From ab23e6146dd08515b4d3ad4d33cbce376e8d68d6 Mon Sep 17 00:00:00 2001 From: tsv2013 Date: Wed, 25 Sep 2019 11:18:11 +0300 Subject: [PATCH] Delete survey.analytics.js --- 1.1.7/survey.analytics.js | 203998 ----------------------------------- 1 file changed, 203998 deletions(-) delete mode 100644 1.1.7/survey.analytics.js diff --git a/1.1.7/survey.analytics.js b/1.1.7/survey.analytics.js deleted file mode 100644 index 4025b7c7..00000000 --- a/1.1.7/survey.analytics.js +++ /dev/null @@ -1,203998 +0,0 @@ -/*! - * surveyjs - SurveyJS Analytics library v1.1.7 - * Copyright (c) 2015-2019 Devsoft Baltic OÜ - http://surveyjs.io/ - * License: MIT (http://www.opensource.org/licenses/mit-license.php) - */ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require("survey-core"), require("c3"), require("chart.js"), require("wordcloud"), require("jquery")); - else if(typeof define === 'function' && define.amd) - define("SurveyAnalytics", ["survey-core", "c3", "chart.js", "wordcloud", "jquery"], factory); - else if(typeof exports === 'object') - exports["SurveyAnalytics"] = factory(require("survey-core"), require("c3"), require("chart.js"), require("wordcloud"), require("jquery")); - else - root["SurveyAnalytics"] = factory(root["Survey"], root["c3"], root["Chart"], root["WordCloud"], root["jQuery"]); -})(this, function(__WEBPACK_EXTERNAL_MODULE_4__, __WEBPACK_EXTERNAL_MODULE_14__, __WEBPACK_EXTERNAL_MODULE_36__, __WEBPACK_EXTERNAL_MODULE_37__, __WEBPACK_EXTERNAL_MODULE_38__) { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; -/******/ -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // identity function for calling harmony imports with the correct context -/******/ __webpack_require__.i = function(value) { return value; }; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 39); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* unused harmony export __assign */ -/* harmony export (immutable) */ __webpack_exports__["a"] = __extends; -/* unused harmony export __rest */ -/* unused harmony export __decorate */ -var __assign = Object["assign"] || - function (target) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) - if (Object.prototype.hasOwnProperty.call(s, p)) - target[p] = s[p]; - } - return target; - }; -function __extends(thisClass, baseClass) { - for (var p in baseClass) - if (baseClass.hasOwnProperty(p)) - thisClass[p] = baseClass[p]; - function __() { - this.constructor = thisClass; - } - thisClass.prototype = - baseClass === null - ? Object.create(baseClass) - : ((__.prototype = baseClass.prototype), new __()); -} -var __rest = function (source, e) { - var result = {}; - for (var propertyName in source) - if (Object.prototype.hasOwnProperty.call(source, propertyName) && - e.indexOf(propertyName) < 0) - result[propertyName] = source[propertyName]; - if (source != null && - typeof Object["getOwnPropertySymbols"] === "function") - for (var i = 0, propertySymbols = Object["getOwnPropertySymbols"](source); i < propertySymbols.length; i++) - if (e.indexOf(propertySymbols[i]) < 0) - result[propertySymbols[i]] = source[propertySymbols[i]]; - return result; -}; -var __decorate = function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 - ? target - : desc === null - ? (desc = Object.getOwnPropertyDescriptor(target, key)) - : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") - r = Reflect.decorate(decorators, target, key, desc); - else - for (var i = decorators.length - 1; i >= 0; i--) - if ((d = decorators[i])) - r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -}; - - -/***/ }), -/* 1 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__visualizerBase__ = __webpack_require__(2); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return VisualizationManager; }); - -var VisualizationManager = /** @class */ (function () { - function VisualizationManager() { - } - VisualizationManager.registerVisualizer = function (typeName, constructor) { - var vizualizers = VisualizationManager.vizualizers[typeName]; - if (!vizualizers) { - vizualizers = []; - VisualizationManager.vizualizers[typeName] = vizualizers; - } - vizualizers.push(constructor); - }; - VisualizationManager.getVisualizers = function (typeName) { - var vizualizers = VisualizationManager.vizualizers[typeName]; - if (!vizualizers) { - return [__WEBPACK_IMPORTED_MODULE_0__visualizerBase__["a" /* VisualizerBase */]]; - } - return vizualizers; - }; - VisualizationManager.vizualizers = {}; - return VisualizationManager; -}()); - - - -/***/ }), -/* 2 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return VisualizerBase; }); -var VisualizerBase = /** @class */ (function () { - function VisualizerBase(targetElement, question, data, options) { - this.targetElement = targetElement; - this.question = question; - this.data = data; - this.options = options; - this.backgroundColor = "#f7f7f7"; - } - VisualizerBase.prototype.update = function (data) { - this.data = data; - }; - VisualizerBase.prototype.destroy = function () { - this.targetElement.innerHTML = ""; - }; - VisualizerBase.prototype.render = function () { - this.targetElement.innerHTML = "This question type is not visualized yet"; - }; - VisualizerBase.prototype.invokeOnUpdate = function () { - this.onUpdate && this.onUpdate(); - }; - VisualizerBase.prototype.getRandomColor = function () { - var colors = this.getColors(); - return "#" + colors[Math.floor(Math.random() * colors.length)]; - }; - VisualizerBase.prototype.getColors = function (count) { - if (count === void 0) { count = 10; } - var colors = Array.isArray(VisualizerBase.customColors) && - VisualizerBase.customColors.length > 0 - ? VisualizerBase.customColors - : VisualizerBase.colors; - var manyColors = []; - for (var index = 0; index < count; index++) { - manyColors = manyColors.concat(colors); - } - return manyColors; - }; - VisualizerBase.customColors = []; - VisualizerBase.colors = [ - "86e1fb", - "3999fb", - "ff6771", - "1eb496", - "ffc152", - "aba1ff", - "7d8da5", - "4ec46c", - "cf37a6", - "4e6198" - ]; - return VisualizerBase; -}()); - - - -/***/ }), -/* 3 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_survey_core__ = __webpack_require__(4); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_survey_core___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_survey_core__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__visualizerBase__ = __webpack_require__(2); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SelectBase; }); - - - -var SelectBase = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](SelectBase, _super); - function SelectBase(targetElement, question, data, options) { - var _this = _super.call(this, targetElement, question, data, options) || this; - _this.targetElement = targetElement; - _this.chartNode = document.createElement("div"); - return _this; - } - SelectBase.prototype.setChartType = function (chartType) { - if (this.chartTypes.indexOf(chartType) !== -1 && - this.chartType !== chartType) { - this.chartType = chartType; - this.createChart(); - this.invokeOnUpdate(); - } - }; - SelectBase.prototype.createChart = function () { }; - SelectBase.prototype.render = function () { - var chartNodeContainer = document.createElement("div"); - var toolbarNodeContainer = document.createElement("div"); - chartNodeContainer.appendChild(toolbarNodeContainer); - chartNodeContainer.appendChild(this.chartNode); - this.targetElement.appendChild(chartNodeContainer); - this.createToolbar(toolbarNodeContainer); - this.createChart(); - }; - SelectBase.prototype.createToolbarItems = function (toolbar) { - var _this = this; - if (this.chartTypes.length > 0) { - var selectWrapper = document.createElement("div"); - selectWrapper.className = "sva-question__select-wrapper"; - var select_1 = document.createElement("select"); - select_1.className = "sva-question__select"; - this.chartTypes.forEach(function (chartType) { - var option = document.createElement("option"); - option.value = chartType; - option.text = chartType; - option.selected = _this.chartType === chartType; - select_1.appendChild(option); - }); - select_1.onchange = function (e) { - _this.setChartType(e.target.value); - }; - selectWrapper.appendChild(select_1); - toolbar.appendChild(selectWrapper); - } - }; - SelectBase.prototype.createToolbar = function (container) { - var toolbar = document.createElement("div"); - toolbar.className = "sva-question__toolbar"; - this.createToolbarItems(toolbar); - container.appendChild(toolbar); - }; - SelectBase.prototype.valuesSource = function () { - var question = this.question; - return question["activeChoices"]; - }; - SelectBase.prototype.getValues = function () { - var values = this.valuesSource().map(function (choice) { return choice.value; }); - if (this.question.hasOther) - values.unshift("other"); - return values; - }; - SelectBase.prototype.getLabels = function () { - var _this = this; - var labels = this.valuesSource().map(function (choice) { - return __WEBPACK_IMPORTED_MODULE_1_survey_core__["ItemValue"].getTextOrHtmlByValue(_this.valuesSource(), choice.value); - }); - if (this.question.hasOther) - labels.unshift("Other"); - return labels; - }; - SelectBase.prototype.getData = function () { - var _this = this; - var values = this.getValues(); - var statistics = values.map(function (v) { return 0; }); - this.data.forEach(function (row) { - var rowValue = row[_this.question.name]; - if (!!rowValue) { - if (Array.isArray(rowValue)) { - values.forEach(function (val, index) { - if (rowValue.indexOf(val) !== -1) { - statistics[index]++; - } - }); - } - else { - values.forEach(function (val, index) { - if (rowValue == val) { - statistics[index]++; - } - }); - } - } - }); - return [statistics]; - }; - return SelectBase; -}(__WEBPACK_IMPORTED_MODULE_2__visualizerBase__["a" /* VisualizerBase */])); - - - -/***/ }), -/* 4 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_4__; - -/***/ }), -/* 5 */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! - * getSize v2.0.3 - * measure size of elements - * MIT license - */ - -/* jshint browser: true, strict: true, undef: true, unused: true */ -/* globals console: false */ - -( function( window, factory ) { - /* jshint strict: false */ /* globals define, module */ - if ( true ) { - // AMD - !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : - __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if ( typeof module == 'object' && module.exports ) { - // CommonJS - module.exports = factory(); - } else { - // browser global - window.getSize = factory(); - } - -})( window, function factory() { -'use strict'; - -// -------------------------- helpers -------------------------- // - -// get a number from a string, not a percentage -function getStyleSize( value ) { - var num = parseFloat( value ); - // not a percent like '100%', and a number - var isValid = value.indexOf('%') == -1 && !isNaN( num ); - return isValid && num; -} - -function noop() {} - -var logError = typeof console == 'undefined' ? noop : - function( message ) { - console.error( message ); - }; - -// -------------------------- measurements -------------------------- // - -var measurements = [ - 'paddingLeft', - 'paddingRight', - 'paddingTop', - 'paddingBottom', - 'marginLeft', - 'marginRight', - 'marginTop', - 'marginBottom', - 'borderLeftWidth', - 'borderRightWidth', - 'borderTopWidth', - 'borderBottomWidth' -]; - -var measurementsLength = measurements.length; - -function getZeroSize() { - var size = { - width: 0, - height: 0, - innerWidth: 0, - innerHeight: 0, - outerWidth: 0, - outerHeight: 0 - }; - for ( var i=0; i < measurementsLength; i++ ) { - var measurement = measurements[i]; - size[ measurement ] = 0; - } - return size; -} - -// -------------------------- getStyle -------------------------- // - -/** - * getStyle, get style of element, check for Firefox bug - * https://bugzilla.mozilla.org/show_bug.cgi?id=548397 - */ -function getStyle( elem ) { - var style = getComputedStyle( elem ); - if ( !style ) { - logError( 'Style returned ' + style + - '. Are you running this code in a hidden iframe on Firefox? ' + - 'See https://bit.ly/getsizebug1' ); - } - return style; -} - -// -------------------------- setup -------------------------- // - -var isSetup = false; - -var isBoxSizeOuter; - -/** - * setup - * check isBoxSizerOuter - * do on first getSize() rather than on page load for Firefox bug - */ -function setup() { - // setup once - if ( isSetup ) { - return; - } - isSetup = true; - - // -------------------------- box sizing -------------------------- // - - /** - * Chrome & Safari measure the outer-width on style.width on border-box elems - * IE11 & Firefox<29 measures the inner-width - */ - var div = document.createElement('div'); - div.style.width = '200px'; - div.style.padding = '1px 2px 3px 4px'; - div.style.borderStyle = 'solid'; - div.style.borderWidth = '1px 2px 3px 4px'; - div.style.boxSizing = 'border-box'; - - var body = document.body || document.documentElement; - body.appendChild( div ); - var style = getStyle( div ); - // round value for browser zoom. desandro/masonry#928 - isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200; - getSize.isBoxSizeOuter = isBoxSizeOuter; - - body.removeChild( div ); -} - -// -------------------------- getSize -------------------------- // - -function getSize( elem ) { - setup(); - - // use querySeletor if elem is string - if ( typeof elem == 'string' ) { - elem = document.querySelector( elem ); - } - - // do not proceed on non-objects - if ( !elem || typeof elem != 'object' || !elem.nodeType ) { - return; - } - - var style = getStyle( elem ); - - // if hidden, everything is 0 - if ( style.display == 'none' ) { - return getZeroSize(); - } - - var size = {}; - size.width = elem.offsetWidth; - size.height = elem.offsetHeight; - - var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box'; - - // get all measurements - for ( var i=0; i < measurementsLength; i++ ) { - var measurement = measurements[i]; - var value = style[ measurement ]; - var num = parseFloat( value ); - // any 'auto', 'medium' value will be 0 - size[ measurement ] = !isNaN( num ) ? num : 0; - } - - var paddingWidth = size.paddingLeft + size.paddingRight; - var paddingHeight = size.paddingTop + size.paddingBottom; - var marginWidth = size.marginLeft + size.marginRight; - var marginHeight = size.marginTop + size.marginBottom; - var borderWidth = size.borderLeftWidth + size.borderRightWidth; - var borderHeight = size.borderTopWidth + size.borderBottomWidth; - - var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; - - // overwrite width and height if we can get it from style - var styleWidth = getStyleSize( style.width ); - if ( styleWidth !== false ) { - size.width = styleWidth + - // add padding and border unless it's already including it - ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); - } - - var styleHeight = getStyleSize( style.height ); - if ( styleHeight !== false ) { - size.height = styleHeight + - // add padding and border unless it's already including it - ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); - } - - size.innerWidth = size.width - ( paddingWidth + borderWidth ); - size.innerHeight = size.height - ( paddingHeight + borderHeight ); - - size.outerWidth = size.width + marginWidth; - size.outerHeight = size.height + marginHeight; - - return size; -} - -return getSize; - -}); - - -/***/ }), -/* 6 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_chart_js__ = __webpack_require__(36); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_chart_js___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_chart_js__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__selectBase__ = __webpack_require__(3); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SelectBaseChartJS; }); - - - -var SelectBaseChartJS = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](SelectBaseChartJS, _super); - function SelectBaseChartJS(targetElement, question, data, options) { - var _this = _super.call(this, targetElement, question, data, options) || this; - _this.chartTypes = ["bar", "horizontalBar", "line", "pie", "doughnut"]; - _this.chartType = "horizontalBar"; - _this.chartNode = document.createElement("canvas"); - _this.toolbarChangeHandler = function (e) { - if (_this.chartType !== e.target.value) { - _this.chartType = e.target.value; - _this.chart.destroy(); - _this.chart = _this.getChartJs(_this.chartNode, _this.chartType); - } - }; - return _this; - } - SelectBaseChartJS.prototype.destroy = function () { - if (!!this.chart) { - this.chart.destroy(); - this.chart = undefined; - this.targetElement.innerHTML = ""; - } - }; - SelectBaseChartJS.prototype.createChart = function () { - this.chart = this.getChartJs(this.chartNode, this.chartType); - }; - SelectBaseChartJS.prototype.getChartJs = function (chartNode, chartType) { - var ctx = chartNode.getContext("2d"); - return new __WEBPACK_IMPORTED_MODULE_1_chart_js___default.a(ctx, { - type: chartType, - data: { - labels: this.getLabels(), - datasets: this.getDatasets() - }, - options: this.getOptions() - }); - }; - SelectBaseChartJS.prototype.getOptions = function () { - return { - responsive: true, - maintainAspectRatio: false, - scales: ["pie", "doughnut"].indexOf(this.chartType) !== -1 - ? undefined - : { - yAxes: [ - { - ticks: { - beginAtZero: true - } - } - ] - } - }; - }; - SelectBaseChartJS.prototype.getDatasets = function () { - var _this = this; - var question = this.question; - return [ - { - label: question.title, - data: this.getData()[0], - backgroundColor: this.getValues().map(function (_) { return _this.getRandomColor(); }) - } - ]; - }; - return SelectBaseChartJS; -}(__WEBPACK_IMPORTED_MODULE_2__selectBase__["a" /* SelectBase */])); - -// VisualizationManager.registerVisualizer("checkbox", SelectBaseChartJS); -// VisualizationManager.registerVisualizer("radiogroup", SelectBaseChartJS); -// VisualizationManager.registerVisualizer("dropdown", SelectBaseChartJS); -// VisualizationManager.registerVisualizer("imagepicker", SelectBaseChartJS); - - -/***/ }), -/* 7 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__visualizationManager__ = __webpack_require__(1); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_masonry_layout__ = __webpack_require__(25); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_masonry_layout___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_masonry_layout__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__index_scss__ = __webpack_require__(23); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__index_scss___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2__index_scss__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__selectBase__ = __webpack_require__(3); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return VisualizationPanel; }); - - - - -var VisualizationPanel = /** @class */ (function () { - function VisualizationPanel(targetElement, questions, data, options) { - this.targetElement = targetElement; - this.questions = questions; - this.data = data; - this.options = options; - this.visualizers = []; - this.filteredData = data; - } - VisualizationPanel.prototype.render = function () { - var _this = this; - var gridSizerClassName = "sva-grid__grid-sizer"; - var questionElementClassName = "sva-question"; - var msnry = undefined; - var getMasonry = function () { return msnry; }; - var gridSizer = document.createElement("div"); //Masonry gridSizer empty element, only used for element sizing - this.targetElement.className = "sva-grid"; - gridSizer.className = gridSizerClassName; - this.targetElement.appendChild(gridSizer); - this.questions.forEach(function (question) { - var questionElement = document.createElement("div"); - var questionContent = document.createElement("div"); - var titleElement = document.createElement("h3"); - var vizualizerElement = document.createElement("div"); - titleElement.innerText = question["title"]; - questionElement.className = questionElementClassName; - questionContent.className = questionElementClassName + "__content"; - titleElement.className = questionElementClassName + "__title"; - questionContent.appendChild(titleElement); - questionContent.appendChild(vizualizerElement); - questionElement.appendChild(questionContent); - _this.targetElement.appendChild(questionElement); - var visualizer = _this.renderQuestion(vizualizerElement, question, _this.filteredData); - visualizer.onUpdate = function () { - if (getMasonry()) { - getMasonry().layout(); - } - }; - if (visualizer instanceof __WEBPACK_IMPORTED_MODULE_3__selectBase__["a" /* SelectBase */]) { - visualizer.onDataItemSelected = function (selectedValue, clearSelection) { - _this.applyFilter(question.name, selectedValue, clearSelection); - _this.update(); - }; - } - _this.visualizers.push(visualizer); - }); - msnry = new __WEBPACK_IMPORTED_MODULE_1_masonry_layout___default.a(this.targetElement, { - columnWidth: "." + gridSizerClassName, - itemSelector: "." + questionElementClassName - }); - }; - VisualizationPanel.prototype.destroy = function () { - this.targetElement.innerHTML = ""; - this.visualizers.forEach(function (visualizer) { - visualizer.onUpdate = undefined; - if (visualizer instanceof __WEBPACK_IMPORTED_MODULE_3__selectBase__["a" /* SelectBase */]) { - visualizer.onDataItemSelected = undefined; - } - visualizer.destroy(); - }); - this.visualizers = []; - }; - VisualizationPanel.prototype.update = function () { - var _this = this; - this.visualizers.forEach(function (visualizer) { - return setTimeout(function () { return visualizer.update(_this.filteredData); }, 10); - }); - }; - VisualizationPanel.prototype.applyFilter = function (questionName, selectedValue, clearSelection) { - var _this = this; - if (clearSelection === void 0) { clearSelection = true; } - if (clearSelection) { - this.filterValues = {}; - } - if (selectedValue !== undefined) { - this.filterValues[questionName] = selectedValue; - } - else { - delete this.filterValues[questionName]; - } - this.filteredData = this.data.filter(function (item) { - return !Object.keys(_this.filterValues).some(function (key) { return item[key] !== _this.filterValues[key]; }); - }); - }; - VisualizationPanel.prototype.renderQuestion = function (vizualizerElement, question, data) { - var visualizers = __WEBPACK_IMPORTED_MODULE_0__visualizationManager__["a" /* VisualizationManager */].getVisualizers(question.getType()); - var visualizer = new visualizers[0](vizualizerElement, question, data); - visualizer.render(); - return visualizer; - }; - return VisualizationPanel; -}()); - - - -/***/ }), -/* 8 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__visualizerBase__ = __webpack_require__(2); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__visualizationManager__ = __webpack_require__(1); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__visualizationPanel__ = __webpack_require__(7); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return VisualizationPanelDynamic; }); - - - - -var VisualizationPanelDynamic = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](VisualizationPanelDynamic, _super); - function VisualizationPanelDynamic(targetNode, question, data, options) { - var _this = _super.call(this, targetNode, question, data, options) || this; - _this.data = []; - data.forEach(function (dataItem) { - return !!dataItem[question.name] && - (_this.data = _this.data.concat(dataItem[question.name])); - }); - return _this; - } - VisualizationPanelDynamic.prototype.getQuestions = function () { - var paneldynamic = this.question; - return paneldynamic.panels[0].questions; - }; - VisualizationPanelDynamic.prototype.render = function () { - var visPanel = new __WEBPACK_IMPORTED_MODULE_3__visualizationPanel__["a" /* VisualizationPanel */](document.getElementById("summaryContainer"), this.getQuestions(), this.data); - visPanel.render(); - }; - VisualizationPanelDynamic.prototype.destroy = function () { - this.targetElement.innerHTML = ""; - }; - return VisualizationPanelDynamic; -}(__WEBPACK_IMPORTED_MODULE_1__visualizerBase__["a" /* VisualizerBase */])); - -__WEBPACK_IMPORTED_MODULE_2__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("paneldynamic", VisualizationPanelDynamic); - - -/***/ }), -/* 9 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__english__ = __webpack_require__(34); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return textHelper; }); - -var stopWordsDictionary = {}; -stopWordsDictionary["en"] = __WEBPACK_IMPORTED_MODULE_0__english__["a" /* stopWords */]; -var textHelper = { - getStopWords: function (locale) { - if (locale === void 0) { locale = ""; } - return stopWordsDictionary[locale || "en"] || []; - } -}; - - -/***/ }), -/* 10 */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/** - * EvEmitter v1.1.0 - * Lil' event emitter - * MIT License - */ - -/* jshint unused: true, undef: true, strict: true */ - -( function( global, factory ) { - // universal module definition - /* jshint strict: false */ /* globals define, module, window */ - if ( true ) { - // AMD - RequireJS - !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : - __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if ( typeof module == 'object' && module.exports ) { - // CommonJS - Browserify, Webpack - module.exports = factory(); - } else { - // Browser globals - global.EvEmitter = factory(); - } - -}( typeof window != 'undefined' ? window : this, function() { - -"use strict"; - -function EvEmitter() {} - -var proto = EvEmitter.prototype; - -proto.on = function( eventName, listener ) { - if ( !eventName || !listener ) { - return; - } - // set events hash - var events = this._events = this._events || {}; - // set listeners array - var listeners = events[ eventName ] = events[ eventName ] || []; - // only add once - if ( listeners.indexOf( listener ) == -1 ) { - listeners.push( listener ); - } - - return this; -}; - -proto.once = function( eventName, listener ) { - if ( !eventName || !listener ) { - return; - } - // add event - this.on( eventName, listener ); - // set once flag - // set onceEvents hash - var onceEvents = this._onceEvents = this._onceEvents || {}; - // set onceListeners object - var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; - // set flag - onceListeners[ listener ] = true; - - return this; -}; - -proto.off = function( eventName, listener ) { - var listeners = this._events && this._events[ eventName ]; - if ( !listeners || !listeners.length ) { - return; - } - var index = listeners.indexOf( listener ); - if ( index != -1 ) { - listeners.splice( index, 1 ); - } - - return this; -}; - -proto.emitEvent = function( eventName, args ) { - var listeners = this._events && this._events[ eventName ]; - if ( !listeners || !listeners.length ) { - return; - } - // copy over to avoid interference if .off() in listener - listeners = listeners.slice(0); - args = args || []; - // once stuff - var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; - - for ( var i=0; i < listeners.length; i++ ) { - var listener = listeners[i] - var isOnce = onceListeners && onceListeners[ listener ]; - if ( isOnce ) { - // remove listener - // remove before trigger to prevent recursion - this.off( eventName, listener ); - // unset once flag - delete onceListeners[ listener ]; - } - // trigger listener - listener.apply( this, args ); - } - - return this; -}; - -proto.allOff = function() { - delete this._events; - delete this._onceEvents; -}; - -return EvEmitter; - -})); - - -/***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global) {var require;var require;/** -* plotly.js v1.49.1 -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* Licensed under the MIT license -*/ -(function(f){if(true){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Plotly = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return require(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i:not(.watermark)": "opacity:0;-webkit-transition:opacity 0.3s ease 0s;-moz-transition:opacity 0.3s ease 0s;-ms-transition:opacity 0.3s ease 0s;-o-transition:opacity 0.3s ease 0s;transition:opacity 0.3s ease 0s;", - "X:hover .modebar--hover .modebar-group": "opacity:1;", - "X .modebar-group": "float:left;display:inline-block;box-sizing:border-box;padding-left:8px;position:relative;vertical-align:middle;white-space:nowrap;", - "X .modebar-btn": "position:relative;font-size:16px;padding:3px 4px;height:22px;cursor:pointer;line-height:normal;box-sizing:border-box;", - "X .modebar-btn svg": "position:relative;top:2px;", - "X .modebar.vertical": "display:flex;flex-direction:column;flex-wrap:wrap;align-content:flex-end;max-height:100%;", - "X .modebar.vertical svg": "top:-1px;", - "X .modebar.vertical .modebar-group": "display:block;float:none;padding-left:0px;padding-bottom:8px;", - "X .modebar.vertical .modebar-group .modebar-btn": "display:block;text-align:center;", - "X [data-title]:before,X [data-title]:after": "position:absolute;-webkit-transform:translate3d(0, 0, 0);-moz-transform:translate3d(0, 0, 0);-ms-transform:translate3d(0, 0, 0);-o-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);display:none;opacity:0;z-index:1001;pointer-events:none;top:110%;right:50%;", - "X [data-title]:hover:before,X [data-title]:hover:after": "display:block;opacity:1;", - "X [data-title]:before": "content:'';position:absolute;background:transparent;border:6px solid transparent;z-index:1002;margin-top:-12px;border-bottom-color:#69738a;margin-right:-6px;", - "X [data-title]:after": "content:attr(data-title);background:#69738a;color:white;padding:8px 10px;font-size:12px;line-height:12px;white-space:nowrap;margin-right:-18px;border-radius:2px;", - "X .vertical [data-title]:before,X .vertical [data-title]:after": "top:0%;right:200%;", - "X .vertical [data-title]:before": "border:6px solid transparent;border-left-color:#69738a;margin-top:8px;margin-right:-30px;", - "X .select-outline": "fill:none;stroke-width:1;shape-rendering:crispEdges;", - "X .select-outline-1": "stroke:white;", - "X .select-outline-2": "stroke:black;stroke-dasharray:2px 2px;", - Y: "font-family:'Open Sans';position:fixed;top:50px;right:20px;z-index:10000;font-size:10pt;max-width:180px;", - "Y p": "margin:0;", - "Y .notifier-note": "min-width:180px;max-width:250px;border:1px solid #fff;z-index:3000;margin:0;background-color:#8c97af;background-color:rgba(140,151,175,0.9);color:#fff;padding:10px;overflow-wrap:break-word;word-wrap:break-word;-ms-hyphens:auto;-webkit-hyphens:auto;hyphens:auto;", - "Y .notifier-close": "color:#fff;opacity:0.8;float:right;padding:0 5px;background:none;border:none;font-size:20px;font-weight:bold;line-height:20px;", - "Y .notifier-close:hover": "color:#444;text-decoration:none;cursor:pointer;" -}; - -for(var selector in rules) { - var fullSelector = selector.replace(/^,/,' ,') - .replace(/X/g, '.js-plotly-plot .plotly') - .replace(/Y/g, '.plotly-notifier'); - Lib.addStyleRule(fullSelector, rules[selector]); -} - -},{"../src/lib":719}],2:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/transforms/aggregate'); - -},{"../src/transforms/aggregate":1265}],3:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/bar'); - -},{"../src/traces/bar":864}],4:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/barpolar'); - -},{"../src/traces/barpolar":876}],5:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/box'); - -},{"../src/traces/box":886}],6:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/components/calendars'); - -},{"../src/components/calendars":591}],7:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/candlestick'); - -},{"../src/traces/candlestick":895}],8:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/carpet'); - -},{"../src/traces/carpet":914}],9:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/choropleth'); - -},{"../src/traces/choropleth":928}],10:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/choroplethmapbox'); - -},{"../src/traces/choroplethmapbox":935}],11:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/cone'); - -},{"../src/traces/cone":941}],12:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/contour'); - -},{"../src/traces/contour":956}],13:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/contourcarpet'); - -},{"../src/traces/contourcarpet":967}],14:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/core'); - -},{"../src/core":697}],15:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/densitymapbox'); - -},{"../src/traces/densitymapbox":977}],16:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/transforms/filter'); - -},{"../src/transforms/filter":1266}],17:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/funnel'); - -},{"../src/traces/funnel":987}],18:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/funnelarea'); - -},{"../src/traces/funnelarea":996}],19:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/transforms/groupby'); - -},{"../src/transforms/groupby":1267}],20:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/heatmap'); - -},{"../src/traces/heatmap":1009}],21:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/heatmapgl'); - -},{"../src/traces/heatmapgl":1018}],22:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/histogram'); - -},{"../src/traces/histogram":1030}],23:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/histogram2d'); - -},{"../src/traces/histogram2d":1036}],24:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/histogram2dcontour'); - -},{"../src/traces/histogram2dcontour":1040}],25:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Plotly = _dereq_('./core'); - -// traces -Plotly.register([ - _dereq_('./bar'), - _dereq_('./box'), - _dereq_('./heatmap'), - _dereq_('./histogram'), - _dereq_('./histogram2d'), - _dereq_('./histogram2dcontour'), - _dereq_('./contour'), - _dereq_('./scatterternary'), - _dereq_('./violin'), - _dereq_('./funnel'), - _dereq_('./waterfall'), - - _dereq_('./pie'), - _dereq_('./sunburst'), - _dereq_('./funnelarea'), - - _dereq_('./scatter3d'), - _dereq_('./surface'), - _dereq_('./isosurface'), - _dereq_('./volume'), - _dereq_('./mesh3d'), - _dereq_('./cone'), - _dereq_('./streamtube'), - - _dereq_('./scattergeo'), - _dereq_('./choropleth'), - - _dereq_('./scattergl'), - _dereq_('./splom'), - - _dereq_('./pointcloud'), - _dereq_('./heatmapgl'), - - _dereq_('./parcoords'), - - _dereq_('./parcats'), - - _dereq_('./scattermapbox'), - _dereq_('./choroplethmapbox'), - _dereq_('./densitymapbox'), - - _dereq_('./sankey'), - _dereq_('./indicator'), - - _dereq_('./table'), - - _dereq_('./carpet'), - _dereq_('./scattercarpet'), - _dereq_('./contourcarpet'), - - _dereq_('./ohlc'), - _dereq_('./candlestick'), - - _dereq_('./scatterpolar'), - _dereq_('./scatterpolargl'), - _dereq_('./barpolar') -]); - -// transforms -// -// Please note that all *transform* methods are executed before -// all *calcTransform* methods - which could possibly lead to -// unexpected results when applying multiple transforms of different types -// to a given trace. -// -// For more info, see: -// https://github.com/plotly/plotly.js/pull/978#pullrequestreview-2403353 -// -Plotly.register([ - _dereq_('./aggregate'), - _dereq_('./filter'), - _dereq_('./groupby'), - _dereq_('./sort') -]); - -// components -Plotly.register([ - _dereq_('./calendars') -]); - -module.exports = Plotly; - -},{"./aggregate":2,"./bar":3,"./barpolar":4,"./box":5,"./calendars":6,"./candlestick":7,"./carpet":8,"./choropleth":9,"./choroplethmapbox":10,"./cone":11,"./contour":12,"./contourcarpet":13,"./core":14,"./densitymapbox":15,"./filter":16,"./funnel":17,"./funnelarea":18,"./groupby":19,"./heatmap":20,"./heatmapgl":21,"./histogram":22,"./histogram2d":23,"./histogram2dcontour":24,"./indicator":26,"./isosurface":27,"./mesh3d":28,"./ohlc":29,"./parcats":30,"./parcoords":31,"./pie":32,"./pointcloud":33,"./sankey":34,"./scatter3d":35,"./scattercarpet":36,"./scattergeo":37,"./scattergl":38,"./scattermapbox":39,"./scatterpolar":40,"./scatterpolargl":41,"./scatterternary":42,"./sort":43,"./splom":44,"./streamtube":45,"./sunburst":46,"./surface":47,"./table":48,"./violin":49,"./volume":50,"./waterfall":51}],26:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/indicator'); - -},{"../src/traces/indicator":1046}],27:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/isosurface'); - -},{"../src/traces/isosurface":1052}],28:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/mesh3d'); - -},{"../src/traces/mesh3d":1057}],29:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/ohlc'); - -},{"../src/traces/ohlc":1062}],30:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/parcats'); - -},{"../src/traces/parcats":1071}],31:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/parcoords'); - -},{"../src/traces/parcoords":1081}],32:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/pie'); - -},{"../src/traces/pie":1092}],33:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/pointcloud'); - -},{"../src/traces/pointcloud":1101}],34:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/sankey'); - -},{"../src/traces/sankey":1107}],35:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/scatter3d'); - -},{"../src/traces/scatter3d":1143}],36:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/scattercarpet'); - -},{"../src/traces/scattercarpet":1149}],37:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/scattergeo'); - -},{"../src/traces/scattergeo":1156}],38:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/scattergl'); - -},{"../src/traces/scattergl":1167}],39:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/scattermapbox'); - -},{"../src/traces/scattermapbox":1176}],40:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/scatterpolar'); - -},{"../src/traces/scatterpolar":1183}],41:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/scatterpolargl'); - -},{"../src/traces/scatterpolargl":1189}],42:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/scatterternary'); - -},{"../src/traces/scatterternary":1196}],43:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/transforms/sort'); - -},{"../src/transforms/sort":1269}],44:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/splom'); - -},{"../src/traces/splom":1205}],45:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/streamtube'); - -},{"../src/traces/streamtube":1213}],46:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/sunburst'); - -},{"../src/traces/sunburst":1219}],47:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/surface'); - -},{"../src/traces/surface":1228}],48:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/table'); - -},{"../src/traces/table":1236}],49:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/violin'); - -},{"../src/traces/violin":1244}],50:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/volume'); - -},{"../src/traces/volume":1252}],51:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = _dereq_('../src/traces/waterfall'); - -},{"../src/traces/waterfall":1260}],52:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createViewController - -var createTurntable = _dereq_('turntable-camera-controller') -var createOrbit = _dereq_('orbit-camera-controller') -var createMatrix = _dereq_('matrix-camera-controller') - -function ViewController(controllers, mode) { - this._controllerNames = Object.keys(controllers) - this._controllerList = this._controllerNames.map(function(n) { - return controllers[n] - }) - this._mode = mode - this._active = controllers[mode] - if(!this._active) { - this._mode = 'turntable' - this._active = controllers.turntable - } - this.modes = this._controllerNames - this.computedMatrix = this._active.computedMatrix - this.computedEye = this._active.computedEye - this.computedUp = this._active.computedUp - this.computedCenter = this._active.computedCenter - this.computedRadius = this._active.computedRadius -} - -var proto = ViewController.prototype - -var COMMON_METHODS = [ - ['flush', 1], - ['idle', 1], - ['lookAt', 4], - ['rotate', 4], - ['pan', 4], - ['translate', 4], - ['setMatrix', 2], - ['setDistanceLimits', 2], - ['setDistance', 2] -] - -COMMON_METHODS.forEach(function(method) { - var name = method[0] - var argNames = [] - for(var i=0; i 0 ? totalTopLinksWidth + verticalMargin + baseRadius : totalTopLinksWidth; - totalBottomLinksWidth = totalBottomLinksWidth > 0 ? totalBottomLinksWidth + verticalMargin + baseRadius : totalBottomLinksWidth; - totalRightLinksWidth = totalRightLinksWidth > 0 ? totalRightLinksWidth + verticalMargin + baseRadius : totalRightLinksWidth; - totalLeftLinksWidth = totalLeftLinksWidth > 0 ? totalLeftLinksWidth + verticalMargin + baseRadius : totalLeftLinksWidth; - - return { "top": totalTopLinksWidth, "bottom": totalBottomLinksWidth, "left": totalLeftLinksWidth, "right": totalRightLinksWidth }; - } - - // Update the x0, y0, x1 and y1 for the sankeyCircular, to allow space for any circular links - function scaleSankeySize(graph, margin) { - - var maxColumn = d3Array.max(graph.nodes, function (node) { - return node.column; - }); - - var currentWidth = x1 - x0; - var currentHeight = y1 - y0; - - var newWidth = currentWidth + margin.right + margin.left; - var newHeight = currentHeight + margin.top + margin.bottom; - - var scaleX = currentWidth / newWidth; - var scaleY = currentHeight / newHeight; - - x0 = x0 * scaleX + margin.left; - x1 = margin.right == 0 ? x1 : x1 * scaleX; - y0 = y0 * scaleY + margin.top; - y1 = y1 * scaleY; - - graph.nodes.forEach(function (node) { - node.x0 = x0 + node.column * ((x1 - x0 - dx) / maxColumn); - node.x1 = node.x0 + dx; - }); - - return scaleY; - } - - // Iteratively assign the depth for each node. - // Nodes are assigned the maximum depth of incoming neighbors plus one; - // nodes with no incoming links are assigned depth zero, while - // nodes with no outgoing links are assigned the maximum depth. - function computeNodeDepths(graph) { - var nodes, next, x; - - for (nodes = graph.nodes, next = [], x = 0; nodes.length; ++x, nodes = next, next = []) { - nodes.forEach(function (node) { - node.depth = x; - node.sourceLinks.forEach(function (link) { - if (next.indexOf(link.target) < 0 && !link.circular) { - next.push(link.target); - } - }); - }); - } - - for (nodes = graph.nodes, next = [], x = 0; nodes.length; ++x, nodes = next, next = []) { - nodes.forEach(function (node) { - node.height = x; - node.targetLinks.forEach(function (link) { - if (next.indexOf(link.source) < 0 && !link.circular) { - next.push(link.source); - } - }); - }); - } - - // assign column numbers, and get max value - graph.nodes.forEach(function (node) { - node.column = Math.floor(align.call(null, node, x)); - }); - } - - // Assign nodes' breadths, and then shift nodes that overlap (resolveCollisions) - function computeNodeBreadths(graph, iterations, id) { - var columns = d3Collection.nest().key(function (d) { - return d.column; - }).sortKeys(d3Array.ascending).entries(graph.nodes).map(function (d) { - return d.values; - }); - - initializeNodeBreadth(id); - resolveCollisions(); - - for (var alpha = 1, n = iterations; n > 0; --n) { - relaxLeftAndRight(alpha *= 0.99, id); - resolveCollisions(); - } - - function initializeNodeBreadth(id) { - - //override py if nodePadding has been set - if (paddingRatio) { - var padding = Infinity; - columns.forEach(function (nodes) { - var thisPadding = y1 * paddingRatio / (nodes.length + 1); - padding = thisPadding < padding ? thisPadding : padding; - }); - py = padding; - } - - var ky = d3Array.min(columns, function (nodes) { - return (y1 - y0 - (nodes.length - 1) * py) / d3Array.sum(nodes, value); - }); - - //calculate the widths of the links - ky = ky * scale; - - graph.links.forEach(function (link) { - link.width = link.value * ky; - }); - - //determine how much to scale down the chart, based on circular links - var margin = getCircleMargins(graph); - var ratio = scaleSankeySize(graph, margin); - - //re-calculate widths - ky = ky * ratio; - - graph.links.forEach(function (link) { - link.width = link.value * ky; - }); - - columns.forEach(function (nodes) { - var nodesLength = nodes.length; - nodes.forEach(function (node, i) { - if (node.depth == columns.length - 1 && nodesLength == 1) { - node.y0 = y1 / 2 - node.value * ky; - node.y1 = node.y0 + node.value * ky; - } else if (node.depth == 0 && nodesLength == 1) { - node.y0 = y1 / 2 - node.value * ky; - node.y1 = node.y0 + node.value * ky; - } else if (node.partOfCycle) { - if (numberOfNonSelfLinkingCycles(node, id) == 0) { - node.y0 = y1 / 2 + i; - node.y1 = node.y0 + node.value * ky; - } else if (node.circularLinkType == 'top') { - node.y0 = y0 + i; - node.y1 = node.y0 + node.value * ky; - } else { - node.y0 = y1 - node.value * ky - i; - node.y1 = node.y0 + node.value * ky; - } - } else { - if (margin.top == 0 || margin.bottom == 0) { - node.y0 = (y1 - y0) / nodesLength * i; - node.y1 = node.y0 + node.value * ky; - } else { - node.y0 = (y1 - y0) / 2 - nodesLength / 2 + i; - node.y1 = node.y0 + node.value * ky; - } - } - }); - }); - } - - // For each node in each column, check the node's vertical position in relation to its targets and sources vertical position - // and shift up/down to be closer to the vertical middle of those targets and sources - function relaxLeftAndRight(alpha, id) { - var columnsLength = columns.length; - - columns.forEach(function (nodes) { - var n = nodes.length; - var depth = nodes[0].depth; - - nodes.forEach(function (node) { - // check the node is not an orphan - var nodeHeight; - if (node.sourceLinks.length || node.targetLinks.length) { - if (node.partOfCycle && numberOfNonSelfLinkingCycles(node, id) > 0) ; else if (depth == 0 && n == 1) { - nodeHeight = node.y1 - node.y0; - - node.y0 = y1 / 2 - nodeHeight / 2; - node.y1 = y1 / 2 + nodeHeight / 2; - } else if (depth == columnsLength - 1 && n == 1) { - nodeHeight = node.y1 - node.y0; - - node.y0 = y1 / 2 - nodeHeight / 2; - node.y1 = y1 / 2 + nodeHeight / 2; - } else { - var avg = 0; - - var avgTargetY = d3Array.mean(node.sourceLinks, linkTargetCenter); - var avgSourceY = d3Array.mean(node.targetLinks, linkSourceCenter); - - if (avgTargetY && avgSourceY) { - avg = (avgTargetY + avgSourceY) / 2; - } else { - avg = avgTargetY || avgSourceY; - } - - var dy = (avg - nodeCenter(node)) * alpha; - // positive if it node needs to move down - node.y0 += dy; - node.y1 += dy; - } - } - }); - }); - } - - // For each column, check if nodes are overlapping, and if so, shift up/down - function resolveCollisions() { - columns.forEach(function (nodes) { - var node, - dy, - y = y0, - n = nodes.length, - i; - - // Push any overlapping nodes down. - nodes.sort(ascendingBreadth); - - for (i = 0; i < n; ++i) { - node = nodes[i]; - dy = y - node.y0; - - if (dy > 0) { - node.y0 += dy; - node.y1 += dy; - } - y = node.y1 + py; - } - - // If the bottommost node goes outside the bounds, push it back up. - dy = y - py - y1; - if (dy > 0) { - y = node.y0 -= dy, node.y1 -= dy; - - // Push any overlapping nodes back up. - for (i = n - 2; i >= 0; --i) { - node = nodes[i]; - dy = node.y1 + py - y; - if (dy > 0) node.y0 -= dy, node.y1 -= dy; - y = node.y0; - } - } - }); - } - } - - // Assign the links y0 and y1 based on source/target nodes position, - // plus the link's relative position to other links to the same node - function computeLinkBreadths(graph) { - graph.nodes.forEach(function (node) { - node.sourceLinks.sort(ascendingTargetBreadth); - node.targetLinks.sort(ascendingSourceBreadth); - }); - graph.nodes.forEach(function (node) { - var y0 = node.y0; - var y1 = y0; - - // start from the bottom of the node for cycle links - var y0cycle = node.y1; - var y1cycle = y0cycle; - - node.sourceLinks.forEach(function (link) { - if (link.circular) { - link.y0 = y0cycle - link.width / 2; - y0cycle = y0cycle - link.width; - } else { - link.y0 = y0 + link.width / 2; - y0 += link.width; - } - }); - node.targetLinks.forEach(function (link) { - if (link.circular) { - link.y1 = y1cycle - link.width / 2; - y1cycle = y1cycle - link.width; - } else { - link.y1 = y1 + link.width / 2; - y1 += link.width; - } - }); - }); - } - - return sankeyCircular; - } - - /// ///////////////////////////////////////////////////////////////////////////////// - // Cycle functions - // portion of code to detect circular links based on Colin Fergus' bl.ock https://gist.github.com/cfergus/3956043 - - // Identify circles in the link objects - function identifyCircles(graph, id, sortNodes) { - var circularLinkID = 0; - if (sortNodes === null) { - - // Building adjacency graph - var adjList = []; - for (var i = 0; i < graph.links.length; i++) { - var link = graph.links[i]; - var source = link.source.index; - var target = link.target.index; - if (!adjList[source]) adjList[source] = []; - if (!adjList[target]) adjList[target] = []; - - // Add links if not already in set - if (adjList[source].indexOf(target) === -1) adjList[source].push(target); - } - - // Find all elementary circuits - var cycles = findCircuits(adjList); - - // Sort by circuits length - cycles.sort(function (a, b) { - return a.length - b.length; - }); - - var circularLinks = {}; - for (i = 0; i < cycles.length; i++) { - var cycle = cycles[i]; - var last = cycle.slice(-2); - if (!circularLinks[last[0]]) circularLinks[last[0]] = {}; - circularLinks[last[0]][last[1]] = true; - } - - graph.links.forEach(function (link) { - var target = link.target.index; - var source = link.source.index; - // If self-linking or a back-edge - if (target === source || circularLinks[source] && circularLinks[source][target]) { - link.circular = true; - link.circularLinkID = circularLinkID; - circularLinkID = circularLinkID + 1; - } else { - link.circular = false; - } - }); - } else { - graph.links.forEach(function (link) { - if (link.source[sortNodes] < link.target[sortNodes]) { - link.circular = false; - } else { - link.circular = true; - link.circularLinkID = circularLinkID; - circularLinkID = circularLinkID + 1; - } - }); - } - } - - // Assign a circular link type (top or bottom), based on: - // - if the source/target node already has circular links, then use the same type - // - if not, choose the type with fewer links - function selectCircularLinkTypes(graph, id) { - var numberOfTops = 0; - var numberOfBottoms = 0; - graph.links.forEach(function (link) { - if (link.circular) { - // if either souce or target has type already use that - if (link.source.circularLinkType || link.target.circularLinkType) { - // default to source type if available - link.circularLinkType = link.source.circularLinkType ? link.source.circularLinkType : link.target.circularLinkType; - } else { - link.circularLinkType = numberOfTops < numberOfBottoms ? 'top' : 'bottom'; - } - - if (link.circularLinkType == 'top') { - numberOfTops = numberOfTops + 1; - } else { - numberOfBottoms = numberOfBottoms + 1; - } - - graph.nodes.forEach(function (node) { - if (getNodeID(node, id) == getNodeID(link.source, id) || getNodeID(node, id) == getNodeID(link.target, id)) { - node.circularLinkType = link.circularLinkType; - } - }); - } - }); - - //correct self-linking links to be same direction as node - graph.links.forEach(function (link) { - if (link.circular) { - //if both source and target node are same type, then link should have same type - if (link.source.circularLinkType == link.target.circularLinkType) { - link.circularLinkType = link.source.circularLinkType; - } - //if link is selflinking, then link should have same type as node - if (selfLinking(link, id)) { - link.circularLinkType = link.source.circularLinkType; - } - } - }); - } - - // Return the angle between a straight line between the source and target of the link, and the vertical plane of the node - function linkAngle(link) { - var adjacent = Math.abs(link.y1 - link.y0); - var opposite = Math.abs(link.target.x0 - link.source.x1); - - return Math.atan(opposite / adjacent); - } - - // Check if two circular links potentially overlap - function circularLinksCross(link1, link2) { - if (link1.source.column < link2.target.column) { - return false; - } else if (link1.target.column > link2.source.column) { - return false; - } else { - return true; - } - } - - // Return the number of circular links for node, not including self linking links - function numberOfNonSelfLinkingCycles(node, id) { - var sourceCount = 0; - node.sourceLinks.forEach(function (l) { - sourceCount = l.circular && !selfLinking(l, id) ? sourceCount + 1 : sourceCount; - }); - - var targetCount = 0; - node.targetLinks.forEach(function (l) { - targetCount = l.circular && !selfLinking(l, id) ? targetCount + 1 : targetCount; - }); - - return sourceCount + targetCount; - } - - // Check if a circular link is the only circular link for both its source and target node - function onlyCircularLink(link) { - var nodeSourceLinks = link.source.sourceLinks; - var sourceCount = 0; - nodeSourceLinks.forEach(function (l) { - sourceCount = l.circular ? sourceCount + 1 : sourceCount; - }); - - var nodeTargetLinks = link.target.targetLinks; - var targetCount = 0; - nodeTargetLinks.forEach(function (l) { - targetCount = l.circular ? targetCount + 1 : targetCount; - }); - - if (sourceCount > 1 || targetCount > 1) { - return false; - } else { - return true; - } - } - - // creates vertical buffer values per set of top/bottom links - function calcVerticalBuffer(links, circularLinkGap, id) { - links.sort(sortLinkColumnAscending); - links.forEach(function (link, i) { - var buffer = 0; - - if (selfLinking(link, id) && onlyCircularLink(link)) { - link.circularPathData.verticalBuffer = buffer + link.width / 2; - } else { - var j = 0; - for (j; j < i; j++) { - if (circularLinksCross(links[i], links[j])) { - var bufferOverThisLink = links[j].circularPathData.verticalBuffer + links[j].width / 2 + circularLinkGap; - buffer = bufferOverThisLink > buffer ? bufferOverThisLink : buffer; - } - } - - link.circularPathData.verticalBuffer = buffer + link.width / 2; - } - }); - - return links; - } - - // calculate the optimum path for a link to reduce overlaps - function addCircularPathData(graph, circularLinkGap, y1, id) { - //var baseRadius = 10 - var buffer = 5; - //var verticalMargin = 25 - - var minY = d3Array.min(graph.links, function (link) { - return link.source.y0; - }); - - // create object for circular Path Data - graph.links.forEach(function (link) { - if (link.circular) { - link.circularPathData = {}; - } - }); - - // calc vertical offsets per top/bottom links - var topLinks = graph.links.filter(function (l) { - return l.circularLinkType == 'top'; - }); - /* topLinks = */calcVerticalBuffer(topLinks, circularLinkGap, id); - - var bottomLinks = graph.links.filter(function (l) { - return l.circularLinkType == 'bottom'; - }); - /* bottomLinks = */calcVerticalBuffer(bottomLinks, circularLinkGap, id); - - // add the base data for each link - graph.links.forEach(function (link) { - if (link.circular) { - link.circularPathData.arcRadius = link.width + baseRadius; - link.circularPathData.leftNodeBuffer = buffer; - link.circularPathData.rightNodeBuffer = buffer; - link.circularPathData.sourceWidth = link.source.x1 - link.source.x0; - link.circularPathData.sourceX = link.source.x0 + link.circularPathData.sourceWidth; - link.circularPathData.targetX = link.target.x0; - link.circularPathData.sourceY = link.y0; - link.circularPathData.targetY = link.y1; - - // for self linking paths, and that the only circular link in/out of that node - if (selfLinking(link, id) && onlyCircularLink(link)) { - link.circularPathData.leftSmallArcRadius = baseRadius + link.width / 2; - link.circularPathData.leftLargeArcRadius = baseRadius + link.width / 2; - link.circularPathData.rightSmallArcRadius = baseRadius + link.width / 2; - link.circularPathData.rightLargeArcRadius = baseRadius + link.width / 2; - - if (link.circularLinkType == 'bottom') { - link.circularPathData.verticalFullExtent = link.source.y1 + verticalMargin + link.circularPathData.verticalBuffer; - link.circularPathData.verticalLeftInnerExtent = link.circularPathData.verticalFullExtent - link.circularPathData.leftLargeArcRadius; - link.circularPathData.verticalRightInnerExtent = link.circularPathData.verticalFullExtent - link.circularPathData.rightLargeArcRadius; - } else { - // top links - link.circularPathData.verticalFullExtent = link.source.y0 - verticalMargin - link.circularPathData.verticalBuffer; - link.circularPathData.verticalLeftInnerExtent = link.circularPathData.verticalFullExtent + link.circularPathData.leftLargeArcRadius; - link.circularPathData.verticalRightInnerExtent = link.circularPathData.verticalFullExtent + link.circularPathData.rightLargeArcRadius; - } - } else { - // else calculate normally - // add left extent coordinates, based on links with same source column and circularLink type - var thisColumn = link.source.column; - var thisCircularLinkType = link.circularLinkType; - var sameColumnLinks = graph.links.filter(function (l) { - return l.source.column == thisColumn && l.circularLinkType == thisCircularLinkType; - }); - - if (link.circularLinkType == 'bottom') { - sameColumnLinks.sort(sortLinkSourceYDescending); - } else { - sameColumnLinks.sort(sortLinkSourceYAscending); - } - - var radiusOffset = 0; - sameColumnLinks.forEach(function (l, i) { - if (l.circularLinkID == link.circularLinkID) { - link.circularPathData.leftSmallArcRadius = baseRadius + link.width / 2 + radiusOffset; - link.circularPathData.leftLargeArcRadius = baseRadius + link.width / 2 + i * circularLinkGap + radiusOffset; - } - radiusOffset = radiusOffset + l.width; - }); - - // add right extent coordinates, based on links with same target column and circularLink type - thisColumn = link.target.column; - sameColumnLinks = graph.links.filter(function (l) { - return l.target.column == thisColumn && l.circularLinkType == thisCircularLinkType; - }); - if (link.circularLinkType == 'bottom') { - sameColumnLinks.sort(sortLinkTargetYDescending); - } else { - sameColumnLinks.sort(sortLinkTargetYAscending); - } - - radiusOffset = 0; - sameColumnLinks.forEach(function (l, i) { - if (l.circularLinkID == link.circularLinkID) { - link.circularPathData.rightSmallArcRadius = baseRadius + link.width / 2 + radiusOffset; - link.circularPathData.rightLargeArcRadius = baseRadius + link.width / 2 + i * circularLinkGap + radiusOffset; - } - radiusOffset = radiusOffset + l.width; - }); - - // bottom links - if (link.circularLinkType == 'bottom') { - link.circularPathData.verticalFullExtent = Math.max(y1, link.source.y1, link.target.y1) + verticalMargin + link.circularPathData.verticalBuffer; - link.circularPathData.verticalLeftInnerExtent = link.circularPathData.verticalFullExtent - link.circularPathData.leftLargeArcRadius; - link.circularPathData.verticalRightInnerExtent = link.circularPathData.verticalFullExtent - link.circularPathData.rightLargeArcRadius; - } else { - // top links - link.circularPathData.verticalFullExtent = minY - verticalMargin - link.circularPathData.verticalBuffer; - link.circularPathData.verticalLeftInnerExtent = link.circularPathData.verticalFullExtent + link.circularPathData.leftLargeArcRadius; - link.circularPathData.verticalRightInnerExtent = link.circularPathData.verticalFullExtent + link.circularPathData.rightLargeArcRadius; - } - } - - // all links - link.circularPathData.leftInnerExtent = link.circularPathData.sourceX + link.circularPathData.leftNodeBuffer; - link.circularPathData.rightInnerExtent = link.circularPathData.targetX - link.circularPathData.rightNodeBuffer; - link.circularPathData.leftFullExtent = link.circularPathData.sourceX + link.circularPathData.leftLargeArcRadius + link.circularPathData.leftNodeBuffer; - link.circularPathData.rightFullExtent = link.circularPathData.targetX - link.circularPathData.rightLargeArcRadius - link.circularPathData.rightNodeBuffer; - } - - if (link.circular) { - link.path = createCircularPathString(link); - } else { - var normalPath = d3Shape.linkHorizontal().source(function (d) { - var x = d.source.x0 + (d.source.x1 - d.source.x0); - var y = d.y0; - return [x, y]; - }).target(function (d) { - var x = d.target.x0; - var y = d.y1; - return [x, y]; - }); - link.path = normalPath(link); - } - }); - } - - // create a d path using the addCircularPathData - function createCircularPathString(link) { - var pathString = ''; - // 'pathData' is assigned a value but never used - // var pathData = {} - - if (link.circularLinkType == 'top') { - pathString = - // start at the right of the source node - 'M' + link.circularPathData.sourceX + ' ' + link.circularPathData.sourceY + ' ' + - // line right to buffer point - 'L' + link.circularPathData.leftInnerExtent + ' ' + link.circularPathData.sourceY + ' ' + - // Arc around: Centre of arc X and //Centre of arc Y - 'A' + link.circularPathData.leftLargeArcRadius + ' ' + link.circularPathData.leftSmallArcRadius + ' 0 0 0 ' + - // End of arc X //End of arc Y - link.circularPathData.leftFullExtent + ' ' + (link.circularPathData.sourceY - link.circularPathData.leftSmallArcRadius) + ' ' + // End of arc X - // line up to buffer point - 'L' + link.circularPathData.leftFullExtent + ' ' + link.circularPathData.verticalLeftInnerExtent + ' ' + - // Arc around: Centre of arc X and //Centre of arc Y - 'A' + link.circularPathData.leftLargeArcRadius + ' ' + link.circularPathData.leftLargeArcRadius + ' 0 0 0 ' + - // End of arc X //End of arc Y - link.circularPathData.leftInnerExtent + ' ' + link.circularPathData.verticalFullExtent + ' ' + // End of arc X - // line left to buffer point - 'L' + link.circularPathData.rightInnerExtent + ' ' + link.circularPathData.verticalFullExtent + ' ' + - // Arc around: Centre of arc X and //Centre of arc Y - 'A' + link.circularPathData.rightLargeArcRadius + ' ' + link.circularPathData.rightLargeArcRadius + ' 0 0 0 ' + - // End of arc X //End of arc Y - link.circularPathData.rightFullExtent + ' ' + link.circularPathData.verticalRightInnerExtent + ' ' + // End of arc X - // line down - 'L' + link.circularPathData.rightFullExtent + ' ' + (link.circularPathData.targetY - link.circularPathData.rightSmallArcRadius) + ' ' + - // Arc around: Centre of arc X and //Centre of arc Y - 'A' + link.circularPathData.rightLargeArcRadius + ' ' + link.circularPathData.rightSmallArcRadius + ' 0 0 0 ' + - // End of arc X //End of arc Y - link.circularPathData.rightInnerExtent + ' ' + link.circularPathData.targetY + ' ' + // End of arc X - // line to end - 'L' + link.circularPathData.targetX + ' ' + link.circularPathData.targetY; - } else { - // bottom path - pathString = - // start at the right of the source node - 'M' + link.circularPathData.sourceX + ' ' + link.circularPathData.sourceY + ' ' + - // line right to buffer point - 'L' + link.circularPathData.leftInnerExtent + ' ' + link.circularPathData.sourceY + ' ' + - // Arc around: Centre of arc X and //Centre of arc Y - 'A' + link.circularPathData.leftLargeArcRadius + ' ' + link.circularPathData.leftSmallArcRadius + ' 0 0 1 ' + - // End of arc X //End of arc Y - link.circularPathData.leftFullExtent + ' ' + (link.circularPathData.sourceY + link.circularPathData.leftSmallArcRadius) + ' ' + // End of arc X - // line down to buffer point - 'L' + link.circularPathData.leftFullExtent + ' ' + link.circularPathData.verticalLeftInnerExtent + ' ' + - // Arc around: Centre of arc X and //Centre of arc Y - 'A' + link.circularPathData.leftLargeArcRadius + ' ' + link.circularPathData.leftLargeArcRadius + ' 0 0 1 ' + - // End of arc X //End of arc Y - link.circularPathData.leftInnerExtent + ' ' + link.circularPathData.verticalFullExtent + ' ' + // End of arc X - // line left to buffer point - 'L' + link.circularPathData.rightInnerExtent + ' ' + link.circularPathData.verticalFullExtent + ' ' + - // Arc around: Centre of arc X and //Centre of arc Y - 'A' + link.circularPathData.rightLargeArcRadius + ' ' + link.circularPathData.rightLargeArcRadius + ' 0 0 1 ' + - // End of arc X //End of arc Y - link.circularPathData.rightFullExtent + ' ' + link.circularPathData.verticalRightInnerExtent + ' ' + // End of arc X - // line up - 'L' + link.circularPathData.rightFullExtent + ' ' + (link.circularPathData.targetY + link.circularPathData.rightSmallArcRadius) + ' ' + - // Arc around: Centre of arc X and //Centre of arc Y - 'A' + link.circularPathData.rightLargeArcRadius + ' ' + link.circularPathData.rightSmallArcRadius + ' 0 0 1 ' + - // End of arc X //End of arc Y - link.circularPathData.rightInnerExtent + ' ' + link.circularPathData.targetY + ' ' + // End of arc X - // line to end - 'L' + link.circularPathData.targetX + ' ' + link.circularPathData.targetY; - } - - return pathString; - } - - // sort links based on the distance between the source and tartget node columns - // if the same, then use Y position of the source node - function sortLinkColumnAscending(link1, link2) { - if (linkColumnDistance(link1) == linkColumnDistance(link2)) { - return link1.circularLinkType == 'bottom' ? sortLinkSourceYDescending(link1, link2) : sortLinkSourceYAscending(link1, link2); - } else { - return linkColumnDistance(link2) - linkColumnDistance(link1); - } - } - - // sort ascending links by their source vertical position, y0 - function sortLinkSourceYAscending(link1, link2) { - return link1.y0 - link2.y0; - } - - // sort descending links by their source vertical position, y0 - function sortLinkSourceYDescending(link1, link2) { - return link2.y0 - link1.y0; - } - - // sort ascending links by their target vertical position, y1 - function sortLinkTargetYAscending(link1, link2) { - return link1.y1 - link2.y1; - } - - // sort descending links by their target vertical position, y1 - function sortLinkTargetYDescending(link1, link2) { - return link2.y1 - link1.y1; - } - - // return the distance between the link's target and source node, in terms of the nodes' column - function linkColumnDistance(link) { - return link.target.column - link.source.column; - } - - // return the distance between the link's target and source node, in terms of the nodes' X coordinate - function linkXLength(link) { - return link.target.x0 - link.source.x1; - } - - // Return the Y coordinate on the longerLink path * which is perpendicular shorterLink's source. - // * approx, based on a straight line from target to source, when in fact the path is a bezier - function linkPerpendicularYToLinkSource(longerLink, shorterLink) { - // get the angle for the longer link - var angle = linkAngle(longerLink); - - // get the adjacent length to the other link's x position - var heightFromY1ToPependicular = linkXLength(shorterLink) / Math.tan(angle); - - // add or subtract from longer link1's original y1, depending on the slope - var yPerpendicular = incline(longerLink) == 'up' ? longerLink.y1 + heightFromY1ToPependicular : longerLink.y1 - heightFromY1ToPependicular; - - return yPerpendicular; - } - - // Return the Y coordinate on the longerLink path * which is perpendicular shorterLink's source. - // * approx, based on a straight line from target to source, when in fact the path is a bezier - function linkPerpendicularYToLinkTarget(longerLink, shorterLink) { - // get the angle for the longer link - var angle = linkAngle(longerLink); - - // get the adjacent length to the other link's x position - var heightFromY1ToPependicular = linkXLength(shorterLink) / Math.tan(angle); - - // add or subtract from longer link's original y1, depending on the slope - var yPerpendicular = incline(longerLink) == 'up' ? longerLink.y1 - heightFromY1ToPependicular : longerLink.y1 + heightFromY1ToPependicular; - - return yPerpendicular; - } - - // Move any nodes that overlap links which span 2+ columns - function resolveNodeLinkOverlaps(graph, y0, y1, id) { - - graph.links.forEach(function (link) { - if (link.circular) { - return; - } - - if (link.target.column - link.source.column > 1) { - var columnToTest = link.source.column + 1; - var maxColumnToTest = link.target.column - 1; - - var i = 1; - var numberOfColumnsToTest = maxColumnToTest - columnToTest + 1; - - for (i = 1; columnToTest <= maxColumnToTest; columnToTest++, i++) { - graph.nodes.forEach(function (node) { - if (node.column == columnToTest) { - var t = i / (numberOfColumnsToTest + 1); - - // Find all the points of a cubic bezier curve in javascript - // https://stackoverflow.com/questions/15397596/find-all-the-points-of-a-cubic-bezier-curve-in-javascript - - var B0_t = Math.pow(1 - t, 3); - var B1_t = 3 * t * Math.pow(1 - t, 2); - var B2_t = 3 * Math.pow(t, 2) * (1 - t); - var B3_t = Math.pow(t, 3); - - var py_t = B0_t * link.y0 + B1_t * link.y0 + B2_t * link.y1 + B3_t * link.y1; - - var linkY0AtColumn = py_t - link.width / 2; - var linkY1AtColumn = py_t + link.width / 2; - var dy; - - // If top of link overlaps node, push node up - if (linkY0AtColumn > node.y0 && linkY0AtColumn < node.y1) { - - dy = node.y1 - linkY0AtColumn + 10; - dy = node.circularLinkType == 'bottom' ? dy : -dy; - - node = adjustNodeHeight(node, dy, y0, y1); - - // check if other nodes need to move up too - graph.nodes.forEach(function (otherNode) { - // don't need to check itself or nodes at different columns - if (getNodeID(otherNode, id) == getNodeID(node, id) || otherNode.column != node.column) { - return; - } - if (nodesOverlap(node, otherNode)) { - adjustNodeHeight(otherNode, dy, y0, y1); - } - }); - } else if (linkY1AtColumn > node.y0 && linkY1AtColumn < node.y1) { - // If bottom of link overlaps node, push node down - dy = linkY1AtColumn - node.y0 + 10; - - node = adjustNodeHeight(node, dy, y0, y1); - - // check if other nodes need to move down too - graph.nodes.forEach(function (otherNode) { - // don't need to check itself or nodes at different columns - if (getNodeID(otherNode, id) == getNodeID(node, id) || otherNode.column != node.column) { - return; - } - if (otherNode.y0 < node.y1 && otherNode.y1 > node.y1) { - adjustNodeHeight(otherNode, dy, y0, y1); - } - }); - } else if (linkY0AtColumn < node.y0 && linkY1AtColumn > node.y1) { - // if link completely overlaps node - dy = linkY1AtColumn - node.y0 + 10; - - node = adjustNodeHeight(node, dy, y0, y1); - - graph.nodes.forEach(function (otherNode) { - // don't need to check itself or nodes at different columns - if (getNodeID(otherNode, id) == getNodeID(node, id) || otherNode.column != node.column) { - return; - } - if (otherNode.y0 < node.y1 && otherNode.y1 > node.y1) { - adjustNodeHeight(otherNode, dy, y0, y1); - } - }); - } - } - }); - } - } - }); - } - - // check if two nodes overlap - function nodesOverlap(nodeA, nodeB) { - // test if nodeA top partially overlaps nodeB - if (nodeA.y0 > nodeB.y0 && nodeA.y0 < nodeB.y1) { - return true; - } else if (nodeA.y1 > nodeB.y0 && nodeA.y1 < nodeB.y1) { - // test if nodeA bottom partially overlaps nodeB - return true; - } else if (nodeA.y0 < nodeB.y0 && nodeA.y1 > nodeB.y1) { - // test if nodeA covers nodeB - return true; - } else { - return false; - } - } - - // update a node, and its associated links, vertical positions (y0, y1) - function adjustNodeHeight(node, dy, sankeyY0, sankeyY1) { - if (node.y0 + dy >= sankeyY0 && node.y1 + dy <= sankeyY1) { - node.y0 = node.y0 + dy; - node.y1 = node.y1 + dy; - - node.targetLinks.forEach(function (l) { - l.y1 = l.y1 + dy; - }); - - node.sourceLinks.forEach(function (l) { - l.y0 = l.y0 + dy; - }); - } - return node; - } - - // sort and set the links' y0 for each node - function sortSourceLinks(graph, y1, id, moveNodes) { - graph.nodes.forEach(function (node) { - // move any nodes up which are off the bottom - if (moveNodes && node.y + (node.y1 - node.y0) > y1) { - node.y = node.y - (node.y + (node.y1 - node.y0) - y1); - } - - var nodesSourceLinks = graph.links.filter(function (l) { - return getNodeID(l.source, id) == getNodeID(node, id); - }); - - var nodeSourceLinksLength = nodesSourceLinks.length; - - // if more than 1 link then sort - if (nodeSourceLinksLength > 1) { - nodesSourceLinks.sort(function (link1, link2) { - // if both are not circular... - if (!link1.circular && !link2.circular) { - // if the target nodes are the same column, then sort by the link's target y - if (link1.target.column == link2.target.column) { - return link1.y1 - link2.y1; - } else if (!sameInclines(link1, link2)) { - // if the links slope in different directions, then sort by the link's target y - return link1.y1 - link2.y1; - - // if the links slope in same directions, then sort by any overlap - } else { - if (link1.target.column > link2.target.column) { - var link2Adj = linkPerpendicularYToLinkTarget(link2, link1); - return link1.y1 - link2Adj; - } - if (link2.target.column > link1.target.column) { - var link1Adj = linkPerpendicularYToLinkTarget(link1, link2); - return link1Adj - link2.y1; - } - } - } - - // if only one is circular, the move top links up, or bottom links down - if (link1.circular && !link2.circular) { - return link1.circularLinkType == 'top' ? -1 : 1; - } else if (link2.circular && !link1.circular) { - return link2.circularLinkType == 'top' ? 1 : -1; - } - - // if both links are circular... - if (link1.circular && link2.circular) { - // ...and they both loop the same way (both top) - if (link1.circularLinkType === link2.circularLinkType && link1.circularLinkType == 'top') { - // ...and they both connect to a target with same column, then sort by the target's y - if (link1.target.column === link2.target.column) { - return link1.target.y1 - link2.target.y1; - } else { - // ...and they connect to different column targets, then sort by how far back they - return link2.target.column - link1.target.column; - } - } else if (link1.circularLinkType === link2.circularLinkType && link1.circularLinkType == 'bottom') { - // ...and they both loop the same way (both bottom) - // ...and they both connect to a target with same column, then sort by the target's y - if (link1.target.column === link2.target.column) { - return link2.target.y1 - link1.target.y1; - } else { - // ...and they connect to different column targets, then sort by how far back they - return link1.target.column - link2.target.column; - } - } else { - // ...and they loop around different ways, the move top up and bottom down - return link1.circularLinkType == 'top' ? -1 : 1; - } - } - }); - } - - // update y0 for links - var ySourceOffset = node.y0; - - nodesSourceLinks.forEach(function (link) { - link.y0 = ySourceOffset + link.width / 2; - ySourceOffset = ySourceOffset + link.width; - }); - - // correct any circular bottom links so they are at the bottom of the node - nodesSourceLinks.forEach(function (link, i) { - if (link.circularLinkType == 'bottom') { - var j = i + 1; - var offsetFromBottom = 0; - // sum the widths of any links that are below this link - for (j; j < nodeSourceLinksLength; j++) { - offsetFromBottom = offsetFromBottom + nodesSourceLinks[j].width; - } - link.y0 = node.y1 - offsetFromBottom - link.width / 2; - } - }); - }); - } - - // sort and set the links' y1 for each node - function sortTargetLinks(graph, y1, id) { - graph.nodes.forEach(function (node) { - var nodesTargetLinks = graph.links.filter(function (l) { - return getNodeID(l.target, id) == getNodeID(node, id); - }); - - var nodesTargetLinksLength = nodesTargetLinks.length; - - if (nodesTargetLinksLength > 1) { - nodesTargetLinks.sort(function (link1, link2) { - // if both are not circular, the base on the source y position - if (!link1.circular && !link2.circular) { - if (link1.source.column == link2.source.column) { - return link1.y0 - link2.y0; - } else if (!sameInclines(link1, link2)) { - return link1.y0 - link2.y0; - } else { - // get the angle of the link to the further source node (ie the smaller column) - if (link2.source.column < link1.source.column) { - var link2Adj = linkPerpendicularYToLinkSource(link2, link1); - - return link1.y0 - link2Adj; - } - if (link1.source.column < link2.source.column) { - var link1Adj = linkPerpendicularYToLinkSource(link1, link2); - - return link1Adj - link2.y0; - } - } - } - - // if only one is circular, the move top links up, or bottom links down - if (link1.circular && !link2.circular) { - return link1.circularLinkType == 'top' ? -1 : 1; - } else if (link2.circular && !link1.circular) { - return link2.circularLinkType == 'top' ? 1 : -1; - } - - // if both links are circular... - if (link1.circular && link2.circular) { - // ...and they both loop the same way (both top) - if (link1.circularLinkType === link2.circularLinkType && link1.circularLinkType == 'top') { - // ...and they both connect to a target with same column, then sort by the target's y - if (link1.source.column === link2.source.column) { - return link1.source.y1 - link2.source.y1; - } else { - // ...and they connect to different column targets, then sort by how far back they - return link1.source.column - link2.source.column; - } - } else if (link1.circularLinkType === link2.circularLinkType && link1.circularLinkType == 'bottom') { - // ...and they both loop the same way (both bottom) - // ...and they both connect to a target with same column, then sort by the target's y - if (link1.source.column === link2.source.column) { - return link1.source.y1 - link2.source.y1; - } else { - // ...and they connect to different column targets, then sort by how far back they - return link2.source.column - link1.source.column; - } - } else { - // ...and they loop around different ways, the move top up and bottom down - return link1.circularLinkType == 'top' ? -1 : 1; - } - } - }); - } - - // update y1 for links - var yTargetOffset = node.y0; - - nodesTargetLinks.forEach(function (link) { - link.y1 = yTargetOffset + link.width / 2; - yTargetOffset = yTargetOffset + link.width; - }); - - // correct any circular bottom links so they are at the bottom of the node - nodesTargetLinks.forEach(function (link, i) { - if (link.circularLinkType == 'bottom') { - var j = i + 1; - var offsetFromBottom = 0; - // sum the widths of any links that are below this link - for (j; j < nodesTargetLinksLength; j++) { - offsetFromBottom = offsetFromBottom + nodesTargetLinks[j].width; - } - link.y1 = node.y1 - offsetFromBottom - link.width / 2; - } - }); - }); - } - - // test if links both slope up, or both slope down - function sameInclines(link1, link2) { - return incline(link1) == incline(link2); - } - - // returns the slope of a link, from source to target - // up => slopes up from source to target - // down => slopes down from source to target - function incline(link) { - return link.y0 - link.y1 > 0 ? 'up' : 'down'; - } - - // check if link is self linking, ie links a node to the same node - function selfLinking(link, id) { - return getNodeID(link.source, id) == getNodeID(link.target, id); - } - - function fillHeight(graph, y0, y1) { - - var nodes = graph.nodes; - var links = graph.links; - - var top = false; - var bottom = false; - - links.forEach(function (link) { - if (link.circularLinkType == "top") { - top = true; - } else if (link.circularLinkType == "bottom") { - bottom = true; - } - }); - - if (top == false || bottom == false) { - var minY0 = d3Array.min(nodes, function (node) { - return node.y0; - }); - var maxY1 = d3Array.max(nodes, function (node) { - return node.y1; - }); - var currentHeight = maxY1 - minY0; - var chartHeight = y1 - y0; - var ratio = chartHeight / currentHeight; - - nodes.forEach(function (node) { - var nodeHeight = (node.y1 - node.y0) * ratio; - node.y0 = (node.y0 - minY0) * ratio; - node.y1 = node.y0 + nodeHeight; - }); - - links.forEach(function (link) { - link.y0 = (link.y0 - minY0) * ratio; - link.y1 = (link.y1 - minY0) * ratio; - link.width = link.width * ratio; - }); - } - } - - exports.sankeyCircular = sankeyCircular; - exports.sankeyCenter = center; - exports.sankeyLeft = left; - exports.sankeyRight = right; - exports.sankeyJustify = justify; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{"d3-array":152,"d3-collection":153,"d3-shape":161,"elementary-circuits-directed-graph":172}],54:[function(_dereq_,module,exports){ -// https://github.com/d3/d3-sankey Version 0.7.2. Copyright 2019 Mike Bostock. -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, _dereq_('d3-array'), _dereq_('d3-collection'), _dereq_('d3-shape')) : - typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'd3-collection', 'd3-shape'], factory) : - (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3)); -}(this, (function (exports,d3Array,d3Collection,d3Shape) { 'use strict'; - -function targetDepth(d) { - return d.target.depth; -} - -function left(node) { - return node.depth; -} - -function right(node, n) { - return n - 1 - node.height; -} - -function justify(node, n) { - return node.sourceLinks.length ? node.depth : n - 1; -} - -function center(node) { - return node.targetLinks.length ? node.depth - : node.sourceLinks.length ? d3Array.min(node.sourceLinks, targetDepth) - 1 - : 0; -} - -function constant(x) { - return function() { - return x; - }; -} - -function ascendingSourceBreadth(a, b) { - return ascendingBreadth(a.source, b.source) || a.index - b.index; -} - -function ascendingTargetBreadth(a, b) { - return ascendingBreadth(a.target, b.target) || a.index - b.index; -} - -function ascendingBreadth(a, b) { - return a.y0 - b.y0; -} - -function value(d) { - return d.value; -} - -function nodeCenter(node) { - return (node.y0 + node.y1) / 2; -} - -function weightedSource(link) { - return nodeCenter(link.source) * link.value; -} - -function weightedTarget(link) { - return nodeCenter(link.target) * link.value; -} - -function defaultId(d) { - return d.index; -} - -function defaultNodes(graph) { - return graph.nodes; -} - -function defaultLinks(graph) { - return graph.links; -} - -function find(nodeById, id) { - var node = nodeById.get(id); - if (!node) throw new Error("missing: " + id); - return node; -} - -var sankey = function() { - var x0 = 0, y0 = 0, x1 = 1, y1 = 1, // extent - dx = 24, // nodeWidth - py = 8, // nodePadding - id = defaultId, - align = justify, - nodes = defaultNodes, - links = defaultLinks, - iterations = 32, - maxPaddedSpace = 2 / 3; // Defined as a fraction of the total available space - - function sankey() { - var graph = {nodes: nodes.apply(null, arguments), links: links.apply(null, arguments)}; - computeNodeLinks(graph); - computeNodeValues(graph); - computeNodeDepths(graph); - computeNodeBreadths(graph, iterations); - computeLinkBreadths(graph); - return graph; - } - - sankey.update = function(graph) { - computeLinkBreadths(graph); - return graph; - }; - - sankey.nodeId = function(_) { - return arguments.length ? (id = typeof _ === "function" ? _ : constant(_), sankey) : id; - }; - - sankey.nodeAlign = function(_) { - return arguments.length ? (align = typeof _ === "function" ? _ : constant(_), sankey) : align; - }; - - sankey.nodeWidth = function(_) { - return arguments.length ? (dx = +_, sankey) : dx; - }; - - sankey.nodePadding = function(_) { - return arguments.length ? (py = +_, sankey) : py; - }; - - sankey.nodes = function(_) { - return arguments.length ? (nodes = typeof _ === "function" ? _ : constant(_), sankey) : nodes; - }; - - sankey.links = function(_) { - return arguments.length ? (links = typeof _ === "function" ? _ : constant(_), sankey) : links; - }; - - sankey.size = function(_) { - return arguments.length ? (x0 = y0 = 0, x1 = +_[0], y1 = +_[1], sankey) : [x1 - x0, y1 - y0]; - }; - - sankey.extent = function(_) { - return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], sankey) : [[x0, y0], [x1, y1]]; - }; - - sankey.iterations = function(_) { - return arguments.length ? (iterations = +_, sankey) : iterations; - }; - - // Populate the sourceLinks and targetLinks for each node. - // Also, if the source and target are not objects, assume they are indices. - function computeNodeLinks(graph) { - graph.nodes.forEach(function(node, i) { - node.index = i; - node.sourceLinks = []; - node.targetLinks = []; - }); - - var nodeById = d3Collection.map(graph.nodes, id); - graph.links.forEach(function(link, i) { - link.index = i; - var source = link.source, target = link.target; - if (typeof source !== "object") source = link.source = find(nodeById, source); - if (typeof target !== "object") target = link.target = find(nodeById, target); - source.sourceLinks.push(link); - target.targetLinks.push(link); - }); - } - - // Compute the value (size) of each node by summing the associated links. - function computeNodeValues(graph) { - graph.nodes.forEach(function(node) { - node.value = Math.max( - d3Array.sum(node.sourceLinks, value), - d3Array.sum(node.targetLinks, value) - ); - }); - } - - // Iteratively assign the depth (x-position) for each node. - // Nodes are assigned the maximum depth of incoming neighbors plus one; - // nodes with no incoming links are assigned depth zero, while - // nodes with no outgoing links are assigned the maximum depth. - function computeNodeDepths(graph) { - var nodes, next, x; - - for (nodes = graph.nodes, next = [], x = 0; nodes.length; ++x, nodes = next, next = []) { - nodes.forEach(function(node) { - node.depth = x; - node.sourceLinks.forEach(function(link) { - if (next.indexOf(link.target) < 0) { - next.push(link.target); - } - }); - }); - } - - for (nodes = graph.nodes, next = [], x = 0; nodes.length; ++x, nodes = next, next = []) { - nodes.forEach(function(node) { - node.height = x; - node.targetLinks.forEach(function(link) { - if (next.indexOf(link.source) < 0) { - next.push(link.source); - } - }); - }); - } - - var kx = (x1 - x0 - dx) / (x - 1); - graph.nodes.forEach(function(node) { - node.x1 = (node.x0 = x0 + Math.max(0, Math.min(x - 1, Math.floor(align.call(null, node, x)))) * kx) + dx; - }); - } - - function computeNodeBreadths(graph) { - var columns = d3Collection.nest() - .key(function(d) { return d.x0; }) - .sortKeys(d3Array.ascending) - .entries(graph.nodes) - .map(function(d) { return d.values; }); - - // - initializeNodeBreadth(); - resolveCollisions(); - for (var alpha = 1, n = iterations; n > 0; --n) { - relaxRightToLeft(alpha *= 0.99); - resolveCollisions(); - relaxLeftToRight(alpha); - resolveCollisions(); - } - - function initializeNodeBreadth() { - var L = d3Array.max(columns, function(nodes) { - return nodes.length; - }); - var maxNodePadding = maxPaddedSpace * (y1 - y0) / (L - 1); - if(py > maxNodePadding) py = maxNodePadding; - var ky = d3Array.min(columns, function(nodes) { - return (y1 - y0 - (nodes.length - 1) * py) / d3Array.sum(nodes, value); - }); - - columns.forEach(function(nodes) { - nodes.forEach(function(node, i) { - node.y1 = (node.y0 = i) + node.value * ky; - }); - }); - - graph.links.forEach(function(link) { - link.width = link.value * ky; - }); - } - - function relaxLeftToRight(alpha) { - columns.forEach(function(nodes) { - nodes.forEach(function(node) { - if (node.targetLinks.length) { - var dy = (d3Array.sum(node.targetLinks, weightedSource) / d3Array.sum(node.targetLinks, value) - nodeCenter(node)) * alpha; - node.y0 += dy, node.y1 += dy; - } - }); - }); - } - - function relaxRightToLeft(alpha) { - columns.slice().reverse().forEach(function(nodes) { - nodes.forEach(function(node) { - if (node.sourceLinks.length) { - var dy = (d3Array.sum(node.sourceLinks, weightedTarget) / d3Array.sum(node.sourceLinks, value) - nodeCenter(node)) * alpha; - node.y0 += dy, node.y1 += dy; - } - }); - }); - } - - function resolveCollisions() { - columns.forEach(function(nodes) { - var node, - dy, - y = y0, - n = nodes.length, - i; - - // Push any overlapping nodes down. - nodes.sort(ascendingBreadth); - for (i = 0; i < n; ++i) { - node = nodes[i]; - dy = y - node.y0; - if (dy > 0) node.y0 += dy, node.y1 += dy; - y = node.y1 + py; - } - - // If the bottommost node goes outside the bounds, push it back up. - dy = y - py - y1; - if (dy > 0) { - y = (node.y0 -= dy), node.y1 -= dy; - - // Push any overlapping nodes back up. - for (i = n - 2; i >= 0; --i) { - node = nodes[i]; - dy = node.y1 + py - y; - if (dy > 0) node.y0 -= dy, node.y1 -= dy; - y = node.y0; - } - } - }); - } - } - - function computeLinkBreadths(graph) { - graph.nodes.forEach(function(node) { - node.sourceLinks.sort(ascendingTargetBreadth); - node.targetLinks.sort(ascendingSourceBreadth); - }); - graph.nodes.forEach(function(node) { - var y0 = node.y0, y1 = y0; - node.sourceLinks.forEach(function(link) { - link.y0 = y0 + link.width / 2, y0 += link.width; - }); - node.targetLinks.forEach(function(link) { - link.y1 = y1 + link.width / 2, y1 += link.width; - }); - }); - } - - return sankey; -}; - -function horizontalSource(d) { - return [d.source.x1, d.y0]; -} - -function horizontalTarget(d) { - return [d.target.x0, d.y1]; -} - -var sankeyLinkHorizontal = function() { - return d3Shape.linkHorizontal() - .source(horizontalSource) - .target(horizontalTarget); -}; - -exports.sankey = sankey; -exports.sankeyCenter = center; -exports.sankeyLeft = left; -exports.sankeyRight = right; -exports.sankeyJustify = justify; -exports.sankeyLinkHorizontal = sankeyLinkHorizontal; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{"d3-array":152,"d3-collection":153,"d3-shape":161}],55:[function(_dereq_,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var meta_1 = _dereq_("@turf/meta"); -// Note: change RADIUS => earthRadius -var RADIUS = 6378137; -/** - * Takes one or more features and returns their area in square meters. - * - * @name area - * @param {GeoJSON} geojson input GeoJSON feature(s) - * @returns {number} area in square meters - * @example - * var polygon = turf.polygon([[[125, -15], [113, -22], [154, -27], [144, -15], [125, -15]]]); - * - * var area = turf.area(polygon); - * - * //addToMap - * var addToMap = [polygon] - * polygon.properties.area = area - */ -function area(geojson) { - return meta_1.geomReduce(geojson, function (value, geom) { - return value + calculateArea(geom); - }, 0); -} -exports.default = area; -/** - * Calculate Area - * - * @private - * @param {Geometry} geom GeoJSON Geometries - * @returns {number} area - */ -function calculateArea(geom) { - var total = 0; - var i; - switch (geom.type) { - case "Polygon": - return polygonArea(geom.coordinates); - case "MultiPolygon": - for (i = 0; i < geom.coordinates.length; i++) { - total += polygonArea(geom.coordinates[i]); - } - return total; - case "Point": - case "MultiPoint": - case "LineString": - case "MultiLineString": - return 0; - } - return 0; -} -function polygonArea(coords) { - var total = 0; - if (coords && coords.length > 0) { - total += Math.abs(ringArea(coords[0])); - for (var i = 1; i < coords.length; i++) { - total -= Math.abs(ringArea(coords[i])); - } - } - return total; -} -/** - * @private - * Calculate the approximate area of the polygon were it projected onto the earth. - * Note that this area will be positive if ring is oriented clockwise, otherwise it will be negative. - * - * Reference: - * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for Polygons on a Sphere", - * JPL Publication 07-03, Jet Propulsion - * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409 - * - * @param {Array>} coords Ring Coordinates - * @returns {number} The approximate signed geodesic area of the polygon in square meters. - */ -function ringArea(coords) { - var p1; - var p2; - var p3; - var lowerIndex; - var middleIndex; - var upperIndex; - var i; - var total = 0; - var coordsLength = coords.length; - if (coordsLength > 2) { - for (i = 0; i < coordsLength; i++) { - if (i === coordsLength - 2) { - lowerIndex = coordsLength - 2; - middleIndex = coordsLength - 1; - upperIndex = 0; - } - else if (i === coordsLength - 1) { - lowerIndex = coordsLength - 1; - middleIndex = 0; - upperIndex = 1; - } - else { - lowerIndex = i; - middleIndex = i + 1; - upperIndex = i + 2; - } - p1 = coords[lowerIndex]; - p2 = coords[middleIndex]; - p3 = coords[upperIndex]; - total += (rad(p3[0]) - rad(p1[0])) * Math.sin(rad(p2[1])); - } - total = total * RADIUS * RADIUS / 2; - } - return total; -} -function rad(num) { - return num * Math.PI / 180; -} - -},{"@turf/meta":58}],56:[function(_dereq_,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var meta_1 = _dereq_("@turf/meta"); -var helpers_1 = _dereq_("@turf/helpers"); -/** - * Takes one or more features and calculates the centroid using the mean of all vertices. - * This lessens the effect of small islands and artifacts when calculating the centroid of a set of polygons. - * - * @name centroid - * @param {GeoJSON} geojson GeoJSON to be centered - * @param {Object} [options={}] Optional Parameters - * @param {Object} [options.properties={}] an Object that is used as the {@link Feature}'s properties - * @returns {Feature} the centroid of the input features - * @example - * var polygon = turf.polygon([[[-81, 41], [-88, 36], [-84, 31], [-80, 33], [-77, 39], [-81, 41]]]); - * - * var centroid = turf.centroid(polygon); - * - * //addToMap - * var addToMap = [polygon, centroid] - */ -function centroid(geojson, options) { - if (options === void 0) { options = {}; } - var xSum = 0; - var ySum = 0; - var len = 0; - meta_1.coordEach(geojson, function (coord) { - xSum += coord[0]; - ySum += coord[1]; - len++; - }); - return helpers_1.point([xSum / len, ySum / len], options.properties); -} -exports.default = centroid; - -},{"@turf/helpers":57,"@turf/meta":58}],57:[function(_dereq_,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * @module helpers - */ -/** - * Earth Radius used with the Harvesine formula and approximates using a spherical (non-ellipsoid) Earth. - * - * @memberof helpers - * @type {number} - */ -exports.earthRadius = 6371008.8; -/** - * Unit of measurement factors using a spherical (non-ellipsoid) earth radius. - * - * @memberof helpers - * @type {Object} - */ -exports.factors = { - centimeters: exports.earthRadius * 100, - centimetres: exports.earthRadius * 100, - degrees: exports.earthRadius / 111325, - feet: exports.earthRadius * 3.28084, - inches: exports.earthRadius * 39.370, - kilometers: exports.earthRadius / 1000, - kilometres: exports.earthRadius / 1000, - meters: exports.earthRadius, - metres: exports.earthRadius, - miles: exports.earthRadius / 1609.344, - millimeters: exports.earthRadius * 1000, - millimetres: exports.earthRadius * 1000, - nauticalmiles: exports.earthRadius / 1852, - radians: 1, - yards: exports.earthRadius / 1.0936, -}; -/** - * Units of measurement factors based on 1 meter. - * - * @memberof helpers - * @type {Object} - */ -exports.unitsFactors = { - centimeters: 100, - centimetres: 100, - degrees: 1 / 111325, - feet: 3.28084, - inches: 39.370, - kilometers: 1 / 1000, - kilometres: 1 / 1000, - meters: 1, - metres: 1, - miles: 1 / 1609.344, - millimeters: 1000, - millimetres: 1000, - nauticalmiles: 1 / 1852, - radians: 1 / exports.earthRadius, - yards: 1 / 1.0936, -}; -/** - * Area of measurement factors based on 1 square meter. - * - * @memberof helpers - * @type {Object} - */ -exports.areaFactors = { - acres: 0.000247105, - centimeters: 10000, - centimetres: 10000, - feet: 10.763910417, - inches: 1550.003100006, - kilometers: 0.000001, - kilometres: 0.000001, - meters: 1, - metres: 1, - miles: 3.86e-7, - millimeters: 1000000, - millimetres: 1000000, - yards: 1.195990046, -}; -/** - * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}. - * - * @name feature - * @param {Geometry} geometry input geometry - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the Feature - * @returns {Feature} a GeoJSON Feature - * @example - * var geometry = { - * "type": "Point", - * "coordinates": [110, 50] - * }; - * - * var feature = turf.feature(geometry); - * - * //=feature - */ -function feature(geom, properties, options) { - if (options === void 0) { options = {}; } - var feat = { type: "Feature" }; - if (options.id === 0 || options.id) { - feat.id = options.id; - } - if (options.bbox) { - feat.bbox = options.bbox; - } - feat.properties = properties || {}; - feat.geometry = geom; - return feat; -} -exports.feature = feature; -/** - * Creates a GeoJSON {@link Geometry} from a Geometry string type & coordinates. - * For GeometryCollection type use `helpers.geometryCollection` - * - * @name geometry - * @param {string} type Geometry Type - * @param {Array} coordinates Coordinates - * @param {Object} [options={}] Optional Parameters - * @returns {Geometry} a GeoJSON Geometry - * @example - * var type = "Point"; - * var coordinates = [110, 50]; - * var geometry = turf.geometry(type, coordinates); - * // => geometry - */ -function geometry(type, coordinates, options) { - if (options === void 0) { options = {}; } - switch (type) { - case "Point": return point(coordinates).geometry; - case "LineString": return lineString(coordinates).geometry; - case "Polygon": return polygon(coordinates).geometry; - case "MultiPoint": return multiPoint(coordinates).geometry; - case "MultiLineString": return multiLineString(coordinates).geometry; - case "MultiPolygon": return multiPolygon(coordinates).geometry; - default: throw new Error(type + " is invalid"); - } -} -exports.geometry = geometry; -/** - * Creates a {@link Point} {@link Feature} from a Position. - * - * @name point - * @param {Array} coordinates longitude, latitude position (each in decimal degrees) - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the Feature - * @returns {Feature} a Point feature - * @example - * var point = turf.point([-75.343, 39.984]); - * - * //=point - */ -function point(coordinates, properties, options) { - if (options === void 0) { options = {}; } - var geom = { - type: "Point", - coordinates: coordinates, - }; - return feature(geom, properties, options); -} -exports.point = point; -/** - * Creates a {@link Point} {@link FeatureCollection} from an Array of Point coordinates. - * - * @name points - * @param {Array>} coordinates an array of Points - * @param {Object} [properties={}] Translate these properties to each Feature - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] - * associated with the FeatureCollection - * @param {string|number} [options.id] Identifier associated with the FeatureCollection - * @returns {FeatureCollection} Point Feature - * @example - * var points = turf.points([ - * [-75, 39], - * [-80, 45], - * [-78, 50] - * ]); - * - * //=points - */ -function points(coordinates, properties, options) { - if (options === void 0) { options = {}; } - return featureCollection(coordinates.map(function (coords) { - return point(coords, properties); - }), options); -} -exports.points = points; -/** - * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings. - * - * @name polygon - * @param {Array>>} coordinates an array of LinearRings - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the Feature - * @returns {Feature} Polygon Feature - * @example - * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' }); - * - * //=polygon - */ -function polygon(coordinates, properties, options) { - if (options === void 0) { options = {}; } - for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) { - var ring = coordinates_1[_i]; - if (ring.length < 4) { - throw new Error("Each LinearRing of a Polygon must have 4 or more Positions."); - } - for (var j = 0; j < ring[ring.length - 1].length; j++) { - // Check if first point of Polygon contains two numbers - if (ring[ring.length - 1][j] !== ring[0][j]) { - throw new Error("First and last Position are not equivalent."); - } - } - } - var geom = { - type: "Polygon", - coordinates: coordinates, - }; - return feature(geom, properties, options); -} -exports.polygon = polygon; -/** - * Creates a {@link Polygon} {@link FeatureCollection} from an Array of Polygon coordinates. - * - * @name polygons - * @param {Array>>>} coordinates an array of Polygon coordinates - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the FeatureCollection - * @returns {FeatureCollection} Polygon FeatureCollection - * @example - * var polygons = turf.polygons([ - * [[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], - * [[[-15, 42], [-14, 46], [-12, 41], [-17, 44], [-15, 42]]], - * ]); - * - * //=polygons - */ -function polygons(coordinates, properties, options) { - if (options === void 0) { options = {}; } - return featureCollection(coordinates.map(function (coords) { - return polygon(coords, properties); - }), options); -} -exports.polygons = polygons; -/** - * Creates a {@link LineString} {@link Feature} from an Array of Positions. - * - * @name lineString - * @param {Array>} coordinates an array of Positions - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the Feature - * @returns {Feature} LineString Feature - * @example - * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'}); - * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'}); - * - * //=linestring1 - * //=linestring2 - */ -function lineString(coordinates, properties, options) { - if (options === void 0) { options = {}; } - if (coordinates.length < 2) { - throw new Error("coordinates must be an array of two or more positions"); - } - var geom = { - type: "LineString", - coordinates: coordinates, - }; - return feature(geom, properties, options); -} -exports.lineString = lineString; -/** - * Creates a {@link LineString} {@link FeatureCollection} from an Array of LineString coordinates. - * - * @name lineStrings - * @param {Array>>} coordinates an array of LinearRings - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] - * associated with the FeatureCollection - * @param {string|number} [options.id] Identifier associated with the FeatureCollection - * @returns {FeatureCollection} LineString FeatureCollection - * @example - * var linestrings = turf.lineStrings([ - * [[-24, 63], [-23, 60], [-25, 65], [-20, 69]], - * [[-14, 43], [-13, 40], [-15, 45], [-10, 49]] - * ]); - * - * //=linestrings - */ -function lineStrings(coordinates, properties, options) { - if (options === void 0) { options = {}; } - return featureCollection(coordinates.map(function (coords) { - return lineString(coords, properties); - }), options); -} -exports.lineStrings = lineStrings; -/** - * Takes one or more {@link Feature|Features} and creates a {@link FeatureCollection}. - * - * @name featureCollection - * @param {Feature[]} features input features - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the Feature - * @returns {FeatureCollection} FeatureCollection of Features - * @example - * var locationA = turf.point([-75.343, 39.984], {name: 'Location A'}); - * var locationB = turf.point([-75.833, 39.284], {name: 'Location B'}); - * var locationC = turf.point([-75.534, 39.123], {name: 'Location C'}); - * - * var collection = turf.featureCollection([ - * locationA, - * locationB, - * locationC - * ]); - * - * //=collection - */ -function featureCollection(features, options) { - if (options === void 0) { options = {}; } - var fc = { type: "FeatureCollection" }; - if (options.id) { - fc.id = options.id; - } - if (options.bbox) { - fc.bbox = options.bbox; - } - fc.features = features; - return fc; -} -exports.featureCollection = featureCollection; -/** - * Creates a {@link Feature} based on a - * coordinate array. Properties can be added optionally. - * - * @name multiLineString - * @param {Array>>} coordinates an array of LineStrings - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the Feature - * @returns {Feature} a MultiLineString feature - * @throws {Error} if no coordinates are passed - * @example - * var multiLine = turf.multiLineString([[[0,0],[10,10]]]); - * - * //=multiLine - */ -function multiLineString(coordinates, properties, options) { - if (options === void 0) { options = {}; } - var geom = { - type: "MultiLineString", - coordinates: coordinates, - }; - return feature(geom, properties, options); -} -exports.multiLineString = multiLineString; -/** - * Creates a {@link Feature} based on a - * coordinate array. Properties can be added optionally. - * - * @name multiPoint - * @param {Array>} coordinates an array of Positions - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the Feature - * @returns {Feature} a MultiPoint feature - * @throws {Error} if no coordinates are passed - * @example - * var multiPt = turf.multiPoint([[0,0],[10,10]]); - * - * //=multiPt - */ -function multiPoint(coordinates, properties, options) { - if (options === void 0) { options = {}; } - var geom = { - type: "MultiPoint", - coordinates: coordinates, - }; - return feature(geom, properties, options); -} -exports.multiPoint = multiPoint; -/** - * Creates a {@link Feature} based on a - * coordinate array. Properties can be added optionally. - * - * @name multiPolygon - * @param {Array>>>} coordinates an array of Polygons - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the Feature - * @returns {Feature} a multipolygon feature - * @throws {Error} if no coordinates are passed - * @example - * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]); - * - * //=multiPoly - * - */ -function multiPolygon(coordinates, properties, options) { - if (options === void 0) { options = {}; } - var geom = { - type: "MultiPolygon", - coordinates: coordinates, - }; - return feature(geom, properties, options); -} -exports.multiPolygon = multiPolygon; -/** - * Creates a {@link Feature} based on a - * coordinate array. Properties can be added optionally. - * - * @name geometryCollection - * @param {Array} geometries an array of GeoJSON Geometries - * @param {Object} [properties={}] an Object of key-value pairs to add as properties - * @param {Object} [options={}] Optional Parameters - * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature - * @param {string|number} [options.id] Identifier associated with the Feature - * @returns {Feature} a GeoJSON GeometryCollection Feature - * @example - * var pt = turf.geometry("Point", [100, 0]); - * var line = turf.geometry("LineString", [[101, 0], [102, 1]]); - * var collection = turf.geometryCollection([pt, line]); - * - * // => collection - */ -function geometryCollection(geometries, properties, options) { - if (options === void 0) { options = {}; } - var geom = { - type: "GeometryCollection", - geometries: geometries, - }; - return feature(geom, properties, options); -} -exports.geometryCollection = geometryCollection; -/** - * Round number to precision - * - * @param {number} num Number - * @param {number} [precision=0] Precision - * @returns {number} rounded number - * @example - * turf.round(120.4321) - * //=120 - * - * turf.round(120.4321, 2) - * //=120.43 - */ -function round(num, precision) { - if (precision === void 0) { precision = 0; } - if (precision && !(precision >= 0)) { - throw new Error("precision must be a positive number"); - } - var multiplier = Math.pow(10, precision || 0); - return Math.round(num * multiplier) / multiplier; -} -exports.round = round; -/** - * Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit. - * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet - * - * @name radiansToLength - * @param {number} radians in radians across the sphere - * @param {string} [units="kilometers"] can be degrees, radians, miles, or kilometers inches, yards, metres, - * meters, kilometres, kilometers. - * @returns {number} distance - */ -function radiansToLength(radians, units) { - if (units === void 0) { units = "kilometers"; } - var factor = exports.factors[units]; - if (!factor) { - throw new Error(units + " units is invalid"); - } - return radians * factor; -} -exports.radiansToLength = radiansToLength; -/** - * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians - * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet - * - * @name lengthToRadians - * @param {number} distance in real units - * @param {string} [units="kilometers"] can be degrees, radians, miles, or kilometers inches, yards, metres, - * meters, kilometres, kilometers. - * @returns {number} radians - */ -function lengthToRadians(distance, units) { - if (units === void 0) { units = "kilometers"; } - var factor = exports.factors[units]; - if (!factor) { - throw new Error(units + " units is invalid"); - } - return distance / factor; -} -exports.lengthToRadians = lengthToRadians; -/** - * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into degrees - * Valid units: miles, nauticalmiles, inches, yards, meters, metres, centimeters, kilometres, feet - * - * @name lengthToDegrees - * @param {number} distance in real units - * @param {string} [units="kilometers"] can be degrees, radians, miles, or kilometers inches, yards, metres, - * meters, kilometres, kilometers. - * @returns {number} degrees - */ -function lengthToDegrees(distance, units) { - return radiansToDegrees(lengthToRadians(distance, units)); -} -exports.lengthToDegrees = lengthToDegrees; -/** - * Converts any bearing angle from the north line direction (positive clockwise) - * and returns an angle between 0-360 degrees (positive clockwise), 0 being the north line - * - * @name bearingToAzimuth - * @param {number} bearing angle, between -180 and +180 degrees - * @returns {number} angle between 0 and 360 degrees - */ -function bearingToAzimuth(bearing) { - var angle = bearing % 360; - if (angle < 0) { - angle += 360; - } - return angle; -} -exports.bearingToAzimuth = bearingToAzimuth; -/** - * Converts an angle in radians to degrees - * - * @name radiansToDegrees - * @param {number} radians angle in radians - * @returns {number} degrees between 0 and 360 degrees - */ -function radiansToDegrees(radians) { - var degrees = radians % (2 * Math.PI); - return degrees * 180 / Math.PI; -} -exports.radiansToDegrees = radiansToDegrees; -/** - * Converts an angle in degrees to radians - * - * @name degreesToRadians - * @param {number} degrees angle between 0 and 360 degrees - * @returns {number} angle in radians - */ -function degreesToRadians(degrees) { - var radians = degrees % 360; - return radians * Math.PI / 180; -} -exports.degreesToRadians = degreesToRadians; -/** - * Converts a length to the requested unit. - * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet - * - * @param {number} length to be converted - * @param {Units} [originalUnit="kilometers"] of the length - * @param {Units} [finalUnit="kilometers"] returned unit - * @returns {number} the converted length - */ -function convertLength(length, originalUnit, finalUnit) { - if (originalUnit === void 0) { originalUnit = "kilometers"; } - if (finalUnit === void 0) { finalUnit = "kilometers"; } - if (!(length >= 0)) { - throw new Error("length must be a positive number"); - } - return radiansToLength(lengthToRadians(length, originalUnit), finalUnit); -} -exports.convertLength = convertLength; -/** - * Converts a area to the requested unit. - * Valid units: kilometers, kilometres, meters, metres, centimetres, millimeters, acres, miles, yards, feet, inches - * @param {number} area to be converted - * @param {Units} [originalUnit="meters"] of the distance - * @param {Units} [finalUnit="kilometers"] returned unit - * @returns {number} the converted distance - */ -function convertArea(area, originalUnit, finalUnit) { - if (originalUnit === void 0) { originalUnit = "meters"; } - if (finalUnit === void 0) { finalUnit = "kilometers"; } - if (!(area >= 0)) { - throw new Error("area must be a positive number"); - } - var startFactor = exports.areaFactors[originalUnit]; - if (!startFactor) { - throw new Error("invalid original units"); - } - var finalFactor = exports.areaFactors[finalUnit]; - if (!finalFactor) { - throw new Error("invalid final units"); - } - return (area / startFactor) * finalFactor; -} -exports.convertArea = convertArea; -/** - * isNumber - * - * @param {*} num Number to validate - * @returns {boolean} true/false - * @example - * turf.isNumber(123) - * //=true - * turf.isNumber('foo') - * //=false - */ -function isNumber(num) { - return !isNaN(num) && num !== null && !Array.isArray(num) && !/^\s*$/.test(num); -} -exports.isNumber = isNumber; -/** - * isObject - * - * @param {*} input variable to validate - * @returns {boolean} true/false - * @example - * turf.isObject({elevation: 10}) - * //=true - * turf.isObject('foo') - * //=false - */ -function isObject(input) { - return (!!input) && (input.constructor === Object); -} -exports.isObject = isObject; -/** - * Validate BBox - * - * @private - * @param {Array} bbox BBox to validate - * @returns {void} - * @throws Error if BBox is not valid - * @example - * validateBBox([-180, -40, 110, 50]) - * //=OK - * validateBBox([-180, -40]) - * //=Error - * validateBBox('Foo') - * //=Error - * validateBBox(5) - * //=Error - * validateBBox(null) - * //=Error - * validateBBox(undefined) - * //=Error - */ -function validateBBox(bbox) { - if (!bbox) { - throw new Error("bbox is required"); - } - if (!Array.isArray(bbox)) { - throw new Error("bbox must be an Array"); - } - if (bbox.length !== 4 && bbox.length !== 6) { - throw new Error("bbox must be an Array of 4 or 6 numbers"); - } - bbox.forEach(function (num) { - if (!isNumber(num)) { - throw new Error("bbox must only contain numbers"); - } - }); -} -exports.validateBBox = validateBBox; -/** - * Validate Id - * - * @private - * @param {string|number} id Id to validate - * @returns {void} - * @throws Error if Id is not valid - * @example - * validateId([-180, -40, 110, 50]) - * //=Error - * validateId([-180, -40]) - * //=Error - * validateId('Foo') - * //=OK - * validateId(5) - * //=OK - * validateId(null) - * //=Error - * validateId(undefined) - * //=Error - */ -function validateId(id) { - if (!id) { - throw new Error("id is required"); - } - if (["string", "number"].indexOf(typeof id) === -1) { - throw new Error("id must be a number or a string"); - } -} -exports.validateId = validateId; -// Deprecated methods -function radians2degrees() { - throw new Error("method has been renamed to `radiansToDegrees`"); -} -exports.radians2degrees = radians2degrees; -function degrees2radians() { - throw new Error("method has been renamed to `degreesToRadians`"); -} -exports.degrees2radians = degrees2radians; -function distanceToDegrees() { - throw new Error("method has been renamed to `lengthToDegrees`"); -} -exports.distanceToDegrees = distanceToDegrees; -function distanceToRadians() { - throw new Error("method has been renamed to `lengthToRadians`"); -} -exports.distanceToRadians = distanceToRadians; -function radiansToDistance() { - throw new Error("method has been renamed to `radiansToLength`"); -} -exports.radiansToDistance = radiansToDistance; -function bearingToAngle() { - throw new Error("method has been renamed to `bearingToAzimuth`"); -} -exports.bearingToAngle = bearingToAngle; -function convertDistance() { - throw new Error("method has been renamed to `convertLength`"); -} -exports.convertDistance = convertDistance; - -},{}],58:[function(_dereq_,module,exports){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { value: true }); - -var helpers = _dereq_('@turf/helpers'); - -/** - * Callback for coordEach - * - * @callback coordEachCallback - * @param {Array} currentCoord The current coordinate being processed. - * @param {number} coordIndex The current index of the coordinate being processed. - * @param {number} featureIndex The current index of the Feature being processed. - * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. - * @param {number} geometryIndex The current index of the Geometry being processed. - */ - -/** - * Iterate over coordinates in any GeoJSON object, similar to Array.forEach() - * - * @name coordEach - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object - * @param {Function} callback a method that takes (currentCoord, coordIndex, featureIndex, multiFeatureIndex) - * @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration. - * @returns {void} - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {"foo": "bar"}), - * turf.point([36, 53], {"hello": "world"}) - * ]); - * - * turf.coordEach(features, function (currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) { - * //=currentCoord - * //=coordIndex - * //=featureIndex - * //=multiFeatureIndex - * //=geometryIndex - * }); - */ -function coordEach(geojson, callback, excludeWrapCoord) { - // Handles null Geometry -- Skips this GeoJSON - if (geojson === null) return; - var j, k, l, geometry, stopG, coords, - geometryMaybeCollection, - wrapShrink = 0, - coordIndex = 0, - isGeometryCollection, - type = geojson.type, - isFeatureCollection = type === 'FeatureCollection', - isFeature = type === 'Feature', - stop = isFeatureCollection ? geojson.features.length : 1; - - // This logic may look a little weird. The reason why it is that way - // is because it's trying to be fast. GeoJSON supports multiple kinds - // of objects at its root: FeatureCollection, Features, Geometries. - // This function has the responsibility of handling all of them, and that - // means that some of the `for` loops you see below actually just don't apply - // to certain inputs. For instance, if you give this just a - // Point geometry, then both loops are short-circuited and all we do - // is gradually rename the input until it's called 'geometry'. - // - // This also aims to allocate as few resources as possible: just a - // few numbers and booleans, rather than any temporary arrays as would - // be required with the normalization approach. - for (var featureIndex = 0; featureIndex < stop; featureIndex++) { - geometryMaybeCollection = (isFeatureCollection ? geojson.features[featureIndex].geometry : - (isFeature ? geojson.geometry : geojson)); - isGeometryCollection = (geometryMaybeCollection) ? geometryMaybeCollection.type === 'GeometryCollection' : false; - stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1; - - for (var geomIndex = 0; geomIndex < stopG; geomIndex++) { - var multiFeatureIndex = 0; - var geometryIndex = 0; - geometry = isGeometryCollection ? - geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection; - - // Handles null Geometry -- Skips this geometry - if (geometry === null) continue; - coords = geometry.coordinates; - var geomType = geometry.type; - - wrapShrink = (excludeWrapCoord && (geomType === 'Polygon' || geomType === 'MultiPolygon')) ? 1 : 0; - - switch (geomType) { - case null: - break; - case 'Point': - if (callback(coords, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) === false) return false; - coordIndex++; - multiFeatureIndex++; - break; - case 'LineString': - case 'MultiPoint': - for (j = 0; j < coords.length; j++) { - if (callback(coords[j], coordIndex, featureIndex, multiFeatureIndex, geometryIndex) === false) return false; - coordIndex++; - if (geomType === 'MultiPoint') multiFeatureIndex++; - } - if (geomType === 'LineString') multiFeatureIndex++; - break; - case 'Polygon': - case 'MultiLineString': - for (j = 0; j < coords.length; j++) { - for (k = 0; k < coords[j].length - wrapShrink; k++) { - if (callback(coords[j][k], coordIndex, featureIndex, multiFeatureIndex, geometryIndex) === false) return false; - coordIndex++; - } - if (geomType === 'MultiLineString') multiFeatureIndex++; - if (geomType === 'Polygon') geometryIndex++; - } - if (geomType === 'Polygon') multiFeatureIndex++; - break; - case 'MultiPolygon': - for (j = 0; j < coords.length; j++) { - geometryIndex = 0; - for (k = 0; k < coords[j].length; k++) { - for (l = 0; l < coords[j][k].length - wrapShrink; l++) { - if (callback(coords[j][k][l], coordIndex, featureIndex, multiFeatureIndex, geometryIndex) === false) return false; - coordIndex++; - } - geometryIndex++; - } - multiFeatureIndex++; - } - break; - case 'GeometryCollection': - for (j = 0; j < geometry.geometries.length; j++) - if (coordEach(geometry.geometries[j], callback, excludeWrapCoord) === false) return false; - break; - default: - throw new Error('Unknown Geometry Type'); - } - } - } -} - -/** - * Callback for coordReduce - * - * The first time the callback function is called, the values provided as arguments depend - * on whether the reduce method has an initialValue argument. - * - * If an initialValue is provided to the reduce method: - * - The previousValue argument is initialValue. - * - The currentValue argument is the value of the first element present in the array. - * - * If an initialValue is not provided: - * - The previousValue argument is the value of the first element present in the array. - * - The currentValue argument is the value of the second element present in the array. - * - * @callback coordReduceCallback - * @param {*} previousValue The accumulated value previously returned in the last invocation - * of the callback, or initialValue, if supplied. - * @param {Array} currentCoord The current coordinate being processed. - * @param {number} coordIndex The current index of the coordinate being processed. - * Starts at index 0, if an initialValue is provided, and at index 1 otherwise. - * @param {number} featureIndex The current index of the Feature being processed. - * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. - * @param {number} geometryIndex The current index of the Geometry being processed. - */ - -/** - * Reduce coordinates in any GeoJSON object, similar to Array.reduce() - * - * @name coordReduce - * @param {FeatureCollection|Geometry|Feature} geojson any GeoJSON object - * @param {Function} callback a method that takes (previousValue, currentCoord, coordIndex) - * @param {*} [initialValue] Value to use as the first argument to the first call of the callback. - * @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration. - * @returns {*} The value that results from the reduction. - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {"foo": "bar"}), - * turf.point([36, 53], {"hello": "world"}) - * ]); - * - * turf.coordReduce(features, function (previousValue, currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) { - * //=previousValue - * //=currentCoord - * //=coordIndex - * //=featureIndex - * //=multiFeatureIndex - * //=geometryIndex - * return currentCoord; - * }); - */ -function coordReduce(geojson, callback, initialValue, excludeWrapCoord) { - var previousValue = initialValue; - coordEach(geojson, function (currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) { - if (coordIndex === 0 && initialValue === undefined) previousValue = currentCoord; - else previousValue = callback(previousValue, currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex); - }, excludeWrapCoord); - return previousValue; -} - -/** - * Callback for propEach - * - * @callback propEachCallback - * @param {Object} currentProperties The current Properties being processed. - * @param {number} featureIndex The current index of the Feature being processed. - */ - -/** - * Iterate over properties in any GeoJSON object, similar to Array.forEach() - * - * @name propEach - * @param {FeatureCollection|Feature} geojson any GeoJSON object - * @param {Function} callback a method that takes (currentProperties, featureIndex) - * @returns {void} - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {foo: 'bar'}), - * turf.point([36, 53], {hello: 'world'}) - * ]); - * - * turf.propEach(features, function (currentProperties, featureIndex) { - * //=currentProperties - * //=featureIndex - * }); - */ -function propEach(geojson, callback) { - var i; - switch (geojson.type) { - case 'FeatureCollection': - for (i = 0; i < geojson.features.length; i++) { - if (callback(geojson.features[i].properties, i) === false) break; - } - break; - case 'Feature': - callback(geojson.properties, 0); - break; - } -} - - -/** - * Callback for propReduce - * - * The first time the callback function is called, the values provided as arguments depend - * on whether the reduce method has an initialValue argument. - * - * If an initialValue is provided to the reduce method: - * - The previousValue argument is initialValue. - * - The currentValue argument is the value of the first element present in the array. - * - * If an initialValue is not provided: - * - The previousValue argument is the value of the first element present in the array. - * - The currentValue argument is the value of the second element present in the array. - * - * @callback propReduceCallback - * @param {*} previousValue The accumulated value previously returned in the last invocation - * of the callback, or initialValue, if supplied. - * @param {*} currentProperties The current Properties being processed. - * @param {number} featureIndex The current index of the Feature being processed. - */ - -/** - * Reduce properties in any GeoJSON object into a single value, - * similar to how Array.reduce works. However, in this case we lazily run - * the reduction, so an array of all properties is unnecessary. - * - * @name propReduce - * @param {FeatureCollection|Feature} geojson any GeoJSON object - * @param {Function} callback a method that takes (previousValue, currentProperties, featureIndex) - * @param {*} [initialValue] Value to use as the first argument to the first call of the callback. - * @returns {*} The value that results from the reduction. - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {foo: 'bar'}), - * turf.point([36, 53], {hello: 'world'}) - * ]); - * - * turf.propReduce(features, function (previousValue, currentProperties, featureIndex) { - * //=previousValue - * //=currentProperties - * //=featureIndex - * return currentProperties - * }); - */ -function propReduce(geojson, callback, initialValue) { - var previousValue = initialValue; - propEach(geojson, function (currentProperties, featureIndex) { - if (featureIndex === 0 && initialValue === undefined) previousValue = currentProperties; - else previousValue = callback(previousValue, currentProperties, featureIndex); - }); - return previousValue; -} - -/** - * Callback for featureEach - * - * @callback featureEachCallback - * @param {Feature} currentFeature The current Feature being processed. - * @param {number} featureIndex The current index of the Feature being processed. - */ - -/** - * Iterate over features in any GeoJSON object, similar to - * Array.forEach. - * - * @name featureEach - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object - * @param {Function} callback a method that takes (currentFeature, featureIndex) - * @returns {void} - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {foo: 'bar'}), - * turf.point([36, 53], {hello: 'world'}) - * ]); - * - * turf.featureEach(features, function (currentFeature, featureIndex) { - * //=currentFeature - * //=featureIndex - * }); - */ -function featureEach(geojson, callback) { - if (geojson.type === 'Feature') { - callback(geojson, 0); - } else if (geojson.type === 'FeatureCollection') { - for (var i = 0; i < geojson.features.length; i++) { - if (callback(geojson.features[i], i) === false) break; - } - } -} - -/** - * Callback for featureReduce - * - * The first time the callback function is called, the values provided as arguments depend - * on whether the reduce method has an initialValue argument. - * - * If an initialValue is provided to the reduce method: - * - The previousValue argument is initialValue. - * - The currentValue argument is the value of the first element present in the array. - * - * If an initialValue is not provided: - * - The previousValue argument is the value of the first element present in the array. - * - The currentValue argument is the value of the second element present in the array. - * - * @callback featureReduceCallback - * @param {*} previousValue The accumulated value previously returned in the last invocation - * of the callback, or initialValue, if supplied. - * @param {Feature} currentFeature The current Feature being processed. - * @param {number} featureIndex The current index of the Feature being processed. - */ - -/** - * Reduce features in any GeoJSON object, similar to Array.reduce(). - * - * @name featureReduce - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object - * @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex) - * @param {*} [initialValue] Value to use as the first argument to the first call of the callback. - * @returns {*} The value that results from the reduction. - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {"foo": "bar"}), - * turf.point([36, 53], {"hello": "world"}) - * ]); - * - * turf.featureReduce(features, function (previousValue, currentFeature, featureIndex) { - * //=previousValue - * //=currentFeature - * //=featureIndex - * return currentFeature - * }); - */ -function featureReduce(geojson, callback, initialValue) { - var previousValue = initialValue; - featureEach(geojson, function (currentFeature, featureIndex) { - if (featureIndex === 0 && initialValue === undefined) previousValue = currentFeature; - else previousValue = callback(previousValue, currentFeature, featureIndex); - }); - return previousValue; -} - -/** - * Get all coordinates from any GeoJSON object. - * - * @name coordAll - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object - * @returns {Array>} coordinate position array - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {foo: 'bar'}), - * turf.point([36, 53], {hello: 'world'}) - * ]); - * - * var coords = turf.coordAll(features); - * //= [[26, 37], [36, 53]] - */ -function coordAll(geojson) { - var coords = []; - coordEach(geojson, function (coord) { - coords.push(coord); - }); - return coords; -} - -/** - * Callback for geomEach - * - * @callback geomEachCallback - * @param {Geometry} currentGeometry The current Geometry being processed. - * @param {number} featureIndex The current index of the Feature being processed. - * @param {Object} featureProperties The current Feature Properties being processed. - * @param {Array} featureBBox The current Feature BBox being processed. - * @param {number|string} featureId The current Feature Id being processed. - */ - -/** - * Iterate over each geometry in any GeoJSON object, similar to Array.forEach() - * - * @name geomEach - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object - * @param {Function} callback a method that takes (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) - * @returns {void} - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {foo: 'bar'}), - * turf.point([36, 53], {hello: 'world'}) - * ]); - * - * turf.geomEach(features, function (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) { - * //=currentGeometry - * //=featureIndex - * //=featureProperties - * //=featureBBox - * //=featureId - * }); - */ -function geomEach(geojson, callback) { - var i, j, g, geometry, stopG, - geometryMaybeCollection, - isGeometryCollection, - featureProperties, - featureBBox, - featureId, - featureIndex = 0, - isFeatureCollection = geojson.type === 'FeatureCollection', - isFeature = geojson.type === 'Feature', - stop = isFeatureCollection ? geojson.features.length : 1; - - // This logic may look a little weird. The reason why it is that way - // is because it's trying to be fast. GeoJSON supports multiple kinds - // of objects at its root: FeatureCollection, Features, Geometries. - // This function has the responsibility of handling all of them, and that - // means that some of the `for` loops you see below actually just don't apply - // to certain inputs. For instance, if you give this just a - // Point geometry, then both loops are short-circuited and all we do - // is gradually rename the input until it's called 'geometry'. - // - // This also aims to allocate as few resources as possible: just a - // few numbers and booleans, rather than any temporary arrays as would - // be required with the normalization approach. - for (i = 0; i < stop; i++) { - - geometryMaybeCollection = (isFeatureCollection ? geojson.features[i].geometry : - (isFeature ? geojson.geometry : geojson)); - featureProperties = (isFeatureCollection ? geojson.features[i].properties : - (isFeature ? geojson.properties : {})); - featureBBox = (isFeatureCollection ? geojson.features[i].bbox : - (isFeature ? geojson.bbox : undefined)); - featureId = (isFeatureCollection ? geojson.features[i].id : - (isFeature ? geojson.id : undefined)); - isGeometryCollection = (geometryMaybeCollection) ? geometryMaybeCollection.type === 'GeometryCollection' : false; - stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1; - - for (g = 0; g < stopG; g++) { - geometry = isGeometryCollection ? - geometryMaybeCollection.geometries[g] : geometryMaybeCollection; - - // Handle null Geometry - if (geometry === null) { - if (callback(null, featureIndex, featureProperties, featureBBox, featureId) === false) return false; - continue; - } - switch (geometry.type) { - case 'Point': - case 'LineString': - case 'MultiPoint': - case 'Polygon': - case 'MultiLineString': - case 'MultiPolygon': { - if (callback(geometry, featureIndex, featureProperties, featureBBox, featureId) === false) return false; - break; - } - case 'GeometryCollection': { - for (j = 0; j < geometry.geometries.length; j++) { - if (callback(geometry.geometries[j], featureIndex, featureProperties, featureBBox, featureId) === false) return false; - } - break; - } - default: - throw new Error('Unknown Geometry Type'); - } - } - // Only increase `featureIndex` per each feature - featureIndex++; - } -} - -/** - * Callback for geomReduce - * - * The first time the callback function is called, the values provided as arguments depend - * on whether the reduce method has an initialValue argument. - * - * If an initialValue is provided to the reduce method: - * - The previousValue argument is initialValue. - * - The currentValue argument is the value of the first element present in the array. - * - * If an initialValue is not provided: - * - The previousValue argument is the value of the first element present in the array. - * - The currentValue argument is the value of the second element present in the array. - * - * @callback geomReduceCallback - * @param {*} previousValue The accumulated value previously returned in the last invocation - * of the callback, or initialValue, if supplied. - * @param {Geometry} currentGeometry The current Geometry being processed. - * @param {number} featureIndex The current index of the Feature being processed. - * @param {Object} featureProperties The current Feature Properties being processed. - * @param {Array} featureBBox The current Feature BBox being processed. - * @param {number|string} featureId The current Feature Id being processed. - */ - -/** - * Reduce geometry in any GeoJSON object, similar to Array.reduce(). - * - * @name geomReduce - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object - * @param {Function} callback a method that takes (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId) - * @param {*} [initialValue] Value to use as the first argument to the first call of the callback. - * @returns {*} The value that results from the reduction. - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {foo: 'bar'}), - * turf.point([36, 53], {hello: 'world'}) - * ]); - * - * turf.geomReduce(features, function (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId) { - * //=previousValue - * //=currentGeometry - * //=featureIndex - * //=featureProperties - * //=featureBBox - * //=featureId - * return currentGeometry - * }); - */ -function geomReduce(geojson, callback, initialValue) { - var previousValue = initialValue; - geomEach(geojson, function (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) { - if (featureIndex === 0 && initialValue === undefined) previousValue = currentGeometry; - else previousValue = callback(previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId); - }); - return previousValue; -} - -/** - * Callback for flattenEach - * - * @callback flattenEachCallback - * @param {Feature} currentFeature The current flattened feature being processed. - * @param {number} featureIndex The current index of the Feature being processed. - * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. - */ - -/** - * Iterate over flattened features in any GeoJSON object, similar to - * Array.forEach. - * - * @name flattenEach - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object - * @param {Function} callback a method that takes (currentFeature, featureIndex, multiFeatureIndex) - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {foo: 'bar'}), - * turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'}) - * ]); - * - * turf.flattenEach(features, function (currentFeature, featureIndex, multiFeatureIndex) { - * //=currentFeature - * //=featureIndex - * //=multiFeatureIndex - * }); - */ -function flattenEach(geojson, callback) { - geomEach(geojson, function (geometry, featureIndex, properties, bbox, id) { - // Callback for single geometry - var type = (geometry === null) ? null : geometry.type; - switch (type) { - case null: - case 'Point': - case 'LineString': - case 'Polygon': - if (callback(helpers.feature(geometry, properties, {bbox: bbox, id: id}), featureIndex, 0) === false) return false; - return; - } - - var geomType; - - // Callback for multi-geometry - switch (type) { - case 'MultiPoint': - geomType = 'Point'; - break; - case 'MultiLineString': - geomType = 'LineString'; - break; - case 'MultiPolygon': - geomType = 'Polygon'; - break; - } - - for (var multiFeatureIndex = 0; multiFeatureIndex < geometry.coordinates.length; multiFeatureIndex++) { - var coordinate = geometry.coordinates[multiFeatureIndex]; - var geom = { - type: geomType, - coordinates: coordinate - }; - if (callback(helpers.feature(geom, properties), featureIndex, multiFeatureIndex) === false) return false; - } - }); -} - -/** - * Callback for flattenReduce - * - * The first time the callback function is called, the values provided as arguments depend - * on whether the reduce method has an initialValue argument. - * - * If an initialValue is provided to the reduce method: - * - The previousValue argument is initialValue. - * - The currentValue argument is the value of the first element present in the array. - * - * If an initialValue is not provided: - * - The previousValue argument is the value of the first element present in the array. - * - The currentValue argument is the value of the second element present in the array. - * - * @callback flattenReduceCallback - * @param {*} previousValue The accumulated value previously returned in the last invocation - * of the callback, or initialValue, if supplied. - * @param {Feature} currentFeature The current Feature being processed. - * @param {number} featureIndex The current index of the Feature being processed. - * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. - */ - -/** - * Reduce flattened features in any GeoJSON object, similar to Array.reduce(). - * - * @name flattenReduce - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object - * @param {Function} callback a method that takes (previousValue, currentFeature, featureIndex, multiFeatureIndex) - * @param {*} [initialValue] Value to use as the first argument to the first call of the callback. - * @returns {*} The value that results from the reduction. - * @example - * var features = turf.featureCollection([ - * turf.point([26, 37], {foo: 'bar'}), - * turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'}) - * ]); - * - * turf.flattenReduce(features, function (previousValue, currentFeature, featureIndex, multiFeatureIndex) { - * //=previousValue - * //=currentFeature - * //=featureIndex - * //=multiFeatureIndex - * return currentFeature - * }); - */ -function flattenReduce(geojson, callback, initialValue) { - var previousValue = initialValue; - flattenEach(geojson, function (currentFeature, featureIndex, multiFeatureIndex) { - if (featureIndex === 0 && multiFeatureIndex === 0 && initialValue === undefined) previousValue = currentFeature; - else previousValue = callback(previousValue, currentFeature, featureIndex, multiFeatureIndex); - }); - return previousValue; -} - -/** - * Callback for segmentEach - * - * @callback segmentEachCallback - * @param {Feature} currentSegment The current Segment being processed. - * @param {number} featureIndex The current index of the Feature being processed. - * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. - * @param {number} geometryIndex The current index of the Geometry being processed. - * @param {number} segmentIndex The current index of the Segment being processed. - * @returns {void} - */ - -/** - * Iterate over 2-vertex line segment in any GeoJSON object, similar to Array.forEach() - * (Multi)Point geometries do not contain segments therefore they are ignored during this operation. - * - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON - * @param {Function} callback a method that takes (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) - * @returns {void} - * @example - * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]); - * - * // Iterate over GeoJSON by 2-vertex segments - * turf.segmentEach(polygon, function (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) { - * //=currentSegment - * //=featureIndex - * //=multiFeatureIndex - * //=geometryIndex - * //=segmentIndex - * }); - * - * // Calculate the total number of segments - * var total = 0; - * turf.segmentEach(polygon, function () { - * total++; - * }); - */ -function segmentEach(geojson, callback) { - flattenEach(geojson, function (feature, featureIndex, multiFeatureIndex) { - var segmentIndex = 0; - - // Exclude null Geometries - if (!feature.geometry) return; - // (Multi)Point geometries do not contain segments therefore they are ignored during this operation. - var type = feature.geometry.type; - if (type === 'Point' || type === 'MultiPoint') return; - - // Generate 2-vertex line segments - var previousCoords; - var previousFeatureIndex = 0; - var previousMultiIndex = 0; - var prevGeomIndex = 0; - if (coordEach(feature, function (currentCoord, coordIndex, featureIndexCoord, multiPartIndexCoord, geometryIndex) { - // Simulating a meta.coordReduce() since `reduce` operations cannot be stopped by returning `false` - if (previousCoords === undefined || featureIndex > previousFeatureIndex || multiPartIndexCoord > previousMultiIndex || geometryIndex > prevGeomIndex) { - previousCoords = currentCoord; - previousFeatureIndex = featureIndex; - previousMultiIndex = multiPartIndexCoord; - prevGeomIndex = geometryIndex; - segmentIndex = 0; - return; - } - var currentSegment = helpers.lineString([previousCoords, currentCoord], feature.properties); - if (callback(currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) === false) return false; - segmentIndex++; - previousCoords = currentCoord; - }) === false) return false; - }); -} - -/** - * Callback for segmentReduce - * - * The first time the callback function is called, the values provided as arguments depend - * on whether the reduce method has an initialValue argument. - * - * If an initialValue is provided to the reduce method: - * - The previousValue argument is initialValue. - * - The currentValue argument is the value of the first element present in the array. - * - * If an initialValue is not provided: - * - The previousValue argument is the value of the first element present in the array. - * - The currentValue argument is the value of the second element present in the array. - * - * @callback segmentReduceCallback - * @param {*} previousValue The accumulated value previously returned in the last invocation - * of the callback, or initialValue, if supplied. - * @param {Feature} currentSegment The current Segment being processed. - * @param {number} featureIndex The current index of the Feature being processed. - * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. - * @param {number} geometryIndex The current index of the Geometry being processed. - * @param {number} segmentIndex The current index of the Segment being processed. - */ - -/** - * Reduce 2-vertex line segment in any GeoJSON object, similar to Array.reduce() - * (Multi)Point geometries do not contain segments therefore they are ignored during this operation. - * - * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON - * @param {Function} callback a method that takes (previousValue, currentSegment, currentIndex) - * @param {*} [initialValue] Value to use as the first argument to the first call of the callback. - * @returns {void} - * @example - * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]); - * - * // Iterate over GeoJSON by 2-vertex segments - * turf.segmentReduce(polygon, function (previousSegment, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) { - * //= previousSegment - * //= currentSegment - * //= featureIndex - * //= multiFeatureIndex - * //= geometryIndex - * //= segmentInex - * return currentSegment - * }); - * - * // Calculate the total number of segments - * var initialValue = 0 - * var total = turf.segmentReduce(polygon, function (previousValue) { - * previousValue++; - * return previousValue; - * }, initialValue); - */ -function segmentReduce(geojson, callback, initialValue) { - var previousValue = initialValue; - var started = false; - segmentEach(geojson, function (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) { - if (started === false && initialValue === undefined) previousValue = currentSegment; - else previousValue = callback(previousValue, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex); - started = true; - }); - return previousValue; -} - -/** - * Callback for lineEach - * - * @callback lineEachCallback - * @param {Feature} currentLine The current LineString|LinearRing being processed - * @param {number} featureIndex The current index of the Feature being processed - * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed - * @param {number} geometryIndex The current index of the Geometry being processed - */ - -/** - * Iterate over line or ring coordinates in LineString, Polygon, MultiLineString, MultiPolygon Features or Geometries, - * similar to Array.forEach. - * - * @name lineEach - * @param {Geometry|Feature} geojson object - * @param {Function} callback a method that takes (currentLine, featureIndex, multiFeatureIndex, geometryIndex) - * @example - * var multiLine = turf.multiLineString([ - * [[26, 37], [35, 45]], - * [[36, 53], [38, 50], [41, 55]] - * ]); - * - * turf.lineEach(multiLine, function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) { - * //=currentLine - * //=featureIndex - * //=multiFeatureIndex - * //=geometryIndex - * }); - */ -function lineEach(geojson, callback) { - // validation - if (!geojson) throw new Error('geojson is required'); - - flattenEach(geojson, function (feature, featureIndex, multiFeatureIndex) { - if (feature.geometry === null) return; - var type = feature.geometry.type; - var coords = feature.geometry.coordinates; - switch (type) { - case 'LineString': - if (callback(feature, featureIndex, multiFeatureIndex, 0, 0) === false) return false; - break; - case 'Polygon': - for (var geometryIndex = 0; geometryIndex < coords.length; geometryIndex++) { - if (callback(helpers.lineString(coords[geometryIndex], feature.properties), featureIndex, multiFeatureIndex, geometryIndex) === false) return false; - } - break; - } - }); -} - -/** - * Callback for lineReduce - * - * The first time the callback function is called, the values provided as arguments depend - * on whether the reduce method has an initialValue argument. - * - * If an initialValue is provided to the reduce method: - * - The previousValue argument is initialValue. - * - The currentValue argument is the value of the first element present in the array. - * - * If an initialValue is not provided: - * - The previousValue argument is the value of the first element present in the array. - * - The currentValue argument is the value of the second element present in the array. - * - * @callback lineReduceCallback - * @param {*} previousValue The accumulated value previously returned in the last invocation - * of the callback, or initialValue, if supplied. - * @param {Feature} currentLine The current LineString|LinearRing being processed. - * @param {number} featureIndex The current index of the Feature being processed - * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed - * @param {number} geometryIndex The current index of the Geometry being processed - */ - -/** - * Reduce features in any GeoJSON object, similar to Array.reduce(). - * - * @name lineReduce - * @param {Geometry|Feature} geojson object - * @param {Function} callback a method that takes (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex) - * @param {*} [initialValue] Value to use as the first argument to the first call of the callback. - * @returns {*} The value that results from the reduction. - * @example - * var multiPoly = turf.multiPolygon([ - * turf.polygon([[[12,48],[2,41],[24,38],[12,48]], [[9,44],[13,41],[13,45],[9,44]]]), - * turf.polygon([[[5, 5], [0, 0], [2, 2], [4, 4], [5, 5]]]) - * ]); - * - * turf.lineReduce(multiPoly, function (previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex) { - * //=previousValue - * //=currentLine - * //=featureIndex - * //=multiFeatureIndex - * //=geometryIndex - * return currentLine - * }); - */ -function lineReduce(geojson, callback, initialValue) { - var previousValue = initialValue; - lineEach(geojson, function (currentLine, featureIndex, multiFeatureIndex, geometryIndex) { - if (featureIndex === 0 && initialValue === undefined) previousValue = currentLine; - else previousValue = callback(previousValue, currentLine, featureIndex, multiFeatureIndex, geometryIndex); - }); - return previousValue; -} - -/** - * Finds a particular 2-vertex LineString Segment from a GeoJSON using `@turf/meta` indexes. - * - * Negative indexes are permitted. - * Point & MultiPoint will always return null. - * - * @param {FeatureCollection|Feature|Geometry} geojson Any GeoJSON Feature or Geometry - * @param {Object} [options={}] Optional parameters - * @param {number} [options.featureIndex=0] Feature Index - * @param {number} [options.multiFeatureIndex=0] Multi-Feature Index - * @param {number} [options.geometryIndex=0] Geometry Index - * @param {number} [options.segmentIndex=0] Segment Index - * @param {Object} [options.properties={}] Translate Properties to output LineString - * @param {BBox} [options.bbox={}] Translate BBox to output LineString - * @param {number|string} [options.id={}] Translate Id to output LineString - * @returns {Feature} 2-vertex GeoJSON Feature LineString - * @example - * var multiLine = turf.multiLineString([ - * [[10, 10], [50, 30], [30, 40]], - * [[-10, -10], [-50, -30], [-30, -40]] - * ]); - * - * // First Segment (defaults are 0) - * turf.findSegment(multiLine); - * // => Feature> - * - * // First Segment of 2nd Multi Feature - * turf.findSegment(multiLine, {multiFeatureIndex: 1}); - * // => Feature> - * - * // Last Segment of Last Multi Feature - * turf.findSegment(multiLine, {multiFeatureIndex: -1, segmentIndex: -1}); - * // => Feature> - */ -function findSegment(geojson, options) { - // Optional Parameters - options = options || {}; - if (!helpers.isObject(options)) throw new Error('options is invalid'); - var featureIndex = options.featureIndex || 0; - var multiFeatureIndex = options.multiFeatureIndex || 0; - var geometryIndex = options.geometryIndex || 0; - var segmentIndex = options.segmentIndex || 0; - - // Find FeatureIndex - var properties = options.properties; - var geometry; - - switch (geojson.type) { - case 'FeatureCollection': - if (featureIndex < 0) featureIndex = geojson.features.length + featureIndex; - properties = properties || geojson.features[featureIndex].properties; - geometry = geojson.features[featureIndex].geometry; - break; - case 'Feature': - properties = properties || geojson.properties; - geometry = geojson.geometry; - break; - case 'Point': - case 'MultiPoint': - return null; - case 'LineString': - case 'Polygon': - case 'MultiLineString': - case 'MultiPolygon': - geometry = geojson; - break; - default: - throw new Error('geojson is invalid'); - } - - // Find SegmentIndex - if (geometry === null) return null; - var coords = geometry.coordinates; - switch (geometry.type) { - case 'Point': - case 'MultiPoint': - return null; - case 'LineString': - if (segmentIndex < 0) segmentIndex = coords.length + segmentIndex - 1; - return helpers.lineString([coords[segmentIndex], coords[segmentIndex + 1]], properties, options); - case 'Polygon': - if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex; - if (segmentIndex < 0) segmentIndex = coords[geometryIndex].length + segmentIndex - 1; - return helpers.lineString([coords[geometryIndex][segmentIndex], coords[geometryIndex][segmentIndex + 1]], properties, options); - case 'MultiLineString': - if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex; - if (segmentIndex < 0) segmentIndex = coords[multiFeatureIndex].length + segmentIndex - 1; - return helpers.lineString([coords[multiFeatureIndex][segmentIndex], coords[multiFeatureIndex][segmentIndex + 1]], properties, options); - case 'MultiPolygon': - if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex; - if (geometryIndex < 0) geometryIndex = coords[multiFeatureIndex].length + geometryIndex; - if (segmentIndex < 0) segmentIndex = coords[multiFeatureIndex][geometryIndex].length - segmentIndex - 1; - return helpers.lineString([coords[multiFeatureIndex][geometryIndex][segmentIndex], coords[multiFeatureIndex][geometryIndex][segmentIndex + 1]], properties, options); - } - throw new Error('geojson is invalid'); -} - -/** - * Finds a particular Point from a GeoJSON using `@turf/meta` indexes. - * - * Negative indexes are permitted. - * - * @param {FeatureCollection|Feature|Geometry} geojson Any GeoJSON Feature or Geometry - * @param {Object} [options={}] Optional parameters - * @param {number} [options.featureIndex=0] Feature Index - * @param {number} [options.multiFeatureIndex=0] Multi-Feature Index - * @param {number} [options.geometryIndex=0] Geometry Index - * @param {number} [options.coordIndex=0] Coord Index - * @param {Object} [options.properties={}] Translate Properties to output Point - * @param {BBox} [options.bbox={}] Translate BBox to output Point - * @param {number|string} [options.id={}] Translate Id to output Point - * @returns {Feature} 2-vertex GeoJSON Feature Point - * @example - * var multiLine = turf.multiLineString([ - * [[10, 10], [50, 30], [30, 40]], - * [[-10, -10], [-50, -30], [-30, -40]] - * ]); - * - * // First Segment (defaults are 0) - * turf.findPoint(multiLine); - * // => Feature> - * - * // First Segment of the 2nd Multi-Feature - * turf.findPoint(multiLine, {multiFeatureIndex: 1}); - * // => Feature> - * - * // Last Segment of last Multi-Feature - * turf.findPoint(multiLine, {multiFeatureIndex: -1, coordIndex: -1}); - * // => Feature> - */ -function findPoint(geojson, options) { - // Optional Parameters - options = options || {}; - if (!helpers.isObject(options)) throw new Error('options is invalid'); - var featureIndex = options.featureIndex || 0; - var multiFeatureIndex = options.multiFeatureIndex || 0; - var geometryIndex = options.geometryIndex || 0; - var coordIndex = options.coordIndex || 0; - - // Find FeatureIndex - var properties = options.properties; - var geometry; - - switch (geojson.type) { - case 'FeatureCollection': - if (featureIndex < 0) featureIndex = geojson.features.length + featureIndex; - properties = properties || geojson.features[featureIndex].properties; - geometry = geojson.features[featureIndex].geometry; - break; - case 'Feature': - properties = properties || geojson.properties; - geometry = geojson.geometry; - break; - case 'Point': - case 'MultiPoint': - return null; - case 'LineString': - case 'Polygon': - case 'MultiLineString': - case 'MultiPolygon': - geometry = geojson; - break; - default: - throw new Error('geojson is invalid'); - } - - // Find Coord Index - if (geometry === null) return null; - var coords = geometry.coordinates; - switch (geometry.type) { - case 'Point': - return helpers.point(coords, properties, options); - case 'MultiPoint': - if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex; - return helpers.point(coords[multiFeatureIndex], properties, options); - case 'LineString': - if (coordIndex < 0) coordIndex = coords.length + coordIndex; - return helpers.point(coords[coordIndex], properties, options); - case 'Polygon': - if (geometryIndex < 0) geometryIndex = coords.length + geometryIndex; - if (coordIndex < 0) coordIndex = coords[geometryIndex].length + coordIndex; - return helpers.point(coords[geometryIndex][coordIndex], properties, options); - case 'MultiLineString': - if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex; - if (coordIndex < 0) coordIndex = coords[multiFeatureIndex].length + coordIndex; - return helpers.point(coords[multiFeatureIndex][coordIndex], properties, options); - case 'MultiPolygon': - if (multiFeatureIndex < 0) multiFeatureIndex = coords.length + multiFeatureIndex; - if (geometryIndex < 0) geometryIndex = coords[multiFeatureIndex].length + geometryIndex; - if (coordIndex < 0) coordIndex = coords[multiFeatureIndex][geometryIndex].length - coordIndex; - return helpers.point(coords[multiFeatureIndex][geometryIndex][coordIndex], properties, options); - } - throw new Error('geojson is invalid'); -} - -exports.coordEach = coordEach; -exports.coordReduce = coordReduce; -exports.propEach = propEach; -exports.propReduce = propReduce; -exports.featureEach = featureEach; -exports.featureReduce = featureReduce; -exports.coordAll = coordAll; -exports.geomEach = geomEach; -exports.geomReduce = geomReduce; -exports.flattenEach = flattenEach; -exports.flattenReduce = flattenReduce; -exports.segmentEach = segmentEach; -exports.segmentReduce = segmentReduce; -exports.lineEach = lineEach; -exports.lineReduce = lineReduce; -exports.findSegment = findSegment; -exports.findPoint = findPoint; - -},{"@turf/helpers":57}],59:[function(_dereq_,module,exports){ -'use strict' - -var weakMap = typeof WeakMap === 'undefined' ? _dereq_('weak-map') : WeakMap -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') - -var TriangleCache = new weakMap() - -function createABigTriangle(gl) { - - var triangleVAO = TriangleCache.get(gl) - var handle = triangleVAO && (triangleVAO._triangleBuffer.handle || triangleVAO._triangleBuffer.buffer) - if(!handle || !gl.isBuffer(handle)) { - var buf = createBuffer(gl, new Float32Array([-1, -1, -1, 4, 4, -1])) - triangleVAO = createVAO(gl, [ - { buffer: buf, - type: gl.FLOAT, - size: 2 - } - ]) - triangleVAO._triangleBuffer = buf - TriangleCache.set(gl, triangleVAO) - } - triangleVAO.bind() - gl.drawArrays(gl.TRIANGLES, 0, 3) - triangleVAO.unbind() -} - -module.exports = createABigTriangle - -},{"gl-buffer":241,"gl-vao":327,"weak-map":552}],60:[function(_dereq_,module,exports){ - -module.exports = absolutize - -/** - * redefine `path` with absolute coordinates - * - * @param {Array} path - * @return {Array} - */ - -function absolutize(path){ - var startX = 0 - var startY = 0 - var x = 0 - var y = 0 - - return path.map(function(seg){ - seg = seg.slice() - var type = seg[0] - var command = type.toUpperCase() - - // is relative - if (type != command) { - seg[0] = command - switch (type) { - case 'a': - seg[6] += x - seg[7] += y - break - case 'v': - seg[1] += y - break - case 'h': - seg[1] += x - break - default: - for (var i = 1; i < seg.length;) { - seg[i++] += x - seg[i++] += y - } - } - } - - // update cursor state - switch (command) { - case 'Z': - x = startX - y = startY - break - case 'H': - x = seg[1] - break - case 'V': - y = seg[1] - break - case 'M': - x = startX = seg[1] - y = startY = seg[2] - break - default: - x = seg[seg.length - 2] - y = seg[seg.length - 1] - } - - return seg - }) -} - -},{}],61:[function(_dereq_,module,exports){ -var padLeft = _dereq_('pad-left') - -module.exports = addLineNumbers -function addLineNumbers (string, start, delim) { - start = typeof start === 'number' ? start : 1 - delim = delim || ': ' - - var lines = string.split(/\r?\n/) - var totalDigits = String(lines.length + start - 1).length - return lines.map(function (line, i) { - var c = i + start - var digits = String(c).length - var prefix = padLeft(c, totalDigits - digits) - return prefix + delim + line - }).join('\n') -} - -},{"pad-left":457}],62:[function(_dereq_,module,exports){ -'use strict' - -module.exports = affineHull - -var orient = _dereq_('robust-orientation') - -function linearlyIndependent(points, d) { - var nhull = new Array(d+1) - for(var i=0; i max) max = arr[i]; - if (arr[i] < min) min = arr[i]; - } - - bounds[offset] = min - bounds[dim + offset] = max - } - - return bounds; -} - -},{}],66:[function(_dereq_,module,exports){ -'use strict' - -var getBounds = _dereq_('array-bounds') - -module.exports = normalize; - -function normalize (arr, dim, bounds) { - if (!arr || arr.length == null) throw Error('Argument should be an array') - - if (dim == null) dim = 1 - if (bounds == null) bounds = getBounds(arr, dim) - - for (var offset = 0; offset < dim; offset++) { - var max = bounds[dim + offset], min = bounds[offset], i = offset, l = arr.length; - - if (max === Infinity && min === -Infinity) { - for (i = offset; i < l; i+=dim) { - arr[i] = arr[i] === max ? 1 : arr[i] === min ? 0 : .5 - } - } - else if (max === Infinity) { - for (i = offset; i < l; i+=dim) { - arr[i] = arr[i] === max ? 1 : 0 - } - } - else if (min === -Infinity) { - for (i = offset; i < l; i+=dim) { - arr[i] = arr[i] === min ? 0 : 1 - } - } - else { - var range = max - min - for (i = offset; i < l; i+=dim) { - arr[i] = range === 0 ? .5 : (arr[i] - min) / range - } - } - } - - return arr; -} - -},{"array-bounds":65}],67:[function(_dereq_,module,exports){ - -module.exports = function newArray(start, end) { - var n0 = typeof start === 'number', - n1 = typeof end === 'number' - - if (n0 && !n1) { - end = start - start = 0 - } else if (!n0 && !n1) { - start = 0 - end = 0 - } - - start = start|0 - end = end|0 - var len = end-start - if (len<0) - throw new Error('array length must be positive') - - var a = new Array(len) - for (var i=0, c=start; i - * @license MIT - */ -function compare(a, b) { - if (a === b) { - return 0; - } - - var x = a.length; - var y = b.length; - - for (var i = 0, len = Math.min(x, y); i < len; ++i) { - if (a[i] !== b[i]) { - x = a[i]; - y = b[i]; - break; - } - } - - if (x < y) { - return -1; - } - if (y < x) { - return 1; - } - return 0; -} -function isBuffer(b) { - if (global.Buffer && typeof global.Buffer.isBuffer === 'function') { - return global.Buffer.isBuffer(b); - } - return !!(b != null && b._isBuffer); -} - -// based on node assert, original notice: -// NB: The URL to the CommonJS spec is kept just for tradition. -// node-assert has evolved a lot since then, both in API and behavior. - -// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 -// -// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! -// -// Originally from narwhal.js (http://narwhaljs.org) -// Copyright (c) 2009 Thomas Robinson <280north.com> -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the 'Software'), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -var util = _dereq_('util/'); -var hasOwn = Object.prototype.hasOwnProperty; -var pSlice = Array.prototype.slice; -var functionsHaveNames = (function () { - return function foo() {}.name === 'foo'; -}()); -function pToString (obj) { - return Object.prototype.toString.call(obj); -} -function isView(arrbuf) { - if (isBuffer(arrbuf)) { - return false; - } - if (typeof global.ArrayBuffer !== 'function') { - return false; - } - if (typeof ArrayBuffer.isView === 'function') { - return ArrayBuffer.isView(arrbuf); - } - if (!arrbuf) { - return false; - } - if (arrbuf instanceof DataView) { - return true; - } - if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { - return true; - } - return false; -} -// 1. The assert module provides functions that throw -// AssertionError's when particular conditions are not met. The -// assert module must conform to the following interface. - -var assert = module.exports = ok; - -// 2. The AssertionError is defined in assert. -// new assert.AssertionError({ message: message, -// actual: actual, -// expected: expected }) - -var regex = /\s*function\s+([^\(\s]*)\s*/; -// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js -function getName(func) { - if (!util.isFunction(func)) { - return; - } - if (functionsHaveNames) { - return func.name; - } - var str = func.toString(); - var match = str.match(regex); - return match && match[1]; -} -assert.AssertionError = function AssertionError(options) { - this.name = 'AssertionError'; - this.actual = options.actual; - this.expected = options.expected; - this.operator = options.operator; - if (options.message) { - this.message = options.message; - this.generatedMessage = false; - } else { - this.message = getMessage(this); - this.generatedMessage = true; - } - var stackStartFunction = options.stackStartFunction || fail; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, stackStartFunction); - } else { - // non v8 browsers so we can have a stacktrace - var err = new Error(); - if (err.stack) { - var out = err.stack; - - // try to strip useless frames - var fn_name = getName(stackStartFunction); - var idx = out.indexOf('\n' + fn_name); - if (idx >= 0) { - // once we have located the function frame - // we need to strip out everything before it (and its line) - var next_line = out.indexOf('\n', idx + 1); - out = out.substring(next_line + 1); - } - - this.stack = out; - } - } -}; - -// assert.AssertionError instanceof Error -util.inherits(assert.AssertionError, Error); - -function truncate(s, n) { - if (typeof s === 'string') { - return s.length < n ? s : s.slice(0, n); - } else { - return s; - } -} -function inspect(something) { - if (functionsHaveNames || !util.isFunction(something)) { - return util.inspect(something); - } - var rawname = getName(something); - var name = rawname ? ': ' + rawname : ''; - return '[Function' + name + ']'; -} -function getMessage(self) { - return truncate(inspect(self.actual), 128) + ' ' + - self.operator + ' ' + - truncate(inspect(self.expected), 128); -} - -// At present only the three keys mentioned above are used and -// understood by the spec. Implementations or sub modules can pass -// other keys to the AssertionError's constructor - they will be -// ignored. - -// 3. All of the following functions must throw an AssertionError -// when a corresponding condition is not met, with a message that -// may be undefined if not provided. All assertion methods provide -// both the actual and expected values to the assertion error for -// display purposes. - -function fail(actual, expected, message, operator, stackStartFunction) { - throw new assert.AssertionError({ - message: message, - actual: actual, - expected: expected, - operator: operator, - stackStartFunction: stackStartFunction - }); -} - -// EXTENSION! allows for well behaved errors defined elsewhere. -assert.fail = fail; - -// 4. Pure assertion tests whether a value is truthy, as determined -// by !!guard. -// assert.ok(guard, message_opt); -// This statement is equivalent to assert.equal(true, !!guard, -// message_opt);. To test strictly for the value true, use -// assert.strictEqual(true, guard, message_opt);. - -function ok(value, message) { - if (!value) fail(value, true, message, '==', assert.ok); -} -assert.ok = ok; - -// 5. The equality assertion tests shallow, coercive equality with -// ==. -// assert.equal(actual, expected, message_opt); - -assert.equal = function equal(actual, expected, message) { - if (actual != expected) fail(actual, expected, message, '==', assert.equal); -}; - -// 6. The non-equality assertion tests for whether two objects are not equal -// with != assert.notEqual(actual, expected, message_opt); - -assert.notEqual = function notEqual(actual, expected, message) { - if (actual == expected) { - fail(actual, expected, message, '!=', assert.notEqual); - } -}; - -// 7. The equivalence assertion tests a deep equality relation. -// assert.deepEqual(actual, expected, message_opt); - -assert.deepEqual = function deepEqual(actual, expected, message) { - if (!_deepEqual(actual, expected, false)) { - fail(actual, expected, message, 'deepEqual', assert.deepEqual); - } -}; - -assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { - if (!_deepEqual(actual, expected, true)) { - fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual); - } -}; - -function _deepEqual(actual, expected, strict, memos) { - // 7.1. All identical values are equivalent, as determined by ===. - if (actual === expected) { - return true; - } else if (isBuffer(actual) && isBuffer(expected)) { - return compare(actual, expected) === 0; - - // 7.2. If the expected value is a Date object, the actual value is - // equivalent if it is also a Date object that refers to the same time. - } else if (util.isDate(actual) && util.isDate(expected)) { - return actual.getTime() === expected.getTime(); - - // 7.3 If the expected value is a RegExp object, the actual value is - // equivalent if it is also a RegExp object with the same source and - // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). - } else if (util.isRegExp(actual) && util.isRegExp(expected)) { - return actual.source === expected.source && - actual.global === expected.global && - actual.multiline === expected.multiline && - actual.lastIndex === expected.lastIndex && - actual.ignoreCase === expected.ignoreCase; - - // 7.4. Other pairs that do not both pass typeof value == 'object', - // equivalence is determined by ==. - } else if ((actual === null || typeof actual !== 'object') && - (expected === null || typeof expected !== 'object')) { - return strict ? actual === expected : actual == expected; - - // If both values are instances of typed arrays, wrap their underlying - // ArrayBuffers in a Buffer each to increase performance - // This optimization requires the arrays to have the same type as checked by - // Object.prototype.toString (aka pToString). Never perform binary - // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their - // bit patterns are not identical. - } else if (isView(actual) && isView(expected) && - pToString(actual) === pToString(expected) && - !(actual instanceof Float32Array || - actual instanceof Float64Array)) { - return compare(new Uint8Array(actual.buffer), - new Uint8Array(expected.buffer)) === 0; - - // 7.5 For all other Object pairs, including Array objects, equivalence is - // determined by having the same number of owned properties (as verified - // with Object.prototype.hasOwnProperty.call), the same set of keys - // (although not necessarily the same order), equivalent values for every - // corresponding key, and an identical 'prototype' property. Note: this - // accounts for both named and indexed properties on Arrays. - } else if (isBuffer(actual) !== isBuffer(expected)) { - return false; - } else { - memos = memos || {actual: [], expected: []}; - - var actualIndex = memos.actual.indexOf(actual); - if (actualIndex !== -1) { - if (actualIndex === memos.expected.indexOf(expected)) { - return true; - } - } - - memos.actual.push(actual); - memos.expected.push(expected); - - return objEquiv(actual, expected, strict, memos); - } -} - -function isArguments(object) { - return Object.prototype.toString.call(object) == '[object Arguments]'; -} - -function objEquiv(a, b, strict, actualVisitedObjects) { - if (a === null || a === undefined || b === null || b === undefined) - return false; - // if one is a primitive, the other must be same - if (util.isPrimitive(a) || util.isPrimitive(b)) - return a === b; - if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) - return false; - var aIsArgs = isArguments(a); - var bIsArgs = isArguments(b); - if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) - return false; - if (aIsArgs) { - a = pSlice.call(a); - b = pSlice.call(b); - return _deepEqual(a, b, strict); - } - var ka = objectKeys(a); - var kb = objectKeys(b); - var key, i; - // having the same number of owned properties (keys incorporates - // hasOwnProperty) - if (ka.length !== kb.length) - return false; - //the same set of keys (although not necessarily the same order), - ka.sort(); - kb.sort(); - //~~~cheap key test - for (i = ka.length - 1; i >= 0; i--) { - if (ka[i] !== kb[i]) - return false; - } - //equivalent values for every corresponding key, and - //~~~possibly expensive deep test - for (i = ka.length - 1; i >= 0; i--) { - key = ka[i]; - if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) - return false; - } - return true; -} - -// 8. The non-equivalence assertion tests for any deep inequality. -// assert.notDeepEqual(actual, expected, message_opt); - -assert.notDeepEqual = function notDeepEqual(actual, expected, message) { - if (_deepEqual(actual, expected, false)) { - fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); - } -}; - -assert.notDeepStrictEqual = notDeepStrictEqual; -function notDeepStrictEqual(actual, expected, message) { - if (_deepEqual(actual, expected, true)) { - fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual); - } -} - - -// 9. The strict equality assertion tests strict equality, as determined by ===. -// assert.strictEqual(actual, expected, message_opt); - -assert.strictEqual = function strictEqual(actual, expected, message) { - if (actual !== expected) { - fail(actual, expected, message, '===', assert.strictEqual); - } -}; - -// 10. The strict non-equality assertion tests for strict inequality, as -// determined by !==. assert.notStrictEqual(actual, expected, message_opt); - -assert.notStrictEqual = function notStrictEqual(actual, expected, message) { - if (actual === expected) { - fail(actual, expected, message, '!==', assert.notStrictEqual); - } -}; - -function expectedException(actual, expected) { - if (!actual || !expected) { - return false; - } - - if (Object.prototype.toString.call(expected) == '[object RegExp]') { - return expected.test(actual); - } - - try { - if (actual instanceof expected) { - return true; - } - } catch (e) { - // Ignore. The instanceof check doesn't work for arrow functions. - } - - if (Error.isPrototypeOf(expected)) { - return false; - } - - return expected.call({}, actual) === true; -} - -function _tryBlock(block) { - var error; - try { - block(); - } catch (e) { - error = e; - } - return error; -} - -function _throws(shouldThrow, block, expected, message) { - var actual; - - if (typeof block !== 'function') { - throw new TypeError('"block" argument must be a function'); - } - - if (typeof expected === 'string') { - message = expected; - expected = null; - } - - actual = _tryBlock(block); - - message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + - (message ? ' ' + message : '.'); - - if (shouldThrow && !actual) { - fail(actual, expected, 'Missing expected exception' + message); - } - - var userProvidedMessage = typeof message === 'string'; - var isUnwantedException = !shouldThrow && util.isError(actual); - var isUnexpectedException = !shouldThrow && actual && !expected; - - if ((isUnwantedException && - userProvidedMessage && - expectedException(actual, expected)) || - isUnexpectedException) { - fail(actual, expected, 'Got unwanted exception' + message); - } - - if ((shouldThrow && actual && expected && - !expectedException(actual, expected)) || (!shouldThrow && actual)) { - throw actual; - } -} - -// 11. Expected to throw an error: -// assert.throws(block, Error_opt, message_opt); - -assert.throws = function(block, /*optional*/error, /*optional*/message) { - _throws(true, block, error, message); -}; - -// EXTENSION! This is annoying to write outside this module. -assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { - _throws(false, block, error, message); -}; - -assert.ifError = function(err) { if (err) throw err; }; - -// Expose a strict only variant of assert -function strict(value, message) { - if (!value) fail(value, true, message, '==', strict); -} -assert.strict = objectAssign(strict, assert, { - equal: assert.strictEqual, - deepEqual: assert.deepStrictEqual, - notEqual: assert.notStrictEqual, - notDeepEqual: assert.notDeepStrictEqual -}); -assert.strict.strict = assert.strict; - -var objectKeys = Object.keys || function (obj) { - var keys = []; - for (var key in obj) { - if (hasOwn.call(obj, key)) keys.push(key); - } - return keys; -}; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"object-assign":454,"util/":71}],69:[function(_dereq_,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],70:[function(_dereq_,module,exports){ -module.exports = function isBuffer(arg) { - return arg && typeof arg === 'object' - && typeof arg.copy === 'function' - && typeof arg.fill === 'function' - && typeof arg.readUInt8 === 'function'; -} -},{}],71:[function(_dereq_,module,exports){ -(function (process,global){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var formatRegExp = /%[sdj%]/g; -exports.format = function(f) { - if (!isString(f)) { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(inspect(arguments[i])); - } - return objects.join(' '); - } - - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': - try { - return JSON.stringify(args[i++]); - } catch (_) { - return '[Circular]'; - } - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (isNull(x) || !isObject(x)) { - str += ' ' + x; - } else { - str += ' ' + inspect(x); - } - } - return str; -}; - - -// Mark that a method should not be used. -// Returns a modified function which warns once by default. -// If --no-deprecation is set, then it is a no-op. -exports.deprecate = function(fn, msg) { - // Allow for deprecating things in the process of starting up. - if (isUndefined(global.process)) { - return function() { - return exports.deprecate(fn, msg).apply(this, arguments); - }; - } - - if (process.noDeprecation === true) { - return fn; - } - - var warned = false; - function deprecated() { - if (!warned) { - if (process.throwDeprecation) { - throw new Error(msg); - } else if (process.traceDeprecation) { - console.trace(msg); - } else { - console.error(msg); - } - warned = true; - } - return fn.apply(this, arguments); - } - - return deprecated; -}; - - -var debugs = {}; -var debugEnviron; -exports.debuglog = function(set) { - if (isUndefined(debugEnviron)) - debugEnviron = process.env.NODE_DEBUG || ''; - set = set.toUpperCase(); - if (!debugs[set]) { - if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { - var pid = process.pid; - debugs[set] = function() { - var msg = exports.format.apply(exports, arguments); - console.error('%s %d: %s', set, pid, msg); - }; - } else { - debugs[set] = function() {}; - } - } - return debugs[set]; -}; - - -/** - * Echos the value of a value. Trys to print the value out - * in the best way possible given the different types. - * - * @param {Object} obj The object to print out. - * @param {Object} opts Optional options object that alters the output. - */ -/* legacy: obj, showHidden, depth, colors*/ -function inspect(obj, opts) { - // default options - var ctx = { - seen: [], - stylize: stylizeNoColor - }; - // legacy... - if (arguments.length >= 3) ctx.depth = arguments[2]; - if (arguments.length >= 4) ctx.colors = arguments[3]; - if (isBoolean(opts)) { - // legacy... - ctx.showHidden = opts; - } else if (opts) { - // got an "options" object - exports._extend(ctx, opts); - } - // set default options - if (isUndefined(ctx.showHidden)) ctx.showHidden = false; - if (isUndefined(ctx.depth)) ctx.depth = 2; - if (isUndefined(ctx.colors)) ctx.colors = false; - if (isUndefined(ctx.customInspect)) ctx.customInspect = true; - if (ctx.colors) ctx.stylize = stylizeWithColor; - return formatValue(ctx, obj, ctx.depth); -} -exports.inspect = inspect; - - -// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics -inspect.colors = { - 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [30, 39], - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] -}; - -// Don't use 'blue' not visible on cmd.exe -inspect.styles = { - 'special': 'cyan', - 'number': 'yellow', - 'boolean': 'yellow', - 'undefined': 'grey', - 'null': 'bold', - 'string': 'green', - 'date': 'magenta', - // "name": intentionally not styling - 'regexp': 'red' -}; - - -function stylizeWithColor(str, styleType) { - var style = inspect.styles[styleType]; - - if (style) { - return '\u001b[' + inspect.colors[style][0] + 'm' + str + - '\u001b[' + inspect.colors[style][1] + 'm'; - } else { - return str; - } -} - - -function stylizeNoColor(str, styleType) { - return str; -} - - -function arrayToHash(array) { - var hash = {}; - - array.forEach(function(val, idx) { - hash[val] = true; - }); - - return hash; -} - - -function formatValue(ctx, value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (ctx.customInspect && - value && - isFunction(value.inspect) && - // Filter out the util module, it's inspect function is special - value.inspect !== exports.inspect && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - var ret = value.inspect(recurseTimes, ctx); - if (!isString(ret)) { - ret = formatValue(ctx, ret, recurseTimes); - } - return ret; - } - - // Primitive types cannot have properties - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; - } - - // Look up the keys of the object. - var keys = Object.keys(value); - var visibleKeys = arrayToHash(keys); - - if (ctx.showHidden) { - keys = Object.getOwnPropertyNames(value); - } - - // IE doesn't make error fields non-enumerable - // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx - if (isError(value) - && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { - return formatError(value); - } - - // Some type of object without properties can be shortcutted. - if (keys.length === 0) { - if (isFunction(value)) { - var name = value.name ? ': ' + value.name : ''; - return ctx.stylize('[Function' + name + ']', 'special'); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toString.call(value), 'date'); - } - if (isError(value)) { - return formatError(value); - } - } - - var base = '', array = false, braces = ['{', '}']; - - // Make Array say that they are Array - if (isArray(value)) { - array = true; - braces = ['[', ']']; - } - - // Make functions say that they are functions - if (isFunction(value)) { - var n = value.name ? ': ' + value.name : ''; - base = ' [Function' + n + ']'; - } - - // Make RegExps say that they are RegExps - if (isRegExp(value)) { - base = ' ' + RegExp.prototype.toString.call(value); - } - - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + Date.prototype.toUTCString.call(value); - } - - // Make error with message first say the error - if (isError(value)) { - base = ' ' + formatError(value); - } - - if (keys.length === 0 && (!array || value.length == 0)) { - return braces[0] + base + braces[1]; - } - - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } else { - return ctx.stylize('[Object]', 'special'); - } - } - - ctx.seen.push(value); - - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function(key) { - return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); - }); - } - - ctx.seen.pop(); - - return reduceToSingleString(output, base, braces); -} - - -function formatPrimitive(ctx, value) { - if (isUndefined(value)) - return ctx.stylize('undefined', 'undefined'); - if (isString(value)) { - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return ctx.stylize(simple, 'string'); - } - if (isNumber(value)) - return ctx.stylize('' + value, 'number'); - if (isBoolean(value)) - return ctx.stylize('' + value, 'boolean'); - // For some reason typeof null is "object", so special case here. - if (isNull(value)) - return ctx.stylize('null', 'null'); -} - - -function formatError(value) { - return '[' + Error.prototype.toString.call(value) + ']'; -} - - -function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (hasOwnProperty(value, String(i))) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - String(i), true)); - } else { - output.push(''); - } - } - keys.forEach(function(key) { - if (!key.match(/^\d+$/)) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - key, true)); - } - }); - return output; -} - - -function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str, desc; - desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; - if (desc.get) { - if (desc.set) { - str = ctx.stylize('[Getter/Setter]', 'special'); - } else { - str = ctx.stylize('[Getter]', 'special'); - } - } else { - if (desc.set) { - str = ctx.stylize('[Setter]', 'special'); - } - } - if (!hasOwnProperty(visibleKeys, key)) { - name = '[' + key + ']'; - } - if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (isNull(recurseTimes)) { - str = formatValue(ctx, desc.value, null); - } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n').substr(2); - } else { - str = '\n' + str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n'); - } - } - } else { - str = ctx.stylize('[Circular]', 'special'); - } - } - if (isUndefined(name)) { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, 'name'); - } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, 'string'); - } - } - - return name + ': ' + str; -} - - -function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; - var length = output.reduce(function(prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) numLinesEst++; - return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; - }, 0); - - if (length > 60) { - return braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; - } - - return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; -} - - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -function isArray(ar) { - return Array.isArray(ar); -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return isObject(re) && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return isObject(e) && - (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -exports.isBuffer = _dereq_('./support/isBuffer'); - -function objectToString(o) { - return Object.prototype.toString.call(o); -} - - -function pad(n) { - return n < 10 ? '0' + n.toString(10) : n.toString(10); -} - - -var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec']; - -// 26 Feb 16:19:34 -function timestamp() { - var d = new Date(); - var time = [pad(d.getHours()), - pad(d.getMinutes()), - pad(d.getSeconds())].join(':'); - return [d.getDate(), months[d.getMonth()], time].join(' '); -} - - -// log is just a thin wrapper to console.log that prepends a timestamp -exports.log = function() { - console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); -}; - - -/** - * Inherit the prototype methods from one constructor into another. - * - * The Function.prototype.inherits from lang.js rewritten as a standalone - * function (not on Function.prototype). NOTE: If this file is to be loaded - * during bootstrapping this function needs to be rewritten using some native - * functions as prototype setup using normal JavaScript does not work as - * expected during bootstrapping (see mirror.js in r114903). - * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. - */ -exports.inherits = _dereq_('inherits'); - -exports._extend = function(origin, add) { - // Don't do anything if add isn't an object - if (!add || !isObject(add)) return origin; - - var keys = Object.keys(add); - var i = keys.length; - while (i--) { - origin[keys[i]] = add[keys[i]]; - } - return origin; -}; - -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":70,"_process":482,"inherits":69}],72:[function(_dereq_,module,exports){ -module.exports = function _atob(str) { - return atob(str) -} - -},{}],73:[function(_dereq_,module,exports){ -'use strict' - -module.exports = barycentric - -var solve = _dereq_('robust-linear-solve') - -function reduce(x) { - var r = 0 - for(var i=0; i 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // Trim off extra bytes after placeholder bytes are found - // See: https://github.com/beatgammit/base64-js/issues/42 - var validLen = b64.indexOf('=') - if (validLen === -1) validLen = len - - var placeHoldersLen = validLen === len - ? 0 - : 4 - (validLen % 4) - - return [validLen, placeHoldersLen] -} - -// base64 is 4/3 + up to two characters of the original data -function byteLength (b64) { - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} - -function _byteLength (b64, validLen, placeHoldersLen) { - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} - -function toByteArray (b64) { - var tmp - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - - var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) - - var curByte = 0 - - // if there are placeholders, only get up to the last complete 4 chars - var len = placeHoldersLen > 0 - ? validLen - 4 - : validLen - - for (var i = 0; i < len; i += 4) { - tmp = - (revLookup[b64.charCodeAt(i)] << 18) | - (revLookup[b64.charCodeAt(i + 1)] << 12) | - (revLookup[b64.charCodeAt(i + 2)] << 6) | - revLookup[b64.charCodeAt(i + 3)] - arr[curByte++] = (tmp >> 16) & 0xFF - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } - - if (placeHoldersLen === 2) { - tmp = - (revLookup[b64.charCodeAt(i)] << 2) | - (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[curByte++] = tmp & 0xFF - } - - if (placeHoldersLen === 1) { - tmp = - (revLookup[b64.charCodeAt(i)] << 10) | - (revLookup[b64.charCodeAt(i + 1)] << 4) | - (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } - - return arr -} - -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + - lookup[num >> 12 & 0x3F] + - lookup[num >> 6 & 0x3F] + - lookup[num & 0x3F] -} - -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = - ((uint8[i] << 16) & 0xFF0000) + - ((uint8[i + 1] << 8) & 0xFF00) + - (uint8[i + 2] & 0xFF) - output.push(tripletToBase64(tmp)) - } - return output.join('') -} - -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 - - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk( - uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) - )) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - parts.push( - lookup[tmp >> 2] + - lookup[(tmp << 4) & 0x3F] + - '==' - ) - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + uint8[len - 1] - parts.push( - lookup[tmp >> 10] + - lookup[(tmp >> 4) & 0x3F] + - lookup[(tmp << 2) & 0x3F] + - '=' - ) - } - - return parts.join('') -} - -},{}],75:[function(_dereq_,module,exports){ -'use strict' - -var rationalize = _dereq_('./lib/rationalize') - -module.exports = add - -function add(a, b) { - return rationalize( - a[0].mul(b[1]).add(b[0].mul(a[1])), - a[1].mul(b[1])) -} - -},{"./lib/rationalize":85}],76:[function(_dereq_,module,exports){ -'use strict' - -module.exports = cmp - -function cmp(a, b) { - return a[0].mul(b[1]).cmp(b[0].mul(a[1])) -} - -},{}],77:[function(_dereq_,module,exports){ -'use strict' - -var rationalize = _dereq_('./lib/rationalize') - -module.exports = div - -function div(a, b) { - return rationalize(a[0].mul(b[1]), a[1].mul(b[0])) -} - -},{"./lib/rationalize":85}],78:[function(_dereq_,module,exports){ -'use strict' - -var isRat = _dereq_('./is-rat') -var isBN = _dereq_('./lib/is-bn') -var num2bn = _dereq_('./lib/num-to-bn') -var str2bn = _dereq_('./lib/str-to-bn') -var rationalize = _dereq_('./lib/rationalize') -var div = _dereq_('./div') - -module.exports = makeRational - -function makeRational(numer, denom) { - if(isRat(numer)) { - if(denom) { - return div(numer, makeRational(denom)) - } - return [numer[0].clone(), numer[1].clone()] - } - var shift = 0 - var a, b - if(isBN(numer)) { - a = numer.clone() - } else if(typeof numer === 'string') { - a = str2bn(numer) - } else if(numer === 0) { - return [num2bn(0), num2bn(1)] - } else if(numer === Math.floor(numer)) { - a = num2bn(numer) - } else { - while(numer !== Math.floor(numer)) { - numer = numer * Math.pow(2, 256) - shift -= 256 - } - a = num2bn(numer) - } - if(isRat(denom)) { - a.mul(denom[1]) - b = denom[0].clone() - } else if(isBN(denom)) { - b = denom.clone() - } else if(typeof denom === 'string') { - b = str2bn(denom) - } else if(!denom) { - b = num2bn(1) - } else if(denom === Math.floor(denom)) { - b = num2bn(denom) - } else { - while(denom !== Math.floor(denom)) { - denom = denom * Math.pow(2, 256) - shift += 256 - } - b = num2bn(denom) - } - if(shift > 0) { - a = a.ushln(shift) - } else if(shift < 0) { - b = b.ushln(-shift) - } - return rationalize(a, b) -} - -},{"./div":77,"./is-rat":79,"./lib/is-bn":83,"./lib/num-to-bn":84,"./lib/rationalize":85,"./lib/str-to-bn":86}],79:[function(_dereq_,module,exports){ -'use strict' - -var isBN = _dereq_('./lib/is-bn') - -module.exports = isRat - -function isRat(x) { - return Array.isArray(x) && x.length === 2 && isBN(x[0]) && isBN(x[1]) -} - -},{"./lib/is-bn":83}],80:[function(_dereq_,module,exports){ -'use strict' - -var BN = _dereq_('bn.js') - -module.exports = sign - -function sign (x) { - return x.cmp(new BN(0)) -} - -},{"bn.js":94}],81:[function(_dereq_,module,exports){ -'use strict' - -var sign = _dereq_('./bn-sign') - -module.exports = bn2num - -//TODO: Make this better -function bn2num(b) { - var l = b.length - var words = b.words - var out = 0 - if (l === 1) { - out = words[0] - } else if (l === 2) { - out = words[0] + (words[1] * 0x4000000) - } else { - for (var i = 0; i < l; i++) { - var w = words[i] - out += w * Math.pow(0x4000000, i) - } - } - return sign(b) * out -} - -},{"./bn-sign":80}],82:[function(_dereq_,module,exports){ -'use strict' - -var db = _dereq_('double-bits') -var ctz = _dereq_('bit-twiddle').countTrailingZeros - -module.exports = ctzNumber - -//Counts the number of trailing zeros -function ctzNumber(x) { - var l = ctz(db.lo(x)) - if(l < 32) { - return l - } - var h = ctz(db.hi(x)) - if(h > 20) { - return 52 - } - return h + 32 -} - -},{"bit-twiddle":92,"double-bits":167}],83:[function(_dereq_,module,exports){ -'use strict' - -var BN = _dereq_('bn.js') - -module.exports = isBN - -//Test if x is a bignumber -//FIXME: obviously this is the wrong way to do it -function isBN(x) { - return x && typeof x === 'object' && Boolean(x.words) -} - -},{"bn.js":94}],84:[function(_dereq_,module,exports){ -'use strict' - -var BN = _dereq_('bn.js') -var db = _dereq_('double-bits') - -module.exports = num2bn - -function num2bn(x) { - var e = db.exponent(x) - if(e < 52) { - return new BN(x) - } else { - return (new BN(x * Math.pow(2, 52-e))).ushln(e-52) - } -} - -},{"bn.js":94,"double-bits":167}],85:[function(_dereq_,module,exports){ -'use strict' - -var num2bn = _dereq_('./num-to-bn') -var sign = _dereq_('./bn-sign') - -module.exports = rationalize - -function rationalize(numer, denom) { - var snumer = sign(numer) - var sdenom = sign(denom) - if(snumer === 0) { - return [num2bn(0), num2bn(1)] - } - if(sdenom === 0) { - return [num2bn(0), num2bn(0)] - } - if(sdenom < 0) { - numer = numer.neg() - denom = denom.neg() - } - var d = numer.gcd(denom) - if(d.cmpn(1)) { - return [ numer.div(d), denom.div(d) ] - } - return [ numer, denom ] -} - -},{"./bn-sign":80,"./num-to-bn":84}],86:[function(_dereq_,module,exports){ -'use strict' - -var BN = _dereq_('bn.js') - -module.exports = str2BN - -function str2BN(x) { - return new BN(x) -} - -},{"bn.js":94}],87:[function(_dereq_,module,exports){ -'use strict' - -var rationalize = _dereq_('./lib/rationalize') - -module.exports = mul - -function mul(a, b) { - return rationalize(a[0].mul(b[0]), a[1].mul(b[1])) -} - -},{"./lib/rationalize":85}],88:[function(_dereq_,module,exports){ -'use strict' - -var bnsign = _dereq_('./lib/bn-sign') - -module.exports = sign - -function sign(x) { - return bnsign(x[0]) * bnsign(x[1]) -} - -},{"./lib/bn-sign":80}],89:[function(_dereq_,module,exports){ -'use strict' - -var rationalize = _dereq_('./lib/rationalize') - -module.exports = sub - -function sub(a, b) { - return rationalize(a[0].mul(b[1]).sub(a[1].mul(b[0])), a[1].mul(b[1])) -} - -},{"./lib/rationalize":85}],90:[function(_dereq_,module,exports){ -'use strict' - -var bn2num = _dereq_('./lib/bn-to-num') -var ctz = _dereq_('./lib/ctz') - -module.exports = roundRat - -// Round a rational to the closest float -function roundRat (f) { - var a = f[0] - var b = f[1] - if (a.cmpn(0) === 0) { - return 0 - } - var h = a.abs().divmod(b.abs()) - var iv = h.div - var x = bn2num(iv) - var ir = h.mod - var sgn = (a.negative !== b.negative) ? -1 : 1 - if (ir.cmpn(0) === 0) { - return sgn * x - } - if (x) { - var s = ctz(x) + 4 - var y = bn2num(ir.ushln(s).divRound(b)) - return sgn * (x + y * Math.pow(2, -s)) - } else { - var ybits = b.bitLength() - ir.bitLength() + 53 - var y = bn2num(ir.ushln(ybits).divRound(b)) - if (ybits < 1023) { - return sgn * y * Math.pow(2, -ybits) - } - y *= Math.pow(2, -1023) - return sgn * y * Math.pow(2, 1023 - ybits) - } -} - -},{"./lib/bn-to-num":81,"./lib/ctz":82}],91:[function(_dereq_,module,exports){ -"use strict" - -function compileSearch(funcName, predicate, reversed, extraArgs, useNdarray, earlyOut) { - var code = [ - "function ", funcName, "(a,l,h,", extraArgs.join(","), "){", -earlyOut ? "" : "var i=", (reversed ? "l-1" : "h+1"), -";while(l<=h){\ -var m=(l+h)>>>1,x=a", useNdarray ? ".get(m)" : "[m]"] - if(earlyOut) { - if(predicate.indexOf("c") < 0) { - code.push(";if(x===y){return m}else if(x<=y){") - } else { - code.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){") - } - } else { - code.push(";if(", predicate, "){i=m;") - } - if(reversed) { - code.push("l=m+1}else{h=m-1}") - } else { - code.push("h=m-1}else{l=m+1}") - } - code.push("}") - if(earlyOut) { - code.push("return -1};") - } else { - code.push("return i};") - } - return code.join("") -} - -function compileBoundsSearch(predicate, reversed, suffix, earlyOut) { - var result = new Function([ - compileSearch("A", "x" + predicate + "y", reversed, ["y"], false, earlyOut), - compileSearch("B", "x" + predicate + "y", reversed, ["y"], true, earlyOut), - compileSearch("P", "c(x,y)" + predicate + "0", reversed, ["y", "c"], false, earlyOut), - compileSearch("Q", "c(x,y)" + predicate + "0", reversed, ["y", "c"], true, earlyOut), -"function dispatchBsearch", suffix, "(a,y,c,l,h){\ -if(a.shape){\ -if(typeof(c)==='function'){\ -return Q(a,(l===undefined)?0:l|0,(h===undefined)?a.shape[0]-1:h|0,y,c)\ -}else{\ -return B(a,(c===undefined)?0:c|0,(l===undefined)?a.shape[0]-1:l|0,y)\ -}}else{\ -if(typeof(c)==='function'){\ -return P(a,(l===undefined)?0:l|0,(h===undefined)?a.length-1:h|0,y,c)\ -}else{\ -return A(a,(c===undefined)?0:c|0,(l===undefined)?a.length-1:l|0,y)\ -}}}\ -return dispatchBsearch", suffix].join("")) - return result() -} - -module.exports = { - ge: compileBoundsSearch(">=", false, "GE"), - gt: compileBoundsSearch(">", false, "GT"), - lt: compileBoundsSearch("<", true, "LT"), - le: compileBoundsSearch("<=", true, "LE"), - eq: compileBoundsSearch("-", true, "EQ", true) -} - -},{}],92:[function(_dereq_,module,exports){ -/** - * Bit twiddling hacks for JavaScript. - * - * Author: Mikola Lysenko - * - * Ported from Stanford bit twiddling hack library: - * http://graphics.stanford.edu/~seander/bithacks.html - */ - -"use strict"; "use restrict"; - -//Number of bits in an integer -var INT_BITS = 32; - -//Constants -exports.INT_BITS = INT_BITS; -exports.INT_MAX = 0x7fffffff; -exports.INT_MIN = -1<<(INT_BITS-1); - -//Returns -1, 0, +1 depending on sign of x -exports.sign = function(v) { - return (v > 0) - (v < 0); -} - -//Computes absolute value of integer -exports.abs = function(v) { - var mask = v >> (INT_BITS-1); - return (v ^ mask) - mask; -} - -//Computes minimum of integers x and y -exports.min = function(x, y) { - return y ^ ((x ^ y) & -(x < y)); -} - -//Computes maximum of integers x and y -exports.max = function(x, y) { - return x ^ ((x ^ y) & -(x < y)); -} - -//Checks if a number is a power of two -exports.isPow2 = function(v) { - return !(v & (v-1)) && (!!v); -} - -//Computes log base 2 of v -exports.log2 = function(v) { - var r, shift; - r = (v > 0xFFFF) << 4; v >>>= r; - shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; - return r | (v >> 1); -} - -//Computes log base 10 of v -exports.log10 = function(v) { - return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : - (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : - (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; -} - -//Counts number of bits -exports.popCount = function(v) { - v = v - ((v >>> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); - return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; -} - -//Counts number of trailing zeros -function countTrailingZeros(v) { - var c = 32; - v &= -v; - if (v) c--; - if (v & 0x0000FFFF) c -= 16; - if (v & 0x00FF00FF) c -= 8; - if (v & 0x0F0F0F0F) c -= 4; - if (v & 0x33333333) c -= 2; - if (v & 0x55555555) c -= 1; - return c; -} -exports.countTrailingZeros = countTrailingZeros; - -//Rounds to next power of 2 -exports.nextPow2 = function(v) { - v += v === 0; - --v; - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v + 1; -} - -//Rounds down to previous power of 2 -exports.prevPow2 = function(v) { - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v - (v>>>1); -} - -//Computes parity of word -exports.parity = function(v) { - v ^= v >>> 16; - v ^= v >>> 8; - v ^= v >>> 4; - v &= 0xf; - return (0x6996 >>> v) & 1; -} - -var REVERSE_TABLE = new Array(256); - -(function(tab) { - for(var i=0; i<256; ++i) { - var v = i, r = i, s = 7; - for (v >>>= 1; v; v >>>= 1) { - r <<= 1; - r |= v & 1; - --s; - } - tab[i] = (r << s) & 0xff; - } -})(REVERSE_TABLE); - -//Reverse bits in a 32 bit word -exports.reverse = function(v) { - return (REVERSE_TABLE[ v & 0xff] << 24) | - (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | - (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | - REVERSE_TABLE[(v >>> 24) & 0xff]; -} - -//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes -exports.interleave2 = function(x, y) { - x &= 0xFFFF; - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y &= 0xFFFF; - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -//Extracts the nth interleaved component -exports.deinterleave2 = function(v, n) { - v = (v >>> n) & 0x55555555; - v = (v | (v >>> 1)) & 0x33333333; - v = (v | (v >>> 2)) & 0x0F0F0F0F; - v = (v | (v >>> 4)) & 0x00FF00FF; - v = (v | (v >>> 16)) & 0x000FFFF; - return (v << 16) >> 16; -} - - -//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes -exports.interleave3 = function(x, y, z) { - x &= 0x3FF; - x = (x | (x<<16)) & 4278190335; - x = (x | (x<<8)) & 251719695; - x = (x | (x<<4)) & 3272356035; - x = (x | (x<<2)) & 1227133513; - - y &= 0x3FF; - y = (y | (y<<16)) & 4278190335; - y = (y | (y<<8)) & 251719695; - y = (y | (y<<4)) & 3272356035; - y = (y | (y<<2)) & 1227133513; - x |= (y << 1); - - z &= 0x3FF; - z = (z | (z<<16)) & 4278190335; - z = (z | (z<<8)) & 251719695; - z = (z | (z<<4)) & 3272356035; - z = (z | (z<<2)) & 1227133513; - - return x | (z << 2); -} - -//Extracts nth interleaved component of a 3-tuple -exports.deinterleave3 = function(v, n) { - v = (v >>> n) & 1227133513; - v = (v | (v>>>2)) & 3272356035; - v = (v | (v>>>4)) & 251719695; - v = (v | (v>>>8)) & 4278190335; - v = (v | (v>>>16)) & 0x3FF; - return (v<<22)>>22; -} - -//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) -exports.nextCombination = function(v) { - var t = v | (v - 1); - return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); -} - - -},{}],93:[function(_dereq_,module,exports){ -'use strict' - -var clamp = _dereq_('clamp') - -module.exports = calcSDF - -var INF = 1e20; - -function calcSDF(src, options) { - if (!options) options = {} - - var cutoff = options.cutoff == null ? 0.25 : options.cutoff - var radius = options.radius == null ? 8 : options.radius - var channel = options.channel || 0 - var w, h, size, data, intData, stride, ctx, canvas, imgData, i, l - - // handle image container - if (ArrayBuffer.isView(src) || Array.isArray(src)) { - if (!options.width || !options.height) throw Error('For raw data width and height should be provided by options') - w = options.width, h = options.height - data = src - - if (!options.stride) stride = Math.floor(src.length / w / h) - else stride = options.stride - } - else { - if (window.HTMLCanvasElement && src instanceof window.HTMLCanvasElement) { - canvas = src - ctx = canvas.getContext('2d') - w = canvas.width, h = canvas.height - imgData = ctx.getImageData(0, 0, w, h) - data = imgData.data - stride = 4 - } - else if (window.CanvasRenderingContext2D && src instanceof window.CanvasRenderingContext2D) { - canvas = src.canvas - ctx = src - w = canvas.width, h = canvas.height - imgData = ctx.getImageData(0, 0, w, h) - data = imgData.data - stride = 4 - } - else if (window.ImageData && src instanceof window.ImageData) { - imgData = src - w = src.width, h = src.height - data = imgData.data - stride = 4 - } - } - - size = Math.max(w, h) - - //convert int data to floats - if ((window.Uint8ClampedArray && data instanceof window.Uint8ClampedArray) || (window.Uint8Array && data instanceof window.Uint8Array)) { - intData = data - data = Array(w*h) - - for (i = 0, l = intData.length; i < l; i++) { - data[i] = intData[i*stride + channel] / 255 - } - } - else { - if (stride !== 1) throw Error('Raw data can have only 1 value per pixel') - } - - // temporary arrays for the distance transform - var gridOuter = Array(w * h) - var gridInner = Array(w * h) - var f = Array(size) - var d = Array(size) - var z = Array(size + 1) - var v = Array(size) - - for (i = 0, l = w * h; i < l; i++) { - var a = data[i] - gridOuter[i] = a === 1 ? 0 : a === 0 ? INF : Math.pow(Math.max(0, 0.5 - a), 2) - gridInner[i] = a === 1 ? INF : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2) - } - - edt(gridOuter, w, h, f, d, v, z) - edt(gridInner, w, h, f, d, v, z) - - var dist = window.Float32Array ? new Float32Array(w * h) : new Array(w * h) - - for (i = 0, l = w*h; i < l; i++) { - dist[i] = clamp(1 - ( (gridOuter[i] - gridInner[i]) / radius + cutoff), 0, 1) - } - - return dist -} - -// 2D Euclidean distance transform by Felzenszwalb & Huttenlocher https://cs.brown.edu/~pff/dt/ -function edt(data, width, height, f, d, v, z) { - for (var x = 0; x < width; x++) { - for (var y = 0; y < height; y++) { - f[y] = data[y * width + x] - } - edt1d(f, d, v, z, height) - for (y = 0; y < height; y++) { - data[y * width + x] = d[y] - } - } - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - f[x] = data[y * width + x] - } - edt1d(f, d, v, z, width) - for (x = 0; x < width; x++) { - data[y * width + x] = Math.sqrt(d[x]) - } - } -} - -// 1D squared distance transform -function edt1d(f, d, v, z, n) { - v[0] = 0; - z[0] = -INF - z[1] = +INF - - for (var q = 1, k = 0; q < n; q++) { - var s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]) - while (s <= z[k]) { - k-- - s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]) - } - k++ - v[k] = q - z[k] = s - z[k + 1] = +INF - } - - for (q = 0, k = 0; q < n; q++) { - while (z[k + 1] < q) k++ - d[q] = (q - v[k]) * (q - v[k]) + f[v[k]] - } -} - -},{"clamp":115}],94:[function(_dereq_,module,exports){ -(function (module, exports) { - 'use strict'; - - // Utils - function assert (val, msg) { - if (!val) throw new Error(msg || 'Assertion failed'); - } - - // Could use `inherits` module, but don't want to move from single file - // architecture yet. - function inherits (ctor, superCtor) { - ctor.super_ = superCtor; - var TempCtor = function () {}; - TempCtor.prototype = superCtor.prototype; - ctor.prototype = new TempCtor(); - ctor.prototype.constructor = ctor; - } - - // BN - - function BN (number, base, endian) { - if (BN.isBN(number)) { - return number; - } - - this.negative = 0; - this.words = null; - this.length = 0; - - // Reduction context - this.red = null; - - if (number !== null) { - if (base === 'le' || base === 'be') { - endian = base; - base = 10; - } - - this._init(number || 0, base || 10, endian || 'be'); - } - } - if (typeof module === 'object') { - module.exports = BN; - } else { - exports.BN = BN; - } - - BN.BN = BN; - BN.wordSize = 26; - - var Buffer; - try { - Buffer = _dereq_('buffer').Buffer; - } catch (e) { - } - - BN.isBN = function isBN (num) { - if (num instanceof BN) { - return true; - } - - return num !== null && typeof num === 'object' && - num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); - }; - - BN.max = function max (left, right) { - if (left.cmp(right) > 0) return left; - return right; - }; - - BN.min = function min (left, right) { - if (left.cmp(right) < 0) return left; - return right; - }; - - BN.prototype._init = function init (number, base, endian) { - if (typeof number === 'number') { - return this._initNumber(number, base, endian); - } - - if (typeof number === 'object') { - return this._initArray(number, base, endian); - } - - if (base === 'hex') { - base = 16; - } - assert(base === (base | 0) && base >= 2 && base <= 36); - - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') { - start++; - } - - if (base === 16) { - this._parseHex(number, start); - } else { - this._parseBase(number, base, start); - } - - if (number[0] === '-') { - this.negative = 1; - } - - this.strip(); - - if (endian !== 'le') return; - - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initNumber = function _initNumber (number, base, endian) { - if (number < 0) { - this.negative = 1; - number = -number; - } - if (number < 0x4000000) { - this.words = [ number & 0x3ffffff ]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; - } - - if (endian !== 'le') return; - - // Reverse the bytes - this._initArray(this.toArray(), base, endian); - }; - - BN.prototype._initArray = function _initArray (number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [ 0 ]; - this.length = 1; - return this; - } - - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - var off = 0; - if (endian === 'be') { - for (i = number.length - 1, j = 0; i >= 0; i -= 3) { - w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (i = 0, j = 0; i < number.length; i += 3) { - w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this.strip(); - }; - - function parseHex (str, start, end) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r <<= 4; - - // 'a' - 'f' - if (c >= 49 && c <= 54) { - r |= c - 49 + 0xa; - - // 'A' - 'F' - } else if (c >= 17 && c <= 22) { - r |= c - 17 + 0xa; - - // '0' - '9' - } else { - r |= c & 0xf; - } - } - return r; - } - - BN.prototype._parseHex = function _parseHex (number, start) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - this.words[i] = 0; - } - - var j, w; - // Scan 24-bit chunks and add them to the number - var off = 0; - for (i = number.length - 6, j = 0; i >= start; i -= 6) { - w = parseHex(number, i, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - if (i + 6 !== start) { - w = parseHex(number, start, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - } - this.strip(); - }; - - function parseBase (str, start, end, mul) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - - r *= mul; - - // 'a' - if (c >= 49) { - r += c - 49 + 0xa; - - // 'A' - } else if (c >= 17) { - r += c - 17 + 0xa; - - // '0' - '9' - } else { - r += c; - } - } - return r; - } - - BN.prototype._parseBase = function _parseBase (number, base, start) { - // Initialize as zero - this.words = [ 0 ]; - this.length = 1; - - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { - limbLen++; - } - limbLen--; - limbPow = (limbPow / base) | 0; - - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; - - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); - - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - - if (mod !== 0) { - var pow = 1; - word = parseBase(number, i, number.length, base); - - for (i = 0; i < mod; i++) { - pow *= base; - } - - this.imuln(pow); - if (this.words[0] + word < 0x4000000) { - this.words[0] += word; - } else { - this._iaddn(word); - } - } - }; - - BN.prototype.copy = function copy (dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) { - dest.words[i] = this.words[i]; - } - dest.length = this.length; - dest.negative = this.negative; - dest.red = this.red; - }; - - BN.prototype.clone = function clone () { - var r = new BN(null); - this.copy(r); - return r; - }; - - BN.prototype._expand = function _expand (size) { - while (this.length < size) { - this.words[this.length++] = 0; - } - return this; - }; - - // Remove leading `0` from `this` - BN.prototype.strip = function strip () { - while (this.length > 1 && this.words[this.length - 1] === 0) { - this.length--; - } - return this._normSign(); - }; - - BN.prototype._normSign = function _normSign () { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) { - this.negative = 0; - } - return this; - }; - - BN.prototype.inspect = function inspect () { - return (this.red ? ''; - }; - - /* - - var zeros = []; - var groupSizes = []; - var groupBases = []; - - var s = ''; - var i = -1; - while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; - } - groupSizes[0] = 0; - groupSizes[1] = 0; - groupBases[0] = 0; - groupBases[1] = 0; - var base = 2 - 1; - while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; - } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; - } - - */ - - var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' - ]; - - var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 - ]; - - var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 - ]; - - BN.prototype.toString = function toString (base, padding) { - base = base || 10; - padding = padding | 0 || 1; - - var out; - if (base === 16 || base === 'hex') { - out = ''; - var off = 0; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) { - out = zeros[6 - word.length] + word + out; - } else { - out = word + out; - } - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) { - out = carry.toString(16) + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - out = ''; - var c = this.clone(); - c.negative = 0; - while (!c.isZero()) { - var r = c.modn(groupBase).toString(base); - c = c.idivn(groupBase); - - if (!c.isZero()) { - out = zeros[groupSize - r.length] + r + out; - } else { - out = r + out; - } - } - if (this.isZero()) { - out = '0' + out; - } - while (out.length % padding !== 0) { - out = '0' + out; - } - if (this.negative !== 0) { - out = '-' + out; - } - return out; - } - - assert(false, 'Base should be between 2 and 36'); - }; - - BN.prototype.toNumber = function toNumber () { - var ret = this.words[0]; - if (this.length === 2) { - ret += this.words[1] * 0x4000000; - } else if (this.length === 3 && this.words[2] === 0x01) { - // NOTE: at this stage it is known that the top bit is set - ret += 0x10000000000000 + (this.words[1] * 0x4000000); - } else if (this.length > 2) { - assert(false, 'Number can only safely store up to 53 bits'); - } - return (this.negative !== 0) ? -ret : ret; - }; - - BN.prototype.toJSON = function toJSON () { - return this.toString(16); - }; - - BN.prototype.toBuffer = function toBuffer (endian, length) { - assert(typeof Buffer !== 'undefined'); - return this.toArrayLike(Buffer, endian, length); - }; - - BN.prototype.toArray = function toArray (endian, length) { - return this.toArrayLike(Array, endian, length); - }; - - BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { - var byteLength = this.byteLength(); - var reqLength = length || Math.max(1, byteLength); - assert(byteLength <= reqLength, 'byte array longer than desired length'); - assert(reqLength > 0, 'Requested array length <= 0'); - - this.strip(); - var littleEndian = endian === 'le'; - var res = new ArrayType(reqLength); - - var b, i; - var q = this.clone(); - if (!littleEndian) { - // Assume big-endian - for (i = 0; i < reqLength - byteLength; i++) { - res[i] = 0; - } - - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[reqLength - i - 1] = b; - } - } else { - for (i = 0; !q.isZero(); i++) { - b = q.andln(0xff); - q.iushrn(8); - - res[i] = b; - } - - for (; i < reqLength; i++) { - res[i] = 0; - } - } - - return res; - }; - - if (Math.clz32) { - BN.prototype._countBits = function _countBits (w) { - return 32 - Math.clz32(w); - }; - } else { - BN.prototype._countBits = function _countBits (w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; - } - - BN.prototype._zeroBits = function _zeroBits (w) { - // Short-cut - if (w === 0) return 26; - - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; - } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; - } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; - } - if ((t & 0x1) === 0) { - r++; - } - return r; - }; - - // Return number of used bits in a BN - BN.prototype.bitLength = function bitLength () { - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; - }; - - function toBitArray (num) { - var w = new Array(num.bitLength()); - - for (var bit = 0; bit < w.length; bit++) { - var off = (bit / 26) | 0; - var wbit = bit % 26; - - w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; - } - - return w; - } - - // Number of trailing zero bits - BN.prototype.zeroBits = function zeroBits () { - if (this.isZero()) return 0; - - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) break; - } - return r; - }; - - BN.prototype.byteLength = function byteLength () { - return Math.ceil(this.bitLength() / 8); - }; - - BN.prototype.toTwos = function toTwos (width) { - if (this.negative !== 0) { - return this.abs().inotn(width).iaddn(1); - } - return this.clone(); - }; - - BN.prototype.fromTwos = function fromTwos (width) { - if (this.testn(width - 1)) { - return this.notn(width).iaddn(1).ineg(); - } - return this.clone(); - }; - - BN.prototype.isNeg = function isNeg () { - return this.negative !== 0; - }; - - // Return negative clone of `this` - BN.prototype.neg = function neg () { - return this.clone().ineg(); - }; - - BN.prototype.ineg = function ineg () { - if (!this.isZero()) { - this.negative ^= 1; - } - - return this; - }; - - // Or `num` with `this` in-place - BN.prototype.iuor = function iuor (num) { - while (this.length < num.length) { - this.words[this.length++] = 0; - } - - for (var i = 0; i < num.length; i++) { - this.words[i] = this.words[i] | num.words[i]; - } - - return this.strip(); - }; - - BN.prototype.ior = function ior (num) { - assert((this.negative | num.negative) === 0); - return this.iuor(num); - }; - - // Or `num` with `this` - BN.prototype.or = function or (num) { - if (this.length > num.length) return this.clone().ior(num); - return num.clone().ior(this); - }; - - BN.prototype.uor = function uor (num) { - if (this.length > num.length) return this.clone().iuor(num); - return num.clone().iuor(this); - }; - - // And `num` with `this` in-place - BN.prototype.iuand = function iuand (num) { - // b = min-length(num, this) - var b; - if (this.length > num.length) { - b = num; - } else { - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = this.words[i] & num.words[i]; - } - - this.length = b.length; - - return this.strip(); - }; - - BN.prototype.iand = function iand (num) { - assert((this.negative | num.negative) === 0); - return this.iuand(num); - }; - - // And `num` with `this` - BN.prototype.and = function and (num) { - if (this.length > num.length) return this.clone().iand(num); - return num.clone().iand(this); - }; - - BN.prototype.uand = function uand (num) { - if (this.length > num.length) return this.clone().iuand(num); - return num.clone().iuand(this); - }; - - // Xor `num` with `this` in-place - BN.prototype.iuxor = function iuxor (num) { - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - for (var i = 0; i < b.length; i++) { - this.words[i] = a.words[i] ^ b.words[i]; - } - - if (this !== a) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = a.length; - - return this.strip(); - }; - - BN.prototype.ixor = function ixor (num) { - assert((this.negative | num.negative) === 0); - return this.iuxor(num); - }; - - // Xor `num` with `this` - BN.prototype.xor = function xor (num) { - if (this.length > num.length) return this.clone().ixor(num); - return num.clone().ixor(this); - }; - - BN.prototype.uxor = function uxor (num) { - if (this.length > num.length) return this.clone().iuxor(num); - return num.clone().iuxor(this); - }; - - // Not ``this`` with ``width`` bitwidth - BN.prototype.inotn = function inotn (width) { - assert(typeof width === 'number' && width >= 0); - - var bytesNeeded = Math.ceil(width / 26) | 0; - var bitsLeft = width % 26; - - // Extend the buffer with leading zeroes - this._expand(bytesNeeded); - - if (bitsLeft > 0) { - bytesNeeded--; - } - - // Handle complete words - for (var i = 0; i < bytesNeeded; i++) { - this.words[i] = ~this.words[i] & 0x3ffffff; - } - - // Handle the residue - if (bitsLeft > 0) { - this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); - } - - // And remove leading zeroes - return this.strip(); - }; - - BN.prototype.notn = function notn (width) { - return this.clone().inotn(width); - }; - - // Set `bit` of `this` - BN.prototype.setn = function setn (bit, val) { - assert(typeof bit === 'number' && bit >= 0); - - var off = (bit / 26) | 0; - var wbit = bit % 26; - - this._expand(off + 1); - - if (val) { - this.words[off] = this.words[off] | (1 << wbit); - } else { - this.words[off] = this.words[off] & ~(1 << wbit); - } - - return this.strip(); - }; - - // Add `num` to `this` in-place - BN.prototype.iadd = function iadd (num) { - var r; - - // negative + positive - if (this.negative !== 0 && num.negative === 0) { - this.negative = 0; - r = this.isub(num); - this.negative ^= 1; - return this._normSign(); - - // positive + negative - } else if (this.negative === 0 && num.negative !== 0) { - num.negative = 0; - r = this.isub(num); - num.negative = 1; - return r._normSign(); - } - - // a.length > b.length - var a, b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) + (b.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; - } - - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - return this; - }; - - // Add `num` to `this` - BN.prototype.add = function add (num) { - var res; - if (num.negative !== 0 && this.negative === 0) { - num.negative = 0; - res = this.sub(num); - num.negative ^= 1; - return res; - } else if (num.negative === 0 && this.negative !== 0) { - this.negative = 0; - res = num.sub(this); - this.negative = 1; - return res; - } - - if (this.length > num.length) return this.clone().iadd(num); - - return num.clone().iadd(this); - }; - - // Subtract `num` from `this` in-place - BN.prototype.isub = function isub (num) { - // this - (-num) = this + num - if (num.negative !== 0) { - num.negative = 0; - var r = this.iadd(num); - num.negative = 1; - return r._normSign(); - - // -this - num = -(this + num) - } else if (this.negative !== 0) { - this.negative = 0; - this.iadd(num); - this.negative = 1; - return this._normSign(); - } - - // At this point both numbers are positive - var cmp = this.cmp(num); - - // Optimization - zeroify - if (cmp === 0) { - this.negative = 0; - this.length = 1; - this.words[0] = 0; - return this; - } - - // a > b - var a, b; - if (cmp > 0) { - a = this; - b = num; - } else { - a = num; - b = this; - } - - var carry = 0; - for (var i = 0; i < b.length; i++) { - r = (a.words[i] | 0) - (b.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - for (; carry !== 0 && i < a.length; i++) { - r = (a.words[i] | 0) + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) { - for (; i < a.length; i++) { - this.words[i] = a.words[i]; - } - } - - this.length = Math.max(this.length, i); - - if (a !== this) { - this.negative = 1; - } - - return this.strip(); - }; - - // Subtract `num` from `this` - BN.prototype.sub = function sub (num) { - return this.clone().isub(num); - }; - - function smallMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - var len = (self.length + num.length) | 0; - out.length = len; - len = (len - 1) | 0; - - // Peel one iteration (compiler can't do it, because of code complexity) - var a = self.words[0] | 0; - var b = num.words[0] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - var carry = (r / 0x4000000) | 0; - out.words[0] = lo; - - for (var k = 1; k < len; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = (k - j) | 0; - a = self.words[i] | 0; - b = num.words[j] | 0; - r = a * b + rword; - ncarry += (r / 0x4000000) | 0; - rword = r & 0x3ffffff; - } - out.words[k] = rword | 0; - carry = ncarry | 0; - } - if (carry !== 0) { - out.words[k] = carry | 0; - } else { - out.length--; - } - - return out.strip(); - } - - // TODO(indutny): it may be reasonable to omit it for users who don't need - // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit - // multiplication (like elliptic secp256k1). - var comb10MulTo = function comb10MulTo (self, num, out) { - var a = self.words; - var b = num.words; - var o = out.words; - var c = 0; - var lo; - var mid; - var hi; - var a0 = a[0] | 0; - var al0 = a0 & 0x1fff; - var ah0 = a0 >>> 13; - var a1 = a[1] | 0; - var al1 = a1 & 0x1fff; - var ah1 = a1 >>> 13; - var a2 = a[2] | 0; - var al2 = a2 & 0x1fff; - var ah2 = a2 >>> 13; - var a3 = a[3] | 0; - var al3 = a3 & 0x1fff; - var ah3 = a3 >>> 13; - var a4 = a[4] | 0; - var al4 = a4 & 0x1fff; - var ah4 = a4 >>> 13; - var a5 = a[5] | 0; - var al5 = a5 & 0x1fff; - var ah5 = a5 >>> 13; - var a6 = a[6] | 0; - var al6 = a6 & 0x1fff; - var ah6 = a6 >>> 13; - var a7 = a[7] | 0; - var al7 = a7 & 0x1fff; - var ah7 = a7 >>> 13; - var a8 = a[8] | 0; - var al8 = a8 & 0x1fff; - var ah8 = a8 >>> 13; - var a9 = a[9] | 0; - var al9 = a9 & 0x1fff; - var ah9 = a9 >>> 13; - var b0 = b[0] | 0; - var bl0 = b0 & 0x1fff; - var bh0 = b0 >>> 13; - var b1 = b[1] | 0; - var bl1 = b1 & 0x1fff; - var bh1 = b1 >>> 13; - var b2 = b[2] | 0; - var bl2 = b2 & 0x1fff; - var bh2 = b2 >>> 13; - var b3 = b[3] | 0; - var bl3 = b3 & 0x1fff; - var bh3 = b3 >>> 13; - var b4 = b[4] | 0; - var bl4 = b4 & 0x1fff; - var bh4 = b4 >>> 13; - var b5 = b[5] | 0; - var bl5 = b5 & 0x1fff; - var bh5 = b5 >>> 13; - var b6 = b[6] | 0; - var bl6 = b6 & 0x1fff; - var bh6 = b6 >>> 13; - var b7 = b[7] | 0; - var bl7 = b7 & 0x1fff; - var bh7 = b7 >>> 13; - var b8 = b[8] | 0; - var bl8 = b8 & 0x1fff; - var bh8 = b8 >>> 13; - var b9 = b[9] | 0; - var bl9 = b9 & 0x1fff; - var bh9 = b9 >>> 13; - - out.negative = self.negative ^ num.negative; - out.length = 19; - /* k = 0 */ - lo = Math.imul(al0, bl0); - mid = Math.imul(al0, bh0); - mid = (mid + Math.imul(ah0, bl0)) | 0; - hi = Math.imul(ah0, bh0); - var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; - w0 &= 0x3ffffff; - /* k = 1 */ - lo = Math.imul(al1, bl0); - mid = Math.imul(al1, bh0); - mid = (mid + Math.imul(ah1, bl0)) | 0; - hi = Math.imul(ah1, bh0); - lo = (lo + Math.imul(al0, bl1)) | 0; - mid = (mid + Math.imul(al0, bh1)) | 0; - mid = (mid + Math.imul(ah0, bl1)) | 0; - hi = (hi + Math.imul(ah0, bh1)) | 0; - var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; - w1 &= 0x3ffffff; - /* k = 2 */ - lo = Math.imul(al2, bl0); - mid = Math.imul(al2, bh0); - mid = (mid + Math.imul(ah2, bl0)) | 0; - hi = Math.imul(ah2, bh0); - lo = (lo + Math.imul(al1, bl1)) | 0; - mid = (mid + Math.imul(al1, bh1)) | 0; - mid = (mid + Math.imul(ah1, bl1)) | 0; - hi = (hi + Math.imul(ah1, bh1)) | 0; - lo = (lo + Math.imul(al0, bl2)) | 0; - mid = (mid + Math.imul(al0, bh2)) | 0; - mid = (mid + Math.imul(ah0, bl2)) | 0; - hi = (hi + Math.imul(ah0, bh2)) | 0; - var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; - w2 &= 0x3ffffff; - /* k = 3 */ - lo = Math.imul(al3, bl0); - mid = Math.imul(al3, bh0); - mid = (mid + Math.imul(ah3, bl0)) | 0; - hi = Math.imul(ah3, bh0); - lo = (lo + Math.imul(al2, bl1)) | 0; - mid = (mid + Math.imul(al2, bh1)) | 0; - mid = (mid + Math.imul(ah2, bl1)) | 0; - hi = (hi + Math.imul(ah2, bh1)) | 0; - lo = (lo + Math.imul(al1, bl2)) | 0; - mid = (mid + Math.imul(al1, bh2)) | 0; - mid = (mid + Math.imul(ah1, bl2)) | 0; - hi = (hi + Math.imul(ah1, bh2)) | 0; - lo = (lo + Math.imul(al0, bl3)) | 0; - mid = (mid + Math.imul(al0, bh3)) | 0; - mid = (mid + Math.imul(ah0, bl3)) | 0; - hi = (hi + Math.imul(ah0, bh3)) | 0; - var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; - w3 &= 0x3ffffff; - /* k = 4 */ - lo = Math.imul(al4, bl0); - mid = Math.imul(al4, bh0); - mid = (mid + Math.imul(ah4, bl0)) | 0; - hi = Math.imul(ah4, bh0); - lo = (lo + Math.imul(al3, bl1)) | 0; - mid = (mid + Math.imul(al3, bh1)) | 0; - mid = (mid + Math.imul(ah3, bl1)) | 0; - hi = (hi + Math.imul(ah3, bh1)) | 0; - lo = (lo + Math.imul(al2, bl2)) | 0; - mid = (mid + Math.imul(al2, bh2)) | 0; - mid = (mid + Math.imul(ah2, bl2)) | 0; - hi = (hi + Math.imul(ah2, bh2)) | 0; - lo = (lo + Math.imul(al1, bl3)) | 0; - mid = (mid + Math.imul(al1, bh3)) | 0; - mid = (mid + Math.imul(ah1, bl3)) | 0; - hi = (hi + Math.imul(ah1, bh3)) | 0; - lo = (lo + Math.imul(al0, bl4)) | 0; - mid = (mid + Math.imul(al0, bh4)) | 0; - mid = (mid + Math.imul(ah0, bl4)) | 0; - hi = (hi + Math.imul(ah0, bh4)) | 0; - var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; - w4 &= 0x3ffffff; - /* k = 5 */ - lo = Math.imul(al5, bl0); - mid = Math.imul(al5, bh0); - mid = (mid + Math.imul(ah5, bl0)) | 0; - hi = Math.imul(ah5, bh0); - lo = (lo + Math.imul(al4, bl1)) | 0; - mid = (mid + Math.imul(al4, bh1)) | 0; - mid = (mid + Math.imul(ah4, bl1)) | 0; - hi = (hi + Math.imul(ah4, bh1)) | 0; - lo = (lo + Math.imul(al3, bl2)) | 0; - mid = (mid + Math.imul(al3, bh2)) | 0; - mid = (mid + Math.imul(ah3, bl2)) | 0; - hi = (hi + Math.imul(ah3, bh2)) | 0; - lo = (lo + Math.imul(al2, bl3)) | 0; - mid = (mid + Math.imul(al2, bh3)) | 0; - mid = (mid + Math.imul(ah2, bl3)) | 0; - hi = (hi + Math.imul(ah2, bh3)) | 0; - lo = (lo + Math.imul(al1, bl4)) | 0; - mid = (mid + Math.imul(al1, bh4)) | 0; - mid = (mid + Math.imul(ah1, bl4)) | 0; - hi = (hi + Math.imul(ah1, bh4)) | 0; - lo = (lo + Math.imul(al0, bl5)) | 0; - mid = (mid + Math.imul(al0, bh5)) | 0; - mid = (mid + Math.imul(ah0, bl5)) | 0; - hi = (hi + Math.imul(ah0, bh5)) | 0; - var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; - w5 &= 0x3ffffff; - /* k = 6 */ - lo = Math.imul(al6, bl0); - mid = Math.imul(al6, bh0); - mid = (mid + Math.imul(ah6, bl0)) | 0; - hi = Math.imul(ah6, bh0); - lo = (lo + Math.imul(al5, bl1)) | 0; - mid = (mid + Math.imul(al5, bh1)) | 0; - mid = (mid + Math.imul(ah5, bl1)) | 0; - hi = (hi + Math.imul(ah5, bh1)) | 0; - lo = (lo + Math.imul(al4, bl2)) | 0; - mid = (mid + Math.imul(al4, bh2)) | 0; - mid = (mid + Math.imul(ah4, bl2)) | 0; - hi = (hi + Math.imul(ah4, bh2)) | 0; - lo = (lo + Math.imul(al3, bl3)) | 0; - mid = (mid + Math.imul(al3, bh3)) | 0; - mid = (mid + Math.imul(ah3, bl3)) | 0; - hi = (hi + Math.imul(ah3, bh3)) | 0; - lo = (lo + Math.imul(al2, bl4)) | 0; - mid = (mid + Math.imul(al2, bh4)) | 0; - mid = (mid + Math.imul(ah2, bl4)) | 0; - hi = (hi + Math.imul(ah2, bh4)) | 0; - lo = (lo + Math.imul(al1, bl5)) | 0; - mid = (mid + Math.imul(al1, bh5)) | 0; - mid = (mid + Math.imul(ah1, bl5)) | 0; - hi = (hi + Math.imul(ah1, bh5)) | 0; - lo = (lo + Math.imul(al0, bl6)) | 0; - mid = (mid + Math.imul(al0, bh6)) | 0; - mid = (mid + Math.imul(ah0, bl6)) | 0; - hi = (hi + Math.imul(ah0, bh6)) | 0; - var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; - w6 &= 0x3ffffff; - /* k = 7 */ - lo = Math.imul(al7, bl0); - mid = Math.imul(al7, bh0); - mid = (mid + Math.imul(ah7, bl0)) | 0; - hi = Math.imul(ah7, bh0); - lo = (lo + Math.imul(al6, bl1)) | 0; - mid = (mid + Math.imul(al6, bh1)) | 0; - mid = (mid + Math.imul(ah6, bl1)) | 0; - hi = (hi + Math.imul(ah6, bh1)) | 0; - lo = (lo + Math.imul(al5, bl2)) | 0; - mid = (mid + Math.imul(al5, bh2)) | 0; - mid = (mid + Math.imul(ah5, bl2)) | 0; - hi = (hi + Math.imul(ah5, bh2)) | 0; - lo = (lo + Math.imul(al4, bl3)) | 0; - mid = (mid + Math.imul(al4, bh3)) | 0; - mid = (mid + Math.imul(ah4, bl3)) | 0; - hi = (hi + Math.imul(ah4, bh3)) | 0; - lo = (lo + Math.imul(al3, bl4)) | 0; - mid = (mid + Math.imul(al3, bh4)) | 0; - mid = (mid + Math.imul(ah3, bl4)) | 0; - hi = (hi + Math.imul(ah3, bh4)) | 0; - lo = (lo + Math.imul(al2, bl5)) | 0; - mid = (mid + Math.imul(al2, bh5)) | 0; - mid = (mid + Math.imul(ah2, bl5)) | 0; - hi = (hi + Math.imul(ah2, bh5)) | 0; - lo = (lo + Math.imul(al1, bl6)) | 0; - mid = (mid + Math.imul(al1, bh6)) | 0; - mid = (mid + Math.imul(ah1, bl6)) | 0; - hi = (hi + Math.imul(ah1, bh6)) | 0; - lo = (lo + Math.imul(al0, bl7)) | 0; - mid = (mid + Math.imul(al0, bh7)) | 0; - mid = (mid + Math.imul(ah0, bl7)) | 0; - hi = (hi + Math.imul(ah0, bh7)) | 0; - var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; - w7 &= 0x3ffffff; - /* k = 8 */ - lo = Math.imul(al8, bl0); - mid = Math.imul(al8, bh0); - mid = (mid + Math.imul(ah8, bl0)) | 0; - hi = Math.imul(ah8, bh0); - lo = (lo + Math.imul(al7, bl1)) | 0; - mid = (mid + Math.imul(al7, bh1)) | 0; - mid = (mid + Math.imul(ah7, bl1)) | 0; - hi = (hi + Math.imul(ah7, bh1)) | 0; - lo = (lo + Math.imul(al6, bl2)) | 0; - mid = (mid + Math.imul(al6, bh2)) | 0; - mid = (mid + Math.imul(ah6, bl2)) | 0; - hi = (hi + Math.imul(ah6, bh2)) | 0; - lo = (lo + Math.imul(al5, bl3)) | 0; - mid = (mid + Math.imul(al5, bh3)) | 0; - mid = (mid + Math.imul(ah5, bl3)) | 0; - hi = (hi + Math.imul(ah5, bh3)) | 0; - lo = (lo + Math.imul(al4, bl4)) | 0; - mid = (mid + Math.imul(al4, bh4)) | 0; - mid = (mid + Math.imul(ah4, bl4)) | 0; - hi = (hi + Math.imul(ah4, bh4)) | 0; - lo = (lo + Math.imul(al3, bl5)) | 0; - mid = (mid + Math.imul(al3, bh5)) | 0; - mid = (mid + Math.imul(ah3, bl5)) | 0; - hi = (hi + Math.imul(ah3, bh5)) | 0; - lo = (lo + Math.imul(al2, bl6)) | 0; - mid = (mid + Math.imul(al2, bh6)) | 0; - mid = (mid + Math.imul(ah2, bl6)) | 0; - hi = (hi + Math.imul(ah2, bh6)) | 0; - lo = (lo + Math.imul(al1, bl7)) | 0; - mid = (mid + Math.imul(al1, bh7)) | 0; - mid = (mid + Math.imul(ah1, bl7)) | 0; - hi = (hi + Math.imul(ah1, bh7)) | 0; - lo = (lo + Math.imul(al0, bl8)) | 0; - mid = (mid + Math.imul(al0, bh8)) | 0; - mid = (mid + Math.imul(ah0, bl8)) | 0; - hi = (hi + Math.imul(ah0, bh8)) | 0; - var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; - w8 &= 0x3ffffff; - /* k = 9 */ - lo = Math.imul(al9, bl0); - mid = Math.imul(al9, bh0); - mid = (mid + Math.imul(ah9, bl0)) | 0; - hi = Math.imul(ah9, bh0); - lo = (lo + Math.imul(al8, bl1)) | 0; - mid = (mid + Math.imul(al8, bh1)) | 0; - mid = (mid + Math.imul(ah8, bl1)) | 0; - hi = (hi + Math.imul(ah8, bh1)) | 0; - lo = (lo + Math.imul(al7, bl2)) | 0; - mid = (mid + Math.imul(al7, bh2)) | 0; - mid = (mid + Math.imul(ah7, bl2)) | 0; - hi = (hi + Math.imul(ah7, bh2)) | 0; - lo = (lo + Math.imul(al6, bl3)) | 0; - mid = (mid + Math.imul(al6, bh3)) | 0; - mid = (mid + Math.imul(ah6, bl3)) | 0; - hi = (hi + Math.imul(ah6, bh3)) | 0; - lo = (lo + Math.imul(al5, bl4)) | 0; - mid = (mid + Math.imul(al5, bh4)) | 0; - mid = (mid + Math.imul(ah5, bl4)) | 0; - hi = (hi + Math.imul(ah5, bh4)) | 0; - lo = (lo + Math.imul(al4, bl5)) | 0; - mid = (mid + Math.imul(al4, bh5)) | 0; - mid = (mid + Math.imul(ah4, bl5)) | 0; - hi = (hi + Math.imul(ah4, bh5)) | 0; - lo = (lo + Math.imul(al3, bl6)) | 0; - mid = (mid + Math.imul(al3, bh6)) | 0; - mid = (mid + Math.imul(ah3, bl6)) | 0; - hi = (hi + Math.imul(ah3, bh6)) | 0; - lo = (lo + Math.imul(al2, bl7)) | 0; - mid = (mid + Math.imul(al2, bh7)) | 0; - mid = (mid + Math.imul(ah2, bl7)) | 0; - hi = (hi + Math.imul(ah2, bh7)) | 0; - lo = (lo + Math.imul(al1, bl8)) | 0; - mid = (mid + Math.imul(al1, bh8)) | 0; - mid = (mid + Math.imul(ah1, bl8)) | 0; - hi = (hi + Math.imul(ah1, bh8)) | 0; - lo = (lo + Math.imul(al0, bl9)) | 0; - mid = (mid + Math.imul(al0, bh9)) | 0; - mid = (mid + Math.imul(ah0, bl9)) | 0; - hi = (hi + Math.imul(ah0, bh9)) | 0; - var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; - w9 &= 0x3ffffff; - /* k = 10 */ - lo = Math.imul(al9, bl1); - mid = Math.imul(al9, bh1); - mid = (mid + Math.imul(ah9, bl1)) | 0; - hi = Math.imul(ah9, bh1); - lo = (lo + Math.imul(al8, bl2)) | 0; - mid = (mid + Math.imul(al8, bh2)) | 0; - mid = (mid + Math.imul(ah8, bl2)) | 0; - hi = (hi + Math.imul(ah8, bh2)) | 0; - lo = (lo + Math.imul(al7, bl3)) | 0; - mid = (mid + Math.imul(al7, bh3)) | 0; - mid = (mid + Math.imul(ah7, bl3)) | 0; - hi = (hi + Math.imul(ah7, bh3)) | 0; - lo = (lo + Math.imul(al6, bl4)) | 0; - mid = (mid + Math.imul(al6, bh4)) | 0; - mid = (mid + Math.imul(ah6, bl4)) | 0; - hi = (hi + Math.imul(ah6, bh4)) | 0; - lo = (lo + Math.imul(al5, bl5)) | 0; - mid = (mid + Math.imul(al5, bh5)) | 0; - mid = (mid + Math.imul(ah5, bl5)) | 0; - hi = (hi + Math.imul(ah5, bh5)) | 0; - lo = (lo + Math.imul(al4, bl6)) | 0; - mid = (mid + Math.imul(al4, bh6)) | 0; - mid = (mid + Math.imul(ah4, bl6)) | 0; - hi = (hi + Math.imul(ah4, bh6)) | 0; - lo = (lo + Math.imul(al3, bl7)) | 0; - mid = (mid + Math.imul(al3, bh7)) | 0; - mid = (mid + Math.imul(ah3, bl7)) | 0; - hi = (hi + Math.imul(ah3, bh7)) | 0; - lo = (lo + Math.imul(al2, bl8)) | 0; - mid = (mid + Math.imul(al2, bh8)) | 0; - mid = (mid + Math.imul(ah2, bl8)) | 0; - hi = (hi + Math.imul(ah2, bh8)) | 0; - lo = (lo + Math.imul(al1, bl9)) | 0; - mid = (mid + Math.imul(al1, bh9)) | 0; - mid = (mid + Math.imul(ah1, bl9)) | 0; - hi = (hi + Math.imul(ah1, bh9)) | 0; - var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; - w10 &= 0x3ffffff; - /* k = 11 */ - lo = Math.imul(al9, bl2); - mid = Math.imul(al9, bh2); - mid = (mid + Math.imul(ah9, bl2)) | 0; - hi = Math.imul(ah9, bh2); - lo = (lo + Math.imul(al8, bl3)) | 0; - mid = (mid + Math.imul(al8, bh3)) | 0; - mid = (mid + Math.imul(ah8, bl3)) | 0; - hi = (hi + Math.imul(ah8, bh3)) | 0; - lo = (lo + Math.imul(al7, bl4)) | 0; - mid = (mid + Math.imul(al7, bh4)) | 0; - mid = (mid + Math.imul(ah7, bl4)) | 0; - hi = (hi + Math.imul(ah7, bh4)) | 0; - lo = (lo + Math.imul(al6, bl5)) | 0; - mid = (mid + Math.imul(al6, bh5)) | 0; - mid = (mid + Math.imul(ah6, bl5)) | 0; - hi = (hi + Math.imul(ah6, bh5)) | 0; - lo = (lo + Math.imul(al5, bl6)) | 0; - mid = (mid + Math.imul(al5, bh6)) | 0; - mid = (mid + Math.imul(ah5, bl6)) | 0; - hi = (hi + Math.imul(ah5, bh6)) | 0; - lo = (lo + Math.imul(al4, bl7)) | 0; - mid = (mid + Math.imul(al4, bh7)) | 0; - mid = (mid + Math.imul(ah4, bl7)) | 0; - hi = (hi + Math.imul(ah4, bh7)) | 0; - lo = (lo + Math.imul(al3, bl8)) | 0; - mid = (mid + Math.imul(al3, bh8)) | 0; - mid = (mid + Math.imul(ah3, bl8)) | 0; - hi = (hi + Math.imul(ah3, bh8)) | 0; - lo = (lo + Math.imul(al2, bl9)) | 0; - mid = (mid + Math.imul(al2, bh9)) | 0; - mid = (mid + Math.imul(ah2, bl9)) | 0; - hi = (hi + Math.imul(ah2, bh9)) | 0; - var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; - w11 &= 0x3ffffff; - /* k = 12 */ - lo = Math.imul(al9, bl3); - mid = Math.imul(al9, bh3); - mid = (mid + Math.imul(ah9, bl3)) | 0; - hi = Math.imul(ah9, bh3); - lo = (lo + Math.imul(al8, bl4)) | 0; - mid = (mid + Math.imul(al8, bh4)) | 0; - mid = (mid + Math.imul(ah8, bl4)) | 0; - hi = (hi + Math.imul(ah8, bh4)) | 0; - lo = (lo + Math.imul(al7, bl5)) | 0; - mid = (mid + Math.imul(al7, bh5)) | 0; - mid = (mid + Math.imul(ah7, bl5)) | 0; - hi = (hi + Math.imul(ah7, bh5)) | 0; - lo = (lo + Math.imul(al6, bl6)) | 0; - mid = (mid + Math.imul(al6, bh6)) | 0; - mid = (mid + Math.imul(ah6, bl6)) | 0; - hi = (hi + Math.imul(ah6, bh6)) | 0; - lo = (lo + Math.imul(al5, bl7)) | 0; - mid = (mid + Math.imul(al5, bh7)) | 0; - mid = (mid + Math.imul(ah5, bl7)) | 0; - hi = (hi + Math.imul(ah5, bh7)) | 0; - lo = (lo + Math.imul(al4, bl8)) | 0; - mid = (mid + Math.imul(al4, bh8)) | 0; - mid = (mid + Math.imul(ah4, bl8)) | 0; - hi = (hi + Math.imul(ah4, bh8)) | 0; - lo = (lo + Math.imul(al3, bl9)) | 0; - mid = (mid + Math.imul(al3, bh9)) | 0; - mid = (mid + Math.imul(ah3, bl9)) | 0; - hi = (hi + Math.imul(ah3, bh9)) | 0; - var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; - w12 &= 0x3ffffff; - /* k = 13 */ - lo = Math.imul(al9, bl4); - mid = Math.imul(al9, bh4); - mid = (mid + Math.imul(ah9, bl4)) | 0; - hi = Math.imul(ah9, bh4); - lo = (lo + Math.imul(al8, bl5)) | 0; - mid = (mid + Math.imul(al8, bh5)) | 0; - mid = (mid + Math.imul(ah8, bl5)) | 0; - hi = (hi + Math.imul(ah8, bh5)) | 0; - lo = (lo + Math.imul(al7, bl6)) | 0; - mid = (mid + Math.imul(al7, bh6)) | 0; - mid = (mid + Math.imul(ah7, bl6)) | 0; - hi = (hi + Math.imul(ah7, bh6)) | 0; - lo = (lo + Math.imul(al6, bl7)) | 0; - mid = (mid + Math.imul(al6, bh7)) | 0; - mid = (mid + Math.imul(ah6, bl7)) | 0; - hi = (hi + Math.imul(ah6, bh7)) | 0; - lo = (lo + Math.imul(al5, bl8)) | 0; - mid = (mid + Math.imul(al5, bh8)) | 0; - mid = (mid + Math.imul(ah5, bl8)) | 0; - hi = (hi + Math.imul(ah5, bh8)) | 0; - lo = (lo + Math.imul(al4, bl9)) | 0; - mid = (mid + Math.imul(al4, bh9)) | 0; - mid = (mid + Math.imul(ah4, bl9)) | 0; - hi = (hi + Math.imul(ah4, bh9)) | 0; - var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; - w13 &= 0x3ffffff; - /* k = 14 */ - lo = Math.imul(al9, bl5); - mid = Math.imul(al9, bh5); - mid = (mid + Math.imul(ah9, bl5)) | 0; - hi = Math.imul(ah9, bh5); - lo = (lo + Math.imul(al8, bl6)) | 0; - mid = (mid + Math.imul(al8, bh6)) | 0; - mid = (mid + Math.imul(ah8, bl6)) | 0; - hi = (hi + Math.imul(ah8, bh6)) | 0; - lo = (lo + Math.imul(al7, bl7)) | 0; - mid = (mid + Math.imul(al7, bh7)) | 0; - mid = (mid + Math.imul(ah7, bl7)) | 0; - hi = (hi + Math.imul(ah7, bh7)) | 0; - lo = (lo + Math.imul(al6, bl8)) | 0; - mid = (mid + Math.imul(al6, bh8)) | 0; - mid = (mid + Math.imul(ah6, bl8)) | 0; - hi = (hi + Math.imul(ah6, bh8)) | 0; - lo = (lo + Math.imul(al5, bl9)) | 0; - mid = (mid + Math.imul(al5, bh9)) | 0; - mid = (mid + Math.imul(ah5, bl9)) | 0; - hi = (hi + Math.imul(ah5, bh9)) | 0; - var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; - w14 &= 0x3ffffff; - /* k = 15 */ - lo = Math.imul(al9, bl6); - mid = Math.imul(al9, bh6); - mid = (mid + Math.imul(ah9, bl6)) | 0; - hi = Math.imul(ah9, bh6); - lo = (lo + Math.imul(al8, bl7)) | 0; - mid = (mid + Math.imul(al8, bh7)) | 0; - mid = (mid + Math.imul(ah8, bl7)) | 0; - hi = (hi + Math.imul(ah8, bh7)) | 0; - lo = (lo + Math.imul(al7, bl8)) | 0; - mid = (mid + Math.imul(al7, bh8)) | 0; - mid = (mid + Math.imul(ah7, bl8)) | 0; - hi = (hi + Math.imul(ah7, bh8)) | 0; - lo = (lo + Math.imul(al6, bl9)) | 0; - mid = (mid + Math.imul(al6, bh9)) | 0; - mid = (mid + Math.imul(ah6, bl9)) | 0; - hi = (hi + Math.imul(ah6, bh9)) | 0; - var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; - w15 &= 0x3ffffff; - /* k = 16 */ - lo = Math.imul(al9, bl7); - mid = Math.imul(al9, bh7); - mid = (mid + Math.imul(ah9, bl7)) | 0; - hi = Math.imul(ah9, bh7); - lo = (lo + Math.imul(al8, bl8)) | 0; - mid = (mid + Math.imul(al8, bh8)) | 0; - mid = (mid + Math.imul(ah8, bl8)) | 0; - hi = (hi + Math.imul(ah8, bh8)) | 0; - lo = (lo + Math.imul(al7, bl9)) | 0; - mid = (mid + Math.imul(al7, bh9)) | 0; - mid = (mid + Math.imul(ah7, bl9)) | 0; - hi = (hi + Math.imul(ah7, bh9)) | 0; - var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; - w16 &= 0x3ffffff; - /* k = 17 */ - lo = Math.imul(al9, bl8); - mid = Math.imul(al9, bh8); - mid = (mid + Math.imul(ah9, bl8)) | 0; - hi = Math.imul(ah9, bh8); - lo = (lo + Math.imul(al8, bl9)) | 0; - mid = (mid + Math.imul(al8, bh9)) | 0; - mid = (mid + Math.imul(ah8, bl9)) | 0; - hi = (hi + Math.imul(ah8, bh9)) | 0; - var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; - w17 &= 0x3ffffff; - /* k = 18 */ - lo = Math.imul(al9, bl9); - mid = Math.imul(al9, bh9); - mid = (mid + Math.imul(ah9, bl9)) | 0; - hi = Math.imul(ah9, bh9); - var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; - c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; - w18 &= 0x3ffffff; - o[0] = w0; - o[1] = w1; - o[2] = w2; - o[3] = w3; - o[4] = w4; - o[5] = w5; - o[6] = w6; - o[7] = w7; - o[8] = w8; - o[9] = w9; - o[10] = w10; - o[11] = w11; - o[12] = w12; - o[13] = w13; - o[14] = w14; - o[15] = w15; - o[16] = w16; - o[17] = w17; - o[18] = w18; - if (c !== 0) { - o[19] = c; - out.length++; - } - return out; - }; - - // Polyfill comb - if (!Math.imul) { - comb10MulTo = smallMulTo; - } - - function bigMulTo (self, num, out) { - out.negative = num.negative ^ self.negative; - out.length = self.length + num.length; - - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = self.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; - - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; - - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; - } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } - - return out.strip(); - } - - function jumboMulTo (self, num, out) { - var fftm = new FFTM(); - return fftm.mulp(self, num, out); - } - - BN.prototype.mulTo = function mulTo (num, out) { - var res; - var len = this.length + num.length; - if (this.length === 10 && num.length === 10) { - res = comb10MulTo(this, num, out); - } else if (len < 63) { - res = smallMulTo(this, num, out); - } else if (len < 1024) { - res = bigMulTo(this, num, out); - } else { - res = jumboMulTo(this, num, out); - } - - return res; - }; - - // Cooley-Tukey algorithm for FFT - // slightly revisited to rely on looping instead of recursion - - function FFTM (x, y) { - this.x = x; - this.y = y; - } - - FFTM.prototype.makeRBT = function makeRBT (N) { - var t = new Array(N); - var l = BN.prototype._countBits(N) - 1; - for (var i = 0; i < N; i++) { - t[i] = this.revBin(i, l, N); - } - - return t; - }; - - // Returns binary-reversed representation of `x` - FFTM.prototype.revBin = function revBin (x, l, N) { - if (x === 0 || x === N - 1) return x; - - var rb = 0; - for (var i = 0; i < l; i++) { - rb |= (x & 1) << (l - i - 1); - x >>= 1; - } - - return rb; - }; - - // Performs "tweedling" phase, therefore 'emulating' - // behaviour of the recursive algorithm - FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { - for (var i = 0; i < N; i++) { - rtws[i] = rws[rbt[i]]; - itws[i] = iws[rbt[i]]; - } - }; - - FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { - this.permute(rbt, rws, iws, rtws, itws, N); - - for (var s = 1; s < N; s <<= 1) { - var l = s << 1; - - var rtwdf = Math.cos(2 * Math.PI / l); - var itwdf = Math.sin(2 * Math.PI / l); - - for (var p = 0; p < N; p += l) { - var rtwdf_ = rtwdf; - var itwdf_ = itwdf; - - for (var j = 0; j < s; j++) { - var re = rtws[p + j]; - var ie = itws[p + j]; - - var ro = rtws[p + j + s]; - var io = itws[p + j + s]; - - var rx = rtwdf_ * ro - itwdf_ * io; - - io = rtwdf_ * io + itwdf_ * ro; - ro = rx; - - rtws[p + j] = re + ro; - itws[p + j] = ie + io; - - rtws[p + j + s] = re - ro; - itws[p + j + s] = ie - io; - - /* jshint maxdepth : false */ - if (j !== l) { - rx = rtwdf * rtwdf_ - itwdf * itwdf_; - - itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; - rtwdf_ = rx; - } - } - } - } - }; - - FFTM.prototype.guessLen13b = function guessLen13b (n, m) { - var N = Math.max(m, n) | 1; - var odd = N & 1; - var i = 0; - for (N = N / 2 | 0; N; N = N >>> 1) { - i++; - } - - return 1 << i + 1 + odd; - }; - - FFTM.prototype.conjugate = function conjugate (rws, iws, N) { - if (N <= 1) return; - - for (var i = 0; i < N / 2; i++) { - var t = rws[i]; - - rws[i] = rws[N - i - 1]; - rws[N - i - 1] = t; - - t = iws[i]; - - iws[i] = -iws[N - i - 1]; - iws[N - i - 1] = -t; - } - }; - - FFTM.prototype.normalize13b = function normalize13b (ws, N) { - var carry = 0; - for (var i = 0; i < N / 2; i++) { - var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + - Math.round(ws[2 * i] / N) + - carry; - - ws[i] = w & 0x3ffffff; - - if (w < 0x4000000) { - carry = 0; - } else { - carry = w / 0x4000000 | 0; - } - } - - return ws; - }; - - FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { - var carry = 0; - for (var i = 0; i < len; i++) { - carry = carry + (ws[i] | 0); - - rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; - rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; - } - - // Pad with zeroes - for (i = 2 * len; i < N; ++i) { - rws[i] = 0; - } - - assert(carry === 0); - assert((carry & ~0x1fff) === 0); - }; - - FFTM.prototype.stub = function stub (N) { - var ph = new Array(N); - for (var i = 0; i < N; i++) { - ph[i] = 0; - } - - return ph; - }; - - FFTM.prototype.mulp = function mulp (x, y, out) { - var N = 2 * this.guessLen13b(x.length, y.length); - - var rbt = this.makeRBT(N); - - var _ = this.stub(N); - - var rws = new Array(N); - var rwst = new Array(N); - var iwst = new Array(N); - - var nrws = new Array(N); - var nrwst = new Array(N); - var niwst = new Array(N); - - var rmws = out.words; - rmws.length = N; - - this.convert13b(x.words, x.length, rws, N); - this.convert13b(y.words, y.length, nrws, N); - - this.transform(rws, _, rwst, iwst, N, rbt); - this.transform(nrws, _, nrwst, niwst, N, rbt); - - for (var i = 0; i < N; i++) { - var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; - iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; - rwst[i] = rx; - } - - this.conjugate(rwst, iwst, N); - this.transform(rwst, iwst, rmws, _, N, rbt); - this.conjugate(rmws, _, N); - this.normalize13b(rmws, N); - - out.negative = x.negative ^ y.negative; - out.length = x.length + y.length; - return out.strip(); - }; - - // Multiply `this` by `num` - BN.prototype.mul = function mul (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); - }; - - // Multiply employing FFT - BN.prototype.mulf = function mulf (num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return jumboMulTo(this, num, out); - }; - - // In-place Multiplication - BN.prototype.imul = function imul (num) { - return this.clone().mulTo(num, this); - }; - - BN.prototype.imuln = function imuln (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = (this.words[i] | 0) * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; - } - - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - - return this; - }; - - BN.prototype.muln = function muln (num) { - return this.clone().imuln(num); - }; - - // `this` * `this` - BN.prototype.sqr = function sqr () { - return this.mul(this); - }; - - // `this` * `this` in-place - BN.prototype.isqr = function isqr () { - return this.imul(this.clone()); - }; - - // Math.pow(`this`, `num`) - BN.prototype.pow = function pow (num) { - var w = toBitArray(num); - if (w.length === 0) return new BN(1); - - // Skip leading zeroes - var res = this; - for (var i = 0; i < w.length; i++, res = res.sqr()) { - if (w[i] !== 0) break; - } - - if (++i < w.length) { - for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { - if (w[i] === 0) continue; - - res = res.mul(q); - } - } - - return res; - }; - - // Shift-left in-place - BN.prototype.iushln = function iushln (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); - var i; - - if (r !== 0) { - var carry = 0; - - for (i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = ((this.words[i] | 0) - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); - } - - if (carry) { - this.words[i] = carry; - this.length++; - } - } - - if (s !== 0) { - for (i = this.length - 1; i >= 0; i--) { - this.words[i + s] = this.words[i]; - } - - for (i = 0; i < s; i++) { - this.words[i] = 0; - } - - this.length += s; - } - - return this.strip(); - }; - - BN.prototype.ishln = function ishln (bits) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushln(bits); - }; - - // Shift-right in-place - // NOTE: `hint` is a lowest bit before trailing zeroes - // NOTE: if `extended` is present - it will be filled with destroyed bits - BN.prototype.iushrn = function iushrn (bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) { - h = (hint - (hint % 26)) / 26; - } else { - h = 0; - } - - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; - - h -= s; - h = Math.max(0, h); - - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) { - maskedWords.words[i] = this.words[i]; - } - maskedWords.length = s; - } - - if (s === 0) { - // No-op, we should not move anything at all - } else if (this.length > s) { - this.length -= s; - for (i = 0; i < this.length; i++) { - this.words[i] = this.words[i + s]; - } - } else { - this.words[0] = 0; - this.length = 1; - } - - var carry = 0; - for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i] | 0; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; - } - - // Push carried bits as a mask - if (maskedWords && carry !== 0) { - maskedWords.words[maskedWords.length++] = carry; - } - - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; - } - - return this.strip(); - }; - - BN.prototype.ishrn = function ishrn (bits, hint, extended) { - // TODO(indutny): implement me - assert(this.negative === 0); - return this.iushrn(bits, hint, extended); - }; - - // Shift-left - BN.prototype.shln = function shln (bits) { - return this.clone().ishln(bits); - }; - - BN.prototype.ushln = function ushln (bits) { - return this.clone().iushln(bits); - }; - - // Shift-right - BN.prototype.shrn = function shrn (bits) { - return this.clone().ishrn(bits); - }; - - BN.prototype.ushrn = function ushrn (bits) { - return this.clone().iushrn(bits); - }; - - // Test if n bit is set - BN.prototype.testn = function testn (bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) return false; - - // Check bit and return - var w = this.words[s]; - - return !!(w & q); - }; - - // Return only lowers bits of number (in-place) - BN.prototype.imaskn = function imaskn (bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - - assert(this.negative === 0, 'imaskn works only with positive numbers'); - - if (this.length <= s) { - return this; - } - - if (r !== 0) { - s++; - } - this.length = Math.min(s, this.length); - - if (r !== 0) { - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - this.words[this.length - 1] &= mask; - } - - return this.strip(); - }; - - // Return only lowers bits of number - BN.prototype.maskn = function maskn (bits) { - return this.clone().imaskn(bits); - }; - - // Add plain number `num` to `this` - BN.prototype.iaddn = function iaddn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.isubn(-num); - - // Possible sign change - if (this.negative !== 0) { - if (this.length === 1 && (this.words[0] | 0) < num) { - this.words[0] = num - (this.words[0] | 0); - this.negative = 0; - return this; - } - - this.negative = 0; - this.isubn(num); - this.negative = 1; - return this; - } - - // Add without checks - return this._iaddn(num); - }; - - BN.prototype._iaddn = function _iaddn (num) { - this.words[0] += num; - - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) { - this.words[i + 1] = 1; - } else { - this.words[i + 1]++; - } - } - this.length = Math.max(this.length, i + 1); - - return this; - }; - - // Subtract plain number `num` from `this` - BN.prototype.isubn = function isubn (num) { - assert(typeof num === 'number'); - assert(num < 0x4000000); - if (num < 0) return this.iaddn(-num); - - if (this.negative !== 0) { - this.negative = 0; - this.iaddn(num); - this.negative = 1; - return this; - } - - this.words[0] -= num; - - if (this.length === 1 && this.words[0] < 0) { - this.words[0] = -this.words[0]; - this.negative = 1; - } else { - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; - } - } - - return this.strip(); - }; - - BN.prototype.addn = function addn (num) { - return this.clone().iaddn(num); - }; - - BN.prototype.subn = function subn (num) { - return this.clone().isubn(num); - }; - - BN.prototype.iabs = function iabs () { - this.negative = 0; - - return this; - }; - - BN.prototype.abs = function abs () { - return this.clone().iabs(); - }; - - BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { - var len = num.length + shift; - var i; - - this._expand(len); - - var w; - var carry = 0; - for (i = 0; i < num.length; i++) { - w = (this.words[i + shift] | 0) + carry; - var right = (num.words[i] | 0) * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - w = (this.words[i + shift] | 0) + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } - - if (carry === 0) return this.strip(); - - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (i = 0; i < this.length; i++) { - w = -(this.words[i] | 0) + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; - } - this.negative = 1; - - return this.strip(); - }; - - BN.prototype._wordDiv = function _wordDiv (num, mode) { - var shift = this.length - num.length; - - var a = this.clone(); - var b = num; - - // Normalize - var bhi = b.words[b.length - 1] | 0; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.ushln(shift); - a.iushln(shift); - bhi = b.words[b.length - 1] | 0; - } - - // Initialize quotient - var m = a.length - b.length; - var q; - - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) { - q.words[i] = 0; - } - } - - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (diff.negative === 0) { - a = diff; - if (q) { - q.words[m] = 1; - } - } - - for (var j = m - 1; j >= 0; j--) { - var qj = (a.words[b.length + j] | 0) * 0x4000000 + - (a.words[b.length + j - 1] | 0); - - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); - - a._ishlnsubmul(b, qj, j); - while (a.negative !== 0) { - qj--; - a.negative = 0; - a._ishlnsubmul(b, 1, j); - if (!a.isZero()) { - a.negative ^= 1; - } - } - if (q) { - q.words[j] = qj; - } - } - if (q) { - q.strip(); - } - a.strip(); - - // Denormalize - if (mode !== 'div' && shift !== 0) { - a.iushrn(shift); - } - - return { - div: q || null, - mod: a - }; - }; - - // NOTE: 1) `mode` can be set to `mod` to request mod only, - // to `div` to request div only, or be absent to - // request both div & mod - // 2) `positive` is true if unsigned mod is requested - BN.prototype.divmod = function divmod (num, mode, positive) { - assert(!num.isZero()); - - if (this.isZero()) { - return { - div: new BN(0), - mod: new BN(0) - }; - } - - var div, mod, res; - if (this.negative !== 0 && num.negative === 0) { - res = this.neg().divmod(num, mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.iadd(num); - } - } - - return { - div: div, - mod: mod - }; - } - - if (this.negative === 0 && num.negative !== 0) { - res = this.divmod(num.neg(), mode); - - if (mode !== 'mod') { - div = res.div.neg(); - } - - return { - div: div, - mod: res.mod - }; - } - - if ((this.negative & num.negative) !== 0) { - res = this.neg().divmod(num.neg(), mode); - - if (mode !== 'div') { - mod = res.mod.neg(); - if (positive && mod.negative !== 0) { - mod.isub(num); - } - } - - return { - div: res.div, - mod: mod - }; - } - - // Both numbers are positive at this point - - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) { - return { - div: new BN(0), - mod: this - }; - } - - // Very short reduction - if (num.length === 1) { - if (mode === 'div') { - return { - div: this.divn(num.words[0]), - mod: null - }; - } - - if (mode === 'mod') { - return { - div: null, - mod: new BN(this.modn(num.words[0])) - }; - } - - return { - div: this.divn(num.words[0]), - mod: new BN(this.modn(num.words[0])) - }; - } - - return this._wordDiv(num, mode); - }; - - // Find `this` / `num` - BN.prototype.div = function div (num) { - return this.divmod(num, 'div', false).div; - }; - - // Find `this` % `num` - BN.prototype.mod = function mod (num) { - return this.divmod(num, 'mod', false).mod; - }; - - BN.prototype.umod = function umod (num) { - return this.divmod(num, 'mod', true).mod; - }; - - // Find Round(`this` / `num`) - BN.prototype.divRound = function divRound (num) { - var dm = this.divmod(num); - - // Fast case - exact division - if (dm.mod.isZero()) return dm.div; - - var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; - - var half = num.ushrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); - - // Round down - if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; - - // Round up - return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); - }; - - BN.prototype.modn = function modn (num) { - assert(num <= 0x3ffffff); - var p = (1 << 26) % num; - - var acc = 0; - for (var i = this.length - 1; i >= 0; i--) { - acc = (p * acc + (this.words[i] | 0)) % num; - } - - return acc; - }; - - // In-place division by number - BN.prototype.idivn = function idivn (num) { - assert(num <= 0x3ffffff); - - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = (this.words[i] | 0) + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; - } - - return this.strip(); - }; - - BN.prototype.divn = function divn (num) { - return this.clone().idivn(num); - }; - - BN.prototype.egcd = function egcd (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var x = this; - var y = p.clone(); - - if (x.negative !== 0) { - x = x.umod(p); - } else { - x = x.clone(); - } - - // A * x + B * y = x - var A = new BN(1); - var B = new BN(0); - - // C * x + D * y = y - var C = new BN(0); - var D = new BN(1); - - var g = 0; - - while (x.isEven() && y.isEven()) { - x.iushrn(1); - y.iushrn(1); - ++g; - } - - var yp = y.clone(); - var xp = x.clone(); - - while (!x.isZero()) { - for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - x.iushrn(i); - while (i-- > 0) { - if (A.isOdd() || B.isOdd()) { - A.iadd(yp); - B.isub(xp); - } - - A.iushrn(1); - B.iushrn(1); - } - } - - for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - y.iushrn(j); - while (j-- > 0) { - if (C.isOdd() || D.isOdd()) { - C.iadd(yp); - D.isub(xp); - } - - C.iushrn(1); - D.iushrn(1); - } - } - - if (x.cmp(y) >= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); - } - } - - return { - a: C, - b: D, - gcd: y.iushln(g) - }; - }; - - // This is reduced incarnation of the binary EEA - // above, designated to invert members of the - // _prime_ fields F(p) at a maximal speed - BN.prototype._invmp = function _invmp (p) { - assert(p.negative === 0); - assert(!p.isZero()); - - var a = this; - var b = p.clone(); - - if (a.negative !== 0) { - a = a.umod(p); - } else { - a = a.clone(); - } - - var x1 = new BN(1); - var x2 = new BN(0); - - var delta = b.clone(); - - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); - if (i > 0) { - a.iushrn(i); - while (i-- > 0) { - if (x1.isOdd()) { - x1.iadd(delta); - } - - x1.iushrn(1); - } - } - - for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); - if (j > 0) { - b.iushrn(j); - while (j-- > 0) { - if (x2.isOdd()) { - x2.iadd(delta); - } - - x2.iushrn(1); - } - } - - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); - } else { - b.isub(a); - x2.isub(x1); - } - } - - var res; - if (a.cmpn(1) === 0) { - res = x1; - } else { - res = x2; - } - - if (res.cmpn(0) < 0) { - res.iadd(p); - } - - return res; - }; - - BN.prototype.gcd = function gcd (num) { - if (this.isZero()) return num.abs(); - if (num.isZero()) return this.abs(); - - var a = this.clone(); - var b = num.clone(); - a.negative = 0; - b.negative = 0; - - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.iushrn(1); - b.iushrn(1); - } - - do { - while (a.isEven()) { - a.iushrn(1); - } - while (b.isEven()) { - b.iushrn(1); - } - - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; - } - - a.isub(b); - } while (true); - - return b.iushln(shift); - }; - - // Invert number in the field F(num) - BN.prototype.invm = function invm (num) { - return this.egcd(num).a.umod(num); - }; - - BN.prototype.isEven = function isEven () { - return (this.words[0] & 1) === 0; - }; - - BN.prototype.isOdd = function isOdd () { - return (this.words[0] & 1) === 1; - }; - - // And first word and num - BN.prototype.andln = function andln (num) { - return this.words[0] & num; - }; - - // Increment at the bit position in-line - BN.prototype.bincn = function bincn (bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; - - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - this._expand(s + 1); - this.words[s] |= q; - return this; - } - - // Add bit and propagate, if needed - var carry = q; - for (var i = s; carry !== 0 && i < this.length; i++) { - var w = this.words[i] | 0; - w += carry; - carry = w >>> 26; - w &= 0x3ffffff; - this.words[i] = w; - } - if (carry !== 0) { - this.words[i] = carry; - this.length++; - } - return this; - }; - - BN.prototype.isZero = function isZero () { - return this.length === 1 && this.words[0] === 0; - }; - - BN.prototype.cmpn = function cmpn (num) { - var negative = num < 0; - - if (this.negative !== 0 && !negative) return -1; - if (this.negative === 0 && negative) return 1; - - this.strip(); - - var res; - if (this.length > 1) { - res = 1; - } else { - if (negative) { - num = -num; - } - - assert(num <= 0x3ffffff, 'Number is too big'); - - var w = this.words[0] | 0; - res = w === num ? 0 : w < num ? -1 : 1; - } - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Compare two numbers and return: - // 1 - if `this` > `num` - // 0 - if `this` == `num` - // -1 - if `this` < `num` - BN.prototype.cmp = function cmp (num) { - if (this.negative !== 0 && num.negative === 0) return -1; - if (this.negative === 0 && num.negative !== 0) return 1; - - var res = this.ucmp(num); - if (this.negative !== 0) return -res | 0; - return res; - }; - - // Unsigned comparison - BN.prototype.ucmp = function ucmp (num) { - // At this point both numbers have the same sign - if (this.length > num.length) return 1; - if (this.length < num.length) return -1; - - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i] | 0; - var b = num.words[i] | 0; - - if (a === b) continue; - if (a < b) { - res = -1; - } else if (a > b) { - res = 1; - } - break; - } - return res; - }; - - BN.prototype.gtn = function gtn (num) { - return this.cmpn(num) === 1; - }; - - BN.prototype.gt = function gt (num) { - return this.cmp(num) === 1; - }; - - BN.prototype.gten = function gten (num) { - return this.cmpn(num) >= 0; - }; - - BN.prototype.gte = function gte (num) { - return this.cmp(num) >= 0; - }; - - BN.prototype.ltn = function ltn (num) { - return this.cmpn(num) === -1; - }; - - BN.prototype.lt = function lt (num) { - return this.cmp(num) === -1; - }; - - BN.prototype.lten = function lten (num) { - return this.cmpn(num) <= 0; - }; - - BN.prototype.lte = function lte (num) { - return this.cmp(num) <= 0; - }; - - BN.prototype.eqn = function eqn (num) { - return this.cmpn(num) === 0; - }; - - BN.prototype.eq = function eq (num) { - return this.cmp(num) === 0; - }; - - // - // A reduce context, could be using montgomery or something better, depending - // on the `m` itself. - // - BN.red = function red (num) { - return new Red(num); - }; - - BN.prototype.toRed = function toRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(this.negative === 0, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); - }; - - BN.prototype.fromRed = function fromRed () { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); - }; - - BN.prototype._forceRed = function _forceRed (ctx) { - this.red = ctx; - return this; - }; - - BN.prototype.forceRed = function forceRed (ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); - }; - - BN.prototype.redAdd = function redAdd (num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); - }; - - BN.prototype.redIAdd = function redIAdd (num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); - }; - - BN.prototype.redSub = function redSub (num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); - }; - - BN.prototype.redISub = function redISub (num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); - }; - - BN.prototype.redShl = function redShl (num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); - }; - - BN.prototype.redMul = function redMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); - }; - - BN.prototype.redIMul = function redIMul (num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); - }; - - BN.prototype.redSqr = function redSqr () { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); - }; - - BN.prototype.redISqr = function redISqr () { - assert(this.red, 'redISqr works only with red numbers'); - this.red._verify1(this); - return this.red.isqr(this); - }; - - // Square root over p - BN.prototype.redSqrt = function redSqrt () { - assert(this.red, 'redSqrt works only with red numbers'); - this.red._verify1(this); - return this.red.sqrt(this); - }; - - BN.prototype.redInvm = function redInvm () { - assert(this.red, 'redInvm works only with red numbers'); - this.red._verify1(this); - return this.red.invm(this); - }; - - // Return negative clone of `this` % `red modulo` - BN.prototype.redNeg = function redNeg () { - assert(this.red, 'redNeg works only with red numbers'); - this.red._verify1(this); - return this.red.neg(this); - }; - - BN.prototype.redPow = function redPow (num) { - assert(this.red && !num.red, 'redPow(normalNum)'); - this.red._verify1(this); - return this.red.pow(this, num); - }; - - // Prime numbers with efficient reduction - var primes = { - k256: null, - p224: null, - p192: null, - p25519: null - }; - - // Pseudo-Mersenne prime - function MPrime (name, p) { - // P = 2 ^ N - K - this.name = name; - this.p = new BN(p, 16); - this.n = this.p.bitLength(); - this.k = new BN(1).iushln(this.n).isub(this.p); - - this.tmp = this._tmp(); - } - - MPrime.prototype._tmp = function _tmp () { - var tmp = new BN(null); - tmp.words = new Array(Math.ceil(this.n / 13)); - return tmp; - }; - - MPrime.prototype.ireduce = function ireduce (num) { - // Assumes that `num` is less than `P^2` - // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) - var r = num; - var rlen; - - do { - this.split(r, this.tmp); - r = this.imulK(r); - r = r.iadd(this.tmp); - rlen = r.bitLength(); - } while (rlen > this.n); - - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); - if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - r.strip(); - } - - return r; - }; - - MPrime.prototype.split = function split (input, out) { - input.iushrn(this.n, 0, out); - }; - - MPrime.prototype.imulK = function imulK (num) { - return num.imul(this.k); - }; - - function K256 () { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); - } - inherits(K256, MPrime); - - K256.prototype.split = function split (input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; - - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) { - output.words[i] = input.words[i]; - } - output.length = outLen; - - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; - } - - // Shift by 9 limbs - var prev = input.words[9]; - output.words[output.length++] = prev & mask; - - for (i = 10; i < input.length; i++) { - var next = input.words[i] | 0; - input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); - prev = next; - } - prev >>>= 22; - input.words[i - 10] = prev; - if (prev === 0 && input.length > 10) { - input.length -= 10; - } else { - input.length -= 9; - } - }; - - K256.prototype.imulK = function imulK (num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; - - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i] | 0; - lo += w * 0x3d1; - num.words[i] = lo & 0x3ffffff; - lo = w * 0x40 + ((lo / 0x4000000) | 0); - } - - // Fast length reduction - if (num.words[num.length - 1] === 0) { - num.length--; - if (num.words[num.length - 1] === 0) { - num.length--; - } - } - return num; - }; - - function P224 () { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); - } - inherits(P224, MPrime); - - function P192 () { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); - } - inherits(P192, MPrime); - - function P25519 () { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); - } - inherits(P25519, MPrime); - - P25519.prototype.imulK = function imulK (num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = (num.words[i] | 0) * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; - - num.words[i] = lo; - carry = hi; - } - if (carry !== 0) { - num.words[num.length++] = carry; - } - return num; - }; - - // Exported mostly for testing purposes, use plain name instead - BN._prime = function prime (name) { - // Cached version of prime - if (primes[name]) return primes[name]; - - var prime; - if (name === 'k256') { - prime = new K256(); - } else if (name === 'p224') { - prime = new P224(); - } else if (name === 'p192') { - prime = new P192(); - } else if (name === 'p25519') { - prime = new P25519(); - } else { - throw new Error('Unknown prime ' + name); - } - primes[name] = prime; - - return prime; - }; - - // - // Base reduction engine - // - function Red (m) { - if (typeof m === 'string') { - var prime = BN._prime(m); - this.m = prime.p; - this.prime = prime; - } else { - assert(m.gtn(1), 'modulus must be greater than 1'); - this.m = m; - this.prime = null; - } - } - - Red.prototype._verify1 = function _verify1 (a) { - assert(a.negative === 0, 'red works only with positives'); - assert(a.red, 'red works only with red numbers'); - }; - - Red.prototype._verify2 = function _verify2 (a, b) { - assert((a.negative | b.negative) === 0, 'red works only with positives'); - assert(a.red && a.red === b.red, - 'red works only with red numbers'); - }; - - Red.prototype.imod = function imod (a) { - if (this.prime) return this.prime.ireduce(a)._forceRed(this); - return a.umod(this.m)._forceRed(this); - }; - - Red.prototype.neg = function neg (a) { - if (a.isZero()) { - return a.clone(); - } - - return this.m.sub(a)._forceRed(this); - }; - - Red.prototype.add = function add (a, b) { - this._verify2(a, b); - - var res = a.add(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.iadd = function iadd (a, b) { - this._verify2(a, b); - - var res = a.iadd(b); - if (res.cmp(this.m) >= 0) { - res.isub(this.m); - } - return res; - }; - - Red.prototype.sub = function sub (a, b) { - this._verify2(a, b); - - var res = a.sub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res._forceRed(this); - }; - - Red.prototype.isub = function isub (a, b) { - this._verify2(a, b); - - var res = a.isub(b); - if (res.cmpn(0) < 0) { - res.iadd(this.m); - } - return res; - }; - - Red.prototype.shl = function shl (a, num) { - this._verify1(a); - return this.imod(a.ushln(num)); - }; - - Red.prototype.imul = function imul (a, b) { - this._verify2(a, b); - return this.imod(a.imul(b)); - }; - - Red.prototype.mul = function mul (a, b) { - this._verify2(a, b); - return this.imod(a.mul(b)); - }; - - Red.prototype.isqr = function isqr (a) { - return this.imul(a, a.clone()); - }; - - Red.prototype.sqr = function sqr (a) { - return this.mul(a, a); - }; - - Red.prototype.sqrt = function sqrt (a) { - if (a.isZero()) return a.clone(); - - var mod3 = this.m.andln(3); - assert(mod3 % 2 === 1); - - // Fast case - if (mod3 === 3) { - var pow = this.m.add(new BN(1)).iushrn(2); - return this.pow(a, pow); - } - - // Tonelli-Shanks algorithm (Totally unoptimized and slow) - // - // Find Q and S, that Q * 2 ^ S = (P - 1) - var q = this.m.subn(1); - var s = 0; - while (!q.isZero() && q.andln(1) === 0) { - s++; - q.iushrn(1); - } - assert(!q.isZero()); - - var one = new BN(1).toRed(this); - var nOne = one.redNeg(); - - // Find quadratic non-residue - // NOTE: Max is such because of generalized Riemann hypothesis. - var lpow = this.m.subn(1).iushrn(1); - var z = this.m.bitLength(); - z = new BN(2 * z * z).toRed(this); - - while (this.pow(z, lpow).cmp(nOne) !== 0) { - z.redIAdd(nOne); - } - - var c = this.pow(z, q); - var r = this.pow(a, q.addn(1).iushrn(1)); - var t = this.pow(a, q); - var m = s; - while (t.cmp(one) !== 0) { - var tmp = t; - for (var i = 0; tmp.cmp(one) !== 0; i++) { - tmp = tmp.redSqr(); - } - assert(i < m); - var b = this.pow(c, new BN(1).iushln(m - i - 1)); - - r = r.redMul(b); - c = b.redSqr(); - t = t.redMul(c); - m = i; - } - - return r; - }; - - Red.prototype.invm = function invm (a) { - var inv = a._invmp(this.m); - if (inv.negative !== 0) { - inv.negative = 0; - return this.imod(inv).redNeg(); - } else { - return this.imod(inv); - } - }; - - Red.prototype.pow = function pow (a, num) { - if (num.isZero()) return new BN(1).toRed(this); - if (num.cmpn(1) === 0) return a.clone(); - - var windowSize = 4; - var wnd = new Array(1 << windowSize); - wnd[0] = new BN(1).toRed(this); - wnd[1] = a; - for (var i = 2; i < wnd.length; i++) { - wnd[i] = this.mul(wnd[i - 1], a); - } - - var res = wnd[0]; - var current = 0; - var currentLen = 0; - var start = num.bitLength() % 26; - if (start === 0) { - start = 26; - } - - for (i = num.length - 1; i >= 0; i--) { - var word = num.words[i]; - for (var j = start - 1; j >= 0; j--) { - var bit = (word >> j) & 1; - if (res !== wnd[0]) { - res = this.sqr(res); - } - - if (bit === 0 && current === 0) { - currentLen = 0; - continue; - } - - current <<= 1; - current |= bit; - currentLen++; - if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; - - res = this.mul(res, wnd[current]); - currentLen = 0; - current = 0; - } - start = 26; - } - - return res; - }; - - Red.prototype.convertTo = function convertTo (num) { - var r = num.umod(this.m); - - return r === num ? r.clone() : r; - }; - - Red.prototype.convertFrom = function convertFrom (num) { - var res = num.clone(); - res.red = null; - return res; - }; - - // - // Montgomery method engine - // - - BN.mont = function mont (num) { - return new Mont(num); - }; - - function Mont (m) { - Red.call(this, m); - - this.shift = this.m.bitLength(); - if (this.shift % 26 !== 0) { - this.shift += 26 - (this.shift % 26); - } - - this.r = new BN(1).iushln(this.shift); - this.r2 = this.imod(this.r.sqr()); - this.rinv = this.r._invmp(this.m); - - this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); - this.minv = this.minv.umod(this.r); - this.minv = this.r.sub(this.minv); - } - inherits(Mont, Red); - - Mont.prototype.convertTo = function convertTo (num) { - return this.imod(num.ushln(this.shift)); - }; - - Mont.prototype.convertFrom = function convertFrom (num) { - var r = this.imod(num.mul(this.rinv)); - r.red = null; - return r; - }; - - Mont.prototype.imul = function imul (a, b) { - if (a.isZero() || b.isZero()) { - a.words[0] = 0; - a.length = 1; - return a; - } - - var t = a.imul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.mul = function mul (a, b) { - if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); - - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).iushrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) { - res = u.isub(this.m); - } else if (u.cmpn(0) < 0) { - res = u.iadd(this.m); - } - - return res._forceRed(this); - }; - - Mont.prototype.invm = function invm (a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); - }; -})(typeof module === 'undefined' || module, this); - -},{"buffer":103}],95:[function(_dereq_,module,exports){ -'use strict' - -module.exports = boundary - -function boundary (cells) { - var i, j, k - var n = cells.length - var sz = 0 - for (i = 0; i < n; ++i) { - sz += cells[i].length - } - var result = new Array(sz) - var ptr = 0 - for (i = 0; i < n; ++i) { - var c = cells[i] - var d = c.length - for (j = 0; j < d; ++j) { - var b = result[ptr++] = new Array(d - 1) - var p = 0 - for (k = 0; k < d; ++k) { - if (k === j) { - continue - } - b[p++] = c[k] - } - if (j & 1) { - var tmp = b[1] - b[1] = b[0] - b[0] = tmp - } - } - } - return result -} - -},{}],96:[function(_dereq_,module,exports){ -'use strict' - -module.exports = boxIntersectWrapper - -var pool = _dereq_('typedarray-pool') -var sweep = _dereq_('./lib/sweep') -var boxIntersectIter = _dereq_('./lib/intersect') - -function boxEmpty(d, box) { - for(var j=0; j>>1 - if(d <= 0) { - return - } - - var retval - - //Convert red boxes - var redList = pool.mallocDouble(2*d*n) - var redIds = pool.mallocInt32(n) - n = convertBoxes(red, d, redList, redIds) - - if(n > 0) { - if(d === 1 && full) { - //Special case: 1d complete - sweep.init(n) - retval = sweep.sweepComplete( - d, visit, - 0, n, redList, redIds, - 0, n, redList, redIds) - } else { - - //Convert blue boxes - var blueList = pool.mallocDouble(2*d*m) - var blueIds = pool.mallocInt32(m) - m = convertBoxes(blue, d, blueList, blueIds) - - if(m > 0) { - sweep.init(n+m) - - if(d === 1) { - //Special case: 1d bipartite - retval = sweep.sweepBipartite( - d, visit, - 0, n, redList, redIds, - 0, m, blueList, blueIds) - } else { - //General case: d>1 - retval = boxIntersectIter( - d, visit, full, - n, redList, redIds, - m, blueList, blueIds) - } - - pool.free(blueList) - pool.free(blueIds) - } - } - - pool.free(redList) - pool.free(redIds) - } - - return retval -} - - -var RESULT - -function appendItem(i,j) { - RESULT.push([i,j]) -} - -function intersectFullArray(x) { - RESULT = [] - boxIntersect(x, x, appendItem, true) - return RESULT -} - -function intersectBipartiteArray(x, y) { - RESULT = [] - boxIntersect(x, y, appendItem, false) - return RESULT -} - -//User-friendly wrapper, handle full input and no-visitor cases -function boxIntersectWrapper(arg0, arg1, arg2) { - var result - switch(arguments.length) { - case 1: - return intersectFullArray(arg0) - case 2: - if(typeof arg1 === 'function') { - return boxIntersect(arg0, arg0, arg1, true) - } else { - return intersectBipartiteArray(arg0, arg1) - } - case 3: - return boxIntersect(arg0, arg1, arg2, false) - default: - throw new Error('box-intersect: Invalid arguments') - } -} -},{"./lib/intersect":98,"./lib/sweep":102,"typedarray-pool":545}],97:[function(_dereq_,module,exports){ -'use strict' - -var DIMENSION = 'd' -var AXIS = 'ax' -var VISIT = 'vv' -var FLIP = 'fp' - -var ELEM_SIZE = 'es' - -var RED_START = 'rs' -var RED_END = 're' -var RED_BOXES = 'rb' -var RED_INDEX = 'ri' -var RED_PTR = 'rp' - -var BLUE_START = 'bs' -var BLUE_END = 'be' -var BLUE_BOXES = 'bb' -var BLUE_INDEX = 'bi' -var BLUE_PTR = 'bp' - -var RETVAL = 'rv' - -var INNER_LABEL = 'Q' - -var ARGS = [ - DIMENSION, - AXIS, - VISIT, - RED_START, - RED_END, - RED_BOXES, - RED_INDEX, - BLUE_START, - BLUE_END, - BLUE_BOXES, - BLUE_INDEX -] - -function generateBruteForce(redMajor, flip, full) { - var funcName = 'bruteForce' + - (redMajor ? 'Red' : 'Blue') + - (flip ? 'Flip' : '') + - (full ? 'Full' : '') - - var code = ['function ', funcName, '(', ARGS.join(), '){', - 'var ', ELEM_SIZE, '=2*', DIMENSION, ';'] - - var redLoop = - 'for(var i=' + RED_START + ',' + RED_PTR + '=' + ELEM_SIZE + '*' + RED_START + ';' + - 'i<' + RED_END +';' + - '++i,' + RED_PTR + '+=' + ELEM_SIZE + '){' + - 'var x0=' + RED_BOXES + '[' + AXIS + '+' + RED_PTR + '],' + - 'x1=' + RED_BOXES + '[' + AXIS + '+' + RED_PTR + '+' + DIMENSION + '],' + - 'xi=' + RED_INDEX + '[i];' - - var blueLoop = - 'for(var j=' + BLUE_START + ',' + BLUE_PTR + '=' + ELEM_SIZE + '*' + BLUE_START + ';' + - 'j<' + BLUE_END + ';' + - '++j,' + BLUE_PTR + '+=' + ELEM_SIZE + '){' + - 'var y0=' + BLUE_BOXES + '[' + AXIS + '+' + BLUE_PTR + '],' + - (full ? 'y1=' + BLUE_BOXES + '[' + AXIS + '+' + BLUE_PTR + '+' + DIMENSION + '],' : '') + - 'yi=' + BLUE_INDEX + '[j];' - - if(redMajor) { - code.push(redLoop, INNER_LABEL, ':', blueLoop) - } else { - code.push(blueLoop, INNER_LABEL, ':', redLoop) - } - - if(full) { - code.push('if(y1' + - BLUE_END + '-' + BLUE_START + '){') - - if(full) { - invoke(true, false) - code.push('}else{') - invoke(false, false) - } else { - code.push('if(' + FLIP + '){') - invoke(true, true) - code.push('}else{') - invoke(true, false) - code.push('}}else{if(' + FLIP + '){') - invoke(false, true) - code.push('}else{') - invoke(false, false) - code.push('}') - } - code.push('}}return ' + funcName) - - var codeStr = prefix.join('') + code.join('') - var proc = new Function(codeStr) - return proc() -} - - -exports.partial = bruteForcePlanner(false) -exports.full = bruteForcePlanner(true) -},{}],98:[function(_dereq_,module,exports){ -'use strict' - -module.exports = boxIntersectIter - -var pool = _dereq_('typedarray-pool') -var bits = _dereq_('bit-twiddle') -var bruteForce = _dereq_('./brute') -var bruteForcePartial = bruteForce.partial -var bruteForceFull = bruteForce.full -var sweep = _dereq_('./sweep') -var findMedian = _dereq_('./median') -var genPartition = _dereq_('./partition') - -//Twiddle parameters -var BRUTE_FORCE_CUTOFF = 128 //Cut off for brute force search -var SCAN_CUTOFF = (1<<22) //Cut off for two way scan -var SCAN_COMPLETE_CUTOFF = (1<<22) - -//Partition functions -var partitionInteriorContainsInterval = genPartition( - '!(lo>=p0)&&!(p1>=hi)', - ['p0', 'p1']) - -var partitionStartEqual = genPartition( - 'lo===p0', - ['p0']) - -var partitionStartLessThan = genPartition( - 'lo 0) { - top -= 1 - - var iptr = top * IFRAME_SIZE - var axis = BOX_ISTACK[iptr] - var redStart = BOX_ISTACK[iptr+1] - var redEnd = BOX_ISTACK[iptr+2] - var blueStart = BOX_ISTACK[iptr+3] - var blueEnd = BOX_ISTACK[iptr+4] - var state = BOX_ISTACK[iptr+5] - - var dptr = top * DFRAME_SIZE - var lo = BOX_DSTACK[dptr] - var hi = BOX_DSTACK[dptr+1] - - //Unpack state info - var flip = (state & 1) - var full = !!(state & 16) - - //Unpack indices - var red = xBoxes - var redIndex = xIndex - var blue = yBoxes - var blueIndex = yIndex - if(flip) { - red = yBoxes - redIndex = yIndex - blue = xBoxes - blueIndex = xIndex - } - - if(state & 2) { - redEnd = partitionStartLessThan( - d, axis, - redStart, redEnd, red, redIndex, - hi) - if(redStart >= redEnd) { - continue - } - } - if(state & 4) { - redStart = partitionEndLessThanEqual( - d, axis, - redStart, redEnd, red, redIndex, - lo) - if(redStart >= redEnd) { - continue - } - } - - var redCount = redEnd - redStart - var blueCount = blueEnd - blueStart - - if(full) { - if(d * redCount * (redCount + blueCount) < SCAN_COMPLETE_CUTOFF) { - retval = sweep.scanComplete( - d, axis, visit, - redStart, redEnd, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - if(retval !== void 0) { - return retval - } - continue - } - } else { - if(d * Math.min(redCount, blueCount) < BRUTE_FORCE_CUTOFF) { - //If input small, then use brute force - retval = bruteForcePartial( - d, axis, visit, flip, - redStart, redEnd, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - if(retval !== void 0) { - return retval - } - continue - } else if(d * redCount * blueCount < SCAN_CUTOFF) { - //If input medium sized, then use sweep and prune - retval = sweep.scanBipartite( - d, axis, visit, flip, - redStart, redEnd, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - if(retval !== void 0) { - return retval - } - continue - } - } - - //First, find all red intervals whose interior contains (lo,hi) - var red0 = partitionInteriorContainsInterval( - d, axis, - redStart, redEnd, red, redIndex, - lo, hi) - - //Lower dimensional case - if(redStart < red0) { - - if(d * (red0 - redStart) < BRUTE_FORCE_CUTOFF) { - //Special case for small inputs: use brute force - retval = bruteForceFull( - d, axis+1, visit, - redStart, red0, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - if(retval !== void 0) { - return retval - } - } else if(axis === d-2) { - if(flip) { - retval = sweep.sweepBipartite( - d, visit, - blueStart, blueEnd, blue, blueIndex, - redStart, red0, red, redIndex) - } else { - retval = sweep.sweepBipartite( - d, visit, - redStart, red0, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - } - if(retval !== void 0) { - return retval - } - } else { - iterPush(top++, - axis+1, - redStart, red0, - blueStart, blueEnd, - flip, - -Infinity, Infinity) - iterPush(top++, - axis+1, - blueStart, blueEnd, - redStart, red0, - flip^1, - -Infinity, Infinity) - } - } - - //Divide and conquer phase - if(red0 < redEnd) { - - //Cut blue into 3 parts: - // - // Points < mid point - // Points = mid point - // Points > mid point - // - var blue0 = findMedian( - d, axis, - blueStart, blueEnd, blue, blueIndex) - var mid = blue[elemSize * blue0 + axis] - var blue1 = partitionStartEqual( - d, axis, - blue0, blueEnd, blue, blueIndex, - mid) - - //Right case - if(blue1 < blueEnd) { - iterPush(top++, - axis, - red0, redEnd, - blue1, blueEnd, - (flip|4) + (full ? 16 : 0), - mid, hi) - } - - //Left case - if(blueStart < blue0) { - iterPush(top++, - axis, - red0, redEnd, - blueStart, blue0, - (flip|2) + (full ? 16 : 0), - lo, mid) - } - - //Center case (the hard part) - if(blue0 + 1 === blue1) { - //Optimization: Range with exactly 1 point, use a brute force scan - if(full) { - retval = onePointFull( - d, axis, visit, - red0, redEnd, red, redIndex, - blue0, blue, blueIndex[blue0]) - } else { - retval = onePointPartial( - d, axis, visit, flip, - red0, redEnd, red, redIndex, - blue0, blue, blueIndex[blue0]) - } - if(retval !== void 0) { - return retval - } - } else if(blue0 < blue1) { - var red1 - if(full) { - //If full intersection, need to handle special case - red1 = partitionContainsPoint( - d, axis, - red0, redEnd, red, redIndex, - mid) - if(red0 < red1) { - var redX = partitionStartEqual( - d, axis, - red0, red1, red, redIndex, - mid) - if(axis === d-2) { - //Degenerate sweep intersection: - // [red0, redX] with [blue0, blue1] - if(red0 < redX) { - retval = sweep.sweepComplete( - d, visit, - red0, redX, red, redIndex, - blue0, blue1, blue, blueIndex) - if(retval !== void 0) { - return retval - } - } - - //Normal sweep intersection: - // [redX, red1] with [blue0, blue1] - if(redX < red1) { - retval = sweep.sweepBipartite( - d, visit, - redX, red1, red, redIndex, - blue0, blue1, blue, blueIndex) - if(retval !== void 0) { - return retval - } - } - } else { - if(red0 < redX) { - iterPush(top++, - axis+1, - red0, redX, - blue0, blue1, - 16, - -Infinity, Infinity) - } - if(redX < red1) { - iterPush(top++, - axis+1, - redX, red1, - blue0, blue1, - 0, - -Infinity, Infinity) - iterPush(top++, - axis+1, - blue0, blue1, - redX, red1, - 1, - -Infinity, Infinity) - } - } - } - } else { - if(flip) { - red1 = partitionContainsPointProper( - d, axis, - red0, redEnd, red, redIndex, - mid) - } else { - red1 = partitionContainsPoint( - d, axis, - red0, redEnd, red, redIndex, - mid) - } - if(red0 < red1) { - if(axis === d-2) { - if(flip) { - retval = sweep.sweepBipartite( - d, visit, - blue0, blue1, blue, blueIndex, - red0, red1, red, redIndex) - } else { - retval = sweep.sweepBipartite( - d, visit, - red0, red1, red, redIndex, - blue0, blue1, blue, blueIndex) - } - } else { - iterPush(top++, - axis+1, - red0, red1, - blue0, blue1, - flip, - -Infinity, Infinity) - iterPush(top++, - axis+1, - blue0, blue1, - red0, red1, - flip^1, - -Infinity, Infinity) - } - } - } - } - } - } -} -},{"./brute":97,"./median":99,"./partition":100,"./sweep":102,"bit-twiddle":92,"typedarray-pool":545}],99:[function(_dereq_,module,exports){ -'use strict' - -module.exports = findMedian - -var genPartition = _dereq_('./partition') - -var partitionStartLessThan = genPartition('lostart && boxes[ptr+axis] > x; - --j, ptr-=elemSize) { - //Swap - var aPtr = ptr - var bPtr = ptr+elemSize - for(var k=0; k>> 1) - var elemSize = 2*d - var pivot = mid - var value = boxes[elemSize*mid+axis] - - while(lo < hi) { - if(hi - lo < PARTITION_THRESHOLD) { - insertionSort(d, axis, lo, hi, boxes, ids) - value = boxes[elemSize*mid+axis] - break - } - - //Select pivot using median-of-3 - var count = hi - lo - var pivot0 = (Math.random()*count+lo)|0 - var value0 = boxes[elemSize*pivot0 + axis] - var pivot1 = (Math.random()*count+lo)|0 - var value1 = boxes[elemSize*pivot1 + axis] - var pivot2 = (Math.random()*count+lo)|0 - var value2 = boxes[elemSize*pivot2 + axis] - if(value0 <= value1) { - if(value2 >= value1) { - pivot = pivot1 - value = value1 - } else if(value0 >= value2) { - pivot = pivot0 - value = value0 - } else { - pivot = pivot2 - value = value2 - } - } else { - if(value1 >= value2) { - pivot = pivot1 - value = value1 - } else if(value2 >= value0) { - pivot = pivot0 - value = value0 - } else { - pivot = pivot2 - value = value2 - } - } - - //Swap pivot to end of array - var aPtr = elemSize * (hi-1) - var bPtr = elemSize * pivot - for(var i=0; i= 0) { - reads.push('lo=e[k+n]') - } - if(predicate.indexOf('hi') >= 0) { - reads.push('hi=e[k+o]') - } - fargs.push( - code.replace('_', reads.join()) - .replace('$', predicate)) - return Function.apply(void 0, fargs) -} -},{}],101:[function(_dereq_,module,exports){ -'use strict'; - -//This code is extracted from ndarray-sort -//It is inlined here as a temporary workaround - -module.exports = wrapper; - -var INSERT_SORT_CUTOFF = 32 - -function wrapper(data, n0) { - if (n0 <= 4*INSERT_SORT_CUTOFF) { - insertionSort(0, n0 - 1, data); - } else { - quickSort(0, n0 - 1, data); - } -} - -function insertionSort(left, right, data) { - var ptr = 2*(left+1) - for(var i=left+1; i<=right; ++i) { - var a = data[ptr++] - var b = data[ptr++] - var j = i - var jptr = ptr-2 - while(j-- > left) { - var x = data[jptr-2] - var y = data[jptr-1] - if(x < a) { - break - } else if(x === a && y < b) { - break - } - data[jptr] = x - data[jptr+1] = y - jptr -= 2 - } - data[jptr] = a - data[jptr+1] = b - } -} - -function swap(i, j, data) { - i *= 2 - j *= 2 - var x = data[i] - var y = data[i+1] - data[i] = data[j] - data[i+1] = data[j+1] - data[j] = x - data[j+1] = y -} - -function move(i, j, data) { - i *= 2 - j *= 2 - data[i] = data[j] - data[i+1] = data[j+1] -} - -function rotate(i, j, k, data) { - i *= 2 - j *= 2 - k *= 2 - var x = data[i] - var y = data[i+1] - data[i] = data[j] - data[i+1] = data[j+1] - data[j] = data[k] - data[j+1] = data[k+1] - data[k] = x - data[k+1] = y -} - -function shufflePivot(i, j, px, py, data) { - i *= 2 - j *= 2 - data[i] = data[j] - data[j] = px - data[i+1] = data[j+1] - data[j+1] = py -} - -function compare(i, j, data) { - i *= 2 - j *= 2 - var x = data[i], - y = data[j] - if(x < y) { - return false - } else if(x === y) { - return data[i+1] > data[j+1] - } - return true -} - -function comparePivot(i, y, b, data) { - i *= 2 - var x = data[i] - if(x < y) { - return true - } else if(x === y) { - return data[i+1] < b - } - return false -} - -function quickSort(left, right, data) { - var sixth = (right - left + 1) / 6 | 0, - index1 = left + sixth, - index5 = right - sixth, - index3 = left + right >> 1, - index2 = index3 - sixth, - index4 = index3 + sixth, - el1 = index1, - el2 = index2, - el3 = index3, - el4 = index4, - el5 = index5, - less = left + 1, - great = right - 1, - tmp = 0 - if(compare(el1, el2, data)) { - tmp = el1 - el1 = el2 - el2 = tmp - } - if(compare(el4, el5, data)) { - tmp = el4 - el4 = el5 - el5 = tmp - } - if(compare(el1, el3, data)) { - tmp = el1 - el1 = el3 - el3 = tmp - } - if(compare(el2, el3, data)) { - tmp = el2 - el2 = el3 - el3 = tmp - } - if(compare(el1, el4, data)) { - tmp = el1 - el1 = el4 - el4 = tmp - } - if(compare(el3, el4, data)) { - tmp = el3 - el3 = el4 - el4 = tmp - } - if(compare(el2, el5, data)) { - tmp = el2 - el2 = el5 - el5 = tmp - } - if(compare(el2, el3, data)) { - tmp = el2 - el2 = el3 - el3 = tmp - } - if(compare(el4, el5, data)) { - tmp = el4 - el4 = el5 - el5 = tmp - } - - var pivot1X = data[2*el2] - var pivot1Y = data[2*el2+1] - var pivot2X = data[2*el4] - var pivot2Y = data[2*el4+1] - - var ptr0 = 2 * el1; - var ptr2 = 2 * el3; - var ptr4 = 2 * el5; - var ptr5 = 2 * index1; - var ptr6 = 2 * index3; - var ptr7 = 2 * index5; - for (var i1 = 0; i1 < 2; ++i1) { - var x = data[ptr0+i1]; - var y = data[ptr2+i1]; - var z = data[ptr4+i1]; - data[ptr5+i1] = x; - data[ptr6+i1] = y; - data[ptr7+i1] = z; - } - - move(index2, left, data) - move(index4, right, data) - for (var k = less; k <= great; ++k) { - if (comparePivot(k, pivot1X, pivot1Y, data)) { - if (k !== less) { - swap(k, less, data) - } - ++less; - } else { - if (!comparePivot(k, pivot2X, pivot2Y, data)) { - while (true) { - if (!comparePivot(great, pivot2X, pivot2Y, data)) { - if (--great < k) { - break; - } - continue; - } else { - if (comparePivot(great, pivot1X, pivot1Y, data)) { - rotate(k, less, great, data) - ++less; - --great; - } else { - swap(k, great, data) - --great; - } - break; - } - } - } - } - } - shufflePivot(left, less-1, pivot1X, pivot1Y, data) - shufflePivot(right, great+1, pivot2X, pivot2Y, data) - if (less - 2 - left <= INSERT_SORT_CUTOFF) { - insertionSort(left, less - 2, data); - } else { - quickSort(left, less - 2, data); - } - if (right - (great + 2) <= INSERT_SORT_CUTOFF) { - insertionSort(great + 2, right, data); - } else { - quickSort(great + 2, right, data); - } - if (great - less <= INSERT_SORT_CUTOFF) { - insertionSort(less, great, data); - } else { - quickSort(less, great, data); - } -} -},{}],102:[function(_dereq_,module,exports){ -'use strict' - -module.exports = { - init: sqInit, - sweepBipartite: sweepBipartite, - sweepComplete: sweepComplete, - scanBipartite: scanBipartite, - scanComplete: scanComplete -} - -var pool = _dereq_('typedarray-pool') -var bits = _dereq_('bit-twiddle') -var isort = _dereq_('./sort') - -//Flag for blue -var BLUE_FLAG = (1<<28) - -//1D sweep event queue stuff (use pool to save space) -var INIT_CAPACITY = 1024 -var RED_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY) -var RED_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY) -var BLUE_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY) -var BLUE_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY) -var COMMON_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY) -var COMMON_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY) -var SWEEP_EVENTS = pool.mallocDouble(INIT_CAPACITY * 8) - -//Reserves memory for the 1D sweep data structures -function sqInit(count) { - var rcount = bits.nextPow2(count) - if(RED_SWEEP_QUEUE.length < rcount) { - pool.free(RED_SWEEP_QUEUE) - RED_SWEEP_QUEUE = pool.mallocInt32(rcount) - } - if(RED_SWEEP_INDEX.length < rcount) { - pool.free(RED_SWEEP_INDEX) - RED_SWEEP_INDEX = pool.mallocInt32(rcount) - } - if(BLUE_SWEEP_QUEUE.length < rcount) { - pool.free(BLUE_SWEEP_QUEUE) - BLUE_SWEEP_QUEUE = pool.mallocInt32(rcount) - } - if(BLUE_SWEEP_INDEX.length < rcount) { - pool.free(BLUE_SWEEP_INDEX) - BLUE_SWEEP_INDEX = pool.mallocInt32(rcount) - } - if(COMMON_SWEEP_QUEUE.length < rcount) { - pool.free(COMMON_SWEEP_QUEUE) - COMMON_SWEEP_QUEUE = pool.mallocInt32(rcount) - } - if(COMMON_SWEEP_INDEX.length < rcount) { - pool.free(COMMON_SWEEP_INDEX) - COMMON_SWEEP_INDEX = pool.mallocInt32(rcount) - } - var eventLength = 8 * rcount - if(SWEEP_EVENTS.length < eventLength) { - pool.free(SWEEP_EVENTS) - SWEEP_EVENTS = pool.mallocDouble(eventLength) - } -} - -//Remove an item from the active queue in O(1) -function sqPop(queue, index, count, item) { - var idx = index[item] - var top = queue[count-1] - queue[idx] = top - index[top] = idx -} - -//Insert an item into the active queue in O(1) -function sqPush(queue, index, count, item) { - queue[count] = item - index[item] = count -} - -//Recursion base case: use 1D sweep algorithm -function sweepBipartite( - d, visit, - redStart, redEnd, red, redIndex, - blueStart, blueEnd, blue, blueIndex) { - - //store events as pairs [coordinate, idx] - // - // red create: -(idx+1) - // red destroy: idx - // blue create: -(idx+BLUE_FLAG) - // blue destroy: idx+BLUE_FLAG - // - var ptr = 0 - var elemSize = 2*d - var istart = d-1 - var iend = elemSize-1 - - for(var i=redStart; iright - var n = ptr >>> 1 - isort(SWEEP_EVENTS, n) - - var redActive = 0 - var blueActive = 0 - for(var i=0; i= BLUE_FLAG) { - //blue destroy event - e = (e-BLUE_FLAG)|0 - sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, e) - } else if(e >= 0) { - //red destroy event - sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, e) - } else if(e <= -BLUE_FLAG) { - //blue create event - e = (-e-BLUE_FLAG)|0 - for(var j=0; jright - var n = ptr >>> 1 - isort(SWEEP_EVENTS, n) - - var redActive = 0 - var blueActive = 0 - var commonActive = 0 - for(var i=0; i>1) === (SWEEP_EVENTS[2*i+3]>>1)) { - color = 2 - i += 1 - } - - if(e < 0) { - //Create event - var id = -(e>>1) - 1 - - //Intersect with common - for(var j=0; j>1) - 1 - if(color === 0) { - //Red - sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, id) - } else if(color === 1) { - //Blue - sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, id) - } else if(color === 2) { - //Both - sqPop(COMMON_SWEEP_QUEUE, COMMON_SWEEP_INDEX, commonActive--, id) - } - } - } -} - -//Sweep and prune/scanline algorithm: -// Scan along axis, detect intersections -// Brute force all boxes along axis -function scanBipartite( - d, axis, visit, flip, - redStart, redEnd, red, redIndex, - blueStart, blueEnd, blue, blueIndex) { - - var ptr = 0 - var elemSize = 2*d - var istart = axis - var iend = axis+d - - var redShift = 1 - var blueShift = 1 - if(flip) { - blueShift = BLUE_FLAG - } else { - redShift = BLUE_FLAG - } - - for(var i=redStart; iright - var n = ptr >>> 1 - isort(SWEEP_EVENTS, n) - - var redActive = 0 - for(var i=0; i= BLUE_FLAG) { - isRed = !flip - idx -= BLUE_FLAG - } else { - isRed = !!flip - idx -= 1 - } - if(isRed) { - sqPush(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive++, idx) - } else { - var blueId = blueIndex[idx] - var bluePtr = elemSize * idx - - var b0 = blue[bluePtr+axis+1] - var b1 = blue[bluePtr+axis+1+d] - -red_loop: - for(var j=0; jright - var n = ptr >>> 1 - isort(SWEEP_EVENTS, n) - - var redActive = 0 - for(var i=0; i= BLUE_FLAG) { - RED_SWEEP_QUEUE[redActive++] = idx - BLUE_FLAG - } else { - idx -= 1 - var blueId = blueIndex[idx] - var bluePtr = elemSize * idx - - var b0 = blue[bluePtr+axis+1] - var b1 = blue[bluePtr+axis+1+d] - -red_loop: - for(var j=0; j=0; --j) { - if(RED_SWEEP_QUEUE[j] === idx) { - for(var k=j+1; k 1) - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - // At least give some kind of context to the user - var err = new Error('Unhandled "error" event. (' + er + ')'); - err.context = er; - throw err; - } - return false; - } - - handler = events[type]; - - if (!handler) - return false; - - var isFn = typeof handler === 'function'; - len = arguments.length; - switch (len) { - // fast cases - case 1: - emitNone(handler, isFn, this); - break; - case 2: - emitOne(handler, isFn, this, arguments[1]); - break; - case 3: - emitTwo(handler, isFn, this, arguments[1], arguments[2]); - break; - case 4: - emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); - break; - // slower - default: - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - emitMany(handler, isFn, this, args); - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = target._events; - if (!events) { - events = target._events = objectCreate(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener) { - target.emit('newListener', type, - listener.listener ? listener.listener : listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (!existing) { - // Optimize the case of one listener. Don't need the extra array object. - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - } else { - // If we've already got an array, just append. - if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - } - - // Check for listener leak - if (!existing.warned) { - m = $getMaxListeners(target); - if (m && m > 0 && existing.length > m) { - existing.warned = true; - var w = new Error('Possible EventEmitter memory leak detected. ' + - existing.length + ' "' + String(type) + '" listeners ' + - 'added. Use emitter.setMaxListeners() to ' + - 'increase limit.'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - if (typeof console === 'object' && console.warn) { - console.warn('%s: %s', w.name, w.message); - } - } - } - } - - return target; -} - -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - switch (arguments.length) { - case 0: - return this.listener.call(this.target); - case 1: - return this.listener.call(this.target, arguments[0]); - case 2: - return this.listener.call(this.target, arguments[0], arguments[1]); - case 3: - return this.listener.call(this.target, arguments[0], arguments[1], - arguments[2]); - default: - var args = new Array(arguments.length); - for (var i = 0; i < args.length; ++i) - args[i] = arguments[i]; - this.listener.apply(this.target, args); - } - } -} - -function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; - var wrapped = bind.call(onceWrapper, state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -EventEmitter.prototype.once = function once(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - -// Emits a 'removeListener' event if and only if the listener was removed. -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - var list, events, position, i, originalListener; - - if (typeof listener !== 'function') - throw new TypeError('"listener" argument must be a function'); - - events = this._events; - if (!events) - return this; - - list = events[type]; - if (!list) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - position = -1; - - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else - spliceOne(list, position); - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener) - this.emit('removeListener', type, originalListener || listener); - } - - return this; - }; - -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - var listeners, events, i; - - events = this._events; - if (!events) - return this; - - // not listening for removeListener, no need to emit - if (!events.removeListener) { - if (arguments.length === 0) { - this._events = objectCreate(null); - this._eventsCount = 0; - } else if (events[type]) { - if (--this._eventsCount === 0) - this._events = objectCreate(null); - else - delete events[type]; - } - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - var keys = objectKeys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = objectCreate(null); - this._eventsCount = 0; - return this; - } - - listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - var events = target._events; - - if (!events) - return []; - - var evlistener = events[type]; - if (!evlistener) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); -} - -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } -}; - -EventEmitter.prototype.listenerCount = listenerCount; -function listenerCount(type) { - var events = this._events; - - if (events) { - var evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener) { - return evlistener.length; - } - } - - return 0; -} - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; -}; - -// About 1.5x faster than the two-arg version of Array#splice(). -function spliceOne(list, index) { - for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) - list[i] = list[k]; - list.pop(); -} - -function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) - copy[i] = arr[i]; - return copy; -} - -function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; -} - -function objectCreatePolyfill(proto) { - var F = function() {}; - F.prototype = proto; - return new F; -} -function objectKeysPolyfill(obj) { - var keys = []; - for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { - keys.push(k); - } - return k; -} -function functionBindPolyfill(context) { - var fn = this; - return function () { - return fn.apply(context, arguments); - }; -} - -},{}],105:[function(_dereq_,module,exports){ -(function (Buffer){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -/* eslint-disable no-proto */ - -'use strict' - -var base64 = _dereq_('base64-js') -var ieee754 = _dereq_('ieee754') - -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 - -var K_MAX_LENGTH = 0x7fffffff -exports.kMaxLength = K_MAX_LENGTH - -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Print warning and recommend using `buffer` v4.x which has an Object - * implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * We report that the browser does not support typed arrays if the are not subclassable - * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` - * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support - * for __proto__ and has a buggy typed array implementation. - */ -Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() - -if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && - typeof console.error === 'function') { - console.error( - 'This browser lacks typed array (Uint8Array) support which is required by ' + - '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' - ) -} - -function typedArraySupport () { - // Can typed array instances can be augmented? - try { - var arr = new Uint8Array(1) - arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } } - return arr.foo() === 42 - } catch (e) { - return false - } -} - -Object.defineProperty(Buffer.prototype, 'parent', { - enumerable: true, - get: function () { - if (!Buffer.isBuffer(this)) return undefined - return this.buffer - } -}) - -Object.defineProperty(Buffer.prototype, 'offset', { - enumerable: true, - get: function () { - if (!Buffer.isBuffer(this)) return undefined - return this.byteOffset - } -}) - -function createBuffer (length) { - if (length > K_MAX_LENGTH) { - throw new RangeError('The value "' + length + '" is invalid for option "size"') - } - // Return an augmented `Uint8Array` instance - var buf = new Uint8Array(length) - buf.__proto__ = Buffer.prototype - return buf -} - -/** - * The Buffer constructor returns instances of `Uint8Array` that have their - * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of - * `Uint8Array`, so the returned instances will have all the node `Buffer` methods - * and the `Uint8Array` methods. Square bracket notation works as expected -- it - * returns a single octet. - * - * The `Uint8Array` prototype remains unmodified. - */ - -function Buffer (arg, encodingOrOffset, length) { - // Common case. - if (typeof arg === 'number') { - if (typeof encodingOrOffset === 'string') { - throw new TypeError( - 'The "string" argument must be of type string. Received type number' - ) - } - return allocUnsafe(arg) - } - return from(arg, encodingOrOffset, length) -} - -// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 -if (typeof Symbol !== 'undefined' && Symbol.species != null && - Buffer[Symbol.species] === Buffer) { - Object.defineProperty(Buffer, Symbol.species, { - value: null, - configurable: true, - enumerable: false, - writable: false - }) -} - -Buffer.poolSize = 8192 // not used by this implementation - -function from (value, encodingOrOffset, length) { - if (typeof value === 'string') { - return fromString(value, encodingOrOffset) - } - - if (ArrayBuffer.isView(value)) { - return fromArrayLike(value) - } - - if (value == null) { - throw TypeError( - 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + - 'or Array-like Object. Received type ' + (typeof value) - ) - } - - if (isInstance(value, ArrayBuffer) || - (value && isInstance(value.buffer, ArrayBuffer))) { - return fromArrayBuffer(value, encodingOrOffset, length) - } - - if (typeof value === 'number') { - throw new TypeError( - 'The "value" argument must not be of type number. Received type number' - ) - } - - var valueOf = value.valueOf && value.valueOf() - if (valueOf != null && valueOf !== value) { - return Buffer.from(valueOf, encodingOrOffset, length) - } - - var b = fromObject(value) - if (b) return b - - if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && - typeof value[Symbol.toPrimitive] === 'function') { - return Buffer.from( - value[Symbol.toPrimitive]('string'), encodingOrOffset, length - ) - } - - throw new TypeError( - 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + - 'or Array-like Object. Received type ' + (typeof value) - ) -} - -/** - * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError - * if value is a number. - * Buffer.from(str[, encoding]) - * Buffer.from(array) - * Buffer.from(buffer) - * Buffer.from(arrayBuffer[, byteOffset[, length]]) - **/ -Buffer.from = function (value, encodingOrOffset, length) { - return from(value, encodingOrOffset, length) -} - -// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: -// https://github.com/feross/buffer/pull/148 -Buffer.prototype.__proto__ = Uint8Array.prototype -Buffer.__proto__ = Uint8Array - -function assertSize (size) { - if (typeof size !== 'number') { - throw new TypeError('"size" argument must be of type number') - } else if (size < 0) { - throw new RangeError('The value "' + size + '" is invalid for option "size"') - } -} - -function alloc (size, fill, encoding) { - assertSize(size) - if (size <= 0) { - return createBuffer(size) - } - if (fill !== undefined) { - // Only pay attention to encoding if it's a string. This - // prevents accidentally sending in a number that would - // be interpretted as a start offset. - return typeof encoding === 'string' - ? createBuffer(size).fill(fill, encoding) - : createBuffer(size).fill(fill) - } - return createBuffer(size) -} - -/** - * Creates a new filled Buffer instance. - * alloc(size[, fill[, encoding]]) - **/ -Buffer.alloc = function (size, fill, encoding) { - return alloc(size, fill, encoding) -} - -function allocUnsafe (size) { - assertSize(size) - return createBuffer(size < 0 ? 0 : checked(size) | 0) -} - -/** - * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. - * */ -Buffer.allocUnsafe = function (size) { - return allocUnsafe(size) -} -/** - * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. - */ -Buffer.allocUnsafeSlow = function (size) { - return allocUnsafe(size) -} - -function fromString (string, encoding) { - if (typeof encoding !== 'string' || encoding === '') { - encoding = 'utf8' - } - - if (!Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) - } - - var length = byteLength(string, encoding) | 0 - var buf = createBuffer(length) - - var actual = buf.write(string, encoding) - - if (actual !== length) { - // Writing a hex string, for example, that contains invalid characters will - // cause everything after the first invalid character to be ignored. (e.g. - // 'abxxcd' will be treated as 'ab') - buf = buf.slice(0, actual) - } - - return buf -} - -function fromArrayLike (array) { - var length = array.length < 0 ? 0 : checked(array.length) | 0 - var buf = createBuffer(length) - for (var i = 0; i < length; i += 1) { - buf[i] = array[i] & 255 - } - return buf -} - -function fromArrayBuffer (array, byteOffset, length) { - if (byteOffset < 0 || array.byteLength < byteOffset) { - throw new RangeError('"offset" is outside of buffer bounds') - } - - if (array.byteLength < byteOffset + (length || 0)) { - throw new RangeError('"length" is outside of buffer bounds') - } - - var buf - if (byteOffset === undefined && length === undefined) { - buf = new Uint8Array(array) - } else if (length === undefined) { - buf = new Uint8Array(array, byteOffset) - } else { - buf = new Uint8Array(array, byteOffset, length) - } - - // Return an augmented `Uint8Array` instance - buf.__proto__ = Buffer.prototype - return buf -} - -function fromObject (obj) { - if (Buffer.isBuffer(obj)) { - var len = checked(obj.length) | 0 - var buf = createBuffer(len) - - if (buf.length === 0) { - return buf - } - - obj.copy(buf, 0, 0, len) - return buf - } - - if (obj.length !== undefined) { - if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { - return createBuffer(0) - } - return fromArrayLike(obj) - } - - if (obj.type === 'Buffer' && Array.isArray(obj.data)) { - return fromArrayLike(obj.data) - } -} - -function checked (length) { - // Note: cannot use `length < K_MAX_LENGTH` here because that fails when - // length is NaN (which is otherwise coerced to zero.) - if (length >= K_MAX_LENGTH) { - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') - } - return length | 0 -} - -function SlowBuffer (length) { - if (+length != length) { // eslint-disable-line eqeqeq - length = 0 - } - return Buffer.alloc(+length) -} - -Buffer.isBuffer = function isBuffer (b) { - return b != null && b._isBuffer === true && - b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false -} - -Buffer.compare = function compare (a, b) { - if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) - if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { - throw new TypeError( - 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' - ) - } - - if (a === b) return 0 - - var x = a.length - var y = b.length - - for (var i = 0, len = Math.min(x, y); i < len; ++i) { - if (a[i] !== b[i]) { - x = a[i] - y = b[i] - break - } - } - - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -Buffer.isEncoding = function isEncoding (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'latin1': - case 'binary': - case 'base64': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false - } -} - -Buffer.concat = function concat (list, length) { - if (!Array.isArray(list)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - - if (list.length === 0) { - return Buffer.alloc(0) - } - - var i - if (length === undefined) { - length = 0 - for (i = 0; i < list.length; ++i) { - length += list[i].length - } - } - - var buffer = Buffer.allocUnsafe(length) - var pos = 0 - for (i = 0; i < list.length; ++i) { - var buf = list[i] - if (isInstance(buf, Uint8Array)) { - buf = Buffer.from(buf) - } - if (!Buffer.isBuffer(buf)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - buf.copy(buffer, pos) - pos += buf.length - } - return buffer -} - -function byteLength (string, encoding) { - if (Buffer.isBuffer(string)) { - return string.length - } - if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { - return string.byteLength - } - if (typeof string !== 'string') { - throw new TypeError( - 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + - 'Received type ' + typeof string - ) - } - - var len = string.length - var mustMatch = (arguments.length > 2 && arguments[2] === true) - if (!mustMatch && len === 0) return 0 - - // Use a for loop to avoid recursion - var loweredCase = false - for (;;) { - switch (encoding) { - case 'ascii': - case 'latin1': - case 'binary': - return len - case 'utf8': - case 'utf-8': - return utf8ToBytes(string).length - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return len * 2 - case 'hex': - return len >>> 1 - case 'base64': - return base64ToBytes(string).length - default: - if (loweredCase) { - return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 - } - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} -Buffer.byteLength = byteLength - -function slowToString (encoding, start, end) { - var loweredCase = false - - // No need to verify that "this.length <= MAX_UINT32" since it's a read-only - // property of a typed array. - - // This behaves neither like String nor Uint8Array in that we set start/end - // to their upper/lower bounds if the value passed is out of range. - // undefined is handled specially as per ECMA-262 6th Edition, - // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. - if (start === undefined || start < 0) { - start = 0 - } - // Return early if start > this.length. Done here to prevent potential uint32 - // coercion fail below. - if (start > this.length) { - return '' - } - - if (end === undefined || end > this.length) { - end = this.length - } - - if (end <= 0) { - return '' - } - - // Force coersion to uint32. This will also coerce falsey/NaN values to 0. - end >>>= 0 - start >>>= 0 - - if (end <= start) { - return '' - } - - if (!encoding) encoding = 'utf8' - - while (true) { - switch (encoding) { - case 'hex': - return hexSlice(this, start, end) - - case 'utf8': - case 'utf-8': - return utf8Slice(this, start, end) - - case 'ascii': - return asciiSlice(this, start, end) - - case 'latin1': - case 'binary': - return latin1Slice(this, start, end) - - case 'base64': - return base64Slice(this, start, end) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return utf16leSlice(this, start, end) - - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() - loweredCase = true - } - } -} - -// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) -// to detect a Buffer instance. It's not possible to use `instanceof Buffer` -// reliably in a browserify context because there could be multiple different -// copies of the 'buffer' package in use. This method works even for Buffer -// instances that were created from another copy of the `buffer` package. -// See: https://github.com/feross/buffer/issues/154 -Buffer.prototype._isBuffer = true - -function swap (b, n, m) { - var i = b[n] - b[n] = b[m] - b[m] = i -} - -Buffer.prototype.swap16 = function swap16 () { - var len = this.length - if (len % 2 !== 0) { - throw new RangeError('Buffer size must be a multiple of 16-bits') - } - for (var i = 0; i < len; i += 2) { - swap(this, i, i + 1) - } - return this -} - -Buffer.prototype.swap32 = function swap32 () { - var len = this.length - if (len % 4 !== 0) { - throw new RangeError('Buffer size must be a multiple of 32-bits') - } - for (var i = 0; i < len; i += 4) { - swap(this, i, i + 3) - swap(this, i + 1, i + 2) - } - return this -} - -Buffer.prototype.swap64 = function swap64 () { - var len = this.length - if (len % 8 !== 0) { - throw new RangeError('Buffer size must be a multiple of 64-bits') - } - for (var i = 0; i < len; i += 8) { - swap(this, i, i + 7) - swap(this, i + 1, i + 6) - swap(this, i + 2, i + 5) - swap(this, i + 3, i + 4) - } - return this -} - -Buffer.prototype.toString = function toString () { - var length = this.length - if (length === 0) return '' - if (arguments.length === 0) return utf8Slice(this, 0, length) - return slowToString.apply(this, arguments) -} - -Buffer.prototype.toLocaleString = Buffer.prototype.toString - -Buffer.prototype.equals = function equals (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - if (this === b) return true - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.inspect = function inspect () { - var str = '' - var max = exports.INSPECT_MAX_BYTES - str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() - if (this.length > max) str += ' ... ' - return '' -} - -Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { - if (isInstance(target, Uint8Array)) { - target = Buffer.from(target, target.offset, target.byteLength) - } - if (!Buffer.isBuffer(target)) { - throw new TypeError( - 'The "target" argument must be one of type Buffer or Uint8Array. ' + - 'Received type ' + (typeof target) - ) - } - - if (start === undefined) { - start = 0 - } - if (end === undefined) { - end = target ? target.length : 0 - } - if (thisStart === undefined) { - thisStart = 0 - } - if (thisEnd === undefined) { - thisEnd = this.length - } - - if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { - throw new RangeError('out of range index') - } - - if (thisStart >= thisEnd && start >= end) { - return 0 - } - if (thisStart >= thisEnd) { - return -1 - } - if (start >= end) { - return 1 - } - - start >>>= 0 - end >>>= 0 - thisStart >>>= 0 - thisEnd >>>= 0 - - if (this === target) return 0 - - var x = thisEnd - thisStart - var y = end - start - var len = Math.min(x, y) - - var thisCopy = this.slice(thisStart, thisEnd) - var targetCopy = target.slice(start, end) - - for (var i = 0; i < len; ++i) { - if (thisCopy[i] !== targetCopy[i]) { - x = thisCopy[i] - y = targetCopy[i] - break - } - } - - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, -// OR the last index of `val` in `buffer` at offset <= `byteOffset`. -// -// Arguments: -// - buffer - a Buffer to search -// - val - a string, Buffer, or number -// - byteOffset - an index into `buffer`; will be clamped to an int32 -// - encoding - an optional encoding, relevant is val is a string -// - dir - true for indexOf, false for lastIndexOf -function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { - // Empty buffer means no match - if (buffer.length === 0) return -1 - - // Normalize byteOffset - if (typeof byteOffset === 'string') { - encoding = byteOffset - byteOffset = 0 - } else if (byteOffset > 0x7fffffff) { - byteOffset = 0x7fffffff - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000 - } - byteOffset = +byteOffset // Coerce to Number. - if (numberIsNaN(byteOffset)) { - // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer - byteOffset = dir ? 0 : (buffer.length - 1) - } - - // Normalize byteOffset: negative offsets start from the end of the buffer - if (byteOffset < 0) byteOffset = buffer.length + byteOffset - if (byteOffset >= buffer.length) { - if (dir) return -1 - else byteOffset = buffer.length - 1 - } else if (byteOffset < 0) { - if (dir) byteOffset = 0 - else return -1 - } - - // Normalize val - if (typeof val === 'string') { - val = Buffer.from(val, encoding) - } - - // Finally, search either indexOf (if dir is true) or lastIndexOf - if (Buffer.isBuffer(val)) { - // Special case: looking for empty string/buffer always fails - if (val.length === 0) { - return -1 - } - return arrayIndexOf(buffer, val, byteOffset, encoding, dir) - } else if (typeof val === 'number') { - val = val & 0xFF // Search for a byte value [0-255] - if (typeof Uint8Array.prototype.indexOf === 'function') { - if (dir) { - return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) - } else { - return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) - } - } - return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) - } - - throw new TypeError('val must be string, number or Buffer') -} - -function arrayIndexOf (arr, val, byteOffset, encoding, dir) { - var indexSize = 1 - var arrLength = arr.length - var valLength = val.length - - if (encoding !== undefined) { - encoding = String(encoding).toLowerCase() - if (encoding === 'ucs2' || encoding === 'ucs-2' || - encoding === 'utf16le' || encoding === 'utf-16le') { - if (arr.length < 2 || val.length < 2) { - return -1 - } - indexSize = 2 - arrLength /= 2 - valLength /= 2 - byteOffset /= 2 - } - } - - function read (buf, i) { - if (indexSize === 1) { - return buf[i] - } else { - return buf.readUInt16BE(i * indexSize) - } - } - - var i - if (dir) { - var foundIndex = -1 - for (i = byteOffset; i < arrLength; i++) { - if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { - if (foundIndex === -1) foundIndex = i - if (i - foundIndex + 1 === valLength) return foundIndex * indexSize - } else { - if (foundIndex !== -1) i -= i - foundIndex - foundIndex = -1 - } - } - } else { - if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength - for (i = byteOffset; i >= 0; i--) { - var found = true - for (var j = 0; j < valLength; j++) { - if (read(arr, i + j) !== read(val, j)) { - found = false - break - } - } - if (found) return i - } - } - - return -1 -} - -Buffer.prototype.includes = function includes (val, byteOffset, encoding) { - return this.indexOf(val, byteOffset, encoding) !== -1 -} - -Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, true) -} - -Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, false) -} - -function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - var remaining = buf.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } - - var strLen = string.length - - if (length > strLen / 2) { - length = strLen / 2 - } - for (var i = 0; i < length; ++i) { - var parsed = parseInt(string.substr(i * 2, 2), 16) - if (numberIsNaN(parsed)) return i - buf[offset + i] = parsed - } - return i -} - -function utf8Write (buf, string, offset, length) { - return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) -} - -function asciiWrite (buf, string, offset, length) { - return blitBuffer(asciiToBytes(string), buf, offset, length) -} - -function latin1Write (buf, string, offset, length) { - return asciiWrite(buf, string, offset, length) -} - -function base64Write (buf, string, offset, length) { - return blitBuffer(base64ToBytes(string), buf, offset, length) -} - -function ucs2Write (buf, string, offset, length) { - return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) -} - -Buffer.prototype.write = function write (string, offset, length, encoding) { - // Buffer#write(string) - if (offset === undefined) { - encoding = 'utf8' - length = this.length - offset = 0 - // Buffer#write(string, encoding) - } else if (length === undefined && typeof offset === 'string') { - encoding = offset - length = this.length - offset = 0 - // Buffer#write(string, offset[, length][, encoding]) - } else if (isFinite(offset)) { - offset = offset >>> 0 - if (isFinite(length)) { - length = length >>> 0 - if (encoding === undefined) encoding = 'utf8' - } else { - encoding = length - length = undefined - } - } else { - throw new Error( - 'Buffer.write(string, encoding, offset[, length]) is no longer supported' - ) - } - - var remaining = this.length - offset - if (length === undefined || length > remaining) length = remaining - - if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { - throw new RangeError('Attempt to write outside buffer bounds') - } - - if (!encoding) encoding = 'utf8' - - var loweredCase = false - for (;;) { - switch (encoding) { - case 'hex': - return hexWrite(this, string, offset, length) - - case 'utf8': - case 'utf-8': - return utf8Write(this, string, offset, length) - - case 'ascii': - return asciiWrite(this, string, offset, length) - - case 'latin1': - case 'binary': - return latin1Write(this, string, offset, length) - - case 'base64': - // Warning: maxLength not taken into account in base64Write - return base64Write(this, string, offset, length) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return ucs2Write(this, string, offset, length) - - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} - -Buffer.prototype.toJSON = function toJSON () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) - } -} - -function base64Slice (buf, start, end) { - if (start === 0 && end === buf.length) { - return base64.fromByteArray(buf) - } else { - return base64.fromByteArray(buf.slice(start, end)) - } -} - -function utf8Slice (buf, start, end) { - end = Math.min(buf.length, end) - var res = [] - - var i = start - while (i < end) { - var firstByte = buf[i] - var codePoint = null - var bytesPerSequence = (firstByte > 0xEF) ? 4 - : (firstByte > 0xDF) ? 3 - : (firstByte > 0xBF) ? 2 - : 1 - - if (i + bytesPerSequence <= end) { - var secondByte, thirdByte, fourthByte, tempCodePoint - - switch (bytesPerSequence) { - case 1: - if (firstByte < 0x80) { - codePoint = firstByte - } - break - case 2: - secondByte = buf[i + 1] - if ((secondByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) - if (tempCodePoint > 0x7F) { - codePoint = tempCodePoint - } - } - break - case 3: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) - if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { - codePoint = tempCodePoint - } - } - break - case 4: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - fourthByte = buf[i + 3] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) - if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { - codePoint = tempCodePoint - } - } - } - } - - if (codePoint === null) { - // we did not generate a valid codePoint so insert a - // replacement char (U+FFFD) and advance only 1 byte - codePoint = 0xFFFD - bytesPerSequence = 1 - } else if (codePoint > 0xFFFF) { - // encode to utf16 (surrogate pair dance) - codePoint -= 0x10000 - res.push(codePoint >>> 10 & 0x3FF | 0xD800) - codePoint = 0xDC00 | codePoint & 0x3FF - } - - res.push(codePoint) - i += bytesPerSequence - } - - return decodeCodePointsArray(res) -} - -// Based on http://stackoverflow.com/a/22747272/680742, the browser with -// the lowest limit is Chrome, with 0x10000 args. -// We go 1 magnitude less, for safety -var MAX_ARGUMENTS_LENGTH = 0x1000 - -function decodeCodePointsArray (codePoints) { - var len = codePoints.length - if (len <= MAX_ARGUMENTS_LENGTH) { - return String.fromCharCode.apply(String, codePoints) // avoid extra slice() - } - - // Decode in chunks to avoid "call stack size exceeded". - var res = '' - var i = 0 - while (i < len) { - res += String.fromCharCode.apply( - String, - codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) - ) - } - return res -} - -function asciiSlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i] & 0x7F) - } - return ret -} - -function latin1Slice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i]) - } - return ret -} - -function hexSlice (buf, start, end) { - var len = buf.length - - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len - - var out = '' - for (var i = start; i < end; ++i) { - out += toHex(buf[i]) - } - return out -} - -function utf16leSlice (buf, start, end) { - var bytes = buf.slice(start, end) - var res = '' - for (var i = 0; i < bytes.length; i += 2) { - res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) - } - return res -} - -Buffer.prototype.slice = function slice (start, end) { - var len = this.length - start = ~~start - end = end === undefined ? len : ~~end - - if (start < 0) { - start += len - if (start < 0) start = 0 - } else if (start > len) { - start = len - } - - if (end < 0) { - end += len - if (end < 0) end = 0 - } else if (end > len) { - end = len - } - - if (end < start) end = start - - var newBuf = this.subarray(start, end) - // Return an augmented `Uint8Array` instance - newBuf.__proto__ = Buffer.prototype - return newBuf -} - -/* - * Need to make sure that buffer isn't trying to write out of bounds. - */ -function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') - if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') -} - -Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - - return val -} - -Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - checkOffset(offset, byteLength, this.length) - } - - var val = this[offset + --byteLength] - var mul = 1 - while (byteLength > 0 && (mul *= 0x100)) { - val += this[offset + --byteLength] * mul - } - - return val -} - -Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 1, this.length) - return this[offset] -} - -Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - return this[offset] | (this[offset + 1] << 8) -} - -Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - return (this[offset] << 8) | this[offset + 1] -} - -Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - - return ((this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16)) + - (this[offset + 3] * 0x1000000) -} - -Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) -} - -Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - var i = byteLength - var mul = 1 - var val = this[offset + --i] - while (i > 0 && (mul *= 0x100)) { - val += this[offset + --i] * mul - } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) return (this[offset]) - return ((0xff - this[offset] + 1) * -1) -} - -Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset] | (this[offset + 1] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset + 1] | (this[offset] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) -} - -Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) -} - -Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, true, 23, 4) -} - -Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, false, 23, 4) -} - -Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, true, 52, 8) -} - -Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, false, 52, 8) -} - -function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') - if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') - if (offset + ext > buf.length) throw new RangeError('Index out of range') -} - -Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } - - var mul = 1 - var i = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } - - var i = byteLength - 1 - var mul = 1 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) - this[offset] = (value & 0xff) - return offset + 1 -} - -Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - return offset + 2 -} - -Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - return offset + 2 -} - -Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = (value & 0xff) - return offset + 4 -} - -Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - return offset + 4 -} - -Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - var limit = Math.pow(2, (8 * byteLength) - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } - - var i = 0 - var mul = 1 - var sub = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - var limit = Math.pow(2, (8 * byteLength) - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } - - var i = byteLength - 1 - var mul = 1 - var sub = 0 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) - if (value < 0) value = 0xff + value + 1 - this[offset] = (value & 0xff) - return offset + 1 -} - -Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - return offset + 2 -} - -Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - return offset + 2 -} - -Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - return offset + 4 -} - -Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - return offset + 4 -} - -function checkIEEE754 (buf, value, offset, ext, max, min) { - if (offset + ext > buf.length) throw new RangeError('Index out of range') - if (offset < 0) throw new RangeError('Index out of range') -} - -function writeFloat (buf, value, offset, littleEndian, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) - } - ieee754.write(buf, value, offset, littleEndian, 23, 4) - return offset + 4 -} - -Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { - return writeFloat(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { - return writeFloat(this, value, offset, false, noAssert) -} - -function writeDouble (buf, value, offset, littleEndian, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - ieee754.write(buf, value, offset, littleEndian, 52, 8) - return offset + 8 -} - -Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { - return writeDouble(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { - return writeDouble(this, value, offset, false, noAssert) -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function copy (target, targetStart, start, end) { - if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (targetStart >= target.length) targetStart = target.length - if (!targetStart) targetStart = 0 - if (end > 0 && end < start) end = start - - // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || this.length === 0) return 0 - - // Fatal error conditions - if (targetStart < 0) { - throw new RangeError('targetStart out of bounds') - } - if (start < 0 || start >= this.length) throw new RangeError('Index out of range') - if (end < 0) throw new RangeError('sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) end = this.length - if (target.length - targetStart < end - start) { - end = target.length - targetStart + start - } - - var len = end - start - - if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { - // Use built-in when available, missing from IE11 - this.copyWithin(targetStart, start, end) - } else if (this === target && start < targetStart && targetStart < end) { - // descending copy from end - for (var i = len - 1; i >= 0; --i) { - target[i + targetStart] = this[i + start] - } - } else { - Uint8Array.prototype.set.call( - target, - this.subarray(start, end), - targetStart - ) - } - - return len -} - -// Usage: -// buffer.fill(number[, offset[, end]]) -// buffer.fill(buffer[, offset[, end]]) -// buffer.fill(string[, offset[, end]][, encoding]) -Buffer.prototype.fill = function fill (val, start, end, encoding) { - // Handle string cases: - if (typeof val === 'string') { - if (typeof start === 'string') { - encoding = start - start = 0 - end = this.length - } else if (typeof end === 'string') { - encoding = end - end = this.length - } - if (encoding !== undefined && typeof encoding !== 'string') { - throw new TypeError('encoding must be a string') - } - if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) - } - if (val.length === 1) { - var code = val.charCodeAt(0) - if ((encoding === 'utf8' && code < 128) || - encoding === 'latin1') { - // Fast path: If `val` fits into a single byte, use that numeric value. - val = code - } - } - } else if (typeof val === 'number') { - val = val & 255 - } - - // Invalid ranges are not set to a default, so can range check early. - if (start < 0 || this.length < start || this.length < end) { - throw new RangeError('Out of range index') - } - - if (end <= start) { - return this - } - - start = start >>> 0 - end = end === undefined ? this.length : end >>> 0 - - if (!val) val = 0 - - var i - if (typeof val === 'number') { - for (i = start; i < end; ++i) { - this[i] = val - } - } else { - var bytes = Buffer.isBuffer(val) - ? val - : Buffer.from(val, encoding) - var len = bytes.length - if (len === 0) { - throw new TypeError('The value "' + val + - '" is invalid for argument "value"') - } - for (i = 0; i < end - start; ++i) { - this[i + start] = bytes[i % len] - } - } - - return this -} - -// HELPER FUNCTIONS -// ================ - -var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g - -function base64clean (str) { - // Node takes equal signs as end of the Base64 encoding - str = str.split('=')[0] - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = str.trim().replace(INVALID_BASE64_RE, '') - // Node converts strings with length < 2 to '' - if (str.length < 2) return '' - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + '=' - } - return str -} - -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) -} - -function utf8ToBytes (string, units) { - units = units || Infinity - var codePoint - var length = string.length - var leadSurrogate = null - var bytes = [] - - for (var i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i) - - // is surrogate component - if (codePoint > 0xD7FF && codePoint < 0xE000) { - // last char was a lead - if (!leadSurrogate) { - // no lead yet - if (codePoint > 0xDBFF) { - // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } else if (i + 1 === length) { - // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } - - // valid lead - leadSurrogate = codePoint - - continue - } - - // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint - continue - } - - // valid surrogate pair - codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 - } else if (leadSurrogate) { - // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - } - - leadSurrogate = null - - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint) - } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break - bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else { - throw new Error('Invalid code point') - } - } - - return bytes -} - -function asciiToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xFF) - } - return byteArray -} - -function utf16leToBytes (str, units) { - var c, hi, lo - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - if ((units -= 2) < 0) break - - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } - - return byteArray -} - -function base64ToBytes (str) { - return base64.toByteArray(base64clean(str)) -} - -function blitBuffer (src, dst, offset, length) { - for (var i = 0; i < length; ++i) { - if ((i + offset >= dst.length) || (i >= src.length)) break - dst[i + offset] = src[i] - } - return i -} - -// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass -// the `instanceof` check but they should be treated as of that type. -// See: https://github.com/feross/buffer/issues/166 -function isInstance (obj, type) { - return obj instanceof type || - (obj != null && obj.constructor != null && obj.constructor.name != null && - obj.constructor.name === type.name) -} -function numberIsNaN (obj) { - // For IE11 support - return obj !== obj // eslint-disable-line no-self-compare -} - -}).call(this,_dereq_("buffer").Buffer) -},{"base64-js":74,"buffer":105,"ieee754":412}],106:[function(_dereq_,module,exports){ -'use strict' - -var monotoneTriangulate = _dereq_('./lib/monotone') -var makeIndex = _dereq_('./lib/triangulation') -var delaunayFlip = _dereq_('./lib/delaunay') -var filterTriangulation = _dereq_('./lib/filter') - -module.exports = cdt2d - -function canonicalizeEdge(e) { - return [Math.min(e[0], e[1]), Math.max(e[0], e[1])] -} - -function compareEdge(a, b) { - return a[0]-b[0] || a[1]-b[1] -} - -function canonicalizeEdges(edges) { - return edges.map(canonicalizeEdge).sort(compareEdge) -} - -function getDefault(options, property, dflt) { - if(property in options) { - return options[property] - } - return dflt -} - -function cdt2d(points, edges, options) { - - if(!Array.isArray(edges)) { - options = edges || {} - edges = [] - } else { - options = options || {} - edges = edges || [] - } - - //Parse out options - var delaunay = !!getDefault(options, 'delaunay', true) - var interior = !!getDefault(options, 'interior', true) - var exterior = !!getDefault(options, 'exterior', true) - var infinity = !!getDefault(options, 'infinity', false) - - //Handle trivial case - if((!interior && !exterior) || points.length === 0) { - return [] - } - - //Construct initial triangulation - var cells = monotoneTriangulate(points, edges) - - //If delaunay refinement needed, then improve quality by edge flipping - if(delaunay || interior !== exterior || infinity) { - - //Index all of the cells to support fast neighborhood queries - var triangulation = makeIndex(points.length, canonicalizeEdges(edges)) - for(var i=0; i 0) { - var b = stack.pop() - var a = stack.pop() - - //Find opposite pairs - var x = -1, y = -1 - var star = stars[a] - for(var i=1; i= 0) { - continue - } - - //Flip the edge - triangulation.flip(a, b) - - //Test flipping neighboring edges - testFlip(points, triangulation, stack, x, a, y) - testFlip(points, triangulation, stack, a, y, x) - testFlip(points, triangulation, stack, y, b, x) - testFlip(points, triangulation, stack, b, x, y) - } -} - -},{"binary-search-bounds":111,"robust-in-sphere":508}],108:[function(_dereq_,module,exports){ -'use strict' - -var bsearch = _dereq_('binary-search-bounds') - -module.exports = classifyFaces - -function FaceIndex(cells, neighbor, constraint, flags, active, next, boundary) { - this.cells = cells - this.neighbor = neighbor - this.flags = flags - this.constraint = constraint - this.active = active - this.next = next - this.boundary = boundary -} - -var proto = FaceIndex.prototype - -function compareCell(a, b) { - return a[0] - b[0] || - a[1] - b[1] || - a[2] - b[2] -} - -proto.locate = (function() { - var key = [0,0,0] - return function(a, b, c) { - var x = a, y = b, z = c - if(b < c) { - if(b < a) { - x = b - y = c - z = a - } - } else if(c < a) { - x = c - y = a - z = b - } - if(x < 0) { - return -1 - } - key[0] = x - key[1] = y - key[2] = z - return bsearch.eq(this.cells, key, compareCell) - } -})() - -function indexCells(triangulation, infinity) { - //First get cells and canonicalize - var cells = triangulation.cells() - var nc = cells.length - for(var i=0; i 0 || next.length > 0) { - while(active.length > 0) { - var t = active.pop() - if(flags[t] === -side) { - continue - } - flags[t] = side - var c = cells[t] - for(var j=0; j<3; ++j) { - var f = neighbor[3*t+j] - if(f >= 0 && flags[f] === 0) { - if(constraint[3*t+j]) { - next.push(f) - } else { - active.push(f) - flags[f] = side - } - } - } - } - - //Swap arrays and loop - var tmp = next - next = active - active = tmp - next.length = 0 - side = -side - } - - var result = filterCells(cells, flags, target) - if(infinity) { - return result.concat(index.boundary) - } - return result -} - -},{"binary-search-bounds":111}],109:[function(_dereq_,module,exports){ -'use strict' - -var bsearch = _dereq_('binary-search-bounds') -var orient = _dereq_('robust-orientation')[3] - -var EVENT_POINT = 0 -var EVENT_END = 1 -var EVENT_START = 2 - -module.exports = monotoneTriangulate - -//A partial convex hull fragment, made of two unimonotone polygons -function PartialHull(a, b, idx, lowerIds, upperIds) { - this.a = a - this.b = b - this.idx = idx - this.lowerIds = lowerIds - this.upperIds = upperIds -} - -//An event in the sweep line procedure -function Event(a, b, type, idx) { - this.a = a - this.b = b - this.type = type - this.idx = idx -} - -//This is used to compare events for the sweep line procedure -// Points are: -// 1. sorted lexicographically -// 2. sorted by type (point < end < start) -// 3. segments sorted by winding order -// 4. sorted by index -function compareEvent(a, b) { - var d = - (a.a[0] - b.a[0]) || - (a.a[1] - b.a[1]) || - (a.type - b.type) - if(d) { return d } - if(a.type !== EVENT_POINT) { - d = orient(a.a, a.b, b.b) - if(d) { return d } - } - return a.idx - b.idx -} - -function testPoint(hull, p) { - return orient(hull.a, hull.b, p) -} - -function addPoint(cells, hulls, points, p, idx) { - var lo = bsearch.lt(hulls, p, testPoint) - var hi = bsearch.gt(hulls, p, testPoint) - for(var i=lo; i 1 && orient( - points[lowerIds[m-2]], - points[lowerIds[m-1]], - p) > 0) { - cells.push( - [lowerIds[m-1], - lowerIds[m-2], - idx]) - m -= 1 - } - lowerIds.length = m - lowerIds.push(idx) - - //Insert p into upper hull - var upperIds = hull.upperIds - var m = upperIds.length - while(m > 1 && orient( - points[upperIds[m-2]], - points[upperIds[m-1]], - p) < 0) { - cells.push( - [upperIds[m-2], - upperIds[m-1], - idx]) - m -= 1 - } - upperIds.length = m - upperIds.push(idx) - } -} - -function findSplit(hull, edge) { - var d - if(hull.a[0] < edge.a[0]) { - d = orient(hull.a, hull.b, edge.a) - } else { - d = orient(edge.b, edge.a, hull.a) - } - if(d) { return d } - if(edge.b[0] < hull.b[0]) { - d = orient(hull.a, hull.b, edge.b) - } else { - d = orient(edge.b, edge.a, hull.b) - } - return d || hull.idx - edge.idx -} - -function splitHulls(hulls, points, event) { - var splitIdx = bsearch.le(hulls, event, findSplit) - var hull = hulls[splitIdx] - var upperIds = hull.upperIds - var x = upperIds[upperIds.length-1] - hull.upperIds = [x] - hulls.splice(splitIdx+1, 0, - new PartialHull(event.a, event.b, event.idx, [x], upperIds)) -} - - -function mergeHulls(hulls, points, event) { - //Swap pointers for merge search - var tmp = event.a - event.a = event.b - event.b = tmp - var mergeIdx = bsearch.eq(hulls, event, findSplit) - var upper = hulls[mergeIdx] - var lower = hulls[mergeIdx-1] - lower.upperIds = upper.upperIds - hulls.splice(mergeIdx, 1) -} - - -function monotoneTriangulate(points, edges) { - - var numPoints = points.length - var numEdges = edges.length - - var events = [] - - //Create point events - for(var i=0; i b[0]) { - events.push( - new Event(b, a, EVENT_START, i), - new Event(a, b, EVENT_END, i)) - } - } - - //Sort events - events.sort(compareEvent) - - //Initialize hull - var minX = events[0].a[0] - (1 + Math.abs(events[0].a[0])) * Math.pow(2, -52) - var hull = [ new PartialHull([minX, 1], [minX, 0], -1, [], [], [], []) ] - - //Process events in order - var cells = [] - for(var i=0, numEvents=events.length; i= 0 - } -})() - -proto.removeTriangle = function(i, j, k) { - var stars = this.stars - removePair(stars[i], j, k) - removePair(stars[j], k, i) - removePair(stars[k], i, j) -} - -proto.addTriangle = function(i, j, k) { - var stars = this.stars - stars[i].push(j, k) - stars[j].push(k, i) - stars[k].push(i, j) -} - -proto.opposite = function(j, i) { - var list = this.stars[i] - for(var k=1, n=list.length; k>>1,x=a[m]"] - if(earlyOut) { - if(predicate.indexOf("c") < 0) { - code.push(";if(x===y){return m}else if(x<=y){") - } else { - code.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){") - } - } else { - code.push(";if(", predicate, "){i=m;") - } - if(reversed) { - code.push("l=m+1}else{h=m-1}") - } else { - code.push("h=m-1}else{l=m+1}") - } - code.push("}") - if(earlyOut) { - code.push("return -1};") - } else { - code.push("return i};") - } - return code.join("") -} - -function compileBoundsSearch(predicate, reversed, suffix, earlyOut) { - var result = new Function([ - compileSearch("A", "x" + predicate + "y", reversed, ["y"], earlyOut), - compileSearch("P", "c(x,y)" + predicate + "0", reversed, ["y", "c"], earlyOut), -"function dispatchBsearch", suffix, "(a,y,c,l,h){\ -if(typeof(c)==='function'){\ -return P(a,(l===void 0)?0:l|0,(h===void 0)?a.length-1:h|0,y,c)\ -}else{\ -return A(a,(c===void 0)?0:c|0,(l===void 0)?a.length-1:l|0,y)\ -}}\ -return dispatchBsearch", suffix].join("")) - return result() -} - -module.exports = { - ge: compileBoundsSearch(">=", false, "GE"), - gt: compileBoundsSearch(">", false, "GT"), - lt: compileBoundsSearch("<", true, "LT"), - le: compileBoundsSearch("<=", true, "LE"), - eq: compileBoundsSearch("-", true, "EQ", true) -} - -},{}],112:[function(_dereq_,module,exports){ -'use strict' - -module.exports = orientation - -function orientation(s) { - var p = 1 - for(var i=1; i max ? max : value) - : (value < max ? max : value > min ? min : value) -} - -},{}],116:[function(_dereq_,module,exports){ -'use strict' - -module.exports = cleanPSLG - -var UnionFind = _dereq_('union-find') -var boxIntersect = _dereq_('box-intersect') -var segseg = _dereq_('robust-segment-intersect') -var rat = _dereq_('big-rat') -var ratCmp = _dereq_('big-rat/cmp') -var ratToFloat = _dereq_('big-rat/to-float') -var ratVec = _dereq_('rat-vec') -var nextafter = _dereq_('nextafter') - -var solveIntersection = _dereq_('./lib/rat-seg-intersect') - -// Bounds on a rational number when rounded to a float -function boundRat (r) { - var f = ratToFloat(r) - return [ - nextafter(f, -Infinity), - nextafter(f, Infinity) - ] -} - -// Convert a list of edges in a pslg to bounding boxes -function boundEdges (points, edges) { - var bounds = new Array(edges.length) - for (var i = 0; i < edges.length; ++i) { - var e = edges[i] - var a = points[e[0]] - var b = points[e[1]] - bounds[i] = [ - nextafter(Math.min(a[0], b[0]), -Infinity), - nextafter(Math.min(a[1], b[1]), -Infinity), - nextafter(Math.max(a[0], b[0]), Infinity), - nextafter(Math.max(a[1], b[1]), Infinity) - ] - } - return bounds -} - -// Convert a list of points into bounding boxes by duplicating coords -function boundPoints (points) { - var bounds = new Array(points.length) - for (var i = 0; i < points.length; ++i) { - var p = points[i] - bounds[i] = [ - nextafter(p[0], -Infinity), - nextafter(p[1], -Infinity), - nextafter(p[0], Infinity), - nextafter(p[1], Infinity) - ] - } - return bounds -} - -// Find all pairs of crossing edges in a pslg (given edge bounds) -function getCrossings (points, edges, edgeBounds) { - var result = [] - boxIntersect(edgeBounds, function (i, j) { - var e = edges[i] - var f = edges[j] - if (e[0] === f[0] || e[0] === f[1] || - e[1] === f[0] || e[1] === f[1]) { - return - } - var a = points[e[0]] - var b = points[e[1]] - var c = points[f[0]] - var d = points[f[1]] - if (segseg(a, b, c, d)) { - result.push([i, j]) - } - }) - return result -} - -// Find all pairs of crossing vertices in a pslg (given edge/vert bounds) -function getTJunctions (points, edges, edgeBounds, vertBounds) { - var result = [] - boxIntersect(edgeBounds, vertBounds, function (i, v) { - var e = edges[i] - if (e[0] === v || e[1] === v) { - return - } - var p = points[v] - var a = points[e[0]] - var b = points[e[1]] - if (segseg(a, b, p, p)) { - result.push([i, v]) - } - }) - return result -} - -// Cut edges along crossings/tjunctions -function cutEdges (floatPoints, edges, crossings, junctions, useColor) { - var i, e - - // Convert crossings into tjunctions by constructing rational points - var ratPoints = floatPoints.map(function(p) { - return [ - rat(p[0]), - rat(p[1]) - ] - }) - for (i = 0; i < crossings.length; ++i) { - var crossing = crossings[i] - e = crossing[0] - var f = crossing[1] - var ee = edges[e] - var ef = edges[f] - var x = solveIntersection( - ratVec(floatPoints[ee[0]]), - ratVec(floatPoints[ee[1]]), - ratVec(floatPoints[ef[0]]), - ratVec(floatPoints[ef[1]])) - if (!x) { - // Segments are parallel, should already be handled by t-junctions - continue - } - var idx = floatPoints.length - floatPoints.push([ratToFloat(x[0]), ratToFloat(x[1])]) - ratPoints.push(x) - junctions.push([e, idx], [f, idx]) - } - - // Sort tjunctions - junctions.sort(function (a, b) { - if (a[0] !== b[0]) { - return a[0] - b[0] - } - var u = ratPoints[a[1]] - var v = ratPoints[b[1]] - return ratCmp(u[0], v[0]) || ratCmp(u[1], v[1]) - }) - - // Split edges along junctions - for (i = junctions.length - 1; i >= 0; --i) { - var junction = junctions[i] - e = junction[0] - - var edge = edges[e] - var s = edge[0] - var t = edge[1] - - // Check if edge is not lexicographically sorted - var a = floatPoints[s] - var b = floatPoints[t] - if (((a[0] - b[0]) || (a[1] - b[1])) < 0) { - var tmp = s - s = t - t = tmp - } - - // Split leading edge - edge[0] = s - var last = edge[1] = junction[1] - - // If we are grouping edges by color, remember to track data - var color - if (useColor) { - color = edge[2] - } - - // Split other edges - while (i > 0 && junctions[i - 1][0] === e) { - var junction = junctions[--i] - var next = junction[1] - if (useColor) { - edges.push([last, next, color]) - } else { - edges.push([last, next]) - } - last = next - } - - // Add final edge - if (useColor) { - edges.push([last, t, color]) - } else { - edges.push([last, t]) - } - } - - // Return constructed rational points - return ratPoints -} - -// Merge overlapping points -function dedupPoints (floatPoints, ratPoints, floatBounds) { - var numPoints = ratPoints.length - var uf = new UnionFind(numPoints) - - // Compute rational bounds - var bounds = [] - for (var i = 0; i < ratPoints.length; ++i) { - var p = ratPoints[i] - var xb = boundRat(p[0]) - var yb = boundRat(p[1]) - bounds.push([ - nextafter(xb[0], -Infinity), - nextafter(yb[0], -Infinity), - nextafter(xb[1], Infinity), - nextafter(yb[1], Infinity) - ]) - } - - // Link all points with over lapping boxes - boxIntersect(bounds, function (i, j) { - uf.link(i, j) - }) - - // Do 1 pass over points to combine points in label sets - var noDupes = true - var labels = new Array(numPoints) - for (var i = 0; i < numPoints; ++i) { - var j = uf.find(i) - if (j !== i) { - // Clear no-dupes flag, zero out label - noDupes = false - // Make each point the top-left point from its cell - floatPoints[j] = [ - Math.min(floatPoints[i][0], floatPoints[j][0]), - Math.min(floatPoints[i][1], floatPoints[j][1]) - ] - } - } - - // If no duplicates, return null to signal termination - if (noDupes) { - return null - } - - var ptr = 0 - for (var i = 0; i < numPoints; ++i) { - var j = uf.find(i) - if (j === i) { - labels[i] = ptr - floatPoints[ptr++] = floatPoints[i] - } else { - labels[i] = -1 - } - } - - floatPoints.length = ptr - - // Do a second pass to fix up missing labels - for (var i = 0; i < numPoints; ++i) { - if (labels[i] < 0) { - labels[i] = labels[uf.find(i)] - } - } - - // Return resulting union-find data structure - return labels -} - -function compareLex2 (a, b) { return (a[0] - b[0]) || (a[1] - b[1]) } -function compareLex3 (a, b) { - var d = (a[0] - b[0]) || (a[1] - b[1]) - if (d) { - return d - } - if (a[2] < b[2]) { - return -1 - } else if (a[2] > b[2]) { - return 1 - } - return 0 -} - -// Remove duplicate edge labels -function dedupEdges (edges, labels, useColor) { - if (edges.length === 0) { - return - } - if (labels) { - for (var i = 0; i < edges.length; ++i) { - var e = edges[i] - var a = labels[e[0]] - var b = labels[e[1]] - e[0] = Math.min(a, b) - e[1] = Math.max(a, b) - } - } else { - for (var i = 0; i < edges.length; ++i) { - var e = edges[i] - var a = e[0] - var b = e[1] - e[0] = Math.min(a, b) - e[1] = Math.max(a, b) - } - } - if (useColor) { - edges.sort(compareLex3) - } else { - edges.sort(compareLex2) - } - var ptr = 1 - for (var i = 1; i < edges.length; ++i) { - var prev = edges[i - 1] - var next = edges[i] - if (next[0] === prev[0] && next[1] === prev[1] && - (!useColor || next[2] === prev[2])) { - continue - } - edges[ptr++] = next - } - edges.length = ptr -} - -function preRound (points, edges, useColor) { - var labels = dedupPoints(points, [], boundPoints(points)) - dedupEdges(edges, labels, useColor) - return !!labels -} - -// Repeat until convergence -function snapRound (points, edges, useColor) { - // 1. find edge crossings - var edgeBounds = boundEdges(points, edges) - var crossings = getCrossings(points, edges, edgeBounds) - - // 2. find t-junctions - var vertBounds = boundPoints(points) - var tjunctions = getTJunctions(points, edges, edgeBounds, vertBounds) - - // 3. cut edges, construct rational points - var ratPoints = cutEdges(points, edges, crossings, tjunctions, useColor) - - // 4. dedupe verts - var labels = dedupPoints(points, ratPoints, vertBounds) - - // 5. dedupe edges - dedupEdges(edges, labels, useColor) - - // 6. check termination - if (!labels) { - return (crossings.length > 0 || tjunctions.length > 0) - } - - // More iterations necessary - return true -} - -// Main loop, runs PSLG clean up until completion -function cleanPSLG (points, edges, colors) { - // If using colors, augment edges with color data - var prevEdges - if (colors) { - prevEdges = edges - var augEdges = new Array(edges.length) - for (var i = 0; i < edges.length; ++i) { - var e = edges[i] - augEdges[i] = [e[0], e[1], colors[i]] - } - edges = augEdges - } - - // First round: remove duplicate edges and points - var modified = preRound(points, edges, !!colors) - - // Run snap rounding until convergence - while (snapRound(points, edges, !!colors)) { - modified = true - } - - // Strip color tags - if (!!colors && modified) { - prevEdges.length = 0 - colors.length = 0 - for (var i = 0; i < edges.length; ++i) { - var e = edges[i] - prevEdges.push([e[0], e[1]]) - colors.push(e[2]) - } - } - - return modified -} - -},{"./lib/rat-seg-intersect":117,"big-rat":78,"big-rat/cmp":76,"big-rat/to-float":90,"box-intersect":96,"nextafter":451,"rat-vec":486,"robust-segment-intersect":513,"union-find":546}],117:[function(_dereq_,module,exports){ -'use strict' - -module.exports = solveIntersection - -var ratMul = _dereq_('big-rat/mul') -var ratDiv = _dereq_('big-rat/div') -var ratSub = _dereq_('big-rat/sub') -var ratSign = _dereq_('big-rat/sign') -var rvSub = _dereq_('rat-vec/sub') -var rvAdd = _dereq_('rat-vec/add') -var rvMuls = _dereq_('rat-vec/muls') - -function ratPerp (a, b) { - return ratSub(ratMul(a[0], b[1]), ratMul(a[1], b[0])) -} - -// Solve for intersection -// x = a + t (b-a) -// (x - c) ^ (d-c) = 0 -// (t * (b-a) + (a-c) ) ^ (d-c) = 0 -// t * (b-a)^(d-c) = (d-c)^(a-c) -// t = (d-c)^(a-c) / (b-a)^(d-c) - -function solveIntersection (a, b, c, d) { - var ba = rvSub(b, a) - var dc = rvSub(d, c) - - var baXdc = ratPerp(ba, dc) - - if (ratSign(baXdc) === 0) { - return null - } - - var ac = rvSub(a, c) - var dcXac = ratPerp(dc, ac) - - var t = ratDiv(dcXac, baXdc) - var s = rvMuls(ba, t) - var r = rvAdd(a, s) - - return r -} - -},{"big-rat/div":77,"big-rat/mul":87,"big-rat/sign":88,"big-rat/sub":89,"rat-vec/add":485,"rat-vec/muls":487,"rat-vec/sub":488}],118:[function(_dereq_,module,exports){ -/** @module color-id */ - -'use strict' - -var clamp = _dereq_('clamp') - -module.exports = toNumber -module.exports.to = toNumber -module.exports.from = fromNumber - -function toNumber (rgba, normalized) { - if(normalized == null) normalized = true - - var r = rgba[0], g = rgba[1], b = rgba[2], a = rgba[3] - - if (a == null) a = normalized ? 1 : 255 - - if (normalized) { - r *= 255 - g *= 255 - b *= 255 - a *= 255 - } - - r = clamp(r, 0, 255) & 0xFF - g = clamp(g, 0, 255) & 0xFF - b = clamp(b, 0, 255) & 0xFF - a = clamp(a, 0, 255) & 0xFF - - //hi-order shift converts to -1, so we can't use <<24 - var n = (r * 0x01000000) + (g << 16) + (b << 8) + (a) - - return n -} - -function fromNumber (n, normalized) { - n = +n - - var r = n >>> 24 - var g = (n & 0x00ff0000) >>> 16 - var b = (n & 0x0000ff00) >>> 8 - var a = n & 0x000000ff - - if (normalized === false) return [r, g, b, a] - - return [r/255, g/255, b/255, a/255] -} - -},{"clamp":115}],119:[function(_dereq_,module,exports){ -'use strict' - -module.exports = { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255, 235, 205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategray": [47, 79, 79], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "grey": [128, 128, 128], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "rebeccapurple": [102, 51, 153], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50] -}; - -},{}],120:[function(_dereq_,module,exports){ -/** @module color-normalize */ - -'use strict' - -var rgba = _dereq_('color-rgba') -var clamp = _dereq_('clamp') -var dtype = _dereq_('dtype') - -module.exports = function normalize (color, type) { - if (type === 'float' || !type) type = 'array' - if (type === 'uint') type = 'uint8' - if (type === 'uint_clamped') type = 'uint8_clamped' - var Ctor = dtype(type) - var output = new Ctor(4) - - var normalize = type !== 'uint8' && type !== 'uint8_clamped' - - // attempt to parse non-array arguments - if (!color.length || typeof color === 'string') { - color = rgba(color) - color[0] /= 255 - color[1] /= 255 - color[2] /= 255 - } - - // 0, 1 are possible contradictory values for Arrays: - // [1,1,1] input gives [1,1,1] output instead of [1/255,1/255,1/255], which may be collision if input is meant to be uint. - // converting [1,1,1] to [1/255,1/255,1/255] in case of float input gives larger mistake since [1,1,1] float is frequent edge value, whereas [0,1,1], [1,1,1] etc. uint inputs are relatively rare - if (isInt(color)) { - output[0] = color[0] - output[1] = color[1] - output[2] = color[2] - output[3] = color[3] != null ? color[3] : 255 - - if (normalize) { - output[0] /= 255 - output[1] /= 255 - output[2] /= 255 - output[3] /= 255 - } - - return output - } - - if (!normalize) { - output[0] = clamp(Math.floor(color[0] * 255), 0, 255) - output[1] = clamp(Math.floor(color[1] * 255), 0, 255) - output[2] = clamp(Math.floor(color[2] * 255), 0, 255) - output[3] = color[3] == null ? 255 : clamp(Math.floor(color[3] * 255), 0, 255) - } else { - output[0] = color[0] - output[1] = color[1] - output[2] = color[2] - output[3] = color[3] != null ? color[3] : 1 - } - - return output -} - -function isInt(color) { - if (color instanceof Uint8Array || color instanceof Uint8ClampedArray) return true - - if (Array.isArray(color) && - (color[0] > 1 || color[0] === 0) && - (color[1] > 1 || color[1] === 0) && - (color[2] > 1 || color[2] === 0) && - (!color[3] || color[3] > 1) - ) return true - - return false -} - -},{"clamp":115,"color-rgba":122,"dtype":169}],121:[function(_dereq_,module,exports){ -(function (global){ -/** - * @module color-parse - */ - -'use strict' - -var names = _dereq_('color-name') -var isObject = _dereq_('is-plain-obj') -var defined = _dereq_('defined') - -module.exports = parse - -/** - * Base hues - * http://dev.w3.org/csswg/css-color/#typedef-named-hue - */ -//FIXME: use external hue detector -var baseHues = { - red: 0, - orange: 60, - yellow: 120, - green: 180, - blue: 240, - purple: 300 -} - -/** - * Parse color from the string passed - * - * @return {Object} A space indicator `space`, an array `values` and `alpha` - */ -function parse (cstr) { - var m, parts = [], alpha = 1, space - - if (typeof cstr === 'string') { - //keyword - if (names[cstr]) { - parts = names[cstr].slice() - space = 'rgb' - } - - //reserved words - else if (cstr === 'transparent') { - alpha = 0 - space = 'rgb' - parts = [0,0,0] - } - - //hex - else if (/^#[A-Fa-f0-9]+$/.test(cstr)) { - var base = cstr.slice(1) - var size = base.length - var isShort = size <= 4 - alpha = 1 - - if (isShort) { - parts = [ - parseInt(base[0] + base[0], 16), - parseInt(base[1] + base[1], 16), - parseInt(base[2] + base[2], 16) - ] - if (size === 4) { - alpha = parseInt(base[3] + base[3], 16) / 255 - } - } - else { - parts = [ - parseInt(base[0] + base[1], 16), - parseInt(base[2] + base[3], 16), - parseInt(base[4] + base[5], 16) - ] - if (size === 8) { - alpha = parseInt(base[6] + base[7], 16) / 255 - } - } - - if (!parts[0]) parts[0] = 0 - if (!parts[1]) parts[1] = 0 - if (!parts[2]) parts[2] = 0 - - space = 'rgb' - } - - //color space - else if (m = /^((?:rgb|hs[lvb]|hwb|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms)a?)\s*\(([^\)]*)\)/.exec(cstr)) { - var name = m[1] - var isRGB = name === 'rgb' - var base = name.replace(/a$/, '') - space = base - var size = base === 'cmyk' ? 4 : base === 'gray' ? 1 : 3 - parts = m[2].trim() - .split(/\s*,\s*/) - .map(function (x, i) { - // - if (/%$/.test(x)) { - //alpha - if (i === size) return parseFloat(x) / 100 - //rgb - if (base === 'rgb') return parseFloat(x) * 255 / 100 - return parseFloat(x) - } - //hue - else if (base[i] === 'h') { - // - if (/deg$/.test(x)) { - return parseFloat(x) - } - // - else if (baseHues[x] !== undefined) { - return baseHues[x] - } - } - return parseFloat(x) - }) - - if (name === base) parts.push(1) - alpha = (isRGB) ? 1 : (parts[size] === undefined) ? 1 : parts[size] - parts = parts.slice(0, size) - } - - //named channels case - else if (cstr.length > 10 && /[0-9](?:\s|\/)/.test(cstr)) { - parts = cstr.match(/([0-9]+)/g).map(function (value) { - return parseFloat(value) - }) - - space = cstr.match(/([a-z])/ig).join('').toLowerCase() - } - } - - //numeric case - else if (!isNaN(cstr)) { - space = 'rgb' - parts = [cstr >>> 16, (cstr & 0x00ff00) >>> 8, cstr & 0x0000ff] - } - - //object case - detects css cases of rgb and hsl - else if (isObject(cstr)) { - var r = defined(cstr.r, cstr.red, cstr.R, null) - - if (r !== null) { - space = 'rgb' - parts = [ - r, - defined(cstr.g, cstr.green, cstr.G), - defined(cstr.b, cstr.blue, cstr.B) - ] - } - else { - space = 'hsl' - parts = [ - defined(cstr.h, cstr.hue, cstr.H), - defined(cstr.s, cstr.saturation, cstr.S), - defined(cstr.l, cstr.lightness, cstr.L, cstr.b, cstr.brightness) - ] - } - - alpha = defined(cstr.a, cstr.alpha, cstr.opacity, 1) - - if (cstr.opacity != null) alpha /= 100 - } - - //array - else if (Array.isArray(cstr) || global.ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(cstr)) { - parts = [cstr[0], cstr[1], cstr[2]] - space = 'rgb' - alpha = cstr.length === 4 ? cstr[3] : 1 - } - - return { - space: space, - values: parts, - alpha: alpha - } -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"color-name":119,"defined":164,"is-plain-obj":422}],122:[function(_dereq_,module,exports){ -/** @module color-rgba */ - -'use strict' - -var parse = _dereq_('color-parse') -var hsl = _dereq_('color-space/hsl') -var clamp = _dereq_('clamp') - -module.exports = function rgba (color) { - var values, i, l - - //attempt to parse non-array arguments - var parsed = parse(color) - - if (!parsed.space) return [] - - values = Array(3) - values[0] = clamp(parsed.values[0], 0, 255) - values[1] = clamp(parsed.values[1], 0, 255) - values[2] = clamp(parsed.values[2], 0, 255) - - if (parsed.space[0] === 'h') { - values = hsl.rgb(values) - } - - values.push(clamp(parsed.alpha, 0, 1)) - - return values -} - -},{"clamp":115,"color-parse":121,"color-space/hsl":123}],123:[function(_dereq_,module,exports){ -/** - * @module color-space/hsl - */ -'use strict' - -var rgb = _dereq_('./rgb'); - -module.exports = { - name: 'hsl', - min: [0,0,0], - max: [360,100,100], - channel: ['hue', 'saturation', 'lightness'], - alias: ['HSL'], - - rgb: function(hsl) { - var h = hsl[0] / 360, - s = hsl[1] / 100, - l = hsl[2] / 100, - t1, t2, t3, rgb, val; - - if (s === 0) { - val = l * 255; - return [val, val, val]; - } - - if (l < 0.5) { - t2 = l * (1 + s); - } - else { - t2 = l + s - l * s; - } - t1 = 2 * l - t2; - - rgb = [0, 0, 0]; - for (var i = 0; i < 3; i++) { - t3 = h + 1 / 3 * - (i - 1); - if (t3 < 0) { - t3++; - } - else if (t3 > 1) { - t3--; - } - - if (6 * t3 < 1) { - val = t1 + (t2 - t1) * 6 * t3; - } - else if (2 * t3 < 1) { - val = t2; - } - else if (3 * t3 < 2) { - val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; - } - else { - val = t1; - } - - rgb[i] = val * 255; - } - - return rgb; - } -}; - - -//extend rgb -rgb.hsl = function(rgb) { - var r = rgb[0]/255, - g = rgb[1]/255, - b = rgb[2]/255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - delta = max - min, - h, s, l; - - if (max === min) { - h = 0; - } - else if (r === max) { - h = (g - b) / delta; - } - else if (g === max) { - h = 2 + (b - r) / delta; - } - else if (b === max) { - h = 4 + (r - g)/ delta; - } - - h = Math.min(h * 60, 360); - - if (h < 0) { - h += 360; - } - - l = (min + max) / 2; - - if (max === min) { - s = 0; - } - else if (l <= 0.5) { - s = delta / (max + min); - } - else { - s = delta / (2 - max - min); - } - - return [h, s * 100, l * 100]; -}; - -},{"./rgb":124}],124:[function(_dereq_,module,exports){ -/** - * RGB space. - * - * @module color-space/rgb - */ -'use strict' - -module.exports = { - name: 'rgb', - min: [0,0,0], - max: [255,255,255], - channel: ['red', 'green', 'blue'], - alias: ['RGB'] -}; - -},{}],125:[function(_dereq_,module,exports){ -module.exports={ - "jet":[{"index":0,"rgb":[0,0,131]},{"index":0.125,"rgb":[0,60,170]},{"index":0.375,"rgb":[5,255,255]},{"index":0.625,"rgb":[255,255,0]},{"index":0.875,"rgb":[250,0,0]},{"index":1,"rgb":[128,0,0]}], - - "hsv":[{"index":0,"rgb":[255,0,0]},{"index":0.169,"rgb":[253,255,2]},{"index":0.173,"rgb":[247,255,2]},{"index":0.337,"rgb":[0,252,4]},{"index":0.341,"rgb":[0,252,10]},{"index":0.506,"rgb":[1,249,255]},{"index":0.671,"rgb":[2,0,253]},{"index":0.675,"rgb":[8,0,253]},{"index":0.839,"rgb":[255,0,251]},{"index":0.843,"rgb":[255,0,245]},{"index":1,"rgb":[255,0,6]}], - - "hot":[{"index":0,"rgb":[0,0,0]},{"index":0.3,"rgb":[230,0,0]},{"index":0.6,"rgb":[255,210,0]},{"index":1,"rgb":[255,255,255]}], - - "cool":[{"index":0,"rgb":[0,255,255]},{"index":1,"rgb":[255,0,255]}], - - "spring":[{"index":0,"rgb":[255,0,255]},{"index":1,"rgb":[255,255,0]}], - - "summer":[{"index":0,"rgb":[0,128,102]},{"index":1,"rgb":[255,255,102]}], - - "autumn":[{"index":0,"rgb":[255,0,0]},{"index":1,"rgb":[255,255,0]}], - - "winter":[{"index":0,"rgb":[0,0,255]},{"index":1,"rgb":[0,255,128]}], - - "bone":[{"index":0,"rgb":[0,0,0]},{"index":0.376,"rgb":[84,84,116]},{"index":0.753,"rgb":[169,200,200]},{"index":1,"rgb":[255,255,255]}], - - "copper":[{"index":0,"rgb":[0,0,0]},{"index":0.804,"rgb":[255,160,102]},{"index":1,"rgb":[255,199,127]}], - - "greys":[{"index":0,"rgb":[0,0,0]},{"index":1,"rgb":[255,255,255]}], - - "yignbu":[{"index":0,"rgb":[8,29,88]},{"index":0.125,"rgb":[37,52,148]},{"index":0.25,"rgb":[34,94,168]},{"index":0.375,"rgb":[29,145,192]},{"index":0.5,"rgb":[65,182,196]},{"index":0.625,"rgb":[127,205,187]},{"index":0.75,"rgb":[199,233,180]},{"index":0.875,"rgb":[237,248,217]},{"index":1,"rgb":[255,255,217]}], - - "greens":[{"index":0,"rgb":[0,68,27]},{"index":0.125,"rgb":[0,109,44]},{"index":0.25,"rgb":[35,139,69]},{"index":0.375,"rgb":[65,171,93]},{"index":0.5,"rgb":[116,196,118]},{"index":0.625,"rgb":[161,217,155]},{"index":0.75,"rgb":[199,233,192]},{"index":0.875,"rgb":[229,245,224]},{"index":1,"rgb":[247,252,245]}], - - "yiorrd":[{"index":0,"rgb":[128,0,38]},{"index":0.125,"rgb":[189,0,38]},{"index":0.25,"rgb":[227,26,28]},{"index":0.375,"rgb":[252,78,42]},{"index":0.5,"rgb":[253,141,60]},{"index":0.625,"rgb":[254,178,76]},{"index":0.75,"rgb":[254,217,118]},{"index":0.875,"rgb":[255,237,160]},{"index":1,"rgb":[255,255,204]}], - - "bluered":[{"index":0,"rgb":[0,0,255]},{"index":1,"rgb":[255,0,0]}], - - "rdbu":[{"index":0,"rgb":[5,10,172]},{"index":0.35,"rgb":[106,137,247]},{"index":0.5,"rgb":[190,190,190]},{"index":0.6,"rgb":[220,170,132]},{"index":0.7,"rgb":[230,145,90]},{"index":1,"rgb":[178,10,28]}], - - "picnic":[{"index":0,"rgb":[0,0,255]},{"index":0.1,"rgb":[51,153,255]},{"index":0.2,"rgb":[102,204,255]},{"index":0.3,"rgb":[153,204,255]},{"index":0.4,"rgb":[204,204,255]},{"index":0.5,"rgb":[255,255,255]},{"index":0.6,"rgb":[255,204,255]},{"index":0.7,"rgb":[255,153,255]},{"index":0.8,"rgb":[255,102,204]},{"index":0.9,"rgb":[255,102,102]},{"index":1,"rgb":[255,0,0]}], - - "rainbow":[{"index":0,"rgb":[150,0,90]},{"index":0.125,"rgb":[0,0,200]},{"index":0.25,"rgb":[0,25,255]},{"index":0.375,"rgb":[0,152,255]},{"index":0.5,"rgb":[44,255,150]},{"index":0.625,"rgb":[151,255,0]},{"index":0.75,"rgb":[255,234,0]},{"index":0.875,"rgb":[255,111,0]},{"index":1,"rgb":[255,0,0]}], - - "portland":[{"index":0,"rgb":[12,51,131]},{"index":0.25,"rgb":[10,136,186]},{"index":0.5,"rgb":[242,211,56]},{"index":0.75,"rgb":[242,143,56]},{"index":1,"rgb":[217,30,30]}], - - "blackbody":[{"index":0,"rgb":[0,0,0]},{"index":0.2,"rgb":[230,0,0]},{"index":0.4,"rgb":[230,210,0]},{"index":0.7,"rgb":[255,255,255]},{"index":1,"rgb":[160,200,255]}], - - "earth":[{"index":0,"rgb":[0,0,130]},{"index":0.1,"rgb":[0,180,180]},{"index":0.2,"rgb":[40,210,40]},{"index":0.4,"rgb":[230,230,50]},{"index":0.6,"rgb":[120,70,20]},{"index":1,"rgb":[255,255,255]}], - - "electric":[{"index":0,"rgb":[0,0,0]},{"index":0.15,"rgb":[30,0,100]},{"index":0.4,"rgb":[120,0,100]},{"index":0.6,"rgb":[160,90,0]},{"index":0.8,"rgb":[230,200,0]},{"index":1,"rgb":[255,250,220]}], - - "alpha": [{"index":0, "rgb": [255,255,255,0]},{"index":1, "rgb": [255,255,255,1]}], - - "viridis": [{"index":0,"rgb":[68,1,84]},{"index":0.13,"rgb":[71,44,122]},{"index":0.25,"rgb":[59,81,139]},{"index":0.38,"rgb":[44,113,142]},{"index":0.5,"rgb":[33,144,141]},{"index":0.63,"rgb":[39,173,129]},{"index":0.75,"rgb":[92,200,99]},{"index":0.88,"rgb":[170,220,50]},{"index":1,"rgb":[253,231,37]}], - - "inferno": [{"index":0,"rgb":[0,0,4]},{"index":0.13,"rgb":[31,12,72]},{"index":0.25,"rgb":[85,15,109]},{"index":0.38,"rgb":[136,34,106]},{"index":0.5,"rgb":[186,54,85]},{"index":0.63,"rgb":[227,89,51]},{"index":0.75,"rgb":[249,140,10]},{"index":0.88,"rgb":[249,201,50]},{"index":1,"rgb":[252,255,164]}], - - "magma": [{"index":0,"rgb":[0,0,4]},{"index":0.13,"rgb":[28,16,68]},{"index":0.25,"rgb":[79,18,123]},{"index":0.38,"rgb":[129,37,129]},{"index":0.5,"rgb":[181,54,122]},{"index":0.63,"rgb":[229,80,100]},{"index":0.75,"rgb":[251,135,97]},{"index":0.88,"rgb":[254,194,135]},{"index":1,"rgb":[252,253,191]}], - - "plasma": [{"index":0,"rgb":[13,8,135]},{"index":0.13,"rgb":[75,3,161]},{"index":0.25,"rgb":[125,3,168]},{"index":0.38,"rgb":[168,34,150]},{"index":0.5,"rgb":[203,70,121]},{"index":0.63,"rgb":[229,107,93]},{"index":0.75,"rgb":[248,148,65]},{"index":0.88,"rgb":[253,195,40]},{"index":1,"rgb":[240,249,33]}], - - "warm": [{"index":0,"rgb":[125,0,179]},{"index":0.13,"rgb":[172,0,187]},{"index":0.25,"rgb":[219,0,170]},{"index":0.38,"rgb":[255,0,130]},{"index":0.5,"rgb":[255,63,74]},{"index":0.63,"rgb":[255,123,0]},{"index":0.75,"rgb":[234,176,0]},{"index":0.88,"rgb":[190,228,0]},{"index":1,"rgb":[147,255,0]}], - - "cool": [{"index":0,"rgb":[125,0,179]},{"index":0.13,"rgb":[116,0,218]},{"index":0.25,"rgb":[98,74,237]},{"index":0.38,"rgb":[68,146,231]},{"index":0.5,"rgb":[0,204,197]},{"index":0.63,"rgb":[0,247,146]},{"index":0.75,"rgb":[0,255,88]},{"index":0.88,"rgb":[40,255,8]},{"index":1,"rgb":[147,255,0]}], - - "rainbow-soft": [{"index":0,"rgb":[125,0,179]},{"index":0.1,"rgb":[199,0,180]},{"index":0.2,"rgb":[255,0,121]},{"index":0.3,"rgb":[255,108,0]},{"index":0.4,"rgb":[222,194,0]},{"index":0.5,"rgb":[150,255,0]},{"index":0.6,"rgb":[0,255,55]},{"index":0.7,"rgb":[0,246,150]},{"index":0.8,"rgb":[50,167,222]},{"index":0.9,"rgb":[103,51,235]},{"index":1,"rgb":[124,0,186]}], - - "bathymetry": [{"index":0,"rgb":[40,26,44]},{"index":0.13,"rgb":[59,49,90]},{"index":0.25,"rgb":[64,76,139]},{"index":0.38,"rgb":[63,110,151]},{"index":0.5,"rgb":[72,142,158]},{"index":0.63,"rgb":[85,174,163]},{"index":0.75,"rgb":[120,206,163]},{"index":0.88,"rgb":[187,230,172]},{"index":1,"rgb":[253,254,204]}], - - "cdom": [{"index":0,"rgb":[47,15,62]},{"index":0.13,"rgb":[87,23,86]},{"index":0.25,"rgb":[130,28,99]},{"index":0.38,"rgb":[171,41,96]},{"index":0.5,"rgb":[206,67,86]},{"index":0.63,"rgb":[230,106,84]},{"index":0.75,"rgb":[242,149,103]},{"index":0.88,"rgb":[249,193,135]},{"index":1,"rgb":[254,237,176]}], - - "chlorophyll": [{"index":0,"rgb":[18,36,20]},{"index":0.13,"rgb":[25,63,41]},{"index":0.25,"rgb":[24,91,59]},{"index":0.38,"rgb":[13,119,72]},{"index":0.5,"rgb":[18,148,80]},{"index":0.63,"rgb":[80,173,89]},{"index":0.75,"rgb":[132,196,122]},{"index":0.88,"rgb":[175,221,162]},{"index":1,"rgb":[215,249,208]}], - - "density": [{"index":0,"rgb":[54,14,36]},{"index":0.13,"rgb":[89,23,80]},{"index":0.25,"rgb":[110,45,132]},{"index":0.38,"rgb":[120,77,178]},{"index":0.5,"rgb":[120,113,213]},{"index":0.63,"rgb":[115,151,228]},{"index":0.75,"rgb":[134,185,227]},{"index":0.88,"rgb":[177,214,227]},{"index":1,"rgb":[230,241,241]}], - - "freesurface-blue": [{"index":0,"rgb":[30,4,110]},{"index":0.13,"rgb":[47,14,176]},{"index":0.25,"rgb":[41,45,236]},{"index":0.38,"rgb":[25,99,212]},{"index":0.5,"rgb":[68,131,200]},{"index":0.63,"rgb":[114,156,197]},{"index":0.75,"rgb":[157,181,203]},{"index":0.88,"rgb":[200,208,216]},{"index":1,"rgb":[241,237,236]}], - - "freesurface-red": [{"index":0,"rgb":[60,9,18]},{"index":0.13,"rgb":[100,17,27]},{"index":0.25,"rgb":[142,20,29]},{"index":0.38,"rgb":[177,43,27]},{"index":0.5,"rgb":[192,87,63]},{"index":0.63,"rgb":[205,125,105]},{"index":0.75,"rgb":[216,162,148]},{"index":0.88,"rgb":[227,199,193]},{"index":1,"rgb":[241,237,236]}], - - "oxygen": [{"index":0,"rgb":[64,5,5]},{"index":0.13,"rgb":[106,6,15]},{"index":0.25,"rgb":[144,26,7]},{"index":0.38,"rgb":[168,64,3]},{"index":0.5,"rgb":[188,100,4]},{"index":0.63,"rgb":[206,136,11]},{"index":0.75,"rgb":[220,174,25]},{"index":0.88,"rgb":[231,215,44]},{"index":1,"rgb":[248,254,105]}], - - "par": [{"index":0,"rgb":[51,20,24]},{"index":0.13,"rgb":[90,32,35]},{"index":0.25,"rgb":[129,44,34]},{"index":0.38,"rgb":[159,68,25]},{"index":0.5,"rgb":[182,99,19]},{"index":0.63,"rgb":[199,134,22]},{"index":0.75,"rgb":[212,171,35]},{"index":0.88,"rgb":[221,210,54]},{"index":1,"rgb":[225,253,75]}], - - "phase": [{"index":0,"rgb":[145,105,18]},{"index":0.13,"rgb":[184,71,38]},{"index":0.25,"rgb":[186,58,115]},{"index":0.38,"rgb":[160,71,185]},{"index":0.5,"rgb":[110,97,218]},{"index":0.63,"rgb":[50,123,164]},{"index":0.75,"rgb":[31,131,110]},{"index":0.88,"rgb":[77,129,34]},{"index":1,"rgb":[145,105,18]}], - - "salinity": [{"index":0,"rgb":[42,24,108]},{"index":0.13,"rgb":[33,50,162]},{"index":0.25,"rgb":[15,90,145]},{"index":0.38,"rgb":[40,118,137]},{"index":0.5,"rgb":[59,146,135]},{"index":0.63,"rgb":[79,175,126]},{"index":0.75,"rgb":[120,203,104]},{"index":0.88,"rgb":[193,221,100]},{"index":1,"rgb":[253,239,154]}], - - "temperature": [{"index":0,"rgb":[4,35,51]},{"index":0.13,"rgb":[23,51,122]},{"index":0.25,"rgb":[85,59,157]},{"index":0.38,"rgb":[129,79,143]},{"index":0.5,"rgb":[175,95,130]},{"index":0.63,"rgb":[222,112,101]},{"index":0.75,"rgb":[249,146,66]},{"index":0.88,"rgb":[249,196,65]},{"index":1,"rgb":[232,250,91]}], - - "turbidity": [{"index":0,"rgb":[34,31,27]},{"index":0.13,"rgb":[65,50,41]},{"index":0.25,"rgb":[98,69,52]},{"index":0.38,"rgb":[131,89,57]},{"index":0.5,"rgb":[161,112,59]},{"index":0.63,"rgb":[185,140,66]},{"index":0.75,"rgb":[202,174,88]},{"index":0.88,"rgb":[216,209,126]},{"index":1,"rgb":[233,246,171]}], - - "velocity-blue": [{"index":0,"rgb":[17,32,64]},{"index":0.13,"rgb":[35,52,116]},{"index":0.25,"rgb":[29,81,156]},{"index":0.38,"rgb":[31,113,162]},{"index":0.5,"rgb":[50,144,169]},{"index":0.63,"rgb":[87,173,176]},{"index":0.75,"rgb":[149,196,189]},{"index":0.88,"rgb":[203,221,211]},{"index":1,"rgb":[254,251,230]}], - - "velocity-green": [{"index":0,"rgb":[23,35,19]},{"index":0.13,"rgb":[24,64,38]},{"index":0.25,"rgb":[11,95,45]},{"index":0.38,"rgb":[39,123,35]},{"index":0.5,"rgb":[95,146,12]},{"index":0.63,"rgb":[152,165,18]},{"index":0.75,"rgb":[201,186,69]},{"index":0.88,"rgb":[233,216,137]},{"index":1,"rgb":[255,253,205]}], - - "cubehelix": [{"index":0,"rgb":[0,0,0]},{"index":0.07,"rgb":[22,5,59]},{"index":0.13,"rgb":[60,4,105]},{"index":0.2,"rgb":[109,1,135]},{"index":0.27,"rgb":[161,0,147]},{"index":0.33,"rgb":[210,2,142]},{"index":0.4,"rgb":[251,11,123]},{"index":0.47,"rgb":[255,29,97]},{"index":0.53,"rgb":[255,54,69]},{"index":0.6,"rgb":[255,85,46]},{"index":0.67,"rgb":[255,120,34]},{"index":0.73,"rgb":[255,157,37]},{"index":0.8,"rgb":[241,191,57]},{"index":0.87,"rgb":[224,220,93]},{"index":0.93,"rgb":[218,241,142]},{"index":1,"rgb":[227,253,198]}] -}; - -},{}],126:[function(_dereq_,module,exports){ -/* - * Ben Postlethwaite - * January 2013 - * License MIT - */ -'use strict'; - -var colorScale = _dereq_('./colorScale'); -var lerp = _dereq_('lerp') - -module.exports = createColormap; - -function createColormap (spec) { - /* - * Default Options - */ - var indicies, fromrgba, torgba, - nsteps, cmap, colormap, format, - nshades, colors, alpha, i; - - if ( !spec ) spec = {}; - - nshades = (spec.nshades || 72) - 1; - format = spec.format || 'hex'; - - colormap = spec.colormap; - if (!colormap) colormap = 'jet'; - - if (typeof colormap === 'string') { - colormap = colormap.toLowerCase(); - - if (!colorScale[colormap]) { - throw Error(colormap + ' not a supported colorscale'); - } - - cmap = colorScale[colormap]; - - } else if (Array.isArray(colormap)) { - cmap = colormap.slice(); - - } else { - throw Error('unsupported colormap option', colormap); - } - - if (cmap.length > nshades + 1) { - throw new Error( - colormap+' map requires nshades to be at least size '+cmap.length - ); - } - - if (!Array.isArray(spec.alpha)) { - - if (typeof spec.alpha === 'number') { - alpha = [spec.alpha, spec.alpha]; - - } else { - alpha = [1, 1]; - } - - } else if (spec.alpha.length !== 2) { - alpha = [1, 1]; - - } else { - alpha = spec.alpha.slice(); - } - - // map index points from 0..1 to 0..n-1 - indicies = cmap.map(function(c) { - return Math.round(c.index * nshades); - }); - - // Add alpha channel to the map - alpha[0] = Math.min(Math.max(alpha[0], 0), 1); - alpha[1] = Math.min(Math.max(alpha[1], 0), 1); - - var steps = cmap.map(function(c, i) { - var index = cmap[i].index - - var rgba = cmap[i].rgb.slice(); - - // if user supplies their own map use it - if (rgba.length === 4 && rgba[3] >= 0 && rgba[3] <= 1) { - return rgba - } - rgba[3] = alpha[0] + (alpha[1] - alpha[0])*index; - - return rgba - }) - - - /* - * map increasing linear values between indicies to - * linear steps in colorvalues - */ - var colors = [] - for (i = 0; i < indicies.length-1; ++i) { - nsteps = indicies[i+1] - indicies[i]; - fromrgba = steps[i]; - torgba = steps[i+1]; - - for (var j = 0; j < nsteps; j++) { - var amt = j / nsteps - colors.push([ - Math.round(lerp(fromrgba[0], torgba[0], amt)), - Math.round(lerp(fromrgba[1], torgba[1], amt)), - Math.round(lerp(fromrgba[2], torgba[2], amt)), - lerp(fromrgba[3], torgba[3], amt) - ]) - } - } - - //add 1 step as last value - colors.push(cmap[cmap.length - 1].rgb.concat(alpha[1])) - - if (format === 'hex') colors = colors.map( rgb2hex ); - else if (format === 'rgbaString') colors = colors.map( rgbaStr ); - else if (format === 'float') colors = colors.map( rgb2float ); - - return colors; -}; - -function rgb2float (rgba) { - return [ - rgba[0] / 255, - rgba[1] / 255, - rgba[2] / 255, - rgba[3] - ] -} - -function rgb2hex (rgba) { - var dig, hex = '#'; - for (var i = 0; i < 3; ++i) { - dig = rgba[i]; - dig = dig.toString(16); - hex += ('00' + dig).substr( dig.length ); - } - return hex; -} - -function rgbaStr (rgba) { - return 'rgba(' + rgba.join(',') + ')'; -} - -},{"./colorScale":125,"lerp":425}],127:[function(_dereq_,module,exports){ -"use strict" - -module.exports = compareAngle - -var orient = _dereq_("robust-orientation") -var sgn = _dereq_("signum") -var twoSum = _dereq_("two-sum") -var robustProduct = _dereq_("robust-product") -var robustSum = _dereq_("robust-sum") - -function testInterior(a, b, c) { - var x0 = twoSum(a[0], -b[0]) - var y0 = twoSum(a[1], -b[1]) - var x1 = twoSum(c[0], -b[0]) - var y1 = twoSum(c[1], -b[1]) - - var d = robustSum( - robustProduct(x0, x1), - robustProduct(y0, y1)) - - return d[d.length-1] >= 0 -} - -function compareAngle(a, b, c, d) { - var bcd = orient(b, c, d) - if(bcd === 0) { - //Handle degenerate cases - var sabc = sgn(orient(a, b, c)) - var sabd = sgn(orient(a, b, d)) - if(sabc === sabd) { - if(sabc === 0) { - var ic = testInterior(a, b, c) - var id = testInterior(a, b, d) - if(ic === id) { - return 0 - } else if(ic) { - return 1 - } else { - return -1 - } - } - return 0 - } else if(sabd === 0) { - if(sabc > 0) { - return -1 - } else if(testInterior(a, b, d)) { - return -1 - } else { - return 1 - } - } else if(sabc === 0) { - if(sabd > 0) { - return 1 - } else if(testInterior(a, b, c)) { - return 1 - } else { - return -1 - } - } - return sgn(sabd - sabc) - } - var abc = orient(a, b, c) - if(abc > 0) { - if(bcd > 0 && orient(a, b, d) > 0) { - return 1 - } - return -1 - } else if(abc < 0) { - if(bcd > 0 || orient(a, b, d) > 0) { - return 1 - } - return -1 - } else { - var abd = orient(a, b, d) - if(abd > 0) { - return 1 - } else { - if(testInterior(a, b, c)) { - return 1 - } else { - return -1 - } - } - } -} -},{"robust-orientation":510,"robust-product":511,"robust-sum":515,"signum":516,"two-sum":544}],128:[function(_dereq_,module,exports){ -module.exports = compareCells - -var min = Math.min - -function compareInt(a, b) { - return a - b -} - -function compareCells(a, b) { - var n = a.length - , t = a.length - b.length - if(t) { - return t - } - switch(n) { - case 0: - return 0 - case 1: - return a[0] - b[0] - case 2: - return (a[0]+a[1]-b[0]-b[1]) || - min(a[0],a[1]) - min(b[0],b[1]) - case 3: - var l1 = a[0]+a[1] - , m1 = b[0]+b[1] - t = l1+a[2] - (m1+b[2]) - if(t) { - return t - } - var l0 = min(a[0], a[1]) - , m0 = min(b[0], b[1]) - return min(l0, a[2]) - min(m0, b[2]) || - min(l0+a[2], l1) - min(m0+b[2], m1) - case 4: - var aw=a[0], ax=a[1], ay=a[2], az=a[3] - , bw=b[0], bx=b[1], by=b[2], bz=b[3] - return (aw+ax+ay+az)-(bw+bx+by+bz) || - min(aw,ax,ay,az)-min(bw,bx,by,bz,bw) || - min(aw+ax,aw+ay,aw+az,ax+ay,ax+az,ay+az) - - min(bw+bx,bw+by,bw+bz,bx+by,bx+bz,by+bz) || - min(aw+ax+ay,aw+ax+az,aw+ay+az,ax+ay+az) - - min(bw+bx+by,bw+bx+bz,bw+by+bz,bx+by+bz) - default: - var as = a.slice().sort(compareInt) - var bs = b.slice().sort(compareInt) - for(var i=0; i points[hi][0]) { - hi = i - } - } - if(lo < hi) { - return [[lo], [hi]] - } else if(lo > hi) { - return [[hi], [lo]] - } else { - return [[lo]] - } -} -},{}],132:[function(_dereq_,module,exports){ -'use strict' - -module.exports = convexHull2D - -var monotoneHull = _dereq_('monotone-convex-hull-2d') - -function convexHull2D(points) { - var hull = monotoneHull(points) - var h = hull.length - if(h <= 2) { - return [] - } - var edges = new Array(h) - var a = hull[h-1] - for(var i=0; i= front[k]) { - x += 1 - } - } - c[j] = x - } - } - } - return cells -} - -function convexHullnD(points, d) { - try { - return ich(points, true) - } catch(e) { - //If point set is degenerate, try to find a basis and rerun it - var ah = aff(points) - if(ah.length <= d) { - //No basis, no try - return [] - } - var npoints = permute(points, ah) - var nhull = ich(npoints, true) - return invPermute(nhull, ah) - } -} -},{"affine-hull":62,"incremental-convex-hull":413}],134:[function(_dereq_,module,exports){ -module.exports = { - AFG: 'afghan', - ALA: '\\b\\wland', - ALB: 'albania', - DZA: 'algeria', - ASM: '^(?=.*americ).*samoa', - AND: 'andorra', - AGO: 'angola', - AIA: 'anguill?a', - ATA: 'antarctica', - ATG: 'antigua', - ARG: 'argentin', - ARM: 'armenia', - ABW: '^(?!.*bonaire).*\\baruba', - AUS: 'australia', - AUT: '^(?!.*hungary).*austria|\\baustri.*\\bemp', - AZE: 'azerbaijan', - BHS: 'bahamas', - BHR: 'bahrain', - BGD: 'bangladesh|^(?=.*east).*paki?stan', - BRB: 'barbados', - BLR: 'belarus|byelo', - BEL: '^(?!.*luxem).*belgium', - BLZ: 'belize|^(?=.*british).*honduras', - BEN: 'benin|dahome', - BMU: 'bermuda', - BTN: 'bhutan', - BOL: 'bolivia', - BES: '^(?=.*bonaire).*eustatius|^(?=.*carib).*netherlands|\\bbes.?islands', - BIH: 'herzegovina|bosnia', - BWA: 'botswana|bechuana', - BVT: 'bouvet', - BRA: 'brazil', - IOT: 'british.?indian.?ocean', - BRN: 'brunei', - BGR: 'bulgaria', - BFA: 'burkina|\\bfaso|upper.?volta', - BDI: 'burundi', - CPV: 'verde', - KHM: 'cambodia|kampuchea|khmer', - CMR: 'cameroon', - CAN: 'canada', - CYM: 'cayman', - CAF: '\\bcentral.african.republic', - TCD: '\\bchad', - CHL: '\\bchile', - CHN: '^(?!.*\\bmac)(?!.*\\bhong)(?!.*\\btai)(?!.*\\brep).*china|^(?=.*peo)(?=.*rep).*china', - CXR: 'christmas', - CCK: '\\bcocos|keeling', - COL: 'colombia', - COM: 'comoro', - COG: '^(?!.*\\bdem)(?!.*\\bd[\\.]?r)(?!.*kinshasa)(?!.*zaire)(?!.*belg)(?!.*l.opoldville)(?!.*free).*\\bcongo', - COK: '\\bcook', - CRI: 'costa.?rica', - CIV: 'ivoire|ivory', - HRV: 'croatia', - CUB: '\\bcuba', - CUW: '^(?!.*bonaire).*\\bcura(c|ç)ao', - CYP: 'cyprus', - CSK: 'czechoslovakia', - CZE: '^(?=.*rep).*czech|czechia|bohemia', - COD: '\\bdem.*congo|congo.*\\bdem|congo.*\\bd[\\.]?r|\\bd[\\.]?r.*congo|belgian.?congo|congo.?free.?state|kinshasa|zaire|l.opoldville|drc|droc|rdc', - DNK: 'denmark', - DJI: 'djibouti', - DMA: 'dominica(?!n)', - DOM: 'dominican.rep', - ECU: 'ecuador', - EGY: 'egypt', - SLV: 'el.?salvador', - GNQ: 'guine.*eq|eq.*guine|^(?=.*span).*guinea', - ERI: 'eritrea', - EST: 'estonia', - ETH: 'ethiopia|abyssinia', - FLK: 'falkland|malvinas', - FRO: 'faroe|faeroe', - FJI: 'fiji', - FIN: 'finland', - FRA: '^(?!.*\\bdep)(?!.*martinique).*france|french.?republic|\\bgaul', - GUF: '^(?=.*french).*guiana', - PYF: 'french.?polynesia|tahiti', - ATF: 'french.?southern', - GAB: 'gabon', - GMB: 'gambia', - GEO: '^(?!.*south).*georgia', - DDR: 'german.?democratic.?republic|democratic.?republic.*germany|east.germany', - DEU: '^(?!.*east).*germany|^(?=.*\\bfed.*\\brep).*german', - GHA: 'ghana|gold.?coast', - GIB: 'gibraltar', - GRC: 'greece|hellenic|hellas', - GRL: 'greenland', - GRD: 'grenada', - GLP: 'guadeloupe', - GUM: '\\bguam', - GTM: 'guatemala', - GGY: 'guernsey', - GIN: '^(?!.*eq)(?!.*span)(?!.*bissau)(?!.*portu)(?!.*new).*guinea', - GNB: 'bissau|^(?=.*portu).*guinea', - GUY: 'guyana|british.?guiana', - HTI: 'haiti', - HMD: 'heard.*mcdonald', - VAT: 'holy.?see|vatican|papal.?st', - HND: '^(?!.*brit).*honduras', - HKG: 'hong.?kong', - HUN: '^(?!.*austr).*hungary', - ISL: 'iceland', - IND: 'india(?!.*ocea)', - IDN: 'indonesia', - IRN: '\\biran|persia', - IRQ: '\\biraq|mesopotamia', - IRL: '(^ireland)|(^republic.*ireland)', - IMN: '^(?=.*isle).*\\bman', - ISR: 'israel', - ITA: 'italy', - JAM: 'jamaica', - JPN: 'japan', - JEY: 'jersey', - JOR: 'jordan', - KAZ: 'kazak', - KEN: 'kenya|british.?east.?africa|east.?africa.?prot', - KIR: 'kiribati', - PRK: '^(?=.*democrat|people|north|d.*p.*.r).*\\bkorea|dprk|korea.*(d.*p.*r)', - KWT: 'kuwait', - KGZ: 'kyrgyz|kirghiz', - LAO: '\\blaos?\\b', - LVA: 'latvia', - LBN: 'lebanon', - LSO: 'lesotho|basuto', - LBR: 'liberia', - LBY: 'libya', - LIE: 'liechtenstein', - LTU: 'lithuania', - LUX: '^(?!.*belg).*luxem', - MAC: 'maca(o|u)', - MDG: 'madagascar|malagasy', - MWI: 'malawi|nyasa', - MYS: 'malaysia', - MDV: 'maldive', - MLI: '\\bmali\\b', - MLT: '\\bmalta', - MHL: 'marshall', - MTQ: 'martinique', - MRT: 'mauritania', - MUS: 'mauritius', - MYT: '\\bmayotte', - MEX: '\\bmexic', - FSM: 'fed.*micronesia|micronesia.*fed', - MCO: 'monaco', - MNG: 'mongolia', - MNE: '^(?!.*serbia).*montenegro', - MSR: 'montserrat', - MAR: 'morocco|\\bmaroc', - MOZ: 'mozambique', - MMR: 'myanmar|burma', - NAM: 'namibia', - NRU: 'nauru', - NPL: 'nepal', - NLD: '^(?!.*\\bant)(?!.*\\bcarib).*netherlands', - ANT: '^(?=.*\\bant).*(nether|dutch)', - NCL: 'new.?caledonia', - NZL: 'new.?zealand', - NIC: 'nicaragua', - NER: '\\bniger(?!ia)', - NGA: 'nigeria', - NIU: 'niue', - NFK: 'norfolk', - MNP: 'mariana', - NOR: 'norway', - OMN: '\\boman|trucial', - PAK: '^(?!.*east).*paki?stan', - PLW: 'palau', - PSE: 'palestin|\\bgaza|west.?bank', - PAN: 'panama', - PNG: 'papua|new.?guinea', - PRY: 'paraguay', - PER: 'peru', - PHL: 'philippines', - PCN: 'pitcairn', - POL: 'poland', - PRT: 'portugal', - PRI: 'puerto.?rico', - QAT: 'qatar', - KOR: '^(?!.*d.*p.*r)(?!.*democrat)(?!.*people)(?!.*north).*\\bkorea(?!.*d.*p.*r)', - MDA: 'moldov|b(a|e)ssarabia', - REU: 'r(e|é)union', - ROU: 'r(o|u|ou)mania', - RUS: '\\brussia|soviet.?union|u\\.?s\\.?s\\.?r|socialist.?republics', - RWA: 'rwanda', - BLM: 'barth(e|é)lemy', - SHN: 'helena', - KNA: 'kitts|\\bnevis', - LCA: '\\blucia', - MAF: '^(?=.*collectivity).*martin|^(?=.*france).*martin(?!ique)|^(?=.*french).*martin(?!ique)', - SPM: 'miquelon', - VCT: 'vincent', - WSM: '^(?!.*amer).*samoa', - SMR: 'san.?marino', - STP: '\\bs(a|ã)o.?tom(e|é)', - SAU: '\\bsa\\w*.?arabia', - SEN: 'senegal', - SRB: '^(?!.*monte).*serbia', - SYC: 'seychell', - SLE: 'sierra', - SGP: 'singapore', - SXM: '^(?!.*martin)(?!.*saba).*maarten', - SVK: '^(?!.*cze).*slovak', - SVN: 'slovenia', - SLB: 'solomon', - SOM: 'somali', - ZAF: 'south.africa|s\\\\..?africa', - SGS: 'south.?georgia|sandwich', - SSD: '\\bs\\w*.?sudan', - ESP: 'spain', - LKA: 'sri.?lanka|ceylon', - SDN: '^(?!.*\\bs(?!u)).*sudan', - SUR: 'surinam|dutch.?guiana', - SJM: 'svalbard', - SWZ: 'swaziland', - SWE: 'sweden', - CHE: 'switz|swiss', - SYR: 'syria', - TWN: 'taiwan|taipei|formosa|^(?!.*peo)(?=.*rep).*china', - TJK: 'tajik', - THA: 'thailand|\\bsiam', - MKD: 'macedonia|fyrom', - TLS: '^(?=.*leste).*timor|^(?=.*east).*timor', - TGO: 'togo', - TKL: 'tokelau', - TON: 'tonga', - TTO: 'trinidad|tobago', - TUN: 'tunisia', - TUR: 'turkey', - TKM: 'turkmen', - TCA: 'turks', - TUV: 'tuvalu', - UGA: 'uganda', - UKR: 'ukrain', - ARE: 'emirates|^u\\.?a\\.?e\\.?$|united.?arab.?em', - GBR: 'united.?kingdom|britain|^u\\.?k\\.?$', - TZA: 'tanzania', - USA: 'united.?states\\b(?!.*islands)|\\bu\\.?s\\.?a\\.?\\b|^\\s*u\\.?s\\.?\\b(?!.*islands)', - UMI: 'minor.?outlying.?is', - URY: 'uruguay', - UZB: 'uzbek', - VUT: 'vanuatu|new.?hebrides', - VEN: 'venezuela', - VNM: '^(?!.*republic).*viet.?nam|^(?=.*socialist).*viet.?nam', - VGB: '^(?=.*\\bu\\.?\\s?k).*virgin|^(?=.*brit).*virgin|^(?=.*kingdom).*virgin', - VIR: '^(?=.*\\bu\\.?\\s?s).*virgin|^(?=.*states).*virgin', - WLF: 'futuna|wallis', - ESH: 'western.sahara', - YEM: '^(?!.*arab)(?!.*north)(?!.*sana)(?!.*peo)(?!.*dem)(?!.*south)(?!.*aden)(?!.*\\bp\\.?d\\.?r).*yemen', - YMD: '^(?=.*peo).*yemen|^(?!.*rep)(?=.*dem).*yemen|^(?=.*south).*yemen|^(?=.*aden).*yemen|^(?=.*\\bp\\.?d\\.?r).*yemen', - YUG: 'yugoslavia', - ZMB: 'zambia|northern.?rhodesia', - EAZ: 'zanzibar', - ZWE: 'zimbabwe|^(?!.*northern).*rhodesia' -} - -},{}],135:[function(_dereq_,module,exports){ -module.exports=[ - "xx-small", - "x-small", - "small", - "medium", - "large", - "x-large", - "xx-large", - "larger", - "smaller" -] - -},{}],136:[function(_dereq_,module,exports){ -module.exports=[ - "normal", - "condensed", - "semi-condensed", - "extra-condensed", - "ultra-condensed", - "expanded", - "semi-expanded", - "extra-expanded", - "ultra-expanded" -] - -},{}],137:[function(_dereq_,module,exports){ -module.exports=[ - "normal", - "italic", - "oblique" -] - -},{}],138:[function(_dereq_,module,exports){ -module.exports=[ - "normal", - "bold", - "bolder", - "lighter", - "100", - "200", - "300", - "400", - "500", - "600", - "700", - "800", - "900" -] - -},{}],139:[function(_dereq_,module,exports){ -'use strict' - -module.exports = { - parse: _dereq_('./parse'), - stringify: _dereq_('./stringify') -} - -},{"./parse":141,"./stringify":142}],140:[function(_dereq_,module,exports){ -'use strict' - -var sizes = _dereq_('css-font-size-keywords') - -module.exports = { - isSize: function isSize(value) { - return /^[\d\.]/.test(value) - || value.indexOf('/') !== -1 - || sizes.indexOf(value) !== -1 - } -} - -},{"css-font-size-keywords":135}],141:[function(_dereq_,module,exports){ -'use strict' - -var unquote = _dereq_('unquote') -var globalKeywords = _dereq_('css-global-keywords') -var systemFontKeywords = _dereq_('css-system-font-keywords') -var fontWeightKeywords = _dereq_('css-font-weight-keywords') -var fontStyleKeywords = _dereq_('css-font-style-keywords') -var fontStretchKeywords = _dereq_('css-font-stretch-keywords') -var splitBy = _dereq_('string-split-by') -var isSize = _dereq_('./lib/util').isSize - - -module.exports = parseFont - - -var cache = parseFont.cache = {} - - -function parseFont (value) { - if (typeof value !== 'string') throw new Error('Font argument must be a string.') - - if (cache[value]) return cache[value] - - if (value === '') { - throw new Error('Cannot parse an empty string.') - } - - if (systemFontKeywords.indexOf(value) !== -1) { - return cache[value] = {system: value} - } - - var font = { - style: 'normal', - variant: 'normal', - weight: 'normal', - stretch: 'normal', - lineHeight: 'normal', - size: '1rem', - family: ['serif'] - } - - var tokens = splitBy(value, /\s+/) - var token - - while (token = tokens.shift()) { - if (globalKeywords.indexOf(token) !== -1) { - ['style', 'variant', 'weight', 'stretch'].forEach(function(prop) { - font[prop] = token - }) - - return cache[value] = font - } - - if (fontStyleKeywords.indexOf(token) !== -1) { - font.style = token - continue - } - - if (token === 'normal' || token === 'small-caps') { - font.variant = token - continue - } - - if (fontStretchKeywords.indexOf(token) !== -1) { - font.stretch = token - continue - } - - if (fontWeightKeywords.indexOf(token) !== -1) { - font.weight = token - continue - } - - - if (isSize(token)) { - var parts = splitBy(token, '/') - font.size = parts[0] - if (parts[1] != null) { - font.lineHeight = parseLineHeight(parts[1]) - } - else if (tokens[0] === '/') { - tokens.shift() - font.lineHeight = parseLineHeight(tokens.shift()) - } - - if (!tokens.length) { - throw new Error('Missing required font-family.') - } - font.family = splitBy(tokens.join(' '), /\s*,\s*/).map(unquote) - - return cache[value] = font - } - - throw new Error('Unknown or unsupported font token: ' + token) - } - - throw new Error('Missing required font-size.') -} - - -function parseLineHeight(value) { - var parsed = parseFloat(value) - if (parsed.toString() === value) { - return parsed - } - return value -} - -},{"./lib/util":140,"css-font-stretch-keywords":136,"css-font-style-keywords":137,"css-font-weight-keywords":138,"css-global-keywords":143,"css-system-font-keywords":144,"string-split-by":529,"unquote":548}],142:[function(_dereq_,module,exports){ -'use strict' - -var pick = _dereq_('pick-by-alias') -var isSize = _dereq_('./lib/util').isSize - -var globals = a2o(_dereq_('css-global-keywords')) -var systems = a2o(_dereq_('css-system-font-keywords')) -var weights = a2o(_dereq_('css-font-weight-keywords')) -var styles = a2o(_dereq_('css-font-style-keywords')) -var stretches = a2o(_dereq_('css-font-stretch-keywords')) - -var variants = {'normal': 1, 'small-caps': 1} -var fams = { - 'serif': 1, - 'sans-serif': 1, - 'monospace': 1, - 'cursive': 1, - 'fantasy': 1, - 'system-ui': 1 -} - -var defaults = { - style: 'normal', - variant: 'normal', - weight: 'normal', - stretch: 'normal', - size: '1rem', - lineHeight: 'normal', - family: 'serif' -} - -module.exports = function stringifyFont (o) { - o = pick(o, { - style: 'style fontstyle fontStyle font-style slope distinction', - variant: 'variant font-variant fontVariant fontvariant var capitalization', - weight: 'weight w font-weight fontWeight fontweight', - stretch: 'stretch font-stretch fontStretch fontstretch width', - size: 'size s font-size fontSize fontsize height em emSize', - lineHeight: 'lh line-height lineHeight lineheight leading', - family: 'font family fontFamily font-family fontfamily type typeface face', - system: 'system reserved default global', - }) - - if (o.system) { - if (o.system) verify(o.system, systems) - return o.system - } - - verify(o.style, styles) - verify(o.variant, variants) - verify(o.weight, weights) - verify(o.stretch, stretches) - - // default root value is medium, but by default it's inherited - if (o.size == null) o.size = defaults.size - if (typeof o.size === 'number') o.size += 'px' - - if (!isSize) throw Error('Bad size value `' + o.size + '`') - - // many user-agents use serif, we don't detect that for consistency - if (!o.family) o.family = defaults.family - if (Array.isArray(o.family)) { - if (!o.family.length) o.family = [defaults.family] - o.family = o.family.map(function (f) { - return fams[f] ? f : '"' + f + '"' - }).join(', ') - } - - // [ [ <'font-style'> || || <'font-weight'> || <'font-stretch'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] - var result = [] - - result.push(o.style) - if (o.variant !== o.style) result.push(o.variant) - - if (o.weight !== o.variant && - o.weight !== o.style) result.push(o.weight) - - if (o.stretch !== o.weight && - o.stretch !== o.variant && - o.stretch !== o.style) result.push(o.stretch) - - result.push(o.size + (o.lineHeight == null || o.lineHeight === 'normal' || (o.lineHeight + '' === '1') ? '' : ('/' + o.lineHeight))) - result.push(o.family) - - return result.filter(Boolean).join(' ') -} - -function verify (value, values) { - if (value && !values[value] && !globals[value]) throw Error('Unknown keyword `' + value +'`') - - return value -} - - -// ['a', 'b'] -> {a: true, b: true} -function a2o (a) { - var o = {} - for (var i = 0; i < a.length; i++) { - o[a[i]] = 1 - } - return o -} - -},{"./lib/util":140,"css-font-stretch-keywords":136,"css-font-style-keywords":137,"css-font-weight-keywords":138,"css-global-keywords":143,"css-system-font-keywords":144,"pick-by-alias":465}],143:[function(_dereq_,module,exports){ -module.exports=[ - "inherit", - "initial", - "unset" -] - -},{}],144:[function(_dereq_,module,exports){ -module.exports=[ - "caption", - "icon", - "menu", - "message-box", - "small-caption", - "status-bar" -] - -},{}],145:[function(_dereq_,module,exports){ -"use strict" - -function dcubicHermite(p0, v0, p1, v1, t, f) { - var dh00 = 6*t*t-6*t, - dh10 = 3*t*t-4*t + 1, - dh01 = -6*t*t+6*t, - dh11 = 3*t*t-2*t - if(p0.length) { - if(!f) { - f = new Array(p0.length) - } - for(var i=p0.length-1; i>=0; --i) { - f[i] = dh00*p0[i] + dh10*v0[i] + dh01*p1[i] + dh11*v1[i] - } - return f - } - return dh00*p0 + dh10*v0 + dh01*p1[i] + dh11*v1 -} - -function cubicHermite(p0, v0, p1, v1, t, f) { - var ti = (t-1), t2 = t*t, ti2 = ti*ti, - h00 = (1+2*t)*ti2, - h10 = t*ti2, - h01 = t2*(3-2*t), - h11 = t2*ti - if(p0.length) { - if(!f) { - f = new Array(p0.length) - } - for(var i=p0.length-1; i>=0; --i) { - f[i] = h00*p0[i] + h10*v0[i] + h01*p1[i] + h11*v1[i] - } - return f - } - return h00*p0 + h10*v0 + h01*p1 + h11*v1 -} - -module.exports = cubicHermite -module.exports.derivative = dcubicHermite -},{}],146:[function(_dereq_,module,exports){ -"use strict" - -var createThunk = _dereq_("./lib/thunk.js") - -function Procedure() { - this.argTypes = [] - this.shimArgs = [] - this.arrayArgs = [] - this.arrayBlockIndices = [] - this.scalarArgs = [] - this.offsetArgs = [] - this.offsetArgIndex = [] - this.indexArgs = [] - this.shapeArgs = [] - this.funcName = "" - this.pre = null - this.body = null - this.post = null - this.debug = false -} - -function compileCwise(user_args) { - //Create procedure - var proc = new Procedure() - - //Parse blocks - proc.pre = user_args.pre - proc.body = user_args.body - proc.post = user_args.post - - //Parse arguments - var proc_args = user_args.args.slice(0) - proc.argTypes = proc_args - for(var i=0; i0) { - throw new Error("cwise: pre() block may not reference array args") - } - if(i < proc.post.args.length && proc.post.args[i].count>0) { - throw new Error("cwise: post() block may not reference array args") - } - } else if(arg_type === "scalar") { - proc.scalarArgs.push(i) - proc.shimArgs.push("scalar" + i) - } else if(arg_type === "index") { - proc.indexArgs.push(i) - if(i < proc.pre.args.length && proc.pre.args[i].count > 0) { - throw new Error("cwise: pre() block may not reference array index") - } - if(i < proc.body.args.length && proc.body.args[i].lvalue) { - throw new Error("cwise: body() block may not write to array index") - } - if(i < proc.post.args.length && proc.post.args[i].count > 0) { - throw new Error("cwise: post() block may not reference array index") - } - } else if(arg_type === "shape") { - proc.shapeArgs.push(i) - if(i < proc.pre.args.length && proc.pre.args[i].lvalue) { - throw new Error("cwise: pre() block may not write to array shape") - } - if(i < proc.body.args.length && proc.body.args[i].lvalue) { - throw new Error("cwise: body() block may not write to array shape") - } - if(i < proc.post.args.length && proc.post.args[i].lvalue) { - throw new Error("cwise: post() block may not write to array shape") - } - } else if(typeof arg_type === "object" && arg_type.offset) { - proc.argTypes[i] = "offset" - proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset }) - proc.offsetArgIndex.push(i) - } else { - throw new Error("cwise: Unknown argument type " + proc_args[i]) - } - } - - //Make sure at least one array argument was specified - if(proc.arrayArgs.length <= 0) { - throw new Error("cwise: No array arguments specified") - } - - //Make sure arguments are correct - if(proc.pre.args.length > proc_args.length) { - throw new Error("cwise: Too many arguments in pre() block") - } - if(proc.body.args.length > proc_args.length) { - throw new Error("cwise: Too many arguments in body() block") - } - if(proc.post.args.length > proc_args.length) { - throw new Error("cwise: Too many arguments in post() block") - } - - //Check debug flag - proc.debug = !!user_args.printCode || !!user_args.debug - - //Retrieve name - proc.funcName = user_args.funcName || "cwise" - - //Read in block size - proc.blockSize = user_args.blockSize || 64 - - return createThunk(proc) -} - -module.exports = compileCwise - -},{"./lib/thunk.js":148}],147:[function(_dereq_,module,exports){ -"use strict" - -var uniq = _dereq_("uniq") - -// This function generates very simple loops analogous to how you typically traverse arrays (the outermost loop corresponds to the slowest changing index, the innermost loop to the fastest changing index) -// TODO: If two arrays have the same strides (and offsets) there is potential for decreasing the number of "pointers" and related variables. The drawback is that the type signature would become more specific and that there would thus be less potential for caching, but it might still be worth it, especially when dealing with large numbers of arguments. -function innerFill(order, proc, body) { - var dimension = order.length - , nargs = proc.arrayArgs.length - , has_index = proc.indexArgs.length>0 - , code = [] - , vars = [] - , idx=0, pidx=0, i, j - for(i=0; i 0) { - code.push("var " + vars.join(",")) - } - //Scan loop - for(i=dimension-1; i>=0; --i) { // Start at largest stride and work your way inwards - idx = order[i] - code.push(["for(i",i,"=0;i",i," 0) { - code.push(["index[",pidx,"]-=s",pidx].join("")) - } - code.push(["++index[",idx,"]"].join("")) - } - code.push("}") - } - return code.join("\n") -} - -// Generate "outer" loops that loop over blocks of data, applying "inner" loops to the blocks by manipulating the local variables in such a way that the inner loop only "sees" the current block. -// TODO: If this is used, then the previous declaration (done by generateCwiseOp) of s* is essentially unnecessary. -// I believe the s* are not used elsewhere (in particular, I don't think they're used in the pre/post parts and "shape" is defined independently), so it would be possible to make defining the s* dependent on what loop method is being used. -function outerFill(matched, order, proc, body) { - var dimension = order.length - , nargs = proc.arrayArgs.length - , blockSize = proc.blockSize - , has_index = proc.indexArgs.length > 0 - , code = [] - for(var i=0; i0;){"].join("")) // Iterate back to front - code.push(["if(j",i,"<",blockSize,"){"].join("")) // Either decrease j by blockSize (s = blockSize), or set it to zero (after setting s = j). - code.push(["s",order[i],"=j",i].join("")) - code.push(["j",i,"=0"].join("")) - code.push(["}else{s",order[i],"=",blockSize].join("")) - code.push(["j",i,"-=",blockSize,"}"].join("")) - if(has_index) { - code.push(["index[",order[i],"]=j",i].join("")) - } - } - for(var i=0; i 0) { - allEqual = allEqual && summary[i] === summary[i-1] - } - } - if(allEqual) { - return summary[0] - } - return summary.join("") -} - -//Generates a cwise operator -function generateCWiseOp(proc, typesig) { - - //Compute dimension - // Arrays get put first in typesig, and there are two entries per array (dtype and order), so this gets the number of dimensions in the first array arg. - var dimension = (typesig[1].length - Math.abs(proc.arrayBlockIndices[0]))|0 - var orders = new Array(proc.arrayArgs.length) - var dtypes = new Array(proc.arrayArgs.length) - for(var i=0; i 0) { - vars.push("shape=SS.slice(0)") // Makes the shape over which we iterate available to the user defined functions (so you can use width/height for example) - } - if(proc.indexArgs.length > 0) { - // Prepare an array to keep track of the (logical) indices, initialized to dimension zeroes. - var zeros = new Array(dimension) - for(var i=0; i 0) { - code.push("var " + vars.join(",")) - } - for(var i=0; i 3) { - code.push(processBlock(proc.pre, proc, dtypes)) - } - - //Process body - var body = processBlock(proc.body, proc, dtypes) - var matched = countMatches(loopOrders) - if(matched < dimension) { - code.push(outerFill(matched, loopOrders[0], proc, body)) // TODO: Rather than passing loopOrders[0], it might be interesting to look at passing an order that represents the majority of the arguments for example. - } else { - code.push(innerFill(loopOrders[0], proc, body)) - } - - //Inline epilog - if(proc.post.body.length > 3) { - code.push(processBlock(proc.post, proc, dtypes)) - } - - if(proc.debug) { - console.log("-----Generated cwise routine for ", typesig, ":\n" + code.join("\n") + "\n----------") - } - - var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("") - var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join("")) - return f() -} -module.exports = generateCWiseOp - -},{"uniq":547}],148:[function(_dereq_,module,exports){ -"use strict" - -// The function below is called when constructing a cwise function object, and does the following: -// A function object is constructed which accepts as argument a compilation function and returns another function. -// It is this other function that is eventually returned by createThunk, and this function is the one that actually -// checks whether a certain pattern of arguments has already been used before and compiles new loops as needed. -// The compilation passed to the first function object is used for compiling new functions. -// Once this function object is created, it is called with compile as argument, where the first argument of compile -// is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise). -// So createThunk roughly works like this: -// function createThunk(proc) { -// var thunk = function(compileBound) { -// var CACHED = {} -// return function(arrays and scalars) { -// if (dtype and order of arrays in CACHED) { -// var func = CACHED[dtype and order of arrays] -// } else { -// var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays) -// } -// return func(arrays and scalars) -// } -// } -// return thunk(compile.bind1(proc)) -// } - -var compile = _dereq_("./compile.js") - -function createThunk(proc) { - var code = ["'use strict'", "var CACHED={}"] - var vars = [] - var thunkName = proc.funcName + "_cwise_thunk" - - //Build thunk - code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join("")) - var typesig = [] - var string_typesig = [] - var proc_args = [["array",proc.arrayArgs[0],".shape.slice(", // Slice shape so that we only retain the shape over which we iterate (which gets passed to the cwise operator as SS). - Math.max(0,proc.arrayBlockIndices[0]),proc.arrayBlockIndices[0]<0?(","+proc.arrayBlockIndices[0]+")"):")"].join("")] - var shapeLengthConditions = [], shapeConditions = [] - // Process array arguments - for(var i=0; i0) { // Gather conditions to check for shape equality (ignoring block indices) - shapeLengthConditions.push("array" + proc.arrayArgs[0] + ".shape.length===array" + j + ".shape.length+" + (Math.abs(proc.arrayBlockIndices[0])-Math.abs(proc.arrayBlockIndices[i]))) - shapeConditions.push("array" + proc.arrayArgs[0] + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[0]) + "]===array" + j + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[i]) + "]") - } - } - // Check for shape equality - if (proc.arrayArgs.length > 1) { - code.push("if (!(" + shapeLengthConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same dimensionality!')") - code.push("for(var shapeIndex=array" + proc.arrayArgs[0] + ".shape.length-" + Math.abs(proc.arrayBlockIndices[0]) + "; shapeIndex-->0;) {") - code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')") - code.push("}") - } - // Process scalar arguments - for(var i=0; i b ? 1 : a >= b ? 0 : NaN; -} - -function bisector(compare) { - if (compare.length === 1) compare = ascendingComparator(compare); - return { - left: function(a, x, lo, hi) { - if (lo == null) lo = 0; - if (hi == null) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) < 0) lo = mid + 1; - else hi = mid; - } - return lo; - }, - right: function(a, x, lo, hi) { - if (lo == null) lo = 0; - if (hi == null) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) > 0) hi = mid; - else lo = mid + 1; - } - return lo; - } - }; -} - -function ascendingComparator(f) { - return function(d, x) { - return ascending(f(d), x); - }; -} - -var ascendingBisect = bisector(ascending); -var bisectRight = ascendingBisect.right; -var bisectLeft = ascendingBisect.left; - -function pairs(array, f) { - if (f == null) f = pair; - var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); - while (i < n) pairs[i] = f(p, p = array[++i]); - return pairs; -} - -function pair(a, b) { - return [a, b]; -} - -function cross(values0, values1, reduce) { - var n0 = values0.length, - n1 = values1.length, - values = new Array(n0 * n1), - i0, - i1, - i, - value0; - - if (reduce == null) reduce = pair; - - for (i0 = i = 0; i0 < n0; ++i0) { - for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { - values[i] = reduce(value0, values1[i1]); - } - } - - return values; -} - -function descending(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; -} - -function number(x) { - return x === null ? NaN : +x; -} - -function variance(values, valueof) { - var n = values.length, - m = 0, - i = -1, - mean = 0, - value, - delta, - sum = 0; - - if (valueof == null) { - while (++i < n) { - if (!isNaN(value = number(values[i]))) { - delta = value - mean; - mean += delta / ++m; - sum += delta * (value - mean); - } - } - } - - else { - while (++i < n) { - if (!isNaN(value = number(valueof(values[i], i, values)))) { - delta = value - mean; - mean += delta / ++m; - sum += delta * (value - mean); - } - } - } - - if (m > 1) return sum / (m - 1); -} - -function deviation(array, f) { - var v = variance(array, f); - return v ? Math.sqrt(v) : v; -} - -function extent(values, valueof) { - var n = values.length, - i = -1, - value, - min, - max; - - if (valueof == null) { - while (++i < n) { // Find the first comparable value. - if ((value = values[i]) != null && value >= value) { - min = max = value; - while (++i < n) { // Compare the remaining values. - if ((value = values[i]) != null) { - if (min > value) min = value; - if (max < value) max = value; - } - } - } - } - } - - else { - while (++i < n) { // Find the first comparable value. - if ((value = valueof(values[i], i, values)) != null && value >= value) { - min = max = value; - while (++i < n) { // Compare the remaining values. - if ((value = valueof(values[i], i, values)) != null) { - if (min > value) min = value; - if (max < value) max = value; - } - } - } - } - } - - return [min, max]; -} - -var array = Array.prototype; - -var slice = array.slice; -var map = array.map; - -function constant(x) { - return function() { - return x; - }; -} - -function identity(x) { - return x; -} - -function range(start, stop, step) { - start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; - - var i = -1, - n = Math.max(0, Math.ceil((stop - start) / step)) | 0, - range = new Array(n); - - while (++i < n) { - range[i] = start + i * step; - } - - return range; -} - -var e10 = Math.sqrt(50), - e5 = Math.sqrt(10), - e2 = Math.sqrt(2); - -function ticks(start, stop, count) { - var reverse, - i = -1, - n, - ticks, - step; - - stop = +stop, start = +start, count = +count; - if (start === stop && count > 0) return [start]; - if (reverse = stop < start) n = start, start = stop, stop = n; - if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; - - if (step > 0) { - start = Math.ceil(start / step); - stop = Math.floor(stop / step); - ticks = new Array(n = Math.ceil(stop - start + 1)); - while (++i < n) ticks[i] = (start + i) * step; - } else { - start = Math.floor(start * step); - stop = Math.ceil(stop * step); - ticks = new Array(n = Math.ceil(start - stop + 1)); - while (++i < n) ticks[i] = (start - i) / step; - } - - if (reverse) ticks.reverse(); - - return ticks; -} - -function tickIncrement(start, stop, count) { - var step = (stop - start) / Math.max(0, count), - power = Math.floor(Math.log(step) / Math.LN10), - error = step / Math.pow(10, power); - return power >= 0 - ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) - : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); -} - -function tickStep(start, stop, count) { - var step0 = Math.abs(stop - start) / Math.max(0, count), - step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), - error = step0 / step1; - if (error >= e10) step1 *= 10; - else if (error >= e5) step1 *= 5; - else if (error >= e2) step1 *= 2; - return stop < start ? -step1 : step1; -} - -function sturges(values) { - return Math.ceil(Math.log(values.length) / Math.LN2) + 1; -} - -function histogram() { - var value = identity, - domain = extent, - threshold = sturges; - - function histogram(data) { - var i, - n = data.length, - x, - values = new Array(n); - - for (i = 0; i < n; ++i) { - values[i] = value(data[i], i, data); - } - - var xz = domain(values), - x0 = xz[0], - x1 = xz[1], - tz = threshold(values, x0, x1); - - // Convert number of thresholds into uniform thresholds. - if (!Array.isArray(tz)) { - tz = tickStep(x0, x1, tz); - tz = range(Math.ceil(x0 / tz) * tz, x1, tz); // exclusive - } - - // Remove any thresholds outside the domain. - var m = tz.length; - while (tz[0] <= x0) tz.shift(), --m; - while (tz[m - 1] > x1) tz.pop(), --m; - - var bins = new Array(m + 1), - bin; - - // Initialize bins. - for (i = 0; i <= m; ++i) { - bin = bins[i] = []; - bin.x0 = i > 0 ? tz[i - 1] : x0; - bin.x1 = i < m ? tz[i] : x1; - } - - // Assign data to bins by value, ignoring any outside the domain. - for (i = 0; i < n; ++i) { - x = values[i]; - if (x0 <= x && x <= x1) { - bins[bisectRight(tz, x, 0, m)].push(data[i]); - } - } - - return bins; - } - - histogram.value = function(_) { - return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; - }; - - histogram.domain = function(_) { - return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; - }; - - histogram.thresholds = function(_) { - return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; - }; - - return histogram; -} - -function quantile(values, p, valueof) { - if (valueof == null) valueof = number; - if (!(n = values.length)) return; - if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values); - if (p >= 1) return +valueof(values[n - 1], n - 1, values); - var n, - i = (n - 1) * p, - i0 = Math.floor(i), - value0 = +valueof(values[i0], i0, values), - value1 = +valueof(values[i0 + 1], i0 + 1, values); - return value0 + (value1 - value0) * (i - i0); -} - -function freedmanDiaconis(values, min, max) { - values = map.call(values, number).sort(ascending); - return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(values.length, -1 / 3))); -} - -function scott(values, min, max) { - return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); -} - -function max(values, valueof) { - var n = values.length, - i = -1, - value, - max; - - if (valueof == null) { - while (++i < n) { // Find the first comparable value. - if ((value = values[i]) != null && value >= value) { - max = value; - while (++i < n) { // Compare the remaining values. - if ((value = values[i]) != null && value > max) { - max = value; - } - } - } - } - } - - else { - while (++i < n) { // Find the first comparable value. - if ((value = valueof(values[i], i, values)) != null && value >= value) { - max = value; - while (++i < n) { // Compare the remaining values. - if ((value = valueof(values[i], i, values)) != null && value > max) { - max = value; - } - } - } - } - } - - return max; -} - -function mean(values, valueof) { - var n = values.length, - m = n, - i = -1, - value, - sum = 0; - - if (valueof == null) { - while (++i < n) { - if (!isNaN(value = number(values[i]))) sum += value; - else --m; - } - } - - else { - while (++i < n) { - if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value; - else --m; - } - } - - if (m) return sum / m; -} - -function median(values, valueof) { - var n = values.length, - i = -1, - value, - numbers = []; - - if (valueof == null) { - while (++i < n) { - if (!isNaN(value = number(values[i]))) { - numbers.push(value); - } - } - } - - else { - while (++i < n) { - if (!isNaN(value = number(valueof(values[i], i, values)))) { - numbers.push(value); - } - } - } - - return quantile(numbers.sort(ascending), 0.5); -} - -function merge(arrays) { - var n = arrays.length, - m, - i = -1, - j = 0, - merged, - array; - - while (++i < n) j += arrays[i].length; - merged = new Array(j); - - while (--n >= 0) { - array = arrays[n]; - m = array.length; - while (--m >= 0) { - merged[--j] = array[m]; - } - } - - return merged; -} - -function min(values, valueof) { - var n = values.length, - i = -1, - value, - min; - - if (valueof == null) { - while (++i < n) { // Find the first comparable value. - if ((value = values[i]) != null && value >= value) { - min = value; - while (++i < n) { // Compare the remaining values. - if ((value = values[i]) != null && min > value) { - min = value; - } - } - } - } - } - - else { - while (++i < n) { // Find the first comparable value. - if ((value = valueof(values[i], i, values)) != null && value >= value) { - min = value; - while (++i < n) { // Compare the remaining values. - if ((value = valueof(values[i], i, values)) != null && min > value) { - min = value; - } - } - } - } - } - - return min; -} - -function permute(array, indexes) { - var i = indexes.length, permutes = new Array(i); - while (i--) permutes[i] = array[indexes[i]]; - return permutes; -} - -function scan(values, compare) { - if (!(n = values.length)) return; - var n, - i = 0, - j = 0, - xi, - xj = values[j]; - - if (compare == null) compare = ascending; - - while (++i < n) { - if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) { - xj = xi, j = i; - } - } - - if (compare(xj, xj) === 0) return j; -} - -function shuffle(array, i0, i1) { - var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0), - t, - i; - - while (m) { - i = Math.random() * m-- | 0; - t = array[m + i0]; - array[m + i0] = array[i + i0]; - array[i + i0] = t; - } - - return array; -} - -function sum(values, valueof) { - var n = values.length, - i = -1, - value, - sum = 0; - - if (valueof == null) { - while (++i < n) { - if (value = +values[i]) sum += value; // Note: zero and null are equivalent. - } - } - - else { - while (++i < n) { - if (value = +valueof(values[i], i, values)) sum += value; - } - } - - return sum; -} - -function transpose(matrix) { - if (!(n = matrix.length)) return []; - for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) { - for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { - row[j] = matrix[j][i]; - } - } - return transpose; -} - -function length(d) { - return d.length; -} - -function zip() { - return transpose(arguments); -} - -exports.bisect = bisectRight; -exports.bisectRight = bisectRight; -exports.bisectLeft = bisectLeft; -exports.ascending = ascending; -exports.bisector = bisector; -exports.cross = cross; -exports.descending = descending; -exports.deviation = deviation; -exports.extent = extent; -exports.histogram = histogram; -exports.thresholdFreedmanDiaconis = freedmanDiaconis; -exports.thresholdScott = scott; -exports.thresholdSturges = sturges; -exports.max = max; -exports.mean = mean; -exports.median = median; -exports.merge = merge; -exports.min = min; -exports.pairs = pairs; -exports.permute = permute; -exports.quantile = quantile; -exports.range = range; -exports.scan = scan; -exports.shuffle = shuffle; -exports.sum = sum; -exports.ticks = ticks; -exports.tickIncrement = tickIncrement; -exports.tickStep = tickStep; -exports.transpose = transpose; -exports.variance = variance; -exports.zip = zip; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{}],153:[function(_dereq_,module,exports){ -// https://d3js.org/d3-collection/ Version 1.0.4. Copyright 2017 Mike Bostock. -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.d3 = global.d3 || {}))); -}(this, (function (exports) { 'use strict'; - -var prefix = "$"; - -function Map() {} - -Map.prototype = map.prototype = { - constructor: Map, - has: function(key) { - return (prefix + key) in this; - }, - get: function(key) { - return this[prefix + key]; - }, - set: function(key, value) { - this[prefix + key] = value; - return this; - }, - remove: function(key) { - var property = prefix + key; - return property in this && delete this[property]; - }, - clear: function() { - for (var property in this) if (property[0] === prefix) delete this[property]; - }, - keys: function() { - var keys = []; - for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); - return keys; - }, - values: function() { - var values = []; - for (var property in this) if (property[0] === prefix) values.push(this[property]); - return values; - }, - entries: function() { - var entries = []; - for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); - return entries; - }, - size: function() { - var size = 0; - for (var property in this) if (property[0] === prefix) ++size; - return size; - }, - empty: function() { - for (var property in this) if (property[0] === prefix) return false; - return true; - }, - each: function(f) { - for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); - } -}; - -function map(object, f) { - var map = new Map; - - // Copy constructor. - if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); - - // Index array by numeric index or specified key function. - else if (Array.isArray(object)) { - var i = -1, - n = object.length, - o; - - if (f == null) while (++i < n) map.set(i, object[i]); - else while (++i < n) map.set(f(o = object[i], i, object), o); - } - - // Convert object to map. - else if (object) for (var key in object) map.set(key, object[key]); - - return map; -} - -var nest = function() { - var keys = [], - sortKeys = [], - sortValues, - rollup, - nest; - - function apply(array, depth, createResult, setResult) { - if (depth >= keys.length) { - if (sortValues != null) array.sort(sortValues); - return rollup != null ? rollup(array) : array; - } - - var i = -1, - n = array.length, - key = keys[depth++], - keyValue, - value, - valuesByKey = map(), - values, - result = createResult(); - - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { - values.push(value); - } else { - valuesByKey.set(keyValue, [value]); - } - } - - valuesByKey.each(function(values, key) { - setResult(result, key, apply(values, depth, createResult, setResult)); - }); - - return result; - } - - function entries(map$$1, depth) { - if (++depth > keys.length) return map$$1; - var array, sortKey = sortKeys[depth - 1]; - if (rollup != null && depth >= keys.length) array = map$$1.entries(); - else array = [], map$$1.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); - return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; - } - - return nest = { - object: function(array) { return apply(array, 0, createObject, setObject); }, - map: function(array) { return apply(array, 0, createMap, setMap); }, - entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, - key: function(d) { keys.push(d); return nest; }, - sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, - sortValues: function(order) { sortValues = order; return nest; }, - rollup: function(f) { rollup = f; return nest; } - }; -}; - -function createObject() { - return {}; -} - -function setObject(object, key, value) { - object[key] = value; -} - -function createMap() { - return map(); -} - -function setMap(map$$1, key, value) { - map$$1.set(key, value); -} - -function Set() {} - -var proto = map.prototype; - -Set.prototype = set.prototype = { - constructor: Set, - has: proto.has, - add: function(value) { - value += ""; - this[prefix + value] = value; - return this; - }, - remove: proto.remove, - clear: proto.clear, - values: proto.keys, - size: proto.size, - empty: proto.empty, - each: proto.each -}; - -function set(object, f) { - var set = new Set; - - // Copy constructor. - if (object instanceof Set) object.each(function(value) { set.add(value); }); - - // Otherwise, assume it’s an array. - else if (object) { - var i = -1, n = object.length; - if (f == null) while (++i < n) set.add(object[i]); - else while (++i < n) set.add(f(object[i], i, object)); - } - - return set; -} - -var keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; -}; - -var values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; -}; - -var entries = function(map) { - var entries = []; - for (var key in map) entries.push({key: key, value: map[key]}); - return entries; -}; - -exports.nest = nest; -exports.set = set; -exports.map = map; -exports.keys = keys; -exports.values = values; -exports.entries = entries; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{}],154:[function(_dereq_,module,exports){ -// https://d3js.org/d3-color/ v1.2.3 Copyright 2018 Mike Bostock -(function (global, factory) { -typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : -typeof define === 'function' && define.amd ? define(['exports'], factory) : -(factory((global.d3 = global.d3 || {}))); -}(this, (function (exports) { 'use strict'; - -function define(constructor, factory, prototype) { - constructor.prototype = factory.prototype = prototype; - prototype.constructor = constructor; -} - -function extend(parent, definition) { - var prototype = Object.create(parent.prototype); - for (var key in definition) prototype[key] = definition[key]; - return prototype; -} - -function Color() {} - -var darker = 0.7; -var brighter = 1 / darker; - -var reI = "\\s*([+-]?\\d+)\\s*", - reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*", - reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*", - reHex3 = /^#([0-9a-f]{3})$/, - reHex6 = /^#([0-9a-f]{6})$/, - reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"), - reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"), - reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"), - reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"), - reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"), - reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); - -var named = { - aliceblue: 0xf0f8ff, - antiquewhite: 0xfaebd7, - aqua: 0x00ffff, - aquamarine: 0x7fffd4, - azure: 0xf0ffff, - beige: 0xf5f5dc, - bisque: 0xffe4c4, - black: 0x000000, - blanchedalmond: 0xffebcd, - blue: 0x0000ff, - blueviolet: 0x8a2be2, - brown: 0xa52a2a, - burlywood: 0xdeb887, - cadetblue: 0x5f9ea0, - chartreuse: 0x7fff00, - chocolate: 0xd2691e, - coral: 0xff7f50, - cornflowerblue: 0x6495ed, - cornsilk: 0xfff8dc, - crimson: 0xdc143c, - cyan: 0x00ffff, - darkblue: 0x00008b, - darkcyan: 0x008b8b, - darkgoldenrod: 0xb8860b, - darkgray: 0xa9a9a9, - darkgreen: 0x006400, - darkgrey: 0xa9a9a9, - darkkhaki: 0xbdb76b, - darkmagenta: 0x8b008b, - darkolivegreen: 0x556b2f, - darkorange: 0xff8c00, - darkorchid: 0x9932cc, - darkred: 0x8b0000, - darksalmon: 0xe9967a, - darkseagreen: 0x8fbc8f, - darkslateblue: 0x483d8b, - darkslategray: 0x2f4f4f, - darkslategrey: 0x2f4f4f, - darkturquoise: 0x00ced1, - darkviolet: 0x9400d3, - deeppink: 0xff1493, - deepskyblue: 0x00bfff, - dimgray: 0x696969, - dimgrey: 0x696969, - dodgerblue: 0x1e90ff, - firebrick: 0xb22222, - floralwhite: 0xfffaf0, - forestgreen: 0x228b22, - fuchsia: 0xff00ff, - gainsboro: 0xdcdcdc, - ghostwhite: 0xf8f8ff, - gold: 0xffd700, - goldenrod: 0xdaa520, - gray: 0x808080, - green: 0x008000, - greenyellow: 0xadff2f, - grey: 0x808080, - honeydew: 0xf0fff0, - hotpink: 0xff69b4, - indianred: 0xcd5c5c, - indigo: 0x4b0082, - ivory: 0xfffff0, - khaki: 0xf0e68c, - lavender: 0xe6e6fa, - lavenderblush: 0xfff0f5, - lawngreen: 0x7cfc00, - lemonchiffon: 0xfffacd, - lightblue: 0xadd8e6, - lightcoral: 0xf08080, - lightcyan: 0xe0ffff, - lightgoldenrodyellow: 0xfafad2, - lightgray: 0xd3d3d3, - lightgreen: 0x90ee90, - lightgrey: 0xd3d3d3, - lightpink: 0xffb6c1, - lightsalmon: 0xffa07a, - lightseagreen: 0x20b2aa, - lightskyblue: 0x87cefa, - lightslategray: 0x778899, - lightslategrey: 0x778899, - lightsteelblue: 0xb0c4de, - lightyellow: 0xffffe0, - lime: 0x00ff00, - limegreen: 0x32cd32, - linen: 0xfaf0e6, - magenta: 0xff00ff, - maroon: 0x800000, - mediumaquamarine: 0x66cdaa, - mediumblue: 0x0000cd, - mediumorchid: 0xba55d3, - mediumpurple: 0x9370db, - mediumseagreen: 0x3cb371, - mediumslateblue: 0x7b68ee, - mediumspringgreen: 0x00fa9a, - mediumturquoise: 0x48d1cc, - mediumvioletred: 0xc71585, - midnightblue: 0x191970, - mintcream: 0xf5fffa, - mistyrose: 0xffe4e1, - moccasin: 0xffe4b5, - navajowhite: 0xffdead, - navy: 0x000080, - oldlace: 0xfdf5e6, - olive: 0x808000, - olivedrab: 0x6b8e23, - orange: 0xffa500, - orangered: 0xff4500, - orchid: 0xda70d6, - palegoldenrod: 0xeee8aa, - palegreen: 0x98fb98, - paleturquoise: 0xafeeee, - palevioletred: 0xdb7093, - papayawhip: 0xffefd5, - peachpuff: 0xffdab9, - peru: 0xcd853f, - pink: 0xffc0cb, - plum: 0xdda0dd, - powderblue: 0xb0e0e6, - purple: 0x800080, - rebeccapurple: 0x663399, - red: 0xff0000, - rosybrown: 0xbc8f8f, - royalblue: 0x4169e1, - saddlebrown: 0x8b4513, - salmon: 0xfa8072, - sandybrown: 0xf4a460, - seagreen: 0x2e8b57, - seashell: 0xfff5ee, - sienna: 0xa0522d, - silver: 0xc0c0c0, - skyblue: 0x87ceeb, - slateblue: 0x6a5acd, - slategray: 0x708090, - slategrey: 0x708090, - snow: 0xfffafa, - springgreen: 0x00ff7f, - steelblue: 0x4682b4, - tan: 0xd2b48c, - teal: 0x008080, - thistle: 0xd8bfd8, - tomato: 0xff6347, - turquoise: 0x40e0d0, - violet: 0xee82ee, - wheat: 0xf5deb3, - white: 0xffffff, - whitesmoke: 0xf5f5f5, - yellow: 0xffff00, - yellowgreen: 0x9acd32 -}; - -define(Color, color, { - displayable: function() { - return this.rgb().displayable(); - }, - hex: function() { - return this.rgb().hex(); - }, - toString: function() { - return this.rgb() + ""; - } -}); - -function color(format) { - var m; - format = (format + "").trim().toLowerCase(); - return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 - : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 - : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) - : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) - : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) - : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) - : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) - : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) - : named.hasOwnProperty(format) ? rgbn(named[format]) - : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) - : null; -} - -function rgbn(n) { - return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); -} - -function rgba(r, g, b, a) { - if (a <= 0) r = g = b = NaN; - return new Rgb(r, g, b, a); -} - -function rgbConvert(o) { - if (!(o instanceof Color)) o = color(o); - if (!o) return new Rgb; - o = o.rgb(); - return new Rgb(o.r, o.g, o.b, o.opacity); -} - -function rgb(r, g, b, opacity) { - return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); -} - -function Rgb(r, g, b, opacity) { - this.r = +r; - this.g = +g; - this.b = +b; - this.opacity = +opacity; -} - -define(Rgb, rgb, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); - }, - rgb: function() { - return this; - }, - displayable: function() { - return (0 <= this.r && this.r <= 255) - && (0 <= this.g && this.g <= 255) - && (0 <= this.b && this.b <= 255) - && (0 <= this.opacity && this.opacity <= 1); - }, - hex: function() { - return "#" + hex(this.r) + hex(this.g) + hex(this.b); - }, - toString: function() { - var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); - return (a === 1 ? "rgb(" : "rgba(") - + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " - + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " - + Math.max(0, Math.min(255, Math.round(this.b) || 0)) - + (a === 1 ? ")" : ", " + a + ")"); - } -})); - -function hex(value) { - value = Math.max(0, Math.min(255, Math.round(value) || 0)); - return (value < 16 ? "0" : "") + value.toString(16); -} - -function hsla(h, s, l, a) { - if (a <= 0) h = s = l = NaN; - else if (l <= 0 || l >= 1) h = s = NaN; - else if (s <= 0) h = NaN; - return new Hsl(h, s, l, a); -} - -function hslConvert(o) { - if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); - if (!(o instanceof Color)) o = color(o); - if (!o) return new Hsl; - if (o instanceof Hsl) return o; - o = o.rgb(); - var r = o.r / 255, - g = o.g / 255, - b = o.b / 255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - h = NaN, - s = max - min, - l = (max + min) / 2; - if (s) { - if (r === max) h = (g - b) / s + (g < b) * 6; - else if (g === max) h = (b - r) / s + 2; - else h = (r - g) / s + 4; - s /= l < 0.5 ? max + min : 2 - max - min; - h *= 60; - } else { - s = l > 0 && l < 1 ? 0 : h; - } - return new Hsl(h, s, l, o.opacity); -} - -function hsl(h, s, l, opacity) { - return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); -} - -function Hsl(h, s, l, opacity) { - this.h = +h; - this.s = +s; - this.l = +l; - this.opacity = +opacity; -} - -define(Hsl, hsl, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Hsl(this.h, this.s, this.l * k, this.opacity); - }, - rgb: function() { - var h = this.h % 360 + (this.h < 0) * 360, - s = isNaN(h) || isNaN(this.s) ? 0 : this.s, - l = this.l, - m2 = l + (l < 0.5 ? l : 1 - l) * s, - m1 = 2 * l - m2; - return new Rgb( - hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), - hsl2rgb(h, m1, m2), - hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), - this.opacity - ); - }, - displayable: function() { - return (0 <= this.s && this.s <= 1 || isNaN(this.s)) - && (0 <= this.l && this.l <= 1) - && (0 <= this.opacity && this.opacity <= 1); - } -})); - -/* From FvD 13.37, CSS Color Module Level 3 */ -function hsl2rgb(h, m1, m2) { - return (h < 60 ? m1 + (m2 - m1) * h / 60 - : h < 180 ? m2 - : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 - : m1) * 255; -} - -var deg2rad = Math.PI / 180; -var rad2deg = 180 / Math.PI; - -// https://beta.observablehq.com/@mbostock/lab-and-rgb -var K = 18, - Xn = 0.96422, - Yn = 1, - Zn = 0.82521, - t0 = 4 / 29, - t1 = 6 / 29, - t2 = 3 * t1 * t1, - t3 = t1 * t1 * t1; - -function labConvert(o) { - if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); - if (o instanceof Hcl) { - if (isNaN(o.h)) return new Lab(o.l, 0, 0, o.opacity); - var h = o.h * deg2rad; - return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); - } - if (!(o instanceof Rgb)) o = rgbConvert(o); - var r = rgb2lrgb(o.r), - g = rgb2lrgb(o.g), - b = rgb2lrgb(o.b), - y = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn), x, z; - if (r === g && g === b) x = z = y; else { - x = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn); - z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn); - } - return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); -} - -function gray(l, opacity) { - return new Lab(l, 0, 0, opacity == null ? 1 : opacity); -} - -function lab(l, a, b, opacity) { - return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); -} - -function Lab(l, a, b, opacity) { - this.l = +l; - this.a = +a; - this.b = +b; - this.opacity = +opacity; -} - -define(Lab, lab, extend(Color, { - brighter: function(k) { - return new Lab(this.l + K * (k == null ? 1 : k), this.a, this.b, this.opacity); - }, - darker: function(k) { - return new Lab(this.l - K * (k == null ? 1 : k), this.a, this.b, this.opacity); - }, - rgb: function() { - var y = (this.l + 16) / 116, - x = isNaN(this.a) ? y : y + this.a / 500, - z = isNaN(this.b) ? y : y - this.b / 200; - x = Xn * lab2xyz(x); - y = Yn * lab2xyz(y); - z = Zn * lab2xyz(z); - return new Rgb( - lrgb2rgb( 3.1338561 * x - 1.6168667 * y - 0.4906146 * z), - lrgb2rgb(-0.9787684 * x + 1.9161415 * y + 0.0334540 * z), - lrgb2rgb( 0.0719453 * x - 0.2289914 * y + 1.4052427 * z), - this.opacity - ); - } -})); - -function xyz2lab(t) { - return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; -} - -function lab2xyz(t) { - return t > t1 ? t * t * t : t2 * (t - t0); -} - -function lrgb2rgb(x) { - return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); -} - -function rgb2lrgb(x) { - return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); -} - -function hclConvert(o) { - if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); - if (!(o instanceof Lab)) o = labConvert(o); - if (o.a === 0 && o.b === 0) return new Hcl(NaN, 0, o.l, o.opacity); - var h = Math.atan2(o.b, o.a) * rad2deg; - return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); -} - -function lch(l, c, h, opacity) { - return arguments.length === 1 ? hclConvert(l) : new Hcl(h, c, l, opacity == null ? 1 : opacity); -} - -function hcl(h, c, l, opacity) { - return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); -} - -function Hcl(h, c, l, opacity) { - this.h = +h; - this.c = +c; - this.l = +l; - this.opacity = +opacity; -} - -define(Hcl, hcl, extend(Color, { - brighter: function(k) { - return new Hcl(this.h, this.c, this.l + K * (k == null ? 1 : k), this.opacity); - }, - darker: function(k) { - return new Hcl(this.h, this.c, this.l - K * (k == null ? 1 : k), this.opacity); - }, - rgb: function() { - return labConvert(this).rgb(); - } -})); - -var A = -0.14861, - B = +1.78277, - C = -0.29227, - D = -0.90649, - E = +1.97294, - ED = E * D, - EB = E * B, - BC_DA = B * C - D * A; - -function cubehelixConvert(o) { - if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); - if (!(o instanceof Rgb)) o = rgbConvert(o); - var r = o.r / 255, - g = o.g / 255, - b = o.b / 255, - l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), - bl = b - l, - k = (E * (g - l) - C * bl) / D, - s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 - h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; - return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); -} - -function cubehelix(h, s, l, opacity) { - return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); -} - -function Cubehelix(h, s, l, opacity) { - this.h = +h; - this.s = +s; - this.l = +l; - this.opacity = +opacity; -} - -define(Cubehelix, cubehelix, extend(Color, { - brighter: function(k) { - k = k == null ? brighter : Math.pow(brighter, k); - return new Cubehelix(this.h, this.s, this.l * k, this.opacity); - }, - darker: function(k) { - k = k == null ? darker : Math.pow(darker, k); - return new Cubehelix(this.h, this.s, this.l * k, this.opacity); - }, - rgb: function() { - var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, - l = +this.l, - a = isNaN(this.s) ? 0 : this.s * l * (1 - l), - cosh = Math.cos(h), - sinh = Math.sin(h); - return new Rgb( - 255 * (l + a * (A * cosh + B * sinh)), - 255 * (l + a * (C * cosh + D * sinh)), - 255 * (l + a * (E * cosh)), - this.opacity - ); - } -})); - -exports.color = color; -exports.rgb = rgb; -exports.hsl = hsl; -exports.lab = lab; -exports.hcl = hcl; -exports.lch = lch; -exports.gray = gray; -exports.cubehelix = cubehelix; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{}],155:[function(_dereq_,module,exports){ -// https://d3js.org/d3-dispatch/ Version 1.0.3. Copyright 2017 Mike Bostock. -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.d3 = global.d3 || {}))); -}(this, (function (exports) { 'use strict'; - -var noop = {value: function() {}}; - -function dispatch() { - for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { - if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); - _[t] = []; - } - return new Dispatch(_); -} - -function Dispatch(_) { - this._ = _; -} - -function parseTypenames(typenames, types) { - return typenames.trim().split(/^|\s+/).map(function(t) { - var name = "", i = t.indexOf("."); - if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); - if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); - return {type: t, name: name}; - }); -} - -Dispatch.prototype = dispatch.prototype = { - constructor: Dispatch, - on: function(typename, callback) { - var _ = this._, - T = parseTypenames(typename + "", _), - t, - i = -1, - n = T.length; - - // If no callback was specified, return the callback of the given type and name. - if (arguments.length < 2) { - while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; - return; - } - - // If a type was specified, set the callback for the given type and name. - // Otherwise, if a null callback was specified, remove callbacks of the given name. - if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); - while (++i < n) { - if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback); - else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null); - } - - return this; - }, - copy: function() { - var copy = {}, _ = this._; - for (var t in _) copy[t] = _[t].slice(); - return new Dispatch(copy); - }, - call: function(type, that) { - if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); - }, - apply: function(type, that, args) { - if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); - for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); - } -}; - -function get(type, name) { - for (var i = 0, n = type.length, c; i < n; ++i) { - if ((c = type[i]).name === name) { - return c.value; - } - } -} - -function set(type, name, callback) { - for (var i = 0, n = type.length; i < n; ++i) { - if (type[i].name === name) { - type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); - break; - } - } - if (callback != null) type.push({name: name, value: callback}); - return type; -} - -exports.dispatch = dispatch; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{}],156:[function(_dereq_,module,exports){ -// https://d3js.org/d3-force/ Version 1.1.0. Copyright 2017 Mike Bostock. -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, _dereq_('d3-quadtree'), _dereq_('d3-collection'), _dereq_('d3-dispatch'), _dereq_('d3-timer')) : - typeof define === 'function' && define.amd ? define(['exports', 'd3-quadtree', 'd3-collection', 'd3-dispatch', 'd3-timer'], factory) : - (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3)); -}(this, (function (exports,d3Quadtree,d3Collection,d3Dispatch,d3Timer) { 'use strict'; - -var center = function(x, y) { - var nodes; - - if (x == null) x = 0; - if (y == null) y = 0; - - function force() { - var i, - n = nodes.length, - node, - sx = 0, - sy = 0; - - for (i = 0; i < n; ++i) { - node = nodes[i], sx += node.x, sy += node.y; - } - - for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { - node = nodes[i], node.x -= sx, node.y -= sy; - } - } - - force.initialize = function(_) { - nodes = _; - }; - - force.x = function(_) { - return arguments.length ? (x = +_, force) : x; - }; - - force.y = function(_) { - return arguments.length ? (y = +_, force) : y; - }; - - return force; -}; - -var constant = function(x) { - return function() { - return x; - }; -}; - -var jiggle = function() { - return (Math.random() - 0.5) * 1e-6; -}; - -function x(d) { - return d.x + d.vx; -} - -function y(d) { - return d.y + d.vy; -} - -var collide = function(radius) { - var nodes, - radii, - strength = 1, - iterations = 1; - - if (typeof radius !== "function") radius = constant(radius == null ? 1 : +radius); - - function force() { - var i, n = nodes.length, - tree, - node, - xi, - yi, - ri, - ri2; - - for (var k = 0; k < iterations; ++k) { - tree = d3Quadtree.quadtree(nodes, x, y).visitAfter(prepare); - for (i = 0; i < n; ++i) { - node = nodes[i]; - ri = radii[node.index], ri2 = ri * ri; - xi = node.x + node.vx; - yi = node.y + node.vy; - tree.visit(apply); - } - } - - function apply(quad, x0, y0, x1, y1) { - var data = quad.data, rj = quad.r, r = ri + rj; - if (data) { - if (data.index > node.index) { - var x = xi - data.x - data.vx, - y = yi - data.y - data.vy, - l = x * x + y * y; - if (l < r * r) { - if (x === 0) x = jiggle(), l += x * x; - if (y === 0) y = jiggle(), l += y * y; - l = (r - (l = Math.sqrt(l))) / l * strength; - node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); - node.vy += (y *= l) * r; - data.vx -= x * (r = 1 - r); - data.vy -= y * r; - } - } - return; - } - return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; - } - } - - function prepare(quad) { - if (quad.data) return quad.r = radii[quad.data.index]; - for (var i = quad.r = 0; i < 4; ++i) { - if (quad[i] && quad[i].r > quad.r) { - quad.r = quad[i].r; - } - } - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length, node; - radii = new Array(n); - for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes); - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.iterations = function(_) { - return arguments.length ? (iterations = +_, force) : iterations; - }; - - force.strength = function(_) { - return arguments.length ? (strength = +_, force) : strength; - }; - - force.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius; - }; - - return force; -}; - -function index(d) { - return d.index; -} - -function find(nodeById, nodeId) { - var node = nodeById.get(nodeId); - if (!node) throw new Error("missing: " + nodeId); - return node; -} - -var link = function(links) { - var id = index, - strength = defaultStrength, - strengths, - distance = constant(30), - distances, - nodes, - count, - bias, - iterations = 1; - - if (links == null) links = []; - - function defaultStrength(link) { - return 1 / Math.min(count[link.source.index], count[link.target.index]); - } - - function force(alpha) { - for (var k = 0, n = links.length; k < iterations; ++k) { - for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { - link = links[i], source = link.source, target = link.target; - x = target.x + target.vx - source.x - source.vx || jiggle(); - y = target.y + target.vy - source.y - source.vy || jiggle(); - l = Math.sqrt(x * x + y * y); - l = (l - distances[i]) / l * alpha * strengths[i]; - x *= l, y *= l; - target.vx -= x * (b = bias[i]); - target.vy -= y * b; - source.vx += x * (b = 1 - b); - source.vy += y * b; - } - } - } - - function initialize() { - if (!nodes) return; - - var i, - n = nodes.length, - m = links.length, - nodeById = d3Collection.map(nodes, id), - link; - - for (i = 0, count = new Array(n); i < m; ++i) { - link = links[i], link.index = i; - if (typeof link.source !== "object") link.source = find(nodeById, link.source); - if (typeof link.target !== "object") link.target = find(nodeById, link.target); - count[link.source.index] = (count[link.source.index] || 0) + 1; - count[link.target.index] = (count[link.target.index] || 0) + 1; - } - - for (i = 0, bias = new Array(m); i < m; ++i) { - link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); - } - - strengths = new Array(m), initializeStrength(); - distances = new Array(m), initializeDistance(); - } - - function initializeStrength() { - if (!nodes) return; - - for (var i = 0, n = links.length; i < n; ++i) { - strengths[i] = +strength(links[i], i, links); - } - } - - function initializeDistance() { - if (!nodes) return; - - for (var i = 0, n = links.length; i < n; ++i) { - distances[i] = +distance(links[i], i, links); - } - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.links = function(_) { - return arguments.length ? (links = _, initialize(), force) : links; - }; - - force.id = function(_) { - return arguments.length ? (id = _, force) : id; - }; - - force.iterations = function(_) { - return arguments.length ? (iterations = +_, force) : iterations; - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength; - }; - - force.distance = function(_) { - return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance; - }; - - return force; -}; - -function x$1(d) { - return d.x; -} - -function y$1(d) { - return d.y; -} - -var initialRadius = 10; -var initialAngle = Math.PI * (3 - Math.sqrt(5)); - -var simulation = function(nodes) { - var simulation, - alpha = 1, - alphaMin = 0.001, - alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), - alphaTarget = 0, - velocityDecay = 0.6, - forces = d3Collection.map(), - stepper = d3Timer.timer(step), - event = d3Dispatch.dispatch("tick", "end"); - - if (nodes == null) nodes = []; - - function step() { - tick(); - event.call("tick", simulation); - if (alpha < alphaMin) { - stepper.stop(); - event.call("end", simulation); - } - } - - function tick() { - var i, n = nodes.length, node; - - alpha += (alphaTarget - alpha) * alphaDecay; - - forces.each(function(force) { - force(alpha); - }); - - for (i = 0; i < n; ++i) { - node = nodes[i]; - if (node.fx == null) node.x += node.vx *= velocityDecay; - else node.x = node.fx, node.vx = 0; - if (node.fy == null) node.y += node.vy *= velocityDecay; - else node.y = node.fy, node.vy = 0; - } - } - - function initializeNodes() { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.index = i; - if (isNaN(node.x) || isNaN(node.y)) { - var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; - node.x = radius * Math.cos(angle); - node.y = radius * Math.sin(angle); - } - if (isNaN(node.vx) || isNaN(node.vy)) { - node.vx = node.vy = 0; - } - } - } - - function initializeForce(force) { - if (force.initialize) force.initialize(nodes); - return force; - } - - initializeNodes(); - - return simulation = { - tick: tick, - - restart: function() { - return stepper.restart(step), simulation; - }, - - stop: function() { - return stepper.stop(), simulation; - }, - - nodes: function(_) { - return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; - }, - - alpha: function(_) { - return arguments.length ? (alpha = +_, simulation) : alpha; - }, - - alphaMin: function(_) { - return arguments.length ? (alphaMin = +_, simulation) : alphaMin; - }, - - alphaDecay: function(_) { - return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; - }, - - alphaTarget: function(_) { - return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; - }, - - velocityDecay: function(_) { - return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; - }, - - force: function(name, _) { - return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); - }, - - find: function(x, y, radius) { - var i = 0, - n = nodes.length, - dx, - dy, - d2, - node, - closest; - - if (radius == null) radius = Infinity; - else radius *= radius; - - for (i = 0; i < n; ++i) { - node = nodes[i]; - dx = x - node.x; - dy = y - node.y; - d2 = dx * dx + dy * dy; - if (d2 < radius) closest = node, radius = d2; - } - - return closest; - }, - - on: function(name, _) { - return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); - } - }; -}; - -var manyBody = function() { - var nodes, - node, - alpha, - strength = constant(-30), - strengths, - distanceMin2 = 1, - distanceMax2 = Infinity, - theta2 = 0.81; - - function force(_) { - var i, n = nodes.length, tree = d3Quadtree.quadtree(nodes, x$1, y$1).visitAfter(accumulate); - for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length, node; - strengths = new Array(n); - for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes); - } - - function accumulate(quad) { - var strength = 0, q, c, weight = 0, x, y, i; - - // For internal nodes, accumulate forces from child quadrants. - if (quad.length) { - for (x = y = i = 0; i < 4; ++i) { - if ((q = quad[i]) && (c = Math.abs(q.value))) { - strength += q.value, weight += c, x += c * q.x, y += c * q.y; - } - } - quad.x = x / weight; - quad.y = y / weight; - } - - // For leaf nodes, accumulate forces from coincident quadrants. - else { - q = quad; - q.x = q.data.x; - q.y = q.data.y; - do strength += strengths[q.data.index]; - while (q = q.next); - } - - quad.value = strength; - } - - function apply(quad, x1, _, x2) { - if (!quad.value) return true; - - var x = quad.x - node.x, - y = quad.y - node.y, - w = x2 - x1, - l = x * x + y * y; - - // Apply the Barnes-Hut approximation if possible. - // Limit forces for very close nodes; randomize direction if coincident. - if (w * w / theta2 < l) { - if (l < distanceMax2) { - if (x === 0) x = jiggle(), l += x * x; - if (y === 0) y = jiggle(), l += y * y; - if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); - node.vx += x * quad.value * alpha / l; - node.vy += y * quad.value * alpha / l; - } - return true; - } - - // Otherwise, process points directly. - else if (quad.length || l >= distanceMax2) return; - - // Limit forces for very close nodes; randomize direction if coincident. - if (quad.data !== node || quad.next) { - if (x === 0) x = jiggle(), l += x * x; - if (y === 0) y = jiggle(), l += y * y; - if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); - } - - do if (quad.data !== node) { - w = strengths[quad.data.index] * alpha / l; - node.vx += x * w; - node.vy += y * w; - } while (quad = quad.next); - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; - }; - - force.distanceMin = function(_) { - return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); - }; - - force.distanceMax = function(_) { - return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); - }; - - force.theta = function(_) { - return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); - }; - - return force; -}; - -var radial = function(radius, x, y) { - var nodes, - strength = constant(0.1), - strengths, - radiuses; - - if (typeof radius !== "function") radius = constant(+radius); - if (x == null) x = 0; - if (y == null) y = 0; - - function force(alpha) { - for (var i = 0, n = nodes.length; i < n; ++i) { - var node = nodes[i], - dx = node.x - x || 1e-6, - dy = node.y - y || 1e-6, - r = Math.sqrt(dx * dx + dy * dy), - k = (radiuses[i] - r) * strengths[i] * alpha / r; - node.vx += dx * k; - node.vy += dy * k; - } - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - radiuses = new Array(n); - for (i = 0; i < n; ++i) { - radiuses[i] = +radius(nodes[i], i, nodes); - strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes); - } - } - - force.initialize = function(_) { - nodes = _, initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; - }; - - force.radius = function(_) { - return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius; - }; - - force.x = function(_) { - return arguments.length ? (x = +_, force) : x; - }; - - force.y = function(_) { - return arguments.length ? (y = +_, force) : y; - }; - - return force; -}; - -var x$2 = function(x) { - var strength = constant(0.1), - nodes, - strengths, - xz; - - if (typeof x !== "function") x = constant(x == null ? 0 : +x); - - function force(alpha) { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; - } - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - xz = new Array(n); - for (i = 0; i < n; ++i) { - strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); - } - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; - }; - - force.x = function(_) { - return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), initialize(), force) : x; - }; - - return force; -}; - -var y$2 = function(y) { - var strength = constant(0.1), - nodes, - strengths, - yz; - - if (typeof y !== "function") y = constant(y == null ? 0 : +y); - - function force(alpha) { - for (var i = 0, n = nodes.length, node; i < n; ++i) { - node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; - } - } - - function initialize() { - if (!nodes) return; - var i, n = nodes.length; - strengths = new Array(n); - yz = new Array(n); - for (i = 0; i < n; ++i) { - strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); - } - } - - force.initialize = function(_) { - nodes = _; - initialize(); - }; - - force.strength = function(_) { - return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; - }; - - force.y = function(_) { - return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), initialize(), force) : y; - }; - - return force; -}; - -exports.forceCenter = center; -exports.forceCollide = collide; -exports.forceLink = link; -exports.forceManyBody = manyBody; -exports.forceRadial = radial; -exports.forceSimulation = simulation; -exports.forceX = x$2; -exports.forceY = y$2; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{"d3-collection":153,"d3-dispatch":155,"d3-quadtree":160,"d3-timer":162}],157:[function(_dereq_,module,exports){ -// https://d3js.org/d3-hierarchy/ v1.1.8 Copyright 2018 Mike Bostock -(function (global, factory) { -typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : -typeof define === 'function' && define.amd ? define(['exports'], factory) : -(factory((global.d3 = global.d3 || {}))); -}(this, (function (exports) { 'use strict'; - -function defaultSeparation(a, b) { - return a.parent === b.parent ? 1 : 2; -} - -function meanX(children) { - return children.reduce(meanXReduce, 0) / children.length; -} - -function meanXReduce(x, c) { - return x + c.x; -} - -function maxY(children) { - return 1 + children.reduce(maxYReduce, 0); -} - -function maxYReduce(y, c) { - return Math.max(y, c.y); -} - -function leafLeft(node) { - var children; - while (children = node.children) node = children[0]; - return node; -} - -function leafRight(node) { - var children; - while (children = node.children) node = children[children.length - 1]; - return node; -} - -function cluster() { - var separation = defaultSeparation, - dx = 1, - dy = 1, - nodeSize = false; - - function cluster(root) { - var previousNode, - x = 0; - - // First walk, computing the initial x & y values. - root.eachAfter(function(node) { - var children = node.children; - if (children) { - node.x = meanX(children); - node.y = maxY(children); - } else { - node.x = previousNode ? x += separation(node, previousNode) : 0; - node.y = 0; - previousNode = node; - } - }); - - var left = leafLeft(root), - right = leafRight(root), - x0 = left.x - separation(left, right) / 2, - x1 = right.x + separation(right, left) / 2; - - // Second walk, normalizing x & y to the desired size. - return root.eachAfter(nodeSize ? function(node) { - node.x = (node.x - root.x) * dx; - node.y = (root.y - node.y) * dy; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * dx; - node.y = (1 - (root.y ? node.y / root.y : 1)) * dy; - }); - } - - cluster.separation = function(x) { - return arguments.length ? (separation = x, cluster) : separation; - }; - - cluster.size = function(x) { - return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]); - }; - - cluster.nodeSize = function(x) { - return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null); - }; - - return cluster; -} - -function count(node) { - var sum = 0, - children = node.children, - i = children && children.length; - if (!i) sum = 1; - else while (--i >= 0) sum += children[i].value; - node.value = sum; -} - -function node_count() { - return this.eachAfter(count); -} - -function node_each(callback) { - var node = this, current, next = [node], children, i, n; - do { - current = next.reverse(), next = []; - while (node = current.pop()) { - callback(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - next.push(children[i]); - } - } - } while (next.length); - return this; -} - -function node_eachBefore(callback) { - var node = this, nodes = [node], children, i; - while (node = nodes.pop()) { - callback(node), children = node.children; - if (children) for (i = children.length - 1; i >= 0; --i) { - nodes.push(children[i]); - } - } - return this; -} - -function node_eachAfter(callback) { - var node = this, nodes = [node], next = [], children, i, n; - while (node = nodes.pop()) { - next.push(node), children = node.children; - if (children) for (i = 0, n = children.length; i < n; ++i) { - nodes.push(children[i]); - } - } - while (node = next.pop()) { - callback(node); - } - return this; -} - -function node_sum(value) { - return this.eachAfter(function(node) { - var sum = +value(node.data) || 0, - children = node.children, - i = children && children.length; - while (--i >= 0) sum += children[i].value; - node.value = sum; - }); -} - -function node_sort(compare) { - return this.eachBefore(function(node) { - if (node.children) { - node.children.sort(compare); - } - }); -} - -function node_path(end) { - var start = this, - ancestor = leastCommonAncestor(start, end), - nodes = [start]; - while (start !== ancestor) { - start = start.parent; - nodes.push(start); - } - var k = nodes.length; - while (end !== ancestor) { - nodes.splice(k, 0, end); - end = end.parent; - } - return nodes; -} - -function leastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = a.ancestors(), - bNodes = b.ancestors(), - c = null; - a = aNodes.pop(); - b = bNodes.pop(); - while (a === b) { - c = a; - a = aNodes.pop(); - b = bNodes.pop(); - } - return c; -} - -function node_ancestors() { - var node = this, nodes = [node]; - while (node = node.parent) { - nodes.push(node); - } - return nodes; -} - -function node_descendants() { - var nodes = []; - this.each(function(node) { - nodes.push(node); - }); - return nodes; -} - -function node_leaves() { - var leaves = []; - this.eachBefore(function(node) { - if (!node.children) { - leaves.push(node); - } - }); - return leaves; -} - -function node_links() { - var root = this, links = []; - root.each(function(node) { - if (node !== root) { // Don’t include the root’s parent, if any. - links.push({source: node.parent, target: node}); - } - }); - return links; -} - -function hierarchy(data, children) { - var root = new Node(data), - valued = +data.value && (root.value = data.value), - node, - nodes = [root], - child, - childs, - i, - n; - - if (children == null) children = defaultChildren; - - while (node = nodes.pop()) { - if (valued) node.value = +node.data.value; - if ((childs = children(node.data)) && (n = childs.length)) { - node.children = new Array(n); - for (i = n - 1; i >= 0; --i) { - nodes.push(child = node.children[i] = new Node(childs[i])); - child.parent = node; - child.depth = node.depth + 1; - } - } - } - - return root.eachBefore(computeHeight); -} - -function node_copy() { - return hierarchy(this).eachBefore(copyData); -} - -function defaultChildren(d) { - return d.children; -} - -function copyData(node) { - node.data = node.data.data; -} - -function computeHeight(node) { - var height = 0; - do node.height = height; - while ((node = node.parent) && (node.height < ++height)); -} - -function Node(data) { - this.data = data; - this.depth = - this.height = 0; - this.parent = null; -} - -Node.prototype = hierarchy.prototype = { - constructor: Node, - count: node_count, - each: node_each, - eachAfter: node_eachAfter, - eachBefore: node_eachBefore, - sum: node_sum, - sort: node_sort, - path: node_path, - ancestors: node_ancestors, - descendants: node_descendants, - leaves: node_leaves, - links: node_links, - copy: node_copy -}; - -var slice = Array.prototype.slice; - -function shuffle(array) { - var m = array.length, - t, - i; - - while (m) { - i = Math.random() * m-- | 0; - t = array[m]; - array[m] = array[i]; - array[i] = t; - } - - return array; -} - -function enclose(circles) { - var i = 0, n = (circles = shuffle(slice.call(circles))).length, B = [], p, e; - - while (i < n) { - p = circles[i]; - if (e && enclosesWeak(e, p)) ++i; - else e = encloseBasis(B = extendBasis(B, p)), i = 0; - } - - return e; -} - -function extendBasis(B, p) { - var i, j; - - if (enclosesWeakAll(p, B)) return [p]; - - // If we get here then B must have at least one element. - for (i = 0; i < B.length; ++i) { - if (enclosesNot(p, B[i]) - && enclosesWeakAll(encloseBasis2(B[i], p), B)) { - return [B[i], p]; - } - } - - // If we get here then B must have at least two elements. - for (i = 0; i < B.length - 1; ++i) { - for (j = i + 1; j < B.length; ++j) { - if (enclosesNot(encloseBasis2(B[i], B[j]), p) - && enclosesNot(encloseBasis2(B[i], p), B[j]) - && enclosesNot(encloseBasis2(B[j], p), B[i]) - && enclosesWeakAll(encloseBasis3(B[i], B[j], p), B)) { - return [B[i], B[j], p]; - } - } - } - - // If we get here then something is very wrong. - throw new Error; -} - -function enclosesNot(a, b) { - var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y; - return dr < 0 || dr * dr < dx * dx + dy * dy; -} - -function enclosesWeak(a, b) { - var dr = a.r - b.r + 1e-6, dx = b.x - a.x, dy = b.y - a.y; - return dr > 0 && dr * dr > dx * dx + dy * dy; -} - -function enclosesWeakAll(a, B) { - for (var i = 0; i < B.length; ++i) { - if (!enclosesWeak(a, B[i])) { - return false; - } - } - return true; -} - -function encloseBasis(B) { - switch (B.length) { - case 1: return encloseBasis1(B[0]); - case 2: return encloseBasis2(B[0], B[1]); - case 3: return encloseBasis3(B[0], B[1], B[2]); - } -} - -function encloseBasis1(a) { - return { - x: a.x, - y: a.y, - r: a.r - }; -} - -function encloseBasis2(a, b) { - var x1 = a.x, y1 = a.y, r1 = a.r, - x2 = b.x, y2 = b.y, r2 = b.r, - x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, - l = Math.sqrt(x21 * x21 + y21 * y21); - return { - x: (x1 + x2 + x21 / l * r21) / 2, - y: (y1 + y2 + y21 / l * r21) / 2, - r: (l + r1 + r2) / 2 - }; -} - -function encloseBasis3(a, b, c) { - var x1 = a.x, y1 = a.y, r1 = a.r, - x2 = b.x, y2 = b.y, r2 = b.r, - x3 = c.x, y3 = c.y, r3 = c.r, - a2 = x1 - x2, - a3 = x1 - x3, - b2 = y1 - y2, - b3 = y1 - y3, - c2 = r2 - r1, - c3 = r3 - r1, - d1 = x1 * x1 + y1 * y1 - r1 * r1, - d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2, - d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3, - ab = a3 * b2 - a2 * b3, - xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1, - xb = (b3 * c2 - b2 * c3) / ab, - ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1, - yb = (a2 * c3 - a3 * c2) / ab, - A = xb * xb + yb * yb - 1, - B = 2 * (r1 + xa * xb + ya * yb), - C = xa * xa + ya * ya - r1 * r1, - r = -(A ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B); - return { - x: x1 + xa + xb * r, - y: y1 + ya + yb * r, - r: r - }; -} - -function place(b, a, c) { - var dx = b.x - a.x, x, a2, - dy = b.y - a.y, y, b2, - d2 = dx * dx + dy * dy; - if (d2) { - a2 = a.r + c.r, a2 *= a2; - b2 = b.r + c.r, b2 *= b2; - if (a2 > b2) { - x = (d2 + b2 - a2) / (2 * d2); - y = Math.sqrt(Math.max(0, b2 / d2 - x * x)); - c.x = b.x - x * dx - y * dy; - c.y = b.y - x * dy + y * dx; - } else { - x = (d2 + a2 - b2) / (2 * d2); - y = Math.sqrt(Math.max(0, a2 / d2 - x * x)); - c.x = a.x + x * dx - y * dy; - c.y = a.y + x * dy + y * dx; - } - } else { - c.x = a.x + c.r; - c.y = a.y; - } -} - -function intersects(a, b) { - var dr = a.r + b.r - 1e-6, dx = b.x - a.x, dy = b.y - a.y; - return dr > 0 && dr * dr > dx * dx + dy * dy; -} - -function score(node) { - var a = node._, - b = node.next._, - ab = a.r + b.r, - dx = (a.x * b.r + b.x * a.r) / ab, - dy = (a.y * b.r + b.y * a.r) / ab; - return dx * dx + dy * dy; -} - -function Node$1(circle) { - this._ = circle; - this.next = null; - this.previous = null; -} - -function packEnclose(circles) { - if (!(n = circles.length)) return 0; - - var a, b, c, n, aa, ca, i, j, k, sj, sk; - - // Place the first circle. - a = circles[0], a.x = 0, a.y = 0; - if (!(n > 1)) return a.r; - - // Place the second circle. - b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; - if (!(n > 2)) return a.r + b.r; - - // Place the third circle. - place(b, a, c = circles[2]); - - // Initialize the front-chain using the first three circles a, b and c. - a = new Node$1(a), b = new Node$1(b), c = new Node$1(c); - a.next = c.previous = b; - b.next = a.previous = c; - c.next = b.previous = a; - - // Attempt to place each remaining circle… - pack: for (i = 3; i < n; ++i) { - place(a._, b._, c = circles[i]), c = new Node$1(c); - - // Find the closest intersecting circle on the front-chain, if any. - // “Closeness” is determined by linear distance along the front-chain. - // “Ahead” or “behind” is likewise determined by linear distance. - j = b.next, k = a.previous, sj = b._.r, sk = a._.r; - do { - if (sj <= sk) { - if (intersects(j._, c._)) { - b = j, a.next = b, b.previous = a, --i; - continue pack; - } - sj += j._.r, j = j.next; - } else { - if (intersects(k._, c._)) { - a = k, a.next = b, b.previous = a, --i; - continue pack; - } - sk += k._.r, k = k.previous; - } - } while (j !== k.next); - - // Success! Insert the new circle c between a and b. - c.previous = a, c.next = b, a.next = b.previous = b = c; - - // Compute the new closest circle pair to the centroid. - aa = score(a); - while ((c = c.next) !== b) { - if ((ca = score(c)) < aa) { - a = c, aa = ca; - } - } - b = a.next; - } - - // Compute the enclosing circle of the front chain. - a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a); - - // Translate the circles to put the enclosing circle around the origin. - for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y; - - return c.r; -} - -function siblings(circles) { - packEnclose(circles); - return circles; -} - -function optional(f) { - return f == null ? null : required(f); -} - -function required(f) { - if (typeof f !== "function") throw new Error; - return f; -} - -function constantZero() { - return 0; -} - -function constant(x) { - return function() { - return x; - }; -} - -function defaultRadius(d) { - return Math.sqrt(d.value); -} - -function index() { - var radius = null, - dx = 1, - dy = 1, - padding = constantZero; - - function pack(root) { - root.x = dx / 2, root.y = dy / 2; - if (radius) { - root.eachBefore(radiusLeaf(radius)) - .eachAfter(packChildren(padding, 0.5)) - .eachBefore(translateChild(1)); - } else { - root.eachBefore(radiusLeaf(defaultRadius)) - .eachAfter(packChildren(constantZero, 1)) - .eachAfter(packChildren(padding, root.r / Math.min(dx, dy))) - .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); - } - return root; - } - - pack.radius = function(x) { - return arguments.length ? (radius = optional(x), pack) : radius; - }; - - pack.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; - }; - - pack.padding = function(x) { - return arguments.length ? (padding = typeof x === "function" ? x : constant(+x), pack) : padding; - }; - - return pack; -} - -function radiusLeaf(radius) { - return function(node) { - if (!node.children) { - node.r = Math.max(0, +radius(node) || 0); - } - }; -} - -function packChildren(padding, k) { - return function(node) { - if (children = node.children) { - var children, - i, - n = children.length, - r = padding(node) * k || 0, - e; - - if (r) for (i = 0; i < n; ++i) children[i].r += r; - e = packEnclose(children); - if (r) for (i = 0; i < n; ++i) children[i].r -= r; - node.r = e + r; - } - }; -} - -function translateChild(k) { - return function(node) { - var parent = node.parent; - node.r *= k; - if (parent) { - node.x = parent.x + k * node.x; - node.y = parent.y + k * node.y; - } - }; -} - -function roundNode(node) { - node.x0 = Math.round(node.x0); - node.y0 = Math.round(node.y0); - node.x1 = Math.round(node.x1); - node.y1 = Math.round(node.y1); -} - -function treemapDice(parent, x0, y0, x1, y1) { - var nodes = parent.children, - node, - i = -1, - n = nodes.length, - k = parent.value && (x1 - x0) / parent.value; - - while (++i < n) { - node = nodes[i], node.y0 = y0, node.y1 = y1; - node.x0 = x0, node.x1 = x0 += node.value * k; - } -} - -function partition() { - var dx = 1, - dy = 1, - padding = 0, - round = false; - - function partition(root) { - var n = root.height + 1; - root.x0 = - root.y0 = padding; - root.x1 = dx; - root.y1 = dy / n; - root.eachBefore(positionNode(dy, n)); - if (round) root.eachBefore(roundNode); - return root; - } - - function positionNode(dy, n) { - return function(node) { - if (node.children) { - treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); - } - var x0 = node.x0, - y0 = node.y0, - x1 = node.x1 - padding, - y1 = node.y1 - padding; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - node.x0 = x0; - node.y0 = y0; - node.x1 = x1; - node.y1 = y1; - }; - } - - partition.round = function(x) { - return arguments.length ? (round = !!x, partition) : round; - }; - - partition.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; - }; - - partition.padding = function(x) { - return arguments.length ? (padding = +x, partition) : padding; - }; - - return partition; -} - -var keyPrefix = "$", // Protect against keys like “__proto__”. - preroot = {depth: -1}, - ambiguous = {}; - -function defaultId(d) { - return d.id; -} - -function defaultParentId(d) { - return d.parentId; -} - -function stratify() { - var id = defaultId, - parentId = defaultParentId; - - function stratify(data) { - var d, - i, - n = data.length, - root, - parent, - node, - nodes = new Array(n), - nodeId, - nodeKey, - nodeByKey = {}; - - for (i = 0; i < n; ++i) { - d = data[i], node = nodes[i] = new Node(d); - if ((nodeId = id(d, i, data)) != null && (nodeId += "")) { - nodeKey = keyPrefix + (node.id = nodeId); - nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node; - } - } - - for (i = 0; i < n; ++i) { - node = nodes[i], nodeId = parentId(data[i], i, data); - if (nodeId == null || !(nodeId += "")) { - if (root) throw new Error("multiple roots"); - root = node; - } else { - parent = nodeByKey[keyPrefix + nodeId]; - if (!parent) throw new Error("missing: " + nodeId); - if (parent === ambiguous) throw new Error("ambiguous: " + nodeId); - if (parent.children) parent.children.push(node); - else parent.children = [node]; - node.parent = parent; - } - } - - if (!root) throw new Error("no root"); - root.parent = preroot; - root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight); - root.parent = null; - if (n > 0) throw new Error("cycle"); - - return root; - } - - stratify.id = function(x) { - return arguments.length ? (id = required(x), stratify) : id; - }; - - stratify.parentId = function(x) { - return arguments.length ? (parentId = required(x), stratify) : parentId; - }; - - return stratify; -} - -function defaultSeparation$1(a, b) { - return a.parent === b.parent ? 1 : 2; -} - -// function radialSeparation(a, b) { -// return (a.parent === b.parent ? 1 : 2) / a.depth; -// } - -// This function is used to traverse the left contour of a subtree (or -// subforest). It returns the successor of v on this contour. This successor is -// either given by the leftmost child of v or by the thread of v. The function -// returns null if and only if v is on the highest level of its subtree. -function nextLeft(v) { - var children = v.children; - return children ? children[0] : v.t; -} - -// This function works analogously to nextLeft. -function nextRight(v) { - var children = v.children; - return children ? children[children.length - 1] : v.t; -} - -// Shifts the current subtree rooted at w+. This is done by increasing -// prelim(w+) and mod(w+) by shift. -function moveSubtree(wm, wp, shift) { - var change = shift / (wp.i - wm.i); - wp.c -= change; - wp.s += shift; - wm.c += change; - wp.z += shift; - wp.m += shift; -} - -// All other shifts, applied to the smaller subtrees between w- and w+, are -// performed by this function. To prepare the shifts, we have to adjust -// change(w+), shift(w+), and change(w-). -function executeShifts(v) { - var shift = 0, - change = 0, - children = v.children, - i = children.length, - w; - while (--i >= 0) { - w = children[i]; - w.z += shift; - w.m += shift; - shift += w.s + (change += w.c); - } -} - -// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise, -// returns the specified (default) ancestor. -function nextAncestor(vim, v, ancestor) { - return vim.a.parent === v.parent ? vim.a : ancestor; -} - -function TreeNode(node, i) { - this._ = node; - this.parent = null; - this.children = null; - this.A = null; // default ancestor - this.a = this; // ancestor - this.z = 0; // prelim - this.m = 0; // mod - this.c = 0; // change - this.s = 0; // shift - this.t = null; // thread - this.i = i; // number -} - -TreeNode.prototype = Object.create(Node.prototype); - -function treeRoot(root) { - var tree = new TreeNode(root, 0), - node, - nodes = [tree], - child, - children, - i, - n; - - while (node = nodes.pop()) { - if (children = node._.children) { - node.children = new Array(n = children.length); - for (i = n - 1; i >= 0; --i) { - nodes.push(child = node.children[i] = new TreeNode(children[i], i)); - child.parent = node; - } - } - } - - (tree.parent = new TreeNode(null, 0)).children = [tree]; - return tree; -} - -// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm -function tree() { - var separation = defaultSeparation$1, - dx = 1, - dy = 1, - nodeSize = null; - - function tree(root) { - var t = treeRoot(root); - - // Compute the layout using Buchheim et al.’s algorithm. - t.eachAfter(firstWalk), t.parent.m = -t.z; - t.eachBefore(secondWalk); - - // If a fixed node size is specified, scale x and y. - if (nodeSize) root.eachBefore(sizeNode); - - // If a fixed tree size is specified, scale x and y based on the extent. - // Compute the left-most, right-most, and depth-most nodes for extents. - else { - var left = root, - right = root, - bottom = root; - root.eachBefore(function(node) { - if (node.x < left.x) left = node; - if (node.x > right.x) right = node; - if (node.depth > bottom.depth) bottom = node; - }); - var s = left === right ? 1 : separation(left, right) / 2, - tx = s - left.x, - kx = dx / (right.x + s + tx), - ky = dy / (bottom.depth || 1); - root.eachBefore(function(node) { - node.x = (node.x + tx) * kx; - node.y = node.depth * ky; - }); - } - - return root; - } - - // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is - // applied recursively to the children of v, as well as the function - // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the - // node v is placed to the midpoint of its outermost children. - function firstWalk(v) { - var children = v.children, - siblings = v.parent.children, - w = v.i ? siblings[v.i - 1] : null; - if (children) { - executeShifts(v); - var midpoint = (children[0].z + children[children.length - 1].z) / 2; - if (w) { - v.z = w.z + separation(v._, w._); - v.m = v.z - midpoint; - } else { - v.z = midpoint; - } - } else if (w) { - v.z = w.z + separation(v._, w._); - } - v.parent.A = apportion(v, w, v.parent.A || siblings[0]); - } - - // Computes all real x-coordinates by summing up the modifiers recursively. - function secondWalk(v) { - v._.x = v.z + v.parent.m; - v.m += v.parent.m; - } - - // The core of the algorithm. Here, a new subtree is combined with the - // previous subtrees. Threads are used to traverse the inside and outside - // contours of the left and right subtree up to the highest common level. The - // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the - // superscript o means outside and i means inside, the subscript - means left - // subtree and + means right subtree. For summing up the modifiers along the - // contour, we use respective variables si+, si-, so-, and so+. Whenever two - // nodes of the inside contours conflict, we compute the left one of the - // greatest uncommon ancestors using the function ANCESTOR and call MOVE - // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees. - // Finally, we add a new thread (if necessary). - function apportion(v, w, ancestor) { - if (w) { - var vip = v, - vop = v, - vim = w, - vom = vip.parent.children[0], - sip = vip.m, - sop = vop.m, - sim = vim.m, - som = vom.m, - shift; - while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) { - vom = nextLeft(vom); - vop = nextRight(vop); - vop.a = v; - shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); - if (shift > 0) { - moveSubtree(nextAncestor(vim, v, ancestor), v, shift); - sip += shift; - sop += shift; - } - sim += vim.m; - sip += vip.m; - som += vom.m; - sop += vop.m; - } - if (vim && !nextRight(vop)) { - vop.t = vim; - vop.m += sim - sop; - } - if (vip && !nextLeft(vom)) { - vom.t = vip; - vom.m += sip - som; - ancestor = v; - } - } - return ancestor; - } - - function sizeNode(node) { - node.x *= dx; - node.y = node.depth * dy; - } - - tree.separation = function(x) { - return arguments.length ? (separation = x, tree) : separation; - }; - - tree.size = function(x) { - return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]); - }; - - tree.nodeSize = function(x) { - return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null); - }; - - return tree; -} - -function treemapSlice(parent, x0, y0, x1, y1) { - var nodes = parent.children, - node, - i = -1, - n = nodes.length, - k = parent.value && (y1 - y0) / parent.value; - - while (++i < n) { - node = nodes[i], node.x0 = x0, node.x1 = x1; - node.y0 = y0, node.y1 = y0 += node.value * k; - } -} - -var phi = (1 + Math.sqrt(5)) / 2; - -function squarifyRatio(ratio, parent, x0, y0, x1, y1) { - var rows = [], - nodes = parent.children, - row, - nodeValue, - i0 = 0, - i1 = 0, - n = nodes.length, - dx, dy, - value = parent.value, - sumValue, - minValue, - maxValue, - newRatio, - minRatio, - alpha, - beta; - - while (i0 < n) { - dx = x1 - x0, dy = y1 - y0; - - // Find the next non-empty node. - do sumValue = nodes[i1++].value; while (!sumValue && i1 < n); - minValue = maxValue = sumValue; - alpha = Math.max(dy / dx, dx / dy) / (value * ratio); - beta = sumValue * sumValue * alpha; - minRatio = Math.max(maxValue / beta, beta / minValue); - - // Keep adding nodes while the aspect ratio maintains or improves. - for (; i1 < n; ++i1) { - sumValue += nodeValue = nodes[i1].value; - if (nodeValue < minValue) minValue = nodeValue; - if (nodeValue > maxValue) maxValue = nodeValue; - beta = sumValue * sumValue * alpha; - newRatio = Math.max(maxValue / beta, beta / minValue); - if (newRatio > minRatio) { sumValue -= nodeValue; break; } - minRatio = newRatio; - } - - // Position and record the row orientation. - rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); - if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); - else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); - value -= sumValue, i0 = i1; - } - - return rows; -} - -var squarify = (function custom(ratio) { - - function squarify(parent, x0, y0, x1, y1) { - squarifyRatio(ratio, parent, x0, y0, x1, y1); - } - - squarify.ratio = function(x) { - return custom((x = +x) > 1 ? x : 1); - }; - - return squarify; -})(phi); - -function index$1() { - var tile = squarify, - round = false, - dx = 1, - dy = 1, - paddingStack = [0], - paddingInner = constantZero, - paddingTop = constantZero, - paddingRight = constantZero, - paddingBottom = constantZero, - paddingLeft = constantZero; - - function treemap(root) { - root.x0 = - root.y0 = 0; - root.x1 = dx; - root.y1 = dy; - root.eachBefore(positionNode); - paddingStack = [0]; - if (round) root.eachBefore(roundNode); - return root; - } - - function positionNode(node) { - var p = paddingStack[node.depth], - x0 = node.x0 + p, - y0 = node.y0 + p, - x1 = node.x1 - p, - y1 = node.y1 - p; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - node.x0 = x0; - node.y0 = y0; - node.x1 = x1; - node.y1 = y1; - if (node.children) { - p = paddingStack[node.depth + 1] = paddingInner(node) / 2; - x0 += paddingLeft(node) - p; - y0 += paddingTop(node) - p; - x1 -= paddingRight(node) - p; - y1 -= paddingBottom(node) - p; - if (x1 < x0) x0 = x1 = (x0 + x1) / 2; - if (y1 < y0) y0 = y1 = (y0 + y1) / 2; - tile(node, x0, y0, x1, y1); - } - } - - treemap.round = function(x) { - return arguments.length ? (round = !!x, treemap) : round; - }; - - treemap.size = function(x) { - return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy]; - }; - - treemap.tile = function(x) { - return arguments.length ? (tile = required(x), treemap) : tile; - }; - - treemap.padding = function(x) { - return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner(); - }; - - treemap.paddingInner = function(x) { - return arguments.length ? (paddingInner = typeof x === "function" ? x : constant(+x), treemap) : paddingInner; - }; - - treemap.paddingOuter = function(x) { - return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop(); - }; - - treemap.paddingTop = function(x) { - return arguments.length ? (paddingTop = typeof x === "function" ? x : constant(+x), treemap) : paddingTop; - }; - - treemap.paddingRight = function(x) { - return arguments.length ? (paddingRight = typeof x === "function" ? x : constant(+x), treemap) : paddingRight; - }; - - treemap.paddingBottom = function(x) { - return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant(+x), treemap) : paddingBottom; - }; - - treemap.paddingLeft = function(x) { - return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant(+x), treemap) : paddingLeft; - }; - - return treemap; -} - -function binary(parent, x0, y0, x1, y1) { - var nodes = parent.children, - i, n = nodes.length, - sum, sums = new Array(n + 1); - - for (sums[0] = sum = i = 0; i < n; ++i) { - sums[i + 1] = sum += nodes[i].value; - } - - partition(0, n, parent.value, x0, y0, x1, y1); - - function partition(i, j, value, x0, y0, x1, y1) { - if (i >= j - 1) { - var node = nodes[i]; - node.x0 = x0, node.y0 = y0; - node.x1 = x1, node.y1 = y1; - return; - } - - var valueOffset = sums[i], - valueTarget = (value / 2) + valueOffset, - k = i + 1, - hi = j - 1; - - while (k < hi) { - var mid = k + hi >>> 1; - if (sums[mid] < valueTarget) k = mid + 1; - else hi = mid; - } - - if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k; - - var valueLeft = sums[k] - valueOffset, - valueRight = value - valueLeft; - - if ((x1 - x0) > (y1 - y0)) { - var xk = (x0 * valueRight + x1 * valueLeft) / value; - partition(i, k, valueLeft, x0, y0, xk, y1); - partition(k, j, valueRight, xk, y0, x1, y1); - } else { - var yk = (y0 * valueRight + y1 * valueLeft) / value; - partition(i, k, valueLeft, x0, y0, x1, yk); - partition(k, j, valueRight, x0, yk, x1, y1); - } - } -} - -function sliceDice(parent, x0, y0, x1, y1) { - (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1); -} - -var resquarify = (function custom(ratio) { - - function resquarify(parent, x0, y0, x1, y1) { - if ((rows = parent._squarify) && (rows.ratio === ratio)) { - var rows, - row, - nodes, - i, - j = -1, - n, - m = rows.length, - value = parent.value; - - while (++j < m) { - row = rows[j], nodes = row.children; - for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value; - if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value); - else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1); - value -= row.value; - } - } else { - parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1); - rows.ratio = ratio; - } - } - - resquarify.ratio = function(x) { - return custom((x = +x) > 1 ? x : 1); - }; - - return resquarify; -})(phi); - -exports.cluster = cluster; -exports.hierarchy = hierarchy; -exports.pack = index; -exports.packSiblings = siblings; -exports.packEnclose = enclose; -exports.partition = partition; -exports.stratify = stratify; -exports.tree = tree; -exports.treemap = index$1; -exports.treemapBinary = binary; -exports.treemapDice = treemapDice; -exports.treemapSlice = treemapSlice; -exports.treemapSliceDice = sliceDice; -exports.treemapSquarify = squarify; -exports.treemapResquarify = resquarify; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{}],158:[function(_dereq_,module,exports){ -// https://d3js.org/d3-interpolate/ v1.3.2 Copyright 2018 Mike Bostock -(function (global, factory) { -typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, _dereq_('d3-color')) : -typeof define === 'function' && define.amd ? define(['exports', 'd3-color'], factory) : -(factory((global.d3 = global.d3 || {}),global.d3)); -}(this, (function (exports,d3Color) { 'use strict'; - -function basis(t1, v0, v1, v2, v3) { - var t2 = t1 * t1, t3 = t2 * t1; - return ((1 - 3 * t1 + 3 * t2 - t3) * v0 - + (4 - 6 * t2 + 3 * t3) * v1 - + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 - + t3 * v3) / 6; -} - -function basis$1(values) { - var n = values.length - 1; - return function(t) { - var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), - v1 = values[i], - v2 = values[i + 1], - v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, - v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; - return basis((t - i / n) * n, v0, v1, v2, v3); - }; -} - -function basisClosed(values) { - var n = values.length; - return function(t) { - var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), - v0 = values[(i + n - 1) % n], - v1 = values[i % n], - v2 = values[(i + 1) % n], - v3 = values[(i + 2) % n]; - return basis((t - i / n) * n, v0, v1, v2, v3); - }; -} - -function constant(x) { - return function() { - return x; - }; -} - -function linear(a, d) { - return function(t) { - return a + t * d; - }; -} - -function exponential(a, b, y) { - return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { - return Math.pow(a + t * b, y); - }; -} - -function hue(a, b) { - var d = b - a; - return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant(isNaN(a) ? b : a); -} - -function gamma(y) { - return (y = +y) === 1 ? nogamma : function(a, b) { - return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a); - }; -} - -function nogamma(a, b) { - var d = b - a; - return d ? linear(a, d) : constant(isNaN(a) ? b : a); -} - -var rgb = (function rgbGamma(y) { - var color = gamma(y); - - function rgb(start, end) { - var r = color((start = d3Color.rgb(start)).r, (end = d3Color.rgb(end)).r), - g = color(start.g, end.g), - b = color(start.b, end.b), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.r = r(t); - start.g = g(t); - start.b = b(t); - start.opacity = opacity(t); - return start + ""; - }; - } - - rgb.gamma = rgbGamma; - - return rgb; -})(1); - -function rgbSpline(spline) { - return function(colors) { - var n = colors.length, - r = new Array(n), - g = new Array(n), - b = new Array(n), - i, color; - for (i = 0; i < n; ++i) { - color = d3Color.rgb(colors[i]); - r[i] = color.r || 0; - g[i] = color.g || 0; - b[i] = color.b || 0; - } - r = spline(r); - g = spline(g); - b = spline(b); - color.opacity = 1; - return function(t) { - color.r = r(t); - color.g = g(t); - color.b = b(t); - return color + ""; - }; - }; -} - -var rgbBasis = rgbSpline(basis$1); -var rgbBasisClosed = rgbSpline(basisClosed); - -function array(a, b) { - var nb = b ? b.length : 0, - na = a ? Math.min(nb, a.length) : 0, - x = new Array(na), - c = new Array(nb), - i; - - for (i = 0; i < na; ++i) x[i] = value(a[i], b[i]); - for (; i < nb; ++i) c[i] = b[i]; - - return function(t) { - for (i = 0; i < na; ++i) c[i] = x[i](t); - return c; - }; -} - -function date(a, b) { - var d = new Date; - return a = +a, b -= a, function(t) { - return d.setTime(a + b * t), d; - }; -} - -function number(a, b) { - return a = +a, b -= a, function(t) { - return a + b * t; - }; -} - -function object(a, b) { - var i = {}, - c = {}, - k; - - if (a === null || typeof a !== "object") a = {}; - if (b === null || typeof b !== "object") b = {}; - - for (k in b) { - if (k in a) { - i[k] = value(a[k], b[k]); - } else { - c[k] = b[k]; - } - } - - return function(t) { - for (k in i) c[k] = i[k](t); - return c; - }; -} - -var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, - reB = new RegExp(reA.source, "g"); - -function zero(b) { - return function() { - return b; - }; -} - -function one(b) { - return function(t) { - return b(t) + ""; - }; -} - -function string(a, b) { - var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b - am, // current match in a - bm, // current match in b - bs, // string preceding current number in b, if any - i = -1, // index in s - s = [], // string constants and placeholders - q = []; // number interpolators - - // Coerce inputs to strings. - a = a + "", b = b + ""; - - // Interpolate pairs of numbers in a & b. - while ((am = reA.exec(a)) - && (bm = reB.exec(b))) { - if ((bs = bm.index) > bi) { // a string precedes the next number in b - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match - if (s[i]) s[i] += bm; // coalesce with previous string - else s[++i] = bm; - } else { // interpolate non-matching numbers - s[++i] = null; - q.push({i: i, x: number(am, bm)}); - } - bi = reB.lastIndex; - } - - // Add remains of b. - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; // coalesce with previous string - else s[++i] = bs; - } - - // Special optimization for only a single match. - // Otherwise, interpolate each of the numbers and rejoin the string. - return s.length < 2 ? (q[0] - ? one(q[0].x) - : zero(b)) - : (b = q.length, function(t) { - for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }); -} - -function value(a, b) { - var t = typeof b, c; - return b == null || t === "boolean" ? constant(b) - : (t === "number" ? number - : t === "string" ? ((c = d3Color.color(b)) ? (b = c, rgb) : string) - : b instanceof d3Color.color ? rgb - : b instanceof Date ? date - : Array.isArray(b) ? array - : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object - : number)(a, b); -} - -function discrete(range) { - var n = range.length; - return function(t) { - return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; - }; -} - -function hue$1(a, b) { - var i = hue(+a, +b); - return function(t) { - var x = i(t); - return x - 360 * Math.floor(x / 360); - }; -} - -function round(a, b) { - return a = +a, b -= a, function(t) { - return Math.round(a + b * t); - }; -} - -var degrees = 180 / Math.PI; - -var identity = { - translateX: 0, - translateY: 0, - rotate: 0, - skewX: 0, - scaleX: 1, - scaleY: 1 -}; - -function decompose(a, b, c, d, e, f) { - var scaleX, scaleY, skewX; - if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; - if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; - if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; - if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; - return { - translateX: e, - translateY: f, - rotate: Math.atan2(b, a) * degrees, - skewX: Math.atan(skewX) * degrees, - scaleX: scaleX, - scaleY: scaleY - }; -} - -var cssNode, - cssRoot, - cssView, - svgNode; - -function parseCss(value) { - if (value === "none") return identity; - if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; - cssNode.style.transform = value; - value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); - cssRoot.removeChild(cssNode); - value = value.slice(7, -1).split(","); - return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); -} - -function parseSvg(value) { - if (value == null) return identity; - if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); - svgNode.setAttribute("transform", value); - if (!(value = svgNode.transform.baseVal.consolidate())) return identity; - value = value.matrix; - return decompose(value.a, value.b, value.c, value.d, value.e, value.f); -} - -function interpolateTransform(parse, pxComma, pxParen, degParen) { - - function pop(s) { - return s.length ? s.pop() + " " : ""; - } - - function translate(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push("translate(", null, pxComma, null, pxParen); - q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); - } else if (xb || yb) { - s.push("translate(" + xb + pxComma + yb + pxParen); - } - } - - function rotate(a, b, s, q) { - if (a !== b) { - if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path - q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number(a, b)}); - } else if (b) { - s.push(pop(s) + "rotate(" + b + degParen); - } - } - - function skewX(a, b, s, q) { - if (a !== b) { - q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number(a, b)}); - } else if (b) { - s.push(pop(s) + "skewX(" + b + degParen); - } - } - - function scale(xa, ya, xb, yb, s, q) { - if (xa !== xb || ya !== yb) { - var i = s.push(pop(s) + "scale(", null, ",", null, ")"); - q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); - } else if (xb !== 1 || yb !== 1) { - s.push(pop(s) + "scale(" + xb + "," + yb + ")"); - } - } - - return function(a, b) { - var s = [], // string constants and placeholders - q = []; // number interpolators - a = parse(a), b = parse(b); - translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); - rotate(a.rotate, b.rotate, s, q); - skewX(a.skewX, b.skewX, s, q); - scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); - a = b = null; // gc - return function(t) { - var i = -1, n = q.length, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - }; -} - -var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); -var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); - -var rho = Math.SQRT2, - rho2 = 2, - rho4 = 4, - epsilon2 = 1e-12; - -function cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; -} - -function sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; -} - -function tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); -} - -// p0 = [ux0, uy0, w0] -// p1 = [ux1, uy1, w1] -function zoom(p0, p1) { - var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], - ux1 = p1[0], uy1 = p1[1], w1 = p1[2], - dx = ux1 - ux0, - dy = uy1 - uy0, - d2 = dx * dx + dy * dy, - i, - S; - - // Special case for u0 ≅ u1. - if (d2 < epsilon2) { - S = Math.log(w1 / w0) / rho; - i = function(t) { - return [ - ux0 + t * dx, - uy0 + t * dy, - w0 * Math.exp(rho * t * S) - ]; - }; - } - - // General case. - else { - var d1 = Math.sqrt(d2), - b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), - b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), - r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), - r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); - S = (r1 - r0) / rho; - i = function(t) { - var s = t * S, - coshr0 = cosh(r0), - u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); - return [ - ux0 + u * dx, - uy0 + u * dy, - w0 * coshr0 / cosh(rho * s + r0) - ]; - }; - } - - i.duration = S * 1000; - - return i; -} - -function hsl(hue$$1) { - return function(start, end) { - var h = hue$$1((start = d3Color.hsl(start)).h, (end = d3Color.hsl(end)).h), - s = nogamma(start.s, end.s), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.s = s(t); - start.l = l(t); - start.opacity = opacity(t); - return start + ""; - }; - } -} - -var hsl$1 = hsl(hue); -var hslLong = hsl(nogamma); - -function lab(start, end) { - var l = nogamma((start = d3Color.lab(start)).l, (end = d3Color.lab(end)).l), - a = nogamma(start.a, end.a), - b = nogamma(start.b, end.b), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.l = l(t); - start.a = a(t); - start.b = b(t); - start.opacity = opacity(t); - return start + ""; - }; -} - -function hcl(hue$$1) { - return function(start, end) { - var h = hue$$1((start = d3Color.hcl(start)).h, (end = d3Color.hcl(end)).h), - c = nogamma(start.c, end.c), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.c = c(t); - start.l = l(t); - start.opacity = opacity(t); - return start + ""; - }; - } -} - -var hcl$1 = hcl(hue); -var hclLong = hcl(nogamma); - -function cubehelix(hue$$1) { - return (function cubehelixGamma(y) { - y = +y; - - function cubehelix(start, end) { - var h = hue$$1((start = d3Color.cubehelix(start)).h, (end = d3Color.cubehelix(end)).h), - s = nogamma(start.s, end.s), - l = nogamma(start.l, end.l), - opacity = nogamma(start.opacity, end.opacity); - return function(t) { - start.h = h(t); - start.s = s(t); - start.l = l(Math.pow(t, y)); - start.opacity = opacity(t); - return start + ""; - }; - } - - cubehelix.gamma = cubehelixGamma; - - return cubehelix; - })(1); -} - -var cubehelix$1 = cubehelix(hue); -var cubehelixLong = cubehelix(nogamma); - -function piecewise(interpolate, values) { - var i = 0, n = values.length - 1, v = values[0], I = new Array(n < 0 ? 0 : n); - while (i < n) I[i] = interpolate(v, v = values[++i]); - return function(t) { - var i = Math.max(0, Math.min(n - 1, Math.floor(t *= n))); - return I[i](t - i); - }; -} - -function quantize(interpolator, n) { - var samples = new Array(n); - for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); - return samples; -} - -exports.interpolate = value; -exports.interpolateArray = array; -exports.interpolateBasis = basis$1; -exports.interpolateBasisClosed = basisClosed; -exports.interpolateDate = date; -exports.interpolateDiscrete = discrete; -exports.interpolateHue = hue$1; -exports.interpolateNumber = number; -exports.interpolateObject = object; -exports.interpolateRound = round; -exports.interpolateString = string; -exports.interpolateTransformCss = interpolateTransformCss; -exports.interpolateTransformSvg = interpolateTransformSvg; -exports.interpolateZoom = zoom; -exports.interpolateRgb = rgb; -exports.interpolateRgbBasis = rgbBasis; -exports.interpolateRgbBasisClosed = rgbBasisClosed; -exports.interpolateHsl = hsl$1; -exports.interpolateHslLong = hslLong; -exports.interpolateLab = lab; -exports.interpolateHcl = hcl$1; -exports.interpolateHclLong = hclLong; -exports.interpolateCubehelix = cubehelix$1; -exports.interpolateCubehelixLong = cubehelixLong; -exports.piecewise = piecewise; -exports.quantize = quantize; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{"d3-color":154}],159:[function(_dereq_,module,exports){ -// https://d3js.org/d3-path/ v1.0.7 Copyright 2018 Mike Bostock -(function (global, factory) { -typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : -typeof define === 'function' && define.amd ? define(['exports'], factory) : -(factory((global.d3 = global.d3 || {}))); -}(this, (function (exports) { 'use strict'; - -var pi = Math.PI, - tau = 2 * pi, - epsilon = 1e-6, - tauEpsilon = tau - epsilon; - -function Path() { - this._x0 = this._y0 = // start of current subpath - this._x1 = this._y1 = null; // end of current subpath - this._ = ""; -} - -function path() { - return new Path; -} - -Path.prototype = path.prototype = { - constructor: Path, - moveTo: function(x, y) { - this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y); - }, - closePath: function() { - if (this._x1 !== null) { - this._x1 = this._x0, this._y1 = this._y0; - this._ += "Z"; - } - }, - lineTo: function(x, y) { - this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y); - }, - quadraticCurveTo: function(x1, y1, x, y) { - this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y); - }, - bezierCurveTo: function(x1, y1, x2, y2, x, y) { - this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y); - }, - arcTo: function(x1, y1, x2, y2, r) { - x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; - var x0 = this._x1, - y0 = this._y1, - x21 = x2 - x1, - y21 = y2 - y1, - x01 = x0 - x1, - y01 = y0 - y1, - l01_2 = x01 * x01 + y01 * y01; - - // Is the radius negative? Error. - if (r < 0) throw new Error("negative radius: " + r); - - // Is this path empty? Move to (x1,y1). - if (this._x1 === null) { - this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1); - } - - // Or, is (x1,y1) coincident with (x0,y0)? Do nothing. - else if (!(l01_2 > epsilon)); - - // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? - // Equivalently, is (x1,y1) coincident with (x2,y2)? - // Or, is the radius zero? Line to (x1,y1). - else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) { - this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1); - } - - // Otherwise, draw an arc! - else { - var x20 = x2 - x0, - y20 = y2 - y0, - l21_2 = x21 * x21 + y21 * y21, - l20_2 = x20 * x20 + y20 * y20, - l21 = Math.sqrt(l21_2), - l01 = Math.sqrt(l01_2), - l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), - t01 = l / l01, - t21 = l / l21; - - // If the start tangent is not coincident with (x0,y0), line to. - if (Math.abs(t01 - 1) > epsilon) { - this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01); - } - - this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21); - } - }, - arc: function(x, y, r, a0, a1, ccw) { - x = +x, y = +y, r = +r; - var dx = r * Math.cos(a0), - dy = r * Math.sin(a0), - x0 = x + dx, - y0 = y + dy, - cw = 1 ^ ccw, - da = ccw ? a0 - a1 : a1 - a0; - - // Is the radius negative? Error. - if (r < 0) throw new Error("negative radius: " + r); - - // Is this path empty? Move to (x0,y0). - if (this._x1 === null) { - this._ += "M" + x0 + "," + y0; - } - - // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). - else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) { - this._ += "L" + x0 + "," + y0; - } - - // Is this arc empty? We’re done. - if (!r) return; - - // Does the angle go the wrong way? Flip the direction. - if (da < 0) da = da % tau + tau; - - // Is this a complete circle? Draw two arcs to complete the circle. - if (da > tauEpsilon) { - this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0); - } - - // Is this arc non-empty? Draw an arc! - else if (da > epsilon) { - this._ += "A" + r + "," + r + ",0," + (+(da >= pi)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1)); - } - }, - rect: function(x, y, w, h) { - this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z"; - }, - toString: function() { - return this._; - } -}; - -exports.path = path; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{}],160:[function(_dereq_,module,exports){ -// https://d3js.org/d3-quadtree/ Version 1.0.3. Copyright 2017 Mike Bostock. -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.d3 = global.d3 || {}))); -}(this, (function (exports) { 'use strict'; - -var tree_add = function(d) { - var x = +this._x.call(null, d), - y = +this._y.call(null, d); - return add(this.cover(x, y), x, y, d); -}; - -function add(tree, x, y, d) { - if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points - - var parent, - node = tree._root, - leaf = {data: d}, - x0 = tree._x0, - y0 = tree._y0, - x1 = tree._x1, - y1 = tree._y1, - xm, - ym, - xp, - yp, - right, - bottom, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return tree._root = leaf, tree; - - // Find the existing leaf for the new point, or add it. - while (node.length) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; - } - - // Is the new point is exactly coincident with the existing point? - xp = +tree._x.call(null, node.data); - yp = +tree._y.call(null, node.data); - if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; - - // Otherwise, split the leaf node until the old and new point are separated. - do { - parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); - return parent[j] = node, parent[i] = leaf, tree; -} - -function addAll(data) { - var d, i, n = data.length, - x, - y, - xz = new Array(n), - yz = new Array(n), - x0 = Infinity, - y0 = Infinity, - x1 = -Infinity, - y1 = -Infinity; - - // Compute the points and their extent. - for (i = 0; i < n; ++i) { - if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; - xz[i] = x; - yz[i] = y; - if (x < x0) x0 = x; - if (x > x1) x1 = x; - if (y < y0) y0 = y; - if (y > y1) y1 = y; - } - - // If there were no (valid) points, inherit the existing extent. - if (x1 < x0) x0 = this._x0, x1 = this._x1; - if (y1 < y0) y0 = this._y0, y1 = this._y1; - - // Expand the tree to cover the new points. - this.cover(x0, y0).cover(x1, y1); - - // Add the new points. - for (i = 0; i < n; ++i) { - add(this, xz[i], yz[i], data[i]); - } - - return this; -} - -var tree_cover = function(x, y) { - if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points - - var x0 = this._x0, - y0 = this._y0, - x1 = this._x1, - y1 = this._y1; - - // If the quadtree has no extent, initialize them. - // Integer extent are necessary so that if we later double the extent, - // the existing quadrant boundaries don’t change due to floating point error! - if (isNaN(x0)) { - x1 = (x0 = Math.floor(x)) + 1; - y1 = (y0 = Math.floor(y)) + 1; - } - - // Otherwise, double repeatedly to cover. - else if (x0 > x || x > x1 || y0 > y || y > y1) { - var z = x1 - x0, - node = this._root, - parent, - i; - - switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) { - case 0: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1); - break; - } - case 1: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1); - break; - } - case 2: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y); - break; - } - case 3: { - do parent = new Array(4), parent[i] = node, node = parent; - while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y); - break; - } - } - - if (this._root && this._root.length) this._root = node; - } - - // If the quadtree covers the point already, just return. - else return this; - - this._x0 = x0; - this._y0 = y0; - this._x1 = x1; - this._y1 = y1; - return this; -}; - -var tree_data = function() { - var data = []; - this.visit(function(node) { - if (!node.length) do data.push(node.data); while (node = node.next) - }); - return data; -}; - -var tree_extent = function(_) { - return arguments.length - ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) - : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; -}; - -var Quad = function(node, x0, y0, x1, y1) { - this.node = node; - this.x0 = x0; - this.y0 = y0; - this.x1 = x1; - this.y1 = y1; -}; - -var tree_find = function(x, y, radius) { - var data, - x0 = this._x0, - y0 = this._y0, - x1, - y1, - x2, - y2, - x3 = this._x1, - y3 = this._y1, - quads = [], - node = this._root, - q, - i; - - if (node) quads.push(new Quad(node, x0, y0, x3, y3)); - if (radius == null) radius = Infinity; - else { - x0 = x - radius, y0 = y - radius; - x3 = x + radius, y3 = y + radius; - radius *= radius; - } - - while (q = quads.pop()) { - - // Stop searching if this quadrant can’t contain a closer node. - if (!(node = q.node) - || (x1 = q.x0) > x3 - || (y1 = q.y0) > y3 - || (x2 = q.x1) < x0 - || (y2 = q.y1) < y0) continue; - - // Bisect the current quadrant. - if (node.length) { - var xm = (x1 + x2) / 2, - ym = (y1 + y2) / 2; - - quads.push( - new Quad(node[3], xm, ym, x2, y2), - new Quad(node[2], x1, ym, xm, y2), - new Quad(node[1], xm, y1, x2, ym), - new Quad(node[0], x1, y1, xm, ym) - ); - - // Visit the closest quadrant first. - if (i = (y >= ym) << 1 | (x >= xm)) { - q = quads[quads.length - 1]; - quads[quads.length - 1] = quads[quads.length - 1 - i]; - quads[quads.length - 1 - i] = q; - } - } - - // Visit this point. (Visiting coincident points isn’t necessary!) - else { - var dx = x - +this._x.call(null, node.data), - dy = y - +this._y.call(null, node.data), - d2 = dx * dx + dy * dy; - if (d2 < radius) { - var d = Math.sqrt(radius = d2); - x0 = x - d, y0 = y - d; - x3 = x + d, y3 = y + d; - data = node.data; - } - } - } - - return data; -}; - -var tree_remove = function(d) { - if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points - - var parent, - node = this._root, - retainer, - previous, - next, - x0 = this._x0, - y0 = this._y0, - x1 = this._x1, - y1 = this._y1, - x, - y, - xm, - ym, - right, - bottom, - i, - j; - - // If the tree is empty, initialize the root as a leaf. - if (!node) return this; - - // Find the leaf node for the point. - // While descending, also retain the deepest parent with a non-removed sibling. - if (node.length) while (true) { - if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; - if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; - if (!(parent = node, node = node[i = bottom << 1 | right])) return this; - if (!node.length) break; - if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; - } - - // Find the point to remove. - while (node.data !== d) if (!(previous = node, node = node.next)) return this; - if (next = node.next) delete node.next; - - // If there are multiple coincident points, remove just the point. - if (previous) return (next ? previous.next = next : delete previous.next), this; - - // If this is the root point, remove it. - if (!parent) return this._root = next, this; - - // Remove this leaf. - next ? parent[i] = next : delete parent[i]; - - // If the parent now contains exactly one leaf, collapse superfluous parents. - if ((node = parent[0] || parent[1] || parent[2] || parent[3]) - && node === (parent[3] || parent[2] || parent[1] || parent[0]) - && !node.length) { - if (retainer) retainer[j] = node; - else this._root = node; - } - - return this; -}; - -function removeAll(data) { - for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); - return this; -} - -var tree_root = function() { - return this._root; -}; - -var tree_size = function() { - var size = 0; - this.visit(function(node) { - if (!node.length) do ++size; while (node = node.next) - }); - return size; -}; - -var tree_visit = function(callback) { - var quads = [], q, node = this._root, child, x0, y0, x1, y1; - if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); - while (q = quads.pop()) { - if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { - var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; - if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); - if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); - if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); - if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); - } - } - return this; -}; - -var tree_visitAfter = function(callback) { - var quads = [], next = [], q; - if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); - while (q = quads.pop()) { - var node = q.node; - if (node.length) { - var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; - if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); - if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); - if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); - if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); - } - next.push(q); - } - while (q = next.pop()) { - callback(q.node, q.x0, q.y0, q.x1, q.y1); - } - return this; -}; - -function defaultX(d) { - return d[0]; -} - -var tree_x = function(_) { - return arguments.length ? (this._x = _, this) : this._x; -}; - -function defaultY(d) { - return d[1]; -} - -var tree_y = function(_) { - return arguments.length ? (this._y = _, this) : this._y; -}; - -function quadtree(nodes, x, y) { - var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN); - return nodes == null ? tree : tree.addAll(nodes); -} - -function Quadtree(x, y, x0, y0, x1, y1) { - this._x = x; - this._y = y; - this._x0 = x0; - this._y0 = y0; - this._x1 = x1; - this._y1 = y1; - this._root = undefined; -} - -function leaf_copy(leaf) { - var copy = {data: leaf.data}, next = copy; - while (leaf = leaf.next) next = next.next = {data: leaf.data}; - return copy; -} - -var treeProto = quadtree.prototype = Quadtree.prototype; - -treeProto.copy = function() { - var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), - node = this._root, - nodes, - child; - - if (!node) return copy; - - if (!node.length) return copy._root = leaf_copy(node), copy; - - nodes = [{source: node, target: copy._root = new Array(4)}]; - while (node = nodes.pop()) { - for (var i = 0; i < 4; ++i) { - if (child = node.source[i]) { - if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); - else node.target[i] = leaf_copy(child); - } - } - } - - return copy; -}; - -treeProto.add = tree_add; -treeProto.addAll = addAll; -treeProto.cover = tree_cover; -treeProto.data = tree_data; -treeProto.extent = tree_extent; -treeProto.find = tree_find; -treeProto.remove = tree_remove; -treeProto.removeAll = removeAll; -treeProto.root = tree_root; -treeProto.size = tree_size; -treeProto.visit = tree_visit; -treeProto.visitAfter = tree_visitAfter; -treeProto.x = tree_x; -treeProto.y = tree_y; - -exports.quadtree = quadtree; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{}],161:[function(_dereq_,module,exports){ -// https://d3js.org/d3-shape/ v1.3.4 Copyright 2019 Mike Bostock -(function (global, factory) { -typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, _dereq_('d3-path')) : -typeof define === 'function' && define.amd ? define(['exports', 'd3-path'], factory) : -(factory((global.d3 = global.d3 || {}),global.d3)); -}(this, (function (exports,d3Path) { 'use strict'; - -function constant(x) { - return function constant() { - return x; - }; -} - -var abs = Math.abs; -var atan2 = Math.atan2; -var cos = Math.cos; -var max = Math.max; -var min = Math.min; -var sin = Math.sin; -var sqrt = Math.sqrt; - -var epsilon = 1e-12; -var pi = Math.PI; -var halfPi = pi / 2; -var tau = 2 * pi; - -function acos(x) { - return x > 1 ? 0 : x < -1 ? pi : Math.acos(x); -} - -function asin(x) { - return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x); -} - -function arcInnerRadius(d) { - return d.innerRadius; -} - -function arcOuterRadius(d) { - return d.outerRadius; -} - -function arcStartAngle(d) { - return d.startAngle; -} - -function arcEndAngle(d) { - return d.endAngle; -} - -function arcPadAngle(d) { - return d && d.padAngle; // Note: optional! -} - -function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { - var x10 = x1 - x0, y10 = y1 - y0, - x32 = x3 - x2, y32 = y3 - y2, - t = y32 * x10 - x32 * y10; - if (t * t < epsilon) return; - t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t; - return [x0 + t * x10, y0 + t * y10]; -} - -// Compute perpendicular offset line of length rc. -// http://mathworld.wolfram.com/Circle-LineIntersection.html -function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { - var x01 = x0 - x1, - y01 = y0 - y1, - lo = (cw ? rc : -rc) / sqrt(x01 * x01 + y01 * y01), - ox = lo * y01, - oy = -lo * x01, - x11 = x0 + ox, - y11 = y0 + oy, - x10 = x1 + ox, - y10 = y1 + oy, - x00 = (x11 + x10) / 2, - y00 = (y11 + y10) / 2, - dx = x10 - x11, - dy = y10 - y11, - d2 = dx * dx + dy * dy, - r = r1 - rc, - D = x11 * y10 - x10 * y11, - d = (dy < 0 ? -1 : 1) * sqrt(max(0, r * r * d2 - D * D)), - cx0 = (D * dy - dx * d) / d2, - cy0 = (-D * dx - dy * d) / d2, - cx1 = (D * dy + dx * d) / d2, - cy1 = (-D * dx + dy * d) / d2, - dx0 = cx0 - x00, - dy0 = cy0 - y00, - dx1 = cx1 - x00, - dy1 = cy1 - y00; - - // Pick the closer of the two intersection points. - // TODO Is there a faster way to determine which intersection to use? - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; - - return { - cx: cx0, - cy: cy0, - x01: -ox, - y01: -oy, - x11: cx0 * (r1 / r - 1), - y11: cy0 * (r1 / r - 1) - }; -} - -function arc() { - var innerRadius = arcInnerRadius, - outerRadius = arcOuterRadius, - cornerRadius = constant(0), - padRadius = null, - startAngle = arcStartAngle, - endAngle = arcEndAngle, - padAngle = arcPadAngle, - context = null; - - function arc() { - var buffer, - r, - r0 = +innerRadius.apply(this, arguments), - r1 = +outerRadius.apply(this, arguments), - a0 = startAngle.apply(this, arguments) - halfPi, - a1 = endAngle.apply(this, arguments) - halfPi, - da = abs(a1 - a0), - cw = a1 > a0; - - if (!context) context = buffer = d3Path.path(); - - // Ensure that the outer radius is always larger than the inner radius. - if (r1 < r0) r = r1, r1 = r0, r0 = r; - - // Is it a point? - if (!(r1 > epsilon)) context.moveTo(0, 0); - - // Or is it a circle or annulus? - else if (da > tau - epsilon) { - context.moveTo(r1 * cos(a0), r1 * sin(a0)); - context.arc(0, 0, r1, a0, a1, !cw); - if (r0 > epsilon) { - context.moveTo(r0 * cos(a1), r0 * sin(a1)); - context.arc(0, 0, r0, a1, a0, cw); - } - } - - // Or is it a circular or annular sector? - else { - var a01 = a0, - a11 = a1, - a00 = a0, - a10 = a1, - da0 = da, - da1 = da, - ap = padAngle.apply(this, arguments) / 2, - rp = (ap > epsilon) && (padRadius ? +padRadius.apply(this, arguments) : sqrt(r0 * r0 + r1 * r1)), - rc = min(abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), - rc0 = rc, - rc1 = rc, - t0, - t1; - - // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. - if (rp > epsilon) { - var p0 = asin(rp / r0 * sin(ap)), - p1 = asin(rp / r1 * sin(ap)); - if ((da0 -= p0 * 2) > epsilon) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; - else da0 = 0, a00 = a10 = (a0 + a1) / 2; - if ((da1 -= p1 * 2) > epsilon) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; - else da1 = 0, a01 = a11 = (a0 + a1) / 2; - } - - var x01 = r1 * cos(a01), - y01 = r1 * sin(a01), - x10 = r0 * cos(a10), - y10 = r0 * sin(a10); - - // Apply rounded corners? - if (rc > epsilon) { - var x11 = r1 * cos(a11), - y11 = r1 * sin(a11), - x00 = r0 * cos(a00), - y00 = r0 * sin(a00), - oc; - - // Restrict the corner radius according to the sector angle. - if (da < pi && (oc = intersect(x01, y01, x00, y00, x11, y11, x10, y10))) { - var ax = x01 - oc[0], - ay = y01 - oc[1], - bx = x11 - oc[0], - by = y11 - oc[1], - kc = 1 / sin(acos((ax * bx + ay * by) / (sqrt(ax * ax + ay * ay) * sqrt(bx * bx + by * by))) / 2), - lc = sqrt(oc[0] * oc[0] + oc[1] * oc[1]); - rc0 = min(rc, (r0 - lc) / (kc - 1)); - rc1 = min(rc, (r1 - lc) / (kc + 1)); - } - } - - // Is the sector collapsed to a line? - if (!(da1 > epsilon)) context.moveTo(x01, y01); - - // Does the sector’s outer ring have rounded corners? - else if (rc1 > epsilon) { - t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); - t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); - - context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); - - // Have the corners merged? - if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); - - // Otherwise, draw the two corners and the ring. - else { - context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw); - context.arc(0, 0, r1, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); - context.arc(t1.cx, t1.cy, rc1, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw); - } - } - - // Or is the outer ring just a circular arc? - else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); - - // Is there no inner ring, and it’s a circular sector? - // Or perhaps it’s an annular sector collapsed due to padding? - if (!(r0 > epsilon) || !(da0 > epsilon)) context.lineTo(x10, y10); - - // Does the sector’s inner ring (or point) have rounded corners? - else if (rc0 > epsilon) { - t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); - t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); - - context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); - - // Have the corners merged? - if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); - - // Otherwise, draw the two corners and the ring. - else { - context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw); - context.arc(0, 0, r0, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw); - context.arc(t1.cx, t1.cy, rc0, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw); - } - } - - // Or is the inner ring just a circular arc? - else context.arc(0, 0, r0, a10, a00, cw); - } - - context.closePath(); - - if (buffer) return context = null, buffer + "" || null; - } - - arc.centroid = function() { - var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, - a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi / 2; - return [cos(a) * r, sin(a) * r]; - }; - - arc.innerRadius = function(_) { - return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant(+_), arc) : innerRadius; - }; - - arc.outerRadius = function(_) { - return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant(+_), arc) : outerRadius; - }; - - arc.cornerRadius = function(_) { - return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant(+_), arc) : cornerRadius; - }; - - arc.padRadius = function(_) { - return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant(+_), arc) : padRadius; - }; - - arc.startAngle = function(_) { - return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), arc) : startAngle; - }; - - arc.endAngle = function(_) { - return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), arc) : endAngle; - }; - - arc.padAngle = function(_) { - return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), arc) : padAngle; - }; - - arc.context = function(_) { - return arguments.length ? ((context = _ == null ? null : _), arc) : context; - }; - - return arc; -} - -function Linear(context) { - this._context = context; -} - -Linear.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; // proceed - default: this._context.lineTo(x, y); break; - } - } -}; - -function curveLinear(context) { - return new Linear(context); -} - -function x(p) { - return p[0]; -} - -function y(p) { - return p[1]; -} - -function line() { - var x$$1 = x, - y$$1 = y, - defined = constant(true), - context = null, - curve = curveLinear, - output = null; - - function line(data) { - var i, - n = data.length, - d, - defined0 = false, - buffer; - - if (context == null) output = curve(buffer = d3Path.path()); - - for (i = 0; i <= n; ++i) { - if (!(i < n && defined(d = data[i], i, data)) === defined0) { - if (defined0 = !defined0) output.lineStart(); - else output.lineEnd(); - } - if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data)); - } - - if (buffer) return output = null, buffer + "" || null; - } - - line.x = function(_) { - return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), line) : x$$1; - }; - - line.y = function(_) { - return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), line) : y$$1; - }; - - line.defined = function(_) { - return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), line) : defined; - }; - - line.curve = function(_) { - return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; - }; - - line.context = function(_) { - return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; - }; - - return line; -} - -function area() { - var x0 = x, - x1 = null, - y0 = constant(0), - y1 = y, - defined = constant(true), - context = null, - curve = curveLinear, - output = null; - - function area(data) { - var i, - j, - k, - n = data.length, - d, - defined0 = false, - buffer, - x0z = new Array(n), - y0z = new Array(n); - - if (context == null) output = curve(buffer = d3Path.path()); - - for (i = 0; i <= n; ++i) { - if (!(i < n && defined(d = data[i], i, data)) === defined0) { - if (defined0 = !defined0) { - j = i; - output.areaStart(); - output.lineStart(); - } else { - output.lineEnd(); - output.lineStart(); - for (k = i - 1; k >= j; --k) { - output.point(x0z[k], y0z[k]); - } - output.lineEnd(); - output.areaEnd(); - } - } - if (defined0) { - x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); - output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); - } - } - - if (buffer) return output = null, buffer + "" || null; - } - - function arealine() { - return line().defined(defined).curve(curve).context(context); - } - - area.x = function(_) { - return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), x1 = null, area) : x0; - }; - - area.x0 = function(_) { - return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), area) : x0; - }; - - area.x1 = function(_) { - return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : x1; - }; - - area.y = function(_) { - return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), y1 = null, area) : y0; - }; - - area.y0 = function(_) { - return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), area) : y0; - }; - - area.y1 = function(_) { - return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : y1; - }; - - area.lineX0 = - area.lineY0 = function() { - return arealine().x(x0).y(y0); - }; - - area.lineY1 = function() { - return arealine().x(x0).y(y1); - }; - - area.lineX1 = function() { - return arealine().x(x1).y(y0); - }; - - area.defined = function(_) { - return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), area) : defined; - }; - - area.curve = function(_) { - return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; - }; - - area.context = function(_) { - return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; - }; - - return area; -} - -function descending(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; -} - -function identity(d) { - return d; -} - -function pie() { - var value = identity, - sortValues = descending, - sort = null, - startAngle = constant(0), - endAngle = constant(tau), - padAngle = constant(0); - - function pie(data) { - var i, - n = data.length, - j, - k, - sum = 0, - index = new Array(n), - arcs = new Array(n), - a0 = +startAngle.apply(this, arguments), - da = Math.min(tau, Math.max(-tau, endAngle.apply(this, arguments) - a0)), - a1, - p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), - pa = p * (da < 0 ? -1 : 1), - v; - - for (i = 0; i < n; ++i) { - if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { - sum += v; - } - } - - // Optionally sort the arcs by previously-computed values or by data. - if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); - else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); }); - - // Compute the arcs! They are stored in the original data's order. - for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { - j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { - data: data[j], - index: i, - value: v, - startAngle: a0, - endAngle: a1, - padAngle: p - }; - } - - return arcs; - } - - pie.value = function(_) { - return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), pie) : value; - }; - - pie.sortValues = function(_) { - return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; - }; - - pie.sort = function(_) { - return arguments.length ? (sort = _, sortValues = null, pie) : sort; - }; - - pie.startAngle = function(_) { - return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), pie) : startAngle; - }; - - pie.endAngle = function(_) { - return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), pie) : endAngle; - }; - - pie.padAngle = function(_) { - return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), pie) : padAngle; - }; - - return pie; -} - -var curveRadialLinear = curveRadial(curveLinear); - -function Radial(curve) { - this._curve = curve; -} - -Radial.prototype = { - areaStart: function() { - this._curve.areaStart(); - }, - areaEnd: function() { - this._curve.areaEnd(); - }, - lineStart: function() { - this._curve.lineStart(); - }, - lineEnd: function() { - this._curve.lineEnd(); - }, - point: function(a, r) { - this._curve.point(r * Math.sin(a), r * -Math.cos(a)); - } -}; - -function curveRadial(curve) { - - function radial(context) { - return new Radial(curve(context)); - } - - radial._curve = curve; - - return radial; -} - -function lineRadial(l) { - var c = l.curve; - - l.angle = l.x, delete l.x; - l.radius = l.y, delete l.y; - - l.curve = function(_) { - return arguments.length ? c(curveRadial(_)) : c()._curve; - }; - - return l; -} - -function lineRadial$1() { - return lineRadial(line().curve(curveRadialLinear)); -} - -function areaRadial() { - var a = area().curve(curveRadialLinear), - c = a.curve, - x0 = a.lineX0, - x1 = a.lineX1, - y0 = a.lineY0, - y1 = a.lineY1; - - a.angle = a.x, delete a.x; - a.startAngle = a.x0, delete a.x0; - a.endAngle = a.x1, delete a.x1; - a.radius = a.y, delete a.y; - a.innerRadius = a.y0, delete a.y0; - a.outerRadius = a.y1, delete a.y1; - a.lineStartAngle = function() { return lineRadial(x0()); }, delete a.lineX0; - a.lineEndAngle = function() { return lineRadial(x1()); }, delete a.lineX1; - a.lineInnerRadius = function() { return lineRadial(y0()); }, delete a.lineY0; - a.lineOuterRadius = function() { return lineRadial(y1()); }, delete a.lineY1; - - a.curve = function(_) { - return arguments.length ? c(curveRadial(_)) : c()._curve; - }; - - return a; -} - -function pointRadial(x, y) { - return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)]; -} - -var slice = Array.prototype.slice; - -function linkSource(d) { - return d.source; -} - -function linkTarget(d) { - return d.target; -} - -function link(curve) { - var source = linkSource, - target = linkTarget, - x$$1 = x, - y$$1 = y, - context = null; - - function link() { - var buffer, argv = slice.call(arguments), s = source.apply(this, argv), t = target.apply(this, argv); - if (!context) context = buffer = d3Path.path(); - curve(context, +x$$1.apply(this, (argv[0] = s, argv)), +y$$1.apply(this, argv), +x$$1.apply(this, (argv[0] = t, argv)), +y$$1.apply(this, argv)); - if (buffer) return context = null, buffer + "" || null; - } - - link.source = function(_) { - return arguments.length ? (source = _, link) : source; - }; - - link.target = function(_) { - return arguments.length ? (target = _, link) : target; - }; - - link.x = function(_) { - return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), link) : x$$1; - }; - - link.y = function(_) { - return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), link) : y$$1; - }; - - link.context = function(_) { - return arguments.length ? ((context = _ == null ? null : _), link) : context; - }; - - return link; -} - -function curveHorizontal(context, x0, y0, x1, y1) { - context.moveTo(x0, y0); - context.bezierCurveTo(x0 = (x0 + x1) / 2, y0, x0, y1, x1, y1); -} - -function curveVertical(context, x0, y0, x1, y1) { - context.moveTo(x0, y0); - context.bezierCurveTo(x0, y0 = (y0 + y1) / 2, x1, y0, x1, y1); -} - -function curveRadial$1(context, x0, y0, x1, y1) { - var p0 = pointRadial(x0, y0), - p1 = pointRadial(x0, y0 = (y0 + y1) / 2), - p2 = pointRadial(x1, y0), - p3 = pointRadial(x1, y1); - context.moveTo(p0[0], p0[1]); - context.bezierCurveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]); -} - -function linkHorizontal() { - return link(curveHorizontal); -} - -function linkVertical() { - return link(curveVertical); -} - -function linkRadial() { - var l = link(curveRadial$1); - l.angle = l.x, delete l.x; - l.radius = l.y, delete l.y; - return l; -} - -var circle = { - draw: function(context, size) { - var r = Math.sqrt(size / pi); - context.moveTo(r, 0); - context.arc(0, 0, r, 0, tau); - } -}; - -var cross = { - draw: function(context, size) { - var r = Math.sqrt(size / 5) / 2; - context.moveTo(-3 * r, -r); - context.lineTo(-r, -r); - context.lineTo(-r, -3 * r); - context.lineTo(r, -3 * r); - context.lineTo(r, -r); - context.lineTo(3 * r, -r); - context.lineTo(3 * r, r); - context.lineTo(r, r); - context.lineTo(r, 3 * r); - context.lineTo(-r, 3 * r); - context.lineTo(-r, r); - context.lineTo(-3 * r, r); - context.closePath(); - } -}; - -var tan30 = Math.sqrt(1 / 3), - tan30_2 = tan30 * 2; - -var diamond = { - draw: function(context, size) { - var y = Math.sqrt(size / tan30_2), - x = y * tan30; - context.moveTo(0, -y); - context.lineTo(x, 0); - context.lineTo(0, y); - context.lineTo(-x, 0); - context.closePath(); - } -}; - -var ka = 0.89081309152928522810, - kr = Math.sin(pi / 10) / Math.sin(7 * pi / 10), - kx = Math.sin(tau / 10) * kr, - ky = -Math.cos(tau / 10) * kr; - -var star = { - draw: function(context, size) { - var r = Math.sqrt(size * ka), - x = kx * r, - y = ky * r; - context.moveTo(0, -r); - context.lineTo(x, y); - for (var i = 1; i < 5; ++i) { - var a = tau * i / 5, - c = Math.cos(a), - s = Math.sin(a); - context.lineTo(s * r, -c * r); - context.lineTo(c * x - s * y, s * x + c * y); - } - context.closePath(); - } -}; - -var square = { - draw: function(context, size) { - var w = Math.sqrt(size), - x = -w / 2; - context.rect(x, x, w, w); - } -}; - -var sqrt3 = Math.sqrt(3); - -var triangle = { - draw: function(context, size) { - var y = -Math.sqrt(size / (sqrt3 * 3)); - context.moveTo(0, y * 2); - context.lineTo(-sqrt3 * y, -y); - context.lineTo(sqrt3 * y, -y); - context.closePath(); - } -}; - -var c = -0.5, - s = Math.sqrt(3) / 2, - k = 1 / Math.sqrt(12), - a = (k / 2 + 1) * 3; - -var wye = { - draw: function(context, size) { - var r = Math.sqrt(size / a), - x0 = r / 2, - y0 = r * k, - x1 = x0, - y1 = r * k + r, - x2 = -x1, - y2 = y1; - context.moveTo(x0, y0); - context.lineTo(x1, y1); - context.lineTo(x2, y2); - context.lineTo(c * x0 - s * y0, s * x0 + c * y0); - context.lineTo(c * x1 - s * y1, s * x1 + c * y1); - context.lineTo(c * x2 - s * y2, s * x2 + c * y2); - context.lineTo(c * x0 + s * y0, c * y0 - s * x0); - context.lineTo(c * x1 + s * y1, c * y1 - s * x1); - context.lineTo(c * x2 + s * y2, c * y2 - s * x2); - context.closePath(); - } -}; - -var symbols = [ - circle, - cross, - diamond, - square, - star, - triangle, - wye -]; - -function symbol() { - var type = constant(circle), - size = constant(64), - context = null; - - function symbol() { - var buffer; - if (!context) context = buffer = d3Path.path(); - type.apply(this, arguments).draw(context, +size.apply(this, arguments)); - if (buffer) return context = null, buffer + "" || null; - } - - symbol.type = function(_) { - return arguments.length ? (type = typeof _ === "function" ? _ : constant(_), symbol) : type; - }; - - symbol.size = function(_) { - return arguments.length ? (size = typeof _ === "function" ? _ : constant(+_), symbol) : size; - }; - - symbol.context = function(_) { - return arguments.length ? (context = _ == null ? null : _, symbol) : context; - }; - - return symbol; -} - -function noop() {} - -function point(that, x, y) { - that._context.bezierCurveTo( - (2 * that._x0 + that._x1) / 3, - (2 * that._y0 + that._y1) / 3, - (that._x0 + 2 * that._x1) / 3, - (that._y0 + 2 * that._y1) / 3, - (that._x0 + 4 * that._x1 + x) / 6, - (that._y0 + 4 * that._y1 + y) / 6 - ); -} - -function Basis(context) { - this._context = context; -} - -Basis.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = - this._y0 = this._y1 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 3: point(this, this._x1, this._y1); // proceed - case 2: this._context.lineTo(this._x1, this._y1); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; break; - case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed - default: point(this, x, y); break; - } - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - } -}; - -function basis(context) { - return new Basis(context); -} - -function BasisClosed(context) { - this._context = context; -} - -BasisClosed.prototype = { - areaStart: noop, - areaEnd: noop, - lineStart: function() { - this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = - this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 1: { - this._context.moveTo(this._x2, this._y2); - this._context.closePath(); - break; - } - case 2: { - this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); - this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); - this._context.closePath(); - break; - } - case 3: { - this.point(this._x2, this._y2); - this.point(this._x3, this._y3); - this.point(this._x4, this._y4); - break; - } - } - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._x2 = x, this._y2 = y; break; - case 1: this._point = 2; this._x3 = x, this._y3 = y; break; - case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; - default: point(this, x, y); break; - } - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - } -}; - -function basisClosed(context) { - return new BasisClosed(context); -} - -function BasisOpen(context) { - this._context = context; -} - -BasisOpen.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = - this._y0 = this._y1 = NaN; - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; break; - case 1: this._point = 2; break; - case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; - case 3: this._point = 4; // proceed - default: point(this, x, y); break; - } - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - } -}; - -function basisOpen(context) { - return new BasisOpen(context); -} - -function Bundle(context, beta) { - this._basis = new Basis(context); - this._beta = beta; -} - -Bundle.prototype = { - lineStart: function() { - this._x = []; - this._y = []; - this._basis.lineStart(); - }, - lineEnd: function() { - var x = this._x, - y = this._y, - j = x.length - 1; - - if (j > 0) { - var x0 = x[0], - y0 = y[0], - dx = x[j] - x0, - dy = y[j] - y0, - i = -1, - t; - - while (++i <= j) { - t = i / j; - this._basis.point( - this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), - this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) - ); - } - } - - this._x = this._y = null; - this._basis.lineEnd(); - }, - point: function(x, y) { - this._x.push(+x); - this._y.push(+y); - } -}; - -var bundle = (function custom(beta) { - - function bundle(context) { - return beta === 1 ? new Basis(context) : new Bundle(context, beta); - } - - bundle.beta = function(beta) { - return custom(+beta); - }; - - return bundle; -})(0.85); - -function point$1(that, x, y) { - that._context.bezierCurveTo( - that._x1 + that._k * (that._x2 - that._x0), - that._y1 + that._k * (that._y2 - that._y0), - that._x2 + that._k * (that._x1 - x), - that._y2 + that._k * (that._y1 - y), - that._x2, - that._y2 - ); -} - -function Cardinal(context, tension) { - this._context = context; - this._k = (1 - tension) / 6; -} - -Cardinal.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 2: this._context.lineTo(this._x2, this._y2); break; - case 3: point$1(this, this._x1, this._y1); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; this._x1 = x, this._y1 = y; break; - case 2: this._point = 3; // proceed - default: point$1(this, x, y); break; - } - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var cardinal = (function custom(tension) { - - function cardinal(context) { - return new Cardinal(context, tension); - } - - cardinal.tension = function(tension) { - return custom(+tension); - }; - - return cardinal; -})(0); - -function CardinalClosed(context, tension) { - this._context = context; - this._k = (1 - tension) / 6; -} - -CardinalClosed.prototype = { - areaStart: noop, - areaEnd: noop, - lineStart: function() { - this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = - this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 1: { - this._context.moveTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 2: { - this._context.lineTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 3: { - this.point(this._x3, this._y3); - this.point(this._x4, this._y4); - this.point(this._x5, this._y5); - break; - } - } - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._x3 = x, this._y3 = y; break; - case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; - case 2: this._point = 3; this._x5 = x, this._y5 = y; break; - default: point$1(this, x, y); break; - } - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var cardinalClosed = (function custom(tension) { - - function cardinal$$1(context) { - return new CardinalClosed(context, tension); - } - - cardinal$$1.tension = function(tension) { - return custom(+tension); - }; - - return cardinal$$1; -})(0); - -function CardinalOpen(context, tension) { - this._context = context; - this._k = (1 - tension) / 6; -} - -CardinalOpen.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; break; - case 1: this._point = 2; break; - case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; - case 3: this._point = 4; // proceed - default: point$1(this, x, y); break; - } - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var cardinalOpen = (function custom(tension) { - - function cardinal$$1(context) { - return new CardinalOpen(context, tension); - } - - cardinal$$1.tension = function(tension) { - return custom(+tension); - }; - - return cardinal$$1; -})(0); - -function point$2(that, x, y) { - var x1 = that._x1, - y1 = that._y1, - x2 = that._x2, - y2 = that._y2; - - if (that._l01_a > epsilon) { - var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, - n = 3 * that._l01_a * (that._l01_a + that._l12_a); - x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; - y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; - } - - if (that._l23_a > epsilon) { - var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, - m = 3 * that._l23_a * (that._l23_a + that._l12_a); - x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; - y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; - } - - that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); -} - -function CatmullRom(context, alpha) { - this._context = context; - this._alpha = alpha; -} - -CatmullRom.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._l01_a = this._l12_a = this._l23_a = - this._l01_2a = this._l12_2a = this._l23_2a = - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 2: this._context.lineTo(this._x2, this._y2); break; - case 3: this.point(this._x2, this._y2); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - - if (this._point) { - var x23 = this._x2 - x, - y23 = this._y2 - y; - this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); - } - - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; break; - case 2: this._point = 3; // proceed - default: point$2(this, x, y); break; - } - - this._l01_a = this._l12_a, this._l12_a = this._l23_a; - this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var catmullRom = (function custom(alpha) { - - function catmullRom(context) { - return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); - } - - catmullRom.alpha = function(alpha) { - return custom(+alpha); - }; - - return catmullRom; -})(0.5); - -function CatmullRomClosed(context, alpha) { - this._context = context; - this._alpha = alpha; -} - -CatmullRomClosed.prototype = { - areaStart: noop, - areaEnd: noop, - lineStart: function() { - this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = - this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; - this._l01_a = this._l12_a = this._l23_a = - this._l01_2a = this._l12_2a = this._l23_2a = - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 1: { - this._context.moveTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 2: { - this._context.lineTo(this._x3, this._y3); - this._context.closePath(); - break; - } - case 3: { - this.point(this._x3, this._y3); - this.point(this._x4, this._y4); - this.point(this._x5, this._y5); - break; - } - } - }, - point: function(x, y) { - x = +x, y = +y; - - if (this._point) { - var x23 = this._x2 - x, - y23 = this._y2 - y; - this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); - } - - switch (this._point) { - case 0: this._point = 1; this._x3 = x, this._y3 = y; break; - case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; - case 2: this._point = 3; this._x5 = x, this._y5 = y; break; - default: point$2(this, x, y); break; - } - - this._l01_a = this._l12_a, this._l12_a = this._l23_a; - this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var catmullRomClosed = (function custom(alpha) { - - function catmullRom$$1(context) { - return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); - } - - catmullRom$$1.alpha = function(alpha) { - return custom(+alpha); - }; - - return catmullRom$$1; -})(0.5); - -function CatmullRomOpen(context, alpha) { - this._context = context; - this._alpha = alpha; -} - -CatmullRomOpen.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = this._x2 = - this._y0 = this._y1 = this._y2 = NaN; - this._l01_a = this._l12_a = this._l23_a = - this._l01_2a = this._l12_2a = this._l23_2a = - this._point = 0; - }, - lineEnd: function() { - if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - - if (this._point) { - var x23 = this._x2 - x, - y23 = this._y2 - y; - this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); - } - - switch (this._point) { - case 0: this._point = 1; break; - case 1: this._point = 2; break; - case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; - case 3: this._point = 4; // proceed - default: point$2(this, x, y); break; - } - - this._l01_a = this._l12_a, this._l12_a = this._l23_a; - this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; - this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; - this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; - } -}; - -var catmullRomOpen = (function custom(alpha) { - - function catmullRom$$1(context) { - return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); - } - - catmullRom$$1.alpha = function(alpha) { - return custom(+alpha); - }; - - return catmullRom$$1; -})(0.5); - -function LinearClosed(context) { - this._context = context; -} - -LinearClosed.prototype = { - areaStart: noop, - areaEnd: noop, - lineStart: function() { - this._point = 0; - }, - lineEnd: function() { - if (this._point) this._context.closePath(); - }, - point: function(x, y) { - x = +x, y = +y; - if (this._point) this._context.lineTo(x, y); - else this._point = 1, this._context.moveTo(x, y); - } -}; - -function linearClosed(context) { - return new LinearClosed(context); -} - -function sign(x) { - return x < 0 ? -1 : 1; -} - -// Calculate the slopes of the tangents (Hermite-type interpolation) based on -// the following paper: Steffen, M. 1990. A Simple Method for Monotonic -// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. -// NOV(II), P. 443, 1990. -function slope3(that, x2, y2) { - var h0 = that._x1 - that._x0, - h1 = x2 - that._x1, - s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), - s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), - p = (s0 * h1 + s1 * h0) / (h0 + h1); - return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; -} - -// Calculate a one-sided slope. -function slope2(that, t) { - var h = that._x1 - that._x0; - return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; -} - -// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations -// "you can express cubic Hermite interpolation in terms of cubic Bézier curves -// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". -function point$3(that, t0, t1) { - var x0 = that._x0, - y0 = that._y0, - x1 = that._x1, - y1 = that._y1, - dx = (x1 - x0) / 3; - that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); -} - -function MonotoneX(context) { - this._context = context; -} - -MonotoneX.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x0 = this._x1 = - this._y0 = this._y1 = - this._t0 = NaN; - this._point = 0; - }, - lineEnd: function() { - switch (this._point) { - case 2: this._context.lineTo(this._x1, this._y1); break; - case 3: point$3(this, this._t0, slope2(this, this._t0)); break; - } - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - this._line = 1 - this._line; - }, - point: function(x, y) { - var t1 = NaN; - - x = +x, y = +y; - if (x === this._x1 && y === this._y1) return; // Ignore coincident points. - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; break; - case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break; - default: point$3(this, this._t0, t1 = slope3(this, x, y)); break; - } - - this._x0 = this._x1, this._x1 = x; - this._y0 = this._y1, this._y1 = y; - this._t0 = t1; - } -}; - -function MonotoneY(context) { - this._context = new ReflectContext(context); -} - -(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) { - MonotoneX.prototype.point.call(this, y, x); -}; - -function ReflectContext(context) { - this._context = context; -} - -ReflectContext.prototype = { - moveTo: function(x, y) { this._context.moveTo(y, x); }, - closePath: function() { this._context.closePath(); }, - lineTo: function(x, y) { this._context.lineTo(y, x); }, - bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); } -}; - -function monotoneX(context) { - return new MonotoneX(context); -} - -function monotoneY(context) { - return new MonotoneY(context); -} - -function Natural(context) { - this._context = context; -} - -Natural.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x = []; - this._y = []; - }, - lineEnd: function() { - var x = this._x, - y = this._y, - n = x.length; - - if (n) { - this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); - if (n === 2) { - this._context.lineTo(x[1], y[1]); - } else { - var px = controlPoints(x), - py = controlPoints(y); - for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { - this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); - } - } - } - - if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); - this._line = 1 - this._line; - this._x = this._y = null; - }, - point: function(x, y) { - this._x.push(+x); - this._y.push(+y); - } -}; - -// See https://www.particleincell.com/2012/bezier-splines/ for derivation. -function controlPoints(x) { - var i, - n = x.length - 1, - m, - a = new Array(n), - b = new Array(n), - r = new Array(n); - a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; - for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; - a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; - for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; - a[n - 1] = r[n - 1] / b[n - 1]; - for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; - b[n - 1] = (x[n] + a[n - 1]) / 2; - for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; - return [a, b]; -} - -function natural(context) { - return new Natural(context); -} - -function Step(context, t) { - this._context = context; - this._t = t; -} - -Step.prototype = { - areaStart: function() { - this._line = 0; - }, - areaEnd: function() { - this._line = NaN; - }, - lineStart: function() { - this._x = this._y = NaN; - this._point = 0; - }, - lineEnd: function() { - if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y); - if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); - if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line; - }, - point: function(x, y) { - x = +x, y = +y; - switch (this._point) { - case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; - case 1: this._point = 2; // proceed - default: { - if (this._t <= 0) { - this._context.lineTo(this._x, y); - this._context.lineTo(x, y); - } else { - var x1 = this._x * (1 - this._t) + x * this._t; - this._context.lineTo(x1, this._y); - this._context.lineTo(x1, y); - } - break; - } - } - this._x = x, this._y = y; - } -}; - -function step(context) { - return new Step(context, 0.5); -} - -function stepBefore(context) { - return new Step(context, 0); -} - -function stepAfter(context) { - return new Step(context, 1); -} - -function none(series, order) { - if (!((n = series.length) > 1)) return; - for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { - s0 = s1, s1 = series[order[i]]; - for (j = 0; j < m; ++j) { - s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; - } - } -} - -function none$1(series) { - var n = series.length, o = new Array(n); - while (--n >= 0) o[n] = n; - return o; -} - -function stackValue(d, key) { - return d[key]; -} - -function stack() { - var keys = constant([]), - order = none$1, - offset = none, - value = stackValue; - - function stack(data) { - var kz = keys.apply(this, arguments), - i, - m = data.length, - n = kz.length, - sz = new Array(n), - oz; - - for (i = 0; i < n; ++i) { - for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { - si[j] = sij = [0, +value(data[j], ki, j, data)]; - sij.data = data[j]; - } - si.key = ki; - } - - for (i = 0, oz = order(sz); i < n; ++i) { - sz[oz[i]].index = i; - } - - offset(sz, oz); - return sz; - } - - stack.keys = function(_) { - return arguments.length ? (keys = typeof _ === "function" ? _ : constant(slice.call(_)), stack) : keys; - }; - - stack.value = function(_) { - return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), stack) : value; - }; - - stack.order = function(_) { - return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant(slice.call(_)), stack) : order; - }; - - stack.offset = function(_) { - return arguments.length ? (offset = _ == null ? none : _, stack) : offset; - }; - - return stack; -} - -function expand(series, order) { - if (!((n = series.length) > 0)) return; - for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { - for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0; - if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y; - } - none(series, order); -} - -function diverging(series, order) { - if (!((n = series.length) > 1)) return; - for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) { - for (yp = yn = 0, i = 0; i < n; ++i) { - if ((dy = (d = series[order[i]][j])[1] - d[0]) >= 0) { - d[0] = yp, d[1] = yp += dy; - } else if (dy < 0) { - d[1] = yn, d[0] = yn += dy; - } else { - d[0] = yp; - } - } - } -} - -function silhouette(series, order) { - if (!((n = series.length) > 0)) return; - for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { - for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0; - s0[j][1] += s0[j][0] = -y / 2; - } - none(series, order); -} - -function wiggle(series, order) { - if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return; - for (var y = 0, j = 1, s0, m, n; j < m; ++j) { - for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { - var si = series[order[i]], - sij0 = si[j][1] || 0, - sij1 = si[j - 1][1] || 0, - s3 = (sij0 - sij1) / 2; - for (var k = 0; k < i; ++k) { - var sk = series[order[k]], - skj0 = sk[j][1] || 0, - skj1 = sk[j - 1][1] || 0; - s3 += skj0 - skj1; - } - s1 += sij0, s2 += s3 * sij0; - } - s0[j - 1][1] += s0[j - 1][0] = y; - if (s1) y -= s2 / s1; - } - s0[j - 1][1] += s0[j - 1][0] = y; - none(series, order); -} - -function appearance(series) { - var peaks = series.map(peak); - return none$1(series).sort(function(a, b) { return peaks[a] - peaks[b]; }); -} - -function peak(series) { - var i = -1, j = 0, n = series.length, vi, vj = -Infinity; - while (++i < n) if ((vi = +series[i][1]) > vj) vj = vi, j = i; - return j; -} - -function ascending(series) { - var sums = series.map(sum); - return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; }); -} - -function sum(series) { - var s = 0, i = -1, n = series.length, v; - while (++i < n) if (v = +series[i][1]) s += v; - return s; -} - -function descending$1(series) { - return ascending(series).reverse(); -} - -function insideOut(series) { - var n = series.length, - i, - j, - sums = series.map(sum), - order = appearance(series), - top = 0, - bottom = 0, - tops = [], - bottoms = []; - - for (i = 0; i < n; ++i) { - j = order[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); - } - } - - return bottoms.reverse().concat(tops); -} - -function reverse(series) { - return none$1(series).reverse(); -} - -exports.arc = arc; -exports.area = area; -exports.line = line; -exports.pie = pie; -exports.areaRadial = areaRadial; -exports.radialArea = areaRadial; -exports.lineRadial = lineRadial$1; -exports.radialLine = lineRadial$1; -exports.pointRadial = pointRadial; -exports.linkHorizontal = linkHorizontal; -exports.linkVertical = linkVertical; -exports.linkRadial = linkRadial; -exports.symbol = symbol; -exports.symbols = symbols; -exports.symbolCircle = circle; -exports.symbolCross = cross; -exports.symbolDiamond = diamond; -exports.symbolSquare = square; -exports.symbolStar = star; -exports.symbolTriangle = triangle; -exports.symbolWye = wye; -exports.curveBasisClosed = basisClosed; -exports.curveBasisOpen = basisOpen; -exports.curveBasis = basis; -exports.curveBundle = bundle; -exports.curveCardinalClosed = cardinalClosed; -exports.curveCardinalOpen = cardinalOpen; -exports.curveCardinal = cardinal; -exports.curveCatmullRomClosed = catmullRomClosed; -exports.curveCatmullRomOpen = catmullRomOpen; -exports.curveCatmullRom = catmullRom; -exports.curveLinearClosed = linearClosed; -exports.curveLinear = curveLinear; -exports.curveMonotoneX = monotoneX; -exports.curveMonotoneY = monotoneY; -exports.curveNatural = natural; -exports.curveStep = step; -exports.curveStepAfter = stepAfter; -exports.curveStepBefore = stepBefore; -exports.stack = stack; -exports.stackOffsetExpand = expand; -exports.stackOffsetDiverging = diverging; -exports.stackOffsetNone = none; -exports.stackOffsetSilhouette = silhouette; -exports.stackOffsetWiggle = wiggle; -exports.stackOrderAppearance = appearance; -exports.stackOrderAscending = ascending; -exports.stackOrderDescending = descending$1; -exports.stackOrderInsideOut = insideOut; -exports.stackOrderNone = none$1; -exports.stackOrderReverse = reverse; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{"d3-path":159}],162:[function(_dereq_,module,exports){ -// https://d3js.org/d3-timer/ Version 1.0.7. Copyright 2017 Mike Bostock. -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.d3 = global.d3 || {}))); -}(this, (function (exports) { 'use strict'; - -var frame = 0; -var timeout = 0; -var interval = 0; -var pokeDelay = 1000; -var taskHead; -var taskTail; -var clockLast = 0; -var clockNow = 0; -var clockSkew = 0; -var clock = typeof performance === "object" && performance.now ? performance : Date; -var setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); }; - -function now() { - return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); -} - -function clearNow() { - clockNow = 0; -} - -function Timer() { - this._call = - this._time = - this._next = null; -} - -Timer.prototype = timer.prototype = { - constructor: Timer, - restart: function(callback, delay, time) { - if (typeof callback !== "function") throw new TypeError("callback is not a function"); - time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); - if (!this._next && taskTail !== this) { - if (taskTail) taskTail._next = this; - else taskHead = this; - taskTail = this; - } - this._call = callback; - this._time = time; - sleep(); - }, - stop: function() { - if (this._call) { - this._call = null; - this._time = Infinity; - sleep(); - } - } -}; - -function timer(callback, delay, time) { - var t = new Timer; - t.restart(callback, delay, time); - return t; -} - -function timerFlush() { - now(); // Get the current time, if not already set. - ++frame; // Pretend we’ve set an alarm, if we haven’t already. - var t = taskHead, e; - while (t) { - if ((e = clockNow - t._time) >= 0) t._call.call(null, e); - t = t._next; - } - --frame; -} - -function wake() { - clockNow = (clockLast = clock.now()) + clockSkew; - frame = timeout = 0; - try { - timerFlush(); - } finally { - frame = 0; - nap(); - clockNow = 0; - } -} - -function poke() { - var now = clock.now(), delay = now - clockLast; - if (delay > pokeDelay) clockSkew -= delay, clockLast = now; -} - -function nap() { - var t0, t1 = taskHead, t2, time = Infinity; - while (t1) { - if (t1._call) { - if (time > t1._time) time = t1._time; - t0 = t1, t1 = t1._next; - } else { - t2 = t1._next, t1._next = null; - t1 = t0 ? t0._next = t2 : taskHead = t2; - } - } - taskTail = t0; - sleep(time); -} - -function sleep(time) { - if (frame) return; // Soonest alarm already set, or will be. - if (timeout) timeout = clearTimeout(timeout); - var delay = time - clockNow; // Strictly less than if we recomputed clockNow. - if (delay > 24) { - if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew); - if (interval) interval = clearInterval(interval); - } else { - if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay); - frame = 1, setFrame(wake); - } -} - -var timeout$1 = function(callback, delay, time) { - var t = new Timer; - delay = delay == null ? 0 : +delay; - t.restart(function(elapsed) { - t.stop(); - callback(elapsed + delay); - }, delay, time); - return t; -}; - -var interval$1 = function(callback, delay, time) { - var t = new Timer, total = delay; - if (delay == null) return t.restart(callback, delay, time), t; - delay = +delay, time = time == null ? now() : +time; - t.restart(function tick(elapsed) { - elapsed += total; - t.restart(tick, total += delay, time); - callback(elapsed); - }, delay, time); - return t; -}; - -exports.now = now; -exports.timer = timer; -exports.timerFlush = timerFlush; -exports.timeout = timeout$1; -exports.interval = interval$1; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{}],163:[function(_dereq_,module,exports){ -!function() { - var d3 = { - version: "3.5.17" - }; - var d3_arraySlice = [].slice, d3_array = function(list) { - return d3_arraySlice.call(list); - }; - var d3_document = this.document; - function d3_documentElement(node) { - return node && (node.ownerDocument || node.document || node).documentElement; - } - function d3_window(node) { - return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView); - } - if (d3_document) { - try { - d3_array(d3_document.documentElement.childNodes)[0].nodeType; - } catch (e) { - d3_array = function(list) { - var i = list.length, array = new Array(i); - while (i--) array[i] = list[i]; - return array; - }; - } - } - if (!Date.now) Date.now = function() { - return +new Date(); - }; - if (d3_document) { - try { - d3_document.createElement("DIV").style.setProperty("opacity", 0, ""); - } catch (error) { - var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; - d3_element_prototype.setAttribute = function(name, value) { - d3_element_setAttribute.call(this, name, value + ""); - }; - d3_element_prototype.setAttributeNS = function(space, local, value) { - d3_element_setAttributeNS.call(this, space, local, value + ""); - }; - d3_style_prototype.setProperty = function(name, value, priority) { - d3_style_setProperty.call(this, name, value + "", priority); - }; - } - } - d3.ascending = d3_ascending; - function d3_ascending(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; - } - d3.descending = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; - }; - d3.min = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && a > b) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; - } - return a; - }; - d3.max = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && b > a) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; - } - return a; - }; - d3.extent = function(array, f) { - var i = -1, n = array.length, a, b, c; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = array[i]) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } - return [ a, c ]; - }; - function d3_number(x) { - return x === null ? NaN : +x; - } - function d3_numeric(x) { - return !isNaN(x); - } - d3.sum = function(array, f) { - var s = 0, n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = +array[i])) s += a; - } else { - while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; - } - return s; - }; - d3.mean = function(array, f) { - var s = 0, n = array.length, a, i = -1, j = n; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; - } - if (j) return s / j; - }; - d3.quantile = function(values, p) { - var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; - return e ? v + e * (values[h] - v) : v; - }; - d3.median = function(array, f) { - var numbers = [], n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); - } - if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); - }; - d3.variance = function(array, f) { - var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; - if (arguments.length === 1) { - while (++i < n) { - if (d3_numeric(a = d3_number(array[i]))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } else { - while (++i < n) { - if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } - if (j > 1) return s / (j - 1); - }; - d3.deviation = function() { - var v = d3.variance.apply(this, arguments); - return v ? Math.sqrt(v) : v; - }; - function d3_bisector(compare) { - return { - left: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; - } - return lo; - }, - right: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; - } - return lo; - } - }; - } - var d3_bisect = d3_bisector(d3_ascending); - d3.bisectLeft = d3_bisect.left; - d3.bisect = d3.bisectRight = d3_bisect.right; - d3.bisector = function(f) { - return d3_bisector(f.length === 1 ? function(d, x) { - return d3_ascending(f(d), x); - } : f); - }; - d3.shuffle = function(array, i0, i1) { - if ((m = arguments.length) < 3) { - i1 = array.length; - if (m < 2) i0 = 0; - } - var m = i1 - i0, t, i; - while (m) { - i = Math.random() * m-- | 0; - t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; - } - return array; - }; - d3.permute = function(array, indexes) { - var i = indexes.length, permutes = new Array(i); - while (i--) permutes[i] = array[indexes[i]]; - return permutes; - }; - d3.pairs = function(array) { - var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); - while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; - return pairs; - }; - d3.transpose = function(matrix) { - if (!(n = matrix.length)) return []; - for (var i = -1, m = d3.min(matrix, d3_transposeLength), transpose = new Array(m); ++i < m; ) { - for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) { - row[j] = matrix[j][i]; - } - } - return transpose; - }; - function d3_transposeLength(d) { - return d.length; - } - d3.zip = function() { - return d3.transpose(arguments); - }; - d3.keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; - }; - d3.values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; - }; - d3.entries = function(map) { - var entries = []; - for (var key in map) entries.push({ - key: key, - value: map[key] - }); - return entries; - }; - d3.merge = function(arrays) { - var n = arrays.length, m, i = -1, j = 0, merged, array; - while (++i < n) j += arrays[i].length; - merged = new Array(j); - while (--n >= 0) { - array = arrays[n]; - m = array.length; - while (--m >= 0) { - merged[--j] = array[m]; - } - } - return merged; - }; - var abs = Math.abs; - d3.range = function(start, stop, step) { - if (arguments.length < 3) { - step = 1; - if (arguments.length < 2) { - stop = start; - start = 0; - } - } - if ((stop - start) / step === Infinity) throw new Error("infinite range"); - var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; - start *= k, stop *= k, step *= k; - if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); - return range; - }; - function d3_range_integerScale(x) { - var k = 1; - while (x * k % 1) k *= 10; - return k; - } - function d3_class(ctor, properties) { - for (var key in properties) { - Object.defineProperty(ctor.prototype, key, { - value: properties[key], - enumerable: false - }); - } - } - d3.map = function(object, f) { - var map = new d3_Map(); - if (object instanceof d3_Map) { - object.forEach(function(key, value) { - map.set(key, value); - }); - } else if (Array.isArray(object)) { - var i = -1, n = object.length, o; - if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); - } else { - for (var key in object) map.set(key, object[key]); - } - return map; - }; - function d3_Map() { - this._ = Object.create(null); - } - var d3_map_proto = "__proto__", d3_map_zero = "\x00"; - d3_class(d3_Map, { - has: d3_map_has, - get: function(key) { - return this._[d3_map_escape(key)]; - }, - set: function(key, value) { - return this._[d3_map_escape(key)] = value; - }, - remove: d3_map_remove, - keys: d3_map_keys, - values: function() { - var values = []; - for (var key in this._) values.push(this._[key]); - return values; - }, - entries: function() { - var entries = []; - for (var key in this._) entries.push({ - key: d3_map_unescape(key), - value: this._[key] - }); - return entries; - }, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); - } - }); - function d3_map_escape(key) { - return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; - } - function d3_map_unescape(key) { - return (key += "")[0] === d3_map_zero ? key.slice(1) : key; - } - function d3_map_has(key) { - return d3_map_escape(key) in this._; - } - function d3_map_remove(key) { - return (key = d3_map_escape(key)) in this._ && delete this._[key]; - } - function d3_map_keys() { - var keys = []; - for (var key in this._) keys.push(d3_map_unescape(key)); - return keys; - } - function d3_map_size() { - var size = 0; - for (var key in this._) ++size; - return size; - } - function d3_map_empty() { - for (var key in this._) return false; - return true; - } - d3.nest = function() { - var nest = {}, keys = [], sortKeys = [], sortValues, rollup; - function map(mapType, array, depth) { - if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; - var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(object = array[i]))) { - values.push(object); - } else { - valuesByKey.set(keyValue, [ object ]); - } - } - if (mapType) { - object = mapType(); - setter = function(keyValue, values) { - object.set(keyValue, map(mapType, values, depth)); - }; - } else { - object = {}; - setter = function(keyValue, values) { - object[keyValue] = map(mapType, values, depth); - }; - } - valuesByKey.forEach(setter); - return object; - } - function entries(map, depth) { - if (depth >= keys.length) return map; - var array = [], sortKey = sortKeys[depth++]; - map.forEach(function(key, keyMap) { - array.push({ - key: key, - values: entries(keyMap, depth) - }); - }); - return sortKey ? array.sort(function(a, b) { - return sortKey(a.key, b.key); - }) : array; - } - nest.map = function(array, mapType) { - return map(mapType, array, 0); - }; - nest.entries = function(array) { - return entries(map(d3.map, array, 0), 0); - }; - nest.key = function(d) { - keys.push(d); - return nest; - }; - nest.sortKeys = function(order) { - sortKeys[keys.length - 1] = order; - return nest; - }; - nest.sortValues = function(order) { - sortValues = order; - return nest; - }; - nest.rollup = function(f) { - rollup = f; - return nest; - }; - return nest; - }; - d3.set = function(array) { - var set = new d3_Set(); - if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); - return set; - }; - function d3_Set() { - this._ = Object.create(null); - } - d3_class(d3_Set, { - has: d3_map_has, - add: function(key) { - this._[d3_map_escape(key += "")] = true; - return key; - }, - remove: d3_map_remove, - values: d3_map_keys, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key)); - } - }); - d3.behavior = {}; - function d3_identity(d) { - return d; - } - d3.rebind = function(target, source) { - var i = 1, n = arguments.length, method; - while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); - return target; - }; - function d3_rebind(target, source, method) { - return function() { - var value = method.apply(source, arguments); - return value === source ? target : value; - }; - } - function d3_vendorSymbol(object, name) { - if (name in object) return name; - name = name.charAt(0).toUpperCase() + name.slice(1); - for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { - var prefixName = d3_vendorPrefixes[i] + name; - if (prefixName in object) return prefixName; - } - } - var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; - function d3_noop() {} - d3.dispatch = function() { - var dispatch = new d3_dispatch(), i = -1, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - return dispatch; - }; - function d3_dispatch() {} - d3_dispatch.prototype.on = function(type, listener) { - var i = type.indexOf("."), name = ""; - if (i >= 0) { - name = type.slice(i + 1); - type = type.slice(0, i); - } - if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); - if (arguments.length === 2) { - if (listener == null) for (type in this) { - if (this.hasOwnProperty(type)) this[type].on(name, null); - } - return this; - } - }; - function d3_dispatch_event(dispatch) { - var listeners = [], listenerByName = new d3_Map(); - function event() { - var z = listeners, i = -1, n = z.length, l; - while (++i < n) if (l = z[i].on) l.apply(this, arguments); - return dispatch; - } - event.on = function(name, listener) { - var l = listenerByName.get(name), i; - if (arguments.length < 2) return l && l.on; - if (l) { - l.on = null; - listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); - listenerByName.remove(name); - } - if (listener) listeners.push(listenerByName.set(name, { - on: listener - })); - return dispatch; - }; - return event; - } - d3.event = null; - function d3_eventPreventDefault() { - d3.event.preventDefault(); - } - function d3_eventSource() { - var e = d3.event, s; - while (s = e.sourceEvent) e = s; - return e; - } - function d3_eventDispatch(target) { - var dispatch = new d3_dispatch(), i = 0, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - dispatch.of = function(thiz, argumentz) { - return function(e1) { - try { - var e0 = e1.sourceEvent = d3.event; - e1.target = target; - d3.event = e1; - dispatch[e1.type].apply(thiz, argumentz); - } finally { - d3.event = e0; - } - }; - }; - return dispatch; - } - d3.requote = function(s) { - return s.replace(d3_requote_re, "\\$&"); - }; - var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - var d3_subclass = {}.__proto__ ? function(object, prototype) { - object.__proto__ = prototype; - } : function(object, prototype) { - for (var property in prototype) object[property] = prototype[property]; - }; - function d3_selection(groups) { - d3_subclass(groups, d3_selectionPrototype); - return groups; - } - var d3_select = function(s, n) { - return n.querySelector(s); - }, d3_selectAll = function(s, n) { - return n.querySelectorAll(s); - }, d3_selectMatches = function(n, s) { - var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")]; - d3_selectMatches = function(n, s) { - return d3_selectMatcher.call(n, s); - }; - return d3_selectMatches(n, s); - }; - if (typeof Sizzle === "function") { - d3_select = function(s, n) { - return Sizzle(s, n)[0] || null; - }; - d3_selectAll = Sizzle; - d3_selectMatches = Sizzle.matchesSelector; - } - d3.selection = function() { - return d3.select(d3_document.documentElement); - }; - var d3_selectionPrototype = d3.selection.prototype = []; - d3_selectionPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, group, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(subnode = selector.call(node, node.__data__, i, j)); - if (subnode && "__data__" in node) subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selector(selector) { - return typeof selector === "function" ? selector : function() { - return d3_select(selector, this); - }; - } - d3_selectionPrototype.selectAll = function(selector) { - var subgroups = [], subgroup, node; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); - subgroup.parentNode = node; - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selectorAll(selector) { - return typeof selector === "function" ? selector : function() { - return d3_selectAll(selector, this); - }; - } - var d3_nsXhtml = "http://www.w3.org/1999/xhtml"; - var d3_nsPrefix = { - svg: "http://www.w3.org/2000/svg", - xhtml: d3_nsXhtml, - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" - }; - d3.ns = { - prefix: d3_nsPrefix, - qualify: function(name) { - var i = name.indexOf(":"), prefix = name; - if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); - return d3_nsPrefix.hasOwnProperty(prefix) ? { - space: d3_nsPrefix[prefix], - local: name - } : name; - } - }; - d3_selectionPrototype.attr = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(); - name = d3.ns.qualify(name); - return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); - } - for (value in name) this.each(d3_selection_attr(value, name[value])); - return this; - } - return this.each(d3_selection_attr(name, value)); - }; - function d3_selection_attr(name, value) { - name = d3.ns.qualify(name); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrConstant() { - this.setAttribute(name, value); - } - function attrConstantNS() { - this.setAttributeNS(name.space, name.local, value); - } - function attrFunction() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); - } - function attrFunctionNS() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); - } - return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; - } - function d3_collapse(s) { - return s.trim().replace(/\s+/g, " "); - } - d3_selectionPrototype.classed = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; - if (value = node.classList) { - while (++i < n) if (!value.contains(name[i])) return false; - } else { - value = node.getAttribute("class"); - while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; - } - return true; - } - for (value in name) this.each(d3_selection_classed(value, name[value])); - return this; - } - return this.each(d3_selection_classed(name, value)); - }; - function d3_selection_classedRe(name) { - return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); - } - function d3_selection_classes(name) { - return (name + "").trim().split(/^|\s+/); - } - function d3_selection_classed(name, value) { - name = d3_selection_classes(name).map(d3_selection_classedName); - var n = name.length; - function classedConstant() { - var i = -1; - while (++i < n) name[i](this, value); - } - function classedFunction() { - var i = -1, x = value.apply(this, arguments); - while (++i < n) name[i](this, x); - } - return typeof value === "function" ? classedFunction : classedConstant; - } - function d3_selection_classedName(name) { - var re = d3_selection_classedRe(name); - return function(node, value) { - if (c = node.classList) return value ? c.add(name) : c.remove(name); - var c = node.getAttribute("class") || ""; - if (value) { - re.lastIndex = 0; - if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); - } else { - node.setAttribute("class", d3_collapse(c.replace(re, " "))); - } - }; - } - d3_selectionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); - return this; - } - if (n < 2) { - var node = this.node(); - return d3_window(node).getComputedStyle(node, null).getPropertyValue(name); - } - priority = ""; - } - return this.each(d3_selection_style(name, value, priority)); - }; - function d3_selection_style(name, value, priority) { - function styleNull() { - this.style.removeProperty(name); - } - function styleConstant() { - this.style.setProperty(name, value, priority); - } - function styleFunction() { - var x = value.apply(this, arguments); - if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); - } - return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; - } - d3_selectionPrototype.property = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") return this.node()[name]; - for (value in name) this.each(d3_selection_property(value, name[value])); - return this; - } - return this.each(d3_selection_property(name, value)); - }; - function d3_selection_property(name, value) { - function propertyNull() { - delete this[name]; - } - function propertyConstant() { - this[name] = value; - } - function propertyFunction() { - var x = value.apply(this, arguments); - if (x == null) delete this[name]; else this[name] = x; - } - return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; - } - d3_selectionPrototype.text = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - } : value == null ? function() { - this.textContent = ""; - } : function() { - this.textContent = value; - }) : this.node().textContent; - }; - d3_selectionPrototype.html = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; - } : value == null ? function() { - this.innerHTML = ""; - } : function() { - this.innerHTML = value; - }) : this.node().innerHTML; - }; - d3_selectionPrototype.append = function(name) { - name = d3_selection_creator(name); - return this.select(function() { - return this.appendChild(name.apply(this, arguments)); - }); - }; - function d3_selection_creator(name) { - function create() { - var document = this.ownerDocument, namespace = this.namespaceURI; - return namespace === d3_nsXhtml && document.documentElement.namespaceURI === d3_nsXhtml ? document.createElement(name) : document.createElementNS(namespace, name); - } - function createNS() { - return this.ownerDocument.createElementNS(name.space, name.local); - } - return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create; - } - d3_selectionPrototype.insert = function(name, before) { - name = d3_selection_creator(name); - before = d3_selection_selector(before); - return this.select(function() { - return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); - }); - }; - d3_selectionPrototype.remove = function() { - return this.each(d3_selectionRemove); - }; - function d3_selectionRemove() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); - } - d3_selectionPrototype.data = function(value, key) { - var i = -1, n = this.length, group, node; - if (!arguments.length) { - value = new Array(n = (group = this[0]).length); - while (++i < n) { - if (node = group[i]) { - value[i] = node.__data__; - } - } - return value; - } - function bind(group, groupData) { - var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; - if (key) { - var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; - for (i = -1; ++i < n; ) { - if (node = group[i]) { - if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) { - exitNodes[i] = node; - } else { - nodeByKeyValue.set(keyValue, node); - } - keyValues[i] = keyValue; - } - } - for (i = -1; ++i < m; ) { - if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { - enterNodes[i] = d3_selection_dataNode(nodeData); - } else if (node !== true) { - updateNodes[i] = node; - node.__data__ = nodeData; - } - nodeByKeyValue.set(keyValue, true); - } - for (i = -1; ++i < n; ) { - if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) { - exitNodes[i] = group[i]; - } - } - } else { - for (i = -1; ++i < n0; ) { - node = group[i]; - nodeData = groupData[i]; - if (node) { - node.__data__ = nodeData; - updateNodes[i] = node; - } else { - enterNodes[i] = d3_selection_dataNode(nodeData); - } - } - for (;i < m; ++i) { - enterNodes[i] = d3_selection_dataNode(groupData[i]); - } - for (;i < n; ++i) { - exitNodes[i] = group[i]; - } - } - enterNodes.update = updateNodes; - enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; - enter.push(enterNodes); - update.push(updateNodes); - exit.push(exitNodes); - } - var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); - if (typeof value === "function") { - while (++i < n) { - bind(group = this[i], value.call(group, group.parentNode.__data__, i)); - } - } else { - while (++i < n) { - bind(group = this[i], value); - } - } - update.enter = function() { - return enter; - }; - update.exit = function() { - return exit; - }; - return update; - }; - function d3_selection_dataNode(data) { - return { - __data__: data - }; - } - d3_selectionPrototype.datum = function(value) { - return arguments.length ? this.property("__data__", value) : this.property("__data__"); - }; - d3_selectionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_filter(selector) { - return function() { - return d3_selectMatches(this, selector); - }; - } - d3_selectionPrototype.order = function() { - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { - if (node = group[i]) { - if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); - next = node; - } - } - } - return this; - }; - d3_selectionPrototype.sort = function(comparator) { - comparator = d3_selection_sortComparator.apply(this, arguments); - for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); - return this.order(); - }; - function d3_selection_sortComparator(comparator) { - if (!arguments.length) comparator = d3_ascending; - return function(a, b) { - return a && b ? comparator(a.__data__, b.__data__) : !a - !b; - }; - } - d3_selectionPrototype.each = function(callback) { - return d3_selection_each(this, function(node, i, j) { - callback.call(node, node.__data__, i, j); - }); - }; - function d3_selection_each(groups, callback) { - for (var j = 0, m = groups.length; j < m; j++) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { - if (node = group[i]) callback(node, i, j); - } - } - return groups; - } - d3_selectionPrototype.call = function(callback) { - var args = d3_array(arguments); - callback.apply(args[0] = this, args); - return this; - }; - d3_selectionPrototype.empty = function() { - return !this.node(); - }; - d3_selectionPrototype.node = function() { - for (var j = 0, m = this.length; j < m; j++) { - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - var node = group[i]; - if (node) return node; - } - } - return null; - }; - d3_selectionPrototype.size = function() { - var n = 0; - d3_selection_each(this, function() { - ++n; - }); - return n; - }; - function d3_selection_enter(selection) { - d3_subclass(selection, d3_selection_enterPrototype); - return selection; - } - var d3_selection_enterPrototype = []; - d3.selection.enter = d3_selection_enter; - d3.selection.enter.prototype = d3_selection_enterPrototype; - d3_selection_enterPrototype.append = d3_selectionPrototype.append; - d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; - d3_selection_enterPrototype.node = d3_selectionPrototype.node; - d3_selection_enterPrototype.call = d3_selectionPrototype.call; - d3_selection_enterPrototype.size = d3_selectionPrototype.size; - d3_selection_enterPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, upgroup, group, node; - for (var j = -1, m = this.length; ++j < m; ) { - upgroup = (group = this[j]).update; - subgroups.push(subgroup = []); - subgroup.parentNode = group.parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); - subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - d3_selection_enterPrototype.insert = function(name, before) { - if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); - return d3_selectionPrototype.insert.call(this, name, before); - }; - function d3_selection_enterInsertBefore(enter) { - var i0, j0; - return function(d, i, j) { - var group = enter[j].update, n = group.length, node; - if (j != j0) j0 = j, i0 = 0; - if (i >= i0) i0 = i + 1; - while (!(node = group[i0]) && ++i0 < n) ; - return node; - }; - } - d3.select = function(node) { - var group; - if (typeof node === "string") { - group = [ d3_select(node, d3_document) ]; - group.parentNode = d3_document.documentElement; - } else { - group = [ node ]; - group.parentNode = d3_documentElement(node); - } - return d3_selection([ group ]); - }; - d3.selectAll = function(nodes) { - var group; - if (typeof nodes === "string") { - group = d3_array(d3_selectAll(nodes, d3_document)); - group.parentNode = d3_document.documentElement; - } else { - group = d3_array(nodes); - group.parentNode = null; - } - return d3_selection([ group ]); - }; - d3_selectionPrototype.on = function(type, listener, capture) { - var n = arguments.length; - if (n < 3) { - if (typeof type !== "string") { - if (n < 2) listener = false; - for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); - return this; - } - if (n < 2) return (n = this.node()["__on" + type]) && n._; - capture = false; - } - return this.each(d3_selection_on(type, listener, capture)); - }; - function d3_selection_on(type, listener, capture) { - var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; - if (i > 0) type = type.slice(0, i); - var filter = d3_selection_onFilters.get(type); - if (filter) type = filter, wrap = d3_selection_onFilter; - function onRemove() { - var l = this[name]; - if (l) { - this.removeEventListener(type, l, l.$); - delete this[name]; - } - } - function onAdd() { - var l = wrap(listener, d3_array(arguments)); - onRemove.call(this); - this.addEventListener(type, this[name] = l, l.$ = capture); - l._ = listener; - } - function removeAll() { - var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; - for (var name in this) { - if (match = name.match(re)) { - var l = this[name]; - this.removeEventListener(match[1], l, l.$); - delete this[name]; - } - } - } - return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; - } - var d3_selection_onFilters = d3.map({ - mouseenter: "mouseover", - mouseleave: "mouseout" - }); - if (d3_document) { - d3_selection_onFilters.forEach(function(k) { - if ("on" + k in d3_document) d3_selection_onFilters.remove(k); - }); - } - function d3_selection_onListener(listener, argumentz) { - return function(e) { - var o = d3.event; - d3.event = e; - argumentz[0] = this.__data__; - try { - listener.apply(this, argumentz); - } finally { - d3.event = o; - } - }; - } - function d3_selection_onFilter(listener, argumentz) { - var l = d3_selection_onListener(listener, argumentz); - return function(e) { - var target = this, related = e.relatedTarget; - if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { - l.call(target, e); - } - }; - } - var d3_event_dragSelect, d3_event_dragId = 0; - function d3_event_dragSuppress(node) { - var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); - if (d3_event_dragSelect == null) { - d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect"); - } - if (d3_event_dragSelect) { - var style = d3_documentElement(node).style, select = style[d3_event_dragSelect]; - style[d3_event_dragSelect] = "none"; - } - return function(suppressClick) { - w.on(name, null); - if (d3_event_dragSelect) style[d3_event_dragSelect] = select; - if (suppressClick) { - var off = function() { - w.on(click, null); - }; - w.on(click, function() { - d3_eventPreventDefault(); - off(); - }, true); - setTimeout(off, 0); - } - }; - } - d3.mouse = function(container) { - return d3_mousePoint(container, d3_eventSource()); - }; - var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0; - function d3_mousePoint(container, e) { - if (e.changedTouches) e = e.changedTouches[0]; - var svg = container.ownerSVGElement || container; - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - if (d3_mouse_bug44083 < 0) { - var window = d3_window(container); - if (window.scrollX || window.scrollY) { - svg = d3.select("body").append("svg").style({ - position: "absolute", - top: 0, - left: 0, - margin: 0, - padding: 0, - border: "none" - }, "important"); - var ctm = svg[0][0].getScreenCTM(); - d3_mouse_bug44083 = !(ctm.f || ctm.e); - svg.remove(); - } - } - if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, - point.y = e.clientY; - point = point.matrixTransform(container.getScreenCTM().inverse()); - return [ point.x, point.y ]; - } - var rect = container.getBoundingClientRect(); - return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; - } - d3.touch = function(container, touches, identifier) { - if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; - if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { - if ((touch = touches[i]).identifier === identifier) { - return d3_mousePoint(container, touch); - } - } - }; - d3.behavior.drag = function() { - var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); - function drag() { - this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); - } - function dragstart(id, position, subject, move, end) { - return function() { - var that = this, target = d3.event.target.correspondingElement || d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId); - if (origin) { - dragOffset = origin.apply(that, arguments); - dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; - } else { - dragOffset = [ 0, 0 ]; - } - dispatch({ - type: "dragstart" - }); - function moved() { - var position1 = position(parent, dragId), dx, dy; - if (!position1) return; - dx = position1[0] - position0[0]; - dy = position1[1] - position0[1]; - dragged |= dx | dy; - position0 = position1; - dispatch({ - type: "drag", - x: position1[0] + dragOffset[0], - y: position1[1] + dragOffset[1], - dx: dx, - dy: dy - }); - } - function ended() { - if (!position(parent, dragId)) return; - dragSubject.on(move + dragName, null).on(end + dragName, null); - dragRestore(dragged); - dispatch({ - type: "dragend" - }); - } - }; - } - drag.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return drag; - }; - return d3.rebind(drag, event, "on"); - }; - function d3_behavior_dragTouchId() { - return d3.event.changedTouches[0].identifier; - } - d3.touches = function(container, touches) { - if (arguments.length < 2) touches = d3_eventSource().touches; - return touches ? d3_array(touches).map(function(touch) { - var point = d3_mousePoint(container, touch); - point.identifier = touch.identifier; - return point; - }) : []; - }; - var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π; - function d3_sgn(x) { - return x > 0 ? 1 : x < 0 ? -1 : 0; - } - function d3_cross2d(a, b, c) { - return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); - } - function d3_acos(x) { - return x > 1 ? 0 : x < -1 ? π : Math.acos(x); - } - function d3_asin(x) { - return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); - } - function d3_sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; - } - function d3_cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; - } - function d3_tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); - } - function d3_haversin(x) { - return (x = Math.sin(x / 2)) * x; - } - var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; - d3.interpolateZoom = function(p0, p1) { - var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S; - if (d2 < ε2) { - S = Math.log(w1 / w0) / ρ; - i = function(t) { - return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ]; - }; - } else { - var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); - S = (r1 - r0) / ρ; - i = function(t) { - var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); - return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; - }; - } - i.duration = S * 1e3; - return i; - }; - d3.behavior.zoom = function() { - var view = { - x: 0, - y: 0, - k: 1 - }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; - if (!d3_behavior_zoomWheel) { - d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); - }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return d3.event.wheelDelta; - }, "mousewheel") : (d3_behavior_zoomDelta = function() { - return -d3.event.detail; - }, "MozMousePixelScroll"); - } - function zoom(g) { - g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); - } - zoom.event = function(g) { - g.each(function() { - var dispatch = event.of(this, arguments), view1 = view; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.zoom", function() { - view = this.__chart__ || { - x: 0, - y: 0, - k: 1 - }; - zoomstarted(dispatch); - }).tween("zoom:zoom", function() { - var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); - return function(t) { - var l = i(t), k = dx / l[2]; - this.__chart__ = view = { - x: cx - l[0] * k, - y: cy - l[1] * k, - k: k - }; - zoomed(dispatch); - }; - }).each("interrupt.zoom", function() { - zoomended(dispatch); - }).each("end.zoom", function() { - zoomended(dispatch); - }); - } else { - this.__chart__ = view; - zoomstarted(dispatch); - zoomed(dispatch); - zoomended(dispatch); - } - }); - }; - zoom.translate = function(_) { - if (!arguments.length) return [ view.x, view.y ]; - view = { - x: +_[0], - y: +_[1], - k: view.k - }; - rescale(); - return zoom; - }; - zoom.scale = function(_) { - if (!arguments.length) return view.k; - view = { - x: view.x, - y: view.y, - k: null - }; - scaleTo(+_); - rescale(); - return zoom; - }; - zoom.scaleExtent = function(_) { - if (!arguments.length) return scaleExtent; - scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; - return zoom; - }; - zoom.center = function(_) { - if (!arguments.length) return center; - center = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.size = function(_) { - if (!arguments.length) return size; - size = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.duration = function(_) { - if (!arguments.length) return duration; - duration = +_; - return zoom; - }; - zoom.x = function(z) { - if (!arguments.length) return x1; - x1 = z; - x0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - zoom.y = function(z) { - if (!arguments.length) return y1; - y1 = z; - y0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 - }; - return zoom; - }; - function location(p) { - return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; - } - function point(l) { - return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; - } - function scaleTo(s) { - view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); - } - function translateTo(p, l) { - l = point(l); - view.x += p[0] - l[0]; - view.y += p[1] - l[1]; - } - function zoomTo(that, p, l, k) { - that.__chart__ = { - x: view.x, - y: view.y, - k: view.k - }; - scaleTo(Math.pow(2, k)); - translateTo(center0 = p, l); - that = d3.select(that); - if (duration > 0) that = that.transition().duration(duration); - that.call(zoom.event); - } - function rescale() { - if (x1) x1.domain(x0.range().map(function(x) { - return (x - view.x) / view.k; - }).map(x0.invert)); - if (y1) y1.domain(y0.range().map(function(y) { - return (y - view.y) / view.k; - }).map(y0.invert)); - } - function zoomstarted(dispatch) { - if (!zooming++) dispatch({ - type: "zoomstart" - }); - } - function zoomed(dispatch) { - rescale(); - dispatch({ - type: "zoom", - scale: view.k, - translate: [ view.x, view.y ] - }); - } - function zoomended(dispatch) { - if (!--zooming) dispatch({ - type: "zoomend" - }), center0 = null; - } - function mousedowned() { - var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that); - d3_selection_interrupt.call(that); - zoomstarted(dispatch); - function moved() { - dragged = 1; - translateTo(d3.mouse(that), location0); - zoomed(dispatch); - } - function ended() { - subject.on(mousemove, null).on(mouseup, null); - dragRestore(dragged); - zoomended(dispatch); - } - } - function touchstarted() { - var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that); - started(); - zoomstarted(dispatch); - subject.on(mousedown, null).on(touchstart, started); - function relocate() { - var touches = d3.touches(that); - scale0 = view.k; - touches.forEach(function(t) { - if (t.identifier in locations0) locations0[t.identifier] = location(t); - }); - return touches; - } - function started() { - var target = d3.event.target; - d3.select(target).on(touchmove, moved).on(touchend, ended); - targets.push(target); - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - locations0[changed[i].identifier] = null; - } - var touches = relocate(), now = Date.now(); - if (touches.length === 1) { - if (now - touchtime < 500) { - var p = touches[0]; - zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); - d3_eventPreventDefault(); - } - touchtime = now; - } else if (touches.length > 1) { - var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; - distance0 = dx * dx + dy * dy; - } - } - function moved() { - var touches = d3.touches(that), p0, l0, p1, l1; - d3_selection_interrupt.call(that); - for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { - p1 = touches[i]; - if (l1 = locations0[p1.identifier]) { - if (l0) break; - p0 = p1, l0 = l1; - } - } - if (l1) { - var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); - p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; - l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; - scaleTo(scale1 * scale0); - } - touchtime = null; - translateTo(p0, l0); - zoomed(dispatch); - } - function ended() { - if (d3.event.touches.length) { - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - delete locations0[changed[i].identifier]; - } - for (var identifier in locations0) { - return void relocate(); - } - } - d3.selectAll(targets).on(zoomName, null); - subject.on(mousedown, mousedowned).on(touchstart, touchstarted); - dragRestore(); - zoomended(dispatch); - } - } - function mousewheeled() { - var dispatch = event.of(this, arguments); - if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), - translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch); - mousewheelTimer = setTimeout(function() { - mousewheelTimer = null; - zoomended(dispatch); - }, 50); - d3_eventPreventDefault(); - scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); - translateTo(center0, translate0); - zoomed(dispatch); - } - function dblclicked() { - var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; - zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); - } - return d3.rebind(zoom, event, "on"); - }; - var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel; - d3.color = d3_color; - function d3_color() {} - d3_color.prototype.toString = function() { - return this.rgb() + ""; - }; - d3.hsl = d3_hsl; - function d3_hsl(h, s, l) { - return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); - } - var d3_hslPrototype = d3_hsl.prototype = new d3_color(); - d3_hslPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, this.l / k); - }; - d3_hslPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, k * this.l); - }; - d3_hslPrototype.rgb = function() { - return d3_hsl_rgb(this.h, this.s, this.l); - }; - function d3_hsl_rgb(h, s, l) { - var m1, m2; - h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; - s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; - l = l < 0 ? 0 : l > 1 ? 1 : l; - m2 = l <= .5 ? l * (1 + s) : l + s - l * s; - m1 = 2 * l - m2; - function v(h) { - if (h > 360) h -= 360; else if (h < 0) h += 360; - if (h < 60) return m1 + (m2 - m1) * h / 60; - if (h < 180) return m2; - if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; - return m1; - } - function vv(h) { - return Math.round(v(h) * 255); - } - return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); - } - d3.hcl = d3_hcl; - function d3_hcl(h, c, l) { - return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); - } - var d3_hclPrototype = d3_hcl.prototype = new d3_color(); - d3_hclPrototype.brighter = function(k) { - return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.darker = function(k) { - return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.rgb = function() { - return d3_hcl_lab(this.h, this.c, this.l).rgb(); - }; - function d3_hcl_lab(h, c, l) { - if (isNaN(h)) h = 0; - if (isNaN(c)) c = 0; - return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); - } - d3.lab = d3_lab; - function d3_lab(l, a, b) { - return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); - } - var d3_lab_K = 18; - var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; - var d3_labPrototype = d3_lab.prototype = new d3_color(); - d3_labPrototype.brighter = function(k) { - return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.darker = function(k) { - return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); - }; - d3_labPrototype.rgb = function() { - return d3_lab_rgb(this.l, this.a, this.b); - }; - function d3_lab_rgb(l, a, b) { - var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; - x = d3_lab_xyz(x) * d3_lab_X; - y = d3_lab_xyz(y) * d3_lab_Y; - z = d3_lab_xyz(z) * d3_lab_Z; - return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); - } - function d3_lab_hcl(l, a, b) { - return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); - } - function d3_lab_xyz(x) { - return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; - } - function d3_xyz_lab(x) { - return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; - } - function d3_xyz_rgb(r) { - return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); - } - d3.rgb = d3_rgb; - function d3_rgb(r, g, b) { - return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); - } - function d3_rgbNumber(value) { - return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); - } - function d3_rgbString(value) { - return d3_rgbNumber(value) + ""; - } - var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); - d3_rgbPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - var r = this.r, g = this.g, b = this.b, i = 30; - if (!r && !g && !b) return new d3_rgb(i, i, i); - if (r && r < i) r = i; - if (g && g < i) g = i; - if (b && b < i) b = i; - return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); - }; - d3_rgbPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_rgb(k * this.r, k * this.g, k * this.b); - }; - d3_rgbPrototype.hsl = function() { - return d3_rgb_hsl(this.r, this.g, this.b); - }; - d3_rgbPrototype.toString = function() { - return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); - }; - function d3_rgb_hex(v) { - return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); - } - function d3_rgb_parse(format, rgb, hsl) { - var r = 0, g = 0, b = 0, m1, m2, color; - m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase()); - if (m1) { - m2 = m1[2].split(","); - switch (m1[1]) { - case "hsl": - { - return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); - } - - case "rgb": - { - return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); - } - } - } - if (color = d3_rgb_names.get(format)) { - return rgb(color.r, color.g, color.b); - } - if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { - if (format.length === 4) { - r = (color & 3840) >> 4; - r = r >> 4 | r; - g = color & 240; - g = g >> 4 | g; - b = color & 15; - b = b << 4 | b; - } else if (format.length === 7) { - r = (color & 16711680) >> 16; - g = (color & 65280) >> 8; - b = color & 255; - } - } - return rgb(r, g, b); - } - function d3_rgb_hsl(r, g, b) { - var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; - if (d) { - s = l < .5 ? d / (max + min) : d / (2 - max - min); - if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; - h *= 60; - } else { - h = NaN; - s = l > 0 && l < 1 ? 0 : h; - } - return new d3_hsl(h, s, l); - } - function d3_rgb_lab(r, g, b) { - r = d3_rgb_xyz(r); - g = d3_rgb_xyz(g); - b = d3_rgb_xyz(b); - var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); - return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); - } - function d3_rgb_xyz(r) { - return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); - } - function d3_rgb_parseNumber(c) { - var f = parseFloat(c); - return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; - } - var d3_rgb_names = d3.map({ - aliceblue: 15792383, - antiquewhite: 16444375, - aqua: 65535, - aquamarine: 8388564, - azure: 15794175, - beige: 16119260, - bisque: 16770244, - black: 0, - blanchedalmond: 16772045, - blue: 255, - blueviolet: 9055202, - brown: 10824234, - burlywood: 14596231, - cadetblue: 6266528, - chartreuse: 8388352, - chocolate: 13789470, - coral: 16744272, - cornflowerblue: 6591981, - cornsilk: 16775388, - crimson: 14423100, - cyan: 65535, - darkblue: 139, - darkcyan: 35723, - darkgoldenrod: 12092939, - darkgray: 11119017, - darkgreen: 25600, - darkgrey: 11119017, - darkkhaki: 12433259, - darkmagenta: 9109643, - darkolivegreen: 5597999, - darkorange: 16747520, - darkorchid: 10040012, - darkred: 9109504, - darksalmon: 15308410, - darkseagreen: 9419919, - darkslateblue: 4734347, - darkslategray: 3100495, - darkslategrey: 3100495, - darkturquoise: 52945, - darkviolet: 9699539, - deeppink: 16716947, - deepskyblue: 49151, - dimgray: 6908265, - dimgrey: 6908265, - dodgerblue: 2003199, - firebrick: 11674146, - floralwhite: 16775920, - forestgreen: 2263842, - fuchsia: 16711935, - gainsboro: 14474460, - ghostwhite: 16316671, - gold: 16766720, - goldenrod: 14329120, - gray: 8421504, - green: 32768, - greenyellow: 11403055, - grey: 8421504, - honeydew: 15794160, - hotpink: 16738740, - indianred: 13458524, - indigo: 4915330, - ivory: 16777200, - khaki: 15787660, - lavender: 15132410, - lavenderblush: 16773365, - lawngreen: 8190976, - lemonchiffon: 16775885, - lightblue: 11393254, - lightcoral: 15761536, - lightcyan: 14745599, - lightgoldenrodyellow: 16448210, - lightgray: 13882323, - lightgreen: 9498256, - lightgrey: 13882323, - lightpink: 16758465, - lightsalmon: 16752762, - lightseagreen: 2142890, - lightskyblue: 8900346, - lightslategray: 7833753, - lightslategrey: 7833753, - lightsteelblue: 11584734, - lightyellow: 16777184, - lime: 65280, - limegreen: 3329330, - linen: 16445670, - magenta: 16711935, - maroon: 8388608, - mediumaquamarine: 6737322, - mediumblue: 205, - mediumorchid: 12211667, - mediumpurple: 9662683, - mediumseagreen: 3978097, - mediumslateblue: 8087790, - mediumspringgreen: 64154, - mediumturquoise: 4772300, - mediumvioletred: 13047173, - midnightblue: 1644912, - mintcream: 16121850, - mistyrose: 16770273, - moccasin: 16770229, - navajowhite: 16768685, - navy: 128, - oldlace: 16643558, - olive: 8421376, - olivedrab: 7048739, - orange: 16753920, - orangered: 16729344, - orchid: 14315734, - palegoldenrod: 15657130, - palegreen: 10025880, - paleturquoise: 11529966, - palevioletred: 14381203, - papayawhip: 16773077, - peachpuff: 16767673, - peru: 13468991, - pink: 16761035, - plum: 14524637, - powderblue: 11591910, - purple: 8388736, - rebeccapurple: 6697881, - red: 16711680, - rosybrown: 12357519, - royalblue: 4286945, - saddlebrown: 9127187, - salmon: 16416882, - sandybrown: 16032864, - seagreen: 3050327, - seashell: 16774638, - sienna: 10506797, - silver: 12632256, - skyblue: 8900331, - slateblue: 6970061, - slategray: 7372944, - slategrey: 7372944, - snow: 16775930, - springgreen: 65407, - steelblue: 4620980, - tan: 13808780, - teal: 32896, - thistle: 14204888, - tomato: 16737095, - turquoise: 4251856, - violet: 15631086, - wheat: 16113331, - white: 16777215, - whitesmoke: 16119285, - yellow: 16776960, - yellowgreen: 10145074 - }); - d3_rgb_names.forEach(function(key, value) { - d3_rgb_names.set(key, d3_rgbNumber(value)); - }); - function d3_functor(v) { - return typeof v === "function" ? v : function() { - return v; - }; - } - d3.functor = d3_functor; - d3.xhr = d3_xhrType(d3_identity); - function d3_xhrType(response) { - return function(url, mimeType, callback) { - if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, - mimeType = null; - return d3_xhr(url, mimeType, response, callback); - }; - } - function d3_xhr(url, mimeType, response, callback) { - var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; - if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); - "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { - request.readyState > 3 && respond(); - }; - function respond() { - var status = request.status, result; - if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { - try { - result = response.call(xhr, request); - } catch (e) { - dispatch.error.call(xhr, e); - return; - } - dispatch.load.call(xhr, result); - } else { - dispatch.error.call(xhr, request); - } - } - request.onprogress = function(event) { - var o = d3.event; - d3.event = event; - try { - dispatch.progress.call(xhr, request); - } finally { - d3.event = o; - } - }; - xhr.header = function(name, value) { - name = (name + "").toLowerCase(); - if (arguments.length < 2) return headers[name]; - if (value == null) delete headers[name]; else headers[name] = value + ""; - return xhr; - }; - xhr.mimeType = function(value) { - if (!arguments.length) return mimeType; - mimeType = value == null ? null : value + ""; - return xhr; - }; - xhr.responseType = function(value) { - if (!arguments.length) return responseType; - responseType = value; - return xhr; - }; - xhr.response = function(value) { - response = value; - return xhr; - }; - [ "get", "post" ].forEach(function(method) { - xhr[method] = function() { - return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); - }; - }); - xhr.send = function(method, data, callback) { - if (arguments.length === 2 && typeof data === "function") callback = data, data = null; - request.open(method, url, true); - if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; - if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); - if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); - if (responseType != null) request.responseType = responseType; - if (callback != null) xhr.on("error", callback).on("load", function(request) { - callback(null, request); - }); - dispatch.beforesend.call(xhr, request); - request.send(data == null ? null : data); - return xhr; - }; - xhr.abort = function() { - request.abort(); - return xhr; - }; - d3.rebind(xhr, dispatch, "on"); - return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); - } - function d3_xhr_fixCallback(callback) { - return callback.length === 1 ? function(error, request) { - callback(error == null ? request : null); - } : callback; - } - function d3_xhrHasResponse(request) { - var type = request.responseType; - return type && type !== "text" ? request.response : request.responseText; - } - d3.dsv = function(delimiter, mimeType) { - var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); - function dsv(url, row, callback) { - if (arguments.length < 3) callback = row, row = null; - var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); - xhr.row = function(_) { - return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; - }; - return xhr; - } - function response(request) { - return dsv.parse(request.responseText); - } - function typedResponse(f) { - return function(request) { - return dsv.parse(request.responseText, f); - }; - } - dsv.parse = function(text, f) { - var o; - return dsv.parseRows(text, function(row, i) { - if (o) return o(row, i - 1); - var a = new Function("d", "return {" + row.map(function(name, i) { - return JSON.stringify(name) + ": d[" + i + "]"; - }).join(",") + "}"); - o = f ? function(row, i) { - return f(a(row), i); - } : a; - }); - }; - dsv.parseRows = function(text, f) { - var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; - function token() { - if (I >= N) return EOF; - if (eol) return eol = false, EOL; - var j = I; - if (text.charCodeAt(j) === 34) { - var i = j; - while (i++ < N) { - if (text.charCodeAt(i) === 34) { - if (text.charCodeAt(i + 1) !== 34) break; - ++i; - } - } - I = i + 2; - var c = text.charCodeAt(i + 1); - if (c === 13) { - eol = true; - if (text.charCodeAt(i + 2) === 10) ++I; - } else if (c === 10) { - eol = true; - } - return text.slice(j + 1, i).replace(/""/g, '"'); - } - while (I < N) { - var c = text.charCodeAt(I++), k = 1; - if (c === 10) eol = true; else if (c === 13) { - eol = true; - if (text.charCodeAt(I) === 10) ++I, ++k; - } else if (c !== delimiterCode) continue; - return text.slice(j, I - k); - } - return text.slice(j); - } - while ((t = token()) !== EOF) { - var a = []; - while (t !== EOL && t !== EOF) { - a.push(t); - t = token(); - } - if (f && (a = f(a, n++)) == null) continue; - rows.push(a); - } - return rows; - }; - dsv.format = function(rows) { - if (Array.isArray(rows[0])) return dsv.formatRows(rows); - var fieldSet = new d3_Set(), fields = []; - rows.forEach(function(row) { - for (var field in row) { - if (!fieldSet.has(field)) { - fields.push(fieldSet.add(field)); - } - } - }); - return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { - return fields.map(function(field) { - return formatValue(row[field]); - }).join(delimiter); - })).join("\n"); - }; - dsv.formatRows = function(rows) { - return rows.map(formatRow).join("\n"); - }; - function formatRow(row) { - return row.map(formatValue).join(delimiter); - } - function formatValue(text) { - return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; - } - return dsv; - }; - d3.csv = d3.dsv(",", "text/csv"); - d3.tsv = d3.dsv(" ", "text/tab-separated-values"); - var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { - setTimeout(callback, 17); - }; - d3.timer = function() { - d3_timer.apply(this, arguments); - }; - function d3_timer(callback, delay, then) { - var n = arguments.length; - if (n < 2) delay = 0; - if (n < 3) then = Date.now(); - var time = then + delay, timer = { - c: callback, - t: time, - n: null - }; - if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; - d3_timer_queueTail = timer; - if (!d3_timer_interval) { - d3_timer_timeout = clearTimeout(d3_timer_timeout); - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - return timer; - } - function d3_timer_step() { - var now = d3_timer_mark(), delay = d3_timer_sweep() - now; - if (delay > 24) { - if (isFinite(delay)) { - clearTimeout(d3_timer_timeout); - d3_timer_timeout = setTimeout(d3_timer_step, delay); - } - d3_timer_interval = 0; - } else { - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); - } - } - d3.timer.flush = function() { - d3_timer_mark(); - d3_timer_sweep(); - }; - function d3_timer_mark() { - var now = Date.now(), timer = d3_timer_queueHead; - while (timer) { - if (now >= timer.t && timer.c(now - timer.t)) timer.c = null; - timer = timer.n; - } - return now; - } - function d3_timer_sweep() { - var t0, t1 = d3_timer_queueHead, time = Infinity; - while (t1) { - if (t1.c) { - if (t1.t < time) time = t1.t; - t1 = (t0 = t1).n; - } else { - t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; - } - } - d3_timer_queueTail = t0; - return time; - } - function d3_format_precision(x, p) { - return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); - } - d3.round = function(x, n) { - return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); - }; - var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); - d3.formatPrefix = function(value, precision) { - var i = 0; - if (value = +value) { - if (value < 0) value *= -1; - if (precision) value = d3.round(value, d3_format_precision(value, precision)); - i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); - i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); - } - return d3_formatPrefixes[8 + i / 3]; - }; - function d3_formatPrefix(d, i) { - var k = Math.pow(10, abs(8 - i) * 3); - return { - scale: i > 8 ? function(d) { - return d / k; - } : function(d) { - return d * k; - }, - symbol: d - }; - } - function d3_locale_numberFormat(locale) { - var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { - var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; - while (i > 0 && g > 0) { - if (length + g + 1 > width) g = Math.max(1, width - length); - t.push(value.substring(i -= g, i + g)); - if ((length += g + 1) > width) break; - g = locale_grouping[j = (j + 1) % locale_grouping.length]; - } - return t.reverse().join(locale_thousands); - } : d3_identity; - return function(specifier) { - var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; - if (precision) precision = +precision.substring(1); - if (zfill || fill === "0" && align === "=") { - zfill = fill = "0"; - align = "="; - } - switch (type) { - case "n": - comma = true; - type = "g"; - break; - - case "%": - scale = 100; - suffix = "%"; - type = "f"; - break; - - case "p": - scale = 100; - suffix = "%"; - type = "r"; - break; - - case "b": - case "o": - case "x": - case "X": - if (symbol === "#") prefix = "0" + type.toLowerCase(); - - case "c": - exponent = false; - - case "d": - integer = true; - precision = 0; - break; - - case "s": - scale = -1; - type = "r"; - break; - } - if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; - if (type == "r" && !precision) type = "g"; - if (precision != null) { - if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); - } - type = d3_format_types.get(type) || d3_format_typeDefault; - var zcomma = zfill && comma; - return function(value) { - var fullSuffix = suffix; - if (integer && value % 1) return ""; - var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; - if (scale < 0) { - var unit = d3.formatPrefix(value, precision); - value = unit.scale(value); - fullSuffix = unit.symbol + suffix; - } else { - value *= scale; - } - value = type(value, precision); - var i = value.lastIndexOf("."), before, after; - if (i < 0) { - var j = exponent ? value.lastIndexOf("e") : -1; - if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); - } else { - before = value.substring(0, i); - after = locale_decimal + value.substring(i + 1); - } - if (!zfill && comma) before = formatGroup(before, Infinity); - var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; - if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); - negative += prefix; - value = before + after; - return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; - }; - }; - } - var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; - var d3_format_types = d3.map({ - b: function(x) { - return x.toString(2); - }, - c: function(x) { - return String.fromCharCode(x); - }, - o: function(x) { - return x.toString(8); - }, - x: function(x) { - return x.toString(16); - }, - X: function(x) { - return x.toString(16).toUpperCase(); - }, - g: function(x, p) { - return x.toPrecision(p); - }, - e: function(x, p) { - return x.toExponential(p); - }, - f: function(x, p) { - return x.toFixed(p); - }, - r: function(x, p) { - return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); - } - }); - function d3_format_typeDefault(x) { - return x + ""; - } - var d3_time = d3.time = {}, d3_date = Date; - function d3_date_utc() { - this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); - } - d3_date_utc.prototype = { - getDate: function() { - return this._.getUTCDate(); - }, - getDay: function() { - return this._.getUTCDay(); - }, - getFullYear: function() { - return this._.getUTCFullYear(); - }, - getHours: function() { - return this._.getUTCHours(); - }, - getMilliseconds: function() { - return this._.getUTCMilliseconds(); - }, - getMinutes: function() { - return this._.getUTCMinutes(); - }, - getMonth: function() { - return this._.getUTCMonth(); - }, - getSeconds: function() { - return this._.getUTCSeconds(); - }, - getTime: function() { - return this._.getTime(); - }, - getTimezoneOffset: function() { - return 0; - }, - valueOf: function() { - return this._.valueOf(); - }, - setDate: function() { - d3_time_prototype.setUTCDate.apply(this._, arguments); - }, - setDay: function() { - d3_time_prototype.setUTCDay.apply(this._, arguments); - }, - setFullYear: function() { - d3_time_prototype.setUTCFullYear.apply(this._, arguments); - }, - setHours: function() { - d3_time_prototype.setUTCHours.apply(this._, arguments); - }, - setMilliseconds: function() { - d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); - }, - setMinutes: function() { - d3_time_prototype.setUTCMinutes.apply(this._, arguments); - }, - setMonth: function() { - d3_time_prototype.setUTCMonth.apply(this._, arguments); - }, - setSeconds: function() { - d3_time_prototype.setUTCSeconds.apply(this._, arguments); - }, - setTime: function() { - d3_time_prototype.setTime.apply(this._, arguments); - } - }; - var d3_time_prototype = Date.prototype; - function d3_time_interval(local, step, number) { - function round(date) { - var d0 = local(date), d1 = offset(d0, 1); - return date - d0 < d1 - date ? d0 : d1; - } - function ceil(date) { - step(date = local(new d3_date(date - 1)), 1); - return date; - } - function offset(date, k) { - step(date = new d3_date(+date), k); - return date; - } - function range(t0, t1, dt) { - var time = ceil(t0), times = []; - if (dt > 1) { - while (time < t1) { - if (!(number(time) % dt)) times.push(new Date(+time)); - step(time, 1); - } - } else { - while (time < t1) times.push(new Date(+time)), step(time, 1); - } - return times; - } - function range_utc(t0, t1, dt) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = t0; - return range(utc, t1, dt); - } finally { - d3_date = Date; - } - } - local.floor = local; - local.round = round; - local.ceil = ceil; - local.offset = offset; - local.range = range; - var utc = local.utc = d3_time_interval_utc(local); - utc.floor = utc; - utc.round = d3_time_interval_utc(round); - utc.ceil = d3_time_interval_utc(ceil); - utc.offset = d3_time_interval_utc(offset); - utc.range = range_utc; - return local; - } - function d3_time_interval_utc(method) { - return function(date, k) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = date; - return method(utc, k)._; - } finally { - d3_date = Date; - } - }; - } - d3_time.year = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setMonth(0, 1); - return date; - }, function(date, offset) { - date.setFullYear(date.getFullYear() + offset); - }, function(date) { - return date.getFullYear(); - }); - d3_time.years = d3_time.year.range; - d3_time.years.utc = d3_time.year.utc.range; - d3_time.day = d3_time_interval(function(date) { - var day = new d3_date(2e3, 0); - day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); - return day; - }, function(date, offset) { - date.setDate(date.getDate() + offset); - }, function(date) { - return date.getDate() - 1; - }); - d3_time.days = d3_time.day.range; - d3_time.days.utc = d3_time.day.utc.range; - d3_time.dayOfYear = function(date) { - var year = d3_time.year(date); - return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); - }; - [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { - i = 7 - i; - var interval = d3_time[day] = d3_time_interval(function(date) { - (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); - return date; - }, function(date, offset) { - date.setDate(date.getDate() + Math.floor(offset) * 7); - }, function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); - }); - d3_time[day + "s"] = interval.range; - d3_time[day + "s"].utc = interval.utc.range; - d3_time[day + "OfYear"] = function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); - }; - }); - d3_time.week = d3_time.sunday; - d3_time.weeks = d3_time.sunday.range; - d3_time.weeks.utc = d3_time.sunday.utc.range; - d3_time.weekOfYear = d3_time.sundayOfYear; - function d3_locale_timeFormat(locale) { - var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; - function d3_time_format(template) { - var n = template.length; - function format(date) { - var string = [], i = -1, j = 0, c, p, f; - while (++i < n) { - if (template.charCodeAt(i) === 37) { - string.push(template.slice(j, i)); - if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); - if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); - string.push(c); - j = i + 1; - } - } - string.push(template.slice(j, i)); - return string.join(""); - } - format.parse = function(string) { - var d = { - y: 1900, - m: 0, - d: 1, - H: 0, - M: 0, - S: 0, - L: 0, - Z: null - }, i = d3_time_parse(d, template, string, 0); - if (i != string.length) return null; - if ("p" in d) d.H = d.H % 12 + d.p * 12; - var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); - if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) { - if (!("w" in d)) d.w = "W" in d ? 1 : 0; - date.setFullYear(d.y, 0, 1); - date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); - } else date.setFullYear(d.y, d.m, d.d); - date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); - return localZ ? date._ : date; - }; - format.toString = function() { - return template; - }; - return format; - } - function d3_time_parse(date, template, string, j) { - var c, p, t, i = 0, n = template.length, m = string.length; - while (i < n) { - if (j >= m) return -1; - c = template.charCodeAt(i++); - if (c === 37) { - t = template.charAt(i++); - p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; - if (!p || (j = p(date, string, j)) < 0) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; - } - } - return j; - } - d3_time_format.utc = function(template) { - var local = d3_time_format(template); - function format(date) { - try { - d3_date = d3_date_utc; - var utc = new d3_date(); - utc._ = date; - return local(utc); - } finally { - d3_date = Date; - } - } - format.parse = function(string) { - try { - d3_date = d3_date_utc; - var date = local.parse(string); - return date && date._; - } finally { - d3_date = Date; - } - }; - format.toString = local.toString; - return format; - }; - d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; - var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); - locale_periods.forEach(function(p, i) { - d3_time_periodLookup.set(p.toLowerCase(), i); - }); - var d3_time_formats = { - a: function(d) { - return locale_shortDays[d.getDay()]; - }, - A: function(d) { - return locale_days[d.getDay()]; - }, - b: function(d) { - return locale_shortMonths[d.getMonth()]; - }, - B: function(d) { - return locale_months[d.getMonth()]; - }, - c: d3_time_format(locale_dateTime), - d: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - e: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - H: function(d, p) { - return d3_time_formatPad(d.getHours(), p, 2); - }, - I: function(d, p) { - return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); - }, - j: function(d, p) { - return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); - }, - L: function(d, p) { - return d3_time_formatPad(d.getMilliseconds(), p, 3); - }, - m: function(d, p) { - return d3_time_formatPad(d.getMonth() + 1, p, 2); - }, - M: function(d, p) { - return d3_time_formatPad(d.getMinutes(), p, 2); - }, - p: function(d) { - return locale_periods[+(d.getHours() >= 12)]; - }, - S: function(d, p) { - return d3_time_formatPad(d.getSeconds(), p, 2); - }, - U: function(d, p) { - return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); - }, - w: function(d) { - return d.getDay(); - }, - W: function(d, p) { - return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); - }, - x: d3_time_format(locale_date), - X: d3_time_format(locale_time), - y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 100, p, 2); - }, - Y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); - }, - Z: d3_time_zone, - "%": function() { - return "%"; - } - }; - var d3_time_parsers = { - a: d3_time_parseWeekdayAbbrev, - A: d3_time_parseWeekday, - b: d3_time_parseMonthAbbrev, - B: d3_time_parseMonth, - c: d3_time_parseLocaleFull, - d: d3_time_parseDay, - e: d3_time_parseDay, - H: d3_time_parseHour24, - I: d3_time_parseHour24, - j: d3_time_parseDayOfYear, - L: d3_time_parseMilliseconds, - m: d3_time_parseMonthNumber, - M: d3_time_parseMinutes, - p: d3_time_parseAmPm, - S: d3_time_parseSeconds, - U: d3_time_parseWeekNumberSunday, - w: d3_time_parseWeekdayNumber, - W: d3_time_parseWeekNumberMonday, - x: d3_time_parseLocaleDate, - X: d3_time_parseLocaleTime, - y: d3_time_parseYear, - Y: d3_time_parseFullYear, - Z: d3_time_parseZone, - "%": d3_time_parseLiteralPercent - }; - function d3_time_parseWeekdayAbbrev(date, string, i) { - d3_time_dayAbbrevRe.lastIndex = 0; - var n = d3_time_dayAbbrevRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseWeekday(date, string, i) { - d3_time_dayRe.lastIndex = 0; - var n = d3_time_dayRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonthAbbrev(date, string, i) { - d3_time_monthAbbrevRe.lastIndex = 0; - var n = d3_time_monthAbbrevRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseMonth(date, string, i) { - d3_time_monthRe.lastIndex = 0; - var n = d3_time_monthRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; - } - function d3_time_parseLocaleFull(date, string, i) { - return d3_time_parse(date, d3_time_formats.c.toString(), string, i); - } - function d3_time_parseLocaleDate(date, string, i) { - return d3_time_parse(date, d3_time_formats.x.toString(), string, i); - } - function d3_time_parseLocaleTime(date, string, i) { - return d3_time_parse(date, d3_time_formats.X.toString(), string, i); - } - function d3_time_parseAmPm(date, string, i) { - var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); - return n == null ? -1 : (date.p = n, i); - } - return d3_time_format; - } - var d3_time_formatPads = { - "-": "", - _: " ", - "0": "0" - }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; - function d3_time_formatPad(value, fill, width) { - var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; - return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); - } - function d3_time_formatRe(names) { - return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); - } - function d3_time_formatLookup(names) { - var map = new d3_Map(), i = -1, n = names.length; - while (++i < n) map.set(names[i].toLowerCase(), i); - return map; - } - function d3_time_parseWeekdayNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 1)); - return n ? (date.w = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberSunday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.U = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberMonday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.W = +n[0], i + n[0].length) : -1; - } - function d3_time_parseFullYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 4)); - return n ? (date.y = +n[0], i + n[0].length) : -1; - } - function d3_time_parseYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; - } - function d3_time_parseZone(date, string, i) { - return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, - i + 5) : -1; - } - function d3_time_expandYear(d) { - return d + (d > 68 ? 1900 : 2e3); - } - function d3_time_parseMonthNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.m = n[0] - 1, i + n[0].length) : -1; - } - function d3_time_parseDay(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.d = +n[0], i + n[0].length) : -1; - } - function d3_time_parseDayOfYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.j = +n[0], i + n[0].length) : -1; - } - function d3_time_parseHour24(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.H = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMinutes(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.M = +n[0], i + n[0].length) : -1; - } - function d3_time_parseSeconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.S = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMilliseconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.L = +n[0], i + n[0].length) : -1; - } - function d3_time_zone(d) { - var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; - return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); - } - function d3_time_parseLiteralPercent(date, string, i) { - d3_time_percentRe.lastIndex = 0; - var n = d3_time_percentRe.exec(string.slice(i, i + 1)); - return n ? i + n[0].length : -1; - } - function d3_time_formatMulti(formats) { - var n = formats.length, i = -1; - while (++i < n) formats[i][0] = this(formats[i][0]); - return function(date) { - var i = 0, f = formats[i]; - while (!f[1](date)) f = formats[++i]; - return f[0](date); - }; - } - d3.locale = function(locale) { - return { - numberFormat: d3_locale_numberFormat(locale), - timeFormat: d3_locale_timeFormat(locale) - }; - }; - var d3_locale_enUS = d3.locale({ - decimal: ".", - thousands: ",", - grouping: [ 3 ], - currency: [ "$", "" ], - dateTime: "%a %b %e %X %Y", - date: "%m/%d/%Y", - time: "%H:%M:%S", - periods: [ "AM", "PM" ], - days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], - shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], - months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], - shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] - }); - d3.format = d3_locale_enUS.numberFormat; - d3.geo = {}; - function d3_adder() {} - d3_adder.prototype = { - s: 0, - t: 0, - add: function(y) { - d3_adderSum(y, this.t, d3_adderTemp); - d3_adderSum(d3_adderTemp.s, this.s, this); - if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; - }, - reset: function() { - this.s = this.t = 0; - }, - valueOf: function() { - return this.s; - } - }; - var d3_adderTemp = new d3_adder(); - function d3_adderSum(a, b, o) { - var x = o.s = a + b, bv = x - a, av = x - bv; - o.t = a - av + (b - bv); - } - d3.geo.stream = function(object, listener) { - if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { - d3_geo_streamObjectType[object.type](object, listener); - } else { - d3_geo_streamGeometry(object, listener); - } - }; - function d3_geo_streamGeometry(geometry, listener) { - if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { - d3_geo_streamGeometryType[geometry.type](geometry, listener); - } - } - var d3_geo_streamObjectType = { - Feature: function(feature, listener) { - d3_geo_streamGeometry(feature.geometry, listener); - }, - FeatureCollection: function(object, listener) { - var features = object.features, i = -1, n = features.length; - while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); - } - }; - var d3_geo_streamGeometryType = { - Sphere: function(object, listener) { - listener.sphere(); - }, - Point: function(object, listener) { - object = object.coordinates; - listener.point(object[0], object[1], object[2]); - }, - MultiPoint: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); - }, - LineString: function(object, listener) { - d3_geo_streamLine(object.coordinates, listener, 0); - }, - MultiLineString: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); - }, - Polygon: function(object, listener) { - d3_geo_streamPolygon(object.coordinates, listener); - }, - MultiPolygon: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); - }, - GeometryCollection: function(object, listener) { - var geometries = object.geometries, i = -1, n = geometries.length; - while (++i < n) d3_geo_streamGeometry(geometries[i], listener); - } - }; - function d3_geo_streamLine(coordinates, listener, closed) { - var i = -1, n = coordinates.length - closed, coordinate; - listener.lineStart(); - while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); - listener.lineEnd(); - } - function d3_geo_streamPolygon(coordinates, listener) { - var i = -1, n = coordinates.length; - listener.polygonStart(); - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); - listener.polygonEnd(); - } - d3.geo.area = function(object) { - d3_geo_areaSum = 0; - d3.geo.stream(object, d3_geo_area); - return d3_geo_areaSum; - }; - var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); - var d3_geo_area = { - sphere: function() { - d3_geo_areaSum += 4 * π; - }, - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_areaRingSum.reset(); - d3_geo_area.lineStart = d3_geo_areaRingStart; - }, - polygonEnd: function() { - var area = 2 * d3_geo_areaRingSum; - d3_geo_areaSum += area < 0 ? 4 * π + area : area; - d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; - } - }; - function d3_geo_areaRingStart() { - var λ00, φ00, λ0, cosφ0, sinφ0; - d3_geo_area.point = function(λ, φ) { - d3_geo_area.point = nextPoint; - λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), - sinφ0 = Math.sin(φ); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - φ = φ * d3_radians / 2 + π / 4; - var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); - d3_geo_areaRingSum.add(Math.atan2(v, u)); - λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; - } - d3_geo_area.lineEnd = function() { - nextPoint(λ00, φ00); - }; - } - function d3_geo_cartesian(spherical) { - var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); - return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; - } - function d3_geo_cartesianDot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; - } - function d3_geo_cartesianCross(a, b) { - return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; - } - function d3_geo_cartesianAdd(a, b) { - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; - } - function d3_geo_cartesianScale(vector, k) { - return [ vector[0] * k, vector[1] * k, vector[2] * k ]; - } - function d3_geo_cartesianNormalize(d) { - var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); - d[0] /= l; - d[1] /= l; - d[2] /= l; - } - function d3_geo_spherical(cartesian) { - return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; - } - function d3_geo_sphericalEqual(a, b) { - return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; - } - d3.geo.bounds = function() { - var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; - var bound = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - bound.point = ringPoint; - bound.lineStart = ringStart; - bound.lineEnd = ringEnd; - dλSum = 0; - d3_geo_area.polygonStart(); - }, - polygonEnd: function() { - d3_geo_area.polygonEnd(); - bound.point = point; - bound.lineStart = lineStart; - bound.lineEnd = lineEnd; - if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; - range[0] = λ0, range[1] = λ1; - } - }; - function point(λ, φ) { - ranges.push(range = [ λ0 = λ, λ1 = λ ]); - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - function linePoint(λ, φ) { - var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); - if (p0) { - var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); - d3_geo_cartesianNormalize(inflection); - inflection = d3_geo_spherical(inflection); - var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; - if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = inflection[1] * d3_degrees; - if (φi > φ1) φ1 = φi; - } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = -inflection[1] * d3_degrees; - if (φi < φ0) φ0 = φi; - } else { - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - if (antimeridian) { - if (λ < λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } else { - if (λ1 >= λ0) { - if (λ < λ0) λ0 = λ; - if (λ > λ1) λ1 = λ; - } else { - if (λ > λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } - } - } else { - point(λ, φ); - } - p0 = p, λ_ = λ; - } - function lineStart() { - bound.point = linePoint; - } - function lineEnd() { - range[0] = λ0, range[1] = λ1; - bound.point = point; - p0 = null; - } - function ringPoint(λ, φ) { - if (p0) { - var dλ = λ - λ_; - dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; - } else λ__ = λ, φ__ = φ; - d3_geo_area.point(λ, φ); - linePoint(λ, φ); - } - function ringStart() { - d3_geo_area.lineStart(); - } - function ringEnd() { - ringPoint(λ__, φ__); - d3_geo_area.lineEnd(); - if (abs(dλSum) > ε) λ0 = -(λ1 = 180); - range[0] = λ0, range[1] = λ1; - p0 = null; - } - function angle(λ0, λ1) { - return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; - } - function compareRanges(a, b) { - return a[0] - b[0]; - } - function withinRange(x, range) { - return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; - } - return function(feature) { - φ1 = λ1 = -(λ0 = φ0 = Infinity); - ranges = []; - d3.geo.stream(feature, bound); - var n = ranges.length; - if (n) { - ranges.sort(compareRanges); - for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { - b = ranges[i]; - if (withinRange(b[0], a) || withinRange(b[1], a)) { - if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; - if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; - } else { - merged.push(a = b); - } - } - var best = -Infinity, dλ; - for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { - b = merged[i]; - if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; - } - } - ranges = range = null; - return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; - }; - }(); - d3.geo.centroid = function(object) { - d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, d3_geo_centroid); - var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; - if (m < ε2) { - x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; - if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; - m = x * x + y * y + z * z; - if (m < ε2) return [ NaN, NaN ]; - } - return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; - }; - var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; - var d3_geo_centroid = { - sphere: d3_noop, - point: d3_geo_centroidPoint, - lineStart: d3_geo_centroidLineStart, - lineEnd: d3_geo_centroidLineEnd, - polygonStart: function() { - d3_geo_centroid.lineStart = d3_geo_centroidRingStart; - }, - polygonEnd: function() { - d3_geo_centroid.lineStart = d3_geo_centroidLineStart; - } - }; - function d3_geo_centroidPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); - } - function d3_geo_centroidPointXYZ(x, y, z) { - ++d3_geo_centroidW0; - d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; - d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; - d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; - } - function d3_geo_centroidLineStart() { - var x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroid.point = nextPoint; - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_centroidLineEnd() { - d3_geo_centroid.point = d3_geo_centroidPoint; - } - function d3_geo_centroidRingStart() { - var λ00, φ00, x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ00 = λ, φ00 = φ; - d3_geo_centroid.point = nextPoint; - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroidPointXYZ(x0, y0, z0); - }; - d3_geo_centroid.lineEnd = function() { - nextPoint(λ00, φ00); - d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; - d3_geo_centroid.point = d3_geo_centroidPoint; - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); - d3_geo_centroidX2 += v * cx; - d3_geo_centroidY2 += v * cy; - d3_geo_centroidZ2 += v * cz; - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_compose(a, b) { - function compose(x, y) { - return x = a(x, y), b(x[0], x[1]); - } - if (a.invert && b.invert) compose.invert = function(x, y) { - return x = b.invert(x, y), x && a.invert(x[0], x[1]); - }; - return compose; - } - function d3_true() { - return true; - } - function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { - var subject = [], clip = []; - segments.forEach(function(segment) { - if ((n = segment.length - 1) <= 0) return; - var n, p0 = segment[0], p1 = segment[n]; - if (d3_geo_sphericalEqual(p0, p1)) { - listener.lineStart(); - for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); - listener.lineEnd(); - return; - } - var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); - a.o = b; - subject.push(a); - clip.push(b); - a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); - b = new d3_geo_clipPolygonIntersection(p1, null, a, true); - a.o = b; - subject.push(a); - clip.push(b); - }); - clip.sort(compare); - d3_geo_clipPolygonLinkCircular(subject); - d3_geo_clipPolygonLinkCircular(clip); - if (!subject.length) return; - for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { - clip[i].e = entry = !entry; - } - var start = subject[0], points, point; - while (1) { - var current = start, isSubject = true; - while (current.v) if ((current = current.n) === start) return; - points = current.z; - listener.lineStart(); - do { - current.v = current.o.v = true; - if (current.e) { - if (isSubject) { - for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.n.x, 1, listener); - } - current = current.n; - } else { - if (isSubject) { - points = current.p.z; - for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.p.x, -1, listener); - } - current = current.p; - } - current = current.o; - points = current.z; - isSubject = !isSubject; - } while (!current.v); - listener.lineEnd(); - } - } - function d3_geo_clipPolygonLinkCircular(array) { - if (!(n = array.length)) return; - var n, i = 0, a = array[0], b; - while (++i < n) { - a.n = b = array[i]; - b.p = a; - a = b; - } - a.n = b = array[0]; - b.p = a; - } - function d3_geo_clipPolygonIntersection(point, points, other, entry) { - this.x = point; - this.z = points; - this.o = other; - this.e = entry; - this.v = false; - this.n = this.p = null; - } - function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { - return function(rotate, listener) { - var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - clip.point = pointRing; - clip.lineStart = ringStart; - clip.lineEnd = ringEnd; - segments = []; - polygon = []; - }, - polygonEnd: function() { - clip.point = point; - clip.lineStart = lineStart; - clip.lineEnd = lineEnd; - segments = d3.merge(segments); - var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); - if (segments.length) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); - } else if (clipStartInside) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (polygonStarted) listener.polygonEnd(), polygonStarted = false; - segments = polygon = null; - }, - sphere: function() { - listener.polygonStart(); - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - listener.polygonEnd(); - } - }; - function point(λ, φ) { - var point = rotate(λ, φ); - if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); - } - function pointLine(λ, φ) { - var point = rotate(λ, φ); - line.point(point[0], point[1]); - } - function lineStart() { - clip.point = pointLine; - line.lineStart(); - } - function lineEnd() { - clip.point = point; - line.lineEnd(); - } - var segments; - var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; - function pointRing(λ, φ) { - ring.push([ λ, φ ]); - var point = rotate(λ, φ); - ringListener.point(point[0], point[1]); - } - function ringStart() { - ringListener.lineStart(); - ring = []; - } - function ringEnd() { - pointRing(ring[0][0], ring[0][1]); - ringListener.lineEnd(); - var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; - ring.pop(); - polygon.push(ring); - ring = null; - if (!n) return; - if (clean & 1) { - segment = ringSegments[0]; - var n = segment.length - 1, i = -1, point; - if (n > 0) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - while (++i < n) listener.point((point = segment[i])[0], point[1]); - listener.lineEnd(); - } - return; - } - if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); - segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); - } - return clip; - }; - } - function d3_geo_clipSegmentLength1(segment) { - return segment.length > 1; - } - function d3_geo_clipBufferListener() { - var lines = [], line; - return { - lineStart: function() { - lines.push(line = []); - }, - point: function(λ, φ) { - line.push([ λ, φ ]); - }, - lineEnd: d3_noop, - buffer: function() { - var buffer = lines; - lines = []; - line = null; - return buffer; - }, - rejoin: function() { - if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); - } - }; - } - function d3_geo_clipSort(a, b) { - return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); - } - var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); - function d3_geo_clipAntimeridianLine(listener) { - var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; - return { - lineStart: function() { - listener.lineStart(); - clean = 1; - }, - point: function(λ1, φ1) { - var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); - if (abs(dλ - π) < ε) { - listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - listener.point(λ1, φ0); - clean = 0; - } else if (sλ0 !== sλ1 && dλ >= π) { - if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; - if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; - φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - clean = 0; - } - listener.point(λ0 = λ1, φ0 = φ1); - sλ0 = sλ1; - }, - lineEnd: function() { - listener.lineEnd(); - λ0 = φ0 = NaN; - }, - clean: function() { - return 2 - clean; - } - }; - } - function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { - var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); - return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; - } - function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { - var φ; - if (from == null) { - φ = direction * halfπ; - listener.point(-π, φ); - listener.point(0, φ); - listener.point(π, φ); - listener.point(π, 0); - listener.point(π, -φ); - listener.point(0, -φ); - listener.point(-π, -φ); - listener.point(-π, 0); - listener.point(-π, φ); - } else if (abs(from[0] - to[0]) > ε) { - var s = from[0] < to[0] ? π : -π; - φ = direction * s / 2; - listener.point(-s, φ); - listener.point(0, φ); - listener.point(s, φ); - } else { - listener.point(to[0], to[1]); - } - } - function d3_geo_pointInPolygon(point, polygon) { - var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; - d3_geo_areaRingSum.reset(); - for (var i = 0, n = polygon.length; i < n; ++i) { - var ring = polygon[i], m = ring.length; - if (!m) continue; - var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; - while (true) { - if (j === m) j = 0; - point = ring[j]; - var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; - d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); - polarAngle += antimeridian ? dλ + sdλ * τ : dλ; - if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { - var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); - d3_geo_cartesianNormalize(arc); - var intersection = d3_geo_cartesianCross(meridianNormal, arc); - d3_geo_cartesianNormalize(intersection); - var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); - if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { - winding += antimeridian ^ dλ >= 0 ? 1 : -1; - } - } - if (!j++) break; - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; - } - } - return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < -ε) ^ winding & 1; - } - function d3_geo_clipCircle(radius) { - var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); - return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); - function visible(λ, φ) { - return Math.cos(λ) * Math.cos(φ) > cr; - } - function clipLine(listener) { - var point0, c0, v0, v00, clean; - return { - lineStart: function() { - v00 = v0 = false; - clean = 1; - }, - point: function(λ, φ) { - var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; - if (!point0 && (v00 = v0 = v)) listener.lineStart(); - if (v !== v0) { - point2 = intersect(point0, point1); - if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { - point1[0] += ε; - point1[1] += ε; - v = visible(point1[0], point1[1]); - } - } - if (v !== v0) { - clean = 0; - if (v) { - listener.lineStart(); - point2 = intersect(point1, point0); - listener.point(point2[0], point2[1]); - } else { - point2 = intersect(point0, point1); - listener.point(point2[0], point2[1]); - listener.lineEnd(); - } - point0 = point2; - } else if (notHemisphere && point0 && smallRadius ^ v) { - var t; - if (!(c & c0) && (t = intersect(point1, point0, true))) { - clean = 0; - if (smallRadius) { - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - } else { - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - } - } - } - if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { - listener.point(point1[0], point1[1]); - } - point0 = point1, v0 = v, c0 = c; - }, - lineEnd: function() { - if (v0) listener.lineEnd(); - point0 = null; - }, - clean: function() { - return clean | (v00 && v0) << 1; - } - }; - } - function intersect(a, b, two) { - var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); - var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; - if (!determinant) return !two && a; - var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); - d3_geo_cartesianAdd(A, B); - var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); - if (t2 < 0) return; - var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); - d3_geo_cartesianAdd(q, A); - q = d3_geo_spherical(q); - if (!two) return q; - var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; - if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; - var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; - if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; - if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { - var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); - d3_geo_cartesianAdd(q1, A); - return [ q, d3_geo_spherical(q1) ]; - } - } - function code(λ, φ) { - var r = smallRadius ? radius : π - radius, code = 0; - if (λ < -r) code |= 1; else if (λ > r) code |= 2; - if (φ < -r) code |= 4; else if (φ > r) code |= 8; - return code; - } - } - function d3_geom_clipLine(x0, y0, x1, y1) { - return function(line) { - var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; - r = x0 - ax; - if (!dx && r > 0) return; - r /= dx; - if (dx < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dx > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = x1 - ax; - if (!dx && r < 0) return; - r /= dx; - if (dx < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dx > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - r = y0 - ay; - if (!dy && r > 0) return; - r /= dy; - if (dy < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dy > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = y1 - ay; - if (!dy && r < 0) return; - r /= dy; - if (dy < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dy > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - if (t0 > 0) line.a = { - x: ax + t0 * dx, - y: ay + t0 * dy - }; - if (t1 < 1) line.b = { - x: ax + t1 * dx, - y: ay + t1 * dy - }; - return line; - }; - } - var d3_geo_clipExtentMAX = 1e9; - d3.geo.clipExtent = function() { - var x0, y0, x1, y1, stream, clip, clipExtent = { - stream: function(output) { - if (stream) stream.valid = false; - stream = clip(output); - stream.valid = true; - return stream; - }, - extent: function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); - if (stream) stream.valid = false, stream = null; - return clipExtent; - } - }; - return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); - }; - function d3_geo_clipExtent(x0, y0, x1, y1) { - return function(listener) { - var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - listener = bufferListener; - segments = []; - polygon = []; - clean = true; - }, - polygonEnd: function() { - listener = listener_; - segments = d3.merge(segments); - var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; - if (inside || visible) { - listener.polygonStart(); - if (inside) { - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (visible) { - d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); - } - listener.polygonEnd(); - } - segments = polygon = ring = null; - } - }; - function insidePolygon(p) { - var wn = 0, n = polygon.length, y = p[1]; - for (var i = 0; i < n; ++i) { - for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { - b = v[j]; - if (a[1] <= y) { - if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; - } else { - if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; - } - a = b; - } - } - return wn !== 0; - } - function interpolate(from, to, direction, listener) { - var a = 0, a1 = 0; - if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { - do { - listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); - } while ((a = (a + direction + 4) % 4) !== a1); - } else { - listener.point(to[0], to[1]); - } - } - function pointVisible(x, y) { - return x0 <= x && x <= x1 && y0 <= y && y <= y1; - } - function point(x, y) { - if (pointVisible(x, y)) listener.point(x, y); - } - var x__, y__, v__, x_, y_, v_, first, clean; - function lineStart() { - clip.point = linePoint; - if (polygon) polygon.push(ring = []); - first = true; - v_ = false; - x_ = y_ = NaN; - } - function lineEnd() { - if (segments) { - linePoint(x__, y__); - if (v__ && v_) bufferListener.rejoin(); - segments.push(bufferListener.buffer()); - } - clip.point = point; - if (v_) listener.lineEnd(); - } - function linePoint(x, y) { - x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); - y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); - var v = pointVisible(x, y); - if (polygon) ring.push([ x, y ]); - if (first) { - x__ = x, y__ = y, v__ = v; - first = false; - if (v) { - listener.lineStart(); - listener.point(x, y); - } - } else { - if (v && v_) listener.point(x, y); else { - var l = { - a: { - x: x_, - y: y_ - }, - b: { - x: x, - y: y - } - }; - if (clipLine(l)) { - if (!v_) { - listener.lineStart(); - listener.point(l.a.x, l.a.y); - } - listener.point(l.b.x, l.b.y); - if (!v) listener.lineEnd(); - clean = false; - } else if (v) { - listener.lineStart(); - listener.point(x, y); - clean = false; - } - } - } - x_ = x, y_ = y, v_ = v; - } - return clip; - }; - function corner(p, direction) { - return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; - } - function compare(a, b) { - return comparePoints(a.x, b.x); - } - function comparePoints(a, b) { - var ca = corner(a, 1), cb = corner(b, 1); - return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; - } - } - function d3_geo_conic(projectAt) { - var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); - p.parallels = function(_) { - if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; - return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); - }; - return p; - } - function d3_geo_conicEqualArea(φ0, φ1) { - var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; - function forward(λ, φ) { - var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; - return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = ρ0 - y; - return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; - }; - return forward; - } - (d3.geo.conicEqualArea = function() { - return d3_geo_conic(d3_geo_conicEqualArea); - }).raw = d3_geo_conicEqualArea; - d3.geo.albers = function() { - return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); - }; - d3.geo.albersUsa = function() { - var lower48 = d3.geo.albers(); - var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); - var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); - var point, pointStream = { - point: function(x, y) { - point = [ x, y ]; - } - }, lower48Point, alaskaPoint, hawaiiPoint; - function albersUsa(coordinates) { - var x = coordinates[0], y = coordinates[1]; - point = null; - (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); - return point; - } - albersUsa.invert = function(coordinates) { - var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; - return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); - }; - albersUsa.stream = function(stream) { - var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); - return { - point: function(x, y) { - lower48Stream.point(x, y); - alaskaStream.point(x, y); - hawaiiStream.point(x, y); - }, - sphere: function() { - lower48Stream.sphere(); - alaskaStream.sphere(); - hawaiiStream.sphere(); - }, - lineStart: function() { - lower48Stream.lineStart(); - alaskaStream.lineStart(); - hawaiiStream.lineStart(); - }, - lineEnd: function() { - lower48Stream.lineEnd(); - alaskaStream.lineEnd(); - hawaiiStream.lineEnd(); - }, - polygonStart: function() { - lower48Stream.polygonStart(); - alaskaStream.polygonStart(); - hawaiiStream.polygonStart(); - }, - polygonEnd: function() { - lower48Stream.polygonEnd(); - alaskaStream.polygonEnd(); - hawaiiStream.polygonEnd(); - } - }; - }; - albersUsa.precision = function(_) { - if (!arguments.length) return lower48.precision(); - lower48.precision(_); - alaska.precision(_); - hawaii.precision(_); - return albersUsa; - }; - albersUsa.scale = function(_) { - if (!arguments.length) return lower48.scale(); - lower48.scale(_); - alaska.scale(_ * .35); - hawaii.scale(_); - return albersUsa.translate(lower48.translate()); - }; - albersUsa.translate = function(_) { - if (!arguments.length) return lower48.translate(); - var k = lower48.scale(), x = +_[0], y = +_[1]; - lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; - alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - return albersUsa; - }; - return albersUsa.scale(1070); - }; - var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_pathAreaPolygon = 0; - d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; - }, - polygonEnd: function() { - d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; - d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); - } - }; - function d3_geo_pathAreaRingStart() { - var x00, y00, x0, y0; - d3_geo_pathArea.point = function(x, y) { - d3_geo_pathArea.point = nextPoint; - x00 = x0 = x, y00 = y0 = y; - }; - function nextPoint(x, y) { - d3_geo_pathAreaPolygon += y0 * x - x0 * y; - x0 = x, y0 = y; - } - d3_geo_pathArea.lineEnd = function() { - nextPoint(x00, y00); - }; - } - var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; - var d3_geo_pathBounds = { - point: d3_geo_pathBoundsPoint, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_pathBoundsPoint(x, y) { - if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; - if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; - if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; - if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; - } - function d3_geo_pathBuffer() { - var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointCircle = d3_geo_pathBufferCircle(_); - return stream; - }, - result: function() { - if (buffer.length) { - var result = buffer.join(""); - buffer = []; - return result; - } - } - }; - function point(x, y) { - buffer.push("M", x, ",", y, pointCircle); - } - function pointLineStart(x, y) { - buffer.push("M", x, ",", y); - stream.point = pointLine; - } - function pointLine(x, y) { - buffer.push("L", x, ",", y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - buffer.push("Z"); - } - return stream; - } - function d3_geo_pathBufferCircle(radius) { - return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; - } - var d3_geo_pathCentroid = { - point: d3_geo_pathCentroidPoint, - lineStart: d3_geo_pathCentroidLineStart, - lineEnd: d3_geo_pathCentroidLineEnd, - polygonStart: function() { - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; - }, - polygonEnd: function() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; - d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; - } - }; - function d3_geo_pathCentroidPoint(x, y) { - d3_geo_centroidX0 += x; - d3_geo_centroidY0 += y; - ++d3_geo_centroidZ0; - } - function d3_geo_pathCentroidLineStart() { - var x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - } - function d3_geo_pathCentroidLineEnd() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - } - function d3_geo_pathCentroidRingStart() { - var x00, y00, x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - z = y0 * x - x0 * y; - d3_geo_centroidX2 += z * (x0 + x); - d3_geo_centroidY2 += z * (y0 + y); - d3_geo_centroidZ2 += z * 3; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - d3_geo_pathCentroid.lineEnd = function() { - nextPoint(x00, y00); - }; - } - function d3_geo_pathContext(context) { - var pointRadius = 4.5; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointRadius = _; - return stream; - }, - result: d3_noop - }; - function point(x, y) { - context.moveTo(x + pointRadius, y); - context.arc(x, y, pointRadius, 0, τ); - } - function pointLineStart(x, y) { - context.moveTo(x, y); - stream.point = pointLine; - } - function pointLine(x, y) { - context.lineTo(x, y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - context.closePath(); - } - return stream; - } - function d3_geo_resample(project) { - var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; - function resample(stream) { - return (maxDepth ? resampleRecursive : resampleNone)(stream); - } - function resampleNone(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - }); - } - function resampleRecursive(stream) { - var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; - var resample = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - stream.polygonStart(); - resample.lineStart = ringStart; - }, - polygonEnd: function() { - stream.polygonEnd(); - resample.lineStart = lineStart; - } - }; - function point(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - } - function lineStart() { - x0 = NaN; - resample.point = linePoint; - stream.lineStart(); - } - function linePoint(λ, φ) { - var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); - resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); - stream.point(x0, y0); - } - function lineEnd() { - resample.point = point; - stream.lineEnd(); - } - function ringStart() { - lineStart(); - resample.point = ringPoint; - resample.lineEnd = ringEnd; - } - function ringPoint(λ, φ) { - linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; - resample.point = linePoint; - } - function ringEnd() { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); - resample.lineEnd = lineEnd; - lineEnd(); - } - return resample; - } - function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { - var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; - if (d2 > 4 * δ2 && depth--) { - var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; - if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); - stream.point(x2, y2); - resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); - } - } - } - resample.precision = function(_) { - if (!arguments.length) return Math.sqrt(δ2); - maxDepth = (δ2 = _ * _) > 0 && 16; - return resample; - }; - return resample; - } - d3.geo.path = function() { - var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; - function path(object) { - if (object) { - if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); - if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); - d3.geo.stream(object, cacheStream); - } - return contextStream.result(); - } - path.area = function(object) { - d3_geo_pathAreaSum = 0; - d3.geo.stream(object, projectStream(d3_geo_pathArea)); - return d3_geo_pathAreaSum; - }; - path.centroid = function(object) { - d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); - return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; - }; - path.bounds = function(object) { - d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); - d3.geo.stream(object, projectStream(d3_geo_pathBounds)); - return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; - }; - path.projection = function(_) { - if (!arguments.length) return projection; - projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; - return reset(); - }; - path.context = function(_) { - if (!arguments.length) return context; - contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); - if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); - return reset(); - }; - path.pointRadius = function(_) { - if (!arguments.length) return pointRadius; - pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); - return path; - }; - function reset() { - cacheStream = null; - return path; - } - return path.projection(d3.geo.albersUsa()).context(null); - }; - function d3_geo_pathProjectStream(project) { - var resample = d3_geo_resample(function(x, y) { - return project([ x * d3_degrees, y * d3_degrees ]); - }); - return function(stream) { - return d3_geo_projectionRadians(resample(stream)); - }; - } - d3.geo.transform = function(methods) { - return { - stream: function(stream) { - var transform = new d3_geo_transform(stream); - for (var k in methods) transform[k] = methods[k]; - return transform; - } - }; - }; - function d3_geo_transform(stream) { - this.stream = stream; - } - d3_geo_transform.prototype = { - point: function(x, y) { - this.stream.point(x, y); - }, - sphere: function() { - this.stream.sphere(); - }, - lineStart: function() { - this.stream.lineStart(); - }, - lineEnd: function() { - this.stream.lineEnd(); - }, - polygonStart: function() { - this.stream.polygonStart(); - }, - polygonEnd: function() { - this.stream.polygonEnd(); - } - }; - function d3_geo_transformPoint(stream, point) { - return { - point: point, - sphere: function() { - stream.sphere(); - }, - lineStart: function() { - stream.lineStart(); - }, - lineEnd: function() { - stream.lineEnd(); - }, - polygonStart: function() { - stream.polygonStart(); - }, - polygonEnd: function() { - stream.polygonEnd(); - } - }; - } - d3.geo.projection = d3_geo_projection; - d3.geo.projectionMutator = d3_geo_projectionMutator; - function d3_geo_projection(project) { - return d3_geo_projectionMutator(function() { - return project; - })(); - } - function d3_geo_projectionMutator(projectAt) { - var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { - x = project(x, y); - return [ x[0] * k + δx, δy - x[1] * k ]; - }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; - function projection(point) { - point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); - return [ point[0] * k + δx, δy - point[1] * k ]; - } - function invert(point) { - point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); - return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; - } - projection.stream = function(output) { - if (stream) stream.valid = false; - stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); - stream.valid = true; - return stream; - }; - projection.clipAngle = function(_) { - if (!arguments.length) return clipAngle; - preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); - return invalidate(); - }; - projection.clipExtent = function(_) { - if (!arguments.length) return clipExtent; - clipExtent = _; - postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; - return invalidate(); - }; - projection.scale = function(_) { - if (!arguments.length) return k; - k = +_; - return reset(); - }; - projection.translate = function(_) { - if (!arguments.length) return [ x, y ]; - x = +_[0]; - y = +_[1]; - return reset(); - }; - projection.center = function(_) { - if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; - λ = _[0] % 360 * d3_radians; - φ = _[1] % 360 * d3_radians; - return reset(); - }; - projection.rotate = function(_) { - if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; - δλ = _[0] % 360 * d3_radians; - δφ = _[1] % 360 * d3_radians; - δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; - return reset(); - }; - d3.rebind(projection, projectResample, "precision"); - function reset() { - projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); - var center = project(λ, φ); - δx = x - center[0] * k; - δy = y + center[1] * k; - return invalidate(); - } - function invalidate() { - if (stream) stream.valid = false, stream = null; - return projection; - } - return function() { - project = projectAt.apply(this, arguments); - projection.invert = project.invert && invert; - return reset(); - }; - } - function d3_geo_projectionRadians(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - stream.point(x * d3_radians, y * d3_radians); - }); - } - function d3_geo_equirectangular(λ, φ) { - return [ λ, φ ]; - } - (d3.geo.equirectangular = function() { - return d3_geo_projection(d3_geo_equirectangular); - }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; - d3.geo.rotation = function(rotate) { - rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); - function forward(coordinates) { - coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - } - forward.invert = function(coordinates) { - coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - }; - return forward; - }; - function d3_geo_identityRotation(λ, φ) { - return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - } - d3_geo_identityRotation.invert = d3_geo_equirectangular; - function d3_geo_rotation(δλ, δφ, δγ) { - return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; - } - function d3_geo_forwardRotationλ(δλ) { - return function(λ, φ) { - return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - }; - } - function d3_geo_rotationλ(δλ) { - var rotation = d3_geo_forwardRotationλ(δλ); - rotation.invert = d3_geo_forwardRotationλ(-δλ); - return rotation; - } - function d3_geo_rotationφγ(δφ, δγ) { - var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); - function rotation(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; - return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; - } - rotation.invert = function(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; - return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; - }; - return rotation; - } - d3.geo.circle = function() { - var origin = [ 0, 0 ], angle, precision = 6, interpolate; - function circle() { - var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; - interpolate(null, null, 1, { - point: function(x, y) { - ring.push(x = rotate(x, y)); - x[0] *= d3_degrees, x[1] *= d3_degrees; - } - }); - return { - type: "Polygon", - coordinates: [ ring ] - }; - } - circle.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return circle; - }; - circle.angle = function(x) { - if (!arguments.length) return angle; - interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); - return circle; - }; - circle.precision = function(_) { - if (!arguments.length) return precision; - interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); - return circle; - }; - return circle.angle(90); - }; - function d3_geo_circleInterpolate(radius, precision) { - var cr = Math.cos(radius), sr = Math.sin(radius); - return function(from, to, direction, listener) { - var step = direction * precision; - if (from != null) { - from = d3_geo_circleAngle(cr, from); - to = d3_geo_circleAngle(cr, to); - if (direction > 0 ? from < to : from > to) from += direction * τ; - } else { - from = radius + direction * τ; - to = radius - .5 * step; - } - for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { - listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); - } - }; - } - function d3_geo_circleAngle(cr, point) { - var a = d3_geo_cartesian(point); - a[0] -= cr; - d3_geo_cartesianNormalize(a); - var angle = d3_acos(-a[1]); - return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); - } - d3.geo.distance = function(a, b) { - var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; - return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); - }; - d3.geo.graticule = function() { - var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; - function graticule() { - return { - type: "MultiLineString", - coordinates: lines() - }; - } - function lines() { - return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { - return abs(x % DX) > ε; - }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { - return abs(y % DY) > ε; - }).map(y)); - } - graticule.lines = function() { - return lines().map(function(coordinates) { - return { - type: "LineString", - coordinates: coordinates - }; - }); - }; - graticule.outline = function() { - return { - type: "Polygon", - coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] - }; - }; - graticule.extent = function(_) { - if (!arguments.length) return graticule.minorExtent(); - return graticule.majorExtent(_).minorExtent(_); - }; - graticule.majorExtent = function(_) { - if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; - X0 = +_[0][0], X1 = +_[1][0]; - Y0 = +_[0][1], Y1 = +_[1][1]; - if (X0 > X1) _ = X0, X0 = X1, X1 = _; - if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; - return graticule.precision(precision); - }; - graticule.minorExtent = function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - x0 = +_[0][0], x1 = +_[1][0]; - y0 = +_[0][1], y1 = +_[1][1]; - if (x0 > x1) _ = x0, x0 = x1, x1 = _; - if (y0 > y1) _ = y0, y0 = y1, y1 = _; - return graticule.precision(precision); - }; - graticule.step = function(_) { - if (!arguments.length) return graticule.minorStep(); - return graticule.majorStep(_).minorStep(_); - }; - graticule.majorStep = function(_) { - if (!arguments.length) return [ DX, DY ]; - DX = +_[0], DY = +_[1]; - return graticule; - }; - graticule.minorStep = function(_) { - if (!arguments.length) return [ dx, dy ]; - dx = +_[0], dy = +_[1]; - return graticule; - }; - graticule.precision = function(_) { - if (!arguments.length) return precision; - precision = +_; - x = d3_geo_graticuleX(y0, y1, 90); - y = d3_geo_graticuleY(x0, x1, precision); - X = d3_geo_graticuleX(Y0, Y1, 90); - Y = d3_geo_graticuleY(X0, X1, precision); - return graticule; - }; - return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); - }; - function d3_geo_graticuleX(y0, y1, dy) { - var y = d3.range(y0, y1 - ε, dy).concat(y1); - return function(x) { - return y.map(function(y) { - return [ x, y ]; - }); - }; - } - function d3_geo_graticuleY(x0, x1, dx) { - var x = d3.range(x0, x1 - ε, dx).concat(x1); - return function(y) { - return x.map(function(x) { - return [ x, y ]; - }); - }; - } - function d3_source(d) { - return d.source; - } - function d3_target(d) { - return d.target; - } - d3.geo.greatArc = function() { - var source = d3_source, source_, target = d3_target, target_; - function greatArc() { - return { - type: "LineString", - coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] - }; - } - greatArc.distance = function() { - return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); - }; - greatArc.source = function(_) { - if (!arguments.length) return source; - source = _, source_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.target = function(_) { - if (!arguments.length) return target; - target = _, target_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.precision = function() { - return arguments.length ? greatArc : 0; - }; - return greatArc; - }; - d3.geo.interpolate = function(source, target) { - return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); - }; - function d3_geo_interpolate(x0, y0, x1, y1) { - var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); - var interpolate = d ? function(t) { - var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; - return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; - } : function() { - return [ x0 * d3_degrees, y0 * d3_degrees ]; - }; - interpolate.distance = d; - return interpolate; - } - d3.geo.length = function(object) { - d3_geo_lengthSum = 0; - d3.geo.stream(object, d3_geo_length); - return d3_geo_lengthSum; - }; - var d3_geo_lengthSum; - var d3_geo_length = { - sphere: d3_noop, - point: d3_noop, - lineStart: d3_geo_lengthLineStart, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_lengthLineStart() { - var λ0, sinφ0, cosφ0; - d3_geo_length.point = function(λ, φ) { - λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); - d3_geo_length.point = nextPoint; - }; - d3_geo_length.lineEnd = function() { - d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; - }; - function nextPoint(λ, φ) { - var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); - d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; - } - } - function d3_geo_azimuthal(scale, angle) { - function azimuthal(λ, φ) { - var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); - return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; - } - azimuthal.invert = function(x, y) { - var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); - return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; - }; - return azimuthal; - } - var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { - return Math.sqrt(2 / (1 + cosλcosφ)); - }, function(ρ) { - return 2 * Math.asin(ρ / 2); - }); - (d3.geo.azimuthalEqualArea = function() { - return d3_geo_projection(d3_geo_azimuthalEqualArea); - }).raw = d3_geo_azimuthalEqualArea; - var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { - var c = Math.acos(cosλcosφ); - return c && c / Math.sin(c); - }, d3_identity); - (d3.geo.azimuthalEquidistant = function() { - return d3_geo_projection(d3_geo_azimuthalEquidistant); - }).raw = d3_geo_azimuthalEquidistant; - function d3_geo_conicConformal(φ0, φ1) { - var cosφ0 = Math.cos(φ0), t = function(φ) { - return Math.tan(π / 4 + φ / 2); - }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; - if (!n) return d3_geo_mercator; - function forward(λ, φ) { - if (F > 0) { - if (φ < -halfπ + ε) φ = -halfπ + ε; - } else { - if (φ > halfπ - ε) φ = halfπ - ε; - } - var ρ = F / Math.pow(t(φ), n); - return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); - return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; - }; - return forward; - } - (d3.geo.conicConformal = function() { - return d3_geo_conic(d3_geo_conicConformal); - }).raw = d3_geo_conicConformal; - function d3_geo_conicEquidistant(φ0, φ1) { - var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; - if (abs(n) < ε) return d3_geo_equirectangular; - function forward(λ, φ) { - var ρ = G - φ; - return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = G - y; - return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; - }; - return forward; - } - (d3.geo.conicEquidistant = function() { - return d3_geo_conic(d3_geo_conicEquidistant); - }).raw = d3_geo_conicEquidistant; - var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / cosλcosφ; - }, Math.atan); - (d3.geo.gnomonic = function() { - return d3_geo_projection(d3_geo_gnomonic); - }).raw = d3_geo_gnomonic; - function d3_geo_mercator(λ, φ) { - return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; - } - d3_geo_mercator.invert = function(x, y) { - return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; - }; - function d3_geo_mercatorProjection(project) { - var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; - m.scale = function() { - var v = scale.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.translate = function() { - var v = translate.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.clipExtent = function(_) { - var v = clipExtent.apply(m, arguments); - if (v === m) { - if (clipAuto = _ == null) { - var k = π * scale(), t = translate(); - clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); - } - } else if (clipAuto) { - v = null; - } - return v; - }; - return m.clipExtent(null); - } - (d3.geo.mercator = function() { - return d3_geo_mercatorProjection(d3_geo_mercator); - }).raw = d3_geo_mercator; - var d3_geo_orthographic = d3_geo_azimuthal(function() { - return 1; - }, Math.asin); - (d3.geo.orthographic = function() { - return d3_geo_projection(d3_geo_orthographic); - }).raw = d3_geo_orthographic; - var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / (1 + cosλcosφ); - }, function(ρ) { - return 2 * Math.atan(ρ); - }); - (d3.geo.stereographic = function() { - return d3_geo_projection(d3_geo_stereographic); - }).raw = d3_geo_stereographic; - function d3_geo_transverseMercator(λ, φ) { - return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; - } - d3_geo_transverseMercator.invert = function(x, y) { - return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; - }; - (d3.geo.transverseMercator = function() { - var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; - projection.center = function(_) { - return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); - }; - projection.rotate = function(_) { - return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), - [ _[0], _[1], _[2] - 90 ]); - }; - return rotate([ 0, 0, 90 ]); - }).raw = d3_geo_transverseMercator; - d3.geom = {}; - function d3_geom_pointX(d) { - return d[0]; - } - function d3_geom_pointY(d) { - return d[1]; - } - d3.geom.hull = function(vertices) { - var x = d3_geom_pointX, y = d3_geom_pointY; - if (arguments.length) return hull(vertices); - function hull(data) { - if (data.length < 3) return []; - var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; - for (i = 0; i < n; i++) { - points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); - } - points.sort(d3_geom_hullOrder); - for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); - var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); - var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; - for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); - for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); - return polygon; - } - hull.x = function(_) { - return arguments.length ? (x = _, hull) : x; - }; - hull.y = function(_) { - return arguments.length ? (y = _, hull) : y; - }; - return hull; - }; - function d3_geom_hullUpper(points) { - var n = points.length, hull = [ 0, 1 ], hs = 2; - for (var i = 2; i < n; i++) { - while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; - hull[hs++] = i; - } - return hull.slice(0, hs); - } - function d3_geom_hullOrder(a, b) { - return a[0] - b[0] || a[1] - b[1]; - } - d3.geom.polygon = function(coordinates) { - d3_subclass(coordinates, d3_geom_polygonPrototype); - return coordinates; - }; - var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; - d3_geom_polygonPrototype.area = function() { - var i = -1, n = this.length, a, b = this[n - 1], area = 0; - while (++i < n) { - a = b; - b = this[i]; - area += a[1] * b[0] - a[0] * b[1]; - } - return area * .5; - }; - d3_geom_polygonPrototype.centroid = function(k) { - var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; - if (!arguments.length) k = -1 / (6 * this.area()); - while (++i < n) { - a = b; - b = this[i]; - c = a[0] * b[1] - b[0] * a[1]; - x += (a[0] + b[0]) * c; - y += (a[1] + b[1]) * c; - } - return [ x * k, y * k ]; - }; - d3_geom_polygonPrototype.clip = function(subject) { - var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; - while (++i < n) { - input = subject.slice(); - subject.length = 0; - b = this[i]; - c = input[(m = input.length - closed) - 1]; - j = -1; - while (++j < m) { - d = input[j]; - if (d3_geom_polygonInside(d, a, b)) { - if (!d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - subject.push(d); - } else if (d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); - } - c = d; - } - if (closed) subject.push(subject[0]); - a = b; - } - return subject; - }; - function d3_geom_polygonInside(p, a, b) { - return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); - } - function d3_geom_polygonIntersect(c, d, a, b) { - var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); - return [ x1 + ua * x21, y1 + ua * y21 ]; - } - function d3_geom_polygonClosed(coordinates) { - var a = coordinates[0], b = coordinates[coordinates.length - 1]; - return !(a[0] - b[0] || a[1] - b[1]); - } - var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; - function d3_geom_voronoiBeach() { - d3_geom_voronoiRedBlackNode(this); - this.edge = this.site = this.circle = null; - } - function d3_geom_voronoiCreateBeach(site) { - var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); - beach.site = site; - return beach; - } - function d3_geom_voronoiDetachBeach(beach) { - d3_geom_voronoiDetachCircle(beach); - d3_geom_voronoiBeaches.remove(beach); - d3_geom_voronoiBeachPool.push(beach); - d3_geom_voronoiRedBlackNode(beach); - } - function d3_geom_voronoiRemoveBeach(beach) { - var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { - x: x, - y: y - }, previous = beach.P, next = beach.N, disappearing = [ beach ]; - d3_geom_voronoiDetachBeach(beach); - var lArc = previous; - while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { - previous = lArc.P; - disappearing.unshift(lArc); - d3_geom_voronoiDetachBeach(lArc); - lArc = previous; - } - disappearing.unshift(lArc); - d3_geom_voronoiDetachCircle(lArc); - var rArc = next; - while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { - next = rArc.N; - disappearing.push(rArc); - d3_geom_voronoiDetachBeach(rArc); - rArc = next; - } - disappearing.push(rArc); - d3_geom_voronoiDetachCircle(rArc); - var nArcs = disappearing.length, iArc; - for (iArc = 1; iArc < nArcs; ++iArc) { - rArc = disappearing[iArc]; - lArc = disappearing[iArc - 1]; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); - } - lArc = disappearing[0]; - rArc = disappearing[nArcs - 1]; - rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiAddBeach(site) { - var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; - while (node) { - dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; - if (dxl > ε) node = node.L; else { - dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); - if (dxr > ε) { - if (!node.R) { - lArc = node; - break; - } - node = node.R; - } else { - if (dxl > -ε) { - lArc = node.P; - rArc = node; - } else if (dxr > -ε) { - lArc = node; - rArc = node.N; - } else { - lArc = rArc = node; - } - break; - } - } - } - var newArc = d3_geom_voronoiCreateBeach(site); - d3_geom_voronoiBeaches.insert(lArc, newArc); - if (!lArc && !rArc) return; - if (lArc === rArc) { - d3_geom_voronoiDetachCircle(lArc); - rArc = d3_geom_voronoiCreateBeach(lArc.site); - d3_geom_voronoiBeaches.insert(newArc, rArc); - newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - return; - } - if (!rArc) { - newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - return; - } - d3_geom_voronoiDetachCircle(lArc); - d3_geom_voronoiDetachCircle(rArc); - var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { - x: (cy * hb - by * hc) / d + ax, - y: (bx * hc - cx * hb) / d + ay - }; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); - newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); - rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiLeftBreakPoint(arc, directrix) { - var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; - if (!pby2) return rfocx; - var lArc = arc.P; - if (!lArc) return -Infinity; - site = lArc.site; - var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; - if (!plby2) return lfocx; - var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; - if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; - return (rfocx + lfocx) / 2; - } - function d3_geom_voronoiRightBreakPoint(arc, directrix) { - var rArc = arc.N; - if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); - var site = arc.site; - return site.y === directrix ? site.x : Infinity; - } - function d3_geom_voronoiCell(site) { - this.site = site; - this.edges = []; - } - d3_geom_voronoiCell.prototype.prepare = function() { - var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; - while (iHalfEdge--) { - edge = halfEdges[iHalfEdge].edge; - if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); - } - halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); - return halfEdges.length; - }; - function d3_geom_voronoiCloseCells(extent) { - var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; - while (iCell--) { - cell = cells[iCell]; - if (!cell || !cell.prepare()) continue; - halfEdges = cell.edges; - nHalfEdges = halfEdges.length; - iHalfEdge = 0; - while (iHalfEdge < nHalfEdges) { - end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; - start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; - if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { - halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { - x: x0, - y: abs(x2 - x0) < ε ? y2 : y1 - } : abs(y3 - y1) < ε && x1 - x3 > ε ? { - x: abs(y2 - y1) < ε ? x2 : x1, - y: y1 - } : abs(x3 - x1) < ε && y3 - y0 > ε ? { - x: x1, - y: abs(x2 - x1) < ε ? y2 : y0 - } : abs(y3 - y0) < ε && x3 - x0 > ε ? { - x: abs(y2 - y0) < ε ? x2 : x0, - y: y0 - } : null), cell.site, null)); - ++nHalfEdges; - } - } - } - } - function d3_geom_voronoiHalfEdgeOrder(a, b) { - return b.angle - a.angle; - } - function d3_geom_voronoiCircle() { - d3_geom_voronoiRedBlackNode(this); - this.x = this.y = this.arc = this.site = this.cy = null; - } - function d3_geom_voronoiAttachCircle(arc) { - var lArc = arc.P, rArc = arc.N; - if (!lArc || !rArc) return; - var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; - if (lSite === rSite) return; - var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; - var d = 2 * (ax * cy - ay * cx); - if (d >= -ε2) return; - var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; - var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); - circle.arc = arc; - circle.site = cSite; - circle.x = x + bx; - circle.y = cy + Math.sqrt(x * x + y * y); - circle.cy = cy; - arc.circle = circle; - var before = null, node = d3_geom_voronoiCircles._; - while (node) { - if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { - if (node.L) node = node.L; else { - before = node.P; - break; - } - } else { - if (node.R) node = node.R; else { - before = node; - break; - } - } - } - d3_geom_voronoiCircles.insert(before, circle); - if (!before) d3_geom_voronoiFirstCircle = circle; - } - function d3_geom_voronoiDetachCircle(arc) { - var circle = arc.circle; - if (circle) { - if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; - d3_geom_voronoiCircles.remove(circle); - d3_geom_voronoiCirclePool.push(circle); - d3_geom_voronoiRedBlackNode(circle); - arc.circle = null; - } - } - function d3_geom_voronoiClipEdges(extent) { - var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; - while (i--) { - e = edges[i]; - if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { - e.a = e.b = null; - edges.splice(i, 1); - } - } - } - function d3_geom_voronoiConnectEdge(edge, extent) { - var vb = edge.b; - if (vb) return true; - var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; - if (ry === ly) { - if (fx < x0 || fx >= x1) return; - if (lx > rx) { - if (!va) va = { - x: fx, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: fx, - y: y1 - }; - } else { - if (!va) va = { - x: fx, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: fx, - y: y0 - }; - } - } else { - fm = (lx - rx) / (ry - ly); - fb = fy - fm * fx; - if (fm < -1 || fm > 1) { - if (lx > rx) { - if (!va) va = { - x: (y0 - fb) / fm, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: (y1 - fb) / fm, - y: y1 - }; - } else { - if (!va) va = { - x: (y1 - fb) / fm, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: (y0 - fb) / fm, - y: y0 - }; - } - } else { - if (ly < ry) { - if (!va) va = { - x: x0, - y: fm * x0 + fb - }; else if (va.x >= x1) return; - vb = { - x: x1, - y: fm * x1 + fb - }; - } else { - if (!va) va = { - x: x1, - y: fm * x1 + fb - }; else if (va.x < x0) return; - vb = { - x: x0, - y: fm * x0 + fb - }; - } - } - } - edge.a = va; - edge.b = vb; - return true; - } - function d3_geom_voronoiEdge(lSite, rSite) { - this.l = lSite; - this.r = rSite; - this.a = this.b = null; - } - function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, rSite); - d3_geom_voronoiEdges.push(edge); - if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); - if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); - d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); - d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); - return edge; - } - function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, null); - edge.a = va; - edge.b = vb; - d3_geom_voronoiEdges.push(edge); - return edge; - } - function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { - if (!edge.a && !edge.b) { - edge.a = vertex; - edge.l = lSite; - edge.r = rSite; - } else if (edge.l === rSite) { - edge.b = vertex; - } else { - edge.a = vertex; - } - } - function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { - var va = edge.a, vb = edge.b; - this.edge = edge; - this.site = lSite; - this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); - } - d3_geom_voronoiHalfEdge.prototype = { - start: function() { - return this.edge.l === this.site ? this.edge.a : this.edge.b; - }, - end: function() { - return this.edge.l === this.site ? this.edge.b : this.edge.a; - } - }; - function d3_geom_voronoiRedBlackTree() { - this._ = null; - } - function d3_geom_voronoiRedBlackNode(node) { - node.U = node.C = node.L = node.R = node.P = node.N = null; - } - d3_geom_voronoiRedBlackTree.prototype = { - insert: function(after, node) { - var parent, grandpa, uncle; - if (after) { - node.P = after; - node.N = after.N; - if (after.N) after.N.P = node; - after.N = node; - if (after.R) { - after = after.R; - while (after.L) after = after.L; - after.L = node; - } else { - after.R = node; - } - parent = after; - } else if (this._) { - after = d3_geom_voronoiRedBlackFirst(this._); - node.P = null; - node.N = after; - after.P = after.L = node; - parent = after; - } else { - node.P = node.N = null; - this._ = node; - parent = null; - } - node.L = node.R = null; - node.U = parent; - node.C = true; - after = node; - while (parent && parent.C) { - grandpa = parent.U; - if (parent === grandpa.L) { - uncle = grandpa.R; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.R) { - d3_geom_voronoiRedBlackRotateLeft(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateRight(this, grandpa); - } - } else { - uncle = grandpa.L; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.L) { - d3_geom_voronoiRedBlackRotateRight(this, parent); - after = parent; - parent = after.U; - } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, grandpa); - } - } - parent = after.U; - } - this._.C = false; - }, - remove: function(node) { - if (node.N) node.N.P = node.P; - if (node.P) node.P.N = node.N; - node.N = node.P = null; - var parent = node.U, sibling, left = node.L, right = node.R, next, red; - if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); - if (parent) { - if (parent.L === node) parent.L = next; else parent.R = next; - } else { - this._ = next; - } - if (left && right) { - red = next.C; - next.C = node.C; - next.L = left; - left.U = next; - if (next !== right) { - parent = next.U; - next.U = node.U; - node = next.R; - parent.L = node; - next.R = right; - right.U = next; - } else { - next.U = parent; - parent = next; - node = next.R; - } - } else { - red = node.C; - node = next; - } - if (node) node.U = parent; - if (red) return; - if (node && node.C) { - node.C = false; - return; - } - do { - if (node === this._) break; - if (node === parent.L) { - sibling = parent.R; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - sibling = parent.R; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.R || !sibling.R.C) { - sibling.L.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateRight(this, sibling); - sibling = parent.R; - } - sibling.C = parent.C; - parent.C = sibling.R.C = false; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - node = this._; - break; - } - } else { - sibling = parent.L; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateRight(this, parent); - sibling = parent.L; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.L || !sibling.L.C) { - sibling.R.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, sibling); - sibling = parent.L; - } - sibling.C = parent.C; - parent.C = sibling.L.C = false; - d3_geom_voronoiRedBlackRotateRight(this, parent); - node = this._; - break; - } - } - sibling.C = true; - node = parent; - parent = parent.U; - } while (!node.C); - if (node) node.C = false; - } - }; - function d3_geom_voronoiRedBlackRotateLeft(tree, node) { - var p = node, q = node.R, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.R = q.L; - if (p.R) p.R.U = p; - q.L = p; - } - function d3_geom_voronoiRedBlackRotateRight(tree, node) { - var p = node, q = node.L, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; - } - q.U = parent; - p.U = q; - p.L = q.R; - if (p.L) p.L.U = p; - q.R = p; - } - function d3_geom_voronoiRedBlackFirst(node) { - while (node.L) node = node.L; - return node; - } - function d3_geom_voronoi(sites, bbox) { - var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; - d3_geom_voronoiEdges = []; - d3_geom_voronoiCells = new Array(sites.length); - d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); - d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); - while (true) { - circle = d3_geom_voronoiFirstCircle; - if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { - if (site.x !== x0 || site.y !== y0) { - d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); - d3_geom_voronoiAddBeach(site); - x0 = site.x, y0 = site.y; - } - site = sites.pop(); - } else if (circle) { - d3_geom_voronoiRemoveBeach(circle.arc); - } else { - break; - } - } - if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); - var diagram = { - cells: d3_geom_voronoiCells, - edges: d3_geom_voronoiEdges - }; - d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; - return diagram; - } - function d3_geom_voronoiVertexOrder(a, b) { - return b.y - a.y || b.x - a.x; - } - d3.geom.voronoi = function(points) { - var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; - if (points) return voronoi(points); - function voronoi(data) { - var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; - d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { - var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { - var s = e.start(); - return [ s.x, s.y ]; - }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; - polygon.point = data[i]; - }); - return polygons; - } - function sites(data) { - return data.map(function(d, i) { - return { - x: Math.round(fx(d, i) / ε) * ε, - y: Math.round(fy(d, i) / ε) * ε, - i: i - }; - }); - } - voronoi.links = function(data) { - return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { - return edge.l && edge.r; - }).map(function(edge) { - return { - source: data[edge.l.i], - target: data[edge.r.i] - }; - }); - }; - voronoi.triangles = function(data) { - var triangles = []; - d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { - var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; - while (++j < m) { - e0 = e1; - s0 = s1; - e1 = edges[j].edge; - s1 = e1.l === site ? e1.r : e1.l; - if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { - triangles.push([ data[i], data[s0.i], data[s1.i] ]); - } - } - }); - return triangles; - }; - voronoi.x = function(_) { - return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; - }; - voronoi.y = function(_) { - return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; - }; - voronoi.clipExtent = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; - clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; - return voronoi; - }; - voronoi.size = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; - return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); - }; - return voronoi; - }; - var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; - function d3_geom_voronoiTriangleArea(a, b, c) { - return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); - } - d3.geom.delaunay = function(vertices) { - return d3.geom.voronoi().triangles(vertices); - }; - d3.geom.quadtree = function(points, x1, y1, x2, y2) { - var x = d3_geom_pointX, y = d3_geom_pointY, compat; - if (compat = arguments.length) { - x = d3_geom_quadtreeCompatX; - y = d3_geom_quadtreeCompatY; - if (compat === 3) { - y2 = y1; - x2 = x1; - y1 = x1 = 0; - } - return quadtree(points); - } - function quadtree(data) { - var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; - if (x1 != null) { - x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; - } else { - x2_ = y2_ = -(x1_ = y1_ = Infinity); - xs = [], ys = []; - n = data.length; - if (compat) for (i = 0; i < n; ++i) { - d = data[i]; - if (d.x < x1_) x1_ = d.x; - if (d.y < y1_) y1_ = d.y; - if (d.x > x2_) x2_ = d.x; - if (d.y > y2_) y2_ = d.y; - xs.push(d.x); - ys.push(d.y); - } else for (i = 0; i < n; ++i) { - var x_ = +fx(d = data[i], i), y_ = +fy(d, i); - if (x_ < x1_) x1_ = x_; - if (y_ < y1_) y1_ = y_; - if (x_ > x2_) x2_ = x_; - if (y_ > y2_) y2_ = y_; - xs.push(x_); - ys.push(y_); - } - } - var dx = x2_ - x1_, dy = y2_ - y1_; - if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; - function insert(n, d, x, y, x1, y1, x2, y2) { - if (isNaN(x) || isNaN(y)) return; - if (n.leaf) { - var nx = n.x, ny = n.y; - if (nx != null) { - if (abs(nx - x) + abs(ny - y) < .01) { - insertChild(n, d, x, y, x1, y1, x2, y2); - } else { - var nPoint = n.point; - n.x = n.y = n.point = null; - insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } else { - n.x = x, n.y = y, n.point = d; - } - } else { - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } - function insertChild(n, d, x, y, x1, y1, x2, y2) { - var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; - n.leaf = false; - n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); - if (right) x1 = xm; else x2 = xm; - if (below) y1 = ym; else y2 = ym; - insert(n, d, x, y, x1, y1, x2, y2); - } - var root = d3_geom_quadtreeNode(); - root.add = function(d) { - insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); - }; - root.visit = function(f) { - d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); - }; - root.find = function(point) { - return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); - }; - i = -1; - if (x1 == null) { - while (++i < n) { - insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); - } - --i; - } else data.forEach(root.add); - xs = ys = data = d = null; - return root; - } - quadtree.x = function(_) { - return arguments.length ? (x = _, quadtree) : x; - }; - quadtree.y = function(_) { - return arguments.length ? (y = _, quadtree) : y; - }; - quadtree.extent = function(_) { - if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], - y2 = +_[1][1]; - return quadtree; - }; - quadtree.size = function(_) { - if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; - return quadtree; - }; - return quadtree; - }; - function d3_geom_quadtreeCompatX(d) { - return d.x; - } - function d3_geom_quadtreeCompatY(d) { - return d.y; - } - function d3_geom_quadtreeNode() { - return { - leaf: true, - nodes: [], - point: null, - x: null, - y: null - }; - } - function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { - if (!f(node, x1, y1, x2, y2)) { - var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; - if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); - if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); - if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); - if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); - } - } - function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { - var minDistance2 = Infinity, closestPoint; - (function find(node, x1, y1, x2, y2) { - if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; - if (point = node.point) { - var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy; - if (distance2 < minDistance2) { - var distance = Math.sqrt(minDistance2 = distance2); - x0 = x - distance, y0 = y - distance; - x3 = x + distance, y3 = y + distance; - closestPoint = point; - } - } - var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; - for (var i = below << 1 | right, j = i + 4; i < j; ++i) { - if (node = children[i & 3]) switch (i & 3) { - case 0: - find(node, x1, y1, xm, ym); - break; - - case 1: - find(node, xm, y1, x2, ym); - break; - - case 2: - find(node, x1, ym, xm, y2); - break; - - case 3: - find(node, xm, ym, x2, y2); - break; - } - } - })(root, x0, y0, x3, y3); - return closestPoint; - } - d3.interpolateRgb = d3_interpolateRgb; - function d3_interpolateRgb(a, b) { - a = d3.rgb(a); - b = d3.rgb(b); - var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; - return function(t) { - return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); - }; - } - d3.interpolateObject = d3_interpolateObject; - function d3_interpolateObject(a, b) { - var i = {}, c = {}, k; - for (k in a) { - if (k in b) { - i[k] = d3_interpolate(a[k], b[k]); - } else { - c[k] = a[k]; - } - } - for (k in b) { - if (!(k in a)) { - c[k] = b[k]; - } - } - return function(t) { - for (k in i) c[k] = i[k](t); - return c; - }; - } - d3.interpolateNumber = d3_interpolateNumber; - function d3_interpolateNumber(a, b) { - a = +a, b = +b; - return function(t) { - return a * (1 - t) + b * t; - }; - } - d3.interpolateString = d3_interpolateString; - function d3_interpolateString(a, b) { - var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; - a = a + "", b = b + ""; - while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { - if ((bs = bm.index) > bi) { - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { - if (s[i]) s[i] += bm; else s[++i] = bm; - } else { - s[++i] = null; - q.push({ - i: i, - x: d3_interpolateNumber(am, bm) - }); - } - bi = d3_interpolate_numberB.lastIndex; - } - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; else s[++i] = bs; - } - return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { - return b(t) + ""; - }) : function() { - return b; - } : (b = q.length, function(t) { - for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }); - } - var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); - d3.interpolate = d3_interpolate; - function d3_interpolate(a, b) { - var i = d3.interpolators.length, f; - while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; - return f; - } - d3.interpolators = [ function(a, b) { - var t = typeof b; - return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); - } ]; - d3.interpolateArray = d3_interpolateArray; - function d3_interpolateArray(a, b) { - var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; - for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); - for (;i < na; ++i) c[i] = a[i]; - for (;i < nb; ++i) c[i] = b[i]; - return function(t) { - for (i = 0; i < n0; ++i) c[i] = x[i](t); - return c; - }; - } - var d3_ease_default = function() { - return d3_identity; - }; - var d3_ease = d3.map({ - linear: d3_ease_default, - poly: d3_ease_poly, - quad: function() { - return d3_ease_quad; - }, - cubic: function() { - return d3_ease_cubic; - }, - sin: function() { - return d3_ease_sin; - }, - exp: function() { - return d3_ease_exp; - }, - circle: function() { - return d3_ease_circle; - }, - elastic: d3_ease_elastic, - back: d3_ease_back, - bounce: function() { - return d3_ease_bounce; - } - }); - var d3_ease_mode = d3.map({ - "in": d3_identity, - out: d3_ease_reverse, - "in-out": d3_ease_reflect, - "out-in": function(f) { - return d3_ease_reflect(d3_ease_reverse(f)); - } - }); - d3.ease = function(name) { - var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; - t = d3_ease.get(t) || d3_ease_default; - m = d3_ease_mode.get(m) || d3_identity; - return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); - }; - function d3_ease_clamp(f) { - return function(t) { - return t <= 0 ? 0 : t >= 1 ? 1 : f(t); - }; - } - function d3_ease_reverse(f) { - return function(t) { - return 1 - f(1 - t); - }; - } - function d3_ease_reflect(f) { - return function(t) { - return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); - }; - } - function d3_ease_quad(t) { - return t * t; - } - function d3_ease_cubic(t) { - return t * t * t; - } - function d3_ease_cubicInOut(t) { - if (t <= 0) return 0; - if (t >= 1) return 1; - var t2 = t * t, t3 = t2 * t; - return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); - } - function d3_ease_poly(e) { - return function(t) { - return Math.pow(t, e); - }; - } - function d3_ease_sin(t) { - return 1 - Math.cos(t * halfπ); - } - function d3_ease_exp(t) { - return Math.pow(2, 10 * (t - 1)); - } - function d3_ease_circle(t) { - return 1 - Math.sqrt(1 - t * t); - } - function d3_ease_elastic(a, p) { - var s; - if (arguments.length < 2) p = .45; - if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; - return function(t) { - return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); - }; - } - function d3_ease_back(s) { - if (!s) s = 1.70158; - return function(t) { - return t * t * ((s + 1) * t - s); - }; - } - function d3_ease_bounce(t) { - return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; - } - d3.interpolateHcl = d3_interpolateHcl; - function d3_interpolateHcl(a, b) { - a = d3.hcl(a); - b = d3.hcl(b); - var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; - if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; - }; - } - d3.interpolateHsl = d3_interpolateHsl; - function d3_interpolateHsl(a, b) { - a = d3.hsl(a); - b = d3.hsl(b); - var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; - if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; - }; - } - d3.interpolateLab = d3_interpolateLab; - function d3_interpolateLab(a, b) { - a = d3.lab(a); - b = d3.lab(b); - var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; - return function(t) { - return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; - }; - } - d3.interpolateRound = d3_interpolateRound; - function d3_interpolateRound(a, b) { - b -= a; - return function(t) { - return Math.round(a + b * t); - }; - } - d3.transform = function(string) { - var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); - return (d3.transform = function(string) { - if (string != null) { - g.setAttribute("transform", string); - var t = g.transform.baseVal.consolidate(); - } - return new d3_transform(t ? t.matrix : d3_transformIdentity); - })(string); - }; - function d3_transform(m) { - var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; - if (r0[0] * r1[1] < r1[0] * r0[1]) { - r0[0] *= -1; - r0[1] *= -1; - kx *= -1; - kz *= -1; - } - this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; - this.translate = [ m.e, m.f ]; - this.scale = [ kx, ky ]; - this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; - } - d3_transform.prototype.toString = function() { - return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; - }; - function d3_transformDot(a, b) { - return a[0] * b[0] + a[1] * b[1]; - } - function d3_transformNormalize(a) { - var k = Math.sqrt(d3_transformDot(a, a)); - if (k) { - a[0] /= k; - a[1] /= k; - } - return k; - } - function d3_transformCombine(a, b, k) { - a[0] += k * b[0]; - a[1] += k * b[1]; - return a; - } - var d3_transformIdentity = { - a: 1, - b: 0, - c: 0, - d: 1, - e: 0, - f: 0 - }; - d3.interpolateTransform = d3_interpolateTransform; - function d3_interpolateTransformPop(s) { - return s.length ? s.pop() + "," : ""; - } - function d3_interpolateTranslate(ta, tb, s, q) { - if (ta[0] !== tb[0] || ta[1] !== tb[1]) { - var i = s.push("translate(", null, ",", null, ")"); - q.push({ - i: i - 4, - x: d3_interpolateNumber(ta[0], tb[0]) - }, { - i: i - 2, - x: d3_interpolateNumber(ta[1], tb[1]) - }); - } else if (tb[0] || tb[1]) { - s.push("translate(" + tb + ")"); - } - } - function d3_interpolateRotate(ra, rb, s, q) { - if (ra !== rb) { - if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; - q.push({ - i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2, - x: d3_interpolateNumber(ra, rb) - }); - } else if (rb) { - s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")"); - } - } - function d3_interpolateSkew(wa, wb, s, q) { - if (wa !== wb) { - q.push({ - i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2, - x: d3_interpolateNumber(wa, wb) - }); - } else if (wb) { - s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")"); - } - } - function d3_interpolateScale(ka, kb, s, q) { - if (ka[0] !== kb[0] || ka[1] !== kb[1]) { - var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")"); - q.push({ - i: i - 4, - x: d3_interpolateNumber(ka[0], kb[0]) - }, { - i: i - 2, - x: d3_interpolateNumber(ka[1], kb[1]) - }); - } else if (kb[0] !== 1 || kb[1] !== 1) { - s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")"); - } - } - function d3_interpolateTransform(a, b) { - var s = [], q = []; - a = d3.transform(a), b = d3.transform(b); - d3_interpolateTranslate(a.translate, b.translate, s, q); - d3_interpolateRotate(a.rotate, b.rotate, s, q); - d3_interpolateSkew(a.skew, b.skew, s, q); - d3_interpolateScale(a.scale, b.scale, s, q); - a = b = null; - return function(t) { - var i = -1, n = q.length, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }; - } - function d3_uninterpolateNumber(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return (x - a) / b; - }; - } - function d3_uninterpolateClamp(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return Math.max(0, Math.min(1, (x - a) / b)); - }; - } - d3.layout = {}; - d3.layout.bundle = function() { - return function(links) { - var paths = [], i = -1, n = links.length; - while (++i < n) paths.push(d3_layout_bundlePath(links[i])); - return paths; - }; - }; - function d3_layout_bundlePath(link) { - var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; - while (start !== lca) { - start = start.parent; - points.push(start); - } - var k = points.length; - while (end !== lca) { - points.splice(k, 0, end); - end = end.parent; - } - return points; - } - function d3_layout_bundleAncestors(node) { - var ancestors = [], parent = node.parent; - while (parent != null) { - ancestors.push(node); - node = parent; - parent = parent.parent; - } - ancestors.push(node); - return ancestors; - } - function d3_layout_bundleLeastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; - while (aNode === bNode) { - sharedNode = aNode; - aNode = aNodes.pop(); - bNode = bNodes.pop(); - } - return sharedNode; - } - d3.layout.chord = function() { - var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; - function relayout() { - var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; - chords = []; - groups = []; - k = 0, i = -1; - while (++i < n) { - x = 0, j = -1; - while (++j < n) { - x += matrix[i][j]; - } - groupSums.push(x); - subgroupIndex.push(d3.range(n)); - k += x; - } - if (sortGroups) { - groupIndex.sort(function(a, b) { - return sortGroups(groupSums[a], groupSums[b]); - }); - } - if (sortSubgroups) { - subgroupIndex.forEach(function(d, i) { - d.sort(function(a, b) { - return sortSubgroups(matrix[i][a], matrix[i][b]); - }); - }); - } - k = (τ - padding * n) / k; - x = 0, i = -1; - while (++i < n) { - x0 = x, j = -1; - while (++j < n) { - var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; - subgroups[di + "-" + dj] = { - index: di, - subindex: dj, - startAngle: a0, - endAngle: a1, - value: v - }; - } - groups[di] = { - index: di, - startAngle: x0, - endAngle: x, - value: groupSums[di] - }; - x += padding; - } - i = -1; - while (++i < n) { - j = i - 1; - while (++j < n) { - var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; - if (source.value || target.value) { - chords.push(source.value < target.value ? { - source: target, - target: source - } : { - source: source, - target: target - }); - } - } - } - if (sortChords) resort(); - } - function resort() { - chords.sort(function(a, b) { - return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); - }); - } - chord.matrix = function(x) { - if (!arguments.length) return matrix; - n = (matrix = x) && matrix.length; - chords = groups = null; - return chord; - }; - chord.padding = function(x) { - if (!arguments.length) return padding; - padding = x; - chords = groups = null; - return chord; - }; - chord.sortGroups = function(x) { - if (!arguments.length) return sortGroups; - sortGroups = x; - chords = groups = null; - return chord; - }; - chord.sortSubgroups = function(x) { - if (!arguments.length) return sortSubgroups; - sortSubgroups = x; - chords = null; - return chord; - }; - chord.sortChords = function(x) { - if (!arguments.length) return sortChords; - sortChords = x; - if (chords) resort(); - return chord; - }; - chord.chords = function() { - if (!chords) relayout(); - return chords; - }; - chord.groups = function() { - if (!groups) relayout(); - return groups; - }; - return chord; - }; - d3.layout.force = function() { - var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; - function repulse(node) { - return function(quad, x1, _, x2) { - if (quad.point !== node) { - var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; - if (dw * dw / theta2 < dn) { - if (dn < chargeDistance2) { - var k = quad.charge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - return true; - } - if (quad.point && dn && dn < chargeDistance2) { - var k = quad.pointCharge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - } - return !quad.charge; - }; - } - force.tick = function() { - if ((alpha *= .99) < .005) { - timer = null; - event.end({ - type: "end", - alpha: alpha = 0 - }); - return true; - } - var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; - for (i = 0; i < m; ++i) { - o = links[i]; - s = o.source; - t = o.target; - x = t.x - s.x; - y = t.y - s.y; - if (l = x * x + y * y) { - l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; - x *= l; - y *= l; - t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5); - t.y -= y * k; - s.x += x * (k = 1 - k); - s.y += y * k; - } - } - if (k = alpha * gravity) { - x = size[0] / 2; - y = size[1] / 2; - i = -1; - if (k) while (++i < n) { - o = nodes[i]; - o.x += (x - o.x) * k; - o.y += (y - o.y) * k; - } - } - if (charge) { - d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); - i = -1; - while (++i < n) { - if (!(o = nodes[i]).fixed) { - q.visit(repulse(o)); - } - } - } - i = -1; - while (++i < n) { - o = nodes[i]; - if (o.fixed) { - o.x = o.px; - o.y = o.py; - } else { - o.x -= (o.px - (o.px = o.x)) * friction; - o.y -= (o.py - (o.py = o.y)) * friction; - } - } - event.tick({ - type: "tick", - alpha: alpha - }); - }; - force.nodes = function(x) { - if (!arguments.length) return nodes; - nodes = x; - return force; - }; - force.links = function(x) { - if (!arguments.length) return links; - links = x; - return force; - }; - force.size = function(x) { - if (!arguments.length) return size; - size = x; - return force; - }; - force.linkDistance = function(x) { - if (!arguments.length) return linkDistance; - linkDistance = typeof x === "function" ? x : +x; - return force; - }; - force.distance = force.linkDistance; - force.linkStrength = function(x) { - if (!arguments.length) return linkStrength; - linkStrength = typeof x === "function" ? x : +x; - return force; - }; - force.friction = function(x) { - if (!arguments.length) return friction; - friction = +x; - return force; - }; - force.charge = function(x) { - if (!arguments.length) return charge; - charge = typeof x === "function" ? x : +x; - return force; - }; - force.chargeDistance = function(x) { - if (!arguments.length) return Math.sqrt(chargeDistance2); - chargeDistance2 = x * x; - return force; - }; - force.gravity = function(x) { - if (!arguments.length) return gravity; - gravity = +x; - return force; - }; - force.theta = function(x) { - if (!arguments.length) return Math.sqrt(theta2); - theta2 = x * x; - return force; - }; - force.alpha = function(x) { - if (!arguments.length) return alpha; - x = +x; - if (alpha) { - if (x > 0) { - alpha = x; - } else { - timer.c = null, timer.t = NaN, timer = null; - event.end({ - type: "end", - alpha: alpha = 0 - }); - } - } else if (x > 0) { - event.start({ - type: "start", - alpha: alpha = x - }); - timer = d3_timer(force.tick); - } - return force; - }; - force.start = function() { - var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; - for (i = 0; i < n; ++i) { - (o = nodes[i]).index = i; - o.weight = 0; - } - for (i = 0; i < m; ++i) { - o = links[i]; - if (typeof o.source == "number") o.source = nodes[o.source]; - if (typeof o.target == "number") o.target = nodes[o.target]; - ++o.source.weight; - ++o.target.weight; - } - for (i = 0; i < n; ++i) { - o = nodes[i]; - if (isNaN(o.x)) o.x = position("x", w); - if (isNaN(o.y)) o.y = position("y", h); - if (isNaN(o.px)) o.px = o.x; - if (isNaN(o.py)) o.py = o.y; - } - distances = []; - if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; - strengths = []; - if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; - charges = []; - if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; - function position(dimension, size) { - if (!neighbors) { - neighbors = new Array(n); - for (j = 0; j < n; ++j) { - neighbors[j] = []; - } - for (j = 0; j < m; ++j) { - var o = links[j]; - neighbors[o.source.index].push(o.target); - neighbors[o.target.index].push(o.source); - } - } - var candidates = neighbors[i], j = -1, l = candidates.length, x; - while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x; - return Math.random() * size; - } - return force.resume(); - }; - force.resume = function() { - return force.alpha(.1); - }; - force.stop = function() { - return force.alpha(0); - }; - force.drag = function() { - if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); - if (!arguments.length) return drag; - this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); - }; - function dragmove(d) { - d.px = d3.event.x, d.py = d3.event.y; - force.resume(); - } - return d3.rebind(force, event, "on"); - }; - function d3_layout_forceDragstart(d) { - d.fixed |= 2; - } - function d3_layout_forceDragend(d) { - d.fixed &= ~6; - } - function d3_layout_forceMouseover(d) { - d.fixed |= 4; - d.px = d.x, d.py = d.y; - } - function d3_layout_forceMouseout(d) { - d.fixed &= ~4; - } - function d3_layout_forceAccumulate(quad, alpha, charges) { - var cx = 0, cy = 0; - quad.charge = 0; - if (!quad.leaf) { - var nodes = quad.nodes, n = nodes.length, i = -1, c; - while (++i < n) { - c = nodes[i]; - if (c == null) continue; - d3_layout_forceAccumulate(c, alpha, charges); - quad.charge += c.charge; - cx += c.charge * c.cx; - cy += c.charge * c.cy; - } - } - if (quad.point) { - if (!quad.leaf) { - quad.point.x += Math.random() - .5; - quad.point.y += Math.random() - .5; - } - var k = alpha * charges[quad.point.index]; - quad.charge += quad.pointCharge = k; - cx += k * quad.point.x; - cy += k * quad.point.y; - } - quad.cx = cx / quad.charge; - quad.cy = cy / quad.charge; - } - var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; - d3.layout.hierarchy = function() { - var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; - function hierarchy(root) { - var stack = [ root ], nodes = [], node; - root.depth = 0; - while ((node = stack.pop()) != null) { - nodes.push(node); - if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { - var n, childs, child; - while (--n >= 0) { - stack.push(child = childs[n]); - child.parent = node; - child.depth = node.depth + 1; - } - if (value) node.value = 0; - node.children = childs; - } else { - if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; - delete node.children; - } - } - d3_layout_hierarchyVisitAfter(root, function(node) { - var childs, parent; - if (sort && (childs = node.children)) childs.sort(sort); - if (value && (parent = node.parent)) parent.value += node.value; - }); - return nodes; - } - hierarchy.sort = function(x) { - if (!arguments.length) return sort; - sort = x; - return hierarchy; - }; - hierarchy.children = function(x) { - if (!arguments.length) return children; - children = x; - return hierarchy; - }; - hierarchy.value = function(x) { - if (!arguments.length) return value; - value = x; - return hierarchy; - }; - hierarchy.revalue = function(root) { - if (value) { - d3_layout_hierarchyVisitBefore(root, function(node) { - if (node.children) node.value = 0; - }); - d3_layout_hierarchyVisitAfter(root, function(node) { - var parent; - if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; - if (parent = node.parent) parent.value += node.value; - }); - } - return root; - }; - return hierarchy; - }; - function d3_layout_hierarchyRebind(object, hierarchy) { - d3.rebind(object, hierarchy, "sort", "children", "value"); - object.nodes = object; - object.links = d3_layout_hierarchyLinks; - return object; - } - function d3_layout_hierarchyVisitBefore(node, callback) { - var nodes = [ node ]; - while ((node = nodes.pop()) != null) { - callback(node); - if ((children = node.children) && (n = children.length)) { - var n, children; - while (--n >= 0) nodes.push(children[n]); - } - } - } - function d3_layout_hierarchyVisitAfter(node, callback) { - var nodes = [ node ], nodes2 = []; - while ((node = nodes.pop()) != null) { - nodes2.push(node); - if ((children = node.children) && (n = children.length)) { - var i = -1, n, children; - while (++i < n) nodes.push(children[i]); - } - } - while ((node = nodes2.pop()) != null) { - callback(node); - } - } - function d3_layout_hierarchyChildren(d) { - return d.children; - } - function d3_layout_hierarchyValue(d) { - return d.value; - } - function d3_layout_hierarchySort(a, b) { - return b.value - a.value; - } - function d3_layout_hierarchyLinks(nodes) { - return d3.merge(nodes.map(function(parent) { - return (parent.children || []).map(function(child) { - return { - source: parent, - target: child - }; - }); - })); - } - d3.layout.partition = function() { - var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; - function position(node, x, dx, dy) { - var children = node.children; - node.x = x; - node.y = node.depth * dy; - node.dx = dx; - node.dy = dy; - if (children && (n = children.length)) { - var i = -1, n, c, d; - dx = node.value ? dx / node.value : 0; - while (++i < n) { - position(c = children[i], x, d = c.value * dx, dy); - x += d; - } - } - } - function depth(node) { - var children = node.children, d = 0; - if (children && (n = children.length)) { - var i = -1, n; - while (++i < n) d = Math.max(d, depth(children[i])); - } - return 1 + d; - } - function partition(d, i) { - var nodes = hierarchy.call(this, d, i); - position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); - return nodes; - } - partition.size = function(x) { - if (!arguments.length) return size; - size = x; - return partition; - }; - return d3_layout_hierarchyRebind(partition, hierarchy); - }; - d3.layout.pie = function() { - var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; - function pie(data) { - var n = data.length, values = data.map(function(d, i) { - return +value.call(pie, d, i); - }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v; - if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { - return values[j] - values[i]; - } : function(i, j) { - return sort(data[i], data[j]); - }); - index.forEach(function(i) { - arcs[i] = { - data: data[i], - value: v = values[i], - startAngle: a, - endAngle: a += v * k + pa, - padAngle: p - }; - }); - return arcs; - } - pie.value = function(_) { - if (!arguments.length) return value; - value = _; - return pie; - }; - pie.sort = function(_) { - if (!arguments.length) return sort; - sort = _; - return pie; - }; - pie.startAngle = function(_) { - if (!arguments.length) return startAngle; - startAngle = _; - return pie; - }; - pie.endAngle = function(_) { - if (!arguments.length) return endAngle; - endAngle = _; - return pie; - }; - pie.padAngle = function(_) { - if (!arguments.length) return padAngle; - padAngle = _; - return pie; - }; - return pie; - }; - var d3_layout_pieSortByValue = {}; - d3.layout.stack = function() { - var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; - function stack(data, index) { - if (!(n = data.length)) return data; - var series = data.map(function(d, i) { - return values.call(stack, d, i); - }); - var points = series.map(function(d) { - return d.map(function(v, i) { - return [ x.call(stack, v, i), y.call(stack, v, i) ]; - }); - }); - var orders = order.call(stack, points, index); - series = d3.permute(series, orders); - points = d3.permute(points, orders); - var offsets = offset.call(stack, points, index); - var m = series[0].length, n, i, j, o; - for (j = 0; j < m; ++j) { - out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); - for (i = 1; i < n; ++i) { - out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); - } - } - return data; - } - stack.values = function(x) { - if (!arguments.length) return values; - values = x; - return stack; - }; - stack.order = function(x) { - if (!arguments.length) return order; - order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; - return stack; - }; - stack.offset = function(x) { - if (!arguments.length) return offset; - offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; - return stack; - }; - stack.x = function(z) { - if (!arguments.length) return x; - x = z; - return stack; - }; - stack.y = function(z) { - if (!arguments.length) return y; - y = z; - return stack; - }; - stack.out = function(z) { - if (!arguments.length) return out; - out = z; - return stack; - }; - return stack; - }; - function d3_layout_stackX(d) { - return d.x; - } - function d3_layout_stackY(d) { - return d.y; - } - function d3_layout_stackOut(d, y0, y) { - d.y0 = y0; - d.y = y; - } - var d3_layout_stackOrders = d3.map({ - "inside-out": function(data) { - var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { - return max[a] - max[b]; - }), top = 0, bottom = 0, tops = [], bottoms = []; - for (i = 0; i < n; ++i) { - j = index[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); - } - } - return bottoms.reverse().concat(tops); - }, - reverse: function(data) { - return d3.range(data.length).reverse(); - }, - "default": d3_layout_stackOrderDefault - }); - var d3_layout_stackOffsets = d3.map({ - silhouette: function(data) { - var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o > max) max = o; - sums.push(o); - } - for (j = 0; j < m; ++j) { - y0[j] = (max - sums[j]) / 2; - } - return y0; - }, - wiggle: function(data) { - var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; - y0[0] = o = o0 = 0; - for (j = 1; j < m; ++j) { - for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; - for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { - for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { - s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; - } - s2 += s3 * data[i][j][1]; - } - y0[j] = o -= s1 ? s2 / s1 * dx : 0; - if (o < o0) o0 = o; - } - for (j = 0; j < m; ++j) y0[j] -= o0; - return y0; - }, - expand: function(data) { - var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; - } - for (j = 0; j < m; ++j) y0[j] = 0; - return y0; - }, - zero: d3_layout_stackOffsetZero - }); - function d3_layout_stackOrderDefault(data) { - return d3.range(data.length); - } - function d3_layout_stackOffsetZero(data) { - var j = -1, m = data[0].length, y0 = []; - while (++j < m) y0[j] = 0; - return y0; - } - function d3_layout_stackMaxIndex(array) { - var i = 1, j = 0, v = array[0][1], k, n = array.length; - for (;i < n; ++i) { - if ((k = array[i][1]) > v) { - j = i; - v = k; - } - } - return j; - } - function d3_layout_stackReduceSum(d) { - return d.reduce(d3_layout_stackSum, 0); - } - function d3_layout_stackSum(p, d) { - return p + d[1]; - } - d3.layout.histogram = function() { - var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; - function histogram(data, i) { - var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; - while (++i < m) { - bin = bins[i] = []; - bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); - bin.y = 0; - } - if (m > 0) { - i = -1; - while (++i < n) { - x = values[i]; - if (x >= range[0] && x <= range[1]) { - bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; - bin.y += k; - bin.push(data[i]); - } - } - } - return bins; - } - histogram.value = function(x) { - if (!arguments.length) return valuer; - valuer = x; - return histogram; - }; - histogram.range = function(x) { - if (!arguments.length) return ranger; - ranger = d3_functor(x); - return histogram; - }; - histogram.bins = function(x) { - if (!arguments.length) return binner; - binner = typeof x === "number" ? function(range) { - return d3_layout_histogramBinFixed(range, x); - } : d3_functor(x); - return histogram; - }; - histogram.frequency = function(x) { - if (!arguments.length) return frequency; - frequency = !!x; - return histogram; - }; - return histogram; - }; - function d3_layout_histogramBinSturges(range, values) { - return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); - } - function d3_layout_histogramBinFixed(range, n) { - var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; - while (++x <= n) f[x] = m * x + b; - return f; - } - function d3_layout_histogramRange(values) { - return [ d3.min(values), d3.max(values) ]; - } - d3.layout.pack = function() { - var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; - function pack(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { - return radius; - }; - root.x = root.y = 0; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r = +r(d.value); - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - if (padding) { - var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r += dr; - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r -= dr; - }); - } - d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); - return nodes; - } - pack.size = function(_) { - if (!arguments.length) return size; - size = _; - return pack; - }; - pack.radius = function(_) { - if (!arguments.length) return radius; - radius = _ == null || typeof _ === "function" ? _ : +_; - return pack; - }; - pack.padding = function(_) { - if (!arguments.length) return padding; - padding = +_; - return pack; - }; - return d3_layout_hierarchyRebind(pack, hierarchy); - }; - function d3_layout_packSort(a, b) { - return a.value - b.value; - } - function d3_layout_packInsert(a, b) { - var c = a._pack_next; - a._pack_next = b; - b._pack_prev = a; - b._pack_next = c; - c._pack_prev = b; - } - function d3_layout_packSplice(a, b) { - a._pack_next = b; - b._pack_prev = a; - } - function d3_layout_packIntersects(a, b) { - var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; - return .999 * dr * dr > dx * dx + dy * dy; - } - function d3_layout_packSiblings(node) { - if (!(nodes = node.children) || !(n = nodes.length)) return; - var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; - function bound(node) { - xMin = Math.min(node.x - node.r, xMin); - xMax = Math.max(node.x + node.r, xMax); - yMin = Math.min(node.y - node.r, yMin); - yMax = Math.max(node.y + node.r, yMax); - } - nodes.forEach(d3_layout_packLink); - a = nodes[0]; - a.x = -a.r; - a.y = 0; - bound(a); - if (n > 1) { - b = nodes[1]; - b.x = b.r; - b.y = 0; - bound(b); - if (n > 2) { - c = nodes[2]; - d3_layout_packPlace(a, b, c); - bound(c); - d3_layout_packInsert(a, c); - a._pack_prev = c; - d3_layout_packInsert(c, b); - b = a._pack_next; - for (i = 3; i < n; i++) { - d3_layout_packPlace(a, b, c = nodes[i]); - var isect = 0, s1 = 1, s2 = 1; - for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { - if (d3_layout_packIntersects(j, c)) { - isect = 1; - break; - } - } - if (isect == 1) { - for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { - if (d3_layout_packIntersects(k, c)) { - break; - } - } - } - if (isect) { - if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); - i--; - } else { - d3_layout_packInsert(a, c); - b = c; - bound(c); - } - } - } - } - var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; - for (i = 0; i < n; i++) { - c = nodes[i]; - c.x -= cx; - c.y -= cy; - cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); - } - node.r = cr; - nodes.forEach(d3_layout_packUnlink); - } - function d3_layout_packLink(node) { - node._pack_next = node._pack_prev = node; - } - function d3_layout_packUnlink(node) { - delete node._pack_next; - delete node._pack_prev; - } - function d3_layout_packTransform(node, x, y, k) { - var children = node.children; - node.x = x += k * node.x; - node.y = y += k * node.y; - node.r *= k; - if (children) { - var i = -1, n = children.length; - while (++i < n) d3_layout_packTransform(children[i], x, y, k); - } - } - function d3_layout_packPlace(a, b, c) { - var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; - if (db && (dx || dy)) { - var da = b.r + c.r, dc = dx * dx + dy * dy; - da *= da; - db *= db; - var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); - c.x = a.x + x * dx + y * dy; - c.y = a.y + x * dy - y * dx; - } else { - c.x = a.x + db; - c.y = a.y; - } - } - d3.layout.tree = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; - function tree(d, i) { - var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); - d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; - d3_layout_hierarchyVisitBefore(root1, secondWalk); - if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { - var left = root0, right = root0, bottom = root0; - d3_layout_hierarchyVisitBefore(root0, function(node) { - if (node.x < left.x) left = node; - if (node.x > right.x) right = node; - if (node.depth > bottom.depth) bottom = node; - }); - var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); - d3_layout_hierarchyVisitBefore(root0, function(node) { - node.x = (node.x + tx) * kx; - node.y = node.depth * ky; - }); - } - return nodes; - } - function wrapTree(root0) { - var root1 = { - A: null, - children: [ root0 ] - }, queue = [ root1 ], node1; - while ((node1 = queue.pop()) != null) { - for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { - queue.push((children[i] = child = { - _: children[i], - parent: node1, - children: (child = children[i].children) && child.slice() || [], - A: null, - a: null, - z: 0, - m: 0, - c: 0, - s: 0, - t: null, - i: i - }).a = child); - } - } - return root1.children[0]; - } - function firstWalk(v) { - var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; - if (children.length) { - d3_layout_treeShift(v); - var midpoint = (children[0].z + children[children.length - 1].z) / 2; - if (w) { - v.z = w.z + separation(v._, w._); - v.m = v.z - midpoint; - } else { - v.z = midpoint; - } - } else if (w) { - v.z = w.z + separation(v._, w._); - } - v.parent.A = apportion(v, w, v.parent.A || siblings[0]); - } - function secondWalk(v) { - v._.x = v.z + v.parent.m; - v.m += v.parent.m; - } - function apportion(v, w, ancestor) { - if (w) { - var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; - while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { - vom = d3_layout_treeLeft(vom); - vop = d3_layout_treeRight(vop); - vop.a = v; - shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); - if (shift > 0) { - d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); - sip += shift; - sop += shift; - } - sim += vim.m; - sip += vip.m; - som += vom.m; - sop += vop.m; - } - if (vim && !d3_layout_treeRight(vop)) { - vop.t = vim; - vop.m += sim - sop; - } - if (vip && !d3_layout_treeLeft(vom)) { - vom.t = vip; - vom.m += sip - som; - ancestor = v; - } - } - return ancestor; - } - function sizeNode(node) { - node.x *= size[0]; - node.y = node.depth * size[1]; - } - tree.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return tree; - }; - tree.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null ? sizeNode : null; - return tree; - }; - tree.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) == null ? null : sizeNode; - return tree; - }; - return d3_layout_hierarchyRebind(tree, hierarchy); - }; - function d3_layout_treeSeparation(a, b) { - return a.parent == b.parent ? 1 : 2; - } - function d3_layout_treeLeft(v) { - var children = v.children; - return children.length ? children[0] : v.t; - } - function d3_layout_treeRight(v) { - var children = v.children, n; - return (n = children.length) ? children[n - 1] : v.t; - } - function d3_layout_treeMove(wm, wp, shift) { - var change = shift / (wp.i - wm.i); - wp.c -= change; - wp.s += shift; - wm.c += change; - wp.z += shift; - wp.m += shift; - } - function d3_layout_treeShift(v) { - var shift = 0, change = 0, children = v.children, i = children.length, w; - while (--i >= 0) { - w = children[i]; - w.z += shift; - w.m += shift; - shift += w.s + (change += w.c); - } - } - function d3_layout_treeAncestor(vim, v, ancestor) { - return vim.a.parent === v.parent ? vim.a : ancestor; - } - d3.layout.cluster = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; - function cluster(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; - d3_layout_hierarchyVisitAfter(root, function(node) { - var children = node.children; - if (children && children.length) { - node.x = d3_layout_clusterX(children); - node.y = d3_layout_clusterY(children); - } else { - node.x = previousNode ? x += separation(node, previousNode) : 0; - node.y = 0; - previousNode = node; - } - }); - var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; - d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { - node.x = (node.x - root.x) * size[0]; - node.y = (root.y - node.y) * size[1]; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * size[0]; - node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; - }); - return nodes; - } - cluster.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return cluster; - }; - cluster.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null; - return cluster; - }; - cluster.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) != null; - return cluster; - }; - return d3_layout_hierarchyRebind(cluster, hierarchy); - }; - function d3_layout_clusterY(children) { - return 1 + d3.max(children, function(child) { - return child.y; - }); - } - function d3_layout_clusterX(children) { - return children.reduce(function(x, child) { - return x + child.x; - }, 0) / children.length; - } - function d3_layout_clusterLeft(node) { - var children = node.children; - return children && children.length ? d3_layout_clusterLeft(children[0]) : node; - } - function d3_layout_clusterRight(node) { - var children = node.children, n; - return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; - } - d3.layout.treemap = function() { - var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); - function scale(children, k) { - var i = -1, n = children.length, child, area; - while (++i < n) { - area = (child = children[i]).value * (k < 0 ? 0 : k); - child.area = isNaN(area) || area <= 0 ? 0 : area; - } - } - function squarify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while ((n = remaining.length) > 0) { - row.push(child = remaining[n - 1]); - row.area += child.area; - if (mode !== "squarify" || (score = worst(row, u)) <= best) { - remaining.pop(); - best = score; - } else { - row.area -= row.pop().area; - position(row, u, rect, false); - u = Math.min(rect.dx, rect.dy); - row.length = row.area = 0; - best = Infinity; - } - } - if (row.length) { - position(row, u, rect, true); - row.length = row.area = 0; - } - children.forEach(squarify); - } - } - function stickify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), remaining = children.slice(), child, row = []; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while (child = remaining.pop()) { - row.push(child); - row.area += child.area; - if (child.z != null) { - position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); - row.length = row.area = 0; - } - } - children.forEach(stickify); - } - } - function worst(row, u) { - var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; - while (++i < n) { - if (!(r = row[i].area)) continue; - if (r < rmin) rmin = r; - if (r > rmax) rmax = r; - } - s *= s; - u *= u; - return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; - } - function position(row, u, rect, flush) { - var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; - if (u == rect.dx) { - if (flush || v > rect.dy) v = rect.dy; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dy = v; - x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); - } - o.z = true; - o.dx += rect.x + rect.dx - x; - rect.y += v; - rect.dy -= v; - } else { - if (flush || v > rect.dx) v = rect.dx; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dx = v; - y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); - } - o.z = false; - o.dy += rect.y + rect.dy - y; - rect.x += v; - rect.dx -= v; - } - } - function treemap(d) { - var nodes = stickies || hierarchy(d), root = nodes[0]; - root.x = root.y = 0; - if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0; - if (stickies) hierarchy.revalue(root); - scale([ root ], root.dx * root.dy / root.value); - (stickies ? stickify : squarify)(root); - if (sticky) stickies = nodes; - return nodes; - } - treemap.size = function(x) { - if (!arguments.length) return size; - size = x; - return treemap; - }; - treemap.padding = function(x) { - if (!arguments.length) return padding; - function padFunction(node) { - var p = x.call(treemap, node, node.depth); - return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); - } - function padConstant(node) { - return d3_layout_treemapPad(node, x); - } - var type; - pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], - padConstant) : padConstant; - return treemap; - }; - treemap.round = function(x) { - if (!arguments.length) return round != Number; - round = x ? Math.round : Number; - return treemap; - }; - treemap.sticky = function(x) { - if (!arguments.length) return sticky; - sticky = x; - stickies = null; - return treemap; - }; - treemap.ratio = function(x) { - if (!arguments.length) return ratio; - ratio = x; - return treemap; - }; - treemap.mode = function(x) { - if (!arguments.length) return mode; - mode = x + ""; - return treemap; - }; - return d3_layout_hierarchyRebind(treemap, hierarchy); - }; - function d3_layout_treemapPadNull(node) { - return { - x: node.x, - y: node.y, - dx: node.dx, - dy: node.dy - }; - } - function d3_layout_treemapPad(node, padding) { - var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; - if (dx < 0) { - x += dx / 2; - dx = 0; - } - if (dy < 0) { - y += dy / 2; - dy = 0; - } - return { - x: x, - y: y, - dx: dx, - dy: dy - }; - } - d3.random = { - normal: function(µ, σ) { - var n = arguments.length; - if (n < 2) σ = 1; - if (n < 1) µ = 0; - return function() { - var x, y, r; - do { - x = Math.random() * 2 - 1; - y = Math.random() * 2 - 1; - r = x * x + y * y; - } while (!r || r > 1); - return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); - }; - }, - logNormal: function() { - var random = d3.random.normal.apply(d3, arguments); - return function() { - return Math.exp(random()); - }; - }, - bates: function(m) { - var random = d3.random.irwinHall(m); - return function() { - return random() / m; - }; - }, - irwinHall: function(m) { - return function() { - for (var s = 0, j = 0; j < m; j++) s += Math.random(); - return s; - }; - } - }; - d3.scale = {}; - function d3_scaleExtent(domain) { - var start = domain[0], stop = domain[domain.length - 1]; - return start < stop ? [ start, stop ] : [ stop, start ]; - } - function d3_scaleRange(scale) { - return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); - } - function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { - var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); - return function(x) { - return i(u(x)); - }; - } - function d3_scale_nice(domain, nice) { - var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; - if (x1 < x0) { - dx = i0, i0 = i1, i1 = dx; - dx = x0, x0 = x1, x1 = dx; - } - domain[i0] = nice.floor(x0); - domain[i1] = nice.ceil(x1); - return domain; - } - function d3_scale_niceStep(step) { - return step ? { - floor: function(x) { - return Math.floor(x / step) * step; - }, - ceil: function(x) { - return Math.ceil(x / step) * step; - } - } : d3_scale_niceIdentity; - } - var d3_scale_niceIdentity = { - floor: d3_identity, - ceil: d3_identity - }; - function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { - var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; - if (domain[k] < domain[0]) { - domain = domain.slice().reverse(); - range = range.slice().reverse(); - } - while (++j <= k) { - u.push(uninterpolate(domain[j - 1], domain[j])); - i.push(interpolate(range[j - 1], range[j])); - } - return function(x) { - var j = d3.bisect(domain, x, 1, k) - 1; - return i[j](u[j](x)); - }; - } - d3.scale.linear = function() { - return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); - }; - function d3_scale_linear(domain, range, interpolate, clamp) { - var output, input; - function rescale() { - var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; - output = linear(domain, range, uninterpolate, interpolate); - input = linear(range, domain, uninterpolate, d3_interpolate); - return scale; - } - function scale(x) { - return output(x); - } - scale.invert = function(y) { - return input(y); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(Number); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.rangeRound = function(x) { - return scale.range(x).interpolate(d3_interpolateRound); - }; - scale.clamp = function(x) { - if (!arguments.length) return clamp; - clamp = x; - return rescale(); - }; - scale.interpolate = function(x) { - if (!arguments.length) return interpolate; - interpolate = x; - return rescale(); - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - d3_scale_linearNice(domain, m); - return rescale(); - }; - scale.copy = function() { - return d3_scale_linear(domain, range, interpolate, clamp); - }; - return rescale(); - } - function d3_scale_linearRebind(scale, linear) { - return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); - } - function d3_scale_linearNice(domain, m) { - d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); - d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); - return domain; - } - function d3_scale_linearTickRange(domain, m) { - if (m == null) m = 10; - var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; - if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; - extent[0] = Math.ceil(extent[0] / step) * step; - extent[1] = Math.floor(extent[1] / step) * step + step * .5; - extent[2] = step; - return extent; - } - function d3_scale_linearTicks(domain, m) { - return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); - } - function d3_scale_linearTickFormat(domain, m, format) { - var range = d3_scale_linearTickRange(domain, m); - if (format) { - var match = d3_format_re.exec(format); - match.shift(); - if (match[8] === "s") { - var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); - if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); - match[8] = "f"; - format = d3.format(match.join("")); - return function(d) { - return format(prefix.scale(d)) + prefix.symbol; - }; - } - if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); - format = match.join(""); - } else { - format = ",." + d3_scale_linearPrecision(range[2]) + "f"; - } - return d3.format(format); - } - var d3_scale_linearFormatSignificant = { - s: 1, - g: 1, - p: 1, - r: 1, - e: 1 - }; - function d3_scale_linearPrecision(value) { - return -Math.floor(Math.log(value) / Math.LN10 + .01); - } - function d3_scale_linearFormatPrecision(type, range) { - var p = d3_scale_linearPrecision(range[2]); - return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; - } - d3.scale.log = function() { - return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); - }; - function d3_scale_log(linear, base, positive, domain) { - function log(x) { - return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); - } - function pow(x) { - return positive ? Math.pow(base, x) : -Math.pow(base, -x); - } - function scale(x) { - return linear(log(x)); - } - scale.invert = function(x) { - return pow(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - positive = x[0] >= 0; - linear.domain((domain = x.map(Number)).map(log)); - return scale; - }; - scale.base = function(_) { - if (!arguments.length) return base; - base = +_; - linear.domain(domain.map(log)); - return scale; - }; - scale.nice = function() { - var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); - linear.domain(niced); - domain = niced.map(pow); - return scale; - }; - scale.ticks = function() { - var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; - if (isFinite(j - i)) { - if (positive) { - for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); - ticks.push(pow(i)); - } else { - ticks.push(pow(i)); - for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); - } - for (i = 0; ticks[i] < u; i++) {} - for (j = ticks.length; ticks[j - 1] > v; j--) {} - ticks = ticks.slice(i, j); - } - return ticks; - }; - scale.tickFormat = function(n, format) { - if (!arguments.length) return d3_scale_logFormat; - if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); - var k = Math.max(1, base * n / scale.ticks().length); - return function(d) { - var i = d / pow(Math.round(log(d))); - if (i * base < base - .5) i *= base; - return i <= k ? format(d) : ""; - }; - }; - scale.copy = function() { - return d3_scale_log(linear.copy(), base, positive, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { - floor: function(x) { - return -Math.ceil(-x); - }, - ceil: function(x) { - return -Math.floor(-x); - } - }; - d3.scale.pow = function() { - return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); - }; - function d3_scale_pow(linear, exponent, domain) { - var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); - function scale(x) { - return linear(powp(x)); - } - scale.invert = function(x) { - return powb(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - linear.domain((domain = x.map(Number)).map(powp)); - return scale; - }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - scale.nice = function(m) { - return scale.domain(d3_scale_linearNice(domain, m)); - }; - scale.exponent = function(x) { - if (!arguments.length) return exponent; - powp = d3_scale_powPow(exponent = x); - powb = d3_scale_powPow(1 / exponent); - linear.domain(domain.map(powp)); - return scale; - }; - scale.copy = function() { - return d3_scale_pow(linear.copy(), exponent, domain); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_scale_powPow(e) { - return function(x) { - return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); - }; - } - d3.scale.sqrt = function() { - return d3.scale.pow().exponent(.5); - }; - d3.scale.ordinal = function() { - return d3_scale_ordinal([], { - t: "range", - a: [ [] ] - }); - }; - function d3_scale_ordinal(domain, ranger) { - var index, range, rangeBand; - function scale(x) { - return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; - } - function steps(start, step) { - return d3.range(domain.length).map(function(i) { - return start + step * i; - }); - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = []; - index = new d3_Map(); - var i = -1, n = x.length, xi; - while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); - return scale[ranger.t].apply(scale, ranger.a); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - rangeBand = 0; - ranger = { - t: "range", - a: arguments - }; - return scale; - }; - scale.rangePoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, - 0) : (stop - start) / (domain.length - 1 + padding); - range = steps(start + step * padding / 2, step); - rangeBand = 0; - ranger = { - t: "rangePoints", - a: arguments - }; - return scale; - }; - scale.rangeRoundPoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), - 0) : (stop - start) / (domain.length - 1 + padding) | 0; - range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); - rangeBand = 0; - ranger = { - t: "rangeRoundPoints", - a: arguments - }; - return scale; - }; - scale.rangeBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); - range = steps(start + step * outerPadding, step); - if (reverse) range.reverse(); - rangeBand = step * (1 - padding); - ranger = { - t: "rangeBands", - a: arguments - }; - return scale; - }; - scale.rangeRoundBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); - range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); - if (reverse) range.reverse(); - rangeBand = Math.round(step * (1 - padding)); - ranger = { - t: "rangeRoundBands", - a: arguments - }; - return scale; - }; - scale.rangeBand = function() { - return rangeBand; - }; - scale.rangeExtent = function() { - return d3_scaleExtent(ranger.a[0]); - }; - scale.copy = function() { - return d3_scale_ordinal(domain, ranger); - }; - return scale.domain(domain); - } - d3.scale.category10 = function() { - return d3.scale.ordinal().range(d3_category10); - }; - d3.scale.category20 = function() { - return d3.scale.ordinal().range(d3_category20); - }; - d3.scale.category20b = function() { - return d3.scale.ordinal().range(d3_category20b); - }; - d3.scale.category20c = function() { - return d3.scale.ordinal().range(d3_category20c); - }; - var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); - var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); - var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); - var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); - d3.scale.quantile = function() { - return d3_scale_quantile([], []); - }; - function d3_scale_quantile(domain, range) { - var thresholds; - function rescale() { - var k = 0, q = range.length; - thresholds = []; - while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); - return scale; - } - function scale(x) { - if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.quantiles = function() { - return thresholds; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; - }; - scale.copy = function() { - return d3_scale_quantile(domain, range); - }; - return rescale(); - } - d3.scale.quantize = function() { - return d3_scale_quantize(0, 1, [ 0, 1 ]); - }; - function d3_scale_quantize(x0, x1, range) { - var kx, i; - function scale(x) { - return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; - } - function rescale() { - kx = range.length / (x1 - x0); - i = range.length - 1; - return scale; - } - scale.domain = function(x) { - if (!arguments.length) return [ x0, x1 ]; - x0 = +x[0]; - x1 = +x[x.length - 1]; - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - y = y < 0 ? NaN : y / kx + x0; - return [ y, y + 1 / kx ]; - }; - scale.copy = function() { - return d3_scale_quantize(x0, x1, range); - }; - return rescale(); - } - d3.scale.threshold = function() { - return d3_scale_threshold([ .5 ], [ 0, 1 ]); - }; - function d3_scale_threshold(domain, range) { - function scale(x) { - if (x <= x) return range[d3.bisect(domain, x)]; - } - scale.domain = function(_) { - if (!arguments.length) return domain; - domain = _; - return scale; - }; - scale.range = function(_) { - if (!arguments.length) return range; - range = _; - return scale; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return [ domain[y - 1], domain[y] ]; - }; - scale.copy = function() { - return d3_scale_threshold(domain, range); - }; - return scale; - } - d3.scale.identity = function() { - return d3_scale_identity([ 0, 1 ]); - }; - function d3_scale_identity(domain) { - function identity(x) { - return +x; - } - identity.invert = identity; - identity.domain = identity.range = function(x) { - if (!arguments.length) return domain; - domain = x.map(identity); - return identity; - }; - identity.ticks = function(m) { - return d3_scale_linearTicks(domain, m); - }; - identity.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); - }; - identity.copy = function() { - return d3_scale_identity(domain); - }; - return identity; - } - d3.svg = {}; - function d3_zero() { - return 0; - } - d3.svg.arc = function() { - var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; - function arc() { - var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; - if (r1 < r0) rc = r1, r1 = r0, r0 = rc; - if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; - var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; - if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { - rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); - if (!cw) p1 *= -1; - if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); - if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); - } - if (r1) { - x0 = r1 * Math.cos(a0 + p1); - y0 = r1 * Math.sin(a0 + p1); - x1 = r1 * Math.cos(a1 - p1); - y1 = r1 * Math.sin(a1 - p1); - var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; - if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { - var h1 = (a0 + a1) / 2; - x0 = r1 * Math.cos(h1); - y0 = r1 * Math.sin(h1); - x1 = y1 = null; - } - } else { - x0 = y0 = 0; - } - if (r0) { - x2 = r0 * Math.cos(a1 - p0); - y2 = r0 * Math.sin(a1 - p0); - x3 = r0 * Math.cos(a0 + p0); - y3 = r0 * Math.sin(a0 + p0); - var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; - if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { - var h0 = (a0 + a1) / 2; - x2 = r0 * Math.cos(h0); - y2 = r0 * Math.sin(h0); - x3 = y3 = null; - } - } else { - x2 = y2 = 0; - } - if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { - cr = r0 < r1 ^ cw ? 0 : 1; - var rc1 = rc, rc0 = rc; - if (da < π) { - var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); - rc0 = Math.min(rc, (r0 - lc) / (kc - 1)); - rc1 = Math.min(rc, (r1 - lc) / (kc + 1)); - } - if (x1 != null) { - var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); - if (rc === rc1) { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); - } else { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); - } - } else { - path.push("M", x0, ",", y0); - } - if (x3 != null) { - var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); - if (rc === rc0) { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); - } else { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); - } - } else { - path.push("L", x2, ",", y2); - } - } else { - path.push("M", x0, ",", y0); - if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); - path.push("L", x2, ",", y2); - if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); - } - path.push("Z"); - return path.join(""); - } - function circleSegment(r1, cw) { - return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; - } - arc.innerRadius = function(v) { - if (!arguments.length) return innerRadius; - innerRadius = d3_functor(v); - return arc; - }; - arc.outerRadius = function(v) { - if (!arguments.length) return outerRadius; - outerRadius = d3_functor(v); - return arc; - }; - arc.cornerRadius = function(v) { - if (!arguments.length) return cornerRadius; - cornerRadius = d3_functor(v); - return arc; - }; - arc.padRadius = function(v) { - if (!arguments.length) return padRadius; - padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); - return arc; - }; - arc.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return arc; - }; - arc.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return arc; - }; - arc.padAngle = function(v) { - if (!arguments.length) return padAngle; - padAngle = d3_functor(v); - return arc; - }; - arc.centroid = function() { - var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; - return [ Math.cos(a) * r, Math.sin(a) * r ]; - }; - return arc; - }; - var d3_svg_arcAuto = "auto"; - function d3_svg_arcInnerRadius(d) { - return d.innerRadius; - } - function d3_svg_arcOuterRadius(d) { - return d.outerRadius; - } - function d3_svg_arcStartAngle(d) { - return d.startAngle; - } - function d3_svg_arcEndAngle(d) { - return d.endAngle; - } - function d3_svg_arcPadAngle(d) { - return d && d.padAngle; - } - function d3_svg_arcSweep(x0, y0, x1, y1) { - return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; - } - function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { - var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; - return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; - } - function d3_svg_line(projection) { - var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; - function line(data) { - var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); - function segment() { - segments.push("M", interpolate(projection(points), tension)); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); - } else if (points.length) { - segment(); - points = []; - } - } - if (points.length) segment(); - return segments.length ? segments.join("") : null; - } - line.x = function(_) { - if (!arguments.length) return x; - x = _; - return line; - }; - line.y = function(_) { - if (!arguments.length) return y; - y = _; - return line; - }; - line.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return line; - }; - line.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - return line; - }; - line.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return line; - }; - return line; - } - d3.svg.line = function() { - return d3_svg_line(d3_identity); - }; - var d3_svg_lineInterpolators = d3.map({ - linear: d3_svg_lineLinear, - "linear-closed": d3_svg_lineLinearClosed, - step: d3_svg_lineStep, - "step-before": d3_svg_lineStepBefore, - "step-after": d3_svg_lineStepAfter, - basis: d3_svg_lineBasis, - "basis-open": d3_svg_lineBasisOpen, - "basis-closed": d3_svg_lineBasisClosed, - bundle: d3_svg_lineBundle, - cardinal: d3_svg_lineCardinal, - "cardinal-open": d3_svg_lineCardinalOpen, - "cardinal-closed": d3_svg_lineCardinalClosed, - monotone: d3_svg_lineMonotone - }); - d3_svg_lineInterpolators.forEach(function(key, value) { - value.key = key; - value.closed = /-closed$/.test(key); - }); - function d3_svg_lineLinear(points) { - return points.length > 1 ? points.join("L") : points + "Z"; - } - function d3_svg_lineLinearClosed(points) { - return points.join("L") + "Z"; - } - function d3_svg_lineStep(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); - if (n > 1) path.push("H", p[0]); - return path.join(""); - } - function d3_svg_lineStepBefore(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); - return path.join(""); - } - function d3_svg_lineStepAfter(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); - return path.join(""); - } - function d3_svg_lineCardinalOpen(points, tension) { - return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineCardinalClosed(points, tension) { - return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), - points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); - } - function d3_svg_lineCardinal(points, tension) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); - } - function d3_svg_lineHermite(points, tangents) { - if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { - return d3_svg_lineLinear(points); - } - var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; - if (quad) { - path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; - p0 = points[1]; - pi = 2; - } - if (tangents.length > 1) { - t = tangents[1]; - p = points[pi]; - pi++; - path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - for (var i = 2; i < tangents.length; i++, pi++) { - p = points[pi]; - t = tangents[i]; - path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - } - } - if (quad) { - var lp = points[pi]; - path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; - } - return path; - } - function d3_svg_lineCardinalTangents(points, tension) { - var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; - while (++i < n) { - p0 = p1; - p1 = p2; - p2 = points[i]; - tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); - } - return tangents; - } - function d3_svg_lineBasis(points) { - if (points.length < 3) return d3_svg_lineLinear(points); - var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - points.push(points[n - 1]); - while (++i <= n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - points.pop(); - path.push("L", pi); - return path.join(""); - } - function d3_svg_lineBasisOpen(points) { - if (points.length < 4) return d3_svg_lineLinear(points); - var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; - while (++i < 3) { - pi = points[i]; - px.push(pi[0]); - py.push(pi[1]); - } - path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); - --i; - while (++i < n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBasisClosed(points) { - var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; - while (++i < 4) { - pi = points[i % n]; - px.push(pi[0]); - py.push(pi[1]); - } - path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - --i; - while (++i < m) { - pi = points[i % n]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); - } - return path.join(""); - } - function d3_svg_lineBundle(points, tension) { - var n = points.length - 1; - if (n) { - var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; - while (++i <= n) { - p = points[i]; - t = i / n; - p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); - p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); - } - } - return d3_svg_lineBasis(points); - } - function d3_svg_lineDot4(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; - } - var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; - function d3_svg_lineBasisBezier(path, x, y) { - path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); - } - function d3_svg_lineSlope(p0, p1) { - return (p1[1] - p0[1]) / (p1[0] - p0[0]); - } - function d3_svg_lineFiniteDifferences(points) { - var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); - while (++i < j) { - m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; - } - m[i] = d; - return m; - } - function d3_svg_lineMonotoneTangents(points) { - var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; - while (++i < j) { - d = d3_svg_lineSlope(points[i], points[i + 1]); - if (abs(d) < ε) { - m[i] = m[i + 1] = 0; - } else { - a = m[i] / d; - b = m[i + 1] / d; - s = a * a + b * b; - if (s > 9) { - s = d * 3 / Math.sqrt(s); - m[i] = s * a; - m[i + 1] = s * b; - } - } - } - i = -1; - while (++i <= j) { - s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); - tangents.push([ s || 0, m[i] * s || 0 ]); - } - return tangents; - } - function d3_svg_lineMonotone(points) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); - } - d3.svg.line.radial = function() { - var line = d3_svg_line(d3_svg_lineRadial); - line.radius = line.x, delete line.x; - line.angle = line.y, delete line.y; - return line; - }; - function d3_svg_lineRadial(points) { - var point, i = -1, n = points.length, r, a; - while (++i < n) { - point = points[i]; - r = point[0]; - a = point[1] - halfπ; - point[0] = r * Math.cos(a); - point[1] = r * Math.sin(a); - } - return points; - } - function d3_svg_area(projection) { - var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; - function area(data) { - var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { - return x; - } : d3_functor(x1), fy1 = y0 === y1 ? function() { - return y; - } : d3_functor(y1), x, y; - function segment() { - segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); - points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); - } else if (points0.length) { - segment(); - points0 = []; - points1 = []; - } - } - if (points0.length) segment(); - return segments.length ? segments.join("") : null; - } - area.x = function(_) { - if (!arguments.length) return x1; - x0 = x1 = _; - return area; - }; - area.x0 = function(_) { - if (!arguments.length) return x0; - x0 = _; - return area; - }; - area.x1 = function(_) { - if (!arguments.length) return x1; - x1 = _; - return area; - }; - area.y = function(_) { - if (!arguments.length) return y1; - y0 = y1 = _; - return area; - }; - area.y0 = function(_) { - if (!arguments.length) return y0; - y0 = _; - return area; - }; - area.y1 = function(_) { - if (!arguments.length) return y1; - y1 = _; - return area; - }; - area.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return area; - }; - area.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - interpolateReverse = interpolate.reverse || interpolate; - L = interpolate.closed ? "M" : "L"; - return area; - }; - area.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return area; - }; - return area; - } - d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; - d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; - d3.svg.area = function() { - return d3_svg_area(d3_identity); - }; - d3.svg.area.radial = function() { - var area = d3_svg_area(d3_svg_lineRadial); - area.radius = area.x, delete area.x; - area.innerRadius = area.x0, delete area.x0; - area.outerRadius = area.x1, delete area.x1; - area.angle = area.y, delete area.y; - area.startAngle = area.y0, delete area.y0; - area.endAngle = area.y1, delete area.y1; - return area; - }; - d3.svg.chord = function() { - var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; - function chord(d, i) { - var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); - return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; - } - function subgroup(self, f, d, i) { - var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ; - return { - r: r, - a0: a0, - a1: a1, - p0: [ r * Math.cos(a0), r * Math.sin(a0) ], - p1: [ r * Math.cos(a1), r * Math.sin(a1) ] - }; - } - function equals(a, b) { - return a.a0 == b.a0 && a.a1 == b.a1; - } - function arc(r, p, a) { - return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; - } - function curve(r0, p0, r1, p1) { - return "Q 0,0 " + p1; - } - chord.radius = function(v) { - if (!arguments.length) return radius; - radius = d3_functor(v); - return chord; - }; - chord.source = function(v) { - if (!arguments.length) return source; - source = d3_functor(v); - return chord; - }; - chord.target = function(v) { - if (!arguments.length) return target; - target = d3_functor(v); - return chord; - }; - chord.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return chord; - }; - chord.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return chord; - }; - return chord; - }; - function d3_svg_chordRadius(d) { - return d.radius; - } - d3.svg.diagonal = function() { - var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; - function diagonal(d, i) { - var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { - x: p0.x, - y: m - }, { - x: p3.x, - y: m - }, p3 ]; - p = p.map(projection); - return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; - } - diagonal.source = function(x) { - if (!arguments.length) return source; - source = d3_functor(x); - return diagonal; - }; - diagonal.target = function(x) { - if (!arguments.length) return target; - target = d3_functor(x); - return diagonal; - }; - diagonal.projection = function(x) { - if (!arguments.length) return projection; - projection = x; - return diagonal; - }; - return diagonal; - }; - function d3_svg_diagonalProjection(d) { - return [ d.x, d.y ]; - } - d3.svg.diagonal.radial = function() { - var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; - diagonal.projection = function(x) { - return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; - }; - return diagonal; - }; - function d3_svg_diagonalRadialProjection(projection) { - return function() { - var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ; - return [ r * Math.cos(a), r * Math.sin(a) ]; - }; - } - d3.svg.symbol = function() { - var type = d3_svg_symbolType, size = d3_svg_symbolSize; - function symbol(d, i) { - return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); - } - symbol.type = function(x) { - if (!arguments.length) return type; - type = d3_functor(x); - return symbol; - }; - symbol.size = function(x) { - if (!arguments.length) return size; - size = d3_functor(x); - return symbol; - }; - return symbol; - }; - function d3_svg_symbolSize() { - return 64; - } - function d3_svg_symbolType() { - return "circle"; - } - function d3_svg_symbolCircle(size) { - var r = Math.sqrt(size / π); - return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; - } - var d3_svg_symbols = d3.map({ - circle: d3_svg_symbolCircle, - cross: function(size) { - var r = Math.sqrt(size / 5) / 2; - return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; - }, - diamond: function(size) { - var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; - return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; - }, - square: function(size) { - var r = Math.sqrt(size) / 2; - return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; - }, - "triangle-down": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; - }, - "triangle-up": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; - } - }); - d3.svg.symbolTypes = d3_svg_symbols.keys(); - var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); - d3_selectionPrototype.transition = function(name) { - var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { - time: Date.now(), - ease: d3_ease_cubicInOut, - delay: 0, - duration: 250 - }; - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); - subgroup.push(node); - } - } - return d3_transition(subgroups, ns, id); - }; - d3_selectionPrototype.interrupt = function(name) { - return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); - }; - var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); - function d3_selection_interruptNS(ns) { - return function() { - var lock, activeId, active; - if ((lock = this[ns]) && (active = lock[activeId = lock.active])) { - active.timer.c = null; - active.timer.t = NaN; - if (--lock.count) delete lock[activeId]; else delete this[ns]; - lock.active += .5; - active.event && active.event.interrupt.call(this, this.__data__, active.index); - } - }; - } - function d3_transition(groups, ns, id) { - d3_subclass(groups, d3_transitionPrototype); - groups.namespace = ns; - groups.id = id; - return groups; - } - var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; - d3_transitionPrototype.call = d3_selectionPrototype.call; - d3_transitionPrototype.empty = d3_selectionPrototype.empty; - d3_transitionPrototype.node = d3_selectionPrototype.node; - d3_transitionPrototype.size = d3_selectionPrototype.size; - d3.transition = function(selection, name) { - return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection); - }; - d3.transition.prototype = d3_transitionPrototype; - d3_transitionPrototype.select = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - d3_transitionNode(subnode, i, ns, id, node[ns][id]); - subgroup.push(subnode); - } else { - subgroup.push(null); - } - } - } - return d3_transition(subgroups, ns, id); - }; - d3_transitionPrototype.selectAll = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - transition = node[ns][id]; - subnodes = selector.call(node, node.__data__, i, j); - subgroups.push(subgroup = []); - for (var k = -1, o = subnodes.length; ++k < o; ) { - if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition); - subgroup.push(subnode); - } - } - } - } - return d3_transition(subgroups, ns, id); - }; - d3_transitionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_transition(subgroups, this.namespace, this.id); - }; - d3_transitionPrototype.tween = function(name, tween) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) return this.node()[ns][id].tween.get(name); - return d3_selection_each(this, tween == null ? function(node) { - node[ns][id].tween.remove(name); - } : function(node) { - node[ns][id].tween.set(name, tween); - }); - }; - function d3_transition_tween(groups, name, value, tween) { - var id = groups.id, ns = groups.namespace; - return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { - node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); - } : (value = tween(value), function(node) { - node[ns][id].tween.set(name, value); - })); - } - d3_transitionPrototype.attr = function(nameNS, value) { - if (arguments.length < 2) { - for (value in nameNS) this.attr(value, nameNS[value]); - return this; - } - var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrTween(b) { - return b == null ? attrNull : (b += "", function() { - var a = this.getAttribute(name), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttribute(name, i(t)); - }); - }); - } - function attrTweenNS(b) { - return b == null ? attrNullNS : (b += "", function() { - var a = this.getAttributeNS(name.space, name.local), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttributeNS(name.space, name.local, i(t)); - }); - }); - } - return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.attrTween = function(nameNS, tween) { - var name = d3.ns.qualify(nameNS); - function attrTween(d, i) { - var f = tween.call(this, d, i, this.getAttribute(name)); - return f && function(t) { - this.setAttribute(name, f(t)); - }; - } - function attrTweenNS(d, i) { - var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); - return f && function(t) { - this.setAttributeNS(name.space, name.local, f(t)); - }; - } - return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.style(priority, name[priority], value); - return this; - } - priority = ""; - } - function styleNull() { - this.style.removeProperty(name); - } - function styleString(b) { - return b == null ? styleNull : (b += "", function() { - var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i; - return a !== b && (i = d3_interpolate(a, b), function(t) { - this.style.setProperty(name, i(t), priority); - }); - }); - } - return d3_transition_tween(this, "style." + name, value, styleString); - }; - d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = ""; - function styleTween(d, i) { - var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name)); - return f && function(t) { - this.style.setProperty(name, f(t), priority); - }; - } - return this.tween("style." + name, styleTween); - }; - d3_transitionPrototype.text = function(value) { - return d3_transition_tween(this, "text", value, d3_transition_text); - }; - function d3_transition_text(b) { - if (b == null) b = ""; - return function() { - this.textContent = b; - }; - } - d3_transitionPrototype.remove = function() { - var ns = this.namespace; - return this.each("end.transition", function() { - var p; - if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this); - }); - }; - d3_transitionPrototype.ease = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].ease; - if (typeof value !== "function") value = d3.ease.apply(d3, arguments); - return d3_selection_each(this, function(node) { - node[ns][id].ease = value; - }); - }; - d3_transitionPrototype.delay = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].delay; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].delay = +value.call(node, node.__data__, i, j); - } : (value = +value, function(node) { - node[ns][id].delay = value; - })); - }; - d3_transitionPrototype.duration = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].duration; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); - } : (value = Math.max(1, value), function(node) { - node[ns][id].duration = value; - })); - }; - d3_transitionPrototype.each = function(type, listener) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) { - var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; - try { - d3_transitionInheritId = id; - d3_selection_each(this, function(node, i, j) { - d3_transitionInherit = node[ns][id]; - type.call(node, node.__data__, i, j); - }); - } finally { - d3_transitionInherit = inherit; - d3_transitionInheritId = inheritId; - } - } else { - d3_selection_each(this, function(node) { - var transition = node[ns][id]; - (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener); - }); - } - return this; - }; - d3_transitionPrototype.transition = function() { - var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition; - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if (node = group[i]) { - transition = node[ns][id0]; - d3_transitionNode(node, i, ns, id1, { - time: transition.time, - ease: transition.ease, - delay: transition.delay + transition.duration, - duration: transition.duration - }); - } - subgroup.push(node); - } - } - return d3_transition(subgroups, ns, id1); - }; - function d3_transitionNamespace(name) { - return name == null ? "__transition__" : "__transition_" + name + "__"; - } - function d3_transitionNode(node, i, ns, id, inherit) { - var lock = node[ns] || (node[ns] = { - active: 0, - count: 0 - }), transition = lock[id], time, timer, duration, ease, tweens; - function schedule(elapsed) { - var delay = transition.delay; - timer.t = delay + time; - if (delay <= elapsed) return start(elapsed - delay); - timer.c = start; - } - function start(elapsed) { - var activeId = lock.active, active = lock[activeId]; - if (active) { - active.timer.c = null; - active.timer.t = NaN; - --lock.count; - delete lock[activeId]; - active.event && active.event.interrupt.call(node, node.__data__, active.index); - } - for (var cancelId in lock) { - if (+cancelId < id) { - var cancel = lock[cancelId]; - cancel.timer.c = null; - cancel.timer.t = NaN; - --lock.count; - delete lock[cancelId]; - } - } - timer.c = tick; - d3_timer(function() { - if (timer.c && tick(elapsed || 1)) { - timer.c = null; - timer.t = NaN; - } - return 1; - }, 0, time); - lock.active = id; - transition.event && transition.event.start.call(node, node.__data__, i); - tweens = []; - transition.tween.forEach(function(key, value) { - if (value = value.call(node, node.__data__, i)) { - tweens.push(value); - } - }); - ease = transition.ease; - duration = transition.duration; - } - function tick(elapsed) { - var t = elapsed / duration, e = ease(t), n = tweens.length; - while (n > 0) { - tweens[--n].call(node, e); - } - if (t >= 1) { - transition.event && transition.event.end.call(node, node.__data__, i); - if (--lock.count) delete lock[id]; else delete node[ns]; - return 1; - } - } - if (!transition) { - time = inherit.time; - timer = d3_timer(schedule, 0, time); - transition = lock[id] = { - tween: new d3_Map(), - time: time, - timer: timer, - delay: inherit.delay, - duration: inherit.duration, - ease: inherit.ease, - index: i - }; - inherit = null; - ++lock.count; - } - } - d3.svg.axis = function() { - var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; - function axis(g) { - g.each(function() { - var g = d3.select(this); - var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); - var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; - var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), - d3.transition(path)); - tickEnter.append("line"); - tickEnter.append("text"); - var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; - if (orient === "bottom" || orient === "top") { - tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; - text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); - } else { - tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; - text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); - pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); - } - lineEnter.attr(y2, sign * innerTickSize); - textEnter.attr(y1, sign * tickSpacing); - lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); - textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); - if (scale1.rangeBand) { - var x = scale1, dx = x.rangeBand() / 2; - scale0 = scale1 = function(d) { - return x(d) + dx; - }; - } else if (scale0.rangeBand) { - scale0 = scale1; - } else { - tickExit.call(tickTransform, scale1, scale0); - } - tickEnter.call(tickTransform, scale0, scale1); - tickUpdate.call(tickTransform, scale1, scale1); - }); - } - axis.scale = function(x) { - if (!arguments.length) return scale; - scale = x; - return axis; - }; - axis.orient = function(x) { - if (!arguments.length) return orient; - orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; - return axis; - }; - axis.ticks = function() { - if (!arguments.length) return tickArguments_; - tickArguments_ = d3_array(arguments); - return axis; - }; - axis.tickValues = function(x) { - if (!arguments.length) return tickValues; - tickValues = x; - return axis; - }; - axis.tickFormat = function(x) { - if (!arguments.length) return tickFormat_; - tickFormat_ = x; - return axis; - }; - axis.tickSize = function(x) { - var n = arguments.length; - if (!n) return innerTickSize; - innerTickSize = +x; - outerTickSize = +arguments[n - 1]; - return axis; - }; - axis.innerTickSize = function(x) { - if (!arguments.length) return innerTickSize; - innerTickSize = +x; - return axis; - }; - axis.outerTickSize = function(x) { - if (!arguments.length) return outerTickSize; - outerTickSize = +x; - return axis; - }; - axis.tickPadding = function(x) { - if (!arguments.length) return tickPadding; - tickPadding = +x; - return axis; - }; - axis.tickSubdivide = function() { - return arguments.length && axis; - }; - return axis; - }; - var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { - top: 1, - right: 1, - bottom: 1, - left: 1 - }; - function d3_svg_axisX(selection, x0, x1) { - selection.attr("transform", function(d) { - var v0 = x0(d); - return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; - }); - } - function d3_svg_axisY(selection, y0, y1) { - selection.attr("transform", function(d) { - var v0 = y0(d); - return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; - }); - } - d3.svg.brush = function() { - var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; - function brush(g) { - g.each(function() { - var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); - var background = g.selectAll(".background").data([ 0 ]); - background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); - g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); - var resize = g.selectAll(".resize").data(resizes, d3_identity); - resize.exit().remove(); - resize.enter().append("g").attr("class", function(d) { - return "resize " + d; - }).style("cursor", function(d) { - return d3_svg_brushCursor[d]; - }).append("rect").attr("x", function(d) { - return /[ew]$/.test(d) ? -3 : null; - }).attr("y", function(d) { - return /^[ns]/.test(d) ? -3 : null; - }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); - resize.style("display", brush.empty() ? "none" : null); - var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; - if (x) { - range = d3_scaleRange(x); - backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); - redrawX(gUpdate); - } - if (y) { - range = d3_scaleRange(y); - backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); - redrawY(gUpdate); - } - redraw(gUpdate); - }); - } - brush.event = function(g) { - g.each(function() { - var event_ = event.of(this, arguments), extent1 = { - x: xExtent, - y: yExtent, - i: xExtentDomain, - j: yExtentDomain - }, extent0 = this.__chart__ || extent1; - this.__chart__ = extent1; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.brush", function() { - xExtentDomain = extent0.i; - yExtentDomain = extent0.j; - xExtent = extent0.x; - yExtent = extent0.y; - event_({ - type: "brushstart" - }); - }).tween("brush:brush", function() { - var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); - xExtentDomain = yExtentDomain = null; - return function(t) { - xExtent = extent1.x = xi(t); - yExtent = extent1.y = yi(t); - event_({ - type: "brush", - mode: "resize" - }); - }; - }).each("end.brush", function() { - xExtentDomain = extent1.i; - yExtentDomain = extent1.j; - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - }); - } else { - event_({ - type: "brushstart" - }); - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - } - }); - }; - function redraw(g) { - g.selectAll(".resize").attr("transform", function(d) { - return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; - }); - } - function redrawX(g) { - g.select(".extent").attr("x", xExtent[0]); - g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); - } - function redrawY(g) { - g.select(".extent").attr("y", yExtent[0]); - g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); - } - function brushstart() { - var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset; - var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup); - if (d3.event.changedTouches) { - w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); - } else { - w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); - } - g.interrupt().selectAll("*").interrupt(); - if (dragging) { - origin[0] = xExtent[0] - origin[0]; - origin[1] = yExtent[0] - origin[1]; - } else if (resizing) { - var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); - offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; - origin[0] = xExtent[ex]; - origin[1] = yExtent[ey]; - } else if (d3.event.altKey) center = origin.slice(); - g.style("pointer-events", "none").selectAll(".resize").style("display", null); - d3.select("body").style("cursor", eventTarget.style("cursor")); - event_({ - type: "brushstart" - }); - brushmove(); - function keydown() { - if (d3.event.keyCode == 32) { - if (!dragging) { - center = null; - origin[0] -= xExtent[1]; - origin[1] -= yExtent[1]; - dragging = 2; - } - d3_eventPreventDefault(); - } - } - function keyup() { - if (d3.event.keyCode == 32 && dragging == 2) { - origin[0] += xExtent[1]; - origin[1] += yExtent[1]; - dragging = 0; - d3_eventPreventDefault(); - } - } - function brushmove() { - var point = d3.mouse(target), moved = false; - if (offset) { - point[0] += offset[0]; - point[1] += offset[1]; - } - if (!dragging) { - if (d3.event.altKey) { - if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; - origin[0] = xExtent[+(point[0] < center[0])]; - origin[1] = yExtent[+(point[1] < center[1])]; - } else center = null; - } - if (resizingX && move1(point, x, 0)) { - redrawX(g); - moved = true; - } - if (resizingY && move1(point, y, 1)) { - redrawY(g); - moved = true; - } - if (moved) { - redraw(g); - event_({ - type: "brush", - mode: dragging ? "move" : "resize" - }); - } - } - function move1(point, scale, i) { - var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; - if (dragging) { - r0 -= position; - r1 -= size + position; - } - min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; - if (dragging) { - max = (min += position) + size; - } else { - if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); - if (position < min) { - max = min; - min = position; - } else { - max = position; - } - } - if (extent[0] != min || extent[1] != max) { - if (i) yExtentDomain = null; else xExtentDomain = null; - extent[0] = min; - extent[1] = max; - return true; - } - } - function brushend() { - brushmove(); - g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); - d3.select("body").style("cursor", null); - w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); - dragRestore(); - event_({ - type: "brushend" - }); - } - } - brush.x = function(z) { - if (!arguments.length) return x; - x = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.y = function(z) { - if (!arguments.length) return y; - y = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; - }; - brush.clamp = function(z) { - if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; - if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; - return brush; - }; - brush.extent = function(z) { - var x0, x1, y0, y1, t; - if (!arguments.length) { - if (x) { - if (xExtentDomain) { - x0 = xExtentDomain[0], x1 = xExtentDomain[1]; - } else { - x0 = xExtent[0], x1 = xExtent[1]; - if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - } - } - if (y) { - if (yExtentDomain) { - y0 = yExtentDomain[0], y1 = yExtentDomain[1]; - } else { - y0 = yExtent[0], y1 = yExtent[1]; - if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - } - } - return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; - } - if (x) { - x0 = z[0], x1 = z[1]; - if (y) x0 = x0[0], x1 = x1[0]; - xExtentDomain = [ x0, x1 ]; - if (x.invert) x0 = x(x0), x1 = x(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; - } - if (y) { - y0 = z[0], y1 = z[1]; - if (x) y0 = y0[1], y1 = y1[1]; - yExtentDomain = [ y0, y1 ]; - if (y.invert) y0 = y(y0), y1 = y(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; - } - return brush; - }; - brush.clear = function() { - if (!brush.empty()) { - xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; - xExtentDomain = yExtentDomain = null; - } - return brush; - }; - brush.empty = function() { - return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; - }; - return d3.rebind(brush, event, "on"); - }; - var d3_svg_brushCursor = { - n: "ns-resize", - e: "ew-resize", - s: "ns-resize", - w: "ew-resize", - nw: "nwse-resize", - ne: "nesw-resize", - se: "nwse-resize", - sw: "nesw-resize" - }; - var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; - var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; - var d3_time_formatUtc = d3_time_format.utc; - var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); - d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; - function d3_time_formatIsoNative(date) { - return date.toISOString(); - } - d3_time_formatIsoNative.parse = function(string) { - var date = new Date(string); - return isNaN(date) ? null : date; - }; - d3_time_formatIsoNative.toString = d3_time_formatIso.toString; - d3_time.second = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 1e3) * 1e3); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 1e3); - }, function(date) { - return date.getSeconds(); - }); - d3_time.seconds = d3_time.second.range; - d3_time.seconds.utc = d3_time.second.utc.range; - d3_time.minute = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 6e4) * 6e4); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 6e4); - }, function(date) { - return date.getMinutes(); - }); - d3_time.minutes = d3_time.minute.range; - d3_time.minutes.utc = d3_time.minute.utc.range; - d3_time.hour = d3_time_interval(function(date) { - var timezone = date.getTimezoneOffset() / 60; - return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 36e5); - }, function(date) { - return date.getHours(); - }); - d3_time.hours = d3_time.hour.range; - d3_time.hours.utc = d3_time.hour.utc.range; - d3_time.month = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setDate(1); - return date; - }, function(date, offset) { - date.setMonth(date.getMonth() + offset); - }, function(date) { - return date.getMonth(); - }); - d3_time.months = d3_time.month.range; - d3_time.months.utc = d3_time.month.utc.range; - function d3_time_scale(linear, methods, format) { - function scale(x) { - return linear(x); - } - scale.invert = function(x) { - return d3_time_scaleDate(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(d3_time_scaleDate); - linear.domain(x); - return scale; - }; - function tickMethod(extent, count) { - var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); - return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { - return d / 31536e6; - }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; - } - scale.nice = function(interval, skip) { - var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); - if (method) interval = method[0], skip = method[1]; - function skipped(date) { - return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; - } - return scale.domain(d3_scale_nice(domain, skip > 1 ? { - floor: function(date) { - while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); - return date; - }, - ceil: function(date) { - while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); - return date; - } - } : interval)); - }; - scale.ticks = function(interval, skip) { - var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { - range: interval - }, skip ]; - if (method) interval = method[0], skip = method[1]; - return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); - }; - scale.tickFormat = function() { - return format; - }; - scale.copy = function() { - return d3_time_scale(linear.copy(), methods, format); - }; - return d3_scale_linearRebind(scale, linear); - } - function d3_time_scaleDate(t) { - return new Date(t); - } - var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; - var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; - var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { - return d.getMilliseconds(); - } ], [ ":%S", function(d) { - return d.getSeconds(); - } ], [ "%I:%M", function(d) { - return d.getMinutes(); - } ], [ "%I %p", function(d) { - return d.getHours(); - } ], [ "%a %d", function(d) { - return d.getDay() && d.getDate() != 1; - } ], [ "%b %d", function(d) { - return d.getDate() != 1; - } ], [ "%B", function(d) { - return d.getMonth(); - } ], [ "%Y", d3_true ] ]); - var d3_time_scaleMilliseconds = { - range: function(start, stop, step) { - return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); - }, - floor: d3_identity, - ceil: d3_identity - }; - d3_time_scaleLocalMethods.year = d3_time.year; - d3_time.scale = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); - }; - var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { - return [ m[0].utc, m[1] ]; - }); - var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { - return d.getUTCMilliseconds(); - } ], [ ":%S", function(d) { - return d.getUTCSeconds(); - } ], [ "%I:%M", function(d) { - return d.getUTCMinutes(); - } ], [ "%I %p", function(d) { - return d.getUTCHours(); - } ], [ "%a %d", function(d) { - return d.getUTCDay() && d.getUTCDate() != 1; - } ], [ "%b %d", function(d) { - return d.getUTCDate() != 1; - } ], [ "%B", function(d) { - return d.getUTCMonth(); - } ], [ "%Y", d3_true ] ]); - d3_time_scaleUtcMethods.year = d3_time.year.utc; - d3_time.scale.utc = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); - }; - d3.text = d3_xhrType(function(request) { - return request.responseText; - }); - d3.json = function(url, callback) { - return d3_xhr(url, "application/json", d3_json, callback); - }; - function d3_json(request) { - return JSON.parse(request.responseText); - } - d3.html = function(url, callback) { - return d3_xhr(url, "text/html", d3_html, callback); - }; - function d3_html(request) { - var range = d3_document.createRange(); - range.selectNode(d3_document.body); - return range.createContextualFragment(request.responseText); - } - d3.xml = d3_xhrType(function(request) { - return request.responseXML; - }); - if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3; -}(); -},{}],164:[function(_dereq_,module,exports){ -module.exports = function () { - for (var i = 0; i < arguments.length; i++) { - if (arguments[i] !== undefined) return arguments[i]; - } -}; - -},{}],165:[function(_dereq_,module,exports){ -"use strict" - -var ch = _dereq_("incremental-convex-hull") -var uniq = _dereq_("uniq") - -module.exports = triangulate - -function LiftedPoint(p, i) { - this.point = p - this.index = i -} - -function compareLifted(a, b) { - var ap = a.point - var bp = b.point - var d = ap.length - for(var i=0; i= 2) { - return false - } - } - cell[j] = v - } - return true - }) - } else { - hull = hull.filter(function(cell) { - for(var i=0; i<=d; ++i) { - var v = dindex[cell[i]] - if(v < 0) { - return false - } - cell[i] = v - } - return true - }) - } - - if(d & 1) { - for(var i=0; i fs * threshold) { - var emWidth = (kerningWidth - width) / fs - table[pair] = emWidth * 1000 - } - } - - return table -} - - -function createPairs (range) { - var pairs = [] - - for (var i = range[0]; i <= range[1]; i++) { - var leftChar = String.fromCharCode(i) - for (var j = range[0]; j < range[1]; j++) { - var rightChar = String.fromCharCode(j) - var pair = leftChar + rightChar - - pairs.push(pair) - } - } - - return pairs -} - -},{}],167:[function(_dereq_,module,exports){ -(function (Buffer){ -var hasTypedArrays = false -if(typeof Float64Array !== "undefined") { - var DOUBLE_VIEW = new Float64Array(1) - , UINT_VIEW = new Uint32Array(DOUBLE_VIEW.buffer) - DOUBLE_VIEW[0] = 1.0 - hasTypedArrays = true - if(UINT_VIEW[1] === 0x3ff00000) { - //Use little endian - module.exports = function doubleBitsLE(n) { - DOUBLE_VIEW[0] = n - return [ UINT_VIEW[0], UINT_VIEW[1] ] - } - function toDoubleLE(lo, hi) { - UINT_VIEW[0] = lo - UINT_VIEW[1] = hi - return DOUBLE_VIEW[0] - } - module.exports.pack = toDoubleLE - function lowUintLE(n) { - DOUBLE_VIEW[0] = n - return UINT_VIEW[0] - } - module.exports.lo = lowUintLE - function highUintLE(n) { - DOUBLE_VIEW[0] = n - return UINT_VIEW[1] - } - module.exports.hi = highUintLE - } else if(UINT_VIEW[0] === 0x3ff00000) { - //Use big endian - module.exports = function doubleBitsBE(n) { - DOUBLE_VIEW[0] = n - return [ UINT_VIEW[1], UINT_VIEW[0] ] - } - function toDoubleBE(lo, hi) { - UINT_VIEW[1] = lo - UINT_VIEW[0] = hi - return DOUBLE_VIEW[0] - } - module.exports.pack = toDoubleBE - function lowUintBE(n) { - DOUBLE_VIEW[0] = n - return UINT_VIEW[1] - } - module.exports.lo = lowUintBE - function highUintBE(n) { - DOUBLE_VIEW[0] = n - return UINT_VIEW[0] - } - module.exports.hi = highUintBE - } else { - hasTypedArrays = false - } -} -if(!hasTypedArrays) { - var buffer = new Buffer(8) - module.exports = function doubleBits(n) { - buffer.writeDoubleLE(n, 0, true) - return [ buffer.readUInt32LE(0, true), buffer.readUInt32LE(4, true) ] - } - function toDouble(lo, hi) { - buffer.writeUInt32LE(lo, 0, true) - buffer.writeUInt32LE(hi, 4, true) - return buffer.readDoubleLE(0, true) - } - module.exports.pack = toDouble - function lowUint(n) { - buffer.writeDoubleLE(n, 0, true) - return buffer.readUInt32LE(0, true) - } - module.exports.lo = lowUint - function highUint(n) { - buffer.writeDoubleLE(n, 0, true) - return buffer.readUInt32LE(4, true) - } - module.exports.hi = highUint -} - -module.exports.sign = function(n) { - return module.exports.hi(n) >>> 31 -} - -module.exports.exponent = function(n) { - var b = module.exports.hi(n) - return ((b<<1) >>> 21) - 1023 -} - -module.exports.fraction = function(n) { - var lo = module.exports.lo(n) - var hi = module.exports.hi(n) - var b = hi & ((1<<20) - 1) - if(hi & 0x7ff00000) { - b += (1<<20) - } - return [lo, b] -} - -module.exports.denormalized = function(n) { - var hi = module.exports.hi(n) - return !(hi & 0x7ff00000) -} -}).call(this,_dereq_("buffer").Buffer) -},{"buffer":105}],168:[function(_dereq_,module,exports){ -var abs = _dereq_('abs-svg-path') -var normalize = _dereq_('normalize-svg-path') - -var methods = { - 'M': 'moveTo', - 'C': 'bezierCurveTo' -} - -module.exports = function(context, segments) { - context.beginPath() - - // Make path easy to reproduce. - normalize(abs(segments)).forEach( - function(segment) { - var command = segment[0] - var args = segment.slice(1) - - // Convert the path command to a context method. - context[methods[command]].apply(context, args) - } - ) - - context.closePath() -} - -},{"abs-svg-path":60,"normalize-svg-path":452}],169:[function(_dereq_,module,exports){ -module.exports = function(dtype) { - switch (dtype) { - case 'int8': - return Int8Array - case 'int16': - return Int16Array - case 'int32': - return Int32Array - case 'uint8': - return Uint8Array - case 'uint16': - return Uint16Array - case 'uint32': - return Uint32Array - case 'float32': - return Float32Array - case 'float64': - return Float64Array - case 'array': - return Array - case 'uint8_clamped': - return Uint8ClampedArray - } -} - -},{}],170:[function(_dereq_,module,exports){ -"use strict" - -function dupe_array(count, value, i) { - var c = count[i]|0 - if(c <= 0) { - return [] - } - var result = new Array(c), j - if(i === count.length-1) { - for(j=0; j 0) { - return dupe_number(count|0, value) - } - break - case "object": - if(typeof (count.length) === "number") { - return dupe_array(count, value, 0) - } - break - } - return [] -} - -module.exports = dupe -},{}],171:[function(_dereq_,module,exports){ -"use strict" - -module.exports = edgeToAdjacency - -var uniq = _dereq_("uniq") - -function edgeToAdjacency(edges, numVertices) { - var numEdges = edges.length - if(typeof numVertices !== "number") { - numVertices = 0 - for(var i=0; i= minId; - }); - } - } - - function adjacencyStructureSCC(from) { - // Make subgraph starting from vertex minId - subgraph(from); - var g = edges; - - // Find strongly connected components using Tarjan algorithm - var sccs = tarjan(g); - - // Filter out trivial connected components (ie. made of one node) - var ccs = sccs.components.filter(function(scc) { - return scc.length > 1; - }); - - // Find least vertex - var leastVertex = Infinity; - var leastVertexComponent; - for(var i = 0; i < ccs.length; i++) { - for(var j = 0; j < ccs[i].length; j++) { - if(ccs[i][j] < leastVertex) { - leastVertex = ccs[i][j]; - leastVertexComponent = i; - } - } - } - - var cc = ccs[leastVertexComponent]; - - if(!cc) return false; - - // Return the adjacency list of first component - var adjList = edges.map(function(l, index) { - if(cc.indexOf(index) === -1) return []; - return l.filter(function(i) { - return cc.indexOf(i) !== -1; - }); - }); - - return { - leastVertex: leastVertex, - adjList: adjList - }; - } - - s = 0; - var n = edges.length; - while(s < n) { - // find strong component with least vertex in - // subgraph starting from vertex `s` - var p = adjacencyStructureSCC(s); - - // Its least vertex - s = p.leastVertex; - // Its adjacency list - Ak = p.adjList; - - if(Ak) { - for(var i = 0; i < Ak.length; i++) { - for(var j = 0; j < Ak[i].length; j++) { - var vertexId = Ak[i][j]; - blocked[+vertexId] = false; - B[vertexId] = {}; - } - } - circuit(s); - s = s + 1; - } else { - s = n; - } - - } - - return circuits; -}; - -},{"strongly-connected-components":530}],173:[function(_dereq_,module,exports){ -// Inspired by Google Closure: -// http://closure-library.googlecode.com/svn/docs/ -// closure_goog_array_array.js.html#goog.array.clear - -"use strict"; - -var value = _dereq_("../../object/valid-value"); - -module.exports = function () { - value(this).length = 0; - return this; -}; - -},{"../../object/valid-value":205}],174:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = _dereq_("./is-implemented")() - ? Array.from - : _dereq_("./shim"); - -},{"./is-implemented":175,"./shim":176}],175:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = function () { - var from = Array.from, arr, result; - if (typeof from !== "function") return false; - arr = ["raz", "dwa"]; - result = from(arr); - return Boolean(result && (result !== arr) && (result[1] === "dwa")); -}; - -},{}],176:[function(_dereq_,module,exports){ -"use strict"; - -var iteratorSymbol = _dereq_("es6-symbol").iterator - , isArguments = _dereq_("../../function/is-arguments") - , isFunction = _dereq_("../../function/is-function") - , toPosInt = _dereq_("../../number/to-pos-integer") - , callable = _dereq_("../../object/valid-callable") - , validValue = _dereq_("../../object/valid-value") - , isValue = _dereq_("../../object/is-value") - , isString = _dereq_("../../string/is-string") - , isArray = Array.isArray - , call = Function.prototype.call - , desc = { configurable: true, enumerable: true, writable: true, value: null } - , defineProperty = Object.defineProperty; - -// eslint-disable-next-line complexity -module.exports = function (arrayLike /*, mapFn, thisArg*/) { - var mapFn = arguments[1] - , thisArg = arguments[2] - , Context - , i - , j - , arr - , length - , code - , iterator - , result - , getIterator - , value; - - arrayLike = Object(validValue(arrayLike)); - - if (isValue(mapFn)) callable(mapFn); - if (!this || this === Array || !isFunction(this)) { - // Result: Plain array - if (!mapFn) { - if (isArguments(arrayLike)) { - // Source: Arguments - length = arrayLike.length; - if (length !== 1) return Array.apply(null, arrayLike); - arr = new Array(1); - arr[0] = arrayLike[0]; - return arr; - } - if (isArray(arrayLike)) { - // Source: Array - arr = new Array(length = arrayLike.length); - for (i = 0; i < length; ++i) arr[i] = arrayLike[i]; - return arr; - } - } - arr = []; - } else { - // Result: Non plain array - Context = this; - } - - if (!isArray(arrayLike)) { - if ((getIterator = arrayLike[iteratorSymbol]) !== undefined) { - // Source: Iterator - iterator = callable(getIterator).call(arrayLike); - if (Context) arr = new Context(); - result = iterator.next(); - i = 0; - while (!result.done) { - value = mapFn ? call.call(mapFn, thisArg, result.value, i) : result.value; - if (Context) { - desc.value = value; - defineProperty(arr, i, desc); - } else { - arr[i] = value; - } - result = iterator.next(); - ++i; - } - length = i; - } else if (isString(arrayLike)) { - // Source: String - length = arrayLike.length; - if (Context) arr = new Context(); - for (i = 0, j = 0; i < length; ++i) { - value = arrayLike[i]; - if (i + 1 < length) { - code = value.charCodeAt(0); - // eslint-disable-next-line max-depth - if (code >= 0xd800 && code <= 0xdbff) value += arrayLike[++i]; - } - value = mapFn ? call.call(mapFn, thisArg, value, j) : value; - if (Context) { - desc.value = value; - defineProperty(arr, j, desc); - } else { - arr[j] = value; - } - ++j; - } - length = j; - } - } - if (length === undefined) { - // Source: array or array-like - length = toPosInt(arrayLike.length); - if (Context) arr = new Context(length); - for (i = 0; i < length; ++i) { - value = mapFn ? call.call(mapFn, thisArg, arrayLike[i], i) : arrayLike[i]; - if (Context) { - desc.value = value; - defineProperty(arr, i, desc); - } else { - arr[i] = value; - } - } - } - if (Context) { - desc.value = null; - arr.length = length; - } - return arr; -}; - -},{"../../function/is-arguments":177,"../../function/is-function":178,"../../number/to-pos-integer":184,"../../object/is-value":194,"../../object/valid-callable":203,"../../object/valid-value":205,"../../string/is-string":209,"es6-symbol":219}],177:[function(_dereq_,module,exports){ -"use strict"; - -var objToString = Object.prototype.toString - , id = objToString.call( - (function () { - return arguments; - })() -); - -module.exports = function (value) { - return objToString.call(value) === id; -}; - -},{}],178:[function(_dereq_,module,exports){ -"use strict"; - -var objToString = Object.prototype.toString, id = objToString.call(_dereq_("./noop")); - -module.exports = function (value) { - return typeof value === "function" && objToString.call(value) === id; -}; - -},{"./noop":179}],179:[function(_dereq_,module,exports){ -"use strict"; - -// eslint-disable-next-line no-empty-function -module.exports = function () {}; - -},{}],180:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = _dereq_("./is-implemented")() - ? Math.sign - : _dereq_("./shim"); - -},{"./is-implemented":181,"./shim":182}],181:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = function () { - var sign = Math.sign; - if (typeof sign !== "function") return false; - return (sign(10) === 1) && (sign(-20) === -1); -}; - -},{}],182:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = function (value) { - value = Number(value); - if (isNaN(value) || (value === 0)) return value; - return value > 0 ? 1 : -1; -}; - -},{}],183:[function(_dereq_,module,exports){ -"use strict"; - -var sign = _dereq_("../math/sign") - - , abs = Math.abs, floor = Math.floor; - -module.exports = function (value) { - if (isNaN(value)) return 0; - value = Number(value); - if ((value === 0) || !isFinite(value)) return value; - return sign(value) * floor(abs(value)); -}; - -},{"../math/sign":180}],184:[function(_dereq_,module,exports){ -"use strict"; - -var toInteger = _dereq_("./to-integer") - - , max = Math.max; - -module.exports = function (value) { - return max(0, toInteger(value)); -}; - -},{"./to-integer":183}],185:[function(_dereq_,module,exports){ -// Internal method, used by iteration functions. -// Calls a function for each key-value pair found in object -// Optionally takes compareFn to iterate object in specific order - -"use strict"; - -var callable = _dereq_("./valid-callable") - , value = _dereq_("./valid-value") - , bind = Function.prototype.bind - , call = Function.prototype.call - , keys = Object.keys - , objPropertyIsEnumerable = Object.prototype.propertyIsEnumerable; - -module.exports = function (method, defVal) { - return function (obj, cb /*, thisArg, compareFn*/) { - var list, thisArg = arguments[2], compareFn = arguments[3]; - obj = Object(value(obj)); - callable(cb); - - list = keys(obj); - if (compareFn) { - list.sort(typeof compareFn === "function" ? bind.call(compareFn, obj) : undefined); - } - if (typeof method !== "function") method = list[method]; - return call.call(method, list, function (key, index) { - if (!objPropertyIsEnumerable.call(obj, key)) return defVal; - return call.call(cb, thisArg, obj[key], key, obj, index); - }); - }; -}; - -},{"./valid-callable":203,"./valid-value":205}],186:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = _dereq_("./is-implemented")() - ? Object.assign - : _dereq_("./shim"); - -},{"./is-implemented":187,"./shim":188}],187:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = function () { - var assign = Object.assign, obj; - if (typeof assign !== "function") return false; - obj = { foo: "raz" }; - assign(obj, { bar: "dwa" }, { trzy: "trzy" }); - return (obj.foo + obj.bar + obj.trzy) === "razdwatrzy"; -}; - -},{}],188:[function(_dereq_,module,exports){ -"use strict"; - -var keys = _dereq_("../keys") - , value = _dereq_("../valid-value") - , max = Math.max; - -module.exports = function (dest, src /*, …srcn*/) { - var error, i, length = max(arguments.length, 2), assign; - dest = Object(value(dest)); - assign = function (key) { - try { - dest[key] = src[key]; - } catch (e) { - if (!error) error = e; - } - }; - for (i = 1; i < length; ++i) { - src = arguments[i]; - keys(src).forEach(assign); - } - if (error !== undefined) throw error; - return dest; -}; - -},{"../keys":195,"../valid-value":205}],189:[function(_dereq_,module,exports){ -"use strict"; - -var aFrom = _dereq_("../array/from") - , assign = _dereq_("./assign") - , value = _dereq_("./valid-value"); - -module.exports = function (obj/*, propertyNames, options*/) { - var copy = Object(value(obj)), propertyNames = arguments[1], options = Object(arguments[2]); - if (copy !== obj && !propertyNames) return copy; - var result = {}; - if (propertyNames) { - aFrom(propertyNames, function (propertyName) { - if (options.ensure || propertyName in obj) result[propertyName] = obj[propertyName]; - }); - } else { - assign(result, obj); - } - return result; -}; - -},{"../array/from":174,"./assign":186,"./valid-value":205}],190:[function(_dereq_,module,exports){ -// Workaround for http://code.google.com/p/v8/issues/detail?id=2804 - -"use strict"; - -var create = Object.create, shim; - -if (!_dereq_("./set-prototype-of/is-implemented")()) { - shim = _dereq_("./set-prototype-of/shim"); -} - -module.exports = (function () { - var nullObject, polyProps, desc; - if (!shim) return create; - if (shim.level !== 1) return create; - - nullObject = {}; - polyProps = {}; - desc = { - configurable: false, - enumerable: false, - writable: true, - value: undefined - }; - Object.getOwnPropertyNames(Object.prototype).forEach(function (name) { - if (name === "__proto__") { - polyProps[name] = { - configurable: true, - enumerable: false, - writable: true, - value: undefined - }; - return; - } - polyProps[name] = desc; - }); - Object.defineProperties(nullObject, polyProps); - - Object.defineProperty(shim, "nullPolyfill", { - configurable: false, - enumerable: false, - writable: false, - value: nullObject - }); - - return function (prototype, props) { - return create(prototype === null ? nullObject : prototype, props); - }; -}()); - -},{"./set-prototype-of/is-implemented":201,"./set-prototype-of/shim":202}],191:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = _dereq_("./_iterate")("forEach"); - -},{"./_iterate":185}],192:[function(_dereq_,module,exports){ -// Deprecated - -"use strict"; - -module.exports = function (obj) { - return typeof obj === "function"; -}; - -},{}],193:[function(_dereq_,module,exports){ -"use strict"; - -var isValue = _dereq_("./is-value"); - -var map = { function: true, object: true }; - -module.exports = function (value) { - return (isValue(value) && map[typeof value]) || false; -}; - -},{"./is-value":194}],194:[function(_dereq_,module,exports){ -"use strict"; - -var _undefined = _dereq_("../function/noop")(); // Support ES3 engines - -module.exports = function (val) { - return (val !== _undefined) && (val !== null); -}; - -},{"../function/noop":179}],195:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = _dereq_("./is-implemented")() ? Object.keys : _dereq_("./shim"); - -},{"./is-implemented":196,"./shim":197}],196:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = function () { - try { - Object.keys("primitive"); - return true; - } catch (e) { - return false; - } -}; - -},{}],197:[function(_dereq_,module,exports){ -"use strict"; - -var isValue = _dereq_("../is-value"); - -var keys = Object.keys; - -module.exports = function (object) { return keys(isValue(object) ? Object(object) : object); }; - -},{"../is-value":194}],198:[function(_dereq_,module,exports){ -"use strict"; - -var callable = _dereq_("./valid-callable") - , forEach = _dereq_("./for-each") - , call = Function.prototype.call; - -module.exports = function (obj, cb /*, thisArg*/) { - var result = {}, thisArg = arguments[2]; - callable(cb); - forEach(obj, function (value, key, targetObj, index) { - result[key] = call.call(cb, thisArg, value, key, targetObj, index); - }); - return result; -}; - -},{"./for-each":191,"./valid-callable":203}],199:[function(_dereq_,module,exports){ -"use strict"; - -var isValue = _dereq_("./is-value"); - -var forEach = Array.prototype.forEach, create = Object.create; - -var process = function (src, obj) { - var key; - for (key in src) obj[key] = src[key]; -}; - -// eslint-disable-next-line no-unused-vars -module.exports = function (opts1 /*, …options*/) { - var result = create(null); - forEach.call(arguments, function (options) { - if (!isValue(options)) return; - process(Object(options), result); - }); - return result; -}; - -},{"./is-value":194}],200:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = _dereq_("./is-implemented")() - ? Object.setPrototypeOf - : _dereq_("./shim"); - -},{"./is-implemented":201,"./shim":202}],201:[function(_dereq_,module,exports){ -"use strict"; - -var create = Object.create, getPrototypeOf = Object.getPrototypeOf, plainObject = {}; - -module.exports = function (/* CustomCreate*/) { - var setPrototypeOf = Object.setPrototypeOf, customCreate = arguments[0] || create; - if (typeof setPrototypeOf !== "function") return false; - return getPrototypeOf(setPrototypeOf(customCreate(null), plainObject)) === plainObject; -}; - -},{}],202:[function(_dereq_,module,exports){ -/* eslint no-proto: "off" */ - -// Big thanks to @WebReflection for sorting this out -// https://gist.github.com/WebReflection/5593554 - -"use strict"; - -var isObject = _dereq_("../is-object") - , value = _dereq_("../valid-value") - , objIsPrototypeOf = Object.prototype.isPrototypeOf - , defineProperty = Object.defineProperty - , nullDesc = { - configurable: true, - enumerable: false, - writable: true, - value: undefined -} - , validate; - -validate = function (obj, prototype) { - value(obj); - if (prototype === null || isObject(prototype)) return obj; - throw new TypeError("Prototype must be null or an object"); -}; - -module.exports = (function (status) { - var fn, set; - if (!status) return null; - if (status.level === 2) { - if (status.set) { - set = status.set; - fn = function (obj, prototype) { - set.call(validate(obj, prototype), prototype); - return obj; - }; - } else { - fn = function (obj, prototype) { - validate(obj, prototype).__proto__ = prototype; - return obj; - }; - } - } else { - fn = function self(obj, prototype) { - var isNullBase; - validate(obj, prototype); - isNullBase = objIsPrototypeOf.call(self.nullPolyfill, obj); - if (isNullBase) delete self.nullPolyfill.__proto__; - if (prototype === null) prototype = self.nullPolyfill; - obj.__proto__ = prototype; - if (isNullBase) defineProperty(self.nullPolyfill, "__proto__", nullDesc); - return obj; - }; - } - return Object.defineProperty(fn, "level", { - configurable: false, - enumerable: false, - writable: false, - value: status.level - }); -}( - (function () { - var tmpObj1 = Object.create(null) - , tmpObj2 = {} - , set - , desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); - - if (desc) { - try { - set = desc.set; // Opera crashes at this point - set.call(tmpObj1, tmpObj2); - } catch (ignore) {} - if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { set: set, level: 2 }; - } - - tmpObj1.__proto__ = tmpObj2; - if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { level: 2 }; - - tmpObj1 = {}; - tmpObj1.__proto__ = tmpObj2; - if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { level: 1 }; - - return false; - })() -)); - -_dereq_("../create"); - -},{"../create":190,"../is-object":193,"../valid-value":205}],203:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = function (fn) { - if (typeof fn !== "function") throw new TypeError(fn + " is not a function"); - return fn; -}; - -},{}],204:[function(_dereq_,module,exports){ -"use strict"; - -var isObject = _dereq_("./is-object"); - -module.exports = function (value) { - if (!isObject(value)) throw new TypeError(value + " is not an Object"); - return value; -}; - -},{"./is-object":193}],205:[function(_dereq_,module,exports){ -"use strict"; - -var isValue = _dereq_("./is-value"); - -module.exports = function (value) { - if (!isValue(value)) throw new TypeError("Cannot use null or undefined"); - return value; -}; - -},{"./is-value":194}],206:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = _dereq_("./is-implemented")() - ? String.prototype.contains - : _dereq_("./shim"); - -},{"./is-implemented":207,"./shim":208}],207:[function(_dereq_,module,exports){ -"use strict"; - -var str = "razdwatrzy"; - -module.exports = function () { - if (typeof str.contains !== "function") return false; - return (str.contains("dwa") === true) && (str.contains("foo") === false); -}; - -},{}],208:[function(_dereq_,module,exports){ -"use strict"; - -var indexOf = String.prototype.indexOf; - -module.exports = function (searchString/*, position*/) { - return indexOf.call(this, searchString, arguments[1]) > -1; -}; - -},{}],209:[function(_dereq_,module,exports){ -"use strict"; - -var objToString = Object.prototype.toString, id = objToString.call(""); - -module.exports = function (value) { - return ( - typeof value === "string" || - (value && - typeof value === "object" && - (value instanceof String || objToString.call(value) === id)) || - false - ); -}; - -},{}],210:[function(_dereq_,module,exports){ -"use strict"; - -var generated = Object.create(null), random = Math.random; - -module.exports = function () { - var str; - do { - str = random() - .toString(36) - .slice(2); - } while (generated[str]); - return str; -}; - -},{}],211:[function(_dereq_,module,exports){ -"use strict"; - -var setPrototypeOf = _dereq_("es5-ext/object/set-prototype-of") - , contains = _dereq_("es5-ext/string/#/contains") - , d = _dereq_("d") - , Symbol = _dereq_("es6-symbol") - , Iterator = _dereq_("./"); - -var defineProperty = Object.defineProperty, ArrayIterator; - -ArrayIterator = module.exports = function (arr, kind) { - if (!(this instanceof ArrayIterator)) throw new TypeError("Constructor requires 'new'"); - Iterator.call(this, arr); - if (!kind) kind = "value"; - else if (contains.call(kind, "key+value")) kind = "key+value"; - else if (contains.call(kind, "key")) kind = "key"; - else kind = "value"; - defineProperty(this, "__kind__", d("", kind)); -}; -if (setPrototypeOf) setPrototypeOf(ArrayIterator, Iterator); - -// Internal %ArrayIteratorPrototype% doesn't expose its constructor -delete ArrayIterator.prototype.constructor; - -ArrayIterator.prototype = Object.create(Iterator.prototype, { - _resolve: d(function (i) { - if (this.__kind__ === "value") return this.__list__[i]; - if (this.__kind__ === "key+value") return [i, this.__list__[i]]; - return i; - }) -}); -defineProperty(ArrayIterator.prototype, Symbol.toStringTag, d("c", "Array Iterator")); - -},{"./":214,"d":151,"es5-ext/object/set-prototype-of":200,"es5-ext/string/#/contains":206,"es6-symbol":219}],212:[function(_dereq_,module,exports){ -"use strict"; - -var isArguments = _dereq_("es5-ext/function/is-arguments") - , callable = _dereq_("es5-ext/object/valid-callable") - , isString = _dereq_("es5-ext/string/is-string") - , get = _dereq_("./get"); - -var isArray = Array.isArray, call = Function.prototype.call, some = Array.prototype.some; - -module.exports = function (iterable, cb /*, thisArg*/) { - var mode, thisArg = arguments[2], result, doBreak, broken, i, length, char, code; - if (isArray(iterable) || isArguments(iterable)) mode = "array"; - else if (isString(iterable)) mode = "string"; - else iterable = get(iterable); - - callable(cb); - doBreak = function () { - broken = true; - }; - if (mode === "array") { - some.call(iterable, function (value) { - call.call(cb, thisArg, value, doBreak); - return broken; - }); - return; - } - if (mode === "string") { - length = iterable.length; - for (i = 0; i < length; ++i) { - char = iterable[i]; - if (i + 1 < length) { - code = char.charCodeAt(0); - if (code >= 0xd800 && code <= 0xdbff) char += iterable[++i]; - } - call.call(cb, thisArg, char, doBreak); - if (broken) break; - } - return; - } - result = iterable.next(); - - while (!result.done) { - call.call(cb, thisArg, result.value, doBreak); - if (broken) return; - result = iterable.next(); - } -}; - -},{"./get":213,"es5-ext/function/is-arguments":177,"es5-ext/object/valid-callable":203,"es5-ext/string/is-string":209}],213:[function(_dereq_,module,exports){ -"use strict"; - -var isArguments = _dereq_("es5-ext/function/is-arguments") - , isString = _dereq_("es5-ext/string/is-string") - , ArrayIterator = _dereq_("./array") - , StringIterator = _dereq_("./string") - , iterable = _dereq_("./valid-iterable") - , iteratorSymbol = _dereq_("es6-symbol").iterator; - -module.exports = function (obj) { - if (typeof iterable(obj)[iteratorSymbol] === "function") return obj[iteratorSymbol](); - if (isArguments(obj)) return new ArrayIterator(obj); - if (isString(obj)) return new StringIterator(obj); - return new ArrayIterator(obj); -}; - -},{"./array":211,"./string":216,"./valid-iterable":217,"es5-ext/function/is-arguments":177,"es5-ext/string/is-string":209,"es6-symbol":219}],214:[function(_dereq_,module,exports){ -"use strict"; - -var clear = _dereq_("es5-ext/array/#/clear") - , assign = _dereq_("es5-ext/object/assign") - , callable = _dereq_("es5-ext/object/valid-callable") - , value = _dereq_("es5-ext/object/valid-value") - , d = _dereq_("d") - , autoBind = _dereq_("d/auto-bind") - , Symbol = _dereq_("es6-symbol"); - -var defineProperty = Object.defineProperty, defineProperties = Object.defineProperties, Iterator; - -module.exports = Iterator = function (list, context) { - if (!(this instanceof Iterator)) throw new TypeError("Constructor requires 'new'"); - defineProperties(this, { - __list__: d("w", value(list)), - __context__: d("w", context), - __nextIndex__: d("w", 0) - }); - if (!context) return; - callable(context.on); - context.on("_add", this._onAdd); - context.on("_delete", this._onDelete); - context.on("_clear", this._onClear); -}; - -// Internal %IteratorPrototype% doesn't expose its constructor -delete Iterator.prototype.constructor; - -defineProperties( - Iterator.prototype, - assign( - { - _next: d(function () { - var i; - if (!this.__list__) return undefined; - if (this.__redo__) { - i = this.__redo__.shift(); - if (i !== undefined) return i; - } - if (this.__nextIndex__ < this.__list__.length) return this.__nextIndex__++; - this._unBind(); - return undefined; - }), - next: d(function () { - return this._createResult(this._next()); - }), - _createResult: d(function (i) { - if (i === undefined) return { done: true, value: undefined }; - return { done: false, value: this._resolve(i) }; - }), - _resolve: d(function (i) { - return this.__list__[i]; - }), - _unBind: d(function () { - this.__list__ = null; - delete this.__redo__; - if (!this.__context__) return; - this.__context__.off("_add", this._onAdd); - this.__context__.off("_delete", this._onDelete); - this.__context__.off("_clear", this._onClear); - this.__context__ = null; - }), - toString: d(function () { - return "[object " + (this[Symbol.toStringTag] || "Object") + "]"; - }) - }, - autoBind({ - _onAdd: d(function (index) { - if (index >= this.__nextIndex__) return; - ++this.__nextIndex__; - if (!this.__redo__) { - defineProperty(this, "__redo__", d("c", [index])); - return; - } - this.__redo__.forEach(function (redo, i) { - if (redo >= index) this.__redo__[i] = ++redo; - }, this); - this.__redo__.push(index); - }), - _onDelete: d(function (index) { - var i; - if (index >= this.__nextIndex__) return; - --this.__nextIndex__; - if (!this.__redo__) return; - i = this.__redo__.indexOf(index); - if (i !== -1) this.__redo__.splice(i, 1); - this.__redo__.forEach(function (redo, j) { - if (redo > index) this.__redo__[j] = --redo; - }, this); - }), - _onClear: d(function () { - if (this.__redo__) clear.call(this.__redo__); - this.__nextIndex__ = 0; - }) - }) - ) -); - -defineProperty( - Iterator.prototype, - Symbol.iterator, - d(function () { - return this; - }) -); - -},{"d":151,"d/auto-bind":150,"es5-ext/array/#/clear":173,"es5-ext/object/assign":186,"es5-ext/object/valid-callable":203,"es5-ext/object/valid-value":205,"es6-symbol":219}],215:[function(_dereq_,module,exports){ -"use strict"; - -var isArguments = _dereq_("es5-ext/function/is-arguments") - , isValue = _dereq_("es5-ext/object/is-value") - , isString = _dereq_("es5-ext/string/is-string"); - -var iteratorSymbol = _dereq_("es6-symbol").iterator - , isArray = Array.isArray; - -module.exports = function (value) { - if (!isValue(value)) return false; - if (isArray(value)) return true; - if (isString(value)) return true; - if (isArguments(value)) return true; - return typeof value[iteratorSymbol] === "function"; -}; - -},{"es5-ext/function/is-arguments":177,"es5-ext/object/is-value":194,"es5-ext/string/is-string":209,"es6-symbol":219}],216:[function(_dereq_,module,exports){ -// Thanks @mathiasbynens -// http://mathiasbynens.be/notes/javascript-unicode#iterating-over-symbols - -"use strict"; - -var setPrototypeOf = _dereq_("es5-ext/object/set-prototype-of") - , d = _dereq_("d") - , Symbol = _dereq_("es6-symbol") - , Iterator = _dereq_("./"); - -var defineProperty = Object.defineProperty, StringIterator; - -StringIterator = module.exports = function (str) { - if (!(this instanceof StringIterator)) throw new TypeError("Constructor requires 'new'"); - str = String(str); - Iterator.call(this, str); - defineProperty(this, "__length__", d("", str.length)); -}; -if (setPrototypeOf) setPrototypeOf(StringIterator, Iterator); - -// Internal %ArrayIteratorPrototype% doesn't expose its constructor -delete StringIterator.prototype.constructor; - -StringIterator.prototype = Object.create(Iterator.prototype, { - _next: d(function () { - if (!this.__list__) return undefined; - if (this.__nextIndex__ < this.__length__) return this.__nextIndex__++; - this._unBind(); - return undefined; - }), - _resolve: d(function (i) { - var char = this.__list__[i], code; - if (this.__nextIndex__ === this.__length__) return char; - code = char.charCodeAt(0); - if (code >= 0xd800 && code <= 0xdbff) return char + this.__list__[this.__nextIndex__++]; - return char; - }) -}); -defineProperty(StringIterator.prototype, Symbol.toStringTag, d("c", "String Iterator")); - -},{"./":214,"d":151,"es5-ext/object/set-prototype-of":200,"es6-symbol":219}],217:[function(_dereq_,module,exports){ -"use strict"; - -var isIterable = _dereq_("./is-iterable"); - -module.exports = function (value) { - if (!isIterable(value)) throw new TypeError(value + " is not iterable"); - return value; -}; - -},{"./is-iterable":215}],218:[function(_dereq_,module,exports){ -(function (process,global){ -/*! - * @overview es6-promise - a tiny implementation of Promises/A+. - * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) - * @license Licensed under MIT license - * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE - * @version 3.3.1 - */ - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.ES6Promise = factory()); -}(this, (function () { 'use strict'; - -function objectOrFunction(x) { - return typeof x === 'function' || typeof x === 'object' && x !== null; -} - -function isFunction(x) { - return typeof x === 'function'; -} - -var _isArray = undefined; -if (!Array.isArray) { - _isArray = function (x) { - return Object.prototype.toString.call(x) === '[object Array]'; - }; -} else { - _isArray = Array.isArray; -} - -var isArray = _isArray; - -var len = 0; -var vertxNext = undefined; -var customSchedulerFn = undefined; - -var asap = function asap(callback, arg) { - queue[len] = callback; - queue[len + 1] = arg; - len += 2; - if (len === 2) { - // If len is 2, that means that we need to schedule an async flush. - // If additional callbacks are queued before the queue is flushed, they - // will be processed by this flush that we are scheduling. - if (customSchedulerFn) { - customSchedulerFn(flush); - } else { - scheduleFlush(); - } - } -}; - -function setScheduler(scheduleFn) { - customSchedulerFn = scheduleFn; -} - -function setAsap(asapFn) { - asap = asapFn; -} - -var browserWindow = typeof window !== 'undefined' ? window : undefined; -var browserGlobal = browserWindow || {}; -var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; -var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]'; - -// test for web worker but not in IE10 -var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; - -// node -function useNextTick() { - // node version 0.10.x displays a deprecation warning when nextTick is used recursively - // see https://github.com/cujojs/when/issues/410 for details - return function () { - return process.nextTick(flush); - }; -} - -// vertx -function useVertxTimer() { - return function () { - vertxNext(flush); - }; -} - -function useMutationObserver() { - var iterations = 0; - var observer = new BrowserMutationObserver(flush); - var node = document.createTextNode(''); - observer.observe(node, { characterData: true }); - - return function () { - node.data = iterations = ++iterations % 2; - }; -} - -// web worker -function useMessageChannel() { - var channel = new MessageChannel(); - channel.port1.onmessage = flush; - return function () { - return channel.port2.postMessage(0); - }; -} - -function useSetTimeout() { - // Store setTimeout reference so es6-promise will be unaffected by - // other code modifying setTimeout (like sinon.useFakeTimers()) - var globalSetTimeout = setTimeout; - return function () { - return globalSetTimeout(flush, 1); - }; -} - -var queue = new Array(1000); -function flush() { - for (var i = 0; i < len; i += 2) { - var callback = queue[i]; - var arg = queue[i + 1]; - - callback(arg); - - queue[i] = undefined; - queue[i + 1] = undefined; - } - - len = 0; -} - -function attemptVertx() { - try { - var r = _dereq_; - var vertx = r('vertx'); - vertxNext = vertx.runOnLoop || vertx.runOnContext; - return useVertxTimer(); - } catch (e) { - return useSetTimeout(); - } -} - -var scheduleFlush = undefined; -// Decide what async method to use to triggering processing of queued callbacks: -if (isNode) { - scheduleFlush = useNextTick(); -} else if (BrowserMutationObserver) { - scheduleFlush = useMutationObserver(); -} else if (isWorker) { - scheduleFlush = useMessageChannel(); -} else if (browserWindow === undefined && typeof _dereq_ === 'function') { - scheduleFlush = attemptVertx(); -} else { - scheduleFlush = useSetTimeout(); -} - -function then(onFulfillment, onRejection) { - var _arguments = arguments; - - var parent = this; - - var child = new this.constructor(noop); - - if (child[PROMISE_ID] === undefined) { - makePromise(child); - } - - var _state = parent._state; - - if (_state) { - (function () { - var callback = _arguments[_state - 1]; - asap(function () { - return invokeCallback(_state, child, callback, parent._result); - }); - })(); - } else { - subscribe(parent, child, onFulfillment, onRejection); - } - - return child; -} - -/** - `Promise.resolve` returns a promise that will become resolved with the - passed `value`. It is shorthand for the following: - - ```javascript - let promise = new Promise(function(resolve, reject){ - resolve(1); - }); - - promise.then(function(value){ - // value === 1 - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - let promise = Promise.resolve(1); - - promise.then(function(value){ - // value === 1 - }); - ``` - - @method resolve - @static - @param {Any} value value that the returned promise will be resolved with - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` -*/ -function resolve(object) { - /*jshint validthis:true */ - var Constructor = this; - - if (object && typeof object === 'object' && object.constructor === Constructor) { - return object; - } - - var promise = new Constructor(noop); - _resolve(promise, object); - return promise; -} - -var PROMISE_ID = Math.random().toString(36).substring(16); - -function noop() {} - -var PENDING = void 0; -var FULFILLED = 1; -var REJECTED = 2; - -var GET_THEN_ERROR = new ErrorObject(); - -function selfFulfillment() { - return new TypeError("You cannot resolve a promise with itself"); -} - -function cannotReturnOwn() { - return new TypeError('A promises callback cannot return that same promise.'); -} - -function getThen(promise) { - try { - return promise.then; - } catch (error) { - GET_THEN_ERROR.error = error; - return GET_THEN_ERROR; - } -} - -function tryThen(then, value, fulfillmentHandler, rejectionHandler) { - try { - then.call(value, fulfillmentHandler, rejectionHandler); - } catch (e) { - return e; - } -} - -function handleForeignThenable(promise, thenable, then) { - asap(function (promise) { - var sealed = false; - var error = tryThen(then, thenable, function (value) { - if (sealed) { - return; - } - sealed = true; - if (thenable !== value) { - _resolve(promise, value); - } else { - fulfill(promise, value); - } - }, function (reason) { - if (sealed) { - return; - } - sealed = true; - - _reject(promise, reason); - }, 'Settle: ' + (promise._label || ' unknown promise')); - - if (!sealed && error) { - sealed = true; - _reject(promise, error); - } - }, promise); -} - -function handleOwnThenable(promise, thenable) { - if (thenable._state === FULFILLED) { - fulfill(promise, thenable._result); - } else if (thenable._state === REJECTED) { - _reject(promise, thenable._result); - } else { - subscribe(thenable, undefined, function (value) { - return _resolve(promise, value); - }, function (reason) { - return _reject(promise, reason); - }); - } -} - -function handleMaybeThenable(promise, maybeThenable, then$$) { - if (maybeThenable.constructor === promise.constructor && then$$ === then && maybeThenable.constructor.resolve === resolve) { - handleOwnThenable(promise, maybeThenable); - } else { - if (then$$ === GET_THEN_ERROR) { - _reject(promise, GET_THEN_ERROR.error); - } else if (then$$ === undefined) { - fulfill(promise, maybeThenable); - } else if (isFunction(then$$)) { - handleForeignThenable(promise, maybeThenable, then$$); - } else { - fulfill(promise, maybeThenable); - } - } -} - -function _resolve(promise, value) { - if (promise === value) { - _reject(promise, selfFulfillment()); - } else if (objectOrFunction(value)) { - handleMaybeThenable(promise, value, getThen(value)); - } else { - fulfill(promise, value); - } -} - -function publishRejection(promise) { - if (promise._onerror) { - promise._onerror(promise._result); - } - - publish(promise); -} - -function fulfill(promise, value) { - if (promise._state !== PENDING) { - return; - } - - promise._result = value; - promise._state = FULFILLED; - - if (promise._subscribers.length !== 0) { - asap(publish, promise); - } -} - -function _reject(promise, reason) { - if (promise._state !== PENDING) { - return; - } - promise._state = REJECTED; - promise._result = reason; - - asap(publishRejection, promise); -} - -function subscribe(parent, child, onFulfillment, onRejection) { - var _subscribers = parent._subscribers; - var length = _subscribers.length; - - parent._onerror = null; - - _subscribers[length] = child; - _subscribers[length + FULFILLED] = onFulfillment; - _subscribers[length + REJECTED] = onRejection; - - if (length === 0 && parent._state) { - asap(publish, parent); - } -} - -function publish(promise) { - var subscribers = promise._subscribers; - var settled = promise._state; - - if (subscribers.length === 0) { - return; - } - - var child = undefined, - callback = undefined, - detail = promise._result; - - for (var i = 0; i < subscribers.length; i += 3) { - child = subscribers[i]; - callback = subscribers[i + settled]; - - if (child) { - invokeCallback(settled, child, callback, detail); - } else { - callback(detail); - } - } - - promise._subscribers.length = 0; -} - -function ErrorObject() { - this.error = null; -} - -var TRY_CATCH_ERROR = new ErrorObject(); - -function tryCatch(callback, detail) { - try { - return callback(detail); - } catch (e) { - TRY_CATCH_ERROR.error = e; - return TRY_CATCH_ERROR; - } -} - -function invokeCallback(settled, promise, callback, detail) { - var hasCallback = isFunction(callback), - value = undefined, - error = undefined, - succeeded = undefined, - failed = undefined; - - if (hasCallback) { - value = tryCatch(callback, detail); - - if (value === TRY_CATCH_ERROR) { - failed = true; - error = value.error; - value = null; - } else { - succeeded = true; - } - - if (promise === value) { - _reject(promise, cannotReturnOwn()); - return; - } - } else { - value = detail; - succeeded = true; - } - - if (promise._state !== PENDING) { - // noop - } else if (hasCallback && succeeded) { - _resolve(promise, value); - } else if (failed) { - _reject(promise, error); - } else if (settled === FULFILLED) { - fulfill(promise, value); - } else if (settled === REJECTED) { - _reject(promise, value); - } -} - -function initializePromise(promise, resolver) { - try { - resolver(function resolvePromise(value) { - _resolve(promise, value); - }, function rejectPromise(reason) { - _reject(promise, reason); - }); - } catch (e) { - _reject(promise, e); - } -} - -var id = 0; -function nextId() { - return id++; -} - -function makePromise(promise) { - promise[PROMISE_ID] = id++; - promise._state = undefined; - promise._result = undefined; - promise._subscribers = []; -} - -function Enumerator(Constructor, input) { - this._instanceConstructor = Constructor; - this.promise = new Constructor(noop); - - if (!this.promise[PROMISE_ID]) { - makePromise(this.promise); - } - - if (isArray(input)) { - this._input = input; - this.length = input.length; - this._remaining = input.length; - - this._result = new Array(this.length); - - if (this.length === 0) { - fulfill(this.promise, this._result); - } else { - this.length = this.length || 0; - this._enumerate(); - if (this._remaining === 0) { - fulfill(this.promise, this._result); - } - } - } else { - _reject(this.promise, validationError()); - } -} - -function validationError() { - return new Error('Array Methods must be provided an Array'); -}; - -Enumerator.prototype._enumerate = function () { - var length = this.length; - var _input = this._input; - - for (var i = 0; this._state === PENDING && i < length; i++) { - this._eachEntry(_input[i], i); - } -}; - -Enumerator.prototype._eachEntry = function (entry, i) { - var c = this._instanceConstructor; - var resolve$$ = c.resolve; - - if (resolve$$ === resolve) { - var _then = getThen(entry); - - if (_then === then && entry._state !== PENDING) { - this._settledAt(entry._state, i, entry._result); - } else if (typeof _then !== 'function') { - this._remaining--; - this._result[i] = entry; - } else if (c === Promise) { - var promise = new c(noop); - handleMaybeThenable(promise, entry, _then); - this._willSettleAt(promise, i); - } else { - this._willSettleAt(new c(function (resolve$$) { - return resolve$$(entry); - }), i); - } - } else { - this._willSettleAt(resolve$$(entry), i); - } -}; - -Enumerator.prototype._settledAt = function (state, i, value) { - var promise = this.promise; - - if (promise._state === PENDING) { - this._remaining--; - - if (state === REJECTED) { - _reject(promise, value); - } else { - this._result[i] = value; - } - } - - if (this._remaining === 0) { - fulfill(promise, this._result); - } -}; - -Enumerator.prototype._willSettleAt = function (promise, i) { - var enumerator = this; - - subscribe(promise, undefined, function (value) { - return enumerator._settledAt(FULFILLED, i, value); - }, function (reason) { - return enumerator._settledAt(REJECTED, i, reason); - }); -}; - -/** - `Promise.all` accepts an array of promises, and returns a new promise which - is fulfilled with an array of fulfillment values for the passed promises, or - rejected with the reason of the first passed promise to be rejected. It casts all - elements of the passed iterable to promises as it runs this algorithm. - - Example: - - ```javascript - let promise1 = resolve(1); - let promise2 = resolve(2); - let promise3 = resolve(3); - let promises = [ promise1, promise2, promise3 ]; - - Promise.all(promises).then(function(array){ - // The array here would be [ 1, 2, 3 ]; - }); - ``` - - If any of the `promises` given to `all` are rejected, the first promise - that is rejected will be given as an argument to the returned promises's - rejection handler. For example: - - Example: - - ```javascript - let promise1 = resolve(1); - let promise2 = reject(new Error("2")); - let promise3 = reject(new Error("3")); - let promises = [ promise1, promise2, promise3 ]; - - Promise.all(promises).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(error) { - // error.message === "2" - }); - ``` - - @method all - @static - @param {Array} entries array of promises - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all `promises` have been - fulfilled, or rejected if any of them become rejected. - @static -*/ -function all(entries) { - return new Enumerator(this, entries).promise; -} - -/** - `Promise.race` returns a new promise which is settled in the same way as the - first passed promise to settle. - - Example: - - ```javascript - let promise1 = new Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - let promise2 = new Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 2'); - }, 100); - }); - - Promise.race([promise1, promise2]).then(function(result){ - // result === 'promise 2' because it was resolved before promise1 - // was resolved. - }); - ``` - - `Promise.race` is deterministic in that only the state of the first - settled promise matters. For example, even if other promises given to the - `promises` array argument are resolved, but the first settled promise has - become rejected before the other promises became fulfilled, the returned - promise will become rejected: - - ```javascript - let promise1 = new Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - let promise2 = new Promise(function(resolve, reject){ - setTimeout(function(){ - reject(new Error('promise 2')); - }, 100); - }); - - Promise.race([promise1, promise2]).then(function(result){ - // Code here never runs - }, function(reason){ - // reason.message === 'promise 2' because promise 2 became rejected before - // promise 1 became fulfilled - }); - ``` - - An example real-world use case is implementing timeouts: - - ```javascript - Promise.race([ajax('foo.json'), timeout(5000)]) - ``` - - @method race - @static - @param {Array} promises array of promises to observe - Useful for tooling. - @return {Promise} a promise which settles in the same way as the first passed - promise to settle. -*/ -function race(entries) { - /*jshint validthis:true */ - var Constructor = this; - - if (!isArray(entries)) { - return new Constructor(function (_, reject) { - return reject(new TypeError('You must pass an array to race.')); - }); - } else { - return new Constructor(function (resolve, reject) { - var length = entries.length; - for (var i = 0; i < length; i++) { - Constructor.resolve(entries[i]).then(resolve, reject); - } - }); - } -} - -/** - `Promise.reject` returns a promise rejected with the passed `reason`. - It is shorthand for the following: - - ```javascript - let promise = new Promise(function(resolve, reject){ - reject(new Error('WHOOPS')); - }); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - let promise = Promise.reject(new Error('WHOOPS')); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - @method reject - @static - @param {Any} reason value that the returned promise will be rejected with. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. -*/ -function reject(reason) { - /*jshint validthis:true */ - var Constructor = this; - var promise = new Constructor(noop); - _reject(promise, reason); - return promise; -} - -function needsResolver() { - throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); -} - -function needsNew() { - throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); -} - -/** - Promise objects represent the eventual result of an asynchronous operation. The - primary way of interacting with a promise is through its `then` method, which - registers callbacks to receive either a promise's eventual value or the reason - why the promise cannot be fulfilled. - - Terminology - ----------- - - - `promise` is an object or function with a `then` method whose behavior conforms to this specification. - - `thenable` is an object or function that defines a `then` method. - - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). - - `exception` is a value that is thrown using the throw statement. - - `reason` is a value that indicates why a promise was rejected. - - `settled` the final resting state of a promise, fulfilled or rejected. - - A promise can be in one of three states: pending, fulfilled, or rejected. - - Promises that are fulfilled have a fulfillment value and are in the fulfilled - state. Promises that are rejected have a rejection reason and are in the - rejected state. A fulfillment value is never a thenable. - - Promises can also be said to *resolve* a value. If this value is also a - promise, then the original promise's settled state will match the value's - settled state. So a promise that *resolves* a promise that rejects will - itself reject, and a promise that *resolves* a promise that fulfills will - itself fulfill. - - - Basic Usage: - ------------ - - ```js - let promise = new Promise(function(resolve, reject) { - // on success - resolve(value); - - // on failure - reject(reason); - }); - - promise.then(function(value) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Advanced Usage: - --------------- - - Promises shine when abstracting away asynchronous interactions such as - `XMLHttpRequest`s. - - ```js - function getJSON(url) { - return new Promise(function(resolve, reject){ - let xhr = new XMLHttpRequest(); - - xhr.open('GET', url); - xhr.onreadystatechange = handler; - xhr.responseType = 'json'; - xhr.setRequestHeader('Accept', 'application/json'); - xhr.send(); - - function handler() { - if (this.readyState === this.DONE) { - if (this.status === 200) { - resolve(this.response); - } else { - reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); - } - } - }; - }); - } - - getJSON('/posts.json').then(function(json) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Unlike callbacks, promises are great composable primitives. - - ```js - Promise.all([ - getJSON('/posts'), - getJSON('/comments') - ]).then(function(values){ - values[0] // => postsJSON - values[1] // => commentsJSON - - return values; - }); - ``` - - @class Promise - @param {function} resolver - Useful for tooling. - @constructor -*/ -function Promise(resolver) { - this[PROMISE_ID] = nextId(); - this._result = this._state = undefined; - this._subscribers = []; - - if (noop !== resolver) { - typeof resolver !== 'function' && needsResolver(); - this instanceof Promise ? initializePromise(this, resolver) : needsNew(); - } -} - -Promise.all = all; -Promise.race = race; -Promise.resolve = resolve; -Promise.reject = reject; -Promise._setScheduler = setScheduler; -Promise._setAsap = setAsap; -Promise._asap = asap; - -Promise.prototype = { - constructor: Promise, - - /** - The primary way of interacting with a promise is through its `then` method, - which registers callbacks to receive either a promise's eventual value or the - reason why the promise cannot be fulfilled. - - ```js - findUser().then(function(user){ - // user is available - }, function(reason){ - // user is unavailable, and you are given the reason why - }); - ``` - - Chaining - -------- - - The return value of `then` is itself a promise. This second, 'downstream' - promise is resolved with the return value of the first promise's fulfillment - or rejection handler, or rejected if the handler throws an exception. - - ```js - findUser().then(function (user) { - return user.name; - }, function (reason) { - return 'default name'; - }).then(function (userName) { - // If `findUser` fulfilled, `userName` will be the user's name, otherwise it - // will be `'default name'` - }); - - findUser().then(function (user) { - throw new Error('Found user, but still unhappy'); - }, function (reason) { - throw new Error('`findUser` rejected and we're unhappy'); - }).then(function (value) { - // never reached - }, function (reason) { - // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. - // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. - }); - ``` - If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. - - ```js - findUser().then(function (user) { - throw new PedagogicalException('Upstream error'); - }).then(function (value) { - // never reached - }).then(function (value) { - // never reached - }, function (reason) { - // The `PedgagocialException` is propagated all the way down to here - }); - ``` - - Assimilation - ------------ - - Sometimes the value you want to propagate to a downstream promise can only be - retrieved asynchronously. This can be achieved by returning a promise in the - fulfillment or rejection handler. The downstream promise will then be pending - until the returned promise is settled. This is called *assimilation*. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // The user's comments are now available - }); - ``` - - If the assimliated promise rejects, then the downstream promise will also reject. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // If `findCommentsByAuthor` fulfills, we'll have the value here - }, function (reason) { - // If `findCommentsByAuthor` rejects, we'll have the reason here - }); - ``` - - Simple Example - -------------- - - Synchronous Example - - ```javascript - let result; - - try { - result = findResult(); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - findResult(function(result, err){ - if (err) { - // failure - } else { - // success - } - }); - ``` - - Promise Example; - - ```javascript - findResult().then(function(result){ - // success - }, function(reason){ - // failure - }); - ``` - - Advanced Example - -------------- - - Synchronous Example - - ```javascript - let author, books; - - try { - author = findAuthor(); - books = findBooksByAuthor(author); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - - function foundBooks(books) { - - } - - function failure(reason) { - - } - - findAuthor(function(author, err){ - if (err) { - failure(err); - // failure - } else { - try { - findBoooksByAuthor(author, function(books, err) { - if (err) { - failure(err); - } else { - try { - foundBooks(books); - } catch(reason) { - failure(reason); - } - } - }); - } catch(error) { - failure(err); - } - // success - } - }); - ``` - - Promise Example; - - ```javascript - findAuthor(). - then(findBooksByAuthor). - then(function(books){ - // found books - }).catch(function(reason){ - // something went wrong - }); - ``` - - @method then - @param {Function} onFulfilled - @param {Function} onRejected - Useful for tooling. - @return {Promise} - */ - then: then, - - /** - `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same - as the catch block of a try/catch statement. - - ```js - function findAuthor(){ - throw new Error('couldn't find that author'); - } - - // synchronous - try { - findAuthor(); - } catch(reason) { - // something went wrong - } - - // async with promises - findAuthor().catch(function(reason){ - // something went wrong - }); - ``` - - @method catch - @param {Function} onRejection - Useful for tooling. - @return {Promise} - */ - 'catch': function _catch(onRejection) { - return this.then(null, onRejection); - } -}; - -function polyfill() { - var local = undefined; - - if (typeof global !== 'undefined') { - local = global; - } else if (typeof self !== 'undefined') { - local = self; - } else { - try { - local = Function('return this')(); - } catch (e) { - throw new Error('polyfill failed because global object is unavailable in this environment'); - } - } - - var P = local.Promise; - - if (P) { - var promiseToString = null; - try { - promiseToString = Object.prototype.toString.call(P.resolve()); - } catch (e) { - // silently ignored - } - - if (promiseToString === '[object Promise]' && !P.cast) { - return; - } - } - - local.Promise = Promise; -} - -polyfill(); -// Strange compat.. -Promise.polyfill = polyfill; -Promise.Promise = Promise; - -return Promise; - -}))); - -}).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":482}],219:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = _dereq_('./is-implemented')() ? Symbol : _dereq_('./polyfill'); - -},{"./is-implemented":220,"./polyfill":222}],220:[function(_dereq_,module,exports){ -'use strict'; - -var validTypes = { object: true, symbol: true }; - -module.exports = function () { - var symbol; - if (typeof Symbol !== 'function') return false; - symbol = Symbol('test symbol'); - try { String(symbol); } catch (e) { return false; } - - // Return 'true' also for polyfills - if (!validTypes[typeof Symbol.iterator]) return false; - if (!validTypes[typeof Symbol.toPrimitive]) return false; - if (!validTypes[typeof Symbol.toStringTag]) return false; - - return true; -}; - -},{}],221:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = function (x) { - if (!x) return false; - if (typeof x === 'symbol') return true; - if (!x.constructor) return false; - if (x.constructor.name !== 'Symbol') return false; - return (x[x.constructor.toStringTag] === 'Symbol'); -}; - -},{}],222:[function(_dereq_,module,exports){ -// ES2015 Symbol polyfill for environments that do not (or partially) support it - -'use strict'; - -var d = _dereq_('d') - , validateSymbol = _dereq_('./validate-symbol') - - , create = Object.create, defineProperties = Object.defineProperties - , defineProperty = Object.defineProperty, objPrototype = Object.prototype - , NativeSymbol, SymbolPolyfill, HiddenSymbol, globalSymbols = create(null) - , isNativeSafe; - -if (typeof Symbol === 'function') { - NativeSymbol = Symbol; - try { - String(NativeSymbol()); - isNativeSafe = true; - } catch (ignore) {} -} - -var generateName = (function () { - var created = create(null); - return function (desc) { - var postfix = 0, name, ie11BugWorkaround; - while (created[desc + (postfix || '')]) ++postfix; - desc += (postfix || ''); - created[desc] = true; - name = '@@' + desc; - defineProperty(objPrototype, name, d.gs(null, function (value) { - // For IE11 issue see: - // https://connect.microsoft.com/IE/feedbackdetail/view/1928508/ - // ie11-broken-getters-on-dom-objects - // https://github.com/medikoo/es6-symbol/issues/12 - if (ie11BugWorkaround) return; - ie11BugWorkaround = true; - defineProperty(this, name, d(value)); - ie11BugWorkaround = false; - })); - return name; - }; -}()); - -// Internal constructor (not one exposed) for creating Symbol instances. -// This one is used to ensure that `someSymbol instanceof Symbol` always return false -HiddenSymbol = function Symbol(description) { - if (this instanceof HiddenSymbol) throw new TypeError('Symbol is not a constructor'); - return SymbolPolyfill(description); -}; - -// Exposed `Symbol` constructor -// (returns instances of HiddenSymbol) -module.exports = SymbolPolyfill = function Symbol(description) { - var symbol; - if (this instanceof Symbol) throw new TypeError('Symbol is not a constructor'); - if (isNativeSafe) return NativeSymbol(description); - symbol = create(HiddenSymbol.prototype); - description = (description === undefined ? '' : String(description)); - return defineProperties(symbol, { - __description__: d('', description), - __name__: d('', generateName(description)) - }); -}; -defineProperties(SymbolPolyfill, { - for: d(function (key) { - if (globalSymbols[key]) return globalSymbols[key]; - return (globalSymbols[key] = SymbolPolyfill(String(key))); - }), - keyFor: d(function (s) { - var key; - validateSymbol(s); - for (key in globalSymbols) if (globalSymbols[key] === s) return key; - }), - - // To ensure proper interoperability with other native functions (e.g. Array.from) - // fallback to eventual native implementation of given symbol - hasInstance: d('', (NativeSymbol && NativeSymbol.hasInstance) || SymbolPolyfill('hasInstance')), - isConcatSpreadable: d('', (NativeSymbol && NativeSymbol.isConcatSpreadable) || - SymbolPolyfill('isConcatSpreadable')), - iterator: d('', (NativeSymbol && NativeSymbol.iterator) || SymbolPolyfill('iterator')), - match: d('', (NativeSymbol && NativeSymbol.match) || SymbolPolyfill('match')), - replace: d('', (NativeSymbol && NativeSymbol.replace) || SymbolPolyfill('replace')), - search: d('', (NativeSymbol && NativeSymbol.search) || SymbolPolyfill('search')), - species: d('', (NativeSymbol && NativeSymbol.species) || SymbolPolyfill('species')), - split: d('', (NativeSymbol && NativeSymbol.split) || SymbolPolyfill('split')), - toPrimitive: d('', (NativeSymbol && NativeSymbol.toPrimitive) || SymbolPolyfill('toPrimitive')), - toStringTag: d('', (NativeSymbol && NativeSymbol.toStringTag) || SymbolPolyfill('toStringTag')), - unscopables: d('', (NativeSymbol && NativeSymbol.unscopables) || SymbolPolyfill('unscopables')) -}); - -// Internal tweaks for real symbol producer -defineProperties(HiddenSymbol.prototype, { - constructor: d(SymbolPolyfill), - toString: d('', function () { return this.__name__; }) -}); - -// Proper implementation of methods exposed on Symbol.prototype -// They won't be accessible on produced symbol instances as they derive from HiddenSymbol.prototype -defineProperties(SymbolPolyfill.prototype, { - toString: d(function () { return 'Symbol (' + validateSymbol(this).__description__ + ')'; }), - valueOf: d(function () { return validateSymbol(this); }) -}); -defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toPrimitive, d('', function () { - var symbol = validateSymbol(this); - if (typeof symbol === 'symbol') return symbol; - return symbol.toString(); -})); -defineProperty(SymbolPolyfill.prototype, SymbolPolyfill.toStringTag, d('c', 'Symbol')); - -// Proper implementaton of toPrimitive and toStringTag for returned symbol instances -defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toStringTag, - d('c', SymbolPolyfill.prototype[SymbolPolyfill.toStringTag])); - -// Note: It's important to define `toPrimitive` as last one, as some implementations -// implement `toPrimitive` natively without implementing `toStringTag` (or other specified symbols) -// And that may invoke error in definition flow: -// See: https://github.com/medikoo/es6-symbol/issues/13#issuecomment-164146149 -defineProperty(HiddenSymbol.prototype, SymbolPolyfill.toPrimitive, - d('c', SymbolPolyfill.prototype[SymbolPolyfill.toPrimitive])); - -},{"./validate-symbol":223,"d":151}],223:[function(_dereq_,module,exports){ -'use strict'; - -var isSymbol = _dereq_('./is-symbol'); - -module.exports = function (value) { - if (!isSymbol(value)) throw new TypeError(value + " is not a symbol"); - return value; -}; - -},{"./is-symbol":221}],224:[function(_dereq_,module,exports){ -"use strict" - -module.exports = extractPlanes - -function extractPlanes(M, zNear, zFar) { - var z = zNear || 0.0 - var zf = zFar || 1.0 - return [ - [ M[12] + M[0], M[13] + M[1], M[14] + M[2], M[15] + M[3] ], - [ M[12] - M[0], M[13] - M[1], M[14] - M[2], M[15] - M[3] ], - [ M[12] + M[4], M[13] + M[5], M[14] + M[6], M[15] + M[7] ], - [ M[12] - M[4], M[13] - M[5], M[14] - M[6], M[15] - M[7] ], - [ z*M[12] + M[8], z*M[13] + M[9], z*M[14] + M[10], z*M[15] + M[11] ], - [ zf*M[12] - M[8], zf*M[13] - M[9], zf*M[14] - M[10], zf*M[15] - M[11] ] - ] -} -},{}],225:[function(_dereq_,module,exports){ -/** - * inspired by is-number - * but significantly simplified and sped up by ignoring number and string constructors - * ie these return false: - * new Number(1) - * new String('1') - */ - -'use strict'; - -var allBlankCharCodes = _dereq_('is-string-blank'); - -module.exports = function(n) { - var type = typeof n; - if(type === 'string') { - var original = n; - n = +n; - // whitespace strings cast to zero - filter them out - if(n===0 && allBlankCharCodes(original)) return false; - } - else if(type !== 'number') return false; - - return n - n < 1; -}; - -},{"is-string-blank":423}],226:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createFilteredVector - -var cubicHermite = _dereq_('cubic-hermite') -var bsearch = _dereq_('binary-search-bounds') - -function clamp(lo, hi, x) { - return Math.min(hi, Math.max(lo, x)) -} - -function FilteredVector(state0, velocity0, t0) { - this.dimension = state0.length - this.bounds = [ new Array(this.dimension), new Array(this.dimension) ] - for(var i=0; i= n-1) { - var ptr = state.length-1 - var tf = t - time[n-1] - for(var i=0; i= n-1) { - var ptr = state.length-1 - var tf = t - time[n-1] - for(var i=0; i=0; --i) { - if(velocity[--ptr]) { - return false - } - } - return true -} - -proto.jump = function(t) { - var t0 = this.lastT() - var d = this.dimension - if(t < t0 || arguments.length !== d+1) { - return - } - var state = this._state - var velocity = this._velocity - var ptr = state.length-this.dimension - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - this._time.push(t0, t) - for(var j=0; j<2; ++j) { - for(var i=0; i0; --i) { - state.push(clamp(lo[i-1], hi[i-1], arguments[i])) - velocity.push(0) - } -} - -proto.push = function(t) { - var t0 = this.lastT() - var d = this.dimension - if(t < t0 || arguments.length !== d+1) { - return - } - var state = this._state - var velocity = this._velocity - var ptr = state.length-this.dimension - var dt = t - t0 - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - var sf = (dt > 1e-6) ? 1/dt : 0 - this._time.push(t) - for(var i=d; i>0; --i) { - var xc = clamp(lo[i-1], hi[i-1], arguments[i]) - state.push(xc) - velocity.push((xc - state[ptr++]) * sf) - } -} - -proto.set = function(t) { - var d = this.dimension - if(t < this.lastT() || arguments.length !== d+1) { - return - } - var state = this._state - var velocity = this._velocity - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - this._time.push(t) - for(var i=d; i>0; --i) { - state.push(clamp(lo[i-1], hi[i-1], arguments[i])) - velocity.push(0) - } -} - -proto.move = function(t) { - var t0 = this.lastT() - var d = this.dimension - if(t <= t0 || arguments.length !== d+1) { - return - } - var state = this._state - var velocity = this._velocity - var statePtr = state.length - this.dimension - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - var dt = t - t0 - var sf = (dt > 1e-6) ? 1/dt : 0.0 - this._time.push(t) - for(var i=d; i>0; --i) { - var dx = arguments[i] - state.push(clamp(lo[i-1], hi[i-1], state[statePtr++] + dx)) - velocity.push(dx * sf) - } -} - -proto.idle = function(t) { - var t0 = this.lastT() - if(t < t0) { - return - } - var d = this.dimension - var state = this._state - var velocity = this._velocity - var statePtr = state.length-d - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - var dt = t - t0 - this._time.push(t) - for(var i=d-1; i>=0; --i) { - state.push(clamp(lo[i], hi[i], state[statePtr] + dt * velocity[statePtr])) - velocity.push(0) - statePtr += 1 - } -} - -function getZero(d) { - var result = new Array(d) - for(var i=0; i shape[0] - step[0]/2) (x = step[0]/2), (y += step[1]) - } - - return canvas -} - -},{"css-font/stringify":142}],229:[function(_dereq_,module,exports){ -'use strict' - -module.exports = measure - -measure.canvas = document.createElement('canvas') -measure.cache = {} - -function measure (font, o) { - if (!o) o = {} - - if (typeof font === 'string' || Array.isArray(font)) { - o.family = font - } - - var family = Array.isArray(o.family) ? o.family.join(', ') : o.family - if (!family) throw Error('`family` must be defined') - - var fs = o.size || o.fontSize || o.em || 48 - var weight = o.weight || o.fontWeight || '' - var style = o.style || o.fontStyle || '' - var font = [style, weight, fs].join(' ') + 'px ' + family - var origin = o.origin || 'top' - - if (measure.cache[family]) { - // return more precise values if cache has them - if (fs <= measure.cache[family].em) { - return applyOrigin(measure.cache[family], origin) - } - } - - var canvas = o.canvas || measure.canvas - var ctx = canvas.getContext('2d') - var chars = { - upper: o.upper !== undefined ? o.upper : 'H', - lower: o.lower !== undefined ? o.lower : 'x', - descent: o.descent !== undefined ? o.descent : 'p', - ascent: o.ascent !== undefined ? o.ascent : 'h', - tittle: o.tittle !== undefined ? o.tittle : 'i', - overshoot: o.overshoot !== undefined ? o.overshoot : 'O' - } - var l = Math.ceil(fs * 1.5) - canvas.height = l - canvas.width = l * .5 - ctx.font = font - - var char = 'H' - var result = { - top: 0 - } - - // measure line-height - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'top' - ctx.fillStyle = 'black' - ctx.fillText(char, 0, 0) - var topPx = firstTop(ctx.getImageData(0, 0, l, l)) - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'bottom' - ctx.fillText(char, 0, l) - var bottomPx = firstTop(ctx.getImageData(0, 0, l, l)) - result.lineHeight = - result.bottom = l - bottomPx + topPx - - // measure baseline - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'alphabetic' - ctx.fillText(char, 0, l) - var baselinePx = firstTop(ctx.getImageData(0, 0, l, l)) - var baseline = l - baselinePx - 1 + topPx - result.baseline = - result.alphabetic = baseline - - // measure median - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'middle' - ctx.fillText(char, 0, l * .5) - var medianPx = firstTop(ctx.getImageData(0, 0, l, l)) - result.median = - result.middle = l - medianPx - 1 + topPx - l * .5 - - // measure hanging - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'hanging' - ctx.fillText(char, 0, l * .5) - var hangingPx = firstTop(ctx.getImageData(0, 0, l, l)) - result.hanging = l - hangingPx - 1 + topPx - l * .5 - - // measure ideographic - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'ideographic' - ctx.fillText(char, 0, l) - var ideographicPx = firstTop(ctx.getImageData(0, 0, l, l)) - result.ideographic = l - ideographicPx - 1 + topPx - - // measure cap - if (chars.upper) { - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'top' - ctx.fillText(chars.upper, 0, 0) - result.upper = firstTop(ctx.getImageData(0, 0, l, l)) - result.capHeight = (result.baseline - result.upper) - } - - // measure x - if (chars.lower) { - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'top' - ctx.fillText(chars.lower, 0, 0) - result.lower = firstTop(ctx.getImageData(0, 0, l, l)) - result.xHeight = (result.baseline - result.lower) - } - - // measure tittle - if (chars.tittle) { - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'top' - ctx.fillText(chars.tittle, 0, 0) - result.tittle = firstTop(ctx.getImageData(0, 0, l, l)) - } - - // measure ascent - if (chars.ascent) { - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'top' - ctx.fillText(chars.ascent, 0, 0) - result.ascent = firstTop(ctx.getImageData(0, 0, l, l)) - } - - // measure descent - if (chars.descent) { - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'top' - ctx.fillText(chars.descent, 0, 0) - result.descent = firstBottom(ctx.getImageData(0, 0, l, l)) - } - - // measure overshoot - if (chars.overshoot) { - ctx.clearRect(0, 0, l, l) - ctx.textBaseline = 'top' - ctx.fillText(chars.overshoot, 0, 0) - var overshootPx = firstBottom(ctx.getImageData(0, 0, l, l)) - result.overshoot = overshootPx - baseline - } - - // normalize result - for (var name in result) { - result[name] /= fs - } - - result.em = fs - measure.cache[family] = result - - return applyOrigin(result, origin) -} - -function applyOrigin(obj, origin) { - var res = {} - if (typeof origin === 'string') origin = obj[origin] - for (var name in obj) { - if (name === 'em') continue - res[name] = obj[name] - origin - } - return res -} - -function firstTop(iData) { - var l = iData.height - var data = iData.data - for (var i = 3; i < data.length; i+=4) { - if (data[i] !== 0) { - return Math.floor((i - 3) *.25 / l) - } - } -} - -function firstBottom(iData) { - var l = iData.height - var data = iData.data - for (var i = data.length - 1; i > 0; i -= 4) { - if (data[i] !== 0) { - return Math.floor((i - 3) *.25 / l) - } - } -} - -},{}],230:[function(_dereq_,module,exports){ -"use strict" - -module.exports = createRBTree - -var RED = 0 -var BLACK = 1 - -function RBNode(color, key, value, left, right, count) { - this._color = color - this.key = key - this.value = value - this.left = left - this.right = right - this._count = count -} - -function cloneNode(node) { - return new RBNode(node._color, node.key, node.value, node.left, node.right, node._count) -} - -function repaint(color, node) { - return new RBNode(color, node.key, node.value, node.left, node.right, node._count) -} - -function recount(node) { - node._count = 1 + (node.left ? node.left._count : 0) + (node.right ? node.right._count : 0) -} - -function RedBlackTree(compare, root) { - this._compare = compare - this.root = root -} - -var proto = RedBlackTree.prototype - -Object.defineProperty(proto, "keys", { - get: function() { - var result = [] - this.forEach(function(k,v) { - result.push(k) - }) - return result - } -}) - -Object.defineProperty(proto, "values", { - get: function() { - var result = [] - this.forEach(function(k,v) { - result.push(v) - }) - return result - } -}) - -//Returns the number of nodes in the tree -Object.defineProperty(proto, "length", { - get: function() { - if(this.root) { - return this.root._count - } - return 0 - } -}) - -//Insert a new item into the tree -proto.insert = function(key, value) { - var cmp = this._compare - //Find point to insert new node at - var n = this.root - var n_stack = [] - var d_stack = [] - while(n) { - var d = cmp(key, n.key) - n_stack.push(n) - d_stack.push(d) - if(d <= 0) { - n = n.left - } else { - n = n.right - } - } - //Rebuild path to leaf node - n_stack.push(new RBNode(RED, key, value, null, null, 1)) - for(var s=n_stack.length-2; s>=0; --s) { - var n = n_stack[s] - if(d_stack[s] <= 0) { - n_stack[s] = new RBNode(n._color, n.key, n.value, n_stack[s+1], n.right, n._count+1) - } else { - n_stack[s] = new RBNode(n._color, n.key, n.value, n.left, n_stack[s+1], n._count+1) - } - } - //Rebalance tree using rotations - //console.log("start insert", key, d_stack) - for(var s=n_stack.length-1; s>1; --s) { - var p = n_stack[s-1] - var n = n_stack[s] - if(p._color === BLACK || n._color === BLACK) { - break - } - var pp = n_stack[s-2] - if(pp.left === p) { - if(p.left === n) { - var y = pp.right - if(y && y._color === RED) { - //console.log("LLr") - p._color = BLACK - pp.right = repaint(BLACK, y) - pp._color = RED - s -= 1 - } else { - //console.log("LLb") - pp._color = RED - pp.left = p.right - p._color = BLACK - p.right = pp - n_stack[s-2] = p - n_stack[s-1] = n - recount(pp) - recount(p) - if(s >= 3) { - var ppp = n_stack[s-3] - if(ppp.left === pp) { - ppp.left = p - } else { - ppp.right = p - } - } - break - } - } else { - var y = pp.right - if(y && y._color === RED) { - //console.log("LRr") - p._color = BLACK - pp.right = repaint(BLACK, y) - pp._color = RED - s -= 1 - } else { - //console.log("LRb") - p.right = n.left - pp._color = RED - pp.left = n.right - n._color = BLACK - n.left = p - n.right = pp - n_stack[s-2] = n - n_stack[s-1] = p - recount(pp) - recount(p) - recount(n) - if(s >= 3) { - var ppp = n_stack[s-3] - if(ppp.left === pp) { - ppp.left = n - } else { - ppp.right = n - } - } - break - } - } - } else { - if(p.right === n) { - var y = pp.left - if(y && y._color === RED) { - //console.log("RRr", y.key) - p._color = BLACK - pp.left = repaint(BLACK, y) - pp._color = RED - s -= 1 - } else { - //console.log("RRb") - pp._color = RED - pp.right = p.left - p._color = BLACK - p.left = pp - n_stack[s-2] = p - n_stack[s-1] = n - recount(pp) - recount(p) - if(s >= 3) { - var ppp = n_stack[s-3] - if(ppp.right === pp) { - ppp.right = p - } else { - ppp.left = p - } - } - break - } - } else { - var y = pp.left - if(y && y._color === RED) { - //console.log("RLr") - p._color = BLACK - pp.left = repaint(BLACK, y) - pp._color = RED - s -= 1 - } else { - //console.log("RLb") - p.left = n.right - pp._color = RED - pp.right = n.left - n._color = BLACK - n.right = p - n.left = pp - n_stack[s-2] = n - n_stack[s-1] = p - recount(pp) - recount(p) - recount(n) - if(s >= 3) { - var ppp = n_stack[s-3] - if(ppp.right === pp) { - ppp.right = n - } else { - ppp.left = n - } - } - break - } - } - } - } - //Return new tree - n_stack[0]._color = BLACK - return new RedBlackTree(cmp, n_stack[0]) -} - - -//Visit all nodes inorder -function doVisitFull(visit, node) { - if(node.left) { - var v = doVisitFull(visit, node.left) - if(v) { return v } - } - var v = visit(node.key, node.value) - if(v) { return v } - if(node.right) { - return doVisitFull(visit, node.right) - } -} - -//Visit half nodes in order -function doVisitHalf(lo, compare, visit, node) { - var l = compare(lo, node.key) - if(l <= 0) { - if(node.left) { - var v = doVisitHalf(lo, compare, visit, node.left) - if(v) { return v } - } - var v = visit(node.key, node.value) - if(v) { return v } - } - if(node.right) { - return doVisitHalf(lo, compare, visit, node.right) - } -} - -//Visit all nodes within a range -function doVisit(lo, hi, compare, visit, node) { - var l = compare(lo, node.key) - var h = compare(hi, node.key) - var v - if(l <= 0) { - if(node.left) { - v = doVisit(lo, hi, compare, visit, node.left) - if(v) { return v } - } - if(h > 0) { - v = visit(node.key, node.value) - if(v) { return v } - } - } - if(h > 0 && node.right) { - return doVisit(lo, hi, compare, visit, node.right) - } -} - - -proto.forEach = function rbTreeForEach(visit, lo, hi) { - if(!this.root) { - return - } - switch(arguments.length) { - case 1: - return doVisitFull(visit, this.root) - break - - case 2: - return doVisitHalf(lo, this._compare, visit, this.root) - break - - case 3: - if(this._compare(lo, hi) >= 0) { - return - } - return doVisit(lo, hi, this._compare, visit, this.root) - break - } -} - -//First item in list -Object.defineProperty(proto, "begin", { - get: function() { - var stack = [] - var n = this.root - while(n) { - stack.push(n) - n = n.left - } - return new RedBlackTreeIterator(this, stack) - } -}) - -//Last item in list -Object.defineProperty(proto, "end", { - get: function() { - var stack = [] - var n = this.root - while(n) { - stack.push(n) - n = n.right - } - return new RedBlackTreeIterator(this, stack) - } -}) - -//Find the ith item in the tree -proto.at = function(idx) { - if(idx < 0) { - return new RedBlackTreeIterator(this, []) - } - var n = this.root - var stack = [] - while(true) { - stack.push(n) - if(n.left) { - if(idx < n.left._count) { - n = n.left - continue - } - idx -= n.left._count - } - if(!idx) { - return new RedBlackTreeIterator(this, stack) - } - idx -= 1 - if(n.right) { - if(idx >= n.right._count) { - break - } - n = n.right - } else { - break - } - } - return new RedBlackTreeIterator(this, []) -} - -proto.ge = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - var last_ptr = 0 - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d <= 0) { - last_ptr = stack.length - } - if(d <= 0) { - n = n.left - } else { - n = n.right - } - } - stack.length = last_ptr - return new RedBlackTreeIterator(this, stack) -} - -proto.gt = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - var last_ptr = 0 - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d < 0) { - last_ptr = stack.length - } - if(d < 0) { - n = n.left - } else { - n = n.right - } - } - stack.length = last_ptr - return new RedBlackTreeIterator(this, stack) -} - -proto.lt = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - var last_ptr = 0 - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d > 0) { - last_ptr = stack.length - } - if(d <= 0) { - n = n.left - } else { - n = n.right - } - } - stack.length = last_ptr - return new RedBlackTreeIterator(this, stack) -} - -proto.le = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - var last_ptr = 0 - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d >= 0) { - last_ptr = stack.length - } - if(d < 0) { - n = n.left - } else { - n = n.right - } - } - stack.length = last_ptr - return new RedBlackTreeIterator(this, stack) -} - -//Finds the item with key if it exists -proto.find = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d === 0) { - return new RedBlackTreeIterator(this, stack) - } - if(d <= 0) { - n = n.left - } else { - n = n.right - } - } - return new RedBlackTreeIterator(this, []) -} - -//Removes item with key from tree -proto.remove = function(key) { - var iter = this.find(key) - if(iter) { - return iter.remove() - } - return this -} - -//Returns the item at `key` -proto.get = function(key) { - var cmp = this._compare - var n = this.root - while(n) { - var d = cmp(key, n.key) - if(d === 0) { - return n.value - } - if(d <= 0) { - n = n.left - } else { - n = n.right - } - } - return -} - -//Iterator for red black tree -function RedBlackTreeIterator(tree, stack) { - this.tree = tree - this._stack = stack -} - -var iproto = RedBlackTreeIterator.prototype - -//Test if iterator is valid -Object.defineProperty(iproto, "valid", { - get: function() { - return this._stack.length > 0 - } -}) - -//Node of the iterator -Object.defineProperty(iproto, "node", { - get: function() { - if(this._stack.length > 0) { - return this._stack[this._stack.length-1] - } - return null - }, - enumerable: true -}) - -//Makes a copy of an iterator -iproto.clone = function() { - return new RedBlackTreeIterator(this.tree, this._stack.slice()) -} - -//Swaps two nodes -function swapNode(n, v) { - n.key = v.key - n.value = v.value - n.left = v.left - n.right = v.right - n._color = v._color - n._count = v._count -} - -//Fix up a double black node in a tree -function fixDoubleBlack(stack) { - var n, p, s, z - for(var i=stack.length-1; i>=0; --i) { - n = stack[i] - if(i === 0) { - n._color = BLACK - return - } - //console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key) - p = stack[i-1] - if(p.left === n) { - //console.log("left child") - s = p.right - if(s.right && s.right._color === RED) { - //console.log("case 1: right sibling child red") - s = p.right = cloneNode(s) - z = s.right = cloneNode(s.right) - p.right = s.left - s.left = p - s.right = z - s._color = p._color - n._color = BLACK - p._color = BLACK - z._color = BLACK - recount(p) - recount(s) - if(i > 1) { - var pp = stack[i-2] - if(pp.left === p) { - pp.left = s - } else { - pp.right = s - } - } - stack[i-1] = s - return - } else if(s.left && s.left._color === RED) { - //console.log("case 1: left sibling child red") - s = p.right = cloneNode(s) - z = s.left = cloneNode(s.left) - p.right = z.left - s.left = z.right - z.left = p - z.right = s - z._color = p._color - p._color = BLACK - s._color = BLACK - n._color = BLACK - recount(p) - recount(s) - recount(z) - if(i > 1) { - var pp = stack[i-2] - if(pp.left === p) { - pp.left = z - } else { - pp.right = z - } - } - stack[i-1] = z - return - } - if(s._color === BLACK) { - if(p._color === RED) { - //console.log("case 2: black sibling, red parent", p.right.value) - p._color = BLACK - p.right = repaint(RED, s) - return - } else { - //console.log("case 2: black sibling, black parent", p.right.value) - p.right = repaint(RED, s) - continue - } - } else { - //console.log("case 3: red sibling") - s = cloneNode(s) - p.right = s.left - s.left = p - s._color = p._color - p._color = RED - recount(p) - recount(s) - if(i > 1) { - var pp = stack[i-2] - if(pp.left === p) { - pp.left = s - } else { - pp.right = s - } - } - stack[i-1] = s - stack[i] = p - if(i+1 < stack.length) { - stack[i+1] = n - } else { - stack.push(n) - } - i = i+2 - } - } else { - //console.log("right child") - s = p.left - if(s.left && s.left._color === RED) { - //console.log("case 1: left sibling child red", p.value, p._color) - s = p.left = cloneNode(s) - z = s.left = cloneNode(s.left) - p.left = s.right - s.right = p - s.left = z - s._color = p._color - n._color = BLACK - p._color = BLACK - z._color = BLACK - recount(p) - recount(s) - if(i > 1) { - var pp = stack[i-2] - if(pp.right === p) { - pp.right = s - } else { - pp.left = s - } - } - stack[i-1] = s - return - } else if(s.right && s.right._color === RED) { - //console.log("case 1: right sibling child red") - s = p.left = cloneNode(s) - z = s.right = cloneNode(s.right) - p.left = z.right - s.right = z.left - z.right = p - z.left = s - z._color = p._color - p._color = BLACK - s._color = BLACK - n._color = BLACK - recount(p) - recount(s) - recount(z) - if(i > 1) { - var pp = stack[i-2] - if(pp.right === p) { - pp.right = z - } else { - pp.left = z - } - } - stack[i-1] = z - return - } - if(s._color === BLACK) { - if(p._color === RED) { - //console.log("case 2: black sibling, red parent") - p._color = BLACK - p.left = repaint(RED, s) - return - } else { - //console.log("case 2: black sibling, black parent") - p.left = repaint(RED, s) - continue - } - } else { - //console.log("case 3: red sibling") - s = cloneNode(s) - p.left = s.right - s.right = p - s._color = p._color - p._color = RED - recount(p) - recount(s) - if(i > 1) { - var pp = stack[i-2] - if(pp.right === p) { - pp.right = s - } else { - pp.left = s - } - } - stack[i-1] = s - stack[i] = p - if(i+1 < stack.length) { - stack[i+1] = n - } else { - stack.push(n) - } - i = i+2 - } - } - } -} - -//Removes item at iterator from tree -iproto.remove = function() { - var stack = this._stack - if(stack.length === 0) { - return this.tree - } - //First copy path to node - var cstack = new Array(stack.length) - var n = stack[stack.length-1] - cstack[cstack.length-1] = new RBNode(n._color, n.key, n.value, n.left, n.right, n._count) - for(var i=stack.length-2; i>=0; --i) { - var n = stack[i] - if(n.left === stack[i+1]) { - cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count) - } else { - cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) - } - } - - //Get node - n = cstack[cstack.length-1] - //console.log("start remove: ", n.value) - - //If not leaf, then swap with previous node - if(n.left && n.right) { - //console.log("moving to leaf") - - //First walk to previous leaf - var split = cstack.length - n = n.left - while(n.right) { - cstack.push(n) - n = n.right - } - //Copy path to leaf - var v = cstack[split-1] - cstack.push(new RBNode(n._color, v.key, v.value, n.left, n.right, n._count)) - cstack[split-1].key = n.key - cstack[split-1].value = n.value - - //Fix up stack - for(var i=cstack.length-2; i>=split; --i) { - n = cstack[i] - cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) - } - cstack[split-1].left = cstack[split] - } - //console.log("stack=", cstack.map(function(v) { return v.value })) - - //Remove leaf node - n = cstack[cstack.length-1] - if(n._color === RED) { - //Easy case: removing red leaf - //console.log("RED leaf") - var p = cstack[cstack.length-2] - if(p.left === n) { - p.left = null - } else if(p.right === n) { - p.right = null - } - cstack.pop() - for(var i=0; i 0) { - return this._stack[this._stack.length-1].key - } - return - }, - enumerable: true -}) - -//Returns value -Object.defineProperty(iproto, "value", { - get: function() { - if(this._stack.length > 0) { - return this._stack[this._stack.length-1].value - } - return - }, - enumerable: true -}) - - -//Returns the position of this iterator in the sorted list -Object.defineProperty(iproto, "index", { - get: function() { - var idx = 0 - var stack = this._stack - if(stack.length === 0) { - var r = this.tree.root - if(r) { - return r._count - } - return 0 - } else if(stack[stack.length-1].left) { - idx = stack[stack.length-1].left._count - } - for(var s=stack.length-2; s>=0; --s) { - if(stack[s+1] === stack[s].right) { - ++idx - if(stack[s].left) { - idx += stack[s].left._count - } - } - } - return idx - }, - enumerable: true -}) - -//Advances iterator to next element in list -iproto.next = function() { - var stack = this._stack - if(stack.length === 0) { - return - } - var n = stack[stack.length-1] - if(n.right) { - n = n.right - while(n) { - stack.push(n) - n = n.left - } - } else { - stack.pop() - while(stack.length > 0 && stack[stack.length-1].right === n) { - n = stack[stack.length-1] - stack.pop() - } - } -} - -//Checks if iterator is at end of tree -Object.defineProperty(iproto, "hasNext", { - get: function() { - var stack = this._stack - if(stack.length === 0) { - return false - } - if(stack[stack.length-1].right) { - return true - } - for(var s=stack.length-1; s>0; --s) { - if(stack[s-1].left === stack[s]) { - return true - } - } - return false - } -}) - -//Update value -iproto.update = function(value) { - var stack = this._stack - if(stack.length === 0) { - throw new Error("Can't update empty node!") - } - var cstack = new Array(stack.length) - var n = stack[stack.length-1] - cstack[cstack.length-1] = new RBNode(n._color, n.key, value, n.left, n.right, n._count) - for(var i=stack.length-2; i>=0; --i) { - n = stack[i] - if(n.left === stack[i+1]) { - cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count) - } else { - cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) - } - } - return new RedBlackTree(this.tree._compare, cstack[0]) -} - -//Moves iterator backward one element -iproto.prev = function() { - var stack = this._stack - if(stack.length === 0) { - return - } - var n = stack[stack.length-1] - if(n.left) { - n = n.left - while(n) { - stack.push(n) - n = n.right - } - } else { - stack.pop() - while(stack.length > 0 && stack[stack.length-1].left === n) { - n = stack[stack.length-1] - stack.pop() - } - } -} - -//Checks if iterator is at start of tree -Object.defineProperty(iproto, "hasPrev", { - get: function() { - var stack = this._stack - if(stack.length === 0) { - return false - } - if(stack[stack.length-1].left) { - return true - } - for(var s=stack.length-1; s>0; --s) { - if(stack[s-1].right === stack[s]) { - return true - } - } - return false - } -}) - -//Default comparison function -function defaultCompare(a, b) { - if(a < b) { - return -1 - } - if(a > b) { - return 1 - } - return 0 -} - -//Build a tree -function createRBTree(compare) { - return new RedBlackTree(compare || defaultCompare, null) -} -},{}],231:[function(_dereq_,module,exports){ -// transliterated from the python snippet here: -// http://en.wikipedia.org/wiki/Lanczos_approximation - -var g = 7; -var p = [ - 0.99999999999980993, - 676.5203681218851, - -1259.1392167224028, - 771.32342877765313, - -176.61502916214059, - 12.507343278686905, - -0.13857109526572012, - 9.9843695780195716e-6, - 1.5056327351493116e-7 -]; - -var g_ln = 607/128; -var p_ln = [ - 0.99999999999999709182, - 57.156235665862923517, - -59.597960355475491248, - 14.136097974741747174, - -0.49191381609762019978, - 0.33994649984811888699e-4, - 0.46523628927048575665e-4, - -0.98374475304879564677e-4, - 0.15808870322491248884e-3, - -0.21026444172410488319e-3, - 0.21743961811521264320e-3, - -0.16431810653676389022e-3, - 0.84418223983852743293e-4, - -0.26190838401581408670e-4, - 0.36899182659531622704e-5 -]; - -// Spouge approximation (suitable for large arguments) -function lngamma(z) { - - if(z < 0) return Number('0/0'); - var x = p_ln[0]; - for(var i = p_ln.length - 1; i > 0; --i) x += p_ln[i] / (z + i); - var t = z + g_ln + 0.5; - return .5*Math.log(2*Math.PI)+(z+.5)*Math.log(t)-t+Math.log(x)-Math.log(z); -} - -module.exports = function gamma (z) { - if (z < 0.5) { - return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z)); - } - else if(z > 100) return Math.exp(lngamma(z)); - else { - z -= 1; - var x = p[0]; - for (var i = 1; i < g + 2; i++) { - x += p[i] / (z + i); - } - var t = z + g + 0.5; - - return Math.sqrt(2 * Math.PI) - * Math.pow(t, z + 0.5) - * Math.exp(-t) - * x - ; - } -}; - -module.exports.log = lngamma; - -},{}],232:[function(_dereq_,module,exports){ -module.exports = getCanvasContext -function getCanvasContext (type, opts) { - if (typeof type !== 'string') { - throw new TypeError('must specify type string') - } - - opts = opts || {} - - if (typeof document === 'undefined' && !opts.canvas) { - return null // check for Node - } - - var canvas = opts.canvas || document.createElement('canvas') - if (typeof opts.width === 'number') { - canvas.width = opts.width - } - if (typeof opts.height === 'number') { - canvas.height = opts.height - } - - var attribs = opts - var gl - try { - var names = [ type ] - // prefix GL contexts - if (type.indexOf('webgl') === 0) { - names.push('experimental-' + type) - } - - for (var i = 0; i < names.length; i++) { - gl = canvas.getContext(names[i], attribs) - if (gl) return gl - } - } catch (e) { - gl = null - } - return (gl || null) // ensure null on fail -} - -},{}],233:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createAxes - -var createText = _dereq_('./lib/text.js') -var createLines = _dereq_('./lib/lines.js') -var createBackground = _dereq_('./lib/background.js') -var getCubeProperties = _dereq_('./lib/cube.js') -var Ticks = _dereq_('./lib/ticks.js') - -var identity = new Float32Array([ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1]) - -function copyVec3(a, b) { - a[0] = b[0] - a[1] = b[1] - a[2] = b[2] - return a -} - -function Axes(gl) { - this.gl = gl - - this.pixelRatio = 1 - - this.bounds = [ [-10, -10, -10], - [ 10, 10, 10] ] - this.ticks = [ [], [], [] ] - this.autoTicks = true - this.tickSpacing = [ 1, 1, 1 ] - - this.tickEnable = [ true, true, true ] - this.tickFont = [ 'sans-serif', 'sans-serif', 'sans-serif' ] - this.tickSize = [ 12, 12, 12 ] - this.tickAngle = [ 0, 0, 0 ] - this.tickAlign = [ 'auto', 'auto', 'auto' ] - this.tickColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] - this.tickPad = [ 10, 10, 10 ] - - this.lastCubeProps = { - cubeEdges: [0,0,0], - axis: [0,0,0] - } - - this.labels = [ 'x', 'y', 'z' ] - this.labelEnable = [ true, true, true ] - this.labelFont = 'sans-serif' - this.labelSize = [ 20, 20, 20 ] - this.labelAngle = [ 0, 0, 0 ] - this.labelAlign = [ 'auto', 'auto', 'auto' ] - this.labelColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] - this.labelPad = [ 10, 10, 10 ] - - this.lineEnable = [ true, true, true ] - this.lineMirror = [ false, false, false ] - this.lineWidth = [ 1, 1, 1 ] - this.lineColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] - - this.lineTickEnable = [ true, true, true ] - this.lineTickMirror = [ false, false, false ] - this.lineTickLength = [ 0, 0, 0 ] - this.lineTickWidth = [ 1, 1, 1 ] - this.lineTickColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] - - this.gridEnable = [ true, true, true ] - this.gridWidth = [ 1, 1, 1 ] - this.gridColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] - - this.zeroEnable = [ true, true, true ] - this.zeroLineColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] - this.zeroLineWidth = [ 2, 2, 2 ] - - this.backgroundEnable = [ false, false, false ] - this.backgroundColor = [ [0.8, 0.8, 0.8, 0.5], - [0.8, 0.8, 0.8, 0.5], - [0.8, 0.8, 0.8, 0.5] ] - - this._firstInit = true - this._text = null - this._lines = null - this._background = createBackground(gl) -} - -var proto = Axes.prototype - -proto.update = function(options) { - options = options || {} - - //Option parsing helper functions - function parseOption(nest, cons, name) { - if(name in options) { - var opt = options[name] - var prev = this[name] - var next - if(nest ? (Array.isArray(opt) && Array.isArray(opt[0])) : - Array.isArray(opt) ) { - this[name] = next = [ cons(opt[0]), cons(opt[1]), cons(opt[2]) ] - } else { - this[name] = next = [ cons(opt), cons(opt), cons(opt) ] - } - for(var i=0; i<3; ++i) { - if(next[i] !== prev[i]) { - return true - } - } - } - return false - } - - var NUMBER = parseOption.bind(this, false, Number) - var BOOLEAN = parseOption.bind(this, false, Boolean) - var STRING = parseOption.bind(this, false, String) - var COLOR = parseOption.bind(this, true, function(v) { - if(Array.isArray(v)) { - if(v.length === 3) { - return [ +v[0], +v[1], +v[2], 1.0 ] - } else if(v.length === 4) { - return [ +v[0], +v[1], +v[2], +v[3] ] - } - } - return [ 0, 0, 0, 1 ] - }) - - //Tick marks and bounds - var nextTicks - var ticksUpdate = false - var boundsChanged = false - if('bounds' in options) { - var bounds = options.bounds -i_loop: - for(var i=0; i<2; ++i) { - for(var j=0; j<3; ++j) { - if(bounds[i][j] !== this.bounds[i][j]) { - boundsChanged = true - } - this.bounds[i][j] = bounds[i][j] - } - } - } - if('ticks' in options) { - nextTicks = options.ticks - ticksUpdate = true - this.autoTicks = false - for(var i=0; i<3; ++i) { - this.tickSpacing[i] = 0.0 - } - } else if(NUMBER('tickSpacing')) { - this.autoTicks = true - boundsChanged = true - } - - if(this._firstInit) { - if(!('ticks' in options || 'tickSpacing' in options)) { - this.autoTicks = true - } - - //Force tick recomputation on first update - boundsChanged = true - ticksUpdate = true - this._firstInit = false - } - - if(boundsChanged && this.autoTicks) { - nextTicks = Ticks.create(this.bounds, this.tickSpacing) - ticksUpdate = true - } - - //Compare next ticks to previous ticks, only update if needed - if(ticksUpdate) { - for(var i=0; i<3; ++i) { - nextTicks[i].sort(function(a,b) { - return a.x-b.x - }) - } - if(Ticks.equal(nextTicks, this.ticks)) { - ticksUpdate = false - } else { - this.ticks = nextTicks - } - } - - //Parse tick properties - BOOLEAN('tickEnable') - if(STRING('tickFont')) { - ticksUpdate = true //If font changes, must rebuild vbo - } - NUMBER('tickSize') - NUMBER('tickAngle') - NUMBER('tickPad') - COLOR('tickColor') - - //Axis labels - var labelUpdate = STRING('labels') - if(STRING('labelFont')) { - labelUpdate = true - } - BOOLEAN('labelEnable') - NUMBER('labelSize') - NUMBER('labelPad') - COLOR('labelColor') - - //Axis lines - BOOLEAN('lineEnable') - BOOLEAN('lineMirror') - NUMBER('lineWidth') - COLOR('lineColor') - - //Axis line ticks - BOOLEAN('lineTickEnable') - BOOLEAN('lineTickMirror') - NUMBER('lineTickLength') - NUMBER('lineTickWidth') - COLOR('lineTickColor') - - //Grid lines - BOOLEAN('gridEnable') - NUMBER('gridWidth') - COLOR('gridColor') - - //Zero line - BOOLEAN('zeroEnable') - COLOR('zeroLineColor') - NUMBER('zeroLineWidth') - - //Background - BOOLEAN('backgroundEnable') - COLOR('backgroundColor') - - //Update text if necessary - if(!this._text) { - this._text = createText( - this.gl, - this.bounds, - this.labels, - this.labelFont, - this.ticks, - this.tickFont) - } else if(this._text && (labelUpdate || ticksUpdate)) { - this._text.update( - this.bounds, - this.labels, - this.labelFont, - this.ticks, - this.tickFont) - } - - //Update lines if necessary - if(this._lines && ticksUpdate) { - this._lines.dispose() - this._lines = null - } - if(!this._lines) { - this._lines = createLines(this.gl, this.bounds, this.ticks) - } -} - -function OffsetInfo() { - this.primalOffset = [0,0,0] - this.primalMinor = [0,0,0] - this.mirrorOffset = [0,0,0] - this.mirrorMinor = [0,0,0] -} - -var LINE_OFFSET = [ new OffsetInfo(), new OffsetInfo(), new OffsetInfo() ] - -function computeLineOffset(result, i, bounds, cubeEdges, cubeAxis) { - var primalOffset = result.primalOffset - var primalMinor = result.primalMinor - var dualOffset = result.mirrorOffset - var dualMinor = result.mirrorMinor - var e = cubeEdges[i] - - //Calculate offsets - for(var j=0; j<3; ++j) { - if(i === j) { - continue - } - var a = primalOffset, - b = dualOffset, - c = primalMinor, - d = dualMinor - if(e & (1< 0) { - c[j] = -1 - d[j] = 0 - } else { - c[j] = 0 - d[j] = +1 - } - } -} - -var CUBE_ENABLE = [0,0,0] -var DEFAULT_PARAMS = { - model: identity, - view: identity, - projection: identity, - _ortho: false -} - -proto.isOpaque = function() { - return true -} - -proto.isTransparent = function() { - return false -} - -proto.drawTransparent = function(params) {} - -var ALIGN_OPTION_AUTO = 0 // i.e. as defined in the shader the text would rotate to stay upwards range: [-90,90] - -var PRIMAL_MINOR = [0,0,0] -var MIRROR_MINOR = [0,0,0] -var PRIMAL_OFFSET = [0,0,0] - -proto.draw = function(params) { - params = params || DEFAULT_PARAMS - - var gl = this.gl - - //Geometry for camera and axes - var model = params.model || identity - var view = params.view || identity - var projection = params.projection || identity - var bounds = this.bounds - var isOrtho = params._ortho || false - - //Unpack axis info - var cubeParams = getCubeProperties(model, view, projection, bounds, isOrtho) - var cubeEdges = cubeParams.cubeEdges - var cubeAxis = cubeParams.axis - - var cx = view[12] - var cy = view[13] - var cz = view[14] - var cw = view[15] - - var orthoFix = (isOrtho) ? 2 : 1 // double up padding for orthographic ticks & labels - var pixelScaleF = orthoFix * this.pixelRatio * (projection[3]*cx + projection[7]*cy + projection[11]*cz + projection[15]*cw) / gl.drawingBufferHeight - - for(var i=0; i<3; ++i) { - this.lastCubeProps.cubeEdges[i] = cubeEdges[i] - this.lastCubeProps.axis[i] = cubeAxis[i] - } - - //Compute axis info - var lineOffset = LINE_OFFSET - for(var i=0; i<3; ++i) { - computeLineOffset( - LINE_OFFSET[i], - i, - this.bounds, - cubeEdges, - cubeAxis) - } - - //Set up state parameters - var gl = this.gl - - //Draw background first - var cubeEnable = CUBE_ENABLE - for(var i=0; i<3; ++i) { - if(this.backgroundEnable[i]) { - cubeEnable[i] = cubeAxis[i] - } else { - cubeEnable[i] = 0 - } - } - - this._background.draw( - model, - view, - projection, - bounds, - cubeEnable, - this.backgroundColor) - - //Draw lines - this._lines.bind( - model, - view, - projection, - this) - - //First draw grid lines and zero lines - for(var i=0; i<3; ++i) { - var x = [0,0,0] - if(cubeAxis[i] > 0) { - x[i] = bounds[1][i] - } else { - x[i] = bounds[0][i] - } - - //Draw grid lines - for(var j=0; j<2; ++j) { - var u = (i + 1 + j) % 3 - var v = (i + 1 + (j^1)) % 3 - if(this.gridEnable[u]) { - this._lines.drawGrid(u, v, this.bounds, x, this.gridColor[u], this.gridWidth[u]*this.pixelRatio) - } - } - - //Draw zero lines (need to do this AFTER all grid lines are drawn) - for(var j=0; j<2; ++j) { - var u = (i + 1 + j) % 3 - var v = (i + 1 + (j^1)) % 3 - if(this.zeroEnable[v]) { - //Check if zero line in bounds - if(Math.min(bounds[0][v], bounds[1][v]) <= 0 && Math.max(bounds[0][v], bounds[1][v]) >= 0) { - this._lines.drawZero(u, v, this.bounds, x, this.zeroLineColor[v], this.zeroLineWidth[v]*this.pixelRatio) - } - } - } - } - - //Then draw axis lines and tick marks - for(var i=0; i<3; ++i) { - - //Draw axis lines - if(this.lineEnable[i]) { - this._lines.drawAxisLine(i, this.bounds, lineOffset[i].primalOffset, this.lineColor[i], this.lineWidth[i]*this.pixelRatio) - } - if(this.lineMirror[i]) { - this._lines.drawAxisLine(i, this.bounds, lineOffset[i].mirrorOffset, this.lineColor[i], this.lineWidth[i]*this.pixelRatio) - } - - //Compute minor axes - var primalMinor = copyVec3(PRIMAL_MINOR, lineOffset[i].primalMinor) - var mirrorMinor = copyVec3(MIRROR_MINOR, lineOffset[i].mirrorMinor) - var tickLength = this.lineTickLength - for(var j=0; j<3; ++j) { - var scaleFactor = pixelScaleF / model[5*j] - primalMinor[j] *= tickLength[j] * scaleFactor - mirrorMinor[j] *= tickLength[j] * scaleFactor - } - - - - //Draw axis line ticks - if(this.lineTickEnable[i]) { - this._lines.drawAxisTicks(i, lineOffset[i].primalOffset, primalMinor, this.lineTickColor[i], this.lineTickWidth[i]*this.pixelRatio) - } - if(this.lineTickMirror[i]) { - this._lines.drawAxisTicks(i, lineOffset[i].mirrorOffset, mirrorMinor, this.lineTickColor[i], this.lineTickWidth[i]*this.pixelRatio) - } - } - this._lines.unbind() - - //Draw text sprites - this._text.bind( - model, - view, - projection, - this.pixelRatio) - - var alignOpt // options in shader are from this list {-1, 0, 1, 2, 3, ..., n} - // -1: backward compatible - // 0: raw data - // 1: auto align, free angles - // 2: auto align, horizontal or vertical - //3-n: auto align, round to n directions e.g. 12 -> round to angles with 30-degree steps - - var hv_ratio = 0.5 // can have an effect on the ratio between horizontals and verticals when using option 2 - - var enableAlign - var alignDir - - function alignTo(i) { - alignDir = [0,0,0] - alignDir[i] = 1 - } - - function solveTickAlignments(i, minor, major) { - - var i1 = (i + 1) % 3 - var i2 = (i + 2) % 3 - - var A = minor[i1] - var B = minor[i2] - var C = major[i1] - var D = major[i2] - - if ((A > 0) && (D > 0)) { alignTo(i1); return; } - else if ((A > 0) && (D < 0)) { alignTo(i1); return; } - else if ((A < 0) && (D > 0)) { alignTo(i1); return; } - else if ((A < 0) && (D < 0)) { alignTo(i1); return; } - else if ((B > 0) && (C > 0)) { alignTo(i2); return; } - else if ((B > 0) && (C < 0)) { alignTo(i2); return; } - else if ((B < 0) && (C > 0)) { alignTo(i2); return; } - else if ((B < 0) && (C < 0)) { alignTo(i2); return; } - } - - for(var i=0; i<3; ++i) { - - var minor = lineOffset[i].primalMinor - var major = lineOffset[i].mirrorMinor - - var offset = copyVec3(PRIMAL_OFFSET, lineOffset[i].primalOffset) - - for(var j=0; j<3; ++j) { - if(this.lineTickEnable[i]) { - offset[j] += pixelScaleF * minor[j] * Math.max(this.lineTickLength[j], 0) / model[5*j] - } - } - - var axis = [0,0,0] - axis[i] = 1 - - //Draw tick text - if(this.tickEnable[i]) { - - if(this.tickAngle[i] === -3600) { - this.tickAngle[i] = 0 - this.tickAlign[i] = 'auto' - } else { - this.tickAlign[i] = -1 - } - - enableAlign = 1; - - alignOpt = [this.tickAlign[i], hv_ratio, enableAlign] - if(alignOpt[0] === 'auto') alignOpt[0] = ALIGN_OPTION_AUTO - else alignOpt[0] = parseInt('' + alignOpt[0]) - - alignDir = [0,0,0] - solveTickAlignments(i, minor, major) - - //Add tick padding - for(var j=0; j<3; ++j) { - offset[j] += pixelScaleF * minor[j] * this.tickPad[j] / model[5*j] - } - - //Draw axis - this._text.drawTicks( - i, - this.tickSize[i], - this.tickAngle[i], - offset, - this.tickColor[i], - axis, - alignDir, - alignOpt) - } - - //Draw labels - if(this.labelEnable[i]) { - - enableAlign = 0 - alignDir = [0,0,0] - if(this.labels[i].length > 4) { // for large label axis enable alignDir to axis - alignTo(i) - enableAlign = 1 - } - - alignOpt = [this.labelAlign[i], hv_ratio, enableAlign] - if(alignOpt[0] === 'auto') alignOpt[0] = ALIGN_OPTION_AUTO - else alignOpt[0] = parseInt('' + alignOpt[0]) - - //Add label padding - for(var j=0; j<3; ++j) { - offset[j] += pixelScaleF * minor[j] * this.labelPad[j] / model[5*j] - } - offset[i] += 0.5 * (bounds[0][i] + bounds[1][i]) - - //Draw axis - this._text.drawLabel( - i, - this.labelSize[i], - this.labelAngle[i], - offset, - this.labelColor[i], - [0,0,0], - alignDir, - alignOpt) - } - } - - this._text.unbind() -} - -proto.dispose = function() { - this._text.dispose() - this._lines.dispose() - this._background.dispose() - this._lines = null - this._text = null - this._background = null - this.gl = null -} - -function createAxes(gl, options) { - var axes = new Axes(gl) - axes.update(options) - return axes -} - -},{"./lib/background.js":234,"./lib/cube.js":235,"./lib/lines.js":236,"./lib/text.js":238,"./lib/ticks.js":239}],234:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createBackgroundCube - -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') -var createShader = _dereq_('./shaders').bg - -function BackgroundCube(gl, buffer, vao, shader) { - this.gl = gl - this.buffer = buffer - this.vao = vao - this.shader = shader -} - -var proto = BackgroundCube.prototype - -proto.draw = function(model, view, projection, bounds, enable, colors) { - var needsBG = false - for(var i=0; i<3; ++i) { - needsBG = needsBG || enable[i] - } - if(!needsBG) { - return - } - - var gl = this.gl - - gl.enable(gl.POLYGON_OFFSET_FILL) - gl.polygonOffset(1, 2) - - this.shader.bind() - this.shader.uniforms = { - model: model, - view: view, - projection: projection, - bounds: bounds, - enable: enable, - colors: colors - } - this.vao.bind() - this.vao.draw(this.gl.TRIANGLES, 36) - this.vao.unbind() - - gl.disable(gl.POLYGON_OFFSET_FILL) -} - -proto.dispose = function() { - this.vao.dispose() - this.buffer.dispose() - this.shader.dispose() -} - -function createBackgroundCube(gl) { - //Create cube vertices - var vertices = [] - var indices = [] - var ptr = 0 - for(var d=0; d<3; ++d) { - var u = (d+1) % 3 - var v = (d+2) % 3 - var x = [0,0,0] - var c = [0,0,0] - for(var s=-1; s<=1; s+=2) { - indices.push(ptr, ptr+2, ptr+1, - ptr+1, ptr+2, ptr+3) - x[d] = s - c[d] = s - for(var i=-1; i<=1; i+=2) { - x[u] = i - for(var j=-1; j<=1; j+=2) { - x[v] = j - vertices.push(x[0], x[1], x[2], - c[0], c[1], c[2]) - ptr += 1 - } - } - //Swap u and v - var tt = u - u = v - v = tt - } - } - - //Allocate buffer and vertex array - var buffer = createBuffer(gl, new Float32Array(vertices)) - var elements = createBuffer(gl, new Uint16Array(indices), gl.ELEMENT_ARRAY_BUFFER) - var vao = createVAO(gl, [ - { - buffer: buffer, - type: gl.FLOAT, - size: 3, - offset: 0, - stride: 24 - }, - { - buffer: buffer, - type: gl.FLOAT, - size: 3, - offset: 12, - stride: 24 - } - ], elements) - - //Create shader object - var shader = createShader(gl) - shader.attributes.position.location = 0 - shader.attributes.normal.location = 1 - - return new BackgroundCube(gl, buffer, vao, shader) -} - -},{"./shaders":237,"gl-buffer":241,"gl-vao":327}],235:[function(_dereq_,module,exports){ -"use strict" - -module.exports = getCubeEdges - -var bits = _dereq_('bit-twiddle') -var multiply = _dereq_('gl-mat4/multiply') -var splitPoly = _dereq_('split-polygon') -var orient = _dereq_('robust-orientation') - -var mvp = new Array(16) -var pCubeVerts = new Array(8) -var cubeVerts = new Array(8) -var x = new Array(3) -var zero3 = [0,0,0] - -;(function() { - for(var i=0; i<8; ++i) { - pCubeVerts[i] =[1,1,1,1] - cubeVerts[i] = [1,1,1] - } -})() - - -function transformHg(result, x, mat) { - for(var i=0; i<4; ++i) { - result[i] = mat[12+i] - for(var j=0; j<3; ++j) { - result[i] += x[j]*mat[4*j+i] - } - } -} - -var FRUSTUM_PLANES = [ - [ 0, 0, 1, 0, 0], - [ 0, 0,-1, 1, 0], - [ 0,-1, 0, 1, 0], - [ 0, 1, 0, 1, 0], - [-1, 0, 0, 1, 0], - [ 1, 0, 0, 1, 0] -] - -function polygonArea(p) { - for(var i=0; i o0) { - closest |= 1< o0) { - closest |= 1< cubeVerts[i][1]) { - bottom = i - } - } - - //Find left/right neighbors of bottom vertex - var left = -1 - for(var i=0; i<3; ++i) { - var idx = bottom ^ (1< cubeVerts[right][0]) { - right = idx - } - } - - //Determine edge axis coordinates - var cubeEdges = CUBE_EDGES - cubeEdges[0] = cubeEdges[1] = cubeEdges[2] = 0 - cubeEdges[bits.log2(left^bottom)] = bottom&left - cubeEdges[bits.log2(bottom^right)] = bottom&right - var top = right ^ 7 - if(top === closest || top === farthest) { - top = left ^ 7 - cubeEdges[bits.log2(right^top)] = top&right - } else { - cubeEdges[bits.log2(left^top)] = top&left - } - - //Determine visible faces - var axis = CUBE_AXIS - var cutCorner = closest - for(var d=0; d<3; ++d) { - if(cutCorner & (1< HALF_PI) && (b <= ONE_AND_HALF_PI)) ?\n b - PI :\n b;\n}\n\nfloat look_horizontal_or_vertical(float a, float ratio) {\n // ratio controls the ratio between being horizontal to (vertical + horizontal)\n // if ratio is set to 0.5 then it is 50%, 50%.\n // when using a higher ratio e.g. 0.75 the result would\n // likely be more horizontal than vertical.\n\n float b = positive_angle(a);\n\n return\n (b < ( ratio) * HALF_PI) ? 0.0 :\n (b < (2.0 - ratio) * HALF_PI) ? -HALF_PI :\n (b < (2.0 + ratio) * HALF_PI) ? 0.0 :\n (b < (4.0 - ratio) * HALF_PI) ? HALF_PI :\n 0.0;\n}\n\nfloat roundTo(float a, float b) {\n return float(b * floor((a + 0.5 * b) / b));\n}\n\nfloat look_round_n_directions(float a, int n) {\n float b = positive_angle(a);\n float div = TWO_PI / float(n);\n float c = roundTo(b, div);\n return look_upwards(c);\n}\n\nfloat applyAlignOption(float rawAngle, float delta) {\n return\n (option > 2) ? look_round_n_directions(rawAngle + delta, option) : // option 3-n: round to n directions\n (option == 2) ? look_horizontal_or_vertical(rawAngle + delta, hv_ratio) : // horizontal or vertical\n (option == 1) ? rawAngle + delta : // use free angle, and flip to align with one direction of the axis\n (option == 0) ? look_upwards(rawAngle) : // use free angle, and stay upwards\n (option ==-1) ? 0.0 : // useful for backward compatibility, all texts remains horizontal\n rawAngle; // otherwise return back raw input angle\n}\n\nbool isAxisTitle = (axis.x == 0.0) &&\n (axis.y == 0.0) &&\n (axis.z == 0.0);\n\nvoid main() {\n //Compute world offset\n float axisDistance = position.z;\n vec3 dataPosition = axisDistance * axis + offset;\n\n float beta = angle; // i.e. user defined attributes for each tick\n\n float axisAngle;\n float clipAngle;\n float flip;\n\n if (enableAlign) {\n axisAngle = (isAxisTitle) ? HALF_PI :\n computeViewAngle(dataPosition, dataPosition + axis);\n clipAngle = computeViewAngle(dataPosition, dataPosition + alignDir);\n\n axisAngle += (sin(axisAngle) < 0.0) ? PI : 0.0;\n clipAngle += (sin(clipAngle) < 0.0) ? PI : 0.0;\n\n flip = (dot(vec2(cos(axisAngle), sin(axisAngle)),\n vec2(sin(clipAngle),-cos(clipAngle))) > 0.0) ? 1.0 : 0.0;\n\n beta += applyAlignOption(clipAngle, flip * PI);\n }\n\n //Compute plane offset\n vec2 planeCoord = position.xy * pixelScale;\n\n mat2 planeXform = scale * mat2(\n cos(beta), sin(beta),\n -sin(beta), cos(beta)\n );\n\n vec2 viewOffset = 2.0 * planeXform * planeCoord / resolution;\n\n //Compute clip position\n vec3 clipPosition = project(dataPosition);\n\n //Apply text offset in clip coordinates\n clipPosition += vec3(viewOffset, 0.0);\n\n //Done\n gl_Position = vec4(clipPosition, 1.0);\n}"]) -var textFrag = glslify(["precision highp float;\n#define GLSLIFY 1\n\nuniform vec4 color;\nvoid main() {\n gl_FragColor = color;\n}"]) -exports.text = function(gl) { - return createShader(gl, textVert, textFrag, null, [ - {name: 'position', type: 'vec3'} - ]) -} - -var bgVert = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec3 normal;\n\nuniform mat4 model, view, projection;\nuniform vec3 enable;\nuniform vec3 bounds[2];\n\nvarying vec3 colorChannel;\n\nvoid main() {\n\n vec3 signAxis = sign(bounds[1] - bounds[0]);\n\n vec3 realNormal = signAxis * normal;\n\n if(dot(realNormal, enable) > 0.0) {\n vec3 minRange = min(bounds[0], bounds[1]);\n vec3 maxRange = max(bounds[0], bounds[1]);\n vec3 nPosition = mix(minRange, maxRange, 0.5 * (position + 1.0));\n gl_Position = projection * view * model * vec4(nPosition, 1.0);\n } else {\n gl_Position = vec4(0,0,0,0);\n }\n\n colorChannel = abs(realNormal);\n}"]) -var bgFrag = glslify(["precision highp float;\n#define GLSLIFY 1\n\nuniform vec4 colors[3];\n\nvarying vec3 colorChannel;\n\nvoid main() {\n gl_FragColor = colorChannel.x * colors[0] +\n colorChannel.y * colors[1] +\n colorChannel.z * colors[2];\n}"]) -exports.bg = function(gl) { - return createShader(gl, bgVert, bgFrag, null, [ - {name: 'position', type: 'vec3'}, - {name: 'normal', type: 'vec3'} - ]) -} - -},{"gl-shader":301,"glslify":409}],238:[function(_dereq_,module,exports){ -(function (process){ -"use strict" - -module.exports = createTextSprites - -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') -var vectorizeText = _dereq_('vectorize-text') -var createShader = _dereq_('./shaders').text - -var globals = window || process.global || {} -var __TEXT_CACHE = globals.__TEXT_CACHE || {} -globals.__TEXT_CACHE = {} - -//Vertex buffer format for text is: -// -/// [x,y,z] = Spatial coordinate -// - -var VERTEX_SIZE = 3 - -function TextSprites( - gl, - shader, - buffer, - vao) { - this.gl = gl - this.shader = shader - this.buffer = buffer - this.vao = vao - this.tickOffset = - this.tickCount = - this.labelOffset = - this.labelCount = null -} - -var proto = TextSprites.prototype - -//Bind textures for rendering -var SHAPE = [0,0] -proto.bind = function(model, view, projection, pixelScale) { - this.vao.bind() - this.shader.bind() - var uniforms = this.shader.uniforms - uniforms.model = model - uniforms.view = view - uniforms.projection = projection - uniforms.pixelScale = pixelScale - SHAPE[0] = this.gl.drawingBufferWidth - SHAPE[1] = this.gl.drawingBufferHeight - this.shader.uniforms.resolution = SHAPE -} - -proto.unbind = function() { - this.vao.unbind() -} - -proto.update = function(bounds, labels, labelFont, ticks, tickFont) { - var data = [] - - function addItem(t, text, font, size, lineSpacing, styletags) { - var fontcache = __TEXT_CACHE[font] - if(!fontcache) { - fontcache = __TEXT_CACHE[font] = {} - } - var mesh = fontcache[text] - if(!mesh) { - mesh = fontcache[text] = tryVectorizeText(text, { - triangles: true, - font: font, - textAlign: 'center', - textBaseline: 'middle', - lineSpacing: lineSpacing, - styletags: styletags - }) - } - var scale = (size || 12) / 12 - var positions = mesh.positions - var cells = mesh.cells - for(var i=0, nc=cells.length; i=0; --j) { - var p = positions[c[j]] - data.push(scale*p[0], -scale*p[1], t) - } - } - } - - //Generate sprites for all 3 axes, store data in texture atlases - var tickOffset = [0,0,0] - var tickCount = [0,0,0] - var labelOffset = [0,0,0] - var labelCount = [0,0,0] - var lineSpacing = 1.25 - var styletags = { - breaklines:true, - bolds: true, - italics: true, - subscripts:true, - superscripts:true - } - for(var d=0; d<3; ++d) { - - //Generate label - labelOffset[d] = (data.length/VERTEX_SIZE)|0 - addItem( - 0.5*(bounds[0][d]+bounds[1][d]), - labels[d], - labelFont[d], - 12, // labelFontSize - lineSpacing, - styletags - ) - labelCount[d] = ((data.length/VERTEX_SIZE)|0) - labelOffset[d] - - //Generate sprites for tick marks - tickOffset[d] = (data.length/VERTEX_SIZE)|0 - for(var i=0; i= 0) { - sigFigs = stepStr.length - u - 1 - } - var shift = Math.pow(10, sigFigs) - var x = Math.round(spacing * i * shift) - var xstr = x + "" - if(xstr.indexOf("e") >= 0) { - return xstr - } - var xi = x / shift, xf = x % shift - if(x < 0) { - xi = -Math.ceil(xi)|0 - xf = (-xf)|0 - } else { - xi = Math.floor(xi)|0 - xf = xf|0 - } - var xis = "" + xi - if(x < 0) { - xis = "-" + xis - } - if(sigFigs) { - var xs = "" + xf - while(xs.length < sigFigs) { - xs = "0" + xs - } - return xis + "." + xs - } else { - return xis - } -} - -function defaultTicks(bounds, tickSpacing) { - var array = [] - for(var d=0; d<3; ++d) { - var ticks = [] - var m = 0.5*(bounds[0][d]+bounds[1][d]) - for(var t=0; t*tickSpacing[d]<=bounds[1][d]; ++t) { - ticks.push({x: t*tickSpacing[d], text: prettyPrint(tickSpacing[d], t)}) - } - for(var t=-1; t*tickSpacing[d]>=bounds[0][d]; --t) { - ticks.push({x: t*tickSpacing[d], text: prettyPrint(tickSpacing[d], t)}) - } - array.push(ticks) - } - return array -} - -function ticksEqual(ticksA, ticksB) { - for(var i=0; i<3; ++i) { - if(ticksA[i].length !== ticksB[i].length) { - return false - } - for(var j=0; j len) { - throw new Error("gl-buffer: If resizing buffer, must not specify offset") - } - gl.bufferSubData(type, offset, data) - return len -} - -function makeScratchTypeArray(array, dtype) { - var res = pool.malloc(array.length, dtype) - var n = array.length - for(var i=0; i=0; --i) { - if(stride[i] !== n) { - return false - } - n *= shape[i] - } - return true -} - -proto.update = function(array, offset) { - if(typeof offset !== "number") { - offset = -1 - } - this.bind() - if(typeof array === "object" && typeof array.shape !== "undefined") { //ndarray - var dtype = array.dtype - if(SUPPORTED_TYPES.indexOf(dtype) < 0) { - dtype = "float32" - } - if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) { - var ext = gl.getExtension('OES_element_index_uint') - if(ext && dtype !== "uint16") { - dtype = "uint32" - } else { - dtype = "uint16" - } - } - if(dtype === array.dtype && isPacked(array.shape, array.stride)) { - if(array.offset === 0 && array.data.length === array.shape[0]) { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data, offset) - } else { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data.subarray(array.offset, array.shape[0]), offset) - } - } else { - var tmp = pool.malloc(array.size, dtype) - var ndt = ndarray(tmp, array.shape) - ops.assign(ndt, array) - if(offset < 0) { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp, offset) - } else { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp.subarray(0, array.size), offset) - } - pool.free(tmp) - } - } else if(Array.isArray(array)) { //Vanilla array - var t - if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) { - t = makeScratchTypeArray(array, "uint16") - } else { - t = makeScratchTypeArray(array, "float32") - } - if(offset < 0) { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t, offset) - } else { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t.subarray(0, array.length), offset) - } - pool.free(t) - } else if(typeof array === "object" && typeof array.length === "number") { //Typed array - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array, offset) - } else if(typeof array === "number" || array === undefined) { //Number/default - if(offset >= 0) { - throw new Error("gl-buffer: Cannot specify offset when resizing buffer") - } - array = array | 0 - if(array <= 0) { - array = 1 - } - this.gl.bufferData(this.type, array|0, this.usage) - this.length = array - } else { //Error, case should not happen - throw new Error("gl-buffer: Invalid data type") - } -} - -function createBuffer(gl, data, type, usage) { - type = type || gl.ARRAY_BUFFER - usage = usage || gl.DYNAMIC_DRAW - if(type !== gl.ARRAY_BUFFER && type !== gl.ELEMENT_ARRAY_BUFFER) { - throw new Error("gl-buffer: Invalid type for webgl buffer, must be either gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER") - } - if(usage !== gl.DYNAMIC_DRAW && usage !== gl.STATIC_DRAW && usage !== gl.STREAM_DRAW) { - throw new Error("gl-buffer: Invalid usage for buffer, must be either gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW") - } - var handle = gl.createBuffer() - var result = new GLBuffer(gl, type, handle, 0, usage) - result.update(data) - return result -} - -module.exports = createBuffer - -},{"ndarray":450,"ndarray-ops":444,"typedarray-pool":545}],242:[function(_dereq_,module,exports){ -"use strict"; - -var V = _dereq_('gl-vec3'); - -var vec3 = function(x, y, z) { - var v = V.create(); - if (x !== undefined) { - V.set(v, x, y, z); - } - return v; -} - -var createPositionsForMeshgrid = function(meshgrid) { - var xs = meshgrid[0], ys = meshgrid[1], zs = meshgrid[2]; - var positions = []; - for (var z=0; z= v) { - return i-1; - } - } - return i; -}; - -var tmp = V.create(); -var tmp2 = V.create(); - -var clamp = function(v, min, max) { - return v < min ? min : (v > max ? max : v); -}; - -var sampleMeshgrid = function(point, array, meshgrid, clampOverflow) { - var x = point[0]; - var y = point[1]; - var z = point[2]; - - var w = meshgrid[0].length; - var h = meshgrid[1].length; - var d = meshgrid[2].length; - - // Find the index of the nearest smaller value in the meshgrid for each coordinate of (x,y,z). - // The nearest smaller value index for x is the index x0 such that - // meshgrid[0][x0] < x and for all x1 > x0, meshgrid[0][x1] >= x. - var x0 = findLastSmallerIndex(meshgrid[0], x); - var y0 = findLastSmallerIndex(meshgrid[1], y); - var z0 = findLastSmallerIndex(meshgrid[2], z); - - // Get the nearest larger meshgrid value indices. - // From the above "nearest smaller value", we know that - // meshgrid[0][x0] < x - // meshgrid[0][x0+1] >= x - var x1 = x0 + 1; - var y1 = y0 + 1; - var z1 = z0 + 1; - - if (clampOverflow) { - x0 = clamp(x0, 0, w-1); - x1 = clamp(x1, 0, w-1); - y0 = clamp(y0, 0, h-1); - y1 = clamp(y1, 0, h-1); - z0 = clamp(z0, 0, d-1); - z1 = clamp(z1, 0, d-1); - } - - // Reject points outside the meshgrid, return a zero vector. - if (x0 < 0 || y0 < 0 || z0 < 0 || x1 >= w || y1 >= h || z1 >= d) { - return V.create(); - } - - // Normalize point coordinates to 0..1 scaling factor between x0 and x1. - var xf = (x - meshgrid[0][x0]) / (meshgrid[0][x1] - meshgrid[0][x0]); - var yf = (y - meshgrid[1][y0]) / (meshgrid[1][y1] - meshgrid[1][y0]); - var zf = (z - meshgrid[2][z0]) / (meshgrid[2][z1] - meshgrid[2][z0]); - - if (xf < 0 || xf > 1 || isNaN(xf)) xf = 0; - if (yf < 0 || yf > 1 || isNaN(yf)) yf = 0; - if (zf < 0 || zf > 1 || isNaN(zf)) zf = 0; - - var z0off = z0*w*h; - var z1off = z1*w*h; - - var y0off = y0*w; - var y1off = y1*w; - - var x0off = x0; - var x1off = x1; - - // Sample data array around the (x,y,z) point. - // vZYX = array[zZoff + yYoff + xXoff] - var v000 = array[y0off + z0off + x0off]; - var v001 = array[y0off + z0off + x1off]; - var v010 = array[y1off + z0off + x0off]; - var v011 = array[y1off + z0off + x1off]; - var v100 = array[y0off + z1off + x0off]; - var v101 = array[y0off + z1off + x1off]; - var v110 = array[y1off + z1off + x0off]; - var v111 = array[y1off + z1off + x1off]; - - var result = V.create(); - - // Average samples according to distance to point. - V.lerp(result, v000, v001, xf); - V.lerp(tmp, v010, v011, xf); - V.lerp(result, result, tmp, yf); - V.lerp(tmp, v100, v101, xf); - V.lerp(tmp2, v110, v111, xf); - V.lerp(tmp, tmp, tmp2, yf); - V.lerp(result, result, tmp, zf); - - return result; -}; - -var getOrthogonalVector = function(dst, v) { - // Return up-vector for only-z vector. - if (v[0] === 0 && v[1] === 0) { - V.set(dst, 0, 1, 0); - } else { - // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0). - // From the above if-statement we have ||a|| > 0 U ||b|| > 0. - // Assign z = 0, x = -b, y = a: - // a*-b + b*a + c*0 = -ba + ba + 0 = 0 - V.set(dst, -v[1], v[0], 0); - } - return dst; -}; - -module.exports = function(vectorfield, bounds) { - var positions; - if (vectorfield.positions) { - positions = vectorfield.positions; - } else { - positions = createPositionsForMeshgrid(vectorfield.meshgrid); - } - var meshgrid = vectorfield.meshgrid; - var vectors = vectorfield.vectors; - var geo = { - positions: [], - vertexIntensity: [], - vertexIntensityBounds: vectorfield.vertexIntensityBounds, - vertexNormals: [], - vectors: [], - cells: [], - coneOffset: vectorfield.coneOffset, - colormap: vectorfield.colormap - }; - - if (vectorfield.positions.length === 0) { - if (bounds) { - bounds[0] = [0,0,0]; - bounds[1] = [0,0,0]; - } - return geo; - } - - // Compute bounding box for the dataset. - // Compute maximum velocity for the dataset to use for scaling the cones. - var maxNorm = 0; - var minX = 1/0, maxX = -1/0; - var minY = 1/0, maxY = -1/0; - var minZ = 1/0, maxZ = -1/0; - var p2 = null; - var u2 = null; - var positionVectors = []; - var vectorScale = 1/0; - for (var i = 0; i < positions.length; i++) { - var p = positions[i]; - minX = Math.min(p[0], minX); - maxX = Math.max(p[0], maxX); - minY = Math.min(p[1], minY); - maxY = Math.max(p[1], maxY); - minZ = Math.min(p[2], minZ); - maxZ = Math.max(p[2], maxZ); - var u; - if (meshgrid) { - u = sampleMeshgrid(p, vectors, meshgrid, true); - } else { - u = vectors[i]; - } - if (V.length(u) > maxNorm) { - maxNorm = V.length(u); - } - if (i) { - // Find vector scale [w/ units of time] using "successive" positions - // (not "adjacent" with would be O(n^2)), - // - // The vector scale corresponds to the minimum "time" to travel across two - // two adjacent positions at the average velocity of those two adjacent positions - vectorScale = Math.min(vectorScale, - 2 * V.distance(p2, p) / (V.length(u2) + V.length(u)) - ); - } - p2 = p; - u2 = u; - positionVectors.push(u); - } - var minV = [minX, minY, minZ]; - var maxV = [maxX, maxY, maxZ]; - if (bounds) { - bounds[0] = minV; - bounds[1] = maxV; - } - if (maxNorm === 0) { - maxNorm = 1; - } - - // Inverted max norm would map vector with norm maxNorm to 1 coord space units in length - var invertedMaxNorm = 1 / maxNorm; - - if (!isFinite(vectorScale) || isNaN(vectorScale)) { - vectorScale = 1.0; - } - geo.vectorScale = vectorScale; - - var nml = vec3(0,1,0); - - var coneScale = vectorfield.coneSize || 0.5; - - if (vectorfield.absoluteConeSize) { - coneScale = vectorfield.absoluteConeSize * invertedMaxNorm; - } - - geo.coneScale = coneScale; - - // Build the cone model. - for (var i = 0, j = 0; i < positions.length; i++) { - var p = positions[i]; - var x = p[0], y = p[1], z = p[2]; - var d = positionVectors[i]; - var intensity = V.length(d) * invertedMaxNorm; - for (var k = 0, l = 8; k < l; k++) { - geo.positions.push([x, y, z, j++]); - geo.positions.push([x, y, z, j++]); - geo.positions.push([x, y, z, j++]); - geo.positions.push([x, y, z, j++]); - geo.positions.push([x, y, z, j++]); - geo.positions.push([x, y, z, j++]); - - geo.vectors.push(d); - geo.vectors.push(d); - geo.vectors.push(d); - geo.vectors.push(d); - geo.vectors.push(d); - geo.vectors.push(d); - - geo.vertexIntensity.push(intensity, intensity, intensity); - geo.vertexIntensity.push(intensity, intensity, intensity); - - geo.vertexNormals.push(nml, nml, nml); - geo.vertexNormals.push(nml, nml, nml); - - var m = geo.positions.length; - geo.cells.push([m-6, m-5, m-4], [m-3, m-2, m-1]); - } - } - - return geo; -}; - -module.exports.createConeMesh = _dereq_('./lib/conemesh'); - -},{"./lib/conemesh":243,"gl-vec3":346}],243:[function(_dereq_,module,exports){ -'use strict' - -var DEFAULT_VERTEX_NORMALS_EPSILON = 1e-6; // may be too large if triangles are very small -var DEFAULT_FACE_NORMALS_EPSILON = 1e-6; - -var createShader = _dereq_('gl-shader') -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') -var createTexture = _dereq_('gl-texture2d') -var normals = _dereq_('normals') -var multiply = _dereq_('gl-mat4/multiply') -var invert = _dereq_('gl-mat4/invert') -var ndarray = _dereq_('ndarray') -var colormap = _dereq_('colormap') -var getContour = _dereq_('simplicial-complex-contour') -var pool = _dereq_('typedarray-pool') -var shaders = _dereq_('./shaders') - -var meshShader = shaders.meshShader -var pickShader = shaders.pickShader - -var IDENTITY = [ - 1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1] - -function SimplicialMesh(gl - , texture - , triShader - , pickShader - , trianglePositions - , triangleVectors - , triangleIds - , triangleColors - , triangleUVs - , triangleNormals - , triangleVAO - , edgePositions - , edgeIds - , edgeColors - , edgeUVs - , edgeVAO - , pointPositions - , pointIds - , pointColors - , pointUVs - , pointSizes - , pointVAO - , contourPositions - , contourVAO) { - - this.gl = gl - this.pixelRatio = 1 - this.cells = [] - this.positions = [] - this.intensity = [] - this.texture = texture - this.dirty = true - - this.triShader = triShader - this.pickShader = pickShader - - this.trianglePositions = trianglePositions - this.triangleVectors = triangleVectors - this.triangleColors = triangleColors - this.triangleNormals = triangleNormals - this.triangleUVs = triangleUVs - this.triangleIds = triangleIds - this.triangleVAO = triangleVAO - this.triangleCount = 0 - - this.lineWidth = 1 - this.edgePositions = edgePositions - this.edgeColors = edgeColors - this.edgeUVs = edgeUVs - this.edgeIds = edgeIds - this.edgeVAO = edgeVAO - this.edgeCount = 0 - - this.pointPositions = pointPositions - this.pointColors = pointColors - this.pointUVs = pointUVs - this.pointSizes = pointSizes - this.pointIds = pointIds - this.pointVAO = pointVAO - this.pointCount = 0 - - this.contourLineWidth = 1 - this.contourPositions = contourPositions - this.contourVAO = contourVAO - this.contourCount = 0 - this.contourColor = [0,0,0] - this.contourEnable = true - - this.pickId = 1 - this.bounds = [ - [ Infinity, Infinity, Infinity], - [-Infinity,-Infinity,-Infinity] ] - this.clipBounds = [ - [-Infinity,-Infinity,-Infinity], - [ Infinity, Infinity, Infinity] ] - - this.lightPosition = [1e5, 1e5, 0] - this.ambientLight = 0.8 - this.diffuseLight = 0.8 - this.specularLight = 2.0 - this.roughness = 0.5 - this.fresnel = 1.5 - - this.opacity = 1.0 - - this.coneScale = 2.0 - this.vectorScale = 1.0 - this.coneOffset = 1.0 / 4.0; - - this._model = IDENTITY - this._view = IDENTITY - this._projection = IDENTITY - this._resolution = [1,1] -} - -var proto = SimplicialMesh.prototype - -proto.isOpaque = function() { - return this.opacity >= 1 -} - -proto.isTransparent = function() { - return this.opacity < 1 -} - -proto.pickSlots = 1 - -proto.setPickBase = function(id) { - this.pickId = id -} - -function genColormap(param) { - var colors = colormap({ - colormap: param - , nshades: 256 - , format: 'rgba' - }) - - var result = new Uint8Array(256*4) - for(var i=0; i<256; ++i) { - var c = colors[i] - for(var j=0; j<3; ++j) { - result[4*i+j] = c[j] - } - result[4*i+3] = c[3]*255 - } - - return ndarray(result, [256,256,4], [4,0,1]) -} - -function unpackIntensity(cells, numVerts, cellIntensity) { - var result = new Array(numVerts) - for(var i=0; i 0) { - var shader = this.triShader - shader.bind() - shader.uniforms = uniforms - - this.triangleVAO.bind() - gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) - this.triangleVAO.unbind() - } -} -proto.drawPick = function(params) { - params = params || {} - - var gl = this.gl - - var model = params.model || IDENTITY - var view = params.view || IDENTITY - var projection = params.projection || IDENTITY - - var clipBounds = [[-1e6,-1e6,-1e6],[1e6,1e6,1e6]] - for(var i=0; i<3; ++i) { - clipBounds[0][i] = Math.max(clipBounds[0][i], this.clipBounds[0][i]) - clipBounds[1][i] = Math.min(clipBounds[1][i], this.clipBounds[1][i]) - } - - //Save camera parameters - this._model = [].slice.call(model) - this._view = [].slice.call(view) - this._projection = [].slice.call(projection) - this._resolution = [gl.drawingBufferWidth, gl.drawingBufferHeight] - - var uniforms = { - model: model, - view: view, - projection: projection, - clipBounds: clipBounds, - - vectorScale: this.vectorScale, - coneScale: this.coneScale, - coneOffset: this.coneOffset, - - pickId: this.pickId / 255.0, - } - - var shader = this.pickShader - shader.bind() - shader.uniforms = uniforms - - if(this.triangleCount > 0) { - this.triangleVAO.bind() - gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) - this.triangleVAO.unbind() - } - - if(this.edgeCount > 0) { - this.edgeVAO.bind() - gl.lineWidth(this.lineWidth * this.pixelRatio) - gl.drawArrays(gl.LINES, 0, this.edgeCount*2) - this.edgeVAO.unbind() - } - -} - - -proto.pick = function(pickData) { - if(!pickData) { - return null - } - if(pickData.id !== this.pickId) { - return null - } - - var cellId = pickData.value[0] + 256*pickData.value[1] + 65536*pickData.value[2] - var cell = this.cells[cellId] - var pos = this.positions[cell[1]].slice(0, 3) - - return { - // corresponding to input indices - index: Math.floor(cell[1] / 48), - position: pos, - dataCoordinate: pos - } -} - - -proto.dispose = function() { - this.texture.dispose() - - this.triShader.dispose() - this.pickShader.dispose() - - this.triangleVAO.dispose() - this.trianglePositions.dispose() - this.triangleVectors.dispose() - this.triangleColors.dispose() - this.triangleUVs.dispose() - this.triangleNormals.dispose() - this.triangleIds.dispose() - - this.edgeVAO.dispose() - this.edgePositions.dispose() - this.edgeColors.dispose() - this.edgeUVs.dispose() - this.edgeIds.dispose() - - this.pointVAO.dispose() - this.pointPositions.dispose() - this.pointColors.dispose() - this.pointUVs.dispose() - this.pointSizes.dispose() - this.pointIds.dispose() - - this.contourVAO.dispose() - this.contourPositions.dispose() -} - -function createMeshShader(gl) { - // need to pass meshShader attributes manually, - // to make this work on etpinard's Ubuntu Thinkpad - var shader = createShader(gl, meshShader.vertex, meshShader.fragment, null, meshShader.attributes) - shader.attributes.position.location = 0 - shader.attributes.color.location = 2 - shader.attributes.uv.location = 3 - shader.attributes.vector.location = 5 - return shader -} - - -function createPickShader(gl) { - var shader = createShader(gl, pickShader.vertex, pickShader.fragment, null, pickShader.attributes) - shader.attributes.position.location = 0 - shader.attributes.id.location = 1 - shader.attributes.vector.location = 5 - return shader -} - - - -function createSimplicialMesh(gl, params) { - if (arguments.length === 1) { - params = gl; - gl = params.gl; - } - - - var triShader = params.triShader || createMeshShader(gl) - var pickShader = createPickShader(gl) - var meshTexture = createTexture(gl, - ndarray(new Uint8Array([255,255,255,255]), [1,1,4])) - meshTexture.generateMipmap() - meshTexture.minFilter = gl.LINEAR_MIPMAP_LINEAR - meshTexture.magFilter = gl.LINEAR - - var trianglePositions = createBuffer(gl) - var triangleVectors = createBuffer(gl) - var triangleColors = createBuffer(gl) - var triangleUVs = createBuffer(gl) - var triangleNormals = createBuffer(gl) - var triangleIds = createBuffer(gl) - var triangleVAO = createVAO(gl, [ - { buffer: trianglePositions, - type: gl.FLOAT, - size: 4 - }, - { buffer: triangleIds, - type: gl.UNSIGNED_BYTE, - size: 4, - normalized: true - }, - { buffer: triangleColors, - type: gl.FLOAT, - size: 4 - }, - { buffer: triangleUVs, - type: gl.FLOAT, - size: 2 - }, - { buffer: triangleNormals, - type: gl.FLOAT, - size: 3 - }, - { buffer: triangleVectors, - type: gl.FLOAT, - size: 3 - } - ]) - - var edgePositions = createBuffer(gl) - var edgeColors = createBuffer(gl) - var edgeUVs = createBuffer(gl) - var edgeIds = createBuffer(gl) - var edgeVAO = createVAO(gl, [ - { buffer: edgePositions, - type: gl.FLOAT, - size: 3 - }, - { buffer: edgeIds, - type: gl.UNSIGNED_BYTE, - size: 4, - normalized: true - }, - { buffer: edgeColors, - type: gl.FLOAT, - size: 4 - }, - { buffer: edgeUVs, - type: gl.FLOAT, - size: 2 - } - ]) - - var pointPositions = createBuffer(gl) - var pointColors = createBuffer(gl) - var pointUVs = createBuffer(gl) - var pointSizes = createBuffer(gl) - var pointIds = createBuffer(gl) - var pointVAO = createVAO(gl, [ - { buffer: pointPositions, - type: gl.FLOAT, - size: 3 - }, - { buffer: pointIds, - type: gl.UNSIGNED_BYTE, - size: 4, - normalized: true - }, - { buffer: pointColors, - type: gl.FLOAT, - size: 4 - }, - { buffer: pointUVs, - type: gl.FLOAT, - size: 2 - }, - { buffer: pointSizes, - type: gl.FLOAT, - size: 1 - } - ]) - - var contourPositions = createBuffer(gl) - var contourVAO = createVAO(gl, [ - { buffer: contourPositions, - type: gl.FLOAT, - size: 3 - }]) - - var mesh = new SimplicialMesh(gl - , meshTexture - , triShader - , pickShader - , trianglePositions - , triangleVectors - , triangleIds - , triangleColors - , triangleUVs - , triangleNormals - , triangleVAO - , edgePositions - , edgeIds - , edgeColors - , edgeUVs - , edgeVAO - , pointPositions - , pointIds - , pointColors - , pointUVs - , pointSizes - , pointVAO - , contourPositions - , contourVAO) - - mesh.update(params) - - return mesh -} - -module.exports = createSimplicialMesh - -},{"./shaders":244,"colormap":126,"gl-buffer":241,"gl-mat4/invert":265,"gl-mat4/multiply":267,"gl-shader":301,"gl-texture2d":322,"gl-vao":327,"ndarray":450,"normals":453,"simplicial-complex-contour":518,"typedarray-pool":545}],244:[function(_dereq_,module,exports){ -var glslify = _dereq_('glslify') - -var triVertSrc = glslify(["precision highp float;\n\nprecision highp float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the cone vertex and normal at the given index.\n//\n// The returned vertex is for a cone with its top at origin and height of 1.0,\n// pointing in the direction of the vector attribute.\n//\n// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.\n// These vertices are used to make up the triangles of the cone by the following:\n// segment + 0 top vertex\n// segment + 1 perimeter vertex a+1\n// segment + 2 perimeter vertex a\n// segment + 3 center base vertex\n// segment + 4 perimeter vertex a\n// segment + 5 perimeter vertex a+1\n// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.\n// To go from index to segment, floor(index / 6)\n// To go from segment to angle, 2*pi * (segment/segmentCount)\n// To go from index to segment index, index - (segment*6)\n//\nvec3 getConePosition(vec3 d, float rawIndex, float coneOffset, out vec3 normal) {\n\n const float segmentCount = 8.0;\n\n float index = rawIndex - floor(rawIndex /\n (segmentCount * 6.0)) *\n (segmentCount * 6.0);\n\n float segment = floor(0.001 + index/6.0);\n float segmentIndex = index - (segment*6.0);\n\n normal = -normalize(d);\n\n if (segmentIndex > 2.99 && segmentIndex < 3.01) {\n return mix(vec3(0.0), -d, coneOffset);\n }\n\n float nextAngle = (\n (segmentIndex > 0.99 && segmentIndex < 1.01) ||\n (segmentIndex > 4.99 && segmentIndex < 5.01)\n ) ? 1.0 : 0.0;\n float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);\n\n vec3 v1 = mix(d, vec3(0.0), coneOffset);\n vec3 v2 = v1 - d;\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d)*0.25;\n vec3 y = v * sin(angle) * length(d)*0.25;\n vec3 v3 = v2 + x + y;\n if (segmentIndex < 3.0) {\n vec3 tx = u * sin(angle);\n vec3 ty = v * -cos(angle);\n vec3 tangent = tx + ty;\n normal = normalize(cross(v3 - v1, tangent));\n }\n\n if (segmentIndex == 0.0) {\n return mix(d, vec3(0.0), coneOffset);\n }\n return v3;\n}\n\nattribute vec3 vector;\nattribute vec4 color, position;\nattribute vec2 uv;\nuniform float vectorScale;\nuniform float coneScale;\n\nuniform float coneOffset;\n\nuniform mat4 model\n , view\n , projection\n , inverseModel;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n // Scale the vector magnitude to stay constant with\n // model & view changes.\n vec3 normal;\n vec3 XYZ = getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, coneOffset, normal);\n vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n\n //Lighting geometry parameters\n vec4 cameraCoordinate = view * conePosition;\n cameraCoordinate.xyz /= cameraCoordinate.w;\n f_lightDirection = lightPosition - cameraCoordinate.xyz;\n f_eyeDirection = eyePosition - cameraCoordinate.xyz;\n f_normal = normalize((vec4(normal,0.0) * inverseModel).xyz);\n\n // vec4 m_position = model * vec4(conePosition, 1.0);\n vec4 t_position = view * conePosition;\n gl_Position = projection * t_position;\n\n f_color = color;\n f_data = conePosition.xyz;\n f_position = position.xyz;\n f_uv = uv;\n}\n"]) -var triFragSrc = glslify(["#extension GL_OES_standard_derivatives : enable\n\nprecision highp float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = min(1.0, max(0.0, cookTorranceSpecular(L, V, N, roughness, fresnel)));\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = f_color * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}\n"]) -var pickVertSrc = glslify(["precision highp float;\n\nprecision highp float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the cone vertex and normal at the given index.\n//\n// The returned vertex is for a cone with its top at origin and height of 1.0,\n// pointing in the direction of the vector attribute.\n//\n// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.\n// These vertices are used to make up the triangles of the cone by the following:\n// segment + 0 top vertex\n// segment + 1 perimeter vertex a+1\n// segment + 2 perimeter vertex a\n// segment + 3 center base vertex\n// segment + 4 perimeter vertex a\n// segment + 5 perimeter vertex a+1\n// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.\n// To go from index to segment, floor(index / 6)\n// To go from segment to angle, 2*pi * (segment/segmentCount)\n// To go from index to segment index, index - (segment*6)\n//\nvec3 getConePosition(vec3 d, float rawIndex, float coneOffset, out vec3 normal) {\n\n const float segmentCount = 8.0;\n\n float index = rawIndex - floor(rawIndex /\n (segmentCount * 6.0)) *\n (segmentCount * 6.0);\n\n float segment = floor(0.001 + index/6.0);\n float segmentIndex = index - (segment*6.0);\n\n normal = -normalize(d);\n\n if (segmentIndex > 2.99 && segmentIndex < 3.01) {\n return mix(vec3(0.0), -d, coneOffset);\n }\n\n float nextAngle = (\n (segmentIndex > 0.99 && segmentIndex < 1.01) ||\n (segmentIndex > 4.99 && segmentIndex < 5.01)\n ) ? 1.0 : 0.0;\n float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);\n\n vec3 v1 = mix(d, vec3(0.0), coneOffset);\n vec3 v2 = v1 - d;\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d)*0.25;\n vec3 y = v * sin(angle) * length(d)*0.25;\n vec3 v3 = v2 + x + y;\n if (segmentIndex < 3.0) {\n vec3 tx = u * sin(angle);\n vec3 ty = v * -cos(angle);\n vec3 tangent = tx + ty;\n normal = normalize(cross(v3 - v1, tangent));\n }\n\n if (segmentIndex == 0.0) {\n return mix(d, vec3(0.0), coneOffset);\n }\n return v3;\n}\n\nattribute vec3 vector;\nattribute vec4 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\n\nuniform float vectorScale;\nuniform float coneScale;\nuniform float coneOffset;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n vec3 normal;\n vec3 XYZ = getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, coneOffset, normal);\n vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n gl_Position = projection * view * conePosition;\n f_id = id;\n f_position = position.xyz;\n}\n"]) -var pickFragSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]) - -exports.meshShader = { - vertex: triVertSrc, - fragment: triFragSrc, - attributes: [ - {name: 'position', type: 'vec4'}, - {name: 'normal', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'uv', type: 'vec2'}, - {name: 'vector', type: 'vec3'} - ] -} -exports.pickShader = { - vertex: pickVertSrc, - fragment: pickFragSrc, - attributes: [ - {name: 'position', type: 'vec4'}, - {name: 'id', type: 'vec4'}, - {name: 'vector', type: 'vec3'} - ] -} - -},{"glslify":409}],245:[function(_dereq_,module,exports){ -module.exports = { - 0: 'NONE', - 1: 'ONE', - 2: 'LINE_LOOP', - 3: 'LINE_STRIP', - 4: 'TRIANGLES', - 5: 'TRIANGLE_STRIP', - 6: 'TRIANGLE_FAN', - 256: 'DEPTH_BUFFER_BIT', - 512: 'NEVER', - 513: 'LESS', - 514: 'EQUAL', - 515: 'LEQUAL', - 516: 'GREATER', - 517: 'NOTEQUAL', - 518: 'GEQUAL', - 519: 'ALWAYS', - 768: 'SRC_COLOR', - 769: 'ONE_MINUS_SRC_COLOR', - 770: 'SRC_ALPHA', - 771: 'ONE_MINUS_SRC_ALPHA', - 772: 'DST_ALPHA', - 773: 'ONE_MINUS_DST_ALPHA', - 774: 'DST_COLOR', - 775: 'ONE_MINUS_DST_COLOR', - 776: 'SRC_ALPHA_SATURATE', - 1024: 'STENCIL_BUFFER_BIT', - 1028: 'FRONT', - 1029: 'BACK', - 1032: 'FRONT_AND_BACK', - 1280: 'INVALID_ENUM', - 1281: 'INVALID_VALUE', - 1282: 'INVALID_OPERATION', - 1285: 'OUT_OF_MEMORY', - 1286: 'INVALID_FRAMEBUFFER_OPERATION', - 2304: 'CW', - 2305: 'CCW', - 2849: 'LINE_WIDTH', - 2884: 'CULL_FACE', - 2885: 'CULL_FACE_MODE', - 2886: 'FRONT_FACE', - 2928: 'DEPTH_RANGE', - 2929: 'DEPTH_TEST', - 2930: 'DEPTH_WRITEMASK', - 2931: 'DEPTH_CLEAR_VALUE', - 2932: 'DEPTH_FUNC', - 2960: 'STENCIL_TEST', - 2961: 'STENCIL_CLEAR_VALUE', - 2962: 'STENCIL_FUNC', - 2963: 'STENCIL_VALUE_MASK', - 2964: 'STENCIL_FAIL', - 2965: 'STENCIL_PASS_DEPTH_FAIL', - 2966: 'STENCIL_PASS_DEPTH_PASS', - 2967: 'STENCIL_REF', - 2968: 'STENCIL_WRITEMASK', - 2978: 'VIEWPORT', - 3024: 'DITHER', - 3042: 'BLEND', - 3088: 'SCISSOR_BOX', - 3089: 'SCISSOR_TEST', - 3106: 'COLOR_CLEAR_VALUE', - 3107: 'COLOR_WRITEMASK', - 3317: 'UNPACK_ALIGNMENT', - 3333: 'PACK_ALIGNMENT', - 3379: 'MAX_TEXTURE_SIZE', - 3386: 'MAX_VIEWPORT_DIMS', - 3408: 'SUBPIXEL_BITS', - 3410: 'RED_BITS', - 3411: 'GREEN_BITS', - 3412: 'BLUE_BITS', - 3413: 'ALPHA_BITS', - 3414: 'DEPTH_BITS', - 3415: 'STENCIL_BITS', - 3553: 'TEXTURE_2D', - 4352: 'DONT_CARE', - 4353: 'FASTEST', - 4354: 'NICEST', - 5120: 'BYTE', - 5121: 'UNSIGNED_BYTE', - 5122: 'SHORT', - 5123: 'UNSIGNED_SHORT', - 5124: 'INT', - 5125: 'UNSIGNED_INT', - 5126: 'FLOAT', - 5386: 'INVERT', - 5890: 'TEXTURE', - 6401: 'STENCIL_INDEX', - 6402: 'DEPTH_COMPONENT', - 6406: 'ALPHA', - 6407: 'RGB', - 6408: 'RGBA', - 6409: 'LUMINANCE', - 6410: 'LUMINANCE_ALPHA', - 7680: 'KEEP', - 7681: 'REPLACE', - 7682: 'INCR', - 7683: 'DECR', - 7936: 'VENDOR', - 7937: 'RENDERER', - 7938: 'VERSION', - 9728: 'NEAREST', - 9729: 'LINEAR', - 9984: 'NEAREST_MIPMAP_NEAREST', - 9985: 'LINEAR_MIPMAP_NEAREST', - 9986: 'NEAREST_MIPMAP_LINEAR', - 9987: 'LINEAR_MIPMAP_LINEAR', - 10240: 'TEXTURE_MAG_FILTER', - 10241: 'TEXTURE_MIN_FILTER', - 10242: 'TEXTURE_WRAP_S', - 10243: 'TEXTURE_WRAP_T', - 10497: 'REPEAT', - 10752: 'POLYGON_OFFSET_UNITS', - 16384: 'COLOR_BUFFER_BIT', - 32769: 'CONSTANT_COLOR', - 32770: 'ONE_MINUS_CONSTANT_COLOR', - 32771: 'CONSTANT_ALPHA', - 32772: 'ONE_MINUS_CONSTANT_ALPHA', - 32773: 'BLEND_COLOR', - 32774: 'FUNC_ADD', - 32777: 'BLEND_EQUATION_RGB', - 32778: 'FUNC_SUBTRACT', - 32779: 'FUNC_REVERSE_SUBTRACT', - 32819: 'UNSIGNED_SHORT_4_4_4_4', - 32820: 'UNSIGNED_SHORT_5_5_5_1', - 32823: 'POLYGON_OFFSET_FILL', - 32824: 'POLYGON_OFFSET_FACTOR', - 32854: 'RGBA4', - 32855: 'RGB5_A1', - 32873: 'TEXTURE_BINDING_2D', - 32926: 'SAMPLE_ALPHA_TO_COVERAGE', - 32928: 'SAMPLE_COVERAGE', - 32936: 'SAMPLE_BUFFERS', - 32937: 'SAMPLES', - 32938: 'SAMPLE_COVERAGE_VALUE', - 32939: 'SAMPLE_COVERAGE_INVERT', - 32968: 'BLEND_DST_RGB', - 32969: 'BLEND_SRC_RGB', - 32970: 'BLEND_DST_ALPHA', - 32971: 'BLEND_SRC_ALPHA', - 33071: 'CLAMP_TO_EDGE', - 33170: 'GENERATE_MIPMAP_HINT', - 33189: 'DEPTH_COMPONENT16', - 33306: 'DEPTH_STENCIL_ATTACHMENT', - 33635: 'UNSIGNED_SHORT_5_6_5', - 33648: 'MIRRORED_REPEAT', - 33901: 'ALIASED_POINT_SIZE_RANGE', - 33902: 'ALIASED_LINE_WIDTH_RANGE', - 33984: 'TEXTURE0', - 33985: 'TEXTURE1', - 33986: 'TEXTURE2', - 33987: 'TEXTURE3', - 33988: 'TEXTURE4', - 33989: 'TEXTURE5', - 33990: 'TEXTURE6', - 33991: 'TEXTURE7', - 33992: 'TEXTURE8', - 33993: 'TEXTURE9', - 33994: 'TEXTURE10', - 33995: 'TEXTURE11', - 33996: 'TEXTURE12', - 33997: 'TEXTURE13', - 33998: 'TEXTURE14', - 33999: 'TEXTURE15', - 34000: 'TEXTURE16', - 34001: 'TEXTURE17', - 34002: 'TEXTURE18', - 34003: 'TEXTURE19', - 34004: 'TEXTURE20', - 34005: 'TEXTURE21', - 34006: 'TEXTURE22', - 34007: 'TEXTURE23', - 34008: 'TEXTURE24', - 34009: 'TEXTURE25', - 34010: 'TEXTURE26', - 34011: 'TEXTURE27', - 34012: 'TEXTURE28', - 34013: 'TEXTURE29', - 34014: 'TEXTURE30', - 34015: 'TEXTURE31', - 34016: 'ACTIVE_TEXTURE', - 34024: 'MAX_RENDERBUFFER_SIZE', - 34041: 'DEPTH_STENCIL', - 34055: 'INCR_WRAP', - 34056: 'DECR_WRAP', - 34067: 'TEXTURE_CUBE_MAP', - 34068: 'TEXTURE_BINDING_CUBE_MAP', - 34069: 'TEXTURE_CUBE_MAP_POSITIVE_X', - 34070: 'TEXTURE_CUBE_MAP_NEGATIVE_X', - 34071: 'TEXTURE_CUBE_MAP_POSITIVE_Y', - 34072: 'TEXTURE_CUBE_MAP_NEGATIVE_Y', - 34073: 'TEXTURE_CUBE_MAP_POSITIVE_Z', - 34074: 'TEXTURE_CUBE_MAP_NEGATIVE_Z', - 34076: 'MAX_CUBE_MAP_TEXTURE_SIZE', - 34338: 'VERTEX_ATTRIB_ARRAY_ENABLED', - 34339: 'VERTEX_ATTRIB_ARRAY_SIZE', - 34340: 'VERTEX_ATTRIB_ARRAY_STRIDE', - 34341: 'VERTEX_ATTRIB_ARRAY_TYPE', - 34342: 'CURRENT_VERTEX_ATTRIB', - 34373: 'VERTEX_ATTRIB_ARRAY_POINTER', - 34466: 'NUM_COMPRESSED_TEXTURE_FORMATS', - 34467: 'COMPRESSED_TEXTURE_FORMATS', - 34660: 'BUFFER_SIZE', - 34661: 'BUFFER_USAGE', - 34816: 'STENCIL_BACK_FUNC', - 34817: 'STENCIL_BACK_FAIL', - 34818: 'STENCIL_BACK_PASS_DEPTH_FAIL', - 34819: 'STENCIL_BACK_PASS_DEPTH_PASS', - 34877: 'BLEND_EQUATION_ALPHA', - 34921: 'MAX_VERTEX_ATTRIBS', - 34922: 'VERTEX_ATTRIB_ARRAY_NORMALIZED', - 34930: 'MAX_TEXTURE_IMAGE_UNITS', - 34962: 'ARRAY_BUFFER', - 34963: 'ELEMENT_ARRAY_BUFFER', - 34964: 'ARRAY_BUFFER_BINDING', - 34965: 'ELEMENT_ARRAY_BUFFER_BINDING', - 34975: 'VERTEX_ATTRIB_ARRAY_BUFFER_BINDING', - 35040: 'STREAM_DRAW', - 35044: 'STATIC_DRAW', - 35048: 'DYNAMIC_DRAW', - 35632: 'FRAGMENT_SHADER', - 35633: 'VERTEX_SHADER', - 35660: 'MAX_VERTEX_TEXTURE_IMAGE_UNITS', - 35661: 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', - 35663: 'SHADER_TYPE', - 35664: 'FLOAT_VEC2', - 35665: 'FLOAT_VEC3', - 35666: 'FLOAT_VEC4', - 35667: 'INT_VEC2', - 35668: 'INT_VEC3', - 35669: 'INT_VEC4', - 35670: 'BOOL', - 35671: 'BOOL_VEC2', - 35672: 'BOOL_VEC3', - 35673: 'BOOL_VEC4', - 35674: 'FLOAT_MAT2', - 35675: 'FLOAT_MAT3', - 35676: 'FLOAT_MAT4', - 35678: 'SAMPLER_2D', - 35680: 'SAMPLER_CUBE', - 35712: 'DELETE_STATUS', - 35713: 'COMPILE_STATUS', - 35714: 'LINK_STATUS', - 35715: 'VALIDATE_STATUS', - 35716: 'INFO_LOG_LENGTH', - 35717: 'ATTACHED_SHADERS', - 35718: 'ACTIVE_UNIFORMS', - 35719: 'ACTIVE_UNIFORM_MAX_LENGTH', - 35720: 'SHADER_SOURCE_LENGTH', - 35721: 'ACTIVE_ATTRIBUTES', - 35722: 'ACTIVE_ATTRIBUTE_MAX_LENGTH', - 35724: 'SHADING_LANGUAGE_VERSION', - 35725: 'CURRENT_PROGRAM', - 36003: 'STENCIL_BACK_REF', - 36004: 'STENCIL_BACK_VALUE_MASK', - 36005: 'STENCIL_BACK_WRITEMASK', - 36006: 'FRAMEBUFFER_BINDING', - 36007: 'RENDERBUFFER_BINDING', - 36048: 'FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE', - 36049: 'FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', - 36050: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL', - 36051: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE', - 36053: 'FRAMEBUFFER_COMPLETE', - 36054: 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT', - 36055: 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT', - 36057: 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS', - 36061: 'FRAMEBUFFER_UNSUPPORTED', - 36064: 'COLOR_ATTACHMENT0', - 36096: 'DEPTH_ATTACHMENT', - 36128: 'STENCIL_ATTACHMENT', - 36160: 'FRAMEBUFFER', - 36161: 'RENDERBUFFER', - 36162: 'RENDERBUFFER_WIDTH', - 36163: 'RENDERBUFFER_HEIGHT', - 36164: 'RENDERBUFFER_INTERNAL_FORMAT', - 36168: 'STENCIL_INDEX8', - 36176: 'RENDERBUFFER_RED_SIZE', - 36177: 'RENDERBUFFER_GREEN_SIZE', - 36178: 'RENDERBUFFER_BLUE_SIZE', - 36179: 'RENDERBUFFER_ALPHA_SIZE', - 36180: 'RENDERBUFFER_DEPTH_SIZE', - 36181: 'RENDERBUFFER_STENCIL_SIZE', - 36194: 'RGB565', - 36336: 'LOW_FLOAT', - 36337: 'MEDIUM_FLOAT', - 36338: 'HIGH_FLOAT', - 36339: 'LOW_INT', - 36340: 'MEDIUM_INT', - 36341: 'HIGH_INT', - 36346: 'SHADER_COMPILER', - 36347: 'MAX_VERTEX_UNIFORM_VECTORS', - 36348: 'MAX_VARYING_VECTORS', - 36349: 'MAX_FRAGMENT_UNIFORM_VECTORS', - 37440: 'UNPACK_FLIP_Y_WEBGL', - 37441: 'UNPACK_PREMULTIPLY_ALPHA_WEBGL', - 37442: 'CONTEXT_LOST_WEBGL', - 37443: 'UNPACK_COLORSPACE_CONVERSION_WEBGL', - 37444: 'BROWSER_DEFAULT_WEBGL' -} - -},{}],246:[function(_dereq_,module,exports){ -var gl10 = _dereq_('./1.0/numbers') - -module.exports = function lookupConstant (number) { - return gl10[number] -} - -},{"./1.0/numbers":245}],247:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createErrorBars - -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') -var createShader = _dereq_('./shaders/index') - -var IDENTITY = [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1] - -function ErrorBars(gl, buffer, vao, shader) { - this.gl = gl - this.shader = shader - this.buffer = buffer - this.vao = vao - this.pixelRatio = 1 - this.bounds = [[ Infinity, Infinity, Infinity], [-Infinity,-Infinity,-Infinity]] - this.clipBounds = [[-Infinity,-Infinity,-Infinity], [ Infinity, Infinity, Infinity]] - this.lineWidth = [1,1,1] - this.capSize = [10,10,10] - this.lineCount = [0,0,0] - this.lineOffset = [0,0,0] - this.opacity = 1 - this.hasAlpha = false -} - -var proto = ErrorBars.prototype - -proto.isOpaque = function() { - return !this.hasAlpha -} - -proto.isTransparent = function() { - return this.hasAlpha -} - -proto.drawTransparent = proto.draw = function(cameraParams) { - var gl = this.gl - var uniforms = this.shader.uniforms - - this.shader.bind() - var view = uniforms.view = cameraParams.view || IDENTITY - var projection = uniforms.projection = cameraParams.projection || IDENTITY - uniforms.model = cameraParams.model || IDENTITY - uniforms.clipBounds = this.clipBounds - uniforms.opacity = this.opacity - - - var cx = view[12] - var cy = view[13] - var cz = view[14] - var cw = view[15] - - var isOrtho = cameraParams._ortho || false - var orthoFix = (isOrtho) ? 2 : 1 // double up padding for orthographic ticks & labels - var pixelScaleF = orthoFix * this.pixelRatio * (projection[3]*cx + projection[7]*cy + projection[11]*cz + projection[15]*cw) / gl.drawingBufferHeight - - this.vao.bind() - for(var i=0; i<3; ++i) { - gl.lineWidth(this.lineWidth[i] * this.pixelRatio) - uniforms.capSize = this.capSize[i] * pixelScaleF - if (this.lineCount[i]) { - gl.drawArrays(gl.LINES, this.lineOffset[i], this.lineCount[i]) - } - } - this.vao.unbind() -} - -function updateBounds(bounds, point) { - for(var i=0; i<3; ++i) { - bounds[0][i] = Math.min(bounds[0][i], point[i]) - bounds[1][i] = Math.max(bounds[1][i], point[i]) - } -} - -var FACE_TABLE = (function(){ - var table = new Array(3) - for(var d=0; d<3; ++d) { - var row = [] - for(var j=1; j<=2; ++j) { - for(var s=-1; s<=1; s+=2) { - var u = (j+d) % 3 - var y = [0,0,0] - y[u] = s - row.push(y) - } - } - table[d] = row - } - return table -})() - - -function emitFace(verts, x, c, d) { - var offsets = FACE_TABLE[d] - for(var i=0; i 0) { - var x = p.slice() - x[j] += e[1][j] - verts.push(p[0], p[1], p[2], - c[0], c[1], c[2], c[3], - 0, 0, 0, - x[0], x[1], x[2], - c[0], c[1], c[2], c[3], - 0, 0, 0) - updateBounds(this.bounds, x) - vertexCount += 2 + emitFace(verts, x, c, j) - } - } - this.lineCount[j] = vertexCount - this.lineOffset[j] - } - this.buffer.update(verts) - } -} - -proto.dispose = function() { - this.shader.dispose() - this.buffer.dispose() - this.vao.dispose() -} - -function createErrorBars(options) { - var gl = options.gl - var buffer = createBuffer(gl) - var vao = createVAO(gl, [ - { - buffer: buffer, - type: gl.FLOAT, - size: 3, - offset: 0, - stride: 40 - }, - { - buffer: buffer, - type: gl.FLOAT, - size: 4, - offset: 12, - stride: 40 - }, - { - buffer: buffer, - type: gl.FLOAT, - size: 3, - offset: 28, - stride: 40 - } - ]) - - var shader = createShader(gl) - shader.attributes.position.location = 0 - shader.attributes.color.location = 1 - shader.attributes.offset.location = 2 - - var result = new ErrorBars(gl, buffer, vao, shader) - result.update(options) - return result -} - -},{"./shaders/index":248,"gl-buffer":241,"gl-vao":327}],248:[function(_dereq_,module,exports){ -'use strict' - -var glslify = _dereq_('glslify') -var createShader = _dereq_('gl-shader') - -var vertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position, offset;\nattribute vec4 color;\nuniform mat4 model, view, projection;\nuniform float capSize;\nvarying vec4 fragColor;\nvarying vec3 fragPosition;\n\nvoid main() {\n vec4 worldPosition = model * vec4(position, 1.0);\n worldPosition = (worldPosition / worldPosition.w) + vec4(capSize * offset, 0.0);\n gl_Position = projection * view * worldPosition;\n fragColor = color;\n fragPosition = position;\n}"]) -var fragSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float opacity;\nvarying vec3 fragPosition;\nvarying vec4 fragColor;\n\nvoid main() {\n if (\n outOfRange(clipBounds[0], clipBounds[1], fragPosition) ||\n fragColor.a * opacity == 0.\n ) discard;\n\n gl_FragColor = opacity * fragColor;\n}"]) - -module.exports = function(gl) { - return createShader(gl, vertSrc, fragSrc, null, [ - {name: 'position', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'offset', type: 'vec3'} - ]) -} - -},{"gl-shader":301,"glslify":409}],249:[function(_dereq_,module,exports){ -'use strict' - -var createTexture = _dereq_('gl-texture2d') - -module.exports = createFBO - -var colorAttachmentArrays = null -var FRAMEBUFFER_UNSUPPORTED -var FRAMEBUFFER_INCOMPLETE_ATTACHMENT -var FRAMEBUFFER_INCOMPLETE_DIMENSIONS -var FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT - -function saveFBOState(gl) { - var fbo = gl.getParameter(gl.FRAMEBUFFER_BINDING) - var rbo = gl.getParameter(gl.RENDERBUFFER_BINDING) - var tex = gl.getParameter(gl.TEXTURE_BINDING_2D) - return [fbo, rbo, tex] -} - -function restoreFBOState(gl, data) { - gl.bindFramebuffer(gl.FRAMEBUFFER, data[0]) - gl.bindRenderbuffer(gl.RENDERBUFFER, data[1]) - gl.bindTexture(gl.TEXTURE_2D, data[2]) -} - -function lazyInitColorAttachments(gl, ext) { - var maxColorAttachments = gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL) - colorAttachmentArrays = new Array(maxColorAttachments + 1) - for(var i=0; i<=maxColorAttachments; ++i) { - var x = new Array(maxColorAttachments) - for(var j=0; j 1) { - ext.drawBuffersWEBGL(colorAttachmentArrays[numColors]) - } - - //Allocate depth/stencil buffers - var WEBGL_depth_texture = gl.getExtension('WEBGL_depth_texture') - if(WEBGL_depth_texture) { - if(useStencil) { - fbo.depth = initTexture(gl, width, height, - WEBGL_depth_texture.UNSIGNED_INT_24_8_WEBGL, - gl.DEPTH_STENCIL, - gl.DEPTH_STENCIL_ATTACHMENT) - } else if(useDepth) { - fbo.depth = initTexture(gl, width, height, - gl.UNSIGNED_SHORT, - gl.DEPTH_COMPONENT, - gl.DEPTH_ATTACHMENT) - } - } else { - if(useDepth && useStencil) { - fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_STENCIL, gl.DEPTH_STENCIL_ATTACHMENT) - } else if(useDepth) { - fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_COMPONENT16, gl.DEPTH_ATTACHMENT) - } else if(useStencil) { - fbo._depth_rb = initRenderBuffer(gl, width, height, gl.STENCIL_INDEX, gl.STENCIL_ATTACHMENT) - } - } - - //Check frame buffer state - var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER) - if(status !== gl.FRAMEBUFFER_COMPLETE) { - - //Release all partially allocated resources - fbo._destroyed = true - - //Release all resources - gl.bindFramebuffer(gl.FRAMEBUFFER, null) - gl.deleteFramebuffer(fbo.handle) - fbo.handle = null - if(fbo.depth) { - fbo.depth.dispose() - fbo.depth = null - } - if(fbo._depth_rb) { - gl.deleteRenderbuffer(fbo._depth_rb) - fbo._depth_rb = null - } - for(var i=0; i maxFBOSize || - h < 0 || h > maxFBOSize) { - throw new Error('gl-fbo: Can\'t resize FBO, invalid dimensions') - } - - //Update shape - fbo._shape[0] = w - fbo._shape[1] = h - - //Save framebuffer state - var state = saveFBOState(gl) - - //Resize framebuffer attachments - for(var i=0; i maxFBOSize || height < 0 || height > maxFBOSize) { - throw new Error('gl-fbo: Parameters are too large for FBO') - } - - //Handle each option type - options = options || {} - - //Figure out number of color buffers to use - var numColors = 1 - if('color' in options) { - numColors = Math.max(options.color|0, 0) - if(numColors < 0) { - throw new Error('gl-fbo: Must specify a nonnegative number of colors') - } - if(numColors > 1) { - //Check if multiple render targets supported - if(!WEBGL_draw_buffers) { - throw new Error('gl-fbo: Multiple draw buffer extension not supported') - } else if(numColors > gl.getParameter(WEBGL_draw_buffers.MAX_COLOR_ATTACHMENTS_WEBGL)) { - throw new Error('gl-fbo: Context does not support ' + numColors + ' draw buffers') - } - } - } - - //Determine whether to use floating point textures - var colorType = gl.UNSIGNED_BYTE - var OES_texture_float = gl.getExtension('OES_texture_float') - if(options.float && numColors > 0) { - if(!OES_texture_float) { - throw new Error('gl-fbo: Context does not support floating point textures') - } - colorType = gl.FLOAT - } else if(options.preferFloat && numColors > 0) { - if(OES_texture_float) { - colorType = gl.FLOAT - } - } - - //Check if we should use depth buffer - var useDepth = true - if('depth' in options) { - useDepth = !!options.depth - } - - //Check if we should use a stencil buffer - var useStencil = false - if('stencil' in options) { - useStencil = !!options.stencil - } - - return new Framebuffer( - gl, - width, - height, - colorType, - numColors, - useDepth, - useStencil, - WEBGL_draw_buffers) -} - -},{"gl-texture2d":322}],250:[function(_dereq_,module,exports){ - -var sprintf = _dereq_('sprintf-js').sprintf; -var glConstants = _dereq_('gl-constants/lookup'); -var shaderName = _dereq_('glsl-shader-name'); -var addLineNumbers = _dereq_('add-line-numbers'); - -module.exports = formatCompilerError; - -function formatCompilerError(errLog, src, type) { - "use strict"; - - var name = shaderName(src) || 'of unknown name (see npm glsl-shader-name)'; - - var typeName = 'unknown type'; - if (type !== undefined) { - typeName = type === glConstants.FRAGMENT_SHADER ? 'fragment' : 'vertex' - } - - var longForm = sprintf('Error compiling %s shader %s:\n', typeName, name); - var shortForm = sprintf("%s%s", longForm, errLog); - - var errorStrings = errLog.split('\n'); - var errors = {}; - - for (var i = 0; i < errorStrings.length; i++) { - var errorString = errorStrings[i]; - if (errorString === '' || errorString === "\0") continue; - var lineNo = parseInt(errorString.split(':')[2]); - if (isNaN(lineNo)) { - throw new Error(sprintf('Could not parse error: %s', errorString)); - } - errors[lineNo] = errorString; - } - - var lines = addLineNumbers(src).split('\n'); - - for (var i = 0; i < lines.length; i++) { - if (!errors[i+3] && !errors[i+2] && !errors[i+1]) continue; - var line = lines[i]; - longForm += line + '\n'; - if (errors[i+1]) { - var e = errors[i+1]; - e = e.substr(e.split(':', 3).join(':').length + 1).trim(); - longForm += sprintf('^^^ %s\n\n', e); - } - } - - return { - long: longForm.trim(), - short: shortForm.trim() - }; -} - - -},{"add-line-numbers":61,"gl-constants/lookup":246,"glsl-shader-name":401,"sprintf-js":528}],251:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createHeatmap2D - -var bsearch = _dereq_('binary-search-bounds') -var iota = _dereq_('iota-array') -var pool = _dereq_('typedarray-pool') -var createShader = _dereq_('gl-shader') -var createBuffer = _dereq_('gl-buffer') - -var shaders = _dereq_('./lib/shaders') - -function GLHeatmap2D ( - plot, - shader, - pickShader, - positionBuffer, - weightBuffer, - colorBuffer, - idBuffer) { - this.plot = plot - this.shader = shader - this.pickShader = pickShader - this.positionBuffer = positionBuffer - this.weightBuffer = weightBuffer - this.colorBuffer = colorBuffer - this.idBuffer = idBuffer - this.xData = [] - this.yData = [] - this.shape = [0, 0] - this.bounds = [Infinity, Infinity, -Infinity, -Infinity] - this.pickOffset = 0 -} - -var proto = GLHeatmap2D.prototype - -var WEIGHTS = [ - 0, 0, - 1, 0, - 0, 1, - 1, 0, - 1, 1, - 0, 1 -] - -proto.draw = (function () { - var MATRIX = [ - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - ] - - return function () { - var plot = this.plot - var shader = this.shader - var bounds = this.bounds - var numVertices = this.numVertices - - if (numVertices <= 0) { - return - } - - var gl = plot.gl - var dataBox = plot.dataBox - - var boundX = bounds[2] - bounds[0] - var boundY = bounds[3] - bounds[1] - var dataX = dataBox[2] - dataBox[0] - var dataY = dataBox[3] - dataBox[1] - - MATRIX[0] = 2.0 * boundX / dataX - MATRIX[4] = 2.0 * boundY / dataY - MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 - MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 - - shader.bind() - - var uniforms = shader.uniforms - uniforms.viewTransform = MATRIX - - uniforms.shape = this.shape - - var attributes = shader.attributes - this.positionBuffer.bind() - attributes.position.pointer() - - this.weightBuffer.bind() - attributes.weight.pointer(gl.UNSIGNED_BYTE, false) - - this.colorBuffer.bind() - attributes.color.pointer(gl.UNSIGNED_BYTE, true) - - gl.drawArrays(gl.TRIANGLES, 0, numVertices) - } -})() - -proto.drawPick = (function () { - var MATRIX = [ - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - ] - - var PICK_VECTOR = [0, 0, 0, 0] - - return function (pickOffset) { - var plot = this.plot - var shader = this.pickShader - var bounds = this.bounds - var numVertices = this.numVertices - - if (numVertices <= 0) { - return - } - - var gl = plot.gl - var dataBox = plot.dataBox - - var boundX = bounds[2] - bounds[0] - var boundY = bounds[3] - bounds[1] - var dataX = dataBox[2] - dataBox[0] - var dataY = dataBox[3] - dataBox[1] - - MATRIX[0] = 2.0 * boundX / dataX - MATRIX[4] = 2.0 * boundY / dataY - MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 - MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 - - for (var i = 0; i < 4; ++i) { - PICK_VECTOR[i] = (pickOffset >> (i * 8)) & 0xff - } - - this.pickOffset = pickOffset - - shader.bind() - - var uniforms = shader.uniforms - uniforms.viewTransform = MATRIX - uniforms.pickOffset = PICK_VECTOR - uniforms.shape = this.shape - - var attributes = shader.attributes - this.positionBuffer.bind() - attributes.position.pointer() - - this.weightBuffer.bind() - attributes.weight.pointer(gl.UNSIGNED_BYTE, false) - - this.idBuffer.bind() - attributes.pickId.pointer(gl.UNSIGNED_BYTE, false) - - gl.drawArrays(gl.TRIANGLES, 0, numVertices) - - return pickOffset + this.shape[0] * this.shape[1] - } -})() - -proto.pick = function (x, y, value) { - var pickOffset = this.pickOffset - var pointCount = this.shape[0] * this.shape[1] - if (value < pickOffset || value >= pickOffset + pointCount) { - return null - } - var pointId = value - pickOffset - var xData = this.xData - var yData = this.yData - return { - object: this, - pointId: pointId, - dataCoord: [ - xData[pointId % this.shape[0]], - yData[(pointId / this.shape[0]) | 0]] - } -} - -proto.update = function (options) { - options = options || {} - - var shape = options.shape || [0, 0] - - var x = options.x || iota(shape[0]) - var y = options.y || iota(shape[1]) - var z = options.z || new Float32Array(shape[0] * shape[1]) - - this.xData = x - this.yData = y - - var colorLevels = options.colorLevels || [0] - var colorValues = options.colorValues || [0, 0, 0, 1] - var colorCount = colorLevels.length - - var bounds = this.bounds - var lox = bounds[0] = x[0] - var loy = bounds[1] = y[0] - var hix = bounds[2] = x[x.length - 1] - var hiy = bounds[3] = y[y.length - 1] - - var xs = 1.0 / (hix - lox) - var ys = 1.0 / (hiy - loy) - - var numX = shape[0] - var numY = shape[1] - - this.shape = [numX, numY] - - var numVerts = (numX - 1) * (numY - 1) * (WEIGHTS.length >>> 1) - - this.numVertices = numVerts - - var colors = pool.mallocUint8(numVerts * 4) - var positions = pool.mallocFloat32(numVerts * 2) - var weights = pool.mallocUint8 (numVerts * 2) - var ids = pool.mallocUint32(numVerts) - - var ptr = 0 - - for (var j = 0; j < numY - 1; ++j) { - var yc0 = ys * (y[j] - loy) - var yc1 = ys * (y[j + 1] - loy) - for (var i = 0; i < numX - 1; ++i) { - var xc0 = xs * (x[i] - lox) - var xc1 = xs * (x[i + 1] - lox) - - for (var dd = 0; dd < WEIGHTS.length; dd += 2) { - var dx = WEIGHTS[dd] - var dy = WEIGHTS[dd + 1] - var offset = (j + dy) * numX + (i + dx) - var zc = z[offset] - var colorIdx = bsearch.le(colorLevels, zc) - var r, g, b, a - if (colorIdx < 0) { - r = colorValues[0] - g = colorValues[1] - b = colorValues[2] - a = colorValues[3] - } else if (colorIdx === colorCount - 1) { - r = colorValues[4 * colorCount - 4] - g = colorValues[4 * colorCount - 3] - b = colorValues[4 * colorCount - 2] - a = colorValues[4 * colorCount - 1] - } else { - var t = (zc - colorLevels[colorIdx]) / - (colorLevels[colorIdx + 1] - colorLevels[colorIdx]) - var ti = 1.0 - t - var i0 = 4 * colorIdx - var i1 = 4 * (colorIdx + 1) - r = ti * colorValues[i0] + t * colorValues[i1] - g = ti * colorValues[i0 + 1] + t * colorValues[i1 + 1] - b = ti * colorValues[i0 + 2] + t * colorValues[i1 + 2] - a = ti * colorValues[i0 + 3] + t * colorValues[i1 + 3] - } - - colors[4 * ptr] = 255 * r - colors[4 * ptr + 1] = 255 * g - colors[4 * ptr + 2] = 255 * b - colors[4 * ptr + 3] = 255 * a - - positions[2*ptr] = xc0*.5 + xc1*.5; - positions[2*ptr+1] = yc0*.5 + yc1*.5; - - weights[2*ptr] = dx; - weights[2*ptr+1] = dy; - - ids[ptr] = j * numX + i - - ptr += 1 - } - } - } - - this.positionBuffer.update(positions) - this.weightBuffer.update(weights) - this.colorBuffer.update(colors) - this.idBuffer.update(ids) - - pool.free(positions) - pool.free(colors) - pool.free(weights) - pool.free(ids) -} - -proto.dispose = function () { - this.shader.dispose() - this.pickShader.dispose() - this.positionBuffer.dispose() - this.weightBuffer.dispose() - this.colorBuffer.dispose() - this.idBuffer.dispose() - this.plot.removeObject(this) -} - -function createHeatmap2D (plot, options) { - var gl = plot.gl - - var shader = createShader(gl, shaders.vertex, shaders.fragment) - var pickShader = createShader(gl, shaders.pickVertex, shaders.pickFragment) - - var positionBuffer = createBuffer(gl) - var weightBuffer = createBuffer(gl) - var colorBuffer = createBuffer(gl) - var idBuffer = createBuffer(gl) - - var heatmap = new GLHeatmap2D( - plot, - shader, - pickShader, - positionBuffer, - weightBuffer, - colorBuffer, - idBuffer) - - heatmap.update(options) - plot.addObject(heatmap) - - return heatmap -} - -},{"./lib/shaders":252,"binary-search-bounds":253,"gl-buffer":241,"gl-shader":301,"iota-array":416,"typedarray-pool":545}],252:[function(_dereq_,module,exports){ -'use strict' - -var glslify = _dereq_('glslify') - -module.exports = { - fragment: glslify(["precision lowp float;\n#define GLSLIFY 1\nvarying vec4 fragColor;\nvoid main() {\n gl_FragColor = vec4(fragColor.rgb * fragColor.a, fragColor.a);\n}\n"]), - vertex: glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\nattribute vec4 color;\nattribute vec2 weight;\n\nuniform vec2 shape;\nuniform mat3 viewTransform;\n\nvarying vec4 fragColor;\n\nvoid main() {\n vec3 vPosition = viewTransform * vec3( position + (weight-.5)/(shape-1.) , 1.0);\n fragColor = color;\n gl_Position = vec4(vPosition.xy, 0, vPosition.z);\n}\n"]), - pickFragment: glslify(["precision mediump float;\n#define GLSLIFY 1\n\nvarying vec4 fragId;\nvarying vec2 vWeight;\n\nuniform vec2 shape;\nuniform vec4 pickOffset;\n\nvoid main() {\n vec2 d = step(.5, vWeight);\n vec4 id = fragId + pickOffset;\n id.x += d.x + d.y*shape.x;\n\n id.y += floor(id.x / 256.0);\n id.x -= floor(id.x / 256.0) * 256.0;\n\n id.z += floor(id.y / 256.0);\n id.y -= floor(id.y / 256.0) * 256.0;\n\n id.w += floor(id.z / 256.0);\n id.z -= floor(id.z / 256.0) * 256.0;\n\n gl_FragColor = id/255.;\n}\n"]), - pickVertex: glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\nattribute vec4 pickId;\nattribute vec2 weight;\n\nuniform vec2 shape;\nuniform mat3 viewTransform;\n\nvarying vec4 fragId;\nvarying vec2 vWeight;\n\nvoid main() {\n vWeight = weight;\n\n fragId = pickId;\n\n vec3 vPosition = viewTransform * vec3( position + (weight-.5)/(shape-1.) , 1.0);\n gl_Position = vec4(vPosition.xy, 0, vPosition.z);\n}\n"]) -} - -},{"glslify":409}],253:[function(_dereq_,module,exports){ -arguments[4][111][0].apply(exports,arguments) -},{"dup":111}],254:[function(_dereq_,module,exports){ -var glslify = _dereq_('glslify') -var createShader = _dereq_('gl-shader') - -var vertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position, nextPosition;\nattribute float arcLength, lineWidth;\nattribute vec4 color;\n\nuniform vec2 screenShape;\nuniform float pixelRatio;\nuniform mat4 model, view, projection;\n\nvarying vec4 fragColor;\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\n\nvec4 project(vec3 p) {\n return projection * view * model * vec4(p, 1.0);\n}\n\nvoid main() {\n vec4 startPoint = project(position);\n vec4 endPoint = project(nextPosition);\n\n vec2 A = startPoint.xy / startPoint.w;\n vec2 B = endPoint.xy / endPoint.w;\n\n float clipAngle = atan(\n (B.y - A.y) * screenShape.y,\n (B.x - A.x) * screenShape.x\n );\n\n vec2 offset = 0.5 * pixelRatio * lineWidth * vec2(\n sin(clipAngle),\n -cos(clipAngle)\n ) / screenShape;\n\n gl_Position = vec4(startPoint.xy + startPoint.w * offset, startPoint.zw);\n\n worldPosition = position;\n pixelArcLength = arcLength;\n fragColor = color;\n}\n"]) -var forwardFrag = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform sampler2D dashTexture;\nuniform float dashScale;\nuniform float opacity;\n\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\nvarying vec4 fragColor;\n\nvoid main() {\n if (\n outOfRange(clipBounds[0], clipBounds[1], worldPosition) ||\n fragColor.a * opacity == 0.\n ) discard;\n\n float dashWeight = texture2D(dashTexture, vec2(dashScale * pixelArcLength, 0)).r;\n if(dashWeight < 0.5) {\n discard;\n }\n gl_FragColor = fragColor * opacity;\n}\n"]) -var pickFrag = glslify(["precision highp float;\n#define GLSLIFY 1\n\n#define FLOAT_MAX 1.70141184e38\n#define FLOAT_MIN 1.17549435e-38\n\nlowp vec4 encode_float_1540259130(highp float v) {\n highp float av = abs(v);\n\n //Handle special cases\n if(av < FLOAT_MIN) {\n return vec4(0.0, 0.0, 0.0, 0.0);\n } else if(v > FLOAT_MAX) {\n return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;\n } else if(v < -FLOAT_MAX) {\n return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;\n }\n\n highp vec4 c = vec4(0,0,0,0);\n\n //Compute exponent and mantissa\n highp float e = floor(log2(av));\n highp float m = av * pow(2.0, -e) - 1.0;\n \n //Unpack mantissa\n c[1] = floor(128.0 * m);\n m -= c[1] / 128.0;\n c[2] = floor(32768.0 * m);\n m -= c[2] / 32768.0;\n c[3] = floor(8388608.0 * m);\n \n //Unpack exponent\n highp float ebias = e + 127.0;\n c[0] = floor(ebias / 2.0);\n ebias -= c[0] * 2.0;\n c[1] += floor(ebias) * 128.0; \n\n //Unpack sign bit\n c[0] += 128.0 * step(0.0, -v);\n\n //Scale back to range\n return c / 255.0;\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform float pickId;\nuniform vec3 clipBounds[2];\n\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\nvarying vec4 fragColor;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], worldPosition)) discard;\n\n gl_FragColor = vec4(pickId/255.0, encode_float_1540259130(pixelArcLength).xyz);\n}"]) - -var ATTRIBUTES = [ - {name: 'position', type: 'vec3'}, - {name: 'nextPosition', type: 'vec3'}, - {name: 'arcLength', type: 'float'}, - {name: 'lineWidth', type: 'float'}, - {name: 'color', type: 'vec4'} -] - -exports.createShader = function(gl) { - return createShader(gl, vertSrc, forwardFrag, null, ATTRIBUTES) -} - -exports.createPickShader = function(gl) { - return createShader(gl, vertSrc, pickFrag, null, ATTRIBUTES) -} - -},{"gl-shader":301,"glslify":409}],255:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createLinePlot - -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') -var createTexture = _dereq_('gl-texture2d') -var unpackFloat = _dereq_('glsl-read-float') -var bsearch = _dereq_('binary-search-bounds') -var ndarray = _dereq_('ndarray') -var shaders = _dereq_('./lib/shaders') - -var createShader = shaders.createShader -var createPickShader = shaders.createPickShader - -var identity = [1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1] - -function distance (a, b) { - var s = 0.0 - for (var i = 0; i < 3; ++i) { - var d = a[i] - b[i] - s += d * d - } - return Math.sqrt(s) -} - -function filterClipBounds (bounds) { - var result = [[-1e6, -1e6, -1e6], [1e6, 1e6, 1e6]] - for (var i = 0; i < 3; ++i) { - result[0][i] = Math.max(bounds[0][i], result[0][i]) - result[1][i] = Math.min(bounds[1][i], result[1][i]) - } - return result -} - -function PickResult (tau, position, index, dataCoordinate) { - this.arcLength = tau - this.position = position - this.index = index - this.dataCoordinate = dataCoordinate -} - -function LinePlot (gl, shader, pickShader, buffer, vao, texture) { - this.gl = gl - this.shader = shader - this.pickShader = pickShader - this.buffer = buffer - this.vao = vao - this.clipBounds = [ - [ -Infinity, -Infinity, -Infinity ], - [ Infinity, Infinity, Infinity ]] - this.points = [] - this.arcLength = [] - this.vertexCount = 0 - this.bounds = [[0, 0, 0], [0, 0, 0]] - this.pickId = 0 - this.lineWidth = 1 - this.texture = texture - this.dashScale = 1 - this.opacity = 1 - this.hasAlpha = false - this.dirty = true - this.pixelRatio = 1 -} - -var proto = LinePlot.prototype - -proto.isTransparent = function () { - return this.hasAlpha -} - -proto.isOpaque = function () { - return !this.hasAlpha -} - -proto.pickSlots = 1 - -proto.setPickBase = function (id) { - this.pickId = id -} - -proto.drawTransparent = proto.draw = function (camera) { - if (!this.vertexCount) return - var gl = this.gl - var shader = this.shader - var vao = this.vao - shader.bind() - shader.uniforms = { - model: camera.model || identity, - view: camera.view || identity, - projection: camera.projection || identity, - clipBounds: filterClipBounds(this.clipBounds), - dashTexture: this.texture.bind(), - dashScale: this.dashScale / this.arcLength[this.arcLength.length - 1], - opacity: this.opacity, - screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], - pixelRatio: this.pixelRatio - } - vao.bind() - vao.draw(gl.TRIANGLE_STRIP, this.vertexCount) - vao.unbind() -} - -proto.drawPick = function (camera) { - if (!this.vertexCount) return - var gl = this.gl - var shader = this.pickShader - var vao = this.vao - shader.bind() - shader.uniforms = { - model: camera.model || identity, - view: camera.view || identity, - projection: camera.projection || identity, - pickId: this.pickId, - clipBounds: filterClipBounds(this.clipBounds), - screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], - pixelRatio: this.pixelRatio - } - vao.bind() - vao.draw(gl.TRIANGLE_STRIP, this.vertexCount) - vao.unbind() -} - -proto.update = function (options) { - var i, j - - this.dirty = true - - var connectGaps = !!options.connectGaps - - if ('dashScale' in options) { - this.dashScale = options.dashScale - } - - this.hasAlpha = false // default to no transparent draw - if ('opacity' in options) { - this.opacity = +options.opacity - if(this.opacity < 1) { - this.hasAlpha = true; - } - } - - // Recalculate buffer data - var buffer = [] - var arcLengthArray = [] - var pointArray = [] - var arcLength = 0.0 - var vertexCount = 0 - var bounds = [ - [ Infinity, Infinity, Infinity ], - [ -Infinity, -Infinity, -Infinity ]] - - var positions = options.position || options.positions - if (positions) { - - // Default color - var colors = options.color || options.colors || [0, 0, 0, 1] - - var lineWidth = options.lineWidth || 1 - - var hadGap = false - - fill_loop: - for (i = 1; i < positions.length; ++i) { - var a = positions[i - 1] - var b = positions[i] - - arcLengthArray.push(arcLength) - pointArray.push(a.slice()) - - for (j = 0; j < 3; ++j) { - if (isNaN(a[j]) || isNaN(b[j]) || - !isFinite(a[j]) || !isFinite(b[j])) { - - if (!connectGaps && buffer.length > 0) { - for (var k = 0; k < 24; ++k) { - buffer.push(buffer[buffer.length - 12]) - } - vertexCount += 2 - hadGap = true - } - - continue fill_loop - } - bounds[0][j] = Math.min(bounds[0][j], a[j], b[j]) - bounds[1][j] = Math.max(bounds[1][j], a[j], b[j]) - } - - var acolor, bcolor - if (Array.isArray(colors[0])) { - acolor = (colors.length > i - 1) ? colors[i - 1] : // using index value - (colors.length > 0) ? colors[colors.length - 1] : // using last item - [0, 0, 0, 1]; // using black - - bcolor = (colors.length > i) ? colors[i] : // using index value - (colors.length > 0) ? colors[colors.length - 1] : // using last item - [0, 0, 0, 1]; // using black - } else { - acolor = bcolor = colors - } - - if (acolor.length === 3) { - acolor = [acolor[0], acolor[1], acolor[2], 1] - } - if (bcolor.length === 3) { - bcolor = [bcolor[0], bcolor[1], bcolor[2], 1] - } - - if(!this.hasAlpha && acolor[3] < 1) this.hasAlpha = true - - var w0 - if (Array.isArray(lineWidth)) { - w0 = (lineWidth.length > i - 1) ? lineWidth[i - 1] : // using index value - (lineWidth.length > 0) ? lineWidth[lineWidth.length - 1] : // using last item - [0, 0, 0, 1]; // using black - } else { - w0 = lineWidth - } - - var t0 = arcLength - arcLength += distance(a, b) - - if (hadGap) { - for (j = 0; j < 2; ++j) { - buffer.push( - a[0], a[1], a[2], b[0], b[1], b[2], t0, w0, acolor[0], acolor[1], acolor[2], acolor[3]) - } - vertexCount += 2 - hadGap = false - } - - buffer.push( - a[0], a[1], a[2], b[0], b[1], b[2], t0, w0, acolor[0], acolor[1], acolor[2], acolor[3], - a[0], a[1], a[2], b[0], b[1], b[2], t0, -w0, acolor[0], acolor[1], acolor[2], acolor[3], - b[0], b[1], b[2], a[0], a[1], a[2], arcLength, -w0, bcolor[0], bcolor[1], bcolor[2], bcolor[3], - b[0], b[1], b[2], a[0], a[1], a[2], arcLength, w0, bcolor[0], bcolor[1], bcolor[2], bcolor[3]) - - vertexCount += 4 - } - } - this.buffer.update(buffer) - - arcLengthArray.push(arcLength) - pointArray.push(positions[positions.length - 1].slice()) - - this.bounds = bounds - - this.vertexCount = vertexCount - - this.points = pointArray - this.arcLength = arcLengthArray - - if ('dashes' in options) { - var dashArray = options.dashes - - // Calculate prefix sum - var prefixSum = dashArray.slice() - prefixSum.unshift(0) - for (i = 1; i < prefixSum.length; ++i) { - prefixSum[i] = prefixSum[i - 1] + prefixSum[i] - } - - var dashTexture = ndarray(new Array(256 * 4), [256, 1, 4]) - for (i = 0; i < 256; ++i) { - for (j = 0; j < 4; ++j) { - dashTexture.set(i, 0, j, 0) - } - if (bsearch.le(prefixSum, prefixSum[prefixSum.length - 1] * i / 255.0) & 1) { - dashTexture.set(i, 0, 0, 0) - } else { - dashTexture.set(i, 0, 0, 255) - } - } - - this.texture.setPixels(dashTexture) - } -} - -proto.dispose = function () { - this.shader.dispose() - this.vao.dispose() - this.buffer.dispose() -} - -proto.pick = function (selection) { - if (!selection) { - return null - } - if (selection.id !== this.pickId) { - return null - } - var tau = unpackFloat( - selection.value[0], - selection.value[1], - selection.value[2], - 0) - var index = bsearch.le(this.arcLength, tau) - if (index < 0) { - return null - } - if (index === this.arcLength.length - 1) { - return new PickResult( - this.arcLength[this.arcLength.length - 1], - this.points[this.points.length - 1].slice(), - index) - } - var a = this.points[index] - var b = this.points[Math.min(index + 1, this.points.length - 1)] - var t = (tau - this.arcLength[index]) / (this.arcLength[index + 1] - this.arcLength[index]) - var ti = 1.0 - t - var x = [0, 0, 0] - for (var i = 0; i < 3; ++i) { - x[i] = ti * a[i] + t * b[i] - } - var dataIndex = Math.min((t < 0.5) ? index : (index + 1), this.points.length - 1) - return new PickResult( - tau, - x, - dataIndex, - this.points[dataIndex]) -} - -function createLinePlot (options) { - var gl = options.gl || (options.scene && options.scene.gl) - - var shader = createShader(gl) - shader.attributes.position.location = 0 - shader.attributes.nextPosition.location = 1 - shader.attributes.arcLength.location = 2 - shader.attributes.lineWidth.location = 3 - shader.attributes.color.location = 4 - - var pickShader = createPickShader(gl) - pickShader.attributes.position.location = 0 - pickShader.attributes.nextPosition.location = 1 - pickShader.attributes.arcLength.location = 2 - pickShader.attributes.lineWidth.location = 3 - pickShader.attributes.color.location = 4 - - var buffer = createBuffer(gl) - var vao = createVAO(gl, [ - { - 'buffer': buffer, - 'size': 3, - 'offset': 0, - 'stride': 48 - }, - { - 'buffer': buffer, - 'size': 3, - 'offset': 12, - 'stride': 48 - }, - { - 'buffer': buffer, - 'size': 1, - 'offset': 24, - 'stride': 48 - }, - { - 'buffer': buffer, - 'size': 1, - 'offset': 28, - 'stride': 48 - }, - { - 'buffer': buffer, - 'size': 4, - 'offset': 32, - 'stride': 48 - } - ]) - - // Create texture for dash pattern - var defaultTexture = ndarray(new Array(256 * 4), [256, 1, 4]) - for (var i = 0; i < 256 * 4; ++i) { - defaultTexture.data[i] = 255 - } - var texture = createTexture(gl, defaultTexture) - texture.wrap = gl.REPEAT - - var linePlot = new LinePlot(gl, shader, pickShader, buffer, vao, texture) - linePlot.update(options) - return linePlot -} - -},{"./lib/shaders":254,"binary-search-bounds":256,"gl-buffer":241,"gl-texture2d":322,"gl-vao":327,"glsl-read-float":400,"ndarray":450}],256:[function(_dereq_,module,exports){ -arguments[4][111][0].apply(exports,arguments) -},{"dup":111}],257:[function(_dereq_,module,exports){ -module.exports = invert - -/** - * Inverts a mat2 - * - * @alias mat2.invert - * @param {mat2} out the receiving matrix - * @param {mat2} a the source matrix - * @returns {mat2} out - */ -function invert(out, a) { - var a0 = a[0] - var a1 = a[1] - var a2 = a[2] - var a3 = a[3] - var det = a0 * a3 - a2 * a1 - - if (!det) return null - det = 1.0 / det - - out[0] = a3 * det - out[1] = -a1 * det - out[2] = -a2 * det - out[3] = a0 * det - - return out -} - -},{}],258:[function(_dereq_,module,exports){ -module.exports = invert - -/** - * Inverts a mat3 - * - * @alias mat3.invert - * @param {mat3} out the receiving matrix - * @param {mat3} a the source matrix - * @returns {mat3} out - */ -function invert(out, a) { - var a00 = a[0], a01 = a[1], a02 = a[2] - var a10 = a[3], a11 = a[4], a12 = a[5] - var a20 = a[6], a21 = a[7], a22 = a[8] - - var b01 = a22 * a11 - a12 * a21 - var b11 = -a22 * a10 + a12 * a20 - var b21 = a21 * a10 - a11 * a20 - - // Calculate the determinant - var det = a00 * b01 + a01 * b11 + a02 * b21 - - if (!det) return null - det = 1.0 / det - - out[0] = b01 * det - out[1] = (-a22 * a01 + a02 * a21) * det - out[2] = (a12 * a01 - a02 * a11) * det - out[3] = b11 * det - out[4] = (a22 * a00 - a02 * a20) * det - out[5] = (-a12 * a00 + a02 * a10) * det - out[6] = b21 * det - out[7] = (-a21 * a00 + a01 * a20) * det - out[8] = (a11 * a00 - a01 * a10) * det - - return out -} - -},{}],259:[function(_dereq_,module,exports){ -module.exports = clone; - -/** - * Creates a new mat4 initialized with values from an existing matrix - * - * @param {mat4} a matrix to clone - * @returns {mat4} a new 4x4 matrix - */ -function clone(a) { - var out = new Float32Array(16); - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - out[3] = a[3]; - out[4] = a[4]; - out[5] = a[5]; - out[6] = a[6]; - out[7] = a[7]; - out[8] = a[8]; - out[9] = a[9]; - out[10] = a[10]; - out[11] = a[11]; - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; - return out; -}; -},{}],260:[function(_dereq_,module,exports){ -module.exports = create; - -/** - * Creates a new identity mat4 - * - * @returns {mat4} a new 4x4 matrix - */ -function create() { - var out = new Float32Array(16); - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = 1; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 1; - out[11] = 0; - out[12] = 0; - out[13] = 0; - out[14] = 0; - out[15] = 1; - return out; -}; -},{}],261:[function(_dereq_,module,exports){ -module.exports = determinant; - -/** - * Calculates the determinant of a mat4 - * - * @param {mat4} a the source matrix - * @returns {Number} determinant of a - */ -function determinant(a) { - var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], - a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], - a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], - a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], - - b00 = a00 * a11 - a01 * a10, - b01 = a00 * a12 - a02 * a10, - b02 = a00 * a13 - a03 * a10, - b03 = a01 * a12 - a02 * a11, - b04 = a01 * a13 - a03 * a11, - b05 = a02 * a13 - a03 * a12, - b06 = a20 * a31 - a21 * a30, - b07 = a20 * a32 - a22 * a30, - b08 = a20 * a33 - a23 * a30, - b09 = a21 * a32 - a22 * a31, - b10 = a21 * a33 - a23 * a31, - b11 = a22 * a33 - a23 * a32; - - // Calculate the determinant - return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; -}; -},{}],262:[function(_dereq_,module,exports){ -module.exports = fromQuat; - -/** - * Creates a matrix from a quaternion rotation. - * - * @param {mat4} out mat4 receiving operation result - * @param {quat4} q Rotation quaternion - * @returns {mat4} out - */ -function fromQuat(out, q) { - var x = q[0], y = q[1], z = q[2], w = q[3], - x2 = x + x, - y2 = y + y, - z2 = z + z, - - xx = x * x2, - yx = y * x2, - yy = y * y2, - zx = z * x2, - zy = z * y2, - zz = z * z2, - wx = w * x2, - wy = w * y2, - wz = w * z2; - - out[0] = 1 - yy - zz; - out[1] = yx + wz; - out[2] = zx - wy; - out[3] = 0; - - out[4] = yx - wz; - out[5] = 1 - xx - zz; - out[6] = zy + wx; - out[7] = 0; - - out[8] = zx + wy; - out[9] = zy - wx; - out[10] = 1 - xx - yy; - out[11] = 0; - - out[12] = 0; - out[13] = 0; - out[14] = 0; - out[15] = 1; - - return out; -}; -},{}],263:[function(_dereq_,module,exports){ -module.exports = fromRotationTranslation; - -/** - * Creates a matrix from a quaternion rotation and vector translation - * This is equivalent to (but much faster than): - * - * mat4.identity(dest); - * mat4.translate(dest, vec); - * var quatMat = mat4.create(); - * quat4.toMat4(quat, quatMat); - * mat4.multiply(dest, quatMat); - * - * @param {mat4} out mat4 receiving operation result - * @param {quat4} q Rotation quaternion - * @param {vec3} v Translation vector - * @returns {mat4} out - */ -function fromRotationTranslation(out, q, v) { - // Quaternion math - var x = q[0], y = q[1], z = q[2], w = q[3], - x2 = x + x, - y2 = y + y, - z2 = z + z, - - xx = x * x2, - xy = x * y2, - xz = x * z2, - yy = y * y2, - yz = y * z2, - zz = z * z2, - wx = w * x2, - wy = w * y2, - wz = w * z2; - - out[0] = 1 - (yy + zz); - out[1] = xy + wz; - out[2] = xz - wy; - out[3] = 0; - out[4] = xy - wz; - out[5] = 1 - (xx + zz); - out[6] = yz + wx; - out[7] = 0; - out[8] = xz + wy; - out[9] = yz - wx; - out[10] = 1 - (xx + yy); - out[11] = 0; - out[12] = v[0]; - out[13] = v[1]; - out[14] = v[2]; - out[15] = 1; - - return out; -}; -},{}],264:[function(_dereq_,module,exports){ -module.exports = identity; - -/** - * Set a mat4 to the identity matrix - * - * @param {mat4} out the receiving matrix - * @returns {mat4} out - */ -function identity(out) { - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = 1; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 1; - out[11] = 0; - out[12] = 0; - out[13] = 0; - out[14] = 0; - out[15] = 1; - return out; -}; -},{}],265:[function(_dereq_,module,exports){ -module.exports = invert; - -/** - * Inverts a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -function invert(out, a) { - var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], - a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], - a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], - a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], - - b00 = a00 * a11 - a01 * a10, - b01 = a00 * a12 - a02 * a10, - b02 = a00 * a13 - a03 * a10, - b03 = a01 * a12 - a02 * a11, - b04 = a01 * a13 - a03 * a11, - b05 = a02 * a13 - a03 * a12, - b06 = a20 * a31 - a21 * a30, - b07 = a20 * a32 - a22 * a30, - b08 = a20 * a33 - a23 * a30, - b09 = a21 * a32 - a22 * a31, - b10 = a21 * a33 - a23 * a31, - b11 = a22 * a33 - a23 * a32, - - // Calculate the determinant - det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - - if (!det) { - return null; - } - det = 1.0 / det; - - out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; - out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; - out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; - out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; - out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; - out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; - out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; - out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; - out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; - out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; - out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; - out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; - out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; - out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; - out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; - out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; - - return out; -}; -},{}],266:[function(_dereq_,module,exports){ -var identity = _dereq_('./identity'); - -module.exports = lookAt; - -/** - * Generates a look-at matrix with the given eye position, focal point, and up axis - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {vec3} eye Position of the viewer - * @param {vec3} center Point the viewer is looking at - * @param {vec3} up vec3 pointing up - * @returns {mat4} out - */ -function lookAt(out, eye, center, up) { - var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, - eyex = eye[0], - eyey = eye[1], - eyez = eye[2], - upx = up[0], - upy = up[1], - upz = up[2], - centerx = center[0], - centery = center[1], - centerz = center[2]; - - if (Math.abs(eyex - centerx) < 0.000001 && - Math.abs(eyey - centery) < 0.000001 && - Math.abs(eyez - centerz) < 0.000001) { - return identity(out); - } - - z0 = eyex - centerx; - z1 = eyey - centery; - z2 = eyez - centerz; - - len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); - z0 *= len; - z1 *= len; - z2 *= len; - - x0 = upy * z2 - upz * z1; - x1 = upz * z0 - upx * z2; - x2 = upx * z1 - upy * z0; - len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); - if (!len) { - x0 = 0; - x1 = 0; - x2 = 0; - } else { - len = 1 / len; - x0 *= len; - x1 *= len; - x2 *= len; - } - - y0 = z1 * x2 - z2 * x1; - y1 = z2 * x0 - z0 * x2; - y2 = z0 * x1 - z1 * x0; - - len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); - if (!len) { - y0 = 0; - y1 = 0; - y2 = 0; - } else { - len = 1 / len; - y0 *= len; - y1 *= len; - y2 *= len; - } - - out[0] = x0; - out[1] = y0; - out[2] = z0; - out[3] = 0; - out[4] = x1; - out[5] = y1; - out[6] = z1; - out[7] = 0; - out[8] = x2; - out[9] = y2; - out[10] = z2; - out[11] = 0; - out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); - out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); - out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); - out[15] = 1; - - return out; -}; -},{"./identity":264}],267:[function(_dereq_,module,exports){ -module.exports = multiply; - -/** - * Multiplies two mat4's - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the first operand - * @param {mat4} b the second operand - * @returns {mat4} out - */ -function multiply(out, a, b) { - var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], - a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], - a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], - a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; - - // Cache only the current line of the second matrix - var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; - out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; - out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; - out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - - b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; - out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; - out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; - out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; - out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - return out; -}; -},{}],268:[function(_dereq_,module,exports){ -module.exports = ortho; - -/** - * Generates a orthogonal projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} left Left bound of the frustum - * @param {number} right Right bound of the frustum - * @param {number} bottom Bottom bound of the frustum - * @param {number} top Top bound of the frustum - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -function ortho(out, left, right, bottom, top, near, far) { - var lr = 1 / (left - right), - bt = 1 / (bottom - top), - nf = 1 / (near - far); - out[0] = -2 * lr; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = -2 * bt; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 2 * nf; - out[11] = 0; - out[12] = (left + right) * lr; - out[13] = (top + bottom) * bt; - out[14] = (far + near) * nf; - out[15] = 1; - return out; -}; -},{}],269:[function(_dereq_,module,exports){ -module.exports = perspective; - -/** - * Generates a perspective projection matrix with the given bounds - * - * @param {mat4} out mat4 frustum matrix will be written into - * @param {number} fovy Vertical field of view in radians - * @param {number} aspect Aspect ratio. typically viewport width/height - * @param {number} near Near bound of the frustum - * @param {number} far Far bound of the frustum - * @returns {mat4} out - */ -function perspective(out, fovy, aspect, near, far) { - var f = 1.0 / Math.tan(fovy / 2), - nf = 1 / (near - far); - out[0] = f / aspect; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = f; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = (far + near) * nf; - out[11] = -1; - out[12] = 0; - out[13] = 0; - out[14] = (2 * far * near) * nf; - out[15] = 0; - return out; -}; -},{}],270:[function(_dereq_,module,exports){ -module.exports = rotate; - -/** - * Rotates a mat4 by the given angle - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @param {vec3} axis the axis to rotate around - * @returns {mat4} out - */ -function rotate(out, a, rad, axis) { - var x = axis[0], y = axis[1], z = axis[2], - len = Math.sqrt(x * x + y * y + z * z), - s, c, t, - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23, - b00, b01, b02, - b10, b11, b12, - b20, b21, b22; - - if (Math.abs(len) < 0.000001) { return null; } - - len = 1 / len; - x *= len; - y *= len; - z *= len; - - s = Math.sin(rad); - c = Math.cos(rad); - t = 1 - c; - - a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; - a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; - a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; - - // Construct the elements of the rotation matrix - b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; - b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; - b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; - - // Perform rotation-specific matrix multiplication - out[0] = a00 * b00 + a10 * b01 + a20 * b02; - out[1] = a01 * b00 + a11 * b01 + a21 * b02; - out[2] = a02 * b00 + a12 * b01 + a22 * b02; - out[3] = a03 * b00 + a13 * b01 + a23 * b02; - out[4] = a00 * b10 + a10 * b11 + a20 * b12; - out[5] = a01 * b10 + a11 * b11 + a21 * b12; - out[6] = a02 * b10 + a12 * b11 + a22 * b12; - out[7] = a03 * b10 + a13 * b11 + a23 * b12; - out[8] = a00 * b20 + a10 * b21 + a20 * b22; - out[9] = a01 * b20 + a11 * b21 + a21 * b22; - out[10] = a02 * b20 + a12 * b21 + a22 * b22; - out[11] = a03 * b20 + a13 * b21 + a23 * b22; - - if (a !== out) { // If the source and destination differ, copy the unchanged last row - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; - } - return out; -}; -},{}],271:[function(_dereq_,module,exports){ -module.exports = rotateX; - -/** - * Rotates a matrix by the given angle around the X axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -function rotateX(out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a10 = a[4], - a11 = a[5], - a12 = a[6], - a13 = a[7], - a20 = a[8], - a21 = a[9], - a22 = a[10], - a23 = a[11]; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - out[3] = a[3]; - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; - } - - // Perform axis-specific matrix multiplication - out[4] = a10 * c + a20 * s; - out[5] = a11 * c + a21 * s; - out[6] = a12 * c + a22 * s; - out[7] = a13 * c + a23 * s; - out[8] = a20 * c - a10 * s; - out[9] = a21 * c - a11 * s; - out[10] = a22 * c - a12 * s; - out[11] = a23 * c - a13 * s; - return out; -}; -},{}],272:[function(_dereq_,module,exports){ -module.exports = rotateY; - -/** - * Rotates a matrix by the given angle around the Y axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -function rotateY(out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a[0], - a01 = a[1], - a02 = a[2], - a03 = a[3], - a20 = a[8], - a21 = a[9], - a22 = a[10], - a23 = a[11]; - - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out[4] = a[4]; - out[5] = a[5]; - out[6] = a[6]; - out[7] = a[7]; - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; - } - - // Perform axis-specific matrix multiplication - out[0] = a00 * c - a20 * s; - out[1] = a01 * c - a21 * s; - out[2] = a02 * c - a22 * s; - out[3] = a03 * c - a23 * s; - out[8] = a00 * s + a20 * c; - out[9] = a01 * s + a21 * c; - out[10] = a02 * s + a22 * c; - out[11] = a03 * s + a23 * c; - return out; -}; -},{}],273:[function(_dereq_,module,exports){ -module.exports = rotateZ; - -/** - * Rotates a matrix by the given angle around the Z axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -function rotateZ(out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a[0], - a01 = a[1], - a02 = a[2], - a03 = a[3], - a10 = a[4], - a11 = a[5], - a12 = a[6], - a13 = a[7]; - - if (a !== out) { // If the source and destination differ, copy the unchanged last row - out[8] = a[8]; - out[9] = a[9]; - out[10] = a[10]; - out[11] = a[11]; - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; - } - - // Perform axis-specific matrix multiplication - out[0] = a00 * c + a10 * s; - out[1] = a01 * c + a11 * s; - out[2] = a02 * c + a12 * s; - out[3] = a03 * c + a13 * s; - out[4] = a10 * c - a00 * s; - out[5] = a11 * c - a01 * s; - out[6] = a12 * c - a02 * s; - out[7] = a13 * c - a03 * s; - return out; -}; -},{}],274:[function(_dereq_,module,exports){ -module.exports = scale; - -/** - * Scales the mat4 by the dimensions in the given vec3 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to scale - * @param {vec3} v the vec3 to scale the matrix by - * @returns {mat4} out - **/ -function scale(out, a, v) { - var x = v[0], y = v[1], z = v[2]; - - out[0] = a[0] * x; - out[1] = a[1] * x; - out[2] = a[2] * x; - out[3] = a[3] * x; - out[4] = a[4] * y; - out[5] = a[5] * y; - out[6] = a[6] * y; - out[7] = a[7] * y; - out[8] = a[8] * z; - out[9] = a[9] * z; - out[10] = a[10] * z; - out[11] = a[11] * z; - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; - return out; -}; -},{}],275:[function(_dereq_,module,exports){ -module.exports = translate; - -/** - * Translate a mat4 by the given vector - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to translate - * @param {vec3} v vector to translate by - * @returns {mat4} out - */ -function translate(out, a, v) { - var x = v[0], y = v[1], z = v[2], - a00, a01, a02, a03, - a10, a11, a12, a13, - a20, a21, a22, a23; - - if (a === out) { - out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; - out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; - out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; - out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; - } else { - a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; - a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; - a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; - - out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; - out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; - out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; - - out[12] = a00 * x + a10 * y + a20 * z + a[12]; - out[13] = a01 * x + a11 * y + a21 * z + a[13]; - out[14] = a02 * x + a12 * y + a22 * z + a[14]; - out[15] = a03 * x + a13 * y + a23 * z + a[15]; - } - - return out; -}; -},{}],276:[function(_dereq_,module,exports){ -module.exports = transpose; - -/** - * Transpose the values of a mat4 - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the source matrix - * @returns {mat4} out - */ -function transpose(out, a) { - // If we are transposing ourselves we can skip a few steps but have to cache some values - if (out === a) { - var a01 = a[1], a02 = a[2], a03 = a[3], - a12 = a[6], a13 = a[7], - a23 = a[11]; - - out[1] = a[4]; - out[2] = a[8]; - out[3] = a[12]; - out[4] = a01; - out[6] = a[9]; - out[7] = a[13]; - out[8] = a02; - out[9] = a12; - out[11] = a[14]; - out[12] = a03; - out[13] = a13; - out[14] = a23; - } else { - out[0] = a[0]; - out[1] = a[4]; - out[2] = a[8]; - out[3] = a[12]; - out[4] = a[1]; - out[5] = a[5]; - out[6] = a[9]; - out[7] = a[13]; - out[8] = a[2]; - out[9] = a[6]; - out[10] = a[10]; - out[11] = a[14]; - out[12] = a[3]; - out[13] = a[7]; - out[14] = a[11]; - out[15] = a[15]; - } - - return out; -}; -},{}],277:[function(_dereq_,module,exports){ -'use strict' - -module.exports = invert - -var invert2 = _dereq_('gl-mat2/invert') -var invert3 = _dereq_('gl-mat3/invert') -var invert4 = _dereq_('gl-mat4/invert') - -function invert(out, M) { - switch(M.length) { - case 0: - break - case 1: - out[0] = 1.0 / M[0] - break - case 4: - invert2(out, M) - break - case 9: - invert3(out, M) - break - case 16: - invert4(out, M) - break - default: - throw new Error('currently supports matrices up to 4x4') - break - } - return out -} -},{"gl-mat2/invert":257,"gl-mat3/invert":258,"gl-mat4/invert":265}],278:[function(_dereq_,module,exports){ -'use strict' - -var barycentric = _dereq_('barycentric') -var closestPointToTriangle = _dereq_('polytope-closest-point/lib/closest_point_2d.js') - -module.exports = closestPointToPickLocation - -function xformMatrix(m, v) { - var out = [0,0,0,0] - for(var i=0; i<4; ++i) { - for(var j=0; j<4; ++j) { - out[j] += m[4*i + j] * v[i] - } - } - return out -} - -function projectVertex(v, model, view, projection, resolution) { - var p = xformMatrix(projection, - xformMatrix(view, - xformMatrix(model, [v[0], v[1], v[2], 1]))) - for(var i=0; i<3; ++i) { - p[i] /= p[3] - } - return [ 0.5 * resolution[0] * (1.0+p[0]), 0.5 * resolution[1] * (1.0-p[1]) ] -} - -function barycentricCoord(simplex, point) { - if(simplex.length === 2) { - var d0 = 0.0 - var d1 = 0.0 - for(var i=0; i<2; ++i) { - d0 += Math.pow(point[i] - simplex[0][i], 2) - d1 += Math.pow(point[i] - simplex[1][i], 2) - } - d0 = Math.sqrt(d0) - d1 = Math.sqrt(d1) - if(d0+d1 < 1e-6) { - return [1,0] - } - return [d1/(d0+d1),d0/(d1+d0)] - } else if(simplex.length === 3) { - var closestPoint = [0,0] - closestPointToTriangle(simplex[0], simplex[1], simplex[2], point, closestPoint) - return barycentric(simplex, closestPoint) - } - return [] -} - -function interpolate(simplex, weights) { - var result = [0,0,0] - for(var i=0; i 1.0001) { - return null - } - s += weights[i] - } - if(Math.abs(s - 1.0) > 0.001) { - return null - } - return [closestIndex, interpolate(simplex, weights), weights] -} -},{"barycentric":73,"polytope-closest-point/lib/closest_point_2d.js":481}],279:[function(_dereq_,module,exports){ -var glslify = _dereq_('glslify') - -var triVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position, normal;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model\n , view\n , projection\n , inverseModel;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvec4 project(vec3 p) {\n return projection * view * model * vec4(p, 1.0);\n}\n\nvoid main() {\n gl_Position = project(position);\n\n //Lighting geometry parameters\n vec4 cameraCoordinate = view * vec4(position , 1.0);\n cameraCoordinate.xyz /= cameraCoordinate.w;\n f_lightDirection = lightPosition - cameraCoordinate.xyz;\n f_eyeDirection = eyePosition - cameraCoordinate.xyz;\n f_normal = normalize((vec4(normal, 0.0) * inverseModel).xyz);\n\n f_color = color;\n f_data = position;\n f_uv = uv;\n}\n"]) -var triFragSrc = glslify(["#extension GL_OES_standard_derivatives : enable\n\nprecision highp float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\n//#pragma glslify: beckmann = require(glsl-specular-beckmann) // used in gl-surface3d\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (f_color.a == 0.0 ||\n outOfRange(clipBounds[0], clipBounds[1], f_data)\n ) discard;\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = min(1.0, max(0.0, cookTorranceSpecular(L, V, N, roughness, fresnel)));\n //float specular = max(0.0, beckmann(L, V, N, roughness)); // used in gl-surface3d\n\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = vec4(f_color.rgb, 1.0) * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * f_color.a;\n}\n"]) -var edgeVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model, view, projection;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_color = color;\n f_data = position;\n f_uv = uv;\n}"]) -var edgeFragSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_data)) discard;\n\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}"]) -var pointVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\nattribute float pointSize;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0.0, 0.0 ,0.0 ,0.0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n }\n gl_PointSize = pointSize;\n f_color = color;\n f_uv = uv;\n}"]) -var pointFragSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n vec2 pointR = gl_PointCoord.xy - vec2(0.5, 0.5);\n if(dot(pointR, pointR) > 0.25) {\n discard;\n }\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}"]) -var pickVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_id = id;\n f_position = position;\n}"]) -var pickFragSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]) -var pickPointVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute float pointSize;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n gl_PointSize = pointSize;\n }\n f_id = id;\n f_position = position;\n}"]) -var contourVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position;\n\nuniform mat4 model, view, projection;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n}"]) -var contourFragSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nuniform vec3 contourColor;\n\nvoid main() {\n gl_FragColor = vec4(contourColor, 1.0);\n}\n"]) - -exports.meshShader = { - vertex: triVertSrc, - fragment: triFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'normal', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'uv', type: 'vec2'} - ] -} -exports.wireShader = { - vertex: edgeVertSrc, - fragment: edgeFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'uv', type: 'vec2'} - ] -} -exports.pointShader = { - vertex: pointVertSrc, - fragment: pointFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'uv', type: 'vec2'}, - {name: 'pointSize', type: 'float'} - ] -} -exports.pickShader = { - vertex: pickVertSrc, - fragment: pickFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'id', type: 'vec4'} - ] -} -exports.pointPickShader = { - vertex: pickPointVertSrc, - fragment: pickFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'pointSize', type: 'float'}, - {name: 'id', type: 'vec4'} - ] -} -exports.contourShader = { - vertex: contourVertSrc, - fragment: contourFragSrc, - attributes: [ - {name: 'position', type: 'vec3'} - ] -} - -},{"glslify":409}],280:[function(_dereq_,module,exports){ -'use strict' - -var DEFAULT_VERTEX_NORMALS_EPSILON = 1e-6; // may be too large if triangles are very small -var DEFAULT_FACE_NORMALS_EPSILON = 1e-6; - -var createShader = _dereq_('gl-shader') -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') -var createTexture = _dereq_('gl-texture2d') -var normals = _dereq_('normals') -var multiply = _dereq_('gl-mat4/multiply') -var invert = _dereq_('gl-mat4/invert') -var ndarray = _dereq_('ndarray') -var colormap = _dereq_('colormap') -var getContour = _dereq_('simplicial-complex-contour') -var pool = _dereq_('typedarray-pool') -var shaders = _dereq_('./lib/shaders') -var closestPoint = _dereq_('./lib/closest-point') - -var meshShader = shaders.meshShader -var wireShader = shaders.wireShader -var pointShader = shaders.pointShader -var pickShader = shaders.pickShader -var pointPickShader = shaders.pointPickShader -var contourShader = shaders.contourShader - -var IDENTITY = [ - 1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1] - - -function SimplicialMesh(gl - , texture - , triShader - , lineShader - , pointShader - , pickShader - , pointPickShader - , contourShader - , trianglePositions - , triangleIds - , triangleColors - , triangleUVs - , triangleNormals - , triangleVAO - , edgePositions - , edgeIds - , edgeColors - , edgeUVs - , edgeVAO - , pointPositions - , pointIds - , pointColors - , pointUVs - , pointSizes - , pointVAO - , contourPositions - , contourVAO) { - - this.gl = gl - this.pixelRatio = 1 - this.cells = [] - this.positions = [] - this.intensity = [] - this.texture = texture - this.dirty = true - - this.triShader = triShader - this.lineShader = lineShader - this.pointShader = pointShader - this.pickShader = pickShader - this.pointPickShader = pointPickShader - this.contourShader = contourShader - - this.trianglePositions = trianglePositions - this.triangleColors = triangleColors - this.triangleNormals = triangleNormals - this.triangleUVs = triangleUVs - this.triangleIds = triangleIds - this.triangleVAO = triangleVAO - this.triangleCount = 0 - - this.lineWidth = 1 - this.edgePositions = edgePositions - this.edgeColors = edgeColors - this.edgeUVs = edgeUVs - this.edgeIds = edgeIds - this.edgeVAO = edgeVAO - this.edgeCount = 0 - - this.pointPositions = pointPositions - this.pointColors = pointColors - this.pointUVs = pointUVs - this.pointSizes = pointSizes - this.pointIds = pointIds - this.pointVAO = pointVAO - this.pointCount = 0 - - this.contourLineWidth = 1 - this.contourPositions = contourPositions - this.contourVAO = contourVAO - this.contourCount = 0 - this.contourColor = [0,0,0] - this.contourEnable = true - - this.pickId = 1 - this.bounds = [ - [ Infinity, Infinity, Infinity], - [-Infinity,-Infinity,-Infinity] ] - this.clipBounds = [ - [-Infinity,-Infinity,-Infinity], - [ Infinity, Infinity, Infinity] ] - - this.lightPosition = [1e5, 1e5, 0] - this.ambientLight = 0.8 - this.diffuseLight = 0.8 - this.specularLight = 2.0 - this.roughness = 0.5 - this.fresnel = 1.5 - - this.opacity = 1.0 - this.hasAlpha = false - this.opacityscale = false - - this._model = IDENTITY - this._view = IDENTITY - this._projection = IDENTITY - this._resolution = [1,1] -} - -var proto = SimplicialMesh.prototype - -proto.isOpaque = function() { - return !this.hasAlpha -} - -proto.isTransparent = function() { - return this.hasAlpha -} - -proto.pickSlots = 1 - -proto.setPickBase = function(id) { - this.pickId = id -} - -function getOpacityFromScale(ratio, opacityscale) { - - if(!opacityscale) return 1 - if(!opacityscale.length) return 1 - - for(var i = 0; i < opacityscale.length; ++i) { - if(opacityscale.length < 2) return 1 - if(opacityscale[i][0] === ratio) return opacityscale[i][1] - if(opacityscale[i][0] > ratio && i > 0) { - var d = (opacityscale[i][0] - ratio) / (opacityscale[i][0] - opacityscale[i - 1][0]) - return opacityscale[i][1] * (1 - d) + d * opacityscale[i - 1][1] - } - } - - return 1 -} - -function genColormap(param, opacityscale) { - var colors = colormap({ - colormap: param - , nshades: 256 - , format: 'rgba' - }) - - var result = new Uint8Array(256*4) - for(var i=0; i<256; ++i) { - var c = colors[i] - for(var j=0; j<3; ++j) { - result[4*i+j] = c[j] - } - if(!opacityscale) { - result[4*i+3] = 255 * c[3] - } else { - result[4*i+3] = 255 * getOpacityFromScale(i / 255.0, opacityscale) - } - } - - return ndarray(result, [256,256,4], [4,0,1]) -} - -function unpackIntensity(cells, numVerts, cellIntensity) { - var result = new Array(numVerts) - for(var i=0; i 0) { - var shader = this.triShader - shader.bind() - shader.uniforms = uniforms - - this.triangleVAO.bind() - gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) - this.triangleVAO.unbind() - } - - if(this.edgeCount > 0 && this.lineWidth > 0) { - var shader = this.lineShader - shader.bind() - shader.uniforms = uniforms - - this.edgeVAO.bind() - gl.lineWidth(this.lineWidth * this.pixelRatio) - gl.drawArrays(gl.LINES, 0, this.edgeCount*2) - this.edgeVAO.unbind() - } - - if(this.pointCount > 0) { - var shader = this.pointShader - shader.bind() - shader.uniforms = uniforms - - this.pointVAO.bind() - gl.drawArrays(gl.POINTS, 0, this.pointCount) - this.pointVAO.unbind() - } - - if(this.contourEnable && this.contourCount > 0 && this.contourLineWidth > 0) { - var shader = this.contourShader - shader.bind() - shader.uniforms = uniforms - - this.contourVAO.bind() - gl.drawArrays(gl.LINES, 0, this.contourCount) - this.contourVAO.unbind() - } -} - -proto.drawPick = function(params) { - params = params || {} - - var gl = this.gl - - var model = params.model || IDENTITY - var view = params.view || IDENTITY - var projection = params.projection || IDENTITY - - var clipBounds = [[-1e6,-1e6,-1e6],[1e6,1e6,1e6]] - for(var i=0; i<3; ++i) { - clipBounds[0][i] = Math.max(clipBounds[0][i], this.clipBounds[0][i]) - clipBounds[1][i] = Math.min(clipBounds[1][i], this.clipBounds[1][i]) - } - - //Save camera parameters - this._model = [].slice.call(model) - this._view = [].slice.call(view) - this._projection = [].slice.call(projection) - this._resolution = [gl.drawingBufferWidth, gl.drawingBufferHeight] - - var uniforms = { - model: model, - view: view, - projection: projection, - clipBounds: clipBounds, - pickId: this.pickId / 255.0, - } - - var shader = this.pickShader - shader.bind() - shader.uniforms = uniforms - - if(this.triangleCount > 0) { - this.triangleVAO.bind() - gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) - this.triangleVAO.unbind() - } - - if(this.edgeCount > 0) { - this.edgeVAO.bind() - gl.lineWidth(this.lineWidth * this.pixelRatio) - gl.drawArrays(gl.LINES, 0, this.edgeCount*2) - this.edgeVAO.unbind() - } - - if(this.pointCount > 0) { - var shader = this.pointPickShader - shader.bind() - shader.uniforms = uniforms - - this.pointVAO.bind() - gl.drawArrays(gl.POINTS, 0, this.pointCount) - this.pointVAO.unbind() - } -} - - -proto.pick = function(pickData) { - if(!pickData) { - return null - } - if(pickData.id !== this.pickId) { - return null - } - - var cellId = pickData.value[0] + 256*pickData.value[1] + 65536*pickData.value[2] - var cell = this.cells[cellId] - var positions = this.positions - - var simplex = new Array(cell.length) - for(var i=0; i tickOffset[start]) { - shader.uniforms.dataAxis = DATA_AXIS - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.color = textColor[axis] - shader.uniforms.angle = textAngle[axis] - gl.drawArrays( - gl.TRIANGLES, - tickOffset[start], - tickOffset[end] - tickOffset[start]) - } - } - if(labelEnable[axis] && labelCount) { - SCREEN_OFFSET[axis^1] -= screenScale * pixelRatio * labelPad[axis] - shader.uniforms.dataAxis = ZERO_2 - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.color = labelColor[axis] - shader.uniforms.angle = labelAngle[axis] - gl.drawArrays( - gl.TRIANGLES, - labelOffset, - labelCount) - } - - SCREEN_OFFSET[axis^1] = screenScale * viewBox[2+(axis^1)] - 1.0 - if(tickEnable[axis+2]) { - SCREEN_OFFSET[axis^1] += screenScale * pixelRatio * tickPad[axis+2] - if(start < end && tickOffset[end] > tickOffset[start]) { - shader.uniforms.dataAxis = DATA_AXIS - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.color = textColor[axis+2] - shader.uniforms.angle = textAngle[axis+2] - gl.drawArrays( - gl.TRIANGLES, - tickOffset[start], - tickOffset[end] - tickOffset[start]) - } - } - if(labelEnable[axis+2] && labelCount) { - SCREEN_OFFSET[axis^1] += screenScale * pixelRatio * labelPad[axis+2] - shader.uniforms.dataAxis = ZERO_2 - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.color = labelColor[axis+2] - shader.uniforms.angle = labelAngle[axis+2] - gl.drawArrays( - gl.TRIANGLES, - labelOffset, - labelCount) - } - - } -})() - -proto.drawTitle = (function() { - var DATA_AXIS = [0,0] - var SCREEN_OFFSET = [0,0] - - return function() { - var plot = this.plot - var shader = this.shader - var gl = plot.gl - var screenBox = plot.screenBox - var titleCenter = plot.titleCenter - var titleAngle = plot.titleAngle - var titleColor = plot.titleColor - var pixelRatio = plot.pixelRatio - - if(!this.titleCount) { - return - } - - for(var i=0; i<2; ++i) { - SCREEN_OFFSET[i] = 2.0 * (titleCenter[i]*pixelRatio - screenBox[i]) / - (screenBox[2+i] - screenBox[i]) - 1 - } - - shader.bind() - shader.uniforms.dataAxis = DATA_AXIS - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.angle = titleAngle - shader.uniforms.color = titleColor - - gl.drawArrays(gl.TRIANGLES, this.titleOffset, this.titleCount) - } -})() - -proto.bind = (function() { - var DATA_SHIFT = [0,0] - var DATA_SCALE = [0,0] - var TEXT_SCALE = [0,0] - - return function() { - var plot = this.plot - var shader = this.shader - var bounds = plot._tickBounds - var dataBox = plot.dataBox - var screenBox = plot.screenBox - var viewBox = plot.viewBox - - shader.bind() - - //Set up coordinate scaling uniforms - for(var i=0; i<2; ++i) { - - var lo = bounds[i] - var hi = bounds[i+2] - var boundScale = hi - lo - var dataCenter = 0.5 * (dataBox[i+2] + dataBox[i]) - var dataWidth = (dataBox[i+2] - dataBox[i]) - - var viewLo = viewBox[i] - var viewHi = viewBox[i+2] - var viewScale = viewHi - viewLo - var screenLo = screenBox[i] - var screenHi = screenBox[i+2] - var screenScale = screenHi - screenLo - - DATA_SCALE[i] = 2.0 * boundScale / dataWidth * viewScale / screenScale - DATA_SHIFT[i] = 2.0 * (lo - dataCenter) / dataWidth * viewScale / screenScale - } - - TEXT_SCALE[1] = 2.0 * plot.pixelRatio / (screenBox[3] - screenBox[1]) - TEXT_SCALE[0] = TEXT_SCALE[1] * (screenBox[3] - screenBox[1]) / (screenBox[2] - screenBox[0]) - - shader.uniforms.dataScale = DATA_SCALE - shader.uniforms.dataShift = DATA_SHIFT - shader.uniforms.textScale = TEXT_SCALE - - //Set attributes - this.vbo.bind() - shader.attributes.textCoordinate.pointer() - } -})() - -proto.update = function(options) { - var vertices = [] - var axesTicks = options.ticks - var bounds = options.bounds - var i, j, k, data, scale, dimension - - for(dimension=0; dimension<2; ++dimension) { - var offsets = [Math.floor(vertices.length/3)], tickX = [-Infinity] - - //Copy vertices over to buffer - var ticks = axesTicks[dimension] - for(i=0; i= 0)) { - continue - } - - var zeroIntercept = screenBox[i] - - dataBox[i] * (screenBox[i+2] - screenBox[i]) / (dataBox[i+2] - dataBox[i]) - - if(i === 0) { - line.drawLine( - zeroIntercept, screenBox[1], zeroIntercept, screenBox[3], - zeroLineWidth[i], - zeroLineColor[i]) - } else { - line.drawLine( - screenBox[0], zeroIntercept, screenBox[2], zeroIntercept, - zeroLineWidth[i], - zeroLineColor[i]) - } - } - } - - //Draw traces - for(var i=0; i=0; --i) { - this.objects[i].dispose() - } - this.objects.length = 0 - for(var i=this.overlays.length-1; i>=0; --i) { - this.overlays[i].dispose() - } - this.overlays.length = 0 - - this.gl = null -} - -proto.addObject = function(object) { - if(this.objects.indexOf(object) < 0) { - this.objects.push(object) - this.setDirty() - } -} - -proto.removeObject = function(object) { - var objects = this.objects - for(var i=0; i Math.abs(dy)) { - view.rotate(t, 0, 0, -dx * flipX * Math.PI * camera.rotateSpeed / window.innerWidth) - } else { - if(!camera._ortho) { - var kzoom = -camera.zoomSpeed * flipY * dy / window.innerHeight * (t - view.lastT()) / 20.0 - view.pan(t, 0, 0, distance * (Math.exp(kzoom) - 1)) - } - } - }, true) - } - - camera.enableMouseListeners() - - return camera -} - -},{"3d-view":52,"has-passive-events":411,"mouse-change":435,"mouse-event-offset":436,"mouse-wheel":438,"right-now":504}],289:[function(_dereq_,module,exports){ -var glslify = _dereq_('glslify') -var createShader = _dereq_('gl-shader') - -var vertSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\nattribute vec2 position;\nvarying vec2 uv;\nvoid main() {\n uv = position;\n gl_Position = vec4(position, 0, 1);\n}"]) -var fragSrc = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nuniform sampler2D accumBuffer;\nvarying vec2 uv;\n\nvoid main() {\n vec4 accum = texture2D(accumBuffer, 0.5 * (uv + 1.0));\n gl_FragColor = min(vec4(1,1,1,1), accum);\n}"]) - -module.exports = function(gl) { - return createShader(gl, vertSrc, fragSrc, null, [ { name: 'position', type: 'vec2'}]) -} - -},{"gl-shader":301,"glslify":409}],290:[function(_dereq_,module,exports){ -'use strict' - -var createCamera = _dereq_('./camera.js') -var createAxes = _dereq_('gl-axes3d') -var axesRanges = _dereq_('gl-axes3d/properties') -var createSpikes = _dereq_('gl-spikes3d') -var createSelect = _dereq_('gl-select-static') -var createFBO = _dereq_('gl-fbo') -var drawTriangle = _dereq_('a-big-triangle') -var mouseChange = _dereq_('mouse-change') -var mouseWheel = _dereq_('mouse-wheel') -var perspective = _dereq_('gl-mat4/perspective') -var ortho = _dereq_('gl-mat4/ortho') -var createShader = _dereq_('./lib/shader') -var isMobile = _dereq_('is-mobile')({ tablet: true }) - -module.exports = { - createScene: createScene, - createCamera: createCamera -} - -function MouseSelect() { - this.mouse = [-1,-1] - this.screen = null - this.distance = Infinity - this.index = null - this.dataCoordinate = null - this.dataPosition = null - this.object = null - this.data = null -} - -function getContext(canvas, options) { - var gl = null - try { - gl = canvas.getContext('webgl', options) - if(!gl) { - gl = canvas.getContext('experimental-webgl', options) - } - } catch(e) { - return null - } - return gl -} - -function roundUpPow10(x) { - var y = Math.round(Math.log(Math.abs(x)) / Math.log(10)) - if(y < 0) { - var base = Math.round(Math.pow(10, -y)) - return Math.ceil(x*base) / base - } else if(y > 0) { - var base = Math.round(Math.pow(10, y)) - return Math.ceil(x/base) * base - } - return Math.ceil(x) -} - -function defaultBool(x) { - if(typeof x === 'boolean') { - return x - } - return true -} - -function createScene(options) { - options = options || {} - options.camera = options.camera || {} - - var canvas = options.canvas - if(!canvas) { - canvas = document.createElement('canvas') - if(options.container) { - var container = options.container - container.appendChild(canvas) - } else { - document.body.appendChild(canvas) - } - } - - var gl = options.gl - if(!gl) { - gl = getContext(canvas, - options.glOptions || { - premultipliedAlpha: true, - antialias: true, - preserveDrawingBuffer: isMobile - }) - } - if(!gl) { - throw new Error('webgl not supported') - } - - //Initial bounds - var bounds = options.bounds || [[-10,-10,-10], [10,10,10]] - - //Create selection - var selection = new MouseSelect() - - //Accumulation buffer - var accumBuffer = createFBO(gl, - [gl.drawingBufferWidth, gl.drawingBufferHeight], { - preferFloat: !isMobile - }) - - var accumShader = createShader(gl) - - var isOrtho = - (options.cameraObject && options.cameraObject._ortho === true) || - (options.camera.projection && options.camera.projection.type === 'orthographic') || - false - - //Create a camera - var cameraOptions = { - eye: options.camera.eye || [2,0,0], - center: options.camera.center || [0,0,0], - up: options.camera.up || [0,1,0], - zoomMin: options.camera.zoomMax || 0.1, - zoomMax: options.camera.zoomMin || 100, - mode: options.camera.mode || 'turntable', - _ortho: isOrtho - } - - //Create axes - var axesOptions = options.axes || {} - var axes = createAxes(gl, axesOptions) - axes.enable = !axesOptions.disable - - //Create spikes - var spikeOptions = options.spikes || {} - var spikes = createSpikes(gl, spikeOptions) - - //Object list is empty initially - var objects = [] - var pickBufferIds = [] - var pickBufferCount = [] - var pickBuffers = [] - - //Dirty flag, skip redraw if scene static - var dirty = true - var pickDirty = true - - var projection = new Array(16) - var model = new Array(16) - - var cameraParams = { - view: null, - projection: projection, - model: model, - _ortho: false - } - - var pickDirty = true - - var viewShape = [ gl.drawingBufferWidth, gl.drawingBufferHeight ] - - var camera = options.cameraObject || createCamera(canvas, cameraOptions) - - //Create scene object - var scene = { - gl: gl, - contextLost: false, - pixelRatio: options.pixelRatio || 1, - canvas: canvas, - selection: selection, - camera: camera, - axes: axes, - axesPixels: null, - spikes: spikes, - bounds: bounds, - objects: objects, - shape: viewShape, - aspect: options.aspectRatio || [1,1,1], - pickRadius: options.pickRadius || 10, - zNear: options.zNear || 0.01, - zFar: options.zFar || 1000, - fovy: options.fovy || Math.PI/4, - clearColor: options.clearColor || [0,0,0,0], - autoResize: defaultBool(options.autoResize), - autoBounds: defaultBool(options.autoBounds), - autoScale: !!options.autoScale, - autoCenter: defaultBool(options.autoCenter), - clipToBounds: defaultBool(options.clipToBounds), - snapToData: !!options.snapToData, - onselect: options.onselect || null, - onrender: options.onrender || null, - onclick: options.onclick || null, - cameraParams: cameraParams, - oncontextloss: null, - mouseListener: null, - _stopped: false - } - - var pickShape = [ (gl.drawingBufferWidth/scene.pixelRatio)|0, (gl.drawingBufferHeight/scene.pixelRatio)|0 ] - - function resizeListener() { - if(scene._stopped) { - return - } - if(!scene.autoResize) { - return - } - var parent = canvas.parentNode - var width = 1 - var height = 1 - if(parent && parent !== document.body) { - width = parent.clientWidth - height = parent.clientHeight - } else { - width = window.innerWidth - height = window.innerHeight - } - var nextWidth = Math.ceil(width * scene.pixelRatio)|0 - var nextHeight = Math.ceil(height * scene.pixelRatio)|0 - if(nextWidth !== canvas.width || nextHeight !== canvas.height) { - canvas.width = nextWidth - canvas.height = nextHeight - var style = canvas.style - style.position = style.position || 'absolute' - style.left = '0px' - style.top = '0px' - style.width = width + 'px' - style.height = height + 'px' - dirty = true - } - } - if(scene.autoResize) { - resizeListener() - } - window.addEventListener('resize', resizeListener) - - function reallocPickIds() { - var numObjs = objects.length - var numPick = pickBuffers.length - for(var i=0; i 0 && pickBufferCount[numPick-1] === 0) { - pickBufferCount.pop() - pickBuffers.pop().dispose() - } - } - - scene.update = function(options) { - - if(scene._stopped) { - return - } - options = options || {} - dirty = true - pickDirty = true - } - - scene.add = function(obj) { - if(scene._stopped) { - return - } - obj.axes = axes - objects.push(obj) - pickBufferIds.push(-1) - dirty = true - pickDirty = true - reallocPickIds() - } - - scene.remove = function(obj) { - if(scene._stopped) { - return - } - var idx = objects.indexOf(obj) - if(idx < 0) { - return - } - objects.splice(idx, 1) - pickBufferIds.pop() - dirty = true - pickDirty = true - reallocPickIds() - } - - scene.dispose = function() { - if(scene._stopped) { - return - } - - scene._stopped = true - - window.removeEventListener('resize', resizeListener) - canvas.removeEventListener('webglcontextlost', checkContextLoss) - scene.mouseListener.enabled = false - - if(scene.contextLost) { - return - } - - //Destroy objects - axes.dispose() - spikes.dispose() - for(var i=0; i dy) ? 1.1 : 1.0 / 1.1 - - scene.aspect[0] *= s - scene.aspect[1] *= s - scene.aspect[2] *= s - scene.redraw() - } - }, true) - - //Update mouse position - scene._mouseRotating = false - scene._prevButtons = 0 - - scene.enableMouseListeners = function() { - - scene.mouseListener = mouseChange(canvas, function(buttons, x, y) { - if(scene._stopped) { - return - } - - var numPick = pickBuffers.length - var numObjs = objects.length - var prevObj = selection.object - - selection.distance = Infinity - selection.mouse[0] = x - selection.mouse[1] = y - selection.object = null - selection.screen = null - selection.dataCoordinate = selection.dataPosition = null - - var change = false - - if(buttons && scene._prevButtons) { - scene._mouseRotating = true - } else { - if(scene._mouseRotating) { - pickDirty = true - } - scene._mouseRotating = false - - for(var i=0; i selection.distance) { - continue - } - for(var j=0; j 1.0) {\n discard;\n }\n baseColor = mix(borderColor, color, step(radius, centerFraction));\n gl_FragColor = vec4(baseColor.rgb * baseColor.a, baseColor.a);\n }\n}\n"]) -exports.pickVertex = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\nattribute vec4 pickId;\n\nuniform mat3 matrix;\nuniform float pointSize;\nuniform vec4 pickOffset;\n\nvarying vec4 fragId;\n\nvoid main() {\n vec3 hgPosition = matrix * vec3(position, 1);\n gl_Position = vec4(hgPosition.xy, 0, hgPosition.z);\n gl_PointSize = pointSize;\n\n vec4 id = pickId + pickOffset;\n id.y += floor(id.x / 256.0);\n id.x -= floor(id.x / 256.0) * 256.0;\n\n id.z += floor(id.y / 256.0);\n id.y -= floor(id.y / 256.0) * 256.0;\n\n id.w += floor(id.z / 256.0);\n id.z -= floor(id.z / 256.0) * 256.0;\n\n fragId = id;\n}\n"]) -exports.pickFragment = glslify(["precision mediump float;\n#define GLSLIFY 1\n\nvarying vec4 fragId;\n\nvoid main() {\n float radius = length(2.0 * gl_PointCoord.xy - 1.0);\n if(radius > 1.0) {\n discard;\n }\n gl_FragColor = fragId / 255.0;\n}\n"]) - -},{"glslify":409}],292:[function(_dereq_,module,exports){ -'use strict' - -var createShader = _dereq_('gl-shader') -var createBuffer = _dereq_('gl-buffer') - -var pool = _dereq_('typedarray-pool') - -var SHADERS = _dereq_('./lib/shader') - -module.exports = createPointcloud2D - -function Pointcloud2D(plot, offsetBuffer, pickBuffer, shader, pickShader) { - this.plot = plot - this.offsetBuffer = offsetBuffer - this.pickBuffer = pickBuffer - this.shader = shader - this.pickShader = pickShader - this.sizeMin = 0.5 - this.sizeMinCap = 2 - this.sizeMax = 20 - this.areaRatio = 1.0 - this.pointCount = 0 - this.color = [1, 0, 0, 1] - this.borderColor = [0, 0, 0, 1] - this.blend = false - this.pickOffset = 0 - this.points = null -} - -var proto = Pointcloud2D.prototype - -proto.dispose = function() { - this.shader.dispose() - this.pickShader.dispose() - this.offsetBuffer.dispose() - this.pickBuffer.dispose() - this.plot.removeObject(this) -} - -proto.update = function(options) { - - var i - - options = options || {} - - function dflt(opt, value) { - if(opt in options) { - return options[opt] - } - return value - } - - this.sizeMin = dflt('sizeMin', 0.5) - // this.sizeMinCap = dflt('sizeMinCap', 2) - this.sizeMax = dflt('sizeMax', 20) - this.color = dflt('color', [1, 0, 0, 1]).slice() - this.areaRatio = dflt('areaRatio', 1) - this.borderColor = dflt('borderColor', [0, 0, 0, 1]).slice() - this.blend = dflt('blend', false) - - //Update point data - - // Attempt straight-through processing (STP) to avoid allocation and copy - // TODO eventually abstract out STP logic, maybe into `pool` or a layer above - var pointCount = options.positions.length >>> 1 - var dataStraightThrough = options.positions instanceof Float32Array - var idStraightThrough = options.idToIndex instanceof Int32Array && options.idToIndex.length >= pointCount // permit larger to help reuse - - var data = options.positions - var packed = dataStraightThrough ? data : pool.mallocFloat32(data.length) - var packedId = idStraightThrough ? options.idToIndex : pool.mallocInt32(pointCount) - - if(!dataStraightThrough) { - packed.set(data) - } - - if(!idStraightThrough) { - packed.set(data) - for(i = 0; i < pointCount; i++) { - packedId[i] = i - } - } - - this.points = data - - this.offsetBuffer.update(packed) - this.pickBuffer.update(packedId) - - if(!dataStraightThrough) { - pool.free(packed) - } - - if(!idStraightThrough) { - pool.free(packedId) - } - - this.pointCount = pointCount - this.pickOffset = 0 -} - -function count(points, dataBox) { - var visiblePointCountEstimate = 0 - var length = points.length >>> 1 - var i - for(i = 0; i < length; i++) { - var x = points[i * 2] - var y = points[i * 2 + 1] - if(x >= dataBox[0] && x <= dataBox[2] && y >= dataBox[1] && y <= dataBox[3]) - visiblePointCountEstimate++ - } - return visiblePointCountEstimate -} - -proto.unifiedDraw = (function() { - var MATRIX = [1, 0, 0, - 0, 1, 0, - 0, 0, 1] - var PICK_VEC4 = [0, 0, 0, 0] -return function(pickOffset) { - var pick = pickOffset !== void(0) - - var shader = pick ? this.pickShader : this.shader - var gl = this.plot.gl - var dataBox = this.plot.dataBox - - if(this.pointCount === 0) { - return pickOffset - } - - var dataX = dataBox[2] - dataBox[0] - var dataY = dataBox[3] - dataBox[1] - - var visiblePointCountEstimate = count(this.points, dataBox) - var basicPointSize = this.plot.pickPixelRatio * Math.max(Math.min(this.sizeMinCap, this.sizeMin), Math.min(this.sizeMax, this.sizeMax / Math.pow(visiblePointCountEstimate, 0.33333))) - - MATRIX[0] = 2.0 / dataX - MATRIX[4] = 2.0 / dataY - MATRIX[6] = -2.0 * dataBox[0] / dataX - 1.0 - MATRIX[7] = -2.0 * dataBox[1] / dataY - 1.0 - - this.offsetBuffer.bind() - - shader.bind() - shader.attributes.position.pointer() - shader.uniforms.matrix = MATRIX - shader.uniforms.color = this.color - shader.uniforms.borderColor = this.borderColor - shader.uniforms.pointCloud = basicPointSize < 5 - shader.uniforms.pointSize = basicPointSize - shader.uniforms.centerFraction = Math.min(1, Math.max(0, Math.sqrt(1 - this.areaRatio))) - - if(pick) { - - PICK_VEC4[0] = ( pickOffset & 0xff) - PICK_VEC4[1] = ((pickOffset >> 8) & 0xff) - PICK_VEC4[2] = ((pickOffset >> 16) & 0xff) - PICK_VEC4[3] = ((pickOffset >> 24) & 0xff) - - this.pickBuffer.bind() - shader.attributes.pickId.pointer(gl.UNSIGNED_BYTE) - shader.uniforms.pickOffset = PICK_VEC4 - this.pickOffset = pickOffset - } - - // Worth switching these off, but we can't make assumptions about other - // renderers, so let's restore it after each draw - var blend = gl.getParameter(gl.BLEND) - var dither = gl.getParameter(gl.DITHER) - - if(blend && !this.blend) - gl.disable(gl.BLEND) - if(dither) - gl.disable(gl.DITHER) - - gl.drawArrays(gl.POINTS, 0, this.pointCount) - - if(blend && !this.blend) - gl.enable(gl.BLEND) - if(dither) - gl.enable(gl.DITHER) - - return pickOffset + this.pointCount -} -})() - -proto.draw = proto.unifiedDraw -proto.drawPick = proto.unifiedDraw - -proto.pick = function(x, y, value) { - var pickOffset = this.pickOffset - var pointCount = this.pointCount - if(value < pickOffset || value >= pickOffset + pointCount) { - return null - } - var pointId = value - pickOffset - var points = this.points - return { - object: this, - pointId: pointId, - dataCoord: [points[2 * pointId], points[2 * pointId + 1] ] - } -} - -function createPointcloud2D(plot, options) { - var gl = plot.gl - var buffer = createBuffer(gl) - var pickBuffer = createBuffer(gl) - var shader = createShader(gl, SHADERS.pointVertex, SHADERS.pointFragment) - var pickShader = createShader(gl, SHADERS.pickVertex, SHADERS.pickFragment) - - var result = new Pointcloud2D(plot, buffer, pickBuffer, shader, pickShader) - result.update(options) - - //Register with plot - plot.addObject(result) - - return result -} - -},{"./lib/shader":291,"gl-buffer":241,"gl-shader":301,"typedarray-pool":545}],293:[function(_dereq_,module,exports){ -module.exports = slerp - -/** - * Performs a spherical linear interpolation between two quat - * - * @param {quat} out the receiving quaternion - * @param {quat} a the first operand - * @param {quat} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {quat} out - */ -function slerp (out, a, b, t) { - // benchmarks: - // http://jsperf.com/quaternion-slerp-implementations - - var ax = a[0], ay = a[1], az = a[2], aw = a[3], - bx = b[0], by = b[1], bz = b[2], bw = b[3] - - var omega, cosom, sinom, scale0, scale1 - - // calc cosine - cosom = ax * bx + ay * by + az * bz + aw * bw - // adjust signs (if necessary) - if (cosom < 0.0) { - cosom = -cosom - bx = -bx - by = -by - bz = -bz - bw = -bw - } - // calculate coefficients - if ((1.0 - cosom) > 0.000001) { - // standard case (slerp) - omega = Math.acos(cosom) - sinom = Math.sin(omega) - scale0 = Math.sin((1.0 - t) * omega) / sinom - scale1 = Math.sin(t * omega) / sinom - } else { - // "from" and "to" quaternions are very close - // ... so we can do a linear interpolation - scale0 = 1.0 - t - scale1 = t - } - // calculate final values - out[0] = scale0 * ax + scale1 * bx - out[1] = scale0 * ay + scale1 * by - out[2] = scale0 * az + scale1 * bz - out[3] = scale0 * aw + scale1 * bw - - return out -} - -},{}],294:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = function(a){ - return (!a && a !== 0) ? '' : a.toString(); -} - -},{}],295:[function(_dereq_,module,exports){ -"use strict" - -var vectorizeText = _dereq_("vectorize-text") - -module.exports = getGlyph - -var GLYPH_CACHE = {} - -function getGlyph(symbol, font, pixelRatio) { - var fontCache = GLYPH_CACHE[font] - if(!fontCache) { - fontCache = GLYPH_CACHE[font] = {} - } - if(symbol in fontCache) { - return fontCache[symbol] - } - - var config = { - textAlign: "center", - textBaseline: "middle", - lineHeight: 1.0, - font: font, - lineSpacing: 1.25, - styletags: { - breaklines:true, - bolds: true, - italics: true, - subscripts:true, - superscripts:true - } - } - - //Get line and triangle meshes for glyph - config.triangles = true - var triSymbol = vectorizeText(symbol, config) - config.triangles = false - var lineSymbol = vectorizeText(symbol, config) - - var i, j - - if(pixelRatio && pixelRatio !== 1) { - for(i = 0; i < triSymbol.positions.length; ++i){ - for(j = 0; j < triSymbol.positions[i].length; ++j){ - triSymbol.positions[i][j] /= pixelRatio; - } - } - - for(i = 0; i < lineSymbol.positions.length; ++i){ - for(j = 0; j < lineSymbol.positions[i].length; ++j){ - lineSymbol.positions[i][j] /= pixelRatio; - } - } - } - - //Calculate bounding box - var bounds = [[Infinity,Infinity], [-Infinity,-Infinity]] - var n = lineSymbol.positions.length - for(i = 0; i < n; ++i) { - var p = lineSymbol.positions[i] - for(j=0; j<2; ++j) { - bounds[0][j] = Math.min(bounds[0][j], p[j]) - bounds[1][j] = Math.max(bounds[1][j], p[j]) - } - } - - //Save cached symbol - return fontCache[symbol] = [triSymbol, lineSymbol, bounds] -} -},{"vectorize-text":550}],296:[function(_dereq_,module,exports){ -var createShaderWrapper = _dereq_('gl-shader') -var glslify = _dereq_('glslify') - -var perspectiveVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform vec4 highlightId;\nuniform float highlightScale;\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = 1.0;\n if(distance(highlightId, id) < 0.0001) {\n scale = highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1);\n vec4 viewPosition = view * worldPosition;\n viewPosition = viewPosition / viewPosition.w;\n vec4 clipPosition = projection * (viewPosition + scale * vec4(glyph.x, -glyph.y, 0, 0));\n\n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}"]) -var orthographicVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float highlightScale, pixelRatio;\nuniform vec4 highlightId;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = pixelRatio;\n if(distance(highlightId.bgr, id.bgr) < 0.001) {\n scale *= highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1.0);\n vec4 viewPosition = view * worldPosition;\n vec4 clipPosition = projection * viewPosition;\n clipPosition /= clipPosition.w;\n\n gl_Position = clipPosition + vec4(screenSize * scale * vec2(glyph.x, -glyph.y), 0.0, 0.0);\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}"]) -var projectionVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform float highlightScale;\nuniform vec4 highlightId;\nuniform vec3 axes[2];\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float scale, pixelRatio;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float lscale = pixelRatio * scale;\n if(distance(highlightId, id) < 0.0001) {\n lscale *= highlightScale;\n }\n\n vec4 clipCenter = projection * view * model * vec4(position, 1);\n vec3 dataPosition = position + 0.5*lscale*(axes[0] * glyph.x + axes[1] * glyph.y) * clipCenter.w * screenSize.y;\n vec4 clipPosition = projection * view * model * vec4(dataPosition, 1);\n\n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = dataPosition;\n }\n}\n"]) -var drawFragSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 fragClipBounds[2];\nuniform float opacity;\n\nvarying vec4 interpColor;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (\n outOfRange(fragClipBounds[0], fragClipBounds[1], dataCoordinate) ||\n interpColor.a * opacity == 0.\n ) discard;\n gl_FragColor = interpColor * opacity;\n}\n"]) -var pickFragSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 fragClipBounds[2];\nuniform float pickGroup;\n\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(fragClipBounds[0], fragClipBounds[1], dataCoordinate)) discard;\n\n gl_FragColor = vec4(pickGroup, pickId.bgr);\n}"]) - -var ATTRIBUTES = [ - {name: 'position', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'glyph', type: 'vec2'}, - {name: 'id', type: 'vec4'} -] - -var perspective = { - vertex: perspectiveVertSrc, - fragment: drawFragSrc, - attributes: ATTRIBUTES - }, - ortho = { - vertex: orthographicVertSrc, - fragment: drawFragSrc, - attributes: ATTRIBUTES - }, - project = { - vertex: projectionVertSrc, - fragment: drawFragSrc, - attributes: ATTRIBUTES - }, - pickPerspective = { - vertex: perspectiveVertSrc, - fragment: pickFragSrc, - attributes: ATTRIBUTES - }, - pickOrtho = { - vertex: orthographicVertSrc, - fragment: pickFragSrc, - attributes: ATTRIBUTES - }, - pickProject = { - vertex: projectionVertSrc, - fragment: pickFragSrc, - attributes: ATTRIBUTES - } - -function createShader(gl, src) { - var shader = createShaderWrapper(gl, src) - var attr = shader.attributes - attr.position.location = 0 - attr.color.location = 1 - attr.glyph.location = 2 - attr.id.location = 3 - return shader -} - -exports.createPerspective = function(gl) { - return createShader(gl, perspective) -} -exports.createOrtho = function(gl) { - return createShader(gl, ortho) -} -exports.createProject = function(gl) { - return createShader(gl, project) -} -exports.createPickPerspective = function(gl) { - return createShader(gl, pickPerspective) -} -exports.createPickOrtho = function(gl) { - return createShader(gl, pickOrtho) -} -exports.createPickProject = function(gl) { - return createShader(gl, pickProject) -} - -},{"gl-shader":301,"glslify":409}],297:[function(_dereq_,module,exports){ -'use strict' - -var isAllBlank = _dereq_('is-string-blank') -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') -var pool = _dereq_('typedarray-pool') -var mat4mult = _dereq_('gl-mat4/multiply') -var shaders = _dereq_('./lib/shaders') -var getGlyph = _dereq_('./lib/glyphs') -var getSimpleString = _dereq_('./lib/get-simple-string') - -var IDENTITY = [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1] - -module.exports = createPointCloud - -function transformMat4(x, m) { - var x0 = x[0] - var x1 = x[1] - var x2 = x[2] - var x3 = x[3] - x[0] = m[0] * x0 + m[4] * x1 + m[8] * x2 + m[12] * x3 - x[1] = m[1] * x0 + m[5] * x1 + m[9] * x2 + m[13] * x3 - x[2] = m[2] * x0 + m[6] * x1 + m[10] * x2 + m[14] * x3 - x[3] = m[3] * x0 + m[7] * x1 + m[11] * x2 + m[15] * x3 - return x -} - -function project(p, v, m, x) { - transformMat4(x, x, m) - transformMat4(x, x, v) - return transformMat4(x, x, p) -} - -function ScatterPlotPickResult(index, position) { - this.index = index - this.dataCoordinate = this.position = position -} - -function fixOpacity(a) { - if(a === true) return 1 - if(a > 1) return 1 - return a -} - -function PointCloud( - gl, - shader, - orthoShader, - projectShader, - pointBuffer, - colorBuffer, - glyphBuffer, - idBuffer, - vao, - pickPerspectiveShader, - pickOrthoShader, - pickProjectShader) { - - this.gl = gl - - this.pixelRatio = 1 - - this.shader = shader - this.orthoShader = orthoShader - this.projectShader = projectShader - - this.pointBuffer = pointBuffer - this.colorBuffer = colorBuffer - this.glyphBuffer = glyphBuffer - this.idBuffer = idBuffer - this.vao = vao - this.vertexCount = 0 - this.lineVertexCount = 0 - - this.opacity = 1 - this.hasAlpha = false - - this.lineWidth = 0 - this.projectScale = [2.0/3.0, 2.0/3.0, 2.0/3.0] - this.projectOpacity = [1, 1, 1] - this.projectHasAlpha = false - - this.pickId = 0 - this.pickPerspectiveShader = pickPerspectiveShader - this.pickOrthoShader = pickOrthoShader - this.pickProjectShader = pickProjectShader - this.points = [] - - this._selectResult = new ScatterPlotPickResult(0, [0,0,0]) - - this.useOrtho = true - this.bounds = [[ Infinity,Infinity,Infinity], - [-Infinity,-Infinity,-Infinity]] - - //Axes projections - this.axesProject = [ true, true, true ] - this.axesBounds = [[-Infinity,-Infinity,-Infinity], - [ Infinity, Infinity, Infinity]] - - this.highlightId = [1,1,1,1] - this.highlightScale = 2 - - this.clipBounds = [[-Infinity,-Infinity,-Infinity], - [ Infinity, Infinity, Infinity]] - - this.dirty = true -} - -var proto = PointCloud.prototype - -proto.pickSlots = 1 - -proto.setPickBase = function(pickBase) { - this.pickId = pickBase -} - -proto.isTransparent = function() { - if(this.hasAlpha) { - return true - } - for(var i=0; i<3; ++i) { - if(this.axesProject[i] && this.projectHasAlpha) { - return true - } - } - return false -} - -proto.isOpaque = function() { - if(!this.hasAlpha) { - return true - } - for(var i=0; i<3; ++i) { - if(this.axesProject[i] && !this.projectHasAlpha) { - return true - } - } - return false -} - -var VIEW_SHAPE = [0,0] -var U_VEC = [0,0,0] -var V_VEC = [0,0,0] -var MU_VEC = [0,0,0,1] -var MV_VEC = [0,0,0,1] -var SCRATCH_MATRIX = IDENTITY.slice() -var SCRATCH_VEC = [0,0,0] -var CLIP_BOUNDS = [[0,0,0], [0,0,0]] - -function zeroVec(a) { - a[0] = a[1] = a[2] = 0 - return a -} - -function augment(hg, af) { - hg[0] = af[0] - hg[1] = af[1] - hg[2] = af[2] - hg[3] = 1 - return hg -} - -function setComponent(out, v, i, x) { - out[0] = v[0] - out[1] = v[1] - out[2] = v[2] - out[i] = x - return out -} - -function getClipBounds(bounds) { - var result = CLIP_BOUNDS - for(var i=0; i<2; ++i) { - for(var j=0; j<3; ++j) { - result[i][j] = Math.max(Math.min(bounds[i][j], 1e8), -1e8) - } - } - return result -} - -function drawProject(shader, points, camera, pixelRatio) { - var axesProject = points.axesProject - - var gl = points.gl - var uniforms = shader.uniforms - var model = camera.model || IDENTITY - var view = camera.view || IDENTITY - var projection = camera.projection || IDENTITY - var bounds = points.axesBounds - var clipBounds = getClipBounds(points.clipBounds) - - var cubeAxis - if(points.axes && points.axes.lastCubeProps) { - cubeAxis = points.axes.lastCubeProps.axis - } else { - cubeAxis = [1,1,1] - } - - VIEW_SHAPE[0] = 2.0/gl.drawingBufferWidth - VIEW_SHAPE[1] = 2.0/gl.drawingBufferHeight - - shader.bind() - uniforms.view = view - uniforms.projection = projection - uniforms.screenSize = VIEW_SHAPE - uniforms.highlightId = points.highlightId - uniforms.highlightScale = points.highlightScale - uniforms.clipBounds = clipBounds - uniforms.pickGroup = points.pickId / 255.0 - uniforms.pixelRatio = pixelRatio - - for(var i=0; i<3; ++i) { - if(!axesProject[i]) { - continue - } - - uniforms.scale = points.projectScale[i] - uniforms.opacity = points.projectOpacity[i] - - //Project model matrix - var pmodel = SCRATCH_MATRIX - for(var j=0; j<16; ++j) { - pmodel[j] = 0 - } - for(var j=0; j<4; ++j) { - pmodel[5*j] = 1 - } - pmodel[5*i] = 0 - if(cubeAxis[i] < 0) { - pmodel[12+i] = bounds[0][i] - } else { - pmodel[12+i] = bounds[1][i] - } - mat4mult(pmodel, model, pmodel) - uniforms.model = pmodel - - //Compute initial axes - var u = (i+1)%3 - var v = (i+2)%3 - var du = zeroVec(U_VEC) - var dv = zeroVec(V_VEC) - du[u] = 1 - dv[v] = 1 - - //Align orientation relative to viewer - var mdu = project(projection, view, model, augment(MU_VEC, du)) - var mdv = project(projection, view, model, augment(MV_VEC, dv)) - if(Math.abs(mdu[1]) > Math.abs(mdv[1])) { - var tmp = mdu - mdu = mdv - mdv = tmp - tmp = du - du = dv - dv = tmp - var t = u - u = v - v = t - } - if(mdu[0] < 0) { - du[u] = -1 - } - if(mdv[1] > 0) { - dv[v] = -1 - } - var su = 0.0 - var sv = 0.0 - for(var j=0; j<4; ++j) { - su += Math.pow(model[4*u+j], 2) - sv += Math.pow(model[4*v+j], 2) - } - du[u] /= Math.sqrt(su) - dv[v] /= Math.sqrt(sv) - uniforms.axes[0] = du - uniforms.axes[1] = dv - - //Update fragment clip bounds - uniforms.fragClipBounds[0] = setComponent(SCRATCH_VEC, clipBounds[0], i, -1e8) - uniforms.fragClipBounds[1] = setComponent(SCRATCH_VEC, clipBounds[1], i, 1e8) - - points.vao.bind() - - //Draw interior - points.vao.draw(gl.TRIANGLES, points.vertexCount) - - //Draw edges - if(points.lineWidth > 0) { - gl.lineWidth(points.lineWidth * pixelRatio) - points.vao.draw(gl.LINES, points.lineVertexCount, points.vertexCount) - } - - points.vao.unbind() - } -} - - -var NEG_INFINITY3 = [-1e8, -1e8, -1e8] -var POS_INFINITY3 = [1e8, 1e8, 1e8] -var CLIP_GROUP = [NEG_INFINITY3, POS_INFINITY3] - -function drawFull(shader, pshader, points, camera, pixelRatio, transparent, forceDraw) { - var gl = points.gl - - if(transparent === points.projectHasAlpha || forceDraw) { - drawProject(pshader, points, camera, pixelRatio) - } - - if(transparent === points.hasAlpha || forceDraw) { - - shader.bind() - var uniforms = shader.uniforms - - uniforms.model = camera.model || IDENTITY - uniforms.view = camera.view || IDENTITY - uniforms.projection = camera.projection || IDENTITY - - VIEW_SHAPE[0] = 2.0/gl.drawingBufferWidth - VIEW_SHAPE[1] = 2.0/gl.drawingBufferHeight - uniforms.screenSize = VIEW_SHAPE - - uniforms.highlightId = points.highlightId - uniforms.highlightScale = points.highlightScale - - uniforms.fragClipBounds = CLIP_GROUP - uniforms.clipBounds = points.axes.bounds - - uniforms.opacity = points.opacity - uniforms.pickGroup = points.pickId / 255.0 - - uniforms.pixelRatio = pixelRatio - - points.vao.bind() - - //Draw interior - points.vao.draw(gl.TRIANGLES, points.vertexCount) - - //Draw edges - if(points.lineWidth > 0) { - gl.lineWidth(points.lineWidth * pixelRatio) - points.vao.draw(gl.LINES, points.lineVertexCount, points.vertexCount) - } - - points.vao.unbind() - } - - -} - -proto.draw = function(camera) { - var shader = this.useOrtho ? this.orthoShader : this.shader - drawFull(shader, this.projectShader, this, camera, this.pixelRatio, false, false) -} - -proto.drawTransparent = function(camera) { - var shader = this.useOrtho ? this.orthoShader : this.shader - drawFull(shader, this.projectShader, this, camera, this.pixelRatio, true, false) -} - -proto.drawPick = function(camera) { - var shader = this.useOrtho ? this.pickOrthoShader : this.pickPerspectiveShader - drawFull(shader, this.pickProjectShader, this, camera, 1, true, true) -} - -proto.pick = function(selected) { - if(!selected) { - return null - } - if(selected.id !== this.pickId) { - return null - } - var x = selected.value[2] + (selected.value[1]<<8) + (selected.value[0]<<16) - if(x >= this.pointCount || x < 0) { - return null - } - - //Unpack result - var coord = this.points[x] - var result = this._selectResult - result.index = x - for(var i=0; i<3; ++i) { - result.position[i] = result.dataCoordinate[i] = coord[i] - } - return result -} - -proto.highlight = function(selection) { - if(!selection) { - this.highlightId = [1,1,1,1] - } else { - var pointId = selection.index - var a0 = pointId &0xff - var a1 = (pointId>>8) &0xff - var a2 = (pointId>>16)&0xff - this.highlightId = [a0/255.0, a1/255.0, a2/255.0, 0] - } -} - -function get_glyphData(glyphs, index, font, pixelRatio) { - var str - - // use the data if presented in an array - if(Array.isArray(glyphs)) { - if(index < glyphs.length) { - str = glyphs[index] - } else { - str = undefined - } - } else { - str = glyphs - } - - str = getSimpleString(str) // this would handle undefined cases - - var visible = true - if(isAllBlank(str)) { - str = '▼' // Note: this special character may have minimum number of surfaces - visible = false - } - - var glyph = getGlyph(str, font, pixelRatio) - - return { mesh:glyph[0], - lines:glyph[1], - bounds:glyph[2], - visible:visible }; -} - - - -proto.update = function(options) { - - options = options || {} - - if('perspective' in options) { - this.useOrtho = !options.perspective - } - if('orthographic' in options) { - this.useOrtho = !!options.orthographic - } - if('lineWidth' in options) { - this.lineWidth = options.lineWidth - } - if('project' in options) { - if(Array.isArray(options.project)) { - this.axesProject = options.project - } else { - var v = !!options.project - this.axesProject = [v,v,v] - } - } - if('projectScale' in options) { - if(Array.isArray(options.projectScale)) { - this.projectScale = options.projectScale.slice() - } else { - var s = +options.projectScale - this.projectScale = [s,s,s] - } - } - - this.projectHasAlpha = false // default to no transparent draw - if('projectOpacity' in options) { - if(Array.isArray(options.projectOpacity)) { - this.projectOpacity = options.projectOpacity.slice() - } else { - var s = +options.projectOpacity - this.projectOpacity = [s,s,s] - } - for(var i=0; i<3; ++i) { - this.projectOpacity[i] = fixOpacity(this.projectOpacity[i]); - if(this.projectOpacity[i] < 1) { - this.projectHasAlpha = true; - } - } - } - - this.hasAlpha = false // default to no transparent draw - if('opacity' in options) { - this.opacity = fixOpacity(options.opacity) - if(this.opacity < 1) { - this.hasAlpha = true; - } - } - - //Set dirty flag - this.dirty = true - - //Create new buffers - var points = options.position - - //Text font - var font = options.font || 'normal' - var alignment = options.alignment || [0,0] - - var alignmentX; - var alignmentY; - if (alignment.length === 2) { - alignmentX = alignment[0] - alignmentY = alignment[1] - } else { - alignmentX = [] - alignmentY = [] - for (var i = 0; i < alignment.length; ++i) { - alignmentX[i] = alignment[i][0] - alignmentY[i] = alignment[i][1] - } - } - - //Bounds - var lowerBound = [ Infinity, Infinity, Infinity] - var upperBound = [-Infinity,-Infinity,-Infinity] - - //Unpack options - var glyphs = options.glyph - var colors = options.color - var sizes = options.size - var angles = options.angle - var lineColors = options.lineColor - - //Picking geometry - var pickCounter = -1 - - //First do pass to compute buffer sizes - var triVertexCount = 0 - var lineVertexCount = 0 - - var numPoints = 0; - - if(points.length) { - - //Count number of points and buffer size - numPoints = points.length - - count_loop: - for(var i=0; i 0) { - var triOffset = 0 - var lineOffset = triVertexCount - var color = [0,0,0,1] - var lineColor = [0,0,0,1] - - var isColorArray = Array.isArray(colors) && Array.isArray(colors[0]) - var isLineColorArray = Array.isArray(lineColors) && Array.isArray(lineColors[0]) - - fill_loop: - for(var i=0; i 0) ? (1 - glyphBounds[0][0]) : - (textOffsetX < 0) ? (1 + glyphBounds[1][0]) : 1; - - textOffsetY *= (textOffsetY > 0) ? (1 - glyphBounds[0][1]) : - (textOffsetY < 0) ? (1 + glyphBounds[1][1]) : 1; - - var textOffset = [textOffsetX, textOffsetY] - - //Write out inner marker - var cells = glyphMesh.cells || [] - var verts = glyphMesh.positions || [] - - for(var j=0; j 0) { - - //Draw border - var w = lineWidth * pixelRatio - boxes.drawBox(loX-w, loY-w, hiX+w, loY+w, borderColor) - boxes.drawBox(loX-w, hiY-w, hiX+w, hiY+w, borderColor) - boxes.drawBox(loX-w, loY-w, loX+w, hiY+w, borderColor) - boxes.drawBox(hiX-w, loY-w, hiX+w, hiY+w, borderColor) - } -} - -proto.update = function(options) { - options = options || {} - - this.innerFill = !!options.innerFill - this.outerFill = !!options.outerFill - this.innerColor = (options.innerColor || [0,0,0,0.5]).slice() - this.outerColor = (options.outerColor || [0,0,0,0.5]).slice() - this.borderColor = (options.borderColor || [0,0,0,1]).slice() - this.borderWidth = options.borderWidth || 0 - this.selectBox = (options.selectBox || this.selectBox).slice() -} - -proto.dispose = function() { - this.boxBuffer.dispose() - this.boxShader.dispose() - this.plot.removeOverlay(this) -} - -function createSelectBox(plot, options) { - var gl = plot.gl - var buffer = createBuffer(gl, [ - 0, 0, - 0, 1, - 1, 0, - 1, 1 ]) - var shader = createShader(gl, SHADERS.boxVertex, SHADERS.boxFragment) - var selectBox = new SelectBox(plot, buffer, shader) - selectBox.update(options) - plot.addOverlay(selectBox) - return selectBox -} - -},{"./lib/shaders":298,"gl-buffer":241,"gl-shader":301}],300:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createSelectBuffer - -var createFBO = _dereq_('gl-fbo') -var pool = _dereq_('typedarray-pool') -var ndarray = _dereq_('ndarray') - -var nextPow2 = _dereq_('bit-twiddle').nextPow2 - -var selectRange = _dereq_('cwise/lib/wrapper')({"args":["array",{"offset":[0,0,1],"array":0},{"offset":[0,0,2],"array":0},{"offset":[0,0,3],"array":0},"scalar","scalar","index"],"pre":{"body":"{this_closestD2=1e8,this_closestX=-1,this_closestY=-1}","args":[],"thisVars":["this_closestD2","this_closestX","this_closestY"],"localVars":[]},"body":{"body":"{if(_inline_16_arg0_<255||_inline_16_arg1_<255||_inline_16_arg2_<255||_inline_16_arg3_<255){var _inline_16_l=_inline_16_arg4_-_inline_16_arg6_[0],_inline_16_a=_inline_16_arg5_-_inline_16_arg6_[1],_inline_16_f=_inline_16_l*_inline_16_l+_inline_16_a*_inline_16_a;_inline_16_f this.buffer.length) { - pool.free(this.buffer) - var buffer = this.buffer = pool.mallocUint8(nextPow2(r*c*4)) - for(var i=0; i oldAttribCount) { - for(i = oldAttribCount; i < newAttribCount; i++) { - this.gl.enableVertexAttribArray(i) - } - } else if(oldAttribCount > newAttribCount) { - for(i = newAttribCount; i < oldAttribCount; i++) { - this.gl.disableVertexAttribArray(i) - } - } - - this.gl.lastAttribCount = newAttribCount - - this.gl.useProgram(this.program) -} - -proto.dispose = function() { - - // disabling vertex attributes so new shader starts with zero - // and it's also useful if all shaders are disposed but the - // gl context is reused for subsequent replotting - var oldAttribCount = this.gl.lastAttribCount - for (var i = 0; i < oldAttribCount; i++) { - this.gl.disableVertexAttribArray(i) - } - this.gl.lastAttribCount = 0 - - if(this._fref) { - this._fref.dispose() - } - if(this._vref) { - this._vref.dispose() - } - this.attributes = - this.types = - this.vertShader = - this.fragShader = - this.program = - this._relink = - this._fref = - this._vref = null -} - -function compareAttributes(a, b) { - if(a.name < b.name) { - return -1 - } - return 1 -} - -//Update export hook for glslify-live -proto.update = function( - vertSource - , fragSource - , uniforms - , attributes) { - - //If only one object passed, assume glslify style output - if(!fragSource || arguments.length === 1) { - var obj = vertSource - vertSource = obj.vertex - fragSource = obj.fragment - uniforms = obj.uniforms - attributes = obj.attributes - } - - var wrapper = this - var gl = wrapper.gl - - //Compile vertex and fragment shaders - var pvref = wrapper._vref - wrapper._vref = shaderCache.shader(gl, gl.VERTEX_SHADER, vertSource) - if(pvref) { - pvref.dispose() - } - wrapper.vertShader = wrapper._vref.shader - var pfref = this._fref - wrapper._fref = shaderCache.shader(gl, gl.FRAGMENT_SHADER, fragSource) - if(pfref) { - pfref.dispose() - } - wrapper.fragShader = wrapper._fref.shader - - //If uniforms/attributes is not specified, use RT reflection - if(!uniforms || !attributes) { - - //Create initial test program - var testProgram = gl.createProgram() - gl.attachShader(testProgram, wrapper.fragShader) - gl.attachShader(testProgram, wrapper.vertShader) - gl.linkProgram(testProgram) - if(!gl.getProgramParameter(testProgram, gl.LINK_STATUS)) { - var errLog = gl.getProgramInfoLog(testProgram) - throw new GLError(errLog, 'Error linking program:' + errLog) - } - - //Load data from runtime - uniforms = uniforms || runtime.uniforms(gl, testProgram) - attributes = attributes || runtime.attributes(gl, testProgram) - - //Release test program - gl.deleteProgram(testProgram) - } - - //Sort attributes lexicographically - // overrides undefined WebGL behavior for attribute locations - attributes = attributes.slice() - attributes.sort(compareAttributes) - - //Convert attribute types, read out locations - var attributeUnpacked = [] - var attributeNames = [] - var attributeLocations = [] - var i - for(i=0; i= 0) { - var size = attr.type.charAt(attr.type.length-1)|0 - var locVector = new Array(size) - for(var j=0; j= 0) { - curLocation += 1 - } - attributeLocations[i] = curLocation - } - } - - //Rebuild program and recompute all uniform locations - var uniformLocations = new Array(uniforms.length) - function relink() { - wrapper.program = shaderCache.program( - gl - , wrapper._vref - , wrapper._fref - , attributeNames - , attributeLocations) - - for(var i=0; i= 0) { - var d = type.charCodeAt(type.length-1) - 48 - if(d < 2 || d > 4) { - throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) - } - addVectorAttribute( - gl - , wrapper - , locs[0] - , locations - , d - , obj - , name) - } else if(type.indexOf('mat') >= 0) { - var d = type.charCodeAt(type.length-1) - 48 - if(d < 2 || d > 4) { - throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) - } - addMatrixAttribute( - gl - , wrapper - , locs - , locations - , d - , obj - , name) - } else { - throw new GLError('', 'Unknown data type for attribute ' + name + ': ' + type) - } - break - } - } - return obj -} - -},{"./GLError":302}],304:[function(_dereq_,module,exports){ -'use strict' - -var coallesceUniforms = _dereq_('./reflect') -var GLError = _dereq_("./GLError") - -module.exports = createUniformWrapper - -//Binds a function and returns a value -function identity(x) { - var c = new Function('y', 'return function(){return y}') - return c(x) -} - -function makeVector(length, fill) { - var result = new Array(length) - for(var i=0; i 4) { - throw new GLError('', 'Invalid data type') - } - switch(type.charAt(0)) { - case 'b': - case 'i': - return 'gl.uniform' + d + 'iv(locations[' + index + '],obj' + path + ')' - case 'v': - return 'gl.uniform' + d + 'fv(locations[' + index + '],obj' + path + ')' - default: - throw new GLError('', 'Unrecognized data type for vector ' + name + ': ' + type) - } - } else if(type.indexOf('mat') === 0 && type.length === 4) { - var d = type.charCodeAt(type.length-1) - 48 - if(d < 2 || d > 4) { - throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type) - } - return 'gl.uniformMatrix' + d + 'fv(locations[' + index + '],false,obj' + path + ')' - } else { - throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type) - } - break - } - } - - function enumerateIndices(prefix, type) { - if(typeof type !== 'object') { - return [ [prefix, type] ] - } - var indices = [] - for(var id in type) { - var prop = type[id] - var tprefix = prefix - if(parseInt(id) + '' === id) { - tprefix += '[' + id + ']' - } else { - tprefix += '.' + id - } - if(typeof prop === 'object') { - indices.push.apply(indices, enumerateIndices(tprefix, prop)) - } else { - indices.push([tprefix, prop]) - } - } - return indices - } - - function makeSetter(type) { - var code = [ 'return function updateProperty(obj){' ] - var indices = enumerateIndices('', type) - for(var i=0; i 4) { - throw new GLError('', 'Invalid data type') - } - if(type.charAt(0) === 'b') { - return makeVector(d, false) - } - return makeVector(d, 0) - } else if(type.indexOf('mat') === 0 && type.length === 4) { - var d = type.charCodeAt(type.length-1) - 48 - if(d < 2 || d > 4) { - throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type) - } - return makeVector(d*d, 0) - } else { - throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type) - } - break - } - } - - function storeProperty(obj, prop, type) { - if(typeof type === 'object') { - var child = processObject(type) - Object.defineProperty(obj, prop, { - get: identity(child), - set: makeSetter(type), - enumerable: true, - configurable: false - }) - } else { - if(locations[type]) { - Object.defineProperty(obj, prop, { - get: makeGetter(type), - set: makeSetter(type), - enumerable: true, - configurable: false - }) - } else { - obj[prop] = defaultValue(uniforms[type].type) - } - } - } - - function processObject(obj) { - var result - if(Array.isArray(obj)) { - result = new Array(obj.length) - for(var i=0; i 1) { - if(!(x[0] in o)) { - o[x[0]] = [] - } - o = o[x[0]] - for(var k=1; k 1) { - for(var j=0; j 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the tube vertex and normal at the given index.\n//\n// The returned vertex is for a tube ring with its center at origin, radius of length(d), pointing in the direction of d.\n//\n// Each tube segment is made up of a ring of vertices.\n// These vertices are used to make up the triangles of the tube by connecting them together in the vertex array.\n// The indexes of tube segments run from 0 to 8.\n//\nvec3 getTubePosition(vec3 d, float index, out vec3 normal) {\n float segmentCount = 8.0;\n\n float angle = 2.0 * 3.14159 * (index / segmentCount);\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d);\n vec3 y = v * sin(angle) * length(d);\n vec3 v3 = x + y;\n\n normal = normalize(v3);\n\n return v3;\n}\n\nattribute vec4 vector;\nattribute vec4 color, position;\nattribute vec2 uv;\nuniform float vectorScale;\nuniform float tubeScale;\n\nuniform mat4 model\n , view\n , projection\n , inverseModel;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n // Scale the vector magnitude to stay constant with\n // model & view changes.\n vec3 normal;\n vec3 XYZ = getTubePosition(mat3(model) * (tubeScale * vector.w * normalize(vector.xyz)), position.w, normal);\n vec4 tubePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n\n //Lighting geometry parameters\n vec4 cameraCoordinate = view * tubePosition;\n cameraCoordinate.xyz /= cameraCoordinate.w;\n f_lightDirection = lightPosition - cameraCoordinate.xyz;\n f_eyeDirection = eyePosition - cameraCoordinate.xyz;\n f_normal = normalize((vec4(normal,0.0) * inverseModel).xyz);\n\n // vec4 m_position = model * vec4(tubePosition, 1.0);\n vec4 t_position = view * tubePosition;\n gl_Position = projection * t_position;\n\n f_color = color;\n f_data = tubePosition.xyz;\n f_position = position.xyz;\n f_uv = uv;\n}\n"]) -var triFragSrc = glslify(["#extension GL_OES_standard_derivatives : enable\n\nprecision highp float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data\n , f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = min(1.0, max(0.0, cookTorranceSpecular(L, V, N, roughness, fresnel)));\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = f_color * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}\n"]) -var pickVertSrc = glslify(["precision highp float;\n\nprecision highp float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the tube vertex and normal at the given index.\n//\n// The returned vertex is for a tube ring with its center at origin, radius of length(d), pointing in the direction of d.\n//\n// Each tube segment is made up of a ring of vertices.\n// These vertices are used to make up the triangles of the tube by connecting them together in the vertex array.\n// The indexes of tube segments run from 0 to 8.\n//\nvec3 getTubePosition(vec3 d, float index, out vec3 normal) {\n float segmentCount = 8.0;\n\n float angle = 2.0 * 3.14159 * (index / segmentCount);\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d);\n vec3 y = v * sin(angle) * length(d);\n vec3 v3 = x + y;\n\n normal = normalize(v3);\n\n return v3;\n}\n\nattribute vec4 vector;\nattribute vec4 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform float tubeScale;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n vec3 normal;\n vec3 XYZ = getTubePosition(mat3(model) * (tubeScale * vector.w * normalize(vector.xyz)), position.w, normal);\n vec4 tubePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n\n gl_Position = projection * view * tubePosition;\n f_id = id;\n f_position = position.xyz;\n}\n"]) -var pickFragSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]) - -exports.meshShader = { - vertex: triVertSrc, - fragment: triFragSrc, - attributes: [ - {name: 'position', type: 'vec4'}, - {name: 'normal', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'uv', type: 'vec2'}, - {name: 'vector', type: 'vec4'} - ] -} -exports.pickShader = { - vertex: pickVertSrc, - fragment: pickFragSrc, - attributes: [ - {name: 'position', type: 'vec4'}, - {name: 'id', type: 'vec4'}, - {name: 'vector', type: 'vec4'} - ] -} - -},{"glslify":409}],312:[function(_dereq_,module,exports){ -'use strict' - -var DEFAULT_VERTEX_NORMALS_EPSILON = 1e-6; // may be too large if triangles are very small -var DEFAULT_FACE_NORMALS_EPSILON = 1e-6; - -var createShader = _dereq_('gl-shader') -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') -var createTexture = _dereq_('gl-texture2d') -var normals = _dereq_('normals') -var multiply = _dereq_('gl-mat4/multiply') -var invert = _dereq_('gl-mat4/invert') -var ndarray = _dereq_('ndarray') -var colormap = _dereq_('colormap') -var getContour = _dereq_('simplicial-complex-contour') -var pool = _dereq_('typedarray-pool') -var shaders = _dereq_('./shaders') - -var meshShader = shaders.meshShader -var pickShader = shaders.pickShader - -var IDENTITY = [ - 1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1] - -function SimplicialMesh(gl - , texture - , triShader - , pickShader - , trianglePositions - , triangleVectors - , triangleIds - , triangleColors - , triangleUVs - , triangleNormals - , triangleVAO - , edgePositions - , edgeIds - , edgeColors - , edgeUVs - , edgeVAO - , pointPositions - , pointIds - , pointColors - , pointUVs - , pointSizes - , pointVAO - , contourPositions - , contourVAO) { - - this.gl = gl - this.cells = [] - this.positions = [] - this.intensity = [] - this.texture = texture - this.dirty = true - - this.triShader = triShader - this.pickShader = pickShader - - this.trianglePositions = trianglePositions - this.triangleVectors = triangleVectors - this.triangleColors = triangleColors - this.triangleNormals = triangleNormals - this.triangleUVs = triangleUVs - this.triangleIds = triangleIds - this.triangleVAO = triangleVAO - this.triangleCount = 0 - - this.lineWidth = 1 - this.edgePositions = edgePositions - this.edgeColors = edgeColors - this.edgeUVs = edgeUVs - this.edgeIds = edgeIds - this.edgeVAO = edgeVAO - this.edgeCount = 0 - - this.pointPositions = pointPositions - this.pointColors = pointColors - this.pointUVs = pointUVs - this.pointSizes = pointSizes - this.pointIds = pointIds - this.pointVAO = pointVAO - this.pointCount = 0 - - this.contourLineWidth = 1 - this.contourPositions = contourPositions - this.contourVAO = contourVAO - this.contourCount = 0 - this.contourColor = [0,0,0] - this.contourEnable = false - - this.pickId = 1 - this.bounds = [ - [ Infinity, Infinity, Infinity], - [-Infinity,-Infinity,-Infinity] ] - this.clipBounds = [ - [-Infinity,-Infinity,-Infinity], - [ Infinity, Infinity, Infinity] ] - - this.lightPosition = [1e5, 1e5, 0] - this.ambientLight = 0.8 - this.diffuseLight = 0.8 - this.specularLight = 2.0 - this.roughness = 0.5 - this.fresnel = 1.5 - - this.opacity = 1.0 - - this.tubeScale = 1.0 - - this._model = IDENTITY - this._view = IDENTITY - this._projection = IDENTITY - this._resolution = [1,1] - this.pixelRatio = 1 -} - -var proto = SimplicialMesh.prototype - -proto.isOpaque = function() { - return this.opacity >= 1 -} - -proto.isTransparent = function() { - return this.opacity < 1 -} - -proto.pickSlots = 1 - -proto.setPickBase = function(id) { - this.pickId = id -} - -function genColormap(param) { - var colors = colormap({ - colormap: param - , nshades: 256 - , format: 'rgba' - }) - - var result = new Uint8Array(256*4) - for(var i=0; i<256; ++i) { - var c = colors[i] - for(var j=0; j<3; ++j) { - result[4*i+j] = c[j] - } - result[4*i+3] = c[3]*255 - } - - return ndarray(result, [256,256,4], [4,0,1]) -} - -function unpackIntensity(cells, numVerts, cellIntensity) { - var result = new Array(numVerts) - for(var i=0; i 0) { - var shader = this.triShader - shader.bind() - shader.uniforms = uniforms - - this.triangleVAO.bind() - gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) - this.triangleVAO.unbind() - } -} - -proto.drawPick = function(params) { - params = params || {} - - var gl = this.gl - - var model = params.model || IDENTITY - var view = params.view || IDENTITY - var projection = params.projection || IDENTITY - - var clipBounds = [[-1e6,-1e6,-1e6],[1e6,1e6,1e6]] - for(var i=0; i<3; ++i) { - clipBounds[0][i] = Math.max(clipBounds[0][i], this.clipBounds[0][i]) - clipBounds[1][i] = Math.min(clipBounds[1][i], this.clipBounds[1][i]) - } - - //Save camera parameters - this._model = [].slice.call(model) - this._view = [].slice.call(view) - this._projection = [].slice.call(projection) - this._resolution = [gl.drawingBufferWidth, gl.drawingBufferHeight] - - var uniforms = { - model: model, - view: view, - projection: projection, - clipBounds: clipBounds, - - tubeScale: this.tubeScale, - - pickId: this.pickId / 255.0, - } - - var shader = this.pickShader - shader.bind() - shader.uniforms = uniforms - - if(this.triangleCount > 0) { - this.triangleVAO.bind() - gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) - this.triangleVAO.unbind() - } - - if(this.edgeCount > 0) { - this.edgeVAO.bind() - gl.lineWidth(this.lineWidth * this.pixelRatio) - gl.drawArrays(gl.LINES, 0, this.edgeCount*2) - this.edgeVAO.unbind() - } - -} - - -proto.pick = function(pickData) { - if(!pickData) { - return null - } - if(pickData.id !== this.pickId) { - return null - } - - var cellId = pickData.value[0] + 256*pickData.value[1] + 65536*pickData.value[2] - var cell = this.cells[cellId] - - var pos = this.positions[cell[1]].slice(0, 3) - var intensity = this.intensity[cell[1]] - var velocity = this.vectors[cell[1]].slice(0, 3) - var divergence = this.vectors[cell[1]][3] - - return { - index: cellId, - position: pos, - intensity: intensity, - velocity: velocity, - divergence: divergence, - dataCoordinate: pos - } -} - - -proto.dispose = function() { - this.texture.dispose() - - this.triShader.dispose() - this.pickShader.dispose() - - this.triangleVAO.dispose() - this.trianglePositions.dispose() - this.triangleVectors.dispose() - this.triangleColors.dispose() - this.triangleUVs.dispose() - this.triangleNormals.dispose() - this.triangleIds.dispose() - - this.edgeVAO.dispose() - this.edgePositions.dispose() - this.edgeColors.dispose() - this.edgeUVs.dispose() - this.edgeIds.dispose() - - this.pointVAO.dispose() - this.pointPositions.dispose() - this.pointColors.dispose() - this.pointUVs.dispose() - this.pointSizes.dispose() - this.pointIds.dispose() - - this.contourVAO.dispose() - this.contourPositions.dispose() -} - -function createMeshShader(gl) { - var shader = createShader(gl, meshShader.vertex, meshShader.fragment, null, meshShader.attributes) - shader.attributes.position.location = 0 - shader.attributes.color.location = 2 - shader.attributes.uv.location = 3 - shader.attributes.vector.location = 5 - return shader -} - - -function createPickShader(gl) { - var shader = createShader(gl, pickShader.vertex, pickShader.fragment, null, pickShader.attributes) - shader.attributes.position.location = 0 - shader.attributes.id.location = 1 - shader.attributes.vector.location = 5 - return shader -} - - -function createSimplicialMesh(gl, params) { - if (arguments.length === 1) { - params = gl; - gl = params.gl; - } - - var triShader = params.triShader || createMeshShader(gl) - var pickShader = createPickShader(gl) - - var meshTexture = createTexture(gl, - ndarray(new Uint8Array([255,255,255,255]), [1,1,4])) - meshTexture.generateMipmap() - meshTexture.minFilter = gl.LINEAR_MIPMAP_LINEAR - meshTexture.magFilter = gl.LINEAR - - var trianglePositions = createBuffer(gl) - var triangleVectors = createBuffer(gl) - var triangleColors = createBuffer(gl) - var triangleUVs = createBuffer(gl) - var triangleNormals = createBuffer(gl) - var triangleIds = createBuffer(gl) - var triangleVAO = createVAO(gl, [ - { buffer: trianglePositions, - type: gl.FLOAT, - size: 4 - }, - { buffer: triangleIds, - type: gl.UNSIGNED_BYTE, - size: 4, - normalized: true - }, - { buffer: triangleColors, - type: gl.FLOAT, - size: 4 - }, - { buffer: triangleUVs, - type: gl.FLOAT, - size: 2 - }, - { buffer: triangleNormals, - type: gl.FLOAT, - size: 3 - }, - { buffer: triangleVectors, - type: gl.FLOAT, - size: 4 - } - ]) - - var edgePositions = createBuffer(gl) - var edgeColors = createBuffer(gl) - var edgeUVs = createBuffer(gl) - var edgeIds = createBuffer(gl) - var edgeVAO = createVAO(gl, [ - { buffer: edgePositions, - type: gl.FLOAT, - size: 3 - }, - { buffer: edgeIds, - type: gl.UNSIGNED_BYTE, - size: 4, - normalized: true - }, - { buffer: edgeColors, - type: gl.FLOAT, - size: 4 - }, - { buffer: edgeUVs, - type: gl.FLOAT, - size: 2 - } - ]) - - var pointPositions = createBuffer(gl) - var pointColors = createBuffer(gl) - var pointUVs = createBuffer(gl) - var pointSizes = createBuffer(gl) - var pointIds = createBuffer(gl) - var pointVAO = createVAO(gl, [ - { buffer: pointPositions, - type: gl.FLOAT, - size: 3 - }, - { buffer: pointIds, - type: gl.UNSIGNED_BYTE, - size: 4, - normalized: true - }, - { buffer: pointColors, - type: gl.FLOAT, - size: 4 - }, - { buffer: pointUVs, - type: gl.FLOAT, - size: 2 - }, - { buffer: pointSizes, - type: gl.FLOAT, - size: 1 - } - ]) - - var contourPositions = createBuffer(gl) - var contourVAO = createVAO(gl, [ - { buffer: contourPositions, - type: gl.FLOAT, - size: 3 - }]) - - var mesh = new SimplicialMesh(gl - , meshTexture - , triShader - , pickShader - , trianglePositions - , triangleVectors - , triangleIds - , triangleColors - , triangleUVs - , triangleNormals - , triangleVAO - , edgePositions - , edgeIds - , edgeColors - , edgeUVs - , edgeVAO - , pointPositions - , pointIds - , pointColors - , pointUVs - , pointSizes - , pointVAO - , contourPositions - , contourVAO) - - mesh.update(params) - - return mesh -} - -module.exports = createSimplicialMesh - -},{"./shaders":311,"colormap":126,"gl-buffer":241,"gl-mat4/invert":265,"gl-mat4/multiply":267,"gl-shader":301,"gl-texture2d":322,"gl-vao":327,"ndarray":450,"normals":453,"simplicial-complex-contour":518,"typedarray-pool":545}],313:[function(_dereq_,module,exports){ -"use strict"; - -var vec3 = _dereq_('gl-vec3'); -var vec4 = _dereq_('gl-vec4'); - -var streamToTube = function(stream, maxDivergence, minDistance, maxNorm) { - var points = stream.points; - var velocities = stream.velocities; - var divergences = stream.divergences; - - var p, fwd, r, u, v, up; - up = vec3.set(vec3.create(), 0, 1, 0); - u = vec3.create(); - v = vec3.create(); - var p2 = vec3.create(); - - var verts = []; - var faces = []; - var vectors = []; - var previousVerts = []; - var currentVerts = []; - var intensities = []; - var previousIntensity = 0; - var currentIntensity = 0; - var currentVector = vec4.create(); - var previousVector = vec4.create(); - - var facets = 8; - - for (var i = 0; i < points.length; i++) { - p = points[i]; - fwd = velocities[i]; - r = divergences[i]; - if (maxDivergence === 0) { - r = minDistance * 0.05; - } - currentIntensity = vec3.length(fwd) / maxNorm; - currentVector = vec4.create(); - vec3.copy(currentVector, fwd); - currentVector[3] = r; - - for (var a = 0; a < facets; a++) { - currentVerts[a] = [p[0], p[1], p[2], a]; - } - if (previousVerts.length > 0) { - for (var a = 0; a < facets; a++) { - var a1 = (a+1) % facets; - verts.push( - previousVerts[a], - currentVerts[a], - currentVerts[a1], - - currentVerts[a1], - previousVerts[a1], - previousVerts[a] - ); - vectors.push( - previousVector, - currentVector, - currentVector, - - currentVector, - previousVector, - previousVector - ); - intensities.push( - previousIntensity, - currentIntensity, - currentIntensity, - - currentIntensity, - previousIntensity, - previousIntensity - ); - faces.push( - [verts.length-6, verts.length-5, verts.length-4], - [verts.length-3, verts.length-2, verts.length-1] - ); - } - } - var tmp = previousVerts; - previousVerts = currentVerts; - currentVerts = tmp; - tmp = previousVector; - previousVector = currentVector; - currentVector = tmp; - tmp = previousIntensity; - previousIntensity = currentIntensity; - currentIntensity = tmp; - } - return { - positions: verts, - cells: faces, - vectors: vectors, - vertexIntensity: intensities - }; - -}; - -var createTubes = function(streams, colormap, maxDivergence, minDistance) { - - var maxNorm = 0; - for (var i=0; i maxNorm) { - maxNorm = norm; - } - } - } - - var tubes = streams.map(function(s) { - return streamToTube(s, maxDivergence, minDistance, maxNorm); - }); - - var positions = []; - var cells = []; - var vectors = []; - var vertexIntensity = []; - for (var i=0; i < tubes.length; i++) { - var tube = tubes[i]; - var offset = positions.length; - positions = positions.concat(tube.positions); - vectors = vectors.concat(tube.vectors); - vertexIntensity = vertexIntensity.concat(tube.vertexIntensity); - for (var j=0; j v) return i-1; - } - return i; -}; - -var tmp = vec3.create(); -var tmp2 = vec3.create(); - -var clamp = function(v, min, max) { - return v < min ? min : (v > max ? max : v); -}; - -var sampleMeshgrid = function(point, array, meshgrid, clampOverflow) { - var x = point[0]; - var y = point[1]; - var z = point[2]; - - var w = meshgrid[0].length; - var h = meshgrid[1].length; - var d = meshgrid[2].length; - - // Find the index of the nearest smaller value in the meshgrid for each coordinate of (x,y,z). - // The nearest smaller value index for x is the index x0 such that - // meshgrid[0][x0] < x and for all x1 > x0, meshgrid[0][x1] >= x. - var x0 = findLastSmallerIndex(meshgrid[0], x); - var y0 = findLastSmallerIndex(meshgrid[1], y); - var z0 = findLastSmallerIndex(meshgrid[2], z); - - // Get the nearest larger meshgrid value indices. - // From the above "nearest smaller value", we know that - // meshgrid[0][x0] < x - // meshgrid[0][x0+1] >= x - var x1 = x0 + 1; - var y1 = y0 + 1; - var z1 = z0 + 1; - - if (meshgrid[0][x0] === x) x1 = x0; - if (meshgrid[1][y0] === y) y1 = y0; - if (meshgrid[2][z0] === z) z1 = z0; - - if (clampOverflow) { - x0 = clamp(x0, 0, w-1); - x1 = clamp(x1, 0, w-1); - y0 = clamp(y0, 0, h-1); - y1 = clamp(y1, 0, h-1); - z0 = clamp(z0, 0, d-1); - z1 = clamp(z1, 0, d-1); - } - - // Reject points outside the meshgrid, return a zero vector. - if (x0 < 0 || y0 < 0 || z0 < 0 || x1 >= w || y1 >= h || z1 >= d) { - return vec3.create(); - } - - // Normalize point coordinates to 0..1 scaling factor between x0 and x1. - var xf = (x - meshgrid[0][x0]) / (meshgrid[0][x1] - meshgrid[0][x0]); - var yf = (y - meshgrid[1][y0]) / (meshgrid[1][y1] - meshgrid[1][y0]); - var zf = (z - meshgrid[2][z0]) / (meshgrid[2][z1] - meshgrid[2][z0]); - - if (xf < 0 || xf > 1 || isNaN(xf)) xf = 0; - if (yf < 0 || yf > 1 || isNaN(yf)) yf = 0; - if (zf < 0 || zf > 1 || isNaN(zf)) zf = 0; - - var z0off = z0*w*h; - var z1off = z1*w*h; - - var y0off = y0*w; - var y1off = y1*w; - - var x0off = x0; - var x1off = x1; - - // Sample data array around the (x,y,z) point. - // vZYX = array[zZoff + yYoff + xXoff] - var v000 = array[y0off + z0off + x0off]; - var v001 = array[y0off + z0off + x1off]; - var v010 = array[y1off + z0off + x0off]; - var v011 = array[y1off + z0off + x1off]; - var v100 = array[y0off + z1off + x0off]; - var v101 = array[y0off + z1off + x1off]; - var v110 = array[y1off + z1off + x0off]; - var v111 = array[y1off + z1off + x1off]; - - var result = vec3.create(); - - // Average samples according to distance to point. - vec3.lerp(result, v000, v001, xf); - vec3.lerp(tmp, v010, v011, xf); - vec3.lerp(result, result, tmp, yf); - vec3.lerp(tmp, v100, v101, xf); - vec3.lerp(tmp2, v110, v111, xf); - vec3.lerp(tmp, tmp, tmp2, yf); - vec3.lerp(result, result, tmp, zf); - - return result; -}; - - -var vabs = function(dst, v) { - var x = v[0]; - var y = v[1]; - var z = v[2]; - dst[0] = x >= 0 ? x : -x; - dst[1] = y >= 0 ? y : -y; - dst[2] = z >= 0 ? z : -z; - return dst; -}; - -var findMinSeparation = function(xs) { - var minSeparation = 1/0; - xs.sort(function(a, b) { return a - b; }); - for (var i=1; i= minX && x <= maxX && - y >= minY && y <= maxY && - z >= minZ && z <= maxZ - ); - }; - - var boundsSize = vec3.distance(bounds[0], bounds[1]); - var maxStepSize = 10 * boundsSize / maxLength; - var maxStepSizeSq = maxStepSize * maxStepSize; - - var minDistance = 1; - var maxDivergence = 0; // For component-wise divergence vec3.create(); - var tmp = vec3.create(); - - if (positions.length >= 2) { - minDistance = calculateMinPositionDistance(positions); - } - - for (var i = 0; i < positions.length; i++) { - var p = vec3.create(); - vec3.copy(p, positions[i]); - - var stream = [p]; - var velocities = []; - var v = vectorField.getVelocity(p); - var op = p; - velocities.push(v); - - var divergences = []; - - var dv = vectorField.getDivergence(p, v); - var dvLength = vec3.length(dv); - if (dvLength > maxDivergence && !isNaN(dvLength) && isFinite(dvLength)) { - maxDivergence = dvLength; - } - // In case we need to do component-wise divergence visualization - // vec3.max(maxDivergence, maxDivergence, vabs(tmp, dv)); - divergences.push(dvLength); - - streams.push({points: stream, velocities: velocities, divergences: divergences}); - - var j = 0; - - while (j < maxLength * 100 && stream.length < maxLength && inBounds(bounds, p)) { - j++; - var np = vec3.clone(v); - var sqLen = vec3.squaredLength(np); - if (sqLen === 0) { - break; - } else if (sqLen > maxStepSizeSq) { - vec3.scale(np, np, maxStepSize / Math.sqrt(sqLen)); - } - vec3.add(np, np, p); - - v = vectorField.getVelocity(np); - - if (vec3.squaredDistance(op, np) - maxStepSizeSq > -0.0001 * maxStepSizeSq) { - stream.push(np); - op = np; - velocities.push(v); - var dv = vectorField.getDivergence(np, v); - var dvLength = vec3.length(dv); - if (dvLength > maxDivergence && !isNaN(dvLength) && isFinite(dvLength)) { - maxDivergence = dvLength; - } - // In case we need to do component-wise divergence visualization - //vec3.max(maxDivergence, maxDivergence, vabs(tmp, dv)); - divergences.push(dvLength); - } - - p = np; - } - } - - // Replace NaNs and Infinities with non-NaN, finite maxDivergence - for (var i=0; i max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 lowerBound, upperBound;\nuniform float contourTint;\nuniform vec4 contourColor;\nuniform sampler2D colormap;\nuniform vec3 clipBounds[2];\nuniform float roughness, fresnel, kambient, kdiffuse, kspecular, opacity;\nuniform float vertexColor;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec3 lightDirection, eyeDirection, surfaceNormal;\nvarying vec4 vColor;\n\nvoid main() {\n if ((kill > 0.0) ||\n (outOfRange(clipBounds[0], clipBounds[1], worldCoordinate))) discard;\n\n vec3 N = normalize(surfaceNormal);\n vec3 V = normalize(eyeDirection);\n vec3 L = normalize(lightDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = max(beckmannSpecular(L, V, N, roughness), 0.);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n //decide how to interpolate color — in vertex or in fragment\n vec4 surfaceColor =\n step(vertexColor, .5) * texture2D(colormap, vec2(value, value)) +\n step(.5, vertexColor) * vColor;\n\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = mix(litColor, contourColor, contourTint) * opacity;\n}\n"]) -var contourVertSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec4 uv;\nattribute float f;\n\nuniform vec3 objectOffset;\nuniform mat3 permutation;\nuniform mat4 model, view, projection;\nuniform float height, zOffset;\nuniform sampler2D colormap;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec2 planeCoordinate;\nvarying vec3 lightDirection, eyeDirection, surfaceNormal;\nvarying vec4 vColor;\n\nvoid main() {\n vec3 dataCoordinate = permutation * vec3(uv.xy, height);\n worldCoordinate = objectOffset + dataCoordinate;\n vec4 worldPosition = model * vec4(worldCoordinate, 1.0);\n\n vec4 clipPosition = projection * view * worldPosition;\n clipPosition.z += zOffset;\n\n gl_Position = clipPosition;\n value = f + objectOffset.z;\n kill = -1.0;\n planeCoordinate = uv.zw;\n\n vColor = texture2D(colormap, vec2(value, value));\n\n //Don't do lighting for contours\n surfaceNormal = vec3(1,0,0);\n eyeDirection = vec3(0,1,0);\n lightDirection = vec3(0,0,1);\n}\n"]) -var pickSrc = glslify(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec2 shape;\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec2 planeCoordinate;\nvarying vec3 surfaceNormal;\n\nvec2 splitFloat(float v) {\n float vh = 255.0 * v;\n float upper = floor(vh);\n float lower = fract(vh);\n return vec2(upper / 255.0, floor(lower * 16.0) / 16.0);\n}\n\nvoid main() {\n if ((kill > 0.0) ||\n (outOfRange(clipBounds[0], clipBounds[1], worldCoordinate))) discard;\n\n vec2 ux = splitFloat(planeCoordinate.x / shape.x);\n vec2 uy = splitFloat(planeCoordinate.y / shape.y);\n gl_FragColor = vec4(pickId, ux.x, uy.x, ux.y + (uy.y/16.0));\n}\n"]) - -exports.createShader = function (gl) { - var shader = createShader(gl, vertSrc, fragSrc, null, [ - {name: 'uv', type: 'vec4'}, - {name: 'f', type: 'vec3'}, - {name: 'normal', type: 'vec3'} - ]) - shader.attributes.uv.location = 0 - shader.attributes.f.location = 1 - shader.attributes.normal.location = 2 - return shader -} -exports.createPickShader = function (gl) { - var shader = createShader(gl, vertSrc, pickSrc, null, [ - {name: 'uv', type: 'vec4'}, - {name: 'f', type: 'vec3'}, - {name: 'normal', type: 'vec3'} - ]) - shader.attributes.uv.location = 0 - shader.attributes.f.location = 1 - shader.attributes.normal.location = 2 - return shader -} -exports.createContourShader = function (gl) { - var shader = createShader(gl, contourVertSrc, fragSrc, null, [ - {name: 'uv', type: 'vec4'}, - {name: 'f', type: 'float'} - ]) - shader.attributes.uv.location = 0 - shader.attributes.f.location = 1 - return shader -} -exports.createPickContourShader = function (gl) { - var shader = createShader(gl, contourVertSrc, pickSrc, null, [ - {name: 'uv', type: 'vec4'}, - {name: 'f', type: 'float'} - ]) - shader.attributes.uv.location = 0 - shader.attributes.f.location = 1 - return shader -} - -},{"gl-shader":301,"glslify":409}],315:[function(_dereq_,module,exports){ -arguments[4][111][0].apply(exports,arguments) -},{"dup":111}],316:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createSurfacePlot - -var bits = _dereq_('bit-twiddle') -var createBuffer = _dereq_('gl-buffer') -var createVAO = _dereq_('gl-vao') -var createTexture = _dereq_('gl-texture2d') -var pool = _dereq_('typedarray-pool') -var colormap = _dereq_('colormap') -var ops = _dereq_('ndarray-ops') -var pack = _dereq_('ndarray-pack') -var ndarray = _dereq_('ndarray') -var surfaceNets = _dereq_('surface-nets') -var multiply = _dereq_('gl-mat4/multiply') -var invert = _dereq_('gl-mat4/invert') -var bsearch = _dereq_('binary-search-bounds') -var gradient = _dereq_('ndarray-gradient') -var shaders = _dereq_('./lib/shaders') - -var createShader = shaders.createShader -var createContourShader = shaders.createContourShader -var createPickShader = shaders.createPickShader -var createPickContourShader = shaders.createPickContourShader - -var SURFACE_VERTEX_SIZE = 4 * (4 + 3 + 3) - -var IDENTITY = [ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 ] - -var QUAD = [ - [0, 0], - [0, 1], - [1, 0], - [1, 1], - [1, 0], - [0, 1] -] - -var PERMUTATIONS = [ - [0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0] -] - -;(function () { - for (var i = 0; i < 3; ++i) { - var p = PERMUTATIONS[i] - var u = (i + 1) % 3 - var v = (i + 2) % 3 - p[u + 0] = 1 - p[v + 3] = 1 - p[i + 6] = 1 - } -})() - -function SurfacePickResult (position, index, uv, level, dataCoordinate) { - this.position = position - this.index = index - this.uv = uv - this.level = level - this.dataCoordinate = dataCoordinate -} - -var N_COLORS = 256 - -function genColormap (name) { - var x = pack([colormap({ - colormap: name, - nshades: N_COLORS, - format: 'rgba' - }).map(function (c) { - return [c[0], c[1], c[2], 255 * c[3]] - })]) - ops.divseq(x, 255.0) - return x -} - -function SurfacePlot ( - gl, - shape, - bounds, - shader, - pickShader, - coordinates, - vao, - colorMap, - contourShader, - contourPickShader, - contourBuffer, - contourVAO, - dynamicBuffer, - dynamicVAO, - objectOffset) { - this.gl = gl - this.shape = shape - this.bounds = bounds - this.objectOffset = objectOffset - this.intensityBounds = [] - - this._shader = shader - this._pickShader = pickShader - this._coordinateBuffer = coordinates - this._vao = vao - this._colorMap = colorMap - - this._contourShader = contourShader - this._contourPickShader = contourPickShader - this._contourBuffer = contourBuffer - this._contourVAO = contourVAO - this._contourOffsets = [[], [], []] - this._contourCounts = [[], [], []] - this._vertexCount = 0 - - this._pickResult = new SurfacePickResult([0, 0, 0], [0, 0], [0, 0], [0, 0, 0], [0, 0, 0]) - - this._dynamicBuffer = dynamicBuffer - this._dynamicVAO = dynamicVAO - this._dynamicOffsets = [0, 0, 0] - this._dynamicCounts = [0, 0, 0] - - this.contourWidth = [ 1, 1, 1 ] - this.contourLevels = [[1], [1], [1]] - this.contourTint = [0, 0, 0] - this.contourColor = [[0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 1]] - - this.showContour = true - this.showSurface = true - - this.enableHighlight = [true, true, true] - this.highlightColor = [[0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1]] - this.highlightTint = [ 1, 1, 1 ] - this.highlightLevel = [-1, -1, -1] - - // Dynamic contour options - this.enableDynamic = [ true, true, true ] - this.dynamicLevel = [ NaN, NaN, NaN ] - this.dynamicColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ] - this.dynamicTint = [ 1, 1, 1 ] - this.dynamicWidth = [ 1, 1, 1 ] - - this.axesBounds = [[Infinity, Infinity, Infinity], [-Infinity, -Infinity, -Infinity]] - this.surfaceProject = [ false, false, false ] - this.contourProject = [[ false, false, false ], - [ false, false, false ], - [ false, false, false ]] - - this.colorBounds = [ false, false ] - - // Store xyz fields, need this for picking - this._field = [ - ndarray(pool.mallocFloat(1024), [0, 0]), - ndarray(pool.mallocFloat(1024), [0, 0]), - ndarray(pool.mallocFloat(1024), [0, 0]) ] - - this.pickId = 1 - this.clipBounds = [[-Infinity, -Infinity, -Infinity], [Infinity, Infinity, Infinity]] - - this.snapToData = false - - this.pixelRatio = 1 - - this.opacity = 1.0 - - this.lightPosition = [10, 10000, 0] - this.ambientLight = 0.8 - this.diffuseLight = 0.8 - this.specularLight = 2.0 - this.roughness = 0.5 - this.fresnel = 1.5 - this.vertexColor = 0 - - this.dirty = true -} - -var proto = SurfacePlot.prototype - -proto.isTransparent = function () { - return this.opacity < 1 -} - -proto.isOpaque = function () { - if (this.opacity >= 1) { - return true - } - for (var i = 0; i < 3; ++i) { - if (this._contourCounts[i].length > 0 || this._dynamicCounts[i] > 0) { - return true - } - } - return false -} - -proto.pickSlots = 1 - -proto.setPickBase = function (id) { - this.pickId = id -} - -var ZERO_VEC = [0, 0, 0] - -var PROJECT_DATA = { - showSurface: false, - showContour: false, - projections: [IDENTITY.slice(), IDENTITY.slice(), IDENTITY.slice()], - clipBounds: [ - [[0, 0, 0], [0, 0, 0]], - [[0, 0, 0], [0, 0, 0]], - [[0, 0, 0], [0, 0, 0]]] -} - -function computeProjectionData (camera, obj) { - var i, j, k - - // Compute cube properties - var cubeAxis = (obj.axes && obj.axes.lastCubeProps.axis) || ZERO_VEC - - var showSurface = obj.showSurface - var showContour = obj.showContour - - for (i = 0; i < 3; ++i) { - showSurface = showSurface || obj.surfaceProject[i] - for (j = 0; j < 3; ++j) { - showContour = showContour || obj.contourProject[i][j] - } - } - - for (i = 0; i < 3; ++i) { - // Construct projection onto axis - var axisSquish = PROJECT_DATA.projections[i] - for (j = 0; j < 16; ++j) { - axisSquish[j] = 0 - } - for (j = 0; j < 4; ++j) { - axisSquish[5 * j] = 1 - } - axisSquish[5 * i] = 0 - axisSquish[12 + i] = obj.axesBounds[+(cubeAxis[i] > 0)][i] - multiply(axisSquish, camera.model, axisSquish) - - var nclipBounds = PROJECT_DATA.clipBounds[i] - for (k = 0; k < 2; ++k) { - for (j = 0; j < 3; ++j) { - nclipBounds[k][j] = camera.clipBounds[k][j] - } - } - nclipBounds[0][i] = -1e8 - nclipBounds[1][i] = 1e8 - } - - PROJECT_DATA.showSurface = showSurface - PROJECT_DATA.showContour = showContour - - return PROJECT_DATA -} - -var UNIFORMS = { - model: IDENTITY, - view: IDENTITY, - projection: IDENTITY, - inverseModel: IDENTITY.slice(), - lowerBound: [0, 0, 0], - upperBound: [0, 0, 0], - colorMap: 0, - clipBounds: [[0, 0, 0], [0, 0, 0]], - height: 0.0, - contourTint: 0, - contourColor: [0, 0, 0, 1], - permutation: [1, 0, 0, 0, 1, 0, 0, 0, 1], - zOffset: -1e-4, - objectOffset: [0, 0, 0], - kambient: 1, - kdiffuse: 1, - kspecular: 1, - lightPosition: [1000, 1000, 1000], - eyePosition: [0, 0, 0], - roughness: 1, - fresnel: 1, - opacity: 1, - vertexColor: 0 -} - -var MATRIX_INVERSE = IDENTITY.slice() -var DEFAULT_PERM = [1, 0, 0, 0, 1, 0, 0, 0, 1] - -function drawCore (params, transparent) { - params = params || {} - var gl = this.gl - - gl.disable(gl.CULL_FACE) - - this._colorMap.bind(0) - - var uniforms = UNIFORMS - uniforms.model = params.model || IDENTITY - uniforms.view = params.view || IDENTITY - uniforms.projection = params.projection || IDENTITY - uniforms.lowerBound = [this.bounds[0][0], this.bounds[0][1], this.colorBounds[0] || this.bounds[0][2]] - uniforms.upperBound = [this.bounds[1][0], this.bounds[1][1], this.colorBounds[1] || this.bounds[1][2]] - uniforms.objectOffset = this.objectOffset - uniforms.contourColor = this.contourColor[0] - - uniforms.inverseModel = invert(uniforms.inverseModel, uniforms.model) - - for (var i = 0; i < 2; ++i) { - var clipClamped = uniforms.clipBounds[i] - for (var j = 0; j < 3; ++j) { - clipClamped[j] = Math.min(Math.max(this.clipBounds[i][j], -1e8), 1e8) - } - } - - uniforms.kambient = this.ambientLight - uniforms.kdiffuse = this.diffuseLight - uniforms.kspecular = this.specularLight - - uniforms.roughness = this.roughness - uniforms.fresnel = this.fresnel - uniforms.opacity = this.opacity - - uniforms.height = 0.0 - uniforms.permutation = DEFAULT_PERM - - uniforms.vertexColor = this.vertexColor - - // Compute camera matrix inverse - var invCameraMatrix = MATRIX_INVERSE - multiply(invCameraMatrix, uniforms.view, uniforms.model) - multiply(invCameraMatrix, uniforms.projection, invCameraMatrix) - invert(invCameraMatrix, invCameraMatrix) - - for (i = 0; i < 3; ++i) { - uniforms.eyePosition[i] = invCameraMatrix[12 + i] / invCameraMatrix[15] - } - - var w = invCameraMatrix[15] - for (i = 0; i < 3; ++i) { - w += this.lightPosition[i] * invCameraMatrix[4 * i + 3] - } - for (i = 0; i < 3; ++i) { - var s = invCameraMatrix[12 + i] - for (j = 0; j < 3; ++j) { - s += invCameraMatrix[4 * j + i] * this.lightPosition[j] - } - uniforms.lightPosition[i] = s / w - } - - var projectData = computeProjectionData(uniforms, this) - - if (projectData.showSurface && (transparent === (this.opacity < 1))) { - // Set up uniforms - this._shader.bind() - this._shader.uniforms = uniforms - - // Draw it - this._vao.bind() - - if (this.showSurface && this._vertexCount) { - this._vao.draw(gl.TRIANGLES, this._vertexCount) - } - - // Draw projections of surface - for (i = 0; i < 3; ++i) { - if (!this.surfaceProject[i] || !this.vertexCount) { - continue - } - this._shader.uniforms.model = projectData.projections[i] - this._shader.uniforms.clipBounds = projectData.clipBounds[i] - this._vao.draw(gl.TRIANGLES, this._vertexCount) - } - - this._vao.unbind() - } - - if (projectData.showContour && !transparent) { - var shader = this._contourShader - - // Don't apply lighting to contours - uniforms.kambient = 1.0 - uniforms.kdiffuse = 0.0 - uniforms.kspecular = 0.0 - uniforms.opacity = 1.0 - - shader.bind() - shader.uniforms = uniforms - - // Draw contour lines - var vao = this._contourVAO - vao.bind() - - // Draw contour levels - for (i = 0; i < 3; ++i) { - shader.uniforms.permutation = PERMUTATIONS[i] - gl.lineWidth(this.contourWidth[i] * this.pixelRatio) - - for (j = 0; j < this.contourLevels[i].length; ++j) { - if (j === this.highlightLevel[i]) { - shader.uniforms.contourColor = this.highlightColor[i] - shader.uniforms.contourTint = this.highlightTint[i] - } else if (j === 0 || (j - 1) === this.highlightLevel[i]) { - shader.uniforms.contourColor = this.contourColor[i] - shader.uniforms.contourTint = this.contourTint[i] - } - if (!this._contourCounts[i][j]) { - continue - } - - shader.uniforms.height = this.contourLevels[i][j] - vao.draw(gl.LINES, this._contourCounts[i][j], this._contourOffsets[i][j]) - } - } - - // Draw projections of surface - for (i = 0; i < 3; ++i) { - shader.uniforms.model = projectData.projections[i] - shader.uniforms.clipBounds = projectData.clipBounds[i] - for (j = 0; j < 3; ++j) { - if (!this.contourProject[i][j]) { - continue - } - shader.uniforms.permutation = PERMUTATIONS[j] - gl.lineWidth(this.contourWidth[j] * this.pixelRatio) - for (var k = 0; k < this.contourLevels[j].length; ++k) { - if (k === this.highlightLevel[j]) { - shader.uniforms.contourColor = this.highlightColor[j] - shader.uniforms.contourTint = this.highlightTint[j] - } else if (k === 0 || (k - 1) === this.highlightLevel[j]) { - shader.uniforms.contourColor = this.contourColor[j] - shader.uniforms.contourTint = this.contourTint[j] - } - if (!this._contourCounts[j][k]) { - continue - } - - shader.uniforms.height = this.contourLevels[j][k] - vao.draw(gl.LINES, this._contourCounts[j][k], this._contourOffsets[j][k]) - } - } - } - - vao.unbind() - - // Draw dynamic contours - vao = this._dynamicVAO - vao.bind() - - // Draw contour levels - for (i = 0; i < 3; ++i) { - if (this._dynamicCounts[i] === 0) { - continue - } - - shader.uniforms.model = uniforms.model - shader.uniforms.clipBounds = uniforms.clipBounds - shader.uniforms.permutation = PERMUTATIONS[i] - gl.lineWidth(this.dynamicWidth[i] * this.pixelRatio) - - shader.uniforms.contourColor = this.dynamicColor[i] - shader.uniforms.contourTint = this.dynamicTint[i] - shader.uniforms.height = this.dynamicLevel[i] - vao.draw(gl.LINES, this._dynamicCounts[i], this._dynamicOffsets[i]) - - for (j = 0; j < 3; ++j) { - if (!this.contourProject[j][i]) { - continue - } - - shader.uniforms.model = projectData.projections[j] - shader.uniforms.clipBounds = projectData.clipBounds[j] - vao.draw(gl.LINES, this._dynamicCounts[i], this._dynamicOffsets[i]) - } - } - - vao.unbind() - } -} - -proto.draw = function (params) { - return drawCore.call(this, params, false) -} - -proto.drawTransparent = function (params) { - return drawCore.call(this, params, true) -} - -var PICK_UNIFORMS = { - model: IDENTITY, - view: IDENTITY, - projection: IDENTITY, - inverseModel: IDENTITY, - clipBounds: [[0, 0, 0], [0, 0, 0]], - height: 0.0, - shape: [0, 0], - pickId: 0, - lowerBound: [0, 0, 0], - upperBound: [0, 0, 0], - zOffset: 0.0, - objectOffset: [0, 0, 0], - permutation: [1, 0, 0, 0, 1, 0, 0, 0, 1], - lightPosition: [0, 0, 0], - eyePosition: [0, 0, 0] -} - -proto.drawPick = function (params) { - params = params || {} - var gl = this.gl - gl.disable(gl.CULL_FACE) - - var uniforms = PICK_UNIFORMS - uniforms.model = params.model || IDENTITY - uniforms.view = params.view || IDENTITY - uniforms.projection = params.projection || IDENTITY - uniforms.shape = this._field[2].shape - uniforms.pickId = this.pickId / 255.0 - uniforms.lowerBound = this.bounds[0] - uniforms.upperBound = this.bounds[1] - uniforms.objectOffset = this.objectOffset - uniforms.permutation = DEFAULT_PERM - - for (var i = 0; i < 2; ++i) { - var clipClamped = uniforms.clipBounds[i] - for (var j = 0; j < 3; ++j) { - clipClamped[j] = Math.min(Math.max(this.clipBounds[i][j], -1e8), 1e8) - } - } - - var projectData = computeProjectionData(uniforms, this) - - if (projectData.showSurface) { - // Set up uniforms - this._pickShader.bind() - this._pickShader.uniforms = uniforms - - // Draw it - this._vao.bind() - this._vao.draw(gl.TRIANGLES, this._vertexCount) - - // Draw projections of surface - for (i = 0; i < 3; ++i) { - if (!this.surfaceProject[i]) { - continue - } - this._pickShader.uniforms.model = projectData.projections[i] - this._pickShader.uniforms.clipBounds = projectData.clipBounds[i] - this._vao.draw(gl.TRIANGLES, this._vertexCount) - } - - this._vao.unbind() - } - - if (projectData.showContour) { - var shader = this._contourPickShader - - shader.bind() - shader.uniforms = uniforms - - var vao = this._contourVAO - vao.bind() - - for (j = 0; j < 3; ++j) { - gl.lineWidth(this.contourWidth[j] * this.pixelRatio) - shader.uniforms.permutation = PERMUTATIONS[j] - for (i = 0; i < this.contourLevels[j].length; ++i) { - if (this._contourCounts[j][i]) { - shader.uniforms.height = this.contourLevels[j][i] - vao.draw(gl.LINES, this._contourCounts[j][i], this._contourOffsets[j][i]) - } - } - } - - // Draw projections of surface - for (i = 0; i < 3; ++i) { - shader.uniforms.model = projectData.projections[i] - shader.uniforms.clipBounds = projectData.clipBounds[i] - - for (j = 0; j < 3; ++j) { - if (!this.contourProject[i][j]) { - continue - } - - shader.uniforms.permutation = PERMUTATIONS[j] - gl.lineWidth(this.contourWidth[j] * this.pixelRatio) - for (var k = 0; k < this.contourLevels[j].length; ++k) { - if (this._contourCounts[j][k]) { - shader.uniforms.height = this.contourLevels[j][k] - vao.draw(gl.LINES, this._contourCounts[j][k], this._contourOffsets[j][k]) - } - } - } - } - - vao.unbind() - } -} - -proto.pick = function (selection) { - if (!selection) { - return null - } - - if (selection.id !== this.pickId) { - return null - } - - var shape = this._field[2].shape - - var result = this._pickResult - - // Compute uv coordinate - var x = shape[0] * (selection.value[0] + (selection.value[2] >> 4) / 16.0) / 255.0 - var ix = Math.floor(x) - var fx = x - ix - - var y = shape[1] * (selection.value[1] + (selection.value[2] & 15) / 16.0) / 255.0 - var iy = Math.floor(y) - var fy = y - iy - - ix += 1 - iy += 1 - - // Compute xyz coordinate - var pos = result.position - pos[0] = pos[1] = pos[2] = 0 - for (var dx = 0; dx < 2; ++dx) { - var s = dx ? fx : 1.0 - fx - for (var dy = 0; dy < 2; ++dy) { - var t = dy ? fy : 1.0 - fy - - var r = ix + dx - var c = iy + dy - var w = s * t - - for (var i = 0; i < 3; ++i) { - pos[i] += this._field[i].get(r, c) * w - } - } - } - - // Find closest level - var levelIndex = this._pickResult.level - for (var j = 0; j < 3; ++j) { - levelIndex[j] = bsearch.le(this.contourLevels[j], pos[j]) - if (levelIndex[j] < 0) { - if (this.contourLevels[j].length > 0) { - levelIndex[j] = 0 - } - } else if (levelIndex[j] < this.contourLevels[j].length - 1) { - var a = this.contourLevels[j][levelIndex[j]] - var b = this.contourLevels[j][levelIndex[j] + 1] - if (Math.abs(a - pos[j]) > Math.abs(b - pos[j])) { - levelIndex[j] += 1 - } - } - } - - result.index[0] = fx < 0.5 ? ix : (ix + 1) - result.index[1] = fy < 0.5 ? iy : (iy + 1) - - result.uv[0] = x / shape[0] - result.uv[1] = y / shape[1] - - for (i = 0; i < 3; ++i) { - result.dataCoordinate[i] = this._field[i].get(result.index[0], result.index[1]) - } - - return result -} - -proto.padField = function(dstField, srcField) { - var srcShape = srcField.shape.slice() - var dstShape = dstField.shape.slice() - - // Center - ops.assign(dstField.lo(1, 1).hi(srcShape[0], srcShape[1]), srcField) - - // Edges - ops.assign(dstField.lo(1).hi(srcShape[0], 1), - srcField.hi(srcShape[0], 1)) - ops.assign(dstField.lo(1, dstShape[1] - 1).hi(srcShape[0], 1), - srcField.lo(0, srcShape[1] - 1).hi(srcShape[0], 1)) - ops.assign(dstField.lo(0, 1).hi(1, srcShape[1]), - srcField.hi(1)) - ops.assign(dstField.lo(dstShape[0] - 1, 1).hi(1, srcShape[1]), - srcField.lo(srcShape[0] - 1)) - // Corners - dstField.set(0, 0, srcField.get(0, 0)) - dstField.set(0, dstShape[1] - 1, srcField.get(0, srcShape[1] - 1)) - dstField.set(dstShape[0] - 1, 0, srcField.get(srcShape[0] - 1, 0)) - dstField.set(dstShape[0] - 1, dstShape[1] - 1, srcField.get(srcShape[0] - 1, srcShape[1] - 1)) -} - -function handleArray (param, ctor) { - if (Array.isArray(param)) { - return [ ctor(param[0]), ctor(param[1]), ctor(param[2]) ] - } - return [ ctor(param), ctor(param), ctor(param) ] -} - -function toColor (x) { - if (Array.isArray(x)) { - if (x.length === 3) { - return [x[0], x[1], x[2], 1] - } - return [x[0], x[1], x[2], x[3]] - } - return [0, 0, 0, 1] -} - -function handleColor (param) { - if (Array.isArray(param)) { - if (Array.isArray(param)) { - return [ - toColor(param[0]), - toColor(param[1]), - toColor(param[2]) ] - } else { - var c = toColor(param) - return [ - c.slice(), - c.slice(), - c.slice() ] - } - } -} - -proto.update = function (params) { - params = params || {} - - this.objectOffset = params.objectOffset || this.objectOffset - - this.dirty = true - - if ('contourWidth' in params) { - this.contourWidth = handleArray(params.contourWidth, Number) - } - if ('showContour' in params) { - this.showContour = handleArray(params.showContour, Boolean) - } - if ('showSurface' in params) { - this.showSurface = !!params.showSurface - } - if ('contourTint' in params) { - this.contourTint = handleArray(params.contourTint, Boolean) - } - if ('contourColor' in params) { - this.contourColor = handleColor(params.contourColor) - } - if ('contourProject' in params) { - this.contourProject = handleArray(params.contourProject, function (x) { - return handleArray(x, Boolean) - }) - } - if ('surfaceProject' in params) { - this.surfaceProject = params.surfaceProject - } - if ('dynamicColor' in params) { - this.dynamicColor = handleColor(params.dynamicColor) - } - if ('dynamicTint' in params) { - this.dynamicTint = handleArray(params.dynamicTint, Number) - } - if ('dynamicWidth' in params) { - this.dynamicWidth = handleArray(params.dynamicWidth, Number) - } - if ('opacity' in params) { - this.opacity = params.opacity - } - if ('colorBounds' in params) { - this.colorBounds = params.colorBounds - } - if ('vertexColor' in params) { - this.vertexColor = params.vertexColor ? 1 : 0; - } - - var field = params.field || (params.coords && params.coords[2]) || null - var levelsChanged = false - - if (!field) { - if (this._field[2].shape[0] || this._field[2].shape[2]) { - field = this._field[2].lo(1, 1).hi(this._field[2].shape[0] - 2, this._field[2].shape[1] - 2) - } else { - field = this._field[2].hi(0, 0) - } - } - - // Update field - if ('field' in params || 'coords' in params) { - var fsize = (field.shape[0] + 2) * (field.shape[1] + 2) - - // Resize if necessary - if (fsize > this._field[2].data.length) { - pool.freeFloat(this._field[2].data) - this._field[2].data = pool.mallocFloat(bits.nextPow2(fsize)) - } - - // Pad field - this._field[2] = ndarray(this._field[2].data, [field.shape[0] + 2, field.shape[1] + 2]) - this.padField(this._field[2], field) - - // Save shape of field - this.shape = field.shape.slice() - var shape = this.shape - - // Resize coordinate fields if necessary - for (var i = 0; i < 2; ++i) { - if (this._field[2].size > this._field[i].data.length) { - pool.freeFloat(this._field[i].data) - this._field[i].data = pool.mallocFloat(this._field[2].size) - } - this._field[i] = ndarray(this._field[i].data, [shape[0] + 2, shape[1] + 2]) - } - - // Generate x/y coordinates - if (params.coords) { - var coords = params.coords - if (!Array.isArray(coords) || coords.length !== 3) { - throw new Error('gl-surface: invalid coordinates for x/y') - } - for (i = 0; i < 2; ++i) { - var coord = coords[i] - for (j = 0; j < 2; ++j) { - if (coord.shape[j] !== shape[j]) { - throw new Error('gl-surface: coords have incorrect shape') - } - } - this.padField(this._field[i], coord) - } - } else if (params.ticks) { - var ticks = params.ticks - if (!Array.isArray(ticks) || ticks.length !== 2) { - throw new Error('gl-surface: invalid ticks') - } - for (i = 0; i < 2; ++i) { - var tick = ticks[i] - if (Array.isArray(tick) || tick.length) { - tick = ndarray(tick) - } - if (tick.shape[0] !== shape[i]) { - throw new Error('gl-surface: invalid tick length') - } - // Make a copy view of the tick array - var tick2 = ndarray(tick.data, shape) - tick2.stride[i] = tick.stride[0] - tick2.stride[i ^ 1] = 0 - - // Fill in field array - this.padField(this._field[i], tick2) - } - } else { - for (i = 0; i < 2; ++i) { - var offset = [0, 0] - offset[i] = 1 - this._field[i] = ndarray(this._field[i].data, [shape[0] + 2, shape[1] + 2], offset, 0) - } - this._field[0].set(0, 0, 0) - for (var j = 0; j < shape[0]; ++j) { - this._field[0].set(j + 1, 0, j) - } - this._field[0].set(shape[0] + 1, 0, shape[0] - 1) - this._field[1].set(0, 0, 0) - for (j = 0; j < shape[1]; ++j) { - this._field[1].set(0, j + 1, j) - } - this._field[1].set(0, shape[1] + 1, shape[1] - 1) - } - - // Save shape - var fields = this._field - - // Compute surface normals - var dfields = ndarray(pool.mallocFloat(fields[2].size * 3 * 2), [3, shape[0] + 2, shape[1] + 2, 2]) - for (i = 0; i < 3; ++i) { - gradient(dfields.pick(i), fields[i], 'mirror') - } - var normals = ndarray(pool.mallocFloat(fields[2].size * 3), [shape[0] + 2, shape[1] + 2, 3]) - for (i = 0; i < shape[0] + 2; ++i) { - for (j = 0; j < shape[1] + 2; ++j) { - var dxdu = dfields.get(0, i, j, 0) - var dxdv = dfields.get(0, i, j, 1) - var dydu = dfields.get(1, i, j, 0) - var dydv = dfields.get(1, i, j, 1) - var dzdu = dfields.get(2, i, j, 0) - var dzdv = dfields.get(2, i, j, 1) - - var nx = dydu * dzdv - dydv * dzdu - var ny = dzdu * dxdv - dzdv * dxdu - var nz = dxdu * dydv - dxdv * dydu - - var nl = Math.sqrt(nx * nx + ny * ny + nz * nz) - if (nl < 1e-8) { - nl = Math.max(Math.abs(nx), Math.abs(ny), Math.abs(nz)) - if (nl < 1e-8) { - nz = 1.0 - ny = nx = 0.0 - nl = 1.0 - } else { - nl = 1.0 / nl - } - } else { - nl = 1.0 / Math.sqrt(nl) - } - - normals.set(i, j, 0, nx * nl) - normals.set(i, j, 1, ny * nl) - normals.set(i, j, 2, nz * nl) - } - } - pool.free(dfields.data) - - // Initialize surface - var lo = [ Infinity, Infinity, Infinity ] - var hi = [ -Infinity, -Infinity, -Infinity ] - var lo_intensity = Infinity - var hi_intensity = -Infinity - var count = (shape[0] - 1) * (shape[1] - 1) * 6 - var tverts = pool.mallocFloat(bits.nextPow2(10 * count)) - var tptr = 0 - var vertexCount = 0 - for (i = 0; i < shape[0] - 1; ++i) { - j_loop: - for (j = 0; j < shape[1] - 1; ++j) { - // Test for NaNs - for (var dx = 0; dx < 2; ++dx) { - for (var dy = 0; dy < 2; ++dy) { - for (var k = 0; k < 3; ++k) { - var f = this._field[k].get(1 + i + dx, 1 + j + dy) - if (isNaN(f) || !isFinite(f)) { - continue j_loop - } - } - } - } - for (k = 0; k < 6; ++k) { - var r = i + QUAD[k][0] - var c = j + QUAD[k][1] - - var tx = this._field[0].get(r + 1, c + 1) - var ty = this._field[1].get(r + 1, c + 1) - f = this._field[2].get(r + 1, c + 1) - - nx = normals.get(r + 1, c + 1, 0) - ny = normals.get(r + 1, c + 1, 1) - nz = normals.get(r + 1, c + 1, 2) - - if (params.intensity) { - vf = params.intensity.get(r, c) - } - - var vf = (params.intensity) ? - params.intensity.get(r, c) : - f + this.objectOffset[2]; - - tverts[tptr++] = r - tverts[tptr++] = c - tverts[tptr++] = tx - tverts[tptr++] = ty - tverts[tptr++] = f - tverts[tptr++] = 0 - tverts[tptr++] = vf - tverts[tptr++] = nx - tverts[tptr++] = ny - tverts[tptr++] = nz - - lo[0] = Math.min(lo[0], tx + this.objectOffset[0]) - lo[1] = Math.min(lo[1], ty + this.objectOffset[1]) - lo[2] = Math.min(lo[2], f + this.objectOffset[2]) - lo_intensity = Math.min(lo_intensity, vf) - - hi[0] = Math.max(hi[0], tx + this.objectOffset[0]) - hi[1] = Math.max(hi[1], ty + this.objectOffset[1]) - hi[2] = Math.max(hi[2], f + this.objectOffset[2]) - hi_intensity = Math.max(hi_intensity, vf) - - vertexCount += 1 - } - } - } - - if (params.intensityBounds) { - lo_intensity = +params.intensityBounds[0] - hi_intensity = +params.intensityBounds[1] - } - - // Scale all vertex intensities - for (i = 6; i < tptr; i += 10) { - tverts[i] = (tverts[i] - lo_intensity) / (hi_intensity - lo_intensity) - } - - this._vertexCount = vertexCount - this._coordinateBuffer.update(tverts.subarray(0, tptr)) - pool.freeFloat(tverts) - pool.free(normals.data) - - // Update bounds - this.bounds = [lo, hi] - - // Save intensity - this.intensity = params.intensity || this._field[2] - - if(this.intensityBounds[0] !== lo_intensity || this.intensityBounds[1] !== hi_intensity) { - levelsChanged = true - } - - // Save intensity bound - this.intensityBounds = [lo_intensity, hi_intensity] - } - - // Update level crossings - if ('levels' in params) { - var levels = params.levels - if (!Array.isArray(levels[0])) { - levels = [ [], [], levels ] - } else { - levels = levels.slice() - } - for (i = 0; i < 3; ++i) { - levels[i] = levels[i].slice() - levels[i].sort(function (a, b) { - return a - b - }) - } - for (i = 0; i < 3; ++i) { - for (j = 0; j < levels[i].length; ++j) { - levels[i][j] -= this.objectOffset[i] - } - } - change_test: - for (i = 0; i < 3; ++i) { - if (levels[i].length !== this.contourLevels[i].length) { - levelsChanged = true - break - } - for (j = 0; j < levels[i].length; ++j) { - if (levels[i][j] !== this.contourLevels[i][j]) { - levelsChanged = true - break change_test - } - } - } - this.contourLevels = levels - } - - if (levelsChanged) { - fields = this._field - shape = this.shape - - // Update contour lines - var contourVerts = [] - - for (var dim = 0; dim < 3; ++dim) { - var contourLevel = this.contourLevels[dim] - - var levelOffsets = [] - var levelCounts = [] - - var parts = [0, 0, 0] - - for (i = 0; i < contourLevel.length; ++i) { - var graph = surfaceNets(this._field[dim], contourLevel[i]) - - levelOffsets.push((contourVerts.length / 5) | 0) - vertexCount = 0 - - edge_loop: - for (j = 0; j < graph.cells.length; ++j) { - var e = graph.cells[j] - for (k = 0; k < 2; ++k) { - var p = graph.positions[e[k]] - - var x = p[0] - var ix = Math.floor(x) | 0 - var fx = x - ix - - var y = p[1] - var iy = Math.floor(y) | 0 - var fy = y - iy - - var hole = false - axis_loop: - for (var axis = 0; axis < 3; ++axis) { - parts[axis] = 0.0 - var iu = (dim + axis + 1) % 3 - for (dx = 0; dx < 2; ++dx) { - var s = dx ? fx : 1.0 - fx - r = Math.min(Math.max(ix + dx, 0), shape[0]) | 0 - for (dy = 0; dy < 2; ++dy) { - var t = dy ? fy : 1.0 - fy - c = Math.min(Math.max(iy + dy, 0), shape[1]) | 0 - - if (axis < 2) { - f = this._field[iu].get(r, c) - } else { - f = (this.intensity.get(r, c) - this.intensityBounds[0]) / (this.intensityBounds[1] - this.intensityBounds[0]) - } - if (!isFinite(f) || isNaN(f)) { - hole = true - break axis_loop - } - - var w = s * t - parts[axis] += w * f - } - } - } - - if (!hole) { - contourVerts.push( - parts[0], - parts[1], - p[0], - p[1], - parts[2] - ) - vertexCount += 1 - } else { - if (k > 0) { - // If we already added first edge, pop off verts - for (var l = 0; l < 5; ++l) { - contourVerts.pop() - } - vertexCount -= 1 - } - continue edge_loop - } - } - } - levelCounts.push(vertexCount) - } - - // Store results - this._contourOffsets[dim] = levelOffsets - this._contourCounts[dim] = levelCounts - - } - - var floatBuffer = pool.mallocFloat(contourVerts.length) - for (i = 0; i < contourVerts.length; ++i) { - floatBuffer[i] = contourVerts[i] - } - this._contourBuffer.update(floatBuffer) - pool.freeFloat(floatBuffer) - } - - if (params.colormap) { - this._colorMap.setPixels(genColormap(params.colormap)) - } -} - -proto.dispose = function () { - this._shader.dispose() - this._vao.dispose() - this._coordinateBuffer.dispose() - this._colorMap.dispose() - this._contourBuffer.dispose() - this._contourVAO.dispose() - this._contourShader.dispose() - this._contourPickShader.dispose() - this._dynamicBuffer.dispose() - this._dynamicVAO.dispose() - for (var i = 0; i < 3; ++i) { - pool.freeFloat(this._field[i].data) - } -} - -proto.highlight = function (selection) { - var i - - if (!selection) { - this._dynamicCounts = [0, 0, 0] - this.dyanamicLevel = [NaN, NaN, NaN] - this.highlightLevel = [-1, -1, -1] - return - } - - for (i = 0; i < 3; ++i) { - if (this.enableHighlight[i]) { - this.highlightLevel[i] = selection.level[i] - } else { - this.highlightLevel[i] = -1 - } - } - - var levels - if (this.snapToData) { - levels = selection.dataCoordinate - } else { - levels = selection.position - } - for (i = 0; i < 3; ++i) { - levels[i] -= this.objectOffset[i] - } - if ((!this.enableDynamic[0] || levels[0] === this.dynamicLevel[0]) && - (!this.enableDynamic[1] || levels[1] === this.dynamicLevel[1]) && - (!this.enableDynamic[2] || levels[2] === this.dynamicLevel[2])) { - return - } - - var vertexCount = 0 - var shape = this.shape - var scratchBuffer = pool.mallocFloat(12 * shape[0] * shape[1]) - - for (var d = 0; d < 3; ++d) { - if (!this.enableDynamic[d]) { - this.dynamicLevel[d] = NaN - this._dynamicCounts[d] = 0 - continue - } - - this.dynamicLevel[d] = levels[d] - - var u = (d + 1) % 3 - var v = (d + 2) % 3 - - var f = this._field[d] - var g = this._field[u] - var h = this._field[v] - - var graph = surfaceNets(f, levels[d]) - var edges = graph.cells - var positions = graph.positions - - this._dynamicOffsets[d] = vertexCount - - for (i = 0; i < edges.length; ++i) { - var e = edges[i] - for (var j = 0; j < 2; ++j) { - var p = positions[e[j]] - - var x = +p[0] - var ix = x | 0 - var jx = Math.min(ix + 1, shape[0]) | 0 - var fx = x - ix - var hx = 1.0 - fx - - var y = +p[1] - var iy = y | 0 - var jy = Math.min(iy + 1, shape[1]) | 0 - var fy = y - iy - var hy = 1.0 - fy - - var w00 = hx * hy - var w01 = hx * fy - var w10 = fx * hy - var w11 = fx * fy - - var cu = w00 * g.get(ix, iy) + - w01 * g.get(ix, jy) + - w10 * g.get(jx, iy) + - w11 * g.get(jx, jy) - - var cv = w00 * h.get(ix, iy) + - w01 * h.get(ix, jy) + - w10 * h.get(jx, iy) + - w11 * h.get(jx, jy) - - if (isNaN(cu) || isNaN(cv)) { - if (j) { - vertexCount -= 1 - } - break - } - - scratchBuffer[2 * vertexCount + 0] = cu - scratchBuffer[2 * vertexCount + 1] = cv - - vertexCount += 1 - } - } - - this._dynamicCounts[d] = vertexCount - this._dynamicOffsets[d] - } - - this._dynamicBuffer.update(scratchBuffer.subarray(0, 2 * vertexCount)) - pool.freeFloat(scratchBuffer) -} - -function createSurfacePlot (params) { - var gl = params.gl - - var shader = createShader(gl) - var pickShader = createPickShader(gl) - var contourShader = createContourShader(gl) - var contourPickShader = createPickContourShader(gl) - - var coordinateBuffer = createBuffer(gl) - var vao = createVAO(gl, [ - { buffer: coordinateBuffer, - size: 4, - stride: SURFACE_VERTEX_SIZE, - offset: 0 - }, - { buffer: coordinateBuffer, - size: 3, - stride: SURFACE_VERTEX_SIZE, - offset: 16 - }, - { - buffer: coordinateBuffer, - size: 3, - stride: SURFACE_VERTEX_SIZE, - offset: 28 - } - ]) - - var contourBuffer = createBuffer(gl) - var contourVAO = createVAO(gl, [ - { - buffer: contourBuffer, - size: 4, - stride: 20, - offset: 0 - }, - { - buffer: contourBuffer, - size: 1, - stride: 20, - offset: 16 - } - ]) - - var dynamicBuffer = createBuffer(gl) - var dynamicVAO = createVAO(gl, [ - { - buffer: dynamicBuffer, - size: 2, - type: gl.FLOAT - }]) - - var cmap = createTexture(gl, 1, N_COLORS, gl.RGBA, gl.UNSIGNED_BYTE) - cmap.minFilter = gl.LINEAR - cmap.magFilter = gl.LINEAR - - var surface = new SurfacePlot( - gl, - [0, 0], // shape - [[0, 0, 0], [0, 0, 0]], // bounds - shader, - pickShader, - coordinateBuffer, - vao, - cmap, - contourShader, - contourPickShader, - contourBuffer, - contourVAO, - dynamicBuffer, - dynamicVAO, - [0, 0, 0] // objectOffset - ) - - var nparams = { - levels: [[], [], []] - } - for (var id in params) { - nparams[id] = params[id] - } - nparams.colormap = nparams.colormap || 'jet' - - surface.update(nparams) - - return surface -} - -},{"./lib/shaders":314,"binary-search-bounds":315,"bit-twiddle":92,"colormap":126,"gl-buffer":241,"gl-mat4/invert":265,"gl-mat4/multiply":267,"gl-texture2d":322,"gl-vao":327,"ndarray":450,"ndarray-gradient":441,"ndarray-ops":444,"ndarray-pack":445,"surface-nets":531,"typedarray-pool":545}],317:[function(_dereq_,module,exports){ -'use strict' - -var Font = _dereq_('css-font') -var pick = _dereq_('pick-by-alias') -var createRegl = _dereq_('regl') -var createGl = _dereq_('gl-util/context') -var WeakMap = _dereq_('es6-weak-map') -var rgba = _dereq_('color-normalize') -var fontAtlas = _dereq_('font-atlas') -var pool = _dereq_('typedarray-pool') -var parseRect = _dereq_('parse-rect') -var isObj = _dereq_('is-plain-obj') -var parseUnit = _dereq_('parse-unit') -var px = _dereq_('to-px') -var kerning = _dereq_('detect-kerning') -var extend = _dereq_('object-assign') -var metrics = _dereq_('font-measure') -var flatten = _dereq_('flatten-vertex-data') -var ref = _dereq_('bit-twiddle'); -var nextPow2 = ref.nextPow2; - -var shaderCache = new WeakMap - - -// Safari does not support font-stretch -var isStretchSupported = false -if (document.body) { - var el = document.body.appendChild(document.createElement('div')) - el.style.font = 'italic small-caps bold condensed 16px/2 cursive' - if (getComputedStyle(el).fontStretch) { - isStretchSupported = true - } - document.body.removeChild(el) -} - -var GlText = function GlText (o) { - if (isRegl(o)) { - o = {regl: o} - this.gl = o.regl._gl - } - else { - this.gl = createGl(o) - } - - this.shader = shaderCache.get(this.gl) - - if (!this.shader) { - this.regl = o.regl || createRegl({ gl: this.gl }) - } - else { - this.regl = this.shader.regl - } - - this.charBuffer = this.regl.buffer({ type: 'uint8', usage: 'stream' }) - this.sizeBuffer = this.regl.buffer({ type: 'float', usage: 'stream' }) - - if (!this.shader) { - this.shader = this.createShader() - shaderCache.set(this.gl, this.shader) - } - - this.batch = [] - - // multiple options initial state - this.fontSize = [] - this.font = [] - this.fontAtlas = [] - - this.draw = this.shader.draw.bind(this) - this.render = function () { - // FIXME: add Safari regl report here: - // charBuffer and width just do not trigger - this.regl._refresh() - this.draw(this.batch) - } - this.canvas = this.gl.canvas - - this.update(isObj(o) ? o : {}) -}; - -GlText.prototype.createShader = function createShader () { - var regl = this.regl - - // FIXME: store 2 shader versions: with normal viewport and without - // draw texture method - var draw = regl({ - blend: { - enable: true, - color: [0,0,0,1], - - func: { - srcRGB: 'src alpha', - dstRGB: 'one minus src alpha', - srcAlpha: 'one minus dst alpha', - dstAlpha: 'one' - } - }, - stencil: {enable: false}, - depth: {enable: false}, - - count: regl.prop('count'), - offset: regl.prop('offset'), - attributes: { - charOffset: { - offset: 4, - stride: 8, - buffer: regl.this('sizeBuffer') - }, - width: { - offset: 0, - stride: 8, - buffer: regl.this('sizeBuffer') - }, - char: regl.this('charBuffer'), - position: regl.this('position') - }, - uniforms: { - atlasSize: function (c, p) { return [p.atlas.width, p.atlas.height]; }, - atlasDim: function (c, p) { return [p.atlas.cols, p.atlas.rows]; }, - atlas: function (c, p) { return p.atlas.texture; }, - charStep: function (c, p) { return p.atlas.step; }, - em: function (c, p) { return p.atlas.em; }, - color: regl.prop('color'), - opacity: regl.prop('opacity'), - viewport: regl.this('viewportArray'), - scale: regl.this('scale'), - align: regl.prop('align'), - baseline: regl.prop('baseline'), - translate: regl.this('translate'), - positionOffset: regl.prop('positionOffset') - }, - primitive: 'points', - viewport: regl.this('viewport'), - - vert: ("\n\t\t\tprecision highp float;\n\t\t\tattribute float width, charOffset, char;\n\t\t\tattribute vec2 position;\n\t\t\tuniform float fontSize, charStep, em, align, baseline;\n\t\t\tuniform vec4 viewport;\n\t\t\tuniform vec4 color;\n\t\t\tuniform vec2 atlasSize, atlasDim, scale, translate, positionOffset;\n\t\t\tvarying vec2 charCoord, charId;\n\t\t\tvarying float charWidth;\n\t\t\tvarying vec4 fontColor;\n\t\t\tvoid main () {\n\t\t\t\t" + (!GlText.normalViewport ? 'vec2 positionOffset = vec2(positionOffset.x,- positionOffset.y);' : '') + "\n\n\t\t\t\tvec2 offset = floor(em * (vec2(align + charOffset, baseline)\n\t\t\t\t\t+ positionOffset))\n\t\t\t\t\t/ (viewport.zw * scale.xy);\n\n\t\t\t\tvec2 position = (position + translate) * scale;\n\t\t\t\tposition += offset * scale;\n\n\t\t\t\t" + (GlText.normalViewport ? 'position.y = 1. - position.y;' : '') + "\n\n\t\t\t\tcharCoord = position * viewport.zw + viewport.xy;\n\n\t\t\t\tgl_Position = vec4(position * 2. - 1., 0, 1);\n\n\t\t\t\tgl_PointSize = charStep;\n\n\t\t\t\tcharId.x = mod(char, atlasDim.x);\n\t\t\t\tcharId.y = floor(char / atlasDim.x);\n\n\t\t\t\tcharWidth = width * em;\n\n\t\t\t\tfontColor = color / 255.;\n\t\t\t}"), - - frag: "\n\t\t\tprecision highp float;\n\t\t\tuniform sampler2D atlas;\n\t\t\tuniform float fontSize, charStep, opacity;\n\t\t\tuniform vec2 atlasSize;\n\t\t\tuniform vec4 viewport;\n\t\t\tvarying vec4 fontColor;\n\t\t\tvarying vec2 charCoord, charId;\n\t\t\tvarying float charWidth;\n\n\t\t\tfloat lightness(vec4 color) {\n\t\t\t\treturn color.r * 0.299 + color.g * 0.587 + color.b * 0.114;\n\t\t\t}\n\n\t\t\tvoid main () {\n\t\t\t\tvec2 uv = gl_FragCoord.xy - charCoord + charStep * .5;\n\t\t\t\tfloat halfCharStep = floor(charStep * .5 + .5);\n\n\t\t\t\t// invert y and shift by 1px (FF expecially needs that)\n\t\t\t\tuv.y = charStep - uv.y;\n\n\t\t\t\t// ignore points outside of character bounding box\n\t\t\t\tfloat halfCharWidth = ceil(charWidth * .5);\n\t\t\t\tif (floor(uv.x) > halfCharStep + halfCharWidth ||\n\t\t\t\t\tfloor(uv.x) < halfCharStep - halfCharWidth) return;\n\n\t\t\t\tuv += charId * charStep;\n\t\t\t\tuv = uv / atlasSize;\n\n\t\t\t\tvec4 color = fontColor;\n\t\t\t\tvec4 mask = texture2D(atlas, uv);\n\n\t\t\t\tfloat maskY = lightness(mask);\n\t\t\t\t// float colorY = lightness(color);\n\t\t\t\tcolor.a *= maskY;\n\t\t\t\tcolor.a *= opacity;\n\n\t\t\t\t// color.a += .1;\n\n\t\t\t\t// antialiasing, see yiq color space y-channel formula\n\t\t\t\t// color.rgb += (1. - color.rgb) * (1. - mask.rgb);\n\n\t\t\t\tgl_FragColor = color;\n\t\t\t}" - }) - - // per font-size atlas - var atlas = {} - - return { regl: regl, draw: draw, atlas: atlas } -}; - -GlText.prototype.update = function update (o) { - var this$1 = this; - - if (typeof o === 'string') { o = { text: o } } - else if (!o) { return } - - // FIXME: make this a static transform or more general approact - o = pick(o, { - position: 'position positions coord coords coordinates', - font: 'font fontFace fontface typeface cssFont css-font family fontFamily', - fontSize: 'fontSize fontsize size font-size', - text: 'text texts chars characters value values symbols', - align: 'align alignment textAlign textbaseline', - baseline: 'baseline textBaseline textbaseline', - direction: 'dir direction textDirection', - color: 'color colour fill fill-color fillColor textColor textcolor', - kerning: 'kerning kern', - range: 'range dataBox', - viewport: 'vp viewport viewBox viewbox viewPort', - opacity: 'opacity alpha transparency visible visibility opaque', - offset: 'offset positionOffset padding shift indent indentation' - }, true) - - - if (o.opacity != null) { - if (Array.isArray(o.opacity)) { - this.opacity = o.opacity.map(function (o) { return parseFloat(o); }) - } - else { - this.opacity = parseFloat(o.opacity) - } - } - - if (o.viewport != null) { - this.viewport = parseRect(o.viewport) - - if (GlText.normalViewport) { - this.viewport.y = this.canvas.height - this.viewport.y - this.viewport.height - } - - this.viewportArray = [this.viewport.x, this.viewport.y, this.viewport.width, this.viewport.height] - - } - if (this.viewport == null) { - this.viewport = { - x: 0, y: 0, - width: this.gl.drawingBufferWidth, - height: this.gl.drawingBufferHeight - } - this.viewportArray = [this.viewport.x, this.viewport.y, this.viewport.width, this.viewport.height] - } - - if (o.kerning != null) { this.kerning = o.kerning } - - if (o.offset != null) { - if (typeof o.offset === 'number') { o.offset = [o.offset, 0] } - - this.positionOffset = flatten(o.offset) - } - - if (o.direction) { this.direction = o.direction } - - if (o.range) { - this.range = o.range - this.scale = [1 / (o.range[2] - o.range[0]), 1 / (o.range[3] - o.range[1])] - this.translate = [-o.range[0], -o.range[1]] - } - if (o.scale) { this.scale = o.scale } - if (o.translate) { this.translate = o.translate } - - // default scale corresponds to viewport - if (!this.scale) { this.scale = [1 / this.viewport.width, 1 / this.viewport.height] } - - if (!this.translate) { this.translate = [0, 0] } - - if (!this.font.length && !o.font) { o.font = GlText.baseFontSize + 'px sans-serif' } - - // normalize font caching string - var newFont = false, newFontSize = false - - // obtain new font data - if (o.font) { - (Array.isArray(o.font) ? o.font : [o.font]).forEach(function (font, i) { - // normalize font - if (typeof font === 'string') { - try { - font = Font.parse(font) - } catch (e) { - font = Font.parse(GlText.baseFontSize + 'px ' + font) - } - } - else { font = Font.parse(Font.stringify(font)) } - - var baseString = Font.stringify({ - size: GlText.baseFontSize, - family: font.family, - stretch: isStretchSupported ? font.stretch : undefined, - variant: font.variant, - weight: font.weight, - style: font.style - }) - - var unit = parseUnit(font.size) - var fs = Math.round(unit[0] * px(unit[1])) - if (fs !== this$1.fontSize[i]) { - newFontSize = true - this$1.fontSize[i] = fs - } - - // calc new font metrics/atlas - if (!this$1.font[i] || baseString != this$1.font[i].baseString) { - newFont = true - - // obtain font cache or create one - this$1.font[i] = GlText.fonts[baseString] - if (!this$1.font[i]) { - var family = font.family.join(', ') - var style = [font.style] - if (font.style != font.variant) { style.push(font.variant) } - if (font.variant != font.weight) { style.push(font.weight) } - if (isStretchSupported && font.weight != font.stretch) { style.push(font.stretch) } - - this$1.font[i] = { - baseString: baseString, - - // typeface - family: family, - weight: font.weight, - stretch: font.stretch, - style: font.style, - variant: font.variant, - - // widths of characters - width: {}, - - // kernin pairs offsets - kerning: {}, - - metrics: metrics(family, { - origin: 'top', - fontSize: GlText.baseFontSize, - fontStyle: style.join(' ') - }) - } - - GlText.fonts[baseString] = this$1.font[i] - } - } - }) - } - - // FIXME: make independend font-size - // if (o.fontSize) { - // let unit = parseUnit(o.fontSize) - // let fs = Math.round(unit[0] * px(unit[1])) - - // if (fs != this.fontSize) { - // newFontSize = true - // this.fontSize = fs - // } - // } - - if (newFont || newFontSize) { - this.font.forEach(function (font, i) { - var fontString = Font.stringify({ - size: this$1.fontSize[i], - family: font.family, - stretch: isStretchSupported ? font.stretch : undefined, - variant: font.variant, - weight: font.weight, - style: font.style - }) - - // calc new font size atlas - this$1.fontAtlas[i] = this$1.shader.atlas[fontString] - - if (!this$1.fontAtlas[i]) { - var metrics = font.metrics - - this$1.shader.atlas[fontString] = - this$1.fontAtlas[i] = { - fontString: fontString, - // even step is better for rendered characters - step: Math.ceil(this$1.fontSize[i] * metrics.bottom * .5) * 2, - em: this$1.fontSize[i], - cols: 0, - rows: 0, - height: 0, - width: 0, - chars: [], - ids: {}, - texture: this$1.regl.texture() - } - } - - // bump atlas characters - if (o.text == null) { o.text = this$1.text } - }) - } - - // if multiple positions - duplicate text arguments - // FIXME: this possibly can be done better to avoid array spawn - if (typeof o.text === 'string' && o.position && o.position.length > 2) { - var textArray = Array(o.position.length * .5) - for (var i = 0; i < textArray.length; i++) { - textArray[i] = o.text - } - o.text = textArray - } - - // calculate offsets for the new font/text - var newAtlasChars - if (o.text != null || newFont) { - // FIXME: ignore spaces - // text offsets within the text buffer - this.textOffsets = [0] - - if (Array.isArray(o.text)) { - this.count = o.text[0].length - this.counts = [this.count] - for (var i$1 = 1; i$1 < o.text.length; i$1++) { - this.textOffsets[i$1] = this.textOffsets[i$1 - 1] + o.text[i$1 - 1].length - this.count += o.text[i$1].length - this.counts.push(o.text[i$1].length) - } - this.text = o.text.join('') - } - else { - this.text = o.text - this.count = this.text.length - this.counts = [this.count] - } - - newAtlasChars = [] - - // detect & measure new characters - this.font.forEach(function (font, idx) { - GlText.atlasContext.font = font.baseString - - var atlas = this$1.fontAtlas[idx] - - for (var i = 0; i < this$1.text.length; i++) { - var char = this$1.text.charAt(i) - - if (atlas.ids[char] == null) { - atlas.ids[char] = atlas.chars.length - atlas.chars.push(char) - newAtlasChars.push(char) - } - - if (font.width[char] == null) { - font.width[char] = GlText.atlasContext.measureText(char).width / GlText.baseFontSize - - // measure kerning pairs for the new character - if (this$1.kerning) { - var pairs = [] - for (var baseChar in font.width) { - pairs.push(baseChar + char, char + baseChar) - } - extend(font.kerning, kerning(font.family, { - pairs: pairs - })) - } - } - } - }) - } - - // create single position buffer (faster than batch or multiple separate instances) - if (o.position) { - if (o.position.length > 2) { - var flat = !o.position[0].length - var positionData = pool.mallocFloat(this.count * 2) - for (var i$2 = 0, ptr = 0; i$2 < this.counts.length; i$2++) { - var count = this.counts[i$2] - if (flat) { - for (var j = 0; j < count; j++) { - positionData[ptr++] = o.position[i$2 * 2] - positionData[ptr++] = o.position[i$2 * 2 + 1] - } - } - else { - for (var j$1 = 0; j$1 < count; j$1++) { - positionData[ptr++] = o.position[i$2][0] - positionData[ptr++] = o.position[i$2][1] - } - } - } - if (this.position.call) { - this.position({ - type: 'float', - data: positionData - }) - } else { - this.position = this.regl.buffer({ - type: 'float', - data: positionData - }) - } - pool.freeFloat(positionData) - } - else { - if (this.position.destroy) { this.position.destroy() } - this.position = { - constant: o.position - } - } - } - - // populate text/offset buffers if font/text has changed - // as [charWidth, offset, charWidth, offset...] - // that is in em units since font-size can change often - if (o.text || newFont) { - var charIds = pool.mallocUint8(this.count) - var sizeData = pool.mallocFloat(this.count * 2) - this.textWidth = [] - - for (var i$3 = 0, ptr$1 = 0; i$3 < this.counts.length; i$3++) { - var count$1 = this.counts[i$3] - var font = this.font[i$3] || this.font[0] - var atlas = this.fontAtlas[i$3] || this.fontAtlas[0] - - for (var j$2 = 0; j$2 < count$1; j$2++) { - var char = this.text.charAt(ptr$1) - var prevChar = this.text.charAt(ptr$1 - 1) - - charIds[ptr$1] = atlas.ids[char] - sizeData[ptr$1 * 2] = font.width[char] - - if (j$2) { - var prevWidth = sizeData[ptr$1 * 2 - 2] - var currWidth = sizeData[ptr$1 * 2] - var prevOffset = sizeData[ptr$1 * 2 - 1] - var offset = prevOffset + prevWidth * .5 + currWidth * .5; - - if (this.kerning) { - var kerning$1 = font.kerning[prevChar + char] - if (kerning$1) { - offset += kerning$1 * 1e-3 - } - } - - sizeData[ptr$1 * 2 + 1] = offset - } - else { - sizeData[ptr$1 * 2 + 1] = sizeData[ptr$1 * 2] * .5 - } - - ptr$1++ - } - this.textWidth.push( - !sizeData.length ? 0 : - // last offset + half last width - sizeData[ptr$1 * 2 - 2] * .5 + sizeData[ptr$1 * 2 - 1] - ) - } - - - // bump recalc align offset - if (!o.align) { o.align = this.align } - this.charBuffer({data: charIds, type: 'uint8', usage: 'stream'}) - this.sizeBuffer({data: sizeData, type: 'float', usage: 'stream'}) - pool.freeUint8(charIds) - pool.freeFloat(sizeData) - - // udpate font atlas and texture - if (newAtlasChars.length) { - this.font.forEach(function (font, i) { - var atlas = this$1.fontAtlas[i] - - // FIXME: insert metrics-based ratio here - var step = atlas.step - - var maxCols = Math.floor(GlText.maxAtlasSize / step) - var cols = Math.min(maxCols, atlas.chars.length) - var rows = Math.ceil(atlas.chars.length / cols) - - var atlasWidth = nextPow2( cols * step ) - // let atlasHeight = Math.min(rows * step + step * .5, GlText.maxAtlasSize); - var atlasHeight = nextPow2( rows * step ); - - atlas.width = atlasWidth - atlas.height = atlasHeight; - atlas.rows = rows - atlas.cols = cols - - if (!atlas.em) { return } - - atlas.texture({ - data: fontAtlas({ - canvas: GlText.atlasCanvas, - font: atlas.fontString, - chars: atlas.chars, - shape: [atlasWidth, atlasHeight], - step: [step, step] - }) - }) - - }) - } - } - - if (o.align) { - this.align = o.align - this.alignOffset = this.textWidth.map(function (textWidth, i) { - var align = !Array.isArray(this$1.align) ? this$1.align : this$1.align.length > 1 ? this$1.align[i] : this$1.align[0] - - if (typeof align === 'number') { return align } - switch (align) { - case 'right': - case 'end': - return -textWidth - case 'center': - case 'centre': - case 'middle': - return -textWidth * .5 - } - - return 0 - }) - } - - if (this.baseline == null && o.baseline == null) { - o.baseline = 0 - } - if (o.baseline != null) { - this.baseline = o.baseline - if (!Array.isArray(this.baseline)) { this.baseline = [this.baseline] } - this.baselineOffset = this.baseline.map(function (baseline, i) { - var m = (this$1.font[i] || this$1.font[0]).metrics - var base = 0 - - base += m.bottom * .5 - - if (typeof baseline === 'number') { - base += (baseline - m.baseline) - } - else { - base += -m[baseline] - } - - if (!GlText.normalViewport) { base *= -1 } - return base - }) - } - - // flatten colors to a single uint8 array - if (o.color != null) { - if (!o.color) { o.color = 'transparent' } - - // single color - if (typeof o.color === 'string' || !isNaN(o.color)) { - this.color = rgba(o.color, 'uint8') - } - // array - else { - var colorData - - // flat array - if (typeof o.color[0] === 'number' && o.color.length > this.counts.length) { - var l = o.color.length - colorData = pool.mallocUint8(l) - var sub = (o.color.subarray || o.color.slice).bind(o.color) - for (var i$4 = 0; i$4 < l; i$4 += 4) { - colorData.set(rgba(sub(i$4, i$4 + 4), 'uint8'), i$4) - } - } - // nested array - else { - var l$1 = o.color.length - colorData = pool.mallocUint8(l$1 * 4) - for (var i$5 = 0; i$5 < l$1; i$5++) { - colorData.set(rgba(o.color[i$5] || 0, 'uint8'), i$5 * 4) - } - } - - this.color = colorData - } - } - - // update render batch - if (o.position || o.text || o.color || o.baseline || o.align || o.font || o.offset || o.opacity) { - var isBatch = (this.color.length > 4) - || (this.baselineOffset.length > 1) - || (this.align && this.align.length > 1) - || (this.fontAtlas.length > 1) - || (this.positionOffset.length > 2) - if (isBatch) { - var length = Math.max( - this.position.length * .5 || 0, - this.color.length * .25 || 0, - this.baselineOffset.length || 0, - this.alignOffset.length || 0, - this.font.length || 0, - this.opacity.length || 0, - this.positionOffset.length * .5 || 0 - ) - this.batch = Array(length) - for (var i$6 = 0; i$6 < this.batch.length; i$6++) { - this.batch[i$6] = { - count: this.counts.length > 1 ? this.counts[i$6] : this.counts[0], - offset: this.textOffsets.length > 1 ? this.textOffsets[i$6] : this.textOffsets[0], - color: !this.color ? [0,0,0,255] : this.color.length <= 4 ? this.color : this.color.subarray(i$6 * 4, i$6 * 4 + 4), - opacity: Array.isArray(this.opacity) ? this.opacity[i$6] : this.opacity, - baseline: this.baselineOffset[i$6] != null ? this.baselineOffset[i$6] : this.baselineOffset[0], - align: !this.align ? 0 : this.alignOffset[i$6] != null ? this.alignOffset[i$6] : this.alignOffset[0], - atlas: this.fontAtlas[i$6] || this.fontAtlas[0], - positionOffset: this.positionOffset.length > 2 ? this.positionOffset.subarray(i$6 * 2, i$6 * 2 + 2) : this.positionOffset - } - } - } - // single-color, single-baseline, single-align batch is faster to render - else { - if (this.count) { - this.batch = [{ - count: this.count, - offset: 0, - color: this.color || [0,0,0,255], - opacity: Array.isArray(this.opacity) ? this.opacity[0] : this.opacity, - baseline: this.baselineOffset[0], - align: this.alignOffset ? this.alignOffset[0] : 0, - atlas: this.fontAtlas[0], - positionOffset: this.positionOffset - }] - } - else { - this.batch = [] - } - } - } -}; - -GlText.prototype.destroy = function destroy () { - // TODO: count instances of atlases and destroy all on null -}; - - -// defaults -GlText.prototype.kerning = true -GlText.prototype.position = { constant: new Float32Array(2) } -GlText.prototype.translate = null -GlText.prototype.scale = null -GlText.prototype.font = null -GlText.prototype.text = '' -GlText.prototype.positionOffset = [0, 0] -GlText.prototype.opacity = 1 -GlText.prototype.color = new Uint8Array([0, 0, 0, 255]) -GlText.prototype.alignOffset = [0, 0] - - -// whether viewport should be top↓bottom 2d one (true) or webgl one (false) -GlText.normalViewport = false - -// size of an atlas -GlText.maxAtlasSize = 1024 - -// font atlas canvas is singleton -GlText.atlasCanvas = document.createElement('canvas') -GlText.atlasContext = GlText.atlasCanvas.getContext('2d', {alpha: false}) - -// font-size used for metrics, atlas step calculation -GlText.baseFontSize = 64 - -// fonts storage -GlText.fonts = {} - -// max number of different font atlases/textures cached -// FIXME: enable atlas size limitation via LRU -// GlText.atlasCacheSize = 64 - -function isRegl (o) { - return typeof o === 'function' && - o._gl && - o.prop && - o.texture && - o.buffer -} - - -module.exports = GlText - - -},{"bit-twiddle":92,"color-normalize":120,"css-font":139,"detect-kerning":166,"es6-weak-map":318,"flatten-vertex-data":227,"font-atlas":228,"font-measure":229,"gl-util/context":323,"is-plain-obj":422,"object-assign":454,"parse-rect":459,"parse-unit":461,"pick-by-alias":465,"regl":502,"to-px":539,"typedarray-pool":545}],318:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = _dereq_("./is-implemented")() ? WeakMap : _dereq_("./polyfill"); - -},{"./is-implemented":319,"./polyfill":321}],319:[function(_dereq_,module,exports){ -"use strict"; - -module.exports = function () { - var weakMap, obj; - - if (typeof WeakMap !== "function") return false; - try { - // WebKit doesn't support arguments and crashes - weakMap = new WeakMap([[obj = {}, "one"], [{}, "two"], [{}, "three"]]); - } catch (e) { - return false; - } - if (String(weakMap) !== "[object WeakMap]") return false; - if (typeof weakMap.set !== "function") return false; - if (weakMap.set({}, 1) !== weakMap) return false; - if (typeof weakMap.delete !== "function") return false; - if (typeof weakMap.has !== "function") return false; - if (weakMap.get(obj) !== "one") return false; - - return true; -}; - -},{}],320:[function(_dereq_,module,exports){ -// Exports true if environment provides native `WeakMap` implementation, whatever that is. - -"use strict"; - -module.exports = (function () { - if (typeof WeakMap !== "function") return false; - return Object.prototype.toString.call(new WeakMap()) === "[object WeakMap]"; -}()); - -},{}],321:[function(_dereq_,module,exports){ -"use strict"; - -var isValue = _dereq_("es5-ext/object/is-value") - , setPrototypeOf = _dereq_("es5-ext/object/set-prototype-of") - , object = _dereq_("es5-ext/object/valid-object") - , ensureValue = _dereq_("es5-ext/object/valid-value") - , randomUniq = _dereq_("es5-ext/string/random-uniq") - , d = _dereq_("d") - , getIterator = _dereq_("es6-iterator/get") - , forOf = _dereq_("es6-iterator/for-of") - , toStringTagSymbol = _dereq_("es6-symbol").toStringTag - , isNative = _dereq_("./is-native-implemented") - - , isArray = Array.isArray, defineProperty = Object.defineProperty - , objHasOwnProperty = Object.prototype.hasOwnProperty, getPrototypeOf = Object.getPrototypeOf - , WeakMapPoly; - -module.exports = WeakMapPoly = function (/* Iterable*/) { - var iterable = arguments[0], self; - - if (!(this instanceof WeakMapPoly)) throw new TypeError("Constructor requires 'new'"); - self = isNative && setPrototypeOf && (WeakMap !== WeakMapPoly) - ? setPrototypeOf(new WeakMap(), getPrototypeOf(this)) : this; - - if (isValue(iterable)) { - if (!isArray(iterable)) iterable = getIterator(iterable); - } - defineProperty(self, "__weakMapData__", d("c", "$weakMap$" + randomUniq())); - if (!iterable) return self; - forOf(iterable, function (val) { - ensureValue(val); - self.set(val[0], val[1]); - }); - return self; -}; - -if (isNative) { - if (setPrototypeOf) setPrototypeOf(WeakMapPoly, WeakMap); - WeakMapPoly.prototype = Object.create(WeakMap.prototype, { constructor: d(WeakMapPoly) }); -} - -Object.defineProperties(WeakMapPoly.prototype, { - delete: d(function (key) { - if (objHasOwnProperty.call(object(key), this.__weakMapData__)) { - delete key[this.__weakMapData__]; - return true; - } - return false; - }), - get: d(function (key) { - if (!objHasOwnProperty.call(object(key), this.__weakMapData__)) return undefined; - return key[this.__weakMapData__]; - }), - has: d(function (key) { - return objHasOwnProperty.call(object(key), this.__weakMapData__); - }), - set: d(function (key, value) { - defineProperty(object(key), this.__weakMapData__, d("c", value)); - return this; - }), - toString: d(function () { - return "[object WeakMap]"; - }) -}); -defineProperty(WeakMapPoly.prototype, toStringTagSymbol, d("c", "WeakMap")); - -},{"./is-native-implemented":320,"d":151,"es5-ext/object/is-value":194,"es5-ext/object/set-prototype-of":200,"es5-ext/object/valid-object":204,"es5-ext/object/valid-value":205,"es5-ext/string/random-uniq":210,"es6-iterator/for-of":212,"es6-iterator/get":213,"es6-symbol":219}],322:[function(_dereq_,module,exports){ -'use strict' - -var ndarray = _dereq_('ndarray') -var ops = _dereq_('ndarray-ops') -var pool = _dereq_('typedarray-pool') - -module.exports = createTexture2D - -var linearTypes = null -var filterTypes = null -var wrapTypes = null - -function lazyInitLinearTypes(gl) { - linearTypes = [ - gl.LINEAR, - gl.NEAREST_MIPMAP_LINEAR, - gl.LINEAR_MIPMAP_NEAREST, - gl.LINEAR_MIPMAP_NEAREST - ] - filterTypes = [ - gl.NEAREST, - gl.LINEAR, - gl.NEAREST_MIPMAP_NEAREST, - gl.NEAREST_MIPMAP_LINEAR, - gl.LINEAR_MIPMAP_NEAREST, - gl.LINEAR_MIPMAP_LINEAR - ] - wrapTypes = [ - gl.REPEAT, - gl.CLAMP_TO_EDGE, - gl.MIRRORED_REPEAT - ] -} - -function acceptTextureDOM (obj) { - return ( - ('undefined' != typeof HTMLCanvasElement && obj instanceof HTMLCanvasElement) || - ('undefined' != typeof HTMLImageElement && obj instanceof HTMLImageElement) || - ('undefined' != typeof HTMLVideoElement && obj instanceof HTMLVideoElement) || - ('undefined' != typeof ImageData && obj instanceof ImageData)) -} - -var convertFloatToUint8 = function(out, inp) { - ops.muls(out, inp, 255.0) -} - -function reshapeTexture(tex, w, h) { - var gl = tex.gl - var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) - if(w < 0 || w > maxSize || h < 0 || h > maxSize) { - throw new Error('gl-texture2d: Invalid texture size') - } - tex._shape = [w, h] - tex.bind() - gl.texImage2D(gl.TEXTURE_2D, 0, tex.format, w, h, 0, tex.format, tex.type, null) - tex._mipLevels = [0] - return tex -} - -function Texture2D(gl, handle, width, height, format, type) { - this.gl = gl - this.handle = handle - this.format = format - this.type = type - this._shape = [width, height] - this._mipLevels = [0] - this._magFilter = gl.NEAREST - this._minFilter = gl.NEAREST - this._wrapS = gl.CLAMP_TO_EDGE - this._wrapT = gl.CLAMP_TO_EDGE - this._anisoSamples = 1 - - var parent = this - var wrapVector = [this._wrapS, this._wrapT] - Object.defineProperties(wrapVector, [ - { - get: function() { - return parent._wrapS - }, - set: function(v) { - return parent.wrapS = v - } - }, - { - get: function() { - return parent._wrapT - }, - set: function(v) { - return parent.wrapT = v - } - } - ]) - this._wrapVector = wrapVector - - var shapeVector = [this._shape[0], this._shape[1]] - Object.defineProperties(shapeVector, [ - { - get: function() { - return parent._shape[0] - }, - set: function(v) { - return parent.width = v - } - }, - { - get: function() { - return parent._shape[1] - }, - set: function(v) { - return parent.height = v - } - } - ]) - this._shapeVector = shapeVector -} - -var proto = Texture2D.prototype - -Object.defineProperties(proto, { - minFilter: { - get: function() { - return this._minFilter - }, - set: function(v) { - this.bind() - var gl = this.gl - if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) { - if(!gl.getExtension('OES_texture_float_linear')) { - v = gl.NEAREST - } - } - if(filterTypes.indexOf(v) < 0) { - throw new Error('gl-texture2d: Unknown filter mode ' + v) - } - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, v) - return this._minFilter = v - } - }, - magFilter: { - get: function() { - return this._magFilter - }, - set: function(v) { - this.bind() - var gl = this.gl - if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) { - if(!gl.getExtension('OES_texture_float_linear')) { - v = gl.NEAREST - } - } - if(filterTypes.indexOf(v) < 0) { - throw new Error('gl-texture2d: Unknown filter mode ' + v) - } - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, v) - return this._magFilter = v - } - }, - mipSamples: { - get: function() { - return this._anisoSamples - }, - set: function(i) { - var psamples = this._anisoSamples - this._anisoSamples = Math.max(i, 1)|0 - if(psamples !== this._anisoSamples) { - var ext = this.gl.getExtension('EXT_texture_filter_anisotropic') - if(ext) { - this.gl.texParameterf(this.gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisoSamples) - } - } - return this._anisoSamples - } - }, - wrapS: { - get: function() { - return this._wrapS - }, - set: function(v) { - this.bind() - if(wrapTypes.indexOf(v) < 0) { - throw new Error('gl-texture2d: Unknown wrap mode ' + v) - } - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, v) - return this._wrapS = v - } - }, - wrapT: { - get: function() { - return this._wrapT - }, - set: function(v) { - this.bind() - if(wrapTypes.indexOf(v) < 0) { - throw new Error('gl-texture2d: Unknown wrap mode ' + v) - } - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, v) - return this._wrapT = v - } - }, - wrap: { - get: function() { - return this._wrapVector - }, - set: function(v) { - if(!Array.isArray(v)) { - v = [v,v] - } - if(v.length !== 2) { - throw new Error('gl-texture2d: Must specify wrap mode for rows and columns') - } - for(var i=0; i<2; ++i) { - if(wrapTypes.indexOf(v[i]) < 0) { - throw new Error('gl-texture2d: Unknown wrap mode ' + v) - } - } - this._wrapS = v[0] - this._wrapT = v[1] - - var gl = this.gl - this.bind() - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._wrapS) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._wrapT) - - return v - } - }, - shape: { - get: function() { - return this._shapeVector - }, - set: function(x) { - if(!Array.isArray(x)) { - x = [x|0,x|0] - } else { - if(x.length !== 2) { - throw new Error('gl-texture2d: Invalid texture shape') - } - } - reshapeTexture(this, x[0]|0, x[1]|0) - return [x[0]|0, x[1]|0] - } - }, - width: { - get: function() { - return this._shape[0] - }, - set: function(w) { - w = w|0 - reshapeTexture(this, w, this._shape[1]) - return w - } - }, - height: { - get: function() { - return this._shape[1] - }, - set: function(h) { - h = h|0 - reshapeTexture(this, this._shape[0], h) - return h - } - } -}) - -proto.bind = function(unit) { - var gl = this.gl - if(unit !== undefined) { - gl.activeTexture(gl.TEXTURE0 + (unit|0)) - } - gl.bindTexture(gl.TEXTURE_2D, this.handle) - if(unit !== undefined) { - return (unit|0) - } - return gl.getParameter(gl.ACTIVE_TEXTURE) - gl.TEXTURE0 -} - -proto.dispose = function() { - this.gl.deleteTexture(this.handle) -} - -proto.generateMipmap = function() { - this.bind() - this.gl.generateMipmap(this.gl.TEXTURE_2D) - - //Update mip levels - var l = Math.min(this._shape[0], this._shape[1]) - for(var i=0; l>0; ++i, l>>>=1) { - if(this._mipLevels.indexOf(i) < 0) { - this._mipLevels.push(i) - } - } -} - -proto.setPixels = function(data, x_off, y_off, mip_level) { - var gl = this.gl - this.bind() - if(Array.isArray(x_off)) { - mip_level = y_off - y_off = x_off[1]|0 - x_off = x_off[0]|0 - } else { - x_off = x_off || 0 - y_off = y_off || 0 - } - mip_level = mip_level || 0 - var directData = acceptTextureDOM(data) ? data : data.raw - if(directData) { - var needsMip = this._mipLevels.indexOf(mip_level) < 0 - if(needsMip) { - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, directData) - this._mipLevels.push(mip_level) - } else { - gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, this.format, this.type, directData) - } - } else if(data.shape && data.stride && data.data) { - if(data.shape.length < 2 || - x_off + data.shape[1] > this._shape[1]>>>mip_level || - y_off + data.shape[0] > this._shape[0]>>>mip_level || - x_off < 0 || - y_off < 0) { - throw new Error('gl-texture2d: Texture dimensions are out of bounds') - } - texSubImageArray(gl, x_off, y_off, mip_level, this.format, this.type, this._mipLevels, data) - } else { - throw new Error('gl-texture2d: Unsupported data type') - } -} - - -function isPacked(shape, stride) { - if(shape.length === 3) { - return (stride[2] === 1) && - (stride[1] === shape[0]*shape[2]) && - (stride[0] === shape[2]) - } - return (stride[0] === 1) && - (stride[1] === shape[0]) -} - -function texSubImageArray(gl, x_off, y_off, mip_level, cformat, ctype, mipLevels, array) { - var dtype = array.dtype - var shape = array.shape.slice() - if(shape.length < 2 || shape.length > 3) { - throw new Error('gl-texture2d: Invalid ndarray, must be 2d or 3d') - } - var type = 0, format = 0 - var packed = isPacked(shape, array.stride.slice()) - if(dtype === 'float32') { - type = gl.FLOAT - } else if(dtype === 'float64') { - type = gl.FLOAT - packed = false - dtype = 'float32' - } else if(dtype === 'uint8') { - type = gl.UNSIGNED_BYTE - } else { - type = gl.UNSIGNED_BYTE - packed = false - dtype = 'uint8' - } - var channels = 1 - if(shape.length === 2) { - format = gl.LUMINANCE - shape = [shape[0], shape[1], 1] - array = ndarray(array.data, shape, [array.stride[0], array.stride[1], 1], array.offset) - } else if(shape.length === 3) { - if(shape[2] === 1) { - format = gl.ALPHA - } else if(shape[2] === 2) { - format = gl.LUMINANCE_ALPHA - } else if(shape[2] === 3) { - format = gl.RGB - } else if(shape[2] === 4) { - format = gl.RGBA - } else { - throw new Error('gl-texture2d: Invalid shape for pixel coords') - } - channels = shape[2] - } else { - throw new Error('gl-texture2d: Invalid shape for texture') - } - //For 1-channel textures allow conversion between formats - if((format === gl.LUMINANCE || format === gl.ALPHA) && - (cformat === gl.LUMINANCE || cformat === gl.ALPHA)) { - format = cformat - } - if(format !== cformat) { - throw new Error('gl-texture2d: Incompatible texture format for setPixels') - } - var size = array.size - var needsMip = mipLevels.indexOf(mip_level) < 0 - if(needsMip) { - mipLevels.push(mip_level) - } - if(type === ctype && packed) { - //Array data types are compatible, can directly copy into texture - if(array.offset === 0 && array.data.length === size) { - if(needsMip) { - gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[0], shape[1], 0, cformat, ctype, array.data) - } else { - gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[0], shape[1], cformat, ctype, array.data) - } - } else { - if(needsMip) { - gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[0], shape[1], 0, cformat, ctype, array.data.subarray(array.offset, array.offset+size)) - } else { - gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[0], shape[1], cformat, ctype, array.data.subarray(array.offset, array.offset+size)) - } - } - } else { - //Need to do type conversion to pack data into buffer - var pack_buffer - if(ctype === gl.FLOAT) { - pack_buffer = pool.mallocFloat32(size) - } else { - pack_buffer = pool.mallocUint8(size) - } - var pack_view = ndarray(pack_buffer, shape, [shape[2], shape[2]*shape[0], 1]) - if(type === gl.FLOAT && ctype === gl.UNSIGNED_BYTE) { - convertFloatToUint8(pack_view, array) - } else { - ops.assign(pack_view, array) - } - if(needsMip) { - gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[0], shape[1], 0, cformat, ctype, pack_buffer.subarray(0, size)) - } else { - gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[0], shape[1], cformat, ctype, pack_buffer.subarray(0, size)) - } - if(ctype === gl.FLOAT) { - pool.freeFloat32(pack_buffer) - } else { - pool.freeUint8(pack_buffer) - } - } -} - -function initTexture(gl) { - var tex = gl.createTexture() - gl.bindTexture(gl.TEXTURE_2D, tex) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - return tex -} - -function createTextureShape(gl, width, height, format, type) { - var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) - if(width < 0 || width > maxTextureSize || height < 0 || height > maxTextureSize) { - throw new Error('gl-texture2d: Invalid texture shape') - } - if(type === gl.FLOAT && !gl.getExtension('OES_texture_float')) { - throw new Error('gl-texture2d: Floating point textures not supported on this platform') - } - var tex = initTexture(gl) - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, null) - return new Texture2D(gl, tex, width, height, format, type) -} - -function createTextureDOM(gl, directData, width, height, format, type) { - var tex = initTexture(gl) - gl.texImage2D(gl.TEXTURE_2D, 0, format, format, type, directData) - return new Texture2D(gl, tex, width, height, format, type) -} - -//Creates a texture from an ndarray -function createTextureArray(gl, array) { - var dtype = array.dtype - var shape = array.shape.slice() - var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) - if(shape[0] < 0 || shape[0] > maxSize || shape[1] < 0 || shape[1] > maxSize) { - throw new Error('gl-texture2d: Invalid texture size') - } - var packed = isPacked(shape, array.stride.slice()) - var type = 0 - if(dtype === 'float32') { - type = gl.FLOAT - } else if(dtype === 'float64') { - type = gl.FLOAT - packed = false - dtype = 'float32' - } else if(dtype === 'uint8') { - type = gl.UNSIGNED_BYTE - } else { - type = gl.UNSIGNED_BYTE - packed = false - dtype = 'uint8' - } - var format = 0 - if(shape.length === 2) { - format = gl.LUMINANCE - shape = [shape[0], shape[1], 1] - array = ndarray(array.data, shape, [array.stride[0], array.stride[1], 1], array.offset) - } else if(shape.length === 3) { - if(shape[2] === 1) { - format = gl.ALPHA - } else if(shape[2] === 2) { - format = gl.LUMINANCE_ALPHA - } else if(shape[2] === 3) { - format = gl.RGB - } else if(shape[2] === 4) { - format = gl.RGBA - } else { - throw new Error('gl-texture2d: Invalid shape for pixel coords') - } - } else { - throw new Error('gl-texture2d: Invalid shape for texture') - } - if(type === gl.FLOAT && !gl.getExtension('OES_texture_float')) { - type = gl.UNSIGNED_BYTE - packed = false - } - var buffer, buf_store - var size = array.size - if(!packed) { - var stride = [shape[2], shape[2]*shape[0], 1] - buf_store = pool.malloc(size, dtype) - var buf_array = ndarray(buf_store, shape, stride, 0) - if((dtype === 'float32' || dtype === 'float64') && type === gl.UNSIGNED_BYTE) { - convertFloatToUint8(buf_array, array) - } else { - ops.assign(buf_array, array) - } - buffer = buf_store.subarray(0, size) - } else if (array.offset === 0 && array.data.length === size) { - buffer = array.data - } else { - buffer = array.data.subarray(array.offset, array.offset + size) - } - var tex = initTexture(gl) - gl.texImage2D(gl.TEXTURE_2D, 0, format, shape[0], shape[1], 0, format, type, buffer) - if(!packed) { - pool.free(buf_store) - } - return new Texture2D(gl, tex, shape[0], shape[1], format, type) -} - -function createTexture2D(gl) { - if(arguments.length <= 1) { - throw new Error('gl-texture2d: Missing arguments for texture2d constructor') - } - if(!linearTypes) { - lazyInitLinearTypes(gl) - } - if(typeof arguments[1] === 'number') { - return createTextureShape(gl, arguments[1], arguments[2], arguments[3]||gl.RGBA, arguments[4]||gl.UNSIGNED_BYTE) - } - if(Array.isArray(arguments[1])) { - return createTextureShape(gl, arguments[1][0]|0, arguments[1][1]|0, arguments[2]||gl.RGBA, arguments[3]||gl.UNSIGNED_BYTE) - } - if(typeof arguments[1] === 'object') { - var obj = arguments[1] - var directData = acceptTextureDOM(obj) ? obj : obj.raw - if (directData) { - return createTextureDOM(gl, directData, obj.width|0, obj.height|0, arguments[2]||gl.RGBA, arguments[3]||gl.UNSIGNED_BYTE) - } else if(obj.shape && obj.data && obj.stride) { - return createTextureArray(gl, obj) - } - } - throw new Error('gl-texture2d: Invalid arguments for texture2d constructor') -} - -},{"ndarray":450,"ndarray-ops":444,"typedarray-pool":545}],323:[function(_dereq_,module,exports){ -(function (global){ -/** @module gl-util/context */ -'use strict' - -var pick = _dereq_('pick-by-alias') - -module.exports = function setContext (o) { - if (!o) o = {} - else if (typeof o === 'string') o = {container: o} - - // HTMLCanvasElement - if (isCanvas(o)) { - o = {container: o} - } - // HTMLElement - else if (isElement(o)) { - o = {container: o} - } - // WebGLContext - else if (isContext(o)) { - o = {gl: o} - } - // options object - else { - o = pick(o, { - container: 'container target element el canvas holder parent parentNode wrapper use ref root node', - gl: 'gl context webgl glContext', - attrs: 'attributes attrs contextAttributes', - pixelRatio: 'pixelRatio pxRatio px ratio pxratio pixelratio', - width: 'w width', - height: 'h height' - }, true) - } - - if (!o.pixelRatio) o.pixelRatio = global.pixelRatio || 1 - - // make sure there is container and canvas - if (o.gl) { - return o.gl - } - if (o.canvas) { - o.container = o.canvas.parentNode - } - if (o.container) { - if (typeof o.container === 'string') { - var c = document.querySelector(o.container) - if (!c) throw Error('Element ' + o.container + ' is not found') - o.container = c - } - if (isCanvas(o.container)) { - o.canvas = o.container - o.container = o.canvas.parentNode - } - else if (!o.canvas) { - o.canvas = createCanvas() - o.container.appendChild(o.canvas) - resize(o) - } - } - // blank new canvas - else if (!o.canvas) { - if (typeof document !== 'undefined') { - o.container = document.body || document.documentElement - o.canvas = createCanvas() - o.container.appendChild(o.canvas) - resize(o) - } - else { - throw Error('Not DOM environment. Use headless-gl.') - } - } - - // make sure there is context - if (!o.gl) { - try { - o.gl = o.canvas.getContext('webgl', o.attrs) - } catch (e) { - try { - o.gl = o.canvas.getContext('experimental-webgl', o.attrs) - } - catch (e) { - o.gl = o.canvas.getContext('webgl-experimental', o.attrs) - } - } - } - - return o.gl -} - - -function resize (o) { - if (o.container) { - if (o.container == document.body) { - if (!document.body.style.width) o.canvas.width = o.width || (o.pixelRatio * global.innerWidth) - if (!document.body.style.height) o.canvas.height = o.height || (o.pixelRatio * global.innerHeight) - } - else { - var bounds = o.container.getBoundingClientRect() - o.canvas.width = o.width || (bounds.right - bounds.left) - o.canvas.height = o.height || (bounds.bottom - bounds.top) - } - } -} - -function isCanvas (e) { - return typeof e.getContext === 'function' - && 'width' in e - && 'height' in e -} - -function isElement (e) { - return typeof e.nodeName === 'string' && - typeof e.appendChild === 'function' && - typeof e.getBoundingClientRect === 'function' -} - -function isContext (e) { - return typeof e.drawArrays === 'function' || - typeof e.drawElements === 'function' -} - -function createCanvas () { - var canvas = document.createElement('canvas') - canvas.style.position = 'absolute' - canvas.style.top = 0 - canvas.style.left = 0 - - return canvas -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"pick-by-alias":465}],324:[function(_dereq_,module,exports){ -"use strict" - -function doBind(gl, elements, attributes) { - if(elements) { - elements.bind() - } else { - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null) - } - var nattribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS)|0 - if(attributes) { - if(attributes.length > nattribs) { - throw new Error("gl-vao: Too many vertex attributes") - } - for(var i=0; i 1.0){ - return 0 - } else { - return Math.acos(cosine) - } -} - -},{"./dot":339,"./fromValues":345,"./normalize":356}],330:[function(_dereq_,module,exports){ -module.exports = ceil - -/** - * Math.ceil the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to ceil - * @returns {vec3} out - */ -function ceil(out, a) { - out[0] = Math.ceil(a[0]) - out[1] = Math.ceil(a[1]) - out[2] = Math.ceil(a[2]) - return out -} - -},{}],331:[function(_dereq_,module,exports){ -module.exports = clone; - -/** - * Creates a new vec3 initialized with values from an existing vector - * - * @param {vec3} a vector to clone - * @returns {vec3} a new 3D vector - */ -function clone(a) { - var out = new Float32Array(3) - out[0] = a[0] - out[1] = a[1] - out[2] = a[2] - return out -} -},{}],332:[function(_dereq_,module,exports){ -module.exports = copy; - -/** - * Copy the values from one vec3 to another - * - * @param {vec3} out the receiving vector - * @param {vec3} a the source vector - * @returns {vec3} out - */ -function copy(out, a) { - out[0] = a[0] - out[1] = a[1] - out[2] = a[2] - return out -} -},{}],333:[function(_dereq_,module,exports){ -module.exports = create; - -/** - * Creates a new, empty vec3 - * - * @returns {vec3} a new 3D vector - */ -function create() { - var out = new Float32Array(3) - out[0] = 0 - out[1] = 0 - out[2] = 0 - return out -} -},{}],334:[function(_dereq_,module,exports){ -module.exports = cross; - -/** - * Computes the cross product of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -function cross(out, a, b) { - var ax = a[0], ay = a[1], az = a[2], - bx = b[0], by = b[1], bz = b[2] - - out[0] = ay * bz - az * by - out[1] = az * bx - ax * bz - out[2] = ax * by - ay * bx - return out -} -},{}],335:[function(_dereq_,module,exports){ -module.exports = _dereq_('./distance') - -},{"./distance":336}],336:[function(_dereq_,module,exports){ -module.exports = distance; - -/** - * Calculates the euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} distance between a and b - */ -function distance(a, b) { - var x = b[0] - a[0], - y = b[1] - a[1], - z = b[2] - a[2] - return Math.sqrt(x*x + y*y + z*z) -} -},{}],337:[function(_dereq_,module,exports){ -module.exports = _dereq_('./divide') - -},{"./divide":338}],338:[function(_dereq_,module,exports){ -module.exports = divide; - -/** - * Divides two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -function divide(out, a, b) { - out[0] = a[0] / b[0] - out[1] = a[1] / b[1] - out[2] = a[2] / b[2] - return out -} -},{}],339:[function(_dereq_,module,exports){ -module.exports = dot; - -/** - * Calculates the dot product of two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} dot product of a and b - */ -function dot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] -} -},{}],340:[function(_dereq_,module,exports){ -module.exports = 0.000001 - -},{}],341:[function(_dereq_,module,exports){ -module.exports = equals - -var EPSILON = _dereq_('./epsilon') - -/** - * Returns whether or not the vectors have approximately the same elements in the same position. - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -function equals(a, b) { - var a0 = a[0] - var a1 = a[1] - var a2 = a[2] - var b0 = b[0] - var b1 = b[1] - var b2 = b[2] - return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && - Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && - Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2))) -} - -},{"./epsilon":340}],342:[function(_dereq_,module,exports){ -module.exports = exactEquals - -/** - * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===) - * - * @param {vec3} a The first vector. - * @param {vec3} b The second vector. - * @returns {Boolean} True if the vectors are equal, false otherwise. - */ -function exactEquals(a, b) { - return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] -} - -},{}],343:[function(_dereq_,module,exports){ -module.exports = floor - -/** - * Math.floor the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to floor - * @returns {vec3} out - */ -function floor(out, a) { - out[0] = Math.floor(a[0]) - out[1] = Math.floor(a[1]) - out[2] = Math.floor(a[2]) - return out -} - -},{}],344:[function(_dereq_,module,exports){ -module.exports = forEach; - -var vec = _dereq_('./create')() - -/** - * Perform some operation over an array of vec3s. - * - * @param {Array} a the array of vectors to iterate over - * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed - * @param {Number} offset Number of elements to skip at the beginning of the array - * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array - * @param {Function} fn Function to call for each vector in the array - * @param {Object} [arg] additional argument to pass to fn - * @returns {Array} a - * @function - */ -function forEach(a, stride, offset, count, fn, arg) { - var i, l - if(!stride) { - stride = 3 - } - - if(!offset) { - offset = 0 - } - - if(count) { - l = Math.min((count * stride) + offset, a.length) - } else { - l = a.length - } - - for(i = offset; i < l; i += stride) { - vec[0] = a[i] - vec[1] = a[i+1] - vec[2] = a[i+2] - fn(vec, vec, arg) - a[i] = vec[0] - a[i+1] = vec[1] - a[i+2] = vec[2] - } - - return a -} -},{"./create":333}],345:[function(_dereq_,module,exports){ -module.exports = fromValues; - -/** - * Creates a new vec3 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} a new 3D vector - */ -function fromValues(x, y, z) { - var out = new Float32Array(3) - out[0] = x - out[1] = y - out[2] = z - return out -} -},{}],346:[function(_dereq_,module,exports){ -module.exports = { - EPSILON: _dereq_('./epsilon') - , create: _dereq_('./create') - , clone: _dereq_('./clone') - , angle: _dereq_('./angle') - , fromValues: _dereq_('./fromValues') - , copy: _dereq_('./copy') - , set: _dereq_('./set') - , equals: _dereq_('./equals') - , exactEquals: _dereq_('./exactEquals') - , add: _dereq_('./add') - , subtract: _dereq_('./subtract') - , sub: _dereq_('./sub') - , multiply: _dereq_('./multiply') - , mul: _dereq_('./mul') - , divide: _dereq_('./divide') - , div: _dereq_('./div') - , min: _dereq_('./min') - , max: _dereq_('./max') - , floor: _dereq_('./floor') - , ceil: _dereq_('./ceil') - , round: _dereq_('./round') - , scale: _dereq_('./scale') - , scaleAndAdd: _dereq_('./scaleAndAdd') - , distance: _dereq_('./distance') - , dist: _dereq_('./dist') - , squaredDistance: _dereq_('./squaredDistance') - , sqrDist: _dereq_('./sqrDist') - , length: _dereq_('./length') - , len: _dereq_('./len') - , squaredLength: _dereq_('./squaredLength') - , sqrLen: _dereq_('./sqrLen') - , negate: _dereq_('./negate') - , inverse: _dereq_('./inverse') - , normalize: _dereq_('./normalize') - , dot: _dereq_('./dot') - , cross: _dereq_('./cross') - , lerp: _dereq_('./lerp') - , random: _dereq_('./random') - , transformMat4: _dereq_('./transformMat4') - , transformMat3: _dereq_('./transformMat3') - , transformQuat: _dereq_('./transformQuat') - , rotateX: _dereq_('./rotateX') - , rotateY: _dereq_('./rotateY') - , rotateZ: _dereq_('./rotateZ') - , forEach: _dereq_('./forEach') -} - -},{"./add":328,"./angle":329,"./ceil":330,"./clone":331,"./copy":332,"./create":333,"./cross":334,"./dist":335,"./distance":336,"./div":337,"./divide":338,"./dot":339,"./epsilon":340,"./equals":341,"./exactEquals":342,"./floor":343,"./forEach":344,"./fromValues":345,"./inverse":347,"./len":348,"./length":349,"./lerp":350,"./max":351,"./min":352,"./mul":353,"./multiply":354,"./negate":355,"./normalize":356,"./random":357,"./rotateX":358,"./rotateY":359,"./rotateZ":360,"./round":361,"./scale":362,"./scaleAndAdd":363,"./set":364,"./sqrDist":365,"./sqrLen":366,"./squaredDistance":367,"./squaredLength":368,"./sub":369,"./subtract":370,"./transformMat3":371,"./transformMat4":372,"./transformQuat":373}],347:[function(_dereq_,module,exports){ -module.exports = inverse; - -/** - * Returns the inverse of the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to invert - * @returns {vec3} out - */ -function inverse(out, a) { - out[0] = 1.0 / a[0] - out[1] = 1.0 / a[1] - out[2] = 1.0 / a[2] - return out -} -},{}],348:[function(_dereq_,module,exports){ -module.exports = _dereq_('./length') - -},{"./length":349}],349:[function(_dereq_,module,exports){ -module.exports = length; - -/** - * Calculates the length of a vec3 - * - * @param {vec3} a vector to calculate length of - * @returns {Number} length of a - */ -function length(a) { - var x = a[0], - y = a[1], - z = a[2] - return Math.sqrt(x*x + y*y + z*z) -} -},{}],350:[function(_dereq_,module,exports){ -module.exports = lerp; - -/** - * Performs a linear interpolation between two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec3} out - */ -function lerp(out, a, b, t) { - var ax = a[0], - ay = a[1], - az = a[2] - out[0] = ax + t * (b[0] - ax) - out[1] = ay + t * (b[1] - ay) - out[2] = az + t * (b[2] - az) - return out -} -},{}],351:[function(_dereq_,module,exports){ -module.exports = max; - -/** - * Returns the maximum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -function max(out, a, b) { - out[0] = Math.max(a[0], b[0]) - out[1] = Math.max(a[1], b[1]) - out[2] = Math.max(a[2], b[2]) - return out -} -},{}],352:[function(_dereq_,module,exports){ -module.exports = min; - -/** - * Returns the minimum of two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -function min(out, a, b) { - out[0] = Math.min(a[0], b[0]) - out[1] = Math.min(a[1], b[1]) - out[2] = Math.min(a[2], b[2]) - return out -} -},{}],353:[function(_dereq_,module,exports){ -module.exports = _dereq_('./multiply') - -},{"./multiply":354}],354:[function(_dereq_,module,exports){ -module.exports = multiply; - -/** - * Multiplies two vec3's - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -function multiply(out, a, b) { - out[0] = a[0] * b[0] - out[1] = a[1] * b[1] - out[2] = a[2] * b[2] - return out -} -},{}],355:[function(_dereq_,module,exports){ -module.exports = negate; - -/** - * Negates the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to negate - * @returns {vec3} out - */ -function negate(out, a) { - out[0] = -a[0] - out[1] = -a[1] - out[2] = -a[2] - return out -} -},{}],356:[function(_dereq_,module,exports){ -module.exports = normalize; - -/** - * Normalize a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to normalize - * @returns {vec3} out - */ -function normalize(out, a) { - var x = a[0], - y = a[1], - z = a[2] - var len = x*x + y*y + z*z - if (len > 0) { - //TODO: evaluate use of glm_invsqrt here? - len = 1 / Math.sqrt(len) - out[0] = a[0] * len - out[1] = a[1] * len - out[2] = a[2] * len - } - return out -} -},{}],357:[function(_dereq_,module,exports){ -module.exports = random; - -/** - * Generates a random vector with the given scale - * - * @param {vec3} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec3} out - */ -function random(out, scale) { - scale = scale || 1.0 - - var r = Math.random() * 2.0 * Math.PI - var z = (Math.random() * 2.0) - 1.0 - var zScale = Math.sqrt(1.0-z*z) * scale - - out[0] = Math.cos(r) * zScale - out[1] = Math.sin(r) * zScale - out[2] = z * scale - return out -} -},{}],358:[function(_dereq_,module,exports){ -module.exports = rotateX; - -/** - * Rotate a 3D vector around the x-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -function rotateX(out, a, b, c){ - var by = b[1] - var bz = b[2] - - // Translate point to the origin - var py = a[1] - by - var pz = a[2] - bz - - var sc = Math.sin(c) - var cc = Math.cos(c) - - // perform rotation and translate to correct position - out[0] = a[0] - out[1] = by + py * cc - pz * sc - out[2] = bz + py * sc + pz * cc - - return out -} - -},{}],359:[function(_dereq_,module,exports){ -module.exports = rotateY; - -/** - * Rotate a 3D vector around the y-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -function rotateY(out, a, b, c){ - var bx = b[0] - var bz = b[2] - - // translate point to the origin - var px = a[0] - bx - var pz = a[2] - bz - - var sc = Math.sin(c) - var cc = Math.cos(c) - - // perform rotation and translate to correct position - out[0] = bx + pz * sc + px * cc - out[1] = a[1] - out[2] = bz + pz * cc - px * sc - - return out -} - -},{}],360:[function(_dereq_,module,exports){ -module.exports = rotateZ; - -/** - * Rotate a 3D vector around the z-axis - * @param {vec3} out The receiving vec3 - * @param {vec3} a The vec3 point to rotate - * @param {vec3} b The origin of the rotation - * @param {Number} c The angle of rotation - * @returns {vec3} out - */ -function rotateZ(out, a, b, c){ - var bx = b[0] - var by = b[1] - - //Translate point to the origin - var px = a[0] - bx - var py = a[1] - by - - var sc = Math.sin(c) - var cc = Math.cos(c) - - // perform rotation and translate to correct position - out[0] = bx + px * cc - py * sc - out[1] = by + px * sc + py * cc - out[2] = a[2] - - return out -} - -},{}],361:[function(_dereq_,module,exports){ -module.exports = round - -/** - * Math.round the components of a vec3 - * - * @param {vec3} out the receiving vector - * @param {vec3} a vector to round - * @returns {vec3} out - */ -function round(out, a) { - out[0] = Math.round(a[0]) - out[1] = Math.round(a[1]) - out[2] = Math.round(a[2]) - return out -} - -},{}],362:[function(_dereq_,module,exports){ -module.exports = scale; - -/** - * Scales a vec3 by a scalar number - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec3} out - */ -function scale(out, a, b) { - out[0] = a[0] * b - out[1] = a[1] * b - out[2] = a[2] * b - return out -} -},{}],363:[function(_dereq_,module,exports){ -module.exports = scaleAndAdd; - -/** - * Adds two vec3's after scaling the second operand by a scalar value - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec3} out - */ -function scaleAndAdd(out, a, b, scale) { - out[0] = a[0] + (b[0] * scale) - out[1] = a[1] + (b[1] * scale) - out[2] = a[2] + (b[2] * scale) - return out -} -},{}],364:[function(_dereq_,module,exports){ -module.exports = set; - -/** - * Set the components of a vec3 to the given values - * - * @param {vec3} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @returns {vec3} out - */ -function set(out, x, y, z) { - out[0] = x - out[1] = y - out[2] = z - return out -} -},{}],365:[function(_dereq_,module,exports){ -module.exports = _dereq_('./squaredDistance') - -},{"./squaredDistance":367}],366:[function(_dereq_,module,exports){ -module.exports = _dereq_('./squaredLength') - -},{"./squaredLength":368}],367:[function(_dereq_,module,exports){ -module.exports = squaredDistance; - -/** - * Calculates the squared euclidian distance between two vec3's - * - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {Number} squared distance between a and b - */ -function squaredDistance(a, b) { - var x = b[0] - a[0], - y = b[1] - a[1], - z = b[2] - a[2] - return x*x + y*y + z*z -} -},{}],368:[function(_dereq_,module,exports){ -module.exports = squaredLength; - -/** - * Calculates the squared length of a vec3 - * - * @param {vec3} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -function squaredLength(a) { - var x = a[0], - y = a[1], - z = a[2] - return x*x + y*y + z*z -} -},{}],369:[function(_dereq_,module,exports){ -module.exports = _dereq_('./subtract') - -},{"./subtract":370}],370:[function(_dereq_,module,exports){ -module.exports = subtract; - -/** - * Subtracts vector b from vector a - * - * @param {vec3} out the receiving vector - * @param {vec3} a the first operand - * @param {vec3} b the second operand - * @returns {vec3} out - */ -function subtract(out, a, b) { - out[0] = a[0] - b[0] - out[1] = a[1] - b[1] - out[2] = a[2] - b[2] - return out -} -},{}],371:[function(_dereq_,module,exports){ -module.exports = transformMat3; - -/** - * Transforms the vec3 with a mat3. - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m the 3x3 matrix to transform with - * @returns {vec3} out - */ -function transformMat3(out, a, m) { - var x = a[0], y = a[1], z = a[2] - out[0] = x * m[0] + y * m[3] + z * m[6] - out[1] = x * m[1] + y * m[4] + z * m[7] - out[2] = x * m[2] + y * m[5] + z * m[8] - return out -} -},{}],372:[function(_dereq_,module,exports){ -module.exports = transformMat4; - -/** - * Transforms the vec3 with a mat4. - * 4th vector component is implicitly '1' - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec3} out - */ -function transformMat4(out, a, m) { - var x = a[0], y = a[1], z = a[2], - w = m[3] * x + m[7] * y + m[11] * z + m[15] - w = w || 1.0 - out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w - out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w - out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w - return out -} -},{}],373:[function(_dereq_,module,exports){ -module.exports = transformQuat; - -/** - * Transforms the vec3 with a quat - * - * @param {vec3} out the receiving vector - * @param {vec3} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec3} out - */ -function transformQuat(out, a, q) { - // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations - - var x = a[0], y = a[1], z = a[2], - qx = q[0], qy = q[1], qz = q[2], qw = q[3], - - // calculate quat * vec - ix = qw * x + qy * z - qz * y, - iy = qw * y + qz * x - qx * z, - iz = qw * z + qx * y - qy * x, - iw = -qx * x - qy * y - qz * z - - // calculate result * inverse quat - out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy - out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz - out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx - return out -} -},{}],374:[function(_dereq_,module,exports){ -module.exports = add - -/** - * Adds two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -function add (out, a, b) { - out[0] = a[0] + b[0] - out[1] = a[1] + b[1] - out[2] = a[2] + b[2] - out[3] = a[3] + b[3] - return out -} - -},{}],375:[function(_dereq_,module,exports){ -module.exports = clone - -/** - * Creates a new vec4 initialized with values from an existing vector - * - * @param {vec4} a vector to clone - * @returns {vec4} a new 4D vector - */ -function clone (a) { - var out = new Float32Array(4) - out[0] = a[0] - out[1] = a[1] - out[2] = a[2] - out[3] = a[3] - return out -} - -},{}],376:[function(_dereq_,module,exports){ -module.exports = copy - -/** - * Copy the values from one vec4 to another - * - * @param {vec4} out the receiving vector - * @param {vec4} a the source vector - * @returns {vec4} out - */ -function copy (out, a) { - out[0] = a[0] - out[1] = a[1] - out[2] = a[2] - out[3] = a[3] - return out -} - -},{}],377:[function(_dereq_,module,exports){ -module.exports = create - -/** - * Creates a new, empty vec4 - * - * @returns {vec4} a new 4D vector - */ -function create () { - var out = new Float32Array(4) - out[0] = 0 - out[1] = 0 - out[2] = 0 - out[3] = 0 - return out -} - -},{}],378:[function(_dereq_,module,exports){ -module.exports = distance - -/** - * Calculates the euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} distance between a and b - */ -function distance (a, b) { - var x = b[0] - a[0], - y = b[1] - a[1], - z = b[2] - a[2], - w = b[3] - a[3] - return Math.sqrt(x * x + y * y + z * z + w * w) -} - -},{}],379:[function(_dereq_,module,exports){ -module.exports = divide - -/** - * Divides two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -function divide (out, a, b) { - out[0] = a[0] / b[0] - out[1] = a[1] / b[1] - out[2] = a[2] / b[2] - out[3] = a[3] / b[3] - return out -} - -},{}],380:[function(_dereq_,module,exports){ -module.exports = dot - -/** - * Calculates the dot product of two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} dot product of a and b - */ -function dot (a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] -} - -},{}],381:[function(_dereq_,module,exports){ -module.exports = fromValues - -/** - * Creates a new vec4 initialized with the given values - * - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} a new 4D vector - */ -function fromValues (x, y, z, w) { - var out = new Float32Array(4) - out[0] = x - out[1] = y - out[2] = z - out[3] = w - return out -} - -},{}],382:[function(_dereq_,module,exports){ -module.exports = { - create: _dereq_('./create'), - clone: _dereq_('./clone'), - fromValues: _dereq_('./fromValues'), - copy: _dereq_('./copy'), - set: _dereq_('./set'), - add: _dereq_('./add'), - subtract: _dereq_('./subtract'), - multiply: _dereq_('./multiply'), - divide: _dereq_('./divide'), - min: _dereq_('./min'), - max: _dereq_('./max'), - scale: _dereq_('./scale'), - scaleAndAdd: _dereq_('./scaleAndAdd'), - distance: _dereq_('./distance'), - squaredDistance: _dereq_('./squaredDistance'), - length: _dereq_('./length'), - squaredLength: _dereq_('./squaredLength'), - negate: _dereq_('./negate'), - inverse: _dereq_('./inverse'), - normalize: _dereq_('./normalize'), - dot: _dereq_('./dot'), - lerp: _dereq_('./lerp'), - random: _dereq_('./random'), - transformMat4: _dereq_('./transformMat4'), - transformQuat: _dereq_('./transformQuat') -} - -},{"./add":374,"./clone":375,"./copy":376,"./create":377,"./distance":378,"./divide":379,"./dot":380,"./fromValues":381,"./inverse":383,"./length":384,"./lerp":385,"./max":386,"./min":387,"./multiply":388,"./negate":389,"./normalize":390,"./random":391,"./scale":392,"./scaleAndAdd":393,"./set":394,"./squaredDistance":395,"./squaredLength":396,"./subtract":397,"./transformMat4":398,"./transformQuat":399}],383:[function(_dereq_,module,exports){ -module.exports = inverse - -/** - * Returns the inverse of the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to invert - * @returns {vec4} out - */ -function inverse (out, a) { - out[0] = 1.0 / a[0] - out[1] = 1.0 / a[1] - out[2] = 1.0 / a[2] - out[3] = 1.0 / a[3] - return out -} - -},{}],384:[function(_dereq_,module,exports){ -module.exports = length - -/** - * Calculates the length of a vec4 - * - * @param {vec4} a vector to calculate length of - * @returns {Number} length of a - */ -function length (a) { - var x = a[0], - y = a[1], - z = a[2], - w = a[3] - return Math.sqrt(x * x + y * y + z * z + w * w) -} - -},{}],385:[function(_dereq_,module,exports){ -module.exports = lerp - -/** - * Performs a linear interpolation between two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} t interpolation amount between the two inputs - * @returns {vec4} out - */ -function lerp (out, a, b, t) { - var ax = a[0], - ay = a[1], - az = a[2], - aw = a[3] - out[0] = ax + t * (b[0] - ax) - out[1] = ay + t * (b[1] - ay) - out[2] = az + t * (b[2] - az) - out[3] = aw + t * (b[3] - aw) - return out -} - -},{}],386:[function(_dereq_,module,exports){ -module.exports = max - -/** - * Returns the maximum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -function max (out, a, b) { - out[0] = Math.max(a[0], b[0]) - out[1] = Math.max(a[1], b[1]) - out[2] = Math.max(a[2], b[2]) - out[3] = Math.max(a[3], b[3]) - return out -} - -},{}],387:[function(_dereq_,module,exports){ -module.exports = min - -/** - * Returns the minimum of two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -function min (out, a, b) { - out[0] = Math.min(a[0], b[0]) - out[1] = Math.min(a[1], b[1]) - out[2] = Math.min(a[2], b[2]) - out[3] = Math.min(a[3], b[3]) - return out -} - -},{}],388:[function(_dereq_,module,exports){ -module.exports = multiply - -/** - * Multiplies two vec4's - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -function multiply (out, a, b) { - out[0] = a[0] * b[0] - out[1] = a[1] * b[1] - out[2] = a[2] * b[2] - out[3] = a[3] * b[3] - return out -} - -},{}],389:[function(_dereq_,module,exports){ -module.exports = negate - -/** - * Negates the components of a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to negate - * @returns {vec4} out - */ -function negate (out, a) { - out[0] = -a[0] - out[1] = -a[1] - out[2] = -a[2] - out[3] = -a[3] - return out -} - -},{}],390:[function(_dereq_,module,exports){ -module.exports = normalize - -/** - * Normalize a vec4 - * - * @param {vec4} out the receiving vector - * @param {vec4} a vector to normalize - * @returns {vec4} out - */ -function normalize (out, a) { - var x = a[0], - y = a[1], - z = a[2], - w = a[3] - var len = x * x + y * y + z * z + w * w - if (len > 0) { - len = 1 / Math.sqrt(len) - out[0] = x * len - out[1] = y * len - out[2] = z * len - out[3] = w * len - } - return out -} - -},{}],391:[function(_dereq_,module,exports){ -var vecNormalize = _dereq_('./normalize') -var vecScale = _dereq_('./scale') - -module.exports = random - -/** - * Generates a random vector with the given scale - * - * @param {vec4} out the receiving vector - * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned - * @returns {vec4} out - */ -function random (out, scale) { - scale = scale || 1.0 - - // TODO: This is a pretty awful way of doing this. Find something better. - out[0] = Math.random() - out[1] = Math.random() - out[2] = Math.random() - out[3] = Math.random() - vecNormalize(out, out) - vecScale(out, out, scale) - return out -} - -},{"./normalize":390,"./scale":392}],392:[function(_dereq_,module,exports){ -module.exports = scale - -/** - * Scales a vec4 by a scalar number - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to scale - * @param {Number} b amount to scale the vector by - * @returns {vec4} out - */ -function scale (out, a, b) { - out[0] = a[0] * b - out[1] = a[1] * b - out[2] = a[2] * b - out[3] = a[3] * b - return out -} - -},{}],393:[function(_dereq_,module,exports){ -module.exports = scaleAndAdd - -/** - * Adds two vec4's after scaling the second operand by a scalar value - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @param {Number} scale the amount to scale b by before adding - * @returns {vec4} out - */ -function scaleAndAdd (out, a, b, scale) { - out[0] = a[0] + (b[0] * scale) - out[1] = a[1] + (b[1] * scale) - out[2] = a[2] + (b[2] * scale) - out[3] = a[3] + (b[3] * scale) - return out -} - -},{}],394:[function(_dereq_,module,exports){ -module.exports = set - -/** - * Set the components of a vec4 to the given values - * - * @param {vec4} out the receiving vector - * @param {Number} x X component - * @param {Number} y Y component - * @param {Number} z Z component - * @param {Number} w W component - * @returns {vec4} out - */ -function set (out, x, y, z, w) { - out[0] = x - out[1] = y - out[2] = z - out[3] = w - return out -} - -},{}],395:[function(_dereq_,module,exports){ -module.exports = squaredDistance - -/** - * Calculates the squared euclidian distance between two vec4's - * - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {Number} squared distance between a and b - */ -function squaredDistance (a, b) { - var x = b[0] - a[0], - y = b[1] - a[1], - z = b[2] - a[2], - w = b[3] - a[3] - return x * x + y * y + z * z + w * w -} - -},{}],396:[function(_dereq_,module,exports){ -module.exports = squaredLength - -/** - * Calculates the squared length of a vec4 - * - * @param {vec4} a vector to calculate squared length of - * @returns {Number} squared length of a - */ -function squaredLength (a) { - var x = a[0], - y = a[1], - z = a[2], - w = a[3] - return x * x + y * y + z * z + w * w -} - -},{}],397:[function(_dereq_,module,exports){ -module.exports = subtract - -/** - * Subtracts vector b from vector a - * - * @param {vec4} out the receiving vector - * @param {vec4} a the first operand - * @param {vec4} b the second operand - * @returns {vec4} out - */ -function subtract (out, a, b) { - out[0] = a[0] - b[0] - out[1] = a[1] - b[1] - out[2] = a[2] - b[2] - out[3] = a[3] - b[3] - return out -} - -},{}],398:[function(_dereq_,module,exports){ -module.exports = transformMat4 - -/** - * Transforms the vec4 with a mat4. - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {mat4} m matrix to transform with - * @returns {vec4} out - */ -function transformMat4 (out, a, m) { - var x = a[0], y = a[1], z = a[2], w = a[3] - out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w - out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w - out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w - out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w - return out -} - -},{}],399:[function(_dereq_,module,exports){ -module.exports = transformQuat - -/** - * Transforms the vec4 with a quat - * - * @param {vec4} out the receiving vector - * @param {vec4} a the vector to transform - * @param {quat} q quaternion to transform with - * @returns {vec4} out - */ -function transformQuat (out, a, q) { - var x = a[0], y = a[1], z = a[2], - qx = q[0], qy = q[1], qz = q[2], qw = q[3], - - // calculate quat * vec - ix = qw * x + qy * z - qz * y, - iy = qw * y + qz * x - qx * z, - iz = qw * z + qx * y - qy * x, - iw = -qx * x - qy * y - qz * z - - // calculate result * inverse quat - out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy - out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz - out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx - out[3] = a[3] - return out -} - -},{}],400:[function(_dereq_,module,exports){ -module.exports = decodeFloat - -var UINT8_VIEW = new Uint8Array(4) -var FLOAT_VIEW = new Float32Array(UINT8_VIEW.buffer) - -function decodeFloat(x, y, z, w) { - UINT8_VIEW[0] = w - UINT8_VIEW[1] = z - UINT8_VIEW[2] = y - UINT8_VIEW[3] = x - return FLOAT_VIEW[0] -} - -},{}],401:[function(_dereq_,module,exports){ -var tokenize = _dereq_('glsl-tokenizer') -var atob = _dereq_('atob-lite') - -module.exports = getName - -function getName(src) { - var tokens = Array.isArray(src) - ? src - : tokenize(src) - - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i] - if (token.type !== 'preprocessor') continue - var match = token.data.match(/\#define\s+SHADER_NAME(_B64)?\s+(.+)$/) - if (!match) continue - if (!match[2]) continue - - var b64 = match[1] - var name = match[2] - - return (b64 ? atob(name) : name).trim() - } -} - -},{"atob-lite":72,"glsl-tokenizer":408}],402:[function(_dereq_,module,exports){ -module.exports = tokenize - -var literals100 = _dereq_('./lib/literals') - , operators = _dereq_('./lib/operators') - , builtins100 = _dereq_('./lib/builtins') - , literals300es = _dereq_('./lib/literals-300es') - , builtins300es = _dereq_('./lib/builtins-300es') - -var NORMAL = 999 // <-- never emitted - , TOKEN = 9999 // <-- never emitted - , BLOCK_COMMENT = 0 - , LINE_COMMENT = 1 - , PREPROCESSOR = 2 - , OPERATOR = 3 - , INTEGER = 4 - , FLOAT = 5 - , IDENT = 6 - , BUILTIN = 7 - , KEYWORD = 8 - , WHITESPACE = 9 - , EOF = 10 - , HEX = 11 - -var map = [ - 'block-comment' - , 'line-comment' - , 'preprocessor' - , 'operator' - , 'integer' - , 'float' - , 'ident' - , 'builtin' - , 'keyword' - , 'whitespace' - , 'eof' - , 'integer' -] - -function tokenize(opt) { - var i = 0 - , total = 0 - , mode = NORMAL - , c - , last - , content = [] - , tokens = [] - , token_idx = 0 - , token_offs = 0 - , line = 1 - , col = 0 - , start = 0 - , isnum = false - , isoperator = false - , input = '' - , len - - opt = opt || {} - var allBuiltins = builtins100 - var allLiterals = literals100 - if (opt.version === '300 es') { - allBuiltins = builtins300es - allLiterals = literals300es - } - - return function(data) { - tokens = [] - if (data !== null) return write(data.replace ? data.replace(/\r\n/g, '\n') : data) - return end() - } - - function token(data) { - if (data.length) { - tokens.push({ - type: map[mode] - , data: data - , position: start - , line: line - , column: col - }) - } - } - - function write(chunk) { - i = 0 - input += chunk - len = input.length - - var last - - while(c = input[i], i < len) { - last = i - - switch(mode) { - case BLOCK_COMMENT: i = block_comment(); break - case LINE_COMMENT: i = line_comment(); break - case PREPROCESSOR: i = preprocessor(); break - case OPERATOR: i = operator(); break - case INTEGER: i = integer(); break - case HEX: i = hex(); break - case FLOAT: i = decimal(); break - case TOKEN: i = readtoken(); break - case WHITESPACE: i = whitespace(); break - case NORMAL: i = normal(); break - } - - if(last !== i) { - switch(input[last]) { - case '\n': col = 0; ++line; break - default: ++col; break - } - } - } - - total += i - input = input.slice(i) - return tokens - } - - function end(chunk) { - if(content.length) { - token(content.join('')) - } - - mode = EOF - token('(eof)') - return tokens - } - - function normal() { - content = content.length ? [] : content - - if(last === '/' && c === '*') { - start = total + i - 1 - mode = BLOCK_COMMENT - last = c - return i + 1 - } - - if(last === '/' && c === '/') { - start = total + i - 1 - mode = LINE_COMMENT - last = c - return i + 1 - } - - if(c === '#') { - mode = PREPROCESSOR - start = total + i - return i - } - - if(/\s/.test(c)) { - mode = WHITESPACE - start = total + i - return i - } - - isnum = /\d/.test(c) - isoperator = /[^\w_]/.test(c) - - start = total + i - mode = isnum ? INTEGER : isoperator ? OPERATOR : TOKEN - return i - } - - function whitespace() { - if(/[^\s]/g.test(c)) { - token(content.join('')) - mode = NORMAL - return i - } - content.push(c) - last = c - return i + 1 - } - - function preprocessor() { - if((c === '\r' || c === '\n') && last !== '\\') { - token(content.join('')) - mode = NORMAL - return i - } - content.push(c) - last = c - return i + 1 - } - - function line_comment() { - return preprocessor() - } - - function block_comment() { - if(c === '/' && last === '*') { - content.push(c) - token(content.join('')) - mode = NORMAL - return i + 1 - } - - content.push(c) - last = c - return i + 1 - } - - function operator() { - if(last === '.' && /\d/.test(c)) { - mode = FLOAT - return i - } - - if(last === '/' && c === '*') { - mode = BLOCK_COMMENT - return i - } - - if(last === '/' && c === '/') { - mode = LINE_COMMENT - return i - } - - if(c === '.' && content.length) { - while(determine_operator(content)); - - mode = FLOAT - return i - } - - if(c === ';' || c === ')' || c === '(') { - if(content.length) while(determine_operator(content)); - token(c) - mode = NORMAL - return i + 1 - } - - var is_composite_operator = content.length === 2 && c !== '=' - if(/[\w_\d\s]/.test(c) || is_composite_operator) { - while(determine_operator(content)); - mode = NORMAL - return i - } - - content.push(c) - last = c - return i + 1 - } - - function determine_operator(buf) { - var j = 0 - , idx - , res - - do { - idx = operators.indexOf(buf.slice(0, buf.length + j).join('')) - res = operators[idx] - - if(idx === -1) { - if(j-- + buf.length > 0) continue - res = buf.slice(0, 1).join('') - } - - token(res) - - start += res.length - content = content.slice(res.length) - return content.length - } while(1) - } - - function hex() { - if(/[^a-fA-F0-9]/.test(c)) { - token(content.join('')) - mode = NORMAL - return i - } - - content.push(c) - last = c - return i + 1 - } - - function integer() { - if(c === '.') { - content.push(c) - mode = FLOAT - last = c - return i + 1 - } - - if(/[eE]/.test(c)) { - content.push(c) - mode = FLOAT - last = c - return i + 1 - } - - if(c === 'x' && content.length === 1 && content[0] === '0') { - mode = HEX - content.push(c) - last = c - return i + 1 - } - - if(/[^\d]/.test(c)) { - token(content.join('')) - mode = NORMAL - return i - } - - content.push(c) - last = c - return i + 1 - } - - function decimal() { - if(c === 'f') { - content.push(c) - last = c - i += 1 - } - - if(/[eE]/.test(c)) { - content.push(c) - last = c - return i + 1 - } - - if (c === '-' && /[eE]/.test(last)) { - content.push(c) - last = c - return i + 1 - } - - if(/[^\d]/.test(c)) { - token(content.join('')) - mode = NORMAL - return i - } - - content.push(c) - last = c - return i + 1 - } - - function readtoken() { - if(/[^\d\w_]/.test(c)) { - var contentstr = content.join('') - if(allLiterals.indexOf(contentstr) > -1) { - mode = KEYWORD - } else if(allBuiltins.indexOf(contentstr) > -1) { - mode = BUILTIN - } else { - mode = IDENT - } - token(content.join('')) - mode = NORMAL - return i - } - content.push(c) - last = c - return i + 1 - } -} - -},{"./lib/builtins":404,"./lib/builtins-300es":403,"./lib/literals":406,"./lib/literals-300es":405,"./lib/operators":407}],403:[function(_dereq_,module,exports){ -// 300es builtins/reserved words that were previously valid in v100 -var v100 = _dereq_('./builtins') - -// The texture2D|Cube functions have been removed -// And the gl_ features are updated -v100 = v100.slice().filter(function (b) { - return !/^(gl\_|texture)/.test(b) -}) - -module.exports = v100.concat([ - // the updated gl_ constants - 'gl_VertexID' - , 'gl_InstanceID' - , 'gl_Position' - , 'gl_PointSize' - , 'gl_FragCoord' - , 'gl_FrontFacing' - , 'gl_FragDepth' - , 'gl_PointCoord' - , 'gl_MaxVertexAttribs' - , 'gl_MaxVertexUniformVectors' - , 'gl_MaxVertexOutputVectors' - , 'gl_MaxFragmentInputVectors' - , 'gl_MaxVertexTextureImageUnits' - , 'gl_MaxCombinedTextureImageUnits' - , 'gl_MaxTextureImageUnits' - , 'gl_MaxFragmentUniformVectors' - , 'gl_MaxDrawBuffers' - , 'gl_MinProgramTexelOffset' - , 'gl_MaxProgramTexelOffset' - , 'gl_DepthRangeParameters' - , 'gl_DepthRange' - - // other builtins - , 'trunc' - , 'round' - , 'roundEven' - , 'isnan' - , 'isinf' - , 'floatBitsToInt' - , 'floatBitsToUint' - , 'intBitsToFloat' - , 'uintBitsToFloat' - , 'packSnorm2x16' - , 'unpackSnorm2x16' - , 'packUnorm2x16' - , 'unpackUnorm2x16' - , 'packHalf2x16' - , 'unpackHalf2x16' - , 'outerProduct' - , 'transpose' - , 'determinant' - , 'inverse' - , 'texture' - , 'textureSize' - , 'textureProj' - , 'textureLod' - , 'textureOffset' - , 'texelFetch' - , 'texelFetchOffset' - , 'textureProjOffset' - , 'textureLodOffset' - , 'textureProjLod' - , 'textureProjLodOffset' - , 'textureGrad' - , 'textureGradOffset' - , 'textureProjGrad' - , 'textureProjGradOffset' -]) - -},{"./builtins":404}],404:[function(_dereq_,module,exports){ -module.exports = [ - // Keep this list sorted - 'abs' - , 'acos' - , 'all' - , 'any' - , 'asin' - , 'atan' - , 'ceil' - , 'clamp' - , 'cos' - , 'cross' - , 'dFdx' - , 'dFdy' - , 'degrees' - , 'distance' - , 'dot' - , 'equal' - , 'exp' - , 'exp2' - , 'faceforward' - , 'floor' - , 'fract' - , 'gl_BackColor' - , 'gl_BackLightModelProduct' - , 'gl_BackLightProduct' - , 'gl_BackMaterial' - , 'gl_BackSecondaryColor' - , 'gl_ClipPlane' - , 'gl_ClipVertex' - , 'gl_Color' - , 'gl_DepthRange' - , 'gl_DepthRangeParameters' - , 'gl_EyePlaneQ' - , 'gl_EyePlaneR' - , 'gl_EyePlaneS' - , 'gl_EyePlaneT' - , 'gl_Fog' - , 'gl_FogCoord' - , 'gl_FogFragCoord' - , 'gl_FogParameters' - , 'gl_FragColor' - , 'gl_FragCoord' - , 'gl_FragData' - , 'gl_FragDepth' - , 'gl_FragDepthEXT' - , 'gl_FrontColor' - , 'gl_FrontFacing' - , 'gl_FrontLightModelProduct' - , 'gl_FrontLightProduct' - , 'gl_FrontMaterial' - , 'gl_FrontSecondaryColor' - , 'gl_LightModel' - , 'gl_LightModelParameters' - , 'gl_LightModelProducts' - , 'gl_LightProducts' - , 'gl_LightSource' - , 'gl_LightSourceParameters' - , 'gl_MaterialParameters' - , 'gl_MaxClipPlanes' - , 'gl_MaxCombinedTextureImageUnits' - , 'gl_MaxDrawBuffers' - , 'gl_MaxFragmentUniformComponents' - , 'gl_MaxLights' - , 'gl_MaxTextureCoords' - , 'gl_MaxTextureImageUnits' - , 'gl_MaxTextureUnits' - , 'gl_MaxVaryingFloats' - , 'gl_MaxVertexAttribs' - , 'gl_MaxVertexTextureImageUnits' - , 'gl_MaxVertexUniformComponents' - , 'gl_ModelViewMatrix' - , 'gl_ModelViewMatrixInverse' - , 'gl_ModelViewMatrixInverseTranspose' - , 'gl_ModelViewMatrixTranspose' - , 'gl_ModelViewProjectionMatrix' - , 'gl_ModelViewProjectionMatrixInverse' - , 'gl_ModelViewProjectionMatrixInverseTranspose' - , 'gl_ModelViewProjectionMatrixTranspose' - , 'gl_MultiTexCoord0' - , 'gl_MultiTexCoord1' - , 'gl_MultiTexCoord2' - , 'gl_MultiTexCoord3' - , 'gl_MultiTexCoord4' - , 'gl_MultiTexCoord5' - , 'gl_MultiTexCoord6' - , 'gl_MultiTexCoord7' - , 'gl_Normal' - , 'gl_NormalMatrix' - , 'gl_NormalScale' - , 'gl_ObjectPlaneQ' - , 'gl_ObjectPlaneR' - , 'gl_ObjectPlaneS' - , 'gl_ObjectPlaneT' - , 'gl_Point' - , 'gl_PointCoord' - , 'gl_PointParameters' - , 'gl_PointSize' - , 'gl_Position' - , 'gl_ProjectionMatrix' - , 'gl_ProjectionMatrixInverse' - , 'gl_ProjectionMatrixInverseTranspose' - , 'gl_ProjectionMatrixTranspose' - , 'gl_SecondaryColor' - , 'gl_TexCoord' - , 'gl_TextureEnvColor' - , 'gl_TextureMatrix' - , 'gl_TextureMatrixInverse' - , 'gl_TextureMatrixInverseTranspose' - , 'gl_TextureMatrixTranspose' - , 'gl_Vertex' - , 'greaterThan' - , 'greaterThanEqual' - , 'inversesqrt' - , 'length' - , 'lessThan' - , 'lessThanEqual' - , 'log' - , 'log2' - , 'matrixCompMult' - , 'max' - , 'min' - , 'mix' - , 'mod' - , 'normalize' - , 'not' - , 'notEqual' - , 'pow' - , 'radians' - , 'reflect' - , 'refract' - , 'sign' - , 'sin' - , 'smoothstep' - , 'sqrt' - , 'step' - , 'tan' - , 'texture2D' - , 'texture2DLod' - , 'texture2DProj' - , 'texture2DProjLod' - , 'textureCube' - , 'textureCubeLod' - , 'texture2DLodEXT' - , 'texture2DProjLodEXT' - , 'textureCubeLodEXT' - , 'texture2DGradEXT' - , 'texture2DProjGradEXT' - , 'textureCubeGradEXT' -] - -},{}],405:[function(_dereq_,module,exports){ -var v100 = _dereq_('./literals') - -module.exports = v100.slice().concat([ - 'layout' - , 'centroid' - , 'smooth' - , 'case' - , 'mat2x2' - , 'mat2x3' - , 'mat2x4' - , 'mat3x2' - , 'mat3x3' - , 'mat3x4' - , 'mat4x2' - , 'mat4x3' - , 'mat4x4' - , 'uint' - , 'uvec2' - , 'uvec3' - , 'uvec4' - , 'samplerCubeShadow' - , 'sampler2DArray' - , 'sampler2DArrayShadow' - , 'isampler2D' - , 'isampler3D' - , 'isamplerCube' - , 'isampler2DArray' - , 'usampler2D' - , 'usampler3D' - , 'usamplerCube' - , 'usampler2DArray' - , 'coherent' - , 'restrict' - , 'readonly' - , 'writeonly' - , 'resource' - , 'atomic_uint' - , 'noperspective' - , 'patch' - , 'sample' - , 'subroutine' - , 'common' - , 'partition' - , 'active' - , 'filter' - , 'image1D' - , 'image2D' - , 'image3D' - , 'imageCube' - , 'iimage1D' - , 'iimage2D' - , 'iimage3D' - , 'iimageCube' - , 'uimage1D' - , 'uimage2D' - , 'uimage3D' - , 'uimageCube' - , 'image1DArray' - , 'image2DArray' - , 'iimage1DArray' - , 'iimage2DArray' - , 'uimage1DArray' - , 'uimage2DArray' - , 'image1DShadow' - , 'image2DShadow' - , 'image1DArrayShadow' - , 'image2DArrayShadow' - , 'imageBuffer' - , 'iimageBuffer' - , 'uimageBuffer' - , 'sampler1DArray' - , 'sampler1DArrayShadow' - , 'isampler1D' - , 'isampler1DArray' - , 'usampler1D' - , 'usampler1DArray' - , 'isampler2DRect' - , 'usampler2DRect' - , 'samplerBuffer' - , 'isamplerBuffer' - , 'usamplerBuffer' - , 'sampler2DMS' - , 'isampler2DMS' - , 'usampler2DMS' - , 'sampler2DMSArray' - , 'isampler2DMSArray' - , 'usampler2DMSArray' -]) - -},{"./literals":406}],406:[function(_dereq_,module,exports){ -module.exports = [ - // current - 'precision' - , 'highp' - , 'mediump' - , 'lowp' - , 'attribute' - , 'const' - , 'uniform' - , 'varying' - , 'break' - , 'continue' - , 'do' - , 'for' - , 'while' - , 'if' - , 'else' - , 'in' - , 'out' - , 'inout' - , 'float' - , 'int' - , 'void' - , 'bool' - , 'true' - , 'false' - , 'discard' - , 'return' - , 'mat2' - , 'mat3' - , 'mat4' - , 'vec2' - , 'vec3' - , 'vec4' - , 'ivec2' - , 'ivec3' - , 'ivec4' - , 'bvec2' - , 'bvec3' - , 'bvec4' - , 'sampler1D' - , 'sampler2D' - , 'sampler3D' - , 'samplerCube' - , 'sampler1DShadow' - , 'sampler2DShadow' - , 'struct' - - // future - , 'asm' - , 'class' - , 'union' - , 'enum' - , 'typedef' - , 'template' - , 'this' - , 'packed' - , 'goto' - , 'switch' - , 'default' - , 'inline' - , 'noinline' - , 'volatile' - , 'public' - , 'static' - , 'extern' - , 'external' - , 'interface' - , 'long' - , 'short' - , 'double' - , 'half' - , 'fixed' - , 'unsigned' - , 'input' - , 'output' - , 'hvec2' - , 'hvec3' - , 'hvec4' - , 'dvec2' - , 'dvec3' - , 'dvec4' - , 'fvec2' - , 'fvec3' - , 'fvec4' - , 'sampler2DRect' - , 'sampler3DRect' - , 'sampler2DRectShadow' - , 'sizeof' - , 'cast' - , 'namespace' - , 'using' -] - -},{}],407:[function(_dereq_,module,exports){ -module.exports = [ - '<<=' - , '>>=' - , '++' - , '--' - , '<<' - , '>>' - , '<=' - , '>=' - , '==' - , '!=' - , '&&' - , '||' - , '+=' - , '-=' - , '*=' - , '/=' - , '%=' - , '&=' - , '^^' - , '^=' - , '|=' - , '(' - , ')' - , '[' - , ']' - , '.' - , '!' - , '~' - , '*' - , '/' - , '%' - , '+' - , '-' - , '<' - , '>' - , '&' - , '^' - , '|' - , '?' - , ':' - , '=' - , ',' - , ';' - , '{' - , '}' -] - -},{}],408:[function(_dereq_,module,exports){ -var tokenize = _dereq_('./index') - -module.exports = tokenizeString - -function tokenizeString(str, opt) { - var generator = tokenize(opt) - var tokens = [] - - tokens = tokens.concat(generator(str)) - tokens = tokens.concat(generator(null)) - - return tokens -} - -},{"./index":402}],409:[function(_dereq_,module,exports){ -module.exports = function(strings) { - if (typeof strings === 'string') strings = [strings] - var exprs = [].slice.call(arguments,1) - var parts = [] - for (var i = 0; i < strings.length-1; i++) { - parts.push(strings[i], exprs[i] || '') - } - parts.push(strings[i]) - return parts.join('') -} - -},{}],410:[function(_dereq_,module,exports){ -(function (global){ -'use strict' - -var isBrowser = _dereq_('is-browser') -var hasHover - -if (typeof global.matchMedia === 'function') { - hasHover = !global.matchMedia('(hover: none)').matches -} -else { - hasHover = isBrowser -} - -module.exports = hasHover - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"is-browser":417}],411:[function(_dereq_,module,exports){ -'use strict' - -var isBrowser = _dereq_('is-browser') - -function detect() { - var supported = false - - try { - var opts = Object.defineProperty({}, 'passive', { - get: function() { - supported = true - } - }) - - window.addEventListener('test', null, opts) - window.removeEventListener('test', null, opts) - } catch(e) { - supported = false - } - - return supported -} - -module.exports = isBrowser && detect() - -},{"is-browser":417}],412:[function(_dereq_,module,exports){ -exports.read = function (buffer, offset, isLE, mLen, nBytes) { - var e, m - var eLen = (nBytes * 8) - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var nBits = -7 - var i = isLE ? (nBytes - 1) : 0 - var d = isLE ? -1 : 1 - var s = buffer[offset + i] - - i += d - - e = s & ((1 << (-nBits)) - 1) - s >>= (-nBits) - nBits += eLen - for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} - - m = e & ((1 << (-nBits)) - 1) - e >>= (-nBits) - nBits += mLen - for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} - - if (e === 0) { - e = 1 - eBias - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity) - } else { - m = m + Math.pow(2, mLen) - e = e - eBias - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen) -} - -exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c - var eLen = (nBytes * 8) - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) - var i = isLE ? 0 : (nBytes - 1) - var d = isLE ? 1 : -1 - var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 - - value = Math.abs(value) - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0 - e = eMax - } else { - e = Math.floor(Math.log(value) / Math.LN2) - if (value * (c = Math.pow(2, -e)) < 1) { - e-- - c *= 2 - } - if (e + eBias >= 1) { - value += rt / c - } else { - value += rt * Math.pow(2, 1 - eBias) - } - if (value * c >= 2) { - e++ - c /= 2 - } - - if (e + eBias >= eMax) { - m = 0 - e = eMax - } else if (e + eBias >= 1) { - m = ((value * c) - 1) * Math.pow(2, mLen) - e = e + eBias - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) - e = 0 - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} - - e = (e << mLen) | m - eLen += mLen - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} - - buffer[offset + i - d] |= s * 128 -} - -},{}],413:[function(_dereq_,module,exports){ -"use strict" - -//High level idea: -// 1. Use Clarkson's incremental construction to find convex hull -// 2. Point location in triangulation by jump and walk - -module.exports = incrementalConvexHull - -var orient = _dereq_("robust-orientation") -var compareCell = _dereq_("simplicial-complex").compareCells - -function compareInt(a, b) { - return a - b -} - -function Simplex(vertices, adjacent, boundary) { - this.vertices = vertices - this.adjacent = adjacent - this.boundary = boundary - this.lastVisited = -1 -} - -Simplex.prototype.flip = function() { - var t = this.vertices[0] - this.vertices[0] = this.vertices[1] - this.vertices[1] = t - var u = this.adjacent[0] - this.adjacent[0] = this.adjacent[1] - this.adjacent[1] = u -} - -function GlueFacet(vertices, cell, index) { - this.vertices = vertices - this.cell = cell - this.index = index -} - -function compareGlue(a, b) { - return compareCell(a.vertices, b.vertices) -} - -function bakeOrient(d) { - var code = ["function orient(){var tuple=this.tuple;return test("] - for(var i=0; i<=d; ++i) { - if(i > 0) { - code.push(",") - } - code.push("tuple[", i, "]") - } - code.push(")}return orient") - var proc = new Function("test", code.join("")) - var test = orient[d+1] - if(!test) { - test = orient - } - return proc(test) -} - -var BAKED = [] - -function Triangulation(dimension, vertices, simplices) { - this.dimension = dimension - this.vertices = vertices - this.simplices = simplices - this.interior = simplices.filter(function(c) { - return !c.boundary - }) - - this.tuple = new Array(dimension+1) - for(var i=0; i<=dimension; ++i) { - this.tuple[i] = this.vertices[i] - } - - var o = BAKED[dimension] - if(!o) { - o = BAKED[dimension] = bakeOrient(dimension) - } - this.orient = o -} - -var proto = Triangulation.prototype - -//Degenerate situation where we are on boundary, but coplanar to face -proto.handleBoundaryDegeneracy = function(cell, point) { - var d = this.dimension - var n = this.vertices.length - 1 - var tuple = this.tuple - var verts = this.vertices - - //Dumb solution: Just do dfs from boundary cell until we find any peak, or terminate - var toVisit = [ cell ] - cell.lastVisited = -n - while(toVisit.length > 0) { - cell = toVisit.pop() - var cellVerts = cell.vertices - var cellAdj = cell.adjacent - for(var i=0; i<=d; ++i) { - var neighbor = cellAdj[i] - if(!neighbor.boundary || neighbor.lastVisited <= -n) { - continue - } - var nv = neighbor.vertices - for(var j=0; j<=d; ++j) { - var vv = nv[j] - if(vv < 0) { - tuple[j] = point - } else { - tuple[j] = verts[vv] - } - } - var o = this.orient() - if(o > 0) { - return neighbor - } - neighbor.lastVisited = -n - if(o === 0) { - toVisit.push(neighbor) - } - } - } - return null -} - -proto.walk = function(point, random) { - //Alias local properties - var n = this.vertices.length - 1 - var d = this.dimension - var verts = this.vertices - var tuple = this.tuple - - //Compute initial jump cell - var initIndex = random ? (this.interior.length * Math.random())|0 : (this.interior.length-1) - var cell = this.interior[ initIndex ] - - //Start walking -outerLoop: - while(!cell.boundary) { - var cellVerts = cell.vertices - var cellAdj = cell.adjacent - - for(var i=0; i<=d; ++i) { - tuple[i] = verts[cellVerts[i]] - } - cell.lastVisited = n - - //Find farthest adjacent cell - for(var i=0; i<=d; ++i) { - var neighbor = cellAdj[i] - if(neighbor.lastVisited >= n) { - continue - } - var prev = tuple[i] - tuple[i] = point - var o = this.orient() - tuple[i] = prev - if(o < 0) { - cell = neighbor - continue outerLoop - } else { - if(!neighbor.boundary) { - neighbor.lastVisited = n - } else { - neighbor.lastVisited = -n - } - } - } - return - } - - return cell -} - -proto.addPeaks = function(point, cell) { - var n = this.vertices.length - 1 - var d = this.dimension - var verts = this.vertices - var tuple = this.tuple - var interior = this.interior - var simplices = this.simplices - - //Walking finished at boundary, time to add peaks - var tovisit = [ cell ] - - //Stretch initial boundary cell into a peak - cell.lastVisited = n - cell.vertices[cell.vertices.indexOf(-1)] = n - cell.boundary = false - interior.push(cell) - - //Record a list of all new boundaries created by added peaks so we can glue them together when we are all done - var glueFacets = [] - - //Do a traversal of the boundary walking outward from starting peak - while(tovisit.length > 0) { - //Pop off peak and walk over adjacent cells - var cell = tovisit.pop() - var cellVerts = cell.vertices - var cellAdj = cell.adjacent - var indexOfN = cellVerts.indexOf(n) - if(indexOfN < 0) { - continue - } - - for(var i=0; i<=d; ++i) { - if(i === indexOfN) { - continue - } - - //For each boundary neighbor of the cell - var neighbor = cellAdj[i] - if(!neighbor.boundary || neighbor.lastVisited >= n) { - continue - } - - var nv = neighbor.vertices - - //Test if neighbor is a peak - if(neighbor.lastVisited !== -n) { - //Compute orientation of p relative to each boundary peak - var indexOfNeg1 = 0 - for(var j=0; j<=d; ++j) { - if(nv[j] < 0) { - indexOfNeg1 = j - tuple[j] = point - } else { - tuple[j] = verts[nv[j]] - } - } - var o = this.orient() - - //Test if neighbor cell is also a peak - if(o > 0) { - nv[indexOfNeg1] = n - neighbor.boundary = false - interior.push(neighbor) - tovisit.push(neighbor) - neighbor.lastVisited = n - continue - } else { - neighbor.lastVisited = -n - } - } - - var na = neighbor.adjacent - - //Otherwise, replace neighbor with new face - var vverts = cellVerts.slice() - var vadj = cellAdj.slice() - var ncell = new Simplex(vverts, vadj, true) - simplices.push(ncell) - - //Connect to neighbor - var opposite = na.indexOf(cell) - if(opposite < 0) { - continue - } - na[opposite] = ncell - vadj[indexOfN] = neighbor - - //Connect to cell - vverts[i] = -1 - vadj[i] = cell - cellAdj[i] = ncell - - //Flip facet - ncell.flip() - - //Add to glue list - for(var j=0; j<=d; ++j) { - var uu = vverts[j] - if(uu < 0 || uu === n) { - continue - } - var nface = new Array(d-1) - var nptr = 0 - for(var k=0; k<=d; ++k) { - var vv = vverts[k] - if(vv < 0 || k === j) { - continue - } - nface[nptr++] = vv - } - glueFacets.push(new GlueFacet(nface, ncell, j)) - } - } - } - - //Glue boundary facets together - glueFacets.sort(compareGlue) - - for(var i=0; i+1= 0) { - bcell[ptr++] = cv[j] - } else { - parity = j&1 - } - } - if(parity === (d&1)) { - var t = bcell[0] - bcell[0] = bcell[1] - bcell[1] = t - } - boundary.push(bcell) - } - } - return boundary -} - -function incrementalConvexHull(points, randomSearch) { - var n = points.length - if(n === 0) { - throw new Error("Must have at least d+1 points") - } - var d = points[0].length - if(n <= d) { - throw new Error("Must input at least d+1 points") - } - - //FIXME: This could be degenerate, but need to select d+1 non-coplanar points to bootstrap process - var initialSimplex = points.slice(0, d+1) - - //Make sure initial simplex is positively oriented - var o = orient.apply(void 0, initialSimplex) - if(o === 0) { - throw new Error("Input not in general position") - } - var initialCoords = new Array(d+1) - for(var i=0; i<=d; ++i) { - initialCoords[i] = i - } - if(o < 0) { - initialCoords[0] = 1 - initialCoords[1] = 0 - } - - //Create initial topological index, glue pointers together (kind of messy) - var initialCell = new Simplex(initialCoords, new Array(d+1), false) - var boundary = initialCell.adjacent - var list = new Array(d+2) - for(var i=0; i<=d; ++i) { - var verts = initialCoords.slice() - for(var j=0; j<=d; ++j) { - if(j === i) { - verts[j] = -1 - } - } - var t = verts[0] - verts[0] = verts[1] - verts[1] = t - var cell = new Simplex(verts, new Array(d+1), true) - boundary[i] = cell - list[i] = cell - } - list[d+1] = initialCell - for(var i=0; i<=d; ++i) { - var verts = boundary[i].vertices - var adj = boundary[i].adjacent - for(var j=0; j<=d; ++j) { - var v = verts[j] - if(v < 0) { - adj[j] = initialCell - continue - } - for(var k=0; k<=d; ++k) { - if(boundary[k].vertices.indexOf(v) < 0) { - adj[j] = boundary[k] - } - } - } - } - - //Initialize triangles - var triangles = new Triangulation(d, initialSimplex, list) - - //Insert remaining points - var useRandom = !!randomSearch - for(var i=d+1; i 3*(weight+1)) { - rebuildWithInterval(this, interval) - } else { - this.left.insert(interval) - } - } else { - this.left = createIntervalTree([interval]) - } - } else if(interval[0] > this.mid) { - if(this.right) { - if(4*(this.right.count+1) > 3*(weight+1)) { - rebuildWithInterval(this, interval) - } else { - this.right.insert(interval) - } - } else { - this.right = createIntervalTree([interval]) - } - } else { - var l = bounds.ge(this.leftPoints, interval, compareBegin) - var r = bounds.ge(this.rightPoints, interval, compareEnd) - this.leftPoints.splice(l, 0, interval) - this.rightPoints.splice(r, 0, interval) - } -} - -proto.remove = function(interval) { - var weight = this.count - this.leftPoints - if(interval[1] < this.mid) { - if(!this.left) { - return NOT_FOUND - } - var rw = this.right ? this.right.count : 0 - if(4 * rw > 3 * (weight-1)) { - return rebuildWithoutInterval(this, interval) - } - var r = this.left.remove(interval) - if(r === EMPTY) { - this.left = null - this.count -= 1 - return SUCCESS - } else if(r === SUCCESS) { - this.count -= 1 - } - return r - } else if(interval[0] > this.mid) { - if(!this.right) { - return NOT_FOUND - } - var lw = this.left ? this.left.count : 0 - if(4 * lw > 3 * (weight-1)) { - return rebuildWithoutInterval(this, interval) - } - var r = this.right.remove(interval) - if(r === EMPTY) { - this.right = null - this.count -= 1 - return SUCCESS - } else if(r === SUCCESS) { - this.count -= 1 - } - return r - } else { - if(this.count === 1) { - if(this.leftPoints[0] === interval) { - return EMPTY - } else { - return NOT_FOUND - } - } - if(this.leftPoints.length === 1 && this.leftPoints[0] === interval) { - if(this.left && this.right) { - var p = this - var n = this.left - while(n.right) { - p = n - n = n.right - } - if(p === this) { - n.right = this.right - } else { - var l = this.left - var r = this.right - p.count -= n.count - p.right = n.left - n.left = l - n.right = r - } - copy(this, n) - this.count = (this.left?this.left.count:0) + (this.right?this.right.count:0) + this.leftPoints.length - } else if(this.left) { - copy(this, this.left) - } else { - copy(this, this.right) - } - return SUCCESS - } - for(var l = bounds.ge(this.leftPoints, interval, compareBegin); l=0 && arr[i][1] >= lo; --i) { - var r = cb(arr[i]) - if(r) { return r } - } -} - -function reportRange(arr, cb) { - for(var i=0; i this.mid) { - if(this.right) { - var r = this.right.queryPoint(x, cb) - if(r) { return r } - } - return reportRightRange(this.rightPoints, x, cb) - } else { - return reportRange(this.leftPoints, cb) - } -} - -proto.queryInterval = function(lo, hi, cb) { - if(lo < this.mid && this.left) { - var r = this.left.queryInterval(lo, hi, cb) - if(r) { return r } - } - if(hi > this.mid && this.right) { - var r = this.right.queryInterval(lo, hi, cb) - if(r) { return r } - } - if(hi < this.mid) { - return reportLeftRange(this.leftPoints, hi, cb) - } else if(lo > this.mid) { - return reportRightRange(this.rightPoints, lo, cb) - } else { - return reportRange(this.leftPoints, cb) - } -} - -function compareNumbers(a, b) { - return a - b -} - -function compareBegin(a, b) { - var d = a[0] - b[0] - if(d) { return d } - return a[1] - b[1] -} - -function compareEnd(a, b) { - var d = a[1] - b[1] - if(d) { return d } - return a[0] - b[0] -} - -function createIntervalTree(intervals) { - if(intervals.length === 0) { - return null - } - var pts = [] - for(var i=0; i>1] - - var leftIntervals = [] - var rightIntervals = [] - var centerIntervals = [] - for(var i=0; i - * @license MIT - */ - -// The _isBuffer check is for Safari 5-7 support, because it's missing -// Object.prototype.constructor. Remove this eventually -module.exports = function (obj) { - return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) -} - -function isBuffer (obj) { - return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -} - -// For Node v0.10 support. Remove this eventually. -function isSlowBuffer (obj) { - return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) -} - -},{}],419:[function(_dereq_,module,exports){ -'use strict'; -module.exports = typeof navigator !== 'undefined' && - (/MSIE/.test(navigator.userAgent) || /Trident\//.test(navigator.appVersion)); - -},{}],420:[function(_dereq_,module,exports){ -'use strict' - -module.exports = isMobile; -module.exports.isMobile = isMobile; - -var mobileRE = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i; - -var tabletRE = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino|android|ipad|playbook|silk/i; - -function isMobile (opts) { - if (!opts) opts = {} - var ua = opts.ua - if (!ua && typeof navigator !== 'undefined') ua = navigator.userAgent; - if (ua && ua.headers && typeof ua.headers['user-agent'] === 'string') { - ua = ua.headers['user-agent']; - } - if (typeof ua !== 'string') return false; - - return opts.tablet - ? tabletRE.test(ua) - : mobileRE.test(ua); -} - -},{}],421:[function(_dereq_,module,exports){ -'use strict'; -module.exports = function (x) { - var type = typeof x; - return x !== null && (type === 'object' || type === 'function'); -}; - -},{}],422:[function(_dereq_,module,exports){ -'use strict'; -var toString = Object.prototype.toString; - -module.exports = function (x) { - var prototype; - return toString.call(x) === '[object Object]' && (prototype = Object.getPrototypeOf(x), prototype === null || prototype === Object.getPrototypeOf({})); -}; - -},{}],423:[function(_dereq_,module,exports){ -'use strict'; - -/** - * Is this string all whitespace? - * This solution kind of makes my brain hurt, but it's significantly faster - * than !str.trim() or any other solution I could find. - * - * whitespace codes from: http://en.wikipedia.org/wiki/Whitespace_character - * and verified with: - * - * for(var i = 0; i < 65536; i++) { - * var s = String.fromCharCode(i); - * if(+s===0 && !s.trim()) console.log(i, s); - * } - * - * which counts a couple of these as *not* whitespace, but finds nothing else - * that *is* whitespace. Note that charCodeAt stops at 16 bits, but it appears - * that there are no whitespace characters above this, and code points above - * this do not map onto white space characters. - */ - -module.exports = function(str){ - var l = str.length, - a; - for(var i = 0; i < l; i++) { - a = str.charCodeAt(i); - if((a < 9 || a > 13) && (a !== 32) && (a !== 133) && (a !== 160) && - (a !== 5760) && (a !== 6158) && (a < 8192 || a > 8205) && - (a !== 8232) && (a !== 8233) && (a !== 8239) && (a !== 8287) && - (a !== 8288) && (a !== 12288) && (a !== 65279)) { - return false; - } - } - return true; -} - -},{}],424:[function(_dereq_,module,exports){ -'use strict' - -module.exports = function isPath(str) { - if (typeof str !== 'string') return false - - str = str.trim() - - // https://www.w3.org/TR/SVG/paths.html#PathDataBNF - if (/^[mzlhvcsqta]\s*[-+.0-9][^mlhvzcsqta]+/i.test(str) && /[\dz]$/i.test(str) && str.length > 4) return true - - return false -} - -},{}],425:[function(_dereq_,module,exports){ -function lerp(v0, v1, t) { - return v0*(1-t)+v1*t -} -module.exports = lerp -},{}],426:[function(_dereq_,module,exports){ -/* Mapbox GL JS is licensed under the 3-Clause BSD License. Full text of license: https://github.com/mapbox/mapbox-gl-js/blob/v1.1.1/LICENSE.txt */ -(function (global, factory) { -typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : -typeof define === 'function' && define.amd ? define(factory) : -(global = global || self, global.mapboxgl = factory()); -}(this, function () { 'use strict'; - -/* eslint-disable */ - -var shared, worker, mapboxgl; -// define gets called three times: one for each chunk. we rely on the order -// they're imported to know which is which -function define(_, chunk) { -if (!shared) { - shared = chunk; -} else if (!worker) { - worker = chunk; -} else { - var workerBundleString = 'var sharedChunk = {}; (' + shared + ')(sharedChunk); (' + worker + ')(sharedChunk);' - - var sharedChunk = {}; - shared(sharedChunk); - mapboxgl = chunk(sharedChunk); - mapboxgl.workerUrl = window.URL.createObjectURL(new Blob([workerBundleString], { type: 'text/javascript' })); -} -} - - -define(["exports"],function(t){"use strict";function e(t,e){return t(e={exports:{}},e.exports),e.exports}var r=n;function n(t,e,r,n){this.cx=3*t,this.bx=3*(r-t)-this.cx,this.ax=1-this.cx-this.bx,this.cy=3*e,this.by=3*(n-e)-this.cy,this.ay=1-this.cy-this.by,this.p1x=t,this.p1y=n,this.p2x=r,this.p2y=n;}n.prototype.sampleCurveX=function(t){return ((this.ax*t+this.bx)*t+this.cx)*t},n.prototype.sampleCurveY=function(t){return ((this.ay*t+this.by)*t+this.cy)*t},n.prototype.sampleCurveDerivativeX=function(t){return (3*this.ax*t+2*this.bx)*t+this.cx},n.prototype.solveCurveX=function(t,e){var r,n,i,a,o;for(void 0===e&&(e=1e-6),i=t,o=0;o<8;o++){if(a=this.sampleCurveX(i)-t,Math.abs(a)(n=1))return n;for(;ra?r=i:n=i,i=.5*(n-r)+r;}return i},n.prototype.solve=function(t,e){return this.sampleCurveY(this.solveCurveX(t,e))};var i=a;function a(t,e){this.x=t,this.y=e;}function o(t,e){if(Array.isArray(t)){if(!Array.isArray(e)||t.length!==e.length)return !1;for(var r=0;r0;)e[r]=arguments[r+1];for(var n=0,i=e;n>e/4).toString(16):([1e7]+-[1e3]+-4e3+-8e3+-1e11).replace(/[018]/g,t)}()}function d(t){return !!t&&/^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(t)}function m(t,e){t.forEach(function(t){e[t]&&(e[t]=e[t].bind(e));});}function v(t,e){return -1!==t.indexOf(e,t.length-e.length)}function g(t,e,r){var n={};for(var i in t)n[i]=e.call(r||this,t[i],i,t);return n}function x(t,e,r){var n={};for(var i in t)e.call(r||this,t[i],i,t)&&(n[i]=t[i]);return n}function b(t){return Array.isArray(t)?t.map(b):"object"==typeof t&&t?g(t,b):t}var _={};function w(t){_[t]||("undefined"!=typeof console&&console.warn(t),_[t]=!0);}function A(t,e,r){return (r.y-t.y)*(e.x-t.x)>(e.y-t.y)*(r.x-t.x)}function S(t){for(var e=0,r=0,n=t.length,i=n-1,a=void 0,o=void 0;r@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)(?:\=(?:([^\x00-\x20\(\)<>@\,;\:\\"\/\[\]\?\=\{\}\x7F]+)|(?:\"((?:[^"\\]|\\.)*)\")))?/g,function(t,r,n,i){var a=n||i;return e[r]=!a||a.toLowerCase(),""}),e["max-age"]){var r=parseInt(e["max-age"],10);isNaN(r)?delete e["max-age"]:e["max-age"]=r;}return e}function z(t){try{var e=self[t];return e.setItem("_mapbox_test_",1),e.removeItem("_mapbox_test_"),!0}catch(t){return !1}}var I,B,C,E=self.performance&&self.performance.now?self.performance.now.bind(self.performance):Date.now.bind(Date),M=self.requestAnimationFrame||self.mozRequestAnimationFrame||self.webkitRequestAnimationFrame||self.msRequestAnimationFrame,T=self.cancelAnimationFrame||self.mozCancelAnimationFrame||self.webkitCancelAnimationFrame||self.msCancelAnimationFrame,P={now:E,frame:function(t){var e=M(t);return {cancel:function(){return T(e)}}},getImageData:function(t){var e=self.document.createElement("canvas"),r=e.getContext("2d");if(!r)throw new Error("failed to create canvas 2d context");return e.width=t.width,e.height=t.height,r.drawImage(t,0,0,t.width,t.height),r.getImageData(0,0,t.width,t.height)},resolveURL:function(t){return I||(I=self.document.createElement("a")),I.href=t,I.href},hardwareConcurrency:self.navigator.hardwareConcurrency||4,get devicePixelRatio(){return self.devicePixelRatio}},V={API_URL:"https://api.mapbox.com",get EVENTS_URL(){return this.API_URL?0===this.API_URL.indexOf("https://api.mapbox.cn")?"https://events.mapbox.cn/events/v2":0===this.API_URL.indexOf("https://api.mapbox.com")?"https://events.mapbox.com/events/v2":null:null},FEEDBACK_URL:"https://apps.mapbox.com/feedback",REQUIRE_ACCESS_TOKEN:!0,ACCESS_TOKEN:null,MAX_PARALLEL_IMAGE_REQUESTS:16},F={supported:!1,testSupport:function(t){if(L||!C)return;D?O(t):B=t;}},L=!1,D=!1;function O(t){var e=t.createTexture();t.bindTexture(t.TEXTURE_2D,e);try{if(t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,C),t.isContextLost())return;F.supported=!0;}catch(t){}t.deleteTexture(e),L=!0;}self.document&&((C=self.document.createElement("img")).onload=function(){B&&O(B),B=null,D=!0;},C.onerror=function(){L=!0,B=null;},C.src="data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA=");var R="01";var U=function(t){this._transformRequestFn=t,this._createSkuToken();};U.prototype._createSkuToken=function(){var t=function(){for(var t="",e=0;e<10;e++)t+="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[Math.floor(62*Math.random())];return {token:["1",R,t].join(""),tokenExpiresAt:Date.now()+432e5}}();this._skuToken=t.token,this._skuTokenExpiresAt=t.tokenExpiresAt;},U.prototype._isSkuTokenExpired=function(){return Date.now()>this._skuTokenExpiresAt},U.prototype.transformRequest=function(t,e){return this._transformRequestFn&&this._transformRequestFn(t,e)||{url:t}},U.prototype.normalizeStyleURL=function(t,e){return G(t,e)},U.prototype.normalizeGlyphsURL=function(t,e){return X(t,e)},U.prototype.normalizeSourceURL=function(t,e){return J(t,e)},U.prototype.normalizeSpriteURL=function(t,e,r,n){return H(t,e,r,n)},U.prototype.normalizeTileURL=function(t,e,r){return this._isSkuTokenExpired()&&this._createSkuToken(),$(t,e,r,this._skuToken)},U.prototype.canonicalizeTileURL=function(t){return Q(t)},U.prototype.canonicalizeTileset=function(t,e){return tt(t,e)};var j="See https://www.mapbox.com/api-documentation/#access-tokens-and-token-scopes";function q(t,e){var r=rt(V.API_URL);if(t.protocol=r.protocol,t.authority=r.authority,"/"!==r.path&&(t.path=""+r.path+t.path),!V.REQUIRE_ACCESS_TOKEN)return nt(t);if(!(e=e||V.ACCESS_TOKEN))throw new Error("An API access token is required to use Mapbox GL. "+j);if("s"===e[0])throw new Error("Use a public access token (pk.*) with Mapbox GL, not a secret access token (sk.*). "+j);return t.params.push("access_token="+e),nt(t)}function N(t){return 0===t.indexOf("mapbox:")}var Z=/^((https?:)?\/\/)?([^\/]+\.)?mapbox\.c(n|om)(\/|\?|$)/i;function K(t){return Z.test(t)}var G=function(t,e){if(!N(t))return t;var r=rt(t);return r.path="/styles/v1"+r.path,q(r,e)},X=function(t,e){if(!N(t))return t;var r=rt(t);return r.path="/fonts/v1"+r.path,q(r,e)},J=function(t,e){if(!N(t))return t;var r=rt(t);return r.path="/v4/"+r.authority+".json",r.params.push("secure"),q(r,e)},H=function(t,e,r,n){var i=rt(t);return N(t)?(i.path="/styles/v1"+i.path+"/sprite"+e+r,q(i,n)):(i.path+=""+e+r,nt(i))},Y=/(\.(png|jpg)\d*)(?=$)/,$=function(t,e,r,n){if(!e||!N(e))return t;var i=rt(t),a=P.devicePixelRatio>=2||512===r?"@2x":"",o=F.supported?".webp":"$1";return i.path=i.path.replace(Y,""+a+o),i.path="/v4"+i.path,V.REQUIRE_ACCESS_TOKEN&&V.ACCESS_TOKEN&&n&&i.params.push("sku="+n),q(i)},W=/\.[\w]+$/,Q=function(t){var e=rt(t);if(!e.path.match(/(^\/v4\/)/)||!e.path.match(W))return t;var r="mapbox://tiles/";r+=e.path.replace("/v4/","");var n=e.params.filter(function(t){return !t.match(/^access_token=/)});return n.length&&(r+="?"+n.join("&")),r},tt=function(t,e){if(!N(e))return t.tiles||[];for(var r=[],n=0,i=t.tiles;n=1&&self.localStorage.setItem(e,JSON.stringify(this.eventData));}catch(t){w("Unable to write to LocalStorage");}},at.prototype.processRequests=function(){},at.prototype.postEvent=function(t,e,r){var n=this;if(V.EVENTS_URL){var i=rt(V.EVENTS_URL);i.params.push("access_token="+(V.ACCESS_TOKEN||""));var a={event:this.type,created:new Date(t).toISOString(),sdkIdentifier:"mapbox-gl-js",sdkVersion:"1.1.1",skuId:R,userId:this.anonId},o=e?c(a,e):a,s={url:nt(i),headers:{"Content-Type":"text/plain"},body:JSON.stringify([o])};this.pendingRequest=It(s,function(t){n.pendingRequest=null,r(t),n.saveEventData(),n.processRequests();});}},at.prototype.queueRequest=function(t){this.queue.push(t),this.processRequests();};var ot,st=function(t){function e(){t.call(this,"map.load"),this.success={},this.skuToken="";}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.postMapLoadEvent=function(t,e,r){this.skuToken=r,V.EVENTS_URL&&V.ACCESS_TOKEN&&Array.isArray(t)&&t.some(function(t){return N(t)||K(t)})&&this.queueRequest({id:e,timestamp:Date.now()});},e.prototype.processRequests=function(){var t=this;if(!this.pendingRequest&&0!==this.queue.length){var e=this.queue.shift(),r=e.id,n=e.timestamp;r&&this.success[r]||(this.anonId||this.fetchEventData(),d(this.anonId)||(this.anonId=y()),this.postEvent(n,{skuToken:this.skuToken},function(e){e||r&&(t.success[r]=!0);}));}},e}(at),ut=new(function(t){function e(){t.call(this,"appUserTurnstile");}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.postTurnstileEvent=function(t){V.EVENTS_URL&&V.ACCESS_TOKEN&&Array.isArray(t)&&t.some(function(t){return N(t)||K(t)})&&this.queueRequest(Date.now());},e.prototype.processRequests=function(){var t=this;if(!this.pendingRequest&&0!==this.queue.length){this.anonId&&this.eventData.lastSuccess&&this.eventData.tokenU||this.fetchEventData();var e=it(V.ACCESS_TOKEN),r=e?e.u:V.ACCESS_TOKEN,n=r!==this.eventData.tokenU;d(this.anonId)||(this.anonId=y(),n=!0);var i=this.queue.shift();if(this.eventData.lastSuccess){var a=new Date(this.eventData.lastSuccess),o=new Date(i),s=(i-this.eventData.lastSuccess)/864e5;n=n||s>=1||s<-1||a.getDate()!==o.getDate();}else n=!0;if(!n)return this.processRequests();this.postEvent(i,{"enabled.telemetry":!1},function(e){e||(t.eventData.lastSuccess=i,t.eventData.tokenU=r);});}},e}(at)),lt=ut.postTurnstileEvent.bind(ut),pt=new st,ct=pt.postMapLoadEvent.bind(pt),ht="mapbox-tiles",ft=500,yt=50,dt=42e4;function mt(t,e,r){if(self.caches){var n={status:e.status,statusText:e.statusText,headers:new self.Headers};e.headers.forEach(function(t,e){return n.headers.set(e,t)});var i=k(e.headers.get("Cache-Control")||"");if(!i["no-store"])i["max-age"]&&n.headers.set("Expires",new Date(r+1e3*i["max-age"]).toUTCString()),new Date(n.headers.get("Expires")).getTime()-rDate.now()&&!r["no-cache"]}(n);t.delete(r),i&&t.put(r,n.clone()),e(null,n,i);});});}var xt=1/0;var bt={Unknown:"Unknown",Style:"Style",Source:"Source",Tile:"Tile",Glyphs:"Glyphs",SpriteImage:"SpriteImage",SpriteJSON:"SpriteJSON",Image:"Image"};"function"==typeof Object.freeze&&Object.freeze(bt);var _t=function(t){function e(e,r,n){401===r&&K(n)&&(e+=": you may have provided an invalid Mapbox access token. See https://www.mapbox.com/api-documentation/#access-tokens-and-token-scopes"),t.call(this,e),this.status=r,this.url=n,this.name=this.constructor.name,this.message=e;}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.toString=function(){return this.name+": "+this.message+" ("+this.status+"): "+this.url},e}(Error);function wt(){return "undefined"!=typeof WorkerGlobalScope&&"undefined"!=typeof self&&self instanceof WorkerGlobalScope}var At=wt()?function(){return self.worker&&self.worker.referrer}:function(){var t=self.location.origin;if(t&&"null"!==t&&"file://"!==t)return t+self.location.pathname};function St(t,e){var r,n=new self.AbortController,i=new self.Request(t.url,{method:t.method||"GET",body:t.body,credentials:t.credentials,headers:t.headers,referrer:At(),signal:n.signal}),a=!1,o=!1,s=(r=i.url).indexOf("sku=")>0&&K(r);"json"===t.type&&i.headers.set("Accept","application/json");var u=function(r,n,a){if(!o){if(r&&"SecurityError"!==r.message&&w(r),n&&a)return l(n);var u=Date.now();self.fetch(i).then(function(r){if(r.ok){var n=s?r.clone():null;return l(r,n,u)}return e(new _t(r.statusText,r.status,t.url))}).catch(function(t){20!==t.code&&e(new Error(t.message));});}},l=function(r,n,s){("arrayBuffer"===t.type?r.arrayBuffer():"json"===t.type?r.json():r.text()).then(function(t){o||(n&&s&&mt(i,n,s),a=!0,e(null,t,r.headers.get("Cache-Control"),r.headers.get("Expires")));}).catch(function(t){return e(new Error(t.message))});};return s?gt(i,u):u(null,null),{cancel:function(){o=!0,a||n.abort();}}}var kt=function(t,e){if(!/^file:/.test(t.url)){if(self.fetch&&self.Request&&self.AbortController&&self.Request.prototype.hasOwnProperty("signal"))return St(t,e);if(wt()&&self.worker&&self.worker.actor)return self.worker.actor.send("getResource",t,e)}return function(t,e){var r=new self.XMLHttpRequest;for(var n in r.open(t.method||"GET",t.url,!0),"arrayBuffer"===t.type&&(r.responseType="arraybuffer"),t.headers)r.setRequestHeader(n,t.headers[n]);return "json"===t.type&&r.setRequestHeader("Accept","application/json"),r.withCredentials="include"===t.credentials,r.onerror=function(){e(new Error(r.statusText));},r.onload=function(){if((r.status>=200&&r.status<300||0===r.status)&&null!==r.response){var n=r.response;if("json"===t.type)try{n=JSON.parse(r.response);}catch(t){return e(t)}e(null,n,r.getResponseHeader("Cache-Control"),r.getResponseHeader("Expires"));}else e(new _t(r.statusText,r.status,t.url));},r.send(t.body),{cancel:function(){return r.abort()}}}(t,e)},zt=function(t,e){return kt(c(t,{type:"arrayBuffer"}),e)},It=function(t,e){return kt(c(t,{method:"POST"}),e)};var Bt,Ct;Bt=[],Ct=0;var Et=function(t,e){if(Ct>=V.MAX_PARALLEL_IMAGE_REQUESTS){var r={requestParameters:t,callback:e,cancelled:!1,cancel:function(){this.cancelled=!0;}};return Bt.push(r),r}Ct++;var n=!1,i=function(){if(!n)for(n=!0,Ct--;Bt.length&&Ct0||this._oneTimeListeners&&this._oneTimeListeners[t]&&this._oneTimeListeners[t].length>0||this._eventedParent&&this._eventedParent.listens(t)},Ft.prototype.setEventedParent=function(t,e){return this._eventedParent=t,this._eventedParentData=e,this};var Lt={$version:8,$root:{version:{required:!0,type:"enum",values:[8]},name:{type:"string"},metadata:{type:"*"},center:{type:"array",value:"number"},zoom:{type:"number"},bearing:{type:"number",default:0,period:360,units:"degrees"},pitch:{type:"number",default:0,units:"degrees"},light:{type:"light"},sources:{required:!0,type:"sources"},sprite:{type:"string"},glyphs:{type:"string"},transition:{type:"transition"},layers:{required:!0,type:"array",value:"layer"}},sources:{"*":{type:"source"}},source:["source_vector","source_raster","source_raster_dem","source_geojson","source_video","source_image"],source_vector:{type:{required:!0,type:"enum",values:{vector:{}}},url:{type:"string"},tiles:{type:"array",value:"string"},bounds:{type:"array",value:"number",length:4,default:[-180,-85.051129,180,85.051129]},scheme:{type:"enum",values:{xyz:{},tms:{}},default:"xyz"},minzoom:{type:"number",default:0},maxzoom:{type:"number",default:22},attribution:{type:"string"},"*":{type:"*"}},source_raster:{type:{required:!0,type:"enum",values:{raster:{}}},url:{type:"string"},tiles:{type:"array",value:"string"},bounds:{type:"array",value:"number",length:4,default:[-180,-85.051129,180,85.051129]},minzoom:{type:"number",default:0},maxzoom:{type:"number",default:22},tileSize:{type:"number",default:512,units:"pixels"},scheme:{type:"enum",values:{xyz:{},tms:{}},default:"xyz"},attribution:{type:"string"},"*":{type:"*"}},source_raster_dem:{type:{required:!0,type:"enum",values:{"raster-dem":{}}},url:{type:"string"},tiles:{type:"array",value:"string"},bounds:{type:"array",value:"number",length:4,default:[-180,-85.051129,180,85.051129]},minzoom:{type:"number",default:0},maxzoom:{type:"number",default:22},tileSize:{type:"number",default:512,units:"pixels"},attribution:{type:"string"},encoding:{type:"enum",values:{terrarium:{},mapbox:{}},default:"mapbox"},"*":{type:"*"}},source_geojson:{type:{required:!0,type:"enum",values:{geojson:{}}},data:{type:"*"},maxzoom:{type:"number",default:18},attribution:{type:"string"},buffer:{type:"number",default:128,maximum:512,minimum:0},tolerance:{type:"number",default:.375},cluster:{type:"boolean",default:!1},clusterRadius:{type:"number",default:50,minimum:0},clusterMaxZoom:{type:"number"},clusterProperties:{type:"*"},lineMetrics:{type:"boolean",default:!1},generateId:{type:"boolean",default:!1}},source_video:{type:{required:!0,type:"enum",values:{video:{}}},urls:{required:!0,type:"array",value:"string"},coordinates:{required:!0,type:"array",length:4,value:{type:"array",length:2,value:"number"}}},source_image:{type:{required:!0,type:"enum",values:{image:{}}},url:{required:!0,type:"string"},coordinates:{required:!0,type:"array",length:4,value:{type:"array",length:2,value:"number"}}},layer:{id:{type:"string",required:!0},type:{type:"enum",values:{fill:{},line:{},symbol:{},circle:{},heatmap:{},"fill-extrusion":{},raster:{},hillshade:{},background:{}},required:!0},metadata:{type:"*"},source:{type:"string"},"source-layer":{type:"string"},minzoom:{type:"number",minimum:0,maximum:24},maxzoom:{type:"number",minimum:0,maximum:24},filter:{type:"filter"},layout:{type:"layout"},paint:{type:"paint"}},layout:["layout_fill","layout_line","layout_circle","layout_heatmap","layout_fill-extrusion","layout_symbol","layout_raster","layout_hillshade","layout_background"],layout_background:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible","property-type":"constant"}},layout_fill:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible","property-type":"constant"}},layout_circle:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible","property-type":"constant"}},layout_heatmap:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible","property-type":"constant"}},"layout_fill-extrusion":{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible","property-type":"constant"}},layout_line:{"line-cap":{type:"enum",values:{butt:{},round:{},square:{}},default:"butt",expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"line-join":{type:"enum",values:{bevel:{},round:{},miter:{}},default:"miter",expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"data-driven"},"line-miter-limit":{type:"number",default:2,requires:[{"line-join":"miter"}],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"line-round-limit":{type:"number",default:1.05,requires:[{"line-join":"round"}],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},visibility:{type:"enum",values:{visible:{},none:{}},default:"visible","property-type":"constant"}},layout_symbol:{"symbol-placement":{type:"enum",values:{point:{},line:{},"line-center":{}},default:"point",expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"symbol-spacing":{type:"number",default:250,minimum:1,units:"pixels",requires:[{"symbol-placement":"line"}],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"symbol-avoid-edges":{type:"boolean",default:!1,expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"symbol-sort-key":{type:"number",expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"data-driven"},"symbol-z-order":{type:"enum",values:{auto:{},"viewport-y":{},source:{}},default:"auto",expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"icon-allow-overlap":{type:"boolean",default:!1,requires:["icon-image"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"icon-ignore-placement":{type:"boolean",default:!1,requires:["icon-image"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"icon-optional":{type:"boolean",default:!1,requires:["icon-image","text-field"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"icon-rotation-alignment":{type:"enum",values:{map:{},viewport:{},auto:{}},default:"auto",requires:["icon-image"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"icon-size":{type:"number",default:1,minimum:0,units:"factor of the original icon size",requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom","feature"]},"property-type":"data-driven"},"icon-text-fit":{type:"enum",values:{none:{},width:{},height:{},both:{}},default:"none",requires:["icon-image","text-field"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"icon-text-fit-padding":{type:"array",value:"number",length:4,default:[0,0,0,0],units:"pixels",requires:["icon-image","text-field",{"icon-text-fit":["both","width","height"]}],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"icon-image":{type:"string",tokens:!0,expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"data-driven"},"icon-rotate":{type:"number",default:0,period:360,units:"degrees",requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom","feature"]},"property-type":"data-driven"},"icon-padding":{type:"number",default:2,minimum:0,units:"pixels",requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"icon-keep-upright":{type:"boolean",default:!1,requires:["icon-image",{"icon-rotation-alignment":"map"},{"symbol-placement":["line","line-center"]}],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"icon-offset":{type:"array",value:"number",length:2,default:[0,0],requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom","feature"]},"property-type":"data-driven"},"icon-anchor":{type:"enum",values:{center:{},left:{},right:{},top:{},bottom:{},"top-left":{},"top-right":{},"bottom-left":{},"bottom-right":{}},default:"center",requires:["icon-image"],expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"data-driven"},"icon-pitch-alignment":{type:"enum",values:{map:{},viewport:{},auto:{}},default:"auto",requires:["icon-image"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"text-pitch-alignment":{type:"enum",values:{map:{},viewport:{},auto:{}},default:"auto",requires:["text-field"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"text-rotation-alignment":{type:"enum",values:{map:{},viewport:{},auto:{}},default:"auto",requires:["text-field"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"text-field":{type:"formatted",default:"",tokens:!0,expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-font":{type:"array",value:"string",default:["Open Sans Regular","Arial Unicode MS Regular"],requires:["text-field"],expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-size":{type:"number",default:16,minimum:0,units:"pixels",requires:["text-field"],expression:{interpolated:!0,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-max-width":{type:"number",default:10,minimum:0,units:"ems",requires:["text-field"],expression:{interpolated:!0,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-line-height":{type:"number",default:1.2,units:"ems",requires:["text-field"],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"text-letter-spacing":{type:"number",default:0,units:"ems",requires:["text-field"],expression:{interpolated:!0,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-justify":{type:"enum",values:{auto:{},left:{},center:{},right:{}},default:"center",requires:["text-field"],expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-radial-offset":{type:"number",units:"ems",default:0,requires:[{"!":"text-offset"}],"property-type":"data-driven",expression:{interpolated:!0,parameters:["zoom","feature"]}},"text-variable-anchor":{type:"array",value:"enum",values:{center:{},left:{},right:{},top:{},bottom:{},"top-left":{},"top-right":{},"bottom-left":{},"bottom-right":{}},requires:[{"!":"text-anchor"},{"!":"text-offset"},{"symbol-placement":["point"]}],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"text-anchor":{type:"enum",requires:["text-field"],values:{center:{},left:{},right:{},top:{},bottom:{},"top-left":{},"top-right":{},"bottom-left":{},"bottom-right":{}},default:"center",expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-max-angle":{type:"number",default:45,units:"degrees",requires:["text-field",{"symbol-placement":["line","line-center"]}],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"text-rotate":{type:"number",default:0,period:360,units:"degrees",requires:["text-field"],expression:{interpolated:!0,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-padding":{type:"number",default:2,minimum:0,units:"pixels",requires:["text-field"],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"text-keep-upright":{type:"boolean",default:!0,requires:["text-field",{"text-rotation-alignment":"map"},{"symbol-placement":["line","line-center"]}],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"text-transform":{type:"enum",values:{none:{},uppercase:{},lowercase:{}},default:"none",requires:["text-field"],expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-offset":{type:"array",value:"number",units:"ems",length:2,default:[0,0],requires:["text-field",{"!":"text-radial-offset"}],expression:{interpolated:!0,parameters:["zoom","feature"]},"property-type":"data-driven"},"text-allow-overlap":{type:"boolean",default:!1,requires:["text-field"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"text-ignore-placement":{type:"boolean",default:!1,requires:["text-field"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"text-optional":{type:"boolean",default:!1,requires:["text-field","icon-image"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},visibility:{type:"enum",values:{visible:{},none:{}},default:"visible","property-type":"constant"}},layout_raster:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible","property-type":"constant"}},layout_hillshade:{visibility:{type:"enum",values:{visible:{},none:{}},default:"visible","property-type":"constant"}},filter:{type:"array",value:"*"},filter_operator:{type:"enum",values:{"==":{},"!=":{},">":{},">=":{},"<":{},"<=":{},in:{},"!in":{},all:{},any:{},none:{},has:{},"!has":{}}},geometry_type:{type:"enum",values:{Point:{},LineString:{},Polygon:{}}},function:{expression:{type:"expression"},stops:{type:"array",value:"function_stop"},base:{type:"number",default:1,minimum:0},property:{type:"string",default:"$zoom"},type:{type:"enum",values:{identity:{},exponential:{},interval:{},categorical:{}},default:"exponential"},colorSpace:{type:"enum",values:{rgb:{},lab:{},hcl:{}},default:"rgb"},default:{type:"*",required:!1}},function_stop:{type:"array",minimum:0,maximum:22,value:["number","color"],length:2},expression:{type:"array",value:"*",minimum:1},expression_name:{type:"enum",values:{let:{group:"Variable binding"},var:{group:"Variable binding"},literal:{group:"Types"},array:{group:"Types"},at:{group:"Lookup"},case:{group:"Decision"},match:{group:"Decision"},coalesce:{group:"Decision"},step:{group:"Ramps, scales, curves"},interpolate:{group:"Ramps, scales, curves"},"interpolate-hcl":{group:"Ramps, scales, curves"},"interpolate-lab":{group:"Ramps, scales, curves"},ln2:{group:"Math"},pi:{group:"Math"},e:{group:"Math"},typeof:{group:"Types"},string:{group:"Types"},number:{group:"Types"},boolean:{group:"Types"},object:{group:"Types"},collator:{group:"Types"},format:{group:"Types"},"number-format":{group:"Types"},"to-string":{group:"Types"},"to-number":{group:"Types"},"to-boolean":{group:"Types"},"to-rgba":{group:"Color"},"to-color":{group:"Types"},rgb:{group:"Color"},rgba:{group:"Color"},get:{group:"Lookup"},has:{group:"Lookup"},length:{group:"Lookup"},properties:{group:"Feature data"},"feature-state":{group:"Feature data"},"geometry-type":{group:"Feature data"},id:{group:"Feature data"},zoom:{group:"Zoom"},"heatmap-density":{group:"Heatmap"},"line-progress":{group:"Feature data"},accumulated:{group:"Feature data"},"+":{group:"Math"},"*":{group:"Math"},"-":{group:"Math"},"/":{group:"Math"},"%":{group:"Math"},"^":{group:"Math"},sqrt:{group:"Math"},log10:{group:"Math"},ln:{group:"Math"},log2:{group:"Math"},sin:{group:"Math"},cos:{group:"Math"},tan:{group:"Math"},asin:{group:"Math"},acos:{group:"Math"},atan:{group:"Math"},min:{group:"Math"},max:{group:"Math"},round:{group:"Math"},abs:{group:"Math"},ceil:{group:"Math"},floor:{group:"Math"},"==":{group:"Decision"},"!=":{group:"Decision"},">":{group:"Decision"},"<":{group:"Decision"},">=":{group:"Decision"},"<=":{group:"Decision"},all:{group:"Decision"},any:{group:"Decision"},"!":{group:"Decision"},"is-supported-script":{group:"String"},upcase:{group:"String"},downcase:{group:"String"},concat:{group:"String"},"resolved-locale":{group:"String"}}},light:{anchor:{type:"enum",default:"viewport",values:{map:{},viewport:{}},"property-type":"data-constant",transition:!1,expression:{interpolated:!1,parameters:["zoom"]}},position:{type:"array",default:[1.15,210,30],length:3,value:"number","property-type":"data-constant",transition:!0,expression:{interpolated:!0,parameters:["zoom"]}},color:{type:"color","property-type":"data-constant",default:"#ffffff",expression:{interpolated:!0,parameters:["zoom"]},transition:!0},intensity:{type:"number","property-type":"data-constant",default:.5,minimum:0,maximum:1,expression:{interpolated:!0,parameters:["zoom"]},transition:!0}},paint:["paint_fill","paint_line","paint_circle","paint_heatmap","paint_fill-extrusion","paint_symbol","paint_raster","paint_hillshade","paint_background"],paint_fill:{"fill-antialias":{type:"boolean",default:!0,expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"fill-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-color":{type:"color",default:"#000000",transition:!0,requires:[{"!":"fill-pattern"}],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-outline-color":{type:"color",transition:!0,requires:[{"!":"fill-pattern"},{"fill-antialias":!0}],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-translate":{type:"array",value:"number",length:2,default:[0,0],transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"fill-translate-anchor":{type:"enum",values:{map:{},viewport:{}},default:"map",requires:["fill-translate"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"fill-pattern":{type:"string",transition:!0,expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"cross-faded-data-driven"}},"paint_fill-extrusion":{"fill-extrusion-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"fill-extrusion-color":{type:"color",default:"#000000",transition:!0,requires:[{"!":"fill-extrusion-pattern"}],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-extrusion-translate":{type:"array",value:"number",length:2,default:[0,0],transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"fill-extrusion-translate-anchor":{type:"enum",values:{map:{},viewport:{}},default:"map",requires:["fill-extrusion-translate"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"fill-extrusion-pattern":{type:"string",transition:!0,expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"cross-faded-data-driven"},"fill-extrusion-height":{type:"number",default:0,minimum:0,units:"meters",transition:!0,expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-extrusion-base":{type:"number",default:0,minimum:0,units:"meters",transition:!0,requires:["fill-extrusion-height"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"fill-extrusion-vertical-gradient":{type:"boolean",default:!0,transition:!1,expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"}},paint_line:{"line-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-color":{type:"color",default:"#000000",transition:!0,requires:[{"!":"line-pattern"}],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-translate":{type:"array",value:"number",length:2,default:[0,0],transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"line-translate-anchor":{type:"enum",values:{map:{},viewport:{}},default:"map",requires:["line-translate"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"line-width":{type:"number",default:1,minimum:0,transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-gap-width":{type:"number",default:0,minimum:0,transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-offset":{type:"number",default:0,transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-blur":{type:"number",default:0,minimum:0,transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"line-dasharray":{type:"array",value:"number",minimum:0,transition:!0,units:"line widths",requires:[{"!":"line-pattern"}],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"cross-faded"},"line-pattern":{type:"string",transition:!0,expression:{interpolated:!1,parameters:["zoom","feature"]},"property-type":"cross-faded-data-driven"},"line-gradient":{type:"color",transition:!1,requires:[{"!":"line-dasharray"},{"!":"line-pattern"},{source:"geojson",has:{lineMetrics:!0}}],expression:{interpolated:!0,parameters:["line-progress"]},"property-type":"color-ramp"}},paint_circle:{"circle-radius":{type:"number",default:5,minimum:0,transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-color":{type:"color",default:"#000000",transition:!0,expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-blur":{type:"number",default:0,transition:!0,expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-translate":{type:"array",value:"number",length:2,default:[0,0],transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"circle-translate-anchor":{type:"enum",values:{map:{},viewport:{}},default:"map",requires:["circle-translate"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"circle-pitch-scale":{type:"enum",values:{map:{},viewport:{}},default:"map",expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"circle-pitch-alignment":{type:"enum",values:{map:{},viewport:{}},default:"viewport",expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"circle-stroke-width":{type:"number",default:0,minimum:0,transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-stroke-color":{type:"color",default:"#000000",transition:!0,expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"circle-stroke-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"}},paint_heatmap:{"heatmap-radius":{type:"number",default:30,minimum:1,transition:!0,units:"pixels",expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"heatmap-weight":{type:"number",default:1,minimum:0,transition:!1,expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"heatmap-intensity":{type:"number",default:1,minimum:0,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"heatmap-color":{type:"color",default:["interpolate",["linear"],["heatmap-density"],0,"rgba(0, 0, 255, 0)",.1,"royalblue",.3,"cyan",.5,"lime",.7,"yellow",1,"red"],transition:!1,expression:{interpolated:!0,parameters:["heatmap-density"]},"property-type":"color-ramp"},"heatmap-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"}},paint_symbol:{"icon-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-color":{type:"color",default:"#000000",transition:!0,requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-halo-color":{type:"color",default:"rgba(0, 0, 0, 0)",transition:!0,requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-halo-width":{type:"number",default:0,minimum:0,transition:!0,units:"pixels",requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-halo-blur":{type:"number",default:0,minimum:0,transition:!0,units:"pixels",requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"icon-translate":{type:"array",value:"number",length:2,default:[0,0],transition:!0,units:"pixels",requires:["icon-image"],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"icon-translate-anchor":{type:"enum",values:{map:{},viewport:{}},default:"map",requires:["icon-image","icon-translate"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"text-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,requires:["text-field"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-color":{type:"color",default:"#000000",transition:!0,requires:["text-field"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-halo-color":{type:"color",default:"rgba(0, 0, 0, 0)",transition:!0,requires:["text-field"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-halo-width":{type:"number",default:0,minimum:0,transition:!0,units:"pixels",requires:["text-field"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-halo-blur":{type:"number",default:0,minimum:0,transition:!0,units:"pixels",requires:["text-field"],expression:{interpolated:!0,parameters:["zoom","feature","feature-state"]},"property-type":"data-driven"},"text-translate":{type:"array",value:"number",length:2,default:[0,0],transition:!0,units:"pixels",requires:["text-field"],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"text-translate-anchor":{type:"enum",values:{map:{},viewport:{}},default:"map",requires:["text-field","text-translate"],expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"}},paint_raster:{"raster-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"raster-hue-rotate":{type:"number",default:0,period:360,transition:!0,units:"degrees",expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"raster-brightness-min":{type:"number",default:0,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"raster-brightness-max":{type:"number",default:1,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"raster-saturation":{type:"number",default:0,minimum:-1,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"raster-contrast":{type:"number",default:0,minimum:-1,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"raster-resampling":{type:"enum",values:{linear:{},nearest:{}},default:"linear",expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"raster-fade-duration":{type:"number",default:300,minimum:0,transition:!1,units:"milliseconds",expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"}},paint_hillshade:{"hillshade-illumination-direction":{type:"number",default:335,minimum:0,maximum:359,transition:!1,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"hillshade-illumination-anchor":{type:"enum",values:{map:{},viewport:{}},default:"viewport",expression:{interpolated:!1,parameters:["zoom"]},"property-type":"data-constant"},"hillshade-exaggeration":{type:"number",default:.5,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"hillshade-shadow-color":{type:"color",default:"#000000",transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"hillshade-highlight-color":{type:"color",default:"#FFFFFF",transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"hillshade-accent-color":{type:"color",default:"#000000",transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"}},paint_background:{"background-color":{type:"color",default:"#000000",transition:!0,requires:[{"!":"background-pattern"}],expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"},"background-pattern":{type:"string",transition:!0,expression:{interpolated:!1,parameters:["zoom"]},"property-type":"cross-faded"},"background-opacity":{type:"number",default:1,minimum:0,maximum:1,transition:!0,expression:{interpolated:!0,parameters:["zoom"]},"property-type":"data-constant"}},transition:{duration:{type:"number",default:300,minimum:0,units:"milliseconds"},delay:{type:"number",default:0,minimum:0,units:"milliseconds"}},"property-type":{"data-driven":{type:"property-type"},"cross-faded":{type:"property-type"},"cross-faded-data-driven":{type:"property-type"},"color-ramp":{type:"property-type"},"data-constant":{type:"property-type"},constant:{type:"property-type"}}},Dt=function(t,e,r,n){this.message=(t?t+": ":"")+r,n&&(this.identifier=n),null!=e&&e.__line__&&(this.line=e.__line__);};function Ot(t){var e=t.key,r=t.value;return r?[new Dt(e,r,"constants have been deprecated as of v8")]:[]}function Rt(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];for(var n=0,i=e;n":"value"===t.itemType.kind?"array":"array<"+e+">"}return t.kind}var re=[Kt,Gt,Xt,Jt,Ht,Qt,Yt,te($t)];function ne(t,e){if("error"===e.kind)return null;if("array"===t.kind){if("array"===e.kind&&(0===e.N&&"value"===e.itemType.kind||!ne(t.itemType,e.itemType))&&("number"!=typeof t.N||t.N===e.N))return null}else{if(t.kind===e.kind)return null;if("value"===t.kind)for(var r=0,n=re;r255?255:t}function i(t){return t<0?0:t>1?1:t}function a(t){return "%"===t[t.length-1]?n(parseFloat(t)/100*255):n(parseInt(t))}function o(t){return "%"===t[t.length-1]?i(parseFloat(t)/100):i(parseFloat(t))}function s(t,e,r){return r<0?r+=1:r>1&&(r-=1),6*r<1?t+(e-t)*r*6:2*r<1?e:3*r<2?t+(e-t)*(2/3-r)*6:t}try{e.parseCSSColor=function(t){var e,i=t.replace(/ /g,"").toLowerCase();if(i in r)return r[i].slice();if("#"===i[0])return 4===i.length?(e=parseInt(i.substr(1),16))>=0&&e<=4095?[(3840&e)>>4|(3840&e)>>8,240&e|(240&e)>>4,15&e|(15&e)<<4,1]:null:7===i.length&&(e=parseInt(i.substr(1),16))>=0&&e<=16777215?[(16711680&e)>>16,(65280&e)>>8,255&e,1]:null;var u=i.indexOf("("),l=i.indexOf(")");if(-1!==u&&l+1===i.length){var p=i.substr(0,u),c=i.substr(u+1,l-(u+1)).split(","),h=1;switch(p){case"rgba":if(4!==c.length)return null;h=o(c.pop());case"rgb":return 3!==c.length?null:[a(c[0]),a(c[1]),a(c[2]),h];case"hsla":if(4!==c.length)return null;h=o(c.pop());case"hsl":if(3!==c.length)return null;var f=(parseFloat(c[0])%360+360)%360/360,y=o(c[1]),d=o(c[2]),m=d<=.5?d*(y+1):d+y-d*y,v=2*d-m;return [n(255*s(v,m,f+1/3)),n(255*s(v,m,f)),n(255*s(v,m,f-1/3)),h];default:return null}}return null};}catch(t){}}).parseCSSColor,ae=function(t,e,r,n){void 0===n&&(n=1),this.r=t,this.g=e,this.b=r,this.a=n;};ae.parse=function(t){if(t){if(t instanceof ae)return t;if("string"==typeof t){var e=ie(t);if(e)return new ae(e[0]/255*e[3],e[1]/255*e[3],e[2]/255*e[3],e[3])}}},ae.prototype.toString=function(){var t=this.toArray(),e=t[0],r=t[1],n=t[2],i=t[3];return "rgba("+Math.round(e)+","+Math.round(r)+","+Math.round(n)+","+i+")"},ae.prototype.toArray=function(){var t=this.r,e=this.g,r=this.b,n=this.a;return 0===n?[0,0,0,0]:[255*t/n,255*e/n,255*r/n,n]},ae.black=new ae(0,0,0,1),ae.white=new ae(1,1,1,1),ae.transparent=new ae(0,0,0,0),ae.red=new ae(1,0,0,1);var oe=function(t,e,r){this.sensitivity=t?e?"variant":"case":e?"accent":"base",this.locale=r,this.collator=new Intl.Collator(this.locale?this.locale:[],{sensitivity:this.sensitivity,usage:"search"});};oe.prototype.compare=function(t,e){return this.collator.compare(t,e)},oe.prototype.resolvedLocale=function(){return new Intl.Collator(this.locale?this.locale:[]).resolvedOptions().locale};var se=function(t,e,r){this.text=t,this.scale=e,this.fontStack=r;},ue=function(t){this.sections=t;};function le(t,e,r,n){return "number"==typeof t&&t>=0&&t<=255&&"number"==typeof e&&e>=0&&e<=255&&"number"==typeof r&&r>=0&&r<=255?void 0===n||"number"==typeof n&&n>=0&&n<=1?null:"Invalid rgba value ["+[t,e,r,n].join(", ")+"]: 'a' must be between 0 and 1.":"Invalid rgba value ["+("number"==typeof n?[t,e,r,n]:[t,e,r]).join(", ")+"]: 'r', 'g', and 'b' must be between 0 and 255."}function pe(t){if(null===t)return Kt;if("string"==typeof t)return Xt;if("boolean"==typeof t)return Jt;if("number"==typeof t)return Gt;if(t instanceof ae)return Ht;if(t instanceof oe)return Wt;if(t instanceof ue)return Qt;if(Array.isArray(t)){for(var e,r=t.length,n=0,i=t;n2){var s=t[1];if("string"!=typeof s||!(s in ye)||"object"===s)return e.error('The item type argument of "array" must be one of string, number, boolean',1);a=ye[s],n++;}else a=$t;if(t.length>3){if(null!==t[2]&&("number"!=typeof t[2]||t[2]<0||t[2]!==Math.floor(t[2])))return e.error('The length argument to "array" must be a positive integer literal',2);o=t[2],n++;}r=te(a,o);}else r=ye[i];for(var u=[];n1)&&e.push(n);}}return e.concat(this.args.map(function(t){return t.serialize()}))};var me=function(t){this.type=Qt,this.sections=t;};me.parse=function(t,e){if(t.length<3)return e.error("Expected at least two arguments.");if((t.length-1)%2!=0)return e.error("Expected an even number of arguments.");for(var r=[],n=1;n4?"Invalid rbga value "+JSON.stringify(e)+": expected an array containing either three or four numeric values.":le(e[0],e[1],e[2],e[3])))return new ae(e[0]/255,e[1]/255,e[2]/255,e[3])}throw new fe(r||"Could not parse color from value '"+("string"==typeof e?e:String(JSON.stringify(e)))+"'")}if("number"===this.type.kind){for(var o=null,s=0,u=this.args;s=0)return !1;var r=!0;return t.eachChild(function(t){r&&!ke(t,e)&&(r=!1);}),r}we.parse=function(t,e){if(2!==t.length)return e.error("Expected one argument.");var r=t[1];if("object"!=typeof r||Array.isArray(r))return e.error("Collator options argument must be an object.");var n=e.parse(void 0!==r["case-sensitive"]&&r["case-sensitive"],1,Jt);if(!n)return null;var i=e.parse(void 0!==r["diacritic-sensitive"]&&r["diacritic-sensitive"],1,Jt);if(!i)return null;var a=null;return r.locale&&!(a=e.parse(r.locale,1,Xt))?null:new we(n,i,a)},we.prototype.evaluate=function(t){return new oe(this.caseSensitive.evaluate(t),this.diacriticSensitive.evaluate(t),this.locale?this.locale.evaluate(t):null)},we.prototype.eachChild=function(t){t(this.caseSensitive),t(this.diacriticSensitive),this.locale&&t(this.locale);},we.prototype.possibleOutputs=function(){return [void 0]},we.prototype.serialize=function(){var t={};return t["case-sensitive"]=this.caseSensitive.serialize(),t["diacritic-sensitive"]=this.diacriticSensitive.serialize(),this.locale&&(t.locale=this.locale.serialize()),["collator",t]};var ze=function(t,e){this.type=e.type,this.name=t,this.boundExpression=e;};ze.parse=function(t,e){if(2!==t.length||"string"!=typeof t[1])return e.error("'var' expression requires exactly one string literal argument.");var r=t[1];return e.scope.has(r)?new ze(r,e.scope.get(r)):e.error('Unknown variable "'+r+'". Make sure "'+r+'" has been bound in an enclosing "let" expression before using it.',1)},ze.prototype.evaluate=function(t){return this.boundExpression.evaluate(t)},ze.prototype.eachChild=function(){},ze.prototype.possibleOutputs=function(){return [void 0]},ze.prototype.serialize=function(){return ["var",this.name]};var Ie=function(t,e,r,n,i){void 0===e&&(e=[]),void 0===n&&(n=new Zt),void 0===i&&(i=[]),this.registry=t,this.path=e,this.key=e.map(function(t){return "["+t+"]"}).join(""),this.scope=n,this.errors=i,this.expectedType=r;};function Be(t,e){for(var r,n,i=t.length-1,a=0,o=i,s=0;a<=o;)if(r=t[s=Math.floor((a+o)/2)],n=t[s+1],r<=e){if(s===i||ee))throw new fe("Input is not a number.");o=s-1;}return 0}Ie.prototype.parse=function(t,e,r,n,i){return void 0===i&&(i={}),e?this.concat(e,r,n)._parse(t,i):this._parse(t,i)},Ie.prototype._parse=function(t,e){function r(t,e,r){return "assert"===r?new de(e,[t]):"coerce"===r?new ge(e,[t]):t}if(null!==t&&"string"!=typeof t&&"boolean"!=typeof t&&"number"!=typeof t||(t=["literal",t]),Array.isArray(t)){if(0===t.length)return this.error('Expected an array with at least one element. If you wanted a literal array, use ["literal", []].');var n=t[0];if("string"!=typeof n)return this.error("Expression name must be a string, but found "+typeof n+' instead. If you wanted a literal array, use ["literal", [...]].',0),null;var i=this.registry[n];if(i){var a=i.parse(t,this);if(!a)return null;if(this.expectedType){var o=this.expectedType,s=a.type;if("string"!==o.kind&&"number"!==o.kind&&"boolean"!==o.kind&&"object"!==o.kind&&"array"!==o.kind||"value"!==s.kind)if("color"!==o.kind&&"formatted"!==o.kind||"value"!==s.kind&&"string"!==s.kind){if(this.checkSubtype(o,s))return null}else a=r(a,o,e.typeAnnotation||"coerce");else a=r(a,o,e.typeAnnotation||"assert");}if(!(a instanceof he)&&function t(e){if(e instanceof ze)return t(e.boundExpression);if(e instanceof _e&&"error"===e.name)return !1;if(e instanceof we)return !1;var r=e instanceof ge||e instanceof de;var n=!0;e.eachChild(function(e){n=r?n&&t(e):n&&e instanceof he;});if(!n)return !1;return Ae(e)&&ke(e,["zoom","heatmap-density","line-progress","accumulated","is-supported-script"])}(a)){var u=new be;try{a=new he(a.type,a.evaluate(u));}catch(t){return this.error(t.message),null}}return a}return this.error('Unknown expression "'+n+'". If you wanted a literal array, use ["literal", [...]].',0)}return void 0===t?this.error("'undefined' value invalid. Use null instead."):"object"==typeof t?this.error('Bare objects invalid. Use ["literal", {...}] instead.'):this.error("Expected an array, but found "+typeof t+" instead.")},Ie.prototype.concat=function(t,e,r){var n="number"==typeof t?this.path.concat(t):this.path,i=r?this.scope.concat(r):this.scope;return new Ie(this.registry,n,e||null,i,this.errors)},Ie.prototype.error=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];var n=""+this.key+e.map(function(t){return "["+t+"]"}).join("");this.errors.push(new Nt(n,t));},Ie.prototype.checkSubtype=function(t,e){var r=ne(t,e);return r&&this.error(r),r};var Ce=function(t,e,r){this.type=t,this.input=e,this.labels=[],this.outputs=[];for(var n=0,i=r;n=o)return e.error('Input/output pairs for "step" expressions must be arranged with input values in strictly ascending order.',u);var p=e.parse(s,l,i);if(!p)return null;i=i||p.type,n.push([o,p]);}return new Ce(i,r,n)},Ce.prototype.evaluate=function(t){var e=this.labels,r=this.outputs;if(1===e.length)return r[0].evaluate(t);var n=this.input.evaluate(t);if(n<=e[0])return r[0].evaluate(t);var i=e.length;return n>=e[i-1]?r[i-1].evaluate(t):r[Be(e,n)].evaluate(t)},Ce.prototype.eachChild=function(t){t(this.input);for(var e=0,r=this.outputs;e0&&t.push(this.labels[e]),t.push(this.outputs[e].serialize());return t};var Me=Object.freeze({number:Ee,color:function(t,e,r){return new ae(Ee(t.r,e.r,r),Ee(t.g,e.g,r),Ee(t.b,e.b,r),Ee(t.a,e.a,r))},array:function(t,e,r){return t.map(function(t,n){return Ee(t,e[n],r)})}}),Te=.95047,Pe=1,Ve=1.08883,Fe=4/29,Le=6/29,De=3*Le*Le,Oe=Le*Le*Le,Re=Math.PI/180,Ue=180/Math.PI;function je(t){return t>Oe?Math.pow(t,1/3):t/De+Fe}function qe(t){return t>Le?t*t*t:De*(t-Fe)}function Ne(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Ze(t){return (t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Ke(t){var e=Ze(t.r),r=Ze(t.g),n=Ze(t.b),i=je((.4124564*e+.3575761*r+.1804375*n)/Te),a=je((.2126729*e+.7151522*r+.072175*n)/Pe);return {l:116*a-16,a:500*(i-a),b:200*(a-je((.0193339*e+.119192*r+.9503041*n)/Ve)),alpha:t.a}}function Ge(t){var e=(t.l+16)/116,r=isNaN(t.a)?e:e+t.a/500,n=isNaN(t.b)?e:e-t.b/200;return e=Pe*qe(e),r=Te*qe(r),n=Ve*qe(n),new ae(Ne(3.2404542*r-1.5371385*e-.4985314*n),Ne(-.969266*r+1.8760108*e+.041556*n),Ne(.0556434*r-.2040259*e+1.0572252*n),t.alpha)}function Xe(t,e,r){var n=e-t;return t+r*(n>180||n<-180?n-360*Math.round(n/360):n)}var Je={forward:Ke,reverse:Ge,interpolate:function(t,e,r){return {l:Ee(t.l,e.l,r),a:Ee(t.a,e.a,r),b:Ee(t.b,e.b,r),alpha:Ee(t.alpha,e.alpha,r)}}},He={forward:function(t){var e=Ke(t),r=e.l,n=e.a,i=e.b,a=Math.atan2(i,n)*Ue;return {h:a<0?a+360:a,c:Math.sqrt(n*n+i*i),l:r,alpha:t.a}},reverse:function(t){var e=t.h*Re,r=t.c;return Ge({l:t.l,a:Math.cos(e)*r,b:Math.sin(e)*r,alpha:t.alpha})},interpolate:function(t,e,r){return {h:Xe(t.h,e.h,r),c:Ee(t.c,e.c,r),l:Ee(t.l,e.l,r),alpha:Ee(t.alpha,e.alpha,r)}}},Ye=Object.freeze({lab:Je,hcl:He}),$e=function(t,e,r,n,i){this.type=t,this.operator=e,this.interpolation=r,this.input=n,this.labels=[],this.outputs=[];for(var a=0,o=i;a1}))return e.error("Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.",1);n={name:"cubic-bezier",controlPoints:s};}if(t.length-1<4)return e.error("Expected at least 4 arguments, but found only "+(t.length-1)+".");if((t.length-1)%2!=0)return e.error("Expected an even number of arguments.");if(!(i=e.parse(i,2,Gt)))return null;var u=[],l=null;"interpolate-hcl"===r||"interpolate-lab"===r?l=Ht:e.expectedType&&"value"!==e.expectedType.kind&&(l=e.expectedType);for(var p=0;p=c)return e.error('Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.',f);var d=e.parse(h,y,l);if(!d)return null;l=l||d.type,u.push([c,d]);}return "number"===l.kind||"color"===l.kind||"array"===l.kind&&"number"===l.itemType.kind&&"number"==typeof l.N?new $e(l,r,n,i,u):e.error("Type "+ee(l)+" is not interpolatable.")},$e.prototype.evaluate=function(t){var e=this.labels,r=this.outputs;if(1===e.length)return r[0].evaluate(t);var n=this.input.evaluate(t);if(n<=e[0])return r[0].evaluate(t);var i=e.length;if(n>=e[i-1])return r[i-1].evaluate(t);var a=Be(e,n),o=e[a],s=e[a+1],u=$e.interpolationFactor(this.interpolation,n,o,s),l=r[a].evaluate(t),p=r[a+1].evaluate(t);return "interpolate"===this.operator?Me[this.type.kind.toLowerCase()](l,p,u):"interpolate-hcl"===this.operator?He.reverse(He.interpolate(He.forward(l),He.forward(p),u)):Je.reverse(Je.interpolate(Je.forward(l),Je.forward(p),u))},$e.prototype.eachChild=function(t){t(this.input);for(var e=0,r=this.outputs;e=r.length)throw new fe("Array index out of bounds: "+e+" > "+(r.length-1)+".");if(e!==Math.floor(e))throw new fe("Array index must be an integer, but found "+e+" instead.");return r[e]},er.prototype.eachChild=function(t){t(this.index),t(this.input);},er.prototype.possibleOutputs=function(){return [void 0]},er.prototype.serialize=function(){return ["at",this.index.serialize(),this.input.serialize()]};var rr=function(t,e,r,n,i,a){this.inputType=t,this.type=e,this.input=r,this.cases=n,this.outputs=i,this.otherwise=a;};rr.parse=function(t,e){if(t.length<5)return e.error("Expected at least 4 arguments, but found only "+(t.length-1)+".");if(t.length%2!=1)return e.error("Expected an even number of arguments.");var r,n;e.expectedType&&"value"!==e.expectedType.kind&&(n=e.expectedType);for(var i={},a=[],o=2;oNumber.MAX_SAFE_INTEGER)return l.error("Branch labels must be integers no larger than "+Number.MAX_SAFE_INTEGER+".");if("number"==typeof h&&Math.floor(h)!==h)return l.error("Numeric branch labels must be integer values.");if(r){if(l.checkSubtype(r,pe(h)))return null}else r=pe(h);if(void 0!==i[String(h)])return l.error("Branch labels must be unique.");i[String(h)]=a.length;}var f=e.parse(u,o,n);if(!f)return null;n=n||f.type,a.push(f);}var y=e.parse(t[1],1,$t);if(!y)return null;var d=e.parse(t[t.length-1],t.length-1,n);return d?"value"!==y.type.kind&&e.concat(1).checkSubtype(r,y.type)?null:new rr(r,n,y,i,a,d):null},rr.prototype.evaluate=function(t){var e=this.input.evaluate(t);return (pe(e)===this.inputType&&this.outputs[this.cases[e]]||this.otherwise).evaluate(t)},rr.prototype.eachChild=function(t){t(this.input),this.outputs.forEach(t),t(this.otherwise);},rr.prototype.possibleOutputs=function(){var t;return (t=[]).concat.apply(t,this.outputs.map(function(t){return t.possibleOutputs()})).concat(this.otherwise.possibleOutputs())},rr.prototype.serialize=function(){for(var t=this,e=["match",this.input.serialize()],r=[],n={},i=0,a=Object.keys(this.cases).sort();i",function(t,e,r){return e>r},function(t,e,r,n){return n.compare(e,r)>0}),cr=or("<=",function(t,e,r){return e<=r},function(t,e,r,n){return n.compare(e,r)<=0}),hr=or(">=",function(t,e,r){return e>=r},function(t,e,r,n){return n.compare(e,r)>=0}),fr=function(t,e,r,n,i){this.type=Xt,this.number=t,this.locale=e,this.currency=r,this.minFractionDigits=n,this.maxFractionDigits=i;};fr.parse=function(t,e){if(3!==t.length)return e.error("Expected two arguments.");var r=e.parse(t[1],1,Gt);if(!r)return null;var n=t[2];if("object"!=typeof n||Array.isArray(n))return e.error("NumberFormat options argument must be an object.");var i=null;if(n.locale&&!(i=e.parse(n.locale,1,Xt)))return null;var a=null;if(n.currency&&!(a=e.parse(n.currency,1,Xt)))return null;var o=null;if(n["min-fraction-digits"]&&!(o=e.parse(n["min-fraction-digits"],1,Gt)))return null;var s=null;return n["max-fraction-digits"]&&!(s=e.parse(n["max-fraction-digits"],1,Gt))?null:new fr(r,i,a,o,s)},fr.prototype.evaluate=function(t){return new Intl.NumberFormat(this.locale?this.locale.evaluate(t):[],{style:this.currency?"currency":"decimal",currency:this.currency?this.currency.evaluate(t):void 0,minimumFractionDigits:this.minFractionDigits?this.minFractionDigits.evaluate(t):void 0,maximumFractionDigits:this.maxFractionDigits?this.maxFractionDigits.evaluate(t):void 0}).format(this.number.evaluate(t))},fr.prototype.eachChild=function(t){t(this.number),this.locale&&t(this.locale),this.currency&&t(this.currency),this.minFractionDigits&&t(this.minFractionDigits),this.maxFractionDigits&&t(this.maxFractionDigits);},fr.prototype.possibleOutputs=function(){return [void 0]},fr.prototype.serialize=function(){var t={};return this.locale&&(t.locale=this.locale.serialize()),this.currency&&(t.currency=this.currency.serialize()),this.minFractionDigits&&(t["min-fraction-digits"]=this.minFractionDigits.serialize()),this.maxFractionDigits&&(t["max-fraction-digits"]=this.maxFractionDigits.serialize()),["number-format",this.number.serialize(),t]};var yr=function(t){this.type=Gt,this.input=t;};yr.parse=function(t,e){if(2!==t.length)return e.error("Expected 1 argument, but found "+(t.length-1)+" instead.");var r=e.parse(t[1],1);return r?"array"!==r.type.kind&&"string"!==r.type.kind&&"value"!==r.type.kind?e.error("Expected argument of type string or array, but found "+ee(r.type)+" instead."):new yr(r):null},yr.prototype.evaluate=function(t){var e=this.input.evaluate(t);if("string"==typeof e)return e.length;if(Array.isArray(e))return e.length;throw new fe("Expected value to be of type string or array, but found "+ee(pe(e))+" instead.")},yr.prototype.eachChild=function(t){t(this.input);},yr.prototype.possibleOutputs=function(){return [void 0]},yr.prototype.serialize=function(){var t=["length"];return this.eachChild(function(e){t.push(e.serialize());}),t};var dr={"==":sr,"!=":ur,">":pr,"<":lr,">=":hr,"<=":cr,array:de,at:er,boolean:de,case:nr,coalesce:Qe,collator:we,format:me,interpolate:$e,"interpolate-hcl":$e,"interpolate-lab":$e,length:yr,let:tr,literal:he,match:rr,number:de,"number-format":fr,object:de,step:Ce,string:de,"to-boolean":ge,"to-color":ge,"to-number":ge,"to-string":ge,var:ze};function mr(t,e){var r=e[0],n=e[1],i=e[2],a=e[3];r=r.evaluate(t),n=n.evaluate(t),i=i.evaluate(t);var o=a?a.evaluate(t):1,s=le(r,n,i,o);if(s)throw new fe(s);return new ae(r/255*o,n/255*o,i/255*o,o)}function vr(t,e){return t in e}function gr(t,e){var r=e[t];return void 0===r?null:r}function xr(t){return {type:t}}function br(t){return {result:"success",value:t}}function _r(t){return {result:"error",value:t}}function wr(t){return "data-driven"===t["property-type"]||"cross-faded-data-driven"===t["property-type"]}function Ar(t){return !!t.expression&&t.expression.parameters.indexOf("zoom")>-1}function Sr(t){return !!t.expression&&t.expression.interpolated}function kr(t){return t instanceof Number?"number":t instanceof String?"string":t instanceof Boolean?"boolean":Array.isArray(t)?"array":null===t?"null":typeof t}function zr(t){return "object"==typeof t&&null!==t&&!Array.isArray(t)}function Ir(t){return t}function Br(t,e,r){return void 0!==t?t:void 0!==e?e:void 0!==r?r:void 0}function Cr(t,e,r,n,i){return Br(typeof r===i?n[r]:void 0,t.default,e.default)}function Er(t,e,r){if("number"!==kr(r))return Br(t.default,e.default);var n=t.stops.length;if(1===n)return t.stops[0][1];if(r<=t.stops[0][0])return t.stops[0][1];if(r>=t.stops[n-1][0])return t.stops[n-1][1];var i=Be(t.stops.map(function(t){return t[0]}),r);return t.stops[i][1]}function Mr(t,e,r){var n=void 0!==t.base?t.base:1;if("number"!==kr(r))return Br(t.default,e.default);var i=t.stops.length;if(1===i)return t.stops[0][1];if(r<=t.stops[0][0])return t.stops[0][1];if(r>=t.stops[i-1][0])return t.stops[i-1][1];var a=Be(t.stops.map(function(t){return t[0]}),r),o=function(t,e,r,n){var i=n-r,a=t-r;return 0===i?0:1===e?a/i:(Math.pow(e,a)-1)/(Math.pow(e,i)-1)}(r,n,t.stops[a][0],t.stops[a+1][0]),s=t.stops[a][1],u=t.stops[a+1][1],l=Me[e.type]||Ir;if(t.colorSpace&&"rgb"!==t.colorSpace){var p=Ye[t.colorSpace];l=function(t,e){return p.reverse(p.interpolate(p.forward(t),p.forward(e),o))};}return "function"==typeof s.evaluate?{evaluate:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];var r=s.evaluate.apply(void 0,t),n=u.evaluate.apply(void 0,t);if(void 0!==r&&void 0!==n)return l(r,n,o)}}:l(s,u,o)}function Tr(t,e,r){return "color"===e.type?r=ae.parse(r):"formatted"===e.type?r=ue.fromString(r.toString()):kr(r)===e.type||"enum"===e.type&&e.values[r]||(r=void 0),Br(r,t.default,e.default)}_e.register(dr,{error:[{kind:"error"},[Xt],function(t,e){var r=e[0];throw new fe(r.evaluate(t))}],typeof:[Xt,[$t],function(t,e){return ee(pe(e[0].evaluate(t)))}],"to-rgba":[te(Gt,4),[Ht],function(t,e){return e[0].evaluate(t).toArray()}],rgb:[Ht,[Gt,Gt,Gt],mr],rgba:[Ht,[Gt,Gt,Gt,Gt],mr],has:{type:Jt,overloads:[[[Xt],function(t,e){return vr(e[0].evaluate(t),t.properties())}],[[Xt,Yt],function(t,e){var r=e[0],n=e[1];return vr(r.evaluate(t),n.evaluate(t))}]]},get:{type:$t,overloads:[[[Xt],function(t,e){return gr(e[0].evaluate(t),t.properties())}],[[Xt,Yt],function(t,e){var r=e[0],n=e[1];return gr(r.evaluate(t),n.evaluate(t))}]]},"feature-state":[$t,[Xt],function(t,e){return gr(e[0].evaluate(t),t.featureState||{})}],properties:[Yt,[],function(t){return t.properties()}],"geometry-type":[Xt,[],function(t){return t.geometryType()}],id:[$t,[],function(t){return t.id()}],zoom:[Gt,[],function(t){return t.globals.zoom}],"heatmap-density":[Gt,[],function(t){return t.globals.heatmapDensity||0}],"line-progress":[Gt,[],function(t){return t.globals.lineProgress||0}],accumulated:[$t,[],function(t){return void 0===t.globals.accumulated?null:t.globals.accumulated}],"+":[Gt,xr(Gt),function(t,e){for(var r=0,n=0,i=e;n":[Jt,[Xt,$t],function(t,e){var r=e[0],n=e[1],i=t.properties()[r.value],a=n.value;return typeof i==typeof a&&i>a}],"filter-id->":[Jt,[$t],function(t,e){var r=e[0],n=t.id(),i=r.value;return typeof n==typeof i&&n>i}],"filter-<=":[Jt,[Xt,$t],function(t,e){var r=e[0],n=e[1],i=t.properties()[r.value],a=n.value;return typeof i==typeof a&&i<=a}],"filter-id-<=":[Jt,[$t],function(t,e){var r=e[0],n=t.id(),i=r.value;return typeof n==typeof i&&n<=i}],"filter->=":[Jt,[Xt,$t],function(t,e){var r=e[0],n=e[1],i=t.properties()[r.value],a=n.value;return typeof i==typeof a&&i>=a}],"filter-id->=":[Jt,[$t],function(t,e){var r=e[0],n=t.id(),i=r.value;return typeof n==typeof i&&n>=i}],"filter-has":[Jt,[$t],function(t,e){return e[0].value in t.properties()}],"filter-has-id":[Jt,[],function(t){return null!==t.id()}],"filter-type-in":[Jt,[te(Xt)],function(t,e){return e[0].value.indexOf(t.geometryType())>=0}],"filter-id-in":[Jt,[te($t)],function(t,e){return e[0].value.indexOf(t.id())>=0}],"filter-in-small":[Jt,[Xt,te($t)],function(t,e){var r=e[0];return e[1].value.indexOf(t.properties()[r.value])>=0}],"filter-in-large":[Jt,[Xt,te($t)],function(t,e){var r=e[0],n=e[1];return function(t,e,r,n){for(;r<=n;){var i=r+n>>1;if(e[i]===t)return !0;e[i]>t?n=i-1:r=i+1;}return !1}(t.properties()[r.value],n.value,0,n.value.length-1)}],all:{type:Jt,overloads:[[[Jt,Jt],function(t,e){var r=e[0],n=e[1];return r.evaluate(t)&&n.evaluate(t)}],[xr(Jt),function(t,e){for(var r=0,n=e;r0&&"string"==typeof t[0]&&t[0]in dr}function Fr(t,e){var r=new Ie(dr,[],e?function(t){var e={color:Ht,string:Xt,number:Gt,enum:Xt,boolean:Jt,formatted:Qt};if("array"===t.type)return te(e[t.value]||$t,t.length);return e[t.type]}(e):void 0),n=r.parse(t,void 0,void 0,void 0,e&&"string"===e.type?{typeAnnotation:"coerce"}:void 0);return n?br(new Pr(n,e)):_r(r.errors)}Pr.prototype.evaluateWithoutErrorHandling=function(t,e,r){return this._evaluator.globals=t,this._evaluator.feature=e,this._evaluator.featureState=r,this.expression.evaluate(this._evaluator)},Pr.prototype.evaluate=function(t,e,r){this._evaluator.globals=t,this._evaluator.feature=e||null,this._evaluator.featureState=r||null;try{var n=this.expression.evaluate(this._evaluator);if(null==n)return this._defaultValue;if(this._enumValues&&!(n in this._enumValues))throw new fe("Expected value to be one of "+Object.keys(this._enumValues).map(function(t){return JSON.stringify(t)}).join(", ")+", but found "+JSON.stringify(n)+" instead.");return n}catch(t){return this._warningHistory[t.message]||(this._warningHistory[t.message]=!0,"undefined"!=typeof console&&console.warn(t.message)),this._defaultValue}};var Lr=function(t,e){this.kind=t,this._styleExpression=e,this.isStateDependent="constant"!==t&&!Se(e.expression);};Lr.prototype.evaluateWithoutErrorHandling=function(t,e,r){return this._styleExpression.evaluateWithoutErrorHandling(t,e,r)},Lr.prototype.evaluate=function(t,e,r){return this._styleExpression.evaluate(t,e,r)};var Dr=function(t,e,r){this.kind=t,this.zoomStops=r.labels,this._styleExpression=e,this.isStateDependent="camera"!==t&&!Se(e.expression),r instanceof $e&&(this.interpolationType=r.interpolation);};function Or(t,e){if("error"===(t=Fr(t,e)).result)return t;var r=t.value.expression,n=Ae(r);if(!n&&!wr(e))return _r([new Nt("","data expressions not supported")]);var i=ke(r,["zoom"]);if(!i&&!Ar(e))return _r([new Nt("","zoom expressions not supported")]);var a=function t(e){var r=null;if(e instanceof tr)r=t(e.result);else if(e instanceof Qe)for(var n=0,i=e.args;nn.maximum?[new Dt(e,r,r+" is greater than the maximum value "+n.maximum)]:[]}function Nr(t){var e,r,n,i=t.valueSpec,a=jt(t.value.type),o={},s="categorical"!==a&&void 0===t.value.property,u=!s,l="array"===kr(t.value.stops)&&"array"===kr(t.value.stops[0])&&"object"===kr(t.value.stops[0][0]),p=Ur({key:t.key,value:t.value,valueSpec:t.styleSpec.function,style:t.style,styleSpec:t.styleSpec,objectElementValidators:{stops:function(t){if("identity"===a)return [new Dt(t.key,t.value,'identity function may not have a "stops" property')];var e=[],r=t.value;e=e.concat(jr({key:t.key,value:r,valueSpec:t.valueSpec,style:t.style,styleSpec:t.styleSpec,arrayElementValidator:c})),"array"===kr(r)&&0===r.length&&e.push(new Dt(t.key,r,"array must have at least one stop"));return e},default:function(t){return cn({key:t.key,value:t.value,valueSpec:i,style:t.style,styleSpec:t.styleSpec})}}});return "identity"===a&&s&&p.push(new Dt(t.key,t.value,'missing required property "property"')),"identity"===a||t.value.stops||p.push(new Dt(t.key,t.value,'missing required property "stops"')),"exponential"===a&&t.valueSpec.expression&&!Sr(t.valueSpec)&&p.push(new Dt(t.key,t.value,"exponential functions not supported")),t.styleSpec.$version>=8&&(u&&!wr(t.valueSpec)?p.push(new Dt(t.key,t.value,"property functions not supported")):s&&!Ar(t.valueSpec)&&p.push(new Dt(t.key,t.value,"zoom functions not supported"))),"categorical"!==a&&!l||void 0!==t.value.property||p.push(new Dt(t.key,t.value,'"property" property is required')),p;function c(t){var e=[],a=t.value,s=t.key;if("array"!==kr(a))return [new Dt(s,a,"array expected, "+kr(a)+" found")];if(2!==a.length)return [new Dt(s,a,"array length 2 expected, length "+a.length+" found")];if(l){if("object"!==kr(a[0]))return [new Dt(s,a,"object expected, "+kr(a[0])+" found")];if(void 0===a[0].zoom)return [new Dt(s,a,"object stop key must have zoom")];if(void 0===a[0].value)return [new Dt(s,a,"object stop key must have value")];if(n&&n>jt(a[0].zoom))return [new Dt(s,a[0].zoom,"stop zoom values must appear in ascending order")];jt(a[0].zoom)!==n&&(n=jt(a[0].zoom),r=void 0,o={}),e=e.concat(Ur({key:s+"[0]",value:a[0],valueSpec:{zoom:{}},style:t.style,styleSpec:t.styleSpec,objectElementValidators:{zoom:qr,value:h}}));}else e=e.concat(h({key:s+"[0]",value:a[0],valueSpec:{},style:t.style,styleSpec:t.styleSpec},a));return Vr(qt(a[1]))?e.concat([new Dt(s+"[1]",a[1],"expressions are not allowed in function stops.")]):e.concat(cn({key:s+"[1]",value:a[1],valueSpec:i,style:t.style,styleSpec:t.styleSpec}))}function h(t,n){var s=kr(t.value),u=jt(t.value),l=null!==t.value?t.value:n;if(e){if(s!==e)return [new Dt(t.key,l,s+" stop domain type must match previous stop domain type "+e)]}else e=s;if("number"!==s&&"string"!==s&&"boolean"!==s)return [new Dt(t.key,l,"stop domain value must be a number, string, or boolean")];if("number"!==s&&"categorical"!==a){var p="number expected, "+s+" found";return wr(i)&&void 0===a&&(p+='\nIf you intended to use a categorical function, specify `"type": "categorical"`.'),[new Dt(t.key,l,p)]}return "categorical"!==a||"number"!==s||isFinite(u)&&Math.floor(u)===u?"categorical"!==a&&"number"===s&&void 0!==r&&u=2&&"$id"!==t[1]&&"$type"!==t[1];case"in":case"!in":case"!has":case"none":return !1;case"==":case"!=":case">":case">=":case"<":case"<=":return 3!==t.length||Array.isArray(t[1])||Array.isArray(t[2]);case"any":case"all":for(var e=0,r=t.slice(1);ee?1:0}function Yr(t){if(!t)return !0;var e,r=t[0];return t.length<=1?"any"!==r:"=="===r?$r(t[1],t[2],"=="):"!="===r?tn($r(t[1],t[2],"==")):"<"===r||">"===r||"<="===r||">="===r?$r(t[1],t[2],r):"any"===r?(e=t.slice(1),["any"].concat(e.map(Yr))):"all"===r?["all"].concat(t.slice(1).map(Yr)):"none"===r?["all"].concat(t.slice(1).map(Yr).map(tn)):"in"===r?Wr(t[1],t.slice(2)):"!in"===r?tn(Wr(t[1],t.slice(2))):"has"===r?Qr(t[1]):"!has"!==r||tn(Qr(t[1]))}function $r(t,e,r){switch(t){case"$type":return ["filter-type-"+r,e];case"$id":return ["filter-id-"+r,e];default:return ["filter-"+r,t,e]}}function Wr(t,e){if(0===e.length)return !1;switch(t){case"$type":return ["filter-type-in",["literal",e]];case"$id":return ["filter-id-in",["literal",e]];default:return e.length>200&&!e.some(function(t){return typeof t!=typeof e[0]})?["filter-in-large",t,["literal",e.sort(Hr)]]:["filter-in-small",t,["literal",e]]}}function Qr(t){switch(t){case"$type":return !0;case"$id":return ["filter-has-id"];default:return ["filter-has",t]}}function tn(t){return ["!",t]}function en(t){return Gr(qt(t.value))?Zr(Rt({},t,{expressionContext:"filter",valueSpec:{value:"boolean"}})):function t(e){var r=e.value;var n=e.key;if("array"!==kr(r))return [new Dt(n,r,"array expected, "+kr(r)+" found")];var i=e.styleSpec;var a;var o=[];if(r.length<1)return [new Dt(n,r,"filter array must have at least 1 element")];o=o.concat(Kr({key:n+"[0]",value:r[0],valueSpec:i.filter_operator,style:e.style,styleSpec:e.styleSpec}));switch(jt(r[0])){case"<":case"<=":case">":case">=":r.length>=2&&"$type"===jt(r[1])&&o.push(new Dt(n,r,'"$type" cannot be use with operator "'+r[0]+'"'));case"==":case"!=":3!==r.length&&o.push(new Dt(n,r,'filter array for operator "'+r[0]+'" must have 3 elements'));case"in":case"!in":r.length>=2&&"string"!==(a=kr(r[1]))&&o.push(new Dt(n+"[1]",r[1],"string expected, "+a+" found"));for(var s=2;s=p[f+0]&&n>=p[f+1])?(o[h]=!0,a.push(l[h])):o[h]=!1;}}},An.prototype._forEachCell=function(t,e,r,n,i,a,o,s){for(var u=this._convertToCellCoord(t),l=this._convertToCellCoord(e),p=this._convertToCellCoord(r),c=this._convertToCellCoord(n),h=u;h<=p;h++)for(var f=l;f<=c;f++){var y=this.d*f+h;if((!s||s(this._convertFromCellCoord(h),this._convertFromCellCoord(f),this._convertFromCellCoord(h+1),this._convertFromCellCoord(f+1)))&&i.call(this,t,e,r,n,y,a,o,s))return}},An.prototype._convertFromCellCoord=function(t){return (t-this.padding)/this.scale},An.prototype._convertToCellCoord=function(t){return Math.max(0,Math.min(this.d-1,Math.floor(t*this.scale)+this.padding))},An.prototype.toArrayBuffer=function(){if(this.arrayBuffer)return this.arrayBuffer;for(var t=this.cells,e=wn+this.cells.length+1+1,r=0,n=0;n=0)){var c=t[p];l[p]=kn[u].shallow.indexOf(p)>=0?c:Bn(c,e);}t instanceof Error&&(l.message=t.message);}if(l.$name)throw new Error("$name property is reserved for worker serialization logic.");return "Object"!==u&&(l.$name=u),l}throw new Error("can't serialize object of type "+typeof t)}function Cn(t){if(null==t||"boolean"==typeof t||"number"==typeof t||"string"==typeof t||t instanceof Boolean||t instanceof Number||t instanceof String||t instanceof Date||t instanceof RegExp||t instanceof ArrayBuffer||ArrayBuffer.isView(t)||t instanceof Sn)return t;if(Array.isArray(t))return t.map(Cn);if("object"==typeof t){var e=t.$name||"Object",r=kn[e].klass;if(!r)throw new Error("can't deserialize unregistered class "+e);if(r.deserialize)return r.deserialize(t);for(var n=Object.create(r.prototype),i=0,a=Object.keys(t);i=0?s:Cn(s);}}return n}throw new Error("can't deserialize object of type "+typeof t)}var En=function(){this.first=!0;};En.prototype.update=function(t,e){var r=Math.floor(t);return this.first?(this.first=!1,this.lastIntegerZoom=r,this.lastIntegerZoomTime=0,this.lastZoom=t,this.lastFloorZoom=r,!0):(this.lastFloorZoom>r?(this.lastIntegerZoom=r+1,this.lastIntegerZoomTime=e):this.lastFloorZoom=128&&t<=255},Arabic:function(t){return t>=1536&&t<=1791},"Arabic Supplement":function(t){return t>=1872&&t<=1919},"Arabic Extended-A":function(t){return t>=2208&&t<=2303},"Hangul Jamo":function(t){return t>=4352&&t<=4607},"Unified Canadian Aboriginal Syllabics":function(t){return t>=5120&&t<=5759},Khmer:function(t){return t>=6016&&t<=6143},"Unified Canadian Aboriginal Syllabics Extended":function(t){return t>=6320&&t<=6399},"General Punctuation":function(t){return t>=8192&&t<=8303},"Letterlike Symbols":function(t){return t>=8448&&t<=8527},"Number Forms":function(t){return t>=8528&&t<=8591},"Miscellaneous Technical":function(t){return t>=8960&&t<=9215},"Control Pictures":function(t){return t>=9216&&t<=9279},"Optical Character Recognition":function(t){return t>=9280&&t<=9311},"Enclosed Alphanumerics":function(t){return t>=9312&&t<=9471},"Geometric Shapes":function(t){return t>=9632&&t<=9727},"Miscellaneous Symbols":function(t){return t>=9728&&t<=9983},"Miscellaneous Symbols and Arrows":function(t){return t>=11008&&t<=11263},"CJK Radicals Supplement":function(t){return t>=11904&&t<=12031},"Kangxi Radicals":function(t){return t>=12032&&t<=12255},"Ideographic Description Characters":function(t){return t>=12272&&t<=12287},"CJK Symbols and Punctuation":function(t){return t>=12288&&t<=12351},Hiragana:function(t){return t>=12352&&t<=12447},Katakana:function(t){return t>=12448&&t<=12543},Bopomofo:function(t){return t>=12544&&t<=12591},"Hangul Compatibility Jamo":function(t){return t>=12592&&t<=12687},Kanbun:function(t){return t>=12688&&t<=12703},"Bopomofo Extended":function(t){return t>=12704&&t<=12735},"CJK Strokes":function(t){return t>=12736&&t<=12783},"Katakana Phonetic Extensions":function(t){return t>=12784&&t<=12799},"Enclosed CJK Letters and Months":function(t){return t>=12800&&t<=13055},"CJK Compatibility":function(t){return t>=13056&&t<=13311},"CJK Unified Ideographs Extension A":function(t){return t>=13312&&t<=19903},"Yijing Hexagram Symbols":function(t){return t>=19904&&t<=19967},"CJK Unified Ideographs":function(t){return t>=19968&&t<=40959},"Yi Syllables":function(t){return t>=40960&&t<=42127},"Yi Radicals":function(t){return t>=42128&&t<=42191},"Hangul Jamo Extended-A":function(t){return t>=43360&&t<=43391},"Hangul Syllables":function(t){return t>=44032&&t<=55215},"Hangul Jamo Extended-B":function(t){return t>=55216&&t<=55295},"Private Use Area":function(t){return t>=57344&&t<=63743},"CJK Compatibility Ideographs":function(t){return t>=63744&&t<=64255},"Arabic Presentation Forms-A":function(t){return t>=64336&&t<=65023},"Vertical Forms":function(t){return t>=65040&&t<=65055},"CJK Compatibility Forms":function(t){return t>=65072&&t<=65103},"Small Form Variants":function(t){return t>=65104&&t<=65135},"Arabic Presentation Forms-B":function(t){return t>=65136&&t<=65279},"Halfwidth and Fullwidth Forms":function(t){return t>=65280&&t<=65519}};function Tn(t){for(var e=0,r=t;e=65097&&t<=65103)||(!!Mn["CJK Compatibility Ideographs"](t)||(!!Mn["CJK Compatibility"](t)||(!!Mn["CJK Radicals Supplement"](t)||(!!Mn["CJK Strokes"](t)||(!(!Mn["CJK Symbols and Punctuation"](t)||t>=12296&&t<=12305||t>=12308&&t<=12319||12336===t)||(!!Mn["CJK Unified Ideographs Extension A"](t)||(!!Mn["CJK Unified Ideographs"](t)||(!!Mn["Enclosed CJK Letters and Months"](t)||(!!Mn["Hangul Compatibility Jamo"](t)||(!!Mn["Hangul Jamo Extended-A"](t)||(!!Mn["Hangul Jamo Extended-B"](t)||(!!Mn["Hangul Jamo"](t)||(!!Mn["Hangul Syllables"](t)||(!!Mn.Hiragana(t)||(!!Mn["Ideographic Description Characters"](t)||(!!Mn.Kanbun(t)||(!!Mn["Kangxi Radicals"](t)||(!!Mn["Katakana Phonetic Extensions"](t)||(!(!Mn.Katakana(t)||12540===t)||(!(!Mn["Halfwidth and Fullwidth Forms"](t)||65288===t||65289===t||65293===t||t>=65306&&t<=65310||65339===t||65341===t||65343===t||t>=65371&&t<=65503||65507===t||t>=65512&&t<=65519)||(!(!Mn["Small Form Variants"](t)||t>=65112&&t<=65118||t>=65123&&t<=65126)||(!!Mn["Unified Canadian Aboriginal Syllabics"](t)||(!!Mn["Unified Canadian Aboriginal Syllabics Extended"](t)||(!!Mn["Vertical Forms"](t)||(!!Mn["Yijing Hexagram Symbols"](t)||(!!Mn["Yi Syllables"](t)||!!Mn["Yi Radicals"](t))))))))))))))))))))))))))))))}function Ln(t){return !(Fn(t)||function(t){return !!(Mn["Latin-1 Supplement"](t)&&(167===t||169===t||174===t||177===t||188===t||189===t||190===t||215===t||247===t)||Mn["General Punctuation"](t)&&(8214===t||8224===t||8225===t||8240===t||8241===t||8251===t||8252===t||8258===t||8263===t||8264===t||8265===t||8273===t)||Mn["Letterlike Symbols"](t)||Mn["Number Forms"](t)||Mn["Miscellaneous Technical"](t)&&(t>=8960&&t<=8967||t>=8972&&t<=8991||t>=8996&&t<=9e3||9003===t||t>=9085&&t<=9114||t>=9150&&t<=9165||9167===t||t>=9169&&t<=9179||t>=9186&&t<=9215)||Mn["Control Pictures"](t)&&9251!==t||Mn["Optical Character Recognition"](t)||Mn["Enclosed Alphanumerics"](t)||Mn["Geometric Shapes"](t)||Mn["Miscellaneous Symbols"](t)&&!(t>=9754&&t<=9759)||Mn["Miscellaneous Symbols and Arrows"](t)&&(t>=11026&&t<=11055||t>=11088&&t<=11097||t>=11192&&t<=11243)||Mn["CJK Symbols and Punctuation"](t)||Mn.Katakana(t)||Mn["Private Use Area"](t)||Mn["CJK Compatibility Forms"](t)||Mn["Small Form Variants"](t)||Mn["Halfwidth and Fullwidth Forms"](t)||8734===t||8756===t||8757===t||t>=9984&&t<=10087||t>=10102&&t<=10131||65532===t||65533===t)}(t))}function Dn(t,e){return !(!e&&(t>=1424&&t<=2303||Mn["Arabic Presentation Forms-A"](t)||Mn["Arabic Presentation Forms-B"](t)))&&!(t>=2304&&t<=3583||t>=3840&&t<=4255||Mn.Khmer(t))}var On,Rn=!1,Un=null,jn=!1,qn=new Ft,Nn={applyArabicShaping:null,processBidirectionalText:null,processStyledBidirectionalText:null,isLoaded:function(){return jn||null!=Nn.applyArabicShaping}},Zn=function(t,e){this.zoom=t,e?(this.now=e.now,this.fadeDuration=e.fadeDuration,this.zoomHistory=e.zoomHistory,this.transition=e.transition):(this.now=0,this.fadeDuration=0,this.zoomHistory=new En,this.transition={});};Zn.prototype.isSupportedScript=function(t){return function(t,e){for(var r=0,n=t;rthis.zoomHistory.lastIntegerZoom?{fromScale:2,toScale:1,t:e+(1-e)*r}:{fromScale:.5,toScale:1,t:1-(1-r)*e}};var Kn=function(t,e){this.property=t,this.value=e,this.expression=function(t,e){if(zr(t))return new Rr(t,e);if(Vr(t)){var r=Or(t,e);if("error"===r.result)throw new Error(r.value.map(function(t){return t.key+": "+t.message}).join(", "));return r.value}var n=t;return "string"==typeof t&&"color"===e.type&&(n=ae.parse(t)),{kind:"constant",evaluate:function(){return n}}}(void 0===e?t.specification.default:e,t.specification);};Kn.prototype.isDataDriven=function(){return "source"===this.expression.kind||"composite"===this.expression.kind},Kn.prototype.possiblyEvaluate=function(t){return this.property.possiblyEvaluate(this,t)};var Gn=function(t){this.property=t,this.value=new Kn(t,void 0);};Gn.prototype.transitioned=function(t,e){return new Jn(this.property,this.value,e,c({},t.transition,this.transition),t.now)},Gn.prototype.untransitioned=function(){return new Jn(this.property,this.value,null,{},0)};var Xn=function(t){this._properties=t,this._values=Object.create(t.defaultTransitionablePropertyValues);};Xn.prototype.getValue=function(t){return b(this._values[t].value.value)},Xn.prototype.setValue=function(t,e){this._values.hasOwnProperty(t)||(this._values[t]=new Gn(this._values[t].property)),this._values[t].value=new Kn(this._values[t].property,null===e?void 0:b(e));},Xn.prototype.getTransition=function(t){return b(this._values[t].transition)},Xn.prototype.setTransition=function(t,e){this._values.hasOwnProperty(t)||(this._values[t]=new Gn(this._values[t].property)),this._values[t].transition=b(e)||void 0;},Xn.prototype.serialize=function(){for(var t={},e=0,r=Object.keys(this._values);ethis.end)return this.prior=null,r;if(this.value.isDataDriven())return this.prior=null,r;if(e=1)return 1;var e=t*t,r=e*t;return 4*(t<.5?r:3*(t-e)+r-.75)}(i))}return r};var Hn=function(t){this._properties=t,this._values=Object.create(t.defaultTransitioningPropertyValues);};Hn.prototype.possiblyEvaluate=function(t){for(var e=new Wn(this._properties),r=0,n=Object.keys(this._values);rn.zoomHistory.lastIntegerZoom?{from:t,to:e}:{from:r,to:e}},e.prototype.interpolate=function(t){return t},e}(ti),ri=function(t){this.specification=t;};ri.prototype.possiblyEvaluate=function(t,e){if(void 0!==t.value){if("constant"===t.expression.kind){var r=t.expression.evaluate(e);return this._calculate(r,r,r,e)}return this._calculate(t.expression.evaluate(new Zn(Math.floor(e.zoom-1),e)),t.expression.evaluate(new Zn(Math.floor(e.zoom),e)),t.expression.evaluate(new Zn(Math.floor(e.zoom+1),e)),e)}},ri.prototype._calculate=function(t,e,r,n){return n.zoom>n.zoomHistory.lastIntegerZoom?{from:t,to:e}:{from:r,to:e}},ri.prototype.interpolate=function(t){return t};var ni=function(t){this.specification=t;};ni.prototype.possiblyEvaluate=function(t,e){return !!t.expression.evaluate(e)},ni.prototype.interpolate=function(){return !1};var ii=function(t){for(var e in this.properties=t,this.defaultPropertyValues={},this.defaultTransitionablePropertyValues={},this.defaultTransitioningPropertyValues={},this.defaultPossiblyEvaluatedValues={},t){var r=t[e],n=this.defaultPropertyValues[e]=new Kn(r,void 0),i=this.defaultTransitionablePropertyValues[e]=new Gn(r);this.defaultTransitioningPropertyValues[e]=i.untransitioned(),this.defaultPossiblyEvaluatedValues[e]=n.possiblyEvaluate({});}};zn("DataDrivenProperty",ti),zn("DataConstantProperty",Qn),zn("CrossFadedDataDrivenProperty",ei),zn("CrossFadedProperty",ri),zn("ColorRampProperty",ni);var ai=function(t){function e(e,r){if(t.call(this),this.id=e.id,this.type=e.type,this._featureFilter=function(){return !0},"custom"!==e.type&&(e=e,this.metadata=e.metadata,this.minzoom=e.minzoom,this.maxzoom=e.maxzoom,"background"!==e.type&&(this.source=e.source,this.sourceLayer=e["source-layer"],this.filter=e.filter),r.layout&&(this._unevaluatedLayout=new Yn(r.layout)),r.paint)){for(var n in this._transitionablePaint=new Xn(r.paint),e.paint)this.setPaintProperty(n,e.paint[n],{validate:!1});for(var i in e.layout)this.setLayoutProperty(i,e.layout[i],{validate:!1});this._transitioningPaint=this._transitionablePaint.untransitioned();}}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.getCrossfadeParameters=function(){return this._crossfadeParameters},e.prototype.getLayoutProperty=function(t){return "visibility"===t?this.visibility:this._unevaluatedLayout.getValue(t)},e.prototype.setLayoutProperty=function(t,e,r){if(void 0===r&&(r={}),null!=e){var n="layers."+this.id+".layout."+t;if(this._validate(xn,n,t,e,r))return}"visibility"!==t?this._unevaluatedLayout.setValue(t,e):this.visibility=e;},e.prototype.getPaintProperty=function(t){return v(t,"-transition")?this._transitionablePaint.getTransition(t.slice(0,-"-transition".length)):this._transitionablePaint.getValue(t)},e.prototype.setPaintProperty=function(t,e,r){if(void 0===r&&(r={}),null!=e){var n="layers."+this.id+".paint."+t;if(this._validate(gn,n,t,e,r))return !1}if(v(t,"-transition"))return this._transitionablePaint.setTransition(t.slice(0,-"-transition".length),e||void 0),!1;var i=this._transitionablePaint._values[t],a="cross-faded-data-driven"===i.property.specification["property-type"],o=i.value.isDataDriven();return this._transitionablePaint.setValue(t,e),this._handleSpecialPaintPropertyUpdate(t),this._transitionablePaint._values[t].value.isDataDriven()||o||a},e.prototype._handleSpecialPaintPropertyUpdate=function(t){},e.prototype.isHidden=function(t){return !!(this.minzoom&&t=this.maxzoom)||"none"===this.visibility)},e.prototype.updateTransitions=function(t){this._transitioningPaint=this._transitionablePaint.transitioned(t,this._transitioningPaint);},e.prototype.hasTransition=function(){return this._transitioningPaint.hasTransition()},e.prototype.recalculate=function(t){t.getCrossfadeParameters&&(this._crossfadeParameters=t.getCrossfadeParameters()),this._unevaluatedLayout&&(this.layout=this._unevaluatedLayout.possiblyEvaluate(t)),this.paint=this._transitioningPaint.possiblyEvaluate(t);},e.prototype.serialize=function(){var t={id:this.id,type:this.type,source:this.source,"source-layer":this.sourceLayer,metadata:this.metadata,minzoom:this.minzoom,maxzoom:this.maxzoom,filter:this.filter,layout:this._unevaluatedLayout&&this._unevaluatedLayout.serialize(),paint:this._transitionablePaint&&this._transitionablePaint.serialize()};return this.visibility&&(t.layout=t.layout||{},t.layout.visibility=this.visibility),x(t,function(t,e){return !(void 0===t||"layout"===e&&!Object.keys(t).length||"paint"===e&&!Object.keys(t).length)})},e.prototype._validate=function(t,e,r,n,i){return void 0===i&&(i={}),(!i||!1!==i.validate)&&bn(this,t.call(mn,{key:e,layerType:this.type,objectKey:r,value:n,styleSpec:Lt,style:{glyphs:!0,sprite:!0}}))},e.prototype.is3D=function(){return !1},e.prototype.isTileClipped=function(){return !1},e.prototype.hasOffscreenPass=function(){return !1},e.prototype.resize=function(){},e.prototype.isStateDependent=function(){for(var t in this.paint._values){var e=this.paint.get(t);if(e instanceof $n&&wr(e.property.specification)&&(("source"===e.value.kind||"composite"===e.value.kind)&&e.value.isStateDependent))return !0}return !1},e}(Ft),oi={Int8:Int8Array,Uint8:Uint8Array,Int16:Int16Array,Uint16:Uint16Array,Int32:Int32Array,Uint32:Uint32Array,Float32:Float32Array},si=function(t,e){this._structArray=t,this._pos1=e*this.size,this._pos2=this._pos1/2,this._pos4=this._pos1/4,this._pos8=this._pos1/8;},ui=function(){this.isTransferred=!1,this.capacity=-1,this.resize(0);};function li(t,e){void 0===e&&(e=1);var r=0,n=0;return {members:t.map(function(t){var i,a=(i=t.type,oi[i].BYTES_PER_ELEMENT),o=r=pi(r,Math.max(e,a)),s=t.components||1;return n=Math.max(n,a),r+=a*s,{name:t.name,type:t.type,components:s,offset:o}}),size:pi(r,Math.max(n,e)),alignment:e}}function pi(t,e){return Math.ceil(t/e)*e}ui.serialize=function(t,e){return t._trim(),e&&(t.isTransferred=!0,e.push(t.arrayBuffer)),{length:t.length,arrayBuffer:t.arrayBuffer}},ui.deserialize=function(t){var e=Object.create(this.prototype);return e.arrayBuffer=t.arrayBuffer,e.length=t.length,e.capacity=t.arrayBuffer.byteLength/e.bytesPerElement,e._refreshViews(),e},ui.prototype._trim=function(){this.length!==this.capacity&&(this.capacity=this.length,this.arrayBuffer=this.arrayBuffer.slice(0,this.length*this.bytesPerElement),this._refreshViews());},ui.prototype.clear=function(){this.length=0;},ui.prototype.resize=function(t){this.reserve(t),this.length=t;},ui.prototype.reserve=function(t){if(t>this.capacity){this.capacity=Math.max(t,Math.floor(5*this.capacity),128),this.arrayBuffer=new ArrayBuffer(this.capacity*this.bytesPerElement);var e=this.uint8;this._refreshViews(),e&&this.uint8.set(e);}},ui.prototype._refreshViews=function(){throw new Error("_refreshViews() must be implemented by each concrete StructArray layout")};var ci=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e){var r=this.length;return this.resize(r+1),this.emplace(r,t,e)},e.prototype.emplace=function(t,e,r){var n=2*t;return this.int16[n+0]=e,this.int16[n+1]=r,t},e}(ui);ci.prototype.bytesPerElement=4,zn("StructArrayLayout2i4",ci);var hi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n){var i=this.length;return this.resize(i+1),this.emplace(i,t,e,r,n)},e.prototype.emplace=function(t,e,r,n,i){var a=4*t;return this.int16[a+0]=e,this.int16[a+1]=r,this.int16[a+2]=n,this.int16[a+3]=i,t},e}(ui);hi.prototype.bytesPerElement=8,zn("StructArrayLayout4i8",hi);var fi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,a){var o=this.length;return this.resize(o+1),this.emplace(o,t,e,r,n,i,a)},e.prototype.emplace=function(t,e,r,n,i,a,o){var s=6*t;return this.int16[s+0]=e,this.int16[s+1]=r,this.int16[s+2]=n,this.int16[s+3]=i,this.int16[s+4]=a,this.int16[s+5]=o,t},e}(ui);fi.prototype.bytesPerElement=12,zn("StructArrayLayout2i4i12",fi);var yi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,a){var o=this.length;return this.resize(o+1),this.emplace(o,t,e,r,n,i,a)},e.prototype.emplace=function(t,e,r,n,i,a,o){var s=4*t,u=8*t;return this.int16[s+0]=e,this.int16[s+1]=r,this.uint8[u+4]=n,this.uint8[u+5]=i,this.uint8[u+6]=a,this.uint8[u+7]=o,t},e}(ui);yi.prototype.bytesPerElement=8,zn("StructArrayLayout2i4ub8",yi);var di=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,a,o,s){var u=this.length;return this.resize(u+1),this.emplace(u,t,e,r,n,i,a,o,s)},e.prototype.emplace=function(t,e,r,n,i,a,o,s,u){var l=8*t;return this.uint16[l+0]=e,this.uint16[l+1]=r,this.uint16[l+2]=n,this.uint16[l+3]=i,this.uint16[l+4]=a,this.uint16[l+5]=o,this.uint16[l+6]=s,this.uint16[l+7]=u,t},e}(ui);di.prototype.bytesPerElement=16,zn("StructArrayLayout8ui16",di);var mi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,a,o,s){var u=this.length;return this.resize(u+1),this.emplace(u,t,e,r,n,i,a,o,s)},e.prototype.emplace=function(t,e,r,n,i,a,o,s,u){var l=8*t;return this.int16[l+0]=e,this.int16[l+1]=r,this.int16[l+2]=n,this.int16[l+3]=i,this.uint16[l+4]=a,this.uint16[l+5]=o,this.uint16[l+6]=s,this.uint16[l+7]=u,t},e}(ui);mi.prototype.bytesPerElement=16,zn("StructArrayLayout4i4ui16",mi);var vi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r){var n=this.length;return this.resize(n+1),this.emplace(n,t,e,r)},e.prototype.emplace=function(t,e,r,n){var i=3*t;return this.float32[i+0]=e,this.float32[i+1]=r,this.float32[i+2]=n,t},e}(ui);vi.prototype.bytesPerElement=12,zn("StructArrayLayout3f12",vi);var gi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t){var e=this.length;return this.resize(e+1),this.emplace(e,t)},e.prototype.emplace=function(t,e){var r=1*t;return this.uint32[r+0]=e,t},e}(ui);gi.prototype.bytesPerElement=4,zn("StructArrayLayout1ul4",gi);var xi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,a,o,s,u,l,p){var c=this.length;return this.resize(c+1),this.emplace(c,t,e,r,n,i,a,o,s,u,l,p)},e.prototype.emplace=function(t,e,r,n,i,a,o,s,u,l,p,c){var h=12*t,f=6*t;return this.int16[h+0]=e,this.int16[h+1]=r,this.int16[h+2]=n,this.int16[h+3]=i,this.int16[h+4]=a,this.int16[h+5]=o,this.uint32[f+3]=s,this.uint16[h+8]=u,this.uint16[h+9]=l,this.int16[h+10]=p,this.int16[h+11]=c,t},e}(ui);xi.prototype.bytesPerElement=24,zn("StructArrayLayout6i1ul2ui2i24",xi);var bi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,a){var o=this.length;return this.resize(o+1),this.emplace(o,t,e,r,n,i,a)},e.prototype.emplace=function(t,e,r,n,i,a,o){var s=6*t;return this.int16[s+0]=e,this.int16[s+1]=r,this.int16[s+2]=n,this.int16[s+3]=i,this.int16[s+4]=a,this.int16[s+5]=o,t},e}(ui);bi.prototype.bytesPerElement=12,zn("StructArrayLayout2i2i2i12",bi);var _i=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n){var i=this.length;return this.resize(i+1),this.emplace(i,t,e,r,n)},e.prototype.emplace=function(t,e,r,n,i){var a=12*t,o=3*t;return this.uint8[a+0]=e,this.uint8[a+1]=r,this.float32[o+1]=n,this.float32[o+2]=i,t},e}(ui);_i.prototype.bytesPerElement=12,zn("StructArrayLayout2ub2f12",_i);var wi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,a,o,s,u,l,p,c,h,f,y){var d=this.length;return this.resize(d+1),this.emplace(d,t,e,r,n,i,a,o,s,u,l,p,c,h,f,y)},e.prototype.emplace=function(t,e,r,n,i,a,o,s,u,l,p,c,h,f,y,d){var m=22*t,v=11*t,g=44*t;return this.int16[m+0]=e,this.int16[m+1]=r,this.uint16[m+2]=n,this.uint16[m+3]=i,this.uint32[v+2]=a,this.uint32[v+3]=o,this.uint32[v+4]=s,this.uint16[m+10]=u,this.uint16[m+11]=l,this.uint16[m+12]=p,this.float32[v+7]=c,this.float32[v+8]=h,this.uint8[g+36]=f,this.uint8[g+37]=y,this.uint32[v+10]=d,t},e}(ui);wi.prototype.bytesPerElement=44,zn("StructArrayLayout2i2ui3ul3ui2f2ub1ul44",wi);var Ai=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n,i,a,o,s,u,l,p,c,h,f,y,d,m,v){var g=this.length;return this.resize(g+1),this.emplace(g,t,e,r,n,i,a,o,s,u,l,p,c,h,f,y,d,m,v)},e.prototype.emplace=function(t,e,r,n,i,a,o,s,u,l,p,c,h,f,y,d,m,v,g){var x=22*t,b=11*t;return this.int16[x+0]=e,this.int16[x+1]=r,this.int16[x+2]=n,this.int16[x+3]=i,this.int16[x+4]=a,this.int16[x+5]=o,this.uint16[x+6]=s,this.uint16[x+7]=u,this.uint16[x+8]=l,this.uint16[x+9]=p,this.uint16[x+10]=c,this.uint16[x+11]=h,this.uint16[x+12]=f,this.uint16[x+13]=y,this.uint16[x+14]=d,this.uint32[b+8]=m,this.float32[b+9]=v,this.float32[b+10]=g,t},e}(ui);Ai.prototype.bytesPerElement=44,zn("StructArrayLayout6i9ui1ul2f44",Ai);var Si=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t){var e=this.length;return this.resize(e+1),this.emplace(e,t)},e.prototype.emplace=function(t,e){var r=1*t;return this.float32[r+0]=e,t},e}(ui);Si.prototype.bytesPerElement=4,zn("StructArrayLayout1f4",Si);var ki=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.int16=new Int16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r){var n=this.length;return this.resize(n+1),this.emplace(n,t,e,r)},e.prototype.emplace=function(t,e,r,n){var i=3*t;return this.int16[i+0]=e,this.int16[i+1]=r,this.int16[i+2]=n,t},e}(ui);ki.prototype.bytesPerElement=6,zn("StructArrayLayout3i6",ki);var zi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint32=new Uint32Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r){var n=this.length;return this.resize(n+1),this.emplace(n,t,e,r)},e.prototype.emplace=function(t,e,r,n){var i=2*t,a=4*t;return this.uint32[i+0]=e,this.uint16[a+2]=r,this.uint16[a+3]=n,t},e}(ui);zi.prototype.bytesPerElement=8,zn("StructArrayLayout1ul2ui8",zi);var Ii=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r){var n=this.length;return this.resize(n+1),this.emplace(n,t,e,r)},e.prototype.emplace=function(t,e,r,n){var i=3*t;return this.uint16[i+0]=e,this.uint16[i+1]=r,this.uint16[i+2]=n,t},e}(ui);Ii.prototype.bytesPerElement=6,zn("StructArrayLayout3ui6",Ii);var Bi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e){var r=this.length;return this.resize(r+1),this.emplace(r,t,e)},e.prototype.emplace=function(t,e,r){var n=2*t;return this.uint16[n+0]=e,this.uint16[n+1]=r,t},e}(ui);Bi.prototype.bytesPerElement=4,zn("StructArrayLayout2ui4",Bi);var Ci=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.uint16=new Uint16Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t){var e=this.length;return this.resize(e+1),this.emplace(e,t)},e.prototype.emplace=function(t,e){var r=1*t;return this.uint16[r+0]=e,t},e}(ui);Ci.prototype.bytesPerElement=2,zn("StructArrayLayout1ui2",Ci);var Ei=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e){var r=this.length;return this.resize(r+1),this.emplace(r,t,e)},e.prototype.emplace=function(t,e,r){var n=2*t;return this.float32[n+0]=e,this.float32[n+1]=r,t},e}(ui);Ei.prototype.bytesPerElement=8,zn("StructArrayLayout2f8",Ei);var Mi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._refreshViews=function(){this.uint8=new Uint8Array(this.arrayBuffer),this.float32=new Float32Array(this.arrayBuffer);},e.prototype.emplaceBack=function(t,e,r,n){var i=this.length;return this.resize(i+1),this.emplace(i,t,e,r,n)},e.prototype.emplace=function(t,e,r,n,i){var a=4*t;return this.float32[a+0]=e,this.float32[a+1]=r,this.float32[a+2]=n,this.float32[a+3]=i,t},e}(ui);Mi.prototype.bytesPerElement=16,zn("StructArrayLayout4f16",Mi);var Ti=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={anchorPointX:{configurable:!0},anchorPointY:{configurable:!0},x1:{configurable:!0},y1:{configurable:!0},x2:{configurable:!0},y2:{configurable:!0},featureIndex:{configurable:!0},sourceLayerIndex:{configurable:!0},bucketIndex:{configurable:!0},radius:{configurable:!0},signedDistanceFromAnchor:{configurable:!0},anchorPoint:{configurable:!0}};return r.anchorPointX.get=function(){return this._structArray.int16[this._pos2+0]},r.anchorPointX.set=function(t){this._structArray.int16[this._pos2+0]=t;},r.anchorPointY.get=function(){return this._structArray.int16[this._pos2+1]},r.anchorPointY.set=function(t){this._structArray.int16[this._pos2+1]=t;},r.x1.get=function(){return this._structArray.int16[this._pos2+2]},r.x1.set=function(t){this._structArray.int16[this._pos2+2]=t;},r.y1.get=function(){return this._structArray.int16[this._pos2+3]},r.y1.set=function(t){this._structArray.int16[this._pos2+3]=t;},r.x2.get=function(){return this._structArray.int16[this._pos2+4]},r.x2.set=function(t){this._structArray.int16[this._pos2+4]=t;},r.y2.get=function(){return this._structArray.int16[this._pos2+5]},r.y2.set=function(t){this._structArray.int16[this._pos2+5]=t;},r.featureIndex.get=function(){return this._structArray.uint32[this._pos4+3]},r.featureIndex.set=function(t){this._structArray.uint32[this._pos4+3]=t;},r.sourceLayerIndex.get=function(){return this._structArray.uint16[this._pos2+8]},r.sourceLayerIndex.set=function(t){this._structArray.uint16[this._pos2+8]=t;},r.bucketIndex.get=function(){return this._structArray.uint16[this._pos2+9]},r.bucketIndex.set=function(t){this._structArray.uint16[this._pos2+9]=t;},r.radius.get=function(){return this._structArray.int16[this._pos2+10]},r.radius.set=function(t){this._structArray.int16[this._pos2+10]=t;},r.signedDistanceFromAnchor.get=function(){return this._structArray.int16[this._pos2+11]},r.signedDistanceFromAnchor.set=function(t){this._structArray.int16[this._pos2+11]=t;},r.anchorPoint.get=function(){return new i(this.anchorPointX,this.anchorPointY)},Object.defineProperties(e.prototype,r),e}(si);Ti.prototype.size=24;var Pi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new Ti(this,t)},e}(xi);zn("CollisionBoxArray",Pi);var Vi=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={anchorX:{configurable:!0},anchorY:{configurable:!0},glyphStartIndex:{configurable:!0},numGlyphs:{configurable:!0},vertexStartIndex:{configurable:!0},lineStartIndex:{configurable:!0},lineLength:{configurable:!0},segment:{configurable:!0},lowerSize:{configurable:!0},upperSize:{configurable:!0},lineOffsetX:{configurable:!0},lineOffsetY:{configurable:!0},writingMode:{configurable:!0},hidden:{configurable:!0},crossTileID:{configurable:!0}};return r.anchorX.get=function(){return this._structArray.int16[this._pos2+0]},r.anchorX.set=function(t){this._structArray.int16[this._pos2+0]=t;},r.anchorY.get=function(){return this._structArray.int16[this._pos2+1]},r.anchorY.set=function(t){this._structArray.int16[this._pos2+1]=t;},r.glyphStartIndex.get=function(){return this._structArray.uint16[this._pos2+2]},r.glyphStartIndex.set=function(t){this._structArray.uint16[this._pos2+2]=t;},r.numGlyphs.get=function(){return this._structArray.uint16[this._pos2+3]},r.numGlyphs.set=function(t){this._structArray.uint16[this._pos2+3]=t;},r.vertexStartIndex.get=function(){return this._structArray.uint32[this._pos4+2]},r.vertexStartIndex.set=function(t){this._structArray.uint32[this._pos4+2]=t;},r.lineStartIndex.get=function(){return this._structArray.uint32[this._pos4+3]},r.lineStartIndex.set=function(t){this._structArray.uint32[this._pos4+3]=t;},r.lineLength.get=function(){return this._structArray.uint32[this._pos4+4]},r.lineLength.set=function(t){this._structArray.uint32[this._pos4+4]=t;},r.segment.get=function(){return this._structArray.uint16[this._pos2+10]},r.segment.set=function(t){this._structArray.uint16[this._pos2+10]=t;},r.lowerSize.get=function(){return this._structArray.uint16[this._pos2+11]},r.lowerSize.set=function(t){this._structArray.uint16[this._pos2+11]=t;},r.upperSize.get=function(){return this._structArray.uint16[this._pos2+12]},r.upperSize.set=function(t){this._structArray.uint16[this._pos2+12]=t;},r.lineOffsetX.get=function(){return this._structArray.float32[this._pos4+7]},r.lineOffsetX.set=function(t){this._structArray.float32[this._pos4+7]=t;},r.lineOffsetY.get=function(){return this._structArray.float32[this._pos4+8]},r.lineOffsetY.set=function(t){this._structArray.float32[this._pos4+8]=t;},r.writingMode.get=function(){return this._structArray.uint8[this._pos1+36]},r.writingMode.set=function(t){this._structArray.uint8[this._pos1+36]=t;},r.hidden.get=function(){return this._structArray.uint8[this._pos1+37]},r.hidden.set=function(t){this._structArray.uint8[this._pos1+37]=t;},r.crossTileID.get=function(){return this._structArray.uint32[this._pos4+10]},r.crossTileID.set=function(t){this._structArray.uint32[this._pos4+10]=t;},Object.defineProperties(e.prototype,r),e}(si);Vi.prototype.size=44;var Fi=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new Vi(this,t)},e}(wi);zn("PlacedSymbolArray",Fi);var Li=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={anchorX:{configurable:!0},anchorY:{configurable:!0},rightJustifiedTextSymbolIndex:{configurable:!0},centerJustifiedTextSymbolIndex:{configurable:!0},leftJustifiedTextSymbolIndex:{configurable:!0},verticalPlacedTextSymbolIndex:{configurable:!0},key:{configurable:!0},textBoxStartIndex:{configurable:!0},textBoxEndIndex:{configurable:!0},iconBoxStartIndex:{configurable:!0},iconBoxEndIndex:{configurable:!0},featureIndex:{configurable:!0},numHorizontalGlyphVertices:{configurable:!0},numVerticalGlyphVertices:{configurable:!0},numIconVertices:{configurable:!0},crossTileID:{configurable:!0},textBoxScale:{configurable:!0},radialTextOffset:{configurable:!0}};return r.anchorX.get=function(){return this._structArray.int16[this._pos2+0]},r.anchorX.set=function(t){this._structArray.int16[this._pos2+0]=t;},r.anchorY.get=function(){return this._structArray.int16[this._pos2+1]},r.anchorY.set=function(t){this._structArray.int16[this._pos2+1]=t;},r.rightJustifiedTextSymbolIndex.get=function(){return this._structArray.int16[this._pos2+2]},r.rightJustifiedTextSymbolIndex.set=function(t){this._structArray.int16[this._pos2+2]=t;},r.centerJustifiedTextSymbolIndex.get=function(){return this._structArray.int16[this._pos2+3]},r.centerJustifiedTextSymbolIndex.set=function(t){this._structArray.int16[this._pos2+3]=t;},r.leftJustifiedTextSymbolIndex.get=function(){return this._structArray.int16[this._pos2+4]},r.leftJustifiedTextSymbolIndex.set=function(t){this._structArray.int16[this._pos2+4]=t;},r.verticalPlacedTextSymbolIndex.get=function(){return this._structArray.int16[this._pos2+5]},r.verticalPlacedTextSymbolIndex.set=function(t){this._structArray.int16[this._pos2+5]=t;},r.key.get=function(){return this._structArray.uint16[this._pos2+6]},r.key.set=function(t){this._structArray.uint16[this._pos2+6]=t;},r.textBoxStartIndex.get=function(){return this._structArray.uint16[this._pos2+7]},r.textBoxStartIndex.set=function(t){this._structArray.uint16[this._pos2+7]=t;},r.textBoxEndIndex.get=function(){return this._structArray.uint16[this._pos2+8]},r.textBoxEndIndex.set=function(t){this._structArray.uint16[this._pos2+8]=t;},r.iconBoxStartIndex.get=function(){return this._structArray.uint16[this._pos2+9]},r.iconBoxStartIndex.set=function(t){this._structArray.uint16[this._pos2+9]=t;},r.iconBoxEndIndex.get=function(){return this._structArray.uint16[this._pos2+10]},r.iconBoxEndIndex.set=function(t){this._structArray.uint16[this._pos2+10]=t;},r.featureIndex.get=function(){return this._structArray.uint16[this._pos2+11]},r.featureIndex.set=function(t){this._structArray.uint16[this._pos2+11]=t;},r.numHorizontalGlyphVertices.get=function(){return this._structArray.uint16[this._pos2+12]},r.numHorizontalGlyphVertices.set=function(t){this._structArray.uint16[this._pos2+12]=t;},r.numVerticalGlyphVertices.get=function(){return this._structArray.uint16[this._pos2+13]},r.numVerticalGlyphVertices.set=function(t){this._structArray.uint16[this._pos2+13]=t;},r.numIconVertices.get=function(){return this._structArray.uint16[this._pos2+14]},r.numIconVertices.set=function(t){this._structArray.uint16[this._pos2+14]=t;},r.crossTileID.get=function(){return this._structArray.uint32[this._pos4+8]},r.crossTileID.set=function(t){this._structArray.uint32[this._pos4+8]=t;},r.textBoxScale.get=function(){return this._structArray.float32[this._pos4+9]},r.textBoxScale.set=function(t){this._structArray.float32[this._pos4+9]=t;},r.radialTextOffset.get=function(){return this._structArray.float32[this._pos4+10]},r.radialTextOffset.set=function(t){this._structArray.float32[this._pos4+10]=t;},Object.defineProperties(e.prototype,r),e}(si);Li.prototype.size=44;var Di=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new Li(this,t)},e}(Ai);zn("SymbolInstanceArray",Di);var Oi=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={offsetX:{configurable:!0}};return r.offsetX.get=function(){return this._structArray.float32[this._pos4+0]},r.offsetX.set=function(t){this._structArray.float32[this._pos4+0]=t;},Object.defineProperties(e.prototype,r),e}(si);Oi.prototype.size=4;var Ri=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.getoffsetX=function(t){return this.float32[1*t+0]},e.prototype.get=function(t){return new Oi(this,t)},e}(Si);zn("GlyphOffsetArray",Ri);var Ui=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={x:{configurable:!0},y:{configurable:!0},tileUnitDistanceFromAnchor:{configurable:!0}};return r.x.get=function(){return this._structArray.int16[this._pos2+0]},r.x.set=function(t){this._structArray.int16[this._pos2+0]=t;},r.y.get=function(){return this._structArray.int16[this._pos2+1]},r.y.set=function(t){this._structArray.int16[this._pos2+1]=t;},r.tileUnitDistanceFromAnchor.get=function(){return this._structArray.int16[this._pos2+2]},r.tileUnitDistanceFromAnchor.set=function(t){this._structArray.int16[this._pos2+2]=t;},Object.defineProperties(e.prototype,r),e}(si);Ui.prototype.size=6;var ji=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.getx=function(t){return this.int16[3*t+0]},e.prototype.gety=function(t){return this.int16[3*t+1]},e.prototype.gettileUnitDistanceFromAnchor=function(t){return this.int16[3*t+2]},e.prototype.get=function(t){return new Ui(this,t)},e}(ki);zn("SymbolLineVertexArray",ji);var qi=function(t){function e(){t.apply(this,arguments);}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var r={featureIndex:{configurable:!0},sourceLayerIndex:{configurable:!0},bucketIndex:{configurable:!0}};return r.featureIndex.get=function(){return this._structArray.uint32[this._pos4+0]},r.featureIndex.set=function(t){this._structArray.uint32[this._pos4+0]=t;},r.sourceLayerIndex.get=function(){return this._structArray.uint16[this._pos2+2]},r.sourceLayerIndex.set=function(t){this._structArray.uint16[this._pos2+2]=t;},r.bucketIndex.get=function(){return this._structArray.uint16[this._pos2+3]},r.bucketIndex.set=function(t){this._structArray.uint16[this._pos2+3]=t;},Object.defineProperties(e.prototype,r),e}(si);qi.prototype.size=8;var Ni=function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t){return new qi(this,t)},e}(zi);zn("FeatureIndexArray",Ni);var Zi=li([{name:"a_pos",components:2,type:"Int16"}],4).members,Ki=function(t){void 0===t&&(t=[]),this.segments=t;};function Gi(t,e){return 256*(t=l(Math.floor(t),0,255))+(e=l(Math.floor(e),0,255))}Ki.prototype.prepareSegment=function(t,e,r,n){var i=this.segments[this.segments.length-1];return t>Ki.MAX_VERTEX_ARRAY_LENGTH&&w("Max vertices per segment is "+Ki.MAX_VERTEX_ARRAY_LENGTH+": bucket requested "+t),(!i||i.vertexLength+t>Ki.MAX_VERTEX_ARRAY_LENGTH||i.sortKey!==n)&&(i={vertexOffset:e.length,primitiveOffset:r.length,vertexLength:0,primitiveLength:0},void 0!==n&&(i.sortKey=n),this.segments.push(i)),i},Ki.prototype.get=function(){return this.segments},Ki.prototype.destroy=function(){for(var t=0,e=this.segments;t>1;this.ids[n]>=t?r=n:e=n+1;}for(var i=[];this.ids[e]===t;){var a=this.positions[3*e],o=this.positions[3*e+1],s=this.positions[3*e+2];i.push({index:a,start:o,end:s}),e++;}return i},Xi.serialize=function(t,e){var r=new Float64Array(t.ids),n=new Uint32Array(t.positions);return function t(e,r,n,i){if(n>=i)return;var a=e[n+i>>1];var o=n-1;var s=i+1;for(;;){do{o++;}while(e[o]a);if(o>=s)break;Ji(e,o,s),Ji(r,3*o,3*s),Ji(r,3*o+1,3*s+1),Ji(r,3*o+2,3*s+2);}t(e,r,n,s);t(e,r,s+1,i);}(r,n,0,r.length-1),e.push(r.buffer,n.buffer),{ids:r,positions:n}},Xi.deserialize=function(t){var e=new Xi;return e.ids=t.ids,e.positions=t.positions,e.indexed=!0,e},zn("FeaturePositionMap",Xi);var Hi=function(t,e){this.gl=t.gl,this.location=e;},Yi=function(t){function e(e,r){t.call(this,e,r),this.current=0;}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.set=function(t){this.current!==t&&(this.current=t,this.gl.uniform1i(this.location,t));},e}(Hi),$i=function(t){function e(e,r){t.call(this,e,r),this.current=0;}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.set=function(t){this.current!==t&&(this.current=t,this.gl.uniform1f(this.location,t));},e}(Hi),Wi=function(t){function e(e,r){t.call(this,e,r),this.current=[0,0];}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.set=function(t){t[0]===this.current[0]&&t[1]===this.current[1]||(this.current=t,this.gl.uniform2f(this.location,t[0],t[1]));},e}(Hi),Qi=function(t){function e(e,r){t.call(this,e,r),this.current=[0,0,0];}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.set=function(t){t[0]===this.current[0]&&t[1]===this.current[1]&&t[2]===this.current[2]||(this.current=t,this.gl.uniform3f(this.location,t[0],t[1],t[2]));},e}(Hi),ta=function(t){function e(e,r){t.call(this,e,r),this.current=[0,0,0,0];}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.set=function(t){t[0]===this.current[0]&&t[1]===this.current[1]&&t[2]===this.current[2]&&t[3]===this.current[3]||(this.current=t,this.gl.uniform4f(this.location,t[0],t[1],t[2],t[3]));},e}(Hi),ea=function(t){function e(e,r){t.call(this,e,r),this.current=ae.transparent;}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.set=function(t){t.r===this.current.r&&t.g===this.current.g&&t.b===this.current.b&&t.a===this.current.a||(this.current=t,this.gl.uniform4f(this.location,t.r,t.g,t.b,t.a));},e}(Hi),ra=new Float32Array(16),na=function(t){function e(e,r){t.call(this,e,r),this.current=ra;}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.set=function(t){if(t[12]!==this.current[12]||t[0]!==this.current[0])return this.current=t,void this.gl.uniformMatrix4fv(this.location,!1,t);for(var e=1;e<16;e++)if(t[e]!==this.current[e]){this.current=t,this.gl.uniformMatrix4fv(this.location,!1,t);break}},e}(Hi);function ia(t){return [Gi(255*t.r,255*t.g),Gi(255*t.b,255*t.a)]}var aa=function(t,e,r){this.value=t,this.names=e,this.uniformNames=this.names.map(function(t){return "u_"+t}),this.type=r,this.maxValue=-1/0;};aa.prototype.defines=function(){return this.names.map(function(t){return "#define HAS_UNIFORM_u_"+t})},aa.prototype.setConstantPatternPositions=function(){},aa.prototype.populatePaintArray=function(){},aa.prototype.updatePaintArray=function(){},aa.prototype.upload=function(){},aa.prototype.destroy=function(){},aa.prototype.setUniforms=function(t,e,r,n){e.set(n.constantOr(this.value));},aa.prototype.getBinding=function(t,e){return "color"===this.type?new ea(t,e):new $i(t,e)},aa.serialize=function(t){var e=t.value,r=t.names,n=t.type;return {value:Bn(e),names:r,type:n}},aa.deserialize=function(t){var e=t.value,r=t.names,n=t.type;return new aa(Cn(e),r,n)};var oa=function(t,e,r){this.value=t,this.names=e,this.uniformNames=this.names.map(function(t){return "u_"+t}),this.type=r,this.maxValue=-1/0,this.patternPositions={patternTo:null,patternFrom:null};};oa.prototype.defines=function(){return this.names.map(function(t){return "#define HAS_UNIFORM_u_"+t})},oa.prototype.populatePaintArray=function(){},oa.prototype.updatePaintArray=function(){},oa.prototype.upload=function(){},oa.prototype.destroy=function(){},oa.prototype.setConstantPatternPositions=function(t,e){this.patternPositions.patternTo=t.tlbr,this.patternPositions.patternFrom=e.tlbr;},oa.prototype.setUniforms=function(t,e,r,n,i){var a=this.patternPositions;"u_pattern_to"===i&&a.patternTo&&e.set(a.patternTo),"u_pattern_from"===i&&a.patternFrom&&e.set(a.patternFrom);},oa.prototype.getBinding=function(t,e){return new ta(t,e)};var sa=function(t,e,r,n){this.expression=t,this.names=e,this.type=r,this.uniformNames=this.names.map(function(t){return "a_"+t}),this.maxValue=-1/0,this.paintVertexAttributes=e.map(function(t){return {name:"a_"+t,type:"Float32",components:"color"===r?2:1,offset:0}}),this.paintVertexArray=new n;};sa.prototype.defines=function(){return []},sa.prototype.setConstantPatternPositions=function(){},sa.prototype.populatePaintArray=function(t,e){var r=this.paintVertexArray,n=r.length;r.reserve(t);var i=this.expression.evaluate(new Zn(0),e,{});if("color"===this.type)for(var a=ia(i),o=n;oma.max||o.yma.max)&&w("Geometry exceeds allowed extent, reduce your vector tile buffer size");}return r}function ga(t,e,r,n,i){t.emplaceBack(2*e+(n+1)/2,2*r+(i+1)/2);}var xa=function(t){this.zoom=t.zoom,this.overscaling=t.overscaling,this.layers=t.layers,this.layerIds=this.layers.map(function(t){return t.id}),this.index=t.index,this.hasPattern=!1,this.layoutVertexArray=new ci,this.indexArray=new Ii,this.segments=new Ki,this.programConfigurations=new ca(Zi,t.layers,t.zoom),this.stateDependentLayerIds=this.layers.filter(function(t){return t.isStateDependent()}).map(function(t){return t.id});};function ba(t,e){for(var r=0;r1){if(Sa(t,e))return !0;for(var n=0;n1?t.distSqr(r):t.distSqr(r.sub(e)._mult(i)._add(e))}function Ba(t,e){for(var r,n,i,a=!1,o=0;oe.y!=i.y>e.y&&e.x<(i.x-n.x)*(e.y-n.y)/(i.y-n.y)+n.x&&(a=!a);return a}function Ca(t,e){for(var r=!1,n=0,i=t.length-1;ne.y!=o.y>e.y&&e.x<(o.x-a.x)*(e.y-a.y)/(o.y-a.y)+a.x&&(r=!r);}return r}function Ea(t,e,r){var n=r[0],i=r[2];if(t.xi.x&&e.x>i.x||t.yi.y&&e.y>i.y)return !1;var a=A(t,e,r[0]);return a!==A(t,e,r[1])||a!==A(t,e,r[2])||a!==A(t,e,r[3])}function Ma(t,e,r){var n=e.paint.get(t).value;return "constant"===n.kind?n.value:r.programConfigurations.get(e.id).binders[t].maxValue}function Ta(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1])}function Pa(t,e,r,n,a){if(!e[0]&&!e[1])return t;var o=i.convert(e)._mult(a);"viewport"===r&&o._rotate(-n);for(var s=[],u=0;u=ya||l<0||l>=ya)){var p=this.segments.prepareSegment(4,this.layoutVertexArray,this.indexArray),c=p.vertexLength;ga(this.layoutVertexArray,u,l,-1,-1),ga(this.layoutVertexArray,u,l,1,-1),ga(this.layoutVertexArray,u,l,1,1),ga(this.layoutVertexArray,u,l,-1,1),this.indexArray.emplaceBack(c,c+1,c+2),this.indexArray.emplaceBack(c,c+3,c+2),p.vertexLength+=4,p.primitiveLength+=2;}}this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length,t,r,{});},zn("CircleBucket",xa,{omit:["layers"]});var Va={paint:new ii({"circle-radius":new ti(Lt.paint_circle["circle-radius"]),"circle-color":new ti(Lt.paint_circle["circle-color"]),"circle-blur":new ti(Lt.paint_circle["circle-blur"]),"circle-opacity":new ti(Lt.paint_circle["circle-opacity"]),"circle-translate":new Qn(Lt.paint_circle["circle-translate"]),"circle-translate-anchor":new Qn(Lt.paint_circle["circle-translate-anchor"]),"circle-pitch-scale":new Qn(Lt.paint_circle["circle-pitch-scale"]),"circle-pitch-alignment":new Qn(Lt.paint_circle["circle-pitch-alignment"]),"circle-stroke-width":new ti(Lt.paint_circle["circle-stroke-width"]),"circle-stroke-color":new ti(Lt.paint_circle["circle-stroke-color"]),"circle-stroke-opacity":new ti(Lt.paint_circle["circle-stroke-opacity"])})},Fa=1e-6,La="undefined"!=typeof Float32Array?Float32Array:Array;Math.PI;function Da(){var t=new La(9);return La!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[5]=0,t[6]=0,t[7]=0),t[0]=1,t[4]=1,t[8]=1,t}function Oa(){var t=new La(3);return La!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t}function Ra(t,e,r){var n=new La(3);return n[0]=t,n[1]=e,n[2]=r,n}function Ua(t,e,r){var n=e[0],i=e[1],a=e[2],o=r[0],s=r[1],u=r[2];return t[0]=i*u-a*s,t[1]=a*o-n*u,t[2]=n*s-i*o,t}var ja,qa=function(t){var e=t[0],r=t[1],n=t[2];return Math.sqrt(e*e+r*r+n*n)};ja=Oa();function Na(t,e,r){var n=e[0],i=e[1],a=e[2],o=e[3];return t[0]=r[0]*n+r[4]*i+r[8]*a+r[12]*o,t[1]=r[1]*n+r[5]*i+r[9]*a+r[13]*o,t[2]=r[2]*n+r[6]*i+r[10]*a+r[14]*o,t[3]=r[3]*n+r[7]*i+r[11]*a+r[15]*o,t}!function(){var t,e=(t=new La(4),La!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[3]=0),t);}();function Za(){var t=new La(4);return La!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t[3]=1,t}function Ka(t,e,r,n){var i,a,o,s,u,l=e[0],p=e[1],c=e[2],h=e[3],f=r[0],y=r[1],d=r[2],m=r[3];return (a=l*f+p*y+c*d+h*m)<0&&(a=-a,f=-f,y=-y,d=-d,m=-m),1-a>Fa?(i=Math.acos(a),o=Math.sin(i),s=Math.sin((1-n)*i)/o,u=Math.sin(n*i)/o):(s=1-n,u=n),t[0]=s*l+u*f,t[1]=s*p+u*y,t[2]=s*c+u*d,t[3]=s*h+u*m,t}var Ga,Xa,Ja,Ha,Ya,$a,Wa=function(t,e){var r=e[0],n=e[1],i=e[2],a=e[3],o=r*r+n*n+i*i+a*a;return o>0&&(o=1/Math.sqrt(o)),t[0]=r*o,t[1]=n*o,t[2]=i*o,t[3]=a*o,t};Ga=Oa(),Xa=Ra(1,0,0),Ja=Ra(0,1,0),Ha=Za(),Ya=Za(),$a=Da();!function(){var t,e=(t=new La(2),La!=Float32Array&&(t[0]=0,t[1]=0),t);}();var Qa=function(t){function e(e){t.call(this,e,Va);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.createBucket=function(t){return new xa(t)},e.prototype.queryRadius=function(t){var e=t;return Ma("circle-radius",this,e)+Ma("circle-stroke-width",this,e)+Ta(this.paint.get("circle-translate"))},e.prototype.queryIntersectsFeature=function(t,e,r,n,i,a,o,s){for(var u=Pa(t,this.paint.get("circle-translate"),this.paint.get("circle-translate-anchor"),a.angle,o),l=this.paint.get("circle-radius").evaluate(e,r)+this.paint.get("circle-stroke-width").evaluate(e,r),p="map"===this.paint.get("circle-pitch-alignment"),c=p?u:function(t,e){return t.map(function(t){return to(t,e)})}(u,s),h=p?l*o:l,f=0,y=n;ft.width||i.height>t.height||r.x>t.width-i.width||r.y>t.height-i.height)throw new RangeError("out of range source coordinates for image copy");if(i.width>e.width||i.height>e.height||n.x>e.width-i.width||n.y>e.height-i.height)throw new RangeError("out of range destination coordinates for image copy");for(var o=t.data,s=e.data,u=0;u80*r){n=a=t[0],i=o=t[1];for(var y=r;ya&&(a=s),u>o&&(o=u);l=0!==(l=Math.max(a-n,o-i))?1/l:0;}return xo(h,f,r,n,i,l),f}function vo(t,e,r,n,i){var a,o;if(i===Oo(t,e,r,n)>0)for(a=e;a=e;a-=n)o=Fo(a,t[a],t[a+1],o);return o&&Mo(o,o.next)&&(Lo(o),o=o.next),o}function go(t,e){if(!t)return t;e||(e=t);var r,n=t;do{if(r=!1,n.steiner||!Mo(n,n.next)&&0!==Eo(n.prev,n,n.next))n=n.next;else{if(Lo(n),(n=e=n.prev)===n.next)break;r=!0;}}while(r||n!==e);return e}function xo(t,e,r,n,i,a,o){if(t){!o&&a&&function(t,e,r,n){var i=t;do{null===i.z&&(i.z=zo(i.x,i.y,e,r,n)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next;}while(i!==t);i.prevZ.nextZ=null,i.prevZ=null,function(t){var e,r,n,i,a,o,s,u,l=1;do{for(r=t,t=null,a=null,o=0;r;){for(o++,n=r,s=0,e=0;e0||u>0&&n;)0!==s&&(0===u||!n||r.z<=n.z)?(i=r,r=r.nextZ,s--):(i=n,n=n.nextZ,u--),a?a.nextZ=i:t=i,i.prevZ=a,a=i;r=n;}a.nextZ=null,l*=2;}while(o>1)}(i);}(t,n,i,a);for(var s,u,l=t;t.prev!==t.next;)if(s=t.prev,u=t.next,a?_o(t,n,i,a):bo(t))e.push(s.i/r),e.push(t.i/r),e.push(u.i/r),Lo(t),t=u.next,l=u.next;else if((t=u)===l){o?1===o?xo(t=wo(t,e,r),e,r,n,i,a,2):2===o&&Ao(t,e,r,n,i,a):xo(go(t),e,r,n,i,a,1);break}}}function bo(t){var e=t.prev,r=t,n=t.next;if(Eo(e,r,n)>=0)return !1;for(var i=t.next.next;i!==t.prev;){if(Bo(e.x,e.y,r.x,r.y,n.x,n.y,i.x,i.y)&&Eo(i.prev,i,i.next)>=0)return !1;i=i.next;}return !0}function _o(t,e,r,n){var i=t.prev,a=t,o=t.next;if(Eo(i,a,o)>=0)return !1;for(var s=i.xa.x?i.x>o.x?i.x:o.x:a.x>o.x?a.x:o.x,p=i.y>a.y?i.y>o.y?i.y:o.y:a.y>o.y?a.y:o.y,c=zo(s,u,e,r,n),h=zo(l,p,e,r,n),f=t.prevZ,y=t.nextZ;f&&f.z>=c&&y&&y.z<=h;){if(f!==t.prev&&f!==t.next&&Bo(i.x,i.y,a.x,a.y,o.x,o.y,f.x,f.y)&&Eo(f.prev,f,f.next)>=0)return !1;if(f=f.prevZ,y!==t.prev&&y!==t.next&&Bo(i.x,i.y,a.x,a.y,o.x,o.y,y.x,y.y)&&Eo(y.prev,y,y.next)>=0)return !1;y=y.nextZ;}for(;f&&f.z>=c;){if(f!==t.prev&&f!==t.next&&Bo(i.x,i.y,a.x,a.y,o.x,o.y,f.x,f.y)&&Eo(f.prev,f,f.next)>=0)return !1;f=f.prevZ;}for(;y&&y.z<=h;){if(y!==t.prev&&y!==t.next&&Bo(i.x,i.y,a.x,a.y,o.x,o.y,y.x,y.y)&&Eo(y.prev,y,y.next)>=0)return !1;y=y.nextZ;}return !0}function wo(t,e,r){var n=t;do{var i=n.prev,a=n.next.next;!Mo(i,a)&&To(i,n,n.next,a)&&Po(i,a)&&Po(a,i)&&(e.push(i.i/r),e.push(n.i/r),e.push(a.i/r),Lo(n),Lo(n.next),n=t=a),n=n.next;}while(n!==t);return n}function Ao(t,e,r,n,i,a){var o=t;do{for(var s=o.next.next;s!==o.prev;){if(o.i!==s.i&&Co(o,s)){var u=Vo(o,s);return o=go(o,o.next),u=go(u,u.next),xo(o,e,r,n,i,a),void xo(u,e,r,n,i,a)}s=s.next;}o=o.next;}while(o!==t)}function So(t,e){return t.x-e.x}function ko(t,e){if(e=function(t,e){var r,n=e,i=t.x,a=t.y,o=-1/0;do{if(a<=n.y&&a>=n.next.y&&n.next.y!==n.y){var s=n.x+(a-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(s<=i&&s>o){if(o=s,s===i){if(a===n.y)return n;if(a===n.next.y)return n.next}r=n.x=n.x&&n.x>=p&&i!==n.x&&Bo(ar.x)&&Po(n,t)&&(r=n,h=u),n=n.next;return r}(t,e)){var r=Vo(e,t);go(r,r.next);}}function zo(t,e,r,n,i){return (t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*i)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-n)*i)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function Io(t){var e=t,r=t;do{(e.x=0&&(t-o)*(n-s)-(r-o)*(e-s)>=0&&(r-o)*(a-s)-(i-o)*(n-s)>=0}function Co(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){var r=t;do{if(r.i!==t.i&&r.next.i!==t.i&&r.i!==e.i&&r.next.i!==e.i&&To(r,r.next,t,e))return !0;r=r.next;}while(r!==t);return !1}(t,e)&&Po(t,e)&&Po(e,t)&&function(t,e){var r=t,n=!1,i=(t.x+e.x)/2,a=(t.y+e.y)/2;do{r.y>a!=r.next.y>a&&r.next.y!==r.y&&i<(r.next.x-r.x)*(a-r.y)/(r.next.y-r.y)+r.x&&(n=!n),r=r.next;}while(r!==t);return n}(t,e)}function Eo(t,e,r){return (e.y-t.y)*(r.x-e.x)-(e.x-t.x)*(r.y-e.y)}function Mo(t,e){return t.x===e.x&&t.y===e.y}function To(t,e,r,n){return !!(Mo(t,e)&&Mo(r,n)||Mo(t,n)&&Mo(r,e))||Eo(t,e,r)>0!=Eo(t,e,n)>0&&Eo(r,n,t)>0!=Eo(r,n,e)>0}function Po(t,e){return Eo(t.prev,t,t.next)<0?Eo(t,e,t.next)>=0&&Eo(t,t.prev,e)>=0:Eo(t,e,t.prev)<0||Eo(t,t.next,e)<0}function Vo(t,e){var r=new Do(t.i,t.x,t.y),n=new Do(e.i,e.x,e.y),i=t.next,a=e.prev;return t.next=e,e.prev=t,r.next=i,i.prev=r,n.next=r,r.prev=n,a.next=n,n.prev=a,n}function Fo(t,e,r,n){var i=new Do(t,e,r);return n?(i.next=n.next,i.prev=n,n.next.prev=i,n.next=i):(i.prev=i,i.next=i),i}function Lo(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ);}function Do(t,e,r){this.i=t,this.x=e,this.y=r,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1;}function Oo(t,e,r,n){for(var i=0,a=e,o=r-n;an;){if(i-n>600){var o=i-n+1,s=r-n+1,u=Math.log(o),l=.5*Math.exp(2*u/3),p=.5*Math.sqrt(u*l*(o-l)/o)*(s-o/2<0?-1:1),c=Math.max(n,Math.floor(r-s*l/o+p)),h=Math.min(i,Math.floor(r+(o-s)*l/o+p));t(e,r,c,h,a);}var f=e[r],y=n,d=i;for(Uo(e,n,r),a(e[i],f)>0&&Uo(e,n,i);y0;)d--;}0===a(e[n],f)?Uo(e,n,d):Uo(e,++d,i),d<=r&&(n=d+1),r<=d&&(i=d-1);}}(t,e,r||0,n||t.length-1,i||jo);}function Uo(t,e,r){var n=t[e];t[e]=t[r],t[r]=n;}function jo(t,e){return te?1:0}function qo(t,e){var r=t.length;if(r<=1)return [t];for(var n,i,a=[],o=0;o1)for(var u=0;u0&&(n+=t[i-1].length,r.holes.push(n));}return r},fo.default=yo;var Go=function(t){this.zoom=t.zoom,this.overscaling=t.overscaling,this.layers=t.layers,this.layerIds=this.layers.map(function(t){return t.id}),this.index=t.index,this.hasPattern=!1,this.layoutVertexArray=new ci,this.indexArray=new Ii,this.indexArray2=new Bi,this.programConfigurations=new ca(ho,t.layers,t.zoom),this.segments=new Ki,this.segments2=new Ki,this.stateDependentLayerIds=this.layers.filter(function(t){return t.isStateDependent()}).map(function(t){return t.id});};Go.prototype.populate=function(t,e){this.features=[],this.hasPattern=Zo("fill",this.layers,e);for(var r=0,n=t;r>3;}if(a--,1===n||2===n)o+=t.readSVarint(),s+=t.readSVarint(),1===n&&(e&&u.push(e),e=[]),e.push(new i(o,s));else{if(7!==n)throw new Error("unknown command "+n);e&&e.push(e[0].clone());}}return e&&u.push(e),u},$o.prototype.bbox=function(){var t=this._pbf;t.pos=this._geometry;for(var e=t.readVarint()+t.pos,r=1,n=0,i=0,a=0,o=1/0,s=-1/0,u=1/0,l=-1/0;t.pos>3;}if(n--,1===r||2===r)(i+=t.readSVarint())s&&(s=i),(a+=t.readSVarint())l&&(l=a);else if(7!==r)throw new Error("unknown command "+r)}return [o,u,s,l]},$o.prototype.toGeoJSON=function(t,e,r){var n,i,a=this.extent*Math.pow(2,r),o=this.extent*t,s=this.extent*e,u=this.loadGeometry(),l=$o.types[this.type];function p(t){for(var e=0;e>3;e=1===n?t.readString():2===n?t.readFloat():3===n?t.readDouble():4===n?t.readVarint64():5===n?t.readVarint():6===n?t.readSVarint():7===n?t.readBoolean():null;}return e}(r));}function ns(t,e,r){if(3===t){var n=new ts(r,r.readVarint()+r.pos);n.length&&(e[n.name]=n);}}es.prototype.feature=function(t){if(t<0||t>=this._features.length)throw new Error("feature index out of bounds");this._pbf.pos=this._features[t];var e=this._pbf.readVarint()+this._pbf.pos;return new Yo(this._pbf,e,this.extent,this._keys,this._values)};var is={VectorTile:function(t,e){this.layers=t.readFields(ns,{},e);},VectorTileFeature:Yo,VectorTileLayer:ts},as=is.VectorTileFeature.types,os=Math.pow(2,13);function ss(t,e,r,n,i,a,o,s){t.emplaceBack(e,r,2*Math.floor(n*os)+o,i*os*2,a*os*2,Math.round(s));}var us=function(t){this.zoom=t.zoom,this.overscaling=t.overscaling,this.layers=t.layers,this.layerIds=this.layers.map(function(t){return t.id}),this.index=t.index,this.hasPattern=!1,this.layoutVertexArray=new fi,this.indexArray=new Ii,this.programConfigurations=new ca(Ho,t.layers,t.zoom),this.segments=new Ki,this.stateDependentLayerIds=this.layers.filter(function(t){return t.isStateDependent()}).map(function(t){return t.id});};function ls(t,e){return t.x===e.x&&(t.x<0||t.x>ya)||t.y===e.y&&(t.y<0||t.y>ya)}function ps(t){return t.every(function(t){return t.x<0})||t.every(function(t){return t.x>ya})||t.every(function(t){return t.y<0})||t.every(function(t){return t.y>ya})}us.prototype.populate=function(t,e){this.features=[],this.hasPattern=Zo("fill-extrusion",this.layers,e);for(var r=0,n=t;r=1){var v=f[d-1];if(!ls(m,v)){p.vertexLength+4>Ki.MAX_VERTEX_ARRAY_LENGTH&&(p=this.segments.prepareSegment(4,this.layoutVertexArray,this.indexArray));var g=m.sub(v)._perp()._unit(),x=v.dist(m);y+x>32768&&(y=0),ss(this.layoutVertexArray,m.x,m.y,g.x,g.y,0,0,y),ss(this.layoutVertexArray,m.x,m.y,g.x,g.y,0,1,y),y+=x,ss(this.layoutVertexArray,v.x,v.y,g.x,g.y,0,0,y),ss(this.layoutVertexArray,v.x,v.y,g.x,g.y,0,1,y);var b=p.vertexLength;this.indexArray.emplaceBack(b,b+2,b+1),this.indexArray.emplaceBack(b+1,b+2,b+3),p.vertexLength+=4,p.primitiveLength+=2;}}}}if(p.vertexLength+s>Ki.MAX_VERTEX_ARRAY_LENGTH&&(p=this.segments.prepareSegment(s,this.layoutVertexArray,this.indexArray)),"Polygon"===as[t.type]){for(var _=[],w=[],A=p.vertexLength,S=0,k=o;S>6);}var ws=function(t){this.zoom=t.zoom,this.overscaling=t.overscaling,this.layers=t.layers,this.layerIds=this.layers.map(function(t){return t.id}),this.index=t.index,this.features=[],this.hasPattern=!1,this.layoutVertexArray=new yi,this.indexArray=new Ii,this.programConfigurations=new ca(ds,t.layers,t.zoom),this.segments=new Ki,this.stateDependentLayerIds=this.layers.filter(function(t){return t.isStateDependent()}).map(function(t){return t.id});};function As(t,e){return (t/e.tileTotal*(e.end-e.start)+e.start)*(bs-1)}ws.prototype.populate=function(t,e){this.features=[],this.hasPattern=Zo("line",this.layers,e);for(var r=0,n=t;r=2&&t[p-1].equals(t[p-2]);)p--;for(var c=0;cc){var E=d.dist(_);if(E>2*h){var M=d.sub(d.sub(_)._mult(h/E)._round());this.distance+=M.dist(_),this.addCurrentVertex(M,this.distance,A.mult(1),0,0,!1,y,u),_=M;}}var T=_&&w,P=T?r:w?g:x;if(T&&"round"===P&&(Bi&&(P="bevel"),"bevel"===P&&(B>2&&(P="flipbevel"),B100)z=S.clone().mult(-1);else{var V=A.x*S.y-A.y*S.x>0?-1:1,F=B*A.add(S).mag()/A.sub(S).mag();z._perp()._mult(F*V);}this.addCurrentVertex(d,this.distance,z,0,0,!1,y,u),this.addCurrentVertex(d,this.distance,z.mult(-1),0,0,!1,y,u);}else if("bevel"===P||"fakeround"===P){var L=A.x*S.y-A.y*S.x>0,D=-Math.sqrt(B*B-1);if(L?(v=0,m=D):(m=0,v=D),b||this.addCurrentVertex(d,this.distance,A,m,v,!1,y,u),"fakeround"===P){for(var O=Math.floor(8*(.5-(I-.5))),R=void 0,U=0;U=0;j--)R=A.mult((j+1)/(O+1))._add(S)._unit(),this.addPieSliceVertex(d,this.distance,R,L,y,u);}w&&this.addCurrentVertex(d,this.distance,S,-m,-v,!1,y,u);}else"butt"===P?(b||this.addCurrentVertex(d,this.distance,A,0,0,!1,y,u),w&&this.addCurrentVertex(d,this.distance,S,0,0,!1,y,u)):"square"===P?(b||(this.addCurrentVertex(d,this.distance,A,1,1,!1,y,u),this.e1=this.e2=-1),w&&this.addCurrentVertex(d,this.distance,S,-1,-1,!1,y,u)):"round"===P&&(b||(this.addCurrentVertex(d,this.distance,A,0,0,!1,y,u),this.addCurrentVertex(d,this.distance,A,1,1,!0,y,u),this.e1=this.e2=-1),w&&(this.addCurrentVertex(d,this.distance,S,-1,-1,!0,y,u),this.addCurrentVertex(d,this.distance,S,0,0,!1,y,u)));if(C&&k2*h){var N=d.add(w.sub(d)._mult(h/q)._round());this.distance+=N.dist(d),this.addCurrentVertex(N,this.distance,S.mult(1),0,0,!1,y,u),d=N;}}b=!1;}this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length,e,o,s);}},ws.prototype.addCurrentVertex=function(t,e,r,n,i,a,o,s){var u,l=this.layoutVertexArray,p=this.indexArray;s&&(e=As(e,s)),u=r.clone(),n&&u._sub(r.perp()._mult(n)),_s(l,t,u,a,!1,n,e),this.e3=o.vertexLength++,this.e1>=0&&this.e2>=0&&(p.emplaceBack(this.e1,this.e2,this.e3),o.primitiveLength++),this.e1=this.e2,this.e2=this.e3,u=r.mult(-1),i&&u._sub(r.perp()._mult(i)),_s(l,t,u,a,!0,-i,e),this.e3=o.vertexLength++,this.e1>=0&&this.e2>=0&&(p.emplaceBack(this.e1,this.e2,this.e3),o.primitiveLength++),this.e1=this.e2,this.e2=this.e3,e>bs/2&&!s&&(this.distance=0,this.addCurrentVertex(t,this.distance,r,n,i,a,o));},ws.prototype.addPieSliceVertex=function(t,e,r,n,i,a){r=r.mult(n?-1:1);var o=this.layoutVertexArray,s=this.indexArray;a&&(e=As(e,a)),_s(o,t,r,!1,n,0,e),this.e3=i.vertexLength++,this.e1>=0&&this.e2>=0&&(s.emplaceBack(this.e1,this.e2,this.e3),i.primitiveLength++),n?this.e2=this.e3:this.e1=this.e3;},zn("LineBucket",ws,{omit:["layers","features"]});var Ss=new ii({"line-cap":new Qn(Lt.layout_line["line-cap"]),"line-join":new ti(Lt.layout_line["line-join"]),"line-miter-limit":new Qn(Lt.layout_line["line-miter-limit"]),"line-round-limit":new Qn(Lt.layout_line["line-round-limit"])}),ks={paint:new ii({"line-opacity":new ti(Lt.paint_line["line-opacity"]),"line-color":new ti(Lt.paint_line["line-color"]),"line-translate":new Qn(Lt.paint_line["line-translate"]),"line-translate-anchor":new Qn(Lt.paint_line["line-translate-anchor"]),"line-width":new ti(Lt.paint_line["line-width"]),"line-gap-width":new ti(Lt.paint_line["line-gap-width"]),"line-offset":new ti(Lt.paint_line["line-offset"]),"line-blur":new ti(Lt.paint_line["line-blur"]),"line-dasharray":new ri(Lt.paint_line["line-dasharray"]),"line-pattern":new ei(Lt.paint_line["line-pattern"]),"line-gradient":new ni(Lt.paint_line["line-gradient"])}),layout:Ss},zs=new(function(t){function e(){t.apply(this,arguments);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.possiblyEvaluate=function(e,r){return r=new Zn(Math.floor(r.zoom),{now:r.now,fadeDuration:r.fadeDuration,zoomHistory:r.zoomHistory,transition:r.transition}),t.prototype.possiblyEvaluate.call(this,e,r)},e.prototype.evaluate=function(e,r,n,i){return r=c({},r,{zoom:Math.floor(r.zoom)}),t.prototype.evaluate.call(this,e,r,n,i)},e}(ti))(ks.paint.properties["line-width"].specification);zs.useIntegerZoom=!0;var Is=function(t){function e(e){t.call(this,e,ks);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype._handleSpecialPaintPropertyUpdate=function(t){"line-gradient"===t&&this._updateGradient();},e.prototype._updateGradient=function(){var t=this._transitionablePaint._values["line-gradient"].value.expression;this.gradient=uo(t,"lineProgress"),this.gradientTexture=null;},e.prototype.recalculate=function(e){t.prototype.recalculate.call(this,e),this.paint._values["line-floorwidth"]=zs.possiblyEvaluate(this._transitioningPaint._values["line-width"].value,e);},e.prototype.createBucket=function(t){return new ws(t)},e.prototype.queryRadius=function(t){var e=t,r=Bs(Ma("line-width",this,e),Ma("line-gap-width",this,e)),n=Ma("line-offset",this,e);return r/2+Math.abs(n)+Ta(this.paint.get("line-translate"))},e.prototype.queryIntersectsFeature=function(t,e,r,n,a,o,s){var u=Pa(t,this.paint.get("line-translate"),this.paint.get("line-translate-anchor"),o.angle,s),l=s/2*Bs(this.paint.get("line-width").evaluate(e,r),this.paint.get("line-gap-width").evaluate(e,r)),p=this.paint.get("line-offset").evaluate(e,r);return p&&(n=function(t,e){for(var r=[],n=new i(0,0),a=0;a=3)for(var a=0;a0?e+2*t:t}var Cs=li([{name:"a_pos_offset",components:4,type:"Int16"},{name:"a_data",components:4,type:"Uint16"}]),Es=li([{name:"a_projected_pos",components:3,type:"Float32"}],4),Ms=(li([{name:"a_fade_opacity",components:1,type:"Uint32"}],4),li([{name:"a_placed",components:2,type:"Uint8"},{name:"a_shift",components:2,type:"Float32"}])),Ts=(li([{type:"Int16",name:"anchorPointX"},{type:"Int16",name:"anchorPointY"},{type:"Int16",name:"x1"},{type:"Int16",name:"y1"},{type:"Int16",name:"x2"},{type:"Int16",name:"y2"},{type:"Uint32",name:"featureIndex"},{type:"Uint16",name:"sourceLayerIndex"},{type:"Uint16",name:"bucketIndex"},{type:"Int16",name:"radius"},{type:"Int16",name:"signedDistanceFromAnchor"}]),li([{name:"a_pos",components:2,type:"Int16"},{name:"a_anchor_pos",components:2,type:"Int16"},{name:"a_extrude",components:2,type:"Int16"}],4)),Ps=li([{name:"a_pos",components:2,type:"Int16"},{name:"a_anchor_pos",components:2,type:"Int16"},{name:"a_extrude",components:2,type:"Int16"}],4);li([{type:"Int16",name:"anchorX"},{type:"Int16",name:"anchorY"},{type:"Uint16",name:"glyphStartIndex"},{type:"Uint16",name:"numGlyphs"},{type:"Uint32",name:"vertexStartIndex"},{type:"Uint32",name:"lineStartIndex"},{type:"Uint32",name:"lineLength"},{type:"Uint16",name:"segment"},{type:"Uint16",name:"lowerSize"},{type:"Uint16",name:"upperSize"},{type:"Float32",name:"lineOffsetX"},{type:"Float32",name:"lineOffsetY"},{type:"Uint8",name:"writingMode"},{type:"Uint8",name:"hidden"},{type:"Uint32",name:"crossTileID"}]),li([{type:"Int16",name:"anchorX"},{type:"Int16",name:"anchorY"},{type:"Int16",name:"rightJustifiedTextSymbolIndex"},{type:"Int16",name:"centerJustifiedTextSymbolIndex"},{type:"Int16",name:"leftJustifiedTextSymbolIndex"},{type:"Int16",name:"verticalPlacedTextSymbolIndex"},{type:"Uint16",name:"key"},{type:"Uint16",name:"textBoxStartIndex"},{type:"Uint16",name:"textBoxEndIndex"},{type:"Uint16",name:"iconBoxStartIndex"},{type:"Uint16",name:"iconBoxEndIndex"},{type:"Uint16",name:"featureIndex"},{type:"Uint16",name:"numHorizontalGlyphVertices"},{type:"Uint16",name:"numVerticalGlyphVertices"},{type:"Uint16",name:"numIconVertices"},{type:"Uint32",name:"crossTileID"},{type:"Float32",name:"textBoxScale"},{type:"Float32",name:"radialTextOffset"}]),li([{type:"Float32",name:"offsetX"}]),li([{type:"Int16",name:"x"},{type:"Int16",name:"y"},{type:"Int16",name:"tileUnitDistanceFromAnchor"}]);function Vs(t,e,r){return t.sections.forEach(function(t){t.text=function(t,e,r){var n=e.layout.get("text-transform").evaluate(r,{});return "uppercase"===n?t=t.toLocaleUpperCase():"lowercase"===n&&(t=t.toLocaleLowerCase()),Nn.applyArabicShaping&&(t=Nn.applyArabicShaping(t)),t}(t.text,e,r);}),t}var Fs={"!":"︕","#":"#",$:"$","%":"%","&":"&","(":"︵",")":"︶","*":"*","+":"+",",":"︐","-":"︲",".":"・","/":"/",":":"︓",";":"︔","<":"︿","=":"=",">":"﹀","?":"︖","@":"@","[":"﹇","\\":"\","]":"﹈","^":"^",_:"︳","`":"`","{":"︷","|":"―","}":"︸","~":"~","¢":"¢","£":"£","¥":"¥","¦":"¦","¬":"¬","¯":" ̄","–":"︲","—":"︱","‘":"﹃","’":"﹄","“":"﹁","”":"﹂","…":"︙","‧":"・","₩":"₩","、":"︑","。":"︒","〈":"︿","〉":"﹀","《":"︽","》":"︾","「":"﹁","」":"﹂","『":"﹃","』":"﹄","【":"︻","】":"︼","〔":"︹","〕":"︺","〖":"︗","〗":"︘","!":"︕","(":"︵",")":"︶",",":"︐","-":"︲",".":"・",":":"︓",";":"︔","<":"︿",">":"﹀","?":"︖","[":"﹇","]":"﹈","_":"︳","{":"︷","|":"―","}":"︸","⦅":"︵","⦆":"︶","。":"︒","「":"﹁","」":"﹂"};var Ls=function(t){function e(e,r,n,i){t.call(this,e,r),this.angle=n,void 0!==i&&(this.segment=i);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.clone=function(){return new e(this.x,this.y,this.angle,this.segment)},e}(i);zn("Anchor",Ls);var Ds=256;function Os(t,e){var r=e.expression;if("constant"===r.kind)return {kind:"constant",layoutSize:r.evaluate(new Zn(t+1))};if("source"===r.kind)return {kind:"source"};for(var n=r.zoomStops,i=r.interpolationType,a=0;a0)&&("constant"!==i.value.kind||i.value.value.length>0),u="constant"!==o.value.kind||o.value.value&&o.value.value.length>0,l=n.get("symbol-sort-key");if(this.features=[],s||u){for(var p=e.iconDependencies,c=e.glyphDependencies,h=new Zn(this.zoom),f=0,y=t;f=0;s--)a[s]={x:e[s].x,y:e[s].y,tileUnitDistanceFromAnchor:i},s>0&&(i+=e[s-1].dist(e[s]));for(var u=0;u0;this.addCollisionDebugVertices(a,o,s,u,l?this.collisionCircle:this.collisionBox,i.anchorPoint,r,l);}},Js.prototype.generateCollisionDebugBuffers=function(){for(var t=0;t0},Js.prototype.hasIconData=function(){return this.icon.segments.get().length>0},Js.prototype.hasCollisionBoxData=function(){return this.collisionBox.segments.get().length>0},Js.prototype.hasCollisionCircleData=function(){return this.collisionCircle.segments.get().length>0},Js.prototype.addIndicesForPlacedTextSymbol=function(t){for(var e=this.text.placedSymbolArray.get(t),r=e.vertexStartIndex+4*e.numGlyphs,n=e.vertexStartIndex;n1||this.icon.segments.get().length>1)){this.symbolInstanceIndexes=this.getSortedSymbolIndexes(t),this.sortedAngle=t,this.text.indexArray.clear(),this.icon.indexArray.clear(),this.featureSortOrder=[];for(var r=0,n=this.symbolInstanceIndexes;r=0&&n.indexOf(t)===r&&e.addIndicesForPlacedTextSymbol(t);}),a.verticalPlacedTextSymbolIndex>=0&&this.addIndicesForPlacedTextSymbol(a.verticalPlacedTextSymbolIndex);var o=this.icon.placedSymbolArray.get(i);if(o.numGlyphs){var s=o.vertexStartIndex;this.icon.indexArray.emplaceBack(s,s+1,s+2),this.icon.indexArray.emplaceBack(s+1,s+2,s+3);}}this.text.indexBuffer&&this.text.indexBuffer.updateData(this.text.indexArray),this.icon.indexBuffer&&this.icon.indexBuffer.updateData(this.icon.indexArray);}},zn("SymbolBucket",Js,{omit:["layers","collisionBoxArray","features","compareText"]}),Js.MAX_GLYPHS=65535,Js.addDynamicAttributes=Ks;var Hs=new ii({"symbol-placement":new Qn(Lt.layout_symbol["symbol-placement"]),"symbol-spacing":new Qn(Lt.layout_symbol["symbol-spacing"]),"symbol-avoid-edges":new Qn(Lt.layout_symbol["symbol-avoid-edges"]),"symbol-sort-key":new ti(Lt.layout_symbol["symbol-sort-key"]),"symbol-z-order":new Qn(Lt.layout_symbol["symbol-z-order"]),"icon-allow-overlap":new Qn(Lt.layout_symbol["icon-allow-overlap"]),"icon-ignore-placement":new Qn(Lt.layout_symbol["icon-ignore-placement"]),"icon-optional":new Qn(Lt.layout_symbol["icon-optional"]),"icon-rotation-alignment":new Qn(Lt.layout_symbol["icon-rotation-alignment"]),"icon-size":new ti(Lt.layout_symbol["icon-size"]),"icon-text-fit":new Qn(Lt.layout_symbol["icon-text-fit"]),"icon-text-fit-padding":new Qn(Lt.layout_symbol["icon-text-fit-padding"]),"icon-image":new ti(Lt.layout_symbol["icon-image"]),"icon-rotate":new ti(Lt.layout_symbol["icon-rotate"]),"icon-padding":new Qn(Lt.layout_symbol["icon-padding"]),"icon-keep-upright":new Qn(Lt.layout_symbol["icon-keep-upright"]),"icon-offset":new ti(Lt.layout_symbol["icon-offset"]),"icon-anchor":new ti(Lt.layout_symbol["icon-anchor"]),"icon-pitch-alignment":new Qn(Lt.layout_symbol["icon-pitch-alignment"]),"text-pitch-alignment":new Qn(Lt.layout_symbol["text-pitch-alignment"]),"text-rotation-alignment":new Qn(Lt.layout_symbol["text-rotation-alignment"]),"text-field":new ti(Lt.layout_symbol["text-field"]),"text-font":new ti(Lt.layout_symbol["text-font"]),"text-size":new ti(Lt.layout_symbol["text-size"]),"text-max-width":new ti(Lt.layout_symbol["text-max-width"]),"text-line-height":new Qn(Lt.layout_symbol["text-line-height"]),"text-letter-spacing":new ti(Lt.layout_symbol["text-letter-spacing"]),"text-justify":new ti(Lt.layout_symbol["text-justify"]),"text-radial-offset":new ti(Lt.layout_symbol["text-radial-offset"]),"text-variable-anchor":new Qn(Lt.layout_symbol["text-variable-anchor"]),"text-anchor":new ti(Lt.layout_symbol["text-anchor"]),"text-max-angle":new Qn(Lt.layout_symbol["text-max-angle"]),"text-rotate":new ti(Lt.layout_symbol["text-rotate"]),"text-padding":new Qn(Lt.layout_symbol["text-padding"]),"text-keep-upright":new Qn(Lt.layout_symbol["text-keep-upright"]),"text-transform":new ti(Lt.layout_symbol["text-transform"]),"text-offset":new ti(Lt.layout_symbol["text-offset"]),"text-allow-overlap":new Qn(Lt.layout_symbol["text-allow-overlap"]),"text-ignore-placement":new Qn(Lt.layout_symbol["text-ignore-placement"]),"text-optional":new Qn(Lt.layout_symbol["text-optional"])}),Ys={paint:new ii({"icon-opacity":new ti(Lt.paint_symbol["icon-opacity"]),"icon-color":new ti(Lt.paint_symbol["icon-color"]),"icon-halo-color":new ti(Lt.paint_symbol["icon-halo-color"]),"icon-halo-width":new ti(Lt.paint_symbol["icon-halo-width"]),"icon-halo-blur":new ti(Lt.paint_symbol["icon-halo-blur"]),"icon-translate":new Qn(Lt.paint_symbol["icon-translate"]),"icon-translate-anchor":new Qn(Lt.paint_symbol["icon-translate-anchor"]),"text-opacity":new ti(Lt.paint_symbol["text-opacity"]),"text-color":new ti(Lt.paint_symbol["text-color"]),"text-halo-color":new ti(Lt.paint_symbol["text-halo-color"]),"text-halo-width":new ti(Lt.paint_symbol["text-halo-width"]),"text-halo-blur":new ti(Lt.paint_symbol["text-halo-blur"]),"text-translate":new Qn(Lt.paint_symbol["text-translate"]),"text-translate-anchor":new Qn(Lt.paint_symbol["text-translate-anchor"])}),layout:Hs},$s=function(t){function e(e){t.call(this,e,Ys);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.recalculate=function(e){t.prototype.recalculate.call(this,e),"auto"===this.layout.get("icon-rotation-alignment")&&("point"!==this.layout.get("symbol-placement")?this.layout._values["icon-rotation-alignment"]="map":this.layout._values["icon-rotation-alignment"]="viewport"),"auto"===this.layout.get("text-rotation-alignment")&&("point"!==this.layout.get("symbol-placement")?this.layout._values["text-rotation-alignment"]="map":this.layout._values["text-rotation-alignment"]="viewport"),"auto"===this.layout.get("text-pitch-alignment")&&(this.layout._values["text-pitch-alignment"]=this.layout.get("text-rotation-alignment")),"auto"===this.layout.get("icon-pitch-alignment")&&(this.layout._values["icon-pitch-alignment"]=this.layout.get("icon-rotation-alignment"));},e.prototype.getValueAndResolveTokens=function(t,e){var r,n=this.layout.get(t).evaluate(e,{}),i=this._unevaluatedLayout._values[t];return i.isDataDriven()||Vr(i.value)?n:(r=e.properties,n.replace(/{([^{}]+)}/g,function(t,e){return e in r?String(r[e]):""}))},e.prototype.createBucket=function(t){return new Js(t)},e.prototype.queryRadius=function(){return 0},e.prototype.queryIntersectsFeature=function(){return !1},e}(ai),Ws={paint:new ii({"background-color":new Qn(Lt.paint_background["background-color"]),"background-pattern":new ri(Lt.paint_background["background-pattern"]),"background-opacity":new Qn(Lt.paint_background["background-opacity"])})},Qs=function(t){function e(e){t.call(this,e,Ws);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e}(ai),tu={paint:new ii({"raster-opacity":new Qn(Lt.paint_raster["raster-opacity"]),"raster-hue-rotate":new Qn(Lt.paint_raster["raster-hue-rotate"]),"raster-brightness-min":new Qn(Lt.paint_raster["raster-brightness-min"]),"raster-brightness-max":new Qn(Lt.paint_raster["raster-brightness-max"]),"raster-saturation":new Qn(Lt.paint_raster["raster-saturation"]),"raster-contrast":new Qn(Lt.paint_raster["raster-contrast"]),"raster-resampling":new Qn(Lt.paint_raster["raster-resampling"]),"raster-fade-duration":new Qn(Lt.paint_raster["raster-fade-duration"])})},eu=function(t){function e(e){t.call(this,e,tu);}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e}(ai);var ru=function(t){function e(e){t.call(this,e,{}),this.implementation=e;}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.is3D=function(){return "3d"===this.implementation.renderingMode},e.prototype.hasOffscreenPass=function(){return void 0!==this.implementation.prerender},e.prototype.recalculate=function(){},e.prototype.updateTransitions=function(){},e.prototype.hasTransition=function(){},e.prototype.serialize=function(){},e.prototype.onAdd=function(t){this.implementation.onAdd&&this.implementation.onAdd(t,t.painter.context.gl);},e.prototype.onRemove=function(t){this.implementation.onRemove&&this.implementation.onRemove(t,t.painter.context.gl);},e}(ai),nu={circle:Qa,heatmap:lo,hillshade:co,fill:Jo,"fill-extrusion":hs,line:Is,symbol:$s,background:Qs,raster:eu};function iu(t){for(var e=0,r=0,n=0,i=t;n=0;h--){var f=o[h];if(!(c.w>f.w||c.h>f.h)){if(c.x=f.x,c.y=f.y,u=Math.max(u,c.y+c.h),s=Math.max(s,c.x+c.w),c.w===f.w&&c.h===f.h){var y=o.pop();h>1,p=-7,c=r?i-1:0,h=r?-1:1,f=t[e+c];for(c+=h,a=f&(1<<-p)-1,f>>=-p,p+=s;p>0;a=256*a+t[e+c],c+=h,p-=8);for(o=a&(1<<-p)-1,a>>=-p,p+=n;p>0;o=256*o+t[e+c],c+=h,p-=8);if(0===a)a=1-l;else{if(a===u)return o?NaN:1/0*(f?-1:1);o+=Math.pow(2,n),a-=l;}return (f?-1:1)*o*Math.pow(2,a-n)},yu=function(t,e,r,n,i,a){var o,s,u,l=8*a-i-1,p=(1<>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,f=n?0:a-1,y=n?1:-1,d=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,o=p):(o=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-o))<1&&(o--,u*=2),(e+=o+c>=1?h/u:h*Math.pow(2,1-c))*u>=2&&(o++,u/=2),o+c>=p?(s=0,o=p):o+c>=1?(s=(e*u-1)*Math.pow(2,i),o+=c):(s=e*Math.pow(2,c-1)*Math.pow(2,i),o=0));i>=8;t[r+f]=255&s,f+=y,s/=256,i-=8);for(o=o<0;t[r+f]=255&o,f+=y,o/=256,l-=8);t[r+f-y]|=128*d;},du=mu;function mu(t){this.buf=ArrayBuffer.isView&&ArrayBuffer.isView(t)?t:new Uint8Array(t||0),this.pos=0,this.type=0,this.length=this.buf.length;}mu.Varint=0,mu.Fixed64=1,mu.Bytes=2,mu.Fixed32=5;function vu(t){return t.type===mu.Bytes?t.readVarint()+t.pos:t.pos+1}function gu(t,e,r){return r?4294967296*e+(t>>>0):4294967296*(e>>>0)+(t>>>0)}function xu(t,e,r){var n=e<=16383?1:e<=2097151?2:e<=268435455?3:Math.floor(Math.log(e)/(7*Math.LN2));r.realloc(n);for(var i=r.pos-1;i>=t;i--)r.buf[i+n]=r.buf[i];}function bu(t,e){for(var r=0;r>>8,t[r+2]=e>>>16,t[r+3]=e>>>24;}function Mu(t,e){return (t[e]|t[e+1]<<8|t[e+2]<<16)+(t[e+3]<<24)}mu.prototype={destroy:function(){this.buf=null;},readFields:function(t,e,r){for(r=r||this.length;this.pos>3,a=this.pos;this.type=7&n,t(i,e,this),this.pos===a&&this.skip(n);}return e},readMessage:function(t,e){return this.readFields(t,e,this.readVarint()+this.pos)},readFixed32:function(){var t=Cu(this.buf,this.pos);return this.pos+=4,t},readSFixed32:function(){var t=Mu(this.buf,this.pos);return this.pos+=4,t},readFixed64:function(){var t=Cu(this.buf,this.pos)+4294967296*Cu(this.buf,this.pos+4);return this.pos+=8,t},readSFixed64:function(){var t=Cu(this.buf,this.pos)+4294967296*Mu(this.buf,this.pos+4);return this.pos+=8,t},readFloat:function(){var t=fu(this.buf,this.pos,!0,23,4);return this.pos+=4,t},readDouble:function(){var t=fu(this.buf,this.pos,!0,52,8);return this.pos+=8,t},readVarint:function(t){var e,r,n=this.buf;return e=127&(r=n[this.pos++]),r<128?e:(e|=(127&(r=n[this.pos++]))<<7,r<128?e:(e|=(127&(r=n[this.pos++]))<<14,r<128?e:(e|=(127&(r=n[this.pos++]))<<21,r<128?e:function(t,e,r){var n,i,a=r.buf;if(i=a[r.pos++],n=(112&i)>>4,i<128)return gu(t,n,e);if(i=a[r.pos++],n|=(127&i)<<3,i<128)return gu(t,n,e);if(i=a[r.pos++],n|=(127&i)<<10,i<128)return gu(t,n,e);if(i=a[r.pos++],n|=(127&i)<<17,i<128)return gu(t,n,e);if(i=a[r.pos++],n|=(127&i)<<24,i<128)return gu(t,n,e);if(i=a[r.pos++],n|=(1&i)<<31,i<128)return gu(t,n,e);throw new Error("Expected varint not more than 10 bytes")}(e|=(15&(r=n[this.pos]))<<28,t,this))))},readVarint64:function(){return this.readVarint(!0)},readSVarint:function(){var t=this.readVarint();return t%2==1?(t+1)/-2:t/2},readBoolean:function(){return Boolean(this.readVarint())},readString:function(){var t=this.readVarint()+this.pos,e=function(t,e,r){var n="",i=e;for(;i239?4:u>223?3:u>191?2:1;if(i+p>r)break;1===p?u<128&&(l=u):2===p?128==(192&(a=t[i+1]))&&(l=(31&u)<<6|63&a)<=127&&(l=null):3===p?(a=t[i+1],o=t[i+2],128==(192&a)&&128==(192&o)&&((l=(15&u)<<12|(63&a)<<6|63&o)<=2047||l>=55296&&l<=57343)&&(l=null)):4===p&&(a=t[i+1],o=t[i+2],s=t[i+3],128==(192&a)&&128==(192&o)&&128==(192&s)&&((l=(15&u)<<18|(63&a)<<12|(63&o)<<6|63&s)<=65535||l>=1114112)&&(l=null)),null===l?(l=65533,p=1):l>65535&&(l-=65536,n+=String.fromCharCode(l>>>10&1023|55296),l=56320|1023&l),n+=String.fromCharCode(l),i+=p;}return n}(this.buf,this.pos,t);return this.pos=t,e},readBytes:function(){var t=this.readVarint()+this.pos,e=this.buf.subarray(this.pos,t);return this.pos=t,e},readPackedVarint:function(t,e){if(this.type!==mu.Bytes)return t.push(this.readVarint(e));var r=vu(this);for(t=t||[];this.pos127;);else if(e===mu.Bytes)this.pos=this.readVarint()+this.pos;else if(e===mu.Fixed32)this.pos+=4;else{if(e!==mu.Fixed64)throw new Error("Unimplemented type: "+e);this.pos+=8;}},writeTag:function(t,e){this.writeVarint(t<<3|e);},realloc:function(t){for(var e=this.length||16;e268435455||t<0?function(t,e){var r,n;t>=0?(r=t%4294967296|0,n=t/4294967296|0):(n=~(-t/4294967296),4294967295^(r=~(-t%4294967296))?r=r+1|0:(r=0,n=n+1|0));if(t>=0x10000000000000000||t<-0x10000000000000000)throw new Error("Given varint doesn't fit into 10 bytes");e.realloc(10),function(t,e,r){r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos]=127&t;}(r,0,e),function(t,e){var r=(7&t)<<4;if(e.buf[e.pos++]|=r|((t>>>=3)?128:0),!t)return;if(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),!t)return;if(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),!t)return;if(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),!t)return;if(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),!t)return;e.buf[e.pos++]=127&t;}(n,e);}(t,this):(this.realloc(4),this.buf[this.pos++]=127&t|(t>127?128:0),t<=127||(this.buf[this.pos++]=127&(t>>>=7)|(t>127?128:0),t<=127||(this.buf[this.pos++]=127&(t>>>=7)|(t>127?128:0),t<=127||(this.buf[this.pos++]=t>>>7&127))));},writeSVarint:function(t){this.writeVarint(t<0?2*-t-1:2*t);},writeBoolean:function(t){this.writeVarint(Boolean(t));},writeString:function(t){t=String(t),this.realloc(4*t.length),this.pos++;var e=this.pos;this.pos=function(t,e,r){for(var n,i,a=0;a55295&&n<57344){if(!i){n>56319||a+1===e.length?(t[r++]=239,t[r++]=191,t[r++]=189):i=n;continue}if(n<56320){t[r++]=239,t[r++]=191,t[r++]=189,i=n;continue}n=i-55296<<10|n-56320|65536,i=null;}else i&&(t[r++]=239,t[r++]=191,t[r++]=189,i=null);n<128?t[r++]=n:(n<2048?t[r++]=n>>6|192:(n<65536?t[r++]=n>>12|224:(t[r++]=n>>18|240,t[r++]=n>>12&63|128),t[r++]=n>>6&63|128),t[r++]=63&n|128);}return r}(this.buf,t,this.pos);var r=this.pos-e;r>=128&&xu(e,r,this),this.pos=e-1,this.writeVarint(r),this.pos+=r;},writeFloat:function(t){this.realloc(4),yu(this.buf,t,this.pos,!0,23,4),this.pos+=4;},writeDouble:function(t){this.realloc(8),yu(this.buf,t,this.pos,!0,52,8),this.pos+=8;},writeBytes:function(t){var e=t.length;this.writeVarint(e),this.realloc(e);for(var r=0;r=128&&xu(r,n,this),this.pos=r-1,this.writeVarint(n),this.pos+=n;},writeMessage:function(t,e,r){this.writeTag(t,mu.Bytes),this.writeRawMessage(e,r);},writePackedVarint:function(t,e){e.length&&this.writeMessage(t,bu,e);},writePackedSVarint:function(t,e){e.length&&this.writeMessage(t,_u,e);},writePackedBoolean:function(t,e){e.length&&this.writeMessage(t,Su,e);},writePackedFloat:function(t,e){e.length&&this.writeMessage(t,wu,e);},writePackedDouble:function(t,e){e.length&&this.writeMessage(t,Au,e);},writePackedFixed32:function(t,e){e.length&&this.writeMessage(t,ku,e);},writePackedSFixed32:function(t,e){e.length&&this.writeMessage(t,zu,e);},writePackedFixed64:function(t,e){e.length&&this.writeMessage(t,Iu,e);},writePackedSFixed64:function(t,e){e.length&&this.writeMessage(t,Bu,e);},writeBytesField:function(t,e){this.writeTag(t,mu.Bytes),this.writeBytes(e);},writeFixed32Field:function(t,e){this.writeTag(t,mu.Fixed32),this.writeFixed32(e);},writeSFixed32Field:function(t,e){this.writeTag(t,mu.Fixed32),this.writeSFixed32(e);},writeFixed64Field:function(t,e){this.writeTag(t,mu.Fixed64),this.writeFixed64(e);},writeSFixed64Field:function(t,e){this.writeTag(t,mu.Fixed64),this.writeSFixed64(e);},writeVarintField:function(t,e){this.writeTag(t,mu.Varint),this.writeVarint(e);},writeSVarintField:function(t,e){this.writeTag(t,mu.Varint),this.writeSVarint(e);},writeStringField:function(t,e){this.writeTag(t,mu.Bytes),this.writeString(e);},writeFloatField:function(t,e){this.writeTag(t,mu.Fixed32),this.writeFloat(e);},writeDoubleField:function(t,e){this.writeTag(t,mu.Fixed64),this.writeDouble(e);},writeBooleanField:function(t,e){this.writeVarintField(t,Boolean(e));}};var Tu=3;function Pu(t,e,r){1===t&&r.readMessage(Vu,e);}function Vu(t,e,r){if(3===t){var n=r.readMessage(Fu,{}),i=n.id,a=n.bitmap,o=n.width,s=n.height,u=n.left,l=n.top,p=n.advance;e.push({id:i,bitmap:new ao({width:o+2*Tu,height:s+2*Tu},a),metrics:{width:o,height:s,left:u,top:l,advance:p}});}}function Fu(t,e,r){1===t?e.id=r.readVarint():2===t?e.bitmap=r.readBytes():3===t?e.width=r.readVarint():4===t?e.height=r.readVarint():5===t?e.left=r.readSVarint():6===t?e.top=r.readSVarint():7===t&&(e.advance=r.readVarint());}var Lu=Tu,Du=function(t,e,r){this.target=t,this.parent=e,this.mapId=r,this.callbacks={},this.callbackID=0,m(["receive"],this),this.target.addEventListener("message",this.receive,!1);};function Ou(t,e,r){var n=2*Math.PI*6378137/256/Math.pow(2,r);return [t*n-2*Math.PI*6378137/2,e*n-2*Math.PI*6378137/2]}Du.prototype.send=function(t,e,r,n){var i=this,a=r?this.mapId+":"+this.callbackID++:null;r&&(this.callbacks[a]=r);var o=[];if(this.target.postMessage({targetMapId:n,sourceMapId:this.mapId,type:t,id:String(a),data:Bn(e,o)},o),r)return {cancel:function(){i.callbacks[a]=null,i.target.postMessage({targetMapId:n,sourceMapId:i.mapId,type:"",id:String(a)});}}},Du.prototype.receive=function(t){var e,r=this,n=t.data,i=n.id;if(!n.targetMapId||this.mapId===n.targetMapId){var a=function(t,e){delete r.callbacks[i];var n=[];r.target.postMessage({sourceMapId:r.mapId,type:"",id:String(i),error:t?Bn(t):null,data:Bn(e,n)},n);};if(""===n.type||""===n.type)e=this.callbacks[n.id],delete this.callbacks[n.id],e&&n.error?e(Cn(n.error)):e&&e(null,Cn(n.data));else if(void 0!==n.id&&this.parent[n.type]){this.callbacks[n.id]=null;var o=this.parent[n.type](n.sourceMapId,Cn(n.data),a);o&&null===this.callbacks[n.id]&&(this.callbacks[n.id]=o.cancel);}else if(void 0!==n.id&&this.parent.getWorkerSource){var s=n.type.split("."),u=Cn(n.data);this.parent.getWorkerSource(n.sourceMapId,s[0],u.source)[s[1]](u,a);}else this.parent[n.type](Cn(n.data));}},Du.prototype.remove=function(){this.target.removeEventListener("message",this.receive,!1);};var Ru=function(t,e){t&&(e?this.setSouthWest(t).setNorthEast(e):4===t.length?this.setSouthWest([t[0],t[1]]).setNorthEast([t[2],t[3]]):this.setSouthWest(t[0]).setNorthEast(t[1]));};Ru.prototype.setNorthEast=function(t){return this._ne=t instanceof Uu?new Uu(t.lng,t.lat):Uu.convert(t),this},Ru.prototype.setSouthWest=function(t){return this._sw=t instanceof Uu?new Uu(t.lng,t.lat):Uu.convert(t),this},Ru.prototype.extend=function(t){var e,r,n=this._sw,i=this._ne;if(t instanceof Uu)e=t,r=t;else{if(!(t instanceof Ru))return Array.isArray(t)?t.every(Array.isArray)?this.extend(Ru.convert(t)):this.extend(Uu.convert(t)):this;if(e=t._sw,r=t._ne,!e||!r)return this}return n||i?(n.lng=Math.min(e.lng,n.lng),n.lat=Math.min(e.lat,n.lat),i.lng=Math.max(r.lng,i.lng),i.lat=Math.max(r.lat,i.lat)):(this._sw=new Uu(e.lng,e.lat),this._ne=new Uu(r.lng,r.lat)),this},Ru.prototype.getCenter=function(){return new Uu((this._sw.lng+this._ne.lng)/2,(this._sw.lat+this._ne.lat)/2)},Ru.prototype.getSouthWest=function(){return this._sw},Ru.prototype.getNorthEast=function(){return this._ne},Ru.prototype.getNorthWest=function(){return new Uu(this.getWest(),this.getNorth())},Ru.prototype.getSouthEast=function(){return new Uu(this.getEast(),this.getSouth())},Ru.prototype.getWest=function(){return this._sw.lng},Ru.prototype.getSouth=function(){return this._sw.lat},Ru.prototype.getEast=function(){return this._ne.lng},Ru.prototype.getNorth=function(){return this._ne.lat},Ru.prototype.toArray=function(){return [this._sw.toArray(),this._ne.toArray()]},Ru.prototype.toString=function(){return "LngLatBounds("+this._sw.toString()+", "+this._ne.toString()+")"},Ru.prototype.isEmpty=function(){return !(this._sw&&this._ne)},Ru.convert=function(t){return !t||t instanceof Ru?t:new Ru(t)};var Uu=function(t,e){if(isNaN(t)||isNaN(e))throw new Error("Invalid LngLat object: ("+t+", "+e+")");if(this.lng=+t,this.lat=+e,this.lat>90||this.lat<-90)throw new Error("Invalid LngLat latitude value: must be between -90 and 90")};function ju(t){return 2*Math.PI*6378137*Math.cos(t*Math.PI/180)}function qu(t){return (180+t)/360}function Nu(t){return (180-180/Math.PI*Math.log(Math.tan(Math.PI/4+t*Math.PI/360)))/360}function Zu(t,e){return t/ju(e)}function Ku(t){var e=180-360*t;return 360/Math.PI*Math.atan(Math.exp(e*Math.PI/180))-90}Uu.prototype.wrap=function(){return new Uu(p(this.lng,-180,180),this.lat)},Uu.prototype.toArray=function(){return [this.lng,this.lat]},Uu.prototype.toString=function(){return "LngLat("+this.lng+", "+this.lat+")"},Uu.prototype.toBounds=function(t){void 0===t&&(t=0);var e=360*t/40075017,r=e/Math.cos(Math.PI/180*this.lat);return new Ru(new Uu(this.lng-r,this.lat-e),new Uu(this.lng+r,this.lat+e))},Uu.convert=function(t){if(t instanceof Uu)return t;if(Array.isArray(t)&&(2===t.length||3===t.length))return new Uu(Number(t[0]),Number(t[1]));if(!Array.isArray(t)&&"object"==typeof t&&null!==t)return new Uu(Number("lng"in t?t.lng:t.lon),Number(t.lat));throw new Error("`LngLatLike` argument must be specified as a LngLat instance, an object {lng: , lat: }, an object {lon: , lat: }, or an array of [, ]")};var Gu=function(t,e,r){void 0===r&&(r=0),this.x=+t,this.y=+e,this.z=+r;};Gu.fromLngLat=function(t,e){void 0===e&&(e=0);var r=Uu.convert(t);return new Gu(qu(r.lng),Nu(r.lat),Zu(e,r.lat))},Gu.prototype.toLngLat=function(){return new Uu(360*this.x-180,Ku(this.y))},Gu.prototype.toAltitude=function(){return t=this.z,e=this.y,t*ju(Ku(e));var t,e;};var Xu=function(t,e,r){this.z=t,this.x=e,this.y=r,this.key=Yu(0,t,e,r);};Xu.prototype.equals=function(t){return this.z===t.z&&this.x===t.x&&this.y===t.y},Xu.prototype.url=function(t,e){var r,n,i,a,o,s=(r=this.x,n=this.y,i=this.z,a=Ou(256*r,256*(n=Math.pow(2,i)-n-1),i),o=Ou(256*(r+1),256*(n+1),i),a[0]+","+a[1]+","+o[0]+","+o[1]),u=function(t,e,r){for(var n,i="",a=t;a>0;a--)i+=(e&(n=1<this.canonical.z?new Hu(t,this.wrap,this.canonical.z,this.canonical.x,this.canonical.y):new Hu(t,this.wrap,t,this.canonical.x>>e,this.canonical.y>>e)},Hu.prototype.isChildOf=function(t){if(t.wrap!==this.wrap)return !1;var e=this.canonical.z-t.canonical.z;return 0===t.overscaledZ||t.overscaledZ>e&&t.canonical.y===this.canonical.y>>e},Hu.prototype.children=function(t){if(this.overscaledZ>=t)return [new Hu(this.overscaledZ+1,this.wrap,this.canonical.z,this.canonical.x,this.canonical.y)];var e=this.canonical.z+1,r=2*this.canonical.x,n=2*this.canonical.y;return [new Hu(e,this.wrap,e,r,n),new Hu(e,this.wrap,e,r+1,n),new Hu(e,this.wrap,e,r,n+1),new Hu(e,this.wrap,e,r+1,n+1)]},Hu.prototype.isLessThan=function(t){return this.wrapt.wrap)&&(this.overscaledZt.overscaledZ)&&(this.canonical.xt.canonical.x)&&this.canonical.y=this.dim+1||e<-1||e>=this.dim+1)throw new RangeError("out of range source coordinates for DEM data");return (e+1)*this.stride+(t+1)},$u.prototype._unpackMapbox=function(t,e,r){return (256*t*256+256*e+r)/10-1e4},$u.prototype._unpackTerrarium=function(t,e,r){return 256*t+e+r/256-32768},$u.prototype.getPixels=function(){return new oo({width:this.stride,height:this.stride},new Uint8Array(this.data.buffer))},$u.prototype.backfillBorder=function(t,e,r){if(this.dim!==t.dim)throw new Error("dem dimension mismatch");var n=e*this.dim,i=e*this.dim+this.dim,a=r*this.dim,o=r*this.dim+this.dim;switch(e){case-1:n=i-1;break;case 1:i=n+1;}switch(r){case-1:a=o-1;break;case 1:o=a+1;}for(var s=-e*this.dim,u=-r*this.dim,l=a;l=0)null!==this.deletedStates[t][n]&&(this.deletedStates[t][n]=this.deletedStates[t][n]||{},this.deletedStates[t][n][r]=null);else if(void 0!==e&&e>=0){if(this.stateChanges[t]&&this.stateChanges[t][n])for(r in this.deletedStates[t][n]={},this.stateChanges[t][n])this.deletedStates[t][n][r]=null;else this.deletedStates[t][n]=null;}else this.deletedStates[t]=null;}},rl.prototype.getState=function(t,e){var r=String(e),n=this.state[t]||{},i=this.stateChanges[t]||{},a=c({},n[r],i[r]);if(null===this.deletedStates[t])return {};if(this.deletedStates[t]){var o=this.deletedStates[t][e];if(null===o)return {};for(var s in o)delete a[s];}return a},rl.prototype.initializeTileState=function(t,e){t.setFeatureState(this.state,e);},rl.prototype.coalesceChanges=function(t,e){var r={};for(var n in this.stateChanges){this.state[n]=this.state[n]||{};var i={};for(var a in this.stateChanges[n])this.state[n][a]||(this.state[n][a]={}),c(this.state[n][a],this.stateChanges[n][a]),i[a]=this.state[n][a];r[n]=i;}for(var o in this.deletedStates){this.state[o]=this.state[o]||{};var s={};if(null===this.deletedStates[o])for(var u in this.state[o])s[u]={},this.state[o][u]={};else for(var l in this.deletedStates[o]){if(null===this.deletedStates[o][l])this.state[o][l]={};else for(var p=0,h=Object.keys(this.deletedStates[o][l]);p=0&&p[3]>=0&&s.insert(o,p[0],p[1],p[2],p[3]);}},nl.prototype.loadVTLayers=function(){return this.vtLayers||(this.vtLayers=new is.VectorTile(new du(this.rawTileData)).layers,this.sourceLayerCoder=new Qu(this.vtLayers?Object.keys(this.vtLayers).sort():["_geojsonTileLayer"])),this.vtLayers},nl.prototype.query=function(t,e,r){var n=this;this.loadVTLayers();for(var a=t.params||{},o=ya/t.tileSize/t.scale,s=Jr(a.filter),u=t.queryGeometry,l=t.queryPadding*o,p=il(u),c=this.grid.query(p.minX-l,p.minY-l,p.maxX+l,p.maxY+l),h=il(t.cameraQueryGeometry),f=this.grid3D.query(h.minX-l,h.minY-l,h.maxX+l,h.maxY+l,function(e,r,n,a){return function(t,e,r,n,a){for(var o=0,s=t;o=u.x&&a>=u.y)return !0}var l=[new i(e,r),new i(e,a),new i(n,a),new i(n,r)];if(t.length>2)for(var p=0,c=l;p=0)return !0;return !1}(a,u)){var l=this.sourceLayerCoder.decode(r),p=this.vtLayers[l].feature(n);if(i(new Zn(this.tileID.overscaledZ),p))for(var c=0;c>u.z,p=new i(u.x*l,u.y*l),c=new i(p.x+l,p.y+l),h=this.segments.prepareSegment(4,r,n);r.emplaceBack(p.x,p.y,p.x,p.y),r.emplaceBack(c.x,p.y,c.x,p.y),r.emplaceBack(p.x,c.y,p.x,c.y),r.emplaceBack(c.x,c.y,c.x,c.y);var f=h.vertexLength;n.emplaceBack(f,f+1,f+2),n.emplaceBack(f+1,f+2,f+3),h.vertexLength+=4,h.primitiveLength+=2;}this.maskedBoundsBuffer=e.createVertexBuffer(r,Wu.members),this.maskedIndexBuffer=e.createIndexBuffer(n);}},ol.prototype.hasData=function(){return "loaded"===this.state||"reloading"===this.state||"expired"===this.state},ol.prototype.patternsLoaded=function(){return this.imageAtlas&&!!Object.keys(this.imageAtlas.patternPositions).length},ol.prototype.setExpiryData=function(t){var e=this.expirationTime;if(t.cacheControl){var r=k(t.cacheControl);r["max-age"]&&(this.expirationTime=Date.now()+1e3*r["max-age"]);}else t.expires&&(this.expirationTime=new Date(t.expires).getTime());if(this.expirationTime){var n=Date.now(),i=!1;if(this.expirationTime>n)i=!1;else if(e)if(this.expirationTime=0&&n>=t&&cl[this.text.charCodeAt(n)];n--)r--;this.text=this.text.substring(t,r),this.sectionIndex=this.sectionIndex.slice(t,r);},ll.prototype.substring=function(t,e){var r=new ll;return r.text=this.text.substring(t,e),r.sectionIndex=this.sectionIndex.slice(t,e),r.sections=this.sections,r},ll.prototype.toString=function(){return this.text},ll.prototype.getMaxScale=function(){var t=this;return this.sectionIndex.reduce(function(e,r){return Math.max(e,t.sections[r].scale)},0)};var cl={9:!0,10:!0,11:!0,12:!0,13:!0,32:!0},hl={};function fl(t,e,r,n){var i=Math.pow(t-e,2);return n?t=0,u=0,l=0;l-r/2;){if(--o<0)return !1;s-=t[o].dist(a),a=t[o];}s+=t[o].dist(t[o+1]),o++;for(var u=[],l=0;sn;)l-=u.shift().angleDelta;if(l>i)return !1;o++,s+=c.dist(h);}return !0}function _l(t){for(var e=0,r=0;rl){var y=(l-u)/f,d=Ee(c.x,h.x,y),m=Ee(c.y,h.y,y),v=new Ls(d,m,h.angleTo(c),p);return v._round(),!o||bl(t,v,s,o,e)?v:void 0}u+=f;}}function kl(t,e,r,n,i,a,o,s,u){var l=wl(n,a,o),p=Al(n,i),c=p*o,h=0===t[0].x||t[0].x===u||0===t[0].y||t[0].y===u;return e-c=0&&_=0&&w=0&&f+p<=c){var A=new Ls(_,w,x,d);A._round(),i&&!bl(e,A,o,i,a)||y.push(A);}}h+=g;}u||y.length||s||(y=t(e,h/2,n,i,a,o,s,!0,l));return y}(t,h?e/2*s%e:(p/2+2*a)*o*s%e,e,l,r,c,h,!1,u)}hl[10]=!0,hl[32]=!0,hl[38]=!0,hl[40]=!0,hl[41]=!0,hl[43]=!0,hl[45]=!0,hl[47]=!0,hl[173]=!0,hl[183]=!0,hl[8203]=!0,hl[8208]=!0,hl[8211]=!0,hl[8231]=!0;var zl=function(t,e,r,n,a,o,s,u,l,p,c,h){var f=s.top*u-l,y=s.bottom*u+l,d=s.left*u-l,m=s.right*u+l;if(this.boxStartIndex=t.length,p){var v=y-f,g=m-d;v>0&&(v=Math.max(10*u,v),this._addLineCollisionCircles(t,e,r,r.segment,g,v,n,a,o,c));}else{if(h){var x=new i(d,f),b=new i(m,f),_=new i(d,y),w=new i(m,y),A=h*Math.PI/180;x._rotate(A),b._rotate(A),_._rotate(A),w._rotate(A),d=Math.min(x.x,b.x,_.x,w.x),m=Math.max(x.x,b.x,_.x,w.x),f=Math.min(x.y,b.y,_.y,w.y),y=Math.max(x.y,b.y,_.y,w.y);}t.emplaceBack(r.x,r.y,d,f,m,y,n,a,o,0,0);}this.boxEndIndex=t.length;};zl.prototype._addLineCollisionCircles=function(t,e,r,n,i,a,o,s,u,l){var p=a/2,c=Math.floor(i/p)||1,h=1+.4*Math.log(l)/Math.LN2,f=Math.floor(c*h/2),y=-a/2,d=r,m=n+1,v=y,g=-i/2,x=g-i/4;do{if(--m<0){if(v>g)return;m=0;break}v-=e[m].dist(d),d=e[m];}while(v>x);for(var b=e[m].dist(e[m+1]),_=-f;_i&&(A+=w-i),!(A=e.length)return;b=e[m].dist(e[m+1]);}var S=A-v,k=e[m],z=e[m+1].sub(k)._unit()._mult(S)._add(k)._round(),I=Math.abs(A-y)0)for(var r=(this.length>>1)-1;r>=0;r--)this._down(r);};function Bl(t,e){return te?1:0}function Cl(t,e,r){void 0===e&&(e=1),void 0===r&&(r=!1);for(var n=1/0,a=1/0,o=-1/0,s=-1/0,u=t[0],l=0;lo)&&(o=p.x),(!l||p.y>s)&&(s=p.y);}var c=o-n,h=s-a,f=Math.min(c,h),y=f/2,d=new Il([],El);if(0===f)return new i(n,a);for(var m=n;mg.d||!g.d)&&(g=b,r&&console.log("found best %d after %d probes",Math.round(1e4*b.d)/1e4,x)),b.max-g.d<=e||(y=b.h/2,d.push(new Ml(b.p.x-y,b.p.y-y,y,t)),d.push(new Ml(b.p.x+y,b.p.y-y,y,t)),d.push(new Ml(b.p.x-y,b.p.y+y,y,t)),d.push(new Ml(b.p.x+y,b.p.y+y,y,t)),x+=4);}return r&&(console.log("num probes: "+x),console.log("best distance: "+g.d)),g.p}function El(t,e){return e.max-t.max}function Ml(t,e,r,n){this.p=new i(t,e),this.h=r,this.d=function(t,e){for(var r=!1,n=1/0,i=0;it.y!=p.y>t.y&&t.x<(p.x-l.x)*(t.y-l.y)/(p.y-l.y)+l.x&&(r=!r),n=Math.min(n,Ia(t,l,p));}return (r?1:-1)*Math.sqrt(n)}(this.p,n),this.max=this.d+this.h*Math.SQRT2;}Il.prototype.push=function(t){this.data.push(t),this.length++,this._up(this.length-1);},Il.prototype.pop=function(){if(0!==this.length){var t=this.data[0];return this.length--,this.length>0&&(this.data[0]=this.data[this.length],this._down(0)),this.data.pop(),t}},Il.prototype.peek=function(){return this.data[0]},Il.prototype._up=function(t){for(var e=this.data,r=this.compare,n=e[t];t>0;){var i=t-1>>1,a=e[i];if(r(n,a)>=0)break;e[t]=a,t=i;}e[t]=n;},Il.prototype._down=function(t){for(var e=this.data,r=this.compare,n=this.length>>1,i=e[t];t=0)break;e[t]=o,t=a;}e[t]=i;};var Tl=e(function(t){t.exports=function(t,e){var r,n,i,a,o,s,u,l;for(r=3&t.length,n=t.length-r,i=e,o=3432918353,s=461845907,l=0;l>>16)*o&65535)<<16)&4294967295)<<15|u>>>17))*s+(((u>>>16)*s&65535)<<16)&4294967295)<<13|i>>>19))+((5*(i>>>16)&65535)<<16)&4294967295))+((58964+(a>>>16)&65535)<<16);switch(u=0,r){case 3:u^=(255&t.charCodeAt(l+2))<<16;case 2:u^=(255&t.charCodeAt(l+1))<<8;case 1:i^=u=(65535&(u=(u=(65535&(u^=255&t.charCodeAt(l)))*o+(((u>>>16)*o&65535)<<16)&4294967295)<<15|u>>>17))*s+(((u>>>16)*s&65535)<<16)&4294967295;}return i^=t.length,i=2246822507*(65535&(i^=i>>>16))+((2246822507*(i>>>16)&65535)<<16)&4294967295,i=3266489909*(65535&(i^=i>>>13))+((3266489909*(i>>>16)&65535)<<16)&4294967295,(i^=i>>>16)>>>0};}),Pl=e(function(t){t.exports=function(t,e){for(var r,n=t.length,i=e^n,a=0;n>=4;)r=1540483477*(65535&(r=255&t.charCodeAt(a)|(255&t.charCodeAt(++a))<<8|(255&t.charCodeAt(++a))<<16|(255&t.charCodeAt(++a))<<24))+((1540483477*(r>>>16)&65535)<<16),i=1540483477*(65535&i)+((1540483477*(i>>>16)&65535)<<16)^(r=1540483477*(65535&(r^=r>>>24))+((1540483477*(r>>>16)&65535)<<16)),n-=4,++a;switch(n){case 3:i^=(255&t.charCodeAt(a+2))<<16;case 2:i^=(255&t.charCodeAt(a+1))<<8;case 1:i=1540483477*(65535&(i^=255&t.charCodeAt(a)))+((1540483477*(i>>>16)&65535)<<16);}return i=1540483477*(65535&(i^=i>>>13))+((1540483477*(i>>>16)&65535)<<16),(i^=i>>>15)>>>0};}),Vl=Tl,Fl=Tl,Ll=Pl;Vl.murmur3=Fl,Vl.murmur2=Ll;var Dl=7;function Ol(t,e){var r=0,n=0,i=e/Math.sqrt(2);switch(t){case"top-right":case"top-left":n=i-Dl;break;case"bottom-right":case"bottom-left":n=-i+Dl;break;case"bottom":n=-e+Dl;break;case"top":n=e-Dl;}switch(t){case"top-right":case"bottom-right":r=-i;break;case"top-left":case"bottom-left":r=i;break;case"left":r=e;break;case"right":r=-e;}return [r,n]}function Rl(t){switch(t){case"right":case"top-right":case"bottom-right":return "right";case"left":case"top-left":case"bottom-left":return "left"}return "center"}function Ul(t,e,r,n,a,o,s){var u=o.layoutTextSize.evaluate(e,{}),l=o.layoutIconSize.evaluate(e,{}),p=o.textMaxSize.evaluate(e,{});void 0===p&&(p=u);var c=t.layers[0].layout,h=c.get("icon-offset").evaluate(e,{}),f=Nl(r.horizontal),y=u/24,d=t.tilePixelRatio*y,m=t.tilePixelRatio*p/24,v=t.tilePixelRatio*l,g=t.tilePixelRatio*c.get("symbol-spacing"),x=c.get("text-padding")*t.tilePixelRatio,b=c.get("icon-padding")*t.tilePixelRatio,_=c.get("text-max-angle")/180*Math.PI,A="map"===c.get("text-rotation-alignment")&&"point"!==c.get("symbol-placement"),S="map"===c.get("icon-rotation-alignment")&&"point"!==c.get("symbol-placement"),k=c.get("symbol-placement"),z=g/2,I=function(u,l){l.x<0||l.x>=ya||l.y<0||l.y>=ya||function(t,e,r,n,a,o,s,u,l,p,c,h,f,y,d,m,v,g,x,b,_){var A,S,k=t.addToLineVertexArray(e,r),z=0,I=0,B=0,C={},E=Vl(""),M=(o.layout.get("text-radial-offset").evaluate(x,{})||0)*sl;for(var T in n.horizontal){var P=n.horizontal[T];if(!A){E=Vl(P.text);var V=o.layout.get("text-rotate").evaluate(x,{});A=new zl(s,r,e,u,l,p,P,c,h,f,t.overscaling,V);}var F=1===P.lineCount;if(I+=ql(t,e,P,o,f,x,y,k,n.vertical?ul.horizontal:ul.horizontalOnly,F?Object.keys(n.horizontal):[T],C,b,_),F)break}n.vertical&&(B+=ql(t,e,n.vertical,o,f,x,y,k,ul.vertical,["vertical"],C,b,_));var L=A?A.boxStartIndex:t.collisionBoxArray.length,D=A?A.boxEndIndex:t.collisionBoxArray.length;if(a){var O=function(t,e,r,n,a,o){var s,u,l,p,c=e.image,h=r.layout,f=e.top-1/c.pixelRatio,y=e.left-1/c.pixelRatio,d=e.bottom+1/c.pixelRatio,m=e.right+1/c.pixelRatio;if("none"!==h.get("icon-text-fit")&&a){var v=m-y,g=d-f,x=h.get("text-size").evaluate(o,{})/24,b=a.left*x,_=a.right*x,w=a.top*x,A=_-b,S=a.bottom*x-w,k=h.get("icon-text-fit-padding")[0],z=h.get("icon-text-fit-padding")[1],I=h.get("icon-text-fit-padding")[2],B=h.get("icon-text-fit-padding")[3],C="width"===h.get("icon-text-fit")?.5*(S-g):0,E="height"===h.get("icon-text-fit")?.5*(A-v):0,M="width"===h.get("icon-text-fit")||"both"===h.get("icon-text-fit")?A:v,T="height"===h.get("icon-text-fit")||"both"===h.get("icon-text-fit")?S:g;s=new i(b+E-B,w+C-k),u=new i(b+E+z+M,w+C-k),l=new i(b+E+z+M,w+C+I+T),p=new i(b+E-B,w+C+I+T);}else s=new i(y,f),u=new i(m,f),l=new i(m,d),p=new i(y,d);var P=r.layout.get("icon-rotate").evaluate(o,{})*Math.PI/180;if(P){var V=Math.sin(P),F=Math.cos(P),L=[F,-V,V,F];s._matMult(L),u._matMult(L),p._matMult(L),l._matMult(L);}return [{tl:s,tr:u,bl:p,br:l,tex:c.paddedRect,writingMode:void 0,glyphOffset:[0,0]}]}(0,a,o,0,Nl(n.horizontal),x),R=o.layout.get("icon-rotate").evaluate(x,{});S=new zl(s,r,e,u,l,p,a,d,m,!1,t.overscaling,R),z=4*O.length;var U=t.iconSizeData,j=null;"source"===U.kind?(j=[Ds*o.layout.get("icon-size").evaluate(x,{})])[0]>jl&&w(t.layerIds[0]+': Value for "icon-size" is >= 256. Reduce your "icon-size".'):"composite"===U.kind&&((j=[Ds*_.compositeIconSizes[0].evaluate(x,{}),Ds*_.compositeIconSizes[1].evaluate(x,{})])[0]>jl||j[1]>jl)&&w(t.layerIds[0]+': Value for "icon-size" is >= 256. Reduce your "icon-size".'),t.addSymbols(t.icon,O,j,g,v,x,!1,e,k.lineStartIndex,k.lineLength);}var q=S?S.boxStartIndex:t.collisionBoxArray.length,N=S?S.boxEndIndex:t.collisionBoxArray.length;t.glyphOffsetArray.length>=Js.MAX_GLYPHS&&w("Too many glyphs being rendered in a tile. See https://github.com/mapbox/mapbox-gl-js/issues/2907");t.symbolInstances.emplaceBack(e.x,e.y,C.right>=0?C.right:-1,C.center>=0?C.center:-1,C.left>=0?C.left:-1,C.vertical||-1,E,L,D,q,N,u,I,B,z,0,c,M);}(t,l,u,r,n,t.layers[0],t.collisionBoxArray,e.index,e.sourceLayerIndex,t.index,d,x,A,s,v,b,S,h,e,a,o);};if("line"===k)for(var B=0,C=function(t,e,r,n,a){for(var o=[],s=0;s=n&&h.x>=n||(c.x>=n?c=new i(n,c.y+(h.y-c.y)*((n-c.x)/(h.x-c.x)))._round():h.x>=n&&(h=new i(n,c.y+(h.y-c.y)*((n-c.x)/(h.x-c.x)))._round()),c.y>=a&&h.y>=a||(c.y>=a?c=new i(c.x+(h.x-c.x)*((a-c.y)/(h.y-c.y)),a)._round():h.y>=a&&(h=new i(c.x+(h.x-c.x)*((a-c.y)/(h.y-c.y)),a)._round()),l&&c.equals(l[l.length-1])||(l=[c],o.push(l)),l.push(h)))));}return o}(e.geometry,0,0,ya,ya);B1){var D=Sl(L,_,r.vertical||f,n,24,m);D&&I(L,D);}}else if("Polygon"===e.type)for(var O=0,R=qo(e.geometry,0);Ojl&&w(t.layerIds[0]+': Value for "text-size" is >= 256. Reduce your "text-size".'):"composite"===d.kind&&((m=[Ds*f.compositeTextSizes[0].evaluate(o,{}),Ds*f.compositeTextSizes[1].evaluate(o,{})])[0]>jl||m[1]>jl)&&w(t.layerIds[0]+': Value for "text-size" is >= 256. Reduce your "text-size".'),t.addSymbols(t.text,y,m,s,a,o,l,e,u.lineStartIndex,u.lineLength);for(var v=0,g=p;v=0;o--)if(n.dist(a[o])yt&&(t.send("enforceCacheSizeLimit",ft),xt=0);},t.clamp=l,t.clearTileCache=function(t){var e=self.caches.delete(ht);t&&e.catch(t).then(function(){return t()});},t.clone=function(t){var e=new La(16);return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e[4]=t[4],e[5]=t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e[9]=t[9],e[10]=t[10],e[11]=t[11],e[12]=t[12],e[13]=t[13],e[14]=t[14],e[15]=t[15],e},t.clone$1=b,t.config=V,t.create=function(){var t=new La(16);return La!=Float32Array&&(t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0),t[0]=1,t[5]=1,t[10]=1,t[15]=1,t},t.create$1=Da,t.create$2=function(){var t=new La(4);return La!=Float32Array&&(t[1]=0,t[2]=0),t[0]=1,t[3]=1,t},t.createCommonjsModule=e,t.createExpression=Fr,t.createLayout=li,t.createStyleLayer=function(t){return "custom"===t.type?new ru(t):new nu[t.type](t)},t.deepEqual=o,t.ease=u,t.emitValidationErrors=bn,t.endsWith=v,t.enforceCacheSizeLimit=function(t){self.caches&&self.caches.open(ht).then(function(e){e.keys().then(function(r){for(var n=0;n=P.maxzoom))if("none"!==P.visibility)a(_,this.zoom),(d[P.id]=P.createBucket({index:l.bucketLayerIDs.length,layers:_,zoom:this.zoom,pixelRatio:this.pixelRatio,overscaling:this.overscaling,collisionBoxArray:this.collisionBoxArray,sourceLayerIndex:x,sourceID:this.source})).populate(w,g),l.bucketLayerIDs.push(_.map(function(e){return e.id}));}}}var I=e.mapObject(g.glyphDependencies,function(e){return Object.keys(e).map(Number)});Object.keys(I).length?o.send("getGlyphs",{uid:this.uid,stacks:I},function(e,t){h||(h=e,c=t,D.call(s));}):c={};var T=Object.keys(g.iconDependencies);T.length?o.send("getImages",{icons:T},function(e,t){h||(h=e,p=t,D.call(s));}):p={};var L=Object.keys(g.patternDependencies);function D(){if(h)return n(h);if(c&&p&&f){var t=new i(c),r=new e.ImageAtlas(p,f);for(var o in d){var s=d[o];s instanceof e.SymbolBucket?(a(s.layers,this.zoom),e.performSymbolLayout(s,c,t.positions,p,r.iconPositions,this.showCollisionBoxes)):s.hasPattern&&(s instanceof e.LineBucket||s instanceof e.FillBucket||s instanceof e.FillExtrusionBucket)&&(a(s.layers,this.zoom),s.addFeatures(g,r.patternPositions));}this.status="done",n(null,{buckets:e.values(d).filter(function(e){return !e.isEmpty()}),featureIndex:l,collisionBoxArray:this.collisionBoxArray,glyphAtlasImage:t.image,imageAtlas:r,glyphMap:this.returnDependencies?c:null,iconMap:this.returnDependencies?p:null,glyphPositions:this.returnDependencies?t.positions:null});}}L.length?o.send("getImages",{icons:L},function(e,t){h||(h=e,f=t,D.call(s));}):f={},D.call(this);};var s="undefined"!=typeof performance,u={getEntriesByName:function(e){return !!(s&&performance&&performance.getEntriesByName)&&performance.getEntriesByName(e)},mark:function(e){return !!(s&&performance&&performance.mark)&&performance.mark(e)},measure:function(e,t,r){return !!(s&&performance&&performance.measure)&&performance.measure(e,t,r)},clearMarks:function(e){return !!(s&&performance&&performance.clearMarks)&&performance.clearMarks(e)},clearMeasures:function(e){return !!(s&&performance&&performance.clearMeasures)&&performance.clearMeasures(e)}},l=function(e){this._marks={start:[e.url,"start"].join("#"),end:[e.url,"end"].join("#"),measure:e.url.toString()},u.mark(this._marks.start);};function h(t,r){var o=e.getArrayBuffer(t.request,function(t,o,i,n){t?r(t):o&&r(null,{vectorTile:new e.vectorTile.VectorTile(new e.pbf(o)),rawData:o,cacheControl:i,expires:n});});return function(){o.cancel(),r();}}l.prototype.finish=function(){u.mark(this._marks.end);var e=u.getEntriesByName(this._marks.measure);return 0===e.length&&(u.measure(this._marks.measure,this._marks.start,this._marks.end),e=u.getEntriesByName(this._marks.measure),u.clearMarks(this._marks.start),u.clearMarks(this._marks.end),u.clearMeasures(this._marks.measure)),e},u.Performance=l;var c=function(e,t,r){this.actor=e,this.layerIndex=t,this.loadVectorData=r||h,this.loading={},this.loaded={};};c.prototype.loadTile=function(t,r){var o=this,i=t.uid;this.loading||(this.loading={});var a=!!(t&&t.request&&t.request.collectResourceTiming)&&new u.Performance(t.request),s=this.loading[i]=new n(t);s.abort=this.loadVectorData(t,function(t,n){if(delete o.loading[i],t||!n)return s.status="done",o.loaded[i]=s,r(t);var u=n.rawData,l={};n.expires&&(l.expires=n.expires),n.cacheControl&&(l.cacheControl=n.cacheControl);var h={};if(a){var c=a.finish();c&&(h.resourceTiming=JSON.parse(JSON.stringify(c)));}s.vectorTile=n.vectorTile,s.parse(n.vectorTile,o.layerIndex,o.actor,function(t,o){if(t||!o)return r(t);r(null,e.extend({rawTileData:u.slice(0)},o,l,h));}),o.loaded=o.loaded||{},o.loaded[i]=s;});},c.prototype.reloadTile=function(e,t){var r=this.loaded,o=e.uid,i=this;if(r&&r[o]){var n=r[o];n.showCollisionBoxes=e.showCollisionBoxes;var a=function(e,r){var o=n.reloadCallback;o&&(delete n.reloadCallback,n.parse(n.vectorTile,i.layerIndex,i.actor,o)),t(e,r);};"parsing"===n.status?n.reloadCallback=a:"done"===n.status&&(n.vectorTile?n.parse(n.vectorTile,this.layerIndex,this.actor,a):a());}},c.prototype.abortTile=function(e,t){var r=this.loading,o=e.uid;r&&r[o]&&r[o].abort&&(r[o].abort(),delete r[o]),t();},c.prototype.removeTile=function(e,t){var r=this.loaded,o=e.uid;r&&r[o]&&delete r[o],t();};var p=function(){this.loaded={};};p.prototype.loadTile=function(t,r){var o=t.uid,i=t.encoding,n=t.rawImageData,a=new e.DEMData(o,n,i);this.loaded=this.loaded||{},this.loaded[o]=a,r(null,a);},p.prototype.removeTile=function(e){var t=this.loaded,r=e.uid;t&&t[r]&&delete t[r];};var f={RADIUS:6378137,FLATTENING:1/298.257223563,POLAR_RADIUS:6356752.3142};function d(e){var t=0;if(e&&e.length>0){t+=Math.abs(g(e[0]));for(var r=1;r2){for(a=0;a=0}(e)===t?e:e.reverse()}var M=e.vectorTile.VectorTileFeature.prototype.toGeoJSON,k=function(t){this._feature=t,this.extent=e.EXTENT,this.type=t.type,this.properties=t.tags,"id"in t&&!isNaN(t.id)&&(this.id=parseInt(t.id,10));};k.prototype.loadGeometry=function(){if(1===this._feature.type){for(var t=[],r=0,o=this._feature.geometry;r>31}function J(e,t){for(var r=e.loadGeometry(),o=e.type,i=0,n=0,a=r.length,s=0;s>1;!function e(t,r,o,i,n,a){for(;n>i;){if(n-i>600){var s=n-i+1,u=o-i+1,l=Math.log(s),h=.5*Math.exp(2*l/3),c=.5*Math.sqrt(l*h*(s-h)/s)*(u-s/2<0?-1:1),p=Math.max(i,Math.floor(o-u*h/s+c)),f=Math.min(n,Math.floor(o+(s-u)*h/s+c));e(t,r,o,p,f,a);}var d=r[2*o+a],g=i,m=n;for(j(t,r,i,o),r[2*n+a]>d&&j(t,r,i,n);gd;)m--;}r[2*i+a]===d?j(t,r,i,m):j(t,r,++m,n),m<=o&&(i=m+1),o<=m&&(n=m-1);}}(e,t,a,o,i,n%2),Z(e,t,r,o,a-1,n+1),Z(e,t,r,a+1,i,n+1);}}function j(e,t,r,o){Y(e,r,o),Y(t,2*r,2*o),Y(t,2*r+1,2*o+1);}function Y(e,t,r){var o=e[t];e[t]=e[r],e[r]=o;}function V(e,t,r,o){var i=e-r,n=t-o;return i*i+n*n}L.fromVectorTileJs=D,L.fromGeojsonVt=C,L.GeoJSONWrapper=z;var X=function(e){return e[0]},W=function(e){return e[1]},R=function(e,t,r,o,i){void 0===t&&(t=X),void 0===r&&(r=W),void 0===o&&(o=64),void 0===i&&(i=Float64Array),this.nodeSize=o,this.points=e;for(var n=e.length<65536?Uint16Array:Uint32Array,a=this.ids=new n(e.length),s=this.coords=new i(2*e.length),u=0;u=r&&s<=i&&u>=o&&u<=n&&h.push(e[d]);else{var g=Math.floor((f+p)/2);s=t[2*g],u=t[2*g+1],s>=r&&s<=i&&u>=o&&u<=n&&h.push(e[g]);var m=(c+1)%2;(0===c?r<=s:o<=u)&&(l.push(f),l.push(g-1),l.push(m)),(0===c?i>=s:n>=u)&&(l.push(g+1),l.push(p),l.push(m));}}return h}(this.ids,this.coords,e,t,r,o,this.nodeSize)},R.prototype.within=function(e,t,r){return function(e,t,r,o,i,n){for(var a=[0,e.length-1,0],s=[],u=i*i;a.length;){var l=a.pop(),h=a.pop(),c=a.pop();if(h-c<=n)for(var p=c;p<=h;p++)V(t[2*p],t[2*p+1],r,o)<=u&&s.push(e[p]);else{var f=Math.floor((c+h)/2),d=t[2*f],g=t[2*f+1];V(d,g,r,o)<=u&&s.push(e[f]);var m=(l+1)%2;(0===l?r-i<=d:o-i<=g)&&(a.push(c),a.push(f-1),a.push(m)),(0===l?r+i>=d:o+i>=g)&&(a.push(f+1),a.push(h),a.push(m));}}return s}(this.ids,this.coords,e,t,r,this.nodeSize)};var q={minZoom:0,maxZoom:16,radius:40,extent:512,nodeSize:64,log:!1,reduce:null,map:function(e){return e}},U=function(e){this.options=re(Object.create(q),e),this.trees=new Array(this.options.maxZoom+1);};function $(e,t,r,o,i){return {x:e,y:t,zoom:1/0,id:r,parentId:-1,numPoints:o,properties:i}}function H(e,t){var r=e.geometry.coordinates,o=r[0],i=r[1];return {x:ee(o),y:te(i),zoom:1/0,index:t,parentId:-1}}function K(e){return {type:"Feature",id:e.id,properties:Q(e),geometry:{type:"Point",coordinates:[(o=e.x,360*(o-.5)),(t=e.y,r=(180-360*t)*Math.PI/180,360*Math.atan(Math.exp(r))/Math.PI-90)]}};var t,r,o;}function Q(e){var t=e.numPoints,r=t>=1e4?Math.round(t/1e3)+"k":t>=1e3?Math.round(t/100)/10+"k":t;return re(re({},e.properties),{cluster:!0,cluster_id:e.id,point_count:t,point_count_abbreviated:r})}function ee(e){return e/360+.5}function te(e){var t=Math.sin(e*Math.PI/180),r=.5-.25*Math.log((1+t)/(1-t))/Math.PI;return r<0?0:r>1?1:r}function re(e,t){for(var r in t)e[r]=t[r];return e}function oe(e){return e.x}function ie(e){return e.y}function ne(e,t,r,o,i,n){var a=i-r,s=n-o;if(0!==a||0!==s){var u=((e-r)*a+(t-o)*s)/(a*a+s*s);u>1?(r=i,o=n):u>0&&(r+=a*u,o+=s*u);}return (a=e-r)*a+(s=t-o)*s}function ae(e,t,r,o){var i={id:void 0===e?null:e,type:t,geometry:r,tags:o,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};return function(e){var t=e.geometry,r=e.type;if("Point"===r||"MultiPoint"===r||"LineString"===r)se(e,t);else if("Polygon"===r||"MultiLineString"===r)for(var o=0;o0&&(a+=o?(i*l-u*n)/2:Math.sqrt(Math.pow(u-i,2)+Math.pow(l-n,2))),i=u,n=l;}var h=t.length-3;t[2]=1,function e(t,r,o,i){for(var n,a=i,s=o-r>>1,u=o-r,l=t[r],h=t[r+1],c=t[o],p=t[o+1],f=r+3;fa)n=f,a=d;else if(d===a){var g=Math.abs(f-s);gi&&(n-r>3&&e(t,r,n,i),t[n+2]=a,o-n>3&&e(t,n,o,i));}(t,0,h,r),t[h+2]=1,t.size=Math.abs(a),t.start=0,t.end=t.size;}function ce(e,t,r,o){for(var i=0;i1?1:r}function de(e,t,r,o,i,n,a,s){if(o/=t,n>=(r/=t)&&a=o)return null;for(var u=[],l=0;l=r&&d=o)){var g=[];if("Point"===p||"MultiPoint"===p)ge(c,g,r,o,i);else if("LineString"===p)me(c,g,r,o,i,!1,s.lineMetrics);else if("MultiLineString"===p)ye(c,g,r,o,i,!1);else if("Polygon"===p)ye(c,g,r,o,i,!0);else if("MultiPolygon"===p)for(var m=0;m=r&&a<=o&&(t.push(e[n]),t.push(e[n+1]),t.push(e[n+2]));}}function me(e,t,r,o,i,n,a){for(var s,u,l=ve(e),h=0===i?we:Se,c=e.start,p=0;pr&&(u=h(l,f,d,m,v,r),a&&(l.start=c+s*u)):y>o?x=r&&(u=h(l,f,d,m,v,r),w=!0),x>o&&y<=o&&(u=h(l,f,d,m,v,o),w=!0),!n&&w&&(a&&(l.end=c+s*u),t.push(l),l=ve(e)),a&&(c+=s);}var S=e.length-3;f=e[S],d=e[S+1],g=e[S+2],(y=0===i?f:d)>=r&&y<=o&&xe(l,f,d,g),S=l.length-3,n&&S>=3&&(l[S]!==l[0]||l[S+1]!==l[1])&&xe(l,l[0],l[1],l[2]),l.length&&t.push(l);}function ve(e){var t=[];return t.size=e.size,t.start=e.start,t.end=e.end,t}function ye(e,t,r,o,i,n){for(var a=0;aa.maxX&&(a.maxX=h),c>a.maxY&&(a.maxY=c);}return a}function Ie(e,t,r,o){var i=t.geometry,n=t.type,a=[];if("Point"===n||"MultiPoint"===n)for(var s=0;s0&&t.size<(i?a:o))r.numPoints+=t.length/3;else{for(var s=[],u=0;ua)&&(r.numSimplified++,s.push(t[u]),s.push(t[u+1])),r.numPoints++;i&&function(e,t){for(var r=0,o=0,i=e.length,n=i-2;o0===t)for(o=0,i=e.length;o24)throw new Error("maxZoom should be in the 0-24 range");if(t.promoteId&&t.generateId)throw new Error("promoteId and generateId cannot be used together.");var o=function(e,t){var r=[];if("FeatureCollection"===e.type)for(var o=0;o=o;l--){var h=+Date.now();s=this._cluster(s,l),this.trees[l]=new R(s,oe,ie,n,Float32Array),r&&console.log("z%d: %d clusters in %dms",l,s.length,+Date.now()-h);}return r&&console.timeEnd("total time"),this},U.prototype.getClusters=function(e,t){var r=((e[0]+180)%360+360)%360-180,o=Math.max(-90,Math.min(90,e[1])),i=180===e[2]?180:((e[2]+180)%360+360)%360-180,n=Math.max(-90,Math.min(90,e[3]));if(e[2]-e[0]>=360)r=-180,i=180;else if(r>i){var a=this.getClusters([r,o,180,n],t),s=this.getClusters([-180,o,i,n],t);return a.concat(s)}for(var u=this.trees[this._limitZoom(t)],l=[],h=0,c=u.range(ee(r),te(n),ee(i),te(o));h>5,r=e%32,o="No cluster with the specified id.",i=this.trees[r];if(!i)throw new Error(o);var n=i.points[t];if(!n)throw new Error(o);for(var a=this.options.radius/(this.options.extent*Math.pow(2,r-1)),s=[],u=0,l=i.within(n.x,n.y,a);u1&&console.time("creation"),p=this.tiles[c]=Pe(e,t,r,o,u),this.tileCoords.push({z:t,x:r,y:o}),l)){l>1&&(console.log("tile z%d-%d-%d (features: %d, points: %d, simplified: %d)",t,r,o,p.numFeatures,p.numPoints,p.numSimplified),console.timeEnd("creation"));var f="z"+t;this.stats[f]=(this.stats[f]||0)+1,this.total++;}if(p.source=e,i){if(t===u.maxZoom||t===i)continue;var d=1<1&&console.time("clipping");var g,m,v,y,x,w,S=.5*u.buffer/u.extent,M=.5-S,k=.5+S,b=1+S;g=m=v=y=null,x=de(e,h,r-S,r+k,0,p.minX,p.maxX,u),w=de(e,h,r+M,r+b,0,p.minX,p.maxX,u),e=null,x&&(g=de(x,h,o-S,o+k,1,p.minY,p.maxY,u),m=de(x,h,o+M,o+b,1,p.minY,p.maxY,u),x=null),w&&(v=de(w,h,o-S,o+k,1,p.minY,p.maxY,u),y=de(w,h,o+M,o+b,1,p.minY,p.maxY,u),w=null),l>1&&console.timeEnd("clipping"),s.push(g||[],t+1,2*r,2*o),s.push(m||[],t+1,2*r,2*o+1),s.push(v||[],t+1,2*r+1,2*o),s.push(y||[],t+1,2*r+1,2*o+1);}}},Le.prototype.getTile=function(e,t,r){var o=this.options,i=o.extent,n=o.debug;if(e<0||e>24)return null;var a=1<1&&console.log("drilling down to z%d-%d-%d",e,t,r);for(var u,l=e,h=t,c=r;!u&&l>0;)l--,h=Math.floor(h/2),c=Math.floor(c/2),u=this.tiles[De(l,h,c)];return u&&u.source?(n>1&&console.log("found parent tile z%d-%d-%d",l,h,c),n>1&&console.time("drilling down"),this.splitTile(u.source,l,h,c,e,t,r),n>1&&console.timeEnd("drilling down"),this.tiles[s]?be(this.tiles[s],i):null):null};var ze=function(t){function r(e,r,o){t.call(this,e,r,Ce),o&&(this.loadGeoJSON=o);}return t&&(r.__proto__=t),r.prototype=Object.create(t&&t.prototype),r.prototype.constructor=r,r.prototype.loadData=function(e,t){this._pendingCallback&&this._pendingCallback(null,{abandoned:!0}),this._pendingCallback=t,this._pendingLoadDataParams=e,this._state&&"Idle"!==this._state?this._state="NeedsLoadData":(this._state="Coalescing",this._loadData());},r.prototype._loadData=function(){var t=this;if(this._pendingCallback&&this._pendingLoadDataParams){var r=this._pendingCallback,o=this._pendingLoadDataParams;delete this._pendingCallback,delete this._pendingLoadDataParams;var i=!!(o&&o.request&&o.request.collectResourceTiming)&&new u.Performance(o.request);this.loadGeoJSON(o,function(n,a){if(n||!a)return r(n);if("object"!=typeof a)return r(new Error("Input data given to '"+o.source+"' is not a valid GeoJSON object."));y(a,!0);try{t._geoJSONIndex=o.cluster?new U(function(t){var r=t.superclusterOptions,o=t.clusterProperties;if(!o||!r)return r;for(var i={},n={},a={accumulated:null,zoom:0},s={properties:null},u=Object.keys(o),l=0,h=u;l=0?0:e.button},i.remove=function(t){t.parentNode&&t.parentNode.removeChild(t);};var p=function(e){function i(){e.call(this),this.images={},this.updatedImages={},this.callbackDispatchedThisFrame={},this.loaded=!1,this.requestors=[],this.patterns={},this.atlasImage=new t.RGBAImage({width:1,height:1}),this.dirty=!0;}return e&&(i.__proto__=e),i.prototype=Object.create(e&&e.prototype),i.prototype.constructor=i,i.prototype.isLoaded=function(){return this.loaded},i.prototype.setLoaded=function(t){if(this.loaded!==t&&(this.loaded=t,t)){for(var e=0,i=this.requestors;e=0?1.2:1));}function m(t,e,i,o,r,a,n){for(var s=0;s65535)e(new Error("glyphs > 65535 not supported"));else{var l=a.requests[s];l||(l=a.requests[s]=[],v.loadGlyphRange(i,s,o.url,o.requestManager,function(t,e){if(e)for(var i in e)a.glyphs[+i]=e[+i];for(var o=0,r=l;othis.height)return t.warnOnce("LineAtlas out of space"),null;for(var a=0,n=0;n=o&&e.x=r&&e.y0&&(l[new t.OverscaledTileID(e.overscaledZ,a,i.z,r,i.y-1).key]={backfilled:!1},l[new t.OverscaledTileID(e.overscaledZ,e.wrap,i.z,i.x,i.y-1).key]={backfilled:!1},l[new t.OverscaledTileID(e.overscaledZ,s,i.z,n,i.y-1).key]={backfilled:!1}),i.y+10&&(o.resourceTiming=e._resourceTiming,e._resourceTiming=[]),e.fire(new t.Event("data",o));}});},i.prototype.onAdd=function(t){this.map=t,this.load();},i.prototype.setData=function(e){var i=this;return this._data=e,this.fire(new t.Event("dataloading",{dataType:"source"})),this._updateWorkerData(function(e){if(e)i.fire(new t.ErrorEvent(e));else{var o={dataType:"source",sourceDataType:"content"};i._collectResourceTiming&&i._resourceTiming&&i._resourceTiming.length>0&&(o.resourceTiming=i._resourceTiming,i._resourceTiming=[]),i.fire(new t.Event("data",o));}}),this},i.prototype.getClusterExpansionZoom=function(t,e){return this.dispatcher.send("geojson.getClusterExpansionZoom",{clusterId:t,source:this.id},e,this.workerID),this},i.prototype.getClusterChildren=function(t,e){return this.dispatcher.send("geojson.getClusterChildren",{clusterId:t,source:this.id},e,this.workerID),this},i.prototype.getClusterLeaves=function(t,e,i,o){return this.dispatcher.send("geojson.getClusterLeaves",{source:this.id,clusterId:t,limit:e,offset:i},o,this.workerID),this},i.prototype._updateWorkerData=function(e){var i=this,o=t.extend({},this.workerOptions),r=this._data;"string"==typeof r?(o.request=this.map._requestManager.transformRequest(t.browser.resolveURL(r),t.ResourceType.Source),o.request.collectResourceTiming=this._collectResourceTiming):o.data=JSON.stringify(r),this.workerID=this.dispatcher.send(this.type+".loadData",o,function(t,r){i._removed||r&&r.abandoned||(i._loaded=!0,r&&r.resourceTiming&&r.resourceTiming[i.id]&&(i._resourceTiming=r.resourceTiming[i.id].slice(0)),i.dispatcher.send(i.type+".coalesce",{source:o.source},null,i.workerID),e(t));},this.workerID);},i.prototype.loadTile=function(e,i){var o=this,r=void 0===e.workerID?"loadTile":"reloadTile",a={type:this.type,uid:e.uid,tileID:e.tileID,zoom:e.tileID.overscaledZ,maxZoom:this.maxzoom,tileSize:this.tileSize,source:this.id,pixelRatio:t.browser.devicePixelRatio,showCollisionBoxes:this.map.showCollisionBoxes};e.workerID=this.dispatcher.send(r,a,function(t,a){return e.unloadVectorData(),e.aborted?i(null):t?i(t):(e.loadVectorData(a,o.map.painter,"reloadTile"===r),i(null))},this.workerID);},i.prototype.abortTile=function(t){t.aborted=!0;},i.prototype.unloadTile=function(t){t.unloadVectorData(),this.dispatcher.send("removeTile",{uid:t.uid,type:this.type,source:this.id},null,t.workerID);},i.prototype.onRemove=function(){this._removed=!0,this.dispatcher.send("removeSource",{type:this.type,source:this.id},null,this.workerID);},i.prototype.serialize=function(){return t.extend({},this._options,{type:this.type,data:this._data})},i.prototype.hasTransition=function(){return !1},i}(t.Evented),L=function(e){function i(t,i,o,r){e.call(this),this.id=t,this.dispatcher=o,this.coordinates=i.coordinates,this.type="image",this.minzoom=0,this.maxzoom=22,this.tileSize=512,this.tiles={},this.setEventedParent(r),this.options=i;}return e&&(i.__proto__=e),i.prototype=Object.create(e&&e.prototype),i.prototype.constructor=i,i.prototype.load=function(e,i){var o=this;this.fire(new t.Event("dataloading",{dataType:"source"})),this.url=this.options.url,t.getImage(this.map._requestManager.transformRequest(this.url,t.ResourceType.Image),function(r,a){r?o.fire(new t.ErrorEvent(r)):a&&(o.image=a,e&&(o.coordinates=e),i&&i(),o._finishLoading());});},i.prototype.updateImage=function(t){var e=this;return this.image&&t.url?(this.options.url=t.url,this.load(t.coordinates,function(){e.texture=null;}),this):this},i.prototype._finishLoading=function(){this.map&&(this.setCoordinates(this.coordinates),this.fire(new t.Event("data",{dataType:"source",sourceDataType:"metadata"})));},i.prototype.onAdd=function(t){this.map=t,this.load();},i.prototype.setCoordinates=function(e){var i=this;this.coordinates=e;var o=e.map(t.MercatorCoordinate.fromLngLat);this.tileID=function(e){for(var i=1/0,o=1/0,r=-1/0,a=-1/0,n=0,s=e;nthis.max){var n=this._getAndRemoveByKey(this.order[0]);n&&this.onRemove(n);}return this},F.prototype.has=function(t){return t.wrapped().key in this.data},F.prototype.getAndRemove=function(t){return this.has(t)?this._getAndRemoveByKey(t.wrapped().key):null},F.prototype._getAndRemoveByKey=function(t){var e=this.data[t].shift();return e.timeout&&clearTimeout(e.timeout),0===this.data[t].length&&delete this.data[t],this.order.splice(this.order.indexOf(t),1),e.value},F.prototype.get=function(t){return this.has(t)?this.data[t.wrapped().key][0].value:null},F.prototype.remove=function(t,e){if(!this.has(t))return this;var i=t.wrapped().key,o=void 0===e?0:this.data[i].indexOf(e),r=this.data[i][o];return this.data[i].splice(o,1),r.timeout&&clearTimeout(r.timeout),0===this.data[i].length&&delete this.data[i],this.onRemove(r.value),this.order.splice(this.order.indexOf(i),1),this},F.prototype.setMaxSize=function(t){for(this.max=t;this.order.length>this.max;){var e=this._getAndRemoveByKey(this.order[0]);e&&this.onRemove(e);}return this};var U=function(t,e,i){this.context=t;var o=t.gl;this.buffer=o.createBuffer(),this.dynamicDraw=Boolean(i),this.context.unbindVAO(),t.bindElementBuffer.set(this.buffer),o.bufferData(o.ELEMENT_ARRAY_BUFFER,e.arrayBuffer,this.dynamicDraw?o.DYNAMIC_DRAW:o.STATIC_DRAW),this.dynamicDraw||delete e.arrayBuffer;};U.prototype.bind=function(){this.context.bindElementBuffer.set(this.buffer);},U.prototype.updateData=function(t){var e=this.context.gl;this.context.unbindVAO(),this.bind(),e.bufferSubData(e.ELEMENT_ARRAY_BUFFER,0,t.arrayBuffer);},U.prototype.destroy=function(){var t=this.context.gl;this.buffer&&(t.deleteBuffer(this.buffer),delete this.buffer);};var N={Int8:"BYTE",Uint8:"UNSIGNED_BYTE",Int16:"SHORT",Uint16:"UNSIGNED_SHORT",Int32:"INT",Uint32:"UNSIGNED_INT",Float32:"FLOAT"},Z=function(t,e,i,o){this.length=e.length,this.attributes=i,this.itemSize=e.bytesPerElement,this.dynamicDraw=o,this.context=t;var r=t.gl;this.buffer=r.createBuffer(),t.bindVertexBuffer.set(this.buffer),r.bufferData(r.ARRAY_BUFFER,e.arrayBuffer,this.dynamicDraw?r.DYNAMIC_DRAW:r.STATIC_DRAW),this.dynamicDraw||delete e.arrayBuffer;};Z.prototype.bind=function(){this.context.bindVertexBuffer.set(this.buffer);},Z.prototype.updateData=function(t){var e=this.context.gl;this.bind(),e.bufferSubData(e.ARRAY_BUFFER,0,t.arrayBuffer);},Z.prototype.enableAttributes=function(t,e){for(var i=0;i1||(Math.abs(i)>1&&(1===Math.abs(i+r)?i+=r:1===Math.abs(i-r)&&(i-=r)),e.dem&&t.dem&&(t.dem.backfillBorder(e.dem,i,o),t.neighboringTiles&&t.neighboringTiles[a]&&(t.neighboringTiles[a].backfilled=!0)));}},i.prototype.getTile=function(t){return this.getTileByID(t.key)},i.prototype.getTileByID=function(t){return this._tiles[t]},i.prototype.getZoom=function(t){return t.zoom+t.scaleZoom(t.tileSize/this._source.tileSize)},i.prototype._retainLoadedChildren=function(t,e,i,o){for(var r in this._tiles){var a=this._tiles[r];if(!(o[r]||!a.hasData()||a.tileID.overscaledZ<=e||a.tileID.overscaledZ>i)){for(var n=a.tileID;a&&a.tileID.overscaledZ>e+1;){var s=a.tileID.scaledTo(a.tileID.overscaledZ-1);(a=this._tiles[s.key])&&a.hasData()&&(n=s);}for(var l=n;l.overscaledZ>e;)if(t[(l=l.scaledTo(l.overscaledZ-1)).key]){o[n.key]=n;break}}}},i.prototype.findLoadedParent=function(t,e){for(var i=t.overscaledZ-1;i>=e;i--){var o=t.scaledTo(i);if(!o)return;var r=String(o.key),a=this._tiles[r];if(a&&a.hasData())return a;if(this._cache.has(o))return this._cache.get(o)}},i.prototype.updateCacheSize=function(t){var e=(Math.ceil(t.width/this._source.tileSize)+1)*(Math.ceil(t.height/this._source.tileSize)+1),i=Math.floor(5*e),o="number"==typeof this._maxTileCacheSize?Math.min(this._maxTileCacheSize,i):i;this._cache.setMaxSize(o);},i.prototype.handleWrapJump=function(t){var e=(t-(void 0===this._prevLng?t:this._prevLng))/360,i=Math.round(e);if(this._prevLng=t,i){var o={};for(var r in this._tiles){var a=this._tiles[r];a.tileID=a.tileID.unwrapTo(a.tileID.wrap+i),o[a.tileID.key]=a;}for(var n in this._tiles=o,this._timers)clearTimeout(this._timers[n]),delete this._timers[n];for(var s in this._tiles){var l=this._tiles[s];this._setTileReloadTimer(s,l);}}},i.prototype.update=function(e){var o=this;if(this.transform=e,this._sourceLoaded&&!this._paused){var r;this.updateCacheSize(e),this.handleWrapJump(this.transform.center.lng),this._coveredTiles={},this.used?this._source.tileID?r=e.getVisibleUnwrappedCoordinates(this._source.tileID).map(function(e){return new t.OverscaledTileID(e.canonical.z,e.wrap,e.canonical.z,e.canonical.x,e.canonical.y)}):(r=e.coveringTiles({tileSize:this._source.tileSize,minzoom:this._source.minzoom,maxzoom:this._source.maxzoom,roundZoom:this._source.roundZoom,reparseOverscaled:this._source.reparseOverscaled}),this._source.hasTile&&(r=r.filter(function(t){return o._source.hasTile(t)}))):r=[];var a=(this._source.roundZoom?Math.round:Math.floor)(this.getZoom(e)),n=Math.max(a-i.maxOverzooming,this._source.minzoom),s=Math.max(a+i.maxUnderzooming,this._source.minzoom),l=this._updateRetainedTiles(r,a);if(Dt(this._source.type)){for(var c={},u={},h=0,p=Object.keys(l);hthis._source.maxzoom){var m=_.children(this._source.maxzoom)[0],g=this.getTile(m);if(g&&g.hasData()){o[m.key]=m;continue}}else{var v=_.children(this._source.maxzoom);if(o[v[0].key]&&o[v[1].key]&&o[v[2].key]&&o[v[3].key])continue}for(var y=f.wasRequested(),x=_.overscaledZ-1;x>=a;--x){var b=_.scaledTo(x);if(r[b.key])break;if(r[b.key]=!0,!(f=this.getTile(b))&&y&&(f=this._addTile(b)),f&&(o[b.key]=b,y=f.wasRequested(),f.hasData()))break}}}return o},i.prototype._addTile=function(e){var i=this._tiles[e.key];if(i)return i;(i=this._cache.getAndRemove(e))&&(this._setTileReloadTimer(e.key,i),i.tileID=e,this._state.initializeTileState(i,this.map?this.map.painter:null),this._cacheTimers[e.key]&&(clearTimeout(this._cacheTimers[e.key]),delete this._cacheTimers[e.key],this._setTileReloadTimer(e.key,i)));var o=Boolean(i);return o||(i=new t.Tile(e,this._source.tileSize*e.overscaleFactor()),this._loadTile(i,this._tileLoaded.bind(this,i,e.key,i.state))),i?(i.uses++,this._tiles[e.key]=i,o||this._source.fire(new t.Event("dataloading",{tile:i,coord:i.tileID,dataType:"source"})),i):null},i.prototype._setTileReloadTimer=function(t,e){var i=this;t in this._timers&&(clearTimeout(this._timers[t]),delete this._timers[t]);var o=e.getExpiryTimeout();o&&(this._timers[t]=setTimeout(function(){i._reloadTile(t,"expired"),delete i._timers[t];},o));},i.prototype._removeTile=function(t){var e=this._tiles[t];e&&(e.uses--,delete this._tiles[t],this._timers[t]&&(clearTimeout(this._timers[t]),delete this._timers[t]),e.uses>0||(e.hasData()?this._cache.add(e.tileID,e,e.getExpiryTimeout()):(e.aborted=!0,this._abortTile(e),this._unloadTile(e))));},i.prototype.clearTiles=function(){for(var t in this._shouldReloadOnResume=!1,this._paused=!1,this._tiles)this._removeTile(t);this._cache.reset();},i.prototype.tilesIn=function(e,i,o){var r=this,a=[],n=this.transform;if(!n)return a;for(var s=o?n.getCameraQueryGeometry(e):e,l=e.map(function(t){return n.pointCoordinate(t)}),c=s.map(function(t){return n.pointCoordinate(t)}),u=this.getIds(),h=1/0,p=1/0,d=-1/0,_=-1/0,f=0,m=c;f=0&&g[1].y+m>=0){var v=l.map(function(t){return s.getTilePoint(t)}),y=c.map(function(t){return s.getTilePoint(t)});a.push({tile:o,tileID:s,queryGeometry:v,cameraQueryGeometry:y,scale:f});}}},y=0;y=t.browser.now())return !0}return !1},i.prototype.setFeatureState=function(t,e,i){t=t||"_geojsonTileLayer",this._state.updateState(t,e,i);},i.prototype.removeFeatureState=function(t,e,i){t=t||"_geojsonTileLayer",this._state.removeFeatureState(t,e,i);},i.prototype.getFeatureState=function(t,e){return t=t||"_geojsonTileLayer",this._state.getState(t,e)},i}(t.Evented);function Lt(t,e){return t%32-e%32||e-t}function Dt(t){return "raster"===t||"image"===t||"video"===t}function Mt(){return new t.window.Worker($o.workerUrl)}zt.maxOverzooming=10,zt.maxUnderzooming=3;var Rt=function(){this.active={};};Rt.prototype.acquire=function(t){if(!this.workers)for(this.workers=[];this.workers.length=-e[0]&&i<=e[0]&&o>=-e[1]&&o<=e[1]}function Qt(e,i,o,r,a,n,s,l){var c=r?e.textSizeData:e.iconSizeData,u=t.evaluateSizeForZoom(c,o.transform.zoom),h=[256/o.width*2+1,256/o.height*2+1],p=r?e.text.dynamicLayoutVertexArray:e.icon.dynamicLayoutVertexArray;p.clear();for(var d=e.lineVertexArray,_=r?e.text.placedSymbolArray:e.icon.placedSymbolArray,f=o.transform.width/o.transform.height,m=!1,g=0;g<_.length;g++){var v=_.get(g);if(v.hidden||v.writingMode===t.WritingMode.vertical&&!m)ae(v.numGlyphs,p);else{m=!1;var y=[v.anchorX,v.anchorY,0,1];if(t.transformMat4(y,y,i),Jt(y,h)){var x=.5+y[3]/o.transform.cameraToCenterDistance*.5,b=t.evaluateSizeForFeature(c,u,v),w=s?b*x:b/x,E=new t.Point(v.anchorX,v.anchorY),T=Yt(E,a).point,I={},C=ee(v,w,!1,l,i,a,n,e.glyphOffsetArray,d,p,T,E,I,f);m=C.useVertical,(C.notEnoughRoom||m||C.needsFlipping&&ee(v,w,!0,l,i,a,n,e.glyphOffsetArray,d,p,T,E,I,f).notEnoughRoom)&&ae(v.numGlyphs,p);}else ae(v.numGlyphs,p);}}r?e.text.dynamicLayoutVertexBuffer.updateData(p):e.icon.dynamicLayoutVertexBuffer.updateData(p);}function $t(t,e,i,o,r,a,n,s,l,c,u,h){var p=s.glyphStartIndex+s.numGlyphs,d=s.lineStartIndex,_=s.lineStartIndex+s.lineLength,f=e.getoffsetX(s.glyphStartIndex),m=e.getoffsetX(p-1),g=oe(t*f,i,o,r,a,n,s.segment,d,_,l,c,u,h);if(!g)return null;var v=oe(t*m,i,o,r,a,n,s.segment,d,_,l,c,u,h);return v?{first:g,last:v}:null}function te(e,i,o,r){if(e===t.WritingMode.horizontal&&Math.abs(o.y-i.y)>Math.abs(o.x-i.x)*r)return {useVertical:!0};return (e===t.WritingMode.vertical?i.yo.x)?{needsFlipping:!0}:null}function ee(e,i,o,r,a,n,s,l,c,u,h,p,d,_){var f,m=i/24,g=e.lineOffsetX*m,v=e.lineOffsetY*m;if(e.numGlyphs>1){var y=e.glyphStartIndex+e.numGlyphs,x=e.lineStartIndex,b=e.lineStartIndex+e.lineLength,w=$t(m,l,g,v,o,h,p,e,c,n,d,!1);if(!w)return {notEnoughRoom:!0};var E=Yt(w.first.point,s).point,T=Yt(w.last.point,s).point;if(r&&!o){var I=te(e.writingMode,E,T,_);if(I)return I}f=[w.first];for(var C=e.glyphStartIndex+1;C0?L.point:ie(p,z,S,1,a),M=te(e.writingMode,S,D,_);if(M)return M}var R=oe(m*l.getoffsetX(e.glyphStartIndex),g,v,o,h,p,e.segment,e.lineStartIndex,e.lineStartIndex+e.lineLength,c,n,d,!1);if(!R)return {notEnoughRoom:!0};f=[R];}for(var A=0,k=f;A0?1:-1,m=0;r&&(f*=-1,m=Math.PI),f<0&&(m+=Math.PI);for(var g=f>0?l+s:l+s+1,v=g,y=a,x=a,b=0,w=0,E=Math.abs(_);b+w<=E;){if((g+=f)=c)return null;if(x=y,void 0===(y=p[g])){var T=new t.Point(u.getx(g),u.gety(g)),I=Yt(T,h);if(I.signedDistanceFromCamera>0)y=p[g]=I.point;else{var C=g-f;y=ie(0===b?n:new t.Point(u.getx(C),u.gety(C)),T,x,E-b+1,h);}}b+=w,w=x.dist(y);}var S=(E-b)/w,P=y.sub(x),z=P.mult(S)._add(x);return z._add(P._unit()._perp()._mult(o*f)),{point:z,angle:m+Math.atan2(y.y-x.y,y.x-x.x),tileDistance:d?{prevTileDistance:g-f===v?0:u.gettileUnitDistanceFromAnchor(g-f),lastSegmentViewportDistance:E-b}:null}}Xt.prototype.keysLength=function(){return this.boxKeys.length+this.circleKeys.length},Xt.prototype.insert=function(t,e,i,o,r){this._forEachCell(e,i,o,r,this._insertBoxCell,this.boxUid++),this.boxKeys.push(t),this.bboxes.push(e),this.bboxes.push(i),this.bboxes.push(o),this.bboxes.push(r);},Xt.prototype.insertCircle=function(t,e,i,o){this._forEachCell(e-o,i-o,e+o,i+o,this._insertCircleCell,this.circleUid++),this.circleKeys.push(t),this.circles.push(e),this.circles.push(i),this.circles.push(o);},Xt.prototype._insertBoxCell=function(t,e,i,o,r,a){this.boxCells[r].push(a);},Xt.prototype._insertCircleCell=function(t,e,i,o,r,a){this.circleCells[r].push(a);},Xt.prototype._query=function(t,e,i,o,r,a){if(i<0||t>this.width||o<0||e>this.height)return !r&&[];var n=[];if(t<=0&&e<=0&&this.width<=i&&this.height<=o){if(r)return !0;for(var s=0;s0:n},Xt.prototype._queryCircle=function(t,e,i,o,r){var a=t-i,n=t+i,s=e-i,l=e+i;if(n<0||a>this.width||l<0||s>this.height)return !o&&[];var c=[],u={hitTest:o,circle:{x:t,y:e,radius:i},seenUids:{box:{},circle:{}}};return this._forEachCell(a,s,n,l,this._queryCellCircle,c,u,r),o?c.length>0:c},Xt.prototype.query=function(t,e,i,o,r){return this._query(t,e,i,o,!1,r)},Xt.prototype.hitTest=function(t,e,i,o,r){return this._query(t,e,i,o,!0,r)},Xt.prototype.hitTestCircle=function(t,e,i,o){return this._queryCircle(t,e,i,!0,o)},Xt.prototype._queryCell=function(t,e,i,o,r,a,n,s){var l=n.seenUids,c=this.boxCells[r];if(null!==c)for(var u=this.bboxes,h=0,p=c;h=u[_+0]&&o>=u[_+1]&&(!s||s(this.boxKeys[d]))){if(n.hitTest)return a.push(!0),!0;a.push({key:this.boxKeys[d],x1:u[_],y1:u[_+1],x2:u[_+2],y2:u[_+3]});}}}var f=this.circleCells[r];if(null!==f)for(var m=this.circles,g=0,v=f;gn*n+s*s},Xt.prototype._circleAndRectCollide=function(t,e,i,o,r,a,n){var s=(a-o)/2,l=Math.abs(t-(o+s));if(l>s+i)return !1;var c=(n-r)/2,u=Math.abs(e-(r+c));if(u>c+i)return !1;if(l<=s||u<=c)return !0;var h=l-s,p=u-c;return h*h+p*p<=i*i};var re=new Float32Array([-1/0,-1/0,0,-1/0,-1/0,0,-1/0,-1/0,0,-1/0,-1/0,0]);function ae(t,e){for(var i=0;iS)le(e,P,!1);else{var R=this.projectPoint(c,z,L),A=D*T;if(_.length>0){var k=R.x-_[_.length-4],B=R.y-_[_.length-3];if(A*A*2>k*k+B*B)if(P+8-C&&O=this.screenRightBoundary||o<100||e>this.screenBottomBoundary},se.prototype.isInsideGrid=function(t,e,i,o){return i>=0&&t=0&&e0)return this.prevPlacement&&this.prevPlacement.variableOffsets[d.crossTileID]&&this.prevPlacement.placements[d.crossTileID]&&this.prevPlacement.placements[d.crossTileID].text&&(f=this.prevPlacement.variableOffsets[d.crossTileID].anchor),this.variableOffsets[d.crossTileID]={radialOffset:a,width:o,height:r,anchor:e,textBoxScale:n,prevAnchor:f},this.markUsedJustification(_,e,d),g},me.prototype.placeLayerBucket=function(e,i,o,r,a,n,s,l,c,u){var h=this,p=e.layers[0].layout,d=t.evaluateSizeForZoom(e.textSizeData,this.transform.zoom),_=p.get("text-optional"),f=p.get("icon-optional"),m=p.get("text-allow-overlap"),g=p.get("icon-allow-overlap"),v=m&&(g||!e.hasIconData()||f),y=g&&(m||!e.hasTextData()||_),x=this.collisionGroups.get(e.sourceID),b="map"===p.get("text-rotation-alignment"),w="map"===p.get("text-pitch-alignment"),E="viewport-y"===p.get("symbol-z-order");!e.collisionArrays&&u&&e.deserializeCollisionBoxes(u);var T=function(r,u){if(!c[r.crossTileID])if(l)h.placements[r.crossTileID]=new pe(!1,!1,!1);else{var g=!1,E=!1,T=!0,I=null,C=null,S=null,P=0,z=0;u.textFeatureIndex&&(P=u.textFeatureIndex);var L=u.textBox;if(L)if(p.get("text-variable-anchor")){var D=L.x2-L.x1,M=L.y2-L.y1,R=r.textBoxScale,A=p.get("text-variable-anchor");if(h.prevPlacement&&h.prevPlacement.variableOffsets[r.crossTileID]){var k=h.prevPlacement.variableOffsets[r.crossTileID];A[0]!==k.anchor&&(A=A.filter(function(t){return t!==k.anchor})).unshift(k.anchor);}for(var B=0,O=A;B0;T=I&&I.offscreen;var N=u.textCircles;if(N){var Z=e.text.placedSymbolArray.get(r.centerJustifiedTextSymbolIndex),j=t.evaluateSizeForFeature(e.textSizeData,d,Z);C=h.collisionIndex.placeCollisionCircles(N,p.get("text-allow-overlap"),a,n,Z,e.lineVertexArray,e.glyphOffsetArray,j,i,o,s,w,x.predicate),g=p.get("text-allow-overlap")||C.circles.length>0,T=T&&C.offscreen;}u.iconFeatureIndex&&(z=u.iconFeatureIndex),u.iconBox&&(E=(S=h.collisionIndex.placeCollisionBox(u.iconBox,p.get("icon-allow-overlap"),n,i,x.predicate)).box.length>0,T=T&&S.offscreen);var q=_||0===r.numHorizontalGlyphVertices&&0===r.numVerticalGlyphVertices,V=f||0===r.numIconVertices;q||V?V?q||(E=E&&g):g=E&&g:E=g=E&&g,g&&I&&h.collisionIndex.insertCollisionBox(I.box,p.get("text-ignore-placement"),e.bucketInstanceId,P,x.ID),E&&S&&h.collisionIndex.insertCollisionBox(S.box,p.get("icon-ignore-placement"),e.bucketInstanceId,z,x.ID),g&&C&&h.collisionIndex.insertCollisionCircles(C.circles,p.get("text-ignore-placement"),e.bucketInstanceId,P,x.ID),h.placements[r.crossTileID]=new pe(g||v,E||y,T||e.justReloaded),c[r.crossTileID]=!0;}};if(E)for(var I=e.getSortedSymbolIndexes(this.transform.angle),C=I.length-1;C>=0;--C){var S=I[C];T(e.symbolInstances.get(S),e.collisionArrays[S]);}else for(var P=0;P=0&&(e.text.placedSymbolArray.get(s).crossTileID=a>=0&&s!==a?0:o.crossTileID);}},me.prototype.commit=function(t){this.commitTime=t;var e=this.prevPlacement,i=!1,o=e&&0!==this.fadeDuration?(this.commitTime-e.commitTime)/this.fadeDuration:1,r=e?e.opacities:{},a=e?e.variableOffsets:{};for(var n in this.placements){var s=this.placements[n],l=r[n];l?(this.opacities[n]=new he(l,o,s.text,s.icon),i=i||s.text!==l.text.placed||s.icon!==l.icon.placed):(this.opacities[n]=new he(null,o,s.text,s.icon,s.skipFade),i=i||s.text||s.icon);}for(var c in r){var u=r[c];if(!this.opacities[c]){var h=new he(u,o,!1,!1);h.isHidden()||(this.opacities[c]=h,i=i||u.text.placed||u.icon.placed);}}for(var p in a)this.variableOffsets[p]||!this.opacities[p]||this.opacities[p].isHidden()||(this.variableOffsets[p]=a[p]);i?this.lastPlacementChangeTime=t:"number"!=typeof this.lastPlacementChangeTime&&(this.lastPlacementChangeTime=e?e.lastPlacementChangeTime:t);},me.prototype.updateLayerOpacities=function(t,e){for(var i={},o=0,r=e;o0||f>0,x=d.numIconVertices>0;if(y){for(var b=Ie(v.text),w=(_+f)/4,E=0;E=0&&(e.text.placedSymbolArray.get(t).hidden=T);});var I=this.variableOffsets[d.crossTileID];I&&this.markUsedJustification(e,I.anchor,d);}if(x){for(var C=Ie(v.icon),S=0;St},me.prototype.setStale=function(){this.stale=!0;};var ve=Math.pow(2,25),ye=Math.pow(2,24),xe=Math.pow(2,17),be=Math.pow(2,16),we=Math.pow(2,9),Ee=Math.pow(2,8),Te=Math.pow(2,1);function Ie(t){if(0===t.opacity&&!t.placed)return 0;if(1===t.opacity&&t.placed)return 4294967295;var e=t.placed?1:0,i=Math.floor(127*t.opacity);return i*ve+e*ye+i*xe+e*be+i*we+e*Ee+i*Te+e}var Ce=function(){this._currentTileIndex=0,this._seenCrossTileIDs={};};Ce.prototype.continuePlacement=function(t,e,i,o,r){for(;this._currentTileIndex2};this._currentPlacementIndex>=0;){var s=i[e[this._currentPlacementIndex]],l=this.placement.collisionIndex.transform.zoom;if("symbol"===s.type&&(!s.minzoom||s.minzoom<=l)&&(!s.maxzoom||s.maxzoom>l)){if(this._inProgressLayer||(this._inProgressLayer=new Ce),this._inProgressLayer.continuePlacement(o[s.source],this.placement,this._showCollisionBoxes,s,n))return;delete this._inProgressLayer;}this._currentPlacementIndex--;}this._done=!0;},Se.prototype.commit=function(t){return this.placement.commit(t),this.placement};var Pe=512/t.EXTENT/2,ze=function(t,e,i){this.tileID=t,this.indexedSymbolInstances={},this.bucketInstanceId=i;for(var o=0;ot.overscaledZ)for(var s in n){var l=n[s];l.tileID.isChildOf(t)&&l.findMatches(e.symbolInstances,t,r);}else{var c=n[t.scaledTo(Number(a)).key];c&&c.findMatches(e.symbolInstances,t,r);}}for(var u=0;u1?"@2x":"",l=t.getJSON(i.transformRequest(i.normalizeSpriteURL(e,s,".json"),t.ResourceType.SpriteJSON),function(t,e){l=null,n||(n=t,r=e,u());}),c=t.getImage(i.transformRequest(i.normalizeSpriteURL(e,s,".png"),t.ResourceType.SpriteImage),function(t,e){c=null,n||(n=t,a=e,u());});function u(){if(n)o(n);else if(r&&a){var e=t.browser.getImageData(a),i={};for(var s in r){var l=r[s],c=l.width,u=l.height,h=l.x,p=l.y,d=l.sdf,_=l.pixelRatio,f=new t.RGBAImage({width:c,height:u});t.RGBAImage.copy(e,f,{x:h,y:p},{x:0,y:0},{width:c,height:u}),i[s]={data:f,pixelRatio:_,sdf:d};}o(null,i);}}return {cancel:function(){l&&(l.cancel(),l=null),c&&(c.cancel(),c=null);}}}(e.sprite,this.map._requestManager,function(e,i){if(o._spriteRequest=null,e)o.fire(new t.ErrorEvent(e));else if(i)for(var r in i)o.imageManager.addImage(r,i[r]);o.imageManager.setLoaded(!0),o.fire(new t.Event("data",{dataType:"style"}));}):this.imageManager.setLoaded(!0),this.glyphManager.setURL(e.glyphs);var a=Ot(this.stylesheet.layers);this._order=a.map(function(t){return t.id}),this._layers={};for(var n=0,s=a;n0)throw new Error("Unimplemented: "+r.map(function(t){return t.command}).join(", ")+".");return o.forEach(function(t){"setTransition"!==t.command&&i[t.command].apply(i,t.args);}),this.stylesheet=e,!0},i.prototype.addImage=function(e,i){if(this.getImage(e))return this.fire(new t.ErrorEvent(new Error("An image with this name already exists.")));this.imageManager.addImage(e,i),this.fire(new t.Event("data",{dataType:"style"}));},i.prototype.updateImage=function(t,e){this.imageManager.updateImage(t,e);},i.prototype.getImage=function(t){return this.imageManager.getImage(t)},i.prototype.removeImage=function(e){if(!this.getImage(e))return this.fire(new t.ErrorEvent(new Error("No image with this name exists.")));this.imageManager.removeImage(e),this.fire(new t.Event("data",{dataType:"style"}));},i.prototype.listImages=function(){return this._checkLoaded(),this.imageManager.listImages()},i.prototype.addSource=function(e,i,o){var r=this;if(void 0===o&&(o={}),this._checkLoaded(),void 0!==this.sourceCaches[e])throw new Error("There is already a source with this ID");if(!i.type)throw new Error("The type property must be defined, but the only the following properties were given: "+Object.keys(i).join(", ")+".");if(!(["vector","raster","geojson","video","image"].indexOf(i.type)>=0)||!this._validate(t.validateStyle.source,"sources."+e,i,null,o)){this.map&&this.map._collectResourceTiming&&(i.collectResourceTiming=!0);var a=this.sourceCaches[e]=new zt(e,i,this.dispatcher);a.style=this,a.setEventedParent(this,function(){return {isSourceLoaded:r.loaded(),source:a.serialize(),sourceId:e}}),a.onAdd(this.map),this._changed=!0;}},i.prototype.removeSource=function(e){if(this._checkLoaded(),void 0===this.sourceCaches[e])throw new Error("There is no source with this ID");for(var i in this._layers)if(this._layers[i].source===e)return this.fire(new t.ErrorEvent(new Error('Source "'+e+'" cannot be removed while layer "'+i+'" is using it.')));var o=this.sourceCaches[e];delete this.sourceCaches[e],delete this._updatedSources[e],o.fire(new t.Event("data",{sourceDataType:"metadata",dataType:"source",sourceId:e})),o.setEventedParent(null),o.clearTiles(),o.onRemove&&o.onRemove(this.map),this._changed=!0;},i.prototype.setGeoJSONSourceData=function(t,e){this._checkLoaded(),this.sourceCaches[t].getSource().setData(e),this._changed=!0;},i.prototype.getSource=function(t){return this.sourceCaches[t]&&this.sourceCaches[t].getSource()},i.prototype.addLayer=function(e,i,o){void 0===o&&(o={}),this._checkLoaded();var r=e.id;if(this.getLayer(r))this.fire(new t.ErrorEvent(new Error('Layer with id "'+r+'" already exists on this map')));else{var a;if("custom"===e.type){if(Re(this,t.validateCustomStyleLayer(e)))return;a=t.createStyleLayer(e);}else{if("object"==typeof e.source&&(this.addSource(r,e.source),e=t.clone$1(e),e=t.extend(e,{source:r})),this._validate(t.validateStyle.layer,"layers."+r,e,{arrayIndex:-1},o))return;a=t.createStyleLayer(e),this._validateLayer(a),a.setEventedParent(this,{layer:{id:r}});}var n=i?this._order.indexOf(i):this._order.length;if(i&&-1===n)this.fire(new t.ErrorEvent(new Error('Layer with id "'+i+'" does not exist on this map.')));else{if(this._order.splice(n,0,r),this._layerOrderChanged=!0,this._layers[r]=a,this._removedLayers[r]&&a.source&&"custom"!==a.type){var s=this._removedLayers[r];delete this._removedLayers[r],s.type!==a.type?this._updatedSources[a.source]="clear":(this._updatedSources[a.source]="reload",this.sourceCaches[a.source].pause());}this._updateLayer(a),a.onAdd&&a.onAdd(this.map);}}},i.prototype.moveLayer=function(e,i){if(this._checkLoaded(),this._changed=!0,this._layers[e]){if(e!==i){var o=this._order.indexOf(e);this._order.splice(o,1);var r=i?this._order.indexOf(i):this._order.length;i&&-1===r?this.fire(new t.ErrorEvent(new Error('Layer with id "'+i+'" does not exist on this map.'))):(this._order.splice(r,0,e),this._layerOrderChanged=!0);}}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be moved.")));},i.prototype.removeLayer=function(e){this._checkLoaded();var i=this._layers[e];if(i){i.setEventedParent(null);var o=this._order.indexOf(e);this._order.splice(o,1),this._layerOrderChanged=!0,this._changed=!0,this._removedLayers[e]=i,delete this._layers[e],delete this._updatedLayers[e],delete this._updatedPaintProps[e],i.onRemove&&i.onRemove(this.map);}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be removed.")));},i.prototype.getLayer=function(t){return this._layers[t]},i.prototype.setLayerZoomRange=function(e,i,o){this._checkLoaded();var r=this.getLayer(e);r?r.minzoom===i&&r.maxzoom===o||(null!=i&&(r.minzoom=i),null!=o&&(r.maxzoom=o),this._updateLayer(r)):this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot have zoom extent.")));},i.prototype.setFilter=function(e,i,o){void 0===o&&(o={}),this._checkLoaded();var r=this.getLayer(e);if(r){if(!t.deepEqual(r.filter,i))return null==i?(r.filter=void 0,void this._updateLayer(r)):void(this._validate(t.validateStyle.filter,"layers."+r.id+".filter",i,null,o)||(r.filter=t.clone$1(i),this._updateLayer(r)))}else this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be filtered.")));},i.prototype.getFilter=function(e){return t.clone$1(this.getLayer(e).filter)},i.prototype.setLayoutProperty=function(e,i,o,r){void 0===r&&(r={}),this._checkLoaded();var a=this.getLayer(e);a?t.deepEqual(a.getLayoutProperty(i),o)||(a.setLayoutProperty(i,o,r),this._updateLayer(a)):this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be styled.")));},i.prototype.getLayoutProperty=function(e,i){var o=this.getLayer(e);if(o)return o.getLayoutProperty(i);this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style.")));},i.prototype.setPaintProperty=function(e,i,o,r){void 0===r&&(r={}),this._checkLoaded();var a=this.getLayer(e);a?t.deepEqual(a.getPaintProperty(i),o)||(a.setPaintProperty(i,o,r)&&this._updateLayer(a),this._changed=!0,this._updatedPaintProps[e]=!0):this.fire(new t.ErrorEvent(new Error("The layer '"+e+"' does not exist in the map's style and cannot be styled.")));},i.prototype.getPaintProperty=function(t,e){return this.getLayer(t).getPaintProperty(e)},i.prototype.setFeatureState=function(e,i){this._checkLoaded();var o=e.source,r=e.sourceLayer,a=this.sourceCaches[o],n=parseInt(e.id,10);if(void 0!==a){var s=a.getSource().type;"geojson"===s&&r?this.fire(new t.ErrorEvent(new Error("GeoJSON sources cannot have a sourceLayer parameter."))):"vector"!==s||r?isNaN(n)||n<0?this.fire(new t.ErrorEvent(new Error("The feature id parameter must be provided and non-negative."))):a.setFeatureState(r,n,i):this.fire(new t.ErrorEvent(new Error("The sourceLayer parameter must be provided for vector source types.")));}else this.fire(new t.ErrorEvent(new Error("The source '"+o+"' does not exist in the map's style.")));},i.prototype.removeFeatureState=function(e,i){this._checkLoaded();var o=e.source,r=this.sourceCaches[o];if(void 0!==r){var a=r.getSource().type,n="vector"===a?e.sourceLayer:void 0,s=parseInt(e.id,10);"vector"!==a||n?void 0!==e.id&&isNaN(s)||s<0?this.fire(new t.ErrorEvent(new Error("The feature id parameter must be non-negative."))):i&&"string"!=typeof e.id&&"number"!=typeof e.id?this.fire(new t.ErrorEvent(new Error("A feature id is requred to remove its specific state property."))):r.removeFeatureState(n,s,i):this.fire(new t.ErrorEvent(new Error("The sourceLayer parameter must be provided for vector source types.")));}else this.fire(new t.ErrorEvent(new Error("The source '"+o+"' does not exist in the map's style.")));},i.prototype.getFeatureState=function(e){this._checkLoaded();var i=e.source,o=e.sourceLayer,r=this.sourceCaches[i],a=parseInt(e.id,10);if(void 0!==r)if("vector"!==r.getSource().type||o){if(!(isNaN(a)||a<0))return r.getFeatureState(o,a);this.fire(new t.ErrorEvent(new Error("The feature id parameter must be provided and non-negative.")));}else this.fire(new t.ErrorEvent(new Error("The sourceLayer parameter must be provided for vector source types.")));else this.fire(new t.ErrorEvent(new Error("The source '"+i+"' does not exist in the map's style.")));},i.prototype.getTransition=function(){return t.extend({duration:300,delay:0},this.stylesheet&&this.stylesheet.transition)},i.prototype.serialize=function(){return t.filterObject({version:this.stylesheet.version,name:this.stylesheet.name,metadata:this.stylesheet.metadata,light:this.stylesheet.light,center:this.stylesheet.center,zoom:this.stylesheet.zoom,bearing:this.stylesheet.bearing,pitch:this.stylesheet.pitch,sprite:this.stylesheet.sprite,glyphs:this.stylesheet.glyphs,transition:this.stylesheet.transition,sources:t.mapObject(this.sourceCaches,function(t){return t.serialize()}),layers:this._serializeLayers(this._order)},function(t){return void 0!==t})},i.prototype._updateLayer=function(t){this._updatedLayers[t.id]=!0,t.source&&!this._updatedSources[t.source]&&(this._updatedSources[t.source]="reload",this.sourceCaches[t.source].pause()),this._changed=!0;},i.prototype._flattenAndSortRenderedFeatures=function(t){for(var e=this,i=function(t){return "fill-extrusion"===e._layers[t].type},o={},r=[],a=this._order.length-1;a>=0;a--){var n=this._order[a];if(i(n)){o[n]=a;for(var s=0,l=t;s=0;_--){var f=this._order[_];if(i(f))for(var m=r.length-1;m>=0;m--){var g=r[m].feature;if(o[g.layer.id]<_)break;d.push(g),r.pop();}else for(var v=0,y=t;v 0.5) {gl_FragColor=vec4(0.0,0.0,1.0,0.5)*alpha;}if (v_notUsed > 0.5) {gl_FragColor*=.1;}}","attribute vec2 a_pos;attribute vec2 a_anchor_pos;attribute vec2 a_extrude;attribute vec2 a_placed;attribute vec2 a_shift;uniform mat4 u_matrix;uniform vec2 u_extrude_scale;uniform float u_camera_to_center_distance;varying float v_placed;varying float v_notUsed;void main() {vec4 projectedPoint=u_matrix*vec4(a_anchor_pos,0,1);highp float camera_to_anchor_distance=projectedPoint.w;highp float collision_perspective_ratio=clamp(0.5+0.5*(u_camera_to_center_distance/camera_to_anchor_distance),0.0,4.0);gl_Position=u_matrix*vec4(a_pos,0.0,1.0);gl_Position.xy+=(a_extrude+a_shift)*u_extrude_scale*gl_Position.w*collision_perspective_ratio;v_placed=a_placed.x;v_notUsed=a_placed.y;}"),We=ci("uniform float u_overscale_factor;varying float v_placed;varying float v_notUsed;varying float v_radius;varying vec2 v_extrude;varying vec2 v_extrude_scale;void main() {float alpha=0.5;vec4 color=vec4(1.0,0.0,0.0,1.0)*alpha;if (v_placed > 0.5) {color=vec4(0.0,0.0,1.0,0.5)*alpha;}if (v_notUsed > 0.5) {color*=.2;}float extrude_scale_length=length(v_extrude_scale);float extrude_length=length(v_extrude)*extrude_scale_length;float stroke_width=15.0*extrude_scale_length/u_overscale_factor;float radius=v_radius*extrude_scale_length;float distance_to_edge=abs(extrude_length-radius);float opacity_t=smoothstep(-stroke_width,0.0,-distance_to_edge);gl_FragColor=opacity_t*color;}","attribute vec2 a_pos;attribute vec2 a_anchor_pos;attribute vec2 a_extrude;attribute vec2 a_placed;uniform mat4 u_matrix;uniform vec2 u_extrude_scale;uniform float u_camera_to_center_distance;varying float v_placed;varying float v_notUsed;varying float v_radius;varying vec2 v_extrude;varying vec2 v_extrude_scale;void main() {vec4 projectedPoint=u_matrix*vec4(a_anchor_pos,0,1);highp float camera_to_anchor_distance=projectedPoint.w;highp float collision_perspective_ratio=clamp(0.5+0.5*(u_camera_to_center_distance/camera_to_anchor_distance),0.0,4.0);gl_Position=u_matrix*vec4(a_pos,0.0,1.0);highp float padding_factor=1.2;gl_Position.xy+=a_extrude*u_extrude_scale*padding_factor*gl_Position.w*collision_perspective_ratio;v_placed=a_placed.x;v_notUsed=a_placed.y;v_radius=abs(a_extrude.y);v_extrude=a_extrude*padding_factor;v_extrude_scale=u_extrude_scale*u_camera_to_center_distance*collision_perspective_ratio;}"),Xe=ci("uniform highp vec4 u_color;void main() {gl_FragColor=u_color;}","attribute vec2 a_pos;uniform mat4 u_matrix;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);}"),He=ci("#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float opacity\ngl_FragColor=color*opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","attribute vec2 a_pos;uniform mat4 u_matrix;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float opacity\ngl_Position=u_matrix*vec4(a_pos,0,1);}"),Ke=ci("varying vec2 v_pos;\n#pragma mapbox: define highp vec4 outline_color\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 outline_color\n#pragma mapbox: initialize lowp float opacity\nfloat dist=length(v_pos-gl_FragCoord.xy);float alpha=1.0-smoothstep(0.0,1.0,dist);gl_FragColor=outline_color*(alpha*opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","attribute vec2 a_pos;uniform mat4 u_matrix;uniform vec2 u_world;varying vec2 v_pos;\n#pragma mapbox: define highp vec4 outline_color\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 outline_color\n#pragma mapbox: initialize lowp float opacity\ngl_Position=u_matrix*vec4(a_pos,0,1);v_pos=(gl_Position.xy/gl_Position.w+1.0)/2.0*u_world;}"),Ye=ci("uniform vec2 u_texsize;uniform sampler2D u_image;uniform float u_fade;varying vec2 v_pos_a;varying vec2 v_pos_b;varying vec2 v_pos;\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture2D(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture2D(u_image,pos2);float dist=length(v_pos-gl_FragCoord.xy);float alpha=1.0-smoothstep(0.0,1.0,dist);gl_FragColor=mix(color1,color2,u_fade)*alpha*opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","uniform mat4 u_matrix;uniform vec2 u_world;uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform vec4 u_scale;attribute vec2 a_pos;varying vec2 v_pos_a;varying vec2 v_pos_b;varying vec2 v_pos;\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float pixelRatio=u_scale.x;float tileRatio=u_scale.y;float fromScale=u_scale.z;float toScale=u_scale.w;gl_Position=u_matrix*vec4(a_pos,0,1);vec2 display_size_a=vec2((pattern_br_a.x-pattern_tl_a.x)/pixelRatio,(pattern_br_a.y-pattern_tl_a.y)/pixelRatio);vec2 display_size_b=vec2((pattern_br_b.x-pattern_tl_b.x)/pixelRatio,(pattern_br_b.y-pattern_tl_b.y)/pixelRatio);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileRatio,a_pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileRatio,a_pos);v_pos=(gl_Position.xy/gl_Position.w+1.0)/2.0*u_world;}"),Je=ci("uniform vec2 u_texsize;uniform float u_fade;uniform sampler2D u_image;varying vec2 v_pos_a;varying vec2 v_pos_b;\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture2D(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture2D(u_image,pos2);gl_FragColor=mix(color1,color2,u_fade)*opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","uniform mat4 u_matrix;uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform vec4 u_scale;attribute vec2 a_pos;varying vec2 v_pos_a;varying vec2 v_pos_b;\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float pixelRatio=u_scale.x;float tileZoomRatio=u_scale.y;float fromScale=u_scale.z;float toScale=u_scale.w;vec2 display_size_a=vec2((pattern_br_a.x-pattern_tl_a.x)/pixelRatio,(pattern_br_a.y-pattern_tl_a.y)/pixelRatio);vec2 display_size_b=vec2((pattern_br_b.x-pattern_tl_b.x)/pixelRatio,(pattern_br_b.y-pattern_tl_b.y)/pixelRatio);gl_Position=u_matrix*vec4(a_pos,0,1);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileZoomRatio,a_pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileZoomRatio,a_pos);}"),Qe=ci("varying vec4 v_color;void main() {gl_FragColor=v_color;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","uniform mat4 u_matrix;uniform vec3 u_lightcolor;uniform lowp vec3 u_lightpos;uniform lowp float u_lightintensity;uniform float u_vertical_gradient;uniform lowp float u_opacity;attribute vec2 a_pos;attribute vec4 a_normal_ed;varying vec4 v_color;\n#pragma mapbox: define highp float base\n#pragma mapbox: define highp float height\n#pragma mapbox: define highp vec4 color\nvoid main() {\n#pragma mapbox: initialize highp float base\n#pragma mapbox: initialize highp float height\n#pragma mapbox: initialize highp vec4 color\nvec3 normal=a_normal_ed.xyz;base=max(0.0,base);height=max(0.0,height);float t=mod(normal.x,2.0);gl_Position=u_matrix*vec4(a_pos,t > 0.0 ? height : base,1);float colorvalue=color.r*0.2126+color.g*0.7152+color.b*0.0722;v_color=vec4(0.0,0.0,0.0,1.0);vec4 ambientlight=vec4(0.03,0.03,0.03,1.0);color+=ambientlight;float directional=clamp(dot(normal/16384.0,u_lightpos),0.0,1.0);directional=mix((1.0-u_lightintensity),max((1.0-colorvalue+u_lightintensity),1.0),directional);if (normal.y !=0.0) {directional*=((1.0-u_vertical_gradient)+(u_vertical_gradient*clamp((t+base)*pow(height/150.0,0.5),mix(0.7,0.98,1.0-u_lightintensity),1.0)));}v_color.r+=clamp(color.r*directional*u_lightcolor.r,mix(0.0,0.3,1.0-u_lightcolor.r),1.0);v_color.g+=clamp(color.g*directional*u_lightcolor.g,mix(0.0,0.3,1.0-u_lightcolor.g),1.0);v_color.b+=clamp(color.b*directional*u_lightcolor.b,mix(0.0,0.3,1.0-u_lightcolor.b),1.0);v_color*=u_opacity;}"),$e=ci("uniform vec2 u_texsize;uniform float u_fade;uniform sampler2D u_image;varying vec2 v_pos_a;varying vec2 v_pos_b;varying vec4 v_lighting;\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\nvoid main() {\n#pragma mapbox: initialize lowp float base\n#pragma mapbox: initialize lowp float height\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture2D(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture2D(u_image,pos2);vec4 mixedColor=mix(color1,color2,u_fade);gl_FragColor=mixedColor*v_lighting;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","uniform mat4 u_matrix;uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform float u_height_factor;uniform vec4 u_scale;uniform float u_vertical_gradient;uniform lowp float u_opacity;uniform vec3 u_lightcolor;uniform lowp vec3 u_lightpos;uniform lowp float u_lightintensity;attribute vec2 a_pos;attribute vec4 a_normal_ed;varying vec2 v_pos_a;varying vec2 v_pos_b;varying vec4 v_lighting;\n#pragma mapbox: define lowp float base\n#pragma mapbox: define lowp float height\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\nvoid main() {\n#pragma mapbox: initialize lowp float base\n#pragma mapbox: initialize lowp float height\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float pixelRatio=u_scale.x;float tileRatio=u_scale.y;float fromScale=u_scale.z;float toScale=u_scale.w;vec3 normal=a_normal_ed.xyz;float edgedistance=a_normal_ed.w;vec2 display_size_a=vec2((pattern_br_a.x-pattern_tl_a.x)/pixelRatio,(pattern_br_a.y-pattern_tl_a.y)/pixelRatio);vec2 display_size_b=vec2((pattern_br_b.x-pattern_tl_b.x)/pixelRatio,(pattern_br_b.y-pattern_tl_b.y)/pixelRatio);base=max(0.0,base);height=max(0.0,height);float t=mod(normal.x,2.0);float z=t > 0.0 ? height : base;gl_Position=u_matrix*vec4(a_pos,z,1);vec2 pos=normal.x==1.0 && normal.y==0.0 && normal.z==16384.0\n? a_pos\n: vec2(edgedistance,z*u_height_factor);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileRatio,pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileRatio,pos);v_lighting=vec4(0.0,0.0,0.0,1.0);float directional=clamp(dot(normal/16383.0,u_lightpos),0.0,1.0);directional=mix((1.0-u_lightintensity),max((0.5+u_lightintensity),1.0),directional);if (normal.y !=0.0) {directional*=((1.0-u_vertical_gradient)+(u_vertical_gradient*clamp((t+base)*pow(height/150.0,0.5),mix(0.7,0.98,1.0-u_lightintensity),1.0)));}v_lighting.rgb+=clamp(directional*u_lightcolor,mix(vec3(0.0),vec3(0.3),1.0-u_lightcolor),vec3(1.0));v_lighting*=u_opacity;}"),ti=ci("#ifdef GL_ES\nprecision highp float;\n#endif\nuniform sampler2D u_image;varying vec2 v_pos;uniform vec2 u_dimension;uniform float u_zoom;uniform float u_maxzoom;float getElevation(vec2 coord,float bias) {vec4 data=texture2D(u_image,coord)*255.0;return (data.r+data.g*256.0+data.b*256.0*256.0)/4.0;}void main() {vec2 epsilon=1.0/u_dimension;float a=getElevation(v_pos+vec2(-epsilon.x,-epsilon.y),0.0);float b=getElevation(v_pos+vec2(0,-epsilon.y),0.0);float c=getElevation(v_pos+vec2(epsilon.x,-epsilon.y),0.0);float d=getElevation(v_pos+vec2(-epsilon.x,0),0.0);float e=getElevation(v_pos,0.0);float f=getElevation(v_pos+vec2(epsilon.x,0),0.0);float g=getElevation(v_pos+vec2(-epsilon.x,epsilon.y),0.0);float h=getElevation(v_pos+vec2(0,epsilon.y),0.0);float i=getElevation(v_pos+vec2(epsilon.x,epsilon.y),0.0);float exaggeration=u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;vec2 deriv=vec2((c+f+f+i)-(a+d+d+g),(g+h+h+i)-(a+b+b+c))/ pow(2.0,(u_zoom-u_maxzoom)*exaggeration+19.2562-u_zoom);gl_FragColor=clamp(vec4(deriv.x/2.0+0.5,deriv.y/2.0+0.5,1.0,1.0),0.0,1.0);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","uniform mat4 u_matrix;uniform vec2 u_dimension;attribute vec2 a_pos;attribute vec2 a_texture_pos;varying vec2 v_pos;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);highp vec2 epsilon=1.0/u_dimension;float scale=(u_dimension.x-2.0)/u_dimension.x;v_pos=(a_texture_pos/8192.0)*scale+epsilon;}"),ei=ci("uniform sampler2D u_image;varying vec2 v_pos;uniform vec2 u_latrange;uniform vec2 u_light;uniform vec4 u_shadow;uniform vec4 u_highlight;uniform vec4 u_accent;\n#define PI 3.141592653589793\nvoid main() {vec4 pixel=texture2D(u_image,v_pos);vec2 deriv=((pixel.rg*2.0)-1.0);float scaleFactor=cos(radians((u_latrange[0]-u_latrange[1])*(1.0-v_pos.y)+u_latrange[1]));float slope=atan(1.25*length(deriv)/scaleFactor);float aspect=deriv.x !=0.0 ? atan(deriv.y,-deriv.x) : PI/2.0*(deriv.y > 0.0 ? 1.0 :-1.0);float intensity=u_light.x;float azimuth=u_light.y+PI;float base=1.875-intensity*1.75;float maxValue=0.5*PI;float scaledSlope=intensity !=0.5 ? ((pow(base,slope)-1.0)/(pow(base,maxValue)-1.0))*maxValue : slope;float accent=cos(scaledSlope);vec4 accent_color=(1.0-accent)*u_accent*clamp(intensity*2.0,0.0,1.0);float shade=abs(mod((aspect+azimuth)/PI+0.5,2.0)-1.0);vec4 shade_color=mix(u_shadow,u_highlight,shade)*sin(scaledSlope)*clamp(intensity*2.0,0.0,1.0);gl_FragColor=accent_color*(1.0-shade_color.a)+shade_color;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","uniform mat4 u_matrix;attribute vec2 a_pos;attribute vec2 a_texture_pos;varying vec2 v_pos;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);v_pos=a_texture_pos/8192.0;}"),ii=ci("uniform lowp float u_device_pixel_ratio;varying vec2 v_width2;varying vec2 v_normal;varying float v_gamma_scale;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\nfloat dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);gl_FragColor=color*(alpha*opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","\n#define scale 0.015873016\nattribute vec2 a_pos_normal;attribute vec4 a_data;uniform mat4 u_matrix;uniform mediump float u_ratio;uniform vec2 u_units_to_pixels;uniform lowp float u_device_pixel_ratio;varying vec2 v_normal;varying vec2 v_width2;varying float v_gamma_scale;varying highp float v_linesofar;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump float gapwidth\n#pragma mapbox: initialize lowp float offset\n#pragma mapbox: initialize mediump float width\nfloat ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;v_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*2.0;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);vec4 projected_extrude=u_matrix*vec4(dist/u_ratio,0.0,0.0);gl_Position=u_matrix*vec4(pos+offset2/u_ratio,0.0,1.0)+projected_extrude;float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length(projected_extrude.xy/gl_Position.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;v_width2=vec2(outset,inset);}"),oi=ci("uniform lowp float u_device_pixel_ratio;uniform sampler2D u_image;varying vec2 v_width2;varying vec2 v_normal;varying float v_gamma_scale;varying highp float v_lineprogress;\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\nfloat dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);vec4 color=texture2D(u_image,vec2(v_lineprogress,0.5));gl_FragColor=color*(alpha*opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","\n#define MAX_LINE_DISTANCE 32767.0\n#define scale 0.015873016\nattribute vec2 a_pos_normal;attribute vec4 a_data;uniform mat4 u_matrix;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;uniform vec2 u_units_to_pixels;varying vec2 v_normal;varying vec2 v_width2;varying float v_gamma_scale;varying highp float v_lineprogress;\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\nvoid main() {\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump float gapwidth\n#pragma mapbox: initialize lowp float offset\n#pragma mapbox: initialize mediump float width\nfloat ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;v_lineprogress=(floor(a_data.z/4.0)+a_data.w*64.0)*2.0/MAX_LINE_DISTANCE;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);vec4 projected_extrude=u_matrix*vec4(dist/u_ratio,0.0,0.0);gl_Position=u_matrix*vec4(pos+offset2/u_ratio,0.0,1.0)+projected_extrude;float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length(projected_extrude.xy/gl_Position.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;v_width2=vec2(outset,inset);}"),ri=ci("uniform lowp float u_device_pixel_ratio;uniform vec2 u_texsize;uniform float u_fade;uniform mediump vec4 u_scale;uniform sampler2D u_image;varying vec2 v_normal;varying vec2 v_width2;varying float v_linesofar;varying float v_gamma_scale;\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float pixelRatio=u_scale.x;float tileZoomRatio=u_scale.y;float fromScale=u_scale.z;float toScale=u_scale.w;vec2 display_size_a=vec2((pattern_br_a.x-pattern_tl_a.x)/pixelRatio,(pattern_br_a.y-pattern_tl_a.y)/pixelRatio);vec2 display_size_b=vec2((pattern_br_b.x-pattern_tl_b.x)/pixelRatio,(pattern_br_b.y-pattern_tl_b.y)/pixelRatio);vec2 pattern_size_a=vec2(display_size_a.x*fromScale/tileZoomRatio,display_size_a.y);vec2 pattern_size_b=vec2(display_size_b.x*toScale/tileZoomRatio,display_size_b.y);float dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);float x_a=mod(v_linesofar/pattern_size_a.x,1.0);float x_b=mod(v_linesofar/pattern_size_b.x,1.0);float y_a=0.5+(v_normal.y*clamp(v_width2.s,0.0,(pattern_size_a.y+2.0)/2.0)/pattern_size_a.y);float y_b=0.5+(v_normal.y*clamp(v_width2.s,0.0,(pattern_size_b.y+2.0)/2.0)/pattern_size_b.y);vec2 pos_a=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,vec2(x_a,y_a));vec2 pos_b=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,vec2(x_b,y_b));vec4 color=mix(texture2D(u_image,pos_a),texture2D(u_image,pos_b),u_fade);gl_FragColor=color*alpha*opacity;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","\n#define scale 0.015873016\n#define LINE_DISTANCE_SCALE 2.0\nattribute vec2 a_pos_normal;attribute vec4 a_data;uniform mat4 u_matrix;uniform vec2 u_units_to_pixels;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;varying vec2 v_normal;varying vec2 v_width2;varying float v_linesofar;varying float v_gamma_scale;\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp vec4 pattern_from\n#pragma mapbox: define lowp vec4 pattern_to\nvoid main() {\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float offset\n#pragma mapbox: initialize mediump float gapwidth\n#pragma mapbox: initialize mediump float width\n#pragma mapbox: initialize mediump vec4 pattern_from\n#pragma mapbox: initialize mediump vec4 pattern_to\nfloat ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;float a_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*LINE_DISTANCE_SCALE;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);vec4 projected_extrude=u_matrix*vec4(dist/u_ratio,0.0,0.0);gl_Position=u_matrix*vec4(pos+offset2/u_ratio,0.0,1.0)+projected_extrude;float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length(projected_extrude.xy/gl_Position.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;v_linesofar=a_linesofar;v_width2=vec2(outset,inset);}"),ai=ci("uniform lowp float u_device_pixel_ratio;uniform sampler2D u_image;uniform float u_sdfgamma;uniform float u_mix;varying vec2 v_normal;varying vec2 v_width2;varying vec2 v_tex_a;varying vec2 v_tex_b;varying float v_gamma_scale;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp float floorwidth\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump float width\n#pragma mapbox: initialize lowp float floorwidth\nfloat dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);float sdfdist_a=texture2D(u_image,v_tex_a).a;float sdfdist_b=texture2D(u_image,v_tex_b).a;float sdfdist=mix(sdfdist_a,sdfdist_b,u_mix);alpha*=smoothstep(0.5-u_sdfgamma/floorwidth,0.5+u_sdfgamma/floorwidth,sdfdist);gl_FragColor=color*(alpha*opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","\n#define scale 0.015873016\n#define LINE_DISTANCE_SCALE 2.0\nattribute vec2 a_pos_normal;attribute vec4 a_data;uniform mat4 u_matrix;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;uniform vec2 u_patternscale_a;uniform float u_tex_y_a;uniform vec2 u_patternscale_b;uniform float u_tex_y_b;uniform vec2 u_units_to_pixels;varying vec2 v_normal;varying vec2 v_width2;varying vec2 v_tex_a;varying vec2 v_tex_b;varying float v_gamma_scale;\n#pragma mapbox: define highp vec4 color\n#pragma mapbox: define lowp float blur\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define mediump float gapwidth\n#pragma mapbox: define lowp float offset\n#pragma mapbox: define mediump float width\n#pragma mapbox: define lowp float floorwidth\nvoid main() {\n#pragma mapbox: initialize highp vec4 color\n#pragma mapbox: initialize lowp float blur\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize mediump float gapwidth\n#pragma mapbox: initialize lowp float offset\n#pragma mapbox: initialize mediump float width\n#pragma mapbox: initialize lowp float floorwidth\nfloat ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=a_data.xy-128.0;float a_direction=mod(a_data.z,4.0)-1.0;float a_linesofar=(floor(a_data.z/4.0)+a_data.w*64.0)*LINE_DISTANCE_SCALE;vec2 pos=floor(a_pos_normal*0.5);mediump vec2 normal=a_pos_normal-2.0*pos;normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);vec4 projected_extrude=u_matrix*vec4(dist/u_ratio,0.0,0.0);gl_Position=u_matrix*vec4(pos+offset2/u_ratio,0.0,1.0)+projected_extrude;float extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length(projected_extrude.xy/gl_Position.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;v_tex_a=vec2(a_linesofar*u_patternscale_a.x/floorwidth,normal.y*u_patternscale_a.y+u_tex_y_a);v_tex_b=vec2(a_linesofar*u_patternscale_b.x/floorwidth,normal.y*u_patternscale_b.y+u_tex_y_b);v_width2=vec2(outset,inset);}"),ni=ci("uniform float u_fade_t;uniform float u_opacity;uniform sampler2D u_image0;uniform sampler2D u_image1;varying vec2 v_pos0;varying vec2 v_pos1;uniform float u_brightness_low;uniform float u_brightness_high;uniform float u_saturation_factor;uniform float u_contrast_factor;uniform vec3 u_spin_weights;void main() {vec4 color0=texture2D(u_image0,v_pos0);vec4 color1=texture2D(u_image1,v_pos1);if (color0.a > 0.0) {color0.rgb=color0.rgb/color0.a;}if (color1.a > 0.0) {color1.rgb=color1.rgb/color1.a;}vec4 color=mix(color0,color1,u_fade_t);color.a*=u_opacity;vec3 rgb=color.rgb;rgb=vec3(dot(rgb,u_spin_weights.xyz),dot(rgb,u_spin_weights.zxy),dot(rgb,u_spin_weights.yzx));float average=(color.r+color.g+color.b)/3.0;rgb+=(average-rgb)*u_saturation_factor;rgb=(rgb-0.5)*u_contrast_factor+0.5;vec3 u_high_vec=vec3(u_brightness_low,u_brightness_low,u_brightness_low);vec3 u_low_vec=vec3(u_brightness_high,u_brightness_high,u_brightness_high);gl_FragColor=vec4(mix(u_high_vec,u_low_vec,rgb)*color.a,color.a);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","uniform mat4 u_matrix;uniform vec2 u_tl_parent;uniform float u_scale_parent;uniform float u_buffer_scale;attribute vec2 a_pos;attribute vec2 a_texture_pos;varying vec2 v_pos0;varying vec2 v_pos1;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);v_pos0=(((a_texture_pos/8192.0)-0.5)/u_buffer_scale )+0.5;v_pos1=(v_pos0*u_scale_parent)+u_tl_parent;}"),si=ci("uniform sampler2D u_texture;varying vec2 v_tex;varying float v_fade_opacity;\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\nlowp float alpha=opacity*v_fade_opacity;gl_FragColor=texture2D(u_texture,v_tex)*alpha;\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","const float PI=3.141592653589793;attribute vec4 a_pos_offset;attribute vec4 a_data;attribute vec3 a_projected_pos;attribute float a_fade_opacity;uniform bool u_is_size_zoom_constant;uniform bool u_is_size_feature_constant;uniform highp float u_size_t;uniform highp float u_size;uniform highp float u_camera_to_center_distance;uniform highp float u_pitch;uniform bool u_rotate_symbol;uniform highp float u_aspect_ratio;uniform float u_fade_change;uniform mat4 u_matrix;uniform mat4 u_label_plane_matrix;uniform mat4 u_coord_matrix;uniform bool u_is_text;uniform bool u_pitch_with_map;uniform vec2 u_texsize;varying vec2 v_tex;varying float v_fade_opacity;\n#pragma mapbox: define lowp float opacity\nvoid main() {\n#pragma mapbox: initialize lowp float opacity\nvec2 a_pos=a_pos_offset.xy;vec2 a_offset=a_pos_offset.zw;vec2 a_tex=a_data.xy;vec2 a_size=a_data.zw;highp float segment_angle=-a_projected_pos[2];float size;if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {size=mix(a_size[0],a_size[1],u_size_t)/256.0;} else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {size=a_size[0]/256.0;} else if (!u_is_size_zoom_constant && u_is_size_feature_constant) {size=u_size;} else {size=u_size;}vec4 projectedPoint=u_matrix*vec4(a_pos,0,1);highp float camera_to_anchor_distance=projectedPoint.w;highp float distance_ratio=u_pitch_with_map ?\ncamera_to_anchor_distance/u_camera_to_center_distance :\nu_camera_to_center_distance/camera_to_anchor_distance;highp float perspective_ratio=clamp(0.5+0.5*distance_ratio,0.0,4.0);size*=perspective_ratio;float fontScale=u_is_text ? size/24.0 : size;highp float symbol_rotation=0.0;if (u_rotate_symbol) {vec4 offsetProjectedPoint=u_matrix*vec4(a_pos+vec2(1,0),0,1);vec2 a=projectedPoint.xy/projectedPoint.w;vec2 b=offsetProjectedPoint.xy/offsetProjectedPoint.w;symbol_rotation=atan((b.y-a.y)/u_aspect_ratio,b.x-a.x);}highp float angle_sin=sin(segment_angle+symbol_rotation);highp float angle_cos=cos(segment_angle+symbol_rotation);mat2 rotation_matrix=mat2(angle_cos,-1.0*angle_sin,angle_sin,angle_cos);vec4 projected_pos=u_label_plane_matrix*vec4(a_projected_pos.xy,0.0,1.0);gl_Position=u_coord_matrix*vec4(projected_pos.xy/projected_pos.w+rotation_matrix*(a_offset/32.0*fontScale),0.0,1.0);v_tex=a_tex/u_texsize;vec2 fade_opacity=unpack_opacity(a_fade_opacity);float fade_change=fade_opacity[1] > 0.5 ? u_fade_change :-u_fade_change;v_fade_opacity=max(0.0,min(1.0,fade_opacity[0]+fade_change));}"),li=ci("#define SDF_PX 8.0\nuniform bool u_is_halo;uniform sampler2D u_texture;uniform highp float u_gamma_scale;uniform lowp float u_device_pixel_ratio;uniform bool u_is_text;varying vec2 v_data0;varying vec3 v_data1;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\nvoid main() {\n#pragma mapbox: initialize highp vec4 fill_color\n#pragma mapbox: initialize highp vec4 halo_color\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float halo_width\n#pragma mapbox: initialize lowp float halo_blur\nfloat EDGE_GAMMA=0.105/u_device_pixel_ratio;vec2 tex=v_data0.xy;float gamma_scale=v_data1.x;float size=v_data1.y;float fade_opacity=v_data1[2];float fontScale=u_is_text ? size/24.0 : size;lowp vec4 color=fill_color;highp float gamma=EDGE_GAMMA/(fontScale*u_gamma_scale);lowp float buff=(256.0-64.0)/256.0;if (u_is_halo) {color=halo_color;gamma=(halo_blur*1.19/SDF_PX+EDGE_GAMMA)/(fontScale*u_gamma_scale);buff=(6.0-halo_width/fontScale)/SDF_PX;}lowp float dist=texture2D(u_texture,tex).a;highp float gamma_scaled=gamma*gamma_scale;highp float alpha=smoothstep(buff-gamma_scaled,buff+gamma_scaled,dist);gl_FragColor=color*(alpha*opacity*fade_opacity);\n#ifdef OVERDRAW_INSPECTOR\ngl_FragColor=vec4(1.0);\n#endif\n}","const float PI=3.141592653589793;attribute vec4 a_pos_offset;attribute vec4 a_data;attribute vec3 a_projected_pos;attribute float a_fade_opacity;uniform bool u_is_size_zoom_constant;uniform bool u_is_size_feature_constant;uniform highp float u_size_t;uniform highp float u_size;uniform mat4 u_matrix;uniform mat4 u_label_plane_matrix;uniform mat4 u_coord_matrix;uniform bool u_is_text;uniform bool u_pitch_with_map;uniform highp float u_pitch;uniform bool u_rotate_symbol;uniform highp float u_aspect_ratio;uniform highp float u_camera_to_center_distance;uniform float u_fade_change;uniform vec2 u_texsize;varying vec2 v_data0;varying vec3 v_data1;\n#pragma mapbox: define highp vec4 fill_color\n#pragma mapbox: define highp vec4 halo_color\n#pragma mapbox: define lowp float opacity\n#pragma mapbox: define lowp float halo_width\n#pragma mapbox: define lowp float halo_blur\nvoid main() {\n#pragma mapbox: initialize highp vec4 fill_color\n#pragma mapbox: initialize highp vec4 halo_color\n#pragma mapbox: initialize lowp float opacity\n#pragma mapbox: initialize lowp float halo_width\n#pragma mapbox: initialize lowp float halo_blur\nvec2 a_pos=a_pos_offset.xy;vec2 a_offset=a_pos_offset.zw;vec2 a_tex=a_data.xy;vec2 a_size=a_data.zw;highp float segment_angle=-a_projected_pos[2];float size;if (!u_is_size_zoom_constant && !u_is_size_feature_constant) {size=mix(a_size[0],a_size[1],u_size_t)/256.0;} else if (u_is_size_zoom_constant && !u_is_size_feature_constant) {size=a_size[0]/256.0;} else if (!u_is_size_zoom_constant && u_is_size_feature_constant) {size=u_size;} else {size=u_size;}vec4 projectedPoint=u_matrix*vec4(a_pos,0,1);highp float camera_to_anchor_distance=projectedPoint.w;highp float distance_ratio=u_pitch_with_map ?\ncamera_to_anchor_distance/u_camera_to_center_distance :\nu_camera_to_center_distance/camera_to_anchor_distance;highp float perspective_ratio=clamp(0.5+0.5*distance_ratio,0.0,4.0);size*=perspective_ratio;float fontScale=u_is_text ? size/24.0 : size;highp float symbol_rotation=0.0;if (u_rotate_symbol) {vec4 offsetProjectedPoint=u_matrix*vec4(a_pos+vec2(1,0),0,1);vec2 a=projectedPoint.xy/projectedPoint.w;vec2 b=offsetProjectedPoint.xy/offsetProjectedPoint.w;symbol_rotation=atan((b.y-a.y)/u_aspect_ratio,b.x-a.x);}highp float angle_sin=sin(segment_angle+symbol_rotation);highp float angle_cos=cos(segment_angle+symbol_rotation);mat2 rotation_matrix=mat2(angle_cos,-1.0*angle_sin,angle_sin,angle_cos);vec4 projected_pos=u_label_plane_matrix*vec4(a_projected_pos.xy,0.0,1.0);gl_Position=u_coord_matrix*vec4(projected_pos.xy/projected_pos.w+rotation_matrix*(a_offset/32.0*fontScale),0.0,1.0);float gamma_scale=gl_Position.w;vec2 tex=a_tex/u_texsize;vec2 fade_opacity=unpack_opacity(a_fade_opacity);float fade_change=fade_opacity[1] > 0.5 ? u_fade_change :-u_fade_change;float interpolated_fade_opacity=max(0.0,min(1.0,fade_opacity[0]+fade_change));v_data0=vec2(tex.x,tex.y);v_data1=vec3(gamma_scale,size,interpolated_fade_opacity);}");function ci(t,e){var i=/#pragma mapbox: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g,o={};return {fragmentSource:t=t.replace(i,function(t,e,i,r,a){return o[a]=!0,"define"===e?"\n#ifndef HAS_UNIFORM_u_"+a+"\nvarying "+i+" "+r+" "+a+";\n#else\nuniform "+i+" "+r+" u_"+a+";\n#endif\n":"\n#ifdef HAS_UNIFORM_u_"+a+"\n "+i+" "+r+" "+a+" = u_"+a+";\n#endif\n"}),vertexSource:e=e.replace(i,function(t,e,i,r,a){var n="float"===r?"vec2":"vec4",s=a.match(/color/)?"color":n;return o[a]?"define"===e?"\n#ifndef HAS_UNIFORM_u_"+a+"\nuniform lowp float u_"+a+"_t;\nattribute "+i+" "+n+" a_"+a+";\nvarying "+i+" "+r+" "+a+";\n#else\nuniform "+i+" "+r+" u_"+a+";\n#endif\n":"vec4"===s?"\n#ifndef HAS_UNIFORM_u_"+a+"\n "+a+" = a_"+a+";\n#else\n "+i+" "+r+" "+a+" = u_"+a+";\n#endif\n":"\n#ifndef HAS_UNIFORM_u_"+a+"\n "+a+" = unpack_mix_"+s+"(a_"+a+", u_"+a+"_t);\n#else\n "+i+" "+r+" "+a+" = u_"+a+";\n#endif\n":"define"===e?"\n#ifndef HAS_UNIFORM_u_"+a+"\nuniform lowp float u_"+a+"_t;\nattribute "+i+" "+n+" a_"+a+";\n#else\nuniform "+i+" "+r+" u_"+a+";\n#endif\n":"vec4"===s?"\n#ifndef HAS_UNIFORM_u_"+a+"\n "+i+" "+r+" "+a+" = a_"+a+";\n#else\n "+i+" "+r+" "+a+" = u_"+a+";\n#endif\n":"\n#ifndef HAS_UNIFORM_u_"+a+"\n "+i+" "+r+" "+a+" = unpack_mix_"+s+"(a_"+a+", u_"+a+"_t);\n#else\n "+i+" "+r+" "+a+" = u_"+a+";\n#endif\n"})}}var ui=Object.freeze({prelude:Fe,background:Ue,backgroundPattern:Ne,circle:Ze,clippingMask:je,heatmap:qe,heatmapTexture:Ve,collisionBox:Ge,collisionCircle:We,debug:Xe,fill:He,fillOutline:Ke,fillOutlinePattern:Ye,fillPattern:Je,fillExtrusion:Qe,fillExtrusionPattern:$e,hillshadePrepare:ti,hillshade:ei,line:ii,lineGradient:oi,linePattern:ri,lineSDF:ai,raster:ni,symbolIcon:si,symbolSDF:li}),hi=function(){this.boundProgram=null,this.boundLayoutVertexBuffer=null,this.boundPaintVertexBuffers=[],this.boundIndexBuffer=null,this.boundVertexOffset=null,this.boundDynamicVertexBuffer=null,this.vao=null;};hi.prototype.bind=function(t,e,i,o,r,a,n,s){this.context=t;for(var l=this.boundPaintVertexBuffers.length!==o.length,c=0;!l&&c>16,l>>16],u_pixel_coord_lower:[65535&s,65535&l]}}pi.prototype.draw=function(t,e,i,o,r,a,n,s,l,c,u,h,p,d,_,f){var m,g=t.gl;for(var v in t.program.set(this.program),t.setDepthMode(i),t.setStencilMode(o),t.setColorMode(r),t.setCullFace(a),this.fixedUniforms)this.fixedUniforms[v].set(n[v]);d&&d.setUniforms(t,this.binderUniforms,h,{zoom:p});for(var y=(m={},m[g.LINES]=2,m[g.TRIANGLES]=3,m[g.LINE_STRIP]=1,m)[e],x=0,b=u.get();x0?1-1/(1.001-n):-n),u_contrast_factor:(a=r.paint.get("raster-contrast"),a>0?1/(1-a):1+a),u_spin_weights:Oi(r.paint.get("raster-hue-rotate"))};var a,n;};function Oi(t){t*=Math.PI/180;var e=Math.sin(t),i=Math.cos(t);return [(2*i+1)/3,(-Math.sqrt(3)*e-i+1)/3,(Math.sqrt(3)*e-i+1)/3]}var Fi=function(t,e,i,o,r,a,n,s,l,c){var u=r.transform;return {u_is_size_zoom_constant:+("constant"===t||"source"===t),u_is_size_feature_constant:+("constant"===t||"camera"===t),u_size_t:e?e.uSizeT:0,u_size:e?e.uSize:0,u_camera_to_center_distance:u.cameraToCenterDistance,u_pitch:u.pitch/360*2*Math.PI,u_rotate_symbol:+i,u_aspect_ratio:u.width/u.height,u_fade_change:r.options.fadeDuration?r.symbolFadeChange:1,u_matrix:a,u_label_plane_matrix:n,u_coord_matrix:s,u_is_text:+l,u_pitch_with_map:+o,u_texsize:c,u_texture:0}},Ui=function(e,i,o,r,a,n,s,l,c,u,h){var p=a.transform;return t.extend(Fi(e,i,o,r,a,n,s,l,c,u),{u_gamma_scale:r?Math.cos(p._pitch)*p.cameraToCenterDistance:1,u_device_pixel_ratio:t.browser.devicePixelRatio,u_is_halo:+h})},Ni=function(t,e,i){return {u_matrix:t,u_opacity:e,u_color:i}},Zi=function(e,i,o,r,a,n){return t.extend(function(t,e,i,o){var r=i.imageManager.getPattern(t.from),a=i.imageManager.getPattern(t.to),n=i.imageManager.getPixelSize(),s=n.width,l=n.height,c=Math.pow(2,o.tileID.overscaledZ),u=o.tileSize*Math.pow(2,i.transform.tileZoom)/c,h=u*(o.tileID.canonical.x+o.tileID.wrap*c),p=u*o.tileID.canonical.y;return {u_image:0,u_pattern_tl_a:r.tl,u_pattern_br_a:r.br,u_pattern_tl_b:a.tl,u_pattern_br_b:a.br,u_texsize:[s,l],u_mix:e.t,u_pattern_size_a:r.displaySize,u_pattern_size_b:a.displaySize,u_scale_a:e.fromScale,u_scale_b:e.toScale,u_tile_units_to_pixels:1/ce(o,1,i.transform.tileZoom),u_pixel_coord_upper:[h>>16,p>>16],u_pixel_coord_lower:[65535&h,65535&p]}}(r,n,o,a),{u_matrix:e,u_opacity:i})},ji={fillExtrusion:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_lightpos:new t.Uniform3f(e,i.u_lightpos),u_lightintensity:new t.Uniform1f(e,i.u_lightintensity),u_lightcolor:new t.Uniform3f(e,i.u_lightcolor),u_vertical_gradient:new t.Uniform1f(e,i.u_vertical_gradient),u_opacity:new t.Uniform1f(e,i.u_opacity)}},fillExtrusionPattern:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_lightpos:new t.Uniform3f(e,i.u_lightpos),u_lightintensity:new t.Uniform1f(e,i.u_lightintensity),u_lightcolor:new t.Uniform3f(e,i.u_lightcolor),u_vertical_gradient:new t.Uniform1f(e,i.u_vertical_gradient),u_height_factor:new t.Uniform1f(e,i.u_height_factor),u_image:new t.Uniform1i(e,i.u_image),u_texsize:new t.Uniform2f(e,i.u_texsize),u_pixel_coord_upper:new t.Uniform2f(e,i.u_pixel_coord_upper),u_pixel_coord_lower:new t.Uniform2f(e,i.u_pixel_coord_lower),u_scale:new t.Uniform4f(e,i.u_scale),u_fade:new t.Uniform1f(e,i.u_fade),u_opacity:new t.Uniform1f(e,i.u_opacity)}},fill:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix)}},fillPattern:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_image:new t.Uniform1i(e,i.u_image),u_texsize:new t.Uniform2f(e,i.u_texsize),u_pixel_coord_upper:new t.Uniform2f(e,i.u_pixel_coord_upper),u_pixel_coord_lower:new t.Uniform2f(e,i.u_pixel_coord_lower),u_scale:new t.Uniform4f(e,i.u_scale),u_fade:new t.Uniform1f(e,i.u_fade)}},fillOutline:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_world:new t.Uniform2f(e,i.u_world)}},fillOutlinePattern:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_world:new t.Uniform2f(e,i.u_world),u_image:new t.Uniform1i(e,i.u_image),u_texsize:new t.Uniform2f(e,i.u_texsize),u_pixel_coord_upper:new t.Uniform2f(e,i.u_pixel_coord_upper),u_pixel_coord_lower:new t.Uniform2f(e,i.u_pixel_coord_lower),u_scale:new t.Uniform4f(e,i.u_scale),u_fade:new t.Uniform1f(e,i.u_fade)}},circle:function(e,i){return {u_camera_to_center_distance:new t.Uniform1f(e,i.u_camera_to_center_distance),u_scale_with_map:new t.Uniform1i(e,i.u_scale_with_map),u_pitch_with_map:new t.Uniform1i(e,i.u_pitch_with_map),u_extrude_scale:new t.Uniform2f(e,i.u_extrude_scale),u_device_pixel_ratio:new t.Uniform1f(e,i.u_device_pixel_ratio),u_matrix:new t.UniformMatrix4f(e,i.u_matrix)}},collisionBox:bi,collisionCircle:bi,debug:function(e,i){return {u_color:new t.UniformColor(e,i.u_color),u_matrix:new t.UniformMatrix4f(e,i.u_matrix)}},clippingMask:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix)}},heatmap:function(e,i){return {u_extrude_scale:new t.Uniform1f(e,i.u_extrude_scale),u_intensity:new t.Uniform1f(e,i.u_intensity),u_matrix:new t.UniformMatrix4f(e,i.u_matrix)}},heatmapTexture:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_world:new t.Uniform2f(e,i.u_world),u_image:new t.Uniform1i(e,i.u_image),u_color_ramp:new t.Uniform1i(e,i.u_color_ramp),u_opacity:new t.Uniform1f(e,i.u_opacity)}},hillshade:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_image:new t.Uniform1i(e,i.u_image),u_latrange:new t.Uniform2f(e,i.u_latrange),u_light:new t.Uniform2f(e,i.u_light),u_shadow:new t.UniformColor(e,i.u_shadow),u_highlight:new t.UniformColor(e,i.u_highlight),u_accent:new t.UniformColor(e,i.u_accent)}},hillshadePrepare:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_image:new t.Uniform1i(e,i.u_image),u_dimension:new t.Uniform2f(e,i.u_dimension),u_zoom:new t.Uniform1f(e,i.u_zoom),u_maxzoom:new t.Uniform1f(e,i.u_maxzoom)}},line:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_ratio:new t.Uniform1f(e,i.u_ratio),u_device_pixel_ratio:new t.Uniform1f(e,i.u_device_pixel_ratio),u_units_to_pixels:new t.Uniform2f(e,i.u_units_to_pixels)}},lineGradient:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_ratio:new t.Uniform1f(e,i.u_ratio),u_device_pixel_ratio:new t.Uniform1f(e,i.u_device_pixel_ratio),u_units_to_pixels:new t.Uniform2f(e,i.u_units_to_pixels),u_image:new t.Uniform1i(e,i.u_image)}},linePattern:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_texsize:new t.Uniform2f(e,i.u_texsize),u_ratio:new t.Uniform1f(e,i.u_ratio),u_device_pixel_ratio:new t.Uniform1f(e,i.u_device_pixel_ratio),u_image:new t.Uniform1i(e,i.u_image),u_units_to_pixels:new t.Uniform2f(e,i.u_units_to_pixels),u_scale:new t.Uniform4f(e,i.u_scale),u_fade:new t.Uniform1f(e,i.u_fade)}},lineSDF:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_ratio:new t.Uniform1f(e,i.u_ratio),u_device_pixel_ratio:new t.Uniform1f(e,i.u_device_pixel_ratio),u_units_to_pixels:new t.Uniform2f(e,i.u_units_to_pixels),u_patternscale_a:new t.Uniform2f(e,i.u_patternscale_a),u_patternscale_b:new t.Uniform2f(e,i.u_patternscale_b),u_sdfgamma:new t.Uniform1f(e,i.u_sdfgamma),u_image:new t.Uniform1i(e,i.u_image),u_tex_y_a:new t.Uniform1f(e,i.u_tex_y_a),u_tex_y_b:new t.Uniform1f(e,i.u_tex_y_b),u_mix:new t.Uniform1f(e,i.u_mix)}},raster:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_tl_parent:new t.Uniform2f(e,i.u_tl_parent),u_scale_parent:new t.Uniform1f(e,i.u_scale_parent),u_buffer_scale:new t.Uniform1f(e,i.u_buffer_scale),u_fade_t:new t.Uniform1f(e,i.u_fade_t),u_opacity:new t.Uniform1f(e,i.u_opacity),u_image0:new t.Uniform1i(e,i.u_image0),u_image1:new t.Uniform1i(e,i.u_image1),u_brightness_low:new t.Uniform1f(e,i.u_brightness_low),u_brightness_high:new t.Uniform1f(e,i.u_brightness_high),u_saturation_factor:new t.Uniform1f(e,i.u_saturation_factor),u_contrast_factor:new t.Uniform1f(e,i.u_contrast_factor),u_spin_weights:new t.Uniform3f(e,i.u_spin_weights)}},symbolIcon:function(e,i){return {u_is_size_zoom_constant:new t.Uniform1i(e,i.u_is_size_zoom_constant),u_is_size_feature_constant:new t.Uniform1i(e,i.u_is_size_feature_constant),u_size_t:new t.Uniform1f(e,i.u_size_t),u_size:new t.Uniform1f(e,i.u_size),u_camera_to_center_distance:new t.Uniform1f(e,i.u_camera_to_center_distance),u_pitch:new t.Uniform1f(e,i.u_pitch),u_rotate_symbol:new t.Uniform1i(e,i.u_rotate_symbol),u_aspect_ratio:new t.Uniform1f(e,i.u_aspect_ratio),u_fade_change:new t.Uniform1f(e,i.u_fade_change),u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_label_plane_matrix:new t.UniformMatrix4f(e,i.u_label_plane_matrix),u_coord_matrix:new t.UniformMatrix4f(e,i.u_coord_matrix),u_is_text:new t.Uniform1f(e,i.u_is_text),u_pitch_with_map:new t.Uniform1i(e,i.u_pitch_with_map),u_texsize:new t.Uniform2f(e,i.u_texsize),u_texture:new t.Uniform1i(e,i.u_texture)}},symbolSDF:function(e,i){return {u_is_size_zoom_constant:new t.Uniform1i(e,i.u_is_size_zoom_constant),u_is_size_feature_constant:new t.Uniform1i(e,i.u_is_size_feature_constant),u_size_t:new t.Uniform1f(e,i.u_size_t),u_size:new t.Uniform1f(e,i.u_size),u_camera_to_center_distance:new t.Uniform1f(e,i.u_camera_to_center_distance),u_pitch:new t.Uniform1f(e,i.u_pitch),u_rotate_symbol:new t.Uniform1i(e,i.u_rotate_symbol),u_aspect_ratio:new t.Uniform1f(e,i.u_aspect_ratio),u_fade_change:new t.Uniform1f(e,i.u_fade_change),u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_label_plane_matrix:new t.UniformMatrix4f(e,i.u_label_plane_matrix),u_coord_matrix:new t.UniformMatrix4f(e,i.u_coord_matrix),u_is_text:new t.Uniform1f(e,i.u_is_text),u_pitch_with_map:new t.Uniform1i(e,i.u_pitch_with_map),u_texsize:new t.Uniform2f(e,i.u_texsize),u_texture:new t.Uniform1i(e,i.u_texture),u_gamma_scale:new t.Uniform1f(e,i.u_gamma_scale),u_device_pixel_ratio:new t.Uniform1f(e,i.u_device_pixel_ratio),u_is_halo:new t.Uniform1f(e,i.u_is_halo)}},background:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_opacity:new t.Uniform1f(e,i.u_opacity),u_color:new t.UniformColor(e,i.u_color)}},backgroundPattern:function(e,i){return {u_matrix:new t.UniformMatrix4f(e,i.u_matrix),u_opacity:new t.Uniform1f(e,i.u_opacity),u_image:new t.Uniform1i(e,i.u_image),u_pattern_tl_a:new t.Uniform2f(e,i.u_pattern_tl_a),u_pattern_br_a:new t.Uniform2f(e,i.u_pattern_br_a),u_pattern_tl_b:new t.Uniform2f(e,i.u_pattern_tl_b),u_pattern_br_b:new t.Uniform2f(e,i.u_pattern_br_b),u_texsize:new t.Uniform2f(e,i.u_texsize),u_mix:new t.Uniform1f(e,i.u_mix),u_pattern_size_a:new t.Uniform2f(e,i.u_pattern_size_a),u_pattern_size_b:new t.Uniform2f(e,i.u_pattern_size_b),u_scale_a:new t.Uniform1f(e,i.u_scale_a),u_scale_b:new t.Uniform1f(e,i.u_scale_b),u_pixel_coord_upper:new t.Uniform2f(e,i.u_pixel_coord_upper),u_pixel_coord_lower:new t.Uniform2f(e,i.u_pixel_coord_lower),u_tile_units_to_pixels:new t.Uniform1f(e,i.u_tile_units_to_pixels)}}};function qi(e,i){for(var o=e.sort(function(t,e){return t.tileID.isLessThan(e.tileID)?-1:e.tileID.isLessThan(t.tileID)?1:0}),r=0;r0){var s=t.browser.now(),l=(s-e.timeAdded)/n,c=i?(s-i.timeAdded)/n:-1,u=o.getSource(),h=a.coveringZoomLevel({tileSize:u.tileSize,roundZoom:u.roundZoom}),p=!i||Math.abs(i.tileID.overscaledZ-h)>Math.abs(e.tileID.overscaledZ-h),d=p&&e.refreshedUponExpiration?1:t.clamp(p?l:1-c,0,1);return e.refreshedUponExpiration&&l>=1&&(e.refreshedUponExpiration=!1),i?{opacity:1,mix:1-d}:{opacity:d,mix:0}}return {opacity:1,mix:0}}function io(e,i,o){var r=e.context,a=r.gl,n=o.posMatrix,s=e.useProgram("debug"),l=Tt.disabled,c=It.disabled,u=e.colorModeForRenderPass(),h="$debug";s.draw(r,a.LINE_STRIP,l,c,u,St.disabled,Ei(n,t.Color.red),h,e.debugBuffer,e.tileBorderIndexBuffer,e.debugSegments);for(var p=i.getTileByID(o.key).latestRawTileData,d=p&&p.byteLength||0,_=Math.floor(d/1024),f=function(t,e,i,o){o=o||1;var r,a,n,s,l,c,u,h,p=[];for(r=0,a=t.length;r":[24,[4,18,20,9,4,0]],"?":[18,[3,16,3,17,4,19,5,20,7,21,11,21,13,20,14,19,15,17,15,15,14,13,13,12,9,10,9,7,-1,-1,9,2,8,1,9,0,10,1,9,2]],"@":[27,[18,13,17,15,15,16,12,16,10,15,9,14,8,11,8,8,9,6,11,5,14,5,16,6,17,8,-1,-1,12,16,10,14,9,11,9,8,10,6,11,5,-1,-1,18,16,17,8,17,6,19,5,21,5,23,7,24,10,24,12,23,15,22,17,20,19,18,20,15,21,12,21,9,20,7,19,5,17,4,15,3,12,3,9,4,6,5,4,7,2,9,1,12,0,15,0,18,1,20,2,21,3,-1,-1,19,16,18,8,18,6,19,5]],A:[18,[9,21,1,0,-1,-1,9,21,17,0,-1,-1,4,7,14,7]],B:[21,[4,21,4,0,-1,-1,4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13,11,-1,-1,4,11,13,11,16,10,17,9,18,7,18,4,17,2,16,1,13,0,4,0]],C:[21,[18,16,17,18,15,20,13,21,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5]],D:[21,[4,21,4,0,-1,-1,4,21,11,21,14,20,16,18,17,16,18,13,18,8,17,5,16,3,14,1,11,0,4,0]],E:[19,[4,21,4,0,-1,-1,4,21,17,21,-1,-1,4,11,12,11,-1,-1,4,0,17,0]],F:[18,[4,21,4,0,-1,-1,4,21,17,21,-1,-1,4,11,12,11]],G:[21,[18,16,17,18,15,20,13,21,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,18,8,-1,-1,13,8,18,8]],H:[22,[4,21,4,0,-1,-1,18,21,18,0,-1,-1,4,11,18,11]],I:[8,[4,21,4,0]],J:[16,[12,21,12,5,11,2,10,1,8,0,6,0,4,1,3,2,2,5,2,7]],K:[21,[4,21,4,0,-1,-1,18,21,4,7,-1,-1,9,12,18,0]],L:[17,[4,21,4,0,-1,-1,4,0,16,0]],M:[24,[4,21,4,0,-1,-1,4,21,12,0,-1,-1,20,21,12,0,-1,-1,20,21,20,0]],N:[22,[4,21,4,0,-1,-1,4,21,18,0,-1,-1,18,21,18,0]],O:[22,[9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,19,8,19,13,18,16,17,18,15,20,13,21,9,21]],P:[21,[4,21,4,0,-1,-1,4,21,13,21,16,20,17,19,18,17,18,14,17,12,16,11,13,10,4,10]],Q:[22,[9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,19,8,19,13,18,16,17,18,15,20,13,21,9,21,-1,-1,12,4,18,-2]],R:[21,[4,21,4,0,-1,-1,4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13,11,4,11,-1,-1,11,11,18,0]],S:[20,[17,18,15,20,12,21,8,21,5,20,3,18,3,16,4,14,5,13,7,12,13,10,15,9,16,8,17,6,17,3,15,1,12,0,8,0,5,1,3,3]],T:[16,[8,21,8,0,-1,-1,1,21,15,21]],U:[22,[4,21,4,6,5,3,7,1,10,0,12,0,15,1,17,3,18,6,18,21]],V:[18,[1,21,9,0,-1,-1,17,21,9,0]],W:[24,[2,21,7,0,-1,-1,12,21,7,0,-1,-1,12,21,17,0,-1,-1,22,21,17,0]],X:[20,[3,21,17,0,-1,-1,17,21,3,0]],Y:[18,[1,21,9,11,9,0,-1,-1,17,21,9,11]],Z:[20,[17,21,3,0,-1,-1,3,21,17,21,-1,-1,3,0,17,0]],"[":[14,[4,25,4,-7,-1,-1,5,25,5,-7,-1,-1,4,25,11,25,-1,-1,4,-7,11,-7]],"\\":[14,[0,21,14,-3]],"]":[14,[9,25,9,-7,-1,-1,10,25,10,-7,-1,-1,3,25,10,25,-1,-1,3,-7,10,-7]],"^":[16,[6,15,8,18,10,15,-1,-1,3,12,8,17,13,12,-1,-1,8,17,8,0]],_:[16,[0,-2,16,-2]],"`":[10,[6,21,5,20,4,18,4,16,5,15,6,16,5,17]],a:[19,[15,14,15,0,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],b:[19,[4,21,4,0,-1,-1,4,11,6,13,8,14,11,14,13,13,15,11,16,8,16,6,15,3,13,1,11,0,8,0,6,1,4,3]],c:[18,[15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],d:[19,[15,21,15,0,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],e:[18,[3,8,15,8,15,10,14,12,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],f:[12,[10,21,8,21,6,20,5,17,5,0,-1,-1,2,14,9,14]],g:[19,[15,14,15,-2,14,-5,13,-6,11,-7,8,-7,6,-6,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],h:[19,[4,21,4,0,-1,-1,4,10,7,13,9,14,12,14,14,13,15,10,15,0]],i:[8,[3,21,4,20,5,21,4,22,3,21,-1,-1,4,14,4,0]],j:[10,[5,21,6,20,7,21,6,22,5,21,-1,-1,6,14,6,-3,5,-6,3,-7,1,-7]],k:[17,[4,21,4,0,-1,-1,14,14,4,4,-1,-1,8,8,15,0]],l:[8,[4,21,4,0]],m:[30,[4,14,4,0,-1,-1,4,10,7,13,9,14,12,14,14,13,15,10,15,0,-1,-1,15,10,18,13,20,14,23,14,25,13,26,10,26,0]],n:[19,[4,14,4,0,-1,-1,4,10,7,13,9,14,12,14,14,13,15,10,15,0]],o:[19,[8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3,16,6,16,8,15,11,13,13,11,14,8,14]],p:[19,[4,14,4,-7,-1,-1,4,11,6,13,8,14,11,14,13,13,15,11,16,8,16,6,15,3,13,1,11,0,8,0,6,1,4,3]],q:[19,[15,14,15,-7,-1,-1,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3]],r:[13,[4,14,4,0,-1,-1,4,8,5,11,7,13,9,14,12,14]],s:[17,[14,11,13,13,10,14,7,14,4,13,3,11,4,9,6,8,11,7,13,6,14,4,14,3,13,1,10,0,7,0,4,1,3,3]],t:[12,[5,21,5,4,6,1,8,0,10,0,-1,-1,2,14,9,14]],u:[19,[4,14,4,4,5,1,7,0,10,0,12,1,15,4,-1,-1,15,14,15,0]],v:[16,[2,14,8,0,-1,-1,14,14,8,0]],w:[22,[3,14,7,0,-1,-1,11,14,7,0,-1,-1,11,14,15,0,-1,-1,19,14,15,0]],x:[17,[3,14,14,0,-1,-1,14,14,3,0]],y:[16,[2,14,8,0,-1,-1,14,14,8,0,6,-4,4,-6,2,-7,1,-7]],z:[17,[14,14,3,0,-1,-1,3,14,14,14,-1,-1,3,0,14,0]],"{":[14,[9,25,7,24,6,23,5,21,5,19,6,17,7,16,8,14,8,12,6,10,-1,-1,7,24,6,22,6,20,7,18,8,17,9,15,9,13,8,11,4,9,8,7,9,5,9,3,8,1,7,0,6,-2,6,-4,7,-6,-1,-1,6,8,8,6,8,4,7,2,6,1,5,-1,5,-3,6,-5,7,-6,9,-7]],"|":[8,[4,25,4,-7]],"}":[14,[5,25,7,24,8,23,9,21,9,19,8,17,7,16,6,14,6,12,8,10,-1,-1,7,24,8,22,8,20,7,18,6,17,5,15,5,13,6,11,10,9,6,7,5,5,5,3,6,1,7,0,8,-2,8,-4,7,-6,-1,-1,8,8,6,6,6,4,7,2,8,1,9,-1,9,-3,8,-5,7,-6,5,-7]],"~":[24,[3,6,3,8,4,11,6,12,8,12,10,11,14,8,16,7,18,7,20,8,21,10,-1,-1,3,8,4,10,6,11,8,11,10,10,14,7,16,6,18,6,20,7,21,10,21,12]]};var ro={symbol:function(t,e,i,o,r){if("translucent"===t.renderPass){var a=It.disabled,n=t.colorModeForRenderPass();0!==i.paint.get("icon-opacity").constantOr(1)&&Ki(t,e,i,o,!1,i.paint.get("icon-translate"),i.paint.get("icon-translate-anchor"),i.layout.get("icon-rotation-alignment"),i.layout.get("icon-pitch-alignment"),i.layout.get("icon-keep-upright"),a,n,r),0!==i.paint.get("text-opacity").constantOr(1)&&Ki(t,e,i,o,!0,i.paint.get("text-translate"),i.paint.get("text-translate-anchor"),i.layout.get("text-rotation-alignment"),i.layout.get("text-pitch-alignment"),i.layout.get("text-keep-upright"),a,n,r),e.map.showCollisionBoxes&&function(t,e,i,o){Gi(t,e,i,o,!1),Gi(t,e,i,o,!0);}(t,e,i,o);}},circle:function(t,e,i,o){if("translucent"===t.renderPass){var r=i.paint.get("circle-opacity"),a=i.paint.get("circle-stroke-width"),n=i.paint.get("circle-stroke-opacity");if(0!==r.constantOr(1)||0!==a.constantOr(1)&&0!==n.constantOr(1))for(var s=t.context,l=s.gl,c=t.depthModeForSublayer(0,Tt.ReadOnly),u=It.disabled,h=t.colorModeForRenderPass(),p=0;pe.y){var i=t;t=e,e=i;}return {x0:t.x,y0:t.y,x1:e.x,y1:e.y,dx:e.x-t.x,dy:e.y-t.y}}function so(t,e,i,o,r){var a=Math.max(i,Math.floor(e.y0)),n=Math.min(o,Math.ceil(e.y1));if(t.x0===e.x0&&t.y0===e.y0?t.x0+e.dy/t.dy*t.dx0,h=e.dx<0,p=a;pl.dy&&(n=s,s=l,l=n),s.dy>c.dy&&(n=s,s=c,c=n),l.dy>c.dy&&(n=l,l=c,c=n),s.dy&&so(c,s,o,r,a),l.dy&&so(c,l,o,r,a);}ao.prototype.resize=function(e,i){var o=this.context.gl;if(this.width=e*t.browser.devicePixelRatio,this.height=i*t.browser.devicePixelRatio,this.context.viewport.set([0,0,this.width,this.height]),this.style)for(var r=0,a=this.style._order;r256&&this.clearStencil(),i.setColorMode(Ct.disabled),i.setDepthMode(Tt.disabled);var r=this.useProgram("clippingMask");this._tileClippingMaskIDs={};for(var a=0,n=e;a256&&this.clearStencil();var t=this.nextStencilID++,e=this.context.gl;return new It({func:e.NOTEQUAL,mask:255},t,255,e.KEEP,e.KEEP,e.REPLACE)},ao.prototype.stencilModeForClipping=function(t){var e=this.context.gl;return new It({func:e.EQUAL,mask:255},this._tileClippingMaskIDs[t.key],0,e.KEEP,e.KEEP,e.REPLACE)},ao.prototype.colorModeForRenderPass=function(){var e=this.context.gl;if(this._showOverdrawInspector){return new Ct([e.CONSTANT_COLOR,e.ONE],new t.Color(1/8,1/8,1/8,0),[!0,!0,!0,!0])}return "opaque"===this.renderPass?Ct.unblended:Ct.alphaBlended},ao.prototype.depthModeForSublayer=function(t,e,i){if(!this.opaquePassEnabledForLayer())return Tt.disabled;var o=1-((1+this.currentLayer)*this.numSublayers+t)*this.depthEpsilon;return new Tt(i||this.context.gl.LEQUAL,e,[o,o])},ao.prototype.opaquePassEnabledForLayer=function(){return this.currentLayer=0;this.currentLayer--){var C=this.style._layers[o[this.currentLayer]],S=r[C.source],P=s[C.source];this._renderTileClippingMasks(C,P),this.renderLayer(this,S,C,P);}for(this.renderPass="translucent",this.currentLayer=0;this.currentLayer0?e.pop():null},ao.prototype.isPatternMissing=function(t){if(!t)return !1;var e=this.imageManager.getPattern(t.from),i=this.imageManager.getPattern(t.to);return !e||!i},ao.prototype.useProgram=function(t,e){void 0===e&&(e=this.emptyProgramConfiguration),this.cache=this.cache||{};var i=""+t+(e.cacheKey||"")+(this._showOverdrawInspector?"/overdraw":"");return this.cache[i]||(this.cache[i]=new pi(this.context,ui[t],e,ji[t],this._showOverdrawInspector)),this.cache[i]},ao.prototype.setCustomLayerDefaults=function(){this.context.unbindVAO(),this.context.cullFace.setDefault(),this.context.activeTexture.setDefault(),this.context.pixelStoreUnpack.setDefault(),this.context.pixelStoreUnpackPremultiplyAlpha.setDefault(),this.context.pixelStoreUnpackFlipY.setDefault();},ao.prototype.setBaseState=function(){var t=this.context.gl;this.context.cullFace.set(!1),this.context.viewport.set([0,0,this.width,this.height]),this.context.blendEquation.set(t.FUNC_ADD);};var co=function(e,i,o){this.tileSize=512,this.maxValidLatitude=85.051129,this._renderWorldCopies=void 0===o||o,this._minZoom=e||0,this._maxZoom=i||22,this.setMaxBounds(),this.width=0,this.height=0,this._center=new t.LngLat(0,0),this.zoom=0,this.angle=0,this._fov=.6435011087932844,this._pitch=0,this._unmodified=!0,this._posMatrixCache={},this._alignedPosMatrixCache={};},uo={minZoom:{configurable:!0},maxZoom:{configurable:!0},renderWorldCopies:{configurable:!0},worldSize:{configurable:!0},centerPoint:{configurable:!0},size:{configurable:!0},bearing:{configurable:!0},pitch:{configurable:!0},fov:{configurable:!0},zoom:{configurable:!0},center:{configurable:!0},unmodified:{configurable:!0},point:{configurable:!0}};co.prototype.clone=function(){var t=new co(this._minZoom,this._maxZoom,this._renderWorldCopies);return t.tileSize=this.tileSize,t.latRange=this.latRange,t.width=this.width,t.height=this.height,t._center=this._center,t.zoom=this.zoom,t.angle=this.angle,t._fov=this._fov,t._pitch=this._pitch,t._unmodified=this._unmodified,t._calcMatrices(),t},uo.minZoom.get=function(){return this._minZoom},uo.minZoom.set=function(t){this._minZoom!==t&&(this._minZoom=t,this.zoom=Math.max(this.zoom,t));},uo.maxZoom.get=function(){return this._maxZoom},uo.maxZoom.set=function(t){this._maxZoom!==t&&(this._maxZoom=t,this.zoom=Math.min(this.zoom,t));},uo.renderWorldCopies.get=function(){return this._renderWorldCopies},uo.renderWorldCopies.set=function(t){void 0===t?t=!0:null===t&&(t=!1),this._renderWorldCopies=t;},uo.worldSize.get=function(){return this.tileSize*this.scale},uo.centerPoint.get=function(){return this.size._div(2)},uo.size.get=function(){return new t.Point(this.width,this.height)},uo.bearing.get=function(){return -this.angle/Math.PI*180},uo.bearing.set=function(e){var i=-t.wrap(e,-180,180)*Math.PI/180;this.angle!==i&&(this._unmodified=!1,this.angle=i,this._calcMatrices(),this.rotationMatrix=t.create$2(),t.rotate(this.rotationMatrix,this.rotationMatrix,this.angle));},uo.pitch.get=function(){return this._pitch/Math.PI*180},uo.pitch.set=function(e){var i=t.clamp(e,0,60)/180*Math.PI;this._pitch!==i&&(this._unmodified=!1,this._pitch=i,this._calcMatrices());},uo.fov.get=function(){return this._fov/Math.PI*180},uo.fov.set=function(t){t=Math.max(.01,Math.min(60,t)),this._fov!==t&&(this._unmodified=!1,this._fov=t/180*Math.PI,this._calcMatrices());},uo.zoom.get=function(){return this._zoom},uo.zoom.set=function(t){var e=Math.min(Math.max(t,this.minZoom),this.maxZoom);this._zoom!==e&&(this._unmodified=!1,this._zoom=e,this.scale=this.zoomScale(e),this.tileZoom=Math.floor(e),this.zoomFraction=e-this.tileZoom,this._constrain(),this._calcMatrices());},uo.center.get=function(){return this._center},uo.center.set=function(t){t.lat===this._center.lat&&t.lng===this._center.lng||(this._unmodified=!1,this._center=t,this._constrain(),this._calcMatrices());},co.prototype.coveringZoomLevel=function(t){return (t.roundZoom?Math.round:Math.floor)(this.zoom+this.scaleZoom(this.tileSize/t.tileSize))},co.prototype.getVisibleUnwrappedCoordinates=function(e){var i=[new t.UnwrappedTileID(0,e)];if(this._renderWorldCopies)for(var o=this.pointCoordinate(new t.Point(0,0)),r=this.pointCoordinate(new t.Point(this.width,0)),a=this.pointCoordinate(new t.Point(this.width,this.height)),n=this.pointCoordinate(new t.Point(0,this.height)),s=Math.floor(Math.min(o.x,r.x,a.x,n.x)),l=Math.floor(Math.max(o.x,r.x,a.x,n.x)),c=s-1;c<=l+1;c++)0!==c&&i.push(new t.UnwrappedTileID(c,e));return i},co.prototype.coveringTiles=function(e){var i=this.coveringZoomLevel(e),o=i;if(void 0!==e.minzoom&&ie.maxzoom&&(i=e.maxzoom);var r=t.MercatorCoordinate.fromLngLat(this.center),a=Math.pow(2,i),n=new t.Point(a*r.x-.5,a*r.y-.5);return function(e,i,o,r){void 0===r&&(r=!0);var a=1<=0&&l<=a)for(c=i;cn&&(r=n-m);}if(this.lngRange){var g=d.x,v=c.x/2;g-vl&&(o=l-v);}void 0===o&&void 0===r||(this.center=this.unproject(new t.Point(void 0!==o?o:d.x,void 0!==r?r:d.y))),this._unmodified=u,this._constraining=!1;}},co.prototype._calcMatrices=function(){if(this.height){this.cameraToCenterDistance=.5/Math.tan(this._fov/2)*this.height;var e=this._fov/2,i=Math.PI/2+this._pitch,o=Math.sin(e)*this.cameraToCenterDistance/Math.sin(Math.PI-i-e),r=this.point,a=r.x,n=r.y,s=1.01*(Math.cos(Math.PI/2-this._pitch)*o+this.cameraToCenterDistance),l=new Float64Array(16);t.perspective(l,this._fov,this.width/this.height,1,s),t.scale(l,l,[1,-1,1]),t.translate(l,l,[0,0,-this.cameraToCenterDistance]),t.rotateX(l,l,this._pitch),t.rotateZ(l,l,this.angle),t.translate(l,l,[-a,-n,0]),this.mercatorMatrix=t.scale([],l,[this.worldSize,this.worldSize,this.worldSize]),t.scale(l,l,[1,1,t.mercatorZfromAltitude(1,this.center.lat)*this.worldSize,1]),this.projMatrix=l;var c=this.width%2/2,u=this.height%2/2,h=Math.cos(this.angle),p=Math.sin(this.angle),d=a-Math.round(a)+h*c+p*u,_=n-Math.round(n)+h*u+p*c,f=new Float64Array(l);if(t.translate(f,f,[d>.5?d-1:d,_>.5?_-1:_,0]),this.alignedProjMatrix=f,l=t.create(),t.scale(l,l,[this.width/2,-this.height/2,1]),t.translate(l,l,[1,-1,0]),this.labelPlaneMatrix=l,l=t.create(),t.scale(l,l,[1,-1,1]),t.translate(l,l,[-1,-1,0]),t.scale(l,l,[2/this.width,2/this.height,1]),this.glCoordMatrix=l,this.pixelMatrix=t.multiply(new Float64Array(16),this.labelPlaneMatrix,this.projMatrix),!(l=t.invert(new Float64Array(16),this.pixelMatrix)))throw new Error("failed to invert matrix");this.pixelMatrixInverse=l,this._posMatrixCache={},this._alignedPosMatrixCache={};}},co.prototype.maxPitchScaleFactor=function(){if(!this.pixelMatrixInverse)return 1;var e=this.pointCoordinate(new t.Point(0,0)),i=[e.x*this.worldSize,e.y*this.worldSize,0,1];return t.transformMat4(i,i,this.pixelMatrix)[3]/this.cameraToCenterDistance},co.prototype.getCameraPoint=function(){var e=this._pitch,i=Math.tan(e)*(this.cameraToCenterDistance||1);return this.centerPoint.add(new t.Point(0,i))},co.prototype.getCameraQueryGeometry=function(e){var i=this.getCameraPoint();if(1===e.length)return [e[0],i];for(var o=i.x,r=i.y,a=i.x,n=i.y,s=0,l=e;s=3&&(this._map.jumpTo({center:[+e[2],+e[1]],zoom:+e[0],bearing:+(e[3]||0),pitch:+(e[4]||0)}),!0)},ho.prototype._updateHashUnthrottled=function(){var e=this.getHashString();try{t.window.history.replaceState(t.window.history.state,"",e);}catch(t){}};var po=function(e){function o(o,r,a,n){void 0===n&&(n={});var s=i.mousePos(r.getCanvasContainer(),a),l=r.unproject(s);e.call(this,o,t.extend({point:s,lngLat:l,originalEvent:a},n)),this._defaultPrevented=!1,this.target=r;}e&&(o.__proto__=e),o.prototype=Object.create(e&&e.prototype),o.prototype.constructor=o;var r={defaultPrevented:{configurable:!0}};return o.prototype.preventDefault=function(){this._defaultPrevented=!0;},r.defaultPrevented.get=function(){return this._defaultPrevented},Object.defineProperties(o.prototype,r),o}(t.Event),_o=function(e){function o(o,r,a){var n=i.touchPos(r.getCanvasContainer(),a),s=n.map(function(t){return r.unproject(t)}),l=n.reduce(function(t,e,i,o){return t.add(e.div(o.length))},new t.Point(0,0)),c=r.unproject(l);e.call(this,o,{points:n,point:l,lngLats:s,lngLat:c,originalEvent:a}),this._defaultPrevented=!1;}e&&(o.__proto__=e),o.prototype=Object.create(e&&e.prototype),o.prototype.constructor=o;var r={defaultPrevented:{configurable:!0}};return o.prototype.preventDefault=function(){this._defaultPrevented=!0;},r.defaultPrevented.get=function(){return this._defaultPrevented},Object.defineProperties(o.prototype,r),o}(t.Event),fo=function(t){function e(e,i,o){t.call(this,e,{originalEvent:o}),this._defaultPrevented=!1;}t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e;var i={defaultPrevented:{configurable:!0}};return e.prototype.preventDefault=function(){this._defaultPrevented=!0;},i.defaultPrevented.get=function(){return this._defaultPrevented},Object.defineProperties(e.prototype,i),e}(t.Event),mo=function(e){this._map=e,this._el=e.getCanvasContainer(),this._delta=0,this._defaultZoomRate=.01,this._wheelZoomRate=1/450,t.bindAll(["_onWheel","_onTimeout","_onScrollFrame","_onScrollFinished"],this);};mo.prototype.setZoomRate=function(t){this._defaultZoomRate=t;},mo.prototype.setWheelZoomRate=function(t){this._wheelZoomRate=t;},mo.prototype.isEnabled=function(){return !!this._enabled},mo.prototype.isActive=function(){return !!this._active},mo.prototype.isZooming=function(){return !!this._zooming},mo.prototype.enable=function(t){this.isEnabled()||(this._enabled=!0,this._aroundCenter=t&&"center"===t.around);},mo.prototype.disable=function(){this.isEnabled()&&(this._enabled=!1);},mo.prototype.onWheel=function(e){if(this.isEnabled()){var i=e.deltaMode===t.window.WheelEvent.DOM_DELTA_LINE?40*e.deltaY:e.deltaY,o=t.browser.now(),r=o-(this._lastWheelEventTime||0);this._lastWheelEventTime=o,0!==i&&i%4.000244140625==0?this._type="wheel":0!==i&&Math.abs(i)<4?this._type="trackpad":r>400?(this._type=null,this._lastValue=i,this._timeout=setTimeout(this._onTimeout,40,e)):this._type||(this._type=Math.abs(r*i)<200?"trackpad":"wheel",this._timeout&&(clearTimeout(this._timeout),this._timeout=null,i+=this._lastValue)),e.shiftKey&&i&&(i/=4),this._type&&(this._lastWheelEvent=e,this._delta-=i,this.isActive()||this._start(e)),e.preventDefault();}},mo.prototype._onTimeout=function(t){this._type="wheel",this._delta-=this._lastValue,this.isActive()||this._start(t);},mo.prototype._start=function(e){if(this._delta){this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),this._active=!0,this.isZooming()||(this._zooming=!0,this._map.fire(new t.Event("movestart",{originalEvent:e})),this._map.fire(new t.Event("zoomstart",{originalEvent:e}))),this._finishTimeout&&clearTimeout(this._finishTimeout);var o=i.mousePos(this._el,e);this._around=t.LngLat.convert(this._aroundCenter?this._map.getCenter():this._map.unproject(o)),this._aroundPoint=this._map.transform.locationPoint(this._around),this._frameId||(this._frameId=this._map._requestRenderFrame(this._onScrollFrame));}},mo.prototype._onScrollFrame=function(){var e=this;if(this._frameId=null,this.isActive()){var i=this._map.transform;if(0!==this._delta){var o="wheel"===this._type&&Math.abs(this._delta)>4.000244140625?this._wheelZoomRate:this._defaultZoomRate,r=2/(1+Math.exp(-Math.abs(this._delta*o)));this._delta<0&&0!==r&&(r=1/r);var a="number"==typeof this._targetZoom?i.zoomScale(this._targetZoom):i.scale;this._targetZoom=Math.min(i.maxZoom,Math.max(i.minZoom,i.scaleZoom(a*r))),"wheel"===this._type&&(this._startZoom=i.zoom,this._easing=this._smoothOutEasing(200)),this._delta=0;}var n="number"==typeof this._targetZoom?this._targetZoom:i.zoom,s=this._startZoom,l=this._easing,c=!1;if("wheel"===this._type&&s&&l){var u=Math.min((t.browser.now()-this._lastWheelEventTime)/200,1),h=l(u);i.zoom=t.number(s,n,h),u<1?this._frameId||(this._frameId=this._map._requestRenderFrame(this._onScrollFrame)):c=!0;}else i.zoom=n,c=!0;i.setLocationAtPoint(this._around,this._aroundPoint),this._map.fire(new t.Event("move",{originalEvent:this._lastWheelEvent})),this._map.fire(new t.Event("zoom",{originalEvent:this._lastWheelEvent})),c&&(this._active=!1,this._finishTimeout=setTimeout(function(){e._zooming=!1,e._map.fire(new t.Event("zoomend",{originalEvent:e._lastWheelEvent})),e._map.fire(new t.Event("moveend",{originalEvent:e._lastWheelEvent})),delete e._targetZoom;},200));}},mo.prototype._smoothOutEasing=function(e){var i=t.ease;if(this._prevEase){var o=this._prevEase,r=(t.browser.now()-o.start)/o.duration,a=o.easing(r+.01)-o.easing(r),n=.27/Math.sqrt(a*a+1e-4)*.01,s=Math.sqrt(.0729-n*n);i=t.bezier(n,s,.25,1);}return this._prevEase={start:t.browser.now(),duration:e,easing:i},i};var go=function(e,i){this._map=e,this._el=e.getCanvasContainer(),this._container=e.getContainer(),this._clickTolerance=i.clickTolerance||1,t.bindAll(["_onMouseMove","_onMouseUp","_onKeyDown"],this);};go.prototype.isEnabled=function(){return !!this._enabled},go.prototype.isActive=function(){return !!this._active},go.prototype.enable=function(){this.isEnabled()||(this._enabled=!0);},go.prototype.disable=function(){this.isEnabled()&&(this._enabled=!1);},go.prototype.onMouseDown=function(e){this.isEnabled()&&e.shiftKey&&0===e.button&&(t.window.document.addEventListener("mousemove",this._onMouseMove,!1),t.window.document.addEventListener("keydown",this._onKeyDown,!1),t.window.document.addEventListener("mouseup",this._onMouseUp,!1),i.disableDrag(),this._startPos=this._lastPos=i.mousePos(this._el,e),this._active=!0);},go.prototype._onMouseMove=function(t){var e=i.mousePos(this._el,t);if(!(this._lastPos.equals(e)||!this._box&&e.dist(this._startPos)180&&(d=180);var _=d/180;c+=h*d*(_/2),Math.abs(i._normalizeBearing(c,0))0&&i-e[0][0]>160;)e.shift();};var xo=t.bezier(0,0,.3,1),bo=function(e,i){this._map=e,this._el=e.getCanvasContainer(),this._state="disabled",this._clickTolerance=i.clickTolerance||1,t.bindAll(["_onMove","_onMouseUp","_onTouchEnd","_onBlur","_onDragFrame"],this);};bo.prototype.isEnabled=function(){return "disabled"!==this._state},bo.prototype.isActive=function(){return "active"===this._state},bo.prototype.enable=function(){this.isEnabled()||(this._el.classList.add("mapboxgl-touch-drag-pan"),this._state="enabled");},bo.prototype.disable=function(){if(this.isEnabled())switch(this._el.classList.remove("mapboxgl-touch-drag-pan"),this._state){case"active":this._state="disabled",this._unbind(),this._deactivate(),this._fireEvent("dragend"),this._fireEvent("moveend");break;case"pending":this._state="disabled",this._unbind();break;default:this._state="disabled";}},bo.prototype.onMouseDown=function(e){"enabled"===this._state&&(e.ctrlKey||0!==i.mouseButton(e)||(i.addEventListener(t.window.document,"mousemove",this._onMove,{capture:!0}),i.addEventListener(t.window.document,"mouseup",this._onMouseUp),this._start(e)));},bo.prototype.onTouchStart=function(e){"enabled"===this._state&&(e.touches.length>1||(i.addEventListener(t.window.document,"touchmove",this._onMove,{capture:!0,passive:!1}),i.addEventListener(t.window.document,"touchend",this._onTouchEnd),this._start(e)));},bo.prototype._start=function(e){t.window.addEventListener("blur",this._onBlur),this._state="pending",this._startPos=this._mouseDownPos=this._lastPos=i.mousePos(this._el,e),this._inertia=[[t.browser.now(),this._startPos]];},bo.prototype._onMove=function(e){e.preventDefault();var o=i.mousePos(this._el,e);this._lastPos.equals(o)||"pending"===this._state&&o.dist(this._mouseDownPos)1400&&(s=1400,n._unit()._mult(s));var l=s/750,c=n.mult(-l/2);this._map.panBy(c,{duration:1e3*l,easing:xo,noMoveStart:!0},{originalEvent:t});}}},bo.prototype._fireEvent=function(e,i){return this._map.fire(new t.Event(e,i?{originalEvent:i}:{}))},bo.prototype._drainInertiaBuffer=function(){for(var e=this._inertia,i=t.browser.now();e.length>0&&i-e[0][0]>160;)e.shift();};var wo=function(e){this._map=e,this._el=e.getCanvasContainer(),t.bindAll(["_onKeyDown"],this);};function Eo(t){return t*(2-t)}wo.prototype.isEnabled=function(){return !!this._enabled},wo.prototype.enable=function(){this.isEnabled()||(this._el.addEventListener("keydown",this._onKeyDown,!1),this._enabled=!0);},wo.prototype.disable=function(){this.isEnabled()&&(this._el.removeEventListener("keydown",this._onKeyDown),this._enabled=!1);},wo.prototype._onKeyDown=function(t){if(!(t.altKey||t.ctrlKey||t.metaKey)){var e=0,i=0,o=0,r=0,a=0;switch(t.keyCode){case 61:case 107:case 171:case 187:e=1;break;case 189:case 109:case 173:e=-1;break;case 37:t.shiftKey?i=-1:(t.preventDefault(),r=-1);break;case 39:t.shiftKey?i=1:(t.preventDefault(),r=1);break;case 38:t.shiftKey?o=1:(t.preventDefault(),a=-1);break;case 40:t.shiftKey?o=-1:(a=1,t.preventDefault());break;default:return}var n=this._map,s=n.getZoom(),l={duration:300,delayEndEvents:500,easing:Eo,zoom:e?Math.round(s)+e*(t.shiftKey?2:1):s,bearing:n.getBearing()+15*i,pitch:n.getPitch()+10*o,offset:[100*-r,100*-a],center:n.getCenter()};n.easeTo(l,{originalEvent:t});}};var To=function(e){this._map=e,t.bindAll(["_onDblClick","_onZoomEnd"],this);};To.prototype.isEnabled=function(){return !!this._enabled},To.prototype.isActive=function(){return !!this._active},To.prototype.enable=function(){this.isEnabled()||(this._enabled=!0);},To.prototype.disable=function(){this.isEnabled()&&(this._enabled=!1);},To.prototype.onTouchStart=function(t){var e=this;if(this.isEnabled()&&!(t.points.length>1))if(this._tapped){var i=t.points[0],o=this._tappedPoint;if(o&&o.dist(i)<=30){t.originalEvent.preventDefault();var r=function(){e._tapped&&e._zoom(t),e._map.off("touchcancel",a),e._resetTapped();},a=function(){e._map.off("touchend",r),e._resetTapped();};this._map.once("touchend",r),this._map.once("touchcancel",a);}else this._resetTapped();}else this._tappedPoint=t.points[0],this._tapped=setTimeout(function(){e._tapped=null,e._tappedPoint=null;},300);},To.prototype._resetTapped=function(){clearTimeout(this._tapped),this._tapped=null,this._tappedPoint=null;},To.prototype.onDblClick=function(t){this.isEnabled()&&(t.originalEvent.preventDefault(),this._zoom(t));},To.prototype._zoom=function(t){this._active=!0,this._map.on("zoomend",this._onZoomEnd),this._map.zoomTo(this._map.getZoom()+(t.originalEvent.shiftKey?-1:1),{around:t.lngLat},t);},To.prototype._onZoomEnd=function(){this._active=!1,this._map.off("zoomend",this._onZoomEnd);};var Io=t.bezier(0,0,.15,1),Co=function(e){this._map=e,this._el=e.getCanvasContainer(),t.bindAll(["_onMove","_onEnd","_onTouchFrame"],this);};Co.prototype.isEnabled=function(){return !!this._enabled},Co.prototype.enable=function(t){this.isEnabled()||(this._el.classList.add("mapboxgl-touch-zoom-rotate"),this._enabled=!0,this._aroundCenter=!!t&&"center"===t.around);},Co.prototype.disable=function(){this.isEnabled()&&(this._el.classList.remove("mapboxgl-touch-zoom-rotate"),this._enabled=!1);},Co.prototype.disableRotation=function(){this._rotationDisabled=!0;},Co.prototype.enableRotation=function(){this._rotationDisabled=!1;},Co.prototype.onStart=function(e){if(this.isEnabled()&&2===e.touches.length){var o=i.mousePos(this._el,e.touches[0]),r=i.mousePos(this._el,e.touches[1]),a=o.add(r).div(2);this._startVec=o.sub(r),this._startAround=this._map.transform.pointLocation(a),this._gestureIntent=void 0,this._inertia=[],i.addEventListener(t.window.document,"touchmove",this._onMove,{passive:!1}),i.addEventListener(t.window.document,"touchend",this._onEnd);}},Co.prototype._getTouchEventData=function(t){var e=i.mousePos(this._el,t.touches[0]),o=i.mousePos(this._el,t.touches[1]),r=e.sub(o);return {vec:r,center:e.add(o).div(2),scale:r.mag()/this._startVec.mag(),bearing:this._rotationDisabled?0:180*r.angleWith(this._startVec)/Math.PI}},Co.prototype._onMove=function(e){if(2===e.touches.length){var i=this._getTouchEventData(e),o=i.vec,r=i.scale,a=i.bearing;if(!this._gestureIntent){var n=this._rotationDisabled&&1!==r||Math.abs(1-r)>.15;Math.abs(a)>10?this._gestureIntent="rotate":n&&(this._gestureIntent="zoom"),this._gestureIntent&&(this._map.fire(new t.Event(this._gestureIntent+"start",{originalEvent:e})),this._map.fire(new t.Event("movestart",{originalEvent:e})),this._startVec=o);}this._lastTouchEvent=e,this._frameId||(this._frameId=this._map._requestRenderFrame(this._onTouchFrame)),e.preventDefault();}},Co.prototype._onTouchFrame=function(){this._frameId=null;var e=this._gestureIntent;if(e){var i=this._map.transform;this._startScale||(this._startScale=i.scale,this._startBearing=i.bearing);var o=this._getTouchEventData(this._lastTouchEvent),r=o.center,a=o.bearing,n=o.scale,s=i.pointLocation(r),l=i.locationPoint(s);"rotate"===e&&(i.bearing=this._startBearing+a),i.zoom=i.scaleZoom(this._startScale*n),i.setLocationAtPoint(this._startAround,l),this._map.fire(new t.Event(e,{originalEvent:this._lastTouchEvent})),this._map.fire(new t.Event("move",{originalEvent:this._lastTouchEvent})),this._drainInertiaBuffer(),this._inertia.push([t.browser.now(),n,r]);}},Co.prototype._onEnd=function(e){i.removeEventListener(t.window.document,"touchmove",this._onMove,{passive:!1}),i.removeEventListener(t.window.document,"touchend",this._onEnd);var o=this._gestureIntent,r=this._startScale;if(this._frameId&&(this._map._cancelRenderFrame(this._frameId),this._frameId=null),delete this._gestureIntent,delete this._startScale,delete this._startBearing,delete this._lastTouchEvent,o){this._map.fire(new t.Event(o+"end",{originalEvent:e})),this._drainInertiaBuffer();var a=this._inertia,n=this._map;if(a.length<2)n.snapToNorth({},{originalEvent:e});else{var s=a[a.length-1],l=a[0],c=n.transform.scaleZoom(r*s[1]),u=n.transform.scaleZoom(r*l[1]),h=c-u,p=(s[0]-l[0])/1e3,d=s[2];if(0!==p&&c!==u){var _=.15*h/p;Math.abs(_)>2.5&&(_=_>0?2.5:-2.5);var f=1e3*Math.abs(_/(12*.15)),m=c+_*f/2e3;m<0&&(m=0),n.easeTo({zoom:m,duration:f,easing:Io,around:this._aroundCenter?n.getCenter():n.unproject(d),noMoveStart:!0},{originalEvent:e});}else n.snapToNorth({},{originalEvent:e});}}},Co.prototype._drainInertiaBuffer=function(){for(var e=this._inertia,i=t.browser.now();e.length>2&&i-e[0][0]>160;)e.shift();};var So={scrollZoom:mo,boxZoom:go,dragRotate:yo,dragPan:bo,keyboard:wo,doubleClickZoom:To,touchZoomRotate:Co};var Po=function(e){function i(i,o){e.call(this),this._moving=!1,this._zooming=!1,this.transform=i,this._bearingSnap=o.bearingSnap,t.bindAll(["_renderFrameCallback"],this);}return e&&(i.__proto__=e),i.prototype=Object.create(e&&e.prototype),i.prototype.constructor=i,i.prototype.getCenter=function(){return new t.LngLat(this.transform.center.lng,this.transform.center.lat)},i.prototype.setCenter=function(t,e){return this.jumpTo({center:t},e)},i.prototype.panBy=function(e,i,o){return e=t.Point.convert(e).mult(-1),this.panTo(this.transform.center,t.extend({offset:e},i),o)},i.prototype.panTo=function(e,i,o){return this.easeTo(t.extend({center:e},i),o)},i.prototype.getZoom=function(){return this.transform.zoom},i.prototype.setZoom=function(t,e){return this.jumpTo({zoom:t},e),this},i.prototype.zoomTo=function(e,i,o){return this.easeTo(t.extend({zoom:e},i),o)},i.prototype.zoomIn=function(t,e){return this.zoomTo(this.getZoom()+1,t,e),this},i.prototype.zoomOut=function(t,e){return this.zoomTo(this.getZoom()-1,t,e),this},i.prototype.getBearing=function(){return this.transform.bearing},i.prototype.setBearing=function(t,e){return this.jumpTo({bearing:t},e),this},i.prototype.rotateTo=function(e,i,o){return this.easeTo(t.extend({bearing:e},i),o)},i.prototype.resetNorth=function(e,i){return this.rotateTo(0,t.extend({duration:1e3},e),i),this},i.prototype.snapToNorth=function(t,e){return Math.abs(this.getBearing())e?1:0}),["bottom","left","right","top"])){var n=this.transform,s=n.project(t.LngLat.convert(e)),l=n.project(t.LngLat.convert(i)),c=s.rotate(-o*Math.PI/180),u=l.rotate(-o*Math.PI/180),h=new t.Point(Math.max(c.x,u.x),Math.max(c.y,u.y)),p=new t.Point(Math.min(c.x,u.x),Math.min(c.y,u.y)),d=h.sub(p),_=(n.width-r.padding.left-r.padding.right)/d.x,f=(n.height-r.padding.top-r.padding.bottom)/d.y;if(!(f<0||_<0)){var m=Math.min(n.scaleZoom(n.scale*Math.min(_,f)),r.maxZoom),g=t.Point.convert(r.offset),v=(r.padding.left-r.padding.right)/2,y=(r.padding.top-r.padding.bottom)/2,x=new t.Point(g.x+v,g.y+y).mult(n.scale/n.zoomScale(m));return {center:n.unproject(s.add(l).div(2).sub(x)),zoom:m,bearing:o}}t.warnOnce("Map cannot fit within canvas with the given bounds, padding, and/or offset.");}else t.warnOnce("options.padding must be a positive number, or an Object with keys 'bottom', 'left', 'right', 'top'");},i.prototype.fitBounds=function(t,e,i){return this._fitInternal(this.cameraForBounds(t,e),e,i)},i.prototype.fitScreenCoordinates=function(e,i,o,r,a){return this._fitInternal(this._cameraForBoxAndBearing(this.transform.pointLocation(t.Point.convert(e)),this.transform.pointLocation(t.Point.convert(i)),o,r),r,a)},i.prototype._fitInternal=function(e,i,o){return e?(i=t.extend(e,i)).linear?this.easeTo(i,o):this.flyTo(i,o):this},i.prototype.jumpTo=function(e,i){this.stop();var o=this.transform,r=!1,a=!1,n=!1;return "zoom"in e&&o.zoom!==+e.zoom&&(r=!0,o.zoom=+e.zoom),void 0!==e.center&&(o.center=t.LngLat.convert(e.center)),"bearing"in e&&o.bearing!==+e.bearing&&(a=!0,o.bearing=+e.bearing),"pitch"in e&&o.pitch!==+e.pitch&&(n=!0,o.pitch=+e.pitch),this.fire(new t.Event("movestart",i)).fire(new t.Event("move",i)),r&&this.fire(new t.Event("zoomstart",i)).fire(new t.Event("zoom",i)).fire(new t.Event("zoomend",i)),a&&this.fire(new t.Event("rotatestart",i)).fire(new t.Event("rotate",i)).fire(new t.Event("rotateend",i)),n&&this.fire(new t.Event("pitchstart",i)).fire(new t.Event("pitch",i)).fire(new t.Event("pitchend",i)),this.fire(new t.Event("moveend",i))},i.prototype.easeTo=function(e,i){var o=this;this.stop(),!1===(e=t.extend({offset:[0,0],duration:500,easing:t.ease},e)).animate&&(e.duration=0);var r=this.transform,a=this.getZoom(),n=this.getBearing(),s=this.getPitch(),l="zoom"in e?+e.zoom:a,c="bearing"in e?this._normalizeBearing(e.bearing,n):n,u="pitch"in e?+e.pitch:s,h=r.centerPoint.add(t.Point.convert(e.offset)),p=r.pointLocation(h),d=t.LngLat.convert(e.center||p);this._normalizeCenter(d);var _,f,m=r.project(p),g=r.project(d).sub(m),v=r.zoomScale(l-a);return e.around&&(_=t.LngLat.convert(e.around),f=r.locationPoint(_)),this._zooming=l!==a,this._rotating=n!==c,this._pitching=u!==s,this._prepareEase(i,e.noMoveStart),clearTimeout(this._easeEndTimeoutID),this._ease(function(e){if(o._zooming&&(r.zoom=t.number(a,l,e)),o._rotating&&(r.bearing=t.number(n,c,e)),o._pitching&&(r.pitch=t.number(s,u,e)),_)r.setLocationAtPoint(_,f);else{var p=r.zoomScale(r.zoom-a),d=l>a?Math.min(2,v):Math.max(.5,v),y=Math.pow(d,1-e),x=r.unproject(m.add(g.mult(e*y)).mult(p));r.setLocationAtPoint(r.renderWorldCopies?x.wrap():x,h);}o._fireMoveEvents(i);},function(){e.delayEndEvents?o._easeEndTimeoutID=setTimeout(function(){return o._afterEase(i)},e.delayEndEvents):o._afterEase(i);},e),this},i.prototype._prepareEase=function(e,i){this._moving=!0,i||this.fire(new t.Event("movestart",e)),this._zooming&&this.fire(new t.Event("zoomstart",e)),this._rotating&&this.fire(new t.Event("rotatestart",e)),this._pitching&&this.fire(new t.Event("pitchstart",e));},i.prototype._fireMoveEvents=function(e){this.fire(new t.Event("move",e)),this._zooming&&this.fire(new t.Event("zoom",e)),this._rotating&&this.fire(new t.Event("rotate",e)),this._pitching&&this.fire(new t.Event("pitch",e));},i.prototype._afterEase=function(e){var i=this._zooming,o=this._rotating,r=this._pitching;this._moving=!1,this._zooming=!1,this._rotating=!1,this._pitching=!1,i&&this.fire(new t.Event("zoomend",e)),o&&this.fire(new t.Event("rotateend",e)),r&&this.fire(new t.Event("pitchend",e)),this.fire(new t.Event("moveend",e));},i.prototype.flyTo=function(e,i){var o=this;this.stop(),e=t.extend({offset:[0,0],speed:1.2,curve:1.42,easing:t.ease},e);var r=this.transform,a=this.getZoom(),n=this.getBearing(),s=this.getPitch(),l="zoom"in e?t.clamp(+e.zoom,r.minZoom,r.maxZoom):a,c="bearing"in e?this._normalizeBearing(e.bearing,n):n,u="pitch"in e?+e.pitch:s,h=r.zoomScale(l-a),p=r.centerPoint.add(t.Point.convert(e.offset)),d=r.pointLocation(p),_=t.LngLat.convert(e.center||d);this._normalizeCenter(_);var f=r.project(d),m=r.project(_).sub(f),g=e.curve,v=Math.max(r.width,r.height),y=v/h,x=m.mag();if("minZoom"in e){var b=t.clamp(Math.min(e.minZoom,a,l),r.minZoom,r.maxZoom),w=v/r.zoomScale(b-a);g=Math.sqrt(w/x*2);}var E=g*g;function T(t){var e=(y*y-v*v+(t?-1:1)*E*E*x*x)/(2*(t?y:v)*E*x);return Math.log(Math.sqrt(e*e+1)-e)}function I(t){return (Math.exp(t)-Math.exp(-t))/2}function C(t){return (Math.exp(t)+Math.exp(-t))/2}var S=T(0),P=function(t){return C(S)/C(S+g*t)},z=function(t){return v*((C(S)*(I(e=S+g*t)/C(e))-I(S))/E)/x;var e;},L=(T(1)-S)/g;if(Math.abs(x)<1e-6||!isFinite(L)){if(Math.abs(v-y)<1e-6)return this.easeTo(e,i);var D=ye.maxDuration&&(e.duration=0),this._zooming=!0,this._rotating=n!==c,this._pitching=u!==s,this._prepareEase(i,!1),this._ease(function(e){var h=e*L,d=1/P(h);r.zoom=1===e?l:a+r.scaleZoom(d),o._rotating&&(r.bearing=t.number(n,c,e)),o._pitching&&(r.pitch=t.number(s,u,e));var g=1===e?_:r.unproject(f.add(m.mult(z(h))).mult(d));r.setLocationAtPoint(r.renderWorldCopies?g.wrap():g,p),o._fireMoveEvents(i);},function(){return o._afterEase(i)},e),this},i.prototype.isEasing=function(){return !!this._easeFrameId},i.prototype.stop=function(){if(this._easeFrameId&&(this._cancelRenderFrame(this._easeFrameId),delete this._easeFrameId,delete this._onEaseFrame),this._onEaseEnd){var t=this._onEaseEnd;delete this._onEaseEnd,t.call(this);}return this},i.prototype._ease=function(e,i,o){!1===o.animate||0===o.duration?(e(1),i()):(this._easeStart=t.browser.now(),this._easeOptions=o,this._onEaseFrame=e,this._onEaseEnd=i,this._easeFrameId=this._requestRenderFrame(this._renderFrameCallback));},i.prototype._renderFrameCallback=function(){var e=Math.min((t.browser.now()-this._easeStart)/this._easeOptions.duration,1);this._onEaseFrame(this._easeOptions.easing(e)),e<1?this._easeFrameId=this._requestRenderFrame(this._renderFrameCallback):this.stop();},i.prototype._normalizeBearing=function(e,i){e=t.wrap(e,-180,180);var o=Math.abs(e-i);return Math.abs(e-360-i)180?-360:i<-180?360:0;}},i}(t.Evented),zo=function(e){void 0===e&&(e={}),this.options=e,t.bindAll(["_updateEditLink","_updateData","_updateCompact"],this);};zo.prototype.getDefaultPosition=function(){return "bottom-right"},zo.prototype.onAdd=function(t){var e=this.options&&this.options.compact;return this._map=t,this._container=i.create("div","mapboxgl-ctrl mapboxgl-ctrl-attrib"),this._innerContainer=i.create("div","mapboxgl-ctrl-attrib-inner",this._container),e&&this._container.classList.add("mapboxgl-compact"),this._updateAttributions(),this._updateEditLink(),this._map.on("styledata",this._updateData),this._map.on("sourcedata",this._updateData),this._map.on("moveend",this._updateEditLink),void 0===e&&(this._map.on("resize",this._updateCompact),this._updateCompact()),this._container},zo.prototype.onRemove=function(){i.remove(this._container),this._map.off("styledata",this._updateData),this._map.off("sourcedata",this._updateData),this._map.off("moveend",this._updateEditLink),this._map.off("resize",this._updateCompact),this._map=void 0;},zo.prototype._updateEditLink=function(){var e=this._editLink;e||(e=this._editLink=this._container.querySelector(".mapbox-improve-map"));var i=[{key:"owner",value:this.styleOwner},{key:"id",value:this.styleId},{key:"access_token",value:t.config.ACCESS_TOKEN}];if(e){var o=i.reduce(function(t,e,o){return e.value&&(t+=e.key+"="+e.value+(o=0)return !1;return !0})).join(" | ");n!==this._attribHTML&&(this._attribHTML=n,t.length?(this._innerContainer.innerHTML=n,this._container.classList.remove("mapboxgl-attrib-empty")):this._container.classList.add("mapboxgl-attrib-empty"),this._editLink=null);}},zo.prototype._updateCompact=function(){this._map.getCanvasContainer().offsetWidth<=640?this._container.classList.add("mapboxgl-compact"):this._container.classList.remove("mapboxgl-compact");};var Lo=function(){t.bindAll(["_updateLogo"],this),t.bindAll(["_updateCompact"],this);};Lo.prototype.onAdd=function(t){this._map=t,this._container=i.create("div","mapboxgl-ctrl");var e=i.create("a","mapboxgl-ctrl-logo");return e.target="_blank",e.rel="noopener nofollow",e.href="https://www.mapbox.com/",e.setAttribute("aria-label","Mapbox logo"),e.setAttribute("rel","noopener nofollow"),this._container.appendChild(e),this._container.style.display="none",this._map.on("sourcedata",this._updateLogo),this._updateLogo(),this._map.on("resize",this._updateCompact),this._updateCompact(),this._container},Lo.prototype.onRemove=function(){i.remove(this._container),this._map.off("sourcedata",this._updateLogo),this._map.off("resize",this._updateCompact);},Lo.prototype.getDefaultPosition=function(){return "bottom-left"},Lo.prototype._updateLogo=function(t){t&&"metadata"!==t.sourceDataType||(this._container.style.display=this._logoRequired()?"block":"none");},Lo.prototype._logoRequired=function(){if(this._map.style){var t=this._map.style.sourceCaches;for(var e in t){if(t[e].getSource().mapbox_logo)return !0}return !1}},Lo.prototype._updateCompact=function(){var t=this._container.children;if(t.length){var e=t[0];this._map.getCanvasContainer().offsetWidth<250?e.classList.add("mapboxgl-compact"):e.classList.remove("mapboxgl-compact");}};var Do=function(){this._queue=[],this._id=0,this._cleared=!1,this._currentlyRunning=!1;};Do.prototype.add=function(t){var e=++this._id;return this._queue.push({callback:t,id:e,cancelled:!1}),e},Do.prototype.remove=function(t){for(var e=this._currentlyRunning,i=0,o=e?this._queue.concat(e):this._queue;ie.maxZoom)throw new Error("maxZoom must be greater than minZoom");var a=new co(e.minZoom,e.maxZoom,e.renderWorldCopies);if(o.call(this,a,e),this._interactive=e.interactive,this._maxTileCacheSize=e.maxTileCacheSize,this._failIfMajorPerformanceCaveat=e.failIfMajorPerformanceCaveat,this._preserveDrawingBuffer=e.preserveDrawingBuffer,this._antialias=e.antialias,this._trackResize=e.trackResize,this._bearingSnap=e.bearingSnap,this._refreshExpiredTiles=e.refreshExpiredTiles,this._fadeDuration=e.fadeDuration,this._crossSourceCollisions=e.crossSourceCollisions,this._crossFadingFactor=1,this._collectResourceTiming=e.collectResourceTiming,this._renderTaskQueue=new Do,this._controls=[],this._mapId=t.uniqueId(),this._requestManager=new t.RequestManager(e.transformRequest),"string"==typeof e.container){if(this._container=t.window.document.getElementById(e.container),!this._container)throw new Error("Container '"+e.container+"' not found.")}else{if(!(e.container instanceof Ro))throw new Error("Invalid type: 'container' must be a String or HTMLElement.");this._container=e.container;}if(e.maxBounds&&this.setMaxBounds(e.maxBounds),t.bindAll(["_onWindowOnline","_onWindowResize","_contextLost","_contextRestored"],this),this._setupContainer(),this._setupPainter(),void 0===this.painter)throw new Error("Failed to initialize WebGL.");this.on("move",function(){return r._update(!1)}),this.on("moveend",function(){return r._update(!1)}),this.on("zoom",function(){return r._update(!0)}),void 0!==t.window&&(t.window.addEventListener("online",this._onWindowOnline,!1),t.window.addEventListener("resize",this._onWindowResize,!1)),function(t,e){var o=t.getCanvasContainer(),r=null,a=!1,n=null;for(var s in So)t[s]=new So[s](t,e),e.interactive&&e[s]&&t[s].enable(e[s]);i.addEventListener(o,"mouseout",function(e){t.fire(new po("mouseout",t,e));}),i.addEventListener(o,"mousedown",function(r){a=!0,n=i.mousePos(o,r);var s=new po("mousedown",t,r);t.fire(s),s.defaultPrevented||(e.interactive&&!t.doubleClickZoom.isActive()&&t.stop(),t.boxZoom.onMouseDown(r),t.boxZoom.isActive()||t.dragPan.isActive()||t.dragRotate.onMouseDown(r),t.boxZoom.isActive()||t.dragRotate.isActive()||t.dragPan.onMouseDown(r));}),i.addEventListener(o,"mouseup",function(e){var i=t.dragRotate.isActive();r&&!i&&t.fire(new po("contextmenu",t,r)),r=null,a=!1,t.fire(new po("mouseup",t,e));}),i.addEventListener(o,"mousemove",function(e){if(!t.dragPan.isActive()&&!t.dragRotate.isActive()){for(var i=e.target;i&&i!==o;)i=i.parentNode;i===o&&t.fire(new po("mousemove",t,e));}}),i.addEventListener(o,"mouseover",function(e){for(var i=e.target;i&&i!==o;)i=i.parentNode;i===o&&t.fire(new po("mouseover",t,e));}),i.addEventListener(o,"touchstart",function(i){var o=new _o("touchstart",t,i);t.fire(o),o.defaultPrevented||(e.interactive&&t.stop(),t.boxZoom.isActive()||t.dragRotate.isActive()||t.dragPan.onTouchStart(i),t.touchZoomRotate.onStart(i),t.doubleClickZoom.onTouchStart(o));},{passive:!1}),i.addEventListener(o,"touchmove",function(e){t.fire(new _o("touchmove",t,e));},{passive:!1}),i.addEventListener(o,"touchend",function(e){t.fire(new _o("touchend",t,e));}),i.addEventListener(o,"touchcancel",function(e){t.fire(new _o("touchcancel",t,e));}),i.addEventListener(o,"click",function(r){var a=i.mousePos(o,r);(a.equals(n)||a.dist(n)-1&&this._controls.splice(i,1),e.onRemove(this),this},r.prototype.resize=function(e){var i=this._containerDimensions(),o=i[0],r=i[1];return this._resizeCanvas(o,r),this.transform.resize(o,r),this.painter.resize(o,r),this.fire(new t.Event("movestart",e)).fire(new t.Event("move",e)).fire(new t.Event("resize",e)).fire(new t.Event("moveend",e)),this},r.prototype.getBounds=function(){return this.transform.getBounds()},r.prototype.getMaxBounds=function(){return this.transform.getMaxBounds()},r.prototype.setMaxBounds=function(e){return this.transform.setMaxBounds(t.LngLatBounds.convert(e)),this._update()},r.prototype.setMinZoom=function(t){if((t=null==t?0:t)>=0&&t<=this.transform.maxZoom)return this.transform.minZoom=t,this._update(),this.getZoom()=this.transform.minZoom)return this.transform.maxZoom=t,this._update(),this.getZoom()>t&&this.setZoom(t),this;throw new Error("maxZoom must be greater than the current minZoom")},r.prototype.getRenderWorldCopies=function(){return this.transform.renderWorldCopies},r.prototype.setRenderWorldCopies=function(t){return this.transform.renderWorldCopies=t,this._update()},r.prototype.getMaxZoom=function(){return this.transform.maxZoom},r.prototype.project=function(e){return this.transform.locationPoint(t.LngLat.convert(e))},r.prototype.unproject=function(e){return this.transform.pointLocation(t.Point.convert(e))},r.prototype.isMoving=function(){return this._moving||this.dragPan.isActive()||this.dragRotate.isActive()||this.scrollZoom.isActive()},r.prototype.isZooming=function(){return this._zooming||this.scrollZoom.isZooming()},r.prototype.isRotating=function(){return this._rotating||this.dragRotate.isActive()},r.prototype.on=function(t,e,i){var r=this;if(void 0===i)return o.prototype.on.call(this,t,e);var a=function(){var o;if("mouseenter"===t||"mouseover"===t){var a=!1;return {layer:e,listener:i,delegates:{mousemove:function(o){var n=r.getLayer(e)?r.queryRenderedFeatures(o.point,{layers:[e]}):[];n.length?a||(a=!0,i.call(r,new po(t,r,o.originalEvent,{features:n}))):a=!1;},mouseout:function(){a=!1;}}}}if("mouseleave"===t||"mouseout"===t){var n=!1;return {layer:e,listener:i,delegates:{mousemove:function(o){(r.getLayer(e)?r.queryRenderedFeatures(o.point,{layers:[e]}):[]).length?n=!0:n&&(n=!1,i.call(r,new po(t,r,o.originalEvent)));},mouseout:function(e){n&&(n=!1,i.call(r,new po(t,r,e.originalEvent)));}}}}return {layer:e,listener:i,delegates:(o={},o[t]=function(t){var o=r.getLayer(e)?r.queryRenderedFeatures(t.point,{layers:[e]}):[];o.length&&(t.features=o,i.call(r,t),delete t.features);},o)}}();for(var n in this._delegatedListeners=this._delegatedListeners||{},this._delegatedListeners[t]=this._delegatedListeners[t]||[],this._delegatedListeners[t].push(a),a.delegates)this.on(n,a.delegates[n]);return this},r.prototype.off=function(t,e,i){if(void 0===i)return o.prototype.off.call(this,t,e);if(this._delegatedListeners&&this._delegatedListeners[t])for(var r=this._delegatedListeners[t],a=0;a180;){var s=o.locationPoint(e);if(s.x>=0&&s.y>=0&&s.x<=o.width&&s.y<=o.height)break;e.lng>o.center.lng?e.lng-=360:e.lng+=360;}return e}Fo.prototype._updateZoomButtons=function(){var t=this._map.getZoom();this._zoomInButton.classList.toggle("mapboxgl-ctrl-icon-disabled",t===this._map.getMaxZoom()),this._zoomOutButton.classList.toggle("mapboxgl-ctrl-icon-disabled",t===this._map.getMinZoom());},Fo.prototype._rotateCompassArrow=function(){var t="rotate("+this._map.transform.angle*(180/Math.PI)+"deg)";this._compassArrow.style.transform=t;},Fo.prototype.onAdd=function(t){return this._map=t,this.options.showZoom&&(this._map.on("zoom",this._updateZoomButtons),this._updateZoomButtons()),this.options.showCompass&&(this._map.on("rotate",this._rotateCompassArrow),this._rotateCompassArrow(),this._handler=new yo(t,{button:"left",element:this._compass}),i.addEventListener(this._compass,"mousedown",this._handler.onMouseDown),this._handler.enable()),this._container},Fo.prototype.onRemove=function(){i.remove(this._container),this.options.showZoom&&this._map.off("zoom",this._updateZoomButtons),this.options.showCompass&&(this._map.off("rotate",this._rotateCompassArrow),i.removeEventListener(this._compass,"mousedown",this._handler.onMouseDown),this._handler.disable(),delete this._handler),delete this._map;},Fo.prototype._createButton=function(t,e,o){var r=i.create("button",t,this._container);return r.type="button",r.title=e,r.setAttribute("aria-label",e),r.addEventListener("click",o),r};var No={center:"translate(-50%,-50%)",top:"translate(-50%,0)","top-left":"translate(0,0)","top-right":"translate(-100%,0)",bottom:"translate(-50%,-100%)","bottom-left":"translate(0,-100%)","bottom-right":"translate(-100%,-100%)",left:"translate(0,-50%)",right:"translate(-100%,-50%)"};function Zo(t,e,i){var o=t.classList;for(var r in No)o.remove("mapboxgl-"+i+"-anchor-"+r);o.add("mapboxgl-"+i+"-anchor-"+e);}var jo,qo=function(e){function o(o,r){if(e.call(this),(o instanceof t.window.HTMLElement||r)&&(o=t.extend({element:o},r)),t.bindAll(["_update","_onMove","_onUp","_addDragHandler","_onMapClick"],this),this._anchor=o&&o.anchor||"center",this._color=o&&o.color||"#3FB1CE",this._draggable=o&&o.draggable||!1,this._state="inactive",o&&o.element)this._element=o.element,this._offset=t.Point.convert(o&&o.offset||[0,0]);else{this._defaultMarker=!0,this._element=i.create("div");var a=i.createNS("http://www.w3.org/2000/svg","svg");a.setAttributeNS(null,"display","block"),a.setAttributeNS(null,"height","41px"),a.setAttributeNS(null,"width","27px"),a.setAttributeNS(null,"viewBox","0 0 27 41");var n=i.createNS("http://www.w3.org/2000/svg","g");n.setAttributeNS(null,"stroke","none"),n.setAttributeNS(null,"stroke-width","1"),n.setAttributeNS(null,"fill","none"),n.setAttributeNS(null,"fill-rule","evenodd");var s=i.createNS("http://www.w3.org/2000/svg","g");s.setAttributeNS(null,"fill-rule","nonzero");var l=i.createNS("http://www.w3.org/2000/svg","g");l.setAttributeNS(null,"transform","translate(3.0, 29.0)"),l.setAttributeNS(null,"fill","#000000");for(var c=0,u=[{rx:"10.5",ry:"5.25002273"},{rx:"10.5",ry:"5.25002273"},{rx:"9.5",ry:"4.77275007"},{rx:"8.5",ry:"4.29549936"},{rx:"7.5",ry:"3.81822308"},{rx:"6.5",ry:"3.34094679"},{rx:"5.5",ry:"2.86367051"},{rx:"4.5",ry:"2.38636864"}];c5280)Ko(e,c,p/5280,"mi");else Ko(e,c,p,"ft");}else if(i&&"nautical"===i.unit){Ko(e,c,h/1852,"nm");}else Ko(e,c,h,"m");}function Ko(t,e,i,o){var r,a,n,s=(r=i,a=Math.pow(10,(""+Math.floor(r)).length-1),n=(n=r/a)>=10?10:n>=5?5:n>=3?3:n>=2?2:n>=1?1:function(t){var e=Math.pow(10,Math.ceil(-Math.log(t)/Math.LN10));return Math.round(t*e)/e}(n),a*n),l=s/i;"m"===o&&s>=1e3&&(s/=1e3,o="km"),t.style.width=e*l+"px",t.innerHTML=s+o;}Xo.prototype.getDefaultPosition=function(){return "bottom-left"},Xo.prototype._onMove=function(){Ho(this._map,this._container,this.options);},Xo.prototype.onAdd=function(t){return this._map=t,this._container=i.create("div","mapboxgl-ctrl mapboxgl-ctrl-scale",t.getContainer()),this._map.on("move",this._onMove),this._onMove(),this._container},Xo.prototype.onRemove=function(){i.remove(this._container),this._map.off("move",this._onMove),this._map=void 0;},Xo.prototype.setUnit=function(t){this.options.unit=t,Ho(this._map,this._container,this.options);};var Yo=function(e){this._fullscreen=!1,e&&e.container&&(e.container instanceof t.window.HTMLElement?this._container=e.container:t.warnOnce("Full screen control 'container' must be a DOM element.")),t.bindAll(["_onClickFullscreen","_changeIcon"],this),"onfullscreenchange"in t.window.document?this._fullscreenchange="fullscreenchange":"onmozfullscreenchange"in t.window.document?this._fullscreenchange="mozfullscreenchange":"onwebkitfullscreenchange"in t.window.document?this._fullscreenchange="webkitfullscreenchange":"onmsfullscreenchange"in t.window.document&&(this._fullscreenchange="MSFullscreenChange"),this._className="mapboxgl-ctrl";};Yo.prototype.onAdd=function(e){return this._map=e,this._container||(this._container=this._map.getContainer()),this._controlContainer=i.create("div",this._className+" mapboxgl-ctrl-group"),this._checkFullscreenSupport()?this._setupUI():(this._controlContainer.style.display="none",t.warnOnce("This device does not support fullscreen mode.")),this._controlContainer},Yo.prototype.onRemove=function(){i.remove(this._controlContainer),this._map=null,t.window.document.removeEventListener(this._fullscreenchange,this._changeIcon);},Yo.prototype._checkFullscreenSupport=function(){return !!(t.window.document.fullscreenEnabled||t.window.document.mozFullScreenEnabled||t.window.document.msFullscreenEnabled||t.window.document.webkitFullscreenEnabled)},Yo.prototype._setupUI=function(){(this._fullscreenButton=i.create("button",this._className+"-icon "+this._className+"-fullscreen",this._controlContainer)).type="button",this._updateTitle(),this._fullscreenButton.addEventListener("click",this._onClickFullscreen),t.window.document.addEventListener(this._fullscreenchange,this._changeIcon);},Yo.prototype._updateTitle=function(){var t=this._isFullscreen()?"Exit fullscreen":"Enter fullscreen";this._fullscreenButton.setAttribute("aria-label",t),this._fullscreenButton.title=t;},Yo.prototype._isFullscreen=function(){return this._fullscreen},Yo.prototype._changeIcon=function(){(t.window.document.fullscreenElement||t.window.document.mozFullScreenElement||t.window.document.webkitFullscreenElement||t.window.document.msFullscreenElement)===this._container!==this._fullscreen&&(this._fullscreen=!this._fullscreen,this._fullscreenButton.classList.toggle(this._className+"-shrink"),this._fullscreenButton.classList.toggle(this._className+"-fullscreen"),this._updateTitle());},Yo.prototype._onClickFullscreen=function(){this._isFullscreen()?t.window.document.exitFullscreen?t.window.document.exitFullscreen():t.window.document.mozCancelFullScreen?t.window.document.mozCancelFullScreen():t.window.document.msExitFullscreen?t.window.document.msExitFullscreen():t.window.document.webkitCancelFullScreen&&t.window.document.webkitCancelFullScreen():this._container.requestFullscreen?this._container.requestFullscreen():this._container.mozRequestFullScreen?this._container.mozRequestFullScreen():this._container.msRequestFullscreen?this._container.msRequestFullscreen():this._container.webkitRequestFullscreen&&this._container.webkitRequestFullscreen();};var Jo={closeButton:!0,closeOnClick:!0,className:"",maxWidth:"240px"},Qo=function(e){function o(i){e.call(this),this.options=t.extend(Object.create(Jo),i),t.bindAll(["_update","_onClickClose","remove"],this);}return e&&(o.__proto__=e),o.prototype=Object.create(e&&e.prototype),o.prototype.constructor=o,o.prototype.addTo=function(e){var i=this;return this._map=e,this.options.closeOnClick&&this._map.on("click",this._onClickClose),this._map.on("remove",this.remove),this._update(),this._trackPointer?(this._map.on("mousemove",function(t){i._update(t.point);}),this._map.on("mouseup",function(t){i._update(t.point);}),this._container.classList.add("mapboxgl-popup-track-pointer"),this._map._canvasContainer.classList.add("mapboxgl-track-pointer")):this._map.on("move",this._update),this.fire(new t.Event("open")),this},o.prototype.isOpen=function(){return !!this._map},o.prototype.remove=function(){return this._content&&i.remove(this._content),this._container&&(i.remove(this._container),delete this._container),this._map&&(this._map.off("move",this._update),this._map.off("click",this._onClickClose),this._map.off("remove",this.remove),this._map.off("mousemove"),delete this._map),this.fire(new t.Event("close")),this},o.prototype.getLngLat=function(){return this._lngLat},o.prototype.setLngLat=function(e){return this._lngLat=t.LngLat.convert(e),this._pos=null,this._map&&(this._map.on("move",this._update),this._map.off("mousemove"),this._container.classList.remove("mapboxgl-popup-track-pointer"),this._map._canvasContainer.classList.remove("mapboxgl-track-pointer")),this._trackPointer=!1,this._update(),this},o.prototype.trackPointer=function(){var t=this;return this._trackPointer=!0,this._pos=null,this._map&&(this._map.off("move",this._update),this._map.on("mousemove",function(e){t._update(e.point);}),this._map.on("drag",function(e){t._update(e.point);}),this._container.classList.add("mapboxgl-popup-track-pointer"),this._map._canvasContainer.classList.add("mapboxgl-track-pointer")),this},o.prototype.getElement=function(){return this._container},o.prototype.setText=function(e){return this.setDOMContent(t.window.document.createTextNode(e))},o.prototype.setHTML=function(e){var i,o=t.window.document.createDocumentFragment(),r=t.window.document.createElement("body");for(r.innerHTML=e;i=r.firstChild;)o.appendChild(i);return this.setDOMContent(o)},o.prototype.getMaxWidth=function(){return this._container.style.maxWidth},o.prototype.setMaxWidth=function(t){return this.options.maxWidth=t,this._update(),this},o.prototype.setDOMContent=function(t){return this._createContent(),this._content.appendChild(t),this._update(),this},o.prototype._createContent=function(){this._content&&i.remove(this._content),this._content=i.create("div","mapboxgl-popup-content",this._container),this.options.closeButton&&(this._closeButton=i.create("button","mapboxgl-popup-close-button",this._content),this._closeButton.type="button",this._closeButton.setAttribute("aria-label","Close popup"),this._closeButton.innerHTML="×",this._closeButton.addEventListener("click",this._onClickClose));},o.prototype._update=function(e){var o=this,r=this._lngLat||this._trackPointer;if(this._map&&r&&this._content&&(this._container||(this._container=i.create("div","mapboxgl-popup",this._map.getContainer()),this._tip=i.create("div","mapboxgl-popup-tip",this._container),this._container.appendChild(this._content),this.options.className&&this.options.className.split(" ").forEach(function(t){return o._container.classList.add(t)})),this.options.maxWidth&&this._container.style.maxWidth!==this.options.maxWidth&&(this._container.style.maxWidth=this.options.maxWidth),this._map.transform.renderWorldCopies&&!this._trackPointer&&(this._lngLat=Uo(this._lngLat,this._pos,this._map.transform)),!this._trackPointer||e)){var a=this._pos=this._trackPointer&&e?e:this._map.project(this._lngLat),n=this.options.anchor,s=function e(i){if(i){if("number"==typeof i){var o=Math.round(Math.sqrt(.5*Math.pow(i,2)));return {center:new t.Point(0,0),top:new t.Point(0,i),"top-left":new t.Point(o,o),"top-right":new t.Point(-o,o),bottom:new t.Point(0,-i),"bottom-left":new t.Point(o,-o),"bottom-right":new t.Point(-o,-o),left:new t.Point(i,0),right:new t.Point(-i,0)}}if(i instanceof t.Point||Array.isArray(i)){var r=t.Point.convert(i);return {center:r,top:r,"top-left":r,"top-right":r,bottom:r,"bottom-left":r,"bottom-right":r,left:r,right:r}}return {center:t.Point.convert(i.center||[0,0]),top:t.Point.convert(i.top||[0,0]),"top-left":t.Point.convert(i["top-left"]||[0,0]),"top-right":t.Point.convert(i["top-right"]||[0,0]),bottom:t.Point.convert(i.bottom||[0,0]),"bottom-left":t.Point.convert(i["bottom-left"]||[0,0]),"bottom-right":t.Point.convert(i["bottom-right"]||[0,0]),left:t.Point.convert(i.left||[0,0]),right:t.Point.convert(i.right||[0,0])}}return e(new t.Point(0,0))}(this.options.offset);if(!n){var l,c=this._container.offsetWidth,u=this._container.offsetHeight;l=a.y+s.bottom.ythis._map.transform.height-u?["bottom"]:[],a.xthis._map.transform.width-c/2&&l.push("right"),n=0===l.length?"bottom":l.join("-");}var h=a.add(s[n]).round();i.setTransform(this._container,No[n]+" translate("+h.x+"px,"+h.y+"px)"),Zo(this._container,n,"popup");}},o.prototype._onClickClose=function(){this.remove();},o}(t.Evented);var $o={version:t.version,supported:e,setRTLTextPlugin:t.setRTLTextPlugin,Map:ko,NavigationControl:Fo,GeolocateControl:Go,AttributionControl:zo,ScaleControl:Xo,FullscreenControl:Yo,Popup:Qo,Marker:qo,Style:Be,LngLat:t.LngLat,LngLatBounds:t.LngLatBounds,Point:t.Point,MercatorCoordinate:t.MercatorCoordinate,Evented:t.Evented,config:t.config,get accessToken(){return t.config.ACCESS_TOKEN},set accessToken(e){t.config.ACCESS_TOKEN=e;},get baseApiUrl(){return t.config.API_URL},set baseApiUrl(e){t.config.API_URL=e;},get workerCount(){return Rt.workerCount},set workerCount(t){Rt.workerCount=t;},get maxParallelImageRequests(){return t.config.MAX_PARALLEL_IMAGE_REQUESTS},set maxParallelImageRequests(e){t.config.MAX_PARALLEL_IMAGE_REQUESTS=e;},clearStorage:function(e){t.clearTileCache(e);},workerUrl:""};return $o}); - -// - -return mapboxgl; - -})); - - -},{}],427:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createTable - -var chull = _dereq_('convex-hull') - -function constructVertex(d, a, b) { - var x = new Array(d) - for(var i=0; i row[1][2]) - quaternion[0] = -quaternion[0] - if (row[0][2] > row[2][0]) - quaternion[1] = -quaternion[1] - if (row[1][0] > row[0][1]) - quaternion[2] = -quaternion[2] - return true -} - -//will be replaced by gl-vec4 eventually -function vec4multMat4(out, a, m) { - var x = a[0], y = a[1], z = a[2], w = a[3]; - out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; - out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; - out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; - out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; - return out; -} - -//gets upper-left of a 4x4 matrix into a 3x3 of vectors -function mat3from4(out, mat4x4) { - out[0][0] = mat4x4[0] - out[0][1] = mat4x4[1] - out[0][2] = mat4x4[2] - - out[1][0] = mat4x4[4] - out[1][1] = mat4x4[5] - out[1][2] = mat4x4[6] - - out[2][0] = mat4x4[8] - out[2][1] = mat4x4[9] - out[2][2] = mat4x4[10] -} - -function combine(out, a, b, scale1, scale2) { - out[0] = a[0] * scale1 + b[0] * scale2 - out[1] = a[1] * scale1 + b[1] * scale2 - out[2] = a[2] * scale1 + b[2] * scale2 -} -},{"./normalize":429,"gl-mat4/clone":259,"gl-mat4/create":260,"gl-mat4/determinant":261,"gl-mat4/invert":265,"gl-mat4/transpose":276,"gl-vec3/cross":334,"gl-vec3/dot":339,"gl-vec3/length":349,"gl-vec3/normalize":356}],429:[function(_dereq_,module,exports){ -module.exports = function normalize(out, mat) { - var m44 = mat[15] - // Cannot normalize. - if (m44 === 0) - return false - var scale = 1 / m44 - for (var i=0; i<16; i++) - out[i] = mat[i] * scale - return true -} -},{}],430:[function(_dereq_,module,exports){ -var lerp = _dereq_('gl-vec3/lerp') - -var recompose = _dereq_('mat4-recompose') -var decompose = _dereq_('mat4-decompose') -var determinant = _dereq_('gl-mat4/determinant') -var slerp = _dereq_('quat-slerp') - -var state0 = state() -var state1 = state() -var tmp = state() - -module.exports = interpolate -function interpolate(out, start, end, alpha) { - if (determinant(start) === 0 || determinant(end) === 0) - return false - - //decompose the start and end matrices into individual components - var r0 = decompose(start, state0.translate, state0.scale, state0.skew, state0.perspective, state0.quaternion) - var r1 = decompose(end, state1.translate, state1.scale, state1.skew, state1.perspective, state1.quaternion) - if (!r0 || !r1) - return false - - - //now lerp/slerp the start and end components into a temporary lerp(tmptranslate, state0.translate, state1.translate, alpha) - lerp(tmp.translate, state0.translate, state1.translate, alpha) - lerp(tmp.skew, state0.skew, state1.skew, alpha) - lerp(tmp.scale, state0.scale, state1.scale, alpha) - lerp(tmp.perspective, state0.perspective, state1.perspective, alpha) - slerp(tmp.quaternion, state0.quaternion, state1.quaternion, alpha) - - //and recompose into our 'out' matrix - recompose(out, tmp.translate, tmp.scale, tmp.skew, tmp.perspective, tmp.quaternion) - return true -} - -function state() { - return { - translate: vec3(), - scale: vec3(1), - skew: vec3(), - perspective: vec4(), - quaternion: vec4() - } -} - -function vec3(n) { - return [n||0,n||0,n||0] -} - -function vec4() { - return [0,0,0,1] -} -},{"gl-mat4/determinant":261,"gl-vec3/lerp":350,"mat4-decompose":428,"mat4-recompose":431,"quat-slerp":483}],431:[function(_dereq_,module,exports){ -/* -Input: translation ; a 3 component vector - scale ; a 3 component vector - skew ; skew factors XY,XZ,YZ represented as a 3 component vector - perspective ; a 4 component vector - quaternion ; a 4 component vector -Output: matrix ; a 4x4 matrix - -From: http://www.w3.org/TR/css3-transforms/#recomposing-to-a-3d-matrix -*/ - -var mat4 = { - identity: _dereq_('gl-mat4/identity'), - translate: _dereq_('gl-mat4/translate'), - multiply: _dereq_('gl-mat4/multiply'), - create: _dereq_('gl-mat4/create'), - scale: _dereq_('gl-mat4/scale'), - fromRotationTranslation: _dereq_('gl-mat4/fromRotationTranslation') -} - -var rotationMatrix = mat4.create() -var temp = mat4.create() - -module.exports = function recomposeMat4(matrix, translation, scale, skew, perspective, quaternion) { - mat4.identity(matrix) - - //apply translation & rotation - mat4.fromRotationTranslation(matrix, quaternion, translation) - - //apply perspective - matrix[3] = perspective[0] - matrix[7] = perspective[1] - matrix[11] = perspective[2] - matrix[15] = perspective[3] - - // apply skew - // temp is a identity 4x4 matrix initially - mat4.identity(temp) - - if (skew[2] !== 0) { - temp[9] = skew[2] - mat4.multiply(matrix, matrix, temp) - } - - if (skew[1] !== 0) { - temp[9] = 0 - temp[8] = skew[1] - mat4.multiply(matrix, matrix, temp) - } - - if (skew[0] !== 0) { - temp[8] = 0 - temp[4] = skew[0] - mat4.multiply(matrix, matrix, temp) - } - - //apply scale - mat4.scale(matrix, matrix, scale) - return matrix -} -},{"gl-mat4/create":260,"gl-mat4/fromRotationTranslation":263,"gl-mat4/identity":264,"gl-mat4/multiply":267,"gl-mat4/scale":274,"gl-mat4/translate":275}],432:[function(_dereq_,module,exports){ -'use strict'; -module.exports = Math.log2 || function (x) { - return Math.log(x) * Math.LOG2E; -}; - -},{}],433:[function(_dereq_,module,exports){ -'use strict' - -var bsearch = _dereq_('binary-search-bounds') -var m4interp = _dereq_('mat4-interpolate') -var invert44 = _dereq_('gl-mat4/invert') -var rotateX = _dereq_('gl-mat4/rotateX') -var rotateY = _dereq_('gl-mat4/rotateY') -var rotateZ = _dereq_('gl-mat4/rotateZ') -var lookAt = _dereq_('gl-mat4/lookAt') -var translate = _dereq_('gl-mat4/translate') -var scale = _dereq_('gl-mat4/scale') -var normalize = _dereq_('gl-vec3/normalize') - -var DEFAULT_CENTER = [0,0,0] - -module.exports = createMatrixCameraController - -function MatrixCameraController(initialMatrix) { - this._components = initialMatrix.slice() - this._time = [0] - this.prevMatrix = initialMatrix.slice() - this.nextMatrix = initialMatrix.slice() - this.computedMatrix = initialMatrix.slice() - this.computedInverse = initialMatrix.slice() - this.computedEye = [0,0,0] - this.computedUp = [0,0,0] - this.computedCenter = [0,0,0] - this.computedRadius = [0] - this._limits = [-Infinity, Infinity] -} - -var proto = MatrixCameraController.prototype - -proto.recalcMatrix = function(t) { - var time = this._time - var tidx = bsearch.le(time, t) - var mat = this.computedMatrix - if(tidx < 0) { - return - } - var comps = this._components - if(tidx === time.length-1) { - var ptr = 16*tidx - for(var i=0; i<16; ++i) { - mat[i] = comps[ptr++] - } - } else { - var dt = (time[tidx+1] - time[tidx]) - var ptr = 16*tidx - var prev = this.prevMatrix - var allEqual = true - for(var i=0; i<16; ++i) { - prev[i] = comps[ptr++] - } - var next = this.nextMatrix - for(var i=0; i<16; ++i) { - next[i] = comps[ptr++] - allEqual = allEqual && (prev[i] === next[i]) - } - if(dt < 1e-6 || allEqual) { - for(var i=0; i<16; ++i) { - mat[i] = prev[i] - } - } else { - m4interp(mat, prev, next, (t - time[tidx])/dt) - } - } - - var up = this.computedUp - up[0] = mat[1] - up[1] = mat[5] - up[2] = mat[9] - normalize(up, up) - - var imat = this.computedInverse - invert44(imat, mat) - var eye = this.computedEye - var w = imat[15] - eye[0] = imat[12]/w - eye[1] = imat[13]/w - eye[2] = imat[14]/w - - var center = this.computedCenter - var radius = Math.exp(this.computedRadius[0]) - for(var i=0; i<3; ++i) { - center[i] = eye[i] - mat[2+4*i] * radius - } -} - -proto.idle = function(t) { - if(t < this.lastT()) { - return - } - var mc = this._components - var ptr = mc.length-16 - for(var i=0; i<16; ++i) { - mc.push(mc[ptr++]) - } - this._time.push(t) -} - -proto.flush = function(t) { - var idx = bsearch.gt(this._time, t) - 2 - if(idx < 0) { - return - } - this._time.splice(0, idx) - this._components.splice(0, 16*idx) -} - -proto.lastT = function() { - return this._time[this._time.length-1] -} - -proto.lookAt = function(t, eye, center, up) { - this.recalcMatrix(t) - eye = eye || this.computedEye - center = center || DEFAULT_CENTER - up = up || this.computedUp - this.setMatrix(t, lookAt(this.computedMatrix, eye, center, up)) - var d2 = 0.0 - for(var i=0; i<3; ++i) { - d2 += Math.pow(center[i] - eye[i], 2) - } - d2 = Math.log(Math.sqrt(d2)) - this.computedRadius[0] = d2 -} - -proto.rotate = function(t, yaw, pitch, roll) { - this.recalcMatrix(t) - var mat = this.computedInverse - if(yaw) rotateY(mat, mat, yaw) - if(pitch) rotateX(mat, mat, pitch) - if(roll) rotateZ(mat, mat, roll) - this.setMatrix(t, invert44(this.computedMatrix, mat)) -} - -var tvec = [0,0,0] - -proto.pan = function(t, dx, dy, dz) { - tvec[0] = -(dx || 0.0) - tvec[1] = -(dy || 0.0) - tvec[2] = -(dz || 0.0) - this.recalcMatrix(t) - var mat = this.computedInverse - translate(mat, mat, tvec) - this.setMatrix(t, invert44(mat, mat)) -} - -proto.translate = function(t, dx, dy, dz) { - tvec[0] = dx || 0.0 - tvec[1] = dy || 0.0 - tvec[2] = dz || 0.0 - this.recalcMatrix(t) - var mat = this.computedMatrix - translate(mat, mat, tvec) - this.setMatrix(t, mat) -} - -proto.setMatrix = function(t, mat) { - if(t < this.lastT()) { - return - } - this._time.push(t) - for(var i=0; i<16; ++i) { - this._components.push(mat[i]) - } -} - -proto.setDistance = function(t, d) { - this.computedRadius[0] = d -} - -proto.setDistanceLimits = function(a,b) { - var lim = this._limits - lim[0] = a - lim[1] = b -} - -proto.getDistanceLimits = function(out) { - var lim = this._limits - if(out) { - out[0] = lim[0] - out[1] = lim[1] - return out - } - return lim -} - -function createMatrixCameraController(options) { - options = options || {} - var matrix = options.matrix || - [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1] - return new MatrixCameraController(matrix) -} - -},{"binary-search-bounds":91,"gl-mat4/invert":265,"gl-mat4/lookAt":266,"gl-mat4/rotateX":271,"gl-mat4/rotateY":272,"gl-mat4/rotateZ":273,"gl-mat4/scale":274,"gl-mat4/translate":275,"gl-vec3/normalize":356,"mat4-interpolate":430}],434:[function(_dereq_,module,exports){ -'use strict' - -module.exports = monotoneConvexHull2D - -var orient = _dereq_('robust-orientation')[3] - -function monotoneConvexHull2D(points) { - var n = points.length - - if(n < 3) { - var result = new Array(n) - for(var i=0; i 1 && orient( - points[lower[m-2]], - points[lower[m-1]], - p) <= 0) { - m -= 1 - lower.pop() - } - lower.push(idx) - - //Insert into upper list - m = upper.length - while(m > 1 && orient( - points[upper[m-2]], - points[upper[m-1]], - p) >= 0) { - m -= 1 - upper.pop() - } - upper.push(idx) - } - - //Merge lists together - var result = new Array(upper.length + lower.length - 2) - var ptr = 0 - for(var i=0, nl=lower.length; i0; --j) { - result[ptr++] = upper[j] - } - - //Return result - return result -} -},{"robust-orientation":510}],435:[function(_dereq_,module,exports){ -'use strict' - -module.exports = mouseListen - -var mouse = _dereq_('mouse-event') - -function mouseListen (element, callback) { - if (!callback) { - callback = element - element = window - } - - var buttonState = 0 - var x = 0 - var y = 0 - var mods = { - shift: false, - alt: false, - control: false, - meta: false - } - var attached = false - - function updateMods (ev) { - var changed = false - if ('altKey' in ev) { - changed = changed || ev.altKey !== mods.alt - mods.alt = !!ev.altKey - } - if ('shiftKey' in ev) { - changed = changed || ev.shiftKey !== mods.shift - mods.shift = !!ev.shiftKey - } - if ('ctrlKey' in ev) { - changed = changed || ev.ctrlKey !== mods.control - mods.control = !!ev.ctrlKey - } - if ('metaKey' in ev) { - changed = changed || ev.metaKey !== mods.meta - mods.meta = !!ev.metaKey - } - return changed - } - - function handleEvent (nextButtons, ev) { - var nextX = mouse.x(ev) - var nextY = mouse.y(ev) - if ('buttons' in ev) { - nextButtons = ev.buttons | 0 - } - if (nextButtons !== buttonState || - nextX !== x || - nextY !== y || - updateMods(ev)) { - buttonState = nextButtons | 0 - x = nextX || 0 - y = nextY || 0 - callback && callback(buttonState, x, y, mods) - } - } - - function clearState (ev) { - handleEvent(0, ev) - } - - function handleBlur () { - if (buttonState || - x || - y || - mods.shift || - mods.alt || - mods.meta || - mods.control) { - x = y = 0 - buttonState = 0 - mods.shift = mods.alt = mods.control = mods.meta = false - callback && callback(0, 0, 0, mods) - } - } - - function handleMods (ev) { - if (updateMods(ev)) { - callback && callback(buttonState, x, y, mods) - } - } - - function handleMouseMove (ev) { - if (mouse.buttons(ev) === 0) { - handleEvent(0, ev) - } else { - handleEvent(buttonState, ev) - } - } - - function handleMouseDown (ev) { - handleEvent(buttonState | mouse.buttons(ev), ev) - } - - function handleMouseUp (ev) { - handleEvent(buttonState & ~mouse.buttons(ev), ev) - } - - function attachListeners () { - if (attached) { - return - } - attached = true - - element.addEventListener('mousemove', handleMouseMove) - - element.addEventListener('mousedown', handleMouseDown) - - element.addEventListener('mouseup', handleMouseUp) - - element.addEventListener('mouseleave', clearState) - element.addEventListener('mouseenter', clearState) - element.addEventListener('mouseout', clearState) - element.addEventListener('mouseover', clearState) - - element.addEventListener('blur', handleBlur) - - element.addEventListener('keyup', handleMods) - element.addEventListener('keydown', handleMods) - element.addEventListener('keypress', handleMods) - - if (element !== window) { - window.addEventListener('blur', handleBlur) - - window.addEventListener('keyup', handleMods) - window.addEventListener('keydown', handleMods) - window.addEventListener('keypress', handleMods) - } - } - - function detachListeners () { - if (!attached) { - return - } - attached = false - - element.removeEventListener('mousemove', handleMouseMove) - - element.removeEventListener('mousedown', handleMouseDown) - - element.removeEventListener('mouseup', handleMouseUp) - - element.removeEventListener('mouseleave', clearState) - element.removeEventListener('mouseenter', clearState) - element.removeEventListener('mouseout', clearState) - element.removeEventListener('mouseover', clearState) - - element.removeEventListener('blur', handleBlur) - - element.removeEventListener('keyup', handleMods) - element.removeEventListener('keydown', handleMods) - element.removeEventListener('keypress', handleMods) - - if (element !== window) { - window.removeEventListener('blur', handleBlur) - - window.removeEventListener('keyup', handleMods) - window.removeEventListener('keydown', handleMods) - window.removeEventListener('keypress', handleMods) - } - } - - // Attach listeners - attachListeners() - - var result = { - element: element - } - - Object.defineProperties(result, { - enabled: { - get: function () { return attached }, - set: function (f) { - if (f) { - attachListeners() - } else { - detachListeners() - } - }, - enumerable: true - }, - buttons: { - get: function () { return buttonState }, - enumerable: true - }, - x: { - get: function () { return x }, - enumerable: true - }, - y: { - get: function () { return y }, - enumerable: true - }, - mods: { - get: function () { return mods }, - enumerable: true - } - }) - - return result -} - -},{"mouse-event":437}],436:[function(_dereq_,module,exports){ -var rootPosition = { left: 0, top: 0 } - -module.exports = mouseEventOffset -function mouseEventOffset (ev, target, out) { - target = target || ev.currentTarget || ev.srcElement - if (!Array.isArray(out)) { - out = [ 0, 0 ] - } - var cx = ev.clientX || 0 - var cy = ev.clientY || 0 - var rect = getBoundingClientOffset(target) - out[0] = cx - rect.left - out[1] = cy - rect.top - return out -} - -function getBoundingClientOffset (element) { - if (element === window || - element === document || - element === document.body) { - return rootPosition - } else { - return element.getBoundingClientRect() - } -} - -},{}],437:[function(_dereq_,module,exports){ -'use strict' - -function mouseButtons(ev) { - if(typeof ev === 'object') { - if('buttons' in ev) { - return ev.buttons - } else if('which' in ev) { - var b = ev.which - if(b === 2) { - return 4 - } else if(b === 3) { - return 2 - } else if(b > 0) { - return 1<<(b-1) - } - } else if('button' in ev) { - var b = ev.button - if(b === 1) { - return 4 - } else if(b === 2) { - return 2 - } else if(b >= 0) { - return 1< 0) { - stepVal.push(stride(i, order[j-1]) + "*" + shape(order[j-1]) ) - } - vars.push(step(i,order[j]) + "=(" + stepVal.join("-") + ")|0") - } - } - //Create index variables - for(var i=0; i=0; --i) { - sizeVariable.push(shape(order[i])) - } - //Previous phases and vertex_ids - vars.push(POOL_SIZE + "=(" + sizeVariable.join("*") + ")|0", - PHASES + "=mallocUint32(" + POOL_SIZE + ")", - VERTEX_IDS + "=mallocUint32(" + POOL_SIZE + ")", - POINTER + "=0") - //Create cube variables for phases - vars.push(pcube(0) + "=0") - for(var j=1; j<(1<=0; --i) { - forLoopBegin(i, 0) - } - var phaseFuncArgs = [] - for(var i=0; i0; k=(k-1)&subset) { - faceArgs.push(VERTEX_IDS + "[" + POINTER + "+" + pdelta(k) + "]") - } - faceArgs.push(vert(0)) - for(var k=0; k0){", - index(order[i]), "=1;") - createLoop(i-1, mask|(1< 0") - } - if(typeof args.vertex !== "function") { - error("Must specify vertex creation function") - } - if(typeof args.cell !== "function") { - error("Must specify cell creation function") - } - if(typeof args.phase !== "function") { - error("Must specify phase function") - } - var getters = args.getters || [] - var typesig = new Array(arrays) - for(var i=0; i= 0) { - typesig[i] = true - } else { - typesig[i] = false - } - } - return compileSurfaceProcedure( - args.vertex, - args.cell, - args.phase, - scalars, - order, - typesig) -} -},{"typedarray-pool":545}],440:[function(_dereq_,module,exports){ -"use strict" - - - -var fill = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_1_arg1_=_inline_1_arg2_.apply(void 0,_inline_1_arg0_)}","args":[{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_1_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_1_arg2_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"cwise","blockSize":64}) - -module.exports = function(array, f) { - fill(array, f) - return array -} - -},{"cwise/lib/wrapper":149}],441:[function(_dereq_,module,exports){ -'use strict' - -module.exports = gradient - -var dup = _dereq_('dup') -var cwiseCompiler = _dereq_('cwise-compiler') - -var TEMPLATE_CACHE = {} -var GRADIENT_CACHE = {} - -var EmptyProc = { - body: "", - args: [], - thisVars: [], - localVars: [] -} - -var centralDiff = cwiseCompiler({ - args: [ 'array', 'array', 'array' ], - pre: EmptyProc, - post: EmptyProc, - body: { - args: [ { - name: 'out', - lvalue: true, - rvalue: false, - count: 1 - }, { - name: 'left', - lvalue: false, - rvalue: true, - count: 1 - }, { - name: 'right', - lvalue: false, - rvalue: true, - count: 1 - }], - body: "out=0.5*(left-right)", - thisVars: [], - localVars: [] - }, - funcName: 'cdiff' -}) - -var zeroOut = cwiseCompiler({ - args: [ 'array' ], - pre: EmptyProc, - post: EmptyProc, - body: { - args: [ { - name: 'out', - lvalue: true, - rvalue: false, - count: 1 - }], - body: "out=0", - thisVars: [], - localVars: [] - }, - funcName: 'zero' -}) - -function generateTemplate(d) { - if(d in TEMPLATE_CACHE) { - return TEMPLATE_CACHE[d] - } - var code = [] - for(var i=0; i= 0) { - pickStr.push('0') - } else if(facet.indexOf(-(i+1)) >= 0) { - pickStr.push('s['+i+']-1') - } else { - pickStr.push('-1') - loStr.push('1') - hiStr.push('s['+i+']-2') - } - } - var boundStr = '.lo(' + loStr.join() + ').hi(' + hiStr.join() + ')' - if(loStr.length === 0) { - boundStr = '' - } - - if(cod > 0) { - code.push('if(1') - for(var i=0; i= 0 || facet.indexOf(-(i+1)) >= 0) { - continue - } - code.push('&&s[', i, ']>2') - } - code.push('){grad', cod, '(src.pick(', pickStr.join(), ')', boundStr) - for(var i=0; i= 0 || facet.indexOf(-(i+1)) >= 0) { - continue - } - code.push(',dst.pick(', pickStr.join(), ',', i, ')', boundStr) - } - code.push(');') - } - - for(var i=0; i1){dst.set(', - pickStr.join(), ',', bnd, ',0.5*(src.get(', - cPickStr.join(), ')-src.get(', - dPickStr.join(), ')))}else{dst.set(', - pickStr.join(), ',', bnd, ',0)};') - } else { - code.push('if(s[', bnd, ']>1){diff(', outStr, - ',src.pick(', cPickStr.join(), ')', boundStr, - ',src.pick(', dPickStr.join(), ')', boundStr, - ');}else{zero(', outStr, ');};') - } - break - - case 'mirror': - if(cod === 0) { - code.push('dst.set(', pickStr.join(), ',', bnd, ',0);') - } else { - code.push('zero(', outStr, ');') - } - break - - case 'wrap': - var aPickStr = pickStr.slice() - var bPickStr = pickStr.slice() - if(facet[i] < 0) { - aPickStr[bnd] = 's[' + bnd + ']-2' - bPickStr[bnd] = '0' - - } else { - aPickStr[bnd] = 's[' + bnd + ']-1' - bPickStr[bnd] = '1' - } - if(cod === 0) { - code.push('if(s[', bnd, ']>2){dst.set(', - pickStr.join(), ',', bnd, ',0.5*(src.get(', - aPickStr.join(), ')-src.get(', - bPickStr.join(), ')))}else{dst.set(', - pickStr.join(), ',', bnd, ',0)};') - } else { - code.push('if(s[', bnd, ']>2){diff(', outStr, - ',src.pick(', aPickStr.join(), ')', boundStr, - ',src.pick(', bPickStr.join(), ')', boundStr, - ');}else{zero(', outStr, ');};') - } - break - - default: - throw new Error('ndarray-gradient: Invalid boundary condition') - } - } - - if(cod > 0) { - code.push('};') - } - } - - //Enumerate ridges, facets, etc. of hypercube - for(var i=0; i<(1<>", - rrshift: ">>>" -} -;(function(){ - for(var id in assign_ops) { - var op = assign_ops[id] - exports[id] = makeOp({ - args: ["array","array","array"], - body: {args:["a","b","c"], - body: "a=b"+op+"c"}, - funcName: id - }) - exports[id+"eq"] = makeOp({ - args: ["array","array"], - body: {args:["a","b"], - body:"a"+op+"=b"}, - rvalue: true, - funcName: id+"eq" - }) - exports[id+"s"] = makeOp({ - args: ["array", "array", "scalar"], - body: {args:["a","b","s"], - body:"a=b"+op+"s"}, - funcName: id+"s" - }) - exports[id+"seq"] = makeOp({ - args: ["array","scalar"], - body: {args:["a","s"], - body:"a"+op+"=s"}, - rvalue: true, - funcName: id+"seq" - }) - } -})(); - -var unary_ops = { - not: "!", - bnot: "~", - neg: "-", - recip: "1.0/" -} -;(function(){ - for(var id in unary_ops) { - var op = unary_ops[id] - exports[id] = makeOp({ - args: ["array", "array"], - body: {args:["a","b"], - body:"a="+op+"b"}, - funcName: id - }) - exports[id+"eq"] = makeOp({ - args: ["array"], - body: {args:["a"], - body:"a="+op+"a"}, - rvalue: true, - count: 2, - funcName: id+"eq" - }) - } -})(); - -var binary_ops = { - and: "&&", - or: "||", - eq: "===", - neq: "!==", - lt: "<", - gt: ">", - leq: "<=", - geq: ">=" -} -;(function() { - for(var id in binary_ops) { - var op = binary_ops[id] - exports[id] = makeOp({ - args: ["array","array","array"], - body: {args:["a", "b", "c"], - body:"a=b"+op+"c"}, - funcName: id - }) - exports[id+"s"] = makeOp({ - args: ["array","array","scalar"], - body: {args:["a", "b", "s"], - body:"a=b"+op+"s"}, - funcName: id+"s" - }) - exports[id+"eq"] = makeOp({ - args: ["array", "array"], - body: {args:["a", "b"], - body:"a=a"+op+"b"}, - rvalue:true, - count:2, - funcName: id+"eq" - }) - exports[id+"seq"] = makeOp({ - args: ["array", "scalar"], - body: {args:["a","s"], - body:"a=a"+op+"s"}, - rvalue:true, - count:2, - funcName: id+"seq" - }) - } -})(); - -var math_unary = [ - "abs", - "acos", - "asin", - "atan", - "ceil", - "cos", - "exp", - "floor", - "log", - "round", - "sin", - "sqrt", - "tan" -] -;(function() { - for(var i=0; ithis_s){this_s=-a}else if(a>this_s){this_s=a}", localVars: [], thisVars: ["this_s"]}, - post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"}, - funcName: "norminf" -}) - -exports.norm1 = compile({ - args:["array"], - pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"}, - body: {args:[{name:"a", lvalue:false, rvalue:true, count:3}], body: "this_s+=a<0?-a:a", localVars: [], thisVars: ["this_s"]}, - post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"}, - funcName: "norm1" -}) - -exports.sup = compile({ - args: [ "array" ], - pre: - { body: "this_h=-Infinity", - args: [], - thisVars: [ "this_h" ], - localVars: [] }, - body: - { body: "if(_inline_1_arg0_>this_h)this_h=_inline_1_arg0_", - args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ], - thisVars: [ "this_h" ], - localVars: [] }, - post: - { body: "return this_h", - args: [], - thisVars: [ "this_h" ], - localVars: [] } - }) - -exports.inf = compile({ - args: [ "array" ], - pre: - { body: "this_h=Infinity", - args: [], - thisVars: [ "this_h" ], - localVars: [] }, - body: - { body: "if(_inline_1_arg0_this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}", - args:[ - {name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2}, - {name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}], - thisVars:["this_i","this_v"], - localVars:["_inline_1_k"]}, - post:{ - body:"{return this_i}", - args:[], - thisVars:["this_i"], - localVars:[]} -}) - -exports.random = makeOp({ - args: ["array"], - pre: {args:[], body:"this_f=Math.random", thisVars:["this_f"]}, - body: {args: ["a"], body:"a=this_f()", thisVars:["this_f"]}, - funcName: "random" -}) - -exports.assign = makeOp({ - args:["array", "array"], - body: {args:["a", "b"], body:"a=b"}, - funcName: "assign" }) - -exports.assigns = makeOp({ - args:["array", "scalar"], - body: {args:["a", "b"], body:"a=b"}, - funcName: "assigns" }) - - -exports.equals = compile({ - args:["array", "array"], - pre: EmptyProc, - body: {args:[{name:"x", lvalue:false, rvalue:true, count:1}, - {name:"y", lvalue:false, rvalue:true, count:1}], - body: "if(x!==y){return false}", - localVars: [], - thisVars: []}, - post: {args:[], localVars:[], thisVars:[], body:"return true"}, - funcName: "equals" -}) - - - -},{"cwise-compiler":146}],445:[function(_dereq_,module,exports){ -"use strict" - -var ndarray = _dereq_("ndarray") -var do_convert = _dereq_("./doConvert.js") - -module.exports = function convert(arr, result) { - var shape = [], c = arr, sz = 1 - while(Array.isArray(c)) { - shape.push(c.length) - sz *= c.length - c = c[0] - } - if(shape.length === 0) { - return ndarray() - } - if(!result) { - result = ndarray(new Float64Array(sz), shape) - } - do_convert(result, arr) - return result -} - -},{"./doConvert.js":446,"ndarray":450}],446:[function(_dereq_,module,exports){ -module.exports=_dereq_('cwise-compiler')({"args":["array","scalar","index"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{\nvar _inline_1_v=_inline_1_arg1_,_inline_1_i\nfor(_inline_1_i=0;_inline_1_i<_inline_1_arg2_.length-1;++_inline_1_i) {\n_inline_1_v=_inline_1_v[_inline_1_arg2_[_inline_1_i]]\n}\n_inline_1_arg0_=_inline_1_v[_inline_1_arg2_[_inline_1_arg2_.length-1]]\n}","args":[{"name":"_inline_1_arg0_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_1_arg1_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_1_arg2_","lvalue":false,"rvalue":true,"count":4}],"thisVars":[],"localVars":["_inline_1_i","_inline_1_v"]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"funcName":"convert","blockSize":64}) - -},{"cwise-compiler":146}],447:[function(_dereq_,module,exports){ -"use strict" - -var pool = _dereq_("typedarray-pool") - -var INSERTION_SORT_THRESHOLD = 32 - -function getMallocFree(dtype) { - switch(dtype) { - case "uint8": - return [pool.mallocUint8, pool.freeUint8] - case "uint16": - return [pool.mallocUint16, pool.freeUint16] - case "uint32": - return [pool.mallocUint32, pool.freeUint32] - case "int8": - return [pool.mallocInt8, pool.freeInt8] - case "int16": - return [pool.mallocInt16, pool.freeInt16] - case "int32": - return [pool.mallocInt32, pool.freeInt32] - case "float32": - return [pool.mallocFloat, pool.freeFloat] - case "float64": - return [pool.mallocDouble, pool.freeDouble] - default: - return null - } -} - -function shapeArgs(dimension) { - var args = [] - for(var i=0; i 1) { - var scratch_shape = [] - for(var i=1; i 1) { - - //Copy data into scratch - code.push("dptr=0;sptr=ptr") - for(var i=order.length-1; i>=0; --i) { - var j = order[i] - if(j === 0) { - continue - } - code.push(["for(i",j,"=0;i",j,"left){", - "dptr=0", - "sptr=cptr-s0") - for(var i=1; ib){break __l}"].join("")) - for(var i=order.length-1; i>=1; --i) { - code.push( - "sptr+=e"+i, - "dptr+=f"+i, - "}") - } - - //Copy data back - code.push("dptr=cptr;sptr=cptr-s0") - for(var i=order.length-1; i>=0; --i) { - var j = order[i] - if(j === 0) { - continue - } - code.push(["for(i",j,"=0;i",j,"=0; --i) { - var j = order[i] - if(j === 0) { - continue - } - code.push(["for(i",j,"=0;i",j,"left)&&("+dataRead("cptr-s0")+">scratch)){", - dataWrite("cptr", dataRead("cptr-s0")), - "cptr-=s0", - "}", - dataWrite("cptr", "scratch")) - } - - //Close outer loop body - code.push("}") - if(order.length > 1 && allocator) { - code.push("free(scratch)") - } - code.push("} return " + funcName) - - //Compile and link function - if(allocator) { - var result = new Function("malloc", "free", code.join("\n")) - return result(allocator[0], allocator[1]) - } else { - var result = new Function(code.join("\n")) - return result() - } -} - -function createQuickSort(order, dtype, insertionSort) { - var code = [ "'use strict'" ] - var funcName = ["ndarrayQuickSort", order.join("d"), dtype].join("") - var funcArgs = ["left", "right", "data", "offset" ].concat(shapeArgs(order.length)) - var allocator = getMallocFree(dtype) - var labelCounter=0 - - code.push(["function ", funcName, "(", funcArgs.join(","), "){"].join("")) - - var vars = [ - "sixth=((right-left+1)/6)|0", - "index1=left+sixth", - "index5=right-sixth", - "index3=(left+right)>>1", - "index2=index3-sixth", - "index4=index3+sixth", - "el1=index1", - "el2=index2", - "el3=index3", - "el4=index4", - "el5=index5", - "less=left+1", - "great=right-1", - "pivots_are_equal=true", - "tmp", - "tmp0", - "x", - "y", - "z", - "k", - "ptr0", - "ptr1", - "ptr2", - "comp_pivot1=0", - "comp_pivot2=0", - "comp=0" - ] - - if(order.length > 1) { - var ele_size = [] - for(var i=1; i=0; --i) { - var j = order[i] - if(j === 0) { - continue - } - code.push(["for(i",j,"=0;i",j," 1) { - for(var i=0; i1) { - code.push("ptr_shift+=d"+j) - } else { - code.push("ptr0+=d"+j) - } - code.push("}") - } - } - - function lexicoLoop(label, ptrs, usePivot, body) { - if(ptrs.length === 1) { - code.push("ptr0="+toPointer(ptrs[0])) - } else { - for(var i=0; i 1) { - for(var i=0; i=1; --i) { - if(usePivot) { - code.push("pivot_ptr+=f"+i) - } - if(ptrs.length > 1) { - code.push("ptr_shift+=e"+i) - } else { - code.push("ptr0+=e"+i) - } - code.push("}") - } - } - - function cleanUp() { - if(order.length > 1 && allocator) { - code.push("free(pivot1)", "free(pivot2)") - } - } - - function compareSwap(a_id, b_id) { - var a = "el"+a_id - var b = "el"+b_id - if(order.length > 1) { - var lbl = "__l" + (++labelCounter) - lexicoLoop(lbl, [a, b], false, [ - "comp=",dataRead("ptr0"),"-",dataRead("ptr1"),"\n", - "if(comp>0){tmp0=", a, ";",a,"=",b,";", b,"=tmp0;break ", lbl,"}\n", - "if(comp<0){break ", lbl, "}" - ].join("")) - } else { - code.push(["if(", dataRead(toPointer(a)), ">", dataRead(toPointer(b)), "){tmp0=", a, ";",a,"=",b,";", b,"=tmp0}"].join("")) - } - } - - compareSwap(1, 2) - compareSwap(4, 5) - compareSwap(1, 3) - compareSwap(2, 3) - compareSwap(1, 4) - compareSwap(3, 4) - compareSwap(2, 5) - compareSwap(2, 3) - compareSwap(4, 5) - - if(order.length > 1) { - cacheLoop(["el1", "el2", "el3", "el4", "el5", "index1", "index3", "index5"], true, [ - "pivot1[pivot_ptr]=",dataRead("ptr1"),"\n", - "pivot2[pivot_ptr]=",dataRead("ptr3"),"\n", - "pivots_are_equal=pivots_are_equal&&(pivot1[pivot_ptr]===pivot2[pivot_ptr])\n", - "x=",dataRead("ptr0"),"\n", - "y=",dataRead("ptr2"),"\n", - "z=",dataRead("ptr4"),"\n", - dataWrite("ptr5", "x"),"\n", - dataWrite("ptr6", "y"),"\n", - dataWrite("ptr7", "z") - ].join("")) - } else { - code.push([ - "pivot1=", dataRead(toPointer("el2")), "\n", - "pivot2=", dataRead(toPointer("el4")), "\n", - "pivots_are_equal=pivot1===pivot2\n", - "x=", dataRead(toPointer("el1")), "\n", - "y=", dataRead(toPointer("el3")), "\n", - "z=", dataRead(toPointer("el5")), "\n", - dataWrite(toPointer("index1"), "x"), "\n", - dataWrite(toPointer("index3"), "y"), "\n", - dataWrite(toPointer("index5"), "z") - ].join("")) - } - - - function moveElement(dst, src) { - if(order.length > 1) { - cacheLoop([dst, src], false, - dataWrite("ptr0", dataRead("ptr1")) - ) - } else { - code.push(dataWrite(toPointer(dst), dataRead(toPointer(src)))) - } - } - - moveElement("index2", "left") - moveElement("index4", "right") - - function comparePivot(result, ptr, n) { - if(order.length > 1) { - var lbl = "__l" + (++labelCounter) - lexicoLoop(lbl, [ptr], true, [ - result,"=",dataRead("ptr0"),"-pivot",n,"[pivot_ptr]\n", - "if(",result,"!==0){break ", lbl, "}" - ].join("")) - } else { - code.push([result,"=", dataRead(toPointer(ptr)), "-pivot", n].join("")) - } - } - - function swapElements(a, b) { - if(order.length > 1) { - cacheLoop([a,b],false,[ - "tmp=",dataRead("ptr0"),"\n", - dataWrite("ptr0", dataRead("ptr1")),"\n", - dataWrite("ptr1", "tmp") - ].join("")) - } else { - code.push([ - "ptr0=",toPointer(a),"\n", - "ptr1=",toPointer(b),"\n", - "tmp=",dataRead("ptr0"),"\n", - dataWrite("ptr0", dataRead("ptr1")),"\n", - dataWrite("ptr1", "tmp") - ].join("")) - } - } - - function tripleSwap(k, less, great) { - if(order.length > 1) { - cacheLoop([k,less,great], false, [ - "tmp=",dataRead("ptr0"),"\n", - dataWrite("ptr0", dataRead("ptr1")),"\n", - dataWrite("ptr1", dataRead("ptr2")),"\n", - dataWrite("ptr2", "tmp") - ].join("")) - code.push("++"+less, "--"+great) - } else { - code.push([ - "ptr0=",toPointer(k),"\n", - "ptr1=",toPointer(less),"\n", - "ptr2=",toPointer(great),"\n", - "++",less,"\n", - "--",great,"\n", - "tmp=", dataRead("ptr0"), "\n", - dataWrite("ptr0", dataRead("ptr1")), "\n", - dataWrite("ptr1", dataRead("ptr2")), "\n", - dataWrite("ptr2", "tmp") - ].join("")) - } - } - - function swapAndDecrement(k, great) { - swapElements(k, great) - code.push("--"+great) - } - - code.push("if(pivots_are_equal){") - //Pivots are equal case - code.push("for(k=less;k<=great;++k){") - comparePivot("comp", "k", 1) - code.push("if(comp===0){continue}") - code.push("if(comp<0){") - code.push("if(k!==less){") - swapElements("k", "less") - code.push("}") - code.push("++less") - code.push("}else{") - code.push("while(true){") - comparePivot("comp", "great", 1) - code.push("if(comp>0){") - code.push("great--") - code.push("}else if(comp<0){") - tripleSwap("k", "less", "great") - code.push("break") - code.push("}else{") - swapAndDecrement("k", "great") - code.push("break") - code.push("}") - code.push("}") - code.push("}") - code.push("}") - code.push("}else{") - //Pivots not equal case - code.push("for(k=less;k<=great;++k){") - comparePivot("comp_pivot1", "k", 1) - code.push("if(comp_pivot1<0){") - code.push("if(k!==less){") - swapElements("k", "less") - code.push("}") - code.push("++less") - code.push("}else{") - comparePivot("comp_pivot2", "k", 2) - code.push("if(comp_pivot2>0){") - code.push("while(true){") - comparePivot("comp", "great", 2) - code.push("if(comp>0){") - code.push("if(--great1) { - cacheLoop([mem_dest, pivot_dest], true, [ - dataWrite("ptr0", dataRead("ptr1")), "\n", - dataWrite("ptr1", ["pivot",pivot,"[pivot_ptr]"].join("")) - ].join("")) - } else { - code.push( - dataWrite(toPointer(mem_dest), dataRead(toPointer(pivot_dest))), - dataWrite(toPointer(pivot_dest), "pivot"+pivot)) - } - } - - storePivot("left", "(less-1)", 1) - storePivot("right", "(great+1)", 2) - - //Recursive sort call - function doSort(left, right) { - code.push([ - "if((",right,"-",left,")<=",INSERTION_SORT_THRESHOLD,"){\n", - "insertionSort(", left, ",", right, ",data,offset,", shapeArgs(order.length).join(","), ")\n", - "}else{\n", - funcName, "(", left, ",", right, ",data,offset,", shapeArgs(order.length).join(","), ")\n", - "}" - ].join("")) - } - doSort("left", "(less-2)") - doSort("(great+2)", "right") - - //If pivots are equal, then early out - code.push("if(pivots_are_equal){") - cleanUp() - code.push("return") - code.push("}") - - function walkPointer(ptr, pivot, body) { - if(order.length > 1) { - code.push(["__l",++labelCounter,":while(true){"].join("")) - cacheLoop([ptr], true, [ - "if(", dataRead("ptr0"), "!==pivot", pivot, "[pivot_ptr]){break __l", labelCounter, "}" - ].join("")) - code.push(body, "}") - } else { - code.push(["while(", dataRead(toPointer(ptr)), "===pivot", pivot, "){", body, "}"].join("")) - } - } - - //Check bounds - code.push("if(lessindex5){") - - walkPointer("less", 1, "++less") - walkPointer("great", 2, "--great") - - code.push("for(k=less;k<=great;++k){") - comparePivot("comp_pivot1", "k", 1) - code.push("if(comp_pivot1===0){") - code.push("if(k!==less){") - swapElements("k", "less") - code.push("}") - code.push("++less") - code.push("}else{") - comparePivot("comp_pivot2", "k", 2) - code.push("if(comp_pivot2===0){") - code.push("while(true){") - comparePivot("comp", "great", 2) - code.push("if(comp===0){") - code.push("if(--great 1 && allocator) { - var compiled = new Function("insertionSort", "malloc", "free", code.join("\n")) - return compiled(insertionSort, allocator[0], allocator[1]) - } - var compiled = new Function("insertionSort", code.join("\n")) - return compiled(insertionSort) -} - -function compileSort(order, dtype) { - var code = ["'use strict'"] - var funcName = ["ndarraySortWrapper", order.join("d"), dtype].join("") - var funcArgs = [ "array" ] - - code.push(["function ", funcName, "(", funcArgs.join(","), "){"].join("")) - - //Unpack local variables from array - var vars = ["data=array.data,offset=array.offset|0,shape=array.shape,stride=array.stride"] - for(var i=0; i 0) { - vars.push(["d",j,"=s",j,"-d",p,"*n",p].join("")) - } else { - vars.push(["d",j,"=s",j].join("")) - } - p = j - } - var k = order.length-1-i - if(k !== 0) { - if(q > 0) { - vars.push(["e",k,"=s",k,"-e",q,"*n",q, - ",f",k,"=",scratch_stride[k],"-f",q,"*n",q].join("")) - } else { - vars.push(["e",k,"=s",k,",f",k,"=",scratch_stride[k]].join("")) - } - q = k - } - } - - //Declare local variables - code.push("var " + vars.join(",")) - - //Create arguments for subroutine - var sortArgs = ["0", "n0-1", "data", "offset"].concat(shapeArgs(order.length)) - - //Call main sorting routine - code.push([ - "if(n0<=",INSERTION_SORT_THRESHOLD,"){", - "insertionSort(", sortArgs.join(","), ")}else{", - "quickSort(", sortArgs.join(","), - ")}" - ].join("")) - - //Return - code.push("}return " + funcName) - - //Link everything together - var result = new Function("insertionSort", "quickSort", code.join("\n")) - var insertionSort = createInsertionSort(order, dtype) - var quickSort = createQuickSort(order, dtype, insertionSort) - return result(insertionSort, quickSort) -} - -module.exports = compileSort -},{"typedarray-pool":545}],448:[function(_dereq_,module,exports){ -"use strict" - -var compile = _dereq_("./lib/compile_sort.js") -var CACHE = {} - -function sort(array) { - var order = array.order - var dtype = array.dtype - var typeSig = [order, dtype ] - var typeName = typeSig.join(":") - var compiled = CACHE[typeName] - if(!compiled) { - CACHE[typeName] = compiled = compile(order, dtype) - } - compiled(array) - return array -} - -module.exports = sort -},{"./lib/compile_sort.js":447}],449:[function(_dereq_,module,exports){ -'use strict' - -var interp = _dereq_('ndarray-linear-interpolate') - - -var do_warp = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=new Array(_inline_3_arg4_)}","args":[{"name":"_inline_3_arg0_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_3_arg1_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_3_arg2_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_3_arg3_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_3_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_4_arg2_(this_warped,_inline_4_arg0_),_inline_4_arg1_=_inline_4_arg3_.apply(void 0,this_warped)}","args":[{"name":"_inline_4_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_4_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_4_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_4_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_4_arg4_","lvalue":false,"rvalue":false,"count":0}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warpND","blockSize":64}) - -var do_warp_1 = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=[0]}","args":[],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_7_arg2_(this_warped,_inline_7_arg0_),_inline_7_arg1_=_inline_7_arg3_(_inline_7_arg4_,this_warped[0])}","args":[{"name":"_inline_7_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_7_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_7_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_7_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_7_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warp1D","blockSize":64}) - -var do_warp_2 = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=[0,0]}","args":[],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_10_arg2_(this_warped,_inline_10_arg0_),_inline_10_arg1_=_inline_10_arg3_(_inline_10_arg4_,this_warped[0],this_warped[1])}","args":[{"name":"_inline_10_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_10_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_10_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_10_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_10_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warp2D","blockSize":64}) - -var do_warp_3 = _dereq_('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=[0,0,0]}","args":[],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_13_arg2_(this_warped,_inline_13_arg0_),_inline_13_arg1_=_inline_13_arg3_(_inline_13_arg4_,this_warped[0],this_warped[1],this_warped[2])}","args":[{"name":"_inline_13_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_13_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_13_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_13_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_13_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warp3D","blockSize":64}) - -module.exports = function warp(dest, src, func) { - switch(src.shape.length) { - case 1: - do_warp_1(dest, func, interp.d1, src) - break - case 2: - do_warp_2(dest, func, interp.d2, src) - break - case 3: - do_warp_3(dest, func, interp.d3, src) - break - default: - do_warp(dest, func, interp.bind(undefined, src), src.shape.length) - break - } - return dest -} - -},{"cwise/lib/wrapper":149,"ndarray-linear-interpolate":443}],450:[function(_dereq_,module,exports){ -var iota = _dereq_("iota-array") -var isBuffer = _dereq_("is-buffer") - -var hasTypedArrays = ((typeof Float64Array) !== "undefined") - -function compare1st(a, b) { - return a[0] - b[0] -} - -function order() { - var stride = this.stride - var terms = new Array(stride.length) - var i - for(i=0; iMath.abs(this.stride[1]))?[1,0]:[0,1]}})") - } else if(dimension === 3) { - code.push( -"var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);\ -if(s0>s1){\ -if(s1>s2){\ -return [2,1,0];\ -}else if(s0>s2){\ -return [1,2,0];\ -}else{\ -return [1,0,2];\ -}\ -}else if(s0>s2){\ -return [2,0,1];\ -}else if(s2>s1){\ -return [0,1,2];\ -}else{\ -return [0,2,1];\ -}}})") - } - } else { - code.push("ORDER})") - } - } - - //view.set(i0, ..., v): - code.push( -"proto.set=function "+className+"_set("+args.join(",")+",v){") - if(useGetters) { - code.push("return this.data.set("+index_str+",v)}") - } else { - code.push("return this.data["+index_str+"]=v}") - } - - //view.get(i0, ...): - code.push("proto.get=function "+className+"_get("+args.join(",")+"){") - if(useGetters) { - code.push("return this.data.get("+index_str+")}") - } else { - code.push("return this.data["+index_str+"]}") - } - - //view.index: - code.push( - "proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}") - - //view.hi(): - code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+ - indices.map(function(i) { - return ["(typeof i",i,"!=='number'||i",i,"<0)?this.shape[", i, "]:i", i,"|0"].join("") - }).join(",")+","+ - indices.map(function(i) { - return "this.stride["+i + "]" - }).join(",")+",this.offset)}") - - //view.lo(): - var a_vars = indices.map(function(i) { return "a"+i+"=this.shape["+i+"]" }) - var c_vars = indices.map(function(i) { return "c"+i+"=this.stride["+i+"]" }) - code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(",")) - for(var i=0; i=0){\ -d=i"+i+"|0;\ -b+=c"+i+"*d;\ -a"+i+"-=d}") - } - code.push("return new "+className+"(this.data,"+ - indices.map(function(i) { - return "a"+i - }).join(",")+","+ - indices.map(function(i) { - return "c"+i - }).join(",")+",b)}") - - //view.step(): - code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+ - indices.map(function(i) { - return "a"+i+"=this.shape["+i+"]" - }).join(",")+","+ - indices.map(function(i) { - return "b"+i+"=this.stride["+i+"]" - }).join(",")+",c=this.offset,d=0,ceil=Math.ceil") - for(var i=0; i=0){c=(c+this.stride["+i+"]*i"+i+")|0}else{a.push(this.shape["+i+"]);b.push(this.stride["+i+"])}") - } - code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}") - - //Add return statement - code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+ - indices.map(function(i) { - return "shape["+i+"]" - }).join(",")+","+ - indices.map(function(i) { - return "stride["+i+"]" - }).join(",")+",offset)}") - - //Compile procedure - var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n")) - return procedure(CACHED_CONSTRUCTORS[dtype], order) -} - -function arrayDType(data) { - if(isBuffer(data)) { - return "buffer" - } - if(hasTypedArrays) { - switch(Object.prototype.toString.call(data)) { - case "[object Float64Array]": - return "float64" - case "[object Float32Array]": - return "float32" - case "[object Int8Array]": - return "int8" - case "[object Int16Array]": - return "int16" - case "[object Int32Array]": - return "int32" - case "[object Uint8Array]": - return "uint8" - case "[object Uint16Array]": - return "uint16" - case "[object Uint32Array]": - return "uint32" - case "[object Uint8ClampedArray]": - return "uint8_clamped" - } - } - if(Array.isArray(data)) { - return "array" - } - return "generic" -} - -var CACHED_CONSTRUCTORS = { - "float32":[], - "float64":[], - "int8":[], - "int16":[], - "int32":[], - "uint8":[], - "uint16":[], - "uint32":[], - "array":[], - "uint8_clamped":[], - "buffer":[], - "generic":[] -} - -;(function() { - for(var id in CACHED_CONSTRUCTORS) { - CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1)) - } -}); - -function wrappedNDArrayCtor(data, shape, stride, offset) { - if(data === undefined) { - var ctor = CACHED_CONSTRUCTORS.array[0] - return ctor([]) - } else if(typeof data === "number") { - data = [data] - } - if(shape === undefined) { - shape = [ data.length ] - } - var d = shape.length - if(stride === undefined) { - stride = new Array(d) - for(var i=d-1, sz=1; i>=0; --i) { - stride[i] = sz - sz *= shape[i] - } - } - if(offset === undefined) { - offset = 0 - for(var i=0; i>>0 - -module.exports = nextafter - -function nextafter(x, y) { - if(isNaN(x) || isNaN(y)) { - return NaN - } - if(x === y) { - return x - } - if(x === 0) { - if(y < 0) { - return -SMALLEST_DENORM - } else { - return SMALLEST_DENORM - } - } - var hi = doubleBits.hi(x) - var lo = doubleBits.lo(x) - if((y > x) === (x > 0)) { - if(lo === UINT_MAX) { - hi += 1 - lo = 0 - } else { - lo += 1 - } - } else { - if(lo === 0) { - lo = UINT_MAX - hi -= 1 - } else { - lo -= 1 - } - } - return doubleBits.pack(lo, hi) -} -},{"double-bits":167}],452:[function(_dereq_,module,exports){ - -var π = Math.PI -var _120 = radians(120) - -module.exports = normalize - -/** - * describe `path` in terms of cubic bézier - * curves and move commands - * - * @param {Array} path - * @return {Array} - */ - -function normalize(path){ - // init state - var prev - var result = [] - var bezierX = 0 - var bezierY = 0 - var startX = 0 - var startY = 0 - var quadX = null - var quadY = null - var x = 0 - var y = 0 - - for (var i = 0, len = path.length; i < len; i++) { - var seg = path[i] - var command = seg[0] - switch (command) { - case 'M': - startX = seg[1] - startY = seg[2] - break - case 'A': - seg = arc(x, y,seg[1],seg[2],radians(seg[3]),seg[4],seg[5],seg[6],seg[7]) - // split multi part - seg.unshift('C') - if (seg.length > 7) { - result.push(seg.splice(0, 7)) - seg.unshift('C') - } - break - case 'S': - // default control point - var cx = x - var cy = y - if (prev == 'C' || prev == 'S') { - cx += cx - bezierX // reflect the previous command's control - cy += cy - bezierY // point relative to the current point - } - seg = ['C', cx, cy, seg[1], seg[2], seg[3], seg[4]] - break - case 'T': - if (prev == 'Q' || prev == 'T') { - quadX = x * 2 - quadX // as with 'S' reflect previous control point - quadY = y * 2 - quadY - } else { - quadX = x - quadY = y - } - seg = quadratic(x, y, quadX, quadY, seg[1], seg[2]) - break - case 'Q': - quadX = seg[1] - quadY = seg[2] - seg = quadratic(x, y, seg[1], seg[2], seg[3], seg[4]) - break - case 'L': - seg = line(x, y, seg[1], seg[2]) - break - case 'H': - seg = line(x, y, seg[1], y) - break - case 'V': - seg = line(x, y, x, seg[1]) - break - case 'Z': - seg = line(x, y, startX, startY) - break - } - - // update state - prev = command - x = seg[seg.length - 2] - y = seg[seg.length - 1] - if (seg.length > 4) { - bezierX = seg[seg.length - 4] - bezierY = seg[seg.length - 3] - } else { - bezierX = x - bezierY = y - } - result.push(seg) - } - - return result -} - -function line(x1, y1, x2, y2){ - return ['C', x1, y1, x2, y2, x2, y2] -} - -function quadratic(x1, y1, cx, cy, x2, y2){ - return [ - 'C', - x1/3 + (2/3) * cx, - y1/3 + (2/3) * cy, - x2/3 + (2/3) * cx, - y2/3 + (2/3) * cy, - x2, - y2 - ] -} - -// This function is ripped from -// github.com/DmitryBaranovskiy/raphael/blob/4d97d4/raphael.js#L2216-L2304 -// which references w3.org/TR/SVG11/implnote.html#ArcImplementationNotes -// TODO: make it human readable - -function arc(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { - if (!recursive) { - var xy = rotate(x1, y1, -angle) - x1 = xy.x - y1 = xy.y - xy = rotate(x2, y2, -angle) - x2 = xy.x - y2 = xy.y - var x = (x1 - x2) / 2 - var y = (y1 - y2) / 2 - var h = (x * x) / (rx * rx) + (y * y) / (ry * ry) - if (h > 1) { - h = Math.sqrt(h) - rx = h * rx - ry = h * ry - } - var rx2 = rx * rx - var ry2 = ry * ry - var k = (large_arc_flag == sweep_flag ? -1 : 1) - * Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))) - if (k == Infinity) k = 1 // neutralize - var cx = k * rx * y / ry + (x1 + x2) / 2 - var cy = k * -ry * x / rx + (y1 + y2) / 2 - var f1 = Math.asin(((y1 - cy) / ry).toFixed(9)) - var f2 = Math.asin(((y2 - cy) / ry).toFixed(9)) - - f1 = x1 < cx ? π - f1 : f1 - f2 = x2 < cx ? π - f2 : f2 - if (f1 < 0) f1 = π * 2 + f1 - if (f2 < 0) f2 = π * 2 + f2 - if (sweep_flag && f1 > f2) f1 = f1 - π * 2 - if (!sweep_flag && f2 > f1) f2 = f2 - π * 2 - } else { - f1 = recursive[0] - f2 = recursive[1] - cx = recursive[2] - cy = recursive[3] - } - // greater than 120 degrees requires multiple segments - if (Math.abs(f2 - f1) > _120) { - var f2old = f2 - var x2old = x2 - var y2old = y2 - f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1) - x2 = cx + rx * Math.cos(f2) - y2 = cy + ry * Math.sin(f2) - var res = arc(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]) - } - var t = Math.tan((f2 - f1) / 4) - var hx = 4 / 3 * rx * t - var hy = 4 / 3 * ry * t - var curve = [ - 2 * x1 - (x1 + hx * Math.sin(f1)), - 2 * y1 - (y1 - hy * Math.cos(f1)), - x2 + hx * Math.sin(f2), - y2 - hy * Math.cos(f2), - x2, - y2 - ] - if (recursive) return curve - if (res) curve = curve.concat(res) - for (var i = 0; i < curve.length;) { - var rot = rotate(curve[i], curve[i+1], angle) - curve[i++] = rot.x - curve[i++] = rot.y - } - return curve -} - -function rotate(x, y, rad){ - return { - x: x * Math.cos(rad) - y * Math.sin(rad), - y: x * Math.sin(rad) + y * Math.cos(rad) - } -} - -function radians(degress){ - return degress * (π / 180) -} - -},{}],453:[function(_dereq_,module,exports){ -var DEFAULT_NORMALS_EPSILON = 1e-6; -var DEFAULT_FACE_EPSILON = 1e-6; - -//Estimate the vertex normals of a mesh -exports.vertexNormals = function(faces, positions, specifiedEpsilon) { - - var N = positions.length; - var normals = new Array(N); - var epsilon = specifiedEpsilon === void(0) ? DEFAULT_NORMALS_EPSILON : specifiedEpsilon; - - //Initialize normal array - for(var i=0; i epsilon) { - var norm = normals[c]; - var w = 1.0 / Math.sqrt(m01 * m21); - for(var k=0; k<3; ++k) { - var u = (k+1)%3; - var v = (k+2)%3; - norm[k] += w * (d21[u] * d01[v] - d21[v] * d01[u]); - } - } - } - } - - //Scale all normals to unit length - for(var i=0; i epsilon) { - var w = 1.0 / Math.sqrt(m); - for(var k=0; k<3; ++k) { - norm[k] *= w; - } - } else { - for(var k=0; k<3; ++k) { - norm[k] = 0.0; - } - } - } - - //Return the resulting set of patches - return normals; -} - -//Compute face normals of a mesh -exports.faceNormals = function(faces, positions, specifiedEpsilon) { - - var N = faces.length; - var normals = new Array(N); - var epsilon = specifiedEpsilon === void(0) ? DEFAULT_FACE_EPSILON : specifiedEpsilon; - - for(var i=0; i epsilon) { - l = 1.0 / Math.sqrt(l); - } else { - l = 0.0; - } - for(var j=0; j<3; ++j) { - n[j] *= l; - } - normals[i] = n; - } - return normals; -} - - - -},{}],454:[function(_dereq_,module,exports){ -/* -object-assign -(c) Sindre Sorhus -@license MIT -*/ - -'use strict'; -/* eslint-disable no-unused-vars */ -var getOwnPropertySymbols = Object.getOwnPropertySymbols; -var hasOwnProperty = Object.prototype.hasOwnProperty; -var propIsEnumerable = Object.prototype.propertyIsEnumerable; - -function toObject(val) { - if (val === null || val === undefined) { - throw new TypeError('Object.assign cannot be called with null or undefined'); - } - - return Object(val); -} - -function shouldUseNative() { - try { - if (!Object.assign) { - return false; - } - - // Detect buggy property enumeration order in older V8 versions. - - // https://bugs.chromium.org/p/v8/issues/detail?id=4118 - var test1 = new String('abc'); // eslint-disable-line no-new-wrappers - test1[5] = 'de'; - if (Object.getOwnPropertyNames(test1)[0] === '5') { - return false; - } - - // https://bugs.chromium.org/p/v8/issues/detail?id=3056 - var test2 = {}; - for (var i = 0; i < 10; i++) { - test2['_' + String.fromCharCode(i)] = i; - } - var order2 = Object.getOwnPropertyNames(test2).map(function (n) { - return test2[n]; - }); - if (order2.join('') !== '0123456789') { - return false; - } - - // https://bugs.chromium.org/p/v8/issues/detail?id=3056 - var test3 = {}; - 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { - test3[letter] = letter; - }); - if (Object.keys(Object.assign({}, test3)).join('') !== - 'abcdefghijklmnopqrst') { - return false; - } - - return true; - } catch (err) { - // We don't expect any of the above to throw, but better to be safe. - return false; - } -} - -module.exports = shouldUseNative() ? Object.assign : function (target, source) { - var from; - var to = toObject(target); - var symbols; - - for (var s = 1; s < arguments.length; s++) { - from = Object(arguments[s]); - - for (var key in from) { - if (hasOwnProperty.call(from, key)) { - to[key] = from[key]; - } - } - - if (getOwnPropertySymbols) { - symbols = getOwnPropertySymbols(from); - for (var i = 0; i < symbols.length; i++) { - if (propIsEnumerable.call(from, symbols[i])) { - to[symbols[i]] = from[symbols[i]]; - } - } - } - } - - return to; -}; - -},{}],455:[function(_dereq_,module,exports){ -'use strict' - -module.exports = quatFromFrame - -function quatFromFrame( - out, - rx, ry, rz, - ux, uy, uz, - fx, fy, fz) { - var tr = rx + uy + fz - if(l > 0) { - var l = Math.sqrt(tr + 1.0) - out[0] = 0.5 * (uz - fy) / l - out[1] = 0.5 * (fx - rz) / l - out[2] = 0.5 * (ry - uy) / l - out[3] = 0.5 * l - } else { - var tf = Math.max(rx, uy, fz) - var l = Math.sqrt(2 * tf - tr + 1.0) - if(rx >= tf) { - //x y z order - out[0] = 0.5 * l - out[1] = 0.5 * (ux + ry) / l - out[2] = 0.5 * (fx + rz) / l - out[3] = 0.5 * (uz - fy) / l - } else if(uy >= tf) { - //y z x order - out[0] = 0.5 * (ry + ux) / l - out[1] = 0.5 * l - out[2] = 0.5 * (fy + uz) / l - out[3] = 0.5 * (fx - rz) / l - } else { - //z x y order - out[0] = 0.5 * (rz + fx) / l - out[1] = 0.5 * (uz + fy) / l - out[2] = 0.5 * l - out[3] = 0.5 * (ry - ux) / l - } - } - return out -} -},{}],456:[function(_dereq_,module,exports){ -'use strict' - -module.exports = createOrbitController - -var filterVector = _dereq_('filtered-vector') -var lookAt = _dereq_('gl-mat4/lookAt') -var mat4FromQuat = _dereq_('gl-mat4/fromQuat') -var invert44 = _dereq_('gl-mat4/invert') -var quatFromFrame = _dereq_('./lib/quatFromFrame') - -function len3(x,y,z) { - return Math.sqrt(Math.pow(x,2) + Math.pow(y,2) + Math.pow(z,2)) -} - -function len4(w,x,y,z) { - return Math.sqrt(Math.pow(w,2) + Math.pow(x,2) + Math.pow(y,2) + Math.pow(z,2)) -} - -function normalize4(out, a) { - var ax = a[0] - var ay = a[1] - var az = a[2] - var aw = a[3] - var al = len4(ax, ay, az, aw) - if(al > 1e-6) { - out[0] = ax/al - out[1] = ay/al - out[2] = az/al - out[3] = aw/al - } else { - out[0] = out[1] = out[2] = 0.0 - out[3] = 1.0 - } -} - -function OrbitCameraController(initQuat, initCenter, initRadius) { - this.radius = filterVector([initRadius]) - this.center = filterVector(initCenter) - this.rotation = filterVector(initQuat) - - this.computedRadius = this.radius.curve(0) - this.computedCenter = this.center.curve(0) - this.computedRotation = this.rotation.curve(0) - this.computedUp = [0.1,0,0] - this.computedEye = [0.1,0,0] - this.computedMatrix = [0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - - this.recalcMatrix(0) -} - -var proto = OrbitCameraController.prototype - -proto.lastT = function() { - return Math.max( - this.radius.lastT(), - this.center.lastT(), - this.rotation.lastT()) -} - -proto.recalcMatrix = function(t) { - this.radius.curve(t) - this.center.curve(t) - this.rotation.curve(t) - - var quat = this.computedRotation - normalize4(quat, quat) - - var mat = this.computedMatrix - mat4FromQuat(mat, quat) - - var center = this.computedCenter - var eye = this.computedEye - var up = this.computedUp - var radius = Math.exp(this.computedRadius[0]) - - eye[0] = center[0] + radius * mat[2] - eye[1] = center[1] + radius * mat[6] - eye[2] = center[2] + radius * mat[10] - up[0] = mat[1] - up[1] = mat[5] - up[2] = mat[9] - - for(var i=0; i<3; ++i) { - var rr = 0.0 - for(var j=0; j<3; ++j) { - rr += mat[i+4*j] * eye[j] - } - mat[12+i] = -rr - } -} - -proto.getMatrix = function(t, result) { - this.recalcMatrix(t) - var m = this.computedMatrix - if(result) { - for(var i=0; i<16; ++i) { - result[i] = m[i] - } - return result - } - return m -} - -proto.idle = function(t) { - this.center.idle(t) - this.radius.idle(t) - this.rotation.idle(t) -} - -proto.flush = function(t) { - this.center.flush(t) - this.radius.flush(t) - this.rotation.flush(t) -} - -proto.pan = function(t, dx, dy, dz) { - dx = dx || 0.0 - dy = dy || 0.0 - dz = dz || 0.0 - - this.recalcMatrix(t) - var mat = this.computedMatrix - - var ux = mat[1] - var uy = mat[5] - var uz = mat[9] - var ul = len3(ux, uy, uz) - ux /= ul - uy /= ul - uz /= ul - - var rx = mat[0] - var ry = mat[4] - var rz = mat[8] - var ru = rx * ux + ry * uy + rz * uz - rx -= ux * ru - ry -= uy * ru - rz -= uz * ru - var rl = len3(rx, ry, rz) - rx /= rl - ry /= rl - rz /= rl - - var fx = mat[2] - var fy = mat[6] - var fz = mat[10] - var fu = fx * ux + fy * uy + fz * uz - var fr = fx * rx + fy * ry + fz * rz - fx -= fu * ux + fr * rx - fy -= fu * uy + fr * ry - fz -= fu * uz + fr * rz - var fl = len3(fx, fy, fz) - fx /= fl - fy /= fl - fz /= fl - - var vx = rx * dx + ux * dy - var vy = ry * dx + uy * dy - var vz = rz * dx + uz * dy - - this.center.move(t, vx, vy, vz) - - //Update z-component of radius - var radius = Math.exp(this.computedRadius[0]) - radius = Math.max(1e-4, radius + dz) - this.radius.set(t, Math.log(radius)) -} - -proto.rotate = function(t, dx, dy, dz) { - this.recalcMatrix(t) - - dx = dx||0.0 - dy = dy||0.0 - - var mat = this.computedMatrix - - var rx = mat[0] - var ry = mat[4] - var rz = mat[8] - - var ux = mat[1] - var uy = mat[5] - var uz = mat[9] - - var fx = mat[2] - var fy = mat[6] - var fz = mat[10] - - var qx = dx * rx + dy * ux - var qy = dx * ry + dy * uy - var qz = dx * rz + dy * uz - - var bx = -(fy * qz - fz * qy) - var by = -(fz * qx - fx * qz) - var bz = -(fx * qy - fy * qx) - var bw = Math.sqrt(Math.max(0.0, 1.0 - Math.pow(bx,2) - Math.pow(by,2) - Math.pow(bz,2))) - var bl = len4(bx, by, bz, bw) - if(bl > 1e-6) { - bx /= bl - by /= bl - bz /= bl - bw /= bl - } else { - bx = by = bz = 0.0 - bw = 1.0 - } - - var rotation = this.computedRotation - var ax = rotation[0] - var ay = rotation[1] - var az = rotation[2] - var aw = rotation[3] - - var cx = ax*bw + aw*bx + ay*bz - az*by - var cy = ay*bw + aw*by + az*bx - ax*bz - var cz = az*bw + aw*bz + ax*by - ay*bx - var cw = aw*bw - ax*bx - ay*by - az*bz - - //Apply roll - if(dz) { - bx = fx - by = fy - bz = fz - var s = Math.sin(dz) / len3(bx, by, bz) - bx *= s - by *= s - bz *= s - bw = Math.cos(dx) - cx = cx*bw + cw*bx + cy*bz - cz*by - cy = cy*bw + cw*by + cz*bx - cx*bz - cz = cz*bw + cw*bz + cx*by - cy*bx - cw = cw*bw - cx*bx - cy*by - cz*bz - } - - var cl = len4(cx, cy, cz, cw) - if(cl > 1e-6) { - cx /= cl - cy /= cl - cz /= cl - cw /= cl - } else { - cx = cy = cz = 0.0 - cw = 1.0 - } - - this.rotation.set(t, cx, cy, cz, cw) -} - -proto.lookAt = function(t, eye, center, up) { - this.recalcMatrix(t) - - center = center || this.computedCenter - eye = eye || this.computedEye - up = up || this.computedUp - - var mat = this.computedMatrix - lookAt(mat, eye, center, up) - - var rotation = this.computedRotation - quatFromFrame(rotation, - mat[0], mat[1], mat[2], - mat[4], mat[5], mat[6], - mat[8], mat[9], mat[10]) - normalize4(rotation, rotation) - this.rotation.set(t, rotation[0], rotation[1], rotation[2], rotation[3]) - - var fl = 0.0 - for(var i=0; i<3; ++i) { - fl += Math.pow(center[i] - eye[i], 2) - } - this.radius.set(t, 0.5 * Math.log(Math.max(fl, 1e-6))) - - this.center.set(t, center[0], center[1], center[2]) -} - -proto.translate = function(t, dx, dy, dz) { - this.center.move(t, - dx||0.0, - dy||0.0, - dz||0.0) -} - -proto.setMatrix = function(t, matrix) { - - var rotation = this.computedRotation - quatFromFrame(rotation, - matrix[0], matrix[1], matrix[2], - matrix[4], matrix[5], matrix[6], - matrix[8], matrix[9], matrix[10]) - normalize4(rotation, rotation) - this.rotation.set(t, rotation[0], rotation[1], rotation[2], rotation[3]) - - var mat = this.computedMatrix - invert44(mat, matrix) - var w = mat[15] - if(Math.abs(w) > 1e-6) { - var cx = mat[12]/w - var cy = mat[13]/w - var cz = mat[14]/w - - this.recalcMatrix(t) - var r = Math.exp(this.computedRadius[0]) - this.center.set(t, cx-mat[2]*r, cy-mat[6]*r, cz-mat[10]*r) - this.radius.idle(t) - } else { - this.center.idle(t) - this.radius.idle(t) - } -} - -proto.setDistance = function(t, d) { - if(d > 0) { - this.radius.set(t, Math.log(d)) - } -} - -proto.setDistanceLimits = function(lo, hi) { - if(lo > 0) { - lo = Math.log(lo) - } else { - lo = -Infinity - } - if(hi > 0) { - hi = Math.log(hi) - } else { - hi = Infinity - } - hi = Math.max(hi, lo) - this.radius.bounds[0][0] = lo - this.radius.bounds[1][0] = hi -} - -proto.getDistanceLimits = function(out) { - var bounds = this.radius.bounds - if(out) { - out[0] = Math.exp(bounds[0][0]) - out[1] = Math.exp(bounds[1][0]) - return out - } - return [ Math.exp(bounds[0][0]), Math.exp(bounds[1][0]) ] -} - -proto.toJSON = function() { - this.recalcMatrix(this.lastT()) - return { - center: this.computedCenter.slice(), - rotation: this.computedRotation.slice(), - distance: Math.log(this.computedRadius[0]), - zoomMin: this.radius.bounds[0][0], - zoomMax: this.radius.bounds[1][0] - } -} - -proto.fromJSON = function(options) { - var t = this.lastT() - var c = options.center - if(c) { - this.center.set(t, c[0], c[1], c[2]) - } - var r = options.rotation - if(r) { - this.rotation.set(t, r[0], r[1], r[2], r[3]) - } - var d = options.distance - if(d && d > 0) { - this.radius.set(t, Math.log(d)) - } - this.setDistanceLimits(options.zoomMin, options.zoomMax) -} - -function createOrbitController(options) { - options = options || {} - var center = options.center || [0,0,0] - var rotation = options.rotation || [0,0,0,1] - var radius = options.radius || 1.0 - - center = [].slice.call(center, 0, 3) - rotation = [].slice.call(rotation, 0, 4) - normalize4(rotation, rotation) - - var result = new OrbitCameraController( - rotation, - center, - Math.log(radius)) - - result.setDistanceLimits(options.zoomMin, options.zoomMax) - - if('eye' in options || 'up' in options) { - result.lookAt(0, options.eye, options.center, options.up) - } - - return result -} -},{"./lib/quatFromFrame":455,"filtered-vector":226,"gl-mat4/fromQuat":262,"gl-mat4/invert":265,"gl-mat4/lookAt":266}],457:[function(_dereq_,module,exports){ -/*! - * pad-left - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT license. - */ - -'use strict'; - -var repeat = _dereq_('repeat-string'); - -module.exports = function padLeft(str, num, ch) { - ch = typeof ch !== 'undefined' ? (ch + '') : ' '; - return repeat(ch, num) + str; -}; -},{"repeat-string":503}],458:[function(_dereq_,module,exports){ -'use strict' - -/** - * @module parenthesis - */ - -function parse (str, opts) { - // pretend non-string parsed per-se - if (typeof str !== 'string') return [str] - - var res = [str] - - if (typeof opts === 'string' || Array.isArray(opts)) { - opts = {brackets: opts} - } - else if (!opts) opts = {} - - var brackets = opts.brackets ? (Array.isArray(opts.brackets) ? opts.brackets : [opts.brackets]) : ['{}', '[]', '()'] - - var escape = opts.escape || '___' - - var flat = !!opts.flat - - brackets.forEach(function (bracket) { - // create parenthesis regex - var pRE = new RegExp(['\\', bracket[0], '[^\\', bracket[0], '\\', bracket[1], ']*\\', bracket[1]].join('')) - - var ids = [] - - function replaceToken(token, idx, str){ - // save token to res - var refId = res.push(token.slice(bracket[0].length, -bracket[1].length)) - 1 - - ids.push(refId) - - return escape + refId + escape - } - - res.forEach(function (str, i) { - var prevStr - - // replace paren tokens till there’s none - var a = 0 - while (str != prevStr) { - prevStr = str - str = str.replace(pRE, replaceToken) - if (a++ > 10e3) throw Error('References have circular dependency. Please, check them.') - } - - res[i] = str - }) - - // wrap found refs to brackets - ids = ids.reverse() - res = res.map(function (str) { - ids.forEach(function (id) { - str = str.replace(new RegExp('(\\' + escape + id + '\\' + escape + ')', 'g'), bracket[0] + '$1' + bracket[1]) - }) - return str - }) - }) - - var re = new RegExp('\\' + escape + '([0-9]+)' + '\\' + escape) - - // transform references to tree - function nest (str, refs, escape) { - var res = [], match - - var a = 0 - while (match = re.exec(str)) { - if (a++ > 10e3) throw Error('Circular references in parenthesis') - - res.push(str.slice(0, match.index)) - - res.push(nest(refs[match[1]], refs)) - - str = str.slice(match.index + match[0].length) - } - - res.push(str) - - return res - } - - return flat ? res : nest(res[0], res) -} - -function stringify (arg, opts) { - if (opts && opts.flat) { - var escape = opts && opts.escape || '___' - - var str = arg[0], prevStr - - // pretend bad string stringified with no parentheses - if (!str) return '' - - - var re = new RegExp('\\' + escape + '([0-9]+)' + '\\' + escape) - - var a = 0 - while (str != prevStr) { - if (a++ > 10e3) throw Error('Circular references in ' + arg) - prevStr = str - str = str.replace(re, replaceRef) - } - - return str - } - - return arg.reduce(function f (prev, curr) { - if (Array.isArray(curr)) { - curr = curr.reduce(f, '') - } - return prev + curr - }, '') - - function replaceRef(match, idx){ - if (arg[idx] == null) throw Error('Reference ' + idx + 'is undefined') - return arg[idx] - } -} - -function parenthesis (arg, opts) { - if (Array.isArray(arg)) { - return stringify(arg, opts) - } - else { - return parse(arg, opts) - } -} - -parenthesis.parse = parse -parenthesis.stringify = stringify - -module.exports = parenthesis - -},{}],459:[function(_dereq_,module,exports){ -'use strict' - -var pick = _dereq_('pick-by-alias') - -module.exports = parseRect - -function parseRect (arg) { - var rect - - // direct arguments sequence - if (arguments.length > 1) { - arg = arguments - } - - // svg viewbox - if (typeof arg === 'string') { - arg = arg.split(/\s/).map(parseFloat) - } - else if (typeof arg === 'number') { - arg = [arg] - } - - // 0, 0, 100, 100 - array-like - if (arg.length && typeof arg[0] === 'number') { - // [w, w] - if (arg.length === 1) { - rect = { - width: arg[0], - height: arg[0], - x: 0, y: 0 - } - } - // [w, h] - else if (arg.length === 2) { - rect = { - width: arg[0], - height: arg[1], - x: 0, y: 0 - } - } - // [l, t, r, b] - else { - rect = { - x: arg[0], - y: arg[1], - width: (arg[2] - arg[0]) || 0, - height: (arg[3] - arg[1]) || 0 - } - } - } - // {x, y, w, h} or {l, t, b, r} - else if (arg) { - arg = pick(arg, { - left: 'x l left Left', - top: 'y t top Top', - width: 'w width W Width', - height: 'h height W Width', - bottom: 'b bottom Bottom', - right: 'r right Right' - }) - - rect = { - x: arg.left || 0, - y: arg.top || 0 - } - - if (arg.width == null) { - if (arg.right) rect.width = arg.right - rect.x - else rect.width = 0 - } - else { - rect.width = arg.width - } - - if (arg.height == null) { - if (arg.bottom) rect.height = arg.bottom - rect.y - else rect.height = 0 - } - else { - rect.height = arg.height - } - } - - return rect -} - -},{"pick-by-alias":465}],460:[function(_dereq_,module,exports){ - -module.exports = parse - -/** - * expected argument lengths - * @type {Object} - */ - -var length = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0} - -/** - * segment pattern - * @type {RegExp} - */ - -var segment = /([astvzqmhlc])([^astvzqmhlc]*)/ig - -/** - * parse an svg path data string. Generates an Array - * of commands where each command is an Array of the - * form `[command, arg1, arg2, ...]` - * - * @param {String} path - * @return {Array} - */ - -function parse(path) { - var data = [] - path.replace(segment, function(_, command, args){ - var type = command.toLowerCase() - args = parseValues(args) - - // overloaded moveTo - if (type == 'm' && args.length > 2) { - data.push([command].concat(args.splice(0, 2))) - type = 'l' - command = command == 'm' ? 'l' : 'L' - } - - while (true) { - if (args.length == length[type]) { - args.unshift(command) - return data.push(args) - } - if (args.length < length[type]) throw new Error('malformed path data') - data.push([command].concat(args.splice(0, length[type]))) - } - }) - return data -} - -var number = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig - -function parseValues(args) { - var numbers = args.match(number) - return numbers ? numbers.map(Number) : [] -} - -},{}],461:[function(_dereq_,module,exports){ -module.exports = function parseUnit(str, out) { - if (!out) - out = [ 0, '' ] - - str = String(str) - var num = parseFloat(str, 10) - out[0] = num - out[1] = str.match(/[\d.\-\+]*\s*(.*)/)[1] || '' - return out -} -},{}],462:[function(_dereq_,module,exports){ -(function (process){ -// Generated by CoffeeScript 1.12.2 -(function() { - var getNanoSeconds, hrtime, loadTime, moduleLoadTime, nodeLoadTime, upTime; - - if ((typeof performance !== "undefined" && performance !== null) && performance.now) { - module.exports = function() { - return performance.now(); - }; - } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) { - module.exports = function() { - return (getNanoSeconds() - nodeLoadTime) / 1e6; - }; - hrtime = process.hrtime; - getNanoSeconds = function() { - var hr; - hr = hrtime(); - return hr[0] * 1e9 + hr[1]; - }; - moduleLoadTime = getNanoSeconds(); - upTime = process.uptime() * 1e9; - nodeLoadTime = moduleLoadTime - upTime; - } else if (Date.now) { - module.exports = function() { - return Date.now() - loadTime; - }; - loadTime = Date.now(); - } else { - module.exports = function() { - return new Date().getTime() - loadTime; - }; - loadTime = new Date().getTime(); - } - -}).call(this); - - - -}).call(this,_dereq_('_process')) -},{"_process":482}],463:[function(_dereq_,module,exports){ -"use strict" - -module.exports = permutationSign - -var BRUTE_FORCE_CUTOFF = 32 - -var pool = _dereq_("typedarray-pool") - -function permutationSign(p) { - var n = p.length - if(n < BRUTE_FORCE_CUTOFF) { - //Use quadratic algorithm for small n - var sgn = 1 - for(var i=0; i0; --i) { - t = pinv[i] - s = p[i] - p[i] = p[t] - p[t] = s - pinv[i] = pinv[s] - pinv[s] = t - r = (r + s) * i - } - pool.freeUint32(pinv) - pool.freeUint32(p) - return r -} - -function unrank(n, r, p) { - switch(n) { - case 0: - if(p) { return p } - return [] - case 1: - if(p) { - p[0] = 0 - return p - } else { - return [0] - } - case 2: - if(p) { - if(r) { - p[0] = 0 - p[1] = 1 - } else { - p[0] = 1 - p[1] = 0 - } - return p - } else { - return r ? [0,1] : [1,0] - } - default: - break - } - p = p || new Array(n) - var s, t, i, nf=1 - p[0] = 0 - for(i=1; i0; --i) { - s = (r / nf)|0 - r = (r - s * nf)|0 - nf = (nf / i)|0 - t = p[i]|0 - p[i] = p[s]|0 - p[s] = t|0 - } - return p -} - -exports.rank = rank -exports.unrank = unrank - -},{"invert-permutation":415,"typedarray-pool":545}],465:[function(_dereq_,module,exports){ -'use strict' - - -module.exports = function pick (src, props, keepRest) { - var result = {}, prop, i - - if (typeof props === 'string') props = toList(props) - if (Array.isArray(props)) { - var res = {} - for (i = 0; i < props.length; i++) { - res[props[i]] = true - } - props = res - } - - // convert strings to lists - for (prop in props) { - props[prop] = toList(props[prop]) - } - - // keep-rest strategy requires unmatched props to be preserved - var occupied = {} - - for (prop in props) { - var aliases = props[prop] - - if (Array.isArray(aliases)) { - for (i = 0; i < aliases.length; i++) { - var alias = aliases[i] - - if (keepRest) { - occupied[alias] = true - } - - if (alias in src) { - result[prop] = src[alias] - - if (keepRest) { - for (var j = i; j < aliases.length; j++) { - occupied[aliases[j]] = true - } - } - - break - } - } - } - else if (prop in src) { - if (props[prop]) { - result[prop] = src[prop] - } - - if (keepRest) { - occupied[prop] = true - } - } - } - - if (keepRest) { - for (prop in src) { - if (occupied[prop]) continue - result[prop] = src[prop] - } - } - - return result -} - -var CACHE = {} - -function toList(arg) { - if (CACHE[arg]) return CACHE[arg] - if (typeof arg === 'string') { - arg = CACHE[arg] = arg.split(/\s*,\s*|\s+/) - } - return arg -} - -},{}],466:[function(_dereq_,module,exports){ -"use strict" - -module.exports = planarDual - -var compareAngle = _dereq_("compare-angle") - -function planarDual(cells, positions) { - - var numVertices = positions.length|0 - var numEdges = cells.length - var adj = [new Array(numVertices), new Array(numVertices)] - for(var i=0; i 0) { - nextCell = adj[i][b][0] - nextDir = i - break - } - } - nextVertex = nextCell[nextDir^1] - - for(var dir=0; dir<2; ++dir) { - var nbhd = adj[dir][b] - for(var k=0; k 0) { - nextCell = e - nextVertex = p - nextDir = dir - } - } - } - if(noCut) { - return nextVertex - } - if(nextCell) { - cut(nextCell, nextDir) - } - return nextVertex - } - - function extractCycle(v, dir) { - var e0 = adj[dir][v][0] - var cycle = [v] - cut(e0, dir) - var u = e0[dir^1] - var d0 = dir - while(true) { - while(u !== v) { - cycle.push(u) - u = next(cycle[cycle.length-2], u, false) - } - if(adj[0][v].length + adj[1][v].length === 0) { - break - } - var a = cycle[cycle.length-1] - var b = v - var c = cycle[1] - var d = next(a, b, true) - if(compareAngle(positions[a], positions[b], positions[c], positions[d]) < 0) { - break - } - cycle.push(v) - u = next(a, b) - } - return cycle - } - - function shouldGlue(pcycle, ncycle) { - return (ncycle[1] === ncycle[ncycle.length-1]) - } - - for(var i=0; i 0) { - var ni = adj[0][i].length - var ncycle = extractCycle(i,j) - if(shouldGlue(pcycle, ncycle)) { - //Glue together trivial cycles - pcycle.push.apply(pcycle, ncycle) - } else { - if(pcycle.length > 0) { - cycles.push(pcycle) - } - pcycle = ncycle - } - } - if(pcycle.length > 0) { - cycles.push(pcycle) - } - } - } - - //Combine paths and loops together - return cycles -} -},{"compare-angle":127}],467:[function(_dereq_,module,exports){ -'use strict' - -module.exports = trimLeaves - -var e2a = _dereq_('edges-to-adjacency-list') - -function trimLeaves(edges, positions) { - var adj = e2a(edges, positions.length) - var live = new Array(positions.length) - var nbhd = new Array(positions.length) - - var dead = [] - for(var i=0; i 0) { - var v = dead.pop() - live[v] = false - var n = adj[v] - for(var i=0; i 0 - } - - //Extract all clockwise faces - faces = faces.filter(ccw) - - //Detect which loops are contained in one another to handle parent-of relation - var numFaces = faces.length - var parent = new Array(numFaces) - var containment = new Array(numFaces) - for(var i=0; i 0) { - var top = toVisit.pop() - var nbhd = fadj[top] - uniq(nbhd, function(a,b) { - return a-b - }) - var nnbhr = nbhd.length - var p = parity[top] - var polyline - if(p === 0) { - var c = faces[top] - polyline = [c] - } - for(var i=0; i= 0) { - continue - } - parity[f] = p^1 - toVisit.push(f) - if(p === 0) { - var c = faces[f] - if(!sharedBoundary(c)) { - c.reverse() - polyline.push(c) - } - } - } - if(p === 0) { - result.push(polyline) - } - } - - return result -} -},{"./lib/trim-leaves":467,"edges-to-adjacency-list":171,"planar-dual":466,"point-in-big-polygon":472,"robust-sum":515,"two-product":543,"uniq":547}],469:[function(_dereq_,module,exports){ -'use strict' - -module.exports = _dereq_('./quad') -},{"./quad":471}],470:[function(_dereq_,module,exports){ -arguments[4][111][0].apply(exports,arguments) -},{"dup":111}],471:[function(_dereq_,module,exports){ -/** - * @module point-cluster/quad - * - * Bucket based quad tree clustering - */ - -'use strict' - -var search = _dereq_('binary-search-bounds') -var clamp = _dereq_('clamp') -var rect = _dereq_('parse-rect') -var getBounds = _dereq_('array-bounds') -var pick = _dereq_('pick-by-alias') -var defined = _dereq_('defined') -var flatten = _dereq_('flatten-vertex-data') -var isObj = _dereq_('is-obj') -var dtype = _dereq_('dtype') -var log2 = _dereq_('math-log2') - - -module.exports = function cluster (srcPoints, options) { - if (!options) { options = {} } - - srcPoints = flatten(srcPoints, 'float64') - - options = pick(options, { - bounds: 'range bounds dataBox databox', - maxDepth: 'depth maxDepth maxdepth level maxLevel maxlevel levels', - dtype: 'type dtype format out dst output destination' - // sort: 'sortBy sortby sort', - // pick: 'pick levelPoint', - // nodeSize: 'node nodeSize minNodeSize minSize size' - }) - - // let nodeSize = defined(options.nodeSize, 1) - var maxDepth = defined(options.maxDepth, 255) - var bounds = defined(options.bounds, getBounds(srcPoints, 2)) - if (bounds[0] === bounds[2]) { bounds[2]++ } - if (bounds[1] === bounds[3]) { bounds[3]++ } - - var points = normalize(srcPoints, bounds) - - // init variables - var n = srcPoints.length >>> 1 - var ids - if (!options.dtype) { options.dtype = 'array' } - - if (typeof options.dtype === 'string') { - ids = new (dtype(options.dtype))(n) - } - else if (options.dtype) { - ids = options.dtype - if (Array.isArray(ids)) { ids.length = n } - } - for (var i = 0; i < n; ++i) { - ids[i] = i - } - - // point indexes for levels [0: [a,b,c,d], 1: [a,b,c,d,e,f,...], ...] - var levels = [] - - // starting indexes of subranges in sub levels, levels.length * 4 - var sublevels = [] - - // unique group ids, sorted in z-curve fashion within levels - var groups = [] - - // level offsets in `ids` - var offsets = [] - - - // sort points - sort(0, 0, 1, ids, 0, 1) - - - // return reordered ids with provided methods - // save level offsets in output buffer - var offset = 0 - for (var level = 0; level < levels.length; level++) { - var levelItems = levels[level] - if (ids.set) { ids.set(levelItems, offset) } - else { - for (var i$1 = 0, l = levelItems.length; i$1 < l; i$1++) { - ids[i$1 + offset] = levelItems[i$1] - } - } - var nextOffset = offset + levels[level].length - offsets[level] = [offset, nextOffset] - offset = nextOffset - } - - ids.range = range - - return ids - - - - // FIXME: it is possible to create one typed array heap and reuse that to avoid memory blow - function sort (x, y, diam, ids, level, group) { - if (!ids.length) { return null } - - // save first point as level representative - var levelItems = levels[level] || (levels[level] = []) - var levelGroups = groups[level] || (groups[level] = []) - var sublevel = sublevels[level] || (sublevels[level] = []) - var offset = levelItems.length - - level++ - - // max depth reached - put all items into a first group - if (level > maxDepth) { - for (var i = 0; i < ids.length; i++) { - levelItems.push(ids[i]) - levelGroups.push(group) - sublevel.push(null, null, null, null) - } - - return offset - } - - levelItems.push(ids[0]) - levelGroups.push(group) - - if (ids.length <= 1) { - sublevel.push(null, null, null, null) - return offset - } - - - var d2 = diam * .5 - var cx = x + d2, cy = y + d2 - - // distribute points by 4 buckets - var lolo = [], lohi = [], hilo = [], hihi = [] - - for (var i$1 = 1, l = ids.length; i$1 < l; i$1++) { - var idx = ids[i$1], - x$1 = points[idx * 2], - y$1 = points[idx * 2 + 1] - x$1 < cx ? (y$1 < cy ? lolo.push(idx) : lohi.push(idx)) : (y$1 < cy ? hilo.push(idx) : hihi.push(idx)) - } - - group <<= 2 - sublevel.push( - sort(x, y, d2, lolo, level, group), - sort(x, cy, d2, lohi, level, group + 1), - sort(cx, y, d2, hilo, level, group + 2), - sort(cx, cy, d2, hihi, level, group + 3) - ) - - return offset - } - - // get all points within the passed range - function range () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - var options - - if (isObj(args[args.length - 1])) { - var arg = args.pop() - - // detect if that was a rect object - if (!args.length && (arg.x != null || arg.l != null || arg.left != null)) { - args = [arg] - options = {} - } - - options = pick(arg, { - level: 'level maxLevel', - d: 'd diam diameter r radius px pxSize pixel pixelSize maxD size minSize', - lod: 'lod details ranges offsets' - }) - } - else { - options = {} - } - - if (!args.length) { args = bounds } - - var box = rect.apply( void 0, args ) - - var ref = [ - Math.min(box.x, box.x + box.width), - Math.min(box.y, box.y + box.height), - Math.max(box.x, box.x + box.width), - Math.max(box.y, box.y + box.height) - ]; - var minX = ref[0]; - var minY = ref[1]; - var maxX = ref[2]; - var maxY = ref[3]; - - var ref$1 = normalize([minX, minY, maxX, maxY], bounds ); - var nminX = ref$1[0]; - var nminY = ref$1[1]; - var nmaxX = ref$1[2]; - var nmaxY = ref$1[3]; - - var maxLevel = defined(options.level, levels.length) - - // limit maxLevel by px size - if (options.d != null) { - var d - if (typeof options.d === 'number') { d = [options.d, options.d] } - else if (options.d.length) { d = options.d } - - maxLevel = Math.min( - Math.max( - Math.ceil(-log2(Math.abs(d[0]) / (bounds[2] - bounds[0]))), - Math.ceil(-log2(Math.abs(d[1]) / (bounds[3] - bounds[1]))) - ), - maxLevel - ) - } - maxLevel = Math.min(maxLevel, levels.length) - - // return levels of details - if (options.lod) { - return lod(nminX, nminY, nmaxX, nmaxY, maxLevel) - } - - - - // do selection ids - var selection = [] - - // FIXME: probably we can do LOD here beforehead - select( 0, 0, 1, 0, 0, 1) - - function select ( lox, loy, d, level, from, to ) { - if (from === null || to === null) { return } - - var hix = lox + d - var hiy = loy + d - - // if box does not intersect level - ignore - if ( nminX > hix || nminY > hiy || nmaxX < lox || nmaxY < loy ) { return } - if ( level >= maxLevel ) { return } - if ( from === to ) { return } - - // if points fall into box range - take it - var levelItems = levels[level] - - if (to === undefined) { to = levelItems.length } - - for (var i = from; i < to; i++) { - var id = levelItems[i] - - var px = srcPoints[ id * 2 ] - var py = srcPoints[ id * 2 + 1 ] - - if ( px >= minX && px <= maxX && py >= minY && py <= maxY ) {selection.push(id) - } - } - - // for every subsection do select - var offsets = sublevels[ level ] - var off0 = offsets[ from * 4 + 0 ] - var off1 = offsets[ from * 4 + 1 ] - var off2 = offsets[ from * 4 + 2 ] - var off3 = offsets[ from * 4 + 3 ] - var end = nextOffset(offsets, from + 1) - - var d2 = d * .5 - var nextLevel = level + 1 - select( lox, loy, d2, nextLevel, off0, off1 || off2 || off3 || end) - select( lox, loy + d2, d2, nextLevel, off1, off2 || off3 || end) - select( lox + d2, loy, d2, nextLevel, off2, off3 || end) - select( lox + d2, loy + d2, d2, nextLevel, off3, end) - } - - function nextOffset(offsets, from) { - var offset = null, i = 0 - while(offset === null) { - offset = offsets[ from * 4 + i ] - i++ - if (i > offsets.length) { return null } - } - return offset - } - - return selection - } - - // get range offsets within levels to render lods appropriate for zoom level - // TODO: it is possible to store minSize of a point to optimize neede level calc - function lod (lox, loy, hix, hiy, maxLevel) { - var ranges = [] - - for (var level = 0; level < maxLevel; level++) { - var levelGroups = groups[level] - var from = offsets[level][0] - - var levelGroupStart = group(lox, loy, level) - var levelGroupEnd = group(hix, hiy, level) - - // FIXME: utilize sublevels to speed up search range here - var startOffset = search.ge(levelGroups, levelGroupStart) - var endOffset = search.gt(levelGroups, levelGroupEnd, startOffset, levelGroups.length - 1) - - ranges[level] = [startOffset + from, endOffset + from] - } - - return ranges - } - - // get group id closest to the x,y coordinate, corresponding to a level - function group (x, y, level) { - var group = 1 - - var cx = .5, cy = .5 - var diam = .5 - - for (var i = 0; i < level; i++) { - group <<= 2 - - group += x < cx ? (y < cy ? 0 : 1) : (y < cy ? 2 : 3) - - diam *= .5 - - cx += x < cx ? -diam : diam - cy += y < cy ? -diam : diam - } - - return group - } -} - - -// normalize points by bounds -function normalize (pts, bounds) { - var lox = bounds[0]; - var loy = bounds[1]; - var hix = bounds[2]; - var hiy = bounds[3]; - var scaleX = 1.0 / (hix - lox) - var scaleY = 1.0 / (hiy - loy) - var result = new Array(pts.length) - - for (var i = 0, n = pts.length / 2; i < n; i++) { - result[2*i] = clamp((pts[2*i] - lox) * scaleX, 0, 1) - result[2*i+1] = clamp((pts[2*i+1] - loy) * scaleY, 0, 1) - } - - return result -} -},{"array-bounds":65,"binary-search-bounds":470,"clamp":115,"defined":164,"dtype":169,"flatten-vertex-data":227,"is-obj":421,"math-log2":432,"parse-rect":459,"pick-by-alias":465}],472:[function(_dereq_,module,exports){ -module.exports = preprocessPolygon - -var orient = _dereq_('robust-orientation')[3] -var makeSlabs = _dereq_('slab-decomposition') -var makeIntervalTree = _dereq_('interval-tree-1d') -var bsearch = _dereq_('binary-search-bounds') - -function visitInterval() { - return true -} - -function intervalSearch(table) { - return function(x, y) { - var tree = table[x] - if(tree) { - return !!tree.queryPoint(y, visitInterval) - } - return false - } -} - -function buildVerticalIndex(segments) { - var table = {} - for(var i=0; i 0 && coordinates[bucket] === p[0]) { - root = slabs[bucket-1] - } else { - return 1 - } - } - var lastOrientation = 1 - while(root) { - var s = root.key - var o = orient(p, s[0], s[1]) - if(s[0][0] < s[1][0]) { - if(o < 0) { - root = root.left - } else if(o > 0) { - lastOrientation = -1 - root = root.right - } else { - return 0 - } - } else { - if(o > 0) { - root = root.left - } else if(o < 0) { - lastOrientation = 1 - root = root.right - } else { - return 0 - } - } - } - return lastOrientation - } -} - -function classifyEmpty(p) { - return 1 -} - -function createClassifyVertical(testVertical) { - return function classify(p) { - if(testVertical(p[0], p[1])) { - return 0 - } - return 1 - } -} - -function createClassifyPointDegen(testVertical, testNormal) { - return function classify(p) { - if(testVertical(p[0], p[1])) { - return 0 - } - return testNormal(p) - } -} - -function preprocessPolygon(loops) { - //Compute number of loops - var numLoops = loops.length - - //Unpack segments - var segments = [] - var vsegments = [] - var ptr = 0 - for(var i=0; i= -eps; - }, - pointBetween: function(p, left, right){ - // p must be collinear with left->right - // returns false if p == left, p == right, or left == right - var d_py_ly = p[1] - left[1]; - var d_rx_lx = right[0] - left[0]; - var d_px_lx = p[0] - left[0]; - var d_ry_ly = right[1] - left[1]; - - var dot = d_px_lx * d_rx_lx + d_py_ly * d_ry_ly; - // if `dot` is 0, then `p` == `left` or `left` == `right` (reject) - // if `dot` is less than 0, then `p` is to the left of `left` (reject) - if (dot < eps) - return false; - - var sqlen = d_rx_lx * d_rx_lx + d_ry_ly * d_ry_ly; - // if `dot` > `sqlen`, then `p` is to the right of `right` (reject) - // therefore, if `dot - sqlen` is greater than 0, then `p` is to the right of `right` (reject) - if (dot - sqlen > -eps) - return false; - - return true; - }, - pointsSameX: function(p1, p2){ - return Math.abs(p1[0] - p2[0]) < eps; - }, - pointsSameY: function(p1, p2){ - return Math.abs(p1[1] - p2[1]) < eps; - }, - pointsSame: function(p1, p2){ - return my.pointsSameX(p1, p2) && my.pointsSameY(p1, p2); - }, - pointsCompare: function(p1, p2){ - // returns -1 if p1 is smaller, 1 if p2 is smaller, 0 if equal - if (my.pointsSameX(p1, p2)) - return my.pointsSameY(p1, p2) ? 0 : (p1[1] < p2[1] ? -1 : 1); - return p1[0] < p2[0] ? -1 : 1; - }, - pointsCollinear: function(pt1, pt2, pt3){ - // does pt1->pt2->pt3 make a straight line? - // essentially this is just checking to see if the slope(pt1->pt2) === slope(pt2->pt3) - // if slopes are equal, then they must be collinear, because they share pt2 - var dx1 = pt1[0] - pt2[0]; - var dy1 = pt1[1] - pt2[1]; - var dx2 = pt2[0] - pt3[0]; - var dy2 = pt2[1] - pt3[1]; - return Math.abs(dx1 * dy2 - dx2 * dy1) < eps; - }, - linesIntersect: function(a0, a1, b0, b1){ - // returns false if the lines are coincident (e.g., parallel or on top of each other) - // - // returns an object if the lines intersect: - // { - // pt: [x, y], where the intersection point is at - // alongA: where intersection point is along A, - // alongB: where intersection point is along B - // } - // - // alongA and alongB will each be one of: -2, -1, 0, 1, 2 - // - // with the following meaning: - // - // -2 intersection point is before segment's first point - // -1 intersection point is directly on segment's first point - // 0 intersection point is between segment's first and second points (exclusive) - // 1 intersection point is directly on segment's second point - // 2 intersection point is after segment's second point - var adx = a1[0] - a0[0]; - var ady = a1[1] - a0[1]; - var bdx = b1[0] - b0[0]; - var bdy = b1[1] - b0[1]; - - var axb = adx * bdy - ady * bdx; - if (Math.abs(axb) < eps) - return false; // lines are coincident - - var dx = a0[0] - b0[0]; - var dy = a0[1] - b0[1]; - - var A = (bdx * dy - bdy * dx) / axb; - var B = (adx * dy - ady * dx) / axb; - - var ret = { - alongA: 0, - alongB: 0, - pt: [ - a0[0] + A * adx, - a0[1] + A * ady - ] - }; - - // categorize where intersection point is along A and B - - if (A <= -eps) - ret.alongA = -2; - else if (A < eps) - ret.alongA = -1; - else if (A - 1 <= -eps) - ret.alongA = 0; - else if (A - 1 < eps) - ret.alongA = 1; - else - ret.alongA = 2; - - if (B <= -eps) - ret.alongB = -2; - else if (B < eps) - ret.alongB = -1; - else if (B - 1 <= -eps) - ret.alongB = 0; - else if (B - 1 < eps) - ret.alongB = 1; - else - ret.alongB = 2; - - return ret; - }, - pointInsideRegion: function(pt, region){ - var x = pt[0]; - var y = pt[1]; - var last_x = region[region.length - 1][0]; - var last_y = region[region.length - 1][1]; - var inside = false; - for (var i = 0; i < region.length; i++){ - var curr_x = region[i][0]; - var curr_y = region[i][1]; - - // if y is between curr_y and last_y, and - // x is to the right of the boundary created by the line - if ((curr_y - y > eps) != (last_y - y > eps) && - (last_x - curr_x) * (y - curr_y) / (last_y - curr_y) + curr_x - x > eps) - inside = !inside - - last_x = curr_x; - last_y = curr_y; - } - return inside; - } - }; - return my; -} - -module.exports = Epsilon; - -},{}],476:[function(_dereq_,module,exports){ -// (c) Copyright 2017, Sean Connelly (@voidqk), http://syntheti.cc -// MIT License -// Project Home: https://github.com/voidqk/polybooljs - -// -// convert between PolyBool polygon format and GeoJSON formats (Polygon and MultiPolygon) -// - -var GeoJSON = { - // convert a GeoJSON object to a PolyBool polygon - toPolygon: function(PolyBool, geojson){ - - // converts list of LineString's to segments - function GeoPoly(coords){ - // check for empty coords - if (coords.length <= 0) - return PolyBool.segments({ inverted: false, regions: [] }); - - // convert LineString to segments - function LineString(ls){ - // remove tail which should be the same as head - var reg = ls.slice(0, ls.length - 1); - return PolyBool.segments({ inverted: false, regions: [reg] }); - } - - // the first LineString is considered the outside - var out = LineString(coords[0]); - - // the rest of the LineStrings are considered interior holes, so subtract them from the - // current result - for (var i = 1; i < coords.length; i++) - out = PolyBool.selectDifference(PolyBool.combine(out, LineString(coords[i]))); - - return out; - } - - if (geojson.type === 'Polygon'){ - // single polygon, so just convert it and we're done - return PolyBool.polygon(GeoPoly(geojson.coordinates)); - } - else if (geojson.type === 'MultiPolygon'){ - // multiple polygons, so union all the polygons together - var out = PolyBool.segments({ inverted: false, regions: [] }); - for (var i = 0; i < geojson.coordinates.length; i++) - out = PolyBool.selectUnion(PolyBool.combine(out, GeoPoly(geojson.coordinates[i]))); - return PolyBool.polygon(out); - } - throw new Error('PolyBool: Cannot convert GeoJSON object to PolyBool polygon'); - }, - - // convert a PolyBool polygon to a GeoJSON object - fromPolygon: function(PolyBool, eps, poly){ - // make sure out polygon is clean - poly = PolyBool.polygon(PolyBool.segments(poly)); - - // test if r1 is inside r2 - function regionInsideRegion(r1, r2){ - // we're guaranteed no lines intersect (because the polygon is clean), but a vertex - // could be on the edge -- so we just average pt[0] and pt[1] to produce a point on the - // edge of the first line, which cannot be on an edge - return eps.pointInsideRegion([ - (r1[0][0] + r1[1][0]) * 0.5, - (r1[0][1] + r1[1][1]) * 0.5 - ], r2); - } - - // calculate inside heirarchy - // - // _____________________ _______ roots -> A -> F - // | A | | F | | | - // | _______ _______ | | ___ | +-- B +-- G - // | | B | | C | | | | | | | | - // | | ___ | | ___ | | | | | | | +-- D - // | | | D | | | | E | | | | | G | | | - // | | |___| | | |___| | | | | | | +-- C - // | |_______| |_______| | | |___| | | - // |_____________________| |_______| +-- E - - function newNode(region){ - return { - region: region, - children: [] - }; - } - - var roots = newNode(null); - - function addChild(root, region){ - // first check if we're inside any children - for (var i = 0; i < root.children.length; i++){ - var child = root.children[i]; - if (regionInsideRegion(region, child.region)){ - // we are, so insert inside them instead - addChild(child, region); - return; - } - } - - // not inside any children, so check to see if any children are inside us - var node = newNode(region); - for (var i = 0; i < root.children.length; i++){ - var child = root.children[i]; - if (regionInsideRegion(child.region, region)){ - // oops... move the child beneath us, and remove them from root - node.children.push(child); - root.children.splice(i, 1); - i--; - } - } - - // now we can add ourselves - root.children.push(node); - } - - // add all regions to the root - for (var i = 0; i < poly.regions.length; i++){ - var region = poly.regions[i]; - if (region.length < 3) // regions must have at least 3 points (sanity check) - continue; - addChild(roots, region); - } - - // with our heirarchy, we can distinguish between exterior borders, and interior holes - // the root nodes are exterior, children are interior, children's children are exterior, - // children's children's children are interior, etc - - // while we're at it, exteriors are counter-clockwise, and interiors are clockwise - - function forceWinding(region, clockwise){ - // first, see if we're clockwise or counter-clockwise - // https://en.wikipedia.org/wiki/Shoelace_formula - var winding = 0; - var last_x = region[region.length - 1][0]; - var last_y = region[region.length - 1][1]; - var copy = []; - for (var i = 0; i < region.length; i++){ - var curr_x = region[i][0]; - var curr_y = region[i][1]; - copy.push([curr_x, curr_y]); // create a copy while we're at it - winding += curr_y * last_x - curr_x * last_y; - last_x = curr_x; - last_y = curr_y; - } - // this assumes Cartesian coordinates (Y is positive going up) - var isclockwise = winding < 0; - if (isclockwise !== clockwise) - copy.reverse(); - // while we're here, the last point must be the first point... - copy.push([copy[0][0], copy[0][1]]); - return copy; - } - - var geopolys = []; - - function addExterior(node){ - var poly = [forceWinding(node.region, false)]; - geopolys.push(poly); - // children of exteriors are interior - for (var i = 0; i < node.children.length; i++) - poly.push(getInterior(node.children[i])); - } - - function getInterior(node){ - // children of interiors are exterior - for (var i = 0; i < node.children.length; i++) - addExterior(node.children[i]); - // return the clockwise interior - return forceWinding(node.region, true); - } - - // root nodes are exterior - for (var i = 0; i < roots.children.length; i++) - addExterior(roots.children[i]); - - // lastly, construct the approrpriate GeoJSON object - - if (geopolys.length <= 0) // empty GeoJSON Polygon - return { type: 'Polygon', coordinates: [] }; - if (geopolys.length == 1) // use a GeoJSON Polygon - return { type: 'Polygon', coordinates: geopolys[0] }; - return { // otherwise, use a GeoJSON MultiPolygon - type: 'MultiPolygon', - coordinates: geopolys - }; - } -}; - -module.exports = GeoJSON; - -},{}],477:[function(_dereq_,module,exports){ -// (c) Copyright 2016, Sean Connelly (@voidqk), http://syntheti.cc -// MIT License -// Project Home: https://github.com/voidqk/polybooljs - -// -// this is the core work-horse -// - -var LinkedList = _dereq_('./linked-list'); - -function Intersecter(selfIntersection, eps, buildLog){ - // selfIntersection is true/false depending on the phase of the overall algorithm - - // - // segment creation - // - - function segmentNew(start, end){ - return { - id: buildLog ? buildLog.segmentId() : -1, - start: start, - end: end, - myFill: { - above: null, // is there fill above us? - below: null // is there fill below us? - }, - otherFill: null - }; - } - - function segmentCopy(start, end, seg){ - return { - id: buildLog ? buildLog.segmentId() : -1, - start: start, - end: end, - myFill: { - above: seg.myFill.above, - below: seg.myFill.below - }, - otherFill: null - }; - } - - // - // event logic - // - - var event_root = LinkedList.create(); - - function eventCompare(p1_isStart, p1_1, p1_2, p2_isStart, p2_1, p2_2){ - // compare the selected points first - var comp = eps.pointsCompare(p1_1, p2_1); - if (comp !== 0) - return comp; - // the selected points are the same - - if (eps.pointsSame(p1_2, p2_2)) // if the non-selected points are the same too... - return 0; // then the segments are equal - - if (p1_isStart !== p2_isStart) // if one is a start and the other isn't... - return p1_isStart ? 1 : -1; // favor the one that isn't the start - - // otherwise, we'll have to calculate which one is below the other manually - return eps.pointAboveOrOnLine(p1_2, - p2_isStart ? p2_1 : p2_2, // order matters - p2_isStart ? p2_2 : p2_1 - ) ? 1 : -1; - } - - function eventAdd(ev, other_pt){ - event_root.insertBefore(ev, function(here){ - // should ev be inserted before here? - var comp = eventCompare( - ev .isStart, ev .pt, other_pt, - here.isStart, here.pt, here.other.pt - ); - return comp < 0; - }); - } - - function eventAddSegmentStart(seg, primary){ - var ev_start = LinkedList.node({ - isStart: true, - pt: seg.start, - seg: seg, - primary: primary, - other: null, - status: null - }); - eventAdd(ev_start, seg.end); - return ev_start; - } - - function eventAddSegmentEnd(ev_start, seg, primary){ - var ev_end = LinkedList.node({ - isStart: false, - pt: seg.end, - seg: seg, - primary: primary, - other: ev_start, - status: null - }); - ev_start.other = ev_end; - eventAdd(ev_end, ev_start.pt); - } - - function eventAddSegment(seg, primary){ - var ev_start = eventAddSegmentStart(seg, primary); - eventAddSegmentEnd(ev_start, seg, primary); - return ev_start; - } - - function eventUpdateEnd(ev, end){ - // slides an end backwards - // (start)------------(end) to: - // (start)---(end) - - if (buildLog) - buildLog.segmentChop(ev.seg, end); - - ev.other.remove(); - ev.seg.end = end; - ev.other.pt = end; - eventAdd(ev.other, ev.pt); - } - - function eventDivide(ev, pt){ - var ns = segmentCopy(pt, ev.seg.end, ev.seg); - eventUpdateEnd(ev, pt); - return eventAddSegment(ns, ev.primary); - } - - function calculate(primaryPolyInverted, secondaryPolyInverted){ - // if selfIntersection is true then there is no secondary polygon, so that isn't used - - // - // status logic - // - - var status_root = LinkedList.create(); - - function statusCompare(ev1, ev2){ - var a1 = ev1.seg.start; - var a2 = ev1.seg.end; - var b1 = ev2.seg.start; - var b2 = ev2.seg.end; - - if (eps.pointsCollinear(a1, b1, b2)){ - if (eps.pointsCollinear(a2, b1, b2)) - return 1;//eventCompare(true, a1, a2, true, b1, b2); - return eps.pointAboveOrOnLine(a2, b1, b2) ? 1 : -1; - } - return eps.pointAboveOrOnLine(a1, b1, b2) ? 1 : -1; - } - - function statusFindSurrounding(ev){ - return status_root.findTransition(function(here){ - var comp = statusCompare(ev, here.ev); - return comp > 0; - }); - } - - function checkIntersection(ev1, ev2){ - // returns the segment equal to ev1, or false if nothing equal - - var seg1 = ev1.seg; - var seg2 = ev2.seg; - var a1 = seg1.start; - var a2 = seg1.end; - var b1 = seg2.start; - var b2 = seg2.end; - - if (buildLog) - buildLog.checkIntersection(seg1, seg2); - - var i = eps.linesIntersect(a1, a2, b1, b2); - - if (i === false){ - // segments are parallel or coincident - - // if points aren't collinear, then the segments are parallel, so no intersections - if (!eps.pointsCollinear(a1, a2, b1)) - return false; - // otherwise, segments are on top of each other somehow (aka coincident) - - if (eps.pointsSame(a1, b2) || eps.pointsSame(a2, b1)) - return false; // segments touch at endpoints... no intersection - - var a1_equ_b1 = eps.pointsSame(a1, b1); - var a2_equ_b2 = eps.pointsSame(a2, b2); - - if (a1_equ_b1 && a2_equ_b2) - return ev2; // segments are exactly equal - - var a1_between = !a1_equ_b1 && eps.pointBetween(a1, b1, b2); - var a2_between = !a2_equ_b2 && eps.pointBetween(a2, b1, b2); - - // handy for debugging: - // buildLog.log({ - // a1_equ_b1: a1_equ_b1, - // a2_equ_b2: a2_equ_b2, - // a1_between: a1_between, - // a2_between: a2_between - // }); - - if (a1_equ_b1){ - if (a2_between){ - // (a1)---(a2) - // (b1)----------(b2) - eventDivide(ev2, a2); - } - else{ - // (a1)----------(a2) - // (b1)---(b2) - eventDivide(ev1, b2); - } - return ev2; - } - else if (a1_between){ - if (!a2_equ_b2){ - // make a2 equal to b2 - if (a2_between){ - // (a1)---(a2) - // (b1)-----------------(b2) - eventDivide(ev2, a2); - } - else{ - // (a1)----------(a2) - // (b1)----------(b2) - eventDivide(ev1, b2); - } - } - - // (a1)---(a2) - // (b1)----------(b2) - eventDivide(ev2, a1); - } - } - else{ - // otherwise, lines intersect at i.pt, which may or may not be between the endpoints - - // is A divided between its endpoints? (exclusive) - if (i.alongA === 0){ - if (i.alongB === -1) // yes, at exactly b1 - eventDivide(ev1, b1); - else if (i.alongB === 0) // yes, somewhere between B's endpoints - eventDivide(ev1, i.pt); - else if (i.alongB === 1) // yes, at exactly b2 - eventDivide(ev1, b2); - } - - // is B divided between its endpoints? (exclusive) - if (i.alongB === 0){ - if (i.alongA === -1) // yes, at exactly a1 - eventDivide(ev2, a1); - else if (i.alongA === 0) // yes, somewhere between A's endpoints (exclusive) - eventDivide(ev2, i.pt); - else if (i.alongA === 1) // yes, at exactly a2 - eventDivide(ev2, a2); - } - } - return false; - } - - // - // main event loop - // - var segments = []; - while (!event_root.isEmpty()){ - var ev = event_root.getHead(); - - if (buildLog) - buildLog.vert(ev.pt[0]); - - if (ev.isStart){ - - if (buildLog) - buildLog.segmentNew(ev.seg, ev.primary); - - var surrounding = statusFindSurrounding(ev); - var above = surrounding.before ? surrounding.before.ev : null; - var below = surrounding.after ? surrounding.after.ev : null; - - if (buildLog){ - buildLog.tempStatus( - ev.seg, - above ? above.seg : false, - below ? below.seg : false - ); - } - - function checkBothIntersections(){ - if (above){ - var eve = checkIntersection(ev, above); - if (eve) - return eve; - } - if (below) - return checkIntersection(ev, below); - return false; - } - - var eve = checkBothIntersections(); - if (eve){ - // ev and eve are equal - // we'll keep eve and throw away ev - - // merge ev.seg's fill information into eve.seg - - if (selfIntersection){ - var toggle; // are we a toggling edge? - if (ev.seg.myFill.below === null) - toggle = true; - else - toggle = ev.seg.myFill.above !== ev.seg.myFill.below; - - // merge two segments that belong to the same polygon - // think of this as sandwiching two segments together, where `eve.seg` is - // the bottom -- this will cause the above fill flag to toggle - if (toggle) - eve.seg.myFill.above = !eve.seg.myFill.above; - } - else{ - // merge two segments that belong to different polygons - // each segment has distinct knowledge, so no special logic is needed - // note that this can only happen once per segment in this phase, because we - // are guaranteed that all self-intersections are gone - eve.seg.otherFill = ev.seg.myFill; - } - - if (buildLog) - buildLog.segmentUpdate(eve.seg); - - ev.other.remove(); - ev.remove(); - } - - if (event_root.getHead() !== ev){ - // something was inserted before us in the event queue, so loop back around and - // process it before continuing - if (buildLog) - buildLog.rewind(ev.seg); - continue; - } - - // - // calculate fill flags - // - if (selfIntersection){ - var toggle; // are we a toggling edge? - if (ev.seg.myFill.below === null) // if we are a new segment... - toggle = true; // then we toggle - else // we are a segment that has previous knowledge from a division - toggle = ev.seg.myFill.above !== ev.seg.myFill.below; // calculate toggle - - // next, calculate whether we are filled below us - if (!below){ // if nothing is below us... - // we are filled below us if the polygon is inverted - ev.seg.myFill.below = primaryPolyInverted; - } - else{ - // otherwise, we know the answer -- it's the same if whatever is below - // us is filled above it - ev.seg.myFill.below = below.seg.myFill.above; - } - - // since now we know if we're filled below us, we can calculate whether - // we're filled above us by applying toggle to whatever is below us - if (toggle) - ev.seg.myFill.above = !ev.seg.myFill.below; - else - ev.seg.myFill.above = ev.seg.myFill.below; - } - else{ - // now we fill in any missing transition information, since we are all-knowing - // at this point - - if (ev.seg.otherFill === null){ - // if we don't have other information, then we need to figure out if we're - // inside the other polygon - var inside; - if (!below){ - // if nothing is below us, then we're inside if the other polygon is - // inverted - inside = - ev.primary ? secondaryPolyInverted : primaryPolyInverted; - } - else{ // otherwise, something is below us - // so copy the below segment's other polygon's above - if (ev.primary === below.primary) - inside = below.seg.otherFill.above; - else - inside = below.seg.myFill.above; - } - ev.seg.otherFill = { - above: inside, - below: inside - }; - } - } - - if (buildLog){ - buildLog.status( - ev.seg, - above ? above.seg : false, - below ? below.seg : false - ); - } - - // insert the status and remember it for later removal - ev.other.status = surrounding.insert(LinkedList.node({ ev: ev })); - } - else{ - var st = ev.status; - - if (st === null){ - throw new Error('PolyBool: Zero-length segment detected; your epsilon is ' + - 'probably too small or too large'); - } - - // removing the status will create two new adjacent edges, so we'll need to check - // for those - if (status_root.exists(st.prev) && status_root.exists(st.next)) - checkIntersection(st.prev.ev, st.next.ev); - - if (buildLog) - buildLog.statusRemove(st.ev.seg); - - // remove the status - st.remove(); - - // if we've reached this point, we've calculated everything there is to know, so - // save the segment for reporting - if (!ev.primary){ - // make sure `seg.myFill` actually points to the primary polygon though - var s = ev.seg.myFill; - ev.seg.myFill = ev.seg.otherFill; - ev.seg.otherFill = s; - } - segments.push(ev.seg); - } - - // remove the event and continue - event_root.getHead().remove(); - } - - if (buildLog) - buildLog.done(); - - return segments; - } - - // return the appropriate API depending on what we're doing - if (!selfIntersection){ - // performing combination of polygons, so only deal with already-processed segments - return { - calculate: function(segments1, inverted1, segments2, inverted2){ - // segmentsX come from the self-intersection API, or this API - // invertedX is whether we treat that list of segments as an inverted polygon or not - // returns segments that can be used for further operations - segments1.forEach(function(seg){ - eventAddSegment(segmentCopy(seg.start, seg.end, seg), true); - }); - segments2.forEach(function(seg){ - eventAddSegment(segmentCopy(seg.start, seg.end, seg), false); - }); - return calculate(inverted1, inverted2); - } - }; - } - - // otherwise, performing self-intersection, so deal with regions - return { - addRegion: function(region){ - // regions are a list of points: - // [ [0, 0], [100, 0], [50, 100] ] - // you can add multiple regions before running calculate - var pt1; - var pt2 = region[region.length - 1]; - for (var i = 0; i < region.length; i++){ - pt1 = pt2; - pt2 = region[i]; - - var forward = eps.pointsCompare(pt1, pt2); - if (forward === 0) // points are equal, so we have a zero-length segment - continue; // just skip it - - eventAddSegment( - segmentNew( - forward < 0 ? pt1 : pt2, - forward < 0 ? pt2 : pt1 - ), - true - ); - } - }, - calculate: function(inverted){ - // is the polygon inverted? - // returns segments - return calculate(inverted, false); - } - }; -} - -module.exports = Intersecter; - -},{"./linked-list":478}],478:[function(_dereq_,module,exports){ -// (c) Copyright 2016, Sean Connelly (@voidqk), http://syntheti.cc -// MIT License -// Project Home: https://github.com/voidqk/polybooljs - -// -// simple linked list implementation that allows you to traverse down nodes and save positions -// - -var LinkedList = { - create: function(){ - var my = { - root: { root: true, next: null }, - exists: function(node){ - if (node === null || node === my.root) - return false; - return true; - }, - isEmpty: function(){ - return my.root.next === null; - }, - getHead: function(){ - return my.root.next; - }, - insertBefore: function(node, check){ - var last = my.root; - var here = my.root.next; - while (here !== null){ - if (check(here)){ - node.prev = here.prev; - node.next = here; - here.prev.next = node; - here.prev = node; - return; - } - last = here; - here = here.next; - } - last.next = node; - node.prev = last; - node.next = null; - }, - findTransition: function(check){ - var prev = my.root; - var here = my.root.next; - while (here !== null){ - if (check(here)) - break; - prev = here; - here = here.next; - } - return { - before: prev === my.root ? null : prev, - after: here, - insert: function(node){ - node.prev = prev; - node.next = here; - prev.next = node; - if (here !== null) - here.prev = node; - return node; - } - }; - } - }; - return my; - }, - node: function(data){ - data.prev = null; - data.next = null; - data.remove = function(){ - data.prev.next = data.next; - if (data.next) - data.next.prev = data.prev; - data.prev = null; - data.next = null; - }; - return data; - } -}; - -module.exports = LinkedList; - -},{}],479:[function(_dereq_,module,exports){ -// (c) Copyright 2016, Sean Connelly (@voidqk), http://syntheti.cc -// MIT License -// Project Home: https://github.com/voidqk/polybooljs - -// -// converts a list of segments into a list of regions, while also removing unnecessary verticies -// - -function SegmentChainer(segments, eps, buildLog){ - var chains = []; - var regions = []; - - segments.forEach(function(seg){ - var pt1 = seg.start; - var pt2 = seg.end; - if (eps.pointsSame(pt1, pt2)){ - console.warn('PolyBool: Warning: Zero-length segment detected; your epsilon is ' + - 'probably too small or too large'); - return; - } - - if (buildLog) - buildLog.chainStart(seg); - - // search for two chains that this segment matches - var first_match = { - index: 0, - matches_head: false, - matches_pt1: false - }; - var second_match = { - index: 0, - matches_head: false, - matches_pt1: false - }; - var next_match = first_match; - function setMatch(index, matches_head, matches_pt1){ - // return true if we've matched twice - next_match.index = index; - next_match.matches_head = matches_head; - next_match.matches_pt1 = matches_pt1; - if (next_match === first_match){ - next_match = second_match; - return false; - } - next_match = null; - return true; // we've matched twice, we're done here - } - for (var i = 0; i < chains.length; i++){ - var chain = chains[i]; - var head = chain[0]; - var head2 = chain[1]; - var tail = chain[chain.length - 1]; - var tail2 = chain[chain.length - 2]; - if (eps.pointsSame(head, pt1)){ - if (setMatch(i, true, true)) - break; - } - else if (eps.pointsSame(head, pt2)){ - if (setMatch(i, true, false)) - break; - } - else if (eps.pointsSame(tail, pt1)){ - if (setMatch(i, false, true)) - break; - } - else if (eps.pointsSame(tail, pt2)){ - if (setMatch(i, false, false)) - break; - } - } - - if (next_match === first_match){ - // we didn't match anything, so create a new chain - chains.push([ pt1, pt2 ]); - if (buildLog) - buildLog.chainNew(pt1, pt2); - return; - } - - if (next_match === second_match){ - // we matched a single chain - - if (buildLog) - buildLog.chainMatch(first_match.index); - - // add the other point to the apporpriate end, and check to see if we've closed the - // chain into a loop - - var index = first_match.index; - var pt = first_match.matches_pt1 ? pt2 : pt1; // if we matched pt1, then we add pt2, etc - var addToHead = first_match.matches_head; // if we matched at head, then add to the head - - var chain = chains[index]; - var grow = addToHead ? chain[0] : chain[chain.length - 1]; - var grow2 = addToHead ? chain[1] : chain[chain.length - 2]; - var oppo = addToHead ? chain[chain.length - 1] : chain[0]; - var oppo2 = addToHead ? chain[chain.length - 2] : chain[1]; - - if (eps.pointsCollinear(grow2, grow, pt)){ - // grow isn't needed because it's directly between grow2 and pt: - // grow2 ---grow---> pt - if (addToHead){ - if (buildLog) - buildLog.chainRemoveHead(first_match.index, pt); - chain.shift(); - } - else{ - if (buildLog) - buildLog.chainRemoveTail(first_match.index, pt); - chain.pop(); - } - grow = grow2; // old grow is gone... new grow is what grow2 was - } - - if (eps.pointsSame(oppo, pt)){ - // we're closing the loop, so remove chain from chains - chains.splice(index, 1); - - if (eps.pointsCollinear(oppo2, oppo, grow)){ - // oppo isn't needed because it's directly between oppo2 and grow: - // oppo2 ---oppo--->grow - if (addToHead){ - if (buildLog) - buildLog.chainRemoveTail(first_match.index, grow); - chain.pop(); - } - else{ - if (buildLog) - buildLog.chainRemoveHead(first_match.index, grow); - chain.shift(); - } - } - - if (buildLog) - buildLog.chainClose(first_match.index); - - // we have a closed chain! - regions.push(chain); - return; - } - - // not closing a loop, so just add it to the apporpriate side - if (addToHead){ - if (buildLog) - buildLog.chainAddHead(first_match.index, pt); - chain.unshift(pt); - } - else{ - if (buildLog) - buildLog.chainAddTail(first_match.index, pt); - chain.push(pt); - } - return; - } - - // otherwise, we matched two chains, so we need to combine those chains together - - function reverseChain(index){ - if (buildLog) - buildLog.chainReverse(index); - chains[index].reverse(); // gee, that's easy - } - - function appendChain(index1, index2){ - // index1 gets index2 appended to it, and index2 is removed - var chain1 = chains[index1]; - var chain2 = chains[index2]; - var tail = chain1[chain1.length - 1]; - var tail2 = chain1[chain1.length - 2]; - var head = chain2[0]; - var head2 = chain2[1]; - - if (eps.pointsCollinear(tail2, tail, head)){ - // tail isn't needed because it's directly between tail2 and head - // tail2 ---tail---> head - if (buildLog) - buildLog.chainRemoveTail(index1, tail); - chain1.pop(); - tail = tail2; // old tail is gone... new tail is what tail2 was - } - - if (eps.pointsCollinear(tail, head, head2)){ - // head isn't needed because it's directly between tail and head2 - // tail ---head---> head2 - if (buildLog) - buildLog.chainRemoveHead(index2, head); - chain2.shift(); - } - - if (buildLog) - buildLog.chainJoin(index1, index2); - chains[index1] = chain1.concat(chain2); - chains.splice(index2, 1); - } - - var F = first_match.index; - var S = second_match.index; - - if (buildLog) - buildLog.chainConnect(F, S); - - var reverseF = chains[F].length < chains[S].length; // reverse the shorter chain, if needed - if (first_match.matches_head){ - if (second_match.matches_head){ - if (reverseF){ - // <<<< F <<<< --- >>>> S >>>> - reverseChain(F); - // >>>> F >>>> --- >>>> S >>>> - appendChain(F, S); - } - else{ - // <<<< F <<<< --- >>>> S >>>> - reverseChain(S); - // <<<< F <<<< --- <<<< S <<<< logically same as: - // >>>> S >>>> --- >>>> F >>>> - appendChain(S, F); - } - } - else{ - // <<<< F <<<< --- <<<< S <<<< logically same as: - // >>>> S >>>> --- >>>> F >>>> - appendChain(S, F); - } - } - else{ - if (second_match.matches_head){ - // >>>> F >>>> --- >>>> S >>>> - appendChain(F, S); - } - else{ - if (reverseF){ - // >>>> F >>>> --- <<<< S <<<< - reverseChain(F); - // <<<< F <<<< --- <<<< S <<<< logically same as: - // >>>> S >>>> --- >>>> F >>>> - appendChain(S, F); - } - else{ - // >>>> F >>>> --- <<<< S <<<< - reverseChain(S); - // >>>> F >>>> --- >>>> S >>>> - appendChain(F, S); - } - } - } - }); - - return regions; -} - -module.exports = SegmentChainer; - -},{}],480:[function(_dereq_,module,exports){ -// (c) Copyright 2016, Sean Connelly (@voidqk), http://syntheti.cc -// MIT License -// Project Home: https://github.com/voidqk/polybooljs - -// -// filter a list of segments based on boolean operations -// - -function select(segments, selection, buildLog){ - var result = []; - segments.forEach(function(seg){ - var index = - (seg.myFill.above ? 8 : 0) + - (seg.myFill.below ? 4 : 0) + - ((seg.otherFill && seg.otherFill.above) ? 2 : 0) + - ((seg.otherFill && seg.otherFill.below) ? 1 : 0); - if (selection[index] !== 0){ - // copy the segment to the results, while also calculating the fill status - result.push({ - id: buildLog ? buildLog.segmentId() : -1, - start: seg.start, - end: seg.end, - myFill: { - above: selection[index] === 1, // 1 if filled above - below: selection[index] === 2 // 2 if filled below - }, - otherFill: null - }); - } - }); - - if (buildLog) - buildLog.selected(result); - - return result; -} - -var SegmentSelector = { - union: function(segments, buildLog){ // primary | secondary - // above1 below1 above2 below2 Keep? Value - // 0 0 0 0 => no 0 - // 0 0 0 1 => yes filled below 2 - // 0 0 1 0 => yes filled above 1 - // 0 0 1 1 => no 0 - // 0 1 0 0 => yes filled below 2 - // 0 1 0 1 => yes filled below 2 - // 0 1 1 0 => no 0 - // 0 1 1 1 => no 0 - // 1 0 0 0 => yes filled above 1 - // 1 0 0 1 => no 0 - // 1 0 1 0 => yes filled above 1 - // 1 0 1 1 => no 0 - // 1 1 0 0 => no 0 - // 1 1 0 1 => no 0 - // 1 1 1 0 => no 0 - // 1 1 1 1 => no 0 - return select(segments, [ - 0, 2, 1, 0, - 2, 2, 0, 0, - 1, 0, 1, 0, - 0, 0, 0, 0 - ], buildLog); - }, - intersect: function(segments, buildLog){ // primary & secondary - // above1 below1 above2 below2 Keep? Value - // 0 0 0 0 => no 0 - // 0 0 0 1 => no 0 - // 0 0 1 0 => no 0 - // 0 0 1 1 => no 0 - // 0 1 0 0 => no 0 - // 0 1 0 1 => yes filled below 2 - // 0 1 1 0 => no 0 - // 0 1 1 1 => yes filled below 2 - // 1 0 0 0 => no 0 - // 1 0 0 1 => no 0 - // 1 0 1 0 => yes filled above 1 - // 1 0 1 1 => yes filled above 1 - // 1 1 0 0 => no 0 - // 1 1 0 1 => yes filled below 2 - // 1 1 1 0 => yes filled above 1 - // 1 1 1 1 => no 0 - return select(segments, [ - 0, 0, 0, 0, - 0, 2, 0, 2, - 0, 0, 1, 1, - 0, 2, 1, 0 - ], buildLog); - }, - difference: function(segments, buildLog){ // primary - secondary - // above1 below1 above2 below2 Keep? Value - // 0 0 0 0 => no 0 - // 0 0 0 1 => no 0 - // 0 0 1 0 => no 0 - // 0 0 1 1 => no 0 - // 0 1 0 0 => yes filled below 2 - // 0 1 0 1 => no 0 - // 0 1 1 0 => yes filled below 2 - // 0 1 1 1 => no 0 - // 1 0 0 0 => yes filled above 1 - // 1 0 0 1 => yes filled above 1 - // 1 0 1 0 => no 0 - // 1 0 1 1 => no 0 - // 1 1 0 0 => no 0 - // 1 1 0 1 => yes filled above 1 - // 1 1 1 0 => yes filled below 2 - // 1 1 1 1 => no 0 - return select(segments, [ - 0, 0, 0, 0, - 2, 0, 2, 0, - 1, 1, 0, 0, - 0, 1, 2, 0 - ], buildLog); - }, - differenceRev: function(segments, buildLog){ // secondary - primary - // above1 below1 above2 below2 Keep? Value - // 0 0 0 0 => no 0 - // 0 0 0 1 => yes filled below 2 - // 0 0 1 0 => yes filled above 1 - // 0 0 1 1 => no 0 - // 0 1 0 0 => no 0 - // 0 1 0 1 => no 0 - // 0 1 1 0 => yes filled above 1 - // 0 1 1 1 => yes filled above 1 - // 1 0 0 0 => no 0 - // 1 0 0 1 => yes filled below 2 - // 1 0 1 0 => no 0 - // 1 0 1 1 => yes filled below 2 - // 1 1 0 0 => no 0 - // 1 1 0 1 => no 0 - // 1 1 1 0 => no 0 - // 1 1 1 1 => no 0 - return select(segments, [ - 0, 2, 1, 0, - 0, 0, 1, 1, - 0, 2, 0, 2, - 0, 0, 0, 0 - ], buildLog); - }, - xor: function(segments, buildLog){ // primary ^ secondary - // above1 below1 above2 below2 Keep? Value - // 0 0 0 0 => no 0 - // 0 0 0 1 => yes filled below 2 - // 0 0 1 0 => yes filled above 1 - // 0 0 1 1 => no 0 - // 0 1 0 0 => yes filled below 2 - // 0 1 0 1 => no 0 - // 0 1 1 0 => no 0 - // 0 1 1 1 => yes filled above 1 - // 1 0 0 0 => yes filled above 1 - // 1 0 0 1 => no 0 - // 1 0 1 0 => no 0 - // 1 0 1 1 => yes filled below 2 - // 1 1 0 0 => no 0 - // 1 1 0 1 => yes filled above 1 - // 1 1 1 0 => yes filled below 2 - // 1 1 1 1 => no 0 - return select(segments, [ - 0, 2, 1, 0, - 2, 0, 0, 1, - 1, 0, 0, 2, - 0, 1, 2, 0 - ], buildLog); - } -}; - -module.exports = SegmentSelector; - -},{}],481:[function(_dereq_,module,exports){ -//Optimized version for triangle closest point -// Based on Eberly's WildMagick codes -// http://www.geometrictools.com/LibMathematics/Distance/Distance.html -"use strict"; - -var diff = new Float64Array(4); -var edge0 = new Float64Array(4); -var edge1 = new Float64Array(4); - -function closestPoint2d(V0, V1, V2, point, result) { - //Reallocate buffers if necessary - if(diff.length < point.length) { - diff = new Float64Array(point.length); - edge0 = new Float64Array(point.length); - edge1 = new Float64Array(point.length); - } - //Compute edges - for(var i=0; i= a00) { - s = 1.0; - sqrDistance = a00 + 2.0*b0 + c; - } else { - s = -b0/a00; - sqrDistance = b0*s + c; - } - } else { - s = 0; - if (b1 >= 0) { - t = 0; - sqrDistance = c; - } else if (-b1 >= a11) { - t = 1; - sqrDistance = a11 + 2.0*b1 + c; - } else { - t = -b1/a11; - sqrDistance = b1*t + c; - } - } - } else { // region 3 - s = 0; - if (b1 >= 0) { - t = 0; - sqrDistance = c; - } else if (-b1 >= a11) { - t = 1; - sqrDistance = a11 + 2.0*b1 + c; - } else { - t = -b1/a11; - sqrDistance = b1*t + c; - } - } - } else if (t < 0) { // region 5 - t = 0; - if (b0 >= 0) { - s = 0; - sqrDistance = c; - } else if (-b0 >= a00) { - s = 1; - sqrDistance = a00 + 2.0*b0 + c; - } else { - s = -b0/a00; - sqrDistance = b0*s + c; - } - } else { // region 0 - // minimum at interior point - var invDet = 1.0 / det; - s *= invDet; - t *= invDet; - sqrDistance = s*(a00*s + a01*t + 2.0*b0) + t*(a01*s + a11*t + 2.0*b1) + c; - } - } else { - var tmp0, tmp1, numer, denom; - - if (s < 0) { // region 2 - tmp0 = a01 + b0; - tmp1 = a11 + b1; - if (tmp1 > tmp0) { - numer = tmp1 - tmp0; - denom = a00 - 2.0*a01 + a11; - if (numer >= denom) { - s = 1; - t = 0; - sqrDistance = a00 + 2.0*b0 + c; - } else { - s = numer/denom; - t = 1 - s; - sqrDistance = s*(a00*s + a01*t + 2.0*b0) + - t*(a01*s + a11*t + 2.0*b1) + c; - } - } else { - s = 0; - if (tmp1 <= 0) { - t = 1; - sqrDistance = a11 + 2.0*b1 + c; - } else if (b1 >= 0) { - t = 0; - sqrDistance = c; - } else { - t = -b1/a11; - sqrDistance = b1*t + c; - } - } - } else if (t < 0) { // region 6 - tmp0 = a01 + b1; - tmp1 = a00 + b0; - if (tmp1 > tmp0) { - numer = tmp1 - tmp0; - denom = a00 - 2.0*a01 + a11; - if (numer >= denom) { - t = 1; - s = 0; - sqrDistance = a11 + 2.0*b1 + c; - } else { - t = numer/denom; - s = 1 - t; - sqrDistance = s*(a00*s + a01*t + 2.0*b0) + - t*(a01*s + a11*t + 2.0*b1) + c; - } - } else { - t = 0; - if (tmp1 <= 0) { - s = 1; - sqrDistance = a00 + 2.0*b0 + c; - } else if (b0 >= 0) { - s = 0; - sqrDistance = c; - } else { - s = -b0/a00; - sqrDistance = b0*s + c; - } - } - } else { // region 1 - numer = a11 + b1 - a01 - b0; - if (numer <= 0) { - s = 0; - t = 1; - sqrDistance = a11 + 2.0*b1 + c; - } else { - denom = a00 - 2.0*a01 + a11; - if (numer >= denom) { - s = 1; - t = 0; - sqrDistance = a00 + 2.0*b0 + c; - } else { - s = numer/denom; - t = 1 - s; - sqrDistance = s*(a00*s + a01*t + 2.0*b0) + - t*(a01*s + a11*t + 2.0*b1) + c; - } - } - } - } - var u = 1.0 - s - t; - for(var i=0; i 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; - -process.listeners = function (name) { return [] } - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],483:[function(_dereq_,module,exports){ -module.exports = _dereq_('gl-quat/slerp') -},{"gl-quat/slerp":293}],484:[function(_dereq_,module,exports){ -(function (global){ -var now = _dereq_('performance-now') - , root = typeof window === 'undefined' ? global : window - , vendors = ['moz', 'webkit'] - , suffix = 'AnimationFrame' - , raf = root['request' + suffix] - , caf = root['cancel' + suffix] || root['cancelRequest' + suffix] - -for(var i = 0; !raf && i < vendors.length; i++) { - raf = root[vendors[i] + 'Request' + suffix] - caf = root[vendors[i] + 'Cancel' + suffix] - || root[vendors[i] + 'CancelRequest' + suffix] -} - -// Some versions of FF have rAF but not cAF -if(!raf || !caf) { - var last = 0 - , id = 0 - , queue = [] - , frameDuration = 1000 / 60 - - raf = function(callback) { - if(queue.length === 0) { - var _now = now() - , next = Math.max(0, frameDuration - (_now - last)) - last = next + _now - setTimeout(function() { - var cp = queue.slice(0) - // Clear queue here to prevent - // callbacks from appending listeners - // to the current frame's queue - queue.length = 0 - for(var i = 0; i < cp.length; i++) { - if(!cp[i].cancelled) { - try{ - cp[i].callback(last) - } catch(e) { - setTimeout(function() { throw e }, 0) - } - } - } - }, Math.round(next)) - } - queue.push({ - handle: ++id, - callback: callback, - cancelled: false - }) - return id - } - - caf = function(handle) { - for(var i = 0; i < queue.length; i++) { - if(queue[i].handle === handle) { - queue[i].cancelled = true - } - } - } -} - -module.exports = function(fn) { - // Wrap in a new function to prevent - // `cancel` potentially being assigned - // to the native rAF function - return raf.call(root, fn) -} -module.exports.cancel = function() { - caf.apply(root, arguments) -} -module.exports.polyfill = function(object) { - if (!object) { - object = root; - } - object.requestAnimationFrame = raf - object.cancelAnimationFrame = caf -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"performance-now":462}],485:[function(_dereq_,module,exports){ -'use strict' - -var bnadd = _dereq_('big-rat/add') - -module.exports = add - -function add (a, b) { - var n = a.length - var r = new Array(n) - for (var i=0; i 0) { - var f = cells[ptr-1] - if(compareCell(c, f) === 0 && - orientation(f) !== o) { - ptr -= 1 - continue - } - } - cells[ptr++] = c - } - cells.length = ptr - return cells -} - -},{"cell-orientation":112,"compare-cell":128,"compare-oriented-cell":129}],490:[function(_dereq_,module,exports){ -'use strict' - -var getBounds = _dereq_('array-bounds') -var rgba = _dereq_('color-normalize') -var updateDiff = _dereq_('update-diff') -var pick = _dereq_('pick-by-alias') -var extend = _dereq_('object-assign') -var flatten = _dereq_('flatten-vertex-data') -var ref = _dereq_('to-float32'); -var float32 = ref.float32; -var fract32 = ref.fract32; - -module.exports = Error2D - -var WEIGHTS = [ - //direction, lineWidth shift, capSize shift - - // x-error bar - [1, 0, 0, 1, 0, 0], - [1, 0, 0, -1, 0, 0], - [-1, 0, 0, -1, 0, 0], - - [-1, 0, 0, -1, 0, 0], - [-1, 0, 0, 1, 0, 0], - [1, 0, 0, 1, 0, 0], - - // x-error right cap - [1, 0, -1, 0, 0, 1], - [1, 0, -1, 0, 0, -1], - [1, 0, 1, 0, 0, -1], - - [1, 0, 1, 0, 0, -1], - [1, 0, 1, 0, 0, 1], - [1, 0, -1, 0, 0, 1], - - // x-error left cap - [-1, 0, -1, 0, 0, 1], - [-1, 0, -1, 0, 0, -1], - [-1, 0, 1, 0, 0, -1], - - [-1, 0, 1, 0, 0, -1], - [-1, 0, 1, 0, 0, 1], - [-1, 0, -1, 0, 0, 1], - - // y-error bar - [0, 1, 1, 0, 0, 0], - [0, 1, -1, 0, 0, 0], - [0, -1, -1, 0, 0, 0], - - [0, -1, -1, 0, 0, 0], - [0, 1, 1, 0, 0, 0], - [0, -1, 1, 0, 0, 0], - - // y-error top cap - [0, 1, 0, -1, 1, 0], - [0, 1, 0, -1, -1, 0], - [0, 1, 0, 1, -1, 0], - - [0, 1, 0, 1, 1, 0], - [0, 1, 0, -1, 1, 0], - [0, 1, 0, 1, -1, 0], - - // y-error bottom cap - [0, -1, 0, -1, 1, 0], - [0, -1, 0, -1, -1, 0], - [0, -1, 0, 1, -1, 0], - - [0, -1, 0, 1, 1, 0], - [0, -1, 0, -1, 1, 0], - [0, -1, 0, 1, -1, 0] -] - - -function Error2D (regl, options) { - if (typeof regl === 'function') { - if (!options) { options = {} } - options.regl = regl - } - else { - options = regl - } - if (options.length) { options.positions = options } - regl = options.regl - - if (!regl.hasExtension('ANGLE_instanced_arrays')) { - throw Error('regl-error2d: `ANGLE_instanced_arrays` extension should be enabled'); - } - - // persistent variables - var gl = regl._gl, drawErrors, positionBuffer, positionFractBuffer, colorBuffer, errorBuffer, meshBuffer, - defaults = { - color: 'black', - capSize: 5, - lineWidth: 1, - opacity: 1, - viewport: null, - range: null, - offset: 0, - count: 0, - bounds: null, - positions: [], - errors: [] - }, groups = [] - - //color per-point - colorBuffer = regl.buffer({ - usage: 'dynamic', - type: 'uint8', - data: new Uint8Array(0) - }) - //xy-position per-point - positionBuffer = regl.buffer({ - usage: 'dynamic', - type: 'float', - data: new Uint8Array(0) - }) - //xy-position float32-fraction - positionFractBuffer = regl.buffer({ - usage: 'dynamic', - type: 'float', - data: new Uint8Array(0) - }) - //4 errors per-point - errorBuffer = regl.buffer({ - usage: 'dynamic', - type: 'float', - data: new Uint8Array(0) - }) - //error bar mesh - meshBuffer = regl.buffer({ - usage: 'static', - type: 'float', - data: WEIGHTS - }) - - update(options) - - //drawing method - drawErrors = regl({ - vert: "\n\t\tprecision highp float;\n\n\t\tattribute vec2 position, positionFract;\n\t\tattribute vec4 error;\n\t\tattribute vec4 color;\n\n\t\tattribute vec2 direction, lineOffset, capOffset;\n\n\t\tuniform vec4 viewport;\n\t\tuniform float lineWidth, capSize;\n\t\tuniform vec2 scale, scaleFract, translate, translateFract;\n\n\t\tvarying vec4 fragColor;\n\n\t\tvoid main() {\n\t\t\tfragColor = color / 255.;\n\n\t\t\tvec2 pixelOffset = lineWidth * lineOffset + (capSize + lineWidth) * capOffset;\n\n\t\t\tvec2 dxy = -step(.5, direction.xy) * error.xz + step(direction.xy, vec2(-.5)) * error.yw;\n\n\t\t\tvec2 position = position + dxy;\n\n\t\t\tvec2 pos = (position + translate) * scale\n\t\t\t\t+ (positionFract + translateFract) * scale\n\t\t\t\t+ (position + translate) * scaleFract\n\t\t\t\t+ (positionFract + translateFract) * scaleFract;\n\n\t\t\tpos += pixelOffset / viewport.zw;\n\n\t\t\tgl_Position = vec4(pos * 2. - 1., 0, 1);\n\t\t}\n\t\t", - - frag: "\n\t\tprecision highp float;\n\n\t\tvarying vec4 fragColor;\n\n\t\tuniform float opacity;\n\n\t\tvoid main() {\n\t\t\tgl_FragColor = fragColor;\n\t\t\tgl_FragColor.a *= opacity;\n\t\t}\n\t\t", - - uniforms: { - range: regl.prop('range'), - lineWidth: regl.prop('lineWidth'), - capSize: regl.prop('capSize'), - opacity: regl.prop('opacity'), - scale: regl.prop('scale'), - translate: regl.prop('translate'), - scaleFract: regl.prop('scaleFract'), - translateFract: regl.prop('translateFract'), - viewport: function (ctx, prop) { return [prop.viewport.x, prop.viewport.y, ctx.viewportWidth, ctx.viewportHeight]; } - }, - - attributes: { - //dynamic attributes - color: { - buffer: colorBuffer, - offset: function (ctx, prop) { return prop.offset * 4; }, - divisor: 1, - }, - position: { - buffer: positionBuffer, - offset: function (ctx, prop) { return prop.offset * 8; }, - divisor: 1 - }, - positionFract: { - buffer: positionFractBuffer, - offset: function (ctx, prop) { return prop.offset * 8; }, - divisor: 1 - }, - error: { - buffer: errorBuffer, - offset: function (ctx, prop) { return prop.offset * 16; }, - divisor: 1 - }, - - //static attributes - direction: { - buffer: meshBuffer, - stride: 24, - offset: 0 - }, - lineOffset: { - buffer: meshBuffer, - stride: 24, - offset: 8 - }, - capOffset: { - buffer: meshBuffer, - stride: 24, - offset: 16 - } - }, - - primitive: 'triangles', - - blend: { - enable: true, - color: [0,0,0,0], - equation: { - rgb: 'add', - alpha: 'add' - }, - func: { - srcRGB: 'src alpha', - dstRGB: 'one minus src alpha', - srcAlpha: 'one minus dst alpha', - dstAlpha: 'one' - } - }, - - depth: { - enable: false - }, - - scissor: { - enable: true, - box: regl.prop('viewport') - }, - viewport: regl.prop('viewport'), - stencil: false, - - instances: regl.prop('count'), - count: WEIGHTS.length - }) - - //expose API - extend(error2d, { - update: update, - draw: draw, - destroy: destroy, - regl: regl, - gl: gl, - canvas: gl.canvas, - groups: groups - }) - - return error2d - - function error2d (opts) { - //update - if (opts) { - update(opts) - } - - //destroy - else if (opts === null) { - destroy() - } - - draw() - } - - - //main draw method - function draw (options) { - if (typeof options === 'number') { return drawGroup(options) } - - //make options a batch - if (options && !Array.isArray(options)) { options = [options] } - - - regl._refresh() - - //render multiple polylines via regl batch - groups.forEach(function (s, i) { - if (!s) { return } - - if (options) { - if (!options[i]) { s.draw = false } - else { s.draw = true } - } - - //ignore draw flag for one pass - if (!s.draw) { - s.draw = true; - return - } - - drawGroup(i) - }) - } - - //draw single error group by id - function drawGroup (s) { - if (typeof s === 'number') { s = groups[s] } - if (s == null) { return } - - if (!(s && s.count && s.color && s.opacity && s.positions && s.positions.length > 1)) { return } - - s.scaleRatio = [ - s.scale[0] * s.viewport.width, - s.scale[1] * s.viewport.height - ] - - drawErrors(s) - - if (s.after) { s.after(s) } - } - - function update (options) { - if (!options) { return } - - //direct points argument - if (options.length != null) { - if (typeof options[0] === 'number') { options = [{positions: options}] } - } - - //make options a batch - else if (!Array.isArray(options)) { options = [options] } - - //global count of points - var pointCount = 0, errorCount = 0 - - error2d.groups = groups = options.map(function (options, i) { - var group = groups[i] - - if (!options) { return group } - else if (typeof options === 'function') { options = {after: options} } - else if (typeof options[0] === 'number') { options = {positions: options} } - - //copy options to avoid mutation & handle aliases - options = pick(options, { - color: 'color colors fill', - capSize: 'capSize cap capsize cap-size', - lineWidth: 'lineWidth line-width width line thickness', - opacity: 'opacity alpha', - range: 'range dataBox', - viewport: 'viewport viewBox', - errors: 'errors error', - positions: 'positions position data points' - }) - - if (!group) { - groups[i] = group = { - id: i, - scale: null, - translate: null, - scaleFract: null, - translateFract: null, - draw: true - } - options = extend({}, defaults, options) - } - - updateDiff(group, options, [{ - lineWidth: function (v) { return +v * .5; }, - capSize: function (v) { return +v * .5; }, - opacity: parseFloat, - errors: function (errors) { - errors = flatten(errors) - - errorCount += errors.length - return errors - }, - positions: function (positions, state) { - positions = flatten(positions, 'float64') - state.count = Math.floor(positions.length / 2) - state.bounds = getBounds(positions, 2) - state.offset = pointCount - - pointCount += state.count - - return positions - } - }, { - color: function (colors, state) { - var count = state.count - - if (!colors) { colors = 'transparent' } - - // 'black' or [0,0,0,0] case - if (!Array.isArray(colors) || typeof colors[0] === 'number') { - var color = colors - colors = Array(count) - for (var i = 0; i < count; i++) { - colors[i] = color - } - } - - if (colors.length < count) { throw Error('Not enough colors') } - - var colorData = new Uint8Array(count * 4) - - //convert colors to float arrays - for (var i$1 = 0; i$1 < count; i$1++) { - var c = rgba(colors[i$1], 'uint8') - colorData.set(c, i$1 * 4) - } - - return colorData - }, - - range: function (range, state, options) { - var bounds = state.bounds - if (!range) { range = bounds } - - state.scale = [1 / (range[2] - range[0]), 1 / (range[3] - range[1])] - state.translate = [-range[0], -range[1]] - - state.scaleFract = fract32(state.scale) - state.translateFract = fract32(state.translate) - - return range - }, - - viewport: function (vp) { - var viewport - - if (Array.isArray(vp)) { - viewport = { - x: vp[0], - y: vp[1], - width: vp[2] - vp[0], - height: vp[3] - vp[1] - } - } - else if (vp) { - viewport = { - x: vp.x || vp.left || 0, - y: vp.y || vp.top || 0 - } - - if (vp.right) { viewport.width = vp.right - viewport.x } - else { viewport.width = vp.w || vp.width || 0 } - - if (vp.bottom) { viewport.height = vp.bottom - viewport.y } - else { viewport.height = vp.h || vp.height || 0 } - } - else { - viewport = { - x: 0, y: 0, - width: gl.drawingBufferWidth, - height: gl.drawingBufferHeight - } - } - - return viewport - } - }]) - - return group - }) - - if (pointCount || errorCount) { - var len = groups.reduce(function (acc, group, i) { - return acc + (group ? group.count : 0) - }, 0) - - var positionData = new Float64Array(len * 2) - var colorData = new Uint8Array(len * 4) - var errorData = new Float32Array(len * 4) - - groups.forEach(function (group, i) { - if (!group) { return } - var positions = group.positions; - var count = group.count; - var offset = group.offset; - var color = group.color; - var errors = group.errors; - if (!count) { return } - - colorData.set(color, offset * 4) - errorData.set(errors, offset * 4) - positionData.set(positions, offset * 2) - }) - - positionBuffer(float32(positionData)) - positionFractBuffer(fract32(positionData)) - colorBuffer(colorData) - errorBuffer(errorData) - } - - } - - function destroy () { - positionBuffer.destroy() - positionFractBuffer.destroy() - colorBuffer.destroy() - errorBuffer.destroy() - meshBuffer.destroy() - } -} - -},{"array-bounds":65,"color-normalize":120,"flatten-vertex-data":227,"object-assign":454,"pick-by-alias":465,"to-float32":538,"update-diff":549}],491:[function(_dereq_,module,exports){ -'use strict' - - -var rgba = _dereq_('color-normalize') -var getBounds = _dereq_('array-bounds') -var extend = _dereq_('object-assign') -var glslify = _dereq_('glslify') -var pick = _dereq_('pick-by-alias') -var flatten = _dereq_('flatten-vertex-data') -var triangulate = _dereq_('earcut') -var normalize = _dereq_('array-normalize') -var ref = _dereq_('to-float32'); -var float32 = ref.float32; -var fract32 = ref.fract32; -var WeakMap = _dereq_('es6-weak-map') -var parseRect = _dereq_('parse-rect') - - -module.exports = Line2D - - -/** @constructor */ -function Line2D (regl, options) { - if (!(this instanceof Line2D)) { return new Line2D(regl, options) } - - if (typeof regl === 'function') { - if (!options) { options = {} } - options.regl = regl - } - else { - options = regl - } - if (options.length) { options.positions = options } - regl = options.regl - - if (!regl.hasExtension('ANGLE_instanced_arrays')) { - throw Error('regl-error2d: `ANGLE_instanced_arrays` extension should be enabled'); - } - - // persistent variables - this.gl = regl._gl - this.regl = regl - - // list of options for lines - this.passes = [] - - // cached shaders instance - this.shaders = Line2D.shaders.has(regl) ? Line2D.shaders.get(regl) : Line2D.shaders.set(regl, Line2D.createShaders(regl)).get(regl) - - - // init defaults - this.update(options) -} - - -Line2D.dashMult = 2 -Line2D.maxPatternLength = 256 -Line2D.precisionThreshold = 3e6 -Line2D.maxPoints = 1e4 -Line2D.maxLines = 2048 - - -// cache of created draw calls per-regl instance -Line2D.shaders = new WeakMap() - - -// create static shaders once -Line2D.createShaders = function (regl) { - var offsetBuffer = regl.buffer({ - usage: 'static', - type: 'float', - data: [0,1, 0,0, 1,1, 1,0] - }) - - var shaderOptions = { - primitive: 'triangle strip', - instances: regl.prop('count'), - count: 4, - offset: 0, - - uniforms: { - miterMode: function (ctx, prop) { return prop.join === 'round' ? 2 : 1; }, - miterLimit: regl.prop('miterLimit'), - scale: regl.prop('scale'), - scaleFract: regl.prop('scaleFract'), - translateFract: regl.prop('translateFract'), - translate: regl.prop('translate'), - thickness: regl.prop('thickness'), - dashPattern: regl.prop('dashTexture'), - opacity: regl.prop('opacity'), - pixelRatio: regl.context('pixelRatio'), - id: regl.prop('id'), - dashSize: regl.prop('dashLength'), - viewport: function (c, p) { return [p.viewport.x, p.viewport.y, c.viewportWidth, c.viewportHeight]; }, - depth: regl.prop('depth') - }, - - blend: { - enable: true, - color: [0,0,0,0], - equation: { - rgb: 'add', - alpha: 'add' - }, - func: { - srcRGB: 'src alpha', - dstRGB: 'one minus src alpha', - srcAlpha: 'one minus dst alpha', - dstAlpha: 'one' - } - }, - depth: { - enable: function (c, p) { - return !p.overlay - } - }, - stencil: {enable: false}, - scissor: { - enable: true, - box: regl.prop('viewport') - }, - viewport: regl.prop('viewport') - } - - - // simplified rectangular line shader - var drawRectLine = regl(extend({ - vert: glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec2 aCoord, bCoord, aCoordFract, bCoordFract;\nattribute vec4 color;\nattribute float lineEnd, lineTop;\n\nuniform vec2 scale, scaleFract, translate, translateFract;\nuniform float thickness, pixelRatio, id, depth;\nuniform vec4 viewport;\n\nvarying vec4 fragColor;\nvarying vec2 tangent;\n\nvec2 project(vec2 position, vec2 positionFract, vec2 scale, vec2 scaleFract, vec2 translate, vec2 translateFract) {\n\t// the order is important\n\treturn position * scale + translate\n + positionFract * scale + translateFract\n + position * scaleFract\n + positionFract * scaleFract;\n}\n\nvoid main() {\n\tfloat lineStart = 1. - lineEnd;\n\tfloat lineOffset = lineTop * 2. - 1.;\n\n\tvec2 diff = (bCoord + bCoordFract - aCoord - aCoordFract);\n\ttangent = normalize(diff * scale * viewport.zw);\n\tvec2 normal = vec2(-tangent.y, tangent.x);\n\n\tvec2 position = project(aCoord, aCoordFract, scale, scaleFract, translate, translateFract) * lineStart\n\t\t+ project(bCoord, bCoordFract, scale, scaleFract, translate, translateFract) * lineEnd\n\n\t\t+ thickness * normal * .5 * lineOffset / viewport.zw;\n\n\tgl_Position = vec4(position * 2.0 - 1.0, depth, 1);\n\n\tfragColor = color / 255.;\n}\n"]), - frag: glslify(["precision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D dashPattern;\n\nuniform float dashSize, pixelRatio, thickness, opacity, id;\n\nvarying vec4 fragColor;\nvarying vec2 tangent;\n\nvoid main() {\n\tfloat alpha = 1.;\n\n\tfloat t = fract(dot(tangent, gl_FragCoord.xy) / dashSize) * .5 + .25;\n\tfloat dash = texture2D(dashPattern, vec2(t, .5)).r;\n\n\tgl_FragColor = fragColor;\n\tgl_FragColor.a *= alpha * opacity * dash;\n}\n"]), - - attributes: { - // if point is at the end of segment - lineEnd: { - buffer: offsetBuffer, - divisor: 0, - stride: 8, - offset: 0 - }, - // if point is at the top of segment - lineTop: { - buffer: offsetBuffer, - divisor: 0, - stride: 8, - offset: 4 - }, - // beginning of line coordinate - aCoord: { - buffer: regl.prop('positionBuffer'), - stride: 8, - offset: 8, - divisor: 1 - }, - // end of line coordinate - bCoord: { - buffer: regl.prop('positionBuffer'), - stride: 8, - offset: 16, - divisor: 1 - }, - aCoordFract: { - buffer: regl.prop('positionFractBuffer'), - stride: 8, - offset: 8, - divisor: 1 - }, - bCoordFract: { - buffer: regl.prop('positionFractBuffer'), - stride: 8, - offset: 16, - divisor: 1 - }, - color: { - buffer: regl.prop('colorBuffer'), - stride: 4, - offset: 0, - divisor: 1 - } - } - }, shaderOptions)) - - // create regl draw - var drawMiterLine - - try { - drawMiterLine = regl(extend({ - // culling removes polygon creasing - cull: { - enable: true, - face: 'back' - }, - - vert: glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec2 aCoord, bCoord, nextCoord, prevCoord;\nattribute vec4 aColor, bColor;\nattribute float lineEnd, lineTop;\n\nuniform vec2 scale, translate;\nuniform float thickness, pixelRatio, id, depth;\nuniform vec4 viewport;\nuniform float miterLimit, miterMode;\n\nvarying vec4 fragColor;\nvarying vec4 startCutoff, endCutoff;\nvarying vec2 tangent;\nvarying vec2 startCoord, endCoord;\nvarying float enableStartMiter, enableEndMiter;\n\nconst float REVERSE_THRESHOLD = -.875;\nconst float MIN_DIFF = 1e-6;\n\n// TODO: possible optimizations: avoid overcalculating all for vertices and calc just one instead\n// TODO: precalculate dot products, normalize things beforehead etc.\n// TODO: refactor to rectangular algorithm\n\nfloat distToLine(vec2 p, vec2 a, vec2 b) {\n\tvec2 diff = b - a;\n\tvec2 perp = normalize(vec2(-diff.y, diff.x));\n\treturn dot(p - a, perp);\n}\n\nbool isNaN( float val ){\n return ( val < 0.0 || 0.0 < val || val == 0.0 ) ? false : true;\n}\n\nvoid main() {\n\tvec2 aCoord = aCoord, bCoord = bCoord, prevCoord = prevCoord, nextCoord = nextCoord;\n\n vec2 adjustedScale;\n adjustedScale.x = (abs(scale.x) < MIN_DIFF) ? MIN_DIFF : scale.x;\n adjustedScale.y = (abs(scale.y) < MIN_DIFF) ? MIN_DIFF : scale.y;\n\n vec2 scaleRatio = adjustedScale * viewport.zw;\n\tvec2 normalWidth = thickness / scaleRatio;\n\n\tfloat lineStart = 1. - lineEnd;\n\tfloat lineBot = 1. - lineTop;\n\n\tfragColor = (lineStart * aColor + lineEnd * bColor) / 255.;\n\n\tif (isNaN(aCoord.x) || isNaN(aCoord.y) || isNaN(bCoord.x) || isNaN(bCoord.y)) return;\n\n\tif (aCoord == prevCoord) prevCoord = aCoord + normalize(bCoord - aCoord);\n\tif (bCoord == nextCoord) nextCoord = bCoord - normalize(bCoord - aCoord);\n\n\tvec2 prevDiff = aCoord - prevCoord;\n\tvec2 currDiff = bCoord - aCoord;\n\tvec2 nextDiff = nextCoord - bCoord;\n\n\tvec2 prevTangent = normalize(prevDiff * scaleRatio);\n\tvec2 currTangent = normalize(currDiff * scaleRatio);\n\tvec2 nextTangent = normalize(nextDiff * scaleRatio);\n\n\tvec2 prevNormal = vec2(-prevTangent.y, prevTangent.x);\n\tvec2 currNormal = vec2(-currTangent.y, currTangent.x);\n\tvec2 nextNormal = vec2(-nextTangent.y, nextTangent.x);\n\n\tvec2 startJoinDirection = normalize(prevTangent - currTangent);\n\tvec2 endJoinDirection = normalize(currTangent - nextTangent);\n\n\t// collapsed/unidirectional segment cases\n\t// FIXME: there should be more elegant solution\n\tvec2 prevTanDiff = abs(prevTangent - currTangent);\n\tvec2 nextTanDiff = abs(nextTangent - currTangent);\n\tif (max(prevTanDiff.x, prevTanDiff.y) < MIN_DIFF) {\n\t\tstartJoinDirection = currNormal;\n\t}\n\tif (max(nextTanDiff.x, nextTanDiff.y) < MIN_DIFF) {\n\t\tendJoinDirection = currNormal;\n\t}\n\tif (aCoord == bCoord) {\n\t\tendJoinDirection = startJoinDirection;\n\t\tcurrNormal = prevNormal;\n\t\tcurrTangent = prevTangent;\n\t}\n\n\ttangent = currTangent;\n\n\t//calculate join shifts relative to normals\n\tfloat startJoinShift = dot(currNormal, startJoinDirection);\n\tfloat endJoinShift = dot(currNormal, endJoinDirection);\n\n\tfloat startMiterRatio = abs(1. / startJoinShift);\n\tfloat endMiterRatio = abs(1. / endJoinShift);\n\n\tvec2 startJoin = startJoinDirection * startMiterRatio;\n\tvec2 endJoin = endJoinDirection * endMiterRatio;\n\n\tvec2 startTopJoin, startBotJoin, endTopJoin, endBotJoin;\n\tstartTopJoin = sign(startJoinShift) * startJoin * .5;\n\tstartBotJoin = -startTopJoin;\n\n\tendTopJoin = sign(endJoinShift) * endJoin * .5;\n\tendBotJoin = -endTopJoin;\n\n\tvec2 aTopCoord = aCoord + normalWidth * startTopJoin;\n\tvec2 bTopCoord = bCoord + normalWidth * endTopJoin;\n\tvec2 aBotCoord = aCoord + normalWidth * startBotJoin;\n\tvec2 bBotCoord = bCoord + normalWidth * endBotJoin;\n\n\t//miter anti-clipping\n\tfloat baClipping = distToLine(bCoord, aCoord, aBotCoord) / dot(normalize(normalWidth * endBotJoin), normalize(normalWidth.yx * vec2(-startBotJoin.y, startBotJoin.x)));\n\tfloat abClipping = distToLine(aCoord, bCoord, bTopCoord) / dot(normalize(normalWidth * startBotJoin), normalize(normalWidth.yx * vec2(-endBotJoin.y, endBotJoin.x)));\n\n\t//prevent close to reverse direction switch\n\tbool prevReverse = dot(currTangent, prevTangent) <= REVERSE_THRESHOLD && abs(dot(currTangent, prevNormal)) * min(length(prevDiff), length(currDiff)) < length(normalWidth * currNormal);\n\tbool nextReverse = dot(currTangent, nextTangent) <= REVERSE_THRESHOLD && abs(dot(currTangent, nextNormal)) * min(length(nextDiff), length(currDiff)) < length(normalWidth * currNormal);\n\n\tif (prevReverse) {\n\t\t//make join rectangular\n\t\tvec2 miterShift = normalWidth * startJoinDirection * miterLimit * .5;\n\t\tfloat normalAdjust = 1. - min(miterLimit / startMiterRatio, 1.);\n\t\taBotCoord = aCoord + miterShift - normalAdjust * normalWidth * currNormal * .5;\n\t\taTopCoord = aCoord + miterShift + normalAdjust * normalWidth * currNormal * .5;\n\t}\n\telse if (!nextReverse && baClipping > 0. && baClipping < length(normalWidth * endBotJoin)) {\n\t\t//handle miter clipping\n\t\tbTopCoord -= normalWidth * endTopJoin;\n\t\tbTopCoord += normalize(endTopJoin * normalWidth) * baClipping;\n\t}\n\n\tif (nextReverse) {\n\t\t//make join rectangular\n\t\tvec2 miterShift = normalWidth * endJoinDirection * miterLimit * .5;\n\t\tfloat normalAdjust = 1. - min(miterLimit / endMiterRatio, 1.);\n\t\tbBotCoord = bCoord + miterShift - normalAdjust * normalWidth * currNormal * .5;\n\t\tbTopCoord = bCoord + miterShift + normalAdjust * normalWidth * currNormal * .5;\n\t}\n\telse if (!prevReverse && abClipping > 0. && abClipping < length(normalWidth * startBotJoin)) {\n\t\t//handle miter clipping\n\t\taBotCoord -= normalWidth * startBotJoin;\n\t\taBotCoord += normalize(startBotJoin * normalWidth) * abClipping;\n\t}\n\n\tvec2 aTopPosition = (aTopCoord) * adjustedScale + translate;\n\tvec2 aBotPosition = (aBotCoord) * adjustedScale + translate;\n\n\tvec2 bTopPosition = (bTopCoord) * adjustedScale + translate;\n\tvec2 bBotPosition = (bBotCoord) * adjustedScale + translate;\n\n\t//position is normalized 0..1 coord on the screen\n\tvec2 position = (aTopPosition * lineTop + aBotPosition * lineBot) * lineStart + (bTopPosition * lineTop + bBotPosition * lineBot) * lineEnd;\n\n\tstartCoord = aCoord * scaleRatio + translate * viewport.zw + viewport.xy;\n\tendCoord = bCoord * scaleRatio + translate * viewport.zw + viewport.xy;\n\n\tgl_Position = vec4(position * 2.0 - 1.0, depth, 1);\n\n\tenableStartMiter = step(dot(currTangent, prevTangent), .5);\n\tenableEndMiter = step(dot(currTangent, nextTangent), .5);\n\n\t//bevel miter cutoffs\n\tif (miterMode == 1.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tvec2 startMiterWidth = vec2(startJoinDirection) * thickness * miterLimit * .5;\n\t\t\tstartCutoff = vec4(aCoord, aCoord);\n\t\t\tstartCutoff.zw += vec2(-startJoinDirection.y, startJoinDirection.x) / scaleRatio;\n\t\t\tstartCutoff = startCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tstartCutoff += viewport.xyxy;\n\t\t\tstartCutoff += startMiterWidth.xyxy;\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tvec2 endMiterWidth = vec2(endJoinDirection) * thickness * miterLimit * .5;\n\t\t\tendCutoff = vec4(bCoord, bCoord);\n\t\t\tendCutoff.zw += vec2(-endJoinDirection.y, endJoinDirection.x) / scaleRatio;\n\t\t\tendCutoff = endCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tendCutoff += viewport.xyxy;\n\t\t\tendCutoff += endMiterWidth.xyxy;\n\t\t}\n\t}\n\n\t//round miter cutoffs\n\telse if (miterMode == 2.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tvec2 startMiterWidth = vec2(startJoinDirection) * thickness * abs(dot(startJoinDirection, currNormal)) * .5;\n\t\t\tstartCutoff = vec4(aCoord, aCoord);\n\t\t\tstartCutoff.zw += vec2(-startJoinDirection.y, startJoinDirection.x) / scaleRatio;\n\t\t\tstartCutoff = startCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tstartCutoff += viewport.xyxy;\n\t\t\tstartCutoff += startMiterWidth.xyxy;\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tvec2 endMiterWidth = vec2(endJoinDirection) * thickness * abs(dot(endJoinDirection, currNormal)) * .5;\n\t\t\tendCutoff = vec4(bCoord, bCoord);\n\t\t\tendCutoff.zw += vec2(-endJoinDirection.y, endJoinDirection.x) / scaleRatio;\n\t\t\tendCutoff = endCutoff * scaleRatio.xyxy + translate.xyxy * viewport.zwzw;\n\t\t\tendCutoff += viewport.xyxy;\n\t\t\tendCutoff += endMiterWidth.xyxy;\n\t\t}\n\t}\n}\n"]), - frag: glslify(["precision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D dashPattern;\nuniform float dashSize, pixelRatio, thickness, opacity, id, miterMode;\n\nvarying vec4 fragColor;\nvarying vec2 tangent;\nvarying vec4 startCutoff, endCutoff;\nvarying vec2 startCoord, endCoord;\nvarying float enableStartMiter, enableEndMiter;\n\nfloat distToLine(vec2 p, vec2 a, vec2 b) {\n\tvec2 diff = b - a;\n\tvec2 perp = normalize(vec2(-diff.y, diff.x));\n\treturn dot(p - a, perp);\n}\n\nvoid main() {\n\tfloat alpha = 1., distToStart, distToEnd;\n\tfloat cutoff = thickness * .5;\n\n\t//bevel miter\n\tif (miterMode == 1.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tdistToStart = distToLine(gl_FragCoord.xy, startCutoff.xy, startCutoff.zw);\n\t\t\tif (distToStart < -1.) {\n\t\t\t\tdiscard;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\talpha *= min(max(distToStart + 1., 0.), 1.);\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tdistToEnd = distToLine(gl_FragCoord.xy, endCutoff.xy, endCutoff.zw);\n\t\t\tif (distToEnd < -1.) {\n\t\t\t\tdiscard;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\talpha *= min(max(distToEnd + 1., 0.), 1.);\n\t\t}\n\t}\n\n\t// round miter\n\telse if (miterMode == 2.) {\n\t\tif (enableStartMiter == 1.) {\n\t\t\tdistToStart = distToLine(gl_FragCoord.xy, startCutoff.xy, startCutoff.zw);\n\t\t\tif (distToStart < 0.) {\n\t\t\t\tfloat radius = length(gl_FragCoord.xy - startCoord);\n\n\t\t\t\tif(radius > cutoff + .5) {\n\t\t\t\t\tdiscard;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\talpha -= smoothstep(cutoff - .5, cutoff + .5, radius);\n\t\t\t}\n\t\t}\n\n\t\tif (enableEndMiter == 1.) {\n\t\t\tdistToEnd = distToLine(gl_FragCoord.xy, endCutoff.xy, endCutoff.zw);\n\t\t\tif (distToEnd < 0.) {\n\t\t\t\tfloat radius = length(gl_FragCoord.xy - endCoord);\n\n\t\t\t\tif(radius > cutoff + .5) {\n\t\t\t\t\tdiscard;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\talpha -= smoothstep(cutoff - .5, cutoff + .5, radius);\n\t\t\t}\n\t\t}\n\t}\n\n\tfloat t = fract(dot(tangent, gl_FragCoord.xy) / dashSize) * .5 + .25;\n\tfloat dash = texture2D(dashPattern, vec2(t, .5)).r;\n\n\tgl_FragColor = fragColor;\n\tgl_FragColor.a *= alpha * opacity * dash;\n}\n"]), - - attributes: { - // is line end - lineEnd: { - buffer: offsetBuffer, - divisor: 0, - stride: 8, - offset: 0 - }, - // is line top - lineTop: { - buffer: offsetBuffer, - divisor: 0, - stride: 8, - offset: 4 - }, - // left color - aColor: { - buffer: regl.prop('colorBuffer'), - stride: 4, - offset: 0, - divisor: 1 - }, - // right color - bColor: { - buffer: regl.prop('colorBuffer'), - stride: 4, - offset: 4, - divisor: 1 - }, - prevCoord: { - buffer: regl.prop('positionBuffer'), - stride: 8, - offset: 0, - divisor: 1 - }, - aCoord: { - buffer: regl.prop('positionBuffer'), - stride: 8, - offset: 8, - divisor: 1 - }, - bCoord: { - buffer: regl.prop('positionBuffer'), - stride: 8, - offset: 16, - divisor: 1 - }, - nextCoord: { - buffer: regl.prop('positionBuffer'), - stride: 8, - offset: 24, - divisor: 1 - } - } - }, shaderOptions)) - } catch (e) { - // IE/bad Webkit fallback - drawMiterLine = drawRectLine - } - - // fill shader - var drawFill = regl({ - primitive: 'triangle', - elements: function (ctx, prop) { return prop.triangles; }, - offset: 0, - - vert: glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec2 position, positionFract;\n\nuniform vec4 color;\nuniform vec2 scale, scaleFract, translate, translateFract;\nuniform float pixelRatio, id;\nuniform vec4 viewport;\nuniform float opacity;\n\nvarying vec4 fragColor;\n\nconst float MAX_LINES = 256.;\n\nvoid main() {\n\tfloat depth = (MAX_LINES - 4. - id) / (MAX_LINES);\n\n\tvec2 position = position * scale + translate\n + positionFract * scale + translateFract\n + position * scaleFract\n + positionFract * scaleFract;\n\n\tgl_Position = vec4(position * 2.0 - 1.0, depth, 1);\n\n\tfragColor = color / 255.;\n\tfragColor.a *= opacity;\n}\n"]), - frag: glslify(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor;\n\nvoid main() {\n\tgl_FragColor = fragColor;\n}\n"]), - - uniforms: { - scale: regl.prop('scale'), - color: regl.prop('fill'), - scaleFract: regl.prop('scaleFract'), - translateFract: regl.prop('translateFract'), - translate: regl.prop('translate'), - opacity: regl.prop('opacity'), - pixelRatio: regl.context('pixelRatio'), - id: regl.prop('id'), - viewport: function (ctx, prop) { return [prop.viewport.x, prop.viewport.y, ctx.viewportWidth, ctx.viewportHeight]; } - }, - - attributes: { - position: { - buffer: regl.prop('positionBuffer'), - stride: 8, - offset: 8 - }, - positionFract: { - buffer: regl.prop('positionFractBuffer'), - stride: 8, - offset: 8 - } - }, - - blend: shaderOptions.blend, - - depth: { enable: false }, - scissor: shaderOptions.scissor, - stencil: shaderOptions.stencil, - viewport: shaderOptions.viewport - }) - - return { - fill: drawFill, rect: drawRectLine, miter: drawMiterLine - } -} - - -// used to for new lines instances -Line2D.defaults = { - dashes: null, - join: 'miter', - miterLimit: 1, - thickness: 10, - cap: 'square', - color: 'black', - opacity: 1, - overlay: false, - viewport: null, - range: null, - close: false, - fill: null -} - - -Line2D.prototype.render = function () { - var ref; - - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - if (args.length) { - (ref = this).update.apply(ref, args) - } - - this.draw() -} - - -Line2D.prototype.draw = function () { - var this$1 = this; - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - // render multiple polylines via regl batch - (args.length ? args : this.passes).forEach(function (s, i) { - var ref; - - // render array pass as a list of passes - if (s && Array.isArray(s)) { return (ref = this$1).draw.apply(ref, s) } - - if (typeof s === 'number') { s = this$1.passes[s] } - - if (!(s && s.count > 1 && s.opacity)) { return } - - this$1.regl._refresh() - - if (s.fill && s.triangles && s.triangles.length > 2) { - this$1.shaders.fill(s) - } - - if (!s.thickness) { return } - - // high scale is only available for rect mode with precision - if (s.scale[0] * s.viewport.width > Line2D.precisionThreshold || s.scale[1] * s.viewport.height > Line2D.precisionThreshold) { - this$1.shaders.rect(s) - } - - // thin this.passes or too many points are rendered as simplified rect shader - else if (s.join === 'rect' || (!s.join && (s.thickness <= 2 || s.count >= Line2D.maxPoints))) { - this$1.shaders.rect(s) - } - else { - this$1.shaders.miter(s) - } - }) - - return this -} - -Line2D.prototype.update = function (options) { - var this$1 = this; - - if (!options) { return } - - if (options.length != null) { - if (typeof options[0] === 'number') { options = [{positions: options}] } - } - - // make options a batch - else if (!Array.isArray(options)) { options = [options] } - - var ref = this; - var regl = ref.regl; - var gl = ref.gl; - - // process per-line settings - options.forEach(function (o, i) { - var state = this$1.passes[i] - - if (o === undefined) { return } - - // null-argument removes pass - if (o === null) { - this$1.passes[i] = null - return - } - - if (typeof o[0] === 'number') { o = {positions: o} } - - // handle aliases - o = pick(o, { - positions: 'positions points data coords', - thickness: 'thickness lineWidth lineWidths line-width linewidth width stroke-width strokewidth strokeWidth', - join: 'lineJoin linejoin join type mode', - miterLimit: 'miterlimit miterLimit', - dashes: 'dash dashes dasharray dash-array dashArray', - color: 'color colour stroke colors colours stroke-color strokeColor', - fill: 'fill fill-color fillColor', - opacity: 'alpha opacity', - overlay: 'overlay crease overlap intersect', - close: 'closed close closed-path closePath', - range: 'range dataBox', - viewport: 'viewport viewBox', - hole: 'holes hole hollow' - }) - - // init state - if (!state) { - this$1.passes[i] = state = { - id: i, - scale: null, - scaleFract: null, - translate: null, - translateFract: null, - count: 0, - hole: [], - depth: 0, - - dashLength: 1, - dashTexture: regl.texture({ - channels: 1, - data: new Uint8Array([255]), - width: 1, - height: 1, - mag: 'linear', - min: 'linear' - }), - - colorBuffer: regl.buffer({ - usage: 'dynamic', - type: 'uint8', - data: new Uint8Array() - }), - positionBuffer: regl.buffer({ - usage: 'dynamic', - type: 'float', - data: new Uint8Array() - }), - positionFractBuffer: regl.buffer({ - usage: 'dynamic', - type: 'float', - data: new Uint8Array() - }) - } - - o = extend({}, Line2D.defaults, o) - } - if (o.thickness != null) { state.thickness = parseFloat(o.thickness) } - if (o.opacity != null) { state.opacity = parseFloat(o.opacity) } - if (o.miterLimit != null) { state.miterLimit = parseFloat(o.miterLimit) } - if (o.overlay != null) { - state.overlay = !!o.overlay - if (i < Line2D.maxLines) { - state.depth = 2 * (Line2D.maxLines - 1 - i % Line2D.maxLines) / Line2D.maxLines - 1.; - } - } - if (o.join != null) { state.join = o.join } - if (o.hole != null) { state.hole = o.hole } - if (o.fill != null) { state.fill = !o.fill ? null : rgba(o.fill, 'uint8') } - if (o.viewport != null) { state.viewport = parseRect(o.viewport) } - - if (!state.viewport) { - state.viewport = parseRect([ - gl.drawingBufferWidth, - gl.drawingBufferHeight - ]) - } - - if (o.close != null) { state.close = o.close } - - // reset positions - if (o.positions === null) { o.positions = [] } - if (o.positions) { - var positions, count - - // if positions are an object with x/y - if (o.positions.x && o.positions.y) { - var xPos = o.positions.x - var yPos = o.positions.y - count = state.count = Math.max( - xPos.length, - yPos.length - ) - positions = new Float64Array(count * 2) - for (var i$1 = 0; i$1 < count; i$1++) { - positions[i$1 * 2] = xPos[i$1] - positions[i$1 * 2 + 1] = yPos[i$1] - } - } - else { - positions = flatten(o.positions, 'float64') - count = state.count = Math.floor(positions.length / 2) - } - - var bounds = state.bounds = getBounds(positions, 2) - - // create fill positions - // FIXME: fill positions can be set only along with positions - if (state.fill) { - var pos = [] - - // filter bad vertices and remap triangles to ensure shape - var ids = {} - var lastId = 0 - - for (var i$2 = 0, ptr = 0, l = state.count; i$2 < l; i$2++) { - var x = positions[i$2*2] - var y = positions[i$2*2 + 1] - if (isNaN(x) || isNaN(y) || x == null || y == null) { - x = positions[lastId*2] - y = positions[lastId*2 + 1] - ids[i$2] = lastId - } - else { - lastId = i$2 - } - pos[ptr++] = x - pos[ptr++] = y - } - - var triangles = triangulate(pos, state.hole || []) - - for (var i$3 = 0, l$1 = triangles.length; i$3 < l$1; i$3++) { - if (ids[triangles[i$3]] != null) { triangles[i$3] = ids[triangles[i$3]] } - } - - state.triangles = triangles - } - - // update position buffers - var npos = new Float64Array(positions) - normalize(npos, 2, bounds) - - var positionData = new Float64Array(count * 2 + 6) - - // rotate first segment join - if (state.close) { - if (positions[0] === positions[count*2 - 2] && - positions[1] === positions[count*2 - 1]) { - positionData[0] = npos[count*2 - 4] - positionData[1] = npos[count*2 - 3] - } - else { - positionData[0] = npos[count*2 - 2] - positionData[1] = npos[count*2 - 1] - } - } - else { - positionData[0] = npos[0] - positionData[1] = npos[1] - } - - positionData.set(npos, 2) - - // add last segment - if (state.close) { - // ignore coinciding start/end - if (positions[0] === positions[count*2 - 2] && - positions[1] === positions[count*2 - 1]) { - positionData[count*2 + 2] = npos[2] - positionData[count*2 + 3] = npos[3] - state.count -= 1 - } - else { - positionData[count*2 + 2] = npos[0] - positionData[count*2 + 3] = npos[1] - positionData[count*2 + 4] = npos[2] - positionData[count*2 + 5] = npos[3] - } - } - // add stub - else { - positionData[count*2 + 2] = npos[count*2 - 2] - positionData[count*2 + 3] = npos[count*2 - 1] - positionData[count*2 + 4] = npos[count*2 - 2] - positionData[count*2 + 5] = npos[count*2 - 1] - } - - state.positionBuffer(float32(positionData)) - state.positionFractBuffer(fract32(positionData)) - } - - if (o.range) { - state.range = o.range - } else if (!state.range) { - state.range = state.bounds - } - - if ((o.range || o.positions) && state.count) { - var bounds$1 = state.bounds - - var boundsW = bounds$1[2] - bounds$1[0], - boundsH = bounds$1[3] - bounds$1[1] - - var rangeW = state.range[2] - state.range[0], - rangeH = state.range[3] - state.range[1] - - state.scale = [ - boundsW / rangeW, - boundsH / rangeH - ] - state.translate = [ - -state.range[0] / rangeW + bounds$1[0] / rangeW || 0, - -state.range[1] / rangeH + bounds$1[1] / rangeH || 0 - ] - - state.scaleFract = fract32(state.scale) - state.translateFract = fract32(state.translate) - } - - if (o.dashes) { - var dashLength = 0., dashData - - if (!o.dashes || o.dashes.length < 2) { - dashLength = 1. - dashData = new Uint8Array([255, 255, 255, 255, 255, 255, 255, 255]) - } - - else { - dashLength = 0.; - for(var i$4 = 0; i$4 < o.dashes.length; ++i$4) { - dashLength += o.dashes[i$4] - } - dashData = new Uint8Array(dashLength * Line2D.dashMult) - var ptr$1 = 0 - var fillColor = 255 - - // repeat texture two times to provide smooth 0-step - for (var k = 0; k < 2; k++) { - for(var i$5 = 0; i$5 < o.dashes.length; ++i$5) { - for(var j = 0, l$2 = o.dashes[i$5] * Line2D.dashMult * .5; j < l$2; ++j) { - dashData[ptr$1++] = fillColor - } - fillColor ^= 255 - } - } - } - - state.dashLength = dashLength - state.dashTexture({ - channels: 1, - data: dashData, - width: dashData.length, - height: 1, - mag: 'linear', - min: 'linear' - }, 0, 0) - } - - if (o.color) { - var count$1 = state.count - var colors = o.color - - if (!colors) { colors = 'transparent' } - - var colorData = new Uint8Array(count$1 * 4 + 4) - - // convert colors to typed arrays - if (!Array.isArray(colors) || typeof colors[0] === 'number') { - var c = rgba(colors, 'uint8') - - for (var i$6 = 0; i$6 < count$1 + 1; i$6++) { - colorData.set(c, i$6 * 4) - } - } else { - for (var i$7 = 0; i$7 < count$1; i$7++) { - var c$1 = rgba(colors[i$7], 'uint8') - colorData.set(c$1, i$7 * 4) - } - colorData.set(rgba(colors[0], 'uint8'), count$1 * 4) - } - - state.colorBuffer({ - usage: 'dynamic', - type: 'uint8', - data: colorData - }) - } - }) - - // remove unmentioned passes - if (options.length < this.passes.length) { - for (var i = options.length; i < this.passes.length; i++) { - var pass = this$1.passes[i] - if (!pass) { continue } - pass.colorBuffer.destroy() - pass.positionBuffer.destroy() - pass.dashTexture.destroy() - } - this.passes.length = options.length - } - - // remove null items - var passes = [] - for (var i$1 = 0; i$1 < this.passes.length; i$1++) { - if (this$1.passes[i$1] !== null) { passes.push(this$1.passes[i$1]) } - } - this.passes = passes - - return this -} - -Line2D.prototype.destroy = function () { - this.passes.forEach(function (pass) { - pass.colorBuffer.destroy() - pass.positionBuffer.destroy() - pass.dashTexture.destroy() - }) - - this.passes.length = 0 - - return this -} - -},{"array-bounds":65,"array-normalize":66,"color-normalize":120,"earcut":492,"es6-weak-map":493,"flatten-vertex-data":227,"glslify":409,"object-assign":454,"parse-rect":459,"pick-by-alias":465,"to-float32":538}],492:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = earcut; -module.exports.default = earcut; - -function earcut(data, holeIndices, dim) { - - dim = dim || 2; - - var hasHoles = holeIndices && holeIndices.length, - outerLen = hasHoles ? holeIndices[0] * dim : data.length, - outerNode = linkedList(data, 0, outerLen, dim, true), - triangles = []; - - if (!outerNode || outerNode.next === outerNode.prev) return triangles; - - var minX, minY, maxX, maxY, x, y, invSize; - - if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); - - // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox - if (data.length > 80 * dim) { - minX = maxX = data[0]; - minY = maxY = data[1]; - - for (var i = dim; i < outerLen; i += dim) { - x = data[i]; - y = data[i + 1]; - if (x < minX) minX = x; - if (y < minY) minY = y; - if (x > maxX) maxX = x; - if (y > maxY) maxY = y; - } - - // minX, minY and invSize are later used to transform coords into integers for z-order calculation - invSize = Math.max(maxX - minX, maxY - minY); - invSize = invSize !== 0 ? 1 / invSize : 0; - } - - earcutLinked(outerNode, triangles, dim, minX, minY, invSize); - - return triangles; -} - -// create a circular doubly linked list from polygon points in the specified winding order -function linkedList(data, start, end, dim, clockwise) { - var i, last; - - if (clockwise === (signedArea(data, start, end, dim) > 0)) { - for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); - } else { - for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); - } - - if (last && equals(last, last.next)) { - removeNode(last); - last = last.next; - } - - return last; -} - -// eliminate colinear or duplicate points -function filterPoints(start, end) { - if (!start) return start; - if (!end) end = start; - - var p = start, - again; - do { - again = false; - - if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { - removeNode(p); - p = end = p.prev; - if (p === p.next) break; - again = true; - - } else { - p = p.next; - } - } while (again || p !== end); - - return end; -} - -// main ear slicing loop which triangulates a polygon (given as a linked list) -function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) { - if (!ear) return; - - // interlink polygon nodes in z-order - if (!pass && invSize) indexCurve(ear, minX, minY, invSize); - - var stop = ear, - prev, next; - - // iterate through ears, slicing them one by one - while (ear.prev !== ear.next) { - prev = ear.prev; - next = ear.next; - - if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) { - // cut off the triangle - triangles.push(prev.i / dim); - triangles.push(ear.i / dim); - triangles.push(next.i / dim); - - removeNode(ear); - - // skipping the next vertex leads to less sliver triangles - ear = next.next; - stop = next.next; - - continue; - } - - ear = next; - - // if we looped through the whole remaining polygon and can't find any more ears - if (ear === stop) { - // try filtering points and slicing again - if (!pass) { - earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1); - - // if this didn't work, try curing all small self-intersections locally - } else if (pass === 1) { - ear = cureLocalIntersections(ear, triangles, dim); - earcutLinked(ear, triangles, dim, minX, minY, invSize, 2); - - // as a last resort, try splitting the remaining polygon into two - } else if (pass === 2) { - splitEarcut(ear, triangles, dim, minX, minY, invSize); - } - - break; - } - } -} - -// check whether a polygon node forms a valid ear with adjacent nodes -function isEar(ear) { - var a = ear.prev, - b = ear, - c = ear.next; - - if (area(a, b, c) >= 0) return false; // reflex, can't be an ear - - // now make sure we don't have other points inside the potential ear - var p = ear.next.next; - - while (p !== ear.prev) { - if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && - area(p.prev, p, p.next) >= 0) return false; - p = p.next; - } - - return true; -} - -function isEarHashed(ear, minX, minY, invSize) { - var a = ear.prev, - b = ear, - c = ear.next; - - if (area(a, b, c) >= 0) return false; // reflex, can't be an ear - - // triangle bbox; min & max are calculated like this for speed - var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x), - minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y), - maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x), - maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y); - - // z-order range for the current triangle bbox; - var minZ = zOrder(minTX, minTY, minX, minY, invSize), - maxZ = zOrder(maxTX, maxTY, minX, minY, invSize); - - var p = ear.prevZ, - n = ear.nextZ; - - // look for points inside the triangle in both directions - while (p && p.z >= minZ && n && n.z <= maxZ) { - if (p !== ear.prev && p !== ear.next && - pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && - area(p.prev, p, p.next) >= 0) return false; - p = p.prevZ; - - if (n !== ear.prev && n !== ear.next && - pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && - area(n.prev, n, n.next) >= 0) return false; - n = n.nextZ; - } - - // look for remaining points in decreasing z-order - while (p && p.z >= minZ) { - if (p !== ear.prev && p !== ear.next && - pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && - area(p.prev, p, p.next) >= 0) return false; - p = p.prevZ; - } - - // look for remaining points in increasing z-order - while (n && n.z <= maxZ) { - if (n !== ear.prev && n !== ear.next && - pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && - area(n.prev, n, n.next) >= 0) return false; - n = n.nextZ; - } - - return true; -} - -// go through all polygon nodes and cure small local self-intersections -function cureLocalIntersections(start, triangles, dim) { - var p = start; - do { - var a = p.prev, - b = p.next.next; - - if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { - - triangles.push(a.i / dim); - triangles.push(p.i / dim); - triangles.push(b.i / dim); - - // remove two nodes involved - removeNode(p); - removeNode(p.next); - - p = start = b; - } - p = p.next; - } while (p !== start); - - return p; -} - -// try splitting polygon into two and triangulate them independently -function splitEarcut(start, triangles, dim, minX, minY, invSize) { - // look for a valid diagonal that divides the polygon into two - var a = start; - do { - var b = a.next.next; - while (b !== a.prev) { - if (a.i !== b.i && isValidDiagonal(a, b)) { - // split the polygon in two by the diagonal - var c = splitPolygon(a, b); - - // filter colinear points around the cuts - a = filterPoints(a, a.next); - c = filterPoints(c, c.next); - - // run earcut on each half - earcutLinked(a, triangles, dim, minX, minY, invSize); - earcutLinked(c, triangles, dim, minX, minY, invSize); - return; - } - b = b.next; - } - a = a.next; - } while (a !== start); -} - -// link every hole into the outer loop, producing a single-ring polygon without holes -function eliminateHoles(data, holeIndices, outerNode, dim) { - var queue = [], - i, len, start, end, list; - - for (i = 0, len = holeIndices.length; i < len; i++) { - start = holeIndices[i] * dim; - end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; - list = linkedList(data, start, end, dim, false); - if (list === list.next) list.steiner = true; - queue.push(getLeftmost(list)); - } - - queue.sort(compareX); - - // process holes from left to right - for (i = 0; i < queue.length; i++) { - eliminateHole(queue[i], outerNode); - outerNode = filterPoints(outerNode, outerNode.next); - } - - return outerNode; -} - -function compareX(a, b) { - return a.x - b.x; -} - -// find a bridge between vertices that connects hole with an outer ring and and link it -function eliminateHole(hole, outerNode) { - outerNode = findHoleBridge(hole, outerNode); - if (outerNode) { - var b = splitPolygon(outerNode, hole); - filterPoints(b, b.next); - } -} - -// David Eberly's algorithm for finding a bridge between hole and outer polygon -function findHoleBridge(hole, outerNode) { - var p = outerNode, - hx = hole.x, - hy = hole.y, - qx = -Infinity, - m; - - // find a segment intersected by a ray from the hole's leftmost point to the left; - // segment's endpoint with lesser x will be potential connection point - do { - if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) { - var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); - if (x <= hx && x > qx) { - qx = x; - if (x === hx) { - if (hy === p.y) return p; - if (hy === p.next.y) return p.next; - } - m = p.x < p.next.x ? p : p.next; - } - } - p = p.next; - } while (p !== outerNode); - - if (!m) return null; - - if (hx === qx) return m.prev; // hole touches outer segment; pick lower endpoint - - // look for points inside the triangle of hole point, segment intersection and endpoint; - // if there are no points found, we have a valid connection; - // otherwise choose the point of the minimum angle with the ray as connection point - - var stop = m, - mx = m.x, - my = m.y, - tanMin = Infinity, - tan; - - p = m.next; - - while (p !== stop) { - if (hx >= p.x && p.x >= mx && hx !== p.x && - pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) { - - tan = Math.abs(hy - p.y) / (hx - p.x); // tangential - - if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) { - m = p; - tanMin = tan; - } - } - - p = p.next; - } - - return m; -} - -// interlink polygon nodes in z-order -function indexCurve(start, minX, minY, invSize) { - var p = start; - do { - if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, invSize); - p.prevZ = p.prev; - p.nextZ = p.next; - p = p.next; - } while (p !== start); - - p.prevZ.nextZ = null; - p.prevZ = null; - - sortLinked(p); -} - -// Simon Tatham's linked list merge sort algorithm -// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html -function sortLinked(list) { - var i, p, q, e, tail, numMerges, pSize, qSize, - inSize = 1; - - do { - p = list; - list = null; - tail = null; - numMerges = 0; - - while (p) { - numMerges++; - q = p; - pSize = 0; - for (i = 0; i < inSize; i++) { - pSize++; - q = q.nextZ; - if (!q) break; - } - qSize = inSize; - - while (pSize > 0 || (qSize > 0 && q)) { - - if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) { - e = p; - p = p.nextZ; - pSize--; - } else { - e = q; - q = q.nextZ; - qSize--; - } - - if (tail) tail.nextZ = e; - else list = e; - - e.prevZ = tail; - tail = e; - } - - p = q; - } - - tail.nextZ = null; - inSize *= 2; - - } while (numMerges > 1); - - return list; -} - -// z-order of a point given coords and inverse of the longer side of data bbox -function zOrder(x, y, minX, minY, invSize) { - // coords are transformed into non-negative 15-bit integer range - x = 32767 * (x - minX) * invSize; - y = 32767 * (y - minY) * invSize; - - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -// find the leftmost node of a polygon ring -function getLeftmost(start) { - var p = start, - leftmost = start; - do { - if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p; - p = p.next; - } while (p !== start); - - return leftmost; -} - -// check if a point lies within a convex triangle -function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { - return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && - (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && - (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; -} - -// check if a diagonal between two polygon nodes is valid (lies in polygon interior) -function isValidDiagonal(a, b) { - return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && - locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b); -} - -// signed area of a triangle -function area(p, q, r) { - return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); -} - -// check if two points are equal -function equals(p1, p2) { - return p1.x === p2.x && p1.y === p2.y; -} - -// check if two segments intersect -function intersects(p1, q1, p2, q2) { - if ((equals(p1, q1) && equals(p2, q2)) || - (equals(p1, q2) && equals(p2, q1))) return true; - return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && - area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0; -} - -// check if a polygon diagonal intersects any polygon segments -function intersectsPolygon(a, b) { - var p = a; - do { - if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && - intersects(p, p.next, a, b)) return true; - p = p.next; - } while (p !== a); - - return false; -} - -// check if a polygon diagonal is locally inside the polygon -function locallyInside(a, b) { - return area(a.prev, a, a.next) < 0 ? - area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : - area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; -} - -// check if the middle point of a polygon diagonal is inside the polygon -function middleInside(a, b) { - var p = a, - inside = false, - px = (a.x + b.x) / 2, - py = (a.y + b.y) / 2; - do { - if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y && - (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) - inside = !inside; - p = p.next; - } while (p !== a); - - return inside; -} - -// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; -// if one belongs to the outer ring and another to a hole, it merges it into a single ring -function splitPolygon(a, b) { - var a2 = new Node(a.i, a.x, a.y), - b2 = new Node(b.i, b.x, b.y), - an = a.next, - bp = b.prev; - - a.next = b; - b.prev = a; - - a2.next = an; - an.prev = a2; - - b2.next = a2; - a2.prev = b2; - - bp.next = b2; - b2.prev = bp; - - return b2; -} - -// create a node and optionally link it with previous one (in a circular doubly linked list) -function insertNode(i, x, y, last) { - var p = new Node(i, x, y); - - if (!last) { - p.prev = p; - p.next = p; - - } else { - p.next = last.next; - p.prev = last; - last.next.prev = p; - last.next = p; - } - return p; -} - -function removeNode(p) { - p.next.prev = p.prev; - p.prev.next = p.next; - - if (p.prevZ) p.prevZ.nextZ = p.nextZ; - if (p.nextZ) p.nextZ.prevZ = p.prevZ; -} - -function Node(i, x, y) { - // vertex index in coordinates array - this.i = i; - - // vertex coordinates - this.x = x; - this.y = y; - - // previous and next vertex nodes in a polygon ring - this.prev = null; - this.next = null; - - // z-order curve value - this.z = null; - - // previous and next nodes in z-order - this.prevZ = null; - this.nextZ = null; - - // indicates whether this is a steiner point - this.steiner = false; -} - -// return a percentage difference between the polygon area and its triangulation area; -// used to verify correctness of triangulation -earcut.deviation = function (data, holeIndices, dim, triangles) { - var hasHoles = holeIndices && holeIndices.length; - var outerLen = hasHoles ? holeIndices[0] * dim : data.length; - - var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim)); - if (hasHoles) { - for (var i = 0, len = holeIndices.length; i < len; i++) { - var start = holeIndices[i] * dim; - var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; - polygonArea -= Math.abs(signedArea(data, start, end, dim)); - } - } - - var trianglesArea = 0; - for (i = 0; i < triangles.length; i += 3) { - var a = triangles[i] * dim; - var b = triangles[i + 1] * dim; - var c = triangles[i + 2] * dim; - trianglesArea += Math.abs( - (data[a] - data[c]) * (data[b + 1] - data[a + 1]) - - (data[a] - data[b]) * (data[c + 1] - data[a + 1])); - } - - return polygonArea === 0 && trianglesArea === 0 ? 0 : - Math.abs((trianglesArea - polygonArea) / polygonArea); -}; - -function signedArea(data, start, end, dim) { - var sum = 0; - for (var i = start, j = end - dim; i < end; i += dim) { - sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); - j = i; - } - return sum; -} - -// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts -earcut.flatten = function (data) { - var dim = data[0][0].length, - result = {vertices: [], holes: [], dimensions: dim}, - holeIndex = 0; - - for (var i = 0; i < data.length; i++) { - for (var j = 0; j < data[i].length; j++) { - for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]); - } - if (i > 0) { - holeIndex += data[i - 1].length; - result.holes.push(holeIndex); - } - } - return result; -}; - -},{}],493:[function(_dereq_,module,exports){ -arguments[4][318][0].apply(exports,arguments) -},{"./is-implemented":494,"./polyfill":496,"dup":318}],494:[function(_dereq_,module,exports){ -arguments[4][319][0].apply(exports,arguments) -},{"dup":319}],495:[function(_dereq_,module,exports){ -arguments[4][320][0].apply(exports,arguments) -},{"dup":320}],496:[function(_dereq_,module,exports){ -arguments[4][321][0].apply(exports,arguments) -},{"./is-native-implemented":495,"d":151,"dup":321,"es5-ext/object/is-value":194,"es5-ext/object/set-prototype-of":200,"es5-ext/object/valid-object":204,"es5-ext/object/valid-value":205,"es5-ext/string/random-uniq":210,"es6-iterator/for-of":212,"es6-iterator/get":213,"es6-symbol":219}],497:[function(_dereq_,module,exports){ -'use strict'; - -function _slicedToArray(arr, i) { - return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); -} - -function _toConsumableArray(arr) { - return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); -} - -function _arrayWithoutHoles(arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; - - return arr2; - } -} - -function _arrayWithHoles(arr) { - if (Array.isArray(arr)) return arr; -} - -function _iterableToArray(iter) { - if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); -} - -function _iterableToArrayLimit(arr, i) { - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; - } - } - - return _arr; -} - -function _nonIterableSpread() { - throw new TypeError("Invalid attempt to spread non-iterable instance"); -} - -function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); -} - -var rgba = _dereq_('color-normalize'); - -var getBounds = _dereq_('array-bounds'); - -var colorId = _dereq_('color-id'); - -var cluster = _dereq_('point-cluster'); - -var extend = _dereq_('object-assign'); - -var glslify = _dereq_('glslify'); - -var pick = _dereq_('pick-by-alias'); - -var updateDiff = _dereq_('update-diff'); - -var flatten = _dereq_('flatten-vertex-data'); - -var ie = _dereq_('is-iexplorer'); - -var f32 = _dereq_('to-float32'); - -var parseRect = _dereq_('parse-rect'); - -var scatter = Scatter; - -function Scatter(regl, options) { - var _this = this; - - if (!(this instanceof Scatter)) return new Scatter(regl, options); - - if (typeof regl === 'function') { - if (!options) options = {}; - options.regl = regl; - } else { - options = regl; - regl = null; - } - - if (options && options.length) options.positions = options; - regl = options.regl; // persistent variables - - var gl = regl._gl, - paletteTexture, - palette = [], - paletteIds = {}, - // state - groups = [], - // textures for marker keys - markerTextures = [null], - markerCache = [null]; - var maxColors = 255, - maxSize = 100; // direct color buffer mode - // IE does not support palette anyways - - this.tooManyColors = ie; // texture with color palette - - paletteTexture = regl.texture({ - data: new Uint8Array(maxColors * 4), - width: maxColors, - height: 1, - type: 'uint8', - format: 'rgba', - wrapS: 'clamp', - wrapT: 'clamp', - mag: 'nearest', - min: 'nearest' - }); - extend(this, { - regl: regl, - gl: gl, - groups: groups, - markerCache: markerCache, - markerTextures: markerTextures, - palette: palette, - paletteIds: paletteIds, - paletteTexture: paletteTexture, - maxColors: maxColors, - maxSize: maxSize, - canvas: gl.canvas - }); - this.update(options); // common shader options - - var shaderOptions = { - uniforms: { - pixelRatio: regl.context('pixelRatio'), - palette: paletteTexture, - paletteSize: function paletteSize(ctx, prop) { - return [_this.tooManyColors ? 0 : maxColors, paletteTexture.height]; - }, - scale: regl.prop('scale'), - scaleFract: regl.prop('scaleFract'), - translate: regl.prop('translate'), - translateFract: regl.prop('translateFract'), - opacity: regl.prop('opacity'), - marker: regl.prop('markerTexture') - }, - attributes: { - // FIXME: optimize these parts - x: function x(ctx, prop) { - return prop.xAttr || { - buffer: prop.positionBuffer, - stride: 8, - offset: 0 - }; - }, - y: function y(ctx, prop) { - return prop.yAttr || { - buffer: prop.positionBuffer, - stride: 8, - offset: 4 - }; - }, - xFract: function xFract(ctx, prop) { - return prop.xAttr ? { - constant: [0, 0] - } : { - buffer: prop.positionFractBuffer, - stride: 8, - offset: 0 - }; - }, - yFract: function yFract(ctx, prop) { - return prop.yAttr ? { - constant: [0, 0] - } : { - buffer: prop.positionFractBuffer, - stride: 8, - offset: 4 - }; - }, - size: function size(ctx, prop) { - return prop.size.length ? { - buffer: prop.sizeBuffer, - stride: 2, - offset: 0 - } : { - constant: [Math.round(prop.size * 255 / _this.maxSize)] - }; - }, - borderSize: function borderSize(ctx, prop) { - return prop.borderSize.length ? { - buffer: prop.sizeBuffer, - stride: 2, - offset: 1 - } : { - constant: [Math.round(prop.borderSize * 255 / _this.maxSize)] - }; - }, - colorId: function colorId(ctx, prop) { - return prop.color.length ? { - buffer: prop.colorBuffer, - stride: _this.tooManyColors ? 8 : 4, - offset: 0 - } : { - constant: _this.tooManyColors ? palette.slice(prop.color * 4, prop.color * 4 + 4) : [prop.color] - }; - }, - borderColorId: function borderColorId(ctx, prop) { - return prop.borderColor.length ? { - buffer: prop.colorBuffer, - stride: _this.tooManyColors ? 8 : 4, - offset: _this.tooManyColors ? 4 : 2 - } : { - constant: _this.tooManyColors ? palette.slice(prop.borderColor * 4, prop.borderColor * 4 + 4) : [prop.borderColor] - }; - }, - isActive: function isActive(ctx, prop) { - return prop.activation === true ? { - constant: [1] - } : prop.activation ? prop.activation : { - constant: [0] - }; - } - }, - blend: { - enable: true, - color: [0, 0, 0, 1], - // photoshop blending - func: { - srcRGB: 'src alpha', - dstRGB: 'one minus src alpha', - srcAlpha: 'one minus dst alpha', - dstAlpha: 'one' - } - }, - scissor: { - enable: true, - box: regl.prop('viewport') - }, - viewport: regl.prop('viewport'), - stencil: { - enable: false - }, - depth: { - enable: false - }, - elements: regl.prop('elements'), - count: regl.prop('count'), - offset: regl.prop('offset'), - primitive: 'points' // draw sdf-marker - - }; - var markerOptions = extend({}, shaderOptions); - markerOptions.frag = glslify(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor, fragBorderColor;\nvarying float fragWidth, fragBorderColorLevel, fragColorLevel;\n\nuniform sampler2D marker;\nuniform float pixelRatio, opacity;\n\nfloat smoothStep(float x, float y) {\n return 1.0 / (1.0 + exp(50.0*(x - y)));\n}\n\nvoid main() {\n float dist = texture2D(marker, gl_PointCoord).r, delta = fragWidth;\n\n // max-distance alpha\n if (dist < 0.003) discard;\n\n // null-border case\n if (fragBorderColorLevel == fragColorLevel || fragBorderColor.a == 0.) {\n float colorAmt = smoothstep(.5 - delta, .5 + delta, dist);\n gl_FragColor = vec4(fragColor.rgb, colorAmt * fragColor.a * opacity);\n }\n else {\n float borderColorAmt = smoothstep(fragBorderColorLevel - delta, fragBorderColorLevel + delta, dist);\n float colorAmt = smoothstep(fragColorLevel - delta, fragColorLevel + delta, dist);\n\n vec4 color = fragBorderColor;\n color.a *= borderColorAmt;\n color = mix(color, fragColor, colorAmt);\n color.a *= opacity;\n\n gl_FragColor = color;\n }\n\n}\n"]); - markerOptions.vert = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute float x, y, xFract, yFract;\nattribute float size, borderSize;\nattribute vec4 colorId, borderColorId;\nattribute float isActive;\n\nuniform vec2 scale, scaleFract, translate, translateFract, paletteSize;\nuniform float pixelRatio;\nuniform sampler2D palette;\n\nconst float maxSize = 100.;\nconst float borderLevel = .5;\n\nvarying vec4 fragColor, fragBorderColor;\nvarying float fragPointSize, fragBorderRadius, fragWidth, fragBorderColorLevel, fragColorLevel;\n\nbool isDirect = (paletteSize.x < 1.);\n\nvec4 getColor(vec4 id) {\n return isDirect ? id / 255. : texture2D(palette,\n vec2(\n (id.x + .5) / paletteSize.x,\n (id.y + .5) / paletteSize.y\n )\n );\n}\n\nvoid main() {\n if (isActive == 0.) return;\n\n vec2 position = vec2(x, y);\n vec2 positionFract = vec2(xFract, yFract);\n\n vec4 color = getColor(colorId);\n vec4 borderColor = getColor(borderColorId);\n\n float size = size * maxSize / 255.;\n float borderSize = borderSize * maxSize / 255.;\n\n gl_PointSize = 2. * size * pixelRatio;\n fragPointSize = size * pixelRatio;\n\n vec2 pos = (position + translate) * scale\n + (positionFract + translateFract) * scale\n + (position + translate) * scaleFract\n + (positionFract + translateFract) * scaleFract;\n\n gl_Position = vec4(pos * 2. - 1., 0, 1);\n\n fragColor = color;\n fragBorderColor = borderColor;\n fragWidth = 1. / gl_PointSize;\n\n fragBorderColorLevel = clamp(borderLevel - borderLevel * borderSize / size, 0., 1.);\n fragColorLevel = clamp(borderLevel + (1. - borderLevel) * borderSize / size, 0., 1.);\n}"]); - this.drawMarker = regl(markerOptions); // draw circle - - var circleOptions = extend({}, shaderOptions); - circleOptions.frag = glslify(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor, fragBorderColor;\n\nuniform float opacity;\nvarying float fragBorderRadius, fragWidth;\n\nfloat smoothStep(float edge0, float edge1, float x) {\n\tfloat t;\n\tt = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);\n\treturn t * t * (3.0 - 2.0 * t);\n}\n\nvoid main() {\n\tfloat radius, alpha = 1.0, delta = fragWidth;\n\n\tradius = length(2.0 * gl_PointCoord.xy - 1.0);\n\n\tif (radius > 1.0 + delta) {\n\t\tdiscard;\n\t}\n\n\talpha -= smoothstep(1.0 - delta, 1.0 + delta, radius);\n\n\tfloat borderRadius = fragBorderRadius;\n\tfloat ratio = smoothstep(borderRadius - delta, borderRadius + delta, radius);\n\tvec4 color = mix(fragColor, fragBorderColor, ratio);\n\tcolor.a *= alpha * opacity;\n\tgl_FragColor = color;\n}\n"]); - circleOptions.vert = glslify(["precision highp float;\n#define GLSLIFY 1\n\nattribute float x, y, xFract, yFract;\nattribute float size, borderSize;\nattribute vec4 colorId, borderColorId;\nattribute float isActive;\n\nuniform vec2 scale, scaleFract, translate, translateFract;\nuniform float pixelRatio;\nuniform sampler2D palette;\nuniform vec2 paletteSize;\n\nconst float maxSize = 100.;\n\nvarying vec4 fragColor, fragBorderColor;\nvarying float fragBorderRadius, fragWidth;\n\nbool isDirect = (paletteSize.x < 1.);\n\nvec4 getColor(vec4 id) {\n return isDirect ? id / 255. : texture2D(palette,\n vec2(\n (id.x + .5) / paletteSize.x,\n (id.y + .5) / paletteSize.y\n )\n );\n}\n\nvoid main() {\n // ignore inactive points\n if (isActive == 0.) return;\n\n vec2 position = vec2(x, y);\n vec2 positionFract = vec2(xFract, yFract);\n\n vec4 color = getColor(colorId);\n vec4 borderColor = getColor(borderColorId);\n\n float size = size * maxSize / 255.;\n float borderSize = borderSize * maxSize / 255.;\n\n gl_PointSize = (size + borderSize) * pixelRatio;\n\n vec2 pos = (position + translate) * scale\n + (positionFract + translateFract) * scale\n + (position + translate) * scaleFract\n + (positionFract + translateFract) * scaleFract;\n\n gl_Position = vec4(pos * 2. - 1., 0, 1);\n\n fragBorderRadius = 1. - 2. * borderSize / (size + borderSize);\n fragColor = color;\n fragBorderColor = borderColor.a == 0. || borderSize == 0. ? vec4(color.rgb, 0.) : borderColor;\n fragWidth = 1. / gl_PointSize;\n}\n"]); // polyfill IE - - if (ie) { - circleOptions.frag = circleOptions.frag.replace('smoothstep', 'smoothStep'); - markerOptions.frag = markerOptions.frag.replace('smoothstep', 'smoothStep'); - } - - this.drawCircle = regl(circleOptions); -} // single pass defaults - - -Scatter.defaults = { - color: 'black', - borderColor: 'transparent', - borderSize: 0, - size: 12, - opacity: 1, - marker: undefined, - viewport: null, - range: null, - pixelSize: null, - count: 0, - offset: 0, - bounds: null, - positions: [], - snap: 1e4 // update & redraw - -}; - -Scatter.prototype.render = function () { - if (arguments.length) { - this.update.apply(this, arguments); - } - - this.draw(); - return this; -}; // draw all groups or only indicated ones - - -Scatter.prototype.draw = function () { - var _this2 = this; - - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - var groups = this.groups; // if directly array passed - treat as passes - - if (args.length === 1 && Array.isArray(args[0]) && (args[0][0] === null || Array.isArray(args[0][0]))) { - args = args[0]; - } // FIXME: remove once https://github.com/regl-project/regl/issues/474 resolved - - - this.regl._refresh(); - - if (args.length) { - for (var i = 0; i < args.length; i++) { - this.drawItem(i, args[i]); - } - } // draw all passes - else { - groups.forEach(function (group, i) { - _this2.drawItem(i); - }); - } - - return this; -}; // draw specific scatter group - - -Scatter.prototype.drawItem = function (id, els) { - var groups = this.groups; - var group = groups[id]; // debug viewport - // let { viewport } = group - // gl.enable(gl.SCISSOR_TEST); - // gl.scissor(viewport.x, viewport.y, viewport.width, viewport.height); - // gl.clearColor(0, 0, 0, .5); - // gl.clear(gl.COLOR_BUFFER_BIT); - - if (typeof els === 'number') { - id = els; - group = groups[els]; - els = null; - } - - if (!(group && group.count && group.opacity)) return; // draw circles - - if (group.activation[0]) { - // TODO: optimize this performance by making groups and regl.this props - this.drawCircle(this.getMarkerDrawOptions(0, group, els)); - } // draw all other available markers - - - var batch = []; - - for (var i = 1; i < group.activation.length; i++) { - if (!group.activation[i] || group.activation[i] !== true && !group.activation[i].data.length) continue; - batch.push.apply(batch, _toConsumableArray(this.getMarkerDrawOptions(i, group, els))); - } - - if (batch.length) { - this.drawMarker(batch); - } -}; // get options for the marker ids - - -Scatter.prototype.getMarkerDrawOptions = function (markerId, group, elements) { - var range = group.range, - tree = group.tree, - viewport = group.viewport, - activation = group.activation, - selectionBuffer = group.selectionBuffer, - count = group.count; - var regl = this.regl; // direct points - - if (!tree) { - // if elements array - draw unclustered points - if (elements) { - return [extend({}, group, { - markerTexture: this.markerTextures[markerId], - activation: activation[markerId], - count: elements.length, - elements: elements, - offset: 0 - })]; - } - - return [extend({}, group, { - markerTexture: this.markerTextures[markerId], - activation: activation[markerId], - offset: 0 - })]; - } // clustered points - - - var batch = []; - var lod = tree.range(range, { - lod: true, - px: [(range[2] - range[0]) / viewport.width, (range[3] - range[1]) / viewport.height] - }); // enable elements by using selection buffer - - if (elements) { - var markerActivation = activation[markerId]; - var mask = markerActivation.data; - var data = new Uint8Array(count); - - for (var i = 0; i < elements.length; i++) { - var id = elements[i]; - data[id] = mask ? mask[id] : 1; - } - - selectionBuffer.subdata(data); - } - - for (var l = lod.length; l--;) { - var _lod$l = _slicedToArray(lod[l], 2), - from = _lod$l[0], - to = _lod$l[1]; - - batch.push(extend({}, group, { - markerTexture: this.markerTextures[markerId], - activation: elements ? selectionBuffer : activation[markerId], - offset: from, - count: to - from - })); - } - - return batch; -}; // update groups options - - -Scatter.prototype.update = function () { - var _this3 = this; - - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - if (!args.length) return; // passes are as single array - - if (args.length === 1 && Array.isArray(args[0])) args = args[0]; - var groups = this.groups, - gl = this.gl, - regl = this.regl, - maxSize = this.maxSize, - maxColors = this.maxColors, - palette = this.palette; - this.groups = groups = args.map(function (options, i) { - var group = groups[i]; - if (options === undefined) return group; - if (options === null) options = { - positions: null - };else if (typeof options === 'function') options = { - ondraw: options - };else if (typeof options[0] === 'number') options = { - positions: options // copy options to avoid mutation & handle aliases - - }; - options = pick(options, { - positions: 'positions data points', - snap: 'snap cluster lod tree', - size: 'sizes size radius', - borderSize: 'borderSizes borderSize border-size bordersize borderWidth borderWidths border-width borderwidth stroke-width strokeWidth strokewidth outline', - color: 'colors color fill fill-color fillColor', - borderColor: 'borderColors borderColor stroke stroke-color strokeColor', - marker: 'markers marker shape', - range: 'range dataBox databox', - viewport: 'viewport viewPort viewBox viewbox', - opacity: 'opacity alpha transparency', - bounds: 'bound bounds boundaries limits', - tooManyColors: 'tooManyColors palette paletteMode optimizePalette enablePalette' - }); - if (options.positions === null) options.positions = []; - if (options.tooManyColors != null) _this3.tooManyColors = options.tooManyColors; - - if (!group) { - groups[i] = group = { - id: i, - scale: null, - translate: null, - scaleFract: null, - translateFract: null, - // buffers for active markers - activation: [], - // buffer for filtered markers - selectionBuffer: regl.buffer({ - data: new Uint8Array(0), - usage: 'stream', - type: 'uint8' - }), - // buffers with data: it is faster to switch them per-pass - // than provide one congregate buffer - sizeBuffer: regl.buffer({ - data: new Uint8Array(0), - usage: 'dynamic', - type: 'uint8' - }), - colorBuffer: regl.buffer({ - data: new Uint8Array(0), - usage: 'dynamic', - type: 'uint8' - }), - positionBuffer: regl.buffer({ - data: new Uint8Array(0), - usage: 'dynamic', - type: 'float' - }), - positionFractBuffer: regl.buffer({ - data: new Uint8Array(0), - usage: 'dynamic', - type: 'float' - }) - }; - options = extend({}, Scatter.defaults, options); - } // force update triggers - - - if (options.positions && !('marker' in options)) { - options.marker = group.marker; - delete group.marker; - } // updating markers cause recalculating snapping - - - if (options.marker && !('positions' in options)) { - options.positions = group.positions; - delete group.positions; - } // global count of points - - - var hasSize = 0, - hasColor = 0; - updateDiff(group, options, [{ - snap: true, - size: function size(s, group) { - if (s == null) s = Scatter.defaults.size; - hasSize += s && s.length ? 1 : 0; - return s; - }, - borderSize: function borderSize(s, group) { - if (s == null) s = Scatter.defaults.borderSize; - hasSize += s && s.length ? 1 : 0; - return s; - }, - opacity: parseFloat, - // add colors to palette, save references - color: function color(c, group) { - if (c == null) c = Scatter.defaults.color; - c = _this3.updateColor(c); - hasColor++; - return c; - }, - borderColor: function borderColor(c, group) { - if (c == null) c = Scatter.defaults.borderColor; - c = _this3.updateColor(c); - hasColor++; - return c; - }, - bounds: function bounds(_bounds, group, options) { - if (!('range' in options)) options.range = null; - return _bounds; - }, - positions: function positions(_positions, group, options) { - var snap = group.snap; - var positionBuffer = group.positionBuffer, - positionFractBuffer = group.positionFractBuffer, - selectionBuffer = group.selectionBuffer; // separate buffers for x/y coordinates - - if (_positions.x || _positions.y) { - if (_positions.x.length) { - group.xAttr = { - buffer: regl.buffer(_positions.x), - offset: 0, - stride: 4, - count: _positions.x.length - }; - } else { - group.xAttr = { - buffer: _positions.x.buffer, - offset: _positions.x.offset * 4 || 0, - stride: (_positions.x.stride || 1) * 4, - count: _positions.x.count - }; - } - - if (_positions.y.length) { - group.yAttr = { - buffer: regl.buffer(_positions.y), - offset: 0, - stride: 4, - count: _positions.y.length - }; - } else { - group.yAttr = { - buffer: _positions.y.buffer, - offset: _positions.y.offset * 4 || 0, - stride: (_positions.y.stride || 1) * 4, - count: _positions.y.count - }; - } - - group.count = Math.max(group.xAttr.count, group.yAttr.count); - return _positions; - } - - _positions = flatten(_positions, 'float64'); - var count = group.count = Math.floor(_positions.length / 2); - var bounds = group.bounds = count ? getBounds(_positions, 2) : null; // if range is not provided updated - recalc it - - if (!options.range && !group.range) { - delete group.range; - options.range = bounds; - } // reset marker - - - if (!options.marker && !group.marker) { - delete group.marker; - options.marker = null; - } // build cluster tree if required - - - if (snap && (snap === true || count > snap)) { - group.tree = cluster(_positions, { - bounds: bounds - }); - } // existing tree instance - else if (snap && snap.length) { - group.tree = snap; - } - - if (group.tree) { - var opts = { - primitive: 'points', - usage: 'static', - data: group.tree, - type: 'uint32' - }; - if (group.elements) group.elements(opts);else group.elements = regl.elements(opts); - } // update position buffers - - - positionBuffer({ - data: f32.float(_positions), - usage: 'dynamic' - }); - positionFractBuffer({ - data: f32.fract(_positions), - usage: 'dynamic' - }); // expand selectionBuffer - - selectionBuffer({ - data: new Uint8Array(count), - type: 'uint8', - usage: 'stream' - }); - return _positions; - } - }, { - // create marker ids corresponding to known marker textures - marker: function marker(markers, group, options) { - var activation = group.activation; // reset marker elements - - activation.forEach(function (buffer) { - return buffer && buffer.destroy && buffer.destroy(); - }); - activation.length = 0; // single sdf marker - - if (!markers || typeof markers[0] === 'number') { - var id = _this3.addMarker(markers); - - activation[id] = true; - } // per-point markers use mask buffers to enable markers in vert shader - else { - var markerMasks = []; - - for (var _i = 0, l = Math.min(markers.length, group.count); _i < l; _i++) { - var _id = _this3.addMarker(markers[_i]); - - if (!markerMasks[_id]) markerMasks[_id] = new Uint8Array(group.count); // enable marker by default - - markerMasks[_id][_i] = 1; - } - - for (var _id2 = 0; _id2 < markerMasks.length; _id2++) { - if (!markerMasks[_id2]) continue; - var opts = { - data: markerMasks[_id2], - type: 'uint8', - usage: 'static' - }; - - if (!activation[_id2]) { - activation[_id2] = regl.buffer(opts); - } else { - activation[_id2](opts); - } - - activation[_id2].data = markerMasks[_id2]; - } - } - - return markers; - }, - range: function range(_range, group, options) { - var bounds = group.bounds; // FIXME: why do we need this? - - if (!bounds) return; - if (!_range) _range = bounds; - group.scale = [1 / (_range[2] - _range[0]), 1 / (_range[3] - _range[1])]; - group.translate = [-_range[0], -_range[1]]; - group.scaleFract = f32.fract(group.scale); - group.translateFract = f32.fract(group.translate); - return _range; - }, - viewport: function viewport(vp) { - var rect = parseRect(vp || [gl.drawingBufferWidth, gl.drawingBufferHeight]); // normalize viewport to the canvas coordinates - // rect.y = gl.drawingBufferHeight - rect.height - rect.y - - return rect; - } - }]); // update size buffer, if needed - - if (hasSize) { - var _group = group, - count = _group.count, - size = _group.size, - borderSize = _group.borderSize, - sizeBuffer = _group.sizeBuffer; - var sizes = new Uint8Array(count * 2); - - if (size.length || borderSize.length) { - for (var _i2 = 0; _i2 < count; _i2++) { - // we downscale size to allow for fractions - sizes[_i2 * 2] = Math.round((size[_i2] == null ? size : size[_i2]) * 255 / maxSize); - sizes[_i2 * 2 + 1] = Math.round((borderSize[_i2] == null ? borderSize : borderSize[_i2]) * 255 / maxSize); - } - } - - sizeBuffer({ - data: sizes, - usage: 'dynamic' - }); - } // update color buffer if needed - - - if (hasColor) { - var _group2 = group, - _count = _group2.count, - color = _group2.color, - borderColor = _group2.borderColor, - colorBuffer = _group2.colorBuffer; - var colors; // if too many colors - put colors to buffer directly - - if (_this3.tooManyColors) { - if (color.length || borderColor.length) { - colors = new Uint8Array(_count * 8); - - for (var _i3 = 0; _i3 < _count; _i3++) { - var _colorId = color[_i3]; - colors[_i3 * 8] = palette[_colorId * 4]; - colors[_i3 * 8 + 1] = palette[_colorId * 4 + 1]; - colors[_i3 * 8 + 2] = palette[_colorId * 4 + 2]; - colors[_i3 * 8 + 3] = palette[_colorId * 4 + 3]; - var borderColorId = borderColor[_i3]; - colors[_i3 * 8 + 4] = palette[borderColorId * 4]; - colors[_i3 * 8 + 5] = palette[borderColorId * 4 + 1]; - colors[_i3 * 8 + 6] = palette[borderColorId * 4 + 2]; - colors[_i3 * 8 + 7] = palette[borderColorId * 4 + 3]; - } - } - } // if limited amount of colors - keep palette color picking - // that saves significant memory - else { - if (color.length || borderColor.length) { - // we need slight data increase by 2 due to vec4 borderId in shader - colors = new Uint8Array(_count * 4 + 2); - - for (var _i4 = 0; _i4 < _count; _i4++) { - // put color coords in palette texture - if (color[_i4] != null) { - colors[_i4 * 4] = color[_i4] % maxColors; - colors[_i4 * 4 + 1] = Math.floor(color[_i4] / maxColors); - } - - if (borderColor[_i4] != null) { - colors[_i4 * 4 + 2] = borderColor[_i4] % maxColors; - colors[_i4 * 4 + 3] = Math.floor(borderColor[_i4] / maxColors); - } - } - } - } - - colorBuffer({ - data: colors || new Uint8Array(0), - type: 'uint8', - usage: 'dynamic' - }); - } - - return group; - }); -}; // get (and create) marker texture id - - -Scatter.prototype.addMarker = function (sdf) { - var markerTextures = this.markerTextures, - regl = this.regl, - markerCache = this.markerCache; - var pos = sdf == null ? 0 : markerCache.indexOf(sdf); - if (pos >= 0) return pos; // convert sdf to 0..255 range - - var distArr; - - if (sdf instanceof Uint8Array || sdf instanceof Uint8ClampedArray) { - distArr = sdf; - } else { - distArr = new Uint8Array(sdf.length); - - for (var i = 0, l = sdf.length; i < l; i++) { - distArr[i] = sdf[i] * 255; - } - } - - var radius = Math.floor(Math.sqrt(distArr.length)); - pos = markerTextures.length; - markerCache.push(sdf); - markerTextures.push(regl.texture({ - channels: 1, - data: distArr, - radius: radius, - mag: 'linear', - min: 'linear' - })); - return pos; -}; // register color to palette, return it's index or list of indexes - - -Scatter.prototype.updateColor = function (colors) { - var paletteIds = this.paletteIds, - palette = this.palette, - maxColors = this.maxColors; - - if (!Array.isArray(colors)) { - colors = [colors]; - } - - var idx = []; // if color groups - flatten them - - if (typeof colors[0] === 'number') { - var grouped = []; - - if (Array.isArray(colors)) { - for (var i = 0; i < colors.length; i += 4) { - grouped.push(colors.slice(i, i + 4)); - } - } else { - for (var _i5 = 0; _i5 < colors.length; _i5 += 4) { - grouped.push(colors.subarray(_i5, _i5 + 4)); - } - } - - colors = grouped; - } - - for (var _i6 = 0; _i6 < colors.length; _i6++) { - var color = colors[_i6]; - color = rgba(color, 'uint8'); - var id = colorId(color, false); // if new color - save it - - if (paletteIds[id] == null) { - var pos = palette.length; - paletteIds[id] = Math.floor(pos / 4); - palette[pos] = color[0]; - palette[pos + 1] = color[1]; - palette[pos + 2] = color[2]; - palette[pos + 3] = color[3]; - } - - idx[_i6] = paletteIds[id]; - } // detect if too many colors in palette - - - if (!this.tooManyColors && palette.length > maxColors * 4) this.tooManyColors = true; // limit max color - - this.updatePalette(palette); // keep static index for single-color property - - return idx.length === 1 ? idx[0] : idx; -}; - -Scatter.prototype.updatePalette = function (palette) { - if (this.tooManyColors) return; - var maxColors = this.maxColors, - paletteTexture = this.paletteTexture; - var requiredHeight = Math.ceil(palette.length * .25 / maxColors); // pad data - - if (requiredHeight > 1) { - palette = palette.slice(); - - for (var i = palette.length * .25 % maxColors; i < requiredHeight * maxColors; i++) { - palette.push(0, 0, 0, 0); - } - } // ensure height - - - if (paletteTexture.height < requiredHeight) { - paletteTexture.resize(maxColors, requiredHeight); - } // update full data - - - paletteTexture.subimage({ - width: Math.min(palette.length * .25, maxColors), - height: requiredHeight, - data: palette - }, 0, 0); -}; // remove unused stuff - - -Scatter.prototype.destroy = function () { - this.groups.forEach(function (group) { - group.sizeBuffer.destroy(); - group.positionBuffer.destroy(); - group.positionFractBuffer.destroy(); - group.colorBuffer.destroy(); - group.activation.forEach(function (b) { - return b && b.destroy && b.destroy(); - }); - group.selectionBuffer.destroy(); - if (group.elements) group.elements.destroy(); - }); - this.groups.length = 0; - this.paletteTexture.destroy(); - this.markerTextures.forEach(function (txt) { - return txt && txt.destroy && txt.destroy(); - }); - return this; -}; - -var extend$1 = _dereq_('object-assign'); - -var reglScatter2d = function reglScatter2d(regl, options) { - var scatter$$1 = new scatter(regl, options); - var render = scatter$$1.render.bind(scatter$$1); // expose API - - extend$1(render, { - render: render, - update: scatter$$1.update.bind(scatter$$1), - draw: scatter$$1.draw.bind(scatter$$1), - destroy: scatter$$1.destroy.bind(scatter$$1), - regl: scatter$$1.regl, - gl: scatter$$1.gl, - canvas: scatter$$1.gl.canvas, - groups: scatter$$1.groups, - markers: scatter$$1.markerCache, - palette: scatter$$1.palette - }); - return render; -}; - -module.exports = reglScatter2d; - -},{"array-bounds":65,"color-id":118,"color-normalize":120,"flatten-vertex-data":227,"glslify":409,"is-iexplorer":419,"object-assign":454,"parse-rect":459,"pick-by-alias":465,"point-cluster":499,"to-float32":538,"update-diff":549}],498:[function(_dereq_,module,exports){ -arguments[4][111][0].apply(exports,arguments) -},{"dup":111}],499:[function(_dereq_,module,exports){ -'use strict' - -module.exports = _dereq_('./quad') -},{"./quad":500}],500:[function(_dereq_,module,exports){ -/** - * @module point-cluster/quad - * - * Bucket based quad tree clustering - */ - -'use strict' - -var search = _dereq_('binary-search-bounds') -var clamp = _dereq_('clamp') -var rect = _dereq_('parse-rect') -var getBounds = _dereq_('array-bounds') -var pick = _dereq_('pick-by-alias') -var defined = _dereq_('defined') -var flatten = _dereq_('flatten-vertex-data') -var isObj = _dereq_('is-obj') -var dtype = _dereq_('dtype') -var log2 = _dereq_('math-log2') - -var MAX_GROUP_ID = 1073741824 - -module.exports = function cluster (srcPoints, options) { - if (!options) { options = {} } - - srcPoints = flatten(srcPoints, 'float64') - - options = pick(options, { - bounds: 'range bounds dataBox databox', - maxDepth: 'depth maxDepth maxdepth level maxLevel maxlevel levels', - dtype: 'type dtype format out dst output destination' - // sort: 'sortBy sortby sort', - // pick: 'pick levelPoint', - // nodeSize: 'node nodeSize minNodeSize minSize size' - }) - - // let nodeSize = defined(options.nodeSize, 1) - var maxDepth = defined(options.maxDepth, 255) - var bounds = defined(options.bounds, getBounds(srcPoints, 2)) - if (bounds[0] === bounds[2]) { bounds[2]++ } - if (bounds[1] === bounds[3]) { bounds[3]++ } - - var points = normalize(srcPoints, bounds) - - // init variables - var n = srcPoints.length >>> 1 - var ids - if (!options.dtype) { options.dtype = 'array' } - - if (typeof options.dtype === 'string') { - ids = new (dtype(options.dtype))(n) - } - else if (options.dtype) { - ids = options.dtype - if (Array.isArray(ids)) { ids.length = n } - } - for (var i = 0; i < n; ++i) { - ids[i] = i - } - - // representative point indexes for levels - var levels = [] - - // starting indexes of subranges in sub levels, levels.length * 4 - var sublevels = [] - - // unique group ids, sorted in z-curve fashion within levels by shifting bits - var groups = [] - - // level offsets in `ids` - var offsets = [] - - - // sort points - sort(0, 0, 1, ids, 0, 1) - - - // return reordered ids with provided methods - // save level offsets in output buffer - var offset = 0 - for (var level = 0; level < levels.length; level++) { - var levelItems = levels[level] - if (ids.set) { ids.set(levelItems, offset) } - else { - for (var i$1 = 0, l = levelItems.length; i$1 < l; i$1++) { - ids[i$1 + offset] = levelItems[i$1] - } - } - var nextOffset = offset + levels[level].length - offsets[level] = [offset, nextOffset] - offset = nextOffset - } - - ids.range = range - - return ids - - - - // FIXME: it is possible to create one typed array heap and reuse that to avoid memory blow - function sort (x, y, diam, ids, level, group) { - if (!ids.length) { return null } - - // save first point as level representative - var levelItems = levels[level] || (levels[level] = []) - var levelGroups = groups[level] || (groups[level] = []) - var sublevel = sublevels[level] || (sublevels[level] = []) - var offset = levelItems.length - - level++ - - // max depth reached - put all items into a first group - // alternatively - if group id overflow - avoid proceeding - if (level > maxDepth || group > MAX_GROUP_ID) { - for (var i = 0; i < ids.length; i++) { - levelItems.push(ids[i]) - levelGroups.push(group) - sublevel.push(null, null, null, null) - } - - return offset - } - - levelItems.push(ids[0]) - levelGroups.push(group) - - if (ids.length <= 1) { - sublevel.push(null, null, null, null) - return offset - } - - - var d2 = diam * .5 - var cx = x + d2, cy = y + d2 - - // distribute points by 4 buckets - var lolo = [], lohi = [], hilo = [], hihi = [] - - for (var i$1 = 1, l = ids.length; i$1 < l; i$1++) { - var idx = ids[i$1], - x$1 = points[idx * 2], - y$1 = points[idx * 2 + 1] - x$1 < cx ? (y$1 < cy ? lolo.push(idx) : lohi.push(idx)) : (y$1 < cy ? hilo.push(idx) : hihi.push(idx)) - } - - group <<= 2 - - sublevel.push( - sort(x, y, d2, lolo, level, group), - sort(x, cy, d2, lohi, level, group + 1), - sort(cx, y, d2, hilo, level, group + 2), - sort(cx, cy, d2, hihi, level, group + 3) - ) - - return offset - } - - // get all points within the passed range - function range () { - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - var options - - if (isObj(args[args.length - 1])) { - var arg = args.pop() - - // detect if that was a rect object - if (!args.length && (arg.x != null || arg.l != null || arg.left != null)) { - args = [arg] - options = {} - } - - options = pick(arg, { - level: 'level maxLevel', - d: 'd diam diameter r radius px pxSize pixel pixelSize maxD size minSize', - lod: 'lod details ranges offsets' - }) - } - else { - options = {} - } - - if (!args.length) { args = bounds } - - var box = rect.apply( void 0, args ) - - var ref = [ - Math.min(box.x, box.x + box.width), - Math.min(box.y, box.y + box.height), - Math.max(box.x, box.x + box.width), - Math.max(box.y, box.y + box.height) - ]; - var minX = ref[0]; - var minY = ref[1]; - var maxX = ref[2]; - var maxY = ref[3]; - - var ref$1 = normalize([minX, minY, maxX, maxY], bounds ); - var nminX = ref$1[0]; - var nminY = ref$1[1]; - var nmaxX = ref$1[2]; - var nmaxY = ref$1[3]; - - var maxLevel = defined(options.level, levels.length) - - // limit maxLevel by px size - if (options.d != null) { - var d - if (typeof options.d === 'number') { d = [options.d, options.d] } - else if (options.d.length) { d = options.d } - - maxLevel = Math.min( - Math.max( - Math.ceil(-log2(Math.abs(d[0]) / (bounds[2] - bounds[0]))), - Math.ceil(-log2(Math.abs(d[1]) / (bounds[3] - bounds[1]))) - ), - maxLevel - ) - } - maxLevel = Math.min(maxLevel, levels.length) - - // return levels of details - if (options.lod) { - return lod(nminX, nminY, nmaxX, nmaxY, maxLevel) - } - - - - // do selection ids - var selection = [] - - // FIXME: probably we can do LOD here beforehead - select( 0, 0, 1, 0, 0, 1) - - function select ( lox, loy, d, level, from, to ) { - if (from === null || to === null) { return } - - var hix = lox + d - var hiy = loy + d - - // if box does not intersect level - ignore - if ( nminX > hix || nminY > hiy || nmaxX < lox || nmaxY < loy ) { return } - if ( level >= maxLevel ) { return } - if ( from === to ) { return } - - // if points fall into box range - take it - var levelItems = levels[level] - - if (to === undefined) { to = levelItems.length } - - for (var i = from; i < to; i++) { - var id = levelItems[i] - - var px = srcPoints[ id * 2 ] - var py = srcPoints[ id * 2 + 1 ] - - if ( px >= minX && px <= maxX && py >= minY && py <= maxY ) {selection.push(id) - } - } - - // for every subsection do select - var offsets = sublevels[ level ] - var off0 = offsets[ from * 4 + 0 ] - var off1 = offsets[ from * 4 + 1 ] - var off2 = offsets[ from * 4 + 2 ] - var off3 = offsets[ from * 4 + 3 ] - var end = nextOffset(offsets, from + 1) - - var d2 = d * .5 - var nextLevel = level + 1 - select( lox, loy, d2, nextLevel, off0, off1 || off2 || off3 || end) - select( lox, loy + d2, d2, nextLevel, off1, off2 || off3 || end) - select( lox + d2, loy, d2, nextLevel, off2, off3 || end) - select( lox + d2, loy + d2, d2, nextLevel, off3, end) - } - - function nextOffset(offsets, from) { - var offset = null, i = 0 - while(offset === null) { - offset = offsets[ from * 4 + i ] - i++ - if (i > offsets.length) { return null } - } - return offset - } - - return selection - } - - // get range offsets within levels to render lods appropriate for zoom level - // TODO: it is possible to store minSize of a point to optimize neede level calc - function lod (lox, loy, hix, hiy, maxLevel) { - var ranges = [] - - for (var level = 0; level < maxLevel; level++) { - var levelGroups = groups[level] - var from = offsets[level][0] - - var levelGroupStart = group(lox, loy, level) - var levelGroupEnd = group(hix, hiy, level) - - // FIXME: utilize sublevels to speed up search range here - var startOffset = search.ge(levelGroups, levelGroupStart) - var endOffset = search.gt(levelGroups, levelGroupEnd, startOffset, levelGroups.length - 1) - - ranges[level] = [startOffset + from, endOffset + from] - } - - return ranges - } - - // get group id closest to the x,y coordinate, corresponding to a level - function group (x, y, level) { - var group = 1 - - var cx = .5, cy = .5 - var diam = .5 - - for (var i = 0; i < level; i++) { - group <<= 2 - - group += x < cx ? (y < cy ? 0 : 1) : (y < cy ? 2 : 3) - - diam *= .5 - - cx += x < cx ? -diam : diam - cy += y < cy ? -diam : diam - } - - return group - } -} - - -// normalize points by bounds -function normalize (pts, bounds) { - var lox = bounds[0]; - var loy = bounds[1]; - var hix = bounds[2]; - var hiy = bounds[3]; - var scaleX = 1.0 / (hix - lox) - var scaleY = 1.0 / (hiy - loy) - var result = new Array(pts.length) - - for (var i = 0, n = pts.length / 2; i < n; i++) { - result[2*i] = clamp((pts[2*i] - lox) * scaleX, 0, 1) - result[2*i+1] = clamp((pts[2*i+1] - loy) * scaleY, 0, 1) - } - - return result -} -},{"array-bounds":65,"binary-search-bounds":498,"clamp":115,"defined":164,"dtype":169,"flatten-vertex-data":227,"is-obj":421,"math-log2":432,"parse-rect":459,"pick-by-alias":465}],501:[function(_dereq_,module,exports){ -'use strict' - - -var createScatter = _dereq_('regl-scatter2d') -var pick = _dereq_('pick-by-alias') -var getBounds = _dereq_('array-bounds') -var raf = _dereq_('raf') -var arrRange = _dereq_('array-range') -var rect = _dereq_('parse-rect') -var flatten = _dereq_('flatten-vertex-data') - - -module.exports = SPLOM - - -// @constructor -function SPLOM (regl, options) { - if (!(this instanceof SPLOM)) { return new SPLOM(regl, options) } - - // render passes - this.traces = [] - - // passes for scatter, combined across traces - this.passes = {} - - this.regl = regl - - // main scatter drawing instance - this.scatter = createScatter(regl) - - this.canvas = this.scatter.canvas -} - - -// update & draw passes once per frame -SPLOM.prototype.render = function () { - var this$1 = this; - var ref; - - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - if (args.length) { - (ref = this).update.apply(ref, args) - } - - if (this.regl.attributes.preserveDrawingBuffer) { return this.draw() } - - // make sure draw is not called more often than once a frame - if (this.dirty) { - if (this.planned == null) { - this.planned = raf(function () { - this$1.draw() - this$1.dirty = true - this$1.planned = null - }) - } - } - else { - this.draw() - this.dirty = true - raf(function () { - this$1.dirty = false - }) - } - - return this -} - - -// update passes -SPLOM.prototype.update = function () { - var this$1 = this; - var ref; - - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - if (!args.length) { return } - - for (var i = 0; i < args.length; i++) { - this$1.updateItem(i, args[i]) - } - - // remove nulled passes - this.traces = this.traces.filter(Boolean) - - // FIXME: update passes independently - var passes = [] - var offset = 0 - for (var i$1 = 0; i$1 < this.traces.length; i$1++) { - var trace = this$1.traces[i$1] - var tracePasses = this$1.traces[i$1].passes - for (var j = 0; j < tracePasses.length; j++) { - passes.push(this$1.passes[tracePasses[j]]) - } - // save offset of passes - trace.passOffset = offset - offset += trace.passes.length - } - - (ref = this.scatter).update.apply(ref, passes) - - return this -} - - -// update trace by index, not supposed to be called directly -SPLOM.prototype.updateItem = function (i, options) { - var this$1 = this; - - var ref = this; - var regl = ref.regl; - - // remove pass if null - if (options === null) { - this.traces[i] = null - return this - } - - if (!options) { return this } - - var o = pick(options, { - data: 'data items columns rows values dimensions samples x', - snap: 'snap cluster', - size: 'sizes size radius', - color: 'colors color fill fill-color fillColor', - opacity: 'opacity alpha transparency opaque', - borderSize: 'borderSizes borderSize border-size bordersize borderWidth borderWidths border-width borderwidth stroke-width strokeWidth strokewidth outline', - borderColor: 'borderColors borderColor bordercolor stroke stroke-color strokeColor', - marker: 'markers marker shape', - range: 'range ranges databox dataBox', - viewport: 'viewport viewBox viewbox', - domain: 'domain domains area areas', - padding: 'pad padding paddings pads margin margins', - transpose: 'transpose transposed', - diagonal: 'diagonal diag showDiagonal', - upper: 'upper up top upperhalf upperHalf showupperhalf showUpper showUpperHalf', - lower: 'lower low bottom lowerhalf lowerHalf showlowerhalf showLowerHalf showLower' - }) - - // we provide regl buffer per-trace, since trace data can be changed - var trace = (this.traces[i] || (this.traces[i] = { - id: i, - buffer: regl.buffer({ - usage: 'dynamic', - type: 'float', - data: new Uint8Array() - }), - color: 'black', - marker: null, - size: 12, - borderColor: 'transparent', - borderSize: 1, - viewport: rect([regl._gl.drawingBufferWidth, regl._gl.drawingBufferHeight]), - padding: [0, 0, 0, 0], - opacity: 1, - diagonal: true, - upper: true, - lower: true - })) - - - // save styles - if (o.color != null) { - trace.color = o.color - } - if (o.size != null) { - trace.size = o.size - } - if (o.marker != null) { - trace.marker = o.marker - } - if (o.borderColor != null) { - trace.borderColor = o.borderColor - } - if (o.borderSize != null) { - trace.borderSize = o.borderSize - } - if (o.opacity != null) { - trace.opacity = o.opacity - } - if (o.viewport) { - trace.viewport = rect(o.viewport) - } - if (o.diagonal != null) { trace.diagonal = o.diagonal } - if (o.upper != null) { trace.upper = o.upper } - if (o.lower != null) { trace.lower = o.lower } - - // put flattened data into buffer - if (o.data) { - trace.buffer(flatten(o.data)) - trace.columns = o.data.length - trace.count = o.data[0].length - - // detect bounds per-column - trace.bounds = [] - - for (var i$1 = 0; i$1 < trace.columns; i$1++) { - trace.bounds[i$1] = getBounds(o.data[i$1], 1) - } - } - - // add proper range updating markers - var multirange - if (o.range) { - trace.range = o.range - multirange = trace.range && typeof trace.range[0] !== 'number' - } - - if (o.domain) { - trace.domain = o.domain - } - var multipadding = false - if (o.padding != null) { - // multiple paddings - if (Array.isArray(o.padding) && o.padding.length === trace.columns && typeof o.padding[o.padding.length - 1] === 'number') { - trace.padding = o.padding.map(getPad) - multipadding = true - } - // single padding - else { - trace.padding = getPad(o.padding) - } - } - - // create passes - var m = trace.columns - var n = trace.count - - var w = trace.viewport.width - var h = trace.viewport.height - var left = trace.viewport.x - var top = trace.viewport.y - var iw = w / m - var ih = h / m - - trace.passes = [] - - for (var i$2 = 0; i$2 < m; i$2++) { - for (var j = 0; j < m; j++) { - if (!trace.diagonal && j === i$2) { continue } - if (!trace.upper && i$2 > j) { continue } - if (!trace.lower && i$2 < j) { continue } - - var key = passId(trace.id, i$2, j) - - var pass = this$1.passes[key] || (this$1.passes[key] = {}) - - if (o.data) { - if (o.transpose) { - pass.positions = { - x: {buffer: trace.buffer, offset: j, count: n, stride: m}, - y: {buffer: trace.buffer, offset: i$2, count: n, stride: m} - } - } - else { - pass.positions = { - x: {buffer: trace.buffer, offset: j * n, count: n}, - y: {buffer: trace.buffer, offset: i$2 * n, count: n} - } - } - - pass.bounds = getBox(trace.bounds, i$2, j) - } - - if (o.domain || o.viewport || o.data) { - var pad = multipadding ? getBox(trace.padding, i$2, j) : trace.padding - if (trace.domain) { - var ref$1 = getBox(trace.domain, i$2, j); - var lox = ref$1[0]; - var loy = ref$1[1]; - var hix = ref$1[2]; - var hiy = ref$1[3]; - - pass.viewport = [ - left + lox * w + pad[0], - top + loy * h + pad[1], - left + hix * w - pad[2], - top + hiy * h - pad[3] - ] - } - // consider auto-domain equipartial - else { - pass.viewport = [ - left + j * iw + iw * pad[0], - top + i$2 * ih + ih * pad[1], - left + (j + 1) * iw - iw * pad[2], - top + (i$2 + 1) * ih - ih * pad[3] - ] - } - } - - if (o.color) { pass.color = trace.color } - if (o.size) { pass.size = trace.size } - if (o.marker) { pass.marker = trace.marker } - if (o.borderSize) { pass.borderSize = trace.borderSize } - if (o.borderColor) { pass.borderColor = trace.borderColor } - if (o.opacity) { pass.opacity = trace.opacity } - - if (o.range) { - pass.range = multirange ? getBox(trace.range, i$2, j) : trace.range || pass.bounds - } - - trace.passes.push(key) - } - } - - return this -} - - -// draw all or passed passes -SPLOM.prototype.draw = function () { - var this$1 = this; - var ref$2; - - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - if (!args.length) { - this.scatter.draw() - } - else { - var idx = [] - for (var i = 0; i < args.length; i++) { - // draw(0, 2, 5) - draw traces - if (typeof args[i] === 'number' ) { - var ref = this$1.traces[args[i]]; - var passes = ref.passes; - var passOffset = ref.passOffset; - idx.push.apply(idx, arrRange(passOffset, passOffset + passes.length)) - } - // draw([0, 1, 2 ...], [3, 4, 5]) - draw points - else if (args[i].length) { - var els = args[i] - var ref$1 = this$1.traces[i]; - var passes$1 = ref$1.passes; - var passOffset$1 = ref$1.passOffset; - passes$1 = passes$1.map(function (passId, i) { - idx[passOffset$1 + i] = els - }) - } - } - (ref$2 = this.scatter).draw.apply(ref$2, idx) - } - - return this -} - - -// dispose resources -SPLOM.prototype.destroy = function () { - this.traces.forEach(function (trace) { - if (trace.buffer && trace.buffer.destroy) { trace.buffer.destroy() } - }) - this.traces = null - this.passes = null - - this.scatter.destroy() - - return this -} - - -// return pass corresponding to trace i- j- square -function passId (trace, i, j) { - var id = (trace.id != null ? trace.id : trace) - var n = i - var m = j - var key = id << 16 | (n & 0xff) << 8 | m & 0xff - - return key -} - - -// return bounding box corresponding to a pass -function getBox (items, i, j) { - var ilox, iloy, ihix, ihiy, jlox, jloy, jhix, jhiy - var iitem = items[i], jitem = items[j] - - if (iitem.length > 2) { - ilox = iitem[0] - ihix = iitem[2] - iloy = iitem[1] - ihiy = iitem[3] - } - else if (iitem.length) { - ilox = iloy = iitem[0] - ihix = ihiy = iitem[1] - } - else { - ilox = iitem.x - iloy = iitem.y - ihix = iitem.x + iitem.width - ihiy = iitem.y + iitem.height - } - - if (jitem.length > 2) { - jlox = jitem[0] - jhix = jitem[2] - jloy = jitem[1] - jhiy = jitem[3] - } - else if (jitem.length) { - jlox = jloy = jitem[0] - jhix = jhiy = jitem[1] - } - else { - jlox = jitem.x - jloy = jitem.y - jhix = jitem.x + jitem.width - jhiy = jitem.y + jitem.height - } - - return [ jlox, iloy, jhix, ihiy ] -} - - -function getPad (arg) { - if (typeof arg === 'number') { return [arg, arg, arg, arg] } - else if (arg.length === 2) { return [arg[0], arg[1], arg[0], arg[1]] } - else { - var box = rect(arg) - return [box.x, box.y, box.x + box.width, box.y + box.height] - } -} - -},{"array-bounds":65,"array-range":67,"flatten-vertex-data":227,"parse-rect":459,"pick-by-alias":465,"raf":484,"regl-scatter2d":497}],502:[function(_dereq_,module,exports){ -(function(aa,ia){"object"===typeof exports&&"undefined"!==typeof module?module.exports=ia():"function"===typeof define&&define.amd?define(ia):aa.createREGL=ia()})(this,function(){function aa(a,b){this.id=Ab++;this.type=a;this.data=b}function ia(a){if(0===a.length)return[];var b=a.charAt(0),c=a.charAt(a.length-1);if(1>>=b;c=(255>>=c;b|=c;c=(15>>=c;b|=c;c=(3>>c>>1}function cb(){function a(a){a:{for(var b=16;268435456>=b;b*=16)if(a<=b){a=b;break a}a=0}b=c[bb(a)>>2];return 0>2].push(a)}var c=J(8,function(){return[]});return{alloc:a,free:b,allocType:function(b,c){var d=null;switch(b){case 5120:d=new Int8Array(a(c),0,c);break;case 5121:d=new Uint8Array(a(c),0,c);break;case 5122:d=new Int16Array(a(2*c),0,c);break;case 5123:d=new Uint16Array(a(2*c),0,c);break;case 5124:d=new Int32Array(a(4*c),0,c);break;case 5125:d=new Uint32Array(a(4*c),0,c);break;case 5126:d=new Float32Array(a(4*c),0,c);break;default:return null}return d.length!== -c?d.subarray(0,c):d},freeType:function(a){b(a.buffer)}}}function ma(a){return!!a&&"object"===typeof a&&Array.isArray(a.shape)&&Array.isArray(a.stride)&&"number"===typeof a.offset&&a.shape.length===a.stride.length&&(Array.isArray(a.data)||M(a.data))}function db(a,b,c,e,g,d){for(var n=0;nd&&(d=e.buffer.byteLength,5123===f?d>>=1:5125===f&&(d>>=2));e.vertCount=d;d=h;0>h&&(d=4,h=e.buffer.dimension,1===h&&(d=0),2===h&&(d=1),3===h&&(d=4));e.primType=d}function n(a){e.elementsCount--;delete f[a.id];a.buffer.destroy();a.buffer=null}var f={},r=0,q={uint8:5121,uint16:5123};b.oes_element_index_uint&&(q.uint32=5125);g.prototype.bind=function(){this.buffer.bind()};var t=[];return{create:function(a,b){function k(a){if(a)if("number"===typeof a)h(a),l.primType=4,l.vertCount=a|0, -l.type=5121;else{var b=null,c=35044,e=-1,g=-1,f=0,m=0;if(Array.isArray(a)||M(a)||ma(a))b=a;else if("data"in a&&(b=a.data),"usage"in a&&(c=jb[a.usage]),"primitive"in a&&(e=Sa[a.primitive]),"count"in a&&(g=a.count|0),"type"in a&&(m=q[a.type]),"length"in a)f=a.length|0;else if(f=g,5123===m||5122===m)f*=2;else if(5125===m||5124===m)f*=4;d(l,b,c,e,g,f,m)}else h(),l.primType=4,l.vertCount=0,l.type=5121;return k}var h=c.create(null,34963,!0),l=new g(h._buffer);e.elementsCount++;k(a);k._reglType="elements"; -k._elements=l;k.subdata=function(a,b){h.subdata(a,b);return k};k.destroy=function(){n(l)};return k},createStream:function(a){var b=t.pop();b||(b=new g(c.create(null,34963,!0,!1)._buffer));d(b,a,35040,-1,-1,0,0);return b},destroyStream:function(a){t.push(a)},getElements:function(a){return"function"===typeof a&&a._elements instanceof g?a._elements:null},clear:function(){S(f).forEach(n)}}}function kb(a){for(var b=x.allocType(5123,a.length),c=0;c>>31<<15,d=(e<<1>>>24)-127,e=e>>13&1023;b[c]=-24>d?g:-14>d?g+(e+1024>>-14-d):15>=e,c.height>>=e,C(c,d[e]),a.mipmask|=1<b;++b)a.images[b]=null;return a}function ib(a){for(var b=a.images,c=0;cb){for(var c=0;c=--this.refCount&&A(this)}});n.profile&&(d.getTotalTextureSize=function(){var a=0;Object.keys(X).forEach(function(b){a+=X[b].stats.size});return a});return{create2D:function(b,c){function e(a,b){var c=f.texInfo;y.call(c);var d=D();"number"===typeof a?"number"===typeof b?v(d,a|0,b|0):v(d,a|0,a|0):a?(O(c,a),N(d,a)):v(d,1,1);c.genMipmaps&&(d.mipmask=(d.width<<1)-1);f.mipmask=d.mipmask;r(f,d);f.internalformat=d.internalformat; -e.width=d.width;e.height=d.height;T(f);B(d,3553);R(c,3553);Aa();ib(d);n.profile&&(f.stats.size=Ja(f.internalformat,f.type,d.width,d.height,c.genMipmaps,!1));e.format=J[f.internalformat];e.type=da[f.type];e.mag=oa[c.magFilter];e.min=za[c.minFilter];e.wrapS=ka[c.wrapS];e.wrapT=ka[c.wrapT];return e}var f=new F(3553);X[f.id]=f;d.textureCount++;e(b,c);e.subimage=function(a,b,c,d){b|=0;c|=0;d|=0;var p=h();r(p,f);p.width=0;p.height=0;C(p,a);p.width=p.width||(f.width>>d)-b;p.height=p.height||(f.height>>d)- -c;T(f);k(p,3553,b,c,d);Aa();l(p);return e};e.resize=function(b,c){var d=b|0,h=c|0||d;if(d===f.width&&h===f.height)return e;e.width=f.width=d;e.height=f.height=h;T(f);for(var p,w=f.channels,z=f.type,I=0;f.mipmask>>I;++I){var fa=d>>I,ga=h>>I;if(!fa||!ga)break;p=x.zero.allocType(z,fa*ga*w);a.texImage2D(3553,I,f.format,fa,ga,0,f.format,f.type,p);p&&x.zero.freeType(p)}Aa();n.profile&&(f.stats.size=Ja(f.internalformat,f.type,d,h,!1,!1));return e};e._reglType="texture2d";e._texture=f;n.profile&&(e.stats= -f.stats);e.destroy=function(){f.decRef()};return e},createCube:function(b,c,e,f,g,ua){function A(a,b,c,d,e,f){var H,Y=m.texInfo;y.call(Y);for(H=0;6>H;++H)p[H]=D();if("number"===typeof a||!a)for(a=a|0||1,H=0;6>H;++H)v(p[H],a,a);else if("object"===typeof a)if(b)N(p[0],a),N(p[1],b),N(p[2],c),N(p[3],d),N(p[4],e),N(p[5],f);else if(O(Y,a),q(m,a),"faces"in a)for(a=a.faces,H=0;6>H;++H)r(p[H],m),N(p[H],a[H]);else for(H=0;6>H;++H)N(p[H],a);r(m,p[0]);m.mipmask=Y.genMipmaps?(p[0].width<<1)-1:p[0].mipmask;m.internalformat= -p[0].internalformat;A.width=p[0].width;A.height=p[0].height;T(m);for(H=0;6>H;++H)B(p[H],34069+H);R(Y,34067);Aa();n.profile&&(m.stats.size=Ja(m.internalformat,m.type,A.width,A.height,Y.genMipmaps,!0));A.format=J[m.internalformat];A.type=da[m.type];A.mag=oa[Y.magFilter];A.min=za[Y.minFilter];A.wrapS=ka[Y.wrapS];A.wrapT=ka[Y.wrapT];for(H=0;6>H;++H)ib(p[H]);return A}var m=new F(34067);X[m.id]=m;d.cubeCount++;var p=Array(6);A(b,c,e,f,g,ua);A.subimage=function(a,b,c,p,d){c|=0;p|=0;d|=0;var e=h();r(e,m); -e.width=0;e.height=0;C(e,b);e.width=e.width||(m.width>>d)-c;e.height=e.height||(m.height>>d)-p;T(m);k(e,34069+a,c,p,d);Aa();l(e);return A};A.resize=function(b){b|=0;if(b!==m.width){A.width=m.width=b;A.height=m.height=b;T(m);for(var c=0;6>c;++c)for(var p=0;m.mipmask>>p;++p)a.texImage2D(34069+c,p,m.format,b>>p,b>>p,0,m.format,m.type,null);Aa();n.profile&&(m.stats.size=Ja(m.internalformat,m.type,A.width,A.height,!1,!0));return A}};A._reglType="textureCube";A._texture=m;n.profile&&(A.stats=m.stats);A.destroy= -function(){m.decRef()};return A},clear:function(){for(var b=0;bc;++c)if(0!==(b.mipmask&1<> -c,b.height>>c,0,b.internalformat,b.type,null);else for(var d=0;6>d;++d)a.texImage2D(34069+d,c,b.internalformat,b.width>>c,b.height>>c,0,b.internalformat,b.type,null);R(b.texInfo,b.target)})}}}function Ob(a,b,c,e,g,d){function n(a,b,c){this.target=a;this.texture=b;this.renderbuffer=c;var d=a=0;b?(a=b.width,d=b.height):c&&(a=c.width,d=c.height);this.width=a;this.height=d}function f(a){a&&(a.texture&&a.texture._texture.decRef(),a.renderbuffer&&a.renderbuffer._renderbuffer.decRef())}function r(a,b,c){a&& -(a.texture?a.texture._texture.refCount+=1:a.renderbuffer._renderbuffer.refCount+=1)}function q(b,c){c&&(c.texture?a.framebufferTexture2D(36160,b,c.target,c.texture._texture.texture,0):a.framebufferRenderbuffer(36160,b,36161,c.renderbuffer._renderbuffer.renderbuffer))}function t(a){var b=3553,c=null,d=null,e=a;"object"===typeof a&&(e=a.data,"target"in a&&(b=a.target|0));a=e._reglType;"texture2d"===a?c=e:"textureCube"===a?c=e:"renderbuffer"===a&&(d=e,b=36161);return new n(b,c,d)}function m(a,b,c,d, -f){if(c)return a=e.create2D({width:a,height:b,format:d,type:f}),a._texture.refCount=0,new n(3553,a,null);a=g.create({width:a,height:b,format:d});a._renderbuffer.refCount=0;return new n(36161,null,a)}function C(a){return a&&(a.texture||a.renderbuffer)}function k(a,b,c){a&&(a.texture?a.texture.resize(b,c):a.renderbuffer&&a.renderbuffer.resize(b,c),a.width=b,a.height=c)}function h(){this.id=O++;R[this.id]=this;this.framebuffer=a.createFramebuffer();this.height=this.width=0;this.colorAttachments=[];this.depthStencilAttachment= -this.stencilAttachment=this.depthAttachment=null}function l(a){a.colorAttachments.forEach(f);f(a.depthAttachment);f(a.stencilAttachment);f(a.depthStencilAttachment)}function u(b){a.deleteFramebuffer(b.framebuffer);b.framebuffer=null;d.framebufferCount--;delete R[b.id]}function v(b){var d;a.bindFramebuffer(36160,b.framebuffer);var e=b.colorAttachments;for(d=0;dd;++d){for(m=0;ma;++a)c[a].resize(d);b.width=b.height=d;return b},_reglType:"framebufferCube",destroy:function(){c.forEach(function(a){a.destroy()})}})},clear:function(){S(R).forEach(u)},restore:function(){B.cur=null;B.next=null;B.dirty=!0;S(R).forEach(function(b){b.framebuffer=a.createFramebuffer();v(b)})}})}function ub(){this.w=this.z=this.y= -this.x=this.state=0;this.buffer=null;this.size=0;this.normalized=!1;this.type=5126;this.divisor=this.stride=this.offset=0}function Pb(a,b,c,e){a=c.maxAttributes;b=Array(a);for(c=0;c -a&&(a=b.stats.uniformsCount)});return a},c.getMaxAttributesCount=function(){var a=0;C.forEach(function(b){b.stats.attributesCount>a&&(a=b.stats.attributesCount)});return a});return{clear:function(){var b=a.deleteShader.bind(a);S(q).forEach(b);q={};S(t).forEach(b);t={};C.forEach(function(b){a.deleteProgram(b.program)});C.length=0;m={};c.shaderCount=0},program:function(a,b,d){var e=m[b];e||(e=m[b]={});var g=e[a];g||(g=new f(b,a),c.shaderCount++,r(g,d),e[a]=g,C.push(g));return g},restore:function(){q= -{};t={};for(var a=0;a"+b+"?"+e+".constant["+b+"]:0;"}).join(""),"}}else{", -"if(",f,"(",e,".buffer)){",z,"=",g,".createStream(",34962,",",e,".buffer);","}else{",z,"=",g,".getBuffer(",e,".buffer);","}",k,'="type" in ',e,"?",p.glTypes,"[",e,".type]:",z,".dtype;",w.normalized,"=!!",e,".normalized;");d("size");d("offset");d("stride");d("divisor");c("}}");c.exit("if(",w.isStream,"){",g,".destroyStream(",z,");","}");return w})});return f}function M(a){var b=a["static"],c=a.dynamic,d={};Object.keys(b).forEach(function(a){var c=b[a];d[a]=D(function(a,b){return"number"===typeof c|| -"boolean"===typeof c?""+c:a.link(c)})});Object.keys(c).forEach(function(a){var b=c[a];d[a]=P(b,function(a,c){return a.invoke(c,b)})});return d}function A(a,b,c,d,e){var f=y(a,e),g=x(a,f,e),h=O(a,e),k=R(a,e),m=E(a,e),ba=g.viewport;ba&&(k.viewport=ba);ba=l("scissor.box");(g=g[ba])&&(k[ba]=g);g=0>1)",v],");")}function b(){c(u,".drawArraysInstancedANGLE(",[q,r,t,v],");")}n?da?a():(c("if(",n,"){"),a(),c("}else{"),b(),c("}")):b()}function g(){function a(){c(k+".drawElements("+[q,t,C,r+"<<(("+C+"-5121)>>1)"]+");")}function b(){c(k+".drawArrays("+[q,r,t]+");")}n?da?a():(c("if(",n,"){"),a(),c("}else{"),b(),c("}")): -b()}var h=a.shared,k=h.gl,m=h.draw,l=d.draw,n=function(){var e=l.elements,f=b;if(e){if(e.contextDep&&d.contextDynamic||e.propDep)f=c;e=e.append(a,f)}else e=f.def(m,".","elements");e&&f("if("+e+")"+k+".bindBuffer(34963,"+e+".buffer.buffer);");return e}(),q=e("primitive"),r=e("offset"),t=function(){var e=l.count,f=b;if(e){if(e.contextDep&&d.contextDynamic||e.propDep)f=c;e=e.append(a,f)}else e=f.def(m,".","count");return e}();if("number"===typeof t){if(0===t)return}else c("if(",t,"){"),c.exit("}");var v, -u;ea&&(v=e("instances"),u=a.instancing);var C=n+".type",da=l.elements&&va(l.elements);ea&&("number"!==typeof v||0<=v)?"string"===typeof v?(c("if(",v,">0){"),f(),c("}else if(",v,"<0){"),g(),c("}")):f():g()}function ca(a,b,c,d,e){b=N();e=b.proc("body",e);ea&&(b.instancing=e.def(b.shared.extensions,".angle_instanced_arrays"));a(b,e,c,d);return b.compile().body}function L(a,b,c,d){wa(a,b);U(a,b,c,d.attributes,function(){return!0});W(a,b,c,d.uniforms,function(){return!0});S(a,b,b,c)}function da(a,b){var c= -a.proc("draw",1);wa(a,c);ua(a,c,b.context);K(a,c,b.framebuffer);V(a,c,b);Q(a,c,b.state);G(a,c,b,!1,!0);var d=b.shader.progVar.append(a,c);c(a.shared.gl,".useProgram(",d,".program);");if(b.shader.program)L(a,c,b,b.shader.program);else{var e=a.global.def("{}"),f=c.def(d,".id"),g=c.def(e,"[",f,"]");c(a.cond(g).then(g,".call(this,a0);")["else"](g,"=",e,"[",f,"]=",a.link(function(c){return ca(L,a,b,c,1)}),"(",d,");",g,".call(this,a0);"))}0=--this.refCount&&n(this)};g.profile&&(e.getTotalRenderbufferSize=function(){var a=0;Object.keys(t).forEach(function(b){a+=t[b].stats.size});return a});return{create:function(b,c){function k(b,c){var d=0,e=0,m=32854; -"object"===typeof b&&b?("shape"in b?(e=b.shape,d=e[0]|0,e=e[1]|0):("radius"in b&&(d=e=b.radius|0),"width"in b&&(d=b.width|0),"height"in b&&(e=b.height|0)),"format"in b&&(m=f[b.format])):"number"===typeof b?(d=b|0,e="number"===typeof c?c|0:d):b||(d=e=1);if(d!==h.width||e!==h.height||m!==h.format)return k.width=h.width=d,k.height=h.height=e,h.format=m,a.bindRenderbuffer(36161,h.renderbuffer),a.renderbufferStorage(36161,m,d,e),g.profile&&(h.stats.size=Q[h.format]*h.width*h.height),k.format=r[h.format], -k}var h=new d(a.createRenderbuffer());t[h.id]=h;e.renderbufferCount++;k(b,c);k.resize=function(b,c){var d=b|0,e=c|0||d;if(d===h.width&&e===h.height)return k;k.width=h.width=d;k.height=h.height=e;a.bindRenderbuffer(36161,h.renderbuffer);a.renderbufferStorage(36161,h.format,d,e);g.profile&&(h.stats.size=Q[h.format]*h.width*h.height);return k};k._reglType="renderbuffer";k._renderbuffer=h;g.profile&&(k.stats=h.stats);k.destroy=function(){h.decRef()};return k},clear:function(){S(t).forEach(n)},restore:function(){S(t).forEach(function(b){b.renderbuffer= -a.createRenderbuffer();a.bindRenderbuffer(36161,b.renderbuffer);a.renderbufferStorage(36161,b.format,b.width,b.height)});a.bindRenderbuffer(36161,null)}}},Wa=[];Wa[6408]=4;Wa[6407]=3;var Na=[];Na[5121]=1;Na[5126]=4;Na[36193]=2;var Da=["x","y","z","w"],Ub="blend.func blend.equation stencil.func stencil.opFront stencil.opBack sample.coverage viewport scissor.box polygonOffset.offset".split(" "),Ga={0:0,1:1,zero:0,one:1,"src color":768,"one minus src color":769,"src alpha":770,"one minus src alpha":771, -"dst color":774,"one minus dst color":775,"dst alpha":772,"one minus dst alpha":773,"constant color":32769,"one minus constant color":32770,"constant alpha":32771,"one minus constant alpha":32772,"src alpha saturate":776},Xa={never:512,less:513,"<":513,equal:514,"=":514,"==":514,"===":514,lequal:515,"<=":515,greater:516,">":516,notequal:517,"!=":517,"!==":517,gequal:518,">=":518,always:519},Pa={0:0,zero:0,keep:7680,replace:7681,increment:7682,decrement:7683,"increment wrap":34055,"decrement wrap":34056, -invert:5386},wb={cw:2304,ccw:2305},xb=new Z(!1,!1,!1,function(){}),Xb=function(a,b){function c(){this.endQueryIndex=this.startQueryIndex=-1;this.sum=0;this.stats=null}function e(a,b,d){var e=n.pop()||new c;e.startQueryIndex=a;e.endQueryIndex=b;e.sum=0;e.stats=d;f.push(e)}if(!b.ext_disjoint_timer_query)return null;var g=[],d=[],n=[],f=[],r=[],q=[];return{beginQuery:function(a){var c=g.pop()||b.ext_disjoint_timer_query.createQueryEXT();b.ext_disjoint_timer_query.beginQueryEXT(35007,c);d.push(c);e(d.length- -1,d.length,a)},endQuery:function(){b.ext_disjoint_timer_query.endQueryEXT(35007)},pushScopeStats:e,update:function(){var a,c;a=d.length;if(0!==a){q.length=Math.max(q.length,a+1);r.length=Math.max(r.length,a+1);r[0]=0;var e=q[0]=0;for(c=a=0;c=G.length&&e()}var c=yb(G,a);G[c]=b}}}function q(){var a=S.viewport,b=S.scissor_box;a[0]=a[1]=b[0]=b[1]=0;O.viewportWidth= -O.framebufferWidth=O.drawingBufferWidth=a[2]=b[2]=k.drawingBufferWidth;O.viewportHeight=O.framebufferHeight=O.drawingBufferHeight=a[3]=b[3]=k.drawingBufferHeight}function t(){O.tick+=1;O.time=y();q();V.procs.poll()}function m(){q();V.procs.refresh();B&&B.update()}function y(){return(zb()-D)/1E3}a=Eb(a);if(!a)return null;var k=a.gl,h=k.getContextAttributes();k.isContextLost();var l=Fb(k,a);if(!l)return null;var u=Bb(),v={bufferCount:0,elementsCount:0,framebufferCount:0,shaderCount:0,textureCount:0, -cubeCount:0,renderbufferCount:0,maxTextureUnits:0},x=l.extensions,B=Xb(k,x),D=zb(),J=k.drawingBufferWidth,P=k.drawingBufferHeight,O={tick:0,time:0,viewportWidth:J,viewportHeight:P,framebufferWidth:J,framebufferHeight:P,drawingBufferWidth:J,drawingBufferHeight:P,pixelRatio:a.pixelRatio},R=Vb(k,x),J=Pb(k,x,R,u),F=Gb(k,v,a,J),T=Hb(k,x,F,v),Q=Qb(k,u,v,a),A=Kb(k,x,R,function(){V.procs.poll()},O,v,a),M=Wb(k,x,R,v,a),K=Ob(k,x,R,A,M,v),V=Tb(k,u,x,R,F,T,A,K,{},J,Q,{elements:null,primitive:4,count:-1,offset:0, -instances:-1},O,B,a),u=Rb(k,K,V.procs.poll,O,h,x,R),S=V.next,L=k.canvas,G=[],U=[],W=[],Z=[a.onDestroy],ca=null;L&&(L.addEventListener("webglcontextlost",g,!1),L.addEventListener("webglcontextrestored",d,!1));var aa=K.setFBO=n({framebuffer:la.define.call(null,1,"framebuffer")});m();h=E(n,{clear:function(a){if("framebuffer"in a)if(a.framebuffer&&"framebufferCube"===a.framebuffer_reglType)for(var b=0;6>b;++b)aa(E({framebuffer:a.framebuffer.faces[b]},a),f);else aa(a,f);else f(null,a)},prop:la.define.bind(null, -1),context:la.define.bind(null,2),"this":la.define.bind(null,3),draw:n({}),buffer:function(a){return F.create(a,34962,!1,!1)},elements:function(a){return T.create(a,!1)},texture:A.create2D,cube:A.createCube,renderbuffer:M.create,framebuffer:K.create,framebufferCube:K.createCube,attributes:h,frame:r,on:function(a,b){var c;switch(a){case "frame":return r(b);case "lost":c=U;break;case "restore":c=W;break;case "destroy":c=Z}c.push(b);return{cancel:function(){for(var a=0;a - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - -'use strict'; - -/** - * Results cache - */ - -var res = ''; -var cache; - -/** - * Expose `repeat` - */ - -module.exports = repeat; - -/** - * Repeat the given `string` the specified `number` - * of times. - * - * **Example:** - * - * ```js - * var repeat = require('repeat-string'); - * repeat('A', 5); - * //=> AAAAA - * ``` - * - * @param {String} `string` The string to repeat - * @param {Number} `number` The number of times to repeat the string - * @return {String} Repeated string - * @api public - */ - -function repeat(str, num) { - if (typeof str !== 'string') { - throw new TypeError('expected a string'); - } - - // cover common, quick use cases - if (num === 1) return str; - if (num === 2) return str + str; - - var max = str.length * num; - if (cache !== str || typeof cache === 'undefined') { - cache = str; - res = ''; - } else if (res.length >= max) { - return res.substr(0, max); - } - - while (max > res.length && num > 1) { - if (num & 1) { - res += str; - } - - num >>= 1; - str += str; - } - - res += str; - res = res.substr(0, max); - return res; -} - -},{}],504:[function(_dereq_,module,exports){ -(function (global){ -module.exports = - global.performance && - global.performance.now ? function now() { - return performance.now() - } : Date.now || function now() { - return +new Date - } - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],505:[function(_dereq_,module,exports){ -"use strict" - -module.exports = compressExpansion - -function compressExpansion(e) { - var m = e.length - var Q = e[e.length-1] - var bottom = m - for(var i=m-2; i>=0; --i) { - var a = Q - var b = e[i] - Q = a + b - var bv = Q - a - var q = b - bv - if(q) { - e[--bottom] = Q - Q = q - } - } - var top = 0 - for(var i=bottom; i>1 - return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") - } -} - -function determinant(m) { - if(m.length === 2) { - return ["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("") - } else { - var expr = [] - for(var i=0; i>1 - return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") - } -} - -function makeProduct(a, b) { - if(a.charAt(0) === "m") { - if(b.charAt(0) === "w") { - var toks = a.split("[") - return ["w", b.substr(1), "m", toks[0].substr(1)].join("") - } else { - return ["prod(", a, ",", b, ")"].join("") - } - } else { - return makeProduct(b, a) - } -} - -function sign(s) { - if(s & 1 !== 0) { - return "-" - } - return "" -} - -function determinant(m) { - if(m.length === 2) { - return [["diff(", makeProduct(m[0][0], m[1][1]), ",", makeProduct(m[1][0], m[0][1]), ")"].join("")] - } else { - var expr = [] - for(var i=0; i 0) { - code.push(",") - } - code.push("[") - for(var k=0; k 0) { - code.push(",") - } - if(k === i) { - code.push("+b[", j, "]") - } else { - code.push("+A[", j, "][", k, "]") - } - } - code.push("]") - } - code.push("]),") - } - code.push("det(A)]}return ", funcName) - var proc = new Function("det", code.join("")) - if(n < 6) { - return proc(determinant[n]) - } - return proc(determinant) -} - -function robustLinearSolve0d() { - return [ 0 ] -} - -function robustLinearSolve1d(A, b) { - return [ [ b[0] ], [ A[0][0] ] ] -} - -var CACHE = [ - robustLinearSolve0d, - robustLinearSolve1d -] - -function generateDispatch() { - while(CACHE.length < NUM_EXPAND) { - CACHE.push(generateSolver(CACHE.length)) - } - var procArgs = [] - var code = ["function dispatchLinearSolve(A,b){switch(A.length){"] - for(var i=0; i>1 - return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") - } -} - -function determinant(m) { - if(m.length === 2) { - return [["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("")] - } else { - var expr = [] - for(var i=0; i 0) { - if(r <= 0) { - return det - } else { - s = l + r - } - } else if(l < 0) { - if(r >= 0) { - return det - } else { - s = -(l + r) - } - } else { - return det - } - var tol = ERRBOUND3 * s - if(det >= tol || det <= -tol) { - return det - } - return orientation3Exact(a, b, c) - }, - function orientation4(a,b,c,d) { - var adx = a[0] - d[0] - var bdx = b[0] - d[0] - var cdx = c[0] - d[0] - var ady = a[1] - d[1] - var bdy = b[1] - d[1] - var cdy = c[1] - d[1] - var adz = a[2] - d[2] - var bdz = b[2] - d[2] - var cdz = c[2] - d[2] - var bdxcdy = bdx * cdy - var cdxbdy = cdx * bdy - var cdxady = cdx * ady - var adxcdy = adx * cdy - var adxbdy = adx * bdy - var bdxady = bdx * ady - var det = adz * (bdxcdy - cdxbdy) - + bdz * (cdxady - adxcdy) - + cdz * (adxbdy - bdxady) - var permanent = (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz) - + (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz) - + (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz) - var tol = ERRBOUND4 * permanent - if ((det > tol) || (-det > tol)) { - return det - } - return orientation4Exact(a,b,c,d) - } -] - -function slowOrient(args) { - var proc = CACHED[args.length] - if(!proc) { - proc = CACHED[args.length] = orientation(args.length) - } - return proc.apply(undefined, args) -} - -function generateOrientationProc() { - while(CACHED.length <= NUM_EXPAND) { - CACHED.push(orientation(CACHED.length)) - } - var args = [] - var procArgs = ["slow"] - for(var i=0; i<=NUM_EXPAND; ++i) { - args.push("a" + i) - procArgs.push("o" + i) - } - var code = [ - "function getOrientation(", args.join(), "){switch(arguments.length){case 0:case 1:return 0;" - ] - for(var i=2; i<=NUM_EXPAND; ++i) { - code.push("case ", i, ":return o", i, "(", args.slice(0, i).join(), ");") - } - code.push("}var s=new Array(arguments.length);for(var i=0;i 0 && y0 > 0) || (x0 < 0 && y0 < 0)) { - return false - } - - var x1 = orient(b0, a0, a1) - var y1 = orient(b1, a0, a1) - if((x1 > 0 && y1 > 0) || (x1 < 0 && y1 < 0)) { - return false - } - - //Check for degenerate collinear case - if(x0 === 0 && y0 === 0 && x1 === 0 && y1 === 0) { - return checkCollinear(a0, a1, b0, b1) - } - - return true -} -},{"robust-orientation":510}],514:[function(_dereq_,module,exports){ -"use strict" - -module.exports = robustSubtract - -//Easy case: Add two scalars -function scalarScalar(a, b) { - var x = a + b - var bv = x - a - var av = x - bv - var br = b - bv - var ar = a - av - var y = ar + br - if(y) { - return [y, x] - } - return [x] -} - -function robustSubtract(e, f) { - var ne = e.length|0 - var nf = f.length|0 - if(ne === 1 && nf === 1) { - return scalarScalar(e[0], -f[0]) - } - var n = ne + nf - var g = new Array(n) - var count = 0 - var eptr = 0 - var fptr = 0 - var abs = Math.abs - var ei = e[eptr] - var ea = abs(ei) - var fi = -f[fptr] - var fa = abs(fi) - var a, b - if(ea < fa) { - b = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) - } - } else { - b = fi - fptr += 1 - if(fptr < nf) { - fi = -f[fptr] - fa = abs(fi) - } - } - if((eptr < ne && ea < fa) || (fptr >= nf)) { - a = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) - } - } else { - a = fi - fptr += 1 - if(fptr < nf) { - fi = -f[fptr] - fa = abs(fi) - } - } - var x = a + b - var bv = x - a - var y = b - bv - var q0 = y - var q1 = x - var _x, _bv, _av, _br, _ar - while(eptr < ne && fptr < nf) { - if(ea < fa) { - a = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) - } - } else { - a = fi - fptr += 1 - if(fptr < nf) { - fi = -f[fptr] - fa = abs(fi) - } - } - b = q0 - x = a + b - bv = x - a - y = b - bv - if(y) { - g[count++] = y - } - _x = q1 + x - _bv = _x - q1 - _av = _x - _bv - _br = x - _bv - _ar = q1 - _av - q0 = _ar + _br - q1 = _x - } - while(eptr < ne) { - a = ei - b = q0 - x = a + b - bv = x - a - y = b - bv - if(y) { - g[count++] = y - } - _x = q1 + x - _bv = _x - q1 - _av = _x - _bv - _br = x - _bv - _ar = q1 - _av - q0 = _ar + _br - q1 = _x - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - } - } - while(fptr < nf) { - a = fi - b = q0 - x = a + b - bv = x - a - y = b - bv - if(y) { - g[count++] = y - } - _x = q1 + x - _bv = _x - q1 - _av = _x - _bv - _br = x - _bv - _ar = q1 - _av - q0 = _ar + _br - q1 = _x - fptr += 1 - if(fptr < nf) { - fi = -f[fptr] - } - } - if(q0) { - g[count++] = q0 - } - if(q1) { - g[count++] = q1 - } - if(!count) { - g[count++] = 0.0 - } - g.length = count - return g -} -},{}],515:[function(_dereq_,module,exports){ -"use strict" - -module.exports = linearExpansionSum - -//Easy case: Add two scalars -function scalarScalar(a, b) { - var x = a + b - var bv = x - a - var av = x - bv - var br = b - bv - var ar = a - av - var y = ar + br - if(y) { - return [y, x] - } - return [x] -} - -function linearExpansionSum(e, f) { - var ne = e.length|0 - var nf = f.length|0 - if(ne === 1 && nf === 1) { - return scalarScalar(e[0], f[0]) - } - var n = ne + nf - var g = new Array(n) - var count = 0 - var eptr = 0 - var fptr = 0 - var abs = Math.abs - var ei = e[eptr] - var ea = abs(ei) - var fi = f[fptr] - var fa = abs(fi) - var a, b - if(ea < fa) { - b = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) - } - } else { - b = fi - fptr += 1 - if(fptr < nf) { - fi = f[fptr] - fa = abs(fi) - } - } - if((eptr < ne && ea < fa) || (fptr >= nf)) { - a = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) - } - } else { - a = fi - fptr += 1 - if(fptr < nf) { - fi = f[fptr] - fa = abs(fi) - } - } - var x = a + b - var bv = x - a - var y = b - bv - var q0 = y - var q1 = x - var _x, _bv, _av, _br, _ar - while(eptr < ne && fptr < nf) { - if(ea < fa) { - a = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) - } - } else { - a = fi - fptr += 1 - if(fptr < nf) { - fi = f[fptr] - fa = abs(fi) - } - } - b = q0 - x = a + b - bv = x - a - y = b - bv - if(y) { - g[count++] = y - } - _x = q1 + x - _bv = _x - q1 - _av = _x - _bv - _br = x - _bv - _ar = q1 - _av - q0 = _ar + _br - q1 = _x - } - while(eptr < ne) { - a = ei - b = q0 - x = a + b - bv = x - a - y = b - bv - if(y) { - g[count++] = y - } - _x = q1 + x - _bv = _x - q1 - _av = _x - _bv - _br = x - _bv - _ar = q1 - _av - q0 = _ar + _br - q1 = _x - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - } - } - while(fptr < nf) { - a = fi - b = q0 - x = a + b - bv = x - a - y = b - bv - if(y) { - g[count++] = y - } - _x = q1 + x - _bv = _x - q1 - _av = _x - _bv - _br = x - _bv - _ar = q1 - _av - q0 = _ar + _br - q1 = _x - fptr += 1 - if(fptr < nf) { - fi = f[fptr] - } - } - if(q0) { - g[count++] = q0 - } - if(q1) { - g[count++] = q1 - } - if(!count) { - g[count++] = 0.0 - } - g.length = count - return g -} -},{}],516:[function(_dereq_,module,exports){ -"use strict" - -module.exports = function signum(x) { - if(x < 0) { return -1 } - if(x > 0) { return 1 } - return 0.0 -} -},{}],517:[function(_dereq_,module,exports){ -'use strict' - -module.exports = boundary - -var bnd = _dereq_('boundary-cells') -var reduce = _dereq_('reduce-simplicial-complex') - -function boundary(cells) { - return reduce(bnd(cells)) -} - -},{"boundary-cells":95,"reduce-simplicial-complex":489}],518:[function(_dereq_,module,exports){ -'use strict' - -module.exports = extractContour - -var ndarray = _dereq_('ndarray') -var pool = _dereq_('typedarray-pool') -var ndsort = _dereq_('ndarray-sort') - -var contourAlgorithm = _dereq_('./lib/codegen') - -function getDimension(cells) { - var numCells = cells.length - var d = 0 - for(var i=0; i>1,v=E[2*m+1];', - 'if(v===b){return m}', - 'if(b 0) { - code.push(',') - } - code.push('[') - for(var j=0; j 0) { - code.push(',') - } - code.push('B(C,E,c[', f[0], '],c[', f[1], '])') - } - code.push(']') - } - code.push(');') - } - - for(var i=d+1; i>1; --i) { - if(i < d+1) { - code.push('else ') - } - code.push('if(l===', i, '){') - - //Generate mask - var maskStr = [] - for(var j=0; j> 1 - , s = compareCells(cells[mid], c) - if(s <= 0) { - if(s === 0) { - r = mid - } - lo = mid + 1 - } else if(s > 0) { - hi = mid - 1 - } - } - return r -} -exports.findCell = findCell; - -//Builds an index for an n-cell. This is more general than dual, but less efficient -function incidence(from_cells, to_cells) { - var index = new Array(from_cells.length) - for(var i=0, il=index.length; i= from_cells.length || compareCells(from_cells[idx], b) !== 0) { - break - } - } - } - } - return index -} -exports.incidence = incidence - -//Computes the dual of the mesh. This is basically an optimized version of buildIndex for the situation where from_cells is just the list of vertices -function dual(cells, vertex_count) { - if(!vertex_count) { - return incidence(unique(skeleton(cells, 0)), cells, 0) - } - var res = new Array(vertex_count) - for(var i=0; i>> k) & 1) { - b.push(c[k]) - } - } - result.push(b) - } - } - return normalize(result) -} -exports.explode = explode - -//Enumerates all of the n-cells of a cell complex -function skeleton(cells, n) { - if(n < 0) { - return [] - } - var result = [] - , k0 = (1<<(n+1))-1 - for(var i=0; i> 1 - } - return (i >> 1) - 1 - } - - //Bubble element i down the heap - function heapDown(i) { - var w = heapWeight(i) - while(true) { - var tw = w - var left = 2*i + 1 - var right = 2*(i + 1) - var next = i - if(left < heapCount) { - var lw = heapWeight(left) - if(lw < tw) { - next = left - tw = lw - } - } - if(right < heapCount) { - var rw = heapWeight(right) - if(rw < tw) { - next = right - } - } - if(next === i) { - return i - } - heapSwap(i, next) - i = next - } - } - - //Bubbles element i up the heap - function heapUp(i) { - var w = heapWeight(i) - while(i > 0) { - var parent = heapParent(i) - if(parent >= 0) { - var pw = heapWeight(parent) - if(w < pw) { - heapSwap(i, parent) - i = parent - continue - } - } - return i - } - } - - //Pop minimum element - function heapPop() { - if(heapCount > 0) { - var head = heap[0] - heapSwap(0, heapCount-1) - heapCount -= 1 - heapDown(0) - return head - } - return -1 - } - - //Update heap item i - function heapUpdate(i, w) { - var a = heap[i] - if(weights[a] === w) { - return i - } - weights[a] = -Infinity - heapUp(i) - heapPop() - weights[a] = w - heapCount += 1 - return heapUp(heapCount-1) - } - - //Kills a vertex (assume vertex already removed from heap) - function kill(i) { - if(dead[i]) { - return - } - //Kill vertex - dead[i] = true - //Fixup topology - var s = inv[i] - var t = outv[i] - if(inv[t] >= 0) { - inv[t] = s - } - if(outv[s] >= 0) { - outv[s] = t - } - - //Update weights on s and t - if(index[s] >= 0) { - heapUpdate(index[s], computeWeight(s)) - } - if(index[t] >= 0) { - heapUpdate(index[t], computeWeight(t)) - } - } - - //Initialize weights and heap - var heap = [] - var index = new Array(n) - for(var i=0; i>1; i>=0; --i) { - heapDown(i) - } - - //Kill vertices - while(true) { - var hmin = heapPop() - if((hmin < 0) || (weights[hmin] > minArea)) { - break - } - kill(hmin) - } - - //Build collapsed vertex table - var npositions = [] - for(var i=0; i= 0 && tout >= 0 && tin !== tout) { - var cin = index[tin] - var cout = index[tout] - if(cin !== cout) { - ncells.push([ cin, cout ]) - } - } - }) - - //Normalize result - sc.unique(sc.normalize(ncells)) - - //Return final list of cells - return { - positions: npositions, - edges: ncells - } -} -},{"robust-orientation":510,"simplicial-complex":522}],525:[function(_dereq_,module,exports){ -"use strict" - -module.exports = orderSegments - -var orient = _dereq_("robust-orientation") - -function horizontalOrder(a, b) { - var bl, br - if(b[0][0] < b[1][0]) { - bl = b[0] - br = b[1] - } else if(b[0][0] > b[1][0]) { - bl = b[1] - br = b[0] - } else { - var alo = Math.min(a[0][1], a[1][1]) - var ahi = Math.max(a[0][1], a[1][1]) - var blo = Math.min(b[0][1], b[1][1]) - var bhi = Math.max(b[0][1], b[1][1]) - if(ahi < blo) { - return ahi - blo - } - if(alo > bhi) { - return alo - bhi - } - return ahi - bhi - } - var al, ar - if(a[0][1] < a[1][1]) { - al = a[0] - ar = a[1] - } else { - al = a[1] - ar = a[0] - } - var d = orient(br, bl, al) - if(d) { - return d - } - d = orient(br, bl, ar) - if(d) { - return d - } - return ar - br -} - -function orderSegments(b, a) { - var al, ar - if(a[0][0] < a[1][0]) { - al = a[0] - ar = a[1] - } else if(a[0][0] > a[1][0]) { - al = a[1] - ar = a[0] - } else { - return horizontalOrder(a, b) - } - var bl, br - if(b[0][0] < b[1][0]) { - bl = b[0] - br = b[1] - } else if(b[0][0] > b[1][0]) { - bl = b[1] - br = b[0] - } else { - return -horizontalOrder(b, a) - } - var d1 = orient(al, ar, br) - var d2 = orient(al, ar, bl) - if(d1 < 0) { - if(d2 <= 0) { - return d1 - } - } else if(d1 > 0) { - if(d2 >= 0) { - return d1 - } - } else if(d2) { - return d2 - } - d1 = orient(br, bl, ar) - d2 = orient(br, bl, al) - if(d1 < 0) { - if(d2 <= 0) { - return d1 - } - } else if(d1 > 0) { - if(d2 >= 0) { - return d1 - } - } else if(d2) { - return d2 - } - return ar[0] - br[0] -} -},{"robust-orientation":510}],526:[function(_dereq_,module,exports){ -"use strict" - -module.exports = createSlabDecomposition - -var bounds = _dereq_("binary-search-bounds") -var createRBTree = _dereq_("functional-red-black-tree") -var orient = _dereq_("robust-orientation") -var orderSegments = _dereq_("./lib/order-segments") - -function SlabDecomposition(slabs, coordinates, horizontal) { - this.slabs = slabs - this.coordinates = coordinates - this.horizontal = horizontal -} - -var proto = SlabDecomposition.prototype - -function compareHorizontal(e, y) { - return e.y - y -} - -function searchBucket(root, p) { - var lastNode = null - while(root) { - var seg = root.key - var l, r - if(seg[0][0] < seg[1][0]) { - l = seg[0] - r = seg[1] - } else { - l = seg[1] - r = seg[0] - } - var o = orient(l, r, p) - if(o < 0) { - root = root.left - } else if(o > 0) { - if(p[0] !== seg[1][0]) { - lastNode = root - root = root.right - } else { - var val = searchBucket(root.right, p) - if(val) { - return val - } - root = root.left - } - } else { - if(p[0] !== seg[1][0]) { - return root - } else { - var val = searchBucket(root.right, p) - if(val) { - return val - } - root = root.left - } - } - } - return lastNode -} - -proto.castUp = function(p) { - var bucket = bounds.le(this.coordinates, p[0]) - if(bucket < 0) { - return -1 - } - var root = this.slabs[bucket] - var hitNode = searchBucket(this.slabs[bucket], p) - var lastHit = -1 - if(hitNode) { - lastHit = hitNode.value - } - //Edge case: need to handle horizontal segments (sucks) - if(this.coordinates[bucket] === p[0]) { - var lastSegment = null - if(hitNode) { - lastSegment = hitNode.key - } - if(bucket > 0) { - var otherHitNode = searchBucket(this.slabs[bucket-1], p) - if(otherHitNode) { - if(lastSegment) { - if(orderSegments(otherHitNode.key, lastSegment) > 0) { - lastSegment = otherHitNode.key - lastHit = otherHitNode.value - } - } else { - lastHit = otherHitNode.value - lastSegment = otherHitNode.key - } - } - } - var horiz = this.horizontal[bucket] - if(horiz.length > 0) { - var hbucket = bounds.ge(horiz, p[1], compareHorizontal) - if(hbucket < horiz.length) { - var e = horiz[hbucket] - if(p[1] === e.y) { - if(e.closed) { - return e.index - } else { - while(hbucket < horiz.length-1 && horiz[hbucket+1].y === p[1]) { - hbucket = hbucket+1 - e = horiz[hbucket] - if(e.closed) { - return e.index - } - } - if(e.y === p[1] && !e.start) { - hbucket = hbucket+1 - if(hbucket >= horiz.length) { - return lastHit - } - e = horiz[hbucket] - } - } - } - //Check if e is above/below last segment - if(e.start) { - if(lastSegment) { - var o = orient(lastSegment[0], lastSegment[1], [p[0], e.y]) - if(lastSegment[0][0] > lastSegment[1][0]) { - o = -o - } - if(o > 0) { - lastHit = e.index - } - } else { - lastHit = e.index - } - } else if(e.y !== p[1]) { - lastHit = e.index - } - } - } - } - return lastHit -} - -function IntervalSegment(y, index, start, closed) { - this.y = y - this.index = index - this.start = start - this.closed = closed -} - -function Event(x, segment, create, index) { - this.x = x - this.segment = segment - this.create = create - this.index = index -} - - -function createSlabDecomposition(segments) { - var numSegments = segments.length - var numEvents = 2 * numSegments - var events = new Array(numEvents) - for(var i=0; i 1.0) { - t = 1.0 - } - var ti = 1.0 - t - var n = a.length - var r = new Array(n) - for(var i=0; i 0) || (a > 0 && b < 0)) { - var p = lerpW(s, b, t, a) - pos.push(p) - neg.push(p.slice()) - } - if(b < 0) { - neg.push(t.slice()) - } else if(b > 0) { - pos.push(t.slice()) - } else { - pos.push(t.slice()) - neg.push(t.slice()) - } - a = b - } - return { positive: pos, negative: neg } -} - -function positive(points, plane) { - var pos = [] - var a = planeT(points[points.length-1], plane) - for(var s=points[points.length-1], t=points[0], i=0; i 0) || (a > 0 && b < 0)) { - pos.push(lerpW(s, b, t, a)) - } - if(b >= 0) { - pos.push(t.slice()) - } - a = b - } - return pos -} - -function negative(points, plane) { - var neg = [] - var a = planeT(points[points.length-1], plane) - for(var s=points[points.length-1], t=points[0], i=0; i 0) || (a > 0 && b < 0)) { - neg.push(lerpW(s, b, t, a)) - } - if(b <= 0) { - neg.push(t.slice()) - } - a = b - } - return neg -} -},{"robust-dot-product":507,"robust-sum":515}],528:[function(_dereq_,module,exports){ -/* global window, exports, define */ - -!function() { - 'use strict' - - var re = { - not_string: /[^s]/, - not_bool: /[^t]/, - not_type: /[^T]/, - not_primitive: /[^v]/, - number: /[diefg]/, - numeric_arg: /[bcdiefguxX]/, - json: /[j]/, - not_json: /[^j]/, - text: /^[^\x25]+/, - modulo: /^\x25{2}/, - placeholder: /^\x25(?:([1-9]\d*)\$|\(([^)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/, - key: /^([a-z_][a-z_\d]*)/i, - key_access: /^\.([a-z_][a-z_\d]*)/i, - index_access: /^\[(\d+)\]/, - sign: /^[+-]/ - } - - function sprintf(key) { - // `arguments` is not an array, but should be fine for this call - return sprintf_format(sprintf_parse(key), arguments) - } - - function vsprintf(fmt, argv) { - return sprintf.apply(null, [fmt].concat(argv || [])) - } - - function sprintf_format(parse_tree, argv) { - var cursor = 1, tree_length = parse_tree.length, arg, output = '', i, k, ph, pad, pad_character, pad_length, is_positive, sign - for (i = 0; i < tree_length; i++) { - if (typeof parse_tree[i] === 'string') { - output += parse_tree[i] - } - else if (typeof parse_tree[i] === 'object') { - ph = parse_tree[i] // convenience purposes only - if (ph.keys) { // keyword argument - arg = argv[cursor] - for (k = 0; k < ph.keys.length; k++) { - if (arg == undefined) { - throw new Error(sprintf('[sprintf] Cannot access property "%s" of undefined value "%s"', ph.keys[k], ph.keys[k-1])) - } - arg = arg[ph.keys[k]] - } - } - else if (ph.param_no) { // positional argument (explicit) - arg = argv[ph.param_no] - } - else { // positional argument (implicit) - arg = argv[cursor++] - } - - if (re.not_type.test(ph.type) && re.not_primitive.test(ph.type) && arg instanceof Function) { - arg = arg() - } - - if (re.numeric_arg.test(ph.type) && (typeof arg !== 'number' && isNaN(arg))) { - throw new TypeError(sprintf('[sprintf] expecting number but found %T', arg)) - } - - if (re.number.test(ph.type)) { - is_positive = arg >= 0 - } - - switch (ph.type) { - case 'b': - arg = parseInt(arg, 10).toString(2) - break - case 'c': - arg = String.fromCharCode(parseInt(arg, 10)) - break - case 'd': - case 'i': - arg = parseInt(arg, 10) - break - case 'j': - arg = JSON.stringify(arg, null, ph.width ? parseInt(ph.width) : 0) - break - case 'e': - arg = ph.precision ? parseFloat(arg).toExponential(ph.precision) : parseFloat(arg).toExponential() - break - case 'f': - arg = ph.precision ? parseFloat(arg).toFixed(ph.precision) : parseFloat(arg) - break - case 'g': - arg = ph.precision ? String(Number(arg.toPrecision(ph.precision))) : parseFloat(arg) - break - case 'o': - arg = (parseInt(arg, 10) >>> 0).toString(8) - break - case 's': - arg = String(arg) - arg = (ph.precision ? arg.substring(0, ph.precision) : arg) - break - case 't': - arg = String(!!arg) - arg = (ph.precision ? arg.substring(0, ph.precision) : arg) - break - case 'T': - arg = Object.prototype.toString.call(arg).slice(8, -1).toLowerCase() - arg = (ph.precision ? arg.substring(0, ph.precision) : arg) - break - case 'u': - arg = parseInt(arg, 10) >>> 0 - break - case 'v': - arg = arg.valueOf() - arg = (ph.precision ? arg.substring(0, ph.precision) : arg) - break - case 'x': - arg = (parseInt(arg, 10) >>> 0).toString(16) - break - case 'X': - arg = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase() - break - } - if (re.json.test(ph.type)) { - output += arg - } - else { - if (re.number.test(ph.type) && (!is_positive || ph.sign)) { - sign = is_positive ? '+' : '-' - arg = arg.toString().replace(re.sign, '') - } - else { - sign = '' - } - pad_character = ph.pad_char ? ph.pad_char === '0' ? '0' : ph.pad_char.charAt(1) : ' ' - pad_length = ph.width - (sign + arg).length - pad = ph.width ? (pad_length > 0 ? pad_character.repeat(pad_length) : '') : '' - output += ph.align ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg) - } - } - } - return output - } - - var sprintf_cache = Object.create(null) - - function sprintf_parse(fmt) { - if (sprintf_cache[fmt]) { - return sprintf_cache[fmt] - } - - var _fmt = fmt, match, parse_tree = [], arg_names = 0 - while (_fmt) { - if ((match = re.text.exec(_fmt)) !== null) { - parse_tree.push(match[0]) - } - else if ((match = re.modulo.exec(_fmt)) !== null) { - parse_tree.push('%') - } - else if ((match = re.placeholder.exec(_fmt)) !== null) { - if (match[2]) { - arg_names |= 1 - var field_list = [], replacement_field = match[2], field_match = [] - if ((field_match = re.key.exec(replacement_field)) !== null) { - field_list.push(field_match[1]) - while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { - if ((field_match = re.key_access.exec(replacement_field)) !== null) { - field_list.push(field_match[1]) - } - else if ((field_match = re.index_access.exec(replacement_field)) !== null) { - field_list.push(field_match[1]) - } - else { - throw new SyntaxError('[sprintf] failed to parse named argument key') - } - } - } - else { - throw new SyntaxError('[sprintf] failed to parse named argument key') - } - match[2] = field_list - } - else { - arg_names |= 2 - } - if (arg_names === 3) { - throw new Error('[sprintf] mixing positional and named placeholders is not (yet) supported') - } - - parse_tree.push( - { - placeholder: match[0], - param_no: match[1], - keys: match[2], - sign: match[3], - pad_char: match[4], - align: match[5], - width: match[6], - precision: match[7], - type: match[8] - } - ) - } - else { - throw new SyntaxError('[sprintf] unexpected placeholder') - } - _fmt = _fmt.substring(match[0].length) - } - return sprintf_cache[fmt] = parse_tree - } - - /** - * export to either browser or node.js - */ - /* eslint-disable quote-props */ - if (typeof exports !== 'undefined') { - exports['sprintf'] = sprintf - exports['vsprintf'] = vsprintf - } - if (typeof window !== 'undefined') { - window['sprintf'] = sprintf - window['vsprintf'] = vsprintf - - if (typeof define === 'function' && define['amd']) { - define(function() { - return { - 'sprintf': sprintf, - 'vsprintf': vsprintf - } - }) - } - } - /* eslint-enable quote-props */ -}(); // eslint-disable-line - -},{}],529:[function(_dereq_,module,exports){ -'use strict' - -var paren = _dereq_('parenthesis') - -module.exports = function splitBy (string, separator, o) { - if (string == null) throw Error('First argument should be a string') - if (separator == null) throw Error('Separator should be a string or a RegExp') - - if (!o) o = {} - else if (typeof o === 'string' || Array.isArray(o)) { - o = {ignore: o} - } - - if (o.escape == null) o.escape = true - if (o.ignore == null) o.ignore = ['[]', '()', '{}', '<>', '""', "''", '``', '“”', '«»'] - else { - if (typeof o.ignore === 'string') {o.ignore = [o.ignore]} - - o.ignore = o.ignore.map(function (pair) { - // '"' → '""' - if (pair.length === 1) pair = pair + pair - return pair - }) - } - - var tokens = paren.parse(string, {flat: true, brackets: o.ignore}) - var str = tokens[0] - - var parts = str.split(separator) - - // join parts separated by escape - if (o.escape) { - var cleanParts = [] - for (var i = 0; i < parts.length; i++) { - var prev = parts[i] - var part = parts[i + 1] - - if (prev[prev.length - 1] === '\\' && prev[prev.length - 2] !== '\\') { - cleanParts.push(prev + separator + part) - i++ - } - else { - cleanParts.push(prev) - } - } - parts = cleanParts - } - - // open parens pack & apply unquotes, if any - for (var i = 0; i < parts.length; i++) { - tokens[0] = parts[i] - parts[i] = paren.stringify(tokens, {flat: true}) - } - - return parts -} - -},{"parenthesis":458}],530:[function(_dereq_,module,exports){ -"use strict" - -module.exports = stronglyConnectedComponents - -function stronglyConnectedComponents(adjList) { - var numVertices = adjList.length; - var index = new Array(numVertices) - var lowValue = new Array(numVertices) - var active = new Array(numVertices) - var child = new Array(numVertices) - var scc = new Array(numVertices) - var sccLinks = new Array(numVertices) - - //Initialize tables - for(var i=0; i 0) { - v = T[T.length-1] - var e = adjList[v] - if (child[v] < e.length) { // If we're not done iterating over the children, first try finishing that. - for(var i=child[v]; i= 0) { - // Node v is not yet assigned an scc, but once it is that scc can apparently reach scc[u]. - sccLinks[v].push(scc[u]) - } - } - child[v] = i // Remember where we left off. - } else { // If we're done iterating over the children, check whether we have an scc. - if(lowValue[v] === index[v]) { // TODO: It /might/ be true that T is always a prefix of S (at this point!!!), and if so, this could be used here. - var component = [] - var links = [], linkCount = 0 - for(var i=S.length-1; i>=0; --i) { - var w = S[i] - active[w] = false - component.push(w) - links.push(sccLinks[w]) - linkCount += sccLinks[w].length - scc[w] = components.length - if(w === v) { - S.length = i - break - } - } - components.push(component) - var allLinks = new Array(linkCount) - for(var i=0; i c)|0 },") - if(dtype === "generic") { - code.push("getters:[0],") - } - - //Generate vertex function - var cubeArgs = [] - var extraArgs = [] - for(var i=0; i>>7){") - } - for(var i=0; i<1<<(1< 128) { - if((i%128)===0) { - if(extraFuncs.length > 0) { - currentFunc.push("}}") - } - var efName = "vExtra" + extraFuncs.length - code.push("case ", (i>>>7), ":", efName, "(m&0x7f,", extraArgs.join(), ");break;") - currentFunc = [ - "function ", efName, "(m,", extraArgs.join(), "){switch(m){" - ] - extraFuncs.push(currentFunc) - } - } - currentFunc.push("case ", (i&0x7f), ":") - var crossings = new Array(dimension) - var denoms = new Array(dimension) - var crossingCount = new Array(dimension) - var bias = new Array(dimension) - var totalCrossings = 0 - for(var j=0; j j) { - continue - } - if(!(i&(1< 0) { - cStr = "+" + crossingCount[k] + "*c" - } - var weight = 0.5 * (crossings[k].length / totalCrossings) - var shift = 0.5 + 0.5 * (bias[k] / totalCrossings) - vertexStr.push("d" + k + "-" + shift + "-" + weight + "*(" + crossings[k].join("+") + cStr + ")/(" + denoms[k].join("+") + ")") - - } - } - currentFunc.push("a.push([", vertexStr.join(), "]);", - "break;") - } - code.push("}},") - if(extraFuncs.length > 0) { - currentFunc.push("}}") - } - - //Create face function - var faceArgs = [] - for(var i=0; i<(1<<(dimension-1)); ++i) { - faceArgs.push("v" + i) - } - faceArgs.push("c0", "c1", "p0", "p1", "a", "b", "c") - code.push("cell:function cellFunc(", faceArgs.join(), "){") - - var facets = triangulateCube(dimension-1) - code.push("if(p0){b.push(", - facets.map(function(f) { - return "[" + f.map(function(v) { - return "v" + v - }) + "]" - }).join(), ")}else{b.push(", - facets.map(function(f) { - var e = f.slice() - e.reverse() - return "[" + e.map(function(v) { - return "v" + v - }) + "]" - }).join(), - ")}}});function ", funcName, "(array,level){var verts=[],cells=[];contour(array,verts,cells,level);return {positions:verts,cells:cells};} return ", funcName, ";") - - for(var i=0; i 1) { - div = 1; - } - - if (div < -1) { - div = -1; - } - - return sign * Math.acos(div); -}; - -var getArcCenter = function getArcCenter(px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinphi, cosphi, pxp, pyp) { - var rxsq = Math.pow(rx, 2); - var rysq = Math.pow(ry, 2); - var pxpsq = Math.pow(pxp, 2); - var pypsq = Math.pow(pyp, 2); - - var radicant = rxsq * rysq - rxsq * pypsq - rysq * pxpsq; - - if (radicant < 0) { - radicant = 0; - } - - radicant /= rxsq * pypsq + rysq * pxpsq; - radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1); - - var centerxp = radicant * rx / ry * pyp; - var centeryp = radicant * -ry / rx * pxp; - - var centerx = cosphi * centerxp - sinphi * centeryp + (px + cx) / 2; - var centery = sinphi * centerxp + cosphi * centeryp + (py + cy) / 2; - - var vx1 = (pxp - centerxp) / rx; - var vy1 = (pyp - centeryp) / ry; - var vx2 = (-pxp - centerxp) / rx; - var vy2 = (-pyp - centeryp) / ry; - - var ang1 = vectorAngle(1, 0, vx1, vy1); - var ang2 = vectorAngle(vx1, vy1, vx2, vy2); - - if (sweepFlag === 0 && ang2 > 0) { - ang2 -= TAU; - } - - if (sweepFlag === 1 && ang2 < 0) { - ang2 += TAU; - } - - return [centerx, centery, ang1, ang2]; -}; - -var arcToBezier = function arcToBezier(_ref2) { - var px = _ref2.px, - py = _ref2.py, - cx = _ref2.cx, - cy = _ref2.cy, - rx = _ref2.rx, - ry = _ref2.ry, - _ref2$xAxisRotation = _ref2.xAxisRotation, - xAxisRotation = _ref2$xAxisRotation === undefined ? 0 : _ref2$xAxisRotation, - _ref2$largeArcFlag = _ref2.largeArcFlag, - largeArcFlag = _ref2$largeArcFlag === undefined ? 0 : _ref2$largeArcFlag, - _ref2$sweepFlag = _ref2.sweepFlag, - sweepFlag = _ref2$sweepFlag === undefined ? 0 : _ref2$sweepFlag; - - var curves = []; - - if (rx === 0 || ry === 0) { - return []; - } - - var sinphi = Math.sin(xAxisRotation * TAU / 360); - var cosphi = Math.cos(xAxisRotation * TAU / 360); - - var pxp = cosphi * (px - cx) / 2 + sinphi * (py - cy) / 2; - var pyp = -sinphi * (px - cx) / 2 + cosphi * (py - cy) / 2; - - if (pxp === 0 && pyp === 0) { - return []; - } - - rx = Math.abs(rx); - ry = Math.abs(ry); - - var lambda = Math.pow(pxp, 2) / Math.pow(rx, 2) + Math.pow(pyp, 2) / Math.pow(ry, 2); - - if (lambda > 1) { - rx *= Math.sqrt(lambda); - ry *= Math.sqrt(lambda); - } - - var _getArcCenter = getArcCenter(px, py, cx, cy, rx, ry, largeArcFlag, sweepFlag, sinphi, cosphi, pxp, pyp), - _getArcCenter2 = _slicedToArray(_getArcCenter, 4), - centerx = _getArcCenter2[0], - centery = _getArcCenter2[1], - ang1 = _getArcCenter2[2], - ang2 = _getArcCenter2[3]; - - // If 'ang2' == 90.0000000001, then `ratio` will evaluate to - // 1.0000000001. This causes `segments` to be greater than one, which is an - // unecessary split, and adds extra points to the bezier curve. To alleviate - // this issue, we round to 1.0 when the ratio is close to 1.0. - - - var ratio = Math.abs(ang2) / (TAU / 4); - if (Math.abs(1.0 - ratio) < 0.0000001) { - ratio = 1.0; - } - - var segments = Math.max(Math.ceil(ratio), 1); - - ang2 /= segments; - - for (var i = 0; i < segments; i++) { - curves.push(approxUnitArc(ang1, ang2)); - ang1 += ang2; - } - - return curves.map(function (curve) { - var _mapToEllipse = mapToEllipse(curve[0], rx, ry, cosphi, sinphi, centerx, centery), - x1 = _mapToEllipse.x, - y1 = _mapToEllipse.y; - - var _mapToEllipse2 = mapToEllipse(curve[1], rx, ry, cosphi, sinphi, centerx, centery), - x2 = _mapToEllipse2.x, - y2 = _mapToEllipse2.y; - - var _mapToEllipse3 = mapToEllipse(curve[2], rx, ry, cosphi, sinphi, centerx, centery), - x = _mapToEllipse3.x, - y = _mapToEllipse3.y; - - return { x1: x1, y1: y1, x2: x2, y2: y2, x: x, y: y }; - }); -}; - -exports.default = arcToBezier; -module.exports = exports.default; -},{}],533:[function(_dereq_,module,exports){ -'use strict' - -var parse = _dereq_('parse-svg-path') -var abs = _dereq_('abs-svg-path') -var normalize = _dereq_('normalize-svg-path') -var isSvgPath = _dereq_('is-svg-path') -var assert = _dereq_('assert') - -module.exports = pathBounds - - -function pathBounds(path) { - // ES6 string tpl call - if (Array.isArray(path) && path.length === 1 && typeof path[0] === 'string') path = path[0] - - // svg path string - if (typeof path === 'string') { - assert(isSvgPath(path), 'String is not an SVG path.') - path = parse(path) - } - - assert(Array.isArray(path), 'Argument should be a string or an array of path segments.') - - path = abs(path) - path = normalize(path) - - if (!path.length) return [0, 0, 0, 0] - - var bounds = [Infinity, Infinity, -Infinity, -Infinity] - - for (var i = 0, l = path.length; i < l; i++) { - var points = path[i].slice(1) - - for (var j = 0; j < points.length; j += 2) { - if (points[j + 0] < bounds[0]) bounds[0] = points[j + 0] - if (points[j + 1] < bounds[1]) bounds[1] = points[j + 1] - if (points[j + 0] > bounds[2]) bounds[2] = points[j + 0] - if (points[j + 1] > bounds[3]) bounds[3] = points[j + 1] - } - } - - return bounds -} - -},{"abs-svg-path":60,"assert":68,"is-svg-path":424,"normalize-svg-path":534,"parse-svg-path":460}],534:[function(_dereq_,module,exports){ -'use strict' - -module.exports = normalize - -var arcToCurve = _dereq_('svg-arc-to-cubic-bezier') - -function normalize(path){ - // init state - var prev - var result = [] - var bezierX = 0 - var bezierY = 0 - var startX = 0 - var startY = 0 - var quadX = null - var quadY = null - var x = 0 - var y = 0 - - for (var i = 0, len = path.length; i < len; i++) { - var seg = path[i] - var command = seg[0] - - switch (command) { - case 'M': - startX = seg[1] - startY = seg[2] - break - case 'A': - var curves = arcToCurve({ - px: x, - py: y, - cx: seg[6], - cy: seg[7], - rx: seg[1], - ry: seg[2], - xAxisRotation: seg[3], - largeArcFlag: seg[4], - sweepFlag: seg[5] - }) - - // null-curves - if (!curves.length) continue - - for (var j = 0, c; j < curves.length; j++) { - c = curves[j] - seg = ['C', c.x1, c.y1, c.x2, c.y2, c.x, c.y] - if (j < curves.length - 1) result.push(seg) - } - - break - case 'S': - // default control point - var cx = x - var cy = y - if (prev == 'C' || prev == 'S') { - cx += cx - bezierX // reflect the previous command's control - cy += cy - bezierY // point relative to the current point - } - seg = ['C', cx, cy, seg[1], seg[2], seg[3], seg[4]] - break - case 'T': - if (prev == 'Q' || prev == 'T') { - quadX = x * 2 - quadX // as with 'S' reflect previous control point - quadY = y * 2 - quadY - } else { - quadX = x - quadY = y - } - seg = quadratic(x, y, quadX, quadY, seg[1], seg[2]) - break - case 'Q': - quadX = seg[1] - quadY = seg[2] - seg = quadratic(x, y, seg[1], seg[2], seg[3], seg[4]) - break - case 'L': - seg = line(x, y, seg[1], seg[2]) - break - case 'H': - seg = line(x, y, seg[1], y) - break - case 'V': - seg = line(x, y, x, seg[1]) - break - case 'Z': - seg = line(x, y, startX, startY) - break - } - - // update state - prev = command - x = seg[seg.length - 2] - y = seg[seg.length - 1] - if (seg.length > 4) { - bezierX = seg[seg.length - 4] - bezierY = seg[seg.length - 3] - } else { - bezierX = x - bezierY = y - } - result.push(seg) - } - - return result -} - -function line(x1, y1, x2, y2){ - return ['C', x1, y1, x2, y2, x2, y2] -} - -function quadratic(x1, y1, cx, cy, x2, y2){ - return [ - 'C', - x1/3 + (2/3) * cx, - y1/3 + (2/3) * cy, - x2/3 + (2/3) * cx, - y2/3 + (2/3) * cy, - x2, - y2 - ] -} - -},{"svg-arc-to-cubic-bezier":532}],535:[function(_dereq_,module,exports){ -'use strict' - -var pathBounds = _dereq_('svg-path-bounds') -var parsePath = _dereq_('parse-svg-path') -var drawPath = _dereq_('draw-svg-path') -var isSvgPath = _dereq_('is-svg-path') -var bitmapSdf = _dereq_('bitmap-sdf') - -var canvas = document.createElement('canvas') -var ctx = canvas.getContext('2d') - - -module.exports = pathSdf - - -function pathSdf (path, options) { - if (!isSvgPath(path)) throw Error('Argument should be valid svg path string') - - if (!options) options = {} - - var w, h - if (options.shape) { - w = options.shape[0] - h = options.shape[1] - } - else { - w = canvas.width = options.w || options.width || 200 - h = canvas.height = options.h || options.height || 200 - } - var size = Math.min(w, h) - - var stroke = options.stroke || 0 - - var viewbox = options.viewbox || options.viewBox || pathBounds(path) - var scale = [w / (viewbox[2] - viewbox[0]), h / (viewbox[3] - viewbox[1])] - var maxScale = Math.min(scale[0] || 0, scale[1] || 0) / 2 - - //clear ctx - ctx.fillStyle = 'black' - ctx.fillRect(0, 0, w, h) - - ctx.fillStyle = 'white' - - if (stroke) { - if (typeof stroke != 'number') stroke = 1 - if (stroke > 0) { - ctx.strokeStyle = 'white' - } - else { - ctx.strokeStyle = 'black' - } - - ctx.lineWidth = Math.abs(stroke) - } - - ctx.translate(w * .5, h * .5) - ctx.scale(maxScale, maxScale) - - //if canvas svg paths api is available - if (isPath2DSupported()) { - var path2d = new Path2D(path) - ctx.fill(path2d) - stroke && ctx.stroke(path2d) - } - //fallback to bezier-curves - else { - var segments = parsePath(path) - drawPath(ctx, segments) - ctx.fill() - stroke && ctx.stroke() - } - - ctx.setTransform(1, 0, 0, 1, 0, 0); - - var data = bitmapSdf(ctx, { - cutoff: options.cutoff != null ? options.cutoff : .5, - radius: options.radius != null ? options.radius : size * .5 - }) - - return data -} - -var path2DSupported - -function isPath2DSupported () { - if (path2DSupported != null) return path2DSupported - - var ctx = document.createElement('canvas').getContext('2d') - ctx.canvas.width = ctx.canvas.height = 1 - - if (!window.Path2D) return path2DSupported = false - - var path = new Path2D('M0,0h1v1h-1v-1Z') - - ctx.fillStyle = 'black' - ctx.fill(path) - - var idata = ctx.getImageData(0,0,1,1) - - return path2DSupported = idata && idata.data && idata.data[3] === 255 -} - -},{"bitmap-sdf":93,"draw-svg-path":168,"is-svg-path":424,"parse-svg-path":460,"svg-path-bounds":533}],536:[function(_dereq_,module,exports){ -(function (process){ -'use strict' - -module.exports = textGet - -var vectorizeText = _dereq_('vectorize-text') - -var globals = window || process.global || {} -var __TEXT_CACHE = globals.__TEXT_CACHE || {} -globals.__TEXT_CACHE = {} - -function unwrap(mesh) { - var cells = mesh.cells - var positions = mesh.positions - var data = new Float32Array(cells.length * 6) - var ptr = 0 - var shapeX = 0 - for(var i=0; i0) { - shapeX += 0.02 - } - } - - var data = new Float32Array(bufferSize) - var ptr = 0 - var xOffset = -0.5 * shapeX - for(var i=0; i= 0; - var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name"); - - if (needsAlphaFormat) { - // Special case for "transparent", all other non-alpha formats - // will return rgba when there is transparency. - if (format === "name" && this._a === 0) { - return this.toName(); - } - return this.toRgbString(); - } - if (format === "rgb") { - formattedString = this.toRgbString(); - } - if (format === "prgb") { - formattedString = this.toPercentageRgbString(); - } - if (format === "hex" || format === "hex6") { - formattedString = this.toHexString(); - } - if (format === "hex3") { - formattedString = this.toHexString(true); - } - if (format === "hex4") { - formattedString = this.toHex8String(true); - } - if (format === "hex8") { - formattedString = this.toHex8String(); - } - if (format === "name") { - formattedString = this.toName(); - } - if (format === "hsl") { - formattedString = this.toHslString(); - } - if (format === "hsv") { - formattedString = this.toHsvString(); - } - - return formattedString || this.toHexString(); - }, - clone: function() { - return tinycolor(this.toString()); - }, - - _applyModification: function(fn, args) { - var color = fn.apply(null, [this].concat([].slice.call(args))); - this._r = color._r; - this._g = color._g; - this._b = color._b; - this.setAlpha(color._a); - return this; - }, - lighten: function() { - return this._applyModification(lighten, arguments); - }, - brighten: function() { - return this._applyModification(brighten, arguments); - }, - darken: function() { - return this._applyModification(darken, arguments); - }, - desaturate: function() { - return this._applyModification(desaturate, arguments); - }, - saturate: function() { - return this._applyModification(saturate, arguments); - }, - greyscale: function() { - return this._applyModification(greyscale, arguments); - }, - spin: function() { - return this._applyModification(spin, arguments); - }, - - _applyCombination: function(fn, args) { - return fn.apply(null, [this].concat([].slice.call(args))); - }, - analogous: function() { - return this._applyCombination(analogous, arguments); - }, - complement: function() { - return this._applyCombination(complement, arguments); - }, - monochromatic: function() { - return this._applyCombination(monochromatic, arguments); - }, - splitcomplement: function() { - return this._applyCombination(splitcomplement, arguments); - }, - triad: function() { - return this._applyCombination(triad, arguments); - }, - tetrad: function() { - return this._applyCombination(tetrad, arguments); - } -}; - -// If input is an object, force 1 into "1.0" to handle ratios properly -// String input requires "1.0" as input, so 1 will be treated as 1 -tinycolor.fromRatio = function(color, opts) { - if (typeof color == "object") { - var newColor = {}; - for (var i in color) { - if (color.hasOwnProperty(i)) { - if (i === "a") { - newColor[i] = color[i]; - } - else { - newColor[i] = convertToPercentage(color[i]); - } - } - } - color = newColor; - } - - return tinycolor(color, opts); -}; - -// Given a string or object, convert that input to RGB -// Possible string inputs: -// -// "red" -// "#f00" or "f00" -// "#ff0000" or "ff0000" -// "#ff000000" or "ff000000" -// "rgb 255 0 0" or "rgb (255, 0, 0)" -// "rgb 1.0 0 0" or "rgb (1, 0, 0)" -// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" -// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" -// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" -// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" -// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" -// -function inputToRGB(color) { - - var rgb = { r: 0, g: 0, b: 0 }; - var a = 1; - var s = null; - var v = null; - var l = null; - var ok = false; - var format = false; - - if (typeof color == "string") { - color = stringInputToObject(color); - } - - if (typeof color == "object") { - if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) { - rgb = rgbToRgb(color.r, color.g, color.b); - ok = true; - format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; - } - else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) { - s = convertToPercentage(color.s); - v = convertToPercentage(color.v); - rgb = hsvToRgb(color.h, s, v); - ok = true; - format = "hsv"; - } - else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) { - s = convertToPercentage(color.s); - l = convertToPercentage(color.l); - rgb = hslToRgb(color.h, s, l); - ok = true; - format = "hsl"; - } - - if (color.hasOwnProperty("a")) { - a = color.a; - } - } - - a = boundAlpha(a); - - return { - ok: ok, - format: color.format || format, - r: mathMin(255, mathMax(rgb.r, 0)), - g: mathMin(255, mathMax(rgb.g, 0)), - b: mathMin(255, mathMax(rgb.b, 0)), - a: a - }; -} - - -// Conversion Functions -// -------------------- - -// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: -// - -// `rgbToRgb` -// Handle bounds / percentage checking to conform to CSS color spec -// -// *Assumes:* r, g, b in [0, 255] or [0, 1] -// *Returns:* { r, g, b } in [0, 255] -function rgbToRgb(r, g, b){ - return { - r: bound01(r, 255) * 255, - g: bound01(g, 255) * 255, - b: bound01(b, 255) * 255 - }; -} - -// `rgbToHsl` -// Converts an RGB color value to HSL. -// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] -// *Returns:* { h, s, l } in [0,1] -function rgbToHsl(r, g, b) { - - r = bound01(r, 255); - g = bound01(g, 255); - b = bound01(b, 255); - - var max = mathMax(r, g, b), min = mathMin(r, g, b); - var h, s, l = (max + min) / 2; - - if(max == min) { - h = s = 0; // achromatic - } - else { - var d = max - min; - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - switch(max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - - h /= 6; - } - - return { h: h, s: s, l: l }; -} - -// `hslToRgb` -// Converts an HSL color value to RGB. -// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] -// *Returns:* { r, g, b } in the set [0, 255] -function hslToRgb(h, s, l) { - var r, g, b; - - h = bound01(h, 360); - s = bound01(s, 100); - l = bound01(l, 100); - - function hue2rgb(p, q, t) { - if(t < 0) t += 1; - if(t > 1) t -= 1; - if(t < 1/6) return p + (q - p) * 6 * t; - if(t < 1/2) return q; - if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; - return p; - } - - if(s === 0) { - r = g = b = l; // achromatic - } - else { - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1/3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1/3); - } - - return { r: r * 255, g: g * 255, b: b * 255 }; -} - -// `rgbToHsv` -// Converts an RGB color value to HSV -// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] -// *Returns:* { h, s, v } in [0,1] -function rgbToHsv(r, g, b) { - - r = bound01(r, 255); - g = bound01(g, 255); - b = bound01(b, 255); - - var max = mathMax(r, g, b), min = mathMin(r, g, b); - var h, s, v = max; - - var d = max - min; - s = max === 0 ? 0 : d / max; - - if(max == min) { - h = 0; // achromatic - } - else { - switch(max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h, s: s, v: v }; -} - -// `hsvToRgb` -// Converts an HSV color value to RGB. -// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] -// *Returns:* { r, g, b } in the set [0, 255] - function hsvToRgb(h, s, v) { - - h = bound01(h, 360) * 6; - s = bound01(s, 100); - v = bound01(v, 100); - - var i = Math.floor(h), - f = h - i, - p = v * (1 - s), - q = v * (1 - f * s), - t = v * (1 - (1 - f) * s), - mod = i % 6, - r = [v, q, p, p, t, v][mod], - g = [t, v, v, q, p, p][mod], - b = [p, p, t, v, v, q][mod]; - - return { r: r * 255, g: g * 255, b: b * 255 }; -} - -// `rgbToHex` -// Converts an RGB color to hex -// Assumes r, g, and b are contained in the set [0, 255] -// Returns a 3 or 6 character hex -function rgbToHex(r, g, b, allow3Char) { - - var hex = [ - pad2(mathRound(r).toString(16)), - pad2(mathRound(g).toString(16)), - pad2(mathRound(b).toString(16)) - ]; - - // Return a 3 character hex if possible - if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { - return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); - } - - return hex.join(""); -} - -// `rgbaToHex` -// Converts an RGBA color plus alpha transparency to hex -// Assumes r, g, b are contained in the set [0, 255] and -// a in [0, 1]. Returns a 4 or 8 character rgba hex -function rgbaToHex(r, g, b, a, allow4Char) { - - var hex = [ - pad2(mathRound(r).toString(16)), - pad2(mathRound(g).toString(16)), - pad2(mathRound(b).toString(16)), - pad2(convertDecimalToHex(a)) - ]; - - // Return a 4 character hex if possible - if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) { - return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0); - } - - return hex.join(""); -} - -// `rgbaToArgbHex` -// Converts an RGBA color to an ARGB Hex8 string -// Rarely used, but required for "toFilter()" -function rgbaToArgbHex(r, g, b, a) { - - var hex = [ - pad2(convertDecimalToHex(a)), - pad2(mathRound(r).toString(16)), - pad2(mathRound(g).toString(16)), - pad2(mathRound(b).toString(16)) - ]; - - return hex.join(""); -} - -// `equals` -// Can be called with any tinycolor input -tinycolor.equals = function (color1, color2) { - if (!color1 || !color2) { return false; } - return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); -}; - -tinycolor.random = function() { - return tinycolor.fromRatio({ - r: mathRandom(), - g: mathRandom(), - b: mathRandom() - }); -}; - - -// Modification Functions -// ---------------------- -// Thanks to less.js for some of the basics here -// - -function desaturate(color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var hsl = tinycolor(color).toHsl(); - hsl.s -= amount / 100; - hsl.s = clamp01(hsl.s); - return tinycolor(hsl); -} - -function saturate(color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var hsl = tinycolor(color).toHsl(); - hsl.s += amount / 100; - hsl.s = clamp01(hsl.s); - return tinycolor(hsl); -} - -function greyscale(color) { - return tinycolor(color).desaturate(100); -} - -function lighten (color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var hsl = tinycolor(color).toHsl(); - hsl.l += amount / 100; - hsl.l = clamp01(hsl.l); - return tinycolor(hsl); -} - -function brighten(color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var rgb = tinycolor(color).toRgb(); - rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100)))); - rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100)))); - rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100)))); - return tinycolor(rgb); -} - -function darken (color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var hsl = tinycolor(color).toHsl(); - hsl.l -= amount / 100; - hsl.l = clamp01(hsl.l); - return tinycolor(hsl); -} - -// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. -// Values outside of this range will be wrapped into this range. -function spin(color, amount) { - var hsl = tinycolor(color).toHsl(); - var hue = (hsl.h + amount) % 360; - hsl.h = hue < 0 ? 360 + hue : hue; - return tinycolor(hsl); -} - -// Combination Functions -// --------------------- -// Thanks to jQuery xColor for some of the ideas behind these -// - -function complement(color) { - var hsl = tinycolor(color).toHsl(); - hsl.h = (hsl.h + 180) % 360; - return tinycolor(hsl); -} - -function triad(color) { - var hsl = tinycolor(color).toHsl(); - var h = hsl.h; - return [ - tinycolor(color), - tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), - tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) - ]; -} - -function tetrad(color) { - var hsl = tinycolor(color).toHsl(); - var h = hsl.h; - return [ - tinycolor(color), - tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), - tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), - tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) - ]; -} - -function splitcomplement(color) { - var hsl = tinycolor(color).toHsl(); - var h = hsl.h; - return [ - tinycolor(color), - tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), - tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) - ]; -} - -function analogous(color, results, slices) { - results = results || 6; - slices = slices || 30; - - var hsl = tinycolor(color).toHsl(); - var part = 360 / slices; - var ret = [tinycolor(color)]; - - for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { - hsl.h = (hsl.h + part) % 360; - ret.push(tinycolor(hsl)); - } - return ret; -} - -function monochromatic(color, results) { - results = results || 6; - var hsv = tinycolor(color).toHsv(); - var h = hsv.h, s = hsv.s, v = hsv.v; - var ret = []; - var modification = 1 / results; - - while (results--) { - ret.push(tinycolor({ h: h, s: s, v: v})); - v = (v + modification) % 1; - } - - return ret; -} - -// Utility Functions -// --------------------- - -tinycolor.mix = function(color1, color2, amount) { - amount = (amount === 0) ? 0 : (amount || 50); - - var rgb1 = tinycolor(color1).toRgb(); - var rgb2 = tinycolor(color2).toRgb(); - - var p = amount / 100; - - var rgba = { - r: ((rgb2.r - rgb1.r) * p) + rgb1.r, - g: ((rgb2.g - rgb1.g) * p) + rgb1.g, - b: ((rgb2.b - rgb1.b) * p) + rgb1.b, - a: ((rgb2.a - rgb1.a) * p) + rgb1.a - }; - - return tinycolor(rgba); -}; - - -// Readability Functions -// --------------------- -// false -// tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false -tinycolor.isReadable = function(color1, color2, wcag2) { - var readability = tinycolor.readability(color1, color2); - var wcag2Parms, out; - - out = false; - - wcag2Parms = validateWCAG2Parms(wcag2); - switch (wcag2Parms.level + wcag2Parms.size) { - case "AAsmall": - case "AAAlarge": - out = readability >= 4.5; - break; - case "AAlarge": - out = readability >= 3; - break; - case "AAAsmall": - out = readability >= 7; - break; - } - return out; - -}; - -// `mostReadable` -// Given a base color and a list of possible foreground or background -// colors for that base, returns the most readable color. -// Optionally returns Black or White if the most readable color is unreadable. -// *Example* -// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255" -// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff" -// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3" -// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff" -tinycolor.mostReadable = function(baseColor, colorList, args) { - var bestColor = null; - var bestScore = 0; - var readability; - var includeFallbackColors, level, size ; - args = args || {}; - includeFallbackColors = args.includeFallbackColors ; - level = args.level; - size = args.size; - - for (var i= 0; i < colorList.length ; i++) { - readability = tinycolor.readability(baseColor, colorList[i]); - if (readability > bestScore) { - bestScore = readability; - bestColor = tinycolor(colorList[i]); - } - } - - if (tinycolor.isReadable(baseColor, bestColor, {"level":level,"size":size}) || !includeFallbackColors) { - return bestColor; - } - else { - args.includeFallbackColors=false; - return tinycolor.mostReadable(baseColor,["#fff", "#000"],args); - } -}; - - -// Big List of Colors -// ------------------ -// -var names = tinycolor.names = { - aliceblue: "f0f8ff", - antiquewhite: "faebd7", - aqua: "0ff", - aquamarine: "7fffd4", - azure: "f0ffff", - beige: "f5f5dc", - bisque: "ffe4c4", - black: "000", - blanchedalmond: "ffebcd", - blue: "00f", - blueviolet: "8a2be2", - brown: "a52a2a", - burlywood: "deb887", - burntsienna: "ea7e5d", - cadetblue: "5f9ea0", - chartreuse: "7fff00", - chocolate: "d2691e", - coral: "ff7f50", - cornflowerblue: "6495ed", - cornsilk: "fff8dc", - crimson: "dc143c", - cyan: "0ff", - darkblue: "00008b", - darkcyan: "008b8b", - darkgoldenrod: "b8860b", - darkgray: "a9a9a9", - darkgreen: "006400", - darkgrey: "a9a9a9", - darkkhaki: "bdb76b", - darkmagenta: "8b008b", - darkolivegreen: "556b2f", - darkorange: "ff8c00", - darkorchid: "9932cc", - darkred: "8b0000", - darksalmon: "e9967a", - darkseagreen: "8fbc8f", - darkslateblue: "483d8b", - darkslategray: "2f4f4f", - darkslategrey: "2f4f4f", - darkturquoise: "00ced1", - darkviolet: "9400d3", - deeppink: "ff1493", - deepskyblue: "00bfff", - dimgray: "696969", - dimgrey: "696969", - dodgerblue: "1e90ff", - firebrick: "b22222", - floralwhite: "fffaf0", - forestgreen: "228b22", - fuchsia: "f0f", - gainsboro: "dcdcdc", - ghostwhite: "f8f8ff", - gold: "ffd700", - goldenrod: "daa520", - gray: "808080", - green: "008000", - greenyellow: "adff2f", - grey: "808080", - honeydew: "f0fff0", - hotpink: "ff69b4", - indianred: "cd5c5c", - indigo: "4b0082", - ivory: "fffff0", - khaki: "f0e68c", - lavender: "e6e6fa", - lavenderblush: "fff0f5", - lawngreen: "7cfc00", - lemonchiffon: "fffacd", - lightblue: "add8e6", - lightcoral: "f08080", - lightcyan: "e0ffff", - lightgoldenrodyellow: "fafad2", - lightgray: "d3d3d3", - lightgreen: "90ee90", - lightgrey: "d3d3d3", - lightpink: "ffb6c1", - lightsalmon: "ffa07a", - lightseagreen: "20b2aa", - lightskyblue: "87cefa", - lightslategray: "789", - lightslategrey: "789", - lightsteelblue: "b0c4de", - lightyellow: "ffffe0", - lime: "0f0", - limegreen: "32cd32", - linen: "faf0e6", - magenta: "f0f", - maroon: "800000", - mediumaquamarine: "66cdaa", - mediumblue: "0000cd", - mediumorchid: "ba55d3", - mediumpurple: "9370db", - mediumseagreen: "3cb371", - mediumslateblue: "7b68ee", - mediumspringgreen: "00fa9a", - mediumturquoise: "48d1cc", - mediumvioletred: "c71585", - midnightblue: "191970", - mintcream: "f5fffa", - mistyrose: "ffe4e1", - moccasin: "ffe4b5", - navajowhite: "ffdead", - navy: "000080", - oldlace: "fdf5e6", - olive: "808000", - olivedrab: "6b8e23", - orange: "ffa500", - orangered: "ff4500", - orchid: "da70d6", - palegoldenrod: "eee8aa", - palegreen: "98fb98", - paleturquoise: "afeeee", - palevioletred: "db7093", - papayawhip: "ffefd5", - peachpuff: "ffdab9", - peru: "cd853f", - pink: "ffc0cb", - plum: "dda0dd", - powderblue: "b0e0e6", - purple: "800080", - rebeccapurple: "663399", - red: "f00", - rosybrown: "bc8f8f", - royalblue: "4169e1", - saddlebrown: "8b4513", - salmon: "fa8072", - sandybrown: "f4a460", - seagreen: "2e8b57", - seashell: "fff5ee", - sienna: "a0522d", - silver: "c0c0c0", - skyblue: "87ceeb", - slateblue: "6a5acd", - slategray: "708090", - slategrey: "708090", - snow: "fffafa", - springgreen: "00ff7f", - steelblue: "4682b4", - tan: "d2b48c", - teal: "008080", - thistle: "d8bfd8", - tomato: "ff6347", - turquoise: "40e0d0", - violet: "ee82ee", - wheat: "f5deb3", - white: "fff", - whitesmoke: "f5f5f5", - yellow: "ff0", - yellowgreen: "9acd32" -}; - -// Make it easy to access colors via `hexNames[hex]` -var hexNames = tinycolor.hexNames = flip(names); - - -// Utilities -// --------- - -// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` -function flip(o) { - var flipped = { }; - for (var i in o) { - if (o.hasOwnProperty(i)) { - flipped[o[i]] = i; - } - } - return flipped; -} - -// Return a valid alpha value [0,1] with all invalid values being set to 1 -function boundAlpha(a) { - a = parseFloat(a); - - if (isNaN(a) || a < 0 || a > 1) { - a = 1; - } - - return a; -} - -// Take input from [0, n] and return it as [0, 1] -function bound01(n, max) { - if (isOnePointZero(n)) { n = "100%"; } - - var processPercent = isPercentage(n); - n = mathMin(max, mathMax(0, parseFloat(n))); - - // Automatically convert percentage into number - if (processPercent) { - n = parseInt(n * max, 10) / 100; - } - - // Handle floating point rounding errors - if ((Math.abs(n - max) < 0.000001)) { - return 1; - } - - // Convert into [0, 1] range if it isn't already - return (n % max) / parseFloat(max); -} - -// Force a number between 0 and 1 -function clamp01(val) { - return mathMin(1, mathMax(0, val)); -} - -// Parse a base-16 hex value into a base-10 integer -function parseIntFromHex(val) { - return parseInt(val, 16); -} - -// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 -// -function isOnePointZero(n) { - return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; -} - -// Check to see if string passed in is a percentage -function isPercentage(n) { - return typeof n === "string" && n.indexOf('%') != -1; -} - -// Force a hex value to have 2 characters -function pad2(c) { - return c.length == 1 ? '0' + c : '' + c; -} - -// Replace a decimal with it's percentage value -function convertToPercentage(n) { - if (n <= 1) { - n = (n * 100) + "%"; - } - - return n; -} - -// Converts a decimal to a hex value -function convertDecimalToHex(d) { - return Math.round(parseFloat(d) * 255).toString(16); -} -// Converts a hex value to a decimal -function convertHexToDecimal(h) { - return (parseIntFromHex(h) / 255); -} - -var matchers = (function() { - - // - var CSS_INTEGER = "[-\\+]?\\d+%?"; - - // - var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; - - // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. - var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; - - // Actual matching. - // Parentheses and commas are optional, but not required. - // Whitespace can take the place of commas or opening paren - var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; - var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; - - return { - CSS_UNIT: new RegExp(CSS_UNIT), - rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), - rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), - hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), - hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), - hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), - hsva: new RegExp("hsva" + PERMISSIVE_MATCH4), - hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, - hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, - hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, - hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ - }; -})(); - -// `isValidCSSUnit` -// Take in a single string / number and check to see if it looks like a CSS unit -// (see `matchers` above for definition). -function isValidCSSUnit(color) { - return !!matchers.CSS_UNIT.exec(color); -} - -// `stringInputToObject` -// Permissive string parsing. Take in a number of formats, and output an object -// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` -function stringInputToObject(color) { - - color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); - var named = false; - if (names[color]) { - color = names[color]; - named = true; - } - else if (color == 'transparent') { - return { r: 0, g: 0, b: 0, a: 0, format: "name" }; - } - - // Try to match string input using regular expressions. - // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] - // Just return an object and let the conversion functions handle that. - // This way the result will be the same whether the tinycolor is initialized with string or object. - var match; - if ((match = matchers.rgb.exec(color))) { - return { r: match[1], g: match[2], b: match[3] }; - } - if ((match = matchers.rgba.exec(color))) { - return { r: match[1], g: match[2], b: match[3], a: match[4] }; - } - if ((match = matchers.hsl.exec(color))) { - return { h: match[1], s: match[2], l: match[3] }; - } - if ((match = matchers.hsla.exec(color))) { - return { h: match[1], s: match[2], l: match[3], a: match[4] }; - } - if ((match = matchers.hsv.exec(color))) { - return { h: match[1], s: match[2], v: match[3] }; - } - if ((match = matchers.hsva.exec(color))) { - return { h: match[1], s: match[2], v: match[3], a: match[4] }; - } - if ((match = matchers.hex8.exec(color))) { - return { - r: parseIntFromHex(match[1]), - g: parseIntFromHex(match[2]), - b: parseIntFromHex(match[3]), - a: convertHexToDecimal(match[4]), - format: named ? "name" : "hex8" - }; - } - if ((match = matchers.hex6.exec(color))) { - return { - r: parseIntFromHex(match[1]), - g: parseIntFromHex(match[2]), - b: parseIntFromHex(match[3]), - format: named ? "name" : "hex" - }; - } - if ((match = matchers.hex4.exec(color))) { - return { - r: parseIntFromHex(match[1] + '' + match[1]), - g: parseIntFromHex(match[2] + '' + match[2]), - b: parseIntFromHex(match[3] + '' + match[3]), - a: convertHexToDecimal(match[4] + '' + match[4]), - format: named ? "name" : "hex8" - }; - } - if ((match = matchers.hex3.exec(color))) { - return { - r: parseIntFromHex(match[1] + '' + match[1]), - g: parseIntFromHex(match[2] + '' + match[2]), - b: parseIntFromHex(match[3] + '' + match[3]), - format: named ? "name" : "hex" - }; - } - - return false; -} - -function validateWCAG2Parms(parms) { - // return valid WCAG2 parms for isReadable. - // If input parms are invalid, return {"level":"AA", "size":"small"} - var level, size; - parms = parms || {"level":"AA", "size":"small"}; - level = (parms.level || "AA").toUpperCase(); - size = (parms.size || "small").toLowerCase(); - if (level !== "AA" && level !== "AAA") { - level = "AA"; - } - if (size !== "small" && size !== "large") { - size = "small"; - } - return {"level":level, "size":size}; -} - -// Node: Export function -if (typeof module !== "undefined" && module.exports) { - module.exports = tinycolor; -} -// AMD/requirejs: Define the module -else if (typeof define === 'function' && define.amd) { - define(function () {return tinycolor;}); -} -// Browser: Expose to window -else { - window.tinycolor = tinycolor; -} - -})(Math); - -},{}],538:[function(_dereq_,module,exports){ -/* @module to-float32 */ - -'use strict' - -module.exports = float32 -module.exports.float32 = -module.exports.float = float32 -module.exports.fract32 = -module.exports.fract = fract32 - -var narr = new Float32Array(1) - -// return fractional part of float32 array -function fract32 (arr) { - if (arr.length) { - var fract = float32(arr) - for (var i = 0, l = fract.length; i < l; i++) { - fract[i] = arr[i] - fract[i] - } - return fract - } - - // number - return float32(arr - float32(arr)) -} - -// make sure data is float32 array -function float32 (arr) { - if (arr.length) { - if (arr instanceof Float32Array) return arr - var float = new Float32Array(arr) - float.set(arr) - return float - } - - // number - narr[0] = arr - return narr[0] -} - -},{}],539:[function(_dereq_,module,exports){ -'use strict' - -var parseUnit = _dereq_('parse-unit') - -module.exports = toPX - -var PIXELS_PER_INCH = 96 - -function getPropertyInPX(element, prop) { - var parts = parseUnit(getComputedStyle(element).getPropertyValue(prop)) - return parts[0] * toPX(parts[1], element) -} - -//This brutal hack is needed -function getSizeBrutal(unit, element) { - var testDIV = document.createElement('div') - testDIV.style['font-size'] = '128' + unit - element.appendChild(testDIV) - var size = getPropertyInPX(testDIV, 'font-size') / 128 - element.removeChild(testDIV) - return size -} - -function toPX(str, element) { - element = element || document.body - str = (str || 'px').trim().toLowerCase() - if(element === window || element === document) { - element = document.body - } - switch(str) { - case '%': //Ambiguous, not sure if we should use width or height - return element.clientHeight / 100.0 - case 'ch': - case 'ex': - return getSizeBrutal(str, element) - case 'em': - return getPropertyInPX(element, 'font-size') - case 'rem': - return getPropertyInPX(document.body, 'font-size') - case 'vw': - return window.innerWidth/100 - case 'vh': - return window.innerHeight/100 - case 'vmin': - return Math.min(window.innerWidth, window.innerHeight) / 100 - case 'vmax': - return Math.max(window.innerWidth, window.innerHeight) / 100 - case 'in': - return PIXELS_PER_INCH - case 'cm': - return PIXELS_PER_INCH / 2.54 - case 'mm': - return PIXELS_PER_INCH / 25.4 - case 'pt': - return PIXELS_PER_INCH / 72 - case 'pc': - return PIXELS_PER_INCH / 6 - } - return 1 -} -},{"parse-unit":461}],540:[function(_dereq_,module,exports){ -// https://github.com/topojson/topojson-client Version 2.1.0. Copyright 2016 Mike Bostock. -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.topojson = global.topojson || {}))); -}(this, (function (exports) { 'use strict'; - -var identity = function(x) { - return x; -}; - -var transform = function(topology) { - if ((transform = topology.transform) == null) return identity; - var transform, - x0, - y0, - kx = transform.scale[0], - ky = transform.scale[1], - dx = transform.translate[0], - dy = transform.translate[1]; - return function(point, i) { - if (!i) x0 = y0 = 0; - point[0] = (x0 += point[0]) * kx + dx; - point[1] = (y0 += point[1]) * ky + dy; - return point; - }; -}; - -var bbox = function(topology) { - var bbox = topology.bbox; - - function bboxPoint(p0) { - p1[0] = p0[0], p1[1] = p0[1], t(p1); - if (p1[0] < x0) x0 = p1[0]; - if (p1[0] > x1) x1 = p1[0]; - if (p1[1] < y0) y0 = p1[1]; - if (p1[1] > y1) y1 = p1[1]; - } - - function bboxGeometry(o) { - switch (o.type) { - case "GeometryCollection": o.geometries.forEach(bboxGeometry); break; - case "Point": bboxPoint(o.coordinates); break; - case "MultiPoint": o.coordinates.forEach(bboxPoint); break; - } - } - - if (!bbox) { - var t = transform(topology), p0, p1 = new Array(2), name, - x0 = Infinity, y0 = x0, x1 = -x0, y1 = -x0; - - topology.arcs.forEach(function(arc) { - var i = -1, n = arc.length; - while (++i < n) { - p0 = arc[i], p1[0] = p0[0], p1[1] = p0[1], t(p1, i); - if (p1[0] < x0) x0 = p1[0]; - if (p1[0] > x1) x1 = p1[0]; - if (p1[1] < y0) y0 = p1[1]; - if (p1[1] > y1) y1 = p1[1]; - } - }); - - for (name in topology.objects) { - bboxGeometry(topology.objects[name]); - } - - bbox = topology.bbox = [x0, y0, x1, y1]; - } - - return bbox; -}; - -var reverse = function(array, n) { - var t, j = array.length, i = j - n; - while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; -}; - -var feature = function(topology, o) { - return o.type === "GeometryCollection" - ? {type: "FeatureCollection", features: o.geometries.map(function(o) { return feature$1(topology, o); })} - : feature$1(topology, o); -}; - -function feature$1(topology, o) { - var id = o.id, - bbox = o.bbox, - properties = o.properties == null ? {} : o.properties, - geometry = object(topology, o); - return id == null && bbox == null ? {type: "Feature", properties: properties, geometry: geometry} - : bbox == null ? {type: "Feature", id: id, properties: properties, geometry: geometry} - : {type: "Feature", id: id, bbox: bbox, properties: properties, geometry: geometry}; -} - -function object(topology, o) { - var transformPoint = transform(topology), - arcs = topology.arcs; - - function arc(i, points) { - if (points.length) points.pop(); - for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length; k < n; ++k) { - points.push(transformPoint(a[k].slice(), k)); - } - if (i < 0) reverse(points, n); - } - - function point(p) { - return transformPoint(p.slice()); - } - - function line(arcs) { - var points = []; - for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); - if (points.length < 2) points.push(points[0].slice()); - return points; - } - - function ring(arcs) { - var points = line(arcs); - while (points.length < 4) points.push(points[0].slice()); - return points; - } - - function polygon(arcs) { - return arcs.map(ring); - } - - function geometry(o) { - var type = o.type, coordinates; - switch (type) { - case "GeometryCollection": return {type: type, geometries: o.geometries.map(geometry)}; - case "Point": coordinates = point(o.coordinates); break; - case "MultiPoint": coordinates = o.coordinates.map(point); break; - case "LineString": coordinates = line(o.arcs); break; - case "MultiLineString": coordinates = o.arcs.map(line); break; - case "Polygon": coordinates = polygon(o.arcs); break; - case "MultiPolygon": coordinates = o.arcs.map(polygon); break; - default: return null; - } - return {type: type, coordinates: coordinates}; - } - - return geometry(o); -} - -var stitch = function(topology, arcs) { - var stitchedArcs = {}, - fragmentByStart = {}, - fragmentByEnd = {}, - fragments = [], - emptyIndex = -1; - - // Stitch empty arcs first, since they may be subsumed by other arcs. - arcs.forEach(function(i, j) { - var arc = topology.arcs[i < 0 ? ~i : i], t; - if (arc.length < 3 && !arc[1][0] && !arc[1][1]) { - t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t; - } - }); - - arcs.forEach(function(i) { - var e = ends(i), - start = e[0], - end = e[1], - f, g; - - if (f = fragmentByEnd[start]) { - delete fragmentByEnd[f.end]; - f.push(i); - f.end = end; - if (g = fragmentByStart[end]) { - delete fragmentByStart[g.start]; - var fg = g === f ? f : f.concat(g); - fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; - } else { - fragmentByStart[f.start] = fragmentByEnd[f.end] = f; - } - } else if (f = fragmentByStart[end]) { - delete fragmentByStart[f.start]; - f.unshift(i); - f.start = start; - if (g = fragmentByEnd[start]) { - delete fragmentByEnd[g.end]; - var gf = g === f ? f : g.concat(f); - fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; - } else { - fragmentByStart[f.start] = fragmentByEnd[f.end] = f; - } - } else { - f = [i]; - fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f; - } - }); - - function ends(i) { - var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1; - if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; }); - else p1 = arc[arc.length - 1]; - return i < 0 ? [p1, p0] : [p0, p1]; - } - - function flush(fragmentByEnd, fragmentByStart) { - for (var k in fragmentByEnd) { - var f = fragmentByEnd[k]; - delete fragmentByStart[f.start]; - delete f.start; - delete f.end; - f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; }); - fragments.push(f); - } - } - - flush(fragmentByEnd, fragmentByStart); - flush(fragmentByStart, fragmentByEnd); - arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); }); - - return fragments; -}; - -var mesh = function(topology) { - return object(topology, meshArcs.apply(this, arguments)); -}; - -function meshArcs(topology, object$$1, filter) { - var arcs, i, n; - if (arguments.length > 1) arcs = extractArcs(topology, object$$1, filter); - else for (i = 0, arcs = new Array(n = topology.arcs.length); i < n; ++i) arcs[i] = i; - return {type: "MultiLineString", arcs: stitch(topology, arcs)}; -} - -function extractArcs(topology, object$$1, filter) { - var arcs = [], - geomsByArc = [], - geom; - - function extract0(i) { - var j = i < 0 ? ~i : i; - (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom}); - } - - function extract1(arcs) { - arcs.forEach(extract0); - } - - function extract2(arcs) { - arcs.forEach(extract1); - } - - function extract3(arcs) { - arcs.forEach(extract2); - } - - function geometry(o) { - switch (geom = o, o.type) { - case "GeometryCollection": o.geometries.forEach(geometry); break; - case "LineString": extract1(o.arcs); break; - case "MultiLineString": case "Polygon": extract2(o.arcs); break; - case "MultiPolygon": extract3(o.arcs); break; - } - } - - geometry(object$$1); - - geomsByArc.forEach(filter == null - ? function(geoms) { arcs.push(geoms[0].i); } - : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); }); - - return arcs; -} - -function planarRingArea(ring) { - var i = -1, n = ring.length, a, b = ring[n - 1], area = 0; - while (++i < n) a = b, b = ring[i], area += a[0] * b[1] - a[1] * b[0]; - return Math.abs(area); // Note: doubled area! -} - -var merge = function(topology) { - return object(topology, mergeArcs.apply(this, arguments)); -}; - -function mergeArcs(topology, objects) { - var polygonsByArc = {}, - polygons = [], - groups = []; - - objects.forEach(geometry); - - function geometry(o) { - switch (o.type) { - case "GeometryCollection": o.geometries.forEach(geometry); break; - case "Polygon": extract(o.arcs); break; - case "MultiPolygon": o.arcs.forEach(extract); break; - } - } - - function extract(polygon) { - polygon.forEach(function(ring) { - ring.forEach(function(arc) { - (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon); - }); - }); - polygons.push(polygon); - } - - function area(ring) { - return planarRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]); - } - - polygons.forEach(function(polygon) { - if (!polygon._) { - var group = [], - neighbors = [polygon]; - polygon._ = 1; - groups.push(group); - while (polygon = neighbors.pop()) { - group.push(polygon); - polygon.forEach(function(ring) { - ring.forEach(function(arc) { - polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) { - if (!polygon._) { - polygon._ = 1; - neighbors.push(polygon); - } - }); - }); - }); - } - } - }); - - polygons.forEach(function(polygon) { - delete polygon._; - }); - - return { - type: "MultiPolygon", - arcs: groups.map(function(polygons) { - var arcs = [], n; - - // Extract the exterior (unique) arcs. - polygons.forEach(function(polygon) { - polygon.forEach(function(ring) { - ring.forEach(function(arc) { - if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) { - arcs.push(arc); - } - }); - }); - }); - - // Stitch the arcs into one or more rings. - arcs = stitch(topology, arcs); - - // If more than one ring is returned, - // at most one of these rings can be the exterior; - // choose the one with the greatest absolute area. - if ((n = arcs.length) > 1) { - for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) { - if ((ki = area(arcs[i])) > k) { - t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki; - } - } - } - - return arcs; - }) - }; -} - -var bisect = function(a, x) { - var lo = 0, hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (a[mid] < x) lo = mid + 1; - else hi = mid; - } - return lo; -}; - -var neighbors = function(objects) { - var indexesByArc = {}, // arc index -> array of object indexes - neighbors = objects.map(function() { return []; }); - - function line(arcs, i) { - arcs.forEach(function(a) { - if (a < 0) a = ~a; - var o = indexesByArc[a]; - if (o) o.push(i); - else indexesByArc[a] = [i]; - }); - } - - function polygon(arcs, i) { - arcs.forEach(function(arc) { line(arc, i); }); - } - - function geometry(o, i) { - if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); }); - else if (o.type in geometryType) geometryType[o.type](o.arcs, i); - } - - var geometryType = { - LineString: line, - MultiLineString: polygon, - Polygon: polygon, - MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } - }; - - objects.forEach(geometry); - - for (var i in indexesByArc) { - for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) { - for (var k = j + 1; k < m; ++k) { - var ij = indexes[j], ik = indexes[k], n; - if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik); - if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij); - } - } - } - - return neighbors; -}; - -var quantize = function(topology, n) { - if (!((n = Math.floor(n)) >= 2)) throw new Error("n must be ≥2"); - if (topology.transform) throw new Error("already quantized"); - var bb = bbox(topology), name, - dx = bb[0], kx = (bb[2] - dx) / (n - 1) || 1, - dy = bb[1], ky = (bb[3] - dy) / (n - 1) || 1; - - function quantizePoint(p) { - p[0] = Math.round((p[0] - dx) / kx); - p[1] = Math.round((p[1] - dy) / ky); - } - - function quantizeGeometry(o) { - switch (o.type) { - case "GeometryCollection": o.geometries.forEach(quantizeGeometry); break; - case "Point": quantizePoint(o.coordinates); break; - case "MultiPoint": o.coordinates.forEach(quantizePoint); break; - } - } - - topology.arcs.forEach(function(arc) { - var i = 1, - j = 1, - n = arc.length, - pi = arc[0], - x0 = pi[0] = Math.round((pi[0] - dx) / kx), - y0 = pi[1] = Math.round((pi[1] - dy) / ky), - pj, - x1, - y1; - - for (; i < n; ++i) { - pi = arc[i]; - x1 = Math.round((pi[0] - dx) / kx); - y1 = Math.round((pi[1] - dy) / ky); - if (x1 !== x0 || y1 !== y0) { - pj = arc[j++]; - pj[0] = x1 - x0, x0 = x1; - pj[1] = y1 - y0, y0 = y1; - } - } - - if (j < 2) { - pj = arc[j++]; - pj[0] = 0; - pj[1] = 0; - } - - arc.length = j; - }); - - for (name in topology.objects) { - quantizeGeometry(topology.objects[name]); - } - - topology.transform = { - scale: [kx, ky], - translate: [dx, dy] - }; - - return topology; -}; - -var untransform = function(topology) { - if ((transform = topology.transform) == null) return identity; - var transform, - x0, - y0, - kx = transform.scale[0], - ky = transform.scale[1], - dx = transform.translate[0], - dy = transform.translate[1]; - return function(point, i) { - if (!i) x0 = y0 = 0; - var x1 = Math.round((point[0] - dx) / kx), - y1 = Math.round((point[1] - dy) / ky); - point[0] = x1 - x0, x0 = x1; - point[1] = y1 - y0, y0 = y1; - return point; - }; -}; - -exports.bbox = bbox; -exports.feature = feature; -exports.mesh = mesh; -exports.meshArcs = meshArcs; -exports.merge = merge; -exports.mergeArcs = mergeArcs; -exports.neighbors = neighbors; -exports.quantize = quantize; -exports.transform = transform; -exports.untransform = untransform; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); - -},{}],541:[function(_dereq_,module,exports){ -"use strict" - -module.exports = triangulateCube - -var perm = _dereq_("permutation-rank") -var sgn = _dereq_("permutation-parity") -var gamma = _dereq_("gamma") - -function triangulateCube(dimension) { - if(dimension < 0) { - return [ ] - } - if(dimension === 0) { - return [ [0] ] - } - var dfactorial = Math.round(gamma(dimension+1))|0 - var result = [] - for(var i=0; i Math.max(vy, vz)) { - u[2] = 1 - } else if(vy > Math.max(vx, vz)) { - u[0] = 1 - } else { - u[1] = 1 - } - - var vv = 0 - var uv = 0 - for(var i=0; i<3; ++i ) { - vv += v[i] * v[i] - uv += u[i] * v[i] - } - for(var i=0; i<3; ++i) { - u[i] -= (uv / vv) * v[i] - } - normalize3(u, u) - return u -} - -function TurntableController(zoomMin, zoomMax, center, up, right, radius, theta, phi) { - this.center = filterVector(center) - this.up = filterVector(up) - this.right = filterVector(right) - this.radius = filterVector([radius]) - this.angle = filterVector([theta, phi]) - this.angle.bounds = [[-Infinity,-Math.PI/2], [Infinity,Math.PI/2]] - this.setDistanceLimits(zoomMin, zoomMax) - - this.computedCenter = this.center.curve(0) - this.computedUp = this.up.curve(0) - this.computedRight = this.right.curve(0) - this.computedRadius = this.radius.curve(0) - this.computedAngle = this.angle.curve(0) - this.computedToward = [0,0,0] - this.computedEye = [0,0,0] - this.computedMatrix = new Array(16) - for(var i=0; i<16; ++i) { - this.computedMatrix[i] = 0.5 - } - - this.recalcMatrix(0) -} - -var proto = TurntableController.prototype - -proto.setDistanceLimits = function(minDist, maxDist) { - if(minDist > 0) { - minDist = Math.log(minDist) - } else { - minDist = -Infinity - } - if(maxDist > 0) { - maxDist = Math.log(maxDist) - } else { - maxDist = Infinity - } - maxDist = Math.max(maxDist, minDist) - this.radius.bounds[0][0] = minDist - this.radius.bounds[1][0] = maxDist -} - -proto.getDistanceLimits = function(out) { - var bounds = this.radius.bounds[0] - if(out) { - out[0] = Math.exp(bounds[0][0]) - out[1] = Math.exp(bounds[1][0]) - return out - } - return [ Math.exp(bounds[0][0]), Math.exp(bounds[1][0]) ] -} - -proto.recalcMatrix = function(t) { - //Recompute curves - this.center.curve(t) - this.up.curve(t) - this.right.curve(t) - this.radius.curve(t) - this.angle.curve(t) - - //Compute frame for camera matrix - var up = this.computedUp - var right = this.computedRight - var uu = 0.0 - var ur = 0.0 - for(var i=0; i<3; ++i) { - ur += up[i] * right[i] - uu += up[i] * up[i] - } - var ul = Math.sqrt(uu) - var rr = 0.0 - for(var i=0; i<3; ++i) { - right[i] -= up[i] * ur / uu - rr += right[i] * right[i] - up[i] /= ul - } - var rl = Math.sqrt(rr) - for(var i=0; i<3; ++i) { - right[i] /= rl - } - - //Compute toward vector - var toward = this.computedToward - cross(toward, up, right) - normalize3(toward, toward) - - //Compute angular parameters - var radius = Math.exp(this.computedRadius[0]) - var theta = this.computedAngle[0] - var phi = this.computedAngle[1] - - var ctheta = Math.cos(theta) - var stheta = Math.sin(theta) - var cphi = Math.cos(phi) - var sphi = Math.sin(phi) - - var center = this.computedCenter - - var wx = ctheta * cphi - var wy = stheta * cphi - var wz = sphi - - var sx = -ctheta * sphi - var sy = -stheta * sphi - var sz = cphi - - var eye = this.computedEye - var mat = this.computedMatrix - for(var i=0; i<3; ++i) { - var x = wx * right[i] + wy * toward[i] + wz * up[i] - mat[4*i+1] = sx * right[i] + sy * toward[i] + sz * up[i] - mat[4*i+2] = x - mat[4*i+3] = 0.0 - } - - var ax = mat[1] - var ay = mat[5] - var az = mat[9] - var bx = mat[2] - var by = mat[6] - var bz = mat[10] - var cx = ay * bz - az * by - var cy = az * bx - ax * bz - var cz = ax * by - ay * bx - var cl = len3(cx, cy, cz) - cx /= cl - cy /= cl - cz /= cl - mat[0] = cx - mat[4] = cy - mat[8] = cz - - for(var i=0; i<3; ++i) { - eye[i] = center[i] + mat[2+4*i]*radius - } - - for(var i=0; i<3; ++i) { - var rr = 0.0 - for(var j=0; j<3; ++j) { - rr += mat[i+4*j] * eye[j] - } - mat[12+i] = -rr - } - mat[15] = 1.0 -} - -proto.getMatrix = function(t, result) { - this.recalcMatrix(t) - var mat = this.computedMatrix - if(result) { - for(var i=0; i<16; ++i) { - result[i] = mat[i] - } - return result - } - return mat -} - -var zAxis = [0,0,0] -proto.rotate = function(t, dtheta, dphi, droll) { - this.angle.move(t, dtheta, dphi) - if(droll) { - this.recalcMatrix(t) - - var mat = this.computedMatrix - zAxis[0] = mat[2] - zAxis[1] = mat[6] - zAxis[2] = mat[10] - - var up = this.computedUp - var right = this.computedRight - var toward = this.computedToward - - for(var i=0; i<3; ++i) { - mat[4*i] = up[i] - mat[4*i+1] = right[i] - mat[4*i+2] = toward[i] - } - rotateM(mat, mat, droll, zAxis) - for(var i=0; i<3; ++i) { - up[i] = mat[4*i] - right[i] = mat[4*i+1] - } - - this.up.set(t, up[0], up[1], up[2]) - this.right.set(t, right[0], right[1], right[2]) - } -} - -proto.pan = function(t, dx, dy, dz) { - dx = dx || 0.0 - dy = dy || 0.0 - dz = dz || 0.0 - - this.recalcMatrix(t) - var mat = this.computedMatrix - - var dist = Math.exp(this.computedRadius[0]) - - var ux = mat[1] - var uy = mat[5] - var uz = mat[9] - var ul = len3(ux, uy, uz) - ux /= ul - uy /= ul - uz /= ul - - var rx = mat[0] - var ry = mat[4] - var rz = mat[8] - var ru = rx * ux + ry * uy + rz * uz - rx -= ux * ru - ry -= uy * ru - rz -= uz * ru - var rl = len3(rx, ry, rz) - rx /= rl - ry /= rl - rz /= rl - - var vx = rx * dx + ux * dy - var vy = ry * dx + uy * dy - var vz = rz * dx + uz * dy - this.center.move(t, vx, vy, vz) - - //Update z-component of radius - var radius = Math.exp(this.computedRadius[0]) - radius = Math.max(1e-4, radius + dz) - this.radius.set(t, Math.log(radius)) -} - -proto.translate = function(t, dx, dy, dz) { - this.center.move(t, - dx||0.0, - dy||0.0, - dz||0.0) -} - -//Recenters the coordinate axes -proto.setMatrix = function(t, mat, axes, noSnap) { - - //Get the axes for tare - var ushift = 1 - if(typeof axes === 'number') { - ushift = (axes)|0 - } - if(ushift < 0 || ushift > 3) { - ushift = 1 - } - var vshift = (ushift + 2) % 3 - var fshift = (ushift + 1) % 3 - - //Recompute state for new t value - if(!mat) { - this.recalcMatrix(t) - mat = this.computedMatrix - } - - //Get right and up vectors - var ux = mat[ushift] - var uy = mat[ushift+4] - var uz = mat[ushift+8] - if(!noSnap) { - var ul = len3(ux, uy, uz) - ux /= ul - uy /= ul - uz /= ul - } else { - var ax = Math.abs(ux) - var ay = Math.abs(uy) - var az = Math.abs(uz) - var am = Math.max(ax,ay,az) - if(ax === am) { - ux = (ux < 0) ? -1 : 1 - uy = uz = 0 - } else if(az === am) { - uz = (uz < 0) ? -1 : 1 - ux = uy = 0 - } else { - uy = (uy < 0) ? -1 : 1 - ux = uz = 0 - } - } - - var rx = mat[vshift] - var ry = mat[vshift+4] - var rz = mat[vshift+8] - var ru = rx * ux + ry * uy + rz * uz - rx -= ux * ru - ry -= uy * ru - rz -= uz * ru - var rl = len3(rx, ry, rz) - rx /= rl - ry /= rl - rz /= rl - - var fx = uy * rz - uz * ry - var fy = uz * rx - ux * rz - var fz = ux * ry - uy * rx - var fl = len3(fx, fy, fz) - fx /= fl - fy /= fl - fz /= fl - - this.center.jump(t, ex, ey, ez) - this.radius.idle(t) - this.up.jump(t, ux, uy, uz) - this.right.jump(t, rx, ry, rz) - - var phi, theta - if(ushift === 2) { - var cx = mat[1] - var cy = mat[5] - var cz = mat[9] - var cr = cx * rx + cy * ry + cz * rz - var cf = cx * fx + cy * fy + cz * fz - if(tu < 0) { - phi = -Math.PI/2 - } else { - phi = Math.PI/2 - } - theta = Math.atan2(cf, cr) - } else { - var tx = mat[2] - var ty = mat[6] - var tz = mat[10] - var tu = tx * ux + ty * uy + tz * uz - var tr = tx * rx + ty * ry + tz * rz - var tf = tx * fx + ty * fy + tz * fz - - phi = Math.asin(clamp1(tu)) - theta = Math.atan2(tf, tr) - } - - this.angle.jump(t, theta, phi) - - this.recalcMatrix(t) - var dx = mat[2] - var dy = mat[6] - var dz = mat[10] - - var imat = this.computedMatrix - invert44(imat, mat) - var w = imat[15] - var ex = imat[12] / w - var ey = imat[13] / w - var ez = imat[14] / w - - var gs = Math.exp(this.computedRadius[0]) - this.center.jump(t, ex-dx*gs, ey-dy*gs, ez-dz*gs) -} - -proto.lastT = function() { - return Math.max( - this.center.lastT(), - this.up.lastT(), - this.right.lastT(), - this.radius.lastT(), - this.angle.lastT()) -} - -proto.idle = function(t) { - this.center.idle(t) - this.up.idle(t) - this.right.idle(t) - this.radius.idle(t) - this.angle.idle(t) -} - -proto.flush = function(t) { - this.center.flush(t) - this.up.flush(t) - this.right.flush(t) - this.radius.flush(t) - this.angle.flush(t) -} - -proto.setDistance = function(t, d) { - if(d > 0) { - this.radius.set(t, Math.log(d)) - } -} - -proto.lookAt = function(t, eye, center, up) { - this.recalcMatrix(t) - - eye = eye || this.computedEye - center = center || this.computedCenter - up = up || this.computedUp - - var ux = up[0] - var uy = up[1] - var uz = up[2] - var ul = len3(ux, uy, uz) - if(ul < 1e-6) { - return - } - ux /= ul - uy /= ul - uz /= ul - - var tx = eye[0] - center[0] - var ty = eye[1] - center[1] - var tz = eye[2] - center[2] - var tl = len3(tx, ty, tz) - if(tl < 1e-6) { - return - } - tx /= tl - ty /= tl - tz /= tl - - var right = this.computedRight - var rx = right[0] - var ry = right[1] - var rz = right[2] - var ru = ux*rx + uy*ry + uz*rz - rx -= ru * ux - ry -= ru * uy - rz -= ru * uz - var rl = len3(rx, ry, rz) - - if(rl < 0.01) { - rx = uy * tz - uz * ty - ry = uz * tx - ux * tz - rz = ux * ty - uy * tx - rl = len3(rx, ry, rz) - if(rl < 1e-6) { - return - } - } - rx /= rl - ry /= rl - rz /= rl - - this.up.set(t, ux, uy, uz) - this.right.set(t, rx, ry, rz) - this.center.set(t, center[0], center[1], center[2]) - this.radius.set(t, Math.log(tl)) - - var fx = uy * rz - uz * ry - var fy = uz * rx - ux * rz - var fz = ux * ry - uy * rx - var fl = len3(fx, fy, fz) - fx /= fl - fy /= fl - fz /= fl - - var tu = ux*tx + uy*ty + uz*tz - var tr = rx*tx + ry*ty + rz*tz - var tf = fx*tx + fy*ty + fz*tz - - var phi = Math.asin(clamp1(tu)) - var theta = Math.atan2(tf, tr) - - var angleState = this.angle._state - var lastTheta = angleState[angleState.length-1] - var lastPhi = angleState[angleState.length-2] - lastTheta = lastTheta % (2.0 * Math.PI) - var dp = Math.abs(lastTheta + 2.0 * Math.PI - theta) - var d0 = Math.abs(lastTheta - theta) - var dn = Math.abs(lastTheta - 2.0 * Math.PI - theta) - if(dp < d0) { - lastTheta += 2.0 * Math.PI - } - if(dn < d0) { - lastTheta -= 2.0 * Math.PI - } - - this.angle.jump(this.angle.lastT(), lastTheta, lastPhi) - this.angle.set(t, theta, phi) -} - -function createTurntableController(options) { - options = options || {} - - var center = options.center || [0,0,0] - var up = options.up || [0,1,0] - var right = options.right || findOrthoPair(up) - var radius = options.radius || 1.0 - var theta = options.theta || 0.0 - var phi = options.phi || 0.0 - - center = [].slice.call(center, 0, 3) - - up = [].slice.call(up, 0, 3) - normalize3(up, up) - - right = [].slice.call(right, 0, 3) - normalize3(right, right) - - if('eye' in options) { - var eye = options.eye - var toward = [ - eye[0]-center[0], - eye[1]-center[1], - eye[2]-center[2] - ] - cross(right, toward, up) - if(len3(right[0], right[1], right[2]) < 1e-6) { - right = findOrthoPair(up) - } else { - normalize3(right, right) - } - - radius = len3(toward[0], toward[1], toward[2]) - - var ut = dot3(up, toward) / radius - var rt = dot3(right, toward) / radius - phi = Math.acos(ut) - theta = Math.acos(rt) - } - - //Use logarithmic coordinates for radius - radius = Math.log(radius) - - //Return the controller - return new TurntableController( - options.zoomMin, - options.zoomMax, - center, - up, - right, - radius, - theta, - phi) -} -},{"filtered-vector":226,"gl-mat4/invert":265,"gl-mat4/rotate":270,"gl-vec3/cross":334,"gl-vec3/dot":339,"gl-vec3/normalize":356}],543:[function(_dereq_,module,exports){ -"use strict" - -module.exports = twoProduct - -var SPLITTER = +(Math.pow(2, 27) + 1.0) - -function twoProduct(a, b, result) { - var x = a * b - - var c = SPLITTER * a - var abig = c - a - var ahi = c - abig - var alo = a - ahi - - var d = SPLITTER * b - var bbig = d - b - var bhi = d - bbig - var blo = b - bhi - - var err1 = x - (ahi * bhi) - var err2 = err1 - (alo * bhi) - var err3 = err2 - (ahi * blo) - - var y = alo * blo - err3 - - if(result) { - result[0] = y - result[1] = x - return result - } - - return [ y, x ] -} -},{}],544:[function(_dereq_,module,exports){ -"use strict" - -module.exports = fastTwoSum - -function fastTwoSum(a, b, result) { - var x = a + b - var bv = x - a - var av = x - bv - var br = b - bv - var ar = a - av - if(result) { - result[0] = ar + br - result[1] = x - return result - } - return [ar+br, x] -} -},{}],545:[function(_dereq_,module,exports){ -(function (global,Buffer){ -'use strict' - -var bits = _dereq_('bit-twiddle') -var dup = _dereq_('dup') - -//Legacy pool support -if(!global.__TYPEDARRAY_POOL) { - global.__TYPEDARRAY_POOL = { - UINT8 : dup([32, 0]) - , UINT16 : dup([32, 0]) - , UINT32 : dup([32, 0]) - , INT8 : dup([32, 0]) - , INT16 : dup([32, 0]) - , INT32 : dup([32, 0]) - , FLOAT : dup([32, 0]) - , DOUBLE : dup([32, 0]) - , DATA : dup([32, 0]) - , UINT8C : dup([32, 0]) - , BUFFER : dup([32, 0]) - } -} - -var hasUint8C = (typeof Uint8ClampedArray) !== 'undefined' -var POOL = global.__TYPEDARRAY_POOL - -//Upgrade pool -if(!POOL.UINT8C) { - POOL.UINT8C = dup([32, 0]) -} -if(!POOL.BUFFER) { - POOL.BUFFER = dup([32, 0]) -} - -//New technique: Only allocate from ArrayBufferView and Buffer -var DATA = POOL.DATA - , BUFFER = POOL.BUFFER - -exports.free = function free(array) { - if(Buffer.isBuffer(array)) { - BUFFER[bits.log2(array.length)].push(array) - } else { - if(Object.prototype.toString.call(array) !== '[object ArrayBuffer]') { - array = array.buffer - } - if(!array) { - return - } - var n = array.length || array.byteLength - var log_n = bits.log2(n)|0 - DATA[log_n].push(array) - } -} - -function freeArrayBuffer(buffer) { - if(!buffer) { - return - } - var n = buffer.length || buffer.byteLength - var log_n = bits.log2(n) - DATA[log_n].push(buffer) -} - -function freeTypedArray(array) { - freeArrayBuffer(array.buffer) -} - -exports.freeUint8 = -exports.freeUint16 = -exports.freeUint32 = -exports.freeInt8 = -exports.freeInt16 = -exports.freeInt32 = -exports.freeFloat32 = -exports.freeFloat = -exports.freeFloat64 = -exports.freeDouble = -exports.freeUint8Clamped = -exports.freeDataView = freeTypedArray - -exports.freeArrayBuffer = freeArrayBuffer - -exports.freeBuffer = function freeBuffer(array) { - BUFFER[bits.log2(array.length)].push(array) -} - -exports.malloc = function malloc(n, dtype) { - if(dtype === undefined || dtype === 'arraybuffer') { - return mallocArrayBuffer(n) - } else { - switch(dtype) { - case 'uint8': - return mallocUint8(n) - case 'uint16': - return mallocUint16(n) - case 'uint32': - return mallocUint32(n) - case 'int8': - return mallocInt8(n) - case 'int16': - return mallocInt16(n) - case 'int32': - return mallocInt32(n) - case 'float': - case 'float32': - return mallocFloat(n) - case 'double': - case 'float64': - return mallocDouble(n) - case 'uint8_clamped': - return mallocUint8Clamped(n) - case 'buffer': - return mallocBuffer(n) - case 'data': - case 'dataview': - return mallocDataView(n) - - default: - return null - } - } - return null -} - -function mallocArrayBuffer(n) { - var n = bits.nextPow2(n) - var log_n = bits.log2(n) - var d = DATA[log_n] - if(d.length > 0) { - return d.pop() - } - return new ArrayBuffer(n) -} -exports.mallocArrayBuffer = mallocArrayBuffer - -function mallocUint8(n) { - return new Uint8Array(mallocArrayBuffer(n), 0, n) -} -exports.mallocUint8 = mallocUint8 - -function mallocUint16(n) { - return new Uint16Array(mallocArrayBuffer(2*n), 0, n) -} -exports.mallocUint16 = mallocUint16 - -function mallocUint32(n) { - return new Uint32Array(mallocArrayBuffer(4*n), 0, n) -} -exports.mallocUint32 = mallocUint32 - -function mallocInt8(n) { - return new Int8Array(mallocArrayBuffer(n), 0, n) -} -exports.mallocInt8 = mallocInt8 - -function mallocInt16(n) { - return new Int16Array(mallocArrayBuffer(2*n), 0, n) -} -exports.mallocInt16 = mallocInt16 - -function mallocInt32(n) { - return new Int32Array(mallocArrayBuffer(4*n), 0, n) -} -exports.mallocInt32 = mallocInt32 - -function mallocFloat(n) { - return new Float32Array(mallocArrayBuffer(4*n), 0, n) -} -exports.mallocFloat32 = exports.mallocFloat = mallocFloat - -function mallocDouble(n) { - return new Float64Array(mallocArrayBuffer(8*n), 0, n) -} -exports.mallocFloat64 = exports.mallocDouble = mallocDouble - -function mallocUint8Clamped(n) { - if(hasUint8C) { - return new Uint8ClampedArray(mallocArrayBuffer(n), 0, n) - } else { - return mallocUint8(n) - } -} -exports.mallocUint8Clamped = mallocUint8Clamped - -function mallocDataView(n) { - return new DataView(mallocArrayBuffer(n), 0, n) -} -exports.mallocDataView = mallocDataView - -function mallocBuffer(n) { - n = bits.nextPow2(n) - var log_n = bits.log2(n) - var cache = BUFFER[log_n] - if(cache.length > 0) { - return cache.pop() - } - return new Buffer(n) -} -exports.mallocBuffer = mallocBuffer - -exports.clearCache = function clearCache() { - for(var i=0; i<32; ++i) { - POOL.UINT8[i].length = 0 - POOL.UINT16[i].length = 0 - POOL.UINT32[i].length = 0 - POOL.INT8[i].length = 0 - POOL.INT16[i].length = 0 - POOL.INT32[i].length = 0 - POOL.FLOAT[i].length = 0 - POOL.DOUBLE[i].length = 0 - POOL.UINT8C[i].length = 0 - DATA[i].length = 0 - BUFFER[i].length = 0 - } -} -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},_dereq_("buffer").Buffer) -},{"bit-twiddle":92,"buffer":105,"dup":170}],546:[function(_dereq_,module,exports){ -"use strict"; "use restrict"; - -module.exports = UnionFind; - -function UnionFind(count) { - this.roots = new Array(count); - this.ranks = new Array(count); - - for(var i=0; i" - var clsTag = "" - - var nOPN = opnTag.length - var nCLS = clsTag.length - - var isRecursive = (TAG_CHR[0] === CHR_super0) || - (TAG_CHR[0] === CHR_sub0); - - var a = 0 - var b = -nCLS - while (a > -1) { - a = str.indexOf(opnTag, a) - if(a === -1) break - - b = str.indexOf(clsTag, a + nOPN) - if(b === -1) break - - if(b <= a) break - - for(var i = a; i < b + nCLS; ++i){ - if((i < a + nOPN) || (i >= b)) { - map[i] = null - str = str.substr(0, i) + " " + str.substr(i + 1) - } else { - if(map[i] !== null) { - var pos = map[i].indexOf(TAG_CHR[0]) - if(pos === -1) { - map[i] += TAG_CHR - } else { // i.e. to handle multiple sub/super-scripts - if(isRecursive) { - // i.e to increase the sub/sup number - map[i] = map[i].substr(0, pos + 1) + (1 + parseInt(map[i][pos + 1])) + map[i].substr(pos + 2) - } - } - } - } - } - - var start = a + nOPN - var remainingStr = str.substr(start, b - start) - - var c = remainingStr.indexOf(opnTag) - if(c !== -1) a = c - else a = b + nCLS - } - - return map -} - -function transformPositions(positions, options, size) { - var align = options.textAlign || "start" - var baseline = options.textBaseline || "alphabetic" - - var lo = [1<<30, 1<<30] - var hi = [0,0] - var n = positions.length - for(var i=0; i/g, '\n') // replace
tags with \n in the string - } else { - rawString = rawString.replace(/\/g, ' ') // don't accept
tags in the input and replace with space in this case - } - - var activeStyle = "" - var map = [] - for(j = 0; j < rawString.length; ++j) { - map[j] = activeStyle - } - - if(styletags.bolds === true) map = parseTag(TAG_bold, CHR_bold, rawString, map) - if(styletags.italics === true) map = parseTag(TAG_italic, CHR_italic, rawString, map) - if(styletags.superscripts === true) map = parseTag(TAG_super, CHR_super, rawString, map) - if(styletags.subscripts === true) map = parseTag(TAG_sub, CHR_sub, rawString, map) - - var allStyles = [] - var plainText = "" - for(j = 0; j < rawString.length; ++j) { - if(map[j] !== null) { - plainText += rawString[j] - allStyles.push(map[j]) - } - } - - var allTexts = plainText.split('\n') - - var numberOfLines = allTexts.length - var lineHeight = Math.round(lineSpacing * fontSize) - var offsetX = fontSize - var offsetY = fontSize * 2 - var maxWidth = 0 - var minHeight = numberOfLines * lineHeight + offsetY - - if(canvas.height < minHeight) { - canvas.height = minHeight - } - - context.fillStyle = "#000" - context.fillRect(0, 0, canvas.width, canvas.height) - - context.fillStyle = "#fff" - var i, j, xPos, yPos, zPos - var nDone = 0 - - var buffer = "" - function writeBuffer() { - if(buffer !== "") { - var delta = context.measureText(buffer).width - - context.fillText(buffer, offsetX + xPos, offsetY + yPos) - xPos += delta - } - } - - function getTextFontSize() { - return "" + Math.round(zPos) + "px "; - } - - function changeStyle(oldStyle, newStyle) { - var ctxFont = "" + context.font; - - if(styletags.subscripts === true) { - var oldIndex_Sub = oldStyle.indexOf(CHR_sub0); - var newIndex_Sub = newStyle.indexOf(CHR_sub0); - - var oldSub = (oldIndex_Sub > -1) ? parseInt(oldStyle[1 + oldIndex_Sub]) : 0; - var newSub = (newIndex_Sub > -1) ? parseInt(newStyle[1 + newIndex_Sub]) : 0; - - if(oldSub !== newSub) { - ctxFont = ctxFont.replace(getTextFontSize(), "?px ") - zPos *= Math.pow(0.75, (newSub - oldSub)) - ctxFont = ctxFont.replace("?px ", getTextFontSize()) - } - yPos += 0.25 * lineHeight * (newSub - oldSub); - } - - if(styletags.superscripts === true) { - var oldIndex_Super = oldStyle.indexOf(CHR_super0); - var newIndex_Super = newStyle.indexOf(CHR_super0); - - var oldSuper = (oldIndex_Super > -1) ? parseInt(oldStyle[1 + oldIndex_Super]) : 0; - var newSuper = (newIndex_Super > -1) ? parseInt(newStyle[1 + newIndex_Super]) : 0; - - if(oldSuper !== newSuper) { - ctxFont = ctxFont.replace(getTextFontSize(), "?px ") - zPos *= Math.pow(0.75, (newSuper - oldSuper)) - ctxFont = ctxFont.replace("?px ", getTextFontSize()) - } - yPos -= 0.25 * lineHeight * (newSuper - oldSuper); - } - - if(styletags.bolds === true) { - var wasBold = (oldStyle.indexOf(CHR_bold) > -1) - var is_Bold = (newStyle.indexOf(CHR_bold) > -1) - - if(!wasBold && is_Bold) { - if(wasItalic) { - ctxFont = ctxFont.replace("italic ", "italic bold ") - } else { - ctxFont = "bold " + ctxFont - } - } - if(wasBold && !is_Bold) { - ctxFont = ctxFont.replace("bold ", '') - } - } - - if(styletags.italics === true) { - var wasItalic = (oldStyle.indexOf(CHR_italic) > -1) - var is_Italic = (newStyle.indexOf(CHR_italic) > -1) - - if(!wasItalic && is_Italic) { - ctxFont = "italic " + ctxFont - } - if(wasItalic && !is_Italic) { - ctxFont = ctxFont.replace("italic ", '') - } - } - context.font = ctxFont - } - - for(i = 0; i < numberOfLines; ++i) { - var txt = allTexts[i] + '\n' - xPos = 0 - yPos = i * lineHeight - zPos = fontSize - - buffer = "" - - for(j = 0; j < txt.length; ++j) { - var style = (j + nDone < allStyles.length) ? allStyles[j + nDone] : allStyles[allStyles.length - 1] - if(activeStyle === style) { - buffer += txt[j] - } else { - writeBuffer() - buffer = txt[j] - - if(style !== undefined) { - changeStyle(activeStyle, style) - activeStyle = style - } - } - } - writeBuffer() - - nDone += txt.length - - var width = Math.round(xPos + 2 * offsetX) | 0 - if(maxWidth < width) maxWidth = width - } - - //Cut pixels from image - var xCut = maxWidth - var yCut = offsetY + lineHeight * numberOfLines - var pixels = ndarray(context.getImageData(0, 0, xCut, yCut).data, [yCut, xCut, 4]) - return pixels.pick(-1, -1, 0).transpose(1, 0) -} - -function getContour(pixels, doSimplify) { - var contour = surfaceNets(pixels, 128) - if(doSimplify) { - return simplify(contour.cells, contour.positions, 0.25) - } - return { - edges: contour.cells, - positions: contour.positions - } -} - -function processPixelsImpl(pixels, options, size, simplify) { - //Extract contour - var contour = getContour(pixels, simplify) - - //Apply warp to positions - var positions = transformPositions(contour.positions, options, size) - var edges = contour.edges - var flip = "ccw" === options.orientation - - //Clean up the PSLG, resolve self intersections, etc. - cleanPSLG(positions, edges) - - //If triangulate flag passed, triangulate the result - if(options.polygons || options.polygon || options.polyline) { - var result = toPolygonCrappy(edges, positions) - var nresult = new Array(result.length) - for(var i=0; i 0) size = - options.size - - if(options.lineSpacing && - options.lineSpacing > 0) lineSpacing = - options.lineSpacing - - if(options.styletags && - options.styletags.breaklines) styletags.breaklines = - options.styletags.breaklines ? true : false - - if(options.styletags && - options.styletags.bolds) styletags.bolds = - options.styletags.bolds ? true : false - - if(options.styletags && - options.styletags.italics) styletags.italics = - options.styletags.italics ? true : false - - if(options.styletags && - options.styletags.subscripts) styletags.subscripts = - options.styletags.subscripts ? true : false - - if(options.styletags && - options.styletags.superscripts) styletags.superscripts = - options.styletags.superscripts ? true : false - } - - context.font = [ - options.fontStyle, - options.fontVariant, - options.fontWeight, - size + "px", - options.font - ].filter(function(d) {return d}).join(" ") - context.textAlign = "start" - context.textBaseline = "alphabetic" - context.direction = "ltr" - - var pixels = getPixels(canvas, context, str, size, lineSpacing, styletags) - - return processPixels(pixels, options, size) -} - -},{"cdt2d":106,"clean-pslg":116,"ndarray":450,"planar-graph-to-polyline":468,"simplify-planar-graph":524,"surface-nets":531}],552:[function(_dereq_,module,exports){ -// Copyright (C) 2011 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Install a leaky WeakMap emulation on platforms that - * don't provide a built-in one. - * - *

Assumes that an ES5 platform where, if {@code WeakMap} is - * already present, then it conforms to the anticipated ES6 - * specification. To run this file on an ES5 or almost ES5 - * implementation where the {@code WeakMap} specification does not - * quite conform, run repairES5.js first. - * - *

Even though WeakMapModule is not global, the linter thinks it - * is, which is why it is in the overrides list below. - * - *

NOTE: Before using this WeakMap emulation in a non-SES - * environment, see the note below about hiddenRecord. - * - * @author Mark S. Miller - * @requires crypto, ArrayBuffer, Uint8Array, navigator, console - * @overrides WeakMap, ses, Proxy - * @overrides WeakMapModule - */ - -/** - * This {@code WeakMap} emulation is observably equivalent to the - * ES-Harmony WeakMap, but with leakier garbage collection properties. - * - *

As with true WeakMaps, in this emulation, a key does not - * retain maps indexed by that key and (crucially) a map does not - * retain the keys it indexes. A map by itself also does not retain - * the values associated with that map. - * - *

However, the values associated with a key in some map are - * retained so long as that key is retained and those associations are - * not overridden. For example, when used to support membranes, all - * values exported from a given membrane will live for the lifetime - * they would have had in the absence of an interposed membrane. Even - * when the membrane is revoked, all objects that would have been - * reachable in the absence of revocation will still be reachable, as - * far as the GC can tell, even though they will no longer be relevant - * to ongoing computation. - * - *

The API implemented here is approximately the API as implemented - * in FF6.0a1 and agreed to by MarkM, Andreas Gal, and Dave Herman, - * rather than the offially approved proposal page. TODO(erights): - * upgrade the ecmascript WeakMap proposal page to explain this API - * change and present to EcmaScript committee for their approval. - * - *

The first difference between the emulation here and that in - * FF6.0a1 is the presence of non enumerable {@code get___, has___, - * set___, and delete___} methods on WeakMap instances to represent - * what would be the hidden internal properties of a primitive - * implementation. Whereas the FF6.0a1 WeakMap.prototype methods - * require their {@code this} to be a genuine WeakMap instance (i.e., - * an object of {@code [[Class]]} "WeakMap}), since there is nothing - * unforgeable about the pseudo-internal method names used here, - * nothing prevents these emulated prototype methods from being - * applied to non-WeakMaps with pseudo-internal methods of the same - * names. - * - *

Another difference is that our emulated {@code - * WeakMap.prototype} is not itself a WeakMap. A problem with the - * current FF6.0a1 API is that WeakMap.prototype is itself a WeakMap - * providing ambient mutability and an ambient communications - * channel. Thus, if a WeakMap is already present and has this - * problem, repairES5.js wraps it in a safe wrappper in order to - * prevent access to this channel. (See - * PATCH_MUTABLE_FROZEN_WEAKMAP_PROTO in repairES5.js). - */ - -/** - * If this is a full secureable ES5 platform and the ES-Harmony {@code WeakMap} is - * absent, install an approximate emulation. - * - *

If WeakMap is present but cannot store some objects, use our approximate - * emulation as a wrapper. - * - *

If this is almost a secureable ES5 platform, then WeakMap.js - * should be run after repairES5.js. - * - *

See {@code WeakMap} for documentation of the garbage collection - * properties of this WeakMap emulation. - */ -(function WeakMapModule() { - "use strict"; - - if (typeof ses !== 'undefined' && ses.ok && !ses.ok()) { - // already too broken, so give up - return; - } - - /** - * In some cases (current Firefox), we must make a choice betweeen a - * WeakMap which is capable of using all varieties of host objects as - * keys and one which is capable of safely using proxies as keys. See - * comments below about HostWeakMap and DoubleWeakMap for details. - * - * This function (which is a global, not exposed to guests) marks a - * WeakMap as permitted to do what is necessary to index all host - * objects, at the cost of making it unsafe for proxies. - * - * Do not apply this function to anything which is not a genuine - * fresh WeakMap. - */ - function weakMapPermitHostObjects(map) { - // identity of function used as a secret -- good enough and cheap - if (map.permitHostObjects___) { - map.permitHostObjects___(weakMapPermitHostObjects); - } - } - if (typeof ses !== 'undefined') { - ses.weakMapPermitHostObjects = weakMapPermitHostObjects; - } - - // IE 11 has no Proxy but has a broken WeakMap such that we need to patch - // it using DoubleWeakMap; this flag tells DoubleWeakMap so. - var doubleWeakMapCheckSilentFailure = false; - - // Check if there is already a good-enough WeakMap implementation, and if so - // exit without replacing it. - if (typeof WeakMap === 'function') { - var HostWeakMap = WeakMap; - // There is a WeakMap -- is it good enough? - if (typeof navigator !== 'undefined' && - /Firefox/.test(navigator.userAgent)) { - // We're now *assuming not*, because as of this writing (2013-05-06) - // Firefox's WeakMaps have a miscellany of objects they won't accept, and - // we don't want to make an exhaustive list, and testing for just one - // will be a problem if that one is fixed alone (as they did for Event). - - // If there is a platform that we *can* reliably test on, here's how to - // do it: - // var problematic = ... ; - // var testHostMap = new HostWeakMap(); - // try { - // testHostMap.set(problematic, 1); // Firefox 20 will throw here - // if (testHostMap.get(problematic) === 1) { - // return; - // } - // } catch (e) {} - - } else { - // IE 11 bug: WeakMaps silently fail to store frozen objects. - var testMap = new HostWeakMap(); - var testObject = Object.freeze({}); - testMap.set(testObject, 1); - if (testMap.get(testObject) !== 1) { - doubleWeakMapCheckSilentFailure = true; - // Fall through to installing our WeakMap. - } else { - module.exports = WeakMap; - return; - } - } - } - - var hop = Object.prototype.hasOwnProperty; - var gopn = Object.getOwnPropertyNames; - var defProp = Object.defineProperty; - var isExtensible = Object.isExtensible; - - /** - * Security depends on HIDDEN_NAME being both unguessable and - * undiscoverable by untrusted code. - * - *

Given the known weaknesses of Math.random() on existing - * browsers, it does not generate unguessability we can be confident - * of. - * - *

It is the monkey patching logic in this file that is intended - * to ensure undiscoverability. The basic idea is that there are - * three fundamental means of discovering properties of an object: - * The for/in loop, Object.keys(), and Object.getOwnPropertyNames(), - * as well as some proposed ES6 extensions that appear on our - * whitelist. The first two only discover enumerable properties, and - * we only use HIDDEN_NAME to name a non-enumerable property, so the - * only remaining threat should be getOwnPropertyNames and some - * proposed ES6 extensions that appear on our whitelist. We monkey - * patch them to remove HIDDEN_NAME from the list of properties they - * returns. - * - *

TODO(erights): On a platform with built-in Proxies, proxies - * could be used to trap and thereby discover the HIDDEN_NAME, so we - * need to monkey patch Proxy.create, Proxy.createFunction, etc, in - * order to wrap the provided handler with the real handler which - * filters out all traps using HIDDEN_NAME. - * - *

TODO(erights): Revisit Mike Stay's suggestion that we use an - * encapsulated function at a not-necessarily-secret name, which - * uses the Stiegler shared-state rights amplification pattern to - * reveal the associated value only to the WeakMap in which this key - * is associated with that value. Since only the key retains the - * function, the function can also remember the key without causing - * leakage of the key, so this doesn't violate our general gc - * goals. In addition, because the name need not be a guarded - * secret, we could efficiently handle cross-frame frozen keys. - */ - var HIDDEN_NAME_PREFIX = 'weakmap:'; - var HIDDEN_NAME = HIDDEN_NAME_PREFIX + 'ident:' + Math.random() + '___'; - - if (typeof crypto !== 'undefined' && - typeof crypto.getRandomValues === 'function' && - typeof ArrayBuffer === 'function' && - typeof Uint8Array === 'function') { - var ab = new ArrayBuffer(25); - var u8s = new Uint8Array(ab); - crypto.getRandomValues(u8s); - HIDDEN_NAME = HIDDEN_NAME_PREFIX + 'rand:' + - Array.prototype.map.call(u8s, function(u8) { - return (u8 % 36).toString(36); - }).join('') + '___'; - } - - function isNotHiddenName(name) { - return !( - name.substr(0, HIDDEN_NAME_PREFIX.length) == HIDDEN_NAME_PREFIX && - name.substr(name.length - 3) === '___'); - } - - /** - * Monkey patch getOwnPropertyNames to avoid revealing the - * HIDDEN_NAME. - * - *

The ES5.1 spec requires each name to appear only once, but as - * of this writing, this requirement is controversial for ES6, so we - * made this code robust against this case. If the resulting extra - * search turns out to be expensive, we can probably relax this once - * ES6 is adequately supported on all major browsers, iff no browser - * versions we support at that time have relaxed this constraint - * without providing built-in ES6 WeakMaps. - */ - defProp(Object, 'getOwnPropertyNames', { - value: function fakeGetOwnPropertyNames(obj) { - return gopn(obj).filter(isNotHiddenName); - } - }); - - /** - * getPropertyNames is not in ES5 but it is proposed for ES6 and - * does appear in our whitelist, so we need to clean it too. - */ - if ('getPropertyNames' in Object) { - var originalGetPropertyNames = Object.getPropertyNames; - defProp(Object, 'getPropertyNames', { - value: function fakeGetPropertyNames(obj) { - return originalGetPropertyNames(obj).filter(isNotHiddenName); - } - }); - } - - /** - *

To treat objects as identity-keys with reasonable efficiency - * on ES5 by itself (i.e., without any object-keyed collections), we - * need to add a hidden property to such key objects when we - * can. This raises several issues: - *

    - *
  • Arranging to add this property to objects before we lose the - * chance, and - *
  • Hiding the existence of this new property from most - * JavaScript code. - *
  • Preventing certification theft, where one object is - * created falsely claiming to be the key of an association - * actually keyed by another object. - *
  • Preventing value theft, where untrusted code with - * access to a key object but not a weak map nevertheless - * obtains access to the value associated with that key in that - * weak map. - *
- * We do so by - *
    - *
  • Making the name of the hidden property unguessable, so "[]" - * indexing, which we cannot intercept, cannot be used to access - * a property without knowing the name. - *
  • Making the hidden property non-enumerable, so we need not - * worry about for-in loops or {@code Object.keys}, - *
  • monkey patching those reflective methods that would - * prevent extensions, to add this hidden property first, - *
  • monkey patching those methods that would reveal this - * hidden property. - *
- * Unfortunately, because of same-origin iframes, we cannot reliably - * add this hidden property before an object becomes - * non-extensible. Instead, if we encounter a non-extensible object - * without a hidden record that we can detect (whether or not it has - * a hidden record stored under a name secret to us), then we just - * use the key object itself to represent its identity in a brute - * force leaky map stored in the weak map, losing all the advantages - * of weakness for these. - */ - function getHiddenRecord(key) { - if (key !== Object(key)) { - throw new TypeError('Not an object: ' + key); - } - var hiddenRecord = key[HIDDEN_NAME]; - if (hiddenRecord && hiddenRecord.key === key) { return hiddenRecord; } - if (!isExtensible(key)) { - // Weak map must brute force, as explained in doc-comment above. - return void 0; - } - - // The hiddenRecord and the key point directly at each other, via - // the "key" and HIDDEN_NAME properties respectively. The key - // field is for quickly verifying that this hidden record is an - // own property, not a hidden record from up the prototype chain. - // - // NOTE: Because this WeakMap emulation is meant only for systems like - // SES where Object.prototype is frozen without any numeric - // properties, it is ok to use an object literal for the hiddenRecord. - // This has two advantages: - // * It is much faster in a performance critical place - // * It avoids relying on Object.create(null), which had been - // problematic on Chrome 28.0.1480.0. See - // https://code.google.com/p/google-caja/issues/detail?id=1687 - hiddenRecord = { key: key }; - - // When using this WeakMap emulation on platforms where - // Object.prototype might not be frozen and Object.create(null) is - // reliable, use the following two commented out lines instead. - // hiddenRecord = Object.create(null); - // hiddenRecord.key = key; - - // Please contact us if you need this to work on platforms where - // Object.prototype might not be frozen and - // Object.create(null) might not be reliable. - - try { - defProp(key, HIDDEN_NAME, { - value: hiddenRecord, - writable: false, - enumerable: false, - configurable: false - }); - return hiddenRecord; - } catch (error) { - // Under some circumstances, isExtensible seems to misreport whether - // the HIDDEN_NAME can be defined. - // The circumstances have not been isolated, but at least affect - // Node.js v0.10.26 on TravisCI / Linux, but not the same version of - // Node.js on OS X. - return void 0; - } - } - - /** - * Monkey patch operations that would make their argument - * non-extensible. - * - *

The monkey patched versions throw a TypeError if their - * argument is not an object, so it should only be done to functions - * that should throw a TypeError anyway if their argument is not an - * object. - */ - (function(){ - var oldFreeze = Object.freeze; - defProp(Object, 'freeze', { - value: function identifyingFreeze(obj) { - getHiddenRecord(obj); - return oldFreeze(obj); - } - }); - var oldSeal = Object.seal; - defProp(Object, 'seal', { - value: function identifyingSeal(obj) { - getHiddenRecord(obj); - return oldSeal(obj); - } - }); - var oldPreventExtensions = Object.preventExtensions; - defProp(Object, 'preventExtensions', { - value: function identifyingPreventExtensions(obj) { - getHiddenRecord(obj); - return oldPreventExtensions(obj); - } - }); - })(); - - function constFunc(func) { - func.prototype = null; - return Object.freeze(func); - } - - var calledAsFunctionWarningDone = false; - function calledAsFunctionWarning() { - // Future ES6 WeakMap is currently (2013-09-10) expected to reject WeakMap() - // but we used to permit it and do it ourselves, so warn only. - if (!calledAsFunctionWarningDone && typeof console !== 'undefined') { - calledAsFunctionWarningDone = true; - console.warn('WeakMap should be invoked as new WeakMap(), not ' + - 'WeakMap(). This will be an error in the future.'); - } - } - - var nextId = 0; - - var OurWeakMap = function() { - if (!(this instanceof OurWeakMap)) { // approximate test for new ...() - calledAsFunctionWarning(); - } - - // We are currently (12/25/2012) never encountering any prematurely - // non-extensible keys. - var keys = []; // brute force for prematurely non-extensible keys. - var values = []; // brute force for corresponding values. - var id = nextId++; - - function get___(key, opt_default) { - var index; - var hiddenRecord = getHiddenRecord(key); - if (hiddenRecord) { - return id in hiddenRecord ? hiddenRecord[id] : opt_default; - } else { - index = keys.indexOf(key); - return index >= 0 ? values[index] : opt_default; - } - } - - function has___(key) { - var hiddenRecord = getHiddenRecord(key); - if (hiddenRecord) { - return id in hiddenRecord; - } else { - return keys.indexOf(key) >= 0; - } - } - - function set___(key, value) { - var index; - var hiddenRecord = getHiddenRecord(key); - if (hiddenRecord) { - hiddenRecord[id] = value; - } else { - index = keys.indexOf(key); - if (index >= 0) { - values[index] = value; - } else { - // Since some browsers preemptively terminate slow turns but - // then continue computing with presumably corrupted heap - // state, we here defensively get keys.length first and then - // use it to update both the values and keys arrays, keeping - // them in sync. - index = keys.length; - values[index] = value; - // If we crash here, values will be one longer than keys. - keys[index] = key; - } - } - return this; - } - - function delete___(key) { - var hiddenRecord = getHiddenRecord(key); - var index, lastIndex; - if (hiddenRecord) { - return id in hiddenRecord && delete hiddenRecord[id]; - } else { - index = keys.indexOf(key); - if (index < 0) { - return false; - } - // Since some browsers preemptively terminate slow turns but - // then continue computing with potentially corrupted heap - // state, we here defensively get keys.length first and then use - // it to update both the keys and the values array, keeping - // them in sync. We update the two with an order of assignments, - // such that any prefix of these assignments will preserve the - // key/value correspondence, either before or after the delete. - // Note that this needs to work correctly when index === lastIndex. - lastIndex = keys.length - 1; - keys[index] = void 0; - // If we crash here, there's a void 0 in the keys array, but - // no operation will cause a "keys.indexOf(void 0)", since - // getHiddenRecord(void 0) will always throw an error first. - values[index] = values[lastIndex]; - // If we crash here, values[index] cannot be found here, - // because keys[index] is void 0. - keys[index] = keys[lastIndex]; - // If index === lastIndex and we crash here, then keys[index] - // is still void 0, since the aliasing killed the previous key. - keys.length = lastIndex; - // If we crash here, keys will be one shorter than values. - values.length = lastIndex; - return true; - } - } - - return Object.create(OurWeakMap.prototype, { - get___: { value: constFunc(get___) }, - has___: { value: constFunc(has___) }, - set___: { value: constFunc(set___) }, - delete___: { value: constFunc(delete___) } - }); - }; - - OurWeakMap.prototype = Object.create(Object.prototype, { - get: { - /** - * Return the value most recently associated with key, or - * opt_default if none. - */ - value: function get(key, opt_default) { - return this.get___(key, opt_default); - }, - writable: true, - configurable: true - }, - - has: { - /** - * Is there a value associated with key in this WeakMap? - */ - value: function has(key) { - return this.has___(key); - }, - writable: true, - configurable: true - }, - - set: { - /** - * Associate value with key in this WeakMap, overwriting any - * previous association if present. - */ - value: function set(key, value) { - return this.set___(key, value); - }, - writable: true, - configurable: true - }, - - 'delete': { - /** - * Remove any association for key in this WeakMap, returning - * whether there was one. - * - *

Note that the boolean return here does not work like the - * {@code delete} operator. The {@code delete} operator returns - * whether the deletion succeeds at bringing about a state in - * which the deleted property is absent. The {@code delete} - * operator therefore returns true if the property was already - * absent, whereas this {@code delete} method returns false if - * the association was already absent. - */ - value: function remove(key) { - return this.delete___(key); - }, - writable: true, - configurable: true - } - }); - - if (typeof HostWeakMap === 'function') { - (function() { - // If we got here, then the platform has a WeakMap but we are concerned - // that it may refuse to store some key types. Therefore, make a map - // implementation which makes use of both as possible. - - // In this mode we are always using double maps, so we are not proxy-safe. - // This combination does not occur in any known browser, but we had best - // be safe. - if (doubleWeakMapCheckSilentFailure && typeof Proxy !== 'undefined') { - Proxy = undefined; - } - - function DoubleWeakMap() { - if (!(this instanceof OurWeakMap)) { // approximate test for new ...() - calledAsFunctionWarning(); - } - - // Preferable, truly weak map. - var hmap = new HostWeakMap(); - - // Our hidden-property-based pseudo-weak-map. Lazily initialized in the - // 'set' implementation; thus we can avoid performing extra lookups if - // we know all entries actually stored are entered in 'hmap'. - var omap = undefined; - - // Hidden-property maps are not compatible with proxies because proxies - // can observe the hidden name and either accidentally expose it or fail - // to allow the hidden property to be set. Therefore, we do not allow - // arbitrary WeakMaps to switch to using hidden properties, but only - // those which need the ability, and unprivileged code is not allowed - // to set the flag. - // - // (Except in doubleWeakMapCheckSilentFailure mode in which case we - // disable proxies.) - var enableSwitching = false; - - function dget(key, opt_default) { - if (omap) { - return hmap.has(key) ? hmap.get(key) - : omap.get___(key, opt_default); - } else { - return hmap.get(key, opt_default); - } - } - - function dhas(key) { - return hmap.has(key) || (omap ? omap.has___(key) : false); - } - - var dset; - if (doubleWeakMapCheckSilentFailure) { - dset = function(key, value) { - hmap.set(key, value); - if (!hmap.has(key)) { - if (!omap) { omap = new OurWeakMap(); } - omap.set(key, value); - } - return this; - }; - } else { - dset = function(key, value) { - if (enableSwitching) { - try { - hmap.set(key, value); - } catch (e) { - if (!omap) { omap = new OurWeakMap(); } - omap.set___(key, value); - } - } else { - hmap.set(key, value); - } - return this; - }; - } - - function ddelete(key) { - var result = !!hmap['delete'](key); - if (omap) { return omap.delete___(key) || result; } - return result; - } - - return Object.create(OurWeakMap.prototype, { - get___: { value: constFunc(dget) }, - has___: { value: constFunc(dhas) }, - set___: { value: constFunc(dset) }, - delete___: { value: constFunc(ddelete) }, - permitHostObjects___: { value: constFunc(function(token) { - if (token === weakMapPermitHostObjects) { - enableSwitching = true; - } else { - throw new Error('bogus call to permitHostObjects___'); - } - })} - }); - } - DoubleWeakMap.prototype = OurWeakMap.prototype; - module.exports = DoubleWeakMap; - - // define .constructor to hide OurWeakMap ctor - Object.defineProperty(WeakMap.prototype, 'constructor', { - value: WeakMap, - enumerable: false, // as default .constructor is - configurable: true, - writable: true - }); - })(); - } else { - // There is no host WeakMap, so we must use the emulation. - - // Emulated WeakMaps are incompatible with native proxies (because proxies - // can observe the hidden name), so we must disable Proxy usage (in - // ArrayLike and Domado, currently). - if (typeof Proxy !== 'undefined') { - Proxy = undefined; - } - - module.exports = OurWeakMap; - } -})(); - -},{}],553:[function(_dereq_,module,exports){ -var hiddenStore = _dereq_('./hidden-store.js'); - -module.exports = createStore; - -function createStore() { - var key = {}; - - return function (obj) { - if ((typeof obj !== 'object' || obj === null) && - typeof obj !== 'function' - ) { - throw new Error('Weakmap-shim: Key must be object') - } - - var store = obj.valueOf(key); - return store && store.identity === key ? - store : hiddenStore(obj, key); - }; -} - -},{"./hidden-store.js":554}],554:[function(_dereq_,module,exports){ -module.exports = hiddenStore; - -function hiddenStore(obj, key) { - var store = { identity: key }; - var valueOf = obj.valueOf; - - Object.defineProperty(obj, "valueOf", { - value: function (value) { - return value !== key ? - valueOf.apply(this, arguments) : store; - }, - writable: true - }); - - return store; -} - -},{}],555:[function(_dereq_,module,exports){ -// Original - @Gozola. -// https://gist.github.com/Gozala/1269991 -// This is a reimplemented version (with a few bug fixes). - -var createStore = _dereq_('./create-store.js'); - -module.exports = weakMap; - -function weakMap() { - var privates = createStore(); - - return { - 'get': function (key, fallback) { - var store = privates(key) - return store.hasOwnProperty('value') ? - store.value : fallback - }, - 'set': function (key, value) { - privates(key).value = value; - return this; - }, - 'has': function(key) { - return 'value' in privates(key); - }, - 'delete': function (key) { - return delete privates(key).value; - } - } -} - -},{"./create-store.js":553}],556:[function(_dereq_,module,exports){ -var getContext = _dereq_('get-canvas-context') - -module.exports = function getWebGLContext (opt) { - return getContext('webgl', opt) -} - -},{"get-canvas-context":232}],557:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Traditional Chinese calendar for jQuery v2.0.2. - Written by Nicolas Riesco (enquiries@nicolasriesco.net) December 2016. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -var gregorianCalendar = main.instance(); - -/** Implementation of the traditional Chinese calendar. - Source of calendar tables https://github.com/isee15/Lunar-Solar-Calendar-Converter . - @class ChineseCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function ChineseCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -ChineseCalendar.prototype = new main.baseCalendar; - -assign(ChineseCalendar.prototype, { - /** The calendar name. - @memberof ChineseCalendar */ - name: 'Chinese', - /** Julian date of start of Gregorian epoch: 1 January 0001 CE. - @memberof GregorianCalendar */ - jdEpoch: 1721425.5, - /** true if has a year zero, false if not. - @memberof ChineseCalendar */ - hasYearZero: false, - /** The minimum month number. - This calendar uses month indices to account for intercalary months. - @memberof ChineseCalendar */ - minMonth: 0, - /** The first month in the year. - This calendar uses month indices to account for intercalary months. - @memberof ChineseCalendar */ - firstMonth: 0, - /** The minimum day number. - @memberof ChineseCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof ChineseCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Chinese', - epochs: ['BEC', 'EC'], - monthNumbers: function(date, padded) { - if (typeof date === 'string') { - var match = date.match(MONTH_NUMBER_REGEXP); - return (match) ? match[0] : ''; - } - - var year = this._validateYear(date); - var monthIndex = date.month(); - - var month = '' + this.toChineseMonth(year, monthIndex); - - if (padded && month.length < 2) { - month = "0" + month; - } - - if (this.isIntercalaryMonth(year, monthIndex)) { - month += 'i'; - } - - return month; - }, - monthNames: function(date) { - if (typeof date === 'string') { - var match = date.match(MONTH_NAME_REGEXP); - return (match) ? match[0] : ''; - } - - var year = this._validateYear(date); - var monthIndex = date.month(); - - var month = this.toChineseMonth(year, monthIndex); - - var monthName = ['一月','二月','三月','四月','五月','六月', - '七月','八月','九月','十月','十一月','十二月'][month - 1]; - - if (this.isIntercalaryMonth(year, monthIndex)) { - monthName = '闰' + monthName; - } - - return monthName; - }, - monthNamesShort: function(date) { - if (typeof date === 'string') { - var match = date.match(MONTH_SHORT_NAME_REGEXP); - return (match) ? match[0] : ''; - } - - var year = this._validateYear(date); - var monthIndex = date.month(); - - var month = this.toChineseMonth(year, monthIndex); - - var monthName = ['一','二','三','四','五','六', - '七','八','九','十','十一','十二'][month - 1]; - - if (this.isIntercalaryMonth(year, monthIndex)) { - monthName = '闰' + monthName; - } - - return monthName; - }, - parseMonth: function(year, monthString) { - year = this._validateYear(year); - var month = parseInt(monthString); - var isIntercalary; - - if (!isNaN(month)) { - var i = monthString[monthString.length - 1]; - isIntercalary = (i === 'i' || i === 'I'); - } else { - if (monthString[0] === '闰') { - isIntercalary = true; - monthString = monthString.substring(1); - } - if (monthString[monthString.length - 1] === '月') { - monthString = monthString.substring(0, monthString.length - 1); - } - month = 1 + - ['一','二','三','四','五','六', - '七','八','九','十','十一','十二'].indexOf(monthString); - } - - var monthIndex = this.toMonthIndex(year, month, isIntercalary); - return monthIndex; - }, - dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], - dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], - digits: null, - dateFormat: 'yyyy/mm/dd', - firstDay: 1, - isRTL: false - } - }, - - /** Check that a candidate date is from the same calendar and is valid. - @memberof BaseCalendar - @private - @param year {CDate|number} The date or the year to validate. - @param error {string} Error message if invalid. - @return {number} The year. - @throws Error if year out of range. */ - _validateYear: function(year, error) { - if (year.year) { - year = year.year(); - } - - if (typeof year !== 'number' || year < 1888 || year > 2111) { - throw error.replace(/\{0\}/, this.local.name); - } - - return year; - }, - - /** Retrieve the month index (i.e. accounting for intercalary months). - @memberof ChineseCalendar - @param year {number} The year. - @param month {number} The month (1 for first month). - @param [isIntercalary=false] {boolean} If month is intercalary. - @return {number} The month index (0 for first month). - @throws Error if an invalid month/year or a different calendar used. */ - toMonthIndex: function(year, month, isIntercalary) { - // compute intercalary month in the year (0 if none) - var intercalaryMonth = this.intercalaryMonth(year); - - // validate month - var invalidIntercalaryMonth = - (isIntercalary && month !== intercalaryMonth); - if (invalidIntercalaryMonth || month < 1 || month > 12) { - throw main.local.invalidMonth - .replace(/\{0\}/, this.local.name); - } - - // compute month index - var monthIndex; - - if (!intercalaryMonth) { - monthIndex = month - 1; - } else if(!isIntercalary && month <= intercalaryMonth) { - monthIndex = month - 1; - } else { - monthIndex = month; - } - - return monthIndex; - }, - - /** Retrieve the month (i.e. accounting for intercalary months). - @memberof ChineseCalendar - @param year {CDate|number} The date or the year to examine. - @param monthIndex {number} The month index (0 for first month). - @return {number} The month (1 for first month). - @throws Error if an invalid month/year or a different calendar used. */ - toChineseMonth: function(year, monthIndex) { - if (year.year) { - year = year.year(); - monthIndex = year.month(); - } - - // compute intercalary month in the year (0 if none) - var intercalaryMonth = this.intercalaryMonth(year); - - // validate month - var maxMonthIndex = (intercalaryMonth) ? 12 : 11; - if (monthIndex < 0 || monthIndex > maxMonthIndex) { - throw main.local.invalidMonth - .replace(/\{0\}/, this.local.name); - } - - // compute Chinese month - var month; - - if (!intercalaryMonth) { - month = monthIndex + 1; - } else if(monthIndex < intercalaryMonth) { - month = monthIndex + 1; - } else { - month = monthIndex; - } - - return month; - }, - - /** Determine the intercalary month of a year (if any). - @memberof ChineseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The intercalary month number, or 0 if none. - @throws Error if an invalid year or a different calendar used. */ - intercalaryMonth: function(year) { - year = this._validateYear(year); - - var monthDaysTable = LUNAR_MONTH_DAYS[year - LUNAR_MONTH_DAYS[0]]; - var intercalaryMonth = monthDaysTable >> 13; - - return intercalaryMonth; - }, - - /** Determine whether this date is an intercalary month. - @memberof ChineseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [monthIndex] {number} The month index to examine. - @return {boolean} true if this is an intercalary month, false if not. - @throws Error if an invalid year or a different calendar used. */ - isIntercalaryMonth: function(year, monthIndex) { - if (year.year) { - year = year.year(); - monthIndex = year.month(); - } - - var intercalaryMonth = this.intercalaryMonth(year); - - return !!intercalaryMonth && intercalaryMonth === monthIndex; - }, - - /** Determine whether this date is in a leap year. - @memberof ChineseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - return (this.intercalaryMonth(year) !== 0); - }, - - /** Determine the week of the year for a date - ISO 8601. - @memberof ChineseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [monthIndex] {number} The month index to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, monthIndex, day) { - // compute Chinese new year - var validatedYear = - this._validateYear(year, main.local.invalidyear); - var packedDate = - CHINESE_NEW_YEAR[validatedYear - CHINESE_NEW_YEAR[0]]; - - var y = (packedDate >> 9) & 0xFFF; - var m = (packedDate >> 5) & 0x0F; - var d = packedDate & 0x1F; - - // find first Thrusday of the year - var firstThursday; - firstThursday = gregorianCalendar.newDate(y, m, d); - firstThursday.add(4 - (firstThursday.dayOfWeek() || 7), 'd'); - - // compute days from first Thursday - var offset = - this.toJD(year, monthIndex, day) - firstThursday.toJD(); - return 1 + Math.floor(offset / 7); - }, - - /** Retrieve the number of months in a year. - @memberof ChineseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of months. - @throws Error if an invalid year or a different calendar used. */ - monthsInYear: function(year) { - return (this.leapYear(year)) ? 13 : 12; - }, - - /** Retrieve the number of days in a month. - @memberof ChineseCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [monthIndex] {number} The month index. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, monthIndex) { - if (year.year) { - monthIndex = year.month(); - year = year.year(); - } - - year = this._validateYear(year); - - var monthDaysTable = LUNAR_MONTH_DAYS[year - LUNAR_MONTH_DAYS[0]]; - - var intercalaryMonth = monthDaysTable >> 13; - var maxMonthIndex = (intercalaryMonth) ? 12 : 11; - if (monthIndex > maxMonthIndex) { - throw main.local.invalidMonth - .replace(/\{0\}/, this.local.name); - } - - var daysInMonth = (monthDaysTable & (1 << (12 - monthIndex))) ? - 30 : 29; - - return daysInMonth; - }, - - /** Determine whether this date is a week day. - @memberof ChineseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [monthIndex] {number} The month index to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, monthIndex, day) { - return (this.dayOfWeek(year, monthIndex, day) || 7) < 6; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof ChineseCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [monthIndex] {number} The month index to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, monthIndex, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - year = this._validateYear(date.year()); - monthIndex = date.month(); - day = date.day(); - - var isIntercalary = this.isIntercalaryMonth(year, monthIndex); - var month = this.toChineseMonth(year, monthIndex); - - var solar = toSolar(year, month, day, isIntercalary); - - return gregorianCalendar.toJD(solar.year, solar.month, solar.day); - }, - - /** Create a new date from a Julian date. - @memberof ChineseCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - var date = gregorianCalendar.fromJD(jd); - var lunar = toLunar(date.year(), date.month(), date.day()); - var monthIndex = this.toMonthIndex( - lunar.year, lunar.month, lunar.isIntercalary); - return this.newDate(lunar.year, monthIndex, lunar.day); - }, - - /** Create a new date from a string. - @memberof ChineseCalendar - @param dateString {string} String representing a Chinese date - @return {CDate} The new date. - @throws Error if an invalid date. */ - fromString: function(dateString) { - var match = dateString.match(DATE_REGEXP); - - var year = this._validateYear(+match[1]); - - var month = +match[2]; - var isIntercalary = !!match[3]; - var monthIndex = this.toMonthIndex(year, month, isIntercalary); - - var day = +match[4]; - - return this.newDate(year, monthIndex, day); - }, - - /** Add period(s) to a date. - Cater for no year zero. - @memberof ChineseCalendar - @param date {CDate} The starting date. - @param offset {number} The number of periods to adjust by. - @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. - @return {CDate} The updated date. - @throws Error if a different calendar used. */ - add: function(date, offset, period) { - var year = date.year(); - var monthIndex = date.month(); - var isIntercalary = this.isIntercalaryMonth(year, monthIndex); - var month = this.toChineseMonth(year, monthIndex); - - var cdate = Object.getPrototypeOf(ChineseCalendar.prototype) - .add.call(this, date, offset, period); - - if (period === 'y') { - // Resync month - var resultYear = cdate.year(); - var resultMonthIndex = cdate.month(); - - // Using the fact the month index of an intercalary month - // equals its month number: - var resultCanBeIntercalaryMonth = - this.isIntercalaryMonth(resultYear, month); - - var correctedMonthIndex = - (isIntercalary && resultCanBeIntercalaryMonth) ? - this.toMonthIndex(resultYear, month, true) : - this.toMonthIndex(resultYear, month, false); - - if (correctedMonthIndex !== resultMonthIndex) { - cdate.month(correctedMonthIndex); - } - } - - return cdate; - }, -}); - -// Used by ChineseCalendar.prototype.fromString -var DATE_REGEXP = /^\s*(-?\d\d\d\d|\d\d)[-/](\d?\d)([iI]?)[-/](\d?\d)/m; -var MONTH_NUMBER_REGEXP = /^\d?\d[iI]?/m; -var MONTH_NAME_REGEXP = /^闰?十?[一二三四五六七八九]?月/m; -var MONTH_SHORT_NAME_REGEXP = /^闰?十?[一二三四五六七八九]?/m; - -// Chinese calendar implementation -main.calendars.chinese = ChineseCalendar; - -// Chinese calendar tables from year 1888 to 2111 -// -// Source: -// https://github.com/isee15/Lunar-Solar-Calendar-Converter.git - -// Table of intercalary months and days per month from year 1888 to 2111 -// -// bit (12 - i): days in the i^th month -// (= 0 if i^th lunar month has 29 days) -// (= 1 if i^th lunar month has 30 days) -// (first month in lunar year is i = 0) -// bits (13,14,15,16): intercalary month -// (= 0 if lunar year has no intercalary month) -var LUNAR_MONTH_DAYS = [1887, 0x1694, 0x16aa, 0x4ad5, - 0xab6, 0xc4b7, 0x4ae, 0xa56, 0xb52a, 0x1d2a, 0xd54, 0x75aa, 0x156a, - 0x1096d, 0x95c, 0x14ae, 0xaa4d, 0x1a4c, 0x1b2a, 0x8d55, 0xad4, - 0x135a, 0x495d, 0x95c, 0xd49b, 0x149a, 0x1a4a, 0xbaa5, 0x16a8, - 0x1ad4, 0x52da, 0x12b6, 0xe937, 0x92e, 0x1496, 0xb64b, 0xd4a, - 0xda8, 0x95b5, 0x56c, 0x12ae, 0x492f, 0x92e, 0xcc96, 0x1a94, - 0x1d4a, 0xada9, 0xb5a, 0x56c, 0x726e, 0x125c, 0xf92d, 0x192a, - 0x1a94, 0xdb4a, 0x16aa, 0xad4, 0x955b, 0x4ba, 0x125a, 0x592b, - 0x152a, 0xf695, 0xd94, 0x16aa, 0xaab5, 0x9b4, 0x14b6, 0x6a57, - 0xa56, 0x1152a, 0x1d2a, 0xd54, 0xd5aa, 0x156a, 0x96c, 0x94ae, - 0x14ae, 0xa4c, 0x7d26, 0x1b2a, 0xeb55, 0xad4, 0x12da, 0xa95d, - 0x95a, 0x149a, 0x9a4d, 0x1a4a, 0x11aa5, 0x16a8, 0x16d4, 0xd2da, - 0x12b6, 0x936, 0x9497, 0x1496, 0x1564b, 0xd4a, 0xda8, 0xd5b4, - 0x156c, 0x12ae, 0xa92f, 0x92e, 0xc96, 0x6d4a, 0x1d4a, 0x10d65, - 0xb58, 0x156c, 0xb26d, 0x125c, 0x192c, 0x9a95, 0x1a94, 0x1b4a, - 0x4b55, 0xad4, 0xf55b, 0x4ba, 0x125a, 0xb92b, 0x152a, 0x1694, - 0x96aa, 0x15aa, 0x12ab5, 0x974, 0x14b6, 0xca57, 0xa56, 0x1526, - 0x8e95, 0xd54, 0x15aa, 0x49b5, 0x96c, 0xd4ae, 0x149c, 0x1a4c, - 0xbd26, 0x1aa6, 0xb54, 0x6d6a, 0x12da, 0x1695d, 0x95a, 0x149a, - 0xda4b, 0x1a4a, 0x1aa4, 0xbb54, 0x16b4, 0xada, 0x495b, 0x936, - 0xf497, 0x1496, 0x154a, 0xb6a5, 0xda4, 0x15b4, 0x6ab6, 0x126e, - 0x1092f, 0x92e, 0xc96, 0xcd4a, 0x1d4a, 0xd64, 0x956c, 0x155c, - 0x125c, 0x792e, 0x192c, 0xfa95, 0x1a94, 0x1b4a, 0xab55, 0xad4, - 0x14da, 0x8a5d, 0xa5a, 0x1152b, 0x152a, 0x1694, 0xd6aa, 0x15aa, - 0xab4, 0x94ba, 0x14b6, 0xa56, 0x7527, 0xd26, 0xee53, 0xd54, 0x15aa, - 0xa9b5, 0x96c, 0x14ae, 0x8a4e, 0x1a4c, 0x11d26, 0x1aa4, 0x1b54, - 0xcd6a, 0xada, 0x95c, 0x949d, 0x149a, 0x1a2a, 0x5b25, 0x1aa4, - 0xfb52, 0x16b4, 0xaba, 0xa95b, 0x936, 0x1496, 0x9a4b, 0x154a, - 0x136a5, 0xda4, 0x15ac]; - -// Table of Chinese New Years from year 1888 to 2111 -// -// bits (0 to 4): solar day -// bits (5 to 8): solar month -// bits (9 to 20): solar year -var CHINESE_NEW_YEAR = [1887, 0xec04c, 0xec23f, 0xec435, 0xec649, - 0xec83e, 0xeca51, 0xecc46, 0xece3a, 0xed04d, 0xed242, 0xed436, - 0xed64a, 0xed83f, 0xeda53, 0xedc48, 0xede3d, 0xee050, 0xee244, - 0xee439, 0xee64d, 0xee842, 0xeea36, 0xeec4a, 0xeee3e, 0xef052, - 0xef246, 0xef43a, 0xef64e, 0xef843, 0xefa37, 0xefc4b, 0xefe41, - 0xf0054, 0xf0248, 0xf043c, 0xf0650, 0xf0845, 0xf0a38, 0xf0c4d, - 0xf0e42, 0xf1037, 0xf124a, 0xf143e, 0xf1651, 0xf1846, 0xf1a3a, - 0xf1c4e, 0xf1e44, 0xf2038, 0xf224b, 0xf243f, 0xf2653, 0xf2848, - 0xf2a3b, 0xf2c4f, 0xf2e45, 0xf3039, 0xf324d, 0xf3442, 0xf3636, - 0xf384a, 0xf3a3d, 0xf3c51, 0xf3e46, 0xf403b, 0xf424e, 0xf4443, - 0xf4638, 0xf484c, 0xf4a3f, 0xf4c52, 0xf4e48, 0xf503c, 0xf524f, - 0xf5445, 0xf5639, 0xf584d, 0xf5a42, 0xf5c35, 0xf5e49, 0xf603e, - 0xf6251, 0xf6446, 0xf663b, 0xf684f, 0xf6a43, 0xf6c37, 0xf6e4b, - 0xf703f, 0xf7252, 0xf7447, 0xf763c, 0xf7850, 0xf7a45, 0xf7c39, - 0xf7e4d, 0xf8042, 0xf8254, 0xf8449, 0xf863d, 0xf8851, 0xf8a46, - 0xf8c3b, 0xf8e4f, 0xf9044, 0xf9237, 0xf944a, 0xf963f, 0xf9853, - 0xf9a47, 0xf9c3c, 0xf9e50, 0xfa045, 0xfa238, 0xfa44c, 0xfa641, - 0xfa836, 0xfaa49, 0xfac3d, 0xfae52, 0xfb047, 0xfb23a, 0xfb44e, - 0xfb643, 0xfb837, 0xfba4a, 0xfbc3f, 0xfbe53, 0xfc048, 0xfc23c, - 0xfc450, 0xfc645, 0xfc839, 0xfca4c, 0xfcc41, 0xfce36, 0xfd04a, - 0xfd23d, 0xfd451, 0xfd646, 0xfd83a, 0xfda4d, 0xfdc43, 0xfde37, - 0xfe04b, 0xfe23f, 0xfe453, 0xfe648, 0xfe83c, 0xfea4f, 0xfec44, - 0xfee38, 0xff04c, 0xff241, 0xff436, 0xff64a, 0xff83e, 0xffa51, - 0xffc46, 0xffe3a, 0x10004e, 0x100242, 0x100437, 0x10064b, 0x100841, - 0x100a53, 0x100c48, 0x100e3c, 0x10104f, 0x101244, 0x101438, - 0x10164c, 0x101842, 0x101a35, 0x101c49, 0x101e3d, 0x102051, - 0x102245, 0x10243a, 0x10264e, 0x102843, 0x102a37, 0x102c4b, - 0x102e3f, 0x103053, 0x103247, 0x10343b, 0x10364f, 0x103845, - 0x103a38, 0x103c4c, 0x103e42, 0x104036, 0x104249, 0x10443d, - 0x104651, 0x104846, 0x104a3a, 0x104c4e, 0x104e43, 0x105038, - 0x10524a, 0x10543e, 0x105652, 0x105847, 0x105a3b, 0x105c4f, - 0x105e45, 0x106039, 0x10624c, 0x106441, 0x106635, 0x106849, - 0x106a3d, 0x106c51, 0x106e47, 0x10703c, 0x10724f, 0x107444, - 0x107638, 0x10784c, 0x107a3f, 0x107c53, 0x107e48]; - -function toLunar(yearOrDate, monthOrResult, day, result) { - var solarDate; - var lunarDate; - - if(typeof yearOrDate === 'object') { - solarDate = yearOrDate; - lunarDate = monthOrResult || {}; - - } else { - var isValidYear = (typeof yearOrDate === 'number') && - (yearOrDate >= 1888) && (yearOrDate <= 2111); - if(!isValidYear) - throw new Error("Solar year outside range 1888-2111"); - - var isValidMonth = (typeof monthOrResult === 'number') && - (monthOrResult >= 1) && (monthOrResult <= 12); - if(!isValidMonth) - throw new Error("Solar month outside range 1 - 12"); - - var isValidDay = (typeof day === 'number') && (day >= 1) && (day <= 31); - if(!isValidDay) - throw new Error("Solar day outside range 1 - 31"); - - solarDate = { - year: yearOrDate, - month: monthOrResult, - day: day, - }; - lunarDate = result || {}; - } - - // Compute Chinese new year and lunar year - var chineseNewYearPackedDate = - CHINESE_NEW_YEAR[solarDate.year - CHINESE_NEW_YEAR[0]]; - - var packedDate = (solarDate.year << 9) | (solarDate.month << 5) - | solarDate.day; - - lunarDate.year = (packedDate >= chineseNewYearPackedDate) ? - solarDate.year : - solarDate.year - 1; - - chineseNewYearPackedDate = - CHINESE_NEW_YEAR[lunarDate.year - CHINESE_NEW_YEAR[0]]; - - var y = (chineseNewYearPackedDate >> 9) & 0xFFF; - var m = (chineseNewYearPackedDate >> 5) & 0x0F; - var d = chineseNewYearPackedDate & 0x1F; - - // Compute days from new year - var daysFromNewYear; - - var chineseNewYearJSDate = new Date(y, m -1, d); - var jsDate = new Date(solarDate.year, solarDate.month - 1, solarDate.day); - - daysFromNewYear = Math.round( - (jsDate - chineseNewYearJSDate) / (24 * 3600 * 1000)); - - // Compute lunar month and day - var monthDaysTable = LUNAR_MONTH_DAYS[lunarDate.year - LUNAR_MONTH_DAYS[0]]; - - var i; - for(i = 0; i < 13; i++) { - var daysInMonth = (monthDaysTable & (1 << (12 - i))) ? 30 : 29; - - if (daysFromNewYear < daysInMonth) { - break; - } - - daysFromNewYear -= daysInMonth; - } - - var intercalaryMonth = monthDaysTable >> 13; - if (!intercalaryMonth || i < intercalaryMonth) { - lunarDate.isIntercalary = false; - lunarDate.month = 1 + i; - } else if (i === intercalaryMonth) { - lunarDate.isIntercalary = true; - lunarDate.month = i; - } else { - lunarDate.isIntercalary = false; - lunarDate.month = i; - } - - lunarDate.day = 1 + daysFromNewYear; - - return lunarDate; -} - -function toSolar(yearOrDate, monthOrResult, day, isIntercalaryOrResult, result) { - var solarDate; - var lunarDate; - - if(typeof yearOrDate === 'object') { - lunarDate = yearOrDate; - solarDate = monthOrResult || {}; - - } else { - var isValidYear = (typeof yearOrDate === 'number') && - (yearOrDate >= 1888) && (yearOrDate <= 2111); - if(!isValidYear) - throw new Error("Lunar year outside range 1888-2111"); - - var isValidMonth = (typeof monthOrResult === 'number') && - (monthOrResult >= 1) && (monthOrResult <= 12); - if(!isValidMonth) - throw new Error("Lunar month outside range 1 - 12"); - - var isValidDay = (typeof day === 'number') && (day >= 1) && (day <= 30); - if(!isValidDay) - throw new Error("Lunar day outside range 1 - 30"); - - var isIntercalary; - if(typeof isIntercalaryOrResult === 'object') { - isIntercalary = false; - solarDate = isIntercalaryOrResult; - } else { - isIntercalary = !!isIntercalaryOrResult; - solarDate = result || {}; - } - - lunarDate = { - year: yearOrDate, - month: monthOrResult, - day: day, - isIntercalary: isIntercalary, - }; - } - - // Compute days from new year - var daysFromNewYear; - - daysFromNewYear = lunarDate.day - 1; - - var monthDaysTable = LUNAR_MONTH_DAYS[lunarDate.year - LUNAR_MONTH_DAYS[0]]; - var intercalaryMonth = monthDaysTable >> 13; - - var monthsFromNewYear; - if (!intercalaryMonth) { - monthsFromNewYear = lunarDate.month - 1; - } else if (lunarDate.month > intercalaryMonth) { - monthsFromNewYear = lunarDate.month; - } else if (lunarDate.isIntercalary) { - monthsFromNewYear = lunarDate.month; - } else { - monthsFromNewYear = lunarDate.month - 1; - } - - for(var i = 0; i < monthsFromNewYear; i++) { - var daysInMonth = (monthDaysTable & (1 << (12 - i))) ? 30 : 29; - daysFromNewYear += daysInMonth; - } - - // Compute Chinese new year - var packedDate = CHINESE_NEW_YEAR[lunarDate.year - CHINESE_NEW_YEAR[0]]; - - var y = (packedDate >> 9) & 0xFFF; - var m = (packedDate >> 5) & 0x0F; - var d = packedDate & 0x1F; - - // Compute solar date - var jsDate = new Date(y, m - 1, d + daysFromNewYear); - - solarDate.year = jsDate.getFullYear(); - solarDate.month = 1 + jsDate.getMonth(); - solarDate.day = jsDate.getDate(); - - return solarDate; -} - - -},{"../main":571,"object-assign":454}],558:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Coptic calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) February 2010. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Coptic calendar. - See http://en.wikipedia.org/wiki/Coptic_calendar. - See also Calendrical Calculations: The Millennium Edition - (http://emr.cs.iit.edu/home/reingold/calendar-book/index.shtml). - @class CopticCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function CopticCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -CopticCalendar.prototype = new main.baseCalendar; - -assign(CopticCalendar.prototype, { - /** The calendar name. - @memberof CopticCalendar */ - name: 'Coptic', - /** Julian date of start of Coptic epoch: 29 August 284 CE (Gregorian). - @memberof CopticCalendar */ - jdEpoch: 1825029.5, - /** Days per month in a common year. - @memberof CopticCalendar */ - daysPerMonth: [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 5], - /** true if has a year zero, false if not. - @memberof CopticCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof CopticCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof CopticCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof CopticCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof CopticCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Coptic', - epochs: ['BAM', 'AM'], - monthNames: ['Thout', 'Paopi', 'Hathor', 'Koiak', 'Tobi', 'Meshir', - 'Paremhat', 'Paremoude', 'Pashons', 'Paoni', 'Epip', 'Mesori', 'Pi Kogi Enavot'], - monthNamesShort: ['Tho', 'Pao', 'Hath', 'Koi', 'Tob', 'Mesh', - 'Pat', 'Pad', 'Pash', 'Pao', 'Epi', 'Meso', 'PiK'], - dayNames: ['Tkyriaka', 'Pesnau', 'Pshoment', 'Peftoou', 'Ptiou', 'Psoou', 'Psabbaton'], - dayNamesShort: ['Tky', 'Pes', 'Psh', 'Pef', 'Pti', 'Pso', 'Psa'], - dayNamesMin: ['Tk', 'Pes', 'Psh', 'Pef', 'Pt', 'Pso', 'Psa'], - digits: null, - dateFormat: 'dd/mm/yyyy', - firstDay: 0, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof CopticCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - var year = date.year() + (date.year() < 0 ? 1 : 0); // No year zero - return year % 4 === 3 || year % 4 === -1; - }, - - /** Retrieve the number of months in a year. - @memberof CopticCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of months. - @throws Error if an invalid year or a different calendar used. */ - monthsInYear: function(year) { - this._validate(year, this.minMonth, this.minDay, - main.local.invalidYear || main.regionalOptions[''].invalidYear); - return 13; - }, - - /** Determine the week of the year for a date. - @memberof CopticCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number) the month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Sunday of this week starting on Sunday - var checkDate = this.newDate(year, month, day); - checkDate.add(-checkDate.dayOfWeek(), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a month. - @memberof CopticCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - return this.daysPerMonth[date.month() - 1] + - (date.month() === 13 && this.leapYear(date.year()) ? 1 : 0); - }, - - /** Determine whether this date is a week day. - @memberof CopticCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param month {number} The month to examine. - @param day {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return (this.dayOfWeek(year, month, day) || 7) < 6; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof CopticCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number) the month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - year = date.year(); - if (year < 0) { year++; } // No year zero - return date.day() + (date.month() - 1) * 30 + - (year - 1) * 365 + Math.floor(year / 4) + this.jdEpoch - 1; - }, - - /** Create a new date from a Julian date. - @memberof CopticCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - var c = Math.floor(jd) + 0.5 - this.jdEpoch; - var year = Math.floor((c - Math.floor((c + 366) / 1461)) / 365) + 1; - if (year <= 0) { year--; } // No year zero - c = Math.floor(jd) + 0.5 - this.newDate(year, 1, 1).toJD(); - var month = Math.floor(c / 30) + 1; - var day = c - (month - 1) * 30 + 1; - return this.newDate(year, month, day); - } -}); - -// Coptic calendar implementation -main.calendars.coptic = CopticCalendar; - - -},{"../main":571,"object-assign":454}],559:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Discworld calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) January 2016. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Discworld calendar - Unseen University version. - See also http://wiki.lspace.org/mediawiki/Discworld_calendar - and http://discworld.wikia.com/wiki/Discworld_calendar. - @class DiscworldCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function DiscworldCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -DiscworldCalendar.prototype = new main.baseCalendar; - -assign(DiscworldCalendar.prototype, { - /** The calendar name. - @memberof DiscworldCalendar */ - name: 'Discworld', - /** Julian date of start of Discworld epoch: 1 January 0001 CE. - @memberof DiscworldCalendar */ - jdEpoch: 1721425.5, - /** Days per month in a common year. - @memberof DiscworldCalendar */ - daysPerMonth: [16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32], - /** true if has a year zero, false if not. - @memberof DiscworldCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof DiscworldCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof DiscworldCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof DiscworldCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof DiscworldCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Discworld', - epochs: ['BUC', 'UC'], - monthNames: ['Ick', 'Offle', 'February', 'March', 'April', 'May', 'June', - 'Grune', 'August', 'Spune', 'Sektober', 'Ember', 'December'], - monthNamesShort: ['Ick', 'Off', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Gru', 'Aug', 'Spu', 'Sek', 'Emb', 'Dec'], - dayNames: ['Sunday', 'Octeday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - dayNamesShort: ['Sun', 'Oct', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], - dayNamesMin: ['Su', 'Oc', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], - digits: null, - dateFormat: 'yyyy/mm/dd', - firstDay: 2, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof DiscworldCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return false; - }, - - /** Retrieve the number of months in a year. - @memberof DiscworldCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of months. - @throws Error if an invalid year or a different calendar used. */ - monthsInYear: function(year) { - this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return 13; - }, - - /** Retrieve the number of days in a year. - @memberof DiscworldCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of days. - @throws Error if an invalid year or a different calendar used. */ - daysInYear: function(year) { - this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return 400; - }, - - /** Determine the week of the year for a date. - @memberof DiscworldCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Sunday of this week starting on Sunday - var checkDate = this.newDate(year, month, day); - checkDate.add(-checkDate.dayOfWeek(), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 8) + 1; - }, - - /** Retrieve the number of days in a month. - @memberof DiscworldCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - return this.daysPerMonth[date.month() - 1]; - }, - - /** Retrieve the number of days in a week. - @memberof DiscworldCalendar - @return {number} The number of days. */ - daysInWeek: function() { - return 8; - }, - - /** Retrieve the day of the week for a date. - @memberof DiscworldCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The day of the week: 0 to number of days - 1. - @throws Error if an invalid date or a different calendar used. */ - dayOfWeek: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - return (date.day() + 1) % 8; - }, - - /** Determine whether this date is a week day. - @memberof DiscworldCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - var dow = this.dayOfWeek(year, month, day); - return (dow >= 2 && dow <= 6); - }, - - /** Retrieve additional information about a date. - @memberof DiscworldCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {object} Additional information - contents depends on calendar. - @throws Error if an invalid date or a different calendar used. */ - extraInfo: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - return {century: centuries[Math.floor((date.year() - 1) / 100) + 1] || ''}; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof DiscworldCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - year = date.year() + (date.year() < 0 ? 1 : 0); - month = date.month(); - day = date.day(); - return day + (month > 1 ? 16 : 0) + (month > 2 ? (month - 2) * 32 : 0) + - (year - 1) * 400 + this.jdEpoch - 1; - }, - - /** Create a new date from a Julian date. - @memberof DiscworldCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - jd = Math.floor(jd + 0.5) - Math.floor(this.jdEpoch) - 1; - var year = Math.floor(jd / 400) + 1; - jd -= (year - 1) * 400; - jd += (jd > 15 ? 16 : 0); - var month = Math.floor(jd / 32) + 1; - var day = jd - (month - 1) * 32 + 1; - return this.newDate(year <= 0 ? year - 1 : year, month, day); - } -}); - -// Names of the centuries -var centuries = { - 20: 'Fruitbat', - 21: 'Anchovy' -}; - -// Discworld calendar implementation -main.calendars.discworld = DiscworldCalendar; - - -},{"../main":571,"object-assign":454}],560:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Ethiopian calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) February 2010. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Ethiopian calendar. - See http://en.wikipedia.org/wiki/Ethiopian_calendar. - See also Calendrical Calculations: The Millennium Edition - (http://emr.cs.iit.edu/home/reingold/calendar-book/index.shtml). - @class EthiopianCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function EthiopianCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -EthiopianCalendar.prototype = new main.baseCalendar; - -assign(EthiopianCalendar.prototype, { - /** The calendar name. - @memberof EthiopianCalendar */ - name: 'Ethiopian', - /** Julian date of start of Ethiopian epoch: 27 August 8 CE (Gregorian). - @memberof EthiopianCalendar */ - jdEpoch: 1724220.5, - /** Days per month in a common year. - @memberof EthiopianCalendar */ - daysPerMonth: [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 5], - /** true if has a year zero, false if not. - @memberof EthiopianCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof EthiopianCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof EthiopianCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof EthiopianCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof EthiopianCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Ethiopian', - epochs: ['BEE', 'EE'], - monthNames: ['Meskerem', 'Tikemet', 'Hidar', 'Tahesas', 'Tir', 'Yekatit', - 'Megabit', 'Miazia', 'Genbot', 'Sene', 'Hamle', 'Nehase', 'Pagume'], - monthNamesShort: ['Mes', 'Tik', 'Hid', 'Tah', 'Tir', 'Yek', - 'Meg', 'Mia', 'Gen', 'Sen', 'Ham', 'Neh', 'Pag'], - dayNames: ['Ehud', 'Segno', 'Maksegno', 'Irob', 'Hamus', 'Arb', 'Kidame'], - dayNamesShort: ['Ehu', 'Seg', 'Mak', 'Iro', 'Ham', 'Arb', 'Kid'], - dayNamesMin: ['Eh', 'Se', 'Ma', 'Ir', 'Ha', 'Ar', 'Ki'], - digits: null, - dateFormat: 'dd/mm/yyyy', - firstDay: 0, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof EthiopianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - var year = date.year() + (date.year() < 0 ? 1 : 0); // No year zero - return year % 4 === 3 || year % 4 === -1; - }, - - /** Retrieve the number of months in a year. - @memberof EthiopianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of months. - @throws Error if an invalid year or a different calendar used. */ - monthsInYear: function(year) { - this._validate(year, this.minMonth, this.minDay, - main.local.invalidYear || main.regionalOptions[''].invalidYear); - return 13; - }, - - /** Determine the week of the year for a date. - @memberof EthiopianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Sunday of this week starting on Sunday - var checkDate = this.newDate(year, month, day); - checkDate.add(-checkDate.dayOfWeek(), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a month. - @memberof EthiopianCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - return this.daysPerMonth[date.month() - 1] + - (date.month() === 13 && this.leapYear(date.year()) ? 1 : 0); - }, - - /** Determine whether this date is a week day. - @memberof EthiopianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return (this.dayOfWeek(year, month, day) || 7) < 6; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof EthiopianCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - year = date.year(); - if (year < 0) { year++; } // No year zero - return date.day() + (date.month() - 1) * 30 + - (year - 1) * 365 + Math.floor(year / 4) + this.jdEpoch - 1; - }, - - /** Create a new date from a Julian date. - @memberof EthiopianCalendar - @param jd {number} the Julian date to convert. - @return {CDate} the equivalent date. */ - fromJD: function(jd) { - var c = Math.floor(jd) + 0.5 - this.jdEpoch; - var year = Math.floor((c - Math.floor((c + 366) / 1461)) / 365) + 1; - if (year <= 0) { year--; } // No year zero - c = Math.floor(jd) + 0.5 - this.newDate(year, 1, 1).toJD(); - var month = Math.floor(c / 30) + 1; - var day = c - (month - 1) * 30 + 1; - return this.newDate(year, month, day); - } -}); - -// Ethiopian calendar implementation -main.calendars.ethiopian = EthiopianCalendar; - - -},{"../main":571,"object-assign":454}],561:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Hebrew calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Hebrew civil calendar. - Based on code from http://www.fourmilab.ch/documents/calendar/. - See also http://en.wikipedia.org/wiki/Hebrew_calendar. - @class HebrewCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function HebrewCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -HebrewCalendar.prototype = new main.baseCalendar; - -assign(HebrewCalendar.prototype, { - /** The calendar name. - @memberof HebrewCalendar */ - name: 'Hebrew', - /** Julian date of start of Hebrew epoch: 7 October 3761 BCE. - @memberof HebrewCalendar */ - jdEpoch: 347995.5, - /** Days per month in a common year. - @memberof HebrewCalendar */ - daysPerMonth: [30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 29], - /** true if has a year zero, false if not. - @memberof HebrewCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof HebrewCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof HebrewCalendar */ - firstMonth: 7, - /** The minimum day number. - @memberof HebrewCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof HebrewCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Hebrew', - epochs: ['BAM', 'AM'], - monthNames: ['Nisan', 'Iyar', 'Sivan', 'Tammuz', 'Av', 'Elul', - 'Tishrei', 'Cheshvan', 'Kislev', 'Tevet', 'Shevat', 'Adar', 'Adar II'], - monthNamesShort: ['Nis', 'Iya', 'Siv', 'Tam', 'Av', 'Elu', 'Tis', 'Che', 'Kis', 'Tev', 'She', 'Ada', 'Ad2'], - dayNames: ['Yom Rishon', 'Yom Sheni', 'Yom Shlishi', 'Yom Revi\'i', 'Yom Chamishi', 'Yom Shishi', 'Yom Shabbat'], - dayNamesShort: ['Ris', 'She', 'Shl', 'Rev', 'Cha', 'Shi', 'Sha'], - dayNamesMin: ['Ri','She','Shl','Re','Ch','Shi','Sha'], - digits: null, - dateFormat: 'dd/mm/yyyy', - firstDay: 0, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof HebrewCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return this._leapYear(date.year()); - }, - - /** Determine whether this date is in a leap year. - @memberof HebrewCalendar - @private - @param year {number} The year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - _leapYear: function(year) { - year = (year < 0 ? year + 1 : year); - return mod(year * 7 + 1, 19) < 7; - }, - - /** Retrieve the number of months in a year. - @memberof HebrewCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of months. - @throws Error if an invalid year or a different calendar used. */ - monthsInYear: function(year) { - this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return this._leapYear(year.year ? year.year() : year) ? 13 : 12; - }, - - /** Determine the week of the year for a date. - @memberof HebrewCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Sunday of this week starting on Sunday - var checkDate = this.newDate(year, month, day); - checkDate.add(-checkDate.dayOfWeek(), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a year. - @memberof HebrewCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of days. - @throws Error if an invalid year or a different calendar used. */ - daysInYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - year = date.year(); - return this.toJD((year === -1 ? +1 : year + 1), 7, 1) - this.toJD(year, 7, 1); - }, - - /** Retrieve the number of days in a month. - @memberof HebrewCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - if (year.year) { - month = year.month(); - year = year.year(); - } - this._validate(year, month, this.minDay, main.local.invalidMonth); - return (month === 12 && this.leapYear(year) ? 30 : // Adar I - (month === 8 && mod(this.daysInYear(year), 10) === 5 ? 30 : // Cheshvan in shlemah year - (month === 9 && mod(this.daysInYear(year), 10) === 3 ? 29 : // Kislev in chaserah year - this.daysPerMonth[month - 1]))); - }, - - /** Determine whether this date is a week day. - @memberof HebrewCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return this.dayOfWeek(year, month, day) !== 6; - }, - - /** Retrieve additional information about a date - year type. - @memberof HebrewCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {object} Additional information - contents depends on calendar. - @throws Error if an invalid date or a different calendar used. */ - extraInfo: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - return {yearType: (this.leapYear(date) ? 'embolismic' : 'common') + ' ' + - ['deficient', 'regular', 'complete'][this.daysInYear(date) % 10 - 3]}; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof HebrewCalendar - @param year {CDate)|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - year = date.year(); - month = date.month(); - day = date.day(); - var adjYear = (year <= 0 ? year + 1 : year); - var jd = this.jdEpoch + this._delay1(adjYear) + - this._delay2(adjYear) + day + 1; - if (month < 7) { - for (var m = 7; m <= this.monthsInYear(year); m++) { - jd += this.daysInMonth(year, m); - } - for (var m = 1; m < month; m++) { - jd += this.daysInMonth(year, m); - } - } - else { - for (var m = 7; m < month; m++) { - jd += this.daysInMonth(year, m); - } - } - return jd; - }, - - /** Test for delay of start of new year and to avoid - Sunday, Wednesday, or Friday as start of the new year. - @memberof HebrewCalendar - @private - @param year {number} The year to examine. - @return {number} The days to offset by. */ - _delay1: function(year) { - var months = Math.floor((235 * year - 234) / 19); - var parts = 12084 + 13753 * months; - var day = months * 29 + Math.floor(parts / 25920); - if (mod(3 * (day + 1), 7) < 3) { - day++; - } - return day; - }, - - /** Check for delay in start of new year due to length of adjacent years. - @memberof HebrewCalendar - @private - @param year {number} The year to examine. - @return {number} The days to offset by. */ - _delay2: function(year) { - var last = this._delay1(year - 1); - var present = this._delay1(year); - var next = this._delay1(year + 1); - return ((next - present) === 356 ? 2 : ((present - last) === 382 ? 1 : 0)); - }, - - /** Create a new date from a Julian date. - @memberof HebrewCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - jd = Math.floor(jd) + 0.5; - var year = Math.floor(((jd - this.jdEpoch) * 98496.0) / 35975351.0) - 1; - while (jd >= this.toJD((year === -1 ? +1 : year + 1), 7, 1)) { - year++; - } - var month = (jd < this.toJD(year, 1, 1)) ? 7 : 1; - while (jd > this.toJD(year, month, this.daysInMonth(year, month))) { - month++; - } - var day = jd - this.toJD(year, month, 1) + 1; - return this.newDate(year, month, day); - } -}); - -// Modulus function which works for non-integers. -function mod(a, b) { - return a - (b * Math.floor(a / b)); -} - -// Hebrew calendar implementation -main.calendars.hebrew = HebrewCalendar; - - -},{"../main":571,"object-assign":454}],562:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Islamic calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Islamic or '16 civil' calendar. - Based on code from http://www.iranchamber.com/calendar/converter/iranian_calendar_converter.php. - See also http://en.wikipedia.org/wiki/Islamic_calendar. - @class IslamicCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function IslamicCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -IslamicCalendar.prototype = new main.baseCalendar; - -assign(IslamicCalendar.prototype, { - /** The calendar name. - @memberof IslamicCalendar */ - name: 'Islamic', - /** Julian date of start of Islamic epoch: 16 July 622 CE. - @memberof IslamicCalendar */ - jdEpoch: 1948439.5, - /** Days per month in a common year. - @memberof IslamicCalendar */ - daysPerMonth: [30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29], - /** true if has a year zero, false if not. - @memberof IslamicCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof IslamicCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof IslamicCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof IslamicCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof IslamicCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Islamic', - epochs: ['BH', 'AH'], - monthNames: ['Muharram', 'Safar', 'Rabi\' al-awwal', 'Rabi\' al-thani', 'Jumada al-awwal', 'Jumada al-thani', - 'Rajab', 'Sha\'aban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah'], - monthNamesShort: ['Muh', 'Saf', 'Rab1', 'Rab2', 'Jum1', 'Jum2', 'Raj', 'Sha\'', 'Ram', 'Shaw', 'DhuQ', 'DhuH'], - dayNames: ['Yawm al-ahad', 'Yawm al-ithnayn', 'Yawm ath-thulaathaa\'', - 'Yawm al-arbi\'aa\'', 'Yawm al-khamīs', 'Yawm al-jum\'a', 'Yawm as-sabt'], - dayNamesShort: ['Aha', 'Ith', 'Thu', 'Arb', 'Kha', 'Jum', 'Sab'], - dayNamesMin: ['Ah','It','Th','Ar','Kh','Ju','Sa'], - digits: null, - dateFormat: 'yyyy/mm/dd', - firstDay: 6, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof IslamicCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return (date.year() * 11 + 14) % 30 < 11; - }, - - /** Determine the week of the year for a date. - @memberof IslamicCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Sunday of this week starting on Sunday - var checkDate = this.newDate(year, month, day); - checkDate.add(-checkDate.dayOfWeek(), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a year. - @memberof IslamicCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of days. - @throws Error if an invalid year or a different calendar used. */ - daysInYear: function(year) { - return (this.leapYear(year) ? 355 : 354); - }, - - /** Retrieve the number of days in a month. - @memberof IslamicCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - return this.daysPerMonth[date.month() - 1] + - (date.month() === 12 && this.leapYear(date.year()) ? 1 : 0); - }, - - /** Determine whether this date is a week day. - @memberof IslamicCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return this.dayOfWeek(year, month, day) !== 5; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof IslamicCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - year = date.year(); - month = date.month(); - day = date.day(); - year = (year <= 0 ? year + 1 : year); - return day + Math.ceil(29.5 * (month - 1)) + (year - 1) * 354 + - Math.floor((3 + (11 * year)) / 30) + this.jdEpoch - 1; - }, - - /** Create a new date from a Julian date. - @memberof IslamicCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - jd = Math.floor(jd) + 0.5; - var year = Math.floor((30 * (jd - this.jdEpoch) + 10646) / 10631); - year = (year <= 0 ? year - 1 : year); - var month = Math.min(12, Math.ceil((jd - 29 - this.toJD(year, 1, 1)) / 29.5) + 1); - var day = jd - this.toJD(year, month, 1) + 1; - return this.newDate(year, month, day); - } -}); - -// Islamic (16 civil) calendar implementation -main.calendars.islamic = IslamicCalendar; - - -},{"../main":571,"object-assign":454}],563:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Julian calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Julian calendar. - Based on code from http://www.fourmilab.ch/documents/calendar/. - See also http://en.wikipedia.org/wiki/Julian_calendar. - @class JulianCalendar - @augments BaseCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function JulianCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -JulianCalendar.prototype = new main.baseCalendar; - -assign(JulianCalendar.prototype, { - /** The calendar name. - @memberof JulianCalendar */ - name: 'Julian', - /** Julian date of start of Julian epoch: 1 January 0001 AD = 30 December 0001 BCE. - @memberof JulianCalendar */ - jdEpoch: 1721423.5, - /** Days per month in a common year. - @memberof JulianCalendar */ - daysPerMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], - /** true if has a year zero, false if not. - @memberof JulianCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof JulianCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof JulianCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof JulianCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof JulianCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Julian', - epochs: ['BC', 'AD'], - monthNames: ['January', 'February', 'March', 'April', 'May', 'June', - 'July', 'August', 'September', 'October', 'November', 'December'], - monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], - dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], - dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], - digits: null, - dateFormat: 'mm/dd/yyyy', - firstDay: 0, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof JulianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - var year = (date.year() < 0 ? date.year() + 1 : date.year()); // No year zero - return (year % 4) === 0; - }, - - /** Determine the week of the year for a date - ISO 8601. - @memberof JulianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Thursday of this week starting on Monday - var checkDate = this.newDate(year, month, day); - checkDate.add(4 - (checkDate.dayOfWeek() || 7), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a month. - @memberof JulianCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - return this.daysPerMonth[date.month() - 1] + - (date.month() === 2 && this.leapYear(date.year()) ? 1 : 0); - }, - - /** Determine whether this date is a week day. - @memberof JulianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} True if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return (this.dayOfWeek(year, month, day) || 7) < 6; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof JulianCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - year = date.year(); - month = date.month(); - day = date.day(); - if (year < 0) { year++; } // No year zero - // Jean Meeus algorithm, "Astronomical Algorithms", 1991 - if (month <= 2) { - year--; - month += 12; - } - return Math.floor(365.25 * (year + 4716)) + - Math.floor(30.6001 * (month + 1)) + day - 1524.5; - }, - - /** Create a new date from a Julian date. - @memberof JulianCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - // Jean Meeus algorithm, "Astronomical Algorithms", 1991 - var a = Math.floor(jd + 0.5); - var b = a + 1524; - var c = Math.floor((b - 122.1) / 365.25); - var d = Math.floor(365.25 * c); - var e = Math.floor((b - d) / 30.6001); - var month = e - Math.floor(e < 14 ? 1 : 13); - var year = c - Math.floor(month > 2 ? 4716 : 4715); - var day = b - d - Math.floor(30.6001 * e); - if (year <= 0) { year--; } // No year zero - return this.newDate(year, month, day); - } -}); - -// Julian calendar implementation -main.calendars.julian = JulianCalendar; - - -},{"../main":571,"object-assign":454}],564:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Mayan calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Mayan Long Count calendar. - See also http://en.wikipedia.org/wiki/Mayan_calendar. - @class MayanCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function MayanCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -MayanCalendar.prototype = new main.baseCalendar; - -assign(MayanCalendar.prototype, { - /** The calendar name. - @memberof MayanCalendar */ - name: 'Mayan', - /** Julian date of start of Mayan epoch: 11 August 3114 BCE. - @memberof MayanCalendar */ - jdEpoch: 584282.5, - /** true if has a year zero, false if not. - @memberof MayanCalendar */ - hasYearZero: true, - /** The minimum month number. - @memberof MayanCalendar */ - minMonth: 0, - /** The first month in the year. - @memberof MayanCalendar */ - firstMonth: 0, - /** The minimum day number. - @memberof MayanCalendar */ - minDay: 0, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof MayanCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. - @property haabMonths {string[]} The names of the Haab months. - @property tzolkinMonths {string[]} The names of the Tzolkin months. */ - regionalOptions: { // Localisations - '': { - name: 'Mayan', - epochs: ['', ''], - monthNames: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '10', '11', '12', '13', '14', '15', '16', '17'], - monthNamesShort: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '10', '11', '12', '13', '14', '15', '16', '17'], - dayNames: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], - dayNamesShort: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], - dayNamesMin: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], - digits: null, - dateFormat: 'YYYY.m.d', - firstDay: 0, - isRTL: false, - haabMonths: ['Pop', 'Uo', 'Zip', 'Zotz', 'Tzec', 'Xul', 'Yaxkin', 'Mol', 'Chen', 'Yax', - 'Zac', 'Ceh', 'Mac', 'Kankin', 'Muan', 'Pax', 'Kayab', 'Cumku', 'Uayeb'], - tzolkinMonths: ['Imix', 'Ik', 'Akbal', 'Kan', 'Chicchan', 'Cimi', 'Manik', 'Lamat', 'Muluc', 'Oc', - 'Chuen', 'Eb', 'Ben', 'Ix', 'Men', 'Cib', 'Caban', 'Etznab', 'Cauac', 'Ahau'] - } - }, - - /** Determine whether this date is in a leap year. - @memberof MayanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return false; - }, - - /** Format the year, if not a simple sequential number. - @memberof MayanCalendar - @param year {CDate|number} The date to format or the year to format. - @return {string} The formatted year. - @throws Error if an invalid year or a different calendar used. */ - formatYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - year = date.year(); - var baktun = Math.floor(year / 400); - year = year % 400; - year += (year < 0 ? 400 : 0); - var katun = Math.floor(year / 20); - return baktun + '.' + katun + '.' + (year % 20); - }, - - /** Convert from the formatted year back to a single number. - @memberof MayanCalendar - @param years {string} The year as n.n.n. - @return {number} The sequential year. - @throws Error if an invalid value is supplied. */ - forYear: function(years) { - years = years.split('.'); - if (years.length < 3) { - throw 'Invalid Mayan year'; - } - var year = 0; - for (var i = 0; i < years.length; i++) { - var y = parseInt(years[i], 10); - if (Math.abs(y) > 19 || (i > 0 && y < 0)) { - throw 'Invalid Mayan year'; - } - year = year * 20 + y; - } - return year; - }, - - /** Retrieve the number of months in a year. - @memberof MayanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of months. - @throws Error if an invalid year or a different calendar used. */ - monthsInYear: function(year) { - this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return 18; - }, - - /** Determine the week of the year for a date. - @memberof MayanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - this._validate(year, month, day, main.local.invalidDate); - return 0; - }, - - /** Retrieve the number of days in a year. - @memberof MayanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of days. - @throws Error if an invalid year or a different calendar used. */ - daysInYear: function(year) { - this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return 360; - }, - - /** Retrieve the number of days in a month. - @memberof MayanCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - this._validate(year, month, this.minDay, main.local.invalidMonth); - return 20; - }, - - /** Retrieve the number of days in a week. - @memberof MayanCalendar - @return {number} The number of days. */ - daysInWeek: function() { - return 5; // Just for formatting - }, - - /** Retrieve the day of the week for a date. - @memberof MayanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The day of the week: 0 to number of days - 1. - @throws Error if an invalid date or a different calendar used. */ - dayOfWeek: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - return date.day(); - }, - - /** Determine whether this date is a week day. - @memberof MayanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - this._validate(year, month, day, main.local.invalidDate); - return true; - }, - - /** Retrieve additional information about a date - Haab and Tzolkin equivalents. - @memberof MayanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {object} Additional information - contents depends on calendar. - @throws Error if an invalid date or a different calendar used. */ - extraInfo: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - var jd = date.toJD(); - var haab = this._toHaab(jd); - var tzolkin = this._toTzolkin(jd); - return {haabMonthName: this.local.haabMonths[haab[0] - 1], - haabMonth: haab[0], haabDay: haab[1], - tzolkinDayName: this.local.tzolkinMonths[tzolkin[0] - 1], - tzolkinDay: tzolkin[0], tzolkinTrecena: tzolkin[1]}; - }, - - /** Retrieve Haab date from a Julian date. - @memberof MayanCalendar - @private - @param jd {number} The Julian date. - @return {number[]} Corresponding Haab month and day. */ - _toHaab: function(jd) { - jd -= this.jdEpoch; - var day = mod(jd + 8 + ((18 - 1) * 20), 365); - return [Math.floor(day / 20) + 1, mod(day, 20)]; - }, - - /** Retrieve Tzolkin date from a Julian date. - @memberof MayanCalendar - @private - @param jd {number} The Julian date. - @return {number[]} Corresponding Tzolkin day and trecena. */ - _toTzolkin: function(jd) { - jd -= this.jdEpoch; - return [amod(jd + 20, 20), amod(jd + 4, 13)]; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof MayanCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - return date.day() + (date.month() * 20) + (date.year() * 360) + this.jdEpoch; - }, - - /** Create a new date from a Julian date. - @memberof MayanCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - jd = Math.floor(jd) + 0.5 - this.jdEpoch; - var year = Math.floor(jd / 360); - jd = jd % 360; - jd += (jd < 0 ? 360 : 0); - var month = Math.floor(jd / 20); - var day = jd % 20; - return this.newDate(year, month, day); - } -}); - -// Modulus function which works for non-integers. -function mod(a, b) { - return a - (b * Math.floor(a / b)); -} - -// Modulus function which returns numerator if modulus is zero. -function amod(a, b) { - return mod(a - 1, b) + 1; -} - -// Mayan calendar implementation -main.calendars.mayan = MayanCalendar; - - -},{"../main":571,"object-assign":454}],565:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Nanakshahi calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) January 2016. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Nanakshahi calendar. - See also https://en.wikipedia.org/wiki/Nanakshahi_calendar. - @class NanakshahiCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function NanakshahiCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -NanakshahiCalendar.prototype = new main.baseCalendar; - -var gregorian = main.instance('gregorian'); - -assign(NanakshahiCalendar.prototype, { - /** The calendar name. - @memberof NanakshahiCalendar */ - name: 'Nanakshahi', - /** Julian date of start of Nanakshahi epoch: 14 March 1469 CE. - @memberof NanakshahiCalendar */ - jdEpoch: 2257673.5, - /** Days per month in a common year. - @memberof NanakshahiCalendar */ - daysPerMonth: [31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30], - /** true if has a year zero, false if not. - @memberof NanakshahiCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof NanakshahiCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof NanakshahiCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof NanakshahiCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof NanakshahiCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Nanakshahi', - epochs: ['BN', 'AN'], - monthNames: ['Chet', 'Vaisakh', 'Jeth', 'Harh', 'Sawan', 'Bhadon', - 'Assu', 'Katak', 'Maghar', 'Poh', 'Magh', 'Phagun'], - monthNamesShort: ['Che', 'Vai', 'Jet', 'Har', 'Saw', 'Bha', 'Ass', 'Kat', 'Mgr', 'Poh', 'Mgh', 'Pha'], - dayNames: ['Somvaar', 'Mangalvar', 'Budhvaar', 'Veervaar', 'Shukarvaar', 'Sanicharvaar', 'Etvaar'], - dayNamesShort: ['Som', 'Mangal', 'Budh', 'Veer', 'Shukar', 'Sanichar', 'Et'], - dayNamesMin: ['So', 'Ma', 'Bu', 'Ve', 'Sh', 'Sa', 'Et'], - digits: null, - dateFormat: 'dd-mm-yyyy', - firstDay: 0, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof NanakshahiCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, - main.local.invalidYear || main.regionalOptions[''].invalidYear); - return gregorian.leapYear(date.year() + (date.year() < 1 ? 1 : 0) + 1469); - }, - - /** Determine the week of the year for a date. - @memberof NanakshahiCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Monday of this week starting on Monday - var checkDate = this.newDate(year, month, day); - checkDate.add(1 - (checkDate.dayOfWeek() || 7), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a month. - @memberof NanakshahiCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - return this.daysPerMonth[date.month() - 1] + - (date.month() === 12 && this.leapYear(date.year()) ? 1 : 0); - }, - - /** Determine whether this date is a week day. - @memberof NanakshahiCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return (this.dayOfWeek(year, month, day) || 7) < 6; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof NanakshahiCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidMonth); - var year = date.year(); - if (year < 0) { year++; } // No year zero - var doy = date.day(); - for (var m = 1; m < date.month(); m++) { - doy += this.daysPerMonth[m - 1]; - } - return doy + gregorian.toJD(year + 1468, 3, 13); - }, - - /** Create a new date from a Julian date. - @memberof NanakshahiCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - jd = Math.floor(jd + 0.5); - var year = Math.floor((jd - (this.jdEpoch - 1)) / 366); - while (jd >= this.toJD(year + 1, 1, 1)) { - year++; - } - var day = jd - Math.floor(this.toJD(year, 1, 1) + 0.5) + 1; - var month = 1; - while (day > this.daysInMonth(year, month)) { - day -= this.daysInMonth(year, month); - month++; - } - return this.newDate(year, month, day); - } -}); - -// Nanakshahi calendar implementation -main.calendars.nanakshahi = NanakshahiCalendar; - - -},{"../main":571,"object-assign":454}],566:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Nepali calendar for jQuery v2.0.2. - Written by Artur Neumann (ict.projects{at}nepal.inf.org) April 2013. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Nepali civil calendar. - Based on the ideas from - http://codeissue.com/articles/a04e050dea7468f/algorithm-to-convert-english-date-to-nepali-date-using-c-net - and http://birenj2ee.blogspot.com/2011/04/nepali-calendar-in-java.html - See also http://en.wikipedia.org/wiki/Nepali_calendar - and https://en.wikipedia.org/wiki/Bikram_Samwat. - @class NepaliCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function NepaliCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -NepaliCalendar.prototype = new main.baseCalendar; - -assign(NepaliCalendar.prototype, { - /** The calendar name. - @memberof NepaliCalendar */ - name: 'Nepali', - /** Julian date of start of Nepali epoch: 14 April 57 BCE. - @memberof NepaliCalendar */ - jdEpoch: 1700709.5, - /** Days per month in a common year. - @memberof NepaliCalendar */ - daysPerMonth: [31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - /** true if has a year zero, false if not. - @memberof NepaliCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof NepaliCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof NepaliCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof NepaliCalendar */ - minDay: 1, - /** The number of days in the year. - @memberof NepaliCalendar */ - daysPerYear: 365, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof NepaliCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Nepali', - epochs: ['BBS', 'ABS'], - monthNames: ['Baisakh', 'Jestha', 'Ashadh', 'Shrawan', 'Bhadra', 'Ashwin', - 'Kartik', 'Mangsir', 'Paush', 'Mangh', 'Falgun', 'Chaitra'], - monthNamesShort: ['Bai', 'Je', 'As', 'Shra', 'Bha', 'Ash', 'Kar', 'Mang', 'Pau', 'Ma', 'Fal', 'Chai'], - dayNames: ['Aaitabaar', 'Sombaar', 'Manglbaar', 'Budhabaar', 'Bihibaar', 'Shukrabaar', 'Shanibaar'], - dayNamesShort: ['Aaita', 'Som', 'Mangl', 'Budha', 'Bihi', 'Shukra', 'Shani'], - dayNamesMin: ['Aai', 'So', 'Man', 'Bu', 'Bi', 'Shu', 'Sha'], - digits: null, - dateFormat: 'dd/mm/yyyy', - firstDay: 1, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof NepaliCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - return this.daysInYear(year) !== this.daysPerYear; - }, - - /** Determine the week of the year for a date. - @memberof NepaliCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Sunday of this week starting on Sunday - var checkDate = this.newDate(year, month, day); - checkDate.add(-checkDate.dayOfWeek(), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a year. - @memberof NepaliCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of days. - @throws Error if an invalid year or a different calendar used. */ - daysInYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - year = date.year(); - if (typeof this.NEPALI_CALENDAR_DATA[year] === 'undefined') { - return this.daysPerYear; - } - var daysPerYear = 0; - for (var month_number = this.minMonth; month_number <= 12; month_number++) { - daysPerYear += this.NEPALI_CALENDAR_DATA[year][month_number]; - } - return daysPerYear; - }, - - /** Retrieve the number of days in a month. - @memberof NepaliCalendar - @param year {CDate|number| The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - if (year.year) { - month = year.month(); - year = year.year(); - } - this._validate(year, month, this.minDay, main.local.invalidMonth); - return (typeof this.NEPALI_CALENDAR_DATA[year] === 'undefined' ? - this.daysPerMonth[month - 1] : this.NEPALI_CALENDAR_DATA[year][month]); - }, - - /** Determine whether this date is a week day. - @memberof NepaliCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return this.dayOfWeek(year, month, day) !== 6; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof NepaliCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(nepaliYear, nepaliMonth, nepaliDay) { - var date = this._validate(nepaliYear, nepaliMonth, nepaliDay, main.local.invalidDate); - nepaliYear = date.year(); - nepaliMonth = date.month(); - nepaliDay = date.day(); - var gregorianCalendar = main.instance(); - var gregorianDayOfYear = 0; // We will add all the days that went by since - // the 1st. January and then we can get the Gregorian Date - var nepaliMonthToCheck = nepaliMonth; - var nepaliYearToCheck = nepaliYear; - this._createMissingCalendarData(nepaliYear); - // Get the correct year - var gregorianYear = nepaliYear - (nepaliMonthToCheck > 9 || (nepaliMonthToCheck === 9 && - nepaliDay >= this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][0]) ? 56 : 57); - // First we add the amount of days in the actual Nepali month as the day of year in the - // Gregorian one because at least this days are gone since the 1st. Jan. - if (nepaliMonth !== 9) { - gregorianDayOfYear = nepaliDay; - nepaliMonthToCheck--; - } - // Now we loop throw all Nepali month and add the amount of days to gregorianDayOfYear - // we do this till we reach Paush (9th month). 1st. January always falls in this month - while (nepaliMonthToCheck !== 9) { - if (nepaliMonthToCheck <= 0) { - nepaliMonthToCheck = 12; - nepaliYearToCheck--; - } - gregorianDayOfYear += this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][nepaliMonthToCheck]; - nepaliMonthToCheck--; - } - // If the date that has to be converted is in Paush (month no. 9) we have to do some other calculation - if (nepaliMonth === 9) { - // Add the days that are passed since the first day of Paush and substract the - // amount of days that lie between 1st. Jan and 1st Paush - gregorianDayOfYear += nepaliDay - this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][0]; - // For the first days of Paush we are now in negative values, - // because in the end of the gregorian year we substract - // 365 / 366 days (P.S. remember math in school + - gives -) - if (gregorianDayOfYear < 0) { - gregorianDayOfYear += gregorianCalendar.daysInYear(gregorianYear); - } - } - else { - gregorianDayOfYear += this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][9] - - this.NEPALI_CALENDAR_DATA[nepaliYearToCheck][0]; - } - return gregorianCalendar.newDate(gregorianYear, 1 ,1).add(gregorianDayOfYear, 'd').toJD(); - }, - - /** Create a new date from a Julian date. - @memberof NepaliCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - var gregorianCalendar = main.instance(); - var gregorianDate = gregorianCalendar.fromJD(jd); - var gregorianYear = gregorianDate.year(); - var gregorianDayOfYear = gregorianDate.dayOfYear(); - var nepaliYear = gregorianYear + 56; //this is not final, it could be also +57 but +56 is always true for 1st Jan. - this._createMissingCalendarData(nepaliYear); - var nepaliMonth = 9; // Jan 1 always fall in Nepali month Paush which is the 9th month of Nepali calendar. - // Get the Nepali day in Paush (month 9) of 1st January - var dayOfFirstJanInPaush = this.NEPALI_CALENDAR_DATA[nepaliYear][0]; - // Check how many days are left of Paush . - // Days calculated from 1st Jan till the end of the actual Nepali month, - // we use this value to check if the gregorian Date is in the actual Nepali month. - var daysSinceJanFirstToEndOfNepaliMonth = - this.NEPALI_CALENDAR_DATA[nepaliYear][nepaliMonth] - dayOfFirstJanInPaush + 1; - // If the gregorian day-of-year is smaller o equal than the sum of days between the 1st January and - // the end of the actual nepali month we found the correct nepali month. - // Example: - // The 4th February 2011 is the gregorianDayOfYear 35 (31 days of January + 4) - // 1st January 2011 is in the nepali year 2067, where 1st. January is in the 17th day of Paush (9th month) - // In 2067 Paush has 30days, This means (30-17+1=14) there are 14days between 1st January and end of Paush - // (including 17th January) - // The gregorianDayOfYear (35) is bigger than 14, so we check the next month - // The next nepali month (Mangh) has 29 days - // 29+14=43, this is bigger than gregorianDayOfYear(35) so, we found the correct nepali month - while (gregorianDayOfYear > daysSinceJanFirstToEndOfNepaliMonth) { - nepaliMonth++; - if (nepaliMonth > 12) { - nepaliMonth = 1; - nepaliYear++; - } - daysSinceJanFirstToEndOfNepaliMonth += this.NEPALI_CALENDAR_DATA[nepaliYear][nepaliMonth]; - } - // The last step is to calculate the nepali day-of-month - // to continue our example from before: - // we calculated there are 43 days from 1st. January (17 Paush) till end of Mangh (29 days) - // when we subtract from this 43 days the day-of-year of the the Gregorian date (35), - // we know how far the searched day is away from the end of the Nepali month. - // So we simply subtract this number from the amount of days in this month (30) - var nepaliDayOfMonth = this.NEPALI_CALENDAR_DATA[nepaliYear][nepaliMonth] - - (daysSinceJanFirstToEndOfNepaliMonth - gregorianDayOfYear); - return this.newDate(nepaliYear, nepaliMonth, nepaliDayOfMonth); - }, - - /** Creates missing data in the NEPALI_CALENDAR_DATA table. - This data will not be correct but just give an estimated result. Mostly -/+ 1 day - @private - @param nepaliYear {number} The missing year number. */ - _createMissingCalendarData: function(nepaliYear) { - var tmp_calendar_data = this.daysPerMonth.slice(0); - tmp_calendar_data.unshift(17); - for (var nepaliYearToCreate = (nepaliYear - 1); nepaliYearToCreate < (nepaliYear + 2); nepaliYearToCreate++) { - if (typeof this.NEPALI_CALENDAR_DATA[nepaliYearToCreate] === 'undefined') { - this.NEPALI_CALENDAR_DATA[nepaliYearToCreate] = tmp_calendar_data; - } - } - }, - - NEPALI_CALENDAR_DATA: { - // These data are from http://www.ashesh.com.np - 1970: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 1971: [18, 31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30], - 1972: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], - 1973: [19, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 1974: [19, 31, 31, 32, 30, 31, 31, 30, 29, 30, 29, 30, 30], - 1975: [18, 31, 31, 32, 32, 30, 31, 30, 29, 30, 29, 30, 30], - 1976: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 1977: [18, 31, 32, 31, 32, 31, 31, 29, 30, 29, 30, 29, 31], - 1978: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 1979: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 1980: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 1981: [18, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], - 1982: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 1983: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 1984: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 1985: [18, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], - 1986: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 1987: [18, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 1988: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 1989: [18, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], - 1990: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 1991: [18, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], - // These data are from http://nepalicalendar.rat32.com/index.php - 1992: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 1993: [18, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], - 1994: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 1995: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], - 1996: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 1997: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 1998: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 1999: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2000: [17, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 2001: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2002: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2003: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2004: [17, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 2005: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2006: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2007: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2008: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31], - 2009: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2010: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2011: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2012: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], - 2013: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2014: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2015: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2016: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], - 2017: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2018: [18, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2019: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 2020: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], - 2021: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2022: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], - 2023: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 2024: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], - 2025: [18, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2026: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2027: [17, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 2028: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2029: [18, 31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30], - 2030: [17, 31, 32, 31, 32, 31, 30, 30, 30, 30, 30, 30, 31], - 2031: [17, 31, 32, 31, 32, 31, 31, 31, 31, 31, 31, 31, 31], - 2032: [17, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32], - 2033: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2034: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2035: [17, 30, 32, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31], - 2036: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2037: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2038: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2039: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], - 2040: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2041: [18, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2042: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2043: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], - 2044: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2045: [18, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2046: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2047: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], - 2048: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2049: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], - 2050: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 2051: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], - 2052: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2053: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], - 2054: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 2055: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 30, 29, 30], - 2056: [17, 31, 31, 32, 31, 32, 30, 30, 29, 30, 29, 30, 30], - 2057: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2058: [17, 30, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 2059: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2060: [17, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2061: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2062: [17, 30, 32, 31, 32, 31, 31, 29, 30, 29, 30, 29, 31], - 2063: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2064: [17, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2065: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2066: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 29, 31], - 2067: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2068: [17, 31, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2069: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2070: [17, 31, 31, 31, 32, 31, 31, 29, 30, 30, 29, 30, 30], - 2071: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2072: [17, 31, 32, 31, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2073: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 31], - 2074: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], - 2075: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2076: [16, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], - 2077: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 29, 31], - 2078: [17, 31, 31, 31, 32, 31, 31, 30, 29, 30, 29, 30, 30], - 2079: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 29, 30, 30], - 2080: [16, 31, 32, 31, 32, 31, 30, 30, 30, 29, 29, 30, 30], - // These data are from http://www.ashesh.com.np/nepali-calendar/ - 2081: [17, 31, 31, 32, 32, 31, 30, 30, 30, 29, 30, 30, 30], - 2082: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], - 2083: [17, 31, 31, 32, 31, 31, 30, 30, 30, 29, 30, 30, 30], - 2084: [17, 31, 31, 32, 31, 31, 30, 30, 30, 29, 30, 30, 30], - 2085: [17, 31, 32, 31, 32, 31, 31, 30, 30, 29, 30, 30, 30], - 2086: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], - 2087: [16, 31, 31, 32, 31, 31, 31, 30, 30, 29, 30, 30, 30], - 2088: [16, 30, 31, 32, 32, 30, 31, 30, 30, 29, 30, 30, 30], - 2089: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], - 2090: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], - 2091: [16, 31, 31, 32, 31, 31, 31, 30, 30, 29, 30, 30, 30], - 2092: [16, 31, 31, 32, 32, 31, 30, 30, 30, 29, 30, 30, 30], - 2093: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], - 2094: [17, 31, 31, 32, 31, 31, 30, 30, 30, 29, 30, 30, 30], - 2095: [17, 31, 31, 32, 31, 31, 31, 30, 29, 30, 30, 30, 30], - 2096: [17, 30, 31, 32, 32, 31, 30, 30, 29, 30, 29, 30, 30], - 2097: [17, 31, 32, 31, 32, 31, 30, 30, 30, 29, 30, 30, 30], - 2098: [17, 31, 31, 32, 31, 31, 31, 29, 30, 29, 30, 30, 31], - 2099: [17, 31, 31, 32, 31, 31, 31, 30, 29, 29, 30, 30, 30], - 2100: [17, 31, 32, 31, 32, 30, 31, 30, 29, 30, 29, 30, 30] - } -}); - -// Nepali calendar implementation -main.calendars.nepali = NepaliCalendar; - - -},{"../main":571,"object-assign":454}],567:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Persian calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the Persian or Jalali calendar. - Based on code from http://www.iranchamber.com/calendar/converter/iranian_calendar_converter.php. - See also http://en.wikipedia.org/wiki/Iranian_calendar. - @class PersianCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function PersianCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -PersianCalendar.prototype = new main.baseCalendar; - -assign(PersianCalendar.prototype, { - /** The calendar name. - @memberof PersianCalendar */ - name: 'Persian', - /** Julian date of start of Persian epoch: 19 March 622 CE. - @memberof PersianCalendar */ - jdEpoch: 1948320.5, - /** Days per month in a common year. - @memberof PersianCalendar */ - daysPerMonth: [31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29], - /** true if has a year zero, false if not. - @memberof PersianCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof PersianCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof PersianCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof PersianCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof PersianCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Persian', - epochs: ['BP', 'AP'], - monthNames: ['Farvardin', 'Ordibehesht', 'Khordad', 'Tir', 'Mordad', 'Shahrivar', - 'Mehr', 'Aban', 'Azar', 'Day', 'Bahman', 'Esfand'], - monthNamesShort: ['Far', 'Ord', 'Kho', 'Tir', 'Mor', 'Sha', 'Meh', 'Aba', 'Aza', 'Day', 'Bah', 'Esf'], - dayNames: ['Yekshambe', 'Doshambe', 'Seshambe', 'Chæharshambe', 'Panjshambe', 'Jom\'e', 'Shambe'], - dayNamesShort: ['Yek', 'Do', 'Se', 'Chæ', 'Panj', 'Jom', 'Sha'], - dayNamesMin: ['Ye','Do','Se','Ch','Pa','Jo','Sh'], - digits: null, - dateFormat: 'yyyy/mm/dd', - firstDay: 6, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof PersianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return (((((date.year() - (date.year() > 0 ? 474 : 473)) % 2820) + - 474 + 38) * 682) % 2816) < 682; - }, - - /** Determine the week of the year for a date. - @memberof PersianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Saturday of this week starting on Saturday - var checkDate = this.newDate(year, month, day); - checkDate.add(-((checkDate.dayOfWeek() + 1) % 7), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a month. - @memberof PersianCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - return this.daysPerMonth[date.month() - 1] + - (date.month() === 12 && this.leapYear(date.year()) ? 1 : 0); - }, - - /** Determine whether this date is a week day. - @memberof PersianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return this.dayOfWeek(year, month, day) !== 5; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof PersianCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - year = date.year(); - month = date.month(); - day = date.day(); - var epBase = year - (year >= 0 ? 474 : 473); - var epYear = 474 + mod(epBase, 2820); - return day + (month <= 7 ? (month - 1) * 31 : (month - 1) * 30 + 6) + - Math.floor((epYear * 682 - 110) / 2816) + (epYear - 1) * 365 + - Math.floor(epBase / 2820) * 1029983 + this.jdEpoch - 1; - }, - - /** Create a new date from a Julian date. - @memberof PersianCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - jd = Math.floor(jd) + 0.5; - var depoch = jd - this.toJD(475, 1, 1); - var cycle = Math.floor(depoch / 1029983); - var cyear = mod(depoch, 1029983); - var ycycle = 2820; - if (cyear !== 1029982) { - var aux1 = Math.floor(cyear / 366); - var aux2 = mod(cyear, 366); - ycycle = Math.floor(((2134 * aux1) + (2816 * aux2) + 2815) / 1028522) + aux1 + 1; - } - var year = ycycle + (2820 * cycle) + 474; - year = (year <= 0 ? year - 1 : year); - var yday = jd - this.toJD(year, 1, 1) + 1; - var month = (yday <= 186 ? Math.ceil(yday / 31) : Math.ceil((yday - 6) / 30)); - var day = jd - this.toJD(year, month, 1) + 1; - return this.newDate(year, month, day); - } -}); - -// Modulus function which works for non-integers. -function mod(a, b) { - return a - (b * Math.floor(a / b)); -} - -// Persian (Jalali) calendar implementation -main.calendars.persian = PersianCalendar; -main.calendars.jalali = PersianCalendar; - - -},{"../main":571,"object-assign":454}],568:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Taiwanese (Minguo) calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) February 2010. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -var gregorianCalendar = main.instance(); - -/** Implementation of the Taiwanese calendar. - See http://en.wikipedia.org/wiki/Minguo_calendar. - @class TaiwanCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function TaiwanCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -TaiwanCalendar.prototype = new main.baseCalendar; - -assign(TaiwanCalendar.prototype, { - /** The calendar name. - @memberof TaiwanCalendar */ - name: 'Taiwan', - /** Julian date of start of Taiwan epoch: 1 January 1912 CE (Gregorian). - @memberof TaiwanCalendar */ - jdEpoch: 2419402.5, - /** Difference in years between Taiwan and Gregorian calendars. - @memberof TaiwanCalendar */ - yearsOffset: 1911, - /** Days per month in a common year. - @memberof TaiwanCalendar */ - daysPerMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], - /** true if has a year zero, false if not. - @memberof TaiwanCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof TaiwanCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof TaiwanCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof TaiwanCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof TaiwanCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Taiwan', - epochs: ['BROC', 'ROC'], - monthNames: ['January', 'February', 'March', 'April', 'May', 'June', - 'July', 'August', 'September', 'October', 'November', 'December'], - monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], - dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], - dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], - digits: null, - dateFormat: 'yyyy/mm/dd', - firstDay: 1, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof TaiwanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - var year = this._t2gYear(date.year()); - return gregorianCalendar.leapYear(year); - }, - - /** Determine the week of the year for a date - ISO 8601. - @memberof TaiwanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - var year = this._t2gYear(date.year()); - return gregorianCalendar.weekOfYear(year, date.month(), date.day()); - }, - - /** Retrieve the number of days in a month. - @memberof TaiwanCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - return this.daysPerMonth[date.month() - 1] + - (date.month() === 2 && this.leapYear(date.year()) ? 1 : 0); - }, - - /** Determine whether this date is a week day. - @memberof TaiwanCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return (this.dayOfWeek(year, month, day) || 7) < 6; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof TaiwanCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - var year = this._t2gYear(date.year()); - return gregorianCalendar.toJD(year, date.month(), date.day()); - }, - - /** Create a new date from a Julian date. - @memberof TaiwanCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - var date = gregorianCalendar.fromJD(jd); - var year = this._g2tYear(date.year()); - return this.newDate(year, date.month(), date.day()); - }, - - /** Convert Taiwanese to Gregorian year. - @memberof TaiwanCalendar - @private - @param year {number} The Taiwanese year. - @return {number} The corresponding Gregorian year. */ - _t2gYear: function(year) { - return year + this.yearsOffset + (year >= -this.yearsOffset && year <= -1 ? 1 : 0); - }, - - /** Convert Gregorian to Taiwanese year. - @memberof TaiwanCalendar - @private - @param year {number} The Gregorian year. - @return {number} The corresponding Taiwanese year. */ - _g2tYear: function(year) { - return year - this.yearsOffset - (year >= 1 && year <= this.yearsOffset ? 1 : 0); - } -}); - -// Taiwan calendar implementation -main.calendars.taiwan = TaiwanCalendar; - - -},{"../main":571,"object-assign":454}],569:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Thai calendar for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) February 2010. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -var gregorianCalendar = main.instance(); - -/** Implementation of the Thai calendar. - See http://en.wikipedia.org/wiki/Thai_calendar. - @class ThaiCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function ThaiCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -ThaiCalendar.prototype = new main.baseCalendar; - -assign(ThaiCalendar.prototype, { - /** The calendar name. - @memberof ThaiCalendar */ - name: 'Thai', - /** Julian date of start of Thai epoch: 1 January 543 BCE (Gregorian). - @memberof ThaiCalendar */ - jdEpoch: 1523098.5, - /** Difference in years between Thai and Gregorian calendars. - @memberof ThaiCalendar */ - yearsOffset: 543, - /** Days per month in a common year. - @memberof ThaiCalendar */ - daysPerMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], - /** true if has a year zero, false if not. - @memberof ThaiCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof ThaiCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof ThaiCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof ThaiCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof ThaiCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Thai', - epochs: ['BBE', 'BE'], - monthNames: ['January', 'February', 'March', 'April', 'May', 'June', - 'July', 'August', 'September', 'October', 'November', 'December'], - monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], - dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], - dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], - digits: null, - dateFormat: 'dd/mm/yyyy', - firstDay: 0, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof ThaiCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - var year = this._t2gYear(date.year()); - return gregorianCalendar.leapYear(year); - }, - - /** Determine the week of the year for a date - ISO 8601. - @memberof ThaiCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - var year = this._t2gYear(date.year()); - return gregorianCalendar.weekOfYear(year, date.month(), date.day()); - }, - - /** Retrieve the number of days in a month. - @memberof ThaiCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - return this.daysPerMonth[date.month() - 1] + - (date.month() === 2 && this.leapYear(date.year()) ? 1 : 0); - }, - - /** Determine whether this date is a week day. - @memberof ThaiCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return (this.dayOfWeek(year, month, day) || 7) < 6; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof ThaiCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - var year = this._t2gYear(date.year()); - return gregorianCalendar.toJD(year, date.month(), date.day()); - }, - - /** Create a new date from a Julian date. - @memberof ThaiCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - var date = gregorianCalendar.fromJD(jd); - var year = this._g2tYear(date.year()); - return this.newDate(year, date.month(), date.day()); - }, - - /** Convert Thai to Gregorian year. - @memberof ThaiCalendar - @private - @param year {number} The Thai year. - @return {number} The corresponding Gregorian year. */ - _t2gYear: function(year) { - return year - this.yearsOffset - (year >= 1 && year <= this.yearsOffset ? 1 : 0); - }, - - /** Convert Gregorian to Thai year. - @memberof ThaiCalendar - @private - @param year {number} The Gregorian year. - @return {number} The corresponding Thai year. */ - _g2tYear: function(year) { - return year + this.yearsOffset + (year >= -this.yearsOffset && year <= -1 ? 1 : 0); - } -}); - -// Thai calendar implementation -main.calendars.thai = ThaiCalendar; - - -},{"../main":571,"object-assign":454}],570:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - UmmAlQura calendar for jQuery v2.0.2. - Written by Amro Osama March 2013. - Modified by Binnooh.com & www.elm.sa - 2014 - Added dates back to 1276 Hijri year. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var main = _dereq_('../main'); -var assign = _dereq_('object-assign'); - - -/** Implementation of the UmmAlQura or 'saudi' calendar. - See also http://en.wikipedia.org/wiki/Islamic_calendar#Saudi_Arabia.27s_Umm_al-Qura_calendar. - http://www.ummulqura.org.sa/About.aspx - http://www.staff.science.uu.nl/~gent0113/islam/ummalqura.htm - @class UmmAlQuraCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function UmmAlQuraCalendar(language) { - this.local = this.regionalOptions[language || ''] || this.regionalOptions['']; -} - -UmmAlQuraCalendar.prototype = new main.baseCalendar; - -assign(UmmAlQuraCalendar.prototype, { - /** The calendar name. - @memberof UmmAlQuraCalendar */ - name: 'UmmAlQura', - //jdEpoch: 1948440, // Julian date of start of UmmAlQura epoch: 14 March 1937 CE - //daysPerMonth: // Days per month in a common year, replaced by a method. - /** true if has a year zero, false if not. - @memberof UmmAlQuraCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof UmmAlQuraCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof UmmAlQuraCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof UmmAlQuraCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof UmmAlQuraCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Umm al-Qura', - epochs: ['BH', 'AH'], - monthNames: ['Al-Muharram', 'Safar', 'Rabi\' al-awwal', 'Rabi\' Al-Thani', 'Jumada Al-Awwal', 'Jumada Al-Thani', - 'Rajab', 'Sha\'aban', 'Ramadan', 'Shawwal', 'Dhu al-Qi\'dah', 'Dhu al-Hijjah'], - monthNamesShort: ['Muh', 'Saf', 'Rab1', 'Rab2', 'Jum1', 'Jum2', 'Raj', 'Sha\'', 'Ram', 'Shaw', 'DhuQ', 'DhuH'], - dayNames: ['Yawm al-Ahad', 'Yawm al-Ithnain', 'Yawm al-Thalāthā’', 'Yawm al-Arba‘ā’', 'Yawm al-Khamīs', 'Yawm al-Jum‘a', 'Yawm al-Sabt'], - dayNamesMin: ['Ah', 'Ith', 'Th', 'Ar', 'Kh', 'Ju', 'Sa'], - digits: null, - dateFormat: 'yyyy/mm/dd', - firstDay: 6, - isRTL: true - } - }, - - /** Determine whether this date is in a leap year. - @memberof UmmAlQuraCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function (year) { - var date = this._validate(year, this.minMonth, this.minDay, main.local.invalidYear); - return (this.daysInYear(date.year()) === 355); - }, - - /** Determine the week of the year for a date. - @memberof UmmAlQuraCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function (year, month, day) { - // Find Sunday of this week starting on Sunday - var checkDate = this.newDate(year, month, day); - checkDate.add(-checkDate.dayOfWeek(), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a year. - @memberof UmmAlQuraCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of days. - @throws Error if an invalid year or a different calendar used. */ - daysInYear: function (year) { - var daysCount = 0; - for (var i = 1; i <= 12; i++) { - daysCount += this.daysInMonth(year, i); - } - return daysCount; - }, - - /** Retrieve the number of days in a month. - @memberof UmmAlQuraCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function (year, month) { - var date = this._validate(year, month, this.minDay, main.local.invalidMonth); - var mcjdn = date.toJD() - 2400000 + 0.5; // Modified Chronological Julian Day Number (MCJDN) - // the MCJDN's of the start of the lunations in the Umm al-Qura calendar are stored in the 'ummalqura_dat' array - var index = 0; - for (var i = 0; i < ummalqura_dat.length; i++) { - if (ummalqura_dat[i] > mcjdn) { - return (ummalqura_dat[index] - ummalqura_dat[index - 1]); - } - index++; - } - return 30; // Unknown outside - }, - - /** Determine whether this date is a week day. - @memberof UmmAlQuraCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function (year, month, day) { - return this.dayOfWeek(year, month, day) !== 5; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof UmmAlQuraCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function (year, month, day) { - var date = this._validate(year, month, day, main.local.invalidDate); - var index = (12 * (date.year() - 1)) + date.month() - 15292; - var mcjdn = date.day() + ummalqura_dat[index - 1] - 1; - return mcjdn + 2400000 - 0.5; // Modified Chronological Julian Day Number (MCJDN) - }, - - /** Create a new date from a Julian date. - @memberof UmmAlQuraCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function (jd) { - var mcjdn = jd - 2400000 + 0.5; // Modified Chronological Julian Day Number (MCJDN) - // the MCJDN's of the start of the lunations in the Umm al-Qura calendar - // are stored in the 'ummalqura_dat' array - var index = 0; - for (var i = 0; i < ummalqura_dat.length; i++) { - if (ummalqura_dat[i] > mcjdn) break; - index++; - } - var lunation = index + 15292; //UmmAlQura Lunation Number - var ii = Math.floor((lunation - 1) / 12); - var year = ii + 1; - var month = lunation - 12 * ii; - var day = mcjdn - ummalqura_dat[index - 1] + 1; - return this.newDate(year, month, day); - }, - - /** Determine whether a date is valid for this calendar. - @memberof UmmAlQuraCalendar - @param year {number} The year to examine. - @param month {number} The month to examine. - @param day {number} The day to examine. - @return {boolean} true if a valid date, false if not. */ - isValid: function(year, month, day) { - var valid = main.baseCalendar.prototype.isValid.apply(this, arguments); - if (valid) { - year = (year.year != null ? year.year : year); - valid = (year >= 1276 && year <= 1500); - } - return valid; - }, - - /** Check that a candidate date is from the same calendar and is valid. - @memberof UmmAlQuraCalendar - @private - @param year {CDate|number} The date to validate or the year to validate. - @param month {number} The month to validate. - @param day {number} The day to validate. - @param error {string} Error message if invalid. - @throws Error if different calendars used or invalid date. */ - _validate: function(year, month, day, error) { - var date = main.baseCalendar.prototype._validate.apply(this, arguments); - if (date.year < 1276 || date.year > 1500) { - throw error.replace(/\{0\}/, this.local.name); - } - return date; - } -}); - -// UmmAlQura calendar implementation -main.calendars.ummalqura = UmmAlQuraCalendar; - -var ummalqura_dat = [ - 20, 50, 79, 109, 138, 168, 197, 227, 256, 286, 315, 345, 374, 404, 433, 463, 492, 522, 551, 581, - 611, 641, 670, 700, 729, 759, 788, 818, 847, 877, 906, 936, 965, 995, 1024, 1054, 1083, 1113, 1142, 1172, - 1201, 1231, 1260, 1290, 1320, 1350, 1379, 1409, 1438, 1468, 1497, 1527, 1556, 1586, 1615, 1645, 1674, 1704, 1733, 1763, - 1792, 1822, 1851, 1881, 1910, 1940, 1969, 1999, 2028, 2058, 2087, 2117, 2146, 2176, 2205, 2235, 2264, 2294, 2323, 2353, - 2383, 2413, 2442, 2472, 2501, 2531, 2560, 2590, 2619, 2649, 2678, 2708, 2737, 2767, 2796, 2826, 2855, 2885, 2914, 2944, - 2973, 3003, 3032, 3062, 3091, 3121, 3150, 3180, 3209, 3239, 3268, 3298, 3327, 3357, 3386, 3416, 3446, 3476, 3505, 3535, - 3564, 3594, 3623, 3653, 3682, 3712, 3741, 3771, 3800, 3830, 3859, 3889, 3918, 3948, 3977, 4007, 4036, 4066, 4095, 4125, - 4155, 4185, 4214, 4244, 4273, 4303, 4332, 4362, 4391, 4421, 4450, 4480, 4509, 4539, 4568, 4598, 4627, 4657, 4686, 4716, - 4745, 4775, 4804, 4834, 4863, 4893, 4922, 4952, 4981, 5011, 5040, 5070, 5099, 5129, 5158, 5188, 5218, 5248, 5277, 5307, - 5336, 5366, 5395, 5425, 5454, 5484, 5513, 5543, 5572, 5602, 5631, 5661, 5690, 5720, 5749, 5779, 5808, 5838, 5867, 5897, - 5926, 5956, 5985, 6015, 6044, 6074, 6103, 6133, 6162, 6192, 6221, 6251, 6281, 6311, 6340, 6370, 6399, 6429, 6458, 6488, - 6517, 6547, 6576, 6606, 6635, 6665, 6694, 6724, 6753, 6783, 6812, 6842, 6871, 6901, 6930, 6960, 6989, 7019, 7048, 7078, - 7107, 7137, 7166, 7196, 7225, 7255, 7284, 7314, 7344, 7374, 7403, 7433, 7462, 7492, 7521, 7551, 7580, 7610, 7639, 7669, - 7698, 7728, 7757, 7787, 7816, 7846, 7875, 7905, 7934, 7964, 7993, 8023, 8053, 8083, 8112, 8142, 8171, 8201, 8230, 8260, - 8289, 8319, 8348, 8378, 8407, 8437, 8466, 8496, 8525, 8555, 8584, 8614, 8643, 8673, 8702, 8732, 8761, 8791, 8821, 8850, - 8880, 8909, 8938, 8968, 8997, 9027, 9056, 9086, 9115, 9145, 9175, 9205, 9234, 9264, 9293, 9322, 9352, 9381, 9410, 9440, - 9470, 9499, 9529, 9559, 9589, 9618, 9648, 9677, 9706, 9736, 9765, 9794, 9824, 9853, 9883, 9913, 9943, 9972, 10002, 10032, - 10061, 10090, 10120, 10149, 10178, 10208, 10237, 10267, 10297, 10326, 10356, 10386, 10415, 10445, 10474, 10504, 10533, 10562, 10592, 10621, - 10651, 10680, 10710, 10740, 10770, 10799, 10829, 10858, 10888, 10917, 10947, 10976, 11005, 11035, 11064, 11094, 11124, 11153, 11183, 11213, - 11242, 11272, 11301, 11331, 11360, 11389, 11419, 11448, 11478, 11507, 11537, 11567, 11596, 11626, 11655, 11685, 11715, 11744, 11774, 11803, - 11832, 11862, 11891, 11921, 11950, 11980, 12010, 12039, 12069, 12099, 12128, 12158, 12187, 12216, 12246, 12275, 12304, 12334, 12364, 12393, - 12423, 12453, 12483, 12512, 12542, 12571, 12600, 12630, 12659, 12688, 12718, 12747, 12777, 12807, 12837, 12866, 12896, 12926, 12955, 12984, - 13014, 13043, 13072, 13102, 13131, 13161, 13191, 13220, 13250, 13280, 13310, 13339, 13368, 13398, 13427, 13456, 13486, 13515, 13545, 13574, - 13604, 13634, 13664, 13693, 13723, 13752, 13782, 13811, 13840, 13870, 13899, 13929, 13958, 13988, 14018, 14047, 14077, 14107, 14136, 14166, - 14195, 14224, 14254, 14283, 14313, 14342, 14372, 14401, 14431, 14461, 14490, 14520, 14550, 14579, 14609, 14638, 14667, 14697, 14726, 14756, - 14785, 14815, 14844, 14874, 14904, 14933, 14963, 14993, 15021, 15051, 15081, 15110, 15140, 15169, 15199, 15228, 15258, 15287, 15317, 15347, - 15377, 15406, 15436, 15465, 15494, 15524, 15553, 15582, 15612, 15641, 15671, 15701, 15731, 15760, 15790, 15820, 15849, 15878, 15908, 15937, - 15966, 15996, 16025, 16055, 16085, 16114, 16144, 16174, 16204, 16233, 16262, 16292, 16321, 16350, 16380, 16409, 16439, 16468, 16498, 16528, - 16558, 16587, 16617, 16646, 16676, 16705, 16734, 16764, 16793, 16823, 16852, 16882, 16912, 16941, 16971, 17001, 17030, 17060, 17089, 17118, - 17148, 17177, 17207, 17236, 17266, 17295, 17325, 17355, 17384, 17414, 17444, 17473, 17502, 17532, 17561, 17591, 17620, 17650, 17679, 17709, - 17738, 17768, 17798, 17827, 17857, 17886, 17916, 17945, 17975, 18004, 18034, 18063, 18093, 18122, 18152, 18181, 18211, 18241, 18270, 18300, - 18330, 18359, 18388, 18418, 18447, 18476, 18506, 18535, 18565, 18595, 18625, 18654, 18684, 18714, 18743, 18772, 18802, 18831, 18860, 18890, - 18919, 18949, 18979, 19008, 19038, 19068, 19098, 19127, 19156, 19186, 19215, 19244, 19274, 19303, 19333, 19362, 19392, 19422, 19452, 19481, - 19511, 19540, 19570, 19599, 19628, 19658, 19687, 19717, 19746, 19776, 19806, 19836, 19865, 19895, 19924, 19954, 19983, 20012, 20042, 20071, - 20101, 20130, 20160, 20190, 20219, 20249, 20279, 20308, 20338, 20367, 20396, 20426, 20455, 20485, 20514, 20544, 20573, 20603, 20633, 20662, - 20692, 20721, 20751, 20780, 20810, 20839, 20869, 20898, 20928, 20957, 20987, 21016, 21046, 21076, 21105, 21135, 21164, 21194, 21223, 21253, - 21282, 21312, 21341, 21371, 21400, 21430, 21459, 21489, 21519, 21548, 21578, 21607, 21637, 21666, 21696, 21725, 21754, 21784, 21813, 21843, - 21873, 21902, 21932, 21962, 21991, 22021, 22050, 22080, 22109, 22138, 22168, 22197, 22227, 22256, 22286, 22316, 22346, 22375, 22405, 22434, - 22464, 22493, 22522, 22552, 22581, 22611, 22640, 22670, 22700, 22730, 22759, 22789, 22818, 22848, 22877, 22906, 22936, 22965, 22994, 23024, - 23054, 23083, 23113, 23143, 23173, 23202, 23232, 23261, 23290, 23320, 23349, 23379, 23408, 23438, 23467, 23497, 23527, 23556, 23586, 23616, - 23645, 23674, 23704, 23733, 23763, 23792, 23822, 23851, 23881, 23910, 23940, 23970, 23999, 24029, 24058, 24088, 24117, 24147, 24176, 24206, - 24235, 24265, 24294, 24324, 24353, 24383, 24413, 24442, 24472, 24501, 24531, 24560, 24590, 24619, 24648, 24678, 24707, 24737, 24767, 24796, - 24826, 24856, 24885, 24915, 24944, 24974, 25003, 25032, 25062, 25091, 25121, 25150, 25180, 25210, 25240, 25269, 25299, 25328, 25358, 25387, - 25416, 25446, 25475, 25505, 25534, 25564, 25594, 25624, 25653, 25683, 25712, 25742, 25771, 25800, 25830, 25859, 25888, 25918, 25948, 25977, - 26007, 26037, 26067, 26096, 26126, 26155, 26184, 26214, 26243, 26272, 26302, 26332, 26361, 26391, 26421, 26451, 26480, 26510, 26539, 26568, - 26598, 26627, 26656, 26686, 26715, 26745, 26775, 26805, 26834, 26864, 26893, 26923, 26952, 26982, 27011, 27041, 27070, 27099, 27129, 27159, - 27188, 27218, 27248, 27277, 27307, 27336, 27366, 27395, 27425, 27454, 27484, 27513, 27542, 27572, 27602, 27631, 27661, 27691, 27720, 27750, - 27779, 27809, 27838, 27868, 27897, 27926, 27956, 27985, 28015, 28045, 28074, 28104, 28134, 28163, 28193, 28222, 28252, 28281, 28310, 28340, - 28369, 28399, 28428, 28458, 28488, 28517, 28547, 28577, - // From 1356 - 28607, 28636, 28665, 28695, 28724, 28754, 28783, 28813, 28843, 28872, 28901, 28931, 28960, 28990, 29019, 29049, 29078, 29108, 29137, 29167, - 29196, 29226, 29255, 29285, 29315, 29345, 29375, 29404, 29434, 29463, 29492, 29522, 29551, 29580, 29610, 29640, 29669, 29699, 29729, 29759, - 29788, 29818, 29847, 29876, 29906, 29935, 29964, 29994, 30023, 30053, 30082, 30112, 30141, 30171, 30200, 30230, 30259, 30289, 30318, 30348, - 30378, 30408, 30437, 30467, 30496, 30526, 30555, 30585, 30614, 30644, 30673, 30703, 30732, 30762, 30791, 30821, 30850, 30880, 30909, 30939, - 30968, 30998, 31027, 31057, 31086, 31116, 31145, 31175, 31204, 31234, 31263, 31293, 31322, 31352, 31381, 31411, 31441, 31471, 31500, 31530, - 31559, 31589, 31618, 31648, 31676, 31706, 31736, 31766, 31795, 31825, 31854, 31884, 31913, 31943, 31972, 32002, 32031, 32061, 32090, 32120, - 32150, 32180, 32209, 32239, 32268, 32298, 32327, 32357, 32386, 32416, 32445, 32475, 32504, 32534, 32563, 32593, 32622, 32652, 32681, 32711, - 32740, 32770, 32799, 32829, 32858, 32888, 32917, 32947, 32976, 33006, 33035, 33065, 33094, 33124, 33153, 33183, 33213, 33243, 33272, 33302, - 33331, 33361, 33390, 33420, 33450, 33479, 33509, 33539, 33568, 33598, 33627, 33657, 33686, 33716, 33745, 33775, 33804, 33834, 33863, 33893, - 33922, 33952, 33981, 34011, 34040, 34069, 34099, 34128, 34158, 34187, 34217, 34247, 34277, 34306, 34336, 34365, 34395, 34424, 34454, 34483, - 34512, 34542, 34571, 34601, 34631, 34660, 34690, 34719, 34749, 34778, 34808, 34837, 34867, 34896, 34926, 34955, 34985, 35015, 35044, 35074, - 35103, 35133, 35162, 35192, 35222, 35251, 35280, 35310, 35340, 35370, 35399, 35429, 35458, 35488, 35517, 35547, 35576, 35605, 35635, 35665, - 35694, 35723, 35753, 35782, 35811, 35841, 35871, 35901, 35930, 35960, 35989, 36019, 36048, 36078, 36107, 36136, 36166, 36195, 36225, 36254, - 36284, 36314, 36343, 36373, 36403, 36433, 36462, 36492, 36521, 36551, 36580, 36610, 36639, 36669, 36698, 36728, 36757, 36786, 36816, 36845, - 36875, 36904, 36934, 36963, 36993, 37022, 37052, 37081, 37111, 37141, 37170, 37200, 37229, 37259, 37288, 37318, 37347, 37377, 37406, 37436, - 37465, 37495, 37524, 37554, 37584, 37613, 37643, 37672, 37701, 37731, 37760, 37790, 37819, 37849, 37878, 37908, 37938, 37967, 37997, 38027, - 38056, 38085, 38115, 38144, 38174, 38203, 38233, 38262, 38292, 38322, 38351, 38381, 38410, 38440, 38469, 38499, 38528, 38558, 38587, 38617, - 38646, 38676, 38705, 38735, 38764, 38794, 38823, 38853, 38882, 38912, 38941, 38971, 39001, 39030, 39059, 39089, 39118, 39148, 39178, 39208, - 39237, 39267, 39297, 39326, 39355, 39385, 39414, 39444, 39473, 39503, 39532, 39562, 39592, 39621, 39650, 39680, 39709, 39739, 39768, 39798, - 39827, 39857, 39886, 39916, 39946, 39975, 40005, 40035, 40064, 40094, 40123, 40153, 40182, 40212, 40241, 40271, 40300, 40330, 40359, 40389, - 40418, 40448, 40477, 40507, 40536, 40566, 40595, 40625, 40655, 40685, 40714, 40744, 40773, 40803, 40832, 40862, 40892, 40921, 40951, 40980, - 41009, 41039, 41068, 41098, 41127, 41157, 41186, 41216, 41245, 41275, 41304, 41334, 41364, 41393, 41422, 41452, 41481, 41511, 41540, 41570, - 41599, 41629, 41658, 41688, 41718, 41748, 41777, 41807, 41836, 41865, 41894, 41924, 41953, 41983, 42012, 42042, 42072, 42102, 42131, 42161, - 42190, 42220, 42249, 42279, 42308, 42337, 42367, 42397, 42426, 42456, 42485, 42515, 42545, 42574, 42604, 42633, 42662, 42692, 42721, 42751, - 42780, 42810, 42839, 42869, 42899, 42929, 42958, 42988, 43017, 43046, 43076, 43105, 43135, 43164, 43194, 43223, 43253, 43283, 43312, 43342, - 43371, 43401, 43430, 43460, 43489, 43519, 43548, 43578, 43607, 43637, 43666, 43696, 43726, 43755, 43785, 43814, 43844, 43873, 43903, 43932, - 43962, 43991, 44021, 44050, 44080, 44109, 44139, 44169, 44198, 44228, 44258, 44287, 44317, 44346, 44375, 44405, 44434, 44464, 44493, 44523, - 44553, 44582, 44612, 44641, 44671, 44700, 44730, 44759, 44788, 44818, 44847, 44877, 44906, 44936, 44966, 44996, 45025, 45055, 45084, 45114, - 45143, 45172, 45202, 45231, 45261, 45290, 45320, 45350, 45380, 45409, 45439, 45468, 45498, 45527, 45556, 45586, 45615, 45644, 45674, 45704, - 45733, 45763, 45793, 45823, 45852, 45882, 45911, 45940, 45970, 45999, 46028, 46058, 46088, 46117, 46147, 46177, 46206, 46236, 46265, 46295, - 46324, 46354, 46383, 46413, 46442, 46472, 46501, 46531, 46560, 46590, 46620, 46649, 46679, 46708, 46738, 46767, 46797, 46826, 46856, 46885, - 46915, 46944, 46974, 47003, 47033, 47063, 47092, 47122, 47151, 47181, 47210, 47240, 47269, 47298, 47328, 47357, 47387, 47417, 47446, 47476, - 47506, 47535, 47565, 47594, 47624, 47653, 47682, 47712, 47741, 47771, 47800, 47830, 47860, 47890, 47919, 47949, 47978, 48008, 48037, 48066, - 48096, 48125, 48155, 48184, 48214, 48244, 48273, 48303, 48333, 48362, 48392, 48421, 48450, 48480, 48509, 48538, 48568, 48598, 48627, 48657, - 48687, 48717, 48746, 48776, 48805, 48834, 48864, 48893, 48922, 48952, 48982, 49011, 49041, 49071, 49100, 49130, 49160, 49189, 49218, 49248, - 49277, 49306, 49336, 49365, 49395, 49425, 49455, 49484, 49514, 49543, 49573, 49602, 49632, 49661, 49690, 49720, 49749, 49779, 49809, 49838, - 49868, 49898, 49927, 49957, 49986, 50016, 50045, 50075, 50104, 50133, 50163, 50192, 50222, 50252, 50281, 50311, 50340, 50370, 50400, 50429, - 50459, 50488, 50518, 50547, 50576, 50606, 50635, 50665, 50694, 50724, 50754, 50784, 50813, 50843, 50872, 50902, 50931, 50960, 50990, 51019, - 51049, 51078, 51108, 51138, 51167, 51197, 51227, 51256, 51286, 51315, 51345, 51374, 51403, 51433, 51462, 51492, 51522, 51552, 51582, 51611, - 51641, 51670, 51699, 51729, 51758, 51787, 51816, 51846, 51876, 51906, 51936, 51965, 51995, 52025, 52054, 52083, 52113, 52142, 52171, 52200, - 52230, 52260, 52290, 52319, 52349, 52379, 52408, 52438, 52467, 52497, 52526, 52555, 52585, 52614, 52644, 52673, 52703, 52733, 52762, 52792, - 52822, 52851, 52881, 52910, 52939, 52969, 52998, 53028, 53057, 53087, 53116, 53146, 53176, 53205, 53235, 53264, 53294, 53324, 53353, 53383, - 53412, 53441, 53471, 53500, 53530, 53559, 53589, 53619, 53648, 53678, 53708, 53737, 53767, 53796, 53825, 53855, 53884, 53913, 53943, 53973, - 54003, 54032, 54062, 54092, 54121, 54151, 54180, 54209, 54239, 54268, 54297, 54327, 54357, 54387, 54416, 54446, 54476, 54505, 54535, 54564, - 54593, 54623, 54652, 54681, 54711, 54741, 54770, 54800, 54830, 54859, 54889, 54919, 54948, 54977, 55007, 55036, 55066, 55095, 55125, 55154, - 55184, 55213, 55243, 55273, 55302, 55332, 55361, 55391, 55420, 55450, 55479, 55508, 55538, 55567, 55597, 55627, 55657, 55686, 55716, 55745, - 55775, 55804, 55834, 55863, 55892, 55922, 55951, 55981, 56011, 56040, 56070, 56100, 56129, 56159, 56188, 56218, 56247, 56276, 56306, 56335, - 56365, 56394, 56424, 56454, 56483, 56513, 56543, 56572, 56601, 56631, 56660, 56690, 56719, 56749, 56778, 56808, 56837, 56867, 56897, 56926, - 56956, 56985, 57015, 57044, 57074, 57103, 57133, 57162, 57192, 57221, 57251, 57280, 57310, 57340, 57369, 57399, 57429, 57458, 57487, 57517, - 57546, 57576, 57605, 57634, 57664, 57694, 57723, 57753, 57783, 57813, 57842, 57871, 57901, 57930, 57959, 57989, 58018, 58048, 58077, 58107, - 58137, 58167, 58196, 58226, 58255, 58285, 58314, 58343, 58373, 58402, 58432, 58461, 58491, 58521, 58551, 58580, 58610, 58639, 58669, 58698, - 58727, 58757, 58786, 58816, 58845, 58875, 58905, 58934, 58964, 58994, 59023, 59053, 59082, 59111, 59141, 59170, 59200, 59229, 59259, 59288, - 59318, 59348, 59377, 59407, 59436, 59466, 59495, 59525, 59554, 59584, 59613, 59643, 59672, 59702, 59731, 59761, 59791, 59820, 59850, 59879, - 59909, 59939, 59968, 59997, 60027, 60056, 60086, 60115, 60145, 60174, 60204, 60234, 60264, 60293, 60323, 60352, 60381, 60411, 60440, 60469, - 60499, 60528, 60558, 60588, 60618, 60648, 60677, 60707, 60736, 60765, 60795, 60824, 60853, 60883, 60912, 60942, 60972, 61002, 61031, 61061, - 61090, 61120, 61149, 61179, 61208, 61237, 61267, 61296, 61326, 61356, 61385, 61415, 61445, 61474, 61504, 61533, 61563, 61592, 61621, 61651, - 61680, 61710, 61739, 61769, 61799, 61828, 61858, 61888, 61917, 61947, 61976, 62006, 62035, 62064, 62094, 62123, 62153, 62182, 62212, 62242, - 62271, 62301, 62331, 62360, 62390, 62419, 62448, 62478, 62507, 62537, 62566, 62596, 62625, 62655, 62685, 62715, 62744, 62774, 62803, 62832, - 62862, 62891, 62921, 62950, 62980, 63009, 63039, 63069, 63099, 63128, 63157, 63187, 63216, 63246, 63275, 63305, 63334, 63363, 63393, 63423, - 63453, 63482, 63512, 63541, 63571, 63600, 63630, 63659, 63689, 63718, 63747, 63777, 63807, 63836, 63866, 63895, 63925, 63955, 63984, 64014, - 64043, 64073, 64102, 64131, 64161, 64190, 64220, 64249, 64279, 64309, 64339, 64368, 64398, 64427, 64457, 64486, 64515, 64545, 64574, 64603, - 64633, 64663, 64692, 64722, 64752, 64782, 64811, 64841, 64870, 64899, 64929, 64958, 64987, 65017, 65047, 65076, 65106, 65136, 65166, 65195, - 65225, 65254, 65283, 65313, 65342, 65371, 65401, 65431, 65460, 65490, 65520, 65549, 65579, 65608, 65638, 65667, 65697, 65726, 65755, 65785, - 65815, 65844, 65874, 65903, 65933, 65963, 65992, 66022, 66051, 66081, 66110, 66140, 66169, 66199, 66228, 66258, 66287, 66317, 66346, 66376, - 66405, 66435, 66465, 66494, 66524, 66553, 66583, 66612, 66641, 66671, 66700, 66730, 66760, 66789, 66819, 66849, 66878, 66908, 66937, 66967, - 66996, 67025, 67055, 67084, 67114, 67143, 67173, 67203, 67233, 67262, 67292, 67321, 67351, 67380, 67409, 67439, 67468, 67497, 67527, 67557, - 67587, 67617, 67646, 67676, 67705, 67735, 67764, 67793, 67823, 67852, 67882, 67911, 67941, 67971, 68000, 68030, 68060, 68089, 68119, 68148, - 68177, 68207, 68236, 68266, 68295, 68325, 68354, 68384, 68414, 68443, 68473, 68502, 68532, 68561, 68591, 68620, 68650, 68679, 68708, 68738, - 68768, 68797, 68827, 68857, 68886, 68916, 68946, 68975, 69004, 69034, 69063, 69092, 69122, 69152, 69181, 69211, 69240, 69270, 69300, 69330, - 69359, 69388, 69418, 69447, 69476, 69506, 69535, 69565, 69595, 69624, 69654, 69684, 69713, 69743, 69772, 69802, 69831, 69861, 69890, 69919, - 69949, 69978, 70008, 70038, 70067, 70097, 70126, 70156, 70186, 70215, 70245, 70274, 70303, 70333, 70362, 70392, 70421, 70451, 70481, 70510, - 70540, 70570, 70599, 70629, 70658, 70687, 70717, 70746, 70776, 70805, 70835, 70864, 70894, 70924, 70954, 70983, 71013, 71042, 71071, 71101, - 71130, 71159, 71189, 71218, 71248, 71278, 71308, 71337, 71367, 71397, 71426, 71455, 71485, 71514, 71543, 71573, 71602, 71632, 71662, 71691, - 71721, 71751, 71781, 71810, 71839, 71869, 71898, 71927, 71957, 71986, 72016, 72046, 72075, 72105, 72135, 72164, 72194, 72223, 72253, 72282, - 72311, 72341, 72370, 72400, 72429, 72459, 72489, 72518, 72548, 72577, 72607, 72637, 72666, 72695, 72725, 72754, 72784, 72813, 72843, 72872, - 72902, 72931, 72961, 72991, 73020, 73050, 73080, 73109, 73139, 73168, 73197, 73227, 73256, 73286, 73315, 73345, 73375, 73404, 73434, 73464, - 73493, 73523, 73552, 73581, 73611, 73640, 73669, 73699, 73729, 73758, 73788, 73818, 73848, 73877, 73907, 73936, 73965, 73995, 74024, 74053, - 74083, 74113, 74142, 74172, 74202, 74231, 74261, 74291, 74320, 74349, 74379, 74408, 74437, 74467, 74497, 74526, 74556, 74586, 74615, 74645, - 74675, 74704, 74733, 74763, 74792, 74822, 74851, 74881, 74910, 74940, 74969, 74999, 75029, 75058, 75088, 75117, 75147, 75176, 75206, 75235, - 75264, 75294, 75323, 75353, 75383, 75412, 75442, 75472, 75501, 75531, 75560, 75590, 75619, 75648, 75678, 75707, 75737, 75766, 75796, 75826, - 75856, 75885, 75915, 75944, 75974, 76003, 76032, 76062, 76091, 76121, 76150, 76180, 76210, 76239, 76269, 76299, 76328, 76358, 76387, 76416, - 76446, 76475, 76505, 76534, 76564, 76593, 76623, 76653, 76682, 76712, 76741, 76771, 76801, 76830, 76859, 76889, 76918, 76948, 76977, 77007, - 77036, 77066, 77096, 77125, 77155, 77185, 77214, 77243, 77273, 77302, 77332, 77361, 77390, 77420, 77450, 77479, 77509, 77539, 77569, 77598, - 77627, 77657, 77686, 77715, 77745, 77774, 77804, 77833, 77863, 77893, 77923, 77952, 77982, 78011, 78041, 78070, 78099, 78129, 78158, 78188, - 78217, 78247, 78277, 78307, 78336, 78366, 78395, 78425, 78454, 78483, 78513, 78542, 78572, 78601, 78631, 78661, 78690, 78720, 78750, 78779, - 78808, 78838, 78867, 78897, 78926, 78956, 78985, 79015, 79044, 79074, 79104, 79133, 79163, 79192, 79222, 79251, 79281, 79310, 79340, 79369, - 79399, 79428, 79458, 79487, 79517, 79546, 79576, 79606, 79635, 79665, 79695, 79724, 79753, 79783, 79812, 79841, 79871, 79900, 79930, 79960, - 79990]; - - -},{"../main":571,"object-assign":454}],571:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Calendars for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var assign = _dereq_('object-assign'); - - -function Calendars() { - this.regionalOptions = []; - this.regionalOptions[''] = { - invalidCalendar: 'Calendar {0} not found', - invalidDate: 'Invalid {0} date', - invalidMonth: 'Invalid {0} month', - invalidYear: 'Invalid {0} year', - differentCalendars: 'Cannot mix {0} and {1} dates' - }; - this.local = this.regionalOptions['']; - this.calendars = {}; - this._localCals = {}; -} - -/** Create the calendars plugin. -

Provides support for various world calendars in a consistent manner.

- @class Calendars - @example _exports.instance('julian').newDate(2014, 12, 25) */ -assign(Calendars.prototype, { - - /** Obtain a calendar implementation and localisation. - @memberof Calendars - @param [name='gregorian'] {string} The name of the calendar, e.g. 'gregorian', 'persian', 'islamic'. - @param [language=''] {string} The language code to use for localisation (default is English). - @return {Calendar} The calendar and localisation. - @throws Error if calendar not found. */ - instance: function(name, language) { - name = (name || 'gregorian').toLowerCase(); - language = language || ''; - var cal = this._localCals[name + '-' + language]; - if (!cal && this.calendars[name]) { - cal = new this.calendars[name](language); - this._localCals[name + '-' + language] = cal; - } - if (!cal) { - throw (this.local.invalidCalendar || this.regionalOptions[''].invalidCalendar). - replace(/\{0\}/, name); - } - return cal; - }, - - /** Create a new date - for today if no other parameters given. - @memberof Calendars - @param year {CDate|number} The date to copy or the year for the date. - @param [month] {number} The month for the date. - @param [day] {number} The day for the date. - @param [calendar='gregorian'] {BaseCalendar|string} The underlying calendar or the name of the calendar. - @param [language=''] {string} The language to use for localisation (default English). - @return {CDate} The new date. - @throws Error if an invalid date. */ - newDate: function(year, month, day, calendar, language) { - calendar = (year != null && year.year ? year.calendar() : (typeof calendar === 'string' ? - this.instance(calendar, language) : calendar)) || this.instance(); - return calendar.newDate(year, month, day); - }, - - /** A simple digit substitution function for localising numbers via the Calendar digits option. - @member Calendars - @param digits {string[]} The substitute digits, for 0 through 9. - @return {function} The substitution function. */ - substituteDigits: function(digits) { - return function(value) { - return (value + '').replace(/[0-9]/g, function(digit) { - return digits[digit]; - }); - } - }, - - /** Digit substitution function for localising Chinese style numbers via the Calendar digits option. - @member Calendars - @param digits {string[]} The substitute digits, for 0 through 9. - @param powers {string[]} The characters denoting powers of 10, i.e. 1, 10, 100, 1000. - @return {function} The substitution function. */ - substituteChineseDigits: function(digits, powers) { - return function(value) { - var localNumber = ''; - var power = 0; - while (value > 0) { - var units = value % 10; - localNumber = (units === 0 ? '' : digits[units] + powers[power]) + localNumber; - power++; - value = Math.floor(value / 10); - } - if (localNumber.indexOf(digits[1] + powers[1]) === 0) { - localNumber = localNumber.substr(1); - } - return localNumber || digits[0]; - } - } -}); - -/** Generic date, based on a particular calendar. - @class CDate - @param calendar {BaseCalendar} The underlying calendar implementation. - @param year {number} The year for this date. - @param month {number} The month for this date. - @param day {number} The day for this date. - @return {CDate} The date object. - @throws Error if an invalid date. */ -function CDate(calendar, year, month, day) { - this._calendar = calendar; - this._year = year; - this._month = month; - this._day = day; - if (this._calendar._validateLevel === 0 && - !this._calendar.isValid(this._year, this._month, this._day)) { - throw (_exports.local.invalidDate || _exports.regionalOptions[''].invalidDate). - replace(/\{0\}/, this._calendar.local.name); - } -} - -/** Pad a numeric value with leading zeroes. - @private - @param value {number} The number to format. - @param length {number} The minimum length. - @return {string} The formatted number. */ -function pad(value, length) { - value = '' + value; - return '000000'.substring(0, length - value.length) + value; -} - -assign(CDate.prototype, { - - /** Create a new date. - @memberof CDate - @param [year] {CDate|number} The date to copy or the year for the date (default this date). - @param [month] {number} The month for the date. - @param [day] {number} The day for the date. - @return {CDate} The new date. - @throws Error if an invalid date. */ - newDate: function(year, month, day) { - return this._calendar.newDate((year == null ? this : year), month, day); - }, - - /** Set or retrieve the year for this date. - @memberof CDate - @param [year] {number} The year for the date. - @return {number|CDate} The date's year (if no parameter) or the updated date. - @throws Error if an invalid date. */ - year: function(year) { - return (arguments.length === 0 ? this._year : this.set(year, 'y')); - }, - - /** Set or retrieve the month for this date. - @memberof CDate - @param [month] {number} The month for the date. - @return {number|CDate} The date's month (if no parameter) or the updated date. - @throws Error if an invalid date. */ - month: function(month) { - return (arguments.length === 0 ? this._month : this.set(month, 'm')); - }, - - /** Set or retrieve the day for this date. - @memberof CDate - @param [day] {number} The day for the date. - @return {number|CData} The date's day (if no parameter) or the updated date. - @throws Error if an invalid date. */ - day: function(day) { - return (arguments.length === 0 ? this._day : this.set(day, 'd')); - }, - - /** Set new values for this date. - @memberof CDate - @param year {number} The year for the date. - @param month {number} The month for the date. - @param day {number} The day for the date. - @return {CDate} The updated date. - @throws Error if an invalid date. */ - date: function(year, month, day) { - if (!this._calendar.isValid(year, month, day)) { - throw (_exports.local.invalidDate || _exports.regionalOptions[''].invalidDate). - replace(/\{0\}/, this._calendar.local.name); - } - this._year = year; - this._month = month; - this._day = day; - return this; - }, - - /** Determine whether this date is in a leap year. - @memberof CDate - @return {boolean} true if this is a leap year, false if not. */ - leapYear: function() { - return this._calendar.leapYear(this); - }, - - /** Retrieve the epoch designator for this date, e.g. BCE or CE. - @memberof CDate - @return {string} The current epoch. */ - epoch: function() { - return this._calendar.epoch(this); - }, - - /** Format the year, if not a simple sequential number. - @memberof CDate - @return {string} The formatted year. */ - formatYear: function() { - return this._calendar.formatYear(this); - }, - - /** Retrieve the month of the year for this date, - i.e. the month's position within a numbered year. - @memberof CDate - @return {number} The month of the year: minMonth to months per year. */ - monthOfYear: function() { - return this._calendar.monthOfYear(this); - }, - - /** Retrieve the week of the year for this date. - @memberof CDate - @return {number} The week of the year: 1 to weeks per year. */ - weekOfYear: function() { - return this._calendar.weekOfYear(this); - }, - - /** Retrieve the number of days in the year for this date. - @memberof CDate - @return {number} The number of days in this year. */ - daysInYear: function() { - return this._calendar.daysInYear(this); - }, - - /** Retrieve the day of the year for this date. - @memberof CDate - @return {number} The day of the year: 1 to days per year. */ - dayOfYear: function() { - return this._calendar.dayOfYear(this); - }, - - /** Retrieve the number of days in the month for this date. - @memberof CDate - @return {number} The number of days. */ - daysInMonth: function() { - return this._calendar.daysInMonth(this); - }, - - /** Retrieve the day of the week for this date. - @memberof CDate - @return {number} The day of the week: 0 to number of days - 1. */ - dayOfWeek: function() { - return this._calendar.dayOfWeek(this); - }, - - /** Determine whether this date is a week day. - @memberof CDate - @return {boolean} true if a week day, false if not. */ - weekDay: function() { - return this._calendar.weekDay(this); - }, - - /** Retrieve additional information about this date. - @memberof CDate - @return {object} Additional information - contents depends on calendar. */ - extraInfo: function() { - return this._calendar.extraInfo(this); - }, - - /** Add period(s) to a date. - @memberof CDate - @param offset {number} The number of periods to adjust by. - @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. - @return {CDate} The updated date. */ - add: function(offset, period) { - return this._calendar.add(this, offset, period); - }, - - /** Set a portion of the date. - @memberof CDate - @param value {number} The new value for the period. - @param period {string} One of 'y' for year, 'm' for month, 'd' for day. - @return {CDate} The updated date. - @throws Error if not a valid date. */ - set: function(value, period) { - return this._calendar.set(this, value, period); - }, - - /** Compare this date to another date. - @memberof CDate - @param date {CDate} The other date. - @return {number} -1 if this date is before the other date, - 0 if they are equal, or +1 if this date is after the other date. */ - compareTo: function(date) { - if (this._calendar.name !== date._calendar.name) { - throw (_exports.local.differentCalendars || _exports.regionalOptions[''].differentCalendars). - replace(/\{0\}/, this._calendar.local.name).replace(/\{1\}/, date._calendar.local.name); - } - var c = (this._year !== date._year ? this._year - date._year : - this._month !== date._month ? this.monthOfYear() - date.monthOfYear() : - this._day - date._day); - return (c === 0 ? 0 : (c < 0 ? -1 : +1)); - }, - - /** Retrieve the calendar backing this date. - @memberof CDate - @return {BaseCalendar} The calendar implementation. */ - calendar: function() { - return this._calendar; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof CDate - @return {number} The equivalent Julian date. */ - toJD: function() { - return this._calendar.toJD(this); - }, - - /** Create a new date from a Julian date. - @memberof CDate - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - return this._calendar.fromJD(jd); - }, - - /** Convert this date to a standard (Gregorian) JavaScript Date. - @memberof CDate - @return {Date} The equivalent JavaScript date. */ - toJSDate: function() { - return this._calendar.toJSDate(this); - }, - - /** Create a new date from a standard (Gregorian) JavaScript Date. - @memberof CDate - @param jsd {Date} The JavaScript date to convert. - @return {CDate} The equivalent date. */ - fromJSDate: function(jsd) { - return this._calendar.fromJSDate(jsd); - }, - - /** Convert to a string for display. - @memberof CDate - @return {string} This date as a string. */ - toString: function() { - return (this.year() < 0 ? '-' : '') + pad(Math.abs(this.year()), 4) + - '-' + pad(this.month(), 2) + '-' + pad(this.day(), 2); - } -}); - -/** Basic functionality for all calendars. - Other calendars should extend this: -
OtherCalendar.prototype = new BaseCalendar;
- @class BaseCalendar */ -function BaseCalendar() { - this.shortYearCutoff = '+10'; -} - -assign(BaseCalendar.prototype, { - _validateLevel: 0, // "Stack" to turn validation on/off - - /** Create a new date within this calendar - today if no parameters given. - @memberof BaseCalendar - @param year {CDate|number} The date to duplicate or the year for the date. - @param [month] {number} The month for the date. - @param [day] {number} The day for the date. - @return {CDate} The new date. - @throws Error if not a valid date or a different calendar used. */ - newDate: function(year, month, day) { - if (year == null) { - return this.today(); - } - if (year.year) { - this._validate(year, month, day, - _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); - day = year.day(); - month = year.month(); - year = year.year(); - } - return new CDate(this, year, month, day); - }, - - /** Create a new date for today. - @memberof BaseCalendar - @return {CDate} Today's date. */ - today: function() { - return this.fromJSDate(new Date()); - }, - - /** Retrieve the epoch designator for this date. - @memberof BaseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {string} The current epoch. - @throws Error if an invalid year or a different calendar used. */ - epoch: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, - _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); - return (date.year() < 0 ? this.local.epochs[0] : this.local.epochs[1]); - }, - - /** Format the year, if not a simple sequential number - @memberof BaseCalendar - @param year {CDate|number} The date to format or the year to format. - @return {string} The formatted year. - @throws Error if an invalid year or a different calendar used. */ - formatYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, - _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); - return (date.year() < 0 ? '-' : '') + pad(Math.abs(date.year()), 4) - }, - - /** Retrieve the number of months in a year. - @memberof BaseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of months. - @throws Error if an invalid year or a different calendar used. */ - monthsInYear: function(year) { - this._validate(year, this.minMonth, this.minDay, - _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); - return 12; - }, - - /** Calculate the month's ordinal position within the year - - for those calendars that don't start at month 1! - @memberof BaseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param month {number} The month to examine. - @return {number} The ordinal position, starting from minMonth. - @throws Error if an invalid year/month or a different calendar used. */ - monthOfYear: function(year, month) { - var date = this._validate(year, month, this.minDay, - _exports.local.invalidMonth || _exports.regionalOptions[''].invalidMonth); - return (date.month() + this.monthsInYear(date) - this.firstMonth) % - this.monthsInYear(date) + this.minMonth; - }, - - /** Calculate actual month from ordinal position, starting from minMonth. - @memberof BaseCalendar - @param year {number} The year to examine. - @param ord {number} The month's ordinal position. - @return {number} The month's number. - @throws Error if an invalid year/month. */ - fromMonthOfYear: function(year, ord) { - var m = (ord + this.firstMonth - 2 * this.minMonth) % - this.monthsInYear(year) + this.minMonth; - this._validate(year, m, this.minDay, - _exports.local.invalidMonth || _exports.regionalOptions[''].invalidMonth); - return m; - }, - - /** Retrieve the number of days in a year. - @memberof BaseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {number} The number of days. - @throws Error if an invalid year or a different calendar used. */ - daysInYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, - _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); - return (this.leapYear(date) ? 366 : 365); - }, - - /** Retrieve the day of the year for a date. - @memberof BaseCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The day of the year. - @throws Error if an invalid date or a different calendar used. */ - dayOfYear: function(year, month, day) { - var date = this._validate(year, month, day, - _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); - return date.toJD() - this.newDate(date.year(), - this.fromMonthOfYear(date.year(), this.minMonth), this.minDay).toJD() + 1; - }, - - /** Retrieve the number of days in a week. - @memberof BaseCalendar - @return {number} The number of days. */ - daysInWeek: function() { - return 7; - }, - - /** Retrieve the day of the week for a date. - @memberof BaseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The day of the week: 0 to number of days - 1. - @throws Error if an invalid date or a different calendar used. */ - dayOfWeek: function(year, month, day) { - var date = this._validate(year, month, day, - _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); - return (Math.floor(this.toJD(date)) + 2) % this.daysInWeek(); - }, - - /** Retrieve additional information about a date. - @memberof BaseCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {object} Additional information - contents depends on calendar. - @throws Error if an invalid date or a different calendar used. */ - extraInfo: function(year, month, day) { - this._validate(year, month, day, - _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); - return {}; - }, - - /** Add period(s) to a date. - Cater for no year zero. - @memberof BaseCalendar - @param date {CDate} The starting date. - @param offset {number} The number of periods to adjust by. - @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. - @return {CDate} The updated date. - @throws Error if a different calendar used. */ - add: function(date, offset, period) { - this._validate(date, this.minMonth, this.minDay, - _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); - return this._correctAdd(date, this._add(date, offset, period), offset, period); - }, - - /** Add period(s) to a date. - @memberof BaseCalendar - @private - @param date {CDate} The starting date. - @param offset {number} The number of periods to adjust by. - @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. - @return {CDate} The updated date. */ - _add: function(date, offset, period) { - this._validateLevel++; - if (period === 'd' || period === 'w') { - var jd = date.toJD() + offset * (period === 'w' ? this.daysInWeek() : 1); - var d = date.calendar().fromJD(jd); - this._validateLevel--; - return [d.year(), d.month(), d.day()]; - } - try { - var y = date.year() + (period === 'y' ? offset : 0); - var m = date.monthOfYear() + (period === 'm' ? offset : 0); - var d = date.day();// + (period === 'd' ? offset : 0) + - //(period === 'w' ? offset * this.daysInWeek() : 0); - var resyncYearMonth = function(calendar) { - while (m < calendar.minMonth) { - y--; - m += calendar.monthsInYear(y); - } - var yearMonths = calendar.monthsInYear(y); - while (m > yearMonths - 1 + calendar.minMonth) { - y++; - m -= yearMonths; - yearMonths = calendar.monthsInYear(y); - } - }; - if (period === 'y') { - if (date.month() !== this.fromMonthOfYear(y, m)) { // Hebrew - m = this.newDate(y, date.month(), this.minDay).monthOfYear(); - } - m = Math.min(m, this.monthsInYear(y)); - d = Math.min(d, this.daysInMonth(y, this.fromMonthOfYear(y, m))); - } - else if (period === 'm') { - resyncYearMonth(this); - d = Math.min(d, this.daysInMonth(y, this.fromMonthOfYear(y, m))); - } - var ymd = [y, this.fromMonthOfYear(y, m), d]; - this._validateLevel--; - return ymd; - } - catch (e) { - this._validateLevel--; - throw e; - } - }, - - /** Correct a candidate date after adding period(s) to a date. - Handle no year zero if necessary. - @memberof BaseCalendar - @private - @param date {CDate} The starting date. - @param ymd {number[]} The added date. - @param offset {number} The number of periods to adjust by. - @param period {string} One of 'y' for year, 'm' for month, 'w' for week, 'd' for day. - @return {CDate} The updated date. */ - _correctAdd: function(date, ymd, offset, period) { - if (!this.hasYearZero && (period === 'y' || period === 'm')) { - if (ymd[0] === 0 || // In year zero - (date.year() > 0) !== (ymd[0] > 0)) { // Crossed year zero - var adj = {y: [1, 1, 'y'], m: [1, this.monthsInYear(-1), 'm'], - w: [this.daysInWeek(), this.daysInYear(-1), 'd'], - d: [1, this.daysInYear(-1), 'd']}[period]; - var dir = (offset < 0 ? -1 : +1); - ymd = this._add(date, offset * adj[0] + dir * adj[1], adj[2]); - } - } - return date.date(ymd[0], ymd[1], ymd[2]); - }, - - /** Set a portion of the date. - @memberof BaseCalendar - @param date {CDate} The starting date. - @param value {number} The new value for the period. - @param period {string} One of 'y' for year, 'm' for month, 'd' for day. - @return {CDate} The updated date. - @throws Error if an invalid date or a different calendar used. */ - set: function(date, value, period) { - this._validate(date, this.minMonth, this.minDay, - _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); - var y = (period === 'y' ? value : date.year()); - var m = (period === 'm' ? value : date.month()); - var d = (period === 'd' ? value : date.day()); - if (period === 'y' || period === 'm') { - d = Math.min(d, this.daysInMonth(y, m)); - } - return date.date(y, m, d); - }, - - /** Determine whether a date is valid for this calendar. - @memberof BaseCalendar - @param year {number} The year to examine. - @param month {number} The month to examine. - @param day {number} The day to examine. - @return {boolean} true if a valid date, false if not. */ - isValid: function(year, month, day) { - this._validateLevel++; - var valid = (this.hasYearZero || year !== 0); - if (valid) { - var date = this.newDate(year, month, this.minDay); - valid = (month >= this.minMonth && month - this.minMonth < this.monthsInYear(date)) && - (day >= this.minDay && day - this.minDay < this.daysInMonth(date)); - } - this._validateLevel--; - return valid; - }, - - /** Convert the date to a standard (Gregorian) JavaScript Date. - @memberof BaseCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {Date} The equivalent JavaScript date. - @throws Error if an invalid date or a different calendar used. */ - toJSDate: function(year, month, day) { - var date = this._validate(year, month, day, - _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); - return _exports.instance().fromJD(this.toJD(date)).toJSDate(); - }, - - /** Convert the date from a standard (Gregorian) JavaScript Date. - @memberof BaseCalendar - @param jsd {Date} The JavaScript date. - @return {CDate} The equivalent calendar date. */ - fromJSDate: function(jsd) { - return this.fromJD(_exports.instance().fromJSDate(jsd).toJD()); - }, - - /** Check that a candidate date is from the same calendar and is valid. - @memberof BaseCalendar - @private - @param year {CDate|number} The date to validate or the year to validate. - @param [month] {number} The month to validate. - @param [day] {number} The day to validate. - @param error {string} Rrror message if invalid. - @throws Error if different calendars used or invalid date. */ - _validate: function(year, month, day, error) { - if (year.year) { - if (this._validateLevel === 0 && this.name !== year.calendar().name) { - throw (_exports.local.differentCalendars || _exports.regionalOptions[''].differentCalendars). - replace(/\{0\}/, this.local.name).replace(/\{1\}/, year.calendar().local.name); - } - return year; - } - try { - this._validateLevel++; - if (this._validateLevel === 1 && !this.isValid(year, month, day)) { - throw error.replace(/\{0\}/, this.local.name); - } - var date = this.newDate(year, month, day); - this._validateLevel--; - return date; - } - catch (e) { - this._validateLevel--; - throw e; - } - } -}); - -/** Implementation of the Proleptic Gregorian Calendar. - See http://en.wikipedia.org/wiki/Gregorian_calendar - and http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar. - @class GregorianCalendar - @augments BaseCalendar - @param [language=''] {string} The language code (default English) for localisation. */ -function GregorianCalendar(language) { - this.local = this.regionalOptions[language] || this.regionalOptions['']; -} - -GregorianCalendar.prototype = new BaseCalendar; - -assign(GregorianCalendar.prototype, { - /** The calendar name. - @memberof GregorianCalendar */ - name: 'Gregorian', - /** Julian date of start of Gregorian epoch: 1 January 0001 CE. - @memberof GregorianCalendar */ - jdEpoch: 1721425.5, - /** Days per month in a common year. - @memberof GregorianCalendar */ - daysPerMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], - /** true if has a year zero, false if not. - @memberof GregorianCalendar */ - hasYearZero: false, - /** The minimum month number. - @memberof GregorianCalendar */ - minMonth: 1, - /** The first month in the year. - @memberof GregorianCalendar */ - firstMonth: 1, - /** The minimum day number. - @memberof GregorianCalendar */ - minDay: 1, - - /** Localisations for the plugin. - Entries are objects indexed by the language code ('' being the default US/English). - Each object has the following attributes. - @memberof GregorianCalendar - @property name {string} The calendar name. - @property epochs {string[]} The epoch names. - @property monthNames {string[]} The long names of the months of the year. - @property monthNamesShort {string[]} The short names of the months of the year. - @property dayNames {string[]} The long names of the days of the week. - @property dayNamesShort {string[]} The short names of the days of the week. - @property dayNamesMin {string[]} The minimal names of the days of the week. - @property dateFormat {string} The date format for this calendar. - See the options on formatDate for details. - @property firstDay {number} The number of the first day of the week, starting at 0. - @property isRTL {number} true if this localisation reads right-to-left. */ - regionalOptions: { // Localisations - '': { - name: 'Gregorian', - epochs: ['BCE', 'CE'], - monthNames: ['January', 'February', 'March', 'April', 'May', 'June', - 'July', 'August', 'September', 'October', 'November', 'December'], - monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], - dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], - dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], - digits: null, - dateFormat: 'mm/dd/yyyy', - firstDay: 0, - isRTL: false - } - }, - - /** Determine whether this date is in a leap year. - @memberof GregorianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @return {boolean} true if this is a leap year, false if not. - @throws Error if an invalid year or a different calendar used. */ - leapYear: function(year) { - var date = this._validate(year, this.minMonth, this.minDay, - _exports.local.invalidYear || _exports.regionalOptions[''].invalidYear); - var year = date.year() + (date.year() < 0 ? 1 : 0); // No year zero - return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); - }, - - /** Determine the week of the year for a date - ISO 8601. - @memberof GregorianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {number} The week of the year, starting from 1. - @throws Error if an invalid date or a different calendar used. */ - weekOfYear: function(year, month, day) { - // Find Thursday of this week starting on Monday - var checkDate = this.newDate(year, month, day); - checkDate.add(4 - (checkDate.dayOfWeek() || 7), 'd'); - return Math.floor((checkDate.dayOfYear() - 1) / 7) + 1; - }, - - /** Retrieve the number of days in a month. - @memberof GregorianCalendar - @param year {CDate|number} The date to examine or the year of the month. - @param [month] {number} The month. - @return {number} The number of days in this month. - @throws Error if an invalid month/year or a different calendar used. */ - daysInMonth: function(year, month) { - var date = this._validate(year, month, this.minDay, - _exports.local.invalidMonth || _exports.regionalOptions[''].invalidMonth); - return this.daysPerMonth[date.month() - 1] + - (date.month() === 2 && this.leapYear(date.year()) ? 1 : 0); - }, - - /** Determine whether this date is a week day. - @memberof GregorianCalendar - @param year {CDate|number} The date to examine or the year to examine. - @param [month] {number} The month to examine. - @param [day] {number} The day to examine. - @return {boolean} true if a week day, false if not. - @throws Error if an invalid date or a different calendar used. */ - weekDay: function(year, month, day) { - return (this.dayOfWeek(year, month, day) || 7) < 6; - }, - - /** Retrieve the Julian date equivalent for this date, - i.e. days since January 1, 4713 BCE Greenwich noon. - @memberof GregorianCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {number} The equivalent Julian date. - @throws Error if an invalid date or a different calendar used. */ - toJD: function(year, month, day) { - var date = this._validate(year, month, day, - _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); - year = date.year(); - month = date.month(); - day = date.day(); - if (year < 0) { year++; } // No year zero - // Jean Meeus algorithm, "Astronomical Algorithms", 1991 - if (month < 3) { - month += 12; - year--; - } - var a = Math.floor(year / 100); - var b = 2 - a + Math.floor(a / 4); - return Math.floor(365.25 * (year + 4716)) + - Math.floor(30.6001 * (month + 1)) + day + b - 1524.5; - }, - - /** Create a new date from a Julian date. - @memberof GregorianCalendar - @param jd {number} The Julian date to convert. - @return {CDate} The equivalent date. */ - fromJD: function(jd) { - // Jean Meeus algorithm, "Astronomical Algorithms", 1991 - var z = Math.floor(jd + 0.5); - var a = Math.floor((z - 1867216.25) / 36524.25); - a = z + 1 + a - Math.floor(a / 4); - var b = a + 1524; - var c = Math.floor((b - 122.1) / 365.25); - var d = Math.floor(365.25 * c); - var e = Math.floor((b - d) / 30.6001); - var day = b - d - Math.floor(e * 30.6001); - var month = e - (e > 13.5 ? 13 : 1); - var year = c - (month > 2.5 ? 4716 : 4715); - if (year <= 0) { year--; } // No year zero - return this.newDate(year, month, day); - }, - - /** Convert this date to a standard (Gregorian) JavaScript Date. - @memberof GregorianCalendar - @param year {CDate|number} The date to convert or the year to convert. - @param [month] {number} The month to convert. - @param [day] {number} The day to convert. - @return {Date} The equivalent JavaScript date. - @throws Error if an invalid date or a different calendar used. */ - toJSDate: function(year, month, day) { - var date = this._validate(year, month, day, - _exports.local.invalidDate || _exports.regionalOptions[''].invalidDate); - var jsd = new Date(date.year(), date.month() - 1, date.day()); - jsd.setHours(0); - jsd.setMinutes(0); - jsd.setSeconds(0); - jsd.setMilliseconds(0); - // Hours may be non-zero on daylight saving cut-over: - // > 12 when midnight changeover, but then cannot generate - // midnight datetime, so jump to 1AM, otherwise reset. - jsd.setHours(jsd.getHours() > 12 ? jsd.getHours() + 2 : 0); - return jsd; - }, - - /** Create a new date from a standard (Gregorian) JavaScript Date. - @memberof GregorianCalendar - @param jsd {Date} The JavaScript date to convert. - @return {CDate} The equivalent date. */ - fromJSDate: function(jsd) { - return this.newDate(jsd.getFullYear(), jsd.getMonth() + 1, jsd.getDate()); - } -}); - -// Singleton manager -var _exports = module.exports = new Calendars(); - -// Date template -_exports.cdate = CDate; - -// Base calendar template -_exports.baseCalendar = BaseCalendar; - -// Gregorian calendar implementation -_exports.calendars.gregorian = GregorianCalendar; - - -},{"object-assign":454}],572:[function(_dereq_,module,exports){ -/* - * World Calendars - * https://github.com/alexcjohnson/world-calendars - * - * Batch-converted from kbwood/calendars - * Many thanks to Keith Wood and all of the contributors to the original project! - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* http://keith-wood.name/calendars.html - Calendars extras for jQuery v2.0.2. - Written by Keith Wood (wood.keith{at}optusnet.com.au) August 2009. - Available under the MIT (http://keith-wood.name/licence.html) license. - Please attribute the author if you use it. */ - -var assign = _dereq_('object-assign'); -var main = _dereq_('./main'); - - -assign(main.regionalOptions[''], { - invalidArguments: 'Invalid arguments', - invalidFormat: 'Cannot format a date from another calendar', - missingNumberAt: 'Missing number at position {0}', - unknownNameAt: 'Unknown name at position {0}', - unexpectedLiteralAt: 'Unexpected literal at position {0}', - unexpectedText: 'Additional text found at end' -}); -main.local = main.regionalOptions['']; - -assign(main.cdate.prototype, { - - /** Format this date. - Found in the jquery.calendars.plus.js module. - @memberof CDate - @param [format] {string} The date format to use (see formatDate). - @param [settings] {object} Options for the formatDate function. - @return {string} The formatted date. */ - formatDate: function(format, settings) { - if (typeof format !== 'string') { - settings = format; - format = ''; - } - return this._calendar.formatDate(format || '', this, settings); - } -}); - -assign(main.baseCalendar.prototype, { - - UNIX_EPOCH: main.instance().newDate(1970, 1, 1).toJD(), - SECS_PER_DAY: 24 * 60 * 60, - TICKS_EPOCH: main.instance().jdEpoch, // 1 January 0001 CE - TICKS_PER_DAY: 24 * 60 * 60 * 10000000, - - /** Date form for ATOM (RFC 3339/ISO 8601). - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - ATOM: 'yyyy-mm-dd', - /** Date form for cookies. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - COOKIE: 'D, dd M yyyy', - /** Date form for full date. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - FULL: 'DD, MM d, yyyy', - /** Date form for ISO 8601. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - ISO_8601: 'yyyy-mm-dd', - /** Date form for Julian date. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - JULIAN: 'J', - /** Date form for RFC 822. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - RFC_822: 'D, d M yy', - /** Date form for RFC 850. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - RFC_850: 'DD, dd-M-yy', - /** Date form for RFC 1036. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - RFC_1036: 'D, d M yy', - /** Date form for RFC 1123. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - RFC_1123: 'D, d M yyyy', - /** Date form for RFC 2822. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - RFC_2822: 'D, d M yyyy', - /** Date form for RSS (RFC 822). - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - RSS: 'D, d M yy', - /** Date form for Windows ticks. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - TICKS: '!', - /** Date form for Unix timestamp. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - TIMESTAMP: '@', - /** Date form for W3c (ISO 8601). - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar */ - W3C: 'yyyy-mm-dd', - - /** Format a date object into a string value. - The format can be combinations of the following: -
    -
  • d - day of month (no leading zero)
  • -
  • dd - day of month (two digit)
  • -
  • o - day of year (no leading zeros)
  • -
  • oo - day of year (three digit)
  • -
  • D - day name short
  • -
  • DD - day name long
  • -
  • w - week of year (no leading zero)
  • -
  • ww - week of year (two digit)
  • -
  • m - month of year (no leading zero)
  • -
  • mm - month of year (two digit)
  • -
  • M - month name short
  • -
  • MM - month name long
  • -
  • yy - year (two digit)
  • -
  • yyyy - year (four digit)
  • -
  • YYYY - formatted year
  • -
  • J - Julian date (days since January 1, 4713 BCE Greenwich noon)
  • -
  • @ - Unix timestamp (s since 01/01/1970)
  • -
  • ! - Windows ticks (100ns since 01/01/0001)
  • -
  • '...' - literal text
  • -
  • '' - single quote
  • -
- Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar - @param [format] {string} The desired format of the date (defaults to calendar format). - @param date {CDate} The date value to format. - @param [settings] {object} Addition options, whose attributes include: - @property [dayNamesShort] {string[]} Abbreviated names of the days from Sunday. - @property [dayNames] {string[]} Names of the days from Sunday. - @property [monthNamesShort] {string[]} Abbreviated names of the months. - @property [monthNames] {string[]} Names of the months. - @property [calculateWeek] {CalendarsPickerCalculateWeek} Function that determines week of the year. - @property [localNumbers=false] {boolean} true to localise numbers (if available), - false to use normal Arabic numerals. - @return {string} The date in the above format. - @throws Errors if the date is from a different calendar. */ - formatDate: function(format, date, settings) { - if (typeof format !== 'string') { - settings = date; - date = format; - format = ''; - } - if (!date) { - return ''; - } - if (date.calendar() !== this) { - throw main.local.invalidFormat || main.regionalOptions[''].invalidFormat; - } - format = format || this.local.dateFormat; - settings = settings || {}; - var dayNamesShort = settings.dayNamesShort || this.local.dayNamesShort; - var dayNames = settings.dayNames || this.local.dayNames; - var monthNumbers = settings.monthNumbers || this.local.monthNumbers; - var monthNamesShort = settings.monthNamesShort || this.local.monthNamesShort; - var monthNames = settings.monthNames || this.local.monthNames; - var calculateWeek = settings.calculateWeek || this.local.calculateWeek; - // Check whether a format character is doubled - var doubled = function(match, step) { - var matches = 1; - while (iFormat + matches < format.length && format.charAt(iFormat + matches) === match) { - matches++; - } - iFormat += matches - 1; - return Math.floor(matches / (step || 1)) > 1; - }; - // Format a number, with leading zeroes if necessary - var formatNumber = function(match, value, len, step) { - var num = '' + value; - if (doubled(match, step)) { - while (num.length < len) { - num = '0' + num; - } - } - return num; - }; - // Format a name, short or long as requested - var formatName = function(match, value, shortNames, longNames) { - return (doubled(match) ? longNames[value] : shortNames[value]); - }; - // Format month number - // (e.g. Chinese calendar needs to account for intercalary months) - var calendar = this; - var formatMonth = function(date) { - return (typeof monthNumbers === 'function') ? - monthNumbers.call(calendar, date, doubled('m')) : - localiseNumbers(formatNumber('m', date.month(), 2)); - }; - // Format a month name, short or long as requested - var formatMonthName = function(date, useLongName) { - if (useLongName) { - return (typeof monthNames === 'function') ? - monthNames.call(calendar, date) : - monthNames[date.month() - calendar.minMonth]; - } else { - return (typeof monthNamesShort === 'function') ? - monthNamesShort.call(calendar, date) : - monthNamesShort[date.month() - calendar.minMonth]; - } - }; - // Localise numbers if requested and available - var digits = this.local.digits; - var localiseNumbers = function(value) { - return (settings.localNumbers && digits ? digits(value) : value); - }; - var output = ''; - var literal = false; - for (var iFormat = 0; iFormat < format.length; iFormat++) { - if (literal) { - if (format.charAt(iFormat) === "'" && !doubled("'")) { - literal = false; - } - else { - output += format.charAt(iFormat); - } - } - else { - switch (format.charAt(iFormat)) { - case 'd': output += localiseNumbers(formatNumber('d', date.day(), 2)); break; - case 'D': output += formatName('D', date.dayOfWeek(), - dayNamesShort, dayNames); break; - case 'o': output += formatNumber('o', date.dayOfYear(), 3); break; - case 'w': output += formatNumber('w', date.weekOfYear(), 2); break; - case 'm': output += formatMonth(date); break; - case 'M': output += formatMonthName(date, doubled('M')); break; - case 'y': - output += (doubled('y', 2) ? date.year() : - (date.year() % 100 < 10 ? '0' : '') + date.year() % 100); - break; - case 'Y': - doubled('Y', 2); - output += date.formatYear(); - break; - case 'J': output += date.toJD(); break; - case '@': output += (date.toJD() - this.UNIX_EPOCH) * this.SECS_PER_DAY; break; - case '!': output += (date.toJD() - this.TICKS_EPOCH) * this.TICKS_PER_DAY; break; - case "'": - if (doubled("'")) { - output += "'"; - } - else { - literal = true; - } - break; - default: - output += format.charAt(iFormat); - } - } - } - return output; - }, - - /** Parse a string value into a date object. - See formatDate for the possible formats, plus: -
    -
  • * - ignore rest of string
  • -
- Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar - @param format {string} The expected format of the date ('' for default calendar format). - @param value {string} The date in the above format. - @param [settings] {object} Additional options whose attributes include: - @property [shortYearCutoff] {number} The cutoff year for determining the century. - @property [dayNamesShort] {string[]} Abbreviated names of the days from Sunday. - @property [dayNames] {string[]} Names of the days from Sunday. - @property [monthNamesShort] {string[]} Abbreviated names of the months. - @property [monthNames] {string[]} Names of the months. - @return {CDate} The extracted date value or null if value is blank. - @throws Errors if the format and/or value are missing, - if the value doesn't match the format, or if the date is invalid. */ - parseDate: function(format, value, settings) { - if (value == null) { - throw main.local.invalidArguments || main.regionalOptions[''].invalidArguments; - } - value = (typeof value === 'object' ? value.toString() : value + ''); - if (value === '') { - return null; - } - format = format || this.local.dateFormat; - settings = settings || {}; - var shortYearCutoff = settings.shortYearCutoff || this.shortYearCutoff; - shortYearCutoff = (typeof shortYearCutoff !== 'string' ? shortYearCutoff : - this.today().year() % 100 + parseInt(shortYearCutoff, 10)); - var dayNamesShort = settings.dayNamesShort || this.local.dayNamesShort; - var dayNames = settings.dayNames || this.local.dayNames; - var parseMonth = settings.parseMonth || this.local.parseMonth; - var monthNumbers = settings.monthNumbers || this.local.monthNumbers; - var monthNamesShort = settings.monthNamesShort || this.local.monthNamesShort; - var monthNames = settings.monthNames || this.local.monthNames; - var jd = -1; - var year = -1; - var month = -1; - var day = -1; - var doy = -1; - var shortYear = false; - var literal = false; - // Check whether a format character is doubled - var doubled = function(match, step) { - var matches = 1; - while (iFormat + matches < format.length && format.charAt(iFormat + matches) === match) { - matches++; - } - iFormat += matches - 1; - return Math.floor(matches / (step || 1)) > 1; - }; - // Extract a number from the string value - var getNumber = function(match, step) { - var isDoubled = doubled(match, step); - var size = [2, 3, isDoubled ? 4 : 2, isDoubled ? 4 : 2, 10, 11, 20]['oyYJ@!'.indexOf(match) + 1]; - var digits = new RegExp('^-?\\d{1,' + size + '}'); - var num = value.substring(iValue).match(digits); - if (!num) { - throw (main.local.missingNumberAt || main.regionalOptions[''].missingNumberAt). - replace(/\{0\}/, iValue); - } - iValue += num[0].length; - return parseInt(num[0], 10); - }; - // Extract a month number from the string value - var calendar = this; - var getMonthNumber = function() { - if (typeof monthNumbers === 'function') { - doubled('m'); // update iFormat - var month = monthNumbers.call(calendar, value.substring(iValue)); - iValue += month.length; - return month; - } - - return getNumber('m'); - }; - // Extract a name from the string value and convert to an index - var getName = function(match, shortNames, longNames, step) { - var names = (doubled(match, step) ? longNames : shortNames); - for (var i = 0; i < names.length; i++) { - if (value.substr(iValue, names[i].length).toLowerCase() === names[i].toLowerCase()) { - iValue += names[i].length; - return i + calendar.minMonth; - } - } - throw (main.local.unknownNameAt || main.regionalOptions[''].unknownNameAt). - replace(/\{0\}/, iValue); - }; - // Extract a month number from the string value - var getMonthName = function() { - if (typeof monthNames === 'function') { - var month = doubled('M') ? - monthNames.call(calendar, value.substring(iValue)) : - monthNamesShort.call(calendar, value.substring(iValue)); - iValue += month.length; - return month; - } - - return getName('M', monthNamesShort, monthNames); - }; - // Confirm that a literal character matches the string value - var checkLiteral = function() { - if (value.charAt(iValue) !== format.charAt(iFormat)) { - throw (main.local.unexpectedLiteralAt || - main.regionalOptions[''].unexpectedLiteralAt).replace(/\{0\}/, iValue); - } - iValue++; - }; - var iValue = 0; - for (var iFormat = 0; iFormat < format.length; iFormat++) { - if (literal) { - if (format.charAt(iFormat) === "'" && !doubled("'")) { - literal = false; - } - else { - checkLiteral(); - } - } - else { - switch (format.charAt(iFormat)) { - case 'd': day = getNumber('d'); break; - case 'D': getName('D', dayNamesShort, dayNames); break; - case 'o': doy = getNumber('o'); break; - case 'w': getNumber('w'); break; - case 'm': month = getMonthNumber(); break; - case 'M': month = getMonthName(); break; - case 'y': - var iSave = iFormat; - shortYear = !doubled('y', 2); - iFormat = iSave; - year = getNumber('y', 2); - break; - case 'Y': year = getNumber('Y', 2); break; - case 'J': - jd = getNumber('J') + 0.5; - if (value.charAt(iValue) === '.') { - iValue++; - getNumber('J'); - } - break; - case '@': jd = getNumber('@') / this.SECS_PER_DAY + this.UNIX_EPOCH; break; - case '!': jd = getNumber('!') / this.TICKS_PER_DAY + this.TICKS_EPOCH; break; - case '*': iValue = value.length; break; - case "'": - if (doubled("'")) { - checkLiteral(); - } - else { - literal = true; - } - break; - default: checkLiteral(); - } - } - } - if (iValue < value.length) { - throw main.local.unexpectedText || main.regionalOptions[''].unexpectedText; - } - if (year === -1) { - year = this.today().year(); - } - else if (year < 100 && shortYear) { - year += (shortYearCutoff === -1 ? 1900 : this.today().year() - - this.today().year() % 100 - (year <= shortYearCutoff ? 0 : 100)); - } - if (typeof month === 'string') { - month = parseMonth.call(this, year, month); - } - if (doy > -1) { - month = 1; - day = doy; - for (var dim = this.daysInMonth(year, month); day > dim; dim = this.daysInMonth(year, month)) { - month++; - day -= dim; - } - } - return (jd > -1 ? this.fromJD(jd) : this.newDate(year, month, day)); - }, - - /** A date may be specified as an exact value or a relative one. - Found in the jquery.calendars.plus.js module. - @memberof BaseCalendar - @param dateSpec {CDate|number|string} The date as an object or string in the given format or - an offset - numeric days from today, or string amounts and periods, e.g. '+1m +2w'. - @param defaultDate {CDate} The date to use if no other supplied, may be null. - @param currentDate {CDate} The current date as a possible basis for relative dates, - if null today is used (optional) - @param [dateFormat] {string} The expected date format - see formatDate. - @param [settings] {object} Additional options whose attributes include: - @property [shortYearCutoff] {number} The cutoff year for determining the century. - @property [dayNamesShort] {string[]} Abbreviated names of the days from Sunday. - @property [dayNames] {string[]} Names of the days from Sunday. - @property [monthNamesShort] {string[]} Abbreviated names of the months. - @property [monthNames] {string[]} Names of the months. - @return {CDate} The decoded date. */ - determineDate: function(dateSpec, defaultDate, currentDate, dateFormat, settings) { - if (currentDate && typeof currentDate !== 'object') { - settings = dateFormat; - dateFormat = currentDate; - currentDate = null; - } - if (typeof dateFormat !== 'string') { - settings = dateFormat; - dateFormat = ''; - } - var calendar = this; - var offsetString = function(offset) { - try { - return calendar.parseDate(dateFormat, offset, settings); - } - catch (e) { - // Ignore - } - offset = offset.toLowerCase(); - var date = (offset.match(/^c/) && currentDate ? - currentDate.newDate() : null) || calendar.today(); - var pattern = /([+-]?[0-9]+)\s*(d|w|m|y)?/g; - var matches = pattern.exec(offset); - while (matches) { - date.add(parseInt(matches[1], 10), matches[2] || 'd'); - matches = pattern.exec(offset); - } - return date; - }; - defaultDate = (defaultDate ? defaultDate.newDate() : null); - dateSpec = (dateSpec == null ? defaultDate : - (typeof dateSpec === 'string' ? offsetString(dateSpec) : (typeof dateSpec === 'number' ? - (isNaN(dateSpec) || dateSpec === Infinity || dateSpec === -Infinity ? defaultDate : - calendar.today().add(dateSpec, 'd')) : calendar.newDate(dateSpec)))); - return dateSpec; - } -}); - - -},{"./main":571,"object-assign":454}],573:[function(_dereq_,module,exports){ -module.exports = _dereq_('cwise-compiler')({ - args: ['array', { - offset: [1], - array: 0 - }, 'scalar', 'scalar', 'index'], - pre: { - "body": "{}", - "args": [], - "thisVars": [], - "localVars": [] - }, - post: { - "body": "{}", - "args": [], - "thisVars": [], - "localVars": [] - }, - body: { - "body": "{\n var _inline_1_da = _inline_1_arg0_ - _inline_1_arg3_\n var _inline_1_db = _inline_1_arg1_ - _inline_1_arg3_\n if((_inline_1_da >= 0) !== (_inline_1_db >= 0)) {\n _inline_1_arg2_.push(_inline_1_arg4_[0] + 0.5 + 0.5 * (_inline_1_da + _inline_1_db) / (_inline_1_da - _inline_1_db))\n }\n }", - "args": [{ - "name": "_inline_1_arg0_", - "lvalue": false, - "rvalue": true, - "count": 1 - }, { - "name": "_inline_1_arg1_", - "lvalue": false, - "rvalue": true, - "count": 1 - }, { - "name": "_inline_1_arg2_", - "lvalue": false, - "rvalue": true, - "count": 1 - }, { - "name": "_inline_1_arg3_", - "lvalue": false, - "rvalue": true, - "count": 2 - }, { - "name": "_inline_1_arg4_", - "lvalue": false, - "rvalue": true, - "count": 1 - }], - "thisVars": [], - "localVars": ["_inline_1_da", "_inline_1_db"] - }, - funcName: 'zeroCrossings' -}) - -},{"cwise-compiler":146}],574:[function(_dereq_,module,exports){ -"use strict" - -module.exports = findZeroCrossings - -var core = _dereq_("./lib/zc-core") - -function findZeroCrossings(array, level) { - var cross = [] - level = +level || 0.0 - core(array.hi(array.shape[0]-1), cross, level) - return cross -} -},{"./lib/zc-core":573}],575:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** - * All paths are tuned for maximum scalability of the arrowhead, - * ie throughout arrowwidth=0.3..3 the head is joined smoothly - * to the line, with the line coming from the left and ending at (0, 0). - * - * `backoff` is the distance to move the arrowhead and the end of the line, - * in order that the arrowhead points to the desired place, either at - * the tip of the arrow or (in the case of circle or square) - * the center of the symbol. - * - * `noRotate`, if truthy, says that this arrowhead should not rotate with the - * arrow. That's the case for squares, which should always be straight, and - * circles, for which it's irrelevant. - */ - -module.exports = [ - // no arrow - { - path: '', - backoff: 0 - }, - // wide with flat back - { - path: 'M-2.4,-3V3L0.6,0Z', - backoff: 0.6 - }, - // narrower with flat back - { - path: 'M-3.7,-2.5V2.5L1.3,0Z', - backoff: 1.3 - }, - // barbed - { - path: 'M-4.45,-3L-1.65,-0.2V0.2L-4.45,3L1.55,0Z', - backoff: 1.55 - }, - // wide line-drawn - { - path: 'M-2.2,-2.2L-0.2,-0.2V0.2L-2.2,2.2L-1.4,3L1.6,0L-1.4,-3Z', - backoff: 1.6 - }, - // narrower line-drawn - { - path: 'M-4.4,-2.1L-0.6,-0.2V0.2L-4.4,2.1L-4,3L2,0L-4,-3Z', - backoff: 2 - }, - // circle - { - path: 'M2,0A2,2 0 1,1 0,-2A2,2 0 0,1 2,0Z', - backoff: 0, - noRotate: true - }, - // square - { - path: 'M2,2V-2H-2V2Z', - backoff: 0, - noRotate: true - } -]; - -},{}],576:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var ARROWPATHS = _dereq_('./arrow_paths'); -var fontAttrs = _dereq_('../../plots/font_attributes'); -var cartesianConstants = _dereq_('../../plots/cartesian/constants'); -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - - -module.exports = templatedArray('annotation', { - visible: { - valType: 'boolean', - - dflt: true, - editType: 'calc+arraydraw', - - }, - - text: { - valType: 'string', - - editType: 'calc+arraydraw', - - }, - textangle: { - valType: 'angle', - dflt: 0, - - editType: 'calc+arraydraw', - - }, - font: fontAttrs({ - editType: 'calc+arraydraw', - colorEditType: 'arraydraw', - - }), - width: { - valType: 'number', - min: 1, - dflt: null, - - editType: 'calc+arraydraw', - - }, - height: { - valType: 'number', - min: 1, - dflt: null, - - editType: 'calc+arraydraw', - - }, - opacity: { - valType: 'number', - min: 0, - max: 1, - dflt: 1, - - editType: 'arraydraw', - - }, - align: { - valType: 'enumerated', - values: ['left', 'center', 'right'], - dflt: 'center', - - editType: 'arraydraw', - - }, - valign: { - valType: 'enumerated', - values: ['top', 'middle', 'bottom'], - dflt: 'middle', - - editType: 'arraydraw', - - }, - bgcolor: { - valType: 'color', - dflt: 'rgba(0,0,0,0)', - - editType: 'arraydraw', - - }, - bordercolor: { - valType: 'color', - dflt: 'rgba(0,0,0,0)', - - editType: 'arraydraw', - - }, - borderpad: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'calc+arraydraw', - - }, - borderwidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'calc+arraydraw', - - }, - // arrow - showarrow: { - valType: 'boolean', - dflt: true, - - editType: 'calc+arraydraw', - - }, - arrowcolor: { - valType: 'color', - - editType: 'arraydraw', - - }, - arrowhead: { - valType: 'integer', - min: 0, - max: ARROWPATHS.length, - dflt: 1, - - editType: 'arraydraw', - - }, - startarrowhead: { - valType: 'integer', - min: 0, - max: ARROWPATHS.length, - dflt: 1, - - editType: 'arraydraw', - - }, - arrowside: { - valType: 'flaglist', - flags: ['end', 'start'], - extras: ['none'], - dflt: 'end', - - editType: 'arraydraw', - - }, - arrowsize: { - valType: 'number', - min: 0.3, - dflt: 1, - - editType: 'calc+arraydraw', - - }, - startarrowsize: { - valType: 'number', - min: 0.3, - dflt: 1, - - editType: 'calc+arraydraw', - - }, - arrowwidth: { - valType: 'number', - min: 0.1, - - editType: 'calc+arraydraw', - - }, - standoff: { - valType: 'number', - min: 0, - dflt: 0, - - editType: 'calc+arraydraw', - - }, - startstandoff: { - valType: 'number', - min: 0, - dflt: 0, - - editType: 'calc+arraydraw', - - }, - ax: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - ay: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - axref: { - valType: 'enumerated', - dflt: 'pixel', - values: [ - 'pixel', - cartesianConstants.idRegex.x.toString() - ], - - editType: 'calc', - - }, - ayref: { - valType: 'enumerated', - dflt: 'pixel', - values: [ - 'pixel', - cartesianConstants.idRegex.y.toString() - ], - - editType: 'calc', - - }, - // positioning - xref: { - valType: 'enumerated', - values: [ - 'paper', - cartesianConstants.idRegex.x.toString() - ], - - editType: 'calc', - - }, - x: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - xanchor: { - valType: 'enumerated', - values: ['auto', 'left', 'center', 'right'], - dflt: 'auto', - - editType: 'calc+arraydraw', - - }, - xshift: { - valType: 'number', - dflt: 0, - - editType: 'calc+arraydraw', - - }, - yref: { - valType: 'enumerated', - values: [ - 'paper', - cartesianConstants.idRegex.y.toString() - ], - - editType: 'calc', - - }, - y: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - yanchor: { - valType: 'enumerated', - values: ['auto', 'top', 'middle', 'bottom'], - dflt: 'auto', - - editType: 'calc+arraydraw', - - }, - yshift: { - valType: 'number', - dflt: 0, - - editType: 'calc+arraydraw', - - }, - clicktoshow: { - valType: 'enumerated', - values: [false, 'onoff', 'onout'], - dflt: false, - - editType: 'arraydraw', - - }, - xclick: { - valType: 'any', - - editType: 'arraydraw', - - }, - yclick: { - valType: 'any', - - editType: 'arraydraw', - - }, - hovertext: { - valType: 'string', - - editType: 'arraydraw', - - }, - hoverlabel: { - bgcolor: { - valType: 'color', - - editType: 'arraydraw', - - }, - bordercolor: { - valType: 'color', - - editType: 'arraydraw', - - }, - font: fontAttrs({ - editType: 'arraydraw', - - }), - editType: 'arraydraw' - }, - captureevents: { - valType: 'boolean', - - editType: 'arraydraw', - - }, - editType: 'calc', - - _deprecated: { - ref: { - valType: 'string', - - editType: 'calc', - - } - } -}); - -},{"../../plot_api/plot_template":757,"../../plots/cartesian/constants":773,"../../plots/font_attributes":793,"./arrow_paths":575}],577:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); - -var draw = _dereq_('./draw').draw; - - -module.exports = function calcAutorange(gd) { - var fullLayout = gd._fullLayout; - var annotationList = Lib.filterVisible(fullLayout.annotations); - - if(annotationList.length && gd._fullData.length) { - return Lib.syncOrAsync([draw, annAutorange], gd); - } -}; - -function annAutorange(gd) { - var fullLayout = gd._fullLayout; - - // find the bounding boxes for each of these annotations' - // relative to their anchor points - // use the arrow and the text bg rectangle, - // as the whole anno may include hidden text in its bbox - Lib.filterVisible(fullLayout.annotations).forEach(function(ann) { - var xa = Axes.getFromId(gd, ann.xref); - var ya = Axes.getFromId(gd, ann.yref); - - ann._extremes = {}; - if(xa) calcAxisExpansion(ann, xa); - if(ya) calcAxisExpansion(ann, ya); - }); -} - -function calcAxisExpansion(ann, ax) { - var axId = ax._id; - var letter = axId.charAt(0); - var pos = ann[letter]; - var apos = ann['a' + letter]; - var ref = ann[letter + 'ref']; - var aref = ann['a' + letter + 'ref']; - var padplus = ann['_' + letter + 'padplus']; - var padminus = ann['_' + letter + 'padminus']; - var shift = {x: 1, y: -1}[letter] * ann[letter + 'shift']; - var headSize = 3 * ann.arrowsize * ann.arrowwidth || 0; - var headPlus = headSize + shift; - var headMinus = headSize - shift; - var startHeadSize = 3 * ann.startarrowsize * ann.arrowwidth || 0; - var startHeadPlus = startHeadSize + shift; - var startHeadMinus = startHeadSize - shift; - var extremes; - - if(aref === ref) { - // expand for the arrowhead (padded by arrowhead) - var extremeArrowHead = Axes.findExtremes(ax, [ax.r2c(pos)], { - ppadplus: headPlus, - ppadminus: headMinus - }); - // again for the textbox (padded by textbox) - var extremeText = Axes.findExtremes(ax, [ax.r2c(apos)], { - ppadplus: Math.max(padplus, startHeadPlus), - ppadminus: Math.max(padminus, startHeadMinus) - }); - extremes = { - min: [extremeArrowHead.min[0], extremeText.min[0]], - max: [extremeArrowHead.max[0], extremeText.max[0]] - }; - } else { - startHeadPlus = apos ? startHeadPlus + apos : startHeadPlus; - startHeadMinus = apos ? startHeadMinus - apos : startHeadMinus; - extremes = Axes.findExtremes(ax, [ax.r2c(pos)], { - ppadplus: Math.max(padplus, headPlus, startHeadPlus), - ppadminus: Math.max(padminus, headMinus, startHeadMinus) - }); - } - - ann._extremes[axId] = extremes; -} - -},{"../../lib":719,"../../plots/cartesian/axes":767,"./draw":582}],578:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); -var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; - -module.exports = { - hasClickToShow: hasClickToShow, - onClick: onClick -}; - -/* - * hasClickToShow: does the given hoverData have ANY annotations which will - * turn ON if we click here? (used by hover events to set cursor) - * - * gd: graphDiv - * hoverData: a hoverData array, as included with the *plotly_hover* or - * *plotly_click* events in the `points` attribute - * - * returns: boolean - */ -function hasClickToShow(gd, hoverData) { - var sets = getToggleSets(gd, hoverData); - return sets.on.length > 0 || sets.explicitOff.length > 0; -} - -/* - * onClick: perform the toggling (via Plotly.update) implied by clicking - * at this hoverData - * - * gd: graphDiv - * hoverData: a hoverData array, as included with the *plotly_hover* or - * *plotly_click* events in the `points` attribute - * - * returns: Promise that the update is complete - */ -function onClick(gd, hoverData) { - var toggleSets = getToggleSets(gd, hoverData); - var onSet = toggleSets.on; - var offSet = toggleSets.off.concat(toggleSets.explicitOff); - var update = {}; - var annotationsOut = gd._fullLayout.annotations; - var i, editHelpers; - - if(!(onSet.length || offSet.length)) return; - - for(i = 0; i < onSet.length; i++) { - editHelpers = arrayEditor(gd.layout, 'annotations', annotationsOut[onSet[i]]); - editHelpers.modifyItem('visible', true); - Lib.extendFlat(update, editHelpers.getUpdateObj()); - } - - for(i = 0; i < offSet.length; i++) { - editHelpers = arrayEditor(gd.layout, 'annotations', annotationsOut[offSet[i]]); - editHelpers.modifyItem('visible', false); - Lib.extendFlat(update, editHelpers.getUpdateObj()); - } - - return Registry.call('update', gd, {}, update); -} - -/* - * getToggleSets: find the annotations which will turn on or off at this - * hoverData - * - * gd: graphDiv - * hoverData: a hoverData array, as included with the *plotly_hover* or - * *plotly_click* events in the `points` attribute - * - * returns: { - * on: Array (indices of annotations to turn on), - * off: Array (indices to turn off because you're not hovering on them), - * explicitOff: Array (indices to turn off because you *are* hovering on them) - * } - */ -function getToggleSets(gd, hoverData) { - var annotations = gd._fullLayout.annotations; - var onSet = []; - var offSet = []; - var explicitOffSet = []; - var hoverLen = (hoverData || []).length; - - var i, j, anni, showMode, pointj, xa, ya, toggleType; - - for(i = 0; i < annotations.length; i++) { - anni = annotations[i]; - showMode = anni.clicktoshow; - - if(showMode) { - for(j = 0; j < hoverLen; j++) { - pointj = hoverData[j]; - xa = pointj.xaxis; - ya = pointj.yaxis; - - if(xa._id === anni.xref && - ya._id === anni.yref && - xa.d2r(pointj.x) === clickData2r(anni._xclick, xa) && - ya.d2r(pointj.y) === clickData2r(anni._yclick, ya) - ) { - // match! toggle this annotation - // regardless of its clicktoshow mode - // but if it's onout mode, off is implicit - if(anni.visible) { - if(showMode === 'onout') toggleType = offSet; - else toggleType = explicitOffSet; - } else { - toggleType = onSet; - } - toggleType.push(i); - break; - } - } - - if(j === hoverLen) { - // no match - only turn this annotation OFF, and only if - // showmode is 'onout' - if(anni.visible && showMode === 'onout') offSet.push(i); - } - } - } - - return {on: onSet, off: offSet, explicitOff: explicitOffSet}; -} - -// to handle log axes until v2 -function clickData2r(d, ax) { - return ax.type === 'log' ? ax.l2r(d) : ax.d2r(d); -} - -},{"../../lib":719,"../../plot_api/plot_template":757,"../../registry":847}],579:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../color'); - -// defaults common to 'annotations' and 'annotations3d' -module.exports = function handleAnnotationCommonDefaults(annIn, annOut, fullLayout, coerce) { - coerce('opacity'); - var bgColor = coerce('bgcolor'); - - var borderColor = coerce('bordercolor'); - var borderOpacity = Color.opacity(borderColor); - - coerce('borderpad'); - - var borderWidth = coerce('borderwidth'); - var showArrow = coerce('showarrow'); - - coerce('text', showArrow ? ' ' : fullLayout._dfltTitle.annotation); - coerce('textangle'); - Lib.coerceFont(coerce, 'font', fullLayout.font); - - coerce('width'); - coerce('align'); - - var h = coerce('height'); - if(h) coerce('valign'); - - if(showArrow) { - var arrowside = coerce('arrowside'); - var arrowhead; - var arrowsize; - - if(arrowside.indexOf('end') !== -1) { - arrowhead = coerce('arrowhead'); - arrowsize = coerce('arrowsize'); - } - - if(arrowside.indexOf('start') !== -1) { - coerce('startarrowhead', arrowhead); - coerce('startarrowsize', arrowsize); - } - coerce('arrowcolor', borderOpacity ? annOut.bordercolor : Color.defaultLine); - coerce('arrowwidth', ((borderOpacity && borderWidth) || 1) * 2); - coerce('standoff'); - coerce('startstandoff'); - } - - var hoverText = coerce('hovertext'); - var globalHoverLabel = fullLayout.hoverlabel || {}; - - if(hoverText) { - var hoverBG = coerce('hoverlabel.bgcolor', globalHoverLabel.bgcolor || - (Color.opacity(bgColor) ? Color.rgb(bgColor) : Color.defaultLine) - ); - - var hoverBorder = coerce('hoverlabel.bordercolor', globalHoverLabel.bordercolor || - Color.contrast(hoverBG) - ); - - Lib.coerceFont(coerce, 'hoverlabel.font', { - family: globalHoverLabel.font.family, - size: globalHoverLabel.font.size, - color: globalHoverLabel.font.color || hoverBorder - }); - } - - coerce('captureevents', !!hoverText); -}; - -},{"../../lib":719,"../color":593}],580:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var toLogRange = _dereq_('../../lib/to_log_range'); - -/* - * convertCoords: when converting an axis between log and linear - * you need to alter any annotations on that axis to keep them - * pointing at the same data point. - * In v2.0 this will become obsolete - * - * gd: the plot div - * ax: the axis being changed - * newType: the type it's getting - * doExtra: function(attr, val) from inside relayout that sets the attribute. - * Use this to make the changes as it's aware if any other changes in the - * same relayout call should override this conversion. - */ -module.exports = function convertCoords(gd, ax, newType, doExtra) { - ax = ax || {}; - - var toLog = (newType === 'log') && (ax.type === 'linear'); - var fromLog = (newType === 'linear') && (ax.type === 'log'); - - if(!(toLog || fromLog)) return; - - var annotations = gd._fullLayout.annotations; - var axLetter = ax._id.charAt(0); - var ann; - var attrPrefix; - - function convert(attr) { - var currentVal = ann[attr]; - var newVal = null; - - if(toLog) newVal = toLogRange(currentVal, ax.range); - else newVal = Math.pow(10, currentVal); - - // if conversion failed, delete the value so it gets a default value - if(!isNumeric(newVal)) newVal = null; - - doExtra(attrPrefix + attr, newVal); - } - - for(var i = 0; i < annotations.length; i++) { - ann = annotations[i]; - attrPrefix = 'annotations[' + i + '].'; - - if(ann[axLetter + 'ref'] === ax._id) convert(axLetter); - if(ann['a' + axLetter + 'ref'] === ax._id) convert('a' + axLetter); - } -}; - -},{"../../lib/to_log_range":745,"fast-isnumeric":225}],581:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); - -var handleAnnotationCommonDefaults = _dereq_('./common_defaults'); -var attributes = _dereq_('./attributes'); - - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { - handleArrayContainerDefaults(layoutIn, layoutOut, { - name: 'annotations', - handleItemDefaults: handleAnnotationDefaults - }); -}; - -function handleAnnotationDefaults(annIn, annOut, fullLayout) { - function coerce(attr, dflt) { - return Lib.coerce(annIn, annOut, attributes, attr, dflt); - } - - var visible = coerce('visible'); - var clickToShow = coerce('clicktoshow'); - - if(!(visible || clickToShow)) return; - - handleAnnotationCommonDefaults(annIn, annOut, fullLayout, coerce); - - var showArrow = annOut.showarrow; - - // positioning - var axLetters = ['x', 'y']; - var arrowPosDflt = [-10, -30]; - var gdMock = {_fullLayout: fullLayout}; - - for(var i = 0; i < 2; i++) { - var axLetter = axLetters[i]; - - // xref, yref - var axRef = Axes.coerceRef(annIn, annOut, gdMock, axLetter, '', 'paper'); - - if(axRef !== 'paper') { - var ax = Axes.getFromId(gdMock, axRef); - ax._annIndices.push(annOut._index); - } - - // x, y - Axes.coercePosition(annOut, gdMock, coerce, axRef, axLetter, 0.5); - - if(showArrow) { - var arrowPosAttr = 'a' + axLetter; - // axref, ayref - var aaxRef = Axes.coerceRef(annIn, annOut, gdMock, arrowPosAttr, 'pixel'); - - // for now the arrow can only be on the same axis or specified as pixels - // TODO: sometime it might be interesting to allow it to be on *any* axis - // but that would require updates to drawing & autorange code and maybe more - if(aaxRef !== 'pixel' && aaxRef !== axRef) { - aaxRef = annOut[arrowPosAttr] = 'pixel'; - } - - // ax, ay - var aDflt = (aaxRef === 'pixel') ? arrowPosDflt[i] : 0.4; - Axes.coercePosition(annOut, gdMock, coerce, aaxRef, arrowPosAttr, aDflt); - } - - // xanchor, yanchor - coerce(axLetter + 'anchor'); - - // xshift, yshift - coerce(axLetter + 'shift'); - } - - // if you have one coordinate you should have both - Lib.noneOrAll(annIn, annOut, ['x', 'y']); - - // if you have one part of arrow length you should have both - if(showArrow) { - Lib.noneOrAll(annIn, annOut, ['ax', 'ay']); - } - - if(clickToShow) { - var xClick = coerce('xclick'); - var yClick = coerce('yclick'); - - // put the actual click data to bind to into private attributes - // so we don't have to do this little bit of logic on every hover event - annOut._xclick = (xClick === undefined) ? - annOut.x : - Axes.cleanPosition(xClick, gdMock, annOut.xref); - annOut._yclick = (yClick === undefined) ? - annOut.y : - Axes.cleanPosition(yClick, gdMock, annOut.yref); - } -} - -},{"../../lib":719,"../../plots/array_container_defaults":763,"../../plots/cartesian/axes":767,"./attributes":576,"./common_defaults":579}],582:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Registry = _dereq_('../../registry'); -var Plots = _dereq_('../../plots/plots'); -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var Color = _dereq_('../color'); -var Drawing = _dereq_('../drawing'); -var Fx = _dereq_('../fx'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var setCursor = _dereq_('../../lib/setcursor'); -var dragElement = _dereq_('../dragelement'); -var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; - -var drawArrowHead = _dereq_('./draw_arrow_head'); - -// Annotations are stored in gd.layout.annotations, an array of objects -// index can point to one item in this array, -// or non-numeric to simply add a new one -// or -1 to modify all existing -// opt can be the full options object, or one key (to be set to value) -// or undefined to simply redraw -// if opt is blank, val can be 'add' or a full options object to add a new -// annotation at that point in the array, or 'remove' to delete this one - -module.exports = { - draw: draw, - drawOne: drawOne, - drawRaw: drawRaw -}; - -/* - * draw: draw all annotations without any new modifications - */ -function draw(gd) { - var fullLayout = gd._fullLayout; - - fullLayout._infolayer.selectAll('.annotation').remove(); - - for(var i = 0; i < fullLayout.annotations.length; i++) { - if(fullLayout.annotations[i].visible) { - drawOne(gd, i); - } - } - - return Plots.previousPromises(gd); -} - -/* - * drawOne: draw a single cartesian or paper-ref annotation, potentially with modifications - * - * index (int): the annotation to draw - */ -function drawOne(gd, index) { - var fullLayout = gd._fullLayout; - var options = fullLayout.annotations[index] || {}; - var xa = Axes.getFromId(gd, options.xref); - var ya = Axes.getFromId(gd, options.yref); - - if(xa) xa.setScale(); - if(ya) ya.setScale(); - - drawRaw(gd, options, index, false, xa, ya); -} - -/** - * drawRaw: draw a single annotation, potentially with modifications - * - * @param {DOM element} gd - * @param {object} options : this annotation's fullLayout options - * @param {integer} index : index in 'annotations' container of the annotation to draw - * @param {string} subplotId : id of the annotation's subplot - * - use false for 2d (i.e. cartesian or paper-ref) annotations - * @param {object | undefined} xa : full x-axis object to compute subplot pos-to-px - * @param {object | undefined} ya : ... y-axis - */ -function drawRaw(gd, options, index, subplotId, xa, ya) { - var fullLayout = gd._fullLayout; - var gs = gd._fullLayout._size; - var edits = gd._context.edits; - - var className, containerStr; - - if(subplotId) { - className = 'annotation-' + subplotId; - containerStr = subplotId + '.annotations'; - } else { - className = 'annotation'; - containerStr = 'annotations'; - } - - var editHelpers = arrayEditor(gd.layout, containerStr, options); - var modifyBase = editHelpers.modifyBase; - var modifyItem = editHelpers.modifyItem; - var getUpdateObj = editHelpers.getUpdateObj; - - // remove the existing annotation if there is one - fullLayout._infolayer - .selectAll('.' + className + '[data-index="' + index + '"]') - .remove(); - - var annClipID = 'clip' + fullLayout._uid + '_ann' + index; - - // this annotation is gone - quit now after deleting it - // TODO: use d3 idioms instead of deleting and redrawing every time - if(!options._input || options.visible === false) { - d3.selectAll('#' + annClipID).remove(); - return; - } - - // calculated pixel positions - // x & y each will get text, head, and tail as appropriate - var annPosPx = {x: {}, y: {}}; - var textangle = +options.textangle || 0; - - // create the components - // made a single group to contain all, so opacity can work right - // with border/arrow together this could handle a whole bunch of - // cleanup at this point, but works for now - var annGroup = fullLayout._infolayer.append('g') - .classed(className, true) - .attr('data-index', String(index)) - .style('opacity', options.opacity); - - // another group for text+background so that they can rotate together - var annTextGroup = annGroup.append('g') - .classed('annotation-text-g', true); - - var editTextPosition = edits[options.showarrow ? 'annotationTail' : 'annotationPosition']; - var textEvents = options.captureevents || edits.annotationText || editTextPosition; - - function makeEventData(initialEvent) { - var eventData = { - index: index, - annotation: options._input, - fullAnnotation: options, - event: initialEvent - }; - if(subplotId) { - eventData.subplotId = subplotId; - } - return eventData; - } - - var annTextGroupInner = annTextGroup.append('g') - .style('pointer-events', textEvents ? 'all' : null) - .call(setCursor, 'pointer') - .on('click', function() { - gd._dragging = false; - gd.emit('plotly_clickannotation', makeEventData(d3.event)); - }); - - if(options.hovertext) { - annTextGroupInner - .on('mouseover', function() { - var hoverOptions = options.hoverlabel; - var hoverFont = hoverOptions.font; - var bBox = this.getBoundingClientRect(); - var bBoxRef = gd.getBoundingClientRect(); - - Fx.loneHover({ - x0: bBox.left - bBoxRef.left, - x1: bBox.right - bBoxRef.left, - y: (bBox.top + bBox.bottom) / 2 - bBoxRef.top, - text: options.hovertext, - color: hoverOptions.bgcolor, - borderColor: hoverOptions.bordercolor, - fontFamily: hoverFont.family, - fontSize: hoverFont.size, - fontColor: hoverFont.color - }, { - container: fullLayout._hoverlayer.node(), - outerContainer: fullLayout._paper.node(), - gd: gd - }); - }) - .on('mouseout', function() { - Fx.loneUnhover(fullLayout._hoverlayer.node()); - }); - } - - var borderwidth = options.borderwidth; - var borderpad = options.borderpad; - var borderfull = borderwidth + borderpad; - - var annTextBG = annTextGroupInner.append('rect') - .attr('class', 'bg') - .style('stroke-width', borderwidth + 'px') - .call(Color.stroke, options.bordercolor) - .call(Color.fill, options.bgcolor); - - var isSizeConstrained = options.width || options.height; - - var annTextClip = fullLayout._topclips - .selectAll('#' + annClipID) - .data(isSizeConstrained ? [0] : []); - - annTextClip.enter().append('clipPath') - .classed('annclip', true) - .attr('id', annClipID) - .append('rect'); - annTextClip.exit().remove(); - - var font = options.font; - - var text = fullLayout._meta ? - Lib.templateString(options.text, fullLayout._meta) : - options.text; - - var annText = annTextGroupInner.append('text') - .classed('annotation-text', true) - .text(text); - - function textLayout(s) { - s.call(Drawing.font, font) - .attr({ - 'text-anchor': { - left: 'start', - right: 'end' - }[options.align] || 'middle' - }); - - svgTextUtils.convertToTspans(s, gd, drawGraphicalElements); - return s; - } - - function drawGraphicalElements() { - // if the text has *only* a link, make the whole box into a link - var anchor3 = annText.selectAll('a'); - if(anchor3.size() === 1 && anchor3.text() === annText.text()) { - var wholeLink = annTextGroupInner.insert('a', ':first-child').attr({ - 'xlink:xlink:href': anchor3.attr('xlink:href'), - 'xlink:xlink:show': anchor3.attr('xlink:show') - }) - .style({cursor: 'pointer'}); - - wholeLink.node().appendChild(annTextBG.node()); - } - - var mathjaxGroup = annTextGroupInner.select('.annotation-text-math-group'); - var hasMathjax = !mathjaxGroup.empty(); - var anntextBB = Drawing.bBox( - (hasMathjax ? mathjaxGroup : annText).node()); - var textWidth = anntextBB.width; - var textHeight = anntextBB.height; - var annWidth = options.width || textWidth; - var annHeight = options.height || textHeight; - var outerWidth = Math.round(annWidth + 2 * borderfull); - var outerHeight = Math.round(annHeight + 2 * borderfull); - - function shiftFraction(v, anchor) { - if(anchor === 'auto') { - if(v < 1 / 3) anchor = 'left'; - else if(v > 2 / 3) anchor = 'right'; - else anchor = 'center'; - } - return { - center: 0, - middle: 0, - left: 0.5, - bottom: -0.5, - right: -0.5, - top: 0.5 - }[anchor]; - } - - var annotationIsOffscreen = false; - var letters = ['x', 'y']; - - for(var i = 0; i < letters.length; i++) { - var axLetter = letters[i]; - var axRef = options[axLetter + 'ref'] || axLetter; - var tailRef = options['a' + axLetter + 'ref']; - var ax = {x: xa, y: ya}[axLetter]; - var dimAngle = (textangle + (axLetter === 'x' ? 0 : -90)) * Math.PI / 180; - // note that these two can be either positive or negative - var annSizeFromWidth = outerWidth * Math.cos(dimAngle); - var annSizeFromHeight = outerHeight * Math.sin(dimAngle); - // but this one is the positive total size - var annSize = Math.abs(annSizeFromWidth) + Math.abs(annSizeFromHeight); - var anchor = options[axLetter + 'anchor']; - var overallShift = options[axLetter + 'shift'] * (axLetter === 'x' ? 1 : -1); - var posPx = annPosPx[axLetter]; - var basePx; - var textPadShift; - var alignPosition; - var autoAlignFraction; - var textShift; - - /* - * calculate the *primary* pixel position - * which is the arrowhead if there is one, - * otherwise the text anchor point - */ - if(ax) { - // check if annotation is off screen, to bypass DOM manipulations - var posFraction = ax.r2fraction(options[axLetter]); - if(posFraction < 0 || posFraction > 1) { - if(tailRef === axRef) { - posFraction = ax.r2fraction(options['a' + axLetter]); - if(posFraction < 0 || posFraction > 1) { - annotationIsOffscreen = true; - } - } else { - annotationIsOffscreen = true; - } - } - basePx = ax._offset + ax.r2p(options[axLetter]); - autoAlignFraction = 0.5; - } else { - if(axLetter === 'x') { - alignPosition = options[axLetter]; - basePx = gs.l + gs.w * alignPosition; - } else { - alignPosition = 1 - options[axLetter]; - basePx = gs.t + gs.h * alignPosition; - } - autoAlignFraction = options.showarrow ? 0.5 : alignPosition; - } - - // now translate this into pixel positions of head, tail, and text - // as well as paddings for autorange - if(options.showarrow) { - posPx.head = basePx; - - var arrowLength = options['a' + axLetter]; - - // with an arrow, the text rotates around the anchor point - textShift = annSizeFromWidth * shiftFraction(0.5, options.xanchor) - - annSizeFromHeight * shiftFraction(0.5, options.yanchor); - - if(tailRef === axRef) { - posPx.tail = ax._offset + ax.r2p(arrowLength); - // tail is data-referenced: autorange pads the text in px from the tail - textPadShift = textShift; - } else { - posPx.tail = basePx + arrowLength; - // tail is specified in px from head, so autorange also pads vs head - textPadShift = textShift + arrowLength; - } - - posPx.text = posPx.tail + textShift; - - // constrain pixel/paper referenced so the draggers are at least - // partially visible - var maxPx = fullLayout[(axLetter === 'x') ? 'width' : 'height']; - if(axRef === 'paper') { - posPx.head = Lib.constrain(posPx.head, 1, maxPx - 1); - } - if(tailRef === 'pixel') { - var shiftPlus = -Math.max(posPx.tail - 3, posPx.text); - var shiftMinus = Math.min(posPx.tail + 3, posPx.text) - maxPx; - if(shiftPlus > 0) { - posPx.tail += shiftPlus; - posPx.text += shiftPlus; - } else if(shiftMinus > 0) { - posPx.tail -= shiftMinus; - posPx.text -= shiftMinus; - } - } - - posPx.tail += overallShift; - posPx.head += overallShift; - } else { - // with no arrow, the text rotates and *then* we put the anchor - // relative to the new bounding box - textShift = annSize * shiftFraction(autoAlignFraction, anchor); - textPadShift = textShift; - posPx.text = basePx + textShift; - } - - posPx.text += overallShift; - textShift += overallShift; - textPadShift += overallShift; - - // padplus/minus are used by autorange - options['_' + axLetter + 'padplus'] = (annSize / 2) + textPadShift; - options['_' + axLetter + 'padminus'] = (annSize / 2) - textPadShift; - - // size/shift are used during dragging - options['_' + axLetter + 'size'] = annSize; - options['_' + axLetter + 'shift'] = textShift; - } - - // We have everything we need for calcAutorange at this point, - // we can safely exit - unless we're currently dragging the plot - if(!gd._dragging && annotationIsOffscreen) { - annTextGroupInner.remove(); - return; - } - - var xShift = 0; - var yShift = 0; - - if(options.align !== 'left') { - xShift = (annWidth - textWidth) * (options.align === 'center' ? 0.5 : 1); - } - if(options.valign !== 'top') { - yShift = (annHeight - textHeight) * (options.valign === 'middle' ? 0.5 : 1); - } - - if(hasMathjax) { - mathjaxGroup.select('svg').attr({ - x: borderfull + xShift - 1, - y: borderfull + yShift - }) - .call(Drawing.setClipUrl, isSizeConstrained ? annClipID : null, gd); - } else { - var texty = borderfull + yShift - anntextBB.top; - var textx = borderfull + xShift - anntextBB.left; - - annText.call(svgTextUtils.positionText, textx, texty) - .call(Drawing.setClipUrl, isSizeConstrained ? annClipID : null, gd); - } - - annTextClip.select('rect').call(Drawing.setRect, borderfull, borderfull, - annWidth, annHeight); - - annTextBG.call(Drawing.setRect, borderwidth / 2, borderwidth / 2, - outerWidth - borderwidth, outerHeight - borderwidth); - - annTextGroupInner.call(Drawing.setTranslate, - Math.round(annPosPx.x.text - outerWidth / 2), - Math.round(annPosPx.y.text - outerHeight / 2)); - - /* - * rotate text and background - * we already calculated the text center position *as rotated* - * because we needed that for autoranging anyway, so now whether - * we have an arrow or not, we rotate about the text center. - */ - annTextGroup.attr({transform: 'rotate(' + textangle + ',' + - annPosPx.x.text + ',' + annPosPx.y.text + ')'}); - - /* - * add the arrow - * uses options[arrowwidth,arrowcolor,arrowhead] for styling - * dx and dy are normally zero, but when you are dragging the textbox - * while the head stays put, dx and dy are the pixel offsets - */ - var drawArrow = function(dx, dy) { - annGroup - .selectAll('.annotation-arrow-g') - .remove(); - - var headX = annPosPx.x.head; - var headY = annPosPx.y.head; - var tailX = annPosPx.x.tail + dx; - var tailY = annPosPx.y.tail + dy; - var textX = annPosPx.x.text + dx; - var textY = annPosPx.y.text + dy; - - // find the edge of the text box, where we'll start the arrow: - // create transform matrix to rotate the text box corners - var transform = Lib.rotationXYMatrix(textangle, textX, textY); - var applyTransform = Lib.apply2DTransform(transform); - var applyTransform2 = Lib.apply2DTransform2(transform); - - // calculate and transform bounding box - var width = +annTextBG.attr('width'); - var height = +annTextBG.attr('height'); - var xLeft = textX - 0.5 * width; - var xRight = xLeft + width; - var yTop = textY - 0.5 * height; - var yBottom = yTop + height; - var edges = [ - [xLeft, yTop, xLeft, yBottom], - [xLeft, yBottom, xRight, yBottom], - [xRight, yBottom, xRight, yTop], - [xRight, yTop, xLeft, yTop] - ].map(applyTransform2); - - // Remove the line if it ends inside the box. Use ray - // casting for rotated boxes: see which edges intersect a - // line from the arrowhead to far away and reduce with xor - // to get the parity of the number of intersections. - if(edges.reduce(function(a, x) { - return a ^ - !!Lib.segmentsIntersect(headX, headY, headX + 1e6, headY + 1e6, - x[0], x[1], x[2], x[3]); - }, false)) { - // no line or arrow - so quit drawArrow now - return; - } - - edges.forEach(function(x) { - var p = Lib.segmentsIntersect(tailX, tailY, headX, headY, - x[0], x[1], x[2], x[3]); - if(p) { - tailX = p.x; - tailY = p.y; - } - }); - - var strokewidth = options.arrowwidth; - var arrowColor = options.arrowcolor; - var arrowSide = options.arrowside; - - var arrowGroup = annGroup.append('g') - .style({opacity: Color.opacity(arrowColor)}) - .classed('annotation-arrow-g', true); - - var arrow = arrowGroup.append('path') - .attr('d', 'M' + tailX + ',' + tailY + 'L' + headX + ',' + headY) - .style('stroke-width', strokewidth + 'px') - .call(Color.stroke, Color.rgb(arrowColor)); - - drawArrowHead(arrow, arrowSide, options); - - // the arrow dragger is a small square right at the head, then a line to the tail, - // all expanded by a stroke width of 6px plus the arrow line width - if(edits.annotationPosition && arrow.node().parentNode && !subplotId) { - var arrowDragHeadX = headX; - var arrowDragHeadY = headY; - if(options.standoff) { - var arrowLength = Math.sqrt(Math.pow(headX - tailX, 2) + Math.pow(headY - tailY, 2)); - arrowDragHeadX += options.standoff * (tailX - headX) / arrowLength; - arrowDragHeadY += options.standoff * (tailY - headY) / arrowLength; - } - var arrowDrag = arrowGroup.append('path') - .classed('annotation-arrow', true) - .classed('anndrag', true) - .classed('cursor-move', true) - .attr({ - d: 'M3,3H-3V-3H3ZM0,0L' + (tailX - arrowDragHeadX) + ',' + (tailY - arrowDragHeadY), - transform: 'translate(' + arrowDragHeadX + ',' + arrowDragHeadY + ')' - }) - .style('stroke-width', (strokewidth + 6) + 'px') - .call(Color.stroke, 'rgba(0,0,0,0)') - .call(Color.fill, 'rgba(0,0,0,0)'); - - var annx0, anny0; - - // dragger for the arrow & head: translates the whole thing - // (head/tail/text) all together - dragElement.init({ - element: arrowDrag.node(), - gd: gd, - prepFn: function() { - var pos = Drawing.getTranslate(annTextGroupInner); - - annx0 = pos.x; - anny0 = pos.y; - if(xa && xa.autorange) { - modifyBase(xa._name + '.autorange', true); - } - if(ya && ya.autorange) { - modifyBase(ya._name + '.autorange', true); - } - }, - moveFn: function(dx, dy) { - var annxy0 = applyTransform(annx0, anny0); - var xcenter = annxy0[0] + dx; - var ycenter = annxy0[1] + dy; - annTextGroupInner.call(Drawing.setTranslate, xcenter, ycenter); - - modifyItem('x', xa ? - xa.p2r(xa.r2p(options.x) + dx) : - (options.x + (dx / gs.w))); - modifyItem('y', ya ? - ya.p2r(ya.r2p(options.y) + dy) : - (options.y - (dy / gs.h))); - - if(options.axref === options.xref) { - modifyItem('ax', xa.p2r(xa.r2p(options.ax) + dx)); - } - - if(options.ayref === options.yref) { - modifyItem('ay', ya.p2r(ya.r2p(options.ay) + dy)); - } - - arrowGroup.attr('transform', 'translate(' + dx + ',' + dy + ')'); - annTextGroup.attr({ - transform: 'rotate(' + textangle + ',' + - xcenter + ',' + ycenter + ')' - }); - }, - doneFn: function() { - Registry.call('_guiRelayout', gd, getUpdateObj()); - var notesBox = document.querySelector('.js-notes-box-panel'); - if(notesBox) notesBox.redraw(notesBox.selectedObj); - } - }); - } - }; - - if(options.showarrow) drawArrow(0, 0); - - // user dragging the annotation (text, not arrow) - if(editTextPosition) { - var baseTextTransform; - - // dragger for the textbox: if there's an arrow, just drag the - // textbox and tail, leave the head untouched - dragElement.init({ - element: annTextGroupInner.node(), - gd: gd, - prepFn: function() { - baseTextTransform = annTextGroup.attr('transform'); - }, - moveFn: function(dx, dy) { - var csr = 'pointer'; - if(options.showarrow) { - if(options.axref === options.xref) { - modifyItem('ax', xa.p2r(xa.r2p(options.ax) + dx)); - } else { - modifyItem('ax', options.ax + dx); - } - - if(options.ayref === options.yref) { - modifyItem('ay', ya.p2r(ya.r2p(options.ay) + dy)); - } else { - modifyItem('ay', options.ay + dy); - } - - drawArrow(dx, dy); - } else if(!subplotId) { - var xUpdate, yUpdate; - if(xa) { - xUpdate = xa.p2r(xa.r2p(options.x) + dx); - } else { - var widthFraction = options._xsize / gs.w; - var xLeft = options.x + (options._xshift - options.xshift) / gs.w - widthFraction / 2; - - xUpdate = dragElement.align(xLeft + dx / gs.w, - widthFraction, 0, 1, options.xanchor); - } - - if(ya) { - yUpdate = ya.p2r(ya.r2p(options.y) + dy); - } else { - var heightFraction = options._ysize / gs.h; - var yBottom = options.y - (options._yshift + options.yshift) / gs.h - heightFraction / 2; - - yUpdate = dragElement.align(yBottom - dy / gs.h, - heightFraction, 0, 1, options.yanchor); - } - modifyItem('x', xUpdate); - modifyItem('y', yUpdate); - if(!xa || !ya) { - csr = dragElement.getCursor( - xa ? 0.5 : xUpdate, - ya ? 0.5 : yUpdate, - options.xanchor, options.yanchor - ); - } - } else return; - - annTextGroup.attr({ - transform: 'translate(' + dx + ',' + dy + ')' + baseTextTransform - }); - - setCursor(annTextGroupInner, csr); - }, - clickFn: function(_, initialEvent) { - if(options.captureevents) { - gd.emit('plotly_clickannotation', makeEventData(initialEvent)); - } - }, - doneFn: function() { - setCursor(annTextGroupInner); - Registry.call('_guiRelayout', gd, getUpdateObj()); - var notesBox = document.querySelector('.js-notes-box-panel'); - if(notesBox) notesBox.redraw(notesBox.selectedObj); - } - }); - } - } - - if(edits.annotationText) { - annText.call(svgTextUtils.makeEditable, {delegate: annTextGroupInner, gd: gd}) - .call(textLayout) - .on('edit', function(_text) { - options.text = _text; - - this.call(textLayout); - - modifyItem('text', _text); - - if(xa && xa.autorange) { - modifyBase(xa._name + '.autorange', true); - } - if(ya && ya.autorange) { - modifyBase(ya._name + '.autorange', true); - } - - Registry.call('_guiRelayout', gd, getUpdateObj()); - }); - } else annText.call(textLayout); -} - -},{"../../lib":719,"../../lib/setcursor":739,"../../lib/svg_text_utils":743,"../../plot_api/plot_template":757,"../../plots/cartesian/axes":767,"../../plots/plots":828,"../../registry":847,"../color":593,"../dragelement":611,"../drawing":614,"../fx":632,"./draw_arrow_head":583,"d3":163}],583:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Color = _dereq_('../color'); - -var ARROWPATHS = _dereq_('./arrow_paths'); - -/** - * Add arrowhead(s) to a path or line element - * - * @param {d3.selection} el3: a d3-selected line or path element - * - * @param {string} ends: 'none', 'start', 'end', or 'start+end' for which ends get arrowheads - * - * @param {object} options: style information. Must have all the following: - * @param {number} options.arrowhead: end head style - see ./arrow_paths - * @param {number} options.startarrowhead: start head style - see ./arrow_paths - * @param {number} options.arrowsize: relative size of the end head vs line width - * @param {number} options.startarrowsize: relative size of the start head vs line width - * @param {number} options.standoff: distance in px to move the end arrow point from its target - * @param {number} options.startstandoff: distance in px to move the start arrow point from its target - * @param {number} options.arrowwidth: width of the arrow line - * @param {string} options.arrowcolor: color of the arrow line, for the head to match - * Note that the opacity of this color is ignored, as it's assumed the container - * of both the line and head has opacity applied to it so there isn't greater opacity - * where they overlap. - */ -module.exports = function drawArrowHead(el3, ends, options) { - var el = el3.node(); - var headStyle = ARROWPATHS[options.arrowhead || 0]; - var startHeadStyle = ARROWPATHS[options.startarrowhead || 0]; - var scale = (options.arrowwidth || 1) * (options.arrowsize || 1); - var startScale = (options.arrowwidth || 1) * (options.startarrowsize || 1); - var doStart = ends.indexOf('start') >= 0; - var doEnd = ends.indexOf('end') >= 0; - var backOff = headStyle.backoff * scale + options.standoff; - var startBackOff = startHeadStyle.backoff * startScale + options.startstandoff; - - var start, end, startRot, endRot; - - if(el.nodeName === 'line') { - start = {x: +el3.attr('x1'), y: +el3.attr('y1')}; - end = {x: +el3.attr('x2'), y: +el3.attr('y2')}; - - var dx = start.x - end.x; - var dy = start.y - end.y; - - startRot = Math.atan2(dy, dx); - endRot = startRot + Math.PI; - if(backOff && startBackOff) { - if(backOff + startBackOff > Math.sqrt(dx * dx + dy * dy)) { - hideLine(); - return; - } - } - - if(backOff) { - if(backOff * backOff > dx * dx + dy * dy) { - hideLine(); - return; - } - var backOffX = backOff * Math.cos(startRot); - var backOffY = backOff * Math.sin(startRot); - - end.x += backOffX; - end.y += backOffY; - el3.attr({x2: end.x, y2: end.y}); - } - - if(startBackOff) { - if(startBackOff * startBackOff > dx * dx + dy * dy) { - hideLine(); - return; - } - var startBackOffX = startBackOff * Math.cos(startRot); - var startbackOffY = startBackOff * Math.sin(startRot); - - start.x -= startBackOffX; - start.y -= startbackOffY; - el3.attr({x1: start.x, y1: start.y}); - } - } else if(el.nodeName === 'path') { - var pathlen = el.getTotalLength(); - // using dash to hide the backOff region of the path. - // if we ever allow dash for the arrow we'll have to - // do better than this hack... maybe just manually - // combine the two - var dashArray = ''; - - if(pathlen < backOff + startBackOff) { - hideLine(); - return; - } - - - var start0 = el.getPointAtLength(0); - var dstart = el.getPointAtLength(0.1); - - startRot = Math.atan2(start0.y - dstart.y, start0.x - dstart.x); - start = el.getPointAtLength(Math.min(startBackOff, pathlen)); - - dashArray = '0px,' + startBackOff + 'px,'; - - var end0 = el.getPointAtLength(pathlen); - var dend = el.getPointAtLength(pathlen - 0.1); - - endRot = Math.atan2(end0.y - dend.y, end0.x - dend.x); - end = el.getPointAtLength(Math.max(0, pathlen - backOff)); - - var shortening = dashArray ? startBackOff + backOff : backOff; - dashArray += (pathlen - shortening) + 'px,' + pathlen + 'px'; - - el3.style('stroke-dasharray', dashArray); - } - - function hideLine() { el3.style('stroke-dasharray', '0px,100px'); } - - function drawhead(arrowHeadStyle, p, rot, arrowScale) { - if(!arrowHeadStyle.path) return; - if(arrowHeadStyle.noRotate) rot = 0; - - d3.select(el.parentNode).append('path') - .attr({ - 'class': el3.attr('class'), - d: arrowHeadStyle.path, - transform: - 'translate(' + p.x + ',' + p.y + ')' + - (rot ? 'rotate(' + (rot * 180 / Math.PI) + ')' : '') + - 'scale(' + arrowScale + ')' - }) - .style({ - fill: Color.rgb(options.arrowcolor), - 'stroke-width': 0 - }); - } - - if(doStart) drawhead(startHeadStyle, start, startRot, startScale); - if(doEnd) drawhead(headStyle, end, endRot, scale); -}; - -},{"../color":593,"./arrow_paths":575,"d3":163}],584:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var drawModule = _dereq_('./draw'); -var clickModule = _dereq_('./click'); - -module.exports = { - moduleType: 'component', - name: 'annotations', - - layoutAttributes: _dereq_('./attributes'), - supplyLayoutDefaults: _dereq_('./defaults'), - includeBasePlot: _dereq_('../../plots/cartesian/include_components')('annotations'), - - calcAutorange: _dereq_('./calc_autorange'), - draw: drawModule.draw, - drawOne: drawModule.drawOne, - drawRaw: drawModule.drawRaw, - - hasClickToShow: clickModule.hasClickToShow, - onClick: clickModule.onClick, - - convertCoords: _dereq_('./convert_coords') -}; - -},{"../../plots/cartesian/include_components":777,"./attributes":576,"./calc_autorange":577,"./click":578,"./convert_coords":580,"./defaults":581,"./draw":582}],585:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var annAtts = _dereq_('../annotations/attributes'); -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - -module.exports = overrideAll(templatedArray('annotation', { - visible: annAtts.visible, - x: { - valType: 'any', - - - }, - y: { - valType: 'any', - - - }, - z: { - valType: 'any', - - - }, - ax: { - valType: 'number', - - - }, - ay: { - valType: 'number', - - - }, - - xanchor: annAtts.xanchor, - xshift: annAtts.xshift, - yanchor: annAtts.yanchor, - yshift: annAtts.yshift, - - text: annAtts.text, - textangle: annAtts.textangle, - font: annAtts.font, - width: annAtts.width, - height: annAtts.height, - opacity: annAtts.opacity, - align: annAtts.align, - valign: annAtts.valign, - bgcolor: annAtts.bgcolor, - bordercolor: annAtts.bordercolor, - borderpad: annAtts.borderpad, - borderwidth: annAtts.borderwidth, - showarrow: annAtts.showarrow, - arrowcolor: annAtts.arrowcolor, - arrowhead: annAtts.arrowhead, - startarrowhead: annAtts.startarrowhead, - arrowside: annAtts.arrowside, - arrowsize: annAtts.arrowsize, - startarrowsize: annAtts.startarrowsize, - arrowwidth: annAtts.arrowwidth, - standoff: annAtts.standoff, - startstandoff: annAtts.startstandoff, - hovertext: annAtts.hovertext, - hoverlabel: annAtts.hoverlabel, - captureevents: annAtts.captureevents, - - // maybes later? - // clicktoshow: annAtts.clicktoshow, - // xclick: annAtts.xclick, - // yclick: annAtts.yclick, - - // not needed! - // axref: 'pixel' - // ayref: 'pixel' - // xref: 'x' - // yref: 'y - // zref: 'z' -}), 'calc', 'from-root'); - -},{"../../plot_api/edit_types":750,"../../plot_api/plot_template":757,"../annotations/attributes":576}],586:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); - -module.exports = function convert(scene) { - var fullSceneLayout = scene.fullSceneLayout; - var anns = fullSceneLayout.annotations; - - for(var i = 0; i < anns.length; i++) { - mockAnnAxes(anns[i], scene); - } - - scene.fullLayout._infolayer - .selectAll('.annotation-' + scene.id) - .remove(); -}; - -function mockAnnAxes(ann, scene) { - var fullSceneLayout = scene.fullSceneLayout; - var domain = fullSceneLayout.domain; - var size = scene.fullLayout._size; - - var base = { - // this gets fill in on render - pdata: null, - - // to get setConvert to not execute cleanly - type: 'linear', - - // don't try to update them on `editable: true` - autorange: false, - - // set infinite range so that annotation draw routine - // does not try to remove 'outside-range' annotations, - // this case is handled in the render loop - range: [-Infinity, Infinity] - }; - - ann._xa = {}; - Lib.extendFlat(ann._xa, base); - Axes.setConvert(ann._xa); - ann._xa._offset = size.l + domain.x[0] * size.w; - ann._xa.l2p = function() { - return 0.5 * (1 + ann._pdata[0] / ann._pdata[3]) * size.w * (domain.x[1] - domain.x[0]); - }; - - ann._ya = {}; - Lib.extendFlat(ann._ya, base); - Axes.setConvert(ann._ya); - ann._ya._offset = size.t + (1 - domain.y[1]) * size.h; - ann._ya.l2p = function() { - return 0.5 * (1 - ann._pdata[1] / ann._pdata[3]) * size.h * (domain.y[1] - domain.y[0]); - }; -} - -},{"../../lib":719,"../../plots/cartesian/axes":767}],587:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); -var handleAnnotationCommonDefaults = _dereq_('../annotations/common_defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function handleDefaults(sceneLayoutIn, sceneLayoutOut, opts) { - handleArrayContainerDefaults(sceneLayoutIn, sceneLayoutOut, { - name: 'annotations', - handleItemDefaults: handleAnnotationDefaults, - fullLayout: opts.fullLayout - }); -}; - -function handleAnnotationDefaults(annIn, annOut, sceneLayout, opts) { - function coerce(attr, dflt) { - return Lib.coerce(annIn, annOut, attributes, attr, dflt); - } - - function coercePosition(axLetter) { - var axName = axLetter + 'axis'; - - // mock in such way that getFromId grabs correct 3D axis - var gdMock = { _fullLayout: {} }; - gdMock._fullLayout[axName] = sceneLayout[axName]; - - return Axes.coercePosition(annOut, gdMock, coerce, axLetter, axLetter, 0.5); - } - - - var visible = coerce('visible'); - if(!visible) return; - - handleAnnotationCommonDefaults(annIn, annOut, opts.fullLayout, coerce); - - coercePosition('x'); - coercePosition('y'); - coercePosition('z'); - - // if you have one coordinate you should all three - Lib.noneOrAll(annIn, annOut, ['x', 'y', 'z']); - - // hard-set here for completeness - annOut.xref = 'x'; - annOut.yref = 'y'; - annOut.zref = 'z'; - - coerce('xanchor'); - coerce('yanchor'); - coerce('xshift'); - coerce('yshift'); - - if(annOut.showarrow) { - annOut.axref = 'pixel'; - annOut.ayref = 'pixel'; - - // TODO maybe default values should be bigger than the 2D case? - coerce('ax', -10); - coerce('ay', -30); - - // if you have one part of arrow length you should have both - Lib.noneOrAll(annIn, annOut, ['ax', 'ay']); - } -} - -},{"../../lib":719,"../../plots/array_container_defaults":763,"../../plots/cartesian/axes":767,"../annotations/common_defaults":579,"./attributes":585}],588:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var drawRaw = _dereq_('../annotations/draw').drawRaw; -var project = _dereq_('../../plots/gl3d/project'); -var axLetters = ['x', 'y', 'z']; - -module.exports = function draw(scene) { - var fullSceneLayout = scene.fullSceneLayout; - var dataScale = scene.dataScale; - var anns = fullSceneLayout.annotations; - - for(var i = 0; i < anns.length; i++) { - var ann = anns[i]; - var annotationIsOffscreen = false; - - for(var j = 0; j < 3; j++) { - var axLetter = axLetters[j]; - var pos = ann[axLetter]; - var ax = fullSceneLayout[axLetter + 'axis']; - var posFraction = ax.r2fraction(pos); - - if(posFraction < 0 || posFraction > 1) { - annotationIsOffscreen = true; - break; - } - } - - if(annotationIsOffscreen) { - scene.fullLayout._infolayer - .select('.annotation-' + scene.id + '[data-index="' + i + '"]') - .remove(); - } else { - ann._pdata = project(scene.glplot.cameraParams, [ - fullSceneLayout.xaxis.r2l(ann.x) * dataScale[0], - fullSceneLayout.yaxis.r2l(ann.y) * dataScale[1], - fullSceneLayout.zaxis.r2l(ann.z) * dataScale[2] - ]); - - drawRaw(scene.graphDiv, ann, i, scene.id, ann._xa, ann._ya); - } - } -}; - -},{"../../plots/gl3d/project":816,"../annotations/draw":582}],589:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); - -module.exports = { - moduleType: 'component', - name: 'annotations3d', - - schema: { - subplots: { - scene: {annotations: _dereq_('./attributes')} - } - }, - - layoutAttributes: _dereq_('./attributes'), - handleDefaults: _dereq_('./defaults'), - includeBasePlot: includeGL3D, - - convert: _dereq_('./convert'), - draw: _dereq_('./draw') -}; - -function includeGL3D(layoutIn, layoutOut) { - var GL3D = Registry.subplotsRegistry.gl3d; - if(!GL3D) return; - - var attrRegex = GL3D.attrRegex; - - var keys = Object.keys(layoutIn); - for(var i = 0; i < keys.length; i++) { - var k = keys[i]; - if(attrRegex.test(k) && (layoutIn[k].annotations || []).length) { - Lib.pushUnique(layoutOut._basePlotModules, GL3D); - Lib.pushUnique(layoutOut._subplots.gl3d, k); - } - } -} - -},{"../../lib":719,"../../registry":847,"./attributes":585,"./convert":586,"./defaults":587,"./draw":588}],590:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -// a trimmed down version of: -// https://github.com/alexcjohnson/world-calendars/blob/master/dist/index.js - -module.exports = _dereq_('world-calendars/dist/main'); - -_dereq_('world-calendars/dist/plus'); - -_dereq_('world-calendars/dist/calendars/chinese'); -_dereq_('world-calendars/dist/calendars/coptic'); -_dereq_('world-calendars/dist/calendars/discworld'); -_dereq_('world-calendars/dist/calendars/ethiopian'); -_dereq_('world-calendars/dist/calendars/hebrew'); -_dereq_('world-calendars/dist/calendars/islamic'); -_dereq_('world-calendars/dist/calendars/julian'); -_dereq_('world-calendars/dist/calendars/mayan'); -_dereq_('world-calendars/dist/calendars/nanakshahi'); -_dereq_('world-calendars/dist/calendars/nepali'); -_dereq_('world-calendars/dist/calendars/persian'); -_dereq_('world-calendars/dist/calendars/taiwan'); -_dereq_('world-calendars/dist/calendars/thai'); -_dereq_('world-calendars/dist/calendars/ummalqura'); - -},{"world-calendars/dist/calendars/chinese":557,"world-calendars/dist/calendars/coptic":558,"world-calendars/dist/calendars/discworld":559,"world-calendars/dist/calendars/ethiopian":560,"world-calendars/dist/calendars/hebrew":561,"world-calendars/dist/calendars/islamic":562,"world-calendars/dist/calendars/julian":563,"world-calendars/dist/calendars/mayan":564,"world-calendars/dist/calendars/nanakshahi":565,"world-calendars/dist/calendars/nepali":566,"world-calendars/dist/calendars/persian":567,"world-calendars/dist/calendars/taiwan":568,"world-calendars/dist/calendars/thai":569,"world-calendars/dist/calendars/ummalqura":570,"world-calendars/dist/main":571,"world-calendars/dist/plus":572}],591:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var calendars = _dereq_('./calendars'); - -var Lib = _dereq_('../../lib'); -var constants = _dereq_('../../constants/numerical'); - -var EPOCHJD = constants.EPOCHJD; -var ONEDAY = constants.ONEDAY; - -var attributes = { - valType: 'enumerated', - values: Object.keys(calendars.calendars), - - editType: 'calc', - dflt: 'gregorian' -}; - -var handleDefaults = function(contIn, contOut, attr, dflt) { - var attrs = {}; - attrs[attr] = attributes; - - return Lib.coerce(contIn, contOut, attrs, attr, dflt); -}; - -var handleTraceDefaults = function(traceIn, traceOut, coords, layout) { - for(var i = 0; i < coords.length; i++) { - handleDefaults(traceIn, traceOut, coords[i] + 'calendar', layout.calendar); - } -}; - -// each calendar needs its own default canonical tick. I would love to use -// 2000-01-01 (or even 0000-01-01) for them all but they don't necessarily -// all support either of those dates. Instead I'll use the most significant -// number they *do* support, biased toward the present day. -var CANONICAL_TICK = { - chinese: '2000-01-01', - coptic: '2000-01-01', - discworld: '2000-01-01', - ethiopian: '2000-01-01', - hebrew: '5000-01-01', - islamic: '1000-01-01', - julian: '2000-01-01', - mayan: '5000-01-01', - nanakshahi: '1000-01-01', - nepali: '2000-01-01', - persian: '1000-01-01', - jalali: '1000-01-01', - taiwan: '1000-01-01', - thai: '2000-01-01', - ummalqura: '1400-01-01' -}; - -// Start on a Sunday - for week ticks -// Discworld and Mayan calendars don't have 7-day weeks but we're going to give them -// 7-day week ticks so start on our Sundays. -// If anyone really cares we can customize the auto tick spacings for these calendars. -var CANONICAL_SUNDAY = { - chinese: '2000-01-02', - coptic: '2000-01-03', - discworld: '2000-01-03', - ethiopian: '2000-01-05', - hebrew: '5000-01-01', - islamic: '1000-01-02', - julian: '2000-01-03', - mayan: '5000-01-01', - nanakshahi: '1000-01-05', - nepali: '2000-01-05', - persian: '1000-01-01', - jalali: '1000-01-01', - taiwan: '1000-01-04', - thai: '2000-01-04', - ummalqura: '1400-01-06' -}; - -var DFLTRANGE = { - chinese: ['2000-01-01', '2001-01-01'], - coptic: ['1700-01-01', '1701-01-01'], - discworld: ['1800-01-01', '1801-01-01'], - ethiopian: ['2000-01-01', '2001-01-01'], - hebrew: ['5700-01-01', '5701-01-01'], - islamic: ['1400-01-01', '1401-01-01'], - julian: ['2000-01-01', '2001-01-01'], - mayan: ['5200-01-01', '5201-01-01'], - nanakshahi: ['0500-01-01', '0501-01-01'], - nepali: ['2000-01-01', '2001-01-01'], - persian: ['1400-01-01', '1401-01-01'], - jalali: ['1400-01-01', '1401-01-01'], - taiwan: ['0100-01-01', '0101-01-01'], - thai: ['2500-01-01', '2501-01-01'], - ummalqura: ['1400-01-01', '1401-01-01'] -}; - -/* - * convert d3 templates to world-calendars templates, so our users only need - * to know d3's specifiers. Map space padding to no padding, and unknown fields - * to an ugly placeholder - */ -var UNKNOWN = '##'; -var d3ToWorldCalendars = { - 'd': {'0': 'dd', '-': 'd'}, // 2-digit or unpadded day of month - 'e': {'0': 'd', '-': 'd'}, // alternate, always unpadded day of month - 'a': {'0': 'D', '-': 'D'}, // short weekday name - 'A': {'0': 'DD', '-': 'DD'}, // full weekday name - 'j': {'0': 'oo', '-': 'o'}, // 3-digit or unpadded day of the year - 'W': {'0': 'ww', '-': 'w'}, // 2-digit or unpadded week of the year (Monday first) - 'm': {'0': 'mm', '-': 'm'}, // 2-digit or unpadded month number - 'b': {'0': 'M', '-': 'M'}, // short month name - 'B': {'0': 'MM', '-': 'MM'}, // full month name - 'y': {'0': 'yy', '-': 'yy'}, // 2-digit year (map unpadded to zero-padded) - 'Y': {'0': 'yyyy', '-': 'yyyy'}, // 4-digit year (map unpadded to zero-padded) - 'U': UNKNOWN, // Sunday-first week of the year - 'w': UNKNOWN, // day of the week [0(sunday),6] - // combined format, we replace the date part with the world-calendar version - // and the %X stays there for d3 to handle with time parts - 'c': {'0': 'D M d %X yyyy', '-': 'D M d %X yyyy'}, - 'x': {'0': 'mm/dd/yyyy', '-': 'mm/dd/yyyy'} -}; - -function worldCalFmt(fmt, x, calendar) { - var dateJD = Math.floor((x + 0.05) / ONEDAY) + EPOCHJD; - var cDate = getCal(calendar).fromJD(dateJD); - var i = 0; - var modifier, directive, directiveLen, directiveObj, replacementPart; - - while((i = fmt.indexOf('%', i)) !== -1) { - modifier = fmt.charAt(i + 1); - if(modifier === '0' || modifier === '-' || modifier === '_') { - directiveLen = 3; - directive = fmt.charAt(i + 2); - if(modifier === '_') modifier = '-'; - } else { - directive = modifier; - modifier = '0'; - directiveLen = 2; - } - directiveObj = d3ToWorldCalendars[directive]; - if(!directiveObj) { - i += directiveLen; - } else { - // code is recognized as a date part but world-calendars doesn't support it - if(directiveObj === UNKNOWN) replacementPart = UNKNOWN; - - // format the cDate according to the translated directive - else replacementPart = cDate.formatDate(directiveObj[modifier]); - - fmt = fmt.substr(0, i) + replacementPart + fmt.substr(i + directiveLen); - i += replacementPart.length; - } - } - return fmt; -} - -// cache world calendars, so we don't have to reinstantiate -// during each date-time conversion -var allCals = {}; -function getCal(calendar) { - var calendarObj = allCals[calendar]; - if(calendarObj) return calendarObj; - - calendarObj = allCals[calendar] = calendars.instance(calendar); - return calendarObj; -} - -function makeAttrs(description) { - return Lib.extendFlat({}, attributes, { description: description }); -} - -function makeTraceAttrsDescription(coord) { - return 'Sets the calendar system to use with `' + coord + '` date data.'; -} - -var xAttrs = { - xcalendar: makeAttrs(makeTraceAttrsDescription('x')) -}; - -var xyAttrs = Lib.extendFlat({}, xAttrs, { - ycalendar: makeAttrs(makeTraceAttrsDescription('y')) -}); - -var xyzAttrs = Lib.extendFlat({}, xyAttrs, { - zcalendar: makeAttrs(makeTraceAttrsDescription('z')) -}); - -var axisAttrs = makeAttrs([ - 'Sets the calendar system to use for `range` and `tick0`', - 'if this is a date axis. This does not set the calendar for', - 'interpreting data on this axis, that\'s specified in the trace', - 'or via the global `layout.calendar`' -].join(' ')); - -module.exports = { - moduleType: 'component', - name: 'calendars', - - schema: { - traces: { - scatter: xyAttrs, - bar: xyAttrs, - box: xyAttrs, - heatmap: xyAttrs, - contour: xyAttrs, - histogram: xyAttrs, - histogram2d: xyAttrs, - histogram2dcontour: xyAttrs, - scatter3d: xyzAttrs, - surface: xyzAttrs, - mesh3d: xyzAttrs, - scattergl: xyAttrs, - ohlc: xAttrs, - candlestick: xAttrs - }, - layout: { - calendar: makeAttrs([ - 'Sets the default calendar system to use for interpreting and', - 'displaying dates throughout the plot.' - ].join(' ')) - }, - subplots: { - xaxis: {calendar: axisAttrs}, - yaxis: {calendar: axisAttrs}, - scene: { - xaxis: {calendar: axisAttrs}, - // TODO: it's actually redundant to include yaxis and zaxis here - // because in the scene attributes these are the same object so merging - // into one merges into them all. However, I left them in for parity with - // cartesian, where yaxis is unused until we Plotschema.get() when we - // use its presence or absence to determine whether to delete attributes - // from yaxis if they only apply to x (rangeselector/rangeslider) - yaxis: {calendar: axisAttrs}, - zaxis: {calendar: axisAttrs} - }, - polar: { - radialaxis: {calendar: axisAttrs} - } - }, - transforms: { - filter: { - valuecalendar: makeAttrs([ - 'Sets the calendar system to use for `value`, if it is a date.' - ].join(' ')), - targetcalendar: makeAttrs([ - 'Sets the calendar system to use for `target`, if it is an', - 'array of dates. If `target` is a string (eg *x*) we use the', - 'corresponding trace attribute (eg `xcalendar`) if it exists,', - 'even if `targetcalendar` is provided.' - ].join(' ')) - } - } - }, - - layoutAttributes: attributes, - - handleDefaults: handleDefaults, - handleTraceDefaults: handleTraceDefaults, - - CANONICAL_SUNDAY: CANONICAL_SUNDAY, - CANONICAL_TICK: CANONICAL_TICK, - DFLTRANGE: DFLTRANGE, - - getCal: getCal, - worldCalFmt: worldCalFmt -}; - -},{"../../constants/numerical":695,"../../lib":719,"./calendars":590}],592:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -// IMPORTANT - default colors should be in hex for compatibility -exports.defaults = [ - '#1f77b4', // muted blue - '#ff7f0e', // safety orange - '#2ca02c', // cooked asparagus green - '#d62728', // brick red - '#9467bd', // muted purple - '#8c564b', // chestnut brown - '#e377c2', // raspberry yogurt pink - '#7f7f7f', // middle gray - '#bcbd22', // curry yellow-green - '#17becf' // blue-teal -]; - -exports.defaultLine = '#444'; - -exports.lightLine = '#eee'; - -exports.background = '#fff'; - -exports.borderLine = '#BEC8D9'; - -// with axis.color and Color.interp we aren't using lightLine -// itself anymore, instead interpolating between axis.color -// and the background color using tinycolor.mix. lightFraction -// gives back exactly lightLine if the other colors are defaults. -exports.lightFraction = 100 * (0xe - 0x4) / (0xf - 0x4); - -},{}],593:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var tinycolor = _dereq_('tinycolor2'); -var isNumeric = _dereq_('fast-isnumeric'); - -var color = module.exports = {}; - -var colorAttrs = _dereq_('./attributes'); -color.defaults = colorAttrs.defaults; -var defaultLine = color.defaultLine = colorAttrs.defaultLine; -color.lightLine = colorAttrs.lightLine; -var background = color.background = colorAttrs.background; - -/* - * tinyRGB: turn a tinycolor into an rgb string, but - * unlike the built-in tinycolor.toRgbString this never includes alpha - */ -color.tinyRGB = function(tc) { - var c = tc.toRgb(); - return 'rgb(' + Math.round(c.r) + ', ' + - Math.round(c.g) + ', ' + Math.round(c.b) + ')'; -}; - -color.rgb = function(cstr) { return color.tinyRGB(tinycolor(cstr)); }; - -color.opacity = function(cstr) { return cstr ? tinycolor(cstr).getAlpha() : 0; }; - -color.addOpacity = function(cstr, op) { - var c = tinycolor(cstr).toRgb(); - return 'rgba(' + Math.round(c.r) + ', ' + - Math.round(c.g) + ', ' + Math.round(c.b) + ', ' + op + ')'; -}; - -// combine two colors into one apparent color -// if back has transparency or is missing, -// color.background is assumed behind it -color.combine = function(front, back) { - var fc = tinycolor(front).toRgb(); - if(fc.a === 1) return tinycolor(front).toRgbString(); - - var bc = tinycolor(back || background).toRgb(); - var bcflat = bc.a === 1 ? bc : { - r: 255 * (1 - bc.a) + bc.r * bc.a, - g: 255 * (1 - bc.a) + bc.g * bc.a, - b: 255 * (1 - bc.a) + bc.b * bc.a - }; - var fcflat = { - r: bcflat.r * (1 - fc.a) + fc.r * fc.a, - g: bcflat.g * (1 - fc.a) + fc.g * fc.a, - b: bcflat.b * (1 - fc.a) + fc.b * fc.a - }; - return tinycolor(fcflat).toRgbString(); -}; - -/* - * Create a color that contrasts with cstr. - * - * If cstr is a dark color, we lighten it; if it's light, we darken. - * - * If lightAmount / darkAmount are used, we adjust by these percentages, - * otherwise we go all the way to white or black. - */ -color.contrast = function(cstr, lightAmount, darkAmount) { - var tc = tinycolor(cstr); - - if(tc.getAlpha() !== 1) tc = tinycolor(color.combine(cstr, background)); - - var newColor = tc.isDark() ? - (lightAmount ? tc.lighten(lightAmount) : background) : - (darkAmount ? tc.darken(darkAmount) : defaultLine); - - return newColor.toString(); -}; - -color.stroke = function(s, c) { - var tc = tinycolor(c); - s.style({'stroke': color.tinyRGB(tc), 'stroke-opacity': tc.getAlpha()}); -}; - -color.fill = function(s, c) { - var tc = tinycolor(c); - s.style({ - 'fill': color.tinyRGB(tc), - 'fill-opacity': tc.getAlpha() - }); -}; - -// search container for colors with the deprecated rgb(fractions) format -// and convert them to rgb(0-255 values) -color.clean = function(container) { - if(!container || typeof container !== 'object') return; - - var keys = Object.keys(container); - var i, j, key, val; - - for(i = 0; i < keys.length; i++) { - key = keys[i]; - val = container[key]; - - if(key.substr(key.length - 5) === 'color') { - // only sanitize keys that end in "color" or "colorscale" - - if(Array.isArray(val)) { - for(j = 0; j < val.length; j++) val[j] = cleanOne(val[j]); - } else container[key] = cleanOne(val); - } else if(key.substr(key.length - 10) === 'colorscale' && Array.isArray(val)) { - // colorscales have the format [[0, color1], [frac, color2], ... [1, colorN]] - - for(j = 0; j < val.length; j++) { - if(Array.isArray(val[j])) val[j][1] = cleanOne(val[j][1]); - } - } else if(Array.isArray(val)) { - // recurse into arrays of objects, and plain objects - - var el0 = val[0]; - if(!Array.isArray(el0) && el0 && typeof el0 === 'object') { - for(j = 0; j < val.length; j++) color.clean(val[j]); - } - } else if(val && typeof val === 'object') color.clean(val); - } -}; - -function cleanOne(val) { - if(isNumeric(val) || typeof val !== 'string') return val; - - var valTrim = val.trim(); - if(valTrim.substr(0, 3) !== 'rgb') return val; - - var match = valTrim.match(/^rgba?\s*\(([^()]*)\)$/); - if(!match) return val; - - var parts = match[1].trim().split(/\s*[\s,]\s*/); - var rgba = valTrim.charAt(3) === 'a' && parts.length === 4; - if(!rgba && parts.length !== 3) return val; - - for(var i = 0; i < parts.length; i++) { - if(!parts[i].length) return val; - parts[i] = Number(parts[i]); - - if(!(parts[i] >= 0)) { - // all parts must be non-negative numbers - - return val; - } - - if(i === 3) { - // alpha>1 gets clipped to 1 - - if(parts[i] > 1) parts[i] = 1; - } else if(parts[i] >= 1) { - // r, g, b must be < 1 (ie 1 itself is not allowed) - - return val; - } - } - - var rgbStr = Math.round(parts[0] * 255) + ', ' + - Math.round(parts[1] * 255) + ', ' + - Math.round(parts[2] * 255); - - if(rgba) return 'rgba(' + rgbStr + ', ' + parts[3] + ')'; - return 'rgb(' + rgbStr + ')'; -} - -},{"./attributes":592,"fast-isnumeric":225,"tinycolor2":537}],594:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var axesAttrs = _dereq_('../../plots/cartesian/layout_attributes'); -var fontAttrs = _dereq_('../../plots/font_attributes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - - -module.exports = overrideAll({ -// TODO: only right is supported currently -// orient: { -// valType: 'enumerated', -// -// values: ['left', 'right', 'top', 'bottom'], -// dflt: 'right', -// -// }, - thicknessmode: { - valType: 'enumerated', - values: ['fraction', 'pixels'], - - dflt: 'pixels', - - }, - thickness: { - valType: 'number', - - min: 0, - dflt: 30, - - }, - lenmode: { - valType: 'enumerated', - values: ['fraction', 'pixels'], - - dflt: 'fraction', - - }, - len: { - valType: 'number', - min: 0, - dflt: 1, - - - }, - x: { - valType: 'number', - dflt: 1.02, - min: -2, - max: 3, - - - }, - xanchor: { - valType: 'enumerated', - values: ['left', 'center', 'right'], - dflt: 'left', - - - }, - xpad: { - valType: 'number', - - min: 0, - dflt: 10, - - }, - y: { - valType: 'number', - - dflt: 0.5, - min: -2, - max: 3, - - }, - yanchor: { - valType: 'enumerated', - values: ['top', 'middle', 'bottom'], - - dflt: 'middle', - - }, - ypad: { - valType: 'number', - - min: 0, - dflt: 10, - - }, - // a possible line around the bar itself - outlinecolor: axesAttrs.linecolor, - outlinewidth: axesAttrs.linewidth, - // Should outlinewidth have {dflt: 0} ? - // another possible line outside the padding and tick labels - bordercolor: axesAttrs.linecolor, - borderwidth: { - valType: 'number', - - min: 0, - dflt: 0, - - }, - bgcolor: { - valType: 'color', - - dflt: 'rgba(0,0,0,0)', - - }, - // tick and title properties named and function exactly as in axes - tickmode: axesAttrs.tickmode, - nticks: axesAttrs.nticks, - tick0: axesAttrs.tick0, - dtick: axesAttrs.dtick, - tickvals: axesAttrs.tickvals, - ticktext: axesAttrs.ticktext, - ticks: extendFlat({}, axesAttrs.ticks, {dflt: ''}), - ticklen: axesAttrs.ticklen, - tickwidth: axesAttrs.tickwidth, - tickcolor: axesAttrs.tickcolor, - showticklabels: axesAttrs.showticklabels, - tickfont: fontAttrs({ - - }), - tickangle: axesAttrs.tickangle, - tickformat: axesAttrs.tickformat, - tickformatstops: axesAttrs.tickformatstops, - tickprefix: axesAttrs.tickprefix, - showtickprefix: axesAttrs.showtickprefix, - ticksuffix: axesAttrs.ticksuffix, - showticksuffix: axesAttrs.showticksuffix, - separatethousands: axesAttrs.separatethousands, - exponentformat: axesAttrs.exponentformat, - showexponent: axesAttrs.showexponent, - title: { - text: { - valType: 'string', - - - }, - font: fontAttrs({ - - }), - side: { - valType: 'enumerated', - values: ['right', 'top', 'bottom'], - - dflt: 'top', - - } - }, - - _deprecated: { - title: { - valType: 'string', - - - }, - titlefont: fontAttrs({ - - }), - titleside: { - valType: 'enumerated', - values: ['right', 'top', 'bottom'], - - dflt: 'top', - - } - } -}, 'colorbars', 'from-root'); - -},{"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plots/cartesian/layout_attributes":779,"../../plots/font_attributes":793}],595:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - cn: { - colorbar: 'colorbar', - cbbg: 'cbbg', - cbfill: 'cbfill', - cbfills: 'cbfills', - cbline: 'cbline', - cblines: 'cblines', - cbaxis: 'cbaxis', - cbtitleunshift: 'cbtitleunshift', - cbtitle: 'cbtitle', - cboutline: 'cboutline', - crisp: 'crisp', - jsPlaceholder: 'js-placeholder' - } -}; - -},{}],596:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Template = _dereq_('../../plot_api/plot_template'); - -var handleTickValueDefaults = _dereq_('../../plots/cartesian/tick_value_defaults'); -var handleTickMarkDefaults = _dereq_('../../plots/cartesian/tick_mark_defaults'); -var handleTickLabelDefaults = _dereq_('../../plots/cartesian/tick_label_defaults'); - -var attributes = _dereq_('./attributes'); - -module.exports = function colorbarDefaults(containerIn, containerOut, layout) { - var colorbarOut = Template.newContainer(containerOut, 'colorbar'); - var colorbarIn = containerIn.colorbar || {}; - - function coerce(attr, dflt) { - return Lib.coerce(colorbarIn, colorbarOut, attributes, attr, dflt); - } - - var thicknessmode = coerce('thicknessmode'); - coerce('thickness', (thicknessmode === 'fraction') ? - 30 / (layout.width - layout.margin.l - layout.margin.r) : - 30 - ); - - var lenmode = coerce('lenmode'); - coerce('len', (lenmode === 'fraction') ? - 1 : - layout.height - layout.margin.t - layout.margin.b - ); - - coerce('x'); - coerce('xanchor'); - coerce('xpad'); - coerce('y'); - coerce('yanchor'); - coerce('ypad'); - Lib.noneOrAll(colorbarIn, colorbarOut, ['x', 'y']); - - coerce('outlinecolor'); - coerce('outlinewidth'); - coerce('bordercolor'); - coerce('borderwidth'); - coerce('bgcolor'); - - handleTickValueDefaults(colorbarIn, colorbarOut, coerce, 'linear'); - - var opts = {outerTicks: false, font: layout.font}; - handleTickLabelDefaults(colorbarIn, colorbarOut, coerce, 'linear', opts); - handleTickMarkDefaults(colorbarIn, colorbarOut, coerce, 'linear', opts); - - coerce('title.text', layout._dfltTitle.colorbar); - Lib.coerceFont(coerce, 'title.font', layout.font); - coerce('title.side'); -}; - -},{"../../lib":719,"../../plot_api/plot_template":757,"../../plots/cartesian/tick_label_defaults":786,"../../plots/cartesian/tick_mark_defaults":787,"../../plots/cartesian/tick_value_defaults":788,"./attributes":594}],597:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var tinycolor = _dereq_('tinycolor2'); - -var Plots = _dereq_('../../plots/plots'); -var Registry = _dereq_('../../registry'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var dragElement = _dereq_('../dragelement'); -var Lib = _dereq_('../../lib'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var setCursor = _dereq_('../../lib/setcursor'); -var Drawing = _dereq_('../drawing'); -var Color = _dereq_('../color'); -var Titles = _dereq_('../titles'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var flipScale = _dereq_('../colorscale/helpers').flipScale; - -var handleAxisDefaults = _dereq_('../../plots/cartesian/axis_defaults'); -var handleAxisPositionDefaults = _dereq_('../../plots/cartesian/position_defaults'); -var axisLayoutAttrs = _dereq_('../../plots/cartesian/layout_attributes'); - -var alignmentConstants = _dereq_('../../constants/alignment'); -var LINE_SPACING = alignmentConstants.LINE_SPACING; -var FROM_TL = alignmentConstants.FROM_TL; -var FROM_BR = alignmentConstants.FROM_BR; - -var cn = _dereq_('./constants').cn; - -function draw(gd) { - var fullLayout = gd._fullLayout; - - var colorBars = fullLayout._infolayer - .selectAll('g.' + cn.colorbar) - .data(makeColorBarData(gd), function(opts) { return opts._id; }); - - colorBars.enter().append('g') - .attr('class', function(opts) { return opts._id; }) - .classed(cn.colorbar, true); - - colorBars.each(function(opts) { - var g = d3.select(this); - - Lib.ensureSingle(g, 'rect', cn.cbbg); - Lib.ensureSingle(g, 'g', cn.cbfills); - Lib.ensureSingle(g, 'g', cn.cblines); - Lib.ensureSingle(g, 'g', cn.cbaxis, function(s) { s.classed(cn.crisp, true); }); - Lib.ensureSingle(g, 'g', cn.cbtitleunshift, function(s) { s.append('g').classed(cn.cbtitle, true); }); - Lib.ensureSingle(g, 'rect', cn.cboutline); - - var done = drawColorBar(g, opts, gd); - if(done && done.then) (gd._promises || []).push(done); - - if(gd._context.edits.colorbarPosition) { - makeEditable(g, opts, gd); - } - }); - - colorBars.exit() - .each(function(opts) { Plots.autoMargin(gd, opts._id); }) - .remove(); - - colorBars.order(); -} - -function makeColorBarData(gd) { - var fullLayout = gd._fullLayout; - var calcdata = gd.calcdata; - var out = []; - - // single out item - var opts; - // colorbar attr parent container - var cont; - // trace attr container - var trace; - // colorbar options - var cbOpt; - - function initOpts(opts) { - return extendFlat(opts, { - // fillcolor can be a d3 scale, domain is z values, range is colors - // or leave it out for no fill, - // or set to a string constant for single-color fill - _fillcolor: null, - // line.color has the same options as fillcolor - _line: {color: null, width: null, dash: null}, - // levels of lines to draw. - // note that this DOES NOT determine the extent of the bar - // that's given by the domain of fillcolor - // (or line.color if no fillcolor domain) - _levels: {start: null, end: null, size: null}, - // separate fill levels (for example, heatmap coloring of a - // contour map) if this is omitted, fillcolors will be - // evaluated halfway between levels - _filllevels: null, - // for continuous colorscales: fill with a gradient instead of explicit levels - // value should be the colorscale [[0, c0], [v1, c1], ..., [1, cEnd]] - _fillgradient: null, - // when using a gradient, we need the data range specified separately - _zrange: null - }); - } - - function calcOpts() { - if(typeof cbOpt.calc === 'function') { - cbOpt.calc(gd, trace, opts); - } else { - opts._fillgradient = cont.reversescale ? - flipScale(cont.colorscale) : - cont.colorscale; - opts._zrange = [cont[cbOpt.min], cont[cbOpt.max]]; - } - } - - for(var i = 0; i < calcdata.length; i++) { - var cd = calcdata[i]; - trace = cd[0].trace; - var moduleOpts = trace._module.colorbar; - - if(trace.visible === true && moduleOpts) { - var allowsMultiplotCbs = Array.isArray(moduleOpts); - var cbOpts = allowsMultiplotCbs ? moduleOpts : [moduleOpts]; - - for(var j = 0; j < cbOpts.length; j++) { - cbOpt = cbOpts[j]; - var contName = cbOpt.container; - cont = contName ? trace[contName] : trace; - - if(cont && cont.showscale) { - opts = initOpts(cont.colorbar); - opts._id = 'cb' + trace.uid + (allowsMultiplotCbs && contName ? '-' + contName : ''); - opts._traceIndex = trace.index; - opts._propPrefix = (contName ? contName + '.' : '') + 'colorbar.'; - opts._meta = trace._meta; - calcOpts(); - out.push(opts); - } - } - } - } - - for(var k in fullLayout._colorAxes) { - cont = fullLayout[k]; - - if(cont.showscale) { - var colorAxOpts = fullLayout._colorAxes[k]; - - opts = initOpts(cont.colorbar); - opts._id = 'cb' + k; - opts._propPrefix = k + '.colorbar.'; - opts._meta = fullLayout._meta; - - cbOpt = {min: 'cmin', max: 'cmax'}; - if(colorAxOpts[0] !== 'heatmap') { - trace = colorAxOpts[1]; - cbOpt.calc = trace._module.colorbar.calc; - } - - calcOpts(); - out.push(opts); - } - } - - return out; -} - -function drawColorBar(g, opts, gd) { - var fullLayout = gd._fullLayout; - var gs = fullLayout._size; - - var fillColor = opts._fillcolor; - var line = opts._line; - var title = opts.title; - var titleSide = title.side; - - var zrange = opts._zrange || - d3.extent((typeof fillColor === 'function' ? fillColor : line.color).domain()); - - var lineColormap = typeof line.color === 'function' ? - line.color : - function() { return line.color; }; - var fillColormap = typeof fillColor === 'function' ? - fillColor : - function() { return fillColor; }; - - var levelsIn = opts._levels; - var levelsOut = calcLevels(gd, opts, zrange); - var fillLevels = levelsOut.fill; - var lineLevels = levelsOut.line; - - // we calculate pixel sizes based on the specified graph size, - // not the actual (in case something pushed the margins around) - // which is a little odd but avoids an odd iterative effect - // when the colorbar itself is pushing the margins. - // but then the fractional size is calculated based on the - // actual graph size, so that the axes will size correctly. - var thickPx = Math.round(opts.thickness * (opts.thicknessmode === 'fraction' ? gs.w : 1)); - var thickFrac = thickPx / gs.w; - var lenPx = Math.round(opts.len * (opts.lenmode === 'fraction' ? gs.h : 1)); - var lenFrac = lenPx / gs.h; - var xpadFrac = opts.xpad / gs.w; - var yExtraPx = (opts.borderwidth + opts.outlinewidth) / 2; - var ypadFrac = opts.ypad / gs.h; - - // x positioning: do it initially just for left anchor, - // then fix at the end (since we don't know the width yet) - var xLeft = Math.round(opts.x * gs.w + opts.xpad); - // for dragging... this is getting a little muddled... - var xLeftFrac = opts.x - thickFrac * ({middle: 0.5, right: 1}[opts.xanchor] || 0); - - // y positioning we can do correctly from the start - var yBottomFrac = opts.y + lenFrac * (({top: -0.5, bottom: 0.5}[opts.yanchor] || 0) - 0.5); - var yBottomPx = Math.round(gs.h * (1 - yBottomFrac)); - var yTopPx = yBottomPx - lenPx; - - // stash a few things for makeEditable - opts._lenFrac = lenFrac; - opts._thickFrac = thickFrac; - opts._xLeftFrac = xLeftFrac; - opts._yBottomFrac = yBottomFrac; - - var ax = mockColorBarAxis(gd, opts, zrange); - - // position can't go in through supplyDefaults - // because that restricts it to [0,1] - ax.position = opts.x + xpadFrac + thickFrac; - - if(['top', 'bottom'].indexOf(titleSide) !== -1) { - ax.title.side = titleSide; - ax.titlex = opts.x + xpadFrac; - ax.titley = yBottomFrac + (title.side === 'top' ? lenFrac - ypadFrac : ypadFrac); - } - - if(line.color && opts.tickmode === 'auto') { - ax.tickmode = 'linear'; - ax.tick0 = levelsIn.start; - var dtick = levelsIn.size; - // expand if too many contours, so we don't get too many ticks - var autoNtick = Lib.constrain((yBottomPx - yTopPx) / 50, 4, 15) + 1; - var dtFactor = (zrange[1] - zrange[0]) / ((opts.nticks || autoNtick) * dtick); - if(dtFactor > 1) { - var dtexp = Math.pow(10, Math.floor(Math.log(dtFactor) / Math.LN10)); - dtick *= dtexp * Lib.roundUp(dtFactor / dtexp, [2, 5, 10]); - // if the contours are at round multiples, reset tick0 - // so they're still at round multiples. Otherwise, - // keep the first label on the first contour level - if((Math.abs(levelsIn.start) / levelsIn.size + 1e-6) % 1 < 2e-6) { - ax.tick0 = 0; - } - } - ax.dtick = dtick; - } - - // set domain after init, because we may want to - // allow it outside [0,1] - ax.domain = [ - yBottomFrac + ypadFrac, - yBottomFrac + lenFrac - ypadFrac - ]; - - ax.setScale(); - - g.attr('transform', 'translate(' + Math.round(gs.l) + ',' + Math.round(gs.t) + ')'); - - var titleCont = g.select('.' + cn.cbtitleunshift) - .attr('transform', 'translate(-' + Math.round(gs.l) + ',-' + Math.round(gs.t) + ')'); - - var axLayer = g.select('.' + cn.cbaxis); - var titleEl; - var titleHeight = 0; - - function drawTitle(titleClass, titleOpts) { - var dfltTitleOpts = { - propContainer: ax, - propName: opts._propPrefix + 'title', - traceIndex: opts._traceIndex, - _meta: opts._meta, - placeholder: fullLayout._dfltTitle.colorbar, - containerGroup: g.select('.' + cn.cbtitle) - }; - - // this class-to-rotate thing with convertToTspans is - // getting hackier and hackier... delete groups with the - // wrong class (in case earlier the colorbar was drawn on - // a different side, I think?) - var otherClass = titleClass.charAt(0) === 'h' ? - titleClass.substr(1) : - 'h' + titleClass; - g.selectAll('.' + otherClass + ',.' + otherClass + '-math-group').remove(); - - Titles.draw(gd, titleClass, extendFlat(dfltTitleOpts, titleOpts || {})); - } - - function drawDummyTitle() { - if(['top', 'bottom'].indexOf(titleSide) !== -1) { - // draw the title so we know how much room it needs - // when we squish the axis. This one only applies to - // top or bottom titles, not right side. - var x = gs.l + (opts.x + xpadFrac) * gs.w; - var fontSize = ax.title.font.size; - var y; - - if(titleSide === 'top') { - y = (1 - (yBottomFrac + lenFrac - ypadFrac)) * gs.h + - gs.t + 3 + fontSize * 0.75; - } else { - y = (1 - (yBottomFrac + ypadFrac)) * gs.h + - gs.t - 3 - fontSize * 0.25; - } - drawTitle(ax._id + 'title', { - attributes: {x: x, y: y, 'text-anchor': 'start'} - }); - } - } - - function drawCbTitle() { - if(['top', 'bottom'].indexOf(titleSide) === -1) { - var fontSize = ax.title.font.size; - var y = ax._offset + ax._length / 2; - var x = gs.l + (ax.position || 0) * gs.w + ((ax.side === 'right') ? - 10 + fontSize * ((ax.showticklabels ? 1 : 0.5)) : - -10 - fontSize * ((ax.showticklabels ? 0.5 : 0))); - - // the 'h' + is a hack to get around the fact that - // convertToTspans rotates any 'y...' class by 90 degrees. - // TODO: find a better way to control this. - drawTitle('h' + ax._id + 'title', { - avoid: { - selection: d3.select(gd).selectAll('g.' + ax._id + 'tick'), - side: titleSide, - offsetLeft: gs.l, - offsetTop: 0, - maxShift: fullLayout.width - }, - attributes: {x: x, y: y, 'text-anchor': 'middle'}, - transform: {rotate: '-90', offset: 0} - }); - } - } - - function drawAxis() { - if(['top', 'bottom'].indexOf(titleSide) !== -1) { - // squish the axis top to make room for the title - var titleGroup = g.select('.' + cn.cbtitle); - var titleText = titleGroup.select('text'); - var titleTrans = [-opts.outlinewidth / 2, opts.outlinewidth / 2]; - var mathJaxNode = titleGroup - .select('.h' + ax._id + 'title-math-group') - .node(); - var lineSize = 15.6; - if(titleText.node()) { - lineSize = parseInt(titleText.node().style.fontSize, 10) * LINE_SPACING; - } - if(mathJaxNode) { - titleHeight = Drawing.bBox(mathJaxNode).height; - if(titleHeight > lineSize) { - // not entirely sure how mathjax is doing - // vertical alignment, but this seems to work. - titleTrans[1] -= (titleHeight - lineSize) / 2; - } - } else if(titleText.node() && !titleText.classed(cn.jsPlaceholder)) { - titleHeight = Drawing.bBox(titleText.node()).height; - } - if(titleHeight) { - // buffer btwn colorbar and title - // TODO: configurable - titleHeight += 5; - - if(titleSide === 'top') { - ax.domain[1] -= titleHeight / gs.h; - titleTrans[1] *= -1; - } else { - ax.domain[0] += titleHeight / gs.h; - var nlines = svgTextUtils.lineCount(titleText); - titleTrans[1] += (1 - nlines) * lineSize; - } - - titleGroup.attr('transform', 'translate(' + titleTrans + ')'); - ax.setScale(); - } - } - - g.selectAll('.' + cn.cbfills + ',.' + cn.cblines) - .attr('transform', 'translate(0,' + Math.round(gs.h * (1 - ax.domain[1])) + ')'); - - axLayer.attr('transform', 'translate(0,' + Math.round(-gs.t) + ')'); - - var fills = g.select('.' + cn.cbfills) - .selectAll('rect.' + cn.cbfill) - .data(fillLevels); - fills.enter().append('rect') - .classed(cn.cbfill, true) - .style('stroke', 'none'); - fills.exit().remove(); - - var zBounds = zrange - .map(ax.c2p) - .map(Math.round) - .sort(function(a, b) { return a - b; }); - - fills.each(function(d, i) { - var z = [ - (i === 0) ? zrange[0] : (fillLevels[i] + fillLevels[i - 1]) / 2, - (i === fillLevels.length - 1) ? zrange[1] : (fillLevels[i] + fillLevels[i + 1]) / 2 - ] - .map(ax.c2p) - .map(Math.round); - - // offset the side adjoining the next rectangle so they - // overlap, to prevent antialiasing gaps - z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]); - - - // Colorbar cannot currently support opacities so we - // use an opaque fill even when alpha channels present - var fillEl = d3.select(this).attr({ - x: xLeft, - width: Math.max(thickPx, 2), - y: d3.min(z), - height: Math.max(d3.max(z) - d3.min(z), 2), - }); - - if(opts._fillgradient) { - Drawing.gradient(fillEl, gd, opts._id, 'vertical', opts._fillgradient, 'fill'); - } else { - // tinycolor can't handle exponents and - // at this scale, removing it makes no difference. - var colorString = fillColormap(d).replace('e-', ''); - fillEl.attr('fill', tinycolor(colorString).toHexString()); - } - }); - - var lines = g.select('.' + cn.cblines) - .selectAll('path.' + cn.cbline) - .data(line.color && line.width ? lineLevels : []); - lines.enter().append('path') - .classed(cn.cbline, true); - lines.exit().remove(); - lines.each(function(d) { - d3.select(this) - .attr('d', 'M' + xLeft + ',' + - (Math.round(ax.c2p(d)) + (line.width / 2) % 1) + 'h' + thickPx) - .call(Drawing.lineGroupStyle, line.width, lineColormap(d), line.dash); - }); - - // force full redraw of labels and ticks - axLayer.selectAll('g.' + ax._id + 'tick,path').remove(); - - var shift = xLeft + thickPx + - (opts.outlinewidth || 0) / 2 - (opts.ticks === 'outside' ? 1 : 0); - - var vals = Axes.calcTicks(ax); - var transFn = Axes.makeTransFn(ax); - var tickSign = Axes.getTickSigns(ax)[2]; - - Axes.drawTicks(gd, ax, { - vals: ax.ticks === 'inside' ? Axes.clipEnds(ax, vals) : vals, - layer: axLayer, - path: Axes.makeTickPath(ax, shift, tickSign), - transFn: transFn - }); - - return Axes.drawLabels(gd, ax, { - vals: vals, - layer: axLayer, - transFn: transFn, - labelFns: Axes.makeLabelFns(ax, shift) - }); - } - - // wait for the axis & title to finish rendering before - // continuing positioning - // TODO: why are we redrawing multiple times now with this? - // I guess autoMargin doesn't like being post-promise? - function positionCB() { - var innerWidth = thickPx + opts.outlinewidth / 2 + Drawing.bBox(axLayer.node()).width; - titleEl = titleCont.select('text'); - - if(titleEl.node() && !titleEl.classed(cn.jsPlaceholder)) { - var mathJaxNode = titleCont.select('.h' + ax._id + 'title-math-group').node(); - var titleWidth; - if(mathJaxNode && ['top', 'bottom'].indexOf(titleSide) !== -1) { - titleWidth = Drawing.bBox(mathJaxNode).width; - } else { - // note: the formula below works for all title sides, - // (except for top/bottom mathjax, above) - // but the weird gs.l is because the titleunshift - // transform gets removed by Drawing.bBox - titleWidth = Drawing.bBox(titleCont.node()).right - xLeft - gs.l; - } - innerWidth = Math.max(innerWidth, titleWidth); - } - - var outerwidth = 2 * opts.xpad + innerWidth + opts.borderwidth + opts.outlinewidth / 2; - var outerheight = yBottomPx - yTopPx; - - g.select('.' + cn.cbbg).attr({ - x: xLeft - opts.xpad - (opts.borderwidth + opts.outlinewidth) / 2, - y: yTopPx - yExtraPx, - width: Math.max(outerwidth, 2), - height: Math.max(outerheight + 2 * yExtraPx, 2) - }) - .call(Color.fill, opts.bgcolor) - .call(Color.stroke, opts.bordercolor) - .style('stroke-width', opts.borderwidth); - - g.selectAll('.' + cn.cboutline).attr({ - x: xLeft, - y: yTopPx + opts.ypad + (titleSide === 'top' ? titleHeight : 0), - width: Math.max(thickPx, 2), - height: Math.max(outerheight - 2 * opts.ypad - titleHeight, 2) - }) - .call(Color.stroke, opts.outlinecolor) - .style({ - fill: 'none', - 'stroke-width': opts.outlinewidth - }); - - // fix positioning for xanchor!='left' - var xoffset = ({center: 0.5, right: 1}[opts.xanchor] || 0) * outerwidth; - g.attr('transform', 'translate(' + (gs.l - xoffset) + ',' + gs.t + ')'); - - // auto margin adjustment - var marginOpts = {}; - var tFrac = FROM_TL[opts.yanchor]; - var bFrac = FROM_BR[opts.yanchor]; - if(opts.lenmode === 'pixels') { - marginOpts.y = opts.y; - marginOpts.t = outerheight * tFrac; - marginOpts.b = outerheight * bFrac; - } else { - marginOpts.t = marginOpts.b = 0; - marginOpts.yt = opts.y + opts.len * tFrac; - marginOpts.yb = opts.y - opts.len * bFrac; - } - - var lFrac = FROM_TL[opts.xanchor]; - var rFrac = FROM_BR[opts.xanchor]; - if(opts.thicknessmode === 'pixels') { - marginOpts.x = opts.x; - marginOpts.l = outerwidth * lFrac; - marginOpts.r = outerwidth * rFrac; - } else { - var extraThickness = outerwidth - thickPx; - marginOpts.l = extraThickness * lFrac; - marginOpts.r = extraThickness * rFrac; - marginOpts.xl = opts.x - opts.thickness * lFrac; - marginOpts.xr = opts.x + opts.thickness * rFrac; - } - - Plots.autoMargin(gd, opts._id, marginOpts); - } - - return Lib.syncOrAsync([ - Plots.previousPromises, - drawDummyTitle, - drawAxis, - drawCbTitle, - Plots.previousPromises, - positionCB - ], gd); -} - -function makeEditable(g, opts, gd) { - var fullLayout = gd._fullLayout; - var gs = fullLayout._size; - var t0, xf, yf; - - dragElement.init({ - element: g.node(), - gd: gd, - prepFn: function() { - t0 = g.attr('transform'); - setCursor(g); - }, - moveFn: function(dx, dy) { - g.attr('transform', t0 + ' ' + 'translate(' + dx + ',' + dy + ')'); - - xf = dragElement.align(opts._xLeftFrac + (dx / gs.w), opts._thickFrac, - 0, 1, opts.xanchor); - yf = dragElement.align(opts._yBottomFrac - (dy / gs.h), opts._lenFrac, - 0, 1, opts.yanchor); - - var csr = dragElement.getCursor(xf, yf, opts.xanchor, opts.yanchor); - setCursor(g, csr); - }, - doneFn: function() { - setCursor(g); - - if(xf !== undefined && yf !== undefined) { - var update = {}; - update[opts._propPrefix + 'x'] = xf; - update[opts._propPrefix + 'y'] = yf; - if(opts._traceIndex !== undefined) { - Registry.call('_guiRestyle', gd, update, opts._traceIndex); - } else { - Registry.call('_guiRelayout', gd, update); - } - } - } - }); -} - -function calcLevels(gd, opts, zrange) { - var levelsIn = opts._levels; - var lineLevels = []; - var fillLevels = []; - var l; - var i; - - var l0 = levelsIn.end + levelsIn.size / 100; - var ls = levelsIn.size; - var zr0 = (1.001 * zrange[0] - 0.001 * zrange[1]); - var zr1 = (1.001 * zrange[1] - 0.001 * zrange[0]); - - for(i = 0; i < 1e5; i++) { - l = levelsIn.start + i * ls; - if(ls > 0 ? (l >= l0) : (l <= l0)) break; - if(l > zr0 && l < zr1) lineLevels.push(l); - } - - if(opts._fillgradient) { - fillLevels = [0]; - } else if(typeof opts._fillcolor === 'function') { - var fillLevelsIn = opts._filllevels; - - if(fillLevelsIn) { - l0 = fillLevelsIn.end + fillLevelsIn.size / 100; - ls = fillLevelsIn.size; - for(i = 0; i < 1e5; i++) { - l = fillLevelsIn.start + i * ls; - if(ls > 0 ? (l >= l0) : (l <= l0)) break; - if(l > zrange[0] && l < zrange[1]) fillLevels.push(l); - } - } else { - fillLevels = lineLevels.map(function(v) { - return v - levelsIn.size / 2; - }); - fillLevels.push(fillLevels[fillLevels.length - 1] + levelsIn.size); - } - } else if(opts._fillcolor && typeof opts._fillcolor === 'string') { - // doesn't matter what this value is, with a single value - // we'll make a single fill rect covering the whole bar - fillLevels = [0]; - } - - if(levelsIn.size < 0) { - lineLevels.reverse(); - fillLevels.reverse(); - } - - return {line: lineLevels, fill: fillLevels}; -} - -function mockColorBarAxis(gd, opts, zrange) { - var fullLayout = gd._fullLayout; - - var cbAxisIn = { - type: 'linear', - range: zrange, - tickmode: opts.tickmode, - nticks: opts.nticks, - tick0: opts.tick0, - dtick: opts.dtick, - tickvals: opts.tickvals, - ticktext: opts.ticktext, - ticks: opts.ticks, - ticklen: opts.ticklen, - tickwidth: opts.tickwidth, - tickcolor: opts.tickcolor, - showticklabels: opts.showticklabels, - tickfont: opts.tickfont, - tickangle: opts.tickangle, - tickformat: opts.tickformat, - exponentformat: opts.exponentformat, - separatethousands: opts.separatethousands, - showexponent: opts.showexponent, - showtickprefix: opts.showtickprefix, - tickprefix: opts.tickprefix, - showticksuffix: opts.showticksuffix, - ticksuffix: opts.ticksuffix, - title: opts.title, - showline: true, - anchor: 'free', - side: 'right', - position: 1 - }; - - var cbAxisOut = { - type: 'linear', - _id: 'y' + opts._id - }; - - var axisOptions = { - letter: 'y', - font: fullLayout.font, - noHover: true, - noTickson: true, - calendar: fullLayout.calendar // not really necessary (yet?) - }; - - function coerce(attr, dflt) { - return Lib.coerce(cbAxisIn, cbAxisOut, axisLayoutAttrs, attr, dflt); - } - - handleAxisDefaults(cbAxisIn, cbAxisOut, coerce, axisOptions, fullLayout); - handleAxisPositionDefaults(cbAxisIn, cbAxisOut, coerce, axisOptions); - - return cbAxisOut; -} - -module.exports = { - draw: draw -}; - -},{"../../constants/alignment":688,"../../lib":719,"../../lib/extend":710,"../../lib/setcursor":739,"../../lib/svg_text_utils":743,"../../plots/cartesian/axes":767,"../../plots/cartesian/axis_defaults":769,"../../plots/cartesian/layout_attributes":779,"../../plots/cartesian/position_defaults":782,"../../plots/plots":828,"../../registry":847,"../color":593,"../colorscale/helpers":604,"../dragelement":611,"../drawing":614,"../titles":681,"./constants":595,"d3":163,"tinycolor2":537}],598:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - - -module.exports = function hasColorbar(container) { - return Lib.isPlainObject(container.colorbar); -}; - -},{"../../lib":719}],599:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'component', - name: 'colorbar', - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - - draw: _dereq_('./draw').draw, - hasColorbar: _dereq_('./has_colorbar') -}; - -},{"./attributes":594,"./defaults":596,"./draw":597,"./has_colorbar":598}],600:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorbarAttrs = _dereq_('../colorbar/attributes'); -var counterRegex = _dereq_('../../lib/regex').counter; - -var palettes = _dereq_('./scales.js').scales; -var paletteStr = Object.keys(palettes); - -function code(s) { - return '`' + s + '`'; -} - -/** - * Make colorscale attribute declarations for - * - * - colorscale, - * - (c|z)auto, (c|z)min, (c|z)max, - * - autocolorscale, reversescale, - * - showscale (optionally) - * - color (optionally) - * - * @param {string} context (dflt: '', i.e. from trace root): - * the container this is in ('', *marker*, *marker.line* etc) - * - * @param {object} opts: - * - cLetter {string} (dflt: 'c'): - * leading letter for 'min', 'max and 'auto' attribute (either 'z' or 'c') - * - * - colorAttr {string} (dflt: 'z' if `cLetter: 'z'`, 'color' if `cLetter: 'c'`): - * (for descriptions) sets the name of the color attribute that maps to the colorscale. - * - * N.B. if `colorAttr: 'color'`, we include the `color` declaration here. - * - * - onlyIfNumerical {string} (dflt: false' if `cLetter: 'z'`, true if `cLetter: 'c'`): - * (for descriptions) set to true if colorscale attribute only - * - * - colorscaleDflt {string}: - * overrides the colorscale dflt - * - * - autoColorDflt {boolean} (dflt true): - * normally autocolorscale.dflt is `true`, but pass `false` to override - * - * - noScale {boolean} (dflt: true if `context: 'marker.line'`, false otherwise): - * set to `false` to not include showscale attribute (e.g. for 'marker.line') - * - * - showScaleDflt {boolean} (dflt: true if `cLetter: 'z'`, false otherwise) - * - * - editTypeOverride {boolean} (dflt: ''): - * most of these attributes already require a recalc, but the ones that do not - * have editType *style* or *plot* unless you override (presumably with *calc*) - * - * - anim {boolean) (dflt: undefined): is 'color' animatable? - * - * @return {object} - */ -module.exports = function colorScaleAttrs(context, opts) { - context = context || ''; - opts = opts || {}; - - var cLetter = opts.cLetter || 'c'; - var onlyIfNumerical = ('onlyIfNumerical' in opts) ? opts.onlyIfNumerical : Boolean(context); - var noScale = ('noScale' in opts) ? opts.noScale : context === 'marker.line'; - var showScaleDflt = ('showScaleDflt' in opts) ? opts.showScaleDflt : cLetter === 'z'; - var colorscaleDflt = typeof opts.colorscaleDflt === 'string' ? palettes[opts.colorscaleDflt] : null; - var editTypeOverride = opts.editTypeOverride || ''; - var contextHead = context ? (context + '.') : ''; - - var colorAttr, colorAttrFull; - - if('colorAttr' in opts) { - colorAttr = opts.colorAttr; - colorAttrFull = opts.colorAttr; - } else { - colorAttr = {z: 'z', c: 'color'}[cLetter]; - colorAttrFull = 'in ' + code(contextHead + colorAttr); - } - - var effectDesc = onlyIfNumerical ? - ' Has an effect only if ' + colorAttrFull + 'is set to a numerical array.' : - ''; - - var auto = cLetter + 'auto'; - var min = cLetter + 'min'; - var max = cLetter + 'max'; - var mid = cLetter + 'mid'; - var autoFull = code(contextHead + auto); - var minFull = code(contextHead + min); - var maxFull = code(contextHead + max); - var minmaxFull = minFull + ' and ' + maxFull; - var autoImpliedEdits = {}; - autoImpliedEdits[min] = autoImpliedEdits[max] = undefined; - var minmaxImpliedEdits = {}; - minmaxImpliedEdits[auto] = false; - - var attrs = {}; - - if(colorAttr === 'color') { - attrs.color = { - valType: 'color', - arrayOk: true, - - editType: editTypeOverride || 'style', - - }; - - if(opts.anim) { - attrs.color.anim = true; - } - } - - attrs[auto] = { - valType: 'boolean', - - dflt: true, - editType: 'calc', - impliedEdits: autoImpliedEdits, - - }; - - attrs[min] = { - valType: 'number', - - dflt: null, - editType: editTypeOverride || 'plot', - impliedEdits: minmaxImpliedEdits, - - }; - - attrs[max] = { - valType: 'number', - - dflt: null, - editType: editTypeOverride || 'plot', - impliedEdits: minmaxImpliedEdits, - - }; - - attrs[mid] = { - valType: 'number', - - dflt: null, - editType: 'calc', - impliedEdits: autoImpliedEdits, - - }; - - attrs.colorscale = { - valType: 'colorscale', - - editType: 'calc', - dflt: colorscaleDflt, - impliedEdits: {autocolorscale: false}, - - }; - - attrs.autocolorscale = { - valType: 'boolean', - - // gets overrode in 'heatmap' & 'surface' for backwards comp. - dflt: opts.autoColorDflt === false ? false : true, - editType: 'calc', - impliedEdits: {colorscale: undefined}, - - }; - - attrs.reversescale = { - valType: 'boolean', - - dflt: false, - editType: 'plot', - - }; - - if(!noScale) { - attrs.showscale = { - valType: 'boolean', - - dflt: showScaleDflt, - editType: 'calc', - - }; - - attrs.colorbar = colorbarAttrs; - } - - if(!opts.noColorAxis) { - attrs.coloraxis = { - valType: 'subplotid', - - regex: counterRegex('coloraxis'), - dflt: null, - editType: 'calc', - - }; - } - - return attrs; -}; - -},{"../../lib/regex":735,"../colorbar/attributes":594,"./scales.js":608}],601:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var extractOpts = _dereq_('./helpers').extractOpts; - -module.exports = function calc(gd, trace, opts) { - var fullLayout = gd._fullLayout; - var vals = opts.vals; - var containerStr = opts.containerStr; - - var container = containerStr ? - Lib.nestedProperty(trace, containerStr).get() : - trace; - - var cOpts = extractOpts(container); - var auto = cOpts.auto !== false; - var min = cOpts.min; - var max = cOpts.max; - var mid = cOpts.mid; - - var minVal = function() { return Lib.aggNums(Math.min, null, vals); }; - var maxVal = function() { return Lib.aggNums(Math.max, null, vals); }; - - if(min === undefined) { - min = minVal(); - } else if(auto) { - if(container._colorAx && isNumeric(min)) { - min = Math.min(min, minVal()); - } else { - min = minVal(); - } - } - - if(max === undefined) { - max = maxVal(); - } else if(auto) { - if(container._colorAx && isNumeric(max)) { - max = Math.max(max, maxVal()); - } else { - max = maxVal(); - } - } - - if(auto && mid !== undefined) { - if(max - mid > mid - min) { - min = mid - (max - mid); - } else if(max - mid < mid - min) { - max = mid + (mid - min); - } - } - - if(min === max) { - min -= 0.5; - max += 0.5; - } - - cOpts._sync('min', min); - cOpts._sync('max', max); - - if(cOpts.autocolorscale) { - var scl; - if(min * max < 0) scl = fullLayout.colorscale.diverging; - else if(min >= 0) scl = fullLayout.colorscale.sequential; - else scl = fullLayout.colorscale.sequentialminus; - cOpts._sync('colorscale', scl); - } -}; - -},{"../../lib":719,"./helpers":604,"fast-isnumeric":225}],602:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var hasColorscale = _dereq_('./helpers').hasColorscale; -var extractOpts = _dereq_('./helpers').extractOpts; - -module.exports = function crossTraceDefaults(fullData, fullLayout) { - function replace(cont, k) { - var val = cont['_' + k]; - if(val !== undefined) { - cont[k] = val; - } - } - - function relinkColorAtts(outerCont, cbOpt) { - var cont = cbOpt.container ? - Lib.nestedProperty(outerCont, cbOpt.container).get() : - outerCont; - - if(cont) { - if(cont.coloraxis) { - // stash ref to color axis - cont._colorAx = fullLayout[cont.coloraxis]; - } else { - var cOpts = extractOpts(cont); - var isAuto = cOpts.auto; - - if(isAuto || cOpts.min === undefined) { - replace(cont, cbOpt.min); - } - if(isAuto || cOpts.max === undefined) { - replace(cont, cbOpt.max); - } - if(cOpts.autocolorscale) { - replace(cont, 'colorscale'); - } - } - } - } - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - var cbOpts = trace._module.colorbar; - - if(cbOpts) { - if(Array.isArray(cbOpts)) { - for(var j = 0; j < cbOpts.length; j++) { - relinkColorAtts(trace, cbOpts[j]); - } - } else { - relinkColorAtts(trace, cbOpts); - } - } - - if(hasColorscale(trace, 'marker.line')) { - relinkColorAtts(trace, { - container: 'marker.line', - min: 'cmin', - max: 'cmax' - }); - } - } - - for(var k in fullLayout._colorAxes) { - relinkColorAtts(fullLayout[k], {min: 'cmin', max: 'cmax'}); - } -}; - -},{"../../lib":719,"./helpers":604}],603:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var hasColorbar = _dereq_('../colorbar/has_colorbar'); -var colorbarDefaults = _dereq_('../colorbar/defaults'); - -var isValidScale = _dereq_('./scales').isValid; -var traceIs = _dereq_('../../registry').traceIs; - -function npMaybe(parentCont, prefix) { - var containerStr = prefix.slice(0, prefix.length - 1); - return prefix ? - Lib.nestedProperty(parentCont, containerStr).get() || {} : - parentCont; -} - -/** - * Colorscale / colorbar default handler - * - * @param {object} parentContIn : user (input) parent container (e.g. trace or layout coloraxis object) - * @param {object} parentContOut : full parent container - * @param {object} layout : (full) layout object - * @param {fn} coerce : Lib.coerce wrapper - * @param {object} opts : - * - prefix {string} : attr string prefix to colorscale container from parent root - * - cLetter {string} : 'c or 'z' color letter - */ -module.exports = function colorScaleDefaults(parentContIn, parentContOut, layout, coerce, opts) { - var prefix = opts.prefix; - var cLetter = opts.cLetter; - var inTrace = '_module' in parentContOut; - var containerIn = npMaybe(parentContIn, prefix); - var containerOut = npMaybe(parentContOut, prefix); - var template = npMaybe(parentContOut._template || {}, prefix) || {}; - - // colorScaleDefaults wrapper called if-ever we need to reset the colorscale - // attributes for containers that were linked to invalid color axes - var thisFn = function() { - delete parentContIn.coloraxis; - delete parentContOut.coloraxis; - return colorScaleDefaults(parentContIn, parentContOut, layout, coerce, opts); - }; - - if(inTrace) { - var colorAxes = layout._colorAxes || {}; - var colorAx = coerce(prefix + 'coloraxis'); - - if(colorAx) { - var colorbarVisuals = ( - traceIs(parentContOut, 'contour') && - Lib.nestedProperty(parentContOut, 'contours.coloring').get() - ) || 'heatmap'; - - var stash = colorAxes[colorAx]; - - if(stash) { - stash[2].push(thisFn); - - if(stash[0] !== colorbarVisuals) { - stash[0] = false; - Lib.warn([ - 'Ignoring coloraxis:', colorAx, 'setting', - 'as it is linked to incompatible colorscales.' - ].join(' ')); - } - } else { - // stash: - // - colorbar visual 'type' - // - colorbar options to help in Colorbar.draw - // - list of colorScaleDefaults wrapper functions - colorAxes[colorAx] = [colorbarVisuals, parentContOut, [thisFn]]; - } - return; - } - } - - var minIn = containerIn[cLetter + 'min']; - var maxIn = containerIn[cLetter + 'max']; - var validMinMax = isNumeric(minIn) && isNumeric(maxIn) && (minIn < maxIn); - var auto = coerce(prefix + cLetter + 'auto', !validMinMax); - - if(auto) { - coerce(prefix + cLetter + 'mid'); - } else { - coerce(prefix + cLetter + 'min'); - coerce(prefix + cLetter + 'max'); - } - - // handles both the trace case (autocolorscale is false by default) and - // the marker and marker.line case (autocolorscale is true by default) - var sclIn = containerIn.colorscale; - var sclTemplate = template.colorscale; - var autoColorscaleDflt; - if(sclIn !== undefined) autoColorscaleDflt = !isValidScale(sclIn); - if(sclTemplate !== undefined) autoColorscaleDflt = !isValidScale(sclTemplate); - coerce(prefix + 'autocolorscale', autoColorscaleDflt); - - coerce(prefix + 'colorscale'); - coerce(prefix + 'reversescale'); - - if(prefix !== 'marker.line.') { - // handles both the trace case where the dflt is listed in attributes and - // the marker case where the dflt is determined by hasColorbar - var showScaleDflt; - if(prefix && inTrace) showScaleDflt = hasColorbar(containerIn); - - var showScale = coerce(prefix + 'showscale', showScaleDflt); - if(showScale) colorbarDefaults(containerIn, containerOut, layout); - } -}; - -},{"../../lib":719,"../../registry":847,"../colorbar/defaults":596,"../colorbar/has_colorbar":598,"./scales":608,"fast-isnumeric":225}],604:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var tinycolor = _dereq_('tinycolor2'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../color'); - -var isValidScale = _dereq_('./scales').isValid; - -function hasColorscale(trace, containerStr) { - var container = containerStr ? - Lib.nestedProperty(trace, containerStr).get() || {} : - trace; - var color = container.color; - - var isArrayWithOneNumber = false; - if(Lib.isArrayOrTypedArray(color)) { - for(var i = 0; i < color.length; i++) { - if(isNumeric(color[i])) { - isArrayWithOneNumber = true; - break; - } - } - } - - return ( - Lib.isPlainObject(container) && ( - isArrayWithOneNumber || - container.showscale === true || - (isNumeric(container.cmin) && isNumeric(container.cmax)) || - isValidScale(container.colorscale) || - Lib.isPlainObject(container.colorbar) - ) - ); -} - -var constantAttrs = ['showscale', 'autocolorscale', 'colorscale', 'reversescale', 'colorbar']; -var letterAttrs = ['min', 'max', 'mid', 'auto']; - -/** - * Extract 'c' / 'z', trace / color axis colorscale options - * - * Note that it would be nice to replace all z* with c* equivalents in v2 - * - * @param {object} cont : attribute container - * @return {object}: - * - min: cmin or zmin - * - max: cmax or zmax - * - mid: cmid or zmid - * - auto: cauto or zauto - * - *scale: *scale attrs - * - colorbar: colorbar - * - _sync: function syncing attr and underscore dual (useful when calc'ing min/max) - */ -function extractOpts(cont) { - var colorAx = cont._colorAx; - var cont2 = colorAx ? colorAx : cont; - var out = {}; - var cLetter; - var i, k; - - for(i = 0; i < constantAttrs.length; i++) { - k = constantAttrs[i]; - out[k] = cont2[k]; - } - - if(colorAx) { - cLetter = 'c'; - for(i = 0; i < letterAttrs.length; i++) { - k = letterAttrs[i]; - out[k] = cont2['c' + k]; - } - } else { - var k2; - for(i = 0; i < letterAttrs.length; i++) { - k = letterAttrs[i]; - k2 = 'c' + k; - if(k2 in cont2) { - out[k] = cont2[k2]; - continue; - } - k2 = 'z' + k; - if(k2 in cont2) { - out[k] = cont2[k2]; - } - } - cLetter = k2.charAt(0); - } - - out._sync = function(k, v) { - var k2 = letterAttrs.indexOf(k) !== -1 ? cLetter + k : k; - cont2[k2] = cont2['_' + k2] = v; - }; - - return out; -} - -/** - * Extract colorscale into numeric domain and color range. - * - * @param {object} cont colorscale container (e.g. trace, marker) - * - colorscale {array of arrays} - * - cmin/zmin {number} - * - cmax/zmax {number} - * - reversescale {boolean} - * - * @return {object} - * - domain {array} - * - range {array} - */ -function extractScale(cont) { - var cOpts = extractOpts(cont); - var cmin = cOpts.min; - var cmax = cOpts.max; - - var scl = cOpts.reversescale ? - flipScale(cOpts.colorscale) : - cOpts.colorscale; - - var N = scl.length; - var domain = new Array(N); - var range = new Array(N); - - for(var i = 0; i < N; i++) { - var si = scl[i]; - domain[i] = cmin + si[0] * (cmax - cmin); - range[i] = si[1]; - } - - return {domain: domain, range: range}; -} - -function flipScale(scl) { - var N = scl.length; - var sclNew = new Array(N); - - for(var i = N - 1, j = 0; i >= 0; i--, j++) { - var si = scl[i]; - sclNew[j] = [1 - si[0], si[1]]; - } - return sclNew; -} - -/** - * General colorscale function generator. - * - * @param {object} specs output of Colorscale.extractScale or precomputed domain, range. - * - domain {array} - * - range {array} - * - * @param {object} opts - * - noNumericCheck {boolean} if true, scale func bypasses numeric checks - * - returnArray {boolean} if true, scale func return 4-item array instead of color strings - * - * @return {function} - */ -function makeColorScaleFunc(specs, opts) { - opts = opts || {}; - - var domain = specs.domain; - var range = specs.range; - var N = range.length; - var _range = new Array(N); - - for(var i = 0; i < N; i++) { - var rgba = tinycolor(range[i]).toRgb(); - _range[i] = [rgba.r, rgba.g, rgba.b, rgba.a]; - } - - var _sclFunc = d3.scale.linear() - .domain(domain) - .range(_range) - .clamp(true); - - var noNumericCheck = opts.noNumericCheck; - var returnArray = opts.returnArray; - var sclFunc; - - if(noNumericCheck && returnArray) { - sclFunc = _sclFunc; - } else if(noNumericCheck) { - sclFunc = function(v) { - return colorArray2rbga(_sclFunc(v)); - }; - } else if(returnArray) { - sclFunc = function(v) { - if(isNumeric(v)) return _sclFunc(v); - else if(tinycolor(v).isValid()) return v; - else return Color.defaultLine; - }; - } else { - sclFunc = function(v) { - if(isNumeric(v)) return colorArray2rbga(_sclFunc(v)); - else if(tinycolor(v).isValid()) return v; - else return Color.defaultLine; - }; - } - - // colorbar draw looks into the d3 scale closure for domain and range - sclFunc.domain = _sclFunc.domain; - sclFunc.range = function() { return range; }; - - return sclFunc; -} - -function makeColorScaleFuncFromTrace(trace, opts) { - return makeColorScaleFunc(extractScale(trace), opts); -} - -function colorArray2rbga(colorArray) { - var colorObj = { - r: colorArray[0], - g: colorArray[1], - b: colorArray[2], - a: colorArray[3] - }; - - return tinycolor(colorObj).toRgbString(); -} - -module.exports = { - hasColorscale: hasColorscale, - extractOpts: extractOpts, - extractScale: extractScale, - flipScale: flipScale, - makeColorScaleFunc: makeColorScaleFunc, - makeColorScaleFuncFromTrace: makeColorScaleFuncFromTrace -}; - -},{"../../lib":719,"../color":593,"./scales":608,"d3":163,"fast-isnumeric":225,"tinycolor2":537}],605:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scales = _dereq_('./scales'); -var helpers = _dereq_('./helpers'); - -module.exports = { - moduleType: 'component', - name: 'colorscale', - - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('./layout_attributes'), - - supplyLayoutDefaults: _dereq_('./layout_defaults'), - handleDefaults: _dereq_('./defaults'), - crossTraceDefaults: _dereq_('./cross_trace_defaults'), - - calc: _dereq_('./calc'), - - // ./scales.js is required in lib/coerce.js ; - // it needs to be a seperate module to avoid circular a dependency - scales: scales.scales, - defaultScale: scales.defaultScale, - getScale: scales.get, - isValidScale: scales.isValid, - - hasColorscale: helpers.hasColorscale, - extractOpts: helpers.extractOpts, - extractScale: helpers.extractScale, - flipScale: helpers.flipScale, - makeColorScaleFunc: helpers.makeColorScaleFunc, - makeColorScaleFuncFromTrace: helpers.makeColorScaleFuncFromTrace -}; - -},{"./attributes":600,"./calc":601,"./cross_trace_defaults":602,"./defaults":603,"./helpers":604,"./layout_attributes":606,"./layout_defaults":607,"./scales":608}],606:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var colorScaleAttrs = _dereq_('./attributes'); -var scales = _dereq_('./scales').scales; - -var msg = 'Note that `autocolorscale` must be true for this attribute to work.'; - -module.exports = { - editType: 'calc', - - colorscale: { - editType: 'calc', - - sequential: { - valType: 'colorscale', - dflt: scales.Reds, - - editType: 'calc', - - }, - sequentialminus: { - valType: 'colorscale', - dflt: scales.Blues, - - editType: 'calc', - - }, - diverging: { - valType: 'colorscale', - dflt: scales.RdBu, - - editType: 'calc', - - } - }, - - coloraxis: extendFlat({ - // not really a 'subplot' attribute container, - // but this is the flag we use to denote attributes that - // support yaxis, yaxis2, yaxis3, ... counters - _isSubplotObj: true, - editType: 'calc', - - }, colorScaleAttrs('', { - colorAttr: 'corresponding trace color array(s)', - noColorAxis: true, - showScaleDflt: true - })) -}; - -},{"../../lib/extend":710,"./attributes":600,"./scales":608}],607:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Template = _dereq_('../../plot_api/plot_template'); - -var colorScaleAttrs = _dereq_('./layout_attributes'); -var colorScaleDefaults = _dereq_('./defaults'); - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, colorScaleAttrs, attr, dflt); - } - - coerce('colorscale.sequential'); - coerce('colorscale.sequentialminus'); - coerce('colorscale.diverging'); - - var colorAxes = layoutOut._colorAxes; - var colorAxIn, colorAxOut; - - function coerceAx(attr, dflt) { - return Lib.coerce(colorAxIn, colorAxOut, colorScaleAttrs.coloraxis, attr, dflt); - } - - for(var k in colorAxes) { - var stash = colorAxes[k]; - - if(stash[0]) { - colorAxIn = layoutIn[k] || {}; - colorAxOut = Template.newContainer(layoutOut, k, 'coloraxis'); - colorAxOut._name = k; - colorScaleDefaults(colorAxIn, colorAxOut, layoutOut, coerceAx, {prefix: '', cLetter: 'c'}); - } else { - // re-coerce colorscale attributes w/o coloraxis - for(var i = 0; i < stash[2].length; i++) { - stash[2][i](); - } - delete layoutOut._colorAxes[k]; - } - } -}; - -},{"../../lib":719,"../../plot_api/plot_template":757,"./defaults":603,"./layout_attributes":606}],608:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var tinycolor = _dereq_('tinycolor2'); - -var scales = { - 'Greys': [ - [0, 'rgb(0,0,0)'], [1, 'rgb(255,255,255)'] - ], - - 'YlGnBu': [ - [0, 'rgb(8,29,88)'], [0.125, 'rgb(37,52,148)'], - [0.25, 'rgb(34,94,168)'], [0.375, 'rgb(29,145,192)'], - [0.5, 'rgb(65,182,196)'], [0.625, 'rgb(127,205,187)'], - [0.75, 'rgb(199,233,180)'], [0.875, 'rgb(237,248,217)'], - [1, 'rgb(255,255,217)'] - ], - - 'Greens': [ - [0, 'rgb(0,68,27)'], [0.125, 'rgb(0,109,44)'], - [0.25, 'rgb(35,139,69)'], [0.375, 'rgb(65,171,93)'], - [0.5, 'rgb(116,196,118)'], [0.625, 'rgb(161,217,155)'], - [0.75, 'rgb(199,233,192)'], [0.875, 'rgb(229,245,224)'], - [1, 'rgb(247,252,245)'] - ], - - 'YlOrRd': [ - [0, 'rgb(128,0,38)'], [0.125, 'rgb(189,0,38)'], - [0.25, 'rgb(227,26,28)'], [0.375, 'rgb(252,78,42)'], - [0.5, 'rgb(253,141,60)'], [0.625, 'rgb(254,178,76)'], - [0.75, 'rgb(254,217,118)'], [0.875, 'rgb(255,237,160)'], - [1, 'rgb(255,255,204)'] - ], - - 'Bluered': [ - [0, 'rgb(0,0,255)'], [1, 'rgb(255,0,0)'] - ], - - // modified RdBu based on - // http://www.kennethmoreland.com/color-maps/ - 'RdBu': [ - [0, 'rgb(5,10,172)'], [0.35, 'rgb(106,137,247)'], - [0.5, 'rgb(190,190,190)'], [0.6, 'rgb(220,170,132)'], - [0.7, 'rgb(230,145,90)'], [1, 'rgb(178,10,28)'] - ], - - // Scale for non-negative numeric values - 'Reds': [ - [0, 'rgb(220,220,220)'], [0.2, 'rgb(245,195,157)'], - [0.4, 'rgb(245,160,105)'], [1, 'rgb(178,10,28)'] - ], - - // Scale for non-positive numeric values - 'Blues': [ - [0, 'rgb(5,10,172)'], [0.35, 'rgb(40,60,190)'], - [0.5, 'rgb(70,100,245)'], [0.6, 'rgb(90,120,245)'], - [0.7, 'rgb(106,137,247)'], [1, 'rgb(220,220,220)'] - ], - - 'Picnic': [ - [0, 'rgb(0,0,255)'], [0.1, 'rgb(51,153,255)'], - [0.2, 'rgb(102,204,255)'], [0.3, 'rgb(153,204,255)'], - [0.4, 'rgb(204,204,255)'], [0.5, 'rgb(255,255,255)'], - [0.6, 'rgb(255,204,255)'], [0.7, 'rgb(255,153,255)'], - [0.8, 'rgb(255,102,204)'], [0.9, 'rgb(255,102,102)'], - [1, 'rgb(255,0,0)'] - ], - - 'Rainbow': [ - [0, 'rgb(150,0,90)'], [0.125, 'rgb(0,0,200)'], - [0.25, 'rgb(0,25,255)'], [0.375, 'rgb(0,152,255)'], - [0.5, 'rgb(44,255,150)'], [0.625, 'rgb(151,255,0)'], - [0.75, 'rgb(255,234,0)'], [0.875, 'rgb(255,111,0)'], - [1, 'rgb(255,0,0)'] - ], - - 'Portland': [ - [0, 'rgb(12,51,131)'], [0.25, 'rgb(10,136,186)'], - [0.5, 'rgb(242,211,56)'], [0.75, 'rgb(242,143,56)'], - [1, 'rgb(217,30,30)'] - ], - - 'Jet': [ - [0, 'rgb(0,0,131)'], [0.125, 'rgb(0,60,170)'], - [0.375, 'rgb(5,255,255)'], [0.625, 'rgb(255,255,0)'], - [0.875, 'rgb(250,0,0)'], [1, 'rgb(128,0,0)'] - ], - - 'Hot': [ - [0, 'rgb(0,0,0)'], [0.3, 'rgb(230,0,0)'], - [0.6, 'rgb(255,210,0)'], [1, 'rgb(255,255,255)'] - ], - - 'Blackbody': [ - [0, 'rgb(0,0,0)'], [0.2, 'rgb(230,0,0)'], - [0.4, 'rgb(230,210,0)'], [0.7, 'rgb(255,255,255)'], - [1, 'rgb(160,200,255)'] - ], - - 'Earth': [ - [0, 'rgb(0,0,130)'], [0.1, 'rgb(0,180,180)'], - [0.2, 'rgb(40,210,40)'], [0.4, 'rgb(230,230,50)'], - [0.6, 'rgb(120,70,20)'], [1, 'rgb(255,255,255)'] - ], - - 'Electric': [ - [0, 'rgb(0,0,0)'], [0.15, 'rgb(30,0,100)'], - [0.4, 'rgb(120,0,100)'], [0.6, 'rgb(160,90,0)'], - [0.8, 'rgb(230,200,0)'], [1, 'rgb(255,250,220)'] - ], - - 'Viridis': [ - [0, '#440154'], [0.06274509803921569, '#48186a'], - [0.12549019607843137, '#472d7b'], [0.18823529411764706, '#424086'], - [0.25098039215686274, '#3b528b'], [0.3137254901960784, '#33638d'], - [0.3764705882352941, '#2c728e'], [0.4392156862745098, '#26828e'], - [0.5019607843137255, '#21918c'], [0.5647058823529412, '#1fa088'], - [0.6274509803921569, '#28ae80'], [0.6901960784313725, '#3fbc73'], - [0.7529411764705882, '#5ec962'], [0.8156862745098039, '#84d44b'], - [0.8784313725490196, '#addc30'], [0.9411764705882353, '#d8e219'], - [1, '#fde725'] - ], - - 'Cividis': [ - [0.000000, 'rgb(0,32,76)'], [0.058824, 'rgb(0,42,102)'], - [0.117647, 'rgb(0,52,110)'], [0.176471, 'rgb(39,63,108)'], - [0.235294, 'rgb(60,74,107)'], [0.294118, 'rgb(76,85,107)'], - [0.352941, 'rgb(91,95,109)'], [0.411765, 'rgb(104,106,112)'], - [0.470588, 'rgb(117,117,117)'], [0.529412, 'rgb(131,129,120)'], - [0.588235, 'rgb(146,140,120)'], [0.647059, 'rgb(161,152,118)'], - [0.705882, 'rgb(176,165,114)'], [0.764706, 'rgb(192,177,109)'], - [0.823529, 'rgb(209,191,102)'], [0.882353, 'rgb(225,204,92)'], - [0.941176, 'rgb(243,219,79)'], [1.000000, 'rgb(255,233,69)'] - ] -}; - -var defaultScale = scales.RdBu; - -function getScale(scl, dflt) { - if(!dflt) dflt = defaultScale; - if(!scl) return dflt; - - function parseScale() { - try { - scl = scales[scl] || JSON.parse(scl); - } catch(e) { - scl = dflt; - } - } - - if(typeof scl === 'string') { - parseScale(); - // occasionally scl is double-JSON encoded... - if(typeof scl === 'string') parseScale(); - } - - if(!isValidScaleArray(scl)) return dflt; - return scl; -} - - -function isValidScaleArray(scl) { - var highestVal = 0; - - if(!Array.isArray(scl) || scl.length < 2) return false; - - if(!scl[0] || !scl[scl.length - 1]) return false; - - if(+scl[0][0] !== 0 || +scl[scl.length - 1][0] !== 1) return false; - - for(var i = 0; i < scl.length; i++) { - var si = scl[i]; - - if(si.length !== 2 || +si[0] < highestVal || !tinycolor(si[1]).isValid()) { - return false; - } - - highestVal = +si[0]; - } - - return true; -} - -function isValidScale(scl) { - if(scales[scl] !== undefined) return true; - else return isValidScaleArray(scl); -} - -module.exports = { - scales: scales, - defaultScale: defaultScale, - - get: getScale, - isValid: isValidScale -}; - -},{"tinycolor2":537}],609:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -// for automatic alignment on dragging, <1/3 means left align, -// >2/3 means right, and between is center. Pick the right fraction -// based on where you are, and return the fraction corresponding to -// that position on the object -module.exports = function align(v, dv, v0, v1, anchor) { - var vmin = (v - v0) / (v1 - v0); - var vmax = vmin + dv / (v1 - v0); - var vc = (vmin + vmax) / 2; - - // explicitly specified anchor - if(anchor === 'left' || anchor === 'bottom') return vmin; - if(anchor === 'center' || anchor === 'middle') return vc; - if(anchor === 'right' || anchor === 'top') return vmax; - - // automatic based on position - if(vmin < (2 / 3) - vc) return vmin; - if(vmax > (4 / 3) - vc) return vmax; - return vc; -}; - -},{}],610:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - - -// set cursors pointing toward the closest corner/side, -// to indicate alignment -// x and y are 0-1, fractions of the plot area -var cursorset = [ - ['sw-resize', 's-resize', 'se-resize'], - ['w-resize', 'move', 'e-resize'], - ['nw-resize', 'n-resize', 'ne-resize'] -]; - -module.exports = function getCursor(x, y, xanchor, yanchor) { - if(xanchor === 'left') x = 0; - else if(xanchor === 'center') x = 1; - else if(xanchor === 'right') x = 2; - else x = Lib.constrain(Math.floor(x * 3), 0, 2); - - if(yanchor === 'bottom') y = 0; - else if(yanchor === 'middle') y = 1; - else if(yanchor === 'top') y = 2; - else y = Lib.constrain(Math.floor(y * 3), 0, 2); - - return cursorset[y][x]; -}; - -},{"../../lib":719}],611:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var mouseOffset = _dereq_('mouse-event-offset'); -var hasHover = _dereq_('has-hover'); -var supportsPassive = _dereq_('has-passive-events'); - -var removeElement = _dereq_('../../lib').removeElement; -var constants = _dereq_('../../plots/cartesian/constants'); - -var dragElement = module.exports = {}; - -dragElement.align = _dereq_('./align'); -dragElement.getCursor = _dereq_('./cursor'); - -var unhover = _dereq_('./unhover'); -dragElement.unhover = unhover.wrapped; -dragElement.unhoverRaw = unhover.raw; - -/** - * Abstracts click & drag interactions - * - * During the interaction, a "coverSlip" element - a transparent - * div covering the whole page - is created, which has two key effects: - * - Lets you drag beyond the boundaries of the plot itself without - * dropping (but if you drag all the way out of the browser window the - * interaction will end) - * - Freezes the cursor: whatever mouse cursor the drag element had when the - * interaction started gets copied to the coverSlip for use until mouseup - * - * If the user executes a drag bigger than MINDRAG, callbacks will fire as: - * prepFn, moveFn (1 or more times), doneFn - * If the user does not drag enough, prepFn and clickFn will fire. - * - * Note: If you cancel contextmenu, clickFn will fire even with a right click - * (unlike native events) so you'll get a `plotly_click` event. Cancel context eg: - * gd.addEventListener('contextmenu', function(e) { e.preventDefault(); }); - * TODO: we should probably turn this into a `config` parameter, so we can fix it - * such that if you *don't* cancel contextmenu, we can prevent partial drags, which - * put you in a weird state. - * - * If the user clicks multiple times quickly, clickFn will fire each time - * but numClicks will increase to help you recognize doubleclicks. - * - * @param {object} options with keys: - * element (required) the DOM element to drag - * prepFn (optional) function(event, startX, startY) - * executed on mousedown - * startX and startY are the clientX and clientY pixel position - * of the mousedown event - * moveFn (optional) function(dx, dy) - * executed on move, ONLY after we've exceeded MINDRAG - * (we keep executing moveFn if you move back to where you started) - * dx and dy are the net pixel offset of the drag, - * dragged is true/false, has the mouse moved enough to - * constitute a drag - * doneFn (optional) function(e) - * executed on mouseup, ONLY if we exceeded MINDRAG (so you can be - * sure that moveFn has been called at least once) - * numClicks is how many clicks we've registered within - * a doubleclick time - * e is the original mouseup event - * clickFn (optional) function(numClicks, e) - * executed on mouseup if we have NOT exceeded MINDRAG (ie moveFn - * has not been called at all) - * numClicks is how many clicks we've registered within - * a doubleclick time - * e is the original mousedown event - * clampFn (optional, function(dx, dy) return [dx2, dy2]) - * Provide custom clamping function for small displacements. - * By default, clamping is done using `minDrag` to x and y displacements - * independently. - */ -dragElement.init = function init(options) { - var gd = options.gd; - var numClicks = 1; - var doubleClickDelay = gd._context.doubleClickDelay; - var element = options.element; - - var startX, - startY, - newMouseDownTime, - cursor, - dragCover, - initialEvent, - initialTarget, - rightClick; - - if(!gd._mouseDownTime) gd._mouseDownTime = 0; - - element.style.pointerEvents = 'all'; - - element.onmousedown = onStart; - - if(!supportsPassive) { - element.ontouchstart = onStart; - } else { - if(element._ontouchstart) { - element.removeEventListener('touchstart', element._ontouchstart); - } - element._ontouchstart = onStart; - element.addEventListener('touchstart', onStart, {passive: false}); - } - - function _clampFn(dx, dy, minDrag) { - if(Math.abs(dx) < minDrag) dx = 0; - if(Math.abs(dy) < minDrag) dy = 0; - return [dx, dy]; - } - - var clampFn = options.clampFn || _clampFn; - - function onStart(e) { - // make dragging and dragged into properties of gd - // so that others can look at and modify them - gd._dragged = false; - gd._dragging = true; - var offset = pointerOffset(e); - startX = offset[0]; - startY = offset[1]; - initialTarget = e.target; - initialEvent = e; - rightClick = e.buttons === 2 || e.ctrlKey; - - // fix Fx.hover for touch events - if(typeof e.clientX === 'undefined' && typeof e.clientY === 'undefined') { - e.clientX = startX; - e.clientY = startY; - } - - newMouseDownTime = (new Date()).getTime(); - if(newMouseDownTime - gd._mouseDownTime < doubleClickDelay) { - // in a click train - numClicks += 1; - } else { - // new click train - numClicks = 1; - gd._mouseDownTime = newMouseDownTime; - } - - if(options.prepFn) options.prepFn(e, startX, startY); - - if(hasHover && !rightClick) { - dragCover = coverSlip(); - dragCover.style.cursor = window.getComputedStyle(element).cursor; - } else if(!hasHover) { - // document acts as a dragcover for mobile, bc we can't create dragcover dynamically - dragCover = document; - cursor = window.getComputedStyle(document.documentElement).cursor; - document.documentElement.style.cursor = window.getComputedStyle(element).cursor; - } - - document.addEventListener('mouseup', onDone); - document.addEventListener('touchend', onDone); - - if(options.dragmode !== false) { - e.preventDefault(); - document.addEventListener('mousemove', onMove); - document.addEventListener('touchmove', onMove); - } - - return; - } - - function onMove(e) { - e.preventDefault(); - - var offset = pointerOffset(e); - var minDrag = options.minDrag || constants.MINDRAG; - var dxdy = clampFn(offset[0] - startX, offset[1] - startY, minDrag); - var dx = dxdy[0]; - var dy = dxdy[1]; - - if(dx || dy) { - gd._dragged = true; - dragElement.unhover(gd); - } - - if(gd._dragged && options.moveFn && !rightClick) { - gd._dragdata = { - element: element, - dx: dx, - dy: dy - }; - options.moveFn(dx, dy); - } - - return; - } - - function onDone(e) { - delete gd._dragdata; - - if(options.dragmode !== false) { - e.preventDefault(); - document.removeEventListener('mousemove', onMove); - document.removeEventListener('touchmove', onMove); - } - - document.removeEventListener('mouseup', onDone); - document.removeEventListener('touchend', onDone); - - if(hasHover) { - removeElement(dragCover); - } else if(cursor) { - dragCover.documentElement.style.cursor = cursor; - cursor = null; - } - - if(!gd._dragging) { - gd._dragged = false; - return; - } - gd._dragging = false; - - // don't count as a dblClick unless the mouseUp is also within - // the dblclick delay - if((new Date()).getTime() - gd._mouseDownTime > doubleClickDelay) { - numClicks = Math.max(numClicks - 1, 1); - } - - if(gd._dragged) { - if(options.doneFn) options.doneFn(); - } else { - if(options.clickFn) options.clickFn(numClicks, initialEvent); - - // If we haven't dragged, this should be a click. But because of the - // coverSlip changing the element, the natural system might not generate one, - // so we need to make our own. But right clicks don't normally generate - // click events, only contextmenu events, which happen on mousedown. - if(!rightClick) { - var e2; - - try { - e2 = new MouseEvent('click', e); - } catch(err) { - var offset = pointerOffset(e); - e2 = document.createEvent('MouseEvents'); - e2.initMouseEvent('click', - e.bubbles, e.cancelable, - e.view, e.detail, - e.screenX, e.screenY, - offset[0], offset[1], - e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, - e.button, e.relatedTarget); - } - - initialTarget.dispatchEvent(e2); - } - } - - gd._dragging = false; - gd._dragged = false; - return; - } -}; - -function coverSlip() { - var cover = document.createElement('div'); - - cover.className = 'dragcover'; - var cStyle = cover.style; - cStyle.position = 'fixed'; - cStyle.left = 0; - cStyle.right = 0; - cStyle.top = 0; - cStyle.bottom = 0; - cStyle.zIndex = 999999999; - cStyle.background = 'none'; - - document.body.appendChild(cover); - - return cover; -} - -dragElement.coverSlip = coverSlip; - -function pointerOffset(e) { - return mouseOffset( - e.changedTouches ? e.changedTouches[0] : e, - document.body - ); -} - -},{"../../lib":719,"../../plots/cartesian/constants":773,"./align":609,"./cursor":610,"./unhover":612,"has-hover":410,"has-passive-events":411,"mouse-event-offset":436}],612:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Events = _dereq_('../../lib/events'); -var throttle = _dereq_('../../lib/throttle'); -var getGraphDiv = _dereq_('../../lib/dom').getGraphDiv; - -var hoverConstants = _dereq_('../fx/constants'); - -var unhover = module.exports = {}; - -unhover.wrapped = function(gd, evt, subplot) { - gd = getGraphDiv(gd); - - // Important, clear any queued hovers - if(gd._fullLayout) { - throttle.clear(gd._fullLayout._uid + hoverConstants.HOVERID); - } - - unhover.raw(gd, evt, subplot); -}; - - -// remove hover effects on mouse out, and emit unhover event -unhover.raw = function raw(gd, evt) { - var fullLayout = gd._fullLayout; - var oldhoverdata = gd._hoverdata; - - if(!evt) evt = {}; - if(evt.target && - Events.triggerHandler(gd, 'plotly_beforehover', evt) === false) { - return; - } - - fullLayout._hoverlayer.selectAll('g').remove(); - fullLayout._hoverlayer.selectAll('line').remove(); - fullLayout._hoverlayer.selectAll('circle').remove(); - gd._hoverdata = undefined; - - if(evt.target && oldhoverdata) { - gd.emit('plotly_unhover', { - event: evt, - points: oldhoverdata - }); - } -}; - -},{"../../lib/dom":708,"../../lib/events":709,"../../lib/throttle":744,"../fx/constants":626}],613:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -exports.dash = { - valType: 'string', - // string type usually doesn't take values... this one should really be - // a special type or at least a special coercion function, from the GUI - // you only get these values but elsewhere the user can supply a list of - // dash lengths in px, and it will be honored - values: ['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot'], - dflt: 'solid', - - editType: 'style', - -}; - -},{}],614:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); -var tinycolor = _dereq_('tinycolor2'); - -var Registry = _dereq_('../../registry'); -var Color = _dereq_('../color'); -var Colorscale = _dereq_('../colorscale'); -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); - -var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); -var alignment = _dereq_('../../constants/alignment'); -var LINE_SPACING = alignment.LINE_SPACING; -var DESELECTDIM = _dereq_('../../constants/interactions').DESELECTDIM; - -var subTypes = _dereq_('../../traces/scatter/subtypes'); -var makeBubbleSizeFn = _dereq_('../../traces/scatter/make_bubble_size_func'); - -var drawing = module.exports = {}; - -// ----------------------------------------------------- -// styling functions for plot elements -// ----------------------------------------------------- - -drawing.font = function(s, family, size, color) { - // also allow the form font(s, {family, size, color}) - if(Lib.isPlainObject(family)) { - color = family.color; - size = family.size; - family = family.family; - } - if(family) s.style('font-family', family); - if(size + 1) s.style('font-size', size + 'px'); - if(color) s.call(Color.fill, color); -}; - -/* - * Positioning helpers - * Note: do not use `setPosition` with nodes modified by - * `svgTextUtils.convertToTspans`. Use `svgTextUtils.positionText` - * instead, so that elements get updated to match. - */ -drawing.setPosition = function(s, x, y) { s.attr('x', x).attr('y', y); }; -drawing.setSize = function(s, w, h) { s.attr('width', w).attr('height', h); }; -drawing.setRect = function(s, x, y, w, h) { - s.call(drawing.setPosition, x, y).call(drawing.setSize, w, h); -}; - -/** Translate node - * - * @param {object} d : calcdata point item - * @param {sel} sel : d3 selction of node to translate - * @param {object} xa : corresponding full xaxis object - * @param {object} ya : corresponding full yaxis object - * - * @return {boolean} : - * true if selection got translated - * false if selection could not get translated - */ -drawing.translatePoint = function(d, sel, xa, ya) { - var x = xa.c2p(d.x); - var y = ya.c2p(d.y); - - if(isNumeric(x) && isNumeric(y) && sel.node()) { - // for multiline text this works better - if(sel.node().nodeName === 'text') { - sel.attr('x', x).attr('y', y); - } else { - sel.attr('transform', 'translate(' + x + ',' + y + ')'); - } - } else { - return false; - } - - return true; -}; - -drawing.translatePoints = function(s, xa, ya) { - s.each(function(d) { - var sel = d3.select(this); - drawing.translatePoint(d, sel, xa, ya); - }); -}; - -drawing.hideOutsideRangePoint = function(d, sel, xa, ya, xcalendar, ycalendar) { - sel.attr( - 'display', - (xa.isPtWithinRange(d, xcalendar) && ya.isPtWithinRange(d, ycalendar)) ? null : 'none' - ); -}; - -drawing.hideOutsideRangePoints = function(traceGroups, subplot) { - if(!subplot._hasClipOnAxisFalse) return; - - var xa = subplot.xaxis; - var ya = subplot.yaxis; - - traceGroups.each(function(d) { - var trace = d[0].trace; - var xcalendar = trace.xcalendar; - var ycalendar = trace.ycalendar; - var selector = Registry.traceIs(trace, 'bar-like') ? '.bartext' : '.point,.textpoint'; - - traceGroups.selectAll(selector).each(function(d) { - drawing.hideOutsideRangePoint(d, d3.select(this), xa, ya, xcalendar, ycalendar); - }); - }); -}; - -drawing.crispRound = function(gd, lineWidth, dflt) { - // for lines that disable antialiasing we want to - // make sure the width is an integer, and at least 1 if it's nonzero - - if(!lineWidth || !isNumeric(lineWidth)) return dflt || 0; - - // but not for static plots - these don't get antialiased anyway. - if(gd._context.staticPlot) return lineWidth; - - if(lineWidth < 1) return 1; - return Math.round(lineWidth); -}; - -drawing.singleLineStyle = function(d, s, lw, lc, ld) { - s.style('fill', 'none'); - var line = (((d || [])[0] || {}).trace || {}).line || {}; - var lw1 = lw || line.width || 0; - var dash = ld || line.dash || ''; - - Color.stroke(s, lc || line.color); - drawing.dashLine(s, dash, lw1); -}; - -drawing.lineGroupStyle = function(s, lw, lc, ld) { - s.style('fill', 'none') - .each(function(d) { - var line = (((d || [])[0] || {}).trace || {}).line || {}; - var lw1 = lw || line.width || 0; - var dash = ld || line.dash || ''; - - d3.select(this) - .call(Color.stroke, lc || line.color) - .call(drawing.dashLine, dash, lw1); - }); -}; - -drawing.dashLine = function(s, dash, lineWidth) { - lineWidth = +lineWidth || 0; - - dash = drawing.dashStyle(dash, lineWidth); - - s.style({ - 'stroke-dasharray': dash, - 'stroke-width': lineWidth + 'px' - }); -}; - -drawing.dashStyle = function(dash, lineWidth) { - lineWidth = +lineWidth || 1; - var dlw = Math.max(lineWidth, 3); - - if(dash === 'solid') dash = ''; - else if(dash === 'dot') dash = dlw + 'px,' + dlw + 'px'; - else if(dash === 'dash') dash = (3 * dlw) + 'px,' + (3 * dlw) + 'px'; - else if(dash === 'longdash') dash = (5 * dlw) + 'px,' + (5 * dlw) + 'px'; - else if(dash === 'dashdot') { - dash = (3 * dlw) + 'px,' + dlw + 'px,' + dlw + 'px,' + dlw + 'px'; - } else if(dash === 'longdashdot') { - dash = (5 * dlw) + 'px,' + (2 * dlw) + 'px,' + dlw + 'px,' + (2 * dlw) + 'px'; - } - // otherwise user wrote the dasharray themselves - leave it be - - return dash; -}; - -// Same as fillGroupStyle, except in this case the selection may be a transition -drawing.singleFillStyle = function(sel) { - var node = d3.select(sel.node()); - var data = node.data(); - var fillcolor = (((data[0] || [])[0] || {}).trace || {}).fillcolor; - if(fillcolor) { - sel.call(Color.fill, fillcolor); - } -}; - -drawing.fillGroupStyle = function(s) { - s.style('stroke-width', 0) - .each(function(d) { - var shape = d3.select(this); - // N.B. 'd' won't be a calcdata item when - // fill !== 'none' on a segment-less and marker-less trace - if(d[0].trace) { - shape.call(Color.fill, d[0].trace.fillcolor); - } - }); -}; - -var SYMBOLDEFS = _dereq_('./symbol_defs'); - -drawing.symbolNames = []; -drawing.symbolFuncs = []; -drawing.symbolNeedLines = {}; -drawing.symbolNoDot = {}; -drawing.symbolNoFill = {}; -drawing.symbolList = []; - -Object.keys(SYMBOLDEFS).forEach(function(k) { - var symDef = SYMBOLDEFS[k]; - drawing.symbolList = drawing.symbolList.concat( - [symDef.n, k, symDef.n + 100, k + '-open']); - drawing.symbolNames[symDef.n] = k; - drawing.symbolFuncs[symDef.n] = symDef.f; - if(symDef.needLine) { - drawing.symbolNeedLines[symDef.n] = true; - } - if(symDef.noDot) { - drawing.symbolNoDot[symDef.n] = true; - } else { - drawing.symbolList = drawing.symbolList.concat( - [symDef.n + 200, k + '-dot', symDef.n + 300, k + '-open-dot']); - } - if(symDef.noFill) { - drawing.symbolNoFill[symDef.n] = true; - } -}); - -var MAXSYMBOL = drawing.symbolNames.length; -// add a dot in the middle of the symbol -var DOTPATH = 'M0,0.5L0.5,0L0,-0.5L-0.5,0Z'; - -drawing.symbolNumber = function(v) { - if(typeof v === 'string') { - var vbase = 0; - if(v.indexOf('-open') > 0) { - vbase = 100; - v = v.replace('-open', ''); - } - if(v.indexOf('-dot') > 0) { - vbase += 200; - v = v.replace('-dot', ''); - } - v = drawing.symbolNames.indexOf(v); - if(v >= 0) { v += vbase; } - } - if((v % 100 >= MAXSYMBOL) || v >= 400) { return 0; } - return Math.floor(Math.max(v, 0)); -}; - -function makePointPath(symbolNumber, r) { - var base = symbolNumber % 100; - return drawing.symbolFuncs[base](r) + (symbolNumber >= 200 ? DOTPATH : ''); -} - -var HORZGRADIENT = {x1: 1, x2: 0, y1: 0, y2: 0}; -var VERTGRADIENT = {x1: 0, x2: 0, y1: 1, y2: 0}; -var stopFormatter = d3.format('~.1f'); -var gradientInfo = { - radial: {node: 'radialGradient'}, - radialreversed: {node: 'radialGradient', reversed: true}, - horizontal: {node: 'linearGradient', attrs: HORZGRADIENT}, - horizontalreversed: {node: 'linearGradient', attrs: HORZGRADIENT, reversed: true}, - vertical: {node: 'linearGradient', attrs: VERTGRADIENT}, - verticalreversed: {node: 'linearGradient', attrs: VERTGRADIENT, reversed: true} -}; - -/** - * gradient: create and apply a gradient fill - * - * @param {object} sel: d3 selection to apply this gradient to - * You can use `selection.call(Drawing.gradient, ...)` - * @param {DOM element} gd: the graph div `sel` is part of - * @param {string} gradientID: a unique (within this plot) identifier - * for this gradient, so that we don't create unnecessary definitions - * @param {string} type: 'radial', 'horizontal', or 'vertical', optionally with - * 'reversed' at the end. Normally radial goes center to edge, - * horizontal goes right to left, and vertical goes bottom to top - * @param {array} colorscale: as in attribute values, [[fraction, color], ...] - * @param {string} prop: the property to apply to, 'fill' or 'stroke' - */ -drawing.gradient = function(sel, gd, gradientID, type, colorscale, prop) { - var len = colorscale.length; - var info = gradientInfo[type]; - var colorStops = new Array(len); - for(var i = 0; i < len; i++) { - if(info.reversed) { - colorStops[len - 1 - i] = [stopFormatter((1 - colorscale[i][0]) * 100), colorscale[i][1]]; - } else { - colorStops[i] = [stopFormatter(colorscale[i][0] * 100), colorscale[i][1]]; - } - } - - var fullID = 'g' + gd._fullLayout._uid + '-' + gradientID; - - var gradient = gd._fullLayout._defs.select('.gradients') - .selectAll('#' + fullID) - .data([type + colorStops.join(';')], Lib.identity); - - gradient.exit().remove(); - - gradient.enter() - .append(info.node) - .each(function() { - var el = d3.select(this); - if(info.attrs) el.attr(info.attrs); - - el.attr('id', fullID); - - var stops = el.selectAll('stop') - .data(colorStops); - stops.exit().remove(); - stops.enter().append('stop'); - - stops.each(function(d) { - var tc = tinycolor(d[1]); - d3.select(this).attr({ - offset: d[0] + '%', - 'stop-color': Color.tinyRGB(tc), - 'stop-opacity': tc.getAlpha() - }); - }); - }); - - sel.style(prop, getFullUrl(fullID, gd)) - .style(prop + '-opacity', null); -}; - -/* - * Make the gradients container and clear out any previous gradients. - * We never collect all the gradients we need in one place, - * so we can't ever remove gradients that have stopped being useful, - * except all at once before a full redraw. - * The upside of this is arbitrary points can share gradient defs - */ -drawing.initGradients = function(gd) { - var gradientsGroup = Lib.ensureSingle(gd._fullLayout._defs, 'g', 'gradients'); - gradientsGroup.selectAll('linearGradient,radialGradient').remove(); -}; - - -drawing.pointStyle = function(s, trace, gd) { - if(!s.size()) return; - - var fns = drawing.makePointStyleFns(trace); - - s.each(function(d) { - drawing.singlePointStyle(d, d3.select(this), trace, fns, gd); - }); -}; - -drawing.singlePointStyle = function(d, sel, trace, fns, gd) { - var marker = trace.marker; - var markerLine = marker.line; - - sel.style('opacity', - fns.selectedOpacityFn ? fns.selectedOpacityFn(d) : - (d.mo === undefined ? marker.opacity : d.mo) - ); - - if(fns.ms2mrc) { - var r; - - // handle multi-trace graph edit case - if(d.ms === 'various' || marker.size === 'various') { - r = 3; - } else { - r = fns.ms2mrc(d.ms); - } - - // store the calculated size so hover can use it - d.mrc = r; - - if(fns.selectedSizeFn) { - r = d.mrc = fns.selectedSizeFn(d); - } - - // turn the symbol into a sanitized number - var x = drawing.symbolNumber(d.mx || marker.symbol) || 0; - - // save if this marker is open - // because that impacts how to handle colors - d.om = x % 200 >= 100; - - sel.attr('d', makePointPath(x, r)); - } - - var perPointGradient = false; - var fillColor, lineColor, lineWidth; - - // 'so' is suspected outliers, for box plots - if(d.so) { - lineWidth = markerLine.outlierwidth; - lineColor = markerLine.outliercolor; - fillColor = marker.outliercolor; - } else { - var markerLineWidth = (markerLine || {}).width; - - lineWidth = ( - d.mlw + 1 || - markerLineWidth + 1 || - // TODO: we need the latter for legends... can we get rid of it? - (d.trace ? (d.trace.marker.line || {}).width : 0) + 1 - ) - 1 || 0; - - if('mlc' in d) lineColor = d.mlcc = fns.lineScale(d.mlc); - // weird case: array wasn't long enough to apply to every point - else if(Lib.isArrayOrTypedArray(markerLine.color)) lineColor = Color.defaultLine; - else lineColor = markerLine.color; - - if(Lib.isArrayOrTypedArray(marker.color)) { - fillColor = Color.defaultLine; - perPointGradient = true; - } - - if('mc' in d) { - fillColor = d.mcc = fns.markerScale(d.mc); - } else { - fillColor = marker.color || 'rgba(0,0,0,0)'; - } - - if(fns.selectedColorFn) { - fillColor = fns.selectedColorFn(d); - } - } - - if(d.om) { - // open markers can't have zero linewidth, default to 1px, - // and use fill color as stroke color - sel.call(Color.stroke, fillColor) - .style({ - 'stroke-width': (lineWidth || 1) + 'px', - fill: 'none' - }); - } else { - sel.style('stroke-width', lineWidth + 'px'); - - var markerGradient = marker.gradient; - - var gradientType = d.mgt; - if(gradientType) perPointGradient = true; - else gradientType = markerGradient && markerGradient.type; - - // for legend - arrays will propagate through here, but we don't need - // to treat it as per-point. - if(Array.isArray(gradientType)) { - gradientType = gradientType[0]; - if(!gradientInfo[gradientType]) gradientType = 0; - } - - if(gradientType && gradientType !== 'none') { - var gradientColor = d.mgc; - if(gradientColor) perPointGradient = true; - else gradientColor = markerGradient.color; - - var gradientID = trace.uid; - if(perPointGradient) gradientID += '-' + d.i; - - drawing.gradient(sel, gd, gradientID, gradientType, - [[0, gradientColor], [1, fillColor]], 'fill'); - } else { - Color.fill(sel, fillColor); - } - - if(lineWidth) { - Color.stroke(sel, lineColor); - } - } -}; - -drawing.makePointStyleFns = function(trace) { - var out = {}; - var marker = trace.marker; - - // allow array marker and marker line colors to be - // scaled by given max and min to colorscales - out.markerScale = drawing.tryColorscale(marker, ''); - out.lineScale = drawing.tryColorscale(marker, 'line'); - - if(Registry.traceIs(trace, 'symbols')) { - out.ms2mrc = subTypes.isBubble(trace) ? - makeBubbleSizeFn(trace) : - function() { return (marker.size || 6) / 2; }; - } - - if(trace.selectedpoints) { - Lib.extendFlat(out, drawing.makeSelectedPointStyleFns(trace)); - } - - return out; -}; - -drawing.makeSelectedPointStyleFns = function(trace) { - var out = {}; - - var selectedAttrs = trace.selected || {}; - var unselectedAttrs = trace.unselected || {}; - - var marker = trace.marker || {}; - var selectedMarker = selectedAttrs.marker || {}; - var unselectedMarker = unselectedAttrs.marker || {}; - - var mo = marker.opacity; - var smo = selectedMarker.opacity; - var usmo = unselectedMarker.opacity; - var smoIsDefined = smo !== undefined; - var usmoIsDefined = usmo !== undefined; - - if(Lib.isArrayOrTypedArray(mo) || smoIsDefined || usmoIsDefined) { - out.selectedOpacityFn = function(d) { - var base = d.mo === undefined ? marker.opacity : d.mo; - - if(d.selected) { - return smoIsDefined ? smo : base; - } else { - return usmoIsDefined ? usmo : DESELECTDIM * base; - } - }; - } - - var mc = marker.color; - var smc = selectedMarker.color; - var usmc = unselectedMarker.color; - - if(smc || usmc) { - out.selectedColorFn = function(d) { - var base = d.mcc || mc; - - if(d.selected) { - return smc || base; - } else { - return usmc || base; - } - }; - } - - var ms = marker.size; - var sms = selectedMarker.size; - var usms = unselectedMarker.size; - var smsIsDefined = sms !== undefined; - var usmsIsDefined = usms !== undefined; - - if(Registry.traceIs(trace, 'symbols') && (smsIsDefined || usmsIsDefined)) { - out.selectedSizeFn = function(d) { - var base = d.mrc || ms / 2; - - if(d.selected) { - return smsIsDefined ? sms / 2 : base; - } else { - return usmsIsDefined ? usms / 2 : base; - } - }; - } - - return out; -}; - -drawing.makeSelectedTextStyleFns = function(trace) { - var out = {}; - - var selectedAttrs = trace.selected || {}; - var unselectedAttrs = trace.unselected || {}; - - var textFont = trace.textfont || {}; - var selectedTextFont = selectedAttrs.textfont || {}; - var unselectedTextFont = unselectedAttrs.textfont || {}; - - var tc = textFont.color; - var stc = selectedTextFont.color; - var utc = unselectedTextFont.color; - - out.selectedTextColorFn = function(d) { - var base = d.tc || tc; - - if(d.selected) { - return stc || base; - } else { - if(utc) return utc; - else return stc ? base : Color.addOpacity(base, DESELECTDIM); - } - }; - - return out; -}; - -drawing.selectedPointStyle = function(s, trace) { - if(!s.size() || !trace.selectedpoints) return; - - var fns = drawing.makeSelectedPointStyleFns(trace); - var marker = trace.marker || {}; - var seq = []; - - if(fns.selectedOpacityFn) { - seq.push(function(pt, d) { - pt.style('opacity', fns.selectedOpacityFn(d)); - }); - } - - if(fns.selectedColorFn) { - seq.push(function(pt, d) { - Color.fill(pt, fns.selectedColorFn(d)); - }); - } - - if(fns.selectedSizeFn) { - seq.push(function(pt, d) { - var mx = d.mx || marker.symbol || 0; - var mrc2 = fns.selectedSizeFn(d); - - pt.attr('d', makePointPath(drawing.symbolNumber(mx), mrc2)); - - // save for Drawing.selectedTextStyle - d.mrc2 = mrc2; - }); - } - - if(seq.length) { - s.each(function(d) { - var pt = d3.select(this); - for(var i = 0; i < seq.length; i++) { - seq[i](pt, d); - } - }); - } -}; - -drawing.tryColorscale = function(marker, prefix) { - var cont = prefix ? Lib.nestedProperty(marker, prefix).get() : marker; - - if(cont) { - var colorArray = cont.color; - if((cont.colorscale || cont._colorAx) && Lib.isArrayOrTypedArray(colorArray)) { - return Colorscale.makeColorScaleFuncFromTrace(cont); - } - } - return Lib.identity; -}; - -var TEXTOFFSETSIGN = { - start: 1, end: -1, middle: 0, bottom: 1, top: -1 -}; - -function textPointPosition(s, textPosition, fontSize, markerRadius) { - var group = d3.select(s.node().parentNode); - - var v = textPosition.indexOf('top') !== -1 ? - 'top' : - textPosition.indexOf('bottom') !== -1 ? 'bottom' : 'middle'; - var h = textPosition.indexOf('left') !== -1 ? - 'end' : - textPosition.indexOf('right') !== -1 ? 'start' : 'middle'; - - // if markers are shown, offset a little more than - // the nominal marker size - // ie 2/1.6 * nominal, bcs some markers are a bit bigger - var r = markerRadius ? markerRadius / 0.8 + 1 : 0; - - var numLines = (svgTextUtils.lineCount(s) - 1) * LINE_SPACING + 1; - var dx = TEXTOFFSETSIGN[h] * r; - var dy = fontSize * 0.75 + TEXTOFFSETSIGN[v] * r + - (TEXTOFFSETSIGN[v] - 1) * numLines * fontSize / 2; - - // fix the overall text group position - s.attr('text-anchor', h); - group.attr('transform', 'translate(' + dx + ',' + dy + ')'); -} - -function extracTextFontSize(d, trace) { - var fontSize = d.ts || trace.textfont.size; - return (isNumeric(fontSize) && fontSize > 0) ? fontSize : 0; -} - -// draw text at points -drawing.textPointStyle = function(s, trace, gd) { - if(!s.size()) return; - - var selectedTextColorFn; - - if(trace.selectedpoints) { - var fns = drawing.makeSelectedTextStyleFns(trace); - selectedTextColorFn = fns.selectedTextColorFn; - } - - s.each(function(d) { - var p = d3.select(this); - var text = Lib.extractOption(d, trace, 'tx', 'text'); - - if(!text && text !== 0) { - p.remove(); - return; - } - - var pos = d.tp || trace.textposition; - var fontSize = extracTextFontSize(d, trace); - var fontColor = selectedTextColorFn ? - selectedTextColorFn(d) : - (d.tc || trace.textfont.color); - - p.call(drawing.font, - d.tf || trace.textfont.family, - fontSize, - fontColor) - .text(text) - .call(svgTextUtils.convertToTspans, gd) - .call(textPointPosition, pos, fontSize, d.mrc); - }); -}; - -drawing.selectedTextStyle = function(s, trace) { - if(!s.size() || !trace.selectedpoints) return; - - var fns = drawing.makeSelectedTextStyleFns(trace); - - s.each(function(d) { - var tx = d3.select(this); - var tc = fns.selectedTextColorFn(d); - var tp = d.tp || trace.textposition; - var fontSize = extracTextFontSize(d, trace); - - Color.fill(tx, tc); - textPointPosition(tx, tp, fontSize, d.mrc2 || d.mrc); - }); -}; - -// generalized Catmull-Rom splines, per -// http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf -var CatmullRomExp = 0.5; -drawing.smoothopen = function(pts, smoothness) { - if(pts.length < 3) { return 'M' + pts.join('L');} - var path = 'M' + pts[0]; - var tangents = []; - var i; - for(i = 1; i < pts.length - 1; i++) { - tangents.push(makeTangent(pts[i - 1], pts[i], pts[i + 1], smoothness)); - } - path += 'Q' + tangents[0][0] + ' ' + pts[1]; - for(i = 2; i < pts.length - 1; i++) { - path += 'C' + tangents[i - 2][1] + ' ' + tangents[i - 1][0] + ' ' + pts[i]; - } - path += 'Q' + tangents[pts.length - 3][1] + ' ' + pts[pts.length - 1]; - return path; -}; - -drawing.smoothclosed = function(pts, smoothness) { - if(pts.length < 3) { return 'M' + pts.join('L') + 'Z'; } - var path = 'M' + pts[0]; - var pLast = pts.length - 1; - var tangents = [makeTangent(pts[pLast], pts[0], pts[1], smoothness)]; - var i; - for(i = 1; i < pLast; i++) { - tangents.push(makeTangent(pts[i - 1], pts[i], pts[i + 1], smoothness)); - } - tangents.push( - makeTangent(pts[pLast - 1], pts[pLast], pts[0], smoothness) - ); - - for(i = 1; i <= pLast; i++) { - path += 'C' + tangents[i - 1][1] + ' ' + tangents[i][0] + ' ' + pts[i]; - } - path += 'C' + tangents[pLast][1] + ' ' + tangents[0][0] + ' ' + pts[0] + 'Z'; - return path; -}; - -function makeTangent(prevpt, thispt, nextpt, smoothness) { - var d1x = prevpt[0] - thispt[0]; - var d1y = prevpt[1] - thispt[1]; - var d2x = nextpt[0] - thispt[0]; - var d2y = nextpt[1] - thispt[1]; - var d1a = Math.pow(d1x * d1x + d1y * d1y, CatmullRomExp / 2); - var d2a = Math.pow(d2x * d2x + d2y * d2y, CatmullRomExp / 2); - var numx = (d2a * d2a * d1x - d1a * d1a * d2x) * smoothness; - var numy = (d2a * d2a * d1y - d1a * d1a * d2y) * smoothness; - var denom1 = 3 * d2a * (d1a + d2a); - var denom2 = 3 * d1a * (d1a + d2a); - return [ - [ - d3.round(thispt[0] + (denom1 && numx / denom1), 2), - d3.round(thispt[1] + (denom1 && numy / denom1), 2) - ], [ - d3.round(thispt[0] - (denom2 && numx / denom2), 2), - d3.round(thispt[1] - (denom2 && numy / denom2), 2) - ] - ]; -} - -// step paths - returns a generator function for paths -// with the given step shape -var STEPPATH = { - hv: function(p0, p1) { - return 'H' + d3.round(p1[0], 2) + 'V' + d3.round(p1[1], 2); - }, - vh: function(p0, p1) { - return 'V' + d3.round(p1[1], 2) + 'H' + d3.round(p1[0], 2); - }, - hvh: function(p0, p1) { - return 'H' + d3.round((p0[0] + p1[0]) / 2, 2) + 'V' + - d3.round(p1[1], 2) + 'H' + d3.round(p1[0], 2); - }, - vhv: function(p0, p1) { - return 'V' + d3.round((p0[1] + p1[1]) / 2, 2) + 'H' + - d3.round(p1[0], 2) + 'V' + d3.round(p1[1], 2); - } -}; -var STEPLINEAR = function(p0, p1) { - return 'L' + d3.round(p1[0], 2) + ',' + d3.round(p1[1], 2); -}; -drawing.steps = function(shape) { - var onestep = STEPPATH[shape] || STEPLINEAR; - return function(pts) { - var path = 'M' + d3.round(pts[0][0], 2) + ',' + d3.round(pts[0][1], 2); - for(var i = 1; i < pts.length; i++) { - path += onestep(pts[i - 1], pts[i]); - } - return path; - }; -}; - -// off-screen svg render testing element, shared by the whole page -// uses the id 'js-plotly-tester' and stores it in drawing.tester -drawing.makeTester = function() { - var tester = Lib.ensureSingleById(d3.select('body'), 'svg', 'js-plotly-tester', function(s) { - s.attr(xmlnsNamespaces.svgAttrs) - .style({ - position: 'absolute', - left: '-10000px', - top: '-10000px', - width: '9000px', - height: '9000px', - 'z-index': '1' - }); - }); - - // browsers differ on how they describe the bounding rect of - // the svg if its contents spill over... so make a 1x1px - // reference point we can measure off of. - var testref = Lib.ensureSingle(tester, 'path', 'js-reference-point', function(s) { - s.attr('d', 'M0,0H1V1H0Z') - .style({ - 'stroke-width': 0, - fill: 'black' - }); - }); - - drawing.tester = tester; - drawing.testref = testref; -}; - -/* - * use our offscreen tester to get a clientRect for an element, - * in a reference frame where it isn't translated (or transformed) and - * its anchor point is at (0,0) - * always returns a copy of the bbox, so the caller can modify it safely - * - * @param {SVGElement} node: the element to measure. If possible this should be - * a or MathJax element that's already passed through - * `convertToTspans` because in that case we can cache the results, but it's - * possible to pass in any svg element. - * - * @param {boolean} inTester: is this element already in `drawing.tester`? - * If you are measuring a dummy element, rather than one you really intend - * to use on the plot, making it in `drawing.tester` in the first place - * allows us to test faster because it cuts out cloning and appending it. - * - * @param {string} hash: for internal use only, if we already know the cache key - * for this element beforehand. - * - * @return {object}: a plain object containing the width, height, left, right, - * top, and bottom of `node` - */ -drawing.savedBBoxes = {}; -var savedBBoxesCount = 0; -var maxSavedBBoxes = 10000; - -drawing.bBox = function(node, inTester, hash) { - /* - * Cache elements we've already measured so we don't have to - * remeasure the same thing many times - * We have a few bBox callers though who pass a node larger than - * a or a MathJax , such as an axis group containing many labels. - * These will not generate a hash (unless we figure out an appropriate - * hash key for them) and thus we will not hash them. - */ - if(!hash) hash = nodeHash(node); - var out; - if(hash) { - out = drawing.savedBBoxes[hash]; - if(out) return Lib.extendFlat({}, out); - } else if(node.childNodes.length === 1) { - /* - * If we have only one child element, which is itself hashable, make - * a new hash from this element plus its x,y,transform - * These bounding boxes *include* x,y,transform - mostly for use by - * callers trying to avoid overlaps (ie titles) - */ - var innerNode = node.childNodes[0]; - - hash = nodeHash(innerNode); - if(hash) { - var x = +innerNode.getAttribute('x') || 0; - var y = +innerNode.getAttribute('y') || 0; - var transform = innerNode.getAttribute('transform'); - - if(!transform) { - // in this case, just varying x and y, don't bother caching - // the final bBox because the alteration is quick. - var innerBB = drawing.bBox(innerNode, false, hash); - if(x) { - innerBB.left += x; - innerBB.right += x; - } - if(y) { - innerBB.top += y; - innerBB.bottom += y; - } - return innerBB; - } - /* - * else we have a transform - rather than make a complicated - * (and error-prone and probably slow) transform parser/calculator, - * just continue on calculating the boundingClientRect of the group - * and use the new composite hash to cache it. - * That said, `innerNode.transform.baseVal` is an array of - * `SVGTransform` objects, that *do* seem to have a nice matrix - * multiplication interface that we could use to avoid making - * another getBoundingClientRect call... - */ - hash += '~' + x + '~' + y + '~' + transform; - - out = drawing.savedBBoxes[hash]; - if(out) return Lib.extendFlat({}, out); - } - } - var testNode, tester; - if(inTester) { - testNode = node; - } else { - tester = drawing.tester.node(); - - // copy the node to test into the tester - testNode = node.cloneNode(true); - tester.appendChild(testNode); - } - - // standardize its position (and newline tspans if any) - d3.select(testNode) - .attr('transform', null) - .call(svgTextUtils.positionText, 0, 0); - - var testRect = testNode.getBoundingClientRect(); - var refRect = drawing.testref - .node() - .getBoundingClientRect(); - - if(!inTester) tester.removeChild(testNode); - - var bb = { - height: testRect.height, - width: testRect.width, - left: testRect.left - refRect.left, - top: testRect.top - refRect.top, - right: testRect.right - refRect.left, - bottom: testRect.bottom - refRect.top - }; - - // make sure we don't have too many saved boxes, - // or a long session could overload on memory - // by saving boxes for long-gone elements - if(savedBBoxesCount >= maxSavedBBoxes) { - drawing.savedBBoxes = {}; - savedBBoxesCount = 0; - } - - // cache this bbox - if(hash) drawing.savedBBoxes[hash] = bb; - savedBBoxesCount++; - - return Lib.extendFlat({}, bb); -}; - -// capture everything about a node (at least in our usage) that -// impacts its bounding box, given that bBox clears x, y, and transform -function nodeHash(node) { - var inputText = node.getAttribute('data-unformatted'); - if(inputText === null) return; - return inputText + - node.getAttribute('data-math') + - node.getAttribute('text-anchor') + - node.getAttribute('style'); -} - -/** - * Set clipPath URL in a way that work for all situations. - * - * In details, graphs on pages with HTML tags need to prepend - * the clip path ids with the page's base url EXCEPT during toImage exports. - * - * @param {d3 selection} s : node to add clip-path attribute - * @param {string} localId : local clip-path (w/o base url) id - * @param {DOM element || object} gd - * - context._baseUrl {string} - * - context._exportedPlot {boolean} - */ -drawing.setClipUrl = function(s, localId, gd) { - s.attr('clip-path', getFullUrl(localId, gd)); -}; - -function getFullUrl(localId, gd) { - if(!localId) return null; - - var context = gd._context; - var baseUrl = context._exportedPlot ? '' : (context._baseUrl || ''); - return 'url(\'' + baseUrl + '#' + localId + '\')'; -} - -drawing.getTranslate = function(element) { - // Note the separator [^\d] between x and y in this regex - // We generally use ',' but IE will convert it to ' ' - var re = /.*\btranslate\((-?\d*\.?\d*)[^-\d]*(-?\d*\.?\d*)[^\d].*/; - var getter = element.attr ? 'attr' : 'getAttribute'; - var transform = element[getter]('transform') || ''; - - var translate = transform.replace(re, function(match, p1, p2) { - return [p1, p2].join(' '); - }) - .split(' '); - - return { - x: +translate[0] || 0, - y: +translate[1] || 0 - }; -}; - -drawing.setTranslate = function(element, x, y) { - var re = /(\btranslate\(.*?\);?)/; - var getter = element.attr ? 'attr' : 'getAttribute'; - var setter = element.attr ? 'attr' : 'setAttribute'; - var transform = element[getter]('transform') || ''; - - x = x || 0; - y = y || 0; - - transform = transform.replace(re, '').trim(); - transform += ' translate(' + x + ', ' + y + ')'; - transform = transform.trim(); - - element[setter]('transform', transform); - - return transform; -}; - -drawing.getScale = function(element) { - var re = /.*\bscale\((\d*\.?\d*)[^\d]*(\d*\.?\d*)[^\d].*/; - var getter = element.attr ? 'attr' : 'getAttribute'; - var transform = element[getter]('transform') || ''; - - var translate = transform.replace(re, function(match, p1, p2) { - return [p1, p2].join(' '); - }) - .split(' '); - - return { - x: +translate[0] || 1, - y: +translate[1] || 1 - }; -}; - -drawing.setScale = function(element, x, y) { - var re = /(\bscale\(.*?\);?)/; - var getter = element.attr ? 'attr' : 'getAttribute'; - var setter = element.attr ? 'attr' : 'setAttribute'; - var transform = element[getter]('transform') || ''; - - x = x || 1; - y = y || 1; - - transform = transform.replace(re, '').trim(); - transform += ' scale(' + x + ', ' + y + ')'; - transform = transform.trim(); - - element[setter]('transform', transform); - - return transform; -}; - -var SCALE_RE = /\s*sc.*/; - -drawing.setPointGroupScale = function(selection, xScale, yScale) { - xScale = xScale || 1; - yScale = yScale || 1; - - if(!selection) return; - - // The same scale transform for every point: - var scale = (xScale === 1 && yScale === 1) ? - '' : - ' scale(' + xScale + ',' + yScale + ')'; - - selection.each(function() { - var t = (this.getAttribute('transform') || '').replace(SCALE_RE, ''); - t += scale; - t = t.trim(); - this.setAttribute('transform', t); - }); -}; - -var TEXT_POINT_LAST_TRANSLATION_RE = /translate\([^)]*\)\s*$/; - -drawing.setTextPointsScale = function(selection, xScale, yScale) { - if(!selection) return; - - selection.each(function() { - var transforms; - var el = d3.select(this); - var text = el.select('text'); - - if(!text.node()) return; - - var x = parseFloat(text.attr('x') || 0); - var y = parseFloat(text.attr('y') || 0); - - var existingTransform = (el.attr('transform') || '').match(TEXT_POINT_LAST_TRANSLATION_RE); - - if(xScale === 1 && yScale === 1) { - transforms = []; - } else { - transforms = [ - 'translate(' + x + ',' + y + ')', - 'scale(' + xScale + ',' + yScale + ')', - 'translate(' + (-x) + ',' + (-y) + ')', - ]; - } - - if(existingTransform) { - transforms.push(existingTransform); - } - - el.attr('transform', transforms.join(' ')); - }); -}; - -},{"../../constants/alignment":688,"../../constants/interactions":694,"../../constants/xmlns_namespaces":696,"../../lib":719,"../../lib/svg_text_utils":743,"../../registry":847,"../../traces/scatter/make_bubble_size_func":1128,"../../traces/scatter/subtypes":1135,"../color":593,"../colorscale":605,"./symbol_defs":615,"d3":163,"fast-isnumeric":225,"tinycolor2":537}],615:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -/** Marker symbol definitions - * users can specify markers either by number or name - * add 100 (or '-open') and you get an open marker - * open markers have no fill and use line color as the stroke color - * add 200 (or '-dot') and you get a dot in the middle - * add both and you get both - */ - -module.exports = { - circle: { - n: 0, - f: function(r) { - var rs = d3.round(r, 2); - return 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + - 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z'; - } - }, - square: { - n: 1, - f: function(r) { - var rs = d3.round(r, 2); - return 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z'; - } - }, - diamond: { - n: 2, - f: function(r) { - var rd = d3.round(r * 1.3, 2); - return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z'; - } - }, - cross: { - n: 3, - f: function(r) { - var rc = d3.round(r * 0.4, 2); - var rc2 = d3.round(r * 1.2, 2); - return 'M' + rc2 + ',' + rc + 'H' + rc + 'V' + rc2 + 'H-' + rc + - 'V' + rc + 'H-' + rc2 + 'V-' + rc + 'H-' + rc + 'V-' + rc2 + - 'H' + rc + 'V-' + rc + 'H' + rc2 + 'Z'; - } - }, - x: { - n: 4, - f: function(r) { - var rx = d3.round(r * 0.8 / Math.sqrt(2), 2); - var ne = 'l' + rx + ',' + rx; - var se = 'l' + rx + ',-' + rx; - var sw = 'l-' + rx + ',-' + rx; - var nw = 'l-' + rx + ',' + rx; - return 'M0,' + rx + ne + se + sw + se + sw + nw + sw + nw + ne + nw + ne + 'Z'; - } - }, - 'triangle-up': { - n: 5, - f: function(r) { - var rt = d3.round(r * 2 / Math.sqrt(3), 2); - var r2 = d3.round(r / 2, 2); - var rs = d3.round(r, 2); - return 'M-' + rt + ',' + r2 + 'H' + rt + 'L0,-' + rs + 'Z'; - } - }, - 'triangle-down': { - n: 6, - f: function(r) { - var rt = d3.round(r * 2 / Math.sqrt(3), 2); - var r2 = d3.round(r / 2, 2); - var rs = d3.round(r, 2); - return 'M-' + rt + ',-' + r2 + 'H' + rt + 'L0,' + rs + 'Z'; - } - }, - 'triangle-left': { - n: 7, - f: function(r) { - var rt = d3.round(r * 2 / Math.sqrt(3), 2); - var r2 = d3.round(r / 2, 2); - var rs = d3.round(r, 2); - return 'M' + r2 + ',-' + rt + 'V' + rt + 'L-' + rs + ',0Z'; - } - }, - 'triangle-right': { - n: 8, - f: function(r) { - var rt = d3.round(r * 2 / Math.sqrt(3), 2); - var r2 = d3.round(r / 2, 2); - var rs = d3.round(r, 2); - return 'M-' + r2 + ',-' + rt + 'V' + rt + 'L' + rs + ',0Z'; - } - }, - 'triangle-ne': { - n: 9, - f: function(r) { - var r1 = d3.round(r * 0.6, 2); - var r2 = d3.round(r * 1.2, 2); - return 'M-' + r2 + ',-' + r1 + 'H' + r1 + 'V' + r2 + 'Z'; - } - }, - 'triangle-se': { - n: 10, - f: function(r) { - var r1 = d3.round(r * 0.6, 2); - var r2 = d3.round(r * 1.2, 2); - return 'M' + r1 + ',-' + r2 + 'V' + r1 + 'H-' + r2 + 'Z'; - } - }, - 'triangle-sw': { - n: 11, - f: function(r) { - var r1 = d3.round(r * 0.6, 2); - var r2 = d3.round(r * 1.2, 2); - return 'M' + r2 + ',' + r1 + 'H-' + r1 + 'V-' + r2 + 'Z'; - } - }, - 'triangle-nw': { - n: 12, - f: function(r) { - var r1 = d3.round(r * 0.6, 2); - var r2 = d3.round(r * 1.2, 2); - return 'M-' + r1 + ',' + r2 + 'V-' + r1 + 'H' + r2 + 'Z'; - } - }, - pentagon: { - n: 13, - f: function(r) { - var x1 = d3.round(r * 0.951, 2); - var x2 = d3.round(r * 0.588, 2); - var y0 = d3.round(-r, 2); - var y1 = d3.round(r * -0.309, 2); - var y2 = d3.round(r * 0.809, 2); - return 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2 + 'H-' + x2 + - 'L-' + x1 + ',' + y1 + 'L0,' + y0 + 'Z'; - } - }, - hexagon: { - n: 14, - f: function(r) { - var y0 = d3.round(r, 2); - var y1 = d3.round(r / 2, 2); - var x = d3.round(r * Math.sqrt(3) / 2, 2); - return 'M' + x + ',-' + y1 + 'V' + y1 + 'L0,' + y0 + - 'L-' + x + ',' + y1 + 'V-' + y1 + 'L0,-' + y0 + 'Z'; - } - }, - hexagon2: { - n: 15, - f: function(r) { - var x0 = d3.round(r, 2); - var x1 = d3.round(r / 2, 2); - var y = d3.round(r * Math.sqrt(3) / 2, 2); - return 'M-' + x1 + ',' + y + 'H' + x1 + 'L' + x0 + - ',0L' + x1 + ',-' + y + 'H-' + x1 + 'L-' + x0 + ',0Z'; - } - }, - octagon: { - n: 16, - f: function(r) { - var a = d3.round(r * 0.924, 2); - var b = d3.round(r * 0.383, 2); - return 'M-' + b + ',-' + a + 'H' + b + 'L' + a + ',-' + b + 'V' + b + - 'L' + b + ',' + a + 'H-' + b + 'L-' + a + ',' + b + 'V-' + b + 'Z'; - } - }, - star: { - n: 17, - f: function(r) { - var rs = r * 1.4; - var x1 = d3.round(rs * 0.225, 2); - var x2 = d3.round(rs * 0.951, 2); - var x3 = d3.round(rs * 0.363, 2); - var x4 = d3.round(rs * 0.588, 2); - var y0 = d3.round(-rs, 2); - var y1 = d3.round(rs * -0.309, 2); - var y3 = d3.round(rs * 0.118, 2); - var y4 = d3.round(rs * 0.809, 2); - var y5 = d3.round(rs * 0.382, 2); - return 'M' + x1 + ',' + y1 + 'H' + x2 + 'L' + x3 + ',' + y3 + - 'L' + x4 + ',' + y4 + 'L0,' + y5 + 'L-' + x4 + ',' + y4 + - 'L-' + x3 + ',' + y3 + 'L-' + x2 + ',' + y1 + 'H-' + x1 + - 'L0,' + y0 + 'Z'; - } - }, - hexagram: { - n: 18, - f: function(r) { - var y = d3.round(r * 0.66, 2); - var x1 = d3.round(r * 0.38, 2); - var x2 = d3.round(r * 0.76, 2); - return 'M-' + x2 + ',0l-' + x1 + ',-' + y + 'h' + x2 + - 'l' + x1 + ',-' + y + 'l' + x1 + ',' + y + 'h' + x2 + - 'l-' + x1 + ',' + y + 'l' + x1 + ',' + y + 'h-' + x2 + - 'l-' + x1 + ',' + y + 'l-' + x1 + ',-' + y + 'h-' + x2 + 'Z'; - } - }, - 'star-triangle-up': { - n: 19, - f: function(r) { - var x = d3.round(r * Math.sqrt(3) * 0.8, 2); - var y1 = d3.round(r * 0.8, 2); - var y2 = d3.round(r * 1.6, 2); - var rc = d3.round(r * 4, 2); - var aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; - return 'M-' + x + ',' + y1 + aPart + x + ',' + y1 + - aPart + '0,-' + y2 + aPart + '-' + x + ',' + y1 + 'Z'; - } - }, - 'star-triangle-down': { - n: 20, - f: function(r) { - var x = d3.round(r * Math.sqrt(3) * 0.8, 2); - var y1 = d3.round(r * 0.8, 2); - var y2 = d3.round(r * 1.6, 2); - var rc = d3.round(r * 4, 2); - var aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; - return 'M' + x + ',-' + y1 + aPart + '-' + x + ',-' + y1 + - aPart + '0,' + y2 + aPart + x + ',-' + y1 + 'Z'; - } - }, - 'star-square': { - n: 21, - f: function(r) { - var rp = d3.round(r * 1.1, 2); - var rc = d3.round(r * 2, 2); - var aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; - return 'M-' + rp + ',-' + rp + aPart + '-' + rp + ',' + rp + - aPart + rp + ',' + rp + aPart + rp + ',-' + rp + - aPart + '-' + rp + ',-' + rp + 'Z'; - } - }, - 'star-diamond': { - n: 22, - f: function(r) { - var rp = d3.round(r * 1.4, 2); - var rc = d3.round(r * 1.9, 2); - var aPart = 'A ' + rc + ',' + rc + ' 0 0 1 '; - return 'M-' + rp + ',0' + aPart + '0,' + rp + - aPart + rp + ',0' + aPart + '0,-' + rp + - aPart + '-' + rp + ',0' + 'Z'; - } - }, - 'diamond-tall': { - n: 23, - f: function(r) { - var x = d3.round(r * 0.7, 2); - var y = d3.round(r * 1.4, 2); - return 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z'; - } - }, - 'diamond-wide': { - n: 24, - f: function(r) { - var x = d3.round(r * 1.4, 2); - var y = d3.round(r * 0.7, 2); - return 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z'; - } - }, - hourglass: { - n: 25, - f: function(r) { - var rs = d3.round(r, 2); - return 'M' + rs + ',' + rs + 'H-' + rs + 'L' + rs + ',-' + rs + 'H-' + rs + 'Z'; - }, - noDot: true - }, - bowtie: { - n: 26, - f: function(r) { - var rs = d3.round(r, 2); - return 'M' + rs + ',' + rs + 'V-' + rs + 'L-' + rs + ',' + rs + 'V-' + rs + 'Z'; - }, - noDot: true - }, - 'circle-cross': { - n: 27, - f: function(r) { - var rs = d3.round(r, 2); - return 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs + - 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + - 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z'; - }, - needLine: true, - noDot: true - }, - 'circle-x': { - n: 28, - f: function(r) { - var rs = d3.round(r, 2); - var rc = d3.round(r / Math.sqrt(2), 2); - return 'M' + rc + ',' + rc + 'L-' + rc + ',-' + rc + - 'M' + rc + ',-' + rc + 'L-' + rc + ',' + rc + - 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + - 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z'; - }, - needLine: true, - noDot: true - }, - 'square-cross': { - n: 29, - f: function(r) { - var rs = d3.round(r, 2); - return 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs + - 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z'; - }, - needLine: true, - noDot: true - }, - 'square-x': { - n: 30, - f: function(r) { - var rs = d3.round(r, 2); - return 'M' + rs + ',' + rs + 'L-' + rs + ',-' + rs + - 'M' + rs + ',-' + rs + 'L-' + rs + ',' + rs + - 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z'; - }, - needLine: true, - noDot: true - }, - 'diamond-cross': { - n: 31, - f: function(r) { - var rd = d3.round(r * 1.3, 2); - return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' + - 'M0,-' + rd + 'V' + rd + 'M-' + rd + ',0H' + rd; - }, - needLine: true, - noDot: true - }, - 'diamond-x': { - n: 32, - f: function(r) { - var rd = d3.round(r * 1.3, 2); - var r2 = d3.round(r * 0.65, 2); - return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' + - 'M-' + r2 + ',-' + r2 + 'L' + r2 + ',' + r2 + - 'M-' + r2 + ',' + r2 + 'L' + r2 + ',-' + r2; - }, - needLine: true, - noDot: true - }, - 'cross-thin': { - n: 33, - f: function(r) { - var rc = d3.round(r * 1.4, 2); - return 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc; - }, - needLine: true, - noDot: true, - noFill: true - }, - 'x-thin': { - n: 34, - f: function(r) { - var rx = d3.round(r, 2); - return 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx + - 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx; - }, - needLine: true, - noDot: true, - noFill: true - }, - asterisk: { - n: 35, - f: function(r) { - var rc = d3.round(r * 1.2, 2); - var rs = d3.round(r * 0.85, 2); - return 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc + - 'M' + rs + ',' + rs + 'L-' + rs + ',-' + rs + - 'M' + rs + ',-' + rs + 'L-' + rs + ',' + rs; - }, - needLine: true, - noDot: true, - noFill: true - }, - hash: { - n: 36, - f: function(r) { - var r1 = d3.round(r / 2, 2); - var r2 = d3.round(r, 2); - return 'M' + r1 + ',' + r2 + 'V-' + r2 + - 'm-' + r2 + ',0V' + r2 + - 'M' + r2 + ',' + r1 + 'H-' + r2 + - 'm0,-' + r2 + 'H' + r2; - }, - needLine: true, - noFill: true - }, - 'y-up': { - n: 37, - f: function(r) { - var x = d3.round(r * 1.2, 2); - var y0 = d3.round(r * 1.6, 2); - var y1 = d3.round(r * 0.8, 2); - return 'M-' + x + ',' + y1 + 'L0,0M' + x + ',' + y1 + 'L0,0M0,-' + y0 + 'L0,0'; - }, - needLine: true, - noDot: true, - noFill: true - }, - 'y-down': { - n: 38, - f: function(r) { - var x = d3.round(r * 1.2, 2); - var y0 = d3.round(r * 1.6, 2); - var y1 = d3.round(r * 0.8, 2); - return 'M-' + x + ',-' + y1 + 'L0,0M' + x + ',-' + y1 + 'L0,0M0,' + y0 + 'L0,0'; - }, - needLine: true, - noDot: true, - noFill: true - }, - 'y-left': { - n: 39, - f: function(r) { - var y = d3.round(r * 1.2, 2); - var x0 = d3.round(r * 1.6, 2); - var x1 = d3.round(r * 0.8, 2); - return 'M' + x1 + ',' + y + 'L0,0M' + x1 + ',-' + y + 'L0,0M-' + x0 + ',0L0,0'; - }, - needLine: true, - noDot: true, - noFill: true - }, - 'y-right': { - n: 40, - f: function(r) { - var y = d3.round(r * 1.2, 2); - var x0 = d3.round(r * 1.6, 2); - var x1 = d3.round(r * 0.8, 2); - return 'M-' + x1 + ',' + y + 'L0,0M-' + x1 + ',-' + y + 'L0,0M' + x0 + ',0L0,0'; - }, - needLine: true, - noDot: true, - noFill: true - }, - 'line-ew': { - n: 41, - f: function(r) { - var rc = d3.round(r * 1.4, 2); - return 'M' + rc + ',0H-' + rc; - }, - needLine: true, - noDot: true, - noFill: true - }, - 'line-ns': { - n: 42, - f: function(r) { - var rc = d3.round(r * 1.4, 2); - return 'M0,' + rc + 'V-' + rc; - }, - needLine: true, - noDot: true, - noFill: true - }, - 'line-ne': { - n: 43, - f: function(r) { - var rx = d3.round(r, 2); - return 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx; - }, - needLine: true, - noDot: true, - noFill: true - }, - 'line-nw': { - n: 44, - f: function(r) { - var rx = d3.round(r, 2); - return 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx; - }, - needLine: true, - noDot: true, - noFill: true - } -}; - -},{"d3":163}],616:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -module.exports = { - visible: { - valType: 'boolean', - - editType: 'calc', - - }, - type: { - valType: 'enumerated', - values: ['percent', 'constant', 'sqrt', 'data'], - - editType: 'calc', - - }, - symmetric: { - valType: 'boolean', - - editType: 'calc', - - }, - array: { - valType: 'data_array', - editType: 'calc', - - }, - arrayminus: { - valType: 'data_array', - editType: 'calc', - - }, - value: { - valType: 'number', - min: 0, - dflt: 10, - - editType: 'calc', - - }, - valueminus: { - valType: 'number', - min: 0, - dflt: 10, - - editType: 'calc', - - }, - traceref: { - valType: 'integer', - min: 0, - dflt: 0, - - editType: 'style' - }, - tracerefminus: { - valType: 'integer', - min: 0, - dflt: 0, - - editType: 'style' - }, - copy_ystyle: { - valType: 'boolean', - - editType: 'plot' - }, - copy_zstyle: { - valType: 'boolean', - - editType: 'style' - }, - color: { - valType: 'color', - - editType: 'style', - - }, - thickness: { - valType: 'number', - min: 0, - dflt: 2, - - editType: 'style', - - }, - width: { - valType: 'number', - min: 0, - - editType: 'plot', - - }, - editType: 'calc', - - _deprecated: { - opacity: { - valType: 'number', - - editType: 'style', - - } - } -}; - -},{}],617:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Registry = _dereq_('../../registry'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var Lib = _dereq_('../../lib'); - -var makeComputeError = _dereq_('./compute_error'); - -module.exports = function calc(gd) { - var calcdata = gd.calcdata; - - for(var i = 0; i < calcdata.length; i++) { - var calcTrace = calcdata[i]; - var trace = calcTrace[0].trace; - - if(trace.visible === true && Registry.traceIs(trace, 'errorBarsOK')) { - var xa = Axes.getFromId(gd, trace.xaxis); - var ya = Axes.getFromId(gd, trace.yaxis); - calcOneAxis(calcTrace, trace, xa, 'x'); - calcOneAxis(calcTrace, trace, ya, 'y'); - } - } -}; - -function calcOneAxis(calcTrace, trace, axis, coord) { - var opts = trace['error_' + coord] || {}; - var isVisible = (opts.visible && ['linear', 'log'].indexOf(axis.type) !== -1); - var vals = []; - - if(!isVisible) return; - - var computeError = makeComputeError(opts); - - for(var i = 0; i < calcTrace.length; i++) { - var calcPt = calcTrace[i]; - - var iIn = calcPt.i; - - // for types that don't include `i` in each calcdata point - if(iIn === undefined) iIn = i; - - // for stacked area inserted points - // TODO: errorbars have been tested cursorily with stacked area, - // but not thoroughly. It's not even really clear what you want to do: - // Should it just be calculated based on that trace's size data? - // Should you add errors from below in quadrature? - // And what about normalization, where in principle the errors shrink - // again when you get up to the top end? - // One option would be to forbid errorbars with stacking until we - // decide how to handle these questions. - else if(iIn === null) continue; - - var calcCoord = calcPt[coord]; - - if(!isNumeric(axis.c2l(calcCoord))) continue; - - var errors = computeError(calcCoord, iIn); - if(isNumeric(errors[0]) && isNumeric(errors[1])) { - var shoe = calcPt[coord + 's'] = calcCoord - errors[0]; - var hat = calcPt[coord + 'h'] = calcCoord + errors[1]; - vals.push(shoe, hat); - } - } - - var axId = axis._id; - var baseExtremes = trace._extremes[axId]; - var extremes = Axes.findExtremes( - axis, - vals, - Lib.extendFlat({tozero: baseExtremes.opts.tozero}, {padded: true}) - ); - baseExtremes.min = baseExtremes.min.concat(extremes.min); - baseExtremes.max = baseExtremes.max.concat(extremes.max); -} - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../../registry":847,"./compute_error":618,"fast-isnumeric":225}],618:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -/** - * Error bar computing function generator - * - * N.B. The generated function does not clean the dataPt entries. Non-numeric - * entries result in undefined error magnitudes. - * - * @param {object} opts error bar attributes - * - * @return {function} : - * @param {numeric} dataPt data point from where to compute the error magnitude - * @param {number} index index of dataPt in its corresponding data array - * @return {array} - * - error[0] : error magnitude in the negative direction - * - error[1] : " " " " positive " - */ -module.exports = function makeComputeError(opts) { - var type = opts.type; - var symmetric = opts.symmetric; - - if(type === 'data') { - var array = opts.array || []; - - if(symmetric) { - return function computeError(dataPt, index) { - var val = +(array[index]); - return [val, val]; - }; - } else { - var arrayminus = opts.arrayminus || []; - return function computeError(dataPt, index) { - var val = +array[index]; - var valMinus = +arrayminus[index]; - // in case one is present and the other is missing, fill in 0 - // so we still see the present one. Mostly useful during manual - // data entry. - if(!isNaN(val) || !isNaN(valMinus)) { - return [valMinus || 0, val || 0]; - } - return [NaN, NaN]; - }; - } - } else { - var computeErrorValue = makeComputeErrorValue(type, opts.value); - var computeErrorValueMinus = makeComputeErrorValue(type, opts.valueminus); - - if(symmetric || opts.valueminus === undefined) { - return function computeError(dataPt) { - var val = computeErrorValue(dataPt); - return [val, val]; - }; - } else { - return function computeError(dataPt) { - return [ - computeErrorValueMinus(dataPt), - computeErrorValue(dataPt) - ]; - }; - } - } -}; - -/** - * Compute error bar magnitude (for all types except data) - * - * @param {string} type error bar type - * @param {numeric} value error bar value - * - * @return {function} : - * @param {numeric} dataPt - */ -function makeComputeErrorValue(type, value) { - if(type === 'percent') { - return function(dataPt) { - return Math.abs(dataPt * value / 100); - }; - } - if(type === 'constant') { - return function() { - return Math.abs(value); - }; - } - if(type === 'sqrt') { - return function(dataPt) { - return Math.sqrt(Math.abs(dataPt)); - }; - } -} - -},{}],619:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Template = _dereq_('../../plot_api/plot_template'); - -var attributes = _dereq_('./attributes'); - - -module.exports = function(traceIn, traceOut, defaultColor, opts) { - var objName = 'error_' + opts.axis; - var containerOut = Template.newContainer(traceOut, objName); - var containerIn = traceIn[objName] || {}; - - function coerce(attr, dflt) { - return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); - } - - var hasErrorBars = ( - containerIn.array !== undefined || - containerIn.value !== undefined || - containerIn.type === 'sqrt' - ); - - var visible = coerce('visible', hasErrorBars); - - if(visible === false) return; - - var type = coerce('type', 'array' in containerIn ? 'data' : 'percent'); - var symmetric = true; - - if(type !== 'sqrt') { - symmetric = coerce('symmetric', - !((type === 'data' ? 'arrayminus' : 'valueminus') in containerIn)); - } - - if(type === 'data') { - coerce('array'); - coerce('traceref'); - if(!symmetric) { - coerce('arrayminus'); - coerce('tracerefminus'); - } - } else if(type === 'percent' || type === 'constant') { - coerce('value'); - if(!symmetric) coerce('valueminus'); - } - - var copyAttr = 'copy_' + opts.inherit + 'style'; - if(opts.inherit) { - var inheritObj = traceOut['error_' + opts.inherit]; - if((inheritObj || {}).visible) { - coerce(copyAttr, !(containerIn.color || - isNumeric(containerIn.thickness) || - isNumeric(containerIn.width))); - } - } - if(!opts.inherit || !containerOut[copyAttr]) { - coerce('color', defaultColor); - coerce('thickness'); - coerce('width', Registry.traceIs(traceOut, 'gl3d') ? 0 : 4); - } -}; - -},{"../../lib":719,"../../plot_api/plot_template":757,"../../registry":847,"./attributes":616,"fast-isnumeric":225}],620:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var attributes = _dereq_('./attributes'); - -var xyAttrs = { - error_x: Lib.extendFlat({}, attributes), - error_y: Lib.extendFlat({}, attributes) -}; -delete xyAttrs.error_x.copy_zstyle; -delete xyAttrs.error_y.copy_zstyle; -delete xyAttrs.error_y.copy_ystyle; - -var xyzAttrs = { - error_x: Lib.extendFlat({}, attributes), - error_y: Lib.extendFlat({}, attributes), - error_z: Lib.extendFlat({}, attributes) -}; -delete xyzAttrs.error_x.copy_ystyle; -delete xyzAttrs.error_y.copy_ystyle; -delete xyzAttrs.error_z.copy_ystyle; -delete xyzAttrs.error_z.copy_zstyle; - -module.exports = { - moduleType: 'component', - name: 'errorbars', - - schema: { - traces: { - scatter: xyAttrs, - bar: xyAttrs, - histogram: xyAttrs, - scatter3d: overrideAll(xyzAttrs, 'calc', 'nested'), - scattergl: overrideAll(xyAttrs, 'calc', 'nested') - } - }, - - supplyDefaults: _dereq_('./defaults'), - - calc: _dereq_('./calc'), - makeComputeError: _dereq_('./compute_error'), - - plot: _dereq_('./plot'), - style: _dereq_('./style'), - hoverInfo: hoverInfo -}; - -function hoverInfo(calcPoint, trace, hoverPoint) { - if((trace.error_y || {}).visible) { - hoverPoint.yerr = calcPoint.yh - calcPoint.y; - if(!trace.error_y.symmetric) hoverPoint.yerrneg = calcPoint.y - calcPoint.ys; - } - if((trace.error_x || {}).visible) { - hoverPoint.xerr = calcPoint.xh - calcPoint.x; - if(!trace.error_x.symmetric) hoverPoint.xerrneg = calcPoint.x - calcPoint.xs; - } -} - -},{"../../lib":719,"../../plot_api/edit_types":750,"./attributes":616,"./calc":617,"./compute_error":618,"./defaults":619,"./plot":621,"./style":622}],621:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Drawing = _dereq_('../drawing'); -var subTypes = _dereq_('../../traces/scatter/subtypes'); - -module.exports = function plot(gd, traces, plotinfo, transitionOpts) { - var isNew; - - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - var hasAnimation = transitionOpts && transitionOpts.duration > 0; - - traces.each(function(d) { - var trace = d[0].trace; - // || {} is in case the trace (specifically scatterternary) - // doesn't support error bars at all, but does go through - // the scatter.plot mechanics, which calls ErrorBars.plot - // internally - var xObj = trace.error_x || {}; - var yObj = trace.error_y || {}; - - var keyFunc; - - if(trace.ids) { - keyFunc = function(d) {return d.id;}; - } - - var sparse = ( - subTypes.hasMarkers(trace) && - trace.marker.maxdisplayed > 0 - ); - - if(!yObj.visible && !xObj.visible) d = []; - - var errorbars = d3.select(this).selectAll('g.errorbar') - .data(d, keyFunc); - - errorbars.exit().remove(); - - if(!d.length) return; - - if(!xObj.visible) errorbars.selectAll('path.xerror').remove(); - if(!yObj.visible) errorbars.selectAll('path.yerror').remove(); - - errorbars.style('opacity', 1); - - var enter = errorbars.enter().append('g') - .classed('errorbar', true); - - if(hasAnimation) { - enter.style('opacity', 0).transition() - .duration(transitionOpts.duration) - .style('opacity', 1); - } - - Drawing.setClipUrl(errorbars, plotinfo.layerClipId, gd); - - errorbars.each(function(d) { - var errorbar = d3.select(this); - var coords = errorCoords(d, xa, ya); - - if(sparse && !d.vis) return; - - var path; - - var yerror = errorbar.select('path.yerror'); - if(yObj.visible && isNumeric(coords.x) && - isNumeric(coords.yh) && - isNumeric(coords.ys)) { - var yw = yObj.width; - - path = 'M' + (coords.x - yw) + ',' + - coords.yh + 'h' + (2 * yw) + // hat - 'm-' + yw + ',0V' + coords.ys; // bar - - - if(!coords.noYS) path += 'm-' + yw + ',0h' + (2 * yw); // shoe - - isNew = !yerror.size(); - - if(isNew) { - yerror = errorbar.append('path') - .style('vector-effect', 'non-scaling-stroke') - .classed('yerror', true); - } else if(hasAnimation) { - yerror = yerror - .transition() - .duration(transitionOpts.duration) - .ease(transitionOpts.easing); - } - - yerror.attr('d', path); - } else yerror.remove(); - - var xerror = errorbar.select('path.xerror'); - if(xObj.visible && isNumeric(coords.y) && - isNumeric(coords.xh) && - isNumeric(coords.xs)) { - var xw = (xObj.copy_ystyle ? yObj : xObj).width; - - path = 'M' + coords.xh + ',' + - (coords.y - xw) + 'v' + (2 * xw) + // hat - 'm0,-' + xw + 'H' + coords.xs; // bar - - if(!coords.noXS) path += 'm0,-' + xw + 'v' + (2 * xw); // shoe - - isNew = !xerror.size(); - - if(isNew) { - xerror = errorbar.append('path') - .style('vector-effect', 'non-scaling-stroke') - .classed('xerror', true); - } else if(hasAnimation) { - xerror = xerror - .transition() - .duration(transitionOpts.duration) - .ease(transitionOpts.easing); - } - - xerror.attr('d', path); - } else xerror.remove(); - }); - }); -}; - -// compute the coordinates of the error-bar objects -function errorCoords(d, xa, ya) { - var out = { - x: xa.c2p(d.x), - y: ya.c2p(d.y) - }; - - // calculate the error bar size and hat and shoe locations - if(d.yh !== undefined) { - out.yh = ya.c2p(d.yh); - out.ys = ya.c2p(d.ys); - - // if the shoes go off-scale (ie log scale, error bars past zero) - // clip the bar and hide the shoes - if(!isNumeric(out.ys)) { - out.noYS = true; - out.ys = ya.c2p(d.ys, true); - } - } - - if(d.xh !== undefined) { - out.xh = xa.c2p(d.xh); - out.xs = xa.c2p(d.xs); - - if(!isNumeric(out.xs)) { - out.noXS = true; - out.xs = xa.c2p(d.xs, true); - } - } - - return out; -} - -},{"../../traces/scatter/subtypes":1135,"../drawing":614,"d3":163,"fast-isnumeric":225}],622:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Color = _dereq_('../color'); - - -module.exports = function style(traces) { - traces.each(function(d) { - var trace = d[0].trace; - var yObj = trace.error_y || {}; - var xObj = trace.error_x || {}; - - var s = d3.select(this); - - s.selectAll('path.yerror') - .style('stroke-width', yObj.thickness + 'px') - .call(Color.stroke, yObj.color); - - if(xObj.copy_ystyle) xObj = yObj; - - s.selectAll('path.xerror') - .style('stroke-width', xObj.thickness + 'px') - .call(Color.stroke, xObj.color); - }); -}; - -},{"../color":593,"d3":163}],623:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('../../plots/font_attributes'); -var hoverLabelAttrs = _dereq_('./layout_attributes').hoverlabel; -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = { - hoverlabel: { - bgcolor: extendFlat({}, hoverLabelAttrs.bgcolor, { - arrayOk: true, - - }), - bordercolor: extendFlat({}, hoverLabelAttrs.bordercolor, { - arrayOk: true, - - }), - font: fontAttrs({ - arrayOk: true, - editType: 'none', - - }), - align: extendFlat({}, hoverLabelAttrs.align, {arrayOk: true}), - namelength: extendFlat({}, hoverLabelAttrs.namelength, {arrayOk: true}), - editType: 'none' - } -}; - -},{"../../lib/extend":710,"../../plots/font_attributes":793,"./layout_attributes":633}],624:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); - -module.exports = function calc(gd) { - var calcdata = gd.calcdata; - var fullLayout = gd._fullLayout; - - function makeCoerceHoverInfo(trace) { - return function(val) { - return Lib.coerceHoverinfo({hoverinfo: val}, {_module: trace._module}, fullLayout); - }; - } - - for(var i = 0; i < calcdata.length; i++) { - var cd = calcdata[i]; - var trace = cd[0].trace; - - // don't include hover calc fields for pie traces - // as calcdata items might be sorted by value and - // won't match the data array order. - if(Registry.traceIs(trace, 'pie-like')) continue; - - var fillFn = Registry.traceIs(trace, '2dMap') ? paste : Lib.fillArray; - - fillFn(trace.hoverinfo, cd, 'hi', makeCoerceHoverInfo(trace)); - - if(trace.hovertemplate) fillFn(trace.hovertemplate, cd, 'ht'); - - if(!trace.hoverlabel) continue; - - fillFn(trace.hoverlabel.bgcolor, cd, 'hbg'); - fillFn(trace.hoverlabel.bordercolor, cd, 'hbc'); - fillFn(trace.hoverlabel.font.size, cd, 'hts'); - fillFn(trace.hoverlabel.font.color, cd, 'htc'); - fillFn(trace.hoverlabel.font.family, cd, 'htf'); - fillFn(trace.hoverlabel.namelength, cd, 'hnl'); - fillFn(trace.hoverlabel.align, cd, 'hta'); - } -}; - -function paste(traceAttr, cd, cdAttr, fn) { - fn = fn || Lib.identity; - - if(Array.isArray(traceAttr)) { - cd[0][cdAttr] = fn(traceAttr); - } -} - -},{"../../lib":719,"../../registry":847}],625:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var hover = _dereq_('./hover').hover; - -module.exports = function click(gd, evt, subplot) { - var annotationsDone = Registry.getComponentMethod('annotations', 'onClick')(gd, gd._hoverdata); - - // fallback to fail-safe in case the plot type's hover method doesn't pass the subplot. - // Ternary, for example, didn't, but it was caught because tested. - if(subplot !== undefined) { - // The true flag at the end causes it to re-run the hover computation to figure out *which* - // point is being clicked. Without this, clicking is somewhat unreliable. - hover(gd, evt, subplot, true); - } - - function emitClick() { gd.emit('plotly_click', {points: gd._hoverdata, event: evt}); } - - if(gd._hoverdata && evt && evt.target) { - if(annotationsDone && annotationsDone.then) { - annotationsDone.then(emitClick); - } else emitClick(); - - // why do we get a double event without this??? - if(evt.stopImmediatePropagation) evt.stopImmediatePropagation(); - } -}; - -},{"../../registry":847,"./hover":629}],626:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - // hover labels for multiple horizontal bars get tilted by this angle - YANGLE: 60, - - // size and display constants for hover text - - // pixel size of hover arrows - HOVERARROWSIZE: 6, - // pixels padding around text - HOVERTEXTPAD: 3, - // hover font - HOVERFONTSIZE: 13, - HOVERFONT: 'Arial, sans-serif', - - // minimum time (msec) between hover calls - HOVERMINTIME: 50, - - // ID suffix (with fullLayout._uid) for hover events in the throttle cache - HOVERID: '-hover' -}; - -},{}],627:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attributes = _dereq_('./attributes'); -var handleHoverLabelDefaults = _dereq_('./hoverlabel_defaults'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var opts = Lib.extendFlat({}, layout.hoverlabel); - if(traceOut.hovertemplate) opts.namelength = -1; - - handleHoverLabelDefaults(traceIn, traceOut, coerce, opts); -}; - -},{"../../lib":719,"./attributes":623,"./hoverlabel_defaults":630}],628:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -// look for either subplot or xaxis and yaxis attributes -// does not handle splom case -exports.getSubplot = function getSubplot(trace) { - return trace.subplot || (trace.xaxis + trace.yaxis) || trace.geo; -}; - -// is trace in given list of subplots? -// does handle splom case -exports.isTraceInSubplots = function isTraceInSubplots(trace, subplots) { - if(trace.type === 'splom') { - var xaxes = trace.xaxes || []; - var yaxes = trace.yaxes || []; - for(var i = 0; i < xaxes.length; i++) { - for(var j = 0; j < yaxes.length; j++) { - if(subplots.indexOf(xaxes[i] + yaxes[j]) !== -1) { - return true; - } - } - } - return false; - } - - return subplots.indexOf(exports.getSubplot(trace)) !== -1; -}; - -// convenience functions for mapping all relevant axes -exports.flat = function flat(subplots, v) { - var out = new Array(subplots.length); - for(var i = 0; i < subplots.length; i++) { - out[i] = v; - } - return out; -}; - -exports.p2c = function p2c(axArray, v) { - var out = new Array(axArray.length); - for(var i = 0; i < axArray.length; i++) { - out[i] = axArray[i].p2c(v); - } - return out; -}; - -exports.getDistanceFunction = function getDistanceFunction(mode, dx, dy, dxy) { - if(mode === 'closest') return dxy || exports.quadrature(dx, dy); - return mode === 'x' ? dx : dy; -}; - -exports.getClosest = function getClosest(cd, distfn, pointData) { - // do we already have a point number? (array mode only) - if(pointData.index !== false) { - if(pointData.index >= 0 && pointData.index < cd.length) { - pointData.distance = 0; - } else pointData.index = false; - } else { - // apply the distance function to each data point - // this is the longest loop... if this bogs down, we may need - // to create pre-sorted data (by x or y), not sure how to - // do this for 'closest' - for(var i = 0; i < cd.length; i++) { - var newDistance = distfn(cd[i]); - if(newDistance <= pointData.distance) { - pointData.index = i; - pointData.distance = newDistance; - } - } - } - return pointData; -}; - -/* - * pseudo-distance function for hover effects on areas: inside the region - * distance is finite (`passVal`), outside it's Infinity. - * - * @param {number} v0: signed difference between the current position and the left edge - * @param {number} v1: signed difference between the current position and the right edge - * @param {number} passVal: the value to return on success - */ -exports.inbox = function inbox(v0, v1, passVal) { - return (v0 * v1 < 0 || v0 === 0) ? passVal : Infinity; -}; - -exports.quadrature = function quadrature(dx, dy) { - return function(di) { - var x = dx(di); - var y = dy(di); - return Math.sqrt(x * x + y * y); - }; -}; - -/** Fill event data point object for hover and selection. - * Invokes _module.eventData if present. - * - * N.B. note that point 'index' corresponds to input data array index - * whereas 'number' is its post-transform version. - * - * If the hovered/selected pt corresponds to an multiple input points - * (e.g. for histogram and transformed traces), 'pointNumbers` and 'pointIndices' - * are include in the event data. - * - * @param {object} pt - * @param {object} trace - * @param {object} cd - * @return {object} - */ -exports.makeEventData = function makeEventData(pt, trace, cd) { - // hover uses 'index', select uses 'pointNumber' - var pointNumber = 'index' in pt ? pt.index : pt.pointNumber; - - var out = { - data: trace._input, - fullData: trace, - curveNumber: trace.index, - pointNumber: pointNumber - }; - - if(trace._indexToPoints) { - var pointIndices = trace._indexToPoints[pointNumber]; - - if(pointIndices.length === 1) { - out.pointIndex = pointIndices[0]; - } else { - out.pointIndices = pointIndices; - } - } else { - out.pointIndex = pointNumber; - } - - if(trace._module.eventData) { - out = trace._module.eventData(out, pt, trace, cd, pointNumber); - } else { - if('xVal' in pt) out.x = pt.xVal; - else if('x' in pt) out.x = pt.x; - - if('yVal' in pt) out.y = pt.yVal; - else if('y' in pt) out.y = pt.y; - - if(pt.xa) out.xaxis = pt.xa; - if(pt.ya) out.yaxis = pt.ya; - if(pt.zLabelVal !== undefined) out.z = pt.zLabelVal; - } - - exports.appendArrayPointValue(out, trace, pointNumber); - - return out; -}; - -/** Appends values inside array attributes corresponding to given point number - * - * @param {object} pointData : point data object (gets mutated here) - * @param {object} trace : full trace object - * @param {number|Array(number)} pointNumber : point number. May be a length-2 array - * [row, col] to dig into 2D arrays - */ -exports.appendArrayPointValue = function(pointData, trace, pointNumber) { - var arrayAttrs = trace._arrayAttrs; - - if(!arrayAttrs) { - return; - } - - for(var i = 0; i < arrayAttrs.length; i++) { - var astr = arrayAttrs[i]; - var key = getPointKey(astr); - - if(pointData[key] === undefined) { - var val = Lib.nestedProperty(trace, astr).get(); - var pointVal = getPointData(val, pointNumber); - - if(pointVal !== undefined) pointData[key] = pointVal; - } - } -}; - -/** - * Appends values inside array attributes corresponding to given point number array - * For use when pointData references a plot entity that arose (or potentially arose) - * from multiple points in the input data - * - * @param {object} pointData : point data object (gets mutated here) - * @param {object} trace : full trace object - * @param {Array(number)|Array(Array(number))} pointNumbers : Array of point numbers. - * Each entry in the array may itself be a length-2 array [row, col] to dig into 2D arrays - */ -exports.appendArrayMultiPointValues = function(pointData, trace, pointNumbers) { - var arrayAttrs = trace._arrayAttrs; - - if(!arrayAttrs) { - return; - } - - for(var i = 0; i < arrayAttrs.length; i++) { - var astr = arrayAttrs[i]; - var key = getPointKey(astr); - - if(pointData[key] === undefined) { - var val = Lib.nestedProperty(trace, astr).get(); - var keyVal = new Array(pointNumbers.length); - - for(var j = 0; j < pointNumbers.length; j++) { - keyVal[j] = getPointData(val, pointNumbers[j]); - } - pointData[key] = keyVal; - } - } -}; - -var pointKeyMap = { - ids: 'id', - locations: 'location', - labels: 'label', - values: 'value', - 'marker.colors': 'color', - parents: 'parent' -}; - -function getPointKey(astr) { - return pointKeyMap[astr] || astr; -} - -function getPointData(val, pointNumber) { - if(Array.isArray(pointNumber)) { - if(Array.isArray(val) && Array.isArray(val[pointNumber[0]])) { - return val[pointNumber[0]][pointNumber[1]]; - } - } else { - return val[pointNumber]; - } -} - -},{"../../lib":719}],629:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); -var tinycolor = _dereq_('tinycolor2'); - -var Lib = _dereq_('../../lib'); -var Events = _dereq_('../../lib/events'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var overrideCursor = _dereq_('../../lib/override_cursor'); -var Drawing = _dereq_('../drawing'); -var Color = _dereq_('../color'); -var dragElement = _dereq_('../dragelement'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var Registry = _dereq_('../../registry'); - -var helpers = _dereq_('./helpers'); -var constants = _dereq_('./constants'); - -// hover labels for multiple horizontal bars get tilted by some angle, -// then need to be offset differently if they overlap -var YANGLE = constants.YANGLE; -var YA_RADIANS = Math.PI * YANGLE / 180; - -// expansion of projected height -var YFACTOR = 1 / Math.sin(YA_RADIANS); - -// to make the appropriate post-rotation x offset, -// you need both x and y offsets -var YSHIFTX = Math.cos(YA_RADIANS); -var YSHIFTY = Math.sin(YA_RADIANS); - -// size and display constants for hover text -var HOVERARROWSIZE = constants.HOVERARROWSIZE; -var HOVERTEXTPAD = constants.HOVERTEXTPAD; - -// fx.hover: highlight data on hover -// evt can be a mousemove event, or an object with data about what points -// to hover on -// {xpx,ypx[,hovermode]} - pixel locations from top left -// (with optional overriding hovermode) -// {xval,yval[,hovermode]} - data values -// [{curveNumber,(pointNumber|xval and/or yval)}] - -// array of specific points to highlight -// pointNumber is a single integer if gd.data[curveNumber] is 1D, -// or a two-element array if it's 2D -// xval and yval are data values, -// 1D data may specify either or both, -// 2D data must specify both -// subplot is an id string (default "xy") -// makes use of gl.hovermode, which can be: -// x (find the points with the closest x values, ie a column), -// closest (find the single closest point) -// internally there are two more that occasionally get used: -// y (pick out a row - only used for multiple horizontal bar charts) -// array (used when the user specifies an explicit -// array of points to hover on) -// -// We wrap the hovers in a timer, to limit their frequency. -// The actual rendering is done by private function _hover. -exports.hover = function hover(gd, evt, subplot, noHoverEvent) { - gd = Lib.getGraphDiv(gd); - - Lib.throttle( - gd._fullLayout._uid + constants.HOVERID, - constants.HOVERMINTIME, - function() { _hover(gd, evt, subplot, noHoverEvent); } - ); -}; - -/* - * Draw a single hover item or an array of hover item in a pre-existing svg container somewhere - * hoverItem should have keys: - * - x and y (or x0, x1, y0, and y1): - * the pixel position to mark, relative to opts.container - * - xLabel, yLabel, zLabel, text, and name: - * info to go in the label - * - color: - * the background color for the label. - * - idealAlign (optional): - * 'left' or 'right' for which side of the x/y box to try to put this on first - * - borderColor (optional): - * color for the border, defaults to strongest contrast with color - * - fontFamily (optional): - * string, the font for this label, defaults to constants.HOVERFONT - * - fontSize (optional): - * the label font size, defaults to constants.HOVERFONTSIZE - * - fontColor (optional): - * defaults to borderColor - * opts should have keys: - * - bgColor: - * the background color this is against, used if the trace is - * non-opaque, and for the name, which goes outside the box - * - container: - * a or element to add the hover label to - * - outerContainer: - * normally a parent of `container`, sets the bounding box to use to - * constrain the hover label and determine whether to show it on the left or right - * opts can have optional keys: - * - anchorIndex: - the index of the hover item used as an anchor for positioning. - The other hover items will be pushed up or down to prevent overlap. - */ -exports.loneHover = function loneHover(hoverItems, opts) { - var multiHover = true; - if(!Array.isArray(hoverItems)) { - multiHover = false; - hoverItems = [hoverItems]; - } - - var pointsData = hoverItems.map(function(hoverItem) { - return { - color: hoverItem.color || Color.defaultLine, - x0: hoverItem.x0 || hoverItem.x || 0, - x1: hoverItem.x1 || hoverItem.x || 0, - y0: hoverItem.y0 || hoverItem.y || 0, - y1: hoverItem.y1 || hoverItem.y || 0, - xLabel: hoverItem.xLabel, - yLabel: hoverItem.yLabel, - zLabel: hoverItem.zLabel, - text: hoverItem.text, - name: hoverItem.name, - idealAlign: hoverItem.idealAlign, - - // optional extra bits of styling - borderColor: hoverItem.borderColor, - fontFamily: hoverItem.fontFamily, - fontSize: hoverItem.fontSize, - fontColor: hoverItem.fontColor, - nameLength: hoverItem.nameLength, - textAlign: hoverItem.textAlign, - - // filler to make createHoverText happy - trace: hoverItem.trace || { - index: 0, - hoverinfo: '' - }, - xa: {_offset: 0}, - ya: {_offset: 0}, - index: 0, - - hovertemplate: hoverItem.hovertemplate || false, - eventData: hoverItem.eventData || false, - hovertemplateLabels: hoverItem.hovertemplateLabels || false, - }; - }); - - var container3 = d3.select(opts.container); - var outerContainer3 = opts.outerContainer ? d3.select(opts.outerContainer) : container3; - - var fullOpts = { - hovermode: 'closest', - rotateLabels: false, - bgColor: opts.bgColor || Color.background, - container: container3, - outerContainer: outerContainer3 - }; - - var hoverLabel = createHoverText(pointsData, fullOpts, opts.gd); - - // Fix vertical overlap - var tooltipSpacing = 5; - var lastBottomY = 0; - var anchor = 0; - hoverLabel - .sort(function(a, b) {return a.y0 - b.y0;}) - .each(function(d, i) { - var topY = d.y0 - d.by / 2; - - if((topY - tooltipSpacing) < lastBottomY) { - d.offset = (lastBottomY - topY) + tooltipSpacing; - } else { - d.offset = 0; - } - - lastBottomY = topY + d.by + d.offset; - - if(i === opts.anchorIndex || 0) anchor = d.offset; - }) - .each(function(d) { - d.offset -= anchor; - }); - - alignHoverText(hoverLabel, fullOpts.rotateLabels); - - return multiHover ? hoverLabel : hoverLabel.node(); -}; - -// The actual implementation is here: -function _hover(gd, evt, subplot, noHoverEvent) { - if(!subplot) subplot = 'xy'; - - // if the user passed in an array of subplots, - // use those instead of finding overlayed plots - var subplots = Array.isArray(subplot) ? subplot : [subplot]; - - var fullLayout = gd._fullLayout; - var plots = fullLayout._plots || []; - var plotinfo = plots[subplot]; - var hasCartesian = fullLayout._has('cartesian'); - - // list of all overlaid subplots to look at - if(plotinfo) { - var overlayedSubplots = plotinfo.overlays.map(function(pi) { - return pi.id; - }); - - subplots = subplots.concat(overlayedSubplots); - } - - var len = subplots.length; - var xaArray = new Array(len); - var yaArray = new Array(len); - var supportsCompare = false; - - for(var i = 0; i < len; i++) { - var spId = subplots[i]; - - // 'cartesian' case - var plotObj = plots[spId]; - if(plotObj) { - supportsCompare = true; - - // TODO make sure that fullLayout_plots axis refs - // get updated properly so that we don't have - // to use Axes.getFromId in general. - - xaArray[i] = Axes.getFromId(gd, plotObj.xaxis._id); - yaArray[i] = Axes.getFromId(gd, plotObj.yaxis._id); - continue; - } - - // other subplot types - var _subplot = fullLayout[spId]._subplot; - xaArray[i] = _subplot.xaxis; - yaArray[i] = _subplot.yaxis; - } - - var hovermode = evt.hovermode || fullLayout.hovermode; - - if(hovermode && !supportsCompare) hovermode = 'closest'; - - if(['x', 'y', 'closest'].indexOf(hovermode) === -1 || !gd.calcdata || - gd.querySelector('.zoombox') || gd._dragging) { - return dragElement.unhoverRaw(gd, evt); - } - - var hoverdistance = fullLayout.hoverdistance === -1 ? Infinity : fullLayout.hoverdistance; - var spikedistance = fullLayout.spikedistance === -1 ? Infinity : fullLayout.spikedistance; - - // hoverData: the set of candidate points we've found to highlight - var hoverData = []; - - // searchData: the data to search in. Mostly this is just a copy of - // gd.calcdata, filtered to the subplot and overlays we're on - // but if a point array is supplied it will be a mapping - // of indicated curves - var searchData = []; - - // [x|y]valArray: the axis values of the hover event - // mapped onto each of the currently selected overlaid subplots - var xvalArray, yvalArray; - - var itemnum, curvenum, cd, trace, subplotId, subploti, mode, - xval, yval, pointData, closedataPreviousLength; - - // spikePoints: the set of candidate points we've found to draw spikes to - var spikePoints = { - hLinePoint: null, - vLinePoint: null - }; - - // does subplot have one (or more) horizontal traces? - // This is used to determine whether we rotate the labels or not - var hasOneHorizontalTrace = false; - - // Figure out what we're hovering on: - // mouse location or user-supplied data - - if(Array.isArray(evt)) { - // user specified an array of points to highlight - hovermode = 'array'; - for(itemnum = 0; itemnum < evt.length; itemnum++) { - cd = gd.calcdata[evt[itemnum].curveNumber || 0]; - if(cd) { - trace = cd[0].trace; - if(cd[0].trace.hoverinfo !== 'skip') { - searchData.push(cd); - if(trace.orientation === 'h') { - hasOneHorizontalTrace = true; - } - } - } - } - } else { - for(curvenum = 0; curvenum < gd.calcdata.length; curvenum++) { - cd = gd.calcdata[curvenum]; - trace = cd[0].trace; - if(trace.hoverinfo !== 'skip' && helpers.isTraceInSubplots(trace, subplots)) { - searchData.push(cd); - if(trace.orientation === 'h') { - hasOneHorizontalTrace = true; - } - } - } - - // [x|y]px: the pixels (from top left) of the mouse location - // on the currently selected plot area - // add pointerX|Y property for drawing the spikes in spikesnap 'cursor' situation - var hasUserCalledHover = !evt.target; - var xpx, ypx; - - if(hasUserCalledHover) { - if('xpx' in evt) xpx = evt.xpx; - else xpx = xaArray[0]._length / 2; - - if('ypx' in evt) ypx = evt.ypx; - else ypx = yaArray[0]._length / 2; - } else { - // fire the beforehover event and quit if it returns false - // note that we're only calling this on real mouse events, so - // manual calls to fx.hover will always run. - if(Events.triggerHandler(gd, 'plotly_beforehover', evt) === false) { - return; - } - - var dbb = evt.target.getBoundingClientRect(); - - xpx = evt.clientX - dbb.left; - ypx = evt.clientY - dbb.top; - - // in case hover was called from mouseout into hovertext, - // it's possible you're not actually over the plot anymore - if(xpx < 0 || xpx > xaArray[0]._length || ypx < 0 || ypx > yaArray[0]._length) { - return dragElement.unhoverRaw(gd, evt); - } - } - - evt.pointerX = xpx + xaArray[0]._offset; - evt.pointerY = ypx + yaArray[0]._offset; - - if('xval' in evt) xvalArray = helpers.flat(subplots, evt.xval); - else xvalArray = helpers.p2c(xaArray, xpx); - - if('yval' in evt) yvalArray = helpers.flat(subplots, evt.yval); - else yvalArray = helpers.p2c(yaArray, ypx); - - if(!isNumeric(xvalArray[0]) || !isNumeric(yvalArray[0])) { - Lib.warn('Fx.hover failed', evt, gd); - return dragElement.unhoverRaw(gd, evt); - } - } - - // the pixel distance to beat as a matching point - // in 'x' or 'y' mode this resets for each trace - var distance = Infinity; - - // find the closest point in each trace - // this is minimum dx and/or dy, depending on mode - // and the pixel position for the label (labelXpx, labelYpx) - for(curvenum = 0; curvenum < searchData.length; curvenum++) { - cd = searchData[curvenum]; - - // filter out invisible or broken data - if(!cd || !cd[0] || !cd[0].trace) continue; - - trace = cd[0].trace; - - if(trace.visible !== true || trace._length === 0) continue; - - // Explicitly bail out for these two. I don't know how to otherwise prevent - // the rest of this function from running and failing - if(['carpet', 'contourcarpet'].indexOf(trace._module.name) !== -1) continue; - - if(trace.type === 'splom') { - // splom traces do not generate overlay subplots, - // it is safe to assume here splom traces correspond to the 0th subplot - subploti = 0; - subplotId = subplots[subploti]; - } else { - subplotId = helpers.getSubplot(trace); - subploti = subplots.indexOf(subplotId); - } - - // within one trace mode can sometimes be overridden - mode = hovermode; - - // container for new point, also used to pass info into module.hoverPoints - pointData = { - // trace properties - cd: cd, - trace: trace, - xa: xaArray[subploti], - ya: yaArray[subploti], - - // max distances for hover and spikes - for points that want to show but do not - // want to override other points, set distance/spikeDistance equal to max*Distance - // and it will not get filtered out but it will be guaranteed to have a greater - // distance than any point that calculated a real distance. - maxHoverDistance: hoverdistance, - maxSpikeDistance: spikedistance, - - // point properties - override all of these - index: false, // point index in trace - only used by plotly.js hoverdata consumers - distance: Math.min(distance, hoverdistance), // pixel distance or pseudo-distance - - // distance/pseudo-distance for spikes. This distance should always be calculated - // as if in "closest" mode, and should only be set if this point should - // generate a spike. - spikeDistance: Infinity, - - // in some cases the spikes have different positioning from the hover label - // they don't need x0/x1, just one position - xSpike: undefined, - ySpike: undefined, - - // where and how to display the hover label - color: Color.defaultLine, // trace color - name: trace.name, - x0: undefined, - x1: undefined, - y0: undefined, - y1: undefined, - xLabelVal: undefined, - yLabelVal: undefined, - zLabelVal: undefined, - text: undefined - }; - - // add ref to subplot object (non-cartesian case) - if(fullLayout[subplotId]) { - pointData.subplot = fullLayout[subplotId]._subplot; - } - // add ref to splom scene - if(fullLayout._splomScenes && fullLayout._splomScenes[trace.uid]) { - pointData.scene = fullLayout._splomScenes[trace.uid]; - } - - closedataPreviousLength = hoverData.length; - - // for a highlighting array, figure out what - // we're searching for with this element - if(mode === 'array') { - var selection = evt[curvenum]; - if('pointNumber' in selection) { - pointData.index = selection.pointNumber; - mode = 'closest'; - } else { - mode = ''; - if('xval' in selection) { - xval = selection.xval; - mode = 'x'; - } - if('yval' in selection) { - yval = selection.yval; - mode = mode ? 'closest' : 'y'; - } - } - } else { - xval = xvalArray[subploti]; - yval = yvalArray[subploti]; - } - - // Now if there is range to look in, find the points to hover. - if(hoverdistance !== 0) { - if(trace._module && trace._module.hoverPoints) { - var newPoints = trace._module.hoverPoints(pointData, xval, yval, mode, fullLayout._hoverlayer); - if(newPoints) { - var newPoint; - for(var newPointNum = 0; newPointNum < newPoints.length; newPointNum++) { - newPoint = newPoints[newPointNum]; - if(isNumeric(newPoint.x0) && isNumeric(newPoint.y0)) { - hoverData.push(cleanPoint(newPoint, hovermode)); - } - } - } - } else { - Lib.log('Unrecognized trace type in hover:', trace); - } - } - - // in closest mode, remove any existing (farther) points - // and don't look any farther than this latest point (or points, some - // traces like box & violin make multiple hover labels at once) - if(hovermode === 'closest' && hoverData.length > closedataPreviousLength) { - hoverData.splice(0, closedataPreviousLength); - distance = hoverData[0].distance; - } - - // Now if there is range to look in, find the points to draw the spikelines - // Do it only if there is no hoverData - if(hasCartesian && (spikedistance !== 0)) { - if(hoverData.length === 0) { - pointData.distance = spikedistance; - pointData.index = false; - var closestPoints = trace._module.hoverPoints(pointData, xval, yval, 'closest', fullLayout._hoverlayer); - if(closestPoints) { - closestPoints = closestPoints.filter(function(point) { - // some hover points, like scatter fills, do not allow spikes, - // so will generate a hover point but without a valid spikeDistance - return point.spikeDistance <= spikedistance; - }); - } - if(closestPoints && closestPoints.length) { - var tmpPoint; - var closestVPoints = closestPoints.filter(function(point) { - return point.xa.showspikes; - }); - if(closestVPoints.length) { - var closestVPt = closestVPoints[0]; - if(isNumeric(closestVPt.x0) && isNumeric(closestVPt.y0)) { - tmpPoint = fillSpikePoint(closestVPt); - if(!spikePoints.vLinePoint || (spikePoints.vLinePoint.spikeDistance > tmpPoint.spikeDistance)) { - spikePoints.vLinePoint = tmpPoint; - } - } - } - - var closestHPoints = closestPoints.filter(function(point) { - return point.ya.showspikes; - }); - if(closestHPoints.length) { - var closestHPt = closestHPoints[0]; - if(isNumeric(closestHPt.x0) && isNumeric(closestHPt.y0)) { - tmpPoint = fillSpikePoint(closestHPt); - if(!spikePoints.hLinePoint || (spikePoints.hLinePoint.spikeDistance > tmpPoint.spikeDistance)) { - spikePoints.hLinePoint = tmpPoint; - } - } - } - } - } - } - } - - function selectClosestPoint(pointsData, spikedistance) { - var resultPoint = null; - var minDistance = Infinity; - var thisSpikeDistance; - for(var i = 0; i < pointsData.length; i++) { - thisSpikeDistance = pointsData[i].spikeDistance; - if(thisSpikeDistance < minDistance && thisSpikeDistance <= spikedistance) { - resultPoint = pointsData[i]; - minDistance = thisSpikeDistance; - } - } - return resultPoint; - } - - function fillSpikePoint(point) { - if(!point) return null; - return { - xa: point.xa, - ya: point.ya, - x: point.xSpike !== undefined ? point.xSpike : (point.x0 + point.x1) / 2, - y: point.ySpike !== undefined ? point.ySpike : (point.y0 + point.y1) / 2, - distance: point.distance, - spikeDistance: point.spikeDistance, - curveNumber: point.trace.index, - color: point.color, - pointNumber: point.index - }; - } - - var spikelineOpts = { - fullLayout: fullLayout, - container: fullLayout._hoverlayer, - outerContainer: fullLayout._paperdiv, - event: evt - }; - var oldspikepoints = gd._spikepoints; - var newspikepoints = { - vLinePoint: spikePoints.vLinePoint, - hLinePoint: spikePoints.hLinePoint - }; - gd._spikepoints = newspikepoints; - - // Now if it is not restricted by spikedistance option, set the points to draw the spikelines - if(hasCartesian && (spikedistance !== 0)) { - if(hoverData.length !== 0) { - var tmpHPointData = hoverData.filter(function(point) { - return point.ya.showspikes; - }); - var tmpHPoint = selectClosestPoint(tmpHPointData, spikedistance); - spikePoints.hLinePoint = fillSpikePoint(tmpHPoint); - - var tmpVPointData = hoverData.filter(function(point) { - return point.xa.showspikes; - }); - var tmpVPoint = selectClosestPoint(tmpVPointData, spikedistance); - spikePoints.vLinePoint = fillSpikePoint(tmpVPoint); - } - } - - // if hoverData is empty check for the spikes to draw and quit if there are none - if(hoverData.length === 0) { - var result = dragElement.unhoverRaw(gd, evt); - if(hasCartesian && ((spikePoints.hLinePoint !== null) || (spikePoints.vLinePoint !== null))) { - if(spikesChanged(oldspikepoints)) { - createSpikelines(spikePoints, spikelineOpts); - } - } - return result; - } - - if(hasCartesian) { - if(spikesChanged(oldspikepoints)) { - createSpikelines(spikePoints, spikelineOpts); - } - } - - hoverData.sort(function(d1, d2) { return d1.distance - d2.distance; }); - - // lastly, emit custom hover/unhover events - var oldhoverdata = gd._hoverdata; - var newhoverdata = []; - - // pull out just the data that's useful to - // other people and send it to the event - for(itemnum = 0; itemnum < hoverData.length; itemnum++) { - var pt = hoverData[itemnum]; - var eventData = helpers.makeEventData(pt, pt.trace, pt.cd); - - if(pt.hovertemplate !== false) { - var ht = false; - if(pt.cd[pt.index] && pt.cd[pt.index].ht) { - ht = pt.cd[pt.index].ht; - } - pt.hovertemplate = ht || pt.trace.hovertemplate || false; - } - - pt.eventData = [eventData]; - newhoverdata.push(eventData); - } - - gd._hoverdata = newhoverdata; - - var rotateLabels = ( - (hovermode === 'y' && (searchData.length > 1 || hoverData.length > 1)) || - (hovermode === 'closest' && hasOneHorizontalTrace && hoverData.length > 1) - ); - - var bgColor = Color.combine( - fullLayout.plot_bgcolor || Color.background, - fullLayout.paper_bgcolor - ); - - var labelOpts = { - hovermode: hovermode, - rotateLabels: rotateLabels, - bgColor: bgColor, - container: fullLayout._hoverlayer, - outerContainer: fullLayout._paperdiv, - commonLabelOpts: fullLayout.hoverlabel, - hoverdistance: fullLayout.hoverdistance - }; - - var hoverLabels = createHoverText(hoverData, labelOpts, gd); - - hoverAvoidOverlaps(hoverLabels, rotateLabels ? 'xa' : 'ya', fullLayout); - - alignHoverText(hoverLabels, rotateLabels); - - // TODO: tagName hack is needed to appease geo.js's hack of using evt.target=true - // we should improve the "fx" API so other plots can use it without these hack. - if(evt.target && evt.target.tagName) { - var hasClickToShow = Registry.getComponentMethod('annotations', 'hasClickToShow')(gd, newhoverdata); - overrideCursor(d3.select(evt.target), hasClickToShow ? 'pointer' : ''); - } - - // don't emit events if called manually - if(!evt.target || noHoverEvent || !hoverChanged(gd, evt, oldhoverdata)) return; - - if(oldhoverdata) { - gd.emit('plotly_unhover', { - event: evt, - points: oldhoverdata - }); - } - - gd.emit('plotly_hover', { - event: evt, - points: gd._hoverdata, - xaxes: xaArray, - yaxes: yaArray, - xvals: xvalArray, - yvals: yvalArray - }); -} - -var EXTRA_STRING_REGEX = /([\s\S]*)<\/extra>/; - -function createHoverText(hoverData, opts, gd) { - var fullLayout = gd._fullLayout; - var hovermode = opts.hovermode; - var rotateLabels = opts.rotateLabels; - var bgColor = opts.bgColor; - var container = opts.container; - var outerContainer = opts.outerContainer; - var commonLabelOpts = opts.commonLabelOpts || {}; - - // opts.fontFamily/Size are used for the common label - // and as defaults for each hover label, though the individual labels - // can override this. - var fontFamily = opts.fontFamily || constants.HOVERFONT; - var fontSize = opts.fontSize || constants.HOVERFONTSIZE; - - var c0 = hoverData[0]; - var xa = c0.xa; - var ya = c0.ya; - var commonAttr = hovermode === 'y' ? 'yLabel' : 'xLabel'; - var t0 = c0[commonAttr]; - var t00 = (String(t0) || '').split(' ')[0]; - var outerContainerBB = outerContainer.node().getBoundingClientRect(); - var outerTop = outerContainerBB.top; - var outerWidth = outerContainerBB.width; - var outerHeight = outerContainerBB.height; - - // show the common label, if any, on the axis - // never show a common label in array mode, - // even if sometimes there could be one - var showCommonLabel = ( - (t0 !== undefined) && - (c0.distance <= opts.hoverdistance) && - (hovermode === 'x' || hovermode === 'y') - ); - - // all hover traces hoverinfo must contain the hovermode - // to have common labels - if(showCommonLabel) { - var allHaveZ = true; - var i, traceHoverinfo; - for(i = 0; i < hoverData.length; i++) { - if(allHaveZ && hoverData[i].zLabel === undefined) allHaveZ = false; - - traceHoverinfo = hoverData[i].hoverinfo || hoverData[i].trace.hoverinfo; - if(traceHoverinfo) { - var parts = Array.isArray(traceHoverinfo) ? traceHoverinfo : traceHoverinfo.split('+'); - if(parts.indexOf('all') === -1 && - parts.indexOf(hovermode) === -1) { - showCommonLabel = false; - break; - } - } - } - - // xyz labels put all info in their main label, so have no need of a common label - if(allHaveZ) showCommonLabel = false; - } - - var commonLabel = container.selectAll('g.axistext') - .data(showCommonLabel ? [0] : []); - commonLabel.enter().append('g') - .classed('axistext', true); - commonLabel.exit().remove(); - - commonLabel.each(function() { - var label = d3.select(this); - var lpath = Lib.ensureSingle(label, 'path', '', function(s) { - s.style({'stroke-width': '1px'}); - }); - var ltext = Lib.ensureSingle(label, 'text', '', function(s) { - // prohibit tex interpretation until we can handle - // tex and regular text together - s.attr('data-notex', 1); - }); - - var commonBgColor = commonLabelOpts.bgcolor || Color.defaultLine; - var commonStroke = commonLabelOpts.bordercolor || Color.contrast(commonBgColor); - var contrastColor = Color.contrast(commonBgColor); - - lpath.style({ - fill: commonBgColor, - stroke: commonStroke - }); - - ltext.text(t0) - .call(Drawing.font, - commonLabelOpts.font.family || fontFamily, - commonLabelOpts.font.size || fontSize, - commonLabelOpts.font.color || contrastColor - ) - .call(svgTextUtils.positionText, 0, 0) - .call(svgTextUtils.convertToTspans, gd); - - label.attr('transform', ''); - - var tbb = ltext.node().getBoundingClientRect(); - if(hovermode === 'x') { - ltext.attr('text-anchor', 'middle') - .call(svgTextUtils.positionText, 0, (xa.side === 'top' ? - (outerTop - tbb.bottom - HOVERARROWSIZE - HOVERTEXTPAD) : - (outerTop - tbb.top + HOVERARROWSIZE + HOVERTEXTPAD))); - - var topsign = xa.side === 'top' ? '-' : ''; - lpath.attr('d', 'M0,0' + - 'L' + HOVERARROWSIZE + ',' + topsign + HOVERARROWSIZE + - 'H' + (HOVERTEXTPAD + tbb.width / 2) + - 'v' + topsign + (HOVERTEXTPAD * 2 + tbb.height) + - 'H-' + (HOVERTEXTPAD + tbb.width / 2) + - 'V' + topsign + HOVERARROWSIZE + 'H-' + HOVERARROWSIZE + 'Z'); - - label.attr('transform', 'translate(' + - (xa._offset + (c0.x0 + c0.x1) / 2) + ',' + - (ya._offset + (xa.side === 'top' ? 0 : ya._length)) + ')'); - } else { - ltext.attr('text-anchor', ya.side === 'right' ? 'start' : 'end') - .call(svgTextUtils.positionText, - (ya.side === 'right' ? 1 : -1) * (HOVERTEXTPAD + HOVERARROWSIZE), - outerTop - tbb.top - tbb.height / 2); - - var leftsign = ya.side === 'right' ? '' : '-'; - lpath.attr('d', 'M0,0' + - 'L' + leftsign + HOVERARROWSIZE + ',' + HOVERARROWSIZE + - 'V' + (HOVERTEXTPAD + tbb.height / 2) + - 'h' + leftsign + (HOVERTEXTPAD * 2 + tbb.width) + - 'V-' + (HOVERTEXTPAD + tbb.height / 2) + - 'H' + leftsign + HOVERARROWSIZE + 'V-' + HOVERARROWSIZE + 'Z'); - - label.attr('transform', 'translate(' + - (xa._offset + (ya.side === 'right' ? xa._length : 0)) + ',' + - (ya._offset + (c0.y0 + c0.y1) / 2) + ')'); - } - // remove the "close but not quite" points - // because of error bars, only take up to a space - hoverData = hoverData.filter(function(d) { - return (d.zLabelVal !== undefined) || - (d[commonAttr] || '').split(' ')[0] === t00; - }); - }); - - // show all the individual labels - - // first create the objects - var hoverLabels = container.selectAll('g.hovertext') - .data(hoverData, function(d) { - // N.B. when multiple items have the same result key-function value, - // only the first of those items in hoverData gets rendered - return [d.trace.index, d.index, d.x0, d.y0, d.name, d.attr, d.xa, d.ya || ''].join(','); - }); - hoverLabels.enter().append('g') - .classed('hovertext', true) - .each(function() { - var g = d3.select(this); - // trace name label (rect and text.name) - g.append('rect') - .call(Color.fill, Color.addOpacity(bgColor, 0.8)); - g.append('text').classed('name', true); - // trace data label (path and text.nums) - g.append('path') - .style('stroke-width', '1px'); - g.append('text').classed('nums', true) - .call(Drawing.font, fontFamily, fontSize); - }); - hoverLabels.exit().remove(); - - // then put the text in, position the pointer to the data, - // and figure out sizes - hoverLabels.each(function(d) { - var g = d3.select(this).attr('transform', ''); - var name = ''; - var text = ''; - - // combine possible non-opaque trace color with bgColor - var color0 = d.bgcolor || d.color; - // color for 'nums' part of the label - var numsColor = Color.combine( - Color.opacity(color0) ? color0 : Color.defaultLine, - bgColor - ); - // color for 'name' part of the label - var nameColor = Color.combine( - Color.opacity(d.color) ? d.color : Color.defaultLine, - bgColor - ); - // find a contrasting color for border and text - var contrastColor = d.borderColor || Color.contrast(numsColor); - - // to get custom 'name' labels pass cleanPoint - if(d.nameOverride !== undefined) d.name = d.nameOverride; - - if(d.name) { - if(d.trace._meta) { - d.name = Lib.templateString(d.name, d.trace._meta); - } - name = plainText(d.name, d.nameLength); - } - - if(d.zLabel !== undefined) { - if(d.xLabel !== undefined) text += 'x: ' + d.xLabel + '
'; - if(d.yLabel !== undefined) text += 'y: ' + d.yLabel + '
'; - if(d.trace.type !== 'choropleth' && d.trace.type !== 'choroplethmapbox') { - text += (text ? 'z: ' : '') + d.zLabel; - } - } else if(showCommonLabel && d[hovermode + 'Label'] === t0) { - text = d[(hovermode === 'x' ? 'y' : 'x') + 'Label'] || ''; - } else if(d.xLabel === undefined) { - if(d.yLabel !== undefined && d.trace.type !== 'scattercarpet') { - text = d.yLabel; - } - } else if(d.yLabel === undefined) text = d.xLabel; - else text = '(' + d.xLabel + ', ' + d.yLabel + ')'; - - if((d.text || d.text === 0) && !Array.isArray(d.text)) { - text += (text ? '
' : '') + d.text; - } - - // used by other modules (initially just ternary) that - // manage their own hoverinfo independent of cleanPoint - // the rest of this will still apply, so such modules - // can still put things in (x|y|z)Label, text, and name - // and hoverinfo will still determine their visibility - if(d.extraText !== undefined) text += (text ? '
' : '') + d.extraText; - - // if 'text' is empty at this point, - // and hovertemplate is not defined, - // put 'name' in main label and don't show secondary label - if(text === '' && !d.hovertemplate) { - // if 'name' is also empty, remove entire label - if(name === '') g.remove(); - text = name; - } - - // hovertemplate - var d3locale = fullLayout._d3locale; - var hovertemplate = d.hovertemplate || false; - var hovertemplateLabels = d.hovertemplateLabels || d; - var eventData = d.eventData[0] || {}; - if(hovertemplate) { - text = Lib.hovertemplateString( - hovertemplate, - hovertemplateLabels, - d3locale, - eventData, - d.trace._meta - ); - - text = text.replace(EXTRA_STRING_REGEX, function(match, extra) { - // assign name for secondary text label - name = plainText(extra, d.nameLength); - // remove from main text label - return ''; - }); - } - - // main label - var tx = g.select('text.nums') - .call(Drawing.font, - d.fontFamily || fontFamily, - d.fontSize || fontSize, - d.fontColor || contrastColor) - .text(text) - .attr('data-notex', 1) - .call(svgTextUtils.positionText, 0, 0) - .call(svgTextUtils.convertToTspans, gd); - - var tx2 = g.select('text.name'); - var tx2width = 0; - var tx2height = 0; - - // secondary label for non-empty 'name' - if(name && name !== text) { - tx2.call(Drawing.font, - d.fontFamily || fontFamily, - d.fontSize || fontSize, - nameColor) - .text(name) - .attr('data-notex', 1) - .call(svgTextUtils.positionText, 0, 0) - .call(svgTextUtils.convertToTspans, gd); - - var t2bb = tx2.node().getBoundingClientRect(); - tx2width = t2bb.width + 2 * HOVERTEXTPAD; - tx2height = t2bb.height + 2 * HOVERTEXTPAD; - } else { - tx2.remove(); - g.select('rect').remove(); - } - - g.select('path').style({ - fill: numsColor, - stroke: contrastColor - }); - - var tbb = tx.node().getBoundingClientRect(); - var htx = d.xa._offset + (d.x0 + d.x1) / 2; - var hty = d.ya._offset + (d.y0 + d.y1) / 2; - var dx = Math.abs(d.x1 - d.x0); - var dy = Math.abs(d.y1 - d.y0); - var txTotalWidth = tbb.width + HOVERARROWSIZE + HOVERTEXTPAD + tx2width; - var anchorStartOK, anchorEndOK; - - d.ty0 = outerTop - tbb.top; - d.bx = tbb.width + 2 * HOVERTEXTPAD; - d.by = Math.max(tbb.height + 2 * HOVERTEXTPAD, tx2height); - d.anchor = 'start'; - d.txwidth = tbb.width; - d.tx2width = tx2width; - d.offset = 0; - - if(rotateLabels) { - d.pos = htx; - anchorStartOK = hty + dy / 2 + txTotalWidth <= outerHeight; - anchorEndOK = hty - dy / 2 - txTotalWidth >= 0; - if((d.idealAlign === 'top' || !anchorStartOK) && anchorEndOK) { - hty -= dy / 2; - d.anchor = 'end'; - } else if(anchorStartOK) { - hty += dy / 2; - d.anchor = 'start'; - } else d.anchor = 'middle'; - } else { - d.pos = hty; - anchorStartOK = htx + dx / 2 + txTotalWidth <= outerWidth; - anchorEndOK = htx - dx / 2 - txTotalWidth >= 0; - - if((d.idealAlign === 'left' || !anchorStartOK) && anchorEndOK) { - htx -= dx / 2; - d.anchor = 'end'; - } else if(anchorStartOK) { - htx += dx / 2; - d.anchor = 'start'; - } else { - d.anchor = 'middle'; - - var txHalfWidth = txTotalWidth / 2; - var overflowR = htx + txHalfWidth - outerWidth; - var overflowL = htx - txHalfWidth; - if(overflowR > 0) htx -= overflowR; - if(overflowL < 0) htx += -overflowL; - } - } - - tx.attr('text-anchor', d.anchor); - if(tx2width) tx2.attr('text-anchor', d.anchor); - g.attr('transform', 'translate(' + htx + ',' + hty + ')' + - (rotateLabels ? 'rotate(' + YANGLE + ')' : '')); - }); - - return hoverLabels; -} - -// Make groups of touching points, and within each group -// move each point so that no labels overlap, but the average -// label position is the same as it was before moving. Indicentally, -// this is equivalent to saying all the labels are on equal linear -// springs about their initial position. Initially, each point is -// its own group, but as we find overlaps we will clump the points. -// -// Also, there are hard constraints at the edges of the graphs, -// that push all groups to the middle so they are visible. I don't -// know what happens if the group spans all the way from one edge to -// the other, though it hardly matters - there's just too much -// information then. -function hoverAvoidOverlaps(hoverLabels, axKey, fullLayout) { - var nummoves = 0; - var axSign = 1; - var nLabels = hoverLabels.size(); - - // make groups of touching points - var pointgroups = new Array(nLabels); - var k = 0; - - hoverLabels.each(function(d) { - var ax = d[axKey]; - var axIsX = ax._id.charAt(0) === 'x'; - var rng = ax.range; - - if(k === 0 && rng && ((rng[0] > rng[1]) !== axIsX)) { - axSign = -1; - } - pointgroups[k++] = [{ - datum: d, - traceIndex: d.trace.index, - dp: 0, - pos: d.pos, - posref: d.posref, - size: d.by * (axIsX ? YFACTOR : 1) / 2, - pmin: 0, - pmax: (axIsX ? fullLayout.width : fullLayout.height) - }]; - }); - - pointgroups.sort(function(a, b) { - return (a[0].posref - b[0].posref) || - // for equal positions, sort trace indices increasing or decreasing - // depending on whether the axis is reversed or not... so stacked - // traces will generally keep their order even if one trace adds - // nothing to the stack. - (axSign * (b[0].traceIndex - a[0].traceIndex)); - }); - - var donepositioning, topOverlap, bottomOverlap, i, j, pti, sumdp; - - function constrainGroup(grp) { - var minPt = grp[0]; - var maxPt = grp[grp.length - 1]; - - // overlap with the top - positive vals are overlaps - topOverlap = minPt.pmin - minPt.pos - minPt.dp + minPt.size; - - // overlap with the bottom - positive vals are overlaps - bottomOverlap = maxPt.pos + maxPt.dp + maxPt.size - minPt.pmax; - - // check for min overlap first, so that we always - // see the largest labels - // allow for .01px overlap, so we don't get an - // infinite loop from rounding errors - if(topOverlap > 0.01) { - for(j = grp.length - 1; j >= 0; j--) grp[j].dp += topOverlap; - donepositioning = false; - } - if(bottomOverlap < 0.01) return; - if(topOverlap < -0.01) { - // make sure we're not pushing back and forth - for(j = grp.length - 1; j >= 0; j--) grp[j].dp -= bottomOverlap; - donepositioning = false; - } - if(!donepositioning) return; - - // no room to fix positioning, delete off-screen points - - // first see how many points we need to delete - var deleteCount = 0; - for(i = 0; i < grp.length; i++) { - pti = grp[i]; - if(pti.pos + pti.dp + pti.size > minPt.pmax) deleteCount++; - } - - // start by deleting points whose data is off screen - for(i = grp.length - 1; i >= 0; i--) { - if(deleteCount <= 0) break; - pti = grp[i]; - - // pos has already been constrained to [pmin,pmax] - // so look for points close to that to delete - if(pti.pos > minPt.pmax - 1) { - pti.del = true; - deleteCount--; - } - } - for(i = 0; i < grp.length; i++) { - if(deleteCount <= 0) break; - pti = grp[i]; - - // pos has already been constrained to [pmin,pmax] - // so look for points close to that to delete - if(pti.pos < minPt.pmin + 1) { - pti.del = true; - deleteCount--; - - // shift the whole group minus into this new space - bottomOverlap = pti.size * 2; - for(j = grp.length - 1; j >= 0; j--) grp[j].dp -= bottomOverlap; - } - } - // then delete points that go off the bottom - for(i = grp.length - 1; i >= 0; i--) { - if(deleteCount <= 0) break; - pti = grp[i]; - if(pti.pos + pti.dp + pti.size > minPt.pmax) { - pti.del = true; - deleteCount--; - } - } - } - - // loop through groups, combining them if they overlap, - // until nothing moves - while(!donepositioning && nummoves <= nLabels) { - // to avoid infinite loops, don't move more times - // than there are traces - nummoves++; - - // assume nothing will move in this iteration, - // reverse this if it does - donepositioning = true; - i = 0; - while(i < pointgroups.length - 1) { - // the higher (g0) and lower (g1) point group - var g0 = pointgroups[i]; - var g1 = pointgroups[i + 1]; - - // the lowest point in the higher group (p0) - // the highest point in the lower group (p1) - var p0 = g0[g0.length - 1]; - var p1 = g1[0]; - topOverlap = p0.pos + p0.dp + p0.size - p1.pos - p1.dp + p1.size; - - // Only group points that lie on the same axes - if(topOverlap > 0.01 && (p0.pmin === p1.pmin) && (p0.pmax === p1.pmax)) { - // push the new point(s) added to this group out of the way - for(j = g1.length - 1; j >= 0; j--) g1[j].dp += topOverlap; - - // add them to the group - g0.push.apply(g0, g1); - pointgroups.splice(i + 1, 1); - - // adjust for minimum average movement - sumdp = 0; - for(j = g0.length - 1; j >= 0; j--) sumdp += g0[j].dp; - bottomOverlap = sumdp / g0.length; - for(j = g0.length - 1; j >= 0; j--) g0[j].dp -= bottomOverlap; - donepositioning = false; - } else i++; - } - - // check if we're going off the plot on either side and fix - pointgroups.forEach(constrainGroup); - } - - // now put these offsets into hoverData - for(i = pointgroups.length - 1; i >= 0; i--) { - var grp = pointgroups[i]; - for(j = grp.length - 1; j >= 0; j--) { - var pt = grp[j]; - var hoverPt = pt.datum; - hoverPt.offset = pt.dp; - hoverPt.del = pt.del; - } - } -} - -function alignHoverText(hoverLabels, rotateLabels) { - // finally set the text positioning relative to the data and draw the - // box around it - hoverLabels.each(function(d) { - var g = d3.select(this); - if(d.del) return g.remove(); - - var tx = g.select('text.nums'); - var anchor = d.anchor; - var horzSign = anchor === 'end' ? -1 : 1; - var alignShift = {start: 1, end: -1, middle: 0}[anchor]; - var txx = alignShift * (HOVERARROWSIZE + HOVERTEXTPAD); - var tx2x = txx + alignShift * (d.txwidth + HOVERTEXTPAD); - var offsetX = 0; - var offsetY = d.offset; - - if(anchor === 'middle') { - txx -= d.tx2width / 2; - tx2x += d.txwidth / 2 + HOVERTEXTPAD; - } - if(rotateLabels) { - offsetY *= -YSHIFTY; - offsetX = d.offset * YSHIFTX; - } - - g.select('path').attr('d', anchor === 'middle' ? - // middle aligned: rect centered on data - ('M-' + (d.bx / 2 + d.tx2width / 2) + ',' + (offsetY - d.by / 2) + - 'h' + d.bx + 'v' + d.by + 'h-' + d.bx + 'Z') : - // left or right aligned: side rect with arrow to data - ('M0,0L' + (horzSign * HOVERARROWSIZE + offsetX) + ',' + (HOVERARROWSIZE + offsetY) + - 'v' + (d.by / 2 - HOVERARROWSIZE) + - 'h' + (horzSign * d.bx) + - 'v-' + d.by + - 'H' + (horzSign * HOVERARROWSIZE + offsetX) + - 'V' + (offsetY - HOVERARROWSIZE) + - 'Z')); - - var posX = txx + offsetX; - var posY = offsetY + d.ty0 - d.by / 2 + HOVERTEXTPAD; - var textAlign = d.textAlign || 'auto'; - - if(textAlign !== 'auto') { - if(textAlign === 'left' && anchor !== 'start') { - tx.attr('text-anchor', 'start'); - posX = anchor === 'middle' ? - -d.bx / 2 - d.tx2width / 2 + HOVERTEXTPAD : - -d.bx - HOVERTEXTPAD; - } else if(textAlign === 'right' && anchor !== 'end') { - tx.attr('text-anchor', 'end'); - posX = anchor === 'middle' ? - d.bx / 2 - d.tx2width / 2 - HOVERTEXTPAD : - d.bx + HOVERTEXTPAD; - } - } - - tx.call(svgTextUtils.positionText, posX, posY); - - if(d.tx2width) { - g.select('text.name') - .call(svgTextUtils.positionText, - tx2x + alignShift * HOVERTEXTPAD + offsetX, - offsetY + d.ty0 - d.by / 2 + HOVERTEXTPAD); - g.select('rect') - .call(Drawing.setRect, - tx2x + (alignShift - 1) * d.tx2width / 2 + offsetX, - offsetY - d.by / 2 - 1, - d.tx2width, d.by + 2); - } - }); -} - -function cleanPoint(d, hovermode) { - var index = d.index; - var trace = d.trace || {}; - var cd0 = d.cd[0]; - var cd = d.cd[index] || {}; - - function pass(v) { - return v || (isNumeric(v) && v === 0); - } - - var getVal = Array.isArray(index) ? - function(calcKey, traceKey) { - var v = Lib.castOption(cd0, index, calcKey); - return pass(v) ? v : Lib.extractOption({}, trace, '', traceKey); - } : - function(calcKey, traceKey) { - return Lib.extractOption(cd, trace, calcKey, traceKey); - }; - - function fill(key, calcKey, traceKey) { - var val = getVal(calcKey, traceKey); - if(pass(val)) d[key] = val; - } - - fill('hoverinfo', 'hi', 'hoverinfo'); - fill('bgcolor', 'hbg', 'hoverlabel.bgcolor'); - fill('borderColor', 'hbc', 'hoverlabel.bordercolor'); - fill('fontFamily', 'htf', 'hoverlabel.font.family'); - fill('fontSize', 'hts', 'hoverlabel.font.size'); - fill('fontColor', 'htc', 'hoverlabel.font.color'); - fill('nameLength', 'hnl', 'hoverlabel.namelength'); - fill('textAlign', 'hta', 'hoverlabel.align'); - - d.posref = (hovermode === 'y' || (hovermode === 'closest' && trace.orientation === 'h')) ? - (d.xa._offset + (d.x0 + d.x1) / 2) : - (d.ya._offset + (d.y0 + d.y1) / 2); - - // then constrain all the positions to be on the plot - d.x0 = Lib.constrain(d.x0, 0, d.xa._length); - d.x1 = Lib.constrain(d.x1, 0, d.xa._length); - d.y0 = Lib.constrain(d.y0, 0, d.ya._length); - d.y1 = Lib.constrain(d.y1, 0, d.ya._length); - - // and convert the x and y label values into formatted text - if(d.xLabelVal !== undefined) { - d.xLabel = ('xLabel' in d) ? d.xLabel : Axes.hoverLabelText(d.xa, d.xLabelVal); - d.xVal = d.xa.c2d(d.xLabelVal); - } - if(d.yLabelVal !== undefined) { - d.yLabel = ('yLabel' in d) ? d.yLabel : Axes.hoverLabelText(d.ya, d.yLabelVal); - d.yVal = d.ya.c2d(d.yLabelVal); - } - - // Traces like heatmaps generate the zLabel in their hoverPoints function - if(d.zLabelVal !== undefined && d.zLabel === undefined) { - d.zLabel = String(d.zLabelVal); - } - - // for box means and error bars, add the range to the label - if(!isNaN(d.xerr) && !(d.xa.type === 'log' && d.xerr <= 0)) { - var xeText = Axes.tickText(d.xa, d.xa.c2l(d.xerr), 'hover').text; - if(d.xerrneg !== undefined) { - d.xLabel += ' +' + xeText + ' / -' + - Axes.tickText(d.xa, d.xa.c2l(d.xerrneg), 'hover').text; - } else d.xLabel += ' ± ' + xeText; - - // small distance penalty for error bars, so that if there are - // traces with errors and some without, the error bar label will - // hoist up to the point - if(hovermode === 'x') d.distance += 1; - } - if(!isNaN(d.yerr) && !(d.ya.type === 'log' && d.yerr <= 0)) { - var yeText = Axes.tickText(d.ya, d.ya.c2l(d.yerr), 'hover').text; - if(d.yerrneg !== undefined) { - d.yLabel += ' +' + yeText + ' / -' + - Axes.tickText(d.ya, d.ya.c2l(d.yerrneg), 'hover').text; - } else d.yLabel += ' ± ' + yeText; - - if(hovermode === 'y') d.distance += 1; - } - - var infomode = d.hoverinfo || d.trace.hoverinfo; - - if(infomode && infomode !== 'all') { - infomode = Array.isArray(infomode) ? infomode : infomode.split('+'); - if(infomode.indexOf('x') === -1) d.xLabel = undefined; - if(infomode.indexOf('y') === -1) d.yLabel = undefined; - if(infomode.indexOf('z') === -1) d.zLabel = undefined; - if(infomode.indexOf('text') === -1) d.text = undefined; - if(infomode.indexOf('name') === -1) d.name = undefined; - } - - return d; -} - -function createSpikelines(closestPoints, opts) { - var container = opts.container; - var fullLayout = opts.fullLayout; - var evt = opts.event; - var showY = !!closestPoints.hLinePoint; - var showX = !!closestPoints.vLinePoint; - - var xa, ya; - - // Remove old spikeline items - container.selectAll('.spikeline').remove(); - - if(!(showX || showY)) return; - - var contrastColor = Color.combine(fullLayout.plot_bgcolor, fullLayout.paper_bgcolor); - - // Horizontal line (to y-axis) - if(showY) { - var hLinePoint = closestPoints.hLinePoint; - var hLinePointX, hLinePointY; - - xa = hLinePoint && hLinePoint.xa; - ya = hLinePoint && hLinePoint.ya; - var ySnap = ya.spikesnap; - - if(ySnap === 'cursor') { - hLinePointX = evt.pointerX; - hLinePointY = evt.pointerY; - } else { - hLinePointX = xa._offset + hLinePoint.x; - hLinePointY = ya._offset + hLinePoint.y; - } - var dfltHLineColor = tinycolor.readability(hLinePoint.color, contrastColor) < 1.5 ? - Color.contrast(contrastColor) : hLinePoint.color; - var yMode = ya.spikemode; - var yThickness = ya.spikethickness; - var yColor = ya.spikecolor || dfltHLineColor; - var yBB = ya._boundingBox; - var xEdge = ((yBB.left + yBB.right) / 2) < hLinePointX ? yBB.right : yBB.left; - var xBase, xEndSpike; - - if(yMode.indexOf('toaxis') !== -1 || yMode.indexOf('across') !== -1) { - if(yMode.indexOf('toaxis') !== -1) { - xBase = xEdge; - xEndSpike = hLinePointX; - } - if(yMode.indexOf('across') !== -1) { - xBase = ya._counterSpan[0]; - xEndSpike = ya._counterSpan[1]; - } - - // Foreground horizontal line (to y-axis) - container.insert('line', ':first-child') - .attr({ - x1: xBase, - x2: xEndSpike, - y1: hLinePointY, - y2: hLinePointY, - 'stroke-width': yThickness, - stroke: yColor, - 'stroke-dasharray': Drawing.dashStyle(ya.spikedash, yThickness) - }) - .classed('spikeline', true) - .classed('crisp', true); - - // Background horizontal Line (to y-axis) - container.insert('line', ':first-child') - .attr({ - x1: xBase, - x2: xEndSpike, - y1: hLinePointY, - y2: hLinePointY, - 'stroke-width': yThickness + 2, - stroke: contrastColor - }) - .classed('spikeline', true) - .classed('crisp', true); - } - // Y axis marker - if(yMode.indexOf('marker') !== -1) { - container.insert('circle', ':first-child') - .attr({ - cx: xEdge + (ya.side !== 'right' ? yThickness : -yThickness), - cy: hLinePointY, - r: yThickness, - fill: yColor - }) - .classed('spikeline', true); - } - } - - if(showX) { - var vLinePoint = closestPoints.vLinePoint; - var vLinePointX, vLinePointY; - - xa = vLinePoint && vLinePoint.xa; - ya = vLinePoint && vLinePoint.ya; - var xSnap = xa.spikesnap; - - if(xSnap === 'cursor') { - vLinePointX = evt.pointerX; - vLinePointY = evt.pointerY; - } else { - vLinePointX = xa._offset + vLinePoint.x; - vLinePointY = ya._offset + vLinePoint.y; - } - var dfltVLineColor = tinycolor.readability(vLinePoint.color, contrastColor) < 1.5 ? - Color.contrast(contrastColor) : vLinePoint.color; - var xMode = xa.spikemode; - var xThickness = xa.spikethickness; - var xColor = xa.spikecolor || dfltVLineColor; - var xBB = xa._boundingBox; - var yEdge = ((xBB.top + xBB.bottom) / 2) < vLinePointY ? xBB.bottom : xBB.top; - var yBase, yEndSpike; - - if(xMode.indexOf('toaxis') !== -1 || xMode.indexOf('across') !== -1) { - if(xMode.indexOf('toaxis') !== -1) { - yBase = yEdge; - yEndSpike = vLinePointY; - } - if(xMode.indexOf('across') !== -1) { - yBase = xa._counterSpan[0]; - yEndSpike = xa._counterSpan[1]; - } - - // Foreground vertical line (to x-axis) - container.insert('line', ':first-child') - .attr({ - x1: vLinePointX, - x2: vLinePointX, - y1: yBase, - y2: yEndSpike, - 'stroke-width': xThickness, - stroke: xColor, - 'stroke-dasharray': Drawing.dashStyle(xa.spikedash, xThickness) - }) - .classed('spikeline', true) - .classed('crisp', true); - - // Background vertical line (to x-axis) - container.insert('line', ':first-child') - .attr({ - x1: vLinePointX, - x2: vLinePointX, - y1: yBase, - y2: yEndSpike, - 'stroke-width': xThickness + 2, - stroke: contrastColor - }) - .classed('spikeline', true) - .classed('crisp', true); - } - - // X axis marker - if(xMode.indexOf('marker') !== -1) { - container.insert('circle', ':first-child') - .attr({ - cx: vLinePointX, - cy: yEdge - (xa.side !== 'top' ? xThickness : -xThickness), - r: xThickness, - fill: xColor - }) - .classed('spikeline', true); - } - } -} - -function hoverChanged(gd, evt, oldhoverdata) { - // don't emit any events if nothing changed - if(!oldhoverdata || oldhoverdata.length !== gd._hoverdata.length) return true; - - for(var i = oldhoverdata.length - 1; i >= 0; i--) { - var oldPt = oldhoverdata[i]; - var newPt = gd._hoverdata[i]; - - if(oldPt.curveNumber !== newPt.curveNumber || - String(oldPt.pointNumber) !== String(newPt.pointNumber) || - String(oldPt.pointNumbers) !== String(newPt.pointNumbers) - ) { - return true; - } - } - return false; -} - -function spikesChanged(gd, oldspikepoints) { - // don't relayout the plot because of new spikelines if spikelines points didn't change - if(!oldspikepoints) return true; - if(oldspikepoints.vLinePoint !== gd._spikepoints.vLinePoint || - oldspikepoints.hLinePoint !== gd._spikepoints.hLinePoint - ) return true; - return false; -} - -function plainText(s, len) { - return svgTextUtils.plainText(s || '', { - len: len, - allowedTags: ['br', 'sub', 'sup', 'b', 'i', 'em'] - }); -} - -},{"../../lib":719,"../../lib/events":709,"../../lib/override_cursor":730,"../../lib/svg_text_utils":743,"../../plots/cartesian/axes":767,"../../registry":847,"../color":593,"../dragelement":611,"../drawing":614,"./constants":626,"./helpers":628,"d3":163,"fast-isnumeric":225,"tinycolor2":537}],630:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) { - opts = opts || {}; - - coerce('hoverlabel.bgcolor', opts.bgcolor); - coerce('hoverlabel.bordercolor', opts.bordercolor); - coerce('hoverlabel.namelength', opts.namelength); - Lib.coerceFont(coerce, 'hoverlabel.font', opts.font); - coerce('hoverlabel.align', opts.align); -}; - -},{"../../lib":719}],631:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK; - -module.exports = function(opts, extra) { - opts = opts || {}; - extra = extra || {}; - - var descPart = extra.description ? ' ' + extra.description : ''; - var keys = extra.keys || []; - if(keys.length > 0) { - var quotedKeys = []; - for(var i = 0; i < keys.length; i++) { - quotedKeys[i] = '`' + keys[i] + '`'; - } - descPart = descPart + 'Finally, the template string has access to '; - if(keys.length === 1) { - descPart = 'variable ' + quotedKeys[0]; - } else { - descPart = 'variables ' + quotedKeys.slice(0, -1).join(', ') + ' and ' + quotedKeys.slice(-1) + '.'; - } - } - - var hovertemplate = { - valType: 'string', - - dflt: '', - editType: opts.editType || 'none', - - }; - - if(opts.arrayOk !== false) { - hovertemplate.arrayOk = true; - } - - return hovertemplate; -}; - -},{"../../constants/docs":690}],632:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Lib = _dereq_('../../lib'); -var dragElement = _dereq_('../dragelement'); -var helpers = _dereq_('./helpers'); -var layoutAttributes = _dereq_('./layout_attributes'); -var hoverModule = _dereq_('./hover'); - -module.exports = { - moduleType: 'component', - name: 'fx', - - constants: _dereq_('./constants'), - schema: { - layout: layoutAttributes - }, - - attributes: _dereq_('./attributes'), - layoutAttributes: layoutAttributes, - - supplyLayoutGlobalDefaults: _dereq_('./layout_global_defaults'), - supplyDefaults: _dereq_('./defaults'), - supplyLayoutDefaults: _dereq_('./layout_defaults'), - - calc: _dereq_('./calc'), - - getDistanceFunction: helpers.getDistanceFunction, - getClosest: helpers.getClosest, - inbox: helpers.inbox, - quadrature: helpers.quadrature, - appendArrayPointValue: helpers.appendArrayPointValue, - - castHoverOption: castHoverOption, - castHoverinfo: castHoverinfo, - - hover: hoverModule.hover, - unhover: dragElement.unhover, - - loneHover: hoverModule.loneHover, - loneUnhover: loneUnhover, - - click: _dereq_('./click') -}; - -function loneUnhover(containerOrSelection) { - // duck type whether the arg is a d3 selection because ie9 doesn't - // handle instanceof like modern browsers do. - var selection = Lib.isD3Selection(containerOrSelection) ? - containerOrSelection : - d3.select(containerOrSelection); - - selection.selectAll('g.hovertext').remove(); - selection.selectAll('.spikeline').remove(); -} - -// helpers for traces that use Fx.loneHover - -function castHoverOption(trace, ptNumber, attr) { - return Lib.castOption(trace, ptNumber, 'hoverlabel.' + attr); -} - -function castHoverinfo(trace, fullLayout, ptNumber) { - function _coerce(val) { - return Lib.coerceHoverinfo({hoverinfo: val}, {_module: trace._module}, fullLayout); - } - - return Lib.castOption(trace, ptNumber, 'hoverinfo', _coerce); -} - -},{"../../lib":719,"../dragelement":611,"./attributes":623,"./calc":624,"./click":625,"./constants":626,"./defaults":627,"./helpers":628,"./hover":629,"./layout_attributes":633,"./layout_defaults":634,"./layout_global_defaults":635,"d3":163}],633:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var constants = _dereq_('./constants'); - -var fontAttrs = _dereq_('../../plots/font_attributes')({ - editType: 'none', - -}); -fontAttrs.family.dflt = constants.HOVERFONT; -fontAttrs.size.dflt = constants.HOVERFONTSIZE; - -module.exports = { - clickmode: { - valType: 'flaglist', - - flags: ['event', 'select'], - dflt: 'event', - editType: 'plot', - extras: ['none'], - - }, - dragmode: { - valType: 'enumerated', - - values: ['zoom', 'pan', 'select', 'lasso', 'orbit', 'turntable', false], - dflt: 'zoom', - editType: 'modebar', - - }, - hovermode: { - valType: 'enumerated', - - values: ['x', 'y', 'closest', false], - editType: 'modebar', - - }, - hoverdistance: { - valType: 'integer', - min: -1, - dflt: 20, - - editType: 'none', - - }, - spikedistance: { - valType: 'integer', - min: -1, - dflt: 20, - - editType: 'none', - - }, - hoverlabel: { - bgcolor: { - valType: 'color', - - editType: 'none', - - }, - bordercolor: { - valType: 'color', - - editType: 'none', - - }, - font: fontAttrs, - align: { - valType: 'enumerated', - values: ['left', 'right', 'auto'], - dflt: 'auto', - - editType: 'none', - - }, - namelength: { - valType: 'integer', - min: -1, - dflt: 15, - - editType: 'none', - - }, - editType: 'none' - }, - selectdirection: { - valType: 'enumerated', - - values: ['h', 'v', 'd', 'any'], - dflt: 'any', - - editType: 'none' - } -}; - -},{"../../plots/font_attributes":793,"./constants":626}],634:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var layoutAttributes = _dereq_('./layout_attributes'); - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - - var clickmode = coerce('clickmode'); - - var dragMode = coerce('dragmode'); - if(dragMode === 'select') coerce('selectdirection'); - - var hovermodeDflt; - if(layoutOut._has('cartesian')) { - if(clickmode.indexOf('select') > -1) { - hovermodeDflt = 'closest'; - } else { - // flag for 'horizontal' plots: - // determines the state of the mode bar 'compare' hovermode button - layoutOut._isHoriz = isHoriz(fullData, layoutOut); - hovermodeDflt = layoutOut._isHoriz ? 'y' : 'x'; - } - } else hovermodeDflt = 'closest'; - - var hoverMode = coerce('hovermode', hovermodeDflt); - if(hoverMode) { - coerce('hoverdistance'); - coerce('spikedistance'); - } - - // if only mapbox or geo subplots is present on graph, - // reset 'zoom' dragmode to 'pan' until 'zoom' is implemented, - // so that the correct modebar button is active - var hasMapbox = layoutOut._has('mapbox'); - var hasGeo = layoutOut._has('geo'); - var len = layoutOut._basePlotModules.length; - - if(layoutOut.dragmode === 'zoom' && ( - ((hasMapbox || hasGeo) && len === 1) || - (hasMapbox && hasGeo && len === 2) - )) { - layoutOut.dragmode = 'pan'; - } -}; - -function isHoriz(fullData, fullLayout) { - var stackOpts = fullLayout._scatterStackOpts || {}; - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - var subplot = trace.xaxis + trace.yaxis; - var subplotStackOpts = stackOpts[subplot] || {}; - var groupOpts = subplotStackOpts[trace.stackgroup] || {}; - - if(trace.orientation !== 'h' && groupOpts.orientation !== 'h') { - return false; - } - } - - return true; -} - -},{"../../lib":719,"./layout_attributes":633}],635:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var handleHoverLabelDefaults = _dereq_('./hoverlabel_defaults'); -var layoutAttributes = _dereq_('./layout_attributes'); - -module.exports = function supplyLayoutGlobalDefaults(layoutIn, layoutOut) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - - handleHoverLabelDefaults(layoutIn, layoutOut, coerce); -}; - -},{"../../lib":719,"./hoverlabel_defaults":630,"./layout_attributes":633}],636:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var counterRegex = _dereq_('../../lib/regex').counter; -var domainAttrs = _dereq_('../../plots/domain').attributes; -var cartesianIdRegex = _dereq_('../../plots/cartesian/constants').idRegex; -var Template = _dereq_('../../plot_api/plot_template'); - -var gridAttrs = { - rows: { - valType: 'integer', - min: 1, - - editType: 'plot', - - }, - roworder: { - valType: 'enumerated', - values: ['top to bottom', 'bottom to top'], - dflt: 'top to bottom', - - editType: 'plot', - - }, - columns: { - valType: 'integer', - min: 1, - - editType: 'plot', - - }, - subplots: { - valType: 'info_array', - freeLength: true, - dimensions: 2, - items: {valType: 'enumerated', values: [counterRegex('xy').toString(), ''], editType: 'plot'}, - - editType: 'plot', - - }, - xaxes: { - valType: 'info_array', - freeLength: true, - items: {valType: 'enumerated', values: [cartesianIdRegex.x.toString(), ''], editType: 'plot'}, - - editType: 'plot', - - }, - yaxes: { - valType: 'info_array', - freeLength: true, - items: {valType: 'enumerated', values: [cartesianIdRegex.y.toString(), ''], editType: 'plot'}, - - editType: 'plot', - - }, - pattern: { - valType: 'enumerated', - values: ['independent', 'coupled'], - dflt: 'coupled', - - editType: 'plot', - - }, - xgap: { - valType: 'number', - min: 0, - max: 1, - - editType: 'plot', - - }, - ygap: { - valType: 'number', - min: 0, - max: 1, - - editType: 'plot', - - }, - domain: domainAttrs({name: 'grid', editType: 'plot', noGridCell: true}, { - - }), - xside: { - valType: 'enumerated', - values: ['bottom', 'bottom plot', 'top plot', 'top'], - dflt: 'bottom plot', - - editType: 'plot', - - }, - yside: { - valType: 'enumerated', - values: ['left', 'left plot', 'right plot', 'right'], - dflt: 'left plot', - - editType: 'plot', - - }, - editType: 'plot' -}; - -function getAxes(layout, grid, axLetter) { - var gridVal = grid[axLetter + 'axes']; - var splomVal = Object.keys((layout._splomAxes || {})[axLetter] || {}); - - if(Array.isArray(gridVal)) return gridVal; - if(splomVal.length) return splomVal; -} - -// the shape of the grid - this needs to be done BEFORE supplyDataDefaults -// so that non-subplot traces can place themselves in the grid -function sizeDefaults(layoutIn, layoutOut) { - var gridIn = layoutIn.grid || {}; - var xAxes = getAxes(layoutOut, gridIn, 'x'); - var yAxes = getAxes(layoutOut, gridIn, 'y'); - - if(!layoutIn.grid && !xAxes && !yAxes) return; - - var hasSubplotGrid = Array.isArray(gridIn.subplots) && Array.isArray(gridIn.subplots[0]); - var hasXaxes = Array.isArray(xAxes); - var hasYaxes = Array.isArray(yAxes); - var isSplomGenerated = ( - hasXaxes && xAxes !== gridIn.xaxes && - hasYaxes && yAxes !== gridIn.yaxes - ); - - var dfltRows, dfltColumns; - - if(hasSubplotGrid) { - dfltRows = gridIn.subplots.length; - dfltColumns = gridIn.subplots[0].length; - } else { - if(hasYaxes) dfltRows = yAxes.length; - if(hasXaxes) dfltColumns = xAxes.length; - } - - var gridOut = Template.newContainer(layoutOut, 'grid'); - - function coerce(attr, dflt) { - return Lib.coerce(gridIn, gridOut, gridAttrs, attr, dflt); - } - - var rows = coerce('rows', dfltRows); - var columns = coerce('columns', dfltColumns); - - if(!(rows * columns > 1)) { - delete layoutOut.grid; - return; - } - - if(!hasSubplotGrid && !hasXaxes && !hasYaxes) { - var useDefaultSubplots = coerce('pattern') === 'independent'; - if(useDefaultSubplots) hasSubplotGrid = true; - } - gridOut._hasSubplotGrid = hasSubplotGrid; - - var rowOrder = coerce('roworder'); - var reversed = rowOrder === 'top to bottom'; - - var dfltGapX = hasSubplotGrid ? 0.2 : 0.1; - var dfltGapY = hasSubplotGrid ? 0.3 : 0.1; - - var dfltSideX, dfltSideY; - if(isSplomGenerated && layoutOut._splomGridDflt) { - dfltSideX = layoutOut._splomGridDflt.xside; - dfltSideY = layoutOut._splomGridDflt.yside; - } - - gridOut._domains = { - x: fillGridPositions('x', coerce, dfltGapX, dfltSideX, columns), - y: fillGridPositions('y', coerce, dfltGapY, dfltSideY, rows, reversed) - }; -} - -// coerce x or y sizing attributes and return an array of domains for this direction -function fillGridPositions(axLetter, coerce, dfltGap, dfltSide, len, reversed) { - var dirGap = coerce(axLetter + 'gap', dfltGap); - var domain = coerce('domain.' + axLetter); - coerce(axLetter + 'side', dfltSide); - - var out = new Array(len); - var start = domain[0]; - var step = (domain[1] - start) / (len - dirGap); - var cellDomain = step * (1 - dirGap); - for(var i = 0; i < len; i++) { - var cellStart = start + step * i; - out[reversed ? (len - 1 - i) : i] = [cellStart, cellStart + cellDomain]; - } - return out; -} - -// the (cartesian) contents of the grid - this needs to happen AFTER supplyDataDefaults -// so that we know what cartesian subplots are available -function contentDefaults(layoutIn, layoutOut) { - var gridOut = layoutOut.grid; - // make sure we got to the end of handleGridSizing - if(!gridOut || !gridOut._domains) return; - - var gridIn = layoutIn.grid || {}; - var subplots = layoutOut._subplots; - var hasSubplotGrid = gridOut._hasSubplotGrid; - var rows = gridOut.rows; - var columns = gridOut.columns; - var useDefaultSubplots = gridOut.pattern === 'independent'; - - var i, j, xId, yId, subplotId, subplotsOut, yPos; - - var axisMap = gridOut._axisMap = {}; - - if(hasSubplotGrid) { - var subplotsIn = gridIn.subplots || []; - subplotsOut = gridOut.subplots = new Array(rows); - var index = 1; - - for(i = 0; i < rows; i++) { - var rowOut = subplotsOut[i] = new Array(columns); - var rowIn = subplotsIn[i] || []; - for(j = 0; j < columns; j++) { - if(useDefaultSubplots) { - subplotId = (index === 1) ? 'xy' : ('x' + index + 'y' + index); - index++; - } else subplotId = rowIn[j]; - - rowOut[j] = ''; - - if(subplots.cartesian.indexOf(subplotId) !== -1) { - yPos = subplotId.indexOf('y'); - xId = subplotId.slice(0, yPos); - yId = subplotId.slice(yPos); - if((axisMap[xId] !== undefined && axisMap[xId] !== j) || - (axisMap[yId] !== undefined && axisMap[yId] !== i) - ) { - continue; - } - - rowOut[j] = subplotId; - axisMap[xId] = j; - axisMap[yId] = i; - } - } - } - } else { - var xAxes = getAxes(layoutOut, gridIn, 'x'); - var yAxes = getAxes(layoutOut, gridIn, 'y'); - gridOut.xaxes = fillGridAxes(xAxes, subplots.xaxis, columns, axisMap, 'x'); - gridOut.yaxes = fillGridAxes(yAxes, subplots.yaxis, rows, axisMap, 'y'); - } - - var anchors = gridOut._anchors = {}; - var reversed = gridOut.roworder === 'top to bottom'; - - for(var axisId in axisMap) { - var axLetter = axisId.charAt(0); - var side = gridOut[axLetter + 'side']; - - var i0, inc, iFinal; - - if(side.length < 8) { - // grid edge - ie not "* plot" - make these as free axes - // since we're not guaranteed to have a subplot there at all - anchors[axisId] = 'free'; - } else if(axLetter === 'x') { - if((side.charAt(0) === 't') === reversed) { - i0 = 0; - inc = 1; - iFinal = rows; - } else { - i0 = rows - 1; - inc = -1; - iFinal = -1; - } - if(hasSubplotGrid) { - var column = axisMap[axisId]; - for(i = i0; i !== iFinal; i += inc) { - subplotId = subplotsOut[i][column]; - if(!subplotId) continue; - yPos = subplotId.indexOf('y'); - if(subplotId.slice(0, yPos) === axisId) { - anchors[axisId] = subplotId.slice(yPos); - break; - } - } - } else { - for(i = i0; i !== iFinal; i += inc) { - yId = gridOut.yaxes[i]; - if(subplots.cartesian.indexOf(axisId + yId) !== -1) { - anchors[axisId] = yId; - break; - } - } - } - } else { - if((side.charAt(0) === 'l')) { - i0 = 0; - inc = 1; - iFinal = columns; - } else { - i0 = columns - 1; - inc = -1; - iFinal = -1; - } - if(hasSubplotGrid) { - var row = axisMap[axisId]; - for(i = i0; i !== iFinal; i += inc) { - subplotId = subplotsOut[row][i]; - if(!subplotId) continue; - yPos = subplotId.indexOf('y'); - if(subplotId.slice(yPos) === axisId) { - anchors[axisId] = subplotId.slice(0, yPos); - break; - } - } - } else { - for(i = i0; i !== iFinal; i += inc) { - xId = gridOut.xaxes[i]; - if(subplots.cartesian.indexOf(xId + axisId) !== -1) { - anchors[axisId] = xId; - break; - } - } - } - } - } -} - -function fillGridAxes(axesIn, axesAllowed, len, axisMap, axLetter) { - var out = new Array(len); - var i; - - function fillOneAxis(i, axisId) { - if(axesAllowed.indexOf(axisId) !== -1 && axisMap[axisId] === undefined) { - out[i] = axisId; - axisMap[axisId] = i; - } else out[i] = ''; - } - - if(Array.isArray(axesIn)) { - for(i = 0; i < len; i++) { - fillOneAxis(i, axesIn[i]); - } - } else { - // default axis list is the first `len` axis ids - fillOneAxis(0, axLetter); - for(i = 1; i < len; i++) { - fillOneAxis(i, axLetter + (i + 1)); - } - } - - return out; -} - -module.exports = { - moduleType: 'component', - name: 'grid', - - schema: { - layout: {grid: gridAttrs} - }, - - layoutAttributes: gridAttrs, - sizeDefaults: sizeDefaults, - contentDefaults: contentDefaults -}; - -},{"../../lib":719,"../../lib/regex":735,"../../plot_api/plot_template":757,"../../plots/cartesian/constants":773,"../../plots/domain":792}],637:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var cartesianConstants = _dereq_('../../plots/cartesian/constants'); -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - - -module.exports = templatedArray('image', { - visible: { - valType: 'boolean', - - dflt: true, - editType: 'arraydraw', - - }, - - source: { - valType: 'string', - - editType: 'arraydraw', - - }, - - layer: { - valType: 'enumerated', - values: ['below', 'above'], - dflt: 'above', - - editType: 'arraydraw', - - }, - - sizex: { - valType: 'number', - - dflt: 0, - editType: 'arraydraw', - - }, - - sizey: { - valType: 'number', - - dflt: 0, - editType: 'arraydraw', - - }, - - sizing: { - valType: 'enumerated', - values: ['fill', 'contain', 'stretch'], - dflt: 'contain', - - editType: 'arraydraw', - - }, - - opacity: { - valType: 'number', - - min: 0, - max: 1, - dflt: 1, - editType: 'arraydraw', - - }, - - x: { - valType: 'any', - - dflt: 0, - editType: 'arraydraw', - - }, - - y: { - valType: 'any', - - dflt: 0, - editType: 'arraydraw', - - }, - - xanchor: { - valType: 'enumerated', - values: ['left', 'center', 'right'], - dflt: 'left', - - editType: 'arraydraw', - - }, - - yanchor: { - valType: 'enumerated', - values: ['top', 'middle', 'bottom'], - dflt: 'top', - - editType: 'arraydraw', - - }, - - xref: { - valType: 'enumerated', - values: [ - 'paper', - cartesianConstants.idRegex.x.toString() - ], - dflt: 'paper', - - editType: 'arraydraw', - - }, - - yref: { - valType: 'enumerated', - values: [ - 'paper', - cartesianConstants.idRegex.y.toString() - ], - dflt: 'paper', - - editType: 'arraydraw', - - }, - editType: 'arraydraw' -}); - -},{"../../plot_api/plot_template":757,"../../plots/cartesian/constants":773}],638:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var toLogRange = _dereq_('../../lib/to_log_range'); - -/* - * convertCoords: when converting an axis between log and linear - * you need to alter any images on that axis to keep them - * pointing at the same data point. - * In v2.0 this will become obsolete (or perhaps size will still need conversion?) - * we convert size by declaring that the maximum extent *in data units* should be - * the same, assuming the image is anchored by its center (could remove that restriction - * if we think it's important) even though the actual left and right values will not be - * quite the same since the scale becomes nonlinear (and central anchor means the pixel - * center of the image, not the data units center) - * - * gd: the plot div - * ax: the axis being changed - * newType: the type it's getting - * doExtra: function(attr, val) from inside relayout that sets the attribute. - * Use this to make the changes as it's aware if any other changes in the - * same relayout call should override this conversion. - */ -module.exports = function convertCoords(gd, ax, newType, doExtra) { - ax = ax || {}; - - var toLog = (newType === 'log') && (ax.type === 'linear'); - var fromLog = (newType === 'linear') && (ax.type === 'log'); - - if(!(toLog || fromLog)) return; - - var images = gd._fullLayout.images; - var axLetter = ax._id.charAt(0); - var image; - var attrPrefix; - - for(var i = 0; i < images.length; i++) { - image = images[i]; - attrPrefix = 'images[' + i + '].'; - - if(image[axLetter + 'ref'] === ax._id) { - var currentPos = image[axLetter]; - var currentSize = image['size' + axLetter]; - var newPos = null; - var newSize = null; - - if(toLog) { - newPos = toLogRange(currentPos, ax.range); - - // this is the inverse of the conversion we do in fromLog below - // so that the conversion is reversible (notice the fromLog conversion - // is like sinh, and this one looks like arcsinh) - var dx = currentSize / Math.pow(10, newPos) / 2; - newSize = 2 * Math.log(dx + Math.sqrt(1 + dx * dx)) / Math.LN10; - } else { - newPos = Math.pow(10, currentPos); - newSize = newPos * (Math.pow(10, currentSize / 2) - Math.pow(10, -currentSize / 2)); - } - - // if conversion failed, delete the value so it can get a default later on - if(!isNumeric(newPos)) { - newPos = null; - newSize = null; - } else if(!isNumeric(newSize)) newSize = null; - - doExtra(attrPrefix + axLetter, newPos); - doExtra(attrPrefix + 'size' + axLetter, newSize); - } - } -}; - -},{"../../lib/to_log_range":745,"fast-isnumeric":225}],639:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); - -var attributes = _dereq_('./attributes'); -var name = 'images'; - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { - var opts = { - name: name, - handleItemDefaults: imageDefaults - }; - - handleArrayContainerDefaults(layoutIn, layoutOut, opts); -}; - - -function imageDefaults(imageIn, imageOut, fullLayout) { - function coerce(attr, dflt) { - return Lib.coerce(imageIn, imageOut, attributes, attr, dflt); - } - - var source = coerce('source'); - var visible = coerce('visible', !!source); - - if(!visible) return imageOut; - - coerce('layer'); - coerce('xanchor'); - coerce('yanchor'); - coerce('sizex'); - coerce('sizey'); - coerce('sizing'); - coerce('opacity'); - - var gdMock = { _fullLayout: fullLayout }; - var axLetters = ['x', 'y']; - - for(var i = 0; i < 2; i++) { - // 'paper' is the fallback axref - var axLetter = axLetters[i]; - var axRef = Axes.coerceRef(imageIn, imageOut, gdMock, axLetter, 'paper'); - - if(axRef !== 'paper') { - var ax = Axes.getFromId(gdMock, axRef); - ax._imgIndices.push(imageOut._index); - } - - Axes.coercePosition(imageOut, gdMock, coerce, axRef, axLetter, 0); - } - - return imageOut; -} - -},{"../../lib":719,"../../plots/array_container_defaults":763,"../../plots/cartesian/axes":767,"./attributes":637}],640:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Drawing = _dereq_('../drawing'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); - -module.exports = function draw(gd) { - var fullLayout = gd._fullLayout; - var imageDataAbove = []; - var imageDataSubplot = {}; - var imageDataBelow = []; - var subplot; - var i; - - // Sort into top, subplot, and bottom layers - for(i = 0; i < fullLayout.images.length; i++) { - var img = fullLayout.images[i]; - - if(img.visible) { - if(img.layer === 'below' && img.xref !== 'paper' && img.yref !== 'paper') { - subplot = img.xref + img.yref; - - var plotinfo = fullLayout._plots[subplot]; - - if(!plotinfo) { - // Fall back to _imageLowerLayer in case the requested subplot doesn't exist. - // This can happen if you reference the image to an x / y axis combination - // that doesn't have any data on it (and layer is below) - imageDataBelow.push(img); - continue; - } - - if(plotinfo.mainplot) { - subplot = plotinfo.mainplot.id; - } - - if(!imageDataSubplot[subplot]) { - imageDataSubplot[subplot] = []; - } - imageDataSubplot[subplot].push(img); - } else if(img.layer === 'above') { - imageDataAbove.push(img); - } else { - imageDataBelow.push(img); - } - } - } - - - var anchors = { - x: { - left: { sizing: 'xMin', offset: 0 }, - center: { sizing: 'xMid', offset: -1 / 2 }, - right: { sizing: 'xMax', offset: -1 } - }, - y: { - top: { sizing: 'YMin', offset: 0 }, - middle: { sizing: 'YMid', offset: -1 / 2 }, - bottom: { sizing: 'YMax', offset: -1 } - } - }; - - - // Images must be converted to dataURL's for exporting. - function setImage(d) { - var thisImage = d3.select(this); - - if(this.img && this.img.src === d.source) { - return; - } - - thisImage.attr('xmlns', xmlnsNamespaces.svg); - - var imagePromise = new Promise(function(resolve) { - var img = new Image(); - this.img = img; - - // If not set, a `tainted canvas` error is thrown - img.setAttribute('crossOrigin', 'anonymous'); - img.onerror = errorHandler; - img.onload = function() { - var canvas = document.createElement('canvas'); - canvas.width = this.width; - canvas.height = this.height; - - var ctx = canvas.getContext('2d'); - ctx.drawImage(this, 0, 0); - - var dataURL = canvas.toDataURL('image/png'); - - thisImage.attr('xlink:href', dataURL); - - // resolve promise in onload handler instead of on 'load' to support IE11 - // see https://github.com/plotly/plotly.js/issues/1685 - // for more details - resolve(); - }; - - - thisImage.on('error', errorHandler); - - img.src = d.source; - - function errorHandler() { - thisImage.remove(); - resolve(); - } - }.bind(this)); - - gd._promises.push(imagePromise); - } - - function applyAttributes(d) { - var thisImage = d3.select(this); - - // Axes if specified - var xa = Axes.getFromId(gd, d.xref); - var ya = Axes.getFromId(gd, d.yref); - - var size = fullLayout._size; - var width = xa ? Math.abs(xa.l2p(d.sizex) - xa.l2p(0)) : d.sizex * size.w; - var height = ya ? Math.abs(ya.l2p(d.sizey) - ya.l2p(0)) : d.sizey * size.h; - - // Offsets for anchor positioning - var xOffset = width * anchors.x[d.xanchor].offset; - var yOffset = height * anchors.y[d.yanchor].offset; - - var sizing = anchors.x[d.xanchor].sizing + anchors.y[d.yanchor].sizing; - - // Final positions - var xPos = (xa ? xa.r2p(d.x) + xa._offset : d.x * size.w + size.l) + xOffset; - var yPos = (ya ? ya.r2p(d.y) + ya._offset : size.h - d.y * size.h + size.t) + yOffset; - - // Construct the proper aspectRatio attribute - switch(d.sizing) { - case 'fill': - sizing += ' slice'; - break; - - case 'stretch': - sizing = 'none'; - break; - } - - thisImage.attr({ - x: xPos, - y: yPos, - width: width, - height: height, - preserveAspectRatio: sizing, - opacity: d.opacity - }); - - - // Set proper clipping on images - var xId = xa ? xa._id : ''; - var yId = ya ? ya._id : ''; - var clipAxes = xId + yId; - - Drawing.setClipUrl( - thisImage, - clipAxes ? ('clip' + fullLayout._uid + clipAxes) : null, - gd - ); - } - - var imagesBelow = fullLayout._imageLowerLayer.selectAll('image') - .data(imageDataBelow); - var imagesAbove = fullLayout._imageUpperLayer.selectAll('image') - .data(imageDataAbove); - - imagesBelow.enter().append('image'); - imagesAbove.enter().append('image'); - - imagesBelow.exit().remove(); - imagesAbove.exit().remove(); - - imagesBelow.each(function(d) { - setImage.bind(this)(d); - applyAttributes.bind(this)(d); - }); - imagesAbove.each(function(d) { - setImage.bind(this)(d); - applyAttributes.bind(this)(d); - }); - - var allSubplots = Object.keys(fullLayout._plots); - for(i = 0; i < allSubplots.length; i++) { - subplot = allSubplots[i]; - var subplotObj = fullLayout._plots[subplot]; - - // filter out overlaid plots (which havd their images on the main plot) - // and gl2d plots (which don't support below images, at least not yet) - if(!subplotObj.imagelayer) continue; - - var imagesOnSubplot = subplotObj.imagelayer.selectAll('image') - // even if there are no images on this subplot, we need to run - // enter and exit in case there were previously - .data(imageDataSubplot[subplot] || []); - - imagesOnSubplot.enter().append('image'); - imagesOnSubplot.exit().remove(); - - imagesOnSubplot.each(function(d) { - setImage.bind(this)(d); - applyAttributes.bind(this)(d); - }); - } -}; - -},{"../../constants/xmlns_namespaces":696,"../../plots/cartesian/axes":767,"../drawing":614,"d3":163}],641:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'component', - name: 'images', - - layoutAttributes: _dereq_('./attributes'), - supplyLayoutDefaults: _dereq_('./defaults'), - includeBasePlot: _dereq_('../../plots/cartesian/include_components')('images'), - - draw: _dereq_('./draw'), - - convertCoords: _dereq_('./convert_coords') -}; - -},{"../../plots/cartesian/include_components":777,"./attributes":637,"./convert_coords":638,"./defaults":639,"./draw":640}],642:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('../../plots/font_attributes'); -var colorAttrs = _dereq_('../color/attributes'); - - -module.exports = { - bgcolor: { - valType: 'color', - - editType: 'legend', - - }, - bordercolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'legend', - - }, - borderwidth: { - valType: 'number', - min: 0, - dflt: 0, - - editType: 'legend', - - }, - font: fontAttrs({ - editType: 'legend', - - }), - orientation: { - valType: 'enumerated', - values: ['v', 'h'], - dflt: 'v', - - editType: 'legend', - - }, - traceorder: { - valType: 'flaglist', - flags: ['reversed', 'grouped'], - extras: ['normal'], - - editType: 'legend', - - }, - tracegroupgap: { - valType: 'number', - min: 0, - dflt: 10, - - editType: 'legend', - - }, - itemsizing: { - valType: 'enumerated', - values: ['trace', 'constant'], - dflt: 'trace', - - editType: 'legend', - - }, - - itemclick: { - valType: 'enumerated', - values: ['toggle', 'toggleothers', false], - dflt: 'toggle', - - editType: 'legend', - - }, - itemdoubleclick: { - valType: 'enumerated', - values: ['toggle', 'toggleothers', false], - dflt: 'toggleothers', - - editType: 'legend', - - }, - - x: { - valType: 'number', - min: -2, - max: 3, - dflt: 1.02, - - editType: 'legend', - - }, - xanchor: { - valType: 'enumerated', - values: ['auto', 'left', 'center', 'right'], - dflt: 'left', - - editType: 'legend', - - }, - y: { - valType: 'number', - min: -2, - max: 3, - dflt: 1, - - editType: 'legend', - - }, - yanchor: { - valType: 'enumerated', - values: ['auto', 'top', 'middle', 'bottom'], - dflt: 'auto', - - editType: 'legend', - - }, - uirevision: { - valType: 'any', - - editType: 'none', - - }, - valign: { - valType: 'enumerated', - values: ['top', 'middle', 'bottom'], - dflt: 'middle', - - editType: 'legend', - - }, - editType: 'legend' -}; - -},{"../../plots/font_attributes":793,"../color/attributes":592}],643:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - scrollBarWidth: 6, - scrollBarMinHeight: 20, - scrollBarColor: '#808BA4', - scrollBarMargin: 4, - textOffsetX: 40 -}; - -},{}],644:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Template = _dereq_('../../plot_api/plot_template'); - -var attributes = _dereq_('./attributes'); -var basePlotLayoutAttributes = _dereq_('../../plots/layout_attributes'); -var helpers = _dereq_('./helpers'); - - -module.exports = function legendDefaults(layoutIn, layoutOut, fullData) { - var containerIn = layoutIn.legend || {}; - - var legendTraceCount = 0; - var legendReallyHasATrace = false; - var defaultOrder = 'normal'; - - var defaultX, defaultY, defaultXAnchor, defaultYAnchor; - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - - if(!trace.visible) continue; - - // Note that we explicitly count any trace that is either shown or - // *would* be shown by default, toward the two traces you need to - // ensure the legend is shown by default, because this can still help - // disambiguate. - if(trace.showlegend || trace._dfltShowLegend) { - legendTraceCount++; - if(trace.showlegend) { - legendReallyHasATrace = true; - // Always show the legend by default if there's a pie, - // or if there's only one trace but it's explicitly shown - if(Registry.traceIs(trace, 'pie-like') || - trace._input.showlegend === true - ) { - legendTraceCount++; - } - } - } - - if((Registry.traceIs(trace, 'bar') && layoutOut.barmode === 'stack') || - ['tonextx', 'tonexty'].indexOf(trace.fill) !== -1) { - defaultOrder = helpers.isGrouped({traceorder: defaultOrder}) ? - 'grouped+reversed' : 'reversed'; - } - - if(trace.legendgroup !== undefined && trace.legendgroup !== '') { - defaultOrder = helpers.isReversed({traceorder: defaultOrder}) ? - 'reversed+grouped' : 'grouped'; - } - } - - var showLegend = Lib.coerce(layoutIn, layoutOut, - basePlotLayoutAttributes, 'showlegend', - legendReallyHasATrace && legendTraceCount > 1); - - if(showLegend === false && !containerIn.uirevision) return; - - var containerOut = Template.newContainer(layoutOut, 'legend'); - - function coerce(attr, dflt) { - return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); - } - - coerce('uirevision', layoutOut.uirevision); - - if(showLegend === false) return; - - coerce('bgcolor', layoutOut.paper_bgcolor); - coerce('bordercolor'); - coerce('borderwidth'); - Lib.coerceFont(coerce, 'font', layoutOut.font); - - coerce('orientation'); - if(containerOut.orientation === 'h') { - var xaxis = layoutIn.xaxis; - if(Registry.getComponentMethod('rangeslider', 'isVisible')(xaxis)) { - defaultX = 0; - defaultXAnchor = 'left'; - defaultY = 1.1; - defaultYAnchor = 'bottom'; - } else { - defaultX = 0; - defaultXAnchor = 'left'; - defaultY = -0.1; - defaultYAnchor = 'top'; - } - } - - coerce('traceorder', defaultOrder); - if(helpers.isGrouped(layoutOut.legend)) coerce('tracegroupgap'); - - coerce('itemsizing'); - - coerce('itemclick'); - coerce('itemdoubleclick'); - - coerce('x', defaultX); - coerce('xanchor', defaultXAnchor); - coerce('y', defaultY); - coerce('yanchor', defaultYAnchor); - coerce('valign'); - Lib.noneOrAll(containerIn, containerOut, ['x', 'y']); -}; - -},{"../../lib":719,"../../plot_api/plot_template":757,"../../plots/layout_attributes":819,"../../registry":847,"./attributes":642,"./helpers":648}],645:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Lib = _dereq_('../../lib'); -var Plots = _dereq_('../../plots/plots'); -var Registry = _dereq_('../../registry'); -var Events = _dereq_('../../lib/events'); -var dragElement = _dereq_('../dragelement'); -var Drawing = _dereq_('../drawing'); -var Color = _dereq_('../color'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var handleClick = _dereq_('./handle_click'); - -var constants = _dereq_('./constants'); -var alignmentConstants = _dereq_('../../constants/alignment'); -var LINE_SPACING = alignmentConstants.LINE_SPACING; -var FROM_TL = alignmentConstants.FROM_TL; -var FROM_BR = alignmentConstants.FROM_BR; - -var getLegendData = _dereq_('./get_legend_data'); -var style = _dereq_('./style'); -var helpers = _dereq_('./helpers'); - -module.exports = function draw(gd) { - var fullLayout = gd._fullLayout; - var clipId = 'legend' + fullLayout._uid; - - if(!fullLayout._infolayer || !gd.calcdata) return; - - if(!gd._legendMouseDownTime) gd._legendMouseDownTime = 0; - - var opts = fullLayout.legend; - var legendData = fullLayout.showlegend && getLegendData(gd.calcdata, opts); - var hiddenSlices = fullLayout.hiddenlabels || []; - - if(!fullLayout.showlegend || !legendData.length) { - fullLayout._infolayer.selectAll('.legend').remove(); - fullLayout._topdefs.select('#' + clipId).remove(); - - Plots.autoMargin(gd, 'legend'); - return; - } - - var maxLength = 0; - for(var i = 0; i < legendData.length; i++) { - for(var j = 0; j < legendData[i].length; j++) { - var item = legendData[i][j][0]; - var trace = item.trace; - var isPieLike = Registry.traceIs(trace, 'pie-like'); - var name = isPieLike ? item.label : trace.name; - maxLength = Math.max(maxLength, name && name.length || 0); - } - } - - var firstRender = false; - var legend = Lib.ensureSingle(fullLayout._infolayer, 'g', 'legend', function(s) { - s.attr('pointer-events', 'all'); - firstRender = true; - }); - - var clipPath = Lib.ensureSingleById(fullLayout._topdefs, 'clipPath', clipId, function(s) { - s.append('rect'); - }); - - var bg = Lib.ensureSingle(legend, 'rect', 'bg', function(s) { - s.attr('shape-rendering', 'crispEdges'); - }); - - bg.call(Color.stroke, opts.bordercolor) - .call(Color.fill, opts.bgcolor) - .style('stroke-width', opts.borderwidth + 'px'); - - var scrollBox = Lib.ensureSingle(legend, 'g', 'scrollbox'); - - var scrollBar = Lib.ensureSingle(legend, 'rect', 'scrollbar', function(s) { - s.attr({ - rx: 20, - ry: 3, - width: 0, - height: 0 - }) - .call(Color.fill, '#808BA4'); - }); - - var groups = scrollBox.selectAll('g.groups') - .data(legendData); - - groups.enter().append('g') - .attr('class', 'groups'); - - groups.exit().remove(); - - var traces = groups.selectAll('g.traces') - .data(Lib.identity); - - traces.enter().append('g').attr('class', 'traces'); - traces.exit().remove(); - - traces.style('opacity', function(d) { - var trace = d[0].trace; - if(Registry.traceIs(trace, 'pie-like')) { - return hiddenSlices.indexOf(d[0].label) !== -1 ? 0.5 : 1; - } else { - return trace.visible === 'legendonly' ? 0.5 : 1; - } - }) - .each(function() { - d3.select(this) - .call(drawTexts, gd, maxLength); - }) - .call(style, gd) - .each(function() { - d3.select(this) - .call(setupTraceToggle, gd); - }); - - Lib.syncOrAsync([Plots.previousPromises, - function() { - if(firstRender) { - computeLegendDimensions(gd, groups, traces); - expandMargin(gd); - } - - // Position and size the legend - var lxMin = 0; - var lxMax = fullLayout.width; - var lyMin = 0; - var lyMax = fullLayout.height; - - computeLegendDimensions(gd, groups, traces); - - if(opts._height > lyMax) { - // If the legend doesn't fit in the plot area, - // do not expand the vertical margins. - expandHorizontalMargin(gd); - } else { - expandMargin(gd); - } - - // Scroll section must be executed after repositionLegend. - // It requires the legend width, height, x and y to position the scrollbox - // and these values are mutated in repositionLegend. - var gs = fullLayout._size; - var lx = gs.l + gs.w * opts.x; - var ly = gs.t + gs.h * (1 - opts.y); - - if(Lib.isRightAnchor(opts)) { - lx -= opts._width; - } else if(Lib.isCenterAnchor(opts)) { - lx -= opts._width / 2; - } - - if(Lib.isBottomAnchor(opts)) { - ly -= opts._height; - } else if(Lib.isMiddleAnchor(opts)) { - ly -= opts._height / 2; - } - - // Make sure the legend left and right sides are visible - var legendWidth = opts._width; - var legendWidthMax = gs.w; - - if(legendWidth > legendWidthMax) { - lx = gs.l; - legendWidth = legendWidthMax; - } else { - if(lx + legendWidth > lxMax) lx = lxMax - legendWidth; - if(lx < lxMin) lx = lxMin; - legendWidth = Math.min(lxMax - lx, opts._width); - } - - // Make sure the legend top and bottom are visible - // (legends with a scroll bar are not allowed to stretch beyond the extended - // margins) - var legendHeight = opts._height; - var legendHeightMax = gs.h; - - if(legendHeight > legendHeightMax) { - ly = gs.t; - legendHeight = legendHeightMax; - } else { - if(ly + legendHeight > lyMax) ly = lyMax - legendHeight; - if(ly < lyMin) ly = lyMin; - legendHeight = Math.min(lyMax - ly, opts._height); - } - - // Set size and position of all the elements that make up a legend: - // legend, background and border, scroll box and scroll bar - Drawing.setTranslate(legend, lx, ly); - - // to be safe, remove previous listeners - scrollBar.on('.drag', null); - legend.on('wheel', null); - - if(opts._height <= legendHeight || gd._context.staticPlot) { - // if scrollbar should not be shown. - bg.attr({ - width: legendWidth - opts.borderwidth, - height: legendHeight - opts.borderwidth, - x: opts.borderwidth / 2, - y: opts.borderwidth / 2 - }); - - Drawing.setTranslate(scrollBox, 0, 0); - - clipPath.select('rect').attr({ - width: legendWidth - 2 * opts.borderwidth, - height: legendHeight - 2 * opts.borderwidth, - x: opts.borderwidth, - y: opts.borderwidth - }); - - Drawing.setClipUrl(scrollBox, clipId, gd); - - Drawing.setRect(scrollBar, 0, 0, 0, 0); - delete opts._scrollY; - } else { - var scrollBarHeight = Math.max(constants.scrollBarMinHeight, - legendHeight * legendHeight / opts._height); - var scrollBarYMax = legendHeight - - scrollBarHeight - - 2 * constants.scrollBarMargin; - var scrollBoxYMax = opts._height - legendHeight; - var scrollRatio = scrollBarYMax / scrollBoxYMax; - - var scrollBoxY = Math.min(opts._scrollY || 0, scrollBoxYMax); - - // increase the background and clip-path width - // by the scrollbar width and margin - bg.attr({ - width: legendWidth - - 2 * opts.borderwidth + - constants.scrollBarWidth + - constants.scrollBarMargin, - height: legendHeight - opts.borderwidth, - x: opts.borderwidth / 2, - y: opts.borderwidth / 2 - }); - - clipPath.select('rect').attr({ - width: legendWidth - - 2 * opts.borderwidth + - constants.scrollBarWidth + - constants.scrollBarMargin, - height: legendHeight - 2 * opts.borderwidth, - x: opts.borderwidth, - y: opts.borderwidth + scrollBoxY - }); - - Drawing.setClipUrl(scrollBox, clipId, gd); - - scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio); - - legend.on('wheel', function() { - scrollBoxY = Lib.constrain( - opts._scrollY + - d3.event.deltaY / scrollBarYMax * scrollBoxYMax, - 0, scrollBoxYMax); - scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio); - if(scrollBoxY !== 0 && scrollBoxY !== scrollBoxYMax) { - d3.event.preventDefault(); - } - }); - - var eventY0, scrollBoxY0; - - var drag = d3.behavior.drag() - .on('dragstart', function() { - eventY0 = d3.event.sourceEvent.clientY; - scrollBoxY0 = scrollBoxY; - }) - .on('drag', function() { - var e = d3.event.sourceEvent; - if(e.buttons === 2 || e.ctrlKey) return; - - scrollBoxY = Lib.constrain( - (e.clientY - eventY0) / scrollRatio + scrollBoxY0, - 0, scrollBoxYMax); - scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio); - }); - - scrollBar.call(drag); - } - - - function scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio) { - opts._scrollY = gd._fullLayout.legend._scrollY = scrollBoxY; - Drawing.setTranslate(scrollBox, 0, -scrollBoxY); - - Drawing.setRect( - scrollBar, - legendWidth, - constants.scrollBarMargin + scrollBoxY * scrollRatio, - constants.scrollBarWidth, - scrollBarHeight - ); - clipPath.select('rect').attr({ - y: opts.borderwidth + scrollBoxY - }); - } - - if(gd._context.edits.legendPosition) { - var xf, yf, x0, y0; - - legend.classed('cursor-move', true); - - dragElement.init({ - element: legend.node(), - gd: gd, - prepFn: function() { - var transform = Drawing.getTranslate(legend); - - x0 = transform.x; - y0 = transform.y; - }, - moveFn: function(dx, dy) { - var newX = x0 + dx; - var newY = y0 + dy; - - Drawing.setTranslate(legend, newX, newY); - - xf = dragElement.align(newX, 0, gs.l, gs.l + gs.w, opts.xanchor); - yf = dragElement.align(newY, 0, gs.t + gs.h, gs.t, opts.yanchor); - }, - doneFn: function() { - if(xf !== undefined && yf !== undefined) { - Registry.call('_guiRelayout', gd, {'legend.x': xf, 'legend.y': yf}); - } - }, - clickFn: function(numClicks, e) { - var clickedTrace = fullLayout._infolayer.selectAll('g.traces').filter(function() { - var bbox = this.getBoundingClientRect(); - return ( - e.clientX >= bbox.left && e.clientX <= bbox.right && - e.clientY >= bbox.top && e.clientY <= bbox.bottom - ); - }); - if(clickedTrace.size() > 0) { - clickOrDoubleClick(gd, legend, clickedTrace, numClicks, e); - } - } - }); - } - }], gd); -}; - -function clickOrDoubleClick(gd, legend, legendItem, numClicks, evt) { - var trace = legendItem.data()[0][0].trace; - var evtData = { - event: evt, - node: legendItem.node(), - curveNumber: trace.index, - expandedIndex: trace._expandedIndex, - data: gd.data, - layout: gd.layout, - frames: gd._transitionData._frames, - config: gd._context, - fullData: gd._fullData, - fullLayout: gd._fullLayout - }; - - if(trace._group) { - evtData.group = trace._group; - } - if(Registry.traceIs(trace, 'pie-like')) { - evtData.label = legendItem.datum()[0].label; - } - - var clickVal = Events.triggerHandler(gd, 'plotly_legendclick', evtData); - if(clickVal === false) return; - - if(numClicks === 1) { - legend._clickTimeout = setTimeout(function() { - handleClick(legendItem, gd, numClicks); - }, gd._context.doubleClickDelay); - } else if(numClicks === 2) { - if(legend._clickTimeout) clearTimeout(legend._clickTimeout); - gd._legendMouseDownTime = 0; - - var dblClickVal = Events.triggerHandler(gd, 'plotly_legenddoubleclick', evtData); - if(dblClickVal !== false) handleClick(legendItem, gd, numClicks); - } -} - -function drawTexts(g, gd, maxLength) { - var legendItem = g.data()[0][0]; - var fullLayout = gd._fullLayout; - var trace = legendItem.trace; - var isPieLike = Registry.traceIs(trace, 'pie-like'); - var traceIndex = trace.index; - var isEditable = gd._context.edits.legendText && !isPieLike; - - var name = isPieLike ? legendItem.label : trace.name; - if(trace._meta) { - name = Lib.templateString(name, trace._meta); - } - - var textEl = Lib.ensureSingle(g, 'text', 'legendtext'); - - textEl.attr('text-anchor', 'start') - .classed('user-select-none', true) - .call(Drawing.font, fullLayout.legend.font) - .text(isEditable ? ensureLength(name, maxLength) : name); - - svgTextUtils.positionText(textEl, constants.textOffsetX, 0); - - function textLayout(s) { - svgTextUtils.convertToTspans(s, gd, function() { - computeTextDimensions(g, gd); - }); - } - - if(isEditable) { - textEl.call(svgTextUtils.makeEditable, {gd: gd, text: name}) - .call(textLayout) - .on('edit', function(newName) { - this.text(ensureLength(newName, maxLength)) - .call(textLayout); - - var fullInput = legendItem.trace._fullInput || {}; - var update = {}; - - if(Registry.hasTransform(fullInput, 'groupby')) { - var groupbyIndices = Registry.getTransformIndices(fullInput, 'groupby'); - var index = groupbyIndices[groupbyIndices.length - 1]; - - var kcont = Lib.keyedContainer(fullInput, 'transforms[' + index + '].styles', 'target', 'value.name'); - - kcont.set(legendItem.trace._group, newName); - - update = kcont.constructUpdate(); - } else { - update.name = newName; - } - - return Registry.call('_guiRestyle', gd, update, traceIndex); - }); - } else { - textLayout(textEl); - } -} - -/* - * Make sure we have a reasonably clickable region. - * If this string is missing or very short, pad it with spaces out to at least - * 4 characters, up to the max length of other labels, on the assumption that - * most characters are wider than spaces so a string of spaces will usually be - * no wider than the real labels. - */ -function ensureLength(str, maxLength) { - var targetLength = Math.max(4, maxLength); - if(str && str.trim().length >= targetLength / 2) return str; - str = str || ''; - for(var i = targetLength - str.length; i > 0; i--) str += ' '; - return str; -} - -function setupTraceToggle(g, gd) { - var doubleClickDelay = gd._context.doubleClickDelay; - var newMouseDownTime; - var numClicks = 1; - - var traceToggle = Lib.ensureSingle(g, 'rect', 'legendtoggle', function(s) { - s.style('cursor', 'pointer') - .attr('pointer-events', 'all') - .call(Color.fill, 'rgba(0,0,0,0)'); - }); - - traceToggle.on('mousedown', function() { - newMouseDownTime = (new Date()).getTime(); - if(newMouseDownTime - gd._legendMouseDownTime < doubleClickDelay) { - // in a click train - numClicks += 1; - } else { - // new click train - numClicks = 1; - gd._legendMouseDownTime = newMouseDownTime; - } - }); - traceToggle.on('mouseup', function() { - if(gd._dragged || gd._editing) return; - var legend = gd._fullLayout.legend; - - if((new Date()).getTime() - gd._legendMouseDownTime > doubleClickDelay) { - numClicks = Math.max(numClicks - 1, 1); - } - - clickOrDoubleClick(gd, legend, g, numClicks, d3.event); - }); -} - -function computeTextDimensions(g, gd) { - var legendItem = g.data()[0][0]; - - if(!legendItem.trace.showlegend) { - g.remove(); - return; - } - - var mathjaxGroup = g.select('g[class*=math-group]'); - var mathjaxNode = mathjaxGroup.node(); - var opts = gd._fullLayout.legend; - var lineHeight = opts.font.size * LINE_SPACING; - var height, width; - - if(mathjaxNode) { - var mathjaxBB = Drawing.bBox(mathjaxNode); - - height = mathjaxBB.height; - width = mathjaxBB.width; - - Drawing.setTranslate(mathjaxGroup, 0, (height / 4)); - } else { - var text = g.select('.legendtext'); - var textLines = svgTextUtils.lineCount(text); - var textNode = text.node(); - - height = lineHeight * textLines; - width = textNode ? Drawing.bBox(textNode).width : 0; - - // approximation to height offset to center the font - // to avoid getBoundingClientRect - var textY = lineHeight * (0.3 + (1 - textLines) / 2); - svgTextUtils.positionText(text, constants.textOffsetX, textY); - } - - legendItem.lineHeight = lineHeight; - legendItem.height = Math.max(height, 16) + 3; - legendItem.width = width; -} - -function computeLegendDimensions(gd, groups, traces) { - var fullLayout = gd._fullLayout; - var opts = fullLayout.legend; - var borderwidth = opts.borderwidth; - var isGrouped = helpers.isGrouped(opts); - - var extraWidth = 0; - - var traceGap = 5; - - opts._width = 0; - opts._height = 0; - - if(helpers.isVertical(opts)) { - if(isGrouped) { - groups.each(function(d, i) { - Drawing.setTranslate(this, 0, i * opts.tracegroupgap); - }); - } - - traces.each(function(d) { - var legendItem = d[0]; - var textHeight = legendItem.height; - var textWidth = legendItem.width; - - Drawing.setTranslate(this, - borderwidth, - (5 + borderwidth + opts._height + textHeight / 2)); - - opts._height += textHeight; - opts._width = Math.max(opts._width, textWidth); - }); - - opts._width += 45 + borderwidth * 2; - opts._height += 10 + borderwidth * 2; - - if(isGrouped) { - opts._height += (opts._lgroupsLength - 1) * opts.tracegroupgap; - } - - extraWidth = 40; - } else if(isGrouped) { - var maxHeight = 0; - var maxWidth = 0; - var groupData = groups.data(); - - var maxItems = 0; - - var i; - for(i = 0; i < groupData.length; i++) { - var group = groupData[i]; - var groupWidths = group.map(function(legendItemArray) { - return legendItemArray[0].width; - }); - - var groupWidth = Lib.aggNums(Math.max, null, groupWidths); - var groupHeight = group.reduce(function(a, b) { - return a + b[0].height; - }, 0); - - maxWidth = Math.max(maxWidth, groupWidth); - maxHeight = Math.max(maxHeight, groupHeight); - maxItems = Math.max(maxItems, group.length); - } - - maxWidth += traceGap; - maxWidth += 40; - - var groupXOffsets = [opts._width]; - var groupYOffsets = []; - var rowNum = 0; - for(i = 0; i < groupData.length; i++) { - if(fullLayout._size.w < (borderwidth + opts._width + traceGap + maxWidth)) { - groupXOffsets[groupXOffsets.length - 1] = groupXOffsets[0]; - opts._width = maxWidth; - rowNum++; - } else { - opts._width += maxWidth + borderwidth; - } - - var rowYOffset = (rowNum * maxHeight); - rowYOffset += rowNum > 0 ? opts.tracegroupgap : 0; - - groupYOffsets.push(rowYOffset); - groupXOffsets.push(opts._width); - } - - groups.each(function(d, i) { - Drawing.setTranslate(this, groupXOffsets[i], groupYOffsets[i]); - }); - - groups.each(function() { - var group = d3.select(this); - var groupTraces = group.selectAll('g.traces'); - var groupHeight = 0; - - groupTraces.each(function(d) { - var legendItem = d[0]; - var textHeight = legendItem.height; - - Drawing.setTranslate(this, - 0, - (5 + borderwidth + groupHeight + textHeight / 2)); - - groupHeight += textHeight; - }); - }); - - var maxYLegend = groupYOffsets[groupYOffsets.length - 1] + maxHeight; - opts._height = 10 + (borderwidth * 2) + maxYLegend; - - var maxOffset = Math.max.apply(null, groupXOffsets); - opts._width = maxOffset + maxWidth + 40; - opts._width += borderwidth * 2; - } else { - var rowHeight = 0; - var maxTraceHeight = 0; - var maxTraceWidth = 0; - var offsetX = 0; - var fullTracesWidth = 0; - - // calculate largest width for traces and use for width of all legend items - traces.each(function(d) { - maxTraceWidth = Math.max(40 + d[0].width, maxTraceWidth); - fullTracesWidth += 40 + d[0].width + traceGap; - }); - - // check if legend fits in one row - var oneRowLegend = fullLayout._size.w > borderwidth + fullTracesWidth - traceGap; - - traces.each(function(d) { - var legendItem = d[0]; - var traceWidth = oneRowLegend ? 40 + d[0].width : maxTraceWidth; - - if((borderwidth + offsetX + traceGap + traceWidth) > fullLayout._size.w) { - offsetX = 0; - rowHeight += maxTraceHeight; - opts._height += maxTraceHeight; - // reset for next row - maxTraceHeight = 0; - } - - Drawing.setTranslate(this, - (borderwidth + offsetX), - (5 + borderwidth + legendItem.height / 2) + rowHeight); - - opts._width += traceGap + traceWidth; - - // keep track of tallest trace in group - offsetX += traceGap + traceWidth; - maxTraceHeight = Math.max(legendItem.height, maxTraceHeight); - }); - - if(oneRowLegend) { - opts._height = maxTraceHeight; - } else { - opts._height += maxTraceHeight; - } - - opts._width += borderwidth * 2; - opts._height += 10 + borderwidth * 2; - } - - // make sure we're only getting full pixels - opts._width = Math.ceil(opts._width); - opts._height = Math.ceil(opts._height); - - var isEditable = ( - gd._context.edits.legendText || - gd._context.edits.legendPosition - ); - - traces.each(function(d) { - var legendItem = d[0]; - var bg = d3.select(this).select('.legendtoggle'); - - Drawing.setRect(bg, - 0, - -legendItem.height / 2, - (isEditable ? 0 : opts._width) + extraWidth, - legendItem.height - ); - }); -} - -function expandMargin(gd) { - var fullLayout = gd._fullLayout; - var opts = fullLayout.legend; - - var xanchor = 'left'; - if(Lib.isRightAnchor(opts)) { - xanchor = 'right'; - } else if(Lib.isCenterAnchor(opts)) { - xanchor = 'center'; - } - - var yanchor = 'top'; - if(Lib.isBottomAnchor(opts)) { - yanchor = 'bottom'; - } else if(Lib.isMiddleAnchor(opts)) { - yanchor = 'middle'; - } - - // lastly check if the margin auto-expand has changed - Plots.autoMargin(gd, 'legend', { - x: opts.x, - y: opts.y, - l: opts._width * (FROM_TL[xanchor]), - r: opts._width * (FROM_BR[xanchor]), - b: opts._height * (FROM_BR[yanchor]), - t: opts._height * (FROM_TL[yanchor]) - }); -} - -function expandHorizontalMargin(gd) { - var fullLayout = gd._fullLayout; - var opts = fullLayout.legend; - - var xanchor = 'left'; - if(Lib.isRightAnchor(opts)) { - xanchor = 'right'; - } else if(Lib.isCenterAnchor(opts)) { - xanchor = 'center'; - } - - // lastly check if the margin auto-expand has changed - Plots.autoMargin(gd, 'legend', { - x: opts.x, - y: 0.5, - l: opts._width * (FROM_TL[xanchor]), - r: opts._width * (FROM_BR[xanchor]), - b: 0, - t: 0 - }); -} - -},{"../../constants/alignment":688,"../../lib":719,"../../lib/events":709,"../../lib/svg_text_utils":743,"../../plots/plots":828,"../../registry":847,"../color":593,"../dragelement":611,"../drawing":614,"./constants":643,"./get_legend_data":646,"./handle_click":647,"./helpers":648,"./style":650,"d3":163}],646:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var helpers = _dereq_('./helpers'); - -module.exports = function getLegendData(calcdata, opts) { - var lgroupToTraces = {}; - var lgroups = []; - var hasOneNonBlankGroup = false; - var slicesShown = {}; - var lgroupi = 0; - var i, j; - - function addOneItem(legendGroup, legendItem) { - // each '' legend group is treated as a separate group - if(legendGroup === '' || !helpers.isGrouped(opts)) { - var uniqueGroup = '~~i' + lgroupi; // TODO: check this against fullData legendgroups? - - lgroups.push(uniqueGroup); - lgroupToTraces[uniqueGroup] = [[legendItem]]; - lgroupi++; - } else if(lgroups.indexOf(legendGroup) === -1) { - lgroups.push(legendGroup); - hasOneNonBlankGroup = true; - lgroupToTraces[legendGroup] = [[legendItem]]; - } else lgroupToTraces[legendGroup].push([legendItem]); - } - - // build an { legendgroup: [cd0, cd0], ... } object - for(i = 0; i < calcdata.length; i++) { - var cd = calcdata[i]; - var cd0 = cd[0]; - var trace = cd0.trace; - var lgroup = trace.legendgroup; - - if(!trace.visible || !trace.showlegend) continue; - - if(Registry.traceIs(trace, 'pie-like')) { - if(!slicesShown[lgroup]) slicesShown[lgroup] = {}; - - for(j = 0; j < cd.length; j++) { - var labelj = cd[j].label; - - if(!slicesShown[lgroup][labelj]) { - addOneItem(lgroup, { - label: labelj, - color: cd[j].color, - i: cd[j].i, - trace: trace, - pts: cd[j].pts - }); - - slicesShown[lgroup][labelj] = true; - } - } - } else addOneItem(lgroup, cd0); - } - - // won't draw a legend in this case - if(!lgroups.length) return []; - - // rearrange lgroupToTraces into a d3-friendly array of arrays - var lgroupsLength = lgroups.length; - var ltraces; - var legendData; - - if(hasOneNonBlankGroup && helpers.isGrouped(opts)) { - legendData = new Array(lgroupsLength); - - for(i = 0; i < lgroupsLength; i++) { - ltraces = lgroupToTraces[lgroups[i]]; - legendData[i] = helpers.isReversed(opts) ? ltraces.reverse() : ltraces; - } - } else { - // collapse all groups into one if all groups are blank - legendData = [new Array(lgroupsLength)]; - - for(i = 0; i < lgroupsLength; i++) { - ltraces = lgroupToTraces[lgroups[i]][0]; - legendData[0][helpers.isReversed(opts) ? lgroupsLength - i - 1 : i] = ltraces; - } - lgroupsLength = 1; - } - - // needed in repositionLegend - opts._lgroupsLength = lgroupsLength; - return legendData; -}; - -},{"../../registry":847,"./helpers":648}],647:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); - -var SHOWISOLATETIP = true; - -module.exports = function handleClick(g, gd, numClicks) { - var fullLayout = gd._fullLayout; - - if(gd._dragged || gd._editing) return; - - var itemClick = fullLayout.legend.itemclick; - var itemDoubleClick = fullLayout.legend.itemdoubleclick; - - if(numClicks === 1 && itemClick === 'toggle' && itemDoubleClick === 'toggleothers' && - SHOWISOLATETIP && gd.data && gd._context.showTips - ) { - Lib.notifier(Lib._(gd, 'Double-click on legend to isolate one trace'), 'long'); - SHOWISOLATETIP = false; - } else { - SHOWISOLATETIP = false; - } - - var mode; - if(numClicks === 1) mode = itemClick; - else if(numClicks === 2) mode = itemDoubleClick; - if(!mode) return; - - var hiddenSlices = fullLayout.hiddenlabels ? - fullLayout.hiddenlabels.slice() : - []; - - var legendItem = g.data()[0][0]; - var fullData = gd._fullData; - var fullTrace = legendItem.trace; - var legendgroup = fullTrace.legendgroup; - - var i, j, kcont, key, keys, val; - var attrUpdate = {}; - var attrIndices = []; - var carrs = []; - var carrIdx = []; - - function insertUpdate(traceIndex, key, value) { - var attrIndex = attrIndices.indexOf(traceIndex); - var valueArray = attrUpdate[key]; - if(!valueArray) { - valueArray = attrUpdate[key] = []; - } - - if(attrIndices.indexOf(traceIndex) === -1) { - attrIndices.push(traceIndex); - attrIndex = attrIndices.length - 1; - } - - valueArray[attrIndex] = value; - - return attrIndex; - } - - function setVisibility(fullTrace, visibility) { - var fullInput = fullTrace._fullInput; - if(Registry.hasTransform(fullInput, 'groupby')) { - var kcont = carrs[fullInput.index]; - if(!kcont) { - var groupbyIndices = Registry.getTransformIndices(fullInput, 'groupby'); - var lastGroupbyIndex = groupbyIndices[groupbyIndices.length - 1]; - kcont = Lib.keyedContainer(fullInput, 'transforms[' + lastGroupbyIndex + '].styles', 'target', 'value.visible'); - carrs[fullInput.index] = kcont; - } - - var curState = kcont.get(fullTrace._group); - - // If not specified, assume visible. This happens if there are other style - // properties set for a group but not the visibility. There are many similar - // ways to do this (e.g. why not just `curState = fullTrace.visible`??? The - // answer is: because it breaks other things like groupby trace names in - // subtle ways.) - if(curState === undefined) { - curState = true; - } - - if(curState !== false) { - // true -> legendonly. All others toggle to true: - kcont.set(fullTrace._group, visibility); - } - carrIdx[fullInput.index] = insertUpdate(fullInput.index, 'visible', fullInput.visible === false ? false : true); - } else { - // false -> false (not possible since will not be visible in legend) - // true -> legendonly - // legendonly -> true - var nextVisibility = fullInput.visible === false ? false : visibility; - - insertUpdate(fullInput.index, 'visible', nextVisibility); - } - } - - if(Registry.traceIs(fullTrace, 'pie-like')) { - var thisLabel = legendItem.label; - var thisLabelIndex = hiddenSlices.indexOf(thisLabel); - - if(mode === 'toggle') { - if(thisLabelIndex === -1) hiddenSlices.push(thisLabel); - else hiddenSlices.splice(thisLabelIndex, 1); - } else if(mode === 'toggleothers') { - hiddenSlices = []; - gd.calcdata[0].forEach(function(d) { - if(thisLabel !== d.label) { - hiddenSlices.push(d.label); - } - }); - if(gd._fullLayout.hiddenlabels && gd._fullLayout.hiddenlabels.length === hiddenSlices.length && thisLabelIndex === -1) { - hiddenSlices = []; - } - } - - Registry.call('_guiRelayout', gd, 'hiddenlabels', hiddenSlices); - } else { - var hasLegendgroup = legendgroup && legendgroup.length; - var traceIndicesInGroup = []; - var tracei; - if(hasLegendgroup) { - for(i = 0; i < fullData.length; i++) { - tracei = fullData[i]; - if(!tracei.visible) continue; - if(tracei.legendgroup === legendgroup) { - traceIndicesInGroup.push(i); - } - } - } - - if(mode === 'toggle') { - var nextVisibility; - - switch(fullTrace.visible) { - case true: - nextVisibility = 'legendonly'; - break; - case false: - nextVisibility = false; - break; - case 'legendonly': - nextVisibility = true; - break; - } - - if(hasLegendgroup) { - for(i = 0; i < fullData.length; i++) { - if(fullData[i].visible !== false && fullData[i].legendgroup === legendgroup) { - setVisibility(fullData[i], nextVisibility); - } - } - } else { - setVisibility(fullTrace, nextVisibility); - } - } else if(mode === 'toggleothers') { - // Compute the clicked index. expandedIndex does what we want for expanded traces - // but also culls hidden traces. That means we have some work to do. - var isClicked, isInGroup, otherState; - var isIsolated = true; - for(i = 0; i < fullData.length; i++) { - isClicked = fullData[i] === fullTrace; - if(isClicked) continue; - - isInGroup = (hasLegendgroup && fullData[i].legendgroup === legendgroup); - - if(!isInGroup && fullData[i].visible === true && !Registry.traceIs(fullData[i], 'notLegendIsolatable')) { - isIsolated = false; - break; - } - } - - for(i = 0; i < fullData.length; i++) { - // False is sticky; we don't change it. - if(fullData[i].visible === false) continue; - - if(Registry.traceIs(fullData[i], 'notLegendIsolatable')) { - continue; - } - - switch(fullTrace.visible) { - case 'legendonly': - setVisibility(fullData[i], true); - break; - case true: - otherState = isIsolated ? true : 'legendonly'; - isClicked = fullData[i] === fullTrace; - isInGroup = isClicked || (hasLegendgroup && fullData[i].legendgroup === legendgroup); - setVisibility(fullData[i], isInGroup ? true : otherState); - break; - } - } - } - - for(i = 0; i < carrs.length; i++) { - kcont = carrs[i]; - if(!kcont) continue; - var update = kcont.constructUpdate(); - - var updateKeys = Object.keys(update); - for(j = 0; j < updateKeys.length; j++) { - key = updateKeys[j]; - val = attrUpdate[key] = attrUpdate[key] || []; - val[carrIdx[i]] = update[key]; - } - } - - // The length of the value arrays should be equal and any unspecified - // values should be explicitly undefined for them to get properly culled - // as updates and not accidentally reset to the default value. This fills - // out sparse arrays with the required number of undefined values: - keys = Object.keys(attrUpdate); - for(i = 0; i < keys.length; i++) { - key = keys[i]; - for(j = 0; j < attrIndices.length; j++) { - // Use hasOwnPropety to protect against falsey values: - if(!attrUpdate[key].hasOwnProperty(j)) { - attrUpdate[key][j] = undefined; - } - } - } - - Registry.call('_guiRestyle', gd, attrUpdate, attrIndices); - } -}; - -},{"../../lib":719,"../../registry":847}],648:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -exports.isGrouped = function isGrouped(legendLayout) { - return (legendLayout.traceorder || '').indexOf('grouped') !== -1; -}; - -exports.isVertical = function isVertical(legendLayout) { - return legendLayout.orientation !== 'h'; -}; - -exports.isReversed = function isReversed(legendLayout) { - return (legendLayout.traceorder || '').indexOf('reversed') !== -1; -}; - -},{}],649:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -module.exports = { - moduleType: 'component', - name: 'legend', - - layoutAttributes: _dereq_('./attributes'), - supplyLayoutDefaults: _dereq_('./defaults'), - - draw: _dereq_('./draw'), - style: _dereq_('./style') -}; - -},{"./attributes":642,"./defaults":644,"./draw":645,"./style":650}],650:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../drawing'); -var Color = _dereq_('../color'); - -var subTypes = _dereq_('../../traces/scatter/subtypes'); -var stylePie = _dereq_('../../traces/pie/style_one'); -var pieCastOption = _dereq_('../../traces/pie/helpers').castOption; - -var CST_MARKER_SIZE = 12; -var CST_LINE_WIDTH = 5; -var CST_MARKER_LINE_WIDTH = 2; -var MAX_LINE_WIDTH = 10; -var MAX_MARKER_LINE_WIDTH = 5; - -module.exports = function style(s, gd) { - var fullLayout = gd._fullLayout; - var legend = fullLayout.legend; - var constantItemSizing = legend.itemsizing === 'constant'; - - function boundLineWidth(mlw, cont, max, cst) { - var v; - if(mlw + 1) { - v = mlw; - } else if(cont && cont.width > 0) { - v = cont.width; - } else { - return 0; - } - return constantItemSizing ? cst : Math.min(v, max); - } - - s.each(function(d) { - var traceGroup = d3.select(this); - - var layers = Lib.ensureSingle(traceGroup, 'g', 'layers'); - layers.style('opacity', d[0].trace.opacity); - - var valign = legend.valign; - var lineHeight = d[0].lineHeight; - var height = d[0].height; - - if(valign === 'middle' || !lineHeight || !height) { - layers.attr('transform', null); - } else { - var factor = {top: 1, bottom: -1}[valign]; - var markerOffsetY = factor * (0.5 * (lineHeight - height + 3)); - layers.attr('transform', 'translate(0,' + markerOffsetY + ')'); - } - - var fill = layers - .selectAll('g.legendfill') - .data([d]); - fill.enter().append('g') - .classed('legendfill', true); - - var line = layers - .selectAll('g.legendlines') - .data([d]); - line.enter().append('g') - .classed('legendlines', true); - - var symbol = layers - .selectAll('g.legendsymbols') - .data([d]); - symbol.enter().append('g') - .classed('legendsymbols', true); - - symbol.selectAll('g.legendpoints') - .data([d]) - .enter().append('g') - .classed('legendpoints', true); - }) - .each(styleWaterfalls) - .each(styleFunnels) - .each(styleBars) - .each(styleBoxes) - .each(styleFunnelareas) - .each(stylePies) - .each(styleLines) - .each(stylePoints) - .each(styleCandles) - .each(styleOHLC); - - function styleLines(d) { - var d0 = d[0]; - var trace = d0.trace; - var showFill = trace.visible && trace.fill && trace.fill !== 'none'; - var showLine = subTypes.hasLines(trace); - var contours = trace.contours; - var showGradientLine = false; - var showGradientFill = false; - var dMod, tMod; - - if(contours) { - var coloring = contours.coloring; - - if(coloring === 'lines') { - showGradientLine = true; - } else { - showLine = coloring === 'none' || coloring === 'heatmap' || contours.showlines; - } - - if(contours.type === 'constraint') { - showFill = contours._operation !== '='; - } else if(coloring === 'fill' || coloring === 'heatmap') { - showGradientFill = true; - } - } - - // with fill and no markers or text, move the line and fill up a bit - // so it's more centered - var markersOrText = subTypes.hasMarkers(trace) || subTypes.hasText(trace); - var anyFill = showFill || showGradientFill; - var anyLine = showLine || showGradientLine; - var pathStart = (markersOrText || !anyFill) ? 'M5,0' : - // with a line leave it slightly below center, to leave room for the - // line thickness and because the line is usually more prominent - anyLine ? 'M5,-2' : 'M5,-3'; - - var this3 = d3.select(this); - - var fill = this3.select('.legendfill').selectAll('path') - .data(showFill || showGradientFill ? [d] : []); - fill.enter().append('path').classed('js-fill', true); - fill.exit().remove(); - fill.attr('d', pathStart + 'h30v6h-30z') - .call(showFill ? Drawing.fillGroupStyle : fillGradient); - - if(showLine || showGradientLine) { - var lw = boundLineWidth(undefined, trace.line, MAX_LINE_WIDTH, CST_LINE_WIDTH); - tMod = Lib.minExtend(trace, {line: {width: lw}}); - dMod = [Lib.minExtend(d0, {trace: tMod})]; - } - - var line = this3.select('.legendlines').selectAll('path') - .data(showLine || showGradientLine ? [dMod] : []); - line.enter().append('path').classed('js-line', true); - line.exit().remove(); - - // this is ugly... but you can't apply a gradient to a perfectly - // horizontal or vertical line. Presumably because then - // the system doesn't know how to scale vertical variation, even - // though there *is* no vertical variation in this case. - // so add an invisibly small angle to the line - // This issue (and workaround) exist across (Mac) Chrome, FF, and Safari - line.attr('d', pathStart + (showGradientLine ? 'l30,0.0001' : 'h30')) - .call(showLine ? Drawing.lineGroupStyle : lineGradient); - - function fillGradient(s) { - if(s.size()) { - var gradientID = 'legendfill-' + trace.uid; - Drawing.gradient(s, gd, gradientID, 'horizontalreversed', - trace.colorscale, 'fill'); - } - } - - function lineGradient(s) { - if(s.size()) { - var gradientID = 'legendline-' + trace.uid; - Drawing.lineGroupStyle(s); - Drawing.gradient(s, gd, gradientID, 'horizontalreversed', - trace.colorscale, 'stroke'); - } - } - } - - function stylePoints(d) { - var d0 = d[0]; - var trace = d0.trace; - var showMarkers = subTypes.hasMarkers(trace); - var showText = subTypes.hasText(trace); - var showLines = subTypes.hasLines(trace); - var dMod, tMod; - - // 'scatter3d' don't use gd.calcdata, - // use d0.trace to infer arrayOk attributes - - function boundVal(attrIn, arrayToValFn, bounds, cst) { - var valIn = Lib.nestedProperty(trace, attrIn).get(); - var valToBound = (Lib.isArrayOrTypedArray(valIn) && arrayToValFn) ? - arrayToValFn(valIn) : - valIn; - - if(constantItemSizing && valToBound && cst !== undefined) { - valToBound = cst; - } - - if(bounds) { - if(valToBound < bounds[0]) return bounds[0]; - else if(valToBound > bounds[1]) return bounds[1]; - } - return valToBound; - } - - function pickFirst(array) { return array[0]; } - - // constrain text, markers, etc so they'll fit on the legend - if(showMarkers || showText || showLines) { - var dEdit = {}; - var tEdit = {}; - - if(showMarkers) { - dEdit.mc = boundVal('marker.color', pickFirst); - dEdit.mx = boundVal('marker.symbol', pickFirst); - dEdit.mo = boundVal('marker.opacity', Lib.mean, [0.2, 1]); - dEdit.mlc = boundVal('marker.line.color', pickFirst); - dEdit.mlw = boundVal('marker.line.width', Lib.mean, [0, 5], CST_MARKER_LINE_WIDTH); - tEdit.marker = { - sizeref: 1, - sizemin: 1, - sizemode: 'diameter' - }; - - var ms = boundVal('marker.size', Lib.mean, [2, 16], CST_MARKER_SIZE); - dEdit.ms = ms; - tEdit.marker.size = ms; - } - - if(showLines) { - tEdit.line = { - width: boundVal('line.width', pickFirst, [0, 10], CST_LINE_WIDTH) - }; - } - - if(showText) { - dEdit.tx = 'Aa'; - dEdit.tp = boundVal('textposition', pickFirst); - dEdit.ts = 10; - dEdit.tc = boundVal('textfont.color', pickFirst); - dEdit.tf = boundVal('textfont.family', pickFirst); - } - - dMod = [Lib.minExtend(d0, dEdit)]; - tMod = Lib.minExtend(trace, tEdit); - - // always show legend items in base state - tMod.selectedpoints = null; - } - - var ptgroup = d3.select(this).select('g.legendpoints'); - - var pts = ptgroup.selectAll('path.scatterpts') - .data(showMarkers ? dMod : []); - // make sure marker is on the bottom, in case it enters after text - pts.enter().insert('path', ':first-child') - .classed('scatterpts', true) - .attr('transform', 'translate(20,0)'); - pts.exit().remove(); - pts.call(Drawing.pointStyle, tMod, gd); - - // 'mrc' is set in pointStyle and used in textPointStyle: - // constrain it here - if(showMarkers) dMod[0].mrc = 3; - - var txt = ptgroup.selectAll('g.pointtext') - .data(showText ? dMod : []); - txt.enter() - .append('g').classed('pointtext', true) - .append('text').attr('transform', 'translate(20,0)'); - txt.exit().remove(); - txt.selectAll('text').call(Drawing.textPointStyle, tMod, gd); - } - - function styleWaterfalls(d) { - var trace = d[0].trace; - - var ptsData = []; - if(trace.type === 'waterfall' && trace.visible) { - ptsData = d[0].hasTotals ? - [['increasing', 'M-6,-6V6H0Z'], ['totals', 'M6,6H0L-6,-6H-0Z'], ['decreasing', 'M6,6V-6H0Z']] : - [['increasing', 'M-6,-6V6H6Z'], ['decreasing', 'M6,6V-6H-6Z']]; - } - - var pts = d3.select(this).select('g.legendpoints') - .selectAll('path.legendwaterfall') - .data(ptsData); - pts.enter().append('path').classed('legendwaterfall', true) - .attr('transform', 'translate(20,0)') - .style('stroke-miterlimit', 1); - pts.exit().remove(); - - pts.each(function(dd) { - var pt = d3.select(this); - var cont = trace[dd[0]].marker; - var lw = boundLineWidth(undefined, cont.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH); - - pt.attr('d', dd[1]) - .style('stroke-width', lw + 'px') - .call(Color.fill, cont.color); - - if(lw) { - pt.call(Color.stroke, cont.line.color); - } - }); - } - - function styleBars(d) { - styleBarLike(d, this); - } - - function styleFunnels(d) { - styleBarLike(d, this, 'funnel'); - } - - function styleBarLike(d, lThis, desiredType) { - var trace = d[0].trace; - var marker = trace.marker || {}; - var markerLine = marker.line || {}; - - var isVisible = (!desiredType) ? Registry.traceIs(trace, 'bar') : - (trace.type === desiredType && trace.visible); - - var barpath = d3.select(lThis).select('g.legendpoints') - .selectAll('path.legend' + desiredType) - .data(isVisible ? [d] : []); - barpath.enter().append('path').classed('legend' + desiredType, true) - .attr('d', 'M6,6H-6V-6H6Z') - .attr('transform', 'translate(20,0)'); - barpath.exit().remove(); - - barpath.each(function(d) { - var p = d3.select(this); - var d0 = d[0]; - var w = boundLineWidth(d0.mlw, marker.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH); - - p.style('stroke-width', w + 'px') - .call(Color.fill, d0.mc || marker.color); - - if(w) Color.stroke(p, d0.mlc || markerLine.color); - }); - } - - function styleBoxes(d) { - var trace = d[0].trace; - - var pts = d3.select(this).select('g.legendpoints') - .selectAll('path.legendbox') - .data(Registry.traceIs(trace, 'box-violin') && trace.visible ? [d] : []); - pts.enter().append('path').classed('legendbox', true) - // if we want the median bar, prepend M6,0H-6 - .attr('d', 'M6,6H-6V-6H6Z') - .attr('transform', 'translate(20,0)'); - pts.exit().remove(); - - pts.each(function() { - var p = d3.select(this); - - if((trace.boxpoints === 'all' || trace.points === 'all') && - Color.opacity(trace.fillcolor) === 0 && Color.opacity((trace.line || {}).color) === 0 - ) { - var tMod = Lib.minExtend(trace, { - marker: { - size: constantItemSizing ? CST_MARKER_SIZE : Lib.constrain(trace.marker.size, 2, 16), - sizeref: 1, - sizemin: 1, - sizemode: 'diameter' - } - }); - pts.call(Drawing.pointStyle, tMod, gd); - } else { - var w = boundLineWidth(undefined, trace.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH); - - p.style('stroke-width', w + 'px') - .call(Color.fill, trace.fillcolor); - - if(w) Color.stroke(p, trace.line.color); - } - }); - } - - function styleCandles(d) { - var trace = d[0].trace; - - var pts = d3.select(this).select('g.legendpoints') - .selectAll('path.legendcandle') - .data(trace.type === 'candlestick' && trace.visible ? [d, d] : []); - pts.enter().append('path').classed('legendcandle', true) - .attr('d', function(_, i) { - if(i) return 'M-15,0H-8M-8,6V-6H8Z'; // increasing - return 'M15,0H8M8,-6V6H-8Z'; // decreasing - }) - .attr('transform', 'translate(20,0)') - .style('stroke-miterlimit', 1); - pts.exit().remove(); - - pts.each(function(_, i) { - var p = d3.select(this); - var cont = trace[i ? 'increasing' : 'decreasing']; - var w = boundLineWidth(undefined, cont.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH); - - p.style('stroke-width', w + 'px') - .call(Color.fill, cont.fillcolor); - - if(w) Color.stroke(p, cont.line.color); - }); - } - - function styleOHLC(d) { - var trace = d[0].trace; - - var pts = d3.select(this).select('g.legendpoints') - .selectAll('path.legendohlc') - .data(trace.type === 'ohlc' && trace.visible ? [d, d] : []); - pts.enter().append('path').classed('legendohlc', true) - .attr('d', function(_, i) { - if(i) return 'M-15,0H0M-8,-6V0'; // increasing - return 'M15,0H0M8,6V0'; // decreasing - }) - .attr('transform', 'translate(20,0)') - .style('stroke-miterlimit', 1); - pts.exit().remove(); - - pts.each(function(_, i) { - var p = d3.select(this); - var cont = trace[i ? 'increasing' : 'decreasing']; - var w = boundLineWidth(undefined, cont.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH); - - p.style('fill', 'none') - .call(Drawing.dashLine, cont.line.dash, w); - - if(w) Color.stroke(p, cont.line.color); - }); - } - - function stylePies(d) { - stylePieLike(d, this, 'pie'); - } - - function styleFunnelareas(d) { - stylePieLike(d, this, 'funnelarea'); - } - - function stylePieLike(d, lThis, desiredType) { - var d0 = d[0]; - var trace = d0.trace; - - var isVisible = (!desiredType) ? Registry.traceIs(trace, desiredType) : - (trace.type === desiredType && trace.visible); - - var pts = d3.select(lThis).select('g.legendpoints') - .selectAll('path.legend' + desiredType) - .data(isVisible ? [d] : []); - pts.enter().append('path').classed('legend' + desiredType, true) - .attr('d', 'M6,6H-6V-6H6Z') - .attr('transform', 'translate(20,0)'); - pts.exit().remove(); - - if(pts.size()) { - var cont = (trace.marker || {}).line; - var lw = boundLineWidth(pieCastOption(cont.width, d0.pts), cont, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH); - - var tMod = Lib.minExtend(trace, {marker: {line: {width: lw}}}); - // since minExtend do not slice more than 3 items we need to patch line.color here - tMod.marker.line.color = cont.color; - - var d0Mod = Lib.minExtend(d0, {trace: tMod}); - - stylePie(pts, d0Mod, tMod); - } - } -}; - -},{"../../lib":719,"../../registry":847,"../../traces/pie/helpers":1091,"../../traces/pie/style_one":1097,"../../traces/scatter/subtypes":1135,"../color":593,"../drawing":614,"d3":163}],651:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Plots = _dereq_('../../plots/plots'); -var axisIds = _dereq_('../../plots/cartesian/axis_ids'); -var Lib = _dereq_('../../lib'); -var Icons = _dereq_('../../fonts/ploticon'); - -var _ = Lib._; - -var modeBarButtons = module.exports = {}; - -/** - * ModeBar buttons configuration - * - * @param {string} name - * name / id of the buttons (for tracking) - * @param {string} title - * text that appears while hovering over the button, - * enter null, false or '' for no hover text - * @param {string} icon - * svg icon object associated with the button - * can be linked to Plotly.Icons to use the default plotly icons - * @param {string} [gravity] - * icon positioning - * @param {function} click - * click handler associated with the button, a function of - * 'gd' (the main graph object) and - * 'ev' (the event object) - * @param {string} [attr] - * attribute associated with button, - * use this with 'val' to keep track of the state - * @param {*} [val] - * initial 'attr' value, can be a function of gd - * @param {boolean} [toggle] - * is the button a toggle button? - */ -modeBarButtons.toImage = { - name: 'toImage', - title: function(gd) { - var opts = gd._context.toImageButtonOptions || {}; - var format = opts.format || 'png'; - return format === 'png' ? - _(gd, 'Download plot as a png') : // legacy text - _(gd, 'Download plot'); // generic non-PNG text - }, - icon: Icons.camera, - click: function(gd) { - var toImageButtonOptions = gd._context.toImageButtonOptions; - var opts = {format: toImageButtonOptions.format || 'png'}; - - Lib.notifier(_(gd, 'Taking snapshot - this may take a few seconds'), 'long'); - - if(opts.format !== 'svg' && Lib.isIE()) { - Lib.notifier(_(gd, 'IE only supports svg. Changing format to svg.'), 'long'); - opts.format = 'svg'; - } - - ['filename', 'width', 'height', 'scale'].forEach(function(key) { - if(key in toImageButtonOptions) { - opts[key] = toImageButtonOptions[key]; - } - }); - - Registry.call('downloadImage', gd, opts) - .then(function(filename) { - Lib.notifier(_(gd, 'Snapshot succeeded') + ' - ' + filename, 'long'); - }) - .catch(function() { - Lib.notifier(_(gd, 'Sorry, there was a problem downloading your snapshot!'), 'long'); - }); - } -}; - -modeBarButtons.sendDataToCloud = { - name: 'sendDataToCloud', - title: function(gd) { return _(gd, 'Edit in Chart Studio'); }, - icon: Icons.disk, - click: function(gd) { - Plots.sendDataToCloud(gd); - } -}; - -modeBarButtons.editInChartStudio = { - name: 'editInChartStudio', - title: function(gd) { return _(gd, 'Edit in Chart Studio'); }, - icon: Icons.pencil, - click: function(gd) { - Plots.sendDataToCloud(gd); - } -}; - -modeBarButtons.zoom2d = { - name: 'zoom2d', - title: function(gd) { return _(gd, 'Zoom'); }, - attr: 'dragmode', - val: 'zoom', - icon: Icons.zoombox, - click: handleCartesian -}; - -modeBarButtons.pan2d = { - name: 'pan2d', - title: function(gd) { return _(gd, 'Pan'); }, - attr: 'dragmode', - val: 'pan', - icon: Icons.pan, - click: handleCartesian -}; - -modeBarButtons.select2d = { - name: 'select2d', - title: function(gd) { return _(gd, 'Box Select'); }, - attr: 'dragmode', - val: 'select', - icon: Icons.selectbox, - click: handleCartesian -}; - -modeBarButtons.lasso2d = { - name: 'lasso2d', - title: function(gd) { return _(gd, 'Lasso Select'); }, - attr: 'dragmode', - val: 'lasso', - icon: Icons.lasso, - click: handleCartesian -}; - -modeBarButtons.zoomIn2d = { - name: 'zoomIn2d', - title: function(gd) { return _(gd, 'Zoom in'); }, - attr: 'zoom', - val: 'in', - icon: Icons.zoom_plus, - click: handleCartesian -}; - -modeBarButtons.zoomOut2d = { - name: 'zoomOut2d', - title: function(gd) { return _(gd, 'Zoom out'); }, - attr: 'zoom', - val: 'out', - icon: Icons.zoom_minus, - click: handleCartesian -}; - -modeBarButtons.autoScale2d = { - name: 'autoScale2d', - title: function(gd) { return _(gd, 'Autoscale'); }, - attr: 'zoom', - val: 'auto', - icon: Icons.autoscale, - click: handleCartesian -}; - -modeBarButtons.resetScale2d = { - name: 'resetScale2d', - title: function(gd) { return _(gd, 'Reset axes'); }, - attr: 'zoom', - val: 'reset', - icon: Icons.home, - click: handleCartesian -}; - -modeBarButtons.hoverClosestCartesian = { - name: 'hoverClosestCartesian', - title: function(gd) { return _(gd, 'Show closest data on hover'); }, - attr: 'hovermode', - val: 'closest', - icon: Icons.tooltip_basic, - gravity: 'ne', - click: handleCartesian -}; - -modeBarButtons.hoverCompareCartesian = { - name: 'hoverCompareCartesian', - title: function(gd) { return _(gd, 'Compare data on hover'); }, - attr: 'hovermode', - val: function(gd) { - return gd._fullLayout._isHoriz ? 'y' : 'x'; - }, - icon: Icons.tooltip_compare, - gravity: 'ne', - click: handleCartesian -}; - -function handleCartesian(gd, ev) { - var button = ev.currentTarget; - var astr = button.getAttribute('data-attr'); - var val = button.getAttribute('data-val') || true; - var fullLayout = gd._fullLayout; - var aobj = {}; - var axList = axisIds.list(gd, null, true); - var allSpikesEnabled = 'on'; - - var ax, i; - - if(astr === 'zoom') { - var mag = (val === 'in') ? 0.5 : 2; - var r0 = (1 + mag) / 2; - var r1 = (1 - mag) / 2; - var axName; - - for(i = 0; i < axList.length; i++) { - ax = axList[i]; - - if(!ax.fixedrange) { - axName = ax._name; - if(val === 'auto') aobj[axName + '.autorange'] = true; - else if(val === 'reset') { - if(ax._rangeInitial === undefined) { - aobj[axName + '.autorange'] = true; - } else { - var rangeInitial = ax._rangeInitial.slice(); - aobj[axName + '.range[0]'] = rangeInitial[0]; - aobj[axName + '.range[1]'] = rangeInitial[1]; - } - if(ax._showSpikeInitial !== undefined) { - aobj[axName + '.showspikes'] = ax._showSpikeInitial; - if(allSpikesEnabled === 'on' && !ax._showSpikeInitial) { - allSpikesEnabled = 'off'; - } - } - } else { - var rangeNow = [ - ax.r2l(ax.range[0]), - ax.r2l(ax.range[1]), - ]; - - var rangeNew = [ - r0 * rangeNow[0] + r1 * rangeNow[1], - r0 * rangeNow[1] + r1 * rangeNow[0] - ]; - - aobj[axName + '.range[0]'] = ax.l2r(rangeNew[0]); - aobj[axName + '.range[1]'] = ax.l2r(rangeNew[1]); - } - } - } - fullLayout._cartesianSpikesEnabled = allSpikesEnabled; - } else { - // if ALL traces have orientation 'h', 'hovermode': 'x' otherwise: 'y' - if(astr === 'hovermode' && (val === 'x' || val === 'y')) { - val = fullLayout._isHoriz ? 'y' : 'x'; - button.setAttribute('data-val', val); - } else if(astr === 'hovermode' && val === 'closest') { - for(i = 0; i < axList.length; i++) { - ax = axList[i]; - if(allSpikesEnabled === 'on' && !ax.showspikes) { - allSpikesEnabled = 'off'; - } - } - fullLayout._cartesianSpikesEnabled = allSpikesEnabled; - } - - aobj[astr] = val; - } - - Registry.call('_guiRelayout', gd, aobj); -} - -modeBarButtons.zoom3d = { - name: 'zoom3d', - title: function(gd) { return _(gd, 'Zoom'); }, - attr: 'scene.dragmode', - val: 'zoom', - icon: Icons.zoombox, - click: handleDrag3d -}; - -modeBarButtons.pan3d = { - name: 'pan3d', - title: function(gd) { return _(gd, 'Pan'); }, - attr: 'scene.dragmode', - val: 'pan', - icon: Icons.pan, - click: handleDrag3d -}; - -modeBarButtons.orbitRotation = { - name: 'orbitRotation', - title: function(gd) { return _(gd, 'Orbital rotation'); }, - attr: 'scene.dragmode', - val: 'orbit', - icon: Icons['3d_rotate'], - click: handleDrag3d -}; - -modeBarButtons.tableRotation = { - name: 'tableRotation', - title: function(gd) { return _(gd, 'Turntable rotation'); }, - attr: 'scene.dragmode', - val: 'turntable', - icon: Icons['z-axis'], - click: handleDrag3d -}; - -function handleDrag3d(gd, ev) { - var button = ev.currentTarget; - var attr = button.getAttribute('data-attr'); - var val = button.getAttribute('data-val') || true; - var sceneIds = gd._fullLayout._subplots.gl3d; - var layoutUpdate = {}; - - var parts = attr.split('.'); - - for(var i = 0; i < sceneIds.length; i++) { - layoutUpdate[sceneIds[i] + '.' + parts[1]] = val; - } - - // for multi-type subplots - var val2d = (val === 'pan') ? val : 'zoom'; - layoutUpdate.dragmode = val2d; - - Registry.call('_guiRelayout', gd, layoutUpdate); -} - -modeBarButtons.resetCameraDefault3d = { - name: 'resetCameraDefault3d', - title: function(gd) { return _(gd, 'Reset camera to default'); }, - attr: 'resetDefault', - icon: Icons.home, - click: handleCamera3d -}; - -modeBarButtons.resetCameraLastSave3d = { - name: 'resetCameraLastSave3d', - title: function(gd) { return _(gd, 'Reset camera to last save'); }, - attr: 'resetLastSave', - icon: Icons.movie, - click: handleCamera3d -}; - -function handleCamera3d(gd, ev) { - var button = ev.currentTarget; - var attr = button.getAttribute('data-attr'); - var fullLayout = gd._fullLayout; - var sceneIds = fullLayout._subplots.gl3d; - var aobj = {}; - - for(var i = 0; i < sceneIds.length; i++) { - var sceneId = sceneIds[i]; - var key = sceneId + '.camera'; - var scene = fullLayout[sceneId]._scene; - - if(attr === 'resetLastSave') { - aobj[key + '.up'] = scene.viewInitial.up; - aobj[key + '.eye'] = scene.viewInitial.eye; - aobj[key + '.center'] = scene.viewInitial.center; - } else if(attr === 'resetDefault') { - aobj[key + '.up'] = null; - aobj[key + '.eye'] = null; - aobj[key + '.center'] = null; - } - } - - Registry.call('_guiRelayout', gd, aobj); -} - -modeBarButtons.hoverClosest3d = { - name: 'hoverClosest3d', - title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, - attr: 'hovermode', - val: null, - toggle: true, - icon: Icons.tooltip_basic, - gravity: 'ne', - click: handleHover3d -}; - -function getNextHover3d(gd, ev) { - var button = ev.currentTarget; - var val = button._previousVal; - var fullLayout = gd._fullLayout; - var sceneIds = fullLayout._subplots.gl3d; - - var axes = ['xaxis', 'yaxis', 'zaxis']; - - // initialize 'current spike' object to be stored in the DOM - var currentSpikes = {}; - var layoutUpdate = {}; - - if(val) { - layoutUpdate = val; - button._previousVal = null; - } else { - for(var i = 0; i < sceneIds.length; i++) { - var sceneId = sceneIds[i]; - var sceneLayout = fullLayout[sceneId]; - - var hovermodeAStr = sceneId + '.hovermode'; - currentSpikes[hovermodeAStr] = sceneLayout.hovermode; - layoutUpdate[hovermodeAStr] = false; - - // copy all the current spike attrs - for(var j = 0; j < 3; j++) { - var axis = axes[j]; - var spikeAStr = sceneId + '.' + axis + '.showspikes'; - layoutUpdate[spikeAStr] = false; - currentSpikes[spikeAStr] = sceneLayout[axis].showspikes; - } - } - - button._previousVal = currentSpikes; - } - return layoutUpdate; -} - -function handleHover3d(gd, ev) { - var layoutUpdate = getNextHover3d(gd, ev); - Registry.call('_guiRelayout', gd, layoutUpdate); -} - -modeBarButtons.zoomInGeo = { - name: 'zoomInGeo', - title: function(gd) { return _(gd, 'Zoom in'); }, - attr: 'zoom', - val: 'in', - icon: Icons.zoom_plus, - click: handleGeo -}; - -modeBarButtons.zoomOutGeo = { - name: 'zoomOutGeo', - title: function(gd) { return _(gd, 'Zoom out'); }, - attr: 'zoom', - val: 'out', - icon: Icons.zoom_minus, - click: handleGeo -}; - -modeBarButtons.resetGeo = { - name: 'resetGeo', - title: function(gd) { return _(gd, 'Reset'); }, - attr: 'reset', - val: null, - icon: Icons.autoscale, - click: handleGeo -}; - -modeBarButtons.hoverClosestGeo = { - name: 'hoverClosestGeo', - title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, - attr: 'hovermode', - val: null, - toggle: true, - icon: Icons.tooltip_basic, - gravity: 'ne', - click: toggleHover -}; - -function handleGeo(gd, ev) { - var button = ev.currentTarget; - var attr = button.getAttribute('data-attr'); - var val = button.getAttribute('data-val') || true; - var fullLayout = gd._fullLayout; - var geoIds = fullLayout._subplots.geo; - - for(var i = 0; i < geoIds.length; i++) { - var id = geoIds[i]; - var geoLayout = fullLayout[id]; - - if(attr === 'zoom') { - var scale = geoLayout.projection.scale; - var newScale = (val === 'in') ? 2 * scale : 0.5 * scale; - - Registry.call('_guiRelayout', gd, id + '.projection.scale', newScale); - } else if(attr === 'reset') { - resetView(gd, 'geo'); - } - } -} - -modeBarButtons.hoverClosestGl2d = { - name: 'hoverClosestGl2d', - title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, - attr: 'hovermode', - val: null, - toggle: true, - icon: Icons.tooltip_basic, - gravity: 'ne', - click: toggleHover -}; - -modeBarButtons.hoverClosestPie = { - name: 'hoverClosestPie', - title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, - attr: 'hovermode', - val: 'closest', - icon: Icons.tooltip_basic, - gravity: 'ne', - click: toggleHover -}; - -function getNextHover(gd) { - var fullLayout = gd._fullLayout; - - if(fullLayout.hovermode) return false; - - if(fullLayout._has('cartesian')) { - return fullLayout._isHoriz ? 'y' : 'x'; - } - return 'closest'; -} - -function toggleHover(gd) { - var newHover = getNextHover(gd); - Registry.call('_guiRelayout', gd, 'hovermode', newHover); -} - -modeBarButtons.resetViewSankey = { - name: 'resetSankeyGroup', - title: function(gd) { return _(gd, 'Reset view'); }, - icon: Icons.home, - click: function(gd) { - var aObj = { - 'node.groups': [], - 'node.x': [], - 'node.y': [] - }; - for(var i = 0; i < gd._fullData.length; i++) { - var viewInitial = gd._fullData[i]._viewInitial; - aObj['node.groups'].push(viewInitial.node.groups.slice()); - aObj['node.x'].push(viewInitial.node.x.slice()); - aObj['node.y'].push(viewInitial.node.y.slice()); - } - Registry.call('restyle', gd, aObj); - } -}; - -// buttons when more then one plot types are present - -modeBarButtons.toggleHover = { - name: 'toggleHover', - title: function(gd) { return _(gd, 'Toggle show closest data on hover'); }, - attr: 'hovermode', - val: null, - toggle: true, - icon: Icons.tooltip_basic, - gravity: 'ne', - click: function(gd, ev) { - var layoutUpdate = getNextHover3d(gd, ev); - layoutUpdate.hovermode = getNextHover(gd); - - Registry.call('_guiRelayout', gd, layoutUpdate); - } -}; - -modeBarButtons.resetViews = { - name: 'resetViews', - title: function(gd) { return _(gd, 'Reset views'); }, - icon: Icons.home, - click: function(gd, ev) { - var button = ev.currentTarget; - - button.setAttribute('data-attr', 'zoom'); - button.setAttribute('data-val', 'reset'); - handleCartesian(gd, ev); - - button.setAttribute('data-attr', 'resetLastSave'); - handleCamera3d(gd, ev); - - resetView(gd, 'geo'); - resetView(gd, 'mapbox'); - } -}; - -modeBarButtons.toggleSpikelines = { - name: 'toggleSpikelines', - title: function(gd) { return _(gd, 'Toggle Spike Lines'); }, - icon: Icons.spikeline, - attr: '_cartesianSpikesEnabled', - val: 'on', - click: function(gd) { - var fullLayout = gd._fullLayout; - - fullLayout._cartesianSpikesEnabled = fullLayout._cartesianSpikesEnabled === 'on' ? 'off' : 'on'; - - var aobj = setSpikelineVisibility(gd); - - Registry.call('_guiRelayout', gd, aobj); - } -}; - -function setSpikelineVisibility(gd) { - var fullLayout = gd._fullLayout; - var axList = axisIds.list(gd, null, true); - var aobj = {}; - - var ax, axName; - - for(var i = 0; i < axList.length; i++) { - ax = axList[i]; - axName = ax._name; - aobj[axName + '.showspikes'] = fullLayout._cartesianSpikesEnabled === 'on' ? true : ax._showSpikeInitial; - } - - return aobj; -} - -modeBarButtons.resetViewMapbox = { - name: 'resetViewMapbox', - title: function(gd) { return _(gd, 'Reset view'); }, - attr: 'reset', - icon: Icons.home, - click: function(gd) { - resetView(gd, 'mapbox'); - } -}; - -function resetView(gd, subplotType) { - var fullLayout = gd._fullLayout; - var subplotIds = fullLayout._subplots[subplotType]; - var aObj = {}; - - for(var i = 0; i < subplotIds.length; i++) { - var id = subplotIds[i]; - var subplotObj = fullLayout[id]._subplot; - var viewInitial = subplotObj.viewInitial; - var viewKeys = Object.keys(viewInitial); - - for(var j = 0; j < viewKeys.length; j++) { - var key = viewKeys[j]; - aObj[id + '.' + key] = viewInitial[key]; - } - } - - Registry.call('_guiRelayout', gd, aObj); -} - -},{"../../fonts/ploticon":699,"../../lib":719,"../../plots/cartesian/axis_ids":770,"../../plots/plots":828,"../../registry":847}],652:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -exports.manage = _dereq_('./manage'); - -},{"./manage":653}],653:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var axisIds = _dereq_('../../plots/cartesian/axis_ids'); -var scatterSubTypes = _dereq_('../../traces/scatter/subtypes'); -var Registry = _dereq_('../../registry'); - -var createModeBar = _dereq_('./modebar'); -var modeBarButtons = _dereq_('./buttons'); - -/** - * ModeBar wrapper around 'create' and 'update', - * chooses buttons to pass to ModeBar constructor based on - * plot type and plot config. - * - * @param {object} gd main plot object - * - */ -module.exports = function manageModeBar(gd) { - var fullLayout = gd._fullLayout; - var context = gd._context; - var modeBar = fullLayout._modeBar; - - if(!context.displayModeBar && !context.watermark) { - if(modeBar) { - modeBar.destroy(); - delete fullLayout._modeBar; - } - return; - } - - if(!Array.isArray(context.modeBarButtonsToRemove)) { - throw new Error([ - '*modeBarButtonsToRemove* configuration options', - 'must be an array.' - ].join(' ')); - } - - if(!Array.isArray(context.modeBarButtonsToAdd)) { - throw new Error([ - '*modeBarButtonsToAdd* configuration options', - 'must be an array.' - ].join(' ')); - } - - var customButtons = context.modeBarButtons; - var buttonGroups; - - if(Array.isArray(customButtons) && customButtons.length) { - buttonGroups = fillCustomButton(customButtons); - } else if(!context.displayModeBar && context.watermark) { - buttonGroups = []; - } else { - buttonGroups = getButtonGroups(gd); - } - - if(modeBar) modeBar.update(gd, buttonGroups); - else fullLayout._modeBar = createModeBar(gd, buttonGroups); -}; - -// logic behind which buttons are displayed by default -function getButtonGroups(gd) { - var fullLayout = gd._fullLayout; - var fullData = gd._fullData; - var context = gd._context; - var buttonsToRemove = context.modeBarButtonsToRemove; - var buttonsToAdd = context.modeBarButtonsToAdd; - - var hasCartesian = fullLayout._has('cartesian'); - var hasGL3D = fullLayout._has('gl3d'); - var hasGeo = fullLayout._has('geo'); - var hasPie = fullLayout._has('pie'); - var hasFunnelarea = fullLayout._has('funnelarea'); - var hasGL2D = fullLayout._has('gl2d'); - var hasTernary = fullLayout._has('ternary'); - var hasMapbox = fullLayout._has('mapbox'); - var hasPolar = fullLayout._has('polar'); - var hasSankey = fullLayout._has('sankey'); - var allAxesFixed = areAllAxesFixed(fullLayout); - - var groups = []; - - function addGroup(newGroup) { - if(!newGroup.length) return; - - var out = []; - - for(var i = 0; i < newGroup.length; i++) { - var button = newGroup[i]; - if(buttonsToRemove.indexOf(button) !== -1) continue; - out.push(modeBarButtons[button]); - } - - groups.push(out); - } - - // buttons common to all plot types - var commonGroup = ['toImage']; - if(context.showEditInChartStudio) commonGroup.push('editInChartStudio'); - else if(context.showSendToCloud) commonGroup.push('sendDataToCloud'); - addGroup(commonGroup); - - var zoomGroup = []; - var hoverGroup = []; - var resetGroup = []; - var dragModeGroup = []; - - if((hasCartesian || hasGL2D || hasPie || hasFunnelarea || hasTernary) + hasGeo + hasGL3D + hasMapbox + hasPolar > 1) { - // graphs with more than one plot types get 'union buttons' - // which reset the view or toggle hover labels across all subplots. - hoverGroup = ['toggleHover']; - resetGroup = ['resetViews']; - } else if(hasGeo) { - zoomGroup = ['zoomInGeo', 'zoomOutGeo']; - hoverGroup = ['hoverClosestGeo']; - resetGroup = ['resetGeo']; - } else if(hasGL3D) { - hoverGroup = ['hoverClosest3d']; - resetGroup = ['resetCameraDefault3d', 'resetCameraLastSave3d']; - } else if(hasMapbox) { - hoverGroup = ['toggleHover']; - resetGroup = ['resetViewMapbox']; - } else if(hasGL2D) { - hoverGroup = ['hoverClosestGl2d']; - } else if(hasPie) { - hoverGroup = ['hoverClosestPie']; - } else if(hasSankey) { - hoverGroup = ['hoverClosestCartesian', 'hoverCompareCartesian']; - resetGroup = ['resetViewSankey']; - } else { // hasPolar, hasTernary - // always show at least one hover icon. - hoverGroup = ['toggleHover']; - } - // if we have cartesian, allow switching between closest and compare - // regardless of what other types are on the plot, since they'll all - // just treat any truthy hovermode as 'closest' - if(hasCartesian) { - hoverGroup = ['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian']; - } - if(hasNoHover(fullData)) { - hoverGroup = []; - } - - if((hasCartesian || hasGL2D) && !allAxesFixed) { - zoomGroup = ['zoomIn2d', 'zoomOut2d', 'autoScale2d']; - if(resetGroup[0] !== 'resetViews') resetGroup = ['resetScale2d']; - } - - if(hasGL3D) { - dragModeGroup = ['zoom3d', 'pan3d', 'orbitRotation', 'tableRotation']; - } else if(((hasCartesian || hasGL2D) && !allAxesFixed) || hasTernary) { - dragModeGroup = ['zoom2d', 'pan2d']; - } else if(hasMapbox || hasGeo) { - dragModeGroup = ['pan2d']; - } else if(hasPolar) { - dragModeGroup = ['zoom2d']; - } - if(isSelectable(fullData)) { - dragModeGroup.push('select2d', 'lasso2d'); - } - - addGroup(dragModeGroup); - addGroup(zoomGroup.concat(resetGroup)); - addGroup(hoverGroup); - - return appendButtonsToGroups(groups, buttonsToAdd); -} - -function areAllAxesFixed(fullLayout) { - var axList = axisIds.list({_fullLayout: fullLayout}, null, true); - - for(var i = 0; i < axList.length; i++) { - if(!axList[i].fixedrange) { - return false; - } - } - - return true; -} - -// look for traces that support selection -// to be updated as we add more selectPoints handlers -function isSelectable(fullData) { - var selectable = false; - - for(var i = 0; i < fullData.length; i++) { - if(selectable) break; - - var trace = fullData[i]; - - if(!trace._module || !trace._module.selectPoints) continue; - - if(Registry.traceIs(trace, 'scatter-like')) { - if(scatterSubTypes.hasMarkers(trace) || scatterSubTypes.hasText(trace)) { - selectable = true; - } - } else if(Registry.traceIs(trace, 'box-violin')) { - if(trace.boxpoints === 'all' || trace.points === 'all') { - selectable = true; - } - } else { - // assume that in general if the trace module has selectPoints, - // then it's selectable. Scatter is an exception to this because it must - // have markers or text, not just be a scatter type. - - selectable = true; - } - } - - return selectable; -} - -// check whether all trace are 'noHover' -function hasNoHover(fullData) { - for(var i = 0; i < fullData.length; i++) { - if(!Registry.traceIs(fullData[i], 'noHover')) return false; - } - return true; -} - -function appendButtonsToGroups(groups, buttons) { - if(buttons.length) { - if(Array.isArray(buttons[0])) { - for(var i = 0; i < buttons.length; i++) { - groups.push(buttons[i]); - } - } else groups.push(buttons); - } - - return groups; -} - -// fill in custom buttons referring to default mode bar buttons -function fillCustomButton(customButtons) { - for(var i = 0; i < customButtons.length; i++) { - var buttonGroup = customButtons[i]; - - for(var j = 0; j < buttonGroup.length; j++) { - var button = buttonGroup[j]; - - if(typeof button === 'string') { - if(modeBarButtons[button] !== undefined) { - customButtons[i][j] = modeBarButtons[button]; - } else { - throw new Error([ - '*modeBarButtons* configuration options', - 'invalid button name' - ].join(' ')); - } - } - } - } - - return customButtons; -} - -},{"../../plots/cartesian/axis_ids":770,"../../registry":847,"../../traces/scatter/subtypes":1135,"./buttons":651,"./modebar":654}],654:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var Icons = _dereq_('../../fonts/ploticon'); -var Parser = new DOMParser(); - -/** - * UI controller for interactive plots - * @Class - * @Param {object} opts - * @Param {object} opts.buttons nested arrays of grouped buttons config objects - * @Param {object} opts.container container div to append modeBar - * @Param {object} opts.graphInfo primary plot object containing data and layout - */ -function ModeBar(opts) { - this.container = opts.container; - this.element = document.createElement('div'); - - this.update(opts.graphInfo, opts.buttons); - - this.container.appendChild(this.element); -} - -var proto = ModeBar.prototype; - -/** - * Update modeBar (buttons and logo) - * - * @param {object} graphInfo primary plot object containing data and layout - * @param {array of arrays} buttons nested arrays of grouped buttons to initialize - * - */ -proto.update = function(graphInfo, buttons) { - this.graphInfo = graphInfo; - - var context = this.graphInfo._context; - var fullLayout = this.graphInfo._fullLayout; - var modeBarId = 'modebar-' + fullLayout._uid; - - this.element.setAttribute('id', modeBarId); - this._uid = modeBarId; - - this.element.className = 'modebar'; - if(context.displayModeBar === 'hover') this.element.className += ' modebar--hover ease-bg'; - - if(fullLayout.modebar.orientation === 'v') { - this.element.className += ' vertical'; - buttons = buttons.reverse(); - } - - var style = fullLayout.modebar; - var bgSelector = context.displayModeBar === 'hover' ? '.js-plotly-plot .plotly:hover ' : ''; - - Lib.deleteRelatedStyleRule(modeBarId); - Lib.addRelatedStyleRule(modeBarId, bgSelector + '#' + modeBarId + ' .modebar-group', 'background-color: ' + style.bgcolor); - Lib.addRelatedStyleRule(modeBarId, '#' + modeBarId + ' .modebar-btn .icon path', 'fill: ' + style.color); - Lib.addRelatedStyleRule(modeBarId, '#' + modeBarId + ' .modebar-btn:hover .icon path', 'fill: ' + style.activecolor); - Lib.addRelatedStyleRule(modeBarId, '#' + modeBarId + ' .modebar-btn.active .icon path', 'fill: ' + style.activecolor); - - // if buttons or logo have changed, redraw modebar interior - var needsNewButtons = !this.hasButtons(buttons); - var needsNewLogo = (this.hasLogo !== context.displaylogo); - var needsNewLocale = (this.locale !== context.locale); - - this.locale = context.locale; - - if(needsNewButtons || needsNewLogo || needsNewLocale) { - this.removeAllButtons(); - - this.updateButtons(buttons); - - if(context.watermark || context.displaylogo) { - var logoGroup = this.getLogo(); - if(context.watermark) { - logoGroup.className = logoGroup.className + ' watermark'; - } - - if(fullLayout.modebar.orientation === 'v') { - this.element.insertBefore(logoGroup, this.element.childNodes[0]); - } else { - this.element.appendChild(logoGroup); - } - - this.hasLogo = true; - } - } - - this.updateActiveButton(); -}; - -proto.updateButtons = function(buttons) { - var _this = this; - - this.buttons = buttons; - this.buttonElements = []; - this.buttonsNames = []; - - this.buttons.forEach(function(buttonGroup) { - var group = _this.createGroup(); - - buttonGroup.forEach(function(buttonConfig) { - var buttonName = buttonConfig.name; - if(!buttonName) { - throw new Error('must provide button \'name\' in button config'); - } - if(_this.buttonsNames.indexOf(buttonName) !== -1) { - throw new Error('button name \'' + buttonName + '\' is taken'); - } - _this.buttonsNames.push(buttonName); - - var button = _this.createButton(buttonConfig); - _this.buttonElements.push(button); - group.appendChild(button); - }); - - _this.element.appendChild(group); - }); -}; - -/** - * Empty div for containing a group of buttons - * @Return {HTMLelement} - */ -proto.createGroup = function() { - var group = document.createElement('div'); - group.className = 'modebar-group'; - return group; -}; - -/** - * Create a new button div and set constant and configurable attributes - * @Param {object} config (see ./buttons.js for more info) - * @Return {HTMLelement} - */ -proto.createButton = function(config) { - var _this = this; - var button = document.createElement('a'); - - button.setAttribute('rel', 'tooltip'); - button.className = 'modebar-btn'; - - var title = config.title; - if(title === undefined) title = config.name; - // for localization: allow title to be a callable that takes gd as arg - else if(typeof title === 'function') title = title(this.graphInfo); - - if(title || title === 0) button.setAttribute('data-title', title); - - if(config.attr !== undefined) button.setAttribute('data-attr', config.attr); - - var val = config.val; - if(val !== undefined) { - if(typeof val === 'function') val = val(this.graphInfo); - button.setAttribute('data-val', val); - } - - var click = config.click; - if(typeof click !== 'function') { - throw new Error('must provide button \'click\' function in button config'); - } else { - button.addEventListener('click', function(ev) { - config.click(_this.graphInfo, ev); - - // only needed for 'hoverClosestGeo' which does not call relayout - _this.updateActiveButton(ev.currentTarget); - }); - } - - button.setAttribute('data-toggle', config.toggle || false); - if(config.toggle) d3.select(button).classed('active', true); - - var icon = config.icon; - if(typeof icon === 'function') { - button.appendChild(icon()); - } else { - button.appendChild(this.createIcon(icon || Icons.question)); - } - button.setAttribute('data-gravity', config.gravity || 'n'); - - return button; -}; - -/** - * Add an icon to a button - * @Param {object} thisIcon - * @Param {number} thisIcon.width - * @Param {string} thisIcon.path - * @Param {string} thisIcon.color - * @Return {HTMLelement} - */ -proto.createIcon = function(thisIcon) { - var iconHeight = isNumeric(thisIcon.height) ? - Number(thisIcon.height) : - thisIcon.ascent - thisIcon.descent; - var svgNS = 'http://www.w3.org/2000/svg'; - var icon; - - if(thisIcon.path) { - icon = document.createElementNS(svgNS, 'svg'); - icon.setAttribute('viewBox', [0, 0, thisIcon.width, iconHeight].join(' ')); - icon.setAttribute('class', 'icon'); - - var path = document.createElementNS(svgNS, 'path'); - path.setAttribute('d', thisIcon.path); - - if(thisIcon.transform) { - path.setAttribute('transform', thisIcon.transform); - } else if(thisIcon.ascent !== undefined) { - // Legacy icon transform calculation - path.setAttribute('transform', 'matrix(1 0 0 -1 0 ' + thisIcon.ascent + ')'); - } - - icon.appendChild(path); - } - - if(thisIcon.svg) { - var svgDoc = Parser.parseFromString(thisIcon.svg, 'application/xml'); - icon = svgDoc.childNodes[0]; - } - - icon.setAttribute('height', '1em'); - icon.setAttribute('width', '1em'); - - return icon; -}; - -/** - * Updates active button with attribute specified in layout - * @Param {object} graphInfo plot object containing data and layout - * @Return {HTMLelement} - */ -proto.updateActiveButton = function(buttonClicked) { - var fullLayout = this.graphInfo._fullLayout; - var dataAttrClicked = (buttonClicked !== undefined) ? - buttonClicked.getAttribute('data-attr') : - null; - - this.buttonElements.forEach(function(button) { - var thisval = button.getAttribute('data-val') || true; - var dataAttr = button.getAttribute('data-attr'); - var isToggleButton = (button.getAttribute('data-toggle') === 'true'); - var button3 = d3.select(button); - - // Use 'data-toggle' and 'buttonClicked' to toggle buttons - // that have no one-to-one equivalent in fullLayout - if(isToggleButton) { - if(dataAttr === dataAttrClicked) { - button3.classed('active', !button3.classed('active')); - } - } else { - var val = (dataAttr === null) ? - dataAttr : - Lib.nestedProperty(fullLayout, dataAttr).get(); - - button3.classed('active', val === thisval); - } - }); -}; - -/** - * Check if modeBar is configured as button configuration argument - * - * @Param {object} buttons 2d array of grouped button config objects - * @Return {boolean} - */ -proto.hasButtons = function(buttons) { - var currentButtons = this.buttons; - - if(!currentButtons) return false; - - if(buttons.length !== currentButtons.length) return false; - - for(var i = 0; i < buttons.length; ++i) { - if(buttons[i].length !== currentButtons[i].length) return false; - for(var j = 0; j < buttons[i].length; j++) { - if(buttons[i][j].name !== currentButtons[i][j].name) return false; - } - } - - return true; -}; - -/** - * @return {HTMLDivElement} The logo image wrapped in a group - */ -proto.getLogo = function() { - var group = this.createGroup(); - var a = document.createElement('a'); - - a.href = 'https://plot.ly/'; - a.target = '_blank'; - a.setAttribute('data-title', Lib._(this.graphInfo, 'Produced with Plotly')); - a.className = 'modebar-btn plotlyjsicon modebar-btn--logo'; - - a.appendChild(this.createIcon(Icons.newplotlylogo)); - - group.appendChild(a); - return group; -}; - -proto.removeAllButtons = function() { - while(this.element.firstChild) { - this.element.removeChild(this.element.firstChild); - } - - this.hasLogo = false; -}; - -proto.destroy = function() { - Lib.removeElement(this.container.querySelector('.modebar')); - Lib.deleteRelatedStyleRule(this._uid); -}; - -function createModeBar(gd, buttons) { - var fullLayout = gd._fullLayout; - - var modeBar = new ModeBar({ - graphInfo: gd, - container: fullLayout._modebardiv.node(), - buttons: buttons - }); - - if(fullLayout._privateplot) { - d3.select(modeBar.element).append('span') - .classed('badge-private float--left', true) - .text('PRIVATE'); - } - - return modeBar; -} - -module.exports = createModeBar; - -},{"../../fonts/ploticon":699,"../../lib":719,"d3":163,"fast-isnumeric":225}],655:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('../../plots/font_attributes'); -var colorAttrs = _dereq_('../color/attributes'); -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - -var buttonAttrs = templatedArray('button', { - visible: { - valType: 'boolean', - - dflt: true, - editType: 'plot', - - }, - step: { - valType: 'enumerated', - - values: ['month', 'year', 'day', 'hour', 'minute', 'second', 'all'], - dflt: 'month', - editType: 'plot', - - }, - stepmode: { - valType: 'enumerated', - - values: ['backward', 'todate'], - dflt: 'backward', - editType: 'plot', - - }, - count: { - valType: 'number', - - min: 0, - dflt: 1, - editType: 'plot', - - }, - label: { - valType: 'string', - - editType: 'plot', - - }, - editType: 'plot', - -}); - -module.exports = { - visible: { - valType: 'boolean', - - editType: 'plot', - - }, - - buttons: buttonAttrs, - - x: { - valType: 'number', - min: -2, - max: 3, - - editType: 'plot', - - }, - xanchor: { - valType: 'enumerated', - values: ['auto', 'left', 'center', 'right'], - dflt: 'left', - - editType: 'plot', - - }, - y: { - valType: 'number', - min: -2, - max: 3, - - editType: 'plot', - - }, - yanchor: { - valType: 'enumerated', - values: ['auto', 'top', 'middle', 'bottom'], - dflt: 'bottom', - - editType: 'plot', - - }, - - font: fontAttrs({ - editType: 'plot', - - }), - - bgcolor: { - valType: 'color', - dflt: colorAttrs.lightLine, - - editType: 'plot', - - }, - activecolor: { - valType: 'color', - - editType: 'plot', - - }, - bordercolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'plot', - - }, - borderwidth: { - valType: 'number', - min: 0, - dflt: 0, - - editType: 'plot', - - }, - editType: 'plot' -}; - -},{"../../plot_api/plot_template":757,"../../plots/font_attributes":793,"../color/attributes":592}],656:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -module.exports = { - - // 'y' position pad above counter axis domain - yPad: 0.02, - - // minimum button width (regardless of text size) - minButtonWidth: 30, - - // buttons rect radii - rx: 3, - ry: 3, - - // light fraction used to compute the 'activecolor' default - lightAmount: 25, - darkAmount: 10 -}; - -},{}],657:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../color'); -var Template = _dereq_('../../plot_api/plot_template'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); - -var attributes = _dereq_('./attributes'); -var constants = _dereq_('./constants'); - - -module.exports = function handleDefaults(containerIn, containerOut, layout, counterAxes, calendar) { - var selectorIn = containerIn.rangeselector || {}; - var selectorOut = Template.newContainer(containerOut, 'rangeselector'); - - function coerce(attr, dflt) { - return Lib.coerce(selectorIn, selectorOut, attributes, attr, dflt); - } - - var buttons = handleArrayContainerDefaults(selectorIn, selectorOut, { - name: 'buttons', - handleItemDefaults: buttonDefaults, - calendar: calendar - }); - - var visible = coerce('visible', buttons.length > 0); - if(visible) { - var posDflt = getPosDflt(containerOut, layout, counterAxes); - coerce('x', posDflt[0]); - coerce('y', posDflt[1]); - Lib.noneOrAll(containerIn, containerOut, ['x', 'y']); - - coerce('xanchor'); - coerce('yanchor'); - - Lib.coerceFont(coerce, 'font', layout.font); - - var bgColor = coerce('bgcolor'); - coerce('activecolor', Color.contrast(bgColor, constants.lightAmount, constants.darkAmount)); - coerce('bordercolor'); - coerce('borderwidth'); - } -}; - -function buttonDefaults(buttonIn, buttonOut, selectorOut, opts) { - var calendar = opts.calendar; - - function coerce(attr, dflt) { - return Lib.coerce(buttonIn, buttonOut, attributes.buttons, attr, dflt); - } - - var visible = coerce('visible'); - - if(visible) { - var step = coerce('step'); - if(step !== 'all') { - if(calendar && calendar !== 'gregorian' && (step === 'month' || step === 'year')) { - buttonOut.stepmode = 'backward'; - } else { - coerce('stepmode'); - } - - coerce('count'); - } - - coerce('label'); - } -} - -function getPosDflt(containerOut, layout, counterAxes) { - var anchoredList = counterAxes.filter(function(ax) { - return layout[ax].anchor === containerOut._id; - }); - - var posY = 0; - for(var i = 0; i < anchoredList.length; i++) { - var domain = layout[anchoredList[i]].domain; - if(domain) posY = Math.max(domain[1], posY); - } - - return [containerOut.domain[0], posY + constants.yPad]; -} - -},{"../../lib":719,"../../plot_api/plot_template":757,"../../plots/array_container_defaults":763,"../color":593,"./attributes":655,"./constants":656}],658:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Registry = _dereq_('../../registry'); -var Plots = _dereq_('../../plots/plots'); -var Color = _dereq_('../color'); -var Drawing = _dereq_('../drawing'); -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var axisIds = _dereq_('../../plots/cartesian/axis_ids'); - -var alignmentConstants = _dereq_('../../constants/alignment'); -var LINE_SPACING = alignmentConstants.LINE_SPACING; -var FROM_TL = alignmentConstants.FROM_TL; -var FROM_BR = alignmentConstants.FROM_BR; - -var constants = _dereq_('./constants'); -var getUpdateObject = _dereq_('./get_update_object'); - -module.exports = function draw(gd) { - var fullLayout = gd._fullLayout; - - var selectors = fullLayout._infolayer.selectAll('.rangeselector') - .data(makeSelectorData(gd), selectorKeyFunc); - - selectors.enter().append('g') - .classed('rangeselector', true); - - selectors.exit().remove(); - - selectors.style({ - cursor: 'pointer', - 'pointer-events': 'all' - }); - - selectors.each(function(d) { - var selector = d3.select(this); - var axisLayout = d; - var selectorLayout = axisLayout.rangeselector; - - var buttons = selector.selectAll('g.button') - .data(Lib.filterVisible(selectorLayout.buttons)); - - buttons.enter().append('g') - .classed('button', true); - - buttons.exit().remove(); - - buttons.each(function(d) { - var button = d3.select(this); - var update = getUpdateObject(axisLayout, d); - - d._isActive = isActive(axisLayout, d, update); - - button.call(drawButtonRect, selectorLayout, d); - button.call(drawButtonText, selectorLayout, d, gd); - - button.on('click', function() { - if(gd._dragged) return; - - Registry.call('_guiRelayout', gd, update); - }); - - button.on('mouseover', function() { - d._isHovered = true; - button.call(drawButtonRect, selectorLayout, d); - }); - - button.on('mouseout', function() { - d._isHovered = false; - button.call(drawButtonRect, selectorLayout, d); - }); - }); - - reposition(gd, buttons, selectorLayout, axisLayout._name, selector); - }); -}; - -function makeSelectorData(gd) { - var axes = axisIds.list(gd, 'x', true); - var data = []; - - for(var i = 0; i < axes.length; i++) { - var axis = axes[i]; - - if(axis.rangeselector && axis.rangeselector.visible) { - data.push(axis); - } - } - - return data; -} - -function selectorKeyFunc(d) { - return d._id; -} - -function isActive(axisLayout, opts, update) { - if(opts.step === 'all') { - return axisLayout.autorange === true; - } else { - var keys = Object.keys(update); - - return ( - axisLayout.range[0] === update[keys[0]] && - axisLayout.range[1] === update[keys[1]] - ); - } -} - -function drawButtonRect(button, selectorLayout, d) { - var rect = Lib.ensureSingle(button, 'rect', 'selector-rect', function(s) { - s.attr('shape-rendering', 'crispEdges'); - }); - - rect.attr({ - 'rx': constants.rx, - 'ry': constants.ry - }); - - rect.call(Color.stroke, selectorLayout.bordercolor) - .call(Color.fill, getFillColor(selectorLayout, d)) - .style('stroke-width', selectorLayout.borderwidth + 'px'); -} - -function getFillColor(selectorLayout, d) { - return (d._isActive || d._isHovered) ? - selectorLayout.activecolor : - selectorLayout.bgcolor; -} - -function drawButtonText(button, selectorLayout, d, gd) { - function textLayout(s) { - svgTextUtils.convertToTspans(s, gd); - } - - var text = Lib.ensureSingle(button, 'text', 'selector-text', function(s) { - s.classed('user-select-none', true) - .attr('text-anchor', 'middle'); - }); - - text.call(Drawing.font, selectorLayout.font) - .text(getLabel(d, gd._fullLayout._meta)) - .call(textLayout); -} - -function getLabel(opts, _meta) { - if(opts.label) { - return _meta ? - Lib.templateString(opts.label, _meta) : - opts.label; - } - - if(opts.step === 'all') return 'all'; - - return opts.count + opts.step.charAt(0); -} - -function reposition(gd, buttons, opts, axName, selector) { - var width = 0; - var height = 0; - - var borderWidth = opts.borderwidth; - - buttons.each(function() { - var button = d3.select(this); - var text = button.select('.selector-text'); - - var tHeight = opts.font.size * LINE_SPACING; - var hEff = Math.max(tHeight * svgTextUtils.lineCount(text), 16) + 3; - - height = Math.max(height, hEff); - }); - - buttons.each(function() { - var button = d3.select(this); - var rect = button.select('.selector-rect'); - var text = button.select('.selector-text'); - - var tWidth = text.node() && Drawing.bBox(text.node()).width; - var tHeight = opts.font.size * LINE_SPACING; - var tLines = svgTextUtils.lineCount(text); - - var wEff = Math.max(tWidth + 10, constants.minButtonWidth); - - // TODO add MathJax support - - // TODO add buttongap attribute - - button.attr('transform', 'translate(' + - (borderWidth + width) + ',' + borderWidth + - ')'); - - rect.attr({ - x: 0, - y: 0, - width: wEff, - height: height - }); - - svgTextUtils.positionText(text, wEff / 2, - height / 2 - ((tLines - 1) * tHeight / 2) + 3); - - width += wEff + 5; - }); - - var graphSize = gd._fullLayout._size; - var lx = graphSize.l + graphSize.w * opts.x; - var ly = graphSize.t + graphSize.h * (1 - opts.y); - - var xanchor = 'left'; - if(Lib.isRightAnchor(opts)) { - lx -= width; - xanchor = 'right'; - } - if(Lib.isCenterAnchor(opts)) { - lx -= width / 2; - xanchor = 'center'; - } - - var yanchor = 'top'; - if(Lib.isBottomAnchor(opts)) { - ly -= height; - yanchor = 'bottom'; - } - if(Lib.isMiddleAnchor(opts)) { - ly -= height / 2; - yanchor = 'middle'; - } - - width = Math.ceil(width); - height = Math.ceil(height); - lx = Math.round(lx); - ly = Math.round(ly); - - Plots.autoMargin(gd, axName + '-range-selector', { - x: opts.x, - y: opts.y, - l: width * FROM_TL[xanchor], - r: width * FROM_BR[xanchor], - b: height * FROM_BR[yanchor], - t: height * FROM_TL[yanchor] - }); - - selector.attr('transform', 'translate(' + lx + ',' + ly + ')'); -} - -},{"../../constants/alignment":688,"../../lib":719,"../../lib/svg_text_utils":743,"../../plots/cartesian/axis_ids":770,"../../plots/plots":828,"../../registry":847,"../color":593,"../drawing":614,"./constants":656,"./get_update_object":659,"d3":163}],659:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -module.exports = function getUpdateObject(axisLayout, buttonLayout) { - var axName = axisLayout._name; - var update = {}; - - if(buttonLayout.step === 'all') { - update[axName + '.autorange'] = true; - } else { - var xrange = getXRange(axisLayout, buttonLayout); - - update[axName + '.range[0]'] = xrange[0]; - update[axName + '.range[1]'] = xrange[1]; - } - - return update; -}; - -function getXRange(axisLayout, buttonLayout) { - var currentRange = axisLayout.range; - var base = new Date(axisLayout.r2l(currentRange[1])); - var step = buttonLayout.step; - var count = buttonLayout.count; - var range0; - - switch(buttonLayout.stepmode) { - case 'backward': - range0 = axisLayout.l2r(+d3.time[step].utc.offset(base, -count)); - break; - - case 'todate': - var base2 = d3.time[step].utc.offset(base, -count); - - range0 = axisLayout.l2r(+d3.time[step].utc.ceil(base2)); - break; - } - - var range1 = currentRange[1]; - - return [range0, range1]; -} - -},{"d3":163}],660:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'component', - name: 'rangeselector', - - schema: { - subplots: { - xaxis: {rangeselector: _dereq_('./attributes')} - } - }, - - layoutAttributes: _dereq_('./attributes'), - handleDefaults: _dereq_('./defaults'), - - draw: _dereq_('./draw') -}; - -},{"./attributes":655,"./defaults":657,"./draw":658}],661:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorAttributes = _dereq_('../color/attributes'); - -module.exports = { - bgcolor: { - valType: 'color', - dflt: colorAttributes.background, - - editType: 'plot', - - }, - bordercolor: { - valType: 'color', - dflt: colorAttributes.defaultLine, - - editType: 'plot', - - }, - borderwidth: { - valType: 'integer', - dflt: 0, - min: 0, - - editType: 'plot', - - }, - autorange: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - impliedEdits: {'range[0]': undefined, 'range[1]': undefined}, - - }, - range: { - valType: 'info_array', - - items: [ - {valType: 'any', editType: 'calc', impliedEdits: {'^autorange': false}}, - {valType: 'any', editType: 'calc', impliedEdits: {'^autorange': false}} - ], - editType: 'calc', - impliedEdits: {'autorange': false}, - - }, - thickness: { - valType: 'number', - dflt: 0.15, - min: 0, - max: 1, - - editType: 'plot', - - }, - visible: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - }, - editType: 'calc' -}; - -},{"../color/attributes":592}],662:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var listAxes = _dereq_('../../plots/cartesian/axis_ids').list; -var getAutoRange = _dereq_('../../plots/cartesian/autorange').getAutoRange; -var constants = _dereq_('./constants'); - -module.exports = function calcAutorange(gd) { - var axes = listAxes(gd, 'x', true); - - // Compute new slider range using axis autorange if necessary. - // - // Copy back range to input range slider container to skip - // this step in subsequent draw calls. - - for(var i = 0; i < axes.length; i++) { - var ax = axes[i]; - var opts = ax[constants.name]; - - if(opts && opts.visible && opts.autorange) { - opts._input.autorange = true; - opts._input.range = opts.range = getAutoRange(gd, ax); - } - } -}; - -},{"../../plots/cartesian/autorange":766,"../../plots/cartesian/axis_ids":770,"./constants":663}],663:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - - // attribute container name - name: 'rangeslider', - - // class names - - containerClassName: 'rangeslider-container', - bgClassName: 'rangeslider-bg', - rangePlotClassName: 'rangeslider-rangeplot', - - maskMinClassName: 'rangeslider-mask-min', - maskMaxClassName: 'rangeslider-mask-max', - slideBoxClassName: 'rangeslider-slidebox', - - grabberMinClassName: 'rangeslider-grabber-min', - grabAreaMinClassName: 'rangeslider-grabarea-min', - handleMinClassName: 'rangeslider-handle-min', - - grabberMaxClassName: 'rangeslider-grabber-max', - grabAreaMaxClassName: 'rangeslider-grabarea-max', - handleMaxClassName: 'rangeslider-handle-max', - - maskMinOppAxisClassName: 'rangeslider-mask-min-opp-axis', - maskMaxOppAxisClassName: 'rangeslider-mask-max-opp-axis', - - // style constants - - maskColor: 'rgba(0,0,0,0.4)', - maskOppAxisColor: 'rgba(0,0,0,0.2)', - - slideBoxFill: 'transparent', - slideBoxCursor: 'ew-resize', - - grabAreaFill: 'transparent', - grabAreaCursor: 'col-resize', - grabAreaWidth: 10, - - handleWidth: 4, - handleRadius: 1, - handleStrokeWidth: 1, - - extraPad: 15 -}; - -},{}],664:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Template = _dereq_('../../plot_api/plot_template'); -var axisIds = _dereq_('../../plots/cartesian/axis_ids'); - -var attributes = _dereq_('./attributes'); -var oppAxisAttrs = _dereq_('./oppaxis_attributes'); - -module.exports = function handleDefaults(layoutIn, layoutOut, axName) { - var axIn = layoutIn[axName]; - var axOut = layoutOut[axName]; - - if(!(axIn.rangeslider || layoutOut._requestRangeslider[axOut._id])) return; - - // not super proud of this (maybe store _ in axis object instead - if(!Lib.isPlainObject(axIn.rangeslider)) { - axIn.rangeslider = {}; - } - - var containerIn = axIn.rangeslider; - var containerOut = Template.newContainer(axOut, 'rangeslider'); - - function coerce(attr, dflt) { - return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); - } - - var rangeContainerIn, rangeContainerOut; - function coerceRange(attr, dflt) { - return Lib.coerce(rangeContainerIn, rangeContainerOut, oppAxisAttrs, attr, dflt); - } - - var visible = coerce('visible'); - if(!visible) return; - - coerce('bgcolor', layoutOut.plot_bgcolor); - coerce('bordercolor'); - coerce('borderwidth'); - coerce('thickness'); - - coerce('autorange', !axOut.isValidRange(containerIn.range)); - coerce('range'); - - var subplots = layoutOut._subplots; - if(subplots) { - var yIds = subplots.cartesian - .filter(function(subplotId) { - return subplotId.substr(0, subplotId.indexOf('y')) === axisIds.name2id(axName); - }) - .map(function(subplotId) { - return subplotId.substr(subplotId.indexOf('y'), subplotId.length); - }); - var yNames = Lib.simpleMap(yIds, axisIds.id2name); - for(var i = 0; i < yNames.length; i++) { - var yName = yNames[i]; - - rangeContainerIn = containerIn[yName] || {}; - rangeContainerOut = Template.newContainer(containerOut, yName, 'yaxis'); - - var yAxOut = layoutOut[yName]; - - var rangemodeDflt; - if(rangeContainerIn.range && yAxOut.isValidRange(rangeContainerIn.range)) { - rangemodeDflt = 'fixed'; - } - - var rangeMode = coerceRange('rangemode', rangemodeDflt); - if(rangeMode !== 'match') { - coerceRange('range', yAxOut.range.slice()); - } - } - } - - // to map back range slider (auto) range - containerOut._input = containerIn; -}; - -},{"../../lib":719,"../../plot_api/plot_template":757,"../../plots/cartesian/axis_ids":770,"./attributes":661,"./oppaxis_attributes":668}],665:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Registry = _dereq_('../../registry'); -var Plots = _dereq_('../../plots/plots'); - -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../drawing'); -var Color = _dereq_('../color'); -var Titles = _dereq_('../titles'); - -var Cartesian = _dereq_('../../plots/cartesian'); -var axisIDs = _dereq_('../../plots/cartesian/axis_ids'); - -var dragElement = _dereq_('../dragelement'); -var setCursor = _dereq_('../../lib/setcursor'); - -var constants = _dereq_('./constants'); - -module.exports = function(gd) { - var fullLayout = gd._fullLayout; - var rangeSliderData = fullLayout._rangeSliderData; - for(var i = 0; i < rangeSliderData.length; i++) { - var opts = rangeSliderData[i][constants.name]; - // fullLayout._uid may not exist when we call makeData - opts._clipId = opts._id + '-' + fullLayout._uid; - } - - /* - * - * - * < .... range plot /> - * - * - * - * - * - * - * - * - * - * - * ... - */ - - function keyFunction(axisOpts) { - return axisOpts._name; - } - - var rangeSliders = fullLayout._infolayer - .selectAll('g.' + constants.containerClassName) - .data(rangeSliderData, keyFunction); - - // remove exiting sliders and their corresponding clip paths - rangeSliders.exit().each(function(axisOpts) { - var opts = axisOpts[constants.name]; - fullLayout._topdefs.select('#' + opts._clipId).remove(); - }).remove(); - - // return early if no range slider is visible - if(rangeSliderData.length === 0) return; - - rangeSliders.enter().append('g') - .classed(constants.containerClassName, true) - .attr('pointer-events', 'all'); - - // for all present range sliders - rangeSliders.each(function(axisOpts) { - var rangeSlider = d3.select(this); - var opts = axisOpts[constants.name]; - var oppAxisOpts = fullLayout[axisIDs.id2name(axisOpts.anchor)]; - var oppAxisRangeOpts = opts[axisIDs.id2name(axisOpts.anchor)]; - - // update range - // Expand slider range to the axis range - if(opts.range) { - var rng = Lib.simpleMap(opts.range, axisOpts.r2l); - var axRng = Lib.simpleMap(axisOpts.range, axisOpts.r2l); - var newRng; - - if(axRng[0] < axRng[1]) { - newRng = [ - Math.min(rng[0], axRng[0]), - Math.max(rng[1], axRng[1]) - ]; - } else { - newRng = [ - Math.max(rng[0], axRng[0]), - Math.min(rng[1], axRng[1]) - ]; - } - - opts.range = opts._input.range = Lib.simpleMap(newRng, axisOpts.l2r); - } - - axisOpts.cleanRange('rangeslider.range'); - - // update range slider dimensions - - var margin = fullLayout.margin; - var graphSize = fullLayout._size; - var domain = axisOpts.domain; - var tickHeight = opts._tickHeight; - - var oppBottom = opts._oppBottom; - - opts._width = graphSize.w * (domain[1] - domain[0]); - - var x = Math.round(margin.l + (graphSize.w * domain[0])); - - var y = Math.round( - graphSize.t + graphSize.h * (1 - oppBottom) + - tickHeight + - opts._offsetShift + constants.extraPad - ); - - rangeSlider.attr('transform', 'translate(' + x + ',' + y + ')'); - - // update data <--> pixel coordinate conversion methods - - var range0 = axisOpts.r2l(opts.range[0]); - var range1 = axisOpts.r2l(opts.range[1]); - var dist = range1 - range0; - - opts.p2d = function(v) { - return (v / opts._width) * dist + range0; - }; - - opts.d2p = function(v) { - return (v - range0) / dist * opts._width; - }; - - opts._rl = [range0, range1]; - - if(oppAxisRangeOpts.rangemode !== 'match') { - var range0OppAxis = oppAxisOpts.r2l(oppAxisRangeOpts.range[0]); - var range1OppAxis = oppAxisOpts.r2l(oppAxisRangeOpts.range[1]); - var distOppAxis = range1OppAxis - range0OppAxis; - - opts.d2pOppAxis = function(v) { - return (v - range0OppAxis) / distOppAxis * opts._height; - }; - } - - // update inner nodes - - rangeSlider - .call(drawBg, gd, axisOpts, opts) - .call(addClipPath, gd, axisOpts, opts) - .call(drawRangePlot, gd, axisOpts, opts) - .call(drawMasks, gd, axisOpts, opts, oppAxisRangeOpts) - .call(drawSlideBox, gd, axisOpts, opts) - .call(drawGrabbers, gd, axisOpts, opts); - - // setup drag element - setupDragElement(rangeSlider, gd, axisOpts, opts); - - // update current range - setPixelRange(rangeSlider, gd, axisOpts, opts, oppAxisOpts, oppAxisRangeOpts); - - // title goes next to range slider instead of tick labels, so - // just take it over and draw it from here - if(axisOpts.side === 'bottom') { - Titles.draw(gd, axisOpts._id + 'title', { - propContainer: axisOpts, - propName: axisOpts._name + '.title', - placeholder: fullLayout._dfltTitle.x, - attributes: { - x: axisOpts._offset + axisOpts._length / 2, - y: y + opts._height + opts._offsetShift + 10 + 1.5 * axisOpts.title.font.size, - 'text-anchor': 'middle' - } - }); - } - }); -}; - -function setupDragElement(rangeSlider, gd, axisOpts, opts) { - var slideBox = rangeSlider.select('rect.' + constants.slideBoxClassName).node(); - var grabAreaMin = rangeSlider.select('rect.' + constants.grabAreaMinClassName).node(); - var grabAreaMax = rangeSlider.select('rect.' + constants.grabAreaMaxClassName).node(); - - rangeSlider.on('mousedown', function() { - var event = d3.event; - var target = event.target; - var startX = event.clientX; - var offsetX = startX - rangeSlider.node().getBoundingClientRect().left; - var minVal = opts.d2p(axisOpts._rl[0]); - var maxVal = opts.d2p(axisOpts._rl[1]); - - var dragCover = dragElement.coverSlip(); - - dragCover.addEventListener('mousemove', mouseMove); - dragCover.addEventListener('mouseup', mouseUp); - - function mouseMove(e) { - var delta = +e.clientX - startX; - var pixelMin, pixelMax, cursor; - - switch(target) { - case slideBox: - cursor = 'ew-resize'; - pixelMin = minVal + delta; - pixelMax = maxVal + delta; - break; - - case grabAreaMin: - cursor = 'col-resize'; - pixelMin = minVal + delta; - pixelMax = maxVal; - break; - - case grabAreaMax: - cursor = 'col-resize'; - pixelMin = minVal; - pixelMax = maxVal + delta; - break; - - default: - cursor = 'ew-resize'; - pixelMin = offsetX; - pixelMax = offsetX + delta; - break; - } - - if(pixelMax < pixelMin) { - var tmp = pixelMax; - pixelMax = pixelMin; - pixelMin = tmp; - } - - opts._pixelMin = pixelMin; - opts._pixelMax = pixelMax; - - setCursor(d3.select(dragCover), cursor); - setDataRange(rangeSlider, gd, axisOpts, opts); - } - - function mouseUp() { - dragCover.removeEventListener('mousemove', mouseMove); - dragCover.removeEventListener('mouseup', mouseUp); - Lib.removeElement(dragCover); - } - }); -} - -function setDataRange(rangeSlider, gd, axisOpts, opts) { - function clamp(v) { - return axisOpts.l2r(Lib.constrain(v, opts._rl[0], opts._rl[1])); - } - - var dataMin = clamp(opts.p2d(opts._pixelMin)); - var dataMax = clamp(opts.p2d(opts._pixelMax)); - - window.requestAnimationFrame(function() { - Registry.call('_guiRelayout', gd, axisOpts._name + '.range', [dataMin, dataMax]); - }); -} - -function setPixelRange(rangeSlider, gd, axisOpts, opts, oppAxisOpts, oppAxisRangeOpts) { - var hw2 = constants.handleWidth / 2; - - function clamp(v) { - return Lib.constrain(v, 0, opts._width); - } - - function clampOppAxis(v) { - return Lib.constrain(v, 0, opts._height); - } - - function clampHandle(v) { - return Lib.constrain(v, -hw2, opts._width + hw2); - } - - var pixelMin = clamp(opts.d2p(axisOpts._rl[0])); - var pixelMax = clamp(opts.d2p(axisOpts._rl[1])); - - rangeSlider.select('rect.' + constants.slideBoxClassName) - .attr('x', pixelMin) - .attr('width', pixelMax - pixelMin); - - rangeSlider.select('rect.' + constants.maskMinClassName) - .attr('width', pixelMin); - - rangeSlider.select('rect.' + constants.maskMaxClassName) - .attr('x', pixelMax) - .attr('width', opts._width - pixelMax); - - if(oppAxisRangeOpts.rangemode !== 'match') { - var pixelMinOppAxis = opts._height - clampOppAxis(opts.d2pOppAxis(oppAxisOpts._rl[1])); - var pixelMaxOppAxis = opts._height - clampOppAxis(opts.d2pOppAxis(oppAxisOpts._rl[0])); - - rangeSlider.select('rect.' + constants.maskMinOppAxisClassName) - .attr('x', pixelMin) - .attr('height', pixelMinOppAxis) - .attr('width', pixelMax - pixelMin); - - rangeSlider.select('rect.' + constants.maskMaxOppAxisClassName) - .attr('x', pixelMin) - .attr('y', pixelMaxOppAxis) - .attr('height', opts._height - pixelMaxOppAxis) - .attr('width', pixelMax - pixelMin); - - rangeSlider.select('rect.' + constants.slideBoxClassName) - .attr('y', pixelMinOppAxis) - .attr('height', pixelMaxOppAxis - pixelMinOppAxis); - } - - // add offset for crispier corners - // https://github.com/plotly/plotly.js/pull/1409 - var offset = 0.5; - - var xMin = Math.round(clampHandle(pixelMin - hw2)) - offset; - var xMax = Math.round(clampHandle(pixelMax - hw2)) + offset; - - rangeSlider.select('g.' + constants.grabberMinClassName) - .attr('transform', 'translate(' + xMin + ',' + offset + ')'); - - rangeSlider.select('g.' + constants.grabberMaxClassName) - .attr('transform', 'translate(' + xMax + ',' + offset + ')'); -} - -function drawBg(rangeSlider, gd, axisOpts, opts) { - var bg = Lib.ensureSingle(rangeSlider, 'rect', constants.bgClassName, function(s) { - s.attr({ - x: 0, - y: 0, - 'shape-rendering': 'crispEdges' - }); - }); - - var borderCorrect = (opts.borderwidth % 2) === 0 ? - opts.borderwidth : - opts.borderwidth - 1; - - var offsetShift = -opts._offsetShift; - var lw = Drawing.crispRound(gd, opts.borderwidth); - - bg.attr({ - width: opts._width + borderCorrect, - height: opts._height + borderCorrect, - transform: 'translate(' + offsetShift + ',' + offsetShift + ')', - fill: opts.bgcolor, - stroke: opts.bordercolor, - 'stroke-width': lw - }); -} - -function addClipPath(rangeSlider, gd, axisOpts, opts) { - var fullLayout = gd._fullLayout; - - var clipPath = Lib.ensureSingleById(fullLayout._topdefs, 'clipPath', opts._clipId, function(s) { - s.append('rect').attr({ x: 0, y: 0 }); - }); - - clipPath.select('rect').attr({ - width: opts._width, - height: opts._height - }); -} - -function drawRangePlot(rangeSlider, gd, axisOpts, opts) { - var calcData = gd.calcdata; - - var rangePlots = rangeSlider.selectAll('g.' + constants.rangePlotClassName) - .data(axisOpts._subplotsWith, Lib.identity); - - rangePlots.enter().append('g') - .attr('class', function(id) { return constants.rangePlotClassName + ' ' + id; }) - .call(Drawing.setClipUrl, opts._clipId, gd); - - rangePlots.order(); - - rangePlots.exit().remove(); - - var mainplotinfo; - - rangePlots.each(function(id, i) { - var plotgroup = d3.select(this); - var isMainPlot = (i === 0); - - var oppAxisOpts = axisIDs.getFromId(gd, id, 'y'); - var oppAxisName = oppAxisOpts._name; - var oppAxisRangeOpts = opts[oppAxisName]; - - var mockFigure = { - data: [], - layout: { - xaxis: { - type: axisOpts.type, - domain: [0, 1], - range: opts.range.slice(), - calendar: axisOpts.calendar - }, - width: opts._width, - height: opts._height, - margin: { t: 0, b: 0, l: 0, r: 0 } - }, - _context: gd._context - }; - - mockFigure.layout[oppAxisName] = { - type: oppAxisOpts.type, - domain: [0, 1], - range: oppAxisRangeOpts.rangemode !== 'match' ? oppAxisRangeOpts.range.slice() : oppAxisOpts.range.slice(), - calendar: oppAxisOpts.calendar - }; - - Plots.supplyDefaults(mockFigure); - - var xa = mockFigure._fullLayout.xaxis; - var ya = mockFigure._fullLayout[oppAxisName]; - - xa.clearCalc(); - xa.setScale(); - ya.clearCalc(); - ya.setScale(); - - var plotinfo = { - id: id, - plotgroup: plotgroup, - xaxis: xa, - yaxis: ya, - isRangePlot: true - }; - - if(isMainPlot) mainplotinfo = plotinfo; - else { - plotinfo.mainplot = 'xy'; - plotinfo.mainplotinfo = mainplotinfo; - } - - Cartesian.rangePlot(gd, plotinfo, filterRangePlotCalcData(calcData, id)); - }); -} - -function filterRangePlotCalcData(calcData, subplotId) { - var out = []; - - for(var i = 0; i < calcData.length; i++) { - var calcTrace = calcData[i]; - var trace = calcTrace[0].trace; - - if(trace.xaxis + trace.yaxis === subplotId) { - out.push(calcTrace); - } - } - - return out; -} - -function drawMasks(rangeSlider, gd, axisOpts, opts, oppAxisRangeOpts) { - var maskMin = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMinClassName, function(s) { - s.attr({ - x: 0, - y: 0, - 'shape-rendering': 'crispEdges' - }); - }); - - maskMin - .attr('height', opts._height) - .call(Color.fill, constants.maskColor); - - var maskMax = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMaxClassName, function(s) { - s.attr({ - y: 0, - 'shape-rendering': 'crispEdges' - }); - }); - - maskMax - .attr('height', opts._height) - .call(Color.fill, constants.maskColor); - - // masks used for oppAxis zoom - if(oppAxisRangeOpts.rangemode !== 'match') { - var maskMinOppAxis = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMinOppAxisClassName, function(s) { - s.attr({ - y: 0, - 'shape-rendering': 'crispEdges' - }); - }); - - maskMinOppAxis - .attr('width', opts._width) - .call(Color.fill, constants.maskOppAxisColor); - - var maskMaxOppAxis = Lib.ensureSingle(rangeSlider, 'rect', constants.maskMaxOppAxisClassName, function(s) { - s.attr({ - y: 0, - 'shape-rendering': 'crispEdges' - }); - }); - - maskMaxOppAxis - .attr('width', opts._width) - .style('border-top', constants.maskOppBorder) - .call(Color.fill, constants.maskOppAxisColor); - } -} - -function drawSlideBox(rangeSlider, gd, axisOpts, opts) { - if(gd._context.staticPlot) return; - - var slideBox = Lib.ensureSingle(rangeSlider, 'rect', constants.slideBoxClassName, function(s) { - s.attr({ - y: 0, - cursor: constants.slideBoxCursor, - 'shape-rendering': 'crispEdges' - }); - }); - - slideBox.attr({ - height: opts._height, - fill: constants.slideBoxFill - }); -} - -function drawGrabbers(rangeSlider, gd, axisOpts, opts) { - // - var grabberMin = Lib.ensureSingle(rangeSlider, 'g', constants.grabberMinClassName); - var grabberMax = Lib.ensureSingle(rangeSlider, 'g', constants.grabberMaxClassName); - - // - var handleFixAttrs = { - x: 0, - width: constants.handleWidth, - rx: constants.handleRadius, - fill: Color.background, - stroke: Color.defaultLine, - 'stroke-width': constants.handleStrokeWidth, - 'shape-rendering': 'crispEdges' - }; - var handleDynamicAttrs = { - y: Math.round(opts._height / 4), - height: Math.round(opts._height / 2), - }; - var handleMin = Lib.ensureSingle(grabberMin, 'rect', constants.handleMinClassName, function(s) { - s.attr(handleFixAttrs); - }); - handleMin.attr(handleDynamicAttrs); - - var handleMax = Lib.ensureSingle(grabberMax, 'rect', constants.handleMaxClassName, function(s) { - s.attr(handleFixAttrs); - }); - handleMax.attr(handleDynamicAttrs); - - // - if(gd._context.staticPlot) return; - - var grabAreaFixAttrs = { - width: constants.grabAreaWidth, - x: 0, - y: 0, - fill: constants.grabAreaFill, - cursor: constants.grabAreaCursor - }; - - var grabAreaMin = Lib.ensureSingle(grabberMin, 'rect', constants.grabAreaMinClassName, function(s) { - s.attr(grabAreaFixAttrs); - }); - grabAreaMin.attr('height', opts._height); - - var grabAreaMax = Lib.ensureSingle(grabberMax, 'rect', constants.grabAreaMaxClassName, function(s) { - s.attr(grabAreaFixAttrs); - }); - grabAreaMax.attr('height', opts._height); -} - -},{"../../lib":719,"../../lib/setcursor":739,"../../plots/cartesian":778,"../../plots/cartesian/axis_ids":770,"../../plots/plots":828,"../../registry":847,"../color":593,"../dragelement":611,"../drawing":614,"../titles":681,"./constants":663,"d3":163}],666:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var axisIDs = _dereq_('../../plots/cartesian/axis_ids'); -var constants = _dereq_('./constants'); -var name = constants.name; - -function isVisible(ax) { - var rangeSlider = ax && ax[name]; - return rangeSlider && rangeSlider.visible; -} -exports.isVisible = isVisible; - -exports.makeData = function(fullLayout) { - var axes = axisIDs.list({ _fullLayout: fullLayout }, 'x', true); - var margin = fullLayout.margin; - var rangeSliderData = []; - - if(!fullLayout._has('gl2d')) { - for(var i = 0; i < axes.length; i++) { - var ax = axes[i]; - - if(isVisible(ax)) { - rangeSliderData.push(ax); - - var opts = ax[name]; - opts._id = name + ax._id; - opts._height = (fullLayout.height - margin.b - margin.t) * opts.thickness; - opts._offsetShift = Math.floor(opts.borderwidth / 2); - } - } - } - - fullLayout._rangeSliderData = rangeSliderData; -}; - -exports.autoMarginOpts = function(gd, ax) { - var opts = ax[name]; - - var oppBottom = Infinity; - var counterAxes = ax._counterAxes; - for(var j = 0; j < counterAxes.length; j++) { - var counterId = counterAxes[j]; - var oppAxis = axisIDs.getFromId(gd, counterId); - oppBottom = Math.min(oppBottom, oppAxis.domain[0]); - } - opts._oppBottom = oppBottom; - - var tickHeight = (ax.side === 'bottom' && ax._boundingBox.height) || 0; - opts._tickHeight = tickHeight; - - return { - x: 0, - y: oppBottom, - l: 0, - r: 0, - t: 0, - b: opts._height + gd._fullLayout.margin.b + tickHeight, - pad: constants.extraPad + opts._offsetShift * 2 - }; -}; - -},{"../../plots/cartesian/axis_ids":770,"./constants":663}],667:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attrs = _dereq_('./attributes'); -var oppAxisAttrs = _dereq_('./oppaxis_attributes'); -var helpers = _dereq_('./helpers'); - -module.exports = { - moduleType: 'component', - name: 'rangeslider', - - schema: { - subplots: { - xaxis: { - rangeslider: Lib.extendFlat({}, attrs, { - yaxis: oppAxisAttrs - }) - } - } - }, - - layoutAttributes: _dereq_('./attributes'), - handleDefaults: _dereq_('./defaults'), - calcAutorange: _dereq_('./calc_autorange'), - draw: _dereq_('./draw'), - isVisible: helpers.isVisible, - makeData: helpers.makeData, - autoMarginOpts: helpers.autoMarginOpts -}; - -},{"../../lib":719,"./attributes":661,"./calc_autorange":662,"./defaults":664,"./draw":665,"./helpers":666,"./oppaxis_attributes":668}],668:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - // not really a 'subplot' attribute container, - // but this is the flag we use to denote attributes that - // support yaxis, yaxis2, yaxis3, ... counters - _isSubplotObj: true, - - rangemode: { - valType: 'enumerated', - values: ['auto', 'fixed', 'match'], - dflt: 'match', - - editType: 'calc', - - }, - range: { - valType: 'info_array', - - items: [ - {valType: 'any', editType: 'plot'}, - {valType: 'any', editType: 'plot'} - ], - editType: 'plot', - - }, - editType: 'calc' -}; - -},{}],669:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var annAttrs = _dereq_('../annotations/attributes'); -var scatterLineAttrs = _dereq_('../../traces/scatter/attributes').line; -var dash = _dereq_('../drawing/attributes').dash; -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - -module.exports = templatedArray('shape', { - visible: { - valType: 'boolean', - - dflt: true, - editType: 'calc+arraydraw', - - }, - - type: { - valType: 'enumerated', - values: ['circle', 'rect', 'path', 'line'], - - editType: 'calc+arraydraw', - - }, - - layer: { - valType: 'enumerated', - values: ['below', 'above'], - dflt: 'above', - - editType: 'arraydraw', - - }, - - xref: extendFlat({}, annAttrs.xref, { - - }), - xsizemode: { - valType: 'enumerated', - values: ['scaled', 'pixel'], - dflt: 'scaled', - - editType: 'calc+arraydraw', - - }, - xanchor: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - x0: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - x1: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - - yref: extendFlat({}, annAttrs.yref, { - - }), - ysizemode: { - valType: 'enumerated', - values: ['scaled', 'pixel'], - dflt: 'scaled', - - editType: 'calc+arraydraw', - - }, - yanchor: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - y0: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - y1: { - valType: 'any', - - editType: 'calc+arraydraw', - - }, - - path: { - valType: 'string', - - editType: 'calc+arraydraw', - - }, - - opacity: { - valType: 'number', - min: 0, - max: 1, - dflt: 1, - - editType: 'arraydraw', - - }, - line: { - color: extendFlat({}, scatterLineAttrs.color, {editType: 'arraydraw'}), - width: extendFlat({}, scatterLineAttrs.width, {editType: 'calc+arraydraw'}), - dash: extendFlat({}, dash, {editType: 'arraydraw'}), - - editType: 'calc+arraydraw' - }, - fillcolor: { - valType: 'color', - dflt: 'rgba(0,0,0,0)', - - editType: 'arraydraw', - - }, - editType: 'arraydraw' -}); - -},{"../../lib/extend":710,"../../plot_api/plot_template":757,"../../traces/scatter/attributes":1112,"../annotations/attributes":576,"../drawing/attributes":613}],670:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); - -var constants = _dereq_('./constants'); -var helpers = _dereq_('./helpers'); - - -module.exports = function calcAutorange(gd) { - var fullLayout = gd._fullLayout; - var shapeList = Lib.filterVisible(fullLayout.shapes); - - if(!shapeList.length || !gd._fullData.length) return; - - for(var i = 0; i < shapeList.length; i++) { - var shape = shapeList[i]; - shape._extremes = {}; - - var ax, bounds; - - if(shape.xref !== 'paper') { - var vx0 = shape.xsizemode === 'pixel' ? shape.xanchor : shape.x0; - var vx1 = shape.xsizemode === 'pixel' ? shape.xanchor : shape.x1; - ax = Axes.getFromId(gd, shape.xref); - - bounds = shapeBounds(ax, vx0, vx1, shape.path, constants.paramIsX); - if(bounds) { - shape._extremes[ax._id] = Axes.findExtremes(ax, bounds, calcXPaddingOptions(shape)); - } - } - - if(shape.yref !== 'paper') { - var vy0 = shape.ysizemode === 'pixel' ? shape.yanchor : shape.y0; - var vy1 = shape.ysizemode === 'pixel' ? shape.yanchor : shape.y1; - ax = Axes.getFromId(gd, shape.yref); - - bounds = shapeBounds(ax, vy0, vy1, shape.path, constants.paramIsY); - if(bounds) { - shape._extremes[ax._id] = Axes.findExtremes(ax, bounds, calcYPaddingOptions(shape)); - } - } - } -}; - -function calcXPaddingOptions(shape) { - return calcPaddingOptions(shape.line.width, shape.xsizemode, shape.x0, shape.x1, shape.path, false); -} - -function calcYPaddingOptions(shape) { - return calcPaddingOptions(shape.line.width, shape.ysizemode, shape.y0, shape.y1, shape.path, true); -} - -function calcPaddingOptions(lineWidth, sizeMode, v0, v1, path, isYAxis) { - var ppad = lineWidth / 2; - var axisDirectionReverted = isYAxis; - - if(sizeMode === 'pixel') { - var coords = path ? - helpers.extractPathCoords(path, isYAxis ? constants.paramIsY : constants.paramIsX) : - [v0, v1]; - var maxValue = Lib.aggNums(Math.max, null, coords); - var minValue = Lib.aggNums(Math.min, null, coords); - var beforePad = minValue < 0 ? Math.abs(minValue) + ppad : ppad; - var afterPad = maxValue > 0 ? maxValue + ppad : ppad; - - return { - ppad: ppad, - ppadplus: axisDirectionReverted ? beforePad : afterPad, - ppadminus: axisDirectionReverted ? afterPad : beforePad - }; - } else { - return {ppad: ppad}; - } -} - -function shapeBounds(ax, v0, v1, path, paramsToUse) { - var convertVal = (ax.type === 'category' || ax.type === 'multicategory') ? ax.r2c : ax.d2c; - - if(v0 !== undefined) return [convertVal(v0), convertVal(v1)]; - if(!path) return; - - var min = Infinity; - var max = -Infinity; - var segments = path.match(constants.segmentRE); - var i; - var segment; - var drawnParam; - var params; - var val; - - if(ax.type === 'date') convertVal = helpers.decodeDate(convertVal); - - for(i = 0; i < segments.length; i++) { - segment = segments[i]; - drawnParam = paramsToUse[segment.charAt(0)].drawn; - if(drawnParam === undefined) continue; - - params = segments[i].substr(1).match(constants.paramRE); - if(!params || params.length < drawnParam) continue; - - val = convertVal(params[drawnParam]); - if(val < min) min = val; - if(val > max) max = val; - } - if(max >= min) return [min, max]; -} - -},{"../../lib":719,"../../plots/cartesian/axes":767,"./constants":671,"./helpers":674}],671:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -module.exports = { - segmentRE: /[MLHVQCTSZ][^MLHVQCTSZ]*/g, - paramRE: /[^\s,]+/g, - - // which numbers in each path segment are x (or y) values - // drawn is which param is a drawn point, as opposed to a - // control point (which doesn't count toward autorange. - // TODO: this means curved paths could extend beyond the - // autorange bounds. This is a bit tricky to get right - // unless we revert to bounding boxes, but perhaps there's - // a calculation we could do...) - paramIsX: { - M: {0: true, drawn: 0}, - L: {0: true, drawn: 0}, - H: {0: true, drawn: 0}, - V: {}, - Q: {0: true, 2: true, drawn: 2}, - C: {0: true, 2: true, 4: true, drawn: 4}, - T: {0: true, drawn: 0}, - S: {0: true, 2: true, drawn: 2}, - // A: {0: true, 5: true}, - Z: {} - }, - - paramIsY: { - M: {1: true, drawn: 1}, - L: {1: true, drawn: 1}, - H: {}, - V: {0: true, drawn: 0}, - Q: {1: true, 3: true, drawn: 3}, - C: {1: true, 3: true, 5: true, drawn: 5}, - T: {1: true, drawn: 1}, - S: {1: true, 3: true, drawn: 5}, - // A: {1: true, 6: true}, - Z: {} - }, - - numParams: { - M: 2, - L: 2, - H: 1, - V: 1, - Q: 4, - C: 6, - T: 2, - S: 4, - // A: 7, - Z: 0 - } -}; - -},{}],672:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); - -var attributes = _dereq_('./attributes'); -var helpers = _dereq_('./helpers'); - - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { - handleArrayContainerDefaults(layoutIn, layoutOut, { - name: 'shapes', - handleItemDefaults: handleShapeDefaults - }); -}; - -function handleShapeDefaults(shapeIn, shapeOut, fullLayout) { - function coerce(attr, dflt) { - return Lib.coerce(shapeIn, shapeOut, attributes, attr, dflt); - } - - var visible = coerce('visible'); - - if(!visible) return; - - coerce('layer'); - coerce('opacity'); - coerce('fillcolor'); - coerce('line.color'); - coerce('line.width'); - coerce('line.dash'); - - var dfltType = shapeIn.path ? 'path' : 'rect'; - var shapeType = coerce('type', dfltType); - var xSizeMode = coerce('xsizemode'); - var ySizeMode = coerce('ysizemode'); - - // positioning - var axLetters = ['x', 'y']; - for(var i = 0; i < 2; i++) { - var axLetter = axLetters[i]; - var attrAnchor = axLetter + 'anchor'; - var sizeMode = axLetter === 'x' ? xSizeMode : ySizeMode; - var gdMock = {_fullLayout: fullLayout}; - var ax; - var pos2r; - var r2pos; - - // xref, yref - var axRef = Axes.coerceRef(shapeIn, shapeOut, gdMock, axLetter, '', 'paper'); - - if(axRef !== 'paper') { - ax = Axes.getFromId(gdMock, axRef); - ax._shapeIndices.push(shapeOut._index); - r2pos = helpers.rangeToShapePosition(ax); - pos2r = helpers.shapePositionToRange(ax); - } else { - pos2r = r2pos = Lib.identity; - } - - // Coerce x0, x1, y0, y1 - if(shapeType !== 'path') { - var dflt0 = 0.25; - var dflt1 = 0.75; - - // hack until V2.0 when log has regular range behavior - make it look like other - // ranges to send to coerce, then put it back after - // this is all to give reasonable default position behavior on log axes, which is - // a pretty unimportant edge case so we could just ignore this. - var attr0 = axLetter + '0'; - var attr1 = axLetter + '1'; - var in0 = shapeIn[attr0]; - var in1 = shapeIn[attr1]; - shapeIn[attr0] = pos2r(shapeIn[attr0], true); - shapeIn[attr1] = pos2r(shapeIn[attr1], true); - - if(sizeMode === 'pixel') { - coerce(attr0, 0); - coerce(attr1, 10); - } else { - Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr0, dflt0); - Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attr1, dflt1); - } - - // hack part 2 - shapeOut[attr0] = r2pos(shapeOut[attr0]); - shapeOut[attr1] = r2pos(shapeOut[attr1]); - shapeIn[attr0] = in0; - shapeIn[attr1] = in1; - } - - // Coerce xanchor and yanchor - if(sizeMode === 'pixel') { - // Hack for log axis described above - var inAnchor = shapeIn[attrAnchor]; - shapeIn[attrAnchor] = pos2r(shapeIn[attrAnchor], true); - - Axes.coercePosition(shapeOut, gdMock, coerce, axRef, attrAnchor, 0.25); - - // Hack part 2 - shapeOut[attrAnchor] = r2pos(shapeOut[attrAnchor]); - shapeIn[attrAnchor] = inAnchor; - } - } - - if(shapeType === 'path') { - coerce('path'); - } else { - Lib.noneOrAll(shapeIn, shapeOut, ['x0', 'x1', 'y0', 'y1']); - } -} - -},{"../../lib":719,"../../plots/array_container_defaults":763,"../../plots/cartesian/axes":767,"./attributes":669,"./helpers":674}],673:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var Color = _dereq_('../color'); -var Drawing = _dereq_('../drawing'); -var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; - -var dragElement = _dereq_('../dragelement'); -var setCursor = _dereq_('../../lib/setcursor'); - -var constants = _dereq_('./constants'); -var helpers = _dereq_('./helpers'); - - -// Shapes are stored in gd.layout.shapes, an array of objects -// index can point to one item in this array, -// or non-numeric to simply add a new one -// or -1 to modify all existing -// opt can be the full options object, or one key (to be set to value) -// or undefined to simply redraw -// if opt is blank, val can be 'add' or a full options object to add a new -// annotation at that point in the array, or 'remove' to delete this one - -module.exports = { - draw: draw, - drawOne: drawOne -}; - -function draw(gd) { - var fullLayout = gd._fullLayout; - - // Remove previous shapes before drawing new in shapes in fullLayout.shapes - fullLayout._shapeUpperLayer.selectAll('path').remove(); - fullLayout._shapeLowerLayer.selectAll('path').remove(); - - for(var k in fullLayout._plots) { - var shapelayer = fullLayout._plots[k].shapelayer; - if(shapelayer) shapelayer.selectAll('path').remove(); - } - - for(var i = 0; i < fullLayout.shapes.length; i++) { - if(fullLayout.shapes[i].visible) { - drawOne(gd, i); - } - } - - // may need to resurrect this if we put text (LaTeX) in shapes - // return Plots.previousPromises(gd); -} - -function drawOne(gd, index) { - // remove the existing shape if there is one. - // because indices can change, we need to look in all shape layers - gd._fullLayout._paperdiv - .selectAll('.shapelayer [data-index="' + index + '"]') - .remove(); - - var options = gd._fullLayout.shapes[index] || {}; - - // this shape is gone - quit now after deleting it - // TODO: use d3 idioms instead of deleting and redrawing every time - if(!options._input || options.visible === false) return; - - if(options.layer !== 'below') { - drawShape(gd._fullLayout._shapeUpperLayer); - } else if(options.xref === 'paper' || options.yref === 'paper') { - drawShape(gd._fullLayout._shapeLowerLayer); - } else { - var plotinfo = gd._fullLayout._plots[options.xref + options.yref]; - if(plotinfo) { - var mainPlot = plotinfo.mainplotinfo || plotinfo; - drawShape(mainPlot.shapelayer); - } else { - // Fall back to _shapeLowerLayer in case the requested subplot doesn't exist. - // This can happen if you reference the shape to an x / y axis combination - // that doesn't have any data on it (and layer is below) - drawShape(gd._fullLayout._shapeLowerLayer); - } - } - - function drawShape(shapeLayer) { - var attrs = { - 'data-index': index, - 'fill-rule': 'evenodd', - d: getPathString(gd, options) - }; - var lineColor = options.line.width ? options.line.color : 'rgba(0,0,0,0)'; - - var path = shapeLayer.append('path') - .attr(attrs) - .style('opacity', options.opacity) - .call(Color.stroke, lineColor) - .call(Color.fill, options.fillcolor) - .call(Drawing.dashLine, options.line.dash, options.line.width); - - setClipPath(path, gd, options); - - if(gd._context.edits.shapePosition) setupDragElement(gd, path, options, index, shapeLayer); - } -} - -function setClipPath(shapePath, gd, shapeOptions) { - // note that for layer="below" the clipAxes can be different from the - // subplot we're drawing this in. This could cause problems if the shape - // spans two subplots. See https://github.com/plotly/plotly.js/issues/1452 - var clipAxes = (shapeOptions.xref + shapeOptions.yref).replace(/paper/g, ''); - - Drawing.setClipUrl( - shapePath, - clipAxes ? 'clip' + gd._fullLayout._uid + clipAxes : null, - gd - ); -} - -function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer) { - var MINWIDTH = 10; - var MINHEIGHT = 10; - - var xPixelSized = shapeOptions.xsizemode === 'pixel'; - var yPixelSized = shapeOptions.ysizemode === 'pixel'; - var isLine = shapeOptions.type === 'line'; - var isPath = shapeOptions.type === 'path'; - - var editHelpers = arrayEditor(gd.layout, 'shapes', shapeOptions); - var modifyItem = editHelpers.modifyItem; - - var x0, y0, x1, y1, xAnchor, yAnchor; - var n0, s0, w0, e0, optN, optS, optW, optE; - var pathIn; - - // setup conversion functions - var xa = Axes.getFromId(gd, shapeOptions.xref); - var ya = Axes.getFromId(gd, shapeOptions.yref); - var x2p = helpers.getDataToPixel(gd, xa); - var y2p = helpers.getDataToPixel(gd, ya, true); - var p2x = helpers.getPixelToData(gd, xa); - var p2y = helpers.getPixelToData(gd, ya, true); - - var sensoryElement = obtainSensoryElement(); - var dragOptions = { - element: sensoryElement.node(), - gd: gd, - prepFn: startDrag, - doneFn: endDrag, - clickFn: abortDrag - }; - var dragMode; - - dragElement.init(dragOptions); - - sensoryElement.node().onmousemove = updateDragMode; - - function obtainSensoryElement() { - return isLine ? createLineDragHandles() : shapePath; - } - - function createLineDragHandles() { - var minSensoryWidth = 10; - var sensoryWidth = Math.max(shapeOptions.line.width, minSensoryWidth); - - // Helper shapes group - // Note that by setting the `data-index` attr, it is ensured that - // the helper group is purged in this modules `draw` function - var g = shapeLayer.append('g') - .attr('data-index', index); - - // Helper path for moving - g.append('path') - .attr('d', shapePath.attr('d')) - .style({ - 'cursor': 'move', - 'stroke-width': sensoryWidth, - 'stroke-opacity': '0' // ensure not visible - }); - - // Helper circles for resizing - var circleStyle = { - 'fill-opacity': '0' // ensure not visible - }; - var circleRadius = sensoryWidth / 2 > minSensoryWidth ? sensoryWidth / 2 : minSensoryWidth; - - g.append('circle') - .attr({ - 'data-line-point': 'start-point', - 'cx': xPixelSized ? x2p(shapeOptions.xanchor) + shapeOptions.x0 : x2p(shapeOptions.x0), - 'cy': yPixelSized ? y2p(shapeOptions.yanchor) - shapeOptions.y0 : y2p(shapeOptions.y0), - 'r': circleRadius - }) - .style(circleStyle) - .classed('cursor-grab', true); - - g.append('circle') - .attr({ - 'data-line-point': 'end-point', - 'cx': xPixelSized ? x2p(shapeOptions.xanchor) + shapeOptions.x1 : x2p(shapeOptions.x1), - 'cy': yPixelSized ? y2p(shapeOptions.yanchor) - shapeOptions.y1 : y2p(shapeOptions.y1), - 'r': circleRadius - }) - .style(circleStyle) - .classed('cursor-grab', true); - - return g; - } - - function updateDragMode(evt) { - if(isLine) { - if(evt.target.tagName === 'path') { - dragMode = 'move'; - } else { - dragMode = evt.target.attributes['data-line-point'].value === 'start-point' ? - 'resize-over-start-point' : 'resize-over-end-point'; - } - } else { - // element might not be on screen at time of setup, - // so obtain bounding box here - var dragBBox = dragOptions.element.getBoundingClientRect(); - - // choose 'move' or 'resize' - // based on initial position of cursor within the drag element - var w = dragBBox.right - dragBBox.left; - var h = dragBBox.bottom - dragBBox.top; - var x = evt.clientX - dragBBox.left; - var y = evt.clientY - dragBBox.top; - var cursor = (!isPath && w > MINWIDTH && h > MINHEIGHT && !evt.shiftKey) ? - dragElement.getCursor(x / w, 1 - y / h) : - 'move'; - - setCursor(shapePath, cursor); - - // possible values 'move', 'sw', 'w', 'se', 'e', 'ne', 'n', 'nw' and 'w' - dragMode = cursor.split('-')[0]; - } - } - - function startDrag(evt) { - // setup update strings and initial values - if(xPixelSized) { - xAnchor = x2p(shapeOptions.xanchor); - } - if(yPixelSized) { - yAnchor = y2p(shapeOptions.yanchor); - } - - if(shapeOptions.type === 'path') { - pathIn = shapeOptions.path; - } else { - x0 = xPixelSized ? shapeOptions.x0 : x2p(shapeOptions.x0); - y0 = yPixelSized ? shapeOptions.y0 : y2p(shapeOptions.y0); - x1 = xPixelSized ? shapeOptions.x1 : x2p(shapeOptions.x1); - y1 = yPixelSized ? shapeOptions.y1 : y2p(shapeOptions.y1); - } - - if(x0 < x1) { - w0 = x0; - optW = 'x0'; - e0 = x1; - optE = 'x1'; - } else { - w0 = x1; - optW = 'x1'; - e0 = x0; - optE = 'x0'; - } - - // For fixed size shapes take opposing direction of y-axis into account. - // Hint: For data sized shapes this is done by the y2p function. - if((!yPixelSized && y0 < y1) || (yPixelSized && y0 > y1)) { - n0 = y0; - optN = 'y0'; - s0 = y1; - optS = 'y1'; - } else { - n0 = y1; - optN = 'y1'; - s0 = y0; - optS = 'y0'; - } - - // setup dragMode and the corresponding handler - updateDragMode(evt); - renderVisualCues(shapeLayer, shapeOptions); - deactivateClipPathTemporarily(shapePath, shapeOptions, gd); - dragOptions.moveFn = (dragMode === 'move') ? moveShape : resizeShape; - } - - function endDrag() { - setCursor(shapePath); - removeVisualCues(shapeLayer); - - // Don't rely on clipPath being activated during re-layout - setClipPath(shapePath, gd, shapeOptions); - Registry.call('_guiRelayout', gd, editHelpers.getUpdateObj()); - } - - function abortDrag() { - removeVisualCues(shapeLayer); - } - - function moveShape(dx, dy) { - if(shapeOptions.type === 'path') { - var noOp = function(coord) { return coord; }; - var moveX = noOp; - var moveY = noOp; - - if(xPixelSized) { - modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); - } else { - moveX = function moveX(x) { return p2x(x2p(x) + dx); }; - if(xa && xa.type === 'date') moveX = helpers.encodeDate(moveX); - } - - if(yPixelSized) { - modifyItem('yanchor', shapeOptions.yanchor = p2y(yAnchor + dy)); - } else { - moveY = function moveY(y) { return p2y(y2p(y) + dy); }; - if(ya && ya.type === 'date') moveY = helpers.encodeDate(moveY); - } - - modifyItem('path', shapeOptions.path = movePath(pathIn, moveX, moveY)); - } else { - if(xPixelSized) { - modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); - } else { - modifyItem('x0', shapeOptions.x0 = p2x(x0 + dx)); - modifyItem('x1', shapeOptions.x1 = p2x(x1 + dx)); - } - - if(yPixelSized) { - modifyItem('yanchor', shapeOptions.yanchor = p2y(yAnchor + dy)); - } else { - modifyItem('y0', shapeOptions.y0 = p2y(y0 + dy)); - modifyItem('y1', shapeOptions.y1 = p2y(y1 + dy)); - } - } - - shapePath.attr('d', getPathString(gd, shapeOptions)); - renderVisualCues(shapeLayer, shapeOptions); - } - - function resizeShape(dx, dy) { - if(isPath) { - // TODO: implement path resize, don't forget to update dragMode code - var noOp = function(coord) { return coord; }; - var moveX = noOp; - var moveY = noOp; - - if(xPixelSized) { - modifyItem('xanchor', shapeOptions.xanchor = p2x(xAnchor + dx)); - } else { - moveX = function moveX(x) { return p2x(x2p(x) + dx); }; - if(xa && xa.type === 'date') moveX = helpers.encodeDate(moveX); - } - - if(yPixelSized) { - modifyItem('yanchor', shapeOptions.yanchor = p2y(yAnchor + dy)); - } else { - moveY = function moveY(y) { return p2y(y2p(y) + dy); }; - if(ya && ya.type === 'date') moveY = helpers.encodeDate(moveY); - } - - modifyItem('path', shapeOptions.path = movePath(pathIn, moveX, moveY)); - } else if(isLine) { - if(dragMode === 'resize-over-start-point') { - var newX0 = x0 + dx; - var newY0 = yPixelSized ? y0 - dy : y0 + dy; - modifyItem('x0', shapeOptions.x0 = xPixelSized ? newX0 : p2x(newX0)); - modifyItem('y0', shapeOptions.y0 = yPixelSized ? newY0 : p2y(newY0)); - } else if(dragMode === 'resize-over-end-point') { - var newX1 = x1 + dx; - var newY1 = yPixelSized ? y1 - dy : y1 + dy; - modifyItem('x1', shapeOptions.x1 = xPixelSized ? newX1 : p2x(newX1)); - modifyItem('y1', shapeOptions.y1 = yPixelSized ? newY1 : p2y(newY1)); - } - } else { - var newN = (~dragMode.indexOf('n')) ? n0 + dy : n0; - var newS = (~dragMode.indexOf('s')) ? s0 + dy : s0; - var newW = (~dragMode.indexOf('w')) ? w0 + dx : w0; - var newE = (~dragMode.indexOf('e')) ? e0 + dx : e0; - - // Do things in opposing direction for y-axis. - // Hint: for data-sized shapes the reversal of axis direction is done in p2y. - if(~dragMode.indexOf('n') && yPixelSized) newN = n0 - dy; - if(~dragMode.indexOf('s') && yPixelSized) newS = s0 - dy; - - // Update shape eventually. Again, be aware of the - // opposing direction of the y-axis of fixed size shapes. - if((!yPixelSized && newS - newN > MINHEIGHT) || - (yPixelSized && newN - newS > MINHEIGHT)) { - modifyItem(optN, shapeOptions[optN] = yPixelSized ? newN : p2y(newN)); - modifyItem(optS, shapeOptions[optS] = yPixelSized ? newS : p2y(newS)); - } - if(newE - newW > MINWIDTH) { - modifyItem(optW, shapeOptions[optW] = xPixelSized ? newW : p2x(newW)); - modifyItem(optE, shapeOptions[optE] = xPixelSized ? newE : p2x(newE)); - } - } - - shapePath.attr('d', getPathString(gd, shapeOptions)); - renderVisualCues(shapeLayer, shapeOptions); - } - - function renderVisualCues(shapeLayer, shapeOptions) { - if(xPixelSized || yPixelSized) { - renderAnchor(); - } - - function renderAnchor() { - var isNotPath = shapeOptions.type !== 'path'; - - // d3 join with dummy data to satisfy d3 data-binding - var visualCues = shapeLayer.selectAll('.visual-cue').data([0]); - - // Enter - var strokeWidth = 1; - visualCues.enter() - .append('path') - .attr({ - 'fill': '#fff', - 'fill-rule': 'evenodd', - 'stroke': '#000', - 'stroke-width': strokeWidth - }) - .classed('visual-cue', true); - - // Update - var posX = x2p( - xPixelSized ? - shapeOptions.xanchor : - Lib.midRange( - isNotPath ? - [shapeOptions.x0, shapeOptions.x1] : - helpers.extractPathCoords(shapeOptions.path, constants.paramIsX)) - ); - var posY = y2p( - yPixelSized ? - shapeOptions.yanchor : - Lib.midRange( - isNotPath ? - [shapeOptions.y0, shapeOptions.y1] : - helpers.extractPathCoords(shapeOptions.path, constants.paramIsY)) - ); - - posX = helpers.roundPositionForSharpStrokeRendering(posX, strokeWidth); - posY = helpers.roundPositionForSharpStrokeRendering(posY, strokeWidth); - - if(xPixelSized && yPixelSized) { - var crossPath = 'M' + (posX - 1 - strokeWidth) + ',' + (posY - 1 - strokeWidth) + - 'h-8v2h8 v8h2v-8 h8v-2h-8 v-8h-2 Z'; - visualCues.attr('d', crossPath); - } else if(xPixelSized) { - var vBarPath = 'M' + (posX - 1 - strokeWidth) + ',' + (posY - 9 - strokeWidth) + - 'v18 h2 v-18 Z'; - visualCues.attr('d', vBarPath); - } else { - var hBarPath = 'M' + (posX - 9 - strokeWidth) + ',' + (posY - 1 - strokeWidth) + - 'h18 v2 h-18 Z'; - visualCues.attr('d', hBarPath); - } - } - } - - function removeVisualCues(shapeLayer) { - shapeLayer.selectAll('.visual-cue').remove(); - } - - function deactivateClipPathTemporarily(shapePath, shapeOptions, gd) { - var xref = shapeOptions.xref; - var yref = shapeOptions.yref; - var xa = Axes.getFromId(gd, xref); - var ya = Axes.getFromId(gd, yref); - - var clipAxes = ''; - if(xref !== 'paper' && !xa.autorange) clipAxes += xref; - if(yref !== 'paper' && !ya.autorange) clipAxes += yref; - - Drawing.setClipUrl( - shapePath, - clipAxes ? 'clip' + gd._fullLayout._uid + clipAxes : null, - gd - ); - } -} - -function getPathString(gd, options) { - var type = options.type; - var xa = Axes.getFromId(gd, options.xref); - var ya = Axes.getFromId(gd, options.yref); - var gs = gd._fullLayout._size; - var x2r, x2p, y2r, y2p; - var x0, x1, y0, y1; - - if(xa) { - x2r = helpers.shapePositionToRange(xa); - x2p = function(v) { return xa._offset + xa.r2p(x2r(v, true)); }; - } else { - x2p = function(v) { return gs.l + gs.w * v; }; - } - - if(ya) { - y2r = helpers.shapePositionToRange(ya); - y2p = function(v) { return ya._offset + ya.r2p(y2r(v, true)); }; - } else { - y2p = function(v) { return gs.t + gs.h * (1 - v); }; - } - - if(type === 'path') { - if(xa && xa.type === 'date') x2p = helpers.decodeDate(x2p); - if(ya && ya.type === 'date') y2p = helpers.decodeDate(y2p); - return convertPath(options, x2p, y2p); - } - - if(options.xsizemode === 'pixel') { - var xAnchorPos = x2p(options.xanchor); - x0 = xAnchorPos + options.x0; - x1 = xAnchorPos + options.x1; - } else { - x0 = x2p(options.x0); - x1 = x2p(options.x1); - } - - if(options.ysizemode === 'pixel') { - var yAnchorPos = y2p(options.yanchor); - y0 = yAnchorPos - options.y0; - y1 = yAnchorPos - options.y1; - } else { - y0 = y2p(options.y0); - y1 = y2p(options.y1); - } - - if(type === 'line') return 'M' + x0 + ',' + y0 + 'L' + x1 + ',' + y1; - if(type === 'rect') return 'M' + x0 + ',' + y0 + 'H' + x1 + 'V' + y1 + 'H' + x0 + 'Z'; - - // circle - var cx = (x0 + x1) / 2; - var cy = (y0 + y1) / 2; - var rx = Math.abs(cx - x0); - var ry = Math.abs(cy - y0); - var rArc = 'A' + rx + ',' + ry; - var rightPt = (cx + rx) + ',' + cy; - var topPt = cx + ',' + (cy - ry); - return 'M' + rightPt + rArc + ' 0 1,1 ' + topPt + - rArc + ' 0 0,1 ' + rightPt + 'Z'; -} - - -function convertPath(options, x2p, y2p) { - var pathIn = options.path; - var xSizemode = options.xsizemode; - var ySizemode = options.ysizemode; - var xAnchor = options.xanchor; - var yAnchor = options.yanchor; - - return pathIn.replace(constants.segmentRE, function(segment) { - var paramNumber = 0; - var segmentType = segment.charAt(0); - var xParams = constants.paramIsX[segmentType]; - var yParams = constants.paramIsY[segmentType]; - var nParams = constants.numParams[segmentType]; - - var paramString = segment.substr(1).replace(constants.paramRE, function(param) { - if(xParams[paramNumber]) { - if(xSizemode === 'pixel') param = x2p(xAnchor) + Number(param); - else param = x2p(param); - } else if(yParams[paramNumber]) { - if(ySizemode === 'pixel') param = y2p(yAnchor) - Number(param); - else param = y2p(param); - } - paramNumber++; - - if(paramNumber > nParams) param = 'X'; - return param; - }); - - if(paramNumber > nParams) { - paramString = paramString.replace(/[\s,]*X.*/, ''); - Lib.log('Ignoring extra params in segment ' + segment); - } - - return segmentType + paramString; - }); -} - -function movePath(pathIn, moveX, moveY) { - return pathIn.replace(constants.segmentRE, function(segment) { - var paramNumber = 0; - var segmentType = segment.charAt(0); - var xParams = constants.paramIsX[segmentType]; - var yParams = constants.paramIsY[segmentType]; - var nParams = constants.numParams[segmentType]; - - var paramString = segment.substr(1).replace(constants.paramRE, function(param) { - if(paramNumber >= nParams) return param; - - if(xParams[paramNumber]) param = moveX(param); - else if(yParams[paramNumber]) param = moveY(param); - - paramNumber++; - - return param; - }); - - return segmentType + paramString; - }); -} - -},{"../../lib":719,"../../lib/setcursor":739,"../../plot_api/plot_template":757,"../../plots/cartesian/axes":767,"../../registry":847,"../color":593,"../dragelement":611,"../drawing":614,"./constants":671,"./helpers":674}],674:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var constants = _dereq_('./constants'); - -var Lib = _dereq_('../../lib'); - -// special position conversion functions... category axis positions can't be -// specified by their data values, because they don't make a continuous mapping. -// so these have to be specified in terms of the category serial numbers, -// but can take fractional values. Other axis types we specify position based on -// the actual data values. -// TODO: in V2.0 (when log axis ranges are in data units) range and shape position -// will be identical, so rangeToShapePosition and shapePositionToRange can be -// removed entirely. - -exports.rangeToShapePosition = function(ax) { - return (ax.type === 'log') ? ax.r2d : function(v) { return v; }; -}; - -exports.shapePositionToRange = function(ax) { - return (ax.type === 'log') ? ax.d2r : function(v) { return v; }; -}; - -exports.decodeDate = function(convertToPx) { - return function(v) { - if(v.replace) v = v.replace('_', ' '); - return convertToPx(v); - }; -}; - -exports.encodeDate = function(convertToDate) { - return function(v) { return convertToDate(v).replace(' ', '_'); }; -}; - -exports.extractPathCoords = function(path, paramsToUse) { - var extractedCoordinates = []; - - var segments = path.match(constants.segmentRE); - segments.forEach(function(segment) { - var relevantParamIdx = paramsToUse[segment.charAt(0)].drawn; - if(relevantParamIdx === undefined) return; - - var params = segment.substr(1).match(constants.paramRE); - if(!params || params.length < relevantParamIdx) return; - - extractedCoordinates.push(Lib.cleanNumber(params[relevantParamIdx])); - }); - - return extractedCoordinates; -}; - -exports.getDataToPixel = function(gd, axis, isVertical) { - var gs = gd._fullLayout._size; - var dataToPixel; - - if(axis) { - var d2r = exports.shapePositionToRange(axis); - - dataToPixel = function(v) { - return axis._offset + axis.r2p(d2r(v, true)); - }; - - if(axis.type === 'date') dataToPixel = exports.decodeDate(dataToPixel); - } else if(isVertical) { - dataToPixel = function(v) { return gs.t + gs.h * (1 - v); }; - } else { - dataToPixel = function(v) { return gs.l + gs.w * v; }; - } - - return dataToPixel; -}; - -exports.getPixelToData = function(gd, axis, isVertical) { - var gs = gd._fullLayout._size; - var pixelToData; - - if(axis) { - var r2d = exports.rangeToShapePosition(axis); - pixelToData = function(p) { return r2d(axis.p2r(p - axis._offset)); }; - } else if(isVertical) { - pixelToData = function(p) { return 1 - (p - gs.t) / gs.h; }; - } else { - pixelToData = function(p) { return (p - gs.l) / gs.w; }; - } - - return pixelToData; -}; - -/** - * Based on the given stroke width, rounds the passed - * position value to represent either a full or half pixel. - * - * In case of an odd stroke width (e.g. 1), this measure ensures - * that a stroke positioned at the returned position isn't rendered - * blurry due to anti-aliasing. - * - * In case of an even stroke width (e.g. 2), this measure ensures - * that the position value is transformed to a full pixel value - * so that anti-aliasing doesn't take effect either. - * - * @param {number} pos The raw position value to be transformed - * @param {number} strokeWidth The stroke width - * @returns {number} either an integer or a .5 decimal number - */ -exports.roundPositionForSharpStrokeRendering = function(pos, strokeWidth) { - var strokeWidthIsOdd = Math.round(strokeWidth % 2) === 1; - var posValAsInt = Math.round(pos); - - return strokeWidthIsOdd ? posValAsInt + 0.5 : posValAsInt; -}; - -},{"../../lib":719,"./constants":671}],675:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var drawModule = _dereq_('./draw'); - -module.exports = { - moduleType: 'component', - name: 'shapes', - - layoutAttributes: _dereq_('./attributes'), - supplyLayoutDefaults: _dereq_('./defaults'), - includeBasePlot: _dereq_('../../plots/cartesian/include_components')('shapes'), - - calcAutorange: _dereq_('./calc_autorange'), - draw: drawModule.draw, - drawOne: drawModule.drawOne -}; - -},{"../../plots/cartesian/include_components":777,"./attributes":669,"./calc_autorange":670,"./defaults":672,"./draw":673}],676:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('../../plots/font_attributes'); -var padAttrs = _dereq_('../../plots/pad_attributes'); -var extendDeepAll = _dereq_('../../lib/extend').extendDeepAll; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var animationAttrs = _dereq_('../../plots/animation_attributes'); -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; -var constants = _dereq_('./constants'); - -var stepsAttrs = templatedArray('step', { - visible: { - valType: 'boolean', - - dflt: true, - - }, - method: { - valType: 'enumerated', - values: ['restyle', 'relayout', 'animate', 'update', 'skip'], - dflt: 'restyle', - - - }, - args: { - valType: 'info_array', - - freeLength: true, - items: [ - { valType: 'any' }, - { valType: 'any' }, - { valType: 'any' } - ], - - }, - label: { - valType: 'string', - - - }, - value: { - valType: 'string', - - - }, - execute: { - valType: 'boolean', - - dflt: true, - - } -}); - -module.exports = overrideAll(templatedArray('slider', { - visible: { - valType: 'boolean', - - dflt: true, - - }, - - active: { - valType: 'number', - - min: 0, - dflt: 0, - - }, - - steps: stepsAttrs, - - lenmode: { - valType: 'enumerated', - values: ['fraction', 'pixels'], - - dflt: 'fraction', - - }, - len: { - valType: 'number', - min: 0, - dflt: 1, - - - }, - x: { - valType: 'number', - min: -2, - max: 3, - dflt: 0, - - - }, - pad: extendDeepAll(padAttrs({editType: 'arraydraw'}), { - - }, {t: {dflt: 20}}), - xanchor: { - valType: 'enumerated', - values: ['auto', 'left', 'center', 'right'], - dflt: 'left', - - - }, - y: { - valType: 'number', - min: -2, - max: 3, - dflt: 0, - - - }, - yanchor: { - valType: 'enumerated', - values: ['auto', 'top', 'middle', 'bottom'], - dflt: 'top', - - - }, - - transition: { - duration: { - valType: 'number', - - min: 0, - dflt: 150, - - }, - easing: { - valType: 'enumerated', - values: animationAttrs.transition.easing.values, - - dflt: 'cubic-in-out', - - } - }, - - currentvalue: { - visible: { - valType: 'boolean', - - dflt: true, - - }, - - xanchor: { - valType: 'enumerated', - values: ['left', 'center', 'right'], - dflt: 'left', - - - }, - - offset: { - valType: 'number', - dflt: 10, - - - }, - - prefix: { - valType: 'string', - - - }, - - suffix: { - valType: 'string', - - - }, - - font: fontAttrs({ - - }) - }, - - font: fontAttrs({ - - }), - - activebgcolor: { - valType: 'color', - - dflt: constants.gripBgActiveColor, - - }, - bgcolor: { - valType: 'color', - - dflt: constants.railBgColor, - - }, - bordercolor: { - valType: 'color', - dflt: constants.railBorderColor, - - - }, - borderwidth: { - valType: 'number', - min: 0, - dflt: constants.railBorderWidth, - - - }, - ticklen: { - valType: 'number', - min: 0, - dflt: constants.tickLength, - - - }, - tickcolor: { - valType: 'color', - dflt: constants.tickColor, - - - }, - tickwidth: { - valType: 'number', - min: 0, - dflt: 1, - - - }, - minorticklen: { - valType: 'number', - min: 0, - dflt: constants.minorTickLength, - - - } -}), 'arraydraw', 'from-root'); - -},{"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plot_api/plot_template":757,"../../plots/animation_attributes":762,"../../plots/font_attributes":793,"../../plots/pad_attributes":827,"./constants":677}],677:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -module.exports = { - - // layout attribute name - name: 'sliders', - - // class names - containerClassName: 'slider-container', - groupClassName: 'slider-group', - inputAreaClass: 'slider-input-area', - railRectClass: 'slider-rail-rect', - railTouchRectClass: 'slider-rail-touch-rect', - gripRectClass: 'slider-grip-rect', - tickRectClass: 'slider-tick-rect', - inputProxyClass: 'slider-input-proxy', - labelsClass: 'slider-labels', - labelGroupClass: 'slider-label-group', - labelClass: 'slider-label', - currentValueClass: 'slider-current-value', - - railHeight: 5, - - // DOM attribute name in button group keeping track - // of active update menu - menuIndexAttrName: 'slider-active-index', - - // id root pass to Plots.autoMargin - autoMarginIdRoot: 'slider-', - - // min item width / height - minWidth: 30, - minHeight: 30, - - // padding around item text - textPadX: 40, - - // arrow offset off right edge - arrowOffsetX: 4, - - railRadius: 2, - railWidth: 5, - railBorder: 4, - railBorderWidth: 1, - railBorderColor: '#bec8d9', - railBgColor: '#f8fafc', - - // The distance of the rail from the edge of the touchable area - // Slightly less than the step inset because of the curved edges - // of the rail - railInset: 8, - - // The distance from the extremal tick marks to the edge of the - // touchable area. This is basically the same as the grip radius, - // but for other styles it wouldn't really need to be. - stepInset: 10, - - gripRadius: 10, - gripWidth: 20, - gripHeight: 20, - gripBorder: 20, - gripBorderWidth: 1, - gripBorderColor: '#bec8d9', - gripBgColor: '#f6f8fa', - gripBgActiveColor: '#dbdde0', - - labelPadding: 8, - labelOffset: 0, - - tickWidth: 1, - tickColor: '#333', - tickOffset: 25, - tickLength: 7, - - minorTickOffset: 25, - minorTickColor: '#333', - minorTickLength: 4, - - // Extra space below the current value label: - currentValuePadding: 8, - currentValueInset: 0, -}; - -},{}],678:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); - -var attributes = _dereq_('./attributes'); -var constants = _dereq_('./constants'); - -var name = constants.name; -var stepAttrs = attributes.steps; - - -module.exports = function slidersDefaults(layoutIn, layoutOut) { - handleArrayContainerDefaults(layoutIn, layoutOut, { - name: name, - handleItemDefaults: sliderDefaults - }); -}; - -function sliderDefaults(sliderIn, sliderOut, layoutOut) { - function coerce(attr, dflt) { - return Lib.coerce(sliderIn, sliderOut, attributes, attr, dflt); - } - - var steps = handleArrayContainerDefaults(sliderIn, sliderOut, { - name: 'steps', - handleItemDefaults: stepDefaults - }); - - var stepCount = 0; - for(var i = 0; i < steps.length; i++) { - if(steps[i].visible) stepCount++; - } - - var visible; - // If it has fewer than two options, it's not really a slider - if(stepCount < 2) visible = sliderOut.visible = false; - else visible = coerce('visible'); - if(!visible) return; - - sliderOut._stepCount = stepCount; - var visSteps = sliderOut._visibleSteps = Lib.filterVisible(steps); - - var active = coerce('active'); - if(!(steps[active] || {}).visible) sliderOut.active = visSteps[0]._index; - - coerce('x'); - coerce('y'); - Lib.noneOrAll(sliderIn, sliderOut, ['x', 'y']); - - coerce('xanchor'); - coerce('yanchor'); - - coerce('len'); - coerce('lenmode'); - - coerce('pad.t'); - coerce('pad.r'); - coerce('pad.b'); - coerce('pad.l'); - - Lib.coerceFont(coerce, 'font', layoutOut.font); - - var currentValueIsVisible = coerce('currentvalue.visible'); - - if(currentValueIsVisible) { - coerce('currentvalue.xanchor'); - coerce('currentvalue.prefix'); - coerce('currentvalue.suffix'); - coerce('currentvalue.offset'); - - Lib.coerceFont(coerce, 'currentvalue.font', sliderOut.font); - } - - coerce('transition.duration'); - coerce('transition.easing'); - - coerce('bgcolor'); - coerce('activebgcolor'); - coerce('bordercolor'); - coerce('borderwidth'); - coerce('ticklen'); - coerce('tickwidth'); - coerce('tickcolor'); - coerce('minorticklen'); -} - -function stepDefaults(valueIn, valueOut) { - function coerce(attr, dflt) { - return Lib.coerce(valueIn, valueOut, stepAttrs, attr, dflt); - } - - var visible; - if(valueIn.method !== 'skip' && !Array.isArray(valueIn.args)) { - visible = valueOut.visible = false; - } else visible = coerce('visible'); - - if(visible) { - coerce('method'); - coerce('args'); - var label = coerce('label', 'step-' + valueOut._index); - coerce('value', label); - coerce('execute'); - } -} - -},{"../../lib":719,"../../plots/array_container_defaults":763,"./attributes":676,"./constants":677}],679:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Plots = _dereq_('../../plots/plots'); -var Color = _dereq_('../color'); -var Drawing = _dereq_('../drawing'); -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; - -var constants = _dereq_('./constants'); -var alignmentConstants = _dereq_('../../constants/alignment'); -var LINE_SPACING = alignmentConstants.LINE_SPACING; -var FROM_TL = alignmentConstants.FROM_TL; -var FROM_BR = alignmentConstants.FROM_BR; - -module.exports = function draw(gd) { - var fullLayout = gd._fullLayout; - var sliderData = makeSliderData(fullLayout, gd); - - // draw a container for *all* sliders: - var sliders = fullLayout._infolayer - .selectAll('g.' + constants.containerClassName) - .data(sliderData.length > 0 ? [0] : []); - - sliders.enter().append('g') - .classed(constants.containerClassName, true) - .style('cursor', 'ew-resize'); - - function clearSlider(sliderOpts) { - if(sliderOpts._commandObserver) { - sliderOpts._commandObserver.remove(); - delete sliderOpts._commandObserver; - } - - // Most components don't need to explicitly remove autoMargin, because - // marginPushers does this - but slider updates don't go through - // a full replot so we need to explicitly remove it. - Plots.autoMargin(gd, autoMarginId(sliderOpts)); - } - - sliders.exit().each(function() { - d3.select(this).selectAll('g.' + constants.groupClassName) - .each(clearSlider); - }) - .remove(); - - // Return early if no menus visible: - if(sliderData.length === 0) return; - - var sliderGroups = sliders.selectAll('g.' + constants.groupClassName) - .data(sliderData, keyFunction); - - sliderGroups.enter().append('g') - .classed(constants.groupClassName, true); - - sliderGroups.exit() - .each(clearSlider) - .remove(); - - // Find the dimensions of the sliders: - for(var i = 0; i < sliderData.length; i++) { - var sliderOpts = sliderData[i]; - findDimensions(gd, sliderOpts); - } - - sliderGroups.each(function(sliderOpts) { - var gSlider = d3.select(this); - - computeLabelSteps(sliderOpts); - - Plots.manageCommandObserver(gd, sliderOpts, sliderOpts._visibleSteps, function(data) { - // NB: Same as below. This is *not* always the same as sliderOpts since - // if a new set of steps comes in, the reference in this callback would - // be invalid. We need to refetch it from the slider group, which is - // the join data that creates this slider. So if this slider still exists, - // the group should be valid, *to the best of my knowledge.* If not, - // we'd have to look it up by d3 data join index/key. - var opts = gSlider.data()[0]; - - if(opts.active === data.index) return; - if(opts._dragging) return; - - setActive(gd, gSlider, opts, data.index, false, true); - }); - - drawSlider(gd, d3.select(this), sliderOpts); - }); -}; - -function autoMarginId(sliderOpts) { - return constants.autoMarginIdRoot + sliderOpts._index; -} - -// This really only just filters by visibility: -function makeSliderData(fullLayout, gd) { - var contOpts = fullLayout[constants.name]; - var sliderData = []; - - for(var i = 0; i < contOpts.length; i++) { - var item = contOpts[i]; - if(!item.visible) continue; - item._gd = gd; - sliderData.push(item); - } - - return sliderData; -} - -// This is set in the defaults step: -function keyFunction(opts) { - return opts._index; -} - -// Compute the dimensions (mutates sliderOpts): -function findDimensions(gd, sliderOpts) { - var sliderLabels = Drawing.tester.selectAll('g.' + constants.labelGroupClass) - .data(sliderOpts._visibleSteps); - - sliderLabels.enter().append('g') - .classed(constants.labelGroupClass, true); - - // loop over fake buttons to find width / height - var maxLabelWidth = 0; - var labelHeight = 0; - sliderLabels.each(function(stepOpts) { - var labelGroup = d3.select(this); - - var text = drawLabel(labelGroup, {step: stepOpts}, sliderOpts); - - var textNode = text.node(); - if(textNode) { - var bBox = Drawing.bBox(textNode); - labelHeight = Math.max(labelHeight, bBox.height); - maxLabelWidth = Math.max(maxLabelWidth, bBox.width); - } - }); - - sliderLabels.remove(); - - var dims = sliderOpts._dims = {}; - - dims.inputAreaWidth = Math.max( - constants.railWidth, - constants.gripHeight - ); - - // calculate some overall dimensions - some of these are needed for - // calculating the currentValue dimensions - var graphSize = gd._fullLayout._size; - dims.lx = graphSize.l + graphSize.w * sliderOpts.x; - dims.ly = graphSize.t + graphSize.h * (1 - sliderOpts.y); - - if(sliderOpts.lenmode === 'fraction') { - // fraction: - dims.outerLength = Math.round(graphSize.w * sliderOpts.len); - } else { - // pixels: - dims.outerLength = sliderOpts.len; - } - - // The length of the rail, *excluding* padding on either end: - dims.inputAreaStart = 0; - dims.inputAreaLength = Math.round(dims.outerLength - sliderOpts.pad.l - sliderOpts.pad.r); - - var textableInputLength = dims.inputAreaLength - 2 * constants.stepInset; - var availableSpacePerLabel = textableInputLength / (sliderOpts._stepCount - 1); - var computedSpacePerLabel = maxLabelWidth + constants.labelPadding; - dims.labelStride = Math.max(1, Math.ceil(computedSpacePerLabel / availableSpacePerLabel)); - dims.labelHeight = labelHeight; - - // loop over all possible values for currentValue to find the - // area we need for it - dims.currentValueMaxWidth = 0; - dims.currentValueHeight = 0; - dims.currentValueTotalHeight = 0; - dims.currentValueMaxLines = 1; - - if(sliderOpts.currentvalue.visible) { - // Get the dimensions of the current value label: - var dummyGroup = Drawing.tester.append('g'); - - sliderLabels.each(function(stepOpts) { - var curValPrefix = drawCurrentValue(dummyGroup, sliderOpts, stepOpts.label); - var curValSize = (curValPrefix.node() && Drawing.bBox(curValPrefix.node())) || {width: 0, height: 0}; - var lines = svgTextUtils.lineCount(curValPrefix); - dims.currentValueMaxWidth = Math.max(dims.currentValueMaxWidth, Math.ceil(curValSize.width)); - dims.currentValueHeight = Math.max(dims.currentValueHeight, Math.ceil(curValSize.height)); - dims.currentValueMaxLines = Math.max(dims.currentValueMaxLines, lines); - }); - - dims.currentValueTotalHeight = dims.currentValueHeight + sliderOpts.currentvalue.offset; - - dummyGroup.remove(); - } - - dims.height = dims.currentValueTotalHeight + constants.tickOffset + sliderOpts.ticklen + constants.labelOffset + dims.labelHeight + sliderOpts.pad.t + sliderOpts.pad.b; - - var xanchor = 'left'; - if(Lib.isRightAnchor(sliderOpts)) { - dims.lx -= dims.outerLength; - xanchor = 'right'; - } - if(Lib.isCenterAnchor(sliderOpts)) { - dims.lx -= dims.outerLength / 2; - xanchor = 'center'; - } - - var yanchor = 'top'; - if(Lib.isBottomAnchor(sliderOpts)) { - dims.ly -= dims.height; - yanchor = 'bottom'; - } - if(Lib.isMiddleAnchor(sliderOpts)) { - dims.ly -= dims.height / 2; - yanchor = 'middle'; - } - - dims.outerLength = Math.ceil(dims.outerLength); - dims.height = Math.ceil(dims.height); - dims.lx = Math.round(dims.lx); - dims.ly = Math.round(dims.ly); - - var marginOpts = { - y: sliderOpts.y, - b: dims.height * FROM_BR[yanchor], - t: dims.height * FROM_TL[yanchor] - }; - - if(sliderOpts.lenmode === 'fraction') { - marginOpts.l = 0; - marginOpts.xl = sliderOpts.x - sliderOpts.len * FROM_TL[xanchor]; - marginOpts.r = 0; - marginOpts.xr = sliderOpts.x + sliderOpts.len * FROM_BR[xanchor]; - } else { - marginOpts.x = sliderOpts.x; - marginOpts.l = dims.outerLength * FROM_TL[xanchor]; - marginOpts.r = dims.outerLength * FROM_BR[xanchor]; - } - - Plots.autoMargin(gd, autoMarginId(sliderOpts), marginOpts); -} - -function drawSlider(gd, sliderGroup, sliderOpts) { - // This is related to the other long notes in this file regarding what happens - // when slider steps disappear. This particular fix handles what happens when - // the *current* slider step is removed. The drawing functions will error out - // when they fail to find it, so the fix for now is that it will just draw the - // slider in the first position but will not execute the command. - if(!((sliderOpts.steps[sliderOpts.active] || {}).visible)) { - sliderOpts.active = sliderOpts._visibleSteps[0]._index; - } - - // These are carefully ordered for proper z-ordering: - sliderGroup - .call(drawCurrentValue, sliderOpts) - .call(drawRail, sliderOpts) - .call(drawLabelGroup, sliderOpts) - .call(drawTicks, sliderOpts) - .call(drawTouchRect, gd, sliderOpts) - .call(drawGrip, gd, sliderOpts); - - var dims = sliderOpts._dims; - - // Position the rectangle: - Drawing.setTranslate(sliderGroup, dims.lx + sliderOpts.pad.l, dims.ly + sliderOpts.pad.t); - - sliderGroup.call(setGripPosition, sliderOpts, false); - sliderGroup.call(drawCurrentValue, sliderOpts); -} - -function drawCurrentValue(sliderGroup, sliderOpts, valueOverride) { - if(!sliderOpts.currentvalue.visible) return; - - var dims = sliderOpts._dims; - var x0, textAnchor; - - switch(sliderOpts.currentvalue.xanchor) { - case 'right': - // This is anchored left and adjusted by the width of the longest label - // so that the prefix doesn't move. The goal of this is to emphasize - // what's actually changing and make the update less distracting. - x0 = dims.inputAreaLength - constants.currentValueInset - dims.currentValueMaxWidth; - textAnchor = 'left'; - break; - case 'center': - x0 = dims.inputAreaLength * 0.5; - textAnchor = 'middle'; - break; - default: - x0 = constants.currentValueInset; - textAnchor = 'left'; - } - - var text = Lib.ensureSingle(sliderGroup, 'text', constants.labelClass, function(s) { - s.classed('user-select-none', true) - .attr({ - 'text-anchor': textAnchor, - 'data-notex': 1 - }); - }); - - var str = sliderOpts.currentvalue.prefix ? sliderOpts.currentvalue.prefix : ''; - - if(typeof valueOverride === 'string') { - str += valueOverride; - } else { - var curVal = sliderOpts.steps[sliderOpts.active].label; - var _meta = sliderOpts._gd._fullLayout._meta; - if(_meta) curVal = Lib.templateString(curVal, _meta); - str += curVal; - } - - if(sliderOpts.currentvalue.suffix) { - str += sliderOpts.currentvalue.suffix; - } - - text.call(Drawing.font, sliderOpts.currentvalue.font) - .text(str) - .call(svgTextUtils.convertToTspans, sliderOpts._gd); - - var lines = svgTextUtils.lineCount(text); - - var y0 = (dims.currentValueMaxLines + 1 - lines) * - sliderOpts.currentvalue.font.size * LINE_SPACING; - - svgTextUtils.positionText(text, x0, y0); - - return text; -} - -function drawGrip(sliderGroup, gd, sliderOpts) { - var grip = Lib.ensureSingle(sliderGroup, 'rect', constants.gripRectClass, function(s) { - s.call(attachGripEvents, gd, sliderGroup, sliderOpts) - .style('pointer-events', 'all'); - }); - - grip.attr({ - width: constants.gripWidth, - height: constants.gripHeight, - rx: constants.gripRadius, - ry: constants.gripRadius, - }) - .call(Color.stroke, sliderOpts.bordercolor) - .call(Color.fill, sliderOpts.bgcolor) - .style('stroke-width', sliderOpts.borderwidth + 'px'); -} - -function drawLabel(item, data, sliderOpts) { - var text = Lib.ensureSingle(item, 'text', constants.labelClass, function(s) { - s.classed('user-select-none', true) - .attr({ - 'text-anchor': 'middle', - 'data-notex': 1 - }); - }); - - var tx = data.step.label; - var _meta = sliderOpts._gd._fullLayout._meta; - if(_meta) tx = Lib.templateString(tx, _meta); - - text.call(Drawing.font, sliderOpts.font) - .text(tx) - .call(svgTextUtils.convertToTspans, sliderOpts._gd); - - return text; -} - -function drawLabelGroup(sliderGroup, sliderOpts) { - var labels = Lib.ensureSingle(sliderGroup, 'g', constants.labelsClass); - var dims = sliderOpts._dims; - - var labelItems = labels.selectAll('g.' + constants.labelGroupClass) - .data(dims.labelSteps); - - labelItems.enter().append('g') - .classed(constants.labelGroupClass, true); - - labelItems.exit().remove(); - - labelItems.each(function(d) { - var item = d3.select(this); - - item.call(drawLabel, d, sliderOpts); - - Drawing.setTranslate(item, - normalizedValueToPosition(sliderOpts, d.fraction), - constants.tickOffset + - sliderOpts.ticklen + - // position is the baseline of the top line of text only, even - // if the label spans multiple lines - sliderOpts.font.size * LINE_SPACING + - constants.labelOffset + - dims.currentValueTotalHeight - ); - }); -} - -function handleInput(gd, sliderGroup, sliderOpts, normalizedPosition, doTransition) { - var quantizedPosition = Math.round(normalizedPosition * (sliderOpts._stepCount - 1)); - var quantizedIndex = sliderOpts._visibleSteps[quantizedPosition]._index; - - if(quantizedIndex !== sliderOpts.active) { - setActive(gd, sliderGroup, sliderOpts, quantizedIndex, true, doTransition); - } -} - -function setActive(gd, sliderGroup, sliderOpts, index, doCallback, doTransition) { - var previousActive = sliderOpts.active; - sliderOpts.active = index; - - // due to templating, it's possible this slider doesn't even exist yet - arrayEditor(gd.layout, constants.name, sliderOpts) - .applyUpdate('active', index); - - var step = sliderOpts.steps[sliderOpts.active]; - - sliderGroup.call(setGripPosition, sliderOpts, doTransition); - sliderGroup.call(drawCurrentValue, sliderOpts); - - gd.emit('plotly_sliderchange', { - slider: sliderOpts, - step: sliderOpts.steps[sliderOpts.active], - interaction: doCallback, - previousActive: previousActive - }); - - if(step && step.method && doCallback) { - if(sliderGroup._nextMethod) { - // If we've already queued up an update, just overwrite it with the most recent: - sliderGroup._nextMethod.step = step; - sliderGroup._nextMethod.doCallback = doCallback; - sliderGroup._nextMethod.doTransition = doTransition; - } else { - sliderGroup._nextMethod = {step: step, doCallback: doCallback, doTransition: doTransition}; - sliderGroup._nextMethodRaf = window.requestAnimationFrame(function() { - var _step = sliderGroup._nextMethod.step; - if(!_step.method) return; - - if(_step.execute) { - Plots.executeAPICommand(gd, _step.method, _step.args); - } - - sliderGroup._nextMethod = null; - sliderGroup._nextMethodRaf = null; - }); - } - } -} - -function attachGripEvents(item, gd, sliderGroup) { - var node = sliderGroup.node(); - var $gd = d3.select(gd); - - // NB: This is *not* the same as sliderOpts itself! These callbacks - // are in a closure so this array won't actually be correct if the - // steps have changed since this was initialized. The sliderGroup, - // however, has not changed since that *is* the slider, so it must - // be present to receive mouse events. - function getSliderOpts() { - return sliderGroup.data()[0]; - } - - item.on('mousedown', function() { - var sliderOpts = getSliderOpts(); - gd.emit('plotly_sliderstart', {slider: sliderOpts}); - - var grip = sliderGroup.select('.' + constants.gripRectClass); - - d3.event.stopPropagation(); - d3.event.preventDefault(); - grip.call(Color.fill, sliderOpts.activebgcolor); - - var normalizedPosition = positionToNormalizedValue(sliderOpts, d3.mouse(node)[0]); - handleInput(gd, sliderGroup, sliderOpts, normalizedPosition, true); - sliderOpts._dragging = true; - - $gd.on('mousemove', function() { - var sliderOpts = getSliderOpts(); - var normalizedPosition = positionToNormalizedValue(sliderOpts, d3.mouse(node)[0]); - handleInput(gd, sliderGroup, sliderOpts, normalizedPosition, false); - }); - - $gd.on('mouseup', function() { - var sliderOpts = getSliderOpts(); - sliderOpts._dragging = false; - grip.call(Color.fill, sliderOpts.bgcolor); - $gd.on('mouseup', null); - $gd.on('mousemove', null); - - gd.emit('plotly_sliderend', { - slider: sliderOpts, - step: sliderOpts.steps[sliderOpts.active] - }); - }); - }); -} - -function drawTicks(sliderGroup, sliderOpts) { - var tick = sliderGroup.selectAll('rect.' + constants.tickRectClass) - .data(sliderOpts._visibleSteps); - var dims = sliderOpts._dims; - - tick.enter().append('rect') - .classed(constants.tickRectClass, true); - - tick.exit().remove(); - - tick.attr({ - width: sliderOpts.tickwidth + 'px', - 'shape-rendering': 'crispEdges' - }); - - tick.each(function(d, i) { - var isMajor = i % dims.labelStride === 0; - var item = d3.select(this); - - item - .attr({height: isMajor ? sliderOpts.ticklen : sliderOpts.minorticklen}) - .call(Color.fill, isMajor ? sliderOpts.tickcolor : sliderOpts.tickcolor); - - Drawing.setTranslate(item, - normalizedValueToPosition(sliderOpts, i / (sliderOpts._stepCount - 1)) - 0.5 * sliderOpts.tickwidth, - (isMajor ? constants.tickOffset : constants.minorTickOffset) + dims.currentValueTotalHeight - ); - }); -} - -function computeLabelSteps(sliderOpts) { - var dims = sliderOpts._dims; - dims.labelSteps = []; - var nsteps = sliderOpts._stepCount; - - for(var i = 0; i < nsteps; i += dims.labelStride) { - dims.labelSteps.push({ - fraction: i / (nsteps - 1), - step: sliderOpts._visibleSteps[i] - }); - } -} - -function setGripPosition(sliderGroup, sliderOpts, doTransition) { - var grip = sliderGroup.select('rect.' + constants.gripRectClass); - - var quantizedIndex = 0; - for(var i = 0; i < sliderOpts._stepCount; i++) { - if(sliderOpts._visibleSteps[i]._index === sliderOpts.active) { - quantizedIndex = i; - break; - } - } - - var x = normalizedValueToPosition(sliderOpts, quantizedIndex / (sliderOpts._stepCount - 1)); - - // If this is true, then *this component* is already invoking its own command - // and has triggered its own animation. - if(sliderOpts._invokingCommand) return; - - var el = grip; - if(doTransition && sliderOpts.transition.duration > 0) { - el = el.transition() - .duration(sliderOpts.transition.duration) - .ease(sliderOpts.transition.easing); - } - - // Drawing.setTranslate doesn't work here becasue of the transition duck-typing. - // It's also not necessary because there are no other transitions to preserve. - el.attr('transform', 'translate(' + (x - constants.gripWidth * 0.5) + ',' + (sliderOpts._dims.currentValueTotalHeight) + ')'); -} - -// Convert a number from [0-1] to a pixel position relative to the slider group container: -function normalizedValueToPosition(sliderOpts, normalizedPosition) { - var dims = sliderOpts._dims; - return dims.inputAreaStart + constants.stepInset + - (dims.inputAreaLength - 2 * constants.stepInset) * Math.min(1, Math.max(0, normalizedPosition)); -} - -// Convert a position relative to the slider group to a nubmer in [0, 1] -function positionToNormalizedValue(sliderOpts, position) { - var dims = sliderOpts._dims; - return Math.min(1, Math.max(0, (position - constants.stepInset - dims.inputAreaStart) / (dims.inputAreaLength - 2 * constants.stepInset - 2 * dims.inputAreaStart))); -} - -function drawTouchRect(sliderGroup, gd, sliderOpts) { - var dims = sliderOpts._dims; - var rect = Lib.ensureSingle(sliderGroup, 'rect', constants.railTouchRectClass, function(s) { - s.call(attachGripEvents, gd, sliderGroup, sliderOpts) - .style('pointer-events', 'all'); - }); - - rect.attr({ - width: dims.inputAreaLength, - height: Math.max(dims.inputAreaWidth, constants.tickOffset + sliderOpts.ticklen + dims.labelHeight) - }) - .call(Color.fill, sliderOpts.bgcolor) - .attr('opacity', 0); - - Drawing.setTranslate(rect, 0, dims.currentValueTotalHeight); -} - -function drawRail(sliderGroup, sliderOpts) { - var dims = sliderOpts._dims; - var computedLength = dims.inputAreaLength - constants.railInset * 2; - var rect = Lib.ensureSingle(sliderGroup, 'rect', constants.railRectClass); - - rect.attr({ - width: computedLength, - height: constants.railWidth, - rx: constants.railRadius, - ry: constants.railRadius, - 'shape-rendering': 'crispEdges' - }) - .call(Color.stroke, sliderOpts.bordercolor) - .call(Color.fill, sliderOpts.bgcolor) - .style('stroke-width', sliderOpts.borderwidth + 'px'); - - Drawing.setTranslate(rect, - constants.railInset, - (dims.inputAreaWidth - constants.railWidth) * 0.5 + dims.currentValueTotalHeight - ); -} - -},{"../../constants/alignment":688,"../../lib":719,"../../lib/svg_text_utils":743,"../../plot_api/plot_template":757,"../../plots/plots":828,"../color":593,"../drawing":614,"./constants":677,"d3":163}],680:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var constants = _dereq_('./constants'); - -module.exports = { - moduleType: 'component', - name: constants.name, - - layoutAttributes: _dereq_('./attributes'), - supplyLayoutDefaults: _dereq_('./defaults'), - - draw: _dereq_('./draw') -}; - -},{"./attributes":676,"./constants":677,"./defaults":678,"./draw":679}],681:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Plots = _dereq_('../../plots/plots'); -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../drawing'); -var Color = _dereq_('../color'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var interactConstants = _dereq_('../../constants/interactions'); - -module.exports = { - draw: draw -}; - -var numStripRE = / [XY][0-9]* /; - -/** - * Titles - (re)draw titles on the axes and plot: - * @param {DOM element} gd - the graphDiv - * @param {string} titleClass - the css class of this title - * @param {object} options - how and what to draw - * propContainer - the layout object containing `title` and `titlefont` - * attributes that apply to this title - * propName - the full name of the title property (for Plotly.relayout) - * [traceIndex] - include only if this property applies to one trace - * (such as a colorbar title) - then editing pipes to Plotly.restyle - * instead of Plotly.relayout - * placeholder - placeholder text for an empty editable title - * [avoid] {object} - include if this title should move to avoid other elements - * selection - d3 selection of elements to avoid - * side - which direction to move if there is a conflict - * [offsetLeft] - if these elements are subject to a translation - * wrt the title element - * [offsetTop] - * attributes {object} - position and alignment attributes - * x - pixels - * y - pixels - * text-anchor - start|middle|end - * transform {object} - how to transform the title after positioning - * rotate - degrees - * offset - shift up/down in the rotated frame (unused?) - * containerGroup - if an svg element already exists to hold this - * title, include here. Otherwise it will go in fullLayout._infolayer - * _meta {object (optional} - meta key-value to for title with - * Lib.templateString, default to fullLayout._meta, if not provided - * - * @return {selection} d3 selection of title container group - */ -function draw(gd, titleClass, options) { - var cont = options.propContainer; - var prop = options.propName; - var placeholder = options.placeholder; - var traceIndex = options.traceIndex; - var avoid = options.avoid || {}; - var attributes = options.attributes; - var transform = options.transform; - var group = options.containerGroup; - - var fullLayout = gd._fullLayout; - - var opacity = 1; - var isplaceholder = false; - var title = cont.title; - var txt = (title && title.text ? title.text : '').trim(); - - var font = title && title.font ? title.font : {}; - var fontFamily = font.family; - var fontSize = font.size; - var fontColor = font.color; - - // only make this title editable if we positively identify its property - // as one that has editing enabled. - var editAttr; - if(prop === 'title.text') editAttr = 'titleText'; - else if(prop.indexOf('axis') !== -1) editAttr = 'axisTitleText'; - else if(prop.indexOf('colorbar' !== -1)) editAttr = 'colorbarTitleText'; - var editable = gd._context.edits[editAttr]; - - if(txt === '') opacity = 0; - // look for placeholder text while stripping out numbers from eg X2, Y3 - // this is just for backward compatibility with the old version that had - // "Click to enter X2 title" and may have gotten saved in some old plots, - // we don't want this to show up when these are displayed. - else if(txt.replace(numStripRE, ' % ') === placeholder.replace(numStripRE, ' % ')) { - opacity = 0.2; - isplaceholder = true; - if(!editable) txt = ''; - } - - if(options._meta) { - txt = Lib.templateString(txt, options._meta); - } else if(fullLayout._meta) { - txt = Lib.templateString(txt, fullLayout._meta); - } - - var elShouldExist = txt || editable; - - if(!group) { - group = Lib.ensureSingle(fullLayout._infolayer, 'g', 'g-' + titleClass); - } - - var el = group.selectAll('text') - .data(elShouldExist ? [0] : []); - el.enter().append('text'); - el.text(txt) - // this is hacky, but convertToTspans uses the class - // to determine whether to rotate mathJax... - // so we need to clear out any old class and put the - // correct one (only relevant for colorbars, at least - // for now) - ie don't use .classed - .attr('class', titleClass); - el.exit().remove(); - - if(!elShouldExist) return group; - - function titleLayout(titleEl) { - Lib.syncOrAsync([drawTitle, scootTitle], titleEl); - } - - function drawTitle(titleEl) { - var transformVal; - - if(transform) { - transformVal = ''; - if(transform.rotate) { - transformVal += 'rotate(' + [transform.rotate, attributes.x, attributes.y] + ')'; - } - if(transform.offset) { - transformVal += 'translate(0, ' + transform.offset + ')'; - } - } else { - transformVal = null; - } - - titleEl.attr('transform', transformVal); - - titleEl.style({ - 'font-family': fontFamily, - 'font-size': d3.round(fontSize, 2) + 'px', - fill: Color.rgb(fontColor), - opacity: opacity * Color.opacity(fontColor), - 'font-weight': Plots.fontWeight - }) - .attr(attributes) - .call(svgTextUtils.convertToTspans, gd); - - return Plots.previousPromises(gd); - } - - function scootTitle(titleElIn) { - var titleGroup = d3.select(titleElIn.node().parentNode); - - if(avoid && avoid.selection && avoid.side && txt) { - titleGroup.attr('transform', null); - - // move toward avoid.side (= left, right, top, bottom) if needed - // can include pad (pixels, default 2) - var shift = 0; - var backside = { - left: 'right', - right: 'left', - top: 'bottom', - bottom: 'top' - }[avoid.side]; - var shiftSign = (['left', 'top'].indexOf(avoid.side) !== -1) ? - -1 : 1; - var pad = isNumeric(avoid.pad) ? avoid.pad : 2; - var titlebb = Drawing.bBox(titleGroup.node()); - var paperbb = { - left: 0, - top: 0, - right: fullLayout.width, - bottom: fullLayout.height - }; - var maxshift = avoid.maxShift || ( - (paperbb[avoid.side] - titlebb[avoid.side]) * - ((avoid.side === 'left' || avoid.side === 'top') ? -1 : 1)); - // Prevent the title going off the paper - if(maxshift < 0) shift = maxshift; - else { - // so we don't have to offset each avoided element, - // give the title the opposite offset - var offsetLeft = avoid.offsetLeft || 0; - var offsetTop = avoid.offsetTop || 0; - titlebb.left -= offsetLeft; - titlebb.right -= offsetLeft; - titlebb.top -= offsetTop; - titlebb.bottom -= offsetTop; - - // iterate over a set of elements (avoid.selection) - // to avoid collisions with - avoid.selection.each(function() { - var avoidbb = Drawing.bBox(this); - - if(Lib.bBoxIntersect(titlebb, avoidbb, pad)) { - shift = Math.max(shift, shiftSign * ( - avoidbb[avoid.side] - titlebb[backside]) + pad); - } - }); - shift = Math.min(maxshift, shift); - } - if(shift > 0 || maxshift < 0) { - var shiftTemplate = { - left: [-shift, 0], - right: [shift, 0], - top: [0, -shift], - bottom: [0, shift] - }[avoid.side]; - titleGroup.attr('transform', - 'translate(' + shiftTemplate + ')'); - } - } - } - - el.call(titleLayout); - - function setPlaceholder() { - opacity = 0; - isplaceholder = true; - el.text(placeholder) - .on('mouseover.opacity', function() { - d3.select(this).transition() - .duration(interactConstants.SHOW_PLACEHOLDER).style('opacity', 1); - }) - .on('mouseout.opacity', function() { - d3.select(this).transition() - .duration(interactConstants.HIDE_PLACEHOLDER).style('opacity', 0); - }); - } - - if(editable) { - if(!txt) setPlaceholder(); - else el.on('.opacity', null); - - el.call(svgTextUtils.makeEditable, {gd: gd}) - .on('edit', function(text) { - if(traceIndex !== undefined) { - Registry.call('_guiRestyle', gd, prop, text, traceIndex); - } else { - Registry.call('_guiRelayout', gd, prop, text); - } - }) - .on('cancel', function() { - this.text(this.attr('data-unformatted')) - .call(titleLayout); - }) - .on('input', function(d) { - this.text(d || ' ') - .call(svgTextUtils.positionText, attributes.x, attributes.y); - }); - } - el.classed('js-placeholder', isplaceholder); - - return group; -} - -},{"../../constants/interactions":694,"../../lib":719,"../../lib/svg_text_utils":743,"../../plots/plots":828,"../../registry":847,"../color":593,"../drawing":614,"d3":163,"fast-isnumeric":225}],682:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('../../plots/font_attributes'); -var colorAttrs = _dereq_('../color/attributes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var padAttrs = _dereq_('../../plots/pad_attributes'); -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - -var buttonsAttrs = templatedArray('button', { - visible: { - valType: 'boolean', - - - }, - method: { - valType: 'enumerated', - values: ['restyle', 'relayout', 'animate', 'update', 'skip'], - dflt: 'restyle', - - - }, - args: { - valType: 'info_array', - - freeLength: true, - items: [ - {valType: 'any'}, - {valType: 'any'}, - {valType: 'any'} - ], - - }, - label: { - valType: 'string', - - dflt: '', - - }, - execute: { - valType: 'boolean', - - dflt: true, - - } -}); - -module.exports = overrideAll(templatedArray('updatemenu', { - _arrayAttrRegexps: [/^updatemenus\[(0|[1-9][0-9]+)\]\.buttons/], - - visible: { - valType: 'boolean', - - - }, - - type: { - valType: 'enumerated', - values: ['dropdown', 'buttons'], - dflt: 'dropdown', - - - }, - - direction: { - valType: 'enumerated', - values: ['left', 'right', 'up', 'down'], - dflt: 'down', - - - }, - - active: { - valType: 'integer', - - min: -1, - dflt: 0, - - }, - - showactive: { - valType: 'boolean', - - dflt: true, - - }, - - buttons: buttonsAttrs, - - x: { - valType: 'number', - min: -2, - max: 3, - dflt: -0.05, - - - }, - xanchor: { - valType: 'enumerated', - values: ['auto', 'left', 'center', 'right'], - dflt: 'right', - - - }, - y: { - valType: 'number', - min: -2, - max: 3, - dflt: 1, - - - }, - yanchor: { - valType: 'enumerated', - values: ['auto', 'top', 'middle', 'bottom'], - dflt: 'top', - - - }, - - pad: extendFlat(padAttrs({editType: 'arraydraw'}), { - - }), - - font: fontAttrs({ - - }), - - bgcolor: { - valType: 'color', - - - }, - bordercolor: { - valType: 'color', - dflt: colorAttrs.borderLine, - - - }, - borderwidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'arraydraw', - - } -}), 'arraydraw', 'from-root'); - -},{"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plot_api/plot_template":757,"../../plots/font_attributes":793,"../../plots/pad_attributes":827,"../color/attributes":592}],683:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -module.exports = { - - // layout attribute name - name: 'updatemenus', - - // class names - containerClassName: 'updatemenu-container', - headerGroupClassName: 'updatemenu-header-group', - headerClassName: 'updatemenu-header', - headerArrowClassName: 'updatemenu-header-arrow', - dropdownButtonGroupClassName: 'updatemenu-dropdown-button-group', - dropdownButtonClassName: 'updatemenu-dropdown-button', - buttonClassName: 'updatemenu-button', - itemRectClassName: 'updatemenu-item-rect', - itemTextClassName: 'updatemenu-item-text', - - // DOM attribute name in button group keeping track - // of active update menu - menuIndexAttrName: 'updatemenu-active-index', - - // id root pass to Plots.autoMargin - autoMarginIdRoot: 'updatemenu-', - - // options when 'active: -1' - blankHeaderOpts: { label: ' ' }, - - // min item width / height - minWidth: 30, - minHeight: 30, - - // padding around item text - textPadX: 24, - arrowPadX: 16, - - // item rect radii - rx: 2, - ry: 2, - - // item text x offset off left edge - textOffsetX: 12, - - // item text y offset (w.r.t. middle) - textOffsetY: 3, - - // arrow offset off right edge - arrowOffsetX: 4, - - // gap between header and buttons - gapButtonHeader: 5, - - // gap between between buttons - gapButton: 2, - - // color given to active buttons - activeColor: '#F4FAFF', - - // color given to hovered buttons - hoverColor: '#F4FAFF', - - // symbol for menu open arrow - arrowSymbol: { - left: '◄', - right: '►', - up: '▲', - down: '▼' - } -}; - -},{}],684:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); - -var attributes = _dereq_('./attributes'); -var constants = _dereq_('./constants'); - -var name = constants.name; -var buttonAttrs = attributes.buttons; - - -module.exports = function updateMenusDefaults(layoutIn, layoutOut) { - var opts = { - name: name, - handleItemDefaults: menuDefaults - }; - - handleArrayContainerDefaults(layoutIn, layoutOut, opts); -}; - -function menuDefaults(menuIn, menuOut, layoutOut) { - function coerce(attr, dflt) { - return Lib.coerce(menuIn, menuOut, attributes, attr, dflt); - } - - var buttons = handleArrayContainerDefaults(menuIn, menuOut, { - name: 'buttons', - handleItemDefaults: buttonDefaults - }); - - var visible = coerce('visible', buttons.length > 0); - if(!visible) return; - - coerce('active'); - coerce('direction'); - coerce('type'); - coerce('showactive'); - - coerce('x'); - coerce('y'); - Lib.noneOrAll(menuIn, menuOut, ['x', 'y']); - - coerce('xanchor'); - coerce('yanchor'); - - coerce('pad.t'); - coerce('pad.r'); - coerce('pad.b'); - coerce('pad.l'); - - Lib.coerceFont(coerce, 'font', layoutOut.font); - - coerce('bgcolor', layoutOut.paper_bgcolor); - coerce('bordercolor'); - coerce('borderwidth'); -} - -function buttonDefaults(buttonIn, buttonOut) { - function coerce(attr, dflt) { - return Lib.coerce(buttonIn, buttonOut, buttonAttrs, attr, dflt); - } - - var visible = coerce('visible', - (buttonIn.method === 'skip' || Array.isArray(buttonIn.args))); - if(visible) { - coerce('method'); - coerce('args'); - coerce('label'); - coerce('execute'); - } -} - -},{"../../lib":719,"../../plots/array_container_defaults":763,"./attributes":682,"./constants":683}],685:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Plots = _dereq_('../../plots/plots'); -var Color = _dereq_('../color'); -var Drawing = _dereq_('../drawing'); -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var arrayEditor = _dereq_('../../plot_api/plot_template').arrayEditor; - -var LINE_SPACING = _dereq_('../../constants/alignment').LINE_SPACING; - -var constants = _dereq_('./constants'); -var ScrollBox = _dereq_('./scrollbox'); - -module.exports = function draw(gd) { - var fullLayout = gd._fullLayout; - var menuData = Lib.filterVisible(fullLayout[constants.name]); - - /* Update menu data is bound to the header-group. - * The items in the header group are always present. - * - * Upon clicking on a header its corresponding button - * data is bound to the button-group. - * - * We draw all headers in one group before all buttons - * so that the buttons *always* appear above the headers. - * - * Note that only one set of buttons are visible at once. - * - * - * - * - * - * - * - * - * - * ... - * - * - * - * - * ... - */ - - function clearAutoMargin(menuOpts) { - Plots.autoMargin(gd, autoMarginId(menuOpts)); - } - - // draw update menu container - var menus = fullLayout._menulayer - .selectAll('g.' + constants.containerClassName) - .data(menuData.length > 0 ? [0] : []); - - menus.enter().append('g') - .classed(constants.containerClassName, true) - .style('cursor', 'pointer'); - - menus.exit().each(function() { - // Most components don't need to explicitly remove autoMargin, because - // marginPushers does this - but updatemenu updates don't go through - // a full replot so we need to explicitly remove it. - // This is for removing *all* updatemenus, removing individuals is - // handled below, in headerGroups.exit - d3.select(this).selectAll('g.' + constants.headerGroupClassName) - .each(clearAutoMargin); - }).remove(); - - // return early if no update menus are visible - if(menuData.length === 0) return; - - // join header group - var headerGroups = menus.selectAll('g.' + constants.headerGroupClassName) - .data(menuData, keyFunction); - - headerGroups.enter().append('g') - .classed(constants.headerGroupClassName, true); - - // draw dropdown button container - var gButton = Lib.ensureSingle(menus, 'g', constants.dropdownButtonGroupClassName, function(s) { - s.style('pointer-events', 'all'); - }); - - // find dimensions before plotting anything (this mutates menuOpts) - for(var i = 0; i < menuData.length; i++) { - var menuOpts = menuData[i]; - findDimensions(gd, menuOpts); - } - - // setup scrollbox - var scrollBoxId = 'updatemenus' + fullLayout._uid; - var scrollBox = new ScrollBox(gd, gButton, scrollBoxId); - - // remove exiting header, remove dropped buttons and reset margins - if(headerGroups.enter().size()) { - // make sure gButton is on top of all headers - gButton.node().parentNode.appendChild(gButton.node()); - gButton.call(removeAllButtons); - } - - headerGroups.exit().each(function(menuOpts) { - gButton.call(removeAllButtons); - clearAutoMargin(menuOpts); - }).remove(); - - // draw headers! - headerGroups.each(function(menuOpts) { - var gHeader = d3.select(this); - - var _gButton = menuOpts.type === 'dropdown' ? gButton : null; - Plots.manageCommandObserver(gd, menuOpts, menuOpts.buttons, function(data) { - setActive(gd, menuOpts, menuOpts.buttons[data.index], gHeader, _gButton, scrollBox, data.index, true); - }); - - if(menuOpts.type === 'dropdown') { - drawHeader(gd, gHeader, gButton, scrollBox, menuOpts); - - // if this menu is active, update the dropdown container - if(isActive(gButton, menuOpts)) { - drawButtons(gd, gHeader, gButton, scrollBox, menuOpts); - } - } else { - drawButtons(gd, gHeader, null, null, menuOpts); - } - }); -}; - -// Note that '_index' is set at the default step, -// it corresponds to the menu index in the user layout update menu container. -// Because a menu can be set invisible, -// this is a more 'consistent' field than the index in the menuData. -function keyFunction(menuOpts) { - return menuOpts._index; -} - -function isFolded(gButton) { - return +gButton.attr(constants.menuIndexAttrName) === -1; -} - -function isActive(gButton, menuOpts) { - return +gButton.attr(constants.menuIndexAttrName) === menuOpts._index; -} - -function setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex, isSilentUpdate) { - // update 'active' attribute in menuOpts - menuOpts.active = buttonIndex; - - // due to templating, it's possible this slider doesn't even exist yet - arrayEditor(gd.layout, constants.name, menuOpts) - .applyUpdate('active', buttonIndex); - - if(menuOpts.type === 'buttons') { - drawButtons(gd, gHeader, null, null, menuOpts); - } else if(menuOpts.type === 'dropdown') { - // fold up buttons and redraw header - gButton.attr(constants.menuIndexAttrName, '-1'); - - drawHeader(gd, gHeader, gButton, scrollBox, menuOpts); - - if(!isSilentUpdate) { - drawButtons(gd, gHeader, gButton, scrollBox, menuOpts); - } - } -} - -function drawHeader(gd, gHeader, gButton, scrollBox, menuOpts) { - var header = Lib.ensureSingle(gHeader, 'g', constants.headerClassName, function(s) { - s.style('pointer-events', 'all'); - }); - - var dims = menuOpts._dims; - var active = menuOpts.active; - var headerOpts = menuOpts.buttons[active] || constants.blankHeaderOpts; - var posOpts = { y: menuOpts.pad.t, yPad: 0, x: menuOpts.pad.l, xPad: 0, index: 0 }; - var positionOverrides = { - width: dims.headerWidth, - height: dims.headerHeight - }; - - header - .call(drawItem, menuOpts, headerOpts, gd) - .call(setItemPosition, menuOpts, posOpts, positionOverrides); - - // draw drop arrow at the right edge - var arrow = Lib.ensureSingle(gHeader, 'text', constants.headerArrowClassName, function(s) { - s.classed('user-select-none', true) - .attr('text-anchor', 'end') - .call(Drawing.font, menuOpts.font) - .text(constants.arrowSymbol[menuOpts.direction]); - }); - - arrow.attr({ - x: dims.headerWidth - constants.arrowOffsetX + menuOpts.pad.l, - y: dims.headerHeight / 2 + constants.textOffsetY + menuOpts.pad.t - }); - - header.on('click', function() { - gButton.call(removeAllButtons, - String(isActive(gButton, menuOpts) ? -1 : menuOpts._index) - ); - - drawButtons(gd, gHeader, gButton, scrollBox, menuOpts); - }); - - header.on('mouseover', function() { - header.call(styleOnMouseOver); - }); - - header.on('mouseout', function() { - header.call(styleOnMouseOut, menuOpts); - }); - - // translate header group - Drawing.setTranslate(gHeader, dims.lx, dims.ly); -} - -function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) { - // If this is a set of buttons, set pointer events = all since we play - // some minor games with which container is which in order to simplify - // the drawing of *either* buttons or menus - if(!gButton) { - gButton = gHeader; - gButton.attr('pointer-events', 'all'); - } - - var buttonData = (!isFolded(gButton) || menuOpts.type === 'buttons') ? - menuOpts.buttons : - []; - - var klass = menuOpts.type === 'dropdown' ? constants.dropdownButtonClassName : constants.buttonClassName; - - var buttons = gButton.selectAll('g.' + klass) - .data(Lib.filterVisible(buttonData)); - - var enter = buttons.enter().append('g') - .classed(klass, true); - - var exit = buttons.exit(); - - if(menuOpts.type === 'dropdown') { - enter.attr('opacity', '0') - .transition() - .attr('opacity', '1'); - - exit.transition() - .attr('opacity', '0') - .remove(); - } else { - exit.remove(); - } - - var x0 = 0; - var y0 = 0; - var dims = menuOpts._dims; - - var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; - - if(menuOpts.type === 'dropdown') { - if(isVertical) { - y0 = dims.headerHeight + constants.gapButtonHeader; - } else { - x0 = dims.headerWidth + constants.gapButtonHeader; - } - } - - if(menuOpts.type === 'dropdown' && menuOpts.direction === 'up') { - y0 = -constants.gapButtonHeader + constants.gapButton - dims.openHeight; - } - - if(menuOpts.type === 'dropdown' && menuOpts.direction === 'left') { - x0 = -constants.gapButtonHeader + constants.gapButton - dims.openWidth; - } - - var posOpts = { - x: dims.lx + x0 + menuOpts.pad.l, - y: dims.ly + y0 + menuOpts.pad.t, - yPad: constants.gapButton, - xPad: constants.gapButton, - index: 0, - }; - - var scrollBoxPosition = { - l: posOpts.x + menuOpts.borderwidth, - t: posOpts.y + menuOpts.borderwidth - }; - - buttons.each(function(buttonOpts, buttonIndex) { - var button = d3.select(this); - - button - .call(drawItem, menuOpts, buttonOpts, gd) - .call(setItemPosition, menuOpts, posOpts); - - button.on('click', function() { - // skip `dragend` events - if(d3.event.defaultPrevented) return; - - setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex); - - if(buttonOpts.execute) { - Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args); - } - - gd.emit('plotly_buttonclicked', {menu: menuOpts, button: buttonOpts, active: menuOpts.active}); - }); - - button.on('mouseover', function() { - button.call(styleOnMouseOver); - }); - - button.on('mouseout', function() { - button.call(styleOnMouseOut, menuOpts); - buttons.call(styleButtons, menuOpts); - }); - }); - - buttons.call(styleButtons, menuOpts); - - if(isVertical) { - scrollBoxPosition.w = Math.max(dims.openWidth, dims.headerWidth); - scrollBoxPosition.h = posOpts.y - scrollBoxPosition.t; - } else { - scrollBoxPosition.w = posOpts.x - scrollBoxPosition.l; - scrollBoxPosition.h = Math.max(dims.openHeight, dims.headerHeight); - } - - scrollBoxPosition.direction = menuOpts.direction; - - if(scrollBox) { - if(buttons.size()) { - drawScrollBox(gd, gHeader, gButton, scrollBox, menuOpts, scrollBoxPosition); - } else { - hideScrollBox(scrollBox); - } - } -} - -function drawScrollBox(gd, gHeader, gButton, scrollBox, menuOpts, position) { - // enable the scrollbox - var direction = menuOpts.direction; - var isVertical = (direction === 'up' || direction === 'down'); - var dims = menuOpts._dims; - - var active = menuOpts.active; - var translateX, translateY; - var i; - if(isVertical) { - translateY = 0; - for(i = 0; i < active; i++) { - translateY += dims.heights[i] + constants.gapButton; - } - } else { - translateX = 0; - for(i = 0; i < active; i++) { - translateX += dims.widths[i] + constants.gapButton; - } - } - - scrollBox.enable(position, translateX, translateY); - - if(scrollBox.hbar) { - scrollBox.hbar - .attr('opacity', '0') - .transition() - .attr('opacity', '1'); - } - - if(scrollBox.vbar) { - scrollBox.vbar - .attr('opacity', '0') - .transition() - .attr('opacity', '1'); - } -} - -function hideScrollBox(scrollBox) { - var hasHBar = !!scrollBox.hbar; - var hasVBar = !!scrollBox.vbar; - - if(hasHBar) { - scrollBox.hbar - .transition() - .attr('opacity', '0') - .each('end', function() { - hasHBar = false; - if(!hasVBar) scrollBox.disable(); - }); - } - - if(hasVBar) { - scrollBox.vbar - .transition() - .attr('opacity', '0') - .each('end', function() { - hasVBar = false; - if(!hasHBar) scrollBox.disable(); - }); - } -} - -function drawItem(item, menuOpts, itemOpts, gd) { - item.call(drawItemRect, menuOpts) - .call(drawItemText, menuOpts, itemOpts, gd); -} - -function drawItemRect(item, menuOpts) { - var rect = Lib.ensureSingle(item, 'rect', constants.itemRectClassName, function(s) { - s.attr({ - rx: constants.rx, - ry: constants.ry, - 'shape-rendering': 'crispEdges' - }); - }); - - rect.call(Color.stroke, menuOpts.bordercolor) - .call(Color.fill, menuOpts.bgcolor) - .style('stroke-width', menuOpts.borderwidth + 'px'); -} - -function drawItemText(item, menuOpts, itemOpts, gd) { - var text = Lib.ensureSingle(item, 'text', constants.itemTextClassName, function(s) { - s.classed('user-select-none', true) - .attr({ - 'text-anchor': 'start', - 'data-notex': 1 - }); - }); - - var tx = itemOpts.label; - var _meta = gd._fullLayout._meta; - if(_meta) tx = Lib.templateString(tx, _meta); - - text.call(Drawing.font, menuOpts.font) - .text(tx) - .call(svgTextUtils.convertToTspans, gd); -} - -function styleButtons(buttons, menuOpts) { - var active = menuOpts.active; - - buttons.each(function(buttonOpts, i) { - var button = d3.select(this); - - if(i === active && menuOpts.showactive) { - button.select('rect.' + constants.itemRectClassName) - .call(Color.fill, constants.activeColor); - } - }); -} - -function styleOnMouseOver(item) { - item.select('rect.' + constants.itemRectClassName) - .call(Color.fill, constants.hoverColor); -} - -function styleOnMouseOut(item, menuOpts) { - item.select('rect.' + constants.itemRectClassName) - .call(Color.fill, menuOpts.bgcolor); -} - -// find item dimensions (this mutates menuOpts) -function findDimensions(gd, menuOpts) { - var dims = menuOpts._dims = { - width1: 0, - height1: 0, - heights: [], - widths: [], - totalWidth: 0, - totalHeight: 0, - openWidth: 0, - openHeight: 0, - lx: 0, - ly: 0 - }; - - var fakeButtons = Drawing.tester.selectAll('g.' + constants.dropdownButtonClassName) - .data(Lib.filterVisible(menuOpts.buttons)); - - fakeButtons.enter().append('g') - .classed(constants.dropdownButtonClassName, true); - - var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; - - // loop over fake buttons to find width / height - fakeButtons.each(function(buttonOpts, i) { - var button = d3.select(this); - - button.call(drawItem, menuOpts, buttonOpts, gd); - - var text = button.select('.' + constants.itemTextClassName); - - // width is given by max width of all buttons - var tWidth = text.node() && Drawing.bBox(text.node()).width; - var wEff = Math.max(tWidth + constants.textPadX, constants.minWidth); - - // height is determined by item text - var tHeight = menuOpts.font.size * LINE_SPACING; - var tLines = svgTextUtils.lineCount(text); - var hEff = Math.max(tHeight * tLines, constants.minHeight) + constants.textOffsetY; - - hEff = Math.ceil(hEff); - wEff = Math.ceil(wEff); - - // Store per-item sizes since a row of horizontal buttons, for example, - // don't all need to be the same width: - dims.widths[i] = wEff; - dims.heights[i] = hEff; - - // Height and width of individual element: - dims.height1 = Math.max(dims.height1, hEff); - dims.width1 = Math.max(dims.width1, wEff); - - if(isVertical) { - dims.totalWidth = Math.max(dims.totalWidth, wEff); - dims.openWidth = dims.totalWidth; - dims.totalHeight += hEff + constants.gapButton; - dims.openHeight += hEff + constants.gapButton; - } else { - dims.totalWidth += wEff + constants.gapButton; - dims.openWidth += wEff + constants.gapButton; - dims.totalHeight = Math.max(dims.totalHeight, hEff); - dims.openHeight = dims.totalHeight; - } - }); - - if(isVertical) { - dims.totalHeight -= constants.gapButton; - } else { - dims.totalWidth -= constants.gapButton; - } - - - dims.headerWidth = dims.width1 + constants.arrowPadX; - dims.headerHeight = dims.height1; - - if(menuOpts.type === 'dropdown') { - if(isVertical) { - dims.width1 += constants.arrowPadX; - dims.totalHeight = dims.height1; - } else { - dims.totalWidth = dims.width1; - } - dims.totalWidth += constants.arrowPadX; - } - - fakeButtons.remove(); - - var paddedWidth = dims.totalWidth + menuOpts.pad.l + menuOpts.pad.r; - var paddedHeight = dims.totalHeight + menuOpts.pad.t + menuOpts.pad.b; - - var graphSize = gd._fullLayout._size; - dims.lx = graphSize.l + graphSize.w * menuOpts.x; - dims.ly = graphSize.t + graphSize.h * (1 - menuOpts.y); - - var xanchor = 'left'; - if(Lib.isRightAnchor(menuOpts)) { - dims.lx -= paddedWidth; - xanchor = 'right'; - } - if(Lib.isCenterAnchor(menuOpts)) { - dims.lx -= paddedWidth / 2; - xanchor = 'center'; - } - - var yanchor = 'top'; - if(Lib.isBottomAnchor(menuOpts)) { - dims.ly -= paddedHeight; - yanchor = 'bottom'; - } - if(Lib.isMiddleAnchor(menuOpts)) { - dims.ly -= paddedHeight / 2; - yanchor = 'middle'; - } - - dims.totalWidth = Math.ceil(dims.totalWidth); - dims.totalHeight = Math.ceil(dims.totalHeight); - dims.lx = Math.round(dims.lx); - dims.ly = Math.round(dims.ly); - - Plots.autoMargin(gd, autoMarginId(menuOpts), { - x: menuOpts.x, - y: menuOpts.y, - l: paddedWidth * ({right: 1, center: 0.5}[xanchor] || 0), - r: paddedWidth * ({left: 1, center: 0.5}[xanchor] || 0), - b: paddedHeight * ({top: 1, middle: 0.5}[yanchor] || 0), - t: paddedHeight * ({bottom: 1, middle: 0.5}[yanchor] || 0) - }); -} - -function autoMarginId(menuOpts) { - return constants.autoMarginIdRoot + menuOpts._index; -} - -// set item positions (mutates posOpts) -function setItemPosition(item, menuOpts, posOpts, overrideOpts) { - overrideOpts = overrideOpts || {}; - var rect = item.select('.' + constants.itemRectClassName); - var text = item.select('.' + constants.itemTextClassName); - var borderWidth = menuOpts.borderwidth; - var index = posOpts.index; - var dims = menuOpts._dims; - - Drawing.setTranslate(item, borderWidth + posOpts.x, borderWidth + posOpts.y); - - var isVertical = ['up', 'down'].indexOf(menuOpts.direction) !== -1; - var finalHeight = overrideOpts.height || (isVertical ? dims.heights[index] : dims.height1); - - rect.attr({ - x: 0, - y: 0, - width: overrideOpts.width || (isVertical ? dims.width1 : dims.widths[index]), - height: finalHeight - }); - - var tHeight = menuOpts.font.size * LINE_SPACING; - var tLines = svgTextUtils.lineCount(text); - var spanOffset = ((tLines - 1) * tHeight / 2); - - svgTextUtils.positionText(text, constants.textOffsetX, - finalHeight / 2 - spanOffset + constants.textOffsetY); - - if(isVertical) { - posOpts.y += dims.heights[index] + posOpts.yPad; - } else { - posOpts.x += dims.widths[index] + posOpts.xPad; - } - - posOpts.index++; -} - -function removeAllButtons(gButton, newMenuIndexAttr) { - gButton - .attr(constants.menuIndexAttrName, newMenuIndexAttr || '-1') - .selectAll('g.' + constants.dropdownButtonClassName).remove(); -} - -},{"../../constants/alignment":688,"../../lib":719,"../../lib/svg_text_utils":743,"../../plot_api/plot_template":757,"../../plots/plots":828,"../color":593,"../drawing":614,"./constants":683,"./scrollbox":687,"d3":163}],686:[function(_dereq_,module,exports){ -arguments[4][680][0].apply(exports,arguments) -},{"./attributes":682,"./constants":683,"./defaults":684,"./draw":685,"dup":680}],687:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = ScrollBox; - -var d3 = _dereq_('d3'); - -var Color = _dereq_('../color'); -var Drawing = _dereq_('../drawing'); - -var Lib = _dereq_('../../lib'); - -/** - * Helper class to setup a scroll box - * - * @class - * @param gd Plotly's graph div - * @param container Container to be scroll-boxed (as a D3 selection) - * @param {string} id Id for the clip path to implement the scroll box - */ -function ScrollBox(gd, container, id) { - this.gd = gd; - this.container = container; - this.id = id; - - // See ScrollBox.prototype.enable for further definition - this.position = null; // scrollbox position - this.translateX = null; // scrollbox horizontal translation - this.translateY = null; // scrollbox vertical translation - this.hbar = null; // horizontal scrollbar D3 selection - this.vbar = null; // vertical scrollbar D3 selection - - // element to capture pointer events - this.bg = this.container.selectAll('rect.scrollbox-bg').data([0]); - - this.bg.exit() - .on('.drag', null) - .on('wheel', null) - .remove(); - - this.bg.enter().append('rect') - .classed('scrollbox-bg', true) - .style('pointer-events', 'all') - .attr({ - opacity: 0, - x: 0, - y: 0, - width: 0, - height: 0 - }); -} - -// scroll bar dimensions -ScrollBox.barWidth = 2; -ScrollBox.barLength = 20; -ScrollBox.barRadius = 2; -ScrollBox.barPad = 1; -ScrollBox.barColor = '#808BA4'; - -/** - * If needed, setup a clip path and scrollbars - * - * @method - * @param {Object} position - * @param {number} position.l Left side position (in pixels) - * @param {number} position.t Top side (in pixels) - * @param {number} position.w Width (in pixels) - * @param {number} position.h Height (in pixels) - * @param {string} [position.direction='down'] - * Either 'down', 'left', 'right' or 'up' - * @param {number} [translateX=0] Horizontal offset (in pixels) - * @param {number} [translateY=0] Vertical offset (in pixels) - */ -ScrollBox.prototype.enable = function enable(position, translateX, translateY) { - var fullLayout = this.gd._fullLayout; - var fullWidth = fullLayout.width; - var fullHeight = fullLayout.height; - - // compute position of scrollbox - this.position = position; - - var l = this.position.l; - var w = this.position.w; - var t = this.position.t; - var h = this.position.h; - var direction = this.position.direction; - var isDown = (direction === 'down'); - var isLeft = (direction === 'left'); - var isRight = (direction === 'right'); - var isUp = (direction === 'up'); - var boxW = w; - var boxH = h; - var boxL, boxR; - var boxT, boxB; - - if(!isDown && !isLeft && !isRight && !isUp) { - this.position.direction = 'down'; - isDown = true; - } - - var isVertical = isDown || isUp; - if(isVertical) { - boxL = l; - boxR = boxL + boxW; - - if(isDown) { - // anchor to top side - boxT = t; - boxB = Math.min(boxT + boxH, fullHeight); - boxH = boxB - boxT; - } else { - // anchor to bottom side - boxB = t + boxH; - boxT = Math.max(boxB - boxH, 0); - boxH = boxB - boxT; - } - } else { - boxT = t; - boxB = boxT + boxH; - - if(isLeft) { - // anchor to right side - boxR = l + boxW; - boxL = Math.max(boxR - boxW, 0); - boxW = boxR - boxL; - } else { - // anchor to left side - boxL = l; - boxR = Math.min(boxL + boxW, fullWidth); - boxW = boxR - boxL; - } - } - - this._box = { - l: boxL, - t: boxT, - w: boxW, - h: boxH - }; - - // compute position of horizontal scroll bar - var needsHorizontalScrollBar = (w > boxW); - var hbarW = ScrollBox.barLength + 2 * ScrollBox.barPad; - var hbarH = ScrollBox.barWidth + 2 * ScrollBox.barPad; - // draw horizontal scrollbar on the bottom side - var hbarL = l; - var hbarT = t + h; - - if(hbarT + hbarH > fullHeight) hbarT = fullHeight - hbarH; - - var hbar = this.container.selectAll('rect.scrollbar-horizontal').data( - (needsHorizontalScrollBar) ? [0] : []); - - hbar.exit() - .on('.drag', null) - .remove(); - - hbar.enter().append('rect') - .classed('scrollbar-horizontal', true) - .call(Color.fill, ScrollBox.barColor); - - if(needsHorizontalScrollBar) { - this.hbar = hbar.attr({ - 'rx': ScrollBox.barRadius, - 'ry': ScrollBox.barRadius, - 'x': hbarL, - 'y': hbarT, - 'width': hbarW, - 'height': hbarH - }); - - // hbar center moves between hbarXMin and hbarXMin + hbarTranslateMax - this._hbarXMin = hbarL + hbarW / 2; - this._hbarTranslateMax = boxW - hbarW; - } else { - delete this.hbar; - delete this._hbarXMin; - delete this._hbarTranslateMax; - } - - // compute position of vertical scroll bar - var needsVerticalScrollBar = (h > boxH); - var vbarW = ScrollBox.barWidth + 2 * ScrollBox.barPad; - var vbarH = ScrollBox.barLength + 2 * ScrollBox.barPad; - // draw vertical scrollbar on the right side - var vbarL = l + w; - var vbarT = t; - - if(vbarL + vbarW > fullWidth) vbarL = fullWidth - vbarW; - - var vbar = this.container.selectAll('rect.scrollbar-vertical').data( - (needsVerticalScrollBar) ? [0] : []); - - vbar.exit() - .on('.drag', null) - .remove(); - - vbar.enter().append('rect') - .classed('scrollbar-vertical', true) - .call(Color.fill, ScrollBox.barColor); - - if(needsVerticalScrollBar) { - this.vbar = vbar.attr({ - 'rx': ScrollBox.barRadius, - 'ry': ScrollBox.barRadius, - 'x': vbarL, - 'y': vbarT, - 'width': vbarW, - 'height': vbarH - }); - - // vbar center moves between vbarYMin and vbarYMin + vbarTranslateMax - this._vbarYMin = vbarT + vbarH / 2; - this._vbarTranslateMax = boxH - vbarH; - } else { - delete this.vbar; - delete this._vbarYMin; - delete this._vbarTranslateMax; - } - - // setup a clip path (if scroll bars are needed) - var clipId = this.id; - var clipL = boxL - 0.5; - var clipR = (needsVerticalScrollBar) ? boxR + vbarW + 0.5 : boxR + 0.5; - var clipT = boxT - 0.5; - var clipB = (needsHorizontalScrollBar) ? boxB + hbarH + 0.5 : boxB + 0.5; - - var clipPath = fullLayout._topdefs.selectAll('#' + clipId) - .data((needsHorizontalScrollBar || needsVerticalScrollBar) ? [0] : []); - - clipPath.exit().remove(); - - clipPath.enter() - .append('clipPath').attr('id', clipId) - .append('rect'); - - if(needsHorizontalScrollBar || needsVerticalScrollBar) { - this._clipRect = clipPath.select('rect').attr({ - x: Math.floor(clipL), - y: Math.floor(clipT), - width: Math.ceil(clipR) - Math.floor(clipL), - height: Math.ceil(clipB) - Math.floor(clipT) - }); - - this.container.call(Drawing.setClipUrl, clipId, this.gd); - - this.bg.attr({ - x: l, - y: t, - width: w, - height: h - }); - } else { - this.bg.attr({ - width: 0, - height: 0 - }); - this.container - .on('wheel', null) - .on('.drag', null) - .call(Drawing.setClipUrl, null); - delete this._clipRect; - } - - // set up drag listeners (if scroll bars are needed) - if(needsHorizontalScrollBar || needsVerticalScrollBar) { - var onBoxDrag = d3.behavior.drag() - .on('dragstart', function() { - d3.event.sourceEvent.preventDefault(); - }) - .on('drag', this._onBoxDrag.bind(this)); - - this.container - .on('wheel', null) - .on('wheel', this._onBoxWheel.bind(this)) - .on('.drag', null) - .call(onBoxDrag); - - var onBarDrag = d3.behavior.drag() - .on('dragstart', function() { - d3.event.sourceEvent.preventDefault(); - d3.event.sourceEvent.stopPropagation(); - }) - .on('drag', this._onBarDrag.bind(this)); - - if(needsHorizontalScrollBar) { - this.hbar - .on('.drag', null) - .call(onBarDrag); - } - - if(needsVerticalScrollBar) { - this.vbar - .on('.drag', null) - .call(onBarDrag); - } - } - - // set scrollbox translation - this.setTranslate(translateX, translateY); -}; - -/** - * If present, remove clip-path and scrollbars - * - * @method - */ -ScrollBox.prototype.disable = function disable() { - if(this.hbar || this.vbar) { - this.bg.attr({ - width: 0, - height: 0 - }); - this.container - .on('wheel', null) - .on('.drag', null) - .call(Drawing.setClipUrl, null); - delete this._clipRect; - } - - if(this.hbar) { - this.hbar.on('.drag', null); - this.hbar.remove(); - delete this.hbar; - delete this._hbarXMin; - delete this._hbarTranslateMax; - } - - if(this.vbar) { - this.vbar.on('.drag', null); - this.vbar.remove(); - delete this.vbar; - delete this._vbarYMin; - delete this._vbarTranslateMax; - } -}; - -/** - * Handles scroll box drag events - * - * @method - */ -ScrollBox.prototype._onBoxDrag = function _onBoxDrag() { - var translateX = this.translateX; - var translateY = this.translateY; - - if(this.hbar) { - translateX -= d3.event.dx; - } - - if(this.vbar) { - translateY -= d3.event.dy; - } - - this.setTranslate(translateX, translateY); -}; - -/** - * Handles scroll box wheel events - * - * @method - */ -ScrollBox.prototype._onBoxWheel = function _onBoxWheel() { - var translateX = this.translateX; - var translateY = this.translateY; - - if(this.hbar) { - translateX += d3.event.deltaY; - } - - if(this.vbar) { - translateY += d3.event.deltaY; - } - - this.setTranslate(translateX, translateY); -}; - -/** - * Handles scroll bar drag events - * - * @method - */ -ScrollBox.prototype._onBarDrag = function _onBarDrag() { - var translateX = this.translateX; - var translateY = this.translateY; - - if(this.hbar) { - var xMin = translateX + this._hbarXMin; - var xMax = xMin + this._hbarTranslateMax; - var x = Lib.constrain(d3.event.x, xMin, xMax); - var xf = (x - xMin) / (xMax - xMin); - - var translateXMax = this.position.w - this._box.w; - - translateX = xf * translateXMax; - } - - if(this.vbar) { - var yMin = translateY + this._vbarYMin; - var yMax = yMin + this._vbarTranslateMax; - var y = Lib.constrain(d3.event.y, yMin, yMax); - var yf = (y - yMin) / (yMax - yMin); - - var translateYMax = this.position.h - this._box.h; - - translateY = yf * translateYMax; - } - - this.setTranslate(translateX, translateY); -}; - -/** - * Set clip path and scroll bar translate transform - * - * @method - * @param {number} [translateX=0] Horizontal offset (in pixels) - * @param {number} [translateY=0] Vertical offset (in pixels) - */ -ScrollBox.prototype.setTranslate = function setTranslate(translateX, translateY) { - // store translateX and translateY (needed by mouse event handlers) - var translateXMax = this.position.w - this._box.w; - var translateYMax = this.position.h - this._box.h; - - translateX = Lib.constrain(translateX || 0, 0, translateXMax); - translateY = Lib.constrain(translateY || 0, 0, translateYMax); - - this.translateX = translateX; - this.translateY = translateY; - - this.container.call(Drawing.setTranslate, - this._box.l - this.position.l - translateX, - this._box.t - this.position.t - translateY); - - if(this._clipRect) { - this._clipRect.attr({ - x: Math.floor(this.position.l + translateX - 0.5), - y: Math.floor(this.position.t + translateY - 0.5) - }); - } - - if(this.hbar) { - var xf = translateX / translateXMax; - - this.hbar.call(Drawing.setTranslate, - translateX + xf * this._hbarTranslateMax, - translateY); - } - - if(this.vbar) { - var yf = translateY / translateYMax; - - this.vbar.call(Drawing.setTranslate, - translateX, - translateY + yf * this._vbarTranslateMax); - } -}; - -},{"../../lib":719,"../color":593,"../drawing":614,"d3":163}],688:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -// fraction of some size to get to a named position -module.exports = { - // from bottom left: this is the origin of our paper-reference - // positioning system - FROM_BL: { - left: 0, - center: 0.5, - right: 1, - bottom: 0, - middle: 0.5, - top: 1 - }, - // from top left: this is the screen pixel positioning origin - FROM_TL: { - left: 0, - center: 0.5, - right: 1, - bottom: 1, - middle: 0.5, - top: 0 - }, - // from bottom right: sometimes you just need the opposite of ^^ - FROM_BR: { - left: 1, - center: 0.5, - right: 0, - bottom: 0, - middle: 0.5, - top: 1 - }, - // multiple of fontSize to get the vertical offset between lines - LINE_SPACING: 1.3, - - // multiple of fontSize to shift from the baseline - // to the cap (captical letter) line - // (to use when we don't calculate this shift from Drawing.bBox) - // This is an approximation since in reality cap height can differ - // from font to font. However, according to Wikipedia - // an "average" font might have a cap height of 70% of the em - // https://en.wikipedia.org/wiki/Em_(typography)#History - CAP_SHIFT: 0.70, - - // half the cap height (distance between baseline and cap line) - // of an "average" font (for more info see above). - MID_SHIFT: 0.35, - - OPPOSITE_SIDE: { - left: 'right', - right: 'left', - top: 'bottom', - bottom: 'top' - } -}; - -},{}],689:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - INCREASING: { - COLOR: '#3D9970', - SYMBOL: '▲' - }, - DECREASING: { - COLOR: '#FF4136', - SYMBOL: '▼' - } -}; - -},{}],690:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - FORMAT_LINK: 'https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#d3_format', - DATE_FORMAT_LINK: 'https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md#format' -}; - -},{}],691:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - COMPARISON_OPS: ['=', '!=', '<', '>=', '>', '<='], - COMPARISON_OPS2: ['=', '<', '>=', '>', '<='], - INTERVAL_OPS: ['[]', '()', '[)', '(]', '][', ')(', '](', ')['], - SET_OPS: ['{}', '}{'], - CONSTRAINT_REDUCTION: { - // for contour constraints, open/closed endpoints are equivalent - '=': '=', - - '<': '<', - '<=': '<', - - '>': '>', - '>=': '>', - - '[]': '[]', - '()': '[]', - '[)': '[]', - '(]': '[]', - - '][': '][', - ')(': '][', - '](': '][', - ')[': '][' - } -}; - -},{}],692:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = { - solid: [[], 0], - dot: [[0.5, 1], 200], - dash: [[0.5, 1], 50], - longdash: [[0.5, 1], 10], - dashdot: [[0.5, 0.625, 0.875, 1], 50], - longdashdot: [[0.5, 0.7, 0.8, 1], 10] -}; - -},{}],693:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = { - circle: '●', - 'circle-open': '○', - square: '■', - 'square-open': '□', - diamond: '◆', - 'diamond-open': '◇', - cross: '+', - x: '❌' -}; - -},{}],694:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -module.exports = { - /** - * Timing information for interactive elements - */ - SHOW_PLACEHOLDER: 100, - HIDE_PLACEHOLDER: 1000, - - // opacity dimming fraction for points that are not in selection - DESELECTDIM: 0.2 -}; - -},{}],695:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -module.exports = { - /** - * Standardize all missing data in calcdata to use undefined - * never null or NaN. - * That way we can use !==undefined, or !== BADNUM, - * to test for real data - */ - BADNUM: undefined, - - /* - * Limit certain operations to well below floating point max value - * to avoid glitches: Make sure that even when you multiply it by the - * number of pixels on a giant screen it still works - */ - FP_SAFE: Number.MAX_VALUE / 10000, - - /* - * conversion of date units to milliseconds - * year and month constants are marked "AVG" - * to remind us that not all years and months - * have the same length - */ - ONEAVGYEAR: 31557600000, // 365.25 days - ONEAVGMONTH: 2629800000, // 1/12 of ONEAVGYEAR - ONEDAY: 86400000, - ONEHOUR: 3600000, - ONEMIN: 60000, - ONESEC: 1000, - - /* - * For fast conversion btwn world calendars and epoch ms, the Julian Day Number - * of the unix epoch. From calendars.instance().newDate(1970, 1, 1).toJD() - */ - EPOCHJD: 2440587.5, - - /* - * Are two values nearly equal? Compare to 1PPM - */ - ALMOST_EQUAL: 1 - 1e-6, - - /* - * If we're asked to clip a non-positive log value, how far off-screen - * do we put it? - */ - LOG_CLIP: 10, - - /* - * not a number, but for displaying numbers: the "minus sign" symbol is - * wider than the regular ascii dash "-" - */ - MINUS_SIGN: '\u2212' -}; - -},{}],696:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -exports.xmlns = 'http://www.w3.org/2000/xmlns/'; -exports.svg = 'http://www.w3.org/2000/svg'; -exports.xlink = 'http://www.w3.org/1999/xlink'; - -// the 'old' d3 quirk got fix in v3.5.7 -// https://github.com/mbostock/d3/commit/a6f66e9dd37f764403fc7c1f26be09ab4af24fed -exports.svgAttrs = { - xmlns: exports.svg, - 'xmlns:xlink': exports.xlink -}; - -},{}],697:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -// package version injected by `npm run preprocess` -exports.version = '1.49.1'; - -// inject promise polyfill -_dereq_('es6-promise').polyfill(); - -// inject plot css -_dereq_('../build/plotcss'); - -// inject default MathJax config -_dereq_('./fonts/mathjax_config')(); - -// include registry module and expose register method -var Registry = _dereq_('./registry'); -var register = exports.register = Registry.register; - -// expose plot api methods -var plotApi = _dereq_('./plot_api'); -var methodNames = Object.keys(plotApi); -for(var i = 0; i < methodNames.length; i++) { - var name = methodNames[i]; - // _ -> private API methods, but still registered for internal use - if(name.charAt(0) !== '_') exports[name] = plotApi[name]; - register({ - moduleType: 'apiMethod', - name: name, - fn: plotApi[name] - }); -} - -// scatter is the only trace included by default -register(_dereq_('./traces/scatter')); - -// register all registrable components modules -register([ - _dereq_('./components/fx'), - _dereq_('./components/legend'), - _dereq_('./components/annotations'), - _dereq_('./components/annotations3d'), - _dereq_('./components/shapes'), - _dereq_('./components/images'), - _dereq_('./components/updatemenus'), - _dereq_('./components/sliders'), - _dereq_('./components/rangeslider'), - _dereq_('./components/rangeselector'), - _dereq_('./components/grid'), - _dereq_('./components/errorbars'), - _dereq_('./components/colorscale'), - _dereq_('./components/colorbar') -]); - -// locales en and en-US are required for default behavior -register([ - _dereq_('./locale-en'), - _dereq_('./locale-en-us') -]); - -// plot icons -exports.Icons = _dereq_('./fonts/ploticon'); - -// unofficial 'beta' plot methods, use at your own risk -exports.Plots = _dereq_('./plots/plots'); -exports.Fx = _dereq_('./components/fx'); -exports.Snapshot = _dereq_('./snapshot'); -exports.PlotSchema = _dereq_('./plot_api/plot_schema'); -exports.Queue = _dereq_('./lib/queue'); - -// export d3 used in the bundle -exports.d3 = _dereq_('d3'); - -},{"../build/plotcss":1,"./components/annotations":584,"./components/annotations3d":589,"./components/colorbar":599,"./components/colorscale":605,"./components/errorbars":620,"./components/fx":632,"./components/grid":636,"./components/images":641,"./components/legend":649,"./components/rangeselector":660,"./components/rangeslider":667,"./components/shapes":675,"./components/sliders":680,"./components/updatemenus":686,"./fonts/mathjax_config":698,"./fonts/ploticon":699,"./lib/queue":734,"./locale-en":748,"./locale-en-us":747,"./plot_api":752,"./plot_api/plot_schema":756,"./plots/plots":828,"./registry":847,"./snapshot":852,"./traces/scatter":1123,"d3":163,"es6-promise":218}],698:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* global MathJax:false */ - -module.exports = function() { - if(typeof MathJax !== 'undefined') { - var globalConfig = (window.PlotlyConfig || {}).MathJaxConfig !== 'local'; - - if(globalConfig) { - MathJax.Hub.Config({ - messageStyle: 'none', - skipStartupTypeset: true, - displayAlign: 'left', - tex2jax: { - inlineMath: [['$', '$'], ['\\(', '\\)']] - } - }); - MathJax.Hub.Configured(); - } - } -}; - -},{}],699:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - 'undo': { - 'width': 857.1, - 'height': 1000, - 'path': 'm857 350q0-87-34-166t-91-137-137-92-166-34q-96 0-183 41t-147 114q-4 6-4 13t5 11l76 77q6 5 14 5 9-1 13-7 41-53 100-82t126-29q58 0 110 23t92 61 61 91 22 111-22 111-61 91-92 61-110 23q-55 0-105-20t-90-57l77-77q17-16 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l72-72q60 57 137 88t159 31q87 0 166-34t137-92 91-137 34-166z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'home': { - 'width': 928.6, - 'height': 1000, - 'path': 'm786 296v-267q0-15-11-26t-25-10h-214v214h-143v-214h-214q-15 0-25 10t-11 26v267q0 1 0 2t0 2l321 264 321-264q1-1 1-4z m124 39l-34-41q-5-5-12-6h-2q-7 0-12 3l-386 322-386-322q-7-4-13-4-7 2-12 7l-35 41q-4 5-3 13t6 12l401 334q18 15 42 15t43-15l136-114v109q0 8 5 13t13 5h107q8 0 13-5t5-13v-227l122-102q5-5 6-12t-4-13z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'camera-retro': { - 'width': 1000, - 'height': 1000, - 'path': 'm518 386q0 8-5 13t-13 5q-37 0-63-27t-26-63q0-8 5-13t13-5 12 5 5 13q0 23 16 38t38 16q8 0 13 5t5 13z m125-73q0-59-42-101t-101-42-101 42-42 101 42 101 101 42 101-42 42-101z m-572-320h858v71h-858v-71z m643 320q0 89-62 152t-152 62-151-62-63-152 63-151 151-63 152 63 62 151z m-571 358h214v72h-214v-72z m-72-107h858v143h-462l-36-71h-360v-72z m929 143v-714q0-30-21-51t-50-21h-858q-29 0-50 21t-21 51v714q0 30 21 51t50 21h858q29 0 50-21t21-51z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'zoombox': { - 'width': 1000, - 'height': 1000, - 'path': 'm1000-25l-250 251c40 63 63 138 63 218 0 224-182 406-407 406-224 0-406-182-406-406s183-406 407-406c80 0 155 22 218 62l250-250 125 125z m-812 250l0 438 437 0 0-438-437 0z m62 375l313 0 0-312-313 0 0 312z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'pan': { - 'width': 1000, - 'height': 1000, - 'path': 'm1000 350l-187 188 0-125-250 0 0 250 125 0-188 187-187-187 125 0 0-250-250 0 0 125-188-188 186-187 0 125 252 0 0-250-125 0 187-188 188 188-125 0 0 250 250 0 0-126 187 188z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'zoom_plus': { - 'width': 875, - 'height': 1000, - 'path': 'm1 787l0-875 875 0 0 875-875 0z m687-500l-187 0 0-187-125 0 0 187-188 0 0 125 188 0 0 187 125 0 0-187 187 0 0-125z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'zoom_minus': { - 'width': 875, - 'height': 1000, - 'path': 'm0 788l0-876 875 0 0 876-875 0z m688-500l-500 0 0 125 500 0 0-125z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'autoscale': { - 'width': 1000, - 'height': 1000, - 'path': 'm250 850l-187 0-63 0 0-62 0-188 63 0 0 188 187 0 0 62z m688 0l-188 0 0-62 188 0 0-188 62 0 0 188 0 62-62 0z m-875-938l0 188-63 0 0-188 0-62 63 0 187 0 0 62-187 0z m875 188l0-188-188 0 0-62 188 0 62 0 0 62 0 188-62 0z m-125 188l-1 0-93-94-156 156 156 156 92-93 2 0 0 250-250 0 0-2 93-92-156-156-156 156 94 92 0 2-250 0 0-250 0 0 93 93 157-156-157-156-93 94 0 0 0-250 250 0 0 0-94 93 156 157 156-157-93-93 0 0 250 0 0 250z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'tooltip_basic': { - 'width': 1500, - 'height': 1000, - 'path': 'm375 725l0 0-375-375 375-374 0-1 1125 0 0 750-1125 0z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'tooltip_compare': { - 'width': 1125, - 'height': 1000, - 'path': 'm187 786l0 2-187-188 188-187 0 0 937 0 0 373-938 0z m0-499l0 1-187-188 188-188 0 0 937 0 0 376-938-1z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'plotlylogo': { - 'width': 1542, - 'height': 1000, - 'path': 'm0-10h182v-140h-182v140z m228 146h183v-286h-183v286z m225 714h182v-1000h-182v1000z m225-285h182v-715h-182v715z m225 142h183v-857h-183v857z m231-428h182v-429h-182v429z m225-291h183v-138h-183v138z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'z-axis': { - 'width': 1000, - 'height': 1000, - 'path': 'm833 5l-17 108v41l-130-65 130-66c0 0 0 38 0 39 0-1 36-14 39-25 4-15-6-22-16-30-15-12-39-16-56-20-90-22-187-23-279-23-261 0-341 34-353 59 3 60 228 110 228 110-140-8-351-35-351-116 0-120 293-142 474-142 155 0 477 22 477 142 0 50-74 79-163 96z m-374 94c-58-5-99-21-99-40 0-24 65-43 144-43 79 0 143 19 143 43 0 19-42 34-98 40v216h87l-132 135-133-135h88v-216z m167 515h-136v1c16 16 31 34 46 52l84 109v54h-230v-71h124v-1c-16-17-28-32-44-51l-89-114v-51h245v72z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - '3d_rotate': { - 'width': 1000, - 'height': 1000, - 'path': 'm922 660c-5 4-9 7-14 11-359 263-580-31-580-31l-102 28 58-400c0 1 1 1 2 2 118 108 351 249 351 249s-62 27-100 42c88 83 222 183 347 122 16-8 30-17 44-27-2 1-4 2-6 4z m36-329c0 0 64 229-88 296-62 27-124 14-175-11 157-78 225-208 249-266 8-19 11-31 11-31 2 5 6 15 11 32-5-13-8-20-8-20z m-775-239c70-31 117-50 198-32-121 80-199 346-199 346l-96-15-58-12c0 0 55-226 155-287z m603 133l-317-139c0 0 4-4 19-14 7-5 24-15 24-15s-177-147-389 4c235-287 536-112 536-112l31-22 100 299-4-1z m-298-153c6-4 14-9 24-15 0 0-17 10-24 15z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'camera': { - 'width': 1000, - 'height': 1000, - 'path': 'm500 450c-83 0-150-67-150-150 0-83 67-150 150-150 83 0 150 67 150 150 0 83-67 150-150 150z m400 150h-120c-16 0-34 13-39 29l-31 93c-6 15-23 28-40 28h-340c-16 0-34-13-39-28l-31-94c-6-15-23-28-40-28h-120c-55 0-100-45-100-100v-450c0-55 45-100 100-100h800c55 0 100 45 100 100v450c0 55-45 100-100 100z m-400-550c-138 0-250 112-250 250 0 138 112 250 250 250 138 0 250-112 250-250 0-138-112-250-250-250z m365 380c-19 0-35 16-35 35 0 19 16 35 35 35 19 0 35-16 35-35 0-19-16-35-35-35z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'movie': { - 'width': 1000, - 'height': 1000, - 'path': 'm938 413l-188-125c0 37-17 71-44 94 64 38 107 107 107 187 0 121-98 219-219 219-121 0-219-98-219-219 0-61 25-117 66-156h-115c30 33 49 76 49 125 0 103-84 187-187 187s-188-84-188-187c0-57 26-107 65-141-38-22-65-62-65-109v-250c0-70 56-126 125-126h500c69 0 125 56 125 126l188-126c34 0 62 28 62 63v375c0 35-28 63-62 63z m-750 0c-69 0-125 56-125 125s56 125 125 125 125-56 125-125-56-125-125-125z m406-1c-87 0-157 70-157 157 0 86 70 156 157 156s156-70 156-156-70-157-156-157z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'question': { - 'width': 857.1, - 'height': 1000, - 'path': 'm500 82v107q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h107q8 0 13 5t5 13z m143 375q0 49-31 91t-77 65-95 23q-136 0-207-119-9-14 4-24l74-55q4-4 10-4 9 0 14 7 30 38 48 51 19 14 48 14 27 0 48-15t21-33q0-21-11-34t-38-25q-35-16-65-48t-29-70v-20q0-8 5-13t13-5h107q8 0 13 5t5 13q0 10 12 27t30 28q18 10 28 16t25 19 25 27 16 34 7 45z m214-107q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'disk': { - 'width': 857.1, - 'height': 1000, - 'path': 'm214-7h429v214h-429v-214z m500 0h72v500q0 8-6 21t-11 20l-157 156q-5 6-19 12t-22 5v-232q0-22-15-38t-38-16h-322q-22 0-37 16t-16 38v232h-72v-714h72v232q0 22 16 38t37 16h465q22 0 38-16t15-38v-232z m-214 518v178q0 8-5 13t-13 5h-107q-7 0-13-5t-5-13v-178q0-8 5-13t13-5h107q7 0 13 5t5 13z m357-18v-518q0-22-15-38t-38-16h-750q-23 0-38 16t-16 38v750q0 22 16 38t38 16h517q23 0 50-12t42-26l156-157q16-15 27-42t11-49z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'lasso': { - 'width': 1031, - 'height': 1000, - 'path': 'm1018 538c-36 207-290 336-568 286-277-48-473-256-436-463 10-57 36-108 76-151-13-66 11-137 68-183 34-28 75-41 114-42l-55-70 0 0c-2-1-3-2-4-3-10-14-8-34 5-45 14-11 34-8 45 4 1 1 2 3 2 5l0 0 113 140c16 11 31 24 45 40 4 3 6 7 8 11 48-3 100 0 151 9 278 48 473 255 436 462z m-624-379c-80 14-149 48-197 96 42 42 109 47 156 9 33-26 47-66 41-105z m-187-74c-19 16-33 37-39 60 50-32 109-55 174-68-42-25-95-24-135 8z m360 75c-34-7-69-9-102-8 8 62-16 128-68 170-73 59-175 54-244-5-9 20-16 40-20 61-28 159 121 317 333 354s407-60 434-217c28-159-121-318-333-355z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'selectbox': { - 'width': 1000, - 'height': 1000, - 'path': 'm0 850l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-285l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z', - 'transform': 'matrix(1 0 0 -1 0 850)' - }, - 'spikeline': { - 'width': 1000, - 'height': 1000, - 'path': 'M512 409c0-57-46-104-103-104-57 0-104 47-104 104 0 57 47 103 104 103 57 0 103-46 103-103z m-327-39l92 0 0 92-92 0z m-185 0l92 0 0 92-92 0z m370-186l92 0 0 93-92 0z m0-184l92 0 0 92-92 0z', - 'transform': 'matrix(1.5 0 0 -1.5 0 850)' - }, - 'pencil': { - 'width': 1792, - 'height': 1792, - 'path': 'M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z', - 'transform': 'matrix(1 0 0 1 0 1)' - }, - 'newplotlylogo': { - 'name': 'newplotlylogo', - 'svg': 'plotly-logomark' - } -}; - -},{}],700:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -/** - * Determine the position anchor property of x/y xanchor/yanchor components. - * - * - values < 1/3 align the low side at that fraction, - * - values [1/3, 2/3] align the center at that fraction, - * - values > 2/3 align the right at that fraction. - */ - - -exports.isLeftAnchor = function isLeftAnchor(opts) { - return ( - opts.xanchor === 'left' || - (opts.xanchor === 'auto' && opts.x <= 1 / 3) - ); -}; - -exports.isCenterAnchor = function isCenterAnchor(opts) { - return ( - opts.xanchor === 'center' || - (opts.xanchor === 'auto' && opts.x > 1 / 3 && opts.x < 2 / 3) - ); -}; - -exports.isRightAnchor = function isRightAnchor(opts) { - return ( - opts.xanchor === 'right' || - (opts.xanchor === 'auto' && opts.x >= 2 / 3) - ); -}; - -exports.isTopAnchor = function isTopAnchor(opts) { - return ( - opts.yanchor === 'top' || - (opts.yanchor === 'auto' && opts.y >= 2 / 3) - ); -}; - -exports.isMiddleAnchor = function isMiddleAnchor(opts) { - return ( - opts.yanchor === 'middle' || - (opts.yanchor === 'auto' && opts.y > 1 / 3 && opts.y < 2 / 3) - ); -}; - -exports.isBottomAnchor = function isBottomAnchor(opts) { - return ( - opts.yanchor === 'bottom' || - (opts.yanchor === 'auto' && opts.y <= 1 / 3) - ); -}; - -},{}],701:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var modModule = _dereq_('./mod'); -var mod = modModule.mod; -var modHalf = modModule.modHalf; - -var PI = Math.PI; -var twoPI = 2 * PI; - -function deg2rad(deg) { return deg / 180 * PI; } - -function rad2deg(rad) { return rad / PI * 180; } - -/** - * is sector a full circle? - * ... this comes up a lot in SVG path-drawing routines - * - * N.B. we consider all sectors that span more that 2pi 'full' circles - * - * @param {2-item array} aBnds : angular bounds in *radians* - * @return {boolean} - */ -function isFullCircle(aBnds) { - return Math.abs(aBnds[1] - aBnds[0]) > twoPI - 1e-14; -} - -/** - * angular delta between angle 'a' and 'b' - * solution taken from: https://stackoverflow.com/a/2007279 - * - * @param {number} a : first angle in *radians* - * @param {number} b : second angle in *radians* - * @return {number} angular delta in *radians* - */ -function angleDelta(a, b) { - return modHalf(b - a, twoPI); -} - -/** - * angular distance between angle 'a' and 'b' - * - * @param {number} a : first angle in *radians* - * @param {number} b : second angle in *radians* - * @return {number} angular distance in *radians* - */ -function angleDist(a, b) { - return Math.abs(angleDelta(a, b)); -} - -/** - * is angle inside sector? - * - * @param {number} a : angle to test in *radians* - * @param {2-item array} aBnds : sector's angular bounds in *radians* - * @param {boolean} - */ -function isAngleInsideSector(a, aBnds) { - if(isFullCircle(aBnds)) return true; - - var s0, s1; - - if(aBnds[0] < aBnds[1]) { - s0 = aBnds[0]; - s1 = aBnds[1]; - } else { - s0 = aBnds[1]; - s1 = aBnds[0]; - } - - s0 = mod(s0, twoPI); - s1 = mod(s1, twoPI); - if(s0 > s1) s1 += twoPI; - - var a0 = mod(a, twoPI); - var a1 = a0 + twoPI; - - return (a0 >= s0 && a0 <= s1) || (a1 >= s0 && a1 <= s1); -} - -/** - * is pt (r,a) inside sector? - * - * @param {number} r : pt's radial coordinate - * @param {number} a : pt's angular coordinate in *radians* - * @param {2-item array} rBnds : sector's radial bounds - * @param {2-item array} aBnds : sector's angular bounds in *radians* - * @return {boolean} - */ -function isPtInsideSector(r, a, rBnds, aBnds) { - if(!isAngleInsideSector(a, aBnds)) return false; - - var r0, r1; - - if(rBnds[0] < rBnds[1]) { - r0 = rBnds[0]; - r1 = rBnds[1]; - } else { - r0 = rBnds[1]; - r1 = rBnds[0]; - } - - return r >= r0 && r <= r1; -} - -// common to pathArc, pathSector and pathAnnulus -function _path(r0, r1, a0, a1, cx, cy, isClosed) { - cx = cx || 0; - cy = cy || 0; - - var isCircle = isFullCircle([a0, a1]); - var aStart, aMid, aEnd; - var rStart, rEnd; - - if(isCircle) { - aStart = 0; - aMid = PI; - aEnd = twoPI; - } else { - if(a0 < a1) { - aStart = a0; - aEnd = a1; - } else { - aStart = a1; - aEnd = a0; - } - } - - if(r0 < r1) { - rStart = r0; - rEnd = r1; - } else { - rStart = r1; - rEnd = r0; - } - - // N.B. svg coordinates here, where y increases downward - function pt(r, a) { - return [r * Math.cos(a) + cx, cy - r * Math.sin(a)]; - } - - var largeArc = Math.abs(aEnd - aStart) <= PI ? 0 : 1; - function arc(r, a, cw) { - return 'A' + [r, r] + ' ' + [0, largeArc, cw] + ' ' + pt(r, a); - } - - var p; - - if(isCircle) { - if(rStart === null) { - p = 'M' + pt(rEnd, aStart) + - arc(rEnd, aMid, 0) + - arc(rEnd, aEnd, 0) + 'Z'; - } else { - p = 'M' + pt(rStart, aStart) + - arc(rStart, aMid, 0) + - arc(rStart, aEnd, 0) + 'Z' + - 'M' + pt(rEnd, aStart) + - arc(rEnd, aMid, 1) + - arc(rEnd, aEnd, 1) + 'Z'; - } - } else { - if(rStart === null) { - p = 'M' + pt(rEnd, aStart) + arc(rEnd, aEnd, 0); - if(isClosed) p += 'L0,0Z'; - } else { - p = 'M' + pt(rStart, aStart) + - 'L' + pt(rEnd, aStart) + - arc(rEnd, aEnd, 0) + - 'L' + pt(rStart, aEnd) + - arc(rStart, aStart, 1) + 'Z'; - } - } - - return p; -} - -/** - * path an arc - * - * @param {number} r : radius - * @param {number} a0 : first angular coordinate in *radians* - * @param {number} a1 : second angular coordinate in *radians* - * @param {number (optional)} cx : x coordinate of center - * @param {number (optional)} cy : y coordinate of center - * @return {string} svg path - */ -function pathArc(r, a0, a1, cx, cy) { - return _path(null, r, a0, a1, cx, cy, 0); -} - -/** - * path a sector - * - * @param {number} r : radius - * @param {number} a0 : first angular coordinate in *radians* - * @param {number} a1 : second angular coordinate in *radians* - * @param {number (optional)} cx : x coordinate of center - * @param {number (optional)} cy : y coordinate of center - * @return {string} svg path - */ -function pathSector(r, a0, a1, cx, cy) { - return _path(null, r, a0, a1, cx, cy, 1); -} - -/** - * path an annulus - * - * @param {number} r0 : first radial coordinate - * @param {number} r1 : second radial coordinate - * @param {number} a0 : first angular coordinate in *radians* - * @param {number} a1 : second angular coordinate in *radians* - * @param {number (optional)} cx : x coordinate of center - * @param {number (optional)} cy : y coordinate of center - * @return {string} svg path - */ -function pathAnnulus(r0, r1, a0, a1, cx, cy) { - return _path(r0, r1, a0, a1, cx, cy, 1); -} - -module.exports = { - deg2rad: deg2rad, - rad2deg: rad2deg, - angleDelta: angleDelta, - angleDist: angleDist, - isFullCircle: isFullCircle, - isAngleInsideSector: isAngleInsideSector, - isPtInsideSector: isPtInsideSector, - pathArc: pathArc, - pathSector: pathSector, - pathAnnulus: pathAnnulus -}; - -},{"./mod":726}],702:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isArray = Array.isArray; - -// IE9 fallbacks - -var ab = (typeof ArrayBuffer === 'undefined' || !ArrayBuffer.isView) ? - {isView: function() { return false; }} : - ArrayBuffer; - -var dv = (typeof DataView === 'undefined') ? - function() {} : - DataView; - -function isTypedArray(a) { - return ab.isView(a) && !(a instanceof dv); -} -exports.isTypedArray = isTypedArray; - -function isArrayOrTypedArray(a) { - return isArray(a) || isTypedArray(a); -} -exports.isArrayOrTypedArray = isArrayOrTypedArray; - -/* - * Test whether an input object is 1D. - * - * Assumes we already know the object is an array. - * - * Looks only at the first element, if the dimensionality is - * not consistent we won't figure that out here. - */ -function isArray1D(a) { - return !isArrayOrTypedArray(a[0]); -} -exports.isArray1D = isArray1D; - -/* - * Ensures an array has the right amount of storage space. If it doesn't - * exist, it creates an array. If it does exist, it returns it if too - * short or truncates it in-place. - * - * The goal is to just reuse memory to avoid a bit of excessive garbage - * collection. - */ -exports.ensureArray = function(out, n) { - // TODO: typed array support here? This is only used in - // traces/carpet/compute_control_points - if(!isArray(out)) out = []; - - // If too long, truncate. (If too short, it will grow - // automatically so we don't care about that case) - out.length = n; - - return out; -}; - -/* - * TypedArray-compatible concatenation of n arrays - * if all arrays are the same type it will preserve that type, - * otherwise it falls back on Array. - * Also tries to avoid copying, in case one array has zero length - * But never mutates an existing array - */ -exports.concat = function() { - var args = []; - var allArray = true; - var totalLen = 0; - - var _constructor, arg0, i, argi, posi, leni, out, j; - - for(i = 0; i < arguments.length; i++) { - argi = arguments[i]; - leni = argi.length; - if(leni) { - if(arg0) args.push(argi); - else { - arg0 = argi; - posi = leni; - } - - if(isArray(argi)) { - _constructor = false; - } else { - allArray = false; - if(!totalLen) { - _constructor = argi.constructor; - } else if(_constructor !== argi.constructor) { - // TODO: in principle we could upgrade here, - // ie keep typed array but convert all to Float64Array? - _constructor = false; - } - } - - totalLen += leni; - } - } - - if(!totalLen) return []; - if(!args.length) return arg0; - - if(allArray) return arg0.concat.apply(arg0, args); - if(_constructor) { - // matching typed arrays - out = new _constructor(totalLen); - out.set(arg0); - for(i = 0; i < args.length; i++) { - argi = args[i]; - out.set(argi, posi); - posi += argi.length; - } - return out; - } - - // mismatched types or Array + typed - out = new Array(totalLen); - for(j = 0; j < arg0.length; j++) out[j] = arg0[j]; - for(i = 0; i < args.length; i++) { - argi = args[i]; - for(j = 0; j < argi.length; j++) out[posi + j] = argi[j]; - posi += j; - } - return out; -}; - -exports.maxRowLength = function(z) { - return _rowLength(z, Math.max, 0); -}; - -exports.minRowLength = function(z) { - return _rowLength(z, Math.min, Infinity); -}; - -function _rowLength(z, fn, len0) { - if(isArrayOrTypedArray(z)) { - if(isArrayOrTypedArray(z[0])) { - var len = len0; - for(var i = 0; i < z.length; i++) { - len = fn(len, z[i].length); - } - return len; - } else { - return z.length; - } - } - return 0; -} - -},{}],703:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var BADNUM = _dereq_('../constants/numerical').BADNUM; - -// precompile for speed -var JUNK = /^['"%,$#\s']+|[, ]|['"%,$#\s']+$/g; - -/** - * cleanNumber: remove common leading and trailing cruft - * Always returns either a number or BADNUM. - */ -module.exports = function cleanNumber(v) { - if(typeof v === 'string') { - v = v.replace(JUNK, ''); - } - - if(isNumeric(v)) return Number(v); - - return BADNUM; -}; - -},{"../constants/numerical":695,"fast-isnumeric":225}],704:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** - * Clear gl frame (if any). This is a common pattern as - * we usually set `preserveDrawingBuffer: true` during - * gl context creation (e.g. via `reglUtils.prepare`). - * - * @param {DOM node or object} gd : graph div object - */ -module.exports = function clearGlCanvases(gd) { - var fullLayout = gd._fullLayout; - - if(fullLayout._glcanvas && fullLayout._glcanvas.size()) { - fullLayout._glcanvas.each(function(d) { - if(d.regl) d.regl.clear({color: true, depth: true}); - }); - } -}; - -},{}],705:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** - * Clear responsive handlers (if any). - * - * @param {DOM node or object} gd : graph div object - */ -module.exports = function clearResponsive(gd) { - if(gd._responsiveChartHandler) { - window.removeEventListener('resize', gd._responsiveChartHandler); - delete gd._responsiveChartHandler; - } -}; - -},{}],706:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var tinycolor = _dereq_('tinycolor2'); - -var baseTraceAttrs = _dereq_('../plots/attributes'); -var colorscales = _dereq_('../components/colorscale/scales'); -var DESELECTDIM = _dereq_('../constants/interactions').DESELECTDIM; - -var nestedProperty = _dereq_('./nested_property'); -var counterRegex = _dereq_('./regex').counter; -var modHalf = _dereq_('./mod').modHalf; -var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; - -exports.valObjectMeta = { - data_array: { - // You can use *dflt=[] to force said array to exist though. - - - - coerceFunction: function(v, propOut, dflt) { - // TODO maybe `v: {type: 'float32', vals: [/* ... */]}` also - if(isArrayOrTypedArray(v)) propOut.set(v); - else if(dflt !== undefined) propOut.set(dflt); - } - }, - enumerated: { - - - - coerceFunction: function(v, propOut, dflt, opts) { - if(opts.coerceNumber) v = +v; - if(opts.values.indexOf(v) === -1) propOut.set(dflt); - else propOut.set(v); - }, - validateFunction: function(v, opts) { - if(opts.coerceNumber) v = +v; - - var values = opts.values; - for(var i = 0; i < values.length; i++) { - var k = String(values[i]); - - if((k.charAt(0) === '/' && k.charAt(k.length - 1) === '/')) { - var regex = new RegExp(k.substr(1, k.length - 2)); - if(regex.test(v)) return true; - } else if(v === values[i]) return true; - } - return false; - } - }, - 'boolean': { - - - - coerceFunction: function(v, propOut, dflt) { - if(v === true || v === false) propOut.set(v); - else propOut.set(dflt); - } - }, - number: { - - - - coerceFunction: function(v, propOut, dflt, opts) { - if(!isNumeric(v) || - (opts.min !== undefined && v < opts.min) || - (opts.max !== undefined && v > opts.max)) { - propOut.set(dflt); - } else propOut.set(+v); - } - }, - integer: { - - - - coerceFunction: function(v, propOut, dflt, opts) { - if(v % 1 || !isNumeric(v) || - (opts.min !== undefined && v < opts.min) || - (opts.max !== undefined && v > opts.max)) { - propOut.set(dflt); - } else propOut.set(+v); - } - }, - string: { - - - // TODO 'values shouldn't be in there (edge case: 'dash' in Scatter) - - coerceFunction: function(v, propOut, dflt, opts) { - if(typeof v !== 'string') { - var okToCoerce = (typeof v === 'number'); - - if(opts.strict === true || !okToCoerce) propOut.set(dflt); - else propOut.set(String(v)); - } else if(opts.noBlank && !v) propOut.set(dflt); - else propOut.set(v); - } - }, - color: { - - - - coerceFunction: function(v, propOut, dflt) { - if(tinycolor(v).isValid()) propOut.set(v); - else propOut.set(dflt); - } - }, - colorlist: { - - - - coerceFunction: function(v, propOut, dflt) { - function isColor(color) { - return tinycolor(color).isValid(); - } - if(!Array.isArray(v) || !v.length) propOut.set(dflt); - else if(v.every(isColor)) propOut.set(v); - else propOut.set(dflt); - } - }, - colorscale: { - - - - coerceFunction: function(v, propOut, dflt) { - propOut.set(colorscales.get(v, dflt)); - } - }, - angle: { - - - - coerceFunction: function(v, propOut, dflt) { - if(v === 'auto') propOut.set('auto'); - else if(!isNumeric(v)) propOut.set(dflt); - else propOut.set(modHalf(+v, 360)); - } - }, - subplotid: { - - - - coerceFunction: function(v, propOut, dflt, opts) { - var regex = opts.regex || counterRegex(dflt); - if(typeof v === 'string' && regex.test(v)) { - propOut.set(v); - return; - } - propOut.set(dflt); - }, - validateFunction: function(v, opts) { - var dflt = opts.dflt; - - if(v === dflt) return true; - if(typeof v !== 'string') return false; - if(counterRegex(dflt).test(v)) return true; - - return false; - } - }, - flaglist: { - - - - coerceFunction: function(v, propOut, dflt, opts) { - if(typeof v !== 'string') { - propOut.set(dflt); - return; - } - if((opts.extras || []).indexOf(v) !== -1) { - propOut.set(v); - return; - } - var vParts = v.split('+'); - var i = 0; - while(i < vParts.length) { - var vi = vParts[i]; - if(opts.flags.indexOf(vi) === -1 || vParts.indexOf(vi) < i) { - vParts.splice(i, 1); - } else i++; - } - if(!vParts.length) propOut.set(dflt); - else propOut.set(vParts.join('+')); - } - }, - any: { - - - - coerceFunction: function(v, propOut, dflt) { - if(v === undefined) propOut.set(dflt); - else propOut.set(v); - } - }, - info_array: { - - - // set `dimensions=2` for a 2D array or '1-2' for either - // `items` may be a single object instead of an array, in which case - // `freeLength` must be true. - // if `dimensions='1-2'` and items is a 1D array, then the value can - // either be a matching 1D array or an array of such matching 1D arrays - - coerceFunction: function(v, propOut, dflt, opts) { - // simplified coerce function just for array items - function coercePart(v, opts, dflt) { - var out; - var propPart = {set: function(v) { out = v; }}; - - if(dflt === undefined) dflt = opts.dflt; - - exports.valObjectMeta[opts.valType].coerceFunction(v, propPart, dflt, opts); - - return out; - } - - var twoD = opts.dimensions === 2 || (opts.dimensions === '1-2' && Array.isArray(v) && Array.isArray(v[0])); - - if(!Array.isArray(v)) { - propOut.set(dflt); - return; - } - - var items = opts.items; - var vOut = []; - var arrayItems = Array.isArray(items); - var arrayItems2D = arrayItems && twoD && Array.isArray(items[0]); - var innerItemsOnly = twoD && arrayItems && !arrayItems2D; - var len = (arrayItems && !innerItemsOnly) ? items.length : v.length; - - var i, j, row, item, len2, vNew; - - dflt = Array.isArray(dflt) ? dflt : []; - - if(twoD) { - for(i = 0; i < len; i++) { - vOut[i] = []; - row = Array.isArray(v[i]) ? v[i] : []; - if(innerItemsOnly) len2 = items.length; - else if(arrayItems) len2 = items[i].length; - else len2 = row.length; - - for(j = 0; j < len2; j++) { - if(innerItemsOnly) item = items[j]; - else if(arrayItems) item = items[i][j]; - else item = items; - - vNew = coercePart(row[j], item, (dflt[i] || [])[j]); - if(vNew !== undefined) vOut[i][j] = vNew; - } - } - } else { - for(i = 0; i < len; i++) { - vNew = coercePart(v[i], arrayItems ? items[i] : items, dflt[i]); - if(vNew !== undefined) vOut[i] = vNew; - } - } - - propOut.set(vOut); - }, - validateFunction: function(v, opts) { - if(!Array.isArray(v)) return false; - - var items = opts.items; - var arrayItems = Array.isArray(items); - var twoD = opts.dimensions === 2; - - // when free length is off, input and declared lengths must match - if(!opts.freeLength && v.length !== items.length) return false; - - // valid when all input items are valid - for(var i = 0; i < v.length; i++) { - if(twoD) { - if(!Array.isArray(v[i]) || (!opts.freeLength && v[i].length !== items[i].length)) { - return false; - } - for(var j = 0; j < v[i].length; j++) { - if(!validate(v[i][j], arrayItems ? items[i][j] : items)) { - return false; - } - } - } else if(!validate(v[i], arrayItems ? items[i] : items)) return false; - } - - return true; - } - } -}; - -/** - * Ensures that container[attribute] has a valid value. - * - * attributes[attribute] is an object with possible keys: - * - valType: data_array, enumerated, boolean, ... as in valObjectMeta - * - values: (enumerated only) array of allowed vals - * - min, max: (number, integer only) inclusive bounds on allowed vals - * either or both may be omitted - * - dflt: if attribute is invalid or missing, use this default - * if dflt is provided as an argument to lib.coerce it takes precedence - * as a convenience, returns the value it finally set - */ -exports.coerce = function(containerIn, containerOut, attributes, attribute, dflt) { - var opts = nestedProperty(attributes, attribute).get(); - var propIn = nestedProperty(containerIn, attribute); - var propOut = nestedProperty(containerOut, attribute); - var v = propIn.get(); - - var template = containerOut._template; - if(v === undefined && template) { - v = nestedProperty(template, attribute).get(); - // already used the template value, so short-circuit the second check - template = 0; - } - - if(dflt === undefined) dflt = opts.dflt; - - /** - * arrayOk: value MAY be an array, then we do no value checking - * at this point, because it can be more complicated than the - * individual form (eg. some array vals can be numbers, even if the - * single values must be color strings) - */ - if(opts.arrayOk && isArrayOrTypedArray(v)) { - propOut.set(v); - return v; - } - - var coerceFunction = exports.valObjectMeta[opts.valType].coerceFunction; - coerceFunction(v, propOut, dflt, opts); - - var out = propOut.get(); - // in case v was provided but invalid, try the template again so it still - // overrides the regular default - if(template && out === dflt && !validate(v, opts)) { - v = nestedProperty(template, attribute).get(); - coerceFunction(v, propOut, dflt, opts); - out = propOut.get(); - } - return out; -}; - -/** - * Variation on coerce - * - * Uses coerce to get attribute value if user input is valid, - * returns attribute default if user input it not valid or - * returns false if there is no user input. - */ -exports.coerce2 = function(containerIn, containerOut, attributes, attribute, dflt) { - var propIn = nestedProperty(containerIn, attribute); - var propOut = exports.coerce(containerIn, containerOut, attributes, attribute, dflt); - var valIn = propIn.get(); - - return (valIn !== undefined && valIn !== null) ? propOut : false; -}; - -/* - * Shortcut to coerce the three font attributes - * - * 'coerce' is a lib.coerce wrapper with implied first three arguments - */ -exports.coerceFont = function(coerce, attr, dfltObj) { - var out = {}; - - dfltObj = dfltObj || {}; - - out.family = coerce(attr + '.family', dfltObj.family); - out.size = coerce(attr + '.size', dfltObj.size); - out.color = coerce(attr + '.color', dfltObj.color); - - return out; -}; - -/** Coerce shortcut for 'hoverinfo' - * handling 1-vs-multi-trace dflt logic - * - * @param {object} traceIn : user trace object - * @param {object} traceOut : full trace object (requires _module ref) - * @param {object} layoutOut : full layout object (require _dataLength ref) - * @return {any} : the coerced value - */ -exports.coerceHoverinfo = function(traceIn, traceOut, layoutOut) { - var moduleAttrs = traceOut._module.attributes; - var attrs = moduleAttrs.hoverinfo ? moduleAttrs : baseTraceAttrs; - - var valObj = attrs.hoverinfo; - var dflt; - - if(layoutOut._dataLength === 1) { - var flags = valObj.dflt === 'all' ? - valObj.flags.slice() : - valObj.dflt.split('+'); - - flags.splice(flags.indexOf('name'), 1); - dflt = flags.join('+'); - } - - return exports.coerce(traceIn, traceOut, attrs, 'hoverinfo', dflt); -}; - -/** Coerce shortcut for [un]selected.marker.opacity, - * which has special default logic, to ensure that it corresponds to the - * default selection behavior while allowing to be overtaken by any other - * [un]selected attribute. - * - * N.B. This must be called *after* coercing all the other [un]selected attrs, - * to give the intended result. - * - * @param {object} traceOut : fullData item - * @param {function} coerce : lib.coerce wrapper with implied first three arguments - */ -exports.coerceSelectionMarkerOpacity = function(traceOut, coerce) { - if(!traceOut.marker) return; - - var mo = traceOut.marker.opacity; - // you can still have a `marker` container with no markers if there's text - if(mo === undefined) return; - - var smoDflt; - var usmoDflt; - - // Don't give [un]selected.marker.opacity a default value if - // marker.opacity is an array: handle this during style step. - // - // Only give [un]selected.marker.opacity a default value if you don't - // set any other [un]selected attributes. - if(!isArrayOrTypedArray(mo) && !traceOut.selected && !traceOut.unselected) { - smoDflt = mo; - usmoDflt = DESELECTDIM * mo; - } - - coerce('selected.marker.opacity', smoDflt); - coerce('unselected.marker.opacity', usmoDflt); -}; - -function validate(value, opts) { - var valObjectDef = exports.valObjectMeta[opts.valType]; - - if(opts.arrayOk && isArrayOrTypedArray(value)) return true; - - if(valObjectDef.validateFunction) { - return valObjectDef.validateFunction(value, opts); - } - - var failed = {}; - var out = failed; - var propMock = { set: function(v) { out = v; } }; - - // 'failed' just something mutable that won't be === anything else - - valObjectDef.coerceFunction(value, propMock, failed, opts); - return out !== failed; -} -exports.validate = validate; - -},{"../components/colorscale/scales":608,"../constants/interactions":694,"../plots/attributes":764,"./array":702,"./mod":726,"./nested_property":727,"./regex":735,"fast-isnumeric":225,"tinycolor2":537}],707:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Loggers = _dereq_('./loggers'); -var mod = _dereq_('./mod').mod; - -var constants = _dereq_('../constants/numerical'); -var BADNUM = constants.BADNUM; -var ONEDAY = constants.ONEDAY; -var ONEHOUR = constants.ONEHOUR; -var ONEMIN = constants.ONEMIN; -var ONESEC = constants.ONESEC; -var EPOCHJD = constants.EPOCHJD; - -var Registry = _dereq_('../registry'); - -var utcFormat = d3.time.format.utc; - -var DATETIME_REGEXP = /^\s*(-?\d\d\d\d|\d\d)(-(\d?\d)(-(\d?\d)([ Tt]([01]?\d|2[0-3])(:([0-5]\d)(:([0-5]\d(\.\d+)?))?(Z|z|[+\-]\d\d:?\d\d)?)?)?)?)?\s*$/m; -// special regex for chinese calendars to support yyyy-mmi-dd etc for intercalary months -var DATETIME_REGEXP_CN = /^\s*(-?\d\d\d\d|\d\d)(-(\d?\di?)(-(\d?\d)([ Tt]([01]?\d|2[0-3])(:([0-5]\d)(:([0-5]\d(\.\d+)?))?(Z|z|[+\-]\d\d:?\d\d)?)?)?)?)?\s*$/m; - -// for 2-digit years, the first year we map them onto -var YFIRST = new Date().getFullYear() - 70; - -function isWorldCalendar(calendar) { - return ( - calendar && - Registry.componentsRegistry.calendars && - typeof calendar === 'string' && calendar !== 'gregorian' - ); -} - -/* - * dateTick0: get the canonical tick for this calendar - * - * bool sunday is for week ticks, shift it to a Sunday. - */ -exports.dateTick0 = function(calendar, sunday) { - if(isWorldCalendar(calendar)) { - return sunday ? - Registry.getComponentMethod('calendars', 'CANONICAL_SUNDAY')[calendar] : - Registry.getComponentMethod('calendars', 'CANONICAL_TICK')[calendar]; - } else { - return sunday ? '2000-01-02' : '2000-01-01'; - } -}; - -/* - * dfltRange: for each calendar, give a valid default range - */ -exports.dfltRange = function(calendar) { - if(isWorldCalendar(calendar)) { - return Registry.getComponentMethod('calendars', 'DFLTRANGE')[calendar]; - } else { - return ['2000-01-01', '2001-01-01']; - } -}; - -// is an object a javascript date? -exports.isJSDate = function(v) { - return typeof v === 'object' && v !== null && typeof v.getTime === 'function'; -}; - -// The absolute limits of our date-time system -// This is a little weird: we use MIN_MS and MAX_MS in dateTime2ms -// but we use dateTime2ms to calculate them (after defining it!) -var MIN_MS, MAX_MS; - -/** - * dateTime2ms - turn a date object or string s into milliseconds - * (relative to 1970-01-01, per javascript standard) - * optional calendar (string) to use a non-gregorian calendar - * - * Returns BADNUM if it doesn't find a date - * - * strings should have the form: - * - * -?YYYY-mm-ddHH:MM:SS.sss? - * - * : space (our normal standard) or T or t (ISO-8601) - * : Z, z, or [+\-]HH:?MM and we THROW IT AWAY - * this format comes from https://tools.ietf.org/html/rfc3339#section-5.6 - * but we allow it even with a space as the separator - * - * May truncate after any full field, and sss can be any length - * even >3 digits, though javascript dates truncate to milliseconds, - * we keep as much as javascript numeric precision can hold, but we only - * report back up to 100 microsecond precision, because most dates support - * this precision (close to 1970 support more, very far away support less) - * - * Expanded to support negative years to -9999 but you must always - * give 4 digits, except for 2-digit positive years which we assume are - * near the present time. - * Note that we follow ISO 8601:2004: there *is* a year 0, which - * is 1BC/BCE, and -1===2BC etc. - * - * World calendars: not all of these *have* agreed extensions to this full range, - * if you have another calendar system but want a date range outside its validity, - * you can use a gregorian date string prefixed with 'G' or 'g'. - * - * Where to cut off 2-digit years between 1900s and 2000s? - * from http://support.microsoft.com/kb/244664: - * 1930-2029 (the most retro of all...) - * but in my mac chrome from eg. d=new Date(Date.parse('8/19/50')): - * 1950-2049 - * by Java, from http://stackoverflow.com/questions/2024273/: - * now-80 - now+19 - * or FileMaker Pro, from - * http://www.filemaker.com/12help/html/add_view_data.4.21.html: - * now-70 - now+29 - * but python strptime etc, via - * http://docs.python.org/py3k/library/time.html: - * 1969-2068 (super forward-looking, but static, not sliding!) - * - * lets go with now-70 to now+29, and if anyone runs into this problem - * they can learn the hard way not to use 2-digit years, as no choice we - * make now will cover all possibilities. mostly this will all be taken - * care of in initial parsing, should only be an issue for hand-entered data - * currently (2016) this range is: - * 1946-2045 - */ -exports.dateTime2ms = function(s, calendar) { - // first check if s is a date object - if(exports.isJSDate(s)) { - // Convert to the UTC milliseconds that give the same - // hours as this date has in the local timezone - var tzOffset = s.getTimezoneOffset() * ONEMIN; - var offsetTweak = (s.getUTCMinutes() - s.getMinutes()) * ONEMIN + - (s.getUTCSeconds() - s.getSeconds()) * ONESEC + - (s.getUTCMilliseconds() - s.getMilliseconds()); - - if(offsetTweak) { - var comb = 3 * ONEMIN; - tzOffset = tzOffset - comb / 2 + mod(offsetTweak - tzOffset + comb / 2, comb); - } - s = Number(s) - tzOffset; - if(s >= MIN_MS && s <= MAX_MS) return s; - return BADNUM; - } - // otherwise only accept strings and numbers - if(typeof s !== 'string' && typeof s !== 'number') return BADNUM; - - s = String(s); - - var isWorld = isWorldCalendar(calendar); - - // to handle out-of-range dates in international calendars, accept - // 'G' as a prefix to force the built-in gregorian calendar. - var s0 = s.charAt(0); - if(isWorld && (s0 === 'G' || s0 === 'g')) { - s = s.substr(1); - calendar = ''; - } - - var isChinese = isWorld && calendar.substr(0, 7) === 'chinese'; - - var match = s.match(isChinese ? DATETIME_REGEXP_CN : DATETIME_REGEXP); - if(!match) return BADNUM; - var y = match[1]; - var m = match[3] || '1'; - var d = Number(match[5] || 1); - var H = Number(match[7] || 0); - var M = Number(match[9] || 0); - var S = Number(match[11] || 0); - - if(isWorld) { - // disallow 2-digit years for world calendars - if(y.length === 2) return BADNUM; - y = Number(y); - - var cDate; - try { - var calInstance = Registry.getComponentMethod('calendars', 'getCal')(calendar); - if(isChinese) { - var isIntercalary = m.charAt(m.length - 1) === 'i'; - m = parseInt(m, 10); - cDate = calInstance.newDate(y, calInstance.toMonthIndex(y, m, isIntercalary), d); - } else { - cDate = calInstance.newDate(y, Number(m), d); - } - } catch(e) { return BADNUM; } // Invalid ... date - - if(!cDate) return BADNUM; - - return ((cDate.toJD() - EPOCHJD) * ONEDAY) + - (H * ONEHOUR) + (M * ONEMIN) + (S * ONESEC); - } - - if(y.length === 2) { - y = (Number(y) + 2000 - YFIRST) % 100 + YFIRST; - } else y = Number(y); - - // new Date uses months from 0; subtract 1 here just so we - // don't have to do it again during the validity test below - m -= 1; - - // javascript takes new Date(0..99,m,d) to mean 1900-1999, so - // to support years 0-99 we need to use setFullYear explicitly - // Note that 2000 is a leap year. - var date = new Date(Date.UTC(2000, m, d, H, M)); - date.setUTCFullYear(y); - - if(date.getUTCMonth() !== m) return BADNUM; - if(date.getUTCDate() !== d) return BADNUM; - - return date.getTime() + S * ONESEC; -}; - -MIN_MS = exports.MIN_MS = exports.dateTime2ms('-9999'); -MAX_MS = exports.MAX_MS = exports.dateTime2ms('9999-12-31 23:59:59.9999'); - -// is string s a date? (see above) -exports.isDateTime = function(s, calendar) { - return (exports.dateTime2ms(s, calendar) !== BADNUM); -}; - -// pad a number with zeroes, to given # of digits before the decimal point -function lpad(val, digits) { - return String(val + Math.pow(10, digits)).substr(1); -} - -/** - * Turn ms into string of the form YYYY-mm-dd HH:MM:SS.ssss - * Crop any trailing zeros in time, except never stop right after hours - * (we could choose to crop '-01' from date too but for now we always - * show the whole date) - * Optional range r is the data range that applies, also in ms. - * If rng is big, the later parts of time will be omitted - */ -var NINETYDAYS = 90 * ONEDAY; -var THREEHOURS = 3 * ONEHOUR; -var FIVEMIN = 5 * ONEMIN; -exports.ms2DateTime = function(ms, r, calendar) { - if(typeof ms !== 'number' || !(ms >= MIN_MS && ms <= MAX_MS)) return BADNUM; - - if(!r) r = 0; - - var msecTenths = Math.floor(mod(ms + 0.05, 1) * 10); - var msRounded = Math.round(ms - msecTenths / 10); - var dateStr, h, m, s, msec10, d; - - if(isWorldCalendar(calendar)) { - var dateJD = Math.floor(msRounded / ONEDAY) + EPOCHJD; - var timeMs = Math.floor(mod(ms, ONEDAY)); - try { - dateStr = Registry.getComponentMethod('calendars', 'getCal')(calendar) - .fromJD(dateJD).formatDate('yyyy-mm-dd'); - } catch(e) { - // invalid date in this calendar - fall back to Gyyyy-mm-dd - dateStr = utcFormat('G%Y-%m-%d')(new Date(msRounded)); - } - - // yyyy does NOT guarantee 4-digit years. YYYY mostly does, but does - // other things for a few calendars, so we can't trust it. Just pad - // it manually (after the '-' if there is one) - if(dateStr.charAt(0) === '-') { - while(dateStr.length < 11) dateStr = '-0' + dateStr.substr(1); - } else { - while(dateStr.length < 10) dateStr = '0' + dateStr; - } - - // TODO: if this is faster, we could use this block for extracting - // the time components of regular gregorian too - h = (r < NINETYDAYS) ? Math.floor(timeMs / ONEHOUR) : 0; - m = (r < NINETYDAYS) ? Math.floor((timeMs % ONEHOUR) / ONEMIN) : 0; - s = (r < THREEHOURS) ? Math.floor((timeMs % ONEMIN) / ONESEC) : 0; - msec10 = (r < FIVEMIN) ? (timeMs % ONESEC) * 10 + msecTenths : 0; - } else { - d = new Date(msRounded); - - dateStr = utcFormat('%Y-%m-%d')(d); - - // <90 days: add hours and minutes - never *only* add hours - h = (r < NINETYDAYS) ? d.getUTCHours() : 0; - m = (r < NINETYDAYS) ? d.getUTCMinutes() : 0; - // <3 hours: add seconds - s = (r < THREEHOURS) ? d.getUTCSeconds() : 0; - // <5 minutes: add ms (plus one extra digit, this is msec*10) - msec10 = (r < FIVEMIN) ? d.getUTCMilliseconds() * 10 + msecTenths : 0; - } - - return includeTime(dateStr, h, m, s, msec10); -}; - -// For converting old-style milliseconds to date strings, -// we use the local timezone rather than UTC like we use -// everywhere else, both for backward compatibility and -// because that's how people mostly use javasript date objects. -// Clip one extra day off our date range though so we can't get -// thrown beyond the range by the timezone shift. -exports.ms2DateTimeLocal = function(ms) { - if(!(ms >= MIN_MS + ONEDAY && ms <= MAX_MS - ONEDAY)) return BADNUM; - - var msecTenths = Math.floor(mod(ms + 0.05, 1) * 10); - var d = new Date(Math.round(ms - msecTenths / 10)); - var dateStr = d3.time.format('%Y-%m-%d')(d); - var h = d.getHours(); - var m = d.getMinutes(); - var s = d.getSeconds(); - var msec10 = d.getUTCMilliseconds() * 10 + msecTenths; - - return includeTime(dateStr, h, m, s, msec10); -}; - -function includeTime(dateStr, h, m, s, msec10) { - // include each part that has nonzero data in or after it - if(h || m || s || msec10) { - dateStr += ' ' + lpad(h, 2) + ':' + lpad(m, 2); - if(s || msec10) { - dateStr += ':' + lpad(s, 2); - if(msec10) { - var digits = 4; - while(msec10 % 10 === 0) { - digits -= 1; - msec10 /= 10; - } - dateStr += '.' + lpad(msec10, digits); - } - } - } - return dateStr; -} - -// normalize date format to date string, in case it starts as -// a Date object or milliseconds -// optional dflt is the return value if cleaning fails -exports.cleanDate = function(v, dflt, calendar) { - // let us use cleanDate to provide a missing default without an error - if(v === BADNUM) return dflt; - if(exports.isJSDate(v) || (typeof v === 'number' && isFinite(v))) { - // do not allow milliseconds (old) or jsdate objects (inherently - // described as gregorian dates) with world calendars - if(isWorldCalendar(calendar)) { - Loggers.error('JS Dates and milliseconds are incompatible with world calendars', v); - return dflt; - } - - // NOTE: if someone puts in a year as a number rather than a string, - // this will mistakenly convert it thinking it's milliseconds from 1970 - // that is: '2012' -> Jan. 1, 2012, but 2012 -> 2012 epoch milliseconds - v = exports.ms2DateTimeLocal(+v); - if(!v && dflt !== undefined) return dflt; - } else if(!exports.isDateTime(v, calendar)) { - Loggers.error('unrecognized date', v); - return dflt; - } - return v; -}; - -/* - * Date formatting for ticks and hovertext - */ - -/* - * modDateFormat: Support world calendars, and add one item to - * d3's vocabulary: - * %{n}f where n is the max number of digits of fractional seconds - */ -var fracMatch = /%\d?f/g; -function modDateFormat(fmt, x, formatter, calendar) { - fmt = fmt.replace(fracMatch, function(match) { - var digits = Math.min(+(match.charAt(1)) || 6, 6); - var fracSecs = ((x / 1000 % 1) + 2) - .toFixed(digits) - .substr(2).replace(/0+$/, '') || '0'; - return fracSecs; - }); - - var d = new Date(Math.floor(x + 0.05)); - - if(isWorldCalendar(calendar)) { - try { - fmt = Registry.getComponentMethod('calendars', 'worldCalFmt')(fmt, x, calendar); - } catch(e) { - return 'Invalid'; - } - } - return formatter(fmt)(d); -} - -/* - * formatTime: create a time string from: - * x: milliseconds - * tr: tickround ('M', 'S', or # digits) - * only supports UTC times (where every day is 24 hours and 0 is at midnight) - */ -var MAXSECONDS = [59, 59.9, 59.99, 59.999, 59.9999]; -function formatTime(x, tr) { - var timePart = mod(x + 0.05, ONEDAY); - - var timeStr = lpad(Math.floor(timePart / ONEHOUR), 2) + ':' + - lpad(mod(Math.floor(timePart / ONEMIN), 60), 2); - - if(tr !== 'M') { - if(!isNumeric(tr)) tr = 0; // should only be 'S' - - /* - * this is a weird one - and shouldn't come up unless people - * monkey with tick0 in weird ways, but we need to do something! - * IN PARTICULAR we had better not display garbage (see below) - * for numbers we always round to the nearest increment of the - * precision we're showing, and this seems like the right way to - * handle seconds and milliseconds, as they have a decimal point - * and people will interpret that to mean rounding like numbers. - * but for larger increments we floor the value: it's always - * 2013 until the ball drops on the new year. We could argue about - * which field it is where we start rounding (should 12:08:59 - * round to 12:09 if we're stopping at minutes?) but for now I'll - * say we round seconds but floor everything else. BUT that means - * we need to never round up to 60 seconds, ie 23:59:60 - */ - var sec = Math.min(mod(x / ONESEC, 60), MAXSECONDS[tr]); - - var secStr = (100 + sec).toFixed(tr).substr(1); - if(tr > 0) { - secStr = secStr.replace(/0+$/, '').replace(/[\.]$/, ''); - } - - timeStr += ':' + secStr; - } - return timeStr; -} - -/* - * formatDate: turn a date into tick or hover label text. - * - * x: milliseconds, the value to convert - * fmt: optional, an explicit format string (d3 format, even for world calendars) - * tr: tickround ('y', 'm', 'd', 'M', 'S', or # digits) - * used if no explicit fmt is provided - * formatter: locale-aware d3 date formatter for standard gregorian calendars - * should be the result of exports.getD3DateFormat(gd) - * calendar: optional string, the world calendar system to use - * - * returns the date/time as a string, potentially with the leading portion - * on a separate line (after '\n') - * Note that this means if you provide an explicit format which includes '\n' - * the axis may choose to strip things after it when they don't change from - * one tick to the next (as it does with automatic formatting) - */ -exports.formatDate = function(x, fmt, tr, formatter, calendar, extraFormat) { - calendar = isWorldCalendar(calendar) && calendar; - - if(!fmt) { - if(tr === 'y') fmt = extraFormat.year; - else if(tr === 'm') fmt = extraFormat.month; - else if(tr === 'd') { - fmt = extraFormat.dayMonth + '\n' + extraFormat.year; - } else { - return formatTime(x, tr) + '\n' + modDateFormat(extraFormat.dayMonthYear, x, formatter, calendar); - } - } - - return modDateFormat(fmt, x, formatter, calendar); -}; - -/* - * incrementMonth: make a new milliseconds value from the given one, - * having changed the month - * - * special case for world calendars: multiples of 12 are treated as years, - * even for calendar systems that don't have (always or ever) 12 months/year - * TODO: perhaps we need a different code for year increments to support this? - * - * ms (number): the initial millisecond value - * dMonth (int): the (signed) number of months to shift - * calendar (string): the calendar system to use - * - * changing month does not (and CANNOT) always preserve day, since - * months have different lengths. The worst example of this is: - * d = new Date(1970,0,31); d.setMonth(1) -> Feb 31 turns into Mar 3 - * - * But we want to be able to iterate over the last day of each month, - * regardless of what its number is. - * So shift 3 days forward, THEN set the new month, then unshift: - * 1/31 -> 2/28 (or 29) -> 3/31 -> 4/30 -> ... - * - * Note that odd behavior still exists if you start from the 26th-28th: - * 1/28 -> 2/28 -> 3/31 - * but at least you can't shift any dates into the wrong month, - * and ticks on these days incrementing by month would be very unusual - */ -var THREEDAYS = 3 * ONEDAY; -exports.incrementMonth = function(ms, dMonth, calendar) { - calendar = isWorldCalendar(calendar) && calendar; - - // pull time out and operate on pure dates, then add time back at the end - // this gives maximum precision - not that we *normally* care if we're - // incrementing by month, but better to be safe! - var timeMs = mod(ms, ONEDAY); - ms = Math.round(ms - timeMs); - - if(calendar) { - try { - var dateJD = Math.round(ms / ONEDAY) + EPOCHJD; - var calInstance = Registry.getComponentMethod('calendars', 'getCal')(calendar); - var cDate = calInstance.fromJD(dateJD); - - if(dMonth % 12) calInstance.add(cDate, dMonth, 'm'); - else calInstance.add(cDate, dMonth / 12, 'y'); - - return (cDate.toJD() - EPOCHJD) * ONEDAY + timeMs; - } catch(e) { - Loggers.error('invalid ms ' + ms + ' in calendar ' + calendar); - // then keep going in gregorian even though the result will be 'Invalid' - } - } - - var y = new Date(ms + THREEDAYS); - return y.setUTCMonth(y.getUTCMonth() + dMonth) + timeMs - THREEDAYS; -}; - -/* - * findExactDates: what fraction of data is exact days, months, or years? - * - * data: array of millisecond values - * calendar (string) the calendar to test against - */ -exports.findExactDates = function(data, calendar) { - var exactYears = 0; - var exactMonths = 0; - var exactDays = 0; - var blankCount = 0; - var d; - var di; - - var calInstance = ( - isWorldCalendar(calendar) && - Registry.getComponentMethod('calendars', 'getCal')(calendar) - ); - - for(var i = 0; i < data.length; i++) { - di = data[i]; - - // not date data at all - if(!isNumeric(di)) { - blankCount ++; - continue; - } - - // not an exact date - if(di % ONEDAY) continue; - - if(calInstance) { - try { - d = calInstance.fromJD(di / ONEDAY + EPOCHJD); - if(d.day() === 1) { - if(d.month() === 1) exactYears++; - else exactMonths++; - } else exactDays++; - } catch(e) { - // invalid date in this calendar - ignore it here. - } - } else { - d = new Date(di); - if(d.getUTCDate() === 1) { - if(d.getUTCMonth() === 0) exactYears++; - else exactMonths++; - } else exactDays++; - } - } - exactMonths += exactYears; - exactDays += exactMonths; - - var dataCount = data.length - blankCount; - - return { - exactYears: exactYears / dataCount, - exactMonths: exactMonths / dataCount, - exactDays: exactDays / dataCount - }; -}; - -},{"../constants/numerical":695,"../registry":847,"./loggers":723,"./mod":726,"d3":163,"fast-isnumeric":225}],708:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var loggers = _dereq_('./loggers'); - -/** - * Allow referencing a graph DOM element either directly - * or by its id string - * - * @param {HTMLDivElement|string} gd: a graph element or its id - * - * @returns {HTMLDivElement} the DOM element of the graph - */ -function getGraphDiv(gd) { - var gdElement; - - if(typeof gd === 'string') { - gdElement = document.getElementById(gd); - - if(gdElement === null) { - throw new Error('No DOM element with id \'' + gd + '\' exists on the page.'); - } - - return gdElement; - } else if(gd === null || gd === undefined) { - throw new Error('DOM element provided is null or undefined'); - } - - // otherwise assume that gd is a DOM element - return gd; -} - -function isPlotDiv(el) { - var el3 = d3.select(el); - return el3.node() instanceof HTMLElement && - el3.size() && - el3.classed('js-plotly-plot'); -} - -function removeElement(el) { - var elParent = el && el.parentNode; - if(elParent) elParent.removeChild(el); -} - -/** - * for dynamically adding style rules - * makes one stylesheet that contains all rules added - * by all calls to this function - */ -function addStyleRule(selector, styleString) { - addRelatedStyleRule('global', selector, styleString); -} - -/** - * for dynamically adding style rules - * to a stylesheet uniquely identified by a uid - */ -function addRelatedStyleRule(uid, selector, styleString) { - var id = 'plotly.js-style-' + uid; - var style = document.getElementById(id); - if(!style) { - style = document.createElement('style'); - style.setAttribute('id', id); - // WebKit hack :( - style.appendChild(document.createTextNode('')); - document.head.appendChild(style); - } - var styleSheet = style.sheet; - - if(styleSheet.insertRule) { - styleSheet.insertRule(selector + '{' + styleString + '}', 0); - } else if(styleSheet.addRule) { - styleSheet.addRule(selector, styleString, 0); - } else loggers.warn('addStyleRule failed'); -} - -/** - * to remove from the page a stylesheet identified by a given uid - */ -function deleteRelatedStyleRule(uid) { - var id = 'plotly.js-style-' + uid; - var style = document.getElementById(id); - if(style) removeElement(style); -} - -module.exports = { - getGraphDiv: getGraphDiv, - isPlotDiv: isPlotDiv, - removeElement: removeElement, - addStyleRule: addStyleRule, - addRelatedStyleRule: addRelatedStyleRule, - deleteRelatedStyleRule: deleteRelatedStyleRule -}; - -},{"./loggers":723,"d3":163}],709:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -/* global jQuery:false */ - -var EventEmitter = _dereq_('events').EventEmitter; - -var Events = { - - init: function(plotObj) { - /* - * If we have already instantiated an emitter for this plot - * return early. - */ - if(plotObj._ev instanceof EventEmitter) return plotObj; - - var ev = new EventEmitter(); - var internalEv = new EventEmitter(); - - /* - * Assign to plot._ev while we still live in a land - * where plot is a DOM element with stuff attached to it. - * In the future we can make plot the event emitter itself. - */ - plotObj._ev = ev; - - /* - * Create a second event handler that will manage events *internally*. - * This allows parts of plotly to respond to thing like relayout without - * having to use the user-facing event handler. They cannot peacefully - * coexist on the same handler because a user invoking - * plotObj.removeAllListeners() would detach internal events, breaking - * plotly. - */ - plotObj._internalEv = internalEv; - - /* - * Assign bound methods from the ev to the plot object. These methods - * will reference the 'this' of plot._ev even though they are methods - * of plot. This will keep the event machinery away from the plot object - * which currently is often a DOM element but presents an API that will - * continue to function when plot becomes an emitter. Not all EventEmitter - * methods have been bound to `plot` as some do not currently add value to - * the Plotly event API. - */ - plotObj.on = ev.on.bind(ev); - plotObj.once = ev.once.bind(ev); - plotObj.removeListener = ev.removeListener.bind(ev); - plotObj.removeAllListeners = ev.removeAllListeners.bind(ev); - - /* - * Create functions for managing internal events. These are *only* triggered - * by the mirroring of external events via the emit function. - */ - plotObj._internalOn = internalEv.on.bind(internalEv); - plotObj._internalOnce = internalEv.once.bind(internalEv); - plotObj._removeInternalListener = internalEv.removeListener.bind(internalEv); - plotObj._removeAllInternalListeners = internalEv.removeAllListeners.bind(internalEv); - - /* - * We must wrap emit to continue to support JQuery events. The idea - * is to check to see if the user is using JQuery events, if they are - * we emit JQuery events to trigger user handlers as well as the EventEmitter - * events. - */ - plotObj.emit = function(event, data) { - if(typeof jQuery !== 'undefined') { - jQuery(plotObj).trigger(event, data); - } - - ev.emit(event, data); - internalEv.emit(event, data); - }; - - return plotObj; - }, - - /* - * This function behaves like jQuery's triggerHandler. It calls - * all handlers for a particular event and returns the return value - * of the LAST handler. This function also triggers jQuery's - * triggerHandler for backwards compatibility. - */ - triggerHandler: function(plotObj, event, data) { - var jQueryHandlerValue; - var nodeEventHandlerValue; - - /* - * If jQuery exists run all its handlers for this event and - * collect the return value of the LAST handler function - */ - if(typeof jQuery !== 'undefined') { - jQueryHandlerValue = jQuery(plotObj).triggerHandler(event, data); - } - - /* - * Now run all the node style event handlers - */ - var ev = plotObj._ev; - if(!ev) return jQueryHandlerValue; - - var handlers = ev._events[event]; - if(!handlers) return jQueryHandlerValue; - - // making sure 'this' is the EventEmitter instance - function apply(handler) { - // The 'once' case, we can't just call handler() as we need - // the return value here. So, - // - remove handler - // - call listener and grab return value! - // - stash 'fired' key to not call handler twice - if(handler.listener) { - ev.removeListener(event, handler.listener); - if(!handler.fired) { - handler.fired = true; - return handler.listener.apply(ev, [data]); - } - } else { - return handler.apply(ev, [data]); - } - } - - // handlers can be function or an array of functions - handlers = Array.isArray(handlers) ? handlers : [handlers]; - - var i; - for(i = 0; i < handlers.length - 1; i++) { - apply(handlers[i]); - } - // now call the final handler and collect its value - nodeEventHandlerValue = apply(handlers[i]); - - /* - * Return either the jQuery handler value if it exists or the - * nodeEventHandler value. jQuery event value supersedes nodejs - * events for backwards compatibility reasons. - */ - return jQueryHandlerValue !== undefined ? - jQueryHandlerValue : - nodeEventHandlerValue; - }, - - purge: function(plotObj) { - delete plotObj._ev; - delete plotObj.on; - delete plotObj.once; - delete plotObj.removeListener; - delete plotObj.removeAllListeners; - delete plotObj.emit; - - delete plotObj._ev; - delete plotObj._internalEv; - delete plotObj._internalOn; - delete plotObj._internalOnce; - delete plotObj._removeInternalListener; - delete plotObj._removeAllInternalListeners; - - return plotObj; - } - -}; - -module.exports = Events; - -},{"events":104}],710:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isPlainObject = _dereq_('./is_plain_object.js'); -var isArray = Array.isArray; - -function primitivesLoopSplice(source, target) { - var i, value; - for(i = 0; i < source.length; i++) { - value = source[i]; - if(value !== null && typeof(value) === 'object') { - return false; - } - if(value !== void(0)) { - target[i] = value; - } - } - return true; -} - -exports.extendFlat = function() { - return _extend(arguments, false, false, false); -}; - -exports.extendDeep = function() { - return _extend(arguments, true, false, false); -}; - -exports.extendDeepAll = function() { - return _extend(arguments, true, true, false); -}; - -exports.extendDeepNoArrays = function() { - return _extend(arguments, true, false, true); -}; - -/* - * Inspired by https://github.com/justmoon/node-extend/blob/master/index.js - * All credit to the jQuery authors for perfecting this amazing utility. - * - * API difference with jQuery version: - * - No optional boolean (true -> deep extend) first argument, - * use `extendFlat` for first-level only extend and - * use `extendDeep` for a deep extend. - * - * Other differences with jQuery version: - * - Uses a modern (and faster) isPlainObject routine. - * - Expected to work with object {} and array [] arguments only. - * - Does not check for circular structure. - * FYI: jQuery only does a check across one level. - * Warning: this might result in infinite loops. - * - */ -function _extend(inputs, isDeep, keepAllKeys, noArrayCopies) { - var target = inputs[0]; - var length = inputs.length; - - var input, key, src, copy, copyIsArray, clone, allPrimitives; - - // TODO does this do the right thing for typed arrays? - - if(length === 2 && isArray(target) && isArray(inputs[1]) && target.length === 0) { - allPrimitives = primitivesLoopSplice(inputs[1], target); - - if(allPrimitives) { - return target; - } else { - target.splice(0, target.length); // reset target and continue to next block - } - } - - for(var i = 1; i < length; i++) { - input = inputs[i]; - - for(key in input) { - src = target[key]; - copy = input[key]; - - if(noArrayCopies && isArray(copy)) { - // Stop early and just transfer the array if array copies are disallowed: - - target[key] = copy; - } else if(isDeep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { - // recurse if we're merging plain objects or arrays - - if(copyIsArray) { - copyIsArray = false; - clone = src && isArray(src) ? src : []; - } else { - clone = src && isPlainObject(src) ? src : {}; - } - - // never move original objects, clone them - target[key] = _extend([clone, copy], isDeep, keepAllKeys, noArrayCopies); - } else if(typeof copy !== 'undefined' || keepAllKeys) { - // don't bring in undefined values, except for extendDeepAll - - target[key] = copy; - } - } - } - - return target; -} - -},{"./is_plain_object.js":720}],711:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -/** - * Return news array containing only the unique items - * found in input array. - * - * IMPORTANT: Note that items are considered unique - * if `String({})` is unique. For example; - * - * Lib.filterUnique([ { a: 1 }, { b: 2 } ]) - * - * returns [{ a: 1 }] - * - * and - * - * Lib.filterUnique([ '1', 1 ]) - * - * returns ['1'] - * - * - * @param {array} array base array - * @return {array} new filtered array - */ -module.exports = function filterUnique(array) { - var seen = {}; - var out = []; - var j = 0; - - for(var i = 0; i < array.length; i++) { - var item = array[i]; - - if(seen[item] !== 1) { - seen[item] = 1; - out[j++] = item; - } - } - - return out; -}; - -},{}],712:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** Filter out object items with visible !== true - * insider array container. - * - * @param {array of objects} container - * @return {array of objects} of length <= container - * - */ -module.exports = function filterVisible(container) { - var filterFn = isCalcData(container) ? calcDataFilter : baseFilter; - var out = []; - - for(var i = 0; i < container.length; i++) { - var item = container[i]; - if(filterFn(item)) out.push(item); - } - - return out; -}; - -function baseFilter(item) { - return item.visible === true; -} - -function calcDataFilter(item) { - var trace = item[0].trace; - return trace.visible === true && trace._length !== 0; -} - -function isCalcData(cont) { - return ( - Array.isArray(cont) && - Array.isArray(cont[0]) && - cont[0][0] && - cont[0][0].trace - ); -} - -},{}],713:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var countryRegex = _dereq_('country-regex'); -var Lib = _dereq_('../lib'); - -// make list of all country iso3 ids from at runtime -var countryIds = Object.keys(countryRegex); - -var locationmodeToIdFinder = { - 'ISO-3': Lib.identity, - 'USA-states': Lib.identity, - 'country names': countryNameToISO3 -}; - -function countryNameToISO3(countryName) { - for(var i = 0; i < countryIds.length; i++) { - var iso3 = countryIds[i]; - var regex = new RegExp(countryRegex[iso3]); - - if(regex.test(countryName.trim().toLowerCase())) return iso3; - } - - Lib.log('Unrecognized country name: ' + countryName + '.'); - - return false; -} - -function locationToFeature(locationmode, location, features) { - if(!location || typeof location !== 'string') return false; - - var locationId = locationmodeToIdFinder[locationmode](location); - var filteredFeatures; - var f, i; - - if(locationId) { - if(locationmode === 'USA-states') { - // Filter out features out in USA - // - // This is important as the Natural Earth files - // include state/provinces from USA, Canada, Australia and Brazil - // which have some overlay in their two-letter ids. For example, - // 'WA' is used for both Washington state and Western Australia. - filteredFeatures = []; - for(i = 0; i < features.length; i++) { - f = features[i]; - if(f.properties && f.properties.gu && f.properties.gu === 'USA') { - filteredFeatures.push(f); - } - } - } else { - filteredFeatures = features; - } - - for(i = 0; i < filteredFeatures.length; i++) { - f = filteredFeatures[i]; - if(f.id === locationId) return f; - } - - Lib.log([ - 'Location with id', locationId, - 'does not have a matching topojson feature at this resolution.' - ].join(' ')); - } - - return false; -} - -module.exports = { - locationToFeature: locationToFeature -}; - -},{"../lib":719,"country-regex":134}],714:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var BADNUM = _dereq_('../constants/numerical').BADNUM; - -/** - * Convert calcTrace to GeoJSON 'MultiLineString' coordinate arrays - * - * @param {object} calcTrace - * gd.calcdata item. - * Note that calcTrace[i].lonlat is assumed to be defined - * - * @return {array} - * return line coords array (or array of arrays) - * - */ -exports.calcTraceToLineCoords = function(calcTrace) { - var trace = calcTrace[0].trace; - var connectgaps = trace.connectgaps; - - var coords = []; - var lineString = []; - - for(var i = 0; i < calcTrace.length; i++) { - var calcPt = calcTrace[i]; - var lonlat = calcPt.lonlat; - - if(lonlat[0] !== BADNUM) { - lineString.push(lonlat); - } else if(!connectgaps && lineString.length > 0) { - coords.push(lineString); - lineString = []; - } - } - - if(lineString.length > 0) { - coords.push(lineString); - } - - return coords; -}; - - -/** - * Make line ('LineString' or 'MultiLineString') GeoJSON - * - * @param {array} coords - * results form calcTraceToLineCoords - * @return {object} out - * GeoJSON object - * - */ -exports.makeLine = function(coords) { - if(coords.length === 1) { - return { - type: 'LineString', - coordinates: coords[0] - }; - } else { - return { - type: 'MultiLineString', - coordinates: coords - }; - } -}; - -/** - * Make polygon ('Polygon' or 'MultiPolygon') GeoJSON - * - * @param {array} coords - * results form calcTraceToLineCoords - * @return {object} out - * GeoJSON object - */ -exports.makePolygon = function(coords) { - if(coords.length === 1) { - return { - type: 'Polygon', - coordinates: coords - }; - } else { - var _coords = new Array(coords.length); - - for(var i = 0; i < coords.length; i++) { - _coords[i] = [coords[i]]; - } - - return { - type: 'MultiPolygon', - coordinates: _coords - }; - } -}; - -/** - * Make blank GeoJSON - * - * @return {object} - * Blank GeoJSON object - * - */ -exports.makeBlank = function() { - return { - type: 'Point', - coordinates: [] - }; -}; - -},{"../constants/numerical":695}],715:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var mod = _dereq_('./mod').mod; - -/* - * look for intersection of two line segments - * (1->2 and 3->4) - returns array [x,y] if they do, null if not - */ -exports.segmentsIntersect = segmentsIntersect; -function segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4) { - var a = x2 - x1; - var b = x3 - x1; - var c = x4 - x3; - var d = y2 - y1; - var e = y3 - y1; - var f = y4 - y3; - var det = a * f - c * d; - // parallel lines? intersection is undefined - // ignore the case where they are colinear - if(det === 0) return null; - var t = (b * f - c * e) / det; - var u = (b * d - a * e) / det; - // segments do not intersect? - if(u < 0 || u > 1 || t < 0 || t > 1) return null; - - return {x: x1 + a * t, y: y1 + d * t}; -} - -/* - * find the minimum distance between two line segments (1->2 and 3->4) - */ -exports.segmentDistance = function segmentDistance(x1, y1, x2, y2, x3, y3, x4, y4) { - if(segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) return 0; - - // the two segments and their lengths squared - var x12 = x2 - x1; - var y12 = y2 - y1; - var x34 = x4 - x3; - var y34 = y4 - y3; - var ll12 = x12 * x12 + y12 * y12; - var ll34 = x34 * x34 + y34 * y34; - - // calculate distance squared, then take the sqrt at the very end - var dist2 = Math.min( - perpDistance2(x12, y12, ll12, x3 - x1, y3 - y1), - perpDistance2(x12, y12, ll12, x4 - x1, y4 - y1), - perpDistance2(x34, y34, ll34, x1 - x3, y1 - y3), - perpDistance2(x34, y34, ll34, x2 - x3, y2 - y3) - ); - - return Math.sqrt(dist2); -}; - -/* - * distance squared from segment ab to point c - * [xab, yab] is the vector b-a - * [xac, yac] is the vector c-a - * llab is the length squared of (b-a), just to simplify calculation - */ -function perpDistance2(xab, yab, llab, xac, yac) { - var fcAB = (xac * xab + yac * yab); - if(fcAB < 0) { - // point c is closer to point a - return xac * xac + yac * yac; - } else if(fcAB > llab) { - // point c is closer to point b - var xbc = xac - xab; - var ybc = yac - yab; - return xbc * xbc + ybc * ybc; - } else { - // perpendicular distance is the shortest - var crossProduct = xac * yab - yac * xab; - return crossProduct * crossProduct / llab; - } -} - -// a very short-term cache for getTextLocation, just because -// we're often looping over the same locations multiple times -// invalidated as soon as we look at a different path -var locationCache, workingPath, workingTextWidth; - -// turn a path and position along it into x, y, and angle for the given text -exports.getTextLocation = function getTextLocation(path, totalPathLen, positionOnPath, textWidth) { - if(path !== workingPath || textWidth !== workingTextWidth) { - locationCache = {}; - workingPath = path; - workingTextWidth = textWidth; - } - if(locationCache[positionOnPath]) { - return locationCache[positionOnPath]; - } - - // for the angle, use points on the path separated by the text width - // even though due to curvature, the text will cover a bit more than that - var p0 = path.getPointAtLength(mod(positionOnPath - textWidth / 2, totalPathLen)); - var p1 = path.getPointAtLength(mod(positionOnPath + textWidth / 2, totalPathLen)); - // note: atan handles 1/0 nicely - var theta = Math.atan((p1.y - p0.y) / (p1.x - p0.x)); - // center the text at 2/3 of the center position plus 1/3 the p0/p1 midpoint - // that's the average position of this segment, assuming it's roughly quadratic - var pCenter = path.getPointAtLength(mod(positionOnPath, totalPathLen)); - var x = (pCenter.x * 4 + p0.x + p1.x) / 6; - var y = (pCenter.y * 4 + p0.y + p1.y) / 6; - - var out = {x: x, y: y, theta: theta}; - locationCache[positionOnPath] = out; - return out; -}; - -exports.clearLocationCache = function() { - workingPath = null; -}; - -/* - * Find the segment of `path` that's within the visible area - * given by `bounds` {left, right, top, bottom}, to within a - * precision of `buffer` px - * - * returns: undefined if nothing is visible, else object: - * { - * min: position where the path first enters bounds, or 0 if it - * starts within bounds - * max: position where the path last exits bounds, or the path length - * if it finishes within bounds - * len: max - min, ie the length of visible path - * total: the total path length - just included so the caller doesn't - * need to call path.getTotalLength() again - * isClosed: true iff the start and end points of the path are both visible - * and are at the same point - * } - * - * Works by starting from either end and repeatedly finding the distance from - * that point to the plot area, and if it's outside the plot, moving along the - * path by that distance (because the plot must be at least that far away on - * the path). Note that if a path enters, exits, and re-enters the plot, we - * will not capture this behavior. - */ -exports.getVisibleSegment = function getVisibleSegment(path, bounds, buffer) { - var left = bounds.left; - var right = bounds.right; - var top = bounds.top; - var bottom = bounds.bottom; - - var pMin = 0; - var pTotal = path.getTotalLength(); - var pMax = pTotal; - - var pt0, ptTotal; - - function getDistToPlot(len) { - var pt = path.getPointAtLength(len); - - // hold on to the start and end points for `closed` - if(len === 0) pt0 = pt; - else if(len === pTotal) ptTotal = pt; - - var dx = (pt.x < left) ? left - pt.x : (pt.x > right ? pt.x - right : 0); - var dy = (pt.y < top) ? top - pt.y : (pt.y > bottom ? pt.y - bottom : 0); - return Math.sqrt(dx * dx + dy * dy); - } - - var distToPlot = getDistToPlot(pMin); - while(distToPlot) { - pMin += distToPlot + buffer; - if(pMin > pMax) return; - distToPlot = getDistToPlot(pMin); - } - - distToPlot = getDistToPlot(pMax); - while(distToPlot) { - pMax -= distToPlot + buffer; - if(pMin > pMax) return; - distToPlot = getDistToPlot(pMax); - } - - return { - min: pMin, - max: pMax, - len: pMax - pMin, - total: pTotal, - isClosed: pMin === 0 && pMax === pTotal && - Math.abs(pt0.x - ptTotal.x) < 0.1 && - Math.abs(pt0.y - ptTotal.y) < 0.1 - }; -}; - -/** - * Find point on SVG path corresponding to a given constraint coordinate - * - * @param {SVGPathElement} path - * @param {Number} val : constraint coordinate value - * @param {String} coord : 'x' or 'y' the constraint coordinate - * @param {Object} opts : - * - {Number} pathLength : supply total path length before hand - * - {Number} tolerance - * - {Number} iterationLimit - * @return {SVGPoint} - */ -exports.findPointOnPath = function findPointOnPath(path, val, coord, opts) { - opts = opts || {}; - - var pathLength = opts.pathLength || path.getTotalLength(); - var tolerance = opts.tolerance || 1e-3; - var iterationLimit = opts.iterationLimit || 30; - - // if path starts at a val greater than the path tail (like on vertical violins), - // we must flip the sign of the computed diff. - var mul = path.getPointAtLength(0)[coord] > path.getPointAtLength(pathLength)[coord] ? -1 : 1; - - var i = 0; - var b0 = 0; - var b1 = pathLength; - var mid; - var pt; - var diff; - - while(i < iterationLimit) { - mid = (b0 + b1) / 2; - pt = path.getPointAtLength(mid); - diff = pt[coord] - val; - - if(Math.abs(diff) < tolerance) { - return pt; - } else { - if(mul * diff > 0) { - b1 = mid; - } else { - b0 = mid; - } - i++; - } - } - return pt; -}; - -},{"./mod":726}],716:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var tinycolor = _dereq_('tinycolor2'); -var rgba = _dereq_('color-normalize'); - -var Colorscale = _dereq_('../components/colorscale'); -var colorDflt = _dereq_('../components/color/attributes').defaultLine; -var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; - -var colorDfltRgba = rgba(colorDflt); -var opacityDflt = 1; - -function calculateColor(colorIn, opacityIn) { - var colorOut = colorIn; - colorOut[3] *= opacityIn; - return colorOut; -} - -function validateColor(colorIn) { - if(isNumeric(colorIn)) return colorDfltRgba; - - var colorOut = rgba(colorIn); - - return colorOut.length ? colorOut : colorDfltRgba; -} - -function validateOpacity(opacityIn) { - return isNumeric(opacityIn) ? opacityIn : opacityDflt; -} - -function formatColor(containerIn, opacityIn, len) { - var colorIn = containerIn.color; - var isArrayColorIn = isArrayOrTypedArray(colorIn); - var isArrayOpacityIn = isArrayOrTypedArray(opacityIn); - var cOpts = Colorscale.extractOpts(containerIn); - var colorOut = []; - - var sclFunc, getColor, getOpacity, colori, opacityi; - - if(cOpts.colorscale !== undefined) { - sclFunc = Colorscale.makeColorScaleFuncFromTrace(containerIn); - } else { - sclFunc = validateColor; - } - - if(isArrayColorIn) { - getColor = function(c, i) { - // FIXME: there is double work, considering that sclFunc does the opposite - return c[i] === undefined ? colorDfltRgba : rgba(sclFunc(c[i])); - }; - } else getColor = validateColor; - - if(isArrayOpacityIn) { - getOpacity = function(o, i) { - return o[i] === undefined ? opacityDflt : validateOpacity(o[i]); - }; - } else getOpacity = validateOpacity; - - if(isArrayColorIn || isArrayOpacityIn) { - for(var i = 0; i < len; i++) { - colori = getColor(colorIn, i); - opacityi = getOpacity(opacityIn, i); - colorOut[i] = calculateColor(colori, opacityi); - } - } else colorOut = calculateColor(rgba(colorIn), opacityIn); - - return colorOut; -} - -function parseColorScale(cont, alpha) { - if(alpha === undefined) alpha = 1; - - var cOpts = Colorscale.extractOpts(cont); - - var colorscale = cOpts.reversescale ? - Colorscale.flipScale(cOpts.colorscale) : - cOpts.colorscale; - - return colorscale.map(function(elem) { - var index = elem[0]; - var color = tinycolor(elem[1]); - var rgb = color.toRgb(); - return { - index: index, - rgb: [rgb.r, rgb.g, rgb.b, alpha] - }; - }); -} - -module.exports = { - formatColor: formatColor, - parseColorScale: parseColorScale -}; - -},{"../components/color/attributes":592,"../components/colorscale":605,"./array":702,"color-normalize":120,"fast-isnumeric":225,"tinycolor2":537}],717:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var identity = _dereq_('./identity'); - -function wrap(d) {return [d];} - -module.exports = { - - // The D3 data binding concept and the General Update Pattern promotes the idea of - // traversing into the scenegraph by using the `.data(fun, keyFun)` call. - // The `fun` is most often a `repeat`, ie. the elements beneath a `` element need - // access to the same data, or a `descend`, which fans a scenegraph node into a bunch of - // of elements, e.g. points, lines, rows, requiring an array as input. - // The role of the `keyFun` is to identify what elements are being entered/exited/updated, - // otherwise D3 reverts to using a plain index which would screw up `transition`s. - keyFun: function(d) {return d.key;}, - repeat: wrap, - descend: identity, - - // Plotly.js uses a convention of storing the actual contents of the `calcData` as the - // element zero of a container array. These helpers are just used for clarity as a - // newcomer to the codebase may not know what the `[0]` is, and whether there can be further - // elements (not atm). - wrap: wrap, - unwrap: function(d) {return d[0];} -}; - -},{"./identity":718}],718:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -// Simple helper functions -// none of these need any external deps - -module.exports = function identity(d) { return d; }; - -},{}],719:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var numConstants = _dereq_('../constants/numerical'); -var FP_SAFE = numConstants.FP_SAFE; -var BADNUM = numConstants.BADNUM; - -var lib = module.exports = {}; - -lib.nestedProperty = _dereq_('./nested_property'); -lib.keyedContainer = _dereq_('./keyed_container'); -lib.relativeAttr = _dereq_('./relative_attr'); -lib.isPlainObject = _dereq_('./is_plain_object'); -lib.toLogRange = _dereq_('./to_log_range'); -lib.relinkPrivateKeys = _dereq_('./relink_private'); - -var arrayModule = _dereq_('./array'); -lib.isTypedArray = arrayModule.isTypedArray; -lib.isArrayOrTypedArray = arrayModule.isArrayOrTypedArray; -lib.isArray1D = arrayModule.isArray1D; -lib.ensureArray = arrayModule.ensureArray; -lib.concat = arrayModule.concat; -lib.maxRowLength = arrayModule.maxRowLength; -lib.minRowLength = arrayModule.minRowLength; - -var modModule = _dereq_('./mod'); -lib.mod = modModule.mod; -lib.modHalf = modModule.modHalf; - -var coerceModule = _dereq_('./coerce'); -lib.valObjectMeta = coerceModule.valObjectMeta; -lib.coerce = coerceModule.coerce; -lib.coerce2 = coerceModule.coerce2; -lib.coerceFont = coerceModule.coerceFont; -lib.coerceHoverinfo = coerceModule.coerceHoverinfo; -lib.coerceSelectionMarkerOpacity = coerceModule.coerceSelectionMarkerOpacity; -lib.validate = coerceModule.validate; - -var datesModule = _dereq_('./dates'); -lib.dateTime2ms = datesModule.dateTime2ms; -lib.isDateTime = datesModule.isDateTime; -lib.ms2DateTime = datesModule.ms2DateTime; -lib.ms2DateTimeLocal = datesModule.ms2DateTimeLocal; -lib.cleanDate = datesModule.cleanDate; -lib.isJSDate = datesModule.isJSDate; -lib.formatDate = datesModule.formatDate; -lib.incrementMonth = datesModule.incrementMonth; -lib.dateTick0 = datesModule.dateTick0; -lib.dfltRange = datesModule.dfltRange; -lib.findExactDates = datesModule.findExactDates; -lib.MIN_MS = datesModule.MIN_MS; -lib.MAX_MS = datesModule.MAX_MS; - -var searchModule = _dereq_('./search'); -lib.findBin = searchModule.findBin; -lib.sorterAsc = searchModule.sorterAsc; -lib.sorterDes = searchModule.sorterDes; -lib.distinctVals = searchModule.distinctVals; -lib.roundUp = searchModule.roundUp; -lib.sort = searchModule.sort; -lib.findIndexOfMin = searchModule.findIndexOfMin; - -var statsModule = _dereq_('./stats'); -lib.aggNums = statsModule.aggNums; -lib.len = statsModule.len; -lib.mean = statsModule.mean; -lib.median = statsModule.median; -lib.midRange = statsModule.midRange; -lib.variance = statsModule.variance; -lib.stdev = statsModule.stdev; -lib.interp = statsModule.interp; - -var matrixModule = _dereq_('./matrix'); -lib.init2dArray = matrixModule.init2dArray; -lib.transposeRagged = matrixModule.transposeRagged; -lib.dot = matrixModule.dot; -lib.translationMatrix = matrixModule.translationMatrix; -lib.rotationMatrix = matrixModule.rotationMatrix; -lib.rotationXYMatrix = matrixModule.rotationXYMatrix; -lib.apply2DTransform = matrixModule.apply2DTransform; -lib.apply2DTransform2 = matrixModule.apply2DTransform2; - -var anglesModule = _dereq_('./angles'); -lib.deg2rad = anglesModule.deg2rad; -lib.rad2deg = anglesModule.rad2deg; -lib.angleDelta = anglesModule.angleDelta; -lib.angleDist = anglesModule.angleDist; -lib.isFullCircle = anglesModule.isFullCircle; -lib.isAngleInsideSector = anglesModule.isAngleInsideSector; -lib.isPtInsideSector = anglesModule.isPtInsideSector; -lib.pathArc = anglesModule.pathArc; -lib.pathSector = anglesModule.pathSector; -lib.pathAnnulus = anglesModule.pathAnnulus; - -var anchorUtils = _dereq_('./anchor_utils'); -lib.isLeftAnchor = anchorUtils.isLeftAnchor; -lib.isCenterAnchor = anchorUtils.isCenterAnchor; -lib.isRightAnchor = anchorUtils.isRightAnchor; -lib.isTopAnchor = anchorUtils.isTopAnchor; -lib.isMiddleAnchor = anchorUtils.isMiddleAnchor; -lib.isBottomAnchor = anchorUtils.isBottomAnchor; - -var geom2dModule = _dereq_('./geometry2d'); -lib.segmentsIntersect = geom2dModule.segmentsIntersect; -lib.segmentDistance = geom2dModule.segmentDistance; -lib.getTextLocation = geom2dModule.getTextLocation; -lib.clearLocationCache = geom2dModule.clearLocationCache; -lib.getVisibleSegment = geom2dModule.getVisibleSegment; -lib.findPointOnPath = geom2dModule.findPointOnPath; - -var extendModule = _dereq_('./extend'); -lib.extendFlat = extendModule.extendFlat; -lib.extendDeep = extendModule.extendDeep; -lib.extendDeepAll = extendModule.extendDeepAll; -lib.extendDeepNoArrays = extendModule.extendDeepNoArrays; - -var loggersModule = _dereq_('./loggers'); -lib.log = loggersModule.log; -lib.warn = loggersModule.warn; -lib.error = loggersModule.error; - -var regexModule = _dereq_('./regex'); -lib.counterRegex = regexModule.counter; - -var throttleModule = _dereq_('./throttle'); -lib.throttle = throttleModule.throttle; -lib.throttleDone = throttleModule.done; -lib.clearThrottle = throttleModule.clear; - -var domModule = _dereq_('./dom'); -lib.getGraphDiv = domModule.getGraphDiv; -lib.isPlotDiv = domModule.isPlotDiv; -lib.removeElement = domModule.removeElement; -lib.addStyleRule = domModule.addStyleRule; -lib.addRelatedStyleRule = domModule.addRelatedStyleRule; -lib.deleteRelatedStyleRule = domModule.deleteRelatedStyleRule; - -lib.clearResponsive = _dereq_('./clear_responsive'); - -lib.makeTraceGroups = _dereq_('./make_trace_groups'); - -lib._ = _dereq_('./localize'); - -lib.notifier = _dereq_('./notifier'); - -lib.filterUnique = _dereq_('./filter_unique'); -lib.filterVisible = _dereq_('./filter_visible'); -lib.pushUnique = _dereq_('./push_unique'); - -lib.cleanNumber = _dereq_('./clean_number'); - -lib.ensureNumber = function ensureNumber(v) { - if(!isNumeric(v)) return BADNUM; - v = Number(v); - if(v < -FP_SAFE || v > FP_SAFE) return BADNUM; - return isNumeric(v) ? Number(v) : BADNUM; -}; - -/** - * Is v a valid array index? Accepts numeric strings as well as numbers. - * - * @param {any} v: the value to test - * @param {Optional[integer]} len: the array length we are indexing - * - * @return {bool}: v is a valid array index - */ -lib.isIndex = function(v, len) { - if(len !== undefined && v >= len) return false; - return isNumeric(v) && (v >= 0) && (v % 1 === 0); -}; - -lib.noop = _dereq_('./noop'); -lib.identity = _dereq_('./identity'); - -/** - * create an array of length 'cnt' filled with 'v' at all indices - * - * @param {any} v - * @param {number} cnt - * @return {array} - */ -lib.repeat = function(v, cnt) { - var out = new Array(cnt); - for(var i = 0; i < cnt; i++) { - out[i] = v; - } - return out; -}; - -/** - * swap x and y of the same attribute in container cont - * specify attr with a ? in place of x/y - * you can also swap other things than x/y by providing part1 and part2 - */ -lib.swapAttrs = function(cont, attrList, part1, part2) { - if(!part1) part1 = 'x'; - if(!part2) part2 = 'y'; - for(var i = 0; i < attrList.length; i++) { - var attr = attrList[i]; - var xp = lib.nestedProperty(cont, attr.replace('?', part1)); - var yp = lib.nestedProperty(cont, attr.replace('?', part2)); - var temp = xp.get(); - xp.set(yp.get()); - yp.set(temp); - } -}; - -/** - * SVG painter's algo worked around with reinsertion - */ -lib.raiseToTop = function raiseToTop(elem) { - elem.parentNode.appendChild(elem); -}; - -/** - * cancel a possibly pending transition; returned selection may be used by caller - */ -lib.cancelTransition = function(selection) { - return selection.transition().duration(0); -}; - -// constrain - restrict a number v to be between v0 and v1 -lib.constrain = function(v, v0, v1) { - if(v0 > v1) return Math.max(v1, Math.min(v0, v)); - return Math.max(v0, Math.min(v1, v)); -}; - -/** - * do two bounding boxes from getBoundingClientRect, - * ie {left,right,top,bottom,width,height}, overlap? - * takes optional padding pixels - */ -lib.bBoxIntersect = function(a, b, pad) { - pad = pad || 0; - return (a.left <= b.right + pad && - b.left <= a.right + pad && - a.top <= b.bottom + pad && - b.top <= a.bottom + pad); -}; - -/* - * simpleMap: alternative to Array.map that only - * passes on the element and up to 2 extra args you - * provide (but not the array index or the whole array) - * - * array: the array to map it to - * func: the function to apply - * x1, x2: optional extra args - */ -lib.simpleMap = function(array, func, x1, x2) { - var len = array.length; - var out = new Array(len); - for(var i = 0; i < len; i++) out[i] = func(array[i], x1, x2); - return out; -}; - -/** - * Random string generator - * - * @param {object} existing - * pass in strings to avoid as keys with truthy values - * @param {int} bits - * bits of information in the output string, default 24 - * @param {int} base - * base of string representation, default 16. Should be a power of 2. - */ -lib.randstr = function randstr(existing, bits, base, _recursion) { - if(!base) base = 16; - if(bits === undefined) bits = 24; - if(bits <= 0) return '0'; - - var digits = Math.log(Math.pow(2, bits)) / Math.log(base); - var res = ''; - var i, b, x; - - for(i = 2; digits === Infinity; i *= 2) { - digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i; - } - - var rem = digits - Math.floor(digits); - - for(i = 0; i < Math.floor(digits); i++) { - x = Math.floor(Math.random() * base).toString(base); - res = x + res; - } - - if(rem) { - b = Math.pow(base, rem); - x = Math.floor(Math.random() * b).toString(base); - res = x + res; - } - - var parsed = parseInt(res, base); - if((existing && existing[res]) || - (parsed !== Infinity && parsed >= Math.pow(2, bits))) { - if(_recursion > 10) { - lib.warn('randstr failed uniqueness'); - return res; - } - return randstr(existing, bits, base, (_recursion || 0) + 1); - } else return res; -}; - -lib.OptionControl = function(opt, optname) { - /* - * An environment to contain all option setters and - * getters that collectively modify opts. - * - * You can call up opts from any function in new object - * as this.optname || this.opt - * - * See FitOpts for example of usage - */ - if(!opt) opt = {}; - if(!optname) optname = 'opt'; - - var self = {}; - self.optionList = []; - - self._newoption = function(optObj) { - optObj[optname] = opt; - self[optObj.name] = optObj; - self.optionList.push(optObj); - }; - - self['_' + optname] = opt; - return self; -}; - -/** - * lib.smooth: smooth arrayIn by convolving with - * a hann window with given full width at half max - * bounce the ends in, so the output has the same length as the input - */ -lib.smooth = function(arrayIn, FWHM) { - FWHM = Math.round(FWHM) || 0; // only makes sense for integers - if(FWHM < 2) return arrayIn; - - var alen = arrayIn.length; - var alen2 = 2 * alen; - var wlen = 2 * FWHM - 1; - var w = new Array(wlen); - var arrayOut = new Array(alen); - var i; - var j; - var k; - var v; - - // first make the window array - for(i = 0; i < wlen; i++) { - w[i] = (1 - Math.cos(Math.PI * (i + 1) / FWHM)) / (2 * FWHM); - } - - // now do the convolution - for(i = 0; i < alen; i++) { - v = 0; - for(j = 0; j < wlen; j++) { - k = i + j + 1 - FWHM; - - // multibounce - if(k < -alen) k -= alen2 * Math.round(k / alen2); - else if(k >= alen2) k -= alen2 * Math.floor(k / alen2); - - // single bounce - if(k < 0) k = - 1 - k; - else if(k >= alen) k = alen2 - 1 - k; - - v += arrayIn[k] * w[j]; - } - arrayOut[i] = v; - } - - return arrayOut; -}; - -/** - * syncOrAsync: run a sequence of functions synchronously - * as long as its returns are not promises (ie have no .then) - * includes one argument arg to send to all functions... - * this is mainly just to prevent us having to make wrapper functions - * when the only purpose of the wrapper is to reference gd - * and a final step to be executed at the end - * TODO: if there's an error and everything is sync, - * this doesn't happen yet because we want to make sure - * that it gets reported - */ -lib.syncOrAsync = function(sequence, arg, finalStep) { - var ret, fni; - - function continueAsync() { - return lib.syncOrAsync(sequence, arg, finalStep); - } - - while(sequence.length) { - fni = sequence.splice(0, 1)[0]; - ret = fni(arg); - - if(ret && ret.then) { - return ret.then(continueAsync) - .then(undefined, lib.promiseError); - } - } - - return finalStep && finalStep(arg); -}; - - -/** - * Helper to strip trailing slash, from - * http://stackoverflow.com/questions/6680825/return-string-without-trailing-slash - */ -lib.stripTrailingSlash = function(str) { - if(str.substr(-1) === '/') return str.substr(0, str.length - 1); - return str; -}; - -lib.noneOrAll = function(containerIn, containerOut, attrList) { - /** - * some attributes come together, so if you have one of them - * in the input, you should copy the default values of the others - * to the input as well. - */ - if(!containerIn) return; - - var hasAny = false; - var hasAll = true; - var i; - var val; - - for(i = 0; i < attrList.length; i++) { - val = containerIn[attrList[i]]; - if(val !== undefined && val !== null) hasAny = true; - else hasAll = false; - } - - if(hasAny && !hasAll) { - for(i = 0; i < attrList.length; i++) { - containerIn[attrList[i]] = containerOut[attrList[i]]; - } - } -}; - -/** merges calcdata field (given by cdAttr) with traceAttr values - * - * N.B. Loop over minimum of cd.length and traceAttr.length - * i.e. it does not try to fill in beyond traceAttr.length-1 - * - * @param {array} traceAttr : trace attribute - * @param {object} cd : calcdata trace - * @param {string} cdAttr : calcdata key - */ -lib.mergeArray = function(traceAttr, cd, cdAttr, fn) { - var hasFn = typeof fn === 'function'; - if(lib.isArrayOrTypedArray(traceAttr)) { - var imax = Math.min(traceAttr.length, cd.length); - for(var i = 0; i < imax; i++) { - var v = traceAttr[i]; - cd[i][cdAttr] = hasFn ? fn(v) : v; - } - } -}; - -// cast numbers to positive numbers, returns 0 if not greater than 0 -lib.mergeArrayCastPositive = function(traceAttr, cd, cdAttr) { - return lib.mergeArray(traceAttr, cd, cdAttr, function(v) { - var w = +v; - return !isFinite(w) ? 0 : w > 0 ? w : 0; - }); -}; - -/** fills calcdata field (given by cdAttr) with traceAttr values - * or function of traceAttr values (e.g. some fallback) - * - * N.B. Loops over all cd items. - * - * @param {array} traceAttr : trace attribute - * @param {object} cd : calcdata trace - * @param {string} cdAttr : calcdata key - * @param {function} [fn] : optional function to apply to each array item - */ -lib.fillArray = function(traceAttr, cd, cdAttr, fn) { - fn = fn || lib.identity; - - if(lib.isArrayOrTypedArray(traceAttr)) { - for(var i = 0; i < cd.length; i++) { - cd[i][cdAttr] = fn(traceAttr[i]); - } - } -}; - -/** Handler for trace-wide vs per-point options - * - * @param {object} trace : (full) trace object - * @param {number} ptNumber : index of the point in question - * @param {string} astr : attribute string - * @param {function} [fn] : optional function to apply to each array item - * - * @return {any} - */ -lib.castOption = function(trace, ptNumber, astr, fn) { - fn = fn || lib.identity; - - var val = lib.nestedProperty(trace, astr).get(); - - if(lib.isArrayOrTypedArray(val)) { - if(Array.isArray(ptNumber) && lib.isArrayOrTypedArray(val[ptNumber[0]])) { - return fn(val[ptNumber[0]][ptNumber[1]]); - } else { - return fn(val[ptNumber]); - } - } else { - return val; - } -}; - -/** Extract option from calcdata item, correctly falling back to - * trace value if not found. - * - * @param {object} calcPt : calcdata[i][j] item - * @param {object} trace : (full) trace object - * @param {string} calcKey : calcdata key - * @param {string} traceKey : aka trace attribute string - * @return {any} - */ -lib.extractOption = function(calcPt, trace, calcKey, traceKey) { - if(calcKey in calcPt) return calcPt[calcKey]; - - // fallback to trace value, - // must check if value isn't itself an array - // which means the trace attribute has a corresponding - // calcdata key, but its value is falsy - var traceVal = lib.nestedProperty(trace, traceKey).get(); - if(!Array.isArray(traceVal)) return traceVal; -}; - -function makePtIndex2PtNumber(indexToPoints) { - var ptIndex2ptNumber = {}; - for(var k in indexToPoints) { - var pts = indexToPoints[k]; - for(var j = 0; j < pts.length; j++) { - ptIndex2ptNumber[pts[j]] = +k; - } - } - return ptIndex2ptNumber; -} - -/** Tag selected calcdata items - * - * N.B. note that point 'index' corresponds to input data array index - * whereas 'number' is its post-transform version. - * - * @param {array} calcTrace - * @param {object} trace - * - selectedpoints {array} - * - _indexToPoints {object} - * @param {ptNumber2cdIndex} ptNumber2cdIndex (optional) - * optional map object for trace types that do not have 1-to-1 point number to - * calcdata item index correspondence (e.g. histogram) - */ -lib.tagSelected = function(calcTrace, trace, ptNumber2cdIndex) { - var selectedpoints = trace.selectedpoints; - var indexToPoints = trace._indexToPoints; - var ptIndex2ptNumber; - - // make pt index-to-number map object, which takes care of transformed traces - if(indexToPoints) { - ptIndex2ptNumber = makePtIndex2PtNumber(indexToPoints); - } - - function isCdIndexValid(v) { - return v !== undefined && v < calcTrace.length; - } - - for(var i = 0; i < selectedpoints.length; i++) { - var ptIndex = selectedpoints[i]; - - if(lib.isIndex(ptIndex)) { - var ptNumber = ptIndex2ptNumber ? ptIndex2ptNumber[ptIndex] : ptIndex; - var cdIndex = ptNumber2cdIndex ? ptNumber2cdIndex[ptNumber] : ptNumber; - - if(isCdIndexValid(cdIndex)) { - calcTrace[cdIndex].selected = 1; - } - } - } -}; - -lib.selIndices2selPoints = function(trace) { - var selectedpoints = trace.selectedpoints; - var indexToPoints = trace._indexToPoints; - - if(indexToPoints) { - var ptIndex2ptNumber = makePtIndex2PtNumber(indexToPoints); - var out = []; - - for(var i = 0; i < selectedpoints.length; i++) { - var ptIndex = selectedpoints[i]; - if(lib.isIndex(ptIndex)) { - var ptNumber = ptIndex2ptNumber[ptIndex]; - if(lib.isIndex(ptNumber)) { - out.push(ptNumber); - } - } - } - - return out; - } else { - return selectedpoints; - } -}; - -/** Returns target as set by 'target' transform attribute - * - * @param {object} trace : full trace object - * @param {object} transformOpts : transform option object - * - target (string} : - * either an attribute string referencing an array in the trace object, or - * a set array. - * - * @return {array or false} : the target array (NOT a copy!!) or false if invalid - */ -lib.getTargetArray = function(trace, transformOpts) { - var target = transformOpts.target; - - if(typeof target === 'string' && target) { - var array = lib.nestedProperty(trace, target).get(); - return Array.isArray(array) ? array : false; - } else if(Array.isArray(target)) { - return target; - } - - return false; -}; - -/** - * modified version of jQuery's extend to strip out private objs and functions, - * and cut arrays down to first or 1 elements - * because extend-like algorithms are hella slow - * obj2 is assumed to already be clean of these things (including no arrays) - */ -lib.minExtend = function(obj1, obj2) { - var objOut = {}; - if(typeof obj2 !== 'object') obj2 = {}; - var arrayLen = 3; - var keys = Object.keys(obj1); - var i, k, v; - - for(i = 0; i < keys.length; i++) { - k = keys[i]; - v = obj1[k]; - if(k.charAt(0) === '_' || typeof v === 'function') continue; - else if(k === 'module') objOut[k] = v; - else if(Array.isArray(v)) { - if(k === 'colorscale') { - objOut[k] = v.slice(); - } else { - objOut[k] = v.slice(0, arrayLen); - } - } else if(v && (typeof v === 'object')) objOut[k] = lib.minExtend(obj1[k], obj2[k]); - else objOut[k] = v; - } - - keys = Object.keys(obj2); - for(i = 0; i < keys.length; i++) { - k = keys[i]; - v = obj2[k]; - if(typeof v !== 'object' || !(k in objOut) || typeof objOut[k] !== 'object') { - objOut[k] = v; - } - } - - return objOut; -}; - -lib.titleCase = function(s) { - return s.charAt(0).toUpperCase() + s.substr(1); -}; - -lib.containsAny = function(s, fragments) { - for(var i = 0; i < fragments.length; i++) { - if(s.indexOf(fragments[i]) !== -1) return true; - } - return false; -}; - -lib.isIE = function() { - return typeof window.navigator.msSaveBlob !== 'undefined'; -}; - -var IS_IE9_OR_BELOW_REGEX = /MSIE [1-9]\./; -lib.isIE9orBelow = function() { - return lib.isIE() && IS_IE9_OR_BELOW_REGEX.test(window.navigator.userAgent); -}; - -var IS_SAFARI_REGEX = /Version\/[\d\.]+.*Safari/; -lib.isSafari = function() { - return IS_SAFARI_REGEX.test(window.navigator.userAgent); -}; - -/** - * Duck typing to recognize a d3 selection, mostly for IE9's benefit - * because it doesn't handle instanceof like modern browsers - */ -lib.isD3Selection = function(obj) { - return obj && (typeof obj.classed === 'function'); -}; - -/** - * Append element to DOM only if not present. - * - * @param {d3 selection} parent : parent selection of the element in question - * @param {string} nodeType : node type of element to append - * @param {string} className (optional) : class name of element in question - * @param {fn} enterFn (optional) : optional fn applied to entering elements only - * @return {d3 selection} selection of new layer - * - * Previously, we were using the following pattern: - * - * ``` - * var sel = parent.selectAll('.' + className) - * .data([0]); - * - * sel.enter().append(nodeType) - * .classed(className, true); - * - * return sel; - * ``` - * - * in numerous places in our codebase to achieve the same behavior. - * - * The logic below performs much better, mostly as we are using - * `.select` instead `.selectAll` that is `querySelector` instead of - * `querySelectorAll`. - * - */ -lib.ensureSingle = function(parent, nodeType, className, enterFn) { - var sel = parent.select(nodeType + (className ? '.' + className : '')); - if(sel.size()) return sel; - - var layer = parent.append(nodeType); - if(className) layer.classed(className, true); - if(enterFn) layer.call(enterFn); - - return layer; -}; - -/** - * Same as Lib.ensureSingle, but using id as selector. - * This version is mostly used for clipPath nodes. - * - * @param {d3 selection} parent : parent selection of the element in question - * @param {string} nodeType : node type of element to append - * @param {string} id : id of element in question - * @param {fn} enterFn (optional) : optional fn applied to entering elements only - * @return {d3 selection} selection of new layer - */ -lib.ensureSingleById = function(parent, nodeType, id, enterFn) { - var sel = parent.select(nodeType + '#' + id); - if(sel.size()) return sel; - - var layer = parent.append(nodeType).attr('id', id); - if(enterFn) layer.call(enterFn); - - return layer; -}; - -/** - * Converts a string path to an object. - * - * When given a string containing an array element, it will create a `null` - * filled array of the given size. - * - * @example - * lib.objectFromPath('nested.test[2].path', 'value'); - * // returns { nested: { test: [null, null, { path: 'value' }]} - * - * @param {string} path to nested value - * @param {*} any value to be set - * - * @return {Object} the constructed object with a full nested path - */ -lib.objectFromPath = function(path, value) { - var keys = path.split('.'); - var tmpObj; - var obj = tmpObj = {}; - - for(var i = 0; i < keys.length; i++) { - var key = keys[i]; - var el = null; - - var parts = keys[i].match(/(.*)\[([0-9]+)\]/); - - if(parts) { - key = parts[1]; - el = parts[2]; - - tmpObj = tmpObj[key] = []; - - if(i === keys.length - 1) { - tmpObj[el] = value; - } else { - tmpObj[el] = {}; - } - - tmpObj = tmpObj[el]; - } else { - if(i === keys.length - 1) { - tmpObj[key] = value; - } else { - tmpObj[key] = {}; - } - - tmpObj = tmpObj[key]; - } - } - - return obj; -}; - -/** - * Iterate through an object in-place, converting dotted properties to objects. - * - * Examples: - * - * lib.expandObjectPaths({'nested.test.path': 'value'}); - * => { nested: { test: {path: 'value'}}} - * - * It also handles array notation, e.g.: - * - * lib.expandObjectPaths({'foo[1].bar': 'value'}); - * => { foo: [null, {bar: value}] } - * - * It handles merges the results when two properties are specified in parallel: - * - * lib.expandObjectPaths({'foo[1].bar': 10, 'foo[0].bar': 20}); - * => { foo: [{bar: 10}, {bar: 20}] } - * - * It does NOT, however, merge mulitple mutliply-nested arrays:: - * - * lib.expandObjectPaths({'marker[1].range[1]': 5, 'marker[1].range[0]': 4}) - * => { marker: [null, {range: 4}] } - */ - -// Store this to avoid recompiling regex on *every* prop since this may happen many -// many times for animations. Could maybe be inside the function. Not sure about -// scoping vs. recompilation tradeoff, but at least it's not just inlining it into -// the inner loop. -var dottedPropertyRegex = /^([^\[\.]+)\.(.+)?/; -var indexedPropertyRegex = /^([^\.]+)\[([0-9]+)\](\.)?(.+)?/; - -lib.expandObjectPaths = function(data) { - var match, key, prop, datum, idx, dest, trailingPath; - if(typeof data === 'object' && !Array.isArray(data)) { - for(key in data) { - if(data.hasOwnProperty(key)) { - if((match = key.match(dottedPropertyRegex))) { - datum = data[key]; - prop = match[1]; - - delete data[key]; - - data[prop] = lib.extendDeepNoArrays(data[prop] || {}, lib.objectFromPath(key, lib.expandObjectPaths(datum))[prop]); - } else if((match = key.match(indexedPropertyRegex))) { - datum = data[key]; - - prop = match[1]; - idx = parseInt(match[2]); - - delete data[key]; - - data[prop] = data[prop] || []; - - if(match[3] === '.') { - // This is the case where theere are subsequent properties into which - // we must recurse, e.g. transforms[0].value - trailingPath = match[4]; - dest = data[prop][idx] = data[prop][idx] || {}; - - // NB: Extend deep no arrays prevents this from working on multiple - // nested properties in the same object, e.g. - // - // { - // foo[0].bar[1].range - // foo[0].bar[0].range - // } - // - // In this case, the extendDeepNoArrays will overwrite one array with - // the other, so that both properties *will not* be present in the - // result. Fixing this would require a more intelligent tracking - // of changes and merging than extendDeepNoArrays currently accomplishes. - lib.extendDeepNoArrays(dest, lib.objectFromPath(trailingPath, lib.expandObjectPaths(datum))); - } else { - // This is the case where this property is the end of the line, - // e.g. xaxis.range[0] - data[prop][idx] = lib.expandObjectPaths(datum); - } - } else { - data[key] = lib.expandObjectPaths(data[key]); - } - } - } - } - - return data; -}; - -/** - * Converts value to string separated by the provided separators. - * - * @example - * lib.numSeparate(2016, '.,'); - * // returns '2016' - * - * @example - * lib.numSeparate(3000, '.,', true); - * // returns '3,000' - * - * @example - * lib.numSeparate(1234.56, '|,') - * // returns '1,234|56' - * - * @param {string|number} value the value to be converted - * @param {string} separators string of decimal, then thousands separators - * @param {boolean} separatethousands boolean, 4-digit integers are separated if true - * - * @return {string} the value that has been separated - */ -lib.numSeparate = function(value, separators, separatethousands) { - if(!separatethousands) separatethousands = false; - - if(typeof separators !== 'string' || separators.length === 0) { - throw new Error('Separator string required for formatting!'); - } - - if(typeof value === 'number') { - value = String(value); - } - - var thousandsRe = /(\d+)(\d{3})/; - var decimalSep = separators.charAt(0); - var thouSep = separators.charAt(1); - - var x = value.split('.'); - var x1 = x[0]; - var x2 = x.length > 1 ? decimalSep + x[1] : ''; - - // Years are ignored for thousands separators - if(thouSep && (x.length > 1 || x1.length > 4 || separatethousands)) { - while(thousandsRe.test(x1)) { - x1 = x1.replace(thousandsRe, '$1' + thouSep + '$2'); - } - } - - return x1 + x2; -}; - -lib.TEMPLATE_STRING_REGEX = /%{([^\s%{}:]*)(:[^}]*)?}/g; -var SIMPLE_PROPERTY_REGEX = /^\w*$/; - -/** - * Substitute values from an object into a string - * - * Examples: - * Lib.templateString('name: %{trace}', {trace: 'asdf'}) --> 'name: asdf' - * Lib.templateString('name: %{trace[0].name}', {trace: [{name: 'asdf'}]}) --> 'name: asdf' - * - * @param {string} input string containing %{...} template strings - * @param {obj} data object containing substitution values - * - * @return {string} templated string - */ -lib.templateString = function(string, obj) { - // Not all that useful, but cache nestedProperty instantiation - // just in case it speeds things up *slightly*: - var getterCache = {}; - - return string.replace(lib.TEMPLATE_STRING_REGEX, function(dummy, key) { - if(SIMPLE_PROPERTY_REGEX.test(key)) { - return obj[key] || ''; - } - getterCache[key] = getterCache[key] || lib.nestedProperty(obj, key).get; - return getterCache[key]() || ''; - }); -}; - -var TEMPLATE_STRING_FORMAT_SEPARATOR = /^:/; -var numberOfHoverTemplateWarnings = 0; -var maximumNumberOfHoverTemplateWarnings = 10; -/** - * Substitute values from an object into a string and optionally formats them using d3-format, - * or fallback to associated labels. - * - * Examples: - * Lib.hovertemplateString('name: %{trace}', {trace: 'asdf'}) --> 'name: asdf' - * Lib.hovertemplateString('name: %{trace[0].name}', {trace: [{name: 'asdf'}]}) --> 'name: asdf' - * Lib.hovertemplateString('price: %{y:$.2f}', {y: 1}) --> 'price: $1.00' - * - * @param {obj} d3 locale - * @param {string} input string containing %{...:...} template strings - * @param {obj} data object containing fallback text when no formatting is specified, ex.: {yLabel: 'formattedYValue'} - * @param {obj} data objects containing substitution values - * - * @return {string} templated string - */ -lib.hovertemplateString = function(string, labels, d3locale) { - var args = arguments; - // Not all that useful, but cache nestedProperty instantiation - // just in case it speeds things up *slightly*: - var getterCache = {}; - - return string.replace(lib.TEMPLATE_STRING_REGEX, function(match, key, format) { - var obj, value, i; - for(i = 3; i < args.length; i++) { - obj = args[i]; - if(obj.hasOwnProperty(key)) { - value = obj[key]; - break; - } - - if(!SIMPLE_PROPERTY_REGEX.test(key)) { - value = getterCache[key] || lib.nestedProperty(obj, key).get(); - if(value) getterCache[key] = value; - } - if(value !== undefined) break; - } - - if(value === undefined) { - if(numberOfHoverTemplateWarnings < maximumNumberOfHoverTemplateWarnings) { - lib.warn('Variable \'' + key + '\' in hovertemplate could not be found!'); - value = match; - } - - if(numberOfHoverTemplateWarnings === maximumNumberOfHoverTemplateWarnings) { - lib.warn('Too many hovertemplate warnings - additional warnings will be suppressed'); - } - numberOfHoverTemplateWarnings++; - } - - if(format) { - var fmt; - if(d3locale) { - fmt = d3locale.numberFormat; - } else { - fmt = d3.format; - } - value = fmt(format.replace(TEMPLATE_STRING_FORMAT_SEPARATOR, ''))(value); - } else { - if(labels.hasOwnProperty(key + 'Label')) value = labels[key + 'Label']; - } - return value; - }); -}; - -/* - * alphanumeric string sort, tailored for subplot IDs like scene2, scene10, x10y13 etc - */ -var char0 = 48; -var char9 = 57; -lib.subplotSort = function(a, b) { - var l = Math.min(a.length, b.length) + 1; - var numA = 0; - var numB = 0; - for(var i = 0; i < l; i++) { - var charA = a.charCodeAt(i) || 0; - var charB = b.charCodeAt(i) || 0; - var isNumA = charA >= char0 && charA <= char9; - var isNumB = charB >= char0 && charB <= char9; - - if(isNumA) numA = 10 * numA + charA - char0; - if(isNumB) numB = 10 * numB + charB - char0; - - if(!isNumA || !isNumB) { - if(numA !== numB) return numA - numB; - if(charA !== charB) return charA - charB; - } - } - return numB - numA; -}; - -// repeatable pseudorandom generator -var randSeed = 2000000000; - -lib.seedPseudoRandom = function() { - randSeed = 2000000000; -}; - -lib.pseudoRandom = function() { - var lastVal = randSeed; - randSeed = (69069 * randSeed + 1) % 4294967296; - // don't let consecutive vals be too close together - // gets away from really trying to be random, in favor of better local uniformity - if(Math.abs(randSeed - lastVal) < 429496729) return lib.pseudoRandom(); - return randSeed / 4294967296; -}; - - -/** Fill hover 'pointData' container with 'correct' hover text value - * - * - If trace hoverinfo contains a 'text' flag and hovertext is not set, - * the text elements will be seen in the hover labels. - * - * - If trace hoverinfo contains a 'text' flag and hovertext is set, - * hovertext takes precedence over text - * i.e. the hoverinfo elements will be seen in the hover labels - * - * @param {object} calcPt - * @param {object} trace - * @param {object || array} contOut (mutated here) - */ -lib.fillText = function(calcPt, trace, contOut) { - var fill = Array.isArray(contOut) ? - function(v) { contOut.push(v); } : - function(v) { contOut.text = v; }; - - var htx = lib.extractOption(calcPt, trace, 'htx', 'hovertext'); - if(lib.isValidTextValue(htx)) return fill(htx); - - var tx = lib.extractOption(calcPt, trace, 'tx', 'text'); - if(lib.isValidTextValue(tx)) return fill(tx); -}; - -// accept all truthy values and 0 (which gets cast to '0' in the hover labels) -lib.isValidTextValue = function(v) { - return v || v === 0; -}; - -lib.formatPercent = function(ratio, n) { - n = n || 0; - var str = (Math.round(100 * ratio * Math.pow(10, n)) * Math.pow(0.1, n)).toFixed(n) + '%'; - for(var i = 0; i < n; i++) { - if(str.indexOf('.') !== -1) { - str = str.replace('0%', '%'); - str = str.replace('.%', '%'); - } - } - return str; -}; - -lib.isHidden = function(gd) { - var display = window.getComputedStyle(gd).display; - return !display || display === 'none'; -}; - -},{"../constants/numerical":695,"./anchor_utils":700,"./angles":701,"./array":702,"./clean_number":703,"./clear_responsive":705,"./coerce":706,"./dates":707,"./dom":708,"./extend":710,"./filter_unique":711,"./filter_visible":712,"./geometry2d":715,"./identity":718,"./is_plain_object":720,"./keyed_container":721,"./localize":722,"./loggers":723,"./make_trace_groups":724,"./matrix":725,"./mod":726,"./nested_property":727,"./noop":728,"./notifier":729,"./push_unique":733,"./regex":735,"./relative_attr":736,"./relink_private":737,"./search":738,"./stats":741,"./throttle":744,"./to_log_range":745,"d3":163,"fast-isnumeric":225}],720:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -// more info: http://stackoverflow.com/questions/18531624/isplainobject-thing -module.exports = function isPlainObject(obj) { - // We need to be a little less strict in the `imagetest` container because - // of how async image requests are handled. - // - // N.B. isPlainObject(new Constructor()) will return true in `imagetest` - if(window && window.process && window.process.versions) { - return Object.prototype.toString.call(obj) === '[object Object]'; - } - - return ( - Object.prototype.toString.call(obj) === '[object Object]' && - Object.getPrototypeOf(obj) === Object.prototype - ); -}; - -},{}],721:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var nestedProperty = _dereq_('./nested_property'); - -var SIMPLE_PROPERTY_REGEX = /^\w*$/; - -// bitmask for deciding what's updated. Sometimes the name needs to be updated, -// sometimes the value needs to be updated, and sometimes both do. This is just -// a simple way to track what's updated such that it's a simple OR operation to -// assimilate new updates. -// -// The only exception is the UNSET bit that tracks when we need to explicitly -// unset and remove the property. This concrn arises because of the special -// way in which nestedProperty handles null/undefined. When you specify `null`, -// it prunes any unused items in the tree. I ran into some issues with it getting -// null vs undefined confused, so UNSET is just a bit that forces the property -// update to send `null`, removing the property explicitly rather than setting -// it to undefined. -var NONE = 0; -var NAME = 1; -var VALUE = 2; -var BOTH = 3; -var UNSET = 4; - -module.exports = function keyedContainer(baseObj, path, keyName, valueName) { - keyName = keyName || 'name'; - valueName = valueName || 'value'; - var i, arr, baseProp; - var changeTypes = {}; - - if(path && path.length) { - baseProp = nestedProperty(baseObj, path); - arr = baseProp.get(); - } else { - arr = baseObj; - } - - path = path || ''; - - // Construct an index: - var indexLookup = {}; - if(arr) { - for(i = 0; i < arr.length; i++) { - indexLookup[arr[i][keyName]] = i; - } - } - - var isSimpleValueProp = SIMPLE_PROPERTY_REGEX.test(valueName); - - var obj = { - set: function(name, value) { - var changeType = value === null ? UNSET : NONE; - - // create the base array if necessary - if(!arr) { - if(!baseProp || changeType === UNSET) return; - - arr = []; - baseProp.set(arr); - } - - var idx = indexLookup[name]; - if(idx === undefined) { - if(changeType === UNSET) return; - - changeType = changeType | BOTH; - idx = arr.length; - indexLookup[name] = idx; - } else if(value !== (isSimpleValueProp ? arr[idx][valueName] : nestedProperty(arr[idx], valueName).get())) { - changeType = changeType | VALUE; - } - - var newValue = arr[idx] = arr[idx] || {}; - newValue[keyName] = name; - - if(isSimpleValueProp) { - newValue[valueName] = value; - } else { - nestedProperty(newValue, valueName).set(value); - } - - // If it's not an unset, force that bit to be unset. This is all related to the fact - // that undefined and null are a bit specially implemented in nestedProperties. - if(value !== null) { - changeType = changeType & ~UNSET; - } - - changeTypes[idx] = changeTypes[idx] | changeType; - - return obj; - }, - get: function(name) { - if(!arr) return; - - var idx = indexLookup[name]; - - if(idx === undefined) { - return undefined; - } else if(isSimpleValueProp) { - return arr[idx][valueName]; - } else { - return nestedProperty(arr[idx], valueName).get(); - } - }, - rename: function(name, newName) { - var idx = indexLookup[name]; - - if(idx === undefined) return obj; - changeTypes[idx] = changeTypes[idx] | NAME; - - indexLookup[newName] = idx; - delete indexLookup[name]; - - arr[idx][keyName] = newName; - - return obj; - }, - remove: function(name) { - var idx = indexLookup[name]; - - if(idx === undefined) return obj; - - var object = arr[idx]; - if(Object.keys(object).length > 2) { - // This object contains more than just the key/value, so unset - // the value without modifying the entry otherwise: - changeTypes[idx] = changeTypes[idx] | VALUE; - return obj.set(name, null); - } - - if(isSimpleValueProp) { - for(i = idx; i < arr.length; i++) { - changeTypes[i] = changeTypes[i] | BOTH; - } - for(i = idx; i < arr.length; i++) { - indexLookup[arr[i][keyName]]--; - } - arr.splice(idx, 1); - delete(indexLookup[name]); - } else { - // Perform this update *strictly* so we can check whether the result's - // been pruned. If so, it's a removal. If not, it's a value unset only. - nestedProperty(object, valueName).set(null); - - // Now check if the top level nested property has any keys left. If so, - // the object still has values so we only want to unset the key. If not, - // the entire object can be removed since there's no other data. - // var topLevelKeys = Object.keys(object[valueName.split('.')[0]] || []); - - changeTypes[idx] = changeTypes[idx] | VALUE | UNSET; - } - - return obj; - }, - constructUpdate: function() { - var astr, idx; - var update = {}; - var changed = Object.keys(changeTypes); - for(var i = 0; i < changed.length; i++) { - idx = changed[i]; - astr = path + '[' + idx + ']'; - if(arr[idx]) { - if(changeTypes[idx] & NAME) { - update[astr + '.' + keyName] = arr[idx][keyName]; - } - if(changeTypes[idx] & VALUE) { - if(isSimpleValueProp) { - update[astr + '.' + valueName] = (changeTypes[idx] & UNSET) ? null : arr[idx][valueName]; - } else { - update[astr + '.' + valueName] = (changeTypes[idx] & UNSET) ? null : nestedProperty(arr[idx], valueName).get(); - } - } - } else { - update[astr] = null; - } - } - - return update; - } - }; - - return obj; -}; - -},{"./nested_property":727}],722:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Registry = _dereq_('../registry'); - -/** - * localize: translate a string for the current locale - * - * @param {object} gd: the graphDiv for context - * gd._context.locale determines the language (& optional region/country) - * the dictionary for each locale may either be supplied in - * gd._context.locales or globally via Plotly.register - * @param {string} s: the string to translate - */ -module.exports = function localize(gd, s) { - var locale = gd._context.locale; - - /* - * Priority of lookup: - * contextDicts[locale], - * registeredDicts[locale], - * contextDicts[baseLocale], (if baseLocale is distinct) - * registeredDicts[baseLocale] - * Return the first translation we find. - * This way if you have a regionalization you are allowed to specify - * only what's different from the base locale, everything else will - * fall back on the base. - */ - for(var i = 0; i < 2; i++) { - var locales = gd._context.locales; - for(var j = 0; j < 2; j++) { - var dict = (locales[locale] || {}).dictionary; - if(dict) { - var out = dict[s]; - if(out) return out; - } - locales = Registry.localeRegistry; - } - - var baseLocale = locale.split('-')[0]; - if(baseLocale === locale) break; - locale = baseLocale; - } - - return s; -}; - -},{"../registry":847}],723:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* eslint-disable no-console */ - -var dfltConfig = _dereq_('../plot_api/plot_config').dfltConfig; - -var loggers = module.exports = {}; - -/** - * ------------------------------------------ - * debugging tools - * ------------------------------------------ - */ - -loggers.log = function() { - if(dfltConfig.logging > 1) { - var messages = ['LOG:']; - - for(var i = 0; i < arguments.length; i++) { - messages.push(arguments[i]); - } - - apply(console.trace || console.log, messages); - } -}; - -loggers.warn = function() { - if(dfltConfig.logging > 0) { - var messages = ['WARN:']; - - for(var i = 0; i < arguments.length; i++) { - messages.push(arguments[i]); - } - - apply(console.trace || console.log, messages); - } -}; - -loggers.error = function() { - if(dfltConfig.logging > 0) { - var messages = ['ERROR:']; - - for(var i = 0; i < arguments.length; i++) { - messages.push(arguments[i]); - } - - apply(console.error, messages); - } -}; - -/* - * Robust apply, for IE9 where console.log doesn't support - * apply like other functions do - */ -function apply(f, args) { - if(f && f.apply) { - try { - // `this` should always be console, since here we're always - // applying a method of the console object. - f.apply(console, args); - return; - } catch(e) { /* in case apply failed, fall back on the code below */ } - } - - // no apply - just try calling the function on each arg independently - for(var i = 0; i < args.length; i++) { - try { - f(args[i]); - } catch(e) { - // still fails - last resort simple console.log - console.log(args[i]); - } - } -} - -},{"../plot_api/plot_config":755}],724:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -/** - * General helper to manage trace groups based on calcdata - * - * @param {d3.selection} traceLayer: a selection containing a single group - * to draw these traces into - * @param {array} cdModule: array of calcdata items for this - * module and subplot combination. Assumes the calcdata item for each - * trace is an array with the fullData trace attached to the first item. - * @param {string} cls: the class attribute to give each trace group - * so you can give multiple classes separated by spaces - */ -module.exports = function makeTraceGroups(traceLayer, cdModule, cls) { - var traces = traceLayer.selectAll('g.' + cls.replace(/\s/g, '.')) - .data(cdModule, function(cd) { return cd[0].trace.uid; }); - - traces.exit().remove(); - - traces.enter().append('g') - .attr('class', cls); - - traces.order(); - - // stash ref node to trace group in calcdata, - // useful for (fast) styleOnSelect - var k = traceLayer.classed('rangeplot') ? 'nodeRangePlot3' : 'node3'; - traces.each(function(cd) { cd[0][k] = d3.select(this); }); - - return traces; -}; - -},{"d3":163}],725:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -exports.init2dArray = function(rowLength, colLength) { - var array = new Array(rowLength); - for(var i = 0; i < rowLength; i++) array[i] = new Array(colLength); - return array; -}; - -/** - * transpose a (possibly ragged) 2d array z. inspired by - * http://stackoverflow.com/questions/17428587/ - * transposing-a-2d-array-in-javascript - */ -exports.transposeRagged = function(z) { - var maxlen = 0; - var zlen = z.length; - var i, j; - // Maximum row length: - for(i = 0; i < zlen; i++) maxlen = Math.max(maxlen, z[i].length); - - var t = new Array(maxlen); - for(i = 0; i < maxlen; i++) { - t[i] = new Array(zlen); - for(j = 0; j < zlen; j++) t[i][j] = z[j][i]; - } - - return t; -}; - -// our own dot function so that we don't need to include numeric -exports.dot = function(x, y) { - if(!(x.length && y.length) || x.length !== y.length) return null; - - var len = x.length; - var out; - var i; - - if(x[0].length) { - // mat-vec or mat-mat - out = new Array(len); - for(i = 0; i < len; i++) out[i] = exports.dot(x[i], y); - } else if(y[0].length) { - // vec-mat - var yTranspose = exports.transposeRagged(y); - out = new Array(yTranspose.length); - for(i = 0; i < yTranspose.length; i++) out[i] = exports.dot(x, yTranspose[i]); - } else { - // vec-vec - out = 0; - for(i = 0; i < len; i++) out += x[i] * y[i]; - } - - return out; -}; - -// translate by (x,y) -exports.translationMatrix = function(x, y) { - return [[1, 0, x], [0, 1, y], [0, 0, 1]]; -}; - -// rotate by alpha around (0,0) -exports.rotationMatrix = function(alpha) { - var a = alpha * Math.PI / 180; - return [[Math.cos(a), -Math.sin(a), 0], - [Math.sin(a), Math.cos(a), 0], - [0, 0, 1]]; -}; - -// rotate by alpha around (x,y) -exports.rotationXYMatrix = function(a, x, y) { - return exports.dot( - exports.dot(exports.translationMatrix(x, y), - exports.rotationMatrix(a)), - exports.translationMatrix(-x, -y)); -}; - -// applies a 2D transformation matrix to either x and y params or an [x,y] array -exports.apply2DTransform = function(transform) { - return function() { - var args = arguments; - if(args.length === 3) { - args = args[0]; - }// from map - var xy = arguments.length === 1 ? args[0] : [args[0], args[1]]; - return exports.dot(transform, [xy[0], xy[1], 1]).slice(0, 2); - }; -}; - -// applies a 2D transformation matrix to an [x1,y1,x2,y2] array (to transform a segment) -exports.apply2DTransform2 = function(transform) { - var at = exports.apply2DTransform(transform); - return function(xys) { - return at(xys.slice(0, 2)).concat(at(xys.slice(2, 4))); - }; -}; - -},{}],726:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** - * sanitized modulus function that always returns in the range [0, d) - * rather than (-d, 0] if v is negative - */ -function mod(v, d) { - var out = v % d; - return out < 0 ? out + d : out; -} - -/** - * sanitized modulus function that always returns in the range [-d/2, d/2] - * rather than (-d, 0] if v is negative - */ -function modHalf(v, d) { - return Math.abs(v) > (d / 2) ? - v - Math.round(v / d) * d : - v; -} - -module.exports = { - mod: mod, - modHalf: modHalf -}; - -},{}],727:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; - -/** - * convert a string s (such as 'xaxis.range[0]') - * representing a property of nested object into set and get methods - * also return the string and object so we don't have to keep track of them - * allows [-1] for an array index, to set a property inside all elements - * of an array - * eg if obj = {arr: [{a: 1}, {a: 2}]} - * you can do p = nestedProperty(obj, 'arr[-1].a') - * but you cannot set the array itself this way, to do that - * just set the whole array. - * eg if obj = {arr: [1, 2, 3]} - * you can't do nestedProperty(obj, 'arr[-1]').set(5) - * but you can do nestedProperty(obj, 'arr').set([5, 5, 5]) - */ -module.exports = function nestedProperty(container, propStr) { - if(isNumeric(propStr)) propStr = String(propStr); - else if(typeof propStr !== 'string' || - propStr.substr(propStr.length - 4) === '[-1]') { - throw 'bad property string'; - } - - var j = 0; - var propParts = propStr.split('.'); - var indexed; - var indices; - var i; - - // check for parts of the nesting hierarchy that are numbers (ie array elements) - while(j < propParts.length) { - // look for non-bracket chars, then any number of [##] blocks - indexed = String(propParts[j]).match(/^([^\[\]]*)((\[\-?[0-9]*\])+)$/); - if(indexed) { - if(indexed[1]) propParts[j] = indexed[1]; - // allow propStr to start with bracketed array indices - else if(j === 0) propParts.splice(0, 1); - else throw 'bad property string'; - - indices = indexed[2] - .substr(1, indexed[2].length - 2) - .split(']['); - - for(i = 0; i < indices.length; i++) { - j++; - propParts.splice(j, 0, Number(indices[i])); - } - } - j++; - } - - if(typeof container !== 'object') { - return badContainer(container, propStr, propParts); - } - - return { - set: npSet(container, propParts, propStr), - get: npGet(container, propParts), - astr: propStr, - parts: propParts, - obj: container - }; -}; - -function npGet(cont, parts) { - return function() { - var curCont = cont; - var curPart; - var allSame; - var out; - var i; - var j; - - for(i = 0; i < parts.length - 1; i++) { - curPart = parts[i]; - if(curPart === -1) { - allSame = true; - out = []; - for(j = 0; j < curCont.length; j++) { - out[j] = npGet(curCont[j], parts.slice(i + 1))(); - if(out[j] !== out[0]) allSame = false; - } - return allSame ? out[0] : out; - } - if(typeof curPart === 'number' && !isArrayOrTypedArray(curCont)) { - return undefined; - } - curCont = curCont[curPart]; - if(typeof curCont !== 'object' || curCont === null) { - return undefined; - } - } - - // only hit this if parts.length === 1 - if(typeof curCont !== 'object' || curCont === null) return undefined; - - out = curCont[parts[i]]; - if(out === null) return undefined; - return out; - }; -} - -/* - * Can this value be deleted? We can delete `undefined`, and `null` except INSIDE an - * *args* array. - * - * Previously we also deleted some `{}` and `[]`, in order to try and make set/unset - * a net noop; but this causes far more complication than it's worth, and still had - * lots of exceptions. See https://github.com/plotly/plotly.js/issues/1410 - * - * *args* arrays get passed directly to API methods and we should respect null if - * the user put it there, but otherwise null is deleted as we use it as code - * in restyle/relayout/update for "delete this value" whereas undefined means - * "ignore this edit" - */ -var ARGS_PATTERN = /(^|\.)args\[/; -function isDeletable(val, propStr) { - return (val === undefined) || (val === null && !propStr.match(ARGS_PATTERN)); -} - -function npSet(cont, parts, propStr) { - return function(val) { - var curCont = cont; - var propPart = ''; - var containerLevels = [[cont, propPart]]; - var toDelete = isDeletable(val, propStr); - var curPart; - var i; - - for(i = 0; i < parts.length - 1; i++) { - curPart = parts[i]; - - if(typeof curPart === 'number' && !isArrayOrTypedArray(curCont)) { - throw 'array index but container is not an array'; - } - - // handle special -1 array index - if(curPart === -1) { - toDelete = !setArrayAll(curCont, parts.slice(i + 1), val, propStr); - if(toDelete) break; - else return; - } - - if(!checkNewContainer(curCont, curPart, parts[i + 1], toDelete)) { - break; - } - - curCont = curCont[curPart]; - - if(typeof curCont !== 'object' || curCont === null) { - throw 'container is not an object'; - } - - propPart = joinPropStr(propPart, curPart); - - containerLevels.push([curCont, propPart]); - } - - if(toDelete) { - if(i === parts.length - 1) { - delete curCont[parts[i]]; - - // The one bit of pruning we still do: drop `undefined` from the end of arrays. - // In case someone has already unset previous items, continue until we hit a - // non-undefined value. - if(Array.isArray(curCont) && +parts[i] === curCont.length - 1) { - while(curCont.length && curCont[curCont.length - 1] === undefined) { - curCont.pop(); - } - } - } - } else curCont[parts[i]] = val; - }; -} - -function joinPropStr(propStr, newPart) { - var toAdd = newPart; - if(isNumeric(newPart)) toAdd = '[' + newPart + ']'; - else if(propStr) toAdd = '.' + newPart; - - return propStr + toAdd; -} - -// handle special -1 array index -function setArrayAll(containerArray, innerParts, val, propStr) { - var arrayVal = isArrayOrTypedArray(val); - var allSet = true; - var thisVal = val; - var thisPropStr = propStr.replace('-1', 0); - var deleteThis = arrayVal ? false : isDeletable(val, thisPropStr); - var firstPart = innerParts[0]; - var i; - - for(i = 0; i < containerArray.length; i++) { - thisPropStr = propStr.replace('-1', i); - if(arrayVal) { - thisVal = val[i % val.length]; - deleteThis = isDeletable(thisVal, thisPropStr); - } - if(deleteThis) allSet = false; - if(!checkNewContainer(containerArray, i, firstPart, deleteThis)) { - continue; - } - npSet(containerArray[i], innerParts, propStr.replace('-1', i))(thisVal); - } - return allSet; -} - -/** - * make new sub-container as needed. - * returns false if there's no container and none is needed - * because we're only deleting an attribute - */ -function checkNewContainer(container, part, nextPart, toDelete) { - if(container[part] === undefined) { - if(toDelete) return false; - - if(typeof nextPart === 'number') container[part] = []; - else container[part] = {}; - } - return true; -} - -function badContainer(container, propStr, propParts) { - return { - set: function() { throw 'bad container'; }, - get: function() {}, - astr: propStr, - parts: propParts, - obj: container - }; -} - -},{"./array":702,"fast-isnumeric":225}],728:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -// Simple helper functions -// none of these need any external deps - -module.exports = function noop() {}; - -},{}],729:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var NOTEDATA = []; - -/** - * notifier - * @param {String} text The person's user name - * @param {Number} [delay=1000] The delay time in milliseconds - * or 'long' which provides 2000 ms delay time. - * @return {undefined} this function does not return a value - */ -module.exports = function(text, displayLength) { - if(NOTEDATA.indexOf(text) !== -1) return; - - NOTEDATA.push(text); - - var ts = 1000; - if(isNumeric(displayLength)) ts = displayLength; - else if(displayLength === 'long') ts = 3000; - - var notifierContainer = d3.select('body') - .selectAll('.plotly-notifier') - .data([0]); - notifierContainer.enter() - .append('div') - .classed('plotly-notifier', true); - - var notes = notifierContainer.selectAll('.notifier-note').data(NOTEDATA); - - function killNote(transition) { - transition - .duration(700) - .style('opacity', 0) - .each('end', function(thisText) { - var thisIndex = NOTEDATA.indexOf(thisText); - if(thisIndex !== -1) NOTEDATA.splice(thisIndex, 1); - d3.select(this).remove(); - }); - } - - notes.enter().append('div') - .classed('notifier-note', true) - .style('opacity', 0) - .each(function(thisText) { - var note = d3.select(this); - - note.append('button') - .classed('notifier-close', true) - .html('×') - .on('click', function() { - note.transition().call(killNote); - }); - - var p = note.append('p'); - var lines = thisText.split(//g); - for(var i = 0; i < lines.length; i++) { - if(i) p.append('br'); - p.append('span').text(lines[i]); - } - - note.transition() - .duration(700) - .style('opacity', 1) - .transition() - .delay(ts) - .call(killNote); - }); -}; - -},{"d3":163,"fast-isnumeric":225}],730:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var setCursor = _dereq_('./setcursor'); - -var STASHATTR = 'data-savedcursor'; -var NO_CURSOR = '!!'; - -/* - * works with our CSS cursor classes (see css/_cursor.scss) - * to override a previous cursor set on d3 single-element selections, - * by moving the name of the original cursor to the data-savedcursor attr. - * omit cursor to revert to the previously set value. - */ -module.exports = function overrideCursor(el3, csr) { - var savedCursor = el3.attr(STASHATTR); - if(csr) { - if(!savedCursor) { - var classes = (el3.attr('class') || '').split(' '); - for(var i = 0; i < classes.length; i++) { - var cls = classes[i]; - if(cls.indexOf('cursor-') === 0) { - el3.attr(STASHATTR, cls.substr(7)) - .classed(cls, false); - } - } - if(!el3.attr(STASHATTR)) { - el3.attr(STASHATTR, NO_CURSOR); - } - } - setCursor(el3, csr); - } else if(savedCursor) { - el3.attr(STASHATTR, null); - - if(savedCursor === NO_CURSOR) setCursor(el3); - else setCursor(el3, savedCursor); - } -}; - -},{"./setcursor":739}],731:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var dot = _dereq_('./matrix').dot; -var BADNUM = _dereq_('../constants/numerical').BADNUM; - -var polygon = module.exports = {}; - -/** - * Turn an array of [x, y] pairs into a polygon object - * that can test if points are inside it - * - * @param ptsIn Array of [x, y] pairs - * - * @returns polygon Object {xmin, xmax, ymin, ymax, pts, contains} - * (x|y)(min|max) are the bounding rect of the polygon - * pts is the original array, with the first pair repeated at the end - * contains is a function: (pt, omitFirstEdge) - * pt is the [x, y] pair to test - * omitFirstEdge truthy means points exactly on the first edge don't - * count. This is for use adding one polygon to another so we - * don't double-count the edge where they meet. - * returns boolean: is pt inside the polygon (including on its edges) - */ -polygon.tester = function tester(ptsIn) { - var pts = ptsIn.slice(); - var xmin = pts[0][0]; - var xmax = xmin; - var ymin = pts[0][1]; - var ymax = ymin; - var i; - - pts.push(pts[0]); - for(i = 1; i < pts.length; i++) { - xmin = Math.min(xmin, pts[i][0]); - xmax = Math.max(xmax, pts[i][0]); - ymin = Math.min(ymin, pts[i][1]); - ymax = Math.max(ymax, pts[i][1]); - } - - // do we have a rectangle? Handle this here, so we can use the same - // tester for the rectangular case without sacrificing speed - - var isRect = false; - var rectFirstEdgeTest; - - if(pts.length === 5) { - if(pts[0][0] === pts[1][0]) { // vert, horz, vert, horz - if(pts[2][0] === pts[3][0] && - pts[0][1] === pts[3][1] && - pts[1][1] === pts[2][1]) { - isRect = true; - rectFirstEdgeTest = function(pt) { return pt[0] === pts[0][0]; }; - } - } else if(pts[0][1] === pts[1][1]) { // horz, vert, horz, vert - if(pts[2][1] === pts[3][1] && - pts[0][0] === pts[3][0] && - pts[1][0] === pts[2][0]) { - isRect = true; - rectFirstEdgeTest = function(pt) { return pt[1] === pts[0][1]; }; - } - } - } - - function rectContains(pt, omitFirstEdge) { - var x = pt[0]; - var y = pt[1]; - - if(x === BADNUM || x < xmin || x > xmax || y === BADNUM || y < ymin || y > ymax) { - // pt is outside the bounding box of polygon - return false; - } - if(omitFirstEdge && rectFirstEdgeTest(pt)) return false; - - return true; - } - - function contains(pt, omitFirstEdge) { - var x = pt[0]; - var y = pt[1]; - - if(x === BADNUM || x < xmin || x > xmax || y === BADNUM || y < ymin || y > ymax) { - // pt is outside the bounding box of polygon - return false; - } - - var imax = pts.length; - var x1 = pts[0][0]; - var y1 = pts[0][1]; - var crossings = 0; - var i; - var x0; - var y0; - var xmini; - var ycross; - - for(i = 1; i < imax; i++) { - // find all crossings of a vertical line upward from pt with - // polygon segments - // crossings exactly at xmax don't count, unless the point is - // exactly on the segment, then it counts as inside. - x0 = x1; - y0 = y1; - x1 = pts[i][0]; - y1 = pts[i][1]; - xmini = Math.min(x0, x1); - - if(x < xmini || x > Math.max(x0, x1) || y > Math.max(y0, y1)) { - // outside the bounding box of this segment, it's only a crossing - // if it's below the box. - - continue; - } else if(y < Math.min(y0, y1)) { - // don't count the left-most point of the segment as a crossing - // because we don't want to double-count adjacent crossings - // UNLESS the polygon turns past vertical at exactly this x - // Note that this is repeated below, but we can't factor it out - // because - if(x !== xmini) crossings++; - } else { - // inside the bounding box, check the actual line intercept - - // vertical segment - we know already that the point is exactly - // on the segment, so mark the crossing as exactly at the point. - if(x1 === x0) ycross = y; - // any other angle - else ycross = y0 + (x - x0) * (y1 - y0) / (x1 - x0); - - // exactly on the edge: counts as inside the polygon, unless it's the - // first edge and we're omitting it. - if(y === ycross) { - if(i === 1 && omitFirstEdge) return false; - return true; - } - - if(y <= ycross && x !== xmini) crossings++; - } - } - - // if we've gotten this far, odd crossings means inside, even is outside - return crossings % 2 === 1; - } - - // detect if poly is degenerate - var degenerate = true; - var lastPt = pts[0]; - for(i = 1; i < pts.length; i++) { - if(lastPt[0] !== pts[i][0] || lastPt[1] !== pts[i][1]) { - degenerate = false; - break; - } - } - - return { - xmin: xmin, - xmax: xmax, - ymin: ymin, - ymax: ymax, - pts: pts, - contains: isRect ? rectContains : contains, - isRect: isRect, - degenerate: degenerate - }; -}; - -/** - * Test if a segment of a points array is bent or straight - * - * @param pts Array of [x, y] pairs - * @param start the index of the proposed start of the straight section - * @param end the index of the proposed end point - * @param tolerance the max distance off the line connecting start and end - * before the line counts as bent - * @returns boolean: true means this segment is bent, false means straight - */ -polygon.isSegmentBent = function isSegmentBent(pts, start, end, tolerance) { - var startPt = pts[start]; - var segment = [pts[end][0] - startPt[0], pts[end][1] - startPt[1]]; - var segmentSquared = dot(segment, segment); - var segmentLen = Math.sqrt(segmentSquared); - var unitPerp = [-segment[1] / segmentLen, segment[0] / segmentLen]; - var i; - var part; - var partParallel; - - for(i = start + 1; i < end; i++) { - part = [pts[i][0] - startPt[0], pts[i][1] - startPt[1]]; - partParallel = dot(part, segment); - - if(partParallel < 0 || partParallel > segmentSquared || - Math.abs(dot(part, unitPerp)) > tolerance) return true; - } - return false; -}; - -/** - * Make a filtering polygon, to minimize the number of segments - * - * @param pts Array of [x, y] pairs (must start with at least 1 pair) - * @param tolerance the maximum deviation from straight allowed for - * removing points to simplify the polygon - * - * @returns Object {addPt, raw, filtered} - * addPt is a function(pt: [x, y] pair) to add a raw point and - * continue filtering - * raw is all the input points - * filtered is the resulting filtered Array of [x, y] pairs - */ -polygon.filter = function filter(pts, tolerance) { - var ptsFiltered = [pts[0]]; - var doneRawIndex = 0; - var doneFilteredIndex = 0; - - function addPt(pt) { - pts.push(pt); - var prevFilterLen = ptsFiltered.length; - var iLast = doneRawIndex; - ptsFiltered.splice(doneFilteredIndex + 1); - - for(var i = iLast + 1; i < pts.length; i++) { - if(i === pts.length - 1 || polygon.isSegmentBent(pts, iLast, i + 1, tolerance)) { - ptsFiltered.push(pts[i]); - if(ptsFiltered.length < prevFilterLen - 2) { - doneRawIndex = i; - doneFilteredIndex = ptsFiltered.length - 1; - } - iLast = i; - } - } - } - - if(pts.length > 1) { - var lastPt = pts.pop(); - addPt(lastPt); - } - - return { - addPt: addPt, - raw: pts, - filtered: ptsFiltered - }; -}; - -},{"../constants/numerical":695,"./matrix":725}],732:[function(_dereq_,module,exports){ -(function (global){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var showNoWebGlMsg = _dereq_('./show_no_webgl_msg'); - -// Note that this module should be ONLY required into -// files corresponding to regl trace modules -// so that bundles with non-regl only don't include -// regl and all its bytes. -var createRegl = _dereq_('regl'); - -/** - * Idempotent version of createRegl. Create regl instances - * in the correct canvases with the correct attributes and - * options - * - * @param {DOM node or object} gd : graph div object - * @param {array} extensions : list of extension to pass to createRegl - * - * @return {boolean} true if all createRegl calls succeeded, false otherwise - */ -module.exports = function prepareRegl(gd, extensions) { - var fullLayout = gd._fullLayout; - var success = true; - - fullLayout._glcanvas.each(function(d) { - if(d.regl) return; - // only parcoords needs pick layer - if(d.pick && !fullLayout._has('parcoords')) return; - - try { - d.regl = createRegl({ - canvas: this, - attributes: { - antialias: !d.pick, - preserveDrawingBuffer: true - }, - pixelRatio: gd._context.plotGlPixelRatio || global.devicePixelRatio, - extensions: extensions || [] - }); - } catch(e) { - success = false; - } - - if(success) { - this.addEventListener('webglcontextlost', function(event) { - if(gd && gd.emit) { - gd.emit('plotly_webglcontextlost', { - event: event, - layer: d.key - }); - } - }, false); - } - }); - - if(!success) { - showNoWebGlMsg({container: fullLayout._glcontainer.node()}); - } - return success; -}; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./show_no_webgl_msg":740,"regl":502}],733:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** - * Push array with unique items - * - * Ignores falsy items, except 0 so we can use it to construct arrays of indices. - * - * @param {array} array - * array to be filled - * @param {any} item - * item to be or not to be inserted - * @return {array} - * ref to array (now possibly containing one more item) - * - */ -module.exports = function pushUnique(array, item) { - if(item instanceof RegExp) { - var itemStr = item.toString(); - for(var i = 0; i < array.length; i++) { - if(array[i] instanceof RegExp && array[i].toString() === itemStr) { - return array; - } - } - array.push(item); - } else if((item || item === 0) && array.indexOf(item) === -1) array.push(item); - - return array; -}; - -},{}],734:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); -var dfltConfig = _dereq_('../plot_api/plot_config').dfltConfig; - -/** - * Copy arg array *without* removing `undefined` values from objects. - * - * @param gd - * @param args - * @returns {Array} - */ -function copyArgArray(gd, args) { - var copy = []; - var arg; - - for(var i = 0; i < args.length; i++) { - arg = args[i]; - - if(arg === gd) copy[i] = arg; - else if(typeof arg === 'object') { - copy[i] = Array.isArray(arg) ? - Lib.extendDeep([], arg) : - Lib.extendDeepAll({}, arg); - } else copy[i] = arg; - } - - return copy; -} - - -// ----------------------------------------------------- -// Undo/Redo queue for plots -// ----------------------------------------------------- - - -var queue = {}; - -// TODO: disable/enable undo and redo buttons appropriately - -/** - * Add an item to the undoQueue for a graphDiv - * - * @param gd - * @param undoFunc Function undo this operation - * @param undoArgs Args to supply undoFunc with - * @param redoFunc Function to redo this operation - * @param redoArgs Args to supply redoFunc with - */ -queue.add = function(gd, undoFunc, undoArgs, redoFunc, redoArgs) { - var queueObj, - queueIndex; - - // make sure we have the queue and our position in it - gd.undoQueue = gd.undoQueue || {index: 0, queue: [], sequence: false}; - queueIndex = gd.undoQueue.index; - - // if we're already playing an undo or redo, or if this is an auto operation - // (like pane resize... any others?) then we don't save this to the undo queue - if(gd.autoplay) { - if(!gd.undoQueue.inSequence) gd.autoplay = false; - return; - } - - // if we're not in a sequence or are just starting, we need a new queue item - if(!gd.undoQueue.sequence || gd.undoQueue.beginSequence) { - queueObj = {undo: {calls: [], args: []}, redo: {calls: [], args: []}}; - gd.undoQueue.queue.splice(queueIndex, gd.undoQueue.queue.length - queueIndex, queueObj); - gd.undoQueue.index += 1; - } else { - queueObj = gd.undoQueue.queue[queueIndex - 1]; - } - gd.undoQueue.beginSequence = false; - - // we unshift to handle calls for undo in a forward for loop later - if(queueObj) { - queueObj.undo.calls.unshift(undoFunc); - queueObj.undo.args.unshift(undoArgs); - queueObj.redo.calls.push(redoFunc); - queueObj.redo.args.push(redoArgs); - } - - if(gd.undoQueue.queue.length > dfltConfig.queueLength) { - gd.undoQueue.queue.shift(); - gd.undoQueue.index--; - } -}; - -/** - * Begin a sequence of undoQueue changes - * - * @param gd - */ -queue.startSequence = function(gd) { - gd.undoQueue = gd.undoQueue || {index: 0, queue: [], sequence: false}; - gd.undoQueue.sequence = true; - gd.undoQueue.beginSequence = true; -}; - -/** - * Stop a sequence of undoQueue changes - * - * Call this *after* you're sure your undo chain has ended - * - * @param gd - */ -queue.stopSequence = function(gd) { - gd.undoQueue = gd.undoQueue || {index: 0, queue: [], sequence: false}; - gd.undoQueue.sequence = false; - gd.undoQueue.beginSequence = false; -}; - -/** - * Move one step back in the undo queue, and undo the object there. - * - * @param gd - */ -queue.undo = function undo(gd) { - var queueObj, i; - - if(gd.framework && gd.framework.isPolar) { - gd.framework.undo(); - return; - } - if(gd.undoQueue === undefined || - isNaN(gd.undoQueue.index) || - gd.undoQueue.index <= 0) { - return; - } - - // index is pointing to next *forward* queueObj, point to the one we're undoing - gd.undoQueue.index--; - - // get the queueObj for instructions on how to undo - queueObj = gd.undoQueue.queue[gd.undoQueue.index]; - - // this sequence keeps things from adding to the queue during undo/redo - gd.undoQueue.inSequence = true; - for(i = 0; i < queueObj.undo.calls.length; i++) { - queue.plotDo(gd, queueObj.undo.calls[i], queueObj.undo.args[i]); - } - gd.undoQueue.inSequence = false; - gd.autoplay = false; -}; - -/** - * Redo the current object in the undo, then move forward in the queue. - * - * @param gd - */ -queue.redo = function redo(gd) { - var queueObj, i; - - if(gd.framework && gd.framework.isPolar) { - gd.framework.redo(); - return; - } - if(gd.undoQueue === undefined || - isNaN(gd.undoQueue.index) || - gd.undoQueue.index >= gd.undoQueue.queue.length) { - return; - } - - // get the queueObj for instructions on how to undo - queueObj = gd.undoQueue.queue[gd.undoQueue.index]; - - // this sequence keeps things from adding to the queue during undo/redo - gd.undoQueue.inSequence = true; - for(i = 0; i < queueObj.redo.calls.length; i++) { - queue.plotDo(gd, queueObj.redo.calls[i], queueObj.redo.args[i]); - } - gd.undoQueue.inSequence = false; - gd.autoplay = false; - - // index is pointing to the thing we just redid, move it - gd.undoQueue.index++; -}; - -/** - * Called by undo/redo to make the actual changes. - * - * Not meant to be called publically, but included for mocking out in tests. - * - * @param gd - * @param func - * @param args - */ -queue.plotDo = function(gd, func, args) { - gd.autoplay = true; - - // this *won't* copy gd and it preserves `undefined` properties! - args = copyArgArray(gd, args); - - // call the supplied function - func.apply(null, args); -}; - -module.exports = queue; - -},{"../lib":719,"../plot_api/plot_config":755}],735:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* - * make a regex for matching counter ids/names ie xaxis, xaxis2, xaxis10... - * - * @param {string} head: the head of the pattern, eg 'x' matches 'x', 'x2', 'x10' etc. - * 'xy' is a special case for cartesian subplots: it matches 'x2y3' etc - * @param {Optional(string)} tail: a fixed piece after the id - * eg counterRegex('scene', '.annotations') for scene2.annotations etc. - * @param {boolean} openEnded: if true, the string may continue past the match. - * @param {boolean} matchBeginning: if false, the string may start before the match. - */ -exports.counter = function(head, tail, openEnded, matchBeginning) { - var fullTail = (tail || '') + (openEnded ? '' : '$'); - var startWithPrefix = matchBeginning === false ? '' : '^'; - if(head === 'xy') { - return new RegExp(startWithPrefix + 'x([2-9]|[1-9][0-9]+)?y([2-9]|[1-9][0-9]+)?' + fullTail); - } - return new RegExp(startWithPrefix + head + '([2-9]|[1-9][0-9]+)?' + fullTail); -}; - -},{}],736:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -// ASCEND: chop off the last nesting level - either [] or . - to ascend -// the attribute tree. the remaining attrString is in match[1] -var ASCEND = /^(.*)(\.[^\.\[\]]+|\[\d\])$/; - -// SIMPLEATTR: is this an un-nested attribute? (no dots or brackets) -var SIMPLEATTR = /^[^\.\[\]]+$/; - -/* - * calculate a relative attribute string, similar to a relative path - * - * @param {string} baseAttr: - * an attribute string, such as 'annotations[3].x'. The "current location" - * is the attribute string minus the last component ('annotations[3]') - * @param {string} relativeAttr: - * a route to the desired attribute string, using '^' to ascend - * - * @return {string} attrString: - * for example: - * relativeAttr('annotations[3].x', 'y') = 'annotations[3].y' - * relativeAttr('annotations[3].x', '^[2].z') = 'annotations[2].z' - * relativeAttr('annotations[3].x', '^^margin') = 'margin' - * relativeAttr('annotations[3].x', '^^margin.r') = 'margin.r' - */ -module.exports = function(baseAttr, relativeAttr) { - while(relativeAttr) { - var match = baseAttr.match(ASCEND); - - if(match) baseAttr = match[1]; - else if(baseAttr.match(SIMPLEATTR)) baseAttr = ''; - else throw new Error('bad relativeAttr call:' + [baseAttr, relativeAttr]); - - if(relativeAttr.charAt(0) === '^') relativeAttr = relativeAttr.slice(1); - else break; - } - - if(baseAttr && relativeAttr.charAt(0) !== '[') { - return baseAttr + '.' + relativeAttr; - } - return baseAttr + relativeAttr; -}; - -},{}],737:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; -var isPlainObject = _dereq_('./is_plain_object'); - -/** - * Relink private _keys and keys with a function value from one container - * to the new container. - * Relink means copying if object is pass-by-value and adding a reference - * if object is pass-by-ref. - * This prevents deepCopying massive structures like a webgl context. - */ -module.exports = function relinkPrivateKeys(toContainer, fromContainer) { - for(var k in fromContainer) { - var fromVal = fromContainer[k]; - var toVal = toContainer[k]; - - if(toVal === fromVal) { - continue; - } - if(k.charAt(0) === '_' || typeof fromVal === 'function') { - // if it already exists at this point, it's something - // that we recreate each time around, so ignore it - if(k in toContainer) continue; - - toContainer[k] = fromVal; - } else if(isArrayOrTypedArray(fromVal) && isArrayOrTypedArray(toVal) && isPlainObject(fromVal[0])) { - // filter out data_array items that can contain user objects - // most of the time the toVal === fromVal check will catch these early - // but if the user makes new ones we also don't want to recurse in. - if(k === 'customdata' || k === 'ids') continue; - - // recurse into arrays containers - var minLen = Math.min(fromVal.length, toVal.length); - for(var j = 0; j < minLen; j++) { - if((toVal[j] !== fromVal[j]) && isPlainObject(fromVal[j]) && isPlainObject(toVal[j])) { - relinkPrivateKeys(toVal[j], fromVal[j]); - } - } - } else if(isPlainObject(fromVal) && isPlainObject(toVal)) { - // recurse into objects, but only if they still exist - relinkPrivateKeys(toVal, fromVal); - - if(!Object.keys(toVal).length) delete toContainer[k]; - } - } -}; - -},{"./array":702,"./is_plain_object":720}],738:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var loggers = _dereq_('./loggers'); -var identity = _dereq_('./identity'); - -// don't trust floating point equality - fraction of bin size to call -// "on the line" and ensure that they go the right way specified by -// linelow -var roundingError = 1e-9; - - -/** - * findBin - find the bin for val - note that it can return outside the - * bin range any pos. or neg. integer for linear bins, or -1 or - * bins.length-1 for explicit. - * bins is either an object {start,size,end} or an array length #bins+1 - * bins can be either increasing or decreasing but must be monotonic - * for linear bins, we can just calculate. For listed bins, run a binary - * search linelow (truthy) says the bin boundary should be attributed to - * the lower bin rather than the default upper bin - */ -exports.findBin = function(val, bins, linelow) { - if(isNumeric(bins.start)) { - return linelow ? - Math.ceil((val - bins.start) / bins.size - roundingError) - 1 : - Math.floor((val - bins.start) / bins.size + roundingError); - } else { - var n1 = 0; - var n2 = bins.length; - var c = 0; - var binSize = (n2 > 1) ? (bins[n2 - 1] - bins[0]) / (n2 - 1) : 1; - var n, test; - if(binSize >= 0) { - test = linelow ? lessThan : lessOrEqual; - } else { - test = linelow ? greaterOrEqual : greaterThan; - } - val += binSize * roundingError * (linelow ? -1 : 1) * (binSize >= 0 ? 1 : -1); - // c is just to avoid infinite loops if there's an error - while(n1 < n2 && c++ < 100) { - n = Math.floor((n1 + n2) / 2); - if(test(bins[n], val)) n1 = n + 1; - else n2 = n; - } - if(c > 90) loggers.log('Long binary search...'); - return n1 - 1; - } -}; - -function lessThan(a, b) { return a < b; } -function lessOrEqual(a, b) { return a <= b; } -function greaterThan(a, b) { return a > b; } -function greaterOrEqual(a, b) { return a >= b; } - -exports.sorterAsc = function(a, b) { return a - b; }; -exports.sorterDes = function(a, b) { return b - a; }; - -/** - * find distinct values in an array, lumping together ones that appear to - * just be off by a rounding error - * return the distinct values and the minimum difference between any two - */ -exports.distinctVals = function(valsIn) { - var vals = valsIn.slice(); // otherwise we sort the original array... - vals.sort(exports.sorterAsc); - - var l = vals.length - 1; - var minDiff = (vals[l] - vals[0]) || 1; - var errDiff = minDiff / (l || 1) / 10000; - var v2 = [vals[0]]; - - for(var i = 0; i < l; i++) { - // make sure values aren't just off by a rounding error - if(vals[i + 1] > vals[i] + errDiff) { - minDiff = Math.min(minDiff, vals[i + 1] - vals[i]); - v2.push(vals[i + 1]); - } - } - - return {vals: v2, minDiff: minDiff}; -}; - -/** - * return the smallest element from (sorted) array arrayIn that's bigger than val, - * or (reverse) the largest element smaller than val - * used to find the best tick given the minimum (non-rounded) tick - * particularly useful for date/time where things are not powers of 10 - * binary search is probably overkill here... - */ -exports.roundUp = function(val, arrayIn, reverse) { - var low = 0; - var high = arrayIn.length - 1; - var mid; - var c = 0; - var dlow = reverse ? 0 : 1; - var dhigh = reverse ? 1 : 0; - var rounded = reverse ? Math.ceil : Math.floor; - // c is just to avoid infinite loops if there's an error - while(low < high && c++ < 100) { - mid = rounded((low + high) / 2); - if(arrayIn[mid] <= val) low = mid + dlow; - else high = mid - dhigh; - } - return arrayIn[low]; -}; - -/** - * Tweak to Array.sort(sortFn) that improves performance for pre-sorted arrays - * - * Note that newer browsers (such as Chrome v70+) are starting to pick up - * on pre-sorted arrays which may render the following optimization unnecessary - * in the future. - * - * Motivation: sometimes we need to sort arrays but the input is likely to - * already be sorted. Browsers don't seem to pick up on pre-sorted arrays, - * and in fact Chrome is actually *slower* sorting pre-sorted arrays than purely - * random arrays. FF is at least faster if the array is pre-sorted, but still - * not as fast as it could be. - * Here's how this plays out sorting a length-1e6 array: - * - * Calls to Sort FN | Chrome bare | FF bare | Chrome tweak | FF tweak - * | v68.0 Mac | v61.0 Mac| | - * ------------------+---------------+-----------+----------------+------------ - * ordered | 30.4e6 | 10.1e6 | 1e6 | 1e6 - * reversed | 29.4e6 | 9.9e6 | 1e6 + reverse | 1e6 + reverse - * random | ~21e6 | ~18.7e6 | ~21e6 | ~18.7e6 - * - * So this is a substantial win for pre-sorted (ordered or exactly reversed) - * arrays. Including this wrapper on an unsorted array adds a penalty that will - * in general be only a few calls to the sort function. The only case this - * penalty will be significant is if the array is mostly sorted but there are - * a few unsorted items near the end, but the penalty is still at most N calls - * out of (for N=1e6) ~20N total calls - * - * @param {Array} array: the array, to be sorted in place - * @param {function} sortFn: As in Array.sort, function(a, b) that puts - * item a before item b if the return is negative, a after b if positive, - * and no change if zero. - * @return {Array}: the original array, sorted in place. - */ -exports.sort = function(array, sortFn) { - var notOrdered = 0; - var notReversed = 0; - for(var i = 1; i < array.length; i++) { - var pairOrder = sortFn(array[i], array[i - 1]); - if(pairOrder < 0) notOrdered = 1; - else if(pairOrder > 0) notReversed = 1; - if(notOrdered && notReversed) return array.sort(sortFn); - } - return notReversed ? array : array.reverse(); -}; - -/** - * find index in array 'arr' that minimizes 'fn' - * - * @param {array} arr : array where to search - * @param {fn (optional)} fn : function to minimize, - * if not given, fn is the identity function - * @return {integer} - */ -exports.findIndexOfMin = function(arr, fn) { - fn = fn || identity; - - var min = Infinity; - var ind; - - for(var i = 0; i < arr.length; i++) { - var v = fn(arr[i]); - if(v < min) { - min = v; - ind = i; - } - } - return ind; -}; - -},{"./identity":718,"./loggers":723,"fast-isnumeric":225}],739:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -// works with our CSS cursor classes (see css/_cursor.scss) -// to apply cursors to d3 single-element selections. -// omit cursor to revert to the default. -module.exports = function setCursor(el3, csr) { - (el3.attr('class') || '').split(' ').forEach(function(cls) { - if(cls.indexOf('cursor-') === 0) el3.classed(cls, false); - }); - - if(csr) el3.classed('cursor-' + csr, true); -}; - -},{}],740:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Color = _dereq_('../components/color'); - -var noop = function() {}; - - -/** - * Prints a no webgl error message into the scene container - * @param {scene instance} scene - * - * Expects 'scene' to have property 'container' - * - */ -module.exports = function showNoWebGlMsg(scene) { - for(var prop in scene) { - if(typeof scene[prop] === 'function') scene[prop] = noop; - } - - scene.destroy = function() { - scene.container.parentNode.removeChild(scene.container); - }; - - var div = document.createElement('div'); - div.className = 'no-webgl'; - div.style.cursor = 'pointer'; - div.style.fontSize = '24px'; - div.style.color = Color.defaults[0]; - div.style.position = 'absolute'; - div.style.left = div.style.top = '0px'; - div.style.width = div.style.height = '100%'; - div.style['background-color'] = Color.lightLine; - div.style['z-index'] = 30; - - var p = document.createElement('p'); - p.textContent = 'WebGL is not supported by your browser - visit https://get.webgl.org for more info'; - p.style.position = 'relative'; - p.style.top = '50%'; - p.style.left = '50%'; - p.style.height = '30%'; - p.style.width = '50%'; - p.style.margin = '-15% 0 0 -25%'; - - div.appendChild(p); - scene.container.appendChild(div); - scene.container.style.background = '#FFFFFF'; - scene.container.onclick = function() { - window.open('https://get.webgl.org'); - }; - - // return before setting up camera and onrender methods - return false; -}; - -},{"../components/color":593}],741:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var isArrayOrTypedArray = _dereq_('./array').isArrayOrTypedArray; - -/** - * aggNums() returns the result of an aggregate function applied to an array of - * values, where non-numerical values have been tossed out. - * - * @param {function} f - aggregation function (e.g., Math.min) - * @param {Number} v - initial value (continuing from previous calls) - * if there's no continuing value, use null for selector-type - * functions (max,min), or 0 for summations - * @param {Array} a - array to aggregate (may be nested, we will recurse, - * but all elements must have the same dimension) - * @param {Number} len - maximum length of a to aggregate - * @return {Number} - result of f applied to a starting from v - */ -exports.aggNums = function(f, v, a, len) { - var i, - b; - if(!len || len > a.length) len = a.length; - if(!isNumeric(v)) v = false; - if(isArrayOrTypedArray(a[0])) { - b = new Array(len); - for(i = 0; i < len; i++) b[i] = exports.aggNums(f, v, a[i]); - a = b; - } - - for(i = 0; i < len; i++) { - if(!isNumeric(v)) v = a[i]; - else if(isNumeric(a[i])) v = f(+v, +a[i]); - } - return v; -}; - -/** - * mean & std dev functions using aggNums, so it handles non-numerics nicely - * even need to use aggNums instead of .length, to toss out non-numerics - */ -exports.len = function(data) { - return exports.aggNums(function(a) { return a + 1; }, 0, data); -}; - -exports.mean = function(data, len) { - if(!len) len = exports.len(data); - return exports.aggNums(function(a, b) { return a + b; }, 0, data) / len; -}; - -exports.midRange = function(numArr) { - if(numArr === undefined || numArr.length === 0) return undefined; - return (exports.aggNums(Math.max, null, numArr) + exports.aggNums(Math.min, null, numArr)) / 2; -}; - -exports.variance = function(data, len, mean) { - if(!len) len = exports.len(data); - if(!isNumeric(mean)) mean = exports.mean(data, len); - - return exports.aggNums(function(a, b) { - return a + Math.pow(b - mean, 2); - }, 0, data) / len; -}; - -exports.stdev = function(data, len, mean) { - return Math.sqrt(exports.variance(data, len, mean)); -}; - -/** - * median of a finite set of numbers - * reference page: https://en.wikipedia.org/wiki/Median#Finite_set_of_numbers -**/ -exports.median = function(data) { - var b = data.slice().sort(); - return exports.interp(b, 0.5); -}; - -/** - * interp() computes a percentile (quantile) for a given distribution. - * We interpolate the distribution (to compute quantiles, we follow method #10 here: - * http://www.amstat.org/publications/jse/v14n3/langford.html). - * Typically the index or rank (n * arr.length) may be non-integer. - * For reference: ends are clipped to the extreme values in the array; - * For box plots: index you get is half a point too high (see - * http://en.wikipedia.org/wiki/Percentile#Nearest_rank) but note that this definition - * indexes from 1 rather than 0, so we subtract 1/2 (instead of add). - * - * @param {Array} arr - This array contains the values that make up the distribution. - * @param {Number} n - Between 0 and 1, n = p/100 is such that we compute the p^th percentile. - * For example, the 50th percentile (or median) corresponds to n = 0.5 - * @return {Number} - percentile - */ -exports.interp = function(arr, n) { - if(!isNumeric(n)) throw 'n should be a finite number'; - n = n * arr.length - 0.5; - if(n < 0) return arr[0]; - if(n > arr.length - 1) return arr[arr.length - 1]; - var frac = n % 1; - return frac * arr[Math.ceil(n)] + (1 - frac) * arr[Math.floor(n)]; -}; - -},{"./array":702,"fast-isnumeric":225}],742:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var rgba = _dereq_('color-normalize'); - -function str2RgbaArray(color) { - if(!color) return [0, 0, 0, 1]; - return rgba(color); -} - -module.exports = str2RgbaArray; - -},{"color-normalize":120}],743:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -/* global MathJax:false */ - -var d3 = _dereq_('d3'); - -var Lib = _dereq_('../lib'); -var xmlnsNamespaces = _dereq_('../constants/xmlns_namespaces'); -var LINE_SPACING = _dereq_('../constants/alignment').LINE_SPACING; - -// text converter - -function getSize(_selection, _dimension) { - return _selection.node().getBoundingClientRect()[_dimension]; -} - -var FIND_TEX = /([^$]*)([$]+[^$]*[$]+)([^$]*)/; - -exports.convertToTspans = function(_context, gd, _callback) { - var str = _context.text(); - - // Until we get tex integrated more fully (so it can be used along with non-tex) - // allow some elements to prohibit it by attaching 'data-notex' to the original - var tex = (!_context.attr('data-notex')) && - (typeof MathJax !== 'undefined') && - str.match(FIND_TEX); - - var parent = d3.select(_context.node().parentNode); - if(parent.empty()) return; - var svgClass = (_context.attr('class')) ? _context.attr('class').split(' ')[0] : 'text'; - svgClass += '-math'; - parent.selectAll('svg.' + svgClass).remove(); - parent.selectAll('g.' + svgClass + '-group').remove(); - _context.style('display', null) - .attr({ - // some callers use data-unformatted *from the element* in 'cancel' - // so we need it here even if we're going to turn it into math - // these two (plus style and text-anchor attributes) form the key we're - // going to use for Drawing.bBox - 'data-unformatted': str, - 'data-math': 'N' - }); - - function showText() { - if(!parent.empty()) { - svgClass = _context.attr('class') + '-math'; - parent.select('svg.' + svgClass).remove(); - } - _context.text('') - .style('white-space', 'pre'); - - var hasLink = buildSVGText(_context.node(), str); - - if(hasLink) { - // at least in Chrome, pointer-events does not seem - // to be honored in children of elements - // so if we have an anchor, we have to make the - // whole element respond - _context.style('pointer-events', 'all'); - } - - exports.positionText(_context); - - if(_callback) _callback.call(_context); - } - - if(tex) { - ((gd && gd._promises) || []).push(new Promise(function(resolve) { - _context.style('display', 'none'); - var fontSize = parseInt(_context.node().style.fontSize, 10); - var config = {fontSize: fontSize}; - - texToSVG(tex[2], config, function(_svgEl, _glyphDefs, _svgBBox) { - parent.selectAll('svg.' + svgClass).remove(); - parent.selectAll('g.' + svgClass + '-group').remove(); - - var newSvg = _svgEl && _svgEl.select('svg'); - if(!newSvg || !newSvg.node()) { - showText(); - resolve(); - return; - } - - var mathjaxGroup = parent.append('g') - .classed(svgClass + '-group', true) - .attr({ - 'pointer-events': 'none', - 'data-unformatted': str, - 'data-math': 'Y' - }); - - mathjaxGroup.node().appendChild(newSvg.node()); - - // stitch the glyph defs - if(_glyphDefs && _glyphDefs.node()) { - newSvg.node().insertBefore(_glyphDefs.node().cloneNode(true), - newSvg.node().firstChild); - } - - newSvg.attr({ - 'class': svgClass, - height: _svgBBox.height, - preserveAspectRatio: 'xMinYMin meet' - }) - .style({overflow: 'visible', 'pointer-events': 'none'}); - - var fill = _context.node().style.fill || 'black'; - var g = newSvg.select('g'); - g.attr({fill: fill, stroke: fill}); - - var newSvgW = getSize(g, 'width'); - var newSvgH = getSize(g, 'height'); - var newX = +_context.attr('x') - newSvgW * - {start: 0, middle: 0.5, end: 1}[_context.attr('text-anchor') || 'start']; - // font baseline is about 1/4 fontSize below centerline - var textHeight = fontSize || getSize(_context, 'height'); - var dy = -textHeight / 4; - - if(svgClass[0] === 'y') { - mathjaxGroup.attr({ - transform: 'rotate(' + [-90, +_context.attr('x'), +_context.attr('y')] + - ') translate(' + [-newSvgW / 2, dy - newSvgH / 2] + ')' - }); - newSvg.attr({x: +_context.attr('x'), y: +_context.attr('y')}); - } else if(svgClass[0] === 'l') { - newSvg.attr({x: _context.attr('x'), y: dy - (newSvgH / 2)}); - } else if(svgClass[0] === 'a' && svgClass.indexOf('atitle') !== 0) { - newSvg.attr({x: 0, y: dy}); - } else { - newSvg.attr({x: newX, y: (+_context.attr('y') + dy - newSvgH / 2)}); - } - - if(_callback) _callback.call(_context, mathjaxGroup); - resolve(mathjaxGroup); - }); - })); - } else showText(); - - return _context; -}; - - -// MathJax - -var LT_MATCH = /(<|<|<)/g; -var GT_MATCH = /(>|>|>)/g; - -function cleanEscapesForTex(s) { - return s.replace(LT_MATCH, '\\lt ') - .replace(GT_MATCH, '\\gt '); -} - -function texToSVG(_texString, _config, _callback) { - var originalRenderer, - originalConfig, - originalProcessSectionDelay, - tmpDiv; - - MathJax.Hub.Queue( - function() { - originalConfig = Lib.extendDeepAll({}, MathJax.Hub.config); - - originalProcessSectionDelay = MathJax.Hub.processSectionDelay; - if(MathJax.Hub.processSectionDelay !== undefined) { - // MathJax 2.5+ - MathJax.Hub.processSectionDelay = 0; - } - - return MathJax.Hub.Config({ - messageStyle: 'none', - tex2jax: { - inlineMath: [['$', '$'], ['\\(', '\\)']] - }, - displayAlign: 'left', - }); - }, - function() { - // Get original renderer - originalRenderer = MathJax.Hub.config.menuSettings.renderer; - if(originalRenderer !== 'SVG') { - return MathJax.Hub.setRenderer('SVG'); - } - }, - function() { - var randomID = 'math-output-' + Lib.randstr({}, 64); - tmpDiv = d3.select('body').append('div') - .attr({id: randomID}) - .style({visibility: 'hidden', position: 'absolute'}) - .style({'font-size': _config.fontSize + 'px'}) - .text(cleanEscapesForTex(_texString)); - - return MathJax.Hub.Typeset(tmpDiv.node()); - }, - function() { - var glyphDefs = d3.select('body').select('#MathJax_SVG_glyphs'); - - if(tmpDiv.select('.MathJax_SVG').empty() || !tmpDiv.select('svg').node()) { - Lib.log('There was an error in the tex syntax.', _texString); - _callback(); - } else { - var svgBBox = tmpDiv.select('svg').node().getBoundingClientRect(); - _callback(tmpDiv.select('.MathJax_SVG'), glyphDefs, svgBBox); - } - - tmpDiv.remove(); - - if(originalRenderer !== 'SVG') { - return MathJax.Hub.setRenderer(originalRenderer); - } - }, - function() { - if(originalProcessSectionDelay !== undefined) { - MathJax.Hub.processSectionDelay = originalProcessSectionDelay; - } - return MathJax.Hub.Config(originalConfig); - }); -} - -var TAG_STYLES = { - // would like to use baseline-shift for sub/sup but FF doesn't support it - // so we need to use dy along with the uber hacky shift-back-to - // baseline below - sup: 'font-size:70%', - sub: 'font-size:70%', - b: 'font-weight:bold', - i: 'font-style:italic', - a: 'cursor:pointer', - span: '', - em: 'font-style:italic;font-weight:bold' -}; - -// baseline shifts for sub and sup -var SHIFT_DY = { - sub: '0.3em', - sup: '-0.6em' -}; -// reset baseline by adding a tspan (empty except for a zero-width space) -// with dy of -70% * SHIFT_DY (because font-size=70%) -var RESET_DY = { - sub: '-0.21em', - sup: '0.42em' -}; -var ZERO_WIDTH_SPACE = '\u200b'; - -/* - * Whitelist of protocols in user-supplied urls. Mostly we want to avoid javascript - * and related attack vectors. The empty items are there for IE, that in various - * versions treats relative paths as having different flavors of no protocol, while - * other browsers have these explicitly inherit the protocol of the page they're in. - */ -var PROTOCOLS = ['http:', 'https:', 'mailto:', '', undefined, ':']; - -var NEWLINES = /(\r\n?|\n)/g; - -var SPLIT_TAGS = /(<[^<>]*>)/; - -var ONE_TAG = /<(\/?)([^ >]*)(\s+(.*))?>/i; - -var BR_TAG = //i; - -/* - * style and href: pull them out of either single or double quotes. Also - * - target: (_blank|_self|_parent|_top|framename) - * note that you can't use target to get a popup but if you use popup, - * a `framename` will be passed along as the name of the popup window. - * per the spec, cannot contain whitespace. - * for backward compatibility we default to '_blank' - * - popup: a custom one for us to enable popup (new window) links. String - * for window.open -> strWindowFeatures, like 'menubar=yes,width=500,height=550' - * note that at least in Chrome, you need to give at least one property - * in this string or the page will open in a new tab anyway. We follow this - * convention and will not make a popup if this string is empty. - * per the spec, cannot contain whitespace. - * - * Because we hack in other attributes with style (sub & sup), drop any trailing - * semicolon in user-supplied styles so we can consistently append the tag-dependent style - * - * These are for tag attributes; Chrome anyway will convert entities in - * attribute values, but not in attribute names - * you can test this by for example: - * > p = document.createElement('p') - * > p.innerHTML = 'Hi' - * > p.innerHTML - * <- 'Hi' - */ -var STYLEMATCH = /(^|[\s"'])style\s*=\s*("([^"]*);?"|'([^']*);?')/i; -var HREFMATCH = /(^|[\s"'])href\s*=\s*("([^"]*)"|'([^']*)')/i; -var TARGETMATCH = /(^|[\s"'])target\s*=\s*("([^"\s]*)"|'([^'\s]*)')/i; -var POPUPMATCH = /(^|[\s"'])popup\s*=\s*("([\w=,]*)"|'([\w=,]*)')/i; - -// dedicated matcher for these quoted regexes, that can return their results -// in two different places -function getQuotedMatch(_str, re) { - if(!_str) return null; - var match = _str.match(re); - var result = match && (match[3] || match[4]); - return result && convertEntities(result); -} - -var COLORMATCH = /(^|;)\s*color:/; - -/** - * Strip string of tags - * - * @param {string} _str : input string - * @param {object} opts : - * - len {number} max length of output string - * - allowedTags {array} list of pseudo-html tags to NOT strip - * @return {string} - */ -exports.plainText = function(_str, opts) { - opts = opts || {}; - - var len = (opts.len !== undefined && opts.len !== -1) ? opts.len : Infinity; - var allowedTags = opts.allowedTags !== undefined ? opts.allowedTags : ['br']; - - var ellipsis = '...'; - var eLen = ellipsis.length; - - var oldParts = _str.split(SPLIT_TAGS); - var newParts = []; - var prevTag = ''; - var l = 0; - - for(var i = 0; i < oldParts.length; i++) { - var p = oldParts[i]; - var match = p.match(ONE_TAG); - var tagType = match && match[2].toLowerCase(); - - if(tagType) { - // N.B. tags do not count towards string length - if(allowedTags.indexOf(tagType) !== -1) { - newParts.push(p); - prevTag = tagType; - } - } else { - var pLen = p.length; - - if((l + pLen) < len) { - newParts.push(p); - l += pLen; - } else if(l < len) { - var pLen2 = len - l; - - if(prevTag && (prevTag !== 'br' || pLen2 <= eLen || pLen <= eLen)) { - newParts.pop(); - } - - if(len > eLen) { - newParts.push(p.substr(0, pLen2 - eLen) + ellipsis); - } else { - newParts.push(p.substr(0, pLen2)); - } - break; - } - - prevTag = ''; - } - } - - return newParts.join(''); -}; - -/* - * N.B. HTML entities are listed without the leading '&' and trailing ';' - * https://www.freeformatter.com/html-entities.html - * - * FWIW if we wanted to support the full set, it has 2261 entries: - * https://www.w3.org/TR/html5/entities.json - * though I notice that some of these are duplicates and/or are missing ";" - * eg: "&", "&", "&", and "&" all map to "&" - * We no longer need to include numeric entities here, these are now handled - * by String.fromCodePoint/fromCharCode - * - * Anyway the only ones that are really important to allow are the HTML special - * chars <, >, and &, because these ones can trigger special processing if not - * replaced by the corresponding entity. - */ -var entityToUnicode = { - mu: 'μ', - amp: '&', - lt: '<', - gt: '>', - nbsp: ' ', - times: '×', - plusmn: '±', - deg: '°' -}; - -// NOTE: in general entities can contain uppercase too (so [a-zA-Z]) but all the -// ones we support use only lowercase. If we ever change that, update the regex. -var ENTITY_MATCH = /&(#\d+|#x[\da-fA-F]+|[a-z]+);/g; -function convertEntities(_str) { - return _str.replace(ENTITY_MATCH, function(fullMatch, innerMatch) { - var outChar; - if(innerMatch.charAt(0) === '#') { - // cannot use String.fromCodePoint in IE - outChar = fromCodePoint( - innerMatch.charAt(1) === 'x' ? - parseInt(innerMatch.substr(2), 16) : - parseInt(innerMatch.substr(1), 10) - ); - } else outChar = entityToUnicode[innerMatch]; - - // as in regular HTML, if we didn't decode the entity just - // leave the raw text in place. - return outChar || fullMatch; - }); -} -exports.convertEntities = convertEntities; - -function fromCodePoint(code) { - // Don't allow overflow. In Chrome this turns into � but I feel like it's - // more useful to just not convert it at all. - if(code > 0x10FFFF) return; - var stringFromCodePoint = String.fromCodePoint; - if(stringFromCodePoint) return stringFromCodePoint(code); - - // IE doesn't have String.fromCodePoint - // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint - var stringFromCharCode = String.fromCharCode; - if(code <= 0xFFFF) return stringFromCharCode(code); - return stringFromCharCode( - (code >> 10) + 0xD7C0, - (code % 0x400) + 0xDC00 - ); -} - -/* - * buildSVGText: convert our pseudo-html into SVG tspan elements, and attach these - * to containerNode - * - * @param {svg text element} containerNode: the node to insert this text into - * @param {string} str: the pseudo-html string to convert to svg - * - * @returns {bool}: does the result contain any links? We need to handle the text element - * somewhat differently if it does, so just keep track of this when it happens. - */ -function buildSVGText(containerNode, str) { - /* - * Normalize behavior between IE and others wrt newlines and whitespace:pre - * this combination makes IE barf https://github.com/plotly/plotly.js/issues/746 - * Chrome and FF display \n, \r, or \r\n as a space in this mode. - * I feel like at some point we turned these into
but currently we don't so - * I'm just going to cement what we do now in Chrome and FF - */ - str = str.replace(NEWLINES, ' '); - - var hasLink = false; - - // as we're building the text, keep track of what elements we're nested inside - // nodeStack will be an array of {node, type, style, href, target, popup} - // where only type: 'a' gets the last 3 and node is only added when it's created - var nodeStack = []; - var currentNode; - var currentLine = -1; - - function newLine() { - currentLine++; - - var lineNode = document.createElementNS(xmlnsNamespaces.svg, 'tspan'); - d3.select(lineNode).attr({ - class: 'line', - dy: (currentLine * LINE_SPACING) + 'em' - }); - containerNode.appendChild(lineNode); - - currentNode = lineNode; - - var oldNodeStack = nodeStack; - nodeStack = [{node: lineNode}]; - - if(oldNodeStack.length > 1) { - for(var i = 1; i < oldNodeStack.length; i++) { - enterNode(oldNodeStack[i]); - } - } - } - - function enterNode(nodeSpec) { - var type = nodeSpec.type; - var nodeAttrs = {}; - var nodeType; - - if(type === 'a') { - nodeType = 'a'; - var target = nodeSpec.target; - var href = nodeSpec.href; - var popup = nodeSpec.popup; - if(href) { - nodeAttrs = { - 'xlink:xlink:show': (target === '_blank' || target.charAt(0) !== '_') ? 'new' : 'replace', - target: target, - 'xlink:xlink:href': href - }; - if(popup) { - // security: href and target are not inserted as code but - // as attributes. popup is, but limited to /[A-Za-z0-9_=,]/ - nodeAttrs.onclick = 'window.open(this.href.baseVal,this.target.baseVal,"' + - popup + '");return false;'; - } - } - } else nodeType = 'tspan'; - - if(nodeSpec.style) nodeAttrs.style = nodeSpec.style; - - var newNode = document.createElementNS(xmlnsNamespaces.svg, nodeType); - - if(type === 'sup' || type === 'sub') { - addTextNode(currentNode, ZERO_WIDTH_SPACE); - currentNode.appendChild(newNode); - - var resetter = document.createElementNS(xmlnsNamespaces.svg, 'tspan'); - addTextNode(resetter, ZERO_WIDTH_SPACE); - d3.select(resetter).attr('dy', RESET_DY[type]); - nodeAttrs.dy = SHIFT_DY[type]; - - currentNode.appendChild(newNode); - currentNode.appendChild(resetter); - } else { - currentNode.appendChild(newNode); - } - - d3.select(newNode).attr(nodeAttrs); - - currentNode = nodeSpec.node = newNode; - nodeStack.push(nodeSpec); - } - - function addTextNode(node, text) { - node.appendChild(document.createTextNode(text)); - } - - function exitNode(type) { - // A bare closing tag can't close the root node. If we encounter this it - // means there's an extra closing tag that can just be ignored: - if(nodeStack.length === 1) { - Lib.log('Ignoring unexpected end tag .', str); - return; - } - - var innerNode = nodeStack.pop(); - - if(type !== innerNode.type) { - Lib.log('Start tag <' + innerNode.type + '> doesnt match end tag <' + - type + '>. Pretending it did match.', str); - } - currentNode = nodeStack[nodeStack.length - 1].node; - } - - var hasLines = BR_TAG.test(str); - - if(hasLines) newLine(); - else { - currentNode = containerNode; - nodeStack = [{node: containerNode}]; - } - - var parts = str.split(SPLIT_TAGS); - for(var i = 0; i < parts.length; i++) { - var parti = parts[i]; - var match = parti.match(ONE_TAG); - var tagType = match && match[2].toLowerCase(); - var tagStyle = TAG_STYLES[tagType]; - - if(tagType === 'br') { - newLine(); - } else if(tagStyle === undefined) { - addTextNode(currentNode, convertEntities(parti)); - } else { - // tag - open or close - if(match[1]) { - exitNode(tagType); - } else { - var extra = match[4]; - - var nodeSpec = {type: tagType}; - - // now add style, from both the tag name and any extra css - // Most of the svg css that users will care about is just like html, - // but font color is different (uses fill). Let our users ignore this. - var css = getQuotedMatch(extra, STYLEMATCH); - if(css) { - css = css.replace(COLORMATCH, '$1 fill:'); - if(tagStyle) css += ';' + tagStyle; - } else if(tagStyle) css = tagStyle; - - if(css) nodeSpec.style = css; - - if(tagType === 'a') { - hasLink = true; - - var href = getQuotedMatch(extra, HREFMATCH); - - if(href) { - // check safe protocols - var dummyAnchor = document.createElement('a'); - dummyAnchor.href = href; - if(PROTOCOLS.indexOf(dummyAnchor.protocol) !== -1) { - // Decode href to allow both already encoded and not encoded - // URIs. Without decoding prior encoding, an already encoded - // URI would be encoded twice producing a semantically different URI. - nodeSpec.href = encodeURI(decodeURI(href)); - nodeSpec.target = getQuotedMatch(extra, TARGETMATCH) || '_blank'; - nodeSpec.popup = getQuotedMatch(extra, POPUPMATCH); - } - } - } - - enterNode(nodeSpec); - } - } - } - - return hasLink; -} - -exports.lineCount = function lineCount(s) { - return s.selectAll('tspan.line').size() || 1; -}; - -exports.positionText = function positionText(s, x, y) { - return s.each(function() { - var text = d3.select(this); - - function setOrGet(attr, val) { - if(val === undefined) { - val = text.attr(attr); - if(val === null) { - text.attr(attr, 0); - val = 0; - } - } else text.attr(attr, val); - return val; - } - - var thisX = setOrGet('x', x); - var thisY = setOrGet('y', y); - - if(this.nodeName === 'text') { - text.selectAll('tspan.line').attr({x: thisX, y: thisY}); - } - }); -}; - -function alignHTMLWith(_base, container, options) { - var alignH = options.horizontalAlign; - var alignV = options.verticalAlign || 'top'; - var bRect = _base.node().getBoundingClientRect(); - var cRect = container.node().getBoundingClientRect(); - var thisRect; - var getTop; - var getLeft; - - if(alignV === 'bottom') { - getTop = function() { return bRect.bottom - thisRect.height; }; - } else if(alignV === 'middle') { - getTop = function() { return bRect.top + (bRect.height - thisRect.height) / 2; }; - } else { // default: top - getTop = function() { return bRect.top; }; - } - - if(alignH === 'right') { - getLeft = function() { return bRect.right - thisRect.width; }; - } else if(alignH === 'center') { - getLeft = function() { return bRect.left + (bRect.width - thisRect.width) / 2; }; - } else { // default: left - getLeft = function() { return bRect.left; }; - } - - return function() { - thisRect = this.node().getBoundingClientRect(); - this.style({ - top: (getTop() - cRect.top) + 'px', - left: (getLeft() - cRect.left) + 'px', - 'z-index': 1000 - }); - return this; - }; -} - -/* - * Editable title - * @param {d3.selection} context: the element being edited. Normally text, - * but if it isn't, you should provide the styling options - * @param {object} options: - * @param {div} options.gd: graphDiv - * @param {d3.selection} options.delegate: item to bind events to if not this - * @param {boolean} options.immediate: start editing now (true) or on click (false, default) - * @param {string} options.fill: font color if not as shown - * @param {string} options.background: background color if not as shown - * @param {string} options.text: initial text, if not as shown - * @param {string} options.horizontalAlign: alignment of the edit box wrt. the bound element - * @param {string} options.verticalAlign: alignment of the edit box wrt. the bound element - */ - -exports.makeEditable = function(context, options) { - var gd = options.gd; - var _delegate = options.delegate; - var dispatch = d3.dispatch('edit', 'input', 'cancel'); - var handlerElement = _delegate || context; - - context.style({'pointer-events': _delegate ? 'none' : 'all'}); - - if(context.size() !== 1) throw new Error('boo'); - - function handleClick() { - appendEditable(); - context.style({opacity: 0}); - // also hide any mathjax svg - var svgClass = handlerElement.attr('class'); - var mathjaxClass; - if(svgClass) mathjaxClass = '.' + svgClass.split(' ')[0] + '-math-group'; - else mathjaxClass = '[class*=-math-group]'; - if(mathjaxClass) { - d3.select(context.node().parentNode).select(mathjaxClass).style({opacity: 0}); - } - } - - function selectElementContents(_el) { - var el = _el.node(); - var range = document.createRange(); - range.selectNodeContents(el); - var sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - el.focus(); - } - - function appendEditable() { - var plotDiv = d3.select(gd); - var container = plotDiv.select('.svg-container'); - var div = container.append('div'); - var cStyle = context.node().style; - var fontSize = parseFloat(cStyle.fontSize || 12); - - var initialText = options.text; - if(initialText === undefined) initialText = context.attr('data-unformatted'); - - div.classed('plugin-editable editable', true) - .style({ - position: 'absolute', - 'font-family': cStyle.fontFamily || 'Arial', - 'font-size': fontSize, - color: options.fill || cStyle.fill || 'black', - opacity: 1, - 'background-color': options.background || 'transparent', - outline: '#ffffff33 1px solid', - margin: [-fontSize / 8 + 1, 0, 0, -1].join('px ') + 'px', - padding: '0', - 'box-sizing': 'border-box' - }) - .attr({contenteditable: true}) - .text(initialText) - .call(alignHTMLWith(context, container, options)) - .on('blur', function() { - gd._editing = false; - context.text(this.textContent) - .style({opacity: 1}); - var svgClass = d3.select(this).attr('class'); - var mathjaxClass; - if(svgClass) mathjaxClass = '.' + svgClass.split(' ')[0] + '-math-group'; - else mathjaxClass = '[class*=-math-group]'; - if(mathjaxClass) { - d3.select(context.node().parentNode).select(mathjaxClass).style({opacity: 0}); - } - var text = this.textContent; - d3.select(this).transition().duration(0).remove(); - d3.select(document).on('mouseup', null); - dispatch.edit.call(context, text); - }) - .on('focus', function() { - var editDiv = this; - gd._editing = true; - d3.select(document).on('mouseup', function() { - if(d3.event.target === editDiv) return false; - if(document.activeElement === div.node()) div.node().blur(); - }); - }) - .on('keyup', function() { - if(d3.event.which === 27) { - gd._editing = false; - context.style({opacity: 1}); - d3.select(this) - .style({opacity: 0}) - .on('blur', function() { return false; }) - .transition().remove(); - dispatch.cancel.call(context, this.textContent); - } else { - dispatch.input.call(context, this.textContent); - d3.select(this).call(alignHTMLWith(context, container, options)); - } - }) - .on('keydown', function() { - if(d3.event.which === 13) this.blur(); - }) - .call(selectElementContents); - } - - if(options.immediate) handleClick(); - else handlerElement.on('click', handleClick); - - return d3.rebind(context, dispatch, 'on'); -}; - -},{"../constants/alignment":688,"../constants/xmlns_namespaces":696,"../lib":719,"d3":163}],744:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var timerCache = {}; - -/** - * Throttle a callback. `callback` executes synchronously only if - * more than `minInterval` milliseconds have already elapsed since the latest - * call (if any). Otherwise we wait until `minInterval` is over and execute the - * last callback received while waiting. - * So the first and last events in a train are always executed (eventually) - * but some of the events in the middle can be dropped. - * - * @param {string} id: an identifier to mark events to throttle together - * @param {number} minInterval: minimum time, in milliseconds, between - * invocations of `callback` - * @param {function} callback: the function to throttle. `callback` itself - * should be a purely synchronous function. - */ -exports.throttle = function throttle(id, minInterval, callback) { - var cache = timerCache[id]; - var now = Date.now(); - - if(!cache) { - /* - * Throw out old items before making a new one, to prevent the cache - * getting overgrown, for example from old plots that have been replaced. - * 1 minute age is arbitrary. - */ - for(var idi in timerCache) { - if(timerCache[idi].ts < now - 60000) { - delete timerCache[idi]; - } - } - cache = timerCache[id] = {ts: 0, timer: null}; - } - - _clearTimeout(cache); - - function exec() { - callback(); - cache.ts = Date.now(); - if(cache.onDone) { - cache.onDone(); - cache.onDone = null; - } - } - - if(now > cache.ts + minInterval) { - exec(); - return; - } - - cache.timer = setTimeout(function() { - exec(); - cache.timer = null; - }, minInterval); -}; - -exports.done = function(id) { - var cache = timerCache[id]; - if(!cache || !cache.timer) return Promise.resolve(); - - return new Promise(function(resolve) { - var previousOnDone = cache.onDone; - cache.onDone = function onDone() { - if(previousOnDone) previousOnDone(); - resolve(); - cache.onDone = null; - }; - }); -}; - -/** - * Clear the throttle cache for one or all timers - * @param {optional string} id: - * if provided, clear just this timer - * if omitted, clear all timers (mainly useful for testing) - */ -exports.clear = function(id) { - if(id) { - _clearTimeout(timerCache[id]); - delete timerCache[id]; - } else { - for(var idi in timerCache) exports.clear(idi); - } -}; - -function _clearTimeout(cache) { - if(cache && cache.timer !== null) { - clearTimeout(cache.timer); - cache.timer = null; - } -} - -},{}],745:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -/** - * convert a linear value into a logged value, folding negative numbers into - * the given range - */ -module.exports = function toLogRange(val, range) { - if(val > 0) return Math.log(val) / Math.LN10; - - // move a negative value reference to a log axis - just put the - // result at the lowest range value on the plot (or if the range also went negative, - // one millionth of the top of the range) - var newVal = Math.log(Math.min(range[0], range[1])) / Math.LN10; - if(!isNumeric(newVal)) newVal = Math.log(Math.max(range[0], range[1])) / Math.LN10 - 6; - return newVal; -}; - -},{"fast-isnumeric":225}],746:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var topojsonUtils = module.exports = {}; - -var locationmodeToLayer = _dereq_('../plots/geo/constants').locationmodeToLayer; -var topojsonFeature = _dereq_('topojson-client').feature; - -topojsonUtils.getTopojsonName = function(geoLayout) { - return [ - geoLayout.scope.replace(/ /g, '-'), '_', - geoLayout.resolution.toString(), 'm' - ].join(''); -}; - -topojsonUtils.getTopojsonPath = function(topojsonURL, topojsonName) { - return topojsonURL + topojsonName + '.json'; -}; - -topojsonUtils.getTopojsonFeatures = function(trace, topojson) { - var layer = locationmodeToLayer[trace.locationmode]; - var obj = topojson.objects[layer]; - - return topojsonFeature(topojson, obj).features; -}; - -},{"../plots/geo/constants":795,"topojson-client":540}],747:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'locale', - name: 'en-US', - dictionary: { - 'Click to enter Colorscale title': 'Click to enter Colorscale title' - }, - format: { - date: '%m/%d/%Y' - } -}; - -},{}],748:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'locale', - name: 'en', - dictionary: { - 'Click to enter Colorscale title': 'Click to enter Colourscale title' - }, - format: { - days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], - months: [ - 'January', 'February', 'March', 'April', 'May', 'June', - 'July', 'August', 'September', 'October', 'November', 'December' - ], - shortMonths: [ - 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' - ], - periods: ['AM', 'PM'], - dateTime: '%a %b %e %X %Y', - date: '%d/%m/%Y', - time: '%H:%M:%S', - decimal: '.', - thousands: ',', - grouping: [3], - currency: ['$', ''], - year: '%Y', - month: '%b %Y', - dayMonth: '%b %-d', - dayMonthYear: '%b %-d, %Y' - } -}; - -},{}],749:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Registry = _dereq_('../registry'); - -/* - * containerArrayMatch: does this attribute string point into a - * layout container array? - * - * @param {String} astr: an attribute string, like *annotations[2].text* - * - * @returns {Object | false} Returns false if `astr` doesn't match a container - * array. If it does, returns: - * {array: {String}, index: {Number}, property: {String}} - * ie the attribute string for the array, the index within the array (or '' - * if the whole array) and the property within that (or '' if the whole array - * or the whole object) - */ -module.exports = function containerArrayMatch(astr) { - var rootContainers = Registry.layoutArrayContainers; - var regexpContainers = Registry.layoutArrayRegexes; - var rootPart = astr.split('[')[0]; - var arrayStr; - var match; - - // look for regexp matches first, because they may be nested inside root matches - // eg updatemenus[i].buttons is nested inside updatemenus - for(var i = 0; i < regexpContainers.length; i++) { - match = astr.match(regexpContainers[i]); - if(match && match.index === 0) { - arrayStr = match[0]; - break; - } - } - - // now look for root matches - if(!arrayStr) arrayStr = rootContainers[rootContainers.indexOf(rootPart)]; - - if(!arrayStr) return false; - - var tail = astr.substr(arrayStr.length); - if(!tail) return {array: arrayStr, index: '', property: ''}; - - match = tail.match(/^\[(0|[1-9][0-9]*)\](\.(.+))?$/); - if(!match) return false; - - return {array: arrayStr, index: Number(match[1]), property: match[3] || ''}; -}; - -},{"../registry":847}],750:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); -var extendFlat = Lib.extendFlat; -var isPlainObject = Lib.isPlainObject; - -var traceOpts = { - valType: 'flaglist', - extras: ['none'], - flags: ['calc', 'clearAxisTypes', 'plot', 'style', 'markerSize', 'colorbars'], - -}; - -var layoutOpts = { - valType: 'flaglist', - extras: ['none'], - flags: [ - 'calc', 'plot', 'legend', 'ticks', 'axrange', - 'layoutstyle', 'modebar', 'camera', 'arraydraw', 'colorbars' - ], - -}; - -// flags for inside restyle/relayout include a few extras -// that shouldn't be used in attributes, to deal with certain -// combinations and conditionals efficiently -var traceEditTypeFlags = traceOpts.flags.slice() - .concat(['fullReplot']); - -var layoutEditTypeFlags = layoutOpts.flags.slice() - .concat('layoutReplot'); - -module.exports = { - traces: traceOpts, - layout: layoutOpts, - /* - * default (all false) edit flags for restyle (traces) - * creates a new object each call, so the caller can mutate freely - */ - traceFlags: function() { return falseObj(traceEditTypeFlags); }, - - /* - * default (all false) edit flags for relayout - * creates a new object each call, so the caller can mutate freely - */ - layoutFlags: function() { return falseObj(layoutEditTypeFlags); }, - - /* - * update `flags` with the `editType` values found in `attr` - */ - update: function(flags, attr) { - var editType = attr.editType; - if(editType && editType !== 'none') { - var editTypeParts = editType.split('+'); - for(var i = 0; i < editTypeParts.length; i++) { - flags[editTypeParts[i]] = true; - } - } - }, - - overrideAll: overrideAll -}; - -function falseObj(keys) { - var out = {}; - for(var i = 0; i < keys.length; i++) out[keys[i]] = false; - return out; -} - -/** - * For attributes that are largely copied from elsewhere into a plot type that doesn't - * support partial redraws - overrides the editType field of all attributes in the object - * - * @param {object} attrs: the attributes to override. Will not be mutated. - * @param {string} editTypeOverride: the new editType to use - * @param {'nested'|'from-root'} overrideContainers: - * - 'nested' will override editType for nested containers but not the root. - * - 'from-root' will also override editType of the root container. - * Containers below the absolute top level (trace or layout root) DO need an - * editType even if they are not `valObject`s themselves (eg `scatter.marker`) - * to handle the case where you edit the whole container. - * - * @return {object} a new attributes object with `editType` modified as directed - */ -function overrideAll(attrs, editTypeOverride, overrideContainers) { - var out = extendFlat({}, attrs); - for(var key in out) { - var attr = out[key]; - if(isPlainObject(attr)) { - out[key] = overrideOne(attr, editTypeOverride, overrideContainers, key); - } - } - if(overrideContainers === 'from-root') out.editType = editTypeOverride; - - return out; -} - -function overrideOne(attr, editTypeOverride, overrideContainers, key) { - if(attr.valType) { - var out = extendFlat({}, attr); - out.editType = editTypeOverride; - - if(Array.isArray(attr.items)) { - out.items = new Array(attr.items.length); - for(var i = 0; i < attr.items.length; i++) { - out.items[i] = overrideOne(attr.items[i], editTypeOverride, 'from-root'); - } - } - return out; - } else { - // don't provide an editType for the _deprecated container - return overrideAll(attr, editTypeOverride, - (key.charAt(0) === '_') ? 'nested' : 'from-root'); - } -} - -},{"../lib":719}],751:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var m4FromQuat = _dereq_('gl-mat4/fromQuat'); - -var Registry = _dereq_('../registry'); -var Lib = _dereq_('../lib'); -var Plots = _dereq_('../plots/plots'); -var AxisIds = _dereq_('../plots/cartesian/axis_ids'); -var Color = _dereq_('../components/color'); - -var cleanId = AxisIds.cleanId; -var getFromTrace = AxisIds.getFromTrace; -var traceIs = Registry.traceIs; - -// clear the promise queue if one of them got rejected -exports.clearPromiseQueue = function(gd) { - if(Array.isArray(gd._promises) && gd._promises.length > 0) { - Lib.log('Clearing previous rejected promises from queue.'); - } - - gd._promises = []; -}; - -// make a few changes to the layout right away -// before it gets used for anything -// backward compatibility and cleanup of nonstandard options -exports.cleanLayout = function(layout) { - var i, j; - - if(!layout) layout = {}; - - // cannot have (x|y)axis1, numbering goes axis, axis2, axis3... - if(layout.xaxis1) { - if(!layout.xaxis) layout.xaxis = layout.xaxis1; - delete layout.xaxis1; - } - if(layout.yaxis1) { - if(!layout.yaxis) layout.yaxis = layout.yaxis1; - delete layout.yaxis1; - } - if(layout.scene1) { - if(!layout.scene) layout.scene = layout.scene1; - delete layout.scene1; - } - - var axisAttrRegex = (Plots.subplotsRegistry.cartesian || {}).attrRegex; - var polarAttrRegex = (Plots.subplotsRegistry.polar || {}).attrRegex; - var ternaryAttrRegex = (Plots.subplotsRegistry.ternary || {}).attrRegex; - var sceneAttrRegex = (Plots.subplotsRegistry.gl3d || {}).attrRegex; - - var keys = Object.keys(layout); - for(i = 0; i < keys.length; i++) { - var key = keys[i]; - - if(axisAttrRegex && axisAttrRegex.test(key)) { - // modifications to cartesian axes - - var ax = layout[key]; - if(ax.anchor && ax.anchor !== 'free') { - ax.anchor = cleanId(ax.anchor); - } - if(ax.overlaying) ax.overlaying = cleanId(ax.overlaying); - - // old method of axis type - isdate and islog (before category existed) - if(!ax.type) { - if(ax.isdate) ax.type = 'date'; - else if(ax.islog) ax.type = 'log'; - else if(ax.isdate === false && ax.islog === false) ax.type = 'linear'; - } - if(ax.autorange === 'withzero' || ax.autorange === 'tozero') { - ax.autorange = true; - ax.rangemode = 'tozero'; - } - delete ax.islog; - delete ax.isdate; - delete ax.categories; // replaced by _categories - - // prune empty domain arrays made before the new nestedProperty - if(emptyContainer(ax, 'domain')) delete ax.domain; - - // autotick -> tickmode - if(ax.autotick !== undefined) { - if(ax.tickmode === undefined) { - ax.tickmode = ax.autotick ? 'auto' : 'linear'; - } - delete ax.autotick; - } - - cleanTitle(ax); - } else if(polarAttrRegex && polarAttrRegex.test(key)) { - // modifications for polar - - var polar = layout[key]; - cleanTitle(polar.radialaxis); - } else if(ternaryAttrRegex && ternaryAttrRegex.test(key)) { - // modifications for ternary - - var ternary = layout[key]; - cleanTitle(ternary.aaxis); - cleanTitle(ternary.baxis); - cleanTitle(ternary.caxis); - } else if(sceneAttrRegex && sceneAttrRegex.test(key)) { - // modifications for 3D scenes - - var scene = layout[key]; - - // clean old Camera coords - var cameraposition = scene.cameraposition; - - if(Array.isArray(cameraposition) && cameraposition[0].length === 4) { - var rotation = cameraposition[0]; - var center = cameraposition[1]; - var radius = cameraposition[2]; - var mat = m4FromQuat([], rotation); - var eye = []; - - for(j = 0; j < 3; ++j) { - eye[j] = center[j] + radius * mat[2 + 4 * j]; - } - - scene.camera = { - eye: {x: eye[0], y: eye[1], z: eye[2]}, - center: {x: center[0], y: center[1], z: center[2]}, - up: {x: 0, y: 0, z: 1} // we just ignore calculating camera z up in this case - }; - - delete scene.cameraposition; - } - - // clean axis titles - cleanTitle(scene.xaxis); - cleanTitle(scene.yaxis); - cleanTitle(scene.zaxis); - } - } - - var annotationsLen = Array.isArray(layout.annotations) ? layout.annotations.length : 0; - for(i = 0; i < annotationsLen; i++) { - var ann = layout.annotations[i]; - - if(!Lib.isPlainObject(ann)) continue; - - if(ann.ref) { - if(ann.ref === 'paper') { - ann.xref = 'paper'; - ann.yref = 'paper'; - } else if(ann.ref === 'data') { - ann.xref = 'x'; - ann.yref = 'y'; - } - delete ann.ref; - } - - cleanAxRef(ann, 'xref'); - cleanAxRef(ann, 'yref'); - } - - var shapesLen = Array.isArray(layout.shapes) ? layout.shapes.length : 0; - for(i = 0; i < shapesLen; i++) { - var shape = layout.shapes[i]; - - if(!Lib.isPlainObject(shape)) continue; - - cleanAxRef(shape, 'xref'); - cleanAxRef(shape, 'yref'); - } - - var legend = layout.legend; - if(legend) { - // check for old-style legend positioning (x or y is +/- 100) - if(legend.x > 3) { - legend.x = 1.02; - legend.xanchor = 'left'; - } else if(legend.x < -2) { - legend.x = -0.02; - legend.xanchor = 'right'; - } - - if(legend.y > 3) { - legend.y = 1.02; - legend.yanchor = 'bottom'; - } else if(legend.y < -2) { - legend.y = -0.02; - legend.yanchor = 'top'; - } - } - - // clean plot title - cleanTitle(layout); - - /* - * Moved from rotate -> orbit for dragmode - */ - if(layout.dragmode === 'rotate') layout.dragmode = 'orbit'; - - // sanitize rgb(fractions) and rgba(fractions) that old tinycolor - // supported, but new tinycolor does not because they're not valid css - Color.clean(layout); - - // clean the layout container in layout.template - if(layout.template && layout.template.layout) { - exports.cleanLayout(layout.template.layout); - } - - return layout; -}; - -function cleanAxRef(container, attr) { - var valIn = container[attr]; - var axLetter = attr.charAt(0); - if(valIn && valIn !== 'paper') { - container[attr] = cleanId(valIn, axLetter); - } -} - -/** - * Cleans up old title attribute structure (flat) in favor of the new one (nested). - * - * @param {Object} titleContainer - an object potentially including deprecated title attributes - */ -function cleanTitle(titleContainer) { - if(titleContainer) { - // title -> title.text - // (although title used to be a string attribute, - // numbers are accepted as well) - if(typeof titleContainer.title === 'string' || typeof titleContainer.title === 'number') { - titleContainer.title = { - text: titleContainer.title - }; - } - - rewireAttr('titlefont', 'font'); - rewireAttr('titleposition', 'position'); - rewireAttr('titleside', 'side'); - rewireAttr('titleoffset', 'offset'); - } - - function rewireAttr(oldAttrName, newAttrName) { - var oldAttrSet = titleContainer[oldAttrName]; - var newAttrSet = titleContainer.title && titleContainer.title[newAttrName]; - - if(oldAttrSet && !newAttrSet) { - // Ensure title object exists - if(!titleContainer.title) { - titleContainer.title = {}; - } - - titleContainer.title[newAttrName] = titleContainer[oldAttrName]; - delete titleContainer[oldAttrName]; - } - } -} - -/* - * cleanData: Make a few changes to the data for backward compatibility - * before it gets used for anything. Modifies the data traces users provide. - * - * Important: if you're going to add something here that modifies a data array, - * update it in place so the new array === the old one. - */ -exports.cleanData = function(data) { - for(var tracei = 0; tracei < data.length; tracei++) { - var trace = data[tracei]; - var i; - - // use xbins to bin data in x, and ybins to bin data in y - if(trace.type === 'histogramy' && 'xbins' in trace && !('ybins' in trace)) { - trace.ybins = trace.xbins; - delete trace.xbins; - } - - // error_y.opacity is obsolete - merge into color - if(trace.error_y && 'opacity' in trace.error_y) { - var dc = Color.defaults; - var yeColor = trace.error_y.color || (traceIs(trace, 'bar') ? - Color.defaultLine : - dc[tracei % dc.length]); - trace.error_y.color = Color.addOpacity( - Color.rgb(yeColor), - Color.opacity(yeColor) * trace.error_y.opacity); - delete trace.error_y.opacity; - } - - // convert bardir to orientation, and put the data into - // the axes it's eventually going to be used with - if('bardir' in trace) { - if(trace.bardir === 'h' && (traceIs(trace, 'bar') || - trace.type.substr(0, 9) === 'histogram')) { - trace.orientation = 'h'; - exports.swapXYData(trace); - } - delete trace.bardir; - } - - // now we have only one 1D histogram type, and whether - // it uses x or y data depends on trace.orientation - if(trace.type === 'histogramy') exports.swapXYData(trace); - if(trace.type === 'histogramx' || trace.type === 'histogramy') { - trace.type = 'histogram'; - } - - // scl->scale, reversescl->reversescale - if('scl' in trace && !('colorscale' in trace)) { - trace.colorscale = trace.scl; - delete trace.scl; - } - if('reversescl' in trace && !('reversescale' in trace)) { - trace.reversescale = trace.reversescl; - delete trace.reversescl; - } - - // axis ids x1 -> x, y1-> y - if(trace.xaxis) trace.xaxis = cleanId(trace.xaxis, 'x'); - if(trace.yaxis) trace.yaxis = cleanId(trace.yaxis, 'y'); - - // scene ids scene1 -> scene - if(traceIs(trace, 'gl3d') && trace.scene) { - trace.scene = Plots.subplotsRegistry.gl3d.cleanId(trace.scene); - } - - if(!traceIs(trace, 'pie-like') && !traceIs(trace, 'bar-like')) { - if(Array.isArray(trace.textposition)) { - for(i = 0; i < trace.textposition.length; i++) { - trace.textposition[i] = cleanTextPosition(trace.textposition[i]); - } - } else if(trace.textposition) { - trace.textposition = cleanTextPosition(trace.textposition); - } - } - - // fix typo in colorscale definition - var _module = Registry.getModule(trace); - if(_module && _module.colorbar) { - var containerName = _module.colorbar.container; - var container = containerName ? trace[containerName] : trace; - if(container && container.colorscale) { - if(container.colorscale === 'YIGnBu') container.colorscale = 'YlGnBu'; - if(container.colorscale === 'YIOrRd') container.colorscale = 'YlOrRd'; - } - } - - // fix typo in surface 'highlight*' definitions - if(trace.type === 'surface' && Lib.isPlainObject(trace.contours)) { - var dims = ['x', 'y', 'z']; - - for(i = 0; i < dims.length; i++) { - var opts = trace.contours[dims[i]]; - - if(!Lib.isPlainObject(opts)) continue; - - if(opts.highlightColor) { - opts.highlightcolor = opts.highlightColor; - delete opts.highlightColor; - } - - if(opts.highlightWidth) { - opts.highlightwidth = opts.highlightWidth; - delete opts.highlightWidth; - } - } - } - - // fixes from converting finance from transforms to real trace types - if(trace.type === 'candlestick' || trace.type === 'ohlc') { - var increasingShowlegend = (trace.increasing || {}).showlegend !== false; - var decreasingShowlegend = (trace.decreasing || {}).showlegend !== false; - var increasingName = cleanFinanceDir(trace.increasing); - var decreasingName = cleanFinanceDir(trace.decreasing); - - // now figure out something smart to do with the separate direction - // names we removed - if((increasingName !== false) && (decreasingName !== false)) { - // both sub-names existed: base name previously had no effect - // so ignore it and try to find a shared part of the sub-names - - var newName = commonPrefix( - increasingName, decreasingName, - increasingShowlegend, decreasingShowlegend - ); - // if no common part, leave whatever name was (or wasn't) there - if(newName) trace.name = newName; - } else if((increasingName || decreasingName) && !trace.name) { - // one sub-name existed but not the base name - just use the sub-name - trace.name = increasingName || decreasingName; - } - } - - // transforms backward compatibility fixes - if(Array.isArray(trace.transforms)) { - var transforms = trace.transforms; - - for(i = 0; i < transforms.length; i++) { - var transform = transforms[i]; - - if(!Lib.isPlainObject(transform)) continue; - - switch(transform.type) { - case 'filter': - if(transform.filtersrc) { - transform.target = transform.filtersrc; - delete transform.filtersrc; - } - - if(transform.calendar) { - if(!transform.valuecalendar) { - transform.valuecalendar = transform.calendar; - } - delete transform.calendar; - } - break; - - case 'groupby': - // Name has changed from `style` to `styles`, so use `style` but prefer `styles`: - transform.styles = transform.styles || transform.style; - - if(transform.styles && !Array.isArray(transform.styles)) { - var prevStyles = transform.styles; - var styleKeys = Object.keys(prevStyles); - - transform.styles = []; - for(var j = 0; j < styleKeys.length; j++) { - transform.styles.push({ - target: styleKeys[j], - value: prevStyles[styleKeys[j]] - }); - } - } - break; - } - } - } - - // prune empty containers made before the new nestedProperty - if(emptyContainer(trace, 'line')) delete trace.line; - if('marker' in trace) { - if(emptyContainer(trace.marker, 'line')) delete trace.marker.line; - if(emptyContainer(trace, 'marker')) delete trace.marker; - } - - // sanitize rgb(fractions) and rgba(fractions) that old tinycolor - // supported, but new tinycolor does not because they're not valid css - Color.clean(trace); - - // remove obsolete autobin(x|y) attributes, but only if true - // if false, this needs to happen in Histogram.calc because it - // can be a one-time autobin so we need to know the results before - // we can push them back into the trace. - if(trace.autobinx) { - delete trace.autobinx; - delete trace.xbins; - } - if(trace.autobiny) { - delete trace.autobiny; - delete trace.ybins; - } - - cleanTitle(trace); - if(trace.colorbar) cleanTitle(trace.colorbar); - if(trace.marker && trace.marker.colorbar) cleanTitle(trace.marker.colorbar); - if(trace.line && trace.line.colorbar) cleanTitle(trace.line.colorbar); - if(trace.aaxis) cleanTitle(trace.aaxis); - if(trace.baxis) cleanTitle(trace.baxis); - } -}; - -function cleanFinanceDir(dirContainer) { - if(!Lib.isPlainObject(dirContainer)) return false; - - var dirName = dirContainer.name; - - delete dirContainer.name; - delete dirContainer.showlegend; - - return (typeof dirName === 'string' || typeof dirName === 'number') && String(dirName); -} - -function commonPrefix(name1, name2, show1, show2) { - // if only one is shown in the legend, use that - if(show1 && !show2) return name1; - if(show2 && !show1) return name2; - - // if both or neither are in the legend, check if one is blank (or whitespace) - // and use the other one - // note that hover labels can still use the name even if the legend doesn't - if(!name1.trim()) return name2; - if(!name2.trim()) return name1; - - var minLen = Math.min(name1.length, name2.length); - var i; - for(i = 0; i < minLen; i++) { - if(name1.charAt(i) !== name2.charAt(i)) break; - } - - var out = name1.substr(0, i); - return out.trim(); -} - -// textposition - support partial attributes (ie just 'top') -// and incorrect use of middle / center etc. -function cleanTextPosition(textposition) { - var posY = 'middle'; - var posX = 'center'; - - if(typeof textposition === 'string') { - if(textposition.indexOf('top') !== -1) posY = 'top'; - else if(textposition.indexOf('bottom') !== -1) posY = 'bottom'; - - if(textposition.indexOf('left') !== -1) posX = 'left'; - else if(textposition.indexOf('right') !== -1) posX = 'right'; - } - - return posY + ' ' + posX; -} - -function emptyContainer(outer, innerStr) { - return (innerStr in outer) && - (typeof outer[innerStr] === 'object') && - (Object.keys(outer[innerStr]).length === 0); -} - - -// swap all the data and data attributes associated with x and y -exports.swapXYData = function(trace) { - var i; - Lib.swapAttrs(trace, ['?', '?0', 'd?', '?bins', 'nbins?', 'autobin?', '?src', 'error_?']); - if(Array.isArray(trace.z) && Array.isArray(trace.z[0])) { - if(trace.transpose) delete trace.transpose; - else trace.transpose = true; - } - if(trace.error_x && trace.error_y) { - var errorY = trace.error_y; - var copyYstyle = ('copy_ystyle' in errorY) ? - errorY.copy_ystyle : - !(errorY.color || errorY.thickness || errorY.width); - Lib.swapAttrs(trace, ['error_?.copy_ystyle']); - if(copyYstyle) { - Lib.swapAttrs(trace, ['error_?.color', 'error_?.thickness', 'error_?.width']); - } - } - if(typeof trace.hoverinfo === 'string') { - var hoverInfoParts = trace.hoverinfo.split('+'); - for(i = 0; i < hoverInfoParts.length; i++) { - if(hoverInfoParts[i] === 'x') hoverInfoParts[i] = 'y'; - else if(hoverInfoParts[i] === 'y') hoverInfoParts[i] = 'x'; - } - trace.hoverinfo = hoverInfoParts.join('+'); - } -}; - -// coerce traceIndices input to array of trace indices -exports.coerceTraceIndices = function(gd, traceIndices) { - if(isNumeric(traceIndices)) { - return [traceIndices]; - } else if(!Array.isArray(traceIndices) || !traceIndices.length) { - return gd.data.map(function(_, i) { return i; }); - } else if(Array.isArray(traceIndices)) { - var traceIndicesOut = []; - for(var i = 0; i < traceIndices.length; i++) { - if(Lib.isIndex(traceIndices[i], gd.data.length)) { - traceIndicesOut.push(traceIndices[i]); - } else { - Lib.warn('trace index (', traceIndices[i], ') is not a number or is out of bounds'); - } - } - return traceIndicesOut; - } - - return traceIndices; -}; - -/** - * Manages logic around array container item creation / deletion / update - * that nested property alone can't handle. - * - * @param {Object} np - * nested property of update attribute string about trace or layout object - * @param {*} newVal - * update value passed to restyle / relayout / update - * @param {Object} undoit - * undo hash (N.B. undoit may be mutated here). - * - */ -exports.manageArrayContainers = function(np, newVal, undoit) { - var obj = np.obj; - var parts = np.parts; - var pLength = parts.length; - var pLast = parts[pLength - 1]; - - var pLastIsNumber = isNumeric(pLast); - - if(pLastIsNumber && newVal === null) { - // delete item - - // Clear item in array container when new value is null - var contPath = parts.slice(0, pLength - 1).join('.'); - var cont = Lib.nestedProperty(obj, contPath).get(); - cont.splice(pLast, 1); - - // Note that nested property clears null / undefined at end of - // array container, but not within them. - } else if(pLastIsNumber && np.get() === undefined) { - // create item - - // When adding a new item, make sure undo command will remove it - if(np.get() === undefined) undoit[np.astr] = null; - - np.set(newVal); - } else { - // update item - - // If the last part of attribute string isn't a number, - // np.set is all we need. - np.set(newVal); - } -}; - -/* - * Match the part to strip off to turn an attribute into its parent - * really it should be either '.some_characters' or '[number]' - * but we're a little more permissive here and match either - * '.not_brackets_or_dot' or '[not_brackets_or_dot]' - */ -var ATTR_TAIL_RE = /(\.[^\[\]\.]+|\[[^\[\]\.]+\])$/; - -function getParent(attr) { - var tail = attr.search(ATTR_TAIL_RE); - if(tail > 0) return attr.substr(0, tail); -} - -/* - * hasParent: does an attribute object contain a parent of the given attribute? - * for example, given 'images[2].x' do we also have 'images' or 'images[2]'? - * - * @param {Object} aobj - * update object, whose keys are attribute strings and values are their new settings - * @param {string} attr - * the attribute string to test against - * @returns {Boolean} - * is a parent of attr present in aobj? - */ -exports.hasParent = function(aobj, attr) { - var attrParent = getParent(attr); - while(attrParent) { - if(attrParent in aobj) return true; - attrParent = getParent(attrParent); - } - return false; -}; - -/** - * Empty out types for all axes containing these traces so we auto-set them again - * - * @param {object} gd - * @param {[integer]} traces: trace indices to search for axes to clear the types of - * @param {object} layoutUpdate: any update being done concurrently to the layout, - * which may supercede clearing the axis types - */ -var axLetters = ['x', 'y', 'z']; -exports.clearAxisTypes = function(gd, traces, layoutUpdate) { - for(var i = 0; i < traces.length; i++) { - var trace = gd._fullData[i]; - for(var j = 0; j < 3; j++) { - var ax = getFromTrace(gd, trace, axLetters[j]); - - // do not clear log type - that's never an auto result so must have been intentional - if(ax && ax.type !== 'log') { - var axAttr = ax._name; - var sceneName = ax._id.substr(1); - if(sceneName.substr(0, 5) === 'scene') { - if(layoutUpdate[sceneName] !== undefined) continue; - axAttr = sceneName + '.' + axAttr; - } - var typeAttr = axAttr + '.type'; - - if(layoutUpdate[axAttr] === undefined && layoutUpdate[typeAttr] === undefined) { - Lib.nestedProperty(gd.layout, typeAttr).set(null); - } - } - } - } -}; - -},{"../components/color":593,"../lib":719,"../plots/cartesian/axis_ids":770,"../plots/plots":828,"../registry":847,"fast-isnumeric":225,"gl-mat4/fromQuat":262}],752:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var main = _dereq_('./plot_api'); - -exports.plot = main.plot; -exports.newPlot = main.newPlot; -exports.restyle = main.restyle; -exports.relayout = main.relayout; -exports.redraw = main.redraw; -exports.update = main.update; -exports._guiRestyle = main._guiRestyle; -exports._guiRelayout = main._guiRelayout; -exports._guiUpdate = main._guiUpdate; -exports._storeDirectGUIEdit = main._storeDirectGUIEdit; -exports.react = main.react; -exports.extendTraces = main.extendTraces; -exports.prependTraces = main.prependTraces; -exports.addTraces = main.addTraces; -exports.deleteTraces = main.deleteTraces; -exports.moveTraces = main.moveTraces; -exports.purge = main.purge; -exports.addFrames = main.addFrames; -exports.deleteFrames = main.deleteFrames; -exports.animate = main.animate; -exports.setPlotConfig = main.setPlotConfig; - -exports.toImage = _dereq_('./to_image'); -exports.validate = _dereq_('./validate'); -exports.downloadImage = _dereq_('../snapshot/download'); - -var templateApi = _dereq_('./template_api'); -exports.makeTemplate = templateApi.makeTemplate; -exports.validateTemplate = templateApi.validateTemplate; - -},{"../snapshot/download":849,"./plot_api":754,"./template_api":759,"./to_image":760,"./validate":761}],753:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isPlainObject = _dereq_('../lib/is_plain_object'); -var noop = _dereq_('../lib/noop'); -var Loggers = _dereq_('../lib/loggers'); -var sorterAsc = _dereq_('../lib/search').sorterAsc; -var Registry = _dereq_('../registry'); - - -exports.containerArrayMatch = _dereq_('./container_array_match'); - -var isAddVal = exports.isAddVal = function isAddVal(val) { - return val === 'add' || isPlainObject(val); -}; - -var isRemoveVal = exports.isRemoveVal = function isRemoveVal(val) { - return val === null || val === 'remove'; -}; - -/* - * applyContainerArrayChanges: for managing arrays of layout components in relayout - * handles them all with a consistent interface. - * - * Here are the supported actions -> relayout calls -> edits we get here - * (as prepared in _relayout): - * - * add an empty obj -> {'annotations[2]': 'add'} -> {2: {'': 'add'}} - * add a specific obj -> {'annotations[2]': {attrs}} -> {2: {'': {attrs}}} - * delete an obj -> {'annotations[2]': 'remove'} -> {2: {'': 'remove'}} - * -> {'annotations[2]': null} -> {2: {'': null}} - * delete the whole array -> {'annotations': 'remove'} -> {'': {'': 'remove'}} - * -> {'annotations': null} -> {'': {'': null}} - * edit an object -> {'annotations[2].text': 'boo'} -> {2: {'text': 'boo'}} - * - * You can combine many edits to different objects. Objects are added and edited - * in ascending order, then removed in descending order. - * For example, starting with [a, b, c], if you want to: - * - replace b with d: - * {'annotations[1]': d, 'annotations[2]': null} (b is item 2 after adding d) - * - add a new item d between a and b, and edit b: - * {'annotations[1]': d, 'annotations[2].x': newX} (b is item 2 after adding d) - * - delete b and edit c: - * {'annotations[1]': null, 'annotations[2].x': newX} (c is edited before b is removed) - * - * You CANNOT combine adding/deleting an item at index `i` with edits to the same index `i` - * You CANNOT combine replacing/deleting the whole array with anything else (for the same array). - * - * @param {HTMLDivElement} gd - * the DOM element of the graph container div - * @param {Lib.nestedProperty} componentType: the array we are editing - * @param {Object} edits - * the changes to make; keys are indices to edit, values are themselves objects: - * {attr: newValue} of changes to make to that index (with add/remove behavior - * in special values of the empty attr) - * @param {Object} flags - * the flags for which actions we're going to perform to display these (and - * any other) changes. If we're already `recalc`ing, we don't need to redraw - * individual items - * @param {function} _nestedProperty - * a (possibly modified for gui edits) nestedProperty constructor - * The modified version takes a 3rd argument, for a prefix to the attribute - * string necessary for storing GUI edits - * - * @returns {bool} `true` if it managed to complete drawing of the changes - * `false` would mean the parent should replot. - */ -exports.applyContainerArrayChanges = function applyContainerArrayChanges(gd, np, edits, flags, _nestedProperty) { - var componentType = np.astr; - var supplyComponentDefaults = Registry.getComponentMethod(componentType, 'supplyLayoutDefaults'); - var draw = Registry.getComponentMethod(componentType, 'draw'); - var drawOne = Registry.getComponentMethod(componentType, 'drawOne'); - var replotLater = flags.replot || flags.recalc || (supplyComponentDefaults === noop) || (draw === noop); - var layout = gd.layout; - var fullLayout = gd._fullLayout; - - if(edits['']) { - if(Object.keys(edits).length > 1) { - Loggers.warn('Full array edits are incompatible with other edits', - componentType); - } - - var fullVal = edits['']['']; - - if(isRemoveVal(fullVal)) np.set(null); - else if(Array.isArray(fullVal)) np.set(fullVal); - else { - Loggers.warn('Unrecognized full array edit value', componentType, fullVal); - return true; - } - - if(replotLater) return false; - - supplyComponentDefaults(layout, fullLayout); - draw(gd); - return true; - } - - var componentNums = Object.keys(edits).map(Number).sort(sorterAsc); - var componentArrayIn = np.get(); - var componentArray = componentArrayIn || []; - // componentArrayFull is used just to keep splices in line between - // full and input arrays, so private keys can be copied over after - // redoing supplyDefaults - // TODO: this assumes componentArray is in gd.layout - which will not be - // true after we extend this to restyle - var componentArrayFull = _nestedProperty(fullLayout, componentType).get(); - - var deletes = []; - var firstIndexChange = -1; - var maxIndex = componentArray.length; - var i; - var j; - var componentNum; - var objEdits; - var objKeys; - var objVal; - var adding, prefix; - - // first make the add and edit changes - for(i = 0; i < componentNums.length; i++) { - componentNum = componentNums[i]; - objEdits = edits[componentNum]; - objKeys = Object.keys(objEdits); - objVal = objEdits[''], - adding = isAddVal(objVal); - - if(componentNum < 0 || componentNum > componentArray.length - (adding ? 0 : 1)) { - Loggers.warn('index out of range', componentType, componentNum); - continue; - } - - if(objVal !== undefined) { - if(objKeys.length > 1) { - Loggers.warn( - 'Insertion & removal are incompatible with edits to the same index.', - componentType, componentNum); - } - - if(isRemoveVal(objVal)) { - deletes.push(componentNum); - } else if(adding) { - if(objVal === 'add') objVal = {}; - componentArray.splice(componentNum, 0, objVal); - if(componentArrayFull) componentArrayFull.splice(componentNum, 0, {}); - } else { - Loggers.warn('Unrecognized full object edit value', - componentType, componentNum, objVal); - } - - if(firstIndexChange === -1) firstIndexChange = componentNum; - } else { - for(j = 0; j < objKeys.length; j++) { - prefix = componentType + '[' + componentNum + '].'; - _nestedProperty(componentArray[componentNum], objKeys[j], prefix) - .set(objEdits[objKeys[j]]); - } - } - } - - // now do deletes - for(i = deletes.length - 1; i >= 0; i--) { - componentArray.splice(deletes[i], 1); - // TODO: this drops private keys that had been stored in componentArrayFull - // does this have any ill effects? - if(componentArrayFull) componentArrayFull.splice(deletes[i], 1); - } - - if(!componentArray.length) np.set(null); - else if(!componentArrayIn) np.set(componentArray); - - if(replotLater) return false; - - supplyComponentDefaults(layout, fullLayout); - - // finally draw all the components we need to - // if we added or removed any, redraw all after it - if(drawOne !== noop) { - var indicesToDraw; - if(firstIndexChange === -1) { - // there's no re-indexing to do, so only redraw components that changed - indicesToDraw = componentNums; - } else { - // in case the component array was shortened, we still need do call - // drawOne on the latter items so they get properly removed - maxIndex = Math.max(componentArray.length, maxIndex); - indicesToDraw = []; - for(i = 0; i < componentNums.length; i++) { - componentNum = componentNums[i]; - if(componentNum >= firstIndexChange) break; - indicesToDraw.push(componentNum); - } - for(i = firstIndexChange; i < maxIndex; i++) { - indicesToDraw.push(i); - } - } - for(i = 0; i < indicesToDraw.length; i++) { - drawOne(gd, indicesToDraw[i]); - } - } else draw(gd); - - return true; -}; - -},{"../lib/is_plain_object":720,"../lib/loggers":723,"../lib/noop":728,"../lib/search":738,"../registry":847,"./container_array_match":749}],754:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); -var hasHover = _dereq_('has-hover'); - -var Lib = _dereq_('../lib'); -var nestedProperty = Lib.nestedProperty; - -var Events = _dereq_('../lib/events'); -var Queue = _dereq_('../lib/queue'); - -var Registry = _dereq_('../registry'); -var PlotSchema = _dereq_('./plot_schema'); -var Plots = _dereq_('../plots/plots'); -var Polar = _dereq_('../plots/polar/legacy'); - -var Axes = _dereq_('../plots/cartesian/axes'); -var Drawing = _dereq_('../components/drawing'); -var Color = _dereq_('../components/color'); -var initInteractions = _dereq_('../plots/cartesian/graph_interact').initInteractions; -var xmlnsNamespaces = _dereq_('../constants/xmlns_namespaces'); -var svgTextUtils = _dereq_('../lib/svg_text_utils'); -var clearSelect = _dereq_('../plots/cartesian/select').clearSelect; - -var dfltConfig = _dereq_('./plot_config').dfltConfig; -var manageArrays = _dereq_('./manage_arrays'); -var helpers = _dereq_('./helpers'); -var subroutines = _dereq_('./subroutines'); -var editTypes = _dereq_('./edit_types'); - -var AX_NAME_PATTERN = _dereq_('../plots/cartesian/constants').AX_NAME_PATTERN; - -var numericNameWarningCount = 0; -var numericNameWarningCountLimit = 5; - -/** - * Main plot-creation function - * - * @param {string id or DOM element} gd - * the id or DOM element of the graph container div - * @param {array of objects} data - * array of traces, containing the data and display information for each trace - * @param {object} layout - * object describing the overall display of the plot, - * all the stuff that doesn't pertain to any individual trace - * @param {object} config - * configuration options (see ./plot_config.js for more info) - * - * OR - * - * @param {string id or DOM element} gd - * the id or DOM element of the graph container div - * @param {object} figure - * object containing `data`, `layout`, `config`, and `frames` members - * - */ -function plot(gd, data, layout, config) { - var frames; - - gd = Lib.getGraphDiv(gd); - - // Events.init is idempotent and bails early if gd has already been init'd - Events.init(gd); - - if(Lib.isPlainObject(data)) { - var obj = data; - data = obj.data; - layout = obj.layout; - config = obj.config; - frames = obj.frames; - } - - var okToPlot = Events.triggerHandler(gd, 'plotly_beforeplot', [data, layout, config]); - if(okToPlot === false) return Promise.reject(); - - // if there's no data or layout, and this isn't yet a plotly plot - // container, log a warning to help plotly.js users debug - if(!data && !layout && !Lib.isPlotDiv(gd)) { - Lib.warn('Calling Plotly.plot as if redrawing ' + - 'but this container doesn\'t yet have a plot.', gd); - } - - function addFrames() { - if(frames) { - return exports.addFrames(gd, frames); - } - } - - // transfer configuration options to gd until we move over to - // a more OO like model - setPlotContext(gd, config); - - if(!layout) layout = {}; - - // hook class for plots main container (in case of plotly.js - // this won't be #embedded-graph or .js-tab-contents) - d3.select(gd).classed('js-plotly-plot', true); - - // off-screen getBoundingClientRect testing space, - // in #js-plotly-tester (and stored as Drawing.tester) - // so we can share cached text across tabs - Drawing.makeTester(); - - // collect promises for any async actions during plotting - // any part of the plotting code can push to gd._promises, then - // before we move to the next step, we check that they're all - // complete, and empty out the promise list again. - if(!Array.isArray(gd._promises)) gd._promises = []; - - var graphWasEmpty = ((gd.data || []).length === 0 && Array.isArray(data)); - - // if there is already data on the graph, append the new data - // if you only want to redraw, pass a non-array for data - if(Array.isArray(data)) { - helpers.cleanData(data); - - if(graphWasEmpty) gd.data = data; - else gd.data.push.apply(gd.data, data); - - // for routines outside graph_obj that want a clean tab - // (rather than appending to an existing one) gd.empty - // is used to determine whether to make a new tab - gd.empty = false; - } - - if(!gd.layout || graphWasEmpty) { - gd.layout = helpers.cleanLayout(layout); - } - - Plots.supplyDefaults(gd); - - var fullLayout = gd._fullLayout; - var hasCartesian = fullLayout._has('cartesian'); - - // Legacy polar plots - if(!fullLayout._has('polar') && data && data[0] && data[0].r) { - Lib.log('Legacy polar charts are deprecated!'); - return plotLegacyPolar(gd, data, layout); - } - - // so we don't try to re-call Plotly.plot from inside - // legend and colorbar, if margins changed - fullLayout._replotting = true; - - // make or remake the framework if we need to - if(graphWasEmpty) makePlotFramework(gd); - - // polar need a different framework - if(gd.framework !== makePlotFramework) { - gd.framework = makePlotFramework; - makePlotFramework(gd); - } - - // clear gradient defs on each .plot call, because we know we'll loop through all traces - Drawing.initGradients(gd); - - // save initial show spikes once per graph - if(graphWasEmpty) Axes.saveShowSpikeInitial(gd); - - // prepare the data and find the autorange - - // generate calcdata, if we need to - // to force redoing calcdata, just delete it before calling Plotly.plot - var recalc = !gd.calcdata || gd.calcdata.length !== (gd._fullData || []).length; - if(recalc) Plots.doCalcdata(gd); - - // in case it has changed, attach fullData traces to calcdata - for(var i = 0; i < gd.calcdata.length; i++) { - gd.calcdata[i][0].trace = gd._fullData[i]; - } - - // make the figure responsive - if(gd._context.responsive) { - if(!gd._responsiveChartHandler) { - // Keep a reference to the resize handler to purge it down the road - gd._responsiveChartHandler = function() { if(!Lib.isHidden(gd)) Plots.resize(gd); }; - - // Listen to window resize - window.addEventListener('resize', gd._responsiveChartHandler); - } - } else { - Lib.clearResponsive(gd); - } - - /* - * start async-friendly code - now we're actually drawing things - */ - - var oldMargins = Lib.extendFlat({}, fullLayout._size); - - // draw framework first so that margin-pushing - // components can position themselves correctly - var drawFrameworkCalls = 0; - function drawFramework() { - var basePlotModules = fullLayout._basePlotModules; - - for(var i = 0; i < basePlotModules.length; i++) { - if(basePlotModules[i].drawFramework) { - basePlotModules[i].drawFramework(gd); - } - } - - if(!fullLayout._glcanvas && fullLayout._has('gl')) { - fullLayout._glcanvas = fullLayout._glcontainer.selectAll('.gl-canvas').data([{ - key: 'contextLayer', - context: true, - pick: false - }, { - key: 'focusLayer', - context: false, - pick: false - }, { - key: 'pickLayer', - context: false, - pick: true - }], function(d) { return d.key; }); - - fullLayout._glcanvas.enter().append('canvas') - .attr('class', function(d) { - return 'gl-canvas gl-canvas-' + d.key.replace('Layer', ''); - }) - .style({ - position: 'absolute', - top: 0, - left: 0, - overflow: 'visible', - 'pointer-events': 'none' - }); - } - - if(fullLayout._glcanvas) { - fullLayout._glcanvas - .attr('width', fullLayout.width) - .attr('height', fullLayout.height); - - var regl = fullLayout._glcanvas.data()[0].regl; - if(regl) { - // Unfortunately, this can happen when relayouting to large - // width/height on some browsers. - if(Math.floor(fullLayout.width) !== regl._gl.drawingBufferWidth || - Math.floor(fullLayout.height) !== regl._gl.drawingBufferHeight - ) { - var msg = 'WebGL context buffer and canvas dimensions do not match due to browser/WebGL bug.'; - if(drawFrameworkCalls) { - Lib.error(msg); - } else { - Lib.log(msg + ' Clearing graph and plotting again.'); - Plots.cleanPlot([], {}, gd._fullData, fullLayout); - Plots.supplyDefaults(gd); - fullLayout = gd._fullLayout; - Plots.doCalcdata(gd); - drawFrameworkCalls++; - return drawFramework(); - } - } - } - } - - if(fullLayout.modebar.orientation === 'h') { - fullLayout._modebardiv - .style('height', null) - .style('width', '100%'); - } else { - fullLayout._modebardiv - .style('width', null) - .style('height', fullLayout.height + 'px'); - } - - return Plots.previousPromises(gd); - } - - // draw anything that can affect margins. - function marginPushers() { - // First reset the list of things that are allowed to change the margins - // So any deleted traces or components will be wiped out of the - // automargin calculation. - // This means *every* margin pusher must be listed here, even if it - // doesn't actually try to push the margins until later. - Plots.clearAutoMarginIds(gd); - - subroutines.drawMarginPushers(gd); - Axes.allowAutoMargin(gd); - - Plots.doAutoMargin(gd); - return Plots.previousPromises(gd); - } - - // in case the margins changed, draw margin pushers again - function marginPushersAgain() { - if(!Plots.didMarginChange(oldMargins, fullLayout._size)) return; - - return Lib.syncOrAsync([ - marginPushers, - subroutines.layoutStyles - ], gd); - } - - function positionAndAutorange() { - if(!recalc) { - doAutoRangeAndConstraints(); - return; - } - - // TODO: autosize extra for text markers and images - // see https://github.com/plotly/plotly.js/issues/1111 - return Lib.syncOrAsync([ - Registry.getComponentMethod('shapes', 'calcAutorange'), - Registry.getComponentMethod('annotations', 'calcAutorange'), - doAutoRangeAndConstraints - ], gd); - } - - function doAutoRangeAndConstraints() { - if(gd._transitioning) return; - - subroutines.doAutoRangeAndConstraints(gd); - - // store initial ranges *after* enforcing constraints, otherwise - // we will never look like we're at the initial ranges - if(graphWasEmpty) Axes.saveRangeInitial(gd); - - // this one is different from shapes/annotations calcAutorange - // the others incorporate those components into ax._extremes, - // this one actually sets the ranges in rangesliders. - Registry.getComponentMethod('rangeslider', 'calcAutorange')(gd); - } - - // draw ticks, titles, and calculate axis scaling (._b, ._m) - function drawAxes() { - return Axes.draw(gd, graphWasEmpty ? '' : 'redraw'); - } - - var seq = [ - Plots.previousPromises, - addFrames, - drawFramework, - marginPushers, - marginPushersAgain - ]; - - if(hasCartesian) seq.push(positionAndAutorange); - - seq.push(subroutines.layoutStyles); - if(hasCartesian) seq.push(drawAxes); - - seq.push( - subroutines.drawData, - subroutines.finalDraw, - initInteractions, - Plots.addLinks, - Plots.rehover, - Plots.redrag, - // TODO: doAutoMargin is only needed here for axis automargin, which - // happens outside of marginPushers where all the other automargins are - // calculated. Would be much better to separate margin calculations from - // component drawing - see https://github.com/plotly/plotly.js/issues/2704 - Plots.doAutoMargin, - Plots.previousPromises - ); - - // even if everything we did was synchronous, return a promise - // so that the caller doesn't care which route we took - var plotDone = Lib.syncOrAsync(seq, gd); - if(!plotDone || !plotDone.then) plotDone = Promise.resolve(); - - return plotDone.then(function() { - emitAfterPlot(gd); - return gd; - }); -} - -function emitAfterPlot(gd) { - var fullLayout = gd._fullLayout; - - if(fullLayout._redrawFromAutoMarginCount) { - fullLayout._redrawFromAutoMarginCount--; - } else { - gd.emit('plotly_afterplot'); - } -} - -function setPlotConfig(obj) { - return Lib.extendFlat(dfltConfig, obj); -} - -function setBackground(gd, bgColor) { - try { - gd._fullLayout._paper.style('background', bgColor); - } catch(e) { - Lib.error(e); - } -} - -function opaqueSetBackground(gd, bgColor) { - var blend = Color.combine(bgColor, 'white'); - setBackground(gd, blend); -} - -function setPlotContext(gd, config) { - if(!gd._context) { - gd._context = Lib.extendDeep({}, dfltConfig); - - // stash href, used to make robust clipPath URLs - var base = d3.select('base'); - gd._context._baseUrl = base.size() && base.attr('href') ? - window.location.href.split('#')[0] : - ''; - } - - var context = gd._context; - - var i, keys, key; - - if(config) { - keys = Object.keys(config); - for(i = 0; i < keys.length; i++) { - key = keys[i]; - if(key === 'editable' || key === 'edits') continue; - if(key in context) { - if(key === 'setBackground' && config[key] === 'opaque') { - context[key] = opaqueSetBackground; - } else { - context[key] = config[key]; - } - } - } - - // map plot3dPixelRatio to plotGlPixelRatio for backward compatibility - if(config.plot3dPixelRatio && !context.plotGlPixelRatio) { - context.plotGlPixelRatio = context.plot3dPixelRatio; - } - - // now deal with editable and edits - first editable overrides - // everything, then edits refines - var editable = config.editable; - if(editable !== undefined) { - // we're not going to *use* context.editable, we're only going to - // use context.edits... but keep it for the record - context.editable = editable; - - keys = Object.keys(context.edits); - for(i = 0; i < keys.length; i++) { - context.edits[keys[i]] = editable; - } - } - if(config.edits) { - keys = Object.keys(config.edits); - for(i = 0; i < keys.length; i++) { - key = keys[i]; - if(key in context.edits) { - context.edits[key] = config.edits[key]; - } - } - } - - // not part of the user-facing config options - context._exportedPlot = config._exportedPlot; - } - - // staticPlot forces a bunch of others: - if(context.staticPlot) { - context.editable = false; - context.edits = {}; - context.autosizable = false; - context.scrollZoom = false; - context.doubleClick = false; - context.showTips = false; - context.showLink = false; - context.displayModeBar = false; - } - - // make sure hover-only devices have mode bar visible - if(context.displayModeBar === 'hover' && !hasHover) { - context.displayModeBar = true; - } - - // default and fallback for setBackground - if(context.setBackground === 'transparent' || typeof context.setBackground !== 'function') { - context.setBackground = setBackground; - } - - // Check if gd has a specified widht/height to begin with - context._hasZeroHeight = context._hasZeroHeight || gd.clientHeight === 0; - context._hasZeroWidth = context._hasZeroWidth || gd.clientWidth === 0; - - // fill context._scrollZoom helper to help manage scrollZoom flaglist - var szIn = context.scrollZoom; - var szOut = context._scrollZoom = {}; - if(szIn === true) { - szOut.cartesian = 1; - szOut.gl3d = 1; - szOut.geo = 1; - szOut.mapbox = 1; - } else if(typeof szIn === 'string') { - var parts = szIn.split('+'); - for(i = 0; i < parts.length; i++) { - szOut[parts[i]] = 1; - } - } else if(szIn !== false) { - szOut.gl3d = 1; - szOut.geo = 1; - szOut.mapbox = 1; - } -} - -function plotLegacyPolar(gd, data, layout) { - // build or reuse the container skeleton - var plotContainer = d3.select(gd).selectAll('.plot-container') - .data([0]); - plotContainer.enter() - .insert('div', ':first-child') - .classed('plot-container plotly', true); - var paperDiv = plotContainer.selectAll('.svg-container') - .data([0]); - paperDiv.enter().append('div') - .classed('svg-container', true) - .style('position', 'relative'); - - // empty it everytime for now - paperDiv.html(''); - - // fulfill gd requirements - if(data) gd.data = data; - if(layout) gd.layout = layout; - Polar.manager.fillLayout(gd); - - // resize canvas - paperDiv.style({ - width: gd._fullLayout.width + 'px', - height: gd._fullLayout.height + 'px' - }); - - // instantiate framework - gd.framework = Polar.manager.framework(gd); - - // plot - gd.framework({data: gd.data, layout: gd.layout}, paperDiv.node()); - - // set undo point - gd.framework.setUndoPoint(); - - // get the resulting svg for extending it - var polarPlotSVG = gd.framework.svg(); - - // editable title - var opacity = 1; - var txt = gd._fullLayout.title ? gd._fullLayout.title.text : ''; - if(txt === '' || !txt) opacity = 0; - - var titleLayout = function() { - this.call(svgTextUtils.convertToTspans, gd); - // TODO: html/mathjax - // TODO: center title - }; - - var title = polarPlotSVG.select('.title-group text') - .call(titleLayout); - - if(gd._context.edits.titleText) { - var placeholderText = Lib._(gd, 'Click to enter Plot title'); - if(!txt || txt === placeholderText) { - opacity = 0.2; - // placeholder is not going through convertToTspans - // so needs explicit data-unformatted - title.attr({'data-unformatted': placeholderText}) - .text(placeholderText) - .style({opacity: opacity}) - .on('mouseover.opacity', function() { - d3.select(this).transition().duration(100) - .style('opacity', 1); - }) - .on('mouseout.opacity', function() { - d3.select(this).transition().duration(1000) - .style('opacity', 0); - }); - } - - var setContenteditable = function() { - this.call(svgTextUtils.makeEditable, {gd: gd}) - .on('edit', function(text) { - gd.framework({layout: {title: {text: text}}}); - this.text(text) - .call(titleLayout); - this.call(setContenteditable); - }) - .on('cancel', function() { - var txt = this.attr('data-unformatted'); - this.text(txt).call(titleLayout); - }); - }; - title.call(setContenteditable); - } - - gd._context.setBackground(gd, gd._fullLayout.paper_bgcolor); - Plots.addLinks(gd); - - return Promise.resolve(); -} - -// convenience function to force a full redraw, mostly for use by plotly.js -function redraw(gd) { - gd = Lib.getGraphDiv(gd); - - if(!Lib.isPlotDiv(gd)) { - throw new Error('This element is not a Plotly plot: ' + gd); - } - - helpers.cleanData(gd.data); - helpers.cleanLayout(gd.layout); - - gd.calcdata = undefined; - return exports.plot(gd).then(function() { - gd.emit('plotly_redraw'); - return gd; - }); -} - -/** - * Convenience function to make idempotent plot option obvious to users. - * - * @param gd - * @param {Object[]} data - * @param {Object} layout - * @param {Object} config - */ -function newPlot(gd, data, layout, config) { - gd = Lib.getGraphDiv(gd); - - // remove gl contexts - Plots.cleanPlot([], {}, gd._fullData || [], gd._fullLayout || {}); - - Plots.purge(gd); - return exports.plot(gd, data, layout, config); -} - -/** - * Wrap negative indicies to their positive counterparts. - * - * @param {Number[]} indices An array of indices - * @param {Number} maxIndex The maximum index allowable (arr.length - 1) - */ -function positivifyIndices(indices, maxIndex) { - var parentLength = maxIndex + 1; - var positiveIndices = []; - var i; - var index; - - for(i = 0; i < indices.length; i++) { - index = indices[i]; - if(index < 0) { - positiveIndices.push(parentLength + index); - } else { - positiveIndices.push(index); - } - } - return positiveIndices; -} - -/** - * Ensures that an index array for manipulating gd.data is valid. - * - * Intended for use with addTraces, deleteTraces, and moveTraces. - * - * @param gd - * @param indices - * @param arrayName - */ -function assertIndexArray(gd, indices, arrayName) { - var i, - index; - - for(i = 0; i < indices.length; i++) { - index = indices[i]; - - // validate that indices are indeed integers - if(index !== parseInt(index, 10)) { - throw new Error('all values in ' + arrayName + ' must be integers'); - } - - // check that all indices are in bounds for given gd.data array length - if(index >= gd.data.length || index < -gd.data.length) { - throw new Error(arrayName + ' must be valid indices for gd.data.'); - } - - // check that indices aren't repeated - if(indices.indexOf(index, i + 1) > -1 || - index >= 0 && indices.indexOf(-gd.data.length + index) > -1 || - index < 0 && indices.indexOf(gd.data.length + index) > -1) { - throw new Error('each index in ' + arrayName + ' must be unique.'); - } - } -} - -/** - * Private function used by Plotly.moveTraces to check input args - * - * @param gd - * @param currentIndices - * @param newIndices - */ -function checkMoveTracesArgs(gd, currentIndices, newIndices) { - // check that gd has attribute 'data' and 'data' is array - if(!Array.isArray(gd.data)) { - throw new Error('gd.data must be an array.'); - } - - // validate currentIndices array - if(typeof currentIndices === 'undefined') { - throw new Error('currentIndices is a required argument.'); - } else if(!Array.isArray(currentIndices)) { - currentIndices = [currentIndices]; - } - assertIndexArray(gd, currentIndices, 'currentIndices'); - - // validate newIndices array if it exists - if(typeof newIndices !== 'undefined' && !Array.isArray(newIndices)) { - newIndices = [newIndices]; - } - if(typeof newIndices !== 'undefined') { - assertIndexArray(gd, newIndices, 'newIndices'); - } - - // check currentIndices and newIndices are the same length if newIdices exists - if(typeof newIndices !== 'undefined' && currentIndices.length !== newIndices.length) { - throw new Error('current and new indices must be of equal length.'); - } -} -/** - * A private function to reduce the type checking clutter in addTraces. - * - * @param gd - * @param traces - * @param newIndices - */ -function checkAddTracesArgs(gd, traces, newIndices) { - var i, value; - - // check that gd has attribute 'data' and 'data' is array - if(!Array.isArray(gd.data)) { - throw new Error('gd.data must be an array.'); - } - - // make sure traces exists - if(typeof traces === 'undefined') { - throw new Error('traces must be defined.'); - } - - // make sure traces is an array - if(!Array.isArray(traces)) { - traces = [traces]; - } - - // make sure each value in traces is an object - for(i = 0; i < traces.length; i++) { - value = traces[i]; - if(typeof value !== 'object' || (Array.isArray(value) || value === null)) { - throw new Error('all values in traces array must be non-array objects'); - } - } - - // make sure we have an index for each trace - if(typeof newIndices !== 'undefined' && !Array.isArray(newIndices)) { - newIndices = [newIndices]; - } - if(typeof newIndices !== 'undefined' && newIndices.length !== traces.length) { - throw new Error( - 'if indices is specified, traces.length must equal indices.length' - ); - } -} - -/** - * A private function to reduce the type checking clutter in spliceTraces. - * Get all update Properties from gd.data. Validate inputs and outputs. - * Used by prependTrace and extendTraces - * - * @param gd - * @param update - * @param indices - * @param maxPoints - */ -function assertExtendTracesArgs(gd, update, indices, maxPoints) { - var maxPointsIsObject = Lib.isPlainObject(maxPoints); - - if(!Array.isArray(gd.data)) { - throw new Error('gd.data must be an array'); - } - if(!Lib.isPlainObject(update)) { - throw new Error('update must be a key:value object'); - } - - if(typeof indices === 'undefined') { - throw new Error('indices must be an integer or array of integers'); - } - - assertIndexArray(gd, indices, 'indices'); - - for(var key in update) { - /* - * Verify that the attribute to be updated contains as many trace updates - * as indices. Failure must result in throw and no-op - */ - if(!Array.isArray(update[key]) || update[key].length !== indices.length) { - throw new Error('attribute ' + key + ' must be an array of length equal to indices array length'); - } - - /* - * if maxPoints is an object it must match keys and array lengths of 'update' 1:1 - */ - if(maxPointsIsObject && - (!(key in maxPoints) || !Array.isArray(maxPoints[key]) || - maxPoints[key].length !== update[key].length)) { - throw new Error('when maxPoints is set as a key:value object it must contain a 1:1 ' + - 'corrispondence with the keys and number of traces in the update object'); - } - } -} - -/** - * A private function to reduce the type checking clutter in spliceTraces. - * - * @param {Object|HTMLDivElement} gd - * @param {Object} update - * @param {Number[]} indices - * @param {Number||Object} maxPoints - * @return {Object[]} - */ -function getExtendProperties(gd, update, indices, maxPoints) { - var maxPointsIsObject = Lib.isPlainObject(maxPoints); - var updateProps = []; - var trace, target, prop, insert, maxp; - - // allow scalar index to represent a single trace position - if(!Array.isArray(indices)) indices = [indices]; - - // negative indices are wrapped around to their positive value. Equivalent to python indexing. - indices = positivifyIndices(indices, gd.data.length - 1); - - // loop through all update keys and traces and harvest validated data. - for(var key in update) { - for(var j = 0; j < indices.length; j++) { - /* - * Choose the trace indexed by the indices map argument and get the prop setter-getter - * instance that references the key and value for this particular trace. - */ - trace = gd.data[indices[j]]; - prop = nestedProperty(trace, key); - - /* - * Target is the existing gd.data.trace.dataArray value like "x" or "marker.size" - * Target must exist as an Array to allow the extend operation to be performed. - */ - target = prop.get(); - insert = update[key][j]; - - if(!Lib.isArrayOrTypedArray(insert)) { - throw new Error('attribute: ' + key + ' index: ' + j + ' must be an array'); - } - if(!Lib.isArrayOrTypedArray(target)) { - throw new Error('cannot extend missing or non-array attribute: ' + key); - } - if(target.constructor !== insert.constructor) { - throw new Error('cannot extend array with an array of a different type: ' + key); - } - - /* - * maxPoints may be an object map or a scalar. If object select the key:value, else - * Use the scalar maxPoints for all key and trace combinations. - */ - maxp = maxPointsIsObject ? maxPoints[key][j] : maxPoints; - - // could have chosen null here, -1 just tells us to not take a window - if(!isNumeric(maxp)) maxp = -1; - - /* - * Wrap the nestedProperty in an object containing required data - * for lengthening and windowing this particular trace - key combination. - * Flooring maxp mirrors the behaviour of floats in the Array.slice JSnative function. - */ - updateProps.push({ - prop: prop, - target: target, - insert: insert, - maxp: Math.floor(maxp) - }); - } - } - - // all target and insertion data now validated - return updateProps; -} - -/** - * A private function to key Extend and Prepend traces DRY - * - * @param {Object|HTMLDivElement} gd - * @param {Object} update - * @param {Number[]} indices - * @param {Number||Object} maxPoints - * @param {Function} updateArray - * @return {Object} - */ -function spliceTraces(gd, update, indices, maxPoints, updateArray) { - assertExtendTracesArgs(gd, update, indices, maxPoints); - - var updateProps = getExtendProperties(gd, update, indices, maxPoints); - var undoUpdate = {}; - var undoPoints = {}; - - for(var i = 0; i < updateProps.length; i++) { - var prop = updateProps[i].prop; - var maxp = updateProps[i].maxp; - - // return new array and remainder - var out = updateArray(updateProps[i].target, updateProps[i].insert, maxp); - prop.set(out[0]); - - // build the inverse update object for the undo operation - if(!Array.isArray(undoUpdate[prop.astr])) undoUpdate[prop.astr] = []; - undoUpdate[prop.astr].push(out[1]); - - // build the matching maxPoints undo object containing original trace lengths - if(!Array.isArray(undoPoints[prop.astr])) undoPoints[prop.astr] = []; - undoPoints[prop.astr].push(updateProps[i].target.length); - } - - return {update: undoUpdate, maxPoints: undoPoints}; -} - -function concatTypedArray(arr0, arr1) { - var arr2 = new arr0.constructor(arr0.length + arr1.length); - arr2.set(arr0); - arr2.set(arr1, arr0.length); - return arr2; -} - -/** - * extend && prepend traces at indices with update arrays, window trace lengths to maxPoints - * - * Extend and Prepend have identical APIs. Prepend inserts an array at the head while Extend - * inserts an array off the tail. Prepend truncates the tail of the array - counting maxPoints - * from the head, whereas Extend truncates the head of the array, counting backward maxPoints - * from the tail. - * - * If maxPoints is undefined, nonNumeric, negative or greater than extended trace length no - * truncation / windowing will be performed. If its zero, well the whole trace is truncated. - * - * @param {Object|HTMLDivElement} gd The graph div - * @param {Object} update The key:array map of target attributes to extend - * @param {Number|Number[]} indices The locations of traces to be extended - * @param {Number|Object} [maxPoints] Number of points for trace window after lengthening. - * - */ -function extendTraces(gd, update, indices, maxPoints) { - gd = Lib.getGraphDiv(gd); - - function updateArray(target, insert, maxp) { - var newArray, remainder; - - if(Lib.isTypedArray(target)) { - if(maxp < 0) { - var none = new target.constructor(0); - var both = concatTypedArray(target, insert); - - if(maxp < 0) { - newArray = both; - remainder = none; - } else { - newArray = none; - remainder = both; - } - } else { - newArray = new target.constructor(maxp); - remainder = new target.constructor(target.length + insert.length - maxp); - - if(maxp === insert.length) { - newArray.set(insert); - remainder.set(target); - } else if(maxp < insert.length) { - var numberOfItemsFromInsert = insert.length - maxp; - - newArray.set(insert.subarray(numberOfItemsFromInsert)); - remainder.set(target); - remainder.set(insert.subarray(0, numberOfItemsFromInsert), target.length); - } else { - var numberOfItemsFromTarget = maxp - insert.length; - var targetBegin = target.length - numberOfItemsFromTarget; - - newArray.set(target.subarray(targetBegin)); - newArray.set(insert, numberOfItemsFromTarget); - remainder.set(target.subarray(0, targetBegin)); - } - } - } else { - newArray = target.concat(insert); - remainder = (maxp >= 0 && maxp < newArray.length) ? - newArray.splice(0, newArray.length - maxp) : - []; - } - - return [newArray, remainder]; - } - - var undo = spliceTraces(gd, update, indices, maxPoints, updateArray); - var promise = exports.redraw(gd); - var undoArgs = [gd, undo.update, indices, undo.maxPoints]; - Queue.add(gd, exports.prependTraces, undoArgs, extendTraces, arguments); - - return promise; -} - -function prependTraces(gd, update, indices, maxPoints) { - gd = Lib.getGraphDiv(gd); - - function updateArray(target, insert, maxp) { - var newArray, remainder; - - if(Lib.isTypedArray(target)) { - if(maxp <= 0) { - var none = new target.constructor(0); - var both = concatTypedArray(insert, target); - - if(maxp < 0) { - newArray = both; - remainder = none; - } else { - newArray = none; - remainder = both; - } - } else { - newArray = new target.constructor(maxp); - remainder = new target.constructor(target.length + insert.length - maxp); - - if(maxp === insert.length) { - newArray.set(insert); - remainder.set(target); - } else if(maxp < insert.length) { - var numberOfItemsFromInsert = insert.length - maxp; - - newArray.set(insert.subarray(0, numberOfItemsFromInsert)); - remainder.set(insert.subarray(numberOfItemsFromInsert)); - remainder.set(target, numberOfItemsFromInsert); - } else { - var numberOfItemsFromTarget = maxp - insert.length; - - newArray.set(insert); - newArray.set(target.subarray(0, numberOfItemsFromTarget), insert.length); - remainder.set(target.subarray(numberOfItemsFromTarget)); - } - } - } else { - newArray = insert.concat(target); - remainder = (maxp >= 0 && maxp < newArray.length) ? - newArray.splice(maxp, newArray.length) : - []; - } - - return [newArray, remainder]; - } - - var undo = spliceTraces(gd, update, indices, maxPoints, updateArray); - var promise = exports.redraw(gd); - var undoArgs = [gd, undo.update, indices, undo.maxPoints]; - Queue.add(gd, exports.extendTraces, undoArgs, prependTraces, arguments); - - return promise; -} - -/** - * Add data traces to an existing graph div. - * - * @param {Object|HTMLDivElement} gd The graph div - * @param {Object[]} gd.data The array of traces we're adding to - * @param {Object[]|Object} traces The object or array of objects to add - * @param {Number[]|Number} [newIndices=[gd.data.length]] Locations to add traces - * - */ -function addTraces(gd, traces, newIndices) { - gd = Lib.getGraphDiv(gd); - - var currentIndices = []; - var undoFunc = exports.deleteTraces; - var redoFunc = addTraces; - var undoArgs = [gd, currentIndices]; - var redoArgs = [gd, traces]; // no newIndices here - var i; - var promise; - - // all validation is done elsewhere to remove clutter here - checkAddTracesArgs(gd, traces, newIndices); - - // make sure traces is an array - if(!Array.isArray(traces)) { - traces = [traces]; - } - - // make sure traces do not repeat existing ones - traces = traces.map(function(trace) { - return Lib.extendFlat({}, trace); - }); - - helpers.cleanData(traces); - - // add the traces to gd.data (no redrawing yet!) - for(i = 0; i < traces.length; i++) { - gd.data.push(traces[i]); - } - - // to continue, we need to call moveTraces which requires currentIndices - for(i = 0; i < traces.length; i++) { - currentIndices.push(-traces.length + i); - } - - // if the user didn't define newIndices, they just want the traces appended - // i.e., we can simply redraw and be done - if(typeof newIndices === 'undefined') { - promise = exports.redraw(gd); - Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); - return promise; - } - - // make sure indices is property defined - if(!Array.isArray(newIndices)) { - newIndices = [newIndices]; - } - - try { - // this is redundant, but necessary to not catch later possible errors! - checkMoveTracesArgs(gd, currentIndices, newIndices); - } catch(error) { - // something went wrong, reset gd to be safe and rethrow error - gd.data.splice(gd.data.length - traces.length, traces.length); - throw error; - } - - // if we're here, the user has defined specific places to place the new traces - // this requires some extra work that moveTraces will do - Queue.startSequence(gd); - Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); - promise = exports.moveTraces(gd, currentIndices, newIndices); - Queue.stopSequence(gd); - return promise; -} - -/** - * Delete traces at `indices` from gd.data array. - * - * @param {Object|HTMLDivElement} gd The graph div - * @param {Object[]} gd.data The array of traces we're removing from - * @param {Number|Number[]} indices The indices - */ -function deleteTraces(gd, indices) { - gd = Lib.getGraphDiv(gd); - - var traces = []; - var undoFunc = exports.addTraces; - var redoFunc = deleteTraces; - var undoArgs = [gd, traces, indices]; - var redoArgs = [gd, indices]; - var i; - var deletedTrace; - - // make sure indices are defined - if(typeof indices === 'undefined') { - throw new Error('indices must be an integer or array of integers.'); - } else if(!Array.isArray(indices)) { - indices = [indices]; - } - assertIndexArray(gd, indices, 'indices'); - - // convert negative indices to positive indices - indices = positivifyIndices(indices, gd.data.length - 1); - - // we want descending here so that splicing later doesn't affect indexing - indices.sort(Lib.sorterDes); - for(i = 0; i < indices.length; i += 1) { - deletedTrace = gd.data.splice(indices[i], 1)[0]; - traces.push(deletedTrace); - } - - var promise = exports.redraw(gd); - Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); - - return promise; -} - -/** - * Move traces at currentIndices array to locations in newIndices array. - * - * If newIndices is omitted, currentIndices will be moved to the end. E.g., - * these are equivalent: - * - * Plotly.moveTraces(gd, [1, 2, 3], [-3, -2, -1]) - * Plotly.moveTraces(gd, [1, 2, 3]) - * - * @param {Object|HTMLDivElement} gd The graph div - * @param {Object[]} gd.data The array of traces we're removing from - * @param {Number|Number[]} currentIndices The locations of traces to be moved - * @param {Number|Number[]} [newIndices] The locations to move traces to - * - * Example calls: - * - * // move trace i to location x - * Plotly.moveTraces(gd, i, x) - * - * // move trace i to end of array - * Plotly.moveTraces(gd, i) - * - * // move traces i, j, k to end of array (i != j != k) - * Plotly.moveTraces(gd, [i, j, k]) - * - * // move traces [i, j, k] to [x, y, z] (i != j != k) (x != y != z) - * Plotly.moveTraces(gd, [i, j, k], [x, y, z]) - * - * // reorder all traces (assume there are 5--a, b, c, d, e) - * Plotly.moveTraces(gd, [b, d, e, a, c]) // same as 'move to end' - */ -function moveTraces(gd, currentIndices, newIndices) { - gd = Lib.getGraphDiv(gd); - - var newData = []; - var movingTraceMap = []; - var undoFunc = moveTraces; - var redoFunc = moveTraces; - var undoArgs = [gd, newIndices, currentIndices]; - var redoArgs = [gd, currentIndices, newIndices]; - var i; - - // to reduce complexity here, check args elsewhere - // this throws errors where appropriate - checkMoveTracesArgs(gd, currentIndices, newIndices); - - // make sure currentIndices is an array - currentIndices = Array.isArray(currentIndices) ? currentIndices : [currentIndices]; - - // if undefined, define newIndices to point to the end of gd.data array - if(typeof newIndices === 'undefined') { - newIndices = []; - for(i = 0; i < currentIndices.length; i++) { - newIndices.push(-currentIndices.length + i); - } - } - - // make sure newIndices is an array if it's user-defined - newIndices = Array.isArray(newIndices) ? newIndices : [newIndices]; - - // convert negative indices to positive indices (they're the same length) - currentIndices = positivifyIndices(currentIndices, gd.data.length - 1); - newIndices = positivifyIndices(newIndices, gd.data.length - 1); - - // at this point, we've coerced the index arrays into predictable forms - - // get the traces that aren't being moved around - for(i = 0; i < gd.data.length; i++) { - // if index isn't in currentIndices, include it in ignored! - if(currentIndices.indexOf(i) === -1) { - newData.push(gd.data[i]); - } - } - - // get a mapping of indices to moving traces - for(i = 0; i < currentIndices.length; i++) { - movingTraceMap.push({newIndex: newIndices[i], trace: gd.data[currentIndices[i]]}); - } - - // reorder this mapping by newIndex, ascending - movingTraceMap.sort(function(a, b) { - return a.newIndex - b.newIndex; - }); - - // now, add the moving traces back in, in order! - for(i = 0; i < movingTraceMap.length; i += 1) { - newData.splice(movingTraceMap[i].newIndex, 0, movingTraceMap[i].trace); - } - - gd.data = newData; - - var promise = exports.redraw(gd); - Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); - - return promise; -} - -/** - * restyle: update trace attributes of an existing plot - * - * Can be called two ways. - * - * Signature 1: - * @param {String | HTMLDivElement} gd - * the id or DOM element of the graph container div - * @param {String} astr - * attribute string (like `'marker.symbol'`) to update - * @param {*} val - * value to give this attribute - * @param {Number[] | Number} [traces] - * integer or array of integers for the traces to alter (all if omitted) - * - * Signature 2: - * @param {String | HTMLDivElement} gd - * (as in signature 1) - * @param {Object} aobj - * attribute object `{astr1: val1, astr2: val2 ...}` - * allows setting multiple attributes simultaneously - * @param {Number[] | Number} [traces] - * (as in signature 1) - * - * `val` (or `val1`, `val2` ... in the object form) can be an array, - * to apply different values to each trace. - * - * If the array is too short, it will wrap around (useful for - * style files that want to specify cyclical default values). - */ -function restyle(gd, astr, val, _traces) { - gd = Lib.getGraphDiv(gd); - helpers.clearPromiseQueue(gd); - - var aobj = {}; - if(typeof astr === 'string') aobj[astr] = val; - else if(Lib.isPlainObject(astr)) { - // the 3-arg form - aobj = Lib.extendFlat({}, astr); - if(_traces === undefined) _traces = val; - } else { - Lib.warn('Restyle fail.', astr, val, _traces); - return Promise.reject(); - } - - if(Object.keys(aobj).length) gd.changed = true; - - var traces = helpers.coerceTraceIndices(gd, _traces); - - var specs = _restyle(gd, aobj, traces); - var flags = specs.flags; - - // clear calcdata and/or axis types if required so they get regenerated - if(flags.calc) gd.calcdata = undefined; - if(flags.clearAxisTypes) helpers.clearAxisTypes(gd, traces, {}); - - // fill in redraw sequence - var seq = []; - - if(flags.fullReplot) { - seq.push(exports.plot); - } else { - seq.push(Plots.previousPromises); - - // maybe only call Plots.supplyDataDefaults in the splom case, - // to skip over long and slow axes defaults - Plots.supplyDefaults(gd); - - if(flags.markerSize) { - Plots.doCalcdata(gd); - addAxRangeSequence(seq); - - // TODO - // if all axes have autorange:false, then - // proceed to subroutines.doTraceStyle(), - // otherwise we must go through addAxRangeSequence, - // which in general must redraws 'all' axes - } - - if(flags.style) seq.push(subroutines.doTraceStyle); - if(flags.colorbars) seq.push(subroutines.doColorBars); - - seq.push(emitAfterPlot); - } - - seq.push(Plots.rehover, Plots.redrag); - - Queue.add(gd, - restyle, [gd, specs.undoit, specs.traces], - restyle, [gd, specs.redoit, specs.traces] - ); - - var plotDone = Lib.syncOrAsync(seq, gd); - if(!plotDone || !plotDone.then) plotDone = Promise.resolve(); - - return plotDone.then(function() { - gd.emit('plotly_restyle', specs.eventData); - return gd; - }); -} - -// for undo: undefined initial vals must be turned into nulls -// so that we unset rather than ignore them -function undefinedToNull(val) { - if(val === undefined) return null; - return val; -} - -/** - * Factory function to wrap nestedProperty with GUI edits if necessary - * with GUI edits we add an optional prefix to the nestedProperty constructor - * to prepend to the attribute string in the preGUI store. - */ -function makeNP(preGUI, guiEditFlag) { - if(!guiEditFlag) return nestedProperty; - - return function(container, attr, prefix) { - var np = nestedProperty(container, attr); - var npSet = np.set; - np.set = function(val) { - var fullAttr = (prefix || '') + attr; - storeCurrent(fullAttr, np.get(), val, preGUI); - npSet(val); - }; - return np; - }; -} - -function storeCurrent(attr, val, newVal, preGUI) { - if(Array.isArray(val) || Array.isArray(newVal)) { - var arrayVal = Array.isArray(val) ? val : []; - var arrayNew = Array.isArray(newVal) ? newVal : []; - var maxLen = Math.max(arrayVal.length, arrayNew.length); - for(var i = 0; i < maxLen; i++) { - storeCurrent(attr + '[' + i + ']', arrayVal[i], arrayNew[i], preGUI); - } - } else if(Lib.isPlainObject(val) || Lib.isPlainObject(newVal)) { - var objVal = Lib.isPlainObject(val) ? val : {}; - var objNew = Lib.isPlainObject(newVal) ? newVal : {}; - var objBoth = Lib.extendFlat({}, objVal, objNew); - for(var key in objBoth) { - storeCurrent(attr + '.' + key, objVal[key], objNew[key], preGUI); - } - } else if(preGUI[attr] === undefined) { - preGUI[attr] = undefinedToNull(val); - } -} - -/** - * storeDirectGUIEdit: for routines that skip restyle/relayout and mock it - * by emitting a plotly_restyle or plotly_relayout event, this routine - * keeps track of the initial state in _preGUI for use by uirevision - * Does *not* apply these changes to data/layout - that's the responsibility - * of the calling routine. - * - * @param {object} container: the input attributes container (eg `layout` or a `trace`) - * @param {object} preGUI: where original values should be stored, either - * `layout._preGUI` or `layout._tracePreGUI[uid]` - * @param {object} edits: the {attr: val} object as normally passed to `relayout` etc - */ -function _storeDirectGUIEdit(container, preGUI, edits) { - for(var attr in edits) { - var np = nestedProperty(container, attr); - storeCurrent(attr, np.get(), edits[attr], preGUI); - } -} - -function _restyle(gd, aobj, traces) { - var fullLayout = gd._fullLayout; - var fullData = gd._fullData; - var data = gd.data; - var guiEditFlag = fullLayout._guiEditing; - var layoutNP = makeNP(fullLayout._preGUI, guiEditFlag); - var eventData = Lib.extendDeepAll({}, aobj); - var i; - - cleanDeprecatedAttributeKeys(aobj); - - // initialize flags - var flags = editTypes.traceFlags(); - - // copies of the change (and previous values of anything affected) - // for the undo / redo queue - var redoit = {}; - var undoit = {}; - var axlist; - - // make a new empty vals array for undoit - function a0() { return traces.map(function() { return undefined; }); } - - // for autoranging multiple axes - function addToAxlist(axid) { - var axName = Axes.id2name(axid); - if(axlist.indexOf(axName) === -1) axlist.push(axName); - } - - function autorangeAttr(axName) { return 'LAYOUT' + axName + '.autorange'; } - - function rangeAttr(axName) { return 'LAYOUT' + axName + '.range'; } - - function getFullTrace(traceIndex) { - // usually fullData maps 1:1 onto data, but with groupby transforms - // the fullData index can be greater. Take the *first* matching trace. - for(var j = traceIndex; j < fullData.length; j++) { - if(fullData[j]._input === data[traceIndex]) return fullData[j]; - } - // should never get here - and if we *do* it should cause an error - // later on undefined fullTrace is passed to nestedProperty. - } - - // for attrs that interact (like scales & autoscales), save the - // old vals before making the change - // val=undefined will not set a value, just record what the value was. - // val=null will delete the attribute - // attr can be an array to set several at once (all to the same val) - function doextra(attr, val, i) { - if(Array.isArray(attr)) { - attr.forEach(function(a) { doextra(a, val, i); }); - return; - } - // quit if explicitly setting this elsewhere - if(attr in aobj || helpers.hasParent(aobj, attr)) return; - - var extraparam; - if(attr.substr(0, 6) === 'LAYOUT') { - extraparam = layoutNP(gd.layout, attr.replace('LAYOUT', '')); - } else { - var tracei = traces[i]; - var preGUI = fullLayout._tracePreGUI[getFullTrace(tracei)._fullInput.uid]; - extraparam = makeNP(preGUI, guiEditFlag)(data[tracei], attr); - } - - if(!(attr in undoit)) { - undoit[attr] = a0(); - } - if(undoit[attr][i] === undefined) { - undoit[attr][i] = undefinedToNull(extraparam.get()); - } - if(val !== undefined) { - extraparam.set(val); - } - } - - function allBins(binAttr) { - return function(j) { - return fullData[j][binAttr]; - }; - } - - function arrayBins(binAttr) { - return function(vij, j) { - return vij === false ? fullData[traces[j]][binAttr] : null; - }; - } - - // now make the changes to gd.data (and occasionally gd.layout) - // and figure out what kind of graphics update we need to do - for(var ai in aobj) { - if(helpers.hasParent(aobj, ai)) { - throw new Error('cannot set ' + ai + ' and a parent attribute simultaneously'); - } - - var vi = aobj[ai]; - var cont; - var contFull; - var param; - var oldVal; - var newVal; - var valObject; - - // Backward compatibility shim for turning histogram autobin on, - // or freezing previous autobinned values. - // Replace obsolete `autobin(x|y): true` with `(x|y)bins: null` - // and `autobin(x|y): false` with the `(x|y)bins` in `fullData` - if(ai === 'autobinx' || ai === 'autobiny') { - ai = ai.charAt(ai.length - 1) + 'bins'; - if(Array.isArray(vi)) vi = vi.map(arrayBins(ai)); - else if(vi === false) vi = traces.map(allBins(ai)); - else vi = null; - } - - redoit[ai] = vi; - - if(ai.substr(0, 6) === 'LAYOUT') { - param = layoutNP(gd.layout, ai.replace('LAYOUT', '')); - undoit[ai] = [undefinedToNull(param.get())]; - // since we're allowing val to be an array, allow it here too, - // even though that's meaningless - param.set(Array.isArray(vi) ? vi[0] : vi); - // ironically, the layout attrs in restyle only require replot, - // not relayout - flags.calc = true; - continue; - } - - // set attribute in gd.data - undoit[ai] = a0(); - for(i = 0; i < traces.length; i++) { - cont = data[traces[i]]; - contFull = getFullTrace(traces[i]); - var preGUI = fullLayout._tracePreGUI[contFull._fullInput.uid]; - param = makeNP(preGUI, guiEditFlag)(cont, ai); - oldVal = param.get(); - newVal = Array.isArray(vi) ? vi[i % vi.length] : vi; - - if(newVal === undefined) continue; - - var finalPart = param.parts[param.parts.length - 1]; - var prefix = ai.substr(0, ai.length - finalPart.length - 1); - var prefixDot = prefix ? prefix + '.' : ''; - var innerContFull = prefix ? - nestedProperty(contFull, prefix).get() : contFull; - - valObject = PlotSchema.getTraceValObject(contFull, param.parts); - - if(valObject && valObject.impliedEdits && newVal !== null) { - for(var impliedKey in valObject.impliedEdits) { - doextra(Lib.relativeAttr(ai, impliedKey), valObject.impliedEdits[impliedKey], i); - } - } else if((finalPart === 'thicknessmode' || finalPart === 'lenmode') && - oldVal !== newVal && - (newVal === 'fraction' || newVal === 'pixels') && - innerContFull - ) { - // changing colorbar size modes, - // make the resulting size not change - // note that colorbar fractional sizing is based on the - // original plot size, before anything (like a colorbar) - // increases the margins - - var gs = fullLayout._size; - var orient = innerContFull.orient; - var topOrBottom = (orient === 'top') || (orient === 'bottom'); - if(finalPart === 'thicknessmode') { - var thicknorm = topOrBottom ? gs.h : gs.w; - doextra(prefixDot + 'thickness', innerContFull.thickness * - (newVal === 'fraction' ? 1 / thicknorm : thicknorm), i); - } else { - var lennorm = topOrBottom ? gs.w : gs.h; - doextra(prefixDot + 'len', innerContFull.len * - (newVal === 'fraction' ? 1 / lennorm : lennorm), i); - } - } else if(ai === 'type' && ( - (newVal === 'pie') !== (oldVal === 'pie') || - (newVal === 'funnelarea') !== (oldVal === 'funnelarea') - )) { - var labelsTo = 'x'; - var valuesTo = 'y'; - if((newVal === 'bar' || oldVal === 'bar') && cont.orientation === 'h') { - labelsTo = 'y'; - valuesTo = 'x'; - } - Lib.swapAttrs(cont, ['?', '?src'], 'labels', labelsTo); - Lib.swapAttrs(cont, ['d?', '?0'], 'label', labelsTo); - Lib.swapAttrs(cont, ['?', '?src'], 'values', valuesTo); - - if(oldVal === 'pie' || oldVal === 'funnelarea') { - nestedProperty(cont, 'marker.color') - .set(nestedProperty(cont, 'marker.colors').get()); - - // super kludgy - but if all pies are gone we won't remove them otherwise - fullLayout._pielayer.selectAll('g.trace').remove(); - } else if(Registry.traceIs(cont, 'cartesian')) { - nestedProperty(cont, 'marker.colors') - .set(nestedProperty(cont, 'marker.color').get()); - } - } - - undoit[ai][i] = undefinedToNull(oldVal); - // set the new value - if val is an array, it's one el per trace - // first check for attributes that get more complex alterations - var swapAttrs = [ - 'swapxy', 'swapxyaxes', 'orientation', 'orientationaxes' - ]; - if(swapAttrs.indexOf(ai) !== -1) { - // setting an orientation: make sure it's changing - // before we swap everything else - if(ai === 'orientation') { - param.set(newVal); - // obnoxious that we need this level of coupling... but in order to - // properly handle setting orientation to `null` we need to mimic - // the logic inside Bars.supplyDefaults for default orientation - var defaultOrientation = (cont.x && !cont.y) ? 'h' : 'v'; - if((param.get() || defaultOrientation) === contFull.orientation) { - continue; - } - } else if(ai === 'orientationaxes') { - // orientationaxes has no value, - // it flips everything and the axes - - cont.orientation = - {v: 'h', h: 'v'}[contFull.orientation]; - } - helpers.swapXYData(cont); - flags.calc = flags.clearAxisTypes = true; - } else if(Plots.dataArrayContainers.indexOf(param.parts[0]) !== -1) { - // TODO: use manageArrays.applyContainerArrayChanges here too - helpers.manageArrayContainers(param, newVal, undoit); - flags.calc = true; - } else { - if(valObject) { - // must redo calcdata when restyling array values of arrayOk attributes - // ... but no need to this for regl-based traces - if(valObject.arrayOk && - !Registry.traceIs(contFull, 'regl') && - (Lib.isArrayOrTypedArray(newVal) || Lib.isArrayOrTypedArray(oldVal)) - ) { - flags.calc = true; - } else editTypes.update(flags, valObject); - } else { - /* - * if we couldn't find valObject, assume a full recalc. - * This can happen if you're changing type and making - * some other edits too, so the modules we're - * looking at don't have these attributes in them. - */ - flags.calc = true; - } - - // all the other ones, just modify that one attribute - param.set(newVal); - } - } - - // swap the data attributes of the relevant x and y axes? - if(['swapxyaxes', 'orientationaxes'].indexOf(ai) !== -1) { - Axes.swap(gd, traces); - } - - // swap hovermode if set to "compare x/y data" - if(ai === 'orientationaxes') { - var hovermode = nestedProperty(gd.layout, 'hovermode'); - if(hovermode.get() === 'x') { - hovermode.set('y'); - } else if(hovermode.get() === 'y') { - hovermode.set('x'); - } - } - - // Major enough changes deserve autoscale and - // non-reversed axes so people don't get confused - // - // Note: autobin (or its new analog bin clearing) is not included here - // since we're not pushing bins back to gd.data, so if we have bin - // info it was explicitly provided by the user. - if(['orientation', 'type'].indexOf(ai) !== -1) { - axlist = []; - for(i = 0; i < traces.length; i++) { - var trace = data[traces[i]]; - - if(Registry.traceIs(trace, 'cartesian')) { - addToAxlist(trace.xaxis || 'x'); - addToAxlist(trace.yaxis || 'y'); - } - } - - doextra(axlist.map(autorangeAttr), true, 0); - doextra(axlist.map(rangeAttr), [0, 1], 0); - } - } - - if(flags.calc || flags.plot) { - flags.fullReplot = true; - } - - return { - flags: flags, - undoit: undoit, - redoit: redoit, - traces: traces, - eventData: Lib.extendDeepNoArrays([], [eventData, traces]) - }; -} - -/** - * Converts deprecated attribute keys to - * the current API to ensure backwards compatibility. - * - * This is needed for the update mechanism to determine which - * subroutines to run based on the actual attribute - * definitions (that don't include the deprecated ones). - * - * E.g. Maps {'xaxis.title': 'A chart'} to {'xaxis.title.text': 'A chart'} - * and {titlefont: {...}} to {'title.font': {...}}. - * - * @param aobj - */ -function cleanDeprecatedAttributeKeys(aobj) { - var oldAxisTitleRegex = Lib.counterRegex('axis', '\.title', false, false); - var colorbarRegex = /colorbar\.title$/; - var keys = Object.keys(aobj); - var i, key, value; - - for(i = 0; i < keys.length; i++) { - key = keys[i]; - value = aobj[key]; - - if((key === 'title' || oldAxisTitleRegex.test(key) || colorbarRegex.test(key)) && - (typeof value === 'string' || typeof value === 'number')) { - replace(key, key.replace('title', 'title.text')); - } else if(key.indexOf('titlefont') > -1) { - replace(key, key.replace('titlefont', 'title.font')); - } else if(key.indexOf('titleposition') > -1) { - replace(key, key.replace('titleposition', 'title.position')); - } else if(key.indexOf('titleside') > -1) { - replace(key, key.replace('titleside', 'title.side')); - } else if(key.indexOf('titleoffset') > -1) { - replace(key, key.replace('titleoffset', 'title.offset')); - } - } - - function replace(oldAttrStr, newAttrStr) { - aobj[newAttrStr] = aobj[oldAttrStr]; - delete aobj[oldAttrStr]; - } -} - -/** - * relayout: update layout attributes of an existing plot - * - * Can be called two ways: - * - * Signature 1: - * @param {String | HTMLDivElement} gd - * the id or dom element of the graph container div - * @param {String} astr - * attribute string (like `'xaxis.range[0]'`) to update - * @param {*} val - * value to give this attribute - * - * Signature 2: - * @param {String | HTMLDivElement} gd - * (as in signature 1) - * @param {Object} aobj - * attribute object `{astr1: val1, astr2: val2 ...}` - * allows setting multiple attributes simultaneously - */ -function relayout(gd, astr, val) { - gd = Lib.getGraphDiv(gd); - helpers.clearPromiseQueue(gd); - - if(gd.framework && gd.framework.isPolar) { - return Promise.resolve(gd); - } - - var aobj = {}; - if(typeof astr === 'string') { - aobj[astr] = val; - } else if(Lib.isPlainObject(astr)) { - aobj = Lib.extendFlat({}, astr); - } else { - Lib.warn('Relayout fail.', astr, val); - return Promise.reject(); - } - - if(Object.keys(aobj).length) gd.changed = true; - - var specs = _relayout(gd, aobj); - var flags = specs.flags; - - // clear calcdata if required - if(flags.calc) gd.calcdata = undefined; - - // fill in redraw sequence - - // even if we don't have anything left in aobj, - // something may have happened within relayout that we - // need to wait for - var seq = [Plots.previousPromises]; - - if(flags.layoutReplot) { - seq.push(subroutines.layoutReplot); - } else if(Object.keys(aobj).length) { - axRangeSupplyDefaultsByPass(gd, flags, specs) || Plots.supplyDefaults(gd); - - if(flags.legend) seq.push(subroutines.doLegend); - if(flags.layoutstyle) seq.push(subroutines.layoutStyles); - if(flags.axrange) addAxRangeSequence(seq, specs.rangesAltered); - if(flags.ticks) seq.push(subroutines.doTicksRelayout); - if(flags.modebar) seq.push(subroutines.doModeBar); - if(flags.camera) seq.push(subroutines.doCamera); - if(flags.colorbars) seq.push(subroutines.doColorBars); - - seq.push(emitAfterPlot); - } - - seq.push(Plots.rehover, Plots.redrag); - - Queue.add(gd, - relayout, [gd, specs.undoit], - relayout, [gd, specs.redoit] - ); - - var plotDone = Lib.syncOrAsync(seq, gd); - if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd); - - return plotDone.then(function() { - gd.emit('plotly_relayout', specs.eventData); - return gd; - }); -} - -// Optimization mostly for large splom traces where -// Plots.supplyDefaults can take > 100ms -function axRangeSupplyDefaultsByPass(gd, flags, specs) { - var fullLayout = gd._fullLayout; - - if(!flags.axrange) return false; - - for(var k in flags) { - if(k !== 'axrange' && flags[k]) return false; - } - - for(var axId in specs.rangesAltered) { - var axName = Axes.id2name(axId); - var axIn = gd.layout[axName]; - var axOut = fullLayout[axName]; - axOut.autorange = axIn.autorange; - axOut.range = axIn.range.slice(); - axOut.cleanRange(); - - if(axOut._matchGroup) { - for(var axId2 in axOut._matchGroup) { - if(axId2 !== axId) { - var ax2 = fullLayout[Axes.id2name(axId2)]; - ax2.autorange = axOut.autorange; - ax2.range = axOut.range.slice(); - ax2._input.range = axOut.range.slice(); - } - } - } - } - - return true; -} - -function addAxRangeSequence(seq, rangesAltered) { - // N.B. leave as sequence of subroutines (for now) instead of - // subroutine of its own so that finalDraw always gets - // executed after drawData - var drawAxes = rangesAltered ? - function(gd) { - var axIds = []; - var skipTitle = true; - - for(var id in rangesAltered) { - var ax = Axes.getFromId(gd, id); - axIds.push(id); - - if(ax._matchGroup) { - for(var id2 in ax._matchGroup) { - if(!rangesAltered[id2]) { - axIds.push(id2); - } - } - } - - if(ax.automargin) skipTitle = false; - } - - return Axes.draw(gd, axIds, {skipTitle: skipTitle}); - } : - function(gd) { - return Axes.draw(gd, 'redraw'); - }; - - seq.push( - clearSelect, - subroutines.doAutoRangeAndConstraints, - drawAxes, - subroutines.drawData, - subroutines.finalDraw - ); -} - -var AX_RANGE_RE = /^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/; -var AX_AUTORANGE_RE = /^[xyz]axis[0-9]*\.autorange$/; -var AX_DOMAIN_RE = /^[xyz]axis[0-9]*\.domain(\[[0|1]\])?$/; - -function _relayout(gd, aobj) { - var layout = gd.layout; - var fullLayout = gd._fullLayout; - var guiEditFlag = fullLayout._guiEditing; - var layoutNP = makeNP(fullLayout._preGUI, guiEditFlag); - var keys = Object.keys(aobj); - var axes = Axes.list(gd); - var eventData = Lib.extendDeepAll({}, aobj); - var arrayEdits = {}; - - var arrayStr, i, j; - - cleanDeprecatedAttributeKeys(aobj); - keys = Object.keys(aobj); - - // look for 'allaxes', split out into all axes - // in case of 3D the axis are nested within a scene which is held in _id - for(i = 0; i < keys.length; i++) { - if(keys[i].indexOf('allaxes') === 0) { - for(j = 0; j < axes.length; j++) { - var scene = axes[j]._id.substr(1); - var axisAttr = (scene.indexOf('scene') !== -1) ? (scene + '.') : ''; - var newkey = keys[i].replace('allaxes', axisAttr + axes[j]._name); - - if(!aobj[newkey]) aobj[newkey] = aobj[keys[i]]; - } - - delete aobj[keys[i]]; - } - } - - // initialize flags - var flags = editTypes.layoutFlags(); - - // copies of the change (and previous values of anything affected) - // for the undo / redo queue - var redoit = {}; - var undoit = {}; - - // for attrs that interact (like scales & autoscales), save the - // old vals before making the change - // val=undefined will not set a value, just record what the value was. - // attr can be an array to set several at once (all to the same val) - function doextra(attr, val) { - if(Array.isArray(attr)) { - attr.forEach(function(a) { doextra(a, val); }); - return; - } - - // if we have another value for this attribute (explicitly or - // via a parent) do not override with this auto-generated extra - if(attr in aobj || helpers.hasParent(aobj, attr)) return; - - var p = layoutNP(layout, attr); - if(!(attr in undoit)) { - undoit[attr] = undefinedToNull(p.get()); - } - if(val !== undefined) p.set(val); - } - - // for constraint enforcement: keep track of all axes (as {id: name}) - // we're editing the (auto)range of, so we can tell the others constrained - // to scale with them that it's OK for them to shrink - var rangesAltered = {}; - var axId; - - function recordAlteredAxis(pleafPlus) { - var axId = Axes.name2id(pleafPlus.split('.')[0]); - rangesAltered[axId] = 1; - return axId; - } - - // alter gd.layout - for(var ai in aobj) { - if(helpers.hasParent(aobj, ai)) { - throw new Error('cannot set ' + ai + ' and a parent attribute simultaneously'); - } - - var p = layoutNP(layout, ai); - var vi = aobj[ai]; - var plen = p.parts.length; - // p.parts may end with an index integer if the property is an array - var pend = plen - 1; - while(pend > 0 && typeof p.parts[pend] !== 'string') pend--; - // last property in chain (leaf node) - var pleaf = p.parts[pend]; - // leaf plus immediate parent - var pleafPlus = p.parts[pend - 1] + '.' + pleaf; - // trunk nodes (everything except the leaf) - var ptrunk = p.parts.slice(0, pend).join('.'); - var parentIn = nestedProperty(gd.layout, ptrunk).get(); - var parentFull = nestedProperty(fullLayout, ptrunk).get(); - var vOld = p.get(); - - if(vi === undefined) continue; - - redoit[ai] = vi; - - // axis reverse is special - it is its own inverse - // op and has no flag. - undoit[ai] = (pleaf === 'reverse') ? vi : undefinedToNull(vOld); - - var valObject = PlotSchema.getLayoutValObject(fullLayout, p.parts); - - if(valObject && valObject.impliedEdits && vi !== null) { - for(var impliedKey in valObject.impliedEdits) { - doextra(Lib.relativeAttr(ai, impliedKey), valObject.impliedEdits[impliedKey]); - } - } - - // Setting width or height to null must reset the graph's width / height - // back to its initial value as computed during the first pass in Plots.plotAutoSize. - // - // To do so, we must manually set them back here using the _initialAutoSize cache. - // can't use impliedEdits for this because behavior depends on vi - if(['width', 'height'].indexOf(ai) !== -1) { - if(vi) { - doextra('autosize', null); - // currently we don't support autosize one dim only - so - // explicitly set the other one. Note that doextra will - // ignore this if the same relayout call also provides oppositeAttr - var oppositeAttr = ai === 'height' ? 'width' : 'height'; - doextra(oppositeAttr, fullLayout[oppositeAttr]); - } else { - fullLayout[ai] = gd._initialAutoSize[ai]; - } - } else if(ai === 'autosize') { - // depends on vi here too, so again can't use impliedEdits - doextra('width', vi ? null : fullLayout.width); - doextra('height', vi ? null : fullLayout.height); - } else if(pleafPlus.match(AX_RANGE_RE)) { - // check autorange vs range - - recordAlteredAxis(pleafPlus); - nestedProperty(fullLayout, ptrunk + '._inputRange').set(null); - } else if(pleafPlus.match(AX_AUTORANGE_RE)) { - recordAlteredAxis(pleafPlus); - nestedProperty(fullLayout, ptrunk + '._inputRange').set(null); - var axFull = nestedProperty(fullLayout, ptrunk).get(); - if(axFull._inputDomain) { - // if we're autoranging and this axis has a constrained domain, - // reset it so we don't get locked into a shrunken size - axFull._input.domain = axFull._inputDomain.slice(); - } - } else if(pleafPlus.match(AX_DOMAIN_RE)) { - nestedProperty(fullLayout, ptrunk + '._inputDomain').set(null); - } - - // toggling axis type between log and linear: we need to convert - // positions for components that are still using linearized values, - // not data values like newer components. - // previously we did this for log <-> not-log, but now only do it - // for log <-> linear - if(pleaf === 'type') { - var ax = parentIn; - var toLog = parentFull.type === 'linear' && vi === 'log'; - var fromLog = parentFull.type === 'log' && vi === 'linear'; - - if(toLog || fromLog) { - if(!ax || !ax.range) { - // 2D never gets here, but 3D does - // I don't think this is needed, but left here in case there - // are edge cases I'm not thinking of. - doextra(ptrunk + '.autorange', true); - } else if(!parentFull.autorange) { - // toggling log without autorange: need to also recalculate ranges - // because log axes use linearized values for range endpoints - var r0 = ax.range[0]; - var r1 = ax.range[1]; - if(toLog) { - // if both limits are negative, autorange - if(r0 <= 0 && r1 <= 0) { - doextra(ptrunk + '.autorange', true); - } - // if one is negative, set it 6 orders below the other. - if(r0 <= 0) r0 = r1 / 1e6; - else if(r1 <= 0) r1 = r0 / 1e6; - // now set the range values as appropriate - doextra(ptrunk + '.range[0]', Math.log(r0) / Math.LN10); - doextra(ptrunk + '.range[1]', Math.log(r1) / Math.LN10); - } else { - doextra(ptrunk + '.range[0]', Math.pow(10, r0)); - doextra(ptrunk + '.range[1]', Math.pow(10, r1)); - } - } else if(toLog) { - // just make sure the range is positive and in the right - // order, it'll get recalculated later - ax.range = (ax.range[1] > ax.range[0]) ? [1, 2] : [2, 1]; - } - - // clear polar view initial stash for radial range so that - // value get recomputed in correct units - if(Array.isArray(fullLayout._subplots.polar) && - fullLayout._subplots.polar.length && - fullLayout[p.parts[0]] && - p.parts[1] === 'radialaxis' - ) { - delete fullLayout[p.parts[0]]._subplot.viewInitial['radialaxis.range']; - } - - // Annotations and images also need to convert to/from linearized coords - // Shapes do not need this :) - Registry.getComponentMethod('annotations', 'convertCoords')(gd, parentFull, vi, doextra); - Registry.getComponentMethod('images', 'convertCoords')(gd, parentFull, vi, doextra); - } else { - // any other type changes: the range from the previous type - // will not make sense, so autorange it. - doextra(ptrunk + '.autorange', true); - doextra(ptrunk + '.range', null); - } - nestedProperty(fullLayout, ptrunk + '._inputRange').set(null); - } else if(pleaf.match(AX_NAME_PATTERN)) { - var fullProp = nestedProperty(fullLayout, ai).get(); - var newType = (vi || {}).type; - - // This can potentially cause strange behavior if the autotype is not - // numeric (linear, because we don't auto-log) but the previous type - // was log. That's a very strange edge case though - if(!newType || newType === '-') newType = 'linear'; - Registry.getComponentMethod('annotations', 'convertCoords')(gd, fullProp, newType, doextra); - Registry.getComponentMethod('images', 'convertCoords')(gd, fullProp, newType, doextra); - } - - // alter gd.layout - - // collect array component edits for execution all together - // so we can ensure consistent behavior adding/removing items - // and order-independence for add/remove/edit all together in - // one relayout call - var containerArrayMatch = manageArrays.containerArrayMatch(ai); - if(containerArrayMatch) { - arrayStr = containerArrayMatch.array; - i = containerArrayMatch.index; - var propStr = containerArrayMatch.property; - var updateValObject = valObject || {editType: 'calc'}; - - if(i !== '' && propStr === '') { - // special handling of undoit if we're adding or removing an element - // ie 'annotations[2]' which can be {...} (add) or null, - // does not work when replacing the entire array - if(manageArrays.isAddVal(vi)) { - undoit[ai] = null; - } else if(manageArrays.isRemoveVal(vi)) { - undoit[ai] = (nestedProperty(layout, arrayStr).get() || [])[i]; - } else { - Lib.warn('unrecognized full object value', aobj); - } - } - editTypes.update(flags, updateValObject); - - // prepare the edits object we'll send to applyContainerArrayChanges - if(!arrayEdits[arrayStr]) arrayEdits[arrayStr] = {}; - var objEdits = arrayEdits[arrayStr][i]; - if(!objEdits) objEdits = arrayEdits[arrayStr][i] = {}; - objEdits[propStr] = vi; - - delete aobj[ai]; - } else if(pleaf === 'reverse') { - // handle axis reversal explicitly, as there's no 'reverse' attribute - - if(parentIn.range) parentIn.range.reverse(); - else { - doextra(ptrunk + '.autorange', true); - parentIn.range = [1, 0]; - } - - if(parentFull.autorange) flags.calc = true; - else flags.plot = true; - } else { - if((fullLayout._has('scatter-like') && fullLayout._has('regl')) && - (ai === 'dragmode' && - (vi === 'lasso' || vi === 'select') && - !(vOld === 'lasso' || vOld === 'select')) - ) { - flags.plot = true; - } else if(fullLayout._has('gl2d')) { - flags.plot = true; - } else if(valObject) editTypes.update(flags, valObject); - else flags.calc = true; - - p.set(vi); - } - } - - // now we've collected component edits - execute them all together - for(arrayStr in arrayEdits) { - var finished = manageArrays.applyContainerArrayChanges(gd, - layoutNP(layout, arrayStr), arrayEdits[arrayStr], flags, layoutNP); - if(!finished) flags.plot = true; - } - - // figure out if we need to recalculate axis constraints - var constraints = fullLayout._axisConstraintGroups || []; - for(axId in rangesAltered) { - for(i = 0; i < constraints.length; i++) { - var group = constraints[i]; - if(group[axId]) { - // Always recalc if we're changing constrained ranges. - // Otherwise it's possible to violate the constraints by - // specifying arbitrary ranges for all axes in the group. - // this way some ranges may expand beyond what's specified, - // as they do at first draw, to satisfy the constraints. - flags.calc = true; - for(var groupAxId in group) { - if(!rangesAltered[groupAxId]) { - Axes.getFromId(gd, groupAxId)._constraintShrinkable = true; - } - } - } - } - } - - // If the autosize changed or height or width was explicitly specified, - // this triggers a redraw - // TODO: do we really need special aobj.height/width handling here? - // couldn't editType do this? - if(updateAutosize(gd) || aobj.height || aobj.width) flags.plot = true; - - if(flags.plot || flags.calc) { - flags.layoutReplot = true; - } - - // now all attribute mods are done, as are - // redo and undo so we can save them - - return { - flags: flags, - rangesAltered: rangesAltered, - undoit: undoit, - redoit: redoit, - eventData: eventData - }; -} - -/* - * updateAutosize: we made a change, does it change the autosize result? - * puts the new size into fullLayout - * returns true if either height or width changed - */ -function updateAutosize(gd) { - var fullLayout = gd._fullLayout; - var oldWidth = fullLayout.width; - var oldHeight = fullLayout.height; - - // calculate autosizing - if(gd.layout.autosize) Plots.plotAutoSize(gd, gd.layout, fullLayout); - - return (fullLayout.width !== oldWidth) || (fullLayout.height !== oldHeight); -} - -/** - * update: update trace and layout attributes of an existing plot - * - * @param {String | HTMLDivElement} gd - * the id or DOM element of the graph container div - * @param {Object} traceUpdate - * attribute object `{astr1: val1, astr2: val2 ...}` - * corresponding to updates in the plot's traces - * @param {Object} layoutUpdate - * attribute object `{astr1: val1, astr2: val2 ...}` - * corresponding to updates in the plot's layout - * @param {Number[] | Number} [traces] - * integer or array of integers for the traces to alter (all if omitted) - * - */ -function update(gd, traceUpdate, layoutUpdate, _traces) { - gd = Lib.getGraphDiv(gd); - helpers.clearPromiseQueue(gd); - - if(gd.framework && gd.framework.isPolar) { - return Promise.resolve(gd); - } - - if(!Lib.isPlainObject(traceUpdate)) traceUpdate = {}; - if(!Lib.isPlainObject(layoutUpdate)) layoutUpdate = {}; - - if(Object.keys(traceUpdate).length) gd.changed = true; - if(Object.keys(layoutUpdate).length) gd.changed = true; - - var traces = helpers.coerceTraceIndices(gd, _traces); - - var restyleSpecs = _restyle(gd, Lib.extendFlat({}, traceUpdate), traces); - var restyleFlags = restyleSpecs.flags; - - var relayoutSpecs = _relayout(gd, Lib.extendFlat({}, layoutUpdate)); - var relayoutFlags = relayoutSpecs.flags; - - // clear calcdata and/or axis types if required - if(restyleFlags.calc || relayoutFlags.calc) gd.calcdata = undefined; - if(restyleFlags.clearAxisTypes) helpers.clearAxisTypes(gd, traces, layoutUpdate); - - // fill in redraw sequence - var seq = []; - - if(relayoutFlags.layoutReplot) { - // N.B. works fine when both - // relayoutFlags.layoutReplot and restyleFlags.fullReplot are true - seq.push(subroutines.layoutReplot); - } else if(restyleFlags.fullReplot) { - seq.push(exports.plot); - } else { - seq.push(Plots.previousPromises); - axRangeSupplyDefaultsByPass(gd, relayoutFlags, relayoutSpecs) || Plots.supplyDefaults(gd); - - if(restyleFlags.style) seq.push(subroutines.doTraceStyle); - if(restyleFlags.colorbars || relayoutFlags.colorbars) seq.push(subroutines.doColorBars); - if(relayoutFlags.legend) seq.push(subroutines.doLegend); - if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles); - if(relayoutFlags.axrange) addAxRangeSequence(seq, relayoutSpecs.rangesAltered); - if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout); - if(relayoutFlags.modebar) seq.push(subroutines.doModeBar); - if(relayoutFlags.camera) seq.push(subroutines.doCamera); - - seq.push(emitAfterPlot); - } - - seq.push(Plots.rehover, Plots.redrag); - - Queue.add(gd, - update, [gd, restyleSpecs.undoit, relayoutSpecs.undoit, restyleSpecs.traces], - update, [gd, restyleSpecs.redoit, relayoutSpecs.redoit, restyleSpecs.traces] - ); - - var plotDone = Lib.syncOrAsync(seq, gd); - if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd); - - return plotDone.then(function() { - gd.emit('plotly_update', { - data: restyleSpecs.eventData, - layout: relayoutSpecs.eventData - }); - - return gd; - }); -} - -/* - * internal-use-only restyle/relayout/update variants that record the initial - * values in (fullLayout|fullTrace)._preGUI so changes can be persisted across - * Plotly.react data updates, dependent on uirevision attributes - */ -function guiEdit(func) { - return function wrappedEdit(gd) { - gd._fullLayout._guiEditing = true; - var p = func.apply(null, arguments); - gd._fullLayout._guiEditing = false; - return p; - }; -} - -// For connecting edited layout attributes to uirevision attrs -// If no `attr` we use `match[1] + '.uirevision'` -// Ordered by most common edits first, to minimize our search time -var layoutUIControlPatterns = [ - {pattern: /^hiddenlabels/, attr: 'legend.uirevision'}, - {pattern: /^((x|y)axis\d*)\.((auto)?range|title\.text)/}, - - // showspikes and modes include those nested inside scenes - {pattern: /axis\d*\.showspikes$/, attr: 'modebar.uirevision'}, - {pattern: /(hover|drag)mode$/, attr: 'modebar.uirevision'}, - - {pattern: /^(scene\d*)\.camera/}, - {pattern: /^(geo\d*)\.(projection|center)/}, - {pattern: /^(ternary\d*\.[abc]axis)\.(min|title\.text)$/}, - {pattern: /^(polar\d*\.radialaxis)\.((auto)?range|angle|title\.text)/}, - {pattern: /^(polar\d*\.angularaxis)\.rotation/}, - {pattern: /^(mapbox\d*)\.(center|zoom|bearing|pitch)/}, - - {pattern: /^legend\.(x|y)$/, attr: 'editrevision'}, - {pattern: /^(shapes|annotations)/, attr: 'editrevision'}, - {pattern: /^title\.text$/, attr: 'editrevision'} -]; - -// same for trace attributes: if `attr` is given it's in layout, -// or with no `attr` we use `trace.uirevision` -var traceUIControlPatterns = [ - {pattern: /^selectedpoints$/, attr: 'selectionrevision'}, - // "visible" includes trace.transforms[i].styles[j].value.visible - {pattern: /(^|value\.)visible$/, attr: 'legend.uirevision'}, - {pattern: /^dimensions\[\d+\]\.constraintrange/}, - {pattern: /^node\.(x|y|groups)/}, // for Sankey nodes - {pattern: /^level$/}, // for Sunburst traces - - // below this you must be in editable: true mode - // TODO: I still put name and title with `trace.uirevision` - // reasonable or should these be `editrevision`? - // Also applies to axis titles up in the layout section - - // "name" also includes transform.styles - {pattern: /(^|value\.)name$/}, - // including nested colorbar attributes (ie marker.colorbar) - {pattern: /colorbar\.title\.text$/}, - {pattern: /colorbar\.(x|y)$/, attr: 'editrevision'} -]; - -function findUIPattern(key, patternSpecs) { - for(var i = 0; i < patternSpecs.length; i++) { - var spec = patternSpecs[i]; - var match = key.match(spec.pattern); - if(match) { - return {head: match[1], attr: spec.attr}; - } - } -} - -// We're finding the new uirevision before supplyDefaults, so do the -// inheritance manually. Note that only `undefined` inherits - other -// falsy values are returned. -function getNewRev(revAttr, container) { - var newRev = nestedProperty(container, revAttr).get(); - if(newRev !== undefined) return newRev; - - var parts = revAttr.split('.'); - parts.pop(); - while(parts.length > 1) { - parts.pop(); - newRev = nestedProperty(container, parts.join('.') + '.uirevision').get(); - if(newRev !== undefined) return newRev; - } - - return container.uirevision; -} - -function getFullTraceIndexFromUid(uid, fullData) { - for(var i = 0; i < fullData.length; i++) { - if(fullData[i]._fullInput.uid === uid) return i; - } - return -1; -} - -function getTraceIndexFromUid(uid, data, tracei) { - for(var i = 0; i < data.length; i++) { - if(data[i].uid === uid) return i; - } - // fall back on trace order, but only if user didn't provide a uid for that trace - return (!data[tracei] || data[tracei].uid) ? -1 : tracei; -} - -function valsMatch(v1, v2) { - var v1IsObj = Lib.isPlainObject(v1); - var v1IsArray = Array.isArray(v1); - if(v1IsObj || v1IsArray) { - return ( - (v1IsObj && Lib.isPlainObject(v2)) || - (v1IsArray && Array.isArray(v2)) - ) && JSON.stringify(v1) === JSON.stringify(v2); - } - return v1 === v2; -} - -function applyUIRevisions(data, layout, oldFullData, oldFullLayout) { - var layoutPreGUI = oldFullLayout._preGUI; - var key, revAttr, oldRev, newRev, match, preGUIVal, newNP, newVal; - var bothInheritAutorange = []; - var newRangeAccepted = {}; - for(key in layoutPreGUI) { - match = findUIPattern(key, layoutUIControlPatterns); - if(match) { - revAttr = match.attr || (match.head + '.uirevision'); - oldRev = nestedProperty(oldFullLayout, revAttr).get(); - newRev = oldRev && getNewRev(revAttr, layout); - if(newRev && (newRev === oldRev)) { - preGUIVal = layoutPreGUI[key]; - if(preGUIVal === null) preGUIVal = undefined; - newNP = nestedProperty(layout, key); - newVal = newNP.get(); - if(valsMatch(newVal, preGUIVal)) { - if(newVal === undefined && key.substr(key.length - 9) === 'autorange') { - bothInheritAutorange.push(key.substr(0, key.length - 10)); - } - newNP.set(undefinedToNull(nestedProperty(oldFullLayout, key).get())); - continue; - } - } - } else { - Lib.warn('unrecognized GUI edit: ' + key); - } - // if we got this far, the new value was accepted as the new starting - // point (either because it changed or revision changed) - // so remove it from _preGUI for next time. - delete layoutPreGUI[key]; - - if(key.substr(key.length - 8, 6) === 'range[') { - newRangeAccepted[key.substr(0, key.length - 9)] = 1; - } - } - - // Special logic for `autorange`, since it interacts with `range`: - // If the new figure's matching `range` was kept, and `autorange` - // wasn't supplied explicitly in either the original or the new figure, - // we shouldn't alter that - but we may just have done that, so fix it. - for(var i = 0; i < bothInheritAutorange.length; i++) { - var axAttr = bothInheritAutorange[i]; - if(newRangeAccepted[axAttr]) { - var newAx = nestedProperty(layout, axAttr).get(); - if(newAx) delete newAx.autorange; - } - } - - // Now traces - try to match them up by uid (in case we added/deleted in - // the middle), then fall back on index. - var allTracePreGUI = oldFullLayout._tracePreGUI; - for(var uid in allTracePreGUI) { - var tracePreGUI = allTracePreGUI[uid]; - var newTrace = null; - var fullInput; - for(key in tracePreGUI) { - // wait until we know we have preGUI values to look for traces - // but if we don't find both, stop looking at this uid - if(!newTrace) { - var fulli = getFullTraceIndexFromUid(uid, oldFullData); - if(fulli < 0) { - // Somehow we didn't even have this trace in oldFullData... - // I guess this could happen with `deleteTraces` or something - delete allTracePreGUI[uid]; - break; - } - var fullTrace = oldFullData[fulli]; - fullInput = fullTrace._fullInput; - - var newTracei = getTraceIndexFromUid(uid, data, fullInput.index); - if(newTracei < 0) { - // No match in new data - delete allTracePreGUI[uid]; - break; - } - newTrace = data[newTracei]; - } - - match = findUIPattern(key, traceUIControlPatterns); - if(match) { - if(match.attr) { - oldRev = nestedProperty(oldFullLayout, match.attr).get(); - newRev = oldRev && getNewRev(match.attr, layout); - } else { - oldRev = fullInput.uirevision; - // inheritance for trace.uirevision is simple, just layout.uirevision - newRev = newTrace.uirevision; - if(newRev === undefined) newRev = layout.uirevision; - } - - if(newRev && newRev === oldRev) { - preGUIVal = tracePreGUI[key]; - if(preGUIVal === null) preGUIVal = undefined; - newNP = nestedProperty(newTrace, key); - newVal = newNP.get(); - if(valsMatch(newVal, preGUIVal)) { - newNP.set(undefinedToNull(nestedProperty(fullInput, key).get())); - continue; - } - } - } else { - Lib.warn('unrecognized GUI edit: ' + key + ' in trace uid ' + uid); - } - delete tracePreGUI[key]; - } - } -} - -/** - * Plotly.react: - * A plot/update method that takes the full plot state (same API as plot/newPlot) - * and diffs to determine the minimal update pathway - * - * @param {string id or DOM element} gd - * the id or DOM element of the graph container div - * @param {array of objects} data - * array of traces, containing the data and display information for each trace - * @param {object} layout - * object describing the overall display of the plot, - * all the stuff that doesn't pertain to any individual trace - * @param {object} config - * configuration options (see ./plot_config.js for more info) - * - * OR - * - * @param {string id or DOM element} gd - * the id or DOM element of the graph container div - * @param {object} figure - * object containing `data`, `layout`, `config`, and `frames` members - * - */ -function react(gd, data, layout, config) { - var frames, plotDone; - - function addFrames() { return exports.addFrames(gd, frames); } - - gd = Lib.getGraphDiv(gd); - - var oldFullData = gd._fullData; - var oldFullLayout = gd._fullLayout; - - // you can use this as the initial draw as well as to update - if(!Lib.isPlotDiv(gd) || !oldFullData || !oldFullLayout) { - plotDone = exports.newPlot(gd, data, layout, config); - } else { - if(Lib.isPlainObject(data)) { - var obj = data; - data = obj.data; - layout = obj.layout; - config = obj.config; - frames = obj.frames; - } - - var configChanged = false; - // assume that if there's a config at all, we're reacting to it too, - // and completely replace the previous config - if(config) { - var oldConfig = Lib.extendDeep({}, gd._context); - gd._context = undefined; - setPlotContext(gd, config); - configChanged = diffConfig(oldConfig, gd._context); - } - - gd.data = data || []; - helpers.cleanData(gd.data); - gd.layout = layout || {}; - helpers.cleanLayout(gd.layout); - - applyUIRevisions(gd.data, gd.layout, oldFullData, oldFullLayout); - - // "true" skips updating calcdata and remapping arrays from calcTransforms, - // which supplyDefaults usually does at the end, but we may need to NOT do - // if the diff (which we haven't determined yet) says we'll recalc - Plots.supplyDefaults(gd, {skipUpdateCalc: true}); - - var newFullData = gd._fullData; - var newFullLayout = gd._fullLayout; - var immutable = newFullLayout.datarevision === undefined; - var transition = newFullLayout.transition; - - var relayoutFlags = diffLayout(gd, oldFullLayout, newFullLayout, immutable, transition); - var newDataRevision = relayoutFlags.newDataRevision; - var restyleFlags = diffData(gd, oldFullData, newFullData, immutable, transition, newDataRevision); - - // TODO: how to translate this part of relayout to Plotly.react? - // // Setting width or height to null must reset the graph's width / height - // // back to its initial value as computed during the first pass in Plots.plotAutoSize. - // // - // // To do so, we must manually set them back here using the _initialAutoSize cache. - // if(['width', 'height'].indexOf(ai) !== -1 && vi === null) { - // fullLayout[ai] = gd._initialAutoSize[ai]; - // } - - if(updateAutosize(gd)) relayoutFlags.layoutReplot = true; - - // clear calcdata if required - if(restyleFlags.calc || relayoutFlags.calc) gd.calcdata = undefined; - // otherwise do the calcdata updates and calcTransform array remaps that we skipped earlier - else Plots.supplyDefaultsUpdateCalc(gd.calcdata, newFullData); - - // Note: what restyle/relayout use impliedEdits and clearAxisTypes for - // must be handled by the user when using Plotly.react. - - // fill in redraw sequence - var seq = []; - - if(frames) { - gd._transitionData = {}; - Plots.createTransitionData(gd); - seq.push(addFrames); - } - - // Transition pathway, - // only used when 'transition' is set by user and - // when at least one animatable attribute has changed, - // N.B. config changed aren't animatable - if(newFullLayout.transition && !configChanged && (restyleFlags.anim || relayoutFlags.anim)) { - Plots.doCalcdata(gd); - subroutines.doAutoRangeAndConstraints(gd); - - seq.push(function() { - return Plots.transitionFromReact(gd, restyleFlags, relayoutFlags, oldFullLayout); - }); - } else if(restyleFlags.fullReplot || relayoutFlags.layoutReplot || configChanged) { - gd._fullLayout._skipDefaults = true; - seq.push(exports.plot); - } else { - for(var componentType in relayoutFlags.arrays) { - var indices = relayoutFlags.arrays[componentType]; - if(indices.length) { - var drawOne = Registry.getComponentMethod(componentType, 'drawOne'); - if(drawOne !== Lib.noop) { - for(var i = 0; i < indices.length; i++) { - drawOne(gd, indices[i]); - } - } else { - var draw = Registry.getComponentMethod(componentType, 'draw'); - if(draw === Lib.noop) { - throw new Error('cannot draw components: ' + componentType); - } - draw(gd); - } - } - } - - seq.push(Plots.previousPromises); - if(restyleFlags.style) seq.push(subroutines.doTraceStyle); - if(restyleFlags.colorbars || relayoutFlags.colorbars) seq.push(subroutines.doColorBars); - if(relayoutFlags.legend) seq.push(subroutines.doLegend); - if(relayoutFlags.layoutstyle) seq.push(subroutines.layoutStyles); - if(relayoutFlags.axrange) addAxRangeSequence(seq); - if(relayoutFlags.ticks) seq.push(subroutines.doTicksRelayout); - if(relayoutFlags.modebar) seq.push(subroutines.doModeBar); - if(relayoutFlags.camera) seq.push(subroutines.doCamera); - seq.push(emitAfterPlot); - } - - seq.push(Plots.rehover, Plots.redrag); - - plotDone = Lib.syncOrAsync(seq, gd); - if(!plotDone || !plotDone.then) plotDone = Promise.resolve(gd); - } - - return plotDone.then(function() { - gd.emit('plotly_react', { - data: data, - layout: layout - }); - - return gd; - }); -} - -function diffData(gd, oldFullData, newFullData, immutable, transition, newDataRevision) { - var sameTraceLength = oldFullData.length === newFullData.length; - - if(!transition && !sameTraceLength) { - return { - fullReplot: true, - calc: true - }; - } - - var flags = editTypes.traceFlags(); - flags.arrays = {}; - flags.nChanges = 0; - flags.nChangesAnim = 0; - - var i, trace; - - function getTraceValObject(parts) { - var out = PlotSchema.getTraceValObject(trace, parts); - if(!trace._module.animatable && out.anim) { - out.anim = false; - } - return out; - } - - var diffOpts = { - getValObject: getTraceValObject, - flags: flags, - immutable: immutable, - transition: transition, - newDataRevision: newDataRevision, - gd: gd - }; - - var seenUIDs = {}; - - for(i = 0; i < oldFullData.length; i++) { - if(newFullData[i]) { - trace = newFullData[i]._fullInput; - if(Plots.hasMakesDataTransform(trace)) trace = newFullData[i]; - if(seenUIDs[trace.uid]) continue; - seenUIDs[trace.uid] = 1; - - getDiffFlags(oldFullData[i]._fullInput, trace, [], diffOpts); - } - } - - if(flags.calc || flags.plot) { - flags.fullReplot = true; - } - - if(transition && flags.nChanges && flags.nChangesAnim) { - flags.anim = (flags.nChanges === flags.nChangesAnim) && sameTraceLength ? 'all' : 'some'; - } - - return flags; -} - -function diffLayout(gd, oldFullLayout, newFullLayout, immutable, transition) { - var flags = editTypes.layoutFlags(); - flags.arrays = {}; - flags.rangesAltered = {}; - flags.nChanges = 0; - flags.nChangesAnim = 0; - - function getLayoutValObject(parts) { - return PlotSchema.getLayoutValObject(newFullLayout, parts); - } - - var diffOpts = { - getValObject: getLayoutValObject, - flags: flags, - immutable: immutable, - transition: transition, - gd: gd - }; - - getDiffFlags(oldFullLayout, newFullLayout, [], diffOpts); - - if(flags.plot || flags.calc) { - flags.layoutReplot = true; - } - - if(transition && flags.nChanges && flags.nChangesAnim) { - flags.anim = flags.nChanges === flags.nChangesAnim ? 'all' : 'some'; - } - - return flags; -} - -function getDiffFlags(oldContainer, newContainer, outerparts, opts) { - var valObject, key, astr; - - var getValObject = opts.getValObject; - var flags = opts.flags; - var immutable = opts.immutable; - var inArray = opts.inArray; - var arrayIndex = opts.arrayIndex; - - function changed() { - var editType = valObject.editType; - if(inArray && editType.indexOf('arraydraw') !== -1) { - Lib.pushUnique(flags.arrays[inArray], arrayIndex); - return; - } - editTypes.update(flags, valObject); - - if(editType !== 'none') { - flags.nChanges++; - } - - // track animatable changes - if(opts.transition && valObject.anim) { - flags.nChangesAnim++; - } - - // track cartesian axes with altered ranges - if(AX_RANGE_RE.test(astr) || AX_AUTORANGE_RE.test(astr)) { - flags.rangesAltered[outerparts[0]] = 1; - } - - // clear _inputDomain on cartesian axes with altered domains - if(AX_DOMAIN_RE.test(astr)) { - nestedProperty(newContainer, '_inputDomain').set(null); - } - - // track datarevision changes - if(key === 'datarevision') { - flags.newDataRevision = 1; - } - } - - function valObjectCanBeDataArray(valObject) { - return valObject.valType === 'data_array' || valObject.arrayOk; - } - - for(key in oldContainer) { - // short-circuit based on previous calls or previous keys that already maximized the pathway - if(flags.calc && !opts.transition) return; - - var oldVal = oldContainer[key]; - var newVal = newContainer[key]; - var parts = outerparts.concat(key); - astr = parts.join('.'); - - if(key.charAt(0) === '_' || typeof oldVal === 'function' || oldVal === newVal) continue; - - // FIXME: ax.tick0 and dtick get filled in during plotting (except for geo subplots), - // and unlike other auto values they don't make it back into the input, - // so newContainer won't have them. - if((key === 'tick0' || key === 'dtick') && outerparts[0] !== 'geo') { - var tickMode = newContainer.tickmode; - if(tickMode === 'auto' || tickMode === 'array' || !tickMode) continue; - } - // FIXME: Similarly for axis ranges for 3D - // contourcarpet doesn't HAVE zmin/zmax, they're just auto-added. It needs them. - if(key === 'range' && newContainer.autorange) continue; - if((key === 'zmin' || key === 'zmax') && newContainer.type === 'contourcarpet') continue; - - valObject = getValObject(parts); - - // in case type changed, we may not even *have* a valObject. - if(!valObject) continue; - - if(valObject._compareAsJSON && JSON.stringify(oldVal) === JSON.stringify(newVal)) continue; - - var valType = valObject.valType; - var i; - - var canBeDataArray = valObjectCanBeDataArray(valObject); - var wasArray = Array.isArray(oldVal); - var nowArray = Array.isArray(newVal); - - // hack for traces that modify the data in supplyDefaults, like - // converting 1D to 2D arrays, which will always create new objects - if(wasArray && nowArray) { - var inputKey = '_input_' + key; - var oldValIn = oldContainer[inputKey]; - var newValIn = newContainer[inputKey]; - if(Array.isArray(oldValIn) && oldValIn === newValIn) continue; - } - - if(newVal === undefined) { - if(canBeDataArray && wasArray) flags.calc = true; - else changed(); - } else if(valObject._isLinkedToArray) { - var arrayEditIndices = []; - var extraIndices = false; - if(!inArray) flags.arrays[key] = arrayEditIndices; - - var minLen = Math.min(oldVal.length, newVal.length); - var maxLen = Math.max(oldVal.length, newVal.length); - if(minLen !== maxLen) { - if(valObject.editType === 'arraydraw') { - extraIndices = true; - } else { - changed(); - continue; - } - } - - for(i = 0; i < minLen; i++) { - getDiffFlags(oldVal[i], newVal[i], parts.concat(i), - // add array indices, but not if we're already in an array - Lib.extendFlat({inArray: key, arrayIndex: i}, opts)); - } - - // put this at the end so that we know our collected array indices are sorted - // but the check for length changes happens up front so we can short-circuit - // diffing if appropriate - if(extraIndices) { - for(i = minLen; i < maxLen; i++) { - arrayEditIndices.push(i); - } - } - } else if(!valType && Lib.isPlainObject(oldVal)) { - getDiffFlags(oldVal, newVal, parts, opts); - } else if(canBeDataArray) { - if(wasArray && nowArray) { - // don't try to diff two data arrays. If immutable we know the data changed, - // if not, assume it didn't and let `layout.datarevision` tell us if it did - if(immutable) { - flags.calc = true; - } - - // look for animatable attributes when the data changed - if(immutable || opts.newDataRevision) { - changed(); - } - } else if(wasArray !== nowArray) { - flags.calc = true; - } else changed(); - } else if(wasArray && nowArray) { - // info array, colorscale, 'any' - these are short, just stringify. - // I don't *think* that covers up any real differences post-validation, does it? - // otherwise we need to dive in 1 (info_array) or 2 (colorscale) levels and compare - // all elements. - if(oldVal.length !== newVal.length || String(oldVal) !== String(newVal)) { - changed(); - } - } else { - changed(); - } - } - - for(key in newContainer) { - if(!(key in oldContainer || key.charAt(0) === '_' || typeof newContainer[key] === 'function')) { - valObject = getValObject(outerparts.concat(key)); - - if(valObjectCanBeDataArray(valObject) && Array.isArray(newContainer[key])) { - flags.calc = true; - return; - } else changed(); - } - } -} - -/* - * simple diff for config - for now, just treat all changes as equivalent - */ -function diffConfig(oldConfig, newConfig) { - var key; - - for(key in oldConfig) { - if(key.charAt(0) === '_') continue; - var oldVal = oldConfig[key]; - var newVal = newConfig[key]; - if(oldVal !== newVal) { - if(Lib.isPlainObject(oldVal) && Lib.isPlainObject(newVal)) { - if(diffConfig(oldVal, newVal)) { - return true; - } - } else if(Array.isArray(oldVal) && Array.isArray(newVal)) { - if(oldVal.length !== newVal.length) { - return true; - } - for(var i = 0; i < oldVal.length; i++) { - if(oldVal[i] !== newVal[i]) { - if(Lib.isPlainObject(oldVal[i]) && Lib.isPlainObject(newVal[i])) { - if(diffConfig(oldVal[i], newVal[i])) { - return true; - } - } else { - return true; - } - } - } - } else { - return true; - } - } - } -} - -/** - * Animate to a frame, sequence of frame, frame group, or frame definition - * - * @param {string id or DOM element} gd - * the id or DOM element of the graph container div - * - * @param {string or object or array of strings or array of objects} frameOrGroupNameOrFrameList - * a single frame, array of frames, or group to which to animate. The intent is - * inferred by the type of the input. Valid inputs are: - * - * - string, e.g. 'groupname': animate all frames of a given `group` in the order - * in which they are defined via `Plotly.addFrames`. - * - * - array of strings, e.g. ['frame1', frame2']: a list of frames by name to which - * to animate in sequence - * - * - object: {data: ...}: a frame definition to which to animate. The frame is not - * and does not need to be added via `Plotly.addFrames`. It may contain any of - * the properties of a frame, including `data`, `layout`, and `traces`. The - * frame is used as provided and does not use the `baseframe` property. - * - * - array of objects, e.g. [{data: ...}, {data: ...}]: a list of frame objects, - * each following the same rules as a single `object`. - * - * @param {object} animationOpts - * configuration for the animation - */ -function animate(gd, frameOrGroupNameOrFrameList, animationOpts) { - gd = Lib.getGraphDiv(gd); - - if(!Lib.isPlotDiv(gd)) { - throw new Error( - 'This element is not a Plotly plot: ' + gd + '. It\'s likely that you\'ve failed ' + - 'to create a plot before animating it. For more details, see ' + - 'https://plot.ly/javascript/animations/' - ); - } - - var trans = gd._transitionData; - - // This is the queue of frames that will be animated as soon as possible. They - // are popped immediately upon the *start* of a transition: - if(!trans._frameQueue) { - trans._frameQueue = []; - } - - animationOpts = Plots.supplyAnimationDefaults(animationOpts); - var transitionOpts = animationOpts.transition; - var frameOpts = animationOpts.frame; - - // Since frames are popped immediately, an empty queue only means all frames have - // *started* to transition, not that the animation is complete. To solve that, - // track a separate counter that increments at the same time as frames are added - // to the queue, but decrements only when the transition is complete. - if(trans._frameWaitingCnt === undefined) { - trans._frameWaitingCnt = 0; - } - - function getTransitionOpts(i) { - if(Array.isArray(transitionOpts)) { - if(i >= transitionOpts.length) { - return transitionOpts[0]; - } else { - return transitionOpts[i]; - } - } else { - return transitionOpts; - } - } - - function getFrameOpts(i) { - if(Array.isArray(frameOpts)) { - if(i >= frameOpts.length) { - return frameOpts[0]; - } else { - return frameOpts[i]; - } - } else { - return frameOpts; - } - } - - // Execute a callback after the wrapper function has been called n times. - // This is used to defer the resolution until a transition has resovled *and* - // the frame has completed. If it's not done this way, then we get a race - // condition in which the animation might resolve before a transition is complete - // or vice versa. - function callbackOnNthTime(cb, n) { - var cnt = 0; - return function() { - if(cb && ++cnt === n) { - return cb(); - } - }; - } - - return new Promise(function(resolve, reject) { - function discardExistingFrames() { - if(trans._frameQueue.length === 0) { - return; - } - - while(trans._frameQueue.length) { - var next = trans._frameQueue.pop(); - if(next.onInterrupt) { - next.onInterrupt(); - } - } - - gd.emit('plotly_animationinterrupted', []); - } - - function queueFrames(frameList) { - if(frameList.length === 0) return; - - for(var i = 0; i < frameList.length; i++) { - var computedFrame; - - if(frameList[i].type === 'byname') { - // If it's a named frame, compute it: - computedFrame = Plots.computeFrame(gd, frameList[i].name); - } else { - // Otherwise we must have been given a simple object, so treat - // the input itself as the computed frame. - computedFrame = frameList[i].data; - } - - var frameOpts = getFrameOpts(i); - var transitionOpts = getTransitionOpts(i); - - // It doesn't make much sense for the transition duration to be greater than - // the frame duration, so limit it: - transitionOpts.duration = Math.min(transitionOpts.duration, frameOpts.duration); - - var nextFrame = { - frame: computedFrame, - name: frameList[i].name, - frameOpts: frameOpts, - transitionOpts: transitionOpts, - }; - if(i === frameList.length - 1) { - // The last frame in this .animate call stores the promise resolve - // and reject callbacks. This is how we ensure that the animation - // loop (which may exist as a result of a *different* .animate call) - // still resolves or rejecdts this .animate call's promise. once it's - // complete. - nextFrame.onComplete = callbackOnNthTime(resolve, 2); - nextFrame.onInterrupt = reject; - } - - trans._frameQueue.push(nextFrame); - } - - // Set it as never having transitioned to a frame. This will cause the animation - // loop to immediately transition to the next frame (which, for immediate mode, - // is the first frame in the list since all others would have been discarded - // below) - if(animationOpts.mode === 'immediate') { - trans._lastFrameAt = -Infinity; - } - - // Only it's not already running, start a RAF loop. This could be avoided in the - // case that there's only one frame, but it significantly complicated the logic - // and only sped things up by about 5% or so for a lorenz attractor simulation. - // It would be a fine thing to implement, but the benefit of that optimization - // doesn't seem worth the extra complexity. - if(!trans._animationRaf) { - beginAnimationLoop(); - } - } - - function stopAnimationLoop() { - gd.emit('plotly_animated'); - - // Be sure to unset also since it's how we know whether a loop is already running: - window.cancelAnimationFrame(trans._animationRaf); - trans._animationRaf = null; - } - - function nextFrame() { - if(trans._currentFrame && trans._currentFrame.onComplete) { - // Execute the callback and unset it to ensure it doesn't - // accidentally get called twice - trans._currentFrame.onComplete(); - } - - var newFrame = trans._currentFrame = trans._frameQueue.shift(); - - if(newFrame) { - // Since it's sometimes necessary to do deep digging into frame data, - // we'll consider it not 100% impossible for nulls or numbers to sneak through, - // so check when casting the name, just to be absolutely certain: - var stringName = newFrame.name ? newFrame.name.toString() : null; - gd._fullLayout._currentFrame = stringName; - - trans._lastFrameAt = Date.now(); - trans._timeToNext = newFrame.frameOpts.duration; - - // This is simply called and it's left to .transition to decide how to manage - // interrupting current transitions. That means we don't need to worry about - // how it resolves or what happens after this: - Plots.transition(gd, - newFrame.frame.data, - newFrame.frame.layout, - helpers.coerceTraceIndices(gd, newFrame.frame.traces), - newFrame.frameOpts, - newFrame.transitionOpts - ).then(function() { - if(newFrame.onComplete) { - newFrame.onComplete(); - } - }); - - gd.emit('plotly_animatingframe', { - name: stringName, - frame: newFrame.frame, - animation: { - frame: newFrame.frameOpts, - transition: newFrame.transitionOpts, - } - }); - } else { - // If there are no more frames, then stop the RAF loop: - stopAnimationLoop(); - } - } - - function beginAnimationLoop() { - gd.emit('plotly_animating'); - - // If no timer is running, then set last frame = long ago so that the next - // frame is immediately transitioned: - trans._lastFrameAt = -Infinity; - trans._timeToNext = 0; - trans._runningTransitions = 0; - trans._currentFrame = null; - - var doFrame = function() { - // This *must* be requested before nextFrame since nextFrame may decide - // to cancel it if there's nothing more to animated: - trans._animationRaf = window.requestAnimationFrame(doFrame); - - // Check if we're ready for a new frame: - if(Date.now() - trans._lastFrameAt > trans._timeToNext) { - nextFrame(); - } - }; - - doFrame(); - } - - // This is an animate-local counter that helps match up option input list - // items with the particular frame. - var configCounter = 0; - function setTransitionConfig(frame) { - if(Array.isArray(transitionOpts)) { - if(configCounter >= transitionOpts.length) { - frame.transitionOpts = transitionOpts[configCounter]; - } else { - frame.transitionOpts = transitionOpts[0]; - } - } else { - frame.transitionOpts = transitionOpts; - } - configCounter++; - return frame; - } - - // Disambiguate what's sort of frames have been received - var i, frame; - var frameList = []; - var allFrames = frameOrGroupNameOrFrameList === undefined || frameOrGroupNameOrFrameList === null; - var isFrameArray = Array.isArray(frameOrGroupNameOrFrameList); - var isSingleFrame = !allFrames && !isFrameArray && Lib.isPlainObject(frameOrGroupNameOrFrameList); - - if(isSingleFrame) { - // In this case, a simple object has been passed to animate. - frameList.push({ - type: 'object', - data: setTransitionConfig(Lib.extendFlat({}, frameOrGroupNameOrFrameList)) - }); - } else if(allFrames || ['string', 'number'].indexOf(typeof frameOrGroupNameOrFrameList) !== -1) { - // In this case, null or undefined has been passed so that we want to - // animate *all* currently defined frames - for(i = 0; i < trans._frames.length; i++) { - frame = trans._frames[i]; - - if(!frame) continue; - - if(allFrames || String(frame.group) === String(frameOrGroupNameOrFrameList)) { - frameList.push({ - type: 'byname', - name: String(frame.name), - data: setTransitionConfig({name: frame.name}) - }); - } - } - } else if(isFrameArray) { - for(i = 0; i < frameOrGroupNameOrFrameList.length; i++) { - var frameOrName = frameOrGroupNameOrFrameList[i]; - if(['number', 'string'].indexOf(typeof frameOrName) !== -1) { - frameOrName = String(frameOrName); - // In this case, there's an array and this frame is a string name: - frameList.push({ - type: 'byname', - name: frameOrName, - data: setTransitionConfig({name: frameOrName}) - }); - } else if(Lib.isPlainObject(frameOrName)) { - frameList.push({ - type: 'object', - data: setTransitionConfig(Lib.extendFlat({}, frameOrName)) - }); - } - } - } - - // Verify that all of these frames actually exist; return and reject if not: - for(i = 0; i < frameList.length; i++) { - frame = frameList[i]; - if(frame.type === 'byname' && !trans._frameHash[frame.data.name]) { - Lib.warn('animate failure: frame not found: "' + frame.data.name + '"'); - reject(); - return; - } - } - - // If the mode is either next or immediate, then all currently queued frames must - // be dumped and the corresponding .animate promises rejected. - if(['next', 'immediate'].indexOf(animationOpts.mode) !== -1) { - discardExistingFrames(); - } - - if(animationOpts.direction === 'reverse') { - frameList.reverse(); - } - - var currentFrame = gd._fullLayout._currentFrame; - if(currentFrame && animationOpts.fromcurrent) { - var idx = -1; - for(i = 0; i < frameList.length; i++) { - frame = frameList[i]; - if(frame.type === 'byname' && frame.name === currentFrame) { - idx = i; - break; - } - } - - if(idx > 0 && idx < frameList.length - 1) { - var filteredFrameList = []; - for(i = 0; i < frameList.length; i++) { - frame = frameList[i]; - if(frameList[i].type !== 'byname' || i > idx) { - filteredFrameList.push(frame); - } - } - frameList = filteredFrameList; - } - } - - if(frameList.length > 0) { - queueFrames(frameList); - } else { - // This is the case where there were simply no frames. It's a little strange - // since there's not much to do: - gd.emit('plotly_animated'); - resolve(); - } - }); -} - -/** - * Register new frames - * - * @param {string id or DOM element} gd - * the id or DOM element of the graph container div - * - * @param {array of objects} frameList - * list of frame definitions, in which each object includes any of: - * - name: {string} name of frame to add - * - data: {array of objects} trace data - * - layout {object} layout definition - * - traces {array} trace indices - * - baseframe {string} name of frame from which this frame gets defaults - * - * @param {array of integers} indices - * an array of integer indices matching the respective frames in `frameList`. If not - * provided, an index will be provided in serial order. If already used, the frame - * will be overwritten. - */ -function addFrames(gd, frameList, indices) { - gd = Lib.getGraphDiv(gd); - - if(frameList === null || frameList === undefined) { - return Promise.resolve(); - } - - if(!Lib.isPlotDiv(gd)) { - throw new Error( - 'This element is not a Plotly plot: ' + gd + '. It\'s likely that you\'ve failed ' + - 'to create a plot before adding frames. For more details, see ' + - 'https://plot.ly/javascript/animations/' - ); - } - - var i, frame, j, idx; - var _frames = gd._transitionData._frames; - var _frameHash = gd._transitionData._frameHash; - - - if(!Array.isArray(frameList)) { - throw new Error('addFrames failure: frameList must be an Array of frame definitions' + frameList); - } - - // Create a sorted list of insertions since we run into lots of problems if these - // aren't in ascending order of index: - // - // Strictly for sorting. Make sure this is guaranteed to never collide with any - // already-exisisting indices: - var bigIndex = _frames.length + frameList.length * 2; - - var insertions = []; - var _frameHashLocal = {}; - for(i = frameList.length - 1; i >= 0; i--) { - if(!Lib.isPlainObject(frameList[i])) continue; - - // The entire logic for checking for this type of name collision can be removed once we migrate to ES6 and - // use a Map instead of an Object instance, as Map keys aren't converted to strings. - var lookupName = frameList[i].name; - var name = (_frameHash[lookupName] || _frameHashLocal[lookupName] || {}).name; - var newName = frameList[i].name; - var collisionPresent = _frameHash[name] || _frameHashLocal[name]; - - if(name && newName && typeof newName === 'number' && collisionPresent && numericNameWarningCount < numericNameWarningCountLimit) { - numericNameWarningCount++; - - Lib.warn('addFrames: overwriting frame "' + (_frameHash[name] || _frameHashLocal[name]).name + - '" with a frame whose name of type "number" also equates to "' + - name + '". This is valid but may potentially lead to unexpected ' + - 'behavior since all plotly.js frame names are stored internally ' + - 'as strings.'); - - if(numericNameWarningCount === numericNameWarningCountLimit) { - Lib.warn('addFrames: This API call has yielded too many of these warnings. ' + - 'For the rest of this call, further warnings about numeric frame ' + - 'names will be suppressed.'); - } - } - - _frameHashLocal[lookupName] = {name: lookupName}; - - insertions.push({ - frame: Plots.supplyFrameDefaults(frameList[i]), - index: (indices && indices[i] !== undefined && indices[i] !== null) ? indices[i] : bigIndex + i - }); - } - - // Sort this, taking note that undefined insertions end up at the end: - insertions.sort(function(a, b) { - if(a.index > b.index) return -1; - if(a.index < b.index) return 1; - return 0; - }); - - var ops = []; - var revops = []; - var frameCount = _frames.length; - - for(i = insertions.length - 1; i >= 0; i--) { - frame = insertions[i].frame; - - if(typeof frame.name === 'number') { - Lib.warn('Warning: addFrames accepts frames with numeric names, but the numbers are' + - 'implicitly cast to strings'); - } - - if(!frame.name) { - // Repeatedly assign a default name, incrementing the counter each time until - // we get a name that's not in the hashed lookup table: - while(_frameHash[(frame.name = 'frame ' + gd._transitionData._counter++)]); - } - - if(_frameHash[frame.name]) { - // If frame is present, overwrite its definition: - for(j = 0; j < _frames.length; j++) { - if((_frames[j] || {}).name === frame.name) break; - } - ops.push({type: 'replace', index: j, value: frame}); - revops.unshift({type: 'replace', index: j, value: _frames[j]}); - } else { - // Otherwise insert it at the end of the list: - idx = Math.max(0, Math.min(insertions[i].index, frameCount)); - - ops.push({type: 'insert', index: idx, value: frame}); - revops.unshift({type: 'delete', index: idx}); - frameCount++; - } - } - - var undoFunc = Plots.modifyFrames; - var redoFunc = Plots.modifyFrames; - var undoArgs = [gd, revops]; - var redoArgs = [gd, ops]; - - if(Queue) Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); - - return Plots.modifyFrames(gd, ops); -} - -/** - * Delete frame - * - * @param {string id or DOM element} gd - * the id or DOM element of the graph container div - * - * @param {array of integers} frameList - * list of integer indices of frames to be deleted - */ -function deleteFrames(gd, frameList) { - gd = Lib.getGraphDiv(gd); - - if(!Lib.isPlotDiv(gd)) { - throw new Error('This element is not a Plotly plot: ' + gd); - } - - var i, idx; - var _frames = gd._transitionData._frames; - var ops = []; - var revops = []; - - if(!frameList) { - frameList = []; - for(i = 0; i < _frames.length; i++) { - frameList.push(i); - } - } - - frameList = frameList.slice(); - frameList.sort(); - - for(i = frameList.length - 1; i >= 0; i--) { - idx = frameList[i]; - ops.push({type: 'delete', index: idx}); - revops.unshift({type: 'insert', index: idx, value: _frames[idx]}); - } - - var undoFunc = Plots.modifyFrames; - var redoFunc = Plots.modifyFrames; - var undoArgs = [gd, revops]; - var redoArgs = [gd, ops]; - - if(Queue) Queue.add(gd, undoFunc, undoArgs, redoFunc, redoArgs); - - return Plots.modifyFrames(gd, ops); -} - -/** - * Purge a graph container div back to its initial pre-Plotly.plot state - * - * @param {string id or DOM element} gd - * the id or DOM element of the graph container div - */ -function purge(gd) { - gd = Lib.getGraphDiv(gd); - - var fullLayout = gd._fullLayout || {}; - var fullData = gd._fullData || []; - - // remove gl contexts - Plots.cleanPlot([], {}, fullData, fullLayout); - - // purge properties - Plots.purge(gd); - - // purge event emitter methods - Events.purge(gd); - - // remove plot container - if(fullLayout._container) fullLayout._container.remove(); - - // in contrast to Plotly.Plots.purge which does NOT clear _context! - delete gd._context; - - return gd; -} - -// ------------------------------------------------------- -// makePlotFramework: Create the plot container and axes -// ------------------------------------------------------- -function makePlotFramework(gd) { - var gd3 = d3.select(gd); - var fullLayout = gd._fullLayout; - - // Plot container - fullLayout._container = gd3.selectAll('.plot-container').data([0]); - fullLayout._container.enter().insert('div', ':first-child') - .classed('plot-container', true) - .classed('plotly', true); - - // Make the svg container - fullLayout._paperdiv = fullLayout._container.selectAll('.svg-container').data([0]); - fullLayout._paperdiv.enter().append('div') - .classed('svg-container', true) - .style('position', 'relative'); - - // Make the graph containers - // start fresh each time we get here, so we know the order comes out - // right, rather than enter/exit which can muck up the order - // TODO: sort out all the ordering so we don't have to - // explicitly delete anything - // FIXME: parcoords reuses this object, not the best pattern - fullLayout._glcontainer = fullLayout._paperdiv.selectAll('.gl-container') - .data([{}]); - - fullLayout._glcontainer.enter().append('div') - .classed('gl-container', true); - - fullLayout._paperdiv.selectAll('.main-svg').remove(); - fullLayout._paperdiv.select('.modebar-container').remove(); - - fullLayout._paper = fullLayout._paperdiv.insert('svg', ':first-child') - .classed('main-svg', true); - - fullLayout._toppaper = fullLayout._paperdiv.append('svg') - .classed('main-svg', true); - - fullLayout._modebardiv = fullLayout._paperdiv.append('div'); - - fullLayout._hoverpaper = fullLayout._paperdiv.append('svg') - .classed('main-svg', true); - - if(!fullLayout._uid) { - var otherUids = {}; - d3.selectAll('defs').each(function() { - if(this.id) otherUids[this.id.split('-')[1]] = 1; - }); - fullLayout._uid = Lib.randstr(otherUids); - } - - fullLayout._paperdiv.selectAll('.main-svg') - .attr(xmlnsNamespaces.svgAttrs); - - fullLayout._defs = fullLayout._paper.append('defs') - .attr('id', 'defs-' + fullLayout._uid); - - fullLayout._clips = fullLayout._defs.append('g') - .classed('clips', true); - - fullLayout._topdefs = fullLayout._toppaper.append('defs') - .attr('id', 'topdefs-' + fullLayout._uid); - - fullLayout._topclips = fullLayout._topdefs.append('g') - .classed('clips', true); - - fullLayout._bgLayer = fullLayout._paper.append('g') - .classed('bglayer', true); - - fullLayout._draggers = fullLayout._paper.append('g') - .classed('draglayer', true); - - // lower shape/image layer - note that this is behind - // all subplots data/grids but above the backgrounds - // except inset subplots, whose backgrounds are drawn - // inside their own group so that they appear above - // the data for the main subplot - // lower shapes and images which are fully referenced to - // a subplot still get drawn within the subplot's group - // so they will work correctly on insets - var layerBelow = fullLayout._paper.append('g') - .classed('layer-below', true); - fullLayout._imageLowerLayer = layerBelow.append('g') - .classed('imagelayer', true); - fullLayout._shapeLowerLayer = layerBelow.append('g') - .classed('shapelayer', true); - - // single cartesian layer for the whole plot - fullLayout._cartesianlayer = fullLayout._paper.append('g').classed('cartesianlayer', true); - - // single polar layer for the whole plot - fullLayout._polarlayer = fullLayout._paper.append('g').classed('polarlayer', true); - - // single ternary layer for the whole plot - fullLayout._ternarylayer = fullLayout._paper.append('g').classed('ternarylayer', true); - - // single geo layer for the whole plot - fullLayout._geolayer = fullLayout._paper.append('g').classed('geolayer', true); - - // single funnelarea layer for the whole plot - fullLayout._funnelarealayer = fullLayout._paper.append('g').classed('funnelarealayer', true); - - // single pie layer for the whole plot - fullLayout._pielayer = fullLayout._paper.append('g').classed('pielayer', true); - - // single sunburst layer for the whole plot - fullLayout._sunburstlayer = fullLayout._paper.append('g').classed('sunburstlayer', true); - - // single indicator layer for the whole plot - fullLayout._indicatorlayer = fullLayout._toppaper.append('g').classed('indicatorlayer', true); - - // fill in image server scrape-svg - fullLayout._glimages = fullLayout._paper.append('g').classed('glimages', true); - - // lastly upper shapes, info (legend, annotations) and hover layers go on top - // these are in a different svg element normally, but get collapsed into a single - // svg when exporting (after inserting 3D) - // upper shapes/images are only those drawn above the whole plot, including subplots - var layerAbove = fullLayout._toppaper.append('g') - .classed('layer-above', true); - fullLayout._imageUpperLayer = layerAbove.append('g') - .classed('imagelayer', true); - fullLayout._shapeUpperLayer = layerAbove.append('g') - .classed('shapelayer', true); - - fullLayout._infolayer = fullLayout._toppaper.append('g').classed('infolayer', true); - fullLayout._menulayer = fullLayout._toppaper.append('g').classed('menulayer', true); - fullLayout._zoomlayer = fullLayout._toppaper.append('g').classed('zoomlayer', true); - fullLayout._hoverlayer = fullLayout._hoverpaper.append('g').classed('hoverlayer', true); - - // Make the modebar container - fullLayout._modebardiv - .classed('modebar-container', true) - .style('position', 'absolute') - .style('top', '0px') - .style('right', '0px'); - - gd.emit('plotly_framework'); -} - -exports.animate = animate; -exports.addFrames = addFrames; -exports.deleteFrames = deleteFrames; - -exports.addTraces = addTraces; -exports.deleteTraces = deleteTraces; -exports.extendTraces = extendTraces; -exports.moveTraces = moveTraces; -exports.prependTraces = prependTraces; - -exports.newPlot = newPlot; -exports.plot = plot; -exports.purge = purge; - -exports.react = react; -exports.redraw = redraw; -exports.relayout = relayout; -exports.restyle = restyle; - -exports.setPlotConfig = setPlotConfig; - -exports.update = update; - -exports._guiRelayout = guiEdit(relayout); -exports._guiRestyle = guiEdit(restyle); -exports._guiUpdate = guiEdit(update); - -exports._storeDirectGUIEdit = _storeDirectGUIEdit; - -},{"../components/color":593,"../components/drawing":614,"../constants/xmlns_namespaces":696,"../lib":719,"../lib/events":709,"../lib/queue":734,"../lib/svg_text_utils":743,"../plots/cartesian/axes":767,"../plots/cartesian/constants":773,"../plots/cartesian/graph_interact":776,"../plots/cartesian/select":784,"../plots/plots":828,"../plots/polar/legacy":836,"../registry":847,"./edit_types":750,"./helpers":751,"./manage_arrays":753,"./plot_config":755,"./plot_schema":756,"./subroutines":758,"d3":163,"fast-isnumeric":225,"has-hover":410}],755:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** - * This will be transferred over to gd and overridden by - * config args to Plotly.plot. - * - * The defaults are the appropriate settings for plotly.js, - * so we get the right experience without any config argument. - * - * N.B. the config options are not coerced using Lib.coerce so keys - * like `valType` and `values` are only set for documentation purposes - * at the moment. - */ - -var configAttributes = { - staticPlot: { - valType: 'boolean', - dflt: false, - - }, - - plotlyServerURL: { - valType: 'string', - dflt: 'https://plot.ly', - - }, - - editable: { - valType: 'boolean', - dflt: false, - - }, - edits: { - annotationPosition: { - valType: 'boolean', - dflt: false, - - }, - annotationTail: { - valType: 'boolean', - dflt: false, - - }, - annotationText: { - valType: 'boolean', - dflt: false, - - }, - axisTitleText: { - valType: 'boolean', - dflt: false, - - }, - colorbarPosition: { - valType: 'boolean', - dflt: false, - - }, - colorbarTitleText: { - valType: 'boolean', - dflt: false, - - }, - legendPosition: { - valType: 'boolean', - dflt: false, - - }, - legendText: { - valType: 'boolean', - dflt: false, - - }, - shapePosition: { - valType: 'boolean', - dflt: false, - - }, - titleText: { - valType: 'boolean', - dflt: false, - - } - }, - - autosizable: { - valType: 'boolean', - dflt: false, - - }, - responsive: { - valType: 'boolean', - dflt: false, - - }, - fillFrame: { - valType: 'boolean', - dflt: false, - - }, - frameMargins: { - valType: 'number', - dflt: 0, - min: 0, - max: 0.5, - - }, - - scrollZoom: { - valType: 'flaglist', - flags: ['cartesian', 'gl3d', 'geo', 'mapbox'], - extras: [true, false], - dflt: 'gl3d+geo+mapbox', - - }, - doubleClick: { - valType: 'enumerated', - values: [false, 'reset', 'autosize', 'reset+autosize'], - dflt: 'reset+autosize', - - }, - doubleClickDelay: { - valType: 'number', - dflt: 300, - min: 0, - - }, - - showAxisDragHandles: { - valType: 'boolean', - dflt: true, - - }, - showAxisRangeEntryBoxes: { - valType: 'boolean', - dflt: true, - - }, - - showTips: { - valType: 'boolean', - dflt: true, - - }, - - showLink: { - valType: 'boolean', - dflt: false, - - }, - linkText: { - valType: 'string', - dflt: 'Edit chart', - noBlank: true, - - }, - sendData: { - valType: 'boolean', - dflt: true, - - }, - showSources: { - valType: 'any', - dflt: false, - - }, - - displayModeBar: { - valType: 'enumerated', - values: ['hover', true, false], - dflt: 'hover', - - }, - showSendToCloud: { - valType: 'boolean', - dflt: false, - - }, - showEditInChartStudio: { - valType: 'boolean', - dflt: false, - - }, - modeBarButtonsToRemove: { - valType: 'any', - dflt: [], - - }, - modeBarButtonsToAdd: { - valType: 'any', - dflt: [], - - }, - modeBarButtons: { - valType: 'any', - dflt: false, - - }, - toImageButtonOptions: { - valType: 'any', - dflt: {}, - - }, - displaylogo: { - valType: 'boolean', - dflt: true, - - }, - watermark: { - valType: 'boolean', - dflt: false, - - }, - - plotGlPixelRatio: { - valType: 'number', - dflt: 2, - min: 1, - max: 4, - - }, - - setBackground: { - valType: 'any', - dflt: 'transparent', - - }, - - topojsonURL: { - valType: 'string', - noBlank: true, - dflt: 'https://cdn.plot.ly/', - - }, - - mapboxAccessToken: { - valType: 'string', - dflt: null, - - }, - - logging: { - valType: 'boolean', - dflt: 1, - - }, - - queueLength: { - valType: 'integer', - min: 0, - dflt: 0, - - }, - - globalTransforms: { - valType: 'any', - dflt: [], - - }, - - locale: { - valType: 'string', - dflt: 'en-US', - - }, - - locales: { - valType: 'any', - dflt: {}, - - } -}; - -var dfltConfig = {}; - -function crawl(src, target) { - for(var k in src) { - var obj = src[k]; - if(obj.valType) { - target[k] = obj.dflt; - } else { - if(!target[k]) { - target[k] = {}; - } - crawl(obj, target[k]); - } - } -} - -crawl(configAttributes, dfltConfig); - -module.exports = { - configAttributes: configAttributes, - dfltConfig: dfltConfig -}; - -},{}],756:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../registry'); -var Lib = _dereq_('../lib'); - -var baseAttributes = _dereq_('../plots/attributes'); -var baseLayoutAttributes = _dereq_('../plots/layout_attributes'); -var frameAttributes = _dereq_('../plots/frame_attributes'); -var animationAttributes = _dereq_('../plots/animation_attributes'); -var configAttributes = _dereq_('./plot_config').configAttributes; - -// polar attributes are not part of the Registry yet -var polarAreaAttrs = _dereq_('../plots/polar/legacy/area_attributes'); -var polarAxisAttrs = _dereq_('../plots/polar/legacy/axis_attributes'); - -var editTypes = _dereq_('./edit_types'); - -var extendFlat = Lib.extendFlat; -var extendDeepAll = Lib.extendDeepAll; -var isPlainObject = Lib.isPlainObject; -var isArrayOrTypedArray = Lib.isArrayOrTypedArray; -var nestedProperty = Lib.nestedProperty; -var valObjectMeta = Lib.valObjectMeta; - -var IS_SUBPLOT_OBJ = '_isSubplotObj'; -var IS_LINKED_TO_ARRAY = '_isLinkedToArray'; -var ARRAY_ATTR_REGEXPS = '_arrayAttrRegexps'; -var DEPRECATED = '_deprecated'; -var UNDERSCORE_ATTRS = [IS_SUBPLOT_OBJ, IS_LINKED_TO_ARRAY, ARRAY_ATTR_REGEXPS, DEPRECATED]; - -exports.IS_SUBPLOT_OBJ = IS_SUBPLOT_OBJ; -exports.IS_LINKED_TO_ARRAY = IS_LINKED_TO_ARRAY; -exports.DEPRECATED = DEPRECATED; -exports.UNDERSCORE_ATTRS = UNDERSCORE_ATTRS; - -/** Outputs the full plotly.js plot schema - * - * @return {object} - * - defs - * - traces - * - layout - * - transforms - * - frames - * - animations - * - config - */ -exports.get = function() { - var traces = {}; - - Registry.allTypes.concat('area').forEach(function(type) { - traces[type] = getTraceAttributes(type); - }); - - var transforms = {}; - - Object.keys(Registry.transformsRegistry).forEach(function(type) { - transforms[type] = getTransformAttributes(type); - }); - - return { - defs: { - valObjects: valObjectMeta, - metaKeys: UNDERSCORE_ATTRS.concat(['description', 'role', 'editType', 'impliedEdits']), - editType: { - traces: editTypes.traces, - layout: editTypes.layout - }, - impliedEdits: { - - } - }, - - traces: traces, - layout: getLayoutAttributes(), - - transforms: transforms, - - frames: getFramesAttributes(), - animation: formatAttributes(animationAttributes), - - config: formatAttributes(configAttributes) - }; -}; - -/** - * Crawl the attribute tree, recursively calling a callback function - * - * @param {object} attrs - * The node of the attribute tree (e.g. the root) from which recursion originates - * @param {Function} callback - * A callback function with the signature: - * @callback callback - * @param {object} attr an attribute - * @param {String} attrName name string - * @param {object[]} attrs all the attributes - * @param {Number} level the recursion level, 0 at the root - * @param {String} fullAttrString full attribute name (ie 'marker.line') - * @param {Number} [specifiedLevel] - * The level in the tree, in order to let the callback function detect descend or backtrack, - * typically unsupplied (implied 0), just used by the self-recursive call. - * The necessity arises because the tree traversal is not controlled by callback return values. - * The decision to not use callback return values for controlling tree pruning arose from - * the goal of keeping the crawler backwards compatible. Observe that one of the pruning conditions - * precedes the callback call. - * @param {string} [attrString] - * the path to the current attribute, as an attribute string (ie 'marker.line') - * typically unsupplied, but you may supply it if you want to disambiguate which attrs tree you - * are starting from - * - * @return {object} transformOut - * copy of transformIn that contains attribute defaults - */ -exports.crawl = function(attrs, callback, specifiedLevel, attrString) { - var level = specifiedLevel || 0; - attrString = attrString || ''; - - Object.keys(attrs).forEach(function(attrName) { - var attr = attrs[attrName]; - - if(UNDERSCORE_ATTRS.indexOf(attrName) !== -1) return; - - var fullAttrString = (attrString ? attrString + '.' : '') + attrName; - callback(attr, attrName, attrs, level, fullAttrString); - - if(exports.isValObject(attr)) return; - - if(isPlainObject(attr) && attrName !== 'impliedEdits') { - exports.crawl(attr, callback, level + 1, fullAttrString); - } - }); -}; - -/** Is object a value object (or a container object)? - * - * @param {object} obj - * @return {boolean} - * returns true for a valid value object and - * false for tree nodes in the attribute hierarchy - */ -exports.isValObject = function(obj) { - return obj && obj.valType !== undefined; -}; - -/** - * Find all data array attributes in a given trace object - including - * `arrayOk` attributes. - * - * @param {object} trace - * full trace object that contains a reference to `_module.attributes` - * - * @return {array} arrayAttributes - * list of array attributes for the given trace - */ -exports.findArrayAttributes = function(trace) { - var arrayAttributes = []; - var stack = []; - var isArrayStack = []; - var baseContainer, baseAttrName; - - function callback(attr, attrName, attrs, level) { - stack = stack.slice(0, level).concat([attrName]); - isArrayStack = isArrayStack.slice(0, level).concat([attr && attr._isLinkedToArray]); - - var splittableAttr = ( - attr && - (attr.valType === 'data_array' || attr.arrayOk === true) && - !(stack[level - 1] === 'colorbar' && (attrName === 'ticktext' || attrName === 'tickvals')) - ); - - // Manually exclude 'colorbar.tickvals' and 'colorbar.ticktext' for now - // which are declared as `valType: 'data_array'` but scale independently of - // the coordinate arrays. - // - // Down the road, we might want to add a schema field (e.g `uncorrelatedArray: true`) - // to distinguish attributes of the likes. - - if(!splittableAttr) return; - - crawlIntoTrace(baseContainer, 0, ''); - } - - function crawlIntoTrace(container, i, astrPartial) { - var item = container[stack[i]]; - var newAstrPartial = astrPartial + stack[i]; - if(i === stack.length - 1) { - if(isArrayOrTypedArray(item)) { - arrayAttributes.push(baseAttrName + newAstrPartial); - } - } else { - if(isArrayStack[i]) { - if(Array.isArray(item)) { - for(var j = 0; j < item.length; j++) { - if(isPlainObject(item[j])) { - crawlIntoTrace(item[j], i + 1, newAstrPartial + '[' + j + '].'); - } - } - } - } else if(isPlainObject(item)) { - crawlIntoTrace(item, i + 1, newAstrPartial + '.'); - } - } - } - - baseContainer = trace; - baseAttrName = ''; - exports.crawl(baseAttributes, callback); - if(trace._module && trace._module.attributes) { - exports.crawl(trace._module.attributes, callback); - } - - var transforms = trace.transforms; - if(transforms) { - for(var i = 0; i < transforms.length; i++) { - var transform = transforms[i]; - var module = transform._module; - - if(module) { - baseAttrName = 'transforms[' + i + '].'; - baseContainer = transform; - - exports.crawl(module.attributes, callback); - } - } - } - - return arrayAttributes; -}; - -/* - * Find the valObject for one attribute in an existing trace - * - * @param {object} trace - * full trace object that contains a reference to `_module.attributes` - * @param {object} parts - * an array of parts, like ['transforms', 1, 'value'] - * typically from nestedProperty(...).parts - * - * @return {object|false} - * the valObject for this attribute, or the last found parent - * in some cases the innermost valObject will not exist, for example - * `valType: 'any'` attributes where we might set a part of the attribute. - * In that case, stop at the deepest valObject we *do* find. - */ -exports.getTraceValObject = function(trace, parts) { - var head = parts[0]; - var i = 1; // index to start recursing from - var moduleAttrs, valObject; - - if(head === 'transforms') { - if(parts.length === 1) { - return baseAttributes.transforms; - } - var transforms = trace.transforms; - if(!Array.isArray(transforms) || !transforms.length) return false; - var tNum = parts[1]; - if(!isIndex(tNum) || tNum >= transforms.length) { - return false; - } - moduleAttrs = (Registry.transformsRegistry[transforms[tNum].type] || {}).attributes; - valObject = moduleAttrs && moduleAttrs[parts[2]]; - i = 3; // start recursing only inside the transform - } else if(trace.type === 'area') { - valObject = polarAreaAttrs[head]; - } else { - // first look in the module for this trace - // components have already merged their trace attributes in here - var _module = trace._module; - if(!_module) _module = (Registry.modules[trace.type || baseAttributes.type.dflt] || {})._module; - if(!_module) return false; - - moduleAttrs = _module.attributes; - valObject = moduleAttrs && moduleAttrs[head]; - - // then look in the subplot attributes - if(!valObject) { - var subplotModule = _module.basePlotModule; - if(subplotModule && subplotModule.attributes) { - valObject = subplotModule.attributes[head]; - } - } - - // finally look in the global attributes - if(!valObject) valObject = baseAttributes[head]; - } - - return recurseIntoValObject(valObject, parts, i); -}; - -/* - * Find the valObject for one layout attribute - * - * @param {array} parts - * an array of parts, like ['annotations', 1, 'x'] - * typically from nestedProperty(...).parts - * - * @return {object|false} - * the valObject for this attribute, or the last found parent - * in some cases the innermost valObject will not exist, for example - * `valType: 'any'` attributes where we might set a part of the attribute. - * In that case, stop at the deepest valObject we *do* find. - */ -exports.getLayoutValObject = function(fullLayout, parts) { - var valObject = layoutHeadAttr(fullLayout, parts[0]); - - return recurseIntoValObject(valObject, parts, 1); -}; - -function layoutHeadAttr(fullLayout, head) { - var i, key, _module, attributes; - - // look for attributes of the subplot types used on the plot - var basePlotModules = fullLayout._basePlotModules; - if(basePlotModules) { - var out; - for(i = 0; i < basePlotModules.length; i++) { - _module = basePlotModules[i]; - if(_module.attrRegex && _module.attrRegex.test(head)) { - // if a module defines overrides, these take precedence - // initially this is to allow gl2d different editTypes from svg cartesian - if(_module.layoutAttrOverrides) return _module.layoutAttrOverrides; - - // otherwise take the first attributes we find - if(!out && _module.layoutAttributes) out = _module.layoutAttributes; - } - - // a module can also override the behavior of base (and component) module layout attrs - // again see gl2d for initial use case - var baseOverrides = _module.baseLayoutAttrOverrides; - if(baseOverrides && head in baseOverrides) return baseOverrides[head]; - } - if(out) return out; - } - - // look for layout attributes contributed by traces on the plot - var modules = fullLayout._modules; - if(modules) { - for(i = 0; i < modules.length; i++) { - attributes = modules[i].layoutAttributes; - if(attributes && head in attributes) { - return attributes[head]; - } - } - } - - /* - * Next look in components. - * Components that define a schema have already merged this into - * base and subplot attribute defs, so ignore these. - * Others (older style) all put all their attributes - * inside a container matching the module `name` - * eg `attributes` (array) or `legend` (object) - */ - for(key in Registry.componentsRegistry) { - _module = Registry.componentsRegistry[key]; - if(_module.name === 'colorscale' && head.indexOf('coloraxis') === 0) { - return _module.layoutAttributes[head]; - } else if(!_module.schema && (head === _module.name)) { - return _module.layoutAttributes; - } - } - - if(head in baseLayoutAttributes) return baseLayoutAttributes[head]; - - // Polar doesn't populate _modules or _basePlotModules - // just fall back on these when the others fail - if(head === 'radialaxis' || head === 'angularaxis') { - return polarAxisAttrs[head]; - } - return polarAxisAttrs.layout[head] || false; -} - -function recurseIntoValObject(valObject, parts, i) { - if(!valObject) return false; - - if(valObject._isLinkedToArray) { - // skip array index, abort if we try to dive into an array without an index - if(isIndex(parts[i])) i++; - else if(i < parts.length) return false; - } - - // now recurse as far as we can. Occasionally we have an attribute - // setting an internal part below what's in the schema; just return - // the innermost schema item we find. - for(; i < parts.length; i++) { - var newValObject = valObject[parts[i]]; - if(isPlainObject(newValObject)) valObject = newValObject; - else break; - - if(i === parts.length - 1) break; - - if(valObject._isLinkedToArray) { - i++; - if(!isIndex(parts[i])) return false; - } else if(valObject.valType === 'info_array') { - i++; - var index = parts[i]; - if(!isIndex(index)) return false; - - var items = valObject.items; - if(Array.isArray(items)) { - if(index >= items.length) return false; - if(valObject.dimensions === 2) { - i++; - if(parts.length === i) return valObject; - var index2 = parts[i]; - if(!isIndex(index2)) return false; - valObject = items[index][index2]; - } else valObject = items[index]; - } else { - valObject = items; - } - } - } - - return valObject; -} - -// note: this is different from Lib.isIndex, this one doesn't accept numeric -// strings, only actual numbers. -function isIndex(val) { - return val === Math.round(val) && val >= 0; -} - -function getTraceAttributes(type) { - var _module, basePlotModule; - - if(type === 'area') { - _module = { attributes: polarAreaAttrs }; - basePlotModule = {}; - } else { - _module = Registry.modules[type]._module, - basePlotModule = _module.basePlotModule; - } - - var attributes = {}; - - // make 'type' the first attribute in the object - attributes.type = null; - - var copyBaseAttributes = extendDeepAll({}, baseAttributes); - var copyModuleAttributes = extendDeepAll({}, _module.attributes); - - // prune global-level trace attributes that are already defined in a trace - exports.crawl(copyModuleAttributes, function(attr, attrName, attrs, level, fullAttrString) { - nestedProperty(copyBaseAttributes, fullAttrString).set(undefined); - // Prune undefined attributes - if(attr === undefined) nestedProperty(copyModuleAttributes, fullAttrString).set(undefined); - }); - - // base attributes (same for all trace types) - extendDeepAll(attributes, copyBaseAttributes); - - // prune-out base attributes based on trace module categories - if(Registry.traceIs(type, 'noOpacity')) { - delete attributes.opacity; - } - if(!Registry.traceIs(type, 'showLegend')) { - delete attributes.showlegend; - delete attributes.legendgroup; - } - if(Registry.traceIs(type, 'noHover')) { - delete attributes.hoverinfo; - delete attributes.hoverlabel; - } - if(!_module.selectPoints) { - delete attributes.selectedpoints; - } - - // module attributes - extendDeepAll(attributes, copyModuleAttributes); - - // subplot attributes - if(basePlotModule.attributes) { - extendDeepAll(attributes, basePlotModule.attributes); - } - - // 'type' gets overwritten by baseAttributes; reset it here - attributes.type = type; - - var out = { - meta: _module.meta || {}, - categories: _module.categories || {}, - animatable: Boolean(_module.animatable), - type: type, - attributes: formatAttributes(attributes), - }; - - // trace-specific layout attributes - if(_module.layoutAttributes) { - var layoutAttributes = {}; - - extendDeepAll(layoutAttributes, _module.layoutAttributes); - out.layoutAttributes = formatAttributes(layoutAttributes); - } - - // drop anim:true in non-animatable modules - if(!_module.animatable) { - exports.crawl(out, function(attr) { - if(exports.isValObject(attr) && 'anim' in attr) { - delete attr.anim; - } - }); - } - - return out; -} - -function getLayoutAttributes() { - var layoutAttributes = {}; - var key, _module; - - // global layout attributes - extendDeepAll(layoutAttributes, baseLayoutAttributes); - - // add base plot module layout attributes - for(key in Registry.subplotsRegistry) { - _module = Registry.subplotsRegistry[key]; - - if(!_module.layoutAttributes) continue; - - if(Array.isArray(_module.attr)) { - for(var i = 0; i < _module.attr.length; i++) { - handleBasePlotModule(layoutAttributes, _module, _module.attr[i]); - } - } else { - var astr = _module.attr === 'subplot' ? _module.name : _module.attr; - handleBasePlotModule(layoutAttributes, _module, astr); - } - } - - // polar layout attributes - layoutAttributes = assignPolarLayoutAttrs(layoutAttributes); - - // add registered components layout attributes - for(key in Registry.componentsRegistry) { - _module = Registry.componentsRegistry[key]; - var schema = _module.schema; - - if(schema && (schema.subplots || schema.layout)) { - /* - * Components with defined schema have already been merged in at register time - * but a few components define attributes that apply only to xaxis - * not yaxis (rangeselector, rangeslider) - delete from y schema. - * Note that the input attributes for xaxis/yaxis are the same object - * so it's not possible to only add them to xaxis from the start. - * If we ever have such asymmetry the other way, or anywhere else, - * we will need to extend both this code and mergeComponentAttrsToSubplot - * (which will not find yaxis only for example) - */ - var subplots = schema.subplots; - if(subplots && subplots.xaxis && !subplots.yaxis) { - for(var xkey in subplots.xaxis) { - delete layoutAttributes.yaxis[xkey]; - } - } - } else if(_module.name === 'colorscale') { - extendDeepAll(layoutAttributes, _module.layoutAttributes); - } else if(_module.layoutAttributes) { - // older style without schema need to be explicitly merged in now - insertAttrs(layoutAttributes, _module.layoutAttributes, _module.name); - } - } - - return { - layoutAttributes: formatAttributes(layoutAttributes) - }; -} - -function getTransformAttributes(type) { - var _module = Registry.transformsRegistry[type]; - var attributes = extendDeepAll({}, _module.attributes); - - // add registered components transform attributes - Object.keys(Registry.componentsRegistry).forEach(function(k) { - var _module = Registry.componentsRegistry[k]; - - if(_module.schema && _module.schema.transforms && _module.schema.transforms[type]) { - Object.keys(_module.schema.transforms[type]).forEach(function(v) { - insertAttrs(attributes, _module.schema.transforms[type][v], v); - }); - } - }); - - return { - attributes: formatAttributes(attributes) - }; -} - -function getFramesAttributes() { - var attrs = { - frames: extendDeepAll({}, frameAttributes) - }; - - formatAttributes(attrs); - - return attrs.frames; -} - -function formatAttributes(attrs) { - mergeValTypeAndRole(attrs); - formatArrayContainers(attrs); - stringify(attrs); - - return attrs; -} - -function mergeValTypeAndRole(attrs) { - function makeSrcAttr(attrName) { - return { - valType: 'string', - - - editType: 'none' - }; - } - - function callback(attr, attrName, attrs) { - if(exports.isValObject(attr)) { - if(attr.valType === 'data_array') { - // all 'data_array' attrs have role 'data' - attr.role = 'data'; - // all 'data_array' attrs have a corresponding 'src' attr - attrs[attrName + 'src'] = makeSrcAttr(attrName); - } else if(attr.arrayOk === true) { - // all 'arrayOk' attrs have a corresponding 'src' attr - attrs[attrName + 'src'] = makeSrcAttr(attrName); - } - } else if(isPlainObject(attr)) { - // all attrs container objects get role 'object' - attr.role = 'object'; - } - } - - exports.crawl(attrs, callback); -} - -function formatArrayContainers(attrs) { - function callback(attr, attrName, attrs) { - if(!attr) return; - - var itemName = attr[IS_LINKED_TO_ARRAY]; - - if(!itemName) return; - - delete attr[IS_LINKED_TO_ARRAY]; - - attrs[attrName] = { items: {} }; - attrs[attrName].items[itemName] = attr; - attrs[attrName].role = 'object'; - } - - exports.crawl(attrs, callback); -} - -// this can take around 10ms and should only be run from PlotSchema.get(), -// to ensure JSON.stringify(PlotSchema.get()) gives the intended result. -function stringify(attrs) { - function walk(attr) { - for(var k in attr) { - if(isPlainObject(attr[k])) { - walk(attr[k]); - } else if(Array.isArray(attr[k])) { - for(var i = 0; i < attr[k].length; i++) { - walk(attr[k][i]); - } - } else { - // as JSON.stringify(/test/) // => {} - if(attr[k] instanceof RegExp) { - attr[k] = attr[k].toString(); - } - } - } - } - - walk(attrs); -} - -function assignPolarLayoutAttrs(layoutAttributes) { - extendFlat(layoutAttributes, { - radialaxis: polarAxisAttrs.radialaxis, - angularaxis: polarAxisAttrs.angularaxis - }); - - extendFlat(layoutAttributes, polarAxisAttrs.layout); - - return layoutAttributes; -} - -function handleBasePlotModule(layoutAttributes, _module, astr) { - var np = nestedProperty(layoutAttributes, astr); - var attrs = extendDeepAll({}, _module.layoutAttributes); - - attrs[IS_SUBPLOT_OBJ] = true; - np.set(attrs); -} - -function insertAttrs(baseAttrs, newAttrs, astr) { - var np = nestedProperty(baseAttrs, astr); - - np.set(extendDeepAll(np.get() || {}, newAttrs)); -} - -},{"../lib":719,"../plots/animation_attributes":762,"../plots/attributes":764,"../plots/frame_attributes":794,"../plots/layout_attributes":819,"../plots/polar/legacy/area_attributes":834,"../plots/polar/legacy/axis_attributes":835,"../registry":847,"./edit_types":750,"./plot_config":755}],757:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../lib'); -var plotAttributes = _dereq_('../plots/attributes'); - -var TEMPLATEITEMNAME = 'templateitemname'; - -var templateAttrs = { - name: { - valType: 'string', - - editType: 'none', - - } -}; -templateAttrs[TEMPLATEITEMNAME] = { - valType: 'string', - - editType: 'calc', - -}; - -/** - * templatedArray: decorate an attributes object with templating (and array) - * properties. - * - * @param {string} name: the singular form of the array name. Sets - * `_isLinkedToArray` to this, so the schema knows to treat this as an array. - * @param {object} attrs: the item attributes. Since all callers are expected - * to be constructing this object on the spot, we mutate it here for - * performance, rather than extending a new object with it. - * - * @returns {object}: the decorated `attrs` object - */ -exports.templatedArray = function(name, attrs) { - attrs._isLinkedToArray = name; - attrs.name = templateAttrs.name; - attrs[TEMPLATEITEMNAME] = templateAttrs[TEMPLATEITEMNAME]; - return attrs; -}; - -/** - * traceTemplater: logic for matching traces to trace templates - * - * @param {object} dataTemplate: collection of {traceType: [{template}, ...]} - * ie each type the template applies to contains a list of template objects, - * to be provided cyclically to data traces of that type. - * - * @returns {object}: {newTrace}, a function: - * newTrace(traceIn): that takes the input traceIn, coerces its type, then - * uses that type to find the next template to apply. returns the output - * traceOut with template attached, ready to continue supplyDefaults. - */ -exports.traceTemplater = function(dataTemplate) { - var traceCounts = {}; - var traceType, typeTemplates; - - for(traceType in dataTemplate) { - typeTemplates = dataTemplate[traceType]; - if(Array.isArray(typeTemplates) && typeTemplates.length) { - traceCounts[traceType] = 0; - } - } - - function newTrace(traceIn) { - traceType = Lib.coerce(traceIn, {}, plotAttributes, 'type'); - var traceOut = {type: traceType, _template: null}; - if(traceType in traceCounts) { - typeTemplates = dataTemplate[traceType]; - // cycle through traces in the template set for this type - var typei = traceCounts[traceType] % typeTemplates.length; - traceCounts[traceType]++; - traceOut._template = typeTemplates[typei]; - } else { - // TODO: anything we should do for types missing from the template? - // try to apply some other type? Or just bail as we do here? - // Actually I think yes, we should apply other types; would be nice - // if all scatter* could inherit from each other, and if histogram - // could inherit from bar, etc... but how to specify this? And do we - // compose them, or if a type is present require it to be complete? - // Actually this could apply to layout too - 3D annotations - // inheriting from 2D, axes of different types inheriting from each - // other... - } - return traceOut; - } - - return { - newTrace: newTrace - // TODO: function to figure out what's left & what didn't work - }; -}; - -/** - * newContainer: Create a new sub-container inside `container` and propagate any - * applicable template to it. If there's no template, still propagates - * `undefined` so relinkPrivate will not retain an old template! - * - * @param {object} container: the outer container, should already have _template - * if there *is* a template for this plot - * @param {string} name: the key of the new container to make - * @param {string} baseName: if applicable, a base attribute to take the - * template from, ie for xaxis3 the base would be xaxis - * - * @returns {object}: an object for inclusion _full*, empty except for the - * appropriate template piece - */ -exports.newContainer = function(container, name, baseName) { - var template = container._template; - var part = template && (template[name] || (baseName && template[baseName])); - if(!Lib.isPlainObject(part)) part = null; - - var out = container[name] = {_template: part}; - return out; -}; - -/** - * arrayTemplater: special logic for templating both defaults and specific items - * in a container array (annotations etc) - * - * @param {object} container: the outer container, should already have _template - * if there *is* a template for this plot - * @param {string} name: the name of the array to template (ie 'annotations') - * will be used to find default ('annotationdefaults' object) and specific - * ('annotations' array) template specs. - * @param {string} inclusionAttr: the attribute determining this item's - * inclusion in the output, usually 'visible' or 'enabled' - * - * @returns {object}: {newItem, defaultItems}, both functions: - * newItem(itemIn): create an output item, bare except for the correct - * template and name(s), as the base for supplyDefaults - * defaultItems(): to be called after all newItem calls, return any - * specific template items that have not already beeen included, - * also as bare output items ready for supplyDefaults. - */ -exports.arrayTemplater = function(container, name, inclusionAttr) { - var template = container._template; - var defaultsTemplate = template && template[arrayDefaultKey(name)]; - var templateItems = template && template[name]; - if(!Array.isArray(templateItems) || !templateItems.length) { - templateItems = []; - } - - var usedNames = {}; - - function newItem(itemIn) { - // include name and templateitemname in the output object for ALL - // container array items. Note: you could potentially use different - // name and templateitemname, if you're using one template to make - // another template. templateitemname would be the name in the original - // template, and name is the new "subclassed" item name. - var out = {name: itemIn.name, _input: itemIn}; - var templateItemName = out[TEMPLATEITEMNAME] = itemIn[TEMPLATEITEMNAME]; - - // no itemname: use the default template - if(!validItemName(templateItemName)) { - out._template = defaultsTemplate; - return out; - } - - // look for an item matching this itemname - // note these do not inherit from the default template, only the item. - for(var i = 0; i < templateItems.length; i++) { - var templateItem = templateItems[i]; - if(templateItem.name === templateItemName) { - // Note: it's OK to use a template item more than once - // but using it at least once will stop it from generating - // a default item at the end. - usedNames[templateItemName] = 1; - out._template = templateItem; - return out; - } - } - - // Didn't find a matching template item, so since this item is intended - // to only be modifications it's most likely broken. Hide it unless - // it's explicitly marked visible - in which case it gets NO template, - // not even the default. - out[inclusionAttr] = itemIn[inclusionAttr] || false; - // special falsy value we can look for in validateTemplate - out._template = false; - return out; - } - - function defaultItems() { - var out = []; - for(var i = 0; i < templateItems.length; i++) { - var templateItem = templateItems[i]; - var name = templateItem.name; - // only allow named items to be added as defaults, - // and only allow each name once - if(validItemName(name) && !usedNames[name]) { - var outi = { - _template: templateItem, - name: name, - _input: {_templateitemname: name} - }; - outi[TEMPLATEITEMNAME] = templateItem[TEMPLATEITEMNAME]; - out.push(outi); - usedNames[name] = 1; - } - } - return out; - } - - return { - newItem: newItem, - defaultItems: defaultItems - }; -}; - -function validItemName(name) { - return name && typeof name === 'string'; -} - -function arrayDefaultKey(name) { - var lastChar = name.length - 1; - if(name.charAt(lastChar) !== 's') { - Lib.warn('bad argument to arrayDefaultKey: ' + name); - } - return name.substr(0, name.length - 1) + 'defaults'; -} -exports.arrayDefaultKey = arrayDefaultKey; - -/** - * arrayEditor: helper for editing array items that may have come from - * template defaults (in which case they will not exist in the input yet) - * - * @param {object} parentIn: the input container (eg gd.layout) - * @param {string} containerStr: the attribute string for the container inside - * `parentIn`. - * @param {object} itemOut: the _full* item (eg gd._fullLayout.annotations[0]) - * that we'll be editing. Assumed to have been created by `arrayTemplater`. - * - * @returns {object}: {modifyBase, modifyItem, getUpdateObj, applyUpdate}, all functions: - * modifyBase(attr, value): Add an update that's *not* related to the item. - * `attr` is the full attribute string. - * modifyItem(attr, value): Add an update to the item. `attr` is just the - * portion of the attribute string inside the item. - * getUpdateObj(): Get the final constructed update object, to use in - * `restyle` or `relayout`. Also resets the update object in case this - * update was canceled. - * applyUpdate(attr, value): optionally add an update `attr: value`, - * then apply it to `parent` which should be the parent of `containerIn`, - * ie the object to which `containerStr` is the attribute string. - */ -exports.arrayEditor = function(parentIn, containerStr, itemOut) { - var lengthIn = (Lib.nestedProperty(parentIn, containerStr).get() || []).length; - var index = itemOut._index; - // Check that we are indeed off the end of this container. - // Otherwise a devious user could put a key `_templateitemname` in their - // own input and break lots of things. - var templateItemName = (index >= lengthIn) && (itemOut._input || {})._templateitemname; - if(templateItemName) index = lengthIn; - var itemStr = containerStr + '[' + index + ']'; - - var update; - function resetUpdate() { - update = {}; - if(templateItemName) { - update[itemStr] = {}; - update[itemStr][TEMPLATEITEMNAME] = templateItemName; - } - } - resetUpdate(); - - function modifyBase(attr, value) { - update[attr] = value; - } - - function modifyItem(attr, value) { - if(templateItemName) { - // we're making a new object: edit that object - Lib.nestedProperty(update[itemStr], attr).set(value); - } else { - // we're editing an existing object: include *just* the edit - update[itemStr + '.' + attr] = value; - } - } - - function getUpdateObj() { - var updateOut = update; - resetUpdate(); - return updateOut; - } - - function applyUpdate(attr, value) { - if(attr) modifyItem(attr, value); - var updateToApply = getUpdateObj(); - for(var key in updateToApply) { - Lib.nestedProperty(parentIn, key).set(updateToApply[key]); - } - } - - return { - modifyBase: modifyBase, - modifyItem: modifyItem, - getUpdateObj: getUpdateObj, - applyUpdate: applyUpdate - }; -}; - -},{"../lib":719,"../plots/attributes":764}],758:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Registry = _dereq_('../registry'); -var Plots = _dereq_('../plots/plots'); - -var Lib = _dereq_('../lib'); -var clearGlCanvases = _dereq_('../lib/clear_gl_canvases'); - -var Color = _dereq_('../components/color'); -var Drawing = _dereq_('../components/drawing'); -var Titles = _dereq_('../components/titles'); -var ModeBar = _dereq_('../components/modebar'); - -var Axes = _dereq_('../plots/cartesian/axes'); -var alignmentConstants = _dereq_('../constants/alignment'); -var axisConstraints = _dereq_('../plots/cartesian/constraints'); -var enforceAxisConstraints = axisConstraints.enforce; -var cleanAxisConstraints = axisConstraints.clean; -var doAutoRange = _dereq_('../plots/cartesian/autorange').doAutoRange; - -var SVG_TEXT_ANCHOR_START = 'start'; -var SVG_TEXT_ANCHOR_MIDDLE = 'middle'; -var SVG_TEXT_ANCHOR_END = 'end'; - -exports.layoutStyles = function(gd) { - return Lib.syncOrAsync([Plots.doAutoMargin, lsInner], gd); -}; - -function overlappingDomain(xDomain, yDomain, domains) { - for(var i = 0; i < domains.length; i++) { - var existingX = domains[i][0]; - var existingY = domains[i][1]; - - if(existingX[0] >= xDomain[1] || existingX[1] <= xDomain[0]) { - continue; - } - if(existingY[0] < yDomain[1] && existingY[1] > yDomain[0]) { - return true; - } - } - return false; -} - -function lsInner(gd) { - var fullLayout = gd._fullLayout; - var gs = fullLayout._size; - var pad = gs.p; - var axList = Axes.list(gd, '', true); - var i, subplot, plotinfo, ax, xa, ya; - - fullLayout._paperdiv.style({ - width: (gd._context.responsive && fullLayout.autosize && !gd._context._hasZeroWidth && !gd.layout.width) ? '100%' : fullLayout.width + 'px', - height: (gd._context.responsive && fullLayout.autosize && !gd._context._hasZeroHeight && !gd.layout.height) ? '100%' : fullLayout.height + 'px' - }) - .selectAll('.main-svg') - .call(Drawing.setSize, fullLayout.width, fullLayout.height); - gd._context.setBackground(gd, fullLayout.paper_bgcolor); - - exports.drawMainTitle(gd); - ModeBar.manage(gd); - - // _has('cartesian') means SVG specifically, not GL2D - but GL2D - // can still get here because it makes some of the SVG structure - // for shared features like selections. - if(!fullLayout._has('cartesian')) { - return gd._promises.length && Promise.all(gd._promises); - } - - function getLinePosition(ax, counterAx, side) { - var lwHalf = ax._lw / 2; - - if(ax._id.charAt(0) === 'x') { - if(!counterAx) return gs.t + gs.h * (1 - (ax.position || 0)) + (lwHalf % 1); - else if(side === 'top') return counterAx._offset - pad - lwHalf; - return counterAx._offset + counterAx._length + pad + lwHalf; - } - - if(!counterAx) return gs.l + gs.w * (ax.position || 0) + (lwHalf % 1); - else if(side === 'right') return counterAx._offset + counterAx._length + pad + lwHalf; - return counterAx._offset - pad - lwHalf; - } - - // some preparation of axis position info - for(i = 0; i < axList.length; i++) { - ax = axList[i]; - - var counterAx = ax._anchorAxis; - - // clear axis line positions, to be set in the subplot loop below - ax._linepositions = {}; - - // stash crispRounded linewidth so we don't need to pass gd all over the place - ax._lw = Drawing.crispRound(gd, ax.linewidth, 1); - - // figure out the main axis line and main mirror line position. - // it's easier to follow the logic if we handle these separately from - // ax._linepositions, which are only used by mirror=allticks - // for non-main-subplot ticks, and mirror=all(ticks)? for zero line - // hiding logic - ax._mainLinePosition = getLinePosition(ax, counterAx, ax.side); - ax._mainMirrorPosition = (ax.mirror && counterAx) ? - getLinePosition(ax, counterAx, - alignmentConstants.OPPOSITE_SIDE[ax.side]) : null; - } - - // figure out which backgrounds we need to draw, - // and in which layers to put them - var lowerBackgroundIDs = []; - var backgroundIds = []; - var lowerDomains = []; - // no need to draw background when paper and plot color are the same color, - // activate mode just for large splom (which benefit the most from this - // optimization), but this could apply to all cartesian subplots. - var noNeedForBg = ( - Color.opacity(fullLayout.paper_bgcolor) === 1 && - Color.opacity(fullLayout.plot_bgcolor) === 1 && - fullLayout.paper_bgcolor === fullLayout.plot_bgcolor - ); - - for(subplot in fullLayout._plots) { - plotinfo = fullLayout._plots[subplot]; - - if(plotinfo.mainplot) { - // mainplot is a reference to the main plot this one is overlaid on - // so if it exists, this is an overlaid plot and we don't need to - // give it its own background - if(plotinfo.bg) { - plotinfo.bg.remove(); - } - plotinfo.bg = undefined; - } else { - var xDomain = plotinfo.xaxis.domain; - var yDomain = plotinfo.yaxis.domain; - var plotgroup = plotinfo.plotgroup; - - if(overlappingDomain(xDomain, yDomain, lowerDomains)) { - var pgNode = plotgroup.node(); - var plotgroupBg = plotinfo.bg = Lib.ensureSingle(plotgroup, 'rect', 'bg'); - pgNode.insertBefore(plotgroupBg.node(), pgNode.childNodes[0]); - backgroundIds.push(subplot); - } else { - plotgroup.select('rect.bg').remove(); - lowerDomains.push([xDomain, yDomain]); - if(!noNeedForBg) { - lowerBackgroundIDs.push(subplot); - backgroundIds.push(subplot); - } - } - } - } - - // now create all the lower-layer backgrounds at once now that - // we have the list of subplots that need them - var lowerBackgrounds = fullLayout._bgLayer.selectAll('.bg') - .data(lowerBackgroundIDs); - - lowerBackgrounds.enter().append('rect') - .classed('bg', true); - - lowerBackgrounds.exit().remove(); - - lowerBackgrounds.each(function(subplot) { - fullLayout._plots[subplot].bg = d3.select(this); - }); - - // style all backgrounds - for(i = 0; i < backgroundIds.length; i++) { - plotinfo = fullLayout._plots[backgroundIds[i]]; - xa = plotinfo.xaxis; - ya = plotinfo.yaxis; - - if(plotinfo.bg) { - plotinfo.bg - .call(Drawing.setRect, - xa._offset - pad, ya._offset - pad, - xa._length + 2 * pad, ya._length + 2 * pad) - .call(Color.fill, fullLayout.plot_bgcolor) - .style('stroke-width', 0); - } - } - - if(!fullLayout._hasOnlyLargeSploms) { - for(subplot in fullLayout._plots) { - plotinfo = fullLayout._plots[subplot]; - xa = plotinfo.xaxis; - ya = plotinfo.yaxis; - - // Clip so that data only shows up on the plot area. - var clipId = plotinfo.clipId = 'clip' + fullLayout._uid + subplot + 'plot'; - - var plotClip = Lib.ensureSingleById(fullLayout._clips, 'clipPath', clipId, function(s) { - s.classed('plotclip', true) - .append('rect'); - }); - - plotinfo.clipRect = plotClip.select('rect').attr({ - width: xa._length, - height: ya._length - }); - - Drawing.setTranslate(plotinfo.plot, xa._offset, ya._offset); - - var plotClipId; - var layerClipId; - - if(plotinfo._hasClipOnAxisFalse) { - plotClipId = null; - layerClipId = clipId; - } else { - plotClipId = clipId; - layerClipId = null; - } - - Drawing.setClipUrl(plotinfo.plot, plotClipId, gd); - - // stash layer clipId value (null or same as clipId) - // to DRY up Drawing.setClipUrl calls on trace-module and trace layers - // downstream - plotinfo.layerClipId = layerClipId; - } - } - - var xLinesXLeft, xLinesXRight, xLinesYBottom, xLinesYTop, - leftYLineWidth, rightYLineWidth; - var yLinesYBottom, yLinesYTop, yLinesXLeft, yLinesXRight, - connectYBottom, connectYTop; - var extraSubplot; - - function xLinePath(y) { - return 'M' + xLinesXLeft + ',' + y + 'H' + xLinesXRight; - } - - function xLinePathFree(y) { - return 'M' + xa._offset + ',' + y + 'h' + xa._length; - } - - function yLinePath(x) { - return 'M' + x + ',' + yLinesYTop + 'V' + yLinesYBottom; - } - - function yLinePathFree(x) { - return 'M' + x + ',' + ya._offset + 'v' + ya._length; - } - - function mainPath(ax, pathFn, pathFnFree) { - if(!ax.showline || subplot !== ax._mainSubplot) return ''; - if(!ax._anchorAxis) return pathFnFree(ax._mainLinePosition); - var out = pathFn(ax._mainLinePosition); - if(ax.mirror) out += pathFn(ax._mainMirrorPosition); - return out; - } - - for(subplot in fullLayout._plots) { - plotinfo = fullLayout._plots[subplot]; - xa = plotinfo.xaxis; - ya = plotinfo.yaxis; - - /* - * x lines get longer where they meet y lines, to make a crisp corner. - * The x lines get the padding (margin.pad) plus the y line width to - * fill up the corner nicely. Free x lines are excluded - they always - * span exactly the data area of the plot - * - * | XXXXX - * | XXXXX - * | - * +------ - * x1 - * ----- - * x2 - */ - var xPath = 'M0,0'; - if(shouldShowLinesOrTicks(xa, subplot)) { - leftYLineWidth = findCounterAxisLineWidth(xa, 'left', ya, axList); - xLinesXLeft = xa._offset - (leftYLineWidth ? (pad + leftYLineWidth) : 0); - rightYLineWidth = findCounterAxisLineWidth(xa, 'right', ya, axList); - xLinesXRight = xa._offset + xa._length + (rightYLineWidth ? (pad + rightYLineWidth) : 0); - xLinesYBottom = getLinePosition(xa, ya, 'bottom'); - xLinesYTop = getLinePosition(xa, ya, 'top'); - - // save axis line positions for extra ticks to reference - // each subplot that gets ticks from "allticks" gets an entry: - // [left or bottom, right or top] - extraSubplot = (!xa._anchorAxis || subplot !== xa._mainSubplot); - if(extraSubplot && (xa.mirror === 'allticks' || xa.mirror === 'all')) { - xa._linepositions[subplot] = [xLinesYBottom, xLinesYTop]; - } - - xPath = mainPath(xa, xLinePath, xLinePathFree); - if(extraSubplot && xa.showline && (xa.mirror === 'all' || xa.mirror === 'allticks')) { - xPath += xLinePath(xLinesYBottom) + xLinePath(xLinesYTop); - } - - plotinfo.xlines - .style('stroke-width', xa._lw + 'px') - .call(Color.stroke, xa.showline ? - xa.linecolor : 'rgba(0,0,0,0)'); - } - plotinfo.xlines.attr('d', xPath); - - /* - * y lines that meet x axes get longer only by margin.pad, because - * the x axes fill in the corner space. Free y axes, like free x axes, - * always span exactly the data area of the plot - * - * | | XXXX - * y2| y1| XXXX - * | | XXXX - * | - * +----- - */ - var yPath = 'M0,0'; - if(shouldShowLinesOrTicks(ya, subplot)) { - connectYBottom = findCounterAxisLineWidth(ya, 'bottom', xa, axList); - yLinesYBottom = ya._offset + ya._length + (connectYBottom ? pad : 0); - connectYTop = findCounterAxisLineWidth(ya, 'top', xa, axList); - yLinesYTop = ya._offset - (connectYTop ? pad : 0); - yLinesXLeft = getLinePosition(ya, xa, 'left'); - yLinesXRight = getLinePosition(ya, xa, 'right'); - - extraSubplot = (!ya._anchorAxis || subplot !== ya._mainSubplot); - if(extraSubplot && (ya.mirror === 'allticks' || ya.mirror === 'all')) { - ya._linepositions[subplot] = [yLinesXLeft, yLinesXRight]; - } - - yPath = mainPath(ya, yLinePath, yLinePathFree); - if(extraSubplot && ya.showline && (ya.mirror === 'all' || ya.mirror === 'allticks')) { - yPath += yLinePath(yLinesXLeft) + yLinePath(yLinesXRight); - } - - plotinfo.ylines - .style('stroke-width', ya._lw + 'px') - .call(Color.stroke, ya.showline ? - ya.linecolor : 'rgba(0,0,0,0)'); - } - plotinfo.ylines.attr('d', yPath); - } - - Axes.makeClipPaths(gd); - - return gd._promises.length && Promise.all(gd._promises); -} - -function shouldShowLinesOrTicks(ax, subplot) { - return (ax.ticks || ax.showline) && - (subplot === ax._mainSubplot || ax.mirror === 'all' || ax.mirror === 'allticks'); -} - -/* - * should we draw a line on counterAx at this side of ax? - * It's assumed that counterAx is known to overlay the subplot we're working on - * but it may not be its main axis. - */ -function shouldShowLineThisSide(ax, side, counterAx) { - // does counterAx get a line at all? - if(!counterAx.showline || !counterAx._lw) return false; - - // are we drawing *all* lines for counterAx? - if(counterAx.mirror === 'all' || counterAx.mirror === 'allticks') return true; - - var anchorAx = counterAx._anchorAxis; - - // is this a free axis? free axes can only have a subplot side-line with all(ticks)? mirroring - if(!anchorAx) return false; - - // in order to handle cases where the user forgot to anchor this axis correctly - // (because its default anchor has the same domain on the relevant end) - // check whether the relevant position is the same. - var sideIndex = alignmentConstants.FROM_BL[side]; - if(counterAx.side === side) { - return anchorAx.domain[sideIndex] === ax.domain[sideIndex]; - } - return counterAx.mirror && anchorAx.domain[1 - sideIndex] === ax.domain[1 - sideIndex]; -} - -/* - * Is there another axis intersecting `side` end of `ax`? - * First look at `counterAx` (the axis for this subplot), - * then at all other potential counteraxes on or overlaying this subplot. - * Take the line width from the first one that has a line. - */ -function findCounterAxisLineWidth(ax, side, counterAx, axList) { - if(shouldShowLineThisSide(ax, side, counterAx)) { - return counterAx._lw; - } - for(var i = 0; i < axList.length; i++) { - var axi = axList[i]; - if(axi._mainAxis === counterAx._mainAxis && shouldShowLineThisSide(ax, side, axi)) { - return axi._lw; - } - } - return 0; -} - -exports.drawMainTitle = function(gd) { - var fullLayout = gd._fullLayout; - - var textAnchor = getMainTitleTextAnchor(fullLayout); - var dy = getMainTitleDy(fullLayout); - - Titles.draw(gd, 'gtitle', { - propContainer: fullLayout, - propName: 'title.text', - placeholder: fullLayout._dfltTitle.plot, - attributes: { - x: getMainTitleX(fullLayout, textAnchor), - y: getMainTitleY(fullLayout, dy), - 'text-anchor': textAnchor, - dy: dy - } - }); -}; - -function getMainTitleX(fullLayout, textAnchor) { - var title = fullLayout.title; - var gs = fullLayout._size; - var hPadShift = 0; - - if(textAnchor === SVG_TEXT_ANCHOR_START) { - hPadShift = title.pad.l; - } else if(textAnchor === SVG_TEXT_ANCHOR_END) { - hPadShift = -title.pad.r; - } - - switch(title.xref) { - case 'paper': - return gs.l + gs.w * title.x + hPadShift; - case 'container': - default: - return fullLayout.width * title.x + hPadShift; - } -} - -function getMainTitleY(fullLayout, dy) { - var title = fullLayout.title; - var gs = fullLayout._size; - var vPadShift = 0; - - if(dy === '0em' || !dy) { - vPadShift = -title.pad.b; - } else if(dy === alignmentConstants.CAP_SHIFT + 'em') { - vPadShift = title.pad.t; - } - - if(title.y === 'auto') { - return gs.t / 2; - } else { - switch(title.yref) { - case 'paper': - return gs.t + gs.h - gs.h * title.y + vPadShift; - case 'container': - default: - return fullLayout.height - fullLayout.height * title.y + vPadShift; - } - } -} - -function getMainTitleTextAnchor(fullLayout) { - var title = fullLayout.title; - - var textAnchor = SVG_TEXT_ANCHOR_MIDDLE; - if(Lib.isRightAnchor(title)) { - textAnchor = SVG_TEXT_ANCHOR_END; - } else if(Lib.isLeftAnchor(title)) { - textAnchor = SVG_TEXT_ANCHOR_START; - } - - return textAnchor; -} - -function getMainTitleDy(fullLayout) { - var title = fullLayout.title; - - var dy = '0em'; - if(Lib.isTopAnchor(title)) { - dy = alignmentConstants.CAP_SHIFT + 'em'; - } else if(Lib.isMiddleAnchor(title)) { - dy = alignmentConstants.MID_SHIFT + 'em'; - } - - return dy; -} - -exports.doTraceStyle = function(gd) { - var calcdata = gd.calcdata; - var editStyleCalls = []; - var i; - - for(i = 0; i < calcdata.length; i++) { - var cd = calcdata[i]; - var cd0 = cd[0] || {}; - var trace = cd0.trace || {}; - var _module = trace._module || {}; - - // See if we need to do arraysToCalcdata - // call it regardless of what change we made, in case - // supplyDefaults brought in an array that was already - // in gd.data but not in gd._fullData previously - var arraysToCalcdata = _module.arraysToCalcdata; - if(arraysToCalcdata) arraysToCalcdata(cd, trace); - - var editStyle = _module.editStyle; - if(editStyle) editStyleCalls.push({fn: editStyle, cd0: cd0}); - } - - if(editStyleCalls.length) { - for(i = 0; i < editStyleCalls.length; i++) { - var edit = editStyleCalls[i]; - edit.fn(gd, edit.cd0); - } - clearGlCanvases(gd); - exports.redrawReglTraces(gd); - } - - Plots.style(gd); - Registry.getComponentMethod('legend', 'draw')(gd); - - return Plots.previousPromises(gd); -}; - -exports.doColorBars = function(gd) { - Registry.getComponentMethod('colorbar', 'draw')(gd); - return Plots.previousPromises(gd); -}; - -// force plot() to redo the layout and replot with the modified layout -exports.layoutReplot = function(gd) { - var layout = gd.layout; - gd.layout = undefined; - return Registry.call('plot', gd, '', layout); -}; - -exports.doLegend = function(gd) { - Registry.getComponentMethod('legend', 'draw')(gd); - return Plots.previousPromises(gd); -}; - -exports.doTicksRelayout = function(gd) { - Axes.draw(gd, 'redraw'); - - if(gd._fullLayout._hasOnlyLargeSploms) { - Registry.subplotsRegistry.splom.updateGrid(gd); - clearGlCanvases(gd); - exports.redrawReglTraces(gd); - } - - exports.drawMainTitle(gd); - return Plots.previousPromises(gd); -}; - -exports.doModeBar = function(gd) { - var fullLayout = gd._fullLayout; - - ModeBar.manage(gd); - - for(var i = 0; i < fullLayout._basePlotModules.length; i++) { - var updateFx = fullLayout._basePlotModules[i].updateFx; - if(updateFx) updateFx(gd); - } - - return Plots.previousPromises(gd); -}; - -exports.doCamera = function(gd) { - var fullLayout = gd._fullLayout; - var sceneIds = fullLayout._subplots.gl3d; - - for(var i = 0; i < sceneIds.length; i++) { - var sceneLayout = fullLayout[sceneIds[i]]; - var scene = sceneLayout._scene; - - var cameraData = sceneLayout.camera; - scene.setCamera(cameraData); - } -}; - -exports.drawData = function(gd) { - var fullLayout = gd._fullLayout; - - clearGlCanvases(gd); - - // loop over the base plot modules present on graph - var basePlotModules = fullLayout._basePlotModules; - for(var i = 0; i < basePlotModules.length; i++) { - basePlotModules[i].plot(gd); - } - - exports.redrawReglTraces(gd); - - // styling separate from drawing - Plots.style(gd); - - // show annotations and shapes - Registry.getComponentMethod('shapes', 'draw')(gd); - Registry.getComponentMethod('annotations', 'draw')(gd); - - // Mark the first render as complete - fullLayout._replotting = false; - - return Plots.previousPromises(gd); -}; - -// Draw (or redraw) all regl-based traces in one go, -// useful during drag and selection where buffers of targeted traces are updated, -// but all traces need to be redrawn following clearGlCanvases. -// -// Note that _module.plot for regl trace does NOT draw things -// on the canvas, they only update the buffers. -// Drawing is perform here. -// -// TODO try adding per-subplot option using gl.SCISSOR_TEST for -// non-overlaying, disjoint subplots. -// -// TODO try to include parcoords in here. -// https://github.com/plotly/plotly.js/issues/3069 -exports.redrawReglTraces = function(gd) { - var fullLayout = gd._fullLayout; - - if(fullLayout._has('regl')) { - var fullData = gd._fullData; - var cartesianIds = []; - var polarIds = []; - var i, sp; - - if(fullLayout._hasOnlyLargeSploms) { - fullLayout._splomGrid.draw(); - } - - // N.B. - // - Loop over fullData (not _splomScenes) to preserve splom trace-to-trace ordering - // - Fill list if subplot ids (instead of fullLayout._subplots) to handle cases where all traces - // of a given module are `visible !== true` - for(i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - - if(trace.visible === true && trace._length !== 0) { - if(trace.type === 'splom') { - fullLayout._splomScenes[trace.uid].draw(); - } else if(trace.type === 'scattergl') { - Lib.pushUnique(cartesianIds, trace.xaxis + trace.yaxis); - } else if(trace.type === 'scatterpolargl') { - Lib.pushUnique(polarIds, trace.subplot); - } - } - } - - for(i = 0; i < cartesianIds.length; i++) { - sp = fullLayout._plots[cartesianIds[i]]; - if(sp._scene) sp._scene.draw(); - } - - for(i = 0; i < polarIds.length; i++) { - sp = fullLayout[polarIds[i]]._subplot; - if(sp._scene) sp._scene.draw(); - } - } -}; - -exports.doAutoRangeAndConstraints = function(gd) { - var fullLayout = gd._fullLayout; - var axList = Axes.list(gd, '', true); - var matchGroups = fullLayout._axisMatchGroups || []; - var ax; - var axRng; - - for(var i = 0; i < axList.length; i++) { - ax = axList[i]; - cleanAxisConstraints(gd, ax); - doAutoRange(gd, ax); - } - - enforceAxisConstraints(gd); - - groupLoop: - for(var j = 0; j < matchGroups.length; j++) { - var group = matchGroups[j]; - var rng = null; - var id; - - for(id in group) { - ax = Axes.getFromId(gd, id); - if(ax.autorange === false) continue groupLoop; - - axRng = Lib.simpleMap(ax.range, ax.r2l); - if(rng) { - if(rng[0] < rng[1]) { - rng[0] = Math.min(rng[0], axRng[0]); - rng[1] = Math.max(rng[1], axRng[1]); - } else { - rng[0] = Math.max(rng[0], axRng[0]); - rng[1] = Math.min(rng[1], axRng[1]); - } - } else { - rng = axRng; - } - } - - for(id in group) { - ax = Axes.getFromId(gd, id); - ax.range = Lib.simpleMap(rng, ax.l2r); - ax._input.range = ax.range.slice(); - ax.setScale(); - } - } -}; - -// An initial paint must be completed before these components can be -// correctly sized and the whole plot re-margined. fullLayout._replotting must -// be set to false before these will work properly. -exports.finalDraw = function(gd) { - Registry.getComponentMethod('shapes', 'draw')(gd); - Registry.getComponentMethod('images', 'draw')(gd); - Registry.getComponentMethod('annotations', 'draw')(gd); - // TODO: rangesliders really belong in marginPushers but they need to be - // drawn after data - can we at least get the margin pushing part separated - // out and done earlier? - Registry.getComponentMethod('rangeslider', 'draw')(gd); - // TODO: rangeselector only needs to be here (in addition to drawMarginPushers) - // because the margins need to be fully determined before we can call - // autorange and update axis ranges (which rangeselector needs to know which - // button is active). Can we break out its automargin step from its draw step? - Registry.getComponentMethod('rangeselector', 'draw')(gd); -}; - -exports.drawMarginPushers = function(gd) { - Registry.getComponentMethod('legend', 'draw')(gd); - Registry.getComponentMethod('rangeselector', 'draw')(gd); - Registry.getComponentMethod('sliders', 'draw')(gd); - Registry.getComponentMethod('updatemenus', 'draw')(gd); - Registry.getComponentMethod('colorbar', 'draw')(gd); -}; - -},{"../components/color":593,"../components/drawing":614,"../components/modebar":652,"../components/titles":681,"../constants/alignment":688,"../lib":719,"../lib/clear_gl_canvases":704,"../plots/cartesian/autorange":766,"../plots/cartesian/axes":767,"../plots/cartesian/constraints":774,"../plots/plots":828,"../registry":847,"d3":163}],759:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../lib'); -var isPlainObject = Lib.isPlainObject; -var PlotSchema = _dereq_('./plot_schema'); -var Plots = _dereq_('../plots/plots'); -var plotAttributes = _dereq_('../plots/attributes'); -var Template = _dereq_('./plot_template'); -var dfltConfig = _dereq_('./plot_config').dfltConfig; - -/** - * Plotly.makeTemplate: create a template off an existing figure to reuse - * style attributes on other figures. - * - * Note: separated from the rest of templates because otherwise we get circular - * references due to PlotSchema. - * - * @param {object|DOM element|string} figure: The figure to base the template on - * should contain a trace array `figure.data` - * and a layout object `figure.layout` - * @returns {object} template: the extracted template - can then be used as - * `layout.template` in another figure. - */ -exports.makeTemplate = function(figure) { - figure = Lib.isPlainObject(figure) ? figure : Lib.getGraphDiv(figure); - figure = Lib.extendDeep({_context: dfltConfig}, {data: figure.data, layout: figure.layout}); - Plots.supplyDefaults(figure); - var data = figure.data || []; - var layout = figure.layout || {}; - // copy over a few items to help follow the schema - layout._basePlotModules = figure._fullLayout._basePlotModules; - layout._modules = figure._fullLayout._modules; - - var template = { - data: {}, - layout: {} - }; - - /* - * Note: we do NOT validate template values, we just take what's in the - * user inputs data and layout, not the validated values in fullData and - * fullLayout. Even if we were to validate here, there's no guarantee that - * these values would still be valid when applied to a new figure, which - * may contain different trace modes, different axes, etc. So it's - * important that when applying a template we still validate the template - * values, rather than just using them as defaults. - */ - - data.forEach(function(trace) { - // TODO: What if no style info is extracted for this trace. We may - // not want an empty object as the null value. - // TODO: allow transforms to contribute to templates? - // as it stands they are ignored, which may be for the best... - - var traceTemplate = {}; - walkStyleKeys(trace, traceTemplate, getTraceInfo.bind(null, trace)); - - var traceType = Lib.coerce(trace, {}, plotAttributes, 'type'); - var typeTemplates = template.data[traceType]; - if(!typeTemplates) typeTemplates = template.data[traceType] = []; - typeTemplates.push(traceTemplate); - }); - - walkStyleKeys(layout, template.layout, getLayoutInfo.bind(null, layout)); - - /* - * Compose the new template with an existing one to the same effect - * - * NOTE: there's a possibility of slightly different behavior: if the plot - * has an invalid value and the old template has a valid value for the same - * attribute, the plot will use the old template value but this routine - * will pull the invalid value (resulting in the original default). - * In the general case it's not possible to solve this with a single value, - * since valid options can be context-dependent. It could be solved with - * a *list* of values, but that would be huge complexity for little gain. - */ - delete template.layout.template; - var oldTemplate = layout.template; - if(isPlainObject(oldTemplate)) { - var oldLayoutTemplate = oldTemplate.layout; - - var i, traceType, oldTypeTemplates, oldTypeLen, typeTemplates, typeLen; - - if(isPlainObject(oldLayoutTemplate)) { - mergeTemplates(oldLayoutTemplate, template.layout); - } - var oldDataTemplate = oldTemplate.data; - if(isPlainObject(oldDataTemplate)) { - for(traceType in template.data) { - oldTypeTemplates = oldDataTemplate[traceType]; - if(Array.isArray(oldTypeTemplates)) { - typeTemplates = template.data[traceType]; - typeLen = typeTemplates.length; - oldTypeLen = oldTypeTemplates.length; - for(i = 0; i < typeLen; i++) { - mergeTemplates(oldTypeTemplates[i % oldTypeLen], typeTemplates[i]); - } - for(i = typeLen; i < oldTypeLen; i++) { - typeTemplates.push(Lib.extendDeep({}, oldTypeTemplates[i])); - } - } - } - for(traceType in oldDataTemplate) { - if(!(traceType in template.data)) { - template.data[traceType] = Lib.extendDeep([], oldDataTemplate[traceType]); - } - } - } - } - - return template; -}; - -function mergeTemplates(oldTemplate, newTemplate) { - // we don't care about speed here, just make sure we have a totally - // distinct object from the previous template - oldTemplate = Lib.extendDeep({}, oldTemplate); - - // sort keys so we always get annotationdefaults before annotations etc - // so arrayTemplater will work right - var oldKeys = Object.keys(oldTemplate).sort(); - var i, j; - - function mergeOne(oldVal, newVal, key) { - if(isPlainObject(newVal) && isPlainObject(oldVal)) { - mergeTemplates(oldVal, newVal); - } else if(Array.isArray(newVal) && Array.isArray(oldVal)) { - // Note: omitted `inclusionAttr` from arrayTemplater here, - // it's irrelevant as we only want the resulting `_template`. - var templater = Template.arrayTemplater({_template: oldTemplate}, key); - for(j = 0; j < newVal.length; j++) { - var item = newVal[j]; - var oldItem = templater.newItem(item)._template; - if(oldItem) mergeTemplates(oldItem, item); - } - var defaultItems = templater.defaultItems(); - for(j = 0; j < defaultItems.length; j++) newVal.push(defaultItems[j]._template); - - // templateitemname only applies to receiving plots - for(j = 0; j < newVal.length; j++) delete newVal[j].templateitemname; - } - } - - for(i = 0; i < oldKeys.length; i++) { - var key = oldKeys[i]; - var oldVal = oldTemplate[key]; - if(key in newTemplate) { - mergeOne(oldVal, newTemplate[key], key); - } else newTemplate[key] = oldVal; - - // if this is a base key from the old template (eg xaxis), look for - // extended keys (eg xaxis2) in the new template to merge into - if(getBaseKey(key) === key) { - for(var key2 in newTemplate) { - var baseKey2 = getBaseKey(key2); - if(key2 !== baseKey2 && baseKey2 === key && !(key2 in oldTemplate)) { - mergeOne(oldVal, newTemplate[key2], key); - } - } - } - } -} - -function getBaseKey(key) { - return key.replace(/[0-9]+$/, ''); -} - -function walkStyleKeys(parent, templateOut, getAttributeInfo, path, basePath) { - var pathAttr = basePath && getAttributeInfo(basePath); - for(var key in parent) { - var child = parent[key]; - var nextPath = getNextPath(parent, key, path); - var nextBasePath = getNextPath(parent, key, basePath); - var attr = getAttributeInfo(nextBasePath); - if(!attr) { - var baseKey = getBaseKey(key); - if(baseKey !== key) { - nextBasePath = getNextPath(parent, baseKey, basePath); - attr = getAttributeInfo(nextBasePath); - } - } - - // we'll get an attr if path starts with a valid part, then has an - // invalid ending. Make sure we got all the way to the end. - if(pathAttr && (pathAttr === attr)) continue; - - if(!attr || attr._noTemplating || - attr.valType === 'data_array' || - (attr.arrayOk && Array.isArray(child)) - ) { - continue; - } - - if(!attr.valType && isPlainObject(child)) { - walkStyleKeys(child, templateOut, getAttributeInfo, nextPath, nextBasePath); - } else if(attr._isLinkedToArray && Array.isArray(child)) { - var dfltDone = false; - var namedIndex = 0; - var usedNames = {}; - for(var i = 0; i < child.length; i++) { - var item = child[i]; - if(isPlainObject(item)) { - var name = item.name; - if(name) { - if(!usedNames[name]) { - // named array items: allow all attributes except data arrays - walkStyleKeys(item, templateOut, getAttributeInfo, - getNextPath(child, namedIndex, nextPath), - getNextPath(child, namedIndex, nextBasePath)); - namedIndex++; - usedNames[name] = 1; - } - } else if(!dfltDone) { - var dfltKey = Template.arrayDefaultKey(key); - var dfltPath = getNextPath(parent, dfltKey, path); - - // getAttributeInfo will fail if we try to use dfltKey directly. - // Instead put this item into the next array element, then - // pull it out and move it to dfltKey. - var pathInArray = getNextPath(child, namedIndex, nextPath); - walkStyleKeys(item, templateOut, getAttributeInfo, pathInArray, - getNextPath(child, namedIndex, nextBasePath)); - var itemPropInArray = Lib.nestedProperty(templateOut, pathInArray); - var dfltProp = Lib.nestedProperty(templateOut, dfltPath); - dfltProp.set(itemPropInArray.get()); - itemPropInArray.set(null); - - dfltDone = true; - } - } - } - } else { - var templateProp = Lib.nestedProperty(templateOut, nextPath); - templateProp.set(child); - } - } -} - -function getLayoutInfo(layout, path) { - return PlotSchema.getLayoutValObject( - layout, Lib.nestedProperty({}, path).parts - ); -} - -function getTraceInfo(trace, path) { - return PlotSchema.getTraceValObject( - trace, Lib.nestedProperty({}, path).parts - ); -} - -function getNextPath(parent, key, path) { - var nextPath; - if(!path) nextPath = key; - else if(Array.isArray(parent)) nextPath = path + '[' + key + ']'; - else nextPath = path + '.' + key; - - return nextPath; -} - -/** - * validateTemplate: Test for consistency between the given figure and - * a template, either already included in the figure or given separately. - * Note that not every issue we identify here is necessarily a problem, - * it depends on what you're using the template for. - * - * @param {object|DOM element} figure: the plot, with {data, layout} members, - * to test the template against - * @param {Optional(object)} template: the template, with its own {data, layout}, - * to test. If omitted, we will look for a template already attached as the - * plot's `layout.template` attribute. - * - * @returns {array} array of error objects each containing: - * - {string} code - * error code ('missing', 'unused', 'reused', 'noLayout', 'noData') - * - {string} msg - * a full readable description of the issue. - */ -exports.validateTemplate = function(figureIn, template) { - var figure = Lib.extendDeep({}, { - _context: dfltConfig, - data: figureIn.data, - layout: figureIn.layout - }); - var layout = figure.layout || {}; - if(!isPlainObject(template)) template = layout.template || {}; - var layoutTemplate = template.layout; - var dataTemplate = template.data; - var errorList = []; - - figure.layout = layout; - figure.layout.template = template; - Plots.supplyDefaults(figure); - - var fullLayout = figure._fullLayout; - var fullData = figure._fullData; - - var layoutPaths = {}; - function crawlLayoutForContainers(obj, paths) { - for(var key in obj) { - if(key.charAt(0) !== '_' && isPlainObject(obj[key])) { - var baseKey = getBaseKey(key); - var nextPaths = []; - var i; - for(i = 0; i < paths.length; i++) { - nextPaths.push(getNextPath(obj, key, paths[i])); - if(baseKey !== key) nextPaths.push(getNextPath(obj, baseKey, paths[i])); - } - for(i = 0; i < nextPaths.length; i++) { - layoutPaths[nextPaths[i]] = 1; - } - crawlLayoutForContainers(obj[key], nextPaths); - } - } - } - - function crawlLayoutTemplateForContainers(obj, path) { - for(var key in obj) { - if(key.indexOf('defaults') === -1 && isPlainObject(obj[key])) { - var nextPath = getNextPath(obj, key, path); - if(layoutPaths[nextPath]) { - crawlLayoutTemplateForContainers(obj[key], nextPath); - } else { - errorList.push({code: 'unused', path: nextPath}); - } - } - } - } - - if(!isPlainObject(layoutTemplate)) { - errorList.push({code: 'layout'}); - } else { - crawlLayoutForContainers(fullLayout, ['layout']); - crawlLayoutTemplateForContainers(layoutTemplate, 'layout'); - } - - if(!isPlainObject(dataTemplate)) { - errorList.push({code: 'data'}); - } else { - var typeCount = {}; - var traceType; - for(var i = 0; i < fullData.length; i++) { - var fullTrace = fullData[i]; - traceType = fullTrace.type; - typeCount[traceType] = (typeCount[traceType] || 0) + 1; - if(!fullTrace._fullInput._template) { - // this takes care of the case of traceType in the data but not - // the template - errorList.push({ - code: 'missing', - index: fullTrace._fullInput.index, - traceType: traceType - }); - } - } - for(traceType in dataTemplate) { - var templateCount = dataTemplate[traceType].length; - var dataCount = typeCount[traceType] || 0; - if(templateCount > dataCount) { - errorList.push({ - code: 'unused', - traceType: traceType, - templateCount: templateCount, - dataCount: dataCount - }); - } else if(dataCount > templateCount) { - errorList.push({ - code: 'reused', - traceType: traceType, - templateCount: templateCount, - dataCount: dataCount - }); - } - } - } - - // _template: false is when someone tried to modify an array item - // but there was no template with matching name - function crawlForMissingTemplates(obj, path) { - for(var key in obj) { - if(key.charAt(0) === '_') continue; - var val = obj[key]; - var nextPath = getNextPath(obj, key, path); - if(isPlainObject(val)) { - if(Array.isArray(obj) && val._template === false && val.templateitemname) { - errorList.push({ - code: 'missing', - path: nextPath, - templateitemname: val.templateitemname - }); - } - crawlForMissingTemplates(val, nextPath); - } else if(Array.isArray(val) && hasPlainObject(val)) { - crawlForMissingTemplates(val, nextPath); - } - } - } - crawlForMissingTemplates({data: fullData, layout: fullLayout}, ''); - - if(errorList.length) return errorList.map(format); -}; - -function hasPlainObject(arr) { - for(var i = 0; i < arr.length; i++) { - if(isPlainObject(arr[i])) return true; - } -} - -function format(opts) { - var msg; - switch(opts.code) { - case 'data': - msg = 'The template has no key data.'; - break; - case 'layout': - msg = 'The template has no key layout.'; - break; - case 'missing': - if(opts.path) { - msg = 'There are no templates for item ' + opts.path + - ' with name ' + opts.templateitemname; - } else { - msg = 'There are no templates for trace ' + opts.index + - ', of type ' + opts.traceType + '.'; - } - break; - case 'unused': - if(opts.path) { - msg = 'The template item at ' + opts.path + - ' was not used in constructing the plot.'; - } else if(opts.dataCount) { - msg = 'Some of the templates of type ' + opts.traceType + - ' were not used. The template has ' + opts.templateCount + - ' traces, the data only has ' + opts.dataCount + - ' of this type.'; - } else { - msg = 'The template has ' + opts.templateCount + - ' traces of type ' + opts.traceType + - ' but there are none in the data.'; - } - break; - case 'reused': - msg = 'Some of the templates of type ' + opts.traceType + - ' were used more than once. The template has ' + - opts.templateCount + ' traces, the data has ' + - opts.dataCount + ' of this type.'; - break; - } - opts.msg = msg; - - return opts; -} - -},{"../lib":719,"../plots/attributes":764,"../plots/plots":828,"./plot_config":755,"./plot_schema":756,"./plot_template":757}],760:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var plotApi = _dereq_('./plot_api'); -var Lib = _dereq_('../lib'); - -var helpers = _dereq_('../snapshot/helpers'); -var toSVG = _dereq_('../snapshot/tosvg'); -var svgToImg = _dereq_('../snapshot/svgtoimg'); - -var attrs = { - format: { - valType: 'enumerated', - values: ['png', 'jpeg', 'webp', 'svg'], - dflt: 'png', - - }, - width: { - valType: 'number', - min: 1, - - }, - height: { - valType: 'number', - min: 1, - - }, - scale: { - valType: 'number', - min: 0, - dflt: 1, - - }, - setBackground: { - valType: 'any', - dflt: false, - - }, - imageDataOnly: { - valType: 'boolean', - dflt: false, - - } -}; - -/** Plotly.toImage - * - * @param {object | string | HTML div} gd - * can either be a data/layout/config object - * or an existing graph
- * or an id to an existing graph
- * @param {object} opts (see above) - * @return {promise} - */ -function toImage(gd, opts) { - opts = opts || {}; - - var data; - var layout; - var config; - var fullLayout; - - if(Lib.isPlainObject(gd)) { - data = gd.data || []; - layout = gd.layout || {}; - config = gd.config || {}; - fullLayout = {}; - } else { - gd = Lib.getGraphDiv(gd); - data = Lib.extendDeep([], gd.data); - layout = Lib.extendDeep({}, gd.layout); - config = gd._context; - fullLayout = gd._fullLayout || {}; - } - - function isImpliedOrValid(attr) { - return !(attr in opts) || Lib.validate(opts[attr], attrs[attr]); - } - - if((!isImpliedOrValid('width') && opts.width !== null) || - (!isImpliedOrValid('height') && opts.height !== null)) { - throw new Error('Height and width should be pixel values.'); - } - - if(!isImpliedOrValid('format')) { - throw new Error('Image format is not jpeg, png, svg or webp.'); - } - - var fullOpts = {}; - - function coerce(attr, dflt) { - return Lib.coerce(opts, fullOpts, attrs, attr, dflt); - } - - var format = coerce('format'); - var width = coerce('width'); - var height = coerce('height'); - var scale = coerce('scale'); - var setBackground = coerce('setBackground'); - var imageDataOnly = coerce('imageDataOnly'); - - // put the cloned div somewhere off screen before attaching to DOM - var clonedGd = document.createElement('div'); - clonedGd.style.position = 'absolute'; - clonedGd.style.left = '-5000px'; - document.body.appendChild(clonedGd); - - // extend layout with image options - var layoutImage = Lib.extendFlat({}, layout); - if(width) { - layoutImage.width = width; - } else if(opts.width === null && isNumeric(fullLayout.width)) { - layoutImage.width = fullLayout.width; - } - if(height) { - layoutImage.height = height; - } else if(opts.height === null && isNumeric(fullLayout.height)) { - layoutImage.height = fullLayout.height; - } - - // extend config for static plot - var configImage = Lib.extendFlat({}, config, { - _exportedPlot: true, - staticPlot: true, - setBackground: setBackground - }); - - var redrawFunc = helpers.getRedrawFunc(clonedGd); - - function wait() { - return new Promise(function(resolve) { - setTimeout(resolve, helpers.getDelay(clonedGd._fullLayout)); - }); - } - - function convert() { - return new Promise(function(resolve, reject) { - var svg = toSVG(clonedGd, format, scale); - var width = clonedGd._fullLayout.width; - var height = clonedGd._fullLayout.height; - - plotApi.purge(clonedGd); - document.body.removeChild(clonedGd); - - if(format === 'svg') { - if(imageDataOnly) { - return resolve(svg); - } else { - return resolve(helpers.encodeSVG(svg)); - } - } - - var canvas = document.createElement('canvas'); - canvas.id = Lib.randstr(); - - svgToImg({ - format: format, - width: width, - height: height, - scale: scale, - canvas: canvas, - svg: svg, - // ask svgToImg to return a Promise - // rather than EventEmitter - // leave EventEmitter for backward - // compatibility - promise: true - }) - .then(resolve) - .catch(reject); - }); - } - - function urlToImageData(url) { - if(imageDataOnly) { - return url.replace(helpers.IMAGE_URL_PREFIX, ''); - } else { - return url; - } - } - - return new Promise(function(resolve, reject) { - plotApi.plot(clonedGd, data, layoutImage, configImage) - .then(redrawFunc) - .then(wait) - .then(convert) - .then(function(url) { resolve(urlToImageData(url)); }) - .catch(function(err) { reject(err); }); - }); -} - -module.exports = toImage; - -},{"../lib":719,"../snapshot/helpers":851,"../snapshot/svgtoimg":853,"../snapshot/tosvg":855,"./plot_api":754,"fast-isnumeric":225}],761:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); -var Plots = _dereq_('../plots/plots'); -var PlotSchema = _dereq_('./plot_schema'); -var dfltConfig = _dereq_('./plot_config').dfltConfig; - -var isPlainObject = Lib.isPlainObject; -var isArray = Array.isArray; -var isArrayOrTypedArray = Lib.isArrayOrTypedArray; - -/** - * Validate a data array and layout object. - * - * @param {array} data - * @param {object} layout - * - * @return {array} array of error objects each containing: - * - {string} code - * error code ('object', 'array', 'schema', 'unused', 'invisible' or 'value') - * - {string} container - * container where the error occurs ('data' or 'layout') - * - {number} trace - * trace index of the 'data' container where the error occurs - * - {array} path - * nested path to the key that causes the error - * - {string} astr - * attribute string variant of 'path' compatible with Plotly.restyle and - * Plotly.relayout. - * - {string} msg - * error message (shown in console in logger config argument is enable) - */ -module.exports = function validate(data, layout) { - var schema = PlotSchema.get(); - var errorList = []; - var gd = {_context: Lib.extendFlat({}, dfltConfig)}; - - var dataIn, layoutIn; - - if(isArray(data)) { - gd.data = Lib.extendDeep([], data); - dataIn = data; - } else { - gd.data = []; - dataIn = []; - errorList.push(format('array', 'data')); - } - - if(isPlainObject(layout)) { - gd.layout = Lib.extendDeep({}, layout); - layoutIn = layout; - } else { - gd.layout = {}; - layoutIn = {}; - if(arguments.length > 1) { - errorList.push(format('object', 'layout')); - } - } - - // N.B. dataIn and layoutIn are in general not the same as - // gd.data and gd.layout after supplyDefaults as some attributes - // in gd.data and gd.layout (still) get mutated during this step. - - Plots.supplyDefaults(gd); - - var dataOut = gd._fullData; - var len = dataIn.length; - - for(var i = 0; i < len; i++) { - var traceIn = dataIn[i]; - var base = ['data', i]; - - if(!isPlainObject(traceIn)) { - errorList.push(format('object', base)); - continue; - } - - var traceOut = dataOut[i]; - var traceType = traceOut.type; - var traceSchema = schema.traces[traceType].attributes; - - // PlotSchema does something fancy with trace 'type', reset it here - // to make the trace schema compatible with Lib.validate. - traceSchema.type = { - valType: 'enumerated', - values: [traceType] - }; - - if(traceOut.visible === false && traceIn.visible !== false) { - errorList.push(format('invisible', base)); - } - - crawl(traceIn, traceOut, traceSchema, errorList, base); - - var transformsIn = traceIn.transforms; - var transformsOut = traceOut.transforms; - - if(transformsIn) { - if(!isArray(transformsIn)) { - errorList.push(format('array', base, ['transforms'])); - } - - base.push('transforms'); - - for(var j = 0; j < transformsIn.length; j++) { - var path = ['transforms', j]; - var transformType = transformsIn[j].type; - - if(!isPlainObject(transformsIn[j])) { - errorList.push(format('object', base, path)); - continue; - } - - var transformSchema = schema.transforms[transformType] ? - schema.transforms[transformType].attributes : - {}; - - // add 'type' to transform schema to validate the transform type - transformSchema.type = { - valType: 'enumerated', - values: Object.keys(schema.transforms) - }; - - crawl(transformsIn[j], transformsOut[j], transformSchema, errorList, base, path); - } - } - } - - var layoutOut = gd._fullLayout; - var layoutSchema = fillLayoutSchema(schema, dataOut); - - crawl(layoutIn, layoutOut, layoutSchema, errorList, 'layout'); - - // return undefined if no validation errors were found - return (errorList.length === 0) ? void(0) : errorList; -}; - -function crawl(objIn, objOut, schema, list, base, path) { - path = path || []; - - var keys = Object.keys(objIn); - - for(var i = 0; i < keys.length; i++) { - var k = keys[i]; - - // transforms are handled separately - if(k === 'transforms') continue; - - var p = path.slice(); - p.push(k); - - var valIn = objIn[k]; - var valOut = objOut[k]; - - var nestedSchema = getNestedSchema(schema, k); - var isInfoArray = (nestedSchema || {}).valType === 'info_array'; - var isColorscale = (nestedSchema || {}).valType === 'colorscale'; - var items = (nestedSchema || {}).items; - - if(!isInSchema(schema, k)) { - list.push(format('schema', base, p)); - } else if(isPlainObject(valIn) && isPlainObject(valOut)) { - crawl(valIn, valOut, nestedSchema, list, base, p); - } else if(isInfoArray && isArray(valIn)) { - if(valIn.length > valOut.length) { - list.push(format('unused', base, p.concat(valOut.length))); - } - var len = valOut.length; - var arrayItems = Array.isArray(items); - if(arrayItems) len = Math.min(len, items.length); - var m, n, item, valInPart, valOutPart; - if(nestedSchema.dimensions === 2) { - for(n = 0; n < len; n++) { - if(isArray(valIn[n])) { - if(valIn[n].length > valOut[n].length) { - list.push(format('unused', base, p.concat(n, valOut[n].length))); - } - var len2 = valOut[n].length; - for(m = 0; m < (arrayItems ? Math.min(len2, items[n].length) : len2); m++) { - item = arrayItems ? items[n][m] : items; - valInPart = valIn[n][m]; - valOutPart = valOut[n][m]; - if(!Lib.validate(valInPart, item)) { - list.push(format('value', base, p.concat(n, m), valInPart)); - } else if(valOutPart !== valInPart && valOutPart !== +valInPart) { - list.push(format('dynamic', base, p.concat(n, m), valInPart, valOutPart)); - } - } - } else { - list.push(format('array', base, p.concat(n), valIn[n])); - } - } - } else { - for(n = 0; n < len; n++) { - item = arrayItems ? items[n] : items; - valInPart = valIn[n]; - valOutPart = valOut[n]; - if(!Lib.validate(valInPart, item)) { - list.push(format('value', base, p.concat(n), valInPart)); - } else if(valOutPart !== valInPart && valOutPart !== +valInPart) { - list.push(format('dynamic', base, p.concat(n), valInPart, valOutPart)); - } - } - } - } else if(nestedSchema.items && !isInfoArray && isArray(valIn)) { - var _nestedSchema = items[Object.keys(items)[0]]; - var indexList = []; - - var j, _p; - - // loop over valOut items while keeping track of their - // corresponding input container index (given by _index) - for(j = 0; j < valOut.length; j++) { - var _index = valOut[j]._index || j; - - _p = p.slice(); - _p.push(_index); - - if(isPlainObject(valIn[_index]) && isPlainObject(valOut[j])) { - indexList.push(_index); - var valInj = valIn[_index]; - var valOutj = valOut[j]; - if(isPlainObject(valInj) && valInj.visible !== false && valOutj.visible === false) { - list.push(format('invisible', base, _p)); - } else crawl(valInj, valOutj, _nestedSchema, list, base, _p); - } - } - - // loop over valIn to determine where it went wrong for some items - for(j = 0; j < valIn.length; j++) { - _p = p.slice(); - _p.push(j); - - if(!isPlainObject(valIn[j])) { - list.push(format('object', base, _p, valIn[j])); - } else if(indexList.indexOf(j) === -1) { - list.push(format('unused', base, _p)); - } - } - } else if(!isPlainObject(valIn) && isPlainObject(valOut)) { - list.push(format('object', base, p, valIn)); - } else if(!isArrayOrTypedArray(valIn) && isArrayOrTypedArray(valOut) && !isInfoArray && !isColorscale) { - list.push(format('array', base, p, valIn)); - } else if(!(k in objOut)) { - list.push(format('unused', base, p, valIn)); - } else if(!Lib.validate(valIn, nestedSchema)) { - list.push(format('value', base, p, valIn)); - } else if(nestedSchema.valType === 'enumerated' && - ((nestedSchema.coerceNumber && valIn !== +valOut) || valIn !== valOut) - ) { - list.push(format('dynamic', base, p, valIn, valOut)); - } - } - - return list; -} - -// the 'full' layout schema depends on the traces types presents -function fillLayoutSchema(schema, dataOut) { - var layoutSchema = schema.layout.layoutAttributes; - - for(var i = 0; i < dataOut.length; i++) { - var traceOut = dataOut[i]; - var traceSchema = schema.traces[traceOut.type]; - var traceLayoutAttr = traceSchema.layoutAttributes; - - if(traceLayoutAttr) { - if(traceOut.subplot) { - Lib.extendFlat(layoutSchema[traceSchema.attributes.subplot.dflt], traceLayoutAttr); - } else { - Lib.extendFlat(layoutSchema, traceLayoutAttr); - } - } - } - - return layoutSchema; -} - -// validation error codes -var code2msgFunc = { - object: function(base, astr) { - var prefix; - - if(base === 'layout' && astr === '') prefix = 'The layout argument'; - else if(base[0] === 'data' && astr === '') { - prefix = 'Trace ' + base[1] + ' in the data argument'; - } else prefix = inBase(base) + 'key ' + astr; - - return prefix + ' must be linked to an object container'; - }, - array: function(base, astr) { - var prefix; - - if(base === 'data') prefix = 'The data argument'; - else prefix = inBase(base) + 'key ' + astr; - - return prefix + ' must be linked to an array container'; - }, - schema: function(base, astr) { - return inBase(base) + 'key ' + astr + ' is not part of the schema'; - }, - unused: function(base, astr, valIn) { - var target = isPlainObject(valIn) ? 'container' : 'key'; - - return inBase(base) + target + ' ' + astr + ' did not get coerced'; - }, - dynamic: function(base, astr, valIn, valOut) { - return [ - inBase(base) + 'key', - astr, - '(set to \'' + valIn + '\')', - 'got reset to', - '\'' + valOut + '\'', - 'during defaults.' - ].join(' '); - }, - invisible: function(base, astr) { - return ( - astr ? (inBase(base) + 'item ' + astr) : ('Trace ' + base[1]) - ) + ' got defaulted to be not visible'; - }, - value: function(base, astr, valIn) { - return [ - inBase(base) + 'key ' + astr, - 'is set to an invalid value (' + valIn + ')' - ].join(' '); - } -}; - -function inBase(base) { - if(isArray(base)) return 'In data trace ' + base[1] + ', '; - - return 'In ' + base + ', '; -} - -function format(code, base, path, valIn, valOut) { - path = path || ''; - - var container, trace; - - // container is either 'data' or 'layout - // trace is the trace index if 'data', null otherwise - - if(isArray(base)) { - container = base[0]; - trace = base[1]; - } else { - container = base; - trace = null; - } - - var astr = convertPathToAttributeString(path); - var msg = code2msgFunc[code](base, astr, valIn, valOut); - - // log to console if logger config option is enabled - Lib.log(msg); - - return { - code: code, - container: container, - trace: trace, - path: path, - astr: astr, - msg: msg - }; -} - -function isInSchema(schema, key) { - var parts = splitKey(key); - var keyMinusId = parts.keyMinusId; - var id = parts.id; - - if((keyMinusId in schema) && schema[keyMinusId]._isSubplotObj && id) { - return true; - } - - return (key in schema); -} - -function getNestedSchema(schema, key) { - if(key in schema) return schema[key]; - - var parts = splitKey(key); - - return schema[parts.keyMinusId]; -} - -var idRegex = Lib.counterRegex('([a-z]+)'); - -function splitKey(key) { - var idMatch = key.match(idRegex); - - return { - keyMinusId: idMatch && idMatch[1], - id: idMatch && idMatch[2] - }; -} - -function convertPathToAttributeString(path) { - if(!isArray(path)) return String(path); - - var astr = ''; - - for(var i = 0; i < path.length; i++) { - var p = path[i]; - - if(typeof p === 'number') { - astr = astr.substr(0, astr.length - 1) + '[' + p + ']'; - } else { - astr += p; - } - - if(i < path.length - 1) astr += '.'; - } - - return astr; -} - -},{"../lib":719,"../plots/plots":828,"./plot_config":755,"./plot_schema":756}],762:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - mode: { - valType: 'enumerated', - dflt: 'afterall', - - values: ['immediate', 'next', 'afterall'], - - }, - direction: { - valType: 'enumerated', - - values: ['forward', 'reverse'], - dflt: 'forward', - - }, - fromcurrent: { - valType: 'boolean', - dflt: false, - - - }, - frame: { - duration: { - valType: 'number', - - min: 0, - dflt: 500, - - }, - redraw: { - valType: 'boolean', - - dflt: true, - - }, - }, - transition: { - duration: { - valType: 'number', - - min: 0, - dflt: 500, - editType: 'none', - - }, - easing: { - valType: 'enumerated', - dflt: 'cubic-in-out', - values: [ - 'linear', - 'quad', - 'cubic', - 'sin', - 'exp', - 'circle', - 'elastic', - 'back', - 'bounce', - 'linear-in', - 'quad-in', - 'cubic-in', - 'sin-in', - 'exp-in', - 'circle-in', - 'elastic-in', - 'back-in', - 'bounce-in', - 'linear-out', - 'quad-out', - 'cubic-out', - 'sin-out', - 'exp-out', - 'circle-out', - 'elastic-out', - 'back-out', - 'bounce-out', - 'linear-in-out', - 'quad-in-out', - 'cubic-in-out', - 'sin-in-out', - 'exp-in-out', - 'circle-in-out', - 'elastic-in-out', - 'back-in-out', - 'bounce-in-out' - ], - - editType: 'none', - - }, - ordering: { - valType: 'enumerated', - values: ['layout first', 'traces first'], - dflt: 'layout first', - - editType: 'none', - - } - } -}; - -},{}],763:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); -var Template = _dereq_('../plot_api/plot_template'); - -/** Convenience wrapper for making array container logic DRY and consistent - * - * @param {object} parentObjIn - * user input object where the container in question is linked - * (i.e. either a user trace object or the user layout object) - * - * @param {object} parentObjOut - * full object where the coerced container will be linked - * (i.e. either a full trace object or the full layout object) - * - * @param {object} opts - * options object: - * - name {string} - * name of the key linking the container in question - * - inclusionAttr {string} - * name of the item attribute for inclusion/exclusion. Default is 'visible'. - * Since inclusion is true, use eg 'enabled' instead of 'disabled'. - * - handleItemDefaults {function} - * defaults method to be called on each item in the array container in question - * - * Its arguments are: - * - itemIn {object} item in user layout - * - itemOut {object} item in full layout - * - parentObj {object} (as in closure) - * - opts {object} (as in closure) - * N.B. - * - * - opts is passed to handleItemDefaults so it can also store - * links to supplementary data (e.g. fullData for layout components) - * - */ -module.exports = function handleArrayContainerDefaults(parentObjIn, parentObjOut, opts) { - var name = opts.name; - var inclusionAttr = opts.inclusionAttr || 'visible'; - - var previousContOut = parentObjOut[name]; - - var contIn = Lib.isArrayOrTypedArray(parentObjIn[name]) ? parentObjIn[name] : []; - var contOut = parentObjOut[name] = []; - var templater = Template.arrayTemplater(parentObjOut, name, inclusionAttr); - var i, itemOut; - - for(i = 0; i < contIn.length; i++) { - var itemIn = contIn[i]; - - if(!Lib.isPlainObject(itemIn)) { - itemOut = templater.newItem({}); - itemOut[inclusionAttr] = false; - } else { - itemOut = templater.newItem(itemIn); - } - - itemOut._index = i; - - if(itemOut[inclusionAttr] !== false) { - opts.handleItemDefaults(itemIn, itemOut, parentObjOut, opts); - } - - contOut.push(itemOut); - } - - var defaultItems = templater.defaultItems(); - for(i = 0; i < defaultItems.length; i++) { - itemOut = defaultItems[i]; - itemOut._index = contOut.length; - opts.handleItemDefaults({}, itemOut, parentObjOut, opts, {}); - contOut.push(itemOut); - } - - // in case this array gets its defaults rebuilt independent of the whole layout, - // relink the private keys just for this array. - if(Lib.isArrayOrTypedArray(previousContOut)) { - var len = Math.min(previousContOut.length, contOut.length); - for(i = 0; i < len; i++) { - Lib.relinkPrivateKeys(contOut[i], previousContOut[i]); - } - } - - return contOut; -}; - -},{"../lib":719,"../plot_api/plot_template":757}],764:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fxAttrs = _dereq_('../components/fx/attributes'); - -module.exports = { - type: { - valType: 'enumerated', - - values: [], // listed dynamically - dflt: 'scatter', - editType: 'calc+clearAxisTypes', - _noTemplating: true // we handle this at a higher level - }, - visible: { - valType: 'enumerated', - values: [true, false, 'legendonly'], - - dflt: true, - editType: 'calc', - - }, - showlegend: { - valType: 'boolean', - - dflt: true, - editType: 'style', - - }, - legendgroup: { - valType: 'string', - - dflt: '', - editType: 'style', - - }, - opacity: { - valType: 'number', - - min: 0, - max: 1, - dflt: 1, - editType: 'style', - - }, - name: { - valType: 'string', - - editType: 'style', - - }, - uid: { - valType: 'string', - - editType: 'plot', - anim: true, - - }, - ids: { - valType: 'data_array', - editType: 'calc', - anim: true, - - }, - customdata: { - valType: 'data_array', - editType: 'calc', - - }, - meta: { - valType: 'any', - arrayOk: true, - - editType: 'plot', - - }, - - // N.B. these cannot be 'data_array' as they do not have the same length as - // other data arrays and arrayOk attributes in general - // - // Maybe add another valType: - // https://github.com/plotly/plotly.js/issues/1894 - selectedpoints: { - valType: 'any', - - editType: 'calc', - - }, - - hoverinfo: { - valType: 'flaglist', - - flags: ['x', 'y', 'z', 'text', 'name'], - extras: ['all', 'none', 'skip'], - arrayOk: true, - dflt: 'all', - editType: 'none', - - }, - hoverlabel: fxAttrs.hoverlabel, - stream: { - token: { - valType: 'string', - noBlank: true, - strict: true, - - editType: 'calc', - - }, - maxpoints: { - valType: 'number', - min: 0, - max: 10000, - dflt: 500, - - editType: 'calc', - - }, - editType: 'calc' - }, - transforms: { - _isLinkedToArray: 'transform', - editType: 'calc', - - }, - uirevision: { - valType: 'any', - - editType: 'none', - - } -}; - -},{"../components/fx/attributes":623}],765:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -module.exports = { - xaxis: { - valType: 'subplotid', - - dflt: 'x', - editType: 'calc+clearAxisTypes', - - }, - yaxis: { - valType: 'subplotid', - - dflt: 'y', - editType: 'calc+clearAxisTypes', - - } -}; - -},{}],766:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var FP_SAFE = _dereq_('../../constants/numerical').FP_SAFE; -var Registry = _dereq_('../../registry'); - -module.exports = { - getAutoRange: getAutoRange, - makePadFn: makePadFn, - doAutoRange: doAutoRange, - findExtremes: findExtremes, - concatExtremes: concatExtremes -}; - -/** - * getAutoRange - * - * Collects all _extremes values corresponding to a given axis - * and computes its auto range. - * - * Note that getAutoRange uses return values from findExtremes. - * - * @param {object} gd: - * graph div object with filled-in fullData and fullLayout, in particular - * with filled-in '_extremes' containers: - * { - * val: calcdata value, - * pad: extra pixels beyond this value, - * extrapad: bool, does this point want 5% extra padding - * } - * @param {object} ax: - * full axis object, in particular with filled-in '_traceIndices' - * and '_annIndices' / '_shapeIndices' if applicable - * @return {array} - * an array of [min, max]. These are calcdata for log and category axes - * and data for linear and date axes. - * - * TODO: we want to change log to data as well, but it's hard to do this - * maintaining backward compatibility. category will always have to use calcdata - * though, because otherwise values between categories (or outside all categories) - * would be impossible. - */ -function getAutoRange(gd, ax) { - var i, j; - var newRange = []; - - var getPad = makePadFn(ax); - var extremes = concatExtremes(gd, ax); - var minArray = extremes.min; - var maxArray = extremes.max; - - if(minArray.length === 0 || maxArray.length === 0) { - return Lib.simpleMap(ax.range, ax.r2l); - } - - var minmin = minArray[0].val; - var maxmax = maxArray[0].val; - - for(i = 1; i < minArray.length; i++) { - if(minmin !== maxmax) break; - minmin = Math.min(minmin, minArray[i].val); - } - for(i = 1; i < maxArray.length; i++) { - if(minmin !== maxmax) break; - maxmax = Math.max(maxmax, maxArray[i].val); - } - - var axReverse = false; - - if(ax.range) { - var rng = Lib.simpleMap(ax.range, ax.r2l); - axReverse = rng[1] < rng[0]; - } - // one-time setting to easily reverse the axis - // when plotting from code - if(ax.autorange === 'reversed') { - axReverse = true; - ax.autorange = true; - } - - var rangeMode = ax.rangemode; - var toZero = rangeMode === 'tozero'; - var nonNegative = rangeMode === 'nonnegative'; - var axLen = ax._length; - // don't allow padding to reduce the data to < 10% of the length - var minSpan = axLen / 10; - - var mbest = 0; - var minpt, maxpt, minbest, maxbest, dp, dv; - - for(i = 0; i < minArray.length; i++) { - minpt = minArray[i]; - for(j = 0; j < maxArray.length; j++) { - maxpt = maxArray[j]; - dv = maxpt.val - minpt.val; - if(dv > 0) { - dp = axLen - getPad(minpt) - getPad(maxpt); - if(dp > minSpan) { - if(dv / dp > mbest) { - minbest = minpt; - maxbest = maxpt; - mbest = dv / dp; - } - } else if(dv / axLen > mbest) { - // in case of padding longer than the axis - // at least include the unpadded data values. - minbest = {val: minpt.val, pad: 0}; - maxbest = {val: maxpt.val, pad: 0}; - mbest = dv / axLen; - } - } - } - } - - function getMaxPad(prev, pt) { - return Math.max(prev, getPad(pt)); - } - - if(minmin === maxmax) { - var lower = minmin - 1; - var upper = minmin + 1; - if(toZero) { - if(minmin === 0) { - // The only value we have on this axis is 0, and we want to - // autorange so zero is one end. - // In principle this could be [0, 1] or [-1, 0] but usually - // 'tozero' pins 0 to the low end, so follow that. - newRange = [0, 1]; - } else { - var maxPad = (minmin > 0 ? maxArray : minArray).reduce(getMaxPad, 0); - // we're pushing a single value away from the edge due to its - // padding, with the other end clamped at zero - // 0.5 means don't push it farther than the center. - var rangeEnd = minmin / (1 - Math.min(0.5, maxPad / axLen)); - newRange = minmin > 0 ? [0, rangeEnd] : [rangeEnd, 0]; - } - } else if(nonNegative) { - newRange = [Math.max(0, lower), Math.max(1, upper)]; - } else { - newRange = [lower, upper]; - } - } else { - if(toZero) { - if(minbest.val >= 0) { - minbest = {val: 0, pad: 0}; - } - if(maxbest.val <= 0) { - maxbest = {val: 0, pad: 0}; - } - } else if(nonNegative) { - if(minbest.val - mbest * getPad(minbest) < 0) { - minbest = {val: 0, pad: 0}; - } - if(maxbest.val <= 0) { - maxbest = {val: 1, pad: 0}; - } - } - - // in case it changed again... - mbest = (maxbest.val - minbest.val) / - (axLen - getPad(minbest) - getPad(maxbest)); - - newRange = [ - minbest.val - mbest * getPad(minbest), - maxbest.val + mbest * getPad(maxbest) - ]; - } - - // maintain reversal - if(axReverse) newRange.reverse(); - - return Lib.simpleMap(newRange, ax.l2r || Number); -} - -/* - * calculate the pixel padding for ax._min and ax._max entries with - * optional extrapad as 5% of the total axis length - */ -function makePadFn(ax) { - // 5% padding for points that specify extrapad: true - var extrappad = ax._length / 20; - - // domain-constrained axes: base extrappad on the unconstrained - // domain so it's consistent as the domain changes - if((ax.constrain === 'domain') && ax._inputDomain) { - extrappad *= (ax._inputDomain[1] - ax._inputDomain[0]) / - (ax.domain[1] - ax.domain[0]); - } - - return function getPad(pt) { return pt.pad + (pt.extrapad ? extrappad : 0); }; -} - -function concatExtremes(gd, ax) { - var axId = ax._id; - var fullData = gd._fullData; - var fullLayout = gd._fullLayout; - var minArray = []; - var maxArray = []; - var i, j, d; - - function _concat(cont, indices) { - for(i = 0; i < indices.length; i++) { - var item = cont[indices[i]]; - var extremes = (item._extremes || {})[axId]; - if(item.visible === true && extremes) { - for(j = 0; j < extremes.min.length; j++) { - d = extremes.min[j]; - collapseMinArray(minArray, d.val, d.pad, {extrapad: d.extrapad}); - } - for(j = 0; j < extremes.max.length; j++) { - d = extremes.max[j]; - collapseMaxArray(maxArray, d.val, d.pad, {extrapad: d.extrapad}); - } - } - } - } - - _concat(fullData, ax._traceIndices); - _concat(fullLayout.annotations || [], ax._annIndices || []); - _concat(fullLayout.shapes || [], ax._shapeIndices || []); - - return {min: minArray, max: maxArray}; -} - -function doAutoRange(gd, ax) { - ax.setScale(); - - if(ax.autorange) { - ax.range = getAutoRange(gd, ax); - - ax._r = ax.range.slice(); - ax._rl = Lib.simpleMap(ax._r, ax.r2l); - - // doAutoRange will get called on fullLayout, - // but we want to report its results back to layout - - var axIn = ax._input; - - // before we edit _input, store preGUI values - var edits = {}; - edits[ax._attr + '.range'] = ax.range; - edits[ax._attr + '.autorange'] = ax.autorange; - Registry.call('_storeDirectGUIEdit', gd.layout, gd._fullLayout._preGUI, edits); - - axIn.range = ax.range.slice(); - axIn.autorange = ax.autorange; - } - - var anchorAx = ax._anchorAxis; - - if(anchorAx && anchorAx.rangeslider) { - var axeRangeOpts = anchorAx.rangeslider[ax._name]; - if(axeRangeOpts) { - if(axeRangeOpts.rangemode === 'auto') { - axeRangeOpts.range = getAutoRange(gd, ax); - } - } - anchorAx._input.rangeslider[ax._name] = Lib.extendFlat({}, axeRangeOpts); - } -} - -/** - * findExtremes - * - * Find min/max extremes of an array of coordinates on a given axis. - * - * Note that findExtremes is called during `calc`, when we don't yet know the axis - * length; all the inputs should be based solely on the trace data, nothing - * about the axis layout. - * - * Note that `ppad` and `vpad` as well as their asymmetric variants refer to - * the before and after padding of the passed `data` array, not to the whole axis. - * - * @param {object} ax: full axis object - * relies on - * - ax.type - * - ax._m (just its sign) - * - ax.d2l - * @param {array} data: - * array of numbers (i.e. already run though ax.d2c) - * @param {object} opts: - * available keys are: - * vpad: (number or number array) pad values (data value +-vpad) - * ppad: (number or number array) pad pixels (pixel location +-ppad) - * ppadplus, ppadminus, vpadplus, vpadminus: - * separate padding for each side, overrides symmetric - * padded: (boolean) add 5% padding to both ends - * (unless one end is overridden by tozero) - * tozero: (boolean) make sure to include zero if axis is linear, - * and make it a tight bound if possible - * - * @return {object} - * - min {array of objects} - * - max {array of objects} - * each object item has fields: - * - val {number} - * - pad {number} - * - extrappad {number} - * - opts {object}: a ref to the passed "options" object - */ -function findExtremes(ax, data, opts) { - if(!opts) opts = {}; - if(!ax._m) ax.setScale(); - - var minArray = []; - var maxArray = []; - - var len = data.length; - var extrapad = opts.padded || false; - var tozero = opts.tozero && (ax.type === 'linear' || ax.type === '-'); - var isLog = ax.type === 'log'; - var hasArrayOption = false; - var i, v, di, dmin, dmax, ppadiplus, ppadiminus, vmin, vmax; - - function makePadAccessor(item) { - if(Array.isArray(item)) { - hasArrayOption = true; - return function(i) { return Math.max(Number(item[i]||0), 0); }; - } else { - var v = Math.max(Number(item||0), 0); - return function() { return v; }; - } - } - - var ppadplus = makePadAccessor((ax._m > 0 ? - opts.ppadplus : opts.ppadminus) || opts.ppad || 0); - var ppadminus = makePadAccessor((ax._m > 0 ? - opts.ppadminus : opts.ppadplus) || opts.ppad || 0); - var vpadplus = makePadAccessor(opts.vpadplus || opts.vpad); - var vpadminus = makePadAccessor(opts.vpadminus || opts.vpad); - - if(!hasArrayOption) { - // with no arrays other than `data` we don't need to consider - // every point, only the extreme data points - vmin = Infinity; - vmax = -Infinity; - - if(isLog) { - for(i = 0; i < len; i++) { - v = data[i]; - // data is not linearized yet so we still have to filter out negative logs - if(v < vmin && v > 0) vmin = v; - if(v > vmax && v < FP_SAFE) vmax = v; - } - } else { - for(i = 0; i < len; i++) { - v = data[i]; - if(v < vmin && v > -FP_SAFE) vmin = v; - if(v > vmax && v < FP_SAFE) vmax = v; - } - } - - data = [vmin, vmax]; - len = 2; - } - - var collapseOpts = {tozero: tozero, extrapad: extrapad}; - - function addItem(i) { - di = data[i]; - if(!isNumeric(di)) return; - ppadiplus = ppadplus(i); - ppadiminus = ppadminus(i); - vmin = di - vpadminus(i); - vmax = di + vpadplus(i); - // special case for log axes: if vpad makes this object span - // more than an order of mag, clip it to one order. This is so - // we don't have non-positive errors or absurdly large lower - // range due to rounding errors - if(isLog && vmin < vmax / 10) vmin = vmax / 10; - - dmin = ax.c2l(vmin); - dmax = ax.c2l(vmax); - - if(tozero) { - dmin = Math.min(0, dmin); - dmax = Math.max(0, dmax); - } - if(goodNumber(dmin)) { - collapseMinArray(minArray, dmin, ppadiminus, collapseOpts); - } - if(goodNumber(dmax)) { - collapseMaxArray(maxArray, dmax, ppadiplus, collapseOpts); - } - } - - // For efficiency covering monotonic or near-monotonic data, - // check a few points at both ends first and then sweep - // through the middle - var iMax = Math.min(6, len); - for(i = 0; i < iMax; i++) addItem(i); - for(i = len - 1; i >= iMax; i--) addItem(i); - - return { - min: minArray, - max: maxArray, - opts: opts - }; -} - -function collapseMinArray(array, newVal, newPad, opts) { - collapseArray(array, newVal, newPad, opts, lessOrEqual); -} - -function collapseMaxArray(array, newVal, newPad, opts) { - collapseArray(array, newVal, newPad, opts, greaterOrEqual); -} - -/** - * collapseArray - * - * Takes items from 'array' and compares them to 'newVal', 'newPad'. - * - * @param {array} array: - * current set of min or max extremes - * @param {number} newVal: - * new value to compare against - * @param {number} newPad: - * pad value associated with 'newVal' - * @param {object} opts: - * - tozero {boolean} - * - extrapad {number} - * @param {function} atLeastAsExtreme: - * comparison function, use - * - lessOrEqual for min 'array' and - * - greaterOrEqual for max 'array' - * - * In practice, 'array' is either - * - 'extremes[ax._id].min' or - * - 'extremes[ax._id].max - * found in traces and layout items that affect autorange. - * - * Since we don't yet know the relationship between pixels and values - * (that's what we're trying to figure out!) AND we don't yet know how - * many pixels `extrapad` represents (it's going to be 5% of the length, - * but we don't want to have to redo calc just because length changed) - * two point must satisfy three criteria simultaneously for one to supersede the other: - * - at least as extreme a `val` - * - at least as big a `pad` - * - an unpadded point cannot supersede a padded point, but any other combination can - * - * Then: - * - If the item supersedes the new point, set includeThis false - * - If the new pt supersedes the item, delete it from 'array' - */ -function collapseArray(array, newVal, newPad, opts, atLeastAsExtreme) { - var tozero = opts.tozero; - var extrapad = opts.extrapad; - var includeThis = true; - - for(var j = 0; j < array.length && includeThis; j++) { - var v = array[j]; - if(atLeastAsExtreme(v.val, newVal) && v.pad >= newPad && (v.extrapad || !extrapad)) { - includeThis = false; - break; - } else if(atLeastAsExtreme(newVal, v.val) && v.pad <= newPad && (extrapad || !v.extrapad)) { - array.splice(j, 1); - j--; - } - } - if(includeThis) { - var clipAtZero = (tozero && newVal === 0); - array.push({ - val: newVal, - pad: clipAtZero ? 0 : newPad, - extrapad: clipAtZero ? false : extrapad - }); - } -} - -// In order to stop overflow errors, don't consider points -// too close to the limits of js floating point -function goodNumber(v) { - return isNumeric(v) && Math.abs(v) < FP_SAFE; -} - -function lessOrEqual(v0, v1) { return v0 <= v1; } -function greaterOrEqual(v0, v1) { return v0 >= v1; } - -},{"../../constants/numerical":695,"../../lib":719,"../../registry":847,"fast-isnumeric":225}],767:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); -var Plots = _dereq_('../../plots/plots'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var Titles = _dereq_('../../components/titles'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); - -var axAttrs = _dereq_('./layout_attributes'); -var cleanTicks = _dereq_('./clean_ticks'); - -var constants = _dereq_('../../constants/numerical'); -var ONEAVGYEAR = constants.ONEAVGYEAR; -var ONEAVGMONTH = constants.ONEAVGMONTH; -var ONEDAY = constants.ONEDAY; -var ONEHOUR = constants.ONEHOUR; -var ONEMIN = constants.ONEMIN; -var ONESEC = constants.ONESEC; -var MINUS_SIGN = constants.MINUS_SIGN; -var BADNUM = constants.BADNUM; - -var MID_SHIFT = _dereq_('../../constants/alignment').MID_SHIFT; -var LINE_SPACING = _dereq_('../../constants/alignment').LINE_SPACING; - -var axes = module.exports = {}; - -axes.setConvert = _dereq_('./set_convert'); -var autoType = _dereq_('./axis_autotype'); - -var axisIds = _dereq_('./axis_ids'); -axes.id2name = axisIds.id2name; -axes.name2id = axisIds.name2id; -axes.cleanId = axisIds.cleanId; -axes.list = axisIds.list; -axes.listIds = axisIds.listIds; -axes.getFromId = axisIds.getFromId; -axes.getFromTrace = axisIds.getFromTrace; - -var autorange = _dereq_('./autorange'); -axes.getAutoRange = autorange.getAutoRange; -axes.findExtremes = autorange.findExtremes; - -/* - * find the list of possible axes to reference with an xref or yref attribute - * and coerce it to that list - * - * attr: the attribute we're generating a reference for. Should end in 'x' or 'y' - * but can be prefixed, like 'ax' for annotation's arrow x - * dflt: the default to coerce to, or blank to use the first axis (falling back on - * extraOption if there is no axis) - * extraOption: aside from existing axes with this letter, what non-axis value is allowed? - * Only required if it's different from `dflt` - */ -axes.coerceRef = function(containerIn, containerOut, gd, attr, dflt, extraOption) { - var axLetter = attr.charAt(attr.length - 1); - var axlist = gd._fullLayout._subplots[axLetter + 'axis']; - var refAttr = attr + 'ref'; - var attrDef = {}; - - if(!dflt) dflt = axlist[0] || extraOption; - if(!extraOption) extraOption = dflt; - - // data-ref annotations are not supported in gl2d yet - - attrDef[refAttr] = { - valType: 'enumerated', - values: axlist.concat(extraOption ? [extraOption] : []), - dflt: dflt - }; - - // xref, yref - return Lib.coerce(containerIn, containerOut, attrDef, refAttr); -}; - -/* - * coerce position attributes (range-type) that can be either on axes or absolute - * (paper or pixel) referenced. The biggest complication here is that we don't know - * before looking at the axis whether the value must be a number or not (it may be - * a date string), so we can't use the regular valType='number' machinery - * - * axRef (string): the axis this position is referenced to, or: - * paper: fraction of the plot area - * pixel: pixels relative to some starting position - * attr (string): the attribute in containerOut we are coercing - * dflt (number): the default position, as a fraction or pixels. If the attribute - * is to be axis-referenced, this will be converted to an axis data value - * - * Also cleans the values, since the attribute definition itself has to say - * valType: 'any' to handle date axes. This allows us to accept: - * - for category axes: category names, and convert them here into serial numbers. - * Note that this will NOT work for axis range endpoints, because we don't know - * the category list yet (it's set by ax.makeCalcdata during calc) - * but it works for component (note, shape, images) positions. - * - for date axes: JS Dates or milliseconds, and convert to date strings - * - for other types: coerce them to numbers - */ -axes.coercePosition = function(containerOut, gd, coerce, axRef, attr, dflt) { - var cleanPos, pos; - - if(axRef === 'paper' || axRef === 'pixel') { - cleanPos = Lib.ensureNumber; - pos = coerce(attr, dflt); - } else { - var ax = axes.getFromId(gd, axRef); - dflt = ax.fraction2r(dflt); - pos = coerce(attr, dflt); - cleanPos = ax.cleanPos; - } - - containerOut[attr] = cleanPos(pos); -}; - -axes.cleanPosition = function(pos, gd, axRef) { - var cleanPos = (axRef === 'paper' || axRef === 'pixel') ? - Lib.ensureNumber : - axes.getFromId(gd, axRef).cleanPos; - - return cleanPos(pos); -}; - -axes.redrawComponents = function(gd, axIds) { - axIds = axIds ? axIds : axes.listIds(gd); - - var fullLayout = gd._fullLayout; - - function _redrawOneComp(moduleName, methodName, stashName, shortCircuit) { - var method = Registry.getComponentMethod(moduleName, methodName); - var stash = {}; - - for(var i = 0; i < axIds.length; i++) { - var ax = fullLayout[axes.id2name(axIds[i])]; - var indices = ax[stashName]; - - for(var j = 0; j < indices.length; j++) { - var ind = indices[j]; - - if(!stash[ind]) { - method(gd, ind); - stash[ind] = 1; - // once is enough for images (which doesn't use the `i` arg anyway) - if(shortCircuit) return; - } - } - } - } - - // annotations and shapes 'draw' method is slow, - // use the finer-grained 'drawOne' method instead - _redrawOneComp('annotations', 'drawOne', '_annIndices'); - _redrawOneComp('shapes', 'drawOne', '_shapeIndices'); - _redrawOneComp('images', 'draw', '_imgIndices', true); -}; - -var getDataConversions = axes.getDataConversions = function(gd, trace, target, targetArray) { - var ax; - - // If target points to an axis, use the type we already have for that - // axis to find the data type. Otherwise use the values to autotype. - var d2cTarget = (target === 'x' || target === 'y' || target === 'z') ? - target : - targetArray; - - // In the case of an array target, make a mock data array - // and call supplyDefaults to the data type and - // setup the data-to-calc method. - if(Array.isArray(d2cTarget)) { - ax = { - type: autoType(targetArray), - _categories: [] - }; - axes.setConvert(ax); - - // build up ax._categories (usually done during ax.makeCalcdata() - if(ax.type === 'category') { - for(var i = 0; i < targetArray.length; i++) { - ax.d2c(targetArray[i]); - } - } - // TODO what to do for transforms? - } else { - ax = axes.getFromTrace(gd, trace, d2cTarget); - } - - // if 'target' has corresponding axis - // -> use setConvert method - if(ax) return {d2c: ax.d2c, c2d: ax.c2d}; - - // special case for 'ids' - // -> cast to String - if(d2cTarget === 'ids') return {d2c: toString, c2d: toString}; - - // otherwise (e.g. numeric-array of 'marker.color' or 'marker.size') - // -> cast to Number - - return {d2c: toNum, c2d: toNum}; -}; - -function toNum(v) { return +v; } -function toString(v) { return String(v); } - -axes.getDataToCoordFunc = function(gd, trace, target, targetArray) { - return getDataConversions(gd, trace, target, targetArray).d2c; -}; - -// get counteraxis letter for this axis (name or id) -// this can also be used as the id for default counter axis -axes.counterLetter = function(id) { - var axLetter = id.charAt(0); - if(axLetter === 'x') return 'y'; - if(axLetter === 'y') return 'x'; -}; - -// incorporate a new minimum difference and first tick into -// forced -// note that _forceTick0 is linearized, so needs to be turned into -// a range value for setting tick0 -axes.minDtick = function(ax, newDiff, newFirst, allow) { - // doesn't make sense to do forced min dTick on log or category axes, - // and the plot itself may decide to cancel (ie non-grouped bars) - if(['log', 'category', 'multicategory'].indexOf(ax.type) !== -1 || !allow) { - ax._minDtick = 0; - } else if(ax._minDtick === undefined) { - // undefined means there's nothing there yet - - ax._minDtick = newDiff; - ax._forceTick0 = newFirst; - } else if(ax._minDtick) { - if((ax._minDtick / newDiff + 1e-6) % 1 < 2e-6 && - // existing minDtick is an integer multiple of newDiff - // (within rounding err) - // and forceTick0 can be shifted to newFirst - - (((newFirst - ax._forceTick0) / newDiff % 1) + - 1.000001) % 1 < 2e-6) { - ax._minDtick = newDiff; - ax._forceTick0 = newFirst; - } else if((newDiff / ax._minDtick + 1e-6) % 1 > 2e-6 || - // if the converse is true (newDiff is a multiple of minDtick and - // newFirst can be shifted to forceTick0) then do nothing - same - // forcing stands. Otherwise, cancel forced minimum - - (((newFirst - ax._forceTick0) / ax._minDtick % 1) + - 1.000001) % 1 > 2e-6) { - ax._minDtick = 0; - } - } -}; - -// save a copy of the initial axis ranges in fullLayout -// use them in mode bar and dblclick events -axes.saveRangeInitial = function(gd, overwrite) { - var axList = axes.list(gd, '', true); - var hasOneAxisChanged = false; - - for(var i = 0; i < axList.length; i++) { - var ax = axList[i]; - var isNew = (ax._rangeInitial === undefined); - var hasChanged = isNew || !( - ax.range[0] === ax._rangeInitial[0] && - ax.range[1] === ax._rangeInitial[1] - ); - - if((isNew && ax.autorange === false) || (overwrite && hasChanged)) { - ax._rangeInitial = ax.range.slice(); - hasOneAxisChanged = true; - } - } - - return hasOneAxisChanged; -}; - -// save a copy of the initial spike visibility -axes.saveShowSpikeInitial = function(gd, overwrite) { - var axList = axes.list(gd, '', true); - var hasOneAxisChanged = false; - var allSpikesEnabled = 'on'; - - for(var i = 0; i < axList.length; i++) { - var ax = axList[i]; - var isNew = (ax._showSpikeInitial === undefined); - var hasChanged = isNew || !(ax.showspikes === ax._showspikes); - - if(isNew || (overwrite && hasChanged)) { - ax._showSpikeInitial = ax.showspikes; - hasOneAxisChanged = true; - } - - if(allSpikesEnabled === 'on' && !ax.showspikes) { - allSpikesEnabled = 'off'; - } - } - gd._fullLayout._cartesianSpikesEnabled = allSpikesEnabled; - return hasOneAxisChanged; -}; - -axes.autoBin = function(data, ax, nbins, is2d, calendar, size) { - var dataMin = Lib.aggNums(Math.min, null, data); - var dataMax = Lib.aggNums(Math.max, null, data); - - if(ax.type === 'category' || ax.type === 'multicategory') { - return { - start: dataMin - 0.5, - end: dataMax + 0.5, - size: Math.max(1, Math.round(size) || 1), - _dataSpan: dataMax - dataMin, - }; - } - - if(!calendar) calendar = ax.calendar; - - // piggyback off tick code to make "nice" bin sizes and edges - var dummyAx; - if(ax.type === 'log') { - dummyAx = { - type: 'linear', - range: [dataMin, dataMax] - }; - } else { - dummyAx = { - type: ax.type, - range: Lib.simpleMap([dataMin, dataMax], ax.c2r, 0, calendar), - calendar: calendar - }; - } - axes.setConvert(dummyAx); - - size = size && cleanTicks.dtick(size, dummyAx.type); - - if(size) { - dummyAx.dtick = size; - dummyAx.tick0 = cleanTicks.tick0(undefined, dummyAx.type, calendar); - } else { - var size0; - if(nbins) size0 = ((dataMax - dataMin) / nbins); - else { - // totally auto: scale off std deviation so the highest bin is - // somewhat taller than the total number of bins, but don't let - // the size get smaller than the 'nice' rounded down minimum - // difference between values - var distinctData = Lib.distinctVals(data); - var msexp = Math.pow(10, Math.floor( - Math.log(distinctData.minDiff) / Math.LN10)); - var minSize = msexp * Lib.roundUp( - distinctData.minDiff / msexp, [0.9, 1.9, 4.9, 9.9], true); - size0 = Math.max(minSize, 2 * Lib.stdev(data) / - Math.pow(data.length, is2d ? 0.25 : 0.4)); - - // fallback if ax.d2c output BADNUMs - // e.g. when user try to plot categorical bins - // on a layout.xaxis.type: 'linear' - if(!isNumeric(size0)) size0 = 1; - } - - axes.autoTicks(dummyAx, size0); - } - - var finalSize = dummyAx.dtick; - var binStart = axes.tickIncrement( - axes.tickFirst(dummyAx), finalSize, 'reverse', calendar); - var binEnd, bincount; - - // check for too many data points right at the edges of bins - // (>50% within 1% of bin edges) or all data points integral - // and offset the bins accordingly - if(typeof finalSize === 'number') { - binStart = autoShiftNumericBins(binStart, data, dummyAx, dataMin, dataMax); - - bincount = 1 + Math.floor((dataMax - binStart) / finalSize); - binEnd = binStart + bincount * finalSize; - } else { - // month ticks - should be the only nonlinear kind we have at this point. - // dtick (as supplied by axes.autoTick) only has nonlinear values on - // date and log axes, but even if you display a histogram on a log axis - // we bin it on a linear axis (which one could argue against, but that's - // a separate issue) - if(dummyAx.dtick.charAt(0) === 'M') { - binStart = autoShiftMonthBins(binStart, data, finalSize, dataMin, calendar); - } - - // calculate the endpoint for nonlinear ticks - you have to - // just increment until you're done - binEnd = binStart; - bincount = 0; - while(binEnd <= dataMax) { - binEnd = axes.tickIncrement(binEnd, finalSize, false, calendar); - bincount++; - } - } - - return { - start: ax.c2r(binStart, 0, calendar), - end: ax.c2r(binEnd, 0, calendar), - size: finalSize, - _dataSpan: dataMax - dataMin - }; -}; - - -function autoShiftNumericBins(binStart, data, ax, dataMin, dataMax) { - var edgecount = 0; - var midcount = 0; - var intcount = 0; - var blankCount = 0; - - function nearEdge(v) { - // is a value within 1% of a bin edge? - return (1 + (v - binStart) * 100 / ax.dtick) % 100 < 2; - } - - for(var i = 0; i < data.length; i++) { - if(data[i] % 1 === 0) intcount++; - else if(!isNumeric(data[i])) blankCount++; - - if(nearEdge(data[i])) edgecount++; - if(nearEdge(data[i] + ax.dtick / 2)) midcount++; - } - var dataCount = data.length - blankCount; - - if(intcount === dataCount && ax.type !== 'date') { - if(ax.dtick < 1) { - // all integers: if bin size is <1, it's because - // that was specifically requested (large nbins) - // so respect that... but center the bins containing - // integers on those integers - - binStart = dataMin - 0.5 * ax.dtick; - } else { - // otherwise start half an integer down regardless of - // the bin size, just enough to clear up endpoint - // ambiguity about which integers are in which bins. - - binStart -= 0.5; - if(binStart + ax.dtick < dataMin) binStart += ax.dtick; - } - } else if(midcount < dataCount * 0.1) { - if(edgecount > dataCount * 0.3 || - nearEdge(dataMin) || nearEdge(dataMax)) { - // lots of points at the edge, not many in the middle - // shift half a bin - var binshift = ax.dtick / 2; - binStart += (binStart + binshift < dataMin) ? binshift : -binshift; - } - } - return binStart; -} - - -function autoShiftMonthBins(binStart, data, dtick, dataMin, calendar) { - var stats = Lib.findExactDates(data, calendar); - // number of data points that needs to be an exact value - // to shift that increment to (near) the bin center - var threshold = 0.8; - - if(stats.exactDays > threshold) { - var numMonths = Number(dtick.substr(1)); - - if((stats.exactYears > threshold) && (numMonths % 12 === 0)) { - // The exact middle of a non-leap-year is 1.5 days into July - // so if we start the bins here, all but leap years will - // get hover-labeled as exact years. - binStart = axes.tickIncrement(binStart, 'M6', 'reverse') + ONEDAY * 1.5; - } else if(stats.exactMonths > threshold) { - // Months are not as clean, but if we shift half the *longest* - // month (31/2 days) then 31-day months will get labeled exactly - // and shorter months will get labeled with the correct month - // but shifted 12-36 hours into it. - binStart = axes.tickIncrement(binStart, 'M1', 'reverse') + ONEDAY * 15.5; - } else { - // Shifting half a day is exact, but since these are month bins it - // will always give a somewhat odd-looking label, until we do something - // smarter like showing the bin boundaries (or the bounds of the actual - // data in each bin) - binStart -= ONEDAY / 2; - } - var nextBinStart = axes.tickIncrement(binStart, dtick); - - if(nextBinStart <= dataMin) return nextBinStart; - } - return binStart; -} - -// ---------------------------------------------------- -// Ticks and grids -// ---------------------------------------------------- - -// ensure we have tick0, dtick, and tick rounding calculated -axes.prepTicks = function(ax) { - var rng = Lib.simpleMap(ax.range, ax.r2l); - - // calculate max number of (auto) ticks to display based on plot size - if(ax.tickmode === 'auto' || !ax.dtick) { - var nt = ax.nticks; - var minPx; - - if(!nt) { - if(ax.type === 'category' || ax.type === 'multicategory') { - minPx = ax.tickfont ? (ax.tickfont.size || 12) * 1.2 : 15; - nt = ax._length / minPx; - } else { - minPx = ax._id.charAt(0) === 'y' ? 40 : 80; - nt = Lib.constrain(ax._length / minPx, 4, 9) + 1; - } - - // radial axes span half their domain, - // multiply nticks value by two to get correct number of auto ticks. - if(ax._name === 'radialaxis') nt *= 2; - } - - // add a couple of extra digits for filling in ticks when we - // have explicit tickvals without tick text - if(ax.tickmode === 'array') nt *= 100; - - axes.autoTicks(ax, Math.abs(rng[1] - rng[0]) / nt); - // check for a forced minimum dtick - if(ax._minDtick > 0 && ax.dtick < ax._minDtick * 2) { - ax.dtick = ax._minDtick; - ax.tick0 = ax.l2r(ax._forceTick0); - } - } - - // check for missing tick0 - if(!ax.tick0) { - ax.tick0 = (ax.type === 'date') ? '2000-01-01' : 0; - } - - // ensure we don't try to make ticks below our minimum precision - // see https://github.com/plotly/plotly.js/issues/2892 - if(ax.type === 'date' && ax.dtick < 0.1) ax.dtick = 0.1; - - // now figure out rounding of tick values - autoTickRound(ax); -}; - -// calculate the ticks: text, values, positioning -// if ticks are set to automatic, determine the right values (tick0,dtick) -// in any case, set tickround to # of digits to round tick labels to, -// or codes to this effect for log and date scales -axes.calcTicks = function calcTicks(ax) { - axes.prepTicks(ax); - var rng = Lib.simpleMap(ax.range, ax.r2l); - - // now that we've figured out the auto values for formatting - // in case we're missing some ticktext, we can break out for array ticks - if(ax.tickmode === 'array') return arrayTicks(ax); - - // find the first tick - ax._tmin = axes.tickFirst(ax); - - // add a tiny bit so we get ticks which may have rounded out - var startTick = rng[0] * 1.0001 - rng[1] * 0.0001; - var endTick = rng[1] * 1.0001 - rng[0] * 0.0001; - // check for reversed axis - var axrev = (rng[1] < rng[0]); - - // No visible ticks? Quit. - // I've only seen this on category axes with all categories off the edge. - if((ax._tmin < startTick) !== axrev) return []; - - // return the full set of tick vals - var tickVals = []; - if(ax.type === 'category' || ax.type === 'multicategory') { - endTick = (axrev) ? Math.max(-0.5, endTick) : - Math.min(ax._categories.length - 0.5, endTick); - } - - var isDLog = (ax.type === 'log') && !(isNumeric(ax.dtick) || ax.dtick.charAt(0) === 'L'); - - var xPrevious = null; - var maxTicks = Math.max(1000, ax._length || 0); - for(var x = ax._tmin; - (axrev) ? (x >= endTick) : (x <= endTick); - x = axes.tickIncrement(x, ax.dtick, axrev, ax.calendar)) { - // prevent infinite loops - no more than one tick per pixel, - // and make sure each value is different from the previous - if(tickVals.length > maxTicks || x === xPrevious) break; - xPrevious = x; - - var minor = false; - if(isDLog && (x !== (x | 0))) { - minor = true; - } - - tickVals.push({ - minor: minor, - value: x - }); - } - - // If same angle over a full circle, the last tick vals is a duplicate. - // TODO must do something similar for angular date axes. - if(isAngular(ax) && Math.abs(rng[1] - rng[0]) === 360) { - tickVals.pop(); - } - - // save the last tick as well as first, so we can - // show the exponent only on the last one - ax._tmax = (tickVals[tickVals.length - 1] || {}).value; - - // for showing the rest of a date when the main tick label is only the - // latter part: ax._prevDateHead holds what we showed most recently. - // Start with it cleared and mark that we're in calcTicks (ie calculating a - // whole string of these so we should care what the previous date head was!) - ax._prevDateHead = ''; - ax._inCalcTicks = true; - - var ticksOut = new Array(tickVals.length); - for(var i = 0; i < tickVals.length; i++) { - ticksOut[i] = axes.tickText( - ax, - tickVals[i].value, - false, // hover - tickVals[i].minor // noSuffixPrefix - ); - } - - ax._inCalcTicks = false; - - return ticksOut; -}; - -function arrayTicks(ax) { - var vals = ax.tickvals; - var text = ax.ticktext; - var ticksOut = new Array(vals.length); - var rng = Lib.simpleMap(ax.range, ax.r2l); - var r0expanded = rng[0] * 1.0001 - rng[1] * 0.0001; - var r1expanded = rng[1] * 1.0001 - rng[0] * 0.0001; - var tickMin = Math.min(r0expanded, r1expanded); - var tickMax = Math.max(r0expanded, r1expanded); - var j = 0; - - // without a text array, just format the given values as any other ticks - // except with more precision to the numbers - if(!Array.isArray(text)) text = []; - - // make sure showing ticks doesn't accidentally add new categories - // TODO multicategory, if we allow ticktext / tickvals - var tickVal2l = ax.type === 'category' ? ax.d2l_noadd : ax.d2l; - - // array ticks on log axes always show the full number - // (if no explicit ticktext overrides it) - if(ax.type === 'log' && String(ax.dtick).charAt(0) !== 'L') { - ax.dtick = 'L' + Math.pow(10, Math.floor(Math.min(ax.range[0], ax.range[1])) - 1); - } - - for(var i = 0; i < vals.length; i++) { - var vali = tickVal2l(vals[i]); - if(vali > tickMin && vali < tickMax) { - if(text[i] === undefined) ticksOut[j] = axes.tickText(ax, vali); - else ticksOut[j] = tickTextObj(ax, vali, String(text[i])); - j++; - } - } - - if(j < vals.length) ticksOut.splice(j, vals.length - j); - - return ticksOut; -} - -var roundBase10 = [2, 5, 10]; -var roundBase24 = [1, 2, 3, 6, 12]; -var roundBase60 = [1, 2, 5, 10, 15, 30]; -// 2&3 day ticks are weird, but need something btwn 1&7 -var roundDays = [1, 2, 3, 7, 14]; -// approx. tick positions for log axes, showing all (1) and just 1, 2, 5 (2) -// these don't have to be exact, just close enough to round to the right value -var roundLog1 = [-0.046, 0, 0.301, 0.477, 0.602, 0.699, 0.778, 0.845, 0.903, 0.954, 1]; -var roundLog2 = [-0.301, 0, 0.301, 0.699, 1]; -// N.B. `thetaunit; 'radians' angular axes must be converted to degrees -var roundAngles = [15, 30, 45, 90, 180]; - -function roundDTick(roughDTick, base, roundingSet) { - return base * Lib.roundUp(roughDTick / base, roundingSet); -} - -// autoTicks: calculate best guess at pleasant ticks for this axis -// inputs: -// ax - an axis object -// roughDTick - rough tick spacing (to be turned into a nice round number) -// outputs (into ax): -// tick0: starting point for ticks (not necessarily on the graph) -// usually 0 for numeric (=10^0=1 for log) or jan 1, 2000 for dates -// dtick: the actual, nice round tick spacing, usually a little larger than roughDTick -// if the ticks are spaced linearly (linear scale, categories, -// log with only full powers, date ticks < month), -// this will just be a number -// months: M# -// years: M# where # is 12*number of years -// log with linear ticks: L# where # is the linear tick spacing -// log showing powers plus some intermediates: -// D1 shows all digits, D2 shows 2 and 5 -axes.autoTicks = function(ax, roughDTick) { - var base; - - function getBase(v) { - return Math.pow(v, Math.floor(Math.log(roughDTick) / Math.LN10)); - } - - if(ax.type === 'date') { - ax.tick0 = Lib.dateTick0(ax.calendar); - // the criteria below are all based on the rough spacing we calculate - // being > half of the final unit - so precalculate twice the rough val - var roughX2 = 2 * roughDTick; - - if(roughX2 > ONEAVGYEAR) { - roughDTick /= ONEAVGYEAR; - base = getBase(10); - ax.dtick = 'M' + (12 * roundDTick(roughDTick, base, roundBase10)); - } else if(roughX2 > ONEAVGMONTH) { - roughDTick /= ONEAVGMONTH; - ax.dtick = 'M' + roundDTick(roughDTick, 1, roundBase24); - } else if(roughX2 > ONEDAY) { - ax.dtick = roundDTick(roughDTick, ONEDAY, roundDays); - // get week ticks on sunday - // this will also move the base tick off 2000-01-01 if dtick is - // 2 or 3 days... but that's a weird enough case that we'll ignore it. - ax.tick0 = Lib.dateTick0(ax.calendar, true); - } else if(roughX2 > ONEHOUR) { - ax.dtick = roundDTick(roughDTick, ONEHOUR, roundBase24); - } else if(roughX2 > ONEMIN) { - ax.dtick = roundDTick(roughDTick, ONEMIN, roundBase60); - } else if(roughX2 > ONESEC) { - ax.dtick = roundDTick(roughDTick, ONESEC, roundBase60); - } else { - // milliseconds - base = getBase(10); - ax.dtick = roundDTick(roughDTick, base, roundBase10); - } - } else if(ax.type === 'log') { - ax.tick0 = 0; - var rng = Lib.simpleMap(ax.range, ax.r2l); - - if(roughDTick > 0.7) { - // only show powers of 10 - ax.dtick = Math.ceil(roughDTick); - } else if(Math.abs(rng[1] - rng[0]) < 1) { - // span is less than one power of 10 - var nt = 1.5 * Math.abs((rng[1] - rng[0]) / roughDTick); - - // ticks on a linear scale, labeled fully - roughDTick = Math.abs(Math.pow(10, rng[1]) - - Math.pow(10, rng[0])) / nt; - base = getBase(10); - ax.dtick = 'L' + roundDTick(roughDTick, base, roundBase10); - } else { - // include intermediates between powers of 10, - // labeled with small digits - // ax.dtick = "D2" (show 2 and 5) or "D1" (show all digits) - ax.dtick = (roughDTick > 0.3) ? 'D2' : 'D1'; - } - } else if(ax.type === 'category' || ax.type === 'multicategory') { - ax.tick0 = 0; - ax.dtick = Math.ceil(Math.max(roughDTick, 1)); - } else if(isAngular(ax)) { - ax.tick0 = 0; - base = 1; - ax.dtick = roundDTick(roughDTick, base, roundAngles); - } else { - // auto ticks always start at 0 - ax.tick0 = 0; - base = getBase(10); - ax.dtick = roundDTick(roughDTick, base, roundBase10); - } - - // prevent infinite loops - if(ax.dtick === 0) ax.dtick = 1; - - // TODO: this is from log axis histograms with autorange off - if(!isNumeric(ax.dtick) && typeof ax.dtick !== 'string') { - var olddtick = ax.dtick; - ax.dtick = 1; - throw 'ax.dtick error: ' + String(olddtick); - } -}; - -// after dtick is already known, find tickround = precision -// to display in tick labels -// for numeric ticks, integer # digits after . to round to -// for date ticks, the last date part to show (y,m,d,H,M,S) -// or an integer # digits past seconds -function autoTickRound(ax) { - var dtick = ax.dtick; - - ax._tickexponent = 0; - if(!isNumeric(dtick) && typeof dtick !== 'string') { - dtick = 1; - } - - if(ax.type === 'category' || ax.type === 'multicategory') { - ax._tickround = null; - } - if(ax.type === 'date') { - // If tick0 is unusual, give tickround a bit more information - // not necessarily *all* the information in tick0 though, if it's really odd - // minimal string length for tick0: 'd' is 10, 'M' is 16, 'S' is 19 - // take off a leading minus (year < 0) and i (intercalary month) so length is consistent - var tick0ms = ax.r2l(ax.tick0); - var tick0str = ax.l2r(tick0ms).replace(/(^-|i)/g, ''); - var tick0len = tick0str.length; - - if(String(dtick).charAt(0) === 'M') { - // any tick0 more specific than a year: alway show the full date - if(tick0len > 10 || tick0str.substr(5) !== '01-01') ax._tickround = 'd'; - // show the month unless ticks are full multiples of a year - else ax._tickround = (+(dtick.substr(1)) % 12 === 0) ? 'y' : 'm'; - } else if((dtick >= ONEDAY && tick0len <= 10) || (dtick >= ONEDAY * 15)) ax._tickround = 'd'; - else if((dtick >= ONEMIN && tick0len <= 16) || (dtick >= ONEHOUR)) ax._tickround = 'M'; - else if((dtick >= ONESEC && tick0len <= 19) || (dtick >= ONEMIN)) ax._tickround = 'S'; - else { - // tickround is a number of digits of fractional seconds - // of any two adjacent ticks, at least one will have the maximum fractional digits - // of all possible ticks - so take the max. length of tick0 and the next one - var tick1len = ax.l2r(tick0ms + dtick).replace(/^-/, '').length; - ax._tickround = Math.max(tick0len, tick1len) - 20; - - // We shouldn't get here... but in case there's a situation I'm - // not thinking of where tick0str and tick1str are identical or - // something, fall back on maximum precision - if(ax._tickround < 0) ax._tickround = 4; - } - } else if(isNumeric(dtick) || dtick.charAt(0) === 'L') { - // linear or log (except D1, D2) - var rng = ax.range.map(ax.r2d || Number); - if(!isNumeric(dtick)) dtick = Number(dtick.substr(1)); - // 2 digits past largest digit of dtick - ax._tickround = 2 - Math.floor(Math.log(dtick) / Math.LN10 + 0.01); - - var maxend = Math.max(Math.abs(rng[0]), Math.abs(rng[1])); - var rangeexp = Math.floor(Math.log(maxend) / Math.LN10 + 0.01); - if(Math.abs(rangeexp) > 3) { - if(isSIFormat(ax.exponentformat) && !beyondSI(rangeexp)) { - ax._tickexponent = 3 * Math.round((rangeexp - 1) / 3); - } else ax._tickexponent = rangeexp; - } - } else { - // D1 or D2 (log) - ax._tickround = null; - } -} - -// months and years don't have constant millisecond values -// (but a year is always 12 months so we only need months) -// log-scale ticks are also not consistently spaced, except -// for pure powers of 10 -// numeric ticks always have constant differences, other datetime ticks -// can all be calculated as constant number of milliseconds -axes.tickIncrement = function(x, dtick, axrev, calendar) { - var axSign = axrev ? -1 : 1; - - // includes linear, all dates smaller than month, and pure 10^n in log - if(isNumeric(dtick)) return x + axSign * dtick; - - // everything else is a string, one character plus a number - var tType = dtick.charAt(0); - var dtSigned = axSign * Number(dtick.substr(1)); - - // Dates: months (or years - see Lib.incrementMonth) - if(tType === 'M') return Lib.incrementMonth(x, dtSigned, calendar); - - // Log scales: Linear, Digits - else if(tType === 'L') return Math.log(Math.pow(10, x) + dtSigned) / Math.LN10; - - // log10 of 2,5,10, or all digits (logs just have to be - // close enough to round) - else if(tType === 'D') { - var tickset = (dtick === 'D2') ? roundLog2 : roundLog1; - var x2 = x + axSign * 0.01; - var frac = Lib.roundUp(Lib.mod(x2, 1), tickset, axrev); - - return Math.floor(x2) + - Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10; - } else throw 'unrecognized dtick ' + String(dtick); -}; - -// calculate the first tick on an axis -axes.tickFirst = function(ax) { - var r2l = ax.r2l || Number; - var rng = Lib.simpleMap(ax.range, r2l); - var axrev = rng[1] < rng[0]; - var sRound = axrev ? Math.floor : Math.ceil; - // add a tiny extra bit to make sure we get ticks - // that may have been rounded out - var r0 = rng[0] * 1.0001 - rng[1] * 0.0001; - var dtick = ax.dtick; - var tick0 = r2l(ax.tick0); - - if(isNumeric(dtick)) { - var tmin = sRound((r0 - tick0) / dtick) * dtick + tick0; - - // make sure no ticks outside the category list - if(ax.type === 'category' || ax.type === 'multicategory') { - tmin = Lib.constrain(tmin, 0, ax._categories.length - 1); - } - return tmin; - } - - var tType = dtick.charAt(0); - var dtNum = Number(dtick.substr(1)); - - // Dates: months (or years) - if(tType === 'M') { - var cnt = 0; - var t0 = tick0; - var t1, mult, newDTick; - - // This algorithm should work for *any* nonlinear (but close to linear!) - // tick spacing. Limit to 10 iterations, for gregorian months it's normally <=3. - while(cnt < 10) { - t1 = axes.tickIncrement(t0, dtick, axrev, ax.calendar); - if((t1 - r0) * (t0 - r0) <= 0) { - // t1 and t0 are on opposite sides of r0! we've succeeded! - if(axrev) return Math.min(t0, t1); - return Math.max(t0, t1); - } - mult = (r0 - ((t0 + t1) / 2)) / (t1 - t0); - newDTick = tType + ((Math.abs(Math.round(mult)) || 1) * dtNum); - t0 = axes.tickIncrement(t0, newDTick, mult < 0 ? !axrev : axrev, ax.calendar); - cnt++; - } - Lib.error('tickFirst did not converge', ax); - return t0; - } else if(tType === 'L') { - // Log scales: Linear, Digits - - return Math.log(sRound( - (Math.pow(10, r0) - tick0) / dtNum) * dtNum + tick0) / Math.LN10; - } else if(tType === 'D') { - var tickset = (dtick === 'D2') ? roundLog2 : roundLog1; - var frac = Lib.roundUp(Lib.mod(r0, 1), tickset, axrev); - - return Math.floor(r0) + - Math.log(d3.round(Math.pow(10, frac), 1)) / Math.LN10; - } else throw 'unrecognized dtick ' + String(dtick); -}; - -// draw the text for one tick. -// px,py are the location on gd.paper -// prefix is there so the x axis ticks can be dropped a line -// ax is the axis layout, x is the tick value -// hover is a (truthy) flag for whether to show numbers with a bit -// more precision for hovertext -axes.tickText = function(ax, x, hover, noSuffixPrefix) { - var out = tickTextObj(ax, x); - var arrayMode = ax.tickmode === 'array'; - var extraPrecision = hover || arrayMode; - var axType = ax.type; - // TODO multicategory, if we allow ticktext / tickvals - var tickVal2l = axType === 'category' ? ax.d2l_noadd : ax.d2l; - var i; - - if(arrayMode && Array.isArray(ax.ticktext)) { - var rng = Lib.simpleMap(ax.range, ax.r2l); - var minDiff = Math.abs(rng[1] - rng[0]) / 10000; - - for(i = 0; i < ax.ticktext.length; i++) { - if(Math.abs(x - tickVal2l(ax.tickvals[i])) < minDiff) break; - } - if(i < ax.ticktext.length) { - out.text = String(ax.ticktext[i]); - return out; - } - } - - function isHidden(showAttr) { - if(showAttr === undefined) return true; - if(hover) return showAttr === 'none'; - - var firstOrLast = { - first: ax._tmin, - last: ax._tmax - }[showAttr]; - - return showAttr !== 'all' && x !== firstOrLast; - } - - var hideexp = hover ? - 'never' : - ax.exponentformat !== 'none' && isHidden(ax.showexponent) ? 'hide' : ''; - - if(axType === 'date') formatDate(ax, out, hover, extraPrecision); - else if(axType === 'log') formatLog(ax, out, hover, extraPrecision, hideexp); - else if(axType === 'category') formatCategory(ax, out); - else if(axType === 'multicategory') formatMultiCategory(ax, out, hover); - else if(isAngular(ax)) formatAngle(ax, out, hover, extraPrecision, hideexp); - else formatLinear(ax, out, hover, extraPrecision, hideexp); - - // add prefix and suffix - if(!noSuffixPrefix) { - if(ax.tickprefix && !isHidden(ax.showtickprefix)) out.text = ax.tickprefix + out.text; - if(ax.ticksuffix && !isHidden(ax.showticksuffix)) out.text += ax.ticksuffix; - } - - // Setup ticks and grid lines boundaries - // at 1/2 a 'category' to the left/bottom - if(ax.tickson === 'boundaries' || ax.showdividers) { - var inbounds = function(v) { - var p = ax.l2p(v); - return p >= 0 && p <= ax._length ? v : null; - }; - - out.xbnd = [ - inbounds(out.x - 0.5), - inbounds(out.x + ax.dtick - 0.5) - ]; - } - - return out; -}; - -/** - * create text for a hover label on this axis, with special handling of - * log axes (where negative values can't be displayed but can appear in hover text) - * - * @param {object} ax: the axis to format text for - * @param {number} val: calcdata value to format - * @param {Optional(number)} val2: a second value to display - * - * @returns {string} `val` formatted as a string appropriate to this axis, or - * `val` and `val2` as a range (ie ' - ') if `val2` is provided and - * it's different from `val`. - */ -axes.hoverLabelText = function(ax, val, val2) { - if(val2 !== BADNUM && val2 !== val) { - return axes.hoverLabelText(ax, val) + ' - ' + axes.hoverLabelText(ax, val2); - } - - var logOffScale = (ax.type === 'log' && val <= 0); - var tx = axes.tickText(ax, ax.c2l(logOffScale ? -val : val), 'hover').text; - - if(logOffScale) { - return val === 0 ? '0' : MINUS_SIGN + tx; - } - - // TODO: should we do something special if the axis calendar and - // the data calendar are different? Somehow display both dates with - // their system names? Right now it will just display in the axis calendar - // but users could add the other one as text. - return tx; -}; - -function tickTextObj(ax, x, text) { - var tf = ax.tickfont || {}; - - return { - x: x, - dx: 0, - dy: 0, - text: text || '', - fontSize: tf.size, - font: tf.family, - fontColor: tf.color - }; -} - -function formatDate(ax, out, hover, extraPrecision) { - var tr = ax._tickround; - var fmt = (hover && ax.hoverformat) || axes.getTickFormat(ax); - - if(extraPrecision) { - // second or sub-second precision: extra always shows max digits. - // for other fields, extra precision just adds one field. - if(isNumeric(tr)) tr = 4; - else tr = {y: 'm', m: 'd', d: 'M', M: 'S', S: 4}[tr]; - } - - var dateStr = Lib.formatDate(out.x, fmt, tr, ax._dateFormat, ax.calendar, ax._extraFormat); - var headStr; - - var splitIndex = dateStr.indexOf('\n'); - if(splitIndex !== -1) { - headStr = dateStr.substr(splitIndex + 1); - dateStr = dateStr.substr(0, splitIndex); - } - - if(extraPrecision) { - // if extraPrecision led to trailing zeros, strip them off - // actually, this can lead to removing even more zeros than - // in the original rounding, but that's fine because in these - // contexts uniformity is not so important (if there's even - // anything to be uniform with!) - - // can we remove the whole time part? - if(dateStr === '00:00:00' || dateStr === '00:00') { - dateStr = headStr; - headStr = ''; - } else if(dateStr.length === 8) { - // strip off seconds if they're zero (zero fractional seconds - // are already omitted) - // but we never remove minutes and leave just hours - dateStr = dateStr.replace(/:00$/, ''); - } - } - - if(headStr) { - if(hover) { - // hover puts it all on one line, so headPart works best up front - // except for year headPart: turn this into "Jan 1, 2000" etc. - if(tr === 'd') dateStr += ', ' + headStr; - else dateStr = headStr + (dateStr ? ', ' + dateStr : ''); - } else if(!ax._inCalcTicks || (headStr !== ax._prevDateHead)) { - dateStr += '
' + headStr; - ax._prevDateHead = headStr; - } - } - - out.text = dateStr; -} - -function formatLog(ax, out, hover, extraPrecision, hideexp) { - var dtick = ax.dtick; - var x = out.x; - var tickformat = ax.tickformat; - var dtChar0 = typeof dtick === 'string' && dtick.charAt(0); - - if(hideexp === 'never') { - // If this is a hover label, then we must *never* hide the exponent - // for the sake of display, which could give the wrong value by - // potentially many orders of magnitude. If hideexp was 'never', then - // it's now succeeded by preventing the other condition from automating - // this choice. Thus we can unset it so that the axis formatting takes - // precedence. - hideexp = ''; - } - - if(extraPrecision && (dtChar0 !== 'L')) { - dtick = 'L3'; - dtChar0 = 'L'; - } - - if(tickformat || (dtChar0 === 'L')) { - out.text = numFormat(Math.pow(10, x), ax, hideexp, extraPrecision); - } else if(isNumeric(dtick) || ((dtChar0 === 'D') && (Lib.mod(x + 0.01, 1) < 0.1))) { - var p = Math.round(x); - var absP = Math.abs(p); - var exponentFormat = ax.exponentformat; - if(exponentFormat === 'power' || (isSIFormat(exponentFormat) && beyondSI(p))) { - if(p === 0) out.text = 1; - else if(p === 1) out.text = '10'; - else out.text = '10' + (p > 1 ? '' : MINUS_SIGN) + absP + ''; - - out.fontSize *= 1.25; - } else if((exponentFormat === 'e' || exponentFormat === 'E') && absP > 2) { - out.text = '1' + exponentFormat + (p > 0 ? '+' : MINUS_SIGN) + absP; - } else { - out.text = numFormat(Math.pow(10, x), ax, '', 'fakehover'); - if(dtick === 'D1' && ax._id.charAt(0) === 'y') { - out.dy -= out.fontSize / 6; - } - } - } else if(dtChar0 === 'D') { - out.text = String(Math.round(Math.pow(10, Lib.mod(x, 1)))); - out.fontSize *= 0.75; - } else throw 'unrecognized dtick ' + String(dtick); - - // if 9's are printed on log scale, move the 10's away a bit - if(ax.dtick === 'D1') { - var firstChar = String(out.text).charAt(0); - if(firstChar === '0' || firstChar === '1') { - if(ax._id.charAt(0) === 'y') { - out.dx -= out.fontSize / 4; - } else { - out.dy += out.fontSize / 2; - out.dx += (ax.range[1] > ax.range[0] ? 1 : -1) * - out.fontSize * (x < 0 ? 0.5 : 0.25); - } - } - } -} - -function formatCategory(ax, out) { - var tt = ax._categories[Math.round(out.x)]; - if(tt === undefined) tt = ''; - out.text = String(tt); -} - -function formatMultiCategory(ax, out, hover) { - var v = Math.round(out.x); - var cats = ax._categories[v] || []; - var tt = cats[1] === undefined ? '' : String(cats[1]); - var tt2 = cats[0] === undefined ? '' : String(cats[0]); - - if(hover) { - // TODO is this what we want? - out.text = tt2 + ' - ' + tt; - } else { - // setup for secondary labels - out.text = tt; - out.text2 = tt2; - } -} - -function formatLinear(ax, out, hover, extraPrecision, hideexp) { - if(hideexp === 'never') { - // If this is a hover label, then we must *never* hide the exponent - // for the sake of display, which could give the wrong value by - // potentially many orders of magnitude. If hideexp was 'never', then - // it's now succeeded by preventing the other condition from automating - // this choice. Thus we can unset it so that the axis formatting takes - // precedence. - hideexp = ''; - } else if(ax.showexponent === 'all' && Math.abs(out.x / ax.dtick) < 1e-6) { - // don't add an exponent to zero if we're showing all exponents - // so the only reason you'd show an exponent on zero is if it's the - // ONLY tick to get an exponent (first or last) - hideexp = 'hide'; - } - out.text = numFormat(out.x, ax, hideexp, extraPrecision); -} - -function formatAngle(ax, out, hover, extraPrecision, hideexp) { - if(ax.thetaunit === 'radians' && !hover) { - var num = out.x / 180; - - if(num === 0) { - out.text = '0'; - } else { - var frac = num2frac(num); - - if(frac[1] >= 100) { - out.text = numFormat(Lib.deg2rad(out.x), ax, hideexp, extraPrecision); - } else { - var isNeg = out.x < 0; - - if(frac[1] === 1) { - if(frac[0] === 1) out.text = 'π'; - else out.text = frac[0] + 'π'; - } else { - out.text = [ - '', frac[0], '', - '⁄', - '', frac[1], '', - 'π' - ].join(''); - } - - if(isNeg) out.text = MINUS_SIGN + out.text; - } - } - } else { - out.text = numFormat(out.x, ax, hideexp, extraPrecision); - } -} - -// inspired by -// https://github.com/yisibl/num2fraction/blob/master/index.js -function num2frac(num) { - function almostEq(a, b) { - return Math.abs(a - b) <= 1e-6; - } - - function findGCD(a, b) { - return almostEq(b, 0) ? a : findGCD(b, a % b); - } - - function findPrecision(n) { - var e = 1; - while(!almostEq(Math.round(n * e) / e, n)) { - e *= 10; - } - return e; - } - - var precision = findPrecision(num); - var number = num * precision; - var gcd = Math.abs(findGCD(number, precision)); - - return [ - // numerator - Math.round(number / gcd), - // denominator - Math.round(precision / gcd) - ]; -} - -// format a number (tick value) according to the axis settings -// new, more reliable procedure than d3.round or similar: -// add half the rounding increment, then stringify and truncate -// also automatically switch to sci. notation -var SIPREFIXES = ['f', 'p', 'n', 'μ', 'm', '', 'k', 'M', 'G', 'T']; - -function isSIFormat(exponentFormat) { - return exponentFormat === 'SI' || exponentFormat === 'B'; -} - -// are we beyond the range of common SI prefixes? -// 10^-16 -> 1x10^-16 -// 10^-15 -> 1f -// ... -// 10^14 -> 100T -// 10^15 -> 1x10^15 -// 10^16 -> 1x10^16 -function beyondSI(exponent) { - return exponent > 14 || exponent < -15; -} - -function numFormat(v, ax, fmtoverride, hover) { - var isNeg = v < 0; - // max number of digits past decimal point to show - var tickRound = ax._tickround; - var exponentFormat = fmtoverride || ax.exponentformat || 'B'; - var exponent = ax._tickexponent; - var tickformat = axes.getTickFormat(ax); - var separatethousands = ax.separatethousands; - - // special case for hover: set exponent just for this value, and - // add a couple more digits of precision over tick labels - if(hover) { - // make a dummy axis obj to get the auto rounding and exponent - var ah = { - exponentformat: exponentFormat, - dtick: ax.showexponent === 'none' ? ax.dtick : - (isNumeric(v) ? Math.abs(v) || 1 : 1), - // if not showing any exponents, don't change the exponent - // from what we calculate - range: ax.showexponent === 'none' ? ax.range.map(ax.r2d) : [0, v || 1] - }; - autoTickRound(ah); - tickRound = (Number(ah._tickround) || 0) + 4; - exponent = ah._tickexponent; - if(ax.hoverformat) tickformat = ax.hoverformat; - } - - if(tickformat) return ax._numFormat(tickformat)(v).replace(/-/g, MINUS_SIGN); - - // 'epsilon' - rounding increment - var e = Math.pow(10, -tickRound) / 2; - - // exponentFormat codes: - // 'e' (1.2e+6, default) - // 'E' (1.2E+6) - // 'SI' (1.2M) - // 'B' (same as SI except 10^9=B not G) - // 'none' (1200000) - // 'power' (1.2x10^6) - // 'hide' (1.2, use 3rd argument=='hide' to eg - // only show exponent on last tick) - if(exponentFormat === 'none') exponent = 0; - - // take the sign out, put it back manually at the end - // - makes cases easier - v = Math.abs(v); - if(v < e) { - // 0 is just 0, but may get exponent if it's the last tick - v = '0'; - isNeg = false; - } else { - v += e; - // take out a common exponent, if any - if(exponent) { - v *= Math.pow(10, -exponent); - tickRound += exponent; - } - // round the mantissa - if(tickRound === 0) v = String(Math.floor(v)); - else if(tickRound < 0) { - v = String(Math.round(v)); - v = v.substr(0, v.length + tickRound); - for(var i = tickRound; i < 0; i++) v += '0'; - } else { - v = String(v); - var dp = v.indexOf('.') + 1; - if(dp) v = v.substr(0, dp + tickRound).replace(/\.?0+$/, ''); - } - // insert appropriate decimal point and thousands separator - v = Lib.numSeparate(v, ax._separators, separatethousands); - } - - // add exponent - if(exponent && exponentFormat !== 'hide') { - if(isSIFormat(exponentFormat) && beyondSI(exponent)) exponentFormat = 'power'; - - var signedExponent; - if(exponent < 0) signedExponent = MINUS_SIGN + -exponent; - else if(exponentFormat !== 'power') signedExponent = '+' + exponent; - else signedExponent = String(exponent); - - if(exponentFormat === 'e' || exponentFormat === 'E') { - v += exponentFormat + signedExponent; - } else if(exponentFormat === 'power') { - v += '×10' + signedExponent + ''; - } else if(exponentFormat === 'B' && exponent === 9) { - v += 'B'; - } else if(isSIFormat(exponentFormat)) { - v += SIPREFIXES[exponent / 3 + 5]; - } - } - - // put sign back in and return - // replace standard minus character (which is technically a hyphen) - // with a true minus sign - if(isNeg) return MINUS_SIGN + v; - return v; -} - -axes.getTickFormat = function(ax) { - var i; - - function convertToMs(dtick) { - return typeof dtick !== 'string' ? dtick : Number(dtick.replace('M', '')) * ONEAVGMONTH; - } - - function compareLogTicks(left, right) { - var priority = ['L', 'D']; - if(typeof left === typeof right) { - if(typeof left === 'number') { - return left - right; - } else { - var leftPriority = priority.indexOf(left.charAt(0)); - var rightPriority = priority.indexOf(right.charAt(0)); - if(leftPriority === rightPriority) { - return Number(left.replace(/(L|D)/g, '')) - Number(right.replace(/(L|D)/g, '')); - } else { - return leftPriority - rightPriority; - } - } - } else { - return typeof left === 'number' ? 1 : -1; - } - } - - function isProperStop(dtick, range, convert) { - var convertFn = convert || function(x) { return x;}; - var leftDtick = range[0]; - var rightDtick = range[1]; - return ((!leftDtick && typeof leftDtick !== 'number') || convertFn(leftDtick) <= convertFn(dtick)) && - ((!rightDtick && typeof rightDtick !== 'number') || convertFn(rightDtick) >= convertFn(dtick)); - } - - function isProperLogStop(dtick, range) { - var isLeftDtickNull = range[0] === null; - var isRightDtickNull = range[1] === null; - var isDtickInRangeLeft = compareLogTicks(dtick, range[0]) >= 0; - var isDtickInRangeRight = compareLogTicks(dtick, range[1]) <= 0; - return (isLeftDtickNull || isDtickInRangeLeft) && (isRightDtickNull || isDtickInRangeRight); - } - - var tickstop, stopi; - if(ax.tickformatstops && ax.tickformatstops.length > 0) { - switch(ax.type) { - case 'date': - case 'linear': { - for(i = 0; i < ax.tickformatstops.length; i++) { - stopi = ax.tickformatstops[i]; - if(stopi.enabled && isProperStop(ax.dtick, stopi.dtickrange, convertToMs)) { - tickstop = stopi; - break; - } - } - break; - } - case 'log': { - for(i = 0; i < ax.tickformatstops.length; i++) { - stopi = ax.tickformatstops[i]; - if(stopi.enabled && isProperLogStop(ax.dtick, stopi.dtickrange)) { - tickstop = stopi; - break; - } - } - break; - } - default: - } - } - return tickstop ? tickstop.value : ax.tickformat; -}; - -// getSubplots - extract all subplot IDs we need -// as an array of items like 'xy', 'x2y', 'x2y2'... -// sorted by x (x,x2,x3...) then y -// optionally restrict to only subplots containing axis object ax -// -// NOTE: this is currently only used OUTSIDE plotly.js (toolpanel, webapp) -// ideally we get rid of it there (or just copy this there) and remove it here -axes.getSubplots = function(gd, ax) { - var subplotObj = gd._fullLayout._subplots; - var allSubplots = subplotObj.cartesian.concat(subplotObj.gl2d || []); - - var out = ax ? axes.findSubplotsWithAxis(allSubplots, ax) : allSubplots; - - out.sort(function(a, b) { - var aParts = a.substr(1).split('y'); - var bParts = b.substr(1).split('y'); - - if(aParts[0] === bParts[0]) return +aParts[1] - +bParts[1]; - return +aParts[0] - +bParts[0]; - }); - - return out; -}; - -// find all subplots with axis 'ax' -// NOTE: this is only used in axes.getSubplots (only used outside plotly.js) and -// gl2d/convert (where it restricts axis subplots to only those with gl2d) -axes.findSubplotsWithAxis = function(subplots, ax) { - var axMatch = new RegExp( - (ax._id.charAt(0) === 'x') ? ('^' + ax._id + 'y') : (ax._id + '$') - ); - var subplotsWithAx = []; - - for(var i = 0; i < subplots.length; i++) { - var sp = subplots[i]; - if(axMatch.test(sp)) subplotsWithAx.push(sp); - } - - return subplotsWithAx; -}; - -// makeClipPaths: prepare clipPaths for all single axes and all possible xy pairings -axes.makeClipPaths = function(gd) { - var fullLayout = gd._fullLayout; - - // for more info: https://github.com/plotly/plotly.js/issues/2595 - if(fullLayout._hasOnlyLargeSploms) return; - - var fullWidth = {_offset: 0, _length: fullLayout.width, _id: ''}; - var fullHeight = {_offset: 0, _length: fullLayout.height, _id: ''}; - var xaList = axes.list(gd, 'x', true); - var yaList = axes.list(gd, 'y', true); - var clipList = []; - var i, j; - - for(i = 0; i < xaList.length; i++) { - clipList.push({x: xaList[i], y: fullHeight}); - for(j = 0; j < yaList.length; j++) { - if(i === 0) clipList.push({x: fullWidth, y: yaList[j]}); - clipList.push({x: xaList[i], y: yaList[j]}); - } - } - - // selectors don't work right with camelCase tags, - // have to use class instead - // https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I - var axClips = fullLayout._clips.selectAll('.axesclip') - .data(clipList, function(d) { return d.x._id + d.y._id; }); - - axClips.enter().append('clipPath') - .classed('axesclip', true) - .attr('id', function(d) { return 'clip' + fullLayout._uid + d.x._id + d.y._id; }) - .append('rect'); - - axClips.exit().remove(); - - axClips.each(function(d) { - d3.select(this).select('rect').attr({ - x: d.x._offset || 0, - y: d.y._offset || 0, - width: d.x._length || 1, - height: d.y._length || 1 - }); - }); -}; - -/** - * Main multi-axis drawing routine! - * - * @param {DOM element} gd : graph div - * @param {string or array of strings} arg : polymorphic argument - * @param {object} opts: - * - @param {boolean} skipTitle : optional flag to skip axis title draw/update - * - * Signature 1: Axes.draw(gd, 'redraw') - * use this to clear and redraw all axes on graph - * - * Signature 2: Axes.draw(gd, '') - * use this to draw all axes on graph w/o the selectAll().remove() - * of the 'redraw' signature - * - * Signature 3: Axes.draw(gd, [axId, axId2, ...]) - * where the items are axis id string, - * use this to update multiple axes in one call - * - * N.B draw updates: - * - ax._r (stored range for use by zoom/pan) - * - ax._rl (stored linearized range for use by zoom/pan) - */ -axes.draw = function(gd, arg, opts) { - var fullLayout = gd._fullLayout; - - if(arg === 'redraw') { - fullLayout._paper.selectAll('g.subplot').each(function(d) { - var id = d[0]; - var plotinfo = fullLayout._plots[id]; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - plotinfo.xaxislayer.selectAll('.' + xa._id + 'tick').remove(); - plotinfo.yaxislayer.selectAll('.' + ya._id + 'tick').remove(); - plotinfo.xaxislayer.selectAll('.' + xa._id + 'tick2').remove(); - plotinfo.yaxislayer.selectAll('.' + ya._id + 'tick2').remove(); - plotinfo.xaxislayer.selectAll('.' + xa._id + 'divider').remove(); - plotinfo.yaxislayer.selectAll('.' + ya._id + 'divider').remove(); - - if(plotinfo.gridlayer) plotinfo.gridlayer.selectAll('path').remove(); - if(plotinfo.zerolinelayer) plotinfo.zerolinelayer.selectAll('path').remove(); - - fullLayout._infolayer.select('.g-' + xa._id + 'title').remove(); - fullLayout._infolayer.select('.g-' + ya._id + 'title').remove(); - }); - } - - var axList = (!arg || arg === 'redraw') ? axes.listIds(gd) : arg; - - return Lib.syncOrAsync(axList.map(function(axId) { - return function() { - if(!axId) return; - - var ax = axes.getFromId(gd, axId); - var axDone = axes.drawOne(gd, ax, opts); - - ax._r = ax.range.slice(); - ax._rl = Lib.simpleMap(ax._r, ax.r2l); - - return axDone; - }; - })); -}; - -/** - * Draw one cartesian axis - * - * @param {DOM element} gd - * @param {object} ax (full) axis object - * @param {object} opts - * - @param {boolean} skipTitle (set to true to skip axis title draw call) - */ -axes.drawOne = function(gd, ax, opts) { - opts = opts || {}; - - var i, sp, plotinfo; - - ax.setScale(); - - var fullLayout = gd._fullLayout; - var axId = ax._id; - var axLetter = axId.charAt(0); - var counterLetter = axes.counterLetter(axId); - var mainSubplot = ax._mainSubplot; - var mainLinePosition = ax._mainLinePosition; - var mainMirrorPosition = ax._mainMirrorPosition; - var mainPlotinfo = fullLayout._plots[mainSubplot]; - var mainAxLayer = mainPlotinfo[axLetter + 'axislayer']; - var subplotsWithAx = ax._subplotsWith; - - var vals = ax._vals = axes.calcTicks(ax); - - // Add a couple of axis properties that should cause us to recreate - // elements. Used in d3 data function. - var axInfo = [ax.mirror, mainLinePosition, mainMirrorPosition].join('_'); - for(i = 0; i < vals.length; i++) { - vals[i].axInfo = axInfo; - } - - if(!ax.visible) return; - - // stash selections to avoid DOM queries e.g. - // - stash tickLabels selection, so that drawTitle can use it to scoot title - ax._selections = {}; - // stash tick angle (including the computed 'auto' values) per tick-label class - ax._tickAngles = {}; - - var transFn = axes.makeTransFn(ax); - var tickVals; - // We remove zero lines, grid lines, and inside ticks if they're within 1px of the end - // The key case here is removing zero lines when the axis bound is zero - var valsClipped; - - if(ax.tickson === 'boundaries') { - var boundaryVals = getBoundaryVals(ax, vals); - valsClipped = axes.clipEnds(ax, boundaryVals); - tickVals = ax.ticks === 'inside' ? valsClipped : boundaryVals; - } else { - valsClipped = axes.clipEnds(ax, vals); - tickVals = ax.ticks === 'inside' ? valsClipped : vals; - } - - var gridVals = ax._gridVals = valsClipped; - var dividerVals = getDividerVals(ax, vals); - - if(!fullLayout._hasOnlyLargeSploms) { - // keep track of which subplots (by main conteraxis) we've already - // drawn grids for, so we don't overdraw overlaying subplots - var finishedGrids = {}; - - for(i = 0; i < subplotsWithAx.length; i++) { - sp = subplotsWithAx[i]; - plotinfo = fullLayout._plots[sp]; - - var counterAxis = plotinfo[counterLetter + 'axis']; - var mainCounterID = counterAxis._mainAxis._id; - if(finishedGrids[mainCounterID]) continue; - finishedGrids[mainCounterID] = 1; - - var gridPath = axLetter === 'x' ? - 'M0,' + counterAxis._offset + 'v' + counterAxis._length : - 'M' + counterAxis._offset + ',0h' + counterAxis._length; - - axes.drawGrid(gd, ax, { - vals: gridVals, - counterAxis: counterAxis, - layer: plotinfo.gridlayer.select('.' + axId), - path: gridPath, - transFn: transFn - }); - axes.drawZeroLine(gd, ax, { - counterAxis: counterAxis, - layer: plotinfo.zerolinelayer, - path: gridPath, - transFn: transFn - }); - } - } - - var tickSigns = axes.getTickSigns(ax); - var tickSubplots = []; - - if(ax.ticks) { - var mainTickPath = axes.makeTickPath(ax, mainLinePosition, tickSigns[2]); - var mirrorTickPath; - var fullTickPath; - if(ax._anchorAxis && ax.mirror && ax.mirror !== true) { - mirrorTickPath = axes.makeTickPath(ax, mainMirrorPosition, tickSigns[3]); - fullTickPath = mainTickPath + mirrorTickPath; - } else { - mirrorTickPath = ''; - fullTickPath = mainTickPath; - } - - var tickPath; - if(ax.showdividers && ax.ticks === 'outside' && ax.tickson === 'boundaries') { - var dividerLookup = {}; - for(i = 0; i < dividerVals.length; i++) { - dividerLookup[dividerVals[i].x] = 1; - } - tickPath = function(d) { - return dividerLookup[d.x] ? mirrorTickPath : fullTickPath; - }; - } else { - tickPath = fullTickPath; - } - - axes.drawTicks(gd, ax, { - vals: tickVals, - layer: mainAxLayer, - path: tickPath, - transFn: transFn - }); - - tickSubplots = Object.keys(ax._linepositions || {}); - } - - for(i = 0; i < tickSubplots.length; i++) { - sp = tickSubplots[i]; - plotinfo = fullLayout._plots[sp]; - // [bottom or left, top or right], free and main are handled above - var linepositions = ax._linepositions[sp] || []; - var spTickPath = axes.makeTickPath(ax, linepositions[0], tickSigns[0]) + - axes.makeTickPath(ax, linepositions[1], tickSigns[1]); - - axes.drawTicks(gd, ax, { - vals: tickVals, - layer: plotinfo[axLetter + 'axislayer'], - path: spTickPath, - transFn: transFn - }); - } - - var seq = []; - - // tick labels - for now just the main labels. - // TODO: mirror labels, esp for subplots - - seq.push(function() { - return axes.drawLabels(gd, ax, { - vals: vals, - layer: mainAxLayer, - transFn: transFn, - labelFns: axes.makeLabelFns(ax, mainLinePosition) - }); - }); - - if(ax.type === 'multicategory') { - var labelLength = 0; - var pad = {x: 2, y: 10}[axLetter]; - var sgn = tickSigns[2] * (ax.ticks === 'inside' ? -1 : 1); - - seq.push(function() { - labelLength += getLabelLevelSpan(ax, axId + 'tick') + pad; - labelLength += ax._tickAngles[axId + 'tick'] ? ax.tickfont.size * LINE_SPACING : 0; - - return axes.drawLabels(gd, ax, { - vals: getSecondaryLabelVals(ax, vals), - layer: mainAxLayer, - cls: axId + 'tick2', - repositionOnUpdate: true, - secondary: true, - transFn: transFn, - labelFns: axes.makeLabelFns(ax, mainLinePosition + labelLength * sgn) - }); - }); - - seq.push(function() { - labelLength += getLabelLevelSpan(ax, axId + 'tick2'); - ax._labelLength = labelLength; - - return drawDividers(gd, ax, { - vals: dividerVals, - layer: mainAxLayer, - path: axes.makeTickPath(ax, mainLinePosition, sgn, labelLength), - transFn: transFn - }); - }); - } - - function extendRange(range, newRange) { - range[0] = Math.min(range[0], newRange[0]); - range[1] = Math.max(range[1], newRange[1]); - } - - function calcBoundingBox() { - if(ax.showticklabels) { - var gdBB = gd.getBoundingClientRect(); - var bBox = mainAxLayer.node().getBoundingClientRect(); - - /* - * the way we're going to use this, the positioning that matters - * is relative to the origin of gd. This is important particularly - * if gd is scrollable, and may have been scrolled between the time - * we calculate this and the time we use it - */ - - ax._boundingBox = { - width: bBox.width, - height: bBox.height, - left: bBox.left - gdBB.left, - right: bBox.right - gdBB.left, - top: bBox.top - gdBB.top, - bottom: bBox.bottom - gdBB.top - }; - } else { - var gs = fullLayout._size; - var pos; - - // set dummy bbox for ticklabel-less axes - - if(axLetter === 'x') { - pos = ax.anchor === 'free' ? - gs.t + gs.h * (1 - ax.position) : - gs.t + gs.h * (1 - ax._anchorAxis.domain[{bottom: 0, top: 1}[ax.side]]); - - ax._boundingBox = { - top: pos, - bottom: pos, - left: ax._offset, - right: ax._offset + ax._length, - width: ax._length, - height: 0 - }; - } else { - pos = ax.anchor === 'free' ? - gs.l + gs.w * ax.position : - gs.l + gs.w * ax._anchorAxis.domain[{left: 0, right: 1}[ax.side]]; - - ax._boundingBox = { - left: pos, - right: pos, - bottom: ax._offset + ax._length, - top: ax._offset, - height: ax._length, - width: 0 - }; - } - } - - /* - * for spikelines: what's the full domain of positions in the - * opposite direction that are associated with this axis? - * This means any axes that we make a subplot with, plus the - * position of the axis itself if it's free. - */ - if(subplotsWithAx) { - var fullRange = ax._counterSpan = [Infinity, -Infinity]; - - for(var i = 0; i < subplotsWithAx.length; i++) { - var plotinfo = fullLayout._plots[subplotsWithAx[i]]; - var counterAxis = plotinfo[(axLetter === 'x') ? 'yaxis' : 'xaxis']; - - extendRange(fullRange, [ - counterAxis._offset, - counterAxis._offset + counterAxis._length - ]); - } - - if(ax.anchor === 'free') { - extendRange(fullRange, (axLetter === 'x') ? - [ax._boundingBox.bottom, ax._boundingBox.top] : - [ax._boundingBox.right, ax._boundingBox.left]); - } - } - } - - var hasRangeSlider = Registry.getComponentMethod('rangeslider', 'isVisible')(ax); - - function doAutoMargins() { - var s = ax.side.charAt(0); - var push; - var rangeSliderPush; - - if(hasRangeSlider) { - rangeSliderPush = Registry.getComponentMethod('rangeslider', 'autoMarginOpts')(gd, ax); - } - Plots.autoMargin(gd, rangeSliderAutoMarginID(ax), rangeSliderPush); - - if(ax.automargin && (!hasRangeSlider || s !== 'b')) { - push = {x: 0, y: 0, r: 0, l: 0, t: 0, b: 0}; - - var bbox = ax._boundingBox; - var titleOffset = getTitleOffset(gd, ax); - var anchorAxDomainIndex; - var offset; - - switch(axLetter + s) { - case 'xb': - anchorAxDomainIndex = 0; - offset = bbox.top - titleOffset; - push[s] = bbox.height; - break; - case 'xt': - anchorAxDomainIndex = 1; - offset = titleOffset - bbox.bottom; - push[s] = bbox.height; - break; - case 'yl': - anchorAxDomainIndex = 0; - offset = titleOffset - bbox.right; - push[s] = bbox.width; - break; - case 'yr': - anchorAxDomainIndex = 1; - offset = bbox.left - titleOffset; - push[s] = bbox.width; - break; - } - - push[counterLetter] = ax.anchor === 'free' ? - ax.position : - ax._anchorAxis.domain[anchorAxDomainIndex]; - - if(push[s] > 0) { - push[s] += offset; - } - - if(ax.title.text !== fullLayout._dfltTitle[axLetter]) { - push[s] += ax.title.font.size; - } - - if(axLetter === 'x' && bbox.width > 0) { - var rExtra = bbox.right - (ax._offset + ax._length); - if(rExtra > 0) { - push.x = 1; - push.r = rExtra; - } - var lExtra = ax._offset - bbox.left; - if(lExtra > 0) { - push.x = 0; - push.l = lExtra; - } - } else if(axLetter === 'y' && bbox.height > 0) { - var bExtra = bbox.bottom - (ax._offset + ax._length); - if(bExtra > 0) { - push.y = 0; - push.b = bExtra; - } - var tExtra = ax._offset - bbox.top; - if(tExtra > 0) { - push.y = 1; - push.t = tExtra; - } - } - } - - Plots.autoMargin(gd, axAutoMarginID(ax), push); - } - - seq.push(calcBoundingBox, doAutoMargins); - - if(!opts.skipTitle && - !(hasRangeSlider && ax._boundingBox && ax.side === 'bottom') - ) { - seq.push(function() { return drawTitle(gd, ax); }); - } - - return Lib.syncOrAsync(seq); -}; - -function getBoundaryVals(ax, vals) { - var out = []; - var i; - - // boundaryVals are never used for labels; - // no need to worry about the other tickTextObj keys - var _push = function(d, bndIndex) { - var xb = d.xbnd[bndIndex]; - if(xb !== null) { - out.push(Lib.extendFlat({}, d, {x: xb})); - } - }; - - if(vals.length) { - for(i = 0; i < vals.length; i++) { - _push(vals[i], 0); - } - _push(vals[i - 1], 1); - } - - return out; -} - -function getSecondaryLabelVals(ax, vals) { - var out = []; - var lookup = {}; - - for(var i = 0; i < vals.length; i++) { - var d = vals[i]; - if(lookup[d.text2]) { - lookup[d.text2].push(d.x); - } else { - lookup[d.text2] = [d.x]; - } - } - - for(var k in lookup) { - out.push(tickTextObj(ax, Lib.interp(lookup[k], 0.5), k)); - } - - return out; -} - -function getDividerVals(ax, vals) { - var out = []; - var i, current; - - // never used for labels; - // no need to worry about the other tickTextObj keys - var _push = function(d, bndIndex) { - var xb = d.xbnd[bndIndex]; - if(xb !== null) { - out.push(Lib.extendFlat({}, d, {x: xb})); - } - }; - - if(ax.showdividers && vals.length) { - for(i = 0; i < vals.length; i++) { - var d = vals[i]; - if(d.text2 !== current) { - _push(d, 0); - } - current = d.text2; - } - _push(vals[i - 1], 1); - } - - return out; -} - -function getLabelLevelSpan(ax, cls) { - var axLetter = ax._id.charAt(0); - var angle = ax._tickAngles[cls] || 0; - var rad = Lib.deg2rad(angle); - var sinA = Math.sin(rad); - var cosA = Math.cos(rad); - var maxX = 0; - var maxY = 0; - - // N.B. Drawing.bBox does not take into account rotate transforms - - ax._selections[cls].each(function() { - var thisLabel = selectTickLabel(this); - var bb = Drawing.bBox(thisLabel.node()); - var w = bb.width; - var h = bb.height; - maxX = Math.max(maxX, cosA * w, sinA * h); - maxY = Math.max(maxY, sinA * w, cosA * h); - }); - - return {x: maxY, y: maxX}[axLetter]; -} - -/** - * Which direction do the 'ax.side' values, and free ticks go? - * - * @param {object} ax (full) axis object - * - {string} _id (starting with 'x' or 'y') - * - {string} side - * - {string} ticks - * @return {array} all entries are either -1 or 1 - * - [0]: sign for top/right ticks (i.e. negative SVG direction) - * - [1]: sign for bottom/left ticks (i.e. positive SVG direction) - * - [2]: sign for ticks corresponding to 'ax.side' - * - [3]: sign for ticks mirroring 'ax.side' - */ -axes.getTickSigns = function(ax) { - var axLetter = ax._id.charAt(0); - var sideOpposite = {x: 'top', y: 'right'}[axLetter]; - var main = ax.side === sideOpposite ? 1 : -1; - var out = [-1, 1, main, -main]; - // then we flip if outside XOR y axis - if((ax.ticks !== 'inside') === (axLetter === 'x')) { - out = out.map(function(v) { return -v; }); - } - return out; -}; - -/** - * Make axis translate transform function - * - * @param {object} ax (full) axis object - * - {string} _id - * - {number} _offset - * - {fn} l2p - * @return {fn} function of calcTicks items - */ -axes.makeTransFn = function(ax) { - var axLetter = ax._id.charAt(0); - var offset = ax._offset; - return axLetter === 'x' ? - function(d) { return 'translate(' + (offset + ax.l2p(d.x)) + ',0)'; } : - function(d) { return 'translate(0,' + (offset + ax.l2p(d.x)) + ')'; }; -}; - -/** - * Make axis tick path string - * - * @param {object} ax (full) axis object - * - {string} _id - * - {number} ticklen - * - {number} linewidth - * @param {number} shift along direction of ticklen - * @param {1 or -1} sng tick sign - * @param {number (optional)} len tick length - * @return {string} - */ -axes.makeTickPath = function(ax, shift, sgn, len) { - len = len !== undefined ? len : ax.ticklen; - - var axLetter = ax._id.charAt(0); - var pad = (ax.linewidth || 1) / 2; - - return axLetter === 'x' ? - 'M0,' + (shift + pad * sgn) + 'v' + (len * sgn) : - 'M' + (shift + pad * sgn) + ',0h' + (len * sgn); -}; - -/** - * Make axis tick label x, y and anchor functions - * - * @param {object} ax (full) axis object - * - {string} _id - * - {string} ticks - * - {number} ticklen - * - {string} side - * - {number} linewidth - * - {number} tickfont.size - * - {boolean} showline - * @param {number} shift - * @param {number} angle [in degrees] ... - * @return {object} - * - {fn} xFn - * - {fn} yFn - * - {fn} anchorFn - * - {fn} heightFn - * - {number} labelStandoff (gap parallel to ticks) - * - {number} labelShift (gap perpendicular to ticks) - */ -axes.makeLabelFns = function(ax, shift, angle) { - var axLetter = ax._id.charAt(0); - var ticksOnOutsideLabels = ax.tickson !== 'boundaries' && ax.ticks === 'outside'; - - var labelStandoff = 0; - var labelShift = 0; - - if(ticksOnOutsideLabels) { - labelStandoff += ax.ticklen; - } - if(angle && ax.ticks === 'outside') { - var rad = Lib.deg2rad(angle); - labelStandoff = ax.ticklen * Math.cos(rad) + 1; - labelShift = ax.ticklen * Math.sin(rad); - } - if(ax.showticklabels && (ticksOnOutsideLabels || ax.showline)) { - labelStandoff += 0.2 * ax.tickfont.size; - } - labelStandoff += (ax.linewidth || 1) / 2; - - var out = { - labelStandoff: labelStandoff, - labelShift: labelShift - }; - - var x0, y0, ff, flipIt; - - if(axLetter === 'x') { - flipIt = ax.side === 'bottom' ? 1 : -1; - x0 = labelShift * flipIt; - y0 = shift + labelStandoff * flipIt; - ff = ax.side === 'bottom' ? 1 : -0.2; - - out.xFn = function(d) { return d.dx + x0; }; - out.yFn = function(d) { return d.dy + y0 + d.fontSize * ff; }; - out.anchorFn = function(d, a) { - if(!isNumeric(a) || a === 0 || a === 180) { - return 'middle'; - } - return (a * flipIt < 0) ? 'end' : 'start'; - }; - out.heightFn = function(d, a, h) { - return (a < -60 || a > 60) ? -0.5 * h : - ax.side === 'top' ? -h : - 0; - }; - } else if(axLetter === 'y') { - flipIt = ax.side === 'right' ? 1 : -1; - x0 = labelStandoff; - y0 = -labelShift * flipIt; - ff = Math.abs(ax.tickangle) === 90 ? 0.5 : 0; - - out.xFn = function(d) { return d.dx + shift + (x0 + d.fontSize * ff) * flipIt; }; - out.yFn = function(d) { return d.dy + y0 + d.fontSize * MID_SHIFT; }; - out.anchorFn = function(d, a) { - if(isNumeric(a) && Math.abs(a) === 90) { - return 'middle'; - } - return ax.side === 'right' ? 'start' : 'end'; - }; - out.heightFn = function(d, a, h) { - a *= ax.side === 'left' ? 1 : -1; - return a < -30 ? -h : - a < 30 ? -0.5 * h : - 0; - }; - } - - return out; -}; - -function tickDataFn(d) { - return [d.text, d.x, d.axInfo, d.font, d.fontSize, d.fontColor].join('_'); -} - -/** - * Draw axis ticks - * - * @param {DOM element} gd - * @param {object} ax (full) axis object - * - {string} _id - * - {string} ticks - * - {number} linewidth - * - {string} tickcolor - * @param {object} opts - * - {array of object} vals (calcTicks output-like) - * - {d3 selection} layer - * - {string or fn} path - * - {fn} transFn - * - {boolean} crisp (set to false to unset crisp-edge SVG rendering) - */ -axes.drawTicks = function(gd, ax, opts) { - opts = opts || {}; - - var cls = ax._id + 'tick'; - - var ticks = opts.layer.selectAll('path.' + cls) - .data(ax.ticks ? opts.vals : [], tickDataFn); - - ticks.exit().remove(); - - ticks.enter().append('path') - .classed(cls, 1) - .classed('ticks', 1) - .classed('crisp', opts.crisp !== false) - .call(Color.stroke, ax.tickcolor) - .style('stroke-width', Drawing.crispRound(gd, ax.tickwidth, 1) + 'px') - .attr('d', opts.path); - - ticks.attr('transform', opts.transFn); -}; - -/** - * Draw axis grid - * - * @param {DOM element} gd - * @param {object} ax (full) axis object - * - {string} _id - * - {boolean} showgrid - * - {string} gridcolor - * - {string} gridwidth - * - {boolean} zeroline - * - {string} type - * - {string} dtick - * @param {object} opts - * - {array of object} vals (calcTicks output-like) - * - {d3 selection} layer - * - {object} counterAxis (full axis object corresponding to counter axis) - * optional - only required if this axis supports zero lines - * - {string or fn} path - * - {fn} transFn - * - {boolean} crisp (set to false to unset crisp-edge SVG rendering) - */ -axes.drawGrid = function(gd, ax, opts) { - opts = opts || {}; - - var cls = ax._id + 'grid'; - var vals = opts.vals; - var counterAx = opts.counterAxis; - if(ax.showgrid === false) { - vals = []; - } else if(counterAx && axes.shouldShowZeroLine(gd, ax, counterAx)) { - var isArrayMode = ax.tickmode === 'array'; - for(var i = 0; i < vals.length; i++) { - var xi = vals[i].x; - if(isArrayMode ? !xi : (Math.abs(xi) < ax.dtick / 100)) { - vals = vals.slice(0, i).concat(vals.slice(i + 1)); - // In array mode you can in principle have multiple - // ticks at 0, so test them all. Otherwise once we found - // one we can stop. - if(isArrayMode) i--; - else break; - } - } - } - - var grid = opts.layer.selectAll('path.' + cls) - .data(vals, tickDataFn); - - grid.exit().remove(); - - grid.enter().append('path') - .classed(cls, 1) - .classed('crisp', opts.crisp !== false); - - ax._gw = Drawing.crispRound(gd, ax.gridwidth, 1); - - grid.attr('transform', opts.transFn) - .attr('d', opts.path) - .call(Color.stroke, ax.gridcolor || '#ddd') - .style('stroke-width', ax._gw + 'px'); - - if(typeof opts.path === 'function') grid.attr('d', opts.path); -}; - -/** - * Draw axis zero-line - * - * @param {DOM element} gd - * @param {object} ax (full) axis object - * - {string} _id - * - {boolean} zeroline - * - {number} zerolinewidth - * - {string} zerolinecolor - * - {number (optional)} _gridWidthCrispRound - * @param {object} opts - * - {d3 selection} layer - * - {object} counterAxis (full axis object corresponding to counter axis) - * - {string or fn} path - * - {fn} transFn - * - {boolean} crisp (set to false to unset crisp-edge SVG rendering) - */ -axes.drawZeroLine = function(gd, ax, opts) { - opts = opts || opts; - - var cls = ax._id + 'zl'; - var show = axes.shouldShowZeroLine(gd, ax, opts.counterAxis); - - var zl = opts.layer.selectAll('path.' + cls) - .data(show ? [{x: 0, id: ax._id}] : []); - - zl.exit().remove(); - - zl.enter().append('path') - .classed(cls, 1) - .classed('zl', 1) - .classed('crisp', opts.crisp !== false) - .each(function() { - // use the fact that only one element can enter to trigger a sort. - // If several zerolines enter at the same time we will sort once per, - // but generally this should be a minimal overhead. - opts.layer.selectAll('path').sort(function(da, db) { - return axisIds.idSort(da.id, db.id); - }); - }); - - zl.attr('transform', opts.transFn) - .attr('d', opts.path) - .call(Color.stroke, ax.zerolinecolor || Color.defaultLine) - .style('stroke-width', Drawing.crispRound(gd, ax.zerolinewidth, ax._gw || 1) + 'px'); -}; - -/** - * Draw axis tick labels - * - * @param {DOM element} gd - * @param {object} ax (full) axis object - * - {string} _id - * - {boolean} showticklabels - * - {number} tickangle - * - {object (optional)} _selections - * - {object} (optional)} _tickAngles - * @param {object} opts - * - {array of object} vals (calcTicks output-like) - * - {d3 selection} layer - * - {string (optional)} cls (node className) - * - {boolean} repositionOnUpdate (set to true to reposition update selection) - * - {boolean} secondary - * - {fn} transFn - * - {object} labelFns - * + {fn} xFn - * + {fn} yFn - * + {fn} anchorFn - * + {fn} heightFn - */ -axes.drawLabels = function(gd, ax, opts) { - opts = opts || {}; - - var axId = ax._id; - var axLetter = axId.charAt(0); - var cls = opts.cls || axId + 'tick'; - var vals = opts.vals; - var labelFns = opts.labelFns; - var tickAngle = opts.secondary ? 0 : ax.tickangle; - var lastAngle = (ax._tickAngles || {})[cls]; - - var tickLabels = opts.layer.selectAll('g.' + cls) - .data(ax.showticklabels ? vals : [], tickDataFn); - - var labelsReady = []; - - tickLabels.enter().append('g') - .classed(cls, 1) - .append('text') - // only so tex has predictable alignment that we can - // alter later - .attr('text-anchor', 'middle') - .each(function(d) { - var thisLabel = d3.select(this); - var newPromise = gd._promises.length; - - thisLabel - .call(svgTextUtils.positionText, labelFns.xFn(d), labelFns.yFn(d)) - .call(Drawing.font, d.font, d.fontSize, d.fontColor) - .text(d.text) - .call(svgTextUtils.convertToTspans, gd); - - if(gd._promises[newPromise]) { - // if we have an async label, we'll deal with that - // all here so take it out of gd._promises and - // instead position the label and promise this in - // labelsReady - labelsReady.push(gd._promises.pop().then(function() { - positionLabels(thisLabel, tickAngle); - })); - } else { - // sync label: just position it now. - positionLabels(thisLabel, tickAngle); - } - }); - - tickLabels.exit().remove(); - - if(opts.repositionOnUpdate) { - tickLabels.each(function(d) { - d3.select(this).select('text') - .call(svgTextUtils.positionText, labelFns.xFn(d), labelFns.yFn(d)); - }); - } - - function positionLabels(s, angle) { - s.each(function(d) { - var thisLabel = d3.select(this); - var mathjaxGroup = thisLabel.select('.text-math-group'); - var anchor = labelFns.anchorFn(d, angle); - - var transform = opts.transFn.call(thisLabel.node(), d) + - ((isNumeric(angle) && +angle !== 0) ? - (' rotate(' + angle + ',' + labelFns.xFn(d) + ',' + - (labelFns.yFn(d) - d.fontSize / 2) + ')') : - ''); - - // how much to shift a multi-line label to center it vertically. - var nLines = svgTextUtils.lineCount(thisLabel); - var lineHeight = LINE_SPACING * d.fontSize; - var anchorHeight = labelFns.heightFn(d, isNumeric(angle) ? +angle : 0, (nLines - 1) * lineHeight); - - if(anchorHeight) { - transform += ' translate(0, ' + anchorHeight + ')'; - } - - if(mathjaxGroup.empty()) { - thisLabel.select('text').attr({ - transform: transform, - 'text-anchor': anchor - }); - } else { - var mjWidth = Drawing.bBox(mathjaxGroup.node()).width; - var mjShift = mjWidth * {end: -0.5, start: 0.5}[anchor]; - mathjaxGroup.attr('transform', transform + (mjShift ? 'translate(' + mjShift + ',0)' : '')); - } - }); - } - - // make sure all labels are correctly positioned at their base angle - // the positionLabels call above is only for newly drawn labels. - // do this without waiting, using the last calculated angle to - // minimize flicker, then do it again when we know all labels are - // there, putting back the prescribed angle to check for overlaps. - positionLabels(tickLabels, lastAngle || tickAngle); - - function allLabelsReady() { - return labelsReady.length && Promise.all(labelsReady); - } - - function fixLabelOverlaps() { - positionLabels(tickLabels, tickAngle); - - var autoangle = null; - - // check for auto-angling if x labels overlap - // don't auto-angle at all for log axes with - // base and digit format - if(vals.length && axLetter === 'x' && !isNumeric(tickAngle) && - (ax.type !== 'log' || String(ax.dtick).charAt(0) !== 'D') - ) { - autoangle = 0; - - var maxFontSize = 0; - var lbbArray = []; - var i; - - tickLabels.each(function(d) { - maxFontSize = Math.max(maxFontSize, d.fontSize); - - var x = ax.l2p(d.x); - var thisLabel = selectTickLabel(this); - var bb = Drawing.bBox(thisLabel.node()); - - lbbArray.push({ - // ignore about y, just deal with x overlaps - top: 0, - bottom: 10, - height: 10, - left: x - bb.width / 2, - // impose a 2px gap - right: x + bb.width / 2 + 2, - width: bb.width + 2 - }); - }); - - if((ax.tickson === 'boundaries' || ax.showdividers) && !opts.secondary) { - var gap = 2; - if(ax.ticks) gap += ax.tickwidth / 2; - - // TODO should secondary labels also fall into this fix-overlap regime? - - for(i = 0; i < lbbArray.length; i++) { - var xbnd = vals[i].xbnd; - var lbb = lbbArray[i]; - if( - (xbnd[0] !== null && (lbb.left - ax.l2p(xbnd[0])) < gap) || - (xbnd[1] !== null && (ax.l2p(xbnd[1]) - lbb.right) < gap) - ) { - autoangle = 90; - break; - } - } - } else { - var vLen = vals.length; - var tickSpacing = Math.abs((vals[vLen - 1].x - vals[0].x) * ax._m) / (vLen - 1); - var rotate90 = (tickSpacing < maxFontSize * 2.5) || ax.type === 'multicategory'; - - // any overlap at all - set 30 degrees or 90 degrees - for(i = 0; i < lbbArray.length - 1; i++) { - if(Lib.bBoxIntersect(lbbArray[i], lbbArray[i + 1])) { - autoangle = rotate90 ? 90 : 30; - break; - } - } - } - - if(autoangle) { - positionLabels(tickLabels, autoangle); - } - } - - if(ax._tickAngles) { - ax._tickAngles[cls] = autoangle === null ? - (isNumeric(tickAngle) ? tickAngle : 0) : - autoangle; - } - } - - if(ax._selections) { - ax._selections[cls] = tickLabels; - } - - var done = Lib.syncOrAsync([allLabelsReady, fixLabelOverlaps]); - if(done && done.then) gd._promises.push(done); - return done; -}; - -/** - * Draw axis dividers - * - * @param {DOM element} gd - * @param {object} ax (full) axis object - * - {string} _id - * - {string} showdividers - * - {number} dividerwidth - * - {string} dividercolor - * @param {object} opts - * - {array of object} vals (calcTicks output-like) - * - {d3 selection} layer - * - {fn} path - * - {fn} transFn - */ -function drawDividers(gd, ax, opts) { - var cls = ax._id + 'divider'; - var vals = opts.vals; - - var dividers = opts.layer.selectAll('path.' + cls) - .data(vals, tickDataFn); - - dividers.exit().remove(); - - dividers.enter().insert('path', ':first-child') - .classed(cls, 1) - .classed('crisp', 1) - .call(Color.stroke, ax.dividercolor) - .style('stroke-width', Drawing.crispRound(gd, ax.dividerwidth, 1) + 'px'); - - dividers - .attr('transform', opts.transFn) - .attr('d', opts.path); -} - -function getTitleOffset(gd, ax) { - var gs = gd._fullLayout._size; - var axLetter = ax._id.charAt(0); - var side = ax.side; - var anchorAxis; - - if(ax.anchor !== 'free') { - anchorAxis = axisIds.getFromId(gd, ax.anchor); - } else if(axLetter === 'x') { - anchorAxis = { - _offset: gs.t + (1 - (ax.position || 0)) * gs.h, - _length: 0 - }; - } else if(axLetter === 'y') { - anchorAxis = { - _offset: gs.l + (ax.position || 0) * gs.w, - _length: 0 - }; - } - - if(side === 'top' || side === 'left') { - return anchorAxis._offset; - } else if(side === 'bottom' || side === 'right') { - return anchorAxis._offset + anchorAxis._length; - } -} - -function drawTitle(gd, ax) { - var fullLayout = gd._fullLayout; - var axId = ax._id; - var axLetter = axId.charAt(0); - var fontSize = ax.title.font.size; - - var titleStandoff; - if(ax.type === 'multicategory') { - titleStandoff = ax._labelLength; - } else { - var offsetBase = 1.5; - titleStandoff = 10 + fontSize * offsetBase + (ax.linewidth ? ax.linewidth - 1 : 0); - } - - var titleOffset = getTitleOffset(gd, ax); - - var transform, x, y; - - if(axLetter === 'x') { - x = ax._offset + ax._length / 2; - - if(ax.side === 'top') { - y = -titleStandoff - fontSize * (ax.showticklabels ? 1 : 0); - } else { - y = titleStandoff + fontSize * (ax.showticklabels ? 1.5 : 0.5); - } - y += titleOffset; - } else { - y = ax._offset + ax._length / 2; - - if(ax.side === 'right') { - x = titleStandoff + fontSize * (ax.showticklabels ? 1 : 0.5); - } else { - x = -titleStandoff - fontSize * (ax.showticklabels ? 0.5 : 0); - } - x += titleOffset; - - transform = {rotate: '-90', offset: 0}; - } - - var avoid; - - if(ax.type !== 'multicategory') { - var tickLabels = ax._selections[ax._id + 'tick']; - - avoid = { - selection: tickLabels, - side: ax.side - }; - - if(tickLabels && tickLabels.node() && tickLabels.node().parentNode) { - var translation = Drawing.getTranslate(tickLabels.node().parentNode); - avoid.offsetLeft = translation.x; - avoid.offsetTop = translation.y; - } - } - - return Titles.draw(gd, axId + 'title', { - propContainer: ax, - propName: ax._name + '.title.text', - placeholder: fullLayout._dfltTitle[axLetter], - avoid: avoid, - transform: transform, - attributes: {x: x, y: y, 'text-anchor': 'middle'} - }); -} - -axes.shouldShowZeroLine = function(gd, ax, counterAxis) { - var rng = Lib.simpleMap(ax.range, ax.r2l); - return ( - (rng[0] * rng[1] <= 0) && - ax.zeroline && - (ax.type === 'linear' || ax.type === '-') && - ax._gridVals.length && - ( - clipEnds(ax, 0) || - !anyCounterAxLineAtZero(gd, ax, counterAxis, rng) || - hasBarsOrFill(gd, ax) - ) - ); -}; - -axes.clipEnds = function(ax, vals) { - return vals.filter(function(d) { return clipEnds(ax, d.x); }); -}; - -function clipEnds(ax, l) { - var p = ax.l2p(l); - return (p > 1 && p < ax._length - 1); -} - -function anyCounterAxLineAtZero(gd, ax, counterAxis, rng) { - var mainCounterAxis = counterAxis._mainAxis; - if(!mainCounterAxis) return; - - var fullLayout = gd._fullLayout; - var axLetter = ax._id.charAt(0); - var counterLetter = axes.counterLetter(ax._id); - - var zeroPosition = ax._offset + ( - ((Math.abs(rng[0]) < Math.abs(rng[1])) === (axLetter === 'x')) ? - 0 : ax._length - ); - - function lineNearZero(ax2) { - if(!ax2.showline || !ax2.linewidth) return false; - var tolerance = Math.max((ax2.linewidth + ax.zerolinewidth) / 2, 1); - - function closeEnough(pos2) { - return typeof pos2 === 'number' && Math.abs(pos2 - zeroPosition) < tolerance; - } - - if(closeEnough(ax2._mainLinePosition) || closeEnough(ax2._mainMirrorPosition)) { - return true; - } - var linePositions = ax2._linepositions || {}; - for(var k in linePositions) { - if(closeEnough(linePositions[k][0]) || closeEnough(linePositions[k][1])) { - return true; - } - } - } - - var plotinfo = fullLayout._plots[counterAxis._mainSubplot]; - if(!(plotinfo.mainplotinfo || plotinfo).overlays.length) { - return lineNearZero(counterAxis, zeroPosition); - } - - var counterLetterAxes = axes.list(gd, counterLetter); - for(var i = 0; i < counterLetterAxes.length; i++) { - var counterAxis2 = counterLetterAxes[i]; - if( - counterAxis2._mainAxis === mainCounterAxis && - lineNearZero(counterAxis2, zeroPosition) - ) { - return true; - } - } -} - -function hasBarsOrFill(gd, ax) { - var fullData = gd._fullData; - var subplot = ax._mainSubplot; - var axLetter = ax._id.charAt(0); - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - - if(trace.visible === true && (trace.xaxis + trace.yaxis) === subplot) { - if( - Registry.traceIs(trace, 'bar-like') && - trace.orientation === {x: 'h', y: 'v'}[axLetter] - ) return true; - - if( - trace.fill && - trace.fill.charAt(trace.fill.length - 1) === axLetter - ) return true; - } - } - return false; -} - -function selectTickLabel(gTick) { - var s = d3.select(gTick); - var mj = s.select('.text-math-group'); - return mj.empty() ? s.select('text') : mj; -} - -/** - * Find all margin pushers for 2D axes and reserve them for later use - * Both label and rangeslider automargin calculations happen later so - * we need to explicitly allow their ids in order to not delete them. - * - * TODO: can we pull the actual automargin calls forward to avoid this hack? - * We're probably also doing multiple redraws in this case, would be faster - * if we can just do the whole calculation ahead of time and draw once. - */ -axes.allowAutoMargin = function(gd) { - var axList = axes.list(gd, '', true); - for(var i = 0; i < axList.length; i++) { - var ax = axList[i]; - if(ax.automargin) { - Plots.allowAutoMargin(gd, axAutoMarginID(ax)); - } - if(Registry.getComponentMethod('rangeslider', 'isVisible')(ax)) { - Plots.allowAutoMargin(gd, rangeSliderAutoMarginID(ax)); - } - } -}; - -function axAutoMarginID(ax) { return ax._id + '.automargin'; } -function rangeSliderAutoMarginID(ax) { return ax._id + '.rangeslider'; } - -// swap all the presentation attributes of the axes showing these traces -axes.swap = function(gd, traces) { - var axGroups = makeAxisGroups(gd, traces); - - for(var i = 0; i < axGroups.length; i++) { - swapAxisGroup(gd, axGroups[i].x, axGroups[i].y); - } -}; - -function makeAxisGroups(gd, traces) { - var groups = []; - var i, j; - - for(i = 0; i < traces.length; i++) { - var groupsi = []; - var xi = gd._fullData[traces[i]].xaxis; - var yi = gd._fullData[traces[i]].yaxis; - if(!xi || !yi) continue; // not a 2D cartesian trace? - - for(j = 0; j < groups.length; j++) { - if(groups[j].x.indexOf(xi) !== -1 || groups[j].y.indexOf(yi) !== -1) { - groupsi.push(j); - } - } - - if(!groupsi.length) { - groups.push({x: [xi], y: [yi]}); - continue; - } - - var group0 = groups[groupsi[0]]; - var groupj; - - if(groupsi.length > 1) { - for(j = 1; j < groupsi.length; j++) { - groupj = groups[groupsi[j]]; - mergeAxisGroups(group0.x, groupj.x); - mergeAxisGroups(group0.y, groupj.y); - } - } - mergeAxisGroups(group0.x, [xi]); - mergeAxisGroups(group0.y, [yi]); - } - - return groups; -} - -function mergeAxisGroups(intoSet, fromSet) { - for(var i = 0; i < fromSet.length; i++) { - if(intoSet.indexOf(fromSet[i]) === -1) intoSet.push(fromSet[i]); - } -} - -function swapAxisGroup(gd, xIds, yIds) { - var xFullAxes = []; - var yFullAxes = []; - var layout = gd.layout; - var i, j; - - for(i = 0; i < xIds.length; i++) xFullAxes.push(axes.getFromId(gd, xIds[i])); - for(i = 0; i < yIds.length; i++) yFullAxes.push(axes.getFromId(gd, yIds[i])); - - var allAxKeys = Object.keys(axAttrs); - - var noSwapAttrs = [ - 'anchor', 'domain', 'overlaying', 'position', 'side', 'tickangle', 'editType' - ]; - var numericTypes = ['linear', 'log']; - - for(i = 0; i < allAxKeys.length; i++) { - var keyi = allAxKeys[i]; - var xVal = xFullAxes[0][keyi]; - var yVal = yFullAxes[0][keyi]; - var allEqual = true; - var coerceLinearX = false; - var coerceLinearY = false; - if(keyi.charAt(0) === '_' || typeof xVal === 'function' || - noSwapAttrs.indexOf(keyi) !== -1) { - continue; - } - for(j = 1; j < xFullAxes.length && allEqual; j++) { - var xVali = xFullAxes[j][keyi]; - if(keyi === 'type' && numericTypes.indexOf(xVal) !== -1 && - numericTypes.indexOf(xVali) !== -1 && xVal !== xVali) { - // type is special - if we find a mixture of linear and log, - // coerce them all to linear on flipping - coerceLinearX = true; - } else if(xVali !== xVal) allEqual = false; - } - for(j = 1; j < yFullAxes.length && allEqual; j++) { - var yVali = yFullAxes[j][keyi]; - if(keyi === 'type' && numericTypes.indexOf(yVal) !== -1 && - numericTypes.indexOf(yVali) !== -1 && yVal !== yVali) { - // type is special - if we find a mixture of linear and log, - // coerce them all to linear on flipping - coerceLinearY = true; - } else if(yFullAxes[j][keyi] !== yVal) allEqual = false; - } - if(allEqual) { - if(coerceLinearX) layout[xFullAxes[0]._name].type = 'linear'; - if(coerceLinearY) layout[yFullAxes[0]._name].type = 'linear'; - swapAxisAttrs(layout, keyi, xFullAxes, yFullAxes, gd._fullLayout._dfltTitle); - } - } - - // now swap x&y for any annotations anchored to these x & y - for(i = 0; i < gd._fullLayout.annotations.length; i++) { - var ann = gd._fullLayout.annotations[i]; - if(xIds.indexOf(ann.xref) !== -1 && - yIds.indexOf(ann.yref) !== -1) { - Lib.swapAttrs(layout.annotations[i], ['?']); - } - } -} - -function swapAxisAttrs(layout, key, xFullAxes, yFullAxes, dfltTitle) { - // in case the value is the default for either axis, - // look at the first axis in each list and see if - // this key's value is undefined - var np = Lib.nestedProperty; - var xVal = np(layout[xFullAxes[0]._name], key).get(); - var yVal = np(layout[yFullAxes[0]._name], key).get(); - var i; - - if(key === 'title') { - // special handling of placeholder titles - if(xVal && xVal.text === dfltTitle.x) { - xVal.text = dfltTitle.y; - } - if(yVal && yVal.text === dfltTitle.y) { - yVal.text = dfltTitle.x; - } - } - - for(i = 0; i < xFullAxes.length; i++) { - np(layout, xFullAxes[i]._name + '.' + key).set(yVal); - } - for(i = 0; i < yFullAxes.length; i++) { - np(layout, yFullAxes[i]._name + '.' + key).set(xVal); - } -} - -function isAngular(ax) { - return ax._id === 'angularaxis'; -} - -},{"../../components/color":593,"../../components/drawing":614,"../../components/titles":681,"../../constants/alignment":688,"../../constants/numerical":695,"../../lib":719,"../../lib/svg_text_utils":743,"../../plots/plots":828,"../../registry":847,"./autorange":766,"./axis_autotype":768,"./axis_ids":770,"./clean_ticks":772,"./layout_attributes":779,"./set_convert":785,"d3":163,"fast-isnumeric":225}],768:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -module.exports = function autoType(array, calendar, opts) { - opts = opts || {}; - - if(!opts.noMultiCategory && multiCategory(array)) return 'multicategory'; - if(moreDates(array, calendar)) return 'date'; - if(category(array)) return 'category'; - if(linearOK(array)) return 'linear'; - else return '-'; -}; - -// is there at least one number in array? If not, we should leave -// ax.type empty so it can be autoset later -function linearOK(array) { - if(!array) return false; - - for(var i = 0; i < array.length; i++) { - if(isNumeric(array[i])) return true; - } - - return false; -} - -// does the array a have mostly dates rather than numbers? -// note: some values can be neither (such as blanks, text) -// 2- or 4-digit integers can be both, so require twice as many -// dates as non-dates, to exclude cases with mostly 2 & 4 digit -// numbers and a few dates -// as with categories, consider DISTINCT values only. -function moreDates(a, calendar) { - // test at most 1000 points, evenly spaced - var inc = Math.max(1, (a.length - 1) / 1000); - var dcnt = 0; - var ncnt = 0; - var seen = {}; - - for(var i = 0; i < a.length; i += inc) { - var ai = a[Math.round(i)]; - var stri = String(ai); - if(seen[stri]) continue; - seen[stri] = 1; - - if(Lib.isDateTime(ai, calendar)) dcnt += 1; - if(isNumeric(ai)) ncnt += 1; - } - - return (dcnt > ncnt * 2); -} - -// are the (x,y)-values in gd.data mostly text? -// require twice as many DISTINCT categories as distinct numbers -function category(a) { - // test at most 1000 points - var inc = Math.max(1, (a.length - 1) / 1000); - var curvenums = 0; - var curvecats = 0; - var seen = {}; - - for(var i = 0; i < a.length; i += inc) { - var ai = a[Math.round(i)]; - var stri = String(ai); - if(seen[stri]) continue; - seen[stri] = 1; - - if(typeof ai === 'boolean') curvecats++; - else if(Lib.cleanNumber(ai) !== BADNUM) curvenums++; - else if(typeof ai === 'string') curvecats++; - } - - return curvecats > curvenums * 2; -} - -// very-loose requirements for multicategory, -// trace modules that should never auto-type to multicategory -// should be declared with 'noMultiCategory' -function multiCategory(a) { - return Lib.isArrayOrTypedArray(a[0]) && Lib.isArrayOrTypedArray(a[1]); -} - -},{"../../constants/numerical":695,"../../lib":719,"fast-isnumeric":225}],769:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); - -var layoutAttributes = _dereq_('./layout_attributes'); -var handleTickValueDefaults = _dereq_('./tick_value_defaults'); -var handleTickMarkDefaults = _dereq_('./tick_mark_defaults'); -var handleTickLabelDefaults = _dereq_('./tick_label_defaults'); -var handleCategoryOrderDefaults = _dereq_('./category_order_defaults'); -var handleLineGridDefaults = _dereq_('./line_grid_defaults'); -var setConvert = _dereq_('./set_convert'); - -/** - * options: object containing: - * - * letter: 'x' or 'y' - * title: name of the axis (ie 'Colorbar') to go in default title - * font: the default font to inherit - * outerTicks: boolean, should ticks default to outside? - * showGrid: boolean, should gridlines be shown by default? - * noHover: boolean, this axis doesn't support hover effects? - * noTickson: boolean, this axis doesn't support 'tickson' - * data: the plot data, used to manage categories - * bgColor: the plot background color, to calculate default gridline colors - * calendar: - * splomStash: - * visibleDflt: boolean - * reverseDflt: boolean - * automargin: boolean - */ -module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, options, layoutOut) { - var letter = options.letter; - var font = options.font || {}; - var splomStash = options.splomStash || {}; - - var visible = coerce('visible', !options.visibleDflt); - - var axType = containerOut.type; - - if(axType === 'date') { - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleDefaults'); - handleCalendarDefaults(containerIn, containerOut, 'calendar', options.calendar); - } - - setConvert(containerOut, layoutOut); - - var autorangeDflt = !containerOut.isValidRange(containerIn.range); - if(autorangeDflt && options.reverseDflt) autorangeDflt = 'reversed'; - var autoRange = coerce('autorange', autorangeDflt); - if(autoRange && (axType === 'linear' || axType === '-')) coerce('rangemode'); - - coerce('range'); - containerOut.cleanRange(); - - handleCategoryOrderDefaults(containerIn, containerOut, coerce, options); - - if(axType !== 'category' && !options.noHover) coerce('hoverformat'); - - var dfltColor = coerce('color'); - // if axis.color was provided, use it for fonts too; otherwise, - // inherit from global font color in case that was provided. - // Compare to dflt rather than to containerIn, so we can provide color via - // template too. - var dfltFontColor = (dfltColor !== layoutAttributes.color.dflt) ? dfltColor : font.color; - // try to get default title from splom trace, fallback to graph-wide value - var dfltTitle = splomStash.label || layoutOut._dfltTitle[letter]; - - handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options, {pass: 1}); - if(!visible) return containerOut; - - coerce('title.text', dfltTitle); - Lib.coerceFont(coerce, 'title.font', { - family: font.family, - size: Math.round(font.size * 1.2), - color: dfltFontColor - }); - - handleTickValueDefaults(containerIn, containerOut, coerce, axType); - handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options, {pass: 2}); - handleTickMarkDefaults(containerIn, containerOut, coerce, options); - handleLineGridDefaults(containerIn, containerOut, coerce, { - dfltColor: dfltColor, - bgColor: options.bgColor, - showGrid: options.showGrid, - attributes: layoutAttributes - }); - - if(containerOut.showline || containerOut.ticks) coerce('mirror'); - - if(options.automargin) coerce('automargin'); - - var isMultiCategory = containerOut.type === 'multicategory'; - - if(!options.noTickson && - (containerOut.type === 'category' || isMultiCategory) && - (containerOut.ticks || containerOut.showgrid) - ) { - var ticksonDflt; - if(isMultiCategory) ticksonDflt = 'boundaries'; - coerce('tickson', ticksonDflt); - } - - if(isMultiCategory) { - var showDividers = coerce('showdividers'); - if(showDividers) { - coerce('dividercolor'); - coerce('dividerwidth'); - } - } - - return containerOut; -}; - -},{"../../lib":719,"../../registry":847,"./category_order_defaults":771,"./layout_attributes":779,"./line_grid_defaults":781,"./set_convert":785,"./tick_label_defaults":786,"./tick_mark_defaults":787,"./tick_value_defaults":788}],770:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); - -var constants = _dereq_('./constants'); - - -// convert between axis names (xaxis, xaxis2, etc, elements of gd.layout) -// and axis id's (x, x2, etc). Would probably have ditched 'xaxis' -// completely in favor of just 'x' if it weren't ingrained in the API etc. -exports.id2name = function id2name(id) { - if(typeof id !== 'string' || !id.match(constants.AX_ID_PATTERN)) return; - var axNum = id.substr(1); - if(axNum === '1') axNum = ''; - return id.charAt(0) + 'axis' + axNum; -}; - -exports.name2id = function name2id(name) { - if(!name.match(constants.AX_NAME_PATTERN)) return; - var axNum = name.substr(5); - if(axNum === '1') axNum = ''; - return name.charAt(0) + axNum; -}; - -exports.cleanId = function cleanId(id, axLetter) { - if(!id.match(constants.AX_ID_PATTERN)) return; - if(axLetter && id.charAt(0) !== axLetter) return; - - var axNum = id.substr(1).replace(/^0+/, ''); - if(axNum === '1') axNum = ''; - return id.charAt(0) + axNum; -}; - -// get all axis objects, as restricted in listNames -exports.list = function(gd, axLetter, only2d) { - var fullLayout = gd._fullLayout; - if(!fullLayout) return []; - - var idList = exports.listIds(gd, axLetter); - var out = new Array(idList.length); - var i; - - for(i = 0; i < idList.length; i++) { - var idi = idList[i]; - out[i] = fullLayout[idi.charAt(0) + 'axis' + idi.substr(1)]; - } - - if(!only2d) { - var sceneIds3D = fullLayout._subplots.gl3d || []; - - for(i = 0; i < sceneIds3D.length; i++) { - var scene = fullLayout[sceneIds3D[i]]; - - if(axLetter) out.push(scene[axLetter + 'axis']); - else out.push(scene.xaxis, scene.yaxis, scene.zaxis); - } - } - - return out; -}; - -// get all axis ids, optionally restricted by letter -// this only makes sense for 2d axes -exports.listIds = function(gd, axLetter) { - var fullLayout = gd._fullLayout; - if(!fullLayout) return []; - - var subplotLists = fullLayout._subplots; - if(axLetter) return subplotLists[axLetter + 'axis']; - return subplotLists.xaxis.concat(subplotLists.yaxis); -}; - -// get an axis object from its id 'x','x2' etc -// optionally, id can be a subplot (ie 'x2y3') and type gets x or y from it -exports.getFromId = function(gd, id, type) { - var fullLayout = gd._fullLayout; - - if(type === 'x') id = id.replace(/y[0-9]*/, ''); - else if(type === 'y') id = id.replace(/x[0-9]*/, ''); - - return fullLayout[exports.id2name(id)]; -}; - -// get an axis object of specified type from the containing trace -exports.getFromTrace = function(gd, fullTrace, type) { - var fullLayout = gd._fullLayout; - var ax = null; - - if(Registry.traceIs(fullTrace, 'gl3d')) { - var scene = fullTrace.scene; - if(scene.substr(0, 5) === 'scene') { - ax = fullLayout[scene][type + 'axis']; - } - } else { - ax = exports.getFromId(gd, fullTrace[type + 'axis'] || type); - } - - return ax; -}; - -// sort x, x2, x10, y, y2, y10... -exports.idSort = function(id1, id2) { - var letter1 = id1.charAt(0); - var letter2 = id2.charAt(0); - if(letter1 !== letter2) return letter1 > letter2 ? 1 : -1; - return +(id1.substr(1) || 1) - +(id2.substr(1) || 1); -}; - -exports.getAxisGroup = function getAxisGroup(fullLayout, axId) { - var matchGroups = fullLayout._axisMatchGroups; - - for(var i = 0; i < matchGroups.length; i++) { - var group = matchGroups[i]; - if(group[axId]) return 'g' + i; - } - return axId; -}; - -},{"../../registry":847,"./constants":773}],771:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -function findCategories(ax, opts) { - var dataAttr = opts.dataAttr || ax._id.charAt(0); - var lookup = {}; - var axData; - var i, j; - - if(opts.axData) { - // non-x/y case - axData = opts.axData; - } else { - // x/y case - axData = []; - for(i = 0; i < opts.data.length; i++) { - var trace = opts.data[i]; - if(trace[dataAttr + 'axis'] === ax._id) { - axData.push(trace); - } - } - } - - for(i = 0; i < axData.length; i++) { - var vals = axData[i][dataAttr]; - for(j = 0; j < vals.length; j++) { - var v = vals[j]; - if(v !== null && v !== undefined) { - lookup[v] = 1; - } - } - } - - return Object.keys(lookup); -} - -/** - * Fills in category* default and initial categories. - * - * @param {object} containerIn : input axis object - * @param {object} containerOut : full axis object - * @param {function} coerce : Lib.coerce fn wrapper - * @param {object} opts : - * - data {array} : (full) data trace - * OR - * - axData {array} : (full) data associated with axis being coerced here - * - dataAttr {string} : attribute name corresponding to coordinate array - */ -module.exports = function handleCategoryOrderDefaults(containerIn, containerOut, coerce, opts) { - if(containerOut.type !== 'category') return; - - var arrayIn = containerIn.categoryarray; - var isValidArray = (Array.isArray(arrayIn) && arrayIn.length > 0); - - // override default 'categoryorder' value when non-empty array is supplied - var orderDefault; - if(isValidArray) orderDefault = 'array'; - - var order = coerce('categoryorder', orderDefault); - var array; - - // coerce 'categoryarray' only in array order case - if(order === 'array') { - array = coerce('categoryarray'); - } - - // cannot set 'categoryorder' to 'array' with an invalid 'categoryarray' - if(!isValidArray && order === 'array') { - order = containerOut.categoryorder = 'trace'; - } - - // set up things for makeCalcdata - if(order === 'trace') { - containerOut._initialCategories = []; - } else if(order === 'array') { - containerOut._initialCategories = array.slice(); - } else { - array = findCategories(containerOut, opts).sort(); - if(order === 'category ascending') { - containerOut._initialCategories = array; - } else if(order === 'category descending') { - containerOut._initialCategories = array.reverse(); - } - } -}; - -},{}],772:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var Lib = _dereq_('../../lib'); -var ONEDAY = _dereq_('../../constants/numerical').ONEDAY; - -/** - * Return a validated dtick value for this axis - * - * @param {any} dtick: the candidate dtick. valid values are numbers and strings, - * and further constrained depending on the axis type. - * @param {string} axType: the axis type - */ -exports.dtick = function(dtick, axType) { - var isLog = axType === 'log'; - var isDate = axType === 'date'; - var isCat = axType === 'category'; - var dtickDflt = isDate ? ONEDAY : 1; - - if(!dtick) return dtickDflt; - - if(isNumeric(dtick)) { - dtick = Number(dtick); - if(dtick <= 0) return dtickDflt; - if(isCat) { - // category dtick must be positive integers - return Math.max(1, Math.round(dtick)); - } - if(isDate) { - // date dtick must be at least 0.1ms (our current precision) - return Math.max(0.1, dtick); - } - return dtick; - } - - if(typeof dtick !== 'string' || !(isDate || isLog)) { - return dtickDflt; - } - - var prefix = dtick.charAt(0); - var dtickNum = dtick.substr(1); - dtickNum = isNumeric(dtickNum) ? Number(dtickNum) : 0; - - if((dtickNum <= 0) || !( - // "M" gives ticks every (integer) n months - (isDate && prefix === 'M' && dtickNum === Math.round(dtickNum)) || - // "L" gives ticks linearly spaced in data (not in position) every (float) f - (isLog && prefix === 'L') || - // "D1" gives powers of 10 with all small digits between, "D2" gives only 2 and 5 - (isLog && prefix === 'D' && (dtickNum === 1 || dtickNum === 2)) - )) { - return dtickDflt; - } - - return dtick; -}; - -/** - * Return a validated tick0 for this axis - * - * @param {any} tick0: the candidate tick0. Valid values are numbers and strings, - * further constrained depending on the axis type - * @param {string} axType: the axis type - * @param {string} calendar: for date axes, the calendar to validate/convert with - * @param {any} dtick: an already valid dtick. Only used for D1 and D2 log dticks, - * which do not support tick0 at all. - */ -exports.tick0 = function(tick0, axType, calendar, dtick) { - if(axType === 'date') { - return Lib.cleanDate(tick0, Lib.dateTick0(calendar)); - } - if(dtick === 'D1' || dtick === 'D2') { - // D1 and D2 modes ignore tick0 entirely - return undefined; - } - // Aside from date axes, tick0 must be numeric - return isNumeric(tick0) ? Number(tick0) : 0; -}; - -},{"../../constants/numerical":695,"../../lib":719,"fast-isnumeric":225}],773:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; -var counterRegex = _dereq_('../../lib/regex').counter; - - -module.exports = { - - idRegex: { - x: counterRegex('x'), - y: counterRegex('y') - }, - - attrRegex: counterRegex('[xy]axis'), - - // axis match regular expression - xAxisMatch: counterRegex('xaxis'), - yAxisMatch: counterRegex('yaxis'), - - // pattern matching axis ids and names - // note that this is more permissive than counterRegex, as - // id2name, name2id, and cleanId accept "x1" etc - AX_ID_PATTERN: /^[xyz][0-9]*$/, - AX_NAME_PATTERN: /^[xyz]axis[0-9]*$/, - - // and for 2D subplots - SUBPLOT_PATTERN: /^x([0-9]*)y([0-9]*)$/, - - // pixels to move mouse before you stop clamping to starting point - MINDRAG: 8, - - // smallest dimension allowed for a select box - MINSELECT: 12, - - // smallest dimension allowed for a zoombox - MINZOOM: 20, - - // width of axis drag regions - DRAGGERSIZE: 20, - - // max pixels off straight before a lasso select line counts as bent - BENDPX: 1.5, - - // delay before a redraw (relayout) after smooth panning and zooming - REDRAWDELAY: 50, - - // throttling limit (ms) for selectPoints calls - SELECTDELAY: 100, - - // cache ID suffix for throttle - SELECTID: '-select', - - // last resort axis ranges for x and y axes if we have no data - DFLTRANGEX: [-1, 6], - DFLTRANGEY: [-1, 4], - - // Layers to keep trace types in the right order - // N.B. each 'unique' plot method must have its own layer - traceLayerClasses: [ - 'heatmaplayer', - 'contourcarpetlayer', 'contourlayer', - 'funnellayer', 'waterfalllayer', 'barlayer', - 'carpetlayer', - 'violinlayer', - 'boxlayer', - 'ohlclayer', - 'scattercarpetlayer', 'scatterlayer' - ], - - clipOnAxisFalseQuery: [ - '.scatterlayer', - '.barlayer', - '.funnellayer', - '.waterfalllayer' - ], - - layerValue2layerClass: { - 'above traces': 'above', - 'below traces': 'below' - } -}; - -},{"../../lib/regex":735}],774:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var id2name = _dereq_('./axis_ids').id2name; -var scaleZoom = _dereq_('./scale_zoom'); -var makePadFn = _dereq_('./autorange').makePadFn; -var concatExtremes = _dereq_('./autorange').concatExtremes; - -var ALMOST_EQUAL = _dereq_('../../constants/numerical').ALMOST_EQUAL; -var FROM_BL = _dereq_('../../constants/alignment').FROM_BL; - -exports.handleConstraintDefaults = function(containerIn, containerOut, coerce, allAxisIds, layoutOut) { - var constraintGroups = layoutOut._axisConstraintGroups; - var matchGroups = layoutOut._axisMatchGroups; - var axId = containerOut._id; - var axLetter = axId.charAt(0); - var splomStash = ((layoutOut._splomAxes || {})[axLetter] || {})[axId] || {}; - var thisID = containerOut._id; - var letter = thisID.charAt(0); - - // coerce the constraint mechanics even if this axis has no scaleanchor - // because it may be the anchor of another axis. - var constrain = coerce('constrain'); - Lib.coerce(containerIn, containerOut, { - constraintoward: { - valType: 'enumerated', - values: letter === 'x' ? ['left', 'center', 'right'] : ['bottom', 'middle', 'top'], - dflt: letter === 'x' ? 'center' : 'middle' - } - }, 'constraintoward'); - - var matches, matchOpts; - - if((containerIn.matches || splomStash.matches) && !containerOut.fixedrange) { - matchOpts = getConstraintOpts(matchGroups, thisID, allAxisIds, layoutOut); - matches = Lib.coerce(containerIn, containerOut, { - matches: { - valType: 'enumerated', - values: matchOpts.linkableAxes || [], - dflt: splomStash.matches - } - }, 'matches'); - } - - // 'matches' wins over 'scaleanchor' (for now) - var scaleanchor, scaleOpts; - - if(!matches && containerIn.scaleanchor && !(containerOut.fixedrange && constrain !== 'domain')) { - scaleOpts = getConstraintOpts(constraintGroups, thisID, allAxisIds, layoutOut, constrain); - scaleanchor = Lib.coerce(containerIn, containerOut, { - scaleanchor: { - valType: 'enumerated', - values: scaleOpts.linkableAxes || [] - } - }, 'scaleanchor'); - } - - if(matches) { - delete containerOut.constrain; - updateConstraintGroups(matchGroups, matchOpts.thisGroup, thisID, matches, 1); - } else if(allAxisIds.indexOf(containerIn.matches) !== -1) { - Lib.warn('ignored ' + containerOut._name + '.matches: "' + - containerIn.matches + '" to avoid either an infinite loop ' + - 'or because the target axis has fixed range.'); - } - - if(scaleanchor) { - var scaleratio = coerce('scaleratio'); - - // TODO: I suppose I could do attribute.min: Number.MIN_VALUE to avoid zero, - // but that seems hacky. Better way to say "must be a positive number"? - // Of course if you use several super-tiny values you could eventually - // force a product of these to zero and all hell would break loose... - // Likewise with super-huge values. - if(!scaleratio) scaleratio = containerOut.scaleratio = 1; - - updateConstraintGroups(constraintGroups, scaleOpts.thisGroup, thisID, scaleanchor, scaleratio); - } else if(allAxisIds.indexOf(containerIn.scaleanchor) !== -1) { - Lib.warn('ignored ' + containerOut._name + '.scaleanchor: "' + - containerIn.scaleanchor + '" to avoid either an infinite loop ' + - 'and possibly inconsistent scaleratios, or because the target ' + - 'axis has fixed range or this axis declares a *matches* constraint.'); - } -}; - -// If this axis is already part of a constraint group, we can't -// scaleanchor any other axis in that group, or we'd make a loop. -// Filter allAxisIds to enforce this, also matching axis types. -function getConstraintOpts(groups, thisID, allAxisIds, layoutOut, constrain) { - var doesNotConstrainRange = constrain !== 'range'; - var thisType = layoutOut[id2name(thisID)].type; - var i, j, idj, axj; - - var linkableAxes = []; - for(j = 0; j < allAxisIds.length; j++) { - idj = allAxisIds[j]; - if(idj === thisID) continue; - - axj = layoutOut[id2name(idj)]; - if(axj.type === thisType) { - if(!axj.fixedrange) { - linkableAxes.push(idj); - } else if(doesNotConstrainRange && axj.anchor) { - // allow domain constraints on subplots where - // BOTH axes have fixedrange:true and constrain:domain - var counterAxj = layoutOut[id2name(axj.anchor)]; - if(counterAxj.fixedrange) { - linkableAxes.push(idj); - } - } - } - } - - for(i = 0; i < groups.length; i++) { - if(groups[i][thisID]) { - var thisGroup = groups[i]; - - var linkableAxesNoLoops = []; - for(j = 0; j < linkableAxes.length; j++) { - idj = linkableAxes[j]; - if(!thisGroup[idj]) linkableAxesNoLoops.push(idj); - } - return {linkableAxes: linkableAxesNoLoops, thisGroup: thisGroup}; - } - } - - return {linkableAxes: linkableAxes, thisGroup: null}; -} - -/* - * Add this axis to the axis constraint groups, which is the collection - * of axes that are all constrained together on scale. - * - * constraintGroups: a list of objects. each object is - * {axis_id: scale_within_group}, where scale_within_group is - * only important relative to the rest of the group, and defines - * the relative scales between all axes in the group - * - * thisGroup: the group the current axis is already in - * thisID: the id if the current axis - * scaleanchor: the id of the axis to scale it with - * scaleratio: the ratio of this axis to the scaleanchor axis - */ -function updateConstraintGroups(constraintGroups, thisGroup, thisID, scaleanchor, scaleratio) { - var i, j, groupi, keyj, thisGroupIndex; - - if(thisGroup === null) { - thisGroup = {}; - thisGroup[thisID] = 1; - thisGroupIndex = constraintGroups.length; - constraintGroups.push(thisGroup); - } else { - thisGroupIndex = constraintGroups.indexOf(thisGroup); - } - - var thisGroupKeys = Object.keys(thisGroup); - - // we know that this axis isn't in any other groups, but we don't know - // about the scaleanchor axis. If it is, we need to merge the groups. - for(i = 0; i < constraintGroups.length; i++) { - groupi = constraintGroups[i]; - if(i !== thisGroupIndex && groupi[scaleanchor]) { - var baseScale = groupi[scaleanchor]; - for(j = 0; j < thisGroupKeys.length; j++) { - keyj = thisGroupKeys[j]; - groupi[keyj] = baseScale * scaleratio * thisGroup[keyj]; - } - constraintGroups.splice(thisGroupIndex, 1); - return; - } - } - - // otherwise, we insert the new scaleanchor axis as the base scale (1) - // in its group, and scale the rest of the group to it - if(scaleratio !== 1) { - for(j = 0; j < thisGroupKeys.length; j++) { - thisGroup[thisGroupKeys[j]] *= scaleratio; - } - } - thisGroup[scaleanchor] = 1; -} - -exports.enforce = function enforce(gd) { - var fullLayout = gd._fullLayout; - var constraintGroups = fullLayout._axisConstraintGroups || []; - - var i, j, axisID, ax, normScale, mode, factor; - - for(i = 0; i < constraintGroups.length; i++) { - var group = constraintGroups[i]; - var axisIDs = Object.keys(group); - - var minScale = Infinity; - var maxScale = 0; - // mostly matchScale will be the same as minScale - // ie we expand axis ranges to encompass *everything* - // that's currently in any of their ranges, but during - // autorange of a subset of axes we will ignore other - // axes for this purpose. - var matchScale = Infinity; - var normScales = {}; - var axes = {}; - var hasAnyDomainConstraint = false; - - // find the (normalized) scale of each axis in the group - for(j = 0; j < axisIDs.length; j++) { - axisID = axisIDs[j]; - axes[axisID] = ax = fullLayout[id2name(axisID)]; - - if(ax._inputDomain) ax.domain = ax._inputDomain.slice(); - else ax._inputDomain = ax.domain.slice(); - - if(!ax._inputRange) ax._inputRange = ax.range.slice(); - - // set axis scale here so we can use _m rather than - // having to calculate it from length and range - ax.setScale(); - - // abs: inverted scales still satisfy the constraint - normScales[axisID] = normScale = Math.abs(ax._m) / group[axisID]; - minScale = Math.min(minScale, normScale); - if(ax.constrain === 'domain' || !ax._constraintShrinkable) { - matchScale = Math.min(matchScale, normScale); - } - - // this has served its purpose, so remove it - delete ax._constraintShrinkable; - maxScale = Math.max(maxScale, normScale); - - if(ax.constrain === 'domain') hasAnyDomainConstraint = true; - } - - // Do we have a constraint mismatch? Give a small buffer for rounding errors - if(minScale > ALMOST_EQUAL * maxScale && !hasAnyDomainConstraint) continue; - - // now increase any ranges we need to until all normalized scales are equal - for(j = 0; j < axisIDs.length; j++) { - axisID = axisIDs[j]; - normScale = normScales[axisID]; - ax = axes[axisID]; - mode = ax.constrain; - - // even if the scale didn't change, if we're shrinking domain - // we need to recalculate in case `constraintoward` changed - if(normScale !== matchScale || mode === 'domain') { - factor = normScale / matchScale; - - if(mode === 'range') { - scaleZoom(ax, factor); - } else { - // mode === 'domain' - - var inputDomain = ax._inputDomain; - var domainShrunk = (ax.domain[1] - ax.domain[0]) / - (inputDomain[1] - inputDomain[0]); - var rangeShrunk = (ax.r2l(ax.range[1]) - ax.r2l(ax.range[0])) / - (ax.r2l(ax._inputRange[1]) - ax.r2l(ax._inputRange[0])); - - factor /= domainShrunk; - - if(factor * rangeShrunk < 1) { - // we've asked to magnify the axis more than we can just by - // enlarging the domain - so we need to constrict range - ax.domain = ax._input.domain = inputDomain.slice(); - scaleZoom(ax, factor); - continue; - } - - if(rangeShrunk < 1) { - // the range has previously been constricted by ^^, but we've - // switched to the domain-constricted regime, so reset range - ax.range = ax._input.range = ax._inputRange.slice(); - factor *= rangeShrunk; - } - - if(ax.autorange) { - /* - * range & factor may need to change because range was - * calculated for the larger scaling, so some pixel - * paddings may get cut off when we reduce the domain. - * - * This is easier than the regular autorange calculation - * because we already know the scaling `m`, but we still - * need to cut out impossible constraints (like - * annotations with super-long arrows). That's what - * outerMin/Max are for - if the expansion was going to - * go beyond the original domain, it must be impossible - */ - var rl0 = ax.r2l(ax.range[0]); - var rl1 = ax.r2l(ax.range[1]); - var rangeCenter = (rl0 + rl1) / 2; - var rangeMin = rangeCenter; - var rangeMax = rangeCenter; - var halfRange = Math.abs(rl1 - rangeCenter); - // extra tiny bit for rounding errors, in case we actually - // *are* expanding to the full domain - var outerMin = rangeCenter - halfRange * factor * 1.0001; - var outerMax = rangeCenter + halfRange * factor * 1.0001; - var getPad = makePadFn(ax); - - updateDomain(ax, factor); - var m = Math.abs(ax._m); - var extremes = concatExtremes(gd, ax); - var minArray = extremes.min; - var maxArray = extremes.max; - var newVal; - var k; - - for(k = 0; k < minArray.length; k++) { - newVal = minArray[k].val - getPad(minArray[k]) / m; - if(newVal > outerMin && newVal < rangeMin) { - rangeMin = newVal; - } - } - - for(k = 0; k < maxArray.length; k++) { - newVal = maxArray[k].val + getPad(maxArray[k]) / m; - if(newVal < outerMax && newVal > rangeMax) { - rangeMax = newVal; - } - } - - var domainExpand = (rangeMax - rangeMin) / (2 * halfRange); - factor /= domainExpand; - - rangeMin = ax.l2r(rangeMin); - rangeMax = ax.l2r(rangeMax); - ax.range = ax._input.range = (rl0 < rl1) ? - [rangeMin, rangeMax] : [rangeMax, rangeMin]; - } - - updateDomain(ax, factor); - } - } - } - } -}; - -// For use before autoranging, check if this axis was previously constrained -// by domain but no longer is -exports.clean = function clean(gd, ax) { - if(ax._inputDomain) { - var isConstrained = false; - var axId = ax._id; - var constraintGroups = gd._fullLayout._axisConstraintGroups; - for(var j = 0; j < constraintGroups.length; j++) { - if(constraintGroups[j][axId]) { - isConstrained = true; - break; - } - } - if(!isConstrained || ax.constrain !== 'domain') { - ax._input.domain = ax.domain = ax._inputDomain; - delete ax._inputDomain; - } - } -}; - -function updateDomain(ax, factor) { - var inputDomain = ax._inputDomain; - var centerFraction = FROM_BL[ax.constraintoward]; - var center = inputDomain[0] + (inputDomain[1] - inputDomain[0]) * centerFraction; - - ax.domain = ax._input.domain = [ - center + (inputDomain[0] - center) / factor, - center + (inputDomain[1] - center) / factor - ]; - ax.setScale(); -} - -},{"../../constants/alignment":688,"../../constants/numerical":695,"../../lib":719,"./autorange":766,"./axis_ids":770,"./scale_zoom":783}],775:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var tinycolor = _dereq_('tinycolor2'); -var supportsPassive = _dereq_('has-passive-events'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var Fx = _dereq_('../../components/fx'); -var Axes = _dereq_('./axes'); -var setCursor = _dereq_('../../lib/setcursor'); -var dragElement = _dereq_('../../components/dragelement'); -var FROM_TL = _dereq_('../../constants/alignment').FROM_TL; -var clearGlCanvases = _dereq_('../../lib/clear_gl_canvases'); -var redrawReglTraces = _dereq_('../../plot_api/subroutines').redrawReglTraces; - -var Plots = _dereq_('../plots'); - -var getFromId = _dereq_('./axis_ids').getFromId; -var prepSelect = _dereq_('./select').prepSelect; -var clearSelect = _dereq_('./select').clearSelect; -var selectOnClick = _dereq_('./select').selectOnClick; -var scaleZoom = _dereq_('./scale_zoom'); - -var constants = _dereq_('./constants'); -var MINDRAG = constants.MINDRAG; -var MINZOOM = constants.MINZOOM; - -// flag for showing "doubleclick to zoom out" only at the beginning -var SHOWZOOMOUTTIP = true; - -// dragBox: create an element to drag one or more axis ends -// inputs: -// plotinfo - which subplot are we making dragboxes on? -// x,y,w,h - left, top, width, height of the box -// ns - how does this drag the vertical axis? -// 'n' - top only -// 's' - bottom only -// 'ns' - top and bottom together, difference unchanged -// ew - same for horizontal axis -function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { - // mouseDown stores ms of first mousedown event in the last - // `gd._context.doubleClickDelay` ms on the drag bars - // numClicks stores how many mousedowns have been seen - // within `gd._context.doubleClickDelay` so we can check for click or doubleclick events - // dragged stores whether a drag has occurred, so we don't have to - // redraw unnecessarily, ie if no move bigger than MINDRAG or MINZOOM px - var zoomlayer = gd._fullLayout._zoomlayer; - var isMainDrag = (ns + ew === 'nsew'); - var singleEnd = (ns + ew).length === 1; - - // main subplot x and y (i.e. found in plotinfo - the main ones) - var xa0, ya0; - // {ax._id: ax} hash objects - var xaHash, yaHash; - // xaHash/yaHash values (arrays) - var xaxes, yaxes; - // main axis offsets - var xs, ys; - // main axis lengths - var pw, ph; - // contains keys 'xaHash', 'yaHash', 'xaxes', and 'yaxes' - // which are the x/y {ax._id: ax} hash objects and their values - // for linked axis relative to this subplot - var links; - // similar to `links` but for matching axes - var matches; - // set to ew/ns val when active, set to '' when inactive - var xActive, yActive; - // are all axes in this subplot are fixed? - var allFixedRanges; - // do we need to edit x/y ranges? - var editX, editY; - // graph-wide optimization flags - var hasScatterGl, hasSplom, hasSVG; - // collected changes to be made to the plot by relayout at the end - var updates; - - function recomputeAxisLists() { - xa0 = plotinfo.xaxis; - ya0 = plotinfo.yaxis; - pw = xa0._length; - ph = ya0._length; - xs = xa0._offset; - ys = ya0._offset; - - xaHash = {}; - xaHash[xa0._id] = xa0; - yaHash = {}; - yaHash[ya0._id] = ya0; - - // if we're dragging two axes at once, also drag overlays - if(ns && ew) { - var overlays = plotinfo.overlays; - for(var i = 0; i < overlays.length; i++) { - var xa = overlays[i].xaxis; - xaHash[xa._id] = xa; - var ya = overlays[i].yaxis; - yaHash[ya._id] = ya; - } - } - - xaxes = hashValues(xaHash); - yaxes = hashValues(yaHash); - xActive = isDirectionActive(xaxes, ew); - yActive = isDirectionActive(yaxes, ns); - allFixedRanges = !yActive && !xActive; - - links = calcLinks(gd, gd._fullLayout._axisConstraintGroups, xaHash, yaHash); - matches = calcLinks(gd, gd._fullLayout._axisMatchGroups, xaHash, yaHash); - editX = ew || links.isSubplotConstrained || matches.isSubplotConstrained; - editY = ns || links.isSubplotConstrained || matches.isSubplotConstrained; - - var fullLayout = gd._fullLayout; - hasScatterGl = fullLayout._has('scattergl'); - hasSplom = fullLayout._has('splom'); - hasSVG = fullLayout._has('svg'); - } - - recomputeAxisLists(); - - var cursor = getDragCursor(yActive + xActive, gd._fullLayout.dragmode, isMainDrag); - var dragger = makeRectDragger(plotinfo, ns + ew + 'drag', cursor, x, y, w, h); - - // still need to make the element if the axes are disabled - // but nuke its events (except for maindrag which needs them for hover) - // and stop there - if(allFixedRanges && !isMainDrag) { - dragger.onmousedown = null; - dragger.style.pointerEvents = 'none'; - return dragger; - } - - var dragOptions = { - element: dragger, - gd: gd, - plotinfo: plotinfo - }; - - dragOptions.prepFn = function(e, startX, startY) { - var dragModePrev = dragOptions.dragmode; - var dragModeNow = gd._fullLayout.dragmode; - if(dragModeNow !== dragModePrev) { - dragOptions.dragmode = dragModeNow; - } - - recomputeAxisLists(); - - if(!allFixedRanges) { - if(isMainDrag) { - // main dragger handles all drag modes, and changes - // to pan (or to zoom if it already is pan) on shift - if(e.shiftKey) { - if(dragModeNow === 'pan') dragModeNow = 'zoom'; - else if(!isSelectOrLasso(dragModeNow)) dragModeNow = 'pan'; - } else if(e.ctrlKey) { - dragModeNow = 'pan'; - } - } else { - // all other draggers just pan - dragModeNow = 'pan'; - } - } - - if(dragModeNow === 'lasso') dragOptions.minDrag = 1; - else dragOptions.minDrag = undefined; - - if(isSelectOrLasso(dragModeNow)) { - dragOptions.xaxes = xaxes; - dragOptions.yaxes = yaxes; - // this attaches moveFn, clickFn, doneFn on dragOptions - prepSelect(e, startX, startY, dragOptions, dragModeNow); - } else { - dragOptions.clickFn = clickFn; - if(isSelectOrLasso(dragModePrev)) { - // TODO Fix potential bug - // Note: clearing / resetting selection state only happens, when user - // triggers at least one interaction in pan/zoom mode. Otherwise, the - // select/lasso outlines are deleted (in plots.js.cleanPlot) but the selection - // cache isn't cleared. So when the user switches back to select/lasso and - // 'adds to a selection' with Shift, the "old", seemingly removed outlines - // are redrawn again because the selection cache still holds their coordinates. - // However, this isn't easily solved, since plots.js would need - // to have a reference to the dragOptions object (which holds the - // selection cache). - clearAndResetSelect(); - } - - if(!allFixedRanges) { - if(dragModeNow === 'zoom') { - dragOptions.moveFn = zoomMove; - dragOptions.doneFn = zoomDone; - - // zoomMove takes care of the threshold, but we need to - // minimize this so that constrained zoom boxes will flip - // orientation at the right place - dragOptions.minDrag = 1; - - zoomPrep(e, startX, startY); - } else if(dragModeNow === 'pan') { - dragOptions.moveFn = plotDrag; - dragOptions.doneFn = dragTail; - } - } - } - - gd._fullLayout._redrag = function() { - var dragDataNow = gd._dragdata; - - if(dragDataNow && dragDataNow.element === dragger) { - var dragModeNow = gd._fullLayout.dragmode; - - if(!isSelectOrLasso(dragModeNow)) { - recomputeAxisLists(); - updateSubplots([0, 0, pw, ph]); - dragOptions.moveFn(dragDataNow.dx, dragDataNow.dy); - } - - // TODO should we try to "re-select" under select/lasso modes? - // probably best to wait for https://github.com/plotly/plotly.js/issues/1851 - } - }; - }; - - function clearAndResetSelect() { - // clear selection polygon cache (if any) - dragOptions.plotinfo.selection = false; - // clear selection outlines - clearSelect(gd); - } - - function clickFn(numClicks, evt) { - var clickmode = gd._fullLayout.clickmode; - - removeZoombox(gd); - - if(numClicks === 2 && !singleEnd) doubleClick(); - - if(isMainDrag) { - if(clickmode.indexOf('select') > -1) { - selectOnClick(evt, gd, xaxes, yaxes, plotinfo.id, dragOptions); - } - - if(clickmode.indexOf('event') > -1) { - Fx.click(gd, evt, plotinfo.id); - } - } else if(numClicks === 1 && singleEnd) { - var ax = ns ? ya0 : xa0; - var end = (ns === 's' || ew === 'w') ? 0 : 1; - var attrStr = ax._name + '.range[' + end + ']'; - var initialText = getEndText(ax, end); - var hAlign = 'left'; - var vAlign = 'middle'; - - if(ax.fixedrange) return; - - if(ns) { - vAlign = (ns === 'n') ? 'top' : 'bottom'; - if(ax.side === 'right') hAlign = 'right'; - } else if(ew === 'e') hAlign = 'right'; - - if(gd._context.showAxisRangeEntryBoxes) { - d3.select(dragger) - .call(svgTextUtils.makeEditable, { - gd: gd, - immediate: true, - background: gd._fullLayout.paper_bgcolor, - text: String(initialText), - fill: ax.tickfont ? ax.tickfont.color : '#444', - horizontalAlign: hAlign, - verticalAlign: vAlign - }) - .on('edit', function(text) { - var v = ax.d2r(text); - if(v !== undefined) { - Registry.call('_guiRelayout', gd, attrStr, v); - } - }); - } - } - } - - dragElement.init(dragOptions); - - // x/y px position at start of drag - var x0, y0; - // bbox object of the zoombox - var box; - // luminance of bg behind zoombox - var lum; - // zoombox path outline - var path0; - // is zoombox dimmed (during drag) - var dimmed; - // 'x'-only, 'y' or 'xy' zooming - var zoomMode; - // zoombox d3 selection - var zb; - // zoombox corner d3 selection - var corners; - // zoom takes over minDrag, so it also has to take over gd._dragged - var zoomDragged; - - function zoomPrep(e, startX, startY) { - var dragBBox = dragger.getBoundingClientRect(); - x0 = startX - dragBBox.left; - y0 = startY - dragBBox.top; - box = {l: x0, r: x0, w: 0, t: y0, b: y0, h: 0}; - lum = gd._hmpixcount ? - (gd._hmlumcount / gd._hmpixcount) : - tinycolor(gd._fullLayout.plot_bgcolor).getLuminance(); - path0 = 'M0,0H' + pw + 'V' + ph + 'H0V0'; - dimmed = false; - zoomMode = 'xy'; - zoomDragged = false; - zb = makeZoombox(zoomlayer, lum, xs, ys, path0); - corners = makeCorners(zoomlayer, xs, ys); - } - - function zoomMove(dx0, dy0) { - if(gd._transitioningWithDuration) { - return false; - } - - var x1 = Math.max(0, Math.min(pw, dx0 + x0)); - var y1 = Math.max(0, Math.min(ph, dy0 + y0)); - var dx = Math.abs(x1 - x0); - var dy = Math.abs(y1 - y0); - - box.l = Math.min(x0, x1); - box.r = Math.max(x0, x1); - box.t = Math.min(y0, y1); - box.b = Math.max(y0, y1); - - function noZoom() { - zoomMode = ''; - box.r = box.l; - box.t = box.b; - corners.attr('d', 'M0,0Z'); - } - - if(links.isSubplotConstrained) { - if(dx > MINZOOM || dy > MINZOOM) { - zoomMode = 'xy'; - if(dx / pw > dy / ph) { - dy = dx * ph / pw; - if(y0 > y1) box.t = y0 - dy; - else box.b = y0 + dy; - } else { - dx = dy * pw / ph; - if(x0 > x1) box.l = x0 - dx; - else box.r = x0 + dx; - } - corners.attr('d', xyCorners(box)); - } else { - noZoom(); - } - } else if(matches.isSubplotConstrained) { - if(dx > MINZOOM || dy > MINZOOM) { - zoomMode = 'xy'; - - var r0 = Math.min(box.l / pw, (ph - box.b) / ph); - var r1 = Math.max(box.r / pw, (ph - box.t) / ph); - - box.l = r0 * pw; - box.r = r1 * pw; - box.b = (1 - r0) * ph; - box.t = (1 - r1) * ph; - corners.attr('d', xyCorners(box)); - } else { - noZoom(); - } - } else if(!yActive || dy < Math.min(Math.max(dx * 0.6, MINDRAG), MINZOOM)) { - // look for small drags in one direction or the other, - // and only drag the other axis - - if(dx < MINDRAG || !xActive) { - noZoom(); - } else { - box.t = 0; - box.b = ph; - zoomMode = 'x'; - corners.attr('d', xCorners(box, y0)); - } - } else if(!xActive || dx < Math.min(dy * 0.6, MINZOOM)) { - box.l = 0; - box.r = pw; - zoomMode = 'y'; - corners.attr('d', yCorners(box, x0)); - } else { - zoomMode = 'xy'; - corners.attr('d', xyCorners(box)); - } - box.w = box.r - box.l; - box.h = box.b - box.t; - - if(zoomMode) zoomDragged = true; - gd._dragged = zoomDragged; - - updateZoombox(zb, corners, box, path0, dimmed, lum); - computeZoomUpdates(); - gd.emit('plotly_relayouting', updates); - dimmed = true; - } - - function computeZoomUpdates() { - updates = {}; - - // TODO: edit linked axes in zoomAxRanges and in dragTail - if(zoomMode === 'xy' || zoomMode === 'x') { - zoomAxRanges(xaxes, box.l / pw, box.r / pw, updates, links.xaxes); - updateMatchedAxRange('x', updates); - } - if(zoomMode === 'xy' || zoomMode === 'y') { - zoomAxRanges(yaxes, (ph - box.b) / ph, (ph - box.t) / ph, updates, links.yaxes); - updateMatchedAxRange('y', updates); - } - } - - function zoomDone() { - // more strict than dragged, which allows you to come back to where you started - // and still count as dragged - if(Math.min(box.h, box.w) < MINDRAG * 2) { - return removeZoombox(gd); - } - - computeZoomUpdates(); - - removeZoombox(gd); - dragTail(); - showDoubleClickNotifier(gd); - } - - // scroll zoom, on all draggers except corners - var scrollViewBox = [0, 0, pw, ph]; - // wait a little after scrolling before redrawing - var redrawTimer = null; - var REDRAWDELAY = constants.REDRAWDELAY; - var mainplot = plotinfo.mainplot ? gd._fullLayout._plots[plotinfo.mainplot] : plotinfo; - - function zoomWheel(e) { - // deactivate mousewheel scrolling on embedded graphs - // devs can override this with layout._enablescrollzoom, - // but _ ensures this setting won't leave their page - if(!gd._context._scrollZoom.cartesian && !gd._fullLayout._enablescrollzoom) { - return; - } - - clearAndResetSelect(); - - // If a transition is in progress, then disable any behavior: - if(gd._transitioningWithDuration) { - e.preventDefault(); - e.stopPropagation(); - return; - } - - recomputeAxisLists(); - - clearTimeout(redrawTimer); - - var wheelDelta = -e.deltaY; - if(!isFinite(wheelDelta)) wheelDelta = e.wheelDelta / 10; - if(!isFinite(wheelDelta)) { - Lib.log('Did not find wheel motion attributes: ', e); - return; - } - - var zoom = Math.exp(-Math.min(Math.max(wheelDelta, -20), 20) / 200); - var gbb = mainplot.draglayer.select('.nsewdrag').node().getBoundingClientRect(); - var xfrac = (e.clientX - gbb.left) / gbb.width; - var yfrac = (gbb.bottom - e.clientY) / gbb.height; - var i; - - function zoomWheelOneAxis(ax, centerFraction, zoom) { - if(ax.fixedrange) return; - - var axRange = Lib.simpleMap(ax.range, ax.r2l); - var v0 = axRange[0] + (axRange[1] - axRange[0]) * centerFraction; - function doZoom(v) { return ax.l2r(v0 + (v - v0) * zoom); } - ax.range = axRange.map(doZoom); - } - - if(editX) { - // if we're only zooming this axis because of constraints, - // zoom it about the center - if(!ew) xfrac = 0.5; - - for(i = 0; i < xaxes.length; i++) { - zoomWheelOneAxis(xaxes[i], xfrac, zoom); - } - updateMatchedAxRange('x'); - - scrollViewBox[2] *= zoom; - scrollViewBox[0] += scrollViewBox[2] * xfrac * (1 / zoom - 1); - } - if(editY) { - if(!ns) yfrac = 0.5; - - for(i = 0; i < yaxes.length; i++) { - zoomWheelOneAxis(yaxes[i], yfrac, zoom); - } - updateMatchedAxRange('y'); - - scrollViewBox[3] *= zoom; - scrollViewBox[1] += scrollViewBox[3] * (1 - yfrac) * (1 / zoom - 1); - } - - // viewbox redraw at first - updateSubplots(scrollViewBox); - ticksAndAnnotations(); - - gd.emit('plotly_relayouting', updates); - - // then replot after a delay to make sure - // no more scrolling is coming - redrawTimer = setTimeout(function() { - scrollViewBox = [0, 0, pw, ph]; - dragTail(); - }, REDRAWDELAY); - - e.preventDefault(); - return; - } - - // everything but the corners gets wheel zoom - if(ns.length * ew.length !== 1) { - attachWheelEventHandler(dragger, zoomWheel); - } - - // plotDrag: move the plot in response to a drag - function plotDrag(dx, dy) { - // If a transition is in progress, then disable any behavior: - if(gd._transitioningWithDuration) { - return; - } - - // prevent axis drawing from monkeying with margins until we're done - gd._fullLayout._replotting = true; - - if(xActive === 'ew' || yActive === 'ns') { - if(xActive) { - dragAxList(xaxes, dx); - updateMatchedAxRange('x'); - } - if(yActive) { - dragAxList(yaxes, dy); - updateMatchedAxRange('y'); - } - updateSubplots([xActive ? -dx : 0, yActive ? -dy : 0, pw, ph]); - ticksAndAnnotations(); - gd.emit('plotly_relayouting', updates); - return; - } - - // dz: set a new value for one end (0 or 1) of an axis array axArray, - // and return a pixel shift for that end for the viewbox - // based on pixel drag distance d - // TODO: this makes (generally non-fatal) errors when you get - // near floating point limits - function dz(axArray, end, d) { - var otherEnd = 1 - end; - var movedAx; - var newLinearizedEnd; - for(var i = 0; i < axArray.length; i++) { - var axi = axArray[i]; - if(axi.fixedrange) continue; - movedAx = axi; - newLinearizedEnd = axi._rl[otherEnd] + - (axi._rl[end] - axi._rl[otherEnd]) / dZoom(d / axi._length); - var newEnd = axi.l2r(newLinearizedEnd); - - // if l2r comes back false or undefined, it means we've dragged off - // the end of valid ranges - so stop. - if(newEnd !== false && newEnd !== undefined) axi.range[end] = newEnd; - } - return movedAx._length * (movedAx._rl[end] - newLinearizedEnd) / - (movedAx._rl[end] - movedAx._rl[otherEnd]); - } - - if(links.isSubplotConstrained && xActive && yActive) { - // dragging a corner of a constrained subplot: - // respect the fixed corner, but harmonize dx and dy - var dxySign = ((xActive === 'w') === (yActive === 'n')) ? 1 : -1; - var dxyFraction = (dx / pw + dxySign * dy / ph) / 2; - dx = dxyFraction * pw; - dy = dxySign * dxyFraction * ph; - } - - if(xActive === 'w') dx = dz(xaxes, 0, dx); - else if(xActive === 'e') dx = dz(xaxes, 1, -dx); - else if(!xActive) dx = 0; - - if(yActive === 'n') dy = dz(yaxes, 1, dy); - else if(yActive === 's') dy = dz(yaxes, 0, -dy); - else if(!yActive) dy = 0; - - var xStart = (xActive === 'w') ? dx : 0; - var yStart = (yActive === 'n') ? dy : 0; - - if(links.isSubplotConstrained) { - var i; - if(!xActive && yActive.length === 1) { - // dragging one end of the y axis of a constrained subplot - // scale the other axis the same about its middle - for(i = 0; i < xaxes.length; i++) { - xaxes[i].range = xaxes[i]._r.slice(); - scaleZoom(xaxes[i], 1 - dy / ph); - } - dx = dy * pw / ph; - xStart = dx / 2; - } - if(!yActive && xActive.length === 1) { - for(i = 0; i < yaxes.length; i++) { - yaxes[i].range = yaxes[i]._r.slice(); - scaleZoom(yaxes[i], 1 - dx / pw); - } - dy = dx * ph / pw; - yStart = dy / 2; - } - } - - updateMatchedAxRange('x'); - updateMatchedAxRange('y'); - updateSubplots([xStart, yStart, pw - dx, ph - dy]); - ticksAndAnnotations(); - gd.emit('plotly_relayouting', updates); - } - - function updateMatchedAxRange(axLetter, out) { - var matchedAxes = matches.isSubplotConstrained ? - {x: yaxes, y: xaxes}[axLetter] : - matches[axLetter + 'axes']; - - var constrainedAxes = matches.isSubplotConstrained ? - {x: xaxes, y: yaxes}[axLetter] : - []; - - for(var i = 0; i < matchedAxes.length; i++) { - var ax = matchedAxes[i]; - var axId = ax._id; - var axId2 = matches.xLinks[axId] || matches.yLinks[axId]; - var ax2 = constrainedAxes[0] || xaHash[axId2] || yaHash[axId2]; - - if(ax2) { - if(out) { - // zoombox case - don't mutate 'range', just add keys in 'updates' - out[ax._name + '.range[0]'] = out[ax2._name + '.range[0]']; - out[ax._name + '.range[1]'] = out[ax2._name + '.range[1]']; - } else { - ax.range = ax2.range.slice(); - } - } - } - } - - // Draw ticks and annotations (and other components) when ranges change. - // Also records the ranges that have changed for use by update at the end. - function ticksAndAnnotations() { - var activeAxIds = []; - var i; - - function pushActiveAxIds(axList) { - for(i = 0; i < axList.length; i++) { - if(!axList[i].fixedrange) activeAxIds.push(axList[i]._id); - } - } - - if(editX) { - pushActiveAxIds(xaxes); - pushActiveAxIds(links.xaxes); - pushActiveAxIds(matches.xaxes); - } - if(editY) { - pushActiveAxIds(yaxes); - pushActiveAxIds(links.yaxes); - pushActiveAxIds(matches.yaxes); - } - - updates = {}; - for(i = 0; i < activeAxIds.length; i++) { - var axId = activeAxIds[i]; - var ax = getFromId(gd, axId); - Axes.drawOne(gd, ax, {skipTitle: true}); - updates[ax._name + '.range[0]'] = ax.range[0]; - updates[ax._name + '.range[1]'] = ax.range[1]; - } - - Axes.redrawComponents(gd, activeAxIds); - } - - function doubleClick() { - if(gd._transitioningWithDuration) return; - - var doubleClickConfig = gd._context.doubleClick; - - var axList = []; - if(xActive) axList = axList.concat(xaxes); - if(yActive) axList = axList.concat(yaxes); - if(matches.xaxes) axList = axList.concat(matches.xaxes); - if(matches.yaxes) axList = axList.concat(matches.yaxes); - - var attrs = {}; - var ax, i, rangeInitial; - - // For reset+autosize mode: - // If *any* of the main axes is not at its initial range - // (or autoranged, if we have no initial range, to match the logic in - // doubleClickConfig === 'reset' below), we reset. - // If they are *all* at their initial ranges, then we autosize. - if(doubleClickConfig === 'reset+autosize') { - doubleClickConfig = 'autosize'; - - for(i = 0; i < axList.length; i++) { - ax = axList[i]; - if((ax._rangeInitial && ( - ax.range[0] !== ax._rangeInitial[0] || - ax.range[1] !== ax._rangeInitial[1] - )) || - (!ax._rangeInitial && !ax.autorange) - ) { - doubleClickConfig = 'reset'; - break; - } - } - } - - if(doubleClickConfig === 'autosize') { - // don't set the linked axes here, so relayout marks them as shrinkable - // and we autosize just to the requested axis/axes - for(i = 0; i < axList.length; i++) { - ax = axList[i]; - if(!ax.fixedrange) attrs[ax._name + '.autorange'] = true; - } - } else if(doubleClickConfig === 'reset') { - // when we're resetting, reset all linked axes too, so we get back - // to the fully-auto-with-constraints situation - if(xActive || links.isSubplotConstrained) axList = axList.concat(links.xaxes); - if(yActive && !links.isSubplotConstrained) axList = axList.concat(links.yaxes); - - if(links.isSubplotConstrained) { - if(!xActive) axList = axList.concat(xaxes); - else if(!yActive) axList = axList.concat(yaxes); - } - - for(i = 0; i < axList.length; i++) { - ax = axList[i]; - - if(!ax.fixedrange) { - if(!ax._rangeInitial) { - attrs[ax._name + '.autorange'] = true; - } else { - rangeInitial = ax._rangeInitial; - attrs[ax._name + '.range[0]'] = rangeInitial[0]; - attrs[ax._name + '.range[1]'] = rangeInitial[1]; - } - } - } - } - - gd.emit('plotly_doubleclick', null); - Registry.call('_guiRelayout', gd, attrs); - } - - // dragTail - finish a drag event with a redraw - function dragTail() { - // put the subplot viewboxes back to default (Because we're going to) - // be repositioning the data in the relayout. But DON'T call - // ticksAndAnnotations again - it's unnecessary and would overwrite `updates` - updateSubplots([0, 0, pw, ph]); - - // since we may have been redrawing some things during the drag, we may have - // accumulated MathJax promises - wait for them before we relayout. - Lib.syncOrAsync([ - Plots.previousPromises, - function() { - gd._fullLayout._replotting = false; - Registry.call('_guiRelayout', gd, updates); - } - ], gd); - } - - // updateSubplots - find all plot viewboxes that should be - // affected by this drag, and update them. look for all plots - // sharing an affected axis (including the one being dragged), - // includes also scattergl and splom logic. - function updateSubplots(viewBox) { - var fullLayout = gd._fullLayout; - var plotinfos = fullLayout._plots; - var subplots = fullLayout._subplots.cartesian; - var i, sp, xa, ya; - - if(hasSplom) { - Registry.subplotsRegistry.splom.drag(gd); - } - - if(hasScatterGl) { - for(i = 0; i < subplots.length; i++) { - sp = plotinfos[subplots[i]]; - xa = sp.xaxis; - ya = sp.yaxis; - - if(sp._scene) { - var xrng = Lib.simpleMap(xa.range, xa.r2l); - var yrng = Lib.simpleMap(ya.range, ya.r2l); - sp._scene.update({range: [xrng[0], yrng[0], xrng[1], yrng[1]]}); - } - } - } - - if(hasSplom || hasScatterGl) { - clearGlCanvases(gd); - redrawReglTraces(gd); - } - - if(hasSVG) { - var xScaleFactor = viewBox[2] / xa0._length; - var yScaleFactor = viewBox[3] / ya0._length; - - for(i = 0; i < subplots.length; i++) { - sp = plotinfos[subplots[i]]; - xa = sp.xaxis; - ya = sp.yaxis; - - var editX2 = editX && !xa.fixedrange && xaHash[xa._id]; - var editY2 = editY && !ya.fixedrange && yaHash[ya._id]; - - var xScaleFactor2, yScaleFactor2; - var clipDx, clipDy; - - if(editX2) { - xScaleFactor2 = xScaleFactor; - clipDx = ew ? viewBox[0] : getShift(xa, xScaleFactor2); - } else if(matches.xaHash[xa._id]) { - xScaleFactor2 = xScaleFactor; - clipDx = viewBox[0] * xa._length / xa0._length; - } else if(matches.yaHash[xa._id]) { - xScaleFactor2 = yScaleFactor; - clipDx = yActive === 'ns' ? - -viewBox[1] * xa._length / ya0._length : - getShift(xa, xScaleFactor2, {n: 'top', s: 'bottom'}[yActive]); - } else { - xScaleFactor2 = getLinkedScaleFactor(xa, xScaleFactor, yScaleFactor); - clipDx = scaleAndGetShift(xa, xScaleFactor2); - } - - if(editY2) { - yScaleFactor2 = yScaleFactor; - clipDy = ns ? viewBox[1] : getShift(ya, yScaleFactor2); - } else if(matches.yaHash[ya._id]) { - yScaleFactor2 = yScaleFactor; - clipDy = viewBox[1] * ya._length / ya0._length; - } else if(matches.xaHash[ya._id]) { - yScaleFactor2 = xScaleFactor; - clipDy = xActive === 'ew' ? - -viewBox[0] * ya._length / xa0._length : - getShift(ya, yScaleFactor2, {e: 'right', w: 'left'}[xActive]); - } else { - yScaleFactor2 = getLinkedScaleFactor(ya, xScaleFactor, yScaleFactor); - clipDy = scaleAndGetShift(ya, yScaleFactor2); - } - - // don't scale at all if neither axis is scalable here - if(!xScaleFactor2 && !yScaleFactor2) { - continue; - } - - // but if only one is, reset the other axis scaling - if(!xScaleFactor2) xScaleFactor2 = 1; - if(!yScaleFactor2) yScaleFactor2 = 1; - - var plotDx = xa._offset - clipDx / xScaleFactor2; - var plotDy = ya._offset - clipDy / yScaleFactor2; - - // TODO could be more efficient here: - // setTranslate and setScale do a lot of extra work - // when working independently, should perhaps combine - // them into a single routine. - sp.clipRect - .call(Drawing.setTranslate, clipDx, clipDy) - .call(Drawing.setScale, xScaleFactor2, yScaleFactor2); - - sp.plot - .call(Drawing.setTranslate, plotDx, plotDy) - .call(Drawing.setScale, 1 / xScaleFactor2, 1 / yScaleFactor2); - - // apply an inverse scale to individual points to counteract - // the scale of the trace group. - // apply only when scale changes, as adjusting the scale of - // all the points can be expansive. - if(xScaleFactor2 !== sp.xScaleFactor || yScaleFactor2 !== sp.yScaleFactor) { - Drawing.setPointGroupScale(sp.zoomScalePts, xScaleFactor2, yScaleFactor2); - Drawing.setTextPointsScale(sp.zoomScaleTxt, xScaleFactor2, yScaleFactor2); - } - - Drawing.hideOutsideRangePoints(sp.clipOnAxisFalseTraces, sp); - - // update x/y scaleFactor stash - sp.xScaleFactor = xScaleFactor2; - sp.yScaleFactor = yScaleFactor2; - } - } - } - - // Find the appropriate scaling for this axis, if it's linked to the - // dragged axes by constraints. 0 is special, it means this axis shouldn't - // ever be scaled (will be converted to 1 if the other axis is scaled) - function getLinkedScaleFactor(ax, xScaleFactor, yScaleFactor) { - if(ax.fixedrange) return 0; - - if(editX && links.xaHash[ax._id]) { - return xScaleFactor; - } - if(editY && (links.isSubplotConstrained ? links.xaHash : links.yaHash)[ax._id]) { - return yScaleFactor; - } - return 0; - } - - function scaleAndGetShift(ax, scaleFactor) { - if(scaleFactor) { - ax.range = ax._r.slice(); - scaleZoom(ax, scaleFactor); - return getShift(ax, scaleFactor); - } - return 0; - } - - function getShift(ax, scaleFactor, from) { - return ax._length * (1 - scaleFactor) * FROM_TL[from || ax.constraintoward || 'middle']; - } - - return dragger; -} - -function makeDragger(plotinfo, nodeName, dragClass, cursor) { - var dragger3 = Lib.ensureSingle(plotinfo.draglayer, nodeName, dragClass, function(s) { - s.classed('drag', true) - .style({fill: 'transparent', 'stroke-width': 0}) - .attr('data-subplot', plotinfo.id); - }); - - dragger3.call(setCursor, cursor); - - return dragger3.node(); -} - -function makeRectDragger(plotinfo, dragClass, cursor, x, y, w, h) { - var dragger = makeDragger(plotinfo, 'rect', dragClass, cursor); - d3.select(dragger).call(Drawing.setRect, x, y, w, h); - return dragger; -} - -function isDirectionActive(axList, activeVal) { - for(var i = 0; i < axList.length; i++) { - if(!axList[i].fixedrange) return activeVal; - } - return ''; -} - -function getEndText(ax, end) { - var initialVal = ax.range[end]; - var diff = Math.abs(initialVal - ax.range[1 - end]); - var dig; - - // TODO: this should basically be ax.r2d but we're doing extra - // rounding here... can we clean up at all? - if(ax.type === 'date') { - return initialVal; - } else if(ax.type === 'log') { - dig = Math.ceil(Math.max(0, -Math.log(diff) / Math.LN10)) + 3; - return d3.format('.' + dig + 'g')(Math.pow(10, initialVal)); - } else { // linear numeric (or category... but just show numbers here) - dig = Math.floor(Math.log(Math.abs(initialVal)) / Math.LN10) - - Math.floor(Math.log(diff) / Math.LN10) + 4; - return d3.format('.' + String(dig) + 'g')(initialVal); - } -} - -function zoomAxRanges(axList, r0Fraction, r1Fraction, updates, linkedAxes) { - for(var i = 0; i < axList.length; i++) { - var axi = axList[i]; - if(axi.fixedrange) continue; - - var axRangeLinear0 = axi._rl[0]; - var axRangeLinearSpan = axi._rl[1] - axRangeLinear0; - updates[axi._name + '.range[0]'] = axi.l2r(axRangeLinear0 + axRangeLinearSpan * r0Fraction); - updates[axi._name + '.range[1]'] = axi.l2r(axRangeLinear0 + axRangeLinearSpan * r1Fraction); - } - - // zoom linked axes about their centers - if(linkedAxes && linkedAxes.length) { - var linkedR0Fraction = (r0Fraction + (1 - r1Fraction)) / 2; - zoomAxRanges(linkedAxes, linkedR0Fraction, 1 - linkedR0Fraction, updates, []); - } -} - -function dragAxList(axList, pix) { - for(var i = 0; i < axList.length; i++) { - var axi = axList[i]; - if(!axi.fixedrange) { - axi.range = [ - axi.l2r(axi._rl[0] - pix / axi._m), - axi.l2r(axi._rl[1] - pix / axi._m) - ]; - } - } -} - -// common transform for dragging one end of an axis -// d>0 is compressing scale (cursor is over the plot, -// the axis end should move with the cursor) -// d<0 is expanding (cursor is off the plot, axis end moves -// nonlinearly so you can expand far) -function dZoom(d) { - return 1 - ((d >= 0) ? Math.min(d, 0.9) : - 1 / (1 / Math.max(d, -0.3) + 3.222)); -} - -function getDragCursor(nsew, dragmode, isMainDrag) { - if(!nsew) return 'pointer'; - if(nsew === 'nsew') { - // in this case here, clear cursor and - // use the cursor style set on - if(isMainDrag) return ''; - if(dragmode === 'pan') return 'move'; - return 'crosshair'; - } - return nsew.toLowerCase() + '-resize'; -} - -function makeZoombox(zoomlayer, lum, xs, ys, path0) { - return zoomlayer.append('path') - .attr('class', 'zoombox') - .style({ - 'fill': lum > 0.2 ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)', - 'stroke-width': 0 - }) - .attr('transform', 'translate(' + xs + ', ' + ys + ')') - .attr('d', path0 + 'Z'); -} - -function makeCorners(zoomlayer, xs, ys) { - return zoomlayer.append('path') - .attr('class', 'zoombox-corners') - .style({ - fill: Color.background, - stroke: Color.defaultLine, - 'stroke-width': 1, - opacity: 0 - }) - .attr('transform', 'translate(' + xs + ', ' + ys + ')') - .attr('d', 'M0,0Z'); -} - -function updateZoombox(zb, corners, box, path0, dimmed, lum) { - zb.attr('d', - path0 + 'M' + (box.l) + ',' + (box.t) + 'v' + (box.h) + - 'h' + (box.w) + 'v-' + (box.h) + 'h-' + (box.w) + 'Z'); - transitionZoombox(zb, corners, dimmed, lum); -} - -function transitionZoombox(zb, corners, dimmed, lum) { - if(!dimmed) { - zb.transition() - .style('fill', lum > 0.2 ? 'rgba(0,0,0,0.4)' : - 'rgba(255,255,255,0.3)') - .duration(200); - corners.transition() - .style('opacity', 1) - .duration(200); - } -} - -function removeZoombox(gd) { - d3.select(gd) - .selectAll('.zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners') - .remove(); -} - -function showDoubleClickNotifier(gd) { - if(SHOWZOOMOUTTIP && gd.data && gd._context.showTips) { - Lib.notifier(Lib._(gd, 'Double-click to zoom back out'), 'long'); - SHOWZOOMOUTTIP = false; - } -} - -function isSelectOrLasso(dragmode) { - return dragmode === 'lasso' || dragmode === 'select'; -} - -function xCorners(box, y0) { - return 'M' + - (box.l - 0.5) + ',' + (y0 - MINZOOM - 0.5) + - 'h-3v' + (2 * MINZOOM + 1) + 'h3ZM' + - (box.r + 0.5) + ',' + (y0 - MINZOOM - 0.5) + - 'h3v' + (2 * MINZOOM + 1) + 'h-3Z'; -} - -function yCorners(box, x0) { - return 'M' + - (x0 - MINZOOM - 0.5) + ',' + (box.t - 0.5) + - 'v-3h' + (2 * MINZOOM + 1) + 'v3ZM' + - (x0 - MINZOOM - 0.5) + ',' + (box.b + 0.5) + - 'v3h' + (2 * MINZOOM + 1) + 'v-3Z'; -} - -function xyCorners(box) { - var clen = Math.floor(Math.min(box.b - box.t, box.r - box.l, MINZOOM) / 2); - return 'M' + - (box.l - 3.5) + ',' + (box.t - 0.5 + clen) + 'h3v' + (-clen) + - 'h' + clen + 'v-3h-' + (clen + 3) + 'ZM' + - (box.r + 3.5) + ',' + (box.t - 0.5 + clen) + 'h-3v' + (-clen) + - 'h' + (-clen) + 'v-3h' + (clen + 3) + 'ZM' + - (box.r + 3.5) + ',' + (box.b + 0.5 - clen) + 'h-3v' + clen + - 'h' + (-clen) + 'v3h' + (clen + 3) + 'ZM' + - (box.l - 3.5) + ',' + (box.b + 0.5 - clen) + 'h3v' + clen + - 'h' + clen + 'v3h-' + (clen + 3) + 'Z'; -} - -function calcLinks(gd, groups, xaHash, yaHash) { - var isSubplotConstrained = false; - var xLinks = {}; - var yLinks = {}; - var xID, yID, xLinkID, yLinkID; - - for(var i = 0; i < groups.length; i++) { - var group = groups[i]; - // check if any of the x axes we're dragging is in this constraint group - for(xID in xaHash) { - if(group[xID]) { - // put the rest of these axes into xLinks, if we're not already - // dragging them, so we know to scale these axes automatically too - // to match the changes in the dragged x axes - for(xLinkID in group) { - if(!(xLinkID.charAt(0) === 'x' ? xaHash : yaHash)[xLinkID]) { - xLinks[xLinkID] = xID; - } - } - - // check if the x and y axes of THIS drag are linked - for(yID in yaHash) { - if(group[yID]) isSubplotConstrained = true; - } - } - } - - // now check if any of the y axes we're dragging is in this constraint group - // only look for outside links, as we've already checked for links within the dragger - for(yID in yaHash) { - if(group[yID]) { - for(yLinkID in group) { - if(!(yLinkID.charAt(0) === 'x' ? xaHash : yaHash)[yLinkID]) { - yLinks[yLinkID] = yID; - } - } - } - } - } - - if(isSubplotConstrained) { - // merge xLinks and yLinks if the subplot is constrained, - // since we'll always apply both anyway and the two will contain - // duplicates - Lib.extendFlat(xLinks, yLinks); - yLinks = {}; - } - - var xaHashLinked = {}; - var xaxesLinked = []; - for(xLinkID in xLinks) { - var xa = getFromId(gd, xLinkID); - xaxesLinked.push(xa); - xaHashLinked[xa._id] = xa; - } - - var yaHashLinked = {}; - var yaxesLinked = []; - for(yLinkID in yLinks) { - var ya = getFromId(gd, yLinkID); - yaxesLinked.push(ya); - yaHashLinked[ya._id] = ya; - } - - return { - xaHash: xaHashLinked, - yaHash: yaHashLinked, - xaxes: xaxesLinked, - yaxes: yaxesLinked, - xLinks: xLinks, - yLinks: yLinks, - isSubplotConstrained: isSubplotConstrained - }; -} - -// still seems to be some confusion about onwheel vs onmousewheel... -function attachWheelEventHandler(element, handler) { - if(!supportsPassive) { - if(element.onwheel !== undefined) element.onwheel = handler; - else if(element.onmousewheel !== undefined) element.onmousewheel = handler; - } else { - var wheelEventName = element.onwheel !== undefined ? 'wheel' : 'mousewheel'; - - if(element._onwheel) { - element.removeEventListener(wheelEventName, element._onwheel); - } - element._onwheel = handler; - - element.addEventListener(wheelEventName, handler, {passive: false}); - } -} - -function hashValues(hash) { - var out = []; - for(var k in hash) out.push(hash[k]); - return out; -} - -module.exports = { - makeDragBox: makeDragBox, - - makeDragger: makeDragger, - makeRectDragger: makeRectDragger, - makeZoombox: makeZoombox, - makeCorners: makeCorners, - - updateZoombox: updateZoombox, - xyCorners: xyCorners, - transitionZoombox: transitionZoombox, - removeZoombox: removeZoombox, - showDoubleClickNotifier: showDoubleClickNotifier, - - attachWheelEventHandler: attachWheelEventHandler -}; - -},{"../../components/color":593,"../../components/dragelement":611,"../../components/drawing":614,"../../components/fx":632,"../../constants/alignment":688,"../../lib":719,"../../lib/clear_gl_canvases":704,"../../lib/setcursor":739,"../../lib/svg_text_utils":743,"../../plot_api/subroutines":758,"../../registry":847,"../plots":828,"./axes":767,"./axis_ids":770,"./constants":773,"./scale_zoom":783,"./select":784,"d3":163,"has-passive-events":411,"tinycolor2":537}],776:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Fx = _dereq_('../../components/fx'); -var dragElement = _dereq_('../../components/dragelement'); -var setCursor = _dereq_('../../lib/setcursor'); - -var makeDragBox = _dereq_('./dragbox').makeDragBox; -var DRAGGERSIZE = _dereq_('./constants').DRAGGERSIZE; - -exports.initInteractions = function initInteractions(gd) { - var fullLayout = gd._fullLayout; - - if(gd._context.staticPlot) { - // this sweeps up more than just cartesian drag elements... - d3.select(gd).selectAll('.drag').remove(); - return; - } - - if(!fullLayout._has('cartesian') && !fullLayout._has('splom')) return; - - var subplots = Object.keys(fullLayout._plots || {}).sort(function(a, b) { - // sort overlays last, then by x axis number, then y axis number - if((fullLayout._plots[a].mainplot && true) === - (fullLayout._plots[b].mainplot && true)) { - var aParts = a.split('y'); - var bParts = b.split('y'); - return (aParts[0] === bParts[0]) ? - (Number(aParts[1] || 1) - Number(bParts[1] || 1)) : - (Number(aParts[0] || 1) - Number(bParts[0] || 1)); - } - return fullLayout._plots[a].mainplot ? 1 : -1; - }); - - subplots.forEach(function(subplot) { - var plotinfo = fullLayout._plots[subplot]; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - // main and corner draggers need not be repeated for - // overlaid subplots - these draggers drag them all - if(!plotinfo.mainplot) { - // main dragger goes over the grids and data, so we use its - // mousemove events for all data hover effects - var maindrag = makeDragBox(gd, plotinfo, xa._offset, ya._offset, - xa._length, ya._length, 'ns', 'ew'); - - maindrag.onmousemove = function(evt) { - // This is on `gd._fullLayout`, *not* fullLayout because the reference - // changes by the time this is called again. - gd._fullLayout._rehover = function() { - if(gd._fullLayout._hoversubplot === subplot) { - Fx.hover(gd, evt, subplot); - } - }; - - Fx.hover(gd, evt, subplot); - - // Note that we have *not* used the cached fullLayout variable here - // since that may be outdated when this is called as a callback later on - gd._fullLayout._lasthover = maindrag; - gd._fullLayout._hoversubplot = subplot; - }; - - /* - * IMPORTANT: - * We must check for the presence of the drag cover here. - * If we don't, a 'mouseout' event is triggered on the - * maindrag before each 'click' event, which has the effect - * of clearing the hoverdata; thus, cancelling the click event. - */ - maindrag.onmouseout = function(evt) { - if(gd._dragging) return; - - // When the mouse leaves this maindrag, unset the hovered subplot. - // This may cause problems if it leaves the subplot directly *onto* - // another subplot, but that's a tiny corner case at the moment. - gd._fullLayout._hoversubplot = null; - - dragElement.unhover(gd, evt); - }; - - // corner draggers - if(gd._context.showAxisDragHandles) { - makeDragBox(gd, plotinfo, xa._offset - DRAGGERSIZE, ya._offset - DRAGGERSIZE, - DRAGGERSIZE, DRAGGERSIZE, 'n', 'w'); - makeDragBox(gd, plotinfo, xa._offset + xa._length, ya._offset - DRAGGERSIZE, - DRAGGERSIZE, DRAGGERSIZE, 'n', 'e'); - makeDragBox(gd, plotinfo, xa._offset - DRAGGERSIZE, ya._offset + ya._length, - DRAGGERSIZE, DRAGGERSIZE, 's', 'w'); - makeDragBox(gd, plotinfo, xa._offset + xa._length, ya._offset + ya._length, - DRAGGERSIZE, DRAGGERSIZE, 's', 'e'); - } - } - if(gd._context.showAxisDragHandles) { - // x axis draggers - if you have overlaid plots, - // these drag each axis separately - if(subplot === xa._mainSubplot) { - // the y position of the main x axis line - var y0 = xa._mainLinePosition; - if(xa.side === 'top') y0 -= DRAGGERSIZE; - makeDragBox(gd, plotinfo, xa._offset + xa._length * 0.1, y0, - xa._length * 0.8, DRAGGERSIZE, '', 'ew'); - makeDragBox(gd, plotinfo, xa._offset, y0, - xa._length * 0.1, DRAGGERSIZE, '', 'w'); - makeDragBox(gd, plotinfo, xa._offset + xa._length * 0.9, y0, - xa._length * 0.1, DRAGGERSIZE, '', 'e'); - } - // y axis draggers - if(subplot === ya._mainSubplot) { - // the x position of the main y axis line - var x0 = ya._mainLinePosition; - if(ya.side !== 'right') x0 -= DRAGGERSIZE; - makeDragBox(gd, plotinfo, x0, ya._offset + ya._length * 0.1, - DRAGGERSIZE, ya._length * 0.8, 'ns', ''); - makeDragBox(gd, plotinfo, x0, ya._offset + ya._length * 0.9, - DRAGGERSIZE, ya._length * 0.1, 's', ''); - makeDragBox(gd, plotinfo, x0, ya._offset, - DRAGGERSIZE, ya._length * 0.1, 'n', ''); - } - } - }); - - // In case you mousemove over some hovertext, send it to Fx.hover too - // we do this so that we can put the hover text in front of everything, - // but still be able to interact with everything as if it isn't there - var hoverLayer = fullLayout._hoverlayer.node(); - - hoverLayer.onmousemove = function(evt) { - evt.target = gd._fullLayout._lasthover; - Fx.hover(gd, evt, fullLayout._hoversubplot); - }; - - hoverLayer.onclick = function(evt) { - evt.target = gd._fullLayout._lasthover; - Fx.click(gd, evt); - }; - - // also delegate mousedowns... TODO: does this actually work? - hoverLayer.onmousedown = function(evt) { - gd._fullLayout._lasthover.onmousedown(evt); - }; - - exports.updateFx(gd); -}; - -// Minimal set of update needed on 'modebar' edits. -// We only need to update the cursor style. -// -// Note that changing the axis configuration and/or the fixedrange attribute -// should trigger a full initInteractions. -exports.updateFx = function(gd) { - var fullLayout = gd._fullLayout; - var cursor = fullLayout.dragmode === 'pan' ? 'move' : 'crosshair'; - setCursor(fullLayout._draggers, cursor); -}; - -},{"../../components/dragelement":611,"../../components/fx":632,"../../lib/setcursor":739,"./constants":773,"./dragbox":775,"d3":163}],777:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); - -/** - * Factory function for checking component arrays for subplot references. - * - * @param {string} containerArrayName: the top-level array in gd.layout to check - * If an item in this container is found that references a cartesian x and/or y axis, - * ensure cartesian is marked as a base plot module and record the axes (and subplot - * if both refs are axes) in gd._fullLayout - * - * @return {function}: with args layoutIn (gd.layout) and layoutOut (gd._fullLayout) - * as expected of a component includeBasePlot method - */ -module.exports = function makeIncludeComponents(containerArrayName) { - return function includeComponents(layoutIn, layoutOut) { - var array = layoutIn[containerArrayName]; - if(!Array.isArray(array)) return; - - var Cartesian = Registry.subplotsRegistry.cartesian; - var idRegex = Cartesian.idRegex; - var subplots = layoutOut._subplots; - var xaList = subplots.xaxis; - var yaList = subplots.yaxis; - var cartesianList = subplots.cartesian; - var hasCartesianOrGL2D = layoutOut._has('cartesian') || layoutOut._has('gl2d'); - - for(var i = 0; i < array.length; i++) { - var itemi = array[i]; - if(!Lib.isPlainObject(itemi)) continue; - - var xref = itemi.xref; - var yref = itemi.yref; - - var hasXref = idRegex.x.test(xref); - var hasYref = idRegex.y.test(yref); - if(hasXref || hasYref) { - if(!hasCartesianOrGL2D) Lib.pushUnique(layoutOut._basePlotModules, Cartesian); - - var newAxis = false; - if(hasXref && xaList.indexOf(xref) === -1) { - xaList.push(xref); - newAxis = true; - } - if(hasYref && yaList.indexOf(yref) === -1) { - yaList.push(yref); - newAxis = true; - } - - /* - * Notice the logic here: only add a subplot for a component if - * it's referencing both x and y axes AND it's creating a new axis - * so for example if your plot already has xy and x2y2, an annotation - * on x2y or xy2 will not create a new subplot. - */ - if(newAxis && hasXref && hasYref) { - cartesianList.push(xref + yref); - } - } - } - }; -}; - -},{"../../lib":719,"../../registry":847}],778:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Plots = _dereq_('../plots'); -var Drawing = _dereq_('../../components/drawing'); - -var getModuleCalcData = _dereq_('../get_data').getModuleCalcData; -var axisIds = _dereq_('./axis_ids'); -var constants = _dereq_('./constants'); -var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); - -var ensureSingle = Lib.ensureSingle; - -function ensureSingleAndAddDatum(parent, nodeType, className) { - return Lib.ensureSingle(parent, nodeType, className, function(s) { - s.datum(className); - }); -} - -exports.name = 'cartesian'; - -exports.attr = ['xaxis', 'yaxis']; - -exports.idRoot = ['x', 'y']; - -exports.idRegex = constants.idRegex; - -exports.attrRegex = constants.attrRegex; - -exports.attributes = _dereq_('./attributes'); - -exports.layoutAttributes = _dereq_('./layout_attributes'); - -exports.supplyLayoutDefaults = _dereq_('./layout_defaults'); - -exports.transitionAxes = _dereq_('./transition_axes'); - -exports.finalizeSubplots = function(layoutIn, layoutOut) { - var subplots = layoutOut._subplots; - var xList = subplots.xaxis; - var yList = subplots.yaxis; - var spSVG = subplots.cartesian; - var spAll = spSVG.concat(subplots.gl2d || []); - var allX = {}; - var allY = {}; - var i, xi, yi; - - for(i = 0; i < spAll.length; i++) { - var parts = spAll[i].split('y'); - allX[parts[0]] = 1; - allY['y' + parts[1]] = 1; - } - - // check for x axes with no subplot, and make one from the anchor of that x axis - for(i = 0; i < xList.length; i++) { - xi = xList[i]; - if(!allX[xi]) { - yi = (layoutIn[axisIds.id2name(xi)] || {}).anchor; - if(!constants.idRegex.y.test(yi)) yi = 'y'; - spSVG.push(xi + yi); - spAll.push(xi + yi); - - if(!allY[yi]) { - allY[yi] = 1; - Lib.pushUnique(yList, yi); - } - } - } - - // same for y axes with no subplot - for(i = 0; i < yList.length; i++) { - yi = yList[i]; - if(!allY[yi]) { - xi = (layoutIn[axisIds.id2name(yi)] || {}).anchor; - if(!constants.idRegex.x.test(xi)) xi = 'x'; - spSVG.push(xi + yi); - spAll.push(xi + yi); - - if(!allX[xi]) { - allX[xi] = 1; - Lib.pushUnique(xList, xi); - } - } - } - - // finally, if we've gotten here we're supposed to show cartesian... - // so if there are NO subplots at all, make one from the first - // x & y axes in the input layout - if(!spAll.length) { - xi = ''; - yi = ''; - for(var ki in layoutIn) { - if(constants.attrRegex.test(ki)) { - var axLetter = ki.charAt(0); - if(axLetter === 'x') { - if(!xi || (+ki.substr(5) < +xi.substr(5))) { - xi = ki; - } - } else if(!yi || (+ki.substr(5) < +yi.substr(5))) { - yi = ki; - } - } - } - xi = xi ? axisIds.name2id(xi) : 'x'; - yi = yi ? axisIds.name2id(yi) : 'y'; - xList.push(xi); - yList.push(yi); - spSVG.push(xi + yi); - } -}; - -/** - * Cartesian.plot - * - * @param {DOM div | object} gd - * @param {array (optional)} traces - * array of traces indices to plot - * if undefined, plots all cartesian traces, - * @param {object} (optional) transitionOpts - * transition option object - * @param {function} (optional) makeOnCompleteCallback - * transition make callback function from Plots.transition - */ -exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { - var fullLayout = gd._fullLayout; - var subplots = fullLayout._subplots.cartesian; - var calcdata = gd.calcdata; - var i; - - if(!Array.isArray(traces)) { - // If traces is not provided, then it's a complete replot and missing - // traces are removed - traces = []; - for(i = 0; i < calcdata.length; i++) traces.push(i); - } - - for(i = 0; i < subplots.length; i++) { - var subplot = subplots[i]; - var subplotInfo = fullLayout._plots[subplot]; - - // Get all calcdata for this subplot: - var cdSubplot = []; - var pcd; - - for(var j = 0; j < calcdata.length; j++) { - var cd = calcdata[j]; - var trace = cd[0].trace; - - // Skip trace if whitelist provided and it's not whitelisted: - // if (Array.isArray(traces) && traces.indexOf(i) === -1) continue; - if(trace.xaxis + trace.yaxis === subplot) { - // XXX: Should trace carpet dependencies. Only replot all carpet plots if the carpet - // axis has actually changed: - // - // If this trace is specifically requested, add it to the list: - if(traces.indexOf(trace.index) !== -1 || trace.carpet) { - // Okay, so example: traces 0, 1, and 2 have fill = tonext. You animate - // traces 0 and 2. Trace 1 also needs to be updated, otherwise its fill - // is outdated. So this retroactively adds the previous trace if the - // traces are interdependent. - if( - pcd && - pcd[0].trace.xaxis + pcd[0].trace.yaxis === subplot && - ['tonextx', 'tonexty', 'tonext'].indexOf(trace.fill) !== -1 && - cdSubplot.indexOf(pcd) === -1 - ) { - cdSubplot.push(pcd); - } - - cdSubplot.push(cd); - } - - // Track the previous trace on this subplot for the retroactive-add step - // above: - pcd = cd; - } - } - - plotOne(gd, subplotInfo, cdSubplot, transitionOpts, makeOnCompleteCallback); - } -}; - -function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback) { - var traceLayerClasses = constants.traceLayerClasses; - var fullLayout = gd._fullLayout; - var modules = fullLayout._modules; - var _module, cdModuleAndOthers, cdModule; - - var layerData = []; - var zoomScaleQueryParts = []; - - for(var i = 0; i < modules.length; i++) { - _module = modules[i]; - var name = _module.name; - var categories = Registry.modules[name].categories; - - if(categories.svg) { - var className = (_module.layerName || name + 'layer'); - var plotMethod = _module.plot; - - // plot all visible traces of this type on this subplot at once - cdModuleAndOthers = getModuleCalcData(cdSubplot, plotMethod); - cdModule = cdModuleAndOthers[0]; - // don't need to search the found traces again - in fact we need to NOT - // so that if two modules share the same plotter we don't double-plot - cdSubplot = cdModuleAndOthers[1]; - - if(cdModule.length) { - layerData.push({ - i: traceLayerClasses.indexOf(className), - className: className, - plotMethod: plotMethod, - cdModule: cdModule - }); - } - - if(categories.zoomScale) { - zoomScaleQueryParts.push('.' + className); - } - } - } - - layerData.sort(function(a, b) { return a.i - b.i; }); - - var layers = plotinfo.plot.selectAll('g.mlayer') - .data(layerData, function(d) { return d.className; }); - - layers.enter().append('g') - .attr('class', function(d) { return d.className; }) - .classed('mlayer', true) - .classed('rangeplot', plotinfo.isRangePlot); - - layers.exit().remove(); - - layers.order(); - - layers.each(function(d) { - var sel = d3.select(this); - var className = d.className; - - d.plotMethod( - gd, plotinfo, d.cdModule, sel, - transitionOpts, makeOnCompleteCallback - ); - - // layers that allow `cliponaxis: false` - if(constants.clipOnAxisFalseQuery.indexOf('.' + className) === -1) { - Drawing.setClipUrl(sel, plotinfo.layerClipId, gd); - } - }); - - // call Scattergl.plot separately - if(fullLayout._has('scattergl')) { - _module = Registry.getModule('scattergl'); - cdModule = getModuleCalcData(cdSubplot, _module)[0]; - _module.plot(gd, plotinfo, cdModule); - } - - // stash "hot" selections for faster interaction on drag and scroll - if(!gd._context.staticPlot) { - if(plotinfo._hasClipOnAxisFalse) { - plotinfo.clipOnAxisFalseTraces = plotinfo.plot - .selectAll(constants.clipOnAxisFalseQuery.join(',')) - .selectAll('.trace'); - } - - if(zoomScaleQueryParts.length) { - var traces = plotinfo.plot - .selectAll(zoomScaleQueryParts.join(',')) - .selectAll('.trace'); - - plotinfo.zoomScalePts = traces.selectAll('path.point'); - plotinfo.zoomScaleTxt = traces.selectAll('.textpoint'); - } - } -} - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var oldPlots = oldFullLayout._plots || {}; - var newPlots = newFullLayout._plots || {}; - var oldSubplotList = oldFullLayout._subplots || {}; - var plotinfo; - var i, k; - - // when going from a large splom graph to something else, - // we need to clear so that the new cartesian subplot - // can have the correct layer ordering - if(oldFullLayout._hasOnlyLargeSploms && !newFullLayout._hasOnlyLargeSploms) { - for(k in oldPlots) { - plotinfo = oldPlots[k]; - if(plotinfo.plotgroup) plotinfo.plotgroup.remove(); - } - } - - var hadGl = (oldFullLayout._has && oldFullLayout._has('gl')); - var hasGl = (newFullLayout._has && newFullLayout._has('gl')); - - if(hadGl && !hasGl) { - for(k in oldPlots) { - plotinfo = oldPlots[k]; - if(plotinfo._scene) plotinfo._scene.destroy(); - } - } - - // delete any titles we don't need anymore - // check if axis list has changed, and if so clear old titles - if(oldSubplotList.xaxis && oldSubplotList.yaxis) { - var oldAxIDs = axisIds.listIds({_fullLayout: oldFullLayout}); - for(i = 0; i < oldAxIDs.length; i++) { - var oldAxId = oldAxIDs[i]; - if(!newFullLayout[axisIds.id2name(oldAxId)]) { - oldFullLayout._infolayer.selectAll('.g-' + oldAxId + 'title').remove(); - } - } - } - - var hadCartesian = (oldFullLayout._has && oldFullLayout._has('cartesian')); - var hasCartesian = (newFullLayout._has && newFullLayout._has('cartesian')); - - if(hadCartesian && !hasCartesian) { - // if we've gotten rid of all cartesian traces, remove all the subplot svg items - - purgeSubplotLayers(oldFullLayout._cartesianlayer.selectAll('.subplot'), oldFullLayout); - oldFullLayout._defs.selectAll('.axesclip').remove(); - delete oldFullLayout._axisConstraintGroups; - } else if(oldSubplotList.cartesian) { - // otherwise look for subplots we need to remove - - for(i = 0; i < oldSubplotList.cartesian.length; i++) { - var oldSubplotId = oldSubplotList.cartesian[i]; - if(!newPlots[oldSubplotId]) { - var selector = '.' + oldSubplotId + ',.' + oldSubplotId + '-x,.' + oldSubplotId + '-y'; - oldFullLayout._cartesianlayer.selectAll(selector).remove(); - removeSubplotExtras(oldSubplotId, oldFullLayout); - } - } - } -}; - -exports.drawFramework = function(gd) { - var fullLayout = gd._fullLayout; - var subplotData = makeSubplotData(gd); - - var subplotLayers = fullLayout._cartesianlayer.selectAll('.subplot') - .data(subplotData, String); - - subplotLayers.enter().append('g') - .attr('class', function(d) { return 'subplot ' + d[0]; }); - - subplotLayers.order(); - - subplotLayers.exit() - .call(purgeSubplotLayers, fullLayout); - - subplotLayers.each(function(d) { - var id = d[0]; - var plotinfo = fullLayout._plots[id]; - - plotinfo.plotgroup = d3.select(this); - makeSubplotLayer(gd, plotinfo); - - // make separate drag layers for each subplot, - // but append them to paper rather than the plot groups, - // so they end up on top of the rest - plotinfo.draglayer = ensureSingle(fullLayout._draggers, 'g', id); - }); -}; - -exports.rangePlot = function(gd, plotinfo, cdSubplot) { - makeSubplotLayer(gd, plotinfo); - plotOne(gd, plotinfo, cdSubplot); - Plots.style(gd); -}; - -function makeSubplotData(gd) { - var fullLayout = gd._fullLayout; - var ids = fullLayout._subplots.cartesian; - var len = ids.length; - var i, j, id, plotinfo, xa, ya; - - // split 'regular' and 'overlaying' subplots - var regulars = []; - var overlays = []; - - for(i = 0; i < len; i++) { - id = ids[i]; - plotinfo = fullLayout._plots[id]; - xa = plotinfo.xaxis; - ya = plotinfo.yaxis; - - var xa2 = xa._mainAxis; - var ya2 = ya._mainAxis; - var mainplot = xa2._id + ya2._id; - var mainplotinfo = fullLayout._plots[mainplot]; - plotinfo.overlays = []; - - if(mainplot !== id && mainplotinfo) { - plotinfo.mainplot = mainplot; - plotinfo.mainplotinfo = mainplotinfo; - overlays.push(id); - } else { - plotinfo.mainplot = undefined; - plotinfo.mainPlotinfo = undefined; - regulars.push(id); - } - } - - // fill in list of overlaying subplots in 'main plot' - for(i = 0; i < overlays.length; i++) { - id = overlays[i]; - plotinfo = fullLayout._plots[id]; - plotinfo.mainplotinfo.overlays.push(plotinfo); - } - - // put 'regular' subplot data before 'overlaying' - var subplotIds = regulars.concat(overlays); - var subplotData = new Array(len); - - for(i = 0; i < len; i++) { - id = subplotIds[i]; - plotinfo = fullLayout._plots[id]; - xa = plotinfo.xaxis; - ya = plotinfo.yaxis; - - // use info about axis layer and overlaying pattern - // to clean what need to be cleaned up in exit selection - var d = [id, xa.layer, ya.layer, xa.overlaying || '', ya.overlaying || '']; - for(j = 0; j < plotinfo.overlays.length; j++) { - d.push(plotinfo.overlays[j].id); - } - subplotData[i] = d; - } - - return subplotData; -} - -function makeSubplotLayer(gd, plotinfo) { - var plotgroup = plotinfo.plotgroup; - var id = plotinfo.id; - var xLayer = constants.layerValue2layerClass[plotinfo.xaxis.layer]; - var yLayer = constants.layerValue2layerClass[plotinfo.yaxis.layer]; - var hasOnlyLargeSploms = gd._fullLayout._hasOnlyLargeSploms; - - if(!plotinfo.mainplot) { - if(hasOnlyLargeSploms) { - // TODO could do even better - // - we don't need plot (but we would have to mock it in lsInner - // and other places - // - we don't (x|y)lines and (x|y)axislayer for most subplots - // usually just the bottom x and left y axes. - plotinfo.xlines = ensureSingle(plotgroup, 'path', 'xlines-above'); - plotinfo.ylines = ensureSingle(plotgroup, 'path', 'ylines-above'); - plotinfo.xaxislayer = ensureSingle(plotgroup, 'g', 'xaxislayer-above'); - plotinfo.yaxislayer = ensureSingle(plotgroup, 'g', 'yaxislayer-above'); - } else { - var backLayer = ensureSingle(plotgroup, 'g', 'layer-subplot'); - plotinfo.shapelayer = ensureSingle(backLayer, 'g', 'shapelayer'); - plotinfo.imagelayer = ensureSingle(backLayer, 'g', 'imagelayer'); - - plotinfo.gridlayer = ensureSingle(plotgroup, 'g', 'gridlayer'); - plotinfo.zerolinelayer = ensureSingle(plotgroup, 'g', 'zerolinelayer'); - - ensureSingle(plotgroup, 'path', 'xlines-below'); - ensureSingle(plotgroup, 'path', 'ylines-below'); - plotinfo.overlinesBelow = ensureSingle(plotgroup, 'g', 'overlines-below'); - - ensureSingle(plotgroup, 'g', 'xaxislayer-below'); - ensureSingle(plotgroup, 'g', 'yaxislayer-below'); - plotinfo.overaxesBelow = ensureSingle(plotgroup, 'g', 'overaxes-below'); - - plotinfo.plot = ensureSingle(plotgroup, 'g', 'plot'); - plotinfo.overplot = ensureSingle(plotgroup, 'g', 'overplot'); - - plotinfo.xlines = ensureSingle(plotgroup, 'path', 'xlines-above'); - plotinfo.ylines = ensureSingle(plotgroup, 'path', 'ylines-above'); - plotinfo.overlinesAbove = ensureSingle(plotgroup, 'g', 'overlines-above'); - - ensureSingle(plotgroup, 'g', 'xaxislayer-above'); - ensureSingle(plotgroup, 'g', 'yaxislayer-above'); - plotinfo.overaxesAbove = ensureSingle(plotgroup, 'g', 'overaxes-above'); - - // set refs to correct layers as determined by 'axis.layer' - plotinfo.xlines = plotgroup.select('.xlines-' + xLayer); - plotinfo.ylines = plotgroup.select('.ylines-' + yLayer); - plotinfo.xaxislayer = plotgroup.select('.xaxislayer-' + xLayer); - plotinfo.yaxislayer = plotgroup.select('.yaxislayer-' + yLayer); - } - } else { - var mainplotinfo = plotinfo.mainplotinfo; - var mainplotgroup = mainplotinfo.plotgroup; - var xId = id + '-x'; - var yId = id + '-y'; - - // now make the components of overlaid subplots - // overlays don't have backgrounds, and append all - // their other components to the corresponding - // extra groups of their main plots. - - plotinfo.gridlayer = mainplotinfo.gridlayer; - plotinfo.zerolinelayer = mainplotinfo.zerolinelayer; - - ensureSingle(mainplotinfo.overlinesBelow, 'path', xId); - ensureSingle(mainplotinfo.overlinesBelow, 'path', yId); - ensureSingle(mainplotinfo.overaxesBelow, 'g', xId); - ensureSingle(mainplotinfo.overaxesBelow, 'g', yId); - - plotinfo.plot = ensureSingle(mainplotinfo.overplot, 'g', id); - - ensureSingle(mainplotinfo.overlinesAbove, 'path', xId); - ensureSingle(mainplotinfo.overlinesAbove, 'path', yId); - ensureSingle(mainplotinfo.overaxesAbove, 'g', xId); - ensureSingle(mainplotinfo.overaxesAbove, 'g', yId); - - // set refs to correct layers as determined by 'abovetraces' - plotinfo.xlines = mainplotgroup.select('.overlines-' + xLayer).select('.' + xId); - plotinfo.ylines = mainplotgroup.select('.overlines-' + yLayer).select('.' + yId); - plotinfo.xaxislayer = mainplotgroup.select('.overaxes-' + xLayer).select('.' + xId); - plotinfo.yaxislayer = mainplotgroup.select('.overaxes-' + yLayer).select('.' + yId); - } - - // common attributes for all subplots, overlays or not - - if(!hasOnlyLargeSploms) { - ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.xaxis._id); - ensureSingleAndAddDatum(plotinfo.gridlayer, 'g', plotinfo.yaxis._id); - plotinfo.gridlayer.selectAll('g') - .map(function(d) { return d[0]; }) - .sort(axisIds.idSort); - } - - plotinfo.xlines - .style('fill', 'none') - .classed('crisp', true); - - plotinfo.ylines - .style('fill', 'none') - .classed('crisp', true); -} - -function purgeSubplotLayers(layers, fullLayout) { - if(!layers) return; - - var overlayIdsToRemove = {}; - - layers.each(function(d) { - var id = d[0]; - var plotgroup = d3.select(this); - - plotgroup.remove(); - removeSubplotExtras(id, fullLayout); - overlayIdsToRemove[id] = true; - - // do not remove individual axis s here - // as other subplots may need them - }); - - // must remove overlaid subplot trace layers 'manually' - - for(var k in fullLayout._plots) { - var subplotInfo = fullLayout._plots[k]; - var overlays = subplotInfo.overlays || []; - - for(var j = 0; j < overlays.length; j++) { - var overlayInfo = overlays[j]; - - if(overlayIdsToRemove[overlayInfo.id]) { - overlayInfo.plot.selectAll('.trace').remove(); - } - } - } -} - -function removeSubplotExtras(subplotId, fullLayout) { - fullLayout._draggers.selectAll('g.' + subplotId).remove(); - fullLayout._defs.select('#clip' + fullLayout._uid + subplotId + 'plot').remove(); -} - -exports.toSVG = function(gd) { - var imageRoot = gd._fullLayout._glimages; - var root = d3.select(gd).selectAll('.svg-container'); - var canvases = root.filter(function(d, i) {return i === root.size() - 1;}) - .selectAll('.gl-canvas-context, .gl-canvas-focus'); - - function canvasToImage() { - var canvas = this; - var imageData = canvas.toDataURL('image/png'); - var image = imageRoot.append('svg:image'); - - image.attr({ - xmlns: xmlnsNamespaces.svg, - 'xlink:href': imageData, - preserveAspectRatio: 'none', - x: 0, - y: 0, - width: canvas.width, - height: canvas.height - }); - } - - canvases.each(canvasToImage); -}; - -exports.updateFx = _dereq_('./graph_interact').updateFx; - -},{"../../components/drawing":614,"../../constants/xmlns_namespaces":696,"../../lib":719,"../../registry":847,"../get_data":802,"../plots":828,"./attributes":765,"./axis_ids":770,"./constants":773,"./graph_interact":776,"./layout_attributes":779,"./layout_defaults":780,"./transition_axes":789,"d3":163}],779:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('../font_attributes'); -var colorAttrs = _dereq_('../../components/color/attributes'); -var dash = _dereq_('../../components/drawing/attributes').dash; -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - -var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK; -var DATE_FORMAT_LINK = _dereq_('../../constants/docs').DATE_FORMAT_LINK; - -var constants = _dereq_('./constants'); - -module.exports = { - visible: { - valType: 'boolean', - - editType: 'plot', - - }, - color: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'ticks', - - }, - title: { - text: { - valType: 'string', - - editType: 'ticks', - - }, - font: fontAttrs({ - editType: 'ticks', - - }), - editType: 'ticks' - }, - type: { - valType: 'enumerated', - // '-' means we haven't yet run autotype or couldn't find any data - // it gets turned into linear in gd._fullLayout but not copied back - // to gd.data like the others are. - values: ['-', 'linear', 'log', 'date', 'category', 'multicategory'], - dflt: '-', - - editType: 'calc', - // we forget when an axis has been autotyped, just writing the auto - // value back to the input - so it doesn't make sense to template this. - // Note: we do NOT prohibit this in `coerce`, so if someone enters a - // type in the template explicitly it will be honored as the default. - _noTemplating: true, - - }, - autorange: { - valType: 'enumerated', - values: [true, false, 'reversed'], - dflt: true, - - editType: 'axrange', - impliedEdits: {'range[0]': undefined, 'range[1]': undefined}, - - }, - rangemode: { - valType: 'enumerated', - values: ['normal', 'tozero', 'nonnegative'], - dflt: 'normal', - - editType: 'plot', - - }, - range: { - valType: 'info_array', - - items: [ - {valType: 'any', editType: 'axrange', impliedEdits: {'^autorange': false}, anim: true}, - {valType: 'any', editType: 'axrange', impliedEdits: {'^autorange': false}, anim: true} - ], - editType: 'axrange', - impliedEdits: {'autorange': false}, - anim: true, - - }, - fixedrange: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - // scaleanchor: not used directly, just put here for reference - // values are any opposite-letter axis id - scaleanchor: { - valType: 'enumerated', - values: [ - constants.idRegex.x.toString(), - constants.idRegex.y.toString() - ], - - editType: 'plot', - - }, - scaleratio: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'plot', - - }, - constrain: { - valType: 'enumerated', - values: ['range', 'domain'], - dflt: 'range', - - editType: 'plot', - - }, - // constraintoward: not used directly, just put here for reference - constraintoward: { - valType: 'enumerated', - values: ['left', 'center', 'right', 'top', 'middle', 'bottom'], - - editType: 'plot', - - }, - matches: { - valType: 'enumerated', - values: [ - constants.idRegex.x.toString(), - constants.idRegex.y.toString() - ], - - editType: 'calc', - - }, - // ticks - tickmode: { - valType: 'enumerated', - values: ['auto', 'linear', 'array'], - - editType: 'ticks', - impliedEdits: {tick0: undefined, dtick: undefined}, - - }, - nticks: { - valType: 'integer', - min: 0, - dflt: 0, - - editType: 'ticks', - - }, - tick0: { - valType: 'any', - - editType: 'ticks', - impliedEdits: {tickmode: 'linear'}, - - }, - dtick: { - valType: 'any', - - editType: 'ticks', - impliedEdits: {tickmode: 'linear'}, - - }, - tickvals: { - valType: 'data_array', - editType: 'ticks', - - }, - ticktext: { - valType: 'data_array', - editType: 'ticks', - - }, - ticks: { - valType: 'enumerated', - values: ['outside', 'inside', ''], - - editType: 'ticks', - - }, - tickson: { - valType: 'enumerated', - values: ['labels', 'boundaries'], - - dflt: 'labels', - editType: 'ticks', - - }, - mirror: { - valType: 'enumerated', - values: [true, 'ticks', false, 'all', 'allticks'], - dflt: false, - - editType: 'ticks+layoutstyle', - - }, - ticklen: { - valType: 'number', - min: 0, - dflt: 5, - - editType: 'ticks', - - }, - tickwidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'ticks', - - }, - tickcolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'ticks', - - }, - showticklabels: { - valType: 'boolean', - dflt: true, - - editType: 'ticks', - - }, - automargin: { - valType: 'boolean', - dflt: false, - - editType: 'ticks', - - }, - showspikes: { - valType: 'boolean', - dflt: false, - - editType: 'modebar', - - }, - spikecolor: { - valType: 'color', - dflt: null, - - editType: 'none', - - }, - spikethickness: { - valType: 'number', - dflt: 3, - - editType: 'none', - - }, - spikedash: extendFlat({}, dash, {dflt: 'dash', editType: 'none'}), - spikemode: { - valType: 'flaglist', - flags: ['toaxis', 'across', 'marker'], - - dflt: 'toaxis', - editType: 'none', - - }, - spikesnap: { - valType: 'enumerated', - values: ['data', 'cursor'], - dflt: 'data', - - editType: 'none', - - }, - tickfont: fontAttrs({ - editType: 'ticks', - - }), - tickangle: { - valType: 'angle', - dflt: 'auto', - - editType: 'ticks', - - }, - tickprefix: { - valType: 'string', - dflt: '', - - editType: 'ticks', - - }, - showtickprefix: { - valType: 'enumerated', - values: ['all', 'first', 'last', 'none'], - dflt: 'all', - - editType: 'ticks', - - }, - ticksuffix: { - valType: 'string', - dflt: '', - - editType: 'ticks', - - }, - showticksuffix: { - valType: 'enumerated', - values: ['all', 'first', 'last', 'none'], - dflt: 'all', - - editType: 'ticks', - - }, - showexponent: { - valType: 'enumerated', - values: ['all', 'first', 'last', 'none'], - dflt: 'all', - - editType: 'ticks', - - }, - exponentformat: { - valType: 'enumerated', - values: ['none', 'e', 'E', 'power', 'SI', 'B'], - dflt: 'B', - - editType: 'ticks', - - }, - separatethousands: { - valType: 'boolean', - dflt: false, - - editType: 'ticks', - - }, - tickformat: { - valType: 'string', - dflt: '', - - editType: 'ticks', - - }, - tickformatstops: templatedArray('tickformatstop', { - enabled: { - valType: 'boolean', - - dflt: true, - editType: 'ticks', - - }, - dtickrange: { - valType: 'info_array', - - items: [ - {valType: 'any', editType: 'ticks'}, - {valType: 'any', editType: 'ticks'} - ], - editType: 'ticks', - - }, - value: { - valType: 'string', - dflt: '', - - editType: 'ticks', - - }, - editType: 'ticks' - }), - hoverformat: { - valType: 'string', - dflt: '', - - editType: 'none', - - }, - // lines and grids - showline: { - valType: 'boolean', - dflt: false, - - editType: 'ticks+layoutstyle', - - }, - linecolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'layoutstyle', - - }, - linewidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'ticks+layoutstyle', - - }, - showgrid: { - valType: 'boolean', - - editType: 'ticks', - - }, - gridcolor: { - valType: 'color', - dflt: colorAttrs.lightLine, - - editType: 'ticks', - - }, - gridwidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'ticks', - - }, - zeroline: { - valType: 'boolean', - - editType: 'ticks', - - }, - zerolinecolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'ticks', - - }, - zerolinewidth: { - valType: 'number', - dflt: 1, - - editType: 'ticks', - - }, - - showdividers: { - valType: 'boolean', - dflt: true, - - editType: 'ticks', - - }, - dividercolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'ticks', - - }, - dividerwidth: { - valType: 'number', - dflt: 1, - - editType: 'ticks', - - }, - // TODO dividerlen: that would override "to label base" length? - - // positioning attributes - // anchor: not used directly, just put here for reference - // values are any opposite-letter axis id - anchor: { - valType: 'enumerated', - values: [ - 'free', - constants.idRegex.x.toString(), - constants.idRegex.y.toString() - ], - - editType: 'plot', - - }, - // side: not used directly, as values depend on direction - // values are top, bottom for x axes, and left, right for y - side: { - valType: 'enumerated', - values: ['top', 'bottom', 'left', 'right'], - - editType: 'plot', - - }, - // overlaying: not used directly, just put here for reference - // values are false and any other same-letter axis id that's not - // itself overlaying anything - overlaying: { - valType: 'enumerated', - values: [ - 'free', - constants.idRegex.x.toString(), - constants.idRegex.y.toString() - ], - - editType: 'plot', - - }, - layer: { - valType: 'enumerated', - values: ['above traces', 'below traces'], - dflt: 'above traces', - - editType: 'plot', - - }, - domain: { - valType: 'info_array', - - items: [ - {valType: 'number', min: 0, max: 1, editType: 'plot'}, - {valType: 'number', min: 0, max: 1, editType: 'plot'} - ], - dflt: [0, 1], - editType: 'plot', - - }, - position: { - valType: 'number', - min: 0, - max: 1, - dflt: 0, - - editType: 'plot', - - }, - categoryorder: { - valType: 'enumerated', - values: [ - 'trace', 'category ascending', 'category descending', 'array', - 'total ascending', 'total descending', - 'min ascending', 'min descending', - 'max ascending', 'max descending', - 'sum ascending', 'sum descending', - 'mean ascending', 'mean descending', - 'median ascending', 'median descending' - ], - dflt: 'trace', - - editType: 'calc', - - }, - categoryarray: { - valType: 'data_array', - - editType: 'calc', - - }, - uirevision: { - valType: 'any', - - editType: 'none', - - }, - editType: 'calc', - - _deprecated: { - autotick: { - valType: 'boolean', - - editType: 'ticks', - - }, - title: { - valType: 'string', - - editType: 'ticks', - - }, - titlefont: fontAttrs({ - editType: 'ticks', - - }) - } -}; - -},{"../../components/color/attributes":592,"../../components/drawing/attributes":613,"../../constants/docs":690,"../../lib/extend":710,"../../plot_api/plot_template":757,"../font_attributes":793,"./constants":773}],780:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); -var Template = _dereq_('../../plot_api/plot_template'); -var basePlotLayoutAttributes = _dereq_('../layout_attributes'); - -var layoutAttributes = _dereq_('./layout_attributes'); -var handleTypeDefaults = _dereq_('./type_defaults'); -var handleAxisDefaults = _dereq_('./axis_defaults'); -var handleConstraintDefaults = _dereq_('./constraints').handleConstraintDefaults; -var handlePositionDefaults = _dereq_('./position_defaults'); - -var axisIds = _dereq_('./axis_ids'); -var id2name = axisIds.id2name; -var name2id = axisIds.name2id; - -var Registry = _dereq_('../../registry'); -var traceIs = Registry.traceIs; -var getComponentMethod = Registry.getComponentMethod; - -function appendList(cont, k, item) { - if(Array.isArray(cont[k])) cont[k].push(item); - else cont[k] = [item]; -} - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - var ax2traces = {}; - var xaMayHide = {}; - var yaMayHide = {}; - var xaMustDisplay = {}; - var yaMustDisplay = {}; - var yaMustForward = {}; - var yaMayBackward = {}; - var outerTicks = {}; - var noGrids = {}; - var i, j; - - // look for axes in the data - for(i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - if(!traceIs(trace, 'cartesian') && !traceIs(trace, 'gl2d')) continue; - - var xaName; - if(trace.xaxis) { - xaName = id2name(trace.xaxis); - appendList(ax2traces, xaName, trace); - } else if(trace.xaxes) { - for(j = 0; j < trace.xaxes.length; j++) { - appendList(ax2traces, id2name(trace.xaxes[j]), trace); - } - } - - var yaName; - if(trace.yaxis) { - yaName = id2name(trace.yaxis); - appendList(ax2traces, yaName, trace); - } else if(trace.yaxes) { - for(j = 0; j < trace.yaxes.length; j++) { - appendList(ax2traces, id2name(trace.yaxes[j]), trace); - } - } - - // logic for funnels - if(trace.type === 'funnel') { - if(trace.orientation === 'h') { - if(xaName) xaMayHide[xaName] = true; - if(yaName) yaMayBackward[yaName] = true; - } else { - if(yaName) yaMayHide[yaName] = true; - } - } else { - if(yaName) { - yaMustDisplay[yaName] = true; - yaMustForward[yaName] = true; - } - - if(!traceIs(trace, 'carpet') || (trace.type === 'carpet' && !trace._cheater)) { - if(xaName) xaMustDisplay[xaName] = true; - } - } - - // Two things trigger axis visibility: - // 1. is not carpet - // 2. carpet that's not cheater - - // The above check for definitely-not-cheater is not adequate. This - // second list tracks which axes *could* be a cheater so that the - // full condition triggering hiding is: - // *could* be a cheater and *is not definitely visible* - if(trace.type === 'carpet' && trace._cheater) { - if(xaName) xaMayHide[xaName] = true; - } - - // check for default formatting tweaks - if(traceIs(trace, '2dMap')) { - outerTicks[xaName] = true; - outerTicks[yaName] = true; - } - - if(traceIs(trace, 'oriented')) { - var positionAxis = trace.orientation === 'h' ? yaName : xaName; - noGrids[positionAxis] = true; - } - } - - var subplots = layoutOut._subplots; - var xIds = subplots.xaxis; - var yIds = subplots.yaxis; - var xNames = Lib.simpleMap(xIds, id2name); - var yNames = Lib.simpleMap(yIds, id2name); - var axNames = xNames.concat(yNames); - - // plot_bgcolor only makes sense if there's a (2D) plot! - // TODO: bgcolor for each subplot, to inherit from the main one - var plotBgColor = Color.background; - if(xIds.length && yIds.length) { - plotBgColor = Lib.coerce(layoutIn, layoutOut, basePlotLayoutAttributes, 'plot_bgcolor'); - } - - var bgColor = Color.combine(plotBgColor, layoutOut.paper_bgcolor); - - var axName, axLetter, axLayoutIn, axLayoutOut; - - function coerce(attr, dflt) { - return Lib.coerce(axLayoutIn, axLayoutOut, layoutAttributes, attr, dflt); - } - - function coerce2(attr, dflt) { - return Lib.coerce2(axLayoutIn, axLayoutOut, layoutAttributes, attr, dflt); - } - - function getCounterAxes(axLetter) { - return (axLetter === 'x') ? yIds : xIds; - } - - var counterAxes = {x: getCounterAxes('x'), y: getCounterAxes('y')}; - var allAxisIds = counterAxes.x.concat(counterAxes.y); - - function getOverlayableAxes(axLetter, axName) { - var list = (axLetter === 'x') ? xNames : yNames; - var out = []; - - for(var j = 0; j < list.length; j++) { - var axName2 = list[j]; - - if(axName2 !== axName && !(layoutIn[axName2] || {}).overlaying) { - out.push(name2id(axName2)); - } - } - - return out; - } - - // first pass creates the containers, determines types, and handles most of the settings - for(i = 0; i < axNames.length; i++) { - axName = axNames[i]; - axLetter = axName.charAt(0); - - if(!Lib.isPlainObject(layoutIn[axName])) { - layoutIn[axName] = {}; - } - - axLayoutIn = layoutIn[axName]; - axLayoutOut = Template.newContainer(layoutOut, axName, axLetter + 'axis'); - - var traces = ax2traces[axName] || []; - axLayoutOut._traceIndices = traces.map(function(t) { return t._expandedIndex; }); - axLayoutOut._annIndices = []; - axLayoutOut._shapeIndices = []; - axLayoutOut._imgIndices = []; - axLayoutOut._subplotsWith = []; - axLayoutOut._counterAxes = []; - - // set up some private properties - axLayoutOut._name = axLayoutOut._attr = axName; - var id = axLayoutOut._id = name2id(axName); - - var overlayableAxes = getOverlayableAxes(axLetter, axName); - - var visibleDflt = - (axLetter === 'x' && !xaMustDisplay[axName] && xaMayHide[axName]) || - (axLetter === 'y' && !yaMustDisplay[axName] && yaMayHide[axName]); - - var reverseDflt = - (axLetter === 'y' && !yaMustForward[axName] && yaMayBackward[axName]); - - var defaultOptions = { - letter: axLetter, - font: layoutOut.font, - outerTicks: outerTicks[axName], - showGrid: !noGrids[axName], - data: traces, - bgColor: bgColor, - calendar: layoutOut.calendar, - automargin: true, - visibleDflt: visibleDflt, - reverseDflt: reverseDflt, - splomStash: ((layoutOut._splomAxes || {})[axLetter] || {})[id] - }; - - coerce('uirevision', layoutOut.uirevision); - - handleTypeDefaults(axLayoutIn, axLayoutOut, coerce, defaultOptions); - handleAxisDefaults(axLayoutIn, axLayoutOut, coerce, defaultOptions, layoutOut); - - var spikecolor = coerce2('spikecolor'); - var spikethickness = coerce2('spikethickness'); - var spikedash = coerce2('spikedash'); - var spikemode = coerce2('spikemode'); - var spikesnap = coerce2('spikesnap'); - var showSpikes = coerce('showspikes', !!spikecolor || !!spikethickness || !!spikedash || !!spikemode || !!spikesnap); - - if(!showSpikes) { - delete axLayoutOut.spikecolor; - delete axLayoutOut.spikethickness; - delete axLayoutOut.spikedash; - delete axLayoutOut.spikemode; - delete axLayoutOut.spikesnap; - } - - handlePositionDefaults(axLayoutIn, axLayoutOut, coerce, { - letter: axLetter, - counterAxes: counterAxes[axLetter], - overlayableAxes: overlayableAxes, - grid: layoutOut.grid - }); - - axLayoutOut._input = axLayoutIn; - } - - // quick second pass for range slider and selector defaults - var rangeSliderDefaults = getComponentMethod('rangeslider', 'handleDefaults'); - var rangeSelectorDefaults = getComponentMethod('rangeselector', 'handleDefaults'); - - for(i = 0; i < xNames.length; i++) { - axName = xNames[i]; - axLayoutIn = layoutIn[axName]; - axLayoutOut = layoutOut[axName]; - - rangeSliderDefaults(layoutIn, layoutOut, axName); - - if(axLayoutOut.type === 'date') { - rangeSelectorDefaults( - axLayoutIn, - axLayoutOut, - layoutOut, - yNames, - axLayoutOut.calendar - ); - } - - coerce('fixedrange'); - } - - for(i = 0; i < yNames.length; i++) { - axName = yNames[i]; - axLayoutIn = layoutIn[axName]; - axLayoutOut = layoutOut[axName]; - - var anchoredAxis = layoutOut[id2name(axLayoutOut.anchor)]; - - var fixedRangeDflt = getComponentMethod('rangeslider', 'isVisible')(anchoredAxis); - - coerce('fixedrange', fixedRangeDflt); - } - - // Finally, handle scale constraints and matching axes. - // - // We need to do this after all axes have coerced both `type` - // (so we link only axes of the same type) and - // `fixedrange` (so we can avoid linking from OR TO a fixed axis). - - // sets of axes linked by `scaleanchor` along with the scaleratios compounded - // together, populated in handleConstraintDefaults - var constraintGroups = layoutOut._axisConstraintGroups = []; - // similar to _axisConstraintGroups, but for matching axes - var matchGroups = layoutOut._axisMatchGroups = []; - - for(i = 0; i < axNames.length; i++) { - axName = axNames[i]; - axLetter = axName.charAt(0); - axLayoutIn = layoutIn[axName]; - axLayoutOut = layoutOut[axName]; - - handleConstraintDefaults(axLayoutIn, axLayoutOut, coerce, allAxisIds, layoutOut); - } - - for(i = 0; i < matchGroups.length; i++) { - var group = matchGroups[i]; - var rng = null; - var autorange = null; - var axId; - - // find 'matching' range attrs - for(axId in group) { - axLayoutOut = layoutOut[id2name(axId)]; - if(!axLayoutOut.matches) { - rng = axLayoutOut.range; - autorange = axLayoutOut.autorange; - } - } - // if `ax.matches` values are reciprocal, - // pick values of first axis in group - if(rng === null || autorange === null) { - for(axId in group) { - axLayoutOut = layoutOut[id2name(axId)]; - rng = axLayoutOut.range; - autorange = axLayoutOut.autorange; - break; - } - } - // apply matching range attrs - for(axId in group) { - axLayoutOut = layoutOut[id2name(axId)]; - if(axLayoutOut.matches) { - axLayoutOut.range = rng.slice(); - axLayoutOut.autorange = autorange; - } - axLayoutOut._matchGroup = group; - } - - // remove matching axis from scaleanchor constraint groups (for now) - if(constraintGroups.length) { - for(axId in group) { - for(j = 0; j < constraintGroups.length; j++) { - var group2 = constraintGroups[j]; - for(var axId2 in group2) { - if(axId === axId2) { - Lib.warn('Axis ' + axId2 + ' is set with both ' + - 'a *scaleanchor* and *matches* constraint; ' + - 'ignoring the scale constraint.'); - - delete group2[axId2]; - if(Object.keys(group2).length < 2) { - constraintGroups.splice(j, 1); - } - } - } - } - } - } - } -}; - -},{"../../components/color":593,"../../lib":719,"../../plot_api/plot_template":757,"../../registry":847,"../layout_attributes":819,"./axis_defaults":769,"./axis_ids":770,"./constraints":774,"./layout_attributes":779,"./position_defaults":782,"./type_defaults":790}],781:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorMix = _dereq_('tinycolor2').mix; -var lightFraction = _dereq_('../../components/color/attributes').lightFraction; -var Lib = _dereq_('../../lib'); - -/** - * @param {object} opts : - * - dfltColor {string} : default axis color - * - bgColor {string} : combined subplot bg color - * - blend {number, optional} : blend percentage (to compute dflt grid color) - * - showLine {boolean} : show line by default - * - showGrid {boolean} : show grid by default - * - noZeroLine {boolean} : don't coerce zeroline* attributes - * - attributes {object} : attribute object associated with input containers - */ -module.exports = function handleLineGridDefaults(containerIn, containerOut, coerce, opts) { - opts = opts || {}; - - var dfltColor = opts.dfltColor; - - function coerce2(attr, dflt) { - return Lib.coerce2(containerIn, containerOut, opts.attributes, attr, dflt); - } - - var lineColor = coerce2('linecolor', dfltColor); - var lineWidth = coerce2('linewidth'); - var showLine = coerce('showline', opts.showLine || !!lineColor || !!lineWidth); - - if(!showLine) { - delete containerOut.linecolor; - delete containerOut.linewidth; - } - - var gridColorDflt = colorMix(dfltColor, opts.bgColor, opts.blend || lightFraction).toRgbString(); - var gridColor = coerce2('gridcolor', gridColorDflt); - var gridWidth = coerce2('gridwidth'); - var showGridLines = coerce('showgrid', opts.showGrid || !!gridColor || !!gridWidth); - - if(!showGridLines) { - delete containerOut.gridcolor; - delete containerOut.gridwidth; - } - - if(!opts.noZeroLine) { - var zeroLineColor = coerce2('zerolinecolor', dfltColor); - var zeroLineWidth = coerce2('zerolinewidth'); - var showZeroLine = coerce('zeroline', opts.showGrid || !!zeroLineColor || !!zeroLineWidth); - - if(!showZeroLine) { - delete containerOut.zerolinecolor; - delete containerOut.zerolinewidth; - } - } -}; - -},{"../../components/color/attributes":592,"../../lib":719,"tinycolor2":537}],782:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); - - -module.exports = function handlePositionDefaults(containerIn, containerOut, coerce, options) { - var counterAxes = options.counterAxes || []; - var overlayableAxes = options.overlayableAxes || []; - var letter = options.letter; - var grid = options.grid; - - var dfltAnchor, dfltDomain, dfltSide, dfltPosition; - - if(grid) { - dfltDomain = grid._domains[letter][grid._axisMap[containerOut._id]]; - dfltAnchor = grid._anchors[containerOut._id]; - if(dfltDomain) { - dfltSide = grid[letter + 'side'].split(' ')[0]; - dfltPosition = grid.domain[letter][dfltSide === 'right' || dfltSide === 'top' ? 1 : 0]; - } - } - - // Even if there's a grid, this axis may not be in it - fall back on non-grid defaults - dfltDomain = dfltDomain || [0, 1]; - dfltAnchor = dfltAnchor || (isNumeric(containerIn.position) ? 'free' : (counterAxes[0] || 'free')); - dfltSide = dfltSide || (letter === 'x' ? 'bottom' : 'left'); - dfltPosition = dfltPosition || 0; - - var anchor = Lib.coerce(containerIn, containerOut, { - anchor: { - valType: 'enumerated', - values: ['free'].concat(counterAxes), - dflt: dfltAnchor - } - }, 'anchor'); - - if(anchor === 'free') coerce('position', dfltPosition); - - Lib.coerce(containerIn, containerOut, { - side: { - valType: 'enumerated', - values: letter === 'x' ? ['bottom', 'top'] : ['left', 'right'], - dflt: dfltSide - } - }, 'side'); - - var overlaying = false; - if(overlayableAxes.length) { - overlaying = Lib.coerce(containerIn, containerOut, { - overlaying: { - valType: 'enumerated', - values: [false].concat(overlayableAxes), - dflt: false - } - }, 'overlaying'); - } - - if(!overlaying) { - // TODO: right now I'm copying this domain over to overlaying axes - // in ax.setscale()... but this means we still need (imperfect) logic - // in the axes popover to hide domain for the overlaying axis. - // perhaps I should make a private version _domain that all axes get??? - var domain = coerce('domain', dfltDomain); - - // according to https://www.npmjs.com/package/canvas-size - // the minimum value of max canvas width across browsers and devices is 4096 - // which applied in the calculation below: - if(domain[0] > domain[1] - 1 / 4096) containerOut.domain = dfltDomain; - Lib.noneOrAll(containerIn.domain, containerOut.domain, dfltDomain); - } - - coerce('layer'); - - return containerOut; -}; - -},{"../../lib":719,"fast-isnumeric":225}],783:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var FROM_BL = _dereq_('../../constants/alignment').FROM_BL; - -module.exports = function scaleZoom(ax, factor, centerFraction) { - if(centerFraction === undefined) { - centerFraction = FROM_BL[ax.constraintoward || 'center']; - } - - var rangeLinear = [ax.r2l(ax.range[0]), ax.r2l(ax.range[1])]; - var center = rangeLinear[0] + (rangeLinear[1] - rangeLinear[0]) * centerFraction; - - ax.range = ax._input.range = [ - ax.l2r(center + (rangeLinear[0] - center) * factor), - ax.l2r(center + (rangeLinear[1] - center) * factor) - ]; -}; - -},{"../../constants/alignment":688}],784:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var polybool = _dereq_('polybooljs'); - -var Registry = _dereq_('../../registry'); -var Color = _dereq_('../../components/color'); -var Fx = _dereq_('../../components/fx'); - -var Lib = _dereq_('../../lib'); -var polygon = _dereq_('../../lib/polygon'); -var throttle = _dereq_('../../lib/throttle'); -var makeEventData = _dereq_('../../components/fx/helpers').makeEventData; -var getFromId = _dereq_('./axis_ids').getFromId; -var clearGlCanvases = _dereq_('../../lib/clear_gl_canvases'); - -var redrawReglTraces = _dereq_('../../plot_api/subroutines').redrawReglTraces; - -var constants = _dereq_('./constants'); -var MINSELECT = constants.MINSELECT; - -var filteredPolygon = polygon.filter; -var polygonTester = polygon.tester; - -function getAxId(ax) { return ax._id; } - -function prepSelect(e, startX, startY, dragOptions, mode) { - var gd = dragOptions.gd; - var fullLayout = gd._fullLayout; - var zoomLayer = fullLayout._zoomlayer; - var dragBBox = dragOptions.element.getBoundingClientRect(); - var plotinfo = dragOptions.plotinfo; - var xs = plotinfo.xaxis._offset; - var ys = plotinfo.yaxis._offset; - var x0 = startX - dragBBox.left; - var y0 = startY - dragBBox.top; - var x1 = x0; - var y1 = y0; - var path0 = 'M' + x0 + ',' + y0; - var pw = dragOptions.xaxes[0]._length; - var ph = dragOptions.yaxes[0]._length; - var allAxes = dragOptions.xaxes.concat(dragOptions.yaxes); - var subtract = e.altKey; - - var filterPoly, selectionTester, mergedPolygons, currentPolygon; - var i, searchInfo, eventData; - - coerceSelectionsCache(e, gd, dragOptions); - - if(mode === 'lasso') { - filterPoly = filteredPolygon([[x0, y0]], constants.BENDPX); - } - - var outlines = zoomLayer.selectAll('path.select-outline-' + plotinfo.id).data([1, 2]); - - outlines.enter() - .append('path') - .attr('class', function(d) { return 'select-outline select-outline-' + d + ' select-outline-' + plotinfo.id; }) - .attr('transform', 'translate(' + xs + ', ' + ys + ')') - .attr('d', path0 + 'Z'); - - var corners = zoomLayer.append('path') - .attr('class', 'zoombox-corners') - .style({ - fill: Color.background, - stroke: Color.defaultLine, - 'stroke-width': 1 - }) - .attr('transform', 'translate(' + xs + ', ' + ys + ')') - .attr('d', 'M0,0Z'); - - - var throttleID = fullLayout._uid + constants.SELECTID; - var selection = []; - - // find the traces to search for selection points - var searchTraces = determineSearchTraces(gd, dragOptions.xaxes, - dragOptions.yaxes, dragOptions.subplot); - - // in v2 (once log ranges are fixed), - // we'll be able to p2r here for all axis types - function p2r(ax, v) { - return ax.type === 'log' ? ax.p2d(v) : ax.p2r(v); - } - - function axValue(ax) { - var index = (ax._id.charAt(0) === 'y') ? 1 : 0; - return function(v) { return p2r(ax, v[index]); }; - } - - function ascending(a, b) { return a - b; } - - // allow subplots to override fillRangeItems routine - var fillRangeItems; - - if(plotinfo.fillRangeItems) { - fillRangeItems = plotinfo.fillRangeItems; - } else { - if(mode === 'select') { - fillRangeItems = function(eventData, poly) { - var ranges = eventData.range = {}; - - for(i = 0; i < allAxes.length; i++) { - var ax = allAxes[i]; - var axLetter = ax._id.charAt(0); - - ranges[ax._id] = [ - p2r(ax, poly[axLetter + 'min']), - p2r(ax, poly[axLetter + 'max']) - ].sort(ascending); - } - }; - } else { - fillRangeItems = function(eventData, poly, filterPoly) { - var dataPts = eventData.lassoPoints = {}; - - for(i = 0; i < allAxes.length; i++) { - var ax = allAxes[i]; - dataPts[ax._id] = filterPoly.filtered.map(axValue(ax)); - } - }; - } - } - - dragOptions.moveFn = function(dx0, dy0) { - x1 = Math.max(0, Math.min(pw, dx0 + x0)); - y1 = Math.max(0, Math.min(ph, dy0 + y0)); - - var dx = Math.abs(x1 - x0); - var dy = Math.abs(y1 - y0); - - if(mode === 'select') { - var direction = fullLayout.selectdirection; - - if(fullLayout.selectdirection === 'any') { - if(dy < Math.min(dx * 0.6, MINSELECT)) direction = 'h'; - else if(dx < Math.min(dy * 0.6, MINSELECT)) direction = 'v'; - else direction = 'd'; - } else { - direction = fullLayout.selectdirection; - } - - if(direction === 'h') { - // horizontal motion: make a vertical box - currentPolygon = [[x0, 0], [x0, ph], [x1, ph], [x1, 0]]; - currentPolygon.xmin = Math.min(x0, x1); - currentPolygon.xmax = Math.max(x0, x1); - currentPolygon.ymin = Math.min(0, ph); - currentPolygon.ymax = Math.max(0, ph); - // extras to guide users in keeping a straight selection - corners.attr('d', 'M' + currentPolygon.xmin + ',' + (y0 - MINSELECT) + - 'h-4v' + (2 * MINSELECT) + 'h4Z' + - 'M' + (currentPolygon.xmax - 1) + ',' + (y0 - MINSELECT) + - 'h4v' + (2 * MINSELECT) + 'h-4Z'); - } else if(direction === 'v') { - // vertical motion: make a horizontal box - currentPolygon = [[0, y0], [0, y1], [pw, y1], [pw, y0]]; - currentPolygon.xmin = Math.min(0, pw); - currentPolygon.xmax = Math.max(0, pw); - currentPolygon.ymin = Math.min(y0, y1); - currentPolygon.ymax = Math.max(y0, y1); - corners.attr('d', 'M' + (x0 - MINSELECT) + ',' + currentPolygon.ymin + - 'v-4h' + (2 * MINSELECT) + 'v4Z' + - 'M' + (x0 - MINSELECT) + ',' + (currentPolygon.ymax - 1) + - 'v4h' + (2 * MINSELECT) + 'v-4Z'); - } else if(direction === 'd') { - // diagonal motion - currentPolygon = [[x0, y0], [x0, y1], [x1, y1], [x1, y0]]; - currentPolygon.xmin = Math.min(x0, x1); - currentPolygon.xmax = Math.max(x0, x1); - currentPolygon.ymin = Math.min(y0, y1); - currentPolygon.ymax = Math.max(y0, y1); - corners.attr('d', 'M0,0Z'); - } - } else if(mode === 'lasso') { - filterPoly.addPt([x1, y1]); - currentPolygon = filterPoly.filtered; - } - - // create outline & tester - if(dragOptions.selectionDefs && dragOptions.selectionDefs.length) { - mergedPolygons = mergePolygons(dragOptions.mergedPolygons, currentPolygon, subtract); - currentPolygon.subtract = subtract; - selectionTester = multiTester(dragOptions.selectionDefs.concat([currentPolygon])); - } else { - mergedPolygons = [currentPolygon]; - selectionTester = polygonTester(currentPolygon); - } - - // draw selection - drawSelection(mergedPolygons, outlines); - - - throttle.throttle( - throttleID, - constants.SELECTDELAY, - function() { - selection = []; - - var thisSelection; - var traceSelections = []; - var traceSelection; - for(i = 0; i < searchTraces.length; i++) { - searchInfo = searchTraces[i]; - - traceSelection = searchInfo._module.selectPoints(searchInfo, selectionTester); - traceSelections.push(traceSelection); - - thisSelection = fillSelectionItem(traceSelection, searchInfo); - - if(selection.length) { - for(var j = 0; j < thisSelection.length; j++) { - selection.push(thisSelection[j]); - } - } else selection = thisSelection; - } - - eventData = {points: selection}; - updateSelectedState(gd, searchTraces, eventData); - fillRangeItems(eventData, currentPolygon, filterPoly); - dragOptions.gd.emit('plotly_selecting', eventData); - } - ); - }; - - dragOptions.clickFn = function(numClicks, evt) { - var clickmode = fullLayout.clickmode; - - corners.remove(); - - throttle.done(throttleID).then(function() { - throttle.clear(throttleID); - if(numClicks === 2) { - // clear selection on doubleclick - outlines.remove(); - for(i = 0; i < searchTraces.length; i++) { - searchInfo = searchTraces[i]; - searchInfo._module.selectPoints(searchInfo, false); - } - - updateSelectedState(gd, searchTraces); - - clearSelectionsCache(dragOptions); - - gd.emit('plotly_deselect', null); - } else { - if(clickmode.indexOf('select') > -1) { - selectOnClick(evt, gd, dragOptions.xaxes, dragOptions.yaxes, - dragOptions.subplot, dragOptions, outlines); - } - - if(clickmode === 'event') { - // TODO: remove in v2 - this was probably never intended to work as it does, - // but in case anyone depends on it we don't want to break it now. - // Note that click-to-select introduced pre v2 also emitts proper - // event data when clickmode is having 'select' in its flag list. - gd.emit('plotly_selected', undefined); - } - } - - Fx.click(gd, evt); - }).catch(Lib.error); - }; - - dragOptions.doneFn = function() { - corners.remove(); - - throttle.done(throttleID).then(function() { - throttle.clear(throttleID); - dragOptions.gd.emit('plotly_selected', eventData); - - if(currentPolygon && dragOptions.selectionDefs) { - // save last polygons - currentPolygon.subtract = subtract; - dragOptions.selectionDefs.push(currentPolygon); - - // we have to keep reference to arrays container - dragOptions.mergedPolygons.length = 0; - [].push.apply(dragOptions.mergedPolygons, mergedPolygons); - } - - if(dragOptions.doneFnCompleted) { - dragOptions.doneFnCompleted(selection); - } - }).catch(Lib.error); - }; -} - -function selectOnClick(evt, gd, xAxes, yAxes, subplot, dragOptions, polygonOutlines) { - var hoverData = gd._hoverdata; - var clickmode = gd._fullLayout.clickmode; - var sendEvents = clickmode.indexOf('event') > -1; - var selection = []; - var searchTraces, searchInfo, currentSelectionDef, selectionTester, traceSelection; - var thisTracesSelection, pointOrBinSelected, subtract, eventData, i; - - if(isHoverDataSet(hoverData)) { - coerceSelectionsCache(evt, gd, dragOptions); - searchTraces = determineSearchTraces(gd, xAxes, yAxes, subplot); - var clickedPtInfo = extractClickedPtInfo(hoverData, searchTraces); - var isBinnedTrace = clickedPtInfo.pointNumbers.length > 0; - - - // Note: potentially costly operation isPointOrBinSelected is - // called as late as possible through the use of an assignment - // in an if condition. - if(isBinnedTrace ? - isOnlyThisBinSelected(searchTraces, clickedPtInfo) : - isOnlyOnePointSelected(searchTraces) && - (pointOrBinSelected = isPointOrBinSelected(clickedPtInfo))) { - if(polygonOutlines) polygonOutlines.remove(); - for(i = 0; i < searchTraces.length; i++) { - searchInfo = searchTraces[i]; - searchInfo._module.selectPoints(searchInfo, false); - } - - updateSelectedState(gd, searchTraces); - - clearSelectionsCache(dragOptions); - - if(sendEvents) { - gd.emit('plotly_deselect', null); - } - } else { - subtract = evt.shiftKey && - (pointOrBinSelected !== undefined ? - pointOrBinSelected : - isPointOrBinSelected(clickedPtInfo)); - currentSelectionDef = newPointSelectionDef(clickedPtInfo.pointNumber, clickedPtInfo.searchInfo, subtract); - - var allSelectionDefs = dragOptions.selectionDefs.concat([currentSelectionDef]); - selectionTester = multiTester(allSelectionDefs); - - for(i = 0; i < searchTraces.length; i++) { - traceSelection = searchTraces[i]._module.selectPoints(searchTraces[i], selectionTester); - thisTracesSelection = fillSelectionItem(traceSelection, searchTraces[i]); - - if(selection.length) { - for(var j = 0; j < thisTracesSelection.length; j++) { - selection.push(thisTracesSelection[j]); - } - } else selection = thisTracesSelection; - } - - eventData = {points: selection}; - updateSelectedState(gd, searchTraces, eventData); - - if(currentSelectionDef && dragOptions) { - dragOptions.selectionDefs.push(currentSelectionDef); - } - - if(polygonOutlines) drawSelection(dragOptions.mergedPolygons, polygonOutlines); - - if(sendEvents) { - gd.emit('plotly_selected', eventData); - } - } - } -} - -/** - * Constructs a new point selection definition object. - */ -function newPointSelectionDef(pointNumber, searchInfo, subtract) { - return { - pointNumber: pointNumber, - searchInfo: searchInfo, - subtract: subtract - }; -} - -function isPointSelectionDef(o) { - return 'pointNumber' in o && 'searchInfo' in o; -} - -/* - * Constructs a new point number tester. - */ -function newPointNumTester(pointSelectionDef) { - return { - xmin: 0, - xmax: 0, - ymin: 0, - ymax: 0, - pts: [], - contains: function(pt, omitFirstEdge, pointNumber, searchInfo) { - var idxWantedTrace = pointSelectionDef.searchInfo.cd[0].trace._expandedIndex; - var idxActualTrace = searchInfo.cd[0].trace._expandedIndex; - return idxActualTrace === idxWantedTrace && - pointNumber === pointSelectionDef.pointNumber; - }, - isRect: false, - degenerate: false, - subtract: pointSelectionDef.subtract - }; -} - -/** - * Wraps multiple selection testers. - * - * @param {Array} list - An array of selection testers. - * - * @return a selection tester object with a contains function - * that can be called to evaluate a point against all wrapped - * selection testers that were passed in list. - */ -function multiTester(list) { - var testers = []; - var xmin = isPointSelectionDef(list[0]) ? 0 : list[0][0][0]; - var xmax = xmin; - var ymin = isPointSelectionDef(list[0]) ? 0 : list[0][0][1]; - var ymax = ymin; - - for(var i = 0; i < list.length; i++) { - if(isPointSelectionDef(list[i])) { - testers.push(newPointNumTester(list[i])); - } else { - var tester = polygon.tester(list[i]); - tester.subtract = list[i].subtract; - testers.push(tester); - xmin = Math.min(xmin, tester.xmin); - xmax = Math.max(xmax, tester.xmax); - ymin = Math.min(ymin, tester.ymin); - ymax = Math.max(ymax, tester.ymax); - } - } - - /** - * Tests if the given point is within this tester. - * - * @param {Array} pt - [0] is the x coordinate, [1] is the y coordinate of the point. - * @param {*} arg - An optional parameter to pass down to wrapped testers. - * @param {number} pointNumber - The point number of the point within the underlying data array. - * @param {number} searchInfo - An object identifying the trace the point is contained in. - * - * @return {boolean} true if point is considered to be selected, false otherwise. - */ - function contains(pt, arg, pointNumber, searchInfo) { - var contained = false; - for(var i = 0; i < testers.length; i++) { - if(testers[i].contains(pt, arg, pointNumber, searchInfo)) { - // if contained by subtract tester - exclude the point - contained = testers[i].subtract === false; - } - } - - return contained; - } - - return { - xmin: xmin, - xmax: xmax, - ymin: ymin, - ymax: ymax, - pts: [], - contains: contains, - isRect: false, - degenerate: false - }; -} - -function coerceSelectionsCache(evt, gd, dragOptions) { - var fullLayout = gd._fullLayout; - var plotinfo = dragOptions.plotinfo; - - var selectingOnSameSubplot = ( - fullLayout._lastSelectedSubplot && - fullLayout._lastSelectedSubplot === plotinfo.id - ); - var hasModifierKey = evt.shiftKey || evt.altKey; - - if(selectingOnSameSubplot && hasModifierKey && - (plotinfo.selection && plotinfo.selection.selectionDefs) && !dragOptions.selectionDefs) { - // take over selection definitions from prev mode, if any - dragOptions.selectionDefs = plotinfo.selection.selectionDefs; - dragOptions.mergedPolygons = plotinfo.selection.mergedPolygons; - } else if(!hasModifierKey || !plotinfo.selection) { - clearSelectionsCache(dragOptions); - } - - // clear selection outline when selecting a different subplot - if(!selectingOnSameSubplot) { - clearSelect(gd); - fullLayout._lastSelectedSubplot = plotinfo.id; - } -} - -function clearSelectionsCache(dragOptions) { - var plotinfo = dragOptions.plotinfo; - - plotinfo.selection = {}; - plotinfo.selection.selectionDefs = dragOptions.selectionDefs = []; - plotinfo.selection.mergedPolygons = dragOptions.mergedPolygons = []; -} - -function determineSearchTraces(gd, xAxes, yAxes, subplot) { - var searchTraces = []; - var xAxisIds = xAxes.map(getAxId); - var yAxisIds = yAxes.map(getAxId); - var cd, trace, i; - - for(i = 0; i < gd.calcdata.length; i++) { - cd = gd.calcdata[i]; - trace = cd[0].trace; - - if(trace.visible !== true || !trace._module || !trace._module.selectPoints) continue; - - if(subplot && (trace.subplot === subplot || trace.geo === subplot)) { - searchTraces.push(createSearchInfo(trace._module, cd, xAxes[0], yAxes[0])); - } else if( - trace.type === 'splom' && - // FIXME: make sure we don't have more than single axis for splom - trace._xaxes[xAxisIds[0]] && trace._yaxes[yAxisIds[0]] - ) { - var info = createSearchInfo(trace._module, cd, xAxes[0], yAxes[0]); - info.scene = gd._fullLayout._splomScenes[trace.uid]; - searchTraces.push(info); - } else if( - trace.type === 'sankey' - ) { - var sankeyInfo = createSearchInfo(trace._module, cd, xAxes[0], yAxes[0]); - searchTraces.push(sankeyInfo); - } else { - if(xAxisIds.indexOf(trace.xaxis) === -1) continue; - if(yAxisIds.indexOf(trace.yaxis) === -1) continue; - - searchTraces.push(createSearchInfo(trace._module, cd, - getFromId(gd, trace.xaxis), getFromId(gd, trace.yaxis))); - } - } - - return searchTraces; - - function createSearchInfo(module, calcData, xaxis, yaxis) { - return { - _module: module, - cd: calcData, - xaxis: xaxis, - yaxis: yaxis - }; - } -} - -function drawSelection(polygons, outlines) { - var paths = []; - var i, d; - - for(i = 0; i < polygons.length; i++) { - var ppts = polygons[i]; - paths.push(ppts.join('L') + 'L' + ppts[0]); - } - - d = polygons.length > 0 ? - 'M' + paths.join('M') + 'Z' : - 'M0,0Z'; - outlines.attr('d', d); -} - -function isHoverDataSet(hoverData) { - return hoverData && - Array.isArray(hoverData) && - hoverData[0].hoverOnBox !== true; -} - -function extractClickedPtInfo(hoverData, searchTraces) { - var hoverDatum = hoverData[0]; - var pointNumber = -1; - var pointNumbers = []; - var searchInfo, i; - - for(i = 0; i < searchTraces.length; i++) { - searchInfo = searchTraces[i]; - if(hoverDatum.fullData._expandedIndex === searchInfo.cd[0].trace._expandedIndex) { - // Special case for box (and violin) - if(hoverDatum.hoverOnBox === true) { - break; - } - - // Hint: in some traces like histogram, one graphical element - // doesn't correspond to one particular data point, but to - // bins of data points. Thus, hoverDatum can have a binNumber - // property instead of pointNumber. - if(hoverDatum.pointNumber !== undefined) { - pointNumber = hoverDatum.pointNumber; - } else if(hoverDatum.binNumber !== undefined) { - pointNumber = hoverDatum.binNumber; - pointNumbers = hoverDatum.pointNumbers; - } - - break; - } - } - - return { - pointNumber: pointNumber, - pointNumbers: pointNumbers, - searchInfo: searchInfo - }; -} - -function isPointOrBinSelected(clickedPtInfo) { - var trace = clickedPtInfo.searchInfo.cd[0].trace; - var ptNum = clickedPtInfo.pointNumber; - var ptNums = clickedPtInfo.pointNumbers; - var ptNumsSet = ptNums.length > 0; - - // When pointsNumbers is set (e.g. histogram's binning), - // it is assumed that when the first point of - // a bin is selected, all others are as well - var ptNumToTest = ptNumsSet ? ptNums[0] : ptNum; - - // TODO potential performance improvement - // Primarily we need this function to determine if a click adds - // or subtracts from a selection. - // In cases `trace.selectedpoints` is a huge array, indexOf - // might be slow. One remedy would be to introduce a hash somewhere. - return trace.selectedpoints ? trace.selectedpoints.indexOf(ptNumToTest) > -1 : false; -} - -function isOnlyThisBinSelected(searchTraces, clickedPtInfo) { - var tracesWithSelectedPts = []; - var searchInfo, trace, isSameTrace, i; - - for(i = 0; i < searchTraces.length; i++) { - searchInfo = searchTraces[i]; - if(searchInfo.cd[0].trace.selectedpoints && searchInfo.cd[0].trace.selectedpoints.length > 0) { - tracesWithSelectedPts.push(searchInfo); - } - } - - if(tracesWithSelectedPts.length === 1) { - isSameTrace = tracesWithSelectedPts[0] === clickedPtInfo.searchInfo; - if(isSameTrace) { - trace = clickedPtInfo.searchInfo.cd[0].trace; - if(trace.selectedpoints.length === clickedPtInfo.pointNumbers.length) { - for(i = 0; i < clickedPtInfo.pointNumbers.length; i++) { - if(trace.selectedpoints.indexOf(clickedPtInfo.pointNumbers[i]) < 0) { - return false; - } - } - return true; - } - } - } - - return false; -} - -function isOnlyOnePointSelected(searchTraces) { - var len = 0; - var searchInfo, trace, i; - - for(i = 0; i < searchTraces.length; i++) { - searchInfo = searchTraces[i]; - trace = searchInfo.cd[0].trace; - if(trace.selectedpoints) { - if(trace.selectedpoints.length > 1) return false; - - len += trace.selectedpoints.length; - if(len > 1) return false; - } - } - - return len === 1; -} - -function updateSelectedState(gd, searchTraces, eventData) { - var i, searchInfo, cd, trace; - - // before anything else, update preGUI if necessary - for(i = 0; i < searchTraces.length; i++) { - var fullInputTrace = searchTraces[i].cd[0].trace._fullInput; - var tracePreGUI = gd._fullLayout._tracePreGUI[fullInputTrace.uid] || {}; - if(tracePreGUI.selectedpoints === undefined) { - tracePreGUI.selectedpoints = fullInputTrace._input.selectedpoints || null; - } - } - - if(eventData) { - var pts = eventData.points || []; - - for(i = 0; i < searchTraces.length; i++) { - trace = searchTraces[i].cd[0].trace; - trace._input.selectedpoints = trace._fullInput.selectedpoints = []; - if(trace._fullInput !== trace) trace.selectedpoints = []; - } - - for(i = 0; i < pts.length; i++) { - var pt = pts[i]; - var data = pt.data; - var fullData = pt.fullData; - - if(pt.pointIndices) { - [].push.apply(data.selectedpoints, pt.pointIndices); - if(trace._fullInput !== trace) { - [].push.apply(fullData.selectedpoints, pt.pointIndices); - } - } else { - data.selectedpoints.push(pt.pointIndex); - if(trace._fullInput !== trace) { - fullData.selectedpoints.push(pt.pointIndex); - } - } - } - } else { - for(i = 0; i < searchTraces.length; i++) { - trace = searchTraces[i].cd[0].trace; - delete trace.selectedpoints; - delete trace._input.selectedpoints; - if(trace._fullInput !== trace) { - delete trace._fullInput.selectedpoints; - } - } - } - - var hasRegl = false; - - for(i = 0; i < searchTraces.length; i++) { - searchInfo = searchTraces[i]; - cd = searchInfo.cd; - trace = cd[0].trace; - - if(Registry.traceIs(trace, 'regl')) { - hasRegl = true; - } - - var _module = searchInfo._module; - var fn = _module.styleOnSelect || _module.style; - if(fn) { - fn(gd, cd, cd[0].node3); - if(cd[0].nodeRangePlot3) fn(gd, cd, cd[0].nodeRangePlot3); - } - } - - if(hasRegl) { - clearGlCanvases(gd); - redrawReglTraces(gd); - } -} - -function mergePolygons(list, poly, subtract) { - var res; - - if(subtract) { - res = polybool.difference({ - regions: list, - inverted: false - }, { - regions: [poly], - inverted: false - }); - - return res.regions; - } - - res = polybool.union({ - regions: list, - inverted: false - }, { - regions: [poly], - inverted: false - }); - - return res.regions; -} - -function fillSelectionItem(selection, searchInfo) { - if(Array.isArray(selection)) { - var cd = searchInfo.cd; - var trace = searchInfo.cd[0].trace; - - for(var i = 0; i < selection.length; i++) { - selection[i] = makeEventData(selection[i], trace, cd); - } - } - - return selection; -} - -// until we get around to persistent selections, remove the outline -// here. The selection itself will be removed when the plot redraws -// at the end. -function clearSelect(gd) { - var fullLayout = gd._fullLayout || {}; - var zoomlayer = fullLayout._zoomlayer; - if(zoomlayer) { - zoomlayer.selectAll('.select-outline').remove(); - } -} - -module.exports = { - prepSelect: prepSelect, - clearSelect: clearSelect, - selectOnClick: selectOnClick -}; - -},{"../../components/color":593,"../../components/fx":632,"../../components/fx/helpers":628,"../../lib":719,"../../lib/clear_gl_canvases":704,"../../lib/polygon":731,"../../lib/throttle":744,"../../plot_api/subroutines":758,"../../registry":847,"./axis_ids":770,"./constants":773,"polybooljs":473}],785:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var cleanNumber = Lib.cleanNumber; -var ms2DateTime = Lib.ms2DateTime; -var dateTime2ms = Lib.dateTime2ms; -var ensureNumber = Lib.ensureNumber; -var isArrayOrTypedArray = Lib.isArrayOrTypedArray; - -var numConstants = _dereq_('../../constants/numerical'); -var FP_SAFE = numConstants.FP_SAFE; -var BADNUM = numConstants.BADNUM; -var LOG_CLIP = numConstants.LOG_CLIP; - -var constants = _dereq_('./constants'); -var axisIds = _dereq_('./axis_ids'); - -function fromLog(v) { - return Math.pow(10, v); -} - -function isValidCategory(v) { - return v !== null && v !== undefined; -} - -/** - * Define the conversion functions for an axis data is used in 5 ways: - * - * d: data, in whatever form it's provided - * c: calcdata: turned into numbers, but not linearized - * l: linearized - same as c except for log axes (and other nonlinear - * mappings later?) this is used when we need to know if it's - * *possible* to show some data on this axis, without caring about - * the current range - * p: pixel value - mapped to the screen with current size and zoom - * r: ranges, tick0, and annotation positions match one of the above - * but are handled differently for different types: - * - linear and date: data format (d) - * - category: calcdata format (c), and will stay that way because - * the data format has no continuous mapping - * - log: linearized (l) format - * TODO: in v2.0 we plan to change it to data format. At that point - * shapes will work the same way as ranges, tick0, and annotations - * so they can use this conversion too. - * - * Creates/updates these conversion functions, and a few more utilities - * like cleanRange, and makeCalcdata - * - * also clears the autotick constraints ._minDtick, ._forceTick0 - */ -module.exports = function setConvert(ax, fullLayout) { - fullLayout = fullLayout || {}; - - var axId = (ax._id || 'x'); - var axLetter = axId.charAt(0); - - function toLog(v, clip) { - if(v > 0) return Math.log(v) / Math.LN10; - - else if(v <= 0 && clip && ax.range && ax.range.length === 2) { - // clip NaN (ie past negative infinity) to LOG_CLIP axis - // length past the negative edge - var r0 = ax.range[0]; - var r1 = ax.range[1]; - return 0.5 * (r0 + r1 - 2 * LOG_CLIP * Math.abs(r0 - r1)); - } else return BADNUM; - } - - /* - * wrapped dateTime2ms that: - * - accepts ms numbers for backward compatibility - * - inserts a dummy arg so calendar is the 3rd arg (see notes below). - * - defaults to ax.calendar - */ - function dt2ms(v, _, calendar) { - // NOTE: Changed this behavior: previously we took any numeric value - // to be a ms, even if it was a string that could be a bare year. - // Now we convert it as a date if at all possible, and only try - // as (local) ms if that fails. - var ms = dateTime2ms(v, calendar || ax.calendar); - if(ms === BADNUM) { - if(isNumeric(v)) { - v = +v; - // keep track of tenths of ms, that `new Date` will drop - // same logic as in Lib.ms2DateTime - var msecTenths = Math.floor(Lib.mod(v + 0.05, 1) * 10); - var msRounded = Math.round(v - msecTenths / 10); - ms = dateTime2ms(new Date(msRounded)) + msecTenths / 10; - } else return BADNUM; - } - return ms; - } - - // wrapped ms2DateTime to insert default ax.calendar - function ms2dt(v, r, calendar) { - return ms2DateTime(v, r, calendar || ax.calendar); - } - - function getCategoryName(v) { - return ax._categories[Math.round(v)]; - } - - /* - * setCategoryIndex: return the index of category v, - * inserting it in the list if it's not already there - * - * this will enter the categories in the order it - * encounters them, ie all the categories from the - * first data set, then all the ones from the second - * that aren't in the first etc. - * - * it is assumed that this function is being invoked in the - * already sorted category order; otherwise there would be - * a disconnect between the array and the index returned - */ - function setCategoryIndex(v) { - if(isValidCategory(v)) { - if(ax._categoriesMap === undefined) { - ax._categoriesMap = {}; - } - - if(ax._categoriesMap[v] !== undefined) { - return ax._categoriesMap[v]; - } else { - ax._categories.push(typeof v === 'number' ? String(v) : v); - - var curLength = ax._categories.length - 1; - ax._categoriesMap[v] = curLength; - - return curLength; - } - } - return BADNUM; - } - - function setMultiCategoryIndex(arrayIn, len) { - var arrayOut = new Array(len); - - for(var i = 0; i < len; i++) { - var v0 = (arrayIn[0] || [])[i]; - var v1 = (arrayIn[1] || [])[i]; - arrayOut[i] = getCategoryIndex([v0, v1]); - } - - return arrayOut; - } - - function getCategoryIndex(v) { - if(ax._categoriesMap) { - return ax._categoriesMap[v]; - } - } - - function getCategoryPosition(v) { - // d2l/d2c variant that that won't add categories but will also - // allow numbers to be mapped to the linearized axis positions - var index = getCategoryIndex(v); - if(index !== undefined) return index; - if(isNumeric(v)) return +v; - } - - function l2p(v) { - if(!isNumeric(v)) return BADNUM; - - // include 2 fractional digits on pixel, for PDF zooming etc - return d3.round(ax._b + ax._m * v, 2); - } - - function p2l(px) { return (px - ax._b) / ax._m; } - - // conversions among c/l/p are fairly simple - do them together for all axis types - ax.c2l = (ax.type === 'log') ? toLog : ensureNumber; - ax.l2c = (ax.type === 'log') ? fromLog : ensureNumber; - - ax.l2p = l2p; - ax.p2l = p2l; - - ax.c2p = (ax.type === 'log') ? function(v, clip) { return l2p(toLog(v, clip)); } : l2p; - ax.p2c = (ax.type === 'log') ? function(px) { return fromLog(p2l(px)); } : p2l; - - /* - * now type-specific conversions for **ALL** other combinations - * they're all written out, instead of being combinations of each other, for - * both clarity and speed. - */ - if(['linear', '-'].indexOf(ax.type) !== -1) { - // all are data vals, but d and r need cleaning - ax.d2r = ax.r2d = ax.d2c = ax.r2c = ax.d2l = ax.r2l = cleanNumber; - ax.c2d = ax.c2r = ax.l2d = ax.l2r = ensureNumber; - - ax.d2p = ax.r2p = function(v) { return ax.l2p(cleanNumber(v)); }; - ax.p2d = ax.p2r = p2l; - - ax.cleanPos = ensureNumber; - } else if(ax.type === 'log') { - // d and c are data vals, r and l are logged (but d and r need cleaning) - ax.d2r = ax.d2l = function(v, clip) { return toLog(cleanNumber(v), clip); }; - ax.r2d = ax.r2c = function(v) { return fromLog(cleanNumber(v)); }; - - ax.d2c = ax.r2l = cleanNumber; - ax.c2d = ax.l2r = ensureNumber; - - ax.c2r = toLog; - ax.l2d = fromLog; - - ax.d2p = function(v, clip) { return ax.l2p(ax.d2r(v, clip)); }; - ax.p2d = function(px) { return fromLog(p2l(px)); }; - - ax.r2p = function(v) { return ax.l2p(cleanNumber(v)); }; - ax.p2r = p2l; - - ax.cleanPos = ensureNumber; - } else if(ax.type === 'date') { - // r and d are date strings, l and c are ms - - /* - * Any of these functions with r and d on either side, calendar is the - * **3rd** argument. log has reserved the second argument. - * - * Unless you need the special behavior of the second arg (ms2DateTime - * uses this to limit precision, toLog uses true to clip negatives - * to offscreen low rather than undefined), it's safe to pass 0. - */ - ax.d2r = ax.r2d = Lib.identity; - - ax.d2c = ax.r2c = ax.d2l = ax.r2l = dt2ms; - ax.c2d = ax.c2r = ax.l2d = ax.l2r = ms2dt; - - ax.d2p = ax.r2p = function(v, _, calendar) { return ax.l2p(dt2ms(v, 0, calendar)); }; - ax.p2d = ax.p2r = function(px, r, calendar) { return ms2dt(p2l(px), r, calendar); }; - - ax.cleanPos = function(v) { return Lib.cleanDate(v, BADNUM, ax.calendar); }; - } else if(ax.type === 'category') { - // d is categories (string) - // c and l are indices (numbers) - // r is categories or numbers - - ax.d2c = ax.d2l = setCategoryIndex; - ax.r2d = ax.c2d = ax.l2d = getCategoryName; - - ax.d2r = ax.d2l_noadd = getCategoryPosition; - - ax.r2c = function(v) { - var index = getCategoryPosition(v); - return index !== undefined ? index : ax.fraction2r(0.5); - }; - - ax.l2r = ax.c2r = ensureNumber; - ax.r2l = getCategoryPosition; - - ax.d2p = function(v) { return ax.l2p(ax.r2c(v)); }; - ax.p2d = function(px) { return getCategoryName(p2l(px)); }; - ax.r2p = ax.d2p; - ax.p2r = p2l; - - ax.cleanPos = function(v) { - if(typeof v === 'string' && v !== '') return v; - return ensureNumber(v); - }; - } else if(ax.type === 'multicategory') { - // N.B. multicategory axes don't define d2c and d2l, - // as 'data-to-calcdata' conversion needs to take into - // account all data array items as in ax.makeCalcdata. - - ax.r2d = ax.c2d = ax.l2d = getCategoryName; - ax.d2r = ax.d2l_noadd = getCategoryPosition; - - ax.r2c = function(v) { - var index = getCategoryPosition(v); - return index !== undefined ? index : ax.fraction2r(0.5); - }; - - ax.r2c_just_indices = getCategoryIndex; - - ax.l2r = ax.c2r = ensureNumber; - ax.r2l = getCategoryPosition; - - ax.d2p = function(v) { return ax.l2p(ax.r2c(v)); }; - ax.p2d = function(px) { return getCategoryName(p2l(px)); }; - ax.r2p = ax.d2p; - ax.p2r = p2l; - - ax.cleanPos = function(v) { - if(Array.isArray(v) || (typeof v === 'string' && v !== '')) return v; - return ensureNumber(v); - }; - - ax.setupMultiCategory = function(fullData) { - var traceIndices = ax._traceIndices; - var i, j; - - var matchGroups = fullLayout._axisMatchGroups; - if(matchGroups && matchGroups.length && ax._categories.length === 0) { - for(i = 0; i < matchGroups.length; i++) { - var group = matchGroups[i]; - if(group[axId]) { - for(var axId2 in group) { - if(axId2 !== axId) { - var ax2 = fullLayout[axisIds.id2name(axId2)]; - traceIndices = traceIndices.concat(ax2._traceIndices); - } - } - } - } - } - - // [ [cnt, {$cat: index}], for 1,2 ] - var seen = [[0, {}], [0, {}]]; - // [ [arrayIn[0][i], arrayIn[1][i]], for i .. N ] - var list = []; - - for(i = 0; i < traceIndices.length; i++) { - var trace = fullData[traceIndices[i]]; - - if(axLetter in trace) { - var arrayIn = trace[axLetter]; - var len = trace._length || Lib.minRowLength(arrayIn); - - if(isArrayOrTypedArray(arrayIn[0]) && isArrayOrTypedArray(arrayIn[1])) { - for(j = 0; j < len; j++) { - var v0 = arrayIn[0][j]; - var v1 = arrayIn[1][j]; - - if(isValidCategory(v0) && isValidCategory(v1)) { - list.push([v0, v1]); - - if(!(v0 in seen[0][1])) { - seen[0][1][v0] = seen[0][0]++; - } - if(!(v1 in seen[1][1])) { - seen[1][1][v1] = seen[1][0]++; - } - } - } - } - } - } - - list.sort(function(a, b) { - var ind0 = seen[0][1]; - var d = ind0[a[0]] - ind0[b[0]]; - if(d) return d; - - var ind1 = seen[1][1]; - return ind1[a[1]] - ind1[b[1]]; - }); - - for(i = 0; i < list.length; i++) { - setCategoryIndex(list[i]); - } - }; - } - - // find the range value at the specified (linear) fraction of the axis - ax.fraction2r = function(v) { - var rl0 = ax.r2l(ax.range[0]); - var rl1 = ax.r2l(ax.range[1]); - return ax.l2r(rl0 + v * (rl1 - rl0)); - }; - - // find the fraction of the range at the specified range value - ax.r2fraction = function(v) { - var rl0 = ax.r2l(ax.range[0]); - var rl1 = ax.r2l(ax.range[1]); - return (ax.r2l(v) - rl0) / (rl1 - rl0); - }; - - /* - * cleanRange: make sure range is a couplet of valid & distinct values - * keep numbers away from the limits of floating point numbers, - * and dates away from the ends of our date system (+/- 9999 years) - * - * optional param rangeAttr: operate on a different attribute, like - * ax._r, rather than ax.range - */ - ax.cleanRange = function(rangeAttr, opts) { - if(!opts) opts = {}; - if(!rangeAttr) rangeAttr = 'range'; - - var range = Lib.nestedProperty(ax, rangeAttr).get(); - var i, dflt; - - if(ax.type === 'date') dflt = Lib.dfltRange(ax.calendar); - else if(axLetter === 'y') dflt = constants.DFLTRANGEY; - else dflt = opts.dfltRange || constants.DFLTRANGEX; - - // make sure we don't later mutate the defaults - dflt = dflt.slice(); - - if(!range || range.length !== 2) { - Lib.nestedProperty(ax, rangeAttr).set(dflt); - return; - } - - if(ax.type === 'date' && !ax.autorange) { - // check if milliseconds or js date objects are provided for range - // and convert to date strings - range[0] = Lib.cleanDate(range[0], BADNUM, ax.calendar); - range[1] = Lib.cleanDate(range[1], BADNUM, ax.calendar); - } - - for(i = 0; i < 2; i++) { - if(ax.type === 'date') { - if(!Lib.isDateTime(range[i], ax.calendar)) { - ax[rangeAttr] = dflt; - break; - } - - if(ax.r2l(range[0]) === ax.r2l(range[1])) { - // split by +/- 1 second - var linCenter = Lib.constrain(ax.r2l(range[0]), - Lib.MIN_MS + 1000, Lib.MAX_MS - 1000); - range[0] = ax.l2r(linCenter - 1000); - range[1] = ax.l2r(linCenter + 1000); - break; - } - } else { - if(!isNumeric(range[i])) { - if(isNumeric(range[1 - i])) { - range[i] = range[1 - i] * (i ? 10 : 0.1); - } else { - ax[rangeAttr] = dflt; - break; - } - } - - if(range[i] < -FP_SAFE) range[i] = -FP_SAFE; - else if(range[i] > FP_SAFE) range[i] = FP_SAFE; - - if(range[0] === range[1]) { - // somewhat arbitrary: split by 1 or 1ppm, whichever is bigger - var inc = Math.max(1, Math.abs(range[0] * 1e-6)); - range[0] -= inc; - range[1] += inc; - } - } - } - }; - - // set scaling to pixels - ax.setScale = function(usePrivateRange) { - var gs = fullLayout._size; - - // make sure we have a domain (pull it in from the axis - // this one is overlaying if necessary) - if(ax.overlaying) { - var ax2 = axisIds.getFromId({ _fullLayout: fullLayout }, ax.overlaying); - ax.domain = ax2.domain; - } - - // While transitions are occuring, occurring, we get a double-transform - // issue if we transform the drawn layer *and* use the new axis range to - // draw the data. This allows us to construct setConvert using the pre- - // interaction values of the range: - var rangeAttr = (usePrivateRange && ax._r) ? '_r' : 'range'; - var calendar = ax.calendar; - ax.cleanRange(rangeAttr); - - var rl0 = ax.r2l(ax[rangeAttr][0], calendar); - var rl1 = ax.r2l(ax[rangeAttr][1], calendar); - - if(axLetter === 'y') { - ax._offset = gs.t + (1 - ax.domain[1]) * gs.h; - ax._length = gs.h * (ax.domain[1] - ax.domain[0]); - ax._m = ax._length / (rl0 - rl1); - ax._b = -ax._m * rl1; - } else { - ax._offset = gs.l + ax.domain[0] * gs.w; - ax._length = gs.w * (ax.domain[1] - ax.domain[0]); - ax._m = ax._length / (rl1 - rl0); - ax._b = -ax._m * rl0; - } - - if(!isFinite(ax._m) || !isFinite(ax._b) || ax._length < 0) { - fullLayout._replotting = false; - throw new Error('Something went wrong with axis scaling'); - } - }; - - // makeCalcdata: takes an x or y array and converts it - // to a position on the axis object "ax" - // inputs: - // trace - a data object from gd.data - // axLetter - a string, either 'x' or 'y', for which item - // to convert (TODO: is this now always the same as - // the first letter of ax._id?) - // in case the expected data isn't there, make a list of - // integers based on the opposite data - ax.makeCalcdata = function(trace, axLetter) { - var arrayIn, arrayOut, i, len; - - var axType = ax.type; - var cal = axType === 'date' && trace[axLetter + 'calendar']; - - if(axLetter in trace) { - arrayIn = trace[axLetter]; - len = trace._length || Lib.minRowLength(arrayIn); - - if(Lib.isTypedArray(arrayIn) && (axType === 'linear' || axType === 'log')) { - if(len === arrayIn.length) { - return arrayIn; - } else if(arrayIn.subarray) { - return arrayIn.subarray(0, len); - } - } - - if(axType === 'multicategory') { - return setMultiCategoryIndex(arrayIn, len); - } - - arrayOut = new Array(len); - for(i = 0; i < len; i++) { - arrayOut[i] = ax.d2c(arrayIn[i], 0, cal); - } - } else { - var v0 = ((axLetter + '0') in trace) ? ax.d2c(trace[axLetter + '0'], 0, cal) : 0; - var dv = (trace['d' + axLetter]) ? Number(trace['d' + axLetter]) : 1; - - // the opposing data, for size if we have x and dx etc - arrayIn = trace[{x: 'y', y: 'x'}[axLetter]]; - len = trace._length || arrayIn.length; - arrayOut = new Array(len); - - for(i = 0; i < len; i++) { - arrayOut[i] = v0 + i * dv; - } - } - - return arrayOut; - }; - - ax.isValidRange = function(range) { - return ( - Array.isArray(range) && - range.length === 2 && - isNumeric(ax.r2l(range[0])) && - isNumeric(ax.r2l(range[1])) - ); - }; - - ax.isPtWithinRange = function(d, calendar) { - var coord = ax.c2l(d[axLetter], null, calendar); - var r0 = ax.r2l(ax.range[0]); - var r1 = ax.r2l(ax.range[1]); - - if(r0 < r1) { - return r0 <= coord && coord <= r1; - } else { - // Reversed axis case. - return r1 <= coord && coord <= r0; - } - }; - - // should skip if not category nor multicategory - ax.clearCalc = function() { - var emptyCategories = function() { - ax._categories = []; - ax._categoriesMap = {}; - }; - - var matchGroups = fullLayout._axisMatchGroups; - - if(matchGroups && matchGroups.length) { - var found = false; - - for(var i = 0; i < matchGroups.length; i++) { - var group = matchGroups[i]; - - if(group[axId]) { - found = true; - var categories = null; - var categoriesMap = null; - - for(var axId2 in group) { - var ax2 = fullLayout[axisIds.id2name(axId2)]; - if(ax2._categories) { - categories = ax2._categories; - categoriesMap = ax2._categoriesMap; - break; - } - } - - if(categories && categoriesMap) { - ax._categories = categories; - ax._categoriesMap = categoriesMap; - } else { - emptyCategories(); - } - break; - } - } - if(!found) emptyCategories(); - } else { - emptyCategories(); - } - - if(ax._initialCategories) { - for(var j = 0; j < ax._initialCategories.length; j++) { - setCategoryIndex(ax._initialCategories[j]); - } - } - }; - - // sort the axis (and all the matching ones) by _initialCategories - // returns the indices of the traces affected by the reordering - ax.sortByInitialCategories = function() { - var affectedTraces = []; - var emptyCategories = function() { - ax._categories = []; - ax._categoriesMap = {}; - }; - - emptyCategories(); - - if(ax._initialCategories) { - for(var j = 0; j < ax._initialCategories.length; j++) { - setCategoryIndex(ax._initialCategories[j]); - } - } - - affectedTraces = affectedTraces.concat(ax._traceIndices); - - // Propagate to matching axes - var group = ax._matchGroup; - for(var axId2 in group) { - if(axId === axId2) continue; - var ax2 = fullLayout[axisIds.id2name(axId2)]; - ax2._categories = ax._categories; - ax2._categoriesMap = ax._categoriesMap; - affectedTraces = affectedTraces.concat(ax2._traceIndices); - } - return affectedTraces; - }; - - // Propagate localization into the axis so that - // methods in Axes can use it w/o having to pass fullLayout - // Default (non-d3) number formatting uses separators directly - // dates and d3-formatted numbers use the d3 locale - // Fall back on default format for dummy axes that don't care about formatting - var locale = fullLayout._d3locale; - if(ax.type === 'date') { - ax._dateFormat = locale ? locale.timeFormat.utc : d3.time.format.utc; - ax._extraFormat = fullLayout._extraFormat; - } - // occasionally we need _numFormat to pass through - // even though it won't be needed by this axis - ax._separators = fullLayout.separators; - ax._numFormat = locale ? locale.numberFormat : d3.format; - - // and for bar charts and box plots: reset forced minimum tick spacing - delete ax._minDtick; - delete ax._forceTick0; -}; - -},{"../../constants/numerical":695,"../../lib":719,"./axis_ids":770,"./constants":773,"d3":163,"fast-isnumeric":225}],786:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var layoutAttributes = _dereq_('./layout_attributes'); -var handleArrayContainerDefaults = _dereq_('../array_container_defaults'); - -module.exports = function handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options, config) { - if(!config || config.pass === 1) { - handlePrefixSuffix(containerIn, containerOut, coerce, axType, options); - } - - if(!config || config.pass === 2) { - handleOtherDefaults(containerIn, containerOut, coerce, axType, options); - } -}; - -function handlePrefixSuffix(containerIn, containerOut, coerce, axType, options) { - var showAttrDflt = getShowAttrDflt(containerIn); - - var tickPrefix = coerce('tickprefix'); - if(tickPrefix) coerce('showtickprefix', showAttrDflt); - - var tickSuffix = coerce('ticksuffix', options.tickSuffixDflt); - if(tickSuffix) coerce('showticksuffix', showAttrDflt); -} - -function handleOtherDefaults(containerIn, containerOut, coerce, axType, options) { - var showAttrDflt = getShowAttrDflt(containerIn); - - var tickPrefix = coerce('tickprefix'); - if(tickPrefix) coerce('showtickprefix', showAttrDflt); - - var tickSuffix = coerce('ticksuffix', options.tickSuffixDflt); - if(tickSuffix) coerce('showticksuffix', showAttrDflt); - - var showTickLabels = coerce('showticklabels'); - if(showTickLabels) { - var font = options.font || {}; - var contColor = containerOut.color; - // as with titlefont.color, inherit axis.color only if one was - // explicitly provided - var dfltFontColor = (contColor && contColor !== layoutAttributes.color.dflt) ? - contColor : font.color; - Lib.coerceFont(coerce, 'tickfont', { - family: font.family, - size: font.size, - color: dfltFontColor - }); - coerce('tickangle'); - - if(axType !== 'category') { - var tickFormat = coerce('tickformat'); - var tickformatStops = containerIn.tickformatstops; - if(Array.isArray(tickformatStops) && tickformatStops.length) { - handleArrayContainerDefaults(containerIn, containerOut, { - name: 'tickformatstops', - inclusionAttr: 'enabled', - handleItemDefaults: tickformatstopDefaults - }); - } - if(!tickFormat && axType !== 'date') { - coerce('showexponent', showAttrDflt); - coerce('exponentformat'); - coerce('separatethousands'); - } - } - } -} - -/* - * Attributes 'showexponent', 'showtickprefix' and 'showticksuffix' - * share values. - * - * If only 1 attribute is set, - * the remaining attributes inherit that value. - * - * If 2 attributes are set to the same value, - * the remaining attribute inherits that value. - * - * If 2 attributes are set to different values, - * the remaining is set to its dflt value. - * - */ -function getShowAttrDflt(containerIn) { - var showAttrsAll = ['showexponent', 'showtickprefix', 'showticksuffix']; - var showAttrs = showAttrsAll.filter(function(a) { - return containerIn[a] !== undefined; - }); - var sameVal = function(a) { - return containerIn[a] === containerIn[showAttrs[0]]; - }; - - if(showAttrs.every(sameVal) || showAttrs.length === 1) { - return containerIn[showAttrs[0]]; - } -} - -function tickformatstopDefaults(valueIn, valueOut) { - function coerce(attr, dflt) { - return Lib.coerce(valueIn, valueOut, layoutAttributes.tickformatstops, attr, dflt); - } - - var enabled = coerce('enabled'); - if(enabled) { - coerce('dtickrange'); - coerce('value'); - } -} - -},{"../../lib":719,"../array_container_defaults":763,"./layout_attributes":779}],787:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var layoutAttributes = _dereq_('./layout_attributes'); - - -/** - * options: inherits outerTicks from axes.handleAxisDefaults - */ -module.exports = function handleTickDefaults(containerIn, containerOut, coerce, options) { - var tickLen = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'ticklen'); - var tickWidth = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'tickwidth'); - var tickColor = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'tickcolor', containerOut.color); - var showTicks = coerce('ticks', (options.outerTicks || tickLen || tickWidth || tickColor) ? 'outside' : ''); - - if(!showTicks) { - delete containerOut.ticklen; - delete containerOut.tickwidth; - delete containerOut.tickcolor; - } -}; - -},{"../../lib":719,"./layout_attributes":779}],788:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var cleanTicks = _dereq_('./clean_ticks'); - -module.exports = function handleTickValueDefaults(containerIn, containerOut, coerce, axType) { - var tickmode; - - if(containerIn.tickmode === 'array' && - (axType === 'log' || axType === 'date')) { - tickmode = containerOut.tickmode = 'auto'; - } else { - var tickmodeDefault = Array.isArray(containerIn.tickvals) ? 'array' : - containerIn.dtick ? 'linear' : - 'auto'; - tickmode = coerce('tickmode', tickmodeDefault); - } - - if(tickmode === 'auto') coerce('nticks'); - else if(tickmode === 'linear') { - // dtick is usually a positive number, but there are some - // special strings available for log or date axes - // tick0 also has special logic - var dtick = containerOut.dtick = cleanTicks.dtick( - containerIn.dtick, axType); - containerOut.tick0 = cleanTicks.tick0( - containerIn.tick0, axType, containerOut.calendar, dtick); - } else if(axType !== 'multicategory') { - var tickvals = coerce('tickvals'); - if(tickvals === undefined) containerOut.tickmode = 'auto'; - else coerce('ticktext'); - } -}; - -},{"./clean_ticks":772}],789:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Registry = _dereq_('../../registry'); -var Drawing = _dereq_('../../components/drawing'); -var Axes = _dereq_('./axes'); - -/** - * transitionAxes - * - * transition axes from one set of ranges to another, using a svg - * transformations, similar to during panning. - * - * @param {DOM element | object} gd - * @param {array} edits : array of 'edits', each item with - * - plotinfo {object} subplot object - * - xr0 {array} initial x-range - * - xr1 {array} end x-range - * - yr0 {array} initial y-range - * - yr1 {array} end y-range - * @param {object} transitionOpts - * @param {function} makeOnCompleteCallback - */ -module.exports = function transitionAxes(gd, edits, transitionOpts, makeOnCompleteCallback) { - var fullLayout = gd._fullLayout; - - // special case for redraw:false Plotly.animate that relies on this - // to update axis-referenced layout components - if(edits.length === 0) { - Axes.redrawComponents(gd); - return; - } - - function unsetSubplotTransform(subplot) { - var xa = subplot.xaxis; - var ya = subplot.yaxis; - - fullLayout._defs.select('#' + subplot.clipId + '> rect') - .call(Drawing.setTranslate, 0, 0) - .call(Drawing.setScale, 1, 1); - - subplot.plot - .call(Drawing.setTranslate, xa._offset, ya._offset) - .call(Drawing.setScale, 1, 1); - - var traceGroups = subplot.plot.selectAll('.scatterlayer .trace'); - - // This is specifically directed at scatter traces, applying an inverse - // scale to individual points to counteract the scale of the trace - // as a whole: - traceGroups.selectAll('.point') - .call(Drawing.setPointGroupScale, 1, 1); - traceGroups.selectAll('.textpoint') - .call(Drawing.setTextPointsScale, 1, 1); - traceGroups - .call(Drawing.hideOutsideRangePoints, subplot); - } - - function updateSubplot(edit, progress) { - var plotinfo = edit.plotinfo; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - var xr0 = edit.xr0; - var xr1 = edit.xr1; - var xlen = xa._length; - var yr0 = edit.yr0; - var yr1 = edit.yr1; - var ylen = ya._length; - - var editX = !!xr1; - var editY = !!yr1; - var viewBox = []; - - if(editX) { - var dx0 = xr0[1] - xr0[0]; - var dx1 = xr1[1] - xr1[0]; - viewBox[0] = (xr0[0] * (1 - progress) + progress * xr1[0] - xr0[0]) / (xr0[1] - xr0[0]) * xlen; - viewBox[2] = xlen * ((1 - progress) + progress * dx1 / dx0); - xa.range[0] = xr0[0] * (1 - progress) + progress * xr1[0]; - xa.range[1] = xr0[1] * (1 - progress) + progress * xr1[1]; - } else { - viewBox[0] = 0; - viewBox[2] = xlen; - } - - if(editY) { - var dy0 = yr0[1] - yr0[0]; - var dy1 = yr1[1] - yr1[0]; - viewBox[1] = (yr0[1] * (1 - progress) + progress * yr1[1] - yr0[1]) / (yr0[0] - yr0[1]) * ylen; - viewBox[3] = ylen * ((1 - progress) + progress * dy1 / dy0); - ya.range[0] = yr0[0] * (1 - progress) + progress * yr1[0]; - ya.range[1] = yr0[1] * (1 - progress) + progress * yr1[1]; - } else { - viewBox[1] = 0; - viewBox[3] = ylen; - } - - Axes.drawOne(gd, xa, {skipTitle: true}); - Axes.drawOne(gd, ya, {skipTitle: true}); - Axes.redrawComponents(gd, [xa._id, ya._id]); - - var xScaleFactor = editX ? xlen / viewBox[2] : 1; - var yScaleFactor = editY ? ylen / viewBox[3] : 1; - var clipDx = editX ? viewBox[0] : 0; - var clipDy = editY ? viewBox[1] : 0; - var fracDx = editX ? (viewBox[0] / viewBox[2] * xlen) : 0; - var fracDy = editY ? (viewBox[1] / viewBox[3] * ylen) : 0; - var plotDx = xa._offset - fracDx; - var plotDy = ya._offset - fracDy; - - plotinfo.clipRect - .call(Drawing.setTranslate, clipDx, clipDy) - .call(Drawing.setScale, 1 / xScaleFactor, 1 / yScaleFactor); - - plotinfo.plot - .call(Drawing.setTranslate, plotDx, plotDy) - .call(Drawing.setScale, xScaleFactor, yScaleFactor); - - // apply an inverse scale to individual points to counteract - // the scale of the trace group. - Drawing.setPointGroupScale(plotinfo.zoomScalePts, 1 / xScaleFactor, 1 / yScaleFactor); - Drawing.setTextPointsScale(plotinfo.zoomScaleTxt, 1 / xScaleFactor, 1 / yScaleFactor); - } - - var onComplete; - if(makeOnCompleteCallback) { - // This module makes the choice whether or not it notifies Plotly.transition - // about completion: - onComplete = makeOnCompleteCallback(); - } - - function transitionComplete() { - var aobj = {}; - - for(var i = 0; i < edits.length; i++) { - var edit = edits[i]; - if(edit.xr1) aobj[edit.plotinfo.xaxis._name + '.range'] = edit.xr1.slice(); - if(edit.yr1) aobj[edit.plotinfo.yaxis._name + '.range'] = edit.yr1.slice(); - } - - // Signal that this transition has completed: - onComplete && onComplete(); - - return Registry.call('relayout', gd, aobj).then(function() { - for(var i = 0; i < edits.length; i++) { - unsetSubplotTransform(edits[i].plotinfo); - } - }); - } - - function transitionInterrupt() { - var aobj = {}; - - for(var i = 0; i < edits.length; i++) { - var edit = edits[i]; - if(edit.xr0) aobj[edit.plotinfo.xaxis._name + '.range'] = edit.xr0.slice(); - if(edit.yr0) aobj[edit.plotinfo.yaxis._name + '.range'] = edit.yr0.slice(); - } - - return Registry.call('relayout', gd, aobj).then(function() { - for(var i = 0; i < edits.length; i++) { - unsetSubplotTransform(edits[i].plotinfo); - } - }); - } - - var t1, t2, raf; - var easeFn = d3.ease(transitionOpts.easing); - - gd._transitionData._interruptCallbacks.push(function() { - window.cancelAnimationFrame(raf); - raf = null; - return transitionInterrupt(); - }); - - function doFrame() { - t2 = Date.now(); - - var tInterp = Math.min(1, (t2 - t1) / transitionOpts.duration); - var progress = easeFn(tInterp); - - for(var i = 0; i < edits.length; i++) { - updateSubplot(edits[i], progress); - } - - if(t2 - t1 > transitionOpts.duration) { - transitionComplete(); - raf = window.cancelAnimationFrame(doFrame); - } else { - raf = window.requestAnimationFrame(doFrame); - } - } - - t1 = Date.now(); - raf = window.requestAnimationFrame(doFrame); - - return Promise.resolve(); -}; - -},{"../../components/drawing":614,"../../registry":847,"./axes":767,"d3":163}],790:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var traceIs = _dereq_('../../registry').traceIs; -var autoType = _dereq_('./axis_autotype'); - -/* - * data: the plot data to use in choosing auto type - * name: axis object name (ie 'xaxis') if one should be stored - */ -module.exports = function handleTypeDefaults(containerIn, containerOut, coerce, options) { - var axType = coerce('type', (options.splomStash || {}).type); - - if(axType === '-') { - setAutoType(containerOut, options.data); - - if(containerOut.type === '-') { - containerOut.type = 'linear'; - } else { - // copy autoType back to input axis - // note that if this object didn't exist - // in the input layout, we have to put it in - // this happens in the main supplyDefaults function - containerIn.type = containerOut.type; - } - } -}; - -function setAutoType(ax, data) { - // new logic: let people specify any type they want, - // only autotype if type is '-' - if(ax.type !== '-') return; - - var id = ax._id; - var axLetter = id.charAt(0); - - // support 3d - if(id.indexOf('scene') !== -1) id = axLetter; - - var d0 = getFirstNonEmptyTrace(data, id, axLetter); - if(!d0) return; - - // first check for histograms, as the count direction - // should always default to a linear axis - if(d0.type === 'histogram' && - axLetter === {v: 'y', h: 'x'}[d0.orientation || 'v']) { - ax.type = 'linear'; - return; - } - - var calAttr = axLetter + 'calendar'; - var calendar = d0[calAttr]; - var opts = {noMultiCategory: !traceIs(d0, 'cartesian') || traceIs(d0, 'noMultiCategory')}; - var i; - - // check all boxes on this x axis to see - // if they're dates, numbers, or categories - if(isBoxWithoutPositionCoords(d0, axLetter)) { - var posLetter = getBoxPosLetter(d0); - var boxPositions = []; - - for(i = 0; i < data.length; i++) { - var trace = data[i]; - if(!traceIs(trace, 'box-violin') || (trace[axLetter + 'axis'] || axLetter) !== id) continue; - - if(trace[posLetter] !== undefined) boxPositions.push(trace[posLetter][0]); - else if(trace.name !== undefined) boxPositions.push(trace.name); - else boxPositions.push('text'); - - if(trace[calAttr] !== calendar) calendar = undefined; - } - - ax.type = autoType(boxPositions, calendar, opts); - } else if(d0.type === 'splom') { - var dimensions = d0.dimensions; - var dim = dimensions[d0._axesDim[id]]; - if(dim.visible) ax.type = autoType(dim.values, calendar, opts); - } else { - ax.type = autoType(d0[axLetter] || [d0[axLetter + '0']], calendar, opts); - } -} - -function getFirstNonEmptyTrace(data, id, axLetter) { - for(var i = 0; i < data.length; i++) { - var trace = data[i]; - - if(trace.type === 'splom' && - trace._length > 0 && - (trace['_' + axLetter + 'axes'] || {})[id] - ) { - return trace; - } - - if((trace[axLetter + 'axis'] || axLetter) === id) { - if(isBoxWithoutPositionCoords(trace, axLetter)) { - return trace; - } else if((trace[axLetter] || []).length || trace[axLetter + '0']) { - return trace; - } - } - } -} - -function getBoxPosLetter(trace) { - return {v: 'x', h: 'y'}[trace.orientation || 'v']; -} - -function isBoxWithoutPositionCoords(trace, axLetter) { - var posLetter = getBoxPosLetter(trace); - var isBox = traceIs(trace, 'box-violin'); - var isCandlestick = traceIs(trace._fullInput || {}, 'candlestick'); - - return ( - isBox && - !isCandlestick && - axLetter === posLetter && - trace[posLetter] === undefined && - trace[posLetter + '0'] === undefined - ); -} - -},{"../../registry":847,"./axis_autotype":768}],791:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../registry'); -var Lib = _dereq_('../lib'); - -/* - * Create or update an observer. This function is designed to be - * idempotent so that it can be called over and over as the component - * updates, and will attach and detach listeners as needed. - * - * @param {optional object} container - * An object on which the observer is stored. This is the mechanism - * by which it is idempotent. If it already exists, another won't be - * added. Each time it's called, the value lookup table is updated. - * @param {array} commandList - * An array of commands, following either `buttons` of `updatemenus` - * or `steps` of `sliders`. - * @param {function} onchange - * A listener called when the value is changed. Receives data object - * with information about the new state. - */ -exports.manageCommandObserver = function(gd, container, commandList, onchange) { - var ret = {}; - var enabled = true; - - if(container && container._commandObserver) { - ret = container._commandObserver; - } - - if(!ret.cache) { - ret.cache = {}; - } - - // Either create or just recompute this: - ret.lookupTable = {}; - - var binding = exports.hasSimpleAPICommandBindings(gd, commandList, ret.lookupTable); - - if(container && container._commandObserver) { - if(!binding) { - // If container exists and there are no longer any bindings, - // remove existing: - if(container._commandObserver.remove) { - container._commandObserver.remove(); - container._commandObserver = null; - return ret; - } - } else { - // If container exists and there *are* bindings, then the lookup - // table should have been updated and check is already attached, - // so there's nothing to be done: - return ret; - } - } - - // Determine whether there's anything to do for this binding: - - if(binding) { - // Build the cache: - bindingValueHasChanged(gd, binding, ret.cache); - - ret.check = function check() { - if(!enabled) return; - - var update = bindingValueHasChanged(gd, binding, ret.cache); - - if(update.changed && onchange) { - // Disable checks for the duration of this command in order to avoid - // infinite loops: - if(ret.lookupTable[update.value] !== undefined) { - ret.disable(); - Promise.resolve(onchange({ - value: update.value, - type: binding.type, - prop: binding.prop, - traces: binding.traces, - index: ret.lookupTable[update.value] - })).then(ret.enable, ret.enable); - } - } - - return update.changed; - }; - - var checkEvents = [ - 'plotly_relayout', - 'plotly_redraw', - 'plotly_restyle', - 'plotly_update', - 'plotly_animatingframe', - 'plotly_afterplot' - ]; - - for(var i = 0; i < checkEvents.length; i++) { - gd._internalOn(checkEvents[i], ret.check); - } - - ret.remove = function() { - for(var i = 0; i < checkEvents.length; i++) { - gd._removeInternalListener(checkEvents[i], ret.check); - } - }; - } else { - // TODO: It'd be really neat to actually give a *reason* for this, but at least a warning - // is a start - Lib.log('Unable to automatically bind plot updates to API command'); - - ret.lookupTable = {}; - ret.remove = function() {}; - } - - ret.disable = function disable() { - enabled = false; - }; - - ret.enable = function enable() { - enabled = true; - }; - - if(container) { - container._commandObserver = ret; - } - - return ret; -}; - -/* - * This function checks to see if an array of objects containing - * method and args properties is compatible with automatic two-way - * binding. The criteria right now are that - * - * 1. multiple traces may be affected - * 2. only one property may be affected - * 3. the same property must be affected by all commands - */ -exports.hasSimpleAPICommandBindings = function(gd, commandList, bindingsByValue) { - var i; - var n = commandList.length; - - var refBinding; - - for(i = 0; i < n; i++) { - var binding; - var command = commandList[i]; - var method = command.method; - var args = command.args; - - if(!Array.isArray(args)) args = []; - - // If any command has no method, refuse to bind: - if(!method) { - return false; - } - var bindings = exports.computeAPICommandBindings(gd, method, args); - - // Right now, handle one and *only* one property being set: - if(bindings.length !== 1) { - return false; - } - - if(!refBinding) { - refBinding = bindings[0]; - if(Array.isArray(refBinding.traces)) { - refBinding.traces.sort(); - } - } else { - binding = bindings[0]; - if(binding.type !== refBinding.type) { - return false; - } - if(binding.prop !== refBinding.prop) { - return false; - } - if(Array.isArray(refBinding.traces)) { - if(Array.isArray(binding.traces)) { - binding.traces.sort(); - for(var j = 0; j < refBinding.traces.length; j++) { - if(refBinding.traces[j] !== binding.traces[j]) { - return false; - } - } - } else { - return false; - } - } else { - if(binding.prop !== refBinding.prop) { - return false; - } - } - } - - binding = bindings[0]; - var value = binding.value; - if(Array.isArray(value)) { - if(value.length === 1) { - value = value[0]; - } else { - return false; - } - } - if(bindingsByValue) { - bindingsByValue[value] = i; - } - } - - return refBinding; -}; - -function bindingValueHasChanged(gd, binding, cache) { - var container, value, obj; - var changed = false; - - if(binding.type === 'data') { - // If it's data, we need to get a trace. Based on the limited scope - // of what we cover, we can just take the first trace from the list, - // or otherwise just the first trace: - container = gd._fullData[binding.traces !== null ? binding.traces[0] : 0]; - } else if(binding.type === 'layout') { - container = gd._fullLayout; - } else { - return false; - } - - value = Lib.nestedProperty(container, binding.prop).get(); - - obj = cache[binding.type] = cache[binding.type] || {}; - - if(obj.hasOwnProperty(binding.prop)) { - if(obj[binding.prop] !== value) { - changed = true; - } - } - - obj[binding.prop] = value; - - return { - changed: changed, - value: value - }; -} - -/* - * Execute an API command. There's really not much to this; it just provides - * a common hook so that implementations don't need to be synchronized across - * multiple components with the ability to invoke API commands. - * - * @param {string} method - * The name of the plotly command to execute. Must be one of 'animate', - * 'restyle', 'relayout', 'update'. - * @param {array} args - * A list of arguments passed to the API command - */ -exports.executeAPICommand = function(gd, method, args) { - if(method === 'skip') return Promise.resolve(); - - var _method = Registry.apiMethodRegistry[method]; - var allArgs = [gd]; - if(!Array.isArray(args)) args = []; - - for(var i = 0; i < args.length; i++) { - allArgs.push(args[i]); - } - - return _method.apply(null, allArgs).catch(function(err) { - Lib.warn('API call to Plotly.' + method + ' rejected.', err); - return Promise.reject(err); - }); -}; - -exports.computeAPICommandBindings = function(gd, method, args) { - var bindings; - - if(!Array.isArray(args)) args = []; - - switch(method) { - case 'restyle': - bindings = computeDataBindings(gd, args); - break; - case 'relayout': - bindings = computeLayoutBindings(gd, args); - break; - case 'update': - bindings = computeDataBindings(gd, [args[0], args[2]]) - .concat(computeLayoutBindings(gd, [args[1]])); - break; - case 'animate': - bindings = computeAnimateBindings(gd, args); - break; - default: - // This is the case where intelligent logic about what affects - // this command is not implemented. It causes no ill effects. - // For example, addFrames simply won't bind to a control component. - bindings = []; - } - return bindings; -}; - -function computeAnimateBindings(gd, args) { - // We'll assume that the only relevant modification an animation - // makes that's meaningfully tracked is the frame: - if(Array.isArray(args[0]) && args[0].length === 1 && ['string', 'number'].indexOf(typeof args[0][0]) !== -1) { - return [{type: 'layout', prop: '_currentFrame', value: args[0][0].toString()}]; - } else { - return []; - } -} - -function computeLayoutBindings(gd, args) { - var bindings = []; - - var astr = args[0]; - var aobj = {}; - if(typeof astr === 'string') { - aobj[astr] = args[1]; - } else if(Lib.isPlainObject(astr)) { - aobj = astr; - } else { - return bindings; - } - - crawl(aobj, function(path, attrName, attr) { - bindings.push({type: 'layout', prop: path, value: attr}); - }, '', 0); - - return bindings; -} - -function computeDataBindings(gd, args) { - var traces, astr, val, aobj; - var bindings = []; - - // Logic copied from Plotly.restyle: - astr = args[0]; - val = args[1]; - traces = args[2]; - aobj = {}; - if(typeof astr === 'string') { - aobj[astr] = val; - } else if(Lib.isPlainObject(astr)) { - // the 3-arg form - aobj = astr; - - if(traces === undefined) { - traces = val; - } - } else { - return bindings; - } - - if(traces === undefined) { - // Explicitly assign this to null instead of undefined: - traces = null; - } - - crawl(aobj, function(path, attrName, _attr) { - var thisTraces; - var attr; - - if(Array.isArray(_attr)) { - attr = _attr.slice(); - - var nAttr = Math.min(attr.length, gd.data.length); - if(traces) { - nAttr = Math.min(nAttr, traces.length); - } - thisTraces = []; - for(var j = 0; j < nAttr; j++) { - thisTraces[j] = traces ? traces[j] : j; - } - } else { - attr = _attr; - thisTraces = traces ? traces.slice() : null; - } - - // Convert [7] to just 7 when traces is null: - if(thisTraces === null) { - if(Array.isArray(attr)) { - attr = attr[0]; - } - } else if(Array.isArray(thisTraces)) { - if(!Array.isArray(attr)) { - var tmp = attr; - attr = []; - for(var i = 0; i < thisTraces.length; i++) { - attr[i] = tmp; - } - } - attr.length = Math.min(thisTraces.length, attr.length); - } - - bindings.push({ - type: 'data', - prop: path, - traces: thisTraces, - value: attr - }); - }, '', 0); - - return bindings; -} - -function crawl(attrs, callback, path, depth) { - Object.keys(attrs).forEach(function(attrName) { - var attr = attrs[attrName]; - - if(attrName[0] === '_') return; - - var thisPath = path + (depth > 0 ? '.' : '') + attrName; - - if(Lib.isPlainObject(attr)) { - crawl(attr, callback, thisPath, depth + 1); - } else { - // Only execute the callback on leaf nodes: - callback(thisPath, attrName, attr); - } - }); -} - -},{"../lib":719,"../registry":847}],792:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var extendFlat = _dereq_('../lib/extend').extendFlat; - -/** - * Make a xy domain attribute group - * - * @param {object} opts - * @param {string} - * opts.name: name to be inserted in the default description - * @param {boolean} - * opts.trace: set to true for trace containers - * @param {string} - * opts.editType: editType for all pieces - * @param {boolean} - * opts.noGridCell: set to true to omit `row` and `column` - * - * @param {object} extra - * @param {string} - * extra.description: extra description. N.B we use - * a separate extra container to make it compatible with - * the compress_attributes transform. - * - * @return {object} attributes object containing {x,y} as specified - */ -exports.attributes = function(opts, extra) { - opts = opts || {}; - extra = extra || {}; - - var base = { - valType: 'info_array', - - editType: opts.editType, - items: [ - {valType: 'number', min: 0, max: 1, editType: opts.editType}, - {valType: 'number', min: 0, max: 1, editType: opts.editType} - ], - dflt: [0, 1] - }; - - var namePart = opts.name ? opts.name + ' ' : ''; - var contPart = opts.trace ? 'trace ' : 'subplot '; - var descPart = extra.description ? ' ' + extra.description : ''; - - var out = { - x: extendFlat({}, base, { - - }), - y: extendFlat({}, base, { - - }), - editType: opts.editType - }; - - if(!opts.noGridCell) { - out.row = { - valType: 'integer', - min: 0, - dflt: 0, - - editType: opts.editType, - - }; - out.column = { - valType: 'integer', - min: 0, - dflt: 0, - - editType: opts.editType, - - }; - } - - return out; -}; - -exports.defaults = function(containerOut, layout, coerce, dfltDomains) { - var dfltX = (dfltDomains && dfltDomains.x) || [0, 1]; - var dfltY = (dfltDomains && dfltDomains.y) || [0, 1]; - - var grid = layout.grid; - if(grid) { - var column = coerce('domain.column'); - if(column !== undefined) { - if(column < grid.columns) dfltX = grid._domains.x[column]; - else delete containerOut.domain.column; - } - - var row = coerce('domain.row'); - if(row !== undefined) { - if(row < grid.rows) dfltY = grid._domains.y[row]; - else delete containerOut.domain.row; - } - } - - coerce('domain.x', dfltX); - coerce('domain.y', dfltY); -}; - -},{"../lib/extend":710}],793:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* - * make a font attribute group - * - * @param {object} opts - * @param {string} - * opts.description: where & how this font is used - * @param {optional bool} arrayOk: - * should each part (family, size, color) be arrayOk? default false. - * @param {string} editType: - * the editType for all pieces of this font - * @param {optional string} colorEditType: - * a separate editType just for color - * - * @return {object} attributes object containing {family, size, color} as specified - */ -module.exports = function(opts) { - var editType = opts.editType; - var colorEditType = opts.colorEditType; - if(colorEditType === undefined) colorEditType = editType; - var attrs = { - family: { - valType: 'string', - - noBlank: true, - strict: true, - editType: editType, - - }, - size: { - valType: 'number', - - min: 1, - editType: editType - }, - color: { - valType: 'color', - - editType: colorEditType - }, - editType: editType, - // blank strings so compress_attributes can remove - // TODO - that's uber hacky... better solution? - - }; - - if(opts.arrayOk) { - attrs.family.arrayOk = true; - attrs.size.arrayOk = true; - attrs.color.arrayOk = true; - } - - return attrs; -}; - -},{}],794:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - _isLinkedToArray: 'frames_entry', - - group: { - valType: 'string', - - - }, - name: { - valType: 'string', - - - }, - traces: { - valType: 'any', - - - }, - baseframe: { - valType: 'string', - - - }, - data: { - valType: 'any', - - - }, - layout: { - valType: 'any', - - - } -}; - -},{}],795:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -// projection names to d3 function name -exports.projNames = { - // d3.geo.projection - 'equirectangular': 'equirectangular', - 'mercator': 'mercator', - 'orthographic': 'orthographic', - 'natural earth': 'naturalEarth', - 'kavrayskiy7': 'kavrayskiy7', - 'miller': 'miller', - 'robinson': 'robinson', - 'eckert4': 'eckert4', - 'azimuthal equal area': 'azimuthalEqualArea', - 'azimuthal equidistant': 'azimuthalEquidistant', - 'conic equal area': 'conicEqualArea', - 'conic conformal': 'conicConformal', - 'conic equidistant': 'conicEquidistant', - 'gnomonic': 'gnomonic', - 'stereographic': 'stereographic', - 'mollweide': 'mollweide', - 'hammer': 'hammer', - 'transverse mercator': 'transverseMercator', - 'albers usa': 'albersUsa', - 'winkel tripel': 'winkel3', - 'aitoff': 'aitoff', - 'sinusoidal': 'sinusoidal' -}; - -// name of the axes -exports.axesNames = ['lonaxis', 'lataxis']; - -// max longitudinal angular span (EXPERIMENTAL) -exports.lonaxisSpan = { - 'orthographic': 180, - 'azimuthal equal area': 360, - 'azimuthal equidistant': 360, - 'conic conformal': 180, - 'gnomonic': 160, - 'stereographic': 180, - 'transverse mercator': 180, - '*': 360 -}; - -// max latitudinal angular span (EXPERIMENTAL) -exports.lataxisSpan = { - 'conic conformal': 150, - 'stereographic': 179.5, - '*': 180 -}; - -// defaults for each scope -exports.scopeDefaults = { - world: { - lonaxisRange: [-180, 180], - lataxisRange: [-90, 90], - projType: 'equirectangular', - projRotate: [0, 0, 0] - }, - usa: { - lonaxisRange: [-180, -50], - lataxisRange: [15, 80], - projType: 'albers usa' - }, - europe: { - lonaxisRange: [-30, 60], - lataxisRange: [30, 85], - projType: 'conic conformal', - projRotate: [15, 0, 0], - projParallels: [0, 60] - }, - asia: { - lonaxisRange: [22, 160], - lataxisRange: [-15, 55], - projType: 'mercator', - projRotate: [0, 0, 0] - }, - africa: { - lonaxisRange: [-30, 60], - lataxisRange: [-40, 40], - projType: 'mercator', - projRotate: [0, 0, 0] - }, - 'north america': { - lonaxisRange: [-180, -45], - lataxisRange: [5, 85], - projType: 'conic conformal', - projRotate: [-100, 0, 0], - projParallels: [29.5, 45.5] - }, - 'south america': { - lonaxisRange: [-100, -30], - lataxisRange: [-60, 15], - projType: 'mercator', - projRotate: [0, 0, 0] - } -}; - -// angular pad to avoid rounding error around clip angles -exports.clipPad = 1e-3; - -// map projection precision -exports.precision = 0.1; - -// default land and water fill colors -exports.landColor = '#F0DC82'; -exports.waterColor = '#3399FF'; - -// locationmode to layer name -exports.locationmodeToLayer = { - 'ISO-3': 'countries', - 'USA-states': 'subunits', - 'country names': 'countries' -}; - -// SVG element for a sphere (use to frame maps) -exports.sphereSVG = {type: 'Sphere'}; - -// N.B. base layer names must be the same as in the topojson files - -// base layer with a fill color -exports.fillLayers = { - ocean: 1, - land: 1, - lakes: 1 -}; - -// base layer with a only a line color -exports.lineLayers = { - subunits: 1, - countries: 1, - coastlines: 1, - rivers: 1, - frame: 1 -}; - -exports.layers = [ - 'bg', - 'ocean', 'land', 'lakes', - 'subunits', 'countries', 'coastlines', 'rivers', - 'lataxis', 'lonaxis', 'frame', - 'backplot', - 'frontplot' -]; - -exports.layersForChoropleth = [ - 'bg', - 'ocean', 'land', - 'subunits', 'countries', 'coastlines', - 'lataxis', 'lonaxis', 'frame', - 'backplot', - 'rivers', 'lakes', - 'frontplot' -]; - -exports.layerNameToAdjective = { - ocean: 'ocean', - land: 'land', - lakes: 'lake', - subunits: 'subunit', - countries: 'country', - coastlines: 'coastline', - rivers: 'river', - frame: 'frame' -}; - -},{}],796:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* global PlotlyGeoAssets:false */ - -var d3 = _dereq_('d3'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var Fx = _dereq_('../../components/fx'); -var Plots = _dereq_('../plots'); -var Axes = _dereq_('../cartesian/axes'); -var dragElement = _dereq_('../../components/dragelement'); -var prepSelect = _dereq_('../cartesian/select').prepSelect; -var selectOnClick = _dereq_('../cartesian/select').selectOnClick; - -var createGeoZoom = _dereq_('./zoom'); -var constants = _dereq_('./constants'); - -var topojsonUtils = _dereq_('../../lib/topojson_utils'); -var topojsonFeature = _dereq_('topojson-client').feature; - -_dereq_('./projections')(d3); - -function Geo(opts) { - this.id = opts.id; - this.graphDiv = opts.graphDiv; - this.container = opts.container; - this.topojsonURL = opts.topojsonURL; - this.isStatic = opts.staticPlot; - - this.topojsonName = null; - this.topojson = null; - - this.projection = null; - this.scope = null; - this.viewInitial = null; - this.fitScale = null; - this.bounds = null; - this.midPt = null; - - this.hasChoropleth = false; - this.traceHash = {}; - - this.layers = {}; - this.basePaths = {}; - this.dataPaths = {}; - this.dataPoints = {}; - - this.clipDef = null; - this.clipRect = null; - this.bgRect = null; - - this.makeFramework(); -} - -var proto = Geo.prototype; - -module.exports = function createGeo(opts) { - return new Geo(opts); -}; - -proto.plot = function(geoCalcData, fullLayout, promises) { - var _this = this; - var geoLayout = fullLayout[this.id]; - - var needsTopojson = false; - for(var k in constants.layerNameToAdjective) { - if(k !== 'frame' && geoLayout['show' + k]) { - needsTopojson = true; - break; - } - } - for(var i = 0; i < geoCalcData.length; i++) { - if(geoCalcData[0][0].trace.locationmode) { - needsTopojson = true; - break; - } - } - if(!needsTopojson) { - return _this.update(geoCalcData, fullLayout); - } - - var topojsonNameNew = topojsonUtils.getTopojsonName(geoLayout); - - if(_this.topojson === null || topojsonNameNew !== _this.topojsonName) { - _this.topojsonName = topojsonNameNew; - - if(PlotlyGeoAssets.topojson[_this.topojsonName] === undefined) { - promises.push(_this.fetchTopojson().then(function(topojson) { - PlotlyGeoAssets.topojson[_this.topojsonName] = topojson; - _this.topojson = topojson; - _this.update(geoCalcData, fullLayout); - })); - } else { - _this.topojson = PlotlyGeoAssets.topojson[_this.topojsonName]; - _this.update(geoCalcData, fullLayout); - } - } else { - _this.update(geoCalcData, fullLayout); - } -}; - -proto.fetchTopojson = function() { - var topojsonPath = topojsonUtils.getTopojsonPath( - this.topojsonURL, - this.topojsonName - ); - return new Promise(function(resolve, reject) { - d3.json(topojsonPath, function(err, topojson) { - if(err) { - if(err.status === 404) { - return reject(new Error([ - 'plotly.js could not find topojson file at', - topojsonPath, '.', - 'Make sure the *topojsonURL* plot config option', - 'is set properly.' - ].join(' '))); - } else { - return reject(new Error([ - 'unexpected error while fetching topojson file at', - topojsonPath - ].join(' '))); - } - } - resolve(topojson); - }); - }); -}; - -proto.update = function(geoCalcData, fullLayout) { - var geoLayout = fullLayout[this.id]; - - var hasInvalidBounds = this.updateProjection(fullLayout, geoLayout); - if(hasInvalidBounds) return; - - // important: maps with choropleth traces have a different layer order - this.hasChoropleth = false; - for(var i = 0; i < geoCalcData.length; i++) { - if(geoCalcData[i][0].trace.type === 'choropleth') { - this.hasChoropleth = true; - break; - } - } - - if(!this.viewInitial || this.scope !== geoLayout.scope) { - this.saveViewInitial(geoLayout); - } - this.scope = geoLayout.scope; - - this.updateBaseLayers(fullLayout, geoLayout); - this.updateDims(fullLayout, geoLayout); - this.updateFx(fullLayout, geoLayout); - - Plots.generalUpdatePerTraceModule(this.graphDiv, this, geoCalcData, geoLayout); - - var scatterLayer = this.layers.frontplot.select('.scatterlayer'); - this.dataPoints.point = scatterLayer.selectAll('.point'); - this.dataPoints.text = scatterLayer.selectAll('text'); - this.dataPaths.line = scatterLayer.selectAll('.js-line'); - - var choroplethLayer = this.layers.backplot.select('.choroplethlayer'); - this.dataPaths.choropleth = choroplethLayer.selectAll('path'); - - this.render(); -}; - -proto.updateProjection = function(fullLayout, geoLayout) { - var gs = fullLayout._size; - var domain = geoLayout.domain; - var projLayout = geoLayout.projection; - var rotation = projLayout.rotation || {}; - var center = geoLayout.center || {}; - - var projection = this.projection = getProjection(geoLayout); - - // set 'pre-fit' projection - projection - .center([center.lon - rotation.lon, center.lat - rotation.lat]) - .rotate([-rotation.lon, -rotation.lat, rotation.roll]) - .parallels(projLayout.parallels); - - // setup subplot extent [[x0,y0], [x1,y1]] - var extent = [[ - gs.l + gs.w * domain.x[0], - gs.t + gs.h * (1 - domain.y[1]) - ], [ - gs.l + gs.w * domain.x[1], - gs.t + gs.h * (1 - domain.y[0]) - ]]; - - var lonaxis = geoLayout.lonaxis; - var lataxis = geoLayout.lataxis; - var rangeBox = makeRangeBox(lonaxis.range, lataxis.range); - - // fit projection 'scale' and 'translate' to set lon/lat ranges - projection.fitExtent(extent, rangeBox); - - var b = this.bounds = projection.getBounds(rangeBox); - var s = this.fitScale = projection.scale(); - var t = projection.translate(); - - if( - !isFinite(b[0][0]) || !isFinite(b[0][1]) || - !isFinite(b[1][0]) || !isFinite(b[1][1]) || - isNaN(t[0]) || isNaN(t[0]) - ) { - var gd = this.graphDiv; - var attrToUnset = ['projection.rotation', 'center', 'lonaxis.range', 'lataxis.range']; - var msg = 'Invalid geo settings, relayout\'ing to default view.'; - var updateObj = {}; - - // clear all attribute that could cause invalid bounds, - // clear viewInitial to update reset-view behavior - - for(var i = 0; i < attrToUnset.length; i++) { - updateObj[this.id + '.' + attrToUnset[i]] = null; - } - - this.viewInitial = null; - - Lib.warn(msg); - gd._promises.push(Registry.call('relayout', gd, updateObj)); - return msg; - } - - // px coordinates of view mid-point, - // useful to update `geo.center` after interactions - var midPt = this.midPt = [ - (b[0][0] + b[1][0]) / 2, - (b[0][1] + b[1][1]) / 2 - ]; - - // adjust projection to user setting - projection - .scale(projLayout.scale * s) - .translate([t[0] + (midPt[0] - t[0]), t[1] + (midPt[1] - t[1])]) - .clipExtent(b); - - // the 'albers usa' projection does not expose a 'center' method - // so here's this hack to make it respond to 'geoLayout.center' - if(geoLayout._isAlbersUsa) { - var centerPx = projection([center.lon, center.lat]); - var tt = projection.translate(); - - projection.translate([ - tt[0] - (centerPx[0] - tt[0]), - tt[1] - (centerPx[1] - tt[1]) - ]); - } -}; - -proto.updateBaseLayers = function(fullLayout, geoLayout) { - var _this = this; - var topojson = _this.topojson; - var layers = _this.layers; - var basePaths = _this.basePaths; - - function isAxisLayer(d) { - return (d === 'lonaxis' || d === 'lataxis'); - } - - function isLineLayer(d) { - return Boolean(constants.lineLayers[d]); - } - - function isFillLayer(d) { - return Boolean(constants.fillLayers[d]); - } - - var allLayers = this.hasChoropleth ? - constants.layersForChoropleth : - constants.layers; - - var layerData = allLayers.filter(function(d) { - return (isLineLayer(d) || isFillLayer(d)) ? geoLayout['show' + d] : - isAxisLayer(d) ? geoLayout[d].showgrid : - true; - }); - - var join = _this.framework.selectAll('.layer') - .data(layerData, String); - - join.exit().each(function(d) { - delete layers[d]; - delete basePaths[d]; - d3.select(this).remove(); - }); - - join.enter().append('g') - .attr('class', function(d) { return 'layer ' + d; }) - .each(function(d) { - var layer = layers[d] = d3.select(this); - - if(d === 'bg') { - _this.bgRect = layer.append('rect') - .style('pointer-events', 'all'); - } else if(isAxisLayer(d)) { - basePaths[d] = layer.append('path') - .style('fill', 'none'); - } else if(d === 'backplot') { - layer.append('g') - .classed('choroplethlayer', true); - } else if(d === 'frontplot') { - layer.append('g') - .classed('scatterlayer', true); - } else if(isLineLayer(d)) { - basePaths[d] = layer.append('path') - .style('fill', 'none') - .style('stroke-miterlimit', 2); - } else if(isFillLayer(d)) { - basePaths[d] = layer.append('path') - .style('stroke', 'none'); - } - }); - - join.order(); - - join.each(function(d) { - var path = basePaths[d]; - var adj = constants.layerNameToAdjective[d]; - - if(d === 'frame') { - path.datum(constants.sphereSVG); - } else if(isLineLayer(d) || isFillLayer(d)) { - path.datum(topojsonFeature(topojson, topojson.objects[d])); - } else if(isAxisLayer(d)) { - path.datum(makeGraticule(d, geoLayout, fullLayout)) - .call(Color.stroke, geoLayout[d].gridcolor) - .call(Drawing.dashLine, '', geoLayout[d].gridwidth); - } - - if(isLineLayer(d)) { - path.call(Color.stroke, geoLayout[adj + 'color']) - .call(Drawing.dashLine, '', geoLayout[adj + 'width']); - } else if(isFillLayer(d)) { - path.call(Color.fill, geoLayout[adj + 'color']); - } - }); -}; - -proto.updateDims = function(fullLayout, geoLayout) { - var b = this.bounds; - var hFrameWidth = (geoLayout.framewidth || 0) / 2; - - var l = b[0][0] - hFrameWidth; - var t = b[0][1] - hFrameWidth; - var w = b[1][0] - l + hFrameWidth; - var h = b[1][1] - t + hFrameWidth; - - Drawing.setRect(this.clipRect, l, t, w, h); - - this.bgRect - .call(Drawing.setRect, l, t, w, h) - .call(Color.fill, geoLayout.bgcolor); - - this.xaxis._offset = l; - this.xaxis._length = w; - - this.yaxis._offset = t; - this.yaxis._length = h; -}; - -proto.updateFx = function(fullLayout, geoLayout) { - var _this = this; - var gd = _this.graphDiv; - var bgRect = _this.bgRect; - var dragMode = fullLayout.dragmode; - var clickMode = fullLayout.clickmode; - - if(_this.isStatic) return; - - function zoomReset() { - var viewInitial = _this.viewInitial; - var updateObj = {}; - - for(var k in viewInitial) { - updateObj[_this.id + '.' + k] = viewInitial[k]; - } - - Registry.call('_guiRelayout', gd, updateObj); - gd.emit('plotly_doubleclick', null); - } - - function invert(lonlat) { - return _this.projection.invert([ - lonlat[0] + _this.xaxis._offset, - lonlat[1] + _this.yaxis._offset - ]); - } - - var fillRangeItems; - - if(dragMode === 'select') { - fillRangeItems = function(eventData, poly) { - var ranges = eventData.range = {}; - ranges[_this.id] = [ - invert([poly.xmin, poly.ymin]), - invert([poly.xmax, poly.ymax]) - ]; - }; - } else if(dragMode === 'lasso') { - fillRangeItems = function(eventData, poly, pts) { - var dataPts = eventData.lassoPoints = {}; - dataPts[_this.id] = pts.filtered.map(invert); - }; - } - - // Note: dragOptions is needed to be declared for all dragmodes because - // it's the object that holds persistent selection state. - var dragOptions = { - element: _this.bgRect.node(), - gd: gd, - plotinfo: { - id: _this.id, - xaxis: _this.xaxis, - yaxis: _this.yaxis, - fillRangeItems: fillRangeItems - }, - xaxes: [_this.xaxis], - yaxes: [_this.yaxis], - subplot: _this.id, - clickFn: function(numClicks) { - if(numClicks === 2) { - fullLayout._zoomlayer.selectAll('.select-outline').remove(); - } - } - }; - - if(dragMode === 'pan') { - bgRect.node().onmousedown = null; - bgRect.call(createGeoZoom(_this, geoLayout)); - bgRect.on('dblclick.zoom', zoomReset); - if(!gd._context._scrollZoom.geo) { - bgRect.on('wheel.zoom', null); - } - } else if(dragMode === 'select' || dragMode === 'lasso') { - bgRect.on('.zoom', null); - - dragOptions.prepFn = function(e, startX, startY) { - prepSelect(e, startX, startY, dragOptions, dragMode); - }; - - dragElement.init(dragOptions); - } - - bgRect.on('mousemove', function() { - var lonlat = _this.projection.invert(d3.mouse(this)); - - if(!lonlat || isNaN(lonlat[0]) || isNaN(lonlat[1])) { - return dragElement.unhover(gd, d3.event); - } - - _this.xaxis.p2c = function() { return lonlat[0]; }; - _this.yaxis.p2c = function() { return lonlat[1]; }; - - Fx.hover(gd, d3.event, _this.id); - }); - - bgRect.on('mouseout', function() { - if(gd._dragging) return; - dragElement.unhover(gd, d3.event); - }); - - bgRect.on('click', function() { - // For select and lasso the dragElement is handling clicks - if(dragMode !== 'select' && dragMode !== 'lasso') { - if(clickMode.indexOf('select') > -1) { - selectOnClick(d3.event, gd, [_this.xaxis], [_this.yaxis], - _this.id, dragOptions); - } - - if(clickMode.indexOf('event') > -1) { - // TODO: like pie and mapbox, this doesn't support right-click - // actually this one is worse, as right-click starts a pan, or leaves - // select in a weird state. - // Also, only tangentially related, we should cancel hover during pan - Fx.click(gd, d3.event); - } - } - }); -}; - -proto.makeFramework = function() { - var _this = this; - var gd = _this.graphDiv; - var fullLayout = gd._fullLayout; - var clipId = 'clip' + fullLayout._uid + _this.id; - - _this.clipDef = fullLayout._clips.append('clipPath') - .attr('id', clipId); - - _this.clipRect = _this.clipDef.append('rect'); - - _this.framework = d3.select(_this.container).append('g') - .attr('class', 'geo ' + _this.id) - .call(Drawing.setClipUrl, clipId, gd); - - // sane lonlat to px - _this.project = function(v) { - var px = _this.projection(v); - return px ? - [px[0] - _this.xaxis._offset, px[1] - _this.yaxis._offset] : - [null, null]; - }; - - _this.xaxis = { - _id: 'x', - c2p: function(v) { return _this.project(v)[0]; } - }; - - _this.yaxis = { - _id: 'y', - c2p: function(v) { return _this.project(v)[1]; } - }; - - // mock axis for hover formatting - _this.mockAxis = { - type: 'linear', - showexponent: 'all', - exponentformat: 'B' - }; - Axes.setConvert(_this.mockAxis, fullLayout); -}; - -proto.saveViewInitial = function(geoLayout) { - var center = geoLayout.center || {}; - var projLayout = geoLayout.projection; - var rotation = projLayout.rotation || {}; - - if(geoLayout._isScoped) { - this.viewInitial = { - 'center.lon': center.lon, - 'center.lat': center.lat, - 'projection.scale': projLayout.scale - }; - } else if(geoLayout._isClipped) { - this.viewInitial = { - 'projection.scale': projLayout.scale, - 'projection.rotation.lon': rotation.lon, - 'projection.rotation.lat': rotation.lat - }; - } else { - this.viewInitial = { - 'center.lon': center.lon, - 'center.lat': center.lat, - 'projection.scale': projLayout.scale, - 'projection.rotation.lon': rotation.lon - }; - } -}; - -// [hot code path] (re)draw all paths which depend on the projection -proto.render = function() { - var projection = this.projection; - var pathFn = projection.getPath(); - var k; - - function translatePoints(d) { - var lonlatPx = projection(d.lonlat); - return lonlatPx ? - 'translate(' + lonlatPx[0] + ',' + lonlatPx[1] + ')' : - null; - } - - function hideShowPoints(d) { - return projection.isLonLatOverEdges(d.lonlat) ? 'none' : null; - } - - for(k in this.basePaths) { - this.basePaths[k].attr('d', pathFn); - } - - for(k in this.dataPaths) { - this.dataPaths[k].attr('d', function(d) { return pathFn(d.geojson); }); - } - - for(k in this.dataPoints) { - this.dataPoints[k] - .attr('display', hideShowPoints) - .attr('transform', translatePoints); - } -}; - -// Helper that wraps d3.geo[/* projection name /*]() which: -// -// - adds 'fitExtent' (available in d3 v4) -// - adds 'getPath', 'getBounds' convenience methods -// - scopes logic related to 'clipAngle' -// - adds 'isLonLatOverEdges' method -// - sets projection precision -// - sets methods that aren't always defined depending -// on the projection type to a dummy 'd3-esque' function, -// -// This wrapper alleviates subsequent code of (many) annoying if-statements. -function getProjection(geoLayout) { - var projLayout = geoLayout.projection; - var projType = projLayout.type; - - var projection = d3.geo[constants.projNames[projType]](); - - var clipAngle = geoLayout._isClipped ? - constants.lonaxisSpan[projType] / 2 : - null; - - var methods = ['center', 'rotate', 'parallels', 'clipExtent']; - var dummyFn = function(_) { return _ ? projection : []; }; - - for(var i = 0; i < methods.length; i++) { - var m = methods[i]; - if(typeof projection[m] !== 'function') { - projection[m] = dummyFn; - } - } - - projection.isLonLatOverEdges = function(lonlat) { - if(projection(lonlat) === null) { - return true; - } - - if(clipAngle) { - var r = projection.rotate(); - var angle = d3.geo.distance(lonlat, [-r[0], -r[1]]); - var maxAngle = clipAngle * Math.PI / 180; - return angle > maxAngle; - } else { - return false; - } - }; - - projection.getPath = function() { - return d3.geo.path().projection(projection); - }; - - projection.getBounds = function(object) { - return projection.getPath().bounds(object); - }; - - // adapted from d3 v4: - // https://github.com/d3/d3-geo/blob/master/src/projection/fit.js - projection.fitExtent = function(extent, object) { - var w = extent[1][0] - extent[0][0]; - var h = extent[1][1] - extent[0][1]; - var clip = projection.clipExtent && projection.clipExtent(); - - projection - .scale(150) - .translate([0, 0]); - - if(clip) projection.clipExtent(null); - - var b = projection.getBounds(object); - var k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])); - var x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2; - var y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; - - if(clip) projection.clipExtent(clip); - - return projection - .scale(k * 150) - .translate([x, y]); - }; - - projection.precision(constants.precision); - - if(clipAngle) { - projection.clipAngle(clipAngle - constants.clipPad); - } - - return projection; -} - -function makeGraticule(axisName, geoLayout, fullLayout) { - // equivalent to the d3 "ε" - var epsilon = 1e-6; - // same as the geoGraticule default - var precision = 2.5; - - var axLayout = geoLayout[axisName]; - var scopeDefaults = constants.scopeDefaults[geoLayout.scope]; - var rng; - var oppRng; - var coordFn; - - if(axisName === 'lonaxis') { - rng = scopeDefaults.lonaxisRange; - oppRng = scopeDefaults.lataxisRange; - coordFn = function(v, l) { return [v, l]; }; - } else if(axisName === 'lataxis') { - rng = scopeDefaults.lataxisRange; - oppRng = scopeDefaults.lonaxisRange; - coordFn = function(v, l) { return [l, v]; }; - } - - var dummyAx = { - type: 'linear', - range: [rng[0], rng[1] - epsilon], - tick0: axLayout.tick0, - dtick: axLayout.dtick - }; - - Axes.setConvert(dummyAx, fullLayout); - var vals = Axes.calcTicks(dummyAx); - - // remove duplicate on antimeridian - if(!geoLayout.isScoped && axisName === 'lonaxis') { - vals.pop(); - } - - var len = vals.length; - var coords = new Array(len); - - for(var i = 0; i < len; i++) { - var v = vals[i].x; - var line = coords[i] = []; - for(var l = oppRng[0]; l < oppRng[1] + precision; l += precision) { - line.push(coordFn(v, l)); - } - } - - return { - type: 'MultiLineString', - coordinates: coords - }; -} - -// Returns polygon GeoJSON corresponding to lon/lat range box -// with well-defined direction -// -// Note that clipPad padding is added around range to avoid aliasing. -function makeRangeBox(lon, lat) { - var clipPad = constants.clipPad; - var lon0 = lon[0] + clipPad; - var lon1 = lon[1] - clipPad; - var lat0 = lat[0] + clipPad; - var lat1 = lat[1] - clipPad; - - // to cross antimeridian w/o ambiguity - if(lon0 > 0 && lon1 < 0) lon1 += 360; - - var dlon4 = (lon1 - lon0) / 4; - - return { - type: 'Polygon', - coordinates: [[ - [lon0, lat0], - [lon0, lat1], - [lon0 + dlon4, lat1], - [lon0 + 2 * dlon4, lat1], - [lon0 + 3 * dlon4, lat1], - [lon1, lat1], - [lon1, lat0], - [lon1 - dlon4, lat0], - [lon1 - 2 * dlon4, lat0], - [lon1 - 3 * dlon4, lat0], - [lon0, lat0] - ]] - }; -} - -},{"../../components/color":593,"../../components/dragelement":611,"../../components/drawing":614,"../../components/fx":632,"../../lib":719,"../../lib/topojson_utils":746,"../../registry":847,"../cartesian/axes":767,"../cartesian/select":784,"../plots":828,"./constants":795,"./projections":800,"./zoom":801,"d3":163,"topojson-client":540}],797:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var getSubplotCalcData = _dereq_('../../plots/get_data').getSubplotCalcData; -var counterRegex = _dereq_('../../lib').counterRegex; - -var createGeo = _dereq_('./geo'); - -var GEO = 'geo'; -var counter = counterRegex(GEO); - -var attributes = {}; -attributes[GEO] = { - valType: 'subplotid', - - dflt: GEO, - editType: 'calc', - -}; - -function plotGeo(gd) { - var fullLayout = gd._fullLayout; - var calcData = gd.calcdata; - var geoIds = fullLayout._subplots[GEO]; - - for(var i = 0; i < geoIds.length; i++) { - var geoId = geoIds[i]; - var geoCalcData = getSubplotCalcData(calcData, GEO, geoId); - var geoLayout = fullLayout[geoId]; - var geo = geoLayout._subplot; - - if(!geo) { - geo = createGeo({ - id: geoId, - graphDiv: gd, - container: fullLayout._geolayer.node(), - topojsonURL: gd._context.topojsonURL, - staticPlot: gd._context.staticPlot - }); - - fullLayout[geoId]._subplot = geo; - } - - geo.plot(geoCalcData, fullLayout, gd._promises); - } -} - -function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var oldGeoKeys = oldFullLayout._subplots[GEO] || []; - - for(var i = 0; i < oldGeoKeys.length; i++) { - var oldGeoKey = oldGeoKeys[i]; - var oldGeo = oldFullLayout[oldGeoKey]._subplot; - - if(!newFullLayout[oldGeoKey] && !!oldGeo) { - oldGeo.framework.remove(); - oldGeo.clipDef.remove(); - } - } -} - -function updateFx(gd) { - var fullLayout = gd._fullLayout; - var subplotIds = fullLayout._subplots[GEO]; - - for(var i = 0; i < subplotIds.length; i++) { - var subplotLayout = fullLayout[subplotIds[i]]; - var subplotObj = subplotLayout._subplot; - subplotObj.updateFx(fullLayout, subplotLayout); - } -} - -module.exports = { - attr: GEO, - name: GEO, - idRoot: GEO, - idRegex: counter, - attrRegex: counter, - attributes: attributes, - layoutAttributes: _dereq_('./layout_attributes'), - supplyLayoutDefaults: _dereq_('./layout_defaults'), - plot: plotGeo, - updateFx: updateFx, - clean: clean -}; - -},{"../../lib":719,"../../plots/get_data":802,"./geo":796,"./layout_attributes":798,"./layout_defaults":799}],798:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorAttrs = _dereq_('../../components/color/attributes'); -var domainAttrs = _dereq_('../domain').attributes; -var constants = _dereq_('./constants'); -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var geoAxesAttrs = { - range: { - valType: 'info_array', - - items: [ - {valType: 'number'}, - {valType: 'number'} - ], - - }, - showgrid: { - valType: 'boolean', - - dflt: false, - - }, - tick0: { - valType: 'number', - - dflt: 0, - - }, - dtick: { - valType: 'number', - - - }, - gridcolor: { - valType: 'color', - - dflt: colorAttrs.lightLine, - - }, - gridwidth: { - valType: 'number', - - min: 0, - dflt: 1, - - } -}; - -var attrs = module.exports = overrideAll({ - domain: domainAttrs({name: 'geo'}, { - - }), - - resolution: { - valType: 'enumerated', - values: [110, 50], - - dflt: 110, - coerceNumber: true, - - }, - scope: { - valType: 'enumerated', - - values: Object.keys(constants.scopeDefaults), - dflt: 'world', - - }, - projection: { - type: { - valType: 'enumerated', - - values: Object.keys(constants.projNames), - - }, - rotation: { - lon: { - valType: 'number', - - - }, - lat: { - valType: 'number', - - - }, - roll: { - valType: 'number', - - - } - }, - parallels: { - valType: 'info_array', - - items: [ - {valType: 'number'}, - {valType: 'number'} - ], - - }, - scale: { - valType: 'number', - - min: 0, - dflt: 1, - - }, - }, - center: { - lon: { - valType: 'number', - - - }, - lat: { - valType: 'number', - - - } - }, - showcoastlines: { - valType: 'boolean', - - - }, - coastlinecolor: { - valType: 'color', - - dflt: colorAttrs.defaultLine, - - }, - coastlinewidth: { - valType: 'number', - - min: 0, - dflt: 1, - - }, - showland: { - valType: 'boolean', - - dflt: false, - - }, - landcolor: { - valType: 'color', - - dflt: constants.landColor, - - }, - showocean: { - valType: 'boolean', - - dflt: false, - - }, - oceancolor: { - valType: 'color', - - dflt: constants.waterColor, - - }, - showlakes: { - valType: 'boolean', - - dflt: false, - - }, - lakecolor: { - valType: 'color', - - dflt: constants.waterColor, - - }, - showrivers: { - valType: 'boolean', - - dflt: false, - - }, - rivercolor: { - valType: 'color', - - dflt: constants.waterColor, - - }, - riverwidth: { - valType: 'number', - - min: 0, - dflt: 1, - - }, - showcountries: { - valType: 'boolean', - - - }, - countrycolor: { - valType: 'color', - - dflt: colorAttrs.defaultLine, - - }, - countrywidth: { - valType: 'number', - - min: 0, - dflt: 1, - - }, - showsubunits: { - valType: 'boolean', - - - }, - subunitcolor: { - valType: 'color', - - dflt: colorAttrs.defaultLine, - - }, - subunitwidth: { - valType: 'number', - - min: 0, - dflt: 1, - - }, - showframe: { - valType: 'boolean', - - - }, - framecolor: { - valType: 'color', - - dflt: colorAttrs.defaultLine, - - }, - framewidth: { - valType: 'number', - - min: 0, - dflt: 1, - - }, - bgcolor: { - valType: 'color', - - dflt: colorAttrs.background, - - }, - lonaxis: geoAxesAttrs, - lataxis: geoAxesAttrs -}, 'plot', 'from-root'); - -// set uirevision outside of overrideAll so it can be `editType: 'none'` -attrs.uirevision = { - valType: 'any', - - editType: 'none', - -}; - -},{"../../components/color/attributes":592,"../../plot_api/edit_types":750,"../domain":792,"./constants":795}],799:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var handleSubplotDefaults = _dereq_('../subplot_defaults'); -var constants = _dereq_('./constants'); -var layoutAttributes = _dereq_('./layout_attributes'); - -var axesNames = constants.axesNames; - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - handleSubplotDefaults(layoutIn, layoutOut, fullData, { - type: 'geo', - attributes: layoutAttributes, - handleDefaults: handleGeoDefaults, - partition: 'y' - }); -}; - -function handleGeoDefaults(geoLayoutIn, geoLayoutOut, coerce) { - var show; - - var resolution = coerce('resolution'); - var scope = coerce('scope'); - var scopeParams = constants.scopeDefaults[scope]; - - var projType = coerce('projection.type', scopeParams.projType); - var isAlbersUsa = geoLayoutOut._isAlbersUsa = projType === 'albers usa'; - - // no other scopes are allowed for 'albers usa' projection - if(isAlbersUsa) scope = geoLayoutOut.scope = 'usa'; - - var isScoped = geoLayoutOut._isScoped = (scope !== 'world'); - var isConic = geoLayoutOut._isConic = projType.indexOf('conic') !== -1; - geoLayoutOut._isClipped = !!constants.lonaxisSpan[projType]; - - for(var i = 0; i < axesNames.length; i++) { - var axisName = axesNames[i]; - var dtickDflt = [30, 10][i]; - var rangeDflt; - - if(isScoped) { - rangeDflt = scopeParams[axisName + 'Range']; - } else { - var dfltSpans = constants[axisName + 'Span']; - var hSpan = (dfltSpans[projType] || dfltSpans['*']) / 2; - var rot = coerce( - 'projection.rotation.' + axisName.substr(0, 3), - scopeParams.projRotate[i] - ); - rangeDflt = [rot - hSpan, rot + hSpan]; - } - - coerce(axisName + '.range', rangeDflt); - coerce(axisName + '.tick0'); - coerce(axisName + '.dtick', dtickDflt); - - show = coerce(axisName + '.showgrid'); - if(show) { - coerce(axisName + '.gridcolor'); - coerce(axisName + '.gridwidth'); - } - } - - var lonRange = geoLayoutOut.lonaxis.range; - var latRange = geoLayoutOut.lataxis.range; - - // to cross antimeridian w/o ambiguity - var lon0 = lonRange[0]; - var lon1 = lonRange[1]; - if(lon0 > 0 && lon1 < 0) lon1 += 360; - - var centerLon = (lon0 + lon1) / 2; - var projLon; - - if(!isAlbersUsa) { - var dfltProjRotate = isScoped ? scopeParams.projRotate : [centerLon, 0, 0]; - - projLon = coerce('projection.rotation.lon', dfltProjRotate[0]); - coerce('projection.rotation.lat', dfltProjRotate[1]); - coerce('projection.rotation.roll', dfltProjRotate[2]); - - show = coerce('showcoastlines', !isScoped); - if(show) { - coerce('coastlinecolor'); - coerce('coastlinewidth'); - } - - show = coerce('showocean'); - if(show) coerce('oceancolor'); - } - - var centerLonDflt; - var centerLatDflt; - - if(isAlbersUsa) { - // 'albers usa' does not have a 'center', - // these values were found using via: - // projection.invert([geoLayout.center.lon, geoLayoutIn.center.lat]) - centerLonDflt = -96.6; - centerLatDflt = 38.7; - } else { - centerLonDflt = isScoped ? centerLon : projLon; - centerLatDflt = (latRange[0] + latRange[1]) / 2; - } - - coerce('center.lon', centerLonDflt); - coerce('center.lat', centerLatDflt); - - if(isConic) { - var dfltProjParallels = scopeParams.projParallels || [0, 60]; - coerce('projection.parallels', dfltProjParallels); - } - - coerce('projection.scale'); - - show = coerce('showland'); - if(show) coerce('landcolor'); - - show = coerce('showlakes'); - if(show) coerce('lakecolor'); - - show = coerce('showrivers'); - if(show) { - coerce('rivercolor'); - coerce('riverwidth'); - } - - show = coerce('showcountries', isScoped && scope !== 'usa'); - if(show) { - coerce('countrycolor'); - coerce('countrywidth'); - } - - if(scope === 'usa' || (scope === 'north america' && resolution === 50)) { - // Only works for: - // USA states at 110m - // USA states + Canada provinces at 50m - coerce('showsubunits', true); - coerce('subunitcolor'); - coerce('subunitwidth'); - } - - if(!isScoped) { - // Does not work in non-world scopes - show = coerce('showframe', true); - if(show) { - coerce('framecolor'); - coerce('framewidth'); - } - } - - coerce('bgcolor'); -} - -},{"../subplot_defaults":842,"./constants":795,"./layout_attributes":798}],800:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -/* - * Generated by https://github.com/etpinard/d3-geo-projection-picker - * - * which is hand-picks projection from https://github.com/d3/d3-geo-projection - * - * into a CommonJS require-able module. - */ - -'use strict'; - -/* eslint-disable */ - -function addProjectionsToD3(d3) { - d3.geo.project = function(object, projection) { - var stream = projection.stream; - if (!stream) throw new Error("not yet supported"); - return (object && d3_geo_projectObjectType.hasOwnProperty(object.type) ? d3_geo_projectObjectType[object.type] : d3_geo_projectGeometry)(object, stream); - }; - function d3_geo_projectFeature(object, stream) { - return { - type: "Feature", - id: object.id, - properties: object.properties, - geometry: d3_geo_projectGeometry(object.geometry, stream) - }; - } - function d3_geo_projectGeometry(geometry, stream) { - if (!geometry) return null; - if (geometry.type === "GeometryCollection") return { - type: "GeometryCollection", - geometries: object.geometries.map(function(geometry) { - return d3_geo_projectGeometry(geometry, stream); - }) - }; - if (!d3_geo_projectGeometryType.hasOwnProperty(geometry.type)) return null; - var sink = d3_geo_projectGeometryType[geometry.type]; - d3.geo.stream(geometry, stream(sink)); - return sink.result(); - } - var d3_geo_projectObjectType = { - Feature: d3_geo_projectFeature, - FeatureCollection: function(object, stream) { - return { - type: "FeatureCollection", - features: object.features.map(function(feature) { - return d3_geo_projectFeature(feature, stream); - }) - }; - } - }; - var d3_geo_projectPoints = [], d3_geo_projectLines = []; - var d3_geo_projectPoint = { - point: function(x, y) { - d3_geo_projectPoints.push([ x, y ]); - }, - result: function() { - var result = !d3_geo_projectPoints.length ? null : d3_geo_projectPoints.length < 2 ? { - type: "Point", - coordinates: d3_geo_projectPoints[0] - } : { - type: "MultiPoint", - coordinates: d3_geo_projectPoints - }; - d3_geo_projectPoints = []; - return result; - } - }; - var d3_geo_projectLine = { - lineStart: d3_geo_projectNoop, - point: function(x, y) { - d3_geo_projectPoints.push([ x, y ]); - }, - lineEnd: function() { - if (d3_geo_projectPoints.length) d3_geo_projectLines.push(d3_geo_projectPoints), - d3_geo_projectPoints = []; - }, - result: function() { - var result = !d3_geo_projectLines.length ? null : d3_geo_projectLines.length < 2 ? { - type: "LineString", - coordinates: d3_geo_projectLines[0] - } : { - type: "MultiLineString", - coordinates: d3_geo_projectLines - }; - d3_geo_projectLines = []; - return result; - } - }; - var d3_geo_projectPolygon = { - polygonStart: d3_geo_projectNoop, - lineStart: d3_geo_projectNoop, - point: function(x, y) { - d3_geo_projectPoints.push([ x, y ]); - }, - lineEnd: function() { - var n = d3_geo_projectPoints.length; - if (n) { - do d3_geo_projectPoints.push(d3_geo_projectPoints[0].slice()); while (++n < 4); - d3_geo_projectLines.push(d3_geo_projectPoints), d3_geo_projectPoints = []; - } - }, - polygonEnd: d3_geo_projectNoop, - result: function() { - if (!d3_geo_projectLines.length) return null; - var polygons = [], holes = []; - d3_geo_projectLines.forEach(function(ring) { - if (d3_geo_projectClockwise(ring)) polygons.push([ ring ]); else holes.push(ring); - }); - holes.forEach(function(hole) { - var point = hole[0]; - polygons.some(function(polygon) { - if (d3_geo_projectContains(polygon[0], point)) { - polygon.push(hole); - return true; - } - }) || polygons.push([ hole ]); - }); - d3_geo_projectLines = []; - return !polygons.length ? null : polygons.length > 1 ? { - type: "MultiPolygon", - coordinates: polygons - } : { - type: "Polygon", - coordinates: polygons[0] - }; - } - }; - var d3_geo_projectGeometryType = { - Point: d3_geo_projectPoint, - MultiPoint: d3_geo_projectPoint, - LineString: d3_geo_projectLine, - MultiLineString: d3_geo_projectLine, - Polygon: d3_geo_projectPolygon, - MultiPolygon: d3_geo_projectPolygon, - Sphere: d3_geo_projectPolygon - }; - function d3_geo_projectNoop() {} - function d3_geo_projectClockwise(ring) { - if ((n = ring.length) < 4) return false; - var i = 0, n, area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1]; - while (++i < n) area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1]; - return area <= 0; - } - function d3_geo_projectContains(ring, point) { - var x = point[0], y = point[1], contains = false; - for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) { - var pi = ring[i], xi = pi[0], yi = pi[1], pj = ring[j], xj = pj[0], yj = pj[1]; - if (yi > y ^ yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) contains = !contains; - } - return contains; - } - var ε = 1e-6, ε2 = ε * ε, π = Math.PI, halfπ = π / 2, sqrtπ = Math.sqrt(π), radians = π / 180, degrees = 180 / π; - function sinci(x) { - return x ? x / Math.sin(x) : 1; - } - function sgn(x) { - return x > 0 ? 1 : x < 0 ? -1 : 0; - } - function asin(x) { - return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); - } - function acos(x) { - return x > 1 ? 0 : x < -1 ? π : Math.acos(x); - } - function asqrt(x) { - return x > 0 ? Math.sqrt(x) : 0; - } - var projection = d3.geo.projection, projectionMutator = d3.geo.projectionMutator; - d3.geo.interrupt = function(project) { - var lobes = [ [ [ [ -π, 0 ], [ 0, halfπ ], [ π, 0 ] ] ], [ [ [ -π, 0 ], [ 0, -halfπ ], [ π, 0 ] ] ] ]; - var bounds; - function forward(λ, φ) { - var sign = φ < 0 ? -1 : +1, hemilobes = lobes[+(φ < 0)]; - for (var i = 0, n = hemilobes.length - 1; i < n && λ > hemilobes[i][2][0]; ++i) ; - var coordinates = project(λ - hemilobes[i][1][0], φ); - coordinates[0] += project(hemilobes[i][1][0], sign * φ > sign * hemilobes[i][0][1] ? hemilobes[i][0][1] : φ)[0]; - return coordinates; - } - function reset() { - bounds = lobes.map(function(hemilobes) { - return hemilobes.map(function(lobe) { - var x0 = project(lobe[0][0], lobe[0][1])[0], x1 = project(lobe[2][0], lobe[2][1])[0], y0 = project(lobe[1][0], lobe[0][1])[1], y1 = project(lobe[1][0], lobe[1][1])[1], t; - if (y0 > y1) t = y0, y0 = y1, y1 = t; - return [ [ x0, y0 ], [ x1, y1 ] ]; - }); - }); - } - if (project.invert) forward.invert = function(x, y) { - var hemibounds = bounds[+(y < 0)], hemilobes = lobes[+(y < 0)]; - for (var i = 0, n = hemibounds.length; i < n; ++i) { - var b = hemibounds[i]; - if (b[0][0] <= x && x < b[1][0] && b[0][1] <= y && y < b[1][1]) { - var coordinates = project.invert(x - project(hemilobes[i][1][0], 0)[0], y); - coordinates[0] += hemilobes[i][1][0]; - return pointEqual(forward(coordinates[0], coordinates[1]), [ x, y ]) ? coordinates : null; - } - } - }; - var projection = d3.geo.projection(forward), stream_ = projection.stream; - projection.stream = function(stream) { - var rotate = projection.rotate(), rotateStream = stream_(stream), sphereStream = (projection.rotate([ 0, 0 ]), - stream_(stream)); - projection.rotate(rotate); - rotateStream.sphere = function() { - d3.geo.stream(sphere(), sphereStream); - }; - return rotateStream; - }; - projection.lobes = function(_) { - if (!arguments.length) return lobes.map(function(lobes) { - return lobes.map(function(lobe) { - return [ [ lobe[0][0] * 180 / π, lobe[0][1] * 180 / π ], [ lobe[1][0] * 180 / π, lobe[1][1] * 180 / π ], [ lobe[2][0] * 180 / π, lobe[2][1] * 180 / π ] ]; - }); - }); - lobes = _.map(function(lobes) { - return lobes.map(function(lobe) { - return [ [ lobe[0][0] * π / 180, lobe[0][1] * π / 180 ], [ lobe[1][0] * π / 180, lobe[1][1] * π / 180 ], [ lobe[2][0] * π / 180, lobe[2][1] * π / 180 ] ]; - }); - }); - reset(); - return projection; - }; - function sphere() { - var ε = 1e-6, coordinates = []; - for (var i = 0, n = lobes[0].length; i < n; ++i) { - var lobe = lobes[0][i], λ0 = lobe[0][0] * 180 / π, φ0 = lobe[0][1] * 180 / π, φ1 = lobe[1][1] * 180 / π, λ2 = lobe[2][0] * 180 / π, φ2 = lobe[2][1] * 180 / π; - coordinates.push(resample([ [ λ0 + ε, φ0 + ε ], [ λ0 + ε, φ1 - ε ], [ λ2 - ε, φ1 - ε ], [ λ2 - ε, φ2 + ε ] ], 30)); - } - for (var i = lobes[1].length - 1; i >= 0; --i) { - var lobe = lobes[1][i], λ0 = lobe[0][0] * 180 / π, φ0 = lobe[0][1] * 180 / π, φ1 = lobe[1][1] * 180 / π, λ2 = lobe[2][0] * 180 / π, φ2 = lobe[2][1] * 180 / π; - coordinates.push(resample([ [ λ2 - ε, φ2 - ε ], [ λ2 - ε, φ1 + ε ], [ λ0 + ε, φ1 + ε ], [ λ0 + ε, φ0 - ε ] ], 30)); - } - return { - type: "Polygon", - coordinates: [ d3.merge(coordinates) ] - }; - } - function resample(coordinates, m) { - var i = -1, n = coordinates.length, p0 = coordinates[0], p1, dx, dy, resampled = []; - while (++i < n) { - p1 = coordinates[i]; - dx = (p1[0] - p0[0]) / m; - dy = (p1[1] - p0[1]) / m; - for (var j = 0; j < m; ++j) resampled.push([ p0[0] + j * dx, p0[1] + j * dy ]); - p0 = p1; - } - resampled.push(p1); - return resampled; - } - function pointEqual(a, b) { - return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε; - } - return projection; - }; - function eckert4(λ, φ) { - var k = (2 + halfπ) * Math.sin(φ); - φ /= 2; - for (var i = 0, δ = Infinity; i < 10 && Math.abs(δ) > ε; i++) { - var cosφ = Math.cos(φ); - φ -= δ = (φ + Math.sin(φ) * (cosφ + 2) - k) / (2 * cosφ * (1 + cosφ)); - } - return [ 2 / Math.sqrt(π * (4 + π)) * λ * (1 + Math.cos(φ)), 2 * Math.sqrt(π / (4 + π)) * Math.sin(φ) ]; - } - eckert4.invert = function(x, y) { - var A = .5 * y * Math.sqrt((4 + π) / π), k = asin(A), c = Math.cos(k); - return [ x / (2 / Math.sqrt(π * (4 + π)) * (1 + c)), asin((k + A * (c + 2)) / (2 + halfπ)) ]; - }; - (d3.geo.eckert4 = function() { - return projection(eckert4); - }).raw = eckert4; - var hammerAzimuthalEqualArea = d3.geo.azimuthalEqualArea.raw; - function hammer(A, B) { - if (arguments.length < 2) B = A; - if (B === 1) return hammerAzimuthalEqualArea; - if (B === Infinity) return hammerQuarticAuthalic; - function forward(λ, φ) { - var coordinates = hammerAzimuthalEqualArea(λ / B, φ); - coordinates[0] *= A; - return coordinates; - } - forward.invert = function(x, y) { - var coordinates = hammerAzimuthalEqualArea.invert(x / A, y); - coordinates[0] *= B; - return coordinates; - }; - return forward; - } - function hammerProjection() { - var B = 2, m = projectionMutator(hammer), p = m(B); - p.coefficient = function(_) { - if (!arguments.length) return B; - return m(B = +_); - }; - return p; - } - function hammerQuarticAuthalic(λ, φ) { - return [ λ * Math.cos(φ) / Math.cos(φ /= 2), 2 * Math.sin(φ) ]; - } - hammerQuarticAuthalic.invert = function(x, y) { - var φ = 2 * asin(y / 2); - return [ x * Math.cos(φ / 2) / Math.cos(φ), φ ]; - }; - (d3.geo.hammer = hammerProjection).raw = hammer; - function kavrayskiy7(λ, φ) { - return [ 3 * λ / (2 * π) * Math.sqrt(π * π / 3 - φ * φ), φ ]; - } - kavrayskiy7.invert = function(x, y) { - return [ 2 / 3 * π * x / Math.sqrt(π * π / 3 - y * y), y ]; - }; - (d3.geo.kavrayskiy7 = function() { - return projection(kavrayskiy7); - }).raw = kavrayskiy7; - function miller(λ, φ) { - return [ λ, 1.25 * Math.log(Math.tan(π / 4 + .4 * φ)) ]; - } - miller.invert = function(x, y) { - return [ x, 2.5 * Math.atan(Math.exp(.8 * y)) - .625 * π ]; - }; - (d3.geo.miller = function() { - return projection(miller); - }).raw = miller; - function mollweideBromleyθ(Cp) { - return function(θ) { - var Cpsinθ = Cp * Math.sin(θ), i = 30, δ; - do θ -= δ = (θ + Math.sin(θ) - Cpsinθ) / (1 + Math.cos(θ)); while (Math.abs(δ) > ε && --i > 0); - return θ / 2; - }; - } - function mollweideBromley(Cx, Cy, Cp) { - var θ = mollweideBromleyθ(Cp); - function forward(λ, φ) { - return [ Cx * λ * Math.cos(φ = θ(φ)), Cy * Math.sin(φ) ]; - } - forward.invert = function(x, y) { - var θ = asin(y / Cy); - return [ x / (Cx * Math.cos(θ)), asin((2 * θ + Math.sin(2 * θ)) / Cp) ]; - }; - return forward; - } - var mollweideθ = mollweideBromleyθ(π), mollweide = mollweideBromley(Math.SQRT2 / halfπ, Math.SQRT2, π); - (d3.geo.mollweide = function() { - return projection(mollweide); - }).raw = mollweide; - function naturalEarth(λ, φ) { - var φ2 = φ * φ, φ4 = φ2 * φ2; - return [ λ * (.8707 - .131979 * φ2 + φ4 * (-.013791 + φ4 * (.003971 * φ2 - .001529 * φ4))), φ * (1.007226 + φ2 * (.015085 + φ4 * (-.044475 + .028874 * φ2 - .005916 * φ4))) ]; - } - naturalEarth.invert = function(x, y) { - var φ = y, i = 25, δ; - do { - var φ2 = φ * φ, φ4 = φ2 * φ2; - φ -= δ = (φ * (1.007226 + φ2 * (.015085 + φ4 * (-.044475 + .028874 * φ2 - .005916 * φ4))) - y) / (1.007226 + φ2 * (.015085 * 3 + φ4 * (-.044475 * 7 + .028874 * 9 * φ2 - .005916 * 11 * φ4))); - } while (Math.abs(δ) > ε && --i > 0); - return [ x / (.8707 + (φ2 = φ * φ) * (-.131979 + φ2 * (-.013791 + φ2 * φ2 * φ2 * (.003971 - .001529 * φ2)))), φ ]; - }; - (d3.geo.naturalEarth = function() { - return projection(naturalEarth); - }).raw = naturalEarth; - var robinsonConstants = [ [ .9986, -.062 ], [ 1, 0 ], [ .9986, .062 ], [ .9954, .124 ], [ .99, .186 ], [ .9822, .248 ], [ .973, .31 ], [ .96, .372 ], [ .9427, .434 ], [ .9216, .4958 ], [ .8962, .5571 ], [ .8679, .6176 ], [ .835, .6769 ], [ .7986, .7346 ], [ .7597, .7903 ], [ .7186, .8435 ], [ .6732, .8936 ], [ .6213, .9394 ], [ .5722, .9761 ], [ .5322, 1 ] ]; - robinsonConstants.forEach(function(d) { - d[1] *= 1.0144; - }); - function robinson(λ, φ) { - var i = Math.min(18, Math.abs(φ) * 36 / π), i0 = Math.floor(i), di = i - i0, ax = (k = robinsonConstants[i0])[0], ay = k[1], bx = (k = robinsonConstants[++i0])[0], by = k[1], cx = (k = robinsonConstants[Math.min(19, ++i0)])[0], cy = k[1], k; - return [ λ * (bx + di * (cx - ax) / 2 + di * di * (cx - 2 * bx + ax) / 2), (φ > 0 ? halfπ : -halfπ) * (by + di * (cy - ay) / 2 + di * di * (cy - 2 * by + ay) / 2) ]; - } - robinson.invert = function(x, y) { - var yy = y / halfπ, φ = yy * 90, i = Math.min(18, Math.abs(φ / 5)), i0 = Math.max(0, Math.floor(i)); - do { - var ay = robinsonConstants[i0][1], by = robinsonConstants[i0 + 1][1], cy = robinsonConstants[Math.min(19, i0 + 2)][1], u = cy - ay, v = cy - 2 * by + ay, t = 2 * (Math.abs(yy) - by) / u, c = v / u, di = t * (1 - c * t * (1 - 2 * c * t)); - if (di >= 0 || i0 === 1) { - φ = (y >= 0 ? 5 : -5) * (di + i); - var j = 50, δ; - do { - i = Math.min(18, Math.abs(φ) / 5); - i0 = Math.floor(i); - di = i - i0; - ay = robinsonConstants[i0][1]; - by = robinsonConstants[i0 + 1][1]; - cy = robinsonConstants[Math.min(19, i0 + 2)][1]; - φ -= (δ = (y >= 0 ? halfπ : -halfπ) * (by + di * (cy - ay) / 2 + di * di * (cy - 2 * by + ay) / 2) - y) * degrees; - } while (Math.abs(δ) > ε2 && --j > 0); - break; - } - } while (--i0 >= 0); - var ax = robinsonConstants[i0][0], bx = robinsonConstants[i0 + 1][0], cx = robinsonConstants[Math.min(19, i0 + 2)][0]; - return [ x / (bx + di * (cx - ax) / 2 + di * di * (cx - 2 * bx + ax) / 2), φ * radians ]; - }; - (d3.geo.robinson = function() { - return projection(robinson); - }).raw = robinson; - function sinusoidal(λ, φ) { - return [ λ * Math.cos(φ), φ ]; - } - sinusoidal.invert = function(x, y) { - return [ x / Math.cos(y), y ]; - }; - (d3.geo.sinusoidal = function() { - return projection(sinusoidal); - }).raw = sinusoidal; - function aitoff(λ, φ) { - var cosφ = Math.cos(φ), sinciα = sinci(acos(cosφ * Math.cos(λ /= 2))); - return [ 2 * cosφ * Math.sin(λ) * sinciα, Math.sin(φ) * sinciα ]; - } - aitoff.invert = function(x, y) { - if (x * x + 4 * y * y > π * π + ε) return; - var λ = x, φ = y, i = 25; - do { - var sinλ = Math.sin(λ), sinλ_2 = Math.sin(λ / 2), cosλ_2 = Math.cos(λ / 2), sinφ = Math.sin(φ), cosφ = Math.cos(φ), sin_2φ = Math.sin(2 * φ), sin2φ = sinφ * sinφ, cos2φ = cosφ * cosφ, sin2λ_2 = sinλ_2 * sinλ_2, C = 1 - cos2φ * cosλ_2 * cosλ_2, E = C ? acos(cosφ * cosλ_2) * Math.sqrt(F = 1 / C) : F = 0, F, fx = 2 * E * cosφ * sinλ_2 - x, fy = E * sinφ - y, δxδλ = F * (cos2φ * sin2λ_2 + E * cosφ * cosλ_2 * sin2φ), δxδφ = F * (.5 * sinλ * sin_2φ - E * 2 * sinφ * sinλ_2), δyδλ = F * .25 * (sin_2φ * sinλ_2 - E * sinφ * cos2φ * sinλ), δyδφ = F * (sin2φ * cosλ_2 + E * sin2λ_2 * cosφ), denominator = δxδφ * δyδλ - δyδφ * δxδλ; - if (!denominator) break; - var δλ = (fy * δxδφ - fx * δyδφ) / denominator, δφ = (fx * δyδλ - fy * δxδλ) / denominator; - λ -= δλ, φ -= δφ; - } while ((Math.abs(δλ) > ε || Math.abs(δφ) > ε) && --i > 0); - return [ λ, φ ]; - }; - (d3.geo.aitoff = function() { - return projection(aitoff); - }).raw = aitoff; - function winkel3(λ, φ) { - var coordinates = aitoff(λ, φ); - return [ (coordinates[0] + λ / halfπ) / 2, (coordinates[1] + φ) / 2 ]; - } - winkel3.invert = function(x, y) { - var λ = x, φ = y, i = 25; - do { - var cosφ = Math.cos(φ), sinφ = Math.sin(φ), sin_2φ = Math.sin(2 * φ), sin2φ = sinφ * sinφ, cos2φ = cosφ * cosφ, sinλ = Math.sin(λ), cosλ_2 = Math.cos(λ / 2), sinλ_2 = Math.sin(λ / 2), sin2λ_2 = sinλ_2 * sinλ_2, C = 1 - cos2φ * cosλ_2 * cosλ_2, E = C ? acos(cosφ * cosλ_2) * Math.sqrt(F = 1 / C) : F = 0, F, fx = .5 * (2 * E * cosφ * sinλ_2 + λ / halfπ) - x, fy = .5 * (E * sinφ + φ) - y, δxδλ = .5 * F * (cos2φ * sin2λ_2 + E * cosφ * cosλ_2 * sin2φ) + .5 / halfπ, δxδφ = F * (sinλ * sin_2φ / 4 - E * sinφ * sinλ_2), δyδλ = .125 * F * (sin_2φ * sinλ_2 - E * sinφ * cos2φ * sinλ), δyδφ = .5 * F * (sin2φ * cosλ_2 + E * sin2λ_2 * cosφ) + .5, denominator = δxδφ * δyδλ - δyδφ * δxδλ, δλ = (fy * δxδφ - fx * δyδφ) / denominator, δφ = (fx * δyδλ - fy * δxδλ) / denominator; - λ -= δλ, φ -= δφ; - } while ((Math.abs(δλ) > ε || Math.abs(δφ) > ε) && --i > 0); - return [ λ, φ ]; - }; - (d3.geo.winkel3 = function() { - return projection(winkel3); - }).raw = winkel3; -} - -module.exports = addProjectionsToD3; - -},{}],801:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); - -var radians = Math.PI / 180; -var degrees = 180 / Math.PI; -var zoomstartStyle = {cursor: 'pointer'}; -var zoomendStyle = {cursor: 'auto'}; - -function createGeoZoom(geo, geoLayout) { - var projection = geo.projection; - var zoomConstructor; - - if(geoLayout._isScoped) { - zoomConstructor = zoomScoped; - } else if(geoLayout._isClipped) { - zoomConstructor = zoomClipped; - } else { - zoomConstructor = zoomNonClipped; - } - - // TODO add a conic-specific zoom - - return zoomConstructor(geo, projection); -} - -module.exports = createGeoZoom; - -// common to all zoom types -function initZoom(geo, projection) { - return d3.behavior.zoom() - .translate(projection.translate()) - .scale(projection.scale()); -} - -// sync zoom updates with user & full layout -function sync(geo, projection, cb) { - var id = geo.id; - var gd = geo.graphDiv; - var layout = gd.layout; - var userOpts = layout[id]; - var fullLayout = gd._fullLayout; - var fullOpts = fullLayout[id]; - - var preGUI = {}; - var eventData = {}; - - function set(propStr, val) { - preGUI[id + '.' + propStr] = Lib.nestedProperty(userOpts, propStr).get(); - Registry.call('_storeDirectGUIEdit', layout, fullLayout._preGUI, preGUI); - - var fullNp = Lib.nestedProperty(fullOpts, propStr); - if(fullNp.get() !== val) { - fullNp.set(val); - Lib.nestedProperty(userOpts, propStr).set(val); - eventData[id + '.' + propStr] = val; - } - } - - cb(set); - set('projection.scale', projection.scale() / geo.fitScale); - gd.emit('plotly_relayout', eventData); -} - -// zoom for scoped projections -function zoomScoped(geo, projection) { - var zoom = initZoom(geo, projection); - - function handleZoomstart() { - d3.select(this).style(zoomstartStyle); - } - - function handleZoom() { - projection - .scale(d3.event.scale) - .translate(d3.event.translate); - geo.render(); - - var center = projection.invert(geo.midPt); - geo.graphDiv.emit('plotly_relayouting', { - 'geo.projection.scale': projection.scale() / geo.fitScale, - 'geo.center.lon': center[0], - 'geo.center.lat': center[1] - }); - } - - function syncCb(set) { - var center = projection.invert(geo.midPt); - - set('center.lon', center[0]); - set('center.lat', center[1]); - } - - function handleZoomend() { - d3.select(this).style(zoomendStyle); - sync(geo, projection, syncCb); - } - - zoom - .on('zoomstart', handleZoomstart) - .on('zoom', handleZoom) - .on('zoomend', handleZoomend); - - return zoom; -} - -// zoom for non-clipped projections -function zoomNonClipped(geo, projection) { - var zoom = initZoom(geo, projection); - - var INSIDETOLORANCEPXS = 2; - - var mouse0, rotate0, translate0, lastRotate, zoomPoint, - mouse1, rotate1, point1, didZoom; - - function position(x) { return projection.invert(x); } - - function outside(x) { - var pos = position(x); - if(!pos) return true; - - var pt = projection(pos); - return ( - Math.abs(pt[0] - x[0]) > INSIDETOLORANCEPXS || - Math.abs(pt[1] - x[1]) > INSIDETOLORANCEPXS - ); - } - - function handleZoomstart() { - d3.select(this).style(zoomstartStyle); - - mouse0 = d3.mouse(this); - rotate0 = projection.rotate(); - translate0 = projection.translate(); - lastRotate = rotate0; - zoomPoint = position(mouse0); - } - - function handleZoom() { - mouse1 = d3.mouse(this); - - if(outside(mouse0)) { - zoom.scale(projection.scale()); - zoom.translate(projection.translate()); - return; - } - - projection.scale(d3.event.scale); - projection.translate([translate0[0], d3.event.translate[1]]); - - if(!zoomPoint) { - mouse0 = mouse1; - zoomPoint = position(mouse0); - } else if(position(mouse1)) { - point1 = position(mouse1); - rotate1 = [lastRotate[0] + (point1[0] - zoomPoint[0]), rotate0[1], rotate0[2]]; - projection.rotate(rotate1); - lastRotate = rotate1; - } - - didZoom = true; - geo.render(); - - var rotate = projection.rotate(); - var center = projection.invert(geo.midPt); - geo.graphDiv.emit('plotly_relayouting', { - 'geo.projection.scale': projection.scale() / geo.fitScale, - 'geo.center.lon': center[0], - 'geo.center.lat': center[1], - 'geo.projection.rotation.lon': -rotate[0] - - }); - } - - function handleZoomend() { - d3.select(this).style(zoomendStyle); - if(didZoom) sync(geo, projection, syncCb); - } - - function syncCb(set) { - var rotate = projection.rotate(); - var center = projection.invert(geo.midPt); - - set('projection.rotation.lon', -rotate[0]); - set('center.lon', center[0]); - set('center.lat', center[1]); - } - - zoom - .on('zoomstart', handleZoomstart) - .on('zoom', handleZoom) - .on('zoomend', handleZoomend); - - return zoom; -} - -// zoom for clipped projections -// inspired by https://www.jasondavies.com/maps/d3.geo.zoom.js -function zoomClipped(geo, projection) { - var view = {r: projection.rotate(), k: projection.scale()}; - var zoom = initZoom(geo, projection); - var event = d3eventDispatch(zoom, 'zoomstart', 'zoom', 'zoomend'); - var zooming = 0; - var zoomOn = zoom.on; - - var zoomPoint; - - zoom.on('zoomstart', function() { - d3.select(this).style(zoomstartStyle); - - var mouse0 = d3.mouse(this); - var rotate0 = projection.rotate(); - var lastRotate = rotate0; - var translate0 = projection.translate(); - var q = quaternionFromEuler(rotate0); - - zoomPoint = position(projection, mouse0); - - zoomOn.call(zoom, 'zoom', function() { - var mouse1 = d3.mouse(this); - - projection.scale(view.k = d3.event.scale); - - if(!zoomPoint) { - // if no zoomPoint, the mouse wasn't over the actual geography yet - // maybe this point is the start... we'll find out next time! - mouse0 = mouse1; - zoomPoint = position(projection, mouse0); - } else if(position(projection, mouse1)) { - // check if the point is on the map - // if not, don't do anything new but scale - // if it is, then we can assume between will exist below - // so we don't need the 'bank' function, whatever that is. - - // go back to original projection temporarily - // except for scale... that's kind of independent? - projection - .rotate(rotate0) - .translate(translate0); - - // calculate the new params - var point1 = position(projection, mouse1); - var between = rotateBetween(zoomPoint, point1); - var newEuler = eulerFromQuaternion(multiply(q, between)); - var rotateAngles = view.r = unRoll(newEuler, zoomPoint, lastRotate); - - if(!isFinite(rotateAngles[0]) || !isFinite(rotateAngles[1]) || - !isFinite(rotateAngles[2])) { - rotateAngles = lastRotate; - } - - // update the projection - projection.rotate(rotateAngles); - lastRotate = rotateAngles; - } - - zoomed(event.of(this, arguments)); - }); - - zoomstarted(event.of(this, arguments)); - }) - .on('zoomend', function() { - d3.select(this).style(zoomendStyle); - zoomOn.call(zoom, 'zoom', null); - zoomended(event.of(this, arguments)); - sync(geo, projection, syncCb); - }) - .on('zoom.redraw', function() { - geo.render(); - - var _rotate = projection.rotate(); - geo.graphDiv.emit('plotly_relayouting', { - 'geo.projection.scale': projection.scale() / geo.fitScale, - 'geo.projection.rotation.lon': -_rotate[0], - 'geo.projection.rotation.lat': -_rotate[1] - }); - }); - - function zoomstarted(dispatch) { - if(!zooming++) dispatch({type: 'zoomstart'}); - } - - function zoomed(dispatch) { - dispatch({type: 'zoom'}); - } - - function zoomended(dispatch) { - if(!--zooming) dispatch({type: 'zoomend'}); - } - - function syncCb(set) { - var _rotate = projection.rotate(); - set('projection.rotation.lon', -_rotate[0]); - set('projection.rotation.lat', -_rotate[1]); - } - - return d3.rebind(zoom, event, 'on'); -} - -// -- helper functions for zoomClipped - -function position(projection, point) { - var spherical = projection.invert(point); - return spherical && isFinite(spherical[0]) && isFinite(spherical[1]) && cartesian(spherical); -} - -function quaternionFromEuler(euler) { - var lambda = 0.5 * euler[0] * radians; - var phi = 0.5 * euler[1] * radians; - var gamma = 0.5 * euler[2] * radians; - var sinLambda = Math.sin(lambda); - var cosLambda = Math.cos(lambda); - var sinPhi = Math.sin(phi); - var cosPhi = Math.cos(phi); - var sinGamma = Math.sin(gamma); - var cosGamma = Math.cos(gamma); - return [ - cosLambda * cosPhi * cosGamma + sinLambda * sinPhi * sinGamma, - sinLambda * cosPhi * cosGamma - cosLambda * sinPhi * sinGamma, - cosLambda * sinPhi * cosGamma + sinLambda * cosPhi * sinGamma, - cosLambda * cosPhi * sinGamma - sinLambda * sinPhi * cosGamma - ]; -} - -function multiply(a, b) { - var a0 = a[0]; - var a1 = a[1]; - var a2 = a[2]; - var a3 = a[3]; - var b0 = b[0]; - var b1 = b[1]; - var b2 = b[2]; - var b3 = b[3]; - return [ - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3, - a0 * b1 + a1 * b0 + a2 * b3 - a3 * b2, - a0 * b2 - a1 * b3 + a2 * b0 + a3 * b1, - a0 * b3 + a1 * b2 - a2 * b1 + a3 * b0 - ]; -} - -function rotateBetween(a, b) { - if(!a || !b) return; - var axis = cross(a, b); - var norm = Math.sqrt(dot(axis, axis)); - var halfgamma = 0.5 * Math.acos(Math.max(-1, Math.min(1, dot(a, b)))); - var k = Math.sin(halfgamma) / norm; - return norm && [Math.cos(halfgamma), axis[2] * k, -axis[1] * k, axis[0] * k]; -} - -// input: -// rotateAngles: a calculated set of Euler angles -// pt: a point (cartesian in 3-space) to keep fixed -// roll0: an initial roll, to be preserved -// output: -// a set of Euler angles that preserve the projection of pt -// but set roll (output[2]) equal to roll0 -// note that this doesn't depend on the particular projection, -// just on the rotation angles -function unRoll(rotateAngles, pt, lastRotate) { - // calculate the fixed point transformed by these Euler angles - // but with the desired roll undone - var ptRotated = rotateCartesian(pt, 2, rotateAngles[0]); - ptRotated = rotateCartesian(ptRotated, 1, rotateAngles[1]); - ptRotated = rotateCartesian(ptRotated, 0, rotateAngles[2] - lastRotate[2]); - - var x = pt[0]; - var y = pt[1]; - var z = pt[2]; - var f = ptRotated[0]; - var g = ptRotated[1]; - var h = ptRotated[2]; - - // the following essentially solves: - // ptRotated = rotateCartesian(rotateCartesian(pt, 2, newYaw), 1, newPitch) - // for newYaw and newPitch, as best it can - var theta = Math.atan2(y, x) * degrees; - var a = Math.sqrt(x * x + y * y); - var b; - var newYaw1; - - if(Math.abs(g) > a) { - newYaw1 = (g > 0 ? 90 : -90) - theta; - b = 0; - } else { - newYaw1 = Math.asin(g / a) * degrees - theta; - b = Math.sqrt(a * a - g * g); - } - - var newYaw2 = 180 - newYaw1 - 2 * theta; - var newPitch1 = (Math.atan2(h, f) - Math.atan2(z, b)) * degrees; - var newPitch2 = (Math.atan2(h, f) - Math.atan2(z, -b)) * degrees; - - // which is closest to lastRotate[0,1]: newYaw/Pitch or newYaw2/Pitch2? - var dist1 = angleDistance(lastRotate[0], lastRotate[1], newYaw1, newPitch1); - var dist2 = angleDistance(lastRotate[0], lastRotate[1], newYaw2, newPitch2); - - if(dist1 <= dist2) return [newYaw1, newPitch1, lastRotate[2]]; - else return [newYaw2, newPitch2, lastRotate[2]]; -} - -function angleDistance(yaw0, pitch0, yaw1, pitch1) { - var dYaw = angleMod(yaw1 - yaw0); - var dPitch = angleMod(pitch1 - pitch0); - return Math.sqrt(dYaw * dYaw + dPitch * dPitch); -} - -// reduce an angle in degrees to [-180,180] -function angleMod(angle) { - return (angle % 360 + 540) % 360 - 180; -} - -// rotate a cartesian vector -// axis is 0 (x), 1 (y), or 2 (z) -// angle is in degrees -function rotateCartesian(vector, axis, angle) { - var angleRads = angle * radians; - var vectorOut = vector.slice(); - var ax1 = (axis === 0) ? 1 : 0; - var ax2 = (axis === 2) ? 1 : 2; - var cosa = Math.cos(angleRads); - var sina = Math.sin(angleRads); - - vectorOut[ax1] = vector[ax1] * cosa - vector[ax2] * sina; - vectorOut[ax2] = vector[ax2] * cosa + vector[ax1] * sina; - - return vectorOut; -} -function eulerFromQuaternion(q) { - return [ - Math.atan2(2 * (q[0] * q[1] + q[2] * q[3]), 1 - 2 * (q[1] * q[1] + q[2] * q[2])) * degrees, - Math.asin(Math.max(-1, Math.min(1, 2 * (q[0] * q[2] - q[3] * q[1])))) * degrees, - Math.atan2(2 * (q[0] * q[3] + q[1] * q[2]), 1 - 2 * (q[2] * q[2] + q[3] * q[3])) * degrees - ]; -} - -function cartesian(spherical) { - var lambda = spherical[0] * radians; - var phi = spherical[1] * radians; - var cosPhi = Math.cos(phi); - return [ - cosPhi * Math.cos(lambda), - cosPhi * Math.sin(lambda), - Math.sin(phi) - ]; -} - -function dot(a, b) { - var s = 0; - for(var i = 0, n = a.length; i < n; ++i) s += a[i] * b[i]; - return s; -} - -function cross(a, b) { - return [ - a[1] * b[2] - a[2] * b[1], - a[2] * b[0] - a[0] * b[2], - a[0] * b[1] - a[1] * b[0] - ]; -} - -// Like d3.dispatch, but for custom events abstracting native UI events. These -// events have a target component (such as a brush), a target element (such as -// the svg:g element containing the brush) and the standard arguments `d` (the -// target element's data) and `i` (the selection index of the target element). -function d3eventDispatch(target) { - var i = 0; - var n = arguments.length; - var argumentz = []; - - while(++i < n) argumentz.push(arguments[i]); - - var dispatch = d3.dispatch.apply(null, argumentz); - - // Creates a dispatch context for the specified `thiz` (typically, the target - // DOM element that received the source event) and `argumentz` (typically, the - // data `d` and index `i` of the target element). The returned function can be - // used to dispatch an event to any registered listeners; the function takes a - // single argument as input, being the event to dispatch. The event must have - // a "type" attribute which corresponds to a type registered in the - // constructor. This context will automatically populate the "sourceEvent" and - // "target" attributes of the event, as well as setting the `d3.event` global - // for the duration of the notification. - dispatch.of = function(thiz, argumentz) { - return function(e1) { - var e0; - try { - e0 = e1.sourceEvent = d3.event; - e1.target = target; - d3.event = e1; - dispatch[e1.type].apply(thiz, argumentz); - } finally { - d3.event = e0; - } - }; - }; - - return dispatch; -} - -},{"../../lib":719,"../../registry":847,"d3":163}],802:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../registry'); -var SUBPLOT_PATTERN = _dereq_('./cartesian/constants').SUBPLOT_PATTERN; - -/** - * Get calcdata trace(s) associated with a given subplot - * - * @param {array} calcData: as in gd.calcdata - * @param {string} type: subplot type - * @param {string} subplotId: subplot id to look for - * - * @return {array} array of calcdata traces - */ -exports.getSubplotCalcData = function(calcData, type, subplotId) { - var basePlotModule = Registry.subplotsRegistry[type]; - if(!basePlotModule) return []; - - var attr = basePlotModule.attr; - var subplotCalcData = []; - - for(var i = 0; i < calcData.length; i++) { - var calcTrace = calcData[i]; - var trace = calcTrace[0].trace; - - if(trace[attr] === subplotId) subplotCalcData.push(calcTrace); - } - - return subplotCalcData; -}; -/** - * Get calcdata trace(s) that can be plotted with a given module - * NOTE: this isn't necessarily just exactly matching trace type, - * if multiple trace types use the same plotting routine, they will be - * collected here. - * In order to not plot the same thing multiple times, we return two arrays, - * the calcdata we *will* plot with this module, and the ones we *won't* - * - * @param {array} calcdata: as in gd.calcdata - * @param {object|string|fn} arg1: - * the plotting module, or its name, or its plot method - * - * @return {array[array]} [foundCalcdata, remainingCalcdata] - */ -exports.getModuleCalcData = function(calcdata, arg1) { - var moduleCalcData = []; - var remainingCalcData = []; - - var plotMethod; - if(typeof arg1 === 'string') { - plotMethod = Registry.getModule(arg1).plot; - } else if(typeof arg1 === 'function') { - plotMethod = arg1; - } else { - plotMethod = arg1.plot; - } - if(!plotMethod) { - return [moduleCalcData, calcdata]; - } - - for(var i = 0; i < calcdata.length; i++) { - var cd = calcdata[i]; - var trace = cd[0].trace; - // N.B. - // - 'legendonly' traces do not make it past here - // - skip over 'visible' traces that got trimmed completely during calc transforms - if(trace.visible !== true || trace._length === 0) continue; - - // group calcdata trace not by 'module' (as the name of this function - // would suggest), but by 'module plot method' so that if some traces - // share the same module plot method (e.g. bar and histogram), we - // only call it one! - if(trace._module.plot === plotMethod) { - moduleCalcData.push(cd); - } else { - remainingCalcData.push(cd); - } - } - - return [moduleCalcData, remainingCalcData]; -}; - -/** - * Get the data trace(s) associated with a given subplot. - * - * @param {array} data plotly full data array. - * @param {string} type subplot type to look for. - * @param {string} subplotId subplot id to look for. - * - * @return {array} list of trace objects. - * - */ -exports.getSubplotData = function getSubplotData(data, type, subplotId) { - if(!Registry.subplotsRegistry[type]) return []; - - var attr = Registry.subplotsRegistry[type].attr; - var subplotData = []; - var trace, subplotX, subplotY; - - if(type === 'gl2d') { - var spmatch = subplotId.match(SUBPLOT_PATTERN); - subplotX = 'x' + spmatch[1]; - subplotY = 'y' + spmatch[2]; - } - - for(var i = 0; i < data.length; i++) { - trace = data[i]; - - if(type === 'gl2d' && Registry.traceIs(trace, 'gl2d')) { - if(trace[attr[0]] === subplotX && trace[attr[1]] === subplotY) { - subplotData.push(trace); - } - } else { - if(trace[attr] === subplotId) subplotData.push(trace); - } - } - - return subplotData; -}; - -},{"../registry":847,"./cartesian/constants":773}],803:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var mouseChange = _dereq_('mouse-change'); -var mouseWheel = _dereq_('mouse-wheel'); -var mouseOffset = _dereq_('mouse-event-offset'); -var cartesianConstants = _dereq_('../cartesian/constants'); -var hasPassive = _dereq_('has-passive-events'); - -module.exports = createCamera; - -function Camera2D(element, plot) { - this.element = element; - this.plot = plot; - this.mouseListener = null; - this.wheelListener = null; - this.lastInputTime = Date.now(); - this.lastPos = [0, 0]; - this.boxEnabled = false; - this.boxInited = false; - this.boxStart = [0, 0]; - this.boxEnd = [0, 0]; - this.dragStart = [0, 0]; -} - - -function createCamera(scene) { - var element = scene.mouseContainer; - var plot = scene.glplot; - var result = new Camera2D(element, plot); - - function unSetAutoRange() { - scene.xaxis.autorange = false; - scene.yaxis.autorange = false; - } - - function getSubplotConstraint() { - // note: this assumes we only have one x and one y axis on this subplot - // when this constraint is lifted this block won't make sense - var constraints = scene.graphDiv._fullLayout._axisConstraintGroups; - var xaId = scene.xaxis._id; - var yaId = scene.yaxis._id; - for(var i = 0; i < constraints.length; i++) { - if(constraints[i][xaId] !== -1) { - if(constraints[i][yaId] !== -1) return true; - break; - } - } - return false; - } - - result.mouseListener = mouseChange(element, handleInteraction); - - // enable simple touch interactions - element.addEventListener('touchstart', function(ev) { - var xy = mouseOffset(ev.changedTouches[0], element); - handleInteraction(0, xy[0], xy[1]); - handleInteraction(1, xy[0], xy[1]); - - ev.preventDefault(); - }, hasPassive ? {passive: false} : false); - element.addEventListener('touchmove', function(ev) { - ev.preventDefault(); - var xy = mouseOffset(ev.changedTouches[0], element); - handleInteraction(1, xy[0], xy[1]); - - ev.preventDefault(); - }, hasPassive ? {passive: false} : false); - element.addEventListener('touchend', function(ev) { - handleInteraction(0, result.lastPos[0], result.lastPos[1]); - - ev.preventDefault(); - }, hasPassive ? {passive: false} : false); - - function handleInteraction(buttons, x, y) { - var dataBox = scene.calcDataBox(); - var viewBox = plot.viewBox; - - var lastX = result.lastPos[0]; - var lastY = result.lastPos[1]; - - var MINDRAG = cartesianConstants.MINDRAG * plot.pixelRatio; - var MINZOOM = cartesianConstants.MINZOOM * plot.pixelRatio; - - var dx, dy; - - x *= plot.pixelRatio; - y *= plot.pixelRatio; - - // mouseChange gives y about top; convert to about bottom - y = (viewBox[3] - viewBox[1]) - y; - - function updateRange(i0, start, end) { - var range0 = Math.min(start, end); - var range1 = Math.max(start, end); - - if(range0 !== range1) { - dataBox[i0] = range0; - dataBox[i0 + 2] = range1; - result.dataBox = dataBox; - scene.setRanges(dataBox); - } else { - scene.selectBox.selectBox = [0, 0, 1, 1]; - scene.glplot.setDirty(); - } - } - - switch(scene.fullLayout.dragmode) { - case 'zoom': - if(buttons) { - var dataX = x / - (viewBox[2] - viewBox[0]) * (dataBox[2] - dataBox[0]) + - dataBox[0]; - var dataY = y / - (viewBox[3] - viewBox[1]) * (dataBox[3] - dataBox[1]) + - dataBox[1]; - - if(!result.boxInited) { - result.boxStart[0] = dataX; - result.boxStart[1] = dataY; - result.dragStart[0] = x; - result.dragStart[1] = y; - } - - result.boxEnd[0] = dataX; - result.boxEnd[1] = dataY; - - // we need to mark the box as initialized right away - // so that we can tell the start and end points apart - result.boxInited = true; - - // but don't actually enable the box until the cursor moves - if(!result.boxEnabled && ( - result.boxStart[0] !== result.boxEnd[0] || - result.boxStart[1] !== result.boxEnd[1]) - ) { - result.boxEnabled = true; - } - - // constrain aspect ratio if the axes require it - var smallDx = Math.abs(result.dragStart[0] - x) < MINZOOM; - var smallDy = Math.abs(result.dragStart[1] - y) < MINZOOM; - if(getSubplotConstraint() && !(smallDx && smallDy)) { - dx = result.boxEnd[0] - result.boxStart[0]; - dy = result.boxEnd[1] - result.boxStart[1]; - var dydx = (dataBox[3] - dataBox[1]) / (dataBox[2] - dataBox[0]); - - if(Math.abs(dx * dydx) > Math.abs(dy)) { - result.boxEnd[1] = result.boxStart[1] + - Math.abs(dx) * dydx * (dy >= 0 ? 1 : -1); - - // gl-select-box clips to the plot area bounds, - // which breaks the axis constraint, so don't allow - // this box to go out of bounds - if(result.boxEnd[1] < dataBox[1]) { - result.boxEnd[1] = dataBox[1]; - result.boxEnd[0] = result.boxStart[0] + - (dataBox[1] - result.boxStart[1]) / Math.abs(dydx); - } else if(result.boxEnd[1] > dataBox[3]) { - result.boxEnd[1] = dataBox[3]; - result.boxEnd[0] = result.boxStart[0] + - (dataBox[3] - result.boxStart[1]) / Math.abs(dydx); - } - } else { - result.boxEnd[0] = result.boxStart[0] + - Math.abs(dy) / dydx * (dx >= 0 ? 1 : -1); - - if(result.boxEnd[0] < dataBox[0]) { - result.boxEnd[0] = dataBox[0]; - result.boxEnd[1] = result.boxStart[1] + - (dataBox[0] - result.boxStart[0]) * Math.abs(dydx); - } else if(result.boxEnd[0] > dataBox[2]) { - result.boxEnd[0] = dataBox[2]; - result.boxEnd[1] = result.boxStart[1] + - (dataBox[2] - result.boxStart[0]) * Math.abs(dydx); - } - } - } else { - // otherwise clamp small changes to the origin so we get 1D zoom - - if(smallDx) result.boxEnd[0] = result.boxStart[0]; - if(smallDy) result.boxEnd[1] = result.boxStart[1]; - } - } else if(result.boxEnabled) { - dx = result.boxStart[0] !== result.boxEnd[0]; - dy = result.boxStart[1] !== result.boxEnd[1]; - if(dx || dy) { - if(dx) { - updateRange(0, result.boxStart[0], result.boxEnd[0]); - scene.xaxis.autorange = false; - } - if(dy) { - updateRange(1, result.boxStart[1], result.boxEnd[1]); - scene.yaxis.autorange = false; - } - scene.relayoutCallback(); - } else { - scene.glplot.setDirty(); - } - result.boxEnabled = false; - result.boxInited = false; - } else if(result.boxInited) { - // if box was inited but button released then - reset the box - - result.boxInited = false; - } - break; - - case 'pan': - result.boxEnabled = false; - result.boxInited = false; - - if(buttons) { - if(!result.panning) { - result.dragStart[0] = x; - result.dragStart[1] = y; - } - - if(Math.abs(result.dragStart[0] - x) < MINDRAG) x = result.dragStart[0]; - if(Math.abs(result.dragStart[1] - y) < MINDRAG) y = result.dragStart[1]; - - dx = (lastX - x) * (dataBox[2] - dataBox[0]) / - (plot.viewBox[2] - plot.viewBox[0]); - dy = (lastY - y) * (dataBox[3] - dataBox[1]) / - (plot.viewBox[3] - plot.viewBox[1]); - - dataBox[0] += dx; - dataBox[2] += dx; - dataBox[1] += dy; - dataBox[3] += dy; - - scene.setRanges(dataBox); - - result.panning = true; - result.lastInputTime = Date.now(); - unSetAutoRange(); - scene.cameraChanged(); - scene.handleAnnotations(); - } else if(result.panning) { - result.panning = false; - scene.relayoutCallback(); - } - break; - } - - result.lastPos[0] = x; - result.lastPos[1] = y; - } - - result.wheelListener = mouseWheel(element, function(dx, dy) { - if(!scene.scrollZoom) return false; - - var dataBox = scene.calcDataBox(); - var viewBox = plot.viewBox; - - var lastX = result.lastPos[0]; - var lastY = result.lastPos[1]; - - var scale = Math.exp(5.0 * dy / (viewBox[3] - viewBox[1])); - - var cx = lastX / - (viewBox[2] - viewBox[0]) * (dataBox[2] - dataBox[0]) + - dataBox[0]; - var cy = lastY / - (viewBox[3] - viewBox[1]) * (dataBox[3] - dataBox[1]) + - dataBox[1]; - - dataBox[0] = (dataBox[0] - cx) * scale + cx; - dataBox[2] = (dataBox[2] - cx) * scale + cx; - dataBox[1] = (dataBox[1] - cy) * scale + cy; - dataBox[3] = (dataBox[3] - cy) * scale + cy; - - scene.setRanges(dataBox); - - result.lastInputTime = Date.now(); - unSetAutoRange(); - scene.cameraChanged(); - scene.handleAnnotations(); - scene.relayoutCallback(); - - return true; - }, true); - - return result; -} - -},{"../cartesian/constants":773,"has-passive-events":411,"mouse-change":435,"mouse-event-offset":436,"mouse-wheel":438}],804:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Axes = _dereq_('../cartesian/axes'); - -var str2RGBArray = _dereq_('../../lib/str2rgbarray'); - -function Axes2DOptions(scene) { - this.scene = scene; - this.gl = scene.gl; - this.pixelRatio = scene.pixelRatio; - - this.screenBox = [0, 0, 1, 1]; - this.viewBox = [0, 0, 1, 1]; - this.dataBox = [-1, -1, 1, 1]; - - this.borderLineEnable = [false, false, false, false]; - this.borderLineWidth = [1, 1, 1, 1]; - this.borderLineColor = [ - [0, 0, 0, 1], - [0, 0, 0, 1], - [0, 0, 0, 1], - [0, 0, 0, 1] - ]; - - this.ticks = [[], []]; - this.tickEnable = [true, true, false, false]; - this.tickPad = [15, 15, 15, 15]; - this.tickAngle = [0, 0, 0, 0]; - this.tickColor = [ - [0, 0, 0, 1], - [0, 0, 0, 1], - [0, 0, 0, 1], - [0, 0, 0, 1] - ]; - this.tickMarkLength = [0, 0, 0, 0]; - this.tickMarkWidth = [0, 0, 0, 0]; - this.tickMarkColor = [ - [0, 0, 0, 1], - [0, 0, 0, 1], - [0, 0, 0, 1], - [0, 0, 0, 1] - ]; - - this.labels = ['x', 'y']; - this.labelEnable = [true, true, false, false]; - this.labelAngle = [0, Math.PI / 2, 0, 3.0 * Math.PI / 2]; - this.labelPad = [15, 15, 15, 15]; - this.labelSize = [12, 12]; - this.labelFont = ['sans-serif', 'sans-serif']; - this.labelColor = [ - [0, 0, 0, 1], - [0, 0, 0, 1], - [0, 0, 0, 1], - [0, 0, 0, 1] - ]; - - this.title = ''; - this.titleEnable = true; - this.titleCenter = [0, 0, 0, 0]; - this.titleAngle = 0; - this.titleColor = [0, 0, 0, 1]; - this.titleFont = 'sans-serif'; - this.titleSize = 18; - - this.gridLineEnable = [true, true]; - this.gridLineColor = [ - [0, 0, 0, 0.5], - [0, 0, 0, 0.5] - ]; - this.gridLineWidth = [1, 1]; - - this.zeroLineEnable = [true, true]; - this.zeroLineWidth = [1, 1]; - this.zeroLineColor = [ - [0, 0, 0, 1], - [0, 0, 0, 1] - ]; - - this.borderColor = [0, 0, 0, 0]; - this.backgroundColor = [0, 0, 0, 0]; - - this.static = this.scene.staticPlot; -} - -var proto = Axes2DOptions.prototype; - -var AXES = ['xaxis', 'yaxis']; - -proto.merge = function(options) { - // titles are rendered in SVG - this.titleEnable = false; - this.backgroundColor = str2RGBArray(options.plot_bgcolor); - - var axisName, ax, axTitle, axMirror; - var hasAxisInDfltPos, hasAxisInAltrPos, hasSharedAxis, mirrorLines, mirrorTicks; - var i, j; - - for(i = 0; i < 2; ++i) { - axisName = AXES[i]; - var axisLetter = axisName.charAt(0); - - // get options relevant to this subplot, - // '_name' is e.g. xaxis, xaxis2, yaxis, yaxis4 ... - ax = options[this.scene[axisName]._name]; - - axTitle = ax.title.text === this.scene.fullLayout._dfltTitle[axisLetter] ? '' : ax.title.text; - - for(j = 0; j <= 2; j += 2) { - this.labelEnable[i + j] = false; - this.labels[i + j] = axTitle; - this.labelColor[i + j] = str2RGBArray(ax.title.font.color); - this.labelFont[i + j] = ax.title.font.family; - this.labelSize[i + j] = ax.title.font.size; - this.labelPad[i + j] = this.getLabelPad(axisName, ax); - - this.tickEnable[i + j] = false; - this.tickColor[i + j] = str2RGBArray((ax.tickfont || {}).color); - this.tickAngle[i + j] = (ax.tickangle === 'auto') ? - 0 : - Math.PI * -ax.tickangle / 180; - this.tickPad[i + j] = this.getTickPad(ax); - - this.tickMarkLength[i + j] = 0; - this.tickMarkWidth[i + j] = ax.tickwidth || 0; - this.tickMarkColor[i + j] = str2RGBArray(ax.tickcolor); - - this.borderLineEnable[i + j] = false; - this.borderLineColor[i + j] = str2RGBArray(ax.linecolor); - this.borderLineWidth[i + j] = ax.linewidth || 0; - } - - hasSharedAxis = this.hasSharedAxis(ax); - hasAxisInDfltPos = this.hasAxisInDfltPos(axisName, ax) && !hasSharedAxis; - hasAxisInAltrPos = this.hasAxisInAltrPos(axisName, ax) && !hasSharedAxis; - - axMirror = ax.mirror || false; - mirrorLines = hasSharedAxis ? - (String(axMirror).indexOf('all') !== -1) : // 'all' or 'allticks' - !!axMirror; // all but false - mirrorTicks = hasSharedAxis ? - (axMirror === 'allticks') : - (String(axMirror).indexOf('ticks') !== -1); // 'ticks' or 'allticks' - - // Axis titles and tick labels can only appear of one side of the scene - // and are never show on subplots that share existing axes. - - if(hasAxisInDfltPos) this.labelEnable[i] = true; - else if(hasAxisInAltrPos) this.labelEnable[i + 2] = true; - - if(hasAxisInDfltPos) this.tickEnable[i] = ax.showticklabels; - else if(hasAxisInAltrPos) this.tickEnable[i + 2] = ax.showticklabels; - - // Grid lines and ticks can appear on both sides of the scene - // and can appear on subplot that share existing axes via `ax.mirror`. - - if(hasAxisInDfltPos || mirrorLines) this.borderLineEnable[i] = ax.showline; - if(hasAxisInAltrPos || mirrorLines) this.borderLineEnable[i + 2] = ax.showline; - - if(hasAxisInDfltPos || mirrorTicks) this.tickMarkLength[i] = this.getTickMarkLength(ax); - if(hasAxisInAltrPos || mirrorTicks) this.tickMarkLength[i + 2] = this.getTickMarkLength(ax); - - this.gridLineEnable[i] = ax.showgrid; - this.gridLineColor[i] = str2RGBArray(ax.gridcolor); - this.gridLineWidth[i] = ax.gridwidth; - - this.zeroLineEnable[i] = ax.zeroline; - this.zeroLineColor[i] = str2RGBArray(ax.zerolinecolor); - this.zeroLineWidth[i] = ax.zerolinewidth; - } -}; - -// is an axis shared with an already-drawn subplot ? -proto.hasSharedAxis = function(ax) { - var scene = this.scene; - var subplotIds = scene.fullLayout._subplots.gl2d; - var list = Axes.findSubplotsWithAxis(subplotIds, ax); - - // if index === 0, then the subplot is already drawn as subplots - // are drawn in order. - return (list.indexOf(scene.id) !== 0); -}; - -// has an axis in default position (i.e. bottom/left) ? -proto.hasAxisInDfltPos = function(axisName, ax) { - var axSide = ax.side; - - if(axisName === 'xaxis') return (axSide === 'bottom'); - else if(axisName === 'yaxis') return (axSide === 'left'); -}; - -// has an axis in alternate position (i.e. top/right) ? -proto.hasAxisInAltrPos = function(axisName, ax) { - var axSide = ax.side; - - if(axisName === 'xaxis') return (axSide === 'top'); - else if(axisName === 'yaxis') return (axSide === 'right'); -}; - -proto.getLabelPad = function(axisName, ax) { - var offsetBase = 1.5; - var fontSize = ax.title.font.size; - var showticklabels = ax.showticklabels; - - if(axisName === 'xaxis') { - return (ax.side === 'top') ? - -10 + fontSize * (offsetBase + (showticklabels ? 1 : 0)) : - -10 + fontSize * (offsetBase + (showticklabels ? 0.5 : 0)); - } else if(axisName === 'yaxis') { - return (ax.side === 'right') ? - 10 + fontSize * (offsetBase + (showticklabels ? 1 : 0.5)) : - 10 + fontSize * (offsetBase + (showticklabels ? 0.5 : 0)); - } -}; - -proto.getTickPad = function(ax) { - return (ax.ticks === 'outside') ? 10 + ax.ticklen : 15; -}; - -proto.getTickMarkLength = function(ax) { - if(!ax.ticks) return 0; - - var ticklen = ax.ticklen; - - return (ax.ticks === 'inside') ? -ticklen : ticklen; -}; - - -function createAxes2D(scene) { - return new Axes2DOptions(scene); -} - -module.exports = createAxes2D; - -},{"../../lib/str2rgbarray":742,"../cartesian/axes":767}],805:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var Scene2D = _dereq_('./scene2d'); -var layoutGlobalAttrs = _dereq_('../layout_attributes'); -var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); -var constants = _dereq_('../cartesian/constants'); -var Cartesian = _dereq_('../cartesian'); -var fxAttrs = _dereq_('../../components/fx/layout_attributes'); -var getSubplotData = _dereq_('../get_data').getSubplotData; - -exports.name = 'gl2d'; - -exports.attr = ['xaxis', 'yaxis']; - -exports.idRoot = ['x', 'y']; - -exports.idRegex = constants.idRegex; - -exports.attrRegex = constants.attrRegex; - -exports.attributes = _dereq_('../cartesian/attributes'); - -exports.supplyLayoutDefaults = function(layoutIn, layoutOut, fullData) { - if(!layoutOut._has('cartesian')) { - Cartesian.supplyLayoutDefaults(layoutIn, layoutOut, fullData); - } -}; - -// gl2d uses svg axis attributes verbatim, but overrides editType -// this could potentially be just `layoutAttributes` but it would -// still need special handling somewhere to give it precedence over -// the svg version when both are in use on one plot -exports.layoutAttrOverrides = overrideAll(Cartesian.layoutAttributes, 'plot', 'from-root'); - -// similar overrides for base plot attributes (and those added by components) -exports.baseLayoutAttrOverrides = overrideAll({ - plot_bgcolor: layoutGlobalAttrs.plot_bgcolor, - hoverlabel: fxAttrs.hoverlabel - // dragmode needs calc but only when transitioning TO lasso or select - // so for now it's left inside _relayout - // dragmode: fxAttrs.dragmode -}, 'plot', 'nested'); - -exports.plot = function plot(gd) { - var fullLayout = gd._fullLayout; - var fullData = gd._fullData; - var subplotIds = fullLayout._subplots.gl2d; - - for(var i = 0; i < subplotIds.length; i++) { - var subplotId = subplotIds[i]; - var subplotObj = fullLayout._plots[subplotId]; - var fullSubplotData = getSubplotData(fullData, 'gl2d', subplotId); - - // ref. to corresp. Scene instance - var scene = subplotObj._scene2d; - - // If Scene is not instantiated, create one! - if(scene === undefined) { - scene = new Scene2D({ - id: subplotId, - graphDiv: gd, - container: gd.querySelector('.gl-container'), - staticPlot: gd._context.staticPlot, - plotGlPixelRatio: gd._context.plotGlPixelRatio - }, - fullLayout - ); - - // set ref to Scene instance - subplotObj._scene2d = scene; - } - - scene.plot(fullSubplotData, gd.calcdata, fullLayout, gd.layout); - } -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var oldSceneKeys = oldFullLayout._subplots.gl2d || []; - - for(var i = 0; i < oldSceneKeys.length; i++) { - var id = oldSceneKeys[i]; - var oldSubplot = oldFullLayout._plots[id]; - - // old subplot wasn't gl2d; nothing to do - if(!oldSubplot._scene2d) continue; - - // if no traces are present, delete gl2d subplot - var subplotData = getSubplotData(newFullData, 'gl2d', id); - if(subplotData.length === 0) { - oldSubplot._scene2d.destroy(); - delete oldFullLayout._plots[id]; - } - } - - // since we use cartesian interactions, do cartesian clean - Cartesian.clean.apply(this, arguments); -}; - -exports.drawFramework = function(gd) { - if(!gd._context.staticPlot) { - Cartesian.drawFramework(gd); - } -}; - -exports.toSVG = function(gd) { - var fullLayout = gd._fullLayout; - var subplotIds = fullLayout._subplots.gl2d; - - for(var i = 0; i < subplotIds.length; i++) { - var subplot = fullLayout._plots[subplotIds[i]]; - var scene = subplot._scene2d; - - var imageData = scene.toImage('png'); - var image = fullLayout._glimages.append('svg:image'); - - image.attr({ - xmlns: xmlnsNamespaces.svg, - 'xlink:href': imageData, - x: 0, - y: 0, - width: '100%', - height: '100%', - preserveAspectRatio: 'none' - }); - - scene.destroy(); - } -}; - -exports.updateFx = function(gd) { - var fullLayout = gd._fullLayout; - var subplotIds = fullLayout._subplots.gl2d; - - for(var i = 0; i < subplotIds.length; i++) { - var subplotObj = fullLayout._plots[subplotIds[i]]._scene2d; - subplotObj.updateFx(fullLayout.dragmode); - } -}; - -},{"../../components/fx/layout_attributes":633,"../../constants/xmlns_namespaces":696,"../../plot_api/edit_types":750,"../cartesian":778,"../cartesian/attributes":765,"../cartesian/constants":773,"../get_data":802,"../layout_attributes":819,"./scene2d":806}],806:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var Fx = _dereq_('../../components/fx'); - -var createPlot2D = _dereq_('gl-plot2d'); -var createSpikes = _dereq_('gl-spikes2d'); -var createSelectBox = _dereq_('gl-select-box'); -var getContext = _dereq_('webgl-context'); - -var createOptions = _dereq_('./convert'); -var createCamera = _dereq_('./camera'); -var showNoWebGlMsg = _dereq_('../../lib/show_no_webgl_msg'); -var axisConstraints = _dereq_('../cartesian/constraints'); -var enforceAxisConstraints = axisConstraints.enforce; -var cleanAxisConstraints = axisConstraints.clean; -var doAutoRange = _dereq_('../cartesian/autorange').doAutoRange; - -var AXES = ['xaxis', 'yaxis']; -var STATIC_CANVAS, STATIC_CONTEXT; - -var SUBPLOT_PATTERN = _dereq_('../cartesian/constants').SUBPLOT_PATTERN; - - -function Scene2D(options, fullLayout) { - this.container = options.container; - this.graphDiv = options.graphDiv; - this.pixelRatio = options.plotGlPixelRatio || window.devicePixelRatio; - this.id = options.id; - this.staticPlot = !!options.staticPlot; - this.scrollZoom = this.graphDiv._context._scrollZoom.cartesian; - - this.fullData = null; - this.updateRefs(fullLayout); - - this.makeFramework(); - if(this.stopped) return; - - // update options - this.glplotOptions = createOptions(this); - this.glplotOptions.merge(fullLayout); - - // create the plot - this.glplot = createPlot2D(this.glplotOptions); - - // create camera - this.camera = createCamera(this); - - // trace set - this.traces = {}; - - // create axes spikes - this.spikes = createSpikes(this.glplot); - - this.selectBox = createSelectBox(this.glplot, { - innerFill: false, - outerFill: true - }); - - // last button state - this.lastButtonState = 0; - - // last pick result - this.pickResult = null; - - // is the mouse over the plot? - // it's OK if this says true when it's not, so long as - // when we get a mouseout we set it to false before handling - this.isMouseOver = true; - - // flag to stop render loop - this.stopped = false; - - // redraw the plot - this.redraw = this.draw.bind(this); - this.redraw(); -} - -module.exports = Scene2D; - -var proto = Scene2D.prototype; - -proto.makeFramework = function() { - // create canvas and gl context - if(this.staticPlot) { - if(!STATIC_CONTEXT) { - STATIC_CANVAS = document.createElement('canvas'); - - STATIC_CONTEXT = getContext({ - canvas: STATIC_CANVAS, - preserveDrawingBuffer: false, - premultipliedAlpha: true, - antialias: true - }); - - if(!STATIC_CONTEXT) { - throw new Error('Error creating static canvas/context for image server'); - } - } - - this.canvas = STATIC_CANVAS; - this.gl = STATIC_CONTEXT; - } else { - var liveCanvas = this.container.querySelector('.gl-canvas-focus'); - - var gl = getContext({ - canvas: liveCanvas, - preserveDrawingBuffer: true, - premultipliedAlpha: true - }); - - if(!gl) { - showNoWebGlMsg(this); - this.stopped = true; - return; - } - - this.canvas = liveCanvas; - this.gl = gl; - } - - // position the canvas - var canvas = this.canvas; - - canvas.style.width = '100%'; - canvas.style.height = '100%'; - canvas.style.position = 'absolute'; - canvas.style.top = '0px'; - canvas.style.left = '0px'; - canvas.style['pointer-events'] = 'none'; - - this.updateSize(canvas); - - // disabling user select on the canvas - // sanitizes double-clicks interactions - // ref: https://github.com/plotly/plotly.js/issues/744 - canvas.className += ' user-select-none'; - - // create SVG container for hover text - var svgContainer = this.svgContainer = document.createElementNS( - 'http://www.w3.org/2000/svg', - 'svg'); - svgContainer.style.position = 'absolute'; - svgContainer.style.top = svgContainer.style.left = '0px'; - svgContainer.style.width = svgContainer.style.height = '100%'; - svgContainer.style['z-index'] = 20; - svgContainer.style['pointer-events'] = 'none'; - - // create div to catch the mouse event - var mouseContainer = this.mouseContainer = document.createElement('div'); - mouseContainer.style.position = 'absolute'; - mouseContainer.style['pointer-events'] = 'auto'; - - this.pickCanvas = this.container.querySelector('.gl-canvas-pick'); - - - // append canvas, hover svg and mouse div to container - var container = this.container; - container.appendChild(svgContainer); - container.appendChild(mouseContainer); - - var self = this; - mouseContainer.addEventListener('mouseout', function() { - self.isMouseOver = false; - self.unhover(); - }); - mouseContainer.addEventListener('mouseover', function() { - self.isMouseOver = true; - }); -}; - -proto.toImage = function(format) { - if(!format) format = 'png'; - - this.stopped = true; - - if(this.staticPlot) this.container.appendChild(STATIC_CANVAS); - - // update canvas size - this.updateSize(this.canvas); - - - // grab context and yank out pixels - var gl = this.glplot.gl; - var w = gl.drawingBufferWidth; - var h = gl.drawingBufferHeight; - - // force redraw - gl.clearColor(1, 1, 1, 0); - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - this.glplot.setDirty(); - this.glplot.draw(); - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var pixels = new Uint8Array(w * h * 4); - gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels); - - // flip pixels - for(var j = 0, k = h - 1; j < k; ++j, --k) { - for(var i = 0; i < w; ++i) { - for(var l = 0; l < 4; ++l) { - var tmp = pixels[4 * (w * j + i) + l]; - pixels[4 * (w * j + i) + l] = pixels[4 * (w * k + i) + l]; - pixels[4 * (w * k + i) + l] = tmp; - } - } - } - - var canvas = document.createElement('canvas'); - canvas.width = w; - canvas.height = h; - - var context = canvas.getContext('2d'); - var imageData = context.createImageData(w, h); - imageData.data.set(pixels); - context.putImageData(imageData, 0, 0); - - var dataURL; - - switch(format) { - case 'jpeg': - dataURL = canvas.toDataURL('image/jpeg'); - break; - case 'webp': - dataURL = canvas.toDataURL('image/webp'); - break; - default: - dataURL = canvas.toDataURL('image/png'); - } - - if(this.staticPlot) this.container.removeChild(STATIC_CANVAS); - - return dataURL; -}; - -proto.updateSize = function(canvas) { - if(!canvas) canvas = this.canvas; - - var pixelRatio = this.pixelRatio; - var fullLayout = this.fullLayout; - - var width = fullLayout.width; - var height = fullLayout.height; - var pixelWidth = Math.ceil(pixelRatio * width) |0; - var pixelHeight = Math.ceil(pixelRatio * height) |0; - - // check for resize - if(canvas.width !== pixelWidth || canvas.height !== pixelHeight) { - canvas.width = pixelWidth; - canvas.height = pixelHeight; - } - - return canvas; -}; - -proto.computeTickMarks = function() { - this.xaxis.setScale(); - this.yaxis.setScale(); - - var nextTicks = [ - Axes.calcTicks(this.xaxis), - Axes.calcTicks(this.yaxis) - ]; - - for(var j = 0; j < 2; ++j) { - for(var i = 0; i < nextTicks[j].length; ++i) { - // coercing tick value (may not be a string) to a string - nextTicks[j][i].text = nextTicks[j][i].text + ''; - } - } - - return nextTicks; -}; - -function compareTicks(a, b) { - for(var i = 0; i < 2; ++i) { - var aticks = a[i]; - var bticks = b[i]; - - if(aticks.length !== bticks.length) return true; - - for(var j = 0; j < aticks.length; ++j) { - if(aticks[j].x !== bticks[j].x) return true; - } - } - - return false; -} - -proto.updateRefs = function(newFullLayout) { - this.fullLayout = newFullLayout; - - var spmatch = this.id.match(SUBPLOT_PATTERN); - var xaxisName = 'xaxis' + spmatch[1]; - var yaxisName = 'yaxis' + spmatch[2]; - - this.xaxis = this.fullLayout[xaxisName]; - this.yaxis = this.fullLayout[yaxisName]; -}; - -proto.relayoutCallback = function() { - var graphDiv = this.graphDiv; - var xaxis = this.xaxis; - var yaxis = this.yaxis; - var layout = graphDiv.layout; - - // make a meaningful value to be passed on to possible 'plotly_relayout' subscriber(s) - var update = {}; - var xrange = update[xaxis._name + '.range'] = xaxis.range.slice(); - var yrange = update[yaxis._name + '.range'] = yaxis.range.slice(); - update[xaxis._name + '.autorange'] = xaxis.autorange; - update[yaxis._name + '.autorange'] = yaxis.autorange; - - Registry.call('_storeDirectGUIEdit', graphDiv.layout, graphDiv._fullLayout._preGUI, update); - - // update the input layout - var xaIn = layout[xaxis._name]; - xaIn.range = xrange; - xaIn.autorange = xaxis.autorange; - - var yaIn = layout[yaxis._name]; - yaIn.range = yrange; - yaIn.autorange = yaxis.autorange; - - // lastInputTime helps determine which one is the latest input (if async) - update.lastInputTime = this.camera.lastInputTime; - graphDiv.emit('plotly_relayout', update); -}; - -proto.cameraChanged = function() { - var camera = this.camera; - - this.glplot.setDataBox(this.calcDataBox()); - - var nextTicks = this.computeTickMarks(); - var curTicks = this.glplotOptions.ticks; - - if(compareTicks(nextTicks, curTicks)) { - this.glplotOptions.ticks = nextTicks; - this.glplotOptions.dataBox = camera.dataBox; - this.glplot.update(this.glplotOptions); - this.handleAnnotations(); - } -}; - -proto.handleAnnotations = function() { - var gd = this.graphDiv; - var annotations = this.fullLayout.annotations; - - for(var i = 0; i < annotations.length; i++) { - var ann = annotations[i]; - - if(ann.xref === this.xaxis._id && ann.yref === this.yaxis._id) { - Registry.getComponentMethod('annotations', 'drawOne')(gd, i); - } - } -}; - -proto.destroy = function() { - if(!this.glplot) return; - - var traces = this.traces; - - if(traces) { - Object.keys(traces).map(function(key) { - traces[key].dispose(); - delete traces[key]; - }); - } - - this.glplot.dispose(); - - this.container.removeChild(this.svgContainer); - this.container.removeChild(this.mouseContainer); - - this.fullData = null; - this.glplot = null; - this.stopped = true; - this.camera.mouseListener.enabled = false; - this.mouseContainer.removeEventListener('wheel', this.camera.wheelListener); - this.camera = null; -}; - -proto.plot = function(fullData, calcData, fullLayout) { - var glplot = this.glplot; - - this.updateRefs(fullLayout); - this.xaxis.clearCalc(); - this.yaxis.clearCalc(); - this.updateTraces(fullData, calcData); - this.updateFx(fullLayout.dragmode); - - var width = fullLayout.width; - var height = fullLayout.height; - - this.updateSize(this.canvas); - - var options = this.glplotOptions; - options.merge(fullLayout); - options.screenBox = [0, 0, width, height]; - - var mockGraphDiv = {_fullLayout: { - _axisConstraintGroups: this.graphDiv._fullLayout._axisConstraintGroups, - xaxis: this.xaxis, - yaxis: this.yaxis - }}; - - cleanAxisConstraints(mockGraphDiv, this.xaxis); - cleanAxisConstraints(mockGraphDiv, this.yaxis); - - var size = fullLayout._size; - var domainX = this.xaxis.domain; - var domainY = this.yaxis.domain; - - options.viewBox = [ - size.l + domainX[0] * size.w, - size.b + domainY[0] * size.h, - (width - size.r) - (1 - domainX[1]) * size.w, - (height - size.t) - (1 - domainY[1]) * size.h - ]; - - this.mouseContainer.style.width = size.w * (domainX[1] - domainX[0]) + 'px'; - this.mouseContainer.style.height = size.h * (domainY[1] - domainY[0]) + 'px'; - this.mouseContainer.height = size.h * (domainY[1] - domainY[0]); - this.mouseContainer.style.left = size.l + domainX[0] * size.w + 'px'; - this.mouseContainer.style.top = size.t + (1 - domainY[1]) * size.h + 'px'; - - var ax, i; - - for(i = 0; i < 2; ++i) { - ax = this[AXES[i]]; - ax._length = options.viewBox[i + 2] - options.viewBox[i]; - - doAutoRange(this.graphDiv, ax); - ax.setScale(); - } - - enforceAxisConstraints(mockGraphDiv); - - options.ticks = this.computeTickMarks(); - - options.dataBox = this.calcDataBox(); - - options.merge(fullLayout); - glplot.update(options); - - // force redraw so that promise is returned when rendering is completed - this.glplot.draw(); -}; - -proto.calcDataBox = function() { - var xaxis = this.xaxis; - var yaxis = this.yaxis; - var xrange = xaxis.range; - var yrange = yaxis.range; - var xr2l = xaxis.r2l; - var yr2l = yaxis.r2l; - - return [xr2l(xrange[0]), yr2l(yrange[0]), xr2l(xrange[1]), yr2l(yrange[1])]; -}; - -proto.setRanges = function(dataBox) { - var xaxis = this.xaxis; - var yaxis = this.yaxis; - var xl2r = xaxis.l2r; - var yl2r = yaxis.l2r; - - xaxis.range = [xl2r(dataBox[0]), xl2r(dataBox[2])]; - yaxis.range = [yl2r(dataBox[1]), yl2r(dataBox[3])]; -}; - -proto.updateTraces = function(fullData, calcData) { - var traceIds = Object.keys(this.traces); - var i, j, fullTrace; - - this.fullData = fullData; - - // remove empty traces - traceIdLoop: - for(i = 0; i < traceIds.length; i++) { - var oldUid = traceIds[i]; - var oldTrace = this.traces[oldUid]; - - for(j = 0; j < fullData.length; j++) { - fullTrace = fullData[j]; - - if(fullTrace.uid === oldUid && fullTrace.type === oldTrace.type) { - continue traceIdLoop; - } - } - - oldTrace.dispose(); - delete this.traces[oldUid]; - } - - // update / create trace objects - for(i = 0; i < fullData.length; i++) { - fullTrace = fullData[i]; - var calcTrace = calcData[i]; - var traceObj = this.traces[fullTrace.uid]; - - if(traceObj) traceObj.update(fullTrace, calcTrace); - else { - traceObj = fullTrace._module.plot(this, fullTrace, calcTrace); - this.traces[fullTrace.uid] = traceObj; - } - } - - // order object per traces - this.glplot.objects.sort(function(a, b) { - return a._trace.index - b._trace.index; - }); -}; - -proto.updateFx = function(dragmode) { - // switch to svg interactions in lasso/select mode - if(dragmode === 'lasso' || dragmode === 'select') { - this.pickCanvas.style['pointer-events'] = 'none'; - this.mouseContainer.style['pointer-events'] = 'none'; - } else { - this.pickCanvas.style['pointer-events'] = 'auto'; - this.mouseContainer.style['pointer-events'] = 'auto'; - } - - // set proper cursor - if(dragmode === 'pan') { - this.mouseContainer.style.cursor = 'move'; - } else if(dragmode === 'zoom') { - this.mouseContainer.style.cursor = 'crosshair'; - } else { - this.mouseContainer.style.cursor = null; - } -}; - -proto.emitPointAction = function(nextSelection, eventType) { - var uid = nextSelection.trace.uid; - var ptNumber = nextSelection.pointIndex; - var trace; - - for(var i = 0; i < this.fullData.length; i++) { - if(this.fullData[i].uid === uid) { - trace = this.fullData[i]; - } - } - - var pointData = { - x: nextSelection.traceCoord[0], - y: nextSelection.traceCoord[1], - curveNumber: trace.index, - pointNumber: ptNumber, - data: trace._input, - fullData: this.fullData, - xaxis: this.xaxis, - yaxis: this.yaxis - }; - - Fx.appendArrayPointValue(pointData, trace, ptNumber); - - this.graphDiv.emit(eventType, {points: [pointData]}); -}; - -proto.draw = function() { - if(this.stopped) return; - - requestAnimationFrame(this.redraw); - - var glplot = this.glplot; - var camera = this.camera; - var mouseListener = camera.mouseListener; - var mouseUp = this.lastButtonState === 1 && mouseListener.buttons === 0; - var fullLayout = this.fullLayout; - - this.lastButtonState = mouseListener.buttons; - - this.cameraChanged(); - - var x = mouseListener.x * glplot.pixelRatio; - var y = this.canvas.height - glplot.pixelRatio * mouseListener.y; - - var result; - - if(camera.boxEnabled && fullLayout.dragmode === 'zoom') { - this.selectBox.enabled = true; - - var selectBox = this.selectBox.selectBox = [ - Math.min(camera.boxStart[0], camera.boxEnd[0]), - Math.min(camera.boxStart[1], camera.boxEnd[1]), - Math.max(camera.boxStart[0], camera.boxEnd[0]), - Math.max(camera.boxStart[1], camera.boxEnd[1]) - ]; - - // 1D zoom - for(var i = 0; i < 2; i++) { - if(camera.boxStart[i] === camera.boxEnd[i]) { - selectBox[i] = glplot.dataBox[i]; - selectBox[i + 2] = glplot.dataBox[i + 2]; - } - } - - glplot.setDirty(); - } else if(!camera.panning && this.isMouseOver) { - this.selectBox.enabled = false; - - var size = fullLayout._size; - var domainX = this.xaxis.domain; - var domainY = this.yaxis.domain; - - result = glplot.pick( - (x / glplot.pixelRatio) + size.l + domainX[0] * size.w, - (y / glplot.pixelRatio) - (size.t + (1 - domainY[1]) * size.h) - ); - - var nextSelection = result && result.object._trace.handlePick(result); - - if(nextSelection && mouseUp) { - this.emitPointAction(nextSelection, 'plotly_click'); - } - - if(result && result.object._trace.hoverinfo !== 'skip' && fullLayout.hovermode) { - if(nextSelection && ( - !this.lastPickResult || - this.lastPickResult.traceUid !== nextSelection.trace.uid || - this.lastPickResult.dataCoord[0] !== nextSelection.dataCoord[0] || - this.lastPickResult.dataCoord[1] !== nextSelection.dataCoord[1]) - ) { - var selection = nextSelection; - - this.lastPickResult = { - traceUid: nextSelection.trace ? nextSelection.trace.uid : null, - dataCoord: nextSelection.dataCoord.slice() - }; - this.spikes.update({ center: result.dataCoord }); - - selection.screenCoord = [ - ((glplot.viewBox[2] - glplot.viewBox[0]) * - (result.dataCoord[0] - glplot.dataBox[0]) / - (glplot.dataBox[2] - glplot.dataBox[0]) + glplot.viewBox[0]) / - glplot.pixelRatio, - (this.canvas.height - (glplot.viewBox[3] - glplot.viewBox[1]) * - (result.dataCoord[1] - glplot.dataBox[1]) / - (glplot.dataBox[3] - glplot.dataBox[1]) - glplot.viewBox[1]) / - glplot.pixelRatio - ]; - - // this needs to happen before the next block that deletes traceCoord data - // also it's important to copy, otherwise data is lost by the time event data is read - this.emitPointAction(nextSelection, 'plotly_hover'); - - var trace = this.fullData[selection.trace.index] || {}; - var ptNumber = selection.pointIndex; - var hoverinfo = Fx.castHoverinfo(trace, fullLayout, ptNumber); - - if(hoverinfo && hoverinfo !== 'all') { - var parts = hoverinfo.split('+'); - if(parts.indexOf('x') === -1) selection.traceCoord[0] = undefined; - if(parts.indexOf('y') === -1) selection.traceCoord[1] = undefined; - if(parts.indexOf('z') === -1) selection.traceCoord[2] = undefined; - if(parts.indexOf('text') === -1) selection.textLabel = undefined; - if(parts.indexOf('name') === -1) selection.name = undefined; - } - - Fx.loneHover({ - x: selection.screenCoord[0], - y: selection.screenCoord[1], - xLabel: this.hoverFormatter('xaxis', selection.traceCoord[0]), - yLabel: this.hoverFormatter('yaxis', selection.traceCoord[1]), - zLabel: selection.traceCoord[2], - text: selection.textLabel, - name: selection.name, - color: Fx.castHoverOption(trace, ptNumber, 'bgcolor') || selection.color, - borderColor: Fx.castHoverOption(trace, ptNumber, 'bordercolor'), - fontFamily: Fx.castHoverOption(trace, ptNumber, 'font.family'), - fontSize: Fx.castHoverOption(trace, ptNumber, 'font.size'), - fontColor: Fx.castHoverOption(trace, ptNumber, 'font.color'), - nameLength: Fx.castHoverOption(trace, ptNumber, 'namelength'), - textAlign: Fx.castHoverOption(trace, ptNumber, 'align') - }, { - container: this.svgContainer, - gd: this.graphDiv - }); - } - } - } - - // Remove hover effects if we're not over a point OR - // if we're zooming or panning (in which case result is not set) - if(!result) { - this.unhover(); - } - - glplot.draw(); -}; - -proto.unhover = function() { - if(this.lastPickResult) { - this.spikes.update({}); - this.lastPickResult = null; - this.graphDiv.emit('plotly_unhover'); - Fx.loneUnhover(this.svgContainer); - } -}; - -proto.hoverFormatter = function(axisName, val) { - if(val === undefined) return undefined; - - var axis = this[axisName]; - return Axes.tickText(axis, axis.c2l(val), 'hover').text; -}; - -},{"../../components/fx":632,"../../lib/show_no_webgl_msg":740,"../../plots/cartesian/axes":767,"../../registry":847,"../cartesian/autorange":766,"../cartesian/constants":773,"../cartesian/constraints":774,"./camera":803,"./convert":804,"gl-plot2d":287,"gl-select-box":299,"gl-spikes2d":308,"webgl-context":556}],807:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var fxAttrs = _dereq_('../../components/fx/layout_attributes'); - -var Scene = _dereq_('./scene'); -var getSubplotData = _dereq_('../get_data').getSubplotData; -var Lib = _dereq_('../../lib'); -var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); - -var GL3D = 'gl3d'; -var SCENE = 'scene'; - - -exports.name = GL3D; - -exports.attr = SCENE; - -exports.idRoot = SCENE; - -exports.idRegex = exports.attrRegex = Lib.counterRegex('scene'); - -exports.attributes = _dereq_('./layout/attributes'); - -exports.layoutAttributes = _dereq_('./layout/layout_attributes'); - -exports.baseLayoutAttrOverrides = overrideAll({ - hoverlabel: fxAttrs.hoverlabel -}, 'plot', 'nested'); - -exports.supplyLayoutDefaults = _dereq_('./layout/defaults'); - -exports.plot = function plot(gd) { - var fullLayout = gd._fullLayout; - var fullData = gd._fullData; - var sceneIds = fullLayout._subplots[GL3D]; - - for(var i = 0; i < sceneIds.length; i++) { - var sceneId = sceneIds[i]; - var fullSceneData = getSubplotData(fullData, GL3D, sceneId); - var sceneLayout = fullLayout[sceneId]; - var camera = sceneLayout.camera; - var scene = sceneLayout._scene; - - if(!scene) { - scene = new Scene({ - id: sceneId, - graphDiv: gd, - container: gd.querySelector('.gl-container'), - staticPlot: gd._context.staticPlot, - plotGlPixelRatio: gd._context.plotGlPixelRatio, - camera: camera - }, - fullLayout - ); - - // set ref to Scene instance - sceneLayout._scene = scene; - } - - // save 'initial' camera view settings for modebar button - if(!scene.viewInitial) { - scene.viewInitial = { - up: { - x: camera.up.x, - y: camera.up.y, - z: camera.up.z - }, - eye: { - x: camera.eye.x, - y: camera.eye.y, - z: camera.eye.z - }, - center: { - x: camera.center.x, - y: camera.center.y, - z: camera.center.z - } - }; - } - - scene.plot(fullSceneData, fullLayout, gd.layout); - } -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var oldSceneKeys = oldFullLayout._subplots[GL3D] || []; - - for(var i = 0; i < oldSceneKeys.length; i++) { - var oldSceneKey = oldSceneKeys[i]; - - if(!newFullLayout[oldSceneKey] && !!oldFullLayout[oldSceneKey]._scene) { - oldFullLayout[oldSceneKey]._scene.destroy(); - - if(oldFullLayout._infolayer) { - oldFullLayout._infolayer - .selectAll('.annotation-' + oldSceneKey) - .remove(); - } - } - } -}; - -exports.toSVG = function(gd) { - var fullLayout = gd._fullLayout; - var sceneIds = fullLayout._subplots[GL3D]; - var size = fullLayout._size; - - for(var i = 0; i < sceneIds.length; i++) { - var sceneLayout = fullLayout[sceneIds[i]]; - var domain = sceneLayout.domain; - var scene = sceneLayout._scene; - - var imageData = scene.toImage('png'); - var image = fullLayout._glimages.append('svg:image'); - - image.attr({ - xmlns: xmlnsNamespaces.svg, - 'xlink:href': imageData, - x: size.l + size.w * domain.x[0], - y: size.t + size.h * (1 - domain.y[1]), - width: size.w * (domain.x[1] - domain.x[0]), - height: size.h * (domain.y[1] - domain.y[0]), - preserveAspectRatio: 'none' - }); - - scene.destroy(); - } -}; - -// clean scene ids, 'scene1' -> 'scene' -exports.cleanId = function cleanId(id) { - if(!id.match(/^scene[0-9]*$/)) return; - - var sceneNum = id.substr(5); - if(sceneNum === '1') sceneNum = ''; - - return SCENE + sceneNum; -}; - -exports.updateFx = function(gd) { - var fullLayout = gd._fullLayout; - var subplotIds = fullLayout._subplots[GL3D]; - - for(var i = 0; i < subplotIds.length; i++) { - var subplotObj = fullLayout[subplotIds[i]]._scene; - subplotObj.updateFx(fullLayout.dragmode, fullLayout.hovermode); - } -}; - -},{"../../components/fx/layout_attributes":633,"../../constants/xmlns_namespaces":696,"../../lib":719,"../../plot_api/edit_types":750,"../get_data":802,"./layout/attributes":808,"./layout/defaults":812,"./layout/layout_attributes":813,"./scene":817}],808:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -module.exports = { - scene: { - valType: 'subplotid', - - dflt: 'scene', - editType: 'calc+clearAxisTypes', - - } -}; - -},{}],809:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Color = _dereq_('../../../components/color'); -var axesAttrs = _dereq_('../../cartesian/layout_attributes'); -var extendFlat = _dereq_('../../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../../plot_api/edit_types').overrideAll; - -module.exports = overrideAll({ - visible: axesAttrs.visible, - showspikes: { - valType: 'boolean', - - dflt: true, - - }, - spikesides: { - valType: 'boolean', - - dflt: true, - - }, - spikethickness: { - valType: 'number', - - min: 0, - dflt: 2, - - }, - spikecolor: { - valType: 'color', - - dflt: Color.defaultLine, - - }, - showbackground: { - valType: 'boolean', - - dflt: false, - - }, - backgroundcolor: { - valType: 'color', - - dflt: 'rgba(204, 204, 204, 0.5)', - - }, - showaxeslabels: { - valType: 'boolean', - - dflt: true, - - }, - color: axesAttrs.color, - categoryorder: axesAttrs.categoryorder, - categoryarray: axesAttrs.categoryarray, - title: axesAttrs.title, - type: extendFlat({}, axesAttrs.type, { - values: ['-', 'linear', 'log', 'date', 'category'] - }), - autorange: axesAttrs.autorange, - rangemode: axesAttrs.rangemode, - range: extendFlat({}, axesAttrs.range, { - items: [ - {valType: 'any', editType: 'plot', impliedEdits: {'^autorange': false}}, - {valType: 'any', editType: 'plot', impliedEdits: {'^autorange': false}} - ], - anim: false - }), - // ticks - tickmode: axesAttrs.tickmode, - nticks: axesAttrs.nticks, - tick0: axesAttrs.tick0, - dtick: axesAttrs.dtick, - tickvals: axesAttrs.tickvals, - ticktext: axesAttrs.ticktext, - ticks: axesAttrs.ticks, - mirror: axesAttrs.mirror, - ticklen: axesAttrs.ticklen, - tickwidth: axesAttrs.tickwidth, - tickcolor: axesAttrs.tickcolor, - showticklabels: axesAttrs.showticklabels, - tickfont: axesAttrs.tickfont, - tickangle: axesAttrs.tickangle, - tickprefix: axesAttrs.tickprefix, - showtickprefix: axesAttrs.showtickprefix, - ticksuffix: axesAttrs.ticksuffix, - showticksuffix: axesAttrs.showticksuffix, - showexponent: axesAttrs.showexponent, - exponentformat: axesAttrs.exponentformat, - separatethousands: axesAttrs.separatethousands, - tickformat: axesAttrs.tickformat, - tickformatstops: axesAttrs.tickformatstops, - hoverformat: axesAttrs.hoverformat, - // lines and grids - showline: axesAttrs.showline, - linecolor: axesAttrs.linecolor, - linewidth: axesAttrs.linewidth, - showgrid: axesAttrs.showgrid, - gridcolor: extendFlat({}, axesAttrs.gridcolor, // shouldn't this be on-par with 2D? - {dflt: 'rgb(204, 204, 204)'}), - gridwidth: axesAttrs.gridwidth, - zeroline: axesAttrs.zeroline, - zerolinecolor: axesAttrs.zerolinecolor, - zerolinewidth: axesAttrs.zerolinewidth, - _deprecated: { - title: axesAttrs._deprecated.title, - titlefont: axesAttrs._deprecated.titlefont - } -}, 'plot', 'from-root'); - -},{"../../../components/color":593,"../../../lib/extend":710,"../../../plot_api/edit_types":750,"../../cartesian/layout_attributes":779}],810:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var colorMix = _dereq_('tinycolor2').mix; - -var Lib = _dereq_('../../../lib'); -var Template = _dereq_('../../../plot_api/plot_template'); - -var layoutAttributes = _dereq_('./axis_attributes'); -var handleTypeDefaults = _dereq_('../../cartesian/type_defaults'); -var handleAxisDefaults = _dereq_('../../cartesian/axis_defaults'); - -var axesNames = ['xaxis', 'yaxis', 'zaxis']; - -// TODO: hard-coded lightness fraction based on gridline default colors -// that differ from other subplot types. -var gridLightness = 100 * (204 - 0x44) / (255 - 0x44); - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, options) { - var containerIn, containerOut; - - function coerce(attr, dflt) { - return Lib.coerce(containerIn, containerOut, layoutAttributes, attr, dflt); - } - - for(var j = 0; j < axesNames.length; j++) { - var axName = axesNames[j]; - containerIn = layoutIn[axName] || {}; - - containerOut = Template.newContainer(layoutOut, axName); - containerOut._id = axName[0] + options.scene; - containerOut._name = axName; - - handleTypeDefaults(containerIn, containerOut, coerce, options); - - handleAxisDefaults( - containerIn, - containerOut, - coerce, - { - font: options.font, - letter: axName[0], - data: options.data, - showGrid: true, - noTickson: true, - bgColor: options.bgColor, - calendar: options.calendar - }, - options.fullLayout); - - coerce('gridcolor', colorMix(containerOut.color, options.bgColor, gridLightness).toRgbString()); - coerce('title.text', axName[0]); // shouldn't this be on-par with 2D? - - containerOut.setScale = Lib.noop; - - if(coerce('showspikes')) { - coerce('spikesides'); - coerce('spikethickness'); - coerce('spikecolor', containerOut.color); - } - - coerce('showaxeslabels'); - if(coerce('showbackground')) coerce('backgroundcolor'); - } -}; - -},{"../../../lib":719,"../../../plot_api/plot_template":757,"../../cartesian/axis_defaults":769,"../../cartesian/type_defaults":790,"./axis_attributes":809,"tinycolor2":537}],811:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var str2RgbaArray = _dereq_('../../../lib/str2rgbarray'); -var Lib = _dereq_('../../../lib'); - -var AXES_NAMES = ['xaxis', 'yaxis', 'zaxis']; - -function AxesOptions() { - this.bounds = [ - [-10, -10, -10], - [10, 10, 10] - ]; - - this.ticks = [ [], [], [] ]; - this.tickEnable = [ true, true, true ]; - this.tickFont = [ 'sans-serif', 'sans-serif', 'sans-serif' ]; - this.tickSize = [ 12, 12, 12 ]; - this.tickAngle = [ 0, 0, 0 ]; - this.tickColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; - this.tickPad = [ 18, 18, 18 ]; - - this.labels = [ 'x', 'y', 'z' ]; - this.labelEnable = [ true, true, true ]; - this.labelFont = ['Open Sans', 'Open Sans', 'Open Sans']; - this.labelSize = [ 20, 20, 20 ]; - this.labelColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; - this.labelPad = [ 30, 30, 30 ]; - - this.lineEnable = [ true, true, true ]; - this.lineMirror = [ false, false, false ]; - this.lineWidth = [ 1, 1, 1 ]; - this.lineColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; - - this.lineTickEnable = [ true, true, true ]; - this.lineTickMirror = [ false, false, false ]; - this.lineTickLength = [ 10, 10, 10 ]; - this.lineTickWidth = [ 1, 1, 1 ]; - this.lineTickColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; - - this.gridEnable = [ true, true, true ]; - this.gridWidth = [ 1, 1, 1 ]; - this.gridColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; - - this.zeroEnable = [ true, true, true ]; - this.zeroLineColor = [ [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1] ]; - this.zeroLineWidth = [ 2, 2, 2 ]; - - this.backgroundEnable = [ true, true, true ]; - this.backgroundColor = [ [0.8, 0.8, 0.8, 0.5], - [0.8, 0.8, 0.8, 0.5], - [0.8, 0.8, 0.8, 0.5] ]; - - // some default values are stored for applying model transforms - this._defaultTickPad = this.tickPad.slice(); - this._defaultLabelPad = this.labelPad.slice(); - this._defaultLineTickLength = this.lineTickLength.slice(); -} - -var proto = AxesOptions.prototype; - -proto.merge = function(fullLayout, sceneLayout) { - var opts = this; - for(var i = 0; i < 3; ++i) { - var axes = sceneLayout[AXES_NAMES[i]]; - - if(!axes.visible) { - opts.tickEnable[i] = false; - opts.labelEnable[i] = false; - opts.lineEnable[i] = false; - opts.lineTickEnable[i] = false; - opts.gridEnable[i] = false; - opts.zeroEnable[i] = false; - opts.backgroundEnable[i] = false; - continue; - } - - // Axes labels - opts.labels[i] = fullLayout._meta ? - Lib.templateString(axes.title.text, fullLayout._meta) : - axes.title.text; - - if('font' in axes.title) { - if(axes.title.font.color) opts.labelColor[i] = str2RgbaArray(axes.title.font.color); - if(axes.title.font.family) opts.labelFont[i] = axes.title.font.family; - if(axes.title.font.size) opts.labelSize[i] = axes.title.font.size; - } - - // Lines - if('showline' in axes) opts.lineEnable[i] = axes.showline; - if('linecolor' in axes) opts.lineColor[i] = str2RgbaArray(axes.linecolor); - if('linewidth' in axes) opts.lineWidth[i] = axes.linewidth; - - if('showgrid' in axes) opts.gridEnable[i] = axes.showgrid; - if('gridcolor' in axes) opts.gridColor[i] = str2RgbaArray(axes.gridcolor); - if('gridwidth' in axes) opts.gridWidth[i] = axes.gridwidth; - - // Remove zeroline if axis type is log - // otherwise the zeroline is incorrectly drawn at 1 on log axes - if(axes.type === 'log') opts.zeroEnable[i] = false; - else if('zeroline' in axes) opts.zeroEnable[i] = axes.zeroline; - if('zerolinecolor' in axes) opts.zeroLineColor[i] = str2RgbaArray(axes.zerolinecolor); - if('zerolinewidth' in axes) opts.zeroLineWidth[i] = axes.zerolinewidth; - - // tick lines - if('ticks' in axes && !!axes.ticks) opts.lineTickEnable[i] = true; - else opts.lineTickEnable[i] = false; - - if('ticklen' in axes) { - opts.lineTickLength[i] = opts._defaultLineTickLength[i] = axes.ticklen; - } - if('tickcolor' in axes) opts.lineTickColor[i] = str2RgbaArray(axes.tickcolor); - if('tickwidth' in axes) opts.lineTickWidth[i] = axes.tickwidth; - if('tickangle' in axes) { - opts.tickAngle[i] = (axes.tickangle === 'auto') ? - -3600 : // i.e. special number to set auto option - Math.PI * -axes.tickangle / 180; - } - - // tick labels - if('showticklabels' in axes) opts.tickEnable[i] = axes.showticklabels; - if('tickfont' in axes) { - if(axes.tickfont.color) opts.tickColor[i] = str2RgbaArray(axes.tickfont.color); - if(axes.tickfont.family) opts.tickFont[i] = axes.tickfont.family; - if(axes.tickfont.size) opts.tickSize[i] = axes.tickfont.size; - } - - if('mirror' in axes) { - if(['ticks', 'all', 'allticks'].indexOf(axes.mirror) !== -1) { - opts.lineTickMirror[i] = true; - opts.lineMirror[i] = true; - } else if(axes.mirror === true) { - opts.lineTickMirror[i] = false; - opts.lineMirror[i] = true; - } else { - opts.lineTickMirror[i] = false; - opts.lineMirror[i] = false; - } - } else opts.lineMirror[i] = false; - - // grid background - if('showbackground' in axes && axes.showbackground !== false) { - opts.backgroundEnable[i] = true; - opts.backgroundColor[i] = str2RgbaArray(axes.backgroundcolor); - } else opts.backgroundEnable[i] = false; - } -}; - - -function createAxesOptions(fullLayout, sceneLayout) { - var result = new AxesOptions(); - result.merge(fullLayout, sceneLayout); - return result; -} - -module.exports = createAxesOptions; - -},{"../../../lib":719,"../../../lib/str2rgbarray":742}],812:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../../lib'); -var Color = _dereq_('../../../components/color'); -var Registry = _dereq_('../../../registry'); - -var handleSubplotDefaults = _dereq_('../../subplot_defaults'); -var supplyGl3dAxisLayoutDefaults = _dereq_('./axis_defaults'); -var layoutAttributes = _dereq_('./layout_attributes'); -var getSubplotData = _dereq_('../../get_data').getSubplotData; - -var GL3D = 'gl3d'; - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - var hasNon3D = layoutOut._basePlotModules.length > 1; - - // some layout-wide attribute are used in all scenes - // if 3D is the only visible plot type - function getDfltFromLayout(attr) { - if(hasNon3D) return; - - var isValid = Lib.validate(layoutIn[attr], layoutAttributes[attr]); - if(isValid) return layoutIn[attr]; - } - - handleSubplotDefaults(layoutIn, layoutOut, fullData, { - type: GL3D, - attributes: layoutAttributes, - handleDefaults: handleGl3dDefaults, - fullLayout: layoutOut, - font: layoutOut.font, - fullData: fullData, - getDfltFromLayout: getDfltFromLayout, - paper_bgcolor: layoutOut.paper_bgcolor, - calendar: layoutOut.calendar - }); -}; - -function handleGl3dDefaults(sceneLayoutIn, sceneLayoutOut, coerce, opts) { - /* - * Scene numbering proceeds as follows - * scene - * scene2 - * scene3 - * - * and d.scene will be undefined or some number or number string - * - * Also write back a blank scene object to user layout so that some - * attributes like aspectratio can be written back dynamically. - */ - - var bgcolor = coerce('bgcolor'); - var bgColorCombined = Color.combine(bgcolor, opts.paper_bgcolor); - - var cameraKeys = ['up', 'center', 'eye']; - - for(var j = 0; j < cameraKeys.length; j++) { - coerce('camera.' + cameraKeys[j] + '.x'); - coerce('camera.' + cameraKeys[j] + '.y'); - coerce('camera.' + cameraKeys[j] + '.z'); - } - - coerce('camera.projection.type'); - - /* - * coerce to positive number (min 0) but also do not accept 0 (>0 not >=0) - * note that 0's go false with the !! call - */ - var hasAspect = !!coerce('aspectratio.x') && - !!coerce('aspectratio.y') && - !!coerce('aspectratio.z'); - - var defaultAspectMode = hasAspect ? 'manual' : 'auto'; - var aspectMode = coerce('aspectmode', defaultAspectMode); - - /* - * We need aspectratio object in all the Layouts as it is dynamically set - * in the calculation steps, ie, we cant set the correct data now, it happens later. - * We must also account for the case the user sends bad ratio data with 'manual' set - * for the mode. In this case we must force change it here as the default coerce - * misses it above. - */ - if(!hasAspect) { - sceneLayoutIn.aspectratio = sceneLayoutOut.aspectratio = {x: 1, y: 1, z: 1}; - - if(aspectMode === 'manual') sceneLayoutOut.aspectmode = 'auto'; - - /* - * kind of like autorange - we need the calculated aspectmode back in - * the input layout or relayout can cause problems later - */ - sceneLayoutIn.aspectmode = sceneLayoutOut.aspectmode; - } - - var fullGl3dData = getSubplotData(opts.fullData, GL3D, opts.id); - - supplyGl3dAxisLayoutDefaults(sceneLayoutIn, sceneLayoutOut, { - font: opts.font, - scene: opts.id, - data: fullGl3dData, - bgColor: bgColorCombined, - calendar: opts.calendar, - fullLayout: opts.fullLayout - }); - - Registry.getComponentMethod('annotations3d', 'handleDefaults')( - sceneLayoutIn, sceneLayoutOut, opts - ); - - var dragmode = opts.getDfltFromLayout('dragmode'); - - if(dragmode !== false) { - if(!dragmode) { - dragmode = 'orbit'; - - if(sceneLayoutIn.camera && - sceneLayoutIn.camera.up) { - var x = sceneLayoutIn.camera.up.x; - var y = sceneLayoutIn.camera.up.y; - var z = sceneLayoutIn.camera.up.z; - - if(z !== 0) { - if(!x || !y || !z) { - dragmode = 'turntable'; - } else if(z / Math.sqrt(x * x + y * y + z * z) > 0.999) { - dragmode = 'turntable'; - } - } - } else { - dragmode = 'turntable'; - } - } - } - - coerce('dragmode', dragmode); - coerce('hovermode', opts.getDfltFromLayout('hovermode')); -} - -},{"../../../components/color":593,"../../../lib":719,"../../../registry":847,"../../get_data":802,"../../subplot_defaults":842,"./axis_defaults":810,"./layout_attributes":813}],813:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var gl3dAxisAttrs = _dereq_('./axis_attributes'); -var domainAttrs = _dereq_('../../domain').attributes; -var extendFlat = _dereq_('../../../lib/extend').extendFlat; -var counterRegex = _dereq_('../../../lib').counterRegex; - -function makeCameraVector(x, y, z) { - return { - x: { - valType: 'number', - - dflt: x, - editType: 'camera' - }, - y: { - valType: 'number', - - dflt: y, - editType: 'camera' - }, - z: { - valType: 'number', - - dflt: z, - editType: 'camera' - }, - editType: 'camera' - }; -} - -module.exports = { - _arrayAttrRegexps: [counterRegex('scene', '.annotations', true)], - - bgcolor: { - valType: 'color', - - dflt: 'rgba(0,0,0,0)', - editType: 'plot' - }, - camera: { - up: extendFlat(makeCameraVector(0, 0, 1), { - - }), - center: extendFlat(makeCameraVector(0, 0, 0), { - - }), - eye: extendFlat(makeCameraVector(1.25, 1.25, 1.25), { - - }), - projection: { - type: { - valType: 'enumerated', - - values: ['perspective', 'orthographic'], - dflt: 'perspective', - editType: 'calc', - - }, - editType: 'calc' - }, - editType: 'camera' - }, - domain: domainAttrs({name: 'scene', editType: 'plot'}), - aspectmode: { - valType: 'enumerated', - - values: ['auto', 'cube', 'data', 'manual'], - dflt: 'auto', - editType: 'plot', - impliedEdits: { - 'aspectratio.x': undefined, - 'aspectratio.y': undefined, - 'aspectratio.z': undefined - }, - - }, - aspectratio: { // must be positive (0's are coerced to 1) - x: { - valType: 'number', - - min: 0, - editType: 'plot', - impliedEdits: {'^aspectmode': 'manual'} - }, - y: { - valType: 'number', - - min: 0, - editType: 'plot', - impliedEdits: {'^aspectmode': 'manual'} - }, - z: { - valType: 'number', - - min: 0, - editType: 'plot', - impliedEdits: {'^aspectmode': 'manual'} - }, - editType: 'plot', - impliedEdits: {aspectmode: 'manual'}, - - }, - - xaxis: gl3dAxisAttrs, - yaxis: gl3dAxisAttrs, - zaxis: gl3dAxisAttrs, - - dragmode: { - valType: 'enumerated', - - values: ['orbit', 'turntable', 'zoom', 'pan', false], - editType: 'plot', - - }, - hovermode: { - valType: 'enumerated', - - values: ['closest', false], - dflt: 'closest', - editType: 'modebar', - - }, - uirevision: { - valType: 'any', - - editType: 'none', - - }, - editType: 'plot', - - _deprecated: { - cameraposition: { - valType: 'info_array', - - editType: 'camera', - - } - } -}; - -},{"../../../lib":719,"../../../lib/extend":710,"../../domain":792,"./axis_attributes":809}],814:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var str2RGBArray = _dereq_('../../../lib/str2rgbarray'); - -var AXES_NAMES = ['xaxis', 'yaxis', 'zaxis']; - -function SpikeOptions() { - this.enabled = [true, true, true]; - this.colors = [[0, 0, 0, 1], - [0, 0, 0, 1], - [0, 0, 0, 1]]; - this.drawSides = [true, true, true]; - this.lineWidth = [1, 1, 1]; -} - -var proto = SpikeOptions.prototype; - -proto.merge = function(sceneLayout) { - for(var i = 0; i < 3; ++i) { - var axes = sceneLayout[AXES_NAMES[i]]; - - if(!axes.visible) { - this.enabled[i] = false; - this.drawSides[i] = false; - continue; - } - - this.enabled[i] = axes.showspikes; - this.colors[i] = str2RGBArray(axes.spikecolor); - this.drawSides[i] = axes.spikesides; - this.lineWidth[i] = axes.spikethickness; - } -}; - -function createSpikeOptions(layout) { - var result = new SpikeOptions(); - result.merge(layout); - return result; -} - -module.exports = createSpikeOptions; - -},{"../../../lib/str2rgbarray":742}],815:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -/* eslint block-scoped-var: 0*/ -/* eslint no-redeclare: 0*/ - -'use strict'; - -module.exports = computeTickMarks; - -var Axes = _dereq_('../../cartesian/axes'); -var Lib = _dereq_('../../../lib'); - -var AXES_NAMES = ['xaxis', 'yaxis', 'zaxis']; - -var centerPoint = [0, 0, 0]; - -function contourLevelsFromTicks(ticks) { - var result = new Array(3); - for(var i = 0; i < 3; ++i) { - var tlevel = ticks[i]; - var clevel = new Array(tlevel.length); - for(var j = 0; j < tlevel.length; ++j) { - clevel[j] = tlevel[j].x; - } - result[i] = clevel; - } - return result; -} - -function computeTickMarks(scene) { - var axesOptions = scene.axesOptions; - var glRange = scene.glplot.axesPixels; - var sceneLayout = scene.fullSceneLayout; - - var ticks = [[], [], []]; - - for(var i = 0; i < 3; ++i) { - var axes = sceneLayout[AXES_NAMES[i]]; - - axes._length = (glRange[i].hi - glRange[i].lo) * - glRange[i].pixelsPerDataUnit / scene.dataScale[i]; - - if(Math.abs(axes._length) === Infinity || - isNaN(axes._length)) { - ticks[i] = []; - } else { - axes._input_range = axes.range.slice(); - axes.range[0] = (glRange[i].lo) / scene.dataScale[i]; - axes.range[1] = (glRange[i].hi) / scene.dataScale[i]; - axes._m = 1.0 / (scene.dataScale[i] * glRange[i].pixelsPerDataUnit); - - if(axes.range[0] === axes.range[1]) { - axes.range[0] -= 1; - axes.range[1] += 1; - } - // this is necessary to short-circuit the 'y' handling - // in autotick part of calcTicks... Treating all axes as 'y' in this case - // running the autoticks here, then setting - // autoticks to false to get around the 2D handling in calcTicks. - var tickModeCached = axes.tickmode; - if(axes.tickmode === 'auto') { - axes.tickmode = 'linear'; - var nticks = axes.nticks || Lib.constrain((axes._length / 40), 4, 9); - Axes.autoTicks(axes, Math.abs(axes.range[1] - axes.range[0]) / nticks); - } - var dataTicks = Axes.calcTicks(axes); - for(var j = 0; j < dataTicks.length; ++j) { - dataTicks[j].x = dataTicks[j].x * scene.dataScale[i]; - - if(axes.type === 'date') { - dataTicks[j].text = - dataTicks[j].text.replace(/\/g, ' '); - } - } - ticks[i] = dataTicks; - - - axes.tickmode = tickModeCached; - } - } - - axesOptions.ticks = ticks; - - // Calculate tick lengths dynamically - for(var i = 0; i < 3; ++i) { - centerPoint[i] = 0.5 * (scene.glplot.bounds[0][i] + scene.glplot.bounds[1][i]); - for(var j = 0; j < 2; ++j) { - axesOptions.bounds[j][i] = scene.glplot.bounds[j][i]; - } - } - - scene.contourLevels = contourLevelsFromTicks(ticks); -} - -},{"../../../lib":719,"../../cartesian/axes":767}],816:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -function xformMatrix(m, v) { - var out = [0, 0, 0, 0]; - var i, j; - - for(i = 0; i < 4; ++i) { - for(j = 0; j < 4; ++j) { - out[j] += m[4 * i + j] * v[i]; - } - } - - return out; -} - -function project(camera, v) { - var p = xformMatrix(camera.projection, - xformMatrix(camera.view, - xformMatrix(camera.model, [v[0], v[1], v[2], 1]))); - return p; -} - -module.exports = project; - -},{}],817:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var createCamera = _dereq_('gl-plot3d').createCamera; -var createPlot = _dereq_('gl-plot3d').createScene; -var getContext = _dereq_('webgl-context'); -var passiveSupported = _dereq_('has-passive-events'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); - -var Axes = _dereq_('../../plots/cartesian/axes'); -var Fx = _dereq_('../../components/fx'); - -var str2RGBAarray = _dereq_('../../lib/str2rgbarray'); -var showNoWebGlMsg = _dereq_('../../lib/show_no_webgl_msg'); - -var project = _dereq_('./project'); -var createAxesOptions = _dereq_('./layout/convert'); -var createSpikeOptions = _dereq_('./layout/spikes'); -var computeTickMarks = _dereq_('./layout/tick_marks'); - - -var STATIC_CANVAS, STATIC_CONTEXT; - -function render(scene) { - var gd = scene.graphDiv; - var trace; - - // update size of svg container - var svgContainer = scene.svgContainer; - var clientRect = scene.container.getBoundingClientRect(); - var width = clientRect.width; - var height = clientRect.height; - svgContainer.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height); - svgContainer.setAttributeNS(null, 'width', width); - svgContainer.setAttributeNS(null, 'height', height); - - computeTickMarks(scene); - scene.glplot.axes.update(scene.axesOptions); - - // check if pick has changed - var keys = Object.keys(scene.traces); - var lastPicked = null; - var selection = scene.glplot.selection; - for(var i = 0; i < keys.length; ++i) { - trace = scene.traces[keys[i]]; - if(trace.data.hoverinfo !== 'skip' && trace.handlePick(selection)) { - lastPicked = trace; - } - - if(trace.setContourLevels) trace.setContourLevels(); - } - - function formatter(axisName, val) { - var axis = scene.fullSceneLayout[axisName]; - - return Axes.tickText(axis, axis.d2l(val), 'hover').text; - } - - var oldEventData; - - if(lastPicked !== null) { - var pdata = project(scene.glplot.cameraParams, selection.dataCoordinate); - trace = lastPicked.data; - var traceNow = gd._fullData[trace.index]; - var ptNumber = selection.index; - - var labels = { - xLabel: formatter('xaxis', selection.traceCoordinate[0]), - yLabel: formatter('yaxis', selection.traceCoordinate[1]), - zLabel: formatter('zaxis', selection.traceCoordinate[2]) - }; - - var hoverinfo = Fx.castHoverinfo(traceNow, scene.fullLayout, ptNumber); - var hoverinfoParts = (hoverinfo || '').split('+'); - var isHoverinfoAll = hoverinfo && hoverinfo === 'all'; - - if(!traceNow.hovertemplate && !isHoverinfoAll) { - if(hoverinfoParts.indexOf('x') === -1) labels.xLabel = undefined; - if(hoverinfoParts.indexOf('y') === -1) labels.yLabel = undefined; - if(hoverinfoParts.indexOf('z') === -1) labels.zLabel = undefined; - if(hoverinfoParts.indexOf('text') === -1) selection.textLabel = undefined; - if(hoverinfoParts.indexOf('name') === -1) lastPicked.name = undefined; - } - - var tx; - var vectorTx = []; - - if(trace.type === 'cone' || trace.type === 'streamtube') { - labels.uLabel = formatter('xaxis', selection.traceCoordinate[3]); - if(isHoverinfoAll || hoverinfoParts.indexOf('u') !== -1) { - vectorTx.push('u: ' + labels.uLabel); - } - - labels.vLabel = formatter('yaxis', selection.traceCoordinate[4]); - if(isHoverinfoAll || hoverinfoParts.indexOf('v') !== -1) { - vectorTx.push('v: ' + labels.vLabel); - } - - labels.wLabel = formatter('zaxis', selection.traceCoordinate[5]); - if(isHoverinfoAll || hoverinfoParts.indexOf('w') !== -1) { - vectorTx.push('w: ' + labels.wLabel); - } - - labels.normLabel = selection.traceCoordinate[6].toPrecision(3); - if(isHoverinfoAll || hoverinfoParts.indexOf('norm') !== -1) { - vectorTx.push('norm: ' + labels.normLabel); - } - if(trace.type === 'streamtube') { - labels.divergenceLabel = selection.traceCoordinate[7].toPrecision(3); - if(isHoverinfoAll || hoverinfoParts.indexOf('divergence') !== -1) { - vectorTx.push('divergence: ' + labels.divergenceLabel); - } - } - if(selection.textLabel) { - vectorTx.push(selection.textLabel); - } - tx = vectorTx.join('
'); - } else if(trace.type === 'isosurface' || trace.type === 'volume') { - labels.valueLabel = Axes.tickText(scene.mockAxis, scene.mockAxis.d2l(selection.traceCoordinate[3]), 'hover').text; - vectorTx.push('value: ' + labels.valueLabel); - if(selection.textLabel) { - vectorTx.push(selection.textLabel); - } - tx = vectorTx.join('
'); - } else { - tx = selection.textLabel; - } - - var pointData = { - x: selection.traceCoordinate[0], - y: selection.traceCoordinate[1], - z: selection.traceCoordinate[2], - data: traceNow._input, - fullData: traceNow, - curveNumber: traceNow.index, - pointNumber: ptNumber - }; - - Fx.appendArrayPointValue(pointData, traceNow, ptNumber); - - if(trace._module.eventData) { - pointData = traceNow._module.eventData(pointData, selection, traceNow, {}, ptNumber); - } - - var eventData = {points: [pointData]}; - - if(scene.fullSceneLayout.hovermode) { - Fx.loneHover({ - trace: traceNow, - x: (0.5 + 0.5 * pdata[0] / pdata[3]) * width, - y: (0.5 - 0.5 * pdata[1] / pdata[3]) * height, - xLabel: labels.xLabel, - yLabel: labels.yLabel, - zLabel: labels.zLabel, - text: tx, - name: lastPicked.name, - color: Fx.castHoverOption(traceNow, ptNumber, 'bgcolor') || lastPicked.color, - borderColor: Fx.castHoverOption(traceNow, ptNumber, 'bordercolor'), - fontFamily: Fx.castHoverOption(traceNow, ptNumber, 'font.family'), - fontSize: Fx.castHoverOption(traceNow, ptNumber, 'font.size'), - fontColor: Fx.castHoverOption(traceNow, ptNumber, 'font.color'), - nameLength: Fx.castHoverOption(traceNow, ptNumber, 'namelength'), - textAlign: Fx.castHoverOption(traceNow, ptNumber, 'align'), - hovertemplate: Lib.castOption(traceNow, ptNumber, 'hovertemplate'), - hovertemplateLabels: Lib.extendFlat({}, pointData, labels), - eventData: [pointData] - }, { - container: svgContainer, - gd: gd - }); - } - - if(selection.buttons && selection.distance < 5) { - gd.emit('plotly_click', eventData); - } else { - gd.emit('plotly_hover', eventData); - } - - oldEventData = eventData; - } else { - Fx.loneUnhover(svgContainer); - gd.emit('plotly_unhover', oldEventData); - } - - scene.drawAnnotations(scene); -} - -function tryCreatePlot(scene, cameraObject, pixelRatio, canvas, gl) { - var glplotOptions = { - canvas: canvas, - gl: gl, - container: scene.container, - axes: scene.axesOptions, - spikes: scene.spikeOptions, - pickRadius: 10, - snapToData: true, - autoScale: true, - autoBounds: false, - cameraObject: cameraObject, - pixelRatio: pixelRatio - }; - - // for static plots, we reuse the WebGL context - // as WebKit doesn't collect them reliably - if(scene.staticMode) { - if(!STATIC_CONTEXT) { - STATIC_CANVAS = document.createElement('canvas'); - STATIC_CONTEXT = getContext({ - canvas: STATIC_CANVAS, - preserveDrawingBuffer: true, - premultipliedAlpha: true, - antialias: true - }); - if(!STATIC_CONTEXT) { - throw new Error('error creating static canvas/context for image server'); - } - } - glplotOptions.pixelRatio = scene.pixelRatio; - glplotOptions.gl = STATIC_CONTEXT; - glplotOptions.canvas = STATIC_CANVAS; - } - - try { - scene.glplot = createPlot(glplotOptions); - } catch(e) { - return false; - } - - return true; -} - -function initializeGLPlot(scene, pixelRatio, canvas, gl) { - scene.initializeGLCamera(); - - var success = tryCreatePlot(scene, scene.camera, pixelRatio, canvas, gl); - /* - * createPlot will throw when webgl is not enabled in the client. - * Lets return an instance of the module with all functions noop'd. - * The destroy method - which will remove the container from the DOM - * is overridden with a function that removes the container only. - */ - if(!success) return showNoWebGlMsg(scene); - - var gd = scene.graphDiv; - - var relayoutCallback = function(scene) { - if(scene.fullSceneLayout.dragmode === false) return; - - var update = {}; - update[scene.id + '.camera'] = getLayoutCamera(scene.camera); - scene.saveCamera(gd.layout); - scene.graphDiv.emit('plotly_relayout', update); - }; - - scene.glplot.canvas.addEventListener('mouseup', function() { - relayoutCallback(scene); - }); - - scene.glplot.canvas.addEventListener('wheel', function() { - if(gd._context._scrollZoom.gl3d) { - relayoutCallback(scene); - } - }, passiveSupported ? {passive: false} : false); - - scene.glplot.canvas.addEventListener('mousemove', function() { - if(scene.fullSceneLayout.dragmode === false) return; - if(scene.camera.mouseListener.buttons === 0) return; - - var update = {}; - update[scene.id + '.camera'] = getLayoutCamera(scene.camera); - scene.graphDiv.emit('plotly_relayouting', update); - }); - - if(!scene.staticMode) { - scene.glplot.canvas.addEventListener('webglcontextlost', function(event) { - if(gd && gd.emit) { - gd.emit('plotly_webglcontextlost', { - event: event, - layer: scene.id - }); - } - }, false); - } - - scene.glplot.camera = scene.camera; - - scene.glplot.oncontextloss = function() { - scene.recoverContext(); - }; - - scene.glplot.onrender = render.bind(null, scene); - - // List of scene objects - scene.traces = {}; - - scene.make4thDimension(); - - return true; -} - -function Scene(options, fullLayout) { - // create sub container for plot - var sceneContainer = document.createElement('div'); - var plotContainer = options.container; - - // keep a ref to the graph div to fire hover+click events - this.graphDiv = options.graphDiv; - - // create SVG container for hover text - var svgContainer = document.createElementNS( - 'http://www.w3.org/2000/svg', - 'svg'); - svgContainer.style.position = 'absolute'; - svgContainer.style.top = svgContainer.style.left = '0px'; - svgContainer.style.width = svgContainer.style.height = '100%'; - svgContainer.style['z-index'] = 20; - svgContainer.style['pointer-events'] = 'none'; - sceneContainer.appendChild(svgContainer); - this.svgContainer = svgContainer; - - // Tag the container with the sceneID - sceneContainer.id = options.id; - sceneContainer.style.position = 'absolute'; - sceneContainer.style.top = sceneContainer.style.left = '0px'; - sceneContainer.style.width = sceneContainer.style.height = '100%'; - plotContainer.appendChild(sceneContainer); - - this.fullLayout = fullLayout; - this.id = options.id || 'scene'; - this.fullSceneLayout = fullLayout[this.id]; - - // Saved from last call to plot() - this.plotArgs = [ [], {}, {} ]; - - /* - * Move this to calc step? Why does it work here? - */ - this.axesOptions = createAxesOptions(fullLayout, fullLayout[this.id]); - this.spikeOptions = createSpikeOptions(fullLayout[this.id]); - this.container = sceneContainer; - this.staticMode = !!options.staticPlot; - this.pixelRatio = this.pixelRatio || options.plotGlPixelRatio || 2; - - // Coordinate rescaling - this.dataScale = [1, 1, 1]; - - this.contourLevels = [ [], [], [] ]; - - this.convertAnnotations = Registry.getComponentMethod('annotations3d', 'convert'); - this.drawAnnotations = Registry.getComponentMethod('annotations3d', 'draw'); - - initializeGLPlot(this, this.pixelRatio); -} - -var proto = Scene.prototype; - -proto.initializeGLCamera = function() { - var cameraData = this.fullSceneLayout.camera; - var isOrtho = (cameraData.projection.type === 'orthographic'); - - this.camera = createCamera(this.container, { - center: [cameraData.center.x, cameraData.center.y, cameraData.center.z], - eye: [cameraData.eye.x, cameraData.eye.y, cameraData.eye.z], - up: [cameraData.up.x, cameraData.up.y, cameraData.up.z], - _ortho: isOrtho, - zoomMin: 0.01, - zoomMax: 100, - mode: 'orbit' - }); -}; - -proto.recoverContext = function() { - var scene = this; - var gl = this.glplot.gl; - var canvas = this.glplot.canvas; - var camera = this.glplot.camera; - var pixelRatio = this.glplot.pixelRatio; - this.glplot.dispose(); - - function tryRecover() { - if(gl.isContextLost()) { - requestAnimationFrame(tryRecover); - return; - } - if(!initializeGLPlot(scene, camera, pixelRatio, canvas, gl)) { - Lib.error('Catastrophic and unrecoverable WebGL error. Context lost.'); - return; - } - scene.plot.apply(scene, scene.plotArgs); - } - requestAnimationFrame(tryRecover); -}; - -var axisProperties = [ 'xaxis', 'yaxis', 'zaxis' ]; - -function computeTraceBounds(scene, trace, bounds) { - var sceneLayout = scene.fullSceneLayout; - - for(var d = 0; d < 3; d++) { - var axisName = axisProperties[d]; - var axLetter = axisName.charAt(0); - var ax = sceneLayout[axisName]; - var coords = trace[axLetter]; - var calendar = trace[axLetter + 'calendar']; - var len = trace['_' + axLetter + 'length']; - - if(!Lib.isArrayOrTypedArray(coords)) { - bounds[0][d] = Math.min(bounds[0][d], 0); - bounds[1][d] = Math.max(bounds[1][d], len - 1); - } else { - var v; - - for(var i = 0; i < (len || coords.length); i++) { - if(Lib.isArrayOrTypedArray(coords[i])) { - for(var j = 0; j < coords[i].length; ++j) { - v = ax.d2l(coords[i][j], 0, calendar); - if(!isNaN(v) && isFinite(v)) { - bounds[0][d] = Math.min(bounds[0][d], v); - bounds[1][d] = Math.max(bounds[1][d], v); - } - } - } else { - v = ax.d2l(coords[i], 0, calendar); - if(!isNaN(v) && isFinite(v)) { - bounds[0][d] = Math.min(bounds[0][d], v); - bounds[1][d] = Math.max(bounds[1][d], v); - } - } - } - } - } -} - -function computeAnnotationBounds(scene, bounds) { - var sceneLayout = scene.fullSceneLayout; - var annotations = sceneLayout.annotations || []; - - for(var d = 0; d < 3; d++) { - var axisName = axisProperties[d]; - var axLetter = axisName.charAt(0); - var ax = sceneLayout[axisName]; - - for(var j = 0; j < annotations.length; j++) { - var ann = annotations[j]; - - if(ann.visible) { - var pos = ax.r2l(ann[axLetter]); - if(!isNaN(pos) && isFinite(pos)) { - bounds[0][d] = Math.min(bounds[0][d], pos); - bounds[1][d] = Math.max(bounds[1][d], pos); - } - } - } - } -} - -proto.plot = function(sceneData, fullLayout, layout) { - // Save parameters - this.plotArgs = [sceneData, fullLayout, layout]; - - if(this.glplot.contextLost) return; - - var data, trace; - var i, j, axis, axisType; - var fullSceneLayout = fullLayout[this.id]; - var sceneLayout = layout[this.id]; - - if(fullSceneLayout.bgcolor) this.glplot.clearColor = str2RGBAarray(fullSceneLayout.bgcolor); - else this.glplot.clearColor = [0, 0, 0, 0]; - - this.glplot.snapToData = true; - - // Update layout - this.fullLayout = fullLayout; - this.fullSceneLayout = fullSceneLayout; - - this.glplotLayout = fullSceneLayout; - this.axesOptions.merge(fullLayout, fullSceneLayout); - this.spikeOptions.merge(fullSceneLayout); - - // Update camera and camera mode - this.setCamera(fullSceneLayout.camera); - this.updateFx(fullSceneLayout.dragmode, fullSceneLayout.hovermode); - this.camera.enableWheel = this.graphDiv._context._scrollZoom.gl3d; - - // Update scene - this.glplot.update({}); - - // Update axes functions BEFORE updating traces - this.setConvert(axis); - - // Convert scene data - if(!sceneData) sceneData = []; - else if(!Array.isArray(sceneData)) sceneData = [sceneData]; - - // Compute trace bounding box - var dataBounds = [ - [Infinity, Infinity, Infinity], - [-Infinity, -Infinity, -Infinity] - ]; - - for(i = 0; i < sceneData.length; ++i) { - data = sceneData[i]; - if(data.visible !== true || data._length === 0) continue; - - computeTraceBounds(this, data, dataBounds); - } - computeAnnotationBounds(this, dataBounds); - - var dataScale = [1, 1, 1]; - for(j = 0; j < 3; ++j) { - if(dataBounds[1][j] === dataBounds[0][j]) { - dataScale[j] = 1.0; - } else { - dataScale[j] = 1.0 / (dataBounds[1][j] - dataBounds[0][j]); - } - } - - // Save scale - this.dataScale = dataScale; - - // after computeTraceBounds where ax._categories are filled in - this.convertAnnotations(this); - - // Update traces - for(i = 0; i < sceneData.length; ++i) { - data = sceneData[i]; - if(data.visible !== true || data._length === 0) { - continue; - } - trace = this.traces[data.uid]; - if(trace) { - if(trace.data.type === data.type) { - trace.update(data); - } else { - trace.dispose(); - trace = data._module.plot(this, data); - this.traces[data.uid] = trace; - } - } else { - trace = data._module.plot(this, data); - this.traces[data.uid] = trace; - } - trace.name = data.name; - } - - // Remove empty traces - var traceIds = Object.keys(this.traces); - - traceIdLoop: - for(i = 0; i < traceIds.length; ++i) { - for(j = 0; j < sceneData.length; ++j) { - if(sceneData[j].uid === traceIds[i] && - (sceneData[j].visible === true && sceneData[j]._length !== 0)) { - continue traceIdLoop; - } - } - trace = this.traces[traceIds[i]]; - trace.dispose(); - delete this.traces[traceIds[i]]; - } - - // order object per trace index - this.glplot.objects.sort(function(a, b) { - return a._trace.data.index - b._trace.data.index; - }); - - // Update ranges (needs to be called *after* objects are added due to updates) - var sceneBounds = [[0, 0, 0], [0, 0, 0]]; - var axisDataRange = []; - var axisTypeRatios = {}; - - for(i = 0; i < 3; ++i) { - axis = fullSceneLayout[axisProperties[i]]; - axisType = axis.type; - - if(axisType in axisTypeRatios) { - axisTypeRatios[axisType].acc *= dataScale[i]; - axisTypeRatios[axisType].count += 1; - } else { - axisTypeRatios[axisType] = { - acc: dataScale[i], - count: 1 - }; - } - - if(axis.autorange) { - sceneBounds[0][i] = Infinity; - sceneBounds[1][i] = -Infinity; - - var objects = this.glplot.objects; - var annotations = this.fullSceneLayout.annotations || []; - var axLetter = axis._name.charAt(0); - - for(j = 0; j < objects.length; j++) { - var obj = objects[j]; - var objBounds = obj.bounds; - var pad = obj._trace.data._pad || 0; - - if(obj.constructor.name === 'ErrorBars' && axis._lowerLogErrorBound) { - sceneBounds[0][i] = Math.min(sceneBounds[0][i], axis._lowerLogErrorBound); - } else { - sceneBounds[0][i] = Math.min(sceneBounds[0][i], objBounds[0][i] / dataScale[i] - pad); - } - sceneBounds[1][i] = Math.max(sceneBounds[1][i], objBounds[1][i] / dataScale[i] + pad); - } - - for(j = 0; j < annotations.length; j++) { - var ann = annotations[j]; - - // N.B. not taking into consideration the arrowhead - if(ann.visible) { - var pos = axis.r2l(ann[axLetter]); - sceneBounds[0][i] = Math.min(sceneBounds[0][i], pos); - sceneBounds[1][i] = Math.max(sceneBounds[1][i], pos); - } - } - - if('rangemode' in axis && axis.rangemode === 'tozero') { - sceneBounds[0][i] = Math.min(sceneBounds[0][i], 0); - sceneBounds[1][i] = Math.max(sceneBounds[1][i], 0); - } - if(sceneBounds[0][i] > sceneBounds[1][i]) { - sceneBounds[0][i] = -1; - sceneBounds[1][i] = 1; - } else { - var d = sceneBounds[1][i] - sceneBounds[0][i]; - sceneBounds[0][i] -= d / 32.0; - sceneBounds[1][i] += d / 32.0; - } - - if(axis.autorange === 'reversed') { - // swap bounds: - var tmp = sceneBounds[0][i]; - sceneBounds[0][i] = sceneBounds[1][i]; - sceneBounds[1][i] = tmp; - } - } else { - var range = axis.range; - sceneBounds[0][i] = axis.r2l(range[0]); - sceneBounds[1][i] = axis.r2l(range[1]); - } - if(sceneBounds[0][i] === sceneBounds[1][i]) { - sceneBounds[0][i] -= 1; - sceneBounds[1][i] += 1; - } - axisDataRange[i] = sceneBounds[1][i] - sceneBounds[0][i]; - - // Update plot bounds - this.glplot.bounds[0][i] = sceneBounds[0][i] * dataScale[i]; - this.glplot.bounds[1][i] = sceneBounds[1][i] * dataScale[i]; - } - - var axesScaleRatio = [1, 1, 1]; - - // Compute axis scale per category - for(i = 0; i < 3; ++i) { - axis = fullSceneLayout[axisProperties[i]]; - axisType = axis.type; - var axisRatio = axisTypeRatios[axisType]; - axesScaleRatio[i] = Math.pow(axisRatio.acc, 1.0 / axisRatio.count) / dataScale[i]; - } - - /* - * Dynamically set the aspect ratio depending on the users aspect settings - */ - var axisAutoScaleFactor = 4; - var aspectRatio; - - if(fullSceneLayout.aspectmode === 'auto') { - if(Math.max.apply(null, axesScaleRatio) / Math.min.apply(null, axesScaleRatio) <= axisAutoScaleFactor) { - /* - * USE DATA MODE WHEN AXIS RANGE DIMENSIONS ARE RELATIVELY EQUAL - */ - - aspectRatio = axesScaleRatio; - } else { - /* - * USE EQUAL MODE WHEN AXIS RANGE DIMENSIONS ARE HIGHLY UNEQUAL - */ - aspectRatio = [1, 1, 1]; - } - } else if(fullSceneLayout.aspectmode === 'cube') { - aspectRatio = [1, 1, 1]; - } else if(fullSceneLayout.aspectmode === 'data') { - aspectRatio = axesScaleRatio; - } else if(fullSceneLayout.aspectmode === 'manual') { - var userRatio = fullSceneLayout.aspectratio; - aspectRatio = [userRatio.x, userRatio.y, userRatio.z]; - } else { - throw new Error('scene.js aspectRatio was not one of the enumerated types'); - } - - /* - * Write aspect Ratio back to user data and fullLayout so that it is modifies as user - * manipulates the aspectmode settings and the fullLayout is up-to-date. - */ - fullSceneLayout.aspectratio.x = sceneLayout.aspectratio.x = aspectRatio[0]; - fullSceneLayout.aspectratio.y = sceneLayout.aspectratio.y = aspectRatio[1]; - fullSceneLayout.aspectratio.z = sceneLayout.aspectratio.z = aspectRatio[2]; - - /* - * Finally assign the computed aspecratio to the glplot module. This will have an effect - * on the next render cycle. - */ - this.glplot.aspect = aspectRatio; - - - // Update frame position for multi plots - var domain = fullSceneLayout.domain || null; - var size = fullLayout._size || null; - - if(domain && size) { - var containerStyle = this.container.style; - containerStyle.position = 'absolute'; - containerStyle.left = (size.l + domain.x[0] * size.w) + 'px'; - containerStyle.top = (size.t + (1 - domain.y[1]) * size.h) + 'px'; - containerStyle.width = (size.w * (domain.x[1] - domain.x[0])) + 'px'; - containerStyle.height = (size.h * (domain.y[1] - domain.y[0])) + 'px'; - } - - // force redraw so that promise is returned when rendering is completed - this.glplot.redraw(); -}; - -proto.destroy = function() { - if(!this.glplot) return; - - this.camera.mouseListener.enabled = false; - this.container.removeEventListener('wheel', this.camera.wheelListener); - this.camera = this.glplot.camera = null; - this.glplot.dispose(); - this.container.parentNode.removeChild(this.container); - this.glplot = null; -}; - -// getOrbitCamera :: plotly_coords -> orbit_camera_coords -// inverse of getLayoutCamera -function getOrbitCamera(camera) { - return [ - [camera.eye.x, camera.eye.y, camera.eye.z], - [camera.center.x, camera.center.y, camera.center.z], - [camera.up.x, camera.up.y, camera.up.z] - ]; -} - -// getLayoutCamera :: orbit_camera_coords -> plotly_coords -// inverse of getOrbitCamera -function getLayoutCamera(camera) { - return { - up: {x: camera.up[0], y: camera.up[1], z: camera.up[2]}, - center: {x: camera.center[0], y: camera.center[1], z: camera.center[2]}, - eye: {x: camera.eye[0], y: camera.eye[1], z: camera.eye[2]}, - projection: {type: (camera._ortho === true) ? 'orthographic' : 'perspective'} - }; -} - -// get camera position in plotly coords from 'orbit-camera' coords -proto.getCamera = function getCamera() { - this.glplot.camera.view.recalcMatrix(this.camera.view.lastT()); - return getLayoutCamera(this.glplot.camera); -}; - -// set camera position with a set of plotly coords -proto.setCamera = function setCamera(cameraData) { - this.glplot.camera.lookAt.apply(this, getOrbitCamera(cameraData)); - - var newOrtho = (cameraData.projection.type === 'orthographic'); - var oldOrtho = this.glplot.camera._ortho; - - if(newOrtho !== oldOrtho) { - this.glplot.redraw(); - - var pixelRatio = this.glplot.pixelRatio; - - var RGBA = this.glplot.clearColor; - this.glplot.gl.clearColor( - RGBA[0], RGBA[1], RGBA[2], RGBA[3] - ); - this.glplot.gl.clear( - this.glplot.gl.DEPTH_BUFFER_BIT | - this.glplot.gl.COLOR_BUFFER_BIT - ); - - this.glplot.dispose(); - - initializeGLPlot(this, pixelRatio); - this.glplot.camera._ortho = newOrtho; - } -}; - -// save camera to user layout (i.e. gd.layout) -proto.saveCamera = function saveCamera(layout) { - var fullLayout = this.fullLayout; - var cameraData = this.getCamera(); - var cameraNestedProp = Lib.nestedProperty(layout, this.id + '.camera'); - var cameraDataLastSave = cameraNestedProp.get(); - var hasChanged = false; - - function same(x, y, i, j) { - var vectors = ['up', 'center', 'eye']; - var components = ['x', 'y', 'z']; - return y[vectors[i]] && (x[vectors[i]][components[j]] === y[vectors[i]][components[j]]); - } - - if(cameraDataLastSave === undefined) { - hasChanged = true; - } else { - for(var i = 0; i < 3; i++) { - for(var j = 0; j < 3; j++) { - if(!same(cameraData, cameraDataLastSave, i, j)) { - hasChanged = true; - break; - } - } - } - - if(!cameraDataLastSave.projection || ( - cameraData.projection && - cameraData.projection.type !== cameraDataLastSave.projection.type)) { - hasChanged = true; - } - } - - if(hasChanged) { - var preGUI = {}; - preGUI[this.id + '.camera'] = cameraDataLastSave; - Registry.call('_storeDirectGUIEdit', layout, fullLayout._preGUI, preGUI); - - cameraNestedProp.set(cameraData); - - var cameraFullNP = Lib.nestedProperty(fullLayout, this.id + '.camera'); - cameraFullNP.set(cameraData); - } - - return hasChanged; -}; - -proto.updateFx = function(dragmode, hovermode) { - var camera = this.camera; - if(camera) { - // rotate and orbital are synonymous - if(dragmode === 'orbit') { - camera.mode = 'orbit'; - camera.keyBindingMode = 'rotate'; - } else if(dragmode === 'turntable') { - camera.up = [0, 0, 1]; - camera.mode = 'turntable'; - camera.keyBindingMode = 'rotate'; - - // The setter for camera.mode animates the transition to z-up, - // but only if we *don't* explicitly set z-up earlier via the - // relayout. So push `up` back to layout & fullLayout manually now. - var gd = this.graphDiv; - var fullLayout = gd._fullLayout; - var fullCamera = this.fullSceneLayout.camera; - var x = fullCamera.up.x; - var y = fullCamera.up.y; - var z = fullCamera.up.z; - // only push `up` back to (full)layout if it's going to change - if(z / Math.sqrt(x * x + y * y + z * z) < 0.999) { - var attr = this.id + '.camera.up'; - var zUp = {x: 0, y: 0, z: 1}; - var edits = {}; - edits[attr] = zUp; - var layout = gd.layout; - Registry.call('_storeDirectGUIEdit', layout, fullLayout._preGUI, edits); - fullCamera.up = zUp; - Lib.nestedProperty(layout, attr).set(zUp); - } - } else { - // none rotation modes [pan or zoom] - camera.keyBindingMode = dragmode; - } - } - - // to put dragmode and hovermode on the same grounds from relayout - this.fullSceneLayout.hovermode = hovermode; -}; - -proto.toImage = function(format) { - if(!format) format = 'png'; - - if(this.staticMode) this.container.appendChild(STATIC_CANVAS); - - // Force redraw - this.glplot.redraw(); - - // Grab context and yank out pixels - var gl = this.glplot.gl; - var w = gl.drawingBufferWidth; - var h = gl.drawingBufferHeight; - - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - - var pixels = new Uint8Array(w * h * 4); - gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels); - - // Flip pixels - for(var j = 0, k = h - 1; j < k; ++j, --k) { - for(var i = 0; i < w; ++i) { - for(var l = 0; l < 4; ++l) { - var tmp = pixels[4 * (w * j + i) + l]; - pixels[4 * (w * j + i) + l] = pixels[4 * (w * k + i) + l]; - pixels[4 * (w * k + i) + l] = tmp; - } - } - } - - var canvas = document.createElement('canvas'); - canvas.width = w; - canvas.height = h; - var context = canvas.getContext('2d'); - var imageData = context.createImageData(w, h); - imageData.data.set(pixels); - context.putImageData(imageData, 0, 0); - - var dataURL; - - switch(format) { - case 'jpeg': - dataURL = canvas.toDataURL('image/jpeg'); - break; - case 'webp': - dataURL = canvas.toDataURL('image/webp'); - break; - default: - dataURL = canvas.toDataURL('image/png'); - } - - if(this.staticMode) this.container.removeChild(STATIC_CANVAS); - - return dataURL; -}; - -proto.setConvert = function() { - for(var i = 0; i < 3; i++) { - var ax = this.fullSceneLayout[axisProperties[i]]; - Axes.setConvert(ax, this.fullLayout); - ax.setScale = Lib.noop; - } -}; - -proto.make4thDimension = function() { - var _this = this; - var gd = _this.graphDiv; - var fullLayout = gd._fullLayout; - - // mock axis for hover formatting - _this.mockAxis = { - type: 'linear', - showexponent: 'all', - exponentformat: 'B' - }; - Axes.setConvert(_this.mockAxis, fullLayout); -}; - -module.exports = Scene; - -},{"../../components/fx":632,"../../lib":719,"../../lib/show_no_webgl_msg":740,"../../lib/str2rgbarray":742,"../../plots/cartesian/axes":767,"../../registry":847,"./layout/convert":811,"./layout/spikes":814,"./layout/tick_marks":815,"./project":816,"gl-plot3d":290,"has-passive-events":411,"webgl-context":556}],818:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function zip3(x, y, z, len) { - len = len || x.length; - - var result = new Array(len); - for(var i = 0; i < len; i++) { - result[i] = [x[i], y[i], z[i]]; - } - return result; -}; - -},{}],819:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('./font_attributes'); -var animationAttrs = _dereq_('./animation_attributes'); -var colorAttrs = _dereq_('../components/color/attributes'); -var padAttrs = _dereq_('./pad_attributes'); -var extendFlat = _dereq_('../lib/extend').extendFlat; - -var globalFont = fontAttrs({ - editType: 'calc', - -}); -globalFont.family.dflt = '"Open Sans", verdana, arial, sans-serif'; -globalFont.size.dflt = 12; -globalFont.color.dflt = colorAttrs.defaultLine; - -module.exports = { - font: globalFont, - title: { - text: { - valType: 'string', - - editType: 'layoutstyle', - - }, - font: fontAttrs({ - editType: 'layoutstyle', - - }), - xref: { - valType: 'enumerated', - dflt: 'container', - values: ['container', 'paper'], - - editType: 'layoutstyle', - - }, - yref: { - valType: 'enumerated', - dflt: 'container', - values: ['container', 'paper'], - - editType: 'layoutstyle', - - }, - x: { - valType: 'number', - min: 0, - max: 1, - dflt: 0.5, - - editType: 'layoutstyle', - - }, - y: { - valType: 'number', - min: 0, - max: 1, - dflt: 'auto', - - editType: 'layoutstyle', - - }, - xanchor: { - valType: 'enumerated', - dflt: 'auto', - values: ['auto', 'left', 'center', 'right'], - - editType: 'layoutstyle', - - }, - yanchor: { - valType: 'enumerated', - dflt: 'auto', - values: ['auto', 'top', 'middle', 'bottom'], - - editType: 'layoutstyle', - - }, - pad: extendFlat(padAttrs({editType: 'layoutstyle'}), { - - }), - editType: 'layoutstyle' - }, - autosize: { - valType: 'boolean', - - dflt: false, - // autosize, width, and height get special editType treatment in _relayout - // so we can handle noop resizes more efficiently - editType: 'none', - - }, - width: { - valType: 'number', - - min: 10, - dflt: 700, - editType: 'plot', - - }, - height: { - valType: 'number', - - min: 10, - dflt: 450, - editType: 'plot', - - }, - margin: { - l: { - valType: 'number', - - min: 0, - dflt: 80, - editType: 'plot', - - }, - r: { - valType: 'number', - - min: 0, - dflt: 80, - editType: 'plot', - - }, - t: { - valType: 'number', - - min: 0, - dflt: 100, - editType: 'plot', - - }, - b: { - valType: 'number', - - min: 0, - dflt: 80, - editType: 'plot', - - }, - pad: { - valType: 'number', - - min: 0, - dflt: 0, - editType: 'plot', - - }, - autoexpand: { - valType: 'boolean', - - dflt: true, - editType: 'plot' - }, - editType: 'plot' - }, - paper_bgcolor: { - valType: 'color', - - dflt: colorAttrs.background, - editType: 'plot', - - }, - plot_bgcolor: { - // defined here, but set in cartesian.supplyLayoutDefaults - // because it needs to know if there are (2D) axes or not - valType: 'color', - - dflt: colorAttrs.background, - editType: 'layoutstyle', - - }, - separators: { - valType: 'string', - - editType: 'plot', - - }, - hidesources: { - valType: 'boolean', - - dflt: false, - editType: 'plot', - - }, - showlegend: { - // handled in legend.supplyLayoutDefaults - // but included here because it's not in the legend object - valType: 'boolean', - - editType: 'legend', - - }, - colorway: { - valType: 'colorlist', - dflt: colorAttrs.defaults, - - editType: 'calc', - - }, - datarevision: { - valType: 'any', - - editType: 'calc', - - }, - uirevision: { - valType: 'any', - - editType: 'none', - - }, - editrevision: { - valType: 'any', - - editType: 'none', - - }, - selectionrevision: { - valType: 'any', - - editType: 'none', - - }, - template: { - valType: 'any', - - editType: 'calc', - - }, - modebar: { - orientation: { - valType: 'enumerated', - values: ['v', 'h'], - dflt: 'h', - - editType: 'modebar', - - }, - bgcolor: { - valType: 'color', - - editType: 'modebar', - - }, - color: { - valType: 'color', - - editType: 'modebar', - - }, - activecolor: { - valType: 'color', - - editType: 'modebar', - - }, - uirevision: { - valType: 'any', - - editType: 'none', - - }, - editType: 'modebar' - }, - - meta: { - valType: 'any', - arrayOk: true, - - editType: 'plot', - - }, - - transition: extendFlat({}, animationAttrs.transition, { - - editType: 'none' - }), - _deprecated: { - title: { - valType: 'string', - - editType: 'layoutstyle', - - }, - titlefont: fontAttrs({ - editType: 'layoutstyle', - - }) - } -}; - -},{"../components/color/attributes":592,"../lib/extend":710,"./animation_attributes":762,"./font_attributes":793,"./pad_attributes":827}],820:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var requiredVersion = '1.1.1'; - -var stylesNonMapbox = { - 'open-street-map': { - id: 'osm', - version: 8, - sources: { - 'plotly-osm-tiles': { - type: 'raster', - attribution: '© OpenStreetMap', - tiles: [ - 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png', - 'https://b.tile.openstreetmap.org/{z}/{x}/{y}.png' - ], - tileSize: 256 - } - }, - layers: [{ - id: 'plotly-osm-tiles', - type: 'raster', - source: 'plotly-osm-tiles', - minzoom: 0, - maxzoom: 22 - }] - }, - 'white-bg': { - id: 'white-bg', - version: 8, - sources: {}, - layers: [{ - id: 'white-bg', - type: 'background', - paint: {'background-color': '#FFFFFF'}, - minzoom: 0, - maxzoom: 22 - }] - }, - 'carto-positron': { - id: 'carto-positron', - version: 8, - sources: { - 'plotly-carto-positron': { - type: 'raster', - attribution: '© CARTO', - tiles: ['https://cartodb-basemaps-c.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png'], - tileSize: 256 - } - }, - layers: [{ - id: 'plotly-carto-positron', - type: 'raster', - source: 'plotly-carto-positron', - minzoom: 0, - maxzoom: 22 - }] - }, - 'carto-darkmatter': { - id: 'carto-darkmatter', - version: 8, - sources: { - 'plotly-carto-darkmatter': { - type: 'raster', - attribution: '© CARTO', - tiles: ['https://cartodb-basemaps-c.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png'], - tileSize: 256 - } - }, - layers: [{ - id: 'plotly-carto-darkmatter', - type: 'raster', - source: 'plotly-carto-darkmatter', - minzoom: 0, - maxzoom: 22 - }] - }, - 'stamen-terrain': { - id: 'stamen-terrain', - version: 8, - sources: { - 'plotly-stamen-terrain': { - type: 'raster', - attribution: 'Map tiles by Stamen Design, under CC BY 3.0 | Data by OpenStreetMap, under ODbL.', - tiles: ['https://stamen-tiles.a.ssl.fastly.net/terrain/{z}/{x}/{y}.png'], - tileSize: 256 - } - }, - layers: [{ - id: 'plotly-stamen-terrain', - type: 'raster', - source: 'plotly-stamen-terrain', - minzoom: 0, - maxzoom: 22 - }] - }, - 'stamen-toner': { - id: 'stamen-toner', - version: 8, - sources: { - 'plotly-stamen-toner': { - type: 'raster', - attribution: 'Map tiles by Stamen Design, under CC BY 3.0 | Data by OpenStreetMap, under ODbL.', - tiles: ['https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png'], - tileSize: 256 - } - }, - layers: [{ - id: 'plotly-stamen-toner', - type: 'raster', - source: 'plotly-stamen-toner', - minzoom: 0, - maxzoom: 22 - }] - }, - 'stamen-watercolor': { - id: 'stamen-watercolor', - version: 8, - sources: { - 'plotly-stamen-watercolor': { - type: 'raster', - attribution: 'Map tiles by Stamen Design, under CC BY 3.0 | Data by OpenStreetMap, under CC BY SA.', - tiles: ['https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.png'], - tileSize: 256 - } - }, - layers: [{ - id: 'plotly-stamen-watercolor', - type: 'raster', - source: 'plotly-stamen-watercolor', - minzoom: 0, - maxzoom: 22 - }] - } -}; - -var styleValuesNonMapbox = Object.keys(stylesNonMapbox); - -module.exports = { - requiredVersion: requiredVersion, - - styleUrlPrefix: 'mapbox://styles/mapbox/', - styleUrlSuffix: 'v9', - - styleValuesMapbox: ['basic', 'streets', 'outdoors', 'light', 'dark', 'satellite', 'satellite-streets'], - styleValueDflt: 'basic', - stylesNonMapbox: stylesNonMapbox, - styleValuesNonMapbox: styleValuesNonMapbox, - - traceLayerPrefix: 'plotly-trace-layer-', - layoutLayerPrefix: 'plotly-layout-layer-', - - wrongVersionErrorMsg: [ - 'Your custom plotly.js bundle is not using the correct mapbox-gl version', - 'Please install mapbox-gl@' + requiredVersion + '.' - ].join('\n'), - - noAccessTokenErrorMsg: [ - 'Missing Mapbox access token.', - 'Mapbox trace type require a Mapbox access token to be registered.', - 'For example:', - ' Plotly.plot(gd, data, layout, { mapboxAccessToken: \'my-access-token\' });', - 'More info here: https://www.mapbox.com/help/define-access-token/' - ].join('\n'), - - missingStyleErrorMsg: [ - 'No valid mapbox style found, please set `mapbox.style` to one of:', - styleValuesNonMapbox.join(', '), - 'or register a Mapbox access token to use a Mapbox-served style.' - ].join('\n'), - - multipleTokensErrorMsg: [ - 'Set multiple mapbox access token across different mapbox subplot,', - 'using first token found as mapbox-gl does not allow multiple' + - 'access tokens on the same page.' - ].join('\n'), - - mapOnErrorMsg: 'Mapbox error.', - - // Mapbox logo for static export - mapboxLogo: { - path0: 'm 10.5,1.24 c -5.11,0 -9.25,4.15 -9.25,9.25 0,5.1 4.15,9.25 9.25,9.25 5.1,0 9.25,-4.15 9.25,-9.25 0,-5.11 -4.14,-9.25 -9.25,-9.25 z m 4.39,11.53 c -1.93,1.93 -4.78,2.31 -6.7,2.31 -0.7,0 -1.41,-0.05 -2.1,-0.16 0,0 -1.02,-5.64 2.14,-8.81 0.83,-0.83 1.95,-1.28 3.13,-1.28 1.27,0 2.49,0.51 3.39,1.42 1.84,1.84 1.89,4.75 0.14,6.52 z', - path1: 'M 10.5,-0.01 C 4.7,-0.01 0,4.7 0,10.49 c 0,5.79 4.7,10.5 10.5,10.5 5.8,0 10.5,-4.7 10.5,-10.5 C 20.99,4.7 16.3,-0.01 10.5,-0.01 Z m 0,19.75 c -5.11,0 -9.25,-4.15 -9.25,-9.25 0,-5.1 4.14,-9.26 9.25,-9.26 5.11,0 9.25,4.15 9.25,9.25 0,5.13 -4.14,9.26 -9.25,9.26 z', - path2: 'M 14.74,6.25 C 12.9,4.41 9.98,4.35 8.23,6.1 5.07,9.27 6.09,14.91 6.09,14.91 c 0,0 5.64,1.02 8.81,-2.14 C 16.64,11 16.59,8.09 14.74,6.25 Z m -2.27,4.09 -0.91,1.87 -0.9,-1.87 -1.86,-0.91 1.86,-0.9 0.9,-1.87 0.91,1.87 1.86,0.9 z', - polygon: '11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 14.33,9.43 12.47,10.34' - }, - - // a subset of node_modules/mapbox-gl/dist/mapbox-gl.css - styleRules: { - map: 'overflow:hidden;position:relative;', - 'missing-css': 'display:none;', - 'canary': 'background-color:salmon;', - - // Reusing CSS directives from: https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.css - 'ctrl-bottom-left': 'position: absolute; pointer-events: none; z-index: 2; bottom: 0; left: 0;', - 'ctrl-bottom-right': 'position: absolute; pointer-events: none; z-index: 2; right: 0; bottom: 0;', - 'ctrl': 'clear: both; pointer-events: auto; transform: translate(0, 0);', - - // Compact ctrl - 'ctrl-attrib.mapboxgl-compact .mapboxgl-ctrl-attrib-inner': 'display: none;', - 'ctrl-attrib.mapboxgl-compact:hover .mapboxgl-ctrl-attrib-inner': 'display: block; margin-top:2px', - 'ctrl-attrib.mapboxgl-compact:hover': 'padding: 2px 24px 2px 4px; visibility: visible; margin-top: 6px;', - 'ctrl-attrib.mapboxgl-compact::after': 'content: ""; cursor: pointer; position: absolute; background-image: url(\'data:image/svg+xml;charset=utf-8,%3Csvg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"%3E %3Cpath fill="%23333333" fill-rule="evenodd" d="M4,10a6,6 0 1,0 12,0a6,6 0 1,0 -12,0 M9,7a1,1 0 1,0 2,0a1,1 0 1,0 -2,0 M9,10a1,1 0 1,1 2,0l0,3a1,1 0 1,1 -2,0"/%3E %3C/svg%3E\'); background-color: rgba(255, 255, 255, 0.5); width: 24px; height: 24px; box-sizing: border-box; border-radius: 12px;', - 'ctrl-attrib.mapboxgl-compact': 'min-height: 20px; padding: 0; margin: 10px; position: relative; background-color: #fff; border-radius: 3px 12px 12px 3px;', - 'ctrl-bottom-right > .mapboxgl-ctrl-attrib.mapboxgl-compact::after': 'bottom: 0; right: 0', - 'ctrl-bottom-left > .mapboxgl-ctrl-attrib.mapboxgl-compact::after': 'bottom: 0; left: 0', - - 'ctrl-bottom-left .mapboxgl-ctrl': 'margin: 0 0 10px 10px; float: left;', - 'ctrl-bottom-right .mapboxgl-ctrl': 'margin: 0 10px 10px 0; float: right;', - - 'ctrl-attrib': 'color: rgba(0, 0, 0, 0.75); text-decoration: none; font-size: 12px', - 'ctrl-attrib a': 'color: rgba(0, 0, 0, 0.75); text-decoration: none; font-size: 12px', - 'ctrl-attrib a:hover': 'color: inherit; text-decoration: underline;', - - 'ctrl-attrib .mapbox-improve-map': 'font-weight: bold; margin-left: 2px;', - 'attrib-empty': 'display: none;', - - // Compact Mapbox logo without text - 'ctrl-logo': 'display:block; width: 21px; height: 21px; background-image: url(\'data:image/svg+xml;charset=utf-8,%3C?xml version="1.0" encoding="utf-8"?%3E %3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 21 21" style="enable-background:new 0 0 21 21;" xml:space="preserve"%3E%3Cg transform="translate(0,0.01)"%3E%3Cpath d="m 10.5,1.24 c -5.11,0 -9.25,4.15 -9.25,9.25 0,5.1 4.15,9.25 9.25,9.25 5.1,0 9.25,-4.15 9.25,-9.25 0,-5.11 -4.14,-9.25 -9.25,-9.25 z m 4.39,11.53 c -1.93,1.93 -4.78,2.31 -6.7,2.31 -0.7,0 -1.41,-0.05 -2.1,-0.16 0,0 -1.02,-5.64 2.14,-8.81 0.83,-0.83 1.95,-1.28 3.13,-1.28 1.27,0 2.49,0.51 3.39,1.42 1.84,1.84 1.89,4.75 0.14,6.52 z" style="opacity:0.9;fill:%23ffffff;enable-background:new" class="st0"/%3E%3Cpath d="M 10.5,-0.01 C 4.7,-0.01 0,4.7 0,10.49 c 0,5.79 4.7,10.5 10.5,10.5 5.8,0 10.5,-4.7 10.5,-10.5 C 20.99,4.7 16.3,-0.01 10.5,-0.01 Z m 0,19.75 c -5.11,0 -9.25,-4.15 -9.25,-9.25 0,-5.1 4.14,-9.26 9.25,-9.26 5.11,0 9.25,4.15 9.25,9.25 0,5.13 -4.14,9.26 -9.25,9.26 z" style="opacity:0.35;enable-background:new" class="st1"/%3E%3Cpath d="M 14.74,6.25 C 12.9,4.41 9.98,4.35 8.23,6.1 5.07,9.27 6.09,14.91 6.09,14.91 c 0,0 5.64,1.02 8.81,-2.14 C 16.64,11 16.59,8.09 14.74,6.25 Z m -2.27,4.09 -0.91,1.87 -0.9,-1.87 -1.86,-0.91 1.86,-0.9 0.9,-1.87 0.91,1.87 1.86,0.9 z" style="opacity:0.35;enable-background:new" class="st1"/%3E%3Cpolygon points="11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 14.33,9.43 12.47,10.34 " style="opacity:0.9;fill:%23ffffff;enable-background:new" class="st0"/%3E%3C/g%3E%3C/svg%3E\')' - - // Mapbox logo WITH text below (commented out for now) - // 'ctrl-logo': 'width: 85px; height: 21px; margin: 0 0 -3px -3px; display: block; background-repeat: no-repeat; cursor: pointer; background-image: url(\'data:image/svg+xml;charset=utf-8,%3C?xml version="1.0" encoding="utf-8"?%3E%3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 84.49 21" style="enable-background:new 0 0 84.49 21;" xml:space="preserve"%3E%3Cg%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M83.25,14.26c0,0.12-0.09,0.21-0.21,0.21h-1.61c-0.13,0-0.24-0.06-0.3-0.17l-1.44-2.39l-1.44,2.39 c-0.06,0.11-0.18,0.17-0.3,0.17h-1.61c-0.04,0-0.08-0.01-0.12-0.03c-0.09-0.06-0.13-0.19-0.06-0.28l0,0l2.43-3.68L76.2,6.84 c-0.02-0.03-0.03-0.07-0.03-0.12c0-0.12,0.09-0.21,0.21-0.21h1.61c0.13,0,0.24,0.06,0.3,0.17l1.41,2.36l1.4-2.35 c0.06-0.11,0.18-0.17,0.3-0.17H83c0.04,0,0.08,0.01,0.12,0.03c0.09,0.06,0.13,0.19,0.06,0.28l0,0l-2.37,3.63l2.43,3.67 C83.24,14.18,83.25,14.22,83.25,14.26z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M66.24,9.59c-0.39-1.88-1.96-3.28-3.84-3.28c-1.03,0-2.03,0.42-2.73,1.18V3.51c0-0.13-0.1-0.23-0.23-0.23h-1.4 c-0.13,0-0.23,0.11-0.23,0.23v10.72c0,0.13,0.1,0.23,0.23,0.23h1.4c0.13,0,0.23-0.11,0.23-0.23V13.5c0.71,0.75,1.7,1.18,2.73,1.18 c1.88,0,3.45-1.41,3.84-3.29C66.37,10.79,66.37,10.18,66.24,9.59L66.24,9.59z M62.08,13c-1.32,0-2.39-1.11-2.41-2.48v-0.06 c0.02-1.38,1.09-2.48,2.41-2.48s2.42,1.12,2.42,2.51S63.41,13,62.08,13z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M71.67,6.32c-1.98-0.01-3.72,1.35-4.16,3.29c-0.13,0.59-0.13,1.19,0,1.77c0.44,1.94,2.17,3.32,4.17,3.3 c2.35,0,4.26-1.87,4.26-4.19S74.04,6.32,71.67,6.32z M71.65,13.01c-1.33,0-2.42-1.12-2.42-2.51s1.08-2.52,2.42-2.52 c1.33,0,2.42,1.12,2.42,2.51S72.99,13,71.65,13.01L71.65,13.01z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M62.08,7.98c-1.32,0-2.39,1.11-2.41,2.48v0.06C59.68,11.9,60.75,13,62.08,13s2.42-1.12,2.42-2.51 S63.41,7.98,62.08,7.98z M62.08,11.76c-0.63,0-1.14-0.56-1.17-1.25v-0.04c0.01-0.69,0.54-1.25,1.17-1.25 c0.63,0,1.17,0.57,1.17,1.27C63.24,11.2,62.73,11.76,62.08,11.76z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M71.65,7.98c-1.33,0-2.42,1.12-2.42,2.51S70.32,13,71.65,13s2.42-1.12,2.42-2.51S72.99,7.98,71.65,7.98z M71.65,11.76c-0.64,0-1.17-0.57-1.17-1.27c0-0.7,0.53-1.26,1.17-1.26s1.17,0.57,1.17,1.27C72.82,11.21,72.29,11.76,71.65,11.76z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M45.74,6.53h-1.4c-0.13,0-0.23,0.11-0.23,0.23v0.73c-0.71-0.75-1.7-1.18-2.73-1.18 c-2.17,0-3.94,1.87-3.94,4.19s1.77,4.19,3.94,4.19c1.04,0,2.03-0.43,2.73-1.19v0.73c0,0.13,0.1,0.23,0.23,0.23h1.4 c0.13,0,0.23-0.11,0.23-0.23V6.74c0-0.12-0.09-0.22-0.22-0.22C45.75,6.53,45.75,6.53,45.74,6.53z M44.12,10.53 C44.11,11.9,43.03,13,41.71,13s-2.42-1.12-2.42-2.51s1.08-2.52,2.4-2.52c1.33,0,2.39,1.11,2.41,2.48L44.12,10.53z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M41.71,7.98c-1.33,0-2.42,1.12-2.42,2.51S40.37,13,41.71,13s2.39-1.11,2.41-2.48v-0.06 C44.1,9.09,43.03,7.98,41.71,7.98z M40.55,10.49c0-0.7,0.52-1.27,1.17-1.27c0.64,0,1.14,0.56,1.17,1.25v0.04 c-0.01,0.68-0.53,1.24-1.17,1.24C41.08,11.75,40.55,11.19,40.55,10.49z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M52.41,6.32c-1.03,0-2.03,0.42-2.73,1.18V6.75c0-0.13-0.1-0.23-0.23-0.23h-1.4c-0.13,0-0.23,0.11-0.23,0.23 v10.72c0,0.13,0.1,0.23,0.23,0.23h1.4c0.13,0,0.23-0.1,0.23-0.23V13.5c0.71,0.75,1.7,1.18,2.74,1.18c2.17,0,3.94-1.87,3.94-4.19 S54.58,6.32,52.41,6.32z M52.08,13.01c-1.32,0-2.39-1.11-2.42-2.48v-0.07c0.02-1.38,1.09-2.49,2.4-2.49c1.32,0,2.41,1.12,2.41,2.51 S53.4,13,52.08,13.01L52.08,13.01z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M52.08,7.98c-1.32,0-2.39,1.11-2.42,2.48v0.06c0.03,1.38,1.1,2.48,2.42,2.48s2.41-1.12,2.41-2.51 S53.4,7.98,52.08,7.98z M52.08,11.76c-0.63,0-1.14-0.56-1.17-1.25v-0.04c0.01-0.69,0.54-1.25,1.17-1.25c0.63,0,1.17,0.58,1.17,1.27 S52.72,11.76,52.08,11.76z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M36.08,14.24c0,0.13-0.1,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68c0-0.98-0.74-1.71-1.62-1.71 c-0.8,0-1.46,0.7-1.59,1.62l0.01,4.66c0,0.13-0.11,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68 c0-0.98-0.74-1.71-1.62-1.71c-0.85,0-1.54,0.79-1.6,1.8v4.48c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V6.74 c0.01-0.13,0.1-0.22,0.23-0.22h1.4c0.13,0,0.22,0.11,0.23,0.22V7.4c0.5-0.68,1.3-1.09,2.16-1.1h0.03c1.09,0,2.09,0.6,2.6,1.55 c0.45-0.95,1.4-1.55,2.44-1.56c1.62,0,2.93,1.25,2.9,2.78L36.08,14.24z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M84.34,13.59l-0.07-0.13l-1.96-2.99l1.94-2.95c0.44-0.67,0.26-1.56-0.41-2.02c-0.02,0-0.03,0-0.04-0.01 c-0.23-0.15-0.5-0.22-0.78-0.22h-1.61c-0.56,0-1.08,0.29-1.37,0.78L79.72,6.6l-0.34-0.56C79.09,5.56,78.57,5.27,78,5.27h-1.6 c-0.6,0-1.13,0.37-1.35,0.92c-2.19-1.66-5.28-1.47-7.26,0.45c-0.35,0.34-0.65,0.72-0.89,1.14c-0.9-1.62-2.58-2.72-4.5-2.72 c-0.5,0-1.01,0.07-1.48,0.23V3.51c0-0.82-0.66-1.48-1.47-1.48h-1.4c-0.81,0-1.47,0.66-1.47,1.47v3.75 c-0.95-1.36-2.5-2.18-4.17-2.19c-0.74,0-1.46,0.16-2.12,0.47c-0.24-0.17-0.54-0.26-0.84-0.26h-1.4c-0.45,0-0.87,0.21-1.15,0.56 c-0.02-0.03-0.04-0.05-0.07-0.08c-0.28-0.3-0.68-0.47-1.09-0.47h-1.39c-0.3,0-0.6,0.09-0.84,0.26c-0.67-0.3-1.39-0.46-2.12-0.46 c-1.83,0-3.43,1-4.37,2.5c-0.2-0.46-0.48-0.89-0.83-1.25c-0.8-0.81-1.89-1.25-3.02-1.25h-0.01c-0.89,0.01-1.75,0.33-2.46,0.88 c-0.74-0.57-1.64-0.88-2.57-0.88H28.1c-0.29,0-0.58,0.03-0.86,0.11c-0.28,0.06-0.56,0.16-0.82,0.28c-0.21-0.12-0.45-0.18-0.7-0.18 h-1.4c-0.82,0-1.47,0.66-1.47,1.47v7.5c0,0.82,0.66,1.47,1.47,1.47h1.4c0.82,0,1.48-0.66,1.48-1.48l0,0V9.79 c0.03-0.36,0.23-0.59,0.36-0.59c0.18,0,0.38,0.18,0.38,0.47v4.57c0,0.82,0.66,1.47,1.47,1.47h1.41c0.82,0,1.47-0.66,1.47-1.47 l-0.01-4.57c0.06-0.32,0.25-0.47,0.35-0.47c0.18,0,0.38,0.18,0.38,0.47v4.57c0,0.82,0.66,1.47,1.47,1.47h1.41 c0.82,0,1.47-0.66,1.47-1.47v-0.38c0.96,1.29,2.46,2.06,4.06,2.06c0.74,0,1.46-0.16,2.12-0.47c0.24,0.17,0.54,0.26,0.84,0.26h1.39 c0.3,0,0.6-0.09,0.84-0.26v2.01c0,0.82,0.66,1.47,1.47,1.47h1.4c0.82,0,1.47-0.66,1.47-1.47v-1.77c0.48,0.15,0.99,0.23,1.49,0.22 c1.7,0,3.22-0.87,4.17-2.2v0.52c0,0.82,0.66,1.47,1.47,1.47h1.4c0.3,0,0.6-0.09,0.84-0.26c0.66,0.31,1.39,0.47,2.12,0.47 c1.92,0,3.6-1.1,4.49-2.73c1.54,2.65,4.95,3.53,7.58,1.98c0.18-0.11,0.36-0.22,0.53-0.36c0.22,0.55,0.76,0.91,1.35,0.9H78 c0.56,0,1.08-0.29,1.37-0.78l0.37-0.61l0.37,0.61c0.29,0.48,0.81,0.78,1.38,0.78h1.6c0.81,0,1.46-0.66,1.45-1.46 C84.49,14.02,84.44,13.8,84.34,13.59L84.34,13.59z M35.86,14.47h-1.41c-0.13,0-0.23-0.11-0.23-0.23V9.68 c0-0.98-0.74-1.71-1.62-1.71c-0.8,0-1.46,0.7-1.59,1.62l0.01,4.66c0,0.13-0.1,0.23-0.23,0.23h-1.41c-0.13,0-0.23-0.11-0.23-0.23 V9.68c0-0.98-0.74-1.71-1.62-1.71c-0.85,0-1.54,0.79-1.6,1.8v4.48c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23 V6.74c0.01-0.13,0.11-0.22,0.23-0.22h1.4c0.13,0,0.22,0.11,0.23,0.22V7.4c0.5-0.68,1.3-1.09,2.16-1.1h0.03 c1.09,0,2.09,0.6,2.6,1.55c0.45-0.95,1.4-1.55,2.44-1.56c1.62,0,2.93,1.25,2.9,2.78l0.01,5.16C36.09,14.36,35.98,14.46,35.86,14.47 L35.86,14.47z M45.97,14.24c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V13.5c-0.7,0.76-1.69,1.18-2.72,1.18 c-2.17,0-3.94-1.87-3.94-4.19s1.77-4.19,3.94-4.19c1.03,0,2.02,0.43,2.73,1.18V6.74c0-0.13,0.1-0.23,0.23-0.23h1.4 c0.12-0.01,0.22,0.08,0.23,0.21c0,0.01,0,0.01,0,0.02v7.51h-0.01V14.24z M52.41,14.67c-1.03,0-2.02-0.43-2.73-1.18v3.97 c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.1-0.23-0.23V6.75c0-0.13,0.1-0.22,0.23-0.22h1.4c0.13,0,0.23,0.11,0.23,0.23v0.73 c0.71-0.76,1.7-1.18,2.73-1.18c2.17,0,3.94,1.86,3.94,4.18S54.58,14.67,52.41,14.67z M66.24,11.39c-0.39,1.87-1.96,3.29-3.84,3.29 c-1.03,0-2.02-0.43-2.73-1.18v0.73c0,0.13-0.1,0.23-0.23,0.23h-1.4c-0.13,0-0.23-0.11-0.23-0.23V3.51c0-0.13,0.1-0.23,0.23-0.23 h1.4c0.13,0,0.23,0.11,0.23,0.23v3.97c0.71-0.75,1.7-1.18,2.73-1.17c1.88,0,3.45,1.4,3.84,3.28C66.37,10.19,66.37,10.8,66.24,11.39 L66.24,11.39L66.24,11.39z M71.67,14.68c-2,0.01-3.73-1.35-4.17-3.3c-0.13-0.59-0.13-1.19,0-1.77c0.44-1.94,2.17-3.31,4.17-3.3 c2.36,0,4.26,1.87,4.26,4.19S74.03,14.68,71.67,14.68L71.67,14.68z M83.04,14.47h-1.61c-0.13,0-0.24-0.06-0.3-0.17l-1.44-2.39 l-1.44,2.39c-0.06,0.11-0.18,0.17-0.3,0.17h-1.61c-0.04,0-0.08-0.01-0.12-0.03c-0.09-0.06-0.13-0.19-0.06-0.28l0,0l2.43-3.68 L76.2,6.84c-0.02-0.03-0.03-0.07-0.03-0.12c0-0.12,0.09-0.21,0.21-0.21h1.61c0.13,0,0.24,0.06,0.3,0.17l1.41,2.36l1.41-2.36 c0.06-0.11,0.18-0.17,0.3-0.17h1.61c0.04,0,0.08,0.01,0.12,0.03c0.09,0.06,0.13,0.19,0.06,0.28l0,0l-2.38,3.64l2.43,3.67 c0.02,0.03,0.03,0.07,0.03,0.12C83.25,14.38,83.16,14.47,83.04,14.47L83.04,14.47L83.04,14.47z"/%3E %3Cpath class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" d="M10.5,1.24c-5.11,0-9.25,4.15-9.25,9.25s4.15,9.25,9.25,9.25s9.25-4.15,9.25-9.25 C19.75,5.38,15.61,1.24,10.5,1.24z M14.89,12.77c-1.93,1.93-4.78,2.31-6.7,2.31c-0.7,0-1.41-0.05-2.1-0.16c0,0-1.02-5.64,2.14-8.81 c0.83-0.83,1.95-1.28,3.13-1.28c1.27,0,2.49,0.51,3.39,1.42C16.59,8.09,16.64,11,14.89,12.77z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M10.5-0.01C4.7-0.01,0,4.7,0,10.49s4.7,10.5,10.5,10.5S21,16.29,21,10.49C20.99,4.7,16.3-0.01,10.5-0.01z M10.5,19.74c-5.11,0-9.25-4.15-9.25-9.25s4.14-9.26,9.25-9.26s9.25,4.15,9.25,9.25C19.75,15.61,15.61,19.74,10.5,19.74z"/%3E %3Cpath class="st1" style="opacity:0.35; enable-background:new;" d="M14.74,6.25C12.9,4.41,9.98,4.35,8.23,6.1c-3.16,3.17-2.14,8.81-2.14,8.81s5.64,1.02,8.81-2.14 C16.64,11,16.59,8.09,14.74,6.25z M12.47,10.34l-0.91,1.87l-0.9-1.87L8.8,9.43l1.86-0.9l0.9-1.87l0.91,1.87l1.86,0.9L12.47,10.34z"/%3E %3Cpolygon class="st0" style="opacity:0.9; fill: %23FFFFFF; enable-background: new;" points="14.33,9.43 12.47,10.34 11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 "/%3E%3C/g%3E%3C/svg%3E\');' - } -}; - -},{}],821:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -/** - * Convert plotly.js 'textposition' to mapbox-gl 'anchor' and 'offset' - * (with the help of the icon size). - * - * @param {string} textpostion : plotly.js textposition value - * @param {number} iconSize : plotly.js icon size (e.g. marker.size for traces) - * - * @return {object} - * - anchor - * - offset - */ -module.exports = function convertTextOpts(textposition, iconSize) { - var parts = textposition.split(' '); - var vPos = parts[0]; - var hPos = parts[1]; - - // ballpack values - var factor = Lib.isArrayOrTypedArray(iconSize) ? Lib.mean(iconSize) : iconSize; - var xInc = 0.5 + (factor / 100); - var yInc = 1.5 + (factor / 100); - - var anchorVals = ['', '']; - var offset = [0, 0]; - - switch(vPos) { - case 'top': - anchorVals[0] = 'top'; - offset[1] = -yInc; - break; - case 'bottom': - anchorVals[0] = 'bottom'; - offset[1] = yInc; - break; - } - - switch(hPos) { - case 'left': - anchorVals[1] = 'right'; - offset[0] = -xInc; - break; - case 'right': - anchorVals[1] = 'left'; - offset[0] = xInc; - break; - } - - // Mapbox text-anchor must be one of: - // center, left, right, top, bottom, - // top-left, top-right, bottom-left, bottom-right - - var anchor; - if(anchorVals[0] && anchorVals[1]) anchor = anchorVals.join('-'); - else if(anchorVals[0]) anchor = anchorVals[0]; - else if(anchorVals[1]) anchor = anchorVals[1]; - else anchor = 'center'; - - return { anchor: anchor, offset: offset }; -}; - -},{"../../lib":719}],822:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var mapboxgl = _dereq_('mapbox-gl'); - -var Lib = _dereq_('../../lib'); -var getSubplotCalcData = _dereq_('../../plots/get_data').getSubplotCalcData; -var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); -var d3 = _dereq_('d3'); -var Drawing = _dereq_('../../components/drawing'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); - -var Mapbox = _dereq_('./mapbox'); - -var MAPBOX = 'mapbox'; - -var constants = exports.constants = _dereq_('./constants'); - -exports.name = MAPBOX; - -exports.attr = 'subplot'; - -exports.idRoot = MAPBOX; - -exports.idRegex = exports.attrRegex = Lib.counterRegex(MAPBOX); - -exports.attributes = { - subplot: { - valType: 'subplotid', - - dflt: 'mapbox', - editType: 'calc', - - } -}; - -exports.layoutAttributes = _dereq_('./layout_attributes'); - -exports.supplyLayoutDefaults = _dereq_('./layout_defaults'); - -exports.plot = function plot(gd) { - var fullLayout = gd._fullLayout; - var calcData = gd.calcdata; - var mapboxIds = fullLayout._subplots[MAPBOX]; - - if(mapboxgl.version !== constants.requiredVersion) { - throw new Error(constants.wrongVersionErrorMsg); - } - - var accessToken = findAccessToken(gd, mapboxIds); - mapboxgl.accessToken = accessToken; - - for(var i = 0; i < mapboxIds.length; i++) { - var id = mapboxIds[i]; - var subplotCalcData = getSubplotCalcData(calcData, MAPBOX, id); - var opts = fullLayout[id]; - var mapbox = opts._subplot; - - if(!mapbox) { - mapbox = new Mapbox(gd, id); - fullLayout[id]._subplot = mapbox; - } - - if(!mapbox.viewInitial) { - mapbox.viewInitial = { - center: Lib.extendFlat({}, opts.center), - zoom: opts.zoom, - bearing: opts.bearing, - pitch: opts.pitch - }; - } - - mapbox.plot(subplotCalcData, fullLayout, gd._promises); - } -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var oldMapboxKeys = oldFullLayout._subplots[MAPBOX] || []; - - for(var i = 0; i < oldMapboxKeys.length; i++) { - var oldMapboxKey = oldMapboxKeys[i]; - - if(!newFullLayout[oldMapboxKey] && !!oldFullLayout[oldMapboxKey]._subplot) { - oldFullLayout[oldMapboxKey]._subplot.destroy(); - } - } -}; - -exports.toSVG = function(gd) { - var fullLayout = gd._fullLayout; - var subplotIds = fullLayout._subplots[MAPBOX]; - var size = fullLayout._size; - - for(var i = 0; i < subplotIds.length; i++) { - var opts = fullLayout[subplotIds[i]]; - var domain = opts.domain; - var mapbox = opts._subplot; - - var imageData = mapbox.toImage('png'); - var image = fullLayout._glimages.append('svg:image'); - - image.attr({ - xmlns: xmlnsNamespaces.svg, - 'xlink:href': imageData, - x: size.l + size.w * domain.x[0], - y: size.t + size.h * (1 - domain.y[1]), - width: size.w * (domain.x[1] - domain.x[0]), - height: size.h * (domain.y[1] - domain.y[0]), - preserveAspectRatio: 'none' - }); - - var subplotDiv = d3.select(opts._subplot.div); - - // Append logo if visible - var hidden = subplotDiv.select('.mapboxgl-ctrl-logo').node().offsetParent === null; - if(!hidden) { - var logo = fullLayout._glimages.append('g'); - logo.attr('transform', 'translate(' + (size.l + size.w * domain.x[0] + 10) + ', ' + (size.t + size.h * (1 - domain.y[0]) - 31) + ')'); - logo.append('path') - .attr('d', constants.mapboxLogo.path0) - .style({ - opacity: 0.9, - fill: '#ffffff', - 'enable-background': 'new' - }); - - logo.append('path') - .attr('d', constants.mapboxLogo.path1) - .style('opacity', 0.35) - .style('enable-background', 'new'); - - logo.append('path') - .attr('d', constants.mapboxLogo.path2) - .style('opacity', 0.35) - .style('enable-background', 'new'); - - logo.append('polygon') - .attr('points', constants.mapboxLogo.polygon) - .style({ - opacity: 0.9, - fill: '#ffffff', - 'enable-background': 'new' - }); - } - - // Add attributions - var attributions = subplotDiv - .select('.mapboxgl-ctrl-attrib').text() - .replace('Improve this map', ''); - - var attributionGroup = fullLayout._glimages.append('g'); - - var attributionText = attributionGroup.append('text'); - attributionText - .text(attributions) - .classed('static-attribution', true) - .attr({ - 'font-size': 12, - 'font-family': 'Arial', - 'color': 'rgba(0, 0, 0, 0.75)', - 'text-anchor': 'end', - 'data-unformatted': attributions - }); - - var bBox = Drawing.bBox(attributionText.node()); - - // Break into multiple lines twice larger than domain - var maxWidth = size.w * (domain.x[1] - domain.x[0]); - if((bBox.width > maxWidth / 2)) { - var multilineAttributions = attributions.split('|').join('
'); - attributionText - .text(multilineAttributions) - .attr('data-unformatted', multilineAttributions) - .call(svgTextUtils.convertToTspans, gd); - - bBox = Drawing.bBox(attributionText.node()); - } - attributionText.attr('transform', 'translate(-3, ' + (-bBox.height + 8) + ')'); - - // Draw white rectangle behind text - attributionGroup - .insert('rect', '.static-attribution') - .attr({ - x: -bBox.width - 6, - y: -bBox.height - 3, - width: bBox.width + 6, - height: bBox.height + 3, - fill: 'rgba(255, 255, 255, 0.75)' - }); - - // Scale down if larger than domain - var scaleRatio = 1; - if((bBox.width + 6) > maxWidth) scaleRatio = maxWidth / (bBox.width + 6); - - var offset = [(size.l + size.w * domain.x[1]), (size.t + size.h * (1 - domain.y[0]))]; - attributionGroup.attr('transform', 'translate(' + offset[0] + ',' + offset[1] + ') scale(' + scaleRatio + ')'); - } -}; - -// N.B. mapbox-gl only allows one accessToken to be set per page: -// https://github.com/mapbox/mapbox-gl-js/issues/6331 -function findAccessToken(gd, mapboxIds) { - var fullLayout = gd._fullLayout; - var context = gd._context; - - // special case for Mapbox Atlas users - if(context.mapboxAccessToken === '') return ''; - - var tokensUseful = []; - var tokensListed = []; - var hasOneSetMapboxStyle = false; - var wontWork = false; - - // Take the first token we find in a mapbox subplot. - // These default to the context value but may be overridden. - for(var i = 0; i < mapboxIds.length; i++) { - var opts = fullLayout[mapboxIds[i]]; - var token = opts.accesstoken; - - if(isMapboxStyle(opts.style)) { - if(token) { - Lib.pushUnique(tokensUseful, token); - } else { - if(isMapboxStyle(opts._input.style)) { - Lib.error('Uses Mapbox map style, but did not set an access token.'); - hasOneSetMapboxStyle = true; - } - wontWork = true; - } - } - - if(token) { - Lib.pushUnique(tokensListed, token); - } - } - - if(wontWork) { - var msg = hasOneSetMapboxStyle ? - constants.noAccessTokenErrorMsg : - constants.missingStyleErrorMsg; - throw new Error(msg); - } - - if(tokensUseful.length) { - if(tokensUseful.length > 1) { - Lib.warn(constants.multipleTokensErrorMsg); - } - return tokensUseful[0]; - } else { - if(tokensListed.length) { - Lib.log([ - 'Listed mapbox access token(s)', tokensListed.join(','), - 'but did not use a Mapbox map style, ignoring token(s).' - ].join(' ')); - } - return ''; - } -} - -function isMapboxStyle(s) { - return typeof s === 'string' && constants.styleValuesMapbox.indexOf(s) !== -1; -} - -exports.updateFx = function(gd) { - var fullLayout = gd._fullLayout; - var subplotIds = fullLayout._subplots[MAPBOX]; - - for(var i = 0; i < subplotIds.length; i++) { - var subplotObj = fullLayout[subplotIds[i]]._subplot; - subplotObj.updateFx(fullLayout); - } -}; - -},{"../../components/drawing":614,"../../constants/xmlns_namespaces":696,"../../lib":719,"../../lib/svg_text_utils":743,"../../plots/get_data":802,"./constants":820,"./layout_attributes":824,"./layout_defaults":825,"./mapbox":826,"d3":163,"mapbox-gl":426}],823:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var convertTextOpts = _dereq_('./convert_text_opts'); -var constants = _dereq_('./constants'); - -function MapboxLayer(subplot, index) { - this.subplot = subplot; - - this.uid = subplot.uid + '-' + index; - this.index = index; - - this.idSource = 'source-' + this.uid; - this.idLayer = constants.layoutLayerPrefix + this.uid; - - // some state variable to check if a remove/add step is needed - this.sourceType = null; - this.source = null; - this.layerType = null; - this.below = null; - - // is layer currently visible - this.visible = false; -} - -var proto = MapboxLayer.prototype; - -proto.update = function update(opts) { - if(!this.visible) { - // IMPORTANT: must create source before layer to not cause errors - this.updateSource(opts); - this.updateLayer(opts); - } else if(this.needsNewSource(opts)) { - // IMPORTANT: must delete layer before source to not cause errors - this.removeLayer(); - this.updateSource(opts); - this.updateLayer(opts); - } else if(this.needsNewLayer(opts)) { - this.updateLayer(opts); - } else { - this.updateStyle(opts); - } - - this.visible = isVisible(opts); -}; - -proto.needsNewSource = function(opts) { - // for some reason changing layer to 'fill' or 'symbol' - // w/o changing the source throws an exception in mapbox-gl 0.18 ; - // stay safe and make new source on type changes - return ( - this.sourceType !== opts.sourcetype || - this.source !== opts.source || - this.layerType !== opts.type - ); -}; - -proto.needsNewLayer = function(opts) { - return ( - this.layerType !== opts.type || - this.below !== this.subplot.belowLookup['layout-' + this.index] - ); -}; - -proto.updateSource = function(opts) { - var map = this.subplot.map; - - if(map.getSource(this.idSource)) map.removeSource(this.idSource); - - this.sourceType = opts.sourcetype; - this.source = opts.source; - - if(!isVisible(opts)) return; - - var sourceOpts = convertSourceOpts(opts); - - map.addSource(this.idSource, sourceOpts); -}; - -proto.updateLayer = function(opts) { - var subplot = this.subplot; - var convertedOpts = convertOpts(opts); - - var below = this.subplot.belowLookup['layout-' + this.index]; - var _below; - - if(below === 'traces') { - var mapLayers = subplot.getMapLayers(); - - // find id of first plotly trace layer - for(var i = 0; i < mapLayers.length; i++) { - var layerId = mapLayers[i].id; - if(typeof layerId === 'string' && - layerId.indexOf(constants.traceLayerPrefix) === 0 - ) { - _below = layerId; - break; - } - } - } else { - _below = below; - } - - this.removeLayer(); - - if(isVisible(opts)) { - subplot.addLayer({ - id: this.idLayer, - source: this.idSource, - 'source-layer': opts.sourcelayer || '', - type: opts.type, - minzoom: opts.minzoom, - maxzoom: opts.maxzoom, - layout: convertedOpts.layout, - paint: convertedOpts.paint - }, _below); - } - - this.layerType = opts.type; - this.below = below; -}; - -proto.updateStyle = function(opts) { - if(isVisible(opts)) { - var convertedOpts = convertOpts(opts); - this.subplot.setOptions(this.idLayer, 'setLayoutProperty', convertedOpts.layout); - this.subplot.setOptions(this.idLayer, 'setPaintProperty', convertedOpts.paint); - } -}; - -proto.removeLayer = function() { - var map = this.subplot.map; - if(map.getLayer(this.idLayer)) { - map.removeLayer(this.idLayer); - } -}; - -proto.dispose = function() { - var map = this.subplot.map; - map.removeLayer(this.idLayer); - map.removeSource(this.idSource); -}; - -function isVisible(opts) { - var source = opts.source; - - return opts.visible && ( - Lib.isPlainObject(source) || - ((typeof source === 'string' || Array.isArray(source)) && source.length > 0) - ); -} - -function convertOpts(opts) { - var layout = {}; - var paint = {}; - - switch(opts.type) { - case 'circle': - Lib.extendFlat(paint, { - 'circle-radius': opts.circle.radius, - 'circle-color': opts.color, - 'circle-opacity': opts.opacity - }); - break; - - case 'line': - Lib.extendFlat(paint, { - 'line-width': opts.line.width, - 'line-color': opts.color, - 'line-opacity': opts.opacity, - 'line-dasharray': opts.line.dash - }); - break; - - case 'fill': - Lib.extendFlat(paint, { - 'fill-color': opts.color, - 'fill-outline-color': opts.fill.outlinecolor, - 'fill-opacity': opts.opacity - - // no way to pass specify outline width at the moment - }); - break; - - case 'symbol': - var symbol = opts.symbol; - var textOpts = convertTextOpts(symbol.textposition, symbol.iconsize); - - Lib.extendFlat(layout, { - 'icon-image': symbol.icon + '-15', - 'icon-size': symbol.iconsize / 10, - - 'text-field': symbol.text, - 'text-size': symbol.textfont.size, - 'text-anchor': textOpts.anchor, - 'text-offset': textOpts.offset, - 'symbol-placement': symbol.placement, - - // TODO font family - // 'text-font': symbol.textfont.family.split(', '), - }); - - Lib.extendFlat(paint, { - 'icon-color': opts.color, - 'text-color': symbol.textfont.color, - 'text-opacity': opts.opacity - }); - break; - } - - return { - layout: layout, - paint: paint - }; -} - -function convertSourceOpts(opts) { - var sourceType = opts.sourcetype; - var source = opts.source; - var sourceOpts = {type: sourceType}; - var field; - - if(sourceType === 'geojson') { - field = 'data'; - } else if(sourceType === 'vector') { - field = typeof source === 'string' ? 'url' : 'tiles'; - } else if(sourceType === 'raster') { - field = 'tiles'; - sourceOpts.tileSize = 256; - } else if(sourceType === 'image') { - field = 'url'; - sourceOpts.coordinates = opts.coordinates; - } - - sourceOpts[field] = source; - - if(opts.sourceattribution) sourceOpts.attribution = opts.sourceattribution; - - return sourceOpts; -} - -module.exports = function createMapboxLayer(subplot, index, opts) { - var mapboxLayer = new MapboxLayer(subplot, index); - - mapboxLayer.update(opts); - - return mapboxLayer; -}; - -},{"../../lib":719,"./constants":820,"./convert_text_opts":821}],824:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var defaultLine = _dereq_('../../components/color').defaultLine; -var domainAttrs = _dereq_('../domain').attributes; -var fontAttrs = _dereq_('../font_attributes'); -var textposition = _dereq_('../../traces/scatter/attributes').textposition; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - -var constants = _dereq_('./constants'); - -var fontAttr = fontAttrs({ - -}); -fontAttr.family.dflt = 'Open Sans Regular, Arial Unicode MS Regular'; - -var attrs = module.exports = overrideAll({ - _arrayAttrRegexps: [Lib.counterRegex('mapbox', '.layers', true)], - - domain: domainAttrs({name: 'mapbox'}), - - accesstoken: { - valType: 'string', - noBlank: true, - strict: true, - - - }, - style: { - valType: 'any', - values: constants.styleValuesMapbox.concat(constants.styleValuesNonMapbox), - dflt: constants.styleValueDflt, - - - }, - - center: { - lon: { - valType: 'number', - dflt: 0, - - - }, - lat: { - valType: 'number', - dflt: 0, - - - } - }, - zoom: { - valType: 'number', - dflt: 1, - - - }, - bearing: { - valType: 'number', - dflt: 0, - - - }, - pitch: { - valType: 'number', - dflt: 0, - - - }, - - layers: templatedArray('layer', { - visible: { - valType: 'boolean', - - dflt: true, - - }, - sourcetype: { - valType: 'enumerated', - values: ['geojson', 'vector', 'raster', 'image'], - dflt: 'geojson', - - - }, - - source: { - valType: 'any', - - - }, - - sourcelayer: { - valType: 'string', - dflt: '', - - - }, - - sourceattribution: { - valType: 'string', - - - }, - - type: { - valType: 'enumerated', - values: ['circle', 'line', 'fill', 'symbol', 'raster'], - dflt: 'circle', - - - }, - - coordinates: { - valType: 'any', - - - }, - - // attributes shared between all types - below: { - valType: 'string', - - - }, - color: { - valType: 'color', - dflt: defaultLine, - - - }, - opacity: { - valType: 'number', - min: 0, - max: 1, - dflt: 1, - - - }, - minzoom: { - valType: 'number', - min: 0, - max: 24, - dflt: 0, - - - }, - maxzoom: { - valType: 'number', - min: 0, - max: 24, - dflt: 24, - - - }, - - // type-specific style attributes - circle: { - radius: { - valType: 'number', - dflt: 15, - - - } - }, - - line: { - width: { - valType: 'number', - dflt: 2, - - - }, - dash: { - valType: 'data_array', - - - } - }, - - fill: { - outlinecolor: { - valType: 'color', - dflt: defaultLine, - - - } - }, - - symbol: { - icon: { - valType: 'string', - dflt: 'marker', - - - }, - iconsize: { - valType: 'number', - dflt: 10, - - - }, - text: { - valType: 'string', - dflt: '', - - - }, - placement: { - valType: 'enumerated', - values: ['point', 'line', 'line-center'], - dflt: 'point', - - - }, - textfont: fontAttr, - textposition: Lib.extendFlat({}, textposition, { arrayOk: false }) - } - }) -}, 'plot', 'from-root'); - -// set uirevision outside of overrideAll so it can be `editType: 'none'` -attrs.uirevision = { - valType: 'any', - - editType: 'none', - -}; - -},{"../../components/color":593,"../../lib":719,"../../plot_api/edit_types":750,"../../plot_api/plot_template":757,"../../traces/scatter/attributes":1112,"../domain":792,"../font_attributes":793,"./constants":820}],825:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var handleSubplotDefaults = _dereq_('../subplot_defaults'); -var handleArrayContainerDefaults = _dereq_('../array_container_defaults'); -var layoutAttributes = _dereq_('./layout_attributes'); - - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - handleSubplotDefaults(layoutIn, layoutOut, fullData, { - type: 'mapbox', - attributes: layoutAttributes, - handleDefaults: handleDefaults, - partition: 'y', - accessToken: layoutOut._mapboxAccessToken - }); -}; - -function handleDefaults(containerIn, containerOut, coerce, opts) { - coerce('accesstoken', opts.accessToken); - coerce('style'); - coerce('center.lon'); - coerce('center.lat'); - coerce('zoom'); - coerce('bearing'); - coerce('pitch'); - - handleArrayContainerDefaults(containerIn, containerOut, { - name: 'layers', - handleItemDefaults: handleLayerDefaults - }); - - // copy ref to input container to update 'center' and 'zoom' on map move - containerOut._input = containerIn; -} - -function handleLayerDefaults(layerIn, layerOut) { - function coerce(attr, dflt) { - return Lib.coerce(layerIn, layerOut, layoutAttributes.layers, attr, dflt); - } - - var visible = coerce('visible'); - if(visible) { - var sourceType = coerce('sourcetype'); - var mustBeRasterLayer = sourceType === 'raster' || sourceType === 'image'; - - coerce('source'); - coerce('sourceattribution'); - - if(sourceType === 'vector') { - coerce('sourcelayer'); - } - - if(sourceType === 'image') { - coerce('coordinates'); - } - - var typeDflt; - if(mustBeRasterLayer) typeDflt = 'raster'; - - var type = coerce('type', typeDflt); - - if(mustBeRasterLayer && type !== 'raster') { - type = layerOut.type = 'raster'; - Lib.log('Source types *raster* and *image* must drawn *raster* layer type.'); - } - - coerce('below'); - coerce('color'); - coerce('opacity'); - coerce('minzoom'); - coerce('maxzoom'); - - if(type === 'circle') { - coerce('circle.radius'); - } - - if(type === 'line') { - coerce('line.width'); - coerce('line.dash'); - } - - if(type === 'fill') { - coerce('fill.outlinecolor'); - } - - if(type === 'symbol') { - coerce('symbol.icon'); - coerce('symbol.iconsize'); - - coerce('symbol.text'); - Lib.coerceFont(coerce, 'symbol.textfont'); - coerce('symbol.textposition'); - coerce('symbol.placement'); - } - } -} - -},{"../../lib":719,"../array_container_defaults":763,"../subplot_defaults":842,"./layout_attributes":824}],826:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* global PlotlyGeoAssets:false */ - -var mapboxgl = _dereq_('mapbox-gl'); -var d3 = _dereq_('d3'); - -var Fx = _dereq_('../../components/fx'); -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); -var Axes = _dereq_('../cartesian/axes'); -var dragElement = _dereq_('../../components/dragelement'); -var prepSelect = _dereq_('../cartesian/select').prepSelect; -var selectOnClick = _dereq_('../cartesian/select').selectOnClick; -var constants = _dereq_('./constants'); -var createMapboxLayer = _dereq_('./layers'); - -function Mapbox(gd, id) { - this.id = id; - this.gd = gd; - - var fullLayout = gd._fullLayout; - var context = gd._context; - - this.container = fullLayout._glcontainer.node(); - this.isStatic = context.staticPlot; - - // unique id for this Mapbox instance - this.uid = fullLayout._uid + '-' + this.id; - - // create framework on instantiation for a smoother first plot call - this.div = null; - this.xaxis = null; - this.yaxis = null; - this.createFramework(fullLayout); - - // state variables used to infer how and what to update - this.map = null; - this.accessToken = null; - this.styleObj = null; - this.traceHash = {}; - this.layerList = []; - this.belowLookup = {}; -} - -var proto = Mapbox.prototype; - -proto.plot = function(calcData, fullLayout, promises) { - var self = this; - var opts = fullLayout[self.id]; - - // remove map and create a new map if access token has change - if(self.map && (opts.accesstoken !== self.accessToken)) { - self.map.remove(); - self.map = null; - self.styleObj = null; - self.traceHash = []; - self.layerList = {}; - } - - var promise; - - if(!self.map) { - promise = new Promise(function(resolve, reject) { - self.createMap(calcData, fullLayout, resolve, reject); - }); - } else { - promise = new Promise(function(resolve, reject) { - self.updateMap(calcData, fullLayout, resolve, reject); - }); - } - - promises.push(promise); -}; - -proto.createMap = function(calcData, fullLayout, resolve, reject) { - var self = this; - var opts = fullLayout[self.id]; - - // store style id and URL or object - var styleObj = self.styleObj = getStyleObj(opts.style); - - // store access token associated with this map - self.accessToken = opts.accesstoken; - - // create the map! - var map = self.map = new mapboxgl.Map({ - container: self.div, - - style: styleObj.style, - center: convertCenter(opts.center), - zoom: opts.zoom, - bearing: opts.bearing, - pitch: opts.pitch, - - interactive: !self.isStatic, - preserveDrawingBuffer: self.isStatic, - - doubleClickZoom: false, - boxZoom: false, - - attributionControl: false - }) - .addControl(new mapboxgl.AttributionControl({ - compact: true - })); - - - // make sure canvas does not inherit left and top css - map._canvas.style.left = '0px'; - map._canvas.style.top = '0px'; - - self.rejectOnError(reject); - - if(!self.isStatic) { - self.initFx(calcData, fullLayout); - } - - var promises = []; - - promises.push(new Promise(function(resolve) { - map.once('load', resolve); - })); - - promises = promises.concat(self.fetchMapData(calcData, fullLayout)); - - Promise.all(promises).then(function() { - self.fillBelowLookup(calcData, fullLayout); - self.updateData(calcData); - self.updateLayout(fullLayout); - self.resolveOnRender(resolve); - }).catch(reject); -}; - -proto.fetchMapData = function(calcData) { - var promises = []; - - function fetch(url) { - return new Promise(function(resolve, reject) { - d3.json(url, function(err, d) { - if(err) { - delete PlotlyGeoAssets[url]; - var msg = err.status === 404 ? - ('GeoJSON at URL "' + url + '" does not exist.') : - ('Unexpected error while fetching from ' + url); - return reject(new Error(msg)); - } - - PlotlyGeoAssets[url] = d; - resolve(d); - }); - }); - } - - for(var i = 0; i < calcData.length; i++) { - var trace = calcData[i][0].trace; - var url = trace.geojson; - - if(typeof url === 'string' && !PlotlyGeoAssets[url]) { - PlotlyGeoAssets[url] = 'pending'; - promises.push(fetch(url)); - } - } - - return promises; -}; - -proto.updateMap = function(calcData, fullLayout, resolve, reject) { - var self = this; - var map = self.map; - var opts = fullLayout[this.id]; - - self.rejectOnError(reject); - - var promises = []; - var styleObj = getStyleObj(opts.style); - - if(self.styleObj.id !== styleObj.id) { - self.styleObj = styleObj; - map.setStyle(styleObj.style); - - // need to rebuild trace layers on reload - // to avoid 'lost event' errors - self.traceHash = {}; - - promises.push(new Promise(function(resolve) { - map.once('styledata', resolve); - })); - } - - promises = promises.concat(self.fetchMapData(calcData, fullLayout)); - - Promise.all(promises).then(function() { - self.fillBelowLookup(calcData, fullLayout); - self.updateData(calcData); - self.updateLayout(fullLayout); - self.resolveOnRender(resolve); - }).catch(reject); -}; - -proto.fillBelowLookup = function(calcData, fullLayout) { - var opts = fullLayout[this.id]; - var layers = opts.layers; - var i, val; - - var belowLookup = this.belowLookup = {}; - var hasTraceAtTop = false; - - for(i = 0; i < calcData.length; i++) { - var trace = calcData[i][0].trace; - var _module = trace._module; - - if(typeof trace.below === 'string') { - val = trace.below; - } else if(_module.getBelow) { - // 'smart' default that depend the map's base layers - val = _module.getBelow(trace, this); - } - - if(val === '') { - hasTraceAtTop = true; - } - - belowLookup['trace-' + trace.uid] = val || ''; - } - - for(i = 0; i < layers.length; i++) { - var item = layers[i]; - - if(typeof item.below === 'string') { - val = item.below; - } else if(hasTraceAtTop) { - // if one or more trace(s) set `below:''` and - // layers[i].below is unset, - // place layer below traces - val = 'traces'; - } else { - val = ''; - } - - belowLookup['layout-' + i] = val; - } - - // N.B. If multiple layers have the 'below' value, - // we must clear the stashed 'below' field in order - // to make `traceHash[k].update()` and `layerList[i].update()` - // remove/add the all those layers to have preserve - // the correct layer ordering - var val2list = {}; - var k, id; - - for(k in belowLookup) { - val = belowLookup[k]; - if(val2list[val]) { - val2list[val].push(k); - } else { - val2list[val] = [k]; - } - } - - for(val in val2list) { - var list = val2list[val]; - if(list.length > 1) { - for(i = 0; i < list.length; i++) { - k = list[i]; - if(k.indexOf('trace-') === 0) { - id = k.split('trace-')[1]; - if(this.traceHash[id]) { - this.traceHash[id].below = null; - } - } else if(k.indexOf('layout-') === 0) { - id = k.split('layout-')[1]; - if(this.layerList[id]) { - this.layerList[id].below = null; - } - } - } - } - } -}; - -var traceType2orderIndex = { - choroplethmapbox: 0, - densitymapbox: 1, - scattermapbox: 2 -}; - -proto.updateData = function(calcData) { - var traceHash = this.traceHash; - var traceObj, trace, i, j; - - // Need to sort here by trace type here, - // in case traces with different `type` have the same - // below value, but sorting we ensure that - // e.g. choroplethmapbox traces will be below scattermapbox traces - var calcDataSorted = calcData.slice().sort(function(a, b) { - return ( - traceType2orderIndex[a[0].trace.type] - - traceType2orderIndex[b[0].trace.type] - ); - }); - - // update or create trace objects - for(i = 0; i < calcDataSorted.length; i++) { - var calcTrace = calcDataSorted[i]; - - trace = calcTrace[0].trace; - traceObj = traceHash[trace.uid]; - - if(traceObj) { - traceObj.update(calcTrace); - } else if(trace._module) { - traceHash[trace.uid] = trace._module.plot(this, calcTrace); - } - } - - // remove empty trace objects - var ids = Object.keys(traceHash); - idLoop: - for(i = 0; i < ids.length; i++) { - var id = ids[i]; - - for(j = 0; j < calcData.length; j++) { - trace = calcData[j][0].trace; - if(id === trace.uid) continue idLoop; - } - - traceObj = traceHash[id]; - traceObj.dispose(); - delete traceHash[id]; - } -}; - -proto.updateLayout = function(fullLayout) { - var map = this.map; - var opts = fullLayout[this.id]; - - map.setCenter(convertCenter(opts.center)); - map.setZoom(opts.zoom); - map.setBearing(opts.bearing); - map.setPitch(opts.pitch); - - this.updateLayers(fullLayout); - this.updateFramework(fullLayout); - this.updateFx(fullLayout); - this.map.resize(); - - if(this.gd._context._scrollZoom.mapbox) { - map.scrollZoom.enable(); - } else { - map.scrollZoom.disable(); - } -}; - -proto.resolveOnRender = function(resolve) { - var map = this.map; - - map.on('render', function onRender() { - if(map.loaded()) { - map.off('render', onRender); - // resolve at end of render loop - setTimeout(resolve, 0); - } - }); -}; - -proto.rejectOnError = function(reject) { - var map = this.map; - - function handler() { - reject(new Error(constants.mapOnErrorMsg)); - } - - map.once('error', handler); - map.once('style.error', handler); - map.once('source.error', handler); - map.once('tile.error', handler); - map.once('layer.error', handler); -}; - -proto.createFramework = function(fullLayout) { - var self = this; - - var div = self.div = document.createElement('div'); - div.id = self.uid; - div.style.position = 'absolute'; - self.container.appendChild(div); - - // create mock x/y axes for hover routine - self.xaxis = { - _id: 'x', - c2p: function(v) { return self.project(v).x; } - }; - self.yaxis = { - _id: 'y', - c2p: function(v) { return self.project(v).y; } - }; - - self.updateFramework(fullLayout); - - // mock axis for hover formatting - self.mockAxis = { - type: 'linear', - showexponent: 'all', - exponentformat: 'B' - }; - Axes.setConvert(self.mockAxis, fullLayout); -}; - -proto.initFx = function(calcData, fullLayout) { - var self = this; - var gd = self.gd; - var map = self.map; - - var wheeling = false; - - // keep track of pan / zoom in user layout and emit relayout event - map.on('moveend', function(evt) { - if(!self.map) return; - - var fullLayoutNow = gd._fullLayout; - - // 'moveend' gets triggered by map.setCenter, map.setZoom, - // map.setBearing and map.setPitch. - // - // Here, we make sure that state updates amd 'plotly_relayout' - // are triggered only when the 'moveend' originates from a - // mouse target (filtering out API calls) to not - // duplicate 'plotly_relayout' events. - - if(evt.originalEvent || wheeling) { - var optsNow = fullLayoutNow[self.id]; - Registry.call('_storeDirectGUIEdit', gd.layout, fullLayoutNow._preGUI, self.getViewEdits(optsNow)); - - var viewNow = self.getView(); - optsNow._input.center = optsNow.center = viewNow.center; - optsNow._input.zoom = optsNow.zoom = viewNow.zoom; - optsNow._input.bearing = optsNow.bearing = viewNow.bearing; - optsNow._input.pitch = optsNow.pitch = viewNow.pitch; - - gd.emit('plotly_relayout', self.getViewEdits(viewNow)); - } - wheeling = false; - - if(fullLayoutNow._rehover) { - fullLayoutNow._rehover(); - } - }); - - map.on('wheel', function() { - wheeling = true; - }); - - map.on('mousemove', function(evt) { - var bb = self.div.getBoundingClientRect(); - - // some hackery to get Fx.hover to work - evt.clientX = evt.point.x + bb.left; - evt.clientY = evt.point.y + bb.top; - - evt.target.getBoundingClientRect = function() { return bb; }; - - self.xaxis.p2c = function() { return evt.lngLat.lng; }; - self.yaxis.p2c = function() { return evt.lngLat.lat; }; - - gd._fullLayout._rehover = function() { - if(gd._fullLayout._hoversubplot === self.id) { - Fx.hover(gd, evt, self.id); - } - }; - - Fx.hover(gd, evt, self.id); - gd._fullLayout._hoversubplot = self.id; - }); - - function unhover() { - Fx.loneUnhover(fullLayout._hoverlayer); - } - - map.on('dragstart', unhover); - map.on('zoomstart', unhover); - - map.on('mouseout', function() { - gd._fullLayout._hoversubplot = null; - }); - - function emitUpdate() { - var viewNow = self.getView(); - gd.emit('plotly_relayouting', self.getViewEdits(viewNow)); - } - - map.on('drag', emitUpdate); - map.on('zoom', emitUpdate); - - map.on('dblclick', function() { - var optsNow = gd._fullLayout[self.id]; - Registry.call('_storeDirectGUIEdit', gd.layout, gd._fullLayout._preGUI, self.getViewEdits(optsNow)); - - var viewInitial = self.viewInitial; - map.setCenter(convertCenter(viewInitial.center)); - map.setZoom(viewInitial.zoom); - map.setBearing(viewInitial.bearing); - map.setPitch(viewInitial.pitch); - - var viewNow = self.getView(); - optsNow._input.center = optsNow.center = viewNow.center; - optsNow._input.zoom = optsNow.zoom = viewNow.zoom; - optsNow._input.bearing = optsNow.bearing = viewNow.bearing; - optsNow._input.pitch = optsNow.pitch = viewNow.pitch; - - gd.emit('plotly_doubleclick', null); - gd.emit('plotly_relayout', self.getViewEdits(viewNow)); - }); - - // define event handlers on map creation, to keep one ref per map, - // so that map.on / map.off in updateFx works as expected - self.clearSelect = function() { - gd._fullLayout._zoomlayer.selectAll('.select-outline').remove(); - }; - - /** - * Returns a click handler function that is supposed - * to handle clicks in pan mode. - */ - self.onClickInPanFn = function(dragOptions) { - return function(evt) { - var clickMode = gd._fullLayout.clickmode; - - if(clickMode.indexOf('select') > -1) { - selectOnClick(evt.originalEvent, gd, [self.xaxis], [self.yaxis], self.id, dragOptions); - } - - if(clickMode.indexOf('event') > -1) { - // TODO: this does not support right-click. If we want to support it, we - // would likely need to change mapbox to use dragElement instead of straight - // mapbox event binding. Or perhaps better, make a simple wrapper with the - // right mousedown, mousemove, and mouseup handlers just for a left/right click - // pie would use this too. - Fx.click(gd, evt.originalEvent); - } - }; - }; -}; - -proto.updateFx = function(fullLayout) { - var self = this; - var map = self.map; - var gd = self.gd; - - if(self.isStatic) return; - - function invert(pxpy) { - var obj = self.map.unproject(pxpy); - return [obj.lng, obj.lat]; - } - - var dragMode = fullLayout.dragmode; - var fillRangeItems; - - if(dragMode === 'select') { - fillRangeItems = function(eventData, poly) { - var ranges = eventData.range = {}; - ranges[self.id] = [ - invert([poly.xmin, poly.ymin]), - invert([poly.xmax, poly.ymax]) - ]; - }; - } else { - fillRangeItems = function(eventData, poly, pts) { - var dataPts = eventData.lassoPoints = {}; - dataPts[self.id] = pts.filtered.map(invert); - }; - } - - // Note: dragOptions is needed to be declared for all dragmodes because - // it's the object that holds persistent selection state. - // Merge old dragOptions with new to keep possibly initialized - // persistent selection state. - var oldDragOptions = self.dragOptions; - self.dragOptions = Lib.extendDeep(oldDragOptions || {}, { - element: self.div, - gd: gd, - plotinfo: { - id: self.id, - xaxis: self.xaxis, - yaxis: self.yaxis, - fillRangeItems: fillRangeItems - }, - xaxes: [self.xaxis], - yaxes: [self.yaxis], - subplot: self.id - }); - - // Unregister the old handler before potentially registering - // a new one. Otherwise multiple click handlers might - // be registered resulting in unwanted behavior. - map.off('click', self.onClickInPanHandler); - if(dragMode === 'select' || dragMode === 'lasso') { - map.dragPan.disable(); - map.on('zoomstart', self.clearSelect); - - self.dragOptions.prepFn = function(e, startX, startY) { - prepSelect(e, startX, startY, self.dragOptions, dragMode); - }; - - dragElement.init(self.dragOptions); - } else { - map.dragPan.enable(); - map.off('zoomstart', self.clearSelect); - self.div.onmousedown = null; - - // TODO: this does not support right-click. If we want to support it, we - // would likely need to change mapbox to use dragElement instead of straight - // mapbox event binding. Or perhaps better, make a simple wrapper with the - // right mousedown, mousemove, and mouseup handlers just for a left/right click - // pie would use this too. - self.onClickInPanHandler = self.onClickInPanFn(self.dragOptions); - map.on('click', self.onClickInPanHandler); - } -}; - -proto.updateFramework = function(fullLayout) { - var domain = fullLayout[this.id].domain; - var size = fullLayout._size; - - var style = this.div.style; - style.width = size.w * (domain.x[1] - domain.x[0]) + 'px'; - style.height = size.h * (domain.y[1] - domain.y[0]) + 'px'; - style.left = size.l + domain.x[0] * size.w + 'px'; - style.top = size.t + (1 - domain.y[1]) * size.h + 'px'; - - this.xaxis._offset = size.l + domain.x[0] * size.w; - this.xaxis._length = size.w * (domain.x[1] - domain.x[0]); - - this.yaxis._offset = size.t + (1 - domain.y[1]) * size.h; - this.yaxis._length = size.h * (domain.y[1] - domain.y[0]); -}; - -proto.updateLayers = function(fullLayout) { - var opts = fullLayout[this.id]; - var layers = opts.layers; - var layerList = this.layerList; - var i; - - // if the layer arrays don't match, - // don't try to be smart, - // delete them all, and start all over. - - if(layers.length !== layerList.length) { - for(i = 0; i < layerList.length; i++) { - layerList[i].dispose(); - } - - layerList = this.layerList = []; - - for(i = 0; i < layers.length; i++) { - layerList.push(createMapboxLayer(this, i, layers[i])); - } - } else { - for(i = 0; i < layers.length; i++) { - layerList[i].update(layers[i]); - } - } -}; - -proto.destroy = function() { - if(this.map) { - this.map.remove(); - this.map = null; - this.container.removeChild(this.div); - } -}; - -proto.toImage = function() { - this.map.stop(); - return this.map.getCanvas().toDataURL(); -}; - -// convenience wrapper to create set multiple layer -// 'layout' or 'paint options at once. -proto.setOptions = function(id, methodName, opts) { - for(var k in opts) { - this.map[methodName](id, k, opts[k]); - } -}; - -proto.getMapLayers = function() { - return this.map.getStyle().layers; -}; - -// convenience wrapper that first check in 'below' references -// a layer that exist and then add the layer to the map, -proto.addLayer = function(opts, below) { - var map = this.map; - - if(typeof below === 'string') { - if(below === '') { - map.addLayer(opts, below); - return; - } - - var mapLayers = this.getMapLayers(); - for(var i = 0; i < mapLayers.length; i++) { - if(below === mapLayers[i].id) { - map.addLayer(opts, below); - return; - } - } - - Lib.warn([ - 'Trying to add layer with *below* value', - below, - 'referencing a layer that does not exist', - 'or that does not yet exist.' - ].join(' ')); - } - - map.addLayer(opts); -}; - -// convenience method to project a [lon, lat] array to pixel coords -proto.project = function(v) { - return this.map.project(new mapboxgl.LngLat(v[0], v[1])); -}; - -// get map's current view values in plotly.js notation -proto.getView = function() { - var map = this.map; - var mapCenter = map.getCenter(); - var center = { lon: mapCenter.lng, lat: mapCenter.lat }; - - return { - center: center, - zoom: map.getZoom(), - bearing: map.getBearing(), - pitch: map.getPitch() - }; -}; - -proto.getViewEdits = function(cont) { - var id = this.id; - var keys = ['center', 'zoom', 'bearing', 'pitch']; - var obj = {}; - - for(var i = 0; i < keys.length; i++) { - var k = keys[i]; - obj[id + '.' + k] = cont[k]; - } - - return obj; -}; - -function getStyleObj(val) { - var styleObj = {}; - - if(Lib.isPlainObject(val)) { - styleObj.id = val.id; - styleObj.style = val; - } else if(typeof val === 'string') { - styleObj.id = val; - - if(constants.styleValuesMapbox.indexOf(val) !== -1) { - styleObj.style = convertStyleVal(val); - } else if(constants.stylesNonMapbox[val]) { - styleObj.style = constants.stylesNonMapbox[val]; - } else { - styleObj.style = val; - } - } else { - styleObj.id = constants.styleValueDflt; - styleObj.style = convertStyleVal(constants.styleValueDflt); - } - - styleObj.transition = {duration: 0, delay: 0}; - - return styleObj; -} - -// if style is part of the 'official' mapbox values, add URL prefix and suffix -function convertStyleVal(val) { - return constants.styleUrlPrefix + val + '-' + constants.styleUrlSuffix; -} - -function convertCenter(center) { - return [center.lon, center.lat]; -} - -module.exports = Mapbox; - -},{"../../components/dragelement":611,"../../components/fx":632,"../../lib":719,"../../registry":847,"../cartesian/axes":767,"../cartesian/select":784,"./constants":820,"./layers":823,"d3":163,"mapbox-gl":426}],827:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** - * Creates a set of padding attributes. - * - * @param {object} opts - * @param {string} editType: - * the editType for all pieces of this padding definition - * - * @return {object} attributes object containing {t, r, b, l} as specified - */ -module.exports = function(opts) { - var editType = opts.editType; - return { - t: { - valType: 'number', - dflt: 0, - - editType: editType, - - }, - r: { - valType: 'number', - dflt: 0, - - editType: editType, - - }, - b: { - valType: 'number', - dflt: 0, - - editType: editType, - - }, - l: { - valType: 'number', - dflt: 0, - - editType: editType, - - }, - editType: editType - }; -}; - -},{}],828:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Registry = _dereq_('../registry'); -var PlotSchema = _dereq_('../plot_api/plot_schema'); -var Template = _dereq_('../plot_api/plot_template'); -var Lib = _dereq_('../lib'); -var Color = _dereq_('../components/color'); -var BADNUM = _dereq_('../constants/numerical').BADNUM; - -var axisIDs = _dereq_('./cartesian/axis_ids'); - -var animationAttrs = _dereq_('./animation_attributes'); -var frameAttrs = _dereq_('./frame_attributes'); - -var relinkPrivateKeys = Lib.relinkPrivateKeys; -var _ = Lib._; - -var plots = module.exports = {}; - -// Expose registry methods on Plots for backward-compatibility -Lib.extendFlat(plots, Registry); - -plots.attributes = _dereq_('./attributes'); -plots.attributes.type.values = plots.allTypes; -plots.fontAttrs = _dereq_('./font_attributes'); -plots.layoutAttributes = _dereq_('./layout_attributes'); - -// TODO make this a plot attribute? -plots.fontWeight = 'normal'; - -var transformsRegistry = plots.transformsRegistry; - -var commandModule = _dereq_('./command'); -plots.executeAPICommand = commandModule.executeAPICommand; -plots.computeAPICommandBindings = commandModule.computeAPICommandBindings; -plots.manageCommandObserver = commandModule.manageCommandObserver; -plots.hasSimpleAPICommandBindings = commandModule.hasSimpleAPICommandBindings; - -// in some cases the browser doesn't seem to know how big -// the text is at first, so it needs to draw it, -// then wait a little, then draw it again -plots.redrawText = function(gd) { - gd = Lib.getGraphDiv(gd); - - var fullLayout = gd._fullLayout || {}; - var hasPolar = fullLayout._has && fullLayout._has('polar'); - var hasLegacyPolar = !hasPolar && gd.data && gd.data[0] && gd.data[0].r; - - // do not work if polar is present - if(hasLegacyPolar) return; - - return new Promise(function(resolve) { - setTimeout(function() { - Registry.getComponentMethod('annotations', 'draw')(gd); - Registry.getComponentMethod('legend', 'draw')(gd); - Registry.getComponentMethod('colorbar', 'draw')(gd); - resolve(plots.previousPromises(gd)); - }, 300); - }); -}; - -// resize plot about the container size -plots.resize = function(gd) { - gd = Lib.getGraphDiv(gd); - - return new Promise(function(resolve, reject) { - if(!gd || Lib.isHidden(gd)) { - reject(new Error('Resize must be passed a displayed plot div element.')); - } - - if(gd._redrawTimer) clearTimeout(gd._redrawTimer); - - gd._redrawTimer = setTimeout(function() { - // return if there is nothing to resize or is hidden - if(!gd.layout || (gd.layout.width && gd.layout.height) || Lib.isHidden(gd)) { - resolve(gd); - return; - } - - delete gd.layout.width; - delete gd.layout.height; - - // autosizing doesn't count as a change that needs saving - var oldchanged = gd.changed; - - // nor should it be included in the undo queue - gd.autoplay = true; - - Registry.call('relayout', gd, {autosize: true}).then(function() { - gd.changed = oldchanged; - resolve(gd); - }); - }, 100); - }); -}; - - -// for use in Lib.syncOrAsync, check if there are any -// pending promises in this plot and wait for them -plots.previousPromises = function(gd) { - if((gd._promises || []).length) { - return Promise.all(gd._promises) - .then(function() { gd._promises = []; }); - } -}; - -/** - * Adds the 'Edit chart' link. - * Note that now Plotly.plot() calls this so it can regenerate whenever it replots - * - * Add source links to your graph inside the 'showSources' config argument. - */ -plots.addLinks = function(gd) { - // Do not do anything if showLink and showSources are not set to true in config - if(!gd._context.showLink && !gd._context.showSources) return; - - var fullLayout = gd._fullLayout; - - var linkContainer = Lib.ensureSingle(fullLayout._paper, 'text', 'js-plot-link-container', function(s) { - s.style({ - 'font-family': '"Open Sans", Arial, sans-serif', - 'font-size': '12px', - 'fill': Color.defaultLine, - 'pointer-events': 'all' - }) - .each(function() { - var links = d3.select(this); - links.append('tspan').classed('js-link-to-tool', true); - links.append('tspan').classed('js-link-spacer', true); - links.append('tspan').classed('js-sourcelinks', true); - }); - }); - - // The text node inside svg - var text = linkContainer.node(); - var attrs = {y: fullLayout._paper.attr('height') - 9}; - - // If text's width is bigger than the layout - // Check that text is a child node or document.body - // because otherwise IE/Edge might throw an exception - // when calling getComputedTextLength(). - // Apparently offsetParent is null for invisibles. - if(document.body.contains(text) && text.getComputedTextLength() >= (fullLayout.width - 20)) { - // Align the text at the left - attrs['text-anchor'] = 'start'; - attrs.x = 5; - } else { - // Align the text at the right - attrs['text-anchor'] = 'end'; - attrs.x = fullLayout._paper.attr('width') - 7; - } - - linkContainer.attr(attrs); - - var toolspan = linkContainer.select('.js-link-to-tool'); - var spacespan = linkContainer.select('.js-link-spacer'); - var sourcespan = linkContainer.select('.js-sourcelinks'); - - if(gd._context.showSources) gd._context.showSources(gd); - - // 'view in plotly' link for embedded plots - if(gd._context.showLink) positionPlayWithData(gd, toolspan); - - // separator if we have both sources and tool link - spacespan.text((toolspan.text() && sourcespan.text()) ? ' - ' : ''); -}; - -// note that now this function is only adding the brand in -// iframes and 3rd-party apps -function positionPlayWithData(gd, container) { - container.text(''); - var link = container.append('a') - .attr({ - 'xlink:xlink:href': '#', - 'class': 'link--impt link--embedview', - 'font-weight': 'bold' - }) - .text(gd._context.linkText + ' ' + String.fromCharCode(187)); - - if(gd._context.sendData) { - link.on('click', function() { - plots.sendDataToCloud(gd); - }); - } else { - var path = window.location.pathname.split('/'); - var query = window.location.search; - link.attr({ - 'xlink:xlink:show': 'new', - 'xlink:xlink:href': '/' + path[2].split('.')[0] + '/' + path[1] + query - }); - } -} - -plots.sendDataToCloud = function(gd) { - gd.emit('plotly_beforeexport'); - - var baseUrl = (window.PLOTLYENV || {}).BASE_URL || gd._context.plotlyServerURL; - - var hiddenformDiv = d3.select(gd) - .append('div') - .attr('id', 'hiddenform') - .style('display', 'none'); - - var hiddenform = hiddenformDiv - .append('form') - .attr({ - action: baseUrl + '/external', - method: 'post', - target: '_blank' - }); - - var hiddenformInput = hiddenform - .append('input') - .attr({ - type: 'text', - name: 'data' - }); - - hiddenformInput.node().value = plots.graphJson(gd, false, 'keepdata'); - hiddenform.node().submit(); - hiddenformDiv.remove(); - - gd.emit('plotly_afterexport'); - return false; -}; - -var d3FormatKeys = [ - 'days', 'shortDays', 'months', 'shortMonths', 'periods', - 'dateTime', 'date', 'time', - 'decimal', 'thousands', 'grouping', 'currency' -]; - -var extraFormatKeys = [ - 'year', 'month', 'dayMonth', 'dayMonthYear' -]; - -/* - * Fill in default values - * @param {DOM element} gd - * @param {object} opts - * @param {boolean} opts.skipUpdateCalc: normally if the existing gd.calcdata looks - * compatible with the new gd._fullData we finish by linking the new _fullData traces - * to the old gd.calcdata, so it's correctly set if we're not going to recalc. But also, - * if there are calcTransforms on the trace, we first remap data arrays from the old full - * trace into the new one. Use skipUpdateCalc to defer this (needed by Plotly.react) - * - * gd.data, gd.layout: - * are precisely what the user specified (except as modified by cleanData/cleanLayout), - * these fields shouldn't be modified (except for filling in some auto values) - * nor used directly after the supply defaults step. - * - * gd._fullData, gd._fullLayout: - * are complete descriptions of how to draw the plot, - * use these fields in all required computations. - * - * gd._fullLayout._modules - * is a list of all the trace modules required to draw the plot. - * - * gd._fullLayout._visibleModules - * subset of _modules, a list of modules corresponding to visible:true traces. - * - * gd._fullLayout._basePlotModules - * is a list of all the plot modules required to draw the plot. - * - * gd._fullLayout._transformModules - * is a list of all the transform modules invoked. - * - */ -plots.supplyDefaults = function(gd, opts) { - var skipUpdateCalc = opts && opts.skipUpdateCalc; - var oldFullLayout = gd._fullLayout || {}; - - if(oldFullLayout._skipDefaults) { - delete oldFullLayout._skipDefaults; - return; - } - - var newFullLayout = gd._fullLayout = {}; - var newLayout = gd.layout || {}; - - var oldFullData = gd._fullData || []; - var newFullData = gd._fullData = []; - var newData = gd.data || []; - - var oldCalcdata = gd.calcdata || []; - - var context = gd._context || {}; - - var i; - - // Create all the storage space for frames, but only if doesn't already exist - if(!gd._transitionData) plots.createTransitionData(gd); - - // So we only need to do this once (and since we have gd here) - // get the translated placeholder titles. - // These ones get used as default values so need to be known at supplyDefaults - // others keep their blank defaults but render the placeholder as desired later - // TODO: make these work the same way, only inserting the placeholder text at draw time? - // The challenge is that this has slightly different behavior right now in editable mode: - // using the placeholder as default makes this text permanently (but lightly) visible, - // but explicit '' for these titles gives you a placeholder that's hidden until you mouse - // over it - so you're not distracted by it if you really don't want a title, but if you do - // and you're new to plotly you may not be able to find it. - // When editable=false the two behave the same, no title is drawn. - newFullLayout._dfltTitle = { - plot: _(gd, 'Click to enter Plot title'), - x: _(gd, 'Click to enter X axis title'), - y: _(gd, 'Click to enter Y axis title'), - colorbar: _(gd, 'Click to enter Colorscale title'), - annotation: _(gd, 'new text') - }; - newFullLayout._traceWord = _(gd, 'trace'); - - var formatObj = getFormatObj(gd, d3FormatKeys); - - // stash the token from context so mapbox subplots can use it as default - newFullLayout._mapboxAccessToken = context.mapboxAccessToken; - - // first fill in what we can of layout without looking at data - // because fullData needs a few things from layout - if(oldFullLayout._initialAutoSizeIsDone) { - // coerce the updated layout while preserving width and height - var oldWidth = oldFullLayout.width; - var oldHeight = oldFullLayout.height; - - plots.supplyLayoutGlobalDefaults(newLayout, newFullLayout, formatObj); - - if(!newLayout.width) newFullLayout.width = oldWidth; - if(!newLayout.height) newFullLayout.height = oldHeight; - plots.sanitizeMargins(newFullLayout); - } else { - // coerce the updated layout and autosize if needed - plots.supplyLayoutGlobalDefaults(newLayout, newFullLayout, formatObj); - - var missingWidthOrHeight = (!newLayout.width || !newLayout.height); - var autosize = newFullLayout.autosize; - var autosizable = context.autosizable; - var initialAutoSize = missingWidthOrHeight && (autosize || autosizable); - - if(initialAutoSize) plots.plotAutoSize(gd, newLayout, newFullLayout); - else if(missingWidthOrHeight) plots.sanitizeMargins(newFullLayout); - - // for backwards-compatibility with Plotly v1.x.x - if(!autosize && missingWidthOrHeight) { - newLayout.width = newFullLayout.width; - newLayout.height = newFullLayout.height; - } - } - - newFullLayout._d3locale = getFormatter(formatObj, newFullLayout.separators); - newFullLayout._extraFormat = getFormatObj(gd, extraFormatKeys); - - newFullLayout._initialAutoSizeIsDone = true; - - // keep track of how many traces are inputted - newFullLayout._dataLength = newData.length; - - // clear the lists of trace and baseplot modules, and subplots - newFullLayout._modules = []; - newFullLayout._visibleModules = []; - newFullLayout._basePlotModules = []; - var subplots = newFullLayout._subplots = emptySubplotLists(); - - // initialize axis and subplot hash objects for splom-generated grids - var splomAxes = newFullLayout._splomAxes = {x: {}, y: {}}; - var splomSubplots = newFullLayout._splomSubplots = {}; - // initialize splom grid defaults - newFullLayout._splomGridDflt = {}; - - // for stacked area traces to share config across traces - newFullLayout._scatterStackOpts = {}; - // for the first scatter trace on each subplot (so it knows tonext->tozero) - newFullLayout._firstScatter = {}; - // for grouped bar/box/violin trace to share config across traces - newFullLayout._alignmentOpts = {}; - // track color axes referenced in the data - newFullLayout._colorAxes = {}; - - // for traces to request a default rangeslider on their x axes - // eg set `_requestRangeslider.x2 = true` for xaxis2 - newFullLayout._requestRangeslider = {}; - - // pull uids from old data to use as new defaults - newFullLayout._traceUids = getTraceUids(oldFullData, newData); - - // then do the data - newFullLayout._globalTransforms = (gd._context || {}).globalTransforms; - plots.supplyDataDefaults(newData, newFullData, newLayout, newFullLayout); - - // redo grid size defaults with info about splom x/y axes, - // and fill in generated cartesian axes and subplots - var splomXa = Object.keys(splomAxes.x); - var splomYa = Object.keys(splomAxes.y); - if(splomXa.length > 1 && splomYa.length > 1) { - Registry.getComponentMethod('grid', 'sizeDefaults')(newLayout, newFullLayout); - - for(i = 0; i < splomXa.length; i++) { - Lib.pushUnique(subplots.xaxis, splomXa[i]); - } - for(i = 0; i < splomYa.length; i++) { - Lib.pushUnique(subplots.yaxis, splomYa[i]); - } - for(var k in splomSubplots) { - Lib.pushUnique(subplots.cartesian, k); - } - } - - // attach helper method to check whether a plot type is present on graph - newFullLayout._has = plots._hasPlotType.bind(newFullLayout); - - if(oldFullData.length === newFullData.length) { - for(i = 0; i < newFullData.length; i++) { - relinkPrivateKeys(newFullData[i], oldFullData[i]); - } - } - - // finally, fill in the pieces of layout that may need to look at data - plots.supplyLayoutModuleDefaults(newLayout, newFullLayout, newFullData, gd._transitionData); - - // Special cases that introduce interactions between traces. - // This is after relinkPrivateKeys so we can use those in crossTraceDefaults - // and after layout module defaults, so we can use eg barmode - var _modules = newFullLayout._visibleModules; - var crossTraceDefaultsFuncs = []; - for(i = 0; i < _modules.length; i++) { - var funci = _modules[i].crossTraceDefaults; - // some trace types share crossTraceDefaults (ie histogram2d, histogram2dcontour) - if(funci) Lib.pushUnique(crossTraceDefaultsFuncs, funci); - } - for(i = 0; i < crossTraceDefaultsFuncs.length; i++) { - crossTraceDefaultsFuncs[i](newFullData, newFullLayout); - } - - // turn on flag to optimize large splom-only graphs - // mostly by omitting SVG layers during Cartesian.drawFramework - newFullLayout._hasOnlyLargeSploms = ( - newFullLayout._basePlotModules.length === 1 && - newFullLayout._basePlotModules[0].name === 'splom' && - splomXa.length > 15 && - splomYa.length > 15 && - newFullLayout.shapes.length === 0 && - newFullLayout.images.length === 0 - ); - - // TODO remove in v2.0.0 - // add has-plot-type refs to fullLayout for backward compatibility - newFullLayout._hasCartesian = newFullLayout._has('cartesian'); - newFullLayout._hasGeo = newFullLayout._has('geo'); - newFullLayout._hasGL3D = newFullLayout._has('gl3d'); - newFullLayout._hasGL2D = newFullLayout._has('gl2d'); - newFullLayout._hasTernary = newFullLayout._has('ternary'); - newFullLayout._hasPie = newFullLayout._has('pie'); - - // relink / initialize subplot axis objects - plots.linkSubplots(newFullData, newFullLayout, oldFullData, oldFullLayout); - - // clean subplots and other artifacts from previous plot calls - plots.cleanPlot(newFullData, newFullLayout, oldFullData, oldFullLayout); - - // clear selection outline until we implement persistent selection, - // don't clear them though when drag handlers (e.g. listening to - // `plotly_selecting`) update the graph. - // we should try to come up with a better solution when implementing - // https://github.com/plotly/plotly.js/issues/1851 - if(oldFullLayout._zoomlayer && !gd._dragging) { - oldFullLayout._zoomlayer.selectAll('.select-outline').remove(); - } - - - // fill in meta helpers - fillMetaTextHelpers(newFullData, newFullLayout); - - // relink functions and _ attributes to promote consistency between plots - relinkPrivateKeys(newFullLayout, oldFullLayout); - - // colorscale crossTraceDefaults needs newFullLayout with relinked keys - Registry.getComponentMethod('colorscale', 'crossTraceDefaults')(newFullData, newFullLayout); - - // For persisting GUI-driven changes in layout - // _preGUI and _tracePreGUI were already copied over in relinkPrivateKeys - if(!newFullLayout._preGUI) newFullLayout._preGUI = {}; - // track trace GUI changes by uid rather than by trace index - if(!newFullLayout._tracePreGUI) newFullLayout._tracePreGUI = {}; - var tracePreGUI = newFullLayout._tracePreGUI; - var uids = {}; - var uid; - for(uid in tracePreGUI) uids[uid] = 'old'; - for(i = 0; i < newFullData.length; i++) { - uid = newFullData[i]._fullInput.uid; - if(!uids[uid]) tracePreGUI[uid] = {}; - uids[uid] = 'new'; - } - for(uid in uids) { - if(uids[uid] === 'old') delete tracePreGUI[uid]; - } - - // set up containers for margin calculations - initMargins(newFullLayout); - - // collect and do some initial calculations for rangesliders - Registry.getComponentMethod('rangeslider', 'makeData')(newFullLayout); - - // update object references in calcdata - if(!skipUpdateCalc && oldCalcdata.length === newFullData.length) { - plots.supplyDefaultsUpdateCalc(oldCalcdata, newFullData); - } -}; - -plots.supplyDefaultsUpdateCalc = function(oldCalcdata, newFullData) { - for(var i = 0; i < newFullData.length; i++) { - var newTrace = newFullData[i]; - var cd0 = (oldCalcdata[i] || [])[0]; - if(cd0 && cd0.trace) { - var oldTrace = cd0.trace; - if(oldTrace._hasCalcTransform) { - var arrayAttrs = oldTrace._arrayAttrs; - var j, astr, oldArrayVal; - - for(j = 0; j < arrayAttrs.length; j++) { - astr = arrayAttrs[j]; - oldArrayVal = Lib.nestedProperty(oldTrace, astr).get().slice(); - Lib.nestedProperty(newTrace, astr).set(oldArrayVal); - } - } - cd0.trace = newTrace; - } - } -}; - -/** - * Create a list of uid strings satisfying (in this order of importance): - * 1. all unique, all strings - * 2. matches input uids if provided - * 3. matches previous data uids - */ -function getTraceUids(oldFullData, newData) { - var len = newData.length; - var oldFullInput = []; - var i, prevFullInput; - for(i = 0; i < oldFullData.length; i++) { - var thisFullInput = oldFullData[i]._fullInput; - if(thisFullInput !== prevFullInput) oldFullInput.push(thisFullInput); - prevFullInput = thisFullInput; - } - var oldLen = oldFullInput.length; - var out = new Array(len); - var seenUids = {}; - - function setUid(uid, i) { - out[i] = uid; - seenUids[uid] = 1; - } - - function tryUid(uid, i) { - if(uid && typeof uid === 'string' && !seenUids[uid]) { - setUid(uid, i); - return true; - } - } - - for(i = 0; i < len; i++) { - var newUid = newData[i].uid; - if(typeof newUid === 'number') newUid = String(newUid); - - if(tryUid(newUid, i)) continue; - if(i < oldLen && tryUid(oldFullInput[i].uid, i)) continue; - setUid(Lib.randstr(seenUids), i); - } - - return out; -} - -/** - * Make a container for collecting subplots we need to display. - * - * Finds all subplot types we need to enumerate once and caches it, - * but makes a new output object each time. - * Single-trace subplots (which have no `id`) such as pie, table, etc - * do not need to be collected because we just draw all visible traces. - */ -function emptySubplotLists() { - var collectableSubplotTypes = Registry.collectableSubplotTypes; - var out = {}; - var i, j; - - if(!collectableSubplotTypes) { - collectableSubplotTypes = []; - - var subplotsRegistry = Registry.subplotsRegistry; - - for(var subplotType in subplotsRegistry) { - var subplotModule = subplotsRegistry[subplotType]; - var subplotAttr = subplotModule.attr; - - if(subplotAttr) { - collectableSubplotTypes.push(subplotType); - - // special case, currently just for cartesian: - // we need to enumerate axes, not just subplots - if(Array.isArray(subplotAttr)) { - for(j = 0; j < subplotAttr.length; j++) { - Lib.pushUnique(collectableSubplotTypes, subplotAttr[j]); - } - } - } - } - } - - for(i = 0; i < collectableSubplotTypes.length; i++) { - out[collectableSubplotTypes[i]] = []; - } - return out; -} - -/** - * getFormatObj: use _context to get the format object from locale. - * Used to get d3.locale argument object and extraFormat argument object - * - * Regarding d3.locale argument : - * decimal and thousands can be overridden later by layout.separators - * grouping and currency are not presently used by our automatic number - * formatting system but can be used by custom formats. - * - * @returns {object} d3.locale format object - */ -function getFormatObj(gd, formatKeys) { - var locale = gd._context.locale; - if(!locale) locale === 'en-US'; - - var formatDone = false; - var formatObj = {}; - - function includeFormat(newFormat) { - var formatFinished = true; - for(var i = 0; i < formatKeys.length; i++) { - var formatKey = formatKeys[i]; - if(!formatObj[formatKey]) { - if(newFormat[formatKey]) { - formatObj[formatKey] = newFormat[formatKey]; - } else formatFinished = false; - } - } - if(formatFinished) formatDone = true; - } - - // same as localize, look for format parts in each format spec in the chain - for(var i = 0; i < 2; i++) { - var locales = gd._context.locales; - for(var j = 0; j < 2; j++) { - var formatj = (locales[locale] || {}).format; - if(formatj) { - includeFormat(formatj); - if(formatDone) break; - } - locales = Registry.localeRegistry; - } - - var baseLocale = locale.split('-')[0]; - if(formatDone || baseLocale === locale) break; - locale = baseLocale; - } - - // lastly pick out defaults from english (non-US, as DMY is so much more common) - if(!formatDone) includeFormat(Registry.localeRegistry.en.format); - - return formatObj; -} - -/** - * getFormatter: combine the final separators with the locale formatting object - * we pulled earlier to generate number and time formatters - * TODO: remove separators in v2, only use locale, so we don't need this step? - * - * @param {object} formatObj: d3.locale format object - * @param {string} separators: length-2 string to override decimal and thousands - * separators in number formatting - * - * @returns {object} {numberFormat, timeFormat} d3 formatter factory functions - * for numbers and time - */ -function getFormatter(formatObj, separators) { - formatObj.decimal = separators.charAt(0); - formatObj.thousands = separators.charAt(1); - - return d3.locale(formatObj); -} - -function fillMetaTextHelpers(newFullData, newFullLayout) { - var _meta; - var meta4data = []; - - if(newFullLayout.meta) { - _meta = newFullLayout._meta = { - meta: newFullLayout.meta, - layout: {meta: newFullLayout.meta} - }; - } - - for(var i = 0; i < newFullData.length; i++) { - var trace = newFullData[i]; - - if(trace.meta) { - meta4data[trace.index] = trace._meta = {meta: trace.meta}; - } else if(newFullLayout.meta) { - trace._meta = {meta: newFullLayout.meta}; - } - if(newFullLayout.meta) { - trace._meta.layout = {meta: newFullLayout.meta}; - } - } - - if(meta4data.length) { - if(!_meta) { - _meta = newFullLayout._meta = {}; - } - _meta.data = meta4data; - } -} - -// Create storage for all of the data related to frames and transitions: -plots.createTransitionData = function(gd) { - // Set up the default keyframe if it doesn't exist: - if(!gd._transitionData) { - gd._transitionData = {}; - } - - if(!gd._transitionData._frames) { - gd._transitionData._frames = []; - } - - if(!gd._transitionData._frameHash) { - gd._transitionData._frameHash = {}; - } - - if(!gd._transitionData._counter) { - gd._transitionData._counter = 0; - } - - if(!gd._transitionData._interruptCallbacks) { - gd._transitionData._interruptCallbacks = []; - } -}; - -// helper function to be bound to fullLayout to check -// whether a certain plot type is present on plot -// or trace has a category -plots._hasPlotType = function(category) { - var i; - - // check base plot modules - var basePlotModules = this._basePlotModules || []; - for(i = 0; i < basePlotModules.length; i++) { - if(basePlotModules[i].name === category) return true; - } - - // check trace modules (including non-visible:true) - var modules = this._modules || []; - for(i = 0; i < modules.length; i++) { - var name = modules[i].name; - if(name === category) return true; - // N.B. this is modules[i] along with 'categories' as a hash object - var _module = Registry.modules[name]; - if(_module && _module.categories[category]) return true; - } - - return false; -}; - -plots.cleanPlot = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var i, j; - - var basePlotModules = oldFullLayout._basePlotModules || []; - for(i = 0; i < basePlotModules.length; i++) { - var _module = basePlotModules[i]; - - if(_module.clean) { - _module.clean(newFullData, newFullLayout, oldFullData, oldFullLayout); - } - } - - var hadGl = oldFullLayout._has && oldFullLayout._has('gl'); - var hasGl = newFullLayout._has && newFullLayout._has('gl'); - - if(hadGl && !hasGl) { - if(oldFullLayout._glcontainer !== undefined) { - oldFullLayout._glcontainer.selectAll('.gl-canvas').remove(); - oldFullLayout._glcontainer.selectAll('.no-webgl').remove(); - oldFullLayout._glcanvas = null; - } - } - - var hasInfoLayer = !!oldFullLayout._infolayer; - - oldLoop: - for(i = 0; i < oldFullData.length; i++) { - var oldTrace = oldFullData[i]; - var oldUid = oldTrace.uid; - - for(j = 0; j < newFullData.length; j++) { - var newTrace = newFullData[j]; - - if(oldUid === newTrace.uid) continue oldLoop; - } - - // clean old colorbars - if(hasInfoLayer) { - oldFullLayout._infolayer.select('.cb' + oldUid).remove(); - } - } -}; - -plots.linkSubplots = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var i, j; - - var oldSubplots = oldFullLayout._plots || {}; - var newSubplots = newFullLayout._plots = {}; - var newSubplotList = newFullLayout._subplots; - - var mockGd = { - _fullData: newFullData, - _fullLayout: newFullLayout - }; - - var ids = newSubplotList.cartesian.concat(newSubplotList.gl2d || []); - - for(i = 0; i < ids.length; i++) { - var id = ids[i]; - var oldSubplot = oldSubplots[id]; - var xaxis = axisIDs.getFromId(mockGd, id, 'x'); - var yaxis = axisIDs.getFromId(mockGd, id, 'y'); - var plotinfo; - - // link or create subplot object - if(oldSubplot) { - plotinfo = newSubplots[id] = oldSubplot; - } else { - plotinfo = newSubplots[id] = {}; - plotinfo.id = id; - } - - // add these axis ids to each others' subplot lists - xaxis._counterAxes.push(yaxis._id); - yaxis._counterAxes.push(xaxis._id); - xaxis._subplotsWith.push(id); - yaxis._subplotsWith.push(id); - - // update x and y axis layout object refs - plotinfo.xaxis = xaxis; - plotinfo.yaxis = yaxis; - - // By default, we clip at the subplot level, - // but if one trace on a given subplot has *cliponaxis* set to false, - // we need to clip at the trace module layer level; - // find this out here, once of for all. - plotinfo._hasClipOnAxisFalse = false; - - for(j = 0; j < newFullData.length; j++) { - var trace = newFullData[j]; - - if( - trace.xaxis === plotinfo.xaxis._id && - trace.yaxis === plotinfo.yaxis._id && - trace.cliponaxis === false - ) { - plotinfo._hasClipOnAxisFalse = true; - break; - } - } - } - - // while we're at it, link overlaying axes to their main axes and - // anchored axes to the axes they're anchored to - var axList = axisIDs.list(mockGd, null, true); - var ax; - for(i = 0; i < axList.length; i++) { - ax = axList[i]; - var mainAx = null; - - if(ax.overlaying) { - mainAx = axisIDs.getFromId(mockGd, ax.overlaying); - - // you cannot overlay an axis that's already overlaying another - if(mainAx && mainAx.overlaying) { - ax.overlaying = false; - mainAx = null; - } - } - ax._mainAxis = mainAx || ax; - - /* - * For now force overlays to overlay completely... so they - * can drag together correctly and share backgrounds. - * Later perhaps we make separate axis domain and - * tick/line domain or something, so they can still share - * the (possibly larger) dragger and background but don't - * have to both be drawn over that whole domain - */ - if(mainAx) ax.domain = mainAx.domain.slice(); - - ax._anchorAxis = ax.anchor === 'free' ? - null : - axisIDs.getFromId(mockGd, ax.anchor); - } - - // finally, we can find the main subplot for each axis - // (on which the ticks & labels are drawn) - for(i = 0; i < axList.length; i++) { - ax = axList[i]; - ax._counterAxes.sort(axisIDs.idSort); - ax._subplotsWith.sort(Lib.subplotSort); - ax._mainSubplot = findMainSubplot(ax, newFullLayout); - } -}; - -function findMainSubplot(ax, fullLayout) { - var mockGd = {_fullLayout: fullLayout}; - - var isX = ax._id.charAt(0) === 'x'; - var anchorAx = ax._mainAxis._anchorAxis; - var mainSubplotID = ''; - var nextBestMainSubplotID = ''; - var anchorID = ''; - - // First try the main ID with the anchor - if(anchorAx) { - anchorID = anchorAx._mainAxis._id; - mainSubplotID = isX ? (ax._id + anchorID) : (anchorID + ax._id); - } - - // Then look for a subplot with the counteraxis overlaying the anchor - // If that fails just use the first subplot including this axis - if(!mainSubplotID || !fullLayout._plots[mainSubplotID]) { - mainSubplotID = ''; - - var counterIDs = ax._counterAxes; - for(var j = 0; j < counterIDs.length; j++) { - var counterPart = counterIDs[j]; - var id = isX ? (ax._id + counterPart) : (counterPart + ax._id); - if(!nextBestMainSubplotID) nextBestMainSubplotID = id; - var counterAx = axisIDs.getFromId(mockGd, counterPart); - if(anchorID && counterAx.overlaying === anchorID) { - mainSubplotID = id; - break; - } - } - } - - return mainSubplotID || nextBestMainSubplotID; -} - -// This function clears any trace attributes with valType: color and -// no set dflt filed in the plot schema. This is needed because groupby (which -// is the only transform for which this currently applies) supplies parent -// trace defaults, then expanded trace defaults. The result is that `null` -// colors are default-supplied and inherited as a color instead of a null. -// The result is that expanded trace default colors have no effect, with -// the final result that groups are indistinguishable. This function clears -// those colors so that individual groupby groups get unique colors. -plots.clearExpandedTraceDefaultColors = function(trace) { - var colorAttrs, path, i; - - // This uses weird closure state in order to satisfy the linter rule - // that we can't create functions in a loop. - function locateColorAttrs(attr, attrName, attrs, level) { - path[level] = attrName; - path.length = level + 1; - if(attr.valType === 'color' && attr.dflt === undefined) { - colorAttrs.push(path.join('.')); - } - } - - path = []; - - // Get the cached colorAttrs: - colorAttrs = trace._module._colorAttrs; - - // Or else compute and cache the colorAttrs on the module: - if(!colorAttrs) { - trace._module._colorAttrs = colorAttrs = []; - PlotSchema.crawl( - trace._module.attributes, - locateColorAttrs - ); - } - - for(i = 0; i < colorAttrs.length; i++) { - var origprop = Lib.nestedProperty(trace, '_input.' + colorAttrs[i]); - - if(!origprop.get()) { - Lib.nestedProperty(trace, colorAttrs[i]).set(null); - } - } -}; - - -plots.supplyDataDefaults = function(dataIn, dataOut, layout, fullLayout) { - var modules = fullLayout._modules; - var visibleModules = fullLayout._visibleModules; - var basePlotModules = fullLayout._basePlotModules; - var cnt = 0; - var colorCnt = 0; - - var i, fullTrace, trace; - - fullLayout._transformModules = []; - - function pushModule(fullTrace) { - dataOut.push(fullTrace); - - var _module = fullTrace._module; - if(!_module) return; - - Lib.pushUnique(modules, _module); - if(fullTrace.visible === true) Lib.pushUnique(visibleModules, _module); - Lib.pushUnique(basePlotModules, fullTrace._module.basePlotModule); - cnt++; - - // TODO: do we really want color not to increment for explicitly invisible traces? - // This logic is weird, but matches previous behavior: traces that you explicitly - // set to visible:false do not increment the color, but traces WE determine to be - // empty or invalid (and thus set to visible:false) DO increment color. - // I kind of think we should just let all traces increment color, visible or not. - // see mock: axes-autotype-empty vs. a test of restyling visible: false that - // I can't find right now... - if(fullTrace._input.visible !== false) colorCnt++; - } - - var carpetIndex = {}; - var carpetDependents = []; - var dataTemplate = (layout.template || {}).data || {}; - var templater = Template.traceTemplater(dataTemplate); - - for(i = 0; i < dataIn.length; i++) { - trace = dataIn[i]; - - // reuse uid we may have pulled out of oldFullData - // Note: templater supplies trace type - fullTrace = templater.newTrace(trace); - fullTrace.uid = fullLayout._traceUids[i]; - plots.supplyTraceDefaults(trace, fullTrace, colorCnt, fullLayout, i); - - fullTrace.index = i; - fullTrace._input = trace; - fullTrace._expandedIndex = cnt; - - if(fullTrace.transforms && fullTrace.transforms.length) { - var sdInvisible = trace.visible !== false && fullTrace.visible === false; - - var expandedTraces = applyTransforms(fullTrace, dataOut, layout, fullLayout); - - for(var j = 0; j < expandedTraces.length; j++) { - var expandedTrace = expandedTraces[j]; - - // No further templating during transforms. - var fullExpandedTrace = { - _template: fullTrace._template, - type: fullTrace.type, - // set uid using parent uid and expanded index - // to promote consistency between update calls - uid: fullTrace.uid + j - }; - - // If the first supplyDefaults created `visible: false`, - // clear it before running supplyDefaults a second time, - // because sometimes there are items we still want to coerce - // inside trace modules before determining that the trace is - // again `visible: false`, for example partial visibilities - // in `splom` traces. - if(sdInvisible && expandedTrace.visible === false) { - delete expandedTrace.visible; - } - - plots.supplyTraceDefaults(expandedTrace, fullExpandedTrace, cnt, fullLayout, i); - - // relink private (i.e. underscore) keys expanded trace to full expanded trace so - // that transform supply-default methods can set _ keys for future use. - relinkPrivateKeys(fullExpandedTrace, expandedTrace); - - // add info about parent data trace - fullExpandedTrace.index = i; - fullExpandedTrace._input = trace; - fullExpandedTrace._fullInput = fullTrace; - - // add info about the expanded data - fullExpandedTrace._expandedIndex = cnt; - fullExpandedTrace._expandedInput = expandedTrace; - - pushModule(fullExpandedTrace); - } - } else { - // add identify refs for consistency with transformed traces - fullTrace._fullInput = fullTrace; - fullTrace._expandedInput = fullTrace; - - pushModule(fullTrace); - } - - if(Registry.traceIs(fullTrace, 'carpetAxis')) { - carpetIndex[fullTrace.carpet] = fullTrace; - } - - if(Registry.traceIs(fullTrace, 'carpetDependent')) { - carpetDependents.push(i); - } - } - - for(i = 0; i < carpetDependents.length; i++) { - fullTrace = dataOut[carpetDependents[i]]; - - if(!fullTrace.visible) continue; - - var carpetAxis = carpetIndex[fullTrace.carpet]; - fullTrace._carpet = carpetAxis; - - if(!carpetAxis || !carpetAxis.visible) { - fullTrace.visible = false; - continue; - } - - fullTrace.xaxis = carpetAxis.xaxis; - fullTrace.yaxis = carpetAxis.yaxis; - } -}; - -plots.supplyAnimationDefaults = function(opts) { - opts = opts || {}; - var i; - var optsOut = {}; - - function coerce(attr, dflt) { - return Lib.coerce(opts || {}, optsOut, animationAttrs, attr, dflt); - } - - coerce('mode'); - coerce('direction'); - coerce('fromcurrent'); - - if(Array.isArray(opts.frame)) { - optsOut.frame = []; - for(i = 0; i < opts.frame.length; i++) { - optsOut.frame[i] = plots.supplyAnimationFrameDefaults(opts.frame[i] || {}); - } - } else { - optsOut.frame = plots.supplyAnimationFrameDefaults(opts.frame || {}); - } - - if(Array.isArray(opts.transition)) { - optsOut.transition = []; - for(i = 0; i < opts.transition.length; i++) { - optsOut.transition[i] = plots.supplyAnimationTransitionDefaults(opts.transition[i] || {}); - } - } else { - optsOut.transition = plots.supplyAnimationTransitionDefaults(opts.transition || {}); - } - - return optsOut; -}; - -plots.supplyAnimationFrameDefaults = function(opts) { - var optsOut = {}; - - function coerce(attr, dflt) { - return Lib.coerce(opts || {}, optsOut, animationAttrs.frame, attr, dflt); - } - - coerce('duration'); - coerce('redraw'); - - return optsOut; -}; - -plots.supplyAnimationTransitionDefaults = function(opts) { - var optsOut = {}; - - function coerce(attr, dflt) { - return Lib.coerce(opts || {}, optsOut, animationAttrs.transition, attr, dflt); - } - - coerce('duration'); - coerce('easing'); - - return optsOut; -}; - -plots.supplyFrameDefaults = function(frameIn) { - var frameOut = {}; - - function coerce(attr, dflt) { - return Lib.coerce(frameIn, frameOut, frameAttrs, attr, dflt); - } - - coerce('group'); - coerce('name'); - coerce('traces'); - coerce('baseframe'); - coerce('data'); - coerce('layout'); - - return frameOut; -}; - -plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, traceInIndex) { - var colorway = layout.colorway || Color.defaults; - var defaultColor = colorway[colorIndex % colorway.length]; - - var i; - - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, plots.attributes, attr, dflt); - } - - var visible = coerce('visible'); - - coerce('type'); - coerce('name', layout._traceWord + ' ' + traceInIndex); - - coerce('uirevision', layout.uirevision); - - // we want even invisible traces to make their would-be subplots visible - // so coerce the subplot id(s) now no matter what - var _module = plots.getModule(traceOut); - - traceOut._module = _module; - if(_module) { - var basePlotModule = _module.basePlotModule; - var subplotAttr = basePlotModule.attr; - var subplotAttrs = basePlotModule.attributes; - if(subplotAttr && subplotAttrs) { - var subplots = layout._subplots; - var subplotId = ''; - - // TODO - currently if we draw an empty gl2d subplot, it draws - // nothing then gets stuck and you can't get it back without newPlot - // sort this out in the regl refactor? but for now just drop empty gl2d subplots - if(basePlotModule.name !== 'gl2d' || visible) { - if(Array.isArray(subplotAttr)) { - for(i = 0; i < subplotAttr.length; i++) { - var attri = subplotAttr[i]; - var vali = Lib.coerce(traceIn, traceOut, subplotAttrs, attri); - - if(subplots[attri]) Lib.pushUnique(subplots[attri], vali); - subplotId += vali; - } - } else { - subplotId = Lib.coerce(traceIn, traceOut, subplotAttrs, subplotAttr); - } - - if(subplots[basePlotModule.name]) { - Lib.pushUnique(subplots[basePlotModule.name], subplotId); - } - } - } - } - - if(visible) { - coerce('customdata'); - coerce('ids'); - coerce('meta'); - - if(Registry.traceIs(traceOut, 'showLegend')) { - traceOut._dfltShowLegend = true; - coerce('showlegend'); - coerce('legendgroup'); - } else { - traceOut._dfltShowLegend = false; - } - - if(_module) { - _module.supplyDefaults(traceIn, traceOut, defaultColor, layout); - } - - if(!Registry.traceIs(traceOut, 'noOpacity')) { - coerce('opacity'); - } - - if(Registry.traceIs(traceOut, 'notLegendIsolatable')) { - // This clears out the legendonly state for traces like carpet that - // cannot be isolated in the legend - traceOut.visible = !!traceOut.visible; - } - - if(!Registry.traceIs(traceOut, 'noHover')) { - if(!traceOut.hovertemplate) Lib.coerceHoverinfo(traceIn, traceOut, layout); - - // parcats support hover, but not hoverlabel stylings (yet) - if(traceOut.type !== 'parcats') { - Registry.getComponentMethod('fx', 'supplyDefaults')(traceIn, traceOut, defaultColor, layout); - } - } - - if(_module && _module.selectPoints) { - coerce('selectedpoints'); - } - - plots.supplyTransformDefaults(traceIn, traceOut, layout); - } - - return traceOut; -}; - -/** - * hasMakesDataTransform: does this trace have a transform that makes its own - * data, either by grabbing it from somewhere else or by creating it from input - * parameters? If so, we should still keep going with supplyDefaults - * even if the trace is invisible, which may just be because it has no data yet. - */ -function hasMakesDataTransform(trace) { - var transforms = trace.transforms; - if(Array.isArray(transforms) && transforms.length) { - for(var i = 0; i < transforms.length; i++) { - var ti = transforms[i]; - var _module = ti._module || transformsRegistry[ti.type]; - if(_module && _module.makesData) return true; - } - } - return false; -} - -plots.hasMakesDataTransform = hasMakesDataTransform; - -plots.supplyTransformDefaults = function(traceIn, traceOut, layout) { - // For now we only allow transforms on 1D traces, ie those that specify a _length. - // If we were to implement 2D transforms, we'd need to have each transform - // describe its own applicability and disable itself when it doesn't apply. - // Also allow transforms that make their own data, but not in globalTransforms - if(!(traceOut._length || hasMakesDataTransform(traceIn))) return; - - var globalTransforms = layout._globalTransforms || []; - var transformModules = layout._transformModules || []; - - if(!Array.isArray(traceIn.transforms) && globalTransforms.length === 0) return; - - var containerIn = traceIn.transforms || []; - var transformList = globalTransforms.concat(containerIn); - var containerOut = traceOut.transforms = []; - - for(var i = 0; i < transformList.length; i++) { - var transformIn = transformList[i]; - var type = transformIn.type; - var _module = transformsRegistry[type]; - var transformOut; - - /* - * Supply defaults may run twice. First pass runs all supply defaults steps - * and adds the _module to any output transforms. - * If transforms exist another pass is run so that any generated traces also - * go through supply defaults. This has the effect of rerunning - * supplyTransformDefaults. If the transform does not have a `transform` - * function it could not have generated any new traces and the second stage - * is unnecessary. We detect this case with the following variables. - */ - var isFirstStage = !(transformIn._module && transformIn._module === _module); - var doLaterStages = _module && typeof _module.transform === 'function'; - - if(!_module) Lib.warn('Unrecognized transform type ' + type + '.'); - - if(_module && _module.supplyDefaults && (isFirstStage || doLaterStages)) { - transformOut = _module.supplyDefaults(transformIn, traceOut, layout, traceIn); - transformOut.type = type; - transformOut._module = _module; - - Lib.pushUnique(transformModules, _module); - } else { - transformOut = Lib.extendFlat({}, transformIn); - } - - containerOut.push(transformOut); - } -}; - -function applyTransforms(fullTrace, fullData, layout, fullLayout) { - var container = fullTrace.transforms; - var dataOut = [fullTrace]; - - for(var i = 0; i < container.length; i++) { - var transform = container[i]; - var _module = transformsRegistry[transform.type]; - - if(_module && _module.transform) { - dataOut = _module.transform(dataOut, { - transform: transform, - fullTrace: fullTrace, - fullData: fullData, - layout: layout, - fullLayout: fullLayout, - transformIndex: i - }); - } - } - - return dataOut; -} - -plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, plots.layoutAttributes, attr, dflt); - } - - var template = layoutIn.template; - if(Lib.isPlainObject(template)) { - layoutOut.template = template; - layoutOut._template = template.layout; - layoutOut._dataTemplate = template.data; - } - - var globalFont = Lib.coerceFont(coerce, 'font'); - - coerce('title.text', layoutOut._dfltTitle.plot); - - Lib.coerceFont(coerce, 'title.font', { - family: globalFont.family, - size: Math.round(globalFont.size * 1.4), - color: globalFont.color - }); - - coerce('title.xref'); - coerce('title.yref'); - coerce('title.x'); - coerce('title.y'); - coerce('title.xanchor'); - coerce('title.yanchor'); - coerce('title.pad.t'); - coerce('title.pad.r'); - coerce('title.pad.b'); - coerce('title.pad.l'); - - // Make sure that autosize is defaulted to *true* - // on layouts with no set width and height for backward compatibly, - // in particular https://plot.ly/javascript/responsive-fluid-layout/ - // - // Before https://github.com/plotly/plotly.js/pull/635 , - // layouts with no set width and height were set temporary set to 'initial' - // to pass through the autosize routine - // - // This behavior is subject to change in v2. - coerce('autosize', !(layoutIn.width && layoutIn.height)); - - coerce('width'); - coerce('height'); - coerce('margin.l'); - coerce('margin.r'); - coerce('margin.t'); - coerce('margin.b'); - coerce('margin.pad'); - coerce('margin.autoexpand'); - - if(layoutIn.width && layoutIn.height) plots.sanitizeMargins(layoutOut); - - Registry.getComponentMethod('grid', 'sizeDefaults')(layoutIn, layoutOut); - - coerce('paper_bgcolor'); - - coerce('separators', formatObj.decimal + formatObj.thousands); - coerce('hidesources'); - - coerce('colorway'); - - coerce('datarevision'); - var uirevision = coerce('uirevision'); - coerce('editrevision', uirevision); - coerce('selectionrevision', uirevision); - - coerce('modebar.orientation'); - coerce('modebar.bgcolor', Color.addOpacity(layoutOut.paper_bgcolor, 0.5)); - var modebarDefaultColor = Color.contrast(Color.rgb(layoutOut.modebar.bgcolor)); - coerce('modebar.color', Color.addOpacity(modebarDefaultColor, 0.3)); - coerce('modebar.activecolor', Color.addOpacity(modebarDefaultColor, 0.7)); - coerce('modebar.uirevision', uirevision); - - coerce('meta'); - - // do not include defaults in fullLayout when users do not set transition - if(Lib.isPlainObject(layoutIn.transition)) { - coerce('transition.duration'); - coerce('transition.easing'); - coerce('transition.ordering'); - } - - Registry.getComponentMethod( - 'calendars', - 'handleDefaults' - )(layoutIn, layoutOut, 'calendar'); - - Registry.getComponentMethod( - 'fx', - 'supplyLayoutGlobalDefaults' - )(layoutIn, layoutOut, coerce); -}; - -plots.plotAutoSize = function plotAutoSize(gd, layout, fullLayout) { - var context = gd._context || {}; - var frameMargins = context.frameMargins; - var newWidth; - var newHeight; - - var isPlotDiv = Lib.isPlotDiv(gd); - - if(isPlotDiv) gd.emit('plotly_autosize'); - - // embedded in an iframe - just take the full iframe size - // if we get to this point, with no aspect ratio restrictions - if(context.fillFrame) { - newWidth = window.innerWidth; - newHeight = window.innerHeight; - - // somehow we get a few extra px height sometimes... - // just hide it - document.body.style.overflow = 'hidden'; - } else { - // plotly.js - let the developers do what they want, either - // provide height and width for the container div, - // specify size in layout, or take the defaults, - // but don't enforce any ratio restrictions - var computedStyle = isPlotDiv ? window.getComputedStyle(gd) : {}; - - newWidth = parseFloat(computedStyle.width) || parseFloat(computedStyle.maxWidth) || fullLayout.width; - newHeight = parseFloat(computedStyle.height) || parseFloat(computedStyle.maxHeight) || fullLayout.height; - - if(isNumeric(frameMargins) && frameMargins > 0) { - var factor = 1 - 2 * frameMargins; - newWidth = Math.round(factor * newWidth); - newHeight = Math.round(factor * newHeight); - } - } - - var minWidth = plots.layoutAttributes.width.min; - var minHeight = plots.layoutAttributes.height.min; - if(newWidth < minWidth) newWidth = minWidth; - if(newHeight < minHeight) newHeight = minHeight; - - var widthHasChanged = !layout.width && - (Math.abs(fullLayout.width - newWidth) > 1); - var heightHasChanged = !layout.height && - (Math.abs(fullLayout.height - newHeight) > 1); - - if(heightHasChanged || widthHasChanged) { - if(widthHasChanged) fullLayout.width = newWidth; - if(heightHasChanged) fullLayout.height = newHeight; - } - - // cache initial autosize value, used in relayout when - // width or height values are set to null - if(!gd._initialAutoSize) { - gd._initialAutoSize = { width: newWidth, height: newHeight }; - } - - plots.sanitizeMargins(fullLayout); -}; - -plots.supplyLayoutModuleDefaults = function(layoutIn, layoutOut, fullData, transitionData) { - var componentsRegistry = Registry.componentsRegistry; - var basePlotModules = layoutOut._basePlotModules; - var component, i, _module; - - var Cartesian = Registry.subplotsRegistry.cartesian; - - // check if any components need to add more base plot modules - // that weren't captured by traces - for(component in componentsRegistry) { - _module = componentsRegistry[component]; - - if(_module.includeBasePlot) { - _module.includeBasePlot(layoutIn, layoutOut); - } - } - - // make sure we *at least* have some cartesian axes - if(!basePlotModules.length) { - basePlotModules.push(Cartesian); - } - - // ensure all cartesian axes have at least one subplot - if(layoutOut._has('cartesian')) { - Registry.getComponentMethod('grid', 'contentDefaults')(layoutIn, layoutOut); - Cartesian.finalizeSubplots(layoutIn, layoutOut); - } - - // sort subplot lists - for(var subplotType in layoutOut._subplots) { - layoutOut._subplots[subplotType].sort(Lib.subplotSort); - } - - // base plot module layout defaults - for(i = 0; i < basePlotModules.length; i++) { - _module = basePlotModules[i]; - - // e.g. pie does not have a layout-defaults step - if(_module.supplyLayoutDefaults) { - _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); - } - } - - // trace module layout defaults - // use _modules rather than _visibleModules so that even - // legendonly traces can include settings - eg barmode, which affects - // legend.traceorder default value. - var modules = layoutOut._modules; - for(i = 0; i < modules.length; i++) { - _module = modules[i]; - - if(_module.supplyLayoutDefaults) { - _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); - } - } - - // transform module layout defaults - var transformModules = layoutOut._transformModules; - for(i = 0; i < transformModules.length; i++) { - _module = transformModules[i]; - - if(_module.supplyLayoutDefaults) { - _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData, transitionData); - } - } - - for(component in componentsRegistry) { - _module = componentsRegistry[component]; - - if(_module.supplyLayoutDefaults) { - _module.supplyLayoutDefaults(layoutIn, layoutOut, fullData); - } - } -}; - -// Remove all plotly attributes from a div so it can be replotted fresh -// TODO: these really need to be encapsulated into a much smaller set... -plots.purge = function(gd) { - // note: we DO NOT remove _context because it doesn't change when we insert - // a new plot, and may have been set outside of our scope. - - var fullLayout = gd._fullLayout || {}; - if(fullLayout._glcontainer !== undefined) { - fullLayout._glcontainer.selectAll('.gl-canvas').remove(); - fullLayout._glcontainer.remove(); - fullLayout._glcanvas = null; - } - if(fullLayout._geocontainer !== undefined) fullLayout._geocontainer.remove(); - - // remove modebar - if(fullLayout._modeBar) fullLayout._modeBar.destroy(); - - if(gd._transitionData) { - // Ensure any dangling callbacks are simply dropped if the plot is purged. - // This is more or less only actually important for testing. - if(gd._transitionData._interruptCallbacks) { - gd._transitionData._interruptCallbacks.length = 0; - } - - if(gd._transitionData._animationRaf) { - window.cancelAnimationFrame(gd._transitionData._animationRaf); - } - } - - // remove any planned throttles - Lib.clearThrottle(); - - // remove responsive handler - Lib.clearResponsive(gd); - - // data and layout - delete gd.data; - delete gd.layout; - delete gd._fullData; - delete gd._fullLayout; - delete gd.calcdata; - delete gd.framework; - delete gd.empty; - - delete gd.fid; - - delete gd.undoqueue; // action queue - delete gd.undonum; - delete gd.autoplay; // are we doing an action that doesn't go in undo queue? - delete gd.changed; - - // these get recreated on Plotly.plot anyway, but just to be safe - // (and to have a record of them...) - delete gd._promises; - delete gd._redrawTimer; - delete gd._hmlumcount; - delete gd._hmpixcount; - delete gd._transitionData; - delete gd._transitioning; - delete gd._initialAutoSize; - delete gd._transitioningWithDuration; - - // created during certain events, that *should* clean them up - // themselves, but may not if there was an error - delete gd._dragging; - delete gd._dragged; - delete gd._dragdata; - delete gd._hoverdata; - delete gd._snapshotInProgress; - delete gd._editing; - delete gd._mouseDownTime; - delete gd._legendMouseDownTime; - - // remove all event listeners - if(gd.removeAllListeners) gd.removeAllListeners(); -}; - -plots.style = function(gd) { - var _modules = gd._fullLayout._visibleModules; - var styleModules = []; - var i; - - // some trace modules reuse the same style method, - // make sure to not unnecessary call them multiple times. - - for(i = 0; i < _modules.length; i++) { - var _module = _modules[i]; - if(_module.style) { - Lib.pushUnique(styleModules, _module.style); - } - } - - for(i = 0; i < styleModules.length; i++) { - styleModules[i](gd); - } -}; - -plots.sanitizeMargins = function(fullLayout) { - // polar doesn't do margins... - if(!fullLayout || !fullLayout.margin) return; - - var width = fullLayout.width; - var height = fullLayout.height; - var margin = fullLayout.margin; - var plotWidth = width - (margin.l + margin.r); - var plotHeight = height - (margin.t + margin.b); - var correction; - - // if margin.l + margin.r = 0 then plotWidth > 0 - // as width >= 10 by supplyDefaults - // similarly for margin.t + margin.b - - if(plotWidth < 0) { - correction = (width - 1) / (margin.l + margin.r); - margin.l = Math.floor(correction * margin.l); - margin.r = Math.floor(correction * margin.r); - } - - if(plotHeight < 0) { - correction = (height - 1) / (margin.t + margin.b); - margin.t = Math.floor(correction * margin.t); - margin.b = Math.floor(correction * margin.b); - } -}; - -plots.clearAutoMarginIds = function(gd) { - gd._fullLayout._pushmarginIds = {}; -}; - -plots.allowAutoMargin = function(gd, id) { - gd._fullLayout._pushmarginIds[id] = 1; -}; - -function initMargins(fullLayout) { - var margin = fullLayout.margin; - - if(!fullLayout._size) { - var gs = fullLayout._size = { - l: Math.round(margin.l), - r: Math.round(margin.r), - t: Math.round(margin.t), - b: Math.round(margin.b), - p: Math.round(margin.pad) - }; - gs.w = Math.round(fullLayout.width) - gs.l - gs.r; - gs.h = Math.round(fullLayout.height) - gs.t - gs.b; - } - if(!fullLayout._pushmargin) fullLayout._pushmargin = {}; - if(!fullLayout._pushmarginIds) fullLayout._pushmarginIds = {}; -} - -/** - * autoMargin: called by components that may need to expand the margins to - * be rendered on-plot. - * - * @param {DOM element} gd - * @param {string} id - an identifier unique (within this plot) to this object, - * so we can remove a previous margin expansion from the same object. - * @param {object} o - the margin requirements of this object, or omit to delete - * this entry (like if it's hidden). Keys are: - * x, y: plot fraction of the anchor point. - * xl, xr, yt, yb: if the object has an extent defined in plot fraction, - * you can specify both edges as plot fractions in each dimension - * l, r, t, b: the pixels to pad past the plot fraction x[l|r] and y[t|b] - * pad: extra pixels to add in all directions, default 12 (why?) - */ -plots.autoMargin = function(gd, id, o) { - var fullLayout = gd._fullLayout; - - var pushMargin = fullLayout._pushmargin; - var pushMarginIds = fullLayout._pushmarginIds; - - if(fullLayout.margin.autoexpand !== false) { - if(!o) { - delete pushMargin[id]; - delete pushMarginIds[id]; - } else { - var pad = o.pad; - if(pad === undefined) { - var margin = fullLayout.margin; - // if no explicit pad is given, use 12px unless there's a - // specified margin that's smaller than that - pad = Math.min(12, margin.l, margin.r, margin.t, margin.b); - } - - // if the item is too big, just give it enough automargin to - // make sure you can still grab it and bring it back - if(o.l + o.r > fullLayout.width * 0.5) o.l = o.r = 0; - if(o.b + o.t > fullLayout.height * 0.5) o.b = o.t = 0; - - var xl = o.xl !== undefined ? o.xl : o.x; - var xr = o.xr !== undefined ? o.xr : o.x; - var yt = o.yt !== undefined ? o.yt : o.y; - var yb = o.yb !== undefined ? o.yb : o.y; - - pushMargin[id] = { - l: {val: xl, size: o.l + pad}, - r: {val: xr, size: o.r + pad}, - b: {val: yb, size: o.b + pad}, - t: {val: yt, size: o.t + pad} - }; - pushMarginIds[id] = 1; - } - - if(!fullLayout._replotting) { - plots.doAutoMargin(gd); - } - } -}; - -plots.doAutoMargin = function(gd) { - var fullLayout = gd._fullLayout; - if(!fullLayout._size) fullLayout._size = {}; - initMargins(fullLayout); - - var gs = fullLayout._size; - var margin = fullLayout.margin; - var oldMargins = Lib.extendFlat({}, gs); - - // adjust margins for outside components - // fullLayout.margin is the requested margin, - // fullLayout._size has margins and plotsize after adjustment - var ml = margin.l; - var mr = margin.r; - var mt = margin.t; - var mb = margin.b; - var width = fullLayout.width; - var height = fullLayout.height; - var pushMargin = fullLayout._pushmargin; - var pushMarginIds = fullLayout._pushmarginIds; - - if(fullLayout.margin.autoexpand !== false) { - for(var k in pushMargin) { - if(!pushMarginIds[k]) delete pushMargin[k]; - } - - // fill in the requested margins - pushMargin.base = { - l: {val: 0, size: ml}, - r: {val: 1, size: mr}, - t: {val: 1, size: mt}, - b: {val: 0, size: mb} - }; - - // now cycle through all the combinations of l and r - // (and t and b) to find the required margins - - for(var k1 in pushMargin) { - var pushleft = pushMargin[k1].l || {}; - var pushbottom = pushMargin[k1].b || {}; - var fl = pushleft.val; - var pl = pushleft.size; - var fb = pushbottom.val; - var pb = pushbottom.size; - - for(var k2 in pushMargin) { - if(isNumeric(pl) && pushMargin[k2].r) { - var fr = pushMargin[k2].r.val; - var pr = pushMargin[k2].r.size; - - if(fr > fl) { - var newL = (pl * fr + (pr - width) * fl) / (fr - fl); - var newR = (pr * (1 - fl) + (pl - width) * (1 - fr)) / (fr - fl); - if(newL >= 0 && newR >= 0 && width - (newL + newR) > 0 && newL + newR > ml + mr) { - ml = newL; - mr = newR; - } - } - } - - if(isNumeric(pb) && pushMargin[k2].t) { - var ft = pushMargin[k2].t.val; - var pt = pushMargin[k2].t.size; - - if(ft > fb) { - var newB = (pb * ft + (pt - height) * fb) / (ft - fb); - var newT = (pt * (1 - fb) + (pb - height) * (1 - ft)) / (ft - fb); - if(newB >= 0 && newT >= 0 && height - (newT + newB) > 0 && newB + newT > mb + mt) { - mb = newB; - mt = newT; - } - } - } - } - } - } - - gs.l = Math.round(ml); - gs.r = Math.round(mr); - gs.t = Math.round(mt); - gs.b = Math.round(mb); - gs.p = Math.round(margin.pad); - gs.w = Math.round(width) - gs.l - gs.r; - gs.h = Math.round(height) - gs.t - gs.b; - - // if things changed and we're not already redrawing, trigger a redraw - if(!fullLayout._replotting && plots.didMarginChange(oldMargins, gs)) { - if('_redrawFromAutoMarginCount' in fullLayout) { - fullLayout._redrawFromAutoMarginCount++; - } else { - fullLayout._redrawFromAutoMarginCount = 1; - } - return Registry.call('plot', gd); - } -}; - -var marginKeys = ['l', 'r', 't', 'b', 'p', 'w', 'h']; - -plots.didMarginChange = function(margin0, margin1) { - for(var i = 0; i < marginKeys.length; i++) { - var k = marginKeys[i]; - var m0 = margin0[k]; - var m1 = margin1[k]; - // use 1px tolerance in case we old/new differ only - // by rounding errors, which can lead to infinite loops - if(!isNumeric(m0) || Math.abs(m1 - m0) > 1) { - return true; - } - } - return false; -}; - -/** - * JSONify the graph data and layout - * - * This function needs to recurse because some src can be inside - * sub-objects. - * - * It also strips out functions and private (starts with _) elements. - * Therefore, we can add temporary things to data and layout that don't - * get saved. - * - * @param gd The graphDiv - * @param {Boolean} dataonly If true, don't return layout. - * @param {'keepref'|'keepdata'|'keepall'} [mode='keepref'] Filter what's kept - * keepref: remove data for which there's a src present - * eg if there's xsrc present (and xsrc is well-formed, - * ie has : and some chars before it), strip out x - * keepdata: remove all src tags, don't remove the data itself - * keepall: keep data and src - * @param {String} output If you specify 'object', the result will not be stringified - * @param {Boolean} useDefaults If truthy, use _fullLayout and _fullData - * @returns {Object|String} - */ -plots.graphJson = function(gd, dataonly, mode, output, useDefaults) { - // if the defaults aren't supplied yet, we need to do that... - if((useDefaults && dataonly && !gd._fullData) || - (useDefaults && !dataonly && !gd._fullLayout)) { - plots.supplyDefaults(gd); - } - - var data = (useDefaults) ? gd._fullData : gd.data; - var layout = (useDefaults) ? gd._fullLayout : gd.layout; - var frames = (gd._transitionData || {})._frames; - - function stripObj(d) { - if(typeof d === 'function') { - return null; - } - if(Lib.isPlainObject(d)) { - var o = {}; - var v, src; - for(v in d) { - // remove private elements and functions - // _ is for private, [ is a mistake ie [object Object] - if(typeof d[v] === 'function' || - ['_', '['].indexOf(v.charAt(0)) !== -1) { - continue; - } - - // look for src/data matches and remove the appropriate one - if(mode === 'keepdata') { - // keepdata: remove all ...src tags - if(v.substr(v.length - 3) === 'src') { - continue; - } - } else if(mode === 'keepstream') { - // keep sourced data if it's being streamed. - // similar to keepref, but if the 'stream' object exists - // in a trace, we will keep the data array. - src = d[v + 'src']; - if(typeof src === 'string' && src.indexOf(':') > 0) { - if(!Lib.isPlainObject(d.stream)) { - continue; - } - } - } else if(mode !== 'keepall') { - // keepref: remove sourced data but only - // if the source tag is well-formed - src = d[v + 'src']; - if(typeof src === 'string' && src.indexOf(':') > 0) { - continue; - } - } - - // OK, we're including this... recurse into it - o[v] = stripObj(d[v]); - } - return o; - } - - if(Array.isArray(d)) { - return d.map(stripObj); - } - - if(Lib.isTypedArray(d)) { - return Lib.simpleMap(d, Lib.identity); - } - - // convert native dates to date strings... - // mostly for external users exporting to plotly - if(Lib.isJSDate(d)) return Lib.ms2DateTimeLocal(+d); - - return d; - } - - var obj = { - data: (data || []).map(function(v) { - var d = stripObj(v); - // fit has some little arrays in it that don't contain data, - // just fit params and meta - if(dataonly) { delete d.fit; } - return d; - }) - }; - if(!dataonly) { obj.layout = stripObj(layout); } - - if(gd.framework && gd.framework.isPolar) obj = gd.framework.getConfig(); - - if(frames) obj.frames = stripObj(frames); - - return (output === 'object') ? obj : JSON.stringify(obj); -}; - -/** - * Modify a keyframe using a list of operations: - * - * @param {array of objects} operations - * Sequence of operations to be performed on the keyframes - */ -plots.modifyFrames = function(gd, operations) { - var i, op, frame; - var _frames = gd._transitionData._frames; - var _frameHash = gd._transitionData._frameHash; - - for(i = 0; i < operations.length; i++) { - op = operations[i]; - - switch(op.type) { - // No reason this couldn't exist, but is currently unused/untested: - /* case 'rename': - frame = _frames[op.index]; - delete _frameHash[frame.name]; - _frameHash[op.name] = frame; - frame.name = op.name; - break;*/ - case 'replace': - frame = op.value; - var oldName = (_frames[op.index] || {}).name; - var newName = frame.name; - _frames[op.index] = _frameHash[newName] = frame; - - if(newName !== oldName) { - // If name has changed in addition to replacement, then update - // the lookup table: - delete _frameHash[oldName]; - _frameHash[newName] = frame; - } - - break; - case 'insert': - frame = op.value; - _frameHash[frame.name] = frame; - _frames.splice(op.index, 0, frame); - break; - case 'delete': - frame = _frames[op.index]; - delete _frameHash[frame.name]; - _frames.splice(op.index, 1); - break; - } - } - - return Promise.resolve(); -}; - -/* - * Compute a keyframe. Merge a keyframe into its base frame(s) and - * expand properties. - * - * @param {object} frameLookup - * An object containing frames keyed by name (i.e. gd._transitionData._frameHash) - * @param {string} frame - * The name of the keyframe to be computed - * - * Returns: a new object with the merged content - */ -plots.computeFrame = function(gd, frameName) { - var frameLookup = gd._transitionData._frameHash; - var i, traceIndices, traceIndex, destIndex; - - // Null or undefined will fail on .toString(). We'll allow numbers since we - // make it clear frames must be given string names, but we'll allow numbers - // here since they're otherwise fine for looking up frames as long as they're - // properly cast to strings. We really just want to ensure here that this - // 1) doesn't fail, and - // 2) doens't give an incorrect answer (which String(frameName) would) - if(!frameName) { - throw new Error('computeFrame must be given a string frame name'); - } - - var framePtr = frameLookup[frameName.toString()]; - - // Return false if the name is invalid: - if(!framePtr) { - return false; - } - - var frameStack = [framePtr]; - var frameNameStack = [framePtr.name]; - - // Follow frame pointers: - while(framePtr.baseframe && (framePtr = frameLookup[framePtr.baseframe.toString()])) { - // Avoid infinite loops: - if(frameNameStack.indexOf(framePtr.name) !== -1) break; - - frameStack.push(framePtr); - frameNameStack.push(framePtr.name); - } - - // A new object for the merged result: - var result = {}; - - // Merge, starting with the last and ending with the desired frame: - while((framePtr = frameStack.pop())) { - if(framePtr.layout) { - result.layout = plots.extendLayout(result.layout, framePtr.layout); - } - - if(framePtr.data) { - if(!result.data) { - result.data = []; - } - traceIndices = framePtr.traces; - - if(!traceIndices) { - // If not defined, assume serial order starting at zero - traceIndices = []; - for(i = 0; i < framePtr.data.length; i++) { - traceIndices[i] = i; - } - } - - if(!result.traces) { - result.traces = []; - } - - for(i = 0; i < framePtr.data.length; i++) { - // Loop through this frames data, find out where it should go, - // and merge it! - traceIndex = traceIndices[i]; - if(traceIndex === undefined || traceIndex === null) { - continue; - } - - destIndex = result.traces.indexOf(traceIndex); - if(destIndex === -1) { - destIndex = result.data.length; - result.traces[destIndex] = traceIndex; - } - - result.data[destIndex] = plots.extendTrace(result.data[destIndex], framePtr.data[i]); - } - } - } - - return result; -}; - -/* - * Recompute the lookup table that maps frame name -> frame object. addFrames/ - * deleteFrames already manages this data one at a time, so the only time this - * is necessary is if you poke around manually in `gd._transitionData._frames` - * and create and haven't updated the lookup table. - */ -plots.recomputeFrameHash = function(gd) { - var hash = gd._transitionData._frameHash = {}; - var frames = gd._transitionData._frames; - for(var i = 0; i < frames.length; i++) { - var frame = frames[i]; - if(frame && frame.name) { - hash[frame.name] = frame; - } - } -}; - -/** - * Extend an object, treating container arrays very differently by extracting - * their contents and merging them separately. - * - * This exists so that we can extendDeepNoArrays and avoid stepping into data - * arrays without knowledge of the plot schema, but so that we may also manually - * recurse into known container arrays, such as transforms. - * - * See extendTrace and extendLayout below for usage. - */ -plots.extendObjectWithContainers = function(dest, src, containerPaths) { - var containerProp, containerVal, i, j, srcProp, destProp, srcContainer, destContainer; - var copy = Lib.extendDeepNoArrays({}, src || {}); - var expandedObj = Lib.expandObjectPaths(copy); - var containerObj = {}; - - // Step through and extract any container properties. Otherwise extendDeepNoArrays - // will clobber any existing properties with an empty array and then supplyDefaults - // will reset everything to defaults. - if(containerPaths && containerPaths.length) { - for(i = 0; i < containerPaths.length; i++) { - containerProp = Lib.nestedProperty(expandedObj, containerPaths[i]); - containerVal = containerProp.get(); - - if(containerVal === undefined) { - Lib.nestedProperty(containerObj, containerPaths[i]).set(null); - } else { - containerProp.set(null); - Lib.nestedProperty(containerObj, containerPaths[i]).set(containerVal); - } - } - } - - dest = Lib.extendDeepNoArrays(dest || {}, expandedObj); - - if(containerPaths && containerPaths.length) { - for(i = 0; i < containerPaths.length; i++) { - srcProp = Lib.nestedProperty(containerObj, containerPaths[i]); - srcContainer = srcProp.get(); - - if(!srcContainer) continue; - - destProp = Lib.nestedProperty(dest, containerPaths[i]); - destContainer = destProp.get(); - - if(!Array.isArray(destContainer)) { - destContainer = []; - destProp.set(destContainer); - } - - for(j = 0; j < srcContainer.length; j++) { - var srcObj = srcContainer[j]; - - if(srcObj === null) destContainer[j] = null; - else { - destContainer[j] = plots.extendObjectWithContainers(destContainer[j], srcObj); - } - } - - destProp.set(destContainer); - } - } - - return dest; -}; - -plots.dataArrayContainers = ['transforms', 'dimensions']; -plots.layoutArrayContainers = Registry.layoutArrayContainers; - -/* - * Extend a trace definition. This method: - * - * 1. directly transfers any array references - * 2. manually recurses into container arrays like transforms - * - * The result is the original object reference with the new contents merged in. - */ -plots.extendTrace = function(destTrace, srcTrace) { - return plots.extendObjectWithContainers(destTrace, srcTrace, plots.dataArrayContainers); -}; - -/* - * Extend a layout definition. This method: - * - * 1. directly transfers any array references (not critically important for - * layout since there aren't really data arrays) - * 2. manually recurses into container arrays like annotations - * - * The result is the original object reference with the new contents merged in. - */ -plots.extendLayout = function(destLayout, srcLayout) { - return plots.extendObjectWithContainers(destLayout, srcLayout, plots.layoutArrayContainers); -}; - -/** - * Transition to a set of new data and layout properties from Plotly.animate - * - * @param {DOM element} gd - * @param {Object[]} data - * an array of data objects following the normal Plotly data definition format - * @param {Object} layout - * a layout object, following normal Plotly layout format - * @param {Number[]} traces - * indices of the corresponding traces specified in `data` - * @param {Object} frameOpts - * options for the frame (i.e. whether to redraw post-transition) - * @param {Object} transitionOpts - * options for the transition - */ -plots.transition = function(gd, data, layout, traces, frameOpts, transitionOpts) { - var opts = {redraw: frameOpts.redraw}; - var transitionedTraces = {}; - var axEdits = []; - - opts.prepareFn = function() { - var dataLength = Array.isArray(data) ? data.length : 0; - var traceIndices = traces.slice(0, dataLength); - - for(var i = 0; i < traceIndices.length; i++) { - var traceIdx = traceIndices[i]; - var trace = gd._fullData[traceIdx]; - var _module = trace._module; - - // There's nothing to do if this module is not defined: - if(!_module) continue; - - // Don't register the trace as transitioned if it doesn't know what to do. - // If it *is* registered, it will receive a callback that it's responsible - // for calling in order to register the transition as having completed. - if(_module.animatable) { - var n = _module.basePlotModule.name; - if(!transitionedTraces[n]) transitionedTraces[n] = []; - transitionedTraces[n].push(traceIdx); - } - - gd.data[traceIndices[i]] = plots.extendTrace(gd.data[traceIndices[i]], data[i]); - } - - // Follow the same procedure. Clone it so we don't mangle the input, then - // expand any object paths so we can merge deep into gd.layout: - var layoutUpdate = Lib.expandObjectPaths(Lib.extendDeepNoArrays({}, layout)); - - // Before merging though, we need to modify the incoming layout. We only - // know how to *transition* layout ranges, so it's imperative that a new - // range not be sent to the layout before the transition has started. So - // we must remove the things we can transition: - var axisAttrRe = /^[xy]axis[0-9]*$/; - for(var attr in layoutUpdate) { - if(!axisAttrRe.test(attr)) continue; - delete layoutUpdate[attr].range; - } - - plots.extendLayout(gd.layout, layoutUpdate); - - // Supply defaults after applying the incoming properties. Note that any attempt - // to simplify this step and reduce the amount of work resulted in the reconstruction - // of essentially the whole supplyDefaults step, so that it seems sensible to just use - // supplyDefaults even though it's heavier than would otherwise be desired for - // transitions: - - // first delete calcdata so supplyDefaults knows a calc step is coming - delete gd.calcdata; - - plots.supplyDefaults(gd); - plots.doCalcdata(gd); - - var newLayout = Lib.expandObjectPaths(layout); - - if(newLayout) { - var subplots = gd._fullLayout._plots; - - for(var k in subplots) { - var plotinfo = subplots[k]; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - var xr0 = xa.range.slice(); - var yr0 = ya.range.slice(); - - var xr1; - if(Array.isArray(newLayout[xa._name + '.range'])) { - xr1 = newLayout[xa._name + '.range'].slice(); - } else if(Array.isArray((newLayout[xa._name] || {}).range)) { - xr1 = newLayout[xa._name].range.slice(); - } - - var yr1; - if(Array.isArray(newLayout[ya._name + '.range'])) { - yr1 = newLayout[ya._name + '.range'].slice(); - } else if(Array.isArray((newLayout[ya._name] || {}).range)) { - yr1 = newLayout[ya._name].range.slice(); - } - - var editX; - if(xr0 && xr1 && (xr0[0] !== xr1[0] || xr0[1] !== xr1[1])) { - editX = {xr0: xr0, xr1: xr1}; - } - - var editY; - if(yr0 && yr1 && (yr0[0] !== yr1[0] || yr0[1] !== yr1[1])) { - editY = {yr0: yr0, yr1: yr1}; - } - - if(editX || editY) { - axEdits.push(Lib.extendFlat({plotinfo: plotinfo}, editX, editY)); - } - } - } - - return Promise.resolve(); - }; - - opts.runFn = function(makeCallback) { - var traceTransitionOpts; - var basePlotModules = gd._fullLayout._basePlotModules; - var hasAxisTransition = axEdits.length; - var i; - - if(layout) { - for(i = 0; i < basePlotModules.length; i++) { - if(basePlotModules[i].transitionAxes) { - basePlotModules[i].transitionAxes(gd, axEdits, transitionOpts, makeCallback); - } - } - } - - // Here handle the exception that we refuse to animate scales and axes at the same - // time. In other words, if there's an axis transition, then set the data transition - // to instantaneous. - if(hasAxisTransition) { - traceTransitionOpts = Lib.extendFlat({}, transitionOpts); - traceTransitionOpts.duration = 0; - // This means do not transition cartesian traces, - // this happens on layout-only (e.g. axis range) animations - delete transitionedTraces.cartesian; - } else { - traceTransitionOpts = transitionOpts; - } - - // Note that we pass a callback to *create* the callback that must be invoked on completion. - // This is since not all traces know about transitions, so it greatly simplifies matters if - // the trace is responsible for creating a callback, if needed, and then executing it when - // the time is right. - for(var n in transitionedTraces) { - var traceIndices = transitionedTraces[n]; - var _module = gd._fullData[traceIndices[0]]._module; - _module.basePlotModule.plot(gd, traceIndices, traceTransitionOpts, makeCallback); - } - }; - - return _transition(gd, transitionOpts, opts); -}; - -/** - * Transition to a set of new data and layout properties from Plotly.react - * - * @param {DOM element} gd - * @param {object} restyleFlags - * - anim {'all'|'some'} - * @param {object} relayoutFlags - * - anim {'all'|'some'} - * @param {object} oldFullLayout : old (pre Plotly.react) fullLayout - */ -plots.transitionFromReact = function(gd, restyleFlags, relayoutFlags, oldFullLayout) { - var fullLayout = gd._fullLayout; - var transitionOpts = fullLayout.transition; - var opts = {}; - var axEdits = []; - - opts.prepareFn = function() { - var subplots = fullLayout._plots; - - // no need to redraw at end of transition, - // if all changes are animatable - opts.redraw = false; - if(restyleFlags.anim === 'some') opts.redraw = true; - if(relayoutFlags.anim === 'some') opts.redraw = true; - - for(var k in subplots) { - var plotinfo = subplots[k]; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - var xr0 = oldFullLayout[xa._name].range.slice(); - var yr0 = oldFullLayout[ya._name].range.slice(); - var xr1 = xa.range.slice(); - var yr1 = ya.range.slice(); - - xa.setScale(); - ya.setScale(); - - var editX; - if(xr0[0] !== xr1[0] || xr0[1] !== xr1[1]) { - editX = {xr0: xr0, xr1: xr1}; - } - - var editY; - if(yr0[0] !== yr1[0] || yr0[1] !== yr1[1]) { - editY = {yr0: yr0, yr1: yr1}; - } - - if(editX || editY) { - axEdits.push(Lib.extendFlat({plotinfo: plotinfo}, editX, editY)); - } - } - - return Promise.resolve(); - }; - - opts.runFn = function(makeCallback) { - var fullData = gd._fullData; - var fullLayout = gd._fullLayout; - var basePlotModules = fullLayout._basePlotModules; - - var axisTransitionOpts; - var traceTransitionOpts; - var transitionedTraces; - - var allTraceIndices = []; - for(var i = 0; i < fullData.length; i++) { - allTraceIndices.push(i); - } - - function transitionAxes() { - for(var j = 0; j < basePlotModules.length; j++) { - if(basePlotModules[j].transitionAxes) { - basePlotModules[j].transitionAxes(gd, axEdits, axisTransitionOpts, makeCallback); - } - } - } - - function transitionTraces() { - for(var j = 0; j < basePlotModules.length; j++) { - basePlotModules[j].plot(gd, transitionedTraces, traceTransitionOpts, makeCallback); - } - } - - if(axEdits.length && restyleFlags.anim) { - if(transitionOpts.ordering === 'traces first') { - axisTransitionOpts = Lib.extendFlat({}, transitionOpts, {duration: 0}); - transitionedTraces = allTraceIndices; - traceTransitionOpts = transitionOpts; - transitionTraces(); - setTimeout(transitionAxes, transitionOpts.duration); - } else { - axisTransitionOpts = transitionOpts; - transitionedTraces = null; - traceTransitionOpts = Lib.extendFlat({}, transitionOpts, {duration: 0}); - transitionAxes(); - transitionTraces(); - } - } else if(axEdits.length) { - axisTransitionOpts = transitionOpts; - transitionAxes(); - } else if(restyleFlags.anim) { - transitionedTraces = allTraceIndices; - traceTransitionOpts = transitionOpts; - transitionTraces(); - } - }; - - return _transition(gd, transitionOpts, opts); -}; - -/** - * trace/layout transition wrapper that works - * for transitions initiated by Plotly.animate and Plotly.react. - * - * @param {DOM element} gd - * @param {object} transitionOpts - * @param {object} opts - * - redraw {boolean} - * - prepareFn {function} *should return a Promise* - * - runFn {function} ran inside executeTransitions - */ -function _transition(gd, transitionOpts, opts) { - var aborted = false; - - function executeCallbacks(list) { - var p = Promise.resolve(); - if(!list) return p; - while(list.length) { - p = p.then((list.shift())); - } - return p; - } - - function flushCallbacks(list) { - if(!list) return; - while(list.length) { - list.shift(); - } - } - - function executeTransitions() { - gd.emit('plotly_transitioning', []); - - return new Promise(function(resolve) { - // This flag is used to disabled things like autorange: - gd._transitioning = true; - - // When instantaneous updates are coming through quickly, it's too much to simply disable - // all interaction, so store this flag so we can disambiguate whether mouse interactions - // should be fully disabled or not: - if(transitionOpts.duration > 0) { - gd._transitioningWithDuration = true; - } - - // If another transition is triggered, this callback will be executed simply because it's - // in the interruptCallbacks queue. If this transition completes, it will instead flush - // that queue and forget about this callback. - gd._transitionData._interruptCallbacks.push(function() { - aborted = true; - }); - - if(opts.redraw) { - gd._transitionData._interruptCallbacks.push(function() { - return Registry.call('redraw', gd); - }); - } - - // Emit this and make sure it happens last: - gd._transitionData._interruptCallbacks.push(function() { - gd.emit('plotly_transitioninterrupted', []); - }); - - // Construct callbacks that are executed on transition end. This ensures the d3 transitions - // are *complete* before anything else is done. - var numCallbacks = 0; - var numCompleted = 0; - function makeCallback() { - numCallbacks++; - return function() { - numCompleted++; - // When all are complete, perform a redraw: - if(!aborted && numCompleted === numCallbacks) { - completeTransition(resolve); - } - }; - } - - opts.runFn(makeCallback); - - // If nothing else creates a callback, then this will trigger the completion in the next tick: - setTimeout(makeCallback()); - }); - } - - function completeTransition(callback) { - // This a simple workaround for tests which purge the graph before animations - // have completed. That's not a very common case, so this is the simplest - // fix. - if(!gd._transitionData) return; - - flushCallbacks(gd._transitionData._interruptCallbacks); - - return Promise.resolve().then(function() { - if(opts.redraw) { - return Registry.call('redraw', gd); - } - }).then(function() { - // Set transitioning false again once the redraw has occurred. This is used, for example, - // to prevent the trailing redraw from autoranging: - gd._transitioning = false; - gd._transitioningWithDuration = false; - - gd.emit('plotly_transitioned', []); - }).then(callback); - } - - function interruptPreviousTransitions() { - // Fail-safe against purged plot: - if(!gd._transitionData) return; - - // If a transition is interrupted, set this to false. At the moment, the only thing that would - // interrupt a transition is another transition, so that it will momentarily be set to true - // again, but this determines whether autorange or dragbox work, so it's for the sake of - // cleanliness: - gd._transitioning = false; - - return executeCallbacks(gd._transitionData._interruptCallbacks); - } - - var seq = [ - plots.previousPromises, - interruptPreviousTransitions, - opts.prepareFn, - plots.rehover, - executeTransitions - ]; - - var transitionStarting = Lib.syncOrAsync(seq, gd); - - if(!transitionStarting || !transitionStarting.then) { - transitionStarting = Promise.resolve(); - } - - return transitionStarting.then(function() { return gd; }); -} - -plots.doCalcdata = function(gd, traces) { - var axList = axisIDs.list(gd); - var fullData = gd._fullData; - var fullLayout = gd._fullLayout; - - var trace, _module, i, j; - - // XXX: Is this correct? Needs a closer look so that *some* traces can be recomputed without - // *all* needing doCalcdata: - var calcdata = new Array(fullData.length); - var oldCalcdata = (gd.calcdata || []).slice(); - gd.calcdata = calcdata; - - // extra helper variables - - // how many box/violins plots do we have (in case they're grouped) - fullLayout._numBoxes = 0; - fullLayout._numViolins = 0; - - // initialize violin per-scale-group stats container - fullLayout._violinScaleGroupStats = {}; - - // for calculating avg luminosity of heatmaps - gd._hmpixcount = 0; - gd._hmlumcount = 0; - - // for sharing colors across pies / sunbursts / funnelarea (and for legend) - fullLayout._piecolormap = {}; - fullLayout._sunburstcolormap = {}; - fullLayout._funnelareacolormap = {}; - - // If traces were specified and this trace was not included, - // then transfer it over from the old calcdata: - for(i = 0; i < fullData.length; i++) { - if(Array.isArray(traces) && traces.indexOf(i) === -1) { - calcdata[i] = oldCalcdata[i]; - continue; - } - } - - for(i = 0; i < fullData.length; i++) { - trace = fullData[i]; - - trace._arrayAttrs = PlotSchema.findArrayAttributes(trace); - - // keep track of trace extremes (for autorange) in here - trace._extremes = {}; - } - - // add polar axes to axis list - var polarIds = fullLayout._subplots.polar || []; - for(i = 0; i < polarIds.length; i++) { - axList.push( - fullLayout[polarIds[i]].radialaxis, - fullLayout[polarIds[i]].angularaxis - ); - } - - var hasCalcTransform = false; - - function transformCalci(i) { - trace = fullData[i]; - _module = trace._module; - - if(trace.visible === true && trace.transforms) { - // we need one round of trace module calc before - // the calc transform to 'fill in' the categories list - // used for example in the data-to-coordinate method - if(_module && _module.calc) { - var cdi = _module.calc(gd, trace); - - // must clear scene 'batches', so that 2nd - // _module.calc call starts from scratch - if(cdi[0] && cdi[0].t && cdi[0].t._scene) { - delete cdi[0].t._scene.dirty; - } - } - - for(j = 0; j < trace.transforms.length; j++) { - var transform = trace.transforms[j]; - - _module = transformsRegistry[transform.type]; - if(_module && _module.calcTransform) { - trace._hasCalcTransform = true; - hasCalcTransform = true; - _module.calcTransform(gd, trace, transform); - } - } - } - } - - function calci(i, isContainer) { - trace = fullData[i]; - _module = trace._module; - - if(!!_module.isContainer !== isContainer) return; - - var cd = []; - - if(trace.visible === true && trace._length !== 0) { - // clear existing ref in case it got relinked - delete trace._indexToPoints; - // keep ref of index-to-points map object of the *last* enabled transform, - // this index-to-points map object is required to determine the calcdata indices - // that correspond to input indices (e.g. from 'selectedpoints') - var transforms = trace.transforms || []; - for(j = transforms.length - 1; j >= 0; j--) { - if(transforms[j].enabled) { - trace._indexToPoints = transforms[j]._indexToPoints; - break; - } - } - - if(_module && _module.calc) { - cd = _module.calc(gd, trace); - } - } - - // Make sure there is a first point. - // - // This ensures there is a calcdata item for every trace, - // even if cartesian logic doesn't handle it (for things like legends). - if(!Array.isArray(cd) || !cd[0]) { - cd = [{x: BADNUM, y: BADNUM}]; - } - - // add the trace-wide properties to the first point, - // per point properties to every point - // t is the holder for trace-wide properties - if(!cd[0].t) cd[0].t = {}; - cd[0].trace = trace; - - calcdata[i] = cd; - } - - setupAxisCategories(axList, fullData); - - // 'transform' loop - must calc container traces first - // so that if their dependent traces can get transform properly - for(i = 0; i < fullData.length; i++) calci(i, true); - for(i = 0; i < fullData.length; i++) transformCalci(i); - - // clear stuff that should recomputed in 'regular' loop - if(hasCalcTransform) setupAxisCategories(axList, fullData); - - // 'regular' loop - make sure container traces (eg carpet) calc before - // contained traces (eg contourcarpet) - for(i = 0; i < fullData.length; i++) calci(i, true); - for(i = 0; i < fullData.length; i++) calci(i, false); - - doCrossTraceCalc(gd); - - // Sort axis categories per value if specified - var sorted = sortAxisCategoriesByValue(axList, gd); - if(sorted.length) { - // how many box/violins plots do we have (in case they're grouped) - fullLayout._numBoxes = 0; - fullLayout._numViolins = 0; - // If a sort operation was performed, run calc() again - for(i = 0; i < sorted.length; i++) calci(sorted[i], true); - for(i = 0; i < sorted.length; i++) calci(sorted[i], false); - doCrossTraceCalc(gd); - } - - Registry.getComponentMethod('fx', 'calc')(gd); - Registry.getComponentMethod('errorbars', 'calc')(gd); -}; - -var sortAxisCategoriesByValueRegex = /(total|sum|min|max|mean|median) (ascending|descending)/; - -function sortAxisCategoriesByValue(axList, gd) { - var affectedTraces = []; - var i, j, k, l, o; - - function zMapCategory(type, ax, value) { - var axLetter = ax._id.charAt(0); - if(type === 'histogram2dcontour') { - var counterAxLetter = ax._counterAxes[0]; - var counterAx = axisIDs.getFromId(gd, counterAxLetter); - - var xCategorical = axLetter === 'x' || (counterAxLetter === 'x' && counterAx.type === 'category'); - var yCategorical = axLetter === 'y' || (counterAxLetter === 'y' && counterAx.type === 'category'); - - return function(o, l) { - if(o === 0 || l === 0) return -1; // Skip first row and column - if(xCategorical && o === value[l].length - 1) return -1; - if(yCategorical && l === value.length - 1) return -1; - - return (axLetter === 'y' ? l : o) - 1; - }; - } else { - return function(o, l) { - return axLetter === 'y' ? l : o; - }; - } - } - - var aggFn = { - 'min': function(values) {return Lib.aggNums(Math.min, null, values);}, - 'max': function(values) {return Lib.aggNums(Math.max, null, values);}, - 'sum': function(values) {return Lib.aggNums(function(a, b) { return a + b;}, null, values);}, - 'total': function(values) {return Lib.aggNums(function(a, b) { return a + b;}, null, values);}, - 'mean': function(values) {return Lib.mean(values);}, - 'median': function(values) {return Lib.median(values);} - }; - - for(i = 0; i < axList.length; i++) { - var ax = axList[i]; - if(ax.type !== 'category') continue; - - // Order by value - var match = ax.categoryorder.match(sortAxisCategoriesByValueRegex); - if(match) { - var aggregator = match[1]; - var order = match[2]; - - // Store values associated with each category - var categoriesValue = []; - for(j = 0; j < ax._categories.length; j++) { - categoriesValue.push([ax._categories[j], []]); - } - - // Collect values across traces - for(j = 0; j < ax._traceIndices.length; j++) { - var traceIndex = ax._traceIndices[j]; - var fullTrace = gd._fullData[traceIndex]; - var axLetter = ax._id.charAt(0); - - // Skip over invisible traces - if(fullTrace.visible !== true) continue; - - var type = fullTrace.type; - if(Registry.traceIs(fullTrace, 'histogram')) { - delete fullTrace._xautoBinFinished; - delete fullTrace._yautoBinFinished; - } - - var cd = gd.calcdata[traceIndex]; - for(k = 0; k < cd.length; k++) { - var cdi = cd[k]; - var cat, catIndex, value; - - if(type === 'splom') { - // If `splom`, collect values across dimensions - // Find which dimension the current axis is representing - var currentDimensionIndex = fullTrace._axesDim[ax._id]; - - // Apply logic to associated x axis if it's defined - if(axLetter === 'y') { - var associatedXAxisID = fullTrace._diag[currentDimensionIndex][0]; - if(associatedXAxisID) ax = gd._fullLayout[axisIDs.id2name(associatedXAxisID)]; - } - - var categories = cdi.trace.dimensions[currentDimensionIndex].values; - for(l = 0; l < categories.length; l++) { - cat = categories[l]; - catIndex = ax._categoriesMap[cat]; - - // Collect associated values at index `l` over all other dimensions - for(o = 0; o < cdi.trace.dimensions.length; o++) { - if(o === currentDimensionIndex) continue; - var dimension = cdi.trace.dimensions[o]; - categoriesValue[catIndex][1].push(dimension.values[l]); - } - } - } else if(type === 'scattergl') { - // If `scattergl`, collect all values stashed under cdi.t - for(l = 0; l < cdi.t.x.length; l++) { - if(axLetter === 'x') { - cat = cdi.t.x[l]; - catIndex = cat; - value = cdi.t.y[l]; - } - - if(axLetter === 'y') { - cat = cdi.t.y[l]; - catIndex = cat; - value = cdi.t.x[l]; - } - categoriesValue[catIndex][1].push(value); - } - // must clear scene 'batches', so that 2nd - // _module.calc call starts from scratch - if(cdi.t && cdi.t._scene) { - delete cdi.t._scene.dirty; - } - } else if(cdi.hasOwnProperty('z')) { - // If 2dMap, collect values in `z` - value = cdi.z; - var mapping = zMapCategory(fullTrace.type, ax, value); - - for(l = 0; l < value.length; l++) { - for(o = 0; o < value[l].length; o++) { - catIndex = mapping(o, l); - if(catIndex + 1) categoriesValue[catIndex][1].push(value[l][o]); - } - } - } else { - // For all other 2d cartesian traces - if(axLetter === 'x') { - cat = cdi.p + 1 ? cdi.p : cdi.x; - value = cdi.s || cdi.v || cdi.y; - } else if(axLetter === 'y') { - cat = cdi.p + 1 ? cdi.p : cdi.y; - value = cdi.s || cdi.v || cdi.x; - } - if(!Array.isArray(value)) value = [value]; - for(l = 0; l < value.length; l++) { - categoriesValue[cat][1].push(value[l]); - } - } - } - } - - ax._categoriesValue = categoriesValue; - - var categoriesAggregatedValue = []; - for(j = 0; j < categoriesValue.length; j++) { - categoriesAggregatedValue.push([ - categoriesValue[j][0], - aggFn[aggregator](categoriesValue[j][1]) - ]); - } - - // Sort by aggregated value - categoriesAggregatedValue.sort(function(a, b) { - return a[1] - b[1]; - }); - - ax._categoriesAggregatedValue = categoriesAggregatedValue; - - // Set new category order - ax._initialCategories = categoriesAggregatedValue.map(function(c) { - return c[0]; - }); - - // Reverse if descending - if(order === 'descending') { - ax._initialCategories.reverse(); - } - - // Sort all matching axes - affectedTraces = affectedTraces.concat(ax.sortByInitialCategories()); - } - } - return affectedTraces; -} - -function setupAxisCategories(axList, fullData) { - for(var i = 0; i < axList.length; i++) { - var ax = axList[i]; - ax.clearCalc(); - if(ax.type === 'multicategory') { - ax.setupMultiCategory(fullData); - } - } -} - -function doCrossTraceCalc(gd) { - var fullLayout = gd._fullLayout; - var modules = fullLayout._visibleModules; - var hash = {}; - var i, j, k; - - // position and range calculations for traces that - // depend on each other ie bars (stacked or grouped) - // and boxes (grouped) push each other out of the way - - for(j = 0; j < modules.length; j++) { - var _module = modules[j]; - var fn = _module.crossTraceCalc; - if(fn) { - var spType = _module.basePlotModule.name; - if(hash[spType]) { - Lib.pushUnique(hash[spType], fn); - } else { - hash[spType] = [fn]; - } - } - } - - for(k in hash) { - var methods = hash[k]; - var subplots = fullLayout._subplots[k]; - - if(Array.isArray(subplots)) { - for(i = 0; i < subplots.length; i++) { - var sp = subplots[i]; - var spInfo = k === 'cartesian' ? - fullLayout._plots[sp] : - fullLayout[sp]; - - for(j = 0; j < methods.length; j++) { - methods[j](gd, spInfo, sp); - } - } - } else { - for(j = 0; j < methods.length; j++) { - methods[j](gd); - } - } - } -} - -plots.rehover = function(gd) { - if(gd._fullLayout._rehover) { - gd._fullLayout._rehover(); - } -}; - -plots.redrag = function(gd) { - if(gd._fullLayout._redrag) { - gd._fullLayout._redrag(); - } -}; - -plots.generalUpdatePerTraceModule = function(gd, subplot, subplotCalcData, subplotLayout) { - var traceHashOld = subplot.traceHash; - var traceHash = {}; - var i; - - // build up moduleName -> calcData hash - for(i = 0; i < subplotCalcData.length; i++) { - var calcTraces = subplotCalcData[i]; - var trace = calcTraces[0].trace; - - // skip over visible === false traces - // as they don't have `_module` ref - if(trace.visible) { - traceHash[trace.type] = traceHash[trace.type] || []; - traceHash[trace.type].push(calcTraces); - } - } - - // when a trace gets deleted, make sure that its module's - // plot method is called so that it is properly - // removed from the DOM. - for(var moduleNameOld in traceHashOld) { - if(!traceHash[moduleNameOld]) { - var fakeCalcTrace = traceHashOld[moduleNameOld][0]; - var fakeTrace = fakeCalcTrace[0].trace; - - fakeTrace.visible = false; - traceHash[moduleNameOld] = [fakeCalcTrace]; - } - } - - // call module plot method - for(var moduleName in traceHash) { - var moduleCalcData = traceHash[moduleName]; - var _module = moduleCalcData[0][0].trace._module; - - _module.plot(gd, subplot, Lib.filterVisible(moduleCalcData), subplotLayout); - } - - // update moduleName -> calcData hash - subplot.traceHash = traceHash; -}; - -},{"../components/color":593,"../constants/numerical":695,"../lib":719,"../plot_api/plot_schema":756,"../plot_api/plot_template":757,"../registry":847,"./animation_attributes":762,"./attributes":764,"./cartesian/axis_ids":770,"./command":791,"./font_attributes":793,"./frame_attributes":794,"./layout_attributes":819,"d3":163,"fast-isnumeric":225}],829:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attr: 'subplot', - name: 'polar', - - axisNames: ['angularaxis', 'radialaxis'], - axisName2dataArray: {angularaxis: 'theta', radialaxis: 'r'}, - - layerNames: [ - 'draglayer', - 'plotbg', - 'backplot', - 'angular-grid', - 'radial-grid', - 'frontplot', - 'angular-line', - 'radial-line', - 'angular-axis', - 'radial-axis' - ], - - radialDragBoxSize: 50, - angularDragBoxSize: 30, - cornerLen: 25, - cornerHalfWidth: 2, - - // pixels to move mouse before you stop clamping to starting point - MINDRAG: 8, - // smallest radial distance [px] allowed for a zoombox - MINZOOM: 20, - // distance [px] off (r=0) or (r=radius) where we transition - // from single-sided to two-sided radial zoom - OFFEDGE: 20 -}; - -},{}],830:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var polygonTester = _dereq_('../../lib/polygon').tester; - -var findIndexOfMin = Lib.findIndexOfMin; -var isAngleInsideSector = Lib.isAngleInsideSector; -var angleDelta = Lib.angleDelta; -var angleDist = Lib.angleDist; - -/** - * is pt (r,a) inside polygon made up vertices at angles 'vangles' - * inside a given polar sector - * - * @param {number} r : pt's radial coordinate - * @param {number} a : pt's angular coordinate in *radians* - * @param {2-item array} rBnds : sector's radial bounds - * @param {2-item array} aBnds : sector's angular bounds *radians* - * @param {array} vangles : angles of polygon vertices in *radians* - * @return {boolean} - */ -function isPtInsidePolygon(r, a, rBnds, aBnds, vangles) { - if(!isAngleInsideSector(a, aBnds)) return false; - - var r0, r1; - - if(rBnds[0] < rBnds[1]) { - r0 = rBnds[0]; - r1 = rBnds[1]; - } else { - r0 = rBnds[1]; - r1 = rBnds[0]; - } - - var polygonIn = polygonTester(makePolygon(r0, aBnds[0], aBnds[1], vangles)); - var polygonOut = polygonTester(makePolygon(r1, aBnds[0], aBnds[1], vangles)); - var xy = [r * Math.cos(a), r * Math.sin(a)]; - return polygonOut.contains(xy) && !polygonIn.contains(xy); -} - -// find intersection of 'v0' <-> 'v1' edge with a ray at angle 'a' -// (i.e. a line that starts from the origin at angle 'a') -// given an (xp,yp) pair on the 'v0' <-> 'v1' line -// (N.B. 'v0' and 'v1' are angles in radians) -function findIntersectionXY(v0, v1, a, xpyp) { - var xstar, ystar; - - var xp = xpyp[0]; - var yp = xpyp[1]; - var dsin = clampTiny(Math.sin(v1) - Math.sin(v0)); - var dcos = clampTiny(Math.cos(v1) - Math.cos(v0)); - var tanA = Math.tan(a); - var cotanA = clampTiny(1 / tanA); - var m = dsin / dcos; - var b = yp - m * xp; - - if(cotanA) { - if(dsin && dcos) { - // given - // g(x) := v0 -> v1 line = m*x + b - // h(x) := ray at angle 'a' = m*x = tanA*x - // solve g(xstar) = h(xstar) - xstar = b / (tanA - m); - ystar = tanA * xstar; - } else if(dcos) { - // horizontal v0 -> v1 - xstar = yp * cotanA; - ystar = yp; - } else { - // vertical v0 -> v1 - xstar = xp; - ystar = xp * tanA; - } - } else { - // vertical ray - if(dsin && dcos) { - xstar = 0; - ystar = b; - } else if(dcos) { - xstar = 0; - ystar = yp; - } else { - // does this case exists? - xstar = ystar = NaN; - } - } - - return [xstar, ystar]; -} - -// solves l^2 = (f(x)^2 - yp)^2 + (x - xp)^2 -// rearranged into 0 = a*x^2 + b * x + c -// -// where f(x) = m*x + t + yp -// and (x0, x1) = (-b +/- del) / (2*a) -function findXYatLength(l, m, xp, yp) { - var t = -m * xp; - var a = m * m + 1; - var b = 2 * (m * t - xp); - var c = t * t + xp * xp - l * l; - var del = Math.sqrt(b * b - 4 * a * c); - var x0 = (-b + del) / (2 * a); - var x1 = (-b - del) / (2 * a); - return [ - [x0, m * x0 + t + yp], - [x1, m * x1 + t + yp] - ]; -} - -function makeRegularPolygon(r, vangles) { - var len = vangles.length; - var vertices = new Array(len + 1); - var i; - for(i = 0; i < len; i++) { - var va = vangles[i]; - vertices[i] = [r * Math.cos(va), r * Math.sin(va)]; - } - vertices[i] = vertices[0].slice(); - return vertices; -} - -function makeClippedPolygon(r, a0, a1, vangles) { - var len = vangles.length; - var vertices = []; - var i, j; - - function a2xy(a) { - return [r * Math.cos(a), r * Math.sin(a)]; - } - - function findXY(va0, va1, s) { - return findIntersectionXY(va0, va1, s, a2xy(va0)); - } - - function cycleIndex(ind) { - return Lib.mod(ind, len); - } - - function isInside(v) { - return isAngleInsideSector(v, [a0, a1]); - } - - // find index in sector closest to a0 - // use it to find intersection of v[i0] <-> v[i0-1] edge with sector radius - var i0 = findIndexOfMin(vangles, function(v) { - return isInside(v) ? angleDist(v, a0) : Infinity; - }); - var xy0 = findXY(vangles[i0], vangles[cycleIndex(i0 - 1)], a0); - vertices.push(xy0); - - // fill in in-sector vertices - for(i = i0, j = 0; j < len; i++, j++) { - var va = vangles[cycleIndex(i)]; - if(!isInside(va)) break; - vertices.push(a2xy(va)); - } - - // find index in sector closest to a1, - // use it to find intersection of v[iN] <-> v[iN+1] edge with sector radius - var iN = findIndexOfMin(vangles, function(v) { - return isInside(v) ? angleDist(v, a1) : Infinity; - }); - var xyN = findXY(vangles[iN], vangles[cycleIndex(iN + 1)], a1); - vertices.push(xyN); - - vertices.push([0, 0]); - vertices.push(vertices[0].slice()); - - return vertices; -} - -function makePolygon(r, a0, a1, vangles) { - return Lib.isFullCircle([a0, a1]) ? - makeRegularPolygon(r, vangles) : - makeClippedPolygon(r, a0, a1, vangles); -} - -function findPolygonOffset(r, a0, a1, vangles) { - var minX = Infinity; - var minY = Infinity; - var vertices = makePolygon(r, a0, a1, vangles); - - for(var i = 0; i < vertices.length; i++) { - var v = vertices[i]; - minX = Math.min(minX, v[0]); - minY = Math.min(minY, -v[1]); - } - return [minX, minY]; -} - -/** - * find vertex angles (in 'vangles') the enclose angle 'a' - * - * @param {number} a : angle in *radians* - * @param {array} vangles : angles of polygon vertices in *radians* - * @return {2-item array} - */ -function findEnclosingVertexAngles(a, vangles) { - var minFn = function(v) { - var adelta = angleDelta(v, a); - return adelta > 0 ? adelta : Infinity; - }; - var i0 = findIndexOfMin(vangles, minFn); - var i1 = Lib.mod(i0 + 1, vangles.length); - return [vangles[i0], vangles[i1]]; -} - -// to more easily catch 'almost zero' numbers in if-else blocks -function clampTiny(v) { - return Math.abs(v) > 1e-10 ? v : 0; -} - -function transformForSVG(pts0, cx, cy) { - cx = cx || 0; - cy = cy || 0; - - var len = pts0.length; - var pts1 = new Array(len); - - for(var i = 0; i < len; i++) { - var pt = pts0[i]; - pts1[i] = [cx + pt[0], cy - pt[1]]; - } - return pts1; -} - -/** - * path polygon - * - * @param {number} r : polygon 'radius' - * @param {number} a0 : first angular coordinate in *radians* - * @param {number} a1 : second angular coordinate in *radians* - * @param {array} vangles : angles of polygon vertices in *radians* - * @param {number (optional)} cx : x coordinate of center - * @param {number (optional)} cy : y coordinate of center - * @return {string} svg path - * - */ -function pathPolygon(r, a0, a1, vangles, cx, cy) { - var poly = makePolygon(r, a0, a1, vangles); - return 'M' + transformForSVG(poly, cx, cy).join('L'); -} - -/** - * path a polygon 'annulus' - * i.e. a polygon with a concentric hole - * - * N.B. this routine uses the evenodd SVG rule - * - * @param {number} r0 : first radial coordinate - * @param {number} r1 : second radial coordinate - * @param {number} a0 : first angular coordinate in *radians* - * @param {number} a1 : second angular coordinate in *radians* - * @param {array} vangles : angles of polygon vertices in *radians* - * @param {number (optional)} cx : x coordinate of center - * @param {number (optional)} cy : y coordinate of center - * @return {string} svg path - * - */ -function pathPolygonAnnulus(r0, r1, a0, a1, vangles, cx, cy) { - var rStart, rEnd; - - if(r0 < r1) { - rStart = r0; - rEnd = r1; - } else { - rStart = r1; - rEnd = r0; - } - - var inner = transformForSVG(makePolygon(rStart, a0, a1, vangles), cx, cy); - var outer = transformForSVG(makePolygon(rEnd, a0, a1, vangles), cx, cy); - return 'M' + outer.reverse().join('L') + 'M' + inner.join('L'); -} - -module.exports = { - isPtInsidePolygon: isPtInsidePolygon, - findPolygonOffset: findPolygonOffset, - findEnclosingVertexAngles: findEnclosingVertexAngles, - findIntersectionXY: findIntersectionXY, - findXYatLength: findXYatLength, - clampTiny: clampTiny, - pathPolygon: pathPolygon, - pathPolygonAnnulus: pathPolygonAnnulus -}; - -},{"../../lib":719,"../../lib/polygon":731}],831:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var getSubplotCalcData = _dereq_('../get_data').getSubplotCalcData; -var counterRegex = _dereq_('../../lib').counterRegex; - -var createPolar = _dereq_('./polar'); -var constants = _dereq_('./constants'); - -var attr = constants.attr; -var name = constants.name; -var counter = counterRegex(name); - -var attributes = {}; -attributes[attr] = { - valType: 'subplotid', - - dflt: name, - editType: 'calc', - -}; - -function plot(gd) { - var fullLayout = gd._fullLayout; - var calcData = gd.calcdata; - var subplotIds = fullLayout._subplots[name]; - - for(var i = 0; i < subplotIds.length; i++) { - var id = subplotIds[i]; - var subplotCalcData = getSubplotCalcData(calcData, name, id); - var subplot = fullLayout[id]._subplot; - - if(!subplot) { - subplot = createPolar(gd, id); - fullLayout[id]._subplot = subplot; - } - - subplot.plot(subplotCalcData, fullLayout, gd._promises); - } -} - -function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var oldIds = oldFullLayout._subplots[name] || []; - var hadGl = (oldFullLayout._has && oldFullLayout._has('gl')); - var hasGl = (newFullLayout._has && newFullLayout._has('gl')); - var mustCleanScene = hadGl && !hasGl; - - for(var i = 0; i < oldIds.length; i++) { - var id = oldIds[i]; - var oldSubplot = oldFullLayout[id]._subplot; - - if(!newFullLayout[id] && !!oldSubplot) { - oldSubplot.framework.remove(); - oldSubplot.layers['radial-axis-title'].remove(); - - for(var k in oldSubplot.clipPaths) { - oldSubplot.clipPaths[k].remove(); - } - } - - if(mustCleanScene && oldSubplot._scene) { - oldSubplot._scene.destroy(); - oldSubplot._scene = null; - } - } -} - -module.exports = { - attr: attr, - name: name, - idRoot: name, - idRegex: counter, - attrRegex: counter, - attributes: attributes, - layoutAttributes: _dereq_('./layout_attributes'), - supplyLayoutDefaults: _dereq_('./layout_defaults'), - plot: plot, - clean: clean, - toSVG: _dereq_('../cartesian').toSVG -}; - -},{"../../lib":719,"../cartesian":778,"../get_data":802,"./constants":829,"./layout_attributes":832,"./layout_defaults":833,"./polar":840}],832:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorAttrs = _dereq_('../../components/color/attributes'); -var axesAttrs = _dereq_('../cartesian/layout_attributes'); -var domainAttrs = _dereq_('../domain').attributes; -var extendFlat = _dereq_('../../lib').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var axisLineGridAttr = overrideAll({ - color: axesAttrs.color, - showline: extendFlat({}, axesAttrs.showline, {dflt: true}), - linecolor: axesAttrs.linecolor, - linewidth: axesAttrs.linewidth, - showgrid: extendFlat({}, axesAttrs.showgrid, {dflt: true}), - gridcolor: axesAttrs.gridcolor, - gridwidth: axesAttrs.gridwidth - - // TODO add spike* attributes down the road - - // should we add zeroline* attributes? - -}, 'plot', 'from-root'); - -var axisTickAttrs = overrideAll({ - tickmode: axesAttrs.tickmode, - nticks: axesAttrs.nticks, - tick0: axesAttrs.tick0, - dtick: axesAttrs.dtick, - tickvals: axesAttrs.tickvals, - ticktext: axesAttrs.ticktext, - ticks: axesAttrs.ticks, - ticklen: axesAttrs.ticklen, - tickwidth: axesAttrs.tickwidth, - tickcolor: axesAttrs.tickcolor, - showticklabels: axesAttrs.showticklabels, - showtickprefix: axesAttrs.showtickprefix, - tickprefix: axesAttrs.tickprefix, - showticksuffix: axesAttrs.showticksuffix, - ticksuffix: axesAttrs.ticksuffix, - showexponent: axesAttrs.showexponent, - exponentformat: axesAttrs.exponentformat, - separatethousands: axesAttrs.separatethousands, - tickfont: axesAttrs.tickfont, - tickangle: axesAttrs.tickangle, - tickformat: axesAttrs.tickformat, - tickformatstops: axesAttrs.tickformatstops, - layer: axesAttrs.layer -}, 'plot', 'from-root'); - -var radialAxisAttrs = { - visible: extendFlat({}, axesAttrs.visible, {dflt: true}), - type: extendFlat({}, axesAttrs.type, { - values: ['-', 'linear', 'log', 'date', 'category'] - }), - - autorange: extendFlat({}, axesAttrs.autorange, {editType: 'plot'}), - rangemode: { - valType: 'enumerated', - values: ['tozero', 'nonnegative', 'normal'], - dflt: 'tozero', - - editType: 'calc', - - }, - range: extendFlat({}, axesAttrs.range, { - items: [ - {valType: 'any', editType: 'plot', impliedEdits: {'^autorange': false}}, - {valType: 'any', editType: 'plot', impliedEdits: {'^autorange': false}} - ], - editType: 'plot' - }), - - categoryorder: axesAttrs.categoryorder, - categoryarray: axesAttrs.categoryarray, - - angle: { - valType: 'angle', - editType: 'plot', - - - }, - - side: { - valType: 'enumerated', - // TODO add 'center' for `showline: false` radial axes - values: ['clockwise', 'counterclockwise'], - dflt: 'clockwise', - editType: 'plot', - - - }, - - - title: overrideAll(axesAttrs.title, 'plot', 'from-root'), - // might need a 'titleside' and even 'titledirection' down the road - - hoverformat: axesAttrs.hoverformat, - - uirevision: { - valType: 'any', - - editType: 'none', - - }, - - editType: 'calc', - - _deprecated: { - title: axesAttrs._deprecated.title, - titlefont: axesAttrs._deprecated.titlefont - } -}; - -// radial title is not gui-editable, so it needs dflt: '', similar to carpet axes. -radialAxisAttrs.title.text.dflt = ''; - -extendFlat( - radialAxisAttrs, - - // N.B. radialaxis grid lines are circular, - // but radialaxis lines are straight from circle center to outer bound - axisLineGridAttr, - axisTickAttrs -); - -var angularAxisAttrs = { - visible: extendFlat({}, axesAttrs.visible, {dflt: true}), - type: { - valType: 'enumerated', - // 'linear' should maybe be called 'angle' or 'angular' here - // to make clear that axis here is periodic and more tightly match - // `thetaunit`? - // - // skip 'date' for first push - // no 'log' for now - values: ['-', 'linear', 'category'], - dflt: '-', - - editType: 'calc', - _noTemplating: true, - - }, - - categoryorder: axesAttrs.categoryorder, - categoryarray: axesAttrs.categoryarray, - - thetaunit: { - valType: 'enumerated', - values: ['radians', 'degrees'], - dflt: 'degrees', - - editType: 'calc', - - }, - - period: { - valType: 'number', - editType: 'calc', - min: 0, - - - // Examples for date axes: - // - // - period that equals the timeseries length - // http://flowingdata.com/2017/01/24/one-dataset-visualized-25-ways/18-polar-coordinates/ - // - and 1-year periods (focusing on seasonal change0 - // http://otexts.org/fpp2/seasonal-plots.html - // https://blogs.scientificamerican.com/sa-visual/why-are-so-many-babies-born-around-8-00-a-m/ - // http://www.seasonaladjustment.com/2012/09/05/clock-plot-visualising-seasonality-using-r-and-ggplot2-part-3/ - // https://i.pinimg.com/736x/49/b9/72/49b972ccb3206a1a6d6f870dac543280.jpg - // https://www.climate-lab-book.ac.uk/spirals/ - }, - - direction: { - valType: 'enumerated', - values: ['counterclockwise', 'clockwise'], - dflt: 'counterclockwise', - - editType: 'calc', - - }, - - rotation: { - valType: 'angle', - editType: 'calc', - - - }, - - hoverformat: axesAttrs.hoverformat, - - uirevision: { - valType: 'any', - - editType: 'none', - - }, - - editType: 'calc' -}; - -extendFlat( - angularAxisAttrs, - - // N.B. angular grid lines are straight lines from circle center to outer bound - // the angular line is circular bounding the polar plot area. - axisLineGridAttr, - - // N.B. ticksuffix defaults to '°' for angular axes with `thetaunit: 'degrees'` - axisTickAttrs -); - -module.exports = { - // TODO for x/y/zoom system for paper-based zooming: - // x: {}, - // y: {}, - // zoom: {}, - - domain: domainAttrs({name: 'polar', editType: 'plot'}), - - sector: { - valType: 'info_array', - items: [ - {valType: 'number', editType: 'plot'}, - {valType: 'number', editType: 'plot'} - ], - dflt: [0, 360], - - editType: 'plot', - - }, - hole: { - valType: 'number', - min: 0, - max: 1, - dflt: 0, - editType: 'plot', - - - }, - - bgcolor: { - valType: 'color', - - editType: 'plot', - dflt: colorAttrs.background, - - }, - - radialaxis: radialAxisAttrs, - angularaxis: angularAxisAttrs, - - gridshape: { - valType: 'enumerated', - values: ['circular', 'linear'], - dflt: 'circular', - - editType: 'plot', - - }, - - // TODO maybe? - // annotations: - - uirevision: { - valType: 'any', - - editType: 'none', - - }, - - editType: 'calc' -}; - -},{"../../components/color/attributes":592,"../../lib":719,"../../plot_api/edit_types":750,"../cartesian/layout_attributes":779,"../domain":792}],833:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); -var Template = _dereq_('../../plot_api/plot_template'); - -var handleSubplotDefaults = _dereq_('../subplot_defaults'); -var getSubplotData = _dereq_('../get_data').getSubplotData; - -var handleTickValueDefaults = _dereq_('../cartesian/tick_value_defaults'); -var handleTickMarkDefaults = _dereq_('../cartesian/tick_mark_defaults'); -var handleTickLabelDefaults = _dereq_('../cartesian/tick_label_defaults'); -var handleCategoryOrderDefaults = _dereq_('../cartesian/category_order_defaults'); -var handleLineGridDefaults = _dereq_('../cartesian/line_grid_defaults'); -var autoType = _dereq_('../cartesian/axis_autotype'); - -var layoutAttributes = _dereq_('./layout_attributes'); -var setConvert = _dereq_('./set_convert'); -var constants = _dereq_('./constants'); -var axisNames = constants.axisNames; - -function handleDefaults(contIn, contOut, coerce, opts) { - var bgColor = coerce('bgcolor'); - opts.bgColor = Color.combine(bgColor, opts.paper_bgcolor); - - var sector = coerce('sector'); - coerce('hole'); - - // could optimize, subplotData is not always needed! - var subplotData = getSubplotData(opts.fullData, constants.name, opts.id); - var layoutOut = opts.layoutOut; - var axName; - - function coerceAxis(attr, dflt) { - return coerce(axName + '.' + attr, dflt); - } - - for(var i = 0; i < axisNames.length; i++) { - axName = axisNames[i]; - - if(!Lib.isPlainObject(contIn[axName])) { - contIn[axName] = {}; - } - - var axIn = contIn[axName]; - var axOut = Template.newContainer(contOut, axName); - axOut._id = axOut._name = axName; - axOut._attr = opts.id + '.' + axName; - axOut._traceIndices = subplotData.map(function(t) { return t._expandedIndex; }); - - var dataAttr = constants.axisName2dataArray[axName]; - var axType = handleAxisTypeDefaults(axIn, axOut, coerceAxis, subplotData, dataAttr); - - handleCategoryOrderDefaults(axIn, axOut, coerceAxis, { - axData: subplotData, - dataAttr: dataAttr - }); - - var visible = coerceAxis('visible'); - setConvert(axOut, contOut, layoutOut); - - coerceAxis('uirevision', contOut.uirevision); - - var dfltColor; - var dfltFontColor; - - if(visible) { - dfltColor = coerceAxis('color'); - dfltFontColor = (dfltColor === axIn.color) ? dfltColor : opts.font.color; - } - - // We don't want to make downstream code call ax.setScale, - // as both radial and angular axes don't have a set domain. - // Furthermore, angular axes don't have a set range. - // - // Mocked domains and ranges are set by the polar subplot instances, - // but Axes.findExtremes uses the sign of _m to determine which padding value - // to use. - // - // By setting, _m to 1 here, we make Axes.findExtremes think that - // range[1] > range[0], and vice-versa for `autorange: 'reversed'` below. - axOut._m = 1; - - switch(axName) { - case 'radialaxis': - var autoRange = coerceAxis('autorange', !axOut.isValidRange(axIn.range)); - axIn.autorange = autoRange; - if(autoRange && (axType === 'linear' || axType === '-')) coerceAxis('rangemode'); - if(autoRange === 'reversed') axOut._m = -1; - - coerceAxis('range'); - axOut.cleanRange('range', {dfltRange: [0, 1]}); - - if(visible) { - coerceAxis('side'); - coerceAxis('angle', sector[0]); - - coerceAxis('title.text'); - Lib.coerceFont(coerceAxis, 'title.font', { - family: opts.font.family, - size: Math.round(opts.font.size * 1.2), - color: dfltFontColor - }); - } - break; - - case 'angularaxis': - // We do not support 'true' date angular axes yet, - // users can still plot dates on angular axes by setting - // `angularaxis.type: 'category'`. - // - // Here, if a date angular axes is detected, we make - // all its corresponding traces invisible, so that - // when we do add support for data angular axes, the new - // behavior won't conflict with existing behavior - if(axType === 'date') { - Lib.log('Polar plots do not support date angular axes yet.'); - - for(var j = 0; j < subplotData.length; j++) { - subplotData[j].visible = false; - } - - // turn this into a 'dummy' linear axis so that - // the subplot still renders ok - axType = axIn.type = axOut.type = 'linear'; - } - - if(axType === 'linear') { - coerceAxis('thetaunit'); - } else { - coerceAxis('period'); - } - - var direction = coerceAxis('direction'); - coerceAxis('rotation', {counterclockwise: 0, clockwise: 90}[direction]); - break; - } - - if(visible) { - handleTickValueDefaults(axIn, axOut, coerceAxis, axOut.type); - handleTickLabelDefaults(axIn, axOut, coerceAxis, axOut.type, { - tickSuffixDflt: axOut.thetaunit === 'degrees' ? '°' : undefined - }); - handleTickMarkDefaults(axIn, axOut, coerceAxis, {outerTicks: true}); - - var showTickLabels = coerceAxis('showticklabels'); - if(showTickLabels) { - Lib.coerceFont(coerceAxis, 'tickfont', { - family: opts.font.family, - size: opts.font.size, - color: dfltFontColor - }); - coerceAxis('tickangle'); - coerceAxis('tickformat'); - } - - handleLineGridDefaults(axIn, axOut, coerceAxis, { - dfltColor: dfltColor, - bgColor: opts.bgColor, - // default grid color is darker here (60%, vs cartesian default ~91%) - // because the grid is not square so the eye needs heavier cues to follow - blend: 60, - showLine: true, - showGrid: true, - noZeroLine: true, - attributes: layoutAttributes[axName] - }); - - coerceAxis('layer'); - } - - if(axType !== 'category') coerceAxis('hoverformat'); - - axOut._input = axIn; - } - - if(contOut.angularaxis.type === 'category') { - coerce('gridshape'); - } -} - -function handleAxisTypeDefaults(axIn, axOut, coerce, subplotData, dataAttr) { - var axType = coerce('type'); - - if(axType === '-') { - var trace; - - for(var i = 0; i < subplotData.length; i++) { - if(subplotData[i].visible) { - trace = subplotData[i]; - break; - } - } - - if(trace && trace[dataAttr]) { - axOut.type = autoType(trace[dataAttr], 'gregorian'); - } - - if(axOut.type === '-') { - axOut.type = 'linear'; - } else { - // copy autoType back to input axis - // note that if this object didn't exist - // in the input layout, we have to put it in - // this happens in the main supplyDefaults function - axIn.type = axOut.type; - } - } - - return axOut.type; -} - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - handleSubplotDefaults(layoutIn, layoutOut, fullData, { - type: constants.name, - attributes: layoutAttributes, - handleDefaults: handleDefaults, - font: layoutOut.font, - paper_bgcolor: layoutOut.paper_bgcolor, - fullData: fullData, - layoutOut: layoutOut - }); -}; - -},{"../../components/color":593,"../../lib":719,"../../plot_api/plot_template":757,"../cartesian/axis_autotype":768,"../cartesian/category_order_defaults":771,"../cartesian/line_grid_defaults":781,"../cartesian/tick_label_defaults":786,"../cartesian/tick_mark_defaults":787,"../cartesian/tick_value_defaults":788,"../get_data":802,"../subplot_defaults":842,"./constants":829,"./layout_attributes":832,"./set_convert":841}],834:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterAttrs = _dereq_('../../../traces/scatter/attributes'); -var scatterMarkerAttrs = scatterAttrs.marker; -var extendFlat = _dereq_('../../../lib/extend').extendFlat; - -var deprecationWarning = [ - 'Area traces are deprecated!', - 'Please switch to the *barpolar* trace type.' -].join(' '); - -module.exports = { - r: extendFlat({}, scatterAttrs.r, { - - }), - t: extendFlat({}, scatterAttrs.t, { - - }), - marker: { - color: extendFlat({}, scatterMarkerAttrs.color, { - - }), - size: extendFlat({}, scatterMarkerAttrs.size, { - - }), - symbol: extendFlat({}, scatterMarkerAttrs.symbol, { - - }), - opacity: extendFlat({}, scatterMarkerAttrs.opacity, { - - }), - editType: 'calc' - } -}; - -},{"../../../lib/extend":710,"../../../traces/scatter/attributes":1112}],835:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var axesAttrs = _dereq_('../../cartesian/layout_attributes'); -var extendFlat = _dereq_('../../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../../plot_api/edit_types').overrideAll; - -var deprecationWarning = [ - 'Legacy polar charts are deprecated!', - 'Please switch to *polar* subplots.' -].join(' '); - -var domainAttr = extendFlat({}, axesAttrs.domain, { - -}); - -function mergeAttrs(axisName, nonCommonAttrs) { - var commonAttrs = { - showline: { - valType: 'boolean', - - - }, - showticklabels: { - valType: 'boolean', - - - }, - tickorientation: { - valType: 'enumerated', - values: ['horizontal', 'vertical'], - - - }, - ticklen: { - valType: 'number', - min: 0, - - - }, - tickcolor: { - valType: 'color', - - - }, - ticksuffix: { - valType: 'string', - - - }, - endpadding: { - valType: 'number', - - description: deprecationWarning, - }, - visible: { - valType: 'boolean', - - - } - }; - - return extendFlat({}, nonCommonAttrs, commonAttrs); -} - -module.exports = overrideAll({ - radialaxis: mergeAttrs('radial', { - range: { - valType: 'info_array', - - items: [ - { valType: 'number' }, - { valType: 'number' } - ], - - }, - domain: domainAttr, - orientation: { - valType: 'number', - - - } - }), - - angularaxis: mergeAttrs('angular', { - range: { - valType: 'info_array', - - items: [ - { valType: 'number', dflt: 0 }, - { valType: 'number', dflt: 360 } - ], - - }, - domain: domainAttr - }), - - // attributes that appear at layout root - layout: { - direction: { - valType: 'enumerated', - values: ['clockwise', 'counterclockwise'], - - - }, - orientation: { - valType: 'angle', - - - } - } -}, 'plot', 'nested'); - -},{"../../../lib/extend":710,"../../../plot_api/edit_types":750,"../../cartesian/layout_attributes":779}],836:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Polar = module.exports = _dereq_('./micropolar'); - -Polar.manager = _dereq_('./micropolar_manager'); - -},{"./micropolar":837,"./micropolar_manager":838}],837:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -var d3 = _dereq_('d3'); -var Lib = _dereq_('../../../lib'); -var extendDeepAll = Lib.extendDeepAll; -var MID_SHIFT = _dereq_('../../../constants/alignment').MID_SHIFT; - -var µ = module.exports = { version: '0.2.2' }; - -µ.Axis = function module() { - var config = { - data: [], - layout: {} - }, inputConfig = {}, liveConfig = {}; - var svg, container, dispatch = d3.dispatch('hover'), radialScale, angularScale; - var exports = {}; - function render(_container) { - container = _container || container; - var data = config.data; - var axisConfig = config.layout; - if (typeof container == 'string' || container.nodeName) container = d3.select(container); - container.datum(data).each(function(_data, _index) { - var dataOriginal = _data.slice(); - liveConfig = { - data: µ.util.cloneJson(dataOriginal), - layout: µ.util.cloneJson(axisConfig) - }; - var colorIndex = 0; - dataOriginal.forEach(function(d, i) { - if (!d.color) { - d.color = axisConfig.defaultColorRange[colorIndex]; - colorIndex = (colorIndex + 1) % axisConfig.defaultColorRange.length; - } - if (!d.strokeColor) { - d.strokeColor = d.geometry === 'LinePlot' ? d.color : d3.rgb(d.color).darker().toString(); - } - liveConfig.data[i].color = d.color; - liveConfig.data[i].strokeColor = d.strokeColor; - liveConfig.data[i].strokeDash = d.strokeDash; - liveConfig.data[i].strokeSize = d.strokeSize; - }); - var data = dataOriginal.filter(function(d, i) { - var visible = d.visible; - return typeof visible === 'undefined' || visible === true; - }); - var isStacked = false; - var dataWithGroupId = data.map(function(d, i) { - isStacked = isStacked || typeof d.groupId !== 'undefined'; - return d; - }); - if (isStacked) { - var grouped = d3.nest().key(function(d, i) { - return typeof d.groupId != 'undefined' ? d.groupId : 'unstacked'; - }).entries(dataWithGroupId); - var dataYStack = []; - var stacked = grouped.map(function(d, i) { - if (d.key === 'unstacked') return d.values; else { - var prevArray = d.values[0].r.map(function(d, i) { - return 0; - }); - d.values.forEach(function(d, i, a) { - d.yStack = [ prevArray ]; - dataYStack.push(prevArray); - prevArray = µ.util.sumArrays(d.r, prevArray); - }); - return d.values; - } - }); - data = d3.merge(stacked); - } - data.forEach(function(d, i) { - d.t = Array.isArray(d.t[0]) ? d.t : [ d.t ]; - d.r = Array.isArray(d.r[0]) ? d.r : [ d.r ]; - }); - var radius = Math.min(axisConfig.width - axisConfig.margin.left - axisConfig.margin.right, axisConfig.height - axisConfig.margin.top - axisConfig.margin.bottom) / 2; - radius = Math.max(10, radius); - var chartCenter = [ axisConfig.margin.left + radius, axisConfig.margin.top + radius ]; - var extent; - if (isStacked) { - var highestStackedValue = d3.max(µ.util.sumArrays(µ.util.arrayLast(data).r[0], µ.util.arrayLast(dataYStack))); - extent = [ 0, highestStackedValue ]; - } else extent = d3.extent(µ.util.flattenArray(data.map(function(d, i) { - return d.r; - }))); - if (axisConfig.radialAxis.domain != µ.DATAEXTENT) extent[0] = 0; - radialScale = d3.scale.linear().domain(axisConfig.radialAxis.domain != µ.DATAEXTENT && axisConfig.radialAxis.domain ? axisConfig.radialAxis.domain : extent).range([ 0, radius ]); - liveConfig.layout.radialAxis.domain = radialScale.domain(); - var angularDataMerged = µ.util.flattenArray(data.map(function(d, i) { - return d.t; - })); - var isOrdinal = typeof angularDataMerged[0] === 'string'; - var ticks; - if (isOrdinal) { - angularDataMerged = µ.util.deduplicate(angularDataMerged); - ticks = angularDataMerged.slice(); - angularDataMerged = d3.range(angularDataMerged.length); - data = data.map(function(d, i) { - var result = d; - d.t = [ angularDataMerged ]; - if (isStacked) result.yStack = d.yStack; - return result; - }); - } - var hasOnlyLineOrDotPlot = data.filter(function(d, i) { - return d.geometry === 'LinePlot' || d.geometry === 'DotPlot'; - }).length === data.length; - var needsEndSpacing = axisConfig.needsEndSpacing === null ? isOrdinal || !hasOnlyLineOrDotPlot : axisConfig.needsEndSpacing; - var useProvidedDomain = axisConfig.angularAxis.domain && axisConfig.angularAxis.domain != µ.DATAEXTENT && !isOrdinal && axisConfig.angularAxis.domain[0] >= 0; - var angularDomain = useProvidedDomain ? axisConfig.angularAxis.domain : d3.extent(angularDataMerged); - var angularDomainStep = Math.abs(angularDataMerged[1] - angularDataMerged[0]); - if (hasOnlyLineOrDotPlot && !isOrdinal) angularDomainStep = 0; - var angularDomainWithPadding = angularDomain.slice(); - if (needsEndSpacing && isOrdinal) angularDomainWithPadding[1] += angularDomainStep; - var tickCount = axisConfig.angularAxis.ticksCount || 4; - if (tickCount > 8) tickCount = tickCount / (tickCount / 8) + tickCount % 8; - if (axisConfig.angularAxis.ticksStep) { - tickCount = (angularDomainWithPadding[1] - angularDomainWithPadding[0]) / tickCount; - } - var angularTicksStep = axisConfig.angularAxis.ticksStep || (angularDomainWithPadding[1] - angularDomainWithPadding[0]) / (tickCount * (axisConfig.minorTicks + 1)); - if (ticks) angularTicksStep = Math.max(Math.round(angularTicksStep), 1); - if (!angularDomainWithPadding[2]) angularDomainWithPadding[2] = angularTicksStep; - var angularAxisRange = d3.range.apply(this, angularDomainWithPadding); - angularAxisRange = angularAxisRange.map(function(d, i) { - return parseFloat(d.toPrecision(12)); - }); - angularScale = d3.scale.linear().domain(angularDomainWithPadding.slice(0, 2)).range(axisConfig.direction === 'clockwise' ? [ 0, 360 ] : [ 360, 0 ]); - liveConfig.layout.angularAxis.domain = angularScale.domain(); - liveConfig.layout.angularAxis.endPadding = needsEndSpacing ? angularDomainStep : 0; - svg = d3.select(this).select('svg.chart-root'); - if (typeof svg === 'undefined' || svg.empty()) { - var skeleton = "' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '"; - var doc = new DOMParser().parseFromString(skeleton, 'application/xml'); - var newSvg = this.appendChild(this.ownerDocument.importNode(doc.documentElement, true)); - svg = d3.select(newSvg); - } - svg.select('.guides-group').style({ - 'pointer-events': 'none' - }); - svg.select('.angular.axis-group').style({ - 'pointer-events': 'none' - }); - svg.select('.radial.axis-group').style({ - 'pointer-events': 'none' - }); - var chartGroup = svg.select('.chart-group'); - var lineStyle = { - fill: 'none', - stroke: axisConfig.tickColor - }; - var fontStyle = { - 'font-size': axisConfig.font.size, - 'font-family': axisConfig.font.family, - fill: axisConfig.font.color, - 'text-shadow': [ '-1px 0px', '1px -1px', '-1px 1px', '1px 1px' ].map(function(d, i) { - return ' ' + d + ' 0 ' + axisConfig.font.outlineColor; - }).join(',') - }; - var legendContainer; - if (axisConfig.showLegend) { - legendContainer = svg.select('.legend-group').attr({ - transform: 'translate(' + [ radius, axisConfig.margin.top ] + ')' - }).style({ - display: 'block' - }); - var elements = data.map(function(d, i) { - var datumClone = µ.util.cloneJson(d); - datumClone.symbol = d.geometry === 'DotPlot' ? d.dotType || 'circle' : d.geometry != 'LinePlot' ? 'square' : 'line'; - datumClone.visibleInLegend = typeof d.visibleInLegend === 'undefined' || d.visibleInLegend; - datumClone.color = d.geometry === 'LinePlot' ? d.strokeColor : d.color; - return datumClone; - }); - - µ.Legend().config({ - data: data.map(function(d, i) { - return d.name || 'Element' + i; - }), - legendConfig: extendDeepAll({}, - µ.Legend.defaultConfig().legendConfig, - { - container: legendContainer, - elements: elements, - reverseOrder: axisConfig.legend.reverseOrder - } - ) - })(); - - var legendBBox = legendContainer.node().getBBox(); - radius = Math.min(axisConfig.width - legendBBox.width - axisConfig.margin.left - axisConfig.margin.right, axisConfig.height - axisConfig.margin.top - axisConfig.margin.bottom) / 2; - radius = Math.max(10, radius); - chartCenter = [ axisConfig.margin.left + radius, axisConfig.margin.top + radius ]; - radialScale.range([ 0, radius ]); - liveConfig.layout.radialAxis.domain = radialScale.domain(); - legendContainer.attr('transform', 'translate(' + [ chartCenter[0] + radius, chartCenter[1] - radius ] + ')'); - } else { - legendContainer = svg.select('.legend-group').style({ - display: 'none' - }); - } - svg.attr({ - width: axisConfig.width, - height: axisConfig.height - }).style({ - opacity: axisConfig.opacity - }); - chartGroup.attr('transform', 'translate(' + chartCenter + ')').style({ - cursor: 'crosshair' - }); - var centeringOffset = [ (axisConfig.width - (axisConfig.margin.left + axisConfig.margin.right + radius * 2 + (legendBBox ? legendBBox.width : 0))) / 2, (axisConfig.height - (axisConfig.margin.top + axisConfig.margin.bottom + radius * 2)) / 2 ]; - centeringOffset[0] = Math.max(0, centeringOffset[0]); - centeringOffset[1] = Math.max(0, centeringOffset[1]); - svg.select('.outer-group').attr('transform', 'translate(' + centeringOffset + ')'); - if (axisConfig.title && axisConfig.title.text) { - var title = svg.select('g.title-group text').style(fontStyle).text(axisConfig.title.text); - var titleBBox = title.node().getBBox(); - title.attr({ - x: chartCenter[0] - titleBBox.width / 2, - y: chartCenter[1] - radius - 20 - }); - } - var radialAxis = svg.select('.radial.axis-group'); - if (axisConfig.radialAxis.gridLinesVisible) { - var gridCircles = radialAxis.selectAll('circle.grid-circle').data(radialScale.ticks(5)); - gridCircles.enter().append('circle').attr({ - 'class': 'grid-circle' - }).style(lineStyle); - gridCircles.attr('r', radialScale); - gridCircles.exit().remove(); - } - radialAxis.select('circle.outside-circle').attr({ - r: radius - }).style(lineStyle); - var backgroundCircle = svg.select('circle.background-circle').attr({ - r: radius - }).style({ - fill: axisConfig.backgroundColor, - stroke: axisConfig.stroke - }); - function currentAngle(d, i) { - return angularScale(d) % 360 + axisConfig.orientation; - } - if (axisConfig.radialAxis.visible) { - var axis = d3.svg.axis().scale(radialScale).ticks(5).tickSize(5); - radialAxis.call(axis).attr({ - transform: 'rotate(' + axisConfig.radialAxis.orientation + ')' - }); - radialAxis.selectAll('.domain').style(lineStyle); - radialAxis.selectAll('g>text').text(function(d, i) { - return this.textContent + axisConfig.radialAxis.ticksSuffix; - }).style(fontStyle).style({ - 'text-anchor': 'start' - }).attr({ - x: 0, - y: 0, - dx: 0, - dy: 0, - transform: function(d, i) { - if (axisConfig.radialAxis.tickOrientation === 'horizontal') { - return 'rotate(' + -axisConfig.radialAxis.orientation + ') translate(' + [ 0, fontStyle['font-size'] ] + ')'; - } else return 'translate(' + [ 0, fontStyle['font-size'] ] + ')'; - } - }); - radialAxis.selectAll('g>line').style({ - stroke: 'black' - }); - } - var angularAxis = svg.select('.angular.axis-group').selectAll('g.angular-tick').data(angularAxisRange); - var angularAxisEnter = angularAxis.enter().append('g').classed('angular-tick', true); - angularAxis.attr({ - transform: function(d, i) { - return 'rotate(' + currentAngle(d, i) + ')'; - } - }).style({ - display: axisConfig.angularAxis.visible ? 'block' : 'none' - }); - angularAxis.exit().remove(); - angularAxisEnter.append('line').classed('grid-line', true).classed('major', function(d, i) { - return i % (axisConfig.minorTicks + 1) == 0; - }).classed('minor', function(d, i) { - return !(i % (axisConfig.minorTicks + 1) == 0); - }).style(lineStyle); - angularAxisEnter.selectAll('.minor').style({ - stroke: axisConfig.minorTickColor - }); - angularAxis.select('line.grid-line').attr({ - x1: axisConfig.tickLength ? radius - axisConfig.tickLength : 0, - x2: radius - }).style({ - display: axisConfig.angularAxis.gridLinesVisible ? 'block' : 'none' - }); - angularAxisEnter.append('text').classed('axis-text', true).style(fontStyle); - var ticksText = angularAxis.select('text.axis-text').attr({ - x: radius + axisConfig.labelOffset, - dy: MID_SHIFT + 'em', - transform: function(d, i) { - var angle = currentAngle(d, i); - var rad = radius + axisConfig.labelOffset; - var orient = axisConfig.angularAxis.tickOrientation; - if (orient == 'horizontal') return 'rotate(' + -angle + ' ' + rad + ' 0)'; else if (orient == 'radial') return angle < 270 && angle > 90 ? 'rotate(180 ' + rad + ' 0)' : null; else return 'rotate(' + (angle <= 180 && angle > 0 ? -90 : 90) + ' ' + rad + ' 0)'; - } - }).style({ - 'text-anchor': 'middle', - display: axisConfig.angularAxis.labelsVisible ? 'block' : 'none' - }).text(function(d, i) { - if (i % (axisConfig.minorTicks + 1) != 0) return ''; - if (ticks) { - return ticks[d] + axisConfig.angularAxis.ticksSuffix; - } else return d + axisConfig.angularAxis.ticksSuffix; - }).style(fontStyle); - if (axisConfig.angularAxis.rewriteTicks) ticksText.text(function(d, i) { - if (i % (axisConfig.minorTicks + 1) != 0) return ''; - return axisConfig.angularAxis.rewriteTicks(this.textContent, i); - }); - var rightmostTickEndX = d3.max(chartGroup.selectAll('.angular-tick text')[0].map(function(d, i) { - return d.getCTM().e + d.getBBox().width; - })); - legendContainer.attr({ - transform: 'translate(' + [ radius + rightmostTickEndX, axisConfig.margin.top ] + ')' - }); - var hasGeometry = svg.select('g.geometry-group').selectAll('g').size() > 0; - var geometryContainer = svg.select('g.geometry-group').selectAll('g.geometry').data(data); - geometryContainer.enter().append('g').attr({ - 'class': function(d, i) { - return 'geometry geometry' + i; - } - }); - geometryContainer.exit().remove(); - if (data[0] || hasGeometry) { - var geometryConfigs = []; - data.forEach(function(d, i) { - var geometryConfig = {}; - geometryConfig.radialScale = radialScale; - geometryConfig.angularScale = angularScale; - geometryConfig.container = geometryContainer.filter(function(dB, iB) { - return iB == i; - }); - geometryConfig.geometry = d.geometry; - geometryConfig.orientation = axisConfig.orientation; - geometryConfig.direction = axisConfig.direction; - geometryConfig.index = i; - geometryConfigs.push({ - data: d, - geometryConfig: geometryConfig - }); - }); - var geometryConfigsGrouped = d3.nest().key(function(d, i) { - return typeof d.data.groupId != 'undefined' || 'unstacked'; - }).entries(geometryConfigs); - var geometryConfigsGrouped2 = []; - geometryConfigsGrouped.forEach(function(d, i) { - if (d.key === 'unstacked') geometryConfigsGrouped2 = geometryConfigsGrouped2.concat(d.values.map(function(d, i) { - return [ d ]; - })); else geometryConfigsGrouped2.push(d.values); - }); - geometryConfigsGrouped2.forEach(function(d, i) { - var geometry; - if (Array.isArray(d)) geometry = d[0].geometryConfig.geometry; else geometry = d.geometryConfig.geometry; - var finalGeometryConfig = d.map(function(dB, iB) { - return extendDeepAll(µ[geometry].defaultConfig(), dB); - }); - µ[geometry]().config(finalGeometryConfig)(); - }); - } - var guides = svg.select('.guides-group'); - var tooltipContainer = svg.select('.tooltips-group'); - var angularTooltip = µ.tooltipPanel().config({ - container: tooltipContainer, - fontSize: 8 - })(); - var radialTooltip = µ.tooltipPanel().config({ - container: tooltipContainer, - fontSize: 8 - })(); - var geometryTooltip = µ.tooltipPanel().config({ - container: tooltipContainer, - hasTick: true - })(); - var angularValue, radialValue; - if (!isOrdinal) { - var angularGuideLine = guides.select('line').attr({ - x1: 0, - y1: 0, - y2: 0 - }).style({ - stroke: 'grey', - 'pointer-events': 'none' - }); - chartGroup.on('mousemove.angular-guide', function(d, i) { - var mouseAngle = µ.util.getMousePos(backgroundCircle).angle; - angularGuideLine.attr({ - x2: -radius, - transform: 'rotate(' + mouseAngle + ')' - }).style({ - opacity: .5 - }); - var angleWithOriginOffset = (mouseAngle + 180 + 360 - axisConfig.orientation) % 360; - angularValue = angularScale.invert(angleWithOriginOffset); - var pos = µ.util.convertToCartesian(radius + 12, mouseAngle + 180); - angularTooltip.text(µ.util.round(angularValue)).move([ pos[0] + chartCenter[0], pos[1] + chartCenter[1] ]); - }).on('mouseout.angular-guide', function(d, i) { - guides.select('line').style({ - opacity: 0 - }); - }); - } - var angularGuideCircle = guides.select('circle').style({ - stroke: 'grey', - fill: 'none' - }); - chartGroup.on('mousemove.radial-guide', function(d, i) { - var r = µ.util.getMousePos(backgroundCircle).radius; - angularGuideCircle.attr({ - r: r - }).style({ - opacity: .5 - }); - radialValue = radialScale.invert(µ.util.getMousePos(backgroundCircle).radius); - var pos = µ.util.convertToCartesian(r, axisConfig.radialAxis.orientation); - radialTooltip.text(µ.util.round(radialValue)).move([ pos[0] + chartCenter[0], pos[1] + chartCenter[1] ]); - }).on('mouseout.radial-guide', function(d, i) { - angularGuideCircle.style({ - opacity: 0 - }); - geometryTooltip.hide(); - angularTooltip.hide(); - radialTooltip.hide(); - }); - svg.selectAll('.geometry-group .mark').on('mouseover.tooltip', function(d, i) { - var el = d3.select(this); - var color = this.style.fill; - var newColor = 'black'; - var opacity = this.style.opacity || 1; - el.attr({ - 'data-opacity': opacity - }); - if (color && color !== 'none') { - el.attr({ - 'data-fill': color - }); - newColor = d3.hsl(color).darker().toString(); - el.style({ - fill: newColor, - opacity: 1 - }); - var textData = { - t: µ.util.round(d[0]), - r: µ.util.round(d[1]) - }; - if (isOrdinal) textData.t = ticks[d[0]]; - var text = 't: ' + textData.t + ', r: ' + textData.r; - var bbox = this.getBoundingClientRect(); - var svgBBox = svg.node().getBoundingClientRect(); - var pos = [ bbox.left + bbox.width / 2 - centeringOffset[0] - svgBBox.left, bbox.top + bbox.height / 2 - centeringOffset[1] - svgBBox.top ]; - geometryTooltip.config({ - color: newColor - }).text(text); - geometryTooltip.move(pos); - } else { - color = this.style.stroke || 'black'; - el.attr({ - 'data-stroke': color - }); - newColor = d3.hsl(color).darker().toString(); - el.style({ - stroke: newColor, - opacity: 1 - }); - } - }).on('mousemove.tooltip', function(d, i) { - if (d3.event.which != 0) return false; - if (d3.select(this).attr('data-fill')) geometryTooltip.show(); - }).on('mouseout.tooltip', function(d, i) { - geometryTooltip.hide(); - var el = d3.select(this); - var fillColor = el.attr('data-fill'); - if (fillColor) el.style({ - fill: fillColor, - opacity: el.attr('data-opacity') - }); else el.style({ - stroke: el.attr('data-stroke'), - opacity: el.attr('data-opacity') - }); - }); - }); - return exports; - } - exports.render = function(_container) { - render(_container); - return this; - }; - exports.config = function(_x) { - if (!arguments.length) return config; - var xClone = µ.util.cloneJson(_x); - xClone.data.forEach(function(d, i) { - if (!config.data[i]) config.data[i] = {}; - extendDeepAll(config.data[i], µ.Axis.defaultConfig().data[0]); - extendDeepAll(config.data[i], d); - }); - extendDeepAll(config.layout, µ.Axis.defaultConfig().layout); - extendDeepAll(config.layout, xClone.layout); - return this; - }; - exports.getLiveConfig = function() { - return liveConfig; - }; - exports.getinputConfig = function() { - return inputConfig; - }; - exports.radialScale = function(_x) { - return radialScale; - }; - exports.angularScale = function(_x) { - return angularScale; - }; - exports.svg = function() { - return svg; - }; - d3.rebind(exports, dispatch, 'on'); - return exports; -}; - -µ.Axis.defaultConfig = function(d, i) { - var config = { - data: [ { - t: [ 1, 2, 3, 4 ], - r: [ 10, 11, 12, 13 ], - name: 'Line1', - geometry: 'LinePlot', - color: null, - strokeDash: 'solid', - strokeColor: null, - strokeSize: '1', - visibleInLegend: true, - opacity: 1 - } ], - layout: { - defaultColorRange: d3.scale.category10().range(), - title: null, - height: 450, - width: 500, - margin: { - top: 40, - right: 40, - bottom: 40, - left: 40 - }, - font: { - size: 12, - color: 'gray', - outlineColor: 'white', - family: 'Tahoma, sans-serif' - }, - direction: 'clockwise', - orientation: 0, - labelOffset: 10, - radialAxis: { - domain: null, - orientation: -45, - ticksSuffix: '', - visible: true, - gridLinesVisible: true, - tickOrientation: 'horizontal', - rewriteTicks: null - }, - angularAxis: { - domain: [ 0, 360 ], - ticksSuffix: '', - visible: true, - gridLinesVisible: true, - labelsVisible: true, - tickOrientation: 'horizontal', - rewriteTicks: null, - ticksCount: null, - ticksStep: null - }, - minorTicks: 0, - tickLength: null, - tickColor: 'silver', - minorTickColor: '#eee', - backgroundColor: 'none', - needsEndSpacing: null, - showLegend: true, - legend: { - reverseOrder: false - }, - opacity: 1 - } - }; - return config; -}; - -µ.util = {}; - -µ.DATAEXTENT = 'dataExtent'; - -µ.AREA = 'AreaChart'; - -µ.LINE = 'LinePlot'; - -µ.DOT = 'DotPlot'; - -µ.BAR = 'BarChart'; - -µ.util._override = function(_objA, _objB) { - for (var x in _objA) if (x in _objB) _objB[x] = _objA[x]; -}; - -µ.util._extend = function(_objA, _objB) { - for (var x in _objA) _objB[x] = _objA[x]; -}; - -µ.util._rndSnd = function() { - return Math.random() * 2 - 1 + (Math.random() * 2 - 1) + (Math.random() * 2 - 1); -}; - -µ.util.dataFromEquation2 = function(_equation, _step) { - var step = _step || 6; - var data = d3.range(0, 360 + step, step).map(function(deg, index) { - var theta = deg * Math.PI / 180; - var radius = _equation(theta); - return [ deg, radius ]; - }); - return data; -}; - -µ.util.dataFromEquation = function(_equation, _step, _name) { - var step = _step || 6; - var t = [], r = []; - d3.range(0, 360 + step, step).forEach(function(deg, index) { - var theta = deg * Math.PI / 180; - var radius = _equation(theta); - t.push(deg); - r.push(radius); - }); - var result = { - t: t, - r: r - }; - if (_name) result.name = _name; - return result; -}; - -µ.util.ensureArray = function(_val, _count) { - if (typeof _val === 'undefined') return null; - var arr = [].concat(_val); - return d3.range(_count).map(function(d, i) { - return arr[i] || arr[0]; - }); -}; - -µ.util.fillArrays = function(_obj, _valueNames, _count) { - _valueNames.forEach(function(d, i) { - _obj[d] = µ.util.ensureArray(_obj[d], _count); - }); - return _obj; -}; - -µ.util.cloneJson = function(json) { - return JSON.parse(JSON.stringify(json)); -}; - -µ.util.validateKeys = function(obj, keys) { - if (typeof keys === 'string') keys = keys.split('.'); - var next = keys.shift(); - return obj[next] && (!keys.length || objHasKeys(obj[next], keys)); -}; - -µ.util.sumArrays = function(a, b) { - return d3.zip(a, b).map(function(d, i) { - return d3.sum(d); - }); -}; - -µ.util.arrayLast = function(a) { - return a[a.length - 1]; -}; - -µ.util.arrayEqual = function(a, b) { - var i = Math.max(a.length, b.length, 1); - while (i-- >= 0 && a[i] === b[i]) ; - return i === -2; -}; - -µ.util.flattenArray = function(arr) { - var r = []; - while (!µ.util.arrayEqual(r, arr)) { - r = arr; - arr = [].concat.apply([], arr); - } - return arr; -}; - -µ.util.deduplicate = function(arr) { - return arr.filter(function(v, i, a) { - return a.indexOf(v) == i; - }); -}; - -µ.util.convertToCartesian = function(radius, theta) { - var thetaRadians = theta * Math.PI / 180; - var x = radius * Math.cos(thetaRadians); - var y = radius * Math.sin(thetaRadians); - return [ x, y ]; -}; - -µ.util.round = function(_value, _digits) { - var digits = _digits || 2; - var mult = Math.pow(10, digits); - return Math.round(_value * mult) / mult; -}; - -µ.util.getMousePos = function(_referenceElement) { - var mousePos = d3.mouse(_referenceElement.node()); - var mouseX = mousePos[0]; - var mouseY = mousePos[1]; - var mouse = {}; - mouse.x = mouseX; - mouse.y = mouseY; - mouse.pos = mousePos; - mouse.angle = (Math.atan2(mouseY, mouseX) + Math.PI) * 180 / Math.PI; - mouse.radius = Math.sqrt(mouseX * mouseX + mouseY * mouseY); - return mouse; -}; - -µ.util.duplicatesCount = function(arr) { - var uniques = {}, val; - var dups = {}; - for (var i = 0, len = arr.length; i < len; i++) { - val = arr[i]; - if (val in uniques) { - uniques[val]++; - dups[val] = uniques[val]; - } else { - uniques[val] = 1; - } - } - return dups; -}; - -µ.util.duplicates = function(arr) { - return Object.keys(µ.util.duplicatesCount(arr)); -}; - -µ.util.translator = function(obj, sourceBranch, targetBranch, reverse) { - if (reverse) { - var targetBranchCopy = targetBranch.slice(); - targetBranch = sourceBranch; - sourceBranch = targetBranchCopy; - } - var value = sourceBranch.reduce(function(previousValue, currentValue) { - if (typeof previousValue != 'undefined') return previousValue[currentValue]; - }, obj); - if (typeof value === 'undefined') return; - sourceBranch.reduce(function(previousValue, currentValue, index) { - if (typeof previousValue == 'undefined') return; - if (index === sourceBranch.length - 1) delete previousValue[currentValue]; - return previousValue[currentValue]; - }, obj); - targetBranch.reduce(function(previousValue, currentValue, index) { - if (typeof previousValue[currentValue] === 'undefined') previousValue[currentValue] = {}; - if (index === targetBranch.length - 1) previousValue[currentValue] = value; - return previousValue[currentValue]; - }, obj); -}; - -µ.PolyChart = function module() { - var config = [ µ.PolyChart.defaultConfig() ]; - var dispatch = d3.dispatch('hover'); - var dashArray = { - solid: 'none', - dash: [ 5, 2 ], - dot: [ 2, 5 ] - }; - var colorScale; - function exports() { - var geometryConfig = config[0].geometryConfig; - var container = geometryConfig.container; - if (typeof container == 'string') container = d3.select(container); - container.datum(config).each(function(_config, _index) { - var isStack = !!_config[0].data.yStack; - var data = _config.map(function(d, i) { - if (isStack) return d3.zip(d.data.t[0], d.data.r[0], d.data.yStack[0]); else return d3.zip(d.data.t[0], d.data.r[0]); - }); - var angularScale = geometryConfig.angularScale; - var domainMin = geometryConfig.radialScale.domain()[0]; - var generator = {}; - generator.bar = function(d, i, pI) { - var dataConfig = _config[pI].data; - var h = geometryConfig.radialScale(d[1]) - geometryConfig.radialScale(0); - var stackTop = geometryConfig.radialScale(d[2] || 0); - var w = dataConfig.barWidth; - d3.select(this).attr({ - 'class': 'mark bar', - d: 'M' + [ [ h + stackTop, -w / 2 ], [ h + stackTop, w / 2 ], [ stackTop, w / 2 ], [ stackTop, -w / 2 ] ].join('L') + 'Z', - transform: function(d, i) { - return 'rotate(' + (geometryConfig.orientation + angularScale(d[0])) + ')'; - } - }); - }; - generator.dot = function(d, i, pI) { - var stackedData = d[2] ? [ d[0], d[1] + d[2] ] : d; - var symbol = d3.svg.symbol().size(_config[pI].data.dotSize).type(_config[pI].data.dotType)(d, i); - d3.select(this).attr({ - 'class': 'mark dot', - d: symbol, - transform: function(d, i) { - var coord = convertToCartesian(getPolarCoordinates(stackedData)); - return 'translate(' + [ coord.x, coord.y ] + ')'; - } - }); - }; - var line = d3.svg.line.radial().interpolate(_config[0].data.lineInterpolation).radius(function(d) { - return geometryConfig.radialScale(d[1]); - }).angle(function(d) { - return geometryConfig.angularScale(d[0]) * Math.PI / 180; - }); - generator.line = function(d, i, pI) { - var lineData = d[2] ? data[pI].map(function(d, i) { - return [ d[0], d[1] + d[2] ]; - }) : data[pI]; - d3.select(this).each(generator['dot']).style({ - opacity: function(dB, iB) { - return +_config[pI].data.dotVisible; - }, - fill: markStyle.stroke(d, i, pI) - }).attr({ - 'class': 'mark dot' - }); - if (i > 0) return; - var lineSelection = d3.select(this.parentNode).selectAll('path.line').data([ 0 ]); - lineSelection.enter().insert('path'); - lineSelection.attr({ - 'class': 'line', - d: line(lineData), - transform: function(dB, iB) { - return 'rotate(' + (geometryConfig.orientation + 90) + ')'; - }, - 'pointer-events': 'none' - }).style({ - fill: function(dB, iB) { - return markStyle.fill(d, i, pI); - }, - 'fill-opacity': 0, - stroke: function(dB, iB) { - return markStyle.stroke(d, i, pI); - }, - 'stroke-width': function(dB, iB) { - return markStyle['stroke-width'](d, i, pI); - }, - 'stroke-dasharray': function(dB, iB) { - return markStyle['stroke-dasharray'](d, i, pI); - }, - opacity: function(dB, iB) { - return markStyle.opacity(d, i, pI); - }, - display: function(dB, iB) { - return markStyle.display(d, i, pI); - } - }); - }; - var angularRange = geometryConfig.angularScale.range(); - var triangleAngle = Math.abs(angularRange[1] - angularRange[0]) / data[0].length * Math.PI / 180; - var arc = d3.svg.arc().startAngle(function(d) { - return -triangleAngle / 2; - }).endAngle(function(d) { - return triangleAngle / 2; - }).innerRadius(function(d) { - return geometryConfig.radialScale(domainMin + (d[2] || 0)); - }).outerRadius(function(d) { - return geometryConfig.radialScale(domainMin + (d[2] || 0)) + geometryConfig.radialScale(d[1]); - }); - generator.arc = function(d, i, pI) { - d3.select(this).attr({ - 'class': 'mark arc', - d: arc, - transform: function(d, i) { - return 'rotate(' + (geometryConfig.orientation + angularScale(d[0]) + 90) + ')'; - } - }); - }; - var markStyle = { - fill: function(d, i, pI) { - return _config[pI].data.color; - }, - stroke: function(d, i, pI) { - return _config[pI].data.strokeColor; - }, - 'stroke-width': function(d, i, pI) { - return _config[pI].data.strokeSize + 'px'; - }, - 'stroke-dasharray': function(d, i, pI) { - return dashArray[_config[pI].data.strokeDash]; - }, - opacity: function(d, i, pI) { - return _config[pI].data.opacity; - }, - display: function(d, i, pI) { - return typeof _config[pI].data.visible === 'undefined' || _config[pI].data.visible ? 'block' : 'none'; - } - }; - var geometryLayer = d3.select(this).selectAll('g.layer').data(data); - geometryLayer.enter().append('g').attr({ - 'class': 'layer' - }); - var geometry = geometryLayer.selectAll('path.mark').data(function(d, i) { - return d; - }); - geometry.enter().append('path').attr({ - 'class': 'mark' - }); - geometry.style(markStyle).each(generator[geometryConfig.geometryType]); - geometry.exit().remove(); - geometryLayer.exit().remove(); - function getPolarCoordinates(d, i) { - var r = geometryConfig.radialScale(d[1]); - var t = (geometryConfig.angularScale(d[0]) + geometryConfig.orientation) * Math.PI / 180; - return { - r: r, - t: t - }; - } - function convertToCartesian(polarCoordinates) { - var x = polarCoordinates.r * Math.cos(polarCoordinates.t); - var y = polarCoordinates.r * Math.sin(polarCoordinates.t); - return { - x: x, - y: y - }; - } - }); - } - exports.config = function(_x) { - if (!arguments.length) return config; - _x.forEach(function(d, i) { - if (!config[i]) config[i] = {}; - extendDeepAll(config[i], µ.PolyChart.defaultConfig()); - extendDeepAll(config[i], d); - }); - return this; - }; - exports.getColorScale = function() { - return colorScale; - }; - d3.rebind(exports, dispatch, 'on'); - return exports; -}; - -µ.PolyChart.defaultConfig = function() { - var config = { - data: { - name: 'geom1', - t: [ [ 1, 2, 3, 4 ] ], - r: [ [ 1, 2, 3, 4 ] ], - dotType: 'circle', - dotSize: 64, - dotVisible: false, - barWidth: 20, - color: '#ffa500', - strokeSize: 1, - strokeColor: 'silver', - strokeDash: 'solid', - opacity: 1, - index: 0, - visible: true, - visibleInLegend: true - }, - geometryConfig: { - geometry: 'LinePlot', - geometryType: 'arc', - direction: 'clockwise', - orientation: 0, - container: 'body', - radialScale: null, - angularScale: null, - colorScale: d3.scale.category20() - } - }; - return config; -}; - -µ.BarChart = function module() { - return µ.PolyChart(); -}; - -µ.BarChart.defaultConfig = function() { - var config = { - geometryConfig: { - geometryType: 'bar' - } - }; - return config; -}; - -µ.AreaChart = function module() { - return µ.PolyChart(); -}; - -µ.AreaChart.defaultConfig = function() { - var config = { - geometryConfig: { - geometryType: 'arc' - } - }; - return config; -}; - -µ.DotPlot = function module() { - return µ.PolyChart(); -}; - -µ.DotPlot.defaultConfig = function() { - var config = { - geometryConfig: { - geometryType: 'dot', - dotType: 'circle' - } - }; - return config; -}; - -µ.LinePlot = function module() { - return µ.PolyChart(); -}; - -µ.LinePlot.defaultConfig = function() { - var config = { - geometryConfig: { - geometryType: 'line' - } - }; - return config; -}; - -µ.Legend = function module() { - var config = µ.Legend.defaultConfig(); - var dispatch = d3.dispatch('hover'); - function exports() { - var legendConfig = config.legendConfig; - var flattenData = config.data.map(function(d, i) { - return [].concat(d).map(function(dB, iB) { - var element = extendDeepAll({}, legendConfig.elements[i]); - element.name = dB; - element.color = [].concat(legendConfig.elements[i].color)[iB]; - return element; - }); - }); - var data = d3.merge(flattenData); - data = data.filter(function(d, i) { - return legendConfig.elements[i] && (legendConfig.elements[i].visibleInLegend || typeof legendConfig.elements[i].visibleInLegend === 'undefined'); - }); - if (legendConfig.reverseOrder) data = data.reverse(); - var container = legendConfig.container; - if (typeof container == 'string' || container.nodeName) container = d3.select(container); - var colors = data.map(function(d, i) { - return d.color; - }); - var lineHeight = legendConfig.fontSize; - var isContinuous = legendConfig.isContinuous == null ? typeof data[0] === 'number' : legendConfig.isContinuous; - var height = isContinuous ? legendConfig.height : lineHeight * data.length; - var legendContainerGroup = container.classed('legend-group', true); - var svg = legendContainerGroup.selectAll('svg').data([ 0 ]); - var svgEnter = svg.enter().append('svg').attr({ - width: 300, - height: height + lineHeight, - xmlns: 'http://www.w3.org/2000/svg', - 'xmlns:xlink': 'http://www.w3.org/1999/xlink', - version: '1.1' - }); - svgEnter.append('g').classed('legend-axis', true); - svgEnter.append('g').classed('legend-marks', true); - var dataNumbered = d3.range(data.length); - var colorScale = d3.scale[isContinuous ? 'linear' : 'ordinal']().domain(dataNumbered).range(colors); - var dataScale = d3.scale[isContinuous ? 'linear' : 'ordinal']().domain(dataNumbered)[isContinuous ? 'range' : 'rangePoints']([ 0, height ]); - var shapeGenerator = function(_type, _size) { - var squareSize = _size * 3; - if (_type === 'line') { - return 'M' + [ [ -_size / 2, -_size / 12 ], [ _size / 2, -_size / 12 ], [ _size / 2, _size / 12 ], [ -_size / 2, _size / 12 ] ] + 'Z'; - } else if (d3.svg.symbolTypes.indexOf(_type) != -1) return d3.svg.symbol().type(_type).size(squareSize)(); else return d3.svg.symbol().type('square').size(squareSize)(); - }; - if (isContinuous) { - var gradient = svg.select('.legend-marks').append('defs').append('linearGradient').attr({ - id: 'grad1', - x1: '0%', - y1: '0%', - x2: '0%', - y2: '100%' - }).selectAll('stop').data(colors); - gradient.enter().append('stop'); - gradient.attr({ - offset: function(d, i) { - return i / (colors.length - 1) * 100 + '%'; - } - }).style({ - 'stop-color': function(d, i) { - return d; - } - }); - svg.append('rect').classed('legend-mark', true).attr({ - height: legendConfig.height, - width: legendConfig.colorBandWidth, - fill: 'url(#grad1)' - }); - } else { - var legendElement = svg.select('.legend-marks').selectAll('path.legend-mark').data(data); - legendElement.enter().append('path').classed('legend-mark', true); - legendElement.attr({ - transform: function(d, i) { - return 'translate(' + [ lineHeight / 2, dataScale(i) + lineHeight / 2 ] + ')'; - }, - d: function(d, i) { - var symbolType = d.symbol; - return shapeGenerator(symbolType, lineHeight); - }, - fill: function(d, i) { - return colorScale(i); - } - }); - legendElement.exit().remove(); - } - var legendAxis = d3.svg.axis().scale(dataScale).orient('right'); - var axis = svg.select('g.legend-axis').attr({ - transform: 'translate(' + [ isContinuous ? legendConfig.colorBandWidth : lineHeight, lineHeight / 2 ] + ')' - }).call(legendAxis); - axis.selectAll('.domain').style({ - fill: 'none', - stroke: 'none' - }); - axis.selectAll('line').style({ - fill: 'none', - stroke: isContinuous ? legendConfig.textColor : 'none' - }); - axis.selectAll('text').style({ - fill: legendConfig.textColor, - 'font-size': legendConfig.fontSize - }).text(function(d, i) { - return data[i].name; - }); - return exports; - } - exports.config = function(_x) { - if (!arguments.length) return config; - extendDeepAll(config, _x); - return this; - }; - d3.rebind(exports, dispatch, 'on'); - return exports; -}; - -µ.Legend.defaultConfig = function(d, i) { - var config = { - data: [ 'a', 'b', 'c' ], - legendConfig: { - elements: [ { - symbol: 'line', - color: 'red' - }, { - symbol: 'square', - color: 'yellow' - }, { - symbol: 'diamond', - color: 'limegreen' - } ], - height: 150, - colorBandWidth: 30, - fontSize: 12, - container: 'body', - isContinuous: null, - textColor: 'grey', - reverseOrder: false - } - }; - return config; -}; - -µ.tooltipPanel = function() { - var tooltipEl, tooltipTextEl, backgroundEl; - var config = { - container: null, - hasTick: false, - fontSize: 12, - color: 'white', - padding: 5 - }; - var id = 'tooltip-' + µ.tooltipPanel.uid++; - var tickSize = 10; - var exports = function() { - tooltipEl = config.container.selectAll('g.' + id).data([ 0 ]); - var tooltipEnter = tooltipEl.enter().append('g').classed(id, true).style({ - 'pointer-events': 'none', - display: 'none' - }); - backgroundEl = tooltipEnter.append('path').style({ - fill: 'white', - 'fill-opacity': .9 - }).attr({ - d: 'M0 0' - }); - tooltipTextEl = tooltipEnter.append('text').attr({ - dx: config.padding + tickSize, - dy: +config.fontSize * .3 - }); - return exports; - }; - exports.text = function(_text) { - var l = d3.hsl(config.color).l; - var strokeColor = l >= .5 ? '#aaa' : 'white'; - var fillColor = l >= .5 ? 'black' : 'white'; - var text = _text || ''; - tooltipTextEl.style({ - fill: fillColor, - 'font-size': config.fontSize + 'px' - }).text(text); - var padding = config.padding; - var bbox = tooltipTextEl.node().getBBox(); - var boxStyle = { - fill: config.color, - stroke: strokeColor, - 'stroke-width': '2px' - }; - var backGroundW = bbox.width + padding * 2 + tickSize; - var backGroundH = bbox.height + padding * 2; - backgroundEl.attr({ - d: 'M' + [ [ tickSize, -backGroundH / 2 ], [ tickSize, -backGroundH / 4 ], [ config.hasTick ? 0 : tickSize, 0 ], [ tickSize, backGroundH / 4 ], [ tickSize, backGroundH / 2 ], [ backGroundW, backGroundH / 2 ], [ backGroundW, -backGroundH / 2 ] ].join('L') + 'Z' - }).style(boxStyle); - tooltipEl.attr({ - transform: 'translate(' + [ tickSize, -backGroundH / 2 + padding * 2 ] + ')' - }); - tooltipEl.style({ - display: 'block' - }); - return exports; - }; - exports.move = function(_pos) { - if (!tooltipEl) return; - tooltipEl.attr({ - transform: 'translate(' + [ _pos[0], _pos[1] ] + ')' - }).style({ - display: 'block' - }); - return exports; - }; - exports.hide = function() { - if (!tooltipEl) return; - tooltipEl.style({ - display: 'none' - }); - return exports; - }; - exports.show = function() { - if (!tooltipEl) return; - tooltipEl.style({ - display: 'block' - }); - return exports; - }; - exports.config = function(_x) { - extendDeepAll(config, _x); - return exports; - }; - return exports; -}; - -µ.tooltipPanel.uid = 1; - -µ.adapter = {}; - -µ.adapter.plotly = function module() { - var exports = {}; - exports.convert = function(_inputConfig, reverse) { - var outputConfig = {}; - if (_inputConfig.data) { - outputConfig.data = _inputConfig.data.map(function(d, i) { - var r = extendDeepAll({}, d); - var toTranslate = [ - [ r, [ 'marker', 'color' ], [ 'color' ] ], - [ r, [ 'marker', 'opacity' ], [ 'opacity' ] ], - [ r, [ 'marker', 'line', 'color' ], [ 'strokeColor' ] ], - [ r, [ 'marker', 'line', 'dash' ], [ 'strokeDash' ] ], - [ r, [ 'marker', 'line', 'width' ], [ 'strokeSize' ] ], - [ r, [ 'marker', 'symbol' ], [ 'dotType' ] ], - [ r, [ 'marker', 'size' ], [ 'dotSize' ] ], - [ r, [ 'marker', 'barWidth' ], [ 'barWidth' ] ], - [ r, [ 'line', 'interpolation' ], [ 'lineInterpolation' ] ], - [ r, [ 'showlegend' ], [ 'visibleInLegend' ] ] - ]; - toTranslate.forEach(function(d, i) { - µ.util.translator.apply(null, d.concat(reverse)); - }); - - if (!reverse) delete r.marker; - if (reverse) delete r.groupId; - if (!reverse) { - if (r.type === 'scatter') { - if (r.mode === 'lines') r.geometry = 'LinePlot'; else if (r.mode === 'markers') r.geometry = 'DotPlot'; else if (r.mode === 'lines+markers') { - r.geometry = 'LinePlot'; - r.dotVisible = true; - } - } else if (r.type === 'area') r.geometry = 'AreaChart'; else if (r.type === 'bar') r.geometry = 'BarChart'; - delete r.mode; - delete r.type; - } else { - if (r.geometry === 'LinePlot') { - r.type = 'scatter'; - if (r.dotVisible === true) { - delete r.dotVisible; - r.mode = 'lines+markers'; - } else r.mode = 'lines'; - } else if (r.geometry === 'DotPlot') { - r.type = 'scatter'; - r.mode = 'markers'; - } else if (r.geometry === 'AreaChart') r.type = 'area'; else if (r.geometry === 'BarChart') r.type = 'bar'; - delete r.geometry; - } - return r; - }); - if (!reverse && _inputConfig.layout && _inputConfig.layout.barmode === 'stack') { - var duplicates = µ.util.duplicates(outputConfig.data.map(function(d, i) { - return d.geometry; - })); - outputConfig.data.forEach(function(d, i) { - var idx = duplicates.indexOf(d.geometry); - if (idx != -1) outputConfig.data[i].groupId = idx; - }); - } - } - if (_inputConfig.layout) { - var r = extendDeepAll({}, _inputConfig.layout); - var toTranslate = [ - [ r, [ 'plot_bgcolor' ], [ 'backgroundColor' ] ], - [ r, [ 'showlegend' ], [ 'showLegend' ] ], - [ r, [ 'radialaxis' ], [ 'radialAxis' ] ], - [ r, [ 'angularaxis' ], [ 'angularAxis' ] ], - [ r.angularaxis, [ 'showline' ], [ 'gridLinesVisible' ] ], - [ r.angularaxis, [ 'showticklabels' ], [ 'labelsVisible' ] ], - [ r.angularaxis, [ 'nticks' ], [ 'ticksCount' ] ], - [ r.angularaxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], - [ r.angularaxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], - [ r.angularaxis, [ 'range' ], [ 'domain' ] ], - [ r.angularaxis, [ 'endpadding' ], [ 'endPadding' ] ], - [ r.radialaxis, [ 'showline' ], [ 'gridLinesVisible' ] ], - [ r.radialaxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], - [ r.radialaxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], - [ r.radialaxis, [ 'range' ], [ 'domain' ] ], - [ r.angularAxis, [ 'showline' ], [ 'gridLinesVisible' ] ], - [ r.angularAxis, [ 'showticklabels' ], [ 'labelsVisible' ] ], - [ r.angularAxis, [ 'nticks' ], [ 'ticksCount' ] ], - [ r.angularAxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], - [ r.angularAxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], - [ r.angularAxis, [ 'range' ], [ 'domain' ] ], - [ r.angularAxis, [ 'endpadding' ], [ 'endPadding' ] ], - [ r.radialAxis, [ 'showline' ], [ 'gridLinesVisible' ] ], - [ r.radialAxis, [ 'tickorientation' ], [ 'tickOrientation' ] ], - [ r.radialAxis, [ 'ticksuffix' ], [ 'ticksSuffix' ] ], - [ r.radialAxis, [ 'range' ], [ 'domain' ] ], - [ r.font, [ 'outlinecolor' ], [ 'outlineColor' ] ], - [ r.legend, [ 'traceorder' ], [ 'reverseOrder' ] ], - [ r, [ 'labeloffset' ], [ 'labelOffset' ] ], - [ r, [ 'defaultcolorrange' ], [ 'defaultColorRange' ] ] - ]; - toTranslate.forEach(function(d, i) { - µ.util.translator.apply(null, d.concat(reverse)); - }); - - if (!reverse) { - if (r.angularAxis && typeof r.angularAxis.ticklen !== 'undefined') r.tickLength = r.angularAxis.ticklen; - if (r.angularAxis && typeof r.angularAxis.tickcolor !== 'undefined') r.tickColor = r.angularAxis.tickcolor; - } else { - if (typeof r.tickLength !== 'undefined') { - r.angularaxis.ticklen = r.tickLength; - delete r.tickLength; - } - if (r.tickColor) { - r.angularaxis.tickcolor = r.tickColor; - delete r.tickColor; - } - } - if (r.legend && typeof r.legend.reverseOrder != 'boolean') { - r.legend.reverseOrder = r.legend.reverseOrder != 'normal'; - } - if (r.legend && typeof r.legend.traceorder == 'boolean') { - r.legend.traceorder = r.legend.traceorder ? 'reversed' : 'normal'; - delete r.legend.reverseOrder; - } - if (r.margin && typeof r.margin.t != 'undefined') { - var source = [ 't', 'r', 'b', 'l', 'pad' ]; - var target = [ 'top', 'right', 'bottom', 'left', 'pad' ]; - var margin = {}; - d3.entries(r.margin).forEach(function(dB, iB) { - margin[target[source.indexOf(dB.key)]] = dB.value; - }); - r.margin = margin; - } - if (reverse) { - delete r.needsEndSpacing; - delete r.minorTickColor; - delete r.minorTicks; - delete r.angularaxis.ticksCount; - delete r.angularaxis.ticksCount; - delete r.angularaxis.ticksStep; - delete r.angularaxis.rewriteTicks; - delete r.angularaxis.nticks; - delete r.radialaxis.ticksCount; - delete r.radialaxis.ticksCount; - delete r.radialaxis.ticksStep; - delete r.radialaxis.rewriteTicks; - delete r.radialaxis.nticks; - } - outputConfig.layout = r; - } - return outputConfig; - }; - return exports; -}; - -},{"../../../constants/alignment":688,"../../../lib":719,"d3":163}],838:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -/* eslint-disable new-cap */ - -'use strict'; - -var d3 = _dereq_('d3'); -var Lib = _dereq_('../../../lib'); -var Color = _dereq_('../../../components/color'); - -var micropolar = _dereq_('./micropolar'); -var UndoManager = _dereq_('./undo_manager'); -var extendDeepAll = Lib.extendDeepAll; - -var manager = module.exports = {}; - -manager.framework = function(_gd) { - var config, previousConfigClone, plot, convertedInput, container; - var undoManager = new UndoManager(); - - function exports(_inputConfig, _container) { - if(_container) container = _container; - d3.select(d3.select(container).node().parentNode).selectAll('.svg-container>*:not(.chart-root)').remove(); - - config = (!config) ? - _inputConfig : - extendDeepAll(config, _inputConfig); - - if(!plot) plot = micropolar.Axis(); - convertedInput = micropolar.adapter.plotly().convert(config); - plot.config(convertedInput).render(container); - _gd.data = config.data; - _gd.layout = config.layout; - manager.fillLayout(_gd); - return config; - } - exports.isPolar = true; - exports.svg = function() { return plot.svg(); }; - exports.getConfig = function() { return config; }; - exports.getLiveConfig = function() { - return micropolar.adapter.plotly().convert(plot.getLiveConfig(), true); - }; - exports.getLiveScales = function() { return {t: plot.angularScale(), r: plot.radialScale()}; }; - exports.setUndoPoint = function() { - var that = this; - var configClone = micropolar.util.cloneJson(config); - (function(_configClone, _previousConfigClone) { - undoManager.add({ - undo: function() { - if(_previousConfigClone) that(_previousConfigClone); - }, - redo: function() { - that(_configClone); - } - }); - })(configClone, previousConfigClone); - previousConfigClone = micropolar.util.cloneJson(configClone); - }; - exports.undo = function() { undoManager.undo(); }; - exports.redo = function() { undoManager.redo(); }; - return exports; -}; - -manager.fillLayout = function(_gd) { - var container = d3.select(_gd).selectAll('.plot-container'); - var paperDiv = container.selectAll('.svg-container'); - var paper = _gd.framework && _gd.framework.svg && _gd.framework.svg(); - var dflts = { - width: 800, - height: 600, - paper_bgcolor: Color.background, - _container: container, - _paperdiv: paperDiv, - _paper: paper - }; - - _gd._fullLayout = extendDeepAll(dflts, _gd.layout); -}; - -},{"../../../components/color":593,"../../../lib":719,"./micropolar":837,"./undo_manager":839,"d3":163}],839:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -// Modified from https://github.com/ArthurClemens/Javascript-Undo-Manager -// Copyright (c) 2010-2013 Arthur Clemens, arthur@visiblearea.com -module.exports = function UndoManager() { - var undoCommands = []; - var index = -1; - var isExecuting = false; - var callback; - - function execute(command, action) { - if(!command) return this; - - isExecuting = true; - command[action](); - isExecuting = false; - - return this; - } - - return { - add: function(command) { - if(isExecuting) return this; - undoCommands.splice(index + 1, undoCommands.length - index); - undoCommands.push(command); - index = undoCommands.length - 1; - return this; - }, - setCallback: function(callbackFunc) { callback = callbackFunc; }, - undo: function() { - var command = undoCommands[index]; - if(!command) return this; - execute(command, 'undo'); - index -= 1; - if(callback) callback(command.undo); - return this; - }, - redo: function() { - var command = undoCommands[index + 1]; - if(!command) return this; - execute(command, 'redo'); - index += 1; - if(callback) callback(command.redo); - return this; - }, - clear: function() { - undoCommands = []; - index = -1; - }, - hasUndo: function() { return index !== -1; }, - hasRedo: function() { return index < (undoCommands.length - 1); }, - getCommands: function() { return undoCommands; }, - getPreviousCommand: function() { return undoCommands[index - 1]; }, - getIndex: function() { return index; } - }; -}; - -},{}],840:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var tinycolor = _dereq_('tinycolor2'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var Plots = _dereq_('../plots'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var setConvertCartesian = _dereq_('../cartesian/set_convert'); -var setConvertPolar = _dereq_('./set_convert'); -var doAutoRange = _dereq_('../cartesian/autorange').doAutoRange; -var dragBox = _dereq_('../cartesian/dragbox'); -var dragElement = _dereq_('../../components/dragelement'); -var Fx = _dereq_('../../components/fx'); -var Titles = _dereq_('../../components/titles'); -var prepSelect = _dereq_('../cartesian/select').prepSelect; -var selectOnClick = _dereq_('../cartesian/select').selectOnClick; -var clearSelect = _dereq_('../cartesian/select').clearSelect; -var setCursor = _dereq_('../../lib/setcursor'); -var clearGlCanvases = _dereq_('../../lib/clear_gl_canvases'); -var redrawReglTraces = _dereq_('../../plot_api/subroutines').redrawReglTraces; - -var MID_SHIFT = _dereq_('../../constants/alignment').MID_SHIFT; -var constants = _dereq_('./constants'); -var helpers = _dereq_('./helpers'); - -var _ = Lib._; -var mod = Lib.mod; -var deg2rad = Lib.deg2rad; -var rad2deg = Lib.rad2deg; - -function Polar(gd, id) { - this.id = id; - this.gd = gd; - - this._hasClipOnAxisFalse = null; - this.vangles = null; - this.radialAxisAngle = null; - this.traceHash = {}; - this.layers = {}; - this.clipPaths = {}; - this.clipIds = {}; - this.viewInitial = {}; - - var fullLayout = gd._fullLayout; - var clipIdBase = 'clip' + fullLayout._uid + id; - - this.clipIds.forTraces = clipIdBase + '-for-traces'; - this.clipPaths.forTraces = fullLayout._clips.append('clipPath') - .attr('id', this.clipIds.forTraces); - this.clipPaths.forTraces.append('path'); - - this.framework = fullLayout._polarlayer.append('g') - .attr('class', id); - - // unfortunately, we have to keep track of some axis tick settings - // as polar subplots do not implement the 'ticks' editType - this.radialTickLayout = null; - this.angularTickLayout = null; -} - -var proto = Polar.prototype; - -module.exports = function createPolar(gd, id) { - return new Polar(gd, id); -}; - -proto.plot = function(polarCalcData, fullLayout) { - var _this = this; - var polarLayout = fullLayout[_this.id]; - - _this._hasClipOnAxisFalse = false; - for(var i = 0; i < polarCalcData.length; i++) { - var trace = polarCalcData[i][0].trace; - if(trace.cliponaxis === false) { - _this._hasClipOnAxisFalse = true; - break; - } - } - - _this.updateLayers(fullLayout, polarLayout); - _this.updateLayout(fullLayout, polarLayout); - Plots.generalUpdatePerTraceModule(_this.gd, _this, polarCalcData, polarLayout); - _this.updateFx(fullLayout, polarLayout); -}; - -proto.updateLayers = function(fullLayout, polarLayout) { - var _this = this; - var layers = _this.layers; - var radialLayout = polarLayout.radialaxis; - var angularLayout = polarLayout.angularaxis; - var layerNames = constants.layerNames; - - var frontPlotIndex = layerNames.indexOf('frontplot'); - var layerData = layerNames.slice(0, frontPlotIndex); - var isAngularAxisBelowTraces = angularLayout.layer === 'below traces'; - var isRadialAxisBelowTraces = radialLayout.layer === 'below traces'; - - if(isAngularAxisBelowTraces) layerData.push('angular-line'); - if(isRadialAxisBelowTraces) layerData.push('radial-line'); - if(isAngularAxisBelowTraces) layerData.push('angular-axis'); - if(isRadialAxisBelowTraces) layerData.push('radial-axis'); - - layerData.push('frontplot'); - - if(!isAngularAxisBelowTraces) layerData.push('angular-line'); - if(!isRadialAxisBelowTraces) layerData.push('radial-line'); - if(!isAngularAxisBelowTraces) layerData.push('angular-axis'); - if(!isRadialAxisBelowTraces) layerData.push('radial-axis'); - - var join = _this.framework.selectAll('.polarsublayer') - .data(layerData, String); - - join.enter().append('g') - .attr('class', function(d) { return 'polarsublayer ' + d;}) - .each(function(d) { - var sel = layers[d] = d3.select(this); - - switch(d) { - case 'frontplot': - // TODO add option to place in 'backplot' layer?? - sel.append('g').classed('barlayer', true); - sel.append('g').classed('scatterlayer', true); - break; - case 'backplot': - sel.append('g').classed('maplayer', true); - break; - case 'plotbg': - layers.bg = sel.append('path'); - break; - case 'radial-grid': - sel.style('fill', 'none'); - break; - case 'angular-grid': - sel.style('fill', 'none'); - break; - case 'radial-line': - sel.append('line').style('fill', 'none'); - break; - case 'angular-line': - sel.append('path').style('fill', 'none'); - break; - } - }); - - join.order(); -}; - -/* Polar subplots juggle with 6 'axis objects' (!), these are: - * - * - polarLayout.radialaxis (aka radialLayout in this file): - * - polarLayout.angularaxis (aka angularLayout in this file): - * used for data -> calcdata conversions (aka d2c) during the calc step - * - * - this.radialAxis - * extends polarLayout.radialaxis, adds mocked 'domain' and - * few other keys in order to reuse Cartesian doAutoRange and the Axes - * drawing routines. - * used for calcdata -> geometric conversions (aka c2g) during the plot step - * + setGeometry setups ax.c2g for given ax.range - * + setScale setups ax._m,ax._b for given ax.range - * - * - this.angularAxis - * extends polarLayout.angularaxis, adds mocked 'range' and 'domain' and - * a few other keys in order to reuse the Axes drawing routines. - * used for calcdata -> geometric conversions (aka c2g) during the plot step - * + setGeometry setups ax.c2g given ax.rotation, ax.direction & ax._categories, - * and mocks ax.range - * + setScale setups ax._m,ax._b with that mocked ax.range - * - * - this.xaxis - * - this.yaxis - * setup so that polar traces can reuse plot methods of Cartesian traces - * which mostly rely on 2pixel methods (e.g ax.c2p) - */ -proto.updateLayout = function(fullLayout, polarLayout) { - var _this = this; - var layers = _this.layers; - var gs = fullLayout._size; - - // axis attributes - var radialLayout = polarLayout.radialaxis; - var angularLayout = polarLayout.angularaxis; - // layout domains - var xDomain = polarLayout.domain.x; - var yDomain = polarLayout.domain.y; - // offsets from paper edge to layout domain box - _this.xOffset = gs.l + gs.w * xDomain[0]; - _this.yOffset = gs.t + gs.h * (1 - yDomain[1]); - // lengths of the layout domain box - var xLength = _this.xLength = gs.w * (xDomain[1] - xDomain[0]); - var yLength = _this.yLength = gs.h * (yDomain[1] - yDomain[0]); - // sector to plot - var sector = polarLayout.sector; - _this.sectorInRad = sector.map(deg2rad); - var sectorBBox = _this.sectorBBox = computeSectorBBox(sector); - var dxSectorBBox = sectorBBox[2] - sectorBBox[0]; - var dySectorBBox = sectorBBox[3] - sectorBBox[1]; - // aspect ratios - var arDomain = yLength / xLength; - var arSector = Math.abs(dySectorBBox / dxSectorBBox); - // actual lengths and domains of subplot box - var xLength2, yLength2; - var xDomain2, yDomain2; - var gap; - if(arDomain > arSector) { - xLength2 = xLength; - yLength2 = xLength * arSector; - gap = (yLength - yLength2) / gs.h / 2; - xDomain2 = [xDomain[0], xDomain[1]]; - yDomain2 = [yDomain[0] + gap, yDomain[1] - gap]; - } else { - xLength2 = yLength / arSector; - yLength2 = yLength; - gap = (xLength - xLength2) / gs.w / 2; - xDomain2 = [xDomain[0] + gap, xDomain[1] - gap]; - yDomain2 = [yDomain[0], yDomain[1]]; - } - _this.xLength2 = xLength2; - _this.yLength2 = yLength2; - _this.xDomain2 = xDomain2; - _this.yDomain2 = yDomain2; - // actual offsets from paper edge to the subplot box top-left corner - var xOffset2 = _this.xOffset2 = gs.l + gs.w * xDomain2[0]; - var yOffset2 = _this.yOffset2 = gs.t + gs.h * (1 - yDomain2[1]); - // circle radius in px - var radius = _this.radius = xLength2 / dxSectorBBox; - // 'inner' radius in px (when polar.hole is set) - var innerRadius = _this.innerRadius = polarLayout.hole * radius; - // circle center position in px - var cx = _this.cx = xOffset2 - radius * sectorBBox[0]; - var cy = _this.cy = yOffset2 + radius * sectorBBox[3]; - // circle center in the coordinate system of plot area - var cxx = _this.cxx = cx - xOffset2; - var cyy = _this.cyy = cy - yOffset2; - - _this.radialAxis = _this.mockAxis(fullLayout, polarLayout, radialLayout, { - // make this an 'x' axis to make positioning (especially rotation) easier - _id: 'x', - // convert to 'x' axis equivalent - side: { - counterclockwise: 'top', - clockwise: 'bottom' - }[radialLayout.side], - // spans length 1 radius - domain: [innerRadius / gs.w, radius / gs.w] - }); - - _this.angularAxis = _this.mockAxis(fullLayout, polarLayout, angularLayout, { - side: 'right', - // to get auto nticks right - domain: [0, Math.PI], - // don't pass through autorange logic - autorange: false - }); - - _this.doAutoRange(fullLayout, polarLayout); - // N.B. this sets _this.vangles - _this.updateAngularAxis(fullLayout, polarLayout); - // N.B. this sets _this.radialAxisAngle - _this.updateRadialAxis(fullLayout, polarLayout); - _this.updateRadialAxisTitle(fullLayout, polarLayout); - - _this.xaxis = _this.mockCartesianAxis(fullLayout, polarLayout, { - _id: 'x', - domain: xDomain2 - }); - - _this.yaxis = _this.mockCartesianAxis(fullLayout, polarLayout, { - _id: 'y', - domain: yDomain2 - }); - - var dPath = _this.pathSubplot(); - - _this.clipPaths.forTraces.select('path') - .attr('d', dPath) - .attr('transform', strTranslate(cxx, cyy)); - - layers.frontplot - .attr('transform', strTranslate(xOffset2, yOffset2)) - .call(Drawing.setClipUrl, _this._hasClipOnAxisFalse ? null : _this.clipIds.forTraces, _this.gd); - - layers.bg - .attr('d', dPath) - .attr('transform', strTranslate(cx, cy)) - .call(Color.fill, polarLayout.bgcolor); -}; - -proto.mockAxis = function(fullLayout, polarLayout, axLayout, opts) { - var commonOpts = { - // to get _boundingBox computation right when showticklabels is false - anchor: 'free', - position: 0 - }; - - var ax = Lib.extendFlat(commonOpts, axLayout, opts); - setConvertPolar(ax, polarLayout, fullLayout); - return ax; -}; - -proto.mockCartesianAxis = function(fullLayout, polarLayout, opts) { - var _this = this; - var axId = opts._id; - - var ax = Lib.extendFlat({type: 'linear'}, opts); - setConvertCartesian(ax, fullLayout); - - var bboxIndices = { - x: [0, 2], - y: [1, 3] - }; - - ax.setRange = function() { - var sectorBBox = _this.sectorBBox; - var ind = bboxIndices[axId]; - var rl = _this.radialAxis._rl; - var drl = (rl[1] - rl[0]) / (1 - polarLayout.hole); - ax.range = [sectorBBox[ind[0]] * drl, sectorBBox[ind[1]] * drl]; - }; - - ax.isPtWithinRange = axId === 'x' ? - function(d) { return _this.isPtInside(d); } : - function() { return true; }; - - ax.setRange(); - ax.setScale(); - return ax; -}; - -proto.doAutoRange = function(fullLayout, polarLayout) { - var gd = this.gd; - var radialAxis = this.radialAxis; - var radialLayout = polarLayout.radialaxis; - - radialAxis.setScale(); - doAutoRange(gd, radialAxis); - - var rng = radialAxis.range; - radialLayout.range = rng.slice(); - radialLayout._input.range = rng.slice(); - - radialAxis._rl = [ - radialAxis.r2l(rng[0], null, 'gregorian'), - radialAxis.r2l(rng[1], null, 'gregorian') - ]; -}; - -proto.updateRadialAxis = function(fullLayout, polarLayout) { - var _this = this; - var gd = _this.gd; - var layers = _this.layers; - var radius = _this.radius; - var innerRadius = _this.innerRadius; - var cx = _this.cx; - var cy = _this.cy; - var radialLayout = polarLayout.radialaxis; - var a0 = mod(polarLayout.sector[0], 360); - var ax = _this.radialAxis; - var hasRoomForIt = innerRadius < radius; - - _this.fillViewInitialKey('radialaxis.angle', radialLayout.angle); - _this.fillViewInitialKey('radialaxis.range', ax.range.slice()); - - ax.setGeometry(); - - // rotate auto tick labels by 180 if in quadrant II and III to make them - // readable from left-to-right - // - // TODO try moving deeper in Axes.drawLabels for better results? - if(ax.tickangle === 'auto' && (a0 > 90 && a0 <= 270)) { - ax.tickangle = 180; - } - - // easier to set rotate angle with custom translate function - var transFn = function(d) { - return 'translate(' + (ax.l2p(d.x) + innerRadius) + ',0)'; - }; - - // set special grid path function - var gridPathFn = function(d) { - return _this.pathArc(ax.r2p(d.x) + innerRadius); - }; - - var newTickLayout = strTickLayout(radialLayout); - if(_this.radialTickLayout !== newTickLayout) { - layers['radial-axis'].selectAll('.xtick').remove(); - _this.radialTickLayout = newTickLayout; - } - - if(hasRoomForIt) { - ax.setScale(); - - var vals = Axes.calcTicks(ax); - var valsClipped = Axes.clipEnds(ax, vals); - var tickSign = Axes.getTickSigns(ax)[2]; - - Axes.drawTicks(gd, ax, { - vals: vals, - layer: layers['radial-axis'], - path: Axes.makeTickPath(ax, 0, tickSign), - transFn: transFn, - crisp: false - }); - - Axes.drawGrid(gd, ax, { - vals: valsClipped, - layer: layers['radial-grid'], - path: gridPathFn, - transFn: Lib.noop, - crisp: false - }); - - Axes.drawLabels(gd, ax, { - vals: vals, - layer: layers['radial-axis'], - transFn: transFn, - labelFns: Axes.makeLabelFns(ax, 0) - }); - } - - // stash 'actual' radial axis angle for drag handlers (in degrees) - var angle = _this.radialAxisAngle = _this.vangles ? - rad2deg(snapToVertexAngle(deg2rad(radialLayout.angle), _this.vangles)) : - radialLayout.angle; - - var tLayer = strTranslate(cx, cy); - var tLayer2 = tLayer + strRotate(-angle); - - updateElement( - layers['radial-axis'], - hasRoomForIt && (radialLayout.showticklabels || radialLayout.ticks), - {transform: tLayer2} - ); - - updateElement( - layers['radial-grid'], - hasRoomForIt && radialLayout.showgrid, - {transform: tLayer} - ); - - updateElement( - layers['radial-line'].select('line'), - hasRoomForIt && radialLayout.showline, - { - x1: innerRadius, - y1: 0, - x2: radius, - y2: 0, - transform: tLayer2 - } - ) - .attr('stroke-width', radialLayout.linewidth) - .call(Color.stroke, radialLayout.linecolor); -}; - -proto.updateRadialAxisTitle = function(fullLayout, polarLayout, _angle) { - var _this = this; - var gd = _this.gd; - var radius = _this.radius; - var cx = _this.cx; - var cy = _this.cy; - var radialLayout = polarLayout.radialaxis; - var titleClass = _this.id + 'title'; - - var angle = _angle !== undefined ? _angle : _this.radialAxisAngle; - var angleRad = deg2rad(angle); - var cosa = Math.cos(angleRad); - var sina = Math.sin(angleRad); - - var pad = 0; - - // Hint: no need to check if there is in fact a title.text set - // because if plot is editable, pad needs to be calculated anyways - // to properly show placeholder text when title is empty. - if(radialLayout.title) { - var h = Drawing.bBox(_this.layers['radial-axis'].node()).height; - var ts = radialLayout.title.font.size; - pad = radialLayout.side === 'counterclockwise' ? - -h - ts * 0.4 : - h + ts * 0.8; - } - - _this.layers['radial-axis-title'] = Titles.draw(gd, titleClass, { - propContainer: radialLayout, - propName: _this.id + '.radialaxis.title', - placeholder: _(gd, 'Click to enter radial axis title'), - attributes: { - x: cx + (radius / 2) * cosa + pad * sina, - y: cy - (radius / 2) * sina + pad * cosa, - 'text-anchor': 'middle' - }, - transform: {rotate: -angle} - }); -}; - -proto.updateAngularAxis = function(fullLayout, polarLayout) { - var _this = this; - var gd = _this.gd; - var layers = _this.layers; - var radius = _this.radius; - var innerRadius = _this.innerRadius; - var cx = _this.cx; - var cy = _this.cy; - var angularLayout = polarLayout.angularaxis; - var ax = _this.angularAxis; - - _this.fillViewInitialKey('angularaxis.rotation', angularLayout.rotation); - - ax.setGeometry(); - ax.setScale(); - - // 't'ick to 'g'eometric radians is used all over the place here - var t2g = function(d) { return ax.t2g(d.x); }; - - // run rad2deg on tick0 and ditck for thetaunit: 'radians' axes - if(ax.type === 'linear' && ax.thetaunit === 'radians') { - ax.tick0 = rad2deg(ax.tick0); - ax.dtick = rad2deg(ax.dtick); - } - - var _transFn = function(rad) { - return strTranslate(cx + radius * Math.cos(rad), cy - radius * Math.sin(rad)); - }; - - var transFn = function(d) { - return _transFn(t2g(d)); - }; - - var transFn2 = function(d) { - var rad = t2g(d); - return _transFn(rad) + strRotate(-rad2deg(rad)); - }; - - var gridPathFn = function(d) { - var rad = t2g(d); - var cosRad = Math.cos(rad); - var sinRad = Math.sin(rad); - return 'M' + [cx + innerRadius * cosRad, cy - innerRadius * sinRad] + - 'L' + [cx + radius * cosRad, cy - radius * sinRad]; - }; - - var out = Axes.makeLabelFns(ax, 0); - var labelStandoff = out.labelStandoff; - var labelFns = {}; - - labelFns.xFn = function(d) { - var rad = t2g(d); - return Math.cos(rad) * labelStandoff; - }; - - labelFns.yFn = function(d) { - var rad = t2g(d); - var ff = Math.sin(rad) > 0 ? 0.2 : 1; - return -Math.sin(rad) * (labelStandoff + d.fontSize * ff) + - Math.abs(Math.cos(rad)) * (d.fontSize * MID_SHIFT); - }; - - labelFns.anchorFn = function(d) { - var rad = t2g(d); - var cos = Math.cos(rad); - return Math.abs(cos) < 0.1 ? - 'middle' : - (cos > 0 ? 'start' : 'end'); - }; - - labelFns.heightFn = function(d, a, h) { - var rad = t2g(d); - return -0.5 * (1 + Math.sin(rad)) * h; - }; - - var newTickLayout = strTickLayout(angularLayout); - if(_this.angularTickLayout !== newTickLayout) { - layers['angular-axis'].selectAll('.' + ax._id + 'tick').remove(); - _this.angularTickLayout = newTickLayout; - } - - var vals = Axes.calcTicks(ax); - - // angle of polygon vertices in geometric radians (null means circles) - // TODO what to do when ax.period > ax._categories ?? - var vangles; - if(polarLayout.gridshape === 'linear') { - vangles = vals.map(t2g); - - // ax._vals should be always ordered, make them - // always turn counterclockwise for convenience here - if(Lib.angleDelta(vangles[0], vangles[1]) < 0) { - vangles = vangles.slice().reverse(); - } - } else { - vangles = null; - } - _this.vangles = vangles; - - // Use tickval filter for category axes instead of tweaking - // the range w.r.t sector, so that sectors that cross 360 can - // show all their ticks. - if(ax.type === 'category') { - vals = vals.filter(function(d) { - return Lib.isAngleInsideSector(t2g(d), _this.sectorInRad); - }); - } - - if(ax.visible) { - var tickSign = ax.ticks === 'inside' ? -1 : 1; - var pad = (ax.linewidth || 1) / 2; - - Axes.drawTicks(gd, ax, { - vals: vals, - layer: layers['angular-axis'], - path: 'M' + (tickSign * pad) + ',0h' + (tickSign * ax.ticklen), - transFn: transFn2, - crisp: false - }); - - Axes.drawGrid(gd, ax, { - vals: vals, - layer: layers['angular-grid'], - path: gridPathFn, - transFn: Lib.noop, - crisp: false - }); - - Axes.drawLabels(gd, ax, { - vals: vals, - layer: layers['angular-axis'], - repositionOnUpdate: true, - transFn: transFn, - labelFns: labelFns - }); - } - - // TODO maybe two arcs is better here? - // maybe split style attributes between inner and outer angular axes? - - updateElement(layers['angular-line'].select('path'), angularLayout.showline, { - d: _this.pathSubplot(), - transform: strTranslate(cx, cy) - }) - .attr('stroke-width', angularLayout.linewidth) - .call(Color.stroke, angularLayout.linecolor); -}; - -proto.updateFx = function(fullLayout, polarLayout) { - if(!this.gd._context.staticPlot) { - this.updateAngularDrag(fullLayout); - this.updateRadialDrag(fullLayout, polarLayout, 0); - this.updateRadialDrag(fullLayout, polarLayout, 1); - this.updateMainDrag(fullLayout); - } -}; - -proto.updateMainDrag = function(fullLayout) { - var _this = this; - var gd = _this.gd; - var layers = _this.layers; - var zoomlayer = fullLayout._zoomlayer; - var MINZOOM = constants.MINZOOM; - var OFFEDGE = constants.OFFEDGE; - var radius = _this.radius; - var innerRadius = _this.innerRadius; - var cx = _this.cx; - var cy = _this.cy; - var cxx = _this.cxx; - var cyy = _this.cyy; - var sectorInRad = _this.sectorInRad; - var vangles = _this.vangles; - var radialAxis = _this.radialAxis; - var clampTiny = helpers.clampTiny; - var findXYatLength = helpers.findXYatLength; - var findEnclosingVertexAngles = helpers.findEnclosingVertexAngles; - var chw = constants.cornerHalfWidth; - var chl = constants.cornerLen / 2; - - var mainDrag = dragBox.makeDragger(layers, 'path', 'maindrag', 'crosshair'); - - d3.select(mainDrag) - .attr('d', _this.pathSubplot()) - .attr('transform', strTranslate(cx, cy)); - - var dragOpts = { - element: mainDrag, - gd: gd, - subplot: _this.id, - plotinfo: { - id: _this.id, - xaxis: _this.xaxis, - yaxis: _this.yaxis - }, - xaxes: [_this.xaxis], - yaxes: [_this.yaxis] - }; - - // mouse px position at drag start (0), move (1) - var x0, y0; - // radial distance from circle center at drag start (0), move (1) - var r0, r1; - // zoombox persistent quantities - var path0, dimmed, lum; - // zoombox, corners elements - var zb, corners; - - function norm(x, y) { - return Math.sqrt(x * x + y * y); - } - - function xy2r(x, y) { - return norm(x - cxx, y - cyy); - } - - function xy2a(x, y) { - return Math.atan2(cyy - y, x - cxx); - } - - function ra2xy(r, a) { - return [r * Math.cos(a), r * Math.sin(-a)]; - } - - function pathCorner(r, a) { - if(r === 0) return _this.pathSector(2 * chw); - - var da = chl / r; - var am = a - da; - var ap = a + da; - var rb = Math.max(0, Math.min(r, radius)); - var rm = rb - chw; - var rp = rb + chw; - - return 'M' + ra2xy(rm, am) + - 'A' + [rm, rm] + ' 0,0,0 ' + ra2xy(rm, ap) + - 'L' + ra2xy(rp, ap) + - 'A' + [rp, rp] + ' 0,0,1 ' + ra2xy(rp, am) + - 'Z'; - } - - // (x,y) is the pt at middle of the va0 <-> va1 edge - // - // ... we could eventually add another mode for cursor - // angles 'close to' enough to a particular vertex. - function pathCornerForPolygons(r, va0, va1) { - if(r === 0) return _this.pathSector(2 * chw); - - var xy0 = ra2xy(r, va0); - var xy1 = ra2xy(r, va1); - var x = clampTiny((xy0[0] + xy1[0]) / 2); - var y = clampTiny((xy0[1] + xy1[1]) / 2); - var innerPts, outerPts; - - if(x && y) { - var m = y / x; - var mperp = -1 / m; - var midPts = findXYatLength(chw, m, x, y); - innerPts = findXYatLength(chl, mperp, midPts[0][0], midPts[0][1]); - outerPts = findXYatLength(chl, mperp, midPts[1][0], midPts[1][1]); - } else { - var dx, dy; - if(y) { - // horizontal handles - dx = chl; - dy = chw; - } else { - // vertical handles - dx = chw; - dy = chl; - } - innerPts = [[x - dx, y - dy], [x + dx, y - dy]]; - outerPts = [[x - dx, y + dy], [x + dx, y + dy]]; - } - - return 'M' + innerPts.join('L') + - 'L' + outerPts.reverse().join('L') + 'Z'; - } - - function zoomPrep() { - r0 = null; - r1 = null; - path0 = _this.pathSubplot(); - dimmed = false; - - var polarLayoutNow = gd._fullLayout[_this.id]; - lum = tinycolor(polarLayoutNow.bgcolor).getLuminance(); - - zb = dragBox.makeZoombox(zoomlayer, lum, cx, cy, path0); - zb.attr('fill-rule', 'evenodd'); - corners = dragBox.makeCorners(zoomlayer, cx, cy); - clearSelect(gd); - } - - // N.B. this sets scoped 'r0' and 'r1' - // return true if 'valid' zoom distance, false otherwise - function clampAndSetR0R1(rr0, rr1) { - rr1 = Math.max(Math.min(rr1, radius), innerRadius); - - // starting or ending drag near center (outer edge), - // clamps radial distance at origin (at r=radius) - if(rr0 < OFFEDGE) rr0 = 0; - else if((radius - rr0) < OFFEDGE) rr0 = radius; - else if(rr1 < OFFEDGE) rr1 = 0; - else if((radius - rr1) < OFFEDGE) rr1 = radius; - - // make sure r0 < r1, - // to get correct fill pattern in path1 below - if(Math.abs(rr1 - rr0) > MINZOOM) { - if(rr0 < rr1) { - r0 = rr0; - r1 = rr1; - } else { - r0 = rr1; - r1 = rr0; - } - return true; - } else { - r0 = null; - r1 = null; - return false; - } - } - - function applyZoomMove(path1, cpath) { - path1 = path1 || path0; - cpath = cpath || 'M0,0Z'; - - zb.attr('d', path1); - corners.attr('d', cpath); - dragBox.transitionZoombox(zb, corners, dimmed, lum); - dimmed = true; - - var updateObj = {}; - computeZoomUpdates(updateObj); - gd.emit('plotly_relayouting', updateObj); - } - - function zoomMove(dx, dy) { - var x1 = x0 + dx; - var y1 = y0 + dy; - var rr0 = xy2r(x0, y0); - var rr1 = Math.min(xy2r(x1, y1), radius); - var a0 = xy2a(x0, y0); - var path1; - var cpath; - - if(clampAndSetR0R1(rr0, rr1)) { - path1 = path0 + _this.pathSector(r1); - if(r0) path1 += _this.pathSector(r0); - // keep 'starting' angle - cpath = pathCorner(r0, a0) + pathCorner(r1, a0); - } - applyZoomMove(path1, cpath); - } - - function findPolygonRadius(x, y, va0, va1) { - var xy = helpers.findIntersectionXY(va0, va1, va0, [x - cxx, cyy - y]); - return norm(xy[0], xy[1]); - } - - function zoomMoveForPolygons(dx, dy) { - var x1 = x0 + dx; - var y1 = y0 + dy; - var a0 = xy2a(x0, y0); - var a1 = xy2a(x1, y1); - var vangles0 = findEnclosingVertexAngles(a0, vangles); - var vangles1 = findEnclosingVertexAngles(a1, vangles); - var rr0 = findPolygonRadius(x0, y0, vangles0[0], vangles0[1]); - var rr1 = Math.min(findPolygonRadius(x1, y1, vangles1[0], vangles1[1]), radius); - var path1; - var cpath; - - if(clampAndSetR0R1(rr0, rr1)) { - path1 = path0 + _this.pathSector(r1); - if(r0) path1 += _this.pathSector(r0); - // keep 'starting' angle here too - cpath = [ - pathCornerForPolygons(r0, vangles0[0], vangles0[1]), - pathCornerForPolygons(r1, vangles0[0], vangles0[1]) - ].join(' '); - } - applyZoomMove(path1, cpath); - } - - function zoomDone() { - dragBox.removeZoombox(gd); - - if(r0 === null || r1 === null) return; - var updateObj = {}; - computeZoomUpdates(updateObj); - - dragBox.showDoubleClickNotifier(gd); - - Registry.call('_guiRelayout', gd, updateObj); - } - - function computeZoomUpdates(update) { - var rl = radialAxis._rl; - var m = (rl[1] - rl[0]) / (1 - innerRadius / radius) / radius; - var newRng = [ - rl[0] + (r0 - innerRadius) * m, - rl[0] + (r1 - innerRadius) * m - ]; - update[_this.id + '.radialaxis.range'] = newRng; - } - - function zoomClick(numClicks, evt) { - var clickMode = gd._fullLayout.clickmode; - - dragBox.removeZoombox(gd); - - // TODO double once vs twice logic (autorange vs fixed range) - if(numClicks === 2) { - var updateObj = {}; - for(var k in _this.viewInitial) { - updateObj[_this.id + '.' + k] = _this.viewInitial[k]; - } - - gd.emit('plotly_doubleclick', null); - Registry.call('_guiRelayout', gd, updateObj); - } - - if(clickMode.indexOf('select') > -1 && numClicks === 1) { - selectOnClick(evt, gd, [_this.xaxis], [_this.yaxis], _this.id, dragOpts); - } - - if(clickMode.indexOf('event') > -1) { - Fx.click(gd, evt, _this.id); - } - } - - dragOpts.prepFn = function(evt, startX, startY) { - var dragModeNow = gd._fullLayout.dragmode; - - var bbox = mainDrag.getBoundingClientRect(); - x0 = startX - bbox.left; - y0 = startY - bbox.top; - - // need to offset x/y as bbox center does not - // match origin for asymmetric polygons - if(vangles) { - var offset = helpers.findPolygonOffset(radius, sectorInRad[0], sectorInRad[1], vangles); - x0 += cxx + offset[0]; - y0 += cyy + offset[1]; - } - - switch(dragModeNow) { - case 'zoom': - if(vangles) { - dragOpts.moveFn = zoomMoveForPolygons; - } else { - dragOpts.moveFn = zoomMove; - } - dragOpts.clickFn = zoomClick; - dragOpts.doneFn = zoomDone; - zoomPrep(evt, startX, startY); - break; - case 'select': - case 'lasso': - prepSelect(evt, startX, startY, dragOpts, dragModeNow); - break; - } - }; - - mainDrag.onmousemove = function(evt) { - Fx.hover(gd, evt, _this.id); - gd._fullLayout._lasthover = mainDrag; - gd._fullLayout._hoversubplot = _this.id; - }; - - mainDrag.onmouseout = function(evt) { - if(gd._dragging) return; - dragElement.unhover(gd, evt); - }; - - dragElement.init(dragOpts); -}; - -proto.updateRadialDrag = function(fullLayout, polarLayout, rngIndex) { - var _this = this; - var gd = _this.gd; - var layers = _this.layers; - var radius = _this.radius; - var innerRadius = _this.innerRadius; - var cx = _this.cx; - var cy = _this.cy; - var radialAxis = _this.radialAxis; - var bl = constants.radialDragBoxSize; - var bl2 = bl / 2; - - if(!radialAxis.visible) return; - - var angle0 = deg2rad(_this.radialAxisAngle); - var rl = radialAxis._rl; - var rl0 = rl[0]; - var rl1 = rl[1]; - var rbase = rl[rngIndex]; - var m = 0.75 * (rl[1] - rl[0]) / (1 - polarLayout.hole) / radius; - - var tx, ty, className; - if(rngIndex) { - tx = cx + (radius + bl2) * Math.cos(angle0); - ty = cy - (radius + bl2) * Math.sin(angle0); - className = 'radialdrag'; - } else { - // the 'inner' box can get called: - // - when polar.hole>0 - // - when polar.sector isn't a full circle - // otherwise it is hidden behind the main drag. - tx = cx + (innerRadius - bl2) * Math.cos(angle0); - ty = cy - (innerRadius - bl2) * Math.sin(angle0); - className = 'radialdrag-inner'; - } - - var radialDrag = dragBox.makeRectDragger(layers, className, 'crosshair', -bl2, -bl2, bl, bl); - var dragOpts = {element: radialDrag, gd: gd}; - - updateElement(d3.select(radialDrag), radialAxis.visible && innerRadius < radius, { - transform: strTranslate(tx, ty) - }); - - // move function (either rotate or re-range flavor) - var moveFn2; - // rotate angle on done - var angle1; - // re-range range[1] (or range[0]) on done - var rprime; - - function moveFn(dx, dy) { - if(moveFn2) { - moveFn2(dx, dy); - } else { - var dvec = [dx, -dy]; - var rvec = [Math.cos(angle0), Math.sin(angle0)]; - var comp = Math.abs(Lib.dot(dvec, rvec) / Math.sqrt(Lib.dot(dvec, dvec))); - - // mostly perpendicular motions rotate, - // mostly parallel motions re-range - if(!isNaN(comp)) { - moveFn2 = comp < 0.5 ? rotateMove : rerangeMove; - } - } - - var update = {}; - computeRadialAxisUpdates(update); - gd.emit('plotly_relayouting', update); - } - - function computeRadialAxisUpdates(update) { - if(angle1 !== null) { - update[_this.id + '.radialaxis.angle'] = angle1; - } else if(rprime !== null) { - update[_this.id + '.radialaxis.range[' + rngIndex + ']'] = rprime; - } - } - - function doneFn() { - if(angle1 !== null) { - Registry.call('_guiRelayout', gd, _this.id + '.radialaxis.angle', angle1); - } else if(rprime !== null) { - Registry.call('_guiRelayout', gd, _this.id + '.radialaxis.range[' + rngIndex + ']', rprime); - } - } - - function rotateMove(dx, dy) { - // disable for inner drag boxes - if(rngIndex === 0) return; - - var x1 = tx + dx; - var y1 = ty + dy; - - angle1 = Math.atan2(cy - y1, x1 - cx); - if(_this.vangles) angle1 = snapToVertexAngle(angle1, _this.vangles); - angle1 = rad2deg(angle1); - - var transform = strTranslate(cx, cy) + strRotate(-angle1); - layers['radial-axis'].attr('transform', transform); - layers['radial-line'].select('line').attr('transform', transform); - - var fullLayoutNow = _this.gd._fullLayout; - var polarLayoutNow = fullLayoutNow[_this.id]; - _this.updateRadialAxisTitle(fullLayoutNow, polarLayoutNow, angle1); - } - - function rerangeMove(dx, dy) { - // project (dx, dy) unto unit radial axis vector - var dr = Lib.dot([dx, -dy], [Math.cos(angle0), Math.sin(angle0)]); - rprime = rbase - m * dr; - - // make sure rprime does not change the range[0] -> range[1] sign - if((m > 0) !== (rngIndex ? rprime > rl0 : rprime < rl1)) { - rprime = null; - return; - } - - var fullLayoutNow = gd._fullLayout; - var polarLayoutNow = fullLayoutNow[_this.id]; - - // update radial range -> update c2g -> update _m,_b - radialAxis.range[rngIndex] = rprime; - radialAxis._rl[rngIndex] = rprime; - _this.updateRadialAxis(fullLayoutNow, polarLayoutNow); - - _this.xaxis.setRange(); - _this.xaxis.setScale(); - _this.yaxis.setRange(); - _this.yaxis.setScale(); - - var hasRegl = false; - - for(var traceType in _this.traceHash) { - var moduleCalcData = _this.traceHash[traceType]; - var moduleCalcDataVisible = Lib.filterVisible(moduleCalcData); - var _module = moduleCalcData[0][0].trace._module; - _module.plot(gd, _this, moduleCalcDataVisible, polarLayoutNow); - if(Registry.traceIs(traceType, 'gl') && moduleCalcDataVisible.length) hasRegl = true; - } - - if(hasRegl) { - clearGlCanvases(gd); - redrawReglTraces(gd); - } - } - - dragOpts.prepFn = function() { - moveFn2 = null; - angle1 = null; - rprime = null; - - dragOpts.moveFn = moveFn; - dragOpts.doneFn = doneFn; - - clearSelect(gd); - }; - - dragOpts.clampFn = function(dx, dy) { - if(Math.sqrt(dx * dx + dy * dy) < constants.MINDRAG) { - dx = 0; - dy = 0; - } - return [dx, dy]; - }; - - dragElement.init(dragOpts); -}; - -proto.updateAngularDrag = function(fullLayout) { - var _this = this; - var gd = _this.gd; - var layers = _this.layers; - var radius = _this.radius; - var angularAxis = _this.angularAxis; - var cx = _this.cx; - var cy = _this.cy; - var cxx = _this.cxx; - var cyy = _this.cyy; - var dbs = constants.angularDragBoxSize; - - var angularDrag = dragBox.makeDragger(layers, 'path', 'angulardrag', 'move'); - var dragOpts = {element: angularDrag, gd: gd}; - - d3.select(angularDrag) - .attr('d', _this.pathAnnulus(radius, radius + dbs)) - .attr('transform', strTranslate(cx, cy)) - .call(setCursor, 'move'); - - function xy2a(x, y) { - return Math.atan2(cyy + dbs - y, x - cxx - dbs); - } - - // scatter trace, points and textpoints selections - var scatterTraces = layers.frontplot.select('.scatterlayer').selectAll('.trace'); - var scatterPoints = scatterTraces.selectAll('.point'); - var scatterTextPoints = scatterTraces.selectAll('.textpoint'); - - // mouse px position at drag start (0), move (1) - var x0, y0; - // angular axis angle rotation at drag start (0), move (1) - var rot0, rot1; - // induced radial axis rotation (only used on polygon grids) - var rrot1; - // angle about circle center at drag start - var a0; - - function moveFn(dx, dy) { - var fullLayoutNow = _this.gd._fullLayout; - var polarLayoutNow = fullLayoutNow[_this.id]; - - var x1 = x0 + dx; - var y1 = y0 + dy; - var a1 = xy2a(x1, y1); - var da = rad2deg(a1 - a0); - rot1 = rot0 + da; - - layers.frontplot.attr('transform', - strTranslate(_this.xOffset2, _this.yOffset2) + strRotate([-da, cxx, cyy]) - ); - - if(_this.vangles) { - rrot1 = _this.radialAxisAngle + da; - - var trans = strTranslate(cx, cy) + strRotate(-da); - var trans2 = strTranslate(cx, cy) + strRotate(-rrot1); - - layers.bg.attr('transform', trans); - layers['radial-grid'].attr('transform', trans); - layers['radial-axis'].attr('transform', trans2); - layers['radial-line'].select('line').attr('transform', trans2); - _this.updateRadialAxisTitle(fullLayoutNow, polarLayoutNow, rrot1); - } else { - _this.clipPaths.forTraces.select('path').attr('transform', - strTranslate(cxx, cyy) + strRotate(da) - ); - } - - // 'un-rotate' marker and text points - scatterPoints.each(function() { - var sel = d3.select(this); - var xy = Drawing.getTranslate(sel); - sel.attr('transform', strTranslate(xy.x, xy.y) + strRotate([da])); - }); - scatterTextPoints.each(function() { - var sel = d3.select(this); - var tx = sel.select('text'); - var xy = Drawing.getTranslate(sel); - // N.B rotate -> translate ordering matters - sel.attr('transform', strRotate([da, tx.attr('x'), tx.attr('y')]) + strTranslate(xy.x, xy.y)); - }); - - // update rotation -> range -> _m,_b - angularAxis.rotation = Lib.modHalf(rot1, 360); - _this.updateAngularAxis(fullLayoutNow, polarLayoutNow); - - if(_this._hasClipOnAxisFalse && !Lib.isFullCircle(_this.sectorInRad)) { - scatterTraces.call(Drawing.hideOutsideRangePoints, _this); - } - - var hasRegl = false; - - for(var traceType in _this.traceHash) { - if(Registry.traceIs(traceType, 'gl')) { - var moduleCalcData = _this.traceHash[traceType]; - var moduleCalcDataVisible = Lib.filterVisible(moduleCalcData); - var _module = moduleCalcData[0][0].trace._module; - _module.plot(gd, _this, moduleCalcDataVisible, polarLayoutNow); - if(moduleCalcDataVisible.length) hasRegl = true; - } - } - - if(hasRegl) { - clearGlCanvases(gd); - redrawReglTraces(gd); - } - - var update = {}; - computeRotationUpdates(update); - gd.emit('plotly_relayouting', update); - } - - function computeRotationUpdates(updateObj) { - updateObj[_this.id + '.angularaxis.rotation'] = rot1; - - if(_this.vangles) { - updateObj[_this.id + '.radialaxis.angle'] = rrot1; - } - } - - function doneFn() { - scatterTextPoints.select('text').attr('transform', null); - - var updateObj = {}; - computeRotationUpdates(updateObj); - Registry.call('_guiRelayout', gd, updateObj); - } - - dragOpts.prepFn = function(evt, startX, startY) { - var polarLayoutNow = fullLayout[_this.id]; - rot0 = polarLayoutNow.angularaxis.rotation; - - var bbox = angularDrag.getBoundingClientRect(); - x0 = startX - bbox.left; - y0 = startY - bbox.top; - a0 = xy2a(x0, y0); - - dragOpts.moveFn = moveFn; - dragOpts.doneFn = doneFn; - - clearSelect(gd); - }; - - // I don't what we should do in this case, skip we now - if(_this.vangles && !Lib.isFullCircle(_this.sectorInRad)) { - dragOpts.prepFn = Lib.noop; - setCursor(d3.select(angularDrag), null); - } - - dragElement.init(dragOpts); -}; - -proto.isPtInside = function(d) { - var sectorInRad = this.sectorInRad; - var vangles = this.vangles; - var thetag = this.angularAxis.c2g(d.theta); - var radialAxis = this.radialAxis; - var r = radialAxis.c2l(d.r); - var rl = radialAxis._rl; - - var fn = vangles ? helpers.isPtInsidePolygon : Lib.isPtInsideSector; - return fn(r, thetag, rl, sectorInRad, vangles); -}; - -proto.pathArc = function(r) { - var sectorInRad = this.sectorInRad; - var vangles = this.vangles; - var fn = vangles ? helpers.pathPolygon : Lib.pathArc; - return fn(r, sectorInRad[0], sectorInRad[1], vangles); -}; - -proto.pathSector = function(r) { - var sectorInRad = this.sectorInRad; - var vangles = this.vangles; - var fn = vangles ? helpers.pathPolygon : Lib.pathSector; - return fn(r, sectorInRad[0], sectorInRad[1], vangles); -}; - -proto.pathAnnulus = function(r0, r1) { - var sectorInRad = this.sectorInRad; - var vangles = this.vangles; - var fn = vangles ? helpers.pathPolygonAnnulus : Lib.pathAnnulus; - return fn(r0, r1, sectorInRad[0], sectorInRad[1], vangles); -}; - -proto.pathSubplot = function() { - var r0 = this.innerRadius; - var r1 = this.radius; - return r0 ? this.pathAnnulus(r0, r1) : this.pathSector(r1); -}; - -proto.fillViewInitialKey = function(key, val) { - if(!(key in this.viewInitial)) { - this.viewInitial[key] = val; - } -}; - -function strTickLayout(axLayout) { - var out = axLayout.ticks + String(axLayout.ticklen) + String(axLayout.showticklabels); - if('side' in axLayout) out += axLayout.side; - return out; -} - -// Finds the bounding box of a given circle sector, -// inspired by https://math.stackexchange.com/q/1852703 -// -// assumes: -// - sector[0] < sector[1] -// - counterclockwise rotation -function computeSectorBBox(sector) { - var s0 = sector[0]; - var s1 = sector[1]; - var arc = s1 - s0; - var a0 = mod(s0, 360); - var a1 = a0 + arc; - - var ax0 = Math.cos(deg2rad(a0)); - var ay0 = Math.sin(deg2rad(a0)); - var ax1 = Math.cos(deg2rad(a1)); - var ay1 = Math.sin(deg2rad(a1)); - - var x0, y0, x1, y1; - - if((a0 <= 90 && a1 >= 90) || (a0 > 90 && a1 >= 450)) { - y1 = 1; - } else if(ay0 <= 0 && ay1 <= 0) { - y1 = 0; - } else { - y1 = Math.max(ay0, ay1); - } - - if((a0 <= 180 && a1 >= 180) || (a0 > 180 && a1 >= 540)) { - x0 = -1; - } else if(ax0 >= 0 && ax1 >= 0) { - x0 = 0; - } else { - x0 = Math.min(ax0, ax1); - } - - if((a0 <= 270 && a1 >= 270) || (a0 > 270 && a1 >= 630)) { - y0 = -1; - } else if(ay0 >= 0 && ay1 >= 0) { - y0 = 0; - } else { - y0 = Math.min(ay0, ay1); - } - - if(a1 >= 360) { - x1 = 1; - } else if(ax0 <= 0 && ax1 <= 0) { - x1 = 0; - } else { - x1 = Math.max(ax0, ax1); - } - - return [x0, y0, x1, y1]; -} - -function snapToVertexAngle(a, vangles) { - var fn = function(v) { return Lib.angleDist(a, v); }; - var ind = Lib.findIndexOfMin(vangles, fn); - return vangles[ind]; -} - -function updateElement(sel, showAttr, attrs) { - if(showAttr) { - sel.attr('display', null); - sel.attr(attrs); - } else if(sel) { - sel.attr('display', 'none'); - } - return sel; -} - -function strTranslate(x, y) { - return 'translate(' + x + ',' + y + ')'; -} - -function strRotate(angle) { - return 'rotate(' + angle + ')'; -} - -},{"../../components/color":593,"../../components/dragelement":611,"../../components/drawing":614,"../../components/fx":632,"../../components/titles":681,"../../constants/alignment":688,"../../lib":719,"../../lib/clear_gl_canvases":704,"../../lib/setcursor":739,"../../plot_api/subroutines":758,"../../plots/cartesian/axes":767,"../../registry":847,"../cartesian/autorange":766,"../cartesian/dragbox":775,"../cartesian/select":784,"../cartesian/set_convert":785,"../plots":828,"./constants":829,"./helpers":830,"./set_convert":841,"d3":163,"tinycolor2":537}],841:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var setConvertCartesian = _dereq_('../cartesian/set_convert'); - -var deg2rad = Lib.deg2rad; -var rad2deg = Lib.rad2deg; - -/** - * setConvert for polar axes! - * - * @param {object} ax - * axis in question (works for both radial and angular axes) - * @param {object} polarLayout - * full polar layout of the subplot associated with 'ax' - * @param {object} fullLayout - * full layout - * - * Here, reuse some of the Cartesian setConvert logic, - * but we must extend some of it, as both radial and angular axes - * don't have domains and angular axes don't have _true_ ranges. - * - * Moreover, we introduce two new coordinate systems: - * - 'g' for geometric coordinates and - * - 't' for angular ticks - * - * Radial axis coordinate systems: - * - d, c and l: same as for cartesian axes - * - g: like calcdata but translated about `radialaxis.range[0]` & `polar.hole` - * - * Angular axis coordinate systems: - * - d: data, in whatever form it's provided - * - c: calcdata, turned into radians (for linear axes) - * or category indices (category axes) - * - t: tick calcdata, just like 'c' but in degrees for linear axes - * - g: geometric calcdata, radians coordinates that take into account - * axis rotation and direction - * - * Then, 'g'eometric data is ready to be converted to (x,y). - */ -module.exports = function setConvert(ax, polarLayout, fullLayout) { - setConvertCartesian(ax, fullLayout); - - switch(ax._id) { - case 'x': - case 'radialaxis': - setConvertRadial(ax, polarLayout); - break; - case 'angularaxis': - setConvertAngular(ax, polarLayout); - break; - } -}; - -function setConvertRadial(ax, polarLayout) { - var subplot = polarLayout._subplot; - - ax.setGeometry = function() { - var rl0 = ax._rl[0]; - var rl1 = ax._rl[1]; - - var b = subplot.innerRadius; - var m = (subplot.radius - b) / (rl1 - rl0); - var b2 = b / m; - - var rFilter = rl0 > rl1 ? - function(v) { return v <= 0; } : - function(v) { return v >= 0; }; - - ax.c2g = function(v) { - var r = ax.c2l(v) - rl0; - return (rFilter(r) ? r : 0) + b2; - }; - - ax.g2c = function(v) { - return ax.l2c(v + rl0 - b2); - }; - - ax.g2p = function(v) { return v * m; }; - ax.c2p = function(v) { return ax.g2p(ax.c2g(v)); }; - }; -} - -function toRadians(v, unit) { - return unit === 'degrees' ? deg2rad(v) : v; -} - -function fromRadians(v, unit) { - return unit === 'degrees' ? rad2deg(v) : v; -} - -function setConvertAngular(ax, polarLayout) { - var axType = ax.type; - - if(axType === 'linear') { - var _d2c = ax.d2c; - var _c2d = ax.c2d; - - ax.d2c = function(v, unit) { return toRadians(_d2c(v), unit); }; - ax.c2d = function(v, unit) { return _c2d(fromRadians(v, unit)); }; - } - - // override makeCalcdata to handle thetaunit and special theta0/dtheta logic - ax.makeCalcdata = function(trace, coord) { - var arrayIn = trace[coord]; - var len = trace._length; - var arrayOut, i; - - var _d2c = function(v) { return ax.d2c(v, trace.thetaunit); }; - - if(arrayIn) { - if(Lib.isTypedArray(arrayIn) && axType === 'linear') { - if(len === arrayIn.length) { - return arrayIn; - } else if(arrayIn.subarray) { - return arrayIn.subarray(0, len); - } - } - - arrayOut = new Array(len); - for(i = 0; i < len; i++) { - arrayOut[i] = _d2c(arrayIn[i]); - } - } else { - var coord0 = coord + '0'; - var dcoord = 'd' + coord; - var v0 = (coord0 in trace) ? _d2c(trace[coord0]) : 0; - var dv = (trace[dcoord]) ? _d2c(trace[dcoord]) : (ax.period || 2 * Math.PI) / len; - - arrayOut = new Array(len); - for(i = 0; i < len; i++) { - arrayOut[i] = v0 + i * dv; - } - } - - return arrayOut; - }; - - // N.B. we mock the axis 'range' here - ax.setGeometry = function() { - var sector = polarLayout.sector; - var sectorInRad = sector.map(deg2rad); - var dir = {clockwise: -1, counterclockwise: 1}[ax.direction]; - var rot = deg2rad(ax.rotation); - - var rad2g = function(v) { return dir * v + rot; }; - var g2rad = function(v) { return (v - rot) / dir; }; - - var rad2c, c2rad; - var rad2t, t2rad; - - switch(axType) { - case 'linear': - c2rad = rad2c = Lib.identity; - t2rad = deg2rad; - rad2t = rad2deg; - - // Set the angular range in degrees to make auto-tick computation cleaner, - // changing rotation/direction should not affect the angular tick value. - ax.range = Lib.isFullCircle(sectorInRad) ? - [sector[0], sector[0] + 360] : - sectorInRad.map(g2rad).map(rad2deg); - break; - - case 'category': - var catLen = ax._categories.length; - var _period = ax.period ? Math.max(ax.period, catLen) : catLen; - - // fallback in case all categories have been filtered out - if(_period === 0) _period = 1; - - c2rad = t2rad = function(v) { return v * 2 * Math.PI / _period; }; - rad2c = rad2t = function(v) { return v * _period / Math.PI / 2; }; - - ax.range = [0, _period]; - break; - } - - ax.c2g = function(v) { return rad2g(c2rad(v)); }; - ax.g2c = function(v) { return rad2c(g2rad(v)); }; - - ax.t2g = function(v) { return rad2g(t2rad(v)); }; - ax.g2t = function(v) { return rad2t(g2rad(v)); }; - }; -} - -},{"../../lib":719,"../cartesian/set_convert":785}],842:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../lib'); -var Template = _dereq_('../plot_api/plot_template'); -var handleDomainDefaults = _dereq_('./domain').defaults; - - -/** - * Find and supply defaults to all subplots of a given type - * This handles subplots that are contained within one container - so - * gl3d, geo, ternary... but not 2d axes which have separate x and y axes - * finds subplots, coerces their `domain` attributes, then calls the - * given handleDefaults function to fill in everything else. - * - * layoutIn: the complete user-supplied input layout - * layoutOut: the complete finished layout - * fullData: the finished data array, used only to find subplots - * opts: { - * type: subplot type string - * attributes: subplot attributes object - * partition: 'x' or 'y', which direction to divide domain space by default - * (default 'x', ie side-by-side subplots) - * TODO: this option is only here because 3D and geo made opposite - * choices in this regard previously and I didn't want to change it. - * Instead we should do: - * - something consistent - * - something more square (4 cuts 2x2, 5/6 cuts 2x3, etc.) - * - something that includes all subplot types in one arrangement, - * now that we can have them together! - * handleDefaults: function of (subplotLayoutIn, subplotLayoutOut, coerce, opts) - * this opts object is passed through to handleDefaults, so attach any - * additional items needed by this function here as well - * } - */ -module.exports = function handleSubplotDefaults(layoutIn, layoutOut, fullData, opts) { - var subplotType = opts.type; - var subplotAttributes = opts.attributes; - var handleDefaults = opts.handleDefaults; - var partition = opts.partition || 'x'; - - var ids = layoutOut._subplots[subplotType]; - var idsLength = ids.length; - - var baseId = idsLength && ids[0].replace(/\d+$/, ''); - - var subplotLayoutIn, subplotLayoutOut; - - function coerce(attr, dflt) { - return Lib.coerce(subplotLayoutIn, subplotLayoutOut, subplotAttributes, attr, dflt); - } - - for(var i = 0; i < idsLength; i++) { - var id = ids[i]; - - // ternary traces get a layout ternary for free! - if(layoutIn[id]) subplotLayoutIn = layoutIn[id]; - else subplotLayoutIn = layoutIn[id] = {}; - - subplotLayoutOut = Template.newContainer(layoutOut, id, baseId); - - // All subplot containers get a `uirevision` inheriting from the base. - // Currently all subplots containers have some user interaction - // attributes, but if we ever add one that doesn't, we would need an - // option to skip this step. - coerce('uirevision', layoutOut.uirevision); - - var dfltDomains = {}; - dfltDomains[partition] = [i / idsLength, (i + 1) / idsLength]; - handleDomainDefaults(subplotLayoutOut, layoutOut, coerce, dfltDomains); - - opts.id = id; - handleDefaults(subplotLayoutIn, subplotLayoutOut, coerce, opts); - } -}; - -},{"../lib":719,"../plot_api/plot_template":757,"./domain":792}],843:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Ternary = _dereq_('./ternary'); - -var getSubplotCalcData = _dereq_('../../plots/get_data').getSubplotCalcData; -var counterRegex = _dereq_('../../lib').counterRegex; -var TERNARY = 'ternary'; - -exports.name = TERNARY; - -var attr = exports.attr = 'subplot'; - -exports.idRoot = TERNARY; - -exports.idRegex = exports.attrRegex = counterRegex(TERNARY); - -var attributes = exports.attributes = {}; -attributes[attr] = { - valType: 'subplotid', - - dflt: 'ternary', - editType: 'calc', - -}; - -exports.layoutAttributes = _dereq_('./layout_attributes'); - -exports.supplyLayoutDefaults = _dereq_('./layout_defaults'); - -exports.plot = function plot(gd) { - var fullLayout = gd._fullLayout; - var calcData = gd.calcdata; - var ternaryIds = fullLayout._subplots[TERNARY]; - - for(var i = 0; i < ternaryIds.length; i++) { - var ternaryId = ternaryIds[i]; - var ternaryCalcData = getSubplotCalcData(calcData, TERNARY, ternaryId); - var ternary = fullLayout[ternaryId]._subplot; - - // If ternary is not instantiated, create one! - if(!ternary) { - ternary = new Ternary({ - id: ternaryId, - graphDiv: gd, - container: fullLayout._ternarylayer.node() - }, - fullLayout - ); - - fullLayout[ternaryId]._subplot = ternary; - } - - ternary.plot(ternaryCalcData, fullLayout, gd._promises); - } -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var oldTernaryKeys = oldFullLayout._subplots[TERNARY] || []; - - for(var i = 0; i < oldTernaryKeys.length; i++) { - var oldTernaryKey = oldTernaryKeys[i]; - var oldTernary = oldFullLayout[oldTernaryKey]._subplot; - - if(!newFullLayout[oldTernaryKey] && !!oldTernary) { - oldTernary.plotContainer.remove(); - oldTernary.clipDef.remove(); - oldTernary.clipDefRelative.remove(); - oldTernary.layers['a-title'].remove(); - oldTernary.layers['b-title'].remove(); - oldTernary.layers['c-title'].remove(); - } - } -}; - -},{"../../lib":719,"../../plots/get_data":802,"./layout_attributes":844,"./layout_defaults":845,"./ternary":846}],844:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorAttrs = _dereq_('../../components/color/attributes'); -var domainAttrs = _dereq_('../domain').attributes; -var axesAttrs = _dereq_('../cartesian/layout_attributes'); - -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var ternaryAxesAttrs = { - title: axesAttrs.title, - color: axesAttrs.color, - // ticks - tickmode: axesAttrs.tickmode, - nticks: extendFlat({}, axesAttrs.nticks, {dflt: 6, min: 1}), - tick0: axesAttrs.tick0, - dtick: axesAttrs.dtick, - tickvals: axesAttrs.tickvals, - ticktext: axesAttrs.ticktext, - ticks: axesAttrs.ticks, - ticklen: axesAttrs.ticklen, - tickwidth: axesAttrs.tickwidth, - tickcolor: axesAttrs.tickcolor, - showticklabels: axesAttrs.showticklabels, - showtickprefix: axesAttrs.showtickprefix, - tickprefix: axesAttrs.tickprefix, - showticksuffix: axesAttrs.showticksuffix, - ticksuffix: axesAttrs.ticksuffix, - showexponent: axesAttrs.showexponent, - exponentformat: axesAttrs.exponentformat, - separatethousands: axesAttrs.separatethousands, - tickfont: axesAttrs.tickfont, - tickangle: axesAttrs.tickangle, - tickformat: axesAttrs.tickformat, - tickformatstops: axesAttrs.tickformatstops, - hoverformat: axesAttrs.hoverformat, - // lines and grids - showline: extendFlat({}, axesAttrs.showline, {dflt: true}), - linecolor: axesAttrs.linecolor, - linewidth: axesAttrs.linewidth, - showgrid: extendFlat({}, axesAttrs.showgrid, {dflt: true}), - gridcolor: axesAttrs.gridcolor, - gridwidth: axesAttrs.gridwidth, - layer: axesAttrs.layer, - // range - min: { - valType: 'number', - dflt: 0, - - min: 0, - - }, - _deprecated: { - title: axesAttrs._deprecated.title, - titlefont: axesAttrs._deprecated.titlefont - } -}; - -var attrs = module.exports = overrideAll({ - domain: domainAttrs({name: 'ternary'}), - - bgcolor: { - valType: 'color', - - dflt: colorAttrs.background, - - }, - sum: { - valType: 'number', - - dflt: 1, - min: 0, - - }, - aaxis: ternaryAxesAttrs, - baxis: ternaryAxesAttrs, - caxis: ternaryAxesAttrs -}, 'plot', 'from-root'); - -// set uirevisions outside of `overrideAll` so we can get `editType: none` -attrs.uirevision = { - valType: 'any', - - editType: 'none', - -}; - -attrs.aaxis.uirevision = attrs.baxis.uirevision = attrs.caxis.uirevision = { - valType: 'any', - - editType: 'none', - -}; - -},{"../../components/color/attributes":592,"../../lib/extend":710,"../../plot_api/edit_types":750,"../cartesian/layout_attributes":779,"../domain":792}],845:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Color = _dereq_('../../components/color'); -var Template = _dereq_('../../plot_api/plot_template'); -var Lib = _dereq_('../../lib'); - -var handleSubplotDefaults = _dereq_('../subplot_defaults'); -var handleTickLabelDefaults = _dereq_('../cartesian/tick_label_defaults'); -var handleTickMarkDefaults = _dereq_('../cartesian/tick_mark_defaults'); -var handleTickValueDefaults = _dereq_('../cartesian/tick_value_defaults'); -var handleLineGridDefaults = _dereq_('../cartesian/line_grid_defaults'); -var layoutAttributes = _dereq_('./layout_attributes'); - -var axesNames = ['aaxis', 'baxis', 'caxis']; - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - handleSubplotDefaults(layoutIn, layoutOut, fullData, { - type: 'ternary', - attributes: layoutAttributes, - handleDefaults: handleTernaryDefaults, - font: layoutOut.font, - paper_bgcolor: layoutOut.paper_bgcolor - }); -}; - -function handleTernaryDefaults(ternaryLayoutIn, ternaryLayoutOut, coerce, options) { - var bgColor = coerce('bgcolor'); - var sum = coerce('sum'); - options.bgColor = Color.combine(bgColor, options.paper_bgcolor); - var axName, containerIn, containerOut; - - // TODO: allow most (if not all) axis attributes to be set - // in the outer container and used as defaults in the individual axes? - - for(var j = 0; j < axesNames.length; j++) { - axName = axesNames[j]; - containerIn = ternaryLayoutIn[axName] || {}; - containerOut = Template.newContainer(ternaryLayoutOut, axName); - containerOut._name = axName; - - handleAxisDefaults(containerIn, containerOut, options, ternaryLayoutOut); - } - - // if the min values contradict each other, set them all to default (0) - // and delete *all* the inputs so the user doesn't get confused later by - // changing one and having them all change. - var aaxis = ternaryLayoutOut.aaxis; - var baxis = ternaryLayoutOut.baxis; - var caxis = ternaryLayoutOut.caxis; - if(aaxis.min + baxis.min + caxis.min >= sum) { - aaxis.min = 0; - baxis.min = 0; - caxis.min = 0; - if(ternaryLayoutIn.aaxis) delete ternaryLayoutIn.aaxis.min; - if(ternaryLayoutIn.baxis) delete ternaryLayoutIn.baxis.min; - if(ternaryLayoutIn.caxis) delete ternaryLayoutIn.caxis.min; - } -} - -function handleAxisDefaults(containerIn, containerOut, options, ternaryLayoutOut) { - var axAttrs = layoutAttributes[containerOut._name]; - - function coerce(attr, dflt) { - return Lib.coerce(containerIn, containerOut, axAttrs, attr, dflt); - } - - coerce('uirevision', ternaryLayoutOut.uirevision); - - containerOut.type = 'linear'; // no other types allowed for ternary - - var dfltColor = coerce('color'); - // if axis.color was provided, use it for fonts too; otherwise, - // inherit from global font color in case that was provided. - var dfltFontColor = (dfltColor !== axAttrs.color.dflt) ? dfltColor : options.font.color; - - var axName = containerOut._name; - var letterUpper = axName.charAt(0).toUpperCase(); - var dfltTitle = 'Component ' + letterUpper; - - var title = coerce('title.text', dfltTitle); - containerOut._hovertitle = title === dfltTitle ? title : letterUpper; - - Lib.coerceFont(coerce, 'title.font', { - family: options.font.family, - size: Math.round(options.font.size * 1.2), - color: dfltFontColor - }); - - // range is just set by 'min' - max is determined by the other axes mins - coerce('min'); - - handleTickValueDefaults(containerIn, containerOut, coerce, 'linear'); - handleTickLabelDefaults(containerIn, containerOut, coerce, 'linear', {}); - handleTickMarkDefaults(containerIn, containerOut, coerce, - { outerTicks: true }); - - var showTickLabels = coerce('showticklabels'); - if(showTickLabels) { - Lib.coerceFont(coerce, 'tickfont', { - family: options.font.family, - size: options.font.size, - color: dfltFontColor - }); - coerce('tickangle'); - coerce('tickformat'); - } - - handleLineGridDefaults(containerIn, containerOut, coerce, { - dfltColor: dfltColor, - bgColor: options.bgColor, - // default grid color is darker here (60%, vs cartesian default ~91%) - // because the grid is not square so the eye needs heavier cues to follow - blend: 60, - showLine: true, - showGrid: true, - noZeroLine: true, - attributes: axAttrs - }); - - coerce('hoverformat'); - coerce('layer'); -} - -},{"../../components/color":593,"../../lib":719,"../../plot_api/plot_template":757,"../cartesian/line_grid_defaults":781,"../cartesian/tick_label_defaults":786,"../cartesian/tick_mark_defaults":787,"../cartesian/tick_value_defaults":788,"../subplot_defaults":842,"./layout_attributes":844}],846:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var tinycolor = _dereq_('tinycolor2'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var _ = Lib._; -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var setConvert = _dereq_('../cartesian/set_convert'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var Plots = _dereq_('../plots'); -var Axes = _dereq_('../cartesian/axes'); -var dragElement = _dereq_('../../components/dragelement'); -var Fx = _dereq_('../../components/fx'); -var Titles = _dereq_('../../components/titles'); -var prepSelect = _dereq_('../cartesian/select').prepSelect; -var selectOnClick = _dereq_('../cartesian/select').selectOnClick; -var clearSelect = _dereq_('../cartesian/select').clearSelect; -var constants = _dereq_('../cartesian/constants'); - -function Ternary(options, fullLayout) { - this.id = options.id; - this.graphDiv = options.graphDiv; - this.init(fullLayout); - this.makeFramework(fullLayout); - - // unfortunately, we have to keep track of some axis tick settings - // as ternary subplots do not implement the 'ticks' editType - this.aTickLayout = null; - this.bTickLayout = null; - this.cTickLayout = null; -} - -module.exports = Ternary; - -var proto = Ternary.prototype; - -proto.init = function(fullLayout) { - this.container = fullLayout._ternarylayer; - this.defs = fullLayout._defs; - this.layoutId = fullLayout._uid; - this.traceHash = {}; - this.layers = {}; -}; - -proto.plot = function(ternaryCalcData, fullLayout) { - var _this = this; - var ternaryLayout = fullLayout[_this.id]; - var graphSize = fullLayout._size; - - _this._hasClipOnAxisFalse = false; - for(var i = 0; i < ternaryCalcData.length; i++) { - var trace = ternaryCalcData[i][0].trace; - - if(trace.cliponaxis === false) { - _this._hasClipOnAxisFalse = true; - break; - } - } - - _this.updateLayers(ternaryLayout); - _this.adjustLayout(ternaryLayout, graphSize); - Plots.generalUpdatePerTraceModule(_this.graphDiv, _this, ternaryCalcData, ternaryLayout); - _this.layers.plotbg.select('path').call(Color.fill, ternaryLayout.bgcolor); -}; - -proto.makeFramework = function(fullLayout) { - var _this = this; - var gd = _this.graphDiv; - var ternaryLayout = fullLayout[_this.id]; - - var clipId = _this.clipId = 'clip' + _this.layoutId + _this.id; - var clipIdRelative = _this.clipIdRelative = 'clip-relative' + _this.layoutId + _this.id; - - // clippath for this ternary subplot - _this.clipDef = Lib.ensureSingleById(fullLayout._clips, 'clipPath', clipId, function(s) { - s.append('path').attr('d', 'M0,0Z'); - }); - - // 'relative' clippath (i.e. no translation) for this ternary subplot - _this.clipDefRelative = Lib.ensureSingleById(fullLayout._clips, 'clipPath', clipIdRelative, function(s) { - s.append('path').attr('d', 'M0,0Z'); - }); - - // container for everything in this ternary subplot - _this.plotContainer = Lib.ensureSingle(_this.container, 'g', _this.id); - _this.updateLayers(ternaryLayout); - - Drawing.setClipUrl(_this.layers.backplot, clipId, gd); - Drawing.setClipUrl(_this.layers.grids, clipId, gd); -}; - -proto.updateLayers = function(ternaryLayout) { - var _this = this; - var layers = _this.layers; - - // inside that container, we have one container for the data, and - // one each for the three axes around it. - - var plotLayers = ['draglayer', 'plotbg', 'backplot', 'grids']; - - if(ternaryLayout.aaxis.layer === 'below traces') { - plotLayers.push('aaxis', 'aline'); - } - if(ternaryLayout.baxis.layer === 'below traces') { - plotLayers.push('baxis', 'bline'); - } - if(ternaryLayout.caxis.layer === 'below traces') { - plotLayers.push('caxis', 'cline'); - } - - plotLayers.push('frontplot'); - - if(ternaryLayout.aaxis.layer === 'above traces') { - plotLayers.push('aaxis', 'aline'); - } - if(ternaryLayout.baxis.layer === 'above traces') { - plotLayers.push('baxis', 'bline'); - } - if(ternaryLayout.caxis.layer === 'above traces') { - plotLayers.push('caxis', 'cline'); - } - - var toplevel = _this.plotContainer.selectAll('g.toplevel') - .data(plotLayers, String); - - var grids = ['agrid', 'bgrid', 'cgrid']; - - toplevel.enter().append('g') - .attr('class', function(d) { return 'toplevel ' + d; }) - .each(function(d) { - var s = d3.select(this); - layers[d] = s; - - // containers for different trace types. - // NOTE - this is different from cartesian, where all traces - // are in front of grids. Here I'm putting maps behind the grids - // so the grids will always be visible if they're requested. - // Perhaps we want that for cartesian too? - if(d === 'frontplot') { - s.append('g').classed('scatterlayer', true); - } else if(d === 'backplot') { - s.append('g').classed('maplayer', true); - } else if(d === 'plotbg') { - s.append('path').attr('d', 'M0,0Z'); - } else if(d === 'aline' || d === 'bline' || d === 'cline') { - s.append('path'); - } else if(d === 'grids') { - grids.forEach(function(d) { - layers[d] = s.append('g').classed('grid ' + d, true); - }); - } - }); - - toplevel.order(); -}; - -var whRatio = Math.sqrt(4 / 3); - -proto.adjustLayout = function(ternaryLayout, graphSize) { - var _this = this; - var domain = ternaryLayout.domain; - var xDomainCenter = (domain.x[0] + domain.x[1]) / 2; - var yDomainCenter = (domain.y[0] + domain.y[1]) / 2; - var xDomain = domain.x[1] - domain.x[0]; - var yDomain = domain.y[1] - domain.y[0]; - var wmax = xDomain * graphSize.w; - var hmax = yDomain * graphSize.h; - var sum = ternaryLayout.sum; - var amin = ternaryLayout.aaxis.min; - var bmin = ternaryLayout.baxis.min; - var cmin = ternaryLayout.caxis.min; - - var x0, y0, w, h, xDomainFinal, yDomainFinal; - - if(wmax > whRatio * hmax) { - h = hmax; - w = h * whRatio; - } else { - w = wmax; - h = w / whRatio; - } - - xDomainFinal = xDomain * w / wmax; - yDomainFinal = yDomain * h / hmax; - - x0 = graphSize.l + graphSize.w * xDomainCenter - w / 2; - y0 = graphSize.t + graphSize.h * (1 - yDomainCenter) - h / 2; - - _this.x0 = x0; - _this.y0 = y0; - _this.w = w; - _this.h = h; - _this.sum = sum; - - // set up the x and y axis objects we'll use to lay out the points - _this.xaxis = { - type: 'linear', - range: [amin + 2 * cmin - sum, sum - amin - 2 * bmin], - domain: [ - xDomainCenter - xDomainFinal / 2, - xDomainCenter + xDomainFinal / 2 - ], - _id: 'x' - }; - setConvert(_this.xaxis, _this.graphDiv._fullLayout); - _this.xaxis.setScale(); - _this.xaxis.isPtWithinRange = function(d) { - return ( - d.a >= _this.aaxis.range[0] && - d.a <= _this.aaxis.range[1] && - d.b >= _this.baxis.range[1] && - d.b <= _this.baxis.range[0] && - d.c >= _this.caxis.range[1] && - d.c <= _this.caxis.range[0] - ); - }; - - _this.yaxis = { - type: 'linear', - range: [amin, sum - bmin - cmin], - domain: [ - yDomainCenter - yDomainFinal / 2, - yDomainCenter + yDomainFinal / 2 - ], - _id: 'y' - }; - setConvert(_this.yaxis, _this.graphDiv._fullLayout); - _this.yaxis.setScale(); - _this.yaxis.isPtWithinRange = function() { return true; }; - - // set up the modified axes for tick drawing - var yDomain0 = _this.yaxis.domain[0]; - - // aaxis goes up the left side. Set it up as a y axis, but with - // fictitious angles and domain, but then rotate and translate - // it into place at the end - var aaxis = _this.aaxis = extendFlat({}, ternaryLayout.aaxis, { - range: [amin, sum - bmin - cmin], - side: 'left', - // tickangle = 'auto' means 0 anyway for a y axis, need to coerce to 0 here - // so we can shift by 30. - tickangle: (+ternaryLayout.aaxis.tickangle || 0) - 30, - domain: [yDomain0, yDomain0 + yDomainFinal * whRatio], - anchor: 'free', - position: 0, - _id: 'y', - _length: w - }); - setConvert(aaxis, _this.graphDiv._fullLayout); - aaxis.setScale(); - - // baxis goes across the bottom (backward). We can set it up as an x axis - // without any enclosing transformation. - var baxis = _this.baxis = extendFlat({}, ternaryLayout.baxis, { - range: [sum - amin - cmin, bmin], - side: 'bottom', - domain: _this.xaxis.domain, - anchor: 'free', - position: 0, - _id: 'x', - _length: w - }); - setConvert(baxis, _this.graphDiv._fullLayout); - baxis.setScale(); - - // caxis goes down the right side. Set it up as a y axis, with - // post-transformation similar to aaxis - var caxis = _this.caxis = extendFlat({}, ternaryLayout.caxis, { - range: [sum - amin - bmin, cmin], - side: 'right', - tickangle: (+ternaryLayout.caxis.tickangle || 0) + 30, - domain: [yDomain0, yDomain0 + yDomainFinal * whRatio], - anchor: 'free', - position: 0, - _id: 'y', - _length: w - }); - setConvert(caxis, _this.graphDiv._fullLayout); - caxis.setScale(); - - var triangleClip = 'M' + x0 + ',' + (y0 + h) + 'h' + w + 'l-' + (w / 2) + ',-' + h + 'Z'; - _this.clipDef.select('path').attr('d', triangleClip); - _this.layers.plotbg.select('path').attr('d', triangleClip); - - var triangleClipRelative = 'M0,' + h + 'h' + w + 'l-' + (w / 2) + ',-' + h + 'Z'; - _this.clipDefRelative.select('path').attr('d', triangleClipRelative); - - var plotTransform = 'translate(' + x0 + ',' + y0 + ')'; - _this.plotContainer.selectAll('.scatterlayer,.maplayer') - .attr('transform', plotTransform); - - _this.clipDefRelative.select('path').attr('transform', null); - - // TODO: shift axes to accommodate linewidth*sin(30) tick mark angle - - // TODO: there's probably an easier way to handle these translations/offsets now... - var bTransform = 'translate(' + (x0 - baxis._offset) + ',' + (y0 + h) + ')'; - - _this.layers.baxis.attr('transform', bTransform); - _this.layers.bgrid.attr('transform', bTransform); - - var aTransform = 'translate(' + (x0 + w / 2) + ',' + y0 + - ')rotate(30)translate(0,' + -aaxis._offset + ')'; - _this.layers.aaxis.attr('transform', aTransform); - _this.layers.agrid.attr('transform', aTransform); - - var cTransform = 'translate(' + (x0 + w / 2) + ',' + y0 + - ')rotate(-30)translate(0,' + -caxis._offset + ')'; - _this.layers.caxis.attr('transform', cTransform); - _this.layers.cgrid.attr('transform', cTransform); - - _this.drawAxes(true); - - _this.layers.aline.select('path') - .attr('d', aaxis.showline ? - 'M' + x0 + ',' + (y0 + h) + 'l' + (w / 2) + ',-' + h : 'M0,0') - .call(Color.stroke, aaxis.linecolor || '#000') - .style('stroke-width', (aaxis.linewidth || 0) + 'px'); - _this.layers.bline.select('path') - .attr('d', baxis.showline ? - 'M' + x0 + ',' + (y0 + h) + 'h' + w : 'M0,0') - .call(Color.stroke, baxis.linecolor || '#000') - .style('stroke-width', (baxis.linewidth || 0) + 'px'); - _this.layers.cline.select('path') - .attr('d', caxis.showline ? - 'M' + (x0 + w / 2) + ',' + y0 + 'l' + (w / 2) + ',' + h : 'M0,0') - .call(Color.stroke, caxis.linecolor || '#000') - .style('stroke-width', (caxis.linewidth || 0) + 'px'); - - if(!_this.graphDiv._context.staticPlot) { - _this.initInteractions(); - } - - Drawing.setClipUrl( - _this.layers.frontplot, - _this._hasClipOnAxisFalse ? null : _this.clipId, - _this.graphDiv - ); -}; - -proto.drawAxes = function(doTitles) { - var _this = this; - var gd = _this.graphDiv; - var titlesuffix = _this.id.substr(7) + 'title'; - var layers = _this.layers; - var aaxis = _this.aaxis; - var baxis = _this.baxis; - var caxis = _this.caxis; - - _this.drawAx(aaxis); - _this.drawAx(baxis); - _this.drawAx(caxis); - - if(doTitles) { - var apad = Math.max(aaxis.showticklabels ? aaxis.tickfont.size / 2 : 0, - (caxis.showticklabels ? caxis.tickfont.size * 0.75 : 0) + - (caxis.ticks === 'outside' ? caxis.ticklen * 0.87 : 0)); - var bpad = (baxis.showticklabels ? baxis.tickfont.size : 0) + - (baxis.ticks === 'outside' ? baxis.ticklen : 0) + 3; - - layers['a-title'] = Titles.draw(gd, 'a' + titlesuffix, { - propContainer: aaxis, - propName: _this.id + '.aaxis.title', - placeholder: _(gd, 'Click to enter Component A title'), - attributes: { - x: _this.x0 + _this.w / 2, - y: _this.y0 - aaxis.title.font.size / 3 - apad, - 'text-anchor': 'middle' - } - }); - layers['b-title'] = Titles.draw(gd, 'b' + titlesuffix, { - propContainer: baxis, - propName: _this.id + '.baxis.title', - placeholder: _(gd, 'Click to enter Component B title'), - attributes: { - x: _this.x0 - bpad, - y: _this.y0 + _this.h + baxis.title.font.size * 0.83 + bpad, - 'text-anchor': 'middle' - } - }); - layers['c-title'] = Titles.draw(gd, 'c' + titlesuffix, { - propContainer: caxis, - propName: _this.id + '.caxis.title', - placeholder: _(gd, 'Click to enter Component C title'), - attributes: { - x: _this.x0 + _this.w + bpad, - y: _this.y0 + _this.h + caxis.title.font.size * 0.83 + bpad, - 'text-anchor': 'middle' - } - }); - } -}; - -proto.drawAx = function(ax) { - var _this = this; - var gd = _this.graphDiv; - var axName = ax._name; - var axLetter = axName.charAt(0); - var axId = ax._id; - var axLayer = _this.layers[axName]; - var counterAngle = 30; - - var stashKey = axLetter + 'tickLayout'; - var newTickLayout = strTickLayout(ax); - if(_this[stashKey] !== newTickLayout) { - axLayer.selectAll('.' + axId + 'tick').remove(); - _this[stashKey] = newTickLayout; - } - - ax.setScale(); - - var vals = Axes.calcTicks(ax); - var valsClipped = Axes.clipEnds(ax, vals); - var transFn = Axes.makeTransFn(ax); - var tickSign = Axes.getTickSigns(ax)[2]; - - var caRad = Lib.deg2rad(counterAngle); - var pad = tickSign * (ax.linewidth || 1) / 2; - var len = tickSign * ax.ticklen; - var w = _this.w; - var h = _this.h; - - var tickPath = axLetter === 'b' ? - 'M0,' + pad + 'l' + (Math.sin(caRad) * len) + ',' + (Math.cos(caRad) * len) : - 'M' + pad + ',0l' + (Math.cos(caRad) * len) + ',' + (-Math.sin(caRad) * len); - - var gridPath = { - a: 'M0,0l' + h + ',-' + (w / 2), - b: 'M0,0l-' + (w / 2) + ',-' + h, - c: 'M0,0l-' + h + ',' + (w / 2) - }[axLetter]; - - Axes.drawTicks(gd, ax, { - vals: ax.ticks === 'inside' ? valsClipped : vals, - layer: axLayer, - path: tickPath, - transFn: transFn, - crisp: false - }); - - Axes.drawGrid(gd, ax, { - vals: valsClipped, - layer: _this.layers[axLetter + 'grid'], - path: gridPath, - transFn: transFn, - crisp: false - }); - - Axes.drawLabels(gd, ax, { - vals: vals, - layer: axLayer, - transFn: transFn, - labelFns: Axes.makeLabelFns(ax, 0, counterAngle) - }); -}; - -function strTickLayout(axLayout) { - return axLayout.ticks + String(axLayout.ticklen) + String(axLayout.showticklabels); -} - -// hard coded paths for zoom corners -// uses the same sizing as cartesian, length is MINZOOM/2, width is 3px -var CLEN = constants.MINZOOM / 2 + 0.87; -var BLPATH = 'm-0.87,.5h' + CLEN + 'v3h-' + (CLEN + 5.2) + - 'l' + (CLEN / 2 + 2.6) + ',-' + (CLEN * 0.87 + 4.5) + - 'l2.6,1.5l-' + (CLEN / 2) + ',' + (CLEN * 0.87) + 'Z'; -var BRPATH = 'm0.87,.5h-' + CLEN + 'v3h' + (CLEN + 5.2) + - 'l-' + (CLEN / 2 + 2.6) + ',-' + (CLEN * 0.87 + 4.5) + - 'l-2.6,1.5l' + (CLEN / 2) + ',' + (CLEN * 0.87) + 'Z'; -var TOPPATH = 'm0,1l' + (CLEN / 2) + ',' + (CLEN * 0.87) + - 'l2.6,-1.5l-' + (CLEN / 2 + 2.6) + ',-' + (CLEN * 0.87 + 4.5) + - 'l-' + (CLEN / 2 + 2.6) + ',' + (CLEN * 0.87 + 4.5) + - 'l2.6,1.5l' + (CLEN / 2) + ',-' + (CLEN * 0.87) + 'Z'; -var STARTMARKER = 'm0.5,0.5h5v-2h-5v-5h-2v5h-5v2h5v5h2Z'; - -// I guess this could be shared with cartesian... but for now it's separate. -var SHOWZOOMOUTTIP = true; - -proto.initInteractions = function() { - var _this = this; - var dragger = _this.layers.plotbg.select('path').node(); - var gd = _this.graphDiv; - var zoomLayer = gd._fullLayout._zoomlayer; - - // use plotbg for the main interactions - var dragOptions = { - element: dragger, - gd: gd, - plotinfo: { - id: _this.id, - xaxis: _this.xaxis, - yaxis: _this.yaxis - }, - subplot: _this.id, - prepFn: function(e, startX, startY) { - // these aren't available yet when initInteractions - // is called - dragOptions.xaxes = [_this.xaxis]; - dragOptions.yaxes = [_this.yaxis]; - var dragModeNow = gd._fullLayout.dragmode; - - if(dragModeNow === 'lasso') dragOptions.minDrag = 1; - else dragOptions.minDrag = undefined; - - if(dragModeNow === 'zoom') { - dragOptions.moveFn = zoomMove; - dragOptions.clickFn = clickZoomPan; - dragOptions.doneFn = zoomDone; - zoomPrep(e, startX, startY); - } else if(dragModeNow === 'pan') { - dragOptions.moveFn = plotDrag; - dragOptions.clickFn = clickZoomPan; - dragOptions.doneFn = dragDone; - panPrep(); - clearSelect(gd); - } else if(dragModeNow === 'select' || dragModeNow === 'lasso') { - prepSelect(e, startX, startY, dragOptions, dragModeNow); - } - } - }; - - var x0, y0, mins0, span0, mins, lum, path0, dimmed, zb, corners; - - function makeUpdate(_mins) { - var attrs = {}; - attrs[_this.id + '.aaxis.min'] = _mins.a; - attrs[_this.id + '.baxis.min'] = _mins.b; - attrs[_this.id + '.caxis.min'] = _mins.c; - return attrs; - } - - function clickZoomPan(numClicks, evt) { - var clickMode = gd._fullLayout.clickmode; - - removeZoombox(gd); - - if(numClicks === 2) { - gd.emit('plotly_doubleclick', null); - Registry.call('_guiRelayout', gd, makeUpdate({a: 0, b: 0, c: 0})); - } - - if(clickMode.indexOf('select') > -1 && numClicks === 1) { - selectOnClick(evt, gd, [_this.xaxis], [_this.yaxis], _this.id, dragOptions); - } - - if(clickMode.indexOf('event') > -1) { - Fx.click(gd, evt, _this.id); - } - } - - function zoomPrep(e, startX, startY) { - var dragBBox = dragger.getBoundingClientRect(); - x0 = startX - dragBBox.left; - y0 = startY - dragBBox.top; - mins0 = { - a: _this.aaxis.range[0], - b: _this.baxis.range[1], - c: _this.caxis.range[1] - }; - mins = mins0; - span0 = _this.aaxis.range[1] - mins0.a; - lum = tinycolor(_this.graphDiv._fullLayout[_this.id].bgcolor).getLuminance(); - path0 = 'M0,' + _this.h + 'L' + (_this.w / 2) + ', 0L' + _this.w + ',' + _this.h + 'Z'; - dimmed = false; - - zb = zoomLayer.append('path') - .attr('class', 'zoombox') - .attr('transform', 'translate(' + _this.x0 + ', ' + _this.y0 + ')') - .style({ - 'fill': lum > 0.2 ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)', - 'stroke-width': 0 - }) - .attr('d', path0); - - corners = zoomLayer.append('path') - .attr('class', 'zoombox-corners') - .attr('transform', 'translate(' + _this.x0 + ', ' + _this.y0 + ')') - .style({ - fill: Color.background, - stroke: Color.defaultLine, - 'stroke-width': 1, - opacity: 0 - }) - .attr('d', 'M0,0Z'); - - clearSelect(gd); - } - - function getAFrac(x, y) { return 1 - (y / _this.h); } - function getBFrac(x, y) { return 1 - ((x + (_this.h - y) / Math.sqrt(3)) / _this.w); } - function getCFrac(x, y) { return ((x - (_this.h - y) / Math.sqrt(3)) / _this.w); } - - function zoomMove(dx0, dy0) { - var x1 = x0 + dx0; - var y1 = y0 + dy0; - var afrac = Math.max(0, Math.min(1, getAFrac(x0, y0), getAFrac(x1, y1))); - var bfrac = Math.max(0, Math.min(1, getBFrac(x0, y0), getBFrac(x1, y1))); - var cfrac = Math.max(0, Math.min(1, getCFrac(x0, y0), getCFrac(x1, y1))); - var xLeft = ((afrac / 2) + cfrac) * _this.w; - var xRight = (1 - (afrac / 2) - bfrac) * _this.w; - var xCenter = (xLeft + xRight) / 2; - var xSpan = xRight - xLeft; - var yBottom = (1 - afrac) * _this.h; - var yTop = yBottom - xSpan / whRatio; - - if(xSpan < constants.MINZOOM) { - mins = mins0; - zb.attr('d', path0); - corners.attr('d', 'M0,0Z'); - } else { - mins = { - a: mins0.a + afrac * span0, - b: mins0.b + bfrac * span0, - c: mins0.c + cfrac * span0 - }; - zb.attr('d', path0 + 'M' + xLeft + ',' + yBottom + - 'H' + xRight + 'L' + xCenter + ',' + yTop + - 'L' + xLeft + ',' + yBottom + 'Z'); - corners.attr('d', 'M' + x0 + ',' + y0 + STARTMARKER + - 'M' + xLeft + ',' + yBottom + BLPATH + - 'M' + xRight + ',' + yBottom + BRPATH + - 'M' + xCenter + ',' + yTop + TOPPATH); - } - - if(!dimmed) { - zb.transition() - .style('fill', lum > 0.2 ? 'rgba(0,0,0,0.4)' : - 'rgba(255,255,255,0.3)') - .duration(200); - corners.transition() - .style('opacity', 1) - .duration(200); - dimmed = true; - } - - gd.emit('plotly_relayouting', makeUpdate(mins)); - } - - function zoomDone() { - removeZoombox(gd); - - if(mins === mins0) return; - - Registry.call('_guiRelayout', gd, makeUpdate(mins)); - - if(SHOWZOOMOUTTIP && gd.data && gd._context.showTips) { - Lib.notifier(_(gd, 'Double-click to zoom back out'), 'long'); - SHOWZOOMOUTTIP = false; - } - } - - function panPrep() { - mins0 = { - a: _this.aaxis.range[0], - b: _this.baxis.range[1], - c: _this.caxis.range[1] - }; - mins = mins0; - } - - function plotDrag(dx, dy) { - var dxScaled = dx / _this.xaxis._m; - var dyScaled = dy / _this.yaxis._m; - mins = { - a: mins0.a - dyScaled, - b: mins0.b + (dxScaled + dyScaled) / 2, - c: mins0.c - (dxScaled - dyScaled) / 2 - }; - var minsorted = [mins.a, mins.b, mins.c].sort(); - var minindices = { - a: minsorted.indexOf(mins.a), - b: minsorted.indexOf(mins.b), - c: minsorted.indexOf(mins.c) - }; - if(minsorted[0] < 0) { - if(minsorted[1] + minsorted[0] / 2 < 0) { - minsorted[2] += minsorted[0] + minsorted[1]; - minsorted[0] = minsorted[1] = 0; - } else { - minsorted[2] += minsorted[0] / 2; - minsorted[1] += minsorted[0] / 2; - minsorted[0] = 0; - } - mins = { - a: minsorted[minindices.a], - b: minsorted[minindices.b], - c: minsorted[minindices.c] - }; - dy = (mins0.a - mins.a) * _this.yaxis._m; - dx = (mins0.c - mins.c - mins0.b + mins.b) * _this.xaxis._m; - } - - // move the data (translate, don't redraw) - var plotTransform = 'translate(' + (_this.x0 + dx) + ',' + (_this.y0 + dy) + ')'; - _this.plotContainer.selectAll('.scatterlayer,.maplayer') - .attr('transform', plotTransform); - - var plotTransform2 = 'translate(' + -dx + ',' + -dy + ')'; - _this.clipDefRelative.select('path').attr('transform', plotTransform2); - - // move the ticks - _this.aaxis.range = [mins.a, _this.sum - mins.b - mins.c]; - _this.baxis.range = [_this.sum - mins.a - mins.c, mins.b]; - _this.caxis.range = [_this.sum - mins.a - mins.b, mins.c]; - - _this.drawAxes(false); - - if(_this._hasClipOnAxisFalse) { - _this.plotContainer - .select('.scatterlayer').selectAll('.trace') - .call(Drawing.hideOutsideRangePoints, _this); - } - - gd.emit('plotly_relayouting', makeUpdate(mins)); - } - - function dragDone() { - Registry.call('_guiRelayout', gd, makeUpdate(mins)); - } - - // finally, set up hover and click - // these event handlers must already be set before dragElement.init - // so it can stash them and override them. - dragger.onmousemove = function(evt) { - Fx.hover(gd, evt, _this.id); - gd._fullLayout._lasthover = dragger; - gd._fullLayout._hoversubplot = _this.id; - }; - - dragger.onmouseout = function(evt) { - if(gd._dragging) return; - - dragElement.unhover(gd, evt); - }; - - dragElement.init(dragOptions); -}; - -function removeZoombox(gd) { - d3.select(gd) - .selectAll('.zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners') - .remove(); -} - -},{"../../components/color":593,"../../components/dragelement":611,"../../components/drawing":614,"../../components/fx":632,"../../components/titles":681,"../../lib":719,"../../lib/extend":710,"../../registry":847,"../cartesian/axes":767,"../cartesian/constants":773,"../cartesian/select":784,"../cartesian/set_convert":785,"../plots":828,"d3":163,"tinycolor2":537}],847:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Loggers = _dereq_('./lib/loggers'); -var noop = _dereq_('./lib/noop'); -var pushUnique = _dereq_('./lib/push_unique'); -var isPlainObject = _dereq_('./lib/is_plain_object'); -var addStyleRule = _dereq_('./lib/dom').addStyleRule; -var ExtendModule = _dereq_('./lib/extend'); - -var basePlotAttributes = _dereq_('./plots/attributes'); -var baseLayoutAttributes = _dereq_('./plots/layout_attributes'); - -var extendFlat = ExtendModule.extendFlat; -var extendDeepAll = ExtendModule.extendDeepAll; - -exports.modules = {}; -exports.allCategories = {}; -exports.allTypes = []; -exports.subplotsRegistry = {}; -exports.transformsRegistry = {}; -exports.componentsRegistry = {}; -exports.layoutArrayContainers = []; -exports.layoutArrayRegexes = []; -exports.traceLayoutAttributes = {}; -exports.localeRegistry = {}; -exports.apiMethodRegistry = {}; -exports.collectableSubplotTypes = null; - -/** - * Top-level register routine, exported as Plotly.register - * - * @param {object array or array of objects} _modules : - * module object or list of module object to register. - * - * A valid `moduleType: 'trace'` module has fields: - * - name {string} : the trace type - * - categories {array} : categories associated with this trace type, - * tested with Register.traceIs() - * - meta {object} : meta info (mostly for plot-schema) - * - * A valid `moduleType: 'locale'` module has fields: - * - name {string} : the locale name. Should be a 2-digit language string ('en', 'de') - * optionally with a country/region code ('en-GB', 'de-CH'). If a country - * code is used but the base language locale has not yet been supplied, - * we will use this locale for the base as well. - * - dictionary {object} : the dictionary mapping input strings to localized strings - * generally the keys should be the literal input strings, but - * if default translations are provided you can use any string as a key. - * - format {object} : a `d3.locale` format specifier for this locale - * any omitted keys we'll fall back on en-US. - * - * A valid `moduleType: 'transform'` module has fields: - * - name {string} : transform name - * - transform {function} : default-level transform function - * - calcTransform {function} : calc-level transform function - * - attributes {object} : transform attributes declarations - * - supplyDefaults {function} : attributes default-supply function - * - * A valid `moduleType: 'component'` module has fields: - * - name {string} : the component name, used it with Register.getComponentMethod() - * to employ component method. - * - * A valid `moduleType: 'apiMethod'` module has fields: - * - name {string} : the api method name. - * - fn {function} : the api method called with Register.call(); - * - */ -exports.register = function register(_modules) { - exports.collectableSubplotTypes = null; - - if(!_modules) { - throw new Error('No argument passed to Plotly.register.'); - } else if(_modules && !Array.isArray(_modules)) { - _modules = [_modules]; - } - - for(var i = 0; i < _modules.length; i++) { - var newModule = _modules[i]; - - if(!newModule) { - throw new Error('Invalid module was attempted to be registered!'); - } - - switch(newModule.moduleType) { - case 'trace': - registerTraceModule(newModule); - break; - case 'transform': - registerTransformModule(newModule); - break; - case 'component': - registerComponentModule(newModule); - break; - case 'locale': - registerLocale(newModule); - break; - case 'apiMethod': - var name = newModule.name; - exports.apiMethodRegistry[name] = newModule.fn; - break; - default: - throw new Error('Invalid module was attempted to be registered!'); - } - } -}; - -/** - * Get registered module using trace object or trace type - * - * @param {object||string} trace - * trace object with prop 'type' or trace type as a string - * @return {object} - * module object corresponding to trace type - */ -exports.getModule = function(trace) { - var _module = exports.modules[getTraceType(trace)]; - if(!_module) return false; - return _module._module; -}; - -/** - * Determine if this trace type is in a given category - * - * @param {object||string} traceType - * a trace (object) or trace type (string) - * @param {string} category - * category in question - * @return {boolean} - */ -exports.traceIs = function(traceType, category) { - traceType = getTraceType(traceType); - - // old plot.ly workspace hack, nothing to see here - if(traceType === 'various') return false; - - var _module = exports.modules[traceType]; - - if(!_module) { - if(traceType && traceType !== 'area') { - Loggers.log('Unrecognized trace type ' + traceType + '.'); - } - - _module = exports.modules[basePlotAttributes.type.dflt]; - } - - return !!_module.categories[category]; -}; - -/** - * Determine if this trace has a transform of the given type and return - * array of matching indices. - * - * @param {object} data - * a trace object (member of data or fullData) - * @param {string} type - * type of trace to test - * @return {array} - * array of matching indices. If none found, returns [] - */ -exports.getTransformIndices = function(data, type) { - var indices = []; - var transforms = data.transforms || []; - for(var i = 0; i < transforms.length; i++) { - if(transforms[i].type === type) { - indices.push(i); - } - } - return indices; -}; - -/** - * Determine if this trace has a transform of the given type - * - * @param {object} data - * a trace object (member of data or fullData) - * @param {string} type - * type of trace to test - * @return {boolean} - */ -exports.hasTransform = function(data, type) { - var transforms = data.transforms || []; - for(var i = 0; i < transforms.length; i++) { - if(transforms[i].type === type) { - return true; - } - } - return false; -}; - -/** - * Retrieve component module method. Falls back on noop if either the - * module or the method is missing, so the result can always be safely called - * - * @param {string} name - * name of component (as declared in component module) - * @param {string} method - * name of component module method - * @return {function} - */ -exports.getComponentMethod = function(name, method) { - var _module = exports.componentsRegistry[name]; - - if(!_module) return noop; - return _module[method] || noop; -}; - -/** - * Call registered api method. - * - * @param {string} name : api method name - * @param {...array} args : arguments passed to api method - * @return {any} : returns api method output - */ -exports.call = function() { - var name = arguments[0]; - var args = [].slice.call(arguments, 1); - return exports.apiMethodRegistry[name].apply(null, args); -}; - -function registerTraceModule(_module) { - var thisType = _module.name; - var categoriesIn = _module.categories; - var meta = _module.meta; - - if(exports.modules[thisType]) { - Loggers.log('Type ' + thisType + ' already registered'); - return; - } - - if(!exports.subplotsRegistry[_module.basePlotModule.name]) { - registerSubplot(_module.basePlotModule); - } - - var categoryObj = {}; - for(var i = 0; i < categoriesIn.length; i++) { - categoryObj[categoriesIn[i]] = true; - exports.allCategories[categoriesIn[i]] = true; - } - - exports.modules[thisType] = { - _module: _module, - categories: categoryObj - }; - - if(meta && Object.keys(meta).length) { - exports.modules[thisType].meta = meta; - } - - exports.allTypes.push(thisType); - - for(var componentName in exports.componentsRegistry) { - mergeComponentAttrsToTrace(componentName, thisType); - } - - /* - * Collect all trace layout attributes in one place for easier lookup later - * but don't merge them into the base schema as it would confuse the docs - * (at least after https://github.com/plotly/documentation/issues/202 gets done!) - */ - if(_module.layoutAttributes) { - extendFlat(exports.traceLayoutAttributes, _module.layoutAttributes); - } - - var basePlotModule = _module.basePlotModule; - var bpmName = basePlotModule.name; - - // add mapbox-gl CSS here to avoid console warning on instantiation - if(bpmName === 'mapbox') { - var styleRules = basePlotModule.constants.styleRules; - for(var k in styleRules) { - addStyleRule('.js-plotly-plot .plotly .mapboxgl-' + k, styleRules[k]); - } - } - - // if `plotly-geo-assets.js` is not included, - // add `PlotlyGeoAssets` global to stash references to all fetched - // topojson / geojson data - if((bpmName === 'geo' || bpmName === 'mapbox') && - (typeof window !== undefined && window.PlotlyGeoAssets === undefined) - ) { - window.PlotlyGeoAssets = {topojson: {}}; - } -} - -function registerSubplot(_module) { - var plotType = _module.name; - - if(exports.subplotsRegistry[plotType]) { - Loggers.log('Plot type ' + plotType + ' already registered.'); - return; - } - - // relayout array handling will look for component module methods with this - // name and won't find them because this is a subplot module... but that - // should be fine, it will just fall back on redrawing the plot. - findArrayRegexps(_module); - - // not sure what's best for the 'cartesian' type at this point - exports.subplotsRegistry[plotType] = _module; - - for(var componentName in exports.componentsRegistry) { - mergeComponentAttrsToSubplot(componentName, _module.name); - } -} - -function registerComponentModule(_module) { - if(typeof _module.name !== 'string') { - throw new Error('Component module *name* must be a string.'); - } - - var name = _module.name; - exports.componentsRegistry[name] = _module; - - if(_module.layoutAttributes) { - if(_module.layoutAttributes._isLinkedToArray) { - pushUnique(exports.layoutArrayContainers, name); - } - findArrayRegexps(_module); - } - - for(var traceType in exports.modules) { - mergeComponentAttrsToTrace(name, traceType); - } - - for(var subplotName in exports.subplotsRegistry) { - mergeComponentAttrsToSubplot(name, subplotName); - } - - for(var transformType in exports.transformsRegistry) { - mergeComponentAttrsToTransform(name, transformType); - } - - if(_module.schema && _module.schema.layout) { - extendDeepAll(baseLayoutAttributes, _module.schema.layout); - } -} - -function registerTransformModule(_module) { - if(typeof _module.name !== 'string') { - throw new Error('Transform module *name* must be a string.'); - } - - var prefix = 'Transform module ' + _module.name; - var hasTransform = typeof _module.transform === 'function'; - var hasCalcTransform = typeof _module.calcTransform === 'function'; - - if(!hasTransform && !hasCalcTransform) { - throw new Error(prefix + ' is missing a *transform* or *calcTransform* method.'); - } - if(hasTransform && hasCalcTransform) { - Loggers.log([ - prefix + ' has both a *transform* and *calcTransform* methods.', - 'Please note that all *transform* methods are executed', - 'before all *calcTransform* methods.' - ].join(' ')); - } - if(!isPlainObject(_module.attributes)) { - Loggers.log(prefix + ' registered without an *attributes* object.'); - } - if(typeof _module.supplyDefaults !== 'function') { - Loggers.log(prefix + ' registered without a *supplyDefaults* method.'); - } - - exports.transformsRegistry[_module.name] = _module; - - for(var componentName in exports.componentsRegistry) { - mergeComponentAttrsToTransform(componentName, _module.name); - } -} - -function registerLocale(_module) { - var locale = _module.name; - var baseLocale = locale.split('-')[0]; - - var newDict = _module.dictionary; - var newFormat = _module.format; - var hasDict = newDict && Object.keys(newDict).length; - var hasFormat = newFormat && Object.keys(newFormat).length; - - var locales = exports.localeRegistry; - - var localeObj = locales[locale]; - if(!localeObj) locales[locale] = localeObj = {}; - - // Should we use this dict for the base locale? - // In case we're overwriting a previous dict for this locale, check - // whether the base matches the full locale dict now. If we're not - // overwriting, locales[locale] is undefined so this just checks if - // baseLocale already had a dict or not. - // Same logic for dateFormats - if(baseLocale !== locale) { - var baseLocaleObj = locales[baseLocale]; - if(!baseLocaleObj) locales[baseLocale] = baseLocaleObj = {}; - - if(hasDict && baseLocaleObj.dictionary === localeObj.dictionary) { - baseLocaleObj.dictionary = newDict; - } - if(hasFormat && baseLocaleObj.format === localeObj.format) { - baseLocaleObj.format = newFormat; - } - } - - if(hasDict) localeObj.dictionary = newDict; - if(hasFormat) localeObj.format = newFormat; -} - -function findArrayRegexps(_module) { - if(_module.layoutAttributes) { - var arrayAttrRegexps = _module.layoutAttributes._arrayAttrRegexps; - if(arrayAttrRegexps) { - for(var i = 0; i < arrayAttrRegexps.length; i++) { - pushUnique(exports.layoutArrayRegexes, arrayAttrRegexps[i]); - } - } - } -} - -function mergeComponentAttrsToTrace(componentName, traceType) { - var componentSchema = exports.componentsRegistry[componentName].schema; - if(!componentSchema || !componentSchema.traces) return; - - var traceAttrs = componentSchema.traces[traceType]; - if(traceAttrs) { - extendDeepAll(exports.modules[traceType]._module.attributes, traceAttrs); - } -} - -function mergeComponentAttrsToTransform(componentName, transformType) { - var componentSchema = exports.componentsRegistry[componentName].schema; - if(!componentSchema || !componentSchema.transforms) return; - - var transformAttrs = componentSchema.transforms[transformType]; - if(transformAttrs) { - extendDeepAll(exports.transformsRegistry[transformType].attributes, transformAttrs); - } -} - -function mergeComponentAttrsToSubplot(componentName, subplotName) { - var componentSchema = exports.componentsRegistry[componentName].schema; - if(!componentSchema || !componentSchema.subplots) return; - - var subplotModule = exports.subplotsRegistry[subplotName]; - var subplotAttrs = subplotModule.layoutAttributes; - var subplotAttr = subplotModule.attr === 'subplot' ? subplotModule.name : subplotModule.attr; - if(Array.isArray(subplotAttr)) subplotAttr = subplotAttr[0]; - - var componentLayoutAttrs = componentSchema.subplots[subplotAttr]; - if(subplotAttrs && componentLayoutAttrs) { - extendDeepAll(subplotAttrs, componentLayoutAttrs); - } -} - -function getTraceType(traceType) { - if(typeof traceType === 'object') traceType = traceType.type; - return traceType; -} - -},{"./lib/dom":708,"./lib/extend":710,"./lib/is_plain_object":720,"./lib/loggers":723,"./lib/noop":728,"./lib/push_unique":733,"./plots/attributes":764,"./plots/layout_attributes":819}],848:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../registry'); -var Lib = _dereq_('../lib'); - -var extendFlat = Lib.extendFlat; -var extendDeep = Lib.extendDeep; - -// Put default plotTile layouts here -function cloneLayoutOverride(tileClass) { - var override; - - switch(tileClass) { - case 'themes__thumb': - override = { - autosize: true, - width: 150, - height: 150, - title: {text: ''}, - showlegend: false, - margin: {l: 5, r: 5, t: 5, b: 5, pad: 0}, - annotations: [] - }; - break; - - case 'thumbnail': - override = { - title: {text: ''}, - hidesources: true, - showlegend: false, - borderwidth: 0, - bordercolor: '', - margin: {l: 1, r: 1, t: 1, b: 1, pad: 0}, - annotations: [] - }; - break; - - default: - override = {}; - } - - - return override; -} - -function keyIsAxis(keyName) { - var types = ['xaxis', 'yaxis', 'zaxis']; - return (types.indexOf(keyName.slice(0, 5)) > -1); -} - - -module.exports = function clonePlot(graphObj, options) { - // Polar plot compatibility - if(graphObj.framework && graphObj.framework.isPolar) { - graphObj = graphObj.framework.getConfig(); - } - - var i; - var oldData = graphObj.data; - var oldLayout = graphObj.layout; - var newData = extendDeep([], oldData); - var newLayout = extendDeep({}, oldLayout, cloneLayoutOverride(options.tileClass)); - var context = graphObj._context || {}; - - if(options.width) newLayout.width = options.width; - if(options.height) newLayout.height = options.height; - - if(options.tileClass === 'thumbnail' || options.tileClass === 'themes__thumb') { - // kill annotations - newLayout.annotations = []; - var keys = Object.keys(newLayout); - - for(i = 0; i < keys.length; i++) { - if(keyIsAxis(keys[i])) { - newLayout[keys[i]].title = {text: ''}; - } - } - - // kill colorbar and pie labels - for(i = 0; i < newData.length; i++) { - var trace = newData[i]; - trace.showscale = false; - if(trace.marker) trace.marker.showscale = false; - if(Registry.traceIs(trace, 'pie-like')) trace.textposition = 'none'; - } - } - - if(Array.isArray(options.annotations)) { - for(i = 0; i < options.annotations.length; i++) { - newLayout.annotations.push(options.annotations[i]); - } - } - - // TODO: does this scene modification really belong here? - // If we still need it, can it move into the gl3d module? - var sceneIds = Object.keys(newLayout).filter(function(key) { - return key.match(/^scene\d*$/); - }); - if(sceneIds.length) { - var axesImageOverride = {}; - if(options.tileClass === 'thumbnail') { - axesImageOverride = { - title: {text: ''}, - showaxeslabels: false, - showticklabels: false, - linetickenable: false - }; - } - for(i = 0; i < sceneIds.length; i++) { - var scene = newLayout[sceneIds[i]]; - - if(!scene.xaxis) { - scene.xaxis = {}; - } - - if(!scene.yaxis) { - scene.yaxis = {}; - } - - if(!scene.zaxis) { - scene.zaxis = {}; - } - - extendFlat(scene.xaxis, axesImageOverride); - extendFlat(scene.yaxis, axesImageOverride); - extendFlat(scene.zaxis, axesImageOverride); - - // TODO what does this do? - scene._scene = null; - } - } - - var gd = document.createElement('div'); - if(options.tileClass) gd.className = options.tileClass; - - var plotTile = { - gd: gd, - td: gd, // for external (image server) compatibility - layout: newLayout, - data: newData, - config: { - staticPlot: (options.staticPlot === undefined) ? - true : - options.staticPlot, - plotGlPixelRatio: (options.plotGlPixelRatio === undefined) ? - 2 : - options.plotGlPixelRatio, - displaylogo: options.displaylogo || false, - showLink: options.showLink || false, - showTips: options.showTips || false, - mapboxAccessToken: context.mapboxAccessToken - } - }; - - if(options.setBackground !== 'transparent') { - plotTile.config.setBackground = options.setBackground || 'opaque'; - } - - // attaching the default Layout the gd, so you can grab it later - plotTile.gd.defaultLayout = cloneLayoutOverride(options.tileClass); - - return plotTile; -}; - -},{"../lib":719,"../registry":847}],849:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); - -var toImage = _dereq_('../plot_api/to_image'); - -var fileSaver = _dereq_('./filesaver'); -var helpers = _dereq_('./helpers'); - -/** - * Plotly.downloadImage - * - * @param {object | string | HTML div} gd - * can either be a data/layout/config object - * or an existing graph
- * or an id to an existing graph
- * @param {object} opts (see Plotly.toImage in ../plot_api/to_image) - * @return {promise} - */ -function downloadImage(gd, opts) { - var _gd; - if(!Lib.isPlainObject(gd)) _gd = Lib.getGraphDiv(gd); - - opts = opts || {}; - opts.format = opts.format || 'png'; - opts.imageDataOnly = true; - - return new Promise(function(resolve, reject) { - if(_gd && _gd._snapshotInProgress) { - reject(new Error('Snapshotting already in progress.')); - } - - // see comments within svgtoimg for additional - // discussion of problems with IE - // can now draw to canvas, but CORS tainted canvas - // does not allow toDataURL - // svg format will work though - if(Lib.isIE() && opts.format !== 'svg') { - reject(new Error(helpers.MSG_IE_BAD_FORMAT)); - } - - if(_gd) _gd._snapshotInProgress = true; - var promise = toImage(gd, opts); - - var filename = opts.filename || gd.fn || 'newplot'; - filename += '.' + opts.format; - - promise.then(function(result) { - if(_gd) _gd._snapshotInProgress = false; - return fileSaver(result, filename, opts.format); - }).then(function(name) { - resolve(name); - }).catch(function(err) { - if(_gd) _gd._snapshotInProgress = false; - reject(err); - }); - }); -} - -module.exports = downloadImage; - -},{"../lib":719,"../plot_api/to_image":760,"./filesaver":850,"./helpers":851}],850:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); -var helpers = _dereq_('./helpers'); - -/* -* substantial portions of this code from FileSaver.js -* https://github.com/eligrey/FileSaver.js -* License: https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md -* FileSaver.js -* A saveAs() FileSaver implementation. -* 1.1.20160328 -* -* By Eli Grey, http://eligrey.com -* License: MIT -* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md -*/ -function fileSaver(url, name, format) { - var saveLink = document.createElement('a'); - var canUseSaveLink = 'download' in saveLink; - - var promise = new Promise(function(resolve, reject) { - var blob; - var objectUrl; - - if(Lib.isIE9orBelow()) { - reject(new Error('IE < 10 unsupported')); - } - - // Safari doesn't allow downloading of blob urls - if(Lib.isSafari()) { - var prefix = format === 'svg' ? ',' : ';base64,'; - helpers.octetStream(prefix + encodeURIComponent(url)); - return resolve(name); - } - - // IE 10+ (native saveAs) - if(Lib.isIE()) { - // At this point we are only dealing with a decoded SVG as - // a data URL (since IE only supports SVG) - blob = helpers.createBlob(url, 'svg'); - window.navigator.msSaveBlob(blob, name); - blob = null; - return resolve(name); - } - - if(canUseSaveLink) { - blob = helpers.createBlob(url, format); - objectUrl = helpers.createObjectURL(blob); - - saveLink.href = objectUrl; - saveLink.download = name; - document.body.appendChild(saveLink); - saveLink.click(); - - document.body.removeChild(saveLink); - helpers.revokeObjectURL(objectUrl); - blob = null; - - return resolve(name); - } - - reject(new Error('download error')); - }); - - return promise; -} - - -module.exports = fileSaver; - -},{"../lib":719,"./helpers":851}],851:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../registry'); - -exports.getDelay = function(fullLayout) { - if(!fullLayout._has) return 0; - - return ( - fullLayout._has('gl3d') || - fullLayout._has('gl2d') || - fullLayout._has('mapbox') - ) ? 500 : 0; -}; - -exports.getRedrawFunc = function(gd) { - return function() { - var fullLayout = gd._fullLayout || {}; - var hasPolar = fullLayout._has && fullLayout._has('polar'); - var hasLegacyPolar = !hasPolar && gd.data && gd.data[0] && gd.data[0].r; - - if(!hasLegacyPolar) { - Registry.getComponentMethod('colorbar', 'draw')(gd); - } - }; -}; - -exports.encodeSVG = function(svg) { - return 'data:image/svg+xml,' + encodeURIComponent(svg); -}; - -var DOM_URL = window.URL || window.webkitURL; - -exports.createObjectURL = function(blob) { - return DOM_URL.createObjectURL(blob); -}; - -exports.revokeObjectURL = function(url) { - return DOM_URL.revokeObjectURL(url); -}; - -exports.createBlob = function(url, format) { - if(format === 'svg') { - return new window.Blob([url], {type: 'image/svg+xml;charset=utf-8'}); - } else { - var binary = fixBinary(window.atob(url)); - return new window.Blob([binary], {type: 'image/' + format}); - } -}; - -exports.octetStream = function(s) { - document.location.href = 'data:application/octet-stream' + s; -}; - -// Taken from https://bl.ocks.org/nolanlawson/0eac306e4dac2114c752 -function fixBinary(b) { - var len = b.length; - var buf = new ArrayBuffer(len); - var arr = new Uint8Array(buf); - for(var i = 0; i < len; i++) { - arr[i] = b.charCodeAt(i); - } - return buf; -} - -exports.IMAGE_URL_PREFIX = /^data:image\/\w+;base64,/; - -exports.MSG_IE_BAD_FORMAT = 'Sorry IE does not support downloading from canvas. Try {format:\'svg\'} instead.'; - -},{"../registry":847}],852:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var helpers = _dereq_('./helpers'); - -var Snapshot = { - getDelay: helpers.getDelay, - getRedrawFunc: helpers.getRedrawFunc, - clone: _dereq_('./cloneplot'), - toSVG: _dereq_('./tosvg'), - svgToImg: _dereq_('./svgtoimg'), - toImage: _dereq_('./toimage'), - downloadImage: _dereq_('./download') -}; - -module.exports = Snapshot; - -},{"./cloneplot":848,"./download":849,"./helpers":851,"./svgtoimg":853,"./toimage":854,"./tosvg":855}],853:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); -var EventEmitter = _dereq_('events').EventEmitter; - -var helpers = _dereq_('./helpers'); - -function svgToImg(opts) { - var ev = opts.emitter || new EventEmitter(); - - var promise = new Promise(function(resolve, reject) { - var Image = window.Image; - var svg = opts.svg; - var format = opts.format || 'png'; - - // IE only support svg - if(Lib.isIE() && format !== 'svg') { - var ieSvgError = new Error(helpers.MSG_IE_BAD_FORMAT); - reject(ieSvgError); - // eventually remove the ev - // in favor of promises - if(!opts.promise) { - return ev.emit('error', ieSvgError); - } else { - return promise; - } - } - - var canvas = opts.canvas; - var scale = opts.scale || 1; - var w0 = opts.width || 300; - var h0 = opts.height || 150; - var w1 = scale * w0; - var h1 = scale * h0; - - var ctx = canvas.getContext('2d'); - var img = new Image(); - var svgBlob, url; - - if(format === 'svg' || Lib.isIE9orBelow() || Lib.isSafari()) { - url = helpers.encodeSVG(svg); - } else { - svgBlob = helpers.createBlob(svg, 'svg'); - url = helpers.createObjectURL(svgBlob); - } - - canvas.width = w1; - canvas.height = h1; - - img.onload = function() { - var imgData; - - svgBlob = null; - helpers.revokeObjectURL(url); - - // don't need to draw to canvas if svg - // save some time and also avoid failure on IE - if(format !== 'svg') { - ctx.drawImage(img, 0, 0, w1, h1); - } - - switch(format) { - case 'jpeg': - imgData = canvas.toDataURL('image/jpeg'); - break; - case 'png': - imgData = canvas.toDataURL('image/png'); - break; - case 'webp': - imgData = canvas.toDataURL('image/webp'); - break; - case 'svg': - imgData = url; - break; - default: - var errorMsg = 'Image format is not jpeg, png, svg or webp.'; - reject(new Error(errorMsg)); - // eventually remove the ev - // in favor of promises - if(!opts.promise) { - return ev.emit('error', errorMsg); - } - } - resolve(imgData); - // eventually remove the ev - // in favor of promises - if(!opts.promise) { - ev.emit('success', imgData); - } - }; - - img.onerror = function(err) { - svgBlob = null; - helpers.revokeObjectURL(url); - - reject(err); - // eventually remove the ev - // in favor of promises - if(!opts.promise) { - return ev.emit('error', err); - } - }; - - img.src = url; - }); - - // temporary for backward compatibility - // move to only Promise in 2.0.0 - // and eliminate the EventEmitter - if(opts.promise) { - return promise; - } - - return ev; -} - -module.exports = svgToImg; - -},{"../lib":719,"./helpers":851,"events":104}],854:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var EventEmitter = _dereq_('events').EventEmitter; - -var Registry = _dereq_('../registry'); -var Lib = _dereq_('../lib'); - -var helpers = _dereq_('./helpers'); -var clonePlot = _dereq_('./cloneplot'); -var toSVG = _dereq_('./tosvg'); -var svgToImg = _dereq_('./svgtoimg'); - -/** - * @param {object} gd figure Object - * @param {object} opts option object - * @param opts.format 'jpeg' | 'png' | 'webp' | 'svg' - */ -function toImage(gd, opts) { - // first clone the GD so we can operate in a clean environment - var ev = new EventEmitter(); - - var clone = clonePlot(gd, {format: 'png'}); - var clonedGd = clone.gd; - - // put the cloned div somewhere off screen before attaching to DOM - clonedGd.style.position = 'absolute'; - clonedGd.style.left = '-5000px'; - document.body.appendChild(clonedGd); - - function wait() { - var delay = helpers.getDelay(clonedGd._fullLayout); - - setTimeout(function() { - var svg = toSVG(clonedGd); - - var canvas = document.createElement('canvas'); - canvas.id = Lib.randstr(); - - ev = svgToImg({ - format: opts.format, - width: clonedGd._fullLayout.width, - height: clonedGd._fullLayout.height, - canvas: canvas, - emitter: ev, - svg: svg - }); - - ev.clean = function() { - if(clonedGd) document.body.removeChild(clonedGd); - }; - }, delay); - } - - var redrawFunc = helpers.getRedrawFunc(clonedGd); - - Registry.call('plot', clonedGd, clone.data, clone.layout, clone.config) - .then(redrawFunc) - .then(wait) - .catch(function(err) { - ev.emit('error', err); - }); - - - return ev; -} - -module.exports = toImage; - -},{"../lib":719,"../registry":847,"./cloneplot":848,"./helpers":851,"./svgtoimg":853,"./tosvg":855,"events":104}],855:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Lib = _dereq_('../lib'); -var Drawing = _dereq_('../components/drawing'); -var Color = _dereq_('../components/color'); - -var xmlnsNamespaces = _dereq_('../constants/xmlns_namespaces'); -var DOUBLEQUOTE_REGEX = /"/g; -var DUMMY_SUB = 'TOBESTRIPPED'; -var DUMMY_REGEX = new RegExp('("' + DUMMY_SUB + ')|(' + DUMMY_SUB + '")', 'g'); - -function htmlEntityDecode(s) { - var hiddenDiv = d3.select('body').append('div').style({display: 'none'}).html(''); - var replaced = s.replace(/(&[^;]*;)/gi, function(d) { - if(d === '<') { return '<'; } // special handling for brackets - if(d === '&rt;') { return '>'; } - if(d.indexOf('<') !== -1 || d.indexOf('>') !== -1) { return ''; } - return hiddenDiv.html(d).text(); // everything else, let the browser decode it to unicode - }); - hiddenDiv.remove(); - return replaced; -} - -function xmlEntityEncode(str) { - return str.replace(/&(?!\w+;|\#[0-9]+;| \#x[0-9A-F]+;)/g, '&'); -} - -module.exports = function toSVG(gd, format, scale) { - var fullLayout = gd._fullLayout; - var svg = fullLayout._paper; - var toppaper = fullLayout._toppaper; - var width = fullLayout.width; - var height = fullLayout.height; - var i; - - // make background color a rect in the svg, then revert after scraping - // all other alterations have been dealt with by properly preparing the svg - // in the first place... like setting cursors with css classes so we don't - // have to remove them, and providing the right namespaces in the svg to - // begin with - svg.insert('rect', ':first-child') - .call(Drawing.setRect, 0, 0, width, height) - .call(Color.fill, fullLayout.paper_bgcolor); - - // subplot-specific to-SVG methods - // which notably add the contents of the gl-container - // into the main svg node - var basePlotModules = fullLayout._basePlotModules || []; - for(i = 0; i < basePlotModules.length; i++) { - var _module = basePlotModules[i]; - - if(_module.toSVG) _module.toSVG(gd); - } - - // add top items above them assumes everything in toppaper is either - // a group or a defs, and if it's empty (like hoverlayer) we can ignore it. - if(toppaper) { - var nodes = toppaper.node().childNodes; - - // make copy of nodes as childNodes prop gets mutated in loop below - var topGroups = Array.prototype.slice.call(nodes); - - for(i = 0; i < topGroups.length; i++) { - var topGroup = topGroups[i]; - - if(topGroup.childNodes.length) svg.node().appendChild(topGroup); - } - } - - // remove draglayer for Adobe Illustrator compatibility - if(fullLayout._draggers) { - fullLayout._draggers.remove(); - } - - // in case the svg element had an explicit background color, remove this - // we want the rect to get the color so it's the right size; svg bg will - // fill whatever container it's displayed in regardless of plot size. - svg.node().style.background = ''; - - svg.selectAll('text') - .attr({'data-unformatted': null, 'data-math': null}) - .each(function() { - var txt = d3.select(this); - - // hidden text is pre-formatting mathjax, the browser ignores it - // but in a static plot it's useless and it can confuse batik - // we've tried to standardize on display:none but make sure we still - // catch visibility:hidden if it ever arises - if(this.style.visibility === 'hidden' || this.style.display === 'none') { - txt.remove(); - return; - } else { - // clear other visibility/display values to default - // to not potentially confuse non-browser SVG implementations - txt.style({visibility: null, display: null}); - } - - // Font family styles break things because of quotation marks, - // so we must remove them *after* the SVG DOM has been serialized - // to a string (browsers convert singles back) - var ff = this.style.fontFamily; - if(ff && ff.indexOf('"') !== -1) { - txt.style('font-family', ff.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); - } - }); - - svg.selectAll('.point, .scatterpts, .legendfill>path, .legendlines>path, .cbfill').each(function() { - var pt = d3.select(this); - - // similar to font family styles above, - // we must remove " after the SVG DOM has been serialized - var fill = this.style.fill; - if(fill && fill.indexOf('url(') !== -1) { - pt.style('fill', fill.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); - } - - var stroke = this.style.stroke; - if(stroke && stroke.indexOf('url(') !== -1) { - pt.style('stroke', stroke.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); - } - }); - - if(format === 'pdf' || format === 'eps') { - // these formats make the extra line MathJax adds around symbols look super thick in some cases - // it looks better if this is removed entirely. - svg.selectAll('#MathJax_SVG_glyphs path') - .attr('stroke-width', 0); - } - - // fix for IE namespacing quirk? - // http://stackoverflow.com/questions/19610089/unwanted-namespaces-on-svg-markup-when-using-xmlserializer-in-javascript-with-ie - svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns', xmlnsNamespaces.svg); - svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns:xlink', xmlnsNamespaces.xlink); - - if(format === 'svg' && scale) { - svg.attr('width', scale * width); - svg.attr('height', scale * height); - svg.attr('viewBox', '0 0 ' + width + ' ' + height); - } - - var s = new window.XMLSerializer().serializeToString(svg.node()); - s = htmlEntityDecode(s); - s = xmlEntityEncode(s); - - // Fix quotations around font strings and gradient URLs - s = s.replace(DUMMY_REGEX, '\''); - - // IE is very strict, so we will need to clean - // svg with the following regex - // yes this is messy, but do not know a better way - // Even with this IE will not work due to tainted canvas - // see https://github.com/kangax/fabric.js/issues/1957 - // http://stackoverflow.com/questions/18112047/canvas-todataurl-working-in-all-browsers-except-ie10 - // Leave here just in case the CORS/tainted IE issue gets resolved - if(Lib.isIE()) { - // replace double quote with single quote - s = s.replace(/"/gi, '\''); - // url in svg are single quoted - // since we changed double to single - // we'll need to change these to double-quoted - s = s.replace(/(\('#)([^']*)('\))/gi, '(\"#$2\")'); - // font names with spaces will be escaped single-quoted - // we'll need to change these to double-quoted - s = s.replace(/(\\')/gi, '\"'); - } - - return s; -}; - -},{"../components/color":593,"../components/drawing":614,"../constants/xmlns_namespaces":696,"../lib":719,"d3":163}],856:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -// arrayOk attributes, merge them into calcdata array -module.exports = function arraysToCalcdata(cd, trace) { - for(var i = 0; i < cd.length; i++) cd[i].i = i; - - Lib.mergeArray(trace.text, cd, 'tx'); - Lib.mergeArray(trace.hovertext, cd, 'htx'); - - var marker = trace.marker; - if(marker) { - Lib.mergeArray(marker.opacity, cd, 'mo', true); - Lib.mergeArray(marker.color, cd, 'mc'); - - var markerLine = marker.line; - if(markerLine) { - Lib.mergeArray(markerLine.color, cd, 'mlc'); - Lib.mergeArrayCastPositive(markerLine.width, cd, 'mlw'); - } - } -}; - -},{"../../lib":719}],857:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterAttrs = _dereq_('../scatter/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var fontAttrs = _dereq_('../../plots/font_attributes'); -var constants = _dereq_('./constants.js'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var textFontAttrs = fontAttrs({ - editType: 'calc', - arrayOk: true, - colorEditType: 'style', - -}); - -var scatterMarkerAttrs = scatterAttrs.marker; -var scatterMarkerLineAttrs = scatterMarkerAttrs.line; - -var markerLineWidth = extendFlat({}, - scatterMarkerLineAttrs.width, { dflt: 0 }); - -var markerLine = extendFlat({ - width: markerLineWidth, - editType: 'calc' -}, colorScaleAttrs('marker.line')); - -var marker = extendFlat({ - line: markerLine, - editType: 'calc' -}, colorScaleAttrs('marker'), { - opacity: { - valType: 'number', - arrayOk: true, - dflt: 1, - min: 0, - max: 1, - - editType: 'style', - - } -}); - -module.exports = { - x: scatterAttrs.x, - x0: scatterAttrs.x0, - dx: scatterAttrs.dx, - y: scatterAttrs.y, - y0: scatterAttrs.y0, - dy: scatterAttrs.dy, - - text: scatterAttrs.text, - hovertext: scatterAttrs.hovertext, - hovertemplate: hovertemplateAttrs({}, { - keys: constants.eventDataKeys - }), - - textposition: { - valType: 'enumerated', - - values: ['inside', 'outside', 'auto', 'none'], - dflt: 'none', - arrayOk: true, - editType: 'calc', - - }, - - insidetextanchor: { - valType: 'enumerated', - values: ['end', 'middle', 'start'], - dflt: 'end', - - editType: 'plot', - - }, - - textangle: { - valType: 'angle', - dflt: 'auto', - - editType: 'plot', - - }, - - textfont: extendFlat({}, textFontAttrs, { - - }), - - insidetextfont: extendFlat({}, textFontAttrs, { - - }), - - outsidetextfont: extendFlat({}, textFontAttrs, { - - }), - - constraintext: { - valType: 'enumerated', - values: ['inside', 'outside', 'both', 'none'], - - dflt: 'both', - editType: 'calc', - - }, - - cliponaxis: extendFlat({}, scatterAttrs.cliponaxis, { - - }), - - orientation: { - valType: 'enumerated', - - values: ['v', 'h'], - editType: 'calc+clearAxisTypes', - - }, - - base: { - valType: 'any', - dflt: null, - arrayOk: true, - - editType: 'calc', - - }, - - offset: { - valType: 'number', - dflt: null, - arrayOk: true, - - editType: 'calc', - - }, - - width: { - valType: 'number', - dflt: null, - min: 0, - arrayOk: true, - - editType: 'calc', - - }, - - marker: marker, - - offsetgroup: { - valType: 'string', - - dflt: '', - editType: 'calc', - - }, - alignmentgroup: { - valType: 'string', - - dflt: '', - editType: 'calc', - - }, - - selected: { - marker: { - opacity: scatterAttrs.selected.marker.opacity, - color: scatterAttrs.selected.marker.color, - editType: 'style' - }, - textfont: scatterAttrs.selected.textfont, - editType: 'style' - }, - unselected: { - marker: { - opacity: scatterAttrs.unselected.marker.opacity, - color: scatterAttrs.unselected.marker.color, - editType: 'style' - }, - textfont: scatterAttrs.unselected.textfont, - editType: 'style' - }, - - r: scatterAttrs.r, - t: scatterAttrs.t, - - _deprecated: { - bardir: { - valType: 'enumerated', - - editType: 'calc', - values: ['v', 'h'], - - } - } -}; - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/font_attributes":793,"../scatter/attributes":1112,"./constants.js":859}],858:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale; -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); -var arraysToCalcdata = _dereq_('./arrays_to_calcdata'); -var calcSelection = _dereq_('../scatter/calc_selection'); - -module.exports = function calc(gd, trace) { - var xa = Axes.getFromId(gd, trace.xaxis || 'x'); - var ya = Axes.getFromId(gd, trace.yaxis || 'y'); - var size, pos; - - if(trace.orientation === 'h') { - size = xa.makeCalcdata(trace, 'x'); - pos = ya.makeCalcdata(trace, 'y'); - } else { - size = ya.makeCalcdata(trace, 'y'); - pos = xa.makeCalcdata(trace, 'x'); - } - - // create the "calculated data" to plot - var serieslen = Math.min(pos.length, size.length); - var cd = new Array(serieslen); - - // set position and size - for(var i = 0; i < serieslen; i++) { - cd[i] = { p: pos[i], s: size[i] }; - - if(trace.ids) { - cd[i].id = String(trace.ids[i]); - } - } - - // auto-z and autocolorscale if applicable - if(hasColorscale(trace, 'marker')) { - colorscaleCalc(gd, trace, { - vals: trace.marker.color, - containerStr: 'marker', - cLetter: 'c' - }); - } - if(hasColorscale(trace, 'marker.line')) { - colorscaleCalc(gd, trace, { - vals: trace.marker.line.color, - containerStr: 'marker.line', - cLetter: 'c' - }); - } - - arraysToCalcdata(cd, trace); - calcSelection(cd, trace); - - return cd; -}; - -},{"../../components/colorscale/calc":601,"../../components/colorscale/helpers":604,"../../plots/cartesian/axes":767,"../scatter/calc_selection":1114,"./arrays_to_calcdata":856}],859:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = { - eventDataKeys: [] -}; - -},{}],860:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -var Registry = _dereq_('../../registry'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var getAxisGroup = _dereq_('../../plots/cartesian/axis_ids').getAxisGroup; -var Sieve = _dereq_('./sieve.js'); - -/* - * Bar chart stacking/grouping positioning and autoscaling calculations - * for each direction separately calculate the ranges and positions - * note that this handles histograms too - * now doing this one subplot at a time - */ - -function crossTraceCalc(gd, plotinfo) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - var fullLayout = gd._fullLayout; - var fullTraces = gd._fullData; - var calcTraces = gd.calcdata; - var calcTracesHorz = []; - var calcTracesVert = []; - - for(var i = 0; i < fullTraces.length; i++) { - var fullTrace = fullTraces[i]; - if( - fullTrace.visible === true && - Registry.traceIs(fullTrace, 'bar') && - fullTrace.xaxis === xa._id && - fullTrace.yaxis === ya._id - ) { - if(fullTrace.orientation === 'h') { - calcTracesHorz.push(calcTraces[i]); - } else { - calcTracesVert.push(calcTraces[i]); - } - } - } - - var opts = { - mode: fullLayout.barmode, - norm: fullLayout.barnorm, - gap: fullLayout.bargap, - groupgap: fullLayout.bargroupgap - }; - - setGroupPositions(gd, xa, ya, calcTracesVert, opts); - setGroupPositions(gd, ya, xa, calcTracesHorz, opts); -} - -function setGroupPositions(gd, pa, sa, calcTraces, opts) { - if(!calcTraces.length) return; - - var excluded; - var included; - var i, calcTrace, fullTrace; - - initBase(sa, calcTraces); - - switch(opts.mode) { - case 'overlay': - setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts); - break; - - case 'group': - // exclude from the group those traces for which the user set an offset - excluded = []; - included = []; - for(i = 0; i < calcTraces.length; i++) { - calcTrace = calcTraces[i]; - fullTrace = calcTrace[0].trace; - - if(fullTrace.offset === undefined) included.push(calcTrace); - else excluded.push(calcTrace); - } - - if(included.length) { - setGroupPositionsInGroupMode(gd, pa, sa, included, opts); - } - if(excluded.length) { - setGroupPositionsInOverlayMode(pa, sa, excluded, opts); - } - break; - - case 'stack': - case 'relative': - // exclude from the stack those traces for which the user set a base - excluded = []; - included = []; - for(i = 0; i < calcTraces.length; i++) { - calcTrace = calcTraces[i]; - fullTrace = calcTrace[0].trace; - - if(fullTrace.base === undefined) included.push(calcTrace); - else excluded.push(calcTrace); - } - - if(included.length) { - setGroupPositionsInStackOrRelativeMode(gd, pa, sa, included, opts); - } - if(excluded.length) { - setGroupPositionsInOverlayMode(pa, sa, excluded, opts); - } - break; - } - - collectExtents(calcTraces, pa); -} - -function initBase(sa, calcTraces) { - var i, j; - - for(i = 0; i < calcTraces.length; i++) { - var cd = calcTraces[i]; - var trace = cd[0].trace; - var base = (trace.type === 'funnel') ? trace._base : trace.base; - var b; - - // not sure if it really makes sense to have dates for bar size data... - // ideally if we want to make gantt charts or something we'd treat - // the actual size (trace.x or y) as time delta but base as absolute - // time. But included here for completeness. - var scalendar = trace.orientation === 'h' ? trace.xcalendar : trace.ycalendar; - - // 'base' on categorical axes makes no sense - var d2c = sa.type === 'category' || sa.type === 'multicategory' ? - function() { return null; } : - sa.d2c; - - if(isArrayOrTypedArray(base)) { - for(j = 0; j < Math.min(base.length, cd.length); j++) { - b = d2c(base[j], 0, scalendar); - if(isNumeric(b)) { - cd[j].b = +b; - cd[j].hasB = 1; - } else cd[j].b = 0; - } - for(; j < cd.length; j++) { - cd[j].b = 0; - } - } else { - b = d2c(base, 0, scalendar); - var hasBase = isNumeric(b); - b = hasBase ? b : 0; - for(j = 0; j < cd.length; j++) { - cd[j].b = b; - if(hasBase) cd[j].hasB = 1; - } - } - } -} - -function setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts) { - // update position axis and set bar offsets and widths - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - - var sieve = new Sieve([calcTrace], { - sepNegVal: false, - overlapNoMerge: !opts.norm - }); - - // set bar offsets and widths, and update position axis - setOffsetAndWidth(pa, sieve, opts); - - // set bar bases and sizes, and update size axis - // - // (note that `setGroupPositionsInOverlayMode` handles the case barnorm - // is defined, because this function is also invoked for traces that - // can't be grouped or stacked) - if(opts.norm) { - sieveBars(sieve); - normalizeBars(sa, sieve, opts); - } else { - setBaseAndTop(sa, sieve); - } - } -} - -function setGroupPositionsInGroupMode(gd, pa, sa, calcTraces, opts) { - var sieve = new Sieve(calcTraces, { - sepNegVal: false, - overlapNoMerge: !opts.norm - }); - - // set bar offsets and widths, and update position axis - setOffsetAndWidthInGroupMode(gd, pa, sieve, opts); - - // relative-stack bars within the same trace that would otherwise - // be hidden - unhideBarsWithinTrace(sieve); - - // set bar bases and sizes, and update size axis - if(opts.norm) { - sieveBars(sieve); - normalizeBars(sa, sieve, opts); - } else { - setBaseAndTop(sa, sieve); - } -} - -function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces, opts) { - var sieve = new Sieve(calcTraces, { - sepNegVal: opts.mode === 'relative', - overlapNoMerge: !(opts.norm || opts.mode === 'stack' || opts.mode === 'relative') - }); - - // set bar offsets and widths, and update position axis - setOffsetAndWidth(pa, sieve, opts); - - // set bar bases and sizes, and update size axis - stackBars(sa, sieve, opts); - - // flag the outmost bar (for text display purposes) - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - - for(var j = 0; j < calcTrace.length; j++) { - var bar = calcTrace[j]; - - if(bar.s !== BADNUM) { - var isOutmostBar = ((bar.b + bar.s) === sieve.get(bar.p, bar.s)); - if(isOutmostBar) bar._outmost = true; - } - } - } - - // Note that marking the outmost bars has to be done - // before `normalizeBars` changes `bar.b` and `bar.s`. - if(opts.norm) normalizeBars(sa, sieve, opts); -} - -function setOffsetAndWidth(pa, sieve, opts) { - var minDiff = sieve.minDiff; - var calcTraces = sieve.traces; - - // set bar offsets and widths - var barGroupWidth = minDiff * (1 - opts.gap); - var barWidthPlusGap = barGroupWidth; - var barWidth = barWidthPlusGap * (1 - (opts.groupgap || 0)); - - // computer bar group center and bar offset - var offsetFromCenter = -barWidth / 2; - - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - var t = calcTrace[0].t; - - // store bar width and offset for this trace - t.barwidth = barWidth; - t.poffset = offsetFromCenter; - t.bargroupwidth = barGroupWidth; - t.bardelta = minDiff; - } - - // stack bars that only differ by rounding - sieve.binWidth = calcTraces[0][0].t.barwidth / 100; - - // if defined, apply trace offset and width - applyAttributes(sieve); - - // store the bar center in each calcdata item - setBarCenterAndWidth(pa, sieve); - - // update position axes - updatePositionAxis(pa, sieve); -} - -function setOffsetAndWidthInGroupMode(gd, pa, sieve, opts) { - var fullLayout = gd._fullLayout; - var positions = sieve.positions; - var distinctPositions = sieve.distinctPositions; - var minDiff = sieve.minDiff; - var calcTraces = sieve.traces; - var nTraces = calcTraces.length; - - // if there aren't any overlapping positions, - // let them have full width even if mode is group - var overlap = (positions.length !== distinctPositions.length); - var barGroupWidth = minDiff * (1 - opts.gap); - - var groupId = getAxisGroup(fullLayout, pa._id) + calcTraces[0][0].trace.orientation; - var alignmentGroups = fullLayout._alignmentOpts[groupId] || {}; - - for(var i = 0; i < nTraces; i++) { - var calcTrace = calcTraces[i]; - var trace = calcTrace[0].trace; - - var alignmentGroupOpts = alignmentGroups[trace.alignmentgroup] || {}; - var nOffsetGroups = Object.keys(alignmentGroupOpts.offsetGroups || {}).length; - - var barWidthPlusGap; - if(nOffsetGroups) { - barWidthPlusGap = barGroupWidth / nOffsetGroups; - } else { - barWidthPlusGap = overlap ? barGroupWidth / nTraces : barGroupWidth; - } - - var barWidth = barWidthPlusGap * (1 - (opts.groupgap || 0)); - - var offsetFromCenter; - if(nOffsetGroups) { - offsetFromCenter = ((2 * trace._offsetIndex + 1 - nOffsetGroups) * barWidthPlusGap - barWidth) / 2; - } else { - offsetFromCenter = overlap ? - ((2 * i + 1 - nTraces) * barWidthPlusGap - barWidth) / 2 : - -barWidth / 2; - } - - var t = calcTrace[0].t; - t.barwidth = barWidth; - t.poffset = offsetFromCenter; - t.bargroupwidth = barGroupWidth; - t.bardelta = minDiff; - } - - // stack bars that only differ by rounding - sieve.binWidth = calcTraces[0][0].t.barwidth / 100; - - // if defined, apply trace width - applyAttributes(sieve); - - // store the bar center in each calcdata item - setBarCenterAndWidth(pa, sieve); - - // update position axes - updatePositionAxis(pa, sieve, overlap); -} - -function applyAttributes(sieve) { - var calcTraces = sieve.traces; - var i, j; - - for(i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - var calcTrace0 = calcTrace[0]; - var fullTrace = calcTrace0.trace; - var t = calcTrace0.t; - var offset = fullTrace._offset || fullTrace.offset; - var initialPoffset = t.poffset; - var newPoffset; - - if(isArrayOrTypedArray(offset)) { - // if offset is an array, then clone it into t.poffset. - newPoffset = Array.prototype.slice.call(offset, 0, calcTrace.length); - - // guard against non-numeric items - for(j = 0; j < newPoffset.length; j++) { - if(!isNumeric(newPoffset[j])) { - newPoffset[j] = initialPoffset; - } - } - - // if the length of the array is too short, - // then extend it with the initial value of t.poffset - for(j = newPoffset.length; j < calcTrace.length; j++) { - newPoffset.push(initialPoffset); - } - - t.poffset = newPoffset; - } else if(offset !== undefined) { - t.poffset = offset; - } - - var width = fullTrace._width || fullTrace.width; - var initialBarwidth = t.barwidth; - - if(isArrayOrTypedArray(width)) { - // if width is an array, then clone it into t.barwidth. - var newBarwidth = Array.prototype.slice.call(width, 0, calcTrace.length); - - // guard against non-numeric items - for(j = 0; j < newBarwidth.length; j++) { - if(!isNumeric(newBarwidth[j])) newBarwidth[j] = initialBarwidth; - } - - // if the length of the array is too short, - // then extend it with the initial value of t.barwidth - for(j = newBarwidth.length; j < calcTrace.length; j++) { - newBarwidth.push(initialBarwidth); - } - - t.barwidth = newBarwidth; - - // if user didn't set offset, - // then correct t.poffset to ensure bars remain centered - if(offset === undefined) { - newPoffset = []; - for(j = 0; j < calcTrace.length; j++) { - newPoffset.push( - initialPoffset + (initialBarwidth - newBarwidth[j]) / 2 - ); - } - t.poffset = newPoffset; - } - } else if(width !== undefined) { - t.barwidth = width; - - // if user didn't set offset, - // then correct t.poffset to ensure bars remain centered - if(offset === undefined) { - t.poffset = initialPoffset + (initialBarwidth - width) / 2; - } - } - } -} - -function setBarCenterAndWidth(pa, sieve) { - var calcTraces = sieve.traces; - var pLetter = getAxisLetter(pa); - - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - var t = calcTrace[0].t; - var poffset = t.poffset; - var poffsetIsArray = Array.isArray(poffset); - var barwidth = t.barwidth; - var barwidthIsArray = Array.isArray(barwidth); - - for(var j = 0; j < calcTrace.length; j++) { - var calcBar = calcTrace[j]; - - // store the actual bar width and position, for use by hover - var width = calcBar.w = barwidthIsArray ? barwidth[j] : barwidth; - calcBar[pLetter] = calcBar.p + (poffsetIsArray ? poffset[j] : poffset) + width / 2; - } - } -} - -function updatePositionAxis(pa, sieve, allowMinDtick) { - var calcTraces = sieve.traces; - var minDiff = sieve.minDiff; - var vpad = minDiff / 2; - - Axes.minDtick(pa, sieve.minDiff, sieve.distinctPositions[0], allowMinDtick); - - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - var calcTrace0 = calcTrace[0]; - var fullTrace = calcTrace0.trace; - var pts = []; - var bar, l, r, j; - - for(j = 0; j < calcTrace.length; j++) { - bar = calcTrace[j]; - l = bar.p - vpad; - r = bar.p + vpad; - pts.push(l, r); - } - - if(fullTrace.width || fullTrace.offset) { - var t = calcTrace0.t; - var poffset = t.poffset; - var barwidth = t.barwidth; - var poffsetIsArray = Array.isArray(poffset); - var barwidthIsArray = Array.isArray(barwidth); - - for(j = 0; j < calcTrace.length; j++) { - bar = calcTrace[j]; - var calcBarOffset = poffsetIsArray ? poffset[j] : poffset; - var calcBarWidth = barwidthIsArray ? barwidth[j] : barwidth; - l = bar.p + calcBarOffset; - r = l + calcBarWidth; - pts.push(l, r); - } - } - - fullTrace._extremes[pa._id] = Axes.findExtremes(pa, pts, {padded: false}); - } -} - -// store these bar bases and tops in calcdata -// and make sure the size axis includes zero, -// along with the bases and tops of each bar. -function setBaseAndTop(sa, sieve) { - var calcTraces = sieve.traces; - var sLetter = getAxisLetter(sa); - - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - var fullTrace = calcTrace[0].trace; - var pts = []; - var allBaseAboveZero = true; - - for(var j = 0; j < calcTrace.length; j++) { - var bar = calcTrace[j]; - var base = bar.b; - var top = base + bar.s; - - bar[sLetter] = top; - pts.push(top); - if(bar.hasB) pts.push(base); - - if(!bar.hasB || !(bar.b > 0 && bar.s > 0)) { - allBaseAboveZero = false; - } - } - - fullTrace._extremes[sa._id] = Axes.findExtremes(sa, pts, { - tozero: !allBaseAboveZero, - padded: true - }); - } -} - -function stackBars(sa, sieve, opts) { - var sLetter = getAxisLetter(sa); - var calcTraces = sieve.traces; - var calcTrace; - var fullTrace; - var isFunnel; - var i, j; - var bar; - - for(i = 0; i < calcTraces.length; i++) { - calcTrace = calcTraces[i]; - fullTrace = calcTrace[0].trace; - - if(fullTrace.type === 'funnel') { - for(j = 0; j < calcTrace.length; j++) { - bar = calcTrace[j]; - - if(bar.s !== BADNUM) { - // create base of funnels - sieve.put(bar.p, -0.5 * bar.s); - } - } - } - } - - for(i = 0; i < calcTraces.length; i++) { - calcTrace = calcTraces[i]; - fullTrace = calcTrace[0].trace; - - isFunnel = (fullTrace.type === 'funnel'); - - var pts = []; - - for(j = 0; j < calcTrace.length; j++) { - bar = calcTrace[j]; - - if(bar.s !== BADNUM) { - // stack current bar and get previous sum - var value; - if(isFunnel) { - value = bar.s; - } else { - value = bar.s + bar.b; - } - - var base = sieve.put(bar.p, value); - - var top = base + value; - - // store the bar base and top in each calcdata item - bar.b = base; - bar[sLetter] = top; - - if(!opts.norm) { - pts.push(top); - if(bar.hasB) { - pts.push(base); - } - } - } - } - - // if barnorm is set, let normalizeBars update the axis range - if(!opts.norm) { - fullTrace._extremes[sa._id] = Axes.findExtremes(sa, pts, { - // N.B. we don't stack base with 'base', - // so set tozero:true always! - tozero: true, - padded: true - }); - } - } -} - -function sieveBars(sieve) { - var calcTraces = sieve.traces; - - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - - for(var j = 0; j < calcTrace.length; j++) { - var bar = calcTrace[j]; - - if(bar.s !== BADNUM) { - sieve.put(bar.p, bar.b + bar.s); - } - } - } -} - -function unhideBarsWithinTrace(sieve) { - var calcTraces = sieve.traces; - - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - var fullTrace = calcTrace[0].trace; - - if(fullTrace.base === undefined) { - var inTraceSieve = new Sieve([calcTrace], { - sepNegVal: true, - overlapNoMerge: true - }); - - for(var j = 0; j < calcTrace.length; j++) { - var bar = calcTrace[j]; - - if(bar.p !== BADNUM) { - // stack current bar and get previous sum - var base = inTraceSieve.put(bar.p, bar.b + bar.s); - - // if previous sum if non-zero, this means: - // multiple bars have same starting point are potentially hidden, - // shift them vertically so that all bars are visible by default - if(base) bar.b = base; - } - } - } - } -} - -// Note: -// -// normalizeBars requires that either sieveBars or stackBars has been -// previously invoked. -function normalizeBars(sa, sieve, opts) { - var calcTraces = sieve.traces; - var sLetter = getAxisLetter(sa); - var sTop = opts.norm === 'fraction' ? 1 : 100; - var sTiny = sTop / 1e9; // in case of rounding error in sum - var sMin = sa.l2c(sa.c2l(0)); - var sMax = opts.mode === 'stack' ? sTop : sMin; - - function needsPadding(v) { - return ( - isNumeric(sa.c2l(v)) && - ((v < sMin - sTiny) || (v > sMax + sTiny) || !isNumeric(sMin)) - ); - } - - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - var fullTrace = calcTrace[0].trace; - var pts = []; - var allBaseAboveZero = true; - var padded = false; - - for(var j = 0; j < calcTrace.length; j++) { - var bar = calcTrace[j]; - - if(bar.s !== BADNUM) { - var scale = Math.abs(sTop / sieve.get(bar.p, bar.s)); - bar.b *= scale; - bar.s *= scale; - - var base = bar.b; - var top = base + bar.s; - - bar[sLetter] = top; - pts.push(top); - padded = padded || needsPadding(top); - - if(bar.hasB) { - pts.push(base); - padded = padded || needsPadding(base); - } - - if(!bar.hasB || !(bar.b > 0 && bar.s > 0)) { - allBaseAboveZero = false; - } - } - } - - fullTrace._extremes[sa._id] = Axes.findExtremes(sa, pts, { - tozero: !allBaseAboveZero, - padded: padded - }); - } -} - -// find the full position span of bars at each position -// for use by hover, to ensure labels move in if bars are -// narrower than the space they're in. -// run once per trace group (subplot & direction) and -// the same mapping is attached to all calcdata traces -function collectExtents(calcTraces, pa) { - var pLetter = getAxisLetter(pa); - var extents = {}; - var i, j, cd; - - var pMin = Infinity; - var pMax = -Infinity; - - for(i = 0; i < calcTraces.length; i++) { - cd = calcTraces[i]; - for(j = 0; j < cd.length; j++) { - var p = cd[j].p; - if(isNumeric(p)) { - pMin = Math.min(pMin, p); - pMax = Math.max(pMax, p); - } - } - } - - // this is just for positioning of hover labels, and nobody will care if - // the label is 1px too far out; so round positions to 1/10K in case - // position values don't exactly match from trace to trace - var roundFactor = 10000 / (pMax - pMin); - var round = extents.round = function(p) { - return String(Math.round(roundFactor * (p - pMin))); - }; - - for(i = 0; i < calcTraces.length; i++) { - cd = calcTraces[i]; - cd[0].t.extents = extents; - - var poffset = cd[0].t.poffset; - var poffsetIsArray = Array.isArray(poffset); - - for(j = 0; j < cd.length; j++) { - var di = cd[j]; - var p0 = di[pLetter] - di.w / 2; - - if(isNumeric(p0)) { - var p1 = di[pLetter] + di.w / 2; - var pVal = round(di.p); - if(extents[pVal]) { - extents[pVal] = [Math.min(p0, extents[pVal][0]), Math.max(p1, extents[pVal][1])]; - } else { - extents[pVal] = [p0, p1]; - } - } - - di.p0 = di.p + (poffsetIsArray ? poffset[j] : poffset); - di.p1 = di.p0 + di.w; - di.s0 = di.b; - di.s1 = di.s0 + di.s; - } - } -} - -function getAxisLetter(ax) { - return ax._id.charAt(0); -} - -module.exports = { - crossTraceCalc: crossTraceCalc, - setGroupPositions: setGroupPositions -}; - -},{"../../constants/numerical":695,"../../lib":719,"../../plots/cartesian/axes":767,"../../plots/cartesian/axis_ids":770,"../../registry":847,"./sieve.js":869,"fast-isnumeric":225}],861:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); -var Registry = _dereq_('../../registry'); - -var handleXYDefaults = _dereq_('../scatter/xy_defaults'); -var handleStyleDefaults = _dereq_('./style_defaults'); -var getAxisGroup = _dereq_('../../plots/cartesian/axis_ids').getAxisGroup; -var attributes = _dereq_('./attributes'); - -var coerceFont = Lib.coerceFont; - -function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleXYDefaults(traceIn, traceOut, layout, coerce); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('orientation', (traceOut.x && !traceOut.y) ? 'h' : 'v'); - coerce('base'); - coerce('offset'); - coerce('width'); - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - var textposition = coerce('textposition'); - handleText(traceIn, traceOut, layout, coerce, textposition, { - moduleHasSelected: true, - moduleHasUnselected: true, - moduleHasConstrain: true, - moduleHasCliponaxis: true, - moduleHasTextangle: true, - moduleHasInsideanchor: true - }); - - handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout); - - var lineColor = (traceOut.marker.line || {}).color; - - // override defaultColor for error bars with defaultLine - var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'y'}); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'x', inherit: 'y'}); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -} - -function handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce) { - var orientation = traceOut.orientation; - // N.B. grouping is done across all trace types that support it - var posAxId = traceOut[{v: 'x', h: 'y'}[orientation] + 'axis']; - var groupId = getAxisGroup(fullLayout, posAxId) + orientation; - - var alignmentOpts = fullLayout._alignmentOpts || {}; - var alignmentgroup = coerce('alignmentgroup'); - - var alignmentGroups = alignmentOpts[groupId]; - if(!alignmentGroups) alignmentGroups = alignmentOpts[groupId] = {}; - - var alignmentGroupOpts = alignmentGroups[alignmentgroup]; - - if(alignmentGroupOpts) { - alignmentGroupOpts.traces.push(traceOut); - } else { - alignmentGroupOpts = alignmentGroups[alignmentgroup] = { - traces: [traceOut], - alignmentIndex: Object.keys(alignmentGroups).length, - offsetGroups: {} - }; - } - - var offsetgroup = coerce('offsetgroup'); - var offsetGroups = alignmentGroupOpts.offsetGroups; - var offsetGroupOpts = offsetGroups[offsetgroup]; - - if(offsetgroup) { - if(!offsetGroupOpts) { - offsetGroupOpts = offsetGroups[offsetgroup] = { - offsetIndex: Object.keys(offsetGroups).length - }; - } - - traceOut._offsetIndex = offsetGroupOpts.offsetIndex; - } -} - -function crossTraceDefaults(fullData, fullLayout) { - var traceIn, traceOut; - - function coerce(attr) { - return Lib.coerce(traceOut._input, traceOut, attributes, attr); - } - - if(fullLayout.barmode === 'group') { - for(var i = 0; i < fullData.length; i++) { - traceOut = fullData[i]; - - if(traceOut.type === 'bar') { - traceIn = traceOut._input; - handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); - } - } - } -} - -function handleText(traceIn, traceOut, layout, coerce, textposition, opts) { - opts = opts || {}; - var moduleHasSelected = !(opts.moduleHasSelected === false); - var moduleHasUnselected = !(opts.moduleHasUnselected === false); - var moduleHasConstrain = !(opts.moduleHasConstrain === false); - var moduleHasCliponaxis = !(opts.moduleHasCliponaxis === false); - var moduleHasTextangle = !(opts.moduleHasTextangle === false); - var moduleHasInsideanchor = !(opts.moduleHasInsideanchor === false); - - var hasBoth = Array.isArray(textposition) || textposition === 'auto'; - var hasInside = hasBoth || textposition === 'inside'; - var hasOutside = hasBoth || textposition === 'outside'; - - if(hasInside || hasOutside) { - var dfltFont = coerceFont(coerce, 'textfont', layout.font); - - // Note that coercing `insidetextfont` is always needed – - // even if `textposition` is `outside` for each trace – since - // an outside label can become an inside one, for example because - // of a bar being stacked on top of it. - var insideTextFontDefault = Lib.extendFlat({}, dfltFont); - var isTraceTextfontColorSet = traceIn.textfont && traceIn.textfont.color; - var isColorInheritedFromLayoutFont = !isTraceTextfontColorSet; - if(isColorInheritedFromLayoutFont) { - delete insideTextFontDefault.color; - } - coerceFont(coerce, 'insidetextfont', insideTextFontDefault); - - if(hasOutside) coerceFont(coerce, 'outsidetextfont', dfltFont); - - - if(moduleHasSelected) coerce('selected.textfont.color'); - if(moduleHasUnselected) coerce('unselected.textfont.color'); - if(moduleHasConstrain) coerce('constraintext'); - if(moduleHasCliponaxis) coerce('cliponaxis'); - if(moduleHasTextangle) coerce('textangle'); - } - - if(hasInside) { - if(moduleHasInsideanchor) coerce('insidetextanchor'); - } -} - -module.exports = { - supplyDefaults: supplyDefaults, - crossTraceDefaults: crossTraceDefaults, - handleGroupingDefaults: handleGroupingDefaults, - handleText: handleText -}; - -},{"../../components/color":593,"../../lib":719,"../../plots/cartesian/axis_ids":770,"../../registry":847,"../scatter/xy_defaults":1137,"./attributes":857,"./style_defaults":871}],862:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var tinycolor = _dereq_('tinycolor2'); -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; - -exports.coerceString = function(attributeDefinition, value, defaultValue) { - if(typeof value === 'string') { - if(value || !attributeDefinition.noBlank) return value; - } else if(typeof value === 'number' || value === true) { - if(!attributeDefinition.strict) return String(value); - } - - return (defaultValue !== undefined) ? - defaultValue : - attributeDefinition.dflt; -}; - -exports.coerceNumber = function(attributeDefinition, value, defaultValue) { - if(isNumeric(value)) { - value = +value; - - var min = attributeDefinition.min; - var max = attributeDefinition.max; - var isOutOfBounds = (min !== undefined && value < min) || - (max !== undefined && value > max); - - if(!isOutOfBounds) return value; - } - - return (defaultValue !== undefined) ? - defaultValue : - attributeDefinition.dflt; -}; - -exports.coerceColor = function(attributeDefinition, value, defaultValue) { - if(tinycolor(value).isValid()) return value; - - return (defaultValue !== undefined) ? - defaultValue : - attributeDefinition.dflt; -}; - -exports.coerceEnumerated = function(attributeDefinition, value, defaultValue) { - if(attributeDefinition.coerceNumber) value = +value; - - if(attributeDefinition.values.indexOf(value) !== -1) return value; - - return (defaultValue !== undefined) ? - defaultValue : - attributeDefinition.dflt; -}; - -exports.getValue = function(arrayOrScalar, index) { - var value; - if(!Array.isArray(arrayOrScalar)) value = arrayOrScalar; - else if(index < arrayOrScalar.length) value = arrayOrScalar[index]; - return value; -}; - -exports.getLineWidth = function(trace, di) { - var w = - (0 < di.mlw) ? di.mlw : - !isArrayOrTypedArray(trace.marker.line.width) ? trace.marker.line.width : - 0; - - return w; -}; - -},{"../../lib":719,"fast-isnumeric":225,"tinycolor2":537}],863:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Fx = _dereq_('../../components/fx'); -var Registry = _dereq_('../../registry'); -var Color = _dereq_('../../components/color'); - -var fillText = _dereq_('../../lib').fillText; -var getLineWidth = _dereq_('./helpers').getLineWidth; - -function hoverPoints(pointData, xval, yval, hovermode) { - var barPointData = hoverOnBars(pointData, xval, yval, hovermode); - - if(barPointData) { - var cd = barPointData.cd; - var trace = cd[0].trace; - var di = cd[barPointData.index]; - - barPointData.color = getTraceColor(trace, di); - Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, barPointData); - - return [barPointData]; - } -} - -function hoverOnBars(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var trace = cd[0].trace; - var t = cd[0].t; - var isClosest = (hovermode === 'closest'); - var isWaterfall = (trace.type === 'waterfall'); - var maxHoverDistance = pointData.maxHoverDistance; - var maxSpikeDistance = pointData.maxSpikeDistance; - - var posVal, sizeVal, posLetter, sizeLetter, dx, dy, pRangeCalc; - - function thisBarMinPos(di) { return di[posLetter] - di.w / 2; } - function thisBarMaxPos(di) { return di[posLetter] + di.w / 2; } - - var minPos = isClosest ? - thisBarMinPos : - function(di) { - /* - * In compare mode, accept a bar if you're on it *or* its group. - * Nearly always it's the group that matters, but in case the bar - * was explicitly set wider than its group we'd better accept the - * whole bar. - * - * use `bardelta` instead of `bargroupwidth` so we accept hover - * in the gap. That way hover doesn't flash on and off as you - * mouse over the plot in compare modes. - * In 'closest' mode though the flashing seems inevitable, - * without far more complex logic - */ - return Math.min(thisBarMinPos(di), di.p - t.bardelta / 2); - }; - - var maxPos = isClosest ? - thisBarMaxPos : - function(di) { - return Math.max(thisBarMaxPos(di), di.p + t.bardelta / 2); - }; - - function _positionFn(_minPos, _maxPos) { - // add a little to the pseudo-distance for wider bars, so that like scatter, - // if you are over two overlapping bars, the narrower one wins. - return Fx.inbox(_minPos - posVal, _maxPos - posVal, - maxHoverDistance + Math.min(1, Math.abs(_maxPos - _minPos) / pRangeCalc) - 1); - } - - function positionFn(di) { - return _positionFn(minPos(di), maxPos(di)); - } - - function thisBarPositionFn(di) { - return _positionFn(thisBarMinPos(di), thisBarMaxPos(di)); - } - - function sizeFn(di) { - var v = sizeVal; - var b = di.b; - var s = di[sizeLetter]; - - if(isWaterfall) { - s += Math.abs(di.rawS || 0); - } - - // add a gradient so hovering near the end of a - // bar makes it a little closer match - return Fx.inbox(b - v, s - v, maxHoverDistance + (s - v) / (s - b) - 1); - } - - if(trace.orientation === 'h') { - posVal = yval; - sizeVal = xval; - posLetter = 'y'; - sizeLetter = 'x'; - dx = sizeFn; - dy = positionFn; - } else { - posVal = xval; - sizeVal = yval; - posLetter = 'x'; - sizeLetter = 'y'; - dy = sizeFn; - dx = positionFn; - } - - var pa = pointData[posLetter + 'a']; - var sa = pointData[sizeLetter + 'a']; - - pRangeCalc = Math.abs(pa.r2c(pa.range[1]) - pa.r2c(pa.range[0])); - - function dxy(di) { return (dx(di) + dy(di)) / 2; } - var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy); - Fx.getClosest(cd, distfn, pointData); - - // skip the rest (for this trace) if we didn't find a close point - if(pointData.index === false) return; - - // if we get here and we're not in 'closest' mode, push min/max pos back - // onto the group - even though that means occasionally the mouse will be - // over the hover label. - if(!isClosest) { - minPos = function(di) { - return Math.min(thisBarMinPos(di), di.p - t.bargroupwidth / 2); - }; - maxPos = function(di) { - return Math.max(thisBarMaxPos(di), di.p + t.bargroupwidth / 2); - }; - } - - // the closest data point - var index = pointData.index; - var di = cd[index]; - - var size = (trace.base) ? di.b + di.s : di.s; - pointData[sizeLetter + '0'] = pointData[sizeLetter + '1'] = sa.c2p(di[sizeLetter], true); - pointData[sizeLetter + 'LabelVal'] = size; - - var extent = t.extents[t.extents.round(di.p)]; - pointData[posLetter + '0'] = pa.c2p(isClosest ? minPos(di) : extent[0], true); - pointData[posLetter + '1'] = pa.c2p(isClosest ? maxPos(di) : extent[1], true); - pointData[posLetter + 'LabelVal'] = di.p; - - // spikelines always want "closest" distance regardless of hovermode - pointData.spikeDistance = (sizeFn(di) + thisBarPositionFn(di)) / 2 + maxSpikeDistance - maxHoverDistance; - // they also want to point to the data value, regardless of where the label goes - // in case of bars shifted within groups - pointData[posLetter + 'Spike'] = pa.c2p(di.p, true); - - fillText(di, trace, pointData); - pointData.hovertemplate = trace.hovertemplate; - - return pointData; -} - -function getTraceColor(trace, di) { - var mc = di.mcc || trace.marker.color; - var mlc = di.mlcc || trace.marker.line.color; - var mlw = getLineWidth(trace, di); - - if(Color.opacity(mc)) return mc; - else if(Color.opacity(mlc) && mlw) return mlc; -} - -module.exports = { - hoverPoints: hoverPoints, - hoverOnBars: hoverOnBars, - getTraceColor: getTraceColor -}; - -},{"../../components/color":593,"../../components/fx":632,"../../lib":719,"../../registry":847,"./helpers":862}],864:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('./layout_attributes'), - supplyDefaults: _dereq_('./defaults').supplyDefaults, - crossTraceDefaults: _dereq_('./defaults').crossTraceDefaults, - supplyLayoutDefaults: _dereq_('./layout_defaults'), - calc: _dereq_('./calc'), - crossTraceCalc: _dereq_('./cross_trace_calc').crossTraceCalc, - colorbar: _dereq_('../scatter/marker_colorbar'), - arraysToCalcdata: _dereq_('./arrays_to_calcdata'), - plot: _dereq_('./plot').plot, - style: _dereq_('./style').style, - styleOnSelect: _dereq_('./style').styleOnSelect, - hoverPoints: _dereq_('./hover').hoverPoints, - selectPoints: _dereq_('./select'), - - moduleType: 'trace', - name: 'bar', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['bar-like', 'cartesian', 'svg', 'bar', 'oriented', 'errorBarsOK', 'showLegend', 'zoomScale'], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"../scatter/marker_colorbar":1129,"./arrays_to_calcdata":856,"./attributes":857,"./calc":858,"./cross_trace_calc":860,"./defaults":861,"./hover":863,"./layout_attributes":865,"./layout_defaults":866,"./plot":867,"./select":868,"./style":870}],865:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -module.exports = { - barmode: { - valType: 'enumerated', - values: ['stack', 'group', 'overlay', 'relative'], - dflt: 'group', - - editType: 'calc', - - }, - barnorm: { - valType: 'enumerated', - values: ['', 'fraction', 'percent'], - dflt: '', - - editType: 'calc', - - }, - bargap: { - valType: 'number', - min: 0, - max: 1, - - editType: 'calc', - - }, - bargroupgap: { - valType: 'number', - min: 0, - max: 1, - dflt: 0, - - editType: 'calc', - - } -}; - -},{}],866:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var Lib = _dereq_('../../lib'); - -var layoutAttributes = _dereq_('./layout_attributes'); - -module.exports = function(layoutIn, layoutOut, fullData) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - - var hasBars = false; - var shouldBeGapless = false; - var gappedAnyway = false; - var usedSubplots = {}; - - var mode = coerce('barmode'); - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - if(Registry.traceIs(trace, 'bar') && trace.visible) hasBars = true; - else continue; - - // if we have at least 2 grouped bar traces on the same subplot, - // we should default to a gap anyway, even if the data is histograms - if(mode === 'group') { - var subploti = trace.xaxis + trace.yaxis; - if(usedSubplots[subploti]) gappedAnyway = true; - usedSubplots[subploti] = true; - } - - if(trace.visible && trace.type === 'histogram') { - var pa = Axes.getFromId({_fullLayout: layoutOut}, - trace[trace.orientation === 'v' ? 'xaxis' : 'yaxis']); - if(pa.type !== 'category') shouldBeGapless = true; - } - } - - if(!hasBars) { - delete layoutOut.barmode; - return; - } - - if(mode !== 'overlay') coerce('barnorm'); - - coerce('bargap', (shouldBeGapless && !gappedAnyway) ? 0 : 0.2); - coerce('bargroupgap'); -}; - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../../registry":847,"./layout_attributes":865}],867:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); - -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var Registry = _dereq_('../../registry'); -var tickText = _dereq_('../../plots/cartesian/axes').tickText; - -var style = _dereq_('./style'); -var helpers = _dereq_('./helpers'); -var attributes = _dereq_('./attributes'); - -var attributeText = attributes.text; -var attributeTextPosition = attributes.textposition; - -// padding in pixels around text -var TEXTPAD = 3; - -function dirSign(a, b) { - return (a < b) ? 1 : -1; -} - -function getXY(di, xa, ya, isHorizontal) { - var s = []; - var p = []; - - var sAxis = isHorizontal ? xa : ya; - var pAxis = isHorizontal ? ya : xa; - - s[0] = sAxis.c2p(di.s0, true); - p[0] = pAxis.c2p(di.p0, true); - - s[1] = sAxis.c2p(di.s1, true); - p[1] = pAxis.c2p(di.p1, true); - - return isHorizontal ? [s, p] : [p, s]; -} - -function plot(gd, plotinfo, cdModule, traceLayer, opts) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - var fullLayout = gd._fullLayout; - - if(!opts) { - opts = { - mode: fullLayout.barmode, - norm: fullLayout.barmode, - gap: fullLayout.bargap, - groupgap: fullLayout.bargroupgap - }; - } - - var bartraces = Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) { - var plotGroup = d3.select(this); - var trace = cd[0].trace; - var isWaterfall = (trace.type === 'waterfall'); - var isFunnel = (trace.type === 'funnel'); - var isBar = (trace.type === 'bar'); - var shouldDisplayZeros = (isBar || isFunnel); - - var adjustPixel = 0; - if(isWaterfall && trace.connector.visible && trace.connector.mode === 'between') { - adjustPixel = trace.connector.line.width / 2; - } - - var isHorizontal = (trace.orientation === 'h'); - - var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points'); - - var bars = pointGroup.selectAll('g.point').data(Lib.identity); - - bars.enter().append('g') - .classed('point', true); - - bars.exit().remove(); - - bars.each(function(di, i) { - var bar = d3.select(this); - - // now display the bar - // clipped xf/yf (2nd arg true): non-positive - // log values go off-screen by plotwidth - // so you see them continue if you drag the plot - - var xy = getXY(di, xa, ya, isHorizontal); - - var x0 = xy[0][0]; - var x1 = xy[0][1]; - var y0 = xy[1][0]; - var y1 = xy[1][1]; - - var isBlank = ( - x0 === x1 || - y0 === y1 || - !isNumeric(x0) || - !isNumeric(x1) || - !isNumeric(y0) || - !isNumeric(y1) - ); - // display zeros if line.width > 0 - if(isBlank && shouldDisplayZeros && helpers.getLineWidth(trace, di) && (isHorizontal ? x1 - x0 === 0 : y1 - y0 === 0)) { - isBlank = false; - } - di.isBlank = isBlank; - - // in waterfall mode `between` we need to adjust bar end points to match the connector width - if(adjustPixel) { - if(isHorizontal) { - x0 -= dirSign(x0, x1) * adjustPixel; - x1 += dirSign(x0, x1) * adjustPixel; - } else { - y0 -= dirSign(y0, y1) * adjustPixel; - y1 += dirSign(y0, y1) * adjustPixel; - } - } - - var lw; - var mc; - - if(trace.type === 'waterfall') { - if(!isBlank) { - var cont = trace[di.dir].marker; - lw = cont.line.width; - mc = cont.color; - } - } else { - lw = helpers.getLineWidth(trace, di); - mc = di.mc || trace.marker.color; - } - - var offset = d3.round((lw / 2) % 1, 2); - - function roundWithLine(v) { - // if there are explicit gaps, don't round, - // it can make the gaps look crappy - return (opts.gap === 0 && opts.groupgap === 0) ? - d3.round(Math.round(v) - offset, 2) : v; - } - - function expandToVisible(v, vc) { - // if it's not in danger of disappearing entirely, - // round more precisely - return Math.abs(v - vc) >= 2 ? roundWithLine(v) : - // but if it's very thin, expand it so it's - // necessarily visible, even if it might overlap - // its neighbor - (v > vc ? Math.ceil(v) : Math.floor(v)); - } - - if(!gd._context.staticPlot) { - // if bars are not fully opaque or they have a line - // around them, round to integer pixels, mainly for - // safari so we prevent overlaps from its expansive - // pixelation. if the bars ARE fully opaque and have - // no line, expand to a full pixel to make sure we - // can see them - - var op = Color.opacity(mc); - var fixpx = (op < 1 || lw > 0.01) ? roundWithLine : expandToVisible; - x0 = fixpx(x0, x1); - x1 = fixpx(x1, x0); - y0 = fixpx(y0, y1); - y1 = fixpx(y1, y0); - } - - Lib.ensureSingle(bar, 'path') - .style('vector-effect', 'non-scaling-stroke') - .attr('d', isBlank ? 'M0,0Z' : 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z') - .call(Drawing.setClipUrl, plotinfo.layerClipId, gd); - - appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, opts); - - if(plotinfo.layerClipId) { - Drawing.hideOutsideRangePoint(di, bar.select('text'), xa, ya, trace.xcalendar, trace.ycalendar); - } - }); - - // lastly, clip points groups of `cliponaxis !== false` traces - // on `plotinfo._hasClipOnAxisFalse === true` subplots - var hasClipOnAxisFalse = trace.cliponaxis === false; - Drawing.setClipUrl(plotGroup, hasClipOnAxisFalse ? null : plotinfo.layerClipId, gd); - }); - - // error bars are on the top - Registry.getComponentMethod('errorbars', 'plot')(gd, bartraces, plotinfo); -} - -function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - var fullLayout = gd._fullLayout; - var textPosition; - - function appendTextNode(bar, text, textFont) { - var textSelection = Lib.ensureSingle(bar, 'text') - .text(text) - .attr({ - 'class': 'bartext bartext-' + textPosition, - transform: '', - 'text-anchor': 'middle', - // prohibit tex interpretation until we can handle - // tex and regular text together - 'data-notex': 1 - }) - .call(Drawing.font, textFont) - .call(svgTextUtils.convertToTspans, gd); - - return textSelection; - } - - // get trace attributes - var trace = calcTrace[0].trace; - var isHorizontal = (trace.orientation === 'h'); - - var text = getText(calcTrace, i, xa, ya); - textPosition = getTextPosition(trace, i); - - // compute text position - var inStackOrRelativeMode = - opts.mode === 'stack' || - opts.mode === 'relative'; - - var calcBar = calcTrace[i]; - var isOutmostBar = !inStackOrRelativeMode || calcBar._outmost; - - if(!text || - textPosition === 'none' || - ((calcBar.isBlank || x0 === x1 || y0 === y1) && ( - textPosition === 'auto' || - textPosition === 'inside'))) { - bar.select('text').remove(); - return; - } - - var layoutFont = fullLayout.font; - var barColor = style.getBarColor(calcTrace[i], trace); - var insideTextFont = style.getInsideTextFont(trace, i, layoutFont, barColor); - var outsideTextFont = style.getOutsideTextFont(trace, i, layoutFont); - - // Special case: don't use the c2p(v, true) value on log size axes, - // so that we can get correctly inside text scaling - var di = bar.datum(); - if(isHorizontal) { - if(xa.type === 'log' && di.s0 <= 0) { - if(xa.range[0] < xa.range[1]) { - x0 = 0; - } else { - x0 = xa._length; - } - } - } else { - if(ya.type === 'log' && di.s0 <= 0) { - if(ya.range[0] < ya.range[1]) { - y0 = ya._length; - } else { - y0 = 0; - } - } - } - - // padding excluded - var barWidth = Math.abs(x1 - x0) - 2 * TEXTPAD; - var barHeight = Math.abs(y1 - y0) - 2 * TEXTPAD; - - var textSelection; - var textBB; - var textWidth; - var textHeight; - - if(textPosition === 'outside') { - if(!isOutmostBar && !calcBar.hasB) textPosition = 'inside'; - } - - if(textPosition === 'auto') { - if(isOutmostBar) { - // draw text using insideTextFont and check if it fits inside bar - textPosition = 'inside'; - textSelection = appendTextNode(bar, text, insideTextFont); - - textBB = Drawing.bBox(textSelection.node()), - textWidth = textBB.width, - textHeight = textBB.height; - - var textHasSize = (textWidth > 0 && textHeight > 0); - var fitsInside = (textWidth <= barWidth && textHeight <= barHeight); - var fitsInsideIfRotated = (textWidth <= barHeight && textHeight <= barWidth); - var fitsInsideIfShrunk = (isHorizontal) ? - (barWidth >= textWidth * (barHeight / textHeight)) : - (barHeight >= textHeight * (barWidth / textWidth)); - - if(textHasSize && ( - fitsInside || - fitsInsideIfRotated || - fitsInsideIfShrunk) - ) { - textPosition = 'inside'; - } else { - textPosition = 'outside'; - textSelection.remove(); - textSelection = null; - } - } else { - textPosition = 'inside'; - } - } - - if(!textSelection) { - textSelection = appendTextNode(bar, text, - (textPosition === 'outside') ? - outsideTextFont : insideTextFont); - - textBB = Drawing.bBox(textSelection.node()), - textWidth = textBB.width, - textHeight = textBB.height; - - if(textWidth <= 0 || textHeight <= 0) { - textSelection.remove(); - return; - } - } - - // compute text transform - var transform, constrained; - if(textPosition === 'outside') { - constrained = - trace.constraintext === 'both' || - trace.constraintext === 'outside'; - - transform = getTransform(toMoveOutsideBar(x0, x1, y0, y1, textBB, { - isHorizontal: isHorizontal, - constrained: constrained, - angle: trace.textangle - })); - } else { - constrained = - trace.constraintext === 'both' || - trace.constraintext === 'inside'; - - transform = getTransform(toMoveInsideBar(x0, x1, y0, y1, textBB, { - isHorizontal: isHorizontal, - constrained: constrained, - angle: trace.textangle, - anchor: trace.insidetextanchor - })); - } - - textSelection.attr('transform', transform); -} - -function getRotateFromAngle(angle) { - return (angle === 'auto') ? 0 : angle; -} - -function toMoveInsideBar(x0, x1, y0, y1, textBB, opts) { - var isHorizontal = !!opts.isHorizontal; - var constrained = !!opts.constrained; - var angle = opts.angle || 0; - var anchor = opts.anchor || 0; - - var textWidth = textBB.width; - var textHeight = textBB.height; - var lx = Math.abs(x1 - x0); - var ly = Math.abs(y1 - y0); - - var textpad = ( - lx > (2 * TEXTPAD) && - ly > (2 * TEXTPAD) - ) ? TEXTPAD : 0; - - lx -= 2 * textpad; - ly -= 2 * textpad; - - var autoRotate = (angle === 'auto'); - var isAutoRotated = false; - if(autoRotate && - !(textWidth <= lx && textHeight <= ly) && - (textWidth > lx || textHeight > ly) && ( - !(textWidth > ly || textHeight > lx) || - ((textWidth < textHeight) !== (lx < ly)) - )) { - isAutoRotated = true; - } - - if(isAutoRotated) { - // don't rotate yet only swap bar width with height - var tmp = ly; - ly = lx; - lx = tmp; - } - - var rotate = getRotateFromAngle(angle); - var absSin = Math.abs(Math.sin(Math.PI / 180 * rotate)); - var absCos = Math.abs(Math.cos(Math.PI / 180 * rotate)); - - // compute and apply text padding - var dx = Math.max(lx * absCos, ly * absSin); - var dy = Math.max(lx * absSin, ly * absCos); - - var scale = (constrained) ? - Math.min(dx / textWidth, dy / textHeight) : - Math.max(absCos, absSin); - - scale = Math.min(1, scale); - - // compute text and target positions - var targetX = (x0 + x1) / 2; - var targetY = (y0 + y1) / 2; - - if(anchor !== 'middle') { // case of 'start' or 'end' - var targetWidth = scale * (isHorizontal !== isAutoRotated ? textHeight : textWidth); - var targetHeight = scale * (isHorizontal !== isAutoRotated ? textWidth : textHeight); - textpad += 0.5 * (targetWidth * absSin + targetHeight * absCos); - - if(isHorizontal) { - textpad *= dirSign(x0, x1); - targetX = (anchor === 'start') ? x0 + textpad : x1 - textpad; - } else { - textpad *= dirSign(y0, y1); - targetY = (anchor === 'start') ? y0 + textpad : y1 - textpad; - } - } - - var textX = (textBB.left + textBB.right) / 2; - var textY = (textBB.top + textBB.bottom) / 2; - - // lastly apply auto rotation - if(isAutoRotated) rotate += 90; - - return { - textX: textX, - textY: textY, - targetX: targetX, - targetY: targetY, - scale: scale, - rotate: rotate - }; -} - -function toMoveOutsideBar(x0, x1, y0, y1, textBB, opts) { - var isHorizontal = !!opts.isHorizontal; - var constrained = !!opts.constrained; - var angle = opts.angle || 0; - - var textWidth = textBB.width; - var textHeight = textBB.height; - var lx = Math.abs(x1 - x0); - var ly = Math.abs(y1 - y0); - - var textpad; - // Keep the padding so the text doesn't sit right against - // the bars, but don't factor it into barWidth - if(isHorizontal) { - textpad = (ly > 2 * TEXTPAD) ? TEXTPAD : 0; - } else { - textpad = (lx > 2 * TEXTPAD) ? TEXTPAD : 0; - } - - // compute rotate and scale - var scale = 1; - if(constrained) { - scale = (isHorizontal) ? - Math.min(1, ly / textHeight) : - Math.min(1, lx / textWidth); - } - - var rotate = getRotateFromAngle(angle); - var absSin = Math.abs(Math.sin(Math.PI / 180 * rotate)); - var absCos = Math.abs(Math.cos(Math.PI / 180 * rotate)); - - // compute text and target positions - var targetWidth = scale * (isHorizontal ? textHeight : textWidth); - var targetHeight = scale * (isHorizontal ? textWidth : textHeight); - textpad += 0.5 * (targetWidth * absSin + targetHeight * absCos); - - var targetX = (x0 + x1) / 2; - var targetY = (y0 + y1) / 2; - - if(isHorizontal) { - targetX = x1 - textpad * dirSign(x1, x0); - } else { - targetY = y1 + textpad * dirSign(y0, y1); - } - - var textX = (textBB.left + textBB.right) / 2; - var textY = (textBB.top + textBB.bottom) / 2; - - return { - textX: textX, - textY: textY, - targetX: targetX, - targetY: targetY, - scale: scale, - rotate: rotate - }; -} - -function getTransform(opts) { - var textX = opts.textX; - var textY = opts.textY; - var targetX = opts.targetX; - var targetY = opts.targetY; - var scale = opts.scale; - var rotate = opts.rotate; - - var transformScale; - var transformRotate; - var transformTranslate; - - if(scale < 1) transformScale = 'scale(' + scale + ') '; - else { - scale = 1; - transformScale = ''; - } - - transformRotate = (rotate) ? - 'rotate(' + rotate + ' ' + textX + ' ' + textY + ') ' : ''; - - // Note that scaling also affects the center of the text box - var translateX = (targetX - scale * textX); - var translateY = (targetY - scale * textY); - transformTranslate = 'translate(' + translateX + ' ' + translateY + ')'; - - return transformTranslate + transformScale + transformRotate; -} - -function getText(calcTrace, index, xa, ya) { - var trace = calcTrace[0].trace; - - var value; - if(!trace.textinfo) { - value = helpers.getValue(trace.text, index); - } else { - value = calcTextinfo(calcTrace, index, xa, ya); - } - - return helpers.coerceString(attributeText, value); -} - -function getTextPosition(trace, index) { - var value = helpers.getValue(trace.textposition, index); - return helpers.coerceEnumerated(attributeTextPosition, value); -} - -function calcTextinfo(calcTrace, index, xa, ya) { - var trace = calcTrace[0].trace; - var isHorizontal = (trace.orientation === 'h'); - var isWaterfall = (trace.type === 'waterfall'); - var isFunnel = (trace.type === 'funnel'); - - function formatLabel(u) { - var pAxis = isHorizontal ? ya : xa; - return tickText(pAxis, u, true).text; - } - - function formatNumber(v) { - var sAxis = isHorizontal ? xa : ya; - return tickText(sAxis, +v, true).text; - } - - var textinfo = trace.textinfo; - var cdi = calcTrace[index]; - - var parts = textinfo.split('+'); - var text = []; - var tx; - - var hasFlag = function(flag) { return parts.indexOf(flag) !== -1; }; - - if(hasFlag('label')) { - text.push(formatLabel(calcTrace[index].p)); - } - - if(hasFlag('text')) { - tx = Lib.castOption(trace, cdi.i, 'text'); - if(tx === 0 || tx) text.push(tx); - } - - if(isWaterfall) { - var delta = +cdi.rawS || cdi.s; - var final = cdi.v; - var initial = final - delta; - - if(hasFlag('initial')) text.push(formatNumber(initial)); - if(hasFlag('delta')) text.push(formatNumber(delta)); - if(hasFlag('final')) text.push(formatNumber(final)); - } - - if(isFunnel) { - if(hasFlag('value')) text.push(formatNumber(cdi.s)); - - var nPercent = 0; - if(hasFlag('percent initial')) nPercent++; - if(hasFlag('percent previous')) nPercent++; - if(hasFlag('percent total')) nPercent++; - - var hasMultiplePercents = nPercent > 1; - - if(hasFlag('percent initial')) { - tx = Lib.formatPercent(cdi.begR); - if(hasMultiplePercents) tx += ' of initial'; - text.push(tx); - } - if(hasFlag('percent previous')) { - tx = Lib.formatPercent(cdi.difR); - if(hasMultiplePercents) tx += ' of previous'; - text.push(tx); - } - if(hasFlag('percent total')) { - tx = Lib.formatPercent(cdi.sumR); - if(hasMultiplePercents) tx += ' of total'; - text.push(tx); - } - } - - return text.join('
'); -} - -module.exports = { - plot: plot, - getTransform: getTransform, - toMoveInsideBar: toMoveInsideBar, - toMoveOutsideBar: toMoveOutsideBar -}; - -},{"../../components/color":593,"../../components/drawing":614,"../../lib":719,"../../lib/svg_text_utils":743,"../../plots/cartesian/axes":767,"../../registry":847,"./attributes":857,"./helpers":862,"./style":870,"d3":163,"fast-isnumeric":225}],868:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function selectPoints(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var xa = searchInfo.xaxis; - var ya = searchInfo.yaxis; - var trace = cd[0].trace; - var isFunnel = (trace.type === 'funnel'); - var isHorizontal = (trace.orientation === 'h'); - var selection = []; - var i; - - if(selectionTester === false) { - // clear selection - for(i = 0; i < cd.length; i++) { - cd[i].selected = 0; - } - } else { - for(i = 0; i < cd.length; i++) { - var di = cd[i]; - var ct = 'ct' in di ? di.ct : getCentroid(di, xa, ya, isHorizontal, isFunnel); - - if(selectionTester.contains(ct, false, i, searchInfo)) { - selection.push({ - pointNumber: i, - x: xa.c2d(di.x), - y: ya.c2d(di.y) - }); - di.selected = 1; - } else { - di.selected = 0; - } - } - } - - return selection; -}; - -function getCentroid(d, xa, ya, isHorizontal, isFunnel) { - var x0 = xa.c2p(isHorizontal ? d.s0 : d.p0, true); - var x1 = xa.c2p(isHorizontal ? d.s1 : d.p1, true); - var y0 = ya.c2p(isHorizontal ? d.p0 : d.s0, true); - var y1 = ya.c2p(isHorizontal ? d.p1 : d.s1, true); - - if(isFunnel) { - return [(x0 + x1) / 2, (y0 + y1) / 2]; - } else { - if(isHorizontal) { - return [x1, (y0 + y1) / 2]; - } else { - return [(x0 + x1) / 2, y1]; - } - } -} - -},{}],869:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = Sieve; - -var distinctVals = _dereq_('../../lib').distinctVals; -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -/** - * Helper class to sieve data from traces into bins - * - * @class - * - * @param {Array} traces -* Array of calculated traces - * @param {object} opts - * - @param {boolean} [sepNegVal] - * If true, then split data at the same position into a bar - * for positive values and another for negative values - * - @param {boolean} [overlapNoMerge] - * If true, then don't merge overlapping bars into a single bar - */ -function Sieve(traces, opts) { - this.traces = traces; - this.sepNegVal = opts.sepNegVal; - this.overlapNoMerge = opts.overlapNoMerge; - - // for single-bin histograms - see histogram/calc - var width1 = Infinity; - - var positions = []; - for(var i = 0; i < traces.length; i++) { - var trace = traces[i]; - for(var j = 0; j < trace.length; j++) { - var bar = trace[j]; - if(bar.p !== BADNUM) positions.push(bar.p); - } - if(trace[0] && trace[0].width1) { - width1 = Math.min(trace[0].width1, width1); - } - } - this.positions = positions; - - var dv = distinctVals(positions); - this.distinctPositions = dv.vals; - if(dv.vals.length === 1 && width1 !== Infinity) this.minDiff = width1; - else this.minDiff = Math.min(dv.minDiff, width1); - - this.binWidth = this.minDiff; - - this.bins = {}; -} - -/** - * Sieve datum - * - * @method - * @param {number} position - * @param {number} value - * @returns {number} Previous bin value - */ -Sieve.prototype.put = function put(position, value) { - var label = this.getLabel(position, value); - var oldValue = this.bins[label] || 0; - - this.bins[label] = oldValue + value; - - return oldValue; -}; - -/** - * Get current bin value for a given datum - * - * @method - * @param {number} position Position of datum - * @param {number} [value] Value of datum - * (required if this.sepNegVal is true) - * @returns {number} Current bin value - */ -Sieve.prototype.get = function get(position, value) { - var label = this.getLabel(position, value); - return this.bins[label] || 0; -}; - -/** - * Get bin label for a given datum - * - * @method - * @param {number} position Position of datum - * @param {number} [value] Value of datum - * (required if this.sepNegVal is true) - * @returns {string} Bin label - * (prefixed with a 'v' if value is negative and this.sepNegVal is - * true; otherwise prefixed with '^') - */ -Sieve.prototype.getLabel = function getLabel(position, value) { - var prefix = (value < 0 && this.sepNegVal) ? 'v' : '^'; - var label = (this.overlapNoMerge) ? - position : - Math.round(position / this.binWidth); - return prefix + label; -}; - -},{"../../constants/numerical":695,"../../lib":719}],870:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); - -var attributes = _dereq_('./attributes'); -var attributeTextFont = attributes.textfont; -var attributeInsideTextFont = attributes.insidetextfont; -var attributeOutsideTextFont = attributes.outsidetextfont; -var helpers = _dereq_('./helpers'); - -function style(gd) { - var s = d3.select(gd).selectAll('g.barlayer').selectAll('g.trace'); - var barcount = s.size(); - var fullLayout = gd._fullLayout; - - // trace styling - s.style('opacity', function(d) { return d[0].trace.opacity; }) - - // for gapless (either stacked or neighboring grouped) bars use - // crispEdges to turn off antialiasing so an artificial gap - // isn't introduced. - .each(function(d) { - if((fullLayout.barmode === 'stack' && barcount > 1) || - (fullLayout.bargap === 0 && - fullLayout.bargroupgap === 0 && - !d[0].trace.marker.line.width)) { - d3.select(this).attr('shape-rendering', 'crispEdges'); - } - }); - - s.selectAll('g.points').each(function(d) { - var sel = d3.select(this); - var trace = d[0].trace; - stylePoints(sel, trace, gd); - }); - - Registry.getComponentMethod('errorbars', 'style')(s); -} - -function stylePoints(sel, trace, gd) { - Drawing.pointStyle(sel.selectAll('path'), trace, gd); - styleTextPoints(sel, trace, gd); -} - -function styleTextPoints(sel, trace, gd) { - sel.selectAll('text').each(function(d) { - var tx = d3.select(this); - var font = determineFont(tx, d, trace, gd); - Drawing.font(tx, font); - }); -} - -function styleOnSelect(gd, cd, sel) { - var trace = cd[0].trace; - - if(trace.selectedpoints) { - stylePointsInSelectionMode(sel, trace, gd); - } else { - stylePoints(sel, trace, gd); - Registry.getComponentMethod('errorbars', 'style')(sel); - } -} - -function stylePointsInSelectionMode(s, trace, gd) { - Drawing.selectedPointStyle(s.selectAll('path'), trace); - styleTextInSelectionMode(s.selectAll('text'), trace, gd); -} - -function styleTextInSelectionMode(txs, trace, gd) { - txs.each(function(d) { - var tx = d3.select(this); - var font; - - if(d.selected) { - font = Lib.extendFlat({}, determineFont(tx, d, trace, gd)); - - var selectedFontColor = trace.selected.textfont && trace.selected.textfont.color; - if(selectedFontColor) { - font.color = selectedFontColor; - } - - Drawing.font(tx, font); - } else { - Drawing.selectedTextStyle(tx, trace); - } - }); -} - -function determineFont(tx, d, trace, gd) { - var layoutFont = gd._fullLayout.font; - var textFont = trace.textfont; - - if(tx.classed('bartext-inside')) { - var barColor = getBarColor(d, trace); - textFont = getInsideTextFont(trace, d.i, layoutFont, barColor); - } else if(tx.classed('bartext-outside')) { - textFont = getOutsideTextFont(trace, d.i, layoutFont); - } - - return textFont; -} - -function getTextFont(trace, index, defaultValue) { - return getFontValue( - attributeTextFont, trace.textfont, index, defaultValue); -} - -function getInsideTextFont(trace, index, layoutFont, barColor) { - var defaultFont = getTextFont(trace, index, layoutFont); - - var wouldFallBackToLayoutFont = - (trace._input.textfont === undefined || trace._input.textfont.color === undefined) || - (Array.isArray(trace.textfont.color) && trace.textfont.color[index] === undefined); - if(wouldFallBackToLayoutFont) { - defaultFont = { - color: Color.contrast(barColor), - family: defaultFont.family, - size: defaultFont.size - }; - } - - return getFontValue( - attributeInsideTextFont, trace.insidetextfont, index, defaultFont); -} - -function getOutsideTextFont(trace, index, layoutFont) { - var defaultFont = getTextFont(trace, index, layoutFont); - return getFontValue( - attributeOutsideTextFont, trace.outsidetextfont, index, defaultFont); -} - -function getFontValue(attributeDefinition, attributeValue, index, defaultValue) { - attributeValue = attributeValue || {}; - - var familyValue = helpers.getValue(attributeValue.family, index); - var sizeValue = helpers.getValue(attributeValue.size, index); - var colorValue = helpers.getValue(attributeValue.color, index); - - return { - family: helpers.coerceString( - attributeDefinition.family, familyValue, defaultValue.family), - size: helpers.coerceNumber( - attributeDefinition.size, sizeValue, defaultValue.size), - color: helpers.coerceColor( - attributeDefinition.color, colorValue, defaultValue.color) - }; -} - -function getBarColor(cd, trace) { - if(trace.type === 'waterfall') { - return trace[cd.dir].marker.color; - } - return cd.mc || trace.marker.color; -} - -module.exports = { - style: style, - styleTextPoints: styleTextPoints, - styleOnSelect: styleOnSelect, - getInsideTextFont: getInsideTextFont, - getOutsideTextFont: getOutsideTextFont, - getBarColor: getBarColor -}; - -},{"../../components/color":593,"../../components/drawing":614,"../../lib":719,"../../registry":847,"./attributes":857,"./helpers":862,"d3":163}],871:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Color = _dereq_('../../components/color'); -var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale; -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); - -module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout) { - coerce('marker.color', defaultColor); - - if(hasColorscale(traceIn, 'marker')) { - colorscaleDefaults( - traceIn, traceOut, layout, coerce, {prefix: 'marker.', cLetter: 'c'} - ); - } - - coerce('marker.line.color', Color.defaultLine); - - if(hasColorscale(traceIn, 'marker.line')) { - colorscaleDefaults( - traceIn, traceOut, layout, coerce, {prefix: 'marker.line.', cLetter: 'c'} - ); - } - - coerce('marker.line.width'); - coerce('marker.opacity'); - coerce('selected.marker.color'); - coerce('unselected.marker.color'); -}; - -},{"../../components/color":593,"../../components/colorscale/defaults":603,"../../components/colorscale/helpers":604}],872:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var scatterPolarAttrs = _dereq_('../scatterpolar/attributes'); -var barAttrs = _dereq_('../bar/attributes'); - -module.exports = { - r: scatterPolarAttrs.r, - theta: scatterPolarAttrs.theta, - r0: scatterPolarAttrs.r0, - dr: scatterPolarAttrs.dr, - theta0: scatterPolarAttrs.theta0, - dtheta: scatterPolarAttrs.dtheta, - thetaunit: scatterPolarAttrs.thetaunit, - - // orientation: { - // valType: 'enumerated', - // - // values: ['radial', 'angular'], - // editType: 'calc+clearAxisTypes', - // - // }, - - base: extendFlat({}, barAttrs.base, { - - }), - offset: extendFlat({}, barAttrs.offset, { - - }), - width: extendFlat({}, barAttrs.width, { - - }), - - text: extendFlat({}, barAttrs.text, { - - }), - hovertext: extendFlat({}, barAttrs.hovertext, { - - }), - - // textposition: {}, - // textfont: {}, - // insidetextfont: {}, - // outsidetextfont: {}, - // constraintext: {}, - // cliponaxis: extendFlat({}, barAttrs.cliponaxis, {dflt: false}), - - marker: barAttrs.marker, - - hoverinfo: scatterPolarAttrs.hoverinfo, - hovertemplate: hovertemplateAttrs(), - - selected: barAttrs.selected, - unselected: barAttrs.unselected - - // error_x (error_r, error_theta) - // error_y -}; - -},{"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../bar/attributes":857,"../scatterpolar/attributes":1179}],873:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale; -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); -var arraysToCalcdata = _dereq_('../bar/arrays_to_calcdata'); -var setGroupPositions = _dereq_('../bar/cross_trace_calc').setGroupPositions; -var calcSelection = _dereq_('../scatter/calc_selection'); -var traceIs = _dereq_('../../registry').traceIs; -var extendFlat = _dereq_('../../lib').extendFlat; - -function calc(gd, trace) { - var fullLayout = gd._fullLayout; - var subplotId = trace.subplot; - var radialAxis = fullLayout[subplotId].radialaxis; - var angularAxis = fullLayout[subplotId].angularaxis; - var rArray = radialAxis.makeCalcdata(trace, 'r'); - var thetaArray = angularAxis.makeCalcdata(trace, 'theta'); - var len = trace._length; - var cd = new Array(len); - - // 'size' axis variables - var sArray = rArray; - // 'pos' axis variables - var pArray = thetaArray; - - for(var i = 0; i < len; i++) { - cd[i] = {p: pArray[i], s: sArray[i]}; - } - - // convert width and offset in 'c' coordinate, - // set 'c' value(s) in trace._width and trace._offset, - // to make Bar.crossTraceCalc "just work" - function d2c(attr) { - var val = trace[attr]; - if(val !== undefined) { - trace['_' + attr] = Array.isArray(val) ? - angularAxis.makeCalcdata(trace, attr) : - angularAxis.d2c(val, trace.thetaunit); - } - } - - if(angularAxis.type === 'linear') { - d2c('width'); - d2c('offset'); - } - - if(hasColorscale(trace, 'marker')) { - colorscaleCalc(gd, trace, { - vals: trace.marker.color, - containerStr: 'marker', - cLetter: 'c' - }); - } - if(hasColorscale(trace, 'marker.line')) { - colorscaleCalc(gd, trace, { - vals: trace.marker.line.color, - containerStr: 'marker.line', - cLetter: 'c' - }); - } - - arraysToCalcdata(cd, trace); - calcSelection(cd, trace); - - return cd; -} - -function crossTraceCalc(gd, polarLayout, subplotId) { - var calcdata = gd.calcdata; - var barPolarCd = []; - - for(var i = 0; i < calcdata.length; i++) { - var cdi = calcdata[i]; - var trace = cdi[0].trace; - - if(trace.visible === true && traceIs(trace, 'bar') && - trace.subplot === subplotId - ) { - barPolarCd.push(cdi); - } - } - - // to make _extremes is filled in correctly so that - // polar._subplot.radialAxis can get auotrange'd - // TODO clean up! - // I think we want to call getAutorange on polar.radialaxis - // NOT on polar._subplot.radialAxis - var rAxis = extendFlat({}, polarLayout.radialaxis, {_id: 'x'}); - var aAxis = polarLayout.angularaxis; - - setGroupPositions(gd, aAxis, rAxis, barPolarCd, { - mode: polarLayout.barmode, - norm: polarLayout.barnorm, - gap: polarLayout.bargap, - groupgap: polarLayout.bargroupgap - }); -} - -module.exports = { - calc: calc, - crossTraceCalc: crossTraceCalc -}; - -},{"../../components/colorscale/calc":601,"../../components/colorscale/helpers":604,"../../lib":719,"../../registry":847,"../bar/arrays_to_calcdata":856,"../bar/cross_trace_calc":860,"../scatter/calc_selection":1114}],874:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var handleRThetaDefaults = _dereq_('../scatterpolar/defaults').handleRThetaDefaults; -var handleStyleDefaults = _dereq_('../bar/style_defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleRThetaDefaults(traceIn, traceOut, layout, coerce); - if(!len) { - traceOut.visible = false; - return; - } - - // coerce('orientation', (traceOut.theta && !traceOut.r) ? 'angular' : 'radial'); - - coerce('thetaunit'); - coerce('base'); - coerce('offset'); - coerce('width'); - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - // var textPosition = coerce('textposition'); - // var hasBoth = Array.isArray(textPosition) || textPosition === 'auto'; - // var hasInside = hasBoth || textPosition === 'inside'; - // var hasOutside = hasBoth || textPosition === 'outside'; - - // if(hasInside || hasOutside) { - // var textFont = coerceFont(coerce, 'textfont', layout.font); - // if(hasInside) coerceFont(coerce, 'insidetextfont', textFont); - // if(hasOutside) coerceFont(coerce, 'outsidetextfont', textFont); - // coerce('constraintext'); - // coerce('selected.textfont.color'); - // coerce('unselected.textfont.color'); - // coerce('cliponaxis'); - // } - - handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -},{"../../lib":719,"../bar/style_defaults":871,"../scatterpolar/defaults":1181,"./attributes":872}],875:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Fx = _dereq_('../../components/fx'); -var Lib = _dereq_('../../lib'); -var getTraceColor = _dereq_('../bar/hover').getTraceColor; -var fillText = Lib.fillText; -var makeHoverPointText = _dereq_('../scatterpolar/hover').makeHoverPointText; -var isPtInsidePolygon = _dereq_('../../plots/polar/helpers').isPtInsidePolygon; - -module.exports = function hoverPoints(pointData, xval, yval) { - var cd = pointData.cd; - var trace = cd[0].trace; - - var subplot = pointData.subplot; - var radialAxis = subplot.radialAxis; - var angularAxis = subplot.angularAxis; - var vangles = subplot.vangles; - var inboxFn = vangles ? isPtInsidePolygon : Lib.isPtInsideSector; - var maxHoverDistance = pointData.maxHoverDistance; - var period = angularAxis._period || 2 * Math.PI; - - var rVal = Math.abs(radialAxis.g2p(Math.sqrt(xval * xval + yval * yval))); - var thetaVal = Math.atan2(yval, xval); - - // polar.(x|y)axis.p2c doesn't get the reversed radial axis range case right - if(radialAxis.range[0] > radialAxis.range[1]) { - thetaVal += Math.PI; - } - - var distFn = function(di) { - if(inboxFn(rVal, thetaVal, [di.rp0, di.rp1], [di.thetag0, di.thetag1], vangles)) { - return maxHoverDistance + - // add a little to the pseudo-distance for wider bars, so that like scatter, - // if you are over two overlapping bars, the narrower one wins. - Math.min(1, Math.abs(di.thetag1 - di.thetag0) / period) - 1 + - // add a gradient so hovering near the end of a - // bar makes it a little closer match - (di.rp1 - rVal) / (di.rp1 - di.rp0) - 1; - } else { - return Infinity; - } - }; - - Fx.getClosest(cd, distFn, pointData); - if(pointData.index === false) return; - - var index = pointData.index; - var cdi = cd[index]; - - pointData.x0 = pointData.x1 = cdi.ct[0]; - pointData.y0 = pointData.y1 = cdi.ct[1]; - - var _cdi = Lib.extendFlat({}, cdi, {r: cdi.s, theta: cdi.p}); - fillText(cdi, trace, pointData); - makeHoverPointText(_cdi, trace, subplot, pointData); - pointData.hovertemplate = trace.hovertemplate; - pointData.color = getTraceColor(trace, cdi); - pointData.xLabelVal = pointData.yLabelVal = undefined; - - if(cdi.s < 0) { - pointData.idealAlign = 'left'; - } - - return [pointData]; -}; - -},{"../../components/fx":632,"../../lib":719,"../../plots/polar/helpers":830,"../bar/hover":863,"../scatterpolar/hover":1182}],876:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'barpolar', - basePlotModule: _dereq_('../../plots/polar'), - categories: ['polar', 'bar', 'showLegend'], - - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('./layout_attributes'), - supplyDefaults: _dereq_('./defaults'), - supplyLayoutDefaults: _dereq_('./layout_defaults'), - - calc: _dereq_('./calc').calc, - crossTraceCalc: _dereq_('./calc').crossTraceCalc, - - plot: _dereq_('./plot'), - colorbar: _dereq_('../scatter/marker_colorbar'), - - style: _dereq_('../bar/style').style, - styleOnSelect: _dereq_('../bar/style').styleOnSelect, - - hoverPoints: _dereq_('./hover'), - selectPoints: _dereq_('../bar/select'), - - meta: { - - - } -}; - -},{"../../plots/polar":831,"../bar/select":868,"../bar/style":870,"../scatter/marker_colorbar":1129,"./attributes":872,"./calc":873,"./defaults":874,"./hover":875,"./layout_attributes":877,"./layout_defaults":878,"./plot":879}],877:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - barmode: { - valType: 'enumerated', - values: ['stack', 'overlay'], - dflt: 'stack', - - editType: 'calc', - - }, - bargap: { - valType: 'number', - dflt: 0.1, - min: 0, - max: 1, - - editType: 'calc', - - } -}; - -},{}],878:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attrs = _dereq_('./layout_attributes'); - -module.exports = function(layoutIn, layoutOut, fullData) { - var subplotsDone = {}; - var sp; - - function coerce(attr, dflt) { - return Lib.coerce(layoutIn[sp] || {}, layoutOut[sp], attrs, attr, dflt); - } - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - if(trace.type === 'barpolar' && trace.visible === true) { - sp = trace.subplot; - if(!subplotsDone[sp]) { - coerce('barmode'); - coerce('bargap'); - subplotsDone[sp] = 1; - } - } - } -}; - -},{"../../lib":719,"./layout_attributes":877}],879:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../../components/drawing'); -var helpers = _dereq_('../../plots/polar/helpers'); - -module.exports = function plot(gd, subplot, cdbar) { - var xa = subplot.xaxis; - var ya = subplot.yaxis; - var radialAxis = subplot.radialAxis; - var angularAxis = subplot.angularAxis; - var pathFn = makePathFn(subplot); - var barLayer = subplot.layers.frontplot.select('g.barlayer'); - - Lib.makeTraceGroups(barLayer, cdbar, 'trace bars').each(function() { - var plotGroup = d3.select(this); - var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points'); - var bars = pointGroup.selectAll('g.point').data(Lib.identity); - - bars.enter().append('g') - .style('vector-effect', 'non-scaling-stroke') - .style('stroke-miterlimit', 2) - .classed('point', true); - - bars.exit().remove(); - - bars.each(function(di) { - var bar = d3.select(this); - - var rp0 = di.rp0 = radialAxis.c2p(di.s0); - var rp1 = di.rp1 = radialAxis.c2p(di.s1); - var thetag0 = di.thetag0 = angularAxis.c2g(di.p0); - var thetag1 = di.thetag1 = angularAxis.c2g(di.p1); - - var dPath; - - if(!isNumeric(rp0) || !isNumeric(rp1) || - !isNumeric(thetag0) || !isNumeric(thetag1) || - rp0 === rp1 || thetag0 === thetag1 - ) { - // do not remove blank bars, to keep data-to-node - // mapping intact during radial drag, that we - // can skip calling _module.style during interactions - dPath = 'M0,0Z'; - } else { - // this 'center' pt is used for selections and hover labels - var rg1 = radialAxis.c2g(di.s1); - var thetagMid = (thetag0 + thetag1) / 2; - di.ct = [ - xa.c2p(rg1 * Math.cos(thetagMid)), - ya.c2p(rg1 * Math.sin(thetagMid)) - ]; - - dPath = pathFn(rp0, rp1, thetag0, thetag1); - } - - Lib.ensureSingle(bar, 'path').attr('d', dPath); - }); - - // clip plotGroup, when trace layer isn't clipped - Drawing.setClipUrl( - plotGroup, - subplot._hasClipOnAxisFalse ? subplot.clipIds.forTraces : null, - gd - ); - }); -}; - -function makePathFn(subplot) { - var cxx = subplot.cxx; - var cyy = subplot.cyy; - - if(subplot.vangles) { - return function(r0, r1, _a0, _a1) { - var a0, a1; - - if(Lib.angleDelta(_a0, _a1) > 0) { - a0 = _a0; - a1 = _a1; - } else { - a0 = _a1; - a1 = _a0; - } - - var va0 = helpers.findEnclosingVertexAngles(a0, subplot.vangles)[0]; - var va1 = helpers.findEnclosingVertexAngles(a1, subplot.vangles)[1]; - var vaBar = [va0, (a0 + a1) / 2, va1]; - return helpers.pathPolygonAnnulus(r0, r1, a0, a1, vaBar, cxx, cyy); - }; - } - - return function(r0, r1, a0, a1) { - return Lib.pathAnnulus(r0, r1, a0, a1, cxx, cyy); - }; -} - -},{"../../components/drawing":614,"../../lib":719,"../../plots/polar/helpers":830,"d3":163,"fast-isnumeric":225}],880:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterAttrs = _dereq_('../scatter/attributes'); -var barAttrs = _dereq_('../bar/attributes'); -var colorAttrs = _dereq_('../../components/color/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var scatterMarkerAttrs = scatterAttrs.marker; -var scatterMarkerLineAttrs = scatterMarkerAttrs.line; - -module.exports = { - y: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - x: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - x0: { - valType: 'any', - - editType: 'calc+clearAxisTypes', - - }, - y0: { - valType: 'any', - - editType: 'calc+clearAxisTypes', - - }, - name: { - valType: 'string', - - editType: 'calc+clearAxisTypes', - - }, - text: extendFlat({}, scatterAttrs.text, { - - }), - hovertext: extendFlat({}, scatterAttrs.hovertext, { - - }), - hovertemplate: hovertemplateAttrs({ - - }), - whiskerwidth: { - valType: 'number', - min: 0, - max: 1, - dflt: 0.5, - - editType: 'calc', - - }, - notched: { - valType: 'boolean', - - editType: 'calc', - - }, - notchwidth: { - valType: 'number', - min: 0, - max: 0.5, - dflt: 0.25, - - editType: 'calc', - - }, - boxpoints: { - valType: 'enumerated', - values: ['all', 'outliers', 'suspectedoutliers', false], - dflt: 'outliers', - - editType: 'calc', - - }, - boxmean: { - valType: 'enumerated', - values: [true, 'sd', false], - dflt: false, - - editType: 'calc', - - }, - jitter: { - valType: 'number', - min: 0, - max: 1, - - editType: 'calc', - - }, - pointpos: { - valType: 'number', - min: -2, - max: 2, - - editType: 'calc', - - }, - orientation: { - valType: 'enumerated', - values: ['v', 'h'], - - editType: 'calc+clearAxisTypes', - - }, - - width: { - valType: 'number', - min: 0, - - dflt: 0, - editType: 'calc', - - }, - - marker: { - outliercolor: { - valType: 'color', - dflt: 'rgba(0, 0, 0, 0)', - - editType: 'style', - - }, - symbol: extendFlat({}, scatterMarkerAttrs.symbol, - {arrayOk: false, editType: 'plot'}), - opacity: extendFlat({}, scatterMarkerAttrs.opacity, - {arrayOk: false, dflt: 1, editType: 'style'}), - size: extendFlat({}, scatterMarkerAttrs.size, - {arrayOk: false, editType: 'calc'}), - color: extendFlat({}, scatterMarkerAttrs.color, - {arrayOk: false, editType: 'style'}), - line: { - color: extendFlat({}, scatterMarkerLineAttrs.color, - {arrayOk: false, dflt: colorAttrs.defaultLine, editType: 'style'} - ), - width: extendFlat({}, scatterMarkerLineAttrs.width, - {arrayOk: false, dflt: 0, editType: 'style'} - ), - outliercolor: { - valType: 'color', - - editType: 'style', - - }, - outlierwidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'style', - - }, - editType: 'style' - }, - editType: 'plot' - }, - line: { - color: { - valType: 'color', - - editType: 'style', - - }, - width: { - valType: 'number', - - min: 0, - dflt: 2, - editType: 'style', - - }, - editType: 'plot' - }, - fillcolor: scatterAttrs.fillcolor, - - offsetgroup: barAttrs.offsetgroup, - alignmentgroup: barAttrs.alignmentgroup, - - selected: { - marker: scatterAttrs.selected.marker, - editType: 'style' - }, - unselected: { - marker: scatterAttrs.unselected.marker, - editType: 'style' - }, - hoveron: { - valType: 'flaglist', - flags: ['boxes', 'points'], - dflt: 'boxes+points', - - editType: 'style', - - } -}; - -},{"../../components/color/attributes":592,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../bar/attributes":857,"../scatter/attributes":1112}],881:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var _ = Lib._; -var Axes = _dereq_('../../plots/cartesian/axes'); - -// outlier definition based on http://www.physics.csbsju.edu/stats/box2.html -module.exports = function calc(gd, trace) { - var fullLayout = gd._fullLayout; - var xa = Axes.getFromId(gd, trace.xaxis || 'x'); - var ya = Axes.getFromId(gd, trace.yaxis || 'y'); - var cd = []; - - // N.B. violin reuses same Box.calc - var numKey = trace.type === 'violin' ? '_numViolins' : '_numBoxes'; - - var i; - var valAxis, valLetter; - var posAxis, posLetter; - - if(trace.orientation === 'h') { - valAxis = xa; - valLetter = 'x'; - posAxis = ya; - posLetter = 'y'; - } else { - valAxis = ya; - valLetter = 'y'; - posAxis = xa; - posLetter = 'x'; - } - - var val = valAxis.makeCalcdata(trace, valLetter); - var pos = getPos(trace, posLetter, posAxis, val, fullLayout[numKey]); - - var dv = Lib.distinctVals(pos); - var posDistinct = dv.vals; - var dPos = dv.minDiff / 2; - var posBins = makeBins(posDistinct, dPos); - - var pLen = posDistinct.length; - var ptsPerBin = initNestedArray(pLen); - - // bin pts info per position bins - for(i = 0; i < trace._length; i++) { - var v = val[i]; - if(!isNumeric(v)) continue; - - var n = Lib.findBin(pos[i], posBins); - if(n >= 0 && n < pLen) { - var pt = {v: v, i: i}; - arraysToCalcdata(pt, trace, i); - ptsPerBin[n].push(pt); - } - } - - var cdi; - var ptFilterFn = (trace.boxpoints || trace.points) === 'all' ? - Lib.identity : - function(pt) { return (pt.v < cdi.lf || pt.v > cdi.uf); }; - - // build calcdata trace items, one item per distinct position - for(i = 0; i < pLen; i++) { - if(ptsPerBin[i].length > 0) { - var pts = ptsPerBin[i].sort(sortByVal); - var boxVals = pts.map(extractVal); - var bvLen = boxVals.length; - - cdi = {}; - cdi.pos = posDistinct[i]; - cdi.pts = pts; - - // Sort categories by values - cdi[posLetter] = cdi.pos; - cdi[valLetter] = cdi.pts.map(function(pt) { return pt.v; }); - - cdi.min = boxVals[0]; - cdi.max = boxVals[bvLen - 1]; - cdi.mean = Lib.mean(boxVals, bvLen); - cdi.sd = Lib.stdev(boxVals, bvLen, cdi.mean); - - // first quartile - cdi.q1 = Lib.interp(boxVals, 0.25); - // median - cdi.med = Lib.interp(boxVals, 0.5); - // third quartile - cdi.q3 = Lib.interp(boxVals, 0.75); - - // lower and upper fences - last point inside - // 1.5 interquartile ranges from quartiles - cdi.lf = Math.min( - cdi.q1, - boxVals[Math.min( - Lib.findBin(2.5 * cdi.q1 - 1.5 * cdi.q3, boxVals, true) + 1, - bvLen - 1 - )] - ); - cdi.uf = Math.max( - cdi.q3, - boxVals[Math.max( - Lib.findBin(2.5 * cdi.q3 - 1.5 * cdi.q1, boxVals), - 0 - )] - ); - - // lower and upper outliers - 3 IQR out (don't clip to max/min, - // this is only for discriminating suspected & far outliers) - cdi.lo = 4 * cdi.q1 - 3 * cdi.q3; - cdi.uo = 4 * cdi.q3 - 3 * cdi.q1; - - // lower and upper notches ~95% Confidence Intervals for median - var iqr = cdi.q3 - cdi.q1; - var mci = 1.57 * iqr / Math.sqrt(bvLen); - cdi.ln = cdi.med - mci; - cdi.un = cdi.med + mci; - - cdi.pts2 = pts.filter(ptFilterFn); - - cd.push(cdi); - } - } - - calcSelection(cd, trace); - var extremes = Axes.findExtremes(valAxis, val, {padded: true}); - trace._extremes[valAxis._id] = extremes; - - if(cd.length > 0) { - cd[0].t = { - num: fullLayout[numKey], - dPos: dPos, - posLetter: posLetter, - valLetter: valLetter, - labels: { - med: _(gd, 'median:'), - min: _(gd, 'min:'), - q1: _(gd, 'q1:'), - q3: _(gd, 'q3:'), - max: _(gd, 'max:'), - mean: trace.boxmean === 'sd' ? _(gd, 'mean ± σ:') : _(gd, 'mean:'), - lf: _(gd, 'lower fence:'), - uf: _(gd, 'upper fence:') - } - }; - - fullLayout[numKey]++; - return cd; - } else { - return [{t: {empty: true}}]; - } -}; - -// In vertical (horizontal) box plots: -// if no x (y) data, use x0 (y0), or name -// so if you want one box -// per trace, set x0 (y0) to the x (y) value or category for this trace -// (or set x (y) to a constant array matching y (x)) -function getPos(trace, posLetter, posAxis, val, num) { - if(posLetter in trace) { - return posAxis.makeCalcdata(trace, posLetter); - } - - var pos0; - - if(posLetter + '0' in trace) { - pos0 = trace[posLetter + '0']; - } else if('name' in trace && ( - posAxis.type === 'category' || ( - isNumeric(trace.name) && - ['linear', 'log'].indexOf(posAxis.type) !== -1 - ) || ( - Lib.isDateTime(trace.name) && - posAxis.type === 'date' - ) - )) { - pos0 = trace.name; - } else { - pos0 = num; - } - - var pos0c = posAxis.type === 'multicategory' ? - posAxis.r2c_just_indices(pos0) : - posAxis.d2c(pos0, 0, trace[posLetter + 'calendar']); - - return val.map(function() { return pos0c; }); -} - -function makeBins(x, dx) { - var len = x.length; - var bins = new Array(len + 1); - - for(var i = 0; i < len; i++) { - bins[i] = x[i] - dx; - } - bins[len] = x[len - 1] + dx; - - return bins; -} - -function initNestedArray(len) { - var arr = new Array(len); - for(var i = 0; i < len; i++) { - arr[i] = []; - } - return arr; -} - -function arraysToCalcdata(pt, trace, i) { - var trace2calc = { - text: 'tx', - hovertext: 'htx' - }; - - for(var k in trace2calc) { - if(Array.isArray(trace[k])) { - pt[trace2calc[k]] = trace[k][i]; - } - } -} - -function calcSelection(cd, trace) { - if(Lib.isArrayOrTypedArray(trace.selectedpoints)) { - for(var i = 0; i < cd.length; i++) { - var pts = cd[i].pts || []; - var ptNumber2cdIndex = {}; - - for(var j = 0; j < pts.length; j++) { - ptNumber2cdIndex[pts[j].i] = j; - } - - Lib.tagSelected(pts, trace, ptNumber2cdIndex); - } - } -} - -function sortByVal(a, b) { return a.v - b.v; } - -function extractVal(o) { return o.v; } - -},{"../../lib":719,"../../plots/cartesian/axes":767,"fast-isnumeric":225}],882:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var Lib = _dereq_('../../lib'); -var getAxisGroup = _dereq_('../../plots/cartesian/axis_ids').getAxisGroup; - -var orientations = ['v', 'h']; - -function crossTraceCalc(gd, plotinfo) { - var calcdata = gd.calcdata; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - for(var i = 0; i < orientations.length; i++) { - var orientation = orientations[i]; - var posAxis = orientation === 'h' ? ya : xa; - var boxList = []; - - // make list of boxes / candlesticks - // For backward compatibility, candlesticks are treated as if they *are* box traces here - for(var j = 0; j < calcdata.length; j++) { - var cd = calcdata[j]; - var t = cd[0].t; - var trace = cd[0].trace; - - if(trace.visible === true && - (trace.type === 'box' || trace.type === 'candlestick') && - !t.empty && - (trace.orientation || 'v') === orientation && - trace.xaxis === xa._id && - trace.yaxis === ya._id - ) { - boxList.push(j); - } - } - - setPositionOffset('box', gd, boxList, posAxis); - } -} - -function setPositionOffset(traceType, gd, boxList, posAxis) { - var calcdata = gd.calcdata; - var fullLayout = gd._fullLayout; - var axId = posAxis._id; - var axLetter = axId.charAt(0); - - var i, j, calcTrace; - var pointList = []; - var shownPts = 0; - - // make list of box points - for(i = 0; i < boxList.length; i++) { - calcTrace = calcdata[boxList[i]]; - for(j = 0; j < calcTrace.length; j++) { - pointList.push(calcTrace[j].pos); - shownPts += (calcTrace[j].pts2 || []).length; - } - } - - if(!pointList.length) return; - - // box plots - update dPos based on multiple traces - var boxdv = Lib.distinctVals(pointList); - var dPos0 = boxdv.minDiff / 2; - - // check for forced minimum dtick - Axes.minDtick(posAxis, boxdv.minDiff, boxdv.vals[0], true); - - var numKey = traceType === 'violin' ? '_numViolins' : '_numBoxes'; - var numTotal = fullLayout[numKey]; - var group = fullLayout[traceType + 'mode'] === 'group' && numTotal > 1; - var groupFraction = 1 - fullLayout[traceType + 'gap']; - var groupGapFraction = 1 - fullLayout[traceType + 'groupgap']; - - for(i = 0; i < boxList.length; i++) { - calcTrace = calcdata[boxList[i]]; - - var trace = calcTrace[0].trace; - var t = calcTrace[0].t; - var width = trace.width; - var side = trace.side; - - // position coordinate delta - var dPos; - // box half width; - var bdPos; - // box center offset - var bPos; - // half-width within which to accept hover for this box/violin - // always split the distance to the closest box/violin - var wHover; - - if(width) { - dPos = bdPos = wHover = width / 2; - bPos = 0; - } else { - dPos = dPos0; - - if(group) { - var groupId = getAxisGroup(fullLayout, posAxis._id) + trace.orientation; - var alignmentGroups = fullLayout._alignmentOpts[groupId] || {}; - var alignmentGroupOpts = alignmentGroups[trace.alignmentgroup] || {}; - var nOffsetGroups = Object.keys(alignmentGroupOpts.offsetGroups || {}).length; - var num = nOffsetGroups || numTotal; - var shift = nOffsetGroups ? trace._offsetIndex : t.num; - - bdPos = dPos * groupFraction * groupGapFraction / num; - bPos = 2 * dPos * (-0.5 + (shift + 0.5) / num) * groupFraction; - wHover = dPos * groupFraction / num; - } else { - bdPos = dPos * groupFraction * groupGapFraction; - bPos = 0; - wHover = dPos; - } - } - t.dPos = dPos; - t.bPos = bPos; - t.bdPos = bdPos; - t.wHover = wHover; - - // box/violin-only value-space push value - var pushplus; - var pushminus; - // edge of box/violin - var edge = bPos + bdPos; - var edgeplus; - var edgeminus; - // value-space padding - var vpadplus; - var vpadminus; - // pixel-space padding - var ppadplus; - var ppadminus; - // do we add 5% of both sides (more logic for points beyond box/violin below) - var padded = Boolean(width); - // does this trace show points? - var hasPts = (trace.boxpoints || trace.points) && (shownPts > 0); - - if(side === 'positive') { - pushplus = dPos * (width ? 1 : 0.5); - edgeplus = edge; - pushminus = edgeplus = bPos; - } else if(side === 'negative') { - pushplus = edgeplus = bPos; - pushminus = dPos * (width ? 1 : 0.5); - edgeminus = edge; - } else { - pushplus = pushminus = dPos; - edgeplus = edgeminus = edge; - } - - if(hasPts) { - var pointpos = trace.pointpos; - var jitter = trace.jitter; - var ms = trace.marker.size / 2; - - var pp = 0; - if((pointpos + jitter) >= 0) { - pp = edge * (pointpos + jitter); - if(pp > pushplus) { - // (++) beyond plus-value, use pp - padded = true; - ppadplus = ms; - vpadplus = pp; - } else if(pp > edgeplus) { - // (+), use push-value (it's bigger), but add px-pad - ppadplus = ms; - vpadplus = pushplus; - } - } - if(pp <= pushplus) { - // (->) fallback to push value - vpadplus = pushplus; - } - - var pm = 0; - if((pointpos - jitter) <= 0) { - pm = -edge * (pointpos - jitter); - if(pm > pushminus) { - // (--) beyond plus-value, use pp - padded = true; - ppadminus = ms; - vpadminus = pm; - } else if(pm > edgeminus) { - // (-), use push-value (it's bigger), but add px-pad - ppadminus = ms; - vpadminus = pushminus; - } - } - if(pm <= pushminus) { - // (<-) fallback to push value - vpadminus = pushminus; - } - } else { - vpadplus = pushplus; - vpadminus = pushminus; - } - - var pos = new Array(calcTrace.length); - for(j = 0; j < calcTrace.length; j++) { - pos[j] = calcTrace[j].pos; - } - - trace._extremes[axId] = Axes.findExtremes(posAxis, pos, { - padded: padded, - vpadminus: vpadminus, - vpadplus: vpadplus, - // N.B. SVG px-space positive/negative - ppadminus: {x: ppadminus, y: ppadplus}[axLetter], - ppadplus: {x: ppadplus, y: ppadminus}[axLetter], - }); - } -} - -module.exports = { - crossTraceCalc: crossTraceCalc, - setPositionOffset: setPositionOffset -}; - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../../plots/cartesian/axis_ids":770}],883:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); -var Color = _dereq_('../../components/color'); -var handleGroupingDefaults = _dereq_('../bar/defaults').handleGroupingDefaults; -var attributes = _dereq_('./attributes'); - -function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - handleSampleDefaults(traceIn, traceOut, coerce, layout); - if(traceOut.visible === false) return; - - coerce('line.color', (traceIn.marker || {}).color || defaultColor); - coerce('line.width'); - coerce('fillcolor', Color.addOpacity(traceOut.line.color, 0.5)); - - coerce('whiskerwidth'); - coerce('boxmean'); - coerce('width'); - - var notched = coerce('notched', traceIn.notchwidth !== undefined); - if(notched) coerce('notchwidth'); - - handlePointsDefaults(traceIn, traceOut, coerce, {prefix: 'box'}); -} - -function handleSampleDefaults(traceIn, traceOut, coerce, layout) { - var y = coerce('y'); - var x = coerce('x'); - var hasX = x && x.length; - - var defaultOrientation, len; - - if(y && y.length) { - defaultOrientation = 'v'; - if(hasX) { - len = Math.min(Lib.minRowLength(x), Lib.minRowLength(y)); - } else { - coerce('x0'); - len = Lib.minRowLength(y); - } - } else if(hasX) { - defaultOrientation = 'h'; - coerce('y0'); - len = Lib.minRowLength(x); - } else { - traceOut.visible = false; - return; - } - traceOut._length = len; - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout); - - coerce('orientation', defaultOrientation); -} - -function handlePointsDefaults(traceIn, traceOut, coerce, opts) { - var prefix = opts.prefix; - - var outlierColorDflt = Lib.coerce2(traceIn, traceOut, attributes, 'marker.outliercolor'); - var lineoutliercolor = coerce('marker.line.outliercolor'); - - var points = coerce( - prefix + 'points', - (outlierColorDflt || lineoutliercolor) ? 'suspectedoutliers' : undefined - ); - - if(points) { - coerce('jitter', points === 'all' ? 0.3 : 0); - coerce('pointpos', points === 'all' ? -1.5 : 0); - - coerce('marker.symbol'); - coerce('marker.opacity'); - coerce('marker.size'); - coerce('marker.color', traceOut.line.color); - coerce('marker.line.color'); - coerce('marker.line.width'); - - if(points === 'suspectedoutliers') { - coerce('marker.line.outliercolor', traceOut.marker.color); - coerce('marker.line.outlierwidth'); - } - - coerce('selected.marker.color'); - coerce('unselected.marker.color'); - coerce('selected.marker.size'); - coerce('unselected.marker.size'); - - coerce('text'); - coerce('hovertext'); - } else { - delete traceOut.marker; - } - - var hoveron = coerce('hoveron'); - if(hoveron === 'all' || hoveron.indexOf('points') !== -1) { - coerce('hovertemplate'); - } - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -} - -function crossTraceDefaults(fullData, fullLayout) { - var traceIn, traceOut; - - function coerce(attr) { - return Lib.coerce(traceOut._input, traceOut, attributes, attr); - } - - for(var i = 0; i < fullData.length; i++) { - traceOut = fullData[i]; - var traceType = traceOut.type; - - if(traceType === 'box' || traceType === 'violin') { - traceIn = traceOut._input; - if(fullLayout[traceType + 'mode'] === 'group') { - handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); - } - } - } -} - -module.exports = { - supplyDefaults: supplyDefaults, - crossTraceDefaults: crossTraceDefaults, - - handleSampleDefaults: handleSampleDefaults, - handlePointsDefaults: handlePointsDefaults -}; - -},{"../../components/color":593,"../../lib":719,"../../registry":847,"../bar/defaults":861,"./attributes":880}],884:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function eventData(out, pt) { - // Note: hoverOnBox property is needed for click-to-select - // to ignore when a box was clicked. This is the reason box - // implements this custom eventData function. - if(pt.hoverOnBox) out.hoverOnBox = pt.hoverOnBox; - - if('xVal' in pt) out.x = pt.xVal; - if('yVal' in pt) out.y = pt.yVal; - if(pt.xa) out.xaxis = pt.xa; - if(pt.ya) out.yaxis = pt.ya; - - return out; -}; - -},{}],885:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var Lib = _dereq_('../../lib'); -var Fx = _dereq_('../../components/fx'); -var Color = _dereq_('../../components/color'); -var fillText = Lib.fillText; - -function hoverPoints(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var trace = cd[0].trace; - var hoveron = trace.hoveron; - var closeBoxData = []; - var closePtData; - - if(hoveron.indexOf('boxes') !== -1) { - closeBoxData = closeBoxData.concat(hoverOnBoxes(pointData, xval, yval, hovermode)); - } - - if(hoveron.indexOf('points') !== -1) { - closePtData = hoverOnPoints(pointData, xval, yval); - } - - // If there's a point in range and hoveron has points, show the best single point only. - // If hoveron has boxes and there's no point in range (or hoveron doesn't have points), show the box stats. - if(hovermode === 'closest') { - if(closePtData) return [closePtData]; - return closeBoxData; - } - - // Otherwise in compare mode, allow a point AND the box stats to be labeled - // If there are multiple boxes in range (ie boxmode = 'overlay') we'll see stats for all of them. - if(closePtData) { - closeBoxData.push(closePtData); - return closeBoxData; - } - return closeBoxData; -} - -function hoverOnBoxes(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var xa = pointData.xa; - var ya = pointData.ya; - var trace = cd[0].trace; - var t = cd[0].t; - var isViolin = trace.type === 'violin'; - var closeBoxData = []; - - var pLetter, vLetter, pAxis, vAxis, vVal, pVal, dx, dy, dPos, - hoverPseudoDistance, spikePseudoDistance; - - var boxDelta = t.bdPos; - var boxDeltaPos, boxDeltaNeg; - var posAcceptance = t.wHover; - var shiftPos = function(di) { return di.pos + t.bPos - pVal; }; - - if(isViolin && trace.side !== 'both') { - if(trace.side === 'positive') { - dPos = function(di) { - var pos = shiftPos(di); - return Fx.inbox(pos, pos + posAcceptance, hoverPseudoDistance); - }; - boxDeltaPos = boxDelta; - boxDeltaNeg = 0; - } - if(trace.side === 'negative') { - dPos = function(di) { - var pos = shiftPos(di); - return Fx.inbox(pos - posAcceptance, pos, hoverPseudoDistance); - }; - boxDeltaPos = 0; - boxDeltaNeg = boxDelta; - } - } else { - dPos = function(di) { - var pos = shiftPos(di); - return Fx.inbox(pos - posAcceptance, pos + posAcceptance, hoverPseudoDistance); - }; - boxDeltaPos = boxDeltaNeg = boxDelta; - } - - var dVal; - - if(isViolin) { - dVal = function(di) { - return Fx.inbox(di.span[0] - vVal, di.span[1] - vVal, hoverPseudoDistance); - }; - } else { - dVal = function(di) { - return Fx.inbox(di.min - vVal, di.max - vVal, hoverPseudoDistance); - }; - } - - if(trace.orientation === 'h') { - vVal = xval; - pVal = yval; - dx = dVal; - dy = dPos; - pLetter = 'y'; - pAxis = ya; - vLetter = 'x'; - vAxis = xa; - } else { - vVal = yval; - pVal = xval; - dx = dPos; - dy = dVal; - pLetter = 'x'; - pAxis = xa; - vLetter = 'y'; - vAxis = ya; - } - - // if two boxes are overlaying, let the narrowest one win - var pseudoDistance = Math.min(1, boxDelta / Math.abs(pAxis.r2c(pAxis.range[1]) - pAxis.r2c(pAxis.range[0]))); - hoverPseudoDistance = pointData.maxHoverDistance - pseudoDistance; - spikePseudoDistance = pointData.maxSpikeDistance - pseudoDistance; - - function dxy(di) { return (dx(di) + dy(di)) / 2; } - var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy); - Fx.getClosest(cd, distfn, pointData); - - // skip the rest (for this trace) if we didn't find a close point - // and create the item(s) in closedata for this point - if(pointData.index === false) return []; - - var di = cd[pointData.index]; - var lc = trace.line.color; - var mc = (trace.marker || {}).color; - - if(Color.opacity(lc) && trace.line.width) pointData.color = lc; - else if(Color.opacity(mc) && trace.boxpoints) pointData.color = mc; - else pointData.color = trace.fillcolor; - - pointData[pLetter + '0'] = pAxis.c2p(di.pos + t.bPos - boxDeltaNeg, true); - pointData[pLetter + '1'] = pAxis.c2p(di.pos + t.bPos + boxDeltaPos, true); - - pointData[pLetter + 'LabelVal'] = di.pos; - - var spikePosAttr = pLetter + 'Spike'; - pointData.spikeDistance = dxy(di) * spikePseudoDistance / hoverPseudoDistance; - pointData[spikePosAttr] = pAxis.c2p(di.pos, true); - - // box plots: each "point" gets many labels - var usedVals = {}; - var attrs = ['med', 'q1', 'q3', 'min', 'max']; - - if(trace.boxmean || (trace.meanline || {}).visible) { - attrs.push('mean'); - } - if(trace.boxpoints || trace.points) { - attrs.push('lf', 'uf'); - } - - for(var i = 0; i < attrs.length; i++) { - var attr = attrs[i]; - - if(!(attr in di) || (di[attr] in usedVals)) continue; - usedVals[di[attr]] = true; - - // copy out to a new object for each value to label - var val = di[attr]; - var valPx = vAxis.c2p(val, true); - var pointData2 = Lib.extendFlat({}, pointData); - - pointData2.attr = attr; - pointData2[vLetter + '0'] = pointData2[vLetter + '1'] = valPx; - pointData2[vLetter + 'LabelVal'] = val; - pointData2[vLetter + 'Label'] = (t.labels ? t.labels[attr] + ' ' : '') + Axes.hoverLabelText(vAxis, val); - - // Note: introduced to be able to distinguish a - // clicked point from a box during click-to-select - pointData2.hoverOnBox = true; - - if(attr === 'mean' && ('sd' in di) && trace.boxmean === 'sd') { - pointData2[vLetter + 'err'] = di.sd; - } - - // only keep name and spikes on the first item (median) - pointData.name = ''; - pointData.spikeDistance = undefined; - pointData[spikePosAttr] = undefined; - - // no hovertemplate support yet - pointData2.hovertemplate = false; - - closeBoxData.push(pointData2); - } - - return closeBoxData; -} - -function hoverOnPoints(pointData, xval, yval) { - var cd = pointData.cd; - var xa = pointData.xa; - var ya = pointData.ya; - var trace = cd[0].trace; - var xPx = xa.c2p(xval); - var yPx = ya.c2p(yval); - var closePtData; - - var dx = function(di) { - var rad = Math.max(3, di.mrc || 0); - return Math.max(Math.abs(xa.c2p(di.x) - xPx) - rad, 1 - 3 / rad); - }; - var dy = function(di) { - var rad = Math.max(3, di.mrc || 0); - return Math.max(Math.abs(ya.c2p(di.y) - yPx) - rad, 1 - 3 / rad); - }; - var distfn = Fx.quadrature(dx, dy); - - // show one point per trace - var ijClosest = false; - var di, pt; - - for(var i = 0; i < cd.length; i++) { - di = cd[i]; - - for(var j = 0; j < (di.pts || []).length; j++) { - pt = di.pts[j]; - - var newDistance = distfn(pt); - if(newDistance <= pointData.distance) { - pointData.distance = newDistance; - ijClosest = [i, j]; - } - } - } - - if(!ijClosest) return false; - - di = cd[ijClosest[0]]; - pt = di.pts[ijClosest[1]]; - - var xc = xa.c2p(pt.x, true); - var yc = ya.c2p(pt.y, true); - var rad = pt.mrc || 1; - - closePtData = Lib.extendFlat({}, pointData, { - // corresponds to index in x/y input data array - index: pt.i, - color: (trace.marker || {}).color, - name: trace.name, - x0: xc - rad, - x1: xc + rad, - y0: yc - rad, - y1: yc + rad, - spikeDistance: pointData.distance, - hovertemplate: trace.hovertemplate - }); - - var pa; - if(trace.orientation === 'h') { - pa = ya; - closePtData.xLabelVal = pt.x; - closePtData.yLabelVal = di.pos; - } else { - pa = xa; - closePtData.xLabelVal = di.pos; - closePtData.yLabelVal = pt.y; - } - - var pLetter = pa._id.charAt(0); - closePtData[pLetter + 'Spike'] = pa.c2p(di.pos, true); - - fillText(pt, trace, closePtData); - - return closePtData; -} - -module.exports = { - hoverPoints: hoverPoints, - hoverOnBoxes: hoverOnBoxes, - hoverOnPoints: hoverOnPoints -}; - -},{"../../components/color":593,"../../components/fx":632,"../../lib":719,"../../plots/cartesian/axes":767}],886:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('./layout_attributes'), - supplyDefaults: _dereq_('./defaults').supplyDefaults, - crossTraceDefaults: _dereq_('./defaults').crossTraceDefaults, - supplyLayoutDefaults: _dereq_('./layout_defaults').supplyLayoutDefaults, - calc: _dereq_('./calc'), - crossTraceCalc: _dereq_('./cross_trace_calc').crossTraceCalc, - plot: _dereq_('./plot').plot, - style: _dereq_('./style').style, - styleOnSelect: _dereq_('./style').styleOnSelect, - hoverPoints: _dereq_('./hover').hoverPoints, - eventData: _dereq_('./event_data'), - selectPoints: _dereq_('./select'), - - moduleType: 'trace', - name: 'box', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', 'symbols', 'oriented', 'box-violin', 'showLegend', 'boxLayout', 'zoomScale'], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"./attributes":880,"./calc":881,"./cross_trace_calc":882,"./defaults":883,"./event_data":884,"./hover":885,"./layout_attributes":887,"./layout_defaults":888,"./plot":889,"./select":890,"./style":891}],887:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -module.exports = { - boxmode: { - valType: 'enumerated', - values: ['group', 'overlay'], - dflt: 'overlay', - - editType: 'calc', - - }, - boxgap: { - valType: 'number', - min: 0, - max: 1, - dflt: 0.3, - - editType: 'calc', - - }, - boxgroupgap: { - valType: 'number', - min: 0, - max: 1, - dflt: 0.3, - - editType: 'calc', - - } -}; - -},{}],888:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var layoutAttributes = _dereq_('./layout_attributes'); - -function _supply(layoutIn, layoutOut, fullData, coerce, traceType) { - var category = traceType + 'Layout'; - var hasTraceType = false; - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - - if(Registry.traceIs(trace, category)) { - hasTraceType = true; - break; - } - } - if(!hasTraceType) return; - - coerce(traceType + 'mode'); - coerce(traceType + 'gap'); - coerce(traceType + 'groupgap'); -} - -function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - _supply(layoutIn, layoutOut, fullData, coerce, 'box'); -} - -module.exports = { - supplyLayoutDefaults: supplyLayoutDefaults, - _supply: _supply -}; - -},{"../../lib":719,"../../registry":847,"./layout_attributes":887}],889:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../../components/drawing'); - -// constants for dynamic jitter (ie less jitter for sparser points) -var JITTERCOUNT = 5; // points either side of this to include -var JITTERSPREAD = 0.01; // fraction of IQR to count as "dense" - -function plot(gd, plotinfo, cdbox, boxLayer) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - Lib.makeTraceGroups(boxLayer, cdbox, 'trace boxes').each(function(cd) { - var plotGroup = d3.select(this); - var cd0 = cd[0]; - var t = cd0.t; - var trace = cd0.trace; - - // whisker width - t.wdPos = t.bdPos * trace.whiskerwidth; - - if(trace.visible !== true || t.empty) { - plotGroup.remove(); - return; - } - - var posAxis, valAxis; - - if(trace.orientation === 'h') { - posAxis = ya; - valAxis = xa; - } else { - posAxis = xa; - valAxis = ya; - } - - plotBoxAndWhiskers(plotGroup, {pos: posAxis, val: valAxis}, trace, t); - plotPoints(plotGroup, {x: xa, y: ya}, trace, t); - plotBoxMean(plotGroup, {pos: posAxis, val: valAxis}, trace, t); - }); -} - -function plotBoxAndWhiskers(sel, axes, trace, t) { - var posAxis = axes.pos; - var valAxis = axes.val; - var bPos = t.bPos; - var wdPos = t.wdPos || 0; - var bPosPxOffset = t.bPosPxOffset || 0; - var whiskerWidth = trace.whiskerwidth || 0; - var notched = trace.notched || false; - var nw = notched ? 1 - 2 * trace.notchwidth : 1; - - // to support for one-sided box - var bdPos0; - var bdPos1; - if(Array.isArray(t.bdPos)) { - bdPos0 = t.bdPos[0]; - bdPos1 = t.bdPos[1]; - } else { - bdPos0 = t.bdPos; - bdPos1 = t.bdPos; - } - - var paths = sel.selectAll('path.box').data(( - trace.type !== 'violin' || - trace.box.visible - ) ? Lib.identity : []); - - paths.enter().append('path') - .style('vector-effect', 'non-scaling-stroke') - .attr('class', 'box'); - - paths.exit().remove(); - - paths.each(function(d) { - if(d.empty) return 'M0,0Z'; - - var pos = d.pos; - var posc = posAxis.c2p(pos + bPos, true) + bPosPxOffset; - var pos0 = posAxis.c2p(pos + bPos - bdPos0, true) + bPosPxOffset; - var pos1 = posAxis.c2p(pos + bPos + bdPos1, true) + bPosPxOffset; - var posw0 = posAxis.c2p(pos + bPos - wdPos, true) + bPosPxOffset; - var posw1 = posAxis.c2p(pos + bPos + wdPos, true) + bPosPxOffset; - var posm0 = posAxis.c2p(pos + bPos - bdPos0 * nw, true) + bPosPxOffset; - var posm1 = posAxis.c2p(pos + bPos + bdPos1 * nw, true) + bPosPxOffset; - var q1 = valAxis.c2p(d.q1, true); - var q3 = valAxis.c2p(d.q3, true); - // make sure median isn't identical to either of the - // quartiles, so we can see it - var m = Lib.constrain( - valAxis.c2p(d.med, true), - Math.min(q1, q3) + 1, Math.max(q1, q3) - 1 - ); - - // for compatibility with box, violin, and candlestick - // perhaps we should put this into cd0.t instead so it's more explicit, - // but what we have now is: - // - box always has d.lf, but boxpoints can be anything - // - violin has d.lf and should always use it (boxpoints is undefined) - // - candlestick has only min/max - var useExtremes = (d.lf === undefined) || (trace.boxpoints === false); - var lf = valAxis.c2p(useExtremes ? d.min : d.lf, true); - var uf = valAxis.c2p(useExtremes ? d.max : d.uf, true); - var ln = valAxis.c2p(d.ln, true); - var un = valAxis.c2p(d.un, true); - - if(trace.orientation === 'h') { - d3.select(this).attr('d', - 'M' + m + ',' + posm0 + 'V' + posm1 + // median line - 'M' + q1 + ',' + pos0 + 'V' + pos1 + // left edge - (notched ? 'H' + ln + 'L' + m + ',' + posm1 + 'L' + un + ',' + pos1 : '') + // top notched edge - 'H' + q3 + // end of the top edge - 'V' + pos0 + // right edge - (notched ? 'H' + un + 'L' + m + ',' + posm0 + 'L' + ln + ',' + pos0 : '') + // bottom notched edge - 'Z' + // end of the box - 'M' + q1 + ',' + posc + 'H' + lf + 'M' + q3 + ',' + posc + 'H' + uf + // whiskers - ((whiskerWidth === 0) ? '' : // whisker caps - 'M' + lf + ',' + posw0 + 'V' + posw1 + 'M' + uf + ',' + posw0 + 'V' + posw1)); - } else { - d3.select(this).attr('d', - 'M' + posm0 + ',' + m + 'H' + posm1 + // median line - 'M' + pos0 + ',' + q1 + 'H' + pos1 + // top of the box - (notched ? 'V' + ln + 'L' + posm1 + ',' + m + 'L' + pos1 + ',' + un : '') + // notched right edge - 'V' + q3 + // end of the right edge - 'H' + pos0 + // bottom of the box - (notched ? 'V' + un + 'L' + posm0 + ',' + m + 'L' + pos0 + ',' + ln : '') + // notched left edge - 'Z' + // end of the box - 'M' + posc + ',' + q1 + 'V' + lf + 'M' + posc + ',' + q3 + 'V' + uf + // whiskers - ((whiskerWidth === 0) ? '' : // whisker caps - 'M' + posw0 + ',' + lf + 'H' + posw1 + 'M' + posw0 + ',' + uf + 'H' + posw1)); - } - }); -} - -function plotPoints(sel, axes, trace, t) { - var xa = axes.x; - var ya = axes.y; - var bdPos = t.bdPos; - var bPos = t.bPos; - - // to support violin points - var mode = trace.boxpoints || trace.points; - - // repeatable pseudo-random number generator - Lib.seedPseudoRandom(); - - // since box plot points get an extra level of nesting, each - // box needs the trace styling info - var fn = function(d) { - d.forEach(function(v) { - v.t = t; - v.trace = trace; - }); - return d; - }; - - var gPoints = sel.selectAll('g.points') - .data(mode ? fn : []); - - gPoints.enter().append('g') - .attr('class', 'points'); - - gPoints.exit().remove(); - - var paths = gPoints.selectAll('path') - .data(function(d) { - var i; - var pts = d.pts2; - - // normally use IQR, but if this is 0 or too small, use max-min - var typicalSpread = Math.max((d.max - d.min) / 10, d.q3 - d.q1); - var minSpread = typicalSpread * 1e-9; - var spreadLimit = typicalSpread * JITTERSPREAD; - var jitterFactors = []; - var maxJitterFactor = 0; - var newJitter; - - // dynamic jitter - if(trace.jitter) { - if(typicalSpread === 0) { - // edge case of no spread at all: fall back to max jitter - maxJitterFactor = 1; - jitterFactors = new Array(pts.length); - for(i = 0; i < pts.length; i++) { - jitterFactors[i] = 1; - } - } else { - for(i = 0; i < pts.length; i++) { - var i0 = Math.max(0, i - JITTERCOUNT); - var pmin = pts[i0].v; - var i1 = Math.min(pts.length - 1, i + JITTERCOUNT); - var pmax = pts[i1].v; - - if(mode !== 'all') { - if(pts[i].v < d.lf) pmax = Math.min(pmax, d.lf); - else pmin = Math.max(pmin, d.uf); - } - - var jitterFactor = Math.sqrt(spreadLimit * (i1 - i0) / (pmax - pmin + minSpread)) || 0; - jitterFactor = Lib.constrain(Math.abs(jitterFactor), 0, 1); - - jitterFactors.push(jitterFactor); - maxJitterFactor = Math.max(jitterFactor, maxJitterFactor); - } - } - newJitter = trace.jitter * 2 / (maxJitterFactor || 1); - } - - // fills in 'x' and 'y' in calcdata 'pts' item - for(i = 0; i < pts.length; i++) { - var pt = pts[i]; - var v = pt.v; - - var jitterOffset = trace.jitter ? - (newJitter * jitterFactors[i] * (Lib.pseudoRandom() - 0.5)) : - 0; - - var posPx = d.pos + bPos + bdPos * (trace.pointpos + jitterOffset); - - if(trace.orientation === 'h') { - pt.y = posPx; - pt.x = v; - } else { - pt.x = posPx; - pt.y = v; - } - - // tag suspected outliers - if(mode === 'suspectedoutliers' && v < d.uo && v > d.lo) { - pt.so = true; - } - } - - return pts; - }); - - paths.enter().append('path') - .classed('point', true); - - paths.exit().remove(); - - paths.call(Drawing.translatePoints, xa, ya); -} - -function plotBoxMean(sel, axes, trace, t) { - var posAxis = axes.pos; - var valAxis = axes.val; - var bPos = t.bPos; - var bPosPxOffset = t.bPosPxOffset || 0; - - // to support violin mean lines - var mode = trace.boxmean || (trace.meanline || {}).visible; - - // to support for one-sided box - var bdPos0; - var bdPos1; - if(Array.isArray(t.bdPos)) { - bdPos0 = t.bdPos[0]; - bdPos1 = t.bdPos[1]; - } else { - bdPos0 = t.bdPos; - bdPos1 = t.bdPos; - } - - var paths = sel.selectAll('path.mean').data(( - (trace.type === 'box' && trace.boxmean) || - (trace.type === 'violin' && trace.box.visible && trace.meanline.visible) - ) ? Lib.identity : []); - - paths.enter().append('path') - .attr('class', 'mean') - .style({ - fill: 'none', - 'vector-effect': 'non-scaling-stroke' - }); - - paths.exit().remove(); - - paths.each(function(d) { - var posc = posAxis.c2p(d.pos + bPos, true) + bPosPxOffset; - var pos0 = posAxis.c2p(d.pos + bPos - bdPos0, true) + bPosPxOffset; - var pos1 = posAxis.c2p(d.pos + bPos + bdPos1, true) + bPosPxOffset; - var m = valAxis.c2p(d.mean, true); - var sl = valAxis.c2p(d.mean - d.sd, true); - var sh = valAxis.c2p(d.mean + d.sd, true); - - if(trace.orientation === 'h') { - d3.select(this).attr('d', - 'M' + m + ',' + pos0 + 'V' + pos1 + - (mode === 'sd' ? - 'm0,0L' + sl + ',' + posc + 'L' + m + ',' + pos0 + 'L' + sh + ',' + posc + 'Z' : - '') - ); - } else { - d3.select(this).attr('d', - 'M' + pos0 + ',' + m + 'H' + pos1 + - (mode === 'sd' ? - 'm0,0L' + posc + ',' + sl + 'L' + pos0 + ',' + m + 'L' + posc + ',' + sh + 'Z' : - '') - ); - } - }); -} - -module.exports = { - plot: plot, - plotBoxAndWhiskers: plotBoxAndWhiskers, - plotPoints: plotPoints, - plotBoxMean: plotBoxMean -}; - -},{"../../components/drawing":614,"../../lib":719,"d3":163}],890:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function selectPoints(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var xa = searchInfo.xaxis; - var ya = searchInfo.yaxis; - var selection = []; - var i, j; - - if(selectionTester === false) { - for(i = 0; i < cd.length; i++) { - for(j = 0; j < (cd[i].pts || []).length; j++) { - // clear selection - cd[i].pts[j].selected = 0; - } - } - } else { - for(i = 0; i < cd.length; i++) { - for(j = 0; j < (cd[i].pts || []).length; j++) { - var pt = cd[i].pts[j]; - var x = xa.c2p(pt.x); - var y = ya.c2p(pt.y); - - if(selectionTester.contains([x, y], null, pt.i, searchInfo)) { - selection.push({ - pointNumber: pt.i, - x: xa.c2d(pt.x), - y: ya.c2d(pt.y) - }); - pt.selected = 1; - } else { - pt.selected = 0; - } - } - } - } - - return selection; -}; - -},{}],891:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); - -function style(gd, cd, sel) { - var s = sel ? sel : d3.select(gd).selectAll('g.trace.boxes'); - - s.style('opacity', function(d) { return d[0].trace.opacity; }); - - s.each(function(d) { - var el = d3.select(this); - var trace = d[0].trace; - var lineWidth = trace.line.width; - - function styleBox(boxSel, lineWidth, lineColor, fillColor) { - boxSel.style('stroke-width', lineWidth + 'px') - .call(Color.stroke, lineColor) - .call(Color.fill, fillColor); - } - - var allBoxes = el.selectAll('path.box'); - - if(trace.type === 'candlestick') { - allBoxes.each(function(boxData) { - if(boxData.empty) return; - - var thisBox = d3.select(this); - var container = trace[boxData.dir]; // dir = 'increasing' or 'decreasing' - styleBox(thisBox, container.line.width, container.line.color, container.fillcolor); - // TODO: custom selection style for candlesticks - thisBox.style('opacity', trace.selectedpoints && !boxData.selected ? 0.3 : 1); - }); - } else { - styleBox(allBoxes, lineWidth, trace.line.color, trace.fillcolor); - el.selectAll('path.mean') - .style({ - 'stroke-width': lineWidth, - 'stroke-dasharray': (2 * lineWidth) + 'px,' + lineWidth + 'px' - }) - .call(Color.stroke, trace.line.color); - - var pts = el.selectAll('path.point'); - Drawing.pointStyle(pts, trace, gd); - } - }); -} - -function styleOnSelect(gd, cd, sel) { - var trace = cd[0].trace; - var pts = sel.selectAll('path.point'); - - if(trace.selectedpoints) { - Drawing.selectedPointStyle(pts, trace); - } else { - Drawing.pointStyle(pts, trace, gd); - } -} - -module.exports = { - style: style, - styleOnSelect: styleOnSelect -}; - -},{"../../components/color":593,"../../components/drawing":614,"d3":163}],892:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var extendFlat = _dereq_('../../lib').extendFlat; -var OHLCattrs = _dereq_('../ohlc/attributes'); -var boxAttrs = _dereq_('../box/attributes'); - -function directionAttrs(lineColorDefault) { - return { - line: { - color: extendFlat({}, boxAttrs.line.color, {dflt: lineColorDefault}), - width: boxAttrs.line.width, - editType: 'style' - }, - - fillcolor: boxAttrs.fillcolor, - editType: 'style' - }; -} - -module.exports = { - x: OHLCattrs.x, - open: OHLCattrs.open, - high: OHLCattrs.high, - low: OHLCattrs.low, - close: OHLCattrs.close, - - line: { - width: extendFlat({}, boxAttrs.line.width, { - - }), - editType: 'style' - }, - - increasing: directionAttrs(OHLCattrs.increasing.line.color.dflt), - - decreasing: directionAttrs(OHLCattrs.decreasing.line.color.dflt), - - text: OHLCattrs.text, - hovertext: OHLCattrs.hovertext, - whiskerwidth: extendFlat({}, boxAttrs.whiskerwidth, { dflt: 0 }), - - hoverlabel: OHLCattrs.hoverlabel, -}; - -},{"../../lib":719,"../box/attributes":880,"../ohlc/attributes":1058}],893:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); - -var calcCommon = _dereq_('../ohlc/calc').calcCommon; - -module.exports = function(gd, trace) { - var fullLayout = gd._fullLayout; - var xa = Axes.getFromId(gd, trace.xaxis); - var ya = Axes.getFromId(gd, trace.yaxis); - - var x = xa.makeCalcdata(trace, 'x'); - - var cd = calcCommon(gd, trace, x, ya, ptFunc); - - if(cd.length) { - Lib.extendFlat(cd[0].t, { - num: fullLayout._numBoxes, - dPos: Lib.distinctVals(x).minDiff / 2, - posLetter: 'x', - valLetter: 'y', - }); - - fullLayout._numBoxes++; - return cd; - } else { - return [{t: {empty: true}}]; - } -}; - -function ptFunc(o, h, l, c) { - return { - min: l, - q1: Math.min(o, c), - med: c, - q3: Math.max(o, c), - max: h, - }; -} - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../ohlc/calc":1059}],894:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); -var handleOHLC = _dereq_('../ohlc/ohlc_defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleOHLC(traceIn, traceOut, coerce, layout); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('line.width'); - - handleDirection(traceIn, traceOut, coerce, 'increasing'); - handleDirection(traceIn, traceOut, coerce, 'decreasing'); - - coerce('text'); - coerce('hovertext'); - coerce('whiskerwidth'); - - layout._requestRangeslider[traceOut.xaxis] = true; -}; - -function handleDirection(traceIn, traceOut, coerce, direction) { - var lineColor = coerce(direction + '.line.color'); - coerce(direction + '.line.width', traceOut.line.width); - coerce(direction + '.fillcolor', Color.addOpacity(lineColor, 0.5)); -} - -},{"../../components/color":593,"../../lib":719,"../ohlc/ohlc_defaults":1063,"./attributes":892}],895:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'candlestick', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', 'showLegend', 'candlestick', 'boxLayout'], - meta: { - - }, - - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('../box/layout_attributes'), - supplyLayoutDefaults: _dereq_('../box/layout_defaults').supplyLayoutDefaults, - crossTraceCalc: _dereq_('../box/cross_trace_calc').crossTraceCalc, - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('./calc'), - plot: _dereq_('../box/plot').plot, - layerName: 'boxlayer', - style: _dereq_('../box/style').style, - hoverPoints: _dereq_('../ohlc/hover').hoverPoints, - selectPoints: _dereq_('../ohlc/select') -}; - -},{"../../plots/cartesian":778,"../box/cross_trace_calc":882,"../box/layout_attributes":887,"../box/layout_defaults":888,"../box/plot":889,"../box/style":891,"../ohlc/hover":1061,"../ohlc/select":1065,"./attributes":892,"./calc":893,"./defaults":894}],896:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var handleAxisDefaults = _dereq_('./axis_defaults'); -var Template = _dereq_('../../plot_api/plot_template'); - -module.exports = function handleABDefaults(traceIn, traceOut, fullLayout, coerce, dfltColor) { - var a = coerce('a'); - - if(!a) { - coerce('da'); - coerce('a0'); - } - - var b = coerce('b'); - - if(!b) { - coerce('db'); - coerce('b0'); - } - - mimickAxisDefaults(traceIn, traceOut, fullLayout, dfltColor); -}; - -function mimickAxisDefaults(traceIn, traceOut, fullLayout, dfltColor) { - var axesList = ['aaxis', 'baxis']; - - axesList.forEach(function(axName) { - var axLetter = axName.charAt(0); - var axIn = traceIn[axName] || {}; - var axOut = Template.newContainer(traceOut, axName); - - var defaultOptions = { - tickfont: 'x', - id: axLetter + 'axis', - letter: axLetter, - font: traceOut.font, - name: axName, - data: traceIn[axLetter], - calendar: traceOut.calendar, - dfltColor: dfltColor, - bgColor: fullLayout.paper_bgcolor, - fullLayout: fullLayout - }; - - handleAxisDefaults(axIn, axOut, defaultOptions); - axOut._categories = axOut._categories || []; - - // so we don't have to repeat autotype unnecessarily, - // copy an autotype back to traceIn - if(!traceIn[axName] && axIn.type !== '-') { - traceIn[axName] = {type: axIn.type}; - } - }); -} - -},{"../../plot_api/plot_template":757,"./axis_defaults":901}],897:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; - -module.exports = function(a) { - return minMax(a, 0); -}; - -function minMax(a, depth) { - // Limit to ten dimensional datasets. This seems *exceedingly* unlikely to - // ever cause problems or even be a concern. It's include strictly so that - // circular arrays could never cause this to loop. - if(!isArrayOrTypedArray(a) || depth >= 10) { - return null; - } - - var min = Infinity; - var max = -Infinity; - var n = a.length; - for(var i = 0; i < n; i++) { - var datum = a[i]; - - if(isArrayOrTypedArray(datum)) { - var result = minMax(datum, depth + 1); - - if(result) { - min = Math.min(result[0], min); - max = Math.max(result[1], max); - } - } else { - min = Math.min(datum, min); - max = Math.max(datum, max); - } - } - - return [min, max]; -} - -},{"../../lib":719}],898:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('../../plots/font_attributes'); -var axisAttrs = _dereq_('./axis_attributes'); -var colorAttrs = _dereq_('../../components/color/attributes'); - -var carpetFont = fontAttrs({ - editType: 'calc', - -}); -// TODO: inherit from global font -carpetFont.family.dflt = '"Open Sans", verdana, arial, sans-serif'; -carpetFont.size.dflt = 12; -carpetFont.color.dflt = colorAttrs.defaultLine; - -module.exports = { - carpet: { - valType: 'string', - - editType: 'calc', - - }, - x: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - y: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - a: { - valType: 'data_array', - editType: 'calc', - - }, - a0: { - valType: 'number', - dflt: 0, - - editType: 'calc', - - }, - da: { - valType: 'number', - dflt: 1, - - editType: 'calc', - - }, - b: { - valType: 'data_array', - editType: 'calc', - - }, - b0: { - valType: 'number', - dflt: 0, - - editType: 'calc', - - }, - db: { - valType: 'number', - dflt: 1, - - editType: 'calc', - - }, - cheaterslope: { - valType: 'number', - - dflt: 1, - editType: 'calc', - - }, - aaxis: axisAttrs, - baxis: axisAttrs, - font: carpetFont, - color: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'plot', - - }, - transforms: undefined -}; - -},{"../../components/color/attributes":592,"../../plots/font_attributes":793,"./axis_attributes":900}],899:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; - -/* This function retrns a set of control points that define a curve aligned along - * either the a or b axis. Exactly one of a or b must be an array defining the range - * spanned. - * - * Honestly this is the most complicated function I've implemente here so far because - * of the way it handles knot insertion and direction/axis-agnostic slices. - */ -module.exports = function(carpet, carpetcd, a, b) { - var idx, tangent, tanIsoIdx, tanIsoPar, segment, refidx; - var p0, p1, v0, v1, start, end, range; - - var axis = isArrayOrTypedArray(a) ? 'a' : 'b'; - var ax = axis === 'a' ? carpet.aaxis : carpet.baxis; - var smoothing = ax.smoothing; - var toIdx = axis === 'a' ? carpet.a2i : carpet.b2j; - var pt = axis === 'a' ? a : b; - var iso = axis === 'a' ? b : a; - var n = axis === 'a' ? carpetcd.a.length : carpetcd.b.length; - var m = axis === 'a' ? carpetcd.b.length : carpetcd.a.length; - var isoIdx = Math.floor(axis === 'a' ? carpet.b2j(iso) : carpet.a2i(iso)); - - var xy = axis === 'a' ? function(value) { - return carpet.evalxy([], value, isoIdx); - } : function(value) { - return carpet.evalxy([], isoIdx, value); - }; - - if(smoothing) { - tanIsoIdx = Math.max(0, Math.min(m - 2, isoIdx)); - tanIsoPar = isoIdx - tanIsoIdx; - tangent = axis === 'a' ? function(i, ti) { - return carpet.dxydi([], i, tanIsoIdx, ti, tanIsoPar); - } : function(j, tj) { - return carpet.dxydj([], tanIsoIdx, j, tanIsoPar, tj); - }; - } - - var vstart = toIdx(pt[0]); - var vend = toIdx(pt[1]); - - // So that we can make this work in two directions, flip all of the - // math functions if the direction is from higher to lower indices: - // - // Note that the tolerance is directional! - var dir = vstart < vend ? 1 : -1; - var tol = (vend - vstart) * 1e-8; - var dirfloor = dir > 0 ? Math.floor : Math.ceil; - var dirceil = dir > 0 ? Math.ceil : Math.floor; - var dirmin = dir > 0 ? Math.min : Math.max; - var dirmax = dir > 0 ? Math.max : Math.min; - - var idx0 = dirfloor(vstart + tol); - var idx1 = dirceil(vend - tol); - - p0 = xy(vstart); - var segments = [[p0]]; - - for(idx = idx0; idx * dir < idx1 * dir; idx += dir) { - segment = []; - start = dirmax(vstart, idx); - end = dirmin(vend, idx + dir); - range = end - start; - - // In order to figure out which cell we're in for the derivative (remember, - // the derivatives are *not* constant across grid lines), let's just average - // the start and end points. This cuts out just a tiny bit of logic and - // there's really no computational difference: - refidx = Math.max(0, Math.min(n - 2, Math.floor(0.5 * (start + end)))); - - p1 = xy(end); - if(smoothing) { - v0 = tangent(refidx, start - refidx); - v1 = tangent(refidx, end - refidx); - - segment.push([ - p0[0] + v0[0] / 3 * range, - p0[1] + v0[1] / 3 * range - ]); - - segment.push([ - p1[0] - v1[0] / 3 * range, - p1[1] - v1[1] / 3 * range - ]); - } - - segment.push(p1); - - segments.push(segment); - p0 = p1; - } - - return segments; -}; - -},{"../../lib":719}],900:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('../../plots/font_attributes'); -var colorAttrs = _dereq_('../../components/color/attributes'); -var axesAttrs = _dereq_('../../plots/cartesian/layout_attributes'); -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK; -var DATE_FORMAT_LINK = _dereq_('../../constants/docs').TIME_FORMAT_LINK; - -module.exports = { - color: { - valType: 'color', - - editType: 'calc', - - }, - smoothing: { - valType: 'number', - dflt: 1, - min: 0, - max: 1.3, - - editType: 'calc' - }, - title: { - text: { - valType: 'string', - dflt: '', - - editType: 'calc', - - }, - font: fontAttrs({ - editType: 'calc', - - }), - offset: { - valType: 'number', - - dflt: 10, - editType: 'calc', - - }, - editType: 'calc', - }, - type: { - valType: 'enumerated', - // '-' means we haven't yet run autotype or couldn't find any data - // it gets turned into linear in gd._fullLayout but not copied back - // to gd.data like the others are. - values: ['-', 'linear', 'date', 'category'], - dflt: '-', - - editType: 'calc', - - }, - autorange: { - valType: 'enumerated', - values: [true, false, 'reversed'], - dflt: true, - - editType: 'calc', - - }, - rangemode: { - valType: 'enumerated', - values: ['normal', 'tozero', 'nonnegative'], - dflt: 'normal', - - editType: 'calc', - - }, - range: { - valType: 'info_array', - - editType: 'calc', - items: [ - {valType: 'any', editType: 'calc'}, - {valType: 'any', editType: 'calc'} - ], - - }, - - fixedrange: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - cheatertype: { - valType: 'enumerated', - values: ['index', 'value'], - dflt: 'value', - - editType: 'calc' - }, - tickmode: { - valType: 'enumerated', - values: ['linear', 'array'], - dflt: 'array', - - editType: 'calc' - }, - nticks: { - valType: 'integer', - min: 0, - dflt: 0, - - editType: 'calc', - - }, - tickvals: { - valType: 'data_array', - editType: 'calc', - - }, - ticktext: { - valType: 'data_array', - editType: 'calc', - - }, - showticklabels: { - valType: 'enumerated', - values: ['start', 'end', 'both', 'none'], - dflt: 'start', - - editType: 'calc', - - }, - tickfont: fontAttrs({ - editType: 'calc', - - }), - tickangle: { - valType: 'angle', - dflt: 'auto', - - editType: 'calc', - - }, - tickprefix: { - valType: 'string', - dflt: '', - - editType: 'calc', - - }, - showtickprefix: { - valType: 'enumerated', - values: ['all', 'first', 'last', 'none'], - dflt: 'all', - - editType: 'calc', - - }, - ticksuffix: { - valType: 'string', - dflt: '', - - editType: 'calc', - - }, - showticksuffix: { - valType: 'enumerated', - values: ['all', 'first', 'last', 'none'], - dflt: 'all', - - editType: 'calc', - - }, - showexponent: { - valType: 'enumerated', - values: ['all', 'first', 'last', 'none'], - dflt: 'all', - - editType: 'calc', - - }, - exponentformat: { - valType: 'enumerated', - values: ['none', 'e', 'E', 'power', 'SI', 'B'], - dflt: 'B', - - editType: 'calc', - - }, - separatethousands: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - tickformat: { - valType: 'string', - dflt: '', - - editType: 'calc', - - }, - tickformatstops: overrideAll(axesAttrs.tickformatstops, 'calc', 'from-root'), - categoryorder: { - valType: 'enumerated', - values: [ - 'trace', 'category ascending', 'category descending', 'array' - /* , 'value ascending', 'value descending'*/ // value ascending / descending to be implemented later - ], - dflt: 'trace', - - editType: 'calc', - - }, - categoryarray: { - valType: 'data_array', - - editType: 'calc', - - }, - labelpadding: { - valType: 'integer', - - dflt: 10, - editType: 'calc', - - }, - labelprefix: { - valType: 'string', - - editType: 'calc', - - }, - labelsuffix: { - valType: 'string', - dflt: '', - - editType: 'calc', - - }, - // lines and grids - showline: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - linecolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'calc', - - }, - linewidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'calc', - - }, - gridcolor: { - valType: 'color', - - editType: 'calc', - - }, - gridwidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'calc', - - }, - showgrid: { - valType: 'boolean', - - dflt: true, - editType: 'calc', - - }, - minorgridcount: { - valType: 'integer', - min: 0, - dflt: 0, - - editType: 'calc', - - }, - minorgridwidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'calc', - - }, - minorgridcolor: { - valType: 'color', - dflt: colorAttrs.lightLine, - - editType: 'calc', - - }, - startline: { - valType: 'boolean', - - editType: 'calc', - - }, - startlinecolor: { - valType: 'color', - - editType: 'calc', - - }, - startlinewidth: { - valType: 'number', - dflt: 1, - - editType: 'calc', - - }, - endline: { - valType: 'boolean', - - editType: 'calc', - - }, - endlinewidth: { - valType: 'number', - dflt: 1, - - editType: 'calc', - - }, - endlinecolor: { - valType: 'color', - - editType: 'calc', - - }, - tick0: { - valType: 'number', - min: 0, - dflt: 0, - - editType: 'calc', - - }, - dtick: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'calc', - - }, - arraytick0: { - valType: 'integer', - min: 0, - dflt: 0, - - editType: 'calc', - - }, - arraydtick: { - valType: 'integer', - min: 1, - dflt: 1, - - editType: 'calc', - - }, - - _deprecated: { - title: { - valType: 'string', - - editType: 'calc', - - }, - titlefont: fontAttrs({ - editType: 'calc', - - }), - titleoffset: { - valType: 'number', - - dflt: 10, - editType: 'calc', - - } - }, - - editType: 'calc' -}; - -},{"../../components/color/attributes":592,"../../constants/docs":690,"../../plot_api/edit_types":750,"../../plots/cartesian/layout_attributes":779,"../../plots/font_attributes":793}],901:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var carpetAttrs = _dereq_('./attributes'); - -var addOpacity = _dereq_('../../components/color').addOpacity; -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var handleTickValueDefaults = _dereq_('../../plots/cartesian/tick_value_defaults'); -var handleTickLabelDefaults = _dereq_('../../plots/cartesian/tick_label_defaults'); -var handleCategoryOrderDefaults = _dereq_('../../plots/cartesian/category_order_defaults'); -var setConvert = _dereq_('../../plots/cartesian/set_convert'); -var autoType = _dereq_('../../plots/cartesian/axis_autotype'); - -/** - * options: object containing: - * - * letter: 'a' or 'b' - * title: name of the axis (ie 'Colorbar') to go in default title - * name: axis object name (ie 'xaxis') if one should be stored - * font: the default font to inherit - * outerTicks: boolean, should ticks default to outside? - * showGrid: boolean, should gridlines be shown by default? - * data: the plot data to use in choosing auto type - * bgColor: the plot background color, to calculate default gridline colors - */ -module.exports = function handleAxisDefaults(containerIn, containerOut, options) { - var letter = options.letter; - var font = options.font || {}; - var attributes = carpetAttrs[letter + 'axis']; - - function coerce(attr, dflt) { - return Lib.coerce(containerIn, containerOut, attributes, attr, dflt); - } - - function coerce2(attr, dflt) { - return Lib.coerce2(containerIn, containerOut, attributes, attr, dflt); - } - - // set up some private properties - if(options.name) { - containerOut._name = options.name; - containerOut._id = options.name; - } - - // now figure out type and do some more initialization - var axType = coerce('type'); - if(axType === '-') { - if(options.data) setAutoType(containerOut, options.data); - - if(containerOut.type === '-') { - containerOut.type = 'linear'; - } else { - // copy autoType back to input axis - // note that if this object didn't exist - // in the input layout, we have to put it in - // this happens in the main supplyDefaults function - axType = containerIn.type = containerOut.type; - } - } - - coerce('smoothing'); - coerce('cheatertype'); - - coerce('showticklabels'); - coerce('labelprefix', letter + ' = '); - coerce('labelsuffix'); - coerce('showtickprefix'); - coerce('showticksuffix'); - - coerce('separatethousands'); - coerce('tickformat'); - coerce('exponentformat'); - coerce('showexponent'); - coerce('categoryorder'); - - coerce('tickmode'); - coerce('tickvals'); - coerce('ticktext'); - coerce('tick0'); - coerce('dtick'); - - if(containerOut.tickmode === 'array') { - coerce('arraytick0'); - coerce('arraydtick'); - } - - coerce('labelpadding'); - - containerOut._hovertitle = letter; - - - if(axType === 'date') { - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleDefaults'); - handleCalendarDefaults(containerIn, containerOut, 'calendar', options.calendar); - } - - // we need some of the other functions setConvert attaches, but for - // path finding, override pixel scaling to simple passthrough (identity) - setConvert(containerOut, options.fullLayout); - containerOut.c2p = Lib.identity; - - var dfltColor = coerce('color', options.dfltColor); - // if axis.color was provided, use it for fonts too; otherwise, - // inherit from global font color in case that was provided. - var dfltFontColor = (dfltColor === containerIn.color) ? dfltColor : font.color; - - var title = coerce('title.text'); - if(title) { - Lib.coerceFont(coerce, 'title.font', { - family: font.family, - size: Math.round(font.size * 1.2), - color: dfltFontColor - }); - coerce('title.offset'); - } - - coerce('tickangle'); - - var autoRange = coerce('autorange', !containerOut.isValidRange(containerIn.range)); - - if(autoRange) coerce('rangemode'); - - coerce('range'); - containerOut.cleanRange(); - - coerce('fixedrange'); - - handleTickValueDefaults(containerIn, containerOut, coerce, axType); - handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options); - handleCategoryOrderDefaults(containerIn, containerOut, coerce, { - data: options.data, - dataAttr: letter - }); - - var gridColor = coerce2('gridcolor', addOpacity(dfltColor, 0.3)); - var gridWidth = coerce2('gridwidth'); - var showGrid = coerce('showgrid'); - - if(!showGrid) { - delete containerOut.gridcolor; - delete containerOut.gridwidth; - } - - var startLineColor = coerce2('startlinecolor', dfltColor); - var startLineWidth = coerce2('startlinewidth', gridWidth); - var showStartLine = coerce('startline', containerOut.showgrid || !!startLineColor || !!startLineWidth); - - if(!showStartLine) { - delete containerOut.startlinecolor; - delete containerOut.startlinewidth; - } - - var endLineColor = coerce2('endlinecolor', dfltColor); - var endLineWidth = coerce2('endlinewidth', gridWidth); - var showEndLine = coerce('endline', containerOut.showgrid || !!endLineColor || !!endLineWidth); - - if(!showEndLine) { - delete containerOut.endlinecolor; - delete containerOut.endlinewidth; - } - - if(!showGrid) { - delete containerOut.gridcolor; - delete containerOut.gridWidth; - } else { - coerce('minorgridcount'); - coerce('minorgridwidth', gridWidth); - coerce('minorgridcolor', addOpacity(gridColor, 0.06)); - - if(!containerOut.minorgridcount) { - delete containerOut.minorgridwidth; - delete containerOut.minorgridcolor; - } - } - - if(containerOut.showticklabels === 'none') { - delete containerOut.tickfont; - delete containerOut.tickangle; - delete containerOut.showexponent; - delete containerOut.exponentformat; - delete containerOut.tickformat; - delete containerOut.showticksuffix; - delete containerOut.showtickprefix; - } - - if(!containerOut.showticksuffix) { - delete containerOut.ticksuffix; - } - - if(!containerOut.showtickprefix) { - delete containerOut.tickprefix; - } - - // It needs to be coerced, then something above overrides this deep in the axis code, - // but no, we *actually* want to coerce this. - coerce('tickmode'); - - return containerOut; -}; - -function setAutoType(ax, data) { - // new logic: let people specify any type they want, - // only autotype if type is '-' - if(ax.type !== '-') return; - - var id = ax._id; - var axLetter = id.charAt(0); - - var calAttr = axLetter + 'calendar'; - var calendar = ax[calAttr]; - - ax.type = autoType(data, calendar); -} - -},{"../../components/color":593,"../../lib":719,"../../plots/cartesian/axis_autotype":768,"../../plots/cartesian/category_order_defaults":771,"../../plots/cartesian/set_convert":785,"../../plots/cartesian/tick_label_defaults":786,"../../plots/cartesian/tick_value_defaults":788,"../../registry":847,"./attributes":898}],902:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var isArray1D = _dereq_('../../lib').isArray1D; -var cheaterBasis = _dereq_('./cheater_basis'); -var arrayMinmax = _dereq_('./array_minmax'); -var calcGridlines = _dereq_('./calc_gridlines'); -var calcLabels = _dereq_('./calc_labels'); -var calcClipPath = _dereq_('./calc_clippath'); -var clean2dArray = _dereq_('../heatmap/clean_2d_array'); -var smoothFill2dArray = _dereq_('./smooth_fill_2d_array'); -var convertColumnData = _dereq_('../heatmap/convert_column_xyz'); -var setConvert = _dereq_('./set_convert'); - -module.exports = function calc(gd, trace) { - var xa = Axes.getFromId(gd, trace.xaxis); - var ya = Axes.getFromId(gd, trace.yaxis); - var aax = trace.aaxis; - var bax = trace.baxis; - - var x = trace.x; - var y = trace.y; - var cols = []; - if(x && isArray1D(x)) cols.push('x'); - if(y && isArray1D(y)) cols.push('y'); - - if(cols.length) { - convertColumnData(trace, aax, bax, 'a', 'b', cols); - } - - var a = trace._a = trace._a || trace.a; - var b = trace._b = trace._b || trace.b; - x = trace._x || trace.x; - y = trace._y || trace.y; - - var t = {}; - - if(trace._cheater) { - var avals = aax.cheatertype === 'index' ? a.length : a; - var bvals = bax.cheatertype === 'index' ? b.length : b; - x = cheaterBasis(avals, bvals, trace.cheaterslope); - } - - trace._x = x = clean2dArray(x); - trace._y = y = clean2dArray(y); - - // Fill in any undefined values with elliptic smoothing. This doesn't take - // into account the spacing of the values. That is, the derivatives should - // be modified to use a and b values. It's not that hard, but this is already - // moderate overkill for just filling in missing values. - smoothFill2dArray(x, a, b); - smoothFill2dArray(y, a, b); - - setConvert(trace); - - // create conversion functions that depend on the data - trace.setScale(); - - // This is a rather expensive scan. Nothing guarantees monotonicity, - // so we need to scan through all data to get proper ranges: - var xrange = arrayMinmax(x); - var yrange = arrayMinmax(y); - - var dx = 0.5 * (xrange[1] - xrange[0]); - var xc = 0.5 * (xrange[1] + xrange[0]); - - var dy = 0.5 * (yrange[1] - yrange[0]); - var yc = 0.5 * (yrange[1] + yrange[0]); - - // Expand the axes to fit the plot, except just grow it by a factor of 1.3 - // because the labels should be taken into account except that's difficult - // hence 1.3. - var grow = 1.3; - xrange = [xc - dx * grow, xc + dx * grow]; - yrange = [yc - dy * grow, yc + dy * grow]; - - trace._extremes[xa._id] = Axes.findExtremes(xa, xrange, {padded: true}); - trace._extremes[ya._id] = Axes.findExtremes(ya, yrange, {padded: true}); - - // Enumerate the gridlines, both major and minor, and store them on the trace - // object: - calcGridlines(trace, 'a', 'b'); - calcGridlines(trace, 'b', 'a'); - - // Calculate the text labels for each major gridline and store them on the - // trace object: - calcLabels(trace, aax); - calcLabels(trace, bax); - - // Tabulate points for the four segments that bound the axes so that we can - // map to pixel coordinates in the plot function and create a clip rect: - t.clipsegments = calcClipPath(trace._xctrl, trace._yctrl, aax, bax); - - t.x = x; - t.y = y; - t.a = a; - t.b = b; - - return [t]; -}; - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../heatmap/clean_2d_array":1003,"../heatmap/convert_column_xyz":1005,"./array_minmax":897,"./calc_clippath":903,"./calc_gridlines":904,"./calc_labels":905,"./cheater_basis":907,"./set_convert":920,"./smooth_fill_2d_array":921}],903:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = function makeClipPath(xctrl, yctrl, aax, bax) { - var i, x, y; - var segments = []; - - var asmoothing = !!aax.smoothing; - var bsmoothing = !!bax.smoothing; - var nea1 = xctrl[0].length - 1; - var neb1 = xctrl.length - 1; - - // Along the lower a axis: - for(i = 0, x = [], y = []; i <= nea1; i++) { - x[i] = xctrl[0][i]; - y[i] = yctrl[0][i]; - } - segments.push({x: x, y: y, bicubic: asmoothing}); - - // Along the upper b axis: - for(i = 0, x = [], y = []; i <= neb1; i++) { - x[i] = xctrl[i][nea1]; - y[i] = yctrl[i][nea1]; - } - segments.push({x: x, y: y, bicubic: bsmoothing}); - - // Backwards along the upper a axis: - for(i = nea1, x = [], y = []; i >= 0; i--) { - x[nea1 - i] = xctrl[neb1][i]; - y[nea1 - i] = yctrl[neb1][i]; - } - segments.push({x: x, y: y, bicubic: asmoothing}); - - // Backwards along the lower b axis: - for(i = neb1, x = [], y = []; i >= 0; i--) { - x[neb1 - i] = xctrl[i][0]; - y[neb1 - i] = yctrl[i][0]; - } - segments.push({x: x, y: y, bicubic: bsmoothing}); - - return segments; -}; - -},{}],904:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = function calcGridlines(trace, axisLetter, crossAxisLetter) { - var i, j, j0; - var eps, bounds, n1, n2, n, value, v; - var j1, v0, v1, d; - - var data = trace['_' + axisLetter]; - var axis = trace[axisLetter + 'axis']; - - var gridlines = axis._gridlines = []; - var minorgridlines = axis._minorgridlines = []; - var boundarylines = axis._boundarylines = []; - - var crossData = trace['_' + crossAxisLetter]; - var crossAxis = trace[crossAxisLetter + 'axis']; - - if(axis.tickmode === 'array') { - axis.tickvals = data.slice(); - } - - var xcp = trace._xctrl; - var ycp = trace._yctrl; - var nea = xcp[0].length; - var neb = xcp.length; - var na = trace._a.length; - var nb = trace._b.length; - - Axes.prepTicks(axis); - - // don't leave tickvals in axis looking like an attribute - if(axis.tickmode === 'array') delete axis.tickvals; - - // The default is an empty array that will cause the join to remove the gridline if - // it's just disappeared: - // axis._startline = axis._endline = []; - - // If the cross axis uses bicubic interpolation, then the grid - // lines fall once every three expanded grid row/cols: - var stride = axis.smoothing ? 3 : 1; - - function constructValueGridline(value) { - var i, j, j0, tj, pxy, i0, ti, xy, dxydi0, dxydi1, dxydj0, dxydj1; - var xpoints = []; - var ypoints = []; - var ret = {}; - // Search for the fractional grid index giving this line: - if(axisLetter === 'b') { - // For the position we use just the i-j coordinates: - j = trace.b2j(value); - - // The derivatives for catmull-rom splines are discontinuous across cell - // boundaries though, so we need to provide both the cell and the position - // within the cell separately: - j0 = Math.floor(Math.max(0, Math.min(nb - 2, j))); - tj = j - j0; - - ret.length = nb; - ret.crossLength = na; - - ret.xy = function(i) { - return trace.evalxy([], i, j); - }; - - ret.dxy = function(i0, ti) { - return trace.dxydi([], i0, j0, ti, tj); - }; - - for(i = 0; i < na; i++) { - i0 = Math.min(na - 2, i); - ti = i - i0; - xy = trace.evalxy([], i, j); - - if(crossAxis.smoothing && i > 0) { - // First control point: - dxydi0 = trace.dxydi([], i - 1, j0, 0, tj); - xpoints.push(pxy[0] + dxydi0[0] / 3); - ypoints.push(pxy[1] + dxydi0[1] / 3); - - // Second control point: - dxydi1 = trace.dxydi([], i - 1, j0, 1, tj); - xpoints.push(xy[0] - dxydi1[0] / 3); - ypoints.push(xy[1] - dxydi1[1] / 3); - } - - xpoints.push(xy[0]); - ypoints.push(xy[1]); - - pxy = xy; - } - } else { - i = trace.a2i(value); - i0 = Math.floor(Math.max(0, Math.min(na - 2, i))); - ti = i - i0; - - ret.length = na; - ret.crossLength = nb; - - ret.xy = function(j) { - return trace.evalxy([], i, j); - }; - - ret.dxy = function(j0, tj) { - return trace.dxydj([], i0, j0, ti, tj); - }; - - for(j = 0; j < nb; j++) { - j0 = Math.min(nb - 2, j); - tj = j - j0; - xy = trace.evalxy([], i, j); - - if(crossAxis.smoothing && j > 0) { - // First control point: - dxydj0 = trace.dxydj([], i0, j - 1, ti, 0); - xpoints.push(pxy[0] + dxydj0[0] / 3); - ypoints.push(pxy[1] + dxydj0[1] / 3); - - // Second control point: - dxydj1 = trace.dxydj([], i0, j - 1, ti, 1); - xpoints.push(xy[0] - dxydj1[0] / 3); - ypoints.push(xy[1] - dxydj1[1] / 3); - } - - xpoints.push(xy[0]); - ypoints.push(xy[1]); - - pxy = xy; - } - } - - ret.axisLetter = axisLetter; - ret.axis = axis; - ret.crossAxis = crossAxis; - ret.value = value; - ret.constvar = crossAxisLetter; - ret.index = n; - ret.x = xpoints; - ret.y = ypoints; - ret.smoothing = crossAxis.smoothing; - - return ret; - } - - function constructArrayGridline(idx) { - var j, i0, j0, ti, tj; - var xpoints = []; - var ypoints = []; - var ret = {}; - ret.length = data.length; - ret.crossLength = crossData.length; - - if(axisLetter === 'b') { - j0 = Math.max(0, Math.min(nb - 2, idx)); - tj = Math.min(1, Math.max(0, idx - j0)); - - ret.xy = function(i) { - return trace.evalxy([], i, idx); - }; - - ret.dxy = function(i0, ti) { - return trace.dxydi([], i0, j0, ti, tj); - }; - - // In the tickmode: array case, this operation is a simple - // transfer of data: - for(j = 0; j < nea; j++) { - xpoints[j] = xcp[idx * stride][j]; - ypoints[j] = ycp[idx * stride][j]; - } - } else { - i0 = Math.max(0, Math.min(na - 2, idx)); - ti = Math.min(1, Math.max(0, idx - i0)); - - ret.xy = function(j) { - return trace.evalxy([], idx, j); - }; - - ret.dxy = function(j0, tj) { - return trace.dxydj([], i0, j0, ti, tj); - }; - - // In the tickmode: array case, this operation is a simple - // transfer of data: - for(j = 0; j < neb; j++) { - xpoints[j] = xcp[j][idx * stride]; - ypoints[j] = ycp[j][idx * stride]; - } - } - - ret.axisLetter = axisLetter; - ret.axis = axis; - ret.crossAxis = crossAxis; - ret.value = data[idx]; - ret.constvar = crossAxisLetter; - ret.index = idx; - ret.x = xpoints; - ret.y = ypoints; - ret.smoothing = crossAxis.smoothing; - - return ret; - } - - if(axis.tickmode === 'array') { - // var j0 = axis.startline ? 1 : 0; - // var j1 = data.length - (axis.endline ? 1 : 0); - - eps = 5e-15; - bounds = [ - Math.floor(((data.length - 1) - axis.arraytick0) / axis.arraydtick * (1 + eps)), - Math.ceil((- axis.arraytick0) / axis.arraydtick / (1 + eps)) - ].sort(function(a, b) {return a - b;}); - - // Unpack sorted values so we can be sure to avoid infinite loops if something - // is backwards: - n1 = bounds[0] - 1; - n2 = bounds[1] + 1; - - // If the axes fall along array lines, then this is a much simpler process since - // we already have all the control points we need - for(n = n1; n < n2; n++) { - j = axis.arraytick0 + axis.arraydtick * n; - if(j < 0 || j > data.length - 1) continue; - gridlines.push(extendFlat(constructArrayGridline(j), { - color: axis.gridcolor, - width: axis.gridwidth - })); - } - - for(n = n1; n < n2; n++) { - j0 = axis.arraytick0 + axis.arraydtick * n; - j1 = Math.min(j0 + axis.arraydtick, data.length - 1); - - // TODO: fix the bounds computation so we don't have to do a large range and then throw - // out unneeded numbers - if(j0 < 0 || j0 > data.length - 1) continue; - if(j1 < 0 || j1 > data.length - 1) continue; - - v0 = data[j0]; - v1 = data[j1]; - - for(i = 0; i < axis.minorgridcount; i++) { - d = j1 - j0; - - // TODO: fix the bounds computation so we don't have to do a large range and then throw - // out unneeded numbers - if(d <= 0) continue; - - // XXX: This calculation isn't quite right. Off by one somewhere? - v = v0 + (v1 - v0) * (i + 1) / (axis.minorgridcount + 1) * (axis.arraydtick / d); - - // TODO: fix the bounds computation so we don't have to do a large range and then throw - // out unneeded numbers - if(v < data[0] || v > data[data.length - 1]) continue; - minorgridlines.push(extendFlat(constructValueGridline(v), { - color: axis.minorgridcolor, - width: axis.minorgridwidth - })); - } - } - - if(axis.startline) { - boundarylines.push(extendFlat(constructArrayGridline(0), { - color: axis.startlinecolor, - width: axis.startlinewidth - })); - } - - if(axis.endline) { - boundarylines.push(extendFlat(constructArrayGridline(data.length - 1), { - color: axis.endlinecolor, - width: axis.endlinewidth - })); - } - } else { - // If the lines do not fall along the axes, then we have to interpolate - // the contro points and so some math to figure out where the lines are - // in the first place. - - // Compute the integer boudns of tick0 + n * dtick that fall within the range - // (roughly speaking): - // Give this a nice generous epsilon. We use at as * (1 + eps) in order to make - // inequalities a little tolerant in a more or less correct manner: - eps = 5e-15; - bounds = [ - Math.floor((data[data.length - 1] - axis.tick0) / axis.dtick * (1 + eps)), - Math.ceil((data[0] - axis.tick0) / axis.dtick / (1 + eps)) - ].sort(function(a, b) {return a - b;}); - - // Unpack sorted values so we can be sure to avoid infinite loops if something - // is backwards: - n1 = bounds[0]; - n2 = bounds[1]; - - for(n = n1; n <= n2; n++) { - value = axis.tick0 + axis.dtick * n; - - gridlines.push(extendFlat(constructValueGridline(value), { - color: axis.gridcolor, - width: axis.gridwidth - })); - } - - for(n = n1 - 1; n < n2 + 1; n++) { - value = axis.tick0 + axis.dtick * n; - - for(i = 0; i < axis.minorgridcount; i++) { - v = value + axis.dtick * (i + 1) / (axis.minorgridcount + 1); - if(v < data[0] || v > data[data.length - 1]) continue; - minorgridlines.push(extendFlat(constructValueGridline(v), { - color: axis.minorgridcolor, - width: axis.minorgridwidth - })); - } - } - - if(axis.startline) { - boundarylines.push(extendFlat(constructValueGridline(data[0]), { - color: axis.startlinecolor, - width: axis.startlinewidth - })); - } - - if(axis.endline) { - boundarylines.push(extendFlat(constructValueGridline(data[data.length - 1]), { - color: axis.endlinecolor, - width: axis.endlinewidth - })); - } - } -}; - -},{"../../lib/extend":710,"../../plots/cartesian/axes":767}],905:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = function calcLabels(trace, axis) { - var i, tobj, prefix, suffix, gridline; - - var labels = axis._labels = []; - var gridlines = axis._gridlines; - - for(i = 0; i < gridlines.length; i++) { - gridline = gridlines[i]; - - if(['start', 'both'].indexOf(axis.showticklabels) !== -1) { - tobj = Axes.tickText(axis, gridline.value); - - extendFlat(tobj, { - prefix: prefix, - suffix: suffix, - endAnchor: true, - xy: gridline.xy(0), - dxy: gridline.dxy(0, 0), - axis: gridline.axis, - length: gridline.crossAxis.length, - font: gridline.axis.tickfont, - isFirst: i === 0, - isLast: i === gridlines.length - 1 - }); - - labels.push(tobj); - } - - if(['end', 'both'].indexOf(axis.showticklabels) !== -1) { - tobj = Axes.tickText(axis, gridline.value); - - extendFlat(tobj, { - endAnchor: false, - xy: gridline.xy(gridline.crossLength - 1), - dxy: gridline.dxy(gridline.crossLength - 2, 1), - axis: gridline.axis, - length: gridline.crossAxis.length, - font: gridline.axis.tickfont, - isFirst: i === 0, - isLast: i === gridlines.length - 1 - }); - - labels.push(tobj); - } - } -}; - -},{"../../lib/extend":710,"../../plots/cartesian/axes":767}],906:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* - * Compute the tangent vector according to catmull-rom cubic splines (centripetal, - * I think). That differs from the control point in two ways: - * 1. It is a vector, not a position relative to the point - * 2. the vector is longer than the position relative to p1 by a factor of 3 - * - * Close to the boundaries, we'll use these as *quadratic control points, so that - * to make a nice grid, we'll need to divide the tangent by 2 instead of 3. (The - * math works out this way if you work through the bezier derivatives) - */ -var CatmullRomExp = 0.5; -module.exports = function makeControlPoints(p0, p1, p2, smoothness) { - var d1x = p0[0] - p1[0]; - var d1y = p0[1] - p1[1]; - var d2x = p2[0] - p1[0]; - var d2y = p2[1] - p1[1]; - var d1a = Math.pow(d1x * d1x + d1y * d1y, CatmullRomExp / 2); - var d2a = Math.pow(d2x * d2x + d2y * d2y, CatmullRomExp / 2); - var numx = (d2a * d2a * d1x - d1a * d1a * d2x) * smoothness; - var numy = (d2a * d2a * d1y - d1a * d1a * d2y) * smoothness; - var denom1 = d2a * (d1a + d2a) * 3; - var denom2 = d1a * (d1a + d2a) * 3; - - return [[ - p1[0] + (denom1 && numx / denom1), - p1[1] + (denom1 && numy / denom1) - ], [ - p1[0] - (denom2 && numx / denom2), - p1[1] - (denom2 && numy / denom2) - ]]; -}; - -},{}],907:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; - -/* - * Construct a 2D array of cheater values given a, b, and a slope. - * If - */ -module.exports = function(a, b, cheaterslope) { - var i, j, ascal, bscal, aval, bval; - var data = []; - - var na = isArrayOrTypedArray(a) ? a.length : a; - var nb = isArrayOrTypedArray(b) ? b.length : b; - var adata = isArrayOrTypedArray(a) ? a : null; - var bdata = isArrayOrTypedArray(b) ? b : null; - - // If we're using data, scale it so that for data that's just barely - // not evenly spaced, the switch to value-based indexing is continuous. - // This means evenly spaced data should look the same whether value - // or index cheatertype. - if(adata) { - ascal = (adata.length - 1) / (adata[adata.length - 1] - adata[0]) / (na - 1); - } - - if(bdata) { - bscal = (bdata.length - 1) / (bdata[bdata.length - 1] - bdata[0]) / (nb - 1); - } - - var xval; - var xmin = Infinity; - var xmax = -Infinity; - for(j = 0; j < nb; j++) { - data[j] = []; - bval = bdata ? (bdata[j] - bdata[0]) * bscal : j / (nb - 1); - for(i = 0; i < na; i++) { - aval = adata ? (adata[i] - adata[0]) * ascal : i / (na - 1); - xval = aval - bval * cheaterslope; - xmin = Math.min(xval, xmin); - xmax = Math.max(xval, xmax); - data[j][i] = xval; - } - } - - // Normalize cheater values to the 0-1 range. This comes into play when you have - // multiple cheater plots. After careful consideration, it seems better if cheater - // values are normalized to a consistent range. Otherwise one cheater affects the - // layout of other cheaters on the same axis. - var slope = 1.0 / (xmax - xmin); - var offset = -xmin * slope; - for(j = 0; j < nb; j++) { - for(i = 0; i < na; i++) { - data[j][i] = slope * data[j][i] + offset; - } - } - - return data; -}; - -},{"../../lib":719}],908:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var makeControlPoints = _dereq_('./catmull_rom'); -var ensureArray = _dereq_('../../lib').ensureArray; - -/* - * Turns a coarse grid into a fine grid with control points. - * - * Here's an ASCII representation: - * - * o ----- o ----- o ----- o - * | | | | - * | | | | - * | | | | - * o ----- o ----- o ----- o - * | | | | - * | | | | - * ^ | | | | - * | o ----- o ----- o ----- o - * b | | | | | - * | | | | | - * | | | | | - * o ----- o ----- o ----- o - * ------> - * a - * - * First of all, note that we want to do this in *cartesian* space. This means - * we might run into problems when there are extreme differences in x/y scaling, - * but the alternative is that the topology of the contours might actually be - * view-dependent, which seems worse. As a fallback, the only parameter that - * actually affects the result is the *aspect ratio*, so that we can at least - * improve the situation a bit without going all the way to screen coordinates. - * - * This function flattens the points + tangents into a slightly denser grid of - * *control points*. The resulting grid looks like this: - * - * 9 +--o-o--+ -o-o--+--o-o--+ - * 8 o o o o o o o o o o - * | | | | - * 7 o o o o o o o o o o - * 6 +--o-o--+ -o-o--+--o-o--+ - * 5 o o o o o o o o o o - * | | | | - * ^ 4 o o o o o o o o o o - * | 3 +--o-o--+ -o-o--+--o-o--+ - * b | 2 o o o o o o o o o o - * | | | | | - * | 1 o o o o o o o o o o - * 0 +--o-o--+ -o-o--+--o-o--+ - * 0 1 2 3 4 5 6 7 8 9 - * ------> - * a - * - * where `o`s represent newly-computed control points. the resulting dimension is - * - * (m - 1) * 3 + 1 - * = 3 * m - 2 - * - * We could simply store the tangents separately, but that's a nightmare to organize - * in two dimensions since we'll be slicing grid lines in both directions and since - * that basically requires very nearly just as much storage as just storing the dense - * grid. - * - * Wow! - */ - - -/* - * Catmull-rom is biased at the boundaries toward the interior and we actually - * can't use catmull-rom to compute the control point closest to (but inside) - * the boundary. - * - * A note on plotly's spline interpolation. It uses the catmull rom control point - * closest to the boundary *as* a quadratic control point. This seems incorrect, - * so I've elected not to follow that. Given control points 0 and 1, regular plotly - * splines give *equivalent* cubic control points: - * - * Input: - * - * boundary - * | | - * p0 p2 p3 --> interior - * 0.0 0.667 1.0 - * | | - * - * Cubic-equivalent of what plotly splines draw:: - * - * boundary - * | | - * p0 p1 p2 p3 --> interior - * 0.0 0.4444 0.8888 1.0 - * | | - * - * What this function fills in: - * - * boundary - * | | - * p0 p1 p2 p3 --> interior - * 0.0 0.333 0.667 1.0 - * | | - * - * Parameters: - * p0: boundary point - * p2: catmull rom point based on computation at p3 - * p3: first grid point - * - * Of course it works whichever way it's oriented; you just need to interpret the - * input/output accordingly. - */ -function inferCubicControlPoint(p0, p2, p3) { - // Extend p1 away from p0 by 50%. This is the equivalent quadratic point that - // would give the same slope as catmull rom at p0. - var p2e0 = -0.5 * p3[0] + 1.5 * p2[0]; - var p2e1 = -0.5 * p3[1] + 1.5 * p2[1]; - - return [ - (2 * p2e0 + p0[0]) / 3, - (2 * p2e1 + p0[1]) / 3, - ]; -} - -module.exports = function computeControlPoints(xe, ye, x, y, asmoothing, bsmoothing) { - var i, j, ie, je, xej, yej, xj, yj, cp, p1; - // At this point, we know these dimensions are correct and representative of - // the whole 2D arrays: - var na = x[0].length; - var nb = x.length; - - // (n)umber of (e)xpanded points: - var nea = asmoothing ? 3 * na - 2 : na; - var neb = bsmoothing ? 3 * nb - 2 : nb; - - xe = ensureArray(xe, neb); - ye = ensureArray(ye, neb); - - for(ie = 0; ie < neb; ie++) { - xe[ie] = ensureArray(xe[ie], nea); - ye[ie] = ensureArray(ye[ie], nea); - } - - // This loop fills in the X'd points: - // - // . . . . - // . . . . - // | | | | - // | | | | - // X ----- X ----- X ----- X - // | | | | - // | | | | - // | | | | - // X ----- X ----- X ----- X - // - // - // ie = (i) (e)xpanded: - for(j = 0, je = 0; j < nb; j++, je += bsmoothing ? 3 : 1) { - xej = xe[je]; - yej = ye[je]; - xj = x[j]; - yj = y[j]; - - // je = (j) (e)xpanded: - for(i = 0, ie = 0; i < na; i++, ie += asmoothing ? 3 : 1) { - xej[ie] = xj[i]; - yej[ie] = yj[i]; - } - } - - if(asmoothing) { - // If there's a-smoothing, this loop fills in the X'd points with catmull-rom - // control points computed along the a-axis: - // . . . . - // . . . . - // | | | | - // | | | | - // o -Y-X- o -X-X- o -X-Y- o - // | | | | - // | | | | - // | | | | - // o -Y-X- o -X-X- o -X-Y- o - // - // i: 0 1 2 3 - // ie: 0 1 3 3 4 5 6 7 8 9 - // - // ------> - // a - // - for(j = 0, je = 0; j < nb; j++, je += bsmoothing ? 3 : 1) { - // Fill in the points marked X for this a-row: - for(i = 1, ie = 3; i < na - 1; i++, ie += 3) { - cp = makeControlPoints( - [x[j][i - 1], y[j][i - 1]], - [x[j][i ], y[j][i]], - [x[j][i + 1], y[j][i + 1]], - asmoothing - ); - - xe[je][ie - 1] = cp[0][0]; - ye[je][ie - 1] = cp[0][1]; - xe[je][ie + 1] = cp[1][0]; - ye[je][ie + 1] = cp[1][1]; - } - - // The very first cubic interpolation point (to the left for i = 1 above) is - // used as a *quadratic* interpolation point by the spline drawing function - // which isn't really correct. But for the sake of consistency, we'll use it - // as such. Since we're using cubic splines, that means we need to shorten the - // tangent by 1/3 and also construct a new cubic spline control point 1/3 from - // the original to the i = 0 point. - p1 = inferCubicControlPoint( - [xe[je][0], ye[je][0]], - [xe[je][2], ye[je][2]], - [xe[je][3], ye[je][3]] - ); - xe[je][1] = p1[0]; - ye[je][1] = p1[1]; - - // Ditto last points, sans explanation: - p1 = inferCubicControlPoint( - [xe[je][nea - 1], ye[je][nea - 1]], - [xe[je][nea - 3], ye[je][nea - 3]], - [xe[je][nea - 4], ye[je][nea - 4]] - ); - xe[je][nea - 2] = p1[0]; - ye[je][nea - 2] = p1[1]; - } - } - - if(bsmoothing) { - // If there's a-smoothing, this loop fills in the X'd points with catmull-rom - // control points computed along the b-axis: - // . . . . - // X X X X X X X X X X - // | | | | - // X X X X X X X X X X - // o -o-o- o -o-o- o -o-o- o - // X X X X X X X X X X - // | | | | - // Y Y Y Y Y Y Y Y Y Y - // o -o-o- o -o-o- o -o-o- o - // - // i: 0 1 2 3 - // ie: 0 1 3 3 4 5 6 7 8 9 - // - // ------> - // a - // - for(ie = 0; ie < nea; ie++) { - for(je = 3; je < neb - 3; je += 3) { - cp = makeControlPoints( - [xe[je - 3][ie], ye[je - 3][ie]], - [xe[je][ie], ye[je][ie]], - [xe[je + 3][ie], ye[je + 3][ie]], - bsmoothing - ); - - xe[je - 1][ie] = cp[0][0]; - ye[je - 1][ie] = cp[0][1]; - xe[je + 1][ie] = cp[1][0]; - ye[je + 1][ie] = cp[1][1]; - } - // Do the same boundary condition magic for these control points marked Y above: - p1 = inferCubicControlPoint( - [xe[0][ie], ye[0][ie]], - [xe[2][ie], ye[2][ie]], - [xe[3][ie], ye[3][ie]] - ); - xe[1][ie] = p1[0]; - ye[1][ie] = p1[1]; - - p1 = inferCubicControlPoint( - [xe[neb - 1][ie], ye[neb - 1][ie]], - [xe[neb - 3][ie], ye[neb - 3][ie]], - [xe[neb - 4][ie], ye[neb - 4][ie]] - ); - xe[neb - 2][ie] = p1[0]; - ye[neb - 2][ie] = p1[1]; - } - } - - if(asmoothing && bsmoothing) { - // Do one more pass, this time recomputing exactly what we just computed. - // It's overdetermined since we're peforming catmull-rom in two directions, - // so we'll just average the overdetermined. These points don't lie along the - // grid lines, so note that only grid lines will follow normal plotly spline - // interpolation. - // - // Unless of course there was no b smoothing. Then these intermediate points - // don't actually exist and this section is bypassed. - // . . . . - // o X X o X X o X X o - // | | | | - // o X X o X X o X X o - // o -o-o- o -o-o- o -o-o- o - // o X X o X X o X X o - // | | | | - // o Y Y o Y Y o Y Y o - // o -o-o- o -o-o- o -o-o- o - // - // i: 0 1 2 3 - // ie: 0 1 3 3 4 5 6 7 8 9 - // - // ------> - // a - // - for(je = 1; je < neb; je += (je + 1) % 3 === 0 ? 2 : 1) { - // Fill in the points marked X for this a-row: - for(ie = 3; ie < nea - 3; ie += 3) { - cp = makeControlPoints( - [xe[je][ie - 3], ye[je][ie - 3]], - [xe[je][ie], ye[je][ie]], - [xe[je][ie + 3], ye[je][ie + 3]], - asmoothing - ); - - xe[je][ie - 1] = 0.5 * (xe[je][ie - 1] + cp[0][0]); - ye[je][ie - 1] = 0.5 * (ye[je][ie - 1] + cp[0][1]); - xe[je][ie + 1] = 0.5 * (xe[je][ie + 1] + cp[1][0]); - ye[je][ie + 1] = 0.5 * (ye[je][ie + 1] + cp[1][1]); - } - - // This case is just slightly different. The computation is the same, - // but having computed this, we'll average with the existing result. - p1 = inferCubicControlPoint( - [xe[je][0], ye[je][0]], - [xe[je][2], ye[je][2]], - [xe[je][3], ye[je][3]] - ); - xe[je][1] = 0.5 * (xe[je][1] + p1[0]); - ye[je][1] = 0.5 * (ye[je][1] + p1[1]); - - p1 = inferCubicControlPoint( - [xe[je][nea - 1], ye[je][nea - 1]], - [xe[je][nea - 3], ye[je][nea - 3]], - [xe[je][nea - 4], ye[je][nea - 4]] - ); - xe[je][nea - 2] = 0.5 * (xe[je][nea - 2] + p1[0]); - ye[je][nea - 2] = 0.5 * (ye[je][nea - 2] + p1[1]); - } - } - - return [xe, ye]; -}; - -},{"../../lib":719,"./catmull_rom":906}],909:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = { - RELATIVE_CULL_TOLERANCE: 1e-6 -}; - -},{}],910:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* - * Evaluates the derivative of a list of control point arrays. That is, it expects an array or arrays - * that are expanded relative to the raw data to include the bicubic control points, if applicable. If - * only linear interpolation is desired, then the data points correspond 1-1 along that axis to the - * data itself. Since it's catmull-rom splines in either direction note in particular that the - * derivatives are discontinuous across cell boundaries. That's the reason you need both the *cell* - * and the *point within the cell*. - * - * Also note that the discontinuity of the derivative is in magnitude only. The direction *is* - * continuous across cell boundaries. - * - * For example, to compute the derivative of the xcoordinate halfway betwen the 7 and 8th i-gridpoints - * and the 10th and 11th j-gridpoints given bicubic smoothing in both dimensions, you'd write: - * - * var deriv = createIDerivativeEvaluator([x], 1, 1); - * - * var dxdi = deriv([], 7, 10, 0.5, 0.5); - * // => [0.12345] - * - * Since there'd be a bunch of duplicate computation to compute multiple derivatives, you can double - * this up by providing more arrays: - * - * var deriv = createIDerivativeEvaluator([x, y], 1, 1); - * - * var dxdi = deriv([], 7, 10, 0.5, 0.5); - * // => [0.12345, 0.78910] - * - * NB: It's presumed that at this point all data has been sanitized and is valid numerical data arrays - * of the correct dimension. - */ -module.exports = function(arrays, asmoothing, bsmoothing) { - if(asmoothing && bsmoothing) { - return function(out, i0, j0, u, v) { - if(!out) out = []; - var f0, f1, f2, f3, ak, k; - - // Since it's a grid of control points, the actual indices are * 3: - i0 *= 3; - j0 *= 3; - - // Precompute some numbers: - var u2 = u * u; - var ou = 1 - u; - var ou2 = ou * ou; - var ouu2 = ou * u * 2; - var a = -3 * ou2; - var b = 3 * (ou2 - ouu2); - var c = 3 * (ouu2 - u2); - var d = 3 * u2; - - var v2 = v * v; - var v3 = v2 * v; - var ov = 1 - v; - var ov2 = ov * ov; - var ov3 = ov2 * ov; - - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - // Compute the derivatives in the u-direction: - f0 = a * ak[j0 ][i0] + b * ak[j0 ][i0 + 1] + c * ak[j0 ][i0 + 2] + d * ak[j0 ][i0 + 3]; - f1 = a * ak[j0 + 1][i0] + b * ak[j0 + 1][i0 + 1] + c * ak[j0 + 1][i0 + 2] + d * ak[j0 + 1][i0 + 3]; - f2 = a * ak[j0 + 2][i0] + b * ak[j0 + 2][i0 + 1] + c * ak[j0 + 2][i0 + 2] + d * ak[j0 + 2][i0 + 3]; - f3 = a * ak[j0 + 3][i0] + b * ak[j0 + 3][i0 + 1] + c * ak[j0 + 3][i0 + 2] + d * ak[j0 + 3][i0 + 3]; - - // Now just interpolate in the v-direction since it's all separable: - out[k] = ov3 * f0 + 3 * (ov2 * v * f1 + ov * v2 * f2) + v3 * f3; - } - - return out; - }; - } else if(asmoothing) { - // Handle smooth in the a-direction but linear in the b-direction by performing four - // linear interpolations followed by one cubic interpolation of the result - return function(out, i0, j0, u, v) { - if(!out) out = []; - var f0, f1, k, ak; - i0 *= 3; - var u2 = u * u; - var ou = 1 - u; - var ou2 = ou * ou; - var ouu2 = ou * u * 2; - var a = -3 * ou2; - var b = 3 * (ou2 - ouu2); - var c = 3 * (ouu2 - u2); - var d = 3 * u2; - var ov = 1 - v; - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - f0 = a * ak[j0 ][i0] + b * ak[j0 ][i0 + 1] + c * ak[j0 ][i0 + 2] + d * ak[j0 ][i0 + 3]; - f1 = a * ak[j0 + 1][i0] + b * ak[j0 + 1][i0 + 1] + c * ak[j0 + 1][i0 + 2] + d * ak[j0 + 1][i0 + 3]; - - out[k] = ov * f0 + v * f1; - } - return out; - }; - } else if(bsmoothing) { - // Same as the above case, except reversed. I've disabled the no-unused vars rule - // so that this function is fully interpolation-agnostic. Otherwise it would need - // to be called differently in different cases. Which wouldn't be the worst, but - /* eslint-disable no-unused-vars */ - return function(out, i0, j0, u, v) { - /* eslint-enable no-unused-vars */ - if(!out) out = []; - var f0, f1, f2, f3, k, ak; - j0 *= 3; - var v2 = v * v; - var v3 = v2 * v; - var ov = 1 - v; - var ov2 = ov * ov; - var ov3 = ov2 * ov; - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - f0 = ak[j0][i0 + 1] - ak[j0][i0]; - f1 = ak[j0 + 1][i0 + 1] - ak[j0 + 1][i0]; - f2 = ak[j0 + 2][i0 + 1] - ak[j0 + 2][i0]; - f3 = ak[j0 + 3][i0 + 1] - ak[j0 + 3][i0]; - - out[k] = ov3 * f0 + 3 * (ov2 * v * f1 + ov * v2 * f2) + v3 * f3; - } - return out; - }; - } else { - // Finally, both directions are linear: - /* eslint-disable no-unused-vars */ - return function(out, i0, j0, u, v) { - /* eslint-enable no-unused-vars */ - if(!out) out = []; - var f0, f1, k, ak; - var ov = 1 - v; - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - f0 = ak[j0][i0 + 1] - ak[j0][i0]; - f1 = ak[j0 + 1][i0 + 1] - ak[j0 + 1][i0]; - - out[k] = ov * f0 + v * f1; - } - return out; - }; - } -}; - -},{}],911:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function(arrays, asmoothing, bsmoothing) { - if(asmoothing && bsmoothing) { - return function(out, i0, j0, u, v) { - if(!out) out = []; - var f0, f1, f2, f3, ak, k; - - // Since it's a grid of control points, the actual indices are * 3: - i0 *= 3; - j0 *= 3; - - // Precompute some numbers: - var u2 = u * u; - var u3 = u2 * u; - var ou = 1 - u; - var ou2 = ou * ou; - var ou3 = ou2 * ou; - - var v2 = v * v; - var ov = 1 - v; - var ov2 = ov * ov; - var ovv2 = ov * v * 2; - var a = -3 * ov2; - var b = 3 * (ov2 - ovv2); - var c = 3 * (ovv2 - v2); - var d = 3 * v2; - - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - - // Compute the derivatives in the v-direction: - f0 = a * ak[j0][i0] + b * ak[j0 + 1][i0] + c * ak[j0 + 2][i0] + d * ak[j0 + 3][i0]; - f1 = a * ak[j0][i0 + 1] + b * ak[j0 + 1][i0 + 1] + c * ak[j0 + 2][i0 + 1] + d * ak[j0 + 3][i0 + 1]; - f2 = a * ak[j0][i0 + 2] + b * ak[j0 + 1][i0 + 2] + c * ak[j0 + 2][i0 + 2] + d * ak[j0 + 3][i0 + 2]; - f3 = a * ak[j0][i0 + 3] + b * ak[j0 + 1][i0 + 3] + c * ak[j0 + 2][i0 + 3] + d * ak[j0 + 3][i0 + 3]; - - // Now just interpolate in the v-direction since it's all separable: - out[k] = ou3 * f0 + 3 * (ou2 * u * f1 + ou * u2 * f2) + u3 * f3; - } - - return out; - }; - } else if(asmoothing) { - // Handle smooth in the a-direction but linear in the b-direction by performing four - // linear interpolations followed by one cubic interpolation of the result - return function(out, i0, j0, v, u) { - if(!out) out = []; - var f0, f1, f2, f3, k, ak; - i0 *= 3; - var u2 = u * u; - var u3 = u2 * u; - var ou = 1 - u; - var ou2 = ou * ou; - var ou3 = ou2 * ou; - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - - f0 = ak[j0 + 1][i0] - ak[j0][i0]; - f1 = ak[j0 + 1][i0 + 1] - ak[j0][i0 + 1]; - f2 = ak[j0 + 1][i0 + 2] - ak[j0][i0 + 2]; - f3 = ak[j0 + 1][i0 + 3] - ak[j0][i0 + 3]; - - out[k] = ou3 * f0 + 3 * (ou2 * u * f1 + ou * u2 * f2) + u3 * f3; - - // mathematically equivalent: - // f0 = ou3 * ak[j0 ][i0] + 3 * (ou2 * u * ak[j0 ][i0 + 1] + ou * u2 * ak[j0 ][i0 + 2]) + u3 * ak[j0 ][i0 + 3]; - // f1 = ou3 * ak[j0 + 1][i0] + 3 * (ou2 * u * ak[j0 + 1][i0 + 1] + ou * u2 * ak[j0 + 1][i0 + 2]) + u3 * ak[j0 + 1][i0 + 3]; - // out[k] = f1 - f0; - } - return out; - }; - } else if(bsmoothing) { - // Same as the above case, except reversed: - /* eslint-disable no-unused-vars */ - return function(out, i0, j0, u, v) { - /* eslint-enable no-unused-vars */ - if(!out) out = []; - var f0, f1, k, ak; - j0 *= 3; - var ou = 1 - u; - var v2 = v * v; - var ov = 1 - v; - var ov2 = ov * ov; - var ovv2 = ov * v * 2; - var a = -3 * ov2; - var b = 3 * (ov2 - ovv2); - var c = 3 * (ovv2 - v2); - var d = 3 * v2; - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - f0 = a * ak[j0][i0] + b * ak[j0 + 1][i0] + c * ak[j0 + 2][i0] + d * ak[j0 + 3][i0]; - f1 = a * ak[j0][i0 + 1] + b * ak[j0 + 1][i0 + 1] + c * ak[j0 + 2][i0 + 1] + d * ak[j0 + 3][i0 + 1]; - - out[k] = ou * f0 + u * f1; - } - return out; - }; - } else { - // Finally, both directions are linear: - /* eslint-disable no-unused-vars */ - return function(out, i0, j0, v, u) { - /* eslint-enable no-unused-vars */ - if(!out) out = []; - var f0, f1, k, ak; - var ov = 1 - v; - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - f0 = ak[j0 + 1][i0] - ak[j0][i0]; - f1 = ak[j0 + 1][i0 + 1] - ak[j0][i0 + 1]; - - out[k] = ov * f0 + v * f1; - } - return out; - }; - } -}; - -},{}],912:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* - * Return a function that evaluates a set of linear or bicubic control points. - * This will get evaluated a lot, so we'll at least do a bit of extra work to - * flatten some of the choices. In particular, we'll unroll the linear/bicubic - * combinations and we'll allow computing results in parallel to cut down - * on repeated arithmetic. - * - * Take note that we don't search for the correct range in this function. The - * reason is for consistency due to the corrresponding derivative function. In - * particular, the derivatives aren't continuous across cells, so it's important - * to be able control whether the derivative at a cell boundary is approached - * from one side or the other. - */ -module.exports = function(arrays, na, nb, asmoothing, bsmoothing) { - var imax = na - 2; - var jmax = nb - 2; - - if(asmoothing && bsmoothing) { - return function(out, i, j) { - if(!out) out = []; - var f0, f1, f2, f3, ak, k; - - var i0 = Math.max(0, Math.min(Math.floor(i), imax)); - var j0 = Math.max(0, Math.min(Math.floor(j), jmax)); - var u = Math.max(0, Math.min(1, i - i0)); - var v = Math.max(0, Math.min(1, j - j0)); - - // Since it's a grid of control points, the actual indices are * 3: - i0 *= 3; - j0 *= 3; - - // Precompute some numbers: - var u2 = u * u; - var u3 = u2 * u; - var ou = 1 - u; - var ou2 = ou * ou; - var ou3 = ou2 * ou; - - var v2 = v * v; - var v3 = v2 * v; - var ov = 1 - v; - var ov2 = ov * ov; - var ov3 = ov2 * ov; - - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - f0 = ou3 * ak[j0][i0] + 3 * (ou2 * u * ak[j0][i0 + 1] + ou * u2 * ak[j0][i0 + 2]) + u3 * ak[j0][i0 + 3]; - f1 = ou3 * ak[j0 + 1][i0] + 3 * (ou2 * u * ak[j0 + 1][i0 + 1] + ou * u2 * ak[j0 + 1][i0 + 2]) + u3 * ak[j0 + 1][i0 + 3]; - f2 = ou3 * ak[j0 + 2][i0] + 3 * (ou2 * u * ak[j0 + 2][i0 + 1] + ou * u2 * ak[j0 + 2][i0 + 2]) + u3 * ak[j0 + 2][i0 + 3]; - f3 = ou3 * ak[j0 + 3][i0] + 3 * (ou2 * u * ak[j0 + 3][i0 + 1] + ou * u2 * ak[j0 + 3][i0 + 2]) + u3 * ak[j0 + 3][i0 + 3]; - out[k] = ov3 * f0 + 3 * (ov2 * v * f1 + ov * v2 * f2) + v3 * f3; - } - - return out; - }; - } else if(asmoothing) { - // Handle smooth in the a-direction but linear in the b-direction by performing four - // linear interpolations followed by one cubic interpolation of the result - return function(out, i, j) { - if(!out) out = []; - - var i0 = Math.max(0, Math.min(Math.floor(i), imax)); - var j0 = Math.max(0, Math.min(Math.floor(j), jmax)); - var u = Math.max(0, Math.min(1, i - i0)); - var v = Math.max(0, Math.min(1, j - j0)); - - var f0, f1, f2, f3, k, ak; - i0 *= 3; - var u2 = u * u; - var u3 = u2 * u; - var ou = 1 - u; - var ou2 = ou * ou; - var ou3 = ou2 * ou; - var ov = 1 - v; - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - f0 = ov * ak[j0][i0] + v * ak[j0 + 1][i0]; - f1 = ov * ak[j0][i0 + 1] + v * ak[j0 + 1][i0 + 1]; - f2 = ov * ak[j0][i0 + 2] + v * ak[j0 + 1][i0 + 1]; - f3 = ov * ak[j0][i0 + 3] + v * ak[j0 + 1][i0 + 1]; - - out[k] = ou3 * f0 + 3 * (ou2 * u * f1 + ou * u2 * f2) + u3 * f3; - } - return out; - }; - } else if(bsmoothing) { - // Same as the above case, except reversed: - return function(out, i, j) { - if(!out) out = []; - - var i0 = Math.max(0, Math.min(Math.floor(i), imax)); - var j0 = Math.max(0, Math.min(Math.floor(j), jmax)); - var u = Math.max(0, Math.min(1, i - i0)); - var v = Math.max(0, Math.min(1, j - j0)); - - var f0, f1, f2, f3, k, ak; - j0 *= 3; - var v2 = v * v; - var v3 = v2 * v; - var ov = 1 - v; - var ov2 = ov * ov; - var ov3 = ov2 * ov; - var ou = 1 - u; - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - f0 = ou * ak[j0][i0] + u * ak[j0][i0 + 1]; - f1 = ou * ak[j0 + 1][i0] + u * ak[j0 + 1][i0 + 1]; - f2 = ou * ak[j0 + 2][i0] + u * ak[j0 + 2][i0 + 1]; - f3 = ou * ak[j0 + 3][i0] + u * ak[j0 + 3][i0 + 1]; - - out[k] = ov3 * f0 + 3 * (ov2 * v * f1 + ov * v2 * f2) + v3 * f3; - } - return out; - }; - } else { - // Finally, both directions are linear: - return function(out, i, j) { - if(!out) out = []; - - var i0 = Math.max(0, Math.min(Math.floor(i), imax)); - var j0 = Math.max(0, Math.min(Math.floor(j), jmax)); - var u = Math.max(0, Math.min(1, i - i0)); - var v = Math.max(0, Math.min(1, j - j0)); - - var f0, f1, k, ak; - var ov = 1 - v; - var ou = 1 - u; - for(k = 0; k < arrays.length; k++) { - ak = arrays[k]; - f0 = ou * ak[j0][i0] + u * ak[j0][i0 + 1]; - f1 = ou * ak[j0 + 1][i0] + u * ak[j0 + 1][i0 + 1]; - - out[k] = ov * f0 + v * f1; - } - return out; - }; - } -}; - -},{}],913:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var handleXYDefaults = _dereq_('./xy_defaults'); -var handleABDefaults = _dereq_('./ab_defaults'); -var attributes = _dereq_('./attributes'); -var colorAttrs = _dereq_('../../components/color/attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, dfltColor, fullLayout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - traceOut._clipPathId = 'clip' + traceOut.uid + 'carpet'; - - var defaultColor = coerce('color', colorAttrs.defaultLine); - Lib.coerceFont(coerce, 'font'); - - coerce('carpet'); - - handleABDefaults(traceIn, traceOut, fullLayout, coerce, defaultColor); - - if(!traceOut.a || !traceOut.b) { - traceOut.visible = false; - return; - } - - if(traceOut.a.length < 3) { - traceOut.aaxis.smoothing = 0; - } - - if(traceOut.b.length < 3) { - traceOut.baxis.smoothing = 0; - } - - // NB: the input is x/y arrays. You should know that the *first* dimension of x and y - // corresponds to b and the second to a. This sounds backwards but ends up making sense - // the important part to know is that when you write y[j][i], j goes from 0 to b.length - 1 - // and i goes from 0 to a.length - 1. - var validData = handleXYDefaults(traceIn, traceOut, coerce); - if(!validData) { - traceOut.visible = false; - } - - if(traceOut._cheater) { - coerce('cheaterslope'); - } -}; - -},{"../../components/color/attributes":592,"../../lib":719,"./ab_defaults":896,"./attributes":898,"./xy_defaults":922}],914:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - plot: _dereq_('./plot'), - calc: _dereq_('./calc'), - animatable: true, - isContainer: true, // so carpet traces get `calc` before other traces - - moduleType: 'trace', - name: 'carpet', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', 'carpet', 'carpetAxis', 'notLegendIsolatable', 'noMultiCategory'], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"./attributes":898,"./calc":902,"./defaults":913,"./plot":919}],915:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/* - * Given a trace, look up the carpet axis by carpet. - */ -module.exports = function(gd, trace) { - var n = gd._fullData.length; - var firstAxis; - for(var i = 0; i < n; i++) { - var maybeCarpet = gd._fullData[i]; - - if(maybeCarpet.index === trace.index) continue; - - if(maybeCarpet.type === 'carpet') { - if(!firstAxis) { - firstAxis = maybeCarpet; - } - - if(maybeCarpet.carpet === trace.carpet) { - return maybeCarpet; - } - } - } - - return firstAxis; -}; - -},{}],916:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function makePath(xp, yp, isBicubic) { - // Prevent d3 errors that would result otherwise: - if(xp.length === 0) return ''; - - var i; - var path = []; - var stride = isBicubic ? 3 : 1; - for(i = 0; i < xp.length; i += stride) { - path.push(xp[i] + ',' + yp[i]); - - if(isBicubic && i < xp.length - stride) { - path.push('C'); - path.push([ - xp[i + 1] + ',' + yp[i + 1], - xp[i + 2] + ',' + yp[i + 2] + ' ', - ].join(' ')); - } - } - return path.join(isBicubic ? '' : 'L'); -}; - -},{}],917:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; - -/* - * Map an array of x or y coordinates (c) to screen-space pixel coordinates (p). - * The output array is optional, but if provided, it will be reused without - * reallocation to the extent possible. - */ -module.exports = function mapArray(out, data, func) { - var i; - - if(!isArrayOrTypedArray(out)) { - // If not an array, make it an array: - out = []; - } else if(out.length > data.length) { - // If too long, truncate. (If too short, it will grow - // automatically so we don't care about that case) - out = out.slice(0, data.length); - } - - for(i = 0; i < data.length; i++) { - out[i] = func(data[i]); - } - - return out; -}; - -},{"../../lib":719}],918:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = function orientText(trace, xaxis, yaxis, xy, dxy, refDxy) { - var dx = dxy[0] * trace.dpdx(xaxis); - var dy = dxy[1] * trace.dpdy(yaxis); - var flip = 1; - - var offsetMultiplier = 1.0; - if(refDxy) { - var l1 = Math.sqrt(dxy[0] * dxy[0] + dxy[1] * dxy[1]); - var l2 = Math.sqrt(refDxy[0] * refDxy[0] + refDxy[1] * refDxy[1]); - var dot = (dxy[0] * refDxy[0] + dxy[1] * refDxy[1]) / l1 / l2; - offsetMultiplier = Math.max(0.0, dot); - } - - var angle = Math.atan2(dy, dx) * 180 / Math.PI; - if(angle < -90) { - angle += 180; - flip = -flip; - } else if(angle > 90) { - angle -= 180; - flip = -flip; - } - - return { - angle: angle, - flip: flip, - p: trace.c2p(xy, xaxis, yaxis), - offsetMultplier: offsetMultiplier - }; -}; - -},{}],919:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var Drawing = _dereq_('../../components/drawing'); -var map1dArray = _dereq_('./map_1d_array'); -var makepath = _dereq_('./makepath'); -var orientText = _dereq_('./orient_text'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var Lib = _dereq_('../../lib'); -var alignmentConstants = _dereq_('../../constants/alignment'); - -module.exports = function plot(gd, plotinfo, cdcarpet, carpetLayer) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - var fullLayout = gd._fullLayout; - var clipLayer = fullLayout._clips; - - Lib.makeTraceGroups(carpetLayer, cdcarpet, 'trace').each(function(cd) { - var axisLayer = d3.select(this); - var cd0 = cd[0]; - var trace = cd0.trace; - var aax = trace.aaxis; - var bax = trace.baxis; - - var minorLayer = Lib.ensureSingle(axisLayer, 'g', 'minorlayer'); - var majorLayer = Lib.ensureSingle(axisLayer, 'g', 'majorlayer'); - var boundaryLayer = Lib.ensureSingle(axisLayer, 'g', 'boundarylayer'); - var labelLayer = Lib.ensureSingle(axisLayer, 'g', 'labellayer'); - - axisLayer.style('opacity', trace.opacity); - - drawGridLines(xa, ya, majorLayer, aax, 'a', aax._gridlines, true); - drawGridLines(xa, ya, majorLayer, bax, 'b', bax._gridlines, true); - drawGridLines(xa, ya, minorLayer, aax, 'a', aax._minorgridlines, true); - drawGridLines(xa, ya, minorLayer, bax, 'b', bax._minorgridlines, true); - - // NB: These are not ommitted if the lines are not active. The joins must be executed - // in order for them to get cleaned up without a full redraw - drawGridLines(xa, ya, boundaryLayer, aax, 'a-boundary', aax._boundarylines); - drawGridLines(xa, ya, boundaryLayer, bax, 'b-boundary', bax._boundarylines); - - var labelOrientationA = drawAxisLabels(gd, xa, ya, trace, cd0, labelLayer, aax._labels, 'a-label'); - var labelOrientationB = drawAxisLabels(gd, xa, ya, trace, cd0, labelLayer, bax._labels, 'b-label'); - - drawAxisTitles(gd, labelLayer, trace, cd0, xa, ya, labelOrientationA, labelOrientationB); - - drawClipPath(trace, cd0, clipLayer, xa, ya); - }); -}; - -function drawClipPath(trace, t, layer, xaxis, yaxis) { - var seg, xp, yp, i; - - var clip = layer.select('#' + trace._clipPathId); - - if(!clip.size()) { - clip = layer.append('clipPath') - .classed('carpetclip', true); - } - - var path = Lib.ensureSingle(clip, 'path', 'carpetboundary'); - var segments = t.clipsegments; - var segs = []; - - for(i = 0; i < segments.length; i++) { - seg = segments[i]; - xp = map1dArray([], seg.x, xaxis.c2p); - yp = map1dArray([], seg.y, yaxis.c2p); - segs.push(makepath(xp, yp, seg.bicubic)); - } - - // This could be optimized ever so slightly to avoid no-op L segments - // at the corners, but it's so negligible that I don't think it's worth - // the extra complexity - var clipPathData = 'M' + segs.join('L') + 'Z'; - clip.attr('id', trace._clipPathId); - path.attr('d', clipPathData); -} - -function drawGridLines(xaxis, yaxis, layer, axis, axisLetter, gridlines) { - var lineClass = 'const-' + axisLetter + '-lines'; - var gridJoin = layer.selectAll('.' + lineClass).data(gridlines); - - gridJoin.enter().append('path') - .classed(lineClass, true) - .style('vector-effect', 'non-scaling-stroke'); - - gridJoin.each(function(d) { - var gridline = d; - var x = gridline.x; - var y = gridline.y; - - var xp = map1dArray([], x, xaxis.c2p); - var yp = map1dArray([], y, yaxis.c2p); - - var path = 'M' + makepath(xp, yp, gridline.smoothing); - - var el = d3.select(this); - - el.attr('d', path) - .style('stroke-width', gridline.width) - .style('stroke', gridline.color) - .style('fill', 'none'); - }); - - gridJoin.exit().remove(); -} - -function drawAxisLabels(gd, xaxis, yaxis, trace, t, layer, labels, labelClass) { - var labelJoin = layer.selectAll('text.' + labelClass).data(labels); - - labelJoin.enter().append('text') - .classed(labelClass, true); - - var maxExtent = 0; - var labelOrientation = {}; - - labelJoin.each(function(label, i) { - // Most of the positioning is done in calc_labels. Only the parts that depend upon - // the screen space representation of the x and y axes are here: - var orientation; - if(label.axis.tickangle === 'auto') { - orientation = orientText(trace, xaxis, yaxis, label.xy, label.dxy); - } else { - var angle = (label.axis.tickangle + 180.0) * Math.PI / 180.0; - orientation = orientText(trace, xaxis, yaxis, label.xy, [Math.cos(angle), Math.sin(angle)]); - } - - if(!i) { - // TODO: offsetMultiplier? Not currently used anywhere... - labelOrientation = {angle: orientation.angle, flip: orientation.flip}; - } - var direction = (label.endAnchor ? -1 : 1) * orientation.flip; - - var labelEl = d3.select(this) - .attr({ - 'text-anchor': direction > 0 ? 'start' : 'end', - 'data-notex': 1 - }) - .call(Drawing.font, label.font) - .text(label.text) - .call(svgTextUtils.convertToTspans, gd); - - var bbox = Drawing.bBox(this); - - labelEl.attr('transform', - // Translate to the correct point: - 'translate(' + orientation.p[0] + ',' + orientation.p[1] + ') ' + - // Rotate to line up with grid line tangent: - 'rotate(' + orientation.angle + ')' + - // Adjust the baseline and indentation: - 'translate(' + label.axis.labelpadding * direction + ',' + bbox.height * 0.3 + ')' - ); - - maxExtent = Math.max(maxExtent, bbox.width + label.axis.labelpadding); - }); - - labelJoin.exit().remove(); - - labelOrientation.maxExtent = maxExtent; - return labelOrientation; -} - -function drawAxisTitles(gd, layer, trace, t, xa, ya, labelOrientationA, labelOrientationB) { - var a, b, xy, dxy; - - var aMin = Lib.aggNums(Math.min, null, trace.a); - var aMax = Lib.aggNums(Math.max, null, trace.a); - var bMin = Lib.aggNums(Math.min, null, trace.b); - var bMax = Lib.aggNums(Math.max, null, trace.b); - - a = 0.5 * (aMin + aMax); - b = bMin; - xy = trace.ab2xy(a, b, true); - dxy = trace.dxyda_rough(a, b); - if(labelOrientationA.angle === undefined) { - Lib.extendFlat(labelOrientationA, orientText(trace, xa, ya, xy, trace.dxydb_rough(a, b))); - } - drawAxisTitle(gd, layer, trace, t, xy, dxy, trace.aaxis, xa, ya, labelOrientationA, 'a-title'); - - a = aMin; - b = 0.5 * (bMin + bMax); - xy = trace.ab2xy(a, b, true); - dxy = trace.dxydb_rough(a, b); - if(labelOrientationB.angle === undefined) { - Lib.extendFlat(labelOrientationB, orientText(trace, xa, ya, xy, trace.dxyda_rough(a, b))); - } - drawAxisTitle(gd, layer, trace, t, xy, dxy, trace.baxis, xa, ya, labelOrientationB, 'b-title'); -} - -var lineSpacing = alignmentConstants.LINE_SPACING; -var midShift = ((1 - alignmentConstants.MID_SHIFT) / lineSpacing) + 1; - -function drawAxisTitle(gd, layer, trace, t, xy, dxy, axis, xa, ya, labelOrientation, labelClass) { - var data = []; - if(axis.title.text) data.push(axis.title.text); - var titleJoin = layer.selectAll('text.' + labelClass).data(data); - var offset = labelOrientation.maxExtent; - - titleJoin.enter().append('text') - .classed(labelClass, true); - - // There's only one, but we'll do it as a join so it's updated nicely: - titleJoin.each(function() { - var orientation = orientText(trace, xa, ya, xy, dxy); - - if(['start', 'both'].indexOf(axis.showticklabels) === -1) { - offset = 0; - } - - // In addition to the size of the labels, add on some extra padding: - var titleSize = axis.title.font.size; - offset += titleSize + axis.title.offset; - - var labelNorm = labelOrientation.angle + (labelOrientation.flip < 0 ? 180 : 0); - var angleDiff = (labelNorm - orientation.angle + 450) % 360; - var reverseTitle = angleDiff > 90 && angleDiff < 270; - - var el = d3.select(this); - - el.text(axis.title.text) - .call(svgTextUtils.convertToTspans, gd); - - if(reverseTitle) { - offset = (-svgTextUtils.lineCount(el) + midShift) * lineSpacing * titleSize - offset; - } - - el.attr('transform', - 'translate(' + orientation.p[0] + ',' + orientation.p[1] + ') ' + - 'rotate(' + orientation.angle + ') ' + - 'translate(0,' + offset + ')' - ) - .classed('user-select-none', true) - .attr('text-anchor', 'middle') - .call(Drawing.font, axis.title.font); - }); - - titleJoin.exit().remove(); -} - -},{"../../components/drawing":614,"../../constants/alignment":688,"../../lib":719,"../../lib/svg_text_utils":743,"./makepath":916,"./map_1d_array":917,"./orient_text":918,"d3":163}],920:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var constants = _dereq_('./constants'); -var search = _dereq_('../../lib/search').findBin; -var computeControlPoints = _dereq_('./compute_control_points'); -var createSplineEvaluator = _dereq_('./create_spline_evaluator'); -var createIDerivativeEvaluator = _dereq_('./create_i_derivative_evaluator'); -var createJDerivativeEvaluator = _dereq_('./create_j_derivative_evaluator'); - -/* - * Create conversion functions to go from one basis to another. In particular the letter - * abbreviations are: - * - * i: i/j coordinates along the grid. Integer values correspond to data points - * a: real-valued coordinates along the a/b axes - * c: cartesian x-y coordinates - * p: screen-space pixel coordinates - */ -module.exports = function setConvert(trace) { - var a = trace._a; - var b = trace._b; - var na = a.length; - var nb = b.length; - var aax = trace.aaxis; - var bax = trace.baxis; - - // Grab the limits once rather than recomputing the bounds for every point - // independently: - var amin = a[0]; - var amax = a[na - 1]; - var bmin = b[0]; - var bmax = b[nb - 1]; - var arange = a[a.length - 1] - a[0]; - var brange = b[b.length - 1] - b[0]; - - // Compute the tolerance so that points are visible slightly outside the - // defined carpet axis: - var atol = arange * constants.RELATIVE_CULL_TOLERANCE; - var btol = brange * constants.RELATIVE_CULL_TOLERANCE; - - // Expand the limits to include the relative tolerance: - amin -= atol; - amax += atol; - bmin -= btol; - bmax += btol; - - trace.isVisible = function(a, b) { - return a > amin && a < amax && b > bmin && b < bmax; - }; - - trace.isOccluded = function(a, b) { - return a < amin || a > amax || b < bmin || b > bmax; - }; - - trace.setScale = function() { - var x = trace._x; - var y = trace._y; - - // This is potentially a very expensive step! It does the bulk of the work of constructing - // an expanded basis of control points. Note in particular that it overwrites the existing - // basis without creating a new array since that would potentially thrash the garbage - // collector. - var result = computeControlPoints(trace._xctrl, trace._yctrl, x, y, aax.smoothing, bax.smoothing); - trace._xctrl = result[0]; - trace._yctrl = result[1]; - - // This step is the second step in the process, but it's somewhat simpler. It just unrolls - // some logic since it would be unnecessarily expensive to compute both interpolations - // nearly identically but separately and to include a bunch of linear vs. bicubic logic in - // every single call. - trace.evalxy = createSplineEvaluator([trace._xctrl, trace._yctrl], na, nb, aax.smoothing, bax.smoothing); - - trace.dxydi = createIDerivativeEvaluator([trace._xctrl, trace._yctrl], aax.smoothing, bax.smoothing); - trace.dxydj = createJDerivativeEvaluator([trace._xctrl, trace._yctrl], aax.smoothing, bax.smoothing); - }; - - /* - * Convert from i/j data grid coordinates to a/b values. Note in particular that this - * is *linear* interpolation, even if the data is interpolated bicubically. - */ - trace.i2a = function(i) { - var i0 = Math.max(0, Math.floor(i[0]), na - 2); - var ti = i[0] - i0; - return (1 - ti) * a[i0] + ti * a[i0 + 1]; - }; - - trace.j2b = function(j) { - var j0 = Math.max(0, Math.floor(j[1]), na - 2); - var tj = j[1] - j0; - return (1 - tj) * b[j0] + tj * b[j0 + 1]; - }; - - trace.ij2ab = function(ij) { - return [trace.i2a(ij[0]), trace.j2b(ij[1])]; - }; - - /* - * Convert from a/b coordinates to i/j grid-numbered coordinates. This requires searching - * through the a/b data arrays and assumes they are monotonic, which is presumed to have - * been enforced already. - */ - trace.a2i = function(aval) { - var i0 = Math.max(0, Math.min(search(aval, a), na - 2)); - var a0 = a[i0]; - var a1 = a[i0 + 1]; - return Math.max(0, Math.min(na - 1, i0 + (aval - a0) / (a1 - a0))); - }; - - trace.b2j = function(bval) { - var j0 = Math.max(0, Math.min(search(bval, b), nb - 2)); - var b0 = b[j0]; - var b1 = b[j0 + 1]; - return Math.max(0, Math.min(nb - 1, j0 + (bval - b0) / (b1 - b0))); - }; - - trace.ab2ij = function(ab) { - return [trace.a2i(ab[0]), trace.b2j(ab[1])]; - }; - - /* - * Convert from i/j coordinates to x/y caretesian coordinates. This means either bilinear - * or bicubic spline evaluation, but the hard part is already done at this point. - */ - trace.i2c = function(i, j) { - return trace.evalxy([], i, j); - }; - - trace.ab2xy = function(aval, bval, extrapolate) { - if(!extrapolate && (aval < a[0] || aval > a[na - 1] | bval < b[0] || bval > b[nb - 1])) { - return [false, false]; - } - var i = trace.a2i(aval); - var j = trace.b2j(bval); - - var pt = trace.evalxy([], i, j); - - if(extrapolate) { - // This section uses the boundary derivatives to extrapolate linearly outside - // the defined range. Consider a scatter line with one point inside the carpet - // axis and one point outside. If we don't extrapolate, we can't draw the line - // at all. - var iex = 0; - var jex = 0; - var der = []; - - var i0, ti, j0, tj; - if(aval < a[0]) { - i0 = 0; - ti = 0; - iex = (aval - a[0]) / (a[1] - a[0]); - } else if(aval > a[na - 1]) { - i0 = na - 2; - ti = 1; - iex = (aval - a[na - 1]) / (a[na - 1] - a[na - 2]); - } else { - i0 = Math.max(0, Math.min(na - 2, Math.floor(i))); - ti = i - i0; - } - - if(bval < b[0]) { - j0 = 0; - tj = 0; - jex = (bval - b[0]) / (b[1] - b[0]); - } else if(bval > b[nb - 1]) { - j0 = nb - 2; - tj = 1; - jex = (bval - b[nb - 1]) / (b[nb - 1] - b[nb - 2]); - } else { - j0 = Math.max(0, Math.min(nb - 2, Math.floor(j))); - tj = j - j0; - } - - if(iex) { - trace.dxydi(der, i0, j0, ti, tj); - pt[0] += der[0] * iex; - pt[1] += der[1] * iex; - } - - if(jex) { - trace.dxydj(der, i0, j0, ti, tj); - pt[0] += der[0] * jex; - pt[1] += der[1] * jex; - } - } - - return pt; - }; - - - trace.c2p = function(xy, xa, ya) { - return [xa.c2p(xy[0]), ya.c2p(xy[1])]; - }; - - trace.p2x = function(p, xa, ya) { - return [xa.p2c(p[0]), ya.p2c(p[1])]; - }; - - trace.dadi = function(i /* , u*/) { - // Right now only a piecewise linear a or b basis is permitted since smoother interpolation - // would cause monotonicity problems. As a retult, u is entirely disregarded in this - // computation, though we'll specify it as a parameter for the sake of completeness and - // future-proofing. It would be possible to use monotonic cubic interpolation, for example. - // - // See: https://en.wikipedia.org/wiki/Monotone_cubic_interpolation - - // u = u || 0; - - var i0 = Math.max(0, Math.min(a.length - 2, i)); - - // The step (demoninator) is implicitly 1 since that's the grid spacing. - return a[i0 + 1] - a[i0]; - }; - - trace.dbdj = function(j /* , v*/) { - // See above caveats for dadi which also apply here - var j0 = Math.max(0, Math.min(b.length - 2, j)); - - // The step (demoninator) is implicitly 1 since that's the grid spacing. - return b[j0 + 1] - b[j0]; - }; - - // Takes: grid cell coordinate (i, j) and fractional grid cell coordinates (u, v) - // Returns: (dx/da, dy/db) - // - // NB: separate grid cell + fractional grid cell coordinate format is due to the discontinuous - // derivative, as described better in create_i_derivative_evaluator.js - trace.dxyda = function(i0, j0, u, v) { - var dxydi = trace.dxydi(null, i0, j0, u, v); - var dadi = trace.dadi(i0, u); - - return [dxydi[0] / dadi, dxydi[1] / dadi]; - }; - - trace.dxydb = function(i0, j0, u, v) { - var dxydj = trace.dxydj(null, i0, j0, u, v); - var dbdj = trace.dbdj(j0, v); - - return [dxydj[0] / dbdj, dxydj[1] / dbdj]; - }; - - // Sometimes we don't care about precision and all we really want is decent rough - // directions (as is the case with labels). In that case, we can do a very rough finite - // difference and spare having to worry about precise grid coordinates: - trace.dxyda_rough = function(a, b, reldiff) { - var h = arange * (reldiff || 0.1); - var plus = trace.ab2xy(a + h, b, true); - var minus = trace.ab2xy(a - h, b, true); - - return [ - (plus[0] - minus[0]) * 0.5 / h, - (plus[1] - minus[1]) * 0.5 / h - ]; - }; - - trace.dxydb_rough = function(a, b, reldiff) { - var h = brange * (reldiff || 0.1); - var plus = trace.ab2xy(a, b + h, true); - var minus = trace.ab2xy(a, b - h, true); - - return [ - (plus[0] - minus[0]) * 0.5 / h, - (plus[1] - minus[1]) * 0.5 / h - ]; - }; - - trace.dpdx = function(xa) { - return xa._m; - }; - - trace.dpdy = function(ya) { - return ya._m; - }; -}; - -},{"../../lib/search":738,"./compute_control_points":908,"./constants":909,"./create_i_derivative_evaluator":910,"./create_j_derivative_evaluator":911,"./create_spline_evaluator":912}],921:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -/* - * Given a 2D array as well as a basis in either direction, this function fills in the - * 2D array using a combination of smoothing and extrapolation. This is rather important - * for carpet plots since it's used for layout so that we can't simply omit or blank out - * points. We need a reasonable guess so that the interpolation puts points somewhere - * even if we were to somehow represent that the data was missing later on. - * - * input: - * - data: 2D array of arrays - * - a: array such that a.length === data[0].length - * - b: array such that b.length === data.length - */ -module.exports = function smoothFill2dArray(data, a, b) { - var i, j, k; - var ip = []; - var jp = []; - // var neighborCnts = []; - - var ni = data[0].length; - var nj = data.length; - - function avgSurrounding(i, j) { - // As a low-quality start, we can simply average surrounding points (in a not - // non-uniform grid aware manner): - var sum = 0.0; - var val; - var cnt = 0; - if(i > 0 && (val = data[j][i - 1]) !== undefined) { - cnt++; - sum += val; - } - if(i < ni - 1 && (val = data[j][i + 1]) !== undefined) { - cnt++; - sum += val; - } - if(j > 0 && (val = data[j - 1][i]) !== undefined) { - cnt++; - sum += val; - } - if(j < nj - 1 && (val = data[j + 1][i]) !== undefined) { - cnt++; - sum += val; - } - return sum / Math.max(1, cnt); - } - - // This loop iterates over all cells. Any cells that are null will be noted and those - // are the only points we will loop over and update via laplace's equation. Points with - // any neighbors will receive the average. If there are no neighboring points, then they - // will be set to zero. Also as we go, track the maximum magnitude so that we can scale - // our tolerance accordingly. - var dmax = 0.0; - for(i = 0; i < ni; i++) { - for(j = 0; j < nj; j++) { - if(data[j][i] === undefined) { - ip.push(i); - jp.push(j); - - data[j][i] = avgSurrounding(i, j); - // neighborCnts.push(result.neighbors); - } - dmax = Math.max(dmax, Math.abs(data[j][i])); - } - } - - if(!ip.length) return data; - - // The tolerance doesn't need to be excessive. It's just for display positioning - var dxp, dxm, dap, dam, dbp, dbm, c, d, diff, reldiff, overrelaxation; - var tol = 1e-5; - var resid = 0; - var itermax = 100; - var iter = 0; - var n = ip.length; - do { - resid = 0; - // Normally we'd loop in two dimensions, but not all points are blank and need - // an update, so we instead loop only over the points that were tabulated above - for(k = 0; k < n; k++) { - i = ip[k]; - j = jp[k]; - // neighborCnt = neighborCnts[k]; - - // Track a counter for how many contributions there are. We'll use this counter - // to average at the end, which reduces to laplace's equation with neumann boundary - // conditions on the first derivative (second derivative is zero so that we get - // a nice linear extrapolation at the boundaries). - var boundaryCnt = 0; - var newVal = 0; - - var d0, d1, x0, x1, i0, j0; - if(i === 0) { - // If this lies along the i = 0 boundary, extrapolate from the two points - // to the right of this point. Note that the finite differences take into - // account non-uniform grid spacing: - i0 = Math.min(ni - 1, 2); - x0 = a[i0]; - x1 = a[1]; - d0 = data[j][i0]; - d1 = data[j][1]; - newVal += d1 + (d1 - d0) * (a[0] - x1) / (x1 - x0); - boundaryCnt++; - } else if(i === ni - 1) { - // If along the high i boundary, extrapolate from the two points to the - // left of this point - i0 = Math.max(0, ni - 3); - x0 = a[i0]; - x1 = a[ni - 2]; - d0 = data[j][i0]; - d1 = data[j][ni - 2]; - newVal += d1 + (d1 - d0) * (a[ni - 1] - x1) / (x1 - x0); - boundaryCnt++; - } - - if((i === 0 || i === ni - 1) && (j > 0 && j < nj - 1)) { - // If along the min(i) or max(i) boundaries, also smooth vertically as long - // as we're not in a corner. Note that the finite differences used here - // are also aware of nonuniform grid spacing: - dxp = b[j + 1] - b[j]; - dxm = b[j] - b[j - 1]; - newVal += (dxm * data[j + 1][i] + dxp * data[j - 1][i]) / (dxm + dxp); - boundaryCnt++; - } - - if(j === 0) { - // If along the j = 0 boundary, extrpolate this point from the two points - // above it - j0 = Math.min(nj - 1, 2); - x0 = b[j0]; - x1 = b[1]; - d0 = data[j0][i]; - d1 = data[1][i]; - newVal += d1 + (d1 - d0) * (b[0] - x1) / (x1 - x0); - boundaryCnt++; - } else if(j === nj - 1) { - // Same for the max j boundary from the cells below it: - j0 = Math.max(0, nj - 3); - x0 = b[j0]; - x1 = b[nj - 2]; - d0 = data[j0][i]; - d1 = data[nj - 2][i]; - newVal += d1 + (d1 - d0) * (b[nj - 1] - x1) / (x1 - x0); - boundaryCnt++; - } - - if((j === 0 || j === nj - 1) && (i > 0 && i < ni - 1)) { - // Now average points to the left/right as long as not in a corner: - dxp = a[i + 1] - a[i]; - dxm = a[i] - a[i - 1]; - newVal += (dxm * data[j][i + 1] + dxp * data[j][i - 1]) / (dxm + dxp); - boundaryCnt++; - } - - if(!boundaryCnt) { - // If none of the above conditions were triggered, then this is an interior - // point and we can just do a laplace equation update. As above, these differences - // are aware of nonuniform grid spacing: - dap = a[i + 1] - a[i]; - dam = a[i] - a[i - 1]; - dbp = b[j + 1] - b[j]; - dbm = b[j] - b[j - 1]; - - // These are just some useful constants for the iteration, which is perfectly - // straightforward but a little long to derive from f_xx + f_yy = 0. - c = dap * dam * (dap + dam); - d = dbp * dbm * (dbp + dbm); - - newVal = (c * (dbm * data[j + 1][i] + dbp * data[j - 1][i]) + - d * (dam * data[j][i + 1] + dap * data[j][i - 1])) / - (d * (dam + dap) + c * (dbm + dbp)); - } else { - // If we did have contributions from the boundary conditions, then average - // the result from the various contributions: - newVal /= boundaryCnt; - } - - // Jacobi updates are ridiculously slow to converge, so this approach uses a - // Gauss-seidel iteration which is dramatically faster. - diff = newVal - data[j][i]; - reldiff = diff / dmax; - resid += reldiff * reldiff; - - // Gauss-Seidel-ish iteration, omega chosen based on heuristics and some - // quick tests. - // - // NB: Don't overrelax the boundarie. Otherwise set an overrelaxation factor - // which is a little low but safely optimal-ish: - overrelaxation = boundaryCnt ? 0 : 0.85; - - // If there are four non-null neighbors, then we want a simple average without - // overrelaxation. If all the surrouding points are null, then we want the full - // overrelaxation - // - // Based on experiments, this actually seems to slow down convergence just a bit. - // I'll leave it here for reference in case this needs to be revisited, but - // it seems to work just fine without this. - // if (overrelaxation) overrelaxation *= (4 - neighborCnt) / 4; - - data[j][i] += diff * (1 + overrelaxation); - } - - resid = Math.sqrt(resid); - } while(iter++ < itermax && resid > tol); - - Lib.log('Smoother converged to', resid, 'after', iter, 'iterations'); - - return data; -}; - -},{"../../lib":719}],922:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isArray1D = _dereq_('../../lib').isArray1D; - -module.exports = function handleXYDefaults(traceIn, traceOut, coerce) { - var x = coerce('x'); - var hasX = x && x.length; - var y = coerce('y'); - var hasY = y && y.length; - if(!hasX && !hasY) return false; - - traceOut._cheater = !x; - - if((!hasX || isArray1D(x)) && (!hasY || isArray1D(y))) { - var len = hasX ? x.length : Infinity; - if(hasY) len = Math.min(len, y.length); - if(traceOut.a && traceOut.a.length) len = Math.min(len, traceOut.a.length); - if(traceOut.b && traceOut.b.length) len = Math.min(len, traceOut.b.length); - traceOut._length = len; - } else traceOut._length = null; - - return true; -}; - -},{"../../lib":719}],923:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var scatterGeoAttrs = _dereq_('../scattergeo/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var plotAttrs = _dereq_('../../plots/attributes'); -var defaultLine = _dereq_('../../components/color/attributes').defaultLine; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var scatterGeoMarkerLineAttrs = scatterGeoAttrs.marker.line; - -module.exports = extendFlat({ - locations: { - valType: 'data_array', - editType: 'calc', - - }, - locationmode: scatterGeoAttrs.locationmode, - z: { - valType: 'data_array', - editType: 'calc', - - }, - text: extendFlat({}, scatterGeoAttrs.text, { - - }), - hovertext: extendFlat({}, scatterGeoAttrs.hovertext, { - - }), - marker: { - line: { - color: extendFlat({}, scatterGeoMarkerLineAttrs.color, {dflt: defaultLine}), - width: extendFlat({}, scatterGeoMarkerLineAttrs.width, {dflt: 1}), - editType: 'calc' - }, - opacity: { - valType: 'number', - arrayOk: true, - min: 0, - max: 1, - dflt: 1, - - editType: 'style', - - }, - editType: 'calc' - }, - - selected: { - marker: { - opacity: scatterGeoAttrs.selected.marker.opacity, - editType: 'plot' - }, - editType: 'plot' - }, - unselected: { - marker: { - opacity: scatterGeoAttrs.unselected.marker.opacity, - editType: 'plot' - }, - editType: 'plot' - }, - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - editType: 'calc', - flags: ['location', 'z', 'text', 'name'] - }), - hovertemplate: hovertemplateAttrs(), -}, - - colorScaleAttrs('', { - cLetter: 'z', - editTypeOverride: 'calc' - }) -); - -},{"../../components/color/attributes":592,"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../scattergeo/attributes":1151}],924:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); -var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); -var calcSelection = _dereq_('../scatter/calc_selection'); - -function isNonBlankString(v) { - return v && typeof v === 'string'; -} - -module.exports = function calc(gd, trace) { - var len = trace._length; - var calcTrace = new Array(len); - - var isValidLoc; - - if(trace.geojson) { - isValidLoc = function(v) { return isNonBlankString(v) || isNumeric(v); }; - } else { - isValidLoc = isNonBlankString; - } - - for(var i = 0; i < len; i++) { - var calcPt = calcTrace[i] = {}; - var loc = trace.locations[i]; - var z = trace.z[i]; - - if(isValidLoc(loc) && isNumeric(z)) { - calcPt.loc = loc; - calcPt.z = z; - } else { - calcPt.loc = null; - calcPt.z = BADNUM; - } - - calcPt.index = i; - } - - arraysToCalcdata(calcTrace, trace); - colorscaleCalc(gd, trace, { - vals: trace.z, - containerStr: '', - cLetter: 'z' - }); - calcSelection(calcTrace, trace); - - return calcTrace; -}; - -},{"../../components/colorscale/calc":601,"../../constants/numerical":695,"../scatter/arrays_to_calcdata":1111,"../scatter/calc_selection":1114,"fast-isnumeric":225}],925:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var locations = coerce('locations'); - var z = coerce('z'); - - if(!(locations && locations.length && Lib.isArrayOrTypedArray(z) && z.length)) { - traceOut.visible = false; - return; - } - - traceOut._length = Math.min(locations.length, z.length); - - coerce('locationmode'); - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - var mlw = coerce('marker.line.width'); - if(mlw) coerce('marker.line.color'); - coerce('marker.opacity'); - - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -},{"../../components/colorscale/defaults":603,"../../lib":719,"./attributes":923}],926:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function eventData(out, pt, trace, cd, pointNumber) { - out.location = pt.location; - out.z = pt.z; - - var cdi = cd[pointNumber]; - if(cdi.fIn) { - out.properties = cdi.fIn.properties; - } - - return out; -}; - -},{}],927:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var attributes = _dereq_('./attributes'); -var fillText = _dereq_('../../lib').fillText; - -module.exports = function hoverPoints(pointData, xval, yval) { - var cd = pointData.cd; - var trace = cd[0].trace; - var geo = pointData.subplot; - - var pt, i, j, isInside; - - for(i = 0; i < cd.length; i++) { - pt = cd[i]; - isInside = false; - - if(pt._polygons) { - for(j = 0; j < pt._polygons.length; j++) { - if(pt._polygons[j].contains([xval, yval])) { - isInside = !isInside; - } - // for polygons that cross antimeridian as xval is in [-180, 180] - if(pt._polygons[j].contains([xval + 360, yval])) { - isInside = !isInside; - } - } - - if(isInside) break; - } - } - - if(!isInside || !pt) return; - - pointData.x0 = pointData.x1 = pointData.xa.c2p(pt.ct); - pointData.y0 = pointData.y1 = pointData.ya.c2p(pt.ct); - - pointData.index = pt.index; - pointData.location = pt.loc; - pointData.z = pt.z; - pointData.zLabel = Axes.tickText(geo.mockAxis, geo.mockAxis.c2l(pt.z), 'hover').text; - pointData.hovertemplate = pt.hovertemplate; - - makeHoverInfo(pointData, trace, pt, geo.mockAxis); - - return [pointData]; -}; - -function makeHoverInfo(pointData, trace, pt) { - if(trace.hovertemplate) return; - - var hoverinfo = pt.hi || trace.hoverinfo; - - var parts = (hoverinfo === 'all') ? - attributes.hoverinfo.flags : - hoverinfo.split('+'); - - var hasName = (parts.indexOf('name') !== -1); - var hasLocation = (parts.indexOf('location') !== -1); - var hasZ = (parts.indexOf('z') !== -1); - var hasText = (parts.indexOf('text') !== -1); - var hasIdAsNameLabel = !hasName && hasLocation; - - var text = []; - - if(hasIdAsNameLabel) { - pointData.nameOverride = pt.loc; - } else { - if(hasName) pointData.nameOverride = trace.name; - if(hasLocation) text.push(pt.loc); - } - - if(hasZ) { - text.push(pointData.zLabel); - } - if(hasText) { - fillText(pt, trace, text); - } - - pointData.extraText = text.join('
'); -} - -},{"../../lib":719,"../../plots/cartesian/axes":767,"./attributes":923}],928:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../heatmap/colorbar'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot').plot, - style: _dereq_('./style').style, - styleOnSelect: _dereq_('./style').styleOnSelect, - hoverPoints: _dereq_('./hover'), - eventData: _dereq_('./event_data'), - selectPoints: _dereq_('./select'), - - moduleType: 'trace', - name: 'choropleth', - basePlotModule: _dereq_('../../plots/geo'), - categories: ['geo', 'noOpacity'], - meta: { - - } -}; - -},{"../../plots/geo":797,"../heatmap/colorbar":1004,"./attributes":923,"./calc":924,"./defaults":925,"./event_data":926,"./hover":927,"./plot":929,"./select":930,"./style":931}],929:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Lib = _dereq_('../../lib'); -var polygon = _dereq_('../../lib/polygon'); - -var getTopojsonFeatures = _dereq_('../../lib/topojson_utils').getTopojsonFeatures; -var locationToFeature = _dereq_('../../lib/geo_location_utils').locationToFeature; -var style = _dereq_('./style').style; - -function plot(gd, geo, calcData) { - for(var i = 0; i < calcData.length; i++) { - calcGeoJSON(calcData[i], geo.topojson); - } - - var choroplethLayer = geo.layers.backplot.select('.choroplethlayer'); - Lib.makeTraceGroups(choroplethLayer, calcData, 'trace choropleth').each(function(calcTrace) { - var sel = d3.select(this); - - var paths = sel.selectAll('path.choroplethlocation') - .data(Lib.identity); - - paths.enter().append('path') - .classed('choroplethlocation', true); - - paths.exit().remove(); - - // call style here within topojson request callback - style(gd, calcTrace); - }); -} - -function calcGeoJSON(calcTrace, topojson) { - var trace = calcTrace[0].trace; - var len = calcTrace.length; - var features = getTopojsonFeatures(trace, topojson); - - for(var i = 0; i < len; i++) { - var calcPt = calcTrace[i]; - var feature = locationToFeature(trace.locationmode, calcPt.loc, features); - - if(!feature) { - calcPt.geojson = null; - continue; - } - - calcPt.geojson = feature; - calcPt.ct = feature.properties.ct; - calcPt._polygons = feature2polygons(feature); - } -} - -function feature2polygons(feature) { - var geometry = feature.geometry; - var coords = geometry.coordinates; - var loc = feature.id; - - var polygons = []; - var appendPolygon, j, k, m; - - function doesCrossAntiMerdian(pts) { - for(var l = 0; l < pts.length - 1; l++) { - if(pts[l][0] > 0 && pts[l + 1][0] < 0) return l; - } - return null; - } - - if(loc === 'RUS' || loc === 'FJI') { - // Russia and Fiji have landmasses that cross the antimeridian, - // we need to add +360 to their longitude coordinates, so that - // polygon 'contains' doesn't get confused when crossing the antimeridian. - // - // Note that other countries have polygons on either side of the antimeridian - // (e.g. some Aleutian island for the USA), but those don't confuse - // the 'contains' method; these are skipped here. - appendPolygon = function(_pts) { - var pts; - - if(doesCrossAntiMerdian(_pts) === null) { - pts = _pts; - } else { - pts = new Array(_pts.length); - for(m = 0; m < _pts.length; m++) { - // do nut mutate calcdata[i][j].geojson !! - pts[m] = [ - _pts[m][0] < 0 ? _pts[m][0] + 360 : _pts[m][0], - _pts[m][1] - ]; - } - } - - polygons.push(polygon.tester(pts)); - }; - } else if(loc === 'ATA') { - // Antarctica has a landmass that wraps around every longitudes which - // confuses the 'contains' methods. - appendPolygon = function(pts) { - var crossAntiMeridianIndex = doesCrossAntiMerdian(pts); - - // polygon that do not cross anti-meridian need no special handling - if(crossAntiMeridianIndex === null) { - return polygons.push(polygon.tester(pts)); - } - - // stitch polygon by adding pt over South Pole, - // so that it covers the projected region covers all latitudes - // - // Note that the algorithm below only works for polygons that - // start and end on longitude -180 (like the ones built by - // https://github.com/etpinard/sane-topojson). - var stitch = new Array(pts.length + 1); - var si = 0; - - for(m = 0; m < pts.length; m++) { - if(m > crossAntiMeridianIndex) { - stitch[si++] = [pts[m][0] + 360, pts[m][1]]; - } else if(m === crossAntiMeridianIndex) { - stitch[si++] = pts[m]; - stitch[si++] = [pts[m][0], -90]; - } else { - stitch[si++] = pts[m]; - } - } - - // polygon.tester by default appends pt[0] to the points list, - // we must remove it here, to avoid a jump in longitude from 180 to -180, - // that would confuse the 'contains' method - var tester = polygon.tester(stitch); - tester.pts.pop(); - polygons.push(tester); - }; - } else { - // otherwise using same array ref is fine - appendPolygon = function(pts) { - polygons.push(polygon.tester(pts)); - }; - } - - switch(geometry.type) { - case 'MultiPolygon': - for(j = 0; j < coords.length; j++) { - for(k = 0; k < coords[j].length; k++) { - appendPolygon(coords[j][k]); - } - } - break; - case 'Polygon': - for(j = 0; j < coords.length; j++) { - appendPolygon(coords[j]); - } - break; - } - - return polygons; -} - -module.exports = { - plot: plot, - feature2polygons: feature2polygons -}; - -},{"../../lib":719,"../../lib/geo_location_utils":713,"../../lib/polygon":731,"../../lib/topojson_utils":746,"./style":931,"d3":163}],930:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function selectPoints(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var xa = searchInfo.xaxis; - var ya = searchInfo.yaxis; - var selection = []; - - var i, di, ct, x, y; - - if(selectionTester === false) { - for(i = 0; i < cd.length; i++) { - cd[i].selected = 0; - } - } else { - for(i = 0; i < cd.length; i++) { - di = cd[i]; - ct = di.ct; - - if(!ct) continue; - - x = xa.c2p(ct); - y = ya.c2p(ct); - - if(selectionTester.contains([x, y], null, i, searchInfo)) { - selection.push({ - pointNumber: i, - lon: ct[0], - lat: ct[1] - }); - di.selected = 1; - } else { - di.selected = 0; - } - } - } - - return selection; -}; - -},{}],931:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var Colorscale = _dereq_('../../components/colorscale'); - -function style(gd, calcTrace) { - if(calcTrace) styleTrace(gd, calcTrace); -} - -function styleTrace(gd, calcTrace) { - var trace = calcTrace[0].trace; - var s = calcTrace[0].node3; - var locs = s.selectAll('.choroplethlocation'); - var marker = trace.marker || {}; - var markerLine = marker.line || {}; - - var sclFunc = Colorscale.makeColorScaleFuncFromTrace(trace); - - locs.each(function(d) { - d3.select(this) - .attr('fill', sclFunc(d.z)) - .call(Color.stroke, d.mlc || markerLine.color) - .call(Drawing.dashLine, '', d.mlw || markerLine.width || 0) - .style('opacity', marker.opacity); - }); - - Drawing.selectedPointStyle(locs, trace, gd); -} - -function styleOnSelect(gd, calcTrace) { - var s = calcTrace[0].node3; - var trace = calcTrace[0].trace; - - if(trace.selectedpoints) { - Drawing.selectedPointStyle(s.selectAll('.choroplethlocation'), trace, gd); - } else { - styleTrace(gd, calcTrace); - } -} - -module.exports = { - style: style, - styleOnSelect: styleOnSelect -}; - -},{"../../components/color":593,"../../components/colorscale":605,"../../components/drawing":614,"d3":163}],932:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var choroplethAttrs = _dereq_('../choropleth/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = extendFlat({ - locations: { - valType: 'data_array', - editType: 'calc', - - }, - - // TODO - // Maybe start with only one value (that we could name e.g. 'geojson-id'), - // but eventually: - // - we could also support for our own dist/topojson/* - // - some people might want `geojson-properties-name` to map data arrays to - // GeoJSON features - // locationmode: choroplethAttrs.locationmode, - - z: { - valType: 'data_array', - editType: 'calc', - - }, - - // TODO maybe we could also set a "key" to dig out values out of the - // GeoJSON feature `properties` fields? - - geojson: { - valType: 'any', - - editType: 'calc', - - }, - - // TODO agree on name / behaviour - // - // 'below' is used currently for layout.mapbox.layers, - // even though it's not very plotly-esque. - // - // Note also, that the mapbox-gl style don't all have the same layers, - // see https://codepen.io/etpinard/pen/ydVMwM for full list - below: { - valType: 'string', - - editType: 'plot', - - }, - - text: choroplethAttrs.text, - hovertext: choroplethAttrs.hovertext, - - marker: { - line: { - color: extendFlat({}, choroplethAttrs.marker.line.color, {editType: 'plot'}), - width: extendFlat({}, choroplethAttrs.marker.line.width, {editType: 'plot'}), - editType: 'calc' - }, - // TODO maybe having a dflt less than 1, together with `below:''` would be better? - opacity: extendFlat({}, choroplethAttrs.marker.opacity, {editType: 'plot'}), - editType: 'calc' - }, - - selected: { - marker: { - opacity: extendFlat({}, choroplethAttrs.selected.marker.opacity, {editType: 'plot'}), - editType: 'plot' - }, - editType: 'plot' - }, - unselected: { - marker: { - opacity: extendFlat({}, choroplethAttrs.unselected.marker.opacity, {editType: 'plot'}), - editType: 'plot' - }, - editType: 'plot' - }, - - hoverinfo: choroplethAttrs.hoverinfo, - hovertemplate: hovertemplateAttrs({}, {keys: ['properties']}) -}, - - colorScaleAttrs('', { - cLetter: 'z', - editTypeOverride: 'calc' - }) -); - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../choropleth/attributes":923}],933:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var turfArea = _dereq_('@turf/area'); -var turfCentroid = _dereq_('@turf/centroid'); - -var Lib = _dereq_('../../lib'); -var Colorscale = _dereq_('../../components/colorscale'); -var Drawing = _dereq_('../../components/drawing'); - -var makeBlank = _dereq_('../../lib/geojson_utils').makeBlank; -var feature2polygons = _dereq_('../choropleth/plot').feature2polygons; - -/* N.B. - * - * We fetch the GeoJSON files "ourselves" (during - * mapbox.prototype.fetchMapData) where they are stored in a global object - * named `PlotlyGeoAssets` (same as for topojson files in `geo` subplots). - * - * Mapbox does allow using URLs as geojson sources, but does NOT allow filtering - * features by feature `id` that are not numbers (more info in: - * https://github.com/mapbox/mapbox-gl-js/issues/8088). - */ - -function convert(calcTrace) { - var trace = calcTrace[0].trace; - var isVisible = trace.visible === true && trace._length !== 0; - - var fill = { - layout: {visibility: 'none'}, - paint: {} - }; - - var line = { - layout: {visibility: 'none'}, - paint: {} - }; - - var opts = trace._opts = { - fill: fill, - line: line, - geojson: makeBlank() - }; - - if(!isVisible) return opts; - - var geojsonIn = typeof trace.geojson === 'string' ? - (window.PlotlyGeoAssets || {})[trace.geojson] : - trace.geojson; - - // This should not happen, but just in case something goes - // really wrong when fetching the GeoJSON - if(!Lib.isPlainObject(geojsonIn)) { - Lib.error('Oops ... something when wrong when fetching ' + trace.geojson); - return opts; - } - - var lookup = {}; - var featuresOut = []; - var i; - - for(i = 0; i < calcTrace.length; i++) { - var cdi = calcTrace[i]; - if(cdi.loc) lookup[cdi.loc] = cdi; - } - - var sclFunc = Colorscale.makeColorScaleFuncFromTrace(trace); - var marker = trace.marker; - var markerLine = marker.line || {}; - - var opacityFn; - if(Lib.isArrayOrTypedArray(marker.opacity)) { - opacityFn = function(d) { - var mo = d.mo; - return isNumeric(mo) ? +Lib.constrain(mo, 0, 1) : 0; - }; - } - - var lineColorFn; - if(Lib.isArrayOrTypedArray(markerLine.color)) { - lineColorFn = function(d) { return d.mlc; }; - } - - var lineWidthFn; - if(Lib.isArrayOrTypedArray(markerLine.width)) { - lineWidthFn = function(d) { return d.mlw; }; - } - - function appendFeature(fIn) { - var cdi = lookup[fIn.id]; - - if(cdi) { - var geometry = fIn.geometry; - - if(geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') { - var props = {fc: sclFunc(cdi.z)}; - - if(opacityFn) props.mo = opacityFn(cdi); - if(lineColorFn) props.mlc = lineColorFn(cdi); - if(lineWidthFn) props.mlw = lineWidthFn(cdi); - - var fOut = { - type: 'Feature', - geometry: geometry, - properties: props - }; - - cdi._polygons = feature2polygons(fOut); - cdi.ct = findCentroid(fOut); - cdi.fIn = fIn; - cdi.fOut = fOut; - featuresOut.push(fOut); - } else { - Lib.log([ - 'Location with id', cdi.loc, 'does not have a valid GeoJSON geometry,', - 'choroplethmapbox traces only support *Polygon* and *MultiPolygon* geometries.' - ].join(' ')); - } - } - - // remove key from lookup, so that we can track (if any) - // the locations that did not have a corresponding GeoJSON feature - delete lookup[fIn.id]; - } - - switch(geojsonIn.type) { - case 'FeatureCollection': - var featuresIn = geojsonIn.features; - for(i = 0; i < featuresIn.length; i++) { - appendFeature(featuresIn[i]); - } - break; - case 'Feature': - appendFeature(geojsonIn); - break; - default: - Lib.warn([ - 'Invalid GeoJSON type', (geojsonIn.type || 'none') + ',', - 'choroplethmapbox traces only support *FeatureCollection* and *Feature* types.' - ].join(' ')); - return opts; - } - - for(var loc in lookup) { - Lib.log('Location with id ' + loc + ' does not have a matching feature'); - } - - var opacitySetting = opacityFn ? - {type: 'identity', property: 'mo'} : - marker.opacity; - - Lib.extendFlat(fill.paint, { - 'fill-color': {type: 'identity', property: 'fc'}, - 'fill-opacity': opacitySetting - }); - - Lib.extendFlat(line.paint, { - 'line-color': lineColorFn ? - {type: 'identity', property: 'mlc'} : - markerLine.color, - 'line-width': lineWidthFn ? - {type: 'identity', property: 'mlw'} : - markerLine.width, - 'line-opacity': opacitySetting - }); - - fill.layout.visibility = 'visible'; - line.layout.visibility = 'visible'; - - opts.geojson = {type: 'FeatureCollection', features: featuresOut}; - - convertOnSelect(calcTrace); - - return opts; -} - -function convertOnSelect(calcTrace) { - var trace = calcTrace[0].trace; - var opts = trace._opts; - var opacitySetting; - - if(trace.selectedpoints) { - var fns = Drawing.makeSelectedPointStyleFns(trace); - - for(var i = 0; i < calcTrace.length; i++) { - var cdi = calcTrace[i]; - if(cdi.fOut) { - cdi.fOut.properties.mo2 = fns.selectedOpacityFn(cdi); - } - } - - opacitySetting = {type: 'identity', property: 'mo2'}; - } else { - opacitySetting = Lib.isArrayOrTypedArray(trace.marker.opacity) ? - {type: 'identity', property: 'mo'} : - trace.marker.opacity; - } - - Lib.extendFlat(opts.fill.paint, {'fill-opacity': opacitySetting}); - Lib.extendFlat(opts.line.paint, {'line-opacity': opacitySetting}); - - return opts; -} - -// TODO this find the centroid of the polygon of maxArea -// (just like we currently do for geo choropleth polygons), -// maybe instead it would make more sense to compute the centroid -// of each polygon and consider those on hover/select -function findCentroid(feature) { - var geometry = feature.geometry; - var poly; - - if(geometry.type === 'MultiPolygon') { - var coords = geometry.coordinates; - var maxArea = 0; - - for(var i = 0; i < coords.length; i++) { - var polyi = {type: 'Polygon', coordinates: coords[i]}; - var area = turfArea.default(polyi); - if(area > maxArea) { - maxArea = area; - poly = polyi; - } - } - } else { - poly = geometry; - } - - return turfCentroid.default(poly).geometry.coordinates; -} - -module.exports = { - convert: convert, - convertOnSelect: convertOnSelect -}; - -},{"../../components/colorscale":605,"../../components/drawing":614,"../../lib":719,"../../lib/geojson_utils":714,"../choropleth/plot":929,"@turf/area":55,"@turf/centroid":56,"fast-isnumeric":225}],934:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var locations = coerce('locations'); - var z = coerce('z'); - var geojson = coerce('geojson'); - - if(!Lib.isArrayOrTypedArray(locations) || !locations.length || - !Lib.isArrayOrTypedArray(z) || !z.length || - !((typeof geojson === 'string' && geojson !== '') || Lib.isPlainObject(geojson)) - ) { - traceOut.visible = false; - return; - } - - traceOut._length = Math.min(locations.length, z.length); - - coerce('below'); - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - var mlw = coerce('marker.line.width'); - if(mlw) coerce('marker.line.color'); - coerce('marker.opacity'); - - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -},{"../../components/colorscale/defaults":603,"../../lib":719,"./attributes":932}],935:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../heatmap/colorbar'), - calc: _dereq_('../choropleth/calc'), - plot: _dereq_('./plot'), - hoverPoints: _dereq_('../choropleth/hover'), - eventData: _dereq_('../choropleth/event_data'), - selectPoints: _dereq_('../choropleth/select'), - - styleOnSelect: function(_, cd) { - if(cd) { - var trace = cd[0].trace; - trace._glTrace.updateOnSelect(cd); - } - }, - - getBelow: function(trace, subplot) { - var mapLayers = subplot.getMapLayers(); - - // find layer just above top-most "water" layer - // that is not a plotly layer - for(var i = mapLayers.length - 2; i >= 0; i--) { - var layerId = mapLayers[i].id; - - if(typeof layerId === 'string' && - layerId.indexOf('water') === 0 - ) { - for(var j = i + 1; j < mapLayers.length; j++) { - layerId = mapLayers[j].id; - - if(typeof layerId === 'string' && - layerId.indexOf('plotly-') === -1 - ) { - return layerId; - } - } - } - } - }, - - moduleType: 'trace', - name: 'choroplethmapbox', - basePlotModule: _dereq_('../../plots/mapbox'), - categories: ['mapbox', 'gl', 'noOpacity'], - meta: { - hr_name: 'choropleth_mapbox', - - } -}; - -},{"../../plots/mapbox":822,"../choropleth/calc":924,"../choropleth/event_data":926,"../choropleth/hover":927,"../choropleth/select":930,"../heatmap/colorbar":1004,"./attributes":932,"./defaults":934,"./plot":936}],936:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var convert = _dereq_('./convert').convert; -var convertOnSelect = _dereq_('./convert').convertOnSelect; -var LAYER_PREFIX = _dereq_('../../plots/mapbox/constants').traceLayerPrefix; - -function ChoroplethMapbox(subplot, uid) { - this.subplot = subplot; - this.uid = uid; - - // N.B. fill and line layers share same source - this.sourceId = 'source-' + uid; - - this.layerList = [ - ['fill', LAYER_PREFIX + uid + '-fill'], - ['line', LAYER_PREFIX + uid + '-line'] - ]; - - // previous 'below' value, - // need this to update it properly - this.below = null; -} - -var proto = ChoroplethMapbox.prototype; - -proto.update = function(calcTrace) { - this._update(convert(calcTrace)); -}; - -proto.updateOnSelect = function(calcTrace) { - this._update(convertOnSelect(calcTrace)); -}; - -proto._update = function(optsAll) { - var subplot = this.subplot; - var layerList = this.layerList; - var below = subplot.belowLookup['trace-' + this.uid]; - - subplot.map - .getSource(this.sourceId) - .setData(optsAll.geojson); - - if(below !== this.below) { - this._removeLayers(); - this._addLayers(optsAll, below); - this.below = below; - } - - for(var i = 0; i < layerList.length; i++) { - var item = layerList[i]; - var k = item[0]; - var id = item[1]; - var opts = optsAll[k]; - - subplot.setOptions(id, 'setLayoutProperty', opts.layout); - - if(opts.layout.visibility === 'visible') { - subplot.setOptions(id, 'setPaintProperty', opts.paint); - } - } -}; - -proto._addLayers = function(optsAll, below) { - var subplot = this.subplot; - var layerList = this.layerList; - var sourceId = this.sourceId; - - for(var i = 0; i < layerList.length; i++) { - var item = layerList[i]; - var k = item[0]; - var opts = optsAll[k]; - - subplot.addLayer({ - type: k, - id: item[1], - source: sourceId, - layout: opts.layout, - paint: opts.paint - }, below); - } -}; - -proto._removeLayers = function() { - var map = this.subplot.map; - var layerList = this.layerList; - - for(var i = layerList.length - 1; i >= 0; i--) { - map.removeLayer(layerList[i][1]); - } -}; - -proto.dispose = function() { - var map = this.subplot.map; - this._removeLayers(); - map.removeSource(this.sourceId); -}; - -module.exports = function createChoroplethMapbox(subplot, calcTrace) { - var trace = calcTrace[0].trace; - var choroplethMapbox = new ChoroplethMapbox(subplot, trace.uid); - var sourceId = choroplethMapbox.sourceId; - var optsAll = convert(calcTrace); - var below = choroplethMapbox.below = subplot.belowLookup['trace-' + trace.uid]; - - subplot.map.addSource(sourceId, { - type: 'geojson', - data: optsAll.geojson - }); - - choroplethMapbox._addLayers(optsAll, below); - - // link ref for quick update during selections - calcTrace[0].trace._glTrace = choroplethMapbox; - - return choroplethMapbox; -}; - -},{"../../plots/mapbox/constants":820,"./convert":933}],937:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var mesh3dAttrs = _dereq_('../mesh3d/attributes'); -var baseAttrs = _dereq_('../../plots/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var attrs = { - x: { - valType: 'data_array', - - editType: 'calc+clearAxisTypes', - - }, - y: { - valType: 'data_array', - - editType: 'calc+clearAxisTypes', - - }, - z: { - valType: 'data_array', - - editType: 'calc+clearAxisTypes', - - }, - - u: { - valType: 'data_array', - editType: 'calc', - - }, - v: { - valType: 'data_array', - editType: 'calc', - - }, - w: { - valType: 'data_array', - editType: 'calc', - - }, - - // TODO add way to specify cone positions independently of the vector field - // provided, similar to MATLAB's coneplot Cx/Cy/Cz meshgrids, - // see https://www.mathworks.com/help/matlab/ref/coneplot.html - // - // Alternatively, if our goal is only to 'fill in gaps' in the vector data, - // we could try to extend the heatmap 'connectgaps' algorithm to 3D. - // From AJ: this particular algorithm which amounts to a Poisson equation, - // both for interpolation and extrapolation - is the right one to use for - // cones too. It makes a field with zero divergence, which is a good - // baseline assumption for vector fields. - // - // cones: { - // // potential attributes to add: - // // - // // - meshmode: 'cartesian-product', 'pts', 'grid' - // // - // // under `meshmode: 'grid'` - // // - (x|y|z)grid.start - // // - (x|y|z)grid.end - // // - (x|y|z)grid.size - // - // x: { - // valType: 'data_array', - // editType: 'calc', - // - // }, - // y: { - // valType: 'data_array', - // editType: 'calc', - // - // }, - // z: { - // valType: 'data_array', - // editType: 'calc', - // - // }, - // - // editType: 'calc', - // - // }, - - sizemode: { - valType: 'enumerated', - values: ['scaled', 'absolute'], - - editType: 'calc', - dflt: 'scaled', - - }, - sizeref: { - valType: 'number', - - editType: 'calc', - min: 0, - - }, - - anchor: { - valType: 'enumerated', - - editType: 'calc', - values: ['tip', 'tail', 'cm', 'center'], - dflt: 'cm', - - }, - - text: { - valType: 'string', - - dflt: '', - arrayOk: true, - editType: 'calc', - - }, - hovertext: { - valType: 'string', - - dflt: '', - arrayOk: true, - editType: 'calc', - - }, - hovertemplate: hovertemplateAttrs({editType: 'calc'}, {keys: ['norm']}) -}; - -extendFlat(attrs, colorScaleAttrs('', { - colorAttr: 'u/v/w norm', - showScaleDflt: true, - editTypeOverride: 'calc' -})); - -var fromMesh3d = ['opacity', 'lightposition', 'lighting']; - -fromMesh3d.forEach(function(k) { - attrs[k] = mesh3dAttrs[k]; -}); - -attrs.hoverinfo = extendFlat({}, baseAttrs.hoverinfo, { - editType: 'calc', - flags: ['x', 'y', 'z', 'u', 'v', 'w', 'norm', 'text', 'name'], - dflt: 'x+y+z+norm+text+name' -}); - -attrs.transforms = undefined; - -module.exports = attrs; - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../mesh3d/attributes":1053}],938:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); - -module.exports = function calc(gd, trace) { - var u = trace.u; - var v = trace.v; - var w = trace.w; - var len = Math.min( - trace.x.length, trace.y.length, trace.z.length, - u.length, v.length, w.length - ); - var normMax = -Infinity; - var normMin = Infinity; - - for(var i = 0; i < len; i++) { - var uu = u[i]; - var vv = v[i]; - var ww = w[i]; - var norm = Math.sqrt(uu * uu + vv * vv + ww * ww); - - normMax = Math.max(normMax, norm); - normMin = Math.min(normMin, norm); - } - - trace._len = len; - trace._normMax = normMax; - - colorscaleCalc(gd, trace, { - vals: [normMin, normMax], - containerStr: '', - cLetter: 'c' - }); -}; - -},{"../../components/colorscale/calc":601}],939:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var conePlot = _dereq_('gl-cone3d'); -var createConeMesh = _dereq_('gl-cone3d').createConeMesh; - -var simpleMap = _dereq_('../../lib').simpleMap; -var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; -var extractOpts = _dereq_('../../components/colorscale').extractOpts; -var zip3 = _dereq_('../../plots/gl3d/zip3'); - -function Cone(scene, uid) { - this.scene = scene; - this.uid = uid; - this.mesh = null; - this.data = null; -} - -var proto = Cone.prototype; - -proto.handlePick = function(selection) { - if(selection.object === this.mesh) { - var selectIndex = selection.index = selection.data.index; - var xx = this.data.x[selectIndex]; - var yy = this.data.y[selectIndex]; - var zz = this.data.z[selectIndex]; - var uu = this.data.u[selectIndex]; - var vv = this.data.v[selectIndex]; - var ww = this.data.w[selectIndex]; - - selection.traceCoordinate = [ - xx, yy, zz, - uu, vv, ww, - Math.sqrt(uu * uu + vv * vv + ww * ww) - ]; - - var text = this.data.hovertext || this.data.text; - if(Array.isArray(text) && text[selectIndex] !== undefined) { - selection.textLabel = text[selectIndex]; - } else if(text) { - selection.textLabel = text; - } - - return true; - } -}; - -var axisName2scaleIndex = {xaxis: 0, yaxis: 1, zaxis: 2}; -var anchor2coneOffset = {tip: 1, tail: 0, cm: 0.25, center: 0.5}; -var anchor2coneSpan = {tip: 1, tail: 1, cm: 0.75, center: 0.5}; - -function convert(scene, trace) { - var sceneLayout = scene.fullSceneLayout; - var dataScale = scene.dataScale; - var coneOpts = {}; - - function toDataCoords(arr, axisName) { - var ax = sceneLayout[axisName]; - var scale = dataScale[axisName2scaleIndex[axisName]]; - return simpleMap(arr, function(v) { return ax.d2l(v) * scale; }); - } - - coneOpts.vectors = zip3( - toDataCoords(trace.u, 'xaxis'), - toDataCoords(trace.v, 'yaxis'), - toDataCoords(trace.w, 'zaxis'), - trace._len - ); - - coneOpts.positions = zip3( - toDataCoords(trace.x, 'xaxis'), - toDataCoords(trace.y, 'yaxis'), - toDataCoords(trace.z, 'zaxis'), - trace._len - ); - - var cOpts = extractOpts(trace); - coneOpts.colormap = parseColorScale(trace); - coneOpts.vertexIntensityBounds = [cOpts.min / trace._normMax, cOpts.max / trace._normMax]; - coneOpts.coneOffset = anchor2coneOffset[trace.anchor]; - - if(trace.sizemode === 'scaled') { - // unitless sizeref - coneOpts.coneSize = trace.sizeref || 0.5; - } else { - // sizeref here has unit of velocity - coneOpts.coneSize = trace.sizeref && trace._normMax ? - trace.sizeref / trace._normMax : - 0.5; - } - - var meshData = conePlot(coneOpts); - - // pass gl-mesh3d lighting attributes - var lp = trace.lightposition; - meshData.lightPosition = [lp.x, lp.y, lp.z]; - meshData.ambient = trace.lighting.ambient; - meshData.diffuse = trace.lighting.diffuse; - meshData.specular = trace.lighting.specular; - meshData.roughness = trace.lighting.roughness; - meshData.fresnel = trace.lighting.fresnel; - meshData.opacity = trace.opacity; - - // stash autorange pad value - trace._pad = anchor2coneSpan[trace.anchor] * meshData.vectorScale * meshData.coneScale * trace._normMax; - - return meshData; -} - -proto.update = function(data) { - this.data = data; - - var meshData = convert(this.scene, data); - this.mesh.update(meshData); -}; - -proto.dispose = function() { - this.scene.glplot.remove(this.mesh); - this.mesh.dispose(); -}; - -function createConeTrace(scene, data) { - var gl = scene.glplot.gl; - - var meshData = convert(scene, data); - var mesh = createConeMesh(gl, meshData); - - var cone = new Cone(scene, data.uid); - cone.mesh = mesh; - cone.data = data; - mesh._trace = cone; - - scene.glplot.add(mesh); - - return cone; -} - -module.exports = createConeTrace; - -},{"../../components/colorscale":605,"../../lib":719,"../../lib/gl_format_color":716,"../../plots/gl3d/zip3":818,"gl-cone3d":242}],940:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var u = coerce('u'); - var v = coerce('v'); - var w = coerce('w'); - - var x = coerce('x'); - var y = coerce('y'); - var z = coerce('z'); - - if( - !u || !u.length || !v || !v.length || !w || !w.length || - !x || !x.length || !y || !y.length || !z || !z.length - ) { - traceOut.visible = false; - return; - } - - coerce('sizeref'); - coerce('sizemode'); - - coerce('anchor'); - - coerce('lighting.ambient'); - coerce('lighting.diffuse'); - coerce('lighting.specular'); - coerce('lighting.roughness'); - coerce('lighting.fresnel'); - coerce('lightposition.x'); - coerce('lightposition.y'); - coerce('lightposition.z'); - - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - // disable 1D transforms (for now) - traceOut._length = null; -}; - -},{"../../components/colorscale/defaults":603,"../../lib":719,"./attributes":937}],941:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'cone', - basePlotModule: _dereq_('../../plots/gl3d'), - categories: ['gl3d'], - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: { - min: 'cmin', - max: 'cmax' - }, - calc: _dereq_('./calc'), - plot: _dereq_('./convert'), - eventData: function(out, pt) { - out.norm = pt.traceCoordinate[6]; - return out; - }, - - meta: { - - } -}; - -},{"../../plots/gl3d":807,"./attributes":937,"./calc":938,"./convert":939,"./defaults":940}],942:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var heatmapAttrs = _dereq_('../heatmap/attributes'); -var scatterAttrs = _dereq_('../scatter/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var dash = _dereq_('../../components/drawing/attributes').dash; -var fontAttrs = _dereq_('../../plots/font_attributes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var filterOps = _dereq_('../../constants/filter_ops'); -var COMPARISON_OPS2 = filterOps.COMPARISON_OPS2; -var INTERVAL_OPS = filterOps.INTERVAL_OPS; - -var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK; - -var scatterLineAttrs = scatterAttrs.line; - -module.exports = extendFlat({ - z: heatmapAttrs.z, - x: heatmapAttrs.x, - x0: heatmapAttrs.x0, - dx: heatmapAttrs.dx, - y: heatmapAttrs.y, - y0: heatmapAttrs.y0, - dy: heatmapAttrs.dy, - text: heatmapAttrs.text, - hovertext: heatmapAttrs.hovertext, - transpose: heatmapAttrs.transpose, - xtype: heatmapAttrs.xtype, - ytype: heatmapAttrs.ytype, - zhoverformat: heatmapAttrs.zhoverformat, - hovertemplate: heatmapAttrs.hovertemplate, - - connectgaps: heatmapAttrs.connectgaps, - - fillcolor: { - valType: 'color', - - editType: 'calc', - - }, - - autocontour: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - impliedEdits: { - 'contours.start': undefined, - 'contours.end': undefined, - 'contours.size': undefined - }, - - }, - ncontours: { - valType: 'integer', - dflt: 15, - min: 1, - - editType: 'calc', - - }, - - contours: { - type: { - valType: 'enumerated', - values: ['levels', 'constraint'], - dflt: 'levels', - - editType: 'calc', - - }, - start: { - valType: 'number', - dflt: null, - - editType: 'plot', - impliedEdits: {'^autocontour': false}, - - }, - end: { - valType: 'number', - dflt: null, - - editType: 'plot', - impliedEdits: {'^autocontour': false}, - - }, - size: { - valType: 'number', - dflt: null, - min: 0, - - editType: 'plot', - impliedEdits: {'^autocontour': false}, - - }, - coloring: { - valType: 'enumerated', - values: ['fill', 'heatmap', 'lines', 'none'], - dflt: 'fill', - - editType: 'calc', - - }, - showlines: { - valType: 'boolean', - dflt: true, - - editType: 'plot', - - }, - showlabels: { - valType: 'boolean', - dflt: false, - - editType: 'plot', - - }, - labelfont: fontAttrs({ - editType: 'plot', - colorEditType: 'style', - - }), - labelformat: { - valType: 'string', - dflt: '', - - editType: 'plot', - - }, - operation: { - valType: 'enumerated', - values: [].concat(COMPARISON_OPS2).concat(INTERVAL_OPS), - - dflt: '=', - editType: 'calc', - - }, - value: { - valType: 'any', - dflt: 0, - - editType: 'calc', - - }, - editType: 'calc', - impliedEdits: {'autocontour': false} - }, - - line: { - color: extendFlat({}, scatterLineAttrs.color, { - editType: 'style+colorbars', - - }), - width: extendFlat({}, scatterLineAttrs.width, { - editType: 'style+colorbars' - }), - dash: dash, - smoothing: extendFlat({}, scatterLineAttrs.smoothing, { - - }), - editType: 'plot' - } -}, - colorScaleAttrs('', { - cLetter: 'z', - autoColorDflt: false, - editTypeOverride: 'calc' - }) -); - -},{"../../components/colorscale/attributes":600,"../../components/drawing/attributes":613,"../../constants/docs":690,"../../constants/filter_ops":691,"../../lib/extend":710,"../../plots/font_attributes":793,"../heatmap/attributes":1001,"../scatter/attributes":1112}],943:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Colorscale = _dereq_('../../components/colorscale'); - -var heatmapCalc = _dereq_('../heatmap/calc'); -var setContours = _dereq_('./set_contours'); -var endPlus = _dereq_('./end_plus'); - -// most is the same as heatmap calc, then adjust it -// though a few things inside heatmap calc still look for -// contour maps, because the makeBoundArray calls are too entangled -module.exports = function calc(gd, trace) { - var cd = heatmapCalc(gd, trace); - - var zOut = cd[0].z; - setContours(trace, zOut); - - var contours = trace.contours; - var cOpts = Colorscale.extractOpts(trace); - var cVals; - - if(contours.coloring === 'heatmap' && cOpts.auto && trace.autocontour === false) { - var start = contours.start; - var end = endPlus(contours); - var cs = contours.size || 1; - var nc = Math.floor((end - start) / cs) + 1; - - if(!isFinite(cs)) { - cs = 1; - nc = 1; - } - - var min0 = start - cs / 2; - var max0 = min0 + nc * cs; - cVals = [min0, max0]; - } else { - cVals = zOut; - } - - Colorscale.calc(gd, trace, {vals: cVals, cLetter: 'z'}); - - return cd; -}; - -},{"../../components/colorscale":605,"../heatmap/calc":1002,"./end_plus":953,"./set_contours":961}],944:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function(pathinfo, operation, perimeter, trace) { - // Abandon all hope, ye who enter here. - var i, v1, v2; - var pi0 = pathinfo[0]; - var na = pi0.x.length; - var nb = pi0.y.length; - var z = pi0.z; - var contours = trace.contours; - - var boundaryMax = -Infinity; - var boundaryMin = Infinity; - - for(i = 0; i < nb; i++) { - boundaryMin = Math.min(boundaryMin, z[i][0]); - boundaryMin = Math.min(boundaryMin, z[i][na - 1]); - boundaryMax = Math.max(boundaryMax, z[i][0]); - boundaryMax = Math.max(boundaryMax, z[i][na - 1]); - } - - for(i = 1; i < na - 1; i++) { - boundaryMin = Math.min(boundaryMin, z[0][i]); - boundaryMin = Math.min(boundaryMin, z[nb - 1][i]); - boundaryMax = Math.max(boundaryMax, z[0][i]); - boundaryMax = Math.max(boundaryMax, z[nb - 1][i]); - } - - pi0.prefixBoundary = false; - - switch(operation) { - case '>': - if(contours.value > boundaryMax) { - pi0.prefixBoundary = true; - } - break; - case '<': - if(contours.value < boundaryMin) { - pi0.prefixBoundary = true; - } - break; - case '[]': - v1 = Math.min.apply(null, contours.value); - v2 = Math.max.apply(null, contours.value); - if(v2 < boundaryMin || v1 > boundaryMax) { - pi0.prefixBoundary = true; - } - break; - case '][': - v1 = Math.min.apply(null, contours.value); - v2 = Math.max.apply(null, contours.value); - if(v1 < boundaryMin && v2 > boundaryMax) { - pi0.prefixBoundary = true; - } - break; - } -}; - -},{}],945:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var extractOpts = _dereq_('../../components/colorscale').extractOpts; -var makeColorMap = _dereq_('./make_color_map'); -var endPlus = _dereq_('./end_plus'); - -function calc(gd, trace, opts) { - var contours = trace.contours; - var line = trace.line; - var cs = contours.size || 1; - var coloring = contours.coloring; - var colorMap = makeColorMap(trace, {isColorbar: true}); - - if(coloring === 'heatmap') { - var cOpts = extractOpts(trace); - opts._fillgradient = trace.colorscale; - opts._zrange = [cOpts.min, cOpts.max]; - } else if(coloring === 'fill') { - opts._fillcolor = colorMap; - } - - opts._line = { - color: coloring === 'lines' ? colorMap : line.color, - width: contours.showlines !== false ? line.width : 0, - dash: line.dash - }; - - opts._levels = { - start: contours.start, - end: endPlus(contours), - size: cs - }; -} - -module.exports = { - min: 'zmin', - max: 'zmax', - calc: calc -}; - -},{"../../components/colorscale":605,"./end_plus":953,"./make_color_map":958}],946:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; -module.exports = { - // some constants to help with marching squares algorithm - // where does the path start for each index? - BOTTOMSTART: [1, 9, 13, 104, 713], - TOPSTART: [4, 6, 7, 104, 713], - LEFTSTART: [8, 12, 14, 208, 1114], - RIGHTSTART: [2, 3, 11, 208, 1114], - - // which way [dx,dy] do we leave a given index? - // saddles are already disambiguated - NEWDELTA: [ - null, [-1, 0], [0, -1], [-1, 0], - [1, 0], null, [0, -1], [-1, 0], - [0, 1], [0, 1], null, [0, 1], - [1, 0], [1, 0], [0, -1] - ], - - // for each saddle, the first index here is used - // for dx||dy<0, the second for dx||dy>0 - CHOOSESADDLE: { - 104: [4, 1], - 208: [2, 8], - 713: [7, 13], - 1114: [11, 14] - }, - - // after one index has been used for a saddle, which do we - // substitute to be used up later? - SADDLEREMAINDER: {1: 4, 2: 8, 4: 1, 7: 13, 8: 2, 11: 14, 13: 7, 14: 11}, - - // length of a contour, as a multiple of the plot area diagonal, per label - LABELDISTANCE: 2, - - // number of contour levels after which we start increasing the number of - // labels we draw. Many contours means they will generally be close - // together, so it will be harder to follow a long way to find a label - LABELINCREASE: 10, - - // minimum length of a contour line, as a multiple of the label length, - // at which we draw *any* labels - LABELMIN: 3, - - // max number of labels to draw on a single contour path, no matter how long - LABELMAX: 10, - - // constants for the label position cost function - LABELOPTIMIZER: { - // weight given to edge proximity - EDGECOST: 1, - // weight given to the angle off horizontal - ANGLECOST: 1, - // weight given to distance from already-placed labels - NEIGHBORCOST: 5, - // cost multiplier for labels on the same level - SAMELEVELFACTOR: 10, - // minimum distance (as a multiple of the label length) - // for labels on the same level - SAMELEVELDISTANCE: 5, - // maximum cost before we won't even place the label - MAXCOST: 100, - // number of evenly spaced points to look at in the first - // iteration of the search - INITIALSEARCHPOINTS: 10, - // number of binary search iterations after the initial wide search - ITERATIONS: 5 - } -}; - -},{}],947:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; -var isNumeric = _dereq_('fast-isnumeric'); - -var handleLabelDefaults = _dereq_('./label_defaults'); - -var Color = _dereq_('../../components/color'); -var addOpacity = Color.addOpacity; -var opacity = Color.opacity; - -var filterOps = _dereq_('../../constants/filter_ops'); -var CONSTRAINT_REDUCTION = filterOps.CONSTRAINT_REDUCTION; -var COMPARISON_OPS2 = filterOps.COMPARISON_OPS2; - -module.exports = function handleConstraintDefaults(traceIn, traceOut, coerce, layout, defaultColor, opts) { - var contours = traceOut.contours; - var showLines, lineColor, fillColor; - - var operation = coerce('contours.operation'); - contours._operation = CONSTRAINT_REDUCTION[operation]; - - handleConstraintValueDefaults(coerce, contours); - - if(operation === '=') { - showLines = contours.showlines = true; - } else { - showLines = coerce('contours.showlines'); - fillColor = coerce('fillcolor', addOpacity( - (traceIn.line || {}).color || defaultColor, 0.5 - )); - } - - if(showLines) { - var lineDfltColor = fillColor && opacity(fillColor) ? - addOpacity(traceOut.fillcolor, 1) : - defaultColor; - lineColor = coerce('line.color', lineDfltColor); - coerce('line.width', 2); - coerce('line.dash'); - } - - coerce('line.smoothing'); - - handleLabelDefaults(coerce, layout, lineColor, opts); -}; - -function handleConstraintValueDefaults(coerce, contours) { - var zvalue; - - if(COMPARISON_OPS2.indexOf(contours.operation) === -1) { - // Requires an array of two numbers: - coerce('contours.value', [0, 1]); - - if(!Array.isArray(contours.value)) { - if(isNumeric(contours.value)) { - zvalue = parseFloat(contours.value); - contours.value = [zvalue, zvalue + 1]; - } - } else if(contours.value.length > 2) { - contours.value = contours.value.slice(2); - } else if(contours.length === 0) { - contours.value = [0, 1]; - } else if(contours.length < 2) { - zvalue = parseFloat(contours.value[0]); - contours.value = [zvalue, zvalue + 1]; - } else { - contours.value = [ - parseFloat(contours.value[0]), - parseFloat(contours.value[1]) - ]; - } - } else { - // Requires a single scalar: - coerce('contours.value', 0); - - if(!isNumeric(contours.value)) { - if(Array.isArray(contours.value)) { - contours.value = parseFloat(contours.value[0]); - } else { - contours.value = 0; - } - } - } -} - -},{"../../components/color":593,"../../constants/filter_ops":691,"./label_defaults":957,"fast-isnumeric":225}],948:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var filterOps = _dereq_('../../constants/filter_ops'); -var isNumeric = _dereq_('fast-isnumeric'); - -// This syntax conforms to the existing filter transform syntax, but we don't care -// about open vs. closed intervals for simply drawing contours constraints: -module.exports = { - '[]': makeRangeSettings('[]'), - '][': makeRangeSettings(']['), - '>': makeInequalitySettings('>'), - '<': makeInequalitySettings('<'), - '=': makeInequalitySettings('=') -}; - -// This does not in any way shape or form support calendars. It's adapted from -// transforms/filter.js. -function coerceValue(operation, value) { - var hasArrayValue = Array.isArray(value); - - var coercedValue; - - function coerce(value) { - return isNumeric(value) ? (+value) : null; - } - - if(filterOps.COMPARISON_OPS2.indexOf(operation) !== -1) { - coercedValue = hasArrayValue ? coerce(value[0]) : coerce(value); - } else if(filterOps.INTERVAL_OPS.indexOf(operation) !== -1) { - coercedValue = hasArrayValue ? - [coerce(value[0]), coerce(value[1])] : - [coerce(value), coerce(value)]; - } else if(filterOps.SET_OPS.indexOf(operation) !== -1) { - coercedValue = hasArrayValue ? value.map(coerce) : [coerce(value)]; - } - - return coercedValue; -} - -// Returns a parabola scaled so that the min/max is either +/- 1 and zero at the two values -// provided. The data is mapped by this function when constructing intervals so that it's -// very easy to construct contours as normal. -function makeRangeSettings(operation) { - return function(value) { - value = coerceValue(operation, value); - - // Ensure proper ordering: - var min = Math.min(value[0], value[1]); - var max = Math.max(value[0], value[1]); - - return { - start: min, - end: max, - size: max - min - }; - }; -} - -function makeInequalitySettings(operation) { - return function(value) { - value = coerceValue(operation, value); - - return { - start: value, - end: Infinity, - size: Infinity - }; - }; -} - -},{"../../constants/filter_ops":691,"fast-isnumeric":225}],949:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function handleContourDefaults(traceIn, traceOut, coerce, coerce2) { - var contourStart = coerce2('contours.start'); - var contourEnd = coerce2('contours.end'); - var missingEnd = (contourStart === false) || (contourEnd === false); - - // normally we only need size if autocontour is off. But contour.calc - // pushes its calculated contour size back to the input trace, so for - // things like restyle that can call supplyDefaults without calc - // after the initial draw, we can just reuse the previous calculation - var contourSize = coerce('contours.size'); - var autoContour; - - if(missingEnd) autoContour = traceOut.autocontour = true; - else autoContour = coerce('autocontour', false); - - if(autoContour || !contourSize) coerce('ncontours'); -}; - -},{}],950:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -// The contour extraction is great, except it totally fails for constraints because we -// need weird range loops and flipped contours instead of the usual format. This function -// does some weird manipulation of the extracted pathinfo data such that it magically -// draws contours correctly *as* constraints. -module.exports = function(pathinfo, operation) { - var i, pi0, pi1; - - var op0 = function(arr) { return arr.reverse(); }; - var op1 = function(arr) { return arr; }; - - switch(operation) { - case '=': - case '<': - return pathinfo; - case '>': - if(pathinfo.length !== 1) { - Lib.warn('Contour data invalid for the specified inequality operation.'); - } - - // In this case there should be exactly two contour levels in pathinfo. We - // simply concatenate the info into one pathinfo and flip all of the data - // in one. This will draw the contour as closed. - pi0 = pathinfo[0]; - - for(i = 0; i < pi0.edgepaths.length; i++) { - pi0.edgepaths[i] = op0(pi0.edgepaths[i]); - } - - for(i = 0; i < pi0.paths.length; i++) { - pi0.paths[i] = op0(pi0.paths[i]); - } - return pathinfo; - case '][': - var tmp = op0; - op0 = op1; - op1 = tmp; - // It's a nice rule, except this definitely *is* what's intended here. - /* eslint-disable: no-fallthrough */ - case '[]': - /* eslint-enable: no-fallthrough */ - if(pathinfo.length !== 2) { - Lib.warn('Contour data invalid for the specified inequality range operation.'); - } - - // In this case there should be exactly two contour levels in pathinfo. We - // simply concatenate the info into one pathinfo and flip all of the data - // in one. This will draw the contour as closed. - pi0 = copyPathinfo(pathinfo[0]); - pi1 = copyPathinfo(pathinfo[1]); - - for(i = 0; i < pi0.edgepaths.length; i++) { - pi0.edgepaths[i] = op0(pi0.edgepaths[i]); - } - - for(i = 0; i < pi0.paths.length; i++) { - pi0.paths[i] = op0(pi0.paths[i]); - } - - while(pi1.edgepaths.length) { - pi0.edgepaths.push(op1(pi1.edgepaths.shift())); - } - while(pi1.paths.length) { - pi0.paths.push(op1(pi1.paths.shift())); - } - return [pi0]; - } -}; - -function copyPathinfo(pi) { - return Lib.extendFlat({}, pi, { - edgepaths: Lib.extendDeep([], pi.edgepaths), - paths: Lib.extendDeep([], pi.paths) - }); -} - -},{"../../lib":719}],951:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var handleXYZDefaults = _dereq_('../heatmap/xyz_defaults'); -var handleConstraintDefaults = _dereq_('./constraint_defaults'); -var handleContoursDefaults = _dereq_('./contours_defaults'); -var handleStyleDefaults = _dereq_('./style_defaults'); -var attributes = _dereq_('./attributes'); - - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - function coerce2(attr) { - return Lib.coerce2(traceIn, traceOut, attributes, attr); - } - - var len = handleXYZDefaults(traceIn, traceOut, coerce, layout); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - var isConstraint = (coerce('contours.type') === 'constraint'); - coerce('connectgaps', Lib.isArray1D(traceOut.z)); - - if(isConstraint) { - handleConstraintDefaults(traceIn, traceOut, coerce, layout, defaultColor); - } else { - handleContoursDefaults(traceIn, traceOut, coerce, coerce2); - handleStyleDefaults(traceIn, traceOut, coerce, layout); - } -}; - -},{"../../lib":719,"../heatmap/xyz_defaults":1015,"./attributes":942,"./constraint_defaults":947,"./contours_defaults":949,"./style_defaults":963}],952:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var constraintMapping = _dereq_('./constraint_mapping'); -var endPlus = _dereq_('./end_plus'); - -module.exports = function emptyPathinfo(contours, plotinfo, cd0) { - var contoursFinal = (contours.type === 'constraint') ? - constraintMapping[contours._operation](contours.value) : - contours; - - var cs = contoursFinal.size; - var pathinfo = []; - var end = endPlus(contoursFinal); - - var carpet = cd0.trace._carpetTrace; - - var basePathinfo = carpet ? { - // store axes so we can convert to px - xaxis: carpet.aaxis, - yaxis: carpet.baxis, - // full data arrays to use for interpolation - x: cd0.a, - y: cd0.b - } : { - xaxis: plotinfo.xaxis, - yaxis: plotinfo.yaxis, - x: cd0.x, - y: cd0.y - }; - - for(var ci = contoursFinal.start; ci < end; ci += cs) { - pathinfo.push(Lib.extendFlat({ - level: ci, - // all the cells with nontrivial marching index - crossings: {}, - // starting points on the edges of the lattice for each contour - starts: [], - // all unclosed paths (may have less items than starts, - // if a path is closed by rounding) - edgepaths: [], - // all closed paths - paths: [], - z: cd0.z, - smoothing: cd0.trace.line.smoothing - }, basePathinfo)); - - if(pathinfo.length > 1000) { - Lib.warn('Too many contours, clipping at 1000', contours); - break; - } - } - return pathinfo; -}; - -},{"../../lib":719,"./constraint_mapping":948,"./end_plus":953}],953:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -/* - * tiny helper to move the end of the contours a little to prevent - * losing the last contour to rounding errors - */ -module.exports = function endPlus(contours) { - return contours.end + contours.size / 1e6; -}; - -},{}],954:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var constants = _dereq_('./constants'); - -module.exports = function findAllPaths(pathinfo, xtol, ytol) { - var cnt, - startLoc, - i, - pi, - j; - - // Default just passes these values through as they were before: - xtol = xtol || 0.01; - ytol = ytol || 0.01; - - for(i = 0; i < pathinfo.length; i++) { - pi = pathinfo[i]; - - for(j = 0; j < pi.starts.length; j++) { - startLoc = pi.starts[j]; - makePath(pi, startLoc, 'edge', xtol, ytol); - } - - cnt = 0; - while(Object.keys(pi.crossings).length && cnt < 10000) { - cnt++; - startLoc = Object.keys(pi.crossings)[0].split(',').map(Number); - makePath(pi, startLoc, undefined, xtol, ytol); - } - if(cnt === 10000) Lib.log('Infinite loop in contour?'); - } -}; - -function equalPts(pt1, pt2, xtol, ytol) { - return Math.abs(pt1[0] - pt2[0]) < xtol && - Math.abs(pt1[1] - pt2[1]) < ytol; -} - -// distance in index units - uses the 3rd and 4th items in points -function ptDist(pt1, pt2) { - var dx = pt1[2] - pt2[2]; - var dy = pt1[3] - pt2[3]; - return Math.sqrt(dx * dx + dy * dy); -} - -function makePath(pi, loc, edgeflag, xtol, ytol) { - var startLocStr = loc.join(','); - var locStr = startLocStr; - var mi = pi.crossings[locStr]; - var marchStep = startStep(mi, edgeflag, loc); - // start by going backward a half step and finding the crossing point - var pts = [getInterpPx(pi, loc, [-marchStep[0], -marchStep[1]])]; - var startStepStr = marchStep.join(','); - var m = pi.z.length; - var n = pi.z[0].length; - var cnt; - - // now follow the path - for(cnt = 0; cnt < 10000; cnt++) { // just to avoid infinite loops - if(mi > 20) { - mi = constants.CHOOSESADDLE[mi][(marchStep[0] || marchStep[1]) < 0 ? 0 : 1]; - pi.crossings[locStr] = constants.SADDLEREMAINDER[mi]; - } else { - delete pi.crossings[locStr]; - } - - marchStep = constants.NEWDELTA[mi]; - if(!marchStep) { - Lib.log('Found bad marching index:', mi, loc, pi.level); - break; - } - - // find the crossing a half step forward, and then take the full step - pts.push(getInterpPx(pi, loc, marchStep)); - loc[0] += marchStep[0]; - loc[1] += marchStep[1]; - - // don't include the same point multiple times - if(equalPts(pts[pts.length - 1], pts[pts.length - 2], xtol, ytol)) pts.pop(); - locStr = loc.join(','); - - var atEdge = (marchStep[0] && (loc[0] < 0 || loc[0] > n - 2)) || - (marchStep[1] && (loc[1] < 0 || loc[1] > m - 2)); - var closedLoop = (locStr === startLocStr) && (marchStep.join(',') === startStepStr); - - // have we completed a loop, or reached an edge? - if((closedLoop) || (edgeflag && atEdge)) break; - - mi = pi.crossings[locStr]; - } - - if(cnt === 10000) { - Lib.log('Infinite loop in contour?'); - } - var closedpath = equalPts(pts[0], pts[pts.length - 1], xtol, ytol); - var totaldist = 0; - var distThresholdFactor = 0.2 * pi.smoothing; - var alldists = []; - var cropstart = 0; - var distgroup, cnt2, cnt3, newpt, ptcnt, ptavg, thisdist, - i, j, edgepathi, edgepathj; - - /* - * Check for points that are too close together (<1/5 the average dist - * *in grid index units* (important for log axes and nonuniform grids), - * less if less smoothed) and just take the center (or avg of center 2). - * This cuts down on funny behavior when a point is very close to a - * contour level. - */ - for(cnt = 1; cnt < pts.length; cnt++) { - thisdist = ptDist(pts[cnt], pts[cnt - 1]); - totaldist += thisdist; - alldists.push(thisdist); - } - - var distThreshold = totaldist / alldists.length * distThresholdFactor; - - function getpt(i) { return pts[i % pts.length]; } - - for(cnt = pts.length - 2; cnt >= cropstart; cnt--) { - distgroup = alldists[cnt]; - if(distgroup < distThreshold) { - cnt3 = 0; - for(cnt2 = cnt - 1; cnt2 >= cropstart; cnt2--) { - if(distgroup + alldists[cnt2] < distThreshold) { - distgroup += alldists[cnt2]; - } else break; - } - - // closed path with close points wrapping around the boundary? - if(closedpath && cnt === pts.length - 2) { - for(cnt3 = 0; cnt3 < cnt2; cnt3++) { - if(distgroup + alldists[cnt3] < distThreshold) { - distgroup += alldists[cnt3]; - } else break; - } - } - ptcnt = cnt - cnt2 + cnt3 + 1; - ptavg = Math.floor((cnt + cnt2 + cnt3 + 2) / 2); - - // either endpoint included: keep the endpoint - if(!closedpath && cnt === pts.length - 2) newpt = pts[pts.length - 1]; - else if(!closedpath && cnt2 === -1) newpt = pts[0]; - - // odd # of points - just take the central one - else if(ptcnt % 2) newpt = getpt(ptavg); - - // even # of pts - average central two - else { - newpt = [(getpt(ptavg)[0] + getpt(ptavg + 1)[0]) / 2, - (getpt(ptavg)[1] + getpt(ptavg + 1)[1]) / 2]; - } - - pts.splice(cnt2 + 1, cnt - cnt2 + 1, newpt); - cnt = cnt2 + 1; - if(cnt3) cropstart = cnt3; - if(closedpath) { - if(cnt === pts.length - 2) pts[cnt3] = pts[pts.length - 1]; - else if(cnt === 0) pts[pts.length - 1] = pts[0]; - } - } - } - pts.splice(0, cropstart); - - // done with the index parts - remove them so path generation works right - // because it depends on only having [xpx, ypx] - for(cnt = 0; cnt < pts.length; cnt++) pts[cnt].length = 2; - - // don't return single-point paths (ie all points were the same - // so they got deleted?) - if(pts.length < 2) return; - else if(closedpath) { - pts.pop(); - pi.paths.push(pts); - } else { - if(!edgeflag) { - Lib.log('Unclosed interior contour?', - pi.level, startLocStr, pts.join('L')); - } - - // edge path - does it start where an existing edge path ends, or vice versa? - var merged = false; - for(i = 0; i < pi.edgepaths.length; i++) { - edgepathi = pi.edgepaths[i]; - if(!merged && equalPts(edgepathi[0], pts[pts.length - 1], xtol, ytol)) { - pts.pop(); - merged = true; - - // now does it ALSO meet the end of another (or the same) path? - var doublemerged = false; - for(j = 0; j < pi.edgepaths.length; j++) { - edgepathj = pi.edgepaths[j]; - if(equalPts(edgepathj[edgepathj.length - 1], pts[0], xtol, ytol)) { - doublemerged = true; - pts.shift(); - pi.edgepaths.splice(i, 1); - if(j === i) { - // the path is now closed - pi.paths.push(pts.concat(edgepathj)); - } else { - if(j > i) j--; - pi.edgepaths[j] = edgepathj.concat(pts, edgepathi); - } - break; - } - } - if(!doublemerged) { - pi.edgepaths[i] = pts.concat(edgepathi); - } - } - } - for(i = 0; i < pi.edgepaths.length; i++) { - if(merged) break; - edgepathi = pi.edgepaths[i]; - if(equalPts(edgepathi[edgepathi.length - 1], pts[0], xtol, ytol)) { - pts.shift(); - pi.edgepaths[i] = edgepathi.concat(pts); - merged = true; - } - } - - if(!merged) pi.edgepaths.push(pts); - } -} - -// special function to get the marching step of the -// first point in the path (leading to loc) -function startStep(mi, edgeflag, loc) { - var dx = 0; - var dy = 0; - if(mi > 20 && edgeflag) { - // these saddles start at +/- x - if(mi === 208 || mi === 1114) { - // if we're starting at the left side, we must be going right - dx = loc[0] === 0 ? 1 : -1; - } else { - // if we're starting at the bottom, we must be going up - dy = loc[1] === 0 ? 1 : -1; - } - } else if(constants.BOTTOMSTART.indexOf(mi) !== -1) dy = 1; - else if(constants.LEFTSTART.indexOf(mi) !== -1) dx = 1; - else if(constants.TOPSTART.indexOf(mi) !== -1) dy = -1; - else dx = -1; - return [dx, dy]; -} - -/* - * Find the pixel coordinates of a particular crossing - * - * @param {object} pi: the pathinfo object at this level - * @param {array} loc: the grid index [x, y] of the crossing - * @param {array} step: the direction [dx, dy] we're moving on the grid - * - * @return {array} [xpx, ypx, xi, yi]: the first two are the pixel location, - * the next two are the interpolated grid indices, which we use for - * distance calculations to delete points that are too close together. - * This is important when the grid is nonuniform (and most dramatically when - * we're on log axes and include invalid (0 or negative) values. - * It's crucial to delete these extra two before turning an array of these - * points into a path, because those routines require length-2 points. - */ -function getInterpPx(pi, loc, step) { - var locx = loc[0] + Math.max(step[0], 0); - var locy = loc[1] + Math.max(step[1], 0); - var zxy = pi.z[locy][locx]; - var xa = pi.xaxis; - var ya = pi.yaxis; - - if(step[1]) { - var dx = (pi.level - zxy) / (pi.z[locy][locx + 1] - zxy); - - return [xa.c2p((1 - dx) * pi.x[locx] + dx * pi.x[locx + 1], true), - ya.c2p(pi.y[locy], true), - locx + dx, locy]; - } else { - var dy = (pi.level - zxy) / (pi.z[locy + 1][locx] - zxy); - return [xa.c2p(pi.x[locx], true), - ya.c2p((1 - dy) * pi.y[locy] + dy * pi.y[locy + 1], true), - locx, locy + dy]; - } -} - -},{"../../lib":719,"./constants":946}],955:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Color = _dereq_('../../components/color'); - -var heatmapHoverPoints = _dereq_('../heatmap/hover'); - -module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer) { - var hoverData = heatmapHoverPoints(pointData, xval, yval, hovermode, hoverLayer, true); - - if(hoverData) { - hoverData.forEach(function(hoverPt) { - var trace = hoverPt.trace; - if(trace.contours.type === 'constraint') { - if(trace.fillcolor && Color.opacity(trace.fillcolor)) { - hoverPt.color = Color.addOpacity(trace.fillcolor, 1); - } else if(trace.contours.showlines && Color.opacity(trace.line.color)) { - hoverPt.color = Color.addOpacity(trace.line.color, 1); - } - } - }); - } - - return hoverData; -}; - -},{"../../components/color":593,"../heatmap/hover":1008}],956:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot').plot, - style: _dereq_('./style'), - colorbar: _dereq_('./colorbar'), - hoverPoints: _dereq_('./hover'), - - moduleType: 'trace', - name: 'contour', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', '2dMap', 'contour', 'showLegend'], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"./attributes":942,"./calc":943,"./colorbar":945,"./defaults":951,"./hover":955,"./plot":960,"./style":962}],957:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -module.exports = function handleLabelDefaults(coerce, layout, lineColor, opts) { - if(!opts) opts = {}; - var showLabels = coerce('contours.showlabels'); - if(showLabels) { - var globalFont = layout.font; - Lib.coerceFont(coerce, 'contours.labelfont', { - family: globalFont.family, - size: globalFont.size, - color: lineColor - }); - coerce('contours.labelformat'); - } - - if(opts.hasHover !== false) coerce('zhoverformat'); -}; - -},{"../../lib":719}],958:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Colorscale = _dereq_('../../components/colorscale'); -var endPlus = _dereq_('./end_plus'); - -module.exports = function makeColorMap(trace) { - var contours = trace.contours; - var start = contours.start; - var end = endPlus(contours); - var cs = contours.size || 1; - var nc = Math.floor((end - start) / cs) + 1; - var extra = contours.coloring === 'lines' ? 0 : 1; - var cOpts = Colorscale.extractOpts(trace); - - if(!isFinite(cs)) { - cs = 1; - nc = 1; - } - - var scl = cOpts.reversescale ? - Colorscale.flipScale(cOpts.colorscale) : - cOpts.colorscale; - - var len = scl.length; - var domain = new Array(len); - var range = new Array(len); - - var si, i; - - if(contours.coloring === 'heatmap') { - var zmin0 = cOpts.min; - var zmax0 = cOpts.max; - - for(i = 0; i < len; i++) { - si = scl[i]; - domain[i] = si[0] * (zmax0 - zmin0) + zmin0; - range[i] = si[1]; - } - - // do the contours extend beyond the colorscale? - // if so, extend the colorscale with constants - var zRange = d3.extent([ - zmin0, - zmax0, - contours.start, - contours.start + cs * (nc - 1) - ]); - var zmin = zRange[zmin0 < zmax0 ? 0 : 1]; - var zmax = zRange[zmin0 < zmax0 ? 1 : 0]; - - if(zmin !== zmin0) { - domain.splice(0, 0, zmin); - range.splice(0, 0, range[0]); - } - - if(zmax !== zmax0) { - domain.push(zmax); - range.push(range[range.length - 1]); - } - } else { - for(i = 0; i < len; i++) { - si = scl[i]; - domain[i] = (si[0] * (nc + extra - 1) - (extra / 2)) * cs + start; - range[i] = si[1]; - } - } - - return Colorscale.makeColorScaleFunc( - {domain: domain, range: range}, - {noNumericCheck: true} - ); -}; - -},{"../../components/colorscale":605,"./end_plus":953,"d3":163}],959:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var constants = _dereq_('./constants'); - -// Calculate all the marching indices, for ALL levels at once. -// since we want to be exhaustive we'll check for contour crossings -// at every intersection, rather than just following a path -// TODO: shorten the inner loop to only the relevant levels -module.exports = function makeCrossings(pathinfo) { - var z = pathinfo[0].z; - var m = z.length; - var n = z[0].length; // we already made sure z isn't ragged in interp2d - var twoWide = m === 2 || n === 2; - var xi; - var yi; - var startIndices; - var ystartIndices; - var label; - var corners; - var mi; - var pi; - var i; - - for(yi = 0; yi < m - 1; yi++) { - ystartIndices = []; - if(yi === 0) ystartIndices = ystartIndices.concat(constants.BOTTOMSTART); - if(yi === m - 2) ystartIndices = ystartIndices.concat(constants.TOPSTART); - - for(xi = 0; xi < n - 1; xi++) { - startIndices = ystartIndices.slice(); - if(xi === 0) startIndices = startIndices.concat(constants.LEFTSTART); - if(xi === n - 2) startIndices = startIndices.concat(constants.RIGHTSTART); - - label = xi + ',' + yi; - corners = [[z[yi][xi], z[yi][xi + 1]], - [z[yi + 1][xi], z[yi + 1][xi + 1]]]; - for(i = 0; i < pathinfo.length; i++) { - pi = pathinfo[i]; - mi = getMarchingIndex(pi.level, corners); - if(!mi) continue; - - pi.crossings[label] = mi; - if(startIndices.indexOf(mi) !== -1) { - pi.starts.push([xi, yi]); - if(twoWide && startIndices.indexOf(mi, - startIndices.indexOf(mi) + 1) !== -1) { - // the same square has starts from opposite sides - // it's not possible to have starts on opposite edges - // of a corner, only a start and an end... - // but if the array is only two points wide (either way) - // you can have starts on opposite sides. - pi.starts.push([xi, yi]); - } - } - } - } - } -}; - -// modified marching squares algorithm, -// so we disambiguate the saddle points from the start -// and we ignore the cases with no crossings -// the index I'm using is based on: -// http://en.wikipedia.org/wiki/Marching_squares -// except that the saddles bifurcate and I represent them -// as the decimal combination of the two appropriate -// non-saddle indices -function getMarchingIndex(val, corners) { - var mi = (corners[0][0] > val ? 0 : 1) + - (corners[0][1] > val ? 0 : 2) + - (corners[1][1] > val ? 0 : 4) + - (corners[1][0] > val ? 0 : 8); - if(mi === 5 || mi === 10) { - var avg = (corners[0][0] + corners[0][1] + - corners[1][0] + corners[1][1]) / 4; - // two peaks with a big valley - if(val > avg) return (mi === 5) ? 713 : 1114; - // two valleys with a big ridge - return (mi === 5) ? 104 : 208; - } - return (mi === 15) ? 0 : mi; -} - -},{"./constants":946}],960:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../../components/drawing'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var setConvert = _dereq_('../../plots/cartesian/set_convert'); - -var heatmapPlot = _dereq_('../heatmap/plot'); -var makeCrossings = _dereq_('./make_crossings'); -var findAllPaths = _dereq_('./find_all_paths'); -var emptyPathinfo = _dereq_('./empty_pathinfo'); -var convertToConstraints = _dereq_('./convert_to_constraints'); -var closeBoundaries = _dereq_('./close_boundaries'); -var constants = _dereq_('./constants'); -var costConstants = constants.LABELOPTIMIZER; - -exports.plot = function plot(gd, plotinfo, cdcontours, contourLayer) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - Lib.makeTraceGroups(contourLayer, cdcontours, 'contour').each(function(cd) { - var plotGroup = d3.select(this); - var cd0 = cd[0]; - var trace = cd0.trace; - var x = cd0.x; - var y = cd0.y; - var contours = trace.contours; - var pathinfo = emptyPathinfo(contours, plotinfo, cd0); - - // use a heatmap to fill - draw it behind the lines - var heatmapColoringLayer = Lib.ensureSingle(plotGroup, 'g', 'heatmapcoloring'); - var cdheatmaps = []; - if(contours.coloring === 'heatmap') { - cdheatmaps = [cd]; - } - heatmapPlot(gd, plotinfo, cdheatmaps, heatmapColoringLayer); - - makeCrossings(pathinfo); - findAllPaths(pathinfo); - - var leftedge = xa.c2p(x[0], true); - var rightedge = xa.c2p(x[x.length - 1], true); - var bottomedge = ya.c2p(y[0], true); - var topedge = ya.c2p(y[y.length - 1], true); - var perimeter = [ - [leftedge, topedge], - [rightedge, topedge], - [rightedge, bottomedge], - [leftedge, bottomedge] - ]; - - var fillPathinfo = pathinfo; - if(contours.type === 'constraint') { - fillPathinfo = convertToConstraints(pathinfo, contours._operation); - closeBoundaries(fillPathinfo, contours._operation, perimeter, trace); - } - - // draw everything - makeBackground(plotGroup, perimeter, contours); - makeFills(plotGroup, fillPathinfo, perimeter, contours); - makeLinesAndLabels(plotGroup, pathinfo, gd, cd0, contours); - clipGaps(plotGroup, plotinfo, gd, cd0, perimeter); - }); -}; - -function makeBackground(plotgroup, perimeter, contours) { - var bggroup = Lib.ensureSingle(plotgroup, 'g', 'contourbg'); - - var bgfill = bggroup.selectAll('path') - .data(contours.coloring === 'fill' ? [0] : []); - bgfill.enter().append('path'); - bgfill.exit().remove(); - bgfill - .attr('d', 'M' + perimeter.join('L') + 'Z') - .style('stroke', 'none'); -} - -function makeFills(plotgroup, pathinfo, perimeter, contours) { - var fillgroup = Lib.ensureSingle(plotgroup, 'g', 'contourfill'); - - var fillitems = fillgroup.selectAll('path') - .data(contours.coloring === 'fill' || (contours.type === 'constraint' && contours._operation !== '=') ? pathinfo : []); - fillitems.enter().append('path'); - fillitems.exit().remove(); - fillitems.each(function(pi) { - // join all paths for this level together into a single path - // first follow clockwise around the perimeter to close any open paths - // if the whole perimeter is above this level, start with a path - // enclosing the whole thing. With all that, the parity should mean - // that we always fill everything above the contour, nothing below - var fullpath = joinAllPaths(pi, perimeter); - - if(!fullpath) d3.select(this).remove(); - else d3.select(this).attr('d', fullpath).style('stroke', 'none'); - }); -} - -function initFullPath(pi, perimeter) { - var prefixBoundary = pi.prefixBoundary; - if(prefixBoundary === undefined) { - var edgeVal2 = Math.min(pi.z[0][0], pi.z[0][1]); - prefixBoundary = (!pi.edgepaths.length && edgeVal2 > pi.level); - } - - if(prefixBoundary) { - // TODO: why does ^^ not work for constraints? - // pi.prefixBoundary gets set by closeBoundaries - return 'M' + perimeter.join('L') + 'Z'; - } - return ''; -} - -function joinAllPaths(pi, perimeter) { - var fullpath = initFullPath(pi, perimeter); - var i = 0; - var startsleft = pi.edgepaths.map(function(v, i) { return i; }); - var newloop = true; - var endpt; - var newendpt; - var cnt; - var nexti; - var possiblei; - var addpath; - - function istop(pt) { return Math.abs(pt[1] - perimeter[0][1]) < 0.01; } - function isbottom(pt) { return Math.abs(pt[1] - perimeter[2][1]) < 0.01; } - function isleft(pt) { return Math.abs(pt[0] - perimeter[0][0]) < 0.01; } - function isright(pt) { return Math.abs(pt[0] - perimeter[2][0]) < 0.01; } - - while(startsleft.length) { - addpath = Drawing.smoothopen(pi.edgepaths[i], pi.smoothing); - fullpath += newloop ? addpath : addpath.replace(/^M/, 'L'); - startsleft.splice(startsleft.indexOf(i), 1); - endpt = pi.edgepaths[i][pi.edgepaths[i].length - 1]; - nexti = -1; - - // now loop through sides, moving our endpoint until we find a new start - for(cnt = 0; cnt < 4; cnt++) { // just to prevent infinite loops - if(!endpt) { - Lib.log('Missing end?', i, pi); - break; - } - - if(istop(endpt) && !isright(endpt)) newendpt = perimeter[1]; // right top - else if(isleft(endpt)) newendpt = perimeter[0]; // left top - else if(isbottom(endpt)) newendpt = perimeter[3]; // right bottom - else if(isright(endpt)) newendpt = perimeter[2]; // left bottom - - for(possiblei = 0; possiblei < pi.edgepaths.length; possiblei++) { - var ptNew = pi.edgepaths[possiblei][0]; - // is ptNew on the (horz. or vert.) segment from endpt to newendpt? - if(Math.abs(endpt[0] - newendpt[0]) < 0.01) { - if(Math.abs(endpt[0] - ptNew[0]) < 0.01 && - (ptNew[1] - endpt[1]) * (newendpt[1] - ptNew[1]) >= 0) { - newendpt = ptNew; - nexti = possiblei; - } - } else if(Math.abs(endpt[1] - newendpt[1]) < 0.01) { - if(Math.abs(endpt[1] - ptNew[1]) < 0.01 && - (ptNew[0] - endpt[0]) * (newendpt[0] - ptNew[0]) >= 0) { - newendpt = ptNew; - nexti = possiblei; - } - } else { - Lib.log('endpt to newendpt is not vert. or horz.', - endpt, newendpt, ptNew); - } - } - - endpt = newendpt; - - if(nexti >= 0) break; - fullpath += 'L' + newendpt; - } - - if(nexti === pi.edgepaths.length) { - Lib.log('unclosed perimeter path'); - break; - } - - i = nexti; - - // if we closed back on a loop we already included, - // close it and start a new loop - newloop = (startsleft.indexOf(i) === -1); - if(newloop) { - i = startsleft[0]; - fullpath += 'Z'; - } - } - - // finally add the interior paths - for(i = 0; i < pi.paths.length; i++) { - fullpath += Drawing.smoothclosed(pi.paths[i], pi.smoothing); - } - - return fullpath; -} - -function makeLinesAndLabels(plotgroup, pathinfo, gd, cd0, contours) { - var lineContainer = Lib.ensureSingle(plotgroup, 'g', 'contourlines'); - var showLines = contours.showlines !== false; - var showLabels = contours.showlabels; - var clipLinesForLabels = showLines && showLabels; - - // Even if we're not going to show lines, we need to create them - // if we're showing labels, because the fill paths include the perimeter - // so can't be used to position the labels correctly. - // In this case we'll remove the lines after making the labels. - var linegroup = exports.createLines(lineContainer, showLines || showLabels, pathinfo); - - var lineClip = exports.createLineClip(lineContainer, clipLinesForLabels, gd, cd0.trace.uid); - - var labelGroup = plotgroup.selectAll('g.contourlabels') - .data(showLabels ? [0] : []); - - labelGroup.exit().remove(); - - labelGroup.enter().append('g') - .classed('contourlabels', true); - - if(showLabels) { - var labelClipPathData = []; - var labelData = []; - - // invalidate the getTextLocation cache in case paths changed - Lib.clearLocationCache(); - - var contourFormat = exports.labelFormatter(contours, cd0.t.cb, gd._fullLayout); - - var dummyText = Drawing.tester.append('text') - .attr('data-notex', 1) - .call(Drawing.font, contours.labelfont); - - var xa = pathinfo[0].xaxis; - var ya = pathinfo[0].yaxis; - var xLen = xa._length; - var yLen = ya._length; - var xRng = xa.range; - var yRng = ya.range; - var xMin = Lib.aggNums(Math.min, null, cd0.x); - var xMax = Lib.aggNums(Math.max, null, cd0.x); - var yMin = Lib.aggNums(Math.min, null, cd0.y); - var yMax = Lib.aggNums(Math.max, null, cd0.y); - var x0 = Math.max(xa.c2p(xMin, true), 0); - var x1 = Math.min(xa.c2p(xMax, true), xLen); - var y0 = Math.max(ya.c2p(yMax, true), 0); - var y1 = Math.min(ya.c2p(yMin, true), yLen); - - // visible bounds of the contour trace (and the midpoints, to - // help with cost calculations) - var bounds = {}; - - if(xRng[0] < xRng[1]) { - bounds.left = x0; - bounds.right = x1; - } else { - bounds.left = x1; - bounds.right = x0; - } - - if(yRng[0] < yRng[1]) { - bounds.top = y0; - bounds.bottom = y1; - } else { - bounds.top = y1; - bounds.bottom = y0; - } - - bounds.middle = (bounds.top + bounds.bottom) / 2; - bounds.center = (bounds.left + bounds.right) / 2; - - labelClipPathData.push([ - [bounds.left, bounds.top], - [bounds.right, bounds.top], - [bounds.right, bounds.bottom], - [bounds.left, bounds.bottom] - ]); - - var plotDiagonal = Math.sqrt(xLen * xLen + yLen * yLen); - - // the path length to use to scale the number of labels to draw: - var normLength = constants.LABELDISTANCE * plotDiagonal / - Math.max(1, pathinfo.length / constants.LABELINCREASE); - - linegroup.each(function(d) { - var textOpts = exports.calcTextOpts(d.level, contourFormat, dummyText, gd); - - d3.select(this).selectAll('path').each(function() { - var path = this; - var pathBounds = Lib.getVisibleSegment(path, bounds, textOpts.height / 2); - if(!pathBounds) return; - - if(pathBounds.len < (textOpts.width + textOpts.height) * constants.LABELMIN) return; - - var maxLabels = Math.min(Math.ceil(pathBounds.len / normLength), - constants.LABELMAX); - - for(var i = 0; i < maxLabels; i++) { - var loc = exports.findBestTextLocation(path, pathBounds, textOpts, - labelData, bounds); - - if(!loc) break; - - exports.addLabelData(loc, textOpts, labelData, labelClipPathData); - } - }); - }); - - dummyText.remove(); - - exports.drawLabels(labelGroup, labelData, gd, lineClip, - clipLinesForLabels ? labelClipPathData : null); - } - - if(showLabels && !showLines) linegroup.remove(); -} - -exports.createLines = function(lineContainer, makeLines, pathinfo) { - var smoothing = pathinfo[0].smoothing; - - var linegroup = lineContainer.selectAll('g.contourlevel') - .data(makeLines ? pathinfo : []); - - linegroup.exit().remove(); - linegroup.enter().append('g') - .classed('contourlevel', true); - - if(makeLines) { - // pedgepaths / ppaths are used by contourcarpet, for the paths transformed from a/b to x/y - // edgepaths / paths are used by contour since it's in x/y from the start - var opencontourlines = linegroup.selectAll('path.openline') - .data(function(d) { return d.pedgepaths || d.edgepaths; }); - - opencontourlines.exit().remove(); - opencontourlines.enter().append('path') - .classed('openline', true); - - opencontourlines - .attr('d', function(d) { - return Drawing.smoothopen(d, smoothing); - }) - .style('stroke-miterlimit', 1) - .style('vector-effect', 'non-scaling-stroke'); - - var closedcontourlines = linegroup.selectAll('path.closedline') - .data(function(d) { return d.ppaths || d.paths; }); - - closedcontourlines.exit().remove(); - closedcontourlines.enter().append('path') - .classed('closedline', true); - - closedcontourlines - .attr('d', function(d) { - return Drawing.smoothclosed(d, smoothing); - }) - .style('stroke-miterlimit', 1) - .style('vector-effect', 'non-scaling-stroke'); - } - - return linegroup; -}; - -exports.createLineClip = function(lineContainer, clipLinesForLabels, gd, uid) { - var clips = gd._fullLayout._clips; - var clipId = clipLinesForLabels ? ('clipline' + uid) : null; - - var lineClip = clips.selectAll('#' + clipId) - .data(clipLinesForLabels ? [0] : []); - lineClip.exit().remove(); - - lineClip.enter().append('clipPath') - .classed('contourlineclip', true) - .attr('id', clipId); - - Drawing.setClipUrl(lineContainer, clipId, gd); - - return lineClip; -}; - -exports.labelFormatter = function(contours, colorbar, fullLayout) { - if(contours.labelformat) { - return fullLayout._d3locale.numberFormat(contours.labelformat); - } else { - var formatAxis; - if(colorbar) { - formatAxis = colorbar.axis; - } else { - formatAxis = { - type: 'linear', - _id: 'ycontour', - showexponent: 'all', - exponentformat: 'B' - }; - - if(contours.type === 'constraint') { - var value = contours.value; - if(Array.isArray(value)) { - formatAxis.range = [value[0], value[value.length - 1]]; - } else formatAxis.range = [value, value]; - } else { - formatAxis.range = [contours.start, contours.end]; - formatAxis.nticks = (contours.end - contours.start) / contours.size; - } - - if(formatAxis.range[0] === formatAxis.range[1]) { - formatAxis.range[1] += formatAxis.range[0] || 1; - } - if(!formatAxis.nticks) formatAxis.nticks = 1000; - - setConvert(formatAxis, fullLayout); - Axes.prepTicks(formatAxis); - formatAxis._tmin = null; - formatAxis._tmax = null; - } - return function(v) { - return Axes.tickText(formatAxis, v).text; - }; - } -}; - -exports.calcTextOpts = function(level, contourFormat, dummyText, gd) { - var text = contourFormat(level); - dummyText.text(text) - .call(svgTextUtils.convertToTspans, gd); - var bBox = Drawing.bBox(dummyText.node(), true); - - return { - text: text, - width: bBox.width, - height: bBox.height, - level: level, - dy: (bBox.top + bBox.bottom) / 2 - }; -}; - -exports.findBestTextLocation = function(path, pathBounds, textOpts, labelData, plotBounds) { - var textWidth = textOpts.width; - - var p0, dp, pMax, pMin, loc; - if(pathBounds.isClosed) { - dp = pathBounds.len / costConstants.INITIALSEARCHPOINTS; - p0 = pathBounds.min + dp / 2; - pMax = pathBounds.max; - } else { - dp = (pathBounds.len - textWidth) / (costConstants.INITIALSEARCHPOINTS + 1); - p0 = pathBounds.min + dp + textWidth / 2; - pMax = pathBounds.max - (dp + textWidth) / 2; - } - - var cost = Infinity; - for(var j = 0; j < costConstants.ITERATIONS; j++) { - for(var p = p0; p < pMax; p += dp) { - var newLocation = Lib.getTextLocation(path, pathBounds.total, p, textWidth); - var newCost = locationCost(newLocation, textOpts, labelData, plotBounds); - if(newCost < cost) { - cost = newCost; - loc = newLocation; - pMin = p; - } - } - if(cost > costConstants.MAXCOST * 2) break; - - // subsequent iterations just look half steps away from the - // best we found in the previous iteration - if(j) dp /= 2; - p0 = pMin - dp / 2; - pMax = p0 + dp * 1.5; - } - if(cost <= costConstants.MAXCOST) return loc; -}; - -/* - * locationCost: a cost function for label locations - * composed of three kinds of penalty: - * - for open paths, being close to the end of the path - * - the angle away from horizontal - * - being too close to already placed neighbors - */ -function locationCost(loc, textOpts, labelData, bounds) { - var halfWidth = textOpts.width / 2; - var halfHeight = textOpts.height / 2; - var x = loc.x; - var y = loc.y; - var theta = loc.theta; - var dx = Math.cos(theta) * halfWidth; - var dy = Math.sin(theta) * halfWidth; - - // cost for being near an edge - var normX = ((x > bounds.center) ? (bounds.right - x) : (x - bounds.left)) / - (dx + Math.abs(Math.sin(theta) * halfHeight)); - var normY = ((y > bounds.middle) ? (bounds.bottom - y) : (y - bounds.top)) / - (Math.abs(dy) + Math.cos(theta) * halfHeight); - if(normX < 1 || normY < 1) return Infinity; - var cost = costConstants.EDGECOST * (1 / (normX - 1) + 1 / (normY - 1)); - - // cost for not being horizontal - cost += costConstants.ANGLECOST * theta * theta; - - // cost for being close to other labels - var x1 = x - dx; - var y1 = y - dy; - var x2 = x + dx; - var y2 = y + dy; - for(var i = 0; i < labelData.length; i++) { - var labeli = labelData[i]; - var dxd = Math.cos(labeli.theta) * labeli.width / 2; - var dyd = Math.sin(labeli.theta) * labeli.width / 2; - var dist = Lib.segmentDistance( - x1, y1, - x2, y2, - labeli.x - dxd, labeli.y - dyd, - labeli.x + dxd, labeli.y + dyd - ) * 2 / (textOpts.height + labeli.height); - - var sameLevel = labeli.level === textOpts.level; - var distOffset = sameLevel ? costConstants.SAMELEVELDISTANCE : 1; - - if(dist <= distOffset) return Infinity; - - var distFactor = costConstants.NEIGHBORCOST * - (sameLevel ? costConstants.SAMELEVELFACTOR : 1); - - cost += distFactor / (dist - distOffset); - } - - return cost; -} - -exports.addLabelData = function(loc, textOpts, labelData, labelClipPathData) { - var halfWidth = textOpts.width / 2; - var halfHeight = textOpts.height / 2; - - var x = loc.x; - var y = loc.y; - var theta = loc.theta; - - var sin = Math.sin(theta); - var cos = Math.cos(theta); - var dxw = halfWidth * cos; - var dxh = halfHeight * sin; - var dyw = halfWidth * sin; - var dyh = -halfHeight * cos; - var bBoxPts = [ - [x - dxw - dxh, y - dyw - dyh], - [x + dxw - dxh, y + dyw - dyh], - [x + dxw + dxh, y + dyw + dyh], - [x - dxw + dxh, y - dyw + dyh], - ]; - - labelData.push({ - text: textOpts.text, - x: x, - y: y, - dy: textOpts.dy, - theta: theta, - level: textOpts.level, - width: textOpts.width, - height: textOpts.height - }); - - labelClipPathData.push(bBoxPts); -}; - -exports.drawLabels = function(labelGroup, labelData, gd, lineClip, labelClipPathData) { - var labels = labelGroup.selectAll('text') - .data(labelData, function(d) { - return d.text + ',' + d.x + ',' + d.y + ',' + d.theta; - }); - - labels.exit().remove(); - - labels.enter().append('text') - .attr({ - 'data-notex': 1, - 'text-anchor': 'middle' - }) - .each(function(d) { - var x = d.x + Math.sin(d.theta) * d.dy; - var y = d.y - Math.cos(d.theta) * d.dy; - d3.select(this) - .text(d.text) - .attr({ - x: x, - y: y, - transform: 'rotate(' + (180 * d.theta / Math.PI) + ' ' + x + ' ' + y + ')' - }) - .call(svgTextUtils.convertToTspans, gd); - }); - - if(labelClipPathData) { - var clipPath = ''; - for(var i = 0; i < labelClipPathData.length; i++) { - clipPath += 'M' + labelClipPathData[i].join('L') + 'Z'; - } - - var lineClipPath = Lib.ensureSingle(lineClip, 'path', ''); - lineClipPath.attr('d', clipPath); - } -}; - -function clipGaps(plotGroup, plotinfo, gd, cd0, perimeter) { - var clips = gd._fullLayout._clips; - var clipId = 'clip' + cd0.trace.uid; - - var clipPath = clips.selectAll('#' + clipId) - .data(cd0.trace.connectgaps ? [] : [0]); - clipPath.enter().append('clipPath') - .classed('contourclip', true) - .attr('id', clipId); - clipPath.exit().remove(); - - if(cd0.trace.connectgaps === false) { - var clipPathInfo = { - // fraction of the way from missing to present point - // to draw the boundary. - // if you make this 1 (or 1-epsilon) then a point in - // a sea of missing data will disappear entirely. - level: 0.9, - crossings: {}, - starts: [], - edgepaths: [], - paths: [], - xaxis: plotinfo.xaxis, - yaxis: plotinfo.yaxis, - x: cd0.x, - y: cd0.y, - // 0 = no data, 1 = data - z: makeClipMask(cd0), - smoothing: 0 - }; - - makeCrossings([clipPathInfo]); - findAllPaths([clipPathInfo]); - var fullpath = joinAllPaths(clipPathInfo, perimeter); - - var path = Lib.ensureSingle(clipPath, 'path', ''); - path.attr('d', fullpath); - } else clipId = null; - - Drawing.setClipUrl(plotGroup, clipId, gd); -} - -function makeClipMask(cd0) { - var empties = cd0.trace._emptypoints; - var z = []; - var m = cd0.z.length; - var n = cd0.z[0].length; - var i; - var row = []; - var emptyPoint; - - for(i = 0; i < n; i++) row.push(1); - for(i = 0; i < m; i++) z.push(row.slice()); - for(i = 0; i < empties.length; i++) { - emptyPoint = empties[i]; - z[emptyPoint[0]][emptyPoint[1]] = 0; - } - // save this mask to determine whether to show this data in hover - cd0.zmask = z; - return z; -} - -},{"../../components/drawing":614,"../../lib":719,"../../lib/svg_text_utils":743,"../../plots/cartesian/axes":767,"../../plots/cartesian/set_convert":785,"../heatmap/plot":1012,"./close_boundaries":944,"./constants":946,"./convert_to_constraints":950,"./empty_pathinfo":952,"./find_all_paths":954,"./make_crossings":959,"d3":163}],961:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var Lib = _dereq_('../../lib'); - -module.exports = function setContours(trace, vals) { - var contours = trace.contours; - - // check if we need to auto-choose contour levels - if(trace.autocontour) { - // N.B. do not try to use coloraxis cmin/cmax, - // these values here are meant to remain "per-trace" for now - var zmin = trace.zmin; - var zmax = trace.zmax; - if(trace.zauto || zmin === undefined) { - zmin = Lib.aggNums(Math.min, null, vals); - } - if(trace.zauto || zmax === undefined) { - zmax = Lib.aggNums(Math.max, null, vals); - } - - var dummyAx = autoContours(zmin, zmax, trace.ncontours); - contours.size = dummyAx.dtick; - contours.start = Axes.tickFirst(dummyAx); - dummyAx.range.reverse(); - contours.end = Axes.tickFirst(dummyAx); - - if(contours.start === zmin) contours.start += contours.size; - if(contours.end === zmax) contours.end -= contours.size; - - // if you set a small ncontours, *and* the ends are exactly on zmin/zmax - // there's an edge case where start > end now. Make sure there's at least - // one meaningful contour, put it midway between the crossed values - if(contours.start > contours.end) { - contours.start = contours.end = (contours.start + contours.end) / 2; - } - - // copy auto-contour info back to the source data. - // previously we copied the whole contours object back, but that had - // other info (coloring, showlines) that should be left to supplyDefaults - if(!trace._input.contours) trace._input.contours = {}; - Lib.extendFlat(trace._input.contours, { - start: contours.start, - end: contours.end, - size: contours.size - }); - trace._input.autocontour = true; - } else if(contours.type !== 'constraint') { - // sanity checks on manually-supplied start/end/size - var start = contours.start; - var end = contours.end; - var inputContours = trace._input.contours; - - if(start > end) { - contours.start = inputContours.start = end; - end = contours.end = inputContours.end = start; - start = contours.start; - } - - if(!(contours.size > 0)) { - var sizeOut; - if(start === end) sizeOut = 1; - else sizeOut = autoContours(start, end, trace.ncontours).dtick; - - inputContours.size = contours.size = sizeOut; - } - } -}; - - -/* - * autoContours: make a dummy axis object with dtick we can use - * as contours.size, and if needed we can use Axes.tickFirst - * with this axis object to calculate the start and end too - * - * start: the value to start the contours at - * end: the value to end at (must be > start) - * ncontours: max number of contours to make, like roughDTick - * - * returns: an axis object - */ -function autoContours(start, end, ncontours) { - var dummyAx = { - type: 'linear', - range: [start, end] - }; - - Axes.autoTicks( - dummyAx, - (end - start) / (ncontours || 15) - ); - - return dummyAx; -} - -},{"../../lib":719,"../../plots/cartesian/axes":767}],962:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Drawing = _dereq_('../../components/drawing'); -var heatmapStyle = _dereq_('../heatmap/style'); - -var makeColorMap = _dereq_('./make_color_map'); - - -module.exports = function style(gd) { - var contours = d3.select(gd).selectAll('g.contour'); - - contours.style('opacity', function(d) { - return d[0].trace.opacity; - }); - - contours.each(function(d) { - var c = d3.select(this); - var trace = d[0].trace; - var contours = trace.contours; - var line = trace.line; - var cs = contours.size || 1; - var start = contours.start; - - // for contourcarpet only - is this a constraint-type contour trace? - var isConstraintType = contours.type === 'constraint'; - var colorLines = !isConstraintType && contours.coloring === 'lines'; - var colorFills = !isConstraintType && contours.coloring === 'fill'; - - var colorMap = (colorLines || colorFills) ? makeColorMap(trace) : null; - - c.selectAll('g.contourlevel').each(function(d) { - d3.select(this).selectAll('path') - .call(Drawing.lineGroupStyle, - line.width, - colorLines ? colorMap(d.level) : line.color, - line.dash); - }); - - var labelFont = contours.labelfont; - c.selectAll('g.contourlabels text').each(function(d) { - Drawing.font(d3.select(this), { - family: labelFont.family, - size: labelFont.size, - color: labelFont.color || (colorLines ? colorMap(d.level) : line.color) - }); - }); - - if(isConstraintType) { - c.selectAll('g.contourfill path') - .style('fill', trace.fillcolor); - } else if(colorFills) { - var firstFill; - - c.selectAll('g.contourfill path') - .style('fill', function(d) { - if(firstFill === undefined) firstFill = d.level; - return colorMap(d.level + 0.5 * cs); - }); - - if(firstFill === undefined) firstFill = start; - - c.selectAll('g.contourbg path') - .style('fill', colorMap(firstFill - 0.5 * cs)); - } - }); - - heatmapStyle(gd); -}; - -},{"../../components/drawing":614,"../heatmap/style":1013,"./make_color_map":958,"d3":163}],963:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var handleLabelDefaults = _dereq_('./label_defaults'); - - -module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, layout, opts) { - var coloring = coerce('contours.coloring'); - - var showLines; - var lineColor = ''; - if(coloring === 'fill') showLines = coerce('contours.showlines'); - - if(showLines !== false) { - if(coloring !== 'lines') lineColor = coerce('line.color', '#000'); - coerce('line.width', 0.5); - coerce('line.dash'); - } - - if(coloring !== 'none') { - // plots/plots always coerces showlegend to true, but in this case - // we default to false and (by default) show a colorbar instead - if(traceIn.showlegend !== true) traceOut.showlegend = false; - traceOut._dfltShowLegend = false; - - colorscaleDefaults( - traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'} - ); - } - - coerce('line.smoothing'); - - handleLabelDefaults(coerce, layout, lineColor, opts); -}; - -},{"../../components/colorscale/defaults":603,"./label_defaults":957}],964:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var heatmapAttrs = _dereq_('../heatmap/attributes'); -var contourAttrs = _dereq_('../contour/attributes'); -var contourContourAttrs = contourAttrs.contours; -var scatterAttrs = _dereq_('../scatter/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var scatterLineAttrs = scatterAttrs.line; - -module.exports = extendFlat({ - carpet: { - valType: 'string', - - editType: 'calc', - - }, - z: heatmapAttrs.z, - a: heatmapAttrs.x, - a0: heatmapAttrs.x0, - da: heatmapAttrs.dx, - b: heatmapAttrs.y, - b0: heatmapAttrs.y0, - db: heatmapAttrs.dy, - text: heatmapAttrs.text, - hovertext: heatmapAttrs.hovertext, - transpose: heatmapAttrs.transpose, - atype: heatmapAttrs.xtype, - btype: heatmapAttrs.ytype, - - fillcolor: contourAttrs.fillcolor, - - autocontour: contourAttrs.autocontour, - ncontours: contourAttrs.ncontours, - - contours: { - type: contourContourAttrs.type, - start: contourContourAttrs.start, - end: contourContourAttrs.end, - size: contourContourAttrs.size, - coloring: { - // from contourAttrs.contours.coloring but no 'heatmap' option - valType: 'enumerated', - values: ['fill', 'lines', 'none'], - dflt: 'fill', - - editType: 'calc', - - }, - showlines: contourContourAttrs.showlines, - showlabels: contourContourAttrs.showlabels, - labelfont: contourContourAttrs.labelfont, - labelformat: contourContourAttrs.labelformat, - operation: contourContourAttrs.operation, - value: contourContourAttrs.value, - editType: 'calc', - impliedEdits: {'autocontour': false} - }, - - line: { - color: extendFlat({}, scatterLineAttrs.color, { - - }), - width: scatterLineAttrs.width, - dash: scatterLineAttrs.dash, - smoothing: extendFlat({}, scatterLineAttrs.smoothing, { - - }), - editType: 'plot' - }, - transforms: undefined -}, - - colorScaleAttrs('', { - cLetter: 'z', - autoColorDflt: false - }) -); - -},{"../../components/colorscale/attributes":600,"../../lib/extend":710,"../contour/attributes":942,"../heatmap/attributes":1001,"../scatter/attributes":1112}],965:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); -var Lib = _dereq_('../../lib'); - -var convertColumnData = _dereq_('../heatmap/convert_column_xyz'); -var clean2dArray = _dereq_('../heatmap/clean_2d_array'); -var interp2d = _dereq_('../heatmap/interp2d'); -var findEmpties = _dereq_('../heatmap/find_empties'); -var makeBoundArray = _dereq_('../heatmap/make_bound_array'); -var supplyDefaults = _dereq_('./defaults'); -var lookupCarpet = _dereq_('../carpet/lookup_carpetid'); -var setContours = _dereq_('../contour/set_contours'); - -// most is the same as heatmap calc, then adjust it -// though a few things inside heatmap calc still look for -// contour maps, because the makeBoundArray calls are too entangled -module.exports = function calc(gd, trace) { - var carpet = trace._carpetTrace = lookupCarpet(gd, trace); - if(!carpet || !carpet.visible || carpet.visible === 'legendonly') return; - - if(!trace.a || !trace.b) { - // Look up the original incoming carpet data: - var carpetdata = gd.data[carpet.index]; - - // Look up the incoming trace data, *except* perform a shallow - // copy so that we're not actually modifying it when we use it - // to supply defaults: - var tracedata = gd.data[trace.index]; - // var tracedata = extendFlat({}, gd.data[trace.index]); - - // If the data is not specified - if(!tracedata.a) tracedata.a = carpetdata.a; - if(!tracedata.b) tracedata.b = carpetdata.b; - - supplyDefaults(tracedata, trace, trace._defaultColor, gd._fullLayout); - } - - var cd = heatmappishCalc(gd, trace); - setContours(trace, trace._z); - - return cd; -}; - -function heatmappishCalc(gd, trace) { - // prepare the raw data - // run makeCalcdata on x and y even for heatmaps, in case of category mappings - var carpet = trace._carpetTrace; - var aax = carpet.aaxis; - var bax = carpet.baxis; - var a, - a0, - da, - b, - b0, - db, - z; - - // cancel minimum tick spacings (only applies to bars and boxes) - aax._minDtick = 0; - bax._minDtick = 0; - - if(Lib.isArray1D(trace.z)) convertColumnData(trace, aax, bax, 'a', 'b', ['z']); - a = trace._a = trace._a || trace.a; - b = trace._b = trace._b || trace.b; - - a = a ? aax.makeCalcdata(trace, '_a') : []; - b = b ? bax.makeCalcdata(trace, '_b') : []; - a0 = trace.a0 || 0; - da = trace.da || 1; - b0 = trace.b0 || 0; - db = trace.db || 1; - - z = trace._z = clean2dArray(trace._z || trace.z, trace.transpose); - - trace._emptypoints = findEmpties(z); - interp2d(z, trace._emptypoints); - - // create arrays of brick boundaries, to be used by autorange and heatmap.plot - var xlen = Lib.maxRowLength(z); - var xIn = trace.xtype === 'scaled' ? '' : a; - var xArray = makeBoundArray(trace, xIn, a0, da, xlen, aax); - var yIn = trace.ytype === 'scaled' ? '' : b; - var yArray = makeBoundArray(trace, yIn, b0, db, z.length, bax); - - var cd0 = { - a: xArray, - b: yArray, - z: z, - }; - - if(trace.contours.type === 'levels' && trace.contours.coloring !== 'none') { - // auto-z and autocolorscale if applicable - colorscaleCalc(gd, trace, { - vals: z, - containerStr: '', - cLetter: 'z' - }); - } - - return [cd0]; -} - -},{"../../components/colorscale/calc":601,"../../lib":719,"../carpet/lookup_carpetid":915,"../contour/set_contours":961,"../heatmap/clean_2d_array":1003,"../heatmap/convert_column_xyz":1005,"../heatmap/find_empties":1007,"../heatmap/interp2d":1010,"../heatmap/make_bound_array":1011,"./defaults":966}],966:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var handleXYZDefaults = _dereq_('../heatmap/xyz_defaults'); -var attributes = _dereq_('./attributes'); -var handleConstraintDefaults = _dereq_('../contour/constraint_defaults'); -var handleContoursDefaults = _dereq_('../contour/contours_defaults'); -var handleStyleDefaults = _dereq_('../contour/style_defaults'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - function coerce2(attr) { - return Lib.coerce2(traceIn, traceOut, attributes, attr); - } - - coerce('carpet'); - - // If either a or b is not present, then it's not a valid trace *unless* the carpet - // axis has the a or b values we're looking for. So if these are not found, just defer - // that decision until the calc step. - // - // NB: the calc step will modify the original data input by assigning whichever of - // a or b are missing. This is necessary because panning goes right from supplyDefaults - // to plot (skipping calc). That means on subsequent updates, this *will* need to be - // able to find a and b. - // - // The long-term proper fix is that this should perhaps use underscored attributes to - // at least modify the user input to a slightly lesser extent. Fully removing the - // input mutation is challenging. The underscore approach is not currently taken since - // it requires modification to all of the functions below that expect the coerced - // attribute name to match the property name -- except '_a' !== 'a' so that is not - // straightforward. - if(traceIn.a && traceIn.b) { - var len = handleXYZDefaults(traceIn, traceOut, coerce, layout, 'a', 'b'); - - if(!len) { - traceOut.visible = false; - return; - } - - coerce('text'); - var isConstraint = (coerce('contours.type') === 'constraint'); - - if(isConstraint) { - handleConstraintDefaults(traceIn, traceOut, coerce, layout, defaultColor, {hasHover: false}); - } else { - handleContoursDefaults(traceIn, traceOut, coerce, coerce2); - handleStyleDefaults(traceIn, traceOut, coerce, layout, {hasHover: false}); - } - } else { - traceOut._defaultColor = defaultColor; - traceOut._length = null; - } -}; - -},{"../../lib":719,"../contour/constraint_defaults":947,"../contour/contours_defaults":949,"../contour/style_defaults":963,"../heatmap/xyz_defaults":1015,"./attributes":964}],967:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../contour/colorbar'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - style: _dereq_('../contour/style'), - - moduleType: 'trace', - name: 'contourcarpet', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', 'carpet', 'contour', 'symbols', 'showLegend', 'hasLines', 'carpetDependent'], - meta: { - - - } -}; - -},{"../../plots/cartesian":778,"../contour/colorbar":945,"../contour/style":962,"./attributes":964,"./calc":965,"./defaults":966,"./plot":970}],968:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Drawing = _dereq_('../../components/drawing'); -var axisAlignedLine = _dereq_('../carpet/axis_aligned_line'); -var Lib = _dereq_('../../lib'); - -module.exports = function joinAllPaths(trace, pi, perimeter, ab2p, carpet, carpetcd, xa, ya) { - var i; - var fullpath = ''; - - var startsleft = pi.edgepaths.map(function(v, i) { return i; }); - var newloop = true; - var endpt, newendpt, cnt, nexti, possiblei, addpath; - - var atol = Math.abs(perimeter[0][0] - perimeter[2][0]) * 1e-4; - var btol = Math.abs(perimeter[0][1] - perimeter[2][1]) * 1e-4; - - function istop(pt) { return Math.abs(pt[1] - perimeter[0][1]) < btol; } - function isbottom(pt) { return Math.abs(pt[1] - perimeter[2][1]) < btol; } - function isleft(pt) { return Math.abs(pt[0] - perimeter[0][0]) < atol; } - function isright(pt) { return Math.abs(pt[0] - perimeter[2][0]) < atol; } - - function pathto(pt0, pt1) { - var i, j, segments, axis; - var path = ''; - - if((istop(pt0) && !isright(pt0)) || (isbottom(pt0) && !isleft(pt0))) { - axis = carpet.aaxis; - segments = axisAlignedLine(carpet, carpetcd, [pt0[0], pt1[0]], 0.5 * (pt0[1] + pt1[1])); - } else { - axis = carpet.baxis; - segments = axisAlignedLine(carpet, carpetcd, 0.5 * (pt0[0] + pt1[0]), [pt0[1], pt1[1]]); - } - - for(i = 1; i < segments.length; i++) { - path += axis.smoothing ? 'C' : 'L'; - for(j = 0; j < segments[i].length; j++) { - var pt = segments[i][j]; - path += [xa.c2p(pt[0]), ya.c2p(pt[1])] + ' '; - } - } - - return path; - } - - i = 0; - endpt = null; - while(startsleft.length) { - var startpt = pi.edgepaths[i][0]; - - if(endpt) { - fullpath += pathto(endpt, startpt); - } - - addpath = Drawing.smoothopen(pi.edgepaths[i].map(ab2p), pi.smoothing); - fullpath += newloop ? addpath : addpath.replace(/^M/, 'L'); - startsleft.splice(startsleft.indexOf(i), 1); - endpt = pi.edgepaths[i][pi.edgepaths[i].length - 1]; - nexti = -1; - - // now loop through sides, moving our endpoint until we find a new start - for(cnt = 0; cnt < 4; cnt++) { // just to prevent infinite loops - if(!endpt) { - Lib.log('Missing end?', i, pi); - break; - } - - if(istop(endpt) && !isright(endpt)) { - newendpt = perimeter[1]; // left top ---> right top - } else if(isleft(endpt)) { - newendpt = perimeter[0]; // left bottom ---> left top - } else if(isbottom(endpt)) { - newendpt = perimeter[3]; // right bottom - } else if(isright(endpt)) { - newendpt = perimeter[2]; // left bottom - } - - for(possiblei = 0; possiblei < pi.edgepaths.length; possiblei++) { - var ptNew = pi.edgepaths[possiblei][0]; - // is ptNew on the (horz. or vert.) segment from endpt to newendpt? - if(Math.abs(endpt[0] - newendpt[0]) < atol) { - if(Math.abs(endpt[0] - ptNew[0]) < atol && (ptNew[1] - endpt[1]) * (newendpt[1] - ptNew[1]) >= 0) { - newendpt = ptNew; - nexti = possiblei; - } - } else if(Math.abs(endpt[1] - newendpt[1]) < btol) { - if(Math.abs(endpt[1] - ptNew[1]) < btol && (ptNew[0] - endpt[0]) * (newendpt[0] - ptNew[0]) >= 0) { - newendpt = ptNew; - nexti = possiblei; - } - } else { - Lib.log('endpt to newendpt is not vert. or horz.', endpt, newendpt, ptNew); - } - } - - if(nexti >= 0) break; - fullpath += pathto(endpt, newendpt); - endpt = newendpt; - } - - if(nexti === pi.edgepaths.length) { - Lib.log('unclosed perimeter path'); - break; - } - - i = nexti; - - // if we closed back on a loop we already included, - // close it and start a new loop - newloop = (startsleft.indexOf(i) === -1); - if(newloop) { - i = startsleft[0]; - fullpath += pathto(endpt, newendpt) + 'Z'; - endpt = null; - } - } - - // finally add the interior paths - for(i = 0; i < pi.paths.length; i++) { - fullpath += Drawing.smoothclosed(pi.paths[i].map(ab2p), pi.smoothing); - } - - return fullpath; -}; - -},{"../../components/drawing":614,"../../lib":719,"../carpet/axis_aligned_line":899}],969:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function mapPathinfo(pathinfo, map) { - var i, j, k, pi, pedgepaths, ppaths, pedgepath, ppath, path; - - for(i = 0; i < pathinfo.length; i++) { - pi = pathinfo[i]; - pedgepaths = pi.pedgepaths = []; - ppaths = pi.ppaths = []; - for(j = 0; j < pi.edgepaths.length; j++) { - path = pi.edgepaths[j]; - pedgepath = []; - for(k = 0; k < path.length; k++) { - pedgepath[k] = map(path[k]); - } - pedgepaths.push(pedgepath); - } - for(j = 0; j < pi.paths.length; j++) { - path = pi.paths[j]; - ppath = []; - for(k = 0; k < path.length; k++) { - ppath[k] = map(path[k]); - } - ppaths.push(ppath); - } - } -}; - -},{}],970:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var map1dArray = _dereq_('../carpet/map_1d_array'); -var makepath = _dereq_('../carpet/makepath'); -var Drawing = _dereq_('../../components/drawing'); -var Lib = _dereq_('../../lib'); - -var makeCrossings = _dereq_('../contour/make_crossings'); -var findAllPaths = _dereq_('../contour/find_all_paths'); -var contourPlot = _dereq_('../contour/plot'); -var constants = _dereq_('../contour/constants'); -var convertToConstraints = _dereq_('../contour/convert_to_constraints'); -var joinAllPaths = _dereq_('./join_all_paths'); -var emptyPathinfo = _dereq_('../contour/empty_pathinfo'); -var mapPathinfo = _dereq_('./map_pathinfo'); -var lookupCarpet = _dereq_('../carpet/lookup_carpetid'); -var closeBoundaries = _dereq_('../contour/close_boundaries'); - -module.exports = function plot(gd, plotinfo, cdcontours, contourcarpetLayer) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - Lib.makeTraceGroups(contourcarpetLayer, cdcontours, 'contour').each(function(cd) { - var plotGroup = d3.select(this); - var cd0 = cd[0]; - var trace = cd0.trace; - - var carpet = trace._carpetTrace = lookupCarpet(gd, trace); - var carpetcd = gd.calcdata[carpet.index][0]; - - if(!carpet.visible || carpet.visible === 'legendonly') return; - - var a = cd0.a; - var b = cd0.b; - var contours = trace.contours; - var pathinfo = emptyPathinfo(contours, plotinfo, cd0); - var isConstraint = contours.type === 'constraint'; - var operation = contours._operation; - var coloring = isConstraint ? (operation === '=' ? 'lines' : 'fill') : contours.coloring; - - // Map [a, b] (data) --> [i, j] (pixels) - function ab2p(ab) { - var pt = carpet.ab2xy(ab[0], ab[1], true); - return [xa.c2p(pt[0]), ya.c2p(pt[1])]; - } - - // Define the perimeter in a/b coordinates: - var perimeter = [ - [a[0], b[b.length - 1]], - [a[a.length - 1], b[b.length - 1]], - [a[a.length - 1], b[0]], - [a[0], b[0]] - ]; - - // Extract the contour levels: - makeCrossings(pathinfo); - var atol = (a[a.length - 1] - a[0]) * 1e-8; - var btol = (b[b.length - 1] - b[0]) * 1e-8; - findAllPaths(pathinfo, atol, btol); - - // Constraints might need to be draw inverted, which is not something contours - // handle by default since they're assumed fully opaque so that they can be - // drawn overlapping. This function flips the paths as necessary so that they're - // drawn correctly. - // - // TODO: Perhaps this should be generalized and *all* paths should be drawn as - // closed regions so that translucent contour levels would be valid. - // See: https://github.com/plotly/plotly.js/issues/1356 - var fillPathinfo = pathinfo; - if(contours.type === 'constraint') { - fillPathinfo = convertToConstraints(pathinfo, operation); - closeBoundaries(fillPathinfo, operation, perimeter, trace); - } - - // Map the paths in a/b coordinates to pixel coordinates: - mapPathinfo(pathinfo, ab2p); - - // draw everything - - // Compute the boundary path - var seg, xp, yp, i; - var segs = []; - for(i = carpetcd.clipsegments.length - 1; i >= 0; i--) { - seg = carpetcd.clipsegments[i]; - xp = map1dArray([], seg.x, xa.c2p); - yp = map1dArray([], seg.y, ya.c2p); - xp.reverse(); - yp.reverse(); - segs.push(makepath(xp, yp, seg.bicubic)); - } - - var boundaryPath = 'M' + segs.join('L') + 'Z'; - - // Draw the baseline background fill that fills in the space behind any other - // contour levels: - makeBackground(plotGroup, carpetcd.clipsegments, xa, ya, isConstraint, coloring); - - // Draw the specific contour fills. As a simplification, they're assumed to be - // fully opaque so that it's easy to draw them simply overlapping. The alternative - // would be to flip adjacent paths and draw closed paths for each level instead. - makeFills(trace, plotGroup, xa, ya, fillPathinfo, perimeter, ab2p, carpet, carpetcd, coloring, boundaryPath); - - // Draw contour lines: - makeLinesAndLabels(plotGroup, pathinfo, gd, cd0, contours, plotinfo, carpet); - - // Clip the boundary of the plot - Drawing.setClipUrl(plotGroup, carpet._clipPathId, gd); - }); -}; - -function makeLinesAndLabels(plotgroup, pathinfo, gd, cd0, contours, plotinfo, carpet) { - var lineContainer = Lib.ensureSingle(plotgroup, 'g', 'contourlines'); - var showLines = contours.showlines !== false; - var showLabels = contours.showlabels; - var clipLinesForLabels = showLines && showLabels; - - // Even if we're not going to show lines, we need to create them - // if we're showing labels, because the fill paths include the perimeter - // so can't be used to position the labels correctly. - // In this case we'll remove the lines after making the labels. - var linegroup = contourPlot.createLines(lineContainer, showLines || showLabels, pathinfo); - - var lineClip = contourPlot.createLineClip(lineContainer, clipLinesForLabels, gd, cd0.trace.uid); - - var labelGroup = plotgroup.selectAll('g.contourlabels') - .data(showLabels ? [0] : []); - - labelGroup.exit().remove(); - - labelGroup.enter().append('g') - .classed('contourlabels', true); - - if(showLabels) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - var xLen = xa._length; - var yLen = ya._length; - // for simplicity use the xy box for label clipping outline. - var labelClipPathData = [[ - [0, 0], - [xLen, 0], - [xLen, yLen], - [0, yLen] - ]]; - - - var labelData = []; - - // invalidate the getTextLocation cache in case paths changed - Lib.clearLocationCache(); - - var contourFormat = contourPlot.labelFormatter(contours, cd0.t.cb, gd._fullLayout); - - var dummyText = Drawing.tester.append('text') - .attr('data-notex', 1) - .call(Drawing.font, contours.labelfont); - - // use `bounds` only to keep labels away from the x/y boundaries - // `constrainToCarpet` below ensures labels don't go off the - // carpet edges - var bounds = { - left: 0, - right: xLen, - center: xLen / 2, - top: 0, - bottom: yLen, - middle: yLen / 2 - }; - - var plotDiagonal = Math.sqrt(xLen * xLen + yLen * yLen); - - // the path length to use to scale the number of labels to draw: - var normLength = constants.LABELDISTANCE * plotDiagonal / - Math.max(1, pathinfo.length / constants.LABELINCREASE); - - linegroup.each(function(d) { - var textOpts = contourPlot.calcTextOpts(d.level, contourFormat, dummyText, gd); - - d3.select(this).selectAll('path').each(function(pathData) { - var path = this; - var pathBounds = Lib.getVisibleSegment(path, bounds, textOpts.height / 2); - if(!pathBounds) return; - - constrainToCarpet(path, pathData, d, pathBounds, carpet, textOpts.height); - - if(pathBounds.len < (textOpts.width + textOpts.height) * constants.LABELMIN) return; - - var maxLabels = Math.min(Math.ceil(pathBounds.len / normLength), - constants.LABELMAX); - - for(var i = 0; i < maxLabels; i++) { - var loc = contourPlot.findBestTextLocation(path, pathBounds, textOpts, - labelData, bounds); - - if(!loc) break; - - contourPlot.addLabelData(loc, textOpts, labelData, labelClipPathData); - } - }); - }); - - dummyText.remove(); - - contourPlot.drawLabels(labelGroup, labelData, gd, lineClip, - clipLinesForLabels ? labelClipPathData : null); - } - - if(showLabels && !showLines) linegroup.remove(); -} - -// figure out if this path goes off the edge of the carpet -// and shorten the part we call visible to keep labels away from the edge -function constrainToCarpet(path, pathData, levelData, pathBounds, carpet, textHeight) { - var pathABData; - for(var i = 0; i < levelData.pedgepaths.length; i++) { - if(pathData === levelData.pedgepaths[i]) { - pathABData = levelData.edgepaths[i]; - } - } - if(!pathABData) return; - - var aMin = carpet.a[0]; - var aMax = carpet.a[carpet.a.length - 1]; - var bMin = carpet.b[0]; - var bMax = carpet.b[carpet.b.length - 1]; - - function getOffset(abPt, pathVector) { - var offset = 0; - var edgeVector; - var dAB = 0.1; - if(Math.abs(abPt[0] - aMin) < dAB || Math.abs(abPt[0] - aMax) < dAB) { - edgeVector = normalizeVector(carpet.dxydb_rough(abPt[0], abPt[1], dAB)); - offset = Math.max(offset, textHeight * vectorTan(pathVector, edgeVector) / 2); - } - - if(Math.abs(abPt[1] - bMin) < dAB || Math.abs(abPt[1] - bMax) < dAB) { - edgeVector = normalizeVector(carpet.dxyda_rough(abPt[0], abPt[1], dAB)); - offset = Math.max(offset, textHeight * vectorTan(pathVector, edgeVector) / 2); - } - return offset; - } - - var startVector = getUnitVector(path, 0, 1); - var endVector = getUnitVector(path, pathBounds.total, pathBounds.total - 1); - var minStart = getOffset(pathABData[0], startVector); - var maxEnd = pathBounds.total - getOffset(pathABData[pathABData.length - 1], endVector); - - if(pathBounds.min < minStart) pathBounds.min = minStart; - if(pathBounds.max > maxEnd) pathBounds.max = maxEnd; - - pathBounds.len = pathBounds.max - pathBounds.min; -} - -function getUnitVector(path, p0, p1) { - var pt0 = path.getPointAtLength(p0); - var pt1 = path.getPointAtLength(p1); - var dx = pt1.x - pt0.x; - var dy = pt1.y - pt0.y; - var len = Math.sqrt(dx * dx + dy * dy); - return [dx / len, dy / len]; -} - -function normalizeVector(v) { - var len = Math.sqrt(v[0] * v[0] + v[1] * v[1]); - return [v[0] / len, v[1] / len]; -} - -function vectorTan(v0, v1) { - var cos = Math.abs(v0[0] * v1[0] + v0[1] * v1[1]); - var sin = Math.sqrt(1 - cos * cos); - return sin / cos; -} - -function makeBackground(plotgroup, clipsegments, xaxis, yaxis, isConstraint, coloring) { - var seg, xp, yp, i; - var bggroup = Lib.ensureSingle(plotgroup, 'g', 'contourbg'); - - var bgfill = bggroup.selectAll('path') - .data((coloring === 'fill' && !isConstraint) ? [0] : []); - bgfill.enter().append('path'); - bgfill.exit().remove(); - - var segs = []; - for(i = 0; i < clipsegments.length; i++) { - seg = clipsegments[i]; - xp = map1dArray([], seg.x, xaxis.c2p); - yp = map1dArray([], seg.y, yaxis.c2p); - segs.push(makepath(xp, yp, seg.bicubic)); - } - - bgfill - .attr('d', 'M' + segs.join('L') + 'Z') - .style('stroke', 'none'); -} - -function makeFills(trace, plotgroup, xa, ya, pathinfo, perimeter, ab2p, carpet, carpetcd, coloring, boundaryPath) { - var fillgroup = Lib.ensureSingle(plotgroup, 'g', 'contourfill'); - - var fillitems = fillgroup.selectAll('path') - .data(coloring === 'fill' ? pathinfo : []); - fillitems.enter().append('path'); - fillitems.exit().remove(); - fillitems.each(function(pi) { - // join all paths for this level together into a single path - // first follow clockwise around the perimeter to close any open paths - // if the whole perimeter is above this level, start with a path - // enclosing the whole thing. With all that, the parity should mean - // that we always fill everything above the contour, nothing below - var fullpath = joinAllPaths(trace, pi, perimeter, ab2p, carpet, carpetcd, xa, ya); - - if(pi.prefixBoundary) { - fullpath = boundaryPath + fullpath; - } - - if(!fullpath) { - d3.select(this).remove(); - } else { - d3.select(this) - .attr('d', fullpath) - .style('stroke', 'none'); - } - }); -} - -},{"../../components/drawing":614,"../../lib":719,"../carpet/lookup_carpetid":915,"../carpet/makepath":916,"../carpet/map_1d_array":917,"../contour/close_boundaries":944,"../contour/constants":946,"../contour/convert_to_constraints":950,"../contour/empty_pathinfo":952,"../contour/find_all_paths":954,"../contour/make_crossings":959,"../contour/plot":960,"./join_all_paths":968,"./map_pathinfo":969,"d3":163}],971:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var plotAttrs = _dereq_('../../plots/attributes'); -var scatterMapboxAttrs = _dereq_('../scattermapbox/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -/* - * - https://docs.mapbox.com/help/tutorials/make-a-heatmap-with-mapbox-gl-js/ - * - https://docs.mapbox.com/mapbox-gl-js/example/heatmap-layer/ - * - https://docs.mapbox.com/mapbox-gl-js/style-spec/#layers-heatmap - * - https://blog.mapbox.com/introducing-heatmaps-in-mapbox-gl-js-71355ada9e6c - * - * Gotchas: - * - https://github.com/mapbox/mapbox-gl-js/issues/6463 - * - https://github.com/mapbox/mapbox-gl-js/issues/6112 - */ - -/* - * - * In mathematical terms, Mapbox GL heatmaps are a bivariate (2D) kernel density - * estimation with a Gaussian kernel. It means that each data point has an area - * of “influence” around it (called a kernel) where the numerical value of - * influence (which we call density) decreases as you go further from the point. - * If we sum density values of all points in every pixel of the screen, we get a - * combined density value which we then map to a heatmap color. - * - */ - -module.exports = extendFlat({ - lon: scatterMapboxAttrs.lon, - lat: scatterMapboxAttrs.lat, - - z: { - valType: 'data_array', - editType: 'calc', - - }, - - radius: { - valType: 'number', - - editType: 'plot', - arrayOk: true, - min: 1, - dflt: 30, - - }, - - below: { - valType: 'string', - - editType: 'plot', - - }, - - text: scatterMapboxAttrs.text, - hovertext: scatterMapboxAttrs.hovertext, - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['lon', 'lat', 'z', 'text', 'name'] - }), - hovertemplate: hovertemplateAttrs() -}, - colorScaleAttrs('', { - cLetter: 'z', - editTypeOverride: 'calc' - }) -); - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../scattermapbox/attributes":1171}],972:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); -var _ = _dereq_('../../lib')._; - -module.exports = function calc(gd, trace) { - var len = trace._length; - var calcTrace = new Array(len); - var z = trace.z; - var hasZ = isArrayOrTypedArray(z) && z.length; - - for(var i = 0; i < len; i++) { - var cdi = calcTrace[i] = {}; - - var lon = trace.lon[i]; - var lat = trace.lat[i]; - - cdi.lonlat = isNumeric(lon) && isNumeric(lat) ? - [+lon, +lat] : - [BADNUM, BADNUM]; - - if(hasZ) { - var zi = z[i]; - cdi.z = isNumeric(zi) ? zi : BADNUM; - } - } - - colorscaleCalc(gd, trace, { - vals: hasZ ? z : [0, 1], - containerStr: '', - cLetter: 'z' - }); - - if(len) { - calcTrace[0].t = { - labels: { - lat: _(gd, 'lat:') + ' ', - lon: _(gd, 'lon:') + ' ' - } - }; - } - - return calcTrace; -}; - -},{"../../components/colorscale/calc":601,"../../constants/numerical":695,"../../lib":719,"fast-isnumeric":225}],973:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); -var Colorscale = _dereq_('../../components/colorscale'); - -var BADNUM = _dereq_('../../constants/numerical').BADNUM; -var makeBlank = _dereq_('../../lib/geojson_utils').makeBlank; - -module.exports = function convert(calcTrace) { - var trace = calcTrace[0].trace; - var isVisible = (trace.visible === true && trace._length !== 0); - - var heatmap = { - layout: {visibility: 'none'}, - paint: {} - }; - - var opts = trace._opts = { - heatmap: heatmap, - geojson: makeBlank() - }; - - // early return if not visible or placeholder - if(!isVisible) return opts; - - var features = []; - var i; - - var z = trace.z; - var radius = trace.radius; - var hasZ = Lib.isArrayOrTypedArray(z) && z.length; - var hasArrayRadius = Lib.isArrayOrTypedArray(radius); - - for(i = 0; i < calcTrace.length; i++) { - var cdi = calcTrace[i]; - var lonlat = cdi.lonlat; - - if(lonlat[0] !== BADNUM) { - var props = {}; - - if(hasZ) { - var zi = cdi.z; - props.z = zi !== BADNUM ? zi : 0; - } - if(hasArrayRadius) { - props.r = (isNumeric(radius[i]) && radius[i] > 0) ? +radius[i] : 0; - } - - features.push({ - type: 'Feature', - geometry: {type: 'Point', coordinates: lonlat}, - properties: props - }); - } - } - - var cOpts = Colorscale.extractOpts(trace); - var scl = cOpts.reversescale ? - Colorscale.flipScale(cOpts.colorscale) : - cOpts.colorscale; - - // Add alpha channel to first colorscale step. - // If not, we would essentially color the entire map. - // See https://docs.mapbox.com/mapbox-gl-js/example/heatmap-layer/ - var scl01 = scl[0][1]; - var color0 = Color.opacity(scl01) < 1 ? scl01 : Color.addOpacity(scl01, 0); - - var heatmapColor = [ - 'interpolate', ['linear'], - ['heatmap-density'], - 0, color0 - ]; - for(i = 1; i < scl.length; i++) { - heatmapColor.push(scl[i][0], scl[i][1]); - } - - // Those "weights" have to be in [0, 1], we can do this either: - // - as here using a mapbox-gl expression - // - or, scale the 'z' property in the feature loop - var zExp = [ - 'interpolate', ['linear'], - ['get', 'z'], - cOpts.min, 0, - cOpts.max, 1 - ]; - - Lib.extendFlat(opts.heatmap.paint, { - 'heatmap-weight': hasZ ? zExp : 1 / (cOpts.max - cOpts.min), - - 'heatmap-color': heatmapColor, - - 'heatmap-radius': hasArrayRadius ? - {type: 'identity', property: 'r'} : - trace.radius, - - 'heatmap-opacity': trace.opacity - }); - - opts.geojson = {type: 'FeatureCollection', features: features}; - opts.heatmap.layout.visibility = 'visible'; - - return opts; -}; - -},{"../../components/color":593,"../../components/colorscale":605,"../../constants/numerical":695,"../../lib":719,"../../lib/geojson_utils":714,"fast-isnumeric":225}],974:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var lon = coerce('lon') || []; - var lat = coerce('lat') || []; - - var len = Math.min(lon.length, lat.length); - if(!len) { - traceOut.visible = false; - return; - } - - traceOut._length = len; - - coerce('z'); - coerce('radius'); - coerce('below'); - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}); -}; - -},{"../../components/colorscale/defaults":603,"../../lib":719,"./attributes":971}],975:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function eventData(out, pt) { - out.lon = pt.lon; - out.lat = pt.lat; - out.z = pt.z; - return out; -}; - -},{}],976:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var scatterMapboxHoverPoints = _dereq_('../scattermapbox/hover'); - -module.exports = function hoverPoints(pointData, xval, yval) { - var pts = scatterMapboxHoverPoints(pointData, xval, yval); - if(!pts) return; - - var newPointData = pts[0]; - var cd = newPointData.cd; - var trace = cd[0].trace; - var di = cd[newPointData.index]; - - // let Fx.hover pick the color - delete newPointData.color; - - if('z' in di) { - var ax = newPointData.subplot.mockAxis; - newPointData.z = di.z; - newPointData.zLabel = Axes.tickText(ax, ax.c2l(di.z), 'hover').text; - } - - newPointData.extraText = getExtraText(trace, di, cd[0].t.labels); - - return [newPointData]; -}; - -function getExtraText(trace, di, labels) { - if(trace.hovertemplate) return; - - var hoverinfo = di.hi || trace.hoverinfo; - var parts = hoverinfo.split('+'); - var isAll = parts.indexOf('all') !== -1; - var hasLon = parts.indexOf('lon') !== -1; - var hasLat = parts.indexOf('lat') !== -1; - var lonlat = di.lonlat; - var text = []; - - function format(v) { - return v + '\u00B0'; - } - - if(isAll || (hasLon && hasLat)) { - text.push('(' + format(lonlat[0]) + ', ' + format(lonlat[1]) + ')'); - } else if(hasLon) { - text.push(labels.lon + format(lonlat[0])); - } else if(hasLat) { - text.push(labels.lat + format(lonlat[1])); - } - - if(isAll || parts.indexOf('text') !== -1) { - Lib.fillText(di, trace, text); - } - - return text.join('
'); -} - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../scattermapbox/hover":1175}],977:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../heatmap/colorbar'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - hoverPoints: _dereq_('./hover'), - eventData: _dereq_('./event_data'), - - getBelow: function(trace, subplot) { - var mapLayers = subplot.getMapLayers(); - - // find first layer with `type: 'symbol'`, - // that is not a plotly layer - for(var i = 0; i < mapLayers.length; i++) { - var layer = mapLayers[i]; - var layerId = layer.id; - if(layer.type === 'symbol' && - typeof layerId === 'string' && layerId.indexOf('plotly-') === -1 - ) { - return layerId; - } - } - }, - - moduleType: 'trace', - name: 'densitymapbox', - basePlotModule: _dereq_('../../plots/mapbox'), - categories: ['mapbox', 'gl'], - meta: { - hr_name: 'density_mapbox', - - } -}; - -},{"../../plots/mapbox":822,"../heatmap/colorbar":1004,"./attributes":971,"./calc":972,"./defaults":974,"./event_data":975,"./hover":976,"./plot":978}],978:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var convert = _dereq_('./convert'); -var LAYER_PREFIX = _dereq_('../../plots/mapbox/constants').traceLayerPrefix; - -function DensityMapbox(subplot, uid) { - this.subplot = subplot; - this.uid = uid; - - this.sourceId = 'source-' + uid; - - this.layerList = [ - ['heatmap', LAYER_PREFIX + uid + '-heatmap'] - ]; - - // previous 'below' value, - // need this to update it properly - this.below = null; -} - -var proto = DensityMapbox.prototype; - -proto.update = function(calcTrace) { - var subplot = this.subplot; - var layerList = this.layerList; - var optsAll = convert(calcTrace); - var below = subplot.belowLookup['trace-' + this.uid]; - - subplot.map - .getSource(this.sourceId) - .setData(optsAll.geojson); - - if(below !== this.below) { - this._removeLayers(); - this._addLayers(optsAll, below); - this.below = below; - } - - for(var i = 0; i < layerList.length; i++) { - var item = layerList[i]; - var k = item[0]; - var id = item[1]; - var opts = optsAll[k]; - - subplot.setOptions(id, 'setLayoutProperty', opts.layout); - - if(opts.layout.visibility === 'visible') { - subplot.setOptions(id, 'setPaintProperty', opts.paint); - } - } -}; - -proto._addLayers = function(optsAll, below) { - var subplot = this.subplot; - var layerList = this.layerList; - var sourceId = this.sourceId; - - for(var i = 0; i < layerList.length; i++) { - var item = layerList[i]; - var k = item[0]; - var opts = optsAll[k]; - - subplot.addLayer({ - type: k, - id: item[1], - source: sourceId, - layout: opts.layout, - paint: opts.paint - }, below); - } -}; - -proto._removeLayers = function() { - var map = this.subplot.map; - var layerList = this.layerList; - - for(var i = layerList.length - 1; i >= 0; i--) { - map.removeLayer(layerList[i][1]); - } -}; - -proto.dispose = function() { - var map = this.subplot.map; - this._removeLayers(); - map.removeSource(this.sourceId); -}; - -module.exports = function createDensityMapbox(subplot, calcTrace) { - var trace = calcTrace[0].trace; - var densityMapbox = new DensityMapbox(subplot, trace.uid); - var sourceId = densityMapbox.sourceId; - var optsAll = convert(calcTrace); - var below = densityMapbox.below = subplot.belowLookup['trace-' + trace.uid]; - - subplot.map.addSource(sourceId, { - type: 'geojson', - data: optsAll.geojson - }); - - densityMapbox._addLayers(optsAll, below); - - return densityMapbox; -}; - -},{"../../plots/mapbox/constants":820,"./convert":973}],979:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -// arrayOk attributes, merge them into calcdata array -module.exports = function arraysToCalcdata(cd, trace) { - for(var i = 0; i < cd.length; i++) cd[i].i = i; - - Lib.mergeArray(trace.text, cd, 'tx'); - Lib.mergeArray(trace.hovertext, cd, 'htx'); - - var marker = trace.marker; - if(marker) { - Lib.mergeArray(marker.opacity, cd, 'mo'); - Lib.mergeArray(marker.color, cd, 'mc'); - - var markerLine = marker.line; - if(markerLine) { - Lib.mergeArray(markerLine.color, cd, 'mlc'); - Lib.mergeArrayCastPositive(markerLine.width, cd, 'mlw'); - } - } -}; - -},{"../../lib":719}],980:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var barAttrs = _dereq_('../bar/attributes'); -var lineAttrs = _dereq_('../scatter/attributes').line; -var plotAttrs = _dereq_('../../plots/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var constants = _dereq_('./constants'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var Color = _dereq_('../../components/color'); - -module.exports = { - x: barAttrs.x, - x0: barAttrs.x0, - dx: barAttrs.dx, - y: barAttrs.y, - y0: barAttrs.y0, - dy: barAttrs.dy, - - hovertext: barAttrs.hovertext, - hovertemplate: hovertemplateAttrs({}, { - keys: constants.eventDataKeys - }), - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['name', 'x', 'y', 'text', 'percent initial', 'percent previous', 'percent total'] - }), - - textinfo: { - valType: 'flaglist', - flags: ['label', 'text', 'percent initial', 'percent previous', 'percent total', 'value'], - extras: ['none'], - - editType: 'plot', - arrayOk: false, - - }, - - text: barAttrs.text, - textposition: extendFlat({}, barAttrs.textposition, {dflt: 'auto'}), - insidetextanchor: extendFlat({}, barAttrs.insidetextanchor, {dflt: 'middle'}), - textangle: extendFlat({}, barAttrs.textangle, {dflt: 0}), - textfont: barAttrs.textfont, - insidetextfont: barAttrs.insidetextfont, - outsidetextfont: barAttrs.outsidetextfont, - constraintext: barAttrs.constraintext, - cliponaxis: barAttrs.cliponaxis, - - orientation: extendFlat({}, barAttrs.orientation, { - - }), - - offset: extendFlat({}, barAttrs.offset, {arrayOk: false}), - width: extendFlat({}, barAttrs.width, {arrayOk: false}), - - marker: barAttrs.marker, - - connector: { - fillcolor: { - valType: 'color', - - editType: 'style', - - }, - line: { - color: extendFlat({}, lineAttrs.color, {dflt: Color.defaultLine}), - width: extendFlat({}, lineAttrs.width, { - dflt: 0, - editType: 'plot', - }), - dash: lineAttrs.dash, - editType: 'style' - }, - visible: { - valType: 'boolean', - dflt: true, - - editType: 'plot', - - }, - editType: 'plot' - }, - - offsetgroup: barAttrs.offsetgroup, - alignmentgroup: barAttrs.alignmentgroup -}; - -},{"../../components/color":593,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../bar/attributes":857,"../scatter/attributes":1112,"./constants":982}],981:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var arraysToCalcdata = _dereq_('./arrays_to_calcdata'); -var calcSelection = _dereq_('../scatter/calc_selection'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -module.exports = function calc(gd, trace) { - var xa = Axes.getFromId(gd, trace.xaxis || 'x'); - var ya = Axes.getFromId(gd, trace.yaxis || 'y'); - var size, pos, i, cdi; - - if(trace.orientation === 'h') { - size = xa.makeCalcdata(trace, 'x'); - pos = ya.makeCalcdata(trace, 'y'); - } else { - size = ya.makeCalcdata(trace, 'y'); - pos = xa.makeCalcdata(trace, 'x'); - } - - // create the "calculated data" to plot - var serieslen = Math.min(pos.length, size.length); - var cd = new Array(serieslen); - - // Unlike other bar-like traces funnels do not support base attribute. - // bases for funnels are computed internally in a way that - // the mid-point of each bar are located on the axis line. - trace._base = []; - - // set position and size - for(i = 0; i < serieslen; i++) { - // treat negative values as bad numbers - if(size[i] < 0) size[i] = BADNUM; - - var connectToNext = false; - if(size[i] !== BADNUM) { - if(i + 1 < serieslen && size[i + 1] !== BADNUM) { - connectToNext = true; - } - } - - cdi = cd[i] = { - p: pos[i], - s: size[i], - cNext: connectToNext - }; - - trace._base[i] = -0.5 * cdi.s; - - if(trace.ids) { - cdi.id = String(trace.ids[i]); - } - - // calculate total values - if(i === 0) cd[0].vTotal = 0; - cd[0].vTotal += fixNum(cdi.s); - - // ratio from initial value - cdi.begR = fixNum(cdi.s) / fixNum(cd[0].s); - } - - var prevGoodNum; - for(i = 0; i < serieslen; i++) { - cdi = cd[i]; - if(cdi.s === BADNUM) continue; - - // ratio of total value - cdi.sumR = cdi.s / cd[0].vTotal; - - // ratio of previous (good) value - cdi.difR = (prevGoodNum !== undefined) ? cdi.s / prevGoodNum : 1; - - prevGoodNum = cdi.s; - } - - arraysToCalcdata(cd, trace); - calcSelection(cd, trace); - - return cd; -}; - -function fixNum(a) { - return (a === BADNUM) ? 0 : a; -} - -},{"../../constants/numerical":695,"../../plots/cartesian/axes":767,"../scatter/calc_selection":1114,"./arrays_to_calcdata":979}],982:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - eventDataKeys: [ - 'percentInitial', - 'percentPrevious', - 'percentTotal' - ] -}; - -},{}],983:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var setGroupPositions = _dereq_('../bar/cross_trace_calc').setGroupPositions; - -module.exports = function crossTraceCalc(gd, plotinfo) { - var fullLayout = gd._fullLayout; - var fullData = gd._fullData; - var calcdata = gd.calcdata; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - var funnels = []; - var funnelsVert = []; - var funnelsHorz = []; - var cd, i; - - for(i = 0; i < fullData.length; i++) { - var fullTrace = fullData[i]; - var isHorizontal = (fullTrace.orientation === 'h'); - - if( - fullTrace.visible === true && - fullTrace.xaxis === xa._id && - fullTrace.yaxis === ya._id && - fullTrace.type === 'funnel' - ) { - cd = calcdata[i]; - - if(isHorizontal) { - funnelsHorz.push(cd); - } else { - funnelsVert.push(cd); - } - - funnels.push(cd); - } - } - - var opts = { - mode: fullLayout.funnelmode, - norm: fullLayout.funnelnorm, - gap: fullLayout.funnelgap, - groupgap: fullLayout.funnelgroupgap - }; - - setGroupPositions(gd, xa, ya, funnelsVert, opts); - setGroupPositions(gd, ya, xa, funnelsHorz, opts); - - for(i = 0; i < funnels.length; i++) { - cd = funnels[i]; - - for(var j = 0; j < cd.length; j++) { - if(j + 1 < cd.length) { - cd[j].nextP0 = cd[j + 1].p0; - cd[j].nextS0 = cd[j + 1].s0; - - cd[j].nextP1 = cd[j + 1].p1; - cd[j].nextS1 = cd[j + 1].s1; - } - } - } -}; - -},{"../bar/cross_trace_calc":860}],984:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var handleGroupingDefaults = _dereq_('../bar/defaults').handleGroupingDefaults; -var handleText = _dereq_('../bar/defaults').handleText; -var handleXYDefaults = _dereq_('../scatter/xy_defaults'); -var attributes = _dereq_('./attributes'); -var Color = _dereq_('../../components/color'); - -function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleXYDefaults(traceIn, traceOut, layout, coerce); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('orientation', (traceOut.y && !traceOut.x) ? 'v' : 'h'); - coerce('offset'); - coerce('width'); - - var text = coerce('text'); - - coerce('hovertext'); - coerce('hovertemplate'); - - var textposition = coerce('textposition'); - handleText(traceIn, traceOut, layout, coerce, textposition, { - moduleHasSelected: false, - moduleHasUnselected: false, - moduleHasConstrain: true, - moduleHasCliponaxis: true, - moduleHasTextangle: true, - moduleHasInsideanchor: true - }); - - if(traceOut.textposition !== 'none') { - coerce('textinfo', Array.isArray(text) ? 'text+value' : 'value'); - } - - var markerColor = coerce('marker.color', defaultColor); - coerce('marker.line.color', Color.defaultLine); - coerce('marker.line.width'); - - var connectorVisible = coerce('connector.visible'); - if(connectorVisible) { - coerce('connector.fillcolor', defaultFillColor(markerColor)); - - var connectorLineWidth = coerce('connector.line.width'); - if(connectorLineWidth) { - coerce('connector.line.color'); - coerce('connector.line.dash'); - } - } -} - -function defaultFillColor(markerColor) { - var cBase = Lib.isArrayOrTypedArray(markerColor) ? '#000' : markerColor; - - return Color.addOpacity(cBase, 0.5 * Color.opacity(cBase)); -} - -function crossTraceDefaults(fullData, fullLayout) { - var traceIn, traceOut; - - function coerce(attr) { - return Lib.coerce(traceOut._input, traceOut, attributes, attr); - } - - if(fullLayout.funnelmode === 'group') { - for(var i = 0; i < fullData.length; i++) { - traceOut = fullData[i]; - traceIn = traceOut._input; - - handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); - } - } -} - -module.exports = { - supplyDefaults: supplyDefaults, - crossTraceDefaults: crossTraceDefaults -}; - -},{"../../components/color":593,"../../lib":719,"../bar/defaults":861,"../scatter/xy_defaults":1137,"./attributes":980}],985:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function eventData(out, pt /* , trace, cd, pointNumber */) { - // standard cartesian event data - out.x = 'xVal' in pt ? pt.xVal : pt.x; - out.y = 'yVal' in pt ? pt.yVal : pt.y; - - // for funnel - if('percentInitial' in pt) out.percentInitial = pt.percentInitial; - if('percentPrevious' in pt) out.percentPrevious = pt.percentPrevious; - if('percentTotal' in pt) out.percentTotal = pt.percentTotal; - - if(pt.xa) out.xaxis = pt.xa; - if(pt.ya) out.yaxis = pt.ya; - - return out; -}; - -},{}],986:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var opacity = _dereq_('../../components/color').opacity; -var hoverOnBars = _dereq_('../bar/hover').hoverOnBars; -var formatPercent = _dereq_('../../lib').formatPercent; - -module.exports = function hoverPoints(pointData, xval, yval, hovermode) { - var point = hoverOnBars(pointData, xval, yval, hovermode); - if(!point) return; - - var cd = point.cd; - var trace = cd[0].trace; - var isHorizontal = (trace.orientation === 'h'); - - // the closest data point - var index = point.index; - var di = cd[index]; - - var sizeLetter = isHorizontal ? 'x' : 'y'; - point[sizeLetter + 'LabelVal'] = di.s; - - point.percentInitial = di.begR; - point.percentInitialLabel = formatPercent(di.begR, 1); - - point.percentPrevious = di.difR; - point.percentPreviousLabel = formatPercent(di.difR, 1); - - point.percentTotal = di.sumR; - point.percentTotalLabel = formatPercent(di.sumR, 1); - - var hoverinfo = di.hi || trace.hoverinfo; - var text = []; - if(hoverinfo && hoverinfo !== 'none' && hoverinfo !== 'skip') { - var isAll = (hoverinfo === 'all'); - var parts = hoverinfo.split('+'); - - var hasFlag = function(flag) { return isAll || parts.indexOf(flag) !== -1; }; - - if(hasFlag('percent initial')) { - text.push(point.percentInitialLabel + ' of initial'); - } - if(hasFlag('percent previous')) { - text.push(point.percentPreviousLabel + ' of previous'); - } - if(hasFlag('percent total')) { - text.push(point.percentTotalLabel + ' of total'); - } - } - point.extraText = text.join('
'); - - point.color = getTraceColor(trace, di); - - return [point]; -}; - -function getTraceColor(trace, di) { - var cont = trace.marker; - var mc = di.mc || cont.color; - var mlc = di.mlc || cont.line.color; - var mlw = di.mlw || cont.line.width; - if(opacity(mc)) return mc; - else if(opacity(mlc) && mlw) return mlc; -} - -},{"../../components/color":593,"../../lib":719,"../bar/hover":863}],987:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('./layout_attributes'), - supplyDefaults: _dereq_('./defaults').supplyDefaults, - crossTraceDefaults: _dereq_('./defaults').crossTraceDefaults, - supplyLayoutDefaults: _dereq_('./layout_defaults'), - calc: _dereq_('./calc'), - crossTraceCalc: _dereq_('./cross_trace_calc'), - plot: _dereq_('./plot'), - style: _dereq_('./style').style, - hoverPoints: _dereq_('./hover'), - eventData: _dereq_('./event_data'), - - selectPoints: _dereq_('../bar/select'), - - moduleType: 'trace', - name: 'funnel', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['bar-like', 'cartesian', 'svg', 'oriented', 'showLegend', 'zoomScale'], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"../bar/select":868,"./attributes":980,"./calc":981,"./cross_trace_calc":983,"./defaults":984,"./event_data":985,"./hover":986,"./layout_attributes":988,"./layout_defaults":989,"./plot":990,"./style":991}],988:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - funnelmode: { - valType: 'enumerated', - values: ['stack', 'group', 'overlay'], - dflt: 'stack', - - editType: 'calc', - - }, - funnelgap: { - valType: 'number', - min: 0, - max: 1, - - editType: 'calc', - - }, - funnelgroupgap: { - valType: 'number', - min: 0, - max: 1, - dflt: 0, - - editType: 'calc', - - } -}; - -},{}],989:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var layoutAttributes = _dereq_('./layout_attributes'); - -module.exports = function(layoutIn, layoutOut, fullData) { - var hasTraceType = false; - - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - - if(trace.visible && trace.type === 'funnel') { - hasTraceType = true; - break; - } - } - - if(hasTraceType) { - coerce('funnelmode'); - coerce('funnelgap', 0.2); - coerce('funnelgroupgap'); - } -}; - -},{"../../lib":719,"./layout_attributes":988}],990:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../../components/drawing'); -var barPlot = _dereq_('../bar/plot').plot; - -module.exports = function plot(gd, plotinfo, cdModule, traceLayer) { - var fullLayout = gd._fullLayout; - - plotConnectorRegions(gd, plotinfo, cdModule, traceLayer); - plotConnectorLines(gd, plotinfo, cdModule, traceLayer); - - barPlot(gd, plotinfo, cdModule, traceLayer, { - mode: fullLayout.funnelmode, - norm: fullLayout.funnelmode, - gap: fullLayout.funnelgap, - groupgap: fullLayout.funnelgroupgap - }); -}; - -function plotConnectorRegions(gd, plotinfo, cdModule, traceLayer) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) { - var plotGroup = d3.select(this); - var trace = cd[0].trace; - - var group = Lib.ensureSingle(plotGroup, 'g', 'regions'); - - if(!trace.connector || !trace.connector.visible) { - group.remove(); - return; - } - - var isHorizontal = (trace.orientation === 'h'); - - var connectors = group.selectAll('g.region').data(Lib.identity); - - connectors.enter().append('g') - .classed('region', true); - - connectors.exit().remove(); - - var len = connectors.size(); - - connectors.each(function(di, i) { - // don't draw lines between nulls - if(i !== len - 1 && !di.cNext) return; - - var xy = getXY(di, xa, ya, isHorizontal); - var x = xy[0]; - var y = xy[1]; - - var shape = ''; - - if(x[3] !== undefined && y[3] !== undefined) { - if(isHorizontal) { - shape += 'M' + x[0] + ',' + y[1] + 'L' + x[2] + ',' + y[2] + 'H' + x[3] + 'L' + x[1] + ',' + y[1] + 'Z'; - } else { - shape += 'M' + x[1] + ',' + y[1] + 'L' + x[2] + ',' + y[3] + 'V' + y[2] + 'L' + x[1] + ',' + y[0] + 'Z'; - } - } - - Lib.ensureSingle(d3.select(this), 'path') - .attr('d', shape) - .call(Drawing.setClipUrl, plotinfo.layerClipId, gd); - }); - }); -} - -function plotConnectorLines(gd, plotinfo, cdModule, traceLayer) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) { - var plotGroup = d3.select(this); - var trace = cd[0].trace; - - var group = Lib.ensureSingle(plotGroup, 'g', 'lines'); - - if(!trace.connector || !trace.connector.visible || !trace.connector.line.width) { - group.remove(); - return; - } - - var isHorizontal = (trace.orientation === 'h'); - - var connectors = group.selectAll('g.line').data(Lib.identity); - - connectors.enter().append('g') - .classed('line', true); - - connectors.exit().remove(); - - var len = connectors.size(); - - connectors.each(function(di, i) { - // don't draw lines between nulls - if(i !== len - 1 && !di.cNext) return; - - var xy = getXY(di, xa, ya, isHorizontal); - var x = xy[0]; - var y = xy[1]; - - var shape = ''; - - if(x[3] !== undefined && y[3] !== undefined) { - if(isHorizontal) { - shape += 'M' + x[0] + ',' + y[1] + 'L' + x[2] + ',' + y[2]; - shape += 'M' + x[1] + ',' + y[1] + 'L' + x[3] + ',' + y[2]; - } else { - shape += 'M' + x[1] + ',' + y[1] + 'L' + x[2] + ',' + y[3]; - shape += 'M' + x[1] + ',' + y[0] + 'L' + x[2] + ',' + y[2]; - } - } - - if(shape === '') shape = 'M0,0Z'; - - Lib.ensureSingle(d3.select(this), 'path') - .attr('d', shape) - .call(Drawing.setClipUrl, plotinfo.layerClipId, gd); - }); - }); -} - -function getXY(di, xa, ya, isHorizontal) { - var s = []; - var p = []; - - var sAxis = isHorizontal ? xa : ya; - var pAxis = isHorizontal ? ya : xa; - - s[0] = sAxis.c2p(di.s0, true); - p[0] = pAxis.c2p(di.p0, true); - - s[1] = sAxis.c2p(di.s1, true); - p[1] = pAxis.c2p(di.p1, true); - - s[2] = sAxis.c2p(di.nextS0, true); - p[2] = pAxis.c2p(di.nextP0, true); - - s[3] = sAxis.c2p(di.nextS1, true); - p[3] = pAxis.c2p(di.nextP1, true); - - return isHorizontal ? [s, p] : [p, s]; -} - -},{"../../components/drawing":614,"../../lib":719,"../bar/plot":867,"d3":163}],991:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Drawing = _dereq_('../../components/drawing'); -var Color = _dereq_('../../components/color'); -var DESELECTDIM = _dereq_('../../constants/interactions').DESELECTDIM; - -var styleTextPoints = _dereq_('../bar/style').styleTextPoints; - -function style(gd, cd, sel) { - var s = sel ? sel : d3.select(gd).selectAll('g.funnellayer').selectAll('g.trace'); - - s.style('opacity', function(d) { return d[0].trace.opacity; }); - - s.each(function(d) { - var gTrace = d3.select(this); - var trace = d[0].trace; - - gTrace.selectAll('.point > path').each(function(di) { - if(!di.isBlank) { - var cont = trace.marker; - - d3.select(this) - .call(Color.fill, di.mc || cont.color) - .call(Color.stroke, di.mlc || cont.line.color) - .call(Drawing.dashLine, cont.line.dash, di.mlw || cont.line.width) - .style('opacity', trace.selectedpoints && !di.selected ? DESELECTDIM : 1); - } - }); - - styleTextPoints(gTrace, trace, gd); - - gTrace.selectAll('.regions').each(function() { - d3.select(this).selectAll('path').style('stroke-width', 0).call(Color.fill, trace.connector.fillcolor); - }); - - gTrace.selectAll('.lines').each(function() { - var cont = trace.connector.line; - - Drawing.lineGroupStyle( - d3.select(this).selectAll('path'), - cont.width, - cont.color, - cont.dash - ); - }); - }); -} - -module.exports = { - style: style -}; - -},{"../../components/color":593,"../../components/drawing":614,"../../constants/interactions":694,"../bar/style":870,"d3":163}],992:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var pieAttrs = _dereq_('../pie/attributes'); -var plotAttrs = _dereq_('../../plots/attributes'); -var domainAttrs = _dereq_('../../plots/domain').attributes; -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = { - labels: pieAttrs.labels, - // equivalent of x0 and dx, if label is missing - label0: pieAttrs.label0, - dlabel: pieAttrs.dlabel, - values: pieAttrs.values, - - marker: { - colors: pieAttrs.marker.colors, - line: { - color: extendFlat({}, pieAttrs.marker.line.color, { - dflt: null, - - }), - width: extendFlat({}, pieAttrs.marker.line.width, {dflt: 1}), - editType: 'calc' - }, - editType: 'calc' - }, - - text: pieAttrs.text, - hovertext: pieAttrs.hovertext, - - scalegroup: extendFlat({}, pieAttrs.scalegroup, { - - }), - - textinfo: extendFlat({}, pieAttrs.textinfo, { - flags: ['label', 'text', 'value', 'percent'] - }), - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['label', 'text', 'value', 'percent', 'name'] - }), - - hovertemplate: hovertemplateAttrs({}, { - keys: ['label', 'color', 'value', 'percent', 'text'] - }), - - textposition: extendFlat({}, pieAttrs.textposition, { - values: ['inside', 'none'], - dflt: 'inside' - }), - - textfont: pieAttrs.textfont, - insidetextfont: pieAttrs.insidetextfont, - - title: { - text: pieAttrs.title.text, - font: pieAttrs.title.font, - position: extendFlat({}, pieAttrs.title.position, { - values: ['top left', 'top center', 'top right'], - dflt: 'top center' - }), - editType: 'plot' - }, - - domain: domainAttrs({name: 'funnelarea', trace: true, editType: 'calc'}), - - aspectratio: { - valType: 'number', - - min: 0, - dflt: 1, - editType: 'plot', - - }, - - baseratio: { - valType: 'number', - - min: 0, - max: 1, - dflt: 0.333, - editType: 'plot', - - } -}; - -},{"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../../plots/domain":792,"../pie/attributes":1086}],993:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; - -exports.name = 'funnelarea'; - -exports.plot = function(gd) { - var Funnelarea = Registry.getModule('funnelarea'); - var cdFunnelarea = getModuleCalcData(gd.calcdata, Funnelarea)[0]; - Funnelarea.plot(gd, cdFunnelarea); -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var hadFunnelarea = (oldFullLayout._has && oldFullLayout._has('funnelarea')); - var hasFunnelarea = (newFullLayout._has && newFullLayout._has('funnelarea')); - - if(hadFunnelarea && !hasFunnelarea) { - oldFullLayout._funnelarealayer.selectAll('g.trace').remove(); - } -}; - -},{"../../plots/get_data":802,"../../registry":847}],994:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var pieCalc = _dereq_('../pie/calc'); - -function calc(gd, trace) { - return pieCalc.calc(gd, trace); -} - -function crossTraceCalc(gd) { - pieCalc.crossTraceCalc(gd, { type: 'funnelarea' }); -} - -module.exports = { - calc: calc, - crossTraceCalc: crossTraceCalc -}; - -},{"../pie/calc":1088}],995:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attributes = _dereq_('./attributes'); -var handleDomainDefaults = _dereq_('../../plots/domain').defaults; -var handleText = _dereq_('../bar/defaults').handleText; - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len; - var vals = coerce('values'); - var hasVals = Lib.isArrayOrTypedArray(vals); - var labels = coerce('labels'); - if(Array.isArray(labels)) { - len = labels.length; - if(hasVals) len = Math.min(len, vals.length); - } else if(hasVals) { - len = vals.length; - - coerce('label0'); - coerce('dlabel'); - } - - if(!len) { - traceOut.visible = false; - return; - } - traceOut._length = len; - - var lineWidth = coerce('marker.line.width'); - if(lineWidth) coerce('marker.line.color', layout.paper_bgcolor); - - coerce('marker.colors'); - - coerce('scalegroup'); - - var textData = coerce('text'); - var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent'); - coerce('hovertext'); - coerce('hovertemplate'); - - if(textInfo && textInfo !== 'none') { - var textposition = coerce('textposition'); - handleText(traceIn, traceOut, layout, coerce, textposition, { - moduleHasSelected: false, - moduleHasUnselected: false, - moduleHasConstrain: false, - moduleHasCliponaxis: false, - moduleHasTextangle: false, - moduleHasInsideanchor: false - }); - } - - handleDomainDefaults(traceOut, layout, coerce); - - var title = coerce('title.text'); - if(title) { - coerce('title.position'); - Lib.coerceFont(coerce, 'title.font', layout.font); - } - - coerce('aspectratio'); - coerce('baseratio'); -}; - -},{"../../lib":719,"../../plots/domain":792,"../bar/defaults":861,"./attributes":992}],996:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'funnelarea', - basePlotModule: _dereq_('./base_plot'), - categories: ['pie-like', 'funnelarea', 'showLegend'], - - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('./layout_attributes'), - supplyDefaults: _dereq_('./defaults'), - supplyLayoutDefaults: _dereq_('./layout_defaults'), - - calc: _dereq_('./calc').calc, - crossTraceCalc: _dereq_('./calc').crossTraceCalc, - - plot: _dereq_('./plot'), - style: _dereq_('./style'), - styleOne: _dereq_('../pie/style_one'), - - meta: { - - } -}; - -},{"../pie/style_one":1097,"./attributes":992,"./base_plot":993,"./calc":994,"./defaults":995,"./layout_attributes":997,"./layout_defaults":998,"./plot":999,"./style":1000}],997:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hiddenlabels = _dereq_('../pie/layout_attributes').hiddenlabels; - -module.exports = { - hiddenlabels: hiddenlabels, - - funnelareacolorway: { - valType: 'colorlist', - - editType: 'calc', - - }, - extendfunnelareacolors: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - } -}; - -},{"../pie/layout_attributes":1093}],998:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var layoutAttributes = _dereq_('./layout_attributes'); - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - - coerce('hiddenlabels'); - coerce('funnelareacolorway', layoutOut.colorway); - coerce('extendfunnelareacolors'); -}; - -},{"../../lib":719,"./layout_attributes":997}],999:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Drawing = _dereq_('../../components/drawing'); -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); - -var barPlot = _dereq_('../bar/plot'); -var getTransform = barPlot.getTransform; -var toMoveInsideBar = barPlot.toMoveInsideBar; - -var pieHelpers = _dereq_('../pie/helpers'); -var piePlot = _dereq_('../pie/plot'); - -var attachFxHandlers = piePlot.attachFxHandlers; -var determineInsideTextFont = piePlot.determineInsideTextFont; - -var layoutAreas = piePlot.layoutAreas; -var prerenderTitles = piePlot.prerenderTitles; -var positionTitleOutside = piePlot.positionTitleOutside; - -module.exports = function plot(gd, cdModule) { - var fullLayout = gd._fullLayout; - - prerenderTitles(cdModule, gd); - layoutAreas(cdModule, fullLayout._size); - - Lib.makeTraceGroups(fullLayout._funnelarealayer, cdModule, 'trace').each(function(cd) { - var plotGroup = d3.select(this); - var cd0 = cd[0]; - var trace = cd0.trace; - - setCoords(cd); - - plotGroup.each(function() { - var slices = d3.select(this).selectAll('g.slice').data(cd); - - slices.enter().append('g') - .classed('slice', true); - slices.exit().remove(); - - slices.each(function(pt) { - if(pt.hidden) { - d3.select(this).selectAll('path,g').remove(); - return; - } - - // to have consistent event data compared to other traces - pt.pointNumber = pt.i; - pt.curveNumber = trace.index; - - var cx = cd0.cx; - var cy = cd0.cy; - var sliceTop = d3.select(this); - var slicePath = sliceTop.selectAll('path.surface').data([pt]); - - slicePath.enter().append('path') - .classed('surface', true) - .style({'pointer-events': 'all'}); - - sliceTop.call(attachFxHandlers, gd, cd); - - var shape = - 'M' + (cx + pt.TR[0]) + ',' + (cy + pt.TR[1]) + - line(pt.TR, pt.BR) + - line(pt.BR, pt.BL) + - line(pt.BL, pt.TL) + - 'Z'; - - slicePath.attr('d', shape); - - // add text - var textPosition = pieHelpers.castOption(trace.textposition, pt.pts); - var sliceTextGroup = sliceTop.selectAll('g.slicetext') - .data(pt.text && (textPosition !== 'none') ? [0] : []); - - sliceTextGroup.enter().append('g') - .classed('slicetext', true); - sliceTextGroup.exit().remove(); - - sliceTextGroup.each(function() { - var sliceText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) { - // prohibit tex interpretation until we can handle - // tex and regular text together - s.attr('data-notex', 1); - }); - - sliceText.text(pt.text) - .attr({ - 'class': 'slicetext', - transform: '', - 'text-anchor': 'middle' - }) - .call(Drawing.font, determineInsideTextFont(trace, pt, gd._fullLayout.font)) - .call(svgTextUtils.convertToTspans, gd); - - // position the text relative to the slice - var textBB = Drawing.bBox(sliceText.node()); - var transform; - - var x0, x1; - var y0 = Math.min(pt.BL[1], pt.BR[1]); - var y1 = Math.max(pt.TL[1], pt.TR[1]); - - x0 = Math.max(pt.TL[0], pt.BL[0]); - x1 = Math.min(pt.TR[0], pt.BR[0]); - - transform = getTransform(toMoveInsideBar(x0, x1, y0, y1, textBB, { - isHorizontal: true, - constrained: true, - angle: 0, - anchor: 'middle' - })); - - sliceText.attr('transform', - 'translate(' + cx + ',' + cy + ')' + transform - ); - }); - }); - - // add the title - var titleTextGroup = d3.select(this).selectAll('g.titletext') - .data(trace.title.text ? [0] : []); - - titleTextGroup.enter().append('g') - .classed('titletext', true); - titleTextGroup.exit().remove(); - - titleTextGroup.each(function() { - var titleText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) { - // prohibit tex interpretation as above - s.attr('data-notex', 1); - }); - - var txt = trace.title.text; - if(trace._meta) { - txt = Lib.templateString(txt, trace._meta); - } - - titleText.text(txt) - .attr({ - 'class': 'titletext', - transform: '', - 'text-anchor': 'middle', - }) - .call(Drawing.font, trace.title.font) - .call(svgTextUtils.convertToTspans, gd); - - var transform = positionTitleOutside(cd0, fullLayout._size); - - titleText.attr('transform', - 'translate(' + transform.x + ',' + transform.y + ')' + - (transform.scale < 1 ? ('scale(' + transform.scale + ')') : '') + - 'translate(' + transform.tx + ',' + transform.ty + ')'); - }); - }); - }); -}; - -function line(a, b) { - var dx = b[0] - a[0]; - var dy = b[1] - a[1]; - - return 'l' + dx + ',' + dy; -} - -function getBetween(a, b) { - return [ - 0.5 * (a[0] + b[0]), - 0.5 * (a[1] + b[1]) - ]; -} - -function setCoords(cd) { - if(!cd.length) return; - - var cd0 = cd[0]; - var trace = cd0.trace; - - var aspectratio = trace.aspectratio; - - var h = trace.baseratio; - if(h > 0.999) h = 0.999; // TODO: may handle this case separately - var h2 = Math.pow(h, 2); - - var v1 = cd0.vTotal; - var v0 = v1 * h2 / (1 - h2); - - var totalValues = v1; - var sumSteps = v0 / v1; - - function calcPos() { - var q = Math.sqrt(sumSteps); - return { - x: q, - y: -q - }; - } - - function getPoint() { - var pos = calcPos(); - return [pos.x, pos.y]; - } - - var p; - var allPoints = []; - allPoints.push(getPoint()); - - var i, cdi; - for(i = cd.length - 1; i > -1; i--) { - cdi = cd[i]; - if(cdi.hidden) continue; - - var step = cdi.v / totalValues; - sumSteps += step; - - allPoints.push(getPoint()); - } - - var minY = Infinity; - var maxY = -Infinity; - for(i = 0; i < allPoints.length; i++) { - p = allPoints[i]; - minY = Math.min(minY, p[1]); - maxY = Math.max(maxY, p[1]); - } - - // center the shape - for(i = 0; i < allPoints.length; i++) { - allPoints[i][1] -= (maxY + minY) / 2; - } - - var lastX = allPoints[allPoints.length - 1][0]; - - // get pie r - var r = cd0.r; - - var rY = (maxY - minY) / 2; - var scaleX = r / lastX; - var scaleY = r / rY * aspectratio; - - // set funnelarea r - cd0.r = scaleY * rY; - - // scale the shape - for(i = 0; i < allPoints.length; i++) { - allPoints[i][0] *= scaleX; - allPoints[i][1] *= scaleY; - } - - // record first position - p = allPoints[0]; - var prevLeft = [-p[0], p[1]]; - var prevRight = [p[0], p[1]]; - - var n = 0; // note we skip the very first point. - for(i = cd.length - 1; i > -1; i--) { - cdi = cd[i]; - if(cdi.hidden) continue; - - n += 1; - var x = allPoints[n][0]; - var y = allPoints[n][1]; - - cdi.TL = [-x, y]; - cdi.TR = [x, y]; - - cdi.BL = prevLeft; - cdi.BR = prevRight; - - cdi.pxmid = getBetween(cdi.TR, cdi.BR); - - prevLeft = cdi.TL; - prevRight = cdi.TR; - } -} - -},{"../../components/drawing":614,"../../lib":719,"../../lib/svg_text_utils":743,"../bar/plot":867,"../pie/helpers":1091,"../pie/plot":1095,"d3":163}],1000:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var styleOne = _dereq_('../pie/style_one'); - -module.exports = function style(gd) { - gd._fullLayout._funnelarealayer.selectAll('.trace').each(function(cd) { - var cd0 = cd[0]; - var trace = cd0.trace; - var traceSelection = d3.select(this); - - traceSelection.style({opacity: trace.opacity}); - - traceSelection.selectAll('path.surface').each(function(pt) { - d3.select(this).call(styleOne, pt, trace); - }); - }); -}; - -},{"../pie/style_one":1097,"d3":163}],1001:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterAttrs = _dereq_('../scatter/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = extendFlat({ - z: { - valType: 'data_array', - editType: 'calc', - - }, - x: extendFlat({}, scatterAttrs.x, {impliedEdits: {xtype: 'array'}}), - x0: extendFlat({}, scatterAttrs.x0, {impliedEdits: {xtype: 'scaled'}}), - dx: extendFlat({}, scatterAttrs.dx, {impliedEdits: {xtype: 'scaled'}}), - y: extendFlat({}, scatterAttrs.y, {impliedEdits: {ytype: 'array'}}), - y0: extendFlat({}, scatterAttrs.y0, {impliedEdits: {ytype: 'scaled'}}), - dy: extendFlat({}, scatterAttrs.dy, {impliedEdits: {ytype: 'scaled'}}), - - text: { - valType: 'data_array', - editType: 'calc', - - }, - hovertext: { - valType: 'data_array', - editType: 'calc', - - }, - transpose: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - xtype: { - valType: 'enumerated', - values: ['array', 'scaled'], - - editType: 'calc+clearAxisTypes', - - }, - ytype: { - valType: 'enumerated', - values: ['array', 'scaled'], - - editType: 'calc+clearAxisTypes', - - }, - zsmooth: { - valType: 'enumerated', - values: ['fast', 'best', false], - dflt: false, - - editType: 'calc', - - }, - connectgaps: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - xgap: { - valType: 'number', - dflt: 0, - min: 0, - - editType: 'plot', - - }, - ygap: { - valType: 'number', - dflt: 0, - min: 0, - - editType: 'plot', - - }, - zhoverformat: { - valType: 'string', - dflt: '', - - editType: 'none', - - }, - hovertemplate: hovertemplateAttrs() -}, { - transforms: undefined -}, - colorScaleAttrs('', {cLetter: 'z', autoColorDflt: false}) -); - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../constants/docs":690,"../../lib/extend":710,"../scatter/attributes":1112}],1002:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); - -var histogram2dCalc = _dereq_('../histogram2d/calc'); -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); -var convertColumnData = _dereq_('./convert_column_xyz'); -var clean2dArray = _dereq_('./clean_2d_array'); -var interp2d = _dereq_('./interp2d'); -var findEmpties = _dereq_('./find_empties'); -var makeBoundArray = _dereq_('./make_bound_array'); - -module.exports = function calc(gd, trace) { - // prepare the raw data - // run makeCalcdata on x and y even for heatmaps, in case of category mappings - var xa = Axes.getFromId(gd, trace.xaxis || 'x'); - var ya = Axes.getFromId(gd, trace.yaxis || 'y'); - var isContour = Registry.traceIs(trace, 'contour'); - var isHist = Registry.traceIs(trace, 'histogram'); - var isGL2D = Registry.traceIs(trace, 'gl2d'); - var zsmooth = isContour ? 'best' : trace.zsmooth; - var x; - var x0; - var dx; - var y; - var y0; - var dy; - var z; - var i; - var binned; - - // cancel minimum tick spacings (only applies to bars and boxes) - xa._minDtick = 0; - ya._minDtick = 0; - - if(isHist) { - binned = histogram2dCalc(gd, trace); - x = binned.x; - x0 = binned.x0; - dx = binned.dx; - y = binned.y; - y0 = binned.y0; - dy = binned.dy; - z = binned.z; - } else { - var zIn = trace.z; - if(Lib.isArray1D(zIn)) { - convertColumnData(trace, xa, ya, 'x', 'y', ['z']); - x = trace._x; - y = trace._y; - zIn = trace._z; - } else { - x = trace._x = trace.x ? xa.makeCalcdata(trace, 'x') : []; - y = trace._y = trace.y ? ya.makeCalcdata(trace, 'y') : []; - } - - x0 = trace.x0; - dx = trace.dx; - y0 = trace.y0; - dy = trace.dy; - - z = clean2dArray(zIn, trace, xa, ya); - - if(isContour || trace.connectgaps) { - trace._emptypoints = findEmpties(z); - interp2d(z, trace._emptypoints); - } - } - - function noZsmooth(msg) { - zsmooth = trace._input.zsmooth = trace.zsmooth = false; - Lib.warn('cannot use zsmooth: "fast": ' + msg); - } - - // check whether we really can smooth (ie all boxes are about the same size) - if(zsmooth === 'fast') { - if(xa.type === 'log' || ya.type === 'log') { - noZsmooth('log axis found'); - } else if(!isHist) { - if(x.length) { - var avgdx = (x[x.length - 1] - x[0]) / (x.length - 1); - var maxErrX = Math.abs(avgdx / 100); - for(i = 0; i < x.length - 1; i++) { - if(Math.abs(x[i + 1] - x[i] - avgdx) > maxErrX) { - noZsmooth('x scale is not linear'); - break; - } - } - } - if(y.length && zsmooth === 'fast') { - var avgdy = (y[y.length - 1] - y[0]) / (y.length - 1); - var maxErrY = Math.abs(avgdy / 100); - for(i = 0; i < y.length - 1; i++) { - if(Math.abs(y[i + 1] - y[i] - avgdy) > maxErrY) { - noZsmooth('y scale is not linear'); - break; - } - } - } - } - } - - // create arrays of brick boundaries, to be used by autorange and heatmap.plot - var xlen = Lib.maxRowLength(z); - var xIn = trace.xtype === 'scaled' ? '' : x; - var xArray = makeBoundArray(trace, xIn, x0, dx, xlen, xa); - var yIn = trace.ytype === 'scaled' ? '' : y; - var yArray = makeBoundArray(trace, yIn, y0, dy, z.length, ya); - - // handled in gl2d convert step - if(!isGL2D) { - trace._extremes[xa._id] = Axes.findExtremes(xa, xArray); - trace._extremes[ya._id] = Axes.findExtremes(ya, yArray); - } - - var cd0 = { - x: xArray, - y: yArray, - z: z, - text: trace._text || trace.text, - hovertext: trace._hovertext || trace.hovertext - }; - - if(xIn && xIn.length === xArray.length - 1) cd0.xCenter = xIn; - if(yIn && yIn.length === yArray.length - 1) cd0.yCenter = yIn; - - if(isHist) { - cd0.xRanges = binned.xRanges; - cd0.yRanges = binned.yRanges; - cd0.pts = binned.pts; - } - - if(!isContour) { - colorscaleCalc(gd, trace, {vals: z, cLetter: 'z'}); - } - - if(isContour && trace.contours && trace.contours.coloring === 'heatmap') { - var dummyTrace = { - type: trace.type === 'contour' ? 'heatmap' : 'histogram2d', - xcalendar: trace.xcalendar, - ycalendar: trace.ycalendar - }; - cd0.xfill = makeBoundArray(dummyTrace, xIn, x0, dx, xlen, xa); - cd0.yfill = makeBoundArray(dummyTrace, yIn, y0, dy, z.length, ya); - } - - return [cd0]; -}; - -},{"../../components/colorscale/calc":601,"../../lib":719,"../../plots/cartesian/axes":767,"../../registry":847,"../histogram2d/calc":1033,"./clean_2d_array":1003,"./convert_column_xyz":1005,"./find_empties":1007,"./interp2d":1010,"./make_bound_array":1011}],1003:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var Lib = _dereq_('../../lib'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -module.exports = function clean2dArray(zOld, trace, xa, ya) { - var rowlen, collen, getCollen, old2new, i, j; - - function cleanZvalue(v) { - if(!isNumeric(v)) return undefined; - return +v; - } - - if(trace && trace.transpose) { - rowlen = 0; - for(i = 0; i < zOld.length; i++) rowlen = Math.max(rowlen, zOld[i].length); - if(rowlen === 0) return false; - getCollen = function(zOld) { return zOld.length; }; - old2new = function(zOld, i, j) { return (zOld[j] || [])[i]; }; - } else { - rowlen = zOld.length; - getCollen = function(zOld, i) { return zOld[i].length; }; - old2new = function(zOld, i, j) { return (zOld[i] || [])[j]; }; - } - - var padOld2new = function(zOld, i, j) { - if(i === BADNUM || j === BADNUM) return BADNUM; - return old2new(zOld, i, j); - }; - - function axisMapping(ax) { - if(trace && trace.type !== 'carpet' && trace.type !== 'contourcarpet' && - ax && ax.type === 'category' && trace['_' + ax._id.charAt(0)].length) { - var axLetter = ax._id.charAt(0); - var axMapping = {}; - var traceCategories = trace['_' + axLetter + 'CategoryMap'] || trace[axLetter]; - for(i = 0; i < traceCategories.length; i++) { - axMapping[traceCategories[i]] = i; - } - return function(i) { - var ind = axMapping[ax._categories[i]]; - return ind + 1 ? ind : BADNUM; - }; - } else { - return Lib.identity; - } - } - - var xMap = axisMapping(xa); - var yMap = axisMapping(ya); - - if(ya && ya.type === 'category') rowlen = ya._categories.length; - var zNew = new Array(rowlen); - - for(i = 0; i < rowlen; i++) { - if(xa && xa.type === 'category') { - collen = xa._categories.length; - } else { - collen = getCollen(zOld, i); - } - zNew[i] = new Array(collen); - for(j = 0; j < collen; j++) zNew[i][j] = cleanZvalue(padOld2new(zOld, yMap(i), xMap(j))); - } - - return zNew; -}; - -},{"../../constants/numerical":695,"../../lib":719,"fast-isnumeric":225}],1004:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - min: 'zmin', - max: 'zmax' -}; - -},{}],1005:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name, arrayVarNames) { - var colLen = trace._length; - var col1 = ax1.makeCalcdata(trace, var1Name); - var col2 = ax2.makeCalcdata(trace, var2Name); - var textCol = trace.text; - var hasColumnText = (textCol !== undefined && Lib.isArray1D(textCol)); - var hoverTextCol = trace.hovertext; - var hasColumnHoverText = (hoverTextCol !== undefined && Lib.isArray1D(hoverTextCol)); - var i, j; - - var col1dv = Lib.distinctVals(col1); - var col1vals = col1dv.vals; - var col2dv = Lib.distinctVals(col2); - var col2vals = col2dv.vals; - var newArrays = []; - var text; - var hovertext; - - for(i = 0; i < arrayVarNames.length; i++) { - newArrays[i] = Lib.init2dArray(col2vals.length, col1vals.length); - } - - if(hasColumnText) { - text = Lib.init2dArray(col2vals.length, col1vals.length); - } - if(hasColumnHoverText) { - hovertext = Lib.init2dArray(col2vals.length, col1vals.length); - } - - for(i = 0; i < colLen; i++) { - if(col1[i] !== BADNUM && col2[i] !== BADNUM) { - var i1 = Lib.findBin(col1[i] + col1dv.minDiff / 2, col1vals); - var i2 = Lib.findBin(col2[i] + col2dv.minDiff / 2, col2vals); - - for(j = 0; j < arrayVarNames.length; j++) { - var arrayVarName = arrayVarNames[j]; - var arrayVar = trace[arrayVarName]; - var newArray = newArrays[j]; - newArray[i2][i1] = arrayVar[i]; - } - - if(hasColumnText) text[i2][i1] = textCol[i]; - if(hasColumnHoverText) hovertext[i2][i1] = hoverTextCol[i]; - } - } - - trace['_' + var1Name] = col1vals; - trace['_' + var2Name] = col2vals; - for(j = 0; j < arrayVarNames.length; j++) { - trace['_' + arrayVarNames[j]] = newArrays[j]; - } - if(hasColumnText) trace._text = text; - if(hasColumnHoverText) trace._hovertext = hovertext; - - if(ax1 && ax1.type === 'category') { - trace['_' + var1Name + 'CategoryMap'] = col1vals.map(function(v) { return ax1._categories[v];}); - } - - if(ax2 && ax2.type === 'category') { - trace['_' + var2Name + 'CategoryMap'] = col2vals.map(function(v) { return ax2._categories[v];}); - } -}; - -},{"../../constants/numerical":695,"../../lib":719}],1006:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var handleXYZDefaults = _dereq_('./xyz_defaults'); -var handleStyleDefaults = _dereq_('./style_defaults'); -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var attributes = _dereq_('./attributes'); - - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var validData = handleXYZDefaults(traceIn, traceOut, coerce, layout); - if(!validData) { - traceOut.visible = false; - return; - } - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - handleStyleDefaults(traceIn, traceOut, coerce, layout); - - coerce('connectgaps', Lib.isArray1D(traceOut.z) && (traceOut.zsmooth !== false)); - - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}); -}; - -},{"../../components/colorscale/defaults":603,"../../lib":719,"./attributes":1001,"./style_defaults":1014,"./xyz_defaults":1015}],1007:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var maxRowLength = _dereq_('../../lib').maxRowLength; - -/* Return a list of empty points in 2D array z - * each empty point z[i][j] gives an array [i, j, neighborCount] - * neighborCount is the count of 4 nearest neighbors that DO exist - * this is to give us an order of points to evaluate for interpolation. - * if no neighbors exist, we iteratively look for neighbors that HAVE - * neighbors, and add a fractional neighborCount - */ -module.exports = function findEmpties(z) { - var empties = []; - var neighborHash = {}; - var noNeighborList = []; - var nextRow = z[0]; - var row = []; - var blank = [0, 0, 0]; - var rowLength = maxRowLength(z); - var prevRow; - var i; - var j; - var thisPt; - var p; - var neighborCount; - var newNeighborHash; - var foundNewNeighbors; - - for(i = 0; i < z.length; i++) { - prevRow = row; - row = nextRow; - nextRow = z[i + 1] || []; - for(j = 0; j < rowLength; j++) { - if(row[j] === undefined) { - neighborCount = (row[j - 1] !== undefined ? 1 : 0) + - (row[j + 1] !== undefined ? 1 : 0) + - (prevRow[j] !== undefined ? 1 : 0) + - (nextRow[j] !== undefined ? 1 : 0); - - if(neighborCount) { - // for this purpose, don't count off-the-edge points - // as undefined neighbors - if(i === 0) neighborCount++; - if(j === 0) neighborCount++; - if(i === z.length - 1) neighborCount++; - if(j === row.length - 1) neighborCount++; - - // if all neighbors that could exist do, we don't - // need this for finding farther neighbors - if(neighborCount < 4) { - neighborHash[[i, j]] = [i, j, neighborCount]; - } - - empties.push([i, j, neighborCount]); - } else noNeighborList.push([i, j]); - } - } - } - - while(noNeighborList.length) { - newNeighborHash = {}; - foundNewNeighbors = false; - - // look for cells that now have neighbors but didn't before - for(p = noNeighborList.length - 1; p >= 0; p--) { - thisPt = noNeighborList[p]; - i = thisPt[0]; - j = thisPt[1]; - - neighborCount = ((neighborHash[[i - 1, j]] || blank)[2] + - (neighborHash[[i + 1, j]] || blank)[2] + - (neighborHash[[i, j - 1]] || blank)[2] + - (neighborHash[[i, j + 1]] || blank)[2]) / 20; - - if(neighborCount) { - newNeighborHash[thisPt] = [i, j, neighborCount]; - noNeighborList.splice(p, 1); - foundNewNeighbors = true; - } - } - - if(!foundNewNeighbors) { - throw 'findEmpties iterated with no new neighbors'; - } - - // put these new cells into the main neighbor list - for(thisPt in newNeighborHash) { - neighborHash[thisPt] = newNeighborHash[thisPt]; - empties.push(newNeighborHash[thisPt]); - } - } - - // sort the full list in descending order of neighbor count - return empties.sort(function(a, b) { return b[2] - a[2]; }); -}; - -},{"../../lib":719}],1008:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Fx = _dereq_('../../components/fx'); -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var extractOpts = _dereq_('../../components/colorscale').extractOpts; - -module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer, contour) { - var cd0 = pointData.cd[0]; - var trace = cd0.trace; - var xa = pointData.xa; - var ya = pointData.ya; - var x = cd0.x; - var y = cd0.y; - var z = cd0.z; - var xc = cd0.xCenter; - var yc = cd0.yCenter; - var zmask = cd0.zmask; - var zhoverformat = trace.zhoverformat; - var x2 = x; - var y2 = y; - - var xl, yl, nx, ny; - - if(pointData.index !== false) { - try { - nx = Math.round(pointData.index[1]); - ny = Math.round(pointData.index[0]); - } catch(e) { - Lib.error('Error hovering on heatmap, ' + - 'pointNumber must be [row,col], found:', pointData.index); - return; - } - if(nx < 0 || nx >= z[0].length || ny < 0 || ny > z.length) { - return; - } - } else if(Fx.inbox(xval - x[0], xval - x[x.length - 1], 0) > 0 || - Fx.inbox(yval - y[0], yval - y[y.length - 1], 0) > 0) { - return; - } else { - if(contour) { - var i2; - x2 = [2 * x[0] - x[1]]; - - for(i2 = 1; i2 < x.length; i2++) { - x2.push((x[i2] + x[i2 - 1]) / 2); - } - x2.push([2 * x[x.length - 1] - x[x.length - 2]]); - - y2 = [2 * y[0] - y[1]]; - for(i2 = 1; i2 < y.length; i2++) { - y2.push((y[i2] + y[i2 - 1]) / 2); - } - y2.push([2 * y[y.length - 1] - y[y.length - 2]]); - } - nx = Math.max(0, Math.min(x2.length - 2, Lib.findBin(xval, x2))); - ny = Math.max(0, Math.min(y2.length - 2, Lib.findBin(yval, y2))); - } - - var x0 = xa.c2p(x[nx]); - var x1 = xa.c2p(x[nx + 1]); - var y0 = ya.c2p(y[ny]); - var y1 = ya.c2p(y[ny + 1]); - - if(contour) { - x1 = x0; - xl = x[nx]; - y1 = y0; - yl = y[ny]; - } else { - xl = xc ? xc[nx] : ((x[nx] + x[nx + 1]) / 2); - yl = yc ? yc[ny] : ((y[ny] + y[ny + 1]) / 2); - - if(xa && xa.type === 'category') xl = x[nx]; - if(ya && ya.type === 'category') yl = y[ny]; - - if(trace.zsmooth) { - x0 = x1 = xa.c2p(xl); - y0 = y1 = ya.c2p(yl); - } - } - - var zVal = z[ny][nx]; - if(zmask && !zmask[ny][nx]) zVal = undefined; - - var text; - if(Array.isArray(cd0.hovertext) && Array.isArray(cd0.hovertext[ny])) { - text = cd0.hovertext[ny][nx]; - } else if(Array.isArray(cd0.text) && Array.isArray(cd0.text[ny])) { - text = cd0.text[ny][nx]; - } - - // dummy axis for formatting the z value - var cOpts = extractOpts(trace); - var dummyAx = { - type: 'linear', - range: [cOpts.min, cOpts.max], - hoverformat: zhoverformat, - _separators: xa._separators, - _numFormat: xa._numFormat - }; - var zLabel = Axes.tickText(dummyAx, zVal, 'hover').text; - - return [Lib.extendFlat(pointData, { - index: [ny, nx], - // never let a 2D override 1D type as closest point - distance: pointData.maxHoverDistance, - spikeDistance: pointData.maxSpikeDistance, - x0: x0, - x1: x1, - y0: y0, - y1: y1, - xLabelVal: xl, - yLabelVal: yl, - zLabelVal: zVal, - zLabel: zLabel, - text: text - })]; -}; - -},{"../../components/colorscale":605,"../../components/fx":632,"../../lib":719,"../../plots/cartesian/axes":767}],1009:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - colorbar: _dereq_('./colorbar'), - style: _dereq_('./style'), - hoverPoints: _dereq_('./hover'), - - moduleType: 'trace', - name: 'heatmap', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', '2dMap'], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"./attributes":1001,"./calc":1002,"./colorbar":1004,"./defaults":1006,"./hover":1008,"./plot":1012,"./style":1013}],1010:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var INTERPTHRESHOLD = 1e-2; -var NEIGHBORSHIFTS = [[-1, 0], [1, 0], [0, -1], [0, 1]]; - -function correctionOvershoot(maxFractionalChange) { - // start with less overshoot, until we know it's converging, - // then ramp up the overshoot for faster convergence - return 0.5 - 0.25 * Math.min(1, maxFractionalChange * 0.5); -} - -/* - * interp2d: Fill in missing data from a 2D array using an iterative - * poisson equation solver with zero-derivative BC at edges. - * Amazingly, this just amounts to repeatedly averaging all the existing - * nearest neighbors, at least if we don't take x/y scaling into account, - * which is the right approach here where x and y may not even have the - * same units. - * - * @param {array of arrays} z - * The 2D array to fill in. Will be mutated here. Assumed to already be - * cleaned, so all entries are numbers except gaps, which are `undefined`. - * @param {array of arrays} emptyPoints - * Each entry [i, j, neighborCount] for empty points z[i][j] and the number - * of neighbors that are *not* missing. Assumed to be sorted from most to - * least neighbors, as produced by heatmap/find_empties. - */ -module.exports = function interp2d(z, emptyPoints) { - var maxFractionalChange = 1; - var i; - - // one pass to fill in a starting value for all the empties - iterateInterp2d(z, emptyPoints); - - // we're don't need to iterate lone empties - remove them - for(i = 0; i < emptyPoints.length; i++) { - if(emptyPoints[i][2] < 4) break; - } - // but don't remove these points from the original array, - // we'll use them for masking, so make a copy. - emptyPoints = emptyPoints.slice(i); - - for(i = 0; i < 100 && maxFractionalChange > INTERPTHRESHOLD; i++) { - maxFractionalChange = iterateInterp2d(z, emptyPoints, - correctionOvershoot(maxFractionalChange)); - } - if(maxFractionalChange > INTERPTHRESHOLD) { - Lib.log('interp2d didn\'t converge quickly', maxFractionalChange); - } - - return z; -}; - -function iterateInterp2d(z, emptyPoints, overshoot) { - var maxFractionalChange = 0; - var thisPt; - var i; - var j; - var p; - var q; - var neighborShift; - var neighborRow; - var neighborVal; - var neighborCount; - var neighborSum; - var initialVal; - var minNeighbor; - var maxNeighbor; - - for(p = 0; p < emptyPoints.length; p++) { - thisPt = emptyPoints[p]; - i = thisPt[0]; - j = thisPt[1]; - initialVal = z[i][j]; - neighborSum = 0; - neighborCount = 0; - - for(q = 0; q < 4; q++) { - neighborShift = NEIGHBORSHIFTS[q]; - neighborRow = z[i + neighborShift[0]]; - if(!neighborRow) continue; - neighborVal = neighborRow[j + neighborShift[1]]; - if(neighborVal !== undefined) { - if(neighborSum === 0) { - minNeighbor = maxNeighbor = neighborVal; - } else { - minNeighbor = Math.min(minNeighbor, neighborVal); - maxNeighbor = Math.max(maxNeighbor, neighborVal); - } - neighborCount++; - neighborSum += neighborVal; - } - } - - if(neighborCount === 0) { - throw 'iterateInterp2d order is wrong: no defined neighbors'; - } - - // this is the laplace equation interpolation: - // each point is just the average of its neighbors - // note that this ignores differential x/y scaling - // which I think is the right approach, since we - // don't know what that scaling means - z[i][j] = neighborSum / neighborCount; - - if(initialVal === undefined) { - if(neighborCount < 4) maxFractionalChange = 1; - } else { - // we can make large empty regions converge faster - // if we overshoot the change vs the previous value - z[i][j] = (1 + overshoot) * z[i][j] - overshoot * initialVal; - - if(maxNeighbor > minNeighbor) { - maxFractionalChange = Math.max(maxFractionalChange, - Math.abs(z[i][j] - initialVal) / (maxNeighbor - minNeighbor)); - } - } - } - - return maxFractionalChange; -} - -},{"../../lib":719}],1011:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; - -module.exports = function makeBoundArray(trace, arrayIn, v0In, dvIn, numbricks, ax) { - var arrayOut = []; - var isContour = Registry.traceIs(trace, 'contour'); - var isHist = Registry.traceIs(trace, 'histogram'); - var isGL2D = Registry.traceIs(trace, 'gl2d'); - var v0; - var dv; - var i; - - var isArrayOfTwoItemsOrMore = isArrayOrTypedArray(arrayIn) && arrayIn.length > 1; - - if(isArrayOfTwoItemsOrMore && !isHist && (ax.type !== 'category')) { - var len = arrayIn.length; - - // given vals are brick centers - // hopefully length === numbricks, but use this method even if too few are supplied - // and extend it linearly based on the last two points - if(len <= numbricks) { - // contour plots only want the centers - if(isContour || isGL2D) arrayOut = arrayIn.slice(0, numbricks); - else if(numbricks === 1) { - arrayOut = [arrayIn[0] - 0.5, arrayIn[0] + 0.5]; - } else { - arrayOut = [1.5 * arrayIn[0] - 0.5 * arrayIn[1]]; - - for(i = 1; i < len; i++) { - arrayOut.push((arrayIn[i - 1] + arrayIn[i]) * 0.5); - } - - arrayOut.push(1.5 * arrayIn[len - 1] - 0.5 * arrayIn[len - 2]); - } - - if(len < numbricks) { - var lastPt = arrayOut[arrayOut.length - 1]; - var delta = lastPt - arrayOut[arrayOut.length - 2]; - - for(i = len; i < numbricks; i++) { - lastPt += delta; - arrayOut.push(lastPt); - } - } - } else { - // hopefully length === numbricks+1, but do something regardless: - // given vals are brick boundaries - return isContour ? - arrayIn.slice(0, numbricks) : // we must be strict for contours - arrayIn.slice(0, numbricks + 1); - } - } else { - var calendar = trace[ax._id.charAt(0) + 'calendar']; - - if(isHist) { - v0 = ax.r2c(v0In, 0, calendar); - } else { - if(isArrayOrTypedArray(arrayIn) && arrayIn.length === 1) { - v0 = arrayIn[0]; - } else if(v0In === undefined) { - v0 = 0; - } else { - var fn = ax.type === 'log' ? ax.d2c : ax.r2c; - v0 = fn(v0In, 0, calendar); - } - } - - dv = dvIn || 1; - - for(i = (isContour || isGL2D) ? 0 : -0.5; i < numbricks; i++) { - arrayOut.push(v0 + dv * i); - } - } - - return arrayOut; -}; - -},{"../../lib":719,"../../registry":847}],1012:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var tinycolor = _dereq_('tinycolor2'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var makeColorScaleFuncFromTrace = _dereq_('../../components/colorscale').makeColorScaleFuncFromTrace; -var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); - -module.exports = function(gd, plotinfo, cdheatmaps, heatmapLayer) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - Lib.makeTraceGroups(heatmapLayer, cdheatmaps, 'hm').each(function(cd) { - var plotGroup = d3.select(this); - var cd0 = cd[0]; - var trace = cd0.trace; - - var z = cd0.z; - var x = cd0.x; - var y = cd0.y; - var xc = cd0.xCenter; - var yc = cd0.yCenter; - var isContour = Registry.traceIs(trace, 'contour'); - var zsmooth = isContour ? 'best' : trace.zsmooth; - - // get z dims - var m = z.length; - var n = Lib.maxRowLength(z); - var xrev = false; - var yrev = false; - - var left, right, temp, top, bottom, i; - - // TODO: if there are multiple overlapping categorical heatmaps, - // or if we allow category sorting, then the categories may not be - // sequential... may need to reorder and/or expand z - - // Get edges of png in pixels (xa.c2p() maps axes coordinates to pixel coordinates) - // figure out if either axis is reversed (y is usually reversed, in pixel coords) - // also clip the image to maximum 50% outside the visible plot area - // bigger image lets you pan more naturally, but slows performance. - // TODO: use low-resolution images outside the visible plot for panning - // these while loops find the first and last brick bounds that are defined - // (in case of log of a negative) - i = 0; - while(left === undefined && i < x.length - 1) { - left = xa.c2p(x[i]); - i++; - } - i = x.length - 1; - while(right === undefined && i > 0) { - right = xa.c2p(x[i]); - i--; - } - - if(right < left) { - temp = right; - right = left; - left = temp; - xrev = true; - } - - i = 0; - while(top === undefined && i < y.length - 1) { - top = ya.c2p(y[i]); - i++; - } - i = y.length - 1; - while(bottom === undefined && i > 0) { - bottom = ya.c2p(y[i]); - i--; - } - - if(bottom < top) { - temp = top; - top = bottom; - bottom = temp; - yrev = true; - } - - // for contours with heatmap fill, we generate the boundaries based on - // brick centers but then use the brick edges for drawing the bricks - if(isContour) { - xc = x; - yc = y; - x = cd0.xfill; - y = cd0.yfill; - } - - // make an image that goes at most half a screen off either side, to keep - // time reasonable when you zoom in. if zsmooth is true/fast, don't worry - // about this, because zooming doesn't increase number of pixels - // if zsmooth is best, don't include anything off screen because it takes too long - if(zsmooth !== 'fast') { - var extra = zsmooth === 'best' ? 0 : 0.5; - left = Math.max(-extra * xa._length, left); - right = Math.min((1 + extra) * xa._length, right); - top = Math.max(-extra * ya._length, top); - bottom = Math.min((1 + extra) * ya._length, bottom); - } - - var imageWidth = Math.round(right - left); - var imageHeight = Math.round(bottom - top); - - // setup image nodes - - // if image is entirely off-screen, don't even draw it - var isOffScreen = (imageWidth <= 0 || imageHeight <= 0); - - if(isOffScreen) { - var noImage = plotGroup.selectAll('image').data([]); - noImage.exit().remove(); - return; - } - - // generate image data - - var canvasW, canvasH; - if(zsmooth === 'fast') { - canvasW = n; - canvasH = m; - } else { - canvasW = imageWidth; - canvasH = imageHeight; - } - - var canvas = document.createElement('canvas'); - canvas.width = canvasW; - canvas.height = canvasH; - var context = canvas.getContext('2d'); - - var sclFunc = makeColorScaleFuncFromTrace(trace, {noNumericCheck: true, returnArray: true}); - - // map brick boundaries to image pixels - var xpx, - ypx; - if(zsmooth === 'fast') { - xpx = xrev ? - function(index) { return n - 1 - index; } : - Lib.identity; - ypx = yrev ? - function(index) { return m - 1 - index; } : - Lib.identity; - } else { - xpx = function(index) { - return Lib.constrain(Math.round(xa.c2p(x[index]) - left), - 0, imageWidth); - }; - ypx = function(index) { - return Lib.constrain(Math.round(ya.c2p(y[index]) - top), - 0, imageHeight); - }; - } - - // build the pixel map brick-by-brick - // cruise through z-matrix row-by-row - // build a brick at each z-matrix value - var yi = ypx(0); - var yb = [yi, yi]; - var xbi = xrev ? 0 : 1; - var ybi = yrev ? 0 : 1; - // for collecting an average luminosity of the heatmap - var pixcount = 0; - var rcount = 0; - var gcount = 0; - var bcount = 0; - - var xb, j, xi, v, row, c; - - function setColor(v, pixsize) { - if(v !== undefined) { - var c = sclFunc(v); - c[0] = Math.round(c[0]); - c[1] = Math.round(c[1]); - c[2] = Math.round(c[2]); - - pixcount += pixsize; - rcount += c[0] * pixsize; - gcount += c[1] * pixsize; - bcount += c[2] * pixsize; - return c; - } - return [0, 0, 0, 0]; - } - - function interpColor(r0, r1, xinterp, yinterp) { - var z00 = r0[xinterp.bin0]; - if(z00 === undefined) return setColor(undefined, 1); - - var z01 = r0[xinterp.bin1]; - var z10 = r1[xinterp.bin0]; - var z11 = r1[xinterp.bin1]; - var dx = (z01 - z00) || 0; - var dy = (z10 - z00) || 0; - var dxy; - - // the bilinear interpolation term needs different calculations - // for all the different permutations of missing data - // among the neighbors of the main point, to ensure - // continuity across brick boundaries. - if(z01 === undefined) { - if(z11 === undefined) dxy = 0; - else if(z10 === undefined) dxy = 2 * (z11 - z00); - else dxy = (2 * z11 - z10 - z00) * 2 / 3; - } else if(z11 === undefined) { - if(z10 === undefined) dxy = 0; - else dxy = (2 * z00 - z01 - z10) * 2 / 3; - } else if(z10 === undefined) dxy = (2 * z11 - z01 - z00) * 2 / 3; - else dxy = (z11 + z00 - z01 - z10); - - return setColor(z00 + xinterp.frac * dx + yinterp.frac * (dy + xinterp.frac * dxy)); - } - - if(zsmooth) { // best or fast, works fastest with imageData - var pxIndex = 0; - var pixels; - - try { - pixels = new Uint8Array(imageWidth * imageHeight * 4); - } catch(e) { - pixels = new Array(imageWidth * imageHeight * 4); - } - - if(zsmooth === 'best') { - var xForPx = xc || x; - var yForPx = yc || y; - var xPixArray = new Array(xForPx.length); - var yPixArray = new Array(yForPx.length); - var xinterpArray = new Array(imageWidth); - var findInterpX = xc ? findInterpFromCenters : findInterp; - var findInterpY = yc ? findInterpFromCenters : findInterp; - var yinterp, r0, r1; - - // first make arrays of x and y pixel locations of brick boundaries - for(i = 0; i < xForPx.length; i++) xPixArray[i] = Math.round(xa.c2p(xForPx[i]) - left); - for(i = 0; i < yForPx.length; i++) yPixArray[i] = Math.round(ya.c2p(yForPx[i]) - top); - - // then make arrays of interpolations - // (bin0=closest, bin1=next, frac=fractional dist.) - for(i = 0; i < imageWidth; i++) xinterpArray[i] = findInterpX(i, xPixArray); - - // now do the interpolations and fill the png - for(j = 0; j < imageHeight; j++) { - yinterp = findInterpY(j, yPixArray); - r0 = z[yinterp.bin0]; - r1 = z[yinterp.bin1]; - for(i = 0; i < imageWidth; i++, pxIndex += 4) { - c = interpColor(r0, r1, xinterpArray[i], yinterp); - putColor(pixels, pxIndex, c); - } - } - } else { // zsmooth = fast - for(j = 0; j < m; j++) { - row = z[j]; - yb = ypx(j); - for(i = 0; i < imageWidth; i++) { - c = setColor(row[i], 1); - pxIndex = (yb * imageWidth + xpx(i)) * 4; - putColor(pixels, pxIndex, c); - } - } - } - - var imageData = context.createImageData(imageWidth, imageHeight); - try { - imageData.data.set(pixels); - } catch(e) { - var pxArray = imageData.data; - var dlen = pxArray.length; - for(j = 0; j < dlen; j ++) { - pxArray[j] = pixels[j]; - } - } - - context.putImageData(imageData, 0, 0); - } else { // zsmooth = false -> filling potentially large bricks works fastest with fillRect - // gaps do not need to be exact integers, but if they *are* we will get - // cleaner edges by rounding at least one edge - var xGap = trace.xgap; - var yGap = trace.ygap; - var xGapLeft = Math.floor(xGap / 2); - var yGapTop = Math.floor(yGap / 2); - - for(j = 0; j < m; j++) { - row = z[j]; - yb.reverse(); - yb[ybi] = ypx(j + 1); - if(yb[0] === yb[1] || yb[0] === undefined || yb[1] === undefined) { - continue; - } - xi = xpx(0); - xb = [xi, xi]; - for(i = 0; i < n; i++) { - // build one color brick! - xb.reverse(); - xb[xbi] = xpx(i + 1); - if(xb[0] === xb[1] || xb[0] === undefined || xb[1] === undefined) { - continue; - } - v = row[i]; - c = setColor(v, (xb[1] - xb[0]) * (yb[1] - yb[0])); - context.fillStyle = 'rgba(' + c.join(',') + ')'; - - context.fillRect(xb[0] + xGapLeft, yb[0] + yGapTop, - xb[1] - xb[0] - xGap, yb[1] - yb[0] - yGap); - } - } - } - - rcount = Math.round(rcount / pixcount); - gcount = Math.round(gcount / pixcount); - bcount = Math.round(bcount / pixcount); - var avgColor = tinycolor('rgb(' + rcount + ',' + gcount + ',' + bcount + ')'); - - gd._hmpixcount = (gd._hmpixcount||0) + pixcount; - gd._hmlumcount = (gd._hmlumcount||0) + pixcount * avgColor.getLuminance(); - - var image3 = plotGroup.selectAll('image') - .data(cd); - - image3.enter().append('svg:image').attr({ - xmlns: xmlnsNamespaces.svg, - preserveAspectRatio: 'none' - }); - - image3.attr({ - height: imageHeight, - width: imageWidth, - x: left, - y: top, - 'xlink:href': canvas.toDataURL('image/png') - }); - }); -}; - -// get interpolated bin value. Returns {bin0:closest bin, frac:fractional dist to next, bin1:next bin} -function findInterp(pixel, pixArray) { - var maxBin = pixArray.length - 2; - var bin = Lib.constrain(Lib.findBin(pixel, pixArray), 0, maxBin); - var pix0 = pixArray[bin]; - var pix1 = pixArray[bin + 1]; - var interp = Lib.constrain(bin + (pixel - pix0) / (pix1 - pix0) - 0.5, 0, maxBin); - var bin0 = Math.round(interp); - var frac = Math.abs(interp - bin0); - - if(!interp || interp === maxBin || !frac) { - return { - bin0: bin0, - bin1: bin0, - frac: 0 - }; - } - return { - bin0: bin0, - frac: frac, - bin1: Math.round(bin0 + frac / (interp - bin0)) - }; -} - -function findInterpFromCenters(pixel, centerPixArray) { - var maxBin = centerPixArray.length - 1; - var bin = Lib.constrain(Lib.findBin(pixel, centerPixArray), 0, maxBin); - var pix0 = centerPixArray[bin]; - var pix1 = centerPixArray[bin + 1]; - var frac = ((pixel - pix0) / (pix1 - pix0)) || 0; - if(frac <= 0) { - return { - bin0: bin, - bin1: bin, - frac: 0 - }; - } - if(frac < 0.5) { - return { - bin0: bin, - bin1: bin + 1, - frac: frac - }; - } - return { - bin0: bin + 1, - bin1: bin, - frac: 1 - frac - }; -} - -function putColor(pixels, pxIndex, c) { - pixels[pxIndex] = c[0]; - pixels[pxIndex + 1] = c[1]; - pixels[pxIndex + 2] = c[2]; - pixels[pxIndex + 3] = Math.round(c[3] * 255); -} - -},{"../../components/colorscale":605,"../../constants/xmlns_namespaces":696,"../../lib":719,"../../registry":847,"d3":163,"tinycolor2":537}],1013:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -module.exports = function style(gd) { - d3.select(gd).selectAll('.hm image') - .style('opacity', function(d) { - return d.trace.opacity; - }); -}; - -},{"d3":163}],1014:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = function handleStyleDefaults(traceIn, traceOut, coerce) { - var zsmooth = coerce('zsmooth'); - if(zsmooth === false) { - // ensure that xgap and ygap are coerced only when zsmooth allows them to have an effect. - coerce('xgap'); - coerce('ygap'); - } - - coerce('zhoverformat'); -}; - -},{}],1015:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var Lib = _dereq_('../../lib'); - -var Registry = _dereq_('../../registry'); - -module.exports = function handleXYZDefaults(traceIn, traceOut, coerce, layout, xName, yName) { - var z = coerce('z'); - xName = xName || 'x'; - yName = yName || 'y'; - var x, y; - - if(z === undefined || !z.length) return 0; - - if(Lib.isArray1D(traceIn.z)) { - x = coerce(xName); - y = coerce(yName); - - var xlen = Lib.minRowLength(x); - var ylen = Lib.minRowLength(y); - - // column z must be accompanied by xName and yName arrays - if(xlen === 0 || ylen === 0) return 0; - - traceOut._length = Math.min(xlen, ylen, z.length); - } else { - x = coordDefaults(xName, coerce); - y = coordDefaults(yName, coerce); - - // TODO put z validation elsewhere - if(!isValidZ(z)) return 0; - - coerce('transpose'); - - traceOut._length = null; - } - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, [xName, yName], layout); - - return true; -}; - -function coordDefaults(coordStr, coerce) { - var coord = coerce(coordStr); - var coordType = coord ? coerce(coordStr + 'type', 'array') : 'scaled'; - - if(coordType === 'scaled') { - coerce(coordStr + '0'); - coerce('d' + coordStr); - } - - return coord; -} - -function isValidZ(z) { - var allRowsAreArrays = true; - var oneRowIsFilled = false; - var hasOneNumber = false; - var zi; - - /* - * Without this step: - * - * hasOneNumber = false breaks contour but not heatmap - * allRowsAreArrays = false breaks contour but not heatmap - * oneRowIsFilled = false breaks both - */ - - for(var i = 0; i < z.length; i++) { - zi = z[i]; - if(!Lib.isArrayOrTypedArray(zi)) { - allRowsAreArrays = false; - break; - } - if(zi.length > 0) oneRowIsFilled = true; - for(var j = 0; j < zi.length; j++) { - if(isNumeric(zi[j])) { - hasOneNumber = true; - break; - } - } - } - - return (allRowsAreArrays && oneRowIsFilled && hasOneNumber); -} - -},{"../../lib":719,"../../registry":847,"fast-isnumeric":225}],1016:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var heatmapAttrs = _dereq_('../heatmap/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var commonList = [ - 'z', - 'x', 'x0', 'dx', - 'y', 'y0', 'dy', - 'text', 'transpose', - 'xtype', 'ytype' -]; - -var attrs = {}; - -for(var i = 0; i < commonList.length; i++) { - var k = commonList[i]; - attrs[k] = heatmapAttrs[k]; -} - -extendFlat( - attrs, - colorScaleAttrs('', {cLetter: 'z', autoColorDflt: false}) -); - -module.exports = overrideAll(attrs, 'calc', 'nested'); - -},{"../../components/colorscale/attributes":600,"../../lib/extend":710,"../../plot_api/edit_types":750,"../heatmap/attributes":1001}],1017:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var createHeatmap2D = _dereq_('gl-heatmap2d'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var str2RGBArray = _dereq_('../../lib/str2rgbarray'); - - -function Heatmap(scene, uid) { - this.scene = scene; - this.uid = uid; - this.type = 'heatmapgl'; - - this.name = ''; - this.hoverinfo = 'all'; - - this.xData = []; - this.yData = []; - this.zData = []; - this.textLabels = []; - - this.idToIndex = []; - this.bounds = [0, 0, 0, 0]; - - this.options = { - z: [], - x: [], - y: [], - shape: [0, 0], - colorLevels: [0], - colorValues: [0, 0, 0, 1] - }; - - this.heatmap = createHeatmap2D(scene.glplot, this.options); - this.heatmap._trace = this; -} - -var proto = Heatmap.prototype; - -proto.handlePick = function(pickResult) { - var options = this.options; - var shape = options.shape; - var index = pickResult.pointId; - var xIndex = index % shape[0]; - var yIndex = Math.floor(index / shape[0]); - var zIndex = index; - - return { - trace: this, - dataCoord: pickResult.dataCoord, - traceCoord: [ - options.x[xIndex], - options.y[yIndex], - options.z[zIndex] - ], - textLabel: this.textLabels[index], - name: this.name, - pointIndex: [yIndex, xIndex], - hoverinfo: this.hoverinfo - }; -}; - -proto.update = function(fullTrace, calcTrace) { - var calcPt = calcTrace[0]; - - this.index = fullTrace.index; - this.name = fullTrace.name; - this.hoverinfo = fullTrace.hoverinfo; - - // convert z from 2D -> 1D - var z = calcPt.z; - this.options.z = [].concat.apply([], z); - - var rowLen = z[0].length; - var colLen = z.length; - this.options.shape = [rowLen, colLen]; - - this.options.x = calcPt.x; - this.options.y = calcPt.y; - - var colorOptions = convertColorscale(fullTrace); - this.options.colorLevels = colorOptions.colorLevels; - this.options.colorValues = colorOptions.colorValues; - - // convert text from 2D -> 1D - this.textLabels = [].concat.apply([], fullTrace.text); - - this.heatmap.update(this.options); - - var xa = this.scene.xaxis; - var ya = this.scene.yaxis; - fullTrace._extremes[xa._id] = Axes.findExtremes(xa, calcPt.x); - fullTrace._extremes[ya._id] = Axes.findExtremes(ya, calcPt.y); -}; - -proto.dispose = function() { - this.heatmap.dispose(); -}; - -function convertColorscale(fullTrace) { - var scl = fullTrace.colorscale; - var zmin = fullTrace.zmin; - var zmax = fullTrace.zmax; - - var N = scl.length; - var domain = new Array(N); - var range = new Array(4 * N); - - for(var i = 0; i < N; i++) { - var si = scl[i]; - var color = str2RGBArray(si[1]); - - domain[i] = zmin + si[0] * (zmax - zmin); - - for(var j = 0; j < 4; j++) { - range[(4 * i) + j] = color[j]; - } - } - - return { - colorLevels: domain, - colorValues: range - }; -} - -function createHeatmap(scene, fullTrace, calcTrace) { - var plot = new Heatmap(scene, fullTrace.uid); - plot.update(fullTrace, calcTrace); - return plot; -} - -module.exports = createHeatmap; - -},{"../../lib/str2rgbarray":742,"../../plots/cartesian/axes":767,"gl-heatmap2d":251}],1018:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('../heatmap/defaults'), - colorbar: _dereq_('../heatmap/colorbar'), - - calc: _dereq_('../heatmap/calc'), - plot: _dereq_('./convert'), - - moduleType: 'trace', - name: 'heatmapgl', - basePlotModule: _dereq_('../../plots/gl2d'), - categories: ['gl', 'gl2d', '2dMap'], - meta: { - - } -}; - -},{"../../plots/gl2d":805,"../heatmap/calc":1002,"../heatmap/colorbar":1004,"../heatmap/defaults":1006,"./attributes":1016,"./convert":1017}],1019:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var barAttrs = _dereq_('../bar/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var makeBinAttrs = _dereq_('./bin_attributes'); -var constants = _dereq_('./constants'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = { - x: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - y: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - - text: extendFlat({}, barAttrs.text, { - - }), - hovertext: extendFlat({}, barAttrs.hovertext, { - - }), - orientation: barAttrs.orientation, - - histfunc: { - valType: 'enumerated', - values: ['count', 'sum', 'avg', 'min', 'max'], - - dflt: 'count', - editType: 'calc', - - }, - histnorm: { - valType: 'enumerated', - values: ['', 'percent', 'probability', 'density', 'probability density'], - dflt: '', - - editType: 'calc', - - }, - - cumulative: { - enabled: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - - direction: { - valType: 'enumerated', - values: ['increasing', 'decreasing'], - dflt: 'increasing', - - editType: 'calc', - - }, - - currentbin: { - valType: 'enumerated', - values: ['include', 'exclude', 'half'], - dflt: 'include', - - editType: 'calc', - - }, - editType: 'calc' - }, - nbinsx: { - valType: 'integer', - min: 0, - dflt: 0, - - editType: 'calc', - - }, - xbins: makeBinAttrs('x', true), - - nbinsy: { - valType: 'integer', - min: 0, - dflt: 0, - - editType: 'calc', - - }, - ybins: makeBinAttrs('y', true), - autobinx: { - valType: 'boolean', - dflt: null, - - editType: 'calc', - - }, - autobiny: { - valType: 'boolean', - dflt: null, - - editType: 'calc', - - }, - - bingroup: { - valType: 'string', - - dflt: '', - editType: 'calc', - - }, - - hovertemplate: hovertemplateAttrs({}, { - keys: constants.eventDataKeys - }), - - marker: barAttrs.marker, - - offsetgroup: barAttrs.offsetgroup, - alignmentgroup: barAttrs.alignmentgroup, - - selected: barAttrs.selected, - unselected: barAttrs.unselected, - - _deprecated: { - bardir: barAttrs._deprecated.bardir - } -}; - -},{"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../bar/attributes":857,"./bin_attributes":1021,"./constants":1025}],1020:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -module.exports = function doAvg(size, counts) { - var nMax = size.length; - var total = 0; - for(var i = 0; i < nMax; i++) { - if(counts[i]) { - size[i] /= counts[i]; - total += size[i]; - } else size[i] = null; - } - return total; -}; - -},{}],1021:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function makeBinAttrs(axLetter, match) { - return { - start: { - valType: 'any', // for date axes - - editType: 'calc', - - }, - end: { - valType: 'any', // for date axes - - editType: 'calc', - - }, - size: { - valType: 'any', // for date axes - - editType: 'calc', - - }, - editType: 'calc' - }; -}; - -},{}],1022:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - - -module.exports = { - count: function(n, i, size) { - size[n]++; - return 1; - }, - - sum: function(n, i, size, counterData) { - var v = counterData[i]; - if(isNumeric(v)) { - v = Number(v); - size[n] += v; - return v; - } - return 0; - }, - - avg: function(n, i, size, counterData, counts) { - var v = counterData[i]; - if(isNumeric(v)) { - v = Number(v); - size[n] += v; - counts[n]++; - } - return 0; - }, - - min: function(n, i, size, counterData) { - var v = counterData[i]; - if(isNumeric(v)) { - v = Number(v); - if(!isNumeric(size[n])) { - size[n] = v; - return v; - } else if(size[n] > v) { - var delta = v - size[n]; - size[n] = v; - return delta; - } - } - return 0; - }, - - max: function(n, i, size, counterData) { - var v = counterData[i]; - if(isNumeric(v)) { - v = Number(v); - if(!isNumeric(size[n])) { - size[n] = v; - return v; - } else if(size[n] < v) { - var delta = v - size[n]; - size[n] = v; - return delta; - } - } - return 0; - } -}; - -},{"fast-isnumeric":225}],1023:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var numConstants = _dereq_('../../constants/numerical'); -var oneYear = numConstants.ONEAVGYEAR; -var oneMonth = numConstants.ONEAVGMONTH; -var oneDay = numConstants.ONEDAY; -var oneHour = numConstants.ONEHOUR; -var oneMin = numConstants.ONEMIN; -var oneSec = numConstants.ONESEC; -var tickIncrement = _dereq_('../../plots/cartesian/axes').tickIncrement; - - -/* - * make a function that will find rounded bin edges - * @param {number} leftGap: how far from the left edge of any bin is the closest data value? - * @param {number} rightGap: how far from the right edge of any bin is the closest data value? - * @param {Array[number]} binEdges: the actual edge values used in binning - * @param {object} pa: the position axis - * @param {string} calendar: the data calendar - * - * @return {function(v, isRightEdge)}: - * find the start (isRightEdge is falsy) or end (truthy) label value for a bin edge `v` - */ -module.exports = function getBinSpanLabelRound(leftGap, rightGap, binEdges, pa, calendar) { - // the rounding digit is the largest digit that changes in *all* of 4 regions: - // - inside the rightGap before binEdges[0] (shifted 10% to the left) - // - inside the leftGap after binEdges[0] (expanded by 10% of rightGap on each end) - // - same for binEdges[1] - var dv0 = -1.1 * rightGap; - var dv1 = -0.1 * rightGap; - var dv2 = leftGap - dv1; - var edge0 = binEdges[0]; - var edge1 = binEdges[1]; - var leftDigit = Math.min( - biggestDigitChanged(edge0 + dv1, edge0 + dv2, pa, calendar), - biggestDigitChanged(edge1 + dv1, edge1 + dv2, pa, calendar) - ); - var rightDigit = Math.min( - biggestDigitChanged(edge0 + dv0, edge0 + dv1, pa, calendar), - biggestDigitChanged(edge1 + dv0, edge1 + dv1, pa, calendar) - ); - - // normally we try to make the label for the right edge different from - // the left edge label, so it's unambiguous which bin gets data on the edge. - // but if this results in more than 3 extra digits (or for dates, more than - // 2 fields ie hr&min or min&sec, which is 3600x), it'll be more clutter than - // useful so keep the label cleaner instead - var digit, disambiguateEdges; - if(leftDigit > rightDigit && rightDigit < Math.abs(edge1 - edge0) / 4000) { - digit = leftDigit; - disambiguateEdges = false; - } else { - digit = Math.min(leftDigit, rightDigit); - disambiguateEdges = true; - } - - if(pa.type === 'date' && digit > oneDay) { - var dashExclude = (digit === oneYear) ? 1 : 6; - var increment = (digit === oneYear) ? 'M12' : 'M1'; - - return function(v, isRightEdge) { - var dateStr = pa.c2d(v, oneYear, calendar); - var dashPos = dateStr.indexOf('-', dashExclude); - if(dashPos > 0) dateStr = dateStr.substr(0, dashPos); - var roundedV = pa.d2c(dateStr, 0, calendar); - - if(roundedV < v) { - var nextV = tickIncrement(roundedV, increment, false, calendar); - if((roundedV + nextV) / 2 < v + leftGap) roundedV = nextV; - } - - if(isRightEdge && disambiguateEdges) { - return tickIncrement(roundedV, increment, true, calendar); - } - - return roundedV; - }; - } - - return function(v, isRightEdge) { - var roundedV = digit * Math.round(v / digit); - // if we rounded down and we could round up and still be < leftGap - // (or what leftGap values round to), do that - if(roundedV + (digit / 10) < v && roundedV + (digit * 0.9) < v + leftGap) { - roundedV += digit; - } - // finally for the right edge back off one digit - but only if we can do that - // and not clip off any data that's potentially in the bin - if(isRightEdge && disambiguateEdges) { - roundedV -= digit; - } - return roundedV; - }; -}; - -/* - * Find the largest digit that changes within a (calcdata) region [v1, v2] - * if dates, "digit" means date/time part when it's bigger than a second - * returns the unit value to round to this digit, eg 0.01 to round to hundredths, or - * 100 to round to hundreds. returns oneMonth or oneYear for month or year rounding, - * so that Math.min will work, rather than 'M1' and 'M12' - */ -function biggestDigitChanged(v1, v2, pa, calendar) { - // are we crossing zero? can't say anything. - // in principle this doesn't apply to dates but turns out this doesn't matter. - if(v1 * v2 <= 0) return Infinity; - - var dv = Math.abs(v2 - v1); - var isDate = pa.type === 'date'; - var digit = biggestGuaranteedDigitChanged(dv, isDate); - // see if a larger digit also changed - for(var i = 0; i < 10; i++) { - // numbers: next digit needs to be >10x but <100x then gets rounded down. - // dates: next digit can be as much as 60x (then rounded down) - var nextDigit = biggestGuaranteedDigitChanged(digit * 80, isDate); - // if we get to years, the chain stops - if(digit === nextDigit) break; - if(didDigitChange(nextDigit, v1, v2, isDate, pa, calendar)) digit = nextDigit; - else break; - } - return digit; -} - -/* - * Find the largest digit that *definitely* changes in a region [v, v + dv] for any v - * for nonuniform date regions (months/years) pick the largest - */ -function biggestGuaranteedDigitChanged(dv, isDate) { - if(isDate && dv > oneSec) { - // this is supposed to be the biggest *guaranteed* change - // so compare to the longest month and year across any calendar, - // and we'll iterate back up later - // note: does not support rounding larger than one year. We could add - // that if anyone wants it, but seems unusual and not strictly necessary. - if(dv > oneDay) { - if(dv > oneYear * 1.1) return oneYear; - if(dv > oneMonth * 1.1) return oneMonth; - return oneDay; - } - - if(dv > oneHour) return oneHour; - if(dv > oneMin) return oneMin; - return oneSec; - } - return Math.pow(10, Math.floor(Math.log(dv) / Math.LN10)); -} - -function didDigitChange(digit, v1, v2, isDate, pa, calendar) { - if(isDate && digit > oneDay) { - var dateParts1 = dateParts(v1, pa, calendar); - var dateParts2 = dateParts(v2, pa, calendar); - var parti = (digit === oneYear) ? 0 : 1; - return dateParts1[parti] !== dateParts2[parti]; - } - return Math.floor(v2 / digit) - Math.floor(v1 / digit) > 0.1; -} - -function dateParts(v, pa, calendar) { - var parts = pa.c2d(v, oneYear, calendar).split('-'); - if(parts[0] === '') { - parts.unshift(); - parts[0] = '-' + parts[0]; - } - return parts; -} - -},{"../../constants/numerical":695,"../../plots/cartesian/axes":767}],1024:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); -var Axes = _dereq_('../../plots/cartesian/axes'); - -var arraysToCalcdata = _dereq_('../bar/arrays_to_calcdata'); -var binFunctions = _dereq_('./bin_functions'); -var normFunctions = _dereq_('./norm_functions'); -var doAvg = _dereq_('./average'); -var getBinSpanLabelRound = _dereq_('./bin_label_vals'); - -function calc(gd, trace) { - var pos = []; - var size = []; - var pa = Axes.getFromId(gd, trace.orientation === 'h' ? trace.yaxis : trace.xaxis); - var mainData = trace.orientation === 'h' ? 'y' : 'x'; - var counterData = {x: 'y', y: 'x'}[mainData]; - var calendar = trace[mainData + 'calendar']; - var cumulativeSpec = trace.cumulative; - var i; - - var binsAndPos = calcAllAutoBins(gd, trace, pa, mainData); - var binSpec = binsAndPos[0]; - var pos0 = binsAndPos[1]; - - var nonuniformBins = typeof binSpec.size === 'string'; - var binEdges = []; - var bins = nonuniformBins ? binEdges : binSpec; - // make the empty bin array - var inc = []; - var counts = []; - var inputPoints = []; - var total = 0; - var norm = trace.histnorm; - var func = trace.histfunc; - var densityNorm = norm.indexOf('density') !== -1; - var i2, binEnd, n; - - if(cumulativeSpec.enabled && densityNorm) { - // we treat "cumulative" like it means "integral" if you use a density norm, - // which in the end means it's the same as without "density" - norm = norm.replace(/ ?density$/, ''); - densityNorm = false; - } - - var extremeFunc = func === 'max' || func === 'min'; - var sizeInit = extremeFunc ? null : 0; - var binFunc = binFunctions.count; - var normFunc = normFunctions[norm]; - var isAvg = false; - var pr2c = function(v) { return pa.r2c(v, 0, calendar); }; - var rawCounterData; - - if(Lib.isArrayOrTypedArray(trace[counterData]) && func !== 'count') { - rawCounterData = trace[counterData]; - isAvg = func === 'avg'; - binFunc = binFunctions[func]; - } - - // create the bins (and any extra arrays needed) - // assume more than 1e6 bins is an error, so we don't crash the browser - i = pr2c(binSpec.start); - - // decrease end a little in case of rounding errors - binEnd = pr2c(binSpec.end) + (i - Axes.tickIncrement(i, binSpec.size, false, calendar)) / 1e6; - - while(i < binEnd && pos.length < 1e6) { - i2 = Axes.tickIncrement(i, binSpec.size, false, calendar); - pos.push((i + i2) / 2); - size.push(sizeInit); - inputPoints.push([]); - // nonuniform bins (like months) we need to search, - // rather than straight calculate the bin we're in - binEdges.push(i); - // nonuniform bins also need nonuniform normalization factors - if(densityNorm) inc.push(1 / (i2 - i)); - if(isAvg) counts.push(0); - // break to avoid infinite loops - if(i2 <= i) break; - i = i2; - } - binEdges.push(i); - - // for date axes we need bin bounds to be calcdata. For nonuniform bins - // we already have this, but uniform with start/end/size they're still strings. - if(!nonuniformBins && pa.type === 'date') { - bins = { - start: pr2c(bins.start), - end: pr2c(bins.end), - size: bins.size - }; - } - - // bin the data - // and make histogram-specific pt-number-to-cd-index map object - var nMax = size.length; - var uniqueValsPerBin = true; - var leftGap = Infinity; - var rightGap = Infinity; - var ptNumber2cdIndex = {}; - for(i = 0; i < pos0.length; i++) { - var posi = pos0[i]; - n = Lib.findBin(posi, bins); - if(n >= 0 && n < nMax) { - total += binFunc(n, i, size, rawCounterData, counts); - if(uniqueValsPerBin && inputPoints[n].length && posi !== pos0[inputPoints[n][0]]) { - uniqueValsPerBin = false; - } - inputPoints[n].push(i); - ptNumber2cdIndex[i] = n; - - leftGap = Math.min(leftGap, posi - binEdges[n]); - rightGap = Math.min(rightGap, binEdges[n + 1] - posi); - } - } - - var roundFn; - if(!uniqueValsPerBin) { - roundFn = getBinSpanLabelRound(leftGap, rightGap, binEdges, pa, calendar); - } - - // average and/or normalize the data, if needed - if(isAvg) total = doAvg(size, counts); - if(normFunc) normFunc(size, total, inc); - - // after all normalization etc, now we can accumulate if desired - if(cumulativeSpec.enabled) cdf(size, cumulativeSpec.direction, cumulativeSpec.currentbin); - - var seriesLen = Math.min(pos.length, size.length); - var cd = []; - var firstNonzero = 0; - var lastNonzero = seriesLen - 1; - - // look for empty bins at the ends to remove, so autoscale omits them - for(i = 0; i < seriesLen; i++) { - if(size[i]) { - firstNonzero = i; - break; - } - } - for(i = seriesLen - 1; i >= firstNonzero; i--) { - if(size[i]) { - lastNonzero = i; - break; - } - } - - // create the "calculated data" to plot - for(i = firstNonzero; i <= lastNonzero; i++) { - if((isNumeric(pos[i]) && isNumeric(size[i]))) { - var cdi = { - p: pos[i], - s: size[i], - b: 0 - }; - - // setup hover and event data fields, - // N.B. pts and "hover" positions ph0/ph1 don't seem to make much sense - // for cumulative distributions - if(!cumulativeSpec.enabled) { - cdi.pts = inputPoints[i]; - if(uniqueValsPerBin) { - cdi.ph0 = cdi.ph1 = (inputPoints[i].length) ? pos0[inputPoints[i][0]] : pos[i]; - } else { - cdi.ph0 = roundFn(binEdges[i]); - cdi.ph1 = roundFn(binEdges[i + 1], true); - } - } - cd.push(cdi); - } - } - - if(cd.length === 1) { - // when we collapse to a single bin, calcdata no longer describes bin size - // so we need to explicitly specify it - cd[0].width1 = Axes.tickIncrement(cd[0].p, binSpec.size, false, calendar) - cd[0].p; - } - - arraysToCalcdata(cd, trace); - - if(Lib.isArrayOrTypedArray(trace.selectedpoints)) { - Lib.tagSelected(cd, trace, ptNumber2cdIndex); - } - - return cd; -} - -/* - * calcAllAutoBins: we want all histograms inside the same bingroup - * (see logic in Histogram.crossTraceDefaults) to share bin specs - * - * If the user has explicitly specified differing - * bin specs, there's nothing we can do, but if possible we will try to use the - * smallest bins of any of the auto values for all histograms inside the same - * bingroup. - */ -function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) { - var binAttr = mainData + 'bins'; - var fullLayout = gd._fullLayout; - var groupName = trace['_' + mainData + 'bingroup']; - var binOpts = fullLayout._histogramBinOpts[groupName]; - var isOverlay = fullLayout.barmode === 'overlay'; - var i, traces, tracei, calendar, pos0, autoVals, cumulativeSpec; - - var r2c = function(v) { return pa.r2c(v, 0, calendar); }; - var c2r = function(v) { return pa.c2r(v, 0, calendar); }; - - var cleanBound = pa.type === 'date' ? - function(v) { return (v || v === 0) ? Lib.cleanDate(v, null, calendar) : null; } : - function(v) { return isNumeric(v) ? Number(v) : null; }; - - function setBound(attr, bins, newBins) { - if(bins[attr + 'Found']) { - bins[attr] = cleanBound(bins[attr]); - if(bins[attr] === null) bins[attr] = newBins[attr]; - } else { - autoVals[attr] = bins[attr] = newBins[attr]; - Lib.nestedProperty(traces[0], binAttr + '.' + attr).set(newBins[attr]); - } - } - - // all but the first trace in this group has already been marked finished - // clear this flag, so next time we run calc we will run autobin again - if(trace['_' + mainData + 'autoBinFinished']) { - delete trace['_' + mainData + 'autoBinFinished']; - } else { - traces = binOpts.traces; - var allPos = []; - - // Note: we're including `legendonly` traces here for autobin purposes, - // so that showing & hiding from the legend won't affect bins. - // But this complicates things a bit since those traces don't `calc`, - // hence `isFirstVisible`. - var isFirstVisible = true; - var has2dMap = false; - var hasHist2dContour = false; - for(i = 0; i < traces.length; i++) { - tracei = traces[i]; - - if(tracei.visible) { - var mainDatai = binOpts.dirs[i]; - pos0 = tracei['_' + mainDatai + 'pos0'] = pa.makeCalcdata(tracei, mainDatai); - - allPos = Lib.concat(allPos, pos0); - delete tracei['_' + mainData + 'autoBinFinished']; - - if(trace.visible === true) { - if(isFirstVisible) { - isFirstVisible = false; - } else { - delete tracei._autoBin; - tracei['_' + mainData + 'autoBinFinished'] = 1; - } - if(Registry.traceIs(tracei, '2dMap')) { - has2dMap = true; - } - if(tracei.type === 'histogram2dcontour') { - hasHist2dContour = true; - } - } - } - } - - calendar = traces[0][mainData + 'calendar']; - var newBinSpec = Axes.autoBin(allPos, pa, binOpts.nbins, has2dMap, calendar, binOpts.sizeFound && binOpts.size); - - var autoBin = traces[0]._autoBin = {}; - autoVals = autoBin[binOpts.dirs[0]] = {}; - - if(hasHist2dContour) { - // the "true" 2nd argument reverses the tick direction (which we can't - // just do with a minus sign because of month bins) - if(!binOpts.size) { - newBinSpec.start = c2r(Axes.tickIncrement( - r2c(newBinSpec.start), newBinSpec.size, true, calendar)); - } - if(binOpts.end === undefined) { - newBinSpec.end = c2r(Axes.tickIncrement( - r2c(newBinSpec.end), newBinSpec.size, false, calendar)); - } - } - - // Edge case: single-valued histogram overlaying others - // Use them all together to calculate the bin size for the single-valued one - if(isOverlay && !Registry.traceIs(trace, '2dMap') && newBinSpec._dataSpan === 0 && - pa.type !== 'category' && pa.type !== 'multicategory') { - // Several single-valued histograms! Stop infinite recursion, - // just return an extra flag that tells handleSingleValueOverlays - // to sort out this trace too - if(_overlayEdgeCase) return [newBinSpec, pos0, true]; - - newBinSpec = handleSingleValueOverlays(gd, trace, pa, mainData, binAttr); - } - - // adjust for CDF edge cases - cumulativeSpec = tracei.cumulative || {}; - if(cumulativeSpec.enabled && (cumulativeSpec.currentbin !== 'include')) { - if(cumulativeSpec.direction === 'decreasing') { - newBinSpec.start = c2r(Axes.tickIncrement( - r2c(newBinSpec.start), newBinSpec.size, true, calendar)); - } else { - newBinSpec.end = c2r(Axes.tickIncrement( - r2c(newBinSpec.end), newBinSpec.size, false, calendar)); - } - } - - binOpts.size = newBinSpec.size; - if(!binOpts.sizeFound) { - autoVals.size = newBinSpec.size; - Lib.nestedProperty(traces[0], binAttr + '.size').set(newBinSpec.size); - } - - setBound('start', binOpts, newBinSpec); - setBound('end', binOpts, newBinSpec); - } - - pos0 = trace['_' + mainData + 'pos0']; - delete trace['_' + mainData + 'pos0']; - - // Each trace can specify its own start/end, or if omitted - // we ensure they're beyond the bounds of this trace's data, - // and we need to make sure start is aligned with the main start - var traceInputBins = trace._input[binAttr] || {}; - var traceBinOptsCalc = Lib.extendFlat({}, binOpts); - var mainStart = binOpts.start; - var startIn = pa.r2l(traceInputBins.start); - var hasStart = startIn !== undefined; - if((binOpts.startFound || hasStart) && startIn !== pa.r2l(mainStart)) { - // We have an explicit start to reconcile across traces - // if this trace has an explicit start, shift it down to a bin edge - // if another trace had an explicit start, shift it down to a - // bin edge past our data - var traceStart = hasStart ? - startIn : - Lib.aggNums(Math.min, null, pos0); - - var dummyAx = { - type: (pa.type === 'category' || pa.type === 'multicategory') ? 'linear' : pa.type, - r2l: pa.r2l, - dtick: binOpts.size, - tick0: mainStart, - calendar: calendar, - range: ([traceStart, Axes.tickIncrement(traceStart, binOpts.size, false, calendar)]).map(pa.l2r) - }; - var newStart = Axes.tickFirst(dummyAx); - if(newStart > pa.r2l(traceStart)) { - newStart = Axes.tickIncrement(newStart, binOpts.size, true, calendar); - } - traceBinOptsCalc.start = pa.l2r(newStart); - if(!hasStart) Lib.nestedProperty(trace, binAttr + '.start').set(traceBinOptsCalc.start); - } - - var mainEnd = binOpts.end; - var endIn = pa.r2l(traceInputBins.end); - var hasEnd = endIn !== undefined; - if((binOpts.endFound || hasEnd) && endIn !== pa.r2l(mainEnd)) { - // Reconciling an explicit end is easier, as it doesn't need to - // match bin edges - var traceEnd = hasEnd ? - endIn : - Lib.aggNums(Math.max, null, pos0); - - traceBinOptsCalc.end = pa.l2r(traceEnd); - if(!hasEnd) Lib.nestedProperty(trace, binAttr + '.start').set(traceBinOptsCalc.end); - } - - // Backward compatibility for one-time autobinning. - // autobin: true is handled in cleanData, but autobin: false - // needs to be here where we have determined the values. - var autoBinAttr = 'autobin' + mainData; - if(trace._input[autoBinAttr] === false) { - trace._input[binAttr] = Lib.extendFlat({}, trace[binAttr] || {}); - delete trace._input[autoBinAttr]; - delete trace[autoBinAttr]; - } - - return [traceBinOptsCalc, pos0]; -} - -/* - * Adjust single-value histograms in overlay mode to make as good a - * guess as we can at autobin values the user would like. - * - * Returns the binSpec for the trace that sparked all this - */ -function handleSingleValueOverlays(gd, trace, pa, mainData, binAttr) { - var fullLayout = gd._fullLayout; - var overlaidTraceGroup = getConnectedHistograms(gd, trace); - var pastThisTrace = false; - var minSize = Infinity; - var singleValuedTraces = [trace]; - var i, tracei, binOpts; - - // first collect all the: - // - min bin size from all multi-valued traces - // - single-valued traces - for(i = 0; i < overlaidTraceGroup.length; i++) { - tracei = overlaidTraceGroup[i]; - - if(tracei === trace) { - pastThisTrace = true; - } else if(!pastThisTrace) { - // This trace has already had its autobins calculated, so either: - // - it is part of a bingroup - // - it is NOT a single-valued trace - binOpts = fullLayout._histogramBinOpts[tracei['_' + mainData + 'bingroup']]; - minSize = Math.min(minSize, binOpts.size || tracei[binAttr].size); - } else { - var resulti = calcAllAutoBins(gd, tracei, pa, mainData, true); - var binSpeci = resulti[0]; - var isSingleValued = resulti[2]; - - // so we can use this result when we get to tracei in the normal - // course of events, mark it as done and put _pos0 back - tracei['_' + mainData + 'autoBinFinished'] = 1; - tracei['_' + mainData + 'pos0'] = resulti[1]; - - if(isSingleValued) { - singleValuedTraces.push(tracei); - } else { - minSize = Math.min(minSize, binSpeci.size); - } - } - } - - // find the real data values for each single-valued trace - // hunt through pos0 for the first valid value - var dataVals = new Array(singleValuedTraces.length); - for(i = 0; i < singleValuedTraces.length; i++) { - var pos0 = singleValuedTraces[i]['_' + mainData + 'pos0']; - for(var j = 0; j < pos0.length; j++) { - if(pos0[j] !== undefined) { - dataVals[i] = pos0[j]; - break; - } - } - } - - // are ALL traces are single-valued? use the min difference between - // all of their values (which defaults to 1 if there's still only one) - if(!isFinite(minSize)) { - minSize = Lib.distinctVals(dataVals).minDiff; - } - - // now apply the min size we found to all single-valued traces - for(i = 0; i < singleValuedTraces.length; i++) { - tracei = singleValuedTraces[i]; - var calendar = tracei[mainData + 'calendar']; - - var newBins = { - start: pa.c2r(dataVals[i] - minSize / 2, 0, calendar), - end: pa.c2r(dataVals[i] + minSize / 2, 0, calendar), - size: minSize - }; - - tracei._input[binAttr] = tracei[binAttr] = newBins; - - binOpts = fullLayout._histogramBinOpts[tracei['_' + mainData + 'bingroup']]; - if(binOpts) Lib.extendFlat(binOpts, newBins); - } - - return trace[binAttr]; -} - -/* - * Return an array of histograms that share axes and orientation. - * - * Only considers histograms. In principle we could include bars in a - * similar way to how we do manually binned histograms, though this - * would have tons of edge cases and value judgments to make. - */ -function getConnectedHistograms(gd, trace) { - var xid = trace.xaxis; - var yid = trace.yaxis; - var orientation = trace.orientation; - - var out = []; - var fullData = gd._fullData; - for(var i = 0; i < fullData.length; i++) { - var tracei = fullData[i]; - if(tracei.type === 'histogram' && - tracei.visible === true && - tracei.orientation === orientation && - tracei.xaxis === xid && tracei.yaxis === yid - ) { - out.push(tracei); - } - } - - return out; -} - -function cdf(size, direction, currentBin) { - var i, vi, prevSum; - - function firstHalfPoint(i) { - prevSum = size[i]; - size[i] /= 2; - } - - function nextHalfPoint(i) { - vi = size[i]; - size[i] = prevSum + vi / 2; - prevSum += vi; - } - - if(currentBin === 'half') { - if(direction === 'increasing') { - firstHalfPoint(0); - for(i = 1; i < size.length; i++) { - nextHalfPoint(i); - } - } else { - firstHalfPoint(size.length - 1); - for(i = size.length - 2; i >= 0; i--) { - nextHalfPoint(i); - } - } - } else if(direction === 'increasing') { - for(i = 1; i < size.length; i++) { - size[i] += size[i - 1]; - } - - // 'exclude' is identical to 'include' just shifted one bin over - if(currentBin === 'exclude') { - size.unshift(0); - size.pop(); - } - } else { - for(i = size.length - 2; i >= 0; i--) { - size[i] += size[i + 1]; - } - - if(currentBin === 'exclude') { - size.push(0); - size.shift(); - } - } -} - -module.exports = { - calc: calc, - calcAllAutoBins: calcAllAutoBins -}; - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../../registry":847,"../bar/arrays_to_calcdata":856,"./average":1020,"./bin_functions":1022,"./bin_label_vals":1023,"./norm_functions":1031,"fast-isnumeric":225}],1025:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = { - eventDataKeys: ['binNumber'] -}; - -},{}],1026:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var axisIds = _dereq_('../../plots/cartesian/axis_ids'); - -var traceIs = _dereq_('../../registry').traceIs; -var handleGroupingDefaults = _dereq_('../bar/defaults').handleGroupingDefaults; - -var nestedProperty = Lib.nestedProperty; -var getAxisGroup = axisIds.getAxisGroup; - -var BINATTRS = [ - {aStr: {x: 'xbins.start', y: 'ybins.start'}, name: 'start'}, - {aStr: {x: 'xbins.end', y: 'ybins.end'}, name: 'end'}, - {aStr: {x: 'xbins.size', y: 'ybins.size'}, name: 'size'}, - {aStr: {x: 'nbinsx', y: 'nbinsy'}, name: 'nbins'} -]; - -var BINDIRECTIONS = ['x', 'y']; - -// handle bin attrs and relink auto-determined values so fullData is complete -module.exports = function crossTraceDefaults(fullData, fullLayout) { - var allBinOpts = fullLayout._histogramBinOpts = {}; - var histTraces = []; - var mustMatchTracesLookup = {}; - var otherTracesList = []; - - var traceOut, traces, groupName, binDir; - var i, j, k; - - function coerce(attr, dflt) { - return Lib.coerce(traceOut._input, traceOut, traceOut._module.attributes, attr, dflt); - } - - function orientation2binDir(traceOut) { - return traceOut.orientation === 'v' ? 'x' : 'y'; - } - - function getAxisType(traceOut, binDir) { - var ax = axisIds.getFromTrace({_fullLayout: fullLayout}, traceOut, binDir); - return ax.type; - } - - function fillBinOpts(traceOut, groupName, binDir) { - // N.B. group traces that don't have a bingroup with themselves - var fallbackGroupName = traceOut.uid + '__' + binDir; - if(!groupName) groupName = fallbackGroupName; - - var axType = getAxisType(traceOut, binDir); - var calendar = traceOut[binDir + 'calendar']; - var binOpts = allBinOpts[groupName]; - var needsNewItem = true; - - if(binOpts) { - if(axType === binOpts.axType && calendar === binOpts.calendar) { - needsNewItem = false; - binOpts.traces.push(traceOut); - binOpts.dirs.push(binDir); - } else { - groupName = fallbackGroupName; - - if(axType !== binOpts.axType) { - Lib.warn([ - 'Attempted to group the bins of trace', traceOut.index, - 'set on a', 'type:' + axType, 'axis', - 'with bins on', 'type:' + binOpts.axType, 'axis.' - ].join(' ')); - } - if(calendar !== binOpts.calendar) { - // prohibit bingroup for traces using different calendar, - // there's probably a way to make this work, but skip for now - Lib.warn([ - 'Attempted to group the bins of trace', traceOut.index, - 'set with a', calendar, 'calendar', - 'with bins', - (binOpts.calendar ? 'on a ' + binOpts.calendar + ' calendar' : 'w/o a set calendar') - ].join(' ')); - } - } - } - - if(needsNewItem) { - allBinOpts[groupName] = { - traces: [traceOut], - dirs: [binDir], - axType: axType, - calendar: traceOut[binDir + 'calendar'] || '' - }; - } - traceOut['_' + binDir + 'bingroup'] = groupName; - } - - for(i = 0; i < fullData.length; i++) { - traceOut = fullData[i]; - - if(traceIs(traceOut, 'histogram')) { - histTraces.push(traceOut); - - // TODO: this shouldn't be relinked as it's only used within calc - // https://github.com/plotly/plotly.js/issues/749 - delete traceOut._xautoBinFinished; - delete traceOut._yautoBinFinished; - - // N.B. need to coerce *alignmentgroup* before *bingroup*, as traces - // in same alignmentgroup "have to match" - if(!traceIs(traceOut, '2dMap')) { - handleGroupingDefaults(traceOut._input, traceOut, fullLayout, coerce); - } - } - } - - var alignmentOpts = fullLayout._alignmentOpts || {}; - - // Look for traces that "have to match", that is: - // - 1d histogram traces on the same subplot with same orientation under barmode:stack, - // - 1d histogram traces on the same subplot with same orientation under barmode:group - // - 1d histogram traces on the same position axis with the same orientation - // and the same *alignmentgroup* (coerced under barmode:group) - // - Once `stackgroup` gets implemented (see https://github.com/plotly/plotly.js/issues/3614), - // traces within the same stackgroup will also "have to match" - for(i = 0; i < histTraces.length; i++) { - traceOut = histTraces[i]; - groupName = ''; - - if(!traceIs(traceOut, '2dMap')) { - binDir = orientation2binDir(traceOut); - - if(fullLayout.barmode === 'group' && traceOut.alignmentgroup) { - var pa = traceOut[binDir + 'axis']; - var aGroupId = getAxisGroup(fullLayout, pa) + traceOut.orientation; - if((alignmentOpts[aGroupId] || {})[traceOut.alignmentgroup]) { - groupName = aGroupId; - } - } - - if(!groupName && fullLayout.barmode !== 'overlay') { - groupName = ( - getAxisGroup(fullLayout, traceOut.xaxis) + - getAxisGroup(fullLayout, traceOut.yaxis) + - orientation2binDir(traceOut) - ); - } - } - - if(groupName) { - if(!mustMatchTracesLookup[groupName]) { - mustMatchTracesLookup[groupName] = []; - } - mustMatchTracesLookup[groupName].push(traceOut); - } else { - otherTracesList.push(traceOut); - } - } - - // Setup binOpts for traces that have to match, - // if the traces have a valid bingroup, use that - // if not use axis+binDir groupName - for(groupName in mustMatchTracesLookup) { - traces = mustMatchTracesLookup[groupName]; - - // no need to 'force' anything when a single - // trace is detected as "must match" - if(traces.length === 1) { - otherTracesList.push(traces[0]); - continue; - } - - var binGroupFound = false; - for(i = 0; i < traces.length; i++) { - traceOut = traces[i]; - binGroupFound = coerce('bingroup'); - break; - } - - groupName = binGroupFound || groupName; - - for(i = 0; i < traces.length; i++) { - traceOut = traces[i]; - var bingroupIn = traceOut._input.bingroup; - if(bingroupIn && bingroupIn !== groupName) { - Lib.warn([ - 'Trace', traceOut.index, 'must match', - 'within bingroup', groupName + '.', - 'Ignoring its bingroup:', bingroupIn, 'setting.' - ].join(' ')); - } - traceOut.bingroup = groupName; - - // N.B. no need to worry about 2dMap case - // (where both bin direction are set in each trace) - // as 2dMap trace never "have to match" - fillBinOpts(traceOut, groupName, orientation2binDir(traceOut)); - } - } - - // setup binOpts for traces that can but don't have to match, - // notice that these traces can be matched with traces that have to match - for(i = 0; i < otherTracesList.length; i++) { - traceOut = otherTracesList[i]; - - var binGroup = coerce('bingroup'); - - if(traceIs(traceOut, '2dMap')) { - for(k = 0; k < 2; k++) { - binDir = BINDIRECTIONS[k]; - var binGroupInDir = coerce(binDir + 'bingroup', - binGroup ? binGroup + '__' + binDir : null - ); - fillBinOpts(traceOut, binGroupInDir, binDir); - } - } else { - fillBinOpts(traceOut, binGroup, orientation2binDir(traceOut)); - } - } - - // coerce bin attrs! - for(groupName in allBinOpts) { - var binOpts = allBinOpts[groupName]; - traces = binOpts.traces; - - for(j = 0; j < BINATTRS.length; j++) { - var attrSpec = BINATTRS[j]; - var attr = attrSpec.name; - var aStr; - var autoVals; - - // nbins(x|y) is moot if we have a size. This depends on - // nbins coming after size in binAttrs. - if(attr === 'nbins' && binOpts.sizeFound) continue; - - for(i = 0; i < traces.length; i++) { - traceOut = traces[i]; - binDir = binOpts.dirs[i]; - aStr = attrSpec.aStr[binDir]; - - if(nestedProperty(traceOut._input, aStr).get() !== undefined) { - binOpts[attr] = coerce(aStr); - binOpts[attr + 'Found'] = true; - break; - } - - autoVals = (traceOut._autoBin || {})[binDir] || {}; - if(autoVals[attr]) { - // if this is the *first* autoval - nestedProperty(traceOut, aStr).set(autoVals[attr]); - } - } - - // start and end we need to coerce anyway, after having collected the - // first of each into binOpts, in case a trace wants to restrict its - // data to a certain range - if(attr === 'start' || attr === 'end') { - for(; i < traces.length; i++) { - traceOut = traces[i]; - if(traceOut['_' + binDir + 'bingroup']) { - autoVals = (traceOut._autoBin || {})[binDir] || {}; - coerce(aStr, autoVals[attr]); - } - } - } - - if(attr === 'nbins' && !binOpts.sizeFound && !binOpts.nbinsFound) { - traceOut = traces[0]; - binOpts[attr] = coerce(aStr); - } - } - } -}; - -},{"../../lib":719,"../../plots/cartesian/axis_ids":770,"../../registry":847,"../bar/defaults":861}],1027:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); - -var handleStyleDefaults = _dereq_('../bar/style_defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var x = coerce('x'); - var y = coerce('y'); - - var cumulative = coerce('cumulative.enabled'); - if(cumulative) { - coerce('cumulative.direction'); - coerce('cumulative.currentbin'); - } - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - var orientation = coerce('orientation', (y && !x) ? 'h' : 'v'); - var sampleLetter = orientation === 'v' ? 'x' : 'y'; - var aggLetter = orientation === 'v' ? 'y' : 'x'; - - var len = (x && y) ? - Math.min(Lib.minRowLength(x) && Lib.minRowLength(y)) : - Lib.minRowLength(traceOut[sampleLetter] || []); - - if(!len) { - traceOut.visible = false; - return; - } - - traceOut._length = len; - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout); - - var hasAggregationData = traceOut[aggLetter]; - if(hasAggregationData) coerce('histfunc'); - coerce('histnorm'); - - // Note: bin defaults are now handled in Histogram.crossTraceDefaults - // autobin(x|y) are only included here to appease Plotly.validate - coerce('autobin' + sampleLetter); - - handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); - - var lineColor = (traceOut.marker.line || {}).color; - - // override defaultColor for error bars with defaultLine - var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'y'}); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'x', inherit: 'y'}); -}; - -},{"../../components/color":593,"../../lib":719,"../../registry":847,"../bar/style_defaults":871,"./attributes":1019}],1028:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function eventData(out, pt, trace, cd, pointNumber) { - // standard cartesian event data - out.x = 'xVal' in pt ? pt.xVal : pt.x; - out.y = 'yVal' in pt ? pt.yVal : pt.y; - - // for 2d histograms - if('zLabelVal' in pt) out.z = pt.zLabelVal; - - if(pt.xa) out.xaxis = pt.xa; - if(pt.ya) out.yaxis = pt.ya; - - // specific to histogram - CDFs do not have pts (yet?) - if(!(trace.cumulative || {}).enabled) { - var pts = Array.isArray(pointNumber) ? - cd[0].pts[pointNumber[0]][pointNumber[1]] : - cd[pointNumber].pts; - - out.pointNumbers = pts; - out.binNumber = out.pointNumber; - delete out.pointNumber; - delete out.pointIndex; - - var pointIndices; - if(trace._indexToPoints) { - pointIndices = []; - for(var i = 0; i < pts.length; i++) { - pointIndices = pointIndices.concat(trace._indexToPoints[pts[i]]); - } - } else { - pointIndices = pts; - } - - out.pointIndices = pointIndices; - } - - return out; -}; - -},{}],1029:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var barHover = _dereq_('../bar/hover').hoverPoints; -var hoverLabelText = _dereq_('../../plots/cartesian/axes').hoverLabelText; - -module.exports = function hoverPoints(pointData, xval, yval, hovermode) { - var pts = barHover(pointData, xval, yval, hovermode); - - if(!pts) return; - - pointData = pts[0]; - var di = pointData.cd[pointData.index]; - var trace = pointData.cd[0].trace; - - if(!trace.cumulative.enabled) { - var posLetter = trace.orientation === 'h' ? 'y' : 'x'; - - pointData[posLetter + 'Label'] = hoverLabelText(pointData[posLetter + 'a'], di.ph0, di.ph1); - } - - if(trace.hovermplate) pointData.hovertemplate = trace.hovertemplate; - - return pts; -}; - -},{"../../plots/cartesian/axes":767,"../bar/hover":863}],1030:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** - * Histogram has its own attribute, defaults and calc steps, - * but uses bar's plot to display - * and bar's crossTraceCalc (formerly known as setPositions) for stacking and grouping - */ - -/** - * histogram errorBarsOK is debatable, but it's put in for backward compat. - * there are use cases for it - sqrt for a simple histogram works right now, - * constant and % work but they're not so meaningful. I guess it could be cool - * to allow quadrature combination of errors in summed histograms... - */ - -module.exports = { - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('../bar/layout_attributes'), - supplyDefaults: _dereq_('./defaults'), - crossTraceDefaults: _dereq_('./cross_trace_defaults'), - supplyLayoutDefaults: _dereq_('../bar/layout_defaults'), - calc: _dereq_('./calc').calc, - crossTraceCalc: _dereq_('../bar/cross_trace_calc').crossTraceCalc, - plot: _dereq_('../bar/plot').plot, - layerName: 'barlayer', - style: _dereq_('../bar/style').style, - styleOnSelect: _dereq_('../bar/style').styleOnSelect, - colorbar: _dereq_('../scatter/marker_colorbar'), - hoverPoints: _dereq_('./hover'), - selectPoints: _dereq_('../bar/select'), - eventData: _dereq_('./event_data'), - - moduleType: 'trace', - name: 'histogram', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['bar-like', 'cartesian', 'svg', 'bar', 'histogram', 'oriented', 'errorBarsOK', 'showLegend'], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"../bar/cross_trace_calc":860,"../bar/layout_attributes":865,"../bar/layout_defaults":866,"../bar/plot":867,"../bar/select":868,"../bar/style":870,"../scatter/marker_colorbar":1129,"./attributes":1019,"./calc":1024,"./cross_trace_defaults":1026,"./defaults":1027,"./event_data":1028,"./hover":1029}],1031:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -module.exports = { - percent: function(size, total) { - var nMax = size.length; - var norm = 100 / total; - for(var n = 0; n < nMax; n++) size[n] *= norm; - }, - probability: function(size, total) { - var nMax = size.length; - for(var n = 0; n < nMax; n++) size[n] /= total; - }, - density: function(size, total, inc, yinc) { - var nMax = size.length; - yinc = yinc || 1; - for(var n = 0; n < nMax; n++) size[n] *= inc[n] * yinc; - }, - 'probability density': function(size, total, inc, yinc) { - var nMax = size.length; - if(yinc) total /= yinc; - for(var n = 0; n < nMax; n++) size[n] *= inc[n] / total; - } -}; - -},{}],1032:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var histogramAttrs = _dereq_('../histogram/attributes'); -var makeBinAttrs = _dereq_('../histogram/bin_attributes'); -var heatmapAttrs = _dereq_('../heatmap/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = extendFlat( - { - x: histogramAttrs.x, - y: histogramAttrs.y, - - z: { - valType: 'data_array', - editType: 'calc', - - }, - marker: { - color: { - valType: 'data_array', - editType: 'calc', - - }, - editType: 'calc' - }, - - histnorm: histogramAttrs.histnorm, - histfunc: histogramAttrs.histfunc, - nbinsx: histogramAttrs.nbinsx, - xbins: makeBinAttrs('x'), - nbinsy: histogramAttrs.nbinsy, - ybins: makeBinAttrs('y'), - autobinx: histogramAttrs.autobinx, - autobiny: histogramAttrs.autobiny, - - bingroup: extendFlat({}, histogramAttrs.bingroup, { - - }), - xbingroup: extendFlat({}, histogramAttrs.bingroup, { - - }), - ybingroup: extendFlat({}, histogramAttrs.bingroup, { - - }), - - xgap: heatmapAttrs.xgap, - ygap: heatmapAttrs.ygap, - zsmooth: heatmapAttrs.zsmooth, - zhoverformat: heatmapAttrs.zhoverformat, - hovertemplate: hovertemplateAttrs({}, {keys: 'z'}) - }, - colorScaleAttrs('', {cLetter: 'z', autoColorDflt: false}) -); - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../heatmap/attributes":1001,"../histogram/attributes":1019,"../histogram/bin_attributes":1021}],1033:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); - -var binFunctions = _dereq_('../histogram/bin_functions'); -var normFunctions = _dereq_('../histogram/norm_functions'); -var doAvg = _dereq_('../histogram/average'); -var getBinSpanLabelRound = _dereq_('../histogram/bin_label_vals'); -var calcAllAutoBins = _dereq_('../histogram/calc').calcAllAutoBins; - -module.exports = function calc(gd, trace) { - var xa = Axes.getFromId(gd, trace.xaxis); - var ya = Axes.getFromId(gd, trace.yaxis); - - var xcalendar = trace.xcalendar; - var ycalendar = trace.ycalendar; - var xr2c = function(v) { return xa.r2c(v, 0, xcalendar); }; - var yr2c = function(v) { return ya.r2c(v, 0, ycalendar); }; - var xc2r = function(v) { return xa.c2r(v, 0, xcalendar); }; - var yc2r = function(v) { return ya.c2r(v, 0, ycalendar); }; - - var i, j, n, m; - - // calculate the bins - var xBinsAndPos = calcAllAutoBins(gd, trace, xa, 'x'); - var xBinSpec = xBinsAndPos[0]; - var xPos0 = xBinsAndPos[1]; - var yBinsAndPos = calcAllAutoBins(gd, trace, ya, 'y'); - var yBinSpec = yBinsAndPos[0]; - var yPos0 = yBinsAndPos[1]; - - var serieslen = trace._length; - if(xPos0.length > serieslen) xPos0.splice(serieslen, xPos0.length - serieslen); - if(yPos0.length > serieslen) yPos0.splice(serieslen, yPos0.length - serieslen); - - // make the empty bin array & scale the map - var z = []; - var onecol = []; - var zerocol = []; - var nonuniformBinsX = typeof xBinSpec.size === 'string'; - var nonuniformBinsY = typeof yBinSpec.size === 'string'; - var xEdges = []; - var yEdges = []; - var xbins = nonuniformBinsX ? xEdges : xBinSpec; - var ybins = nonuniformBinsY ? yEdges : yBinSpec; - var total = 0; - var counts = []; - var inputPoints = []; - var norm = trace.histnorm; - var func = trace.histfunc; - var densitynorm = norm.indexOf('density') !== -1; - var extremefunc = func === 'max' || func === 'min'; - var sizeinit = extremefunc ? null : 0; - var binfunc = binFunctions.count; - var normfunc = normFunctions[norm]; - var doavg = false; - var xinc = []; - var yinc = []; - - // set a binning function other than count? - // for binning functions: check first for 'z', - // then 'mc' in case we had a colored scatter plot - // and want to transfer these colors to the 2D histo - // TODO: axe this, make it the responsibility of the app changing type? or an impliedEdit? - var rawCounterData = ('z' in trace) ? - trace.z : - (('marker' in trace && Array.isArray(trace.marker.color)) ? - trace.marker.color : ''); - if(rawCounterData && func !== 'count') { - doavg = func === 'avg'; - binfunc = binFunctions[func]; - } - - // decrease end a little in case of rounding errors - var xBinSize = xBinSpec.size; - var xBinStart = xr2c(xBinSpec.start); - var xBinEnd = xr2c(xBinSpec.end) + - (xBinStart - Axes.tickIncrement(xBinStart, xBinSize, false, xcalendar)) / 1e6; - - for(i = xBinStart; i < xBinEnd; i = Axes.tickIncrement(i, xBinSize, false, xcalendar)) { - onecol.push(sizeinit); - xEdges.push(i); - if(doavg) zerocol.push(0); - } - xEdges.push(i); - - var nx = onecol.length; - var dx = (i - xBinStart) / nx; - var x0 = xc2r(xBinStart + dx / 2); - - var yBinSize = yBinSpec.size; - var yBinStart = yr2c(yBinSpec.start); - var yBinEnd = yr2c(yBinSpec.end) + - (yBinStart - Axes.tickIncrement(yBinStart, yBinSize, false, ycalendar)) / 1e6; - - for(i = yBinStart; i < yBinEnd; i = Axes.tickIncrement(i, yBinSize, false, ycalendar)) { - z.push(onecol.slice()); - yEdges.push(i); - var ipCol = new Array(nx); - for(j = 0; j < nx; j++) ipCol[j] = []; - inputPoints.push(ipCol); - if(doavg) counts.push(zerocol.slice()); - } - yEdges.push(i); - - var ny = z.length; - var dy = (i - yBinStart) / ny; - var y0 = yc2r(yBinStart + dy / 2); - - if(densitynorm) { - xinc = makeIncrements(onecol.length, xbins, dx, nonuniformBinsX); - yinc = makeIncrements(z.length, ybins, dy, nonuniformBinsY); - } - - // for date axes we need bin bounds to be calcdata. For nonuniform bins - // we already have this, but uniform with start/end/size they're still strings. - if(!nonuniformBinsX && xa.type === 'date') xbins = binsToCalc(xr2c, xbins); - if(!nonuniformBinsY && ya.type === 'date') ybins = binsToCalc(yr2c, ybins); - - // put data into bins - var uniqueValsPerX = true; - var uniqueValsPerY = true; - var xVals = new Array(nx); - var yVals = new Array(ny); - var xGapLow = Infinity; - var xGapHigh = Infinity; - var yGapLow = Infinity; - var yGapHigh = Infinity; - for(i = 0; i < serieslen; i++) { - var xi = xPos0[i]; - var yi = yPos0[i]; - n = Lib.findBin(xi, xbins); - m = Lib.findBin(yi, ybins); - if(n >= 0 && n < nx && m >= 0 && m < ny) { - total += binfunc(n, i, z[m], rawCounterData, counts[m]); - inputPoints[m][n].push(i); - - if(uniqueValsPerX) { - if(xVals[n] === undefined) xVals[n] = xi; - else if(xVals[n] !== xi) uniqueValsPerX = false; - } - if(uniqueValsPerY) { - if(yVals[m] === undefined) yVals[m] = yi; - else if(yVals[m] !== yi) uniqueValsPerY = false; - } - - xGapLow = Math.min(xGapLow, xi - xEdges[n]); - xGapHigh = Math.min(xGapHigh, xEdges[n + 1] - xi); - yGapLow = Math.min(yGapLow, yi - yEdges[m]); - yGapHigh = Math.min(yGapHigh, yEdges[m + 1] - yi); - } - } - // normalize, if needed - if(doavg) { - for(m = 0; m < ny; m++) total += doAvg(z[m], counts[m]); - } - if(normfunc) { - for(m = 0; m < ny; m++) normfunc(z[m], total, xinc, yinc[m]); - } - - return { - x: xPos0, - xRanges: getRanges(xEdges, uniqueValsPerX && xVals, xGapLow, xGapHigh, xa, xcalendar), - x0: x0, - dx: dx, - y: yPos0, - yRanges: getRanges(yEdges, uniqueValsPerY && yVals, yGapLow, yGapHigh, ya, ycalendar), - y0: y0, - dy: dy, - z: z, - pts: inputPoints - }; -}; - -function makeIncrements(len, bins, dv, nonuniform) { - var out = new Array(len); - var i; - if(nonuniform) { - for(i = 0; i < len; i++) out[i] = 1 / (bins[i + 1] - bins[i]); - } else { - var inc = 1 / dv; - for(i = 0; i < len; i++) out[i] = inc; - } - return out; -} - -function binsToCalc(r2c, bins) { - return { - start: r2c(bins.start), - end: r2c(bins.end), - size: bins.size - }; -} - -function getRanges(edges, uniqueVals, gapLow, gapHigh, ax, calendar) { - var i; - var len = edges.length - 1; - var out = new Array(len); - var roundFn = getBinSpanLabelRound(gapLow, gapHigh, edges, ax, calendar); - - for(i = 0; i < len; i++) { - var v = (uniqueVals || [])[i]; - out[i] = v === undefined ? - [roundFn(edges[i]), roundFn(edges[i + 1], true)] : - [v, v]; - } - return out; -} - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../histogram/average":1020,"../histogram/bin_functions":1022,"../histogram/bin_label_vals":1023,"../histogram/calc":1024,"../histogram/norm_functions":1031}],1034:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var handleSampleDefaults = _dereq_('./sample_defaults'); -var handleStyleDefaults = _dereq_('../heatmap/style_defaults'); -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var attributes = _dereq_('./attributes'); - - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - handleSampleDefaults(traceIn, traceOut, coerce, layout); - if(traceOut.visible === false) return; - - handleStyleDefaults(traceIn, traceOut, coerce, layout); - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'z'}); - coerce('hovertemplate'); -}; - -},{"../../components/colorscale/defaults":603,"../../lib":719,"../heatmap/style_defaults":1014,"./attributes":1032,"./sample_defaults":1037}],1035:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var heatmapHover = _dereq_('../heatmap/hover'); -var hoverLabelText = _dereq_('../../plots/cartesian/axes').hoverLabelText; - -module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer, contour) { - var pts = heatmapHover(pointData, xval, yval, hovermode, hoverLayer, contour); - - if(!pts) return; - - pointData = pts[0]; - var indices = pointData.index; - var ny = indices[0]; - var nx = indices[1]; - var cd0 = pointData.cd[0]; - var xRange = cd0.xRanges[nx]; - var yRange = cd0.yRanges[ny]; - - pointData.xLabel = hoverLabelText(pointData.xa, xRange[0], xRange[1]); - pointData.yLabel = hoverLabelText(pointData.ya, yRange[0], yRange[1]); - - return pts; -}; - -},{"../../plots/cartesian/axes":767,"../heatmap/hover":1008}],1036:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - crossTraceDefaults: _dereq_('../histogram/cross_trace_defaults'), - calc: _dereq_('../heatmap/calc'), - plot: _dereq_('../heatmap/plot'), - layerName: 'heatmaplayer', - colorbar: _dereq_('../heatmap/colorbar'), - style: _dereq_('../heatmap/style'), - hoverPoints: _dereq_('./hover'), - eventData: _dereq_('../histogram/event_data'), - - moduleType: 'trace', - name: 'histogram2d', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', '2dMap', 'histogram'], - meta: { - - - } -}; - -},{"../../plots/cartesian":778,"../heatmap/calc":1002,"../heatmap/colorbar":1004,"../heatmap/plot":1012,"../heatmap/style":1013,"../histogram/cross_trace_defaults":1026,"../histogram/event_data":1028,"./attributes":1032,"./defaults":1034,"./hover":1035}],1037:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); - -module.exports = function handleSampleDefaults(traceIn, traceOut, coerce, layout) { - var x = coerce('x'); - var y = coerce('y'); - var xlen = Lib.minRowLength(x); - var ylen = Lib.minRowLength(y); - - // we could try to accept x0 and dx, etc... - // but that's a pretty weird use case. - // for now require both x and y explicitly specified. - if(!xlen || !ylen) { - traceOut.visible = false; - return; - } - - traceOut._length = Math.min(xlen, ylen); - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout); - - // if marker.color is an array, we can use it in aggregation instead of z - var hasAggregationData = coerce('z') || coerce('marker.color'); - - if(hasAggregationData) coerce('histfunc'); - coerce('histnorm'); - - // Note: bin defaults are now handled in Histogram2D.crossTraceDefaults - // autobin(x|y) are only included here to appease Plotly.validate - coerce('autobinx'); - coerce('autobiny'); -}; - -},{"../../lib":719,"../../registry":847}],1038:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var histogram2dAttrs = _dereq_('../histogram2d/attributes'); -var contourAttrs = _dereq_('../contour/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = extendFlat({ - x: histogram2dAttrs.x, - y: histogram2dAttrs.y, - z: histogram2dAttrs.z, - marker: histogram2dAttrs.marker, - - histnorm: histogram2dAttrs.histnorm, - histfunc: histogram2dAttrs.histfunc, - nbinsx: histogram2dAttrs.nbinsx, - xbins: histogram2dAttrs.xbins, - nbinsy: histogram2dAttrs.nbinsy, - ybins: histogram2dAttrs.ybins, - autobinx: histogram2dAttrs.autobinx, - autobiny: histogram2dAttrs.autobiny, - - bingroup: histogram2dAttrs.bingroup, - xbingroup: histogram2dAttrs.xbingroup, - ybingroup: histogram2dAttrs.ybingroup, - - autocontour: contourAttrs.autocontour, - ncontours: contourAttrs.ncontours, - contours: contourAttrs.contours, - line: contourAttrs.line, - zhoverformat: histogram2dAttrs.zhoverformat, - hovertemplate: histogram2dAttrs.hovertemplate -}, - colorScaleAttrs('', { - cLetter: 'z', - editTypeOverride: 'calc' - }) -); - -},{"../../components/colorscale/attributes":600,"../../lib/extend":710,"../contour/attributes":942,"../histogram2d/attributes":1032}],1039:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var handleSampleDefaults = _dereq_('../histogram2d/sample_defaults'); -var handleContoursDefaults = _dereq_('../contour/contours_defaults'); -var handleStyleDefaults = _dereq_('../contour/style_defaults'); -var attributes = _dereq_('./attributes'); - - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - function coerce2(attr) { - return Lib.coerce2(traceIn, traceOut, attributes, attr); - } - - handleSampleDefaults(traceIn, traceOut, coerce, layout); - if(traceOut.visible === false) return; - - handleContoursDefaults(traceIn, traceOut, coerce, coerce2); - handleStyleDefaults(traceIn, traceOut, coerce, layout); - coerce('hovertemplate'); -}; - -},{"../../lib":719,"../contour/contours_defaults":949,"../contour/style_defaults":963,"../histogram2d/sample_defaults":1037,"./attributes":1038}],1040:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - crossTraceDefaults: _dereq_('../histogram/cross_trace_defaults'), - calc: _dereq_('../contour/calc'), - plot: _dereq_('../contour/plot').plot, - layerName: 'contourlayer', - style: _dereq_('../contour/style'), - colorbar: _dereq_('../contour/colorbar'), - hoverPoints: _dereq_('../contour/hover'), - - moduleType: 'trace', - name: 'histogram2dcontour', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', '2dMap', 'contour', 'histogram', 'showLegend'], - meta: { - - - } -}; - -},{"../../plots/cartesian":778,"../contour/calc":943,"../contour/colorbar":945,"../contour/hover":955,"../contour/plot":960,"../contour/style":962,"../histogram/cross_trace_defaults":1026,"./attributes":1038,"./defaults":1039}],1041:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var extendDeep = _dereq_('../../lib/extend').extendDeep; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var fontAttrs = _dereq_('../../plots/font_attributes'); -var colorAttrs = _dereq_('../../components/color/attributes'); -var domainAttrs = _dereq_('../../plots/domain').attributes; -var axesAttrs = _dereq_('../../plots/cartesian/layout_attributes'); -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; -var delta = _dereq_('../../constants/delta.js'); -var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK; - -var textFontAttrs = fontAttrs({ - editType: 'plot', - colorEditType: 'plot' -}); - -var gaugeBarAttrs = { - color: { - valType: 'color', - editType: 'plot', - - - }, - line: { - color: { - valType: 'color', - - dflt: colorAttrs.defaultLine, - editType: 'plot', - - }, - width: { - valType: 'number', - - min: 0, - dflt: 0, - editType: 'plot', - - }, - editType: 'calc' - }, - thickness: { - valType: 'number', - - min: 0, - max: 1, - dflt: 1, - editType: 'plot', - - }, - editType: 'calc' -}; - -var rangeAttr = { - valType: 'info_array', - - items: [ - {valType: 'number', editType: 'plot'}, - {valType: 'number', editType: 'plot'} - ], - editType: 'plot', - -}; - -var stepsAttrs = templatedArray('steps', extendDeep({}, gaugeBarAttrs, { - range: rangeAttr -})); - -module.exports = { - mode: { - valType: 'flaglist', - editType: 'calc', - - flags: ['number', 'delta', 'gauge'], - dflt: 'number', - - }, - value: { - valType: 'number', - editType: 'calc', - - anim: true, - - }, - align: { - valType: 'enumerated', - values: ['left', 'center', 'right'], - - editType: 'plot', - - }, - // position - domain: domainAttrs({name: 'indicator', trace: true, editType: 'calc'}), - - title: { - text: { - valType: 'string', - - editType: 'plot', - - }, - align: { - valType: 'enumerated', - values: ['left', 'center', 'right'], - - editType: 'plot', - - }, - font: extendFlat({}, textFontAttrs, { - - }), - editType: 'plot' - }, - number: { - valueformat: { - valType: 'string', - dflt: '', - - editType: 'plot', - - }, - font: extendFlat({}, textFontAttrs, { - - }), - prefix: { - valType: 'string', - dflt: '', - - editType: 'plot', - - }, - suffix: { - valType: 'string', - dflt: '', - - editType: 'plot', - - }, - editType: 'plot' - }, - delta: { - reference: { - valType: 'number', - - editType: 'calc', - - }, - position: { - valType: 'enumerated', - values: ['top', 'bottom', 'left', 'right'], - - dflt: 'bottom', - editType: 'plot', - - }, - relative: { - valType: 'boolean', - editType: 'plot', - - dflt: false, - - }, - valueformat: { - valType: 'string', - - editType: 'plot', - - }, - increasing: { - symbol: { - valType: 'string', - - dflt: delta.INCREASING.SYMBOL, - editType: 'plot', - - }, - color: { - valType: 'color', - - dflt: delta.INCREASING.COLOR, - editType: 'plot', - - }, - // TODO: add attribute to show sign - editType: 'plot' - }, - decreasing: { - symbol: { - valType: 'string', - - dflt: delta.DECREASING.SYMBOL, - editType: 'plot', - - }, - color: { - valType: 'color', - - dflt: delta.DECREASING.COLOR, - editType: 'plot', - - }, - // TODO: add attribute to hide sign - editType: 'plot' - }, - font: extendFlat({}, textFontAttrs, { - - }), - editType: 'calc' - }, - gauge: { - shape: { - valType: 'enumerated', - editType: 'plot', - - dflt: 'angular', - values: ['angular', 'bullet'], - - }, - bar: extendDeep({}, gaugeBarAttrs, { - color: {dflt: 'green'}, - - }), - // Background of the gauge - bgcolor: { - valType: 'color', - - editType: 'plot', - - }, - bordercolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - - editType: 'plot', - - }, - borderwidth: { - valType: 'number', - min: 0, - dflt: 1, - - editType: 'plot', - - }, - axis: overrideAll({ - range: rangeAttr, - visible: extendFlat({}, axesAttrs.visible, { - dflt: true - }), - // tick and title properties named and function exactly as in axes - tickmode: axesAttrs.tickmode, - nticks: axesAttrs.nticks, - tick0: axesAttrs.tick0, - dtick: axesAttrs.dtick, - tickvals: axesAttrs.tickvals, - ticktext: axesAttrs.ticktext, - ticks: extendFlat({}, axesAttrs.ticks, {dflt: 'outside'}), - ticklen: axesAttrs.ticklen, - tickwidth: axesAttrs.tickwidth, - tickcolor: axesAttrs.tickcolor, - showticklabels: axesAttrs.showticklabels, - tickfont: fontAttrs({ - - }), - tickangle: axesAttrs.tickangle, - tickformat: axesAttrs.tickformat, - tickformatstops: axesAttrs.tickformatstops, - tickprefix: axesAttrs.tickprefix, - showtickprefix: axesAttrs.showtickprefix, - ticksuffix: axesAttrs.ticksuffix, - showticksuffix: axesAttrs.showticksuffix, - separatethousands: axesAttrs.separatethousands, - exponentformat: axesAttrs.exponentformat, - showexponent: axesAttrs.showexponent, - editType: 'plot' - }, 'plot'), - // Steps (or ranges) and thresholds - steps: stepsAttrs, - threshold: { - line: { - color: extendFlat({}, gaugeBarAttrs.line.color, { - - }), - width: extendFlat({}, gaugeBarAttrs.line.width, { - dflt: 1, - - }), - editType: 'plot' - }, - thickness: extendFlat({}, gaugeBarAttrs.thickness, { - dflt: 0.85, - - }), - value: { - valType: 'number', - editType: 'calc', - dflt: false, - - - }, - editType: 'plot' - }, - - editType: 'plot' - // TODO: in future version, add marker: (bar|needle) - } -}; - -},{"../../components/color/attributes":592,"../../constants/delta.js":689,"../../constants/docs":690,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plot_api/plot_template":757,"../../plots/cartesian/layout_attributes":779,"../../plots/domain":792,"../../plots/font_attributes":793}],1042:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; - -var name = exports.name = 'indicator'; - -exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { - var _module = Registry.getModule(name); - var cdmodule = getModuleCalcData(gd.calcdata, _module)[0]; - _module.plot(gd, cdmodule, transitionOpts, makeOnCompleteCallback); -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var had = (oldFullLayout._has && oldFullLayout._has(name)); - var has = (newFullLayout._has && newFullLayout._has(name)); - - if(had && !has) { - oldFullLayout._indicatorlayer.selectAll('g.trace').remove(); - } -}; - -},{"../../plots/get_data":802,"../../registry":847}],1043:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -// var Lib = require('../../lib'); - -function calc(gd, trace) { - var cd = []; - - var lastReading = trace.value; - if(!(typeof trace._lastValue === 'number')) trace._lastValue = trace.value; - var secondLastReading = trace._lastValue; - var deltaRef = secondLastReading; - if(trace._hasDelta && typeof trace.delta.reference === 'number') { - deltaRef = trace.delta.reference; - } - cd[0] = { - y: lastReading, - lastY: secondLastReading, - - delta: lastReading - deltaRef, - relativeDelta: (lastReading - deltaRef) / deltaRef, - }; - return cd; -} - -module.exports = { - calc: calc -}; - -},{}],1044:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - // Defaults for delta - defaultNumberFontSize: 80, - bulletNumberDomainSize: 0.25, - bulletPadding: 0.025, - innerRadius: 0.75, - valueThickness: 0.5, // thickness of value bars relative to full thickness, - titlePadding: 5, - horizontalPadding: 10 -}; - -},{}],1045:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attributes = _dereq_('./attributes'); -var handleDomainDefaults = _dereq_('../../plots/domain').defaults; -var Template = _dereq_('../../plot_api/plot_template'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); -var cn = _dereq_('./constants.js'); - -var handleTickValueDefaults = _dereq_('../../plots/cartesian/tick_value_defaults'); -var handleTickMarkDefaults = _dereq_('../../plots/cartesian/tick_mark_defaults'); -var handleTickLabelDefaults = _dereq_('../../plots/cartesian/tick_label_defaults'); - -function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - handleDomainDefaults(traceOut, layout, coerce); - - // Mode - coerce('mode'); - traceOut._hasNumber = traceOut.mode.indexOf('number') !== -1; - traceOut._hasDelta = traceOut.mode.indexOf('delta') !== -1; - traceOut._hasGauge = traceOut.mode.indexOf('gauge') !== -1; - - var value = coerce('value'); - traceOut._range = [0, (typeof value === 'number' ? 1.5 * value : 1)]; - - // Number attributes - var auto = new Array(2); - var bignumberFontSize; - if(traceOut._hasNumber) { - coerce('number.valueformat'); - coerce('number.font.color', layout.font.color); - coerce('number.font.family', layout.font.family); - coerce('number.font.size'); - if(traceOut.number.font.size === undefined) { - traceOut.number.font.size = cn.defaultNumberFontSize; - auto[0] = true; - } - coerce('number.prefix'); - coerce('number.suffix'); - bignumberFontSize = traceOut.number.font.size; - } - - // delta attributes - var deltaFontSize; - if(traceOut._hasDelta) { - coerce('delta.font.color', layout.font.color); - coerce('delta.font.family', layout.font.family); - coerce('delta.font.size'); - if(traceOut.delta.font.size === undefined) { - traceOut.delta.font.size = (traceOut._hasNumber ? 0.5 : 1) * (bignumberFontSize || cn.defaultNumberFontSize); - auto[1] = true; - } - coerce('delta.reference', traceOut.value); - coerce('delta.relative'); - coerce('delta.valueformat', traceOut.delta.relative ? '2%' : ''); - coerce('delta.increasing.symbol'); - coerce('delta.increasing.color'); - coerce('delta.decreasing.symbol'); - coerce('delta.decreasing.color'); - coerce('delta.position'); - deltaFontSize = traceOut.delta.font.size; - } - traceOut._scaleNumbers = (!traceOut._hasNumber || auto[0]) && (!traceOut._hasDelta || auto[1]) || false; - - // Title attributes - coerce('title.font.color', layout.font.color); - coerce('title.font.family', layout.font.family); - coerce('title.font.size', 0.25 * (bignumberFontSize || deltaFontSize || cn.defaultNumberFontSize)); - coerce('title.text'); - - // Gauge attributes - var gaugeIn, gaugeOut, axisIn, axisOut; - function coerceGauge(attr, dflt) { - return Lib.coerce(gaugeIn, gaugeOut, attributes.gauge, attr, dflt); - } - function coerceGaugeAxis(attr, dflt) { - return Lib.coerce(axisIn, axisOut, attributes.gauge.axis, attr, dflt); - } - - if(traceOut._hasGauge) { - gaugeIn = traceIn.gauge; - if(!gaugeIn) gaugeIn = {}; - gaugeOut = Template.newContainer(traceOut, 'gauge'); - coerceGauge('shape'); - var isBullet = traceOut._isBullet = traceOut.gauge.shape === 'bullet'; - if(!isBullet) { - coerce('title.align', 'center'); - } - var isAngular = traceOut._isAngular = traceOut.gauge.shape === 'angular'; - if(!isAngular) { - coerce('align', 'center'); - } - - // gauge background - coerceGauge('bgcolor', layout.paper_bgcolor); - coerceGauge('borderwidth'); - coerceGauge('bordercolor'); - - // gauge bar indicator - coerceGauge('bar.color'); - coerceGauge('bar.line.color'); - coerceGauge('bar.line.width'); - var defaultBarThickness = cn.valueThickness * (traceOut.gauge.shape === 'bullet' ? 0.5 : 1); - coerceGauge('bar.thickness', defaultBarThickness); - - // Gauge steps - handleArrayContainerDefaults(gaugeIn, gaugeOut, { - name: 'steps', - handleItemDefaults: stepDefaults - }); - - // Gauge threshold - coerceGauge('threshold.value'); - coerceGauge('threshold.thickness'); - coerceGauge('threshold.line.width'); - coerceGauge('threshold.line.color'); - - // Gauge axis - axisIn = {}; - if(gaugeIn) axisIn = gaugeIn.axis || {}; - axisOut = Template.newContainer(gaugeOut, 'axis'); - coerceGaugeAxis('visible'); - traceOut._range = coerceGaugeAxis('range', traceOut._range); - - var opts = {outerTicks: true}; - handleTickValueDefaults(axisIn, axisOut, coerceGaugeAxis, 'linear'); - handleTickLabelDefaults(axisIn, axisOut, coerceGaugeAxis, 'linear', opts); - handleTickMarkDefaults(axisIn, axisOut, coerceGaugeAxis, opts); - } else { - coerce('title.align', 'center'); - coerce('align', 'center'); - traceOut._isAngular = traceOut._isBullet = false; - } - - // disable 1D transforms - traceOut._length = null; -} - -function stepDefaults(stepIn, stepOut) { - function coerce(attr, dflt) { - return Lib.coerce(stepIn, stepOut, attributes.gauge.steps, attr, dflt); - } - - coerce('color'); - coerce('line.color'); - coerce('line.width'); - coerce('range'); - coerce('thickness'); -} - -module.exports = { - supplyDefaults: supplyDefaults -}; - -},{"../../lib":719,"../../plot_api/plot_template":757,"../../plots/array_container_defaults":763,"../../plots/cartesian/tick_label_defaults":786,"../../plots/cartesian/tick_mark_defaults":787,"../../plots/cartesian/tick_value_defaults":788,"../../plots/domain":792,"./attributes":1041,"./constants.js":1044}],1046:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'indicator', - basePlotModule: _dereq_('./base_plot'), - categories: ['svg', 'noOpacity', 'noHover'], - animatable: true, - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults').supplyDefaults, - - calc: _dereq_('./calc').calc, - - plot: _dereq_('./plot'), - - meta: { - - } -}; - -},{"./attributes":1041,"./base_plot":1042,"./calc":1043,"./defaults":1045,"./plot":1047}],1047:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Lib = _dereq_('../../lib'); -var rad2deg = Lib.rad2deg; -var MID_SHIFT = _dereq_('../../constants/alignment').MID_SHIFT; -var Drawing = _dereq_('../../components/drawing'); -var cn = _dereq_('./constants'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); - -var Axes = _dereq_('../../plots/cartesian/axes'); -var handleAxisDefaults = _dereq_('../../plots/cartesian/axis_defaults'); -var handleAxisPositionDefaults = _dereq_('../../plots/cartesian/position_defaults'); -var axisLayoutAttrs = _dereq_('../../plots/cartesian/layout_attributes'); - -var Color = _dereq_('../../components/color'); -var anchor = { - 'left': 'start', - 'center': 'middle', - 'right': 'end' -}; -var position = { - 'left': 0, - 'center': 0.5, - 'right': 1 -}; - -var SI_PREFIX = /[yzafpnµmkMGTPEZY]/; - -function hasTransition(transitionOpts) { - // If transition config is provided, then it is only a partial replot and traces not - // updated are removed. - return transitionOpts && transitionOpts.duration > 0; -} - -module.exports = function plot(gd, cdModule, transitionOpts, makeOnCompleteCallback) { - var fullLayout = gd._fullLayout; - var onComplete; - - if(hasTransition(transitionOpts)) { - if(makeOnCompleteCallback) { - // If it was passed a callback to register completion, make a callback. If - // this is created, then it must be executed on completion, otherwise the - // pos-transition redraw will not execute: - onComplete = makeOnCompleteCallback(); - } - } - - Lib.makeTraceGroups(fullLayout._indicatorlayer, cdModule, 'trace').each(function(cd) { - var cd0 = cd[0]; - var trace = cd0.trace; - - var plotGroup = d3.select(this); - - // Elements in trace - var hasGauge = trace._hasGauge; - var isAngular = trace._isAngular; - var isBullet = trace._isBullet; - - // Domain size - var domain = trace.domain; - var size = { - w: fullLayout._size.w * (domain.x[1] - domain.x[0]), - h: fullLayout._size.h * (domain.y[1] - domain.y[0]), - l: fullLayout._size.l + fullLayout._size.w * domain.x[0], - r: fullLayout._size.r + fullLayout._size.w * (1 - domain.x[1]), - t: fullLayout._size.t + fullLayout._size.h * (1 - domain.y[1]), - b: fullLayout._size.b + fullLayout._size.h * (domain.y[0]) - }; - var centerX = size.l + size.w / 2; - var centerY = size.t + size.h / 2; - - // Angular gauge size - var radius = Math.min(size.w / 2, size.h); // fill domain - var innerRadius = cn.innerRadius * radius; - - // Position numbers based on mode and set the scaling logic - var numbersX, numbersY, numbersScaler; - var numbersAlign = trace.align || 'center'; - - numbersY = centerY; - if(!hasGauge) { - numbersX = size.l + position[numbersAlign] * size.w; - numbersScaler = function(el) { - return fitTextInsideBox(el, size.w, size.h); - }; - } else { - if(isAngular) { - numbersX = centerX; - numbersY = centerY + radius / 2; - numbersScaler = function(el) { - return fitTextInsideCircle(el, 0.9 * innerRadius); - }; - } - if(isBullet) { - var padding = cn.bulletPadding; - var p = (1 - cn.bulletNumberDomainSize) + padding; - numbersX = size.l + (p + (1 - p) * position[numbersAlign]) * size.w; - numbersScaler = function(el) { - return fitTextInsideBox(el, (cn.bulletNumberDomainSize - padding) * size.w, size.h); - }; - } - } - - // Draw numbers - drawNumbers(gd, plotGroup, cd, { - numbersX: numbersX, - numbersY: numbersY, - numbersScaler: numbersScaler, - transitionOpts: transitionOpts, - onComplete: onComplete - }); - - // Reexpress our gauge background attributes for drawing - var gaugeBg, gaugeOutline; - if(hasGauge) { - gaugeBg = { - range: trace.gauge.axis.range, - color: trace.gauge.bgcolor, - line: { - color: trace.gauge.bordercolor, - width: 0 - }, - thickness: 1 - }; - - gaugeOutline = { - range: trace.gauge.axis.range, - color: 'rgba(0, 0, 0, 0)', - line: { - color: trace.gauge.bordercolor, - width: trace.gauge.borderwidth - }, - thickness: 1 - }; - } - - // Prepare angular gauge layers - var angularGauge = plotGroup.selectAll('g.angular').data(isAngular ? cd : []); - angularGauge.exit().remove(); - var angularaxisLayer = plotGroup.selectAll('g.angularaxis').data(isAngular ? cd : []); - angularaxisLayer.exit().remove(); - - if(isAngular) { - drawAngularGauge(gd, plotGroup, cd, { - radius: radius, - innerRadius: innerRadius, - - gauge: angularGauge, - layer: angularaxisLayer, - size: size, - gaugeBg: gaugeBg, - gaugeOutline: gaugeOutline, - transitionOpts: transitionOpts, - onComplete: onComplete - }); - } - - // Prepare bullet layers - var bulletGauge = plotGroup.selectAll('g.bullet').data(isBullet ? cd : []); - bulletGauge.exit().remove(); - var bulletaxisLayer = plotGroup.selectAll('g.bulletaxis').data(isBullet ? cd : []); - bulletaxisLayer.exit().remove(); - - if(isBullet) { - drawBulletGauge(gd, plotGroup, cd, { - gauge: bulletGauge, - layer: bulletaxisLayer, - size: size, - gaugeBg: gaugeBg, - gaugeOutline: gaugeOutline, - transitionOpts: transitionOpts, - onComplete: onComplete - }); - } - - // title - var title = plotGroup.selectAll('text.title').data(cd); - title.exit().remove(); - title.enter().append('text').classed('title', true); - title - .attr('text-anchor', function() { - return isBullet ? anchor.right : anchor[trace.title.align]; - }) - .text(trace.title.text) - .call(Drawing.font, trace.title.font) - .call(svgTextUtils.convertToTspans, gd); - - // Position title - title.attr('transform', function() { - var titleX = size.l + size.w * position[trace.title.align]; - var titleY; - var titlePadding = cn.titlePadding; - var titlebBox = Drawing.bBox(title.node()); - if(hasGauge) { - if(isAngular) { - // position above axis ticks/labels - if(trace.gauge.axis.visible) { - var bBox = Drawing.bBox(angularaxisLayer.node()); - titleY = (bBox.top - titlePadding) - titlebBox.bottom; - } else { - titleY = size.t + size.h / 2 - radius / 2 - titlebBox.bottom - titlePadding; - } - } - if(isBullet) { - // position outside domain - titleY = numbersY - (titlebBox.top + titlebBox.bottom) / 2; - titleX = size.l - cn.bulletPadding * size.w; // Outside domain, on the left - } - } else { - // position above numbers - titleY = (trace._numbersTop - titlePadding) - titlebBox.bottom; - } - return strTranslate(titleX, titleY); - }); - }); -}; - -function drawBulletGauge(gd, plotGroup, cd, opts) { - var trace = cd[0].trace; - - var bullet = opts.gauge; - var axisLayer = opts.layer; - var gaugeBg = opts.gaugeBg; - var gaugeOutline = opts.gaugeOutline; - var size = opts.size; - var domain = trace.domain; - - var transitionOpts = opts.transitionOpts; - var onComplete = opts.onComplete; - - // preparing axis - var ax, vals, transFn, tickSign, shift; - - // Enter bullet, axis - bullet.enter().append('g').classed('bullet', true); - bullet.attr('transform', 'translate(' + size.l + ', ' + size.t + ')'); - - axisLayer.enter().append('g') - .classed('bulletaxis', true) - .classed('crisp', true); - axisLayer.selectAll('g.' + 'xbulletaxis' + 'tick,path,text').remove(); - - // Draw bullet - var bulletHeight = size.h; // use all vertical domain - var innerBulletHeight = trace.gauge.bar.thickness * bulletHeight; - var bulletLeft = domain.x[0]; - var bulletRight = domain.x[0] + (domain.x[1] - domain.x[0]) * ((trace._hasNumber || trace._hasDelta) ? (1 - cn.bulletNumberDomainSize) : 1); - - ax = mockAxis(gd, trace.gauge.axis); - ax._id = 'xbulletaxis'; - ax.domain = [bulletLeft, bulletRight]; - ax.setScale(); - - vals = Axes.calcTicks(ax); - transFn = Axes.makeTransFn(ax); - tickSign = Axes.getTickSigns(ax)[2]; - - shift = size.t + size.h; - if(ax.visible) { - Axes.drawTicks(gd, ax, { - vals: ax.ticks === 'inside' ? Axes.clipEnds(ax, vals) : vals, - layer: axisLayer, - path: Axes.makeTickPath(ax, shift, tickSign), - transFn: transFn - }); - - Axes.drawLabels(gd, ax, { - vals: vals, - layer: axisLayer, - transFn: transFn, - labelFns: Axes.makeLabelFns(ax, shift) - }); - } - - function drawRect(s) { - s - .attr('width', function(d) { return Math.max(0, ax.c2p(d.range[1]) - ax.c2p(d.range[0]));}) - .attr('x', function(d) { return ax.c2p(d.range[0]);}) - .attr('y', function(d) { return 0.5 * (1 - d.thickness) * bulletHeight;}) - .attr('height', function(d) { return d.thickness * bulletHeight; }); - } - - // Draw bullet background, steps - var boxes = [gaugeBg].concat(trace.gauge.steps); - var bgBullet = bullet.selectAll('g.bg-bullet').data(boxes); - bgBullet.enter().append('g').classed('bg-bullet', true).append('rect'); - bgBullet.select('rect') - .call(drawRect) - .call(styleShape); - bgBullet.exit().remove(); - - // Draw value bar with transitions - var fgBullet = bullet.selectAll('g.value-bullet').data([trace.gauge.bar]); - fgBullet.enter().append('g').classed('value-bullet', true).append('rect'); - fgBullet.select('rect') - .attr('height', innerBulletHeight) - .attr('y', (bulletHeight - innerBulletHeight) / 2) - .call(styleShape); - if(hasTransition(transitionOpts)) { - fgBullet.select('rect') - .transition() - .duration(transitionOpts.duration) - .ease(transitionOpts.easing) - .each('end', function() { onComplete && onComplete(); }) - .each('interrupt', function() { onComplete && onComplete(); }) - .attr('width', Math.max(0, ax.c2p(Math.min(trace.gauge.axis.range[1], cd[0].y)))); - } else { - fgBullet.select('rect') - .attr('width', typeof cd[0].y === 'number' ? - Math.max(0, ax.c2p(Math.min(trace.gauge.axis.range[1], cd[0].y))) : - 0); - } - fgBullet.exit().remove(); - - var data = cd.filter(function() {return trace.gauge.threshold.value;}); - var threshold = bullet.selectAll('g.threshold-bullet').data(data); - threshold.enter().append('g').classed('threshold-bullet', true).append('line'); - threshold.select('line') - .attr('x1', ax.c2p(trace.gauge.threshold.value)) - .attr('x2', ax.c2p(trace.gauge.threshold.value)) - .attr('y1', (1 - trace.gauge.threshold.thickness) / 2 * bulletHeight) - .attr('y2', (1 - (1 - trace.gauge.threshold.thickness) / 2) * bulletHeight) - .call(Color.stroke, trace.gauge.threshold.line.color) - .style('stroke-width', trace.gauge.threshold.line.width); - threshold.exit().remove(); - - var bulletOutline = bullet.selectAll('g.gauge-outline').data([gaugeOutline]); - bulletOutline.enter().append('g').classed('gauge-outline', true).append('rect'); - bulletOutline.select('rect') - .call(drawRect) - .call(styleShape); - bulletOutline.exit().remove(); -} - -function drawAngularGauge(gd, plotGroup, cd, opts) { - var trace = cd[0].trace; - - var size = opts.size; - var radius = opts.radius; - var innerRadius = opts.innerRadius; - var gaugeBg = opts.gaugeBg; - var gaugeOutline = opts.gaugeOutline; - var gaugePosition = [size.l + size.w / 2, size.t + size.h / 2 + radius / 2]; - var gauge = opts.gauge; - var axisLayer = opts.layer; - - var transitionOpts = opts.transitionOpts; - var onComplete = opts.onComplete; - - // circular gauge - var theta = Math.PI / 2; - function valueToAngle(v) { - var min = trace.gauge.axis.range[0]; - var max = trace.gauge.axis.range[1]; - var angle = (v - min) / (max - min) * Math.PI - theta; - if(angle < -theta) return -theta; - if(angle > theta) return theta; - return angle; - } - - function arcPathGenerator(size) { - return d3.svg.arc() - .innerRadius((innerRadius + radius) / 2 - size / 2 * (radius - innerRadius)) - .outerRadius((innerRadius + radius) / 2 + size / 2 * (radius - innerRadius)) - .startAngle(-theta); - } - - function drawArc(p) { - p - .attr('d', function(d) { - return arcPathGenerator(d.thickness) - .startAngle(valueToAngle(d.range[0])) - .endAngle(valueToAngle(d.range[1]))(); - }); - } - - // preparing axis - var ax, vals, transFn, tickSign; - - // Enter gauge and axis - gauge.enter().append('g').classed('angular', true); - gauge.attr('transform', strTranslate(gaugePosition[0], gaugePosition[1])); - - axisLayer.enter().append('g') - .classed('angularaxis', true) - .classed('crisp', true); - axisLayer.selectAll('g.' + 'xangularaxis' + 'tick,path,text').remove(); - - ax = mockAxis(gd, trace.gauge.axis); - ax.type = 'linear'; - ax.range = trace.gauge.axis.range; - ax._id = 'xangularaxis'; // or 'y', but I don't think this makes a difference here - ax.setScale(); - - // 't'ick to 'g'eometric radians is used all over the place here - var t2g = function(d) { - return (ax.range[0] - d.x) / (ax.range[1] - ax.range[0]) * Math.PI + Math.PI; - }; - - var labelFns = {}; - var out = Axes.makeLabelFns(ax, 0); - var labelStandoff = out.labelStandoff; - labelFns.xFn = function(d) { - var rad = t2g(d); - return Math.cos(rad) * labelStandoff; - }; - labelFns.yFn = function(d) { - var rad = t2g(d); - var ff = Math.sin(rad) > 0 ? 0.2 : 1; - return -Math.sin(rad) * (labelStandoff + d.fontSize * ff) + - Math.abs(Math.cos(rad)) * (d.fontSize * MID_SHIFT); - }; - labelFns.anchorFn = function(d) { - var rad = t2g(d); - var cos = Math.cos(rad); - return Math.abs(cos) < 0.1 ? - 'middle' : - (cos > 0 ? 'start' : 'end'); - }; - labelFns.heightFn = function(d, a, h) { - var rad = t2g(d); - return -0.5 * (1 + Math.sin(rad)) * h; - }; - var _transFn = function(rad) { - return strTranslate( - gaugePosition[0] + radius * Math.cos(rad), - gaugePosition[1] - radius * Math.sin(rad) - ); - }; - transFn = function(d) { - return _transFn(t2g(d)); - }; - var transFn2 = function(d) { - var rad = t2g(d); - return _transFn(rad) + 'rotate(' + -rad2deg(rad) + ')'; - }; - vals = Axes.calcTicks(ax); - tickSign = Axes.getTickSigns(ax)[2]; - if(ax.visible) { - tickSign = ax.ticks === 'inside' ? -1 : 1; - var pad = (ax.linewidth || 1) / 2; - Axes.drawTicks(gd, ax, { - vals: vals, - layer: axisLayer, - path: 'M' + (tickSign * pad) + ',0h' + (tickSign * ax.ticklen), - transFn: transFn2 - }); - Axes.drawLabels(gd, ax, { - vals: vals, - layer: axisLayer, - transFn: transFn, - labelFns: labelFns - }); - } - - // Draw background + steps - var arcs = [gaugeBg].concat(trace.gauge.steps); - var bgArc = gauge.selectAll('g.bg-arc').data(arcs); - bgArc.enter().append('g').classed('bg-arc', true).append('path'); - bgArc.select('path').call(drawArc).call(styleShape); - bgArc.exit().remove(); - - // Draw foreground with transition - var valueArcPathGenerator = arcPathGenerator(trace.gauge.bar.thickness); - var valueArc = gauge.selectAll('g.value-arc').data([trace.gauge.bar]); - valueArc.enter().append('g').classed('value-arc', true).append('path'); - var valueArcPath = valueArc.select('path'); - if(hasTransition(transitionOpts)) { - valueArcPath - .transition() - .duration(transitionOpts.duration) - .ease(transitionOpts.easing) - .each('end', function() { onComplete && onComplete(); }) - .each('interrupt', function() { onComplete && onComplete(); }) - .attrTween('d', arcTween(valueArcPathGenerator, valueToAngle(cd[0].lastY), valueToAngle(cd[0].y))); - trace._lastValue = cd[0].y; - } else { - valueArcPath.attr('d', typeof cd[0].y === 'number' ? - valueArcPathGenerator.endAngle(valueToAngle(cd[0].y)) : - 'M0,0Z'); - } - valueArcPath.call(styleShape); - valueArc.exit().remove(); - - // Draw threshold - arcs = []; - var v = trace.gauge.threshold.value; - if(v) { - arcs.push({ - range: [v, v], - color: trace.gauge.threshold.color, - line: { - color: trace.gauge.threshold.line.color, - width: trace.gauge.threshold.line.width - }, - thickness: trace.gauge.threshold.thickness - }); - } - var thresholdArc = gauge.selectAll('g.threshold-arc').data(arcs); - thresholdArc.enter().append('g').classed('threshold-arc', true).append('path'); - thresholdArc.select('path').call(drawArc).call(styleShape); - thresholdArc.exit().remove(); - - // Draw border last - var gaugeBorder = gauge.selectAll('g.gauge-outline').data([gaugeOutline]); - gaugeBorder.enter().append('g').classed('gauge-outline', true).append('path'); - gaugeBorder.select('path').call(drawArc).call(styleShape); - gaugeBorder.exit().remove(); -} - -function drawNumbers(gd, plotGroup, cd, opts) { - var trace = cd[0].trace; - - var numbersX = opts.numbersX; - var numbersY = opts.numbersY; - var numbersAlign = trace.align || 'center'; - var numbersAnchor = anchor[numbersAlign]; - - var transitionOpts = opts.transitionOpts; - var onComplete = opts.onComplete; - - var numbers = Lib.ensureSingle(plotGroup, 'g', 'numbers'); - var bignumberbBox, deltabBox; - var numbersbBox; - - var data = []; - if(trace._hasNumber) data.push('number'); - if(trace._hasDelta) { - data.push('delta'); - if(trace.delta.position === 'left') data.reverse(); - } - var sel = numbers.selectAll('text').data(data); - sel.enter().append('text'); - sel - .attr('text-anchor', function() {return numbersAnchor;}) - .attr('class', function(d) { return d;}) - .attr('x', null) - .attr('y', null) - .attr('dx', null) - .attr('dy', null); - sel.exit().remove(); - - // Function to override the number formatting used during transitions - function transitionFormat(valueformat, fmt, from, to) { - // For now, do not display SI prefix if start and end value do not have any - if(valueformat.match('s') && // If using SI prefix - (from >= 0 !== to >= 0) && // If sign change - (!fmt(from).slice(-1).match(SI_PREFIX) && !fmt(to).slice(-1).match(SI_PREFIX)) // Has no SI prefix - ) { - var transitionValueFormat = valueformat.slice().replace('s', 'f').replace(/\d+/, function(m) { return parseInt(m) - 1;}); - var transitionAx = mockAxis(gd, {tickformat: transitionValueFormat}); - return function(v) { - // Switch to fixed precision if number is smaller than one - if(Math.abs(v) < 1) return Axes.tickText(transitionAx, v).text; - return fmt(v); - }; - } else { - return fmt; - } - } - - function drawBignumber() { - var bignumberAx = mockAxis(gd, {tickformat: trace.number.valueformat}, trace._range); - bignumberAx.setScale(); - Axes.calcTicks(bignumberAx); - - var fmt = function(v) { return Axes.tickText(bignumberAx, v).text;}; - var bignumberSuffix = trace.number.suffix; - var bignumberPrefix = trace.number.prefix; - - var number = numbers.select('text.number'); - - function writeNumber() { - var txt = typeof cd[0].y === 'number' ? - bignumberPrefix + fmt(cd[0].y) + bignumberSuffix : - '-'; - number.text(txt) - .call(Drawing.font, trace.number.font) - .call(svgTextUtils.convertToTspans, gd); - } - - if(hasTransition(transitionOpts)) { - number - .transition() - .duration(transitionOpts.duration) - .ease(transitionOpts.easing) - .each('end', function() { writeNumber(); onComplete && onComplete(); }) - .each('interrupt', function() { writeNumber(); onComplete && onComplete(); }) - .attrTween('text', function() { - var that = d3.select(this); - var interpolator = d3.interpolateNumber(cd[0].lastY, cd[0].y); - trace._lastValue = cd[0].y; - - var transitionFmt = transitionFormat(trace.number.valueformat, fmt, cd[0].lastY, cd[0].y); - return function(t) { - that.text(bignumberPrefix + transitionFmt(interpolator(t)) + bignumberSuffix); - }; - }); - } else { - writeNumber(); - } - - bignumberbBox = measureText(bignumberPrefix + fmt(cd[0].y) + bignumberSuffix, trace.number.font, numbersAnchor, gd); - return number; - } - - function drawDelta() { - var deltaAx = mockAxis(gd, {tickformat: trace.delta.valueformat}, trace._range); - deltaAx.setScale(); - Axes.calcTicks(deltaAx); - - var deltaFmt = function(v) { return Axes.tickText(deltaAx, v).text;}; - var deltaValue = function(d) { - var value = trace.delta.relative ? d.relativeDelta : d.delta; - return value; - }; - var deltaFormatText = function(value, numberFmt) { - if(value === 0 || typeof value !== 'number' || isNaN(value)) return '-'; - return (value > 0 ? trace.delta.increasing.symbol : trace.delta.decreasing.symbol) + numberFmt(value); - }; - var deltaFill = function(d) { - return d.delta >= 0 ? trace.delta.increasing.color : trace.delta.decreasing.color; - }; - if(trace._deltaLastValue === undefined) { - trace._deltaLastValue = deltaValue(cd[0]); - } - var delta = numbers.select('text.delta'); - delta - .call(Drawing.font, trace.delta.font) - .call(Color.fill, deltaFill({delta: trace._deltaLastValue})); - - function writeDelta() { - delta.text(deltaFormatText(deltaValue(cd[0]), deltaFmt)) - .call(Color.fill, deltaFill(cd[0])) - .call(svgTextUtils.convertToTspans, gd); - } - - if(hasTransition(transitionOpts)) { - delta - .transition() - .duration(transitionOpts.duration) - .ease(transitionOpts.easing) - .tween('text', function() { - var that = d3.select(this); - var to = deltaValue(cd[0]); - var from = trace._deltaLastValue; - var transitionFmt = transitionFormat(trace.delta.valueformat, deltaFmt, from, to); - var interpolator = d3.interpolateNumber(from, to); - trace._deltaLastValue = to; - return function(t) { - that.text(deltaFormatText(interpolator(t), transitionFmt)); - that.call(Color.fill, deltaFill({delta: interpolator(t)})); - }; - }) - .each('end', function() { writeDelta(); onComplete && onComplete(); }) - .each('interrupt', function() { writeDelta(); onComplete && onComplete(); }); - } else { - writeDelta(); - } - - deltabBox = measureText(deltaFormatText(deltaValue(cd[0]), deltaFmt), trace.delta.font, numbersAnchor, gd); - return delta; - } - - var key = trace.mode + trace.align; - var delta; - if(trace._hasDelta) { - delta = drawDelta(); - key += trace.delta.position + trace.delta.font.size + trace.delta.font.family + trace.delta.valueformat; - key += trace.delta.increasing.symbol + trace.delta.decreasing.symbol; - numbersbBox = deltabBox; - } - if(trace._hasNumber) { - drawBignumber(); - key += trace.number.font.size + trace.number.font.family + trace.number.valueformat + trace.number.suffix + trace.number.prefix; - numbersbBox = bignumberbBox; - } - - // Position delta relative to bignumber - if(trace._hasDelta && trace._hasNumber) { - var bignumberCenter = [ - (bignumberbBox.left + bignumberbBox.right) / 2, - (bignumberbBox.top + bignumberbBox.bottom) / 2 - ]; - var deltaCenter = [ - (deltabBox.left + deltabBox.right) / 2, - (deltabBox.top + deltabBox.bottom) / 2 - ]; - - var dx, dy; - var padding = 0.75 * trace.delta.font.size; - if(trace.delta.position === 'left') { - dx = cache(trace, 'deltaPos', 0, -1 * (bignumberbBox.width * (position[trace.align]) + deltabBox.width * (1 - position[trace.align]) + padding), key, Math.min); - dy = bignumberCenter[1] - deltaCenter[1]; - - numbersbBox = { - width: bignumberbBox.width + deltabBox.width + padding, - height: Math.max(bignumberbBox.height, deltabBox.height), - left: deltabBox.left + dx, - right: bignumberbBox.right, - top: Math.min(bignumberbBox.top, deltabBox.top + dy), - bottom: Math.max(bignumberbBox.bottom, deltabBox.bottom + dy) - }; - } - if(trace.delta.position === 'right') { - dx = cache(trace, 'deltaPos', 0, bignumberbBox.width * (1 - position[trace.align]) + deltabBox.width * position[trace.align] + padding, key, Math.max); - dy = bignumberCenter[1] - deltaCenter[1]; - - numbersbBox = { - width: bignumberbBox.width + deltabBox.width + padding, - height: Math.max(bignumberbBox.height, deltabBox.height), - left: bignumberbBox.left, - right: deltabBox.right + dx, - top: Math.min(bignumberbBox.top, deltabBox.top + dy), - bottom: Math.max(bignumberbBox.bottom, deltabBox.bottom + dy) - }; - } - if(trace.delta.position === 'bottom') { - dx = null; - dy = deltabBox.height; - - numbersbBox = { - width: Math.max(bignumberbBox.width, deltabBox.width), - height: bignumberbBox.height + deltabBox.height, - left: Math.min(bignumberbBox.left, deltabBox.left), - right: Math.max(bignumberbBox.right, deltabBox.right), - top: bignumberbBox.bottom - bignumberbBox.height, - bottom: bignumberbBox.bottom + deltabBox.height - }; - } - if(trace.delta.position === 'top') { - dx = null; - dy = bignumberbBox.top; - - numbersbBox = { - width: Math.max(bignumberbBox.width, deltabBox.width), - height: bignumberbBox.height + deltabBox.height, - left: Math.min(bignumberbBox.left, deltabBox.left), - right: Math.max(bignumberbBox.right, deltabBox.right), - top: bignumberbBox.bottom - bignumberbBox.height - deltabBox.height, - bottom: bignumberbBox.bottom - }; - } - - delta.attr({dx: dx, dy: dy}); - } - - // Resize numbers to fit within space and position - if(trace._hasNumber || trace._hasDelta) { - numbers.attr('transform', function() { - var m = opts.numbersScaler(numbersbBox); - key += m[2]; - var scaleRatio = cache(trace, 'numbersScale', 1, m[0], key, Math.min); - var translateY; - if(!trace._scaleNumbers) scaleRatio = 1; - if(trace._isAngular) { - // align vertically to bottom - translateY = numbersY - scaleRatio * numbersbBox.bottom; - } else { - // align vertically to center - translateY = numbersY - scaleRatio * (numbersbBox.top + numbersbBox.bottom) / 2; - } - - // Stash the top position of numbersbBox for title positioning - trace._numbersTop = scaleRatio * (numbersbBox.top) + translateY; - - var ref = numbersbBox[numbersAlign]; - if(numbersAlign === 'center') ref = (numbersbBox.left + numbersbBox.right) / 2; - var translateX = numbersX - scaleRatio * ref; - - // Stash translateX - translateX = cache(trace, 'numbersTranslate', 0, translateX, key, Math.max); - return strTranslate(translateX, translateY) + ' scale(' + scaleRatio + ')'; - }); - } -} - -// Apply fill, stroke, stroke-width to SVG shape -function styleShape(p) { - p - .each(function(d) { Color.stroke(d3.select(this), d.line.color);}) - .each(function(d) { Color.fill(d3.select(this), d.color);}) - .style('stroke-width', function(d) { return d.line.width;}); -} - -// Returns a tween for a transition’s "d" attribute, transitioning any selected -// arcs from their current angle to the specified new angle. -function arcTween(arc, endAngle, newAngle) { - return function() { - var interpolate = d3.interpolate(endAngle, newAngle); - return function(t) { - return arc.endAngle(interpolate(t))(); - }; - }; -} - -// mocks our axis -function mockAxis(gd, opts, zrange) { - var fullLayout = gd._fullLayout; - - var axisIn = Lib.extendFlat({ - type: 'linear', - ticks: 'outside', - range: zrange, - showline: true - }, opts); - - var axisOut = { - type: 'linear', - _id: 'x' + opts._id - }; - - var axisOptions = { - letter: 'x', - font: fullLayout.font, - noHover: true, - noTickson: true - }; - - function coerce(attr, dflt) { - return Lib.coerce(axisIn, axisOut, axisLayoutAttrs, attr, dflt); - } - - handleAxisDefaults(axisIn, axisOut, coerce, axisOptions, fullLayout); - handleAxisPositionDefaults(axisIn, axisOut, coerce, axisOptions); - - return axisOut; -} - -function strTranslate(x, y) { - return 'translate(' + x + ',' + y + ')'; -} - -function fitTextInsideBox(textBB, width, height) { - // compute scaling ratio to have text fit within specified width and height - var ratio = Math.min(width / textBB.width, height / textBB.height); - return [ratio, textBB, width + 'x' + height]; -} - -function fitTextInsideCircle(textBB, radius) { - // compute scaling ratio to have text fit within specified radius - var elRadius = Math.sqrt((textBB.width / 2) * (textBB.width / 2) + textBB.height * textBB.height); - var ratio = radius / elRadius; - return [ratio, textBB, radius]; -} - -function measureText(txt, font, textAnchor, gd) { - var element = document.createElementNS('http://www.w3.org/2000/svg', 'text'); - var sel = d3.select(element); - sel.text(txt) - .attr('x', 0) - .attr('y', 0) - .attr('text-anchor', textAnchor) - .attr('data-unformatted', txt) - .call(svgTextUtils.convertToTspans, gd) - .call(Drawing.font, font); - return Drawing.bBox(sel.node()); -} - -function cache(trace, name, initialValue, value, key, fn) { - var objName = '_cache' + name; - if(!(trace[objName] && trace[objName].key === key)) { - trace[objName] = {key: key, value: initialValue}; - } - var v = Lib.aggNums(fn, null, [trace[objName].value, value], 2); - trace[objName].value = v; - - return v; -} - -},{"../../components/color":593,"../../components/drawing":614,"../../constants/alignment":688,"../../lib":719,"../../lib/svg_text_utils":743,"../../plots/cartesian/axes":767,"../../plots/cartesian/axis_defaults":769,"../../plots/cartesian/layout_attributes":779,"../../plots/cartesian/position_defaults":782,"./constants":1044,"d3":163}],1048:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var meshAttrs = _dereq_('../mesh3d/attributes'); -var baseAttrs = _dereq_('../../plots/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -function makeSliceAttr(axLetter) { - return { - show: { - valType: 'boolean', - - dflt: false, - - }, - locations: { - valType: 'data_array', - dflt: [], - - - }, - fill: { - valType: 'number', - - min: 0, - max: 1, - dflt: 1, - - } - }; -} - -function makeCapAttr(axLetter) { - return { - show: { - valType: 'boolean', - - dflt: true, - - }, - fill: { - valType: 'number', - - min: 0, - max: 1, - dflt: 1, - - } - }; -} - -var attrs = module.exports = overrideAll(extendFlat({ - x: { - valType: 'data_array', - - - }, - y: { - valType: 'data_array', - - - }, - z: { - valType: 'data_array', - - - }, - value: { - valType: 'data_array', - - - }, - isomin: { - valType: 'number', - - - }, - isomax: { - valType: 'number', - - - }, - - surface: { - show: { - valType: 'boolean', - - dflt: true, - - }, - count: { - valType: 'integer', - - dflt: 2, - min: 1, - - }, - fill: { - valType: 'number', - - min: 0, - max: 1, - dflt: 1, - - }, - pattern: { - valType: 'flaglist', - flags: ['A', 'B', 'C', 'D', 'E'], - extras: ['all', 'odd', 'even'], - dflt: 'all', - - - } - }, - - spaceframe: { - show: { - valType: 'boolean', - - dflt: false, - - }, - fill: { - valType: 'number', - - min: 0, - max: 1, - dflt: 0.15, - - } - }, - - slices: { - x: makeSliceAttr('x'), - y: makeSliceAttr('y'), - z: makeSliceAttr('z') - }, - - caps: { - x: makeCapAttr('x'), - y: makeCapAttr('y'), - z: makeCapAttr('z') - }, - - text: { - valType: 'string', - - dflt: '', - arrayOk: true, - - }, - hovertext: { - valType: 'string', - - dflt: '', - arrayOk: true, - - }, - hovertemplate: hovertemplateAttrs() -}, - -colorScaleAttrs('', { - colorAttr: '`value`', - showScaleDflt: true, - editTypeOverride: 'calc' -}), { - opacity: meshAttrs.opacity, - lightposition: meshAttrs.lightposition, - lighting: meshAttrs.lighting, - flatshading: meshAttrs.flatshading, - contour: meshAttrs.contour, - - hoverinfo: extendFlat({}, baseAttrs.hoverinfo) -}), 'calc', 'nested'); - -// required defaults to speed up surface normal calculations -attrs.flatshading.dflt = true; attrs.lighting.facenormalsepsilon.dflt = 0; - -attrs.x.editType = attrs.y.editType = attrs.z.editType = attrs.value.editType = 'calc+clearAxisTypes'; -attrs.transforms = undefined; - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plots/attributes":764,"../mesh3d/attributes":1053}],1049:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); - -module.exports = function calc(gd, trace) { - trace._len = Math.min(trace.x.length, trace.y.length, trace.z.length, trace.value.length); - - var min = Infinity; - var max = -Infinity; - var len = trace.value.length; - for(var i = 0; i < len; i++) { - var v = trace.value[i]; - min = Math.min(min, v); - max = Math.max(max, v); - } - - trace._minValues = min; - trace._maxValues = max; - - trace._vMin = (trace.isomin === undefined || trace.isomin === null) ? min : trace.isomin; - trace._vMax = (trace.isomax === undefined || trace.isomin === null) ? max : trace.isomax; - - colorscaleCalc(gd, trace, { - vals: [trace._vMin, trace._vMax], - containerStr: '', - cLetter: 'c' - }); -}; - -},{"../../components/colorscale/calc":601}],1050:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var createMesh = _dereq_('gl-mesh3d'); - -var Lib = _dereq_('../../lib'); - -var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; -var str2RgbaArray = _dereq_('../../lib/str2rgbarray'); -var extractOpts = _dereq_('../../components/colorscale').extractOpts; -var zip3 = _dereq_('../../plots/gl3d/zip3'); - -function distinctVals(col) { - return Lib.distinctVals(col).vals; -} - -var findNearestOnAxis = function(w, arr) { - for(var q = arr.length - 1; q > 0; q--) { - var min = Math.min(arr[q], arr[q - 1]); - var max = Math.max(arr[q], arr[q - 1]); - if(max > min && min < w && w <= max) { - return { - id: q, - distRatio: (max - w) / (max - min) - }; - } - } - return { - id: 0, - distRatio: 0 - }; -}; - -function IsosurfaceTrace(scene, mesh, uid) { - this.scene = scene; - this.uid = uid; - this.mesh = mesh; - this.name = ''; - this.data = null; - this.showContour = false; -} - -var proto = IsosurfaceTrace.prototype; - -proto.handlePick = function(selection) { - if(selection.object === this.mesh) { - var rawId = selection.data.index; - - var x = this.data._x[rawId]; - var y = this.data._y[rawId]; - var z = this.data._z[rawId]; - - var height = this.data._Ys.length; - var depth = this.data._Zs.length; - - var i = findNearestOnAxis(x, this.data._Xs).id; - var j = findNearestOnAxis(y, this.data._Ys).id; - var k = findNearestOnAxis(z, this.data._Zs).id; - - var selectIndex = selection.index = k + depth * j + depth * height * i; - - selection.traceCoordinate = [ - this.data._x[selectIndex], - this.data._y[selectIndex], - this.data._z[selectIndex], - this.data.value[selectIndex] - ]; - - var text = this.data.hovertext || this.data.text; - if(Array.isArray(text) && text[selectIndex] !== undefined) { - selection.textLabel = text[selectIndex]; - } else if(text) { - selection.textLabel = text; - } - - return true; - } -}; - -proto.update = function(data) { - var scene = this.scene; - var layout = scene.fullSceneLayout; - - this.data = generateIsoMeshes(data); - - // Unpack position data - function toDataCoords(axis, coord, scale, calendar) { - return coord.map(function(x) { - return axis.d2l(x, 0, calendar) * scale; - }); - } - - var positions = zip3( - toDataCoords(layout.xaxis, data._x, scene.dataScale[0], data.xcalendar), - toDataCoords(layout.yaxis, data._y, scene.dataScale[1], data.ycalendar), - toDataCoords(layout.zaxis, data._z, scene.dataScale[2], data.zcalendar)); - - var cells = zip3(data._i, data._j, data._k); - - var config = { - positions: positions, - cells: cells, - lightPosition: [data.lightposition.x, data.lightposition.y, data.lightposition.z], - ambient: data.lighting.ambient, - diffuse: data.lighting.diffuse, - specular: data.lighting.specular, - roughness: data.lighting.roughness, - fresnel: data.lighting.fresnel, - vertexNormalsEpsilon: data.lighting.vertexnormalsepsilon, - faceNormalsEpsilon: data.lighting.facenormalsepsilon, - opacity: data.opacity, - contourEnable: data.contour.show, - contourColor: str2RgbaArray(data.contour.color).slice(0, 3), - contourWidth: data.contour.width, - useFacetNormals: data.flatshading - }; - - var cOpts = extractOpts(data); - config.vertexIntensity = data._intensity; - config.vertexIntensityBounds = [cOpts.min, cOpts.max]; - config.colormap = parseColorScale(data); - - // Update mesh - this.mesh.update(config); -}; - -proto.dispose = function() { - this.scene.glplot.remove(this.mesh); - this.mesh.dispose(); -}; - -function generateIsoMeshes(data) { - data._i = []; - data._j = []; - data._k = []; - - var showSurface = data.surface.show; - var showSpaceframe = data.spaceframe.show; - - var surfaceFill = data.surface.fill; - var spaceframeFill = data.spaceframe.fill; - - var drawingSurface = false; - var drawingSpaceframe = false; - - var numFaces = 0; - var numVertices; - var beginVertextLength; - - var Xs = distinctVals(data.x.slice(0, data._len)); - var Ys = distinctVals(data.y.slice(0, data._len)); - var Zs = distinctVals(data.z.slice(0, data._len)); - - var width = Xs.length; - var height = Ys.length; - var depth = Zs.length; - - function getIndex(i, j, k) { - return k + depth * j + depth * height * i; - } - - var minValues = data._minValues; - var maxValues = data._maxValues; - - var vMin = data._vMin; - var vMax = data._vMax; - - var allXs; - var allYs; - var allZs; - var allVs; - - function findVertexId(x, y, z) { - // could be used to find the vertex id of previously generated vertex within the group - - var len = allVs.length; - for(var f = beginVertextLength; f < len; f++) { - if( - x === allXs[f] && - y === allYs[f] && - z === allZs[f] - ) { - return f; - } - } - return -1; - } - - function beginGroup() { - beginVertextLength = numVertices; - } - - function emptyVertices() { - allXs = []; - allYs = []; - allZs = []; - allVs = []; - numVertices = 0; - - beginGroup(); - } - - function addVertex(x, y, z, v) { - allXs.push(x); - allYs.push(y); - allZs.push(z); - allVs.push(v); - numVertices++; - - return numVertices - 1; - } - - function addFace(a, b, c) { - data._i.push(a); - data._j.push(b); - data._k.push(c); - numFaces++; - - return numFaces - 1; - } - - function getCenter(A, B, C) { - var M = []; - for(var i = 0; i < A.length; i++) { - M[i] = (A[i] + B[i] + C[i]) / 3.0; - } - return M; - } - - function getBetween(A, B, r) { - var M = []; - for(var i = 0; i < A.length; i++) { - M[i] = A[i] * (1 - r) + r * B[i]; - } - return M; - } - - var activeFill; - function setFill(fill) { - activeFill = fill; - } - - function createOpenTri(xyzv, abc) { - var A = xyzv[0]; - var B = xyzv[1]; - var C = xyzv[2]; - var G = getCenter(A, B, C); - - var r = Math.sqrt(1 - activeFill); - var p1 = getBetween(G, A, r); - var p2 = getBetween(G, B, r); - var p3 = getBetween(G, C, r); - - var a = abc[0]; - var b = abc[1]; - var c = abc[2]; - - return { - xyzv: [ - [A, B, p2], [p2, p1, A], - [B, C, p3], [p3, p2, B], - [C, A, p1], [p1, p3, C] - ], - abc: [ - [a, b, -1], [-1, -1, a], - [b, c, -1], [-1, -1, b], - [c, a, -1], [-1, -1, c] - ] - }; - } - - function styleIncludes(style, char) { - if(style === 'all' || style === null) return true; - return (style.indexOf(char) > -1); - } - - function mapValue(style, value) { - if(style === null) return value; - return style; - } - - function drawTri(style, xyzv, abc) { - beginGroup(); - - var allXYZVs = [xyzv]; - var allABCs = [abc]; - if(activeFill >= 1) { - allXYZVs = [xyzv]; - allABCs = [abc]; - } else if(activeFill > 0) { - var openTri = createOpenTri(xyzv, abc); - allXYZVs = openTri.xyzv; - allABCs = openTri.abc; - } - - for(var f = 0; f < allXYZVs.length; f++) { - xyzv = allXYZVs[f]; - abc = allABCs[f]; - - var pnts = []; - for(var i = 0; i < 3; i++) { - var x = xyzv[i][0]; - var y = xyzv[i][1]; - var z = xyzv[i][2]; - var v = xyzv[i][3]; - - var id = (abc[i] > -1) ? abc[i] : findVertexId(x, y, z); - if(id > -1) { - pnts[i] = id; - } else { - pnts[i] = addVertex(x, y, z, mapValue(style, v)); - } - } - - addFace(pnts[0], pnts[1], pnts[2]); - } - } - - function drawQuad(style, xyzv, abcd) { - var makeTri = function(i, j, k) { - drawTri(style, [xyzv[i], xyzv[j], xyzv[k]], [abcd[i], abcd[j], abcd[k]]); - }; - - makeTri(0, 1, 2); - makeTri(2, 3, 0); - } - - function drawTetra(style, xyzv, abcd) { - var makeTri = function(i, j, k) { - drawTri(style, [xyzv[i], xyzv[j], xyzv[k]], [abcd[i], abcd[j], abcd[k]]); - }; - - makeTri(0, 1, 2); - makeTri(3, 0, 1); - makeTri(2, 3, 0); - makeTri(1, 2, 3); - } - - function calcIntersection(pointOut, pointIn, min, max) { - var value = pointOut[3]; - - if(value < min) value = min; - if(value > max) value = max; - - var ratio = (pointOut[3] - value) / (pointOut[3] - pointIn[3] + 0.000000001); // we had to add this error to force solve the tiny caps - - var result = []; - for(var s = 0; s < 4; s++) { - result[s] = (1 - ratio) * pointOut[s] + ratio * pointIn[s]; - } - return result; - } - - function inRange(value, min, max) { - return ( - value >= min && - value <= max - ); - } - - function almostInFinalRange(value) { - var vErr = 0.001 * (vMax - vMin); - return ( - value >= vMin - vErr && - value <= vMax + vErr - ); - } - - function getXYZV(indecies) { - var xyzv = []; - for(var q = 0; q < 4; q++) { - var index = indecies[q]; - xyzv.push( - [ - data.x[index], - data.y[index], - data.z[index], - data.value[index] - ] - ); - } - - return xyzv; - } - - var MAX_PASS = 3; - - function tryCreateTri(style, xyzv, abc, min, max, nPass) { - if(!nPass) nPass = 1; - - abc = [-1, -1, -1]; // Note: for the moment we override indices - // to run faster! But it is possible to comment this line - // to reduce the number of vertices. - - var result = false; - - var ok = [ - inRange(xyzv[0][3], min, max), - inRange(xyzv[1][3], min, max), - inRange(xyzv[2][3], min, max) - ]; - - if(!ok[0] && !ok[1] && !ok[2]) { - return false; - } - - var tryDrawTri = function(style, xyzv, abc) { - if( // we check here if the points are in `real` iso-min/max range - almostInFinalRange(xyzv[0][3]) && - almostInFinalRange(xyzv[1][3]) && - almostInFinalRange(xyzv[2][3]) - ) { - drawTri(style, xyzv, abc); - return true; - } else if(nPass < MAX_PASS) { - return tryCreateTri(style, xyzv, abc, vMin, vMax, ++nPass); // i.e. second pass using actual vMin vMax bounds - } - return false; - }; - - if(ok[0] && ok[1] && ok[2]) { - return tryDrawTri(style, xyzv, abc) || result; - } - - var interpolated = false; - - [ - [0, 1, 2], - [2, 0, 1], - [1, 2, 0] - ].forEach(function(e) { - if(ok[e[0]] && ok[e[1]] && !ok[e[2]]) { - var A = xyzv[e[0]]; - var B = xyzv[e[1]]; - var C = xyzv[e[2]]; - - var p1 = calcIntersection(C, A, min, max); - var p2 = calcIntersection(C, B, min, max); - - result = tryDrawTri(style, [p2, p1, A], [-1, -1, abc[e[0]]]) || result; - result = tryDrawTri(style, [A, B, p2], [abc[e[0]], abc[e[1]], -1]) || result; - - interpolated = true; - } - }); - if(interpolated) return result; - - [ - [0, 1, 2], - [1, 2, 0], - [2, 0, 1] - ].forEach(function(e) { - if(ok[e[0]] && !ok[e[1]] && !ok[e[2]]) { - var A = xyzv[e[0]]; - var B = xyzv[e[1]]; - var C = xyzv[e[2]]; - - var p1 = calcIntersection(B, A, min, max); - var p2 = calcIntersection(C, A, min, max); - - result = tryDrawTri(style, [p2, p1, A], [-1, -1, abc[e[0]]]) || result; - - interpolated = true; - } - }); - return result; - } - - function tryCreateTetra(style, abcd, min, max) { - var result = false; - - var xyzv = getXYZV(abcd); - - var ok = [ - inRange(xyzv[0][3], min, max), - inRange(xyzv[1][3], min, max), - inRange(xyzv[2][3], min, max), - inRange(xyzv[3][3], min, max) - ]; - - if(!ok[0] && !ok[1] && !ok[2] && !ok[3]) { - return result; - } - - if(ok[0] && ok[1] && ok[2] && ok[3]) { - if(drawingSpaceframe) { - result = drawTetra(style, xyzv, abcd) || result; - } - return result; - } - - var interpolated = false; - - [ - [0, 1, 2, 3], - [3, 0, 1, 2], - [2, 3, 0, 1], - [1, 2, 3, 0] - ].forEach(function(e) { - if(ok[e[0]] && ok[e[1]] && ok[e[2]] && !ok[e[3]]) { - var A = xyzv[e[0]]; - var B = xyzv[e[1]]; - var C = xyzv[e[2]]; - var D = xyzv[e[3]]; - - if(drawingSpaceframe) { - result = drawTri(style, [A, B, C], [abcd[e[0]], abcd[e[1]], abcd[e[2]]]) || result; - } else { - var p1 = calcIntersection(D, A, min, max); - var p2 = calcIntersection(D, B, min, max); - var p3 = calcIntersection(D, C, min, max); - - result = drawTri(null, [p1, p2, p3], [-1, -1, -1]) || result; - } - - interpolated = true; - } - }); - if(interpolated) return result; - - [ - [0, 1, 2, 3], - [1, 2, 3, 0], - [2, 3, 0, 1], - [3, 0, 1, 2], - [0, 2, 3, 1], - [1, 3, 2, 0] - ].forEach(function(e) { - if(ok[e[0]] && ok[e[1]] && !ok[e[2]] && !ok[e[3]]) { - var A = xyzv[e[0]]; - var B = xyzv[e[1]]; - var C = xyzv[e[2]]; - var D = xyzv[e[3]]; - - var p1 = calcIntersection(C, A, min, max); - var p2 = calcIntersection(C, B, min, max); - var p3 = calcIntersection(D, B, min, max); - var p4 = calcIntersection(D, A, min, max); - - if(drawingSpaceframe) { - result = drawTri(style, [A, p4, p1], [abcd[e[0]], -1, -1]) || result; - result = drawTri(style, [B, p2, p3], [abcd[e[1]], -1, -1]) || result; - } else { - result = drawQuad(null, [p1, p2, p3, p4], [-1, -1, -1, -1]) || result; - } - - interpolated = true; - } - }); - if(interpolated) return result; - - [ - [0, 1, 2, 3], - [1, 2, 3, 0], - [2, 3, 0, 1], - [3, 0, 1, 2] - ].forEach(function(e) { - if(ok[e[0]] && !ok[e[1]] && !ok[e[2]] && !ok[e[3]]) { - var A = xyzv[e[0]]; - var B = xyzv[e[1]]; - var C = xyzv[e[2]]; - var D = xyzv[e[3]]; - - var p1 = calcIntersection(B, A, min, max); - var p2 = calcIntersection(C, A, min, max); - var p3 = calcIntersection(D, A, min, max); - - if(drawingSpaceframe) { - result = drawTri(style, [A, p1, p2], [abcd[e[0]], -1, -1]) || result; - result = drawTri(style, [A, p2, p3], [abcd[e[0]], -1, -1]) || result; - result = drawTri(style, [A, p3, p1], [abcd[e[0]], -1, -1]) || result; - } else { - result = drawTri(null, [p1, p2, p3], [-1, -1, -1]) || result; - } - - interpolated = true; - } - }); - return result; - } - - function addCube(style, p000, p001, p010, p011, p100, p101, p110, p111, min, max) { - var result = false; - - if(drawingSurface) { - if(styleIncludes(style, 'A')) { - result = tryCreateTetra(null, [p000, p001, p010, p100], min, max) || result; - } - if(styleIncludes(style, 'B')) { - result = tryCreateTetra(null, [p001, p010, p011, p111], min, max) || result; - } - if(styleIncludes(style, 'C')) { - result = tryCreateTetra(null, [p001, p100, p101, p111], min, max) || result; - } - if(styleIncludes(style, 'D')) { - result = tryCreateTetra(null, [p010, p100, p110, p111], min, max) || result; - } - if(styleIncludes(style, 'E')) { - result = tryCreateTetra(null, [p001, p010, p100, p111], min, max) || result; - } - } - - if(drawingSpaceframe) { - result = tryCreateTetra(style, [p001, p010, p100, p111], min, max) || result; - } - - return result; - } - - function addRect(style, a, b, c, d, min, max, previousResult) { - return [ - (previousResult[0] === true) ? true : - tryCreateTri(style, getXYZV([a, b, c]), [a, b, c], min, max), - (previousResult[1] === true) ? true : - tryCreateTri(style, getXYZV([c, d, a]), [c, d, a], min, max) - ]; - } - - function begin2dCell(style, p00, p01, p10, p11, min, max, isEven, previousResult) { - // used to create caps and/or slices on exact axis points - if(isEven) { - return addRect(style, p00, p01, p11, p10, min, max, previousResult); - } else { - return addRect(style, p01, p11, p10, p00, min, max, previousResult); - } - } - - function beginSection(style, i, j, k, min, max, distRatios) { - // used to create slices between axis points - - var result = false; - var A, B, C, D; - - var makeSection = function() { - result = tryCreateTri(style, [A, B, C], [-1, -1, -1], min, max) || result; - result = tryCreateTri(style, [C, D, A], [-1, -1, -1], min, max) || result; - }; - - var rX = distRatios[0]; - var rY = distRatios[1]; - var rZ = distRatios[2]; - - if(rX) { - A = getBetween(getXYZV([getIndex(i, j - 0, k - 0)])[0], getXYZV([getIndex(i - 1, j - 0, k - 0)])[0], rX); - B = getBetween(getXYZV([getIndex(i, j - 0, k - 1)])[0], getXYZV([getIndex(i - 1, j - 0, k - 1)])[0], rX); - C = getBetween(getXYZV([getIndex(i, j - 1, k - 1)])[0], getXYZV([getIndex(i - 1, j - 1, k - 1)])[0], rX); - D = getBetween(getXYZV([getIndex(i, j - 1, k - 0)])[0], getXYZV([getIndex(i - 1, j - 1, k - 0)])[0], rX); - makeSection(); - } - - if(rY) { - A = getBetween(getXYZV([getIndex(i - 0, j, k - 0)])[0], getXYZV([getIndex(i - 0, j - 1, k - 0)])[0], rY); - B = getBetween(getXYZV([getIndex(i - 0, j, k - 1)])[0], getXYZV([getIndex(i - 0, j - 1, k - 1)])[0], rY); - C = getBetween(getXYZV([getIndex(i - 1, j, k - 1)])[0], getXYZV([getIndex(i - 1, j - 1, k - 1)])[0], rY); - D = getBetween(getXYZV([getIndex(i - 1, j, k - 0)])[0], getXYZV([getIndex(i - 1, j - 1, k - 0)])[0], rY); - makeSection(); - } - - if(rZ) { - A = getBetween(getXYZV([getIndex(i - 0, j - 0, k)])[0], getXYZV([getIndex(i - 0, j - 0, k - 1)])[0], rZ); - B = getBetween(getXYZV([getIndex(i - 0, j - 1, k)])[0], getXYZV([getIndex(i - 0, j - 1, k - 1)])[0], rZ); - C = getBetween(getXYZV([getIndex(i - 1, j - 1, k)])[0], getXYZV([getIndex(i - 1, j - 1, k - 1)])[0], rZ); - D = getBetween(getXYZV([getIndex(i - 1, j - 0, k)])[0], getXYZV([getIndex(i - 1, j - 0, k - 1)])[0], rZ); - makeSection(); - } - - return result; - } - - function begin3dCell(style, p000, p001, p010, p011, p100, p101, p110, p111, min, max, isEven) { - // used to create spaceframe and/or iso-surfaces - - var cellStyle = style; - if(isEven) { - if(drawingSurface && style === 'even') cellStyle = null; - return addCube(cellStyle, p000, p001, p010, p011, p100, p101, p110, p111, min, max); - } else { - if(drawingSurface && style === 'odd') cellStyle = null; - return addCube(cellStyle, p111, p110, p101, p100, p011, p010, p001, p000, min, max); - } - } - - function draw2dX(style, items, min, max, previousResult) { - var result = []; - var n = 0; - for(var q = 0; q < items.length; q++) { - var i = items[q]; - for(var k = 1; k < depth; k++) { - for(var j = 1; j < height; j++) { - result.push( - begin2dCell(style, - getIndex(i, j - 1, k - 1), - getIndex(i, j - 1, k), - getIndex(i, j, k - 1), - getIndex(i, j, k), - min, - max, - (i + j + k) % 2, - (previousResult && previousResult[n]) ? previousResult[n] : [] - ) - ); - n++; - } - } - } - return result; - } - - function draw2dY(style, items, min, max, previousResult) { - var result = []; - var n = 0; - for(var q = 0; q < items.length; q++) { - var j = items[q]; - for(var i = 1; i < width; i++) { - for(var k = 1; k < depth; k++) { - result.push( - begin2dCell(style, - getIndex(i - 1, j, k - 1), - getIndex(i, j, k - 1), - getIndex(i - 1, j, k), - getIndex(i, j, k), - min, - max, - (i + j + k) % 2, - (previousResult && previousResult[n]) ? previousResult[n] : [] - ) - ); - n++; - } - } - } - return result; - } - - function draw2dZ(style, items, min, max, previousResult) { - var result = []; - var n = 0; - for(var q = 0; q < items.length; q++) { - var k = items[q]; - for(var j = 1; j < height; j++) { - for(var i = 1; i < width; i++) { - result.push( - begin2dCell(style, - getIndex(i - 1, j - 1, k), - getIndex(i - 1, j, k), - getIndex(i, j - 1, k), - getIndex(i, j, k), - min, - max, - (i + j + k) % 2, - (previousResult && previousResult[n]) ? previousResult[n] : [] - ) - ); - n++; - } - } - } - return result; - } - - function draw3d(style, min, max) { - for(var k = 1; k < depth; k++) { - for(var j = 1; j < height; j++) { - for(var i = 1; i < width; i++) { - begin3dCell(style, - getIndex(i - 1, j - 1, k - 1), - getIndex(i - 1, j - 1, k), - getIndex(i - 1, j, k - 1), - getIndex(i - 1, j, k), - getIndex(i, j - 1, k - 1), - getIndex(i, j - 1, k), - getIndex(i, j, k - 1), - getIndex(i, j, k), - min, - max, - (i + j + k) % 2 - ); - } - } - } - } - - function drawSpaceframe(style, min, max) { - drawingSpaceframe = true; - draw3d(style, min, max); - drawingSpaceframe = false; - } - - function drawSurface(style, min, max) { - drawingSurface = true; - draw3d(style, min, max); - drawingSurface = false; - } - - function drawSectionX(style, items, min, max, distRatios, previousResult) { - var result = []; - var n = 0; - for(var q = 0; q < items.length; q++) { - var i = items[q]; - for(var k = 1; k < depth; k++) { - for(var j = 1; j < height; j++) { - result.push( - beginSection(style, i, j, k, min, max, distRatios[q], - (previousResult && previousResult[n]) ? previousResult[n] : [] - ) - ); - n++; - } - } - } - return result; - } - - function drawSectionY(style, items, min, max, distRatios, previousResult) { - var result = []; - var n = 0; - for(var q = 0; q < items.length; q++) { - var j = items[q]; - for(var i = 1; i < width; i++) { - for(var k = 1; k < depth; k++) { - result.push( - beginSection(style, i, j, k, min, max, distRatios[q], - (previousResult && previousResult[n]) ? previousResult[n] : [] - ) - ); - n++; - } - } - } - return result; - } - - function drawSectionZ(style, items, min, max, distRatios, previousResult) { - var result = []; - var n = 0; - for(var q = 0; q < items.length; q++) { - var k = items[q]; - for(var j = 1; j < height; j++) { - for(var i = 1; i < width; i++) { - result.push( - beginSection(style, i, j, k, min, max, distRatios[q], - (previousResult && previousResult[n]) ? previousResult[n] : [] - ) - ); - n++; - } - } - } - return result; - } - - function createRange(a, b) { - var range = []; - for(var q = a; q < b; q++) { - range.push(q); - } - return range; - } - - function insertGridPoints() { - for(var i = 0; i < width; i++) { - for(var j = 0; j < height; j++) { - for(var k = 0; k < depth; k++) { - var index = getIndex(i, j, k); - addVertex( - data.x[index], - data.y[index], - data.z[index], - data.value[index] - ); - } - } - } - } - - function drawAll() { - emptyVertices(); - - // insert grid points - insertGridPoints(); - - var activeStyle = null; - - // draw spaceframes - if(showSpaceframe && spaceframeFill) { - setFill(spaceframeFill); - - drawSpaceframe(activeStyle, vMin, vMax); - } - - // draw iso-surfaces - if(showSurface && surfaceFill) { - setFill(surfaceFill); - - var surfacePattern = data.surface.pattern; - var surfaceCount = data.surface.count; - for(var q = 0; q < surfaceCount; q++) { - var ratio = (surfaceCount === 1) ? 0.5 : q / (surfaceCount - 1); - var level = (1 - ratio) * vMin + ratio * vMax; - - var d1 = Math.abs(level - minValues); - var d2 = Math.abs(level - maxValues); - var ranges = (d1 > d2) ? - [minValues, level] : - [level, maxValues]; - - drawSurface(surfacePattern, ranges[0], ranges[1]); - } - } - - var setupMinMax = [ - [ Math.min(vMin, maxValues), Math.max(vMin, maxValues) ], - [ Math.min(minValues, vMax), Math.max(minValues, vMax) ] - ]; - - ['x', 'y', 'z'].forEach(function(e) { - var preRes = []; - for(var s = 0; s < setupMinMax.length; s++) { - var count = 0; - - var activeMin = setupMinMax[s][0]; - var activeMax = setupMinMax[s][1]; - - // draw slices - var slice = data.slices[e]; - if(slice.show && slice.fill) { - setFill(slice.fill); - - var exactIndices = []; - var ceilIndices = []; - var distRatios = []; - if(slice.locations.length) { - for(var q = 0; q < slice.locations.length; q++) { - var near = findNearestOnAxis( - slice.locations[q], - (e === 'x') ? Xs : - (e === 'y') ? Ys : Zs - ); - - if(near.distRatio === 0) { - exactIndices.push(near.id); - } else if(near.id > 0) { - ceilIndices.push(near.id); - if(e === 'x') { - distRatios.push([near.distRatio, 0, 0]); - } else if(e === 'y') { - distRatios.push([0, near.distRatio, 0]); - } else { - distRatios.push([0, 0, near.distRatio]); - } - } - } - } else { - if(e === 'x') { - exactIndices = createRange(1, width - 1); - } else if(e === 'y') { - exactIndices = createRange(1, height - 1); - } else { - exactIndices = createRange(1, depth - 1); - } - } - - if(ceilIndices.length > 0) { - if(e === 'x') { - preRes[count] = drawSectionX(activeStyle, ceilIndices, activeMin, activeMax, distRatios, preRes[count]); - } else if(e === 'y') { - preRes[count] = drawSectionY(activeStyle, ceilIndices, activeMin, activeMax, distRatios, preRes[count]); - } else { - preRes[count] = drawSectionZ(activeStyle, ceilIndices, activeMin, activeMax, distRatios, preRes[count]); - } - count++; - } - - if(exactIndices.length > 0) { - if(e === 'x') { - preRes[count] = draw2dX(activeStyle, exactIndices, activeMin, activeMax, preRes[count]); - } else if(e === 'y') { - preRes[count] = draw2dY(activeStyle, exactIndices, activeMin, activeMax, preRes[count]); - } else { - preRes[count] = draw2dZ(activeStyle, exactIndices, activeMin, activeMax, preRes[count]); - } - count++; - } - } - - // draw caps - var cap = data.caps[e]; - if(cap.show && cap.fill) { - setFill(cap.fill); - if(e === 'x') { - preRes[count] = draw2dX(activeStyle, [0, width - 1], activeMin, activeMax, preRes[count]); - } else if(e === 'y') { - preRes[count] = draw2dY(activeStyle, [0, height - 1], activeMin, activeMax, preRes[count]); - } else { - preRes[count] = draw2dZ(activeStyle, [0, depth - 1], activeMin, activeMax, preRes[count]); - } - count++; - } - } - }); - - // remove vertices arrays (i.e. grid points) in case no face was created. - if(numFaces === 0) { - emptyVertices(); - } - - data._x = allXs; - data._y = allYs; - data._z = allZs; - data._intensity = allVs; - - data._Xs = Xs; - data._Ys = Ys; - data._Zs = Zs; - } - - drawAll(); - - return data; -} - -function createIsosurfaceTrace(scene, data) { - var gl = scene.glplot.gl; - var mesh = createMesh({gl: gl}); - var result = new IsosurfaceTrace(scene, mesh, data.uid); - - mesh._trace = result; - result.update(data); - scene.glplot.add(mesh); - return result; -} - -module.exports = { - findNearestOnAxis: findNearestOnAxis, - generateIsoMeshes: generateIsoMeshes, - createIsosurfaceTrace: createIsosurfaceTrace, -}; - -},{"../../components/colorscale":605,"../../lib":719,"../../lib/gl_format_color":716,"../../lib/str2rgbarray":742,"../../plots/gl3d/zip3":818,"gl-mesh3d":280}],1051:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); -var attributes = _dereq_('./attributes'); -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); - -function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - supplyIsoDefaults(traceIn, traceOut, defaultColor, layout, coerce); -} - -function supplyIsoDefaults(traceIn, traceOut, defaultColor, layout, coerce) { - var isomin = coerce('isomin'); - var isomax = coerce('isomax'); - - if(isomax !== undefined && isomax !== null && - isomin !== undefined && isomin !== null && - isomin > isomax) { - // applying default values in this case: - traceOut.isomin = null; - traceOut.isomax = null; - } - - var x = coerce('x'); - var y = coerce('y'); - var z = coerce('z'); - var value = coerce('value'); - - if( - !x || !x.length || - !y || !y.length || - !z || !z.length || - !value || !value.length - ) { - traceOut.visible = false; - return; - } - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout); - - ['x', 'y', 'z'].forEach(function(dim) { - var capDim = 'caps.' + dim; - var showCap = coerce(capDim + '.show'); - if(showCap) { - coerce(capDim + '.fill'); - } - - var sliceDim = 'slices.' + dim; - var showSlice = coerce(sliceDim + '.show'); - if(showSlice) { - coerce(sliceDim + '.fill'); - coerce(sliceDim + '.locations'); - } - }); - - var showSpaceframe = coerce('spaceframe.show'); - if(showSpaceframe) { - coerce('spaceframe.fill'); - } - - var showSurface = coerce('surface.show'); - if(showSurface) { - coerce('surface.count'); - coerce('surface.fill'); - coerce('surface.pattern'); - } - - var showContour = coerce('contour.show'); - if(showContour) { - coerce('contour.color'); - coerce('contour.width'); - } - - // Coerce remaining properties - [ - 'text', - 'hovertext', - 'hovertemplate', - 'lighting.ambient', - 'lighting.diffuse', - 'lighting.specular', - 'lighting.roughness', - 'lighting.fresnel', - 'lighting.vertexnormalsepsilon', - 'lighting.facenormalsepsilon', - 'lightposition.x', - 'lightposition.y', - 'lightposition.z', - 'flatshading', - 'opacity' - ].forEach(function(x) { coerce(x); }); - - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); - - // disable 1D transforms (for now) - traceOut._length = null; -} - -module.exports = { - supplyDefaults: supplyDefaults, - supplyIsoDefaults: supplyIsoDefaults -}; - -},{"../../components/colorscale/defaults":603,"../../lib":719,"../../registry":847,"./attributes":1048}],1052:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults').supplyDefaults, - calc: _dereq_('./calc'), - colorbar: { - min: 'cmin', - max: 'cmax' - }, - plot: _dereq_('./convert').createIsosurfaceTrace, - - moduleType: 'trace', - name: 'isosurface', - basePlotModule: _dereq_('../../plots/gl3d'), - categories: ['gl3d'], - meta: { - - } -}; - -},{"../../plots/gl3d":807,"./attributes":1048,"./calc":1049,"./convert":1050,"./defaults":1051}],1053:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var surfaceAtts = _dereq_('../surface/attributes'); -var baseAttrs = _dereq_('../../plots/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = extendFlat({ - x: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - y: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - z: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - - i: { - valType: 'data_array', - editType: 'calc', - - }, - j: { - valType: 'data_array', - editType: 'calc', - - - }, - k: { - valType: 'data_array', - editType: 'calc', - - - }, - - text: { - valType: 'string', - - dflt: '', - arrayOk: true, - editType: 'calc', - - }, - hovertext: { - valType: 'string', - - dflt: '', - arrayOk: true, - editType: 'calc', - - }, - hovertemplate: hovertemplateAttrs({editType: 'calc'}), - - delaunayaxis: { - valType: 'enumerated', - - values: [ 'x', 'y', 'z' ], - dflt: 'z', - editType: 'calc', - - }, - - alphahull: { - valType: 'number', - - dflt: -1, - editType: 'calc', - - }, - - intensity: { - valType: 'data_array', - editType: 'calc', - - }, - - // Color field - color: { - valType: 'color', - - editType: 'calc', - - }, - vertexcolor: { - valType: 'data_array', - - editType: 'calc', - - }, - facecolor: { - valType: 'data_array', - - editType: 'calc', - - }, - transforms: undefined -}, - -colorScaleAttrs('', { - colorAttr: '`intensity`', - showScaleDflt: true, - editTypeOverride: 'calc' -}), { - opacity: surfaceAtts.opacity, - - // Flat shaded mode - flatshading: { - valType: 'boolean', - - dflt: false, - editType: 'calc', - - }, - - contour: { - show: extendFlat({}, surfaceAtts.contours.x.show, { - - }), - color: surfaceAtts.contours.x.color, - width: surfaceAtts.contours.x.width, - editType: 'calc' - }, - - lightposition: { - x: extendFlat({}, surfaceAtts.lightposition.x, {dflt: 1e5}), - y: extendFlat({}, surfaceAtts.lightposition.y, {dflt: 1e5}), - z: extendFlat({}, surfaceAtts.lightposition.z, {dflt: 0}), - editType: 'calc' - }, - lighting: extendFlat({ - vertexnormalsepsilon: { - valType: 'number', - - min: 0.00, - max: 1, - dflt: 1e-12, // otherwise finely tessellated things eg. the brain will have no specular light reflection - editType: 'calc', - - }, - facenormalsepsilon: { - valType: 'number', - - min: 0.00, - max: 1, - dflt: 1e-6, // even the brain model doesn't appear to need finer than this - editType: 'calc', - - }, - editType: 'calc' - }, surfaceAtts.lighting), - - hoverinfo: extendFlat({}, baseAttrs.hoverinfo, {editType: 'calc'}) -}); - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../surface/attributes":1224}],1054:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); - -module.exports = function calc(gd, trace) { - if(trace.intensity) { - colorscaleCalc(gd, trace, { - vals: trace.intensity, - containerStr: '', - cLetter: 'c' - }); - } -}; - -},{"../../components/colorscale/calc":601}],1055:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var createMesh = _dereq_('gl-mesh3d'); -var triangulate = _dereq_('delaunay-triangulate'); -var alphaShape = _dereq_('alpha-shape'); -var convexHull = _dereq_('convex-hull'); - -var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; -var str2RgbaArray = _dereq_('../../lib/str2rgbarray'); -var extractOpts = _dereq_('../../components/colorscale').extractOpts; -var zip3 = _dereq_('../../plots/gl3d/zip3'); - -function Mesh3DTrace(scene, mesh, uid) { - this.scene = scene; - this.uid = uid; - this.mesh = mesh; - this.name = ''; - this.color = '#fff'; - this.data = null; - this.showContour = false; -} - -var proto = Mesh3DTrace.prototype; - -proto.handlePick = function(selection) { - if(selection.object === this.mesh) { - var selectIndex = selection.index = selection.data.index; - - selection.traceCoordinate = [ - this.data.x[selectIndex], - this.data.y[selectIndex], - this.data.z[selectIndex] - ]; - - var text = this.data.hovertext || this.data.text; - if(Array.isArray(text) && text[selectIndex] !== undefined) { - selection.textLabel = text[selectIndex]; - } else if(text) { - selection.textLabel = text; - } - - return true; - } -}; - -function parseColorArray(colors) { - var b = []; - var len = colors.length; - for(var i = 0; i < len; i++) { - b[i] = str2RgbaArray(colors[i]); - } - return b; -} - -// Unpack position data -function toDataCoords(axis, coord, scale, calendar) { - var b = []; - var len = coord.length; - for(var i = 0; i < len; i++) { - b[i] = axis.d2l(coord[i], 0, calendar) * scale; - } - return b; -} - -// Round indices if passed as floats -function toRoundIndex(a) { - var b = []; - var len = a.length; - for(var i = 0; i < len; i++) { - b[i] = Math.round(a[i]); - } - return b; -} - -function delaunayCells(delaunayaxis, positions) { - var d = ['x', 'y', 'z'].indexOf(delaunayaxis); - var b = []; - var len = positions.length; - for(var i = 0; i < len; i++) { - b[i] = [positions[i][(d + 1) % 3], positions[i][(d + 2) % 3]]; - } - return triangulate(b); -} - -// Validate indices -function hasValidIndices(list, numVertices) { - var len = list.length; - for(var i = 0; i < len; i++) { - if(list[i] <= -0.5 || list[i] >= numVertices - 0.5) { // Note: the indices would be rounded -0.49 is valid. - return false; - } - } - return true; -} - -proto.update = function(data) { - var scene = this.scene; - var layout = scene.fullSceneLayout; - - this.data = data; - - var numVertices = data.x.length; - - var positions = zip3( - toDataCoords(layout.xaxis, data.x, scene.dataScale[0], data.xcalendar), - toDataCoords(layout.yaxis, data.y, scene.dataScale[1], data.ycalendar), - toDataCoords(layout.zaxis, data.z, scene.dataScale[2], data.zcalendar) - ); - - var cells; - if(data.i && data.j && data.k) { - if( - data.i.length !== data.j.length || - data.j.length !== data.k.length || - !hasValidIndices(data.i, numVertices) || - !hasValidIndices(data.j, numVertices) || - !hasValidIndices(data.k, numVertices) - ) { - return; - } - cells = zip3( - toRoundIndex(data.i), - toRoundIndex(data.j), - toRoundIndex(data.k) - ); - } else if(data.alphahull === 0) { - cells = convexHull(positions); - } else if(data.alphahull > 0) { - cells = alphaShape(data.alphahull, positions); - } else { - cells = delaunayCells(data.delaunayaxis, positions); - } - - var config = { - positions: positions, - cells: cells, - lightPosition: [data.lightposition.x, data.lightposition.y, data.lightposition.z], - ambient: data.lighting.ambient, - diffuse: data.lighting.diffuse, - specular: data.lighting.specular, - roughness: data.lighting.roughness, - fresnel: data.lighting.fresnel, - vertexNormalsEpsilon: data.lighting.vertexnormalsepsilon, - faceNormalsEpsilon: data.lighting.facenormalsepsilon, - opacity: data.opacity, - contourEnable: data.contour.show, - contourColor: str2RgbaArray(data.contour.color).slice(0, 3), - contourWidth: data.contour.width, - useFacetNormals: data.flatshading - }; - - if(data.intensity) { - var cOpts = extractOpts(data); - this.color = '#fff'; - config.vertexIntensity = data.intensity; - config.vertexIntensityBounds = [cOpts.min, cOpts.max]; - config.colormap = parseColorScale(data); - } else if(data.vertexcolor) { - this.color = data.vertexcolor[0]; - config.vertexColors = parseColorArray(data.vertexcolor); - } else if(data.facecolor) { - this.color = data.facecolor[0]; - config.cellColors = parseColorArray(data.facecolor); - } else { - this.color = data.color; - config.meshColor = str2RgbaArray(data.color); - } - - // Update mesh - this.mesh.update(config); -}; - -proto.dispose = function() { - this.scene.glplot.remove(this.mesh); - this.mesh.dispose(); -}; - -function createMesh3DTrace(scene, data) { - var gl = scene.glplot.gl; - var mesh = createMesh({gl: gl}); - var result = new Mesh3DTrace(scene, mesh, data.uid); - mesh._trace = result; - result.update(data); - scene.glplot.add(mesh); - return result; -} - -module.exports = createMesh3DTrace; - -},{"../../components/colorscale":605,"../../lib/gl_format_color":716,"../../lib/str2rgbarray":742,"../../plots/gl3d/zip3":818,"alpha-shape":64,"convex-hull":130,"delaunay-triangulate":165,"gl-mesh3d":280}],1056:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - // read in face/vertex properties - function readComponents(array) { - var ret = array.map(function(attr) { - var result = coerce(attr); - - if(result && Lib.isArrayOrTypedArray(result)) return result; - return null; - }); - - return ret.every(function(x) { - return x && x.length === ret[0].length; - }) && ret; - } - - var coords = readComponents(['x', 'y', 'z']); - if(!coords) { - traceOut.visible = false; - return; - } - - readComponents(['i', 'j', 'k']); - // three indices should be all provided or not - if( - (traceOut.i && (!traceOut.j || !traceOut.k)) || - (traceOut.j && (!traceOut.k || !traceOut.i)) || - (traceOut.k && (!traceOut.i || !traceOut.j)) - ) { - traceOut.visible = false; - return; - } - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout); - - // Coerce remaining properties - [ - 'lighting.ambient', - 'lighting.diffuse', - 'lighting.specular', - 'lighting.roughness', - 'lighting.fresnel', - 'lighting.vertexnormalsepsilon', - 'lighting.facenormalsepsilon', - 'lightposition.x', - 'lightposition.y', - 'lightposition.z', - 'contour.show', - 'contour.color', - 'contour.width', - 'colorscale', - 'reversescale', - 'flatshading', - 'alphahull', - 'delaunayaxis', - 'opacity' - ].forEach(function(x) { coerce(x); }); - - if('intensity' in traceIn) { - coerce('intensity'); - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); - } else { - traceOut.showscale = false; - - if('facecolor' in traceIn) coerce('facecolor'); - else if('vertexcolor' in traceIn) coerce('vertexcolor'); - else coerce('color', defaultColor); - } - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - // disable 1D transforms - // x/y/z should match lengths, and i/j/k should match as well, but - // the two sets have different lengths so transforms wouldn't work. - traceOut._length = null; -}; - -},{"../../components/colorscale/defaults":603,"../../lib":719,"../../registry":847,"./attributes":1053}],1057:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('./calc'), - colorbar: { - min: 'cmin', - max: 'cmax' - }, - plot: _dereq_('./convert'), - - moduleType: 'trace', - name: 'mesh3d', - basePlotModule: _dereq_('../../plots/gl3d'), - categories: ['gl3d'], - meta: { - - } -}; - -},{"../../plots/gl3d":807,"./attributes":1053,"./calc":1054,"./convert":1055,"./defaults":1056}],1058:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var extendFlat = _dereq_('../../lib').extendFlat; -var scatterAttrs = _dereq_('../scatter/attributes'); -var dash = _dereq_('../../components/drawing/attributes').dash; -var fxAttrs = _dereq_('../../components/fx/attributes'); -var delta = _dereq_('../../constants/delta.js'); - -var INCREASING_COLOR = delta.INCREASING.COLOR; -var DECREASING_COLOR = delta.DECREASING.COLOR; - -var lineAttrs = scatterAttrs.line; - -function directionAttrs(lineColorDefault) { - return { - line: { - color: extendFlat({}, lineAttrs.color, {dflt: lineColorDefault}), - width: lineAttrs.width, - dash: dash, - editType: 'style' - }, - editType: 'style' - }; -} - -module.exports = { - - x: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - - open: { - valType: 'data_array', - editType: 'calc', - - }, - - high: { - valType: 'data_array', - editType: 'calc', - - }, - - low: { - valType: 'data_array', - editType: 'calc', - - }, - - close: { - valType: 'data_array', - editType: 'calc', - - }, - - line: { - width: extendFlat({}, lineAttrs.width, { - - }), - dash: extendFlat({}, dash, { - - }), - editType: 'style' - }, - - increasing: directionAttrs(INCREASING_COLOR), - - decreasing: directionAttrs(DECREASING_COLOR), - - text: { - valType: 'string', - - dflt: '', - arrayOk: true, - editType: 'calc', - - }, - hovertext: { - valType: 'string', - - dflt: '', - arrayOk: true, - editType: 'calc', - - }, - - tickwidth: { - valType: 'number', - min: 0, - max: 0.5, - dflt: 0.3, - - editType: 'calc', - - }, - - hoverlabel: extendFlat({}, fxAttrs.hoverlabel, { - split: { - valType: 'boolean', - - dflt: false, - editType: 'style', - - } - }), -}; - -},{"../../components/drawing/attributes":613,"../../components/fx/attributes":623,"../../constants/delta.js":689,"../../lib":719,"../scatter/attributes":1112}],1059:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var _ = Lib._; -var Axes = _dereq_('../../plots/cartesian/axes'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -function calc(gd, trace) { - var xa = Axes.getFromId(gd, trace.xaxis); - var ya = Axes.getFromId(gd, trace.yaxis); - - var tickLen = convertTickWidth(gd, xa, trace); - var minDiff = trace._minDiff; - trace._minDiff = null; - var x = trace._xcalc; - trace._xcalc = null; - - var cd = calcCommon(gd, trace, x, ya, ptFunc); - - trace._extremes[xa._id] = Axes.findExtremes(xa, x, {vpad: minDiff / 2}); - if(cd.length) { - Lib.extendFlat(cd[0].t, { - wHover: minDiff / 2, - tickLen: tickLen - }); - return cd; - } else { - return [{t: {empty: true}}]; - } -} - -function ptFunc(o, h, l, c) { - return { - o: o, - h: h, - l: l, - c: c - }; -} - - -// shared between OHLC and candlestick -// ptFunc makes a calcdata point specific to each trace type, from oi, hi, li, ci -function calcCommon(gd, trace, x, ya, ptFunc) { - var o = ya.makeCalcdata(trace, 'open'); - var h = ya.makeCalcdata(trace, 'high'); - var l = ya.makeCalcdata(trace, 'low'); - var c = ya.makeCalcdata(trace, 'close'); - - var hasTextArray = Array.isArray(trace.text); - var hasHovertextArray = Array.isArray(trace.hovertext); - - // we're optimists - before we have any changing data, assume increasing - var increasing = true; - var cPrev = null; - - var cd = []; - for(var i = 0; i < x.length; i++) { - var xi = x[i]; - var oi = o[i]; - var hi = h[i]; - var li = l[i]; - var ci = c[i]; - - if(xi !== BADNUM && oi !== BADNUM && hi !== BADNUM && li !== BADNUM && ci !== BADNUM) { - if(ci === oi) { - // if open == close, look for a change from the previous close - if(cPrev !== null && ci !== cPrev) increasing = ci > cPrev; - // else (c === cPrev or cPrev is null) no change - } else increasing = ci > oi; - - cPrev = ci; - - var pt = ptFunc(oi, hi, li, ci); - - pt.pos = xi; - pt.yc = (oi + ci) / 2; - pt.i = i; - pt.dir = increasing ? 'increasing' : 'decreasing'; - - // For categoryorder, store low and high - pt.x = pt.pos; - pt.y = [li, hi]; - - if(hasTextArray) pt.tx = trace.text[i]; - if(hasHovertextArray) pt.htx = trace.hovertext[i]; - - cd.push(pt); - } else { - cd.push({pos: xi, empty: true}); - } - } - - trace._extremes[ya._id] = Axes.findExtremes(ya, Lib.concat(l, h), {padded: true}); - - if(cd.length) { - cd[0].t = { - labels: { - open: _(gd, 'open:') + ' ', - high: _(gd, 'high:') + ' ', - low: _(gd, 'low:') + ' ', - close: _(gd, 'close:') + ' ' - } - }; - } - - return cd; -} - -/* - * find min x-coordinates difference of all traces - * attached to this x-axis and stash the result in _minDiff - * in all traces; when a trace uses this in its - * calc step it deletes _minDiff, so that next calc this is - * done again in case the data changed. - * also since we need it here, stash _xcalc on the trace - */ -function convertTickWidth(gd, xa, trace) { - var minDiff = trace._minDiff; - - if(!minDiff) { - var fullData = gd._fullData; - var ohlcTracesOnThisXaxis = []; - - minDiff = Infinity; - - var i; - - for(i = 0; i < fullData.length; i++) { - var tracei = fullData[i]; - - if(tracei.type === 'ohlc' && - tracei.visible === true && - tracei.xaxis === xa._id - ) { - ohlcTracesOnThisXaxis.push(tracei); - - var xcalc = xa.makeCalcdata(tracei, 'x'); - tracei._xcalc = xcalc; - - var _minDiff = Lib.distinctVals(xcalc).minDiff; - if(_minDiff && isFinite(_minDiff)) { - minDiff = Math.min(minDiff, _minDiff); - } - } - } - - // if minDiff is still Infinity here, set it to 1 - if(minDiff === Infinity) minDiff = 1; - - for(i = 0; i < ohlcTracesOnThisXaxis.length; i++) { - ohlcTracesOnThisXaxis[i]._minDiff = minDiff; - } - } - - return minDiff * trace.tickwidth; -} - -module.exports = { - calc: calc, - calcCommon: calcCommon -}; - -},{"../../constants/numerical":695,"../../lib":719,"../../plots/cartesian/axes":767}],1060:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); -var handleOHLC = _dereq_('./ohlc_defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleOHLC(traceIn, traceOut, coerce, layout); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('line.width'); - coerce('line.dash'); - - handleDirection(traceIn, traceOut, coerce, 'increasing'); - handleDirection(traceIn, traceOut, coerce, 'decreasing'); - - coerce('text'); - coerce('hovertext'); - coerce('tickwidth'); - - layout._requestRangeslider[traceOut.xaxis] = true; -}; - -function handleDirection(traceIn, traceOut, coerce, direction) { - coerce(direction + '.line.color'); - coerce(direction + '.line.width', traceOut.line.width); - coerce(direction + '.line.dash', traceOut.line.dash); -} - -},{"../../lib":719,"./attributes":1058,"./ohlc_defaults":1063}],1061:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var Lib = _dereq_('../../lib'); -var Fx = _dereq_('../../components/fx'); -var Color = _dereq_('../../components/color'); -var fillText = _dereq_('../../lib').fillText; -var delta = _dereq_('../../constants/delta.js'); - -var DIRSYMBOL = { - increasing: delta.INCREASING.SYMBOL, - decreasing: delta.DECREASING.SYMBOL -}; - -function hoverPoints(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var trace = cd[0].trace; - - if(trace.hoverlabel.split) { - return hoverSplit(pointData, xval, yval, hovermode); - } - - return hoverOnPoints(pointData, xval, yval, hovermode); -} - -function getClosestPoint(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var xa = pointData.xa; - var trace = cd[0].trace; - var t = cd[0].t; - - var type = trace.type; - var minAttr = type === 'ohlc' ? 'l' : 'min'; - var maxAttr = type === 'ohlc' ? 'h' : 'max'; - - var hoverPseudoDistance, spikePseudoDistance; - - // potentially shift xval for grouped candlesticks - var centerShift = t.bPos || 0; - var shiftPos = function(di) { return di.pos + centerShift - xval; }; - - // ohlc and candlestick call displayHalfWidth different things... - var displayHalfWidth = t.bdPos || t.tickLen; - var hoverHalfWidth = t.wHover; - - // if two figures are overlaying, let the narrowest one win - var pseudoDistance = Math.min(1, displayHalfWidth / Math.abs(xa.r2c(xa.range[1]) - xa.r2c(xa.range[0]))); - hoverPseudoDistance = pointData.maxHoverDistance - pseudoDistance; - spikePseudoDistance = pointData.maxSpikeDistance - pseudoDistance; - - function dx(di) { - var pos = shiftPos(di); - return Fx.inbox(pos - hoverHalfWidth, pos + hoverHalfWidth, hoverPseudoDistance); - } - - function dy(di) { - var min = di[minAttr]; - var max = di[maxAttr]; - return min === max || Fx.inbox(min - yval, max - yval, hoverPseudoDistance); - } - - function dxy(di) { return (dx(di) + dy(di)) / 2; } - - var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy); - Fx.getClosest(cd, distfn, pointData); - - if(pointData.index === false) return null; - - var di = cd[pointData.index]; - - if(di.empty) return null; - - var dir = di.dir; - var container = trace[dir]; - var lc = container.line.color; - - if(Color.opacity(lc) && container.line.width) pointData.color = lc; - else pointData.color = container.fillcolor; - - pointData.x0 = xa.c2p(di.pos + centerShift - displayHalfWidth, true); - pointData.x1 = xa.c2p(di.pos + centerShift + displayHalfWidth, true); - - pointData.xLabelVal = di.pos; - - pointData.spikeDistance = dxy(di) * spikePseudoDistance / hoverPseudoDistance; - pointData.xSpike = xa.c2p(di.pos, true); - - return pointData; -} - -function hoverSplit(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var ya = pointData.ya; - var trace = cd[0].trace; - var t = cd[0].t; - var closeBoxData = []; - - var closestPoint = getClosestPoint(pointData, xval, yval, hovermode); - // skip the rest (for this trace) if we didn't find a close point - if(!closestPoint) return []; - - var cdIndex = closestPoint.index; - var di = cd[cdIndex]; - var hoverinfo = di.hi || trace.hoverinfo; - var hoverParts = hoverinfo.split('+'); - var isAll = hoverinfo === 'all'; - var hasY = isAll || hoverParts.indexOf('y') !== -1; - - // similar to hoverOnPoints, we return nothing - // if all or y is not present. - if(!hasY) return []; - - var attrs = ['high', 'open', 'close', 'low']; - - // several attributes can have the same y-coordinate. We will - // bunch them together in a single text block. For this, we keep - // a dictionary mapping y-coord -> point data. - var usedVals = {}; - - for(var i = 0; i < attrs.length; i++) { - var attr = attrs[i]; - - var val = trace[attr][closestPoint.index]; - var valPx = ya.c2p(val, true); - var pointData2; - if(val in usedVals) { - pointData2 = usedVals[val]; - pointData2.yLabel += '
' + t.labels[attr] + Axes.hoverLabelText(ya, val); - } else { - // copy out to a new object for each new y-value to label - pointData2 = Lib.extendFlat({}, closestPoint); - - pointData2.y0 = pointData2.y1 = valPx; - pointData2.yLabelVal = val; - pointData2.yLabel = t.labels[attr] + Axes.hoverLabelText(ya, val); - - pointData2.name = ''; - - closeBoxData.push(pointData2); - usedVals[val] = pointData2; - } - } - - return closeBoxData; -} - -function hoverOnPoints(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var ya = pointData.ya; - var trace = cd[0].trace; - var t = cd[0].t; - - var closestPoint = getClosestPoint(pointData, xval, yval, hovermode); - // skip the rest (for this trace) if we didn't find a close point - if(!closestPoint) return []; - - // we don't make a calcdata point if we're missing any piece (x/o/h/l/c) - // so we need to fix the index here to point to the data arrays - var cdIndex = closestPoint.index; - var di = cd[cdIndex]; - var i = closestPoint.index = di.i; - var dir = di.dir; - - function getLabelLine(attr) { - return t.labels[attr] + Axes.hoverLabelText(ya, trace[attr][i]); - } - - var hoverinfo = di.hi || trace.hoverinfo; - var hoverParts = hoverinfo.split('+'); - var isAll = hoverinfo === 'all'; - var hasY = isAll || hoverParts.indexOf('y') !== -1; - var hasText = isAll || hoverParts.indexOf('text') !== -1; - - var textParts = hasY ? [ - getLabelLine('open'), - getLabelLine('high'), - getLabelLine('low'), - getLabelLine('close') + ' ' + DIRSYMBOL[dir] - ] : []; - if(hasText) fillText(di, trace, textParts); - - // don't make .yLabelVal or .text, since we're managing hoverinfo - // put it all in .extraText - closestPoint.extraText = textParts.join('
'); - - // this puts the label *and the spike* at the midpoint of the box, ie - // halfway between open and close, not between high and low. - closestPoint.y0 = closestPoint.y1 = ya.c2p(di.yc, true); - - return [closestPoint]; -} - -module.exports = { - hoverPoints: hoverPoints, - hoverSplit: hoverSplit, - hoverOnPoints: hoverOnPoints -}; - -},{"../../components/color":593,"../../components/fx":632,"../../constants/delta.js":689,"../../lib":719,"../../plots/cartesian/axes":767}],1062:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'ohlc', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', 'showLegend'], - meta: { - - }, - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('./calc').calc, - plot: _dereq_('./plot'), - style: _dereq_('./style'), - hoverPoints: _dereq_('./hover').hoverPoints, - selectPoints: _dereq_('./select') -}; - -},{"../../plots/cartesian":778,"./attributes":1058,"./calc":1059,"./defaults":1060,"./hover":1061,"./plot":1064,"./select":1065,"./style":1066}],1063:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); - -module.exports = function handleOHLC(traceIn, traceOut, coerce, layout) { - var x = coerce('x'); - var open = coerce('open'); - var high = coerce('high'); - var low = coerce('low'); - var close = coerce('close'); - - coerce('hoverlabel.split'); - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, ['x'], layout); - - if(!(open && high && low && close)) return; - - var len = Math.min(open.length, high.length, low.length, close.length); - if(x) len = Math.min(len, Lib.minRowLength(x)); - traceOut._length = len; - - return len; -}; - -},{"../../lib":719,"../../registry":847}],1064:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Lib = _dereq_('../../lib'); - -module.exports = function plot(gd, plotinfo, cdOHLC, ohlcLayer) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - Lib.makeTraceGroups(ohlcLayer, cdOHLC, 'trace ohlc').each(function(cd) { - var plotGroup = d3.select(this); - var cd0 = cd[0]; - var t = cd0.t; - var trace = cd0.trace; - - if(trace.visible !== true || t.empty) { - plotGroup.remove(); - return; - } - - var tickLen = t.tickLen; - - var paths = plotGroup.selectAll('path').data(Lib.identity); - - paths.enter().append('path'); - - paths.exit().remove(); - - paths.attr('d', function(d) { - if(d.empty) return 'M0,0Z'; - - var x = xa.c2p(d.pos, true); - var xo = xa.c2p(d.pos - tickLen, true); - var xc = xa.c2p(d.pos + tickLen, true); - - var yo = ya.c2p(d.o, true); - var yh = ya.c2p(d.h, true); - var yl = ya.c2p(d.l, true); - var yc = ya.c2p(d.c, true); - - return 'M' + xo + ',' + yo + 'H' + x + - 'M' + x + ',' + yh + 'V' + yl + - 'M' + xc + ',' + yc + 'H' + x; - }); - }); -}; - -},{"../../lib":719,"d3":163}],1065:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function selectPoints(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var xa = searchInfo.xaxis; - var ya = searchInfo.yaxis; - var selection = []; - var i; - // for (potentially grouped) candlesticks - var posOffset = cd[0].t.bPos || 0; - - if(selectionTester === false) { - // clear selection - for(i = 0; i < cd.length; i++) { - cd[i].selected = 0; - } - } else { - for(i = 0; i < cd.length; i++) { - var di = cd[i]; - - if(selectionTester.contains([xa.c2p(di.pos + posOffset), ya.c2p(di.yc)], null, di.i, searchInfo)) { - selection.push({ - pointNumber: di.i, - x: xa.c2d(di.pos), - y: ya.c2d(di.yc) - }); - di.selected = 1; - } else { - di.selected = 0; - } - } - } - - return selection; -}; - -},{}],1066:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Drawing = _dereq_('../../components/drawing'); -var Color = _dereq_('../../components/color'); - -module.exports = function style(gd, cd, sel) { - var s = sel ? sel : d3.select(gd).selectAll('g.ohlclayer').selectAll('g.trace'); - - s.style('opacity', function(d) { - return d[0].trace.opacity; - }); - - s.each(function(d) { - var trace = d[0].trace; - - d3.select(this).selectAll('path').each(function(di) { - if(di.empty) return; - - var dirLine = trace[di.dir].line; - d3.select(this) - .style('fill', 'none') - .call(Color.stroke, dirLine.color) - .call(Drawing.dashLine, dirLine.dash, dirLine.width) - // TODO: custom selection style for OHLC - .style('opacity', trace.selectedpoints && !di.selected ? 0.3 : 1); - }); - }); -}; - -},{"../../components/color":593,"../../components/drawing":614,"d3":163}],1067:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var plotAttrs = _dereq_('../../plots/attributes'); -var fontAttrs = _dereq_('../../plots/font_attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var domainAttrs = _dereq_('../../plots/domain').attributes; - -var line = extendFlat( - {editType: 'calc'}, - colorScaleAttrs('line', {editTypeOverride: 'calc'}), - { - shape: { - valType: 'enumerated', - values: ['linear', 'hspline'], - dflt: 'linear', - - editType: 'plot', - - }, - - hovertemplate: hovertemplateAttrs({ - editType: 'plot', - arrayOk: false - }, { - keys: ['count', 'probability'], - - }) - } -); - -module.exports = { - domain: domainAttrs({name: 'parcats', trace: true, editType: 'calc'}), - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['count', 'probability'], - editType: 'plot', - arrayOk: false - }), - hoveron: { - valType: 'enumerated', - values: ['category', 'color', 'dimension'], - dflt: 'category', - - editType: 'plot', - - }, - hovertemplate: hovertemplateAttrs({ - editType: 'plot', - arrayOk: false - }, { - keys: [ - 'count', 'probability', 'category', - 'categorycount', 'colorcount', 'bandcolorcount' - ], - - }), - - arrangement: { - valType: 'enumerated', - values: ['perpendicular', 'freeform', 'fixed'], - dflt: 'perpendicular', - - editType: 'plot', - - }, - bundlecolors: { - valType: 'boolean', - dflt: true, - - editType: 'plot', - - }, - sortpaths: { - valType: 'enumerated', - values: ['forward', 'backward'], - dflt: 'forward', - - editType: 'plot', - - }, - labelfont: fontAttrs({ - editType: 'calc', - - }), - - tickfont: fontAttrs({ - editType: 'calc', - - }), - - dimensions: { - _isLinkedToArray: 'dimension', - label: { - valType: 'string', - - editType: 'calc', - - }, - categoryorder: { - valType: 'enumerated', - values: [ - 'trace', 'category ascending', 'category descending', 'array' - ], - dflt: 'trace', - - editType: 'calc', - - }, - categoryarray: { - valType: 'data_array', - - editType: 'calc', - - }, - ticktext: { - valType: 'data_array', - - editType: 'calc', - - }, - values: { - valType: 'data_array', - - dflt: [], - editType: 'calc', - - }, - displayindex: { - valType: 'integer', - - editType: 'calc', - - }, - editType: 'calc', - - visible: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - } - }, - - line: line, - counts: { - valType: 'number', - min: 0, - dflt: 1, - arrayOk: true, - - editType: 'calc', - - }, - - // Hide unsupported top-level properties from plot-schema - customdata: undefined, - hoverlabel: undefined, - ids: undefined, - legendgroup: undefined, - opacity: undefined, - selectedpoints: undefined, - showlegend: undefined -}; - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../../plots/domain":792,"../../plots/font_attributes":793}],1068:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; -var parcatsPlot = _dereq_('./plot'); - -var PARCATS = 'parcats'; -exports.name = PARCATS; - -exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { - var cdModuleAndOthers = getModuleCalcData(gd.calcdata, PARCATS); - - if(cdModuleAndOthers.length) { - var calcData = cdModuleAndOthers[0]; - parcatsPlot(gd, calcData, transitionOpts, makeOnCompleteCallback); - } -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var hadTable = (oldFullLayout._has && oldFullLayout._has('parcats')); - var hasTable = (newFullLayout._has && newFullLayout._has('parcats')); - - if(hadTable && !hasTable) { - oldFullLayout._paperdiv.selectAll('.parcats').remove(); - } -}; - -},{"../../plots/get_data":802,"./plot":1073}],1069:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -// Requirements -// ============ -var wrap = _dereq_('../../lib/gup').wrap; -var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale; -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); -var filterUnique = _dereq_('../../lib/filter_unique.js'); -var Drawing = _dereq_('../../components/drawing'); -var Lib = _dereq_('../../lib'); - -/** - * Create a wrapped ParcatsModel object from trace - * - * Note: trace defaults have already been applied - * @param {Object} gd - * @param {Object} trace - * @return {Array.} - */ -module.exports = function calc(gd, trace) { - var visibleDims = Lib.filterVisible(trace.dimensions); - - if(visibleDims.length === 0) return []; - - var uniqueInfoDims = visibleDims.map(function(dim) { - var categoryValues; - if(dim.categoryorder === 'trace') { - // Use order of first occurrence in trace - categoryValues = null; - } else if(dim.categoryorder === 'array') { - // Use categories specified in `categoryarray` first, - // then add extra to the end in trace order - categoryValues = dim.categoryarray; - } else { - // Get all categories up front so we can order them - // Should we check for numbers as sort numerically? - categoryValues = filterUnique(dim.values).sort(); - if(dim.categoryorder === 'category descending') { - categoryValues = categoryValues.reverse(); - } - } - return getUniqueInfo(dim.values, categoryValues); - }); - - var counts, - count, - totalCount; - if(Lib.isArrayOrTypedArray(trace.counts)) { - counts = trace.counts; - } else { - counts = [trace.counts]; - } - - validateDimensionDisplayInds(visibleDims); - - visibleDims.forEach(function(dim, dimInd) { - validateCategoryProperties(dim, uniqueInfoDims[dimInd]); - }); - - // Handle path colors - // ------------------ - var line = trace.line; - var markerColorscale; - - // Process colorscale - if(line) { - if(hasColorscale(trace, 'line')) { - colorscaleCalc(gd, trace, { - vals: trace.line.color, - containerStr: 'line', - cLetter: 'c' - }); - } - markerColorscale = Drawing.tryColorscale(line); - } else { - markerColorscale = Lib.identity; - } - - // Build color generation function - function getMarkerColorInfo(index) { - var value; - if(Lib.isArrayOrTypedArray(line.color)) { - value = line.color[index % line.color.length]; - } else { - value = line.color; - } - - return {color: markerColorscale(value), rawColor: value}; - } - - // Number of values and counts - // --------------------------- - var numValues = visibleDims[0].values.length; - - // Build path info - // --------------- - // Mapping from category inds to PathModel objects - var pathModels = {}; - - // Category inds array for each dimension - var categoryIndsDims = uniqueInfoDims.map(function(di) {return di.inds;}); - - // Initialize total count - totalCount = 0; - var valueInd; - var d; - - for(valueInd = 0; valueInd < numValues; valueInd++) { - // Category inds for this input value across dimensions - var categoryIndsPath = []; - for(d = 0; d < categoryIndsDims.length; d++) { - categoryIndsPath.push(categoryIndsDims[d][valueInd]); - } - - // Count - count = counts[valueInd % counts.length]; - - // Update total count - totalCount += count; - - // Path color - var pathColorInfo = getMarkerColorInfo(valueInd); - - // path key - var pathKey = categoryIndsPath + '-' + pathColorInfo.rawColor; - - // Create / Update PathModel - if(pathModels[pathKey] === undefined) { - pathModels[pathKey] = createPathModel(categoryIndsPath, - pathColorInfo.color, - pathColorInfo.rawColor); - } - updatePathModel(pathModels[pathKey], valueInd, count); - } - - var dimensionModels = visibleDims.map(function(di, i) { - return createDimensionModel(i, di._index, di._displayindex, di.label, totalCount); - }); - - - for(valueInd = 0; valueInd < numValues; valueInd++) { - count = counts[valueInd % counts.length]; - - for(d = 0; d < dimensionModels.length; d++) { - var containerInd = dimensionModels[d].containerInd; - var catInd = uniqueInfoDims[d].inds[valueInd]; - var cats = dimensionModels[d].categories; - - if(cats[catInd] === undefined) { - var catValue = trace.dimensions[containerInd]._categoryarray[catInd]; - var catLabel = trace.dimensions[containerInd]._ticktext[catInd]; - cats[catInd] = createCategoryModel(d, catInd, catValue, catLabel); - } - - updateCategoryModel(cats[catInd], valueInd, count); - } - } - - // Compute unique - return wrap(createParcatsModel(dimensionModels, pathModels, totalCount)); -}; - -// Models -// ====== - -// Parcats Model -// ------------- -/** - * @typedef {Object} ParcatsModel - * Object containing calculated information about a parcats trace - * - * @property {Array.} dimensions - * Array of dimension models - * @property {Object.} paths - * Dictionary from category inds string (e.g. "1,2,1,1") to path model - * @property {Number} maxCats - * The maximum number of categories of any dimension in the diagram - * @property {Number} count - * Total number of input values - * @property {Object} trace - */ - -/** - * Create and new ParcatsModel object - * @param {Array.} dimensions - * @param {Object.} paths - * @param {Number} count - * @return {ParcatsModel} - */ -function createParcatsModel(dimensions, paths, count) { - var maxCats = dimensions - .map(function(d) {return d.categories.length;}) - .reduce(function(v1, v2) {return Math.max(v1, v2);}); - return {dimensions: dimensions, paths: paths, trace: undefined, maxCats: maxCats, count: count}; -} - -// Dimension Model -// --------------- -/** - * @typedef {Object} DimensionModel - * Object containing calculated information about a single dimension - * - * @property {Number} dimensionInd - * The index of this dimension among the *visible* dimensions - * @property {Number} containerInd - * The index of this dimension in the original dimensions container, - * irrespective of dimension visibility - * @property {Number} displayInd - * The display index of this dimension (where 0 is the left most dimension) - * @property {String} dimensionLabel - * The label of this dimension - * @property {Number} count - * Total number of input values - * @property {Array.} categories - * @property {Number|null} dragX - * The x position of dimension that is currently being dragged. null if not being dragged - */ - -/** - * Create and new DimensionModel object with an empty categories array - * @param {Number} dimensionInd - * @param {Number} containerInd - * @param {Number} displayInd - * @param {String} dimensionLabel - * @param {Number} count - * Total number of input values - * @return {DimensionModel} - */ -function createDimensionModel(dimensionInd, containerInd, displayInd, dimensionLabel, count) { - return { - dimensionInd: dimensionInd, - containerInd: containerInd, - displayInd: displayInd, - dimensionLabel: dimensionLabel, - count: count, - categories: [], - dragX: null - }; -} - -// Category Model -// -------------- -/** - * @typedef {Object} CategoryModel - * Object containing calculated information about a single category. - * - * @property {Number} dimensionInd - * The index of this categories dimension - * @property {Number} categoryInd - * The index of this category - * @property {Number} displayInd - * The display index of this category (where 0 is the topmost category) - * @property {String} categoryLabel - * The name of this category - * @property categoryValue: Raw value of the category - * @property {Array} valueInds - * Array of indices (into the original value array) of all samples in this category - * @property {Number} count - * The number of elements from the original array in this path - * @property {Number|null} dragY - * The y position of category that is currently being dragged. null if not being dragged - */ - -/** - * Create and return a new CategoryModel object - * @param {Number} dimensionInd - * @param {Number} categoryInd - * The display index of this category (where 0 is the topmost category) - * @param {String} categoryValue - * @param {String} categoryLabel - * @return {CategoryModel} - */ -function createCategoryModel(dimensionInd, categoryInd, categoryValue, categoryLabel) { - return { - dimensionInd: dimensionInd, - categoryInd: categoryInd, - categoryValue: categoryValue, - displayInd: categoryInd, - categoryLabel: categoryLabel, - valueInds: [], - count: 0, - dragY: null - }; -} - -/** - * Update a CategoryModel object with a new value index - * Note: The calling parameter is modified in place. - * - * @param {CategoryModel} categoryModel - * @param {Number} valueInd - * @param {Number} count - */ -function updateCategoryModel(categoryModel, valueInd, count) { - categoryModel.valueInds.push(valueInd); - categoryModel.count += count; -} - - -// Path Model -// ---------- -/** - * @typedef {Object} PathModel - * Object containing calculated information about the samples in a path. - * - * @property {Array} categoryInds - * Array of category indices for each dimension (length `numDimensions`) - * @param {String} pathColor - * Color of this path. (Note: Any colorscaling has already taken place) - * @property {Array} valueInds - * Array of indices (into the original value array) of all samples in this path - * @property {Number} count - * The number of elements from the original array in this path - * @property {String} color - * The path's color (ass CSS color string) - * @property rawColor - * The raw color value specified by the user. May be a CSS color string or a Number - */ - -/** - * Create and return a new PathModel object - * @param {Array} categoryInds - * @param color - * @param rawColor - * @return {PathModel} - */ -function createPathModel(categoryInds, color, rawColor) { - return { - categoryInds: categoryInds, - color: color, - rawColor: rawColor, - valueInds: [], - count: 0 - }; -} - -/** - * Update a PathModel object with a new value index - * Note: The calling parameter is modified in place. - * - * @param {PathModel} pathModel - * @param {Number} valueInd - * @param {Number} count - */ -function updatePathModel(pathModel, valueInd, count) { - pathModel.valueInds.push(valueInd); - pathModel.count += count; -} - -// Unique calculations -// =================== -/** - * @typedef {Object} UniqueInfo - * Object containing information about the unique values of an input array - * - * @property {Array} uniqueValues - * The unique values in the input array - * @property {Array} uniqueCounts - * The number of times each entry in uniqueValues occurs in input array. - * This has the same length as `uniqueValues` - * @property {Array} inds - * Indices into uniqueValues that would reproduce original input array - */ - -/** - * Compute unique value information for an array - * - * IMPORTANT: Note that values are considered unique - * if their string representations are unique. - * - * @param {Array} values - * @param {Array|undefined} uniqueValues - * Array of expected unique values. The uniqueValues property of the resulting UniqueInfo object will begin with - * these entries. Entries are included even if there are zero occurrences in the values array. Entries found in - * the values array that are not present in uniqueValues will be included at the end of the array in the - * UniqueInfo object. - * @return {UniqueInfo} - */ -function getUniqueInfo(values, uniqueValues) { - // Initialize uniqueValues if not specified - if(uniqueValues === undefined || uniqueValues === null) { - uniqueValues = []; - } else { - // Shallow copy so append below doesn't alter input array - uniqueValues = uniqueValues.map(function(e) {return e;}); - } - - // Initialize Variables - var uniqueValueCounts = {}; - var uniqueValueInds = {}; - var inds = []; - - // Initialize uniqueValueCounts and - uniqueValues.forEach(function(uniqueVal, valInd) { - uniqueValueCounts[uniqueVal] = 0; - uniqueValueInds[uniqueVal] = valInd; - }); - - // Compute the necessary unique info in a single pass - for(var i = 0; i < values.length; i++) { - var item = values[i]; - var itemInd; - - if(uniqueValueCounts[item] === undefined) { - // This item has a previously unseen value - uniqueValueCounts[item] = 1; - itemInd = uniqueValues.push(item) - 1; - uniqueValueInds[item] = itemInd; - } else { - // Increment count for this item - uniqueValueCounts[item]++; - itemInd = uniqueValueInds[item]; - } - inds.push(itemInd); - } - - // Build UniqueInfo - var uniqueCounts = uniqueValues.map(function(v) { return uniqueValueCounts[v]; }); - - return { - uniqueValues: uniqueValues, - uniqueCounts: uniqueCounts, - inds: inds - }; -} - - -/** - * Validate the requested display order for the dimensions. - * If the display order is a permutation of 0 through dimensions.length - 1, link to _displayindex - * Otherwise, replace the display order with the dimension order - * @param {Object} trace - */ -function validateDimensionDisplayInds(visibleDims) { - var displayInds = visibleDims.map(function(d) { return d.displayindex; }); - var i; - - if(isRangePermutation(displayInds)) { - for(i = 0; i < visibleDims.length; i++) { - visibleDims[i]._displayindex = visibleDims[i].displayindex; - } - } else { - for(i = 0; i < visibleDims.length; i++) { - visibleDims[i]._displayindex = i; - } - } -} - - -/** - * Update category properties based on the unique values found for this dimension - * @param {Object} dim - * @param {UniqueInfo} uniqueInfoDim - */ -function validateCategoryProperties(dim, uniqueInfoDim) { - // Update categoryarray - dim._categoryarray = uniqueInfoDim.uniqueValues; - - // Handle ticktext - if(dim.ticktext === null || dim.ticktext === undefined) { - dim._ticktext = []; - } else { - // Shallow copy to avoid modifying input array - dim._ticktext = dim.ticktext.slice(); - } - - // Extend ticktext with elements from uniqueInfoDim.uniqueValues - for(var i = dim._ticktext.length; i < uniqueInfoDim.uniqueValues.length; i++) { - dim._ticktext.push(uniqueInfoDim.uniqueValues[i]); - } -} - -/** - * Determine whether an array contains a permutation of the integers from 0 to the array's length - 1 - * @param {Array} inds - * @return {boolean} - */ -function isRangePermutation(inds) { - var indsSpecified = new Array(inds.length); - - for(var i = 0; i < inds.length; i++) { - // Check for out of bounds - if(inds[i] < 0 || inds[i] >= inds.length) { - return false; - } - - // Check for collisions with already specified index - if(indsSpecified[inds[i]] !== undefined) { - return false; - } - - indsSpecified[inds[i]] = true; - } - - // Nothing out of bounds and no collisions. We have a permutation - return true; -} - -},{"../../components/colorscale/calc":601,"../../components/colorscale/helpers":604,"../../components/drawing":614,"../../lib":719,"../../lib/filter_unique.js":711,"../../lib/gup":717}],1070:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale; -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var handleDomainDefaults = _dereq_('../../plots/domain').defaults; -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); - -var attributes = _dereq_('./attributes'); -var mergeLength = _dereq_('../parcoords/merge_length'); - -function handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce) { - coerce('line.shape'); - coerce('line.hovertemplate'); - - var lineColor = coerce('line.color', layout.colorway[0]); - if(hasColorscale(traceIn, 'line') && Lib.isArrayOrTypedArray(lineColor)) { - if(lineColor.length) { - coerce('line.colorscale'); - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c'}); - return lineColor.length; - } else { - traceOut.line.color = defaultColor; - } - } - return Infinity; -} - -function dimensionDefaults(dimensionIn, dimensionOut) { - function coerce(attr, dflt) { - return Lib.coerce(dimensionIn, dimensionOut, attributes.dimensions, attr, dflt); - } - - var values = coerce('values'); - var visible = coerce('visible'); - if(!(values && values.length)) { - visible = dimensionOut.visible = false; - } - - if(visible) { - // Dimension level - coerce('label'); - coerce('displayindex', dimensionOut._index); - - // Category level - var arrayIn = dimensionIn.categoryarray; - var isValidArray = (Array.isArray(arrayIn) && arrayIn.length > 0); - - var orderDefault; - if(isValidArray) orderDefault = 'array'; - var order = coerce('categoryorder', orderDefault); - - // coerce 'categoryarray' only in array order case - if(order === 'array') { - coerce('categoryarray'); - coerce('ticktext'); - } else { - delete dimensionIn.categoryarray; - delete dimensionIn.ticktext; - } - - // cannot set 'categoryorder' to 'array' with an invalid 'categoryarray' - if(!isValidArray && order === 'array') { - dimensionOut.categoryorder = 'trace'; - } - } -} - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var dimensions = handleArrayContainerDefaults(traceIn, traceOut, { - name: 'dimensions', - handleItemDefaults: dimensionDefaults - }); - - var len = handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - - handleDomainDefaults(traceOut, layout, coerce); - - if(!Array.isArray(dimensions) || !dimensions.length) { - traceOut.visible = false; - } - - mergeLength(traceOut, dimensions, 'values', len); - - coerce('hoveron'); - coerce('hovertemplate'); - coerce('arrangement'); - coerce('bundlecolors'); - coerce('sortpaths'); - coerce('counts'); - - var labelfontDflt = { - family: layout.font.family, - size: Math.round(layout.font.size), - color: layout.font.color - }; - - Lib.coerceFont(coerce, 'labelfont', labelfontDflt); - - var categoryfontDefault = { - family: layout.font.family, - size: Math.round(layout.font.size / 1.2), - color: layout.font.color - }; - - Lib.coerceFont(coerce, 'tickfont', categoryfontDefault); -}; - -},{"../../components/colorscale/defaults":603,"../../components/colorscale/helpers":604,"../../lib":719,"../../plots/array_container_defaults":763,"../../plots/domain":792,"../parcoords/merge_length":1083,"./attributes":1067}],1071:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - colorbar: { - container: 'line', - min: 'cmin', - max: 'cmax' - }, - - moduleType: 'trace', - name: 'parcats', - basePlotModule: _dereq_('./base_plot'), - categories: ['noOpacity'], - meta: { - - } -}; - -},{"./attributes":1067,"./base_plot":1068,"./calc":1069,"./defaults":1070,"./plot":1073}],1072:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Plotly = _dereq_('../../plot_api/plot_api'); -var Fx = _dereq_('../../components/fx'); -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../../components/drawing'); -var tinycolor = _dereq_('tinycolor2'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); - -function performPlot(parcatsModels, graphDiv, layout, svg) { - var viewModels = parcatsModels.map(createParcatsViewModel.bind(0, graphDiv, layout)); - - // Get (potentially empty) parcatslayer selection with bound data to single element array - var layerSelection = svg.selectAll('g.parcatslayer').data([null]); - - // Initialize single parcatslayer group if it doesn't exist - layerSelection.enter() - .append('g') - .attr('class', 'parcatslayer') - .style('pointer-events', 'all'); - - // Bind data to children of layerSelection and get reference to traceSelection - var traceSelection = layerSelection - .selectAll('g.trace.parcats') - .data(viewModels, key); - - // Initialize group for each trace/dimensions - var traceEnter = traceSelection.enter() - .append('g') - .attr('class', 'trace parcats'); - - // Update properties for each trace - traceSelection - .attr('transform', function(d) { - return 'translate(' + d.x + ', ' + d.y + ')'; - }); - - // Initialize paths group - traceEnter - .append('g') - .attr('class', 'paths'); - - // Update paths transform - var pathsSelection = traceSelection - .select('g.paths'); - - // Get paths selection - var pathSelection = pathsSelection - .selectAll('path.path') - .data(function(d) { - return d.paths; - }, key); - - // Update existing path colors - pathSelection - .attr('fill', function(d) { - return d.model.color; - }); - - // Create paths - var pathSelectionEnter = pathSelection - .enter() - .append('path') - .attr('class', 'path') - .attr('stroke-opacity', 0) - .attr('fill', function(d) { - return d.model.color; - }) - .attr('fill-opacity', 0); - - stylePathsNoHover(pathSelectionEnter); - - // Set path geometry - pathSelection - .attr('d', function(d) { - return d.svgD; - }); - - // sort paths - if(!pathSelectionEnter.empty()) { - // Only sort paths if there has been a change. - // Otherwise paths are already sorted or a hover operation may be in progress - pathSelection.sort(compareRawColor); - } - - // Remove any old paths - pathSelection.exit().remove(); - - // Path hover - pathSelection - .on('mouseover', mouseoverPath) - .on('mouseout', mouseoutPath) - .on('click', clickPath); - - // Initialize dimensions group - traceEnter.append('g').attr('class', 'dimensions'); - - // Update dimensions transform - var dimensionsSelection = traceSelection - .select('g.dimensions'); - - // Get dimension selection - var dimensionSelection = dimensionsSelection - .selectAll('g.dimension') - .data(function(d) { - return d.dimensions; - }, key); - - // Create dimension groups - dimensionSelection.enter() - .append('g') - .attr('class', 'dimension'); - - // Update dimension group transforms - dimensionSelection.attr('transform', function(d) { - return 'translate(' + d.x + ', 0)'; - }); - - // Remove any old dimensions - dimensionSelection.exit().remove(); - - // Get category selection - var categorySelection = dimensionSelection - .selectAll('g.category') - .data(function(d) { - return d.categories; - }, key); - - // Initialize category groups - var categoryGroupEnterSelection = categorySelection - .enter() - .append('g') - .attr('class', 'category'); - - // Update category transforms - categorySelection - .attr('transform', function(d) { - return 'translate(0, ' + d.y + ')'; - }); - - - // Initialize rectangle - categoryGroupEnterSelection - .append('rect') - .attr('class', 'catrect') - .attr('pointer-events', 'none'); - - - // Update rectangle - categorySelection.select('rect.catrect') - .attr('fill', 'none') - .attr('width', function(d) { - return d.width; - }) - .attr('height', function(d) { - return d.height; - }); - - styleCategoriesNoHover(categoryGroupEnterSelection); - - // Initialize color band rects - var bandSelection = categorySelection - .selectAll('rect.bandrect') - .data( - /** @param {CategoryViewModel} catViewModel*/ - function(catViewModel) { - return catViewModel.bands; - }, key); - - // Raise all update bands to the top so that fading enter/exit bands will be behind - bandSelection.each(function() {Lib.raiseToTop(this);}); - - // Update band color - bandSelection - .attr('fill', function(d) { - return d.color; - }); - - var bandsSelectionEnter = bandSelection.enter() - .append('rect') - .attr('class', 'bandrect') - .attr('stroke-opacity', 0) - .attr('fill', function(d) { - return d.color; - }) - .attr('fill-opacity', 0); - - bandSelection - .attr('fill', function(d) { - return d.color; - }) - .attr('width', function(d) { - return d.width; - }) - .attr('height', function(d) { - return d.height; - }) - .attr('y', function(d) { - return d.y; - }) - .attr('cursor', - /** @param {CategoryBandViewModel} bandModel*/ - function(bandModel) { - if(bandModel.parcatsViewModel.arrangement === 'fixed') { - return 'default'; - } else if(bandModel.parcatsViewModel.arrangement === 'perpendicular') { - return 'ns-resize'; - } else { - return 'move'; - } - }); - - styleBandsNoHover(bandsSelectionEnter); - - bandSelection.exit().remove(); - - // Initialize category label - categoryGroupEnterSelection - .append('text') - .attr('class', 'catlabel') - .attr('pointer-events', 'none'); - - var paperColor = graphDiv._fullLayout.paper_bgcolor; - - // Update category label - categorySelection.select('text.catlabel') - .attr('text-anchor', - function(d) { - if(catInRightDim(d)) { - // Place label to the right of category - return 'start'; - } else { - // Place label to the left of category - return 'end'; - } - }) - .attr('alignment-baseline', 'middle') - - .style('text-shadow', - paperColor + ' -1px 1px 2px, ' + - paperColor + ' 1px 1px 2px, ' + - paperColor + ' 1px -1px 2px, ' + - paperColor + ' -1px -1px 2px') - .style('fill', 'rgb(0, 0, 0)') - .attr('x', - function(d) { - if(catInRightDim(d)) { - // Place label to the right of category - return d.width + 5; - } else { - // Place label to the left of category - return -5; - } - }) - .attr('y', function(d) { - return d.height / 2; - }) - .text(function(d) { - return d.model.categoryLabel; - }) - .each( - /** @param {CategoryViewModel} catModel*/ - function(catModel) { - Drawing.font(d3.select(this), catModel.parcatsViewModel.categorylabelfont); - svgTextUtils.convertToTspans(d3.select(this), graphDiv); - }); - - // Initialize dimension label - categoryGroupEnterSelection - .append('text') - .attr('class', 'dimlabel'); - - // Update dimension label - categorySelection.select('text.dimlabel') - .attr('text-anchor', 'middle') - .attr('alignment-baseline', 'baseline') - .attr('cursor', - /** @param {CategoryViewModel} catModel*/ - function(catModel) { - if(catModel.parcatsViewModel.arrangement === 'fixed') { - return 'default'; - } else { - return 'ew-resize'; - } - }) - .attr('x', function(d) { - return d.width / 2; - }) - .attr('y', -5) - .text(function(d, i) { - if(i === 0) { - // Add dimension label above topmost category - return d.parcatsViewModel.model.dimensions[d.model.dimensionInd].dimensionLabel; - } else { - return null; - } - }) - .each( - /** @param {CategoryViewModel} catModel*/ - function(catModel) { - Drawing.font(d3.select(this), catModel.parcatsViewModel.labelfont); - }); - - // Category hover - // categorySelection.select('rect.catrect') - categorySelection.selectAll('rect.bandrect') - .on('mouseover', mouseoverCategoryBand) - .on('mouseout', mouseoutCategory); - - // Remove unused categories - categorySelection.exit().remove(); - - // Setup drag - dimensionSelection.call(d3.behavior.drag() - .origin(function(d) { - return {x: d.x, y: 0}; - }) - .on('dragstart', dragDimensionStart) - .on('drag', dragDimension) - .on('dragend', dragDimensionEnd)); - - - // Save off selections to view models - traceSelection.each(function(d) { - d.traceSelection = d3.select(this); - d.pathSelection = d3.select(this).selectAll('g.paths').selectAll('path.path'); - d.dimensionSelection = d3.select(this).selectAll('g.dimensions').selectAll('g.dimension'); - }); - - // Remove any orphan traces - traceSelection.exit().remove(); -} - -/** - * Create / update parcat traces - * - * @param {Object} graphDiv - * @param {Object} svg - * @param {Array.} parcatsModels - * @param {Layout} layout - */ -module.exports = function(graphDiv, svg, parcatsModels, layout) { - performPlot(parcatsModels, graphDiv, layout, svg); -}; - -/** - * Function the returns the key property of an object for use with as D3 join function - * @param d - */ -function key(d) { - return d.key; -} - - /** True if a category view model is in the right-most display dimension - * @param {CategoryViewModel} d */ -function catInRightDim(d) { - var numDims = d.parcatsViewModel.dimensions.length; - var leftDimInd = d.parcatsViewModel.dimensions[numDims - 1].model.dimensionInd; - return d.model.dimensionInd === leftDimInd; -} - -/** - * @param {PathViewModel} a - * @param {PathViewModel} b - */ -function compareRawColor(a, b) { - if(a.model.rawColor > b.model.rawColor) { - return 1; - } else if(a.model.rawColor < b.model.rawColor) { - return -1; - } else { - return 0; - } -} - -/** - * Handle path mouseover - * @param {PathViewModel} d - */ -function mouseoverPath(d) { - if(!d.parcatsViewModel.dragDimension) { - // We're not currently dragging - - if(d.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { - // hoverinfo is not skip, so we at least style the paths and emit interaction events - - // Raise path to top - Lib.raiseToTop(this); - - stylePathsHover(d3.select(this)); - - // Emit hover event - var points = buildPointsArrayForPath(d); - d.parcatsViewModel.graphDiv.emit('plotly_hover', {points: points, event: d3.event}); - - // Handle hover label - if(d.parcatsViewModel.hoverinfoItems.indexOf('none') === -1) { - // hoverinfo is a combination of 'count' and 'probability' - - // Mouse - var hoverX = d3.mouse(this)[0]; - - // Label - var gd = d.parcatsViewModel.graphDiv; - var trace = d.parcatsViewModel.trace; - var fullLayout = gd._fullLayout; - var rootBBox = fullLayout._paperdiv.node().getBoundingClientRect(); - var graphDivBBox = d.parcatsViewModel.graphDiv.getBoundingClientRect(); - - // Find path center in path coordinates - var pathCenterX, - pathCenterY, - dimInd; - - for(dimInd = 0; dimInd < (d.leftXs.length - 1); dimInd++) { - if(d.leftXs[dimInd] + d.dimWidths[dimInd] - 2 <= hoverX && hoverX <= d.leftXs[dimInd + 1] + 2) { - var leftDim = d.parcatsViewModel.dimensions[dimInd]; - var rightDim = d.parcatsViewModel.dimensions[dimInd + 1]; - pathCenterX = (leftDim.x + leftDim.width + rightDim.x) / 2; - pathCenterY = (d.topYs[dimInd] + d.topYs[dimInd + 1] + d.height) / 2; - break; - } - } - - // Find path center in root coordinates - var hoverCenterX = d.parcatsViewModel.x + pathCenterX; - var hoverCenterY = d.parcatsViewModel.y + pathCenterY; - - var textColor = tinycolor.mostReadable(d.model.color, ['black', 'white']); - - var count = d.model.count; - var prob = count / d.parcatsViewModel.model.count; - var labels = { - countLabel: count, - probabilityLabel: prob.toFixed(3) - }; - - // Build hover text - var hovertextParts = []; - if(d.parcatsViewModel.hoverinfoItems.indexOf('count') !== -1) { - hovertextParts.push(['Count:', labels.countLabel].join(' ')); - } - if(d.parcatsViewModel.hoverinfoItems.indexOf('probability') !== -1) { - hovertextParts.push(['P:', labels.probabilityLabel].join(' ')); - } - - var hovertext = hovertextParts.join('
'); - var mouseX = d3.mouse(gd)[0]; - - Fx.loneHover({ - trace: trace, - x: hoverCenterX - rootBBox.left + graphDivBBox.left, - y: hoverCenterY - rootBBox.top + graphDivBBox.top, - text: hovertext, - color: d.model.color, - borderColor: 'black', - fontFamily: 'Monaco, "Courier New", monospace', - fontSize: 10, - fontColor: textColor, - idealAlign: mouseX < hoverCenterX ? 'right' : 'left', - hovertemplate: (trace.line || {}).hovertemplate, - hovertemplateLabels: labels, - eventData: [{ - data: trace._input, - fullData: trace, - count: count, - probability: prob - }] - }, { - container: fullLayout._hoverlayer.node(), - outerContainer: fullLayout._paper.node(), - gd: gd - }); - } - } - } -} - -/** - * Handle path mouseout - * @param {PathViewModel} d - */ -function mouseoutPath(d) { - if(!d.parcatsViewModel.dragDimension) { - // We're not currently dragging - stylePathsNoHover(d3.select(this)); - - // Remove and hover label - Fx.loneUnhover(d.parcatsViewModel.graphDiv._fullLayout._hoverlayer.node()); - - // Restore path order - d.parcatsViewModel.pathSelection.sort(compareRawColor); - - // Emit unhover event - if(d.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { - var points = buildPointsArrayForPath(d); - d.parcatsViewModel.graphDiv.emit('plotly_unhover', {points: points, event: d3.event}); - } - } -} - -/** - * Build array of point objects for a path - * - * For use in click/hover events - * @param {PathViewModel} d - */ -function buildPointsArrayForPath(d) { - var points = []; - var curveNumber = getTraceIndex(d.parcatsViewModel); - - for(var i = 0; i < d.model.valueInds.length; i++) { - var pointNumber = d.model.valueInds[i]; - points.push({ - curveNumber: curveNumber, - pointNumber: pointNumber - }); - } - return points; -} - -/** - * Handle path click - * @param {PathViewModel} d - */ -function clickPath(d) { - if(d.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { - // hoverinfo it's skip, so interaction events aren't disabled - var points = buildPointsArrayForPath(d); - d.parcatsViewModel.graphDiv.emit('plotly_click', {points: points, event: d3.event}); - } -} - -function stylePathsNoHover(pathSelection) { - pathSelection - .attr('fill', function(d) { - return d.model.color; - }) - .attr('fill-opacity', 0.6) - .attr('stroke', 'lightgray') - .attr('stroke-width', 0.2) - .attr('stroke-opacity', 1.0); -} - -function stylePathsHover(pathSelection) { - pathSelection - .attr('fill-opacity', 0.8) - .attr('stroke', function(d) { - return tinycolor.mostReadable(d.model.color, ['black', 'white']); - }) - .attr('stroke-width', 0.3); -} - -function styleCategoryHover(categorySelection) { - categorySelection - .select('rect.catrect') - .attr('stroke', 'black') - .attr('stroke-width', 2.5); -} - -function styleCategoriesNoHover(categorySelection) { - categorySelection - .select('rect.catrect') - .attr('stroke', 'black') - .attr('stroke-width', 1) - .attr('stroke-opacity', 1); -} - -function styleBandsHover(bandsSelection) { - bandsSelection - .attr('stroke', 'black') - .attr('stroke-width', 1.5); -} - -function styleBandsNoHover(bandsSelection) { - bandsSelection - .attr('stroke', 'black') - .attr('stroke-width', 0.2) - .attr('stroke-opacity', 1.0) - .attr('fill-opacity', 1.0); -} - -/** - * Return selection of all paths that pass through the specified category - * @param {CategoryBandViewModel} catBandViewModel - */ -function selectPathsThroughCategoryBandColor(catBandViewModel) { - var allPaths = catBandViewModel.parcatsViewModel.pathSelection; - var dimInd = catBandViewModel.categoryViewModel.model.dimensionInd; - var catInd = catBandViewModel.categoryViewModel.model.categoryInd; - - return allPaths - .filter( - /** @param {PathViewModel} pathViewModel */ - function(pathViewModel) { - return pathViewModel.model.categoryInds[dimInd] === catInd && - pathViewModel.model.color === catBandViewModel.color; - }); -} - - -/** - * Perform hover styling for all paths that pass though the specified band element's category - * - * @param {HTMLElement} bandElement - * HTML element for band - * - */ -function styleForCategoryHovermode(bandElement) { - // Get all bands in the current category - var bandSel = d3.select(bandElement.parentNode).selectAll('rect.bandrect'); - - // Raise and style paths - bandSel.each(function(bvm) { - var paths = selectPathsThroughCategoryBandColor(bvm); - stylePathsHover(paths); - paths.each(function() { - // Raise path to top - Lib.raiseToTop(this); - }); - }); - - // Style category - styleCategoryHover(d3.select(bandElement.parentNode)); -} - -/** - * Perform hover styling for all paths that pass though the category of the specified band element and share the - * same color - * - * @param {HTMLElement} bandElement - * HTML element for band - * - */ -function styleForColorHovermode(bandElement) { - var bandViewModel = d3.select(bandElement).datum(); - var catPaths = selectPathsThroughCategoryBandColor(bandViewModel); - stylePathsHover(catPaths); - catPaths.each(function() { - // Raise path to top - Lib.raiseToTop(this); - }); - - // Style category for drag - d3.select(bandElement.parentNode) - .selectAll('rect.bandrect') - .filter(function(b) {return b.color === bandViewModel.color;}) - .each(function() { - Lib.raiseToTop(this); - styleBandsHover(d3.select(this)); - }); -} - - -/** - * @param {HTMLElement} bandElement - * HTML element for band - * @param eventName - * Event name (plotly_hover or plotly_click) - * @param event - * Mouse Event - */ -function emitPointsEventCategoryHovermode(bandElement, eventName, event) { - // Get all bands in the current category - var bandViewModel = d3.select(bandElement).datum(); - var gd = bandViewModel.parcatsViewModel.graphDiv; - var bandSel = d3.select(bandElement.parentNode).selectAll('rect.bandrect'); - - var points = []; - bandSel.each(function(bvm) { - var paths = selectPathsThroughCategoryBandColor(bvm); - paths.each(function(pathViewModel) { - // Extend points array - Array.prototype.push.apply(points, buildPointsArrayForPath(pathViewModel)); - }); - }); - - gd.emit(eventName, {points: points, event: event}); -} - -/** - * @param {HTMLElement} bandElement - * HTML element for band - * @param eventName - * Event name (plotly_hover or plotly_click) - * @param event - * Mouse Event - */ -function emitPointsEventColorHovermode(bandElement, eventName, event) { - var bandViewModel = d3.select(bandElement).datum(); - var gd = bandViewModel.parcatsViewModel.graphDiv; - var paths = selectPathsThroughCategoryBandColor(bandViewModel); - - var points = []; - paths.each(function(pathViewModel) { - // Extend points array - Array.prototype.push.apply(points, buildPointsArrayForPath(pathViewModel)); - }); - - gd.emit(eventName, {points: points, event: event}); -} - -/** - * Create hover label for a band element's category (for use when hoveron === 'category') - * - * @param {ClientRect} rootBBox - * Client bounding box for root of figure - * @param {HTMLElement} bandElement - * HTML element for band - * - */ -function createHoverLabelForCategoryHovermode(rootBBox, bandElement) { - // Selections - var rectSelection = d3.select(bandElement.parentNode).select('rect.catrect'); - var rectBoundingBox = rectSelection.node().getBoundingClientRect(); - - // Models - /** @type {CategoryViewModel} */ - var catViewModel = rectSelection.datum(); - var parcatsViewModel = catViewModel.parcatsViewModel; - var dimensionModel = parcatsViewModel.model.dimensions[catViewModel.model.dimensionInd]; - var trace = parcatsViewModel.trace; - - // Positions - var hoverCenterY = rectBoundingBox.top + rectBoundingBox.height / 2; - var hoverCenterX, - hoverLabelIdealAlign; - - if(parcatsViewModel.dimensions.length > 1 && - dimensionModel.displayInd === parcatsViewModel.dimensions.length - 1) { - // right most dimension - hoverCenterX = rectBoundingBox.left; - hoverLabelIdealAlign = 'left'; - } else { - hoverCenterX = rectBoundingBox.left + rectBoundingBox.width; - hoverLabelIdealAlign = 'right'; - } - - var count = catViewModel.model.count; - var catLabel = catViewModel.model.categoryLabel; - var prob = count / catViewModel.parcatsViewModel.model.count; - var labels = { - countLabel: count, - categoryLabel: catLabel, - probabilityLabel: prob.toFixed(3) - }; - - // Hover label text - var hoverinfoParts = []; - if(catViewModel.parcatsViewModel.hoverinfoItems.indexOf('count') !== -1) { - hoverinfoParts.push(['Count:', labels.countLabel].join(' ')); - } - if(catViewModel.parcatsViewModel.hoverinfoItems.indexOf('probability') !== -1) { - hoverinfoParts.push(['P(' + labels.categoryLabel + '):', labels.probabilityLabel].join(' ')); - } - - var hovertext = hoverinfoParts.join('
'); - return { - trace: trace, - x: hoverCenterX - rootBBox.left, - y: hoverCenterY - rootBBox.top, - text: hovertext, - color: 'lightgray', - borderColor: 'black', - fontFamily: 'Monaco, "Courier New", monospace', - fontSize: 12, - fontColor: 'black', - idealAlign: hoverLabelIdealAlign, - hovertemplate: trace.hovertemplate, - hovertemplateLabels: labels, - eventData: [{ - data: trace._input, - fullData: trace, - count: count, - category: catLabel, - probability: prob - }] - }; -} - -/** - * Create hover label for a band element's category (for use when hoveron === 'category') - * - * @param {ClientRect} rootBBox - * Client bounding box for root of figure - * @param {HTMLElement} bandElement - * HTML element for band - * - */ -function createHoverLabelForDimensionHovermode(rootBBox, bandElement) { - var allHoverlabels = []; - - d3.select(bandElement.parentNode.parentNode) - .selectAll('g.category') - .select('rect.catrect') - .each(function() { - var bandNode = this; - allHoverlabels.push(createHoverLabelForCategoryHovermode(rootBBox, bandNode)); - }); - - return allHoverlabels; -} - -/** - * Create hover labels for a band element's category (for use when hoveron === 'dimension') - * - * @param {ClientRect} rootBBox - * Client bounding box for root of figure - * @param {HTMLElement} bandElement - * HTML element for band - * - */ -function createHoverLabelForColorHovermode(rootBBox, bandElement) { - var bandBoundingBox = bandElement.getBoundingClientRect(); - - // Models - /** @type {CategoryBandViewModel} */ - var bandViewModel = d3.select(bandElement).datum(); - var catViewModel = bandViewModel.categoryViewModel; - var parcatsViewModel = catViewModel.parcatsViewModel; - var dimensionModel = parcatsViewModel.model.dimensions[catViewModel.model.dimensionInd]; - var trace = parcatsViewModel.trace; - - // positions - var hoverCenterY = bandBoundingBox.y + bandBoundingBox.height / 2; - - var hoverCenterX, - hoverLabelIdealAlign; - if(parcatsViewModel.dimensions.length > 1 && - dimensionModel.displayInd === parcatsViewModel.dimensions.length - 1) { - // right most dimension - hoverCenterX = bandBoundingBox.left; - hoverLabelIdealAlign = 'left'; - } else { - hoverCenterX = bandBoundingBox.left + bandBoundingBox.width; - hoverLabelIdealAlign = 'right'; - } - - // Labels - var catLabel = catViewModel.model.categoryLabel; - - // Counts - var totalCount = bandViewModel.parcatsViewModel.model.count; - - var bandColorCount = 0; - bandViewModel.categoryViewModel.bands.forEach(function(b) { - if(b.color === bandViewModel.color) { - bandColorCount += b.count; - } - }); - - var catCount = catViewModel.model.count; - - var colorCount = 0; - parcatsViewModel.pathSelection.each( - /** @param {PathViewModel} pathViewModel */ - function(pathViewModel) { - if(pathViewModel.model.color === bandViewModel.color) { - colorCount += pathViewModel.model.count; - } - }); - - var pColorAndCat = bandColorCount / totalCount; - var pCatGivenColor = bandColorCount / colorCount; - var pColorGivenCat = bandColorCount / catCount; - - var labels = { - countLabel: totalCount, - categoryLabel: catLabel, - probabilityLabel: pColorAndCat.toFixed(3) - }; - - // Hover label text - var hoverinfoParts = []; - if(catViewModel.parcatsViewModel.hoverinfoItems.indexOf('count') !== -1) { - hoverinfoParts.push(['Count:', labels.countLabel].join(' ')); - } - if(catViewModel.parcatsViewModel.hoverinfoItems.indexOf('probability') !== -1) { - hoverinfoParts.push('P(color ∩ ' + catLabel + '): ' + labels.probabilityLabel); - hoverinfoParts.push('P(' + catLabel + ' | color): ' + pCatGivenColor.toFixed(3)); - hoverinfoParts.push('P(color | ' + catLabel + '): ' + pColorGivenCat.toFixed(3)); - } - - var hovertext = hoverinfoParts.join('
'); - - // Compute text color - var textColor = tinycolor.mostReadable(bandViewModel.color, ['black', 'white']); - - return { - trace: trace, - x: hoverCenterX - rootBBox.left, - y: hoverCenterY - rootBBox.top, - // name: 'NAME', - text: hovertext, - color: bandViewModel.color, - borderColor: 'black', - fontFamily: 'Monaco, "Courier New", monospace', - fontColor: textColor, - fontSize: 10, - idealAlign: hoverLabelIdealAlign, - hovertemplate: trace.hovertemplate, - hovertemplateLabels: labels, - eventData: [{ - data: trace._input, - fullData: trace, - category: catLabel, - count: totalCount, - probability: pColorAndCat, - categorycount: catCount, - colorcount: colorCount, - bandcolorcount: bandColorCount - }] - }; -} - -/** - * Handle dimension mouseover - * @param {CategoryBandViewModel} bandViewModel - */ -function mouseoverCategoryBand(bandViewModel) { - if(!bandViewModel.parcatsViewModel.dragDimension) { - // We're not currently dragging - - if(bandViewModel.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { - // hoverinfo is not skip, so we at least style the bands and emit interaction events - - // Mouse - var mouseY = d3.mouse(this)[1]; - if(mouseY < -1) { - // Hover is above above the category rectangle (probably the dimension title text) - return; - } - - var gd = bandViewModel.parcatsViewModel.graphDiv; - var fullLayout = gd._fullLayout; - var rootBBox = fullLayout._paperdiv.node().getBoundingClientRect(); - var hoveron = bandViewModel.parcatsViewModel.hoveron; - - /** @type {HTMLElement} */ - var bandElement = this; - - // Handle style and events - if(hoveron === 'color') { - styleForColorHovermode(bandElement); - emitPointsEventColorHovermode(bandElement, 'plotly_hover', d3.event); - } else { - styleForCategoryHovermode(bandElement); - emitPointsEventCategoryHovermode(bandElement, 'plotly_hover', d3.event); - } - - // Handle hover label - if(bandViewModel.parcatsViewModel.hoverinfoItems.indexOf('none') === -1) { - var hoverItems; - if(hoveron === 'category') { - hoverItems = createHoverLabelForCategoryHovermode(rootBBox, bandElement); - } else if(hoveron === 'color') { - hoverItems = createHoverLabelForColorHovermode(rootBBox, bandElement); - } else if(hoveron === 'dimension') { - hoverItems = createHoverLabelForDimensionHovermode(rootBBox, bandElement); - } - - if(hoverItems) { - Fx.loneHover(hoverItems, { - container: fullLayout._hoverlayer.node(), - outerContainer: fullLayout._paper.node(), - gd: gd - }); - } - } - } - } -} - - -/** - * Handle dimension mouseover - * @param {CategoryBandViewModel} bandViewModel - */ -function mouseoutCategory(bandViewModel) { - var parcatsViewModel = bandViewModel.parcatsViewModel; - - if(!parcatsViewModel.dragDimension) { - // We're not dragging anything - - // Reset unhovered styles - stylePathsNoHover(parcatsViewModel.pathSelection); - styleCategoriesNoHover(parcatsViewModel.dimensionSelection.selectAll('g.category')); - styleBandsNoHover(parcatsViewModel.dimensionSelection.selectAll('g.category').selectAll('rect.bandrect')); - - // Remove hover label - Fx.loneUnhover(parcatsViewModel.graphDiv._fullLayout._hoverlayer.node()); - - // Restore path order - parcatsViewModel.pathSelection.sort(compareRawColor); - - // Emit unhover event - if(parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { - var hoveron = bandViewModel.parcatsViewModel.hoveron; - var bandElement = this; - - // Handle style and events - if(hoveron === 'color') { - emitPointsEventColorHovermode(bandElement, 'plotly_unhover', d3.event); - } else { - emitPointsEventCategoryHovermode(bandElement, 'plotly_unhover', d3.event); - } - } - } -} - - -/** - * Handle dimension drag start - * @param {DimensionViewModel} d - */ -function dragDimensionStart(d) { - // Check if dragging is supported - if(d.parcatsViewModel.arrangement === 'fixed') { - return; - } - - // Save off initial drag indexes for dimension - d.dragDimensionDisplayInd = d.model.displayInd; - d.initialDragDimensionDisplayInds = d.parcatsViewModel.model.dimensions.map(function(d) {return d.displayInd;}); - d.dragHasMoved = false; - - // Check for category hit - d.dragCategoryDisplayInd = null; - d3.select(this) - .selectAll('g.category') - .select('rect.catrect') - .each( - /** @param {CategoryViewModel} catViewModel */ - function(catViewModel) { - var catMouseX = d3.mouse(this)[0]; - var catMouseY = d3.mouse(this)[1]; - - - if(-2 <= catMouseX && catMouseX <= catViewModel.width + 2 && - -2 <= catMouseY && catMouseY <= catViewModel.height + 2) { - // Save off initial drag indexes for categories - d.dragCategoryDisplayInd = catViewModel.model.displayInd; - d.initialDragCategoryDisplayInds = d.model.categories.map(function(c) { - return c.displayInd; - }); - - // Initialize categories dragY to be the current y position - catViewModel.model.dragY = catViewModel.y; - - // Raise category - Lib.raiseToTop(this.parentNode); - - // Get band element - d3.select(this.parentNode) - .selectAll('rect.bandrect') - /** @param {CategoryBandViewModel} bandViewModel */ - .each(function(bandViewModel) { - if(bandViewModel.y < catMouseY && catMouseY <= bandViewModel.y + bandViewModel.height) { - d.potentialClickBand = this; - } - }); - } - }); - - // Update toplevel drag dimension - d.parcatsViewModel.dragDimension = d; - - // Remove hover label if any - Fx.loneUnhover(d.parcatsViewModel.graphDiv._fullLayout._hoverlayer.node()); -} - -/** - * Handle dimension drag - * @param {DimensionViewModel} d - */ -function dragDimension(d) { - // Check if dragging is supported - if(d.parcatsViewModel.arrangement === 'fixed') { - return; - } - - d.dragHasMoved = true; - - if(d.dragDimensionDisplayInd === null) { - return; - } - - var dragDimInd = d.dragDimensionDisplayInd; - var prevDimInd = dragDimInd - 1; - var nextDimInd = dragDimInd + 1; - - var dragDimension = d.parcatsViewModel - .dimensions[dragDimInd]; - - // Update category - if(d.dragCategoryDisplayInd !== null) { - var dragCategory = dragDimension.categories[d.dragCategoryDisplayInd]; - - // Update dragY by dy - dragCategory.model.dragY += d3.event.dy; - var categoryY = dragCategory.model.dragY; - - // Check for category drag swaps - var catDisplayInd = dragCategory.model.displayInd; - var dimCategoryViews = dragDimension.categories; - - var catAbove = dimCategoryViews[catDisplayInd - 1]; - var catBelow = dimCategoryViews[catDisplayInd + 1]; - - // Check for overlap above - if(catAbove !== undefined) { - if(categoryY < (catAbove.y + catAbove.height / 2.0)) { - // Swap display inds - dragCategory.model.displayInd = catAbove.model.displayInd; - catAbove.model.displayInd = catDisplayInd; - } - } - - if(catBelow !== undefined) { - if((categoryY + dragCategory.height) > (catBelow.y + catBelow.height / 2.0)) { - // Swap display inds - dragCategory.model.displayInd = catBelow.model.displayInd; - catBelow.model.displayInd = catDisplayInd; - } - } - - // Update category drag display index - d.dragCategoryDisplayInd = dragCategory.model.displayInd; - } - - // Update dimension position - if(d.dragCategoryDisplayInd === null || d.parcatsViewModel.arrangement === 'freeform') { - dragDimension.model.dragX = d3.event.x; - - // Check for dimension swaps - var prevDimension = d.parcatsViewModel.dimensions[prevDimInd]; - var nextDimension = d.parcatsViewModel.dimensions[nextDimInd]; - - if(prevDimension !== undefined) { - if(dragDimension.model.dragX < (prevDimension.x + prevDimension.width)) { - // Swap display inds - dragDimension.model.displayInd = prevDimension.model.displayInd; - prevDimension.model.displayInd = dragDimInd; - } - } - - if(nextDimension !== undefined) { - if((dragDimension.model.dragX + dragDimension.width) > nextDimension.x) { - // Swap display inds - dragDimension.model.displayInd = nextDimension.model.displayInd; - nextDimension.model.displayInd = d.dragDimensionDisplayInd; - } - } - - // Update drag display index - d.dragDimensionDisplayInd = dragDimension.model.displayInd; - } - - // Update view models - updateDimensionViewModels(d.parcatsViewModel); - updatePathViewModels(d.parcatsViewModel); - - // Update svg geometry - updateSvgCategories(d.parcatsViewModel); - updateSvgPaths(d.parcatsViewModel); -} - - -/** - * Handle dimension drag end - * @param {DimensionViewModel} d - */ -function dragDimensionEnd(d) { - // Check if dragging is supported - if(d.parcatsViewModel.arrangement === 'fixed') { - return; - } - - if(d.dragDimensionDisplayInd === null) { - return; - } - - d3.select(this).selectAll('text').attr('font-weight', 'normal'); - - // Compute restyle command - // ----------------------- - var restyleData = {}; - var traceInd = getTraceIndex(d.parcatsViewModel); - - // ### Handle dimension reordering ### - var finalDragDimensionDisplayInds = d.parcatsViewModel.model.dimensions.map(function(d) {return d.displayInd;}); - var anyDimsReordered = d.initialDragDimensionDisplayInds.some(function(initDimDisplay, dimInd) { - return initDimDisplay !== finalDragDimensionDisplayInds[dimInd]; - }); - - if(anyDimsReordered) { - finalDragDimensionDisplayInds.forEach(function(finalDimDisplay, dimInd) { - var containerInd = d.parcatsViewModel.model.dimensions[dimInd].containerInd; - restyleData['dimensions[' + containerInd + '].displayindex'] = finalDimDisplay; - }); - } - - // ### Handle category reordering ### - var anyCatsReordered = false; - if(d.dragCategoryDisplayInd !== null) { - var finalDragCategoryDisplayInds = d.model.categories.map(function(c) { - return c.displayInd; - }); - - anyCatsReordered = d.initialDragCategoryDisplayInds.some(function(initCatDisplay, catInd) { - return initCatDisplay !== finalDragCategoryDisplayInds[catInd]; - }); - - if(anyCatsReordered) { - // Sort a shallow copy of the category models by display index - var sortedCategoryModels = d.model.categories.slice().sort( - function(a, b) { return a.displayInd - b.displayInd; }); - - // Get new categoryarray and ticktext values - var newCategoryArray = sortedCategoryModels.map(function(v) { return v.categoryValue; }); - var newCategoryLabels = sortedCategoryModels.map(function(v) { return v.categoryLabel; }); - - restyleData['dimensions[' + d.model.containerInd + '].categoryarray'] = [newCategoryArray]; - restyleData['dimensions[' + d.model.containerInd + '].ticktext'] = [newCategoryLabels]; - restyleData['dimensions[' + d.model.containerInd + '].categoryorder'] = 'array'; - } - } - - // Handle potential click event - // ---------------------------- - if(d.parcatsViewModel.hoverinfoItems.indexOf('skip') === -1) { - if(!d.dragHasMoved && d.potentialClickBand) { - if(d.parcatsViewModel.hoveron === 'color') { - emitPointsEventColorHovermode(d.potentialClickBand, 'plotly_click', d3.event.sourceEvent); - } else { - emitPointsEventCategoryHovermode(d.potentialClickBand, 'plotly_click', d3.event.sourceEvent); - } - } - } - - // Nullify drag states - // ------------------- - d.model.dragX = null; - if(d.dragCategoryDisplayInd !== null) { - var dragCategory = d.parcatsViewModel - .dimensions[d.dragDimensionDisplayInd] - .categories[d.dragCategoryDisplayInd]; - - dragCategory.model.dragY = null; - d.dragCategoryDisplayInd = null; - } - - d.dragDimensionDisplayInd = null; - d.parcatsViewModel.dragDimension = null; - d.dragHasMoved = null; - d.potentialClickBand = null; - - // Update view models - // ------------------ - updateDimensionViewModels(d.parcatsViewModel); - updatePathViewModels(d.parcatsViewModel); - - // Perform transition - // ------------------ - var transition = d3.transition() - .duration(300) - .ease('cubic-in-out'); - - transition - .each(function() { - updateSvgCategories(d.parcatsViewModel, true); - updateSvgPaths(d.parcatsViewModel, true); - }) - .each('end', function() { - if(anyDimsReordered || anyCatsReordered) { - // Perform restyle if the order of categories or dimensions changed - Plotly.restyle(d.parcatsViewModel.graphDiv, restyleData, [traceInd]); - } - }); -} - -/** - * - * @param {ParcatsViewModel} parcatsViewModel - */ -function getTraceIndex(parcatsViewModel) { - var traceInd; - var allTraces = parcatsViewModel.graphDiv._fullData; - for(var i = 0; i < allTraces.length; i++) { - if(parcatsViewModel.key === allTraces[i].uid) { - traceInd = i; - break; - } - } - return traceInd; -} - -/** Update the svg paths for view model - * @param {ParcatsViewModel} parcatsViewModel - * @param {boolean} hasTransition Whether to update element with transition - */ -function updateSvgPaths(parcatsViewModel, hasTransition) { - if(hasTransition === undefined) { - hasTransition = false; - } - - function transition(selection) { - return hasTransition ? selection.transition() : selection; - } - - // Update binding - parcatsViewModel.pathSelection.data(function(d) { - return d.paths; - }, key); - - // Update paths - transition(parcatsViewModel.pathSelection).attr('d', function(d) { - return d.svgD; - }); -} - -/** Update the svg paths for view model - * @param {ParcatsViewModel} parcatsViewModel - * @param {boolean} hasTransition Whether to update element with transition - */ -function updateSvgCategories(parcatsViewModel, hasTransition) { - if(hasTransition === undefined) { - hasTransition = false; - } - - function transition(selection) { - return hasTransition ? selection.transition() : selection; - } - - // Update binding - parcatsViewModel.dimensionSelection - .data(function(d) { - return d.dimensions; - }, key); - - var categorySelection = parcatsViewModel.dimensionSelection - .selectAll('g.category') - .data(function(d) {return d.categories;}, key); - - // Update dimension position - transition(parcatsViewModel.dimensionSelection) - .attr('transform', function(d) { - return 'translate(' + d.x + ', 0)'; - }); - - // Update category position - transition(categorySelection) - .attr('transform', function(d) { - return 'translate(0, ' + d.y + ')'; - }); - - var dimLabelSelection = categorySelection.select('.dimlabel'); - - // ### Update dimension label - // Only the top-most display category should have the dimension label - dimLabelSelection - .text(function(d, i) { - if(i === 0) { - // Add dimension label above topmost category - return d.parcatsViewModel.model.dimensions[d.model.dimensionInd].dimensionLabel; - } else { - return null; - } - }); - - // Update category label - // Categories in the right-most display dimension have their labels on - // the right, all others on the left - var catLabelSelection = categorySelection.select('.catlabel'); - catLabelSelection - .attr('text-anchor', - function(d) { - if(catInRightDim(d)) { - // Place label to the right of category - return 'start'; - } else { - // Place label to the left of category - return 'end'; - } - }) - .attr('x', - function(d) { - if(catInRightDim(d)) { - // Place label to the right of category - return d.width + 5; - } else { - // Place label to the left of category - return -5; - } - }) - .each(function(d) { - // Update attriubutes of elements - var newX; - var newAnchor; - if(catInRightDim(d)) { - // Place label to the right of category - newX = d.width + 5; - newAnchor = 'start'; - } else { - // Place label to the left of category - newX = -5; - newAnchor = 'end'; - } - d3.select(this) - .selectAll('tspan') - .attr('x', newX) - .attr('text-anchor', newAnchor); - }); - - // Update bands - // Initialize color band rects - var bandSelection = categorySelection - .selectAll('rect.bandrect') - .data( - /** @param {CategoryViewModel} catViewModel*/ - function(catViewModel) { - return catViewModel.bands; - }, key); - - var bandsSelectionEnter = bandSelection.enter() - .append('rect') - .attr('class', 'bandrect') - .attr('cursor', 'move') - .attr('stroke-opacity', 0) - .attr('fill', function(d) { - return d.color; - }) - .attr('fill-opacity', 0); - - bandSelection - .attr('fill', function(d) { - return d.color; - }) - .attr('width', function(d) { - return d.width; - }) - .attr('height', function(d) { - return d.height; - }) - .attr('y', function(d) { - return d.y; - }); - - styleBandsNoHover(bandsSelectionEnter); - - // Raise bands to the top - bandSelection.each(function() {Lib.raiseToTop(this);}); - - // Remove unused bands - bandSelection.exit().remove(); -} - -/** - * Create a ParcatsViewModel traces - * @param {Object} graphDiv - * Top-level graph div element - * @param {Layout} layout - * SVG layout object - * @param {Array.} wrappedParcatsModel - * Wrapped ParcatsModel for this trace - * @return {ParcatsViewModel} - */ -function createParcatsViewModel(graphDiv, layout, wrappedParcatsModel) { - // Unwrap model - var parcatsModel = wrappedParcatsModel[0]; - - // Compute margin - var margin = layout.margin || {l: 80, r: 80, t: 100, b: 80}; - - // Compute pixel position/extents - var trace = parcatsModel.trace; - var domain = trace.domain; - var figureWidth = layout.width; - var figureHeight = layout.height; - var traceWidth = Math.floor(figureWidth * (domain.x[1] - domain.x[0])); - var traceHeight = Math.floor(figureHeight * (domain.y[1] - domain.y[0])); - var traceX = domain.x[0] * figureWidth + margin.l; - var traceY = layout.height - domain.y[1] * layout.height + margin.t; - - // Handle path shape - // ----------------- - var pathShape = trace.line.shape; - - // Handle hover info - // ----------------- - var hoverinfoItems; - if(trace.hoverinfo === 'all') { - hoverinfoItems = ['count', 'probability']; - } else { - hoverinfoItems = (trace.hoverinfo || '').split('+'); - } - - // Construct parcatsViewModel - // -------------------------- - var parcatsViewModel = { - trace: trace, - key: trace.uid, - model: parcatsModel, - x: traceX, - y: traceY, - width: traceWidth, - height: traceHeight, - hoveron: trace.hoveron, - hoverinfoItems: hoverinfoItems, - arrangement: trace.arrangement, - bundlecolors: trace.bundlecolors, - sortpaths: trace.sortpaths, - labelfont: trace.labelfont, - categorylabelfont: trace.tickfont, - pathShape: pathShape, - dragDimension: null, - margin: margin, - paths: [], - dimensions: [], - graphDiv: graphDiv, - traceSelection: null, - pathSelection: null, - dimensionSelection: null - }; - - // Update dimension view models if we have at least 1 dimension - if(parcatsModel.dimensions) { - updateDimensionViewModels(parcatsViewModel); - - // Update path view models if we have at least 2 dimensions - updatePathViewModels(parcatsViewModel); - } - // Inside a categories view model - return parcatsViewModel; -} - -/** - * Build the SVG string to represents a parallel categories path - * @param {Array.} leftXPositions - * Array of the x positions of the left edge of each dimension (in display order) - * @param {Array.} pathYs - * Array of the y positions of the top of the path at each dimension (in display order) - * @param {Array.} dimWidths - * Array of the widths of each dimension in display order - * @param {Number} pathHeight - * The height of the path in pixels - * @param {Number} curvature - * The curvature factor for the path. 0 results in a straight line and values greater than zero result in curved paths - * @return {string} - */ -function buildSvgPath(leftXPositions, pathYs, dimWidths, pathHeight, curvature) { - // Compute the x midpoint of each path segment - var xRefPoints1 = []; - var xRefPoints2 = []; - var refInterpolator; - var d; - - for(d = 0; d < dimWidths.length - 1; d++) { - refInterpolator = d3.interpolateNumber(dimWidths[d] + leftXPositions[d], leftXPositions[d + 1]); - xRefPoints1.push(refInterpolator(curvature)); - xRefPoints2.push(refInterpolator(1 - curvature)); - } - - // Move to top of path on left edge of left-most category - var svgD = 'M ' + leftXPositions[0] + ',' + pathYs[0]; - - // Horizontal line to right edge - svgD += 'l' + dimWidths[0] + ',0 '; - - // Horizontal line to right edge - for(d = 1; d < dimWidths.length; d++) { - // Curve to left edge of category - svgD += 'C' + xRefPoints1[d - 1] + ',' + pathYs[d - 1] + - ' ' + xRefPoints2[d - 1] + ',' + pathYs[d] + - ' ' + leftXPositions[d] + ',' + pathYs[d]; - - // svgD += 'L' + leftXPositions[d] + ',' + pathYs[d]; - - // Horizontal line to right edge - svgD += 'l' + dimWidths[d] + ',0 '; - } - - // Line down - svgD += 'l' + '0,' + pathHeight + ' '; - - // Line to left edge of right-most category - svgD += 'l -' + dimWidths[dimWidths.length - 1] + ',0 '; - - for(d = dimWidths.length - 2; d >= 0; d--) { - // Curve to right edge of category - svgD += 'C' + xRefPoints2[d] + ',' + (pathYs[d + 1] + pathHeight) + - ' ' + xRefPoints1[d] + ',' + (pathYs[d] + pathHeight) + - ' ' + (leftXPositions[d] + dimWidths[d]) + ',' + (pathYs[d] + pathHeight); - - // svgD += 'L' + (leftXPositions[d] + dimWidths[d]) + ',' + (pathYs[d] + pathHeight); - - // Horizontal line to right edge - svgD += 'l-' + dimWidths[d] + ',0 '; - } - - // Close path - svgD += 'Z'; - return svgD; -} - -/** - * Update the path view models based on the dimension view models in a ParcatsViewModel - * - * @param {ParcatsViewModel} parcatsViewModel - * View model for trace - */ -function updatePathViewModels(parcatsViewModel) { - // Initialize an array of the y position of the top of the next path to be added to each category. - // - // nextYPositions[d][c] is the y position of the next path through category with index c of dimension with index d - var dimensionViewModels = parcatsViewModel.dimensions; - var parcatsModel = parcatsViewModel.model; - var nextYPositions = dimensionViewModels.map( - function(d) { - return d.categories.map( - function(c) { - return c.y; - }); - }); - - // Array from category index to category display index for each true dimension index - var catToDisplayIndPerDim = parcatsViewModel.model.dimensions.map( - function(d) { - return d.categories.map(function(c) {return c.displayInd;}); - }); - - // Array from true dimension index to dimension display index - var dimToDisplayInd = parcatsViewModel.model.dimensions.map(function(d) {return d.displayInd;}); - var displayToDimInd = parcatsViewModel.dimensions.map(function(d) {return d.model.dimensionInd;}); - - // Array of the x position of the left edge of the rectangles for each dimension - var leftXPositions = dimensionViewModels.map( - function(d) { - return d.x; - }); - - // Compute dimension widths - var dimWidths = dimensionViewModels.map(function(d) {return d.width;}); - - // Build sorted Array of PathModel objects - var pathModels = []; - for(var p in parcatsModel.paths) { - if(parcatsModel.paths.hasOwnProperty(p)) { - pathModels.push(parcatsModel.paths[p]); - } - } - - // Compute category display inds to use for sorting paths - function pathDisplayCategoryInds(pathModel) { - var dimensionInds = pathModel.categoryInds.map(function(catInd, dimInd) {return catToDisplayIndPerDim[dimInd][catInd];}); - var displayInds = displayToDimInd.map(function(dimInd) { - return dimensionInds[dimInd]; - }); - return displayInds; - } - - // Sort in ascending order by display index array - pathModels.sort(function(v1, v2) { - // Build display inds for each path - var sortArray1 = pathDisplayCategoryInds(v1); - var sortArray2 = pathDisplayCategoryInds(v2); - - // Handle path sort order - if(parcatsViewModel.sortpaths === 'backward') { - sortArray1.reverse(); - sortArray2.reverse(); - } - - // Append the first value index of the path to break ties - sortArray1.push(v1.valueInds[0]); - sortArray2.push(v2.valueInds[0]); - - // Handle color bundling - if(parcatsViewModel.bundlecolors) { - // Prepend sort array with the raw color value - sortArray1.unshift(v1.rawColor); - sortArray2.unshift(v2.rawColor); - } - - // colors equal, sort by display categories - if(sortArray1 < sortArray2) { - return -1; - } - if(sortArray1 > sortArray2) { - return 1; - } - - return 0; - }); - - // Create path models - var pathViewModels = new Array(pathModels.length); - var totalCount = dimensionViewModels[0].model.count; - var totalHeight = dimensionViewModels[0].categories - .map(function(c) { return c.height; }) - .reduce(function(v1, v2) { return v1 + v2; }); - - - for(var pathNumber = 0; pathNumber < pathModels.length; pathNumber++) { - var pathModel = pathModels[pathNumber]; - - var pathHeight; - if(totalCount > 0) { - pathHeight = totalHeight * (pathModel.count / totalCount); - } else { - pathHeight = 0; - } - - // Build path y coords - var pathYs = new Array(nextYPositions.length); - for(var d = 0; d < pathModel.categoryInds.length; d++) { - var catInd = pathModel.categoryInds[d]; - var catDisplayInd = catToDisplayIndPerDim[d][catInd]; - var dimDisplayInd = dimToDisplayInd[d]; - - // Update next y position - pathYs[dimDisplayInd] = nextYPositions[dimDisplayInd][catDisplayInd]; - nextYPositions[dimDisplayInd][catDisplayInd] += pathHeight; - - // Update category color information - var catViewModle = parcatsViewModel.dimensions[dimDisplayInd].categories[catDisplayInd]; - var numBands = catViewModle.bands.length; - var lastCatBand = catViewModle.bands[numBands - 1]; - - if(lastCatBand === undefined || pathModel.rawColor !== lastCatBand.rawColor) { - // Create a new band - var bandY = lastCatBand === undefined ? 0 : lastCatBand.y + lastCatBand.height; - catViewModle.bands.push({ - key: bandY, - color: pathModel.color, - rawColor: pathModel.rawColor, - height: pathHeight, - width: catViewModle.width, - count: pathModel.count, - y: bandY, - categoryViewModel: catViewModle, - parcatsViewModel: parcatsViewModel - }); - } else { - // Extend current band - var currentBand = catViewModle.bands[numBands - 1]; - currentBand.height += pathHeight; - currentBand.count += pathModel.count; - } - } - - // build svg path - var svgD; - if(parcatsViewModel.pathShape === 'hspline') { - svgD = buildSvgPath(leftXPositions, pathYs, dimWidths, pathHeight, 0.5); - } else { - svgD = buildSvgPath(leftXPositions, pathYs, dimWidths, pathHeight, 0); - } - - pathViewModels[pathNumber] = { - key: pathModel.valueInds[0], - model: pathModel, - height: pathHeight, - leftXs: leftXPositions, - topYs: pathYs, - dimWidths: dimWidths, - svgD: svgD, - parcatsViewModel: parcatsViewModel - }; - } - - parcatsViewModel.paths = pathViewModels; - - // * @property key - // * Unique key for this model - // * @property {PathModel} model - // * Source path model - // * @property {Number} height - // * Height of this path (pixels) - // * @property {String} svgD - // * SVG path "d" attribute string -} - -/** - * Update the dimension view models based on the dimension models in a ParcatsViewModel - * - * @param {ParcatsViewModel} parcatsViewModel - * View model for trace - */ -function updateDimensionViewModels(parcatsViewModel) { - // Compute dimension ordering - var dimensionsIndInfo = parcatsViewModel.model.dimensions.map(function(d) { - return {displayInd: d.displayInd, dimensionInd: d.dimensionInd}; - }); - - dimensionsIndInfo.sort(function(a, b) { - return a.displayInd - b.displayInd; - }); - - var dimensions = []; - for(var displayInd in dimensionsIndInfo) { - var dimensionInd = dimensionsIndInfo[displayInd].dimensionInd; - var dimModel = parcatsViewModel.model.dimensions[dimensionInd]; - dimensions.push(createDimensionViewModel(parcatsViewModel, dimModel)); - } - - parcatsViewModel.dimensions = dimensions; -} - -/** - * Create a parcats DimensionViewModel - * - * @param {ParcatsViewModel} parcatsViewModel - * View model for trace - * @param {DimensionModel} dimensionModel - * @return {DimensionViewModel} - */ -function createDimensionViewModel(parcatsViewModel, dimensionModel) { - // Compute dimension x position - var categoryLabelPad = 40; - var dimWidth = 16; - var numDimensions = parcatsViewModel.model.dimensions.length; - var displayInd = dimensionModel.displayInd; - - // Compute x coordinate values - var dimDx; - var dimX0; - var dimX; - - if(numDimensions > 1) { - dimDx = (parcatsViewModel.width - 2 * categoryLabelPad - dimWidth) / (numDimensions - 1); - } else { - dimDx = 0; - } - dimX0 = categoryLabelPad; - dimX = dimX0 + dimDx * displayInd; - - // Compute categories - var categories = []; - var maxCats = parcatsViewModel.model.maxCats; - var numCats = dimensionModel.categories.length; - var catSpacing = 8; - var totalCount = dimensionModel.count; - var totalHeight = parcatsViewModel.height - catSpacing * (maxCats - 1); - var nextCatHeight; - var nextCatModel; - var nextCat; - var catInd; - var catDisplayInd; - - // Compute starting Y offset - var nextCatY = (maxCats - numCats) * catSpacing / 2.0; - - // Compute category ordering - var categoryIndInfo = dimensionModel.categories.map(function(c) { - return {displayInd: c.displayInd, categoryInd: c.categoryInd}; - }); - - categoryIndInfo.sort(function(a, b) { - return a.displayInd - b.displayInd; - }); - - for(catDisplayInd = 0; catDisplayInd < numCats; catDisplayInd++) { - catInd = categoryIndInfo[catDisplayInd].categoryInd; - nextCatModel = dimensionModel.categories[catInd]; - - if(totalCount > 0) { - nextCatHeight = (nextCatModel.count / totalCount) * totalHeight; - } else { - nextCatHeight = 0; - } - - nextCat = { - key: nextCatModel.valueInds[0], - model: nextCatModel, - width: dimWidth, - height: nextCatHeight, - y: nextCatModel.dragY !== null ? nextCatModel.dragY : nextCatY, - bands: [], - parcatsViewModel: parcatsViewModel - }; - - nextCatY = nextCatY + nextCatHeight + catSpacing; - categories.push(nextCat); - } - - return { - key: dimensionModel.dimensionInd, - x: dimensionModel.dragX !== null ? dimensionModel.dragX : dimX, - y: 0, - width: dimWidth, - model: dimensionModel, - categories: categories, - parcatsViewModel: parcatsViewModel, - dragCategoryDisplayInd: null, - dragDimensionDisplayInd: null, - initialDragDimensionDisplayInds: null, - initialDragCategoryDisplayInds: null, - dragHasMoved: null, - potentialClickBand: null - }; -} - -// JSDoc typedefs -// ============== -/** - * @typedef {Object} Layout - * Object containing svg layout information - * - * @property {Number} width (pixels) - * Usable width for Figure (after margins are removed) - * @property {Number} height (pixels) - * Usable height for Figure (after margins are removed) - * @property {Margin} margin - * Margin around the Figure (pixels) - */ - -/** - * @typedef {Object} Margin - * Object containing padding information in pixels - * - * @property {Number} t - * Top margin - * @property {Number} r - * Right margin - * @property {Number} b - * Bottom margin - * @property {Number} l - * Left margin - */ - -/** - * @typedef {Object} Font - * Object containing font information - * - * @property {Number} size: Font size - * @property {String} color: Font color - * @property {String} family: Font family - */ - -/** - * @typedef {Object} ParcatsViewModel - * Object containing calculated parcats view information - * - * These are quantities that require Layout information to calculate - * @property key - * Unique key for this model - * @property {ParcatsModel} model - * Source parcats model - * @property {Array.} dimensions - * Array of dimension view models - * @property {Number} width - * Width for this trace (pixels) - * @property {Number} height - * Height for this trace (pixels) - * @property {Number} x - * X position of this trace with respect to the Figure (pixels) - * @property {Number} y - * Y position of this trace with respect to the Figure (pixels) - * @property {String} hoveron - * Hover interaction mode. One of: 'category', 'color', or 'dimension' - * @property {Array.} hoverinfoItems - * Info to display on hover. Array with a combination of 'counts' and/or 'probabilities', or 'none', or 'skip' - * @property {String} arrangement - * Category arrangement. One of: 'perpendicular', 'freeform', or 'fixed' - * @property {Boolean} bundlecolors - * Whether paths should be sorted so that like colors are bundled together as they pass through categories - * @property {String} sortpaths - * If 'forward' then sort paths based on dimensions from left to right. If 'backward' sort based on dimensions - * from right to left - * @property {Font} labelfont - * Font for the dimension labels - * @property {Font} categorylabelfont - * Font for the category labels - * @property {String} pathShape - * The shape of the paths. Either 'linear' or 'hspline'. - * @property {DimensionViewModel|null} dragDimension - * Dimension currently being dragged. Null if no drag in progress - * @property {Margin} margin - * Margin around the Figure - * @property {Object} graphDiv - * Top-level graph div element - * @property {Object} traceSelection - * D3 selection of this view models trace group element - * @property {Object} pathSelection - * D3 selection of this view models path elements - * @property {Object} dimensionSelection - * D3 selection of this view models dimension group element - */ - -/** - * @typedef {Object} DimensionViewModel - * Object containing calculated parcats dimension view information - * - * These are quantities that require Layout information to calculate - * @property key - * Unique key for this model - * @property {DimensionModel} model - * Source dimension model - * @property {Number} x - * X position of the center of this dimension with respect to the Figure (pixels) - * @property {Number} y - * Y position of the top of this dimension with respect to the Figure (pixels) - * @property {Number} width - * Width of categories in this dimension (pixels) - * @property {ParcatsViewModel} parcatsViewModel - * The parent trace's view model - * @property {Array.} categories - * Dimensions category view models - * @property {Number|null} dragCategoryDisplayInd - * Display index of category currently being dragged. null if no category is being dragged - * @property {Number|null} dragDimensionDisplayInd - * Display index of the dimension being dragged. null if no dimension is being dragged - * @property {Array.|null} initialDragDimensionDisplayInds - * Dimensions display indexes at the beginning of the current drag. null if no dimension is being dragged - * @property {Array.|null} initialDragCategoryDisplayInds - * Category display indexes for the at the beginning of the current drag. null if no category is being dragged - * @property {HTMLElement} potentialClickBand - * Band under mouse when current drag began. If no drag movement takes place then a click will be emitted for this - * band. Null if not drag in progress. - * @property {Boolean} dragHasMoved - * True if there is an active drag and the drag has moved. If drag doesn't move before being ended then - * this may be interpreted as a click. Null if no drag in progress - */ - -/** - * @typedef {Object} CategoryViewModel - * Object containing calculated parcats category view information - * - * These are quantities that require Layout information to calculate - * @property key - * Unique key for this model - * @property {CategoryModel} model - * Source category model - * @property {Number} width - * Width for this category (pixels) - * @property {Number} height - * Height for this category (pixels) - * @property {Number} y - * Y position of this cateogry with respect to the Figure (pixels) - * @property {Array.} bands - * Array of color bands inside the category - * @property {ParcatsViewModel} parcatsViewModel - * The parent trace's view model - */ - -/** - * @typedef {Object} CategoryBandViewModel - * Object containing calculated category band information. A category band is a region inside a category covering - * paths of a single color - * - * @property key - * Unique key for this model - * @property color - * Band color - * @property rawColor - * Raw color value for band - * @property {Number} width - * Band width - * @property {Number} height - * Band height - * @property {Number} y - * Y position of top of the band with respect to the category - * @property {Number} count - * The number of samples represented by the band - * @property {CategoryViewModel} categoryViewModel - * The parent categorie's view model - * @property {ParcatsViewModel} parcatsViewModel - * The parent trace's view model - */ - -/** - * @typedef {Object} PathViewModel - * Object containing calculated parcats path view information - * - * These are quantities that require Layout information to calculate - * @property key - * Unique key for this model - * @property {PathModel} model - * Source path model - * @property {Number} height - * Height of this path (pixels) - * @property {Array.} leftXs - * The x position of the left edge of each display dimension - * @property {Array.} topYs - * The y position of the top of the path for each display dimension - * @property {Array.} dimWidths - * The width of each display dimension - * @property {String} svgD - * SVG path "d" attribute string - * @property {ParcatsViewModel} parcatsViewModel - * The parent trace's view model - */ - -},{"../../components/drawing":614,"../../components/fx":632,"../../lib":719,"../../lib/svg_text_utils":743,"../../plot_api/plot_api":754,"d3":163,"tinycolor2":537}],1073:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -var parcats = _dereq_('./parcats'); - -/** - * Create / update parcat traces - * - * @param {Object} graphDiv - * @param {Array.} parcatsModels - */ -module.exports = function plot(graphDiv, parcatsModels, transitionOpts, makeOnCompleteCallback) { - var fullLayout = graphDiv._fullLayout; - var svg = fullLayout._paper; - var size = fullLayout._size; - - parcats( - graphDiv, - svg, - parcatsModels, - { - width: size.w, - height: size.h, - margin: { - t: size.t, - r: size.r, - b: size.b, - l: size.l - } - }, - transitionOpts, - makeOnCompleteCallback - ); -}; - -},{"./parcats":1072}],1074:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var axesAttrs = _dereq_('../../plots/cartesian/layout_attributes'); -var fontAttrs = _dereq_('../../plots/font_attributes'); -var domainAttrs = _dereq_('../../plots/domain').attributes; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - -module.exports = { - domain: domainAttrs({name: 'parcoords', trace: true, editType: 'plot'}), - - labelangle: { - valType: 'angle', - dflt: 0, - - editType: 'plot', - - }, - - labelside: { - valType: 'enumerated', - - values: ['top', 'bottom'], - dflt: 'top', - editType: 'plot', - - }, - - labelfont: fontAttrs({ - editType: 'plot', - - }), - tickfont: fontAttrs({ - editType: 'plot', - - }), - rangefont: fontAttrs({ - editType: 'plot', - - }), - - dimensions: templatedArray('dimension', { - label: { - valType: 'string', - - editType: 'plot', - - }, - // TODO: better way to determine ordinal vs continuous axes, - // so users can use tickvals/ticktext with a continuous axis. - tickvals: extendFlat({}, axesAttrs.tickvals, { - editType: 'plot', - - }), - ticktext: extendFlat({}, axesAttrs.ticktext, { - editType: 'plot', - - }), - tickformat: extendFlat({}, axesAttrs.tickformat, { - editType: 'plot' - }), - visible: { - valType: 'boolean', - dflt: true, - - editType: 'plot', - - }, - range: { - valType: 'info_array', - - items: [ - {valType: 'number', editType: 'plot'}, - {valType: 'number', editType: 'plot'} - ], - editType: 'plot', - - }, - constraintrange: { - valType: 'info_array', - - freeLength: true, - dimensions: '1-2', - items: [ - {valType: 'number', editType: 'plot'}, - {valType: 'number', editType: 'plot'} - ], - editType: 'plot', - - }, - multiselect: { - valType: 'boolean', - dflt: true, - - editType: 'plot', - - }, - values: { - valType: 'data_array', - - editType: 'calc', - - }, - editType: 'calc', - - }), - - line: extendFlat({editType: 'calc'}, - colorScaleAttrs('line', { - // the default autocolorscale isn't quite usable for parcoords due to context ambiguity around 0 (grey, off-white) - // autocolorscale therefore defaults to false too, to avoid being overridden by the blue-white-red autocolor palette - colorscaleDflt: 'Viridis', - autoColorDflt: false, - editTypeOverride: 'calc' - }) - ) -}; - -},{"../../components/colorscale/attributes":600,"../../lib/extend":710,"../../plot_api/plot_template":757,"../../plots/cartesian/layout_attributes":779,"../../plots/domain":792,"../../plots/font_attributes":793}],1075:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var c = _dereq_('./constants'); -var d3 = _dereq_('d3'); -var keyFun = _dereq_('../../lib/gup').keyFun; -var repeat = _dereq_('../../lib/gup').repeat; -var sortAsc = _dereq_('../../lib').sorterAsc; - -var snapRatio = c.bar.snapRatio; -function snapOvershoot(v, vAdjacent) { return v * (1 - snapRatio) + vAdjacent * snapRatio; } - -var snapClose = c.bar.snapClose; -function closeToCovering(v, vAdjacent) { return v * (1 - snapClose) + vAdjacent * snapClose; } - -// snap for the low end of a range on an ordinal scale -// on an ordinal scale, always show some overshoot from the exact value, -// so it's clear we're covering it -// find the interval we're in, and snap to 1/4 the distance to the next -// these two could be unified at a slight loss of readability / perf -function ordinalScaleSnap(isHigh, a, v, existingRanges) { - if(overlappingExisting(v, existingRanges)) return v; - - var dir = isHigh ? -1 : 1; - - var first = 0; - var last = a.length - 1; - if(dir < 0) { - var tmp = first; - first = last; - last = tmp; - } - - var aHere = a[first]; - var aPrev = aHere; - for(var i = first; dir * i < dir * last; i += dir) { - var nextI = i + dir; - var aNext = a[nextI]; - - // very close to the previous - snap down to it - if(dir * v < dir * closeToCovering(aHere, aNext)) return snapOvershoot(aHere, aPrev); - if(dir * v < dir * aNext || nextI === last) return snapOvershoot(aNext, aHere); - - aPrev = aHere; - aHere = aNext; - } -} - -function overlappingExisting(v, existingRanges) { - for(var i = 0; i < existingRanges.length; i++) { - if(v >= existingRanges[i][0] && v <= existingRanges[i][1]) return true; - } - return false; -} - -function barHorizontalSetup(selection) { - selection - .attr('x', -c.bar.captureWidth / 2) - .attr('width', c.bar.captureWidth); -} - -function backgroundBarHorizontalSetup(selection) { - selection - .attr('visibility', 'visible') - .style('visibility', 'visible') - .attr('fill', 'yellow') - .attr('opacity', 0); -} - -function setHighlight(d) { - if(!d.brush.filterSpecified) { - return '0,' + d.height; - } - - var pixelRanges = unitToPx(d.brush.filter.getConsolidated(), d.height); - var dashArray = [0]; // we start with a 0 length selection as filter ranges are inclusive, not exclusive - var p, sectionHeight, iNext; - var currentGap = pixelRanges.length ? pixelRanges[0][0] : null; - for(var i = 0; i < pixelRanges.length; i++) { - p = pixelRanges[i]; - sectionHeight = p[1] - p[0]; - dashArray.push(currentGap); - dashArray.push(sectionHeight); - iNext = i + 1; - if(iNext < pixelRanges.length) { - currentGap = pixelRanges[iNext][0] - p[1]; - } - } - dashArray.push(d.height); - // d.height is added at the end to ensure that (1) we have an even number of dasharray points, MDN page says - // "If an odd number of values is provided, then the list of values is repeated to yield an even number of values." - // and (2) it's _at least_ as long as the full height (even if range is minuscule and at the bottom) though this - // may not be necessary, maybe duplicating the last point would do too. But no harm in a longer dasharray than line. - return dashArray; -} - -function unitToPx(unitRanges, height) { - return unitRanges.map(function(pr) { - return pr.map(function(v) { return Math.max(0, v * height); }).sort(sortAsc); - }); -} - -// is the cursor over the north, middle, or south of a bar? -// the end handles extend over the last 10% of the bar -function getRegion(fPix, y) { - var pad = c.bar.handleHeight; - if(y > fPix[1] + pad || y < fPix[0] - pad) return; - if(y >= 0.9 * fPix[1] + 0.1 * fPix[0]) return 'n'; - if(y <= 0.9 * fPix[0] + 0.1 * fPix[1]) return 's'; - return 'ns'; -} - -function clearCursor() { - d3.select(document.body) - .style('cursor', null); -} - -function styleHighlight(selection) { - // stroke-dasharray is used to minimize the number of created DOM nodes, because the requirement calls for up to - // 1000 individual selections on an axis, and there can be 60 axes per parcoords, and multiple parcoords per - // dashboard. The technique is similar to https://codepen.io/monfera/pen/rLYqWR and using a `polyline` with - // multiple sections, or a `path` element via its `d` attribute would also be DOM-sparing alternatives. - selection.attr('stroke-dasharray', setHighlight); -} - -function renderHighlight(root, tweenCallback) { - var bar = d3.select(root).selectAll('.highlight, .highlight-shadow'); - var barToStyle = tweenCallback ? bar.transition().duration(c.bar.snapDuration).each('end', tweenCallback) : bar; - styleHighlight(barToStyle); -} - -function getInterval(d, y) { - var b = d.brush; - var active = b.filterSpecified; - var closestInterval = NaN; - var out = {}; - var i; - - if(active) { - var height = d.height; - var intervals = b.filter.getConsolidated(); - var pixIntervals = unitToPx(intervals, height); - var hoveredInterval = NaN; - var previousInterval = NaN; - var nextInterval = NaN; - for(i = 0; i <= pixIntervals.length; i++) { - var p = pixIntervals[i]; - if(p && p[0] <= y && y <= p[1]) { - // over a bar - hoveredInterval = i; - break; - } else { - // between bars, or before/after the first/last bar - previousInterval = i ? i - 1 : NaN; - if(p && p[0] > y) { - nextInterval = i; - break; // no point continuing as intervals are non-overlapping and sorted; could use log search - } - } - } - - closestInterval = hoveredInterval; - if(isNaN(closestInterval)) { - if(isNaN(previousInterval) || isNaN(nextInterval)) { - closestInterval = isNaN(previousInterval) ? nextInterval : previousInterval; - } else { - closestInterval = (y - pixIntervals[previousInterval][1] < pixIntervals[nextInterval][0] - y) ? - previousInterval : nextInterval; - } - } - - if(!isNaN(closestInterval)) { - var fPix = pixIntervals[closestInterval]; - var region = getRegion(fPix, y); - - if(region) { - out.interval = intervals[closestInterval]; - out.intervalPix = fPix; - out.region = region; - } - } - } - - if(d.ordinal && !out.region) { - var a = d.unitTickvals; - var unitLocation = d.unitToPaddedPx.invert(y); - for(i = 0; i < a.length; i++) { - var rangei = [ - a[Math.max(i - 1, 0)] * 0.25 + a[i] * 0.75, - a[Math.min(i + 1, a.length - 1)] * 0.25 + a[i] * 0.75 - ]; - if(unitLocation >= rangei[0] && unitLocation <= rangei[1]) { - out.clickableOrdinalRange = rangei; - break; - } - } - } - - return out; -} - -function dragstart(lThis, d) { - d3.event.sourceEvent.stopPropagation(); - var y = d.height - d3.mouse(lThis)[1] - 2 * c.verticalPadding; - var unitLocation = d.unitToPaddedPx.invert(y); - var b = d.brush; - var interval = getInterval(d, y); - var unitRange = interval.interval; - var s = b.svgBrush; - s.wasDragged = false; // we start assuming there won't be a drag - useful for reset - s.grabbingBar = interval.region === 'ns'; - if(s.grabbingBar) { - var pixelRange = unitRange.map(d.unitToPaddedPx); - s.grabPoint = y - pixelRange[0] - c.verticalPadding; - s.barLength = pixelRange[1] - pixelRange[0]; - } - s.clickableOrdinalRange = interval.clickableOrdinalRange; - s.stayingIntervals = (d.multiselect && b.filterSpecified) ? b.filter.getConsolidated() : []; - if(unitRange) { - s.stayingIntervals = s.stayingIntervals.filter(function(int2) { - return int2[0] !== unitRange[0] && int2[1] !== unitRange[1]; - }); - } - s.startExtent = interval.region ? unitRange[interval.region === 's' ? 1 : 0] : unitLocation; - d.parent.inBrushDrag = true; - s.brushStartCallback(); -} - -function drag(lThis, d) { - d3.event.sourceEvent.stopPropagation(); - var y = d.height - d3.mouse(lThis)[1] - 2 * c.verticalPadding; - var s = d.brush.svgBrush; - s.wasDragged = true; - s._dragging = true; - - if(s.grabbingBar) { // moving the bar - s.newExtent = [y - s.grabPoint, y + s.barLength - s.grabPoint].map(d.unitToPaddedPx.invert); - } else { // south/north drag or new bar creation - s.newExtent = [s.startExtent, d.unitToPaddedPx.invert(y)].sort(sortAsc); - } - - d.brush.filterSpecified = true; - s.extent = s.stayingIntervals.concat([s.newExtent]); - s.brushCallback(d); - renderHighlight(lThis.parentNode); -} - -function dragend(lThis, d) { - var brush = d.brush; - var filter = brush.filter; - var s = brush.svgBrush; - - if(!s._dragging) { // i.e. click - // mock zero drag - mousemove(lThis, d); - drag(lThis, d); - // remember it is a click not a drag - d.brush.svgBrush.wasDragged = false; - } - s._dragging = false; - - var e = d3.event; - e.sourceEvent.stopPropagation(); - var grabbingBar = s.grabbingBar; - s.grabbingBar = false; - s.grabLocation = undefined; - d.parent.inBrushDrag = false; - clearCursor(); // instead of clearing, a nicer thing would be to set it according to current location - if(!s.wasDragged) { // a click+release on the same spot (ie. w/o dragging) means a bar or full reset - s.wasDragged = undefined; // logic-wise unneeded, just shows `wasDragged` has no longer a meaning - if(s.clickableOrdinalRange) { - if(brush.filterSpecified && d.multiselect) { - s.extent.push(s.clickableOrdinalRange); - } else { - s.extent = [s.clickableOrdinalRange]; - brush.filterSpecified = true; - } - } else if(grabbingBar) { - s.extent = s.stayingIntervals; - if(s.extent.length === 0) { - brushClear(brush); - } - } else { - brushClear(brush); - } - s.brushCallback(d); - renderHighlight(lThis.parentNode); - s.brushEndCallback(brush.filterSpecified ? filter.getConsolidated() : []); - return; // no need to fuse intervals or snap to ordinals, so we can bail early - } - - var mergeIntervals = function() { - // Key piece of logic: once the button is released, possibly overlapping intervals will be fused: - // Here it's done immediately on click release while on ordinal snap transition it's done at the end - filter.set(filter.getConsolidated()); - }; - - if(d.ordinal) { - var a = d.unitTickvals; - if(a[a.length - 1] < a[0]) a.reverse(); - s.newExtent = [ - ordinalScaleSnap(0, a, s.newExtent[0], s.stayingIntervals), - ordinalScaleSnap(1, a, s.newExtent[1], s.stayingIntervals) - ]; - var hasNewExtent = s.newExtent[1] > s.newExtent[0]; - s.extent = s.stayingIntervals.concat(hasNewExtent ? [s.newExtent] : []); - if(!s.extent.length) { - brushClear(brush); - } - s.brushCallback(d); - if(hasNewExtent) { - // merging intervals post the snap tween - renderHighlight(lThis.parentNode, mergeIntervals); - } else { - // if no new interval, don't animate, just redraw the highlight immediately - mergeIntervals(); - renderHighlight(lThis.parentNode); - } - } else { - mergeIntervals(); // merging intervals immediately - } - s.brushEndCallback(brush.filterSpecified ? filter.getConsolidated() : []); -} - -function mousemove(lThis, d) { - var y = d.height - d3.mouse(lThis)[1] - 2 * c.verticalPadding; - var interval = getInterval(d, y); - - var cursor = 'crosshair'; - if(interval.clickableOrdinalRange) cursor = 'pointer'; - else if(interval.region) cursor = interval.region + '-resize'; - d3.select(document.body) - .style('cursor', cursor); -} - -function attachDragBehavior(selection) { - // There's some fiddling with pointer cursor styling so that the cursor preserves its shape while dragging a brush - // even if the cursor strays from the interacting bar, which is bound to happen as bars are thin and the user - // will inevitably leave the hotspot strip. In this regard, it does something similar to what the D3 brush would do. - selection - .on('mousemove', function(d) { - d3.event.preventDefault(); - if(!d.parent.inBrushDrag) mousemove(this, d); - }) - .on('mouseleave', function(d) { - if(!d.parent.inBrushDrag) clearCursor(); - }) - .call(d3.behavior.drag() - .on('dragstart', function(d) { dragstart(this, d); }) - .on('drag', function(d) { drag(this, d); }) - .on('dragend', function(d) { dragend(this, d); }) - ); -} - -function startAsc(a, b) { return a[0] - b[0]; } - -function renderAxisBrush(axisBrush) { - var background = axisBrush.selectAll('.background').data(repeat); - - background.enter() - .append('rect') - .classed('background', true) - .call(barHorizontalSetup) - .call(backgroundBarHorizontalSetup) - .style('pointer-events', 'auto') // parent pointer events are disabled; we must have it to register events - .attr('transform', 'translate(0 ' + c.verticalPadding + ')'); - - background - .call(attachDragBehavior) - .attr('height', function(d) { - return d.height - c.verticalPadding; - }); - - var highlightShadow = axisBrush.selectAll('.highlight-shadow').data(repeat); // we have a set here, can't call it `extent` - - highlightShadow.enter() - .append('line') - .classed('highlight-shadow', true) - .attr('x', -c.bar.width / 2) - .attr('stroke-width', c.bar.width + c.bar.strokeWidth) - .attr('stroke', c.bar.strokeColor) - .attr('opacity', c.bar.strokeOpacity) - .attr('stroke-linecap', 'butt'); - - highlightShadow - .attr('y1', function(d) { return d.height; }) - .call(styleHighlight); - - var highlight = axisBrush.selectAll('.highlight').data(repeat); // we have a set here, can't call it `extent` - - highlight.enter() - .append('line') - .classed('highlight', true) - .attr('x', -c.bar.width / 2) - .attr('stroke-width', c.bar.width - c.bar.strokeWidth) - .attr('stroke', c.bar.fillColor) - .attr('opacity', c.bar.fillOpacity) - .attr('stroke-linecap', 'butt'); - - highlight - .attr('y1', function(d) { return d.height; }) - .call(styleHighlight); -} - -function ensureAxisBrush(axisOverlays) { - var axisBrush = axisOverlays.selectAll('.' + c.cn.axisBrush) - .data(repeat, keyFun); - - axisBrush.enter() - .append('g') - .classed(c.cn.axisBrush, true); - - renderAxisBrush(axisBrush); -} - -function getBrushExtent(brush) { - return brush.svgBrush.extent.map(function(e) {return e.slice();}); -} - -function brushClear(brush) { - brush.filterSpecified = false; - brush.svgBrush.extent = [[-Infinity, Infinity]]; -} - -function axisBrushMoved(callback) { - return function axisBrushMoved(dimension) { - var brush = dimension.brush; - var extent = getBrushExtent(brush); - var newExtent = extent.slice(); - brush.filter.set(newExtent); - callback(); - }; -} - -function dedupeRealRanges(intervals) { - // Fuses elements of intervals if they overlap, yielding discontiguous intervals, results.length <= intervals.length - // Currently uses closed intervals, ie. dedupeRealRanges([[400, 800], [300, 400]]) -> [300, 800] - var queue = intervals.slice(); - var result = []; - var currentInterval; - var current = queue.shift(); - while(current) { // [].shift === undefined, so we don't descend into an empty array - currentInterval = current.slice(); - while((current = queue.shift()) && current[0] <= /* right-open interval would need `<` */ currentInterval[1]) { - currentInterval[1] = Math.max(currentInterval[1], current[1]); - } - result.push(currentInterval); - } - return result; -} - -function makeFilter() { - var filter = []; - var consolidated; - var bounds; - return { - set: function(a) { - filter = a - .map(function(d) { return d.slice().sort(sortAsc); }) - .sort(startAsc); - - // handle unselected case - if(filter.length === 1 && - filter[0][0] === -Infinity && - filter[0][1] === Infinity) { - filter = [[0, -1]]; - } - - consolidated = dedupeRealRanges(filter); - bounds = filter.reduce(function(p, n) { - return [Math.min(p[0], n[0]), Math.max(p[1], n[1])]; - }, [Infinity, -Infinity]); - }, - get: function() { return filter.slice(); }, - getConsolidated: function() { return consolidated; }, - getBounds: function() { return bounds; } - }; -} - -function makeBrush(state, rangeSpecified, initialRange, brushStartCallback, brushCallback, brushEndCallback) { - var filter = makeFilter(); - filter.set(initialRange); - return { - filter: filter, - filterSpecified: rangeSpecified, // there's a difference between not filtering and filtering a non-proper subset - svgBrush: { - extent: [], // this is where the svgBrush writes contents into - brushStartCallback: brushStartCallback, - brushCallback: axisBrushMoved(brushCallback), - brushEndCallback: brushEndCallback - } - }; -} - -// for use by supplyDefaults, but it needed tons of pieces from here so -// seemed to make more sense just to put the whole routine here -function cleanRanges(ranges, dimension) { - if(Array.isArray(ranges[0])) { - ranges = ranges.map(function(ri) { return ri.sort(sortAsc); }); - - if(!dimension.multiselect) ranges = [ranges[0]]; - else ranges = dedupeRealRanges(ranges.sort(startAsc)); - } else ranges = [ranges.sort(sortAsc)]; - - // ordinal snapping - if(dimension.tickvals) { - var sortedTickVals = dimension.tickvals.slice().sort(sortAsc); - ranges = ranges.map(function(ri) { - var rSnapped = [ - ordinalScaleSnap(0, sortedTickVals, ri[0], []), - ordinalScaleSnap(1, sortedTickVals, ri[1], []) - ]; - if(rSnapped[1] > rSnapped[0]) return rSnapped; - }) - .filter(function(ri) { return ri; }); - - if(!ranges.length) return; - } - return ranges.length > 1 ? ranges : ranges[0]; -} - -module.exports = { - makeBrush: makeBrush, - ensureAxisBrush: ensureAxisBrush, - cleanRanges: cleanRanges -}; - -},{"../../lib":719,"../../lib/gup":717,"./constants":1078,"d3":163}],1076:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; -var parcoordsPlot = _dereq_('./plot'); -var xmlnsNamespaces = _dereq_('../../constants/xmlns_namespaces'); - -exports.name = 'parcoords'; - -exports.plot = function(gd) { - var calcData = getModuleCalcData(gd.calcdata, 'parcoords')[0]; - if(calcData.length) parcoordsPlot(gd, calcData); -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var hadParcoords = (oldFullLayout._has && oldFullLayout._has('parcoords')); - var hasParcoords = (newFullLayout._has && newFullLayout._has('parcoords')); - - if(hadParcoords && !hasParcoords) { - oldFullLayout._paperdiv.selectAll('.parcoords').remove(); - oldFullLayout._glimages.selectAll('*').remove(); - } -}; - -exports.toSVG = function(gd) { - var imageRoot = gd._fullLayout._glimages; - var root = d3.select(gd).selectAll('.svg-container'); - var canvases = root.filter(function(d, i) {return i === root.size() - 1;}) - .selectAll('.gl-canvas-context, .gl-canvas-focus'); - - function canvasToImage() { - var canvas = this; - var imageData = canvas.toDataURL('image/png'); - var image = imageRoot.append('svg:image'); - - image.attr({ - xmlns: xmlnsNamespaces.svg, - 'xlink:href': imageData, - preserveAspectRatio: 'none', - x: 0, - y: 0, - width: canvas.width, - height: canvas.height - }); - } - - canvases.each(canvasToImage); - - // Chrome / Safari bug workaround - browser apparently loses connection to the defined pattern - // Without the workaround, these browsers 'lose' the filter brush styling (color etc.) after a snapshot - // on a subsequent interaction. - // Firefox works fine without this workaround - window.setTimeout(function() { - d3.selectAll('#filterBarPattern') - .attr('id', 'filterBarPattern'); - }, 60); -}; - -},{"../../constants/xmlns_namespaces":696,"../../plots/get_data":802,"./plot":1085,"d3":163}],1077:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; -var Colorscale = _dereq_('../../components/colorscale'); -var wrap = _dereq_('../../lib/gup').wrap; - -module.exports = function calc(gd, trace) { - var lineColor; - var cscale; - - if(Colorscale.hasColorscale(trace, 'line') && isArrayOrTypedArray(trace.line.color)) { - lineColor = trace.line.color; - cscale = Colorscale.extractOpts(trace.line).colorscale; - - Colorscale.calc(gd, trace, { - vals: lineColor, - containerStr: 'line', - cLetter: 'c' - }); - } else { - lineColor = constHalf(trace._length); - cscale = [[0, trace.line.color], [1, trace.line.color]]; - } - - return wrap({lineColor: lineColor, cscale: cscale}); -}; - -function constHalf(len) { - var out = new Array(len); - for(var i = 0; i < len; i++) { - out[i] = 0.5; - } - return out; -} - -},{"../../components/colorscale":605,"../../lib":719,"../../lib/gup":717}],1078:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - - -module.exports = { - maxDimensionCount: 60, // this cannot be increased without WebGL code refactoring - overdrag: 45, - verticalPadding: 2, // otherwise, horizontal lines on top or bottom are of lower width - tickDistance: 50, - canvasPixelRatio: 1, - blockLineCount: 5000, - layers: ['contextLineLayer', 'focusLineLayer', 'pickLineLayer'], - axisTitleOffset: 28, - axisExtentOffset: 10, - deselectedLineColor: '#777', - bar: { - width: 4, // Visible width of the filter bar - captureWidth: 10, // Mouse-sensitive width for interaction (Fitts law) - fillColor: 'magenta', // Color of the filter bar fill - fillOpacity: 1, // Filter bar fill opacity - snapDuration: 150, // tween duration in ms for brush snap for ordinal axes - snapRatio: 0.25, // ratio of bar extension relative to the distance between two adjacent ordinal values - snapClose: 0.01, // fraction of inter-value distance to snap to the closer one, even if you're not over it - strokeColor: 'white', // Color of the filter bar side lines - strokeOpacity: 1, // Filter bar side stroke opacity - strokeWidth: 1, // Filter bar side stroke width in pixels - handleHeight: 8, // Height of the filter bar vertical resize areas on top and bottom - handleOpacity: 1, // Opacity of the filter bar vertical resize areas on top and bottom - handleOverlap: 0 // A larger than 0 value causes overlaps with the filter bar, represented as pixels - }, - cn: { - axisExtentText: 'axis-extent-text', - parcoordsLineLayers: 'parcoords-line-layers', - parcoordsLineLayer: 'parcoords-lines', - parcoords: 'parcoords', - parcoordsControlView: 'parcoords-control-view', - yAxis: 'y-axis', - axisOverlays: 'axis-overlays', - axis: 'axis', - axisHeading: 'axis-heading', - axisTitle: 'axis-title', - axisExtent: 'axis-extent', - axisExtentTop: 'axis-extent-top', - axisExtentTopText: 'axis-extent-top-text', - axisExtentBottom: 'axis-extent-bottom', - axisExtentBottomText: 'axis-extent-bottom-text', - axisBrush: 'axis-brush' - }, - id: { - filterBarPattern: 'filter-bar-pattern' - - } -}; - -},{}],1079:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale; -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var handleDomainDefaults = _dereq_('../../plots/domain').defaults; -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); -var Axes = _dereq_('../../plots/cartesian/axes'); - -var attributes = _dereq_('./attributes'); -var axisBrush = _dereq_('./axisbrush'); -var maxDimensionCount = _dereq_('./constants').maxDimensionCount; -var mergeLength = _dereq_('./merge_length'); - -function handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce) { - var lineColor = coerce('line.color', defaultColor); - - if(hasColorscale(traceIn, 'line') && Lib.isArrayOrTypedArray(lineColor)) { - if(lineColor.length) { - coerce('line.colorscale'); - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c'}); - // TODO: I think it would be better to keep showing lines beyond the last line color - // but I'm not sure what color to give these lines - probably black or white - // depending on the background color? - return lineColor.length; - } else { - traceOut.line.color = defaultColor; - } - } - return Infinity; -} - -function dimensionDefaults(dimensionIn, dimensionOut, parentOut, opts) { - function coerce(attr, dflt) { - return Lib.coerce(dimensionIn, dimensionOut, attributes.dimensions, attr, dflt); - } - - var values = coerce('values'); - var visible = coerce('visible'); - if(!(values && values.length)) { - visible = dimensionOut.visible = false; - } - - if(visible) { - coerce('label'); - coerce('tickvals'); - coerce('ticktext'); - coerce('tickformat'); - var range = coerce('range'); - - dimensionOut._ax = { - _id: 'y', - type: 'linear', - showexponent: 'all', - exponentformat: 'B', - range: range - }; - - Axes.setConvert(dimensionOut._ax, opts.layout); - - coerce('multiselect'); - var constraintRange = coerce('constraintrange'); - if(constraintRange) { - dimensionOut.constraintrange = axisBrush.cleanRanges(constraintRange, dimensionOut); - } - } -} - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var dimensionsIn = traceIn.dimensions; - if(Array.isArray(dimensionsIn) && dimensionsIn.length > maxDimensionCount) { - Lib.log('parcoords traces support up to ' + maxDimensionCount + ' dimensions at the moment'); - dimensionsIn.splice(maxDimensionCount); - } - - var dimensions = handleArrayContainerDefaults(traceIn, traceOut, { - name: 'dimensions', - layout: layout, - handleItemDefaults: dimensionDefaults - }); - - var len = handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - - handleDomainDefaults(traceOut, layout, coerce); - - if(!Array.isArray(dimensions) || !dimensions.length) { - traceOut.visible = false; - } - - mergeLength(traceOut, dimensions, 'values', len); - - // make default font size 10px (default is 12), - // scale linearly with global font size - var fontDflt = { - family: layout.font.family, - size: Math.round(layout.font.size / 1.2), - color: layout.font.color - }; - - Lib.coerceFont(coerce, 'labelfont', fontDflt); - Lib.coerceFont(coerce, 'tickfont', fontDflt); - Lib.coerceFont(coerce, 'rangefont', fontDflt); - - coerce('labelangle'); - coerce('labelside'); -}; - -},{"../../components/colorscale/defaults":603,"../../components/colorscale/helpers":604,"../../lib":719,"../../plots/array_container_defaults":763,"../../plots/cartesian/axes":767,"../../plots/domain":792,"./attributes":1074,"./axisbrush":1075,"./constants":1078,"./merge_length":1083}],1080:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isTypedArray = _dereq_('../../lib').isTypedArray; - -exports.convertTypedArray = function(a) { - return isTypedArray(a) ? Array.prototype.slice.call(a) : a; -}; - -exports.isOrdinal = function(dimension) { - return !!dimension.tickvals; -}; - -exports.isVisible = function(dimension) { - return dimension.visible || !('visible' in dimension); -}; - -},{"../../lib":719}],1081:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - colorbar: { - container: 'line', - min: 'cmin', - max: 'cmax' - }, - - moduleType: 'trace', - name: 'parcoords', - basePlotModule: _dereq_('./base_plot'), - categories: ['gl', 'regl', 'noOpacity', 'noHover'], - meta: { - - } -}; - -},{"./attributes":1074,"./base_plot":1076,"./calc":1077,"./defaults":1079,"./plot":1085}],1082:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var glslify = _dereq_('glslify'); -var vertexShaderSource = glslify(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor;\n\nattribute vec4 p01_04, p05_08, p09_12, p13_16,\n p17_20, p21_24, p25_28, p29_32,\n p33_36, p37_40, p41_44, p45_48,\n p49_52, p53_56, p57_60, colors;\n\nuniform mat4 dim0A, dim1A, dim0B, dim1B, dim0C, dim1C, dim0D, dim1D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD;\n\nuniform vec2 resolution, viewBoxPos, viewBoxSize;\nuniform sampler2D mask, palette;\nuniform float maskHeight;\nuniform float drwLayer; // 0: context, 1: focus, 2: pick\nuniform vec4 contextColor;\n\nbool isPick = (drwLayer > 1.5);\nbool isContext = (drwLayer < 0.5);\n\nconst vec4 ZEROS = vec4(0.0, 0.0, 0.0, 0.0);\nconst vec4 UNITS = vec4(1.0, 1.0, 1.0, 1.0);\n\nfloat val(mat4 p, mat4 v) {\n return dot(matrixCompMult(p, v) * UNITS, UNITS);\n}\n\nfloat axisY(float ratio, mat4 A, mat4 B, mat4 C, mat4 D) {\n float y1 = val(A, dim0A) + val(B, dim0B) + val(C, dim0C) + val(D, dim0D);\n float y2 = val(A, dim1A) + val(B, dim1B) + val(C, dim1C) + val(D, dim1D);\n return y1 * (1.0 - ratio) + y2 * ratio;\n}\n\nint iMod(int a, int b) {\n return a - b * (a / b);\n}\n\nbool fOutside(float p, float lo, float hi) {\n return (lo < hi) && (lo > p || p > hi);\n}\n\nbool vOutside(vec4 p, vec4 lo, vec4 hi) {\n return (\n fOutside(p[0], lo[0], hi[0]) ||\n fOutside(p[1], lo[1], hi[1]) ||\n fOutside(p[2], lo[2], hi[2]) ||\n fOutside(p[3], lo[3], hi[3])\n );\n}\n\nbool mOutside(mat4 p, mat4 lo, mat4 hi) {\n return (\n vOutside(p[0], lo[0], hi[0]) ||\n vOutside(p[1], lo[1], hi[1]) ||\n vOutside(p[2], lo[2], hi[2]) ||\n vOutside(p[3], lo[3], hi[3])\n );\n}\n\nbool outsideBoundingBox(mat4 A, mat4 B, mat4 C, mat4 D) {\n return mOutside(A, loA, hiA) ||\n mOutside(B, loB, hiB) ||\n mOutside(C, loC, hiC) ||\n mOutside(D, loD, hiD);\n}\n\nbool outsideRasterMask(mat4 A, mat4 B, mat4 C, mat4 D) {\n mat4 pnts[4];\n pnts[0] = A;\n pnts[1] = B;\n pnts[2] = C;\n pnts[3] = D;\n\n for(int i = 0; i < 4; ++i) {\n for(int j = 0; j < 4; ++j) {\n for(int k = 0; k < 4; ++k) {\n if(0 == iMod(\n int(255.0 * texture2D(mask,\n vec2(\n (float(i * 2 + j / 2) + 0.5) / 8.0,\n (pnts[i][j][k] * (maskHeight - 1.0) + 1.0) / maskHeight\n ))[3]\n ) / int(pow(2.0, float(iMod(j * 4 + k, 8)))),\n 2\n )) return true;\n }\n }\n }\n return false;\n}\n\nvec4 position(bool isContext, float v, mat4 A, mat4 B, mat4 C, mat4 D) {\n float x = 0.5 * sign(v) + 0.5;\n float y = axisY(x, A, B, C, D);\n float z = 1.0 - abs(v);\n\n z += isContext ? 0.0 : 2.0 * float(\n outsideBoundingBox(A, B, C, D) ||\n outsideRasterMask(A, B, C, D)\n );\n\n return vec4(\n 2.0 * (vec2(x, y) * viewBoxSize + viewBoxPos) / resolution - 1.0,\n z,\n 1.0\n );\n}\n\nvoid main() {\n mat4 A = mat4(p01_04, p05_08, p09_12, p13_16);\n mat4 B = mat4(p17_20, p21_24, p25_28, p29_32);\n mat4 C = mat4(p33_36, p37_40, p41_44, p45_48);\n mat4 D = mat4(p49_52, p53_56, p57_60, ZEROS);\n\n float v = colors[3];\n\n gl_Position = position(isContext, v, A, B, C, D);\n\n fragColor =\n isContext ? vec4(contextColor) :\n isPick ? vec4(colors.rgb, 1.0) : texture2D(palette, vec2(abs(v), 0.5));\n}\n"]); -var fragmentShaderSource = glslify(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor;\n\nvoid main() {\n gl_FragColor = fragColor;\n}\n"]); -var maxDim = _dereq_('./constants').maxDimensionCount; - -var Lib = _dereq_('../../lib'); - -// don't change; otherwise near/far plane lines are lost -var depthLimitEpsilon = 1e-6; - -// precision of multiselect is the full range divided into this many parts -var maskHeight = 2048; - -var dummyPixel = new Uint8Array(4); -var dataPixel = new Uint8Array(4); - -var paletteTextureConfig = { - shape: [256, 1], - format: 'rgba', - type: 'uint8', - mag: 'nearest', - min: 'nearest' -}; - -function ensureDraw(regl) { - regl.read({ - x: 0, - y: 0, - width: 1, - height: 1, - data: dummyPixel - }); -} - -function clear(regl, x, y, width, height) { - var gl = regl._gl; - gl.enable(gl.SCISSOR_TEST); - gl.scissor(x, y, width, height); - regl.clear({color: [0, 0, 0, 0], depth: 1}); // clearing is done in scissored panel only -} - -function renderBlock(regl, glAes, renderState, blockLineCount, sampleCount, item) { - var rafKey = item.key; - - function render(blockNumber) { - var count = Math.min(blockLineCount, sampleCount - blockNumber * blockLineCount); - - if(blockNumber === 0) { - // stop drawing possibly stale glyphs before clearing - window.cancelAnimationFrame(renderState.currentRafs[rafKey]); - delete renderState.currentRafs[rafKey]; - clear(regl, item.scissorX, item.scissorY, item.scissorWidth, item.viewBoxSize[1]); - } - - if(renderState.clearOnly) { - return; - } - - item.count = 2 * count; - item.offset = 2 * blockNumber * blockLineCount; - glAes(item); - - if(blockNumber * blockLineCount + count < sampleCount) { - renderState.currentRafs[rafKey] = window.requestAnimationFrame(function() { - render(blockNumber + 1); - }); - } - - renderState.drawCompleted = false; - } - - if(!renderState.drawCompleted) { - ensureDraw(regl); - renderState.drawCompleted = true; - } - - // start with rendering item 0; recursion handles the rest - render(0); -} - -function adjustDepth(d) { - // WebGL matrix operations use floats with limited precision, potentially causing a number near a border of [0, 1] - // to end up slightly outside the border. With an epsilon, we reduce the chance that a line gets clipped by the - // near or the far plane. - return Math.max(depthLimitEpsilon, Math.min(1 - depthLimitEpsilon, d)); -} - -function palette(unitToColor, opacity) { - var result = new Array(256); - for(var i = 0; i < 256; i++) { - result[i] = unitToColor(i / 255).concat(opacity); - } - return result; -} - -// Maps the sample index [0...sampleCount - 1] to a range of [0, 1] as the shader expects colors in the [0, 1] range. -// but first it shifts the sample index by 0, 8 or 16 bits depending on rgbIndex [0..2] -// with the end result that each line will be of a unique color, making it possible for the pick handler -// to uniquely identify which line is hovered over (bijective mapping). -// The inverse, i.e. readPixel is invoked from 'parcoords.js' -function calcPickColor(i, rgbIndex) { - return (i >>> 8 * rgbIndex) % 256 / 255; -} - -function makePoints(sampleCount, dims, color) { - var points = new Array(sampleCount * (maxDim + 4)); - var n = 0; - for(var i = 0; i < sampleCount; i++) { - for(var k = 0; k < maxDim; k++) { - points[n++] = (k < dims.length) ? dims[k].paddedUnitValues[i] : 0.5; - } - points[n++] = calcPickColor(i, 2); - points[n++] = calcPickColor(i, 1); - points[n++] = calcPickColor(i, 0); - points[n++] = adjustDepth(color[i]); - } - return points; -} - -function makeVecAttr(vecIndex, sampleCount, points) { - var pointPairs = new Array(sampleCount * 8); - var n = 0; - for(var i = 0; i < sampleCount; i++) { - for(var j = 0; j < 2; j++) { - for(var k = 0; k < 4; k++) { - var q = vecIndex * 4 + k; - var v = points[i * 64 + q]; - if(q === 63 && j === 0) { - v *= -1; - } - pointPairs[n++] = v; - } - } - } - return pointPairs; -} - -function pad2(num) { - var s = '0' + num; - return s.substr(s.length - 2); -} - -function getAttrName(i) { - return (i < maxDim) ? 'p' + pad2(i + 1) + '_' + pad2(i + 4) : 'colors'; -} - -function setAttributes(attributes, sampleCount, points) { - for(var i = 0; i <= maxDim; i += 4) { - attributes[getAttrName(i)](makeVecAttr(i / 4, sampleCount, points)); - } -} - -function emptyAttributes(regl) { - var attributes = {}; - for(var i = 0; i <= maxDim; i += 4) { - attributes[getAttrName(i)] = regl.buffer({usage: 'dynamic', type: 'float', data: new Uint8Array(0)}); - } - return attributes; -} - -function makeItem(model, leftmost, rightmost, itemNumber, i0, i1, x, y, panelSizeX, panelSizeY, crossfilterDimensionIndex, drwLayer, constraints) { - var dims = [[], []]; - for(var k = 0; k < 64; k++) { - dims[0][k] = (k === i0) ? 1 : 0; - dims[1][k] = (k === i1) ? 1 : 0; - } - - var overdrag = model.lines.canvasOverdrag; - var domain = model.domain; - var canvasWidth = model.canvasWidth; - var canvasHeight = model.canvasHeight; - - var deselectedLinesColor = model.deselectedLines.color; - - var itemModel = Lib.extendFlat({ - key: crossfilterDimensionIndex, - resolution: [canvasWidth, canvasHeight], - viewBoxPos: [x + overdrag, y], - viewBoxSize: [panelSizeX, panelSizeY], - i0: i0, - i1: i1, - - dim0A: dims[0].slice(0, 16), - dim0B: dims[0].slice(16, 32), - dim0C: dims[0].slice(32, 48), - dim0D: dims[0].slice(48, 64), - dim1A: dims[1].slice(0, 16), - dim1B: dims[1].slice(16, 32), - dim1C: dims[1].slice(32, 48), - dim1D: dims[1].slice(48, 64), - - drwLayer: drwLayer, - contextColor: [ - deselectedLinesColor[0] / 255, - deselectedLinesColor[1] / 255, - deselectedLinesColor[2] / 255, - deselectedLinesColor[3] < 1 ? - deselectedLinesColor[3] : - Math.max(1 / 255, Math.pow(1 / model.lines.color.length, 1 / 3)) - ], - - scissorX: (itemNumber === leftmost ? 0 : x + overdrag) + (model.pad.l - overdrag) + model.layoutWidth * domain.x[0], - scissorWidth: (itemNumber === rightmost ? canvasWidth - x + overdrag : panelSizeX + 0.5) + (itemNumber === leftmost ? x + overdrag : 0), - scissorY: y + model.pad.b + model.layoutHeight * domain.y[0], - scissorHeight: panelSizeY, - - viewportX: model.pad.l - overdrag + model.layoutWidth * domain.x[0], - viewportY: model.pad.b + model.layoutHeight * domain.y[0], - viewportWidth: canvasWidth, - viewportHeight: canvasHeight - }, constraints); - - return itemModel; -} - -function expandedPixelRange(bounds) { - var dh = maskHeight - 1; - var a = Math.max(0, Math.floor(bounds[0] * dh), 0); - var b = Math.min(dh, Math.ceil(bounds[1] * dh), dh); - return [ - Math.min(a, b), - Math.max(a, b) - ]; -} - -module.exports = function(canvasGL, d) { - // context & pick describe which canvas we're talking about - won't change with new data - var isContext = d.context; - var isPick = d.pick; - - var regl = d.regl; - - var renderState = { - currentRafs: {}, - drawCompleted: true, - clearOnly: false - }; - - // state to be set by update and used later - var model; - var vm; - var initialDims; - var sampleCount; - var attributes = emptyAttributes(regl); - var maskTexture; - var paletteTexture = regl.texture(paletteTextureConfig); - - var prevAxisOrder = []; - - update(d); - - var glAes = regl({ - - profile: false, - - blend: { - enable: isContext, - func: { - srcRGB: 'src alpha', - dstRGB: 'one minus src alpha', - srcAlpha: 1, - dstAlpha: 1 // 'one minus src alpha' - }, - equation: { - rgb: 'add', - alpha: 'add' - }, - color: [0, 0, 0, 0] - }, - - depth: { - enable: !isContext, - mask: true, - func: 'less', - range: [0, 1] - }, - - // for polygons - cull: { - enable: true, - face: 'back' - }, - - scissor: { - enable: true, - box: { - x: regl.prop('scissorX'), - y: regl.prop('scissorY'), - width: regl.prop('scissorWidth'), - height: regl.prop('scissorHeight') - } - }, - - viewport: { - x: regl.prop('viewportX'), - y: regl.prop('viewportY'), - width: regl.prop('viewportWidth'), - height: regl.prop('viewportHeight') - }, - - dither: false, - - vert: vertexShaderSource, - - frag: fragmentShaderSource, - - primitive: 'lines', - lineWidth: 1, - attributes: attributes, - uniforms: { - resolution: regl.prop('resolution'), - viewBoxPos: regl.prop('viewBoxPos'), - viewBoxSize: regl.prop('viewBoxSize'), - dim0A: regl.prop('dim0A'), - dim1A: regl.prop('dim1A'), - dim0B: regl.prop('dim0B'), - dim1B: regl.prop('dim1B'), - dim0C: regl.prop('dim0C'), - dim1C: regl.prop('dim1C'), - dim0D: regl.prop('dim0D'), - dim1D: regl.prop('dim1D'), - loA: regl.prop('loA'), - hiA: regl.prop('hiA'), - loB: regl.prop('loB'), - hiB: regl.prop('hiB'), - loC: regl.prop('loC'), - hiC: regl.prop('hiC'), - loD: regl.prop('loD'), - hiD: regl.prop('hiD'), - palette: paletteTexture, - contextColor: regl.prop('contextColor'), - mask: regl.prop('maskTexture'), - drwLayer: regl.prop('drwLayer'), - maskHeight: regl.prop('maskHeight') - }, - offset: regl.prop('offset'), - count: regl.prop('count') - }); - - function update(dNew) { - model = dNew.model; - vm = dNew.viewModel; - initialDims = vm.dimensions.slice(); - sampleCount = initialDims[0] ? initialDims[0].values.length : 0; - - var lines = model.lines; - var color = isPick ? lines.color.map(function(_, i) {return i / lines.color.length;}) : lines.color; - - var points = makePoints(sampleCount, initialDims, color); - setAttributes(attributes, sampleCount, points); - - if(!isContext && !isPick) { - paletteTexture = regl.texture(Lib.extendFlat({ - data: palette(model.unitToColor, 255) - }, paletteTextureConfig)); - } - } - - function makeConstraints(isContext) { - var i, j, k; - - var limits = [[], []]; - for(k = 0; k < 64; k++) { - var p = (!isContext && k < initialDims.length) ? - initialDims[k].brush.filter.getBounds() : [-Infinity, Infinity]; - - limits[0][k] = p[0]; - limits[1][k] = p[1]; - } - - var len = maskHeight * 8; - var mask = new Array(len); - for(i = 0; i < len; i++) { - mask[i] = 255; - } - if(!isContext) { - for(i = 0; i < initialDims.length; i++) { - var u = i % 8; - var v = (i - u) / 8; - var bitMask = Math.pow(2, u); - var dim = initialDims[i]; - var ranges = dim.brush.filter.get(); - if(ranges.length < 2) continue; // bail if the bounding box based filter is sufficient - - var prevEnd = expandedPixelRange(ranges[0])[1]; - for(j = 1; j < ranges.length; j++) { - var nextRange = expandedPixelRange(ranges[j]); - for(k = prevEnd + 1; k < nextRange[0]; k++) { - mask[k * 8 + v] &= ~bitMask; - } - prevEnd = Math.max(prevEnd, nextRange[1]); - } - } - } - - var textureData = { - // 8 units x 8 bits = 64 bits, just sufficient for the almost 64 dimensions we support - shape: [8, maskHeight], - format: 'alpha', - type: 'uint8', - mag: 'nearest', - min: 'nearest', - data: mask - }; - if(maskTexture) maskTexture(textureData); - else maskTexture = regl.texture(textureData); - - return { - maskTexture: maskTexture, - maskHeight: maskHeight, - loA: limits[0].slice(0, 16), - loB: limits[0].slice(16, 32), - loC: limits[0].slice(32, 48), - loD: limits[0].slice(48, 64), - hiA: limits[1].slice(0, 16), - hiB: limits[1].slice(16, 32), - hiC: limits[1].slice(32, 48), - hiD: limits[1].slice(48, 64), - }; - } - - function renderGLParcoords(panels, setChanged, clearOnly) { - var panelCount = panels.length; - var i; - - var leftmost; - var rightmost; - var lowestX = Infinity; - var highestX = -Infinity; - - for(i = 0; i < panelCount; i++) { - if(panels[i].dim0.canvasX < lowestX) { - lowestX = panels[i].dim0.canvasX; - leftmost = i; - } - if(panels[i].dim1.canvasX > highestX) { - highestX = panels[i].dim1.canvasX; - rightmost = i; - } - } - - if(panelCount === 0) { - // clear canvas here, as the panel iteration below will not enter the loop body - clear(regl, 0, 0, model.canvasWidth, model.canvasHeight); - } - var constraints = makeConstraints(isContext); - - for(i = 0; i < panelCount; i++) { - var p = panels[i]; - var i0 = p.dim0.crossfilterDimensionIndex; - var i1 = p.dim1.crossfilterDimensionIndex; - var x = p.canvasX; - var y = p.canvasY; - var nextX = x + p.panelSizeX; - if(setChanged || - !prevAxisOrder[i0] || - prevAxisOrder[i0][0] !== x || - prevAxisOrder[i0][1] !== nextX - ) { - prevAxisOrder[i0] = [x, nextX]; - - var item = makeItem( - model, - leftmost, rightmost, i, i0, i1, x, y, - p.panelSizeX, p.panelSizeY, - p.dim0.crossfilterDimensionIndex, - isContext ? 0 : isPick ? 2 : 1, - constraints - ); - - renderState.clearOnly = clearOnly; - - var blockLineCount = setChanged ? model.lines.blockLineCount : sampleCount; - renderBlock( - regl, glAes, renderState, blockLineCount, sampleCount, item - ); - } - } - } - - function readPixel(canvasX, canvasY) { - regl.read({ - x: canvasX, - y: canvasY, - width: 1, - height: 1, - data: dataPixel - }); - return dataPixel; - } - - function readPixels(canvasX, canvasY, width, height) { - var pixelArray = new Uint8Array(4 * width * height); - regl.read({ - x: canvasX, - y: canvasY, - width: width, - height: height, - data: pixelArray - }); - return pixelArray; - } - - function destroy() { - canvasGL.style['pointer-events'] = 'none'; - paletteTexture.destroy(); - if(maskTexture) maskTexture.destroy(); - for(var k in attributes) attributes[k].destroy(); - } - - return { - render: renderGLParcoords, - readPixel: readPixel, - readPixels: readPixels, - destroy: destroy, - update: update - }; -}; - -},{"../../lib":719,"./constants":1078,"glslify":409}],1083:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -/** - * mergeLength: set trace length as the minimum of all dimension data lengths - * and propagates this length into each dimension - * - * @param {object} traceOut: the fullData trace - * @param {Array(object)} dimensions: array of dimension objects - * @param {string} dataAttr: the attribute of each dimension containing the data - * @param {integer} len: an already-existing length from other attributes - */ -module.exports = function(traceOut, dimensions, dataAttr, len) { - if(!len) len = Infinity; - var i, dimi; - for(i = 0; i < dimensions.length; i++) { - dimi = dimensions[i]; - if(dimi.visible) len = Math.min(len, dimi[dataAttr].length); - } - if(len === Infinity) len = 0; - - traceOut._length = len; - for(i = 0; i < dimensions.length; i++) { - dimi = dimensions[i]; - if(dimi.visible) dimi._length = len; - } - - return len; -}; - -},{}],1084:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var rgba = _dereq_('color-rgba'); - -var Axes = _dereq_('../../plots/cartesian/axes'); -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var Drawing = _dereq_('../../components/drawing'); -var Colorscale = _dereq_('../../components/colorscale'); - -var gup = _dereq_('../../lib/gup'); -var keyFun = gup.keyFun; -var repeat = gup.repeat; -var unwrap = gup.unwrap; - -var helpers = _dereq_('./helpers'); -var c = _dereq_('./constants'); -var brush = _dereq_('./axisbrush'); -var lineLayerMaker = _dereq_('./lines'); - -function findExtreme(fn, values, len) { - return Lib.aggNums(fn, null, values, len); -} - -function findExtremes(values, len) { - return fixExtremes( - findExtreme(Math.min, values, len), - findExtreme(Math.max, values, len) - ); -} - -function dimensionExtent(dimension) { - var range = dimension.range; - return range ? - fixExtremes(range[0], range[1]) : - findExtremes(dimension.values, dimension._length); -} - -function fixExtremes(lo, hi) { - if(isNaN(lo) || !isFinite(lo)) { - lo = 0; - } - - if(isNaN(hi) || !isFinite(hi)) { - hi = 0; - } - - // avoid a degenerate (zero-width) domain - if(lo === hi) { - if(lo === 0) { - // no use to multiplying zero, so add/subtract in this case - lo -= 1; - hi += 1; - } else { - // this keeps the range in the order of magnitude of the data - lo *= 0.9; - hi *= 1.1; - } - } - - return [lo, hi]; -} - -function toText(formatter, texts) { - if(texts) { - return function(v, i) { - var text = texts[i]; - if(text === null || text === undefined) return formatter(v); - return text; - }; - } - return formatter; -} - -function domainScale(height, padding, dimension, tickvals, ticktext) { - var extent = dimensionExtent(dimension); - if(tickvals) { - return d3.scale.ordinal() - .domain(tickvals.map(toText(d3.format(dimension.tickformat), ticktext))) - .range(tickvals - .map(function(d) { - var unitVal = (d - extent[0]) / (extent[1] - extent[0]); - return (height - padding + unitVal * (2 * padding - height)); - }) - ); - } - return d3.scale.linear() - .domain(extent) - .range([height - padding, padding]); -} - -function unitToPaddedPx(height, padding) { - return d3.scale.linear().range([padding, height - padding]); -} - -function domainToPaddedUnitScale(dimension, padFraction) { - return d3.scale.linear() - .domain(dimensionExtent(dimension)) - .range([padFraction, 1 - padFraction]); -} - -function ordinalScale(dimension) { - if(!dimension.tickvals) return; - - var extent = dimensionExtent(dimension); - return d3.scale.ordinal() - .domain(dimension.tickvals) - .range(dimension.tickvals.map(function(d) { - return (d - extent[0]) / (extent[1] - extent[0]); - })); -} - -function unitToColorScale(cscale) { - var colorStops = cscale.map(function(d) { return d[0]; }); - var colorTuples = cscale.map(function(d) { - var RGBA = rgba(d[1]); - return d3.rgb('rgb(' + RGBA[0] + ',' + RGBA[1] + ',' + RGBA[2] + ')'); - }); - var prop = function(n) { return function(o) { return o[n]; }; }; - - // We can't use d3 color interpolation as we may have non-uniform color palette raster - // (various color stop distances). - var polylinearUnitScales = 'rgb'.split('').map(function(key) { - return d3.scale.linear() - .clamp(true) - .domain(colorStops) - .range(colorTuples.map(prop(key))); - }); - - return function(d) { - return polylinearUnitScales.map(function(s) { - return s(d); - }); - }; -} - -function someFiltersActive(view) { - return view.dimensions.some(function(p) { - return p.brush.filterSpecified; - }); -} - -function model(layout, d, i) { - var cd0 = unwrap(d); - var trace = cd0.trace; - var lineColor = helpers.convertTypedArray(cd0.lineColor); - var line = trace.line; - var deselectedLines = {color: rgba(c.deselectedLineColor)}; - var cOpts = Colorscale.extractOpts(line); - var cscale = cOpts.reversescale ? Colorscale.flipScale(cd0.cscale) : cd0.cscale; - var domain = trace.domain; - var dimensions = trace.dimensions; - var width = layout.width; - var labelAngle = trace.labelangle; - var labelSide = trace.labelside; - var labelFont = trace.labelfont; - var tickFont = trace.tickfont; - var rangeFont = trace.rangefont; - - var lines = Lib.extendDeepNoArrays({}, line, { - color: lineColor.map(d3.scale.linear().domain( - dimensionExtent({ - values: lineColor, - range: [cOpts.min, cOpts.max], - _length: trace._length - }) - )), - blockLineCount: c.blockLineCount, - canvasOverdrag: c.overdrag * c.canvasPixelRatio - }); - - var groupWidth = Math.floor(width * (domain.x[1] - domain.x[0])); - var groupHeight = Math.floor(layout.height * (domain.y[1] - domain.y[0])); - - var pad = layout.margin || {l: 80, r: 80, t: 100, b: 80}; - var rowContentWidth = groupWidth; - var rowHeight = groupHeight; - - return { - key: i, - colCount: dimensions.filter(helpers.isVisible).length, - dimensions: dimensions, - tickDistance: c.tickDistance, - unitToColor: unitToColorScale(cscale), - lines: lines, - deselectedLines: deselectedLines, - labelAngle: labelAngle, - labelSide: labelSide, - labelFont: labelFont, - tickFont: tickFont, - rangeFont: rangeFont, - layoutWidth: width, - layoutHeight: layout.height, - domain: domain, - translateX: domain.x[0] * width, - translateY: layout.height - domain.y[1] * layout.height, - pad: pad, - canvasWidth: rowContentWidth * c.canvasPixelRatio + 2 * lines.canvasOverdrag, - canvasHeight: rowHeight * c.canvasPixelRatio, - width: rowContentWidth, - height: rowHeight, - canvasPixelRatio: c.canvasPixelRatio - }; -} - -function viewModel(state, callbacks, model) { - var width = model.width; - var height = model.height; - var dimensions = model.dimensions; - var canvasPixelRatio = model.canvasPixelRatio; - - var xScale = function(d) {return width * d / Math.max(1, model.colCount - 1);}; - - var unitPad = c.verticalPadding / height; - var _unitToPaddedPx = unitToPaddedPx(height, c.verticalPadding); - - var vm = { - key: model.key, - xScale: xScale, - model: model, - inBrushDrag: false // consider factoring it out and putting it in a centralized global-ish gesture state object - }; - - var uniqueKeys = {}; - - vm.dimensions = dimensions.filter(helpers.isVisible).map(function(dimension, i) { - var domainToPaddedUnit = domainToPaddedUnitScale(dimension, unitPad); - var foundKey = uniqueKeys[dimension.label]; - uniqueKeys[dimension.label] = (foundKey || 0) + 1; - var key = dimension.label + (foundKey ? '__' + foundKey : ''); - var specifiedConstraint = dimension.constraintrange; - var filterRangeSpecified = specifiedConstraint && specifiedConstraint.length; - if(filterRangeSpecified && !Array.isArray(specifiedConstraint[0])) { - specifiedConstraint = [specifiedConstraint]; - } - var filterRange = filterRangeSpecified ? - specifiedConstraint.map(function(d) { return d.map(domainToPaddedUnit); }) : - [[-Infinity, Infinity]]; - var brushMove = function() { - var p = vm; - p.focusLayer && p.focusLayer.render(p.panels, true); - var filtersActive = someFiltersActive(p); - if(!state.contextShown() && filtersActive) { - p.contextLayer && p.contextLayer.render(p.panels, true); - state.contextShown(true); - } else if(state.contextShown() && !filtersActive) { - p.contextLayer && p.contextLayer.render(p.panels, true, true); - state.contextShown(false); - } - }; - - var truncatedValues = dimension.values; - if(truncatedValues.length > dimension._length) { - truncatedValues = truncatedValues.slice(0, dimension._length); - } - - var tickvals = dimension.tickvals; - var ticktext; - function makeTickItem(v, i) { return {val: v, text: ticktext[i]}; } - function sortTickItem(a, b) { return a.val - b.val; } - if(Array.isArray(tickvals) && tickvals.length) { - ticktext = dimension.ticktext; - - // ensure ticktext and tickvals have same length - if(!Array.isArray(ticktext) || !ticktext.length) { - ticktext = tickvals.map(d3.format(dimension.tickformat)); - } else if(ticktext.length > tickvals.length) { - ticktext = ticktext.slice(0, tickvals.length); - } else if(tickvals.length > ticktext.length) { - tickvals = tickvals.slice(0, ticktext.length); - } - - // check if we need to sort tickvals/ticktext - for(var j = 1; j < tickvals.length; j++) { - if(tickvals[j] < tickvals[j - 1]) { - var tickItems = tickvals.map(makeTickItem).sort(sortTickItem); - for(var k = 0; k < tickvals.length; k++) { - tickvals[k] = tickItems[k].val; - ticktext[k] = tickItems[k].text; - } - break; - } - } - } else tickvals = undefined; - - truncatedValues = helpers.convertTypedArray(truncatedValues); - truncatedValues = helpers.convertTypedArray(truncatedValues); - - return { - key: key, - label: dimension.label, - tickFormat: dimension.tickformat, - tickvals: tickvals, - ticktext: ticktext, - ordinal: helpers.isOrdinal(dimension), - multiselect: dimension.multiselect, - xIndex: i, - crossfilterDimensionIndex: i, - visibleIndex: dimension._index, - height: height, - values: truncatedValues, - paddedUnitValues: truncatedValues.map(domainToPaddedUnit), - unitTickvals: tickvals && tickvals.map(domainToPaddedUnit), - xScale: xScale, - x: xScale(i), - canvasX: xScale(i) * canvasPixelRatio, - unitToPaddedPx: _unitToPaddedPx, - domainScale: domainScale(height, c.verticalPadding, dimension, tickvals, ticktext), - ordinalScale: ordinalScale(dimension), - parent: vm, - model: model, - brush: brush.makeBrush( - state, - filterRangeSpecified, - filterRange, - function() { - state.linePickActive(false); - }, - brushMove, - function(f) { - vm.focusLayer.render(vm.panels, true); - vm.pickLayer && vm.pickLayer.render(vm.panels, true); - state.linePickActive(true); - if(callbacks && callbacks.filterChanged) { - var invScale = domainToPaddedUnit.invert; - - // update gd.data as if a Plotly.restyle were fired - var newRanges = f.map(function(r) { - return r.map(invScale).sort(Lib.sorterAsc); - }).sort(function(a, b) { return a[0] - b[0]; }); - callbacks.filterChanged(vm.key, dimension._index, newRanges); - } - } - ) - }; - }); - - return vm; -} - -function styleExtentTexts(selection) { - selection - .classed(c.cn.axisExtentText, true) - .attr('text-anchor', 'middle') - .style('cursor', 'default') - .style('user-select', 'none'); -} - -function parcoordsInteractionState() { - var linePickActive = true; - var contextShown = false; - return { - linePickActive: function(val) {return arguments.length ? linePickActive = !!val : linePickActive;}, - contextShown: function(val) {return arguments.length ? contextShown = !!val : contextShown;} - }; -} - -function calcTilt(angle, position) { - var dir = (position === 'top') ? 1 : -1; - var radians = angle * Math.PI / 180; - var dx = Math.sin(radians); - var dy = Math.cos(radians); - return { - dir: dir, - dx: dx, - dy: dy, - degrees: angle - }; -} - -function updatePanelLayout(yAxis, vm) { - var panels = vm.panels || (vm.panels = []); - var data = yAxis.data(); - for(var i = 0; i < data.length - 1; i++) { - var p = panels[i] || (panels[i] = {}); - var dim0 = data[i]; - var dim1 = data[i + 1]; - p.dim0 = dim0; - p.dim1 = dim1; - p.canvasX = dim0.canvasX; - p.panelSizeX = dim1.canvasX - dim0.canvasX; - p.panelSizeY = vm.model.canvasHeight; - p.y = 0; - p.canvasY = 0; - } -} - -function calcAllTicks(cd) { - for(var i = 0; i < cd.length; i++) { - for(var j = 0; j < cd[i].length; j++) { - var trace = cd[i][j].trace; - var dimensions = trace.dimensions; - - for(var k = 0; k < dimensions.length; k++) { - var values = dimensions[k].values; - var dim = dimensions[k]._ax; - - if(dim) { - if(!dim.range) { - dim.range = findExtremes(values, trace._length); - } else { - dim.range = fixExtremes(dim.range[0], dim.range[1]); - } - - if(!dim.dtick) { - dim.dtick = 0.01 * (Math.abs(dim.range[1] - dim.range[0]) || 1); - } - - dim.tickformat = dimensions[k].tickformat; - Axes.calcTicks(dim); - dim.cleanRange(); - } - } - } - } -} - -function linearFormat(dim, v) { - return Axes.tickText(dim._ax, v, false).text; -} - -function extremeText(d, isTop) { - if(d.ordinal) return ''; - var domain = d.domainScale.domain(); - var v = (domain[isTop ? domain.length - 1 : 0]); - - return linearFormat(d.model.dimensions[d.visibleIndex], v); -} - - -module.exports = function parcoords(gd, cdModule, layout, callbacks) { - var fullLayout = gd._fullLayout; - var svg = fullLayout._toppaper; - var glContainer = fullLayout._glcontainer; - - calcAllTicks(cdModule); - - var state = parcoordsInteractionState(); - - var vm = cdModule - .filter(function(d) { return unwrap(d).trace.visible; }) - .map(model.bind(0, layout)) - .map(viewModel.bind(0, state, callbacks)); - - glContainer.each(function(d, i) { - return Lib.extendFlat(d, vm[i]); - }); - - var glLayers = glContainer.selectAll('.gl-canvas') - .each(function(d) { - // FIXME: figure out how to handle multiple instances - d.viewModel = vm[0]; - d.model = d.viewModel ? d.viewModel.model : null; - }); - - var lastHovered = null; - - var pickLayer = glLayers.filter(function(d) {return d.pick;}); - - // emit hover / unhover event - pickLayer - .style('pointer-events', 'auto') - .on('mousemove', function(d) { - if(state.linePickActive() && d.lineLayer && callbacks && callbacks.hover) { - var event = d3.event; - var cw = this.width; - var ch = this.height; - var pointer = d3.mouse(this); - var x = pointer[0]; - var y = pointer[1]; - - if(x < 0 || y < 0 || x >= cw || y >= ch) { - return; - } - var pixel = d.lineLayer.readPixel(x, ch - 1 - y); - var found = pixel[3] !== 0; - // inverse of the calcPickColor in `lines.js`; detailed comment there - var curveNumber = found ? pixel[2] + 256 * (pixel[1] + 256 * pixel[0]) : null; - var eventData = { - x: x, - y: y, - clientX: event.clientX, - clientY: event.clientY, - dataIndex: d.model.key, - curveNumber: curveNumber - }; - if(curveNumber !== lastHovered) { // don't unnecessarily repeat the same hit (or miss) - if(found) { - callbacks.hover(eventData); - } else if(callbacks.unhover) { - callbacks.unhover(eventData); - } - lastHovered = curveNumber; - } - } - }); - - glLayers - .style('opacity', function(d) {return d.pick ? 0 : 1;}); - - svg.style('background', 'rgba(255, 255, 255, 0)'); - var controlOverlay = svg.selectAll('.' + c.cn.parcoords) - .data(vm, keyFun); - - controlOverlay.exit().remove(); - - controlOverlay.enter() - .append('g') - .classed(c.cn.parcoords, true) - .style('shape-rendering', 'crispEdges') - .style('pointer-events', 'none'); - - controlOverlay.attr('transform', function(d) { - return 'translate(' + d.model.translateX + ',' + d.model.translateY + ')'; - }); - - var parcoordsControlView = controlOverlay.selectAll('.' + c.cn.parcoordsControlView) - .data(repeat, keyFun); - - parcoordsControlView.enter() - .append('g') - .classed(c.cn.parcoordsControlView, true); - - parcoordsControlView.attr('transform', function(d) { - return 'translate(' + d.model.pad.l + ',' + d.model.pad.t + ')'; - }); - - var yAxis = parcoordsControlView.selectAll('.' + c.cn.yAxis) - .data(function(p) { return p.dimensions; }, keyFun); - - yAxis.enter() - .append('g') - .classed(c.cn.yAxis, true); - - parcoordsControlView.each(function(p) { - updatePanelLayout(yAxis, p); - }); - - glLayers - .each(function(d) { - if(d.viewModel) { - if(!d.lineLayer || callbacks) { // recreate in case of having callbacks e.g. restyle. Should we test for callback to be a restyle? - d.lineLayer = lineLayerMaker(this, d); - } else d.lineLayer.update(d); - - if(d.key || d.key === 0) d.viewModel[d.key] = d.lineLayer; - - var setChanged = (!d.context || // don't update background - callbacks); // unless there is a callback on the context layer. Should we test the callback? - - d.lineLayer.render(d.viewModel.panels, setChanged); - } - }); - - yAxis.attr('transform', function(d) { - return 'translate(' + d.xScale(d.xIndex) + ', 0)'; - }); - - // drag column for reordering columns - yAxis.call(d3.behavior.drag() - .origin(function(d) { return d; }) - .on('drag', function(d) { - var p = d.parent; - state.linePickActive(false); - d.x = Math.max(-c.overdrag, Math.min(d.model.width + c.overdrag, d3.event.x)); - d.canvasX = d.x * d.model.canvasPixelRatio; - yAxis - .sort(function(a, b) { return a.x - b.x; }) - .each(function(e, i) { - e.xIndex = i; - e.x = d === e ? e.x : e.xScale(e.xIndex); - e.canvasX = e.x * e.model.canvasPixelRatio; - }); - - updatePanelLayout(yAxis, p); - - yAxis.filter(function(e) { return Math.abs(d.xIndex - e.xIndex) !== 0; }) - .attr('transform', function(d) { return 'translate(' + d.xScale(d.xIndex) + ', 0)'; }); - d3.select(this).attr('transform', 'translate(' + d.x + ', 0)'); - yAxis.each(function(e, i0, i1) { if(i1 === d.parent.key) p.dimensions[i0] = e; }); - p.contextLayer && p.contextLayer.render(p.panels, false, !someFiltersActive(p)); - p.focusLayer.render && p.focusLayer.render(p.panels); - }) - .on('dragend', function(d) { - var p = d.parent; - d.x = d.xScale(d.xIndex); - d.canvasX = d.x * d.model.canvasPixelRatio; - updatePanelLayout(yAxis, p); - d3.select(this) - .attr('transform', function(d) { return 'translate(' + d.x + ', 0)'; }); - p.contextLayer && p.contextLayer.render(p.panels, false, !someFiltersActive(p)); - p.focusLayer && p.focusLayer.render(p.panels); - p.pickLayer && p.pickLayer.render(p.panels, true); - state.linePickActive(true); - - if(callbacks && callbacks.axesMoved) { - callbacks.axesMoved(p.key, p.dimensions.map(function(e) {return e.crossfilterDimensionIndex;})); - } - }) - ); - - yAxis.exit() - .remove(); - - var axisOverlays = yAxis.selectAll('.' + c.cn.axisOverlays) - .data(repeat, keyFun); - - axisOverlays.enter() - .append('g') - .classed(c.cn.axisOverlays, true); - - axisOverlays.selectAll('.' + c.cn.axis).remove(); - - var axis = axisOverlays.selectAll('.' + c.cn.axis) - .data(repeat, keyFun); - - axis.enter() - .append('g') - .classed(c.cn.axis, true); - - axis - .each(function(d) { - var wantedTickCount = d.model.height / d.model.tickDistance; - var scale = d.domainScale; - var sdom = scale.domain(); - d3.select(this) - .call(d3.svg.axis() - .orient('left') - .tickSize(4) - .outerTickSize(2) - .ticks(wantedTickCount, d.tickFormat) // works for continuous scales only... - .tickValues(d.ordinal ? // and this works for ordinal scales - sdom : - null) - .tickFormat(function(v) { - return helpers.isOrdinal(d) ? v : linearFormat(d.model.dimensions[d.visibleIndex], v); - }) - .scale(scale)); - Drawing.font(axis.selectAll('text'), d.model.tickFont); - }); - - axis.selectAll('.domain, .tick>line') - .attr('fill', 'none') - .attr('stroke', 'black') - .attr('stroke-opacity', 0.25) - .attr('stroke-width', '1px'); - - axis.selectAll('text') - .style('text-shadow', '1px 1px 1px #fff, -1px -1px 1px #fff, 1px -1px 1px #fff, -1px 1px 1px #fff') - .style('cursor', 'default') - .style('user-select', 'none'); - - var axisHeading = axisOverlays.selectAll('.' + c.cn.axisHeading) - .data(repeat, keyFun); - - axisHeading.enter() - .append('g') - .classed(c.cn.axisHeading, true); - - var axisTitle = axisHeading.selectAll('.' + c.cn.axisTitle) - .data(repeat, keyFun); - - axisTitle.enter() - .append('text') - .classed(c.cn.axisTitle, true) - .attr('text-anchor', 'middle') - .style('cursor', 'ew-resize') - .style('user-select', 'none') - .style('pointer-events', 'auto'); - - axisTitle - .text(function(d) { return d.label; }) - .each(function(d) { - var e = d3.select(this); - Drawing.font(e, d.model.labelFont); - svgTextUtils.convertToTspans(e, gd); - }) - .attr('transform', function(d) { - var tilt = calcTilt(d.model.labelAngle, d.model.labelSide); - var r = c.axisTitleOffset; - return ( - (tilt.dir > 0 ? '' : 'translate(0,' + (2 * r + d.model.height) + ')') + - 'rotate(' + tilt.degrees + ')' + - 'translate(' + (-r * tilt.dx) + ',' + (-r * tilt.dy) + ')' - ); - }) - .attr('text-anchor', function(d) { - var tilt = calcTilt(d.model.labelAngle, d.model.labelSide); - var adx = Math.abs(tilt.dx); - var ady = Math.abs(tilt.dy); - - if(2 * adx > ady) { - return (tilt.dir * tilt.dx < 0) ? 'start' : 'end'; - } else { - return 'middle'; - } - }); - - var axisExtent = axisOverlays.selectAll('.' + c.cn.axisExtent) - .data(repeat, keyFun); - - axisExtent.enter() - .append('g') - .classed(c.cn.axisExtent, true); - - var axisExtentTop = axisExtent.selectAll('.' + c.cn.axisExtentTop) - .data(repeat, keyFun); - - axisExtentTop.enter() - .append('g') - .classed(c.cn.axisExtentTop, true); - - axisExtentTop - .attr('transform', 'translate(' + 0 + ',' + -c.axisExtentOffset + ')'); - - var axisExtentTopText = axisExtentTop.selectAll('.' + c.cn.axisExtentTopText) - .data(repeat, keyFun); - - axisExtentTopText.enter() - .append('text') - .classed(c.cn.axisExtentTopText, true) - .call(styleExtentTexts); - - axisExtentTopText - .text(function(d) { return extremeText(d, true); }) - .each(function(d) { Drawing.font(d3.select(this), d.model.rangeFont); }); - - var axisExtentBottom = axisExtent.selectAll('.' + c.cn.axisExtentBottom) - .data(repeat, keyFun); - - axisExtentBottom.enter() - .append('g') - .classed(c.cn.axisExtentBottom, true); - - axisExtentBottom - .attr('transform', function(d) { - return 'translate(' + 0 + ',' + (d.model.height + c.axisExtentOffset) + ')'; - }); - - var axisExtentBottomText = axisExtentBottom.selectAll('.' + c.cn.axisExtentBottomText) - .data(repeat, keyFun); - - axisExtentBottomText.enter() - .append('text') - .classed(c.cn.axisExtentBottomText, true) - .attr('dy', '0.75em') - .call(styleExtentTexts); - - axisExtentBottomText - .text(function(d) { return extremeText(d, false); }) - .each(function(d) { Drawing.font(d3.select(this), d.model.rangeFont); }); - - brush.ensureAxisBrush(axisOverlays); -}; - -},{"../../components/colorscale":605,"../../components/drawing":614,"../../lib":719,"../../lib/gup":717,"../../lib/svg_text_utils":743,"../../plots/cartesian/axes":767,"./axisbrush":1075,"./constants":1078,"./helpers":1080,"./lines":1082,"color-rgba":122,"d3":163}],1085:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var parcoords = _dereq_('./parcoords'); -var prepareRegl = _dereq_('../../lib/prepare_regl'); -var isVisible = _dereq_('./helpers').isVisible; - -function newIndex(visibleIndices, orig, dim) { - var origIndex = orig.indexOf(dim); - var currentIndex = visibleIndices.indexOf(origIndex); - if(currentIndex === -1) { - // invisible dimensions initially go to the end - currentIndex += orig.length; - } - return currentIndex; -} - -function sorter(visibleIndices, orig) { - return function sorter(d1, d2) { - return ( - newIndex(visibleIndices, orig, d1) - - newIndex(visibleIndices, orig, d2) - ); - }; -} - -module.exports = function plot(gd, cdModule) { - var fullLayout = gd._fullLayout; - - var success = prepareRegl(gd); - if(!success) return; - - var currentDims = {}; - var initialDims = {}; - var fullIndices = {}; - var inputIndices = {}; - - var size = fullLayout._size; - - cdModule.forEach(function(d, i) { - var trace = d[0].trace; - fullIndices[i] = trace.index; - var iIn = inputIndices[i] = trace._fullInput.index; - currentDims[i] = gd.data[iIn].dimensions; - initialDims[i] = gd.data[iIn].dimensions.slice(); - }); - - var filterChanged = function(i, initialDimIndex, newRanges) { - // Have updated `constraintrange` data on `gd.data` and raise `Plotly.restyle` event - // without having to incur heavy UI blocking due to an actual `Plotly.restyle` call - - var dim = initialDims[i][initialDimIndex]; - var newConstraints = newRanges.map(function(r) { return r.slice(); }); - - // Store constraint range in preGUI - // This one doesn't work if it's stored in pieces in _storeDirectGUIEdit - // because it's an array of variable dimensionality. So store the whole - // thing at once manually. - var aStr = 'dimensions[' + initialDimIndex + '].constraintrange'; - var preGUI = fullLayout._tracePreGUI[gd._fullData[fullIndices[i]]._fullInput.uid]; - if(preGUI[aStr] === undefined) { - var initialVal = dim.constraintrange; - preGUI[aStr] = initialVal || null; - } - - var fullDimension = gd._fullData[fullIndices[i]].dimensions[initialDimIndex]; - - if(!newConstraints.length) { - delete dim.constraintrange; - delete fullDimension.constraintrange; - newConstraints = null; - } else { - if(newConstraints.length === 1) newConstraints = newConstraints[0]; - dim.constraintrange = newConstraints; - fullDimension.constraintrange = newConstraints.slice(); - // wrap in another array for restyle event data - newConstraints = [newConstraints]; - } - - var restyleData = {}; - restyleData[aStr] = newConstraints; - gd.emit('plotly_restyle', [restyleData, [inputIndices[i]]]); - }; - - var hover = function(eventData) { - gd.emit('plotly_hover', eventData); - }; - - var unhover = function(eventData) { - gd.emit('plotly_unhover', eventData); - }; - - var axesMoved = function(i, visibleIndices) { - // Have updated order data on `gd.data` and raise `Plotly.restyle` event - // without having to incur heavy UI blocking due to an actual `Plotly.restyle` call - - // drag&drop sorting of the visible dimensions - var orig = sorter(visibleIndices, initialDims[i].filter(isVisible)); - currentDims[i].sort(orig); - - // invisible dimensions are not interpreted in the context of drag&drop sorting as an invisible dimension - // cannot be dragged; they're interspersed into their original positions by this subsequent merging step - initialDims[i].filter(function(d) {return !isVisible(d);}) - .sort(function(d) { - // subsequent splicing to be done left to right, otherwise indices may be incorrect - return initialDims[i].indexOf(d); - }) - .forEach(function(d) { - currentDims[i].splice(currentDims[i].indexOf(d), 1); // remove from the end - currentDims[i].splice(initialDims[i].indexOf(d), 0, d); // insert at original index - }); - - // TODO: we can't really store this part of the interaction state - // directly as below, since it incudes data arrays. If we want to - // persist column order we may have to do something special for this - // case to just store the order itself. - // Registry.call('_storeDirectGUIEdit', - // gd.data[inputIndices[i]], - // fullLayout._tracePreGUI[gd._fullData[fullIndices[i]]._fullInput.uid], - // {dimensions: currentDims[i]} - // ); - - gd.emit('plotly_restyle', [{dimensions: [currentDims[i]]}, [inputIndices[i]]]); - }; - - parcoords( - gd, - cdModule, - { // layout - width: size.w, - height: size.h, - margin: { - t: size.t, - r: size.r, - b: size.b, - l: size.l - } - }, - { // callbacks - filterChanged: filterChanged, - hover: hover, - unhover: unhover, - axesMoved: axesMoved - } - ); -}; - -},{"../../lib/prepare_regl":732,"./helpers":1080,"./parcoords":1084}],1086:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var plotAttrs = _dereq_('../../plots/attributes'); -var domainAttrs = _dereq_('../../plots/domain').attributes; -var fontAttrs = _dereq_('../../plots/font_attributes'); -var colorAttrs = _dereq_('../../components/color/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var textFontAttrs = fontAttrs({ - editType: 'plot', - arrayOk: true, - colorEditType: 'plot', - -}); - -module.exports = { - labels: { - valType: 'data_array', - editType: 'calc', - - }, - // equivalent of x0 and dx, if label is missing - label0: { - valType: 'number', - - dflt: 0, - editType: 'calc', - - }, - dlabel: { - valType: 'number', - - dflt: 1, - editType: 'calc', - - }, - - values: { - valType: 'data_array', - editType: 'calc', - - }, - - marker: { - colors: { - valType: 'data_array', // TODO 'color_array' ? - editType: 'calc', - - }, - - line: { - color: { - valType: 'color', - - dflt: colorAttrs.defaultLine, - arrayOk: true, - editType: 'style', - - }, - width: { - valType: 'number', - - min: 0, - dflt: 0, - arrayOk: true, - editType: 'style', - - }, - editType: 'calc' - }, - editType: 'calc' - }, - - text: { - valType: 'data_array', - editType: 'calc', - - }, - hovertext: { - valType: 'string', - - dflt: '', - arrayOk: true, - editType: 'style', - - }, - -// 'see eg:' -// 'https://www.e-education.psu.edu/natureofgeoinfo/sites/www.e-education.psu.edu.natureofgeoinfo/files/image/hisp_pies.gif', -// '(this example involves a map too - may someday be a whole trace type', -// 'of its own. but the point is the size of the whole pie is important.)' - scalegroup: { - valType: 'string', - - dflt: '', - editType: 'calc', - - }, - - // labels (legend is handled by plots.attributes.showlegend and layout.hiddenlabels) - textinfo: { - valType: 'flaglist', - - flags: ['label', 'text', 'value', 'percent'], - extras: ['none'], - editType: 'calc', - - }, - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['label', 'text', 'value', 'percent', 'name'] - }), - hovertemplate: hovertemplateAttrs({}, { - keys: ['label', 'color', 'value', 'percent', 'text'] - }), - textposition: { - valType: 'enumerated', - - values: ['inside', 'outside', 'auto', 'none'], - dflt: 'auto', - arrayOk: true, - editType: 'plot', - - }, - textfont: extendFlat({}, textFontAttrs, { - - }), - insidetextfont: extendFlat({}, textFontAttrs, { - - }), - outsidetextfont: extendFlat({}, textFontAttrs, { - - }), - - title: { - text: { - valType: 'string', - dflt: '', - - editType: 'plot', - - }, - font: extendFlat({}, textFontAttrs, { - - }), - position: { - valType: 'enumerated', - values: [ - 'top left', 'top center', 'top right', - 'middle center', - 'bottom left', 'bottom center', 'bottom right' - ], - - editType: 'plot', - - }, - - editType: 'plot' - }, - - // position and shape - domain: domainAttrs({name: 'pie', trace: true, editType: 'calc'}), - - hole: { - valType: 'number', - - min: 0, - max: 1, - dflt: 0, - editType: 'calc', - - }, - - // ordering and direction - sort: { - valType: 'boolean', - - dflt: true, - editType: 'calc', - - }, - direction: { - /** - * there are two common conventions, both of which place the first - * (largest, if sorted) slice with its left edge at 12 o'clock but - * succeeding slices follow either cw or ccw from there. - * - * see http://visage.co/data-visualization-101-pie-charts/ - */ - valType: 'enumerated', - values: ['clockwise', 'counterclockwise'], - - dflt: 'counterclockwise', - editType: 'calc', - - }, - rotation: { - valType: 'number', - - min: -360, - max: 360, - dflt: 0, - editType: 'calc', - - }, - - pull: { - valType: 'number', - - min: 0, - max: 1, - dflt: 0, - arrayOk: true, - editType: 'calc', - - }, - - _deprecated: { - title: { - valType: 'string', - dflt: '', - - editType: 'calc', - - }, - titlefont: extendFlat({}, textFontAttrs, { - - }), - titleposition: { - valType: 'enumerated', - values: [ - 'top left', 'top center', 'top right', - 'middle center', - 'bottom left', 'bottom center', 'bottom right' - ], - - editType: 'calc', - - } - } -}; - -},{"../../components/color/attributes":592,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../../plots/domain":792,"../../plots/font_attributes":793}],1087:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; - -exports.name = 'pie'; - -exports.plot = function(gd) { - var Pie = Registry.getModule('pie'); - var cdPie = getModuleCalcData(gd.calcdata, Pie)[0]; - Pie.plot(gd, cdPie); -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var hadPie = (oldFullLayout._has && oldFullLayout._has('pie')); - var hasPie = (newFullLayout._has && newFullLayout._has('pie')); - - if(hadPie && !hasPie) { - oldFullLayout._pielayer.selectAll('g.trace').remove(); - } -}; - -},{"../../plots/get_data":802,"../../registry":847}],1088:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; -var tinycolor = _dereq_('tinycolor2'); - -var Color = _dereq_('../../components/color'); -var helpers = _dereq_('./helpers'); -var isValidTextValue = _dereq_('../../lib').isValidTextValue; - -var extendedColorWayList = {}; - -function calc(gd, trace) { - var cd = []; - - var fullLayout = gd._fullLayout; - var hiddenLabels = fullLayout.hiddenlabels || []; - - var labels = trace.labels; - var colors = trace.marker.colors || []; - var vals = trace.values; - var hasVals = isArrayOrTypedArray(vals) && vals.length; - - var i, pt; - - if(trace.dlabel) { - labels = new Array(vals.length); - for(i = 0; i < vals.length; i++) { - labels[i] = String(trace.label0 + i * trace.dlabel); - } - } - - var allThisTraceLabels = {}; - var pullColor = makePullColorFn(fullLayout['_' + trace.type + 'colormap']); - var seriesLen = (hasVals ? vals : labels).length; - var vTotal = 0; - var isAggregated = false; - - for(i = 0; i < seriesLen; i++) { - var v, label, hidden; - if(hasVals) { - v = vals[i]; - if(!isNumeric(v)) continue; - v = +v; - if(v < 0) continue; - } else v = 1; - - label = labels[i]; - if(label === undefined || label === '') label = i; - label = String(label); - - var thisLabelIndex = allThisTraceLabels[label]; - if(thisLabelIndex === undefined) { - allThisTraceLabels[label] = cd.length; - - hidden = hiddenLabels.indexOf(label) !== -1; - - if(!hidden) vTotal += v; - - cd.push({ - v: v, - label: label, - color: pullColor(colors[i], label), - i: i, - pts: [i], - hidden: hidden - }); - } else { - isAggregated = true; - - pt = cd[thisLabelIndex]; - pt.v += v; - pt.pts.push(i); - if(!pt.hidden) vTotal += v; - - if(pt.color === false && colors[i]) { - pt.color = pullColor(colors[i], label); - } - } - } - - var shouldSort = (trace.type === 'funnelarea') ? isAggregated : trace.sort; - if(shouldSort) cd.sort(function(a, b) { return b.v - a.v; }); - - // include the sum of all values in the first point - if(cd[0]) cd[0].vTotal = vTotal; - - // now insert text - var textinfo = trace.textinfo; - if(textinfo && textinfo !== 'none') { - var parts = textinfo.split('+'); - var hasFlag = function(flag) { return parts.indexOf(flag) !== -1; }; - var hasLabel = hasFlag('label'); - var hasText = hasFlag('text'); - var hasValue = hasFlag('value'); - var hasPercent = hasFlag('percent'); - - var separators = fullLayout.separators; - var text; - - for(i = 0; i < cd.length; i++) { - pt = cd[i]; - text = hasLabel ? [pt.label] : []; - if(hasText) { - var tx = helpers.getFirstFilled(trace.text, pt.pts); - if(isValidTextValue(tx)) text.push(tx); - } - if(hasValue) text.push(helpers.formatPieValue(pt.v, separators)); - if(hasPercent) text.push(helpers.formatPiePercent(pt.v / vTotal, separators)); - pt.text = text.join('
'); - } - } - - return cd; -} - -function makePullColorFn(colorMap) { - return function pullColor(color, id) { - if(!color) return false; - - color = tinycolor(color); - if(!color.isValid()) return false; - - color = Color.addOpacity(color, color.getAlpha()); - if(!colorMap[id]) colorMap[id] = color; - - return color; - }; -} - -/* - * `calc` filled in (and collated) explicit colors. - * Now we need to propagate these explicit colors to other traces, - * and fill in default colors. - * This is done after sorting, so we pick defaults - * in the order slices will be displayed - */ -function crossTraceCalc(gd, plotinfo) { // TODO: should we name the second argument opts? - var desiredType = (plotinfo || {}).type; - if(!desiredType) desiredType = 'pie'; - - var fullLayout = gd._fullLayout; - var calcdata = gd.calcdata; - var colorWay = fullLayout[desiredType + 'colorway']; - var colorMap = fullLayout['_' + desiredType + 'colormap']; - - if(fullLayout['extend' + desiredType + 'colors']) { - colorWay = generateExtendedColors(colorWay, extendedColorWayList); - } - var dfltColorCount = 0; - - for(var i = 0; i < calcdata.length; i++) { - var cd = calcdata[i]; - var traceType = cd[0].trace.type; - if(traceType !== desiredType) continue; - - for(var j = 0; j < cd.length; j++) { - var pt = cd[j]; - if(pt.color === false) { - // have we seen this label and assigned a color to it in a previous trace? - if(colorMap[pt.label]) { - pt.color = colorMap[pt.label]; - } else { - colorMap[pt.label] = pt.color = colorWay[dfltColorCount % colorWay.length]; - dfltColorCount++; - } - } - } - } -} - -/** - * pick a default color from the main default set, augmented by - * itself lighter then darker before repeating - */ -function generateExtendedColors(colorList, extendedColorWays) { - var i; - var colorString = JSON.stringify(colorList); - var colors = extendedColorWays[colorString]; - if(!colors) { - colors = colorList.slice(); - - for(i = 0; i < colorList.length; i++) { - colors.push(tinycolor(colorList[i]).lighten(20).toHexString()); - } - - for(i = 0; i < colorList.length; i++) { - colors.push(tinycolor(colorList[i]).darken(20).toHexString()); - } - extendedColorWays[colorString] = colors; - } - - return colors; -} - -module.exports = { - calc: calc, - crossTraceCalc: crossTraceCalc, - - makePullColorFn: makePullColorFn, - generateExtendedColors: generateExtendedColors -}; - -},{"../../components/color":593,"../../lib":719,"./helpers":1091,"fast-isnumeric":225,"tinycolor2":537}],1089:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attributes = _dereq_('./attributes'); -var handleDomainDefaults = _dereq_('../../plots/domain').defaults; -var handleText = _dereq_('../bar/defaults').handleText; - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len; - var vals = coerce('values'); - var hasVals = Lib.isArrayOrTypedArray(vals); - var labels = coerce('labels'); - if(Array.isArray(labels)) { - len = labels.length; - if(hasVals) len = Math.min(len, vals.length); - } else if(hasVals) { - len = vals.length; - - coerce('label0'); - coerce('dlabel'); - } - - if(!len) { - traceOut.visible = false; - return; - } - traceOut._length = len; - - var lineWidth = coerce('marker.line.width'); - if(lineWidth) coerce('marker.line.color'); - - coerce('marker.colors'); - - coerce('scalegroup'); - // TODO: hole needs to be coerced to the same value within a scaleegroup - - var textData = coerce('text'); - var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent'); - coerce('hovertext'); - coerce('hovertemplate'); - - if(textInfo && textInfo !== 'none') { - var textposition = coerce('textposition'); - handleText(traceIn, traceOut, layout, coerce, textposition, { - moduleHasSelected: false, - moduleHasUnselected: false, - moduleHasConstrain: false, - moduleHasCliponaxis: false, - moduleHasTextangle: false, - moduleHasInsideanchor: false - }); - } - - handleDomainDefaults(traceOut, layout, coerce); - - var hole = coerce('hole'); - var title = coerce('title.text'); - if(title) { - var titlePosition = coerce('title.position', hole ? 'middle center' : 'top center'); - if(!hole && titlePosition === 'middle center') traceOut.title.position = 'top center'; - Lib.coerceFont(coerce, 'title.font', layout.font); - } - - coerce('sort'); - coerce('direction'); - coerce('rotation'); - coerce('pull'); -}; - -},{"../../lib":719,"../../plots/domain":792,"../bar/defaults":861,"./attributes":1086}],1090:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var appendArrayMultiPointValues = _dereq_('../../components/fx/helpers').appendArrayMultiPointValues; - -// Note: like other eventData routines, this creates the data for hover/unhover/click events -// but it has a different API and goes through a totally different pathway. -// So to ensure it doesn't get misused, it's not attached to the Pie module. -module.exports = function eventData(pt, trace) { - var out = { - curveNumber: trace.index, - pointNumbers: pt.pts, - data: trace._input, - fullData: trace, - label: pt.label, - color: pt.color, - value: pt.v, - percent: pt.percent, - text: pt.text, - - // pt.v (and pt.i below) for backward compatibility - v: pt.v - }; - - // Only include pointNumber if it's unambiguous - if(pt.pts.length === 1) out.pointNumber = out.i = pt.pts[0]; - - // Add extra data arrays to the output - // notice that this is the multi-point version ('s' on the end!) - // so added data will be arrays matching the pointNumbers array. - appendArrayMultiPointValues(out, trace, pt.pts); - - // don't include obsolete fields in new funnelarea traces - if(trace.type === 'funnelarea') { - delete out.v; - delete out.i; - } - - return out; -}; - -},{"../../components/fx/helpers":628}],1091:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -exports.formatPiePercent = function formatPiePercent(v, separators) { - var vRounded = (v * 100).toPrecision(3); - if(vRounded.lastIndexOf('.') !== -1) { - vRounded = vRounded.replace(/[.]?0+$/, ''); - } - return Lib.numSeparate(vRounded, separators) + '%'; -}; - -exports.formatPieValue = function formatPieValue(v, separators) { - var vRounded = v.toPrecision(10); - if(vRounded.lastIndexOf('.') !== -1) { - vRounded = vRounded.replace(/[.]?0+$/, ''); - } - return Lib.numSeparate(vRounded, separators); -}; - -exports.getFirstFilled = function getFirstFilled(array, indices) { - if(!Array.isArray(array)) return; - for(var i = 0; i < indices.length; i++) { - var v = array[indices[i]]; - if(v || v === 0) return v; - } -}; - -exports.castOption = function castOption(item, indices) { - if(Array.isArray(item)) return exports.getFirstFilled(item, indices); - else if(item) return item; -}; - -},{"../../lib":719}],1092:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - supplyLayoutDefaults: _dereq_('./layout_defaults'), - layoutAttributes: _dereq_('./layout_attributes'), - - calc: _dereq_('./calc').calc, - crossTraceCalc: _dereq_('./calc').crossTraceCalc, - - plot: _dereq_('./plot').plot, - style: _dereq_('./style'), - styleOne: _dereq_('./style_one'), - - moduleType: 'trace', - name: 'pie', - basePlotModule: _dereq_('./base_plot'), - categories: ['pie-like', 'pie', 'showLegend'], - meta: { - - } -}; - -},{"./attributes":1086,"./base_plot":1087,"./calc":1088,"./defaults":1089,"./layout_attributes":1093,"./layout_defaults":1094,"./plot":1095,"./style":1096,"./style_one":1097}],1093:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - hiddenlabels: { - valType: 'data_array', - - editType: 'calc', - - }, - piecolorway: { - valType: 'colorlist', - - editType: 'calc', - - }, - extendpiecolors: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - } -}; - -},{}],1094:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var layoutAttributes = _dereq_('./layout_attributes'); - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - - coerce('hiddenlabels'); - coerce('piecolorway', layoutOut.colorway); - coerce('extendpiecolors'); -}; - -},{"../../lib":719,"./layout_attributes":1093}],1095:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Fx = _dereq_('../../components/fx'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var Lib = _dereq_('../../lib'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); - -var helpers = _dereq_('./helpers'); -var eventData = _dereq_('./event_data'); - -function plot(gd, cdModule) { - var fullLayout = gd._fullLayout; - - prerenderTitles(cdModule, gd); - layoutAreas(cdModule, fullLayout._size); - - var plotGroups = Lib.makeTraceGroups(fullLayout._pielayer, cdModule, 'trace').each(function(cd) { - var plotGroup = d3.select(this); - var cd0 = cd[0]; - var trace = cd0.trace; - - setCoords(cd); - - // TODO: miter might look better but can sometimes cause problems - // maybe miter with a small-ish stroke-miterlimit? - plotGroup.attr('stroke-linejoin', 'round'); - - plotGroup.each(function() { - var slices = d3.select(this).selectAll('g.slice').data(cd); - - slices.enter().append('g') - .classed('slice', true); - slices.exit().remove(); - - var quadrants = [ - [[], []], // y<0: x<0, x>=0 - [[], []] // y>=0: x<0, x>=0 - ]; - var hasOutsideText = false; - - slices.each(function(pt) { - if(pt.hidden) { - d3.select(this).selectAll('path,g').remove(); - return; - } - - // to have consistent event data compared to other traces - pt.pointNumber = pt.i; - pt.curveNumber = trace.index; - - quadrants[pt.pxmid[1] < 0 ? 0 : 1][pt.pxmid[0] < 0 ? 0 : 1].push(pt); - - var cx = cd0.cx; - var cy = cd0.cy; - var sliceTop = d3.select(this); - var slicePath = sliceTop.selectAll('path.surface').data([pt]); - - slicePath.enter().append('path') - .classed('surface', true) - .style({'pointer-events': 'all'}); - - sliceTop.call(attachFxHandlers, gd, cd); - - if(trace.pull) { - var pull = +helpers.castOption(trace.pull, pt.pts) || 0; - if(pull > 0) { - cx += pull * pt.pxmid[0]; - cy += pull * pt.pxmid[1]; - } - } - - pt.cxFinal = cx; - pt.cyFinal = cy; - - function arc(start, finish, cw, scale) { - var dx = scale * (finish[0] - start[0]); - var dy = scale * (finish[1] - start[1]); - - return 'a' + - (scale * cd0.r) + ',' + (scale * cd0.r) + ' 0 ' + - pt.largeArc + (cw ? ' 1 ' : ' 0 ') + dx + ',' + dy; - } - - var hole = trace.hole; - if(pt.v === cd0.vTotal) { // 100% fails bcs arc start and end are identical - var outerCircle = 'M' + (cx + pt.px0[0]) + ',' + (cy + pt.px0[1]) + - arc(pt.px0, pt.pxmid, true, 1) + - arc(pt.pxmid, pt.px0, true, 1) + 'Z'; - if(hole) { - slicePath.attr('d', - 'M' + (cx + hole * pt.px0[0]) + ',' + (cy + hole * pt.px0[1]) + - arc(pt.px0, pt.pxmid, false, hole) + - arc(pt.pxmid, pt.px0, false, hole) + - 'Z' + outerCircle); - } else slicePath.attr('d', outerCircle); - } else { - var outerArc = arc(pt.px0, pt.px1, true, 1); - - if(hole) { - var rim = 1 - hole; - slicePath.attr('d', - 'M' + (cx + hole * pt.px1[0]) + ',' + (cy + hole * pt.px1[1]) + - arc(pt.px1, pt.px0, false, hole) + - 'l' + (rim * pt.px0[0]) + ',' + (rim * pt.px0[1]) + - outerArc + - 'Z'); - } else { - slicePath.attr('d', - 'M' + cx + ',' + cy + - 'l' + pt.px0[0] + ',' + pt.px0[1] + - outerArc + - 'Z'); - } - } - - // add text - var textPosition = helpers.castOption(trace.textposition, pt.pts); - var sliceTextGroup = sliceTop.selectAll('g.slicetext') - .data(pt.text && (textPosition !== 'none') ? [0] : []); - - sliceTextGroup.enter().append('g') - .classed('slicetext', true); - sliceTextGroup.exit().remove(); - - sliceTextGroup.each(function() { - var sliceText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) { - // prohibit tex interpretation until we can handle - // tex and regular text together - s.attr('data-notex', 1); - }); - - sliceText.text(pt.text) - .attr({ - 'class': 'slicetext', - transform: '', - 'text-anchor': 'middle' - }) - .call(Drawing.font, textPosition === 'outside' ? - determineOutsideTextFont(trace, pt, gd._fullLayout.font) : - determineInsideTextFont(trace, pt, gd._fullLayout.font)) - .call(svgTextUtils.convertToTspans, gd); - - // position the text relative to the slice - var textBB = Drawing.bBox(sliceText.node()); - var transform; - - if(textPosition === 'outside') { - transform = transformOutsideText(textBB, pt); - } else { - transform = transformInsideText(textBB, pt, cd0); - if(textPosition === 'auto' && transform.scale < 1) { - sliceText.call(Drawing.font, trace.outsidetextfont); - if(trace.outsidetextfont.family !== trace.insidetextfont.family || - trace.outsidetextfont.size !== trace.insidetextfont.size) { - textBB = Drawing.bBox(sliceText.node()); - } - transform = transformOutsideText(textBB, pt); - } - } - - var translateX = cx + pt.pxmid[0] * transform.rCenter + (transform.x || 0); - var translateY = cy + pt.pxmid[1] * transform.rCenter + (transform.y || 0); - - // save some stuff to use later ensure no labels overlap - if(transform.outside) { - pt.yLabelMin = translateY - textBB.height / 2; - pt.yLabelMid = translateY; - pt.yLabelMax = translateY + textBB.height / 2; - pt.labelExtraX = 0; - pt.labelExtraY = 0; - hasOutsideText = true; - } - - sliceText.attr('transform', - 'translate(' + translateX + ',' + translateY + ')' + - (transform.scale < 1 ? ('scale(' + transform.scale + ')') : '') + - (transform.rotate ? ('rotate(' + transform.rotate + ')') : '') + - 'translate(' + - (-(textBB.left + textBB.right) / 2) + ',' + - (-(textBB.top + textBB.bottom) / 2) + - ')'); - }); - }); - - // add the title - var titleTextGroup = d3.select(this).selectAll('g.titletext') - .data(trace.title.text ? [0] : []); - - titleTextGroup.enter().append('g') - .classed('titletext', true); - titleTextGroup.exit().remove(); - - titleTextGroup.each(function() { - var titleText = Lib.ensureSingle(d3.select(this), 'text', '', function(s) { - // prohibit tex interpretation as above - s.attr('data-notex', 1); - }); - - var txt = trace.title.text; - if(trace._meta) { - txt = Lib.templateString(txt, trace._meta); - } - - titleText.text(txt) - .attr({ - 'class': 'titletext', - transform: '', - 'text-anchor': 'middle', - }) - .call(Drawing.font, trace.title.font) - .call(svgTextUtils.convertToTspans, gd); - - var transform; - - if(trace.title.position === 'middle center') { - transform = positionTitleInside(cd0); - } else { - transform = positionTitleOutside(cd0, fullLayout._size); - } - - titleText.attr('transform', - 'translate(' + transform.x + ',' + transform.y + ')' + - (transform.scale < 1 ? ('scale(' + transform.scale + ')') : '') + - 'translate(' + transform.tx + ',' + transform.ty + ')'); - }); - - // now make sure no labels overlap (at least within one pie) - if(hasOutsideText) scootLabels(quadrants, trace); - - plotTextLines(slices, trace); - }); - }); - - // This is for a bug in Chrome (as of 2015-07-22, and does not affect FF) - // if insidetextfont and outsidetextfont are different sizes, sometimes the size - // of an "em" gets taken from the wrong element at first so lines are - // spaced wrong. You just have to tell it to try again later and it gets fixed. - // I have no idea why we haven't seen this in other contexts. Also, sometimes - // it gets the initial draw correct but on redraw it gets confused. - setTimeout(function() { - plotGroups.selectAll('tspan').each(function() { - var s = d3.select(this); - if(s.attr('dy')) s.attr('dy', s.attr('dy')); - }); - }, 0); -} - -// TODO add support for transition -function plotTextLines(slices, trace) { - slices.each(function(pt) { - var sliceTop = d3.select(this); - - if(!pt.labelExtraX && !pt.labelExtraY) { - sliceTop.select('path.textline').remove(); - return; - } - - // first move the text to its new location - var sliceText = sliceTop.select('g.slicetext text'); - - sliceText.attr('transform', 'translate(' + pt.labelExtraX + ',' + pt.labelExtraY + ')' + - sliceText.attr('transform')); - - // then add a line to the new location - var lineStartX = pt.cxFinal + pt.pxmid[0]; - var lineStartY = pt.cyFinal + pt.pxmid[1]; - var textLinePath = 'M' + lineStartX + ',' + lineStartY; - var finalX = (pt.yLabelMax - pt.yLabelMin) * (pt.pxmid[0] < 0 ? -1 : 1) / 4; - - if(pt.labelExtraX) { - var yFromX = pt.labelExtraX * pt.pxmid[1] / pt.pxmid[0]; - var yNet = pt.yLabelMid + pt.labelExtraY - (pt.cyFinal + pt.pxmid[1]); - - if(Math.abs(yFromX) > Math.abs(yNet)) { - textLinePath += - 'l' + (yNet * pt.pxmid[0] / pt.pxmid[1]) + ',' + yNet + - 'H' + (lineStartX + pt.labelExtraX + finalX); - } else { - textLinePath += 'l' + pt.labelExtraX + ',' + yFromX + - 'v' + (yNet - yFromX) + - 'h' + finalX; - } - } else { - textLinePath += - 'V' + (pt.yLabelMid + pt.labelExtraY) + - 'h' + finalX; - } - - Lib.ensureSingle(sliceTop, 'path', 'textline') - .call(Color.stroke, trace.outsidetextfont.color) - .attr({ - 'stroke-width': Math.min(2, trace.outsidetextfont.size / 8), - d: textLinePath, - fill: 'none' - }); - }); -} - -function attachFxHandlers(sliceTop, gd, cd) { - var cd0 = cd[0]; - var trace = cd0.trace; - var cx = cd0.cx; - var cy = cd0.cy; - - // hover state vars - // have we drawn a hover label, so it should be cleared later - if(!('_hasHoverLabel' in trace)) trace._hasHoverLabel = false; - // have we emitted a hover event, so later an unhover event should be emitted - // note that click events do not depend on this - you can still get them - // with hovermode: false or if you were earlier dragging, then clicked - // in the same slice that you moused up in - if(!('_hasHoverEvent' in trace)) trace._hasHoverEvent = false; - - sliceTop.on('mouseover', function(pt) { - // in case fullLayout or fullData has changed without a replot - var fullLayout2 = gd._fullLayout; - var trace2 = gd._fullData[trace.index]; - - if(gd._dragging || fullLayout2.hovermode === false) return; - - var hoverinfo = trace2.hoverinfo; - if(Array.isArray(hoverinfo)) { - // super hacky: we need to pull out the *first* hoverinfo from - // pt.pts, then put it back into an array in a dummy trace - // and call castHoverinfo on that. - // TODO: do we want to have Fx.castHoverinfo somehow handle this? - // it already takes an array for index, for 2D, so this seems tricky. - hoverinfo = Fx.castHoverinfo({ - hoverinfo: [helpers.castOption(hoverinfo, pt.pts)], - _module: trace._module - }, fullLayout2, 0); - } - - if(hoverinfo === 'all') hoverinfo = 'label+text+value+percent+name'; - - // in case we dragged over the pie from another subplot, - // or if hover is turned off - if(trace2.hovertemplate || (hoverinfo !== 'none' && hoverinfo !== 'skip' && hoverinfo)) { - var rInscribed = pt.rInscribed || 0; - var hoverCenterX = cx + pt.pxmid[0] * (1 - rInscribed); - var hoverCenterY = cy + pt.pxmid[1] * (1 - rInscribed); - var separators = fullLayout2.separators; - var text = []; - - if(hoverinfo && hoverinfo.indexOf('label') !== -1) text.push(pt.label); - pt.text = helpers.castOption(trace2.hovertext || trace2.text, pt.pts); - if(hoverinfo && hoverinfo.indexOf('text') !== -1) { - var tx = pt.text; - if(Lib.isValidTextValue(tx)) text.push(tx); - } - pt.value = pt.v; - pt.valueLabel = helpers.formatPieValue(pt.v, separators); - if(hoverinfo && hoverinfo.indexOf('value') !== -1) text.push(pt.valueLabel); - pt.percent = pt.v / cd0.vTotal; - pt.percentLabel = helpers.formatPiePercent(pt.percent, separators); - if(hoverinfo && hoverinfo.indexOf('percent') !== -1) text.push(pt.percentLabel); - - var hoverLabel = trace2.hoverlabel; - var hoverFont = hoverLabel.font; - - Fx.loneHover({ - trace: trace, - x0: hoverCenterX - rInscribed * cd0.r, - x1: hoverCenterX + rInscribed * cd0.r, - y: hoverCenterY, - text: text.join('
'), - name: (trace2.hovertemplate || hoverinfo.indexOf('name') !== -1) ? trace2.name : undefined, - idealAlign: pt.pxmid[0] < 0 ? 'left' : 'right', - color: helpers.castOption(hoverLabel.bgcolor, pt.pts) || pt.color, - borderColor: helpers.castOption(hoverLabel.bordercolor, pt.pts), - fontFamily: helpers.castOption(hoverFont.family, pt.pts), - fontSize: helpers.castOption(hoverFont.size, pt.pts), - fontColor: helpers.castOption(hoverFont.color, pt.pts), - nameLength: helpers.castOption(hoverLabel.namelength, pt.pts), - textAlign: helpers.castOption(hoverLabel.align, pt.pts), - hovertemplate: helpers.castOption(trace2.hovertemplate, pt.pts), - hovertemplateLabels: pt, - eventData: [eventData(pt, trace2)] - }, { - container: fullLayout2._hoverlayer.node(), - outerContainer: fullLayout2._paper.node(), - gd: gd - }); - - trace._hasHoverLabel = true; - } - - trace._hasHoverEvent = true; - gd.emit('plotly_hover', { - points: [eventData(pt, trace2)], - event: d3.event - }); - }); - - sliceTop.on('mouseout', function(evt) { - var fullLayout2 = gd._fullLayout; - var trace2 = gd._fullData[trace.index]; - var pt = d3.select(this).datum(); - - if(trace._hasHoverEvent) { - evt.originalEvent = d3.event; - gd.emit('plotly_unhover', { - points: [eventData(pt, trace2)], - event: d3.event - }); - trace._hasHoverEvent = false; - } - - if(trace._hasHoverLabel) { - Fx.loneUnhover(fullLayout2._hoverlayer.node()); - trace._hasHoverLabel = false; - } - }); - - sliceTop.on('click', function(pt) { - // TODO: this does not support right-click. If we want to support it, we - // would likely need to change pie to use dragElement instead of straight - // mapbox event binding. Or perhaps better, make a simple wrapper with the - // right mousedown, mousemove, and mouseup handlers just for a left/right click - // mapbox would use this too. - var fullLayout2 = gd._fullLayout; - var trace2 = gd._fullData[trace.index]; - - if(gd._dragging || fullLayout2.hovermode === false) return; - - gd._hoverdata = [eventData(pt, trace2)]; - Fx.click(gd, d3.event); - }); -} - -function determineOutsideTextFont(trace, pt, layoutFont) { - var color = - helpers.castOption(trace.outsidetextfont.color, pt.pts) || - helpers.castOption(trace.textfont.color, pt.pts) || - layoutFont.color; - - var family = - helpers.castOption(trace.outsidetextfont.family, pt.pts) || - helpers.castOption(trace.textfont.family, pt.pts) || - layoutFont.family; - - var size = - helpers.castOption(trace.outsidetextfont.size, pt.pts) || - helpers.castOption(trace.textfont.size, pt.pts) || - layoutFont.size; - - return { - color: color, - family: family, - size: size - }; -} - -function determineInsideTextFont(trace, pt, layoutFont) { - var customColor = helpers.castOption(trace.insidetextfont.color, pt.pts); - if(!customColor && trace._input.textfont) { - // Why not simply using trace.textfont? Because if not set, it - // defaults to layout.font which has a default color. But if - // textfont.color and insidetextfont.color don't supply a value, - // a contrasting color shall be used. - customColor = helpers.castOption(trace._input.textfont.color, pt.pts); - } - - var family = - helpers.castOption(trace.insidetextfont.family, pt.pts) || - helpers.castOption(trace.textfont.family, pt.pts) || - layoutFont.family; - - var size = - helpers.castOption(trace.insidetextfont.size, pt.pts) || - helpers.castOption(trace.textfont.size, pt.pts) || - layoutFont.size; - - return { - color: customColor || Color.contrast(pt.color), - family: family, - size: size - }; -} - -function prerenderTitles(cdModule, gd) { - var cd0, trace; - - // Determine the width and height of the title for each pie. - for(var i = 0; i < cdModule.length; i++) { - cd0 = cdModule[i][0]; - trace = cd0.trace; - - if(trace.title.text) { - var txt = trace.title.text; - if(trace._meta) { - txt = Lib.templateString(txt, trace._meta); - } - - var dummyTitle = Drawing.tester.append('text') - .attr('data-notex', 1) - .text(txt) - .call(Drawing.font, trace.title.font) - .call(svgTextUtils.convertToTspans, gd); - var bBox = Drawing.bBox(dummyTitle.node(), true); - cd0.titleBox = { - width: bBox.width, - height: bBox.height, - }; - dummyTitle.remove(); - } - } -} - -function transformInsideText(textBB, pt, cd0) { - var textDiameter = Math.sqrt(textBB.width * textBB.width + textBB.height * textBB.height); - var textAspect = textBB.width / textBB.height; - var halfAngle = pt.halfangle; - var ring = pt.ring; - var rInscribed = pt.rInscribed; - var r = cd0.r || pt.rpx1; - - // max size text can be inserted inside without rotating it - // this inscribes the text rectangle in a circle, which is then inscribed - // in the slice, so it will be an underestimate, which some day we may want - // to improve so this case can get more use - var transform = { - scale: rInscribed * r * 2 / textDiameter, - - // and the center position and rotation in this case - rCenter: 1 - rInscribed, - rotate: 0 - }; - - if(transform.scale >= 1) return transform; - - // max size if text is rotated radially - var Qr = textAspect + 1 / (2 * Math.tan(halfAngle)); - var maxHalfHeightRotRadial = r * Math.min( - 1 / (Math.sqrt(Qr * Qr + 0.5) + Qr), - ring / (Math.sqrt(textAspect * textAspect + ring / 2) + textAspect) - ); - var radialTransform = { - scale: maxHalfHeightRotRadial * 2 / textBB.height, - rCenter: Math.cos(maxHalfHeightRotRadial / r) - - maxHalfHeightRotRadial * textAspect / r, - rotate: (180 / Math.PI * pt.midangle + 720) % 180 - 90 - }; - - // max size if text is rotated tangentially - var aspectInv = 1 / textAspect; - var Qt = aspectInv + 1 / (2 * Math.tan(halfAngle)); - var maxHalfWidthTangential = r * Math.min( - 1 / (Math.sqrt(Qt * Qt + 0.5) + Qt), - ring / (Math.sqrt(aspectInv * aspectInv + ring / 2) + aspectInv) - ); - var tangentialTransform = { - scale: maxHalfWidthTangential * 2 / textBB.width, - rCenter: Math.cos(maxHalfWidthTangential / r) - - maxHalfWidthTangential / textAspect / r, - rotate: (180 / Math.PI * pt.midangle + 810) % 180 - 90 - }; - // if we need a rotated transform, pick the biggest one - // even if both are bigger than 1 - var rotatedTransform = tangentialTransform.scale > radialTransform.scale ? - tangentialTransform : radialTransform; - - if(transform.scale < 1 && rotatedTransform.scale > transform.scale) return rotatedTransform; - return transform; -} - -function getInscribedRadiusFraction(pt, cd0) { - if(pt.v === cd0.vTotal && !cd0.trace.hole) return 1;// special case of 100% with no hole - - return Math.min(1 / (1 + 1 / Math.sin(pt.halfangle)), pt.ring / 2); -} - -function transformOutsideText(textBB, pt) { - var x = pt.pxmid[0]; - var y = pt.pxmid[1]; - var dx = textBB.width / 2; - var dy = textBB.height / 2; - - if(x < 0) dx *= -1; - if(y < 0) dy *= -1; - - return { - scale: 1, - rCenter: 1, - rotate: 0, - x: dx + Math.abs(dy) * (dx > 0 ? 1 : -1) / 2, - y: dy / (1 + x * x / (y * y)), - outside: true - }; -} - -function positionTitleInside(cd0) { - var textDiameter = - Math.sqrt(cd0.titleBox.width * cd0.titleBox.width + cd0.titleBox.height * cd0.titleBox.height); - return { - x: cd0.cx, - y: cd0.cy, - scale: cd0.trace.hole * cd0.r * 2 / textDiameter, - tx: 0, - ty: - cd0.titleBox.height / 2 + cd0.trace.title.font.size - }; -} - -function positionTitleOutside(cd0, plotSize) { - var scaleX = 1; - var scaleY = 1; - var maxPull; - - var trace = cd0.trace; - // position of the baseline point of the text box in the plot, before scaling. - // we anchored the text in the middle, so the baseline is on the bottom middle - // of the first line of text. - var topMiddle = { - x: cd0.cx, - y: cd0.cy - }; - // relative translation of the text box after scaling - var translate = { - tx: 0, - ty: 0 - }; - - // we reason below as if the baseline is the top middle point of the text box. - // so we must add the font size to approximate the y-coord. of the top. - // note that this correction must happen after scaling. - translate.ty += trace.title.font.size; - maxPull = getMaxPull(trace); - - if(trace.title.position.indexOf('top') !== -1) { - topMiddle.y -= (1 + maxPull) * cd0.r; - translate.ty -= cd0.titleBox.height; - } else if(trace.title.position.indexOf('bottom') !== -1) { - topMiddle.y += (1 + maxPull) * cd0.r; - } - - var rx = applyAspectRatio(cd0.r, cd0.trace.aspectratio); - - var maxWidth = plotSize.w * (trace.domain.x[1] - trace.domain.x[0]) / 2; - if(trace.title.position.indexOf('left') !== -1) { - // we start the text at the left edge of the pie - maxWidth = maxWidth + rx; - topMiddle.x -= (1 + maxPull) * rx; - translate.tx += cd0.titleBox.width / 2; - } else if(trace.title.position.indexOf('center') !== -1) { - maxWidth *= 2; - } else if(trace.title.position.indexOf('right') !== -1) { - maxWidth = maxWidth + rx; - topMiddle.x += (1 + maxPull) * rx; - translate.tx -= cd0.titleBox.width / 2; - } - scaleX = maxWidth / cd0.titleBox.width; - scaleY = getTitleSpace(cd0, plotSize) / cd0.titleBox.height; - return { - x: topMiddle.x, - y: topMiddle.y, - scale: Math.min(scaleX, scaleY), - tx: translate.tx, - ty: translate.ty - }; -} - -function applyAspectRatio(x, aspectratio) { - return x / ((aspectratio === undefined) ? 1 : aspectratio); -} - -function getTitleSpace(cd0, plotSize) { - var trace = cd0.trace; - var pieBoxHeight = plotSize.h * (trace.domain.y[1] - trace.domain.y[0]); - // use at most half of the plot for the title - return Math.min(cd0.titleBox.height, pieBoxHeight / 2); -} - -function getMaxPull(trace) { - var maxPull = trace.pull; - if(!maxPull) return 0; - - var j; - if(Array.isArray(maxPull)) { - maxPull = 0; - for(j = 0; j < trace.pull.length; j++) { - if(trace.pull[j] > maxPull) maxPull = trace.pull[j]; - } - } - return maxPull; -} - -function scootLabels(quadrants, trace) { - var xHalf, yHalf, equatorFirst, farthestX, farthestY, - xDiffSign, yDiffSign, thisQuad, oppositeQuad, - wholeSide, i, thisQuadOutside, firstOppositeOutsidePt; - - function topFirst(a, b) { return a.pxmid[1] - b.pxmid[1]; } - function bottomFirst(a, b) { return b.pxmid[1] - a.pxmid[1]; } - - function scootOneLabel(thisPt, prevPt) { - if(!prevPt) prevPt = {}; - - var prevOuterY = prevPt.labelExtraY + (yHalf ? prevPt.yLabelMax : prevPt.yLabelMin); - var thisInnerY = yHalf ? thisPt.yLabelMin : thisPt.yLabelMax; - var thisOuterY = yHalf ? thisPt.yLabelMax : thisPt.yLabelMin; - var thisSliceOuterY = thisPt.cyFinal + farthestY(thisPt.px0[1], thisPt.px1[1]); - var newExtraY = prevOuterY - thisInnerY; - - var xBuffer, i, otherPt, otherOuterY, otherOuterX, newExtraX; - - // make sure this label doesn't overlap other labels - // this *only* has us move these labels vertically - if(newExtraY * yDiffSign > 0) thisPt.labelExtraY = newExtraY; - - // make sure this label doesn't overlap any slices - if(!Array.isArray(trace.pull)) return; // this can only happen with array pulls - - for(i = 0; i < wholeSide.length; i++) { - otherPt = wholeSide[i]; - - // overlap can only happen if the other point is pulled more than this one - if(otherPt === thisPt || ( - (helpers.castOption(trace.pull, thisPt.pts) || 0) >= - (helpers.castOption(trace.pull, otherPt.pts) || 0)) - ) { - continue; - } - - if((thisPt.pxmid[1] - otherPt.pxmid[1]) * yDiffSign > 0) { - // closer to the equator - by construction all of these happen first - // move the text vertically to get away from these slices - otherOuterY = otherPt.cyFinal + farthestY(otherPt.px0[1], otherPt.px1[1]); - newExtraY = otherOuterY - thisInnerY - thisPt.labelExtraY; - - if(newExtraY * yDiffSign > 0) thisPt.labelExtraY += newExtraY; - } else if((thisOuterY + thisPt.labelExtraY - thisSliceOuterY) * yDiffSign > 0) { - // farther from the equator - happens after we've done all the - // vertical moving we're going to do - // move horizontally to get away from these more polar slices - - // if we're moving horz. based on a slice that's several slices away from this one - // then we need some extra space for the lines to labels between them - xBuffer = 3 * xDiffSign * Math.abs(i - wholeSide.indexOf(thisPt)); - - otherOuterX = otherPt.cxFinal + farthestX(otherPt.px0[0], otherPt.px1[0]); - newExtraX = otherOuterX + xBuffer - (thisPt.cxFinal + thisPt.pxmid[0]) - thisPt.labelExtraX; - - if(newExtraX * xDiffSign > 0) thisPt.labelExtraX += newExtraX; - } - } - } - - for(yHalf = 0; yHalf < 2; yHalf++) { - equatorFirst = yHalf ? topFirst : bottomFirst; - farthestY = yHalf ? Math.max : Math.min; - yDiffSign = yHalf ? 1 : -1; - - for(xHalf = 0; xHalf < 2; xHalf++) { - farthestX = xHalf ? Math.max : Math.min; - xDiffSign = xHalf ? 1 : -1; - - // first sort the array - // note this is a copy of cd, so cd itself doesn't get sorted - // but we can still modify points in place. - thisQuad = quadrants[yHalf][xHalf]; - thisQuad.sort(equatorFirst); - - oppositeQuad = quadrants[1 - yHalf][xHalf]; - wholeSide = oppositeQuad.concat(thisQuad); - - thisQuadOutside = []; - for(i = 0; i < thisQuad.length; i++) { - if(thisQuad[i].yLabelMid !== undefined) thisQuadOutside.push(thisQuad[i]); - } - - firstOppositeOutsidePt = false; - for(i = 0; yHalf && i < oppositeQuad.length; i++) { - if(oppositeQuad[i].yLabelMid !== undefined) { - firstOppositeOutsidePt = oppositeQuad[i]; - break; - } - } - - // each needs to avoid the previous - for(i = 0; i < thisQuadOutside.length; i++) { - var prevPt = i && thisQuadOutside[i - 1]; - // bottom half needs to avoid the first label of the top half - // top half we still need to call scootOneLabel on the first slice - // so we can avoid other slices, but we don't pass a prevPt - if(firstOppositeOutsidePt && !i) prevPt = firstOppositeOutsidePt; - scootOneLabel(thisQuadOutside[i], prevPt); - } - } - } -} - -function layoutAreas(cdModule, plotSize) { - var scaleGroups = []; - - // figure out the center and maximum radius - for(var i = 0; i < cdModule.length; i++) { - var cd0 = cdModule[i][0]; - var trace = cd0.trace; - - var domain = trace.domain; - var width = plotSize.w * (domain.x[1] - domain.x[0]); - var height = plotSize.h * (domain.y[1] - domain.y[0]); - // leave some space for the title, if it will be displayed outside - if(trace.title.text && trace.title.position !== 'middle center') { - height -= getTitleSpace(cd0, plotSize); - } - - var rx = width / 2; - var ry = height / 2; - if(trace.type === 'funnelarea' && !trace.scalegroup) { - ry /= trace.aspectratio; - } - - cd0.r = Math.min(rx, ry) / (1 + getMaxPull(trace)); - - cd0.cx = plotSize.l + plotSize.w * (trace.domain.x[1] + trace.domain.x[0]) / 2; - cd0.cy = plotSize.t + plotSize.h * (1 - trace.domain.y[0]) - height / 2; - if(trace.title.text && trace.title.position.indexOf('bottom') !== -1) { - cd0.cy -= getTitleSpace(cd0, plotSize); - } - - if(trace.scalegroup && scaleGroups.indexOf(trace.scalegroup) === -1) { - scaleGroups.push(trace.scalegroup); - } - } - - groupScale(cdModule, scaleGroups); -} - -function groupScale(cdModule, scaleGroups) { - var cd0, i, trace; - - // scale those that are grouped - for(var k = 0; k < scaleGroups.length; k++) { - var min = Infinity; - var g = scaleGroups[k]; - - for(i = 0; i < cdModule.length; i++) { - cd0 = cdModule[i][0]; - trace = cd0.trace; - - if(trace.scalegroup === g) { - var area; - if(trace.type === 'pie') { - area = cd0.r * cd0.r; - } else if(trace.type === 'funnelarea') { - var rx, ry; - - if(trace.aspectratio > 1) { - rx = cd0.r; - ry = rx / trace.aspectratio; - } else { - ry = cd0.r; - rx = ry * trace.aspectratio; - } - - rx *= (1 + trace.baseratio) / 2; - - area = rx * ry; - } - - min = Math.min(min, area / cd0.vTotal); - } - } - - for(i = 0; i < cdModule.length; i++) { - cd0 = cdModule[i][0]; - trace = cd0.trace; - if(trace.scalegroup === g) { - var v = min * cd0.vTotal; - if(trace.type === 'funnelarea') { - v /= (1 + trace.baseratio) / 2; - v /= trace.aspectratio; - } - - cd0.r = Math.sqrt(v); - } - } - } -} - -function setCoords(cd) { - var cd0 = cd[0]; - var trace = cd0.trace; - var currentAngle = trace.rotation * Math.PI / 180; - var angleFactor = 2 * Math.PI / cd0.vTotal; - var firstPt = 'px0'; - var lastPt = 'px1'; - - var i, cdi, currentCoords; - - if(trace.direction === 'counterclockwise') { - for(i = 0; i < cd.length; i++) { - if(!cd[i].hidden) break; // find the first non-hidden slice - } - if(i === cd.length) return; // all slices hidden - - currentAngle += angleFactor * cd[i].v; - angleFactor *= -1; - firstPt = 'px1'; - lastPt = 'px0'; - } - - function getCoords(angle) { - return [cd0.r * Math.sin(angle), -cd0.r * Math.cos(angle)]; - } - - currentCoords = getCoords(currentAngle); - - for(i = 0; i < cd.length; i++) { - cdi = cd[i]; - if(cdi.hidden) continue; - - cdi[firstPt] = currentCoords; - - currentAngle += angleFactor * cdi.v / 2; - cdi.pxmid = getCoords(currentAngle); - cdi.midangle = currentAngle; - - currentAngle += angleFactor * cdi.v / 2; - currentCoords = getCoords(currentAngle); - - cdi[lastPt] = currentCoords; - - cdi.largeArc = (cdi.v > cd0.vTotal / 2) ? 1 : 0; - - cdi.halfangle = Math.PI * Math.min(cdi.v / cd0.vTotal, 0.5); - cdi.ring = 1 - trace.hole; - cdi.rInscribed = getInscribedRadiusFraction(cdi, cd0); - } -} - -module.exports = { - plot: plot, - transformInsideText: transformInsideText, - determineInsideTextFont: determineInsideTextFont, - positionTitleOutside: positionTitleOutside, - prerenderTitles: prerenderTitles, - layoutAreas: layoutAreas, - attachFxHandlers: attachFxHandlers, -}; - -},{"../../components/color":593,"../../components/drawing":614,"../../components/fx":632,"../../lib":719,"../../lib/svg_text_utils":743,"./event_data":1090,"./helpers":1091,"d3":163}],1096:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var styleOne = _dereq_('./style_one'); - -module.exports = function style(gd) { - gd._fullLayout._pielayer.selectAll('.trace').each(function(cd) { - var cd0 = cd[0]; - var trace = cd0.trace; - var traceSelection = d3.select(this); - - traceSelection.style({opacity: trace.opacity}); - - traceSelection.selectAll('path.surface').each(function(pt) { - d3.select(this).call(styleOne, pt, trace); - }); - }); -}; - -},{"./style_one":1097,"d3":163}],1097:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Color = _dereq_('../../components/color'); -var castOption = _dereq_('./helpers').castOption; - -module.exports = function styleOne(s, pt, trace) { - var line = trace.marker.line; - var lineColor = castOption(line.color, pt.pts) || Color.defaultLine; - var lineWidth = castOption(line.width, pt.pts) || 0; - - s.style('stroke-width', lineWidth) - .call(Color.fill, pt.color) - .call(Color.stroke, lineColor); -}; - -},{"../../components/color":593,"./helpers":1091}],1098:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterglAttrs = _dereq_('../scatter/attributes'); - -module.exports = { - x: scatterglAttrs.x, - y: scatterglAttrs.y, - xy: { - valType: 'data_array', - editType: 'calc', - - }, - indices: { - valType: 'data_array', - editType: 'calc', - - }, - xbounds: { - valType: 'data_array', - editType: 'calc', - - }, - ybounds: { - valType: 'data_array', - editType: 'calc', - - }, - text: scatterglAttrs.text, - marker: { - color: { - valType: 'color', - arrayOk: false, - - editType: 'calc', - - }, - opacity: { - valType: 'number', - min: 0, - max: 1, - dflt: 1, - arrayOk: false, - - editType: 'calc', - - }, - blend: { - valType: 'boolean', - dflt: null, - - editType: 'calc', - - }, - sizemin: { - valType: 'number', - min: 0.1, - max: 2, - dflt: 0.5, - - editType: 'calc', - - }, - sizemax: { - valType: 'number', - min: 0.1, - dflt: 20, - - editType: 'calc', - - }, - border: { - color: { - valType: 'color', - arrayOk: false, - - editType: 'calc', - - }, - arearatio: { - valType: 'number', - min: 0, - max: 1, - dflt: 0, - - editType: 'calc', - - }, - editType: 'calc' - }, - editType: 'calc' - }, - transforms: undefined -}; - -},{"../scatter/attributes":1112}],1099:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var createPointCloudRenderer = _dereq_('gl-pointcloud2d'); - -var str2RGBArray = _dereq_('../../lib/str2rgbarray'); -var findExtremes = _dereq_('../../plots/cartesian/autorange').findExtremes; -var getTraceColor = _dereq_('../scatter/get_trace_color'); - -function Pointcloud(scene, uid) { - this.scene = scene; - this.uid = uid; - this.type = 'pointcloud'; - - this.pickXData = []; - this.pickYData = []; - this.xData = []; - this.yData = []; - this.textLabels = []; - this.color = 'rgb(0, 0, 0)'; - this.name = ''; - this.hoverinfo = 'all'; - - this.idToIndex = new Int32Array(0); - this.bounds = [0, 0, 0, 0]; - - this.pointcloudOptions = { - positions: new Float32Array(0), - idToIndex: this.idToIndex, - sizemin: 0.5, - sizemax: 12, - color: [0, 0, 0, 1], - areaRatio: 1, - borderColor: [0, 0, 0, 1] - }; - this.pointcloud = createPointCloudRenderer(scene.glplot, this.pointcloudOptions); - this.pointcloud._trace = this; // scene2d requires this prop -} - -var proto = Pointcloud.prototype; - -proto.handlePick = function(pickResult) { - var index = this.idToIndex[pickResult.pointId]; - - // prefer the readout from XY, if present - return { - trace: this, - dataCoord: pickResult.dataCoord, - traceCoord: this.pickXYData ? - [this.pickXYData[index * 2], this.pickXYData[index * 2 + 1]] : - [this.pickXData[index], this.pickYData[index]], - textLabel: Array.isArray(this.textLabels) ? - this.textLabels[index] : - this.textLabels, - color: this.color, - name: this.name, - pointIndex: index, - hoverinfo: this.hoverinfo - }; -}; - -proto.update = function(options) { - this.index = options.index; - this.textLabels = options.text; - this.name = options.name; - this.hoverinfo = options.hoverinfo; - this.bounds = [Infinity, Infinity, -Infinity, -Infinity]; - - this.updateFast(options); - - this.color = getTraceColor(options, {}); -}; - -proto.updateFast = function(options) { - var x = this.xData = this.pickXData = options.x; - var y = this.yData = this.pickYData = options.y; - var xy = this.pickXYData = options.xy; - - var userBounds = options.xbounds && options.ybounds; - var index = options.indices; - - var len; - var idToIndex; - var positions; - var bounds = this.bounds; - - var xx, yy, i; - - if(xy) { - positions = xy; - - // dividing xy.length by 2 and truncating to integer if xy.length was not even - len = xy.length >>> 1; - - if(userBounds) { - bounds[0] = options.xbounds[0]; - bounds[2] = options.xbounds[1]; - bounds[1] = options.ybounds[0]; - bounds[3] = options.ybounds[1]; - } else { - for(i = 0; i < len; i++) { - xx = positions[i * 2]; - yy = positions[i * 2 + 1]; - - if(xx < bounds[0]) bounds[0] = xx; - if(xx > bounds[2]) bounds[2] = xx; - if(yy < bounds[1]) bounds[1] = yy; - if(yy > bounds[3]) bounds[3] = yy; - } - } - - if(index) { - idToIndex = index; - } else { - idToIndex = new Int32Array(len); - - for(i = 0; i < len; i++) { - idToIndex[i] = i; - } - } - } else { - len = x.length; - - positions = new Float32Array(2 * len); - idToIndex = new Int32Array(len); - - for(i = 0; i < len; i++) { - xx = x[i]; - yy = y[i]; - - idToIndex[i] = i; - - positions[i * 2] = xx; - positions[i * 2 + 1] = yy; - - if(xx < bounds[0]) bounds[0] = xx; - if(xx > bounds[2]) bounds[2] = xx; - if(yy < bounds[1]) bounds[1] = yy; - if(yy > bounds[3]) bounds[3] = yy; - } - } - - this.idToIndex = idToIndex; - this.pointcloudOptions.idToIndex = idToIndex; - - this.pointcloudOptions.positions = positions; - - var markerColor = str2RGBArray(options.marker.color); - var borderColor = str2RGBArray(options.marker.border.color); - var opacity = options.opacity * options.marker.opacity; - - markerColor[3] *= opacity; - this.pointcloudOptions.color = markerColor; - - // detect blending from the number of points, if undefined - // because large data with blending hits performance - var blend = options.marker.blend; - if(blend === null) { - var maxPoints = 100; - blend = x.length < maxPoints || y.length < maxPoints; - } - this.pointcloudOptions.blend = blend; - - borderColor[3] *= opacity; - this.pointcloudOptions.borderColor = borderColor; - - var markerSizeMin = options.marker.sizemin; - var markerSizeMax = Math.max(options.marker.sizemax, options.marker.sizemin); - this.pointcloudOptions.sizeMin = markerSizeMin; - this.pointcloudOptions.sizeMax = markerSizeMax; - this.pointcloudOptions.areaRatio = options.marker.border.arearatio; - - this.pointcloud.update(this.pointcloudOptions); - - // add item for autorange routine - var xa = this.scene.xaxis; - var ya = this.scene.yaxis; - var pad = markerSizeMax / 2 || 0.5; - options._extremes[xa._id] = findExtremes(xa, [bounds[0], bounds[2]], {ppad: pad}); - options._extremes[ya._id] = findExtremes(ya, [bounds[1], bounds[3]], {ppad: pad}); -}; - -proto.dispose = function() { - this.pointcloud.dispose(); -}; - -function createPointcloud(scene, data) { - var plot = new Pointcloud(scene, data.uid); - plot.update(data); - return plot; -} - -module.exports = createPointcloud; - -},{"../../lib/str2rgbarray":742,"../../plots/cartesian/autorange":766,"../scatter/get_trace_color":1121,"gl-pointcloud2d":292}],1100:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - coerce('x'); - coerce('y'); - - coerce('xbounds'); - coerce('ybounds'); - - if(traceIn.xy && traceIn.xy instanceof Float32Array) { - traceOut.xy = traceIn.xy; - } - - if(traceIn.indices && traceIn.indices instanceof Int32Array) { - traceOut.indices = traceIn.indices; - } - - coerce('text'); - coerce('marker.color', defaultColor); - coerce('marker.opacity'); - coerce('marker.blend'); - coerce('marker.sizemin'); - coerce('marker.sizemax'); - coerce('marker.border.color', defaultColor); - coerce('marker.border.arearatio'); - - // disable 1D transforms - that would defeat the purpose of this trace type, performance! - traceOut._length = null; -}; - -},{"../../lib":719,"./attributes":1098}],1101:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - - // reuse the Scatter3D 'dummy' calc step so that legends know what to do - calc: _dereq_('../scatter3d/calc'), - plot: _dereq_('./convert'), - - moduleType: 'trace', - name: 'pointcloud', - basePlotModule: _dereq_('../../plots/gl2d'), - categories: ['gl', 'gl2d', 'showLegend'], - meta: { - - } -}; - -},{"../../plots/gl2d":805,"../scatter3d/calc":1139,"./attributes":1098,"./convert":1099,"./defaults":1100}],1102:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var fontAttrs = _dereq_('../../plots/font_attributes'); -var plotAttrs = _dereq_('../../plots/attributes'); -var colorAttrs = _dereq_('../../components/color/attributes'); -var fxAttrs = _dereq_('../../components/fx/attributes'); -var domainAttrs = _dereq_('../../plots/domain').attributes; -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var colorAttributes = _dereq_('../../components/colorscale/attributes'); -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK; - -var attrs = module.exports = overrideAll({ - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: [], - arrayOk: false, - - }), - hoverlabel: fxAttrs.hoverlabel, - domain: domainAttrs({name: 'sankey', trace: true}), - - orientation: { - valType: 'enumerated', - values: ['v', 'h'], - dflt: 'h', - - - }, - - valueformat: { - valType: 'string', - dflt: '.3s', - - - }, - - valuesuffix: { - valType: 'string', - dflt: '', - - - }, - - arrangement: { - valType: 'enumerated', - values: ['snap', 'perpendicular', 'freeform', 'fixed'], - dflt: 'snap', - - - }, - - textfont: fontAttrs({ - - }), - - node: { - label: { - valType: 'data_array', - dflt: [], - - - }, - groups: { - valType: 'info_array', - impliedEdits: {'x': [], 'y': []}, - dimensions: 2, - freeLength: true, - dflt: [], - items: {valType: 'number', editType: 'calc'}, - - - }, - x: { - valType: 'data_array', - dflt: [], - - - }, - y: { - valType: 'data_array', - dflt: [], - - - }, - color: { - valType: 'color', - - arrayOk: true, - - }, - line: { - color: { - valType: 'color', - - dflt: colorAttrs.defaultLine, - arrayOk: true, - - }, - width: { - valType: 'number', - - min: 0, - dflt: 0.5, - arrayOk: true, - - } - }, - pad: { - valType: 'number', - arrayOk: false, - min: 0, - dflt: 20, - - - }, - thickness: { - valType: 'number', - arrayOk: false, - min: 1, - dflt: 20, - - - }, - hoverinfo: { - valType: 'enumerated', - values: ['all', 'none', 'skip'], - dflt: 'all', - - - }, - hoverlabel: fxAttrs.hoverlabel, // needs editType override, - hovertemplate: hovertemplateAttrs({}, { - - keys: ['value', 'label'] - }), - - }, - - link: { - label: { - valType: 'data_array', - dflt: [], - - - }, - color: { - valType: 'color', - - arrayOk: true, - - }, - line: { - color: { - valType: 'color', - - dflt: colorAttrs.defaultLine, - arrayOk: true, - - }, - width: { - valType: 'number', - - min: 0, - dflt: 0, - arrayOk: true, - - } - }, - source: { - valType: 'data_array', - - dflt: [], - - }, - target: { - valType: 'data_array', - - dflt: [], - - }, - value: { - valType: 'data_array', - dflt: [], - - - }, - hoverinfo: { - valType: 'enumerated', - values: ['all', 'none', 'skip'], - dflt: 'all', - - - }, - hoverlabel: fxAttrs.hoverlabel, // needs editType override, - hovertemplate: hovertemplateAttrs({}, { - - keys: ['value', 'label'] - }), - colorscales: templatedArray('concentrationscales', { - editType: 'calc', - label: { - valType: 'string', - - editType: 'calc', - - dflt: '' - }, - cmax: { - valType: 'number', - - editType: 'calc', - dflt: 1, - - }, - cmin: { - valType: 'number', - - editType: 'calc', - dflt: 0, - - }, - colorscale: extendFlat(colorAttributes().colorscale, {dflt: [[0, 'white'], [1, 'black']]}) - }), - - - } -}, 'calc', 'nested'); -attrs.transforms = undefined; - -},{"../../components/color/attributes":592,"../../components/colorscale/attributes":600,"../../components/fx/attributes":623,"../../components/fx/hovertemplate_attributes":631,"../../constants/docs":690,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plot_api/plot_template":757,"../../plots/attributes":764,"../../plots/domain":792,"../../plots/font_attributes":793}],1103:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; -var plot = _dereq_('./plot'); -var fxAttrs = _dereq_('../../components/fx/layout_attributes'); - -var setCursor = _dereq_('../../lib/setcursor'); -var dragElement = _dereq_('../../components/dragelement'); -var prepSelect = _dereq_('../../plots/cartesian/select').prepSelect; -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); - -var SANKEY = 'sankey'; - -exports.name = SANKEY; - -exports.baseLayoutAttrOverrides = overrideAll({ - hoverlabel: fxAttrs.hoverlabel -}, 'plot', 'nested'); - -exports.plot = function(gd) { - var calcData = getModuleCalcData(gd.calcdata, SANKEY)[0]; - plot(gd, calcData); - exports.updateFx(gd); -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var hadPlot = (oldFullLayout._has && oldFullLayout._has(SANKEY)); - var hasPlot = (newFullLayout._has && newFullLayout._has(SANKEY)); - - if(hadPlot && !hasPlot) { - oldFullLayout._paperdiv.selectAll('.sankey').remove(); - oldFullLayout._paperdiv.selectAll('.bgsankey').remove(); - } -}; - -exports.updateFx = function(gd) { - for(var i = 0; i < gd._fullData.length; i++) { - subplotUpdateFx(gd, i); - } -}; - -function subplotUpdateFx(gd, index) { - var trace = gd._fullData[index]; - var fullLayout = gd._fullLayout; - - var dragMode = fullLayout.dragmode; - var cursor = fullLayout.dragmode === 'pan' ? 'move' : 'crosshair'; - var bgRect = trace._bgRect; - - if(dragMode === 'pan' || dragMode === 'zoom') return; - - setCursor(bgRect, cursor); - - var xaxis = { - _id: 'x', - c2p: Lib.identity, - _offset: trace._sankey.translateX, - _length: trace._sankey.width - }; - var yaxis = { - _id: 'y', - c2p: Lib.identity, - _offset: trace._sankey.translateY, - _length: trace._sankey.height - }; - - // Note: dragOptions is needed to be declared for all dragmodes because - // it's the object that holds persistent selection state. - var dragOptions = { - gd: gd, - element: bgRect.node(), - plotinfo: { - id: index, - xaxis: xaxis, - yaxis: yaxis, - fillRangeItems: Lib.noop - }, - subplot: index, - // create mock x/y axes for hover routine - xaxes: [xaxis], - yaxes: [yaxis], - doneFnCompleted: function(selection) { - var traceNow = gd._fullData[index]; - var newGroups; - var oldGroups = traceNow.node.groups.slice(); - var newGroup = []; - - function findNode(pt) { - var nodes = traceNow._sankey.graph.nodes; - for(var i = 0; i < nodes.length; i++) { - if(nodes[i].pointNumber === pt) return nodes[i]; - } - } - - for(var j = 0; j < selection.length; j++) { - var node = findNode(selection[j].pointNumber); - if(!node) continue; - - // If the node represents a group - if(node.group) { - // Add all its children to the current selection - for(var k = 0; k < node.childrenNodes.length; k++) { - newGroup.push(node.childrenNodes[k].pointNumber); - } - // Flag group for removal from existing list of groups - oldGroups[node.pointNumber - traceNow.node._count] = false; - } else { - newGroup.push(node.pointNumber); - } - } - - newGroups = oldGroups - .filter(Boolean) - .concat([newGroup]); - - Registry.call('_guiRestyle', gd, { - 'node.groups': [ newGroups ] - }, index); - } - }; - - dragOptions.prepFn = function(e, startX, startY) { - prepSelect(e, startX, startY, dragOptions, dragMode); - }; - - dragElement.init(dragOptions); -} - -},{"../../components/dragelement":611,"../../components/fx/layout_attributes":633,"../../lib":719,"../../lib/setcursor":739,"../../plot_api/edit_types":750,"../../plots/cartesian/select":784,"../../plots/get_data":802,"../../registry":847,"./plot":1108}],1104:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var tarjan = _dereq_('strongly-connected-components'); -var Lib = _dereq_('../../lib'); -var wrap = _dereq_('../../lib/gup').wrap; - -var isArrayOrTypedArray = Lib.isArrayOrTypedArray; -var isIndex = Lib.isIndex; -var Colorscale = _dereq_('../../components/colorscale'); - -function convertToD3Sankey(trace) { - var nodeSpec = trace.node; - var linkSpec = trace.link; - - var links = []; - var hasLinkColorArray = isArrayOrTypedArray(linkSpec.color); - var linkedNodes = {}; - - var components = {}; - var componentCount = linkSpec.colorscales.length; - var i; - for(i = 0; i < componentCount; i++) { - var cscale = linkSpec.colorscales[i]; - var specs = Colorscale.extractScale(cscale, {cLetter: 'c'}); - var scale = Colorscale.makeColorScaleFunc(specs); - components[cscale.label] = scale; - } - - var maxNodeId = 0; - for(i = 0; i < linkSpec.value.length; i++) { - if(linkSpec.source[i] > maxNodeId) maxNodeId = linkSpec.source[i]; - if(linkSpec.target[i] > maxNodeId) maxNodeId = linkSpec.target[i]; - } - var nodeCount = maxNodeId + 1; - trace.node._count = nodeCount; - - // Group nodes - var j; - var groups = trace.node.groups; - var groupLookup = {}; - for(i = 0; i < groups.length; i++) { - var group = groups[i]; - // Build a lookup table to quickly find in which group a node is - for(j = 0; j < group.length; j++) { - var nodeIndex = group[j]; - var groupIndex = nodeCount + i; - if(groupLookup.hasOwnProperty(nodeIndex)) { - Lib.warn('Node ' + nodeIndex + ' is already part of a group.'); - } else { - groupLookup[nodeIndex] = groupIndex; - } - } - } - - // Process links - var groupedLinks = { - source: [], - target: [] - }; - for(i = 0; i < linkSpec.value.length; i++) { - var val = linkSpec.value[i]; - // remove negative values, but keep zeros with special treatment - var source = linkSpec.source[i]; - var target = linkSpec.target[i]; - if(!(val > 0 && isIndex(source, nodeCount) && isIndex(target, nodeCount))) { - continue; - } - - // Remove links that are within the same group - if(groupLookup.hasOwnProperty(source) && groupLookup.hasOwnProperty(target) && groupLookup[source] === groupLookup[target]) { - continue; - } - - // if link targets a node in the group, relink target to that group - if(groupLookup.hasOwnProperty(target)) { - target = groupLookup[target]; - } - - // if link originates from a node in a group, relink source to that group - if(groupLookup.hasOwnProperty(source)) { - source = groupLookup[source]; - } - - source = +source; - target = +target; - linkedNodes[source] = linkedNodes[target] = true; - - var label = ''; - if(linkSpec.label && linkSpec.label[i]) label = linkSpec.label[i]; - - var concentrationscale = null; - if(label && components.hasOwnProperty(label)) concentrationscale = components[label]; - - links.push({ - pointNumber: i, - label: label, - color: hasLinkColorArray ? linkSpec.color[i] : linkSpec.color, - concentrationscale: concentrationscale, - source: source, - target: target, - value: +val - }); - - groupedLinks.source.push(source); - groupedLinks.target.push(target); - } - - // Process nodes - var totalCount = nodeCount + groups.length; - var hasNodeColorArray = isArrayOrTypedArray(nodeSpec.color); - var nodes = []; - for(i = 0; i < totalCount; i++) { - if(!linkedNodes[i]) continue; - var l = nodeSpec.label[i]; - - nodes.push({ - group: (i > nodeCount - 1), - childrenNodes: [], - pointNumber: i, - label: l, - color: hasNodeColorArray ? nodeSpec.color[i] : nodeSpec.color - }); - } - - // Check if we have circularity on the resulting graph - var circular = false; - if(circularityPresent(totalCount, groupedLinks.source, groupedLinks.target)) { - circular = true; - } - - return { - circular: circular, - links: links, - nodes: nodes, - - // Data structure for groups - groups: groups, - groupLookup: groupLookup - }; -} - -function circularityPresent(nodeLen, sources, targets) { - var nodes = Lib.init2dArray(nodeLen, 0); - - for(var i = 0; i < Math.min(sources.length, targets.length); i++) { - if(Lib.isIndex(sources[i], nodeLen) && Lib.isIndex(targets[i], nodeLen)) { - if(sources[i] === targets[i]) { - return true; // self-link which is also a scc of one - } - nodes[sources[i]].push(targets[i]); - } - } - - var scc = tarjan(nodes); - - // Tarján's strongly connected components algorithm coded by Mikola Lysenko - // returns at least one non-singular component if there's circularity in the graph - return scc.components.some(function(c) { - return c.length > 1; - }); -} - -module.exports = function calc(gd, trace) { - var result = convertToD3Sankey(trace); - - return wrap({ - circular: result.circular, - _nodes: result.nodes, - _links: result.links, - - // Data structure for grouping - _groups: result.groups, - _groupLookup: result.groupLookup, - }); -}; - -},{"../../components/colorscale":605,"../../lib":719,"../../lib/gup":717,"strongly-connected-components":530}],1105:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - nodeTextOffsetHorizontal: 4, - nodeTextOffsetVertical: 3, - nodePadAcross: 10, - sankeyIterations: 50, - forceIterations: 5, - forceTicksPerFrame: 10, - duration: 500, - ease: 'linear', - cn: { - sankey: 'sankey', - sankeyLinks: 'sankey-links', - sankeyLink: 'sankey-link', - sankeyNodeSet: 'sankey-node-set', - sankeyNode: 'sankey-node', - nodeRect: 'node-rect', - nodeCapture: 'node-capture', - nodeCentered: 'node-entered', - nodeLabelGuide: 'node-label-guide', - nodeLabel: 'node-label', - nodeLabelTextPath: 'node-label-text-path' - } -}; - -},{}],1106:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attributes = _dereq_('./attributes'); -var Color = _dereq_('../../components/color'); -var tinycolor = _dereq_('tinycolor2'); -var handleDomainDefaults = _dereq_('../../plots/domain').defaults; -var handleHoverLabelDefaults = _dereq_('../../components/fx/hoverlabel_defaults'); -var Template = _dereq_('../../plot_api/plot_template'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var hoverlabelDefault = Lib.extendDeep(layout.hoverlabel, traceIn.hoverlabel); - - // node attributes - var nodeIn = traceIn.node; - var nodeOut = Template.newContainer(traceOut, 'node'); - - function coerceNode(attr, dflt) { - return Lib.coerce(nodeIn, nodeOut, attributes.node, attr, dflt); - } - coerceNode('label'); - coerceNode('groups'); - coerceNode('x'); - coerceNode('y'); - coerceNode('pad'); - coerceNode('thickness'); - coerceNode('line.color'); - coerceNode('line.width'); - coerceNode('hoverinfo', traceIn.hoverinfo); - handleHoverLabelDefaults(nodeIn, nodeOut, coerceNode, hoverlabelDefault); - coerceNode('hovertemplate'); - - var colors = layout.colorway; - - var defaultNodePalette = function(i) {return colors[i % colors.length];}; - - coerceNode('color', nodeOut.label.map(function(d, i) { - return Color.addOpacity(defaultNodePalette(i), 0.8); - })); - - // link attributes - var linkIn = traceIn.link || {}; - var linkOut = Template.newContainer(traceOut, 'link'); - - function coerceLink(attr, dflt) { - return Lib.coerce(linkIn, linkOut, attributes.link, attr, dflt); - } - coerceLink('label'); - coerceLink('source'); - coerceLink('target'); - coerceLink('value'); - coerceLink('line.color'); - coerceLink('line.width'); - coerceLink('hoverinfo', traceIn.hoverinfo); - handleHoverLabelDefaults(linkIn, linkOut, coerceLink, hoverlabelDefault); - coerceLink('hovertemplate'); - - var defaultLinkColor = tinycolor(layout.paper_bgcolor).getLuminance() < 0.333 ? - 'rgba(255, 255, 255, 0.6)' : - 'rgba(0, 0, 0, 0.2)'; - - coerceLink('color', Lib.repeat(defaultLinkColor, linkOut.value.length)); - - handleArrayContainerDefaults(linkIn, linkOut, { - name: 'colorscales', - handleItemDefaults: concentrationscalesDefaults - }); - - handleDomainDefaults(traceOut, layout, coerce); - - coerce('orientation'); - coerce('valueformat'); - coerce('valuesuffix'); - - var dfltArrangement; - if(nodeOut.x.length && nodeOut.y.length) { - dfltArrangement = 'freeform'; - } - coerce('arrangement', dfltArrangement); - - Lib.coerceFont(coerce, 'textfont', Lib.extendFlat({}, layout.font)); - - // disable 1D transforms - arrays here are 1D but their lengths/meanings - // don't match, between nodes and links - traceOut._length = null; -}; - -function concentrationscalesDefaults(In, Out) { - function coerce(attr, dflt) { - return Lib.coerce(In, Out, attributes.link.colorscales, attr, dflt); - } - - coerce('label'); - coerce('cmin'); - coerce('cmax'); - coerce('colorscale'); -} - -},{"../../components/color":593,"../../components/fx/hoverlabel_defaults":630,"../../lib":719,"../../plot_api/plot_template":757,"../../plots/array_container_defaults":763,"../../plots/domain":792,"./attributes":1102,"tinycolor2":537}],1107:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - - moduleType: 'trace', - name: 'sankey', - basePlotModule: _dereq_('./base_plot'), - selectPoints: _dereq_('./select.js'), - categories: ['noOpacity'], - meta: { - - } -}; - -},{"./attributes":1102,"./base_plot":1103,"./calc":1104,"./defaults":1106,"./plot":1108,"./select.js":1110}],1108:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var render = _dereq_('./render'); -var Fx = _dereq_('../../components/fx'); -var Color = _dereq_('../../components/color'); -var Lib = _dereq_('../../lib'); -var cn = _dereq_('./constants').cn; - -var _ = Lib._; - -function renderableValuePresent(d) {return d !== '';} - -function ownTrace(selection, d) { - return selection.filter(function(s) {return s.key === d.traceId;}); -} - -function makeTranslucent(element, alpha) { - d3.select(element) - .select('path') - .style('fill-opacity', alpha); - d3.select(element) - .select('rect') - .style('fill-opacity', alpha); -} - -function makeTextContrasty(element) { - d3.select(element) - .select('text.name') - .style('fill', 'black'); -} - -function relatedLinks(d) { - return function(l) { - return d.node.sourceLinks.indexOf(l.link) !== -1 || d.node.targetLinks.indexOf(l.link) !== -1; - }; -} - -function relatedNodes(l) { - return function(d) { - return d.node.sourceLinks.indexOf(l.link) !== -1 || d.node.targetLinks.indexOf(l.link) !== -1; - }; -} - -function nodeHoveredStyle(sankeyNode, d, sankey) { - if(d && sankey) { - ownTrace(sankey, d) - .selectAll('.' + cn.sankeyLink) - .filter(relatedLinks(d)) - .call(linkHoveredStyle.bind(0, d, sankey, false)); - } -} - -function nodeNonHoveredStyle(sankeyNode, d, sankey) { - if(d && sankey) { - ownTrace(sankey, d) - .selectAll('.' + cn.sankeyLink) - .filter(relatedLinks(d)) - .call(linkNonHoveredStyle.bind(0, d, sankey, false)); - } -} - -function linkHoveredStyle(d, sankey, visitNodes, sankeyLink) { - var label = sankeyLink.datum().link.label; - - sankeyLink.style('fill-opacity', function(l) { - if(!l.link.concentrationscale) { - return 0.4; - } - }); - - if(label) { - ownTrace(sankey, d) - .selectAll('.' + cn.sankeyLink) - .filter(function(l) {return l.link.label === label;}) - .style('fill-opacity', function(l) { - if(!l.link.concentrationscale) { - return 0.4; - } - }); - } - - if(visitNodes) { - ownTrace(sankey, d) - .selectAll('.' + cn.sankeyNode) - .filter(relatedNodes(d)) - .call(nodeHoveredStyle); - } -} - -function linkNonHoveredStyle(d, sankey, visitNodes, sankeyLink) { - var label = sankeyLink.datum().link.label; - - sankeyLink.style('fill-opacity', function(d) {return d.tinyColorAlpha;}); - if(label) { - ownTrace(sankey, d) - .selectAll('.' + cn.sankeyLink) - .filter(function(l) {return l.link.label === label;}) - .style('fill-opacity', function(d) {return d.tinyColorAlpha;}); - } - - if(visitNodes) { - ownTrace(sankey, d) - .selectAll(cn.sankeyNode) - .filter(relatedNodes(d)) - .call(nodeNonHoveredStyle); - } -} - -// does not support array values for now -function castHoverOption(trace, attr) { - var labelOpts = trace.hoverlabel || {}; - var val = Lib.nestedProperty(labelOpts, attr).get(); - return Array.isArray(val) ? false : val; -} - -module.exports = function plot(gd, calcData) { - var fullLayout = gd._fullLayout; - var svg = fullLayout._paper; - var size = fullLayout._size; - - // stash initial view - for(var i = 0; i < gd._fullData.length; i++) { - if(gd._fullData[i].type !== cn.sankey) continue; - if(!gd._fullData[i]._viewInitial) { - var node = gd._fullData[i].node; - gd._fullData[i]._viewInitial = { - node: { - groups: node.groups.slice(), - x: node.x.slice(), - y: node.y.slice() - } - }; - } - } - - var linkSelect = function(element, d) { - var evt = d.link; - evt.originalEvent = d3.event; - gd._hoverdata = [evt]; - Fx.click(gd, { target: true }); - }; - - var linkHover = function(element, d, sankey) { - if(gd._fullLayout.hovermode === false) return; - d3.select(element).call(linkHoveredStyle.bind(0, d, sankey, true)); - if(d.link.trace.link.hoverinfo !== 'skip') { - d.link.fullData = d.link.trace; - gd.emit('plotly_hover', { - event: d3.event, - points: [d.link] - }); - } - }; - - var sourceLabel = _(gd, 'source:') + ' '; - var targetLabel = _(gd, 'target:') + ' '; - var concentrationLabel = _(gd, 'concentration:') + ' '; - var incomingLabel = _(gd, 'incoming flow count:') + ' '; - var outgoingLabel = _(gd, 'outgoing flow count:') + ' '; - - var linkHoverFollow = function(element, d) { - if(gd._fullLayout.hovermode === false) return; - var obj = d.link.trace.link; - if(obj.hoverinfo === 'none' || obj.hoverinfo === 'skip') return; - - var hoverItems = []; - - function hoverCenterPosition(link) { - var hoverCenterX, hoverCenterY; - if(link.circular) { - hoverCenterX = (link.circularPathData.leftInnerExtent + link.circularPathData.rightInnerExtent) / 2 + d.parent.translateX; - hoverCenterY = link.circularPathData.verticalFullExtent + d.parent.translateY; - } else { - hoverCenterX = (link.source.x1 + link.target.x0) / 2 + d.parent.translateX; - hoverCenterY = (link.y0 + link.y1) / 2 + d.parent.translateY; - } - return [hoverCenterX, hoverCenterY]; - } - - // For each related links, create a hoverItem - var anchorIndex = 0; - for(var i = 0; i < d.flow.links.length; i++) { - var link = d.flow.links[i]; - if(gd._fullLayout.hovermode === 'closest' && d.link.pointNumber !== link.pointNumber) continue; - if(d.link.pointNumber === link.pointNumber) anchorIndex = i; - link.fullData = link.trace; - obj = d.link.trace.link; - var hoverCenter = hoverCenterPosition(link); - var hovertemplateLabels = {valueLabel: d3.format(d.valueFormat)(link.value) + d.valueSuffix}; - - hoverItems.push({ - x: hoverCenter[0], - y: hoverCenter[1], - name: hovertemplateLabels.valueLabel, - text: [ - link.label || '', - sourceLabel + link.source.label, - targetLabel + link.target.label, - link.concentrationscale ? concentrationLabel + d3.format('%0.2f')(link.flow.labelConcentration) : '' - ].filter(renderableValuePresent).join('
'), - color: castHoverOption(obj, 'bgcolor') || Color.addOpacity(link.color, 1), - borderColor: castHoverOption(obj, 'bordercolor'), - fontFamily: castHoverOption(obj, 'font.family'), - fontSize: castHoverOption(obj, 'font.size'), - fontColor: castHoverOption(obj, 'font.color'), - nameLength: castHoverOption(obj, 'namelength'), - textAlign: castHoverOption(obj, 'align'), - idealAlign: d3.event.x < hoverCenter[0] ? 'right' : 'left', - - hovertemplate: obj.hovertemplate, - hovertemplateLabels: hovertemplateLabels, - eventData: [link] - }); - } - - var tooltips = Fx.loneHover(hoverItems, { - container: fullLayout._hoverlayer.node(), - outerContainer: fullLayout._paper.node(), - gd: gd, - anchorIndex: anchorIndex - }); - - tooltips.each(function() { - var tooltip = this; - if(!d.link.concentrationscale) { - makeTranslucent(tooltip, 0.65); - } - makeTextContrasty(tooltip); - }); - }; - - var linkUnhover = function(element, d, sankey) { - if(gd._fullLayout.hovermode === false) return; - d3.select(element).call(linkNonHoveredStyle.bind(0, d, sankey, true)); - if(d.link.trace.link.hoverinfo !== 'skip') { - d.link.fullData = d.link.trace; - gd.emit('plotly_unhover', { - event: d3.event, - points: [d.link] - }); - } - - Fx.loneUnhover(fullLayout._hoverlayer.node()); - }; - - var nodeSelect = function(element, d, sankey) { - var evt = d.node; - evt.originalEvent = d3.event; - gd._hoverdata = [evt]; - d3.select(element).call(nodeNonHoveredStyle, d, sankey); - Fx.click(gd, { target: true }); - }; - - var nodeHover = function(element, d, sankey) { - if(gd._fullLayout.hovermode === false) return; - d3.select(element).call(nodeHoveredStyle, d, sankey); - if(d.node.trace.node.hoverinfo !== 'skip') { - d.node.fullData = d.node.trace; - gd.emit('plotly_hover', { - event: d3.event, - points: [d.node] - }); - } - }; - - var nodeHoverFollow = function(element, d) { - if(gd._fullLayout.hovermode === false) return; - - var obj = d.node.trace.node; - if(obj.hoverinfo === 'none' || obj.hoverinfo === 'skip') return; - var nodeRect = d3.select(element).select('.' + cn.nodeRect); - var rootBBox = gd._fullLayout._paperdiv.node().getBoundingClientRect(); - var boundingBox = nodeRect.node().getBoundingClientRect(); - var hoverCenterX0 = boundingBox.left - 2 - rootBBox.left; - var hoverCenterX1 = boundingBox.right + 2 - rootBBox.left; - var hoverCenterY = boundingBox.top + boundingBox.height / 4 - rootBBox.top; - - var hovertemplateLabels = {valueLabel: d3.format(d.valueFormat)(d.node.value) + d.valueSuffix}; - d.node.fullData = d.node.trace; - - var tooltip = Fx.loneHover({ - x0: hoverCenterX0, - x1: hoverCenterX1, - y: hoverCenterY, - name: d3.format(d.valueFormat)(d.node.value) + d.valueSuffix, - text: [ - d.node.label, - incomingLabel + d.node.targetLinks.length, - outgoingLabel + d.node.sourceLinks.length - ].filter(renderableValuePresent).join('
'), - color: castHoverOption(obj, 'bgcolor') || d.tinyColorHue, - borderColor: castHoverOption(obj, 'bordercolor'), - fontFamily: castHoverOption(obj, 'font.family'), - fontSize: castHoverOption(obj, 'font.size'), - fontColor: castHoverOption(obj, 'font.color'), - nameLength: castHoverOption(obj, 'namelength'), - textAlign: castHoverOption(obj, 'align'), - idealAlign: 'left', - - hovertemplate: obj.hovertemplate, - hovertemplateLabels: hovertemplateLabels, - eventData: [d.node] - }, { - container: fullLayout._hoverlayer.node(), - outerContainer: fullLayout._paper.node(), - gd: gd - }); - - makeTranslucent(tooltip, 0.85); - makeTextContrasty(tooltip); - }; - - var nodeUnhover = function(element, d, sankey) { - if(gd._fullLayout.hovermode === false) return; - d3.select(element).call(nodeNonHoveredStyle, d, sankey); - if(d.node.trace.node.hoverinfo !== 'skip') { - d.node.fullData = d.node.trace; - gd.emit('plotly_unhover', { - event: d3.event, - points: [d.node] - }); - } - - Fx.loneUnhover(fullLayout._hoverlayer.node()); - }; - - render( - gd, - svg, - calcData, - { - width: size.w, - height: size.h, - margin: { - t: size.t, - r: size.r, - b: size.b, - l: size.l - } - }, - { - linkEvents: { - hover: linkHover, - follow: linkHoverFollow, - unhover: linkUnhover, - select: linkSelect - }, - nodeEvents: { - hover: nodeHover, - follow: nodeHoverFollow, - unhover: nodeUnhover, - select: nodeSelect - } - } - ); -}; - -},{"../../components/color":593,"../../components/fx":632,"../../lib":719,"./constants":1105,"./render":1109,"d3":163}],1109:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var c = _dereq_('./constants'); -var d3 = _dereq_('d3'); -var tinycolor = _dereq_('tinycolor2'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var d3Sankey = _dereq_('@plotly/d3-sankey'); -var d3SankeyCircular = _dereq_('@plotly/d3-sankey-circular'); -var d3Force = _dereq_('d3-force'); -var Lib = _dereq_('../../lib'); -var gup = _dereq_('../../lib/gup'); -var keyFun = gup.keyFun; -var repeat = gup.repeat; -var unwrap = gup.unwrap; -var interpolateNumber = _dereq_('d3-interpolate').interpolateNumber; - -var Registry = _dereq_('../../registry'); - -// view models - -function sankeyModel(layout, d, traceIndex) { - var calcData = unwrap(d); - var trace = calcData.trace; - var domain = trace.domain; - var horizontal = trace.orientation === 'h'; - var nodePad = trace.node.pad; - var nodeThickness = trace.node.thickness; - - var width = layout.width * (domain.x[1] - domain.x[0]); - var height = layout.height * (domain.y[1] - domain.y[0]); - - var nodes = calcData._nodes; - var links = calcData._links; - var circular = calcData.circular; - - // Select Sankey generator - var sankey; - if(circular) { - sankey = d3SankeyCircular - .sankeyCircular() - .circularLinkGap(0); - } else { - sankey = d3Sankey.sankey(); - } - - sankey - .iterations(c.sankeyIterations) - .size(horizontal ? [width, height] : [height, width]) - .nodeWidth(nodeThickness) - .nodePadding(nodePad) - .nodeId(function(d) { - return d.pointNumber; - }) - .nodes(nodes) - .links(links); - - var graph = sankey(); - - if(sankey.nodePadding() < nodePad) { - Lib.warn('node.pad was reduced to ', sankey.nodePadding(), ' to fit within the figure.'); - } - - // Counters for nested loops - var i, j, k; - - // Create transient nodes for animations - for(var nodePointNumber in calcData._groupLookup) { - var groupIndex = parseInt(calcData._groupLookup[nodePointNumber]); - - // Find node representing groupIndex - var groupingNode; - - for(i = 0; i < graph.nodes.length; i++) { - if(graph.nodes[i].pointNumber === groupIndex) { - groupingNode = graph.nodes[i]; - break; - } - } - // If groupinNode is undefined, no links are targeting this group - if(!groupingNode) continue; - - var child = { - pointNumber: parseInt(nodePointNumber), - x0: groupingNode.x0, - x1: groupingNode.x1, - y0: groupingNode.y0, - y1: groupingNode.y1, - partOfGroup: true, - sourceLinks: [], - targetLinks: [] - }; - - graph.nodes.unshift(child); - groupingNode.childrenNodes.unshift(child); - } - - function computeLinkConcentrations() { - for(i = 0; i < graph.nodes.length; i++) { - var node = graph.nodes[i]; - // Links connecting the same two nodes are part of a flow - var flows = {}; - var flowKey; - var link; - for(j = 0; j < node.targetLinks.length; j++) { - link = node.targetLinks[j]; - flowKey = link.source.pointNumber + ':' + link.target.pointNumber; - if(!flows.hasOwnProperty(flowKey)) flows[flowKey] = []; - flows[flowKey].push(link); - } - - // Compute statistics for each flow - var keys = Object.keys(flows); - for(j = 0; j < keys.length; j++) { - flowKey = keys[j]; - var flowLinks = flows[flowKey]; - - // Find the total size of the flow and total size per label - var total = 0; - var totalPerLabel = {}; - for(k = 0; k < flowLinks.length; k++) { - link = flowLinks[k]; - if(!totalPerLabel[link.label]) totalPerLabel[link.label] = 0; - totalPerLabel[link.label] += link.value; - total += link.value; - } - - // Find the ratio of the link's value and the size of the flow - for(k = 0; k < flowLinks.length; k++) { - link = flowLinks[k]; - link.flow = { - value: total, - labelConcentration: totalPerLabel[link.label] / total, - concentration: link.value / total, - links: flowLinks - }; - if(link.concentrationscale) { - link.color = tinycolor(link.concentrationscale(link.flow.labelConcentration)); - } - } - } - - // Gather statistics of all links at current node - var totalOutflow = 0; - for(j = 0; j < node.sourceLinks.length; j++) { - totalOutflow += node.sourceLinks[j].value; - } - for(j = 0; j < node.sourceLinks.length; j++) { - link = node.sourceLinks[j]; - link.concentrationOut = link.value / totalOutflow; - } - - var totalInflow = 0; - for(j = 0; j < node.targetLinks.length; j++) { - totalInflow += node.targetLinks[j].value; - } - - for(j = 0; j < node.targetLinks.length; j++) { - link = node.targetLinks[j]; - link.concenrationIn = link.value / totalInflow; - } - } - } - computeLinkConcentrations(); - - // Push any overlapping nodes down. - function resolveCollisionsTopToBottom(columns) { - columns.forEach(function(nodes) { - var node; - var dy; - var y = 0; - var n = nodes.length; - var i; - nodes.sort(function(a, b) { - return a.y0 - b.y0; - }); - for(i = 0; i < n; ++i) { - node = nodes[i]; - if(node.y0 >= y) { - // No overlap - } else { - dy = (y - node.y0); - if(dy > 1e-6) node.y0 += dy, node.y1 += dy; - } - y = node.y1 + nodePad; - } - }); - } - - // Group nodes into columns based on their x position - function snapToColumns(nodes) { - // Sort nodes by x position - var orderedNodes = nodes.map(function(n, i) { - return { - x0: n.x0, - index: i - }; - }) - .sort(function(a, b) { - return a.x0 - b.x0; - }); - - var columns = []; - var colNumber = -1; - var colX; // Position of column - var lastX = -Infinity; // Position of last node - var dx; - for(i = 0; i < orderedNodes.length; i++) { - var node = nodes[orderedNodes[i].index]; - // If the node does not overlap with the last one - if(node.x0 > lastX + nodeThickness) { - // Start a new column - colNumber += 1; - colX = node.x0; - } - lastX = node.x0; - - // Add node to its associated column - if(!columns[colNumber]) columns[colNumber] = []; - columns[colNumber].push(node); - - // Change node's x position to align it with its column - dx = colX - node.x0; - node.x0 += dx, node.x1 += dx; - } - return columns; - } - - // Force node position - if(trace.node.x.length && trace.node.y.length) { - for(i = 0; i < Math.min(trace.node.x.length, trace.node.y.length, graph.nodes.length); i++) { - if(trace.node.x[i] && trace.node.y[i]) { - var pos = [trace.node.x[i] * width, trace.node.y[i] * height]; - graph.nodes[i].x0 = pos[0] - nodeThickness / 2; - graph.nodes[i].x1 = pos[0] + nodeThickness / 2; - - var nodeHeight = graph.nodes[i].y1 - graph.nodes[i].y0; - graph.nodes[i].y0 = pos[1] - nodeHeight / 2; - graph.nodes[i].y1 = pos[1] + nodeHeight / 2; - } - } - if(trace.arrangement === 'snap') { - nodes = graph.nodes; - var columns = snapToColumns(nodes); - resolveCollisionsTopToBottom(columns); - } - // Update links - sankey.update(graph); - } - - - return { - circular: circular, - key: traceIndex, - trace: trace, - guid: Lib.randstr(), - horizontal: horizontal, - width: width, - height: height, - nodePad: trace.node.pad, - nodeLineColor: trace.node.line.color, - nodeLineWidth: trace.node.line.width, - linkLineColor: trace.link.line.color, - linkLineWidth: trace.link.line.width, - valueFormat: trace.valueformat, - valueSuffix: trace.valuesuffix, - textFont: trace.textfont, - translateX: domain.x[0] * layout.width + layout.margin.l, - translateY: layout.height - domain.y[1] * layout.height + layout.margin.t, - dragParallel: horizontal ? height : width, - dragPerpendicular: horizontal ? width : height, - arrangement: trace.arrangement, - sankey: sankey, - graph: graph, - forceLayouts: {}, - interactionState: { - dragInProgress: false, - hovered: false - } - }; -} - -function linkModel(d, l, i) { - var tc = tinycolor(l.color); - var basicKey = l.source.label + '|' + l.target.label; - var key = basicKey + '__' + i; - - // for event data - l.trace = d.trace; - l.curveNumber = d.trace.index; - - return { - circular: d.circular, - key: key, - traceId: d.key, - pointNumber: l.pointNumber, - link: l, - tinyColorHue: Color.tinyRGB(tc), - tinyColorAlpha: tc.getAlpha(), - linkPath: linkPath, - linkLineColor: d.linkLineColor, - linkLineWidth: d.linkLineWidth, - valueFormat: d.valueFormat, - valueSuffix: d.valueSuffix, - sankey: d.sankey, - parent: d, - interactionState: d.interactionState, - flow: l.flow - }; -} - -function createCircularClosedPathString(link) { - // Using coordinates computed by d3-sankey-circular - var pathString = ''; - var offset = link.width / 2; - var coords = link.circularPathData; - if(link.circularLinkType === 'top') { - // Top path - pathString = - // start at the left of the target node - 'M ' + - coords.targetX + ' ' + (coords.targetY + offset) + ' ' + - 'L' + - coords.rightInnerExtent + ' ' + (coords.targetY + offset) + - 'A' + - (coords.rightLargeArcRadius + offset) + ' ' + (coords.rightSmallArcRadius + offset) + ' 0 0 1 ' + - (coords.rightFullExtent - offset) + ' ' + (coords.targetY - coords.rightSmallArcRadius) + - 'L' + - (coords.rightFullExtent - offset) + ' ' + coords.verticalRightInnerExtent + - 'A' + - (coords.rightLargeArcRadius + offset) + ' ' + (coords.rightLargeArcRadius + offset) + ' 0 0 1 ' + - coords.rightInnerExtent + ' ' + (coords.verticalFullExtent - offset) + - 'L' + - coords.leftInnerExtent + ' ' + (coords.verticalFullExtent - offset) + - 'A' + - (coords.leftLargeArcRadius + offset) + ' ' + (coords.leftLargeArcRadius + offset) + ' 0 0 1 ' + - (coords.leftFullExtent + offset) + ' ' + coords.verticalLeftInnerExtent + - 'L' + - (coords.leftFullExtent + offset) + ' ' + (coords.sourceY - coords.leftSmallArcRadius) + - 'A' + - (coords.leftLargeArcRadius + offset) + ' ' + (coords.leftSmallArcRadius + offset) + ' 0 0 1 ' + - coords.leftInnerExtent + ' ' + (coords.sourceY + offset) + - 'L' + - coords.sourceX + ' ' + (coords.sourceY + offset) + - - // Walking back - 'L' + - coords.sourceX + ' ' + (coords.sourceY - offset) + - 'L' + - coords.leftInnerExtent + ' ' + (coords.sourceY - offset) + - 'A' + - (coords.leftLargeArcRadius - offset) + ' ' + (coords.leftSmallArcRadius - offset) + ' 0 0 0 ' + - (coords.leftFullExtent - offset) + ' ' + (coords.sourceY - coords.leftSmallArcRadius) + - 'L' + - (coords.leftFullExtent - offset) + ' ' + coords.verticalLeftInnerExtent + - 'A' + - (coords.leftLargeArcRadius - offset) + ' ' + (coords.leftLargeArcRadius - offset) + ' 0 0 0 ' + - coords.leftInnerExtent + ' ' + (coords.verticalFullExtent + offset) + - 'L' + - coords.rightInnerExtent + ' ' + (coords.verticalFullExtent + offset) + - 'A' + - (coords.rightLargeArcRadius - offset) + ' ' + (coords.rightLargeArcRadius - offset) + ' 0 0 0 ' + - (coords.rightFullExtent + offset) + ' ' + coords.verticalRightInnerExtent + - 'L' + - (coords.rightFullExtent + offset) + ' ' + (coords.targetY - coords.rightSmallArcRadius) + - 'A' + - (coords.rightLargeArcRadius - offset) + ' ' + (coords.rightSmallArcRadius - offset) + ' 0 0 0 ' + - coords.rightInnerExtent + ' ' + (coords.targetY - offset) + - 'L' + - coords.targetX + ' ' + (coords.targetY - offset) + - 'Z'; - } else { - // Bottom path - pathString = - // start at the left of the target node - 'M ' + - coords.targetX + ' ' + (coords.targetY - offset) + ' ' + - 'L' + - coords.rightInnerExtent + ' ' + (coords.targetY - offset) + - 'A' + - (coords.rightLargeArcRadius + offset) + ' ' + (coords.rightSmallArcRadius + offset) + ' 0 0 0 ' + - (coords.rightFullExtent - offset) + ' ' + (coords.targetY + coords.rightSmallArcRadius) + - 'L' + - (coords.rightFullExtent - offset) + ' ' + coords.verticalRightInnerExtent + - 'A' + - (coords.rightLargeArcRadius + offset) + ' ' + (coords.rightLargeArcRadius + offset) + ' 0 0 0 ' + - coords.rightInnerExtent + ' ' + (coords.verticalFullExtent + offset) + - 'L' + - coords.leftInnerExtent + ' ' + (coords.verticalFullExtent + offset) + - 'A' + - (coords.leftLargeArcRadius + offset) + ' ' + (coords.leftLargeArcRadius + offset) + ' 0 0 0 ' + - (coords.leftFullExtent + offset) + ' ' + coords.verticalLeftInnerExtent + - 'L' + - (coords.leftFullExtent + offset) + ' ' + (coords.sourceY + coords.leftSmallArcRadius) + - 'A' + - (coords.leftLargeArcRadius + offset) + ' ' + (coords.leftSmallArcRadius + offset) + ' 0 0 0 ' + - coords.leftInnerExtent + ' ' + (coords.sourceY - offset) + - 'L' + - coords.sourceX + ' ' + (coords.sourceY - offset) + - - // Walking back - 'L' + - coords.sourceX + ' ' + (coords.sourceY + offset) + - 'L' + - coords.leftInnerExtent + ' ' + (coords.sourceY + offset) + - 'A' + - (coords.leftLargeArcRadius - offset) + ' ' + (coords.leftSmallArcRadius - offset) + ' 0 0 1 ' + - (coords.leftFullExtent - offset) + ' ' + (coords.sourceY + coords.leftSmallArcRadius) + - 'L' + - (coords.leftFullExtent - offset) + ' ' + coords.verticalLeftInnerExtent + - 'A' + - (coords.leftLargeArcRadius - offset) + ' ' + (coords.leftLargeArcRadius - offset) + ' 0 0 1 ' + - coords.leftInnerExtent + ' ' + (coords.verticalFullExtent - offset) + - 'L' + - coords.rightInnerExtent + ' ' + (coords.verticalFullExtent - offset) + - 'A' + - (coords.rightLargeArcRadius - offset) + ' ' + (coords.rightLargeArcRadius - offset) + ' 0 0 1 ' + - (coords.rightFullExtent + offset) + ' ' + coords.verticalRightInnerExtent + - 'L' + - (coords.rightFullExtent + offset) + ' ' + (coords.targetY + coords.rightSmallArcRadius) + - 'A' + - (coords.rightLargeArcRadius - offset) + ' ' + (coords.rightSmallArcRadius - offset) + ' 0 0 1 ' + - coords.rightInnerExtent + ' ' + (coords.targetY + offset) + - 'L' + - coords.targetX + ' ' + (coords.targetY + offset) + - 'Z'; - } - return pathString; -} - -function linkPath() { - var curvature = 0.5; - function path(d) { - if(d.link.circular) { - return createCircularClosedPathString(d.link); - } else { - var x0 = d.link.source.x1; - var x1 = d.link.target.x0; - var xi = interpolateNumber(x0, x1); - var x2 = xi(curvature); - var x3 = xi(1 - curvature); - var y0a = d.link.y0 - d.link.width / 2; - var y0b = d.link.y0 + d.link.width / 2; - var y1a = d.link.y1 - d.link.width / 2; - var y1b = d.link.y1 + d.link.width / 2; - return 'M' + x0 + ',' + y0a + - 'C' + x2 + ',' + y0a + - ' ' + x3 + ',' + y1a + - ' ' + x1 + ',' + y1a + - 'L' + x1 + ',' + y1b + - 'C' + x3 + ',' + y1b + - ' ' + x2 + ',' + y0b + - ' ' + x0 + ',' + y0b + - 'Z'; - } - } - return path; -} - -function nodeModel(d, n) { - var tc = tinycolor(n.color); - var zoneThicknessPad = c.nodePadAcross; - var zoneLengthPad = d.nodePad / 2; - n.dx = n.x1 - n.x0; - n.dy = n.y1 - n.y0; - var visibleThickness = n.dx; - var visibleLength = Math.max(0.5, n.dy); - - var key = 'node_' + n.pointNumber; - // If it's a group, it's mutable and should be unique - if(n.group) { - key = Lib.randstr(); - } - - // for event data - n.trace = d.trace; - n.curveNumber = d.trace.index; - - return { - index: n.pointNumber, - key: key, - partOfGroup: n.partOfGroup || false, - group: n.group, - traceId: d.key, - trace: d.trace, - node: n, - nodePad: d.nodePad, - nodeLineColor: d.nodeLineColor, - nodeLineWidth: d.nodeLineWidth, - textFont: d.textFont, - size: d.horizontal ? d.height : d.width, - visibleWidth: Math.ceil(visibleThickness), - visibleHeight: visibleLength, - zoneX: -zoneThicknessPad, - zoneY: -zoneLengthPad, - zoneWidth: visibleThickness + 2 * zoneThicknessPad, - zoneHeight: visibleLength + 2 * zoneLengthPad, - labelY: d.horizontal ? n.dy / 2 + 1 : n.dx / 2 + 1, - left: n.originalLayer === 1, - sizeAcross: d.width, - forceLayouts: d.forceLayouts, - horizontal: d.horizontal, - darkBackground: tc.getBrightness() <= 128, - tinyColorHue: Color.tinyRGB(tc), - tinyColorAlpha: tc.getAlpha(), - valueFormat: d.valueFormat, - valueSuffix: d.valueSuffix, - sankey: d.sankey, - graph: d.graph, - arrangement: d.arrangement, - uniqueNodeLabelPathId: [d.guid, d.key, key].join('_'), - interactionState: d.interactionState, - figure: d - }; -} - -// rendering snippets - -function updateNodePositions(sankeyNode) { - sankeyNode - .attr('transform', function(d) { - return 'translate(' + d.node.x0.toFixed(3) + ', ' + (d.node.y0).toFixed(3) + ')'; - }); -} - -function updateNodeShapes(sankeyNode) { - sankeyNode.call(updateNodePositions); -} - -function updateShapes(sankeyNode, sankeyLink) { - sankeyNode.call(updateNodeShapes); - sankeyLink.attr('d', linkPath()); -} - -function sizeNode(rect) { - rect - .attr('width', function(d) {return d.node.x1 - d.node.x0;}) - .attr('height', function(d) {return d.visibleHeight;}); -} - -function salientEnough(d) {return (d.link.width > 1 || d.linkLineWidth > 0);} - -function sankeyTransform(d) { - var offset = 'translate(' + d.translateX + ',' + d.translateY + ')'; - return offset + (d.horizontal ? 'matrix(1 0 0 1 0 0)' : 'matrix(0 1 1 0 0 0)'); -} - -function nodeCentering(d) { - return 'translate(' + (d.horizontal ? 0 : d.labelY) + ' ' + (d.horizontal ? d.labelY : 0) + ')'; -} - -function textGuidePath(d) { - return d3.svg.line()([ - [d.horizontal ? (d.left ? -d.sizeAcross : d.visibleWidth + c.nodeTextOffsetHorizontal) : c.nodeTextOffsetHorizontal, 0], - [d.horizontal ? (d.left ? - c.nodeTextOffsetHorizontal : d.sizeAcross) : d.visibleHeight - c.nodeTextOffsetHorizontal, 0] - ]); -} - -function sankeyInverseTransform(d) {return d.horizontal ? 'matrix(1 0 0 1 0 0)' : 'matrix(0 1 1 0 0 0)';} -function textFlip(d) {return d.horizontal ? 'scale(1 1)' : 'scale(-1 1)';} -function nodeTextColor(d) {return d.darkBackground && !d.horizontal ? 'rgb(255,255,255)' : 'rgb(0,0,0)';} -function nodeTextOffset(d) {return d.horizontal && d.left ? '100%' : '0%';} - -// event handling - -function attachPointerEvents(selection, sankey, eventSet) { - selection - .on('.basic', null) // remove any preexisting handlers - .on('mouseover.basic', function(d) { - if(!d.interactionState.dragInProgress && !d.partOfGroup) { - eventSet.hover(this, d, sankey); - d.interactionState.hovered = [this, d]; - } - }) - .on('mousemove.basic', function(d) { - if(!d.interactionState.dragInProgress && !d.partOfGroup) { - eventSet.follow(this, d); - d.interactionState.hovered = [this, d]; - } - }) - .on('mouseout.basic', function(d) { - if(!d.interactionState.dragInProgress && !d.partOfGroup) { - eventSet.unhover(this, d, sankey); - d.interactionState.hovered = false; - } - }) - .on('click.basic', function(d) { - if(d.interactionState.hovered) { - eventSet.unhover(this, d, sankey); - d.interactionState.hovered = false; - } - if(!d.interactionState.dragInProgress && !d.partOfGroup) { - eventSet.select(this, d, sankey); - } - }); -} - -function attachDragHandler(sankeyNode, sankeyLink, callbacks, gd) { - var dragBehavior = d3.behavior.drag() - .origin(function(d) { - return { - x: d.node.x0 + d.visibleWidth / 2, - y: d.node.y0 + d.visibleHeight / 2 - }; - }) - - .on('dragstart', function(d) { - if(d.arrangement === 'fixed') return; - Lib.ensureSingle(gd._fullLayout._infolayer, 'g', 'dragcover', function(s) { - gd._fullLayout._dragCover = s; - }); - Lib.raiseToTop(this); - d.interactionState.dragInProgress = d.node; - - saveCurrentDragPosition(d.node); - if(d.interactionState.hovered) { - callbacks.nodeEvents.unhover.apply(0, d.interactionState.hovered); - d.interactionState.hovered = false; - } - if(d.arrangement === 'snap') { - var forceKey = d.traceId + '|' + d.key; - if(d.forceLayouts[forceKey]) { - d.forceLayouts[forceKey].alpha(1); - } else { // make a forceLayout if needed - attachForce(sankeyNode, forceKey, d, gd); - } - startForce(sankeyNode, sankeyLink, d, forceKey, gd); - } - }) - - .on('drag', function(d) { - if(d.arrangement === 'fixed') return; - var x = d3.event.x; - var y = d3.event.y; - if(d.arrangement === 'snap') { - d.node.x0 = x - d.visibleWidth / 2; - d.node.x1 = x + d.visibleWidth / 2; - d.node.y0 = y - d.visibleHeight / 2; - d.node.y1 = y + d.visibleHeight / 2; - } else { - if(d.arrangement === 'freeform') { - d.node.x0 = x - d.visibleWidth / 2; - d.node.x1 = x + d.visibleWidth / 2; - } - y = Math.max(0, Math.min(d.size - d.visibleHeight / 2, y)); - d.node.y0 = y - d.visibleHeight / 2; - d.node.y1 = y + d.visibleHeight / 2; - } - - saveCurrentDragPosition(d.node); - if(d.arrangement !== 'snap') { - d.sankey.update(d.graph); - updateShapes(sankeyNode.filter(sameLayer(d)), sankeyLink); - } - }) - - .on('dragend', function(d) { - if(d.arrangement === 'fixed') return; - d.interactionState.dragInProgress = false; - for(var i = 0; i < d.node.childrenNodes.length; i++) { - d.node.childrenNodes[i].x = d.node.x; - d.node.childrenNodes[i].y = d.node.y; - } - if(d.arrangement !== 'snap') persistFinalNodePositions(d, gd); - }); - - sankeyNode - .on('.drag', null) // remove possible previous handlers - .call(dragBehavior); -} - -function attachForce(sankeyNode, forceKey, d, gd) { - // Attach force to nodes in the same column (same x coordinate) - switchToForceFormat(d.graph.nodes); - var nodes = d.graph.nodes - .filter(function(n) {return n.originalX === d.node.originalX;}) - // Filter out children - .filter(function(n) {return !n.partOfGroup;}); - d.forceLayouts[forceKey] = d3Force.forceSimulation(nodes) - .alphaDecay(0) - .force('collide', d3Force.forceCollide() - .radius(function(n) {return n.dy / 2 + d.nodePad / 2;}) - .strength(1) - .iterations(c.forceIterations)) - .force('constrain', snappingForce(sankeyNode, forceKey, nodes, d, gd)) - .stop(); -} - -function startForce(sankeyNode, sankeyLink, d, forceKey, gd) { - window.requestAnimationFrame(function faster() { - var i; - for(i = 0; i < c.forceTicksPerFrame; i++) { - d.forceLayouts[forceKey].tick(); - } - - var nodes = d.graph.nodes; - switchToSankeyFormat(nodes); - - d.sankey.update(d.graph); - updateShapes(sankeyNode.filter(sameLayer(d)), sankeyLink); - - if(d.forceLayouts[forceKey].alpha() > 0) { - window.requestAnimationFrame(faster); - } else { - // Make sure the final x position is equal to its original value - // because the force simulation will have numerical error - var x = d.node.originalX; - d.node.x0 = x - d.visibleWidth / 2; - d.node.x1 = x + d.visibleWidth / 2; - - persistFinalNodePositions(d, gd); - } - }); -} - -function snappingForce(sankeyNode, forceKey, nodes, d) { - return function _snappingForce() { - var maxVelocity = 0; - for(var i = 0; i < nodes.length; i++) { - var n = nodes[i]; - if(n === d.interactionState.dragInProgress) { // constrain node position to the dragging pointer - n.x = n.lastDraggedX; - n.y = n.lastDraggedY; - } else { - n.vx = (n.originalX - n.x) / c.forceTicksPerFrame; // snap to layer - n.y = Math.min(d.size - n.dy / 2, Math.max(n.dy / 2, n.y)); // constrain to extent - } - maxVelocity = Math.max(maxVelocity, Math.abs(n.vx), Math.abs(n.vy)); - } - if(!d.interactionState.dragInProgress && maxVelocity < 0.1 && d.forceLayouts[forceKey].alpha() > 0) { - d.forceLayouts[forceKey].alpha(0); // This will stop the animation loop - } - }; -} - -// basic data utilities - -function persistFinalNodePositions(d, gd) { - var x = []; - var y = []; - for(var i = 0; i < d.graph.nodes.length; i++) { - var nodeX = (d.graph.nodes[i].x0 + d.graph.nodes[i].x1) / 2; - var nodeY = (d.graph.nodes[i].y0 + d.graph.nodes[i].y1) / 2; - x.push(nodeX / d.figure.width); - y.push(nodeY / d.figure.height); - } - Registry.call('_guiRestyle', gd, { - 'node.x': [x], - 'node.y': [y] - }, d.trace.index) - .then(function() { - if(gd._fullLayout._dragCover) gd._fullLayout._dragCover.remove(); - }); -} - -function persistOriginalPlace(nodes) { - var distinctLayerPositions = []; - var i; - for(i = 0; i < nodes.length; i++) { - nodes[i].originalX = (nodes[i].x0 + nodes[i].x1) / 2; - nodes[i].originalY = (nodes[i].y0 + nodes[i].y1) / 2; - if(distinctLayerPositions.indexOf(nodes[i].originalX) === -1) { - distinctLayerPositions.push(nodes[i].originalX); - } - } - distinctLayerPositions.sort(function(a, b) {return a - b;}); - for(i = 0; i < nodes.length; i++) { - nodes[i].originalLayerIndex = distinctLayerPositions.indexOf(nodes[i].originalX); - nodes[i].originalLayer = nodes[i].originalLayerIndex / (distinctLayerPositions.length - 1); - } -} - -function saveCurrentDragPosition(d) { - d.lastDraggedX = d.x0 + d.dx / 2; - d.lastDraggedY = d.y0 + d.dy / 2; -} - -function sameLayer(d) { - return function(n) {return n.node.originalX === d.node.originalX;}; -} - -function switchToForceFormat(nodes) { - // force uses x, y as centers - for(var i = 0; i < nodes.length; i++) { - nodes[i].y = (nodes[i].y0 + nodes[i].y1) / 2; - nodes[i].x = (nodes[i].x0 + nodes[i].x1) / 2; - } -} - -function switchToSankeyFormat(nodes) { - // sankey uses x0, x1, y0, y1 - for(var i = 0; i < nodes.length; i++) { - nodes[i].y0 = nodes[i].y - nodes[i].dy / 2; - nodes[i].y1 = nodes[i].y0 + nodes[i].dy; - - nodes[i].x0 = nodes[i].x - nodes[i].dx / 2; - nodes[i].x1 = nodes[i].x0 + nodes[i].dx; - } -} - -// scene graph -module.exports = function(gd, svg, calcData, layout, callbacks) { - // To prevent animation on first render - var firstRender = false; - Lib.ensureSingle(gd._fullLayout._infolayer, 'g', 'first-render', function() { - firstRender = true; - }); - - // To prevent animation on dragging - var dragcover = gd._fullLayout._dragCover; - - var styledData = calcData - .filter(function(d) {return unwrap(d).trace.visible;}) - .map(sankeyModel.bind(null, layout)); - - var sankey = svg.selectAll('.' + c.cn.sankey) - .data(styledData, keyFun); - - sankey.exit() - .remove(); - - sankey.enter() - .append('g') - .classed(c.cn.sankey, true) - .style('box-sizing', 'content-box') - .style('position', 'absolute') - .style('left', 0) - .style('shape-rendering', 'geometricPrecision') - .style('pointer-events', 'auto') - .attr('transform', sankeyTransform); - - sankey.each(function(d, i) { - gd._fullData[i]._sankey = d; - // Create dragbox if missing - var dragboxClassName = 'bgsankey-' + d.trace.uid + '-' + i; - Lib.ensureSingle(gd._fullLayout._draggers, 'rect', dragboxClassName); - - gd._fullData[i]._bgRect = d3.select('.' + dragboxClassName); - - // Style dragbox - gd._fullData[i]._bgRect - .style('pointer-events', 'all') - .attr('width', d.width) - .attr('height', d.height) - .attr('x', d.translateX) - .attr('y', d.translateY) - .classed('bgsankey', true) - .style({fill: 'transparent', 'stroke-width': 0}); - }); - - sankey.transition() - .ease(c.ease).duration(c.duration) - .attr('transform', sankeyTransform); - - var sankeyLinks = sankey.selectAll('.' + c.cn.sankeyLinks) - .data(repeat, keyFun); - - sankeyLinks.enter() - .append('g') - .classed(c.cn.sankeyLinks, true) - .style('fill', 'none'); - - var sankeyLink = sankeyLinks.selectAll('.' + c.cn.sankeyLink) - .data(function(d) { - var links = d.graph.links; - return links - .filter(function(l) {return l.value;}) - .map(linkModel.bind(null, d)); - }, keyFun); - - sankeyLink - .enter().append('path') - .classed(c.cn.sankeyLink, true) - .call(attachPointerEvents, sankey, callbacks.linkEvents); - - sankeyLink - .style('stroke', function(d) { - return salientEnough(d) ? Color.tinyRGB(tinycolor(d.linkLineColor)) : d.tinyColorHue; - }) - .style('stroke-opacity', function(d) { - return salientEnough(d) ? Color.opacity(d.linkLineColor) : d.tinyColorAlpha; - }) - .style('fill', function(d) { - return d.tinyColorHue; - }) - .style('fill-opacity', function(d) { - return d.tinyColorAlpha; - }) - .style('stroke-width', function(d) { - return salientEnough(d) ? d.linkLineWidth : 1; - }) - .attr('d', linkPath()); - - sankeyLink - .style('opacity', function() { return (gd._context.staticPlot || firstRender || dragcover) ? 1 : 0;}) - .transition() - .ease(c.ease).duration(c.duration) - .style('opacity', 1); - - sankeyLink.exit() - .transition() - .ease(c.ease).duration(c.duration) - .style('opacity', 0) - .remove(); - - var sankeyNodeSet = sankey.selectAll('.' + c.cn.sankeyNodeSet) - .data(repeat, keyFun); - - sankeyNodeSet.enter() - .append('g') - .classed(c.cn.sankeyNodeSet, true); - - sankeyNodeSet - .style('cursor', function(d) { - switch(d.arrangement) { - case 'fixed': return 'default'; - case 'perpendicular': return 'ns-resize'; - default: return 'move'; - } - }); - - var sankeyNode = sankeyNodeSet.selectAll('.' + c.cn.sankeyNode) - .data(function(d) { - var nodes = d.graph.nodes; - persistOriginalPlace(nodes); - return nodes - .map(nodeModel.bind(null, d)); - }, keyFun); - - sankeyNode.enter() - .append('g') - .classed(c.cn.sankeyNode, true) - .call(updateNodePositions) - .style('opacity', function(n) { return ((gd._context.staticPlot || firstRender) && !n.partOfGroup) ? 1 : 0;}); - - sankeyNode - .call(attachPointerEvents, sankey, callbacks.nodeEvents) - .call(attachDragHandler, sankeyLink, callbacks, gd); // has to be here as it binds sankeyLink - - sankeyNode - .transition() - .ease(c.ease).duration(c.duration) - .call(updateNodePositions) - .style('opacity', function(n) { return n.partOfGroup ? 0 : 1;}); - - sankeyNode.exit() - .transition() - .ease(c.ease).duration(c.duration) - .style('opacity', 0) - .remove(); - - var nodeRect = sankeyNode.selectAll('.' + c.cn.nodeRect) - .data(repeat); - - nodeRect.enter() - .append('rect') - .classed(c.cn.nodeRect, true) - .call(sizeNode); - - nodeRect - .style('stroke-width', function(d) {return d.nodeLineWidth;}) - .style('stroke', function(d) {return Color.tinyRGB(tinycolor(d.nodeLineColor));}) - .style('stroke-opacity', function(d) {return Color.opacity(d.nodeLineColor);}) - .style('fill', function(d) {return d.tinyColorHue;}) - .style('fill-opacity', function(d) {return d.tinyColorAlpha;}); - - nodeRect.transition() - .ease(c.ease).duration(c.duration) - .call(sizeNode); - - var nodeCapture = sankeyNode.selectAll('.' + c.cn.nodeCapture) - .data(repeat); - - nodeCapture.enter() - .append('rect') - .classed(c.cn.nodeCapture, true) - .style('fill-opacity', 0); - - nodeCapture - .attr('x', function(d) {return d.zoneX;}) - .attr('y', function(d) {return d.zoneY;}) - .attr('width', function(d) {return d.zoneWidth;}) - .attr('height', function(d) {return d.zoneHeight;}); - - var nodeCentered = sankeyNode.selectAll('.' + c.cn.nodeCentered) - .data(repeat); - - nodeCentered.enter() - .append('g') - .classed(c.cn.nodeCentered, true) - .attr('transform', nodeCentering); - - nodeCentered - .transition() - .ease(c.ease).duration(c.duration) - .attr('transform', nodeCentering); - - var nodeLabelGuide = nodeCentered.selectAll('.' + c.cn.nodeLabelGuide) - .data(repeat); - - nodeLabelGuide.enter() - .append('path') - .classed(c.cn.nodeLabelGuide, true) - .attr('id', function(d) {return d.uniqueNodeLabelPathId;}) - .attr('d', textGuidePath) - .attr('transform', sankeyInverseTransform); - - nodeLabelGuide - .transition() - .ease(c.ease).duration(c.duration) - .attr('d', textGuidePath) - .attr('transform', sankeyInverseTransform); - - var nodeLabel = nodeCentered.selectAll('.' + c.cn.nodeLabel) - .data(repeat); - - nodeLabel.enter() - .append('text') - .classed(c.cn.nodeLabel, true) - .attr('transform', textFlip) - .style('user-select', 'none') - .style('cursor', 'default') - .style('fill', 'black'); - - nodeLabel - .style('text-shadow', function(d) { - return d.horizontal ? '-1px 1px 1px #fff, 1px 1px 1px #fff, 1px -1px 1px #fff, -1px -1px 1px #fff' : 'none'; - }) - .each(function(d) {Drawing.font(nodeLabel, d.textFont);}); - - nodeLabel - .transition() - .ease(c.ease).duration(c.duration) - .attr('transform', textFlip); - - var nodeLabelTextPath = nodeLabel.selectAll('.' + c.cn.nodeLabelTextPath) - .data(repeat); - - nodeLabelTextPath.enter() - .append('textPath') - .classed(c.cn.nodeLabelTextPath, true) - .attr('alignment-baseline', 'middle') - .attr('xlink:href', function(d) {return '#' + d.uniqueNodeLabelPathId;}) - .attr('startOffset', nodeTextOffset) - .style('fill', nodeTextColor); - - nodeLabelTextPath - .text(function(d) {return d.horizontal || d.node.dy > 5 ? d.node.label : '';}) - .attr('text-anchor', function(d) {return d.horizontal && d.left ? 'end' : 'start';}); - - nodeLabelTextPath - .transition() - .ease(c.ease).duration(c.duration) - .attr('startOffset', nodeTextOffset) - .style('fill', nodeTextColor); -}; - -},{"../../components/color":593,"../../components/drawing":614,"../../lib":719,"../../lib/gup":717,"../../registry":847,"./constants":1105,"@plotly/d3-sankey":54,"@plotly/d3-sankey-circular":53,"d3":163,"d3-force":156,"d3-interpolate":158,"tinycolor2":537}],1110:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function selectPoints(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var selection = []; - var fullData = cd[0].trace; - - var nodes = fullData._sankey.graph.nodes; - - for(var i = 0; i < nodes.length; i++) { - var node = nodes[i]; - if(node.partOfGroup) continue; // Those are invisible - - // Position of node's centroid - var pos = [(node.x0 + node.x1) / 2, (node.y0 + node.y1) / 2]; - - // Swap x and y if trace is vertical - if(fullData.orientation === 'v') pos.reverse(); - - if(selectionTester && selectionTester.contains(pos, false, i, searchInfo)) { - selection.push({ - pointNumber: node.pointNumber - // TODO: add eventData - }); - } - } - return selection; -}; - -},{}],1111:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - - -// arrayOk attributes, merge them into calcdata array -module.exports = function arraysToCalcdata(cd, trace) { - // so each point knows which index it originally came from - for(var i = 0; i < cd.length; i++) cd[i].i = i; - - Lib.mergeArray(trace.text, cd, 'tx'); - Lib.mergeArray(trace.hovertext, cd, 'htx'); - Lib.mergeArray(trace.customdata, cd, 'data'); - Lib.mergeArray(trace.textposition, cd, 'tp'); - if(trace.textfont) { - Lib.mergeArrayCastPositive(trace.textfont.size, cd, 'ts'); - Lib.mergeArray(trace.textfont.color, cd, 'tc'); - Lib.mergeArray(trace.textfont.family, cd, 'tf'); - } - - var marker = trace.marker; - if(marker) { - Lib.mergeArrayCastPositive(marker.size, cd, 'ms'); - Lib.mergeArrayCastPositive(marker.opacity, cd, 'mo'); - Lib.mergeArray(marker.symbol, cd, 'mx'); - Lib.mergeArray(marker.color, cd, 'mc'); - - var markerLine = marker.line; - if(marker.line) { - Lib.mergeArray(markerLine.color, cd, 'mlc'); - Lib.mergeArrayCastPositive(markerLine.width, cd, 'mlw'); - } - - var markerGradient = marker.gradient; - if(markerGradient && markerGradient.type !== 'none') { - Lib.mergeArray(markerGradient.type, cd, 'mgt'); - Lib.mergeArray(markerGradient.color, cd, 'mgc'); - } - } -}; - -},{"../../lib":719}],1112:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var fontAttrs = _dereq_('../../plots/font_attributes'); -var dash = _dereq_('../../components/drawing/attributes').dash; - -var Drawing = _dereq_('../../components/drawing'); -var constants = _dereq_('./constants'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = { - x: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - anim: true, - - }, - x0: { - valType: 'any', - dflt: 0, - - editType: 'calc+clearAxisTypes', - anim: true, - - }, - dx: { - valType: 'number', - dflt: 1, - - editType: 'calc', - anim: true, - - }, - y: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - anim: true, - - }, - y0: { - valType: 'any', - dflt: 0, - - editType: 'calc+clearAxisTypes', - anim: true, - - }, - dy: { - valType: 'number', - dflt: 1, - - editType: 'calc', - anim: true, - - }, - - stackgroup: { - valType: 'string', - - dflt: '', - editType: 'calc', - - }, - orientation: { - valType: 'enumerated', - - values: ['v', 'h'], - editType: 'calc', - - }, - groupnorm: { - valType: 'enumerated', - values: ['', 'fraction', 'percent'], - dflt: '', - - editType: 'calc', - - }, - stackgaps: { - valType: 'enumerated', - values: ['infer zero', 'interpolate'], - dflt: 'infer zero', - - editType: 'calc', - - }, - - text: { - valType: 'string', - - dflt: '', - arrayOk: true, - editType: 'calc', - - }, - hovertext: { - valType: 'string', - - dflt: '', - arrayOk: true, - editType: 'style', - - }, - mode: { - valType: 'flaglist', - flags: ['lines', 'markers', 'text'], - extras: ['none'], - - editType: 'calc', - - }, - hoveron: { - valType: 'flaglist', - flags: ['points', 'fills'], - - editType: 'style', - - }, - hovertemplate: hovertemplateAttrs({}, { - keys: constants.eventDataKeys - }), - line: { - color: { - valType: 'color', - - editType: 'style', - anim: true, - - }, - width: { - valType: 'number', - min: 0, - dflt: 2, - - editType: 'style', - anim: true, - - }, - shape: { - valType: 'enumerated', - values: ['linear', 'spline', 'hv', 'vh', 'hvh', 'vhv'], - dflt: 'linear', - - editType: 'plot', - - }, - smoothing: { - valType: 'number', - min: 0, - max: 1.3, - dflt: 1, - - editType: 'plot', - - }, - dash: extendFlat({}, dash, {editType: 'style'}), - simplify: { - valType: 'boolean', - dflt: true, - - editType: 'plot', - - }, - editType: 'plot' - }, - - connectgaps: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - cliponaxis: { - valType: 'boolean', - dflt: true, - - editType: 'plot', - - }, - - fill: { - valType: 'enumerated', - values: ['none', 'tozeroy', 'tozerox', 'tonexty', 'tonextx', 'toself', 'tonext'], - - editType: 'calc', - - }, - fillcolor: { - valType: 'color', - - editType: 'style', - anim: true, - - }, - marker: extendFlat({ - symbol: { - valType: 'enumerated', - values: Drawing.symbolList, - dflt: 'circle', - arrayOk: true, - - editType: 'style', - - }, - opacity: { - valType: 'number', - min: 0, - max: 1, - arrayOk: true, - - editType: 'style', - anim: true, - - }, - size: { - valType: 'number', - min: 0, - dflt: 6, - arrayOk: true, - - editType: 'calc', - anim: true, - - }, - maxdisplayed: { - valType: 'number', - min: 0, - dflt: 0, - - editType: 'plot', - - }, - sizeref: { - valType: 'number', - dflt: 1, - - editType: 'calc', - - }, - sizemin: { - valType: 'number', - min: 0, - dflt: 0, - - editType: 'calc', - - }, - sizemode: { - valType: 'enumerated', - values: ['diameter', 'area'], - dflt: 'diameter', - - editType: 'calc', - - }, - - line: extendFlat({ - width: { - valType: 'number', - min: 0, - arrayOk: true, - - editType: 'style', - anim: true, - - }, - editType: 'calc' - }, - colorScaleAttrs('marker.line', {anim: true}) - ), - gradient: { - type: { - valType: 'enumerated', - values: ['radial', 'horizontal', 'vertical', 'none'], - arrayOk: true, - dflt: 'none', - - editType: 'calc', - - }, - color: { - valType: 'color', - arrayOk: true, - - editType: 'calc', - - }, - editType: 'calc' - }, - editType: 'calc' - }, - colorScaleAttrs('marker', {anim: true}) - ), - selected: { - marker: { - opacity: { - valType: 'number', - min: 0, - max: 1, - - editType: 'style', - - }, - color: { - valType: 'color', - - editType: 'style', - - }, - size: { - valType: 'number', - min: 0, - - editType: 'style', - - }, - editType: 'style' - }, - textfont: { - color: { - valType: 'color', - - editType: 'style', - - }, - editType: 'style' - }, - editType: 'style' - }, - unselected: { - marker: { - opacity: { - valType: 'number', - min: 0, - max: 1, - - editType: 'style', - - }, - color: { - valType: 'color', - - editType: 'style', - - }, - size: { - valType: 'number', - min: 0, - - editType: 'style', - - }, - editType: 'style' - }, - textfont: { - color: { - valType: 'color', - - editType: 'style', - - }, - editType: 'style' - }, - editType: 'style' - }, - - textposition: { - valType: 'enumerated', - values: [ - 'top left', 'top center', 'top right', - 'middle left', 'middle center', 'middle right', - 'bottom left', 'bottom center', 'bottom right' - ], - dflt: 'middle center', - arrayOk: true, - - editType: 'calc', - - }, - textfont: fontAttrs({ - editType: 'calc', - colorEditType: 'style', - arrayOk: true, - - }), - - r: { - valType: 'data_array', - editType: 'calc', - - }, - t: { - valType: 'data_array', - editType: 'calc', - - } -}; - -},{"../../components/colorscale/attributes":600,"../../components/drawing":614,"../../components/drawing/attributes":613,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/font_attributes":793,"./constants":1116}],1113:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var Lib = _dereq_('../../lib'); - -var Axes = _dereq_('../../plots/cartesian/axes'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -var subTypes = _dereq_('./subtypes'); -var calcColorscale = _dereq_('./colorscale_calc'); -var arraysToCalcdata = _dereq_('./arrays_to_calcdata'); -var calcSelection = _dereq_('./calc_selection'); - -function calc(gd, trace) { - var fullLayout = gd._fullLayout; - var xa = Axes.getFromId(gd, trace.xaxis || 'x'); - var ya = Axes.getFromId(gd, trace.yaxis || 'y'); - var x = xa.makeCalcdata(trace, 'x'); - var y = ya.makeCalcdata(trace, 'y'); - var serieslen = trace._length; - var cd = new Array(serieslen); - var ids = trace.ids; - var stackGroupOpts = getStackOpts(trace, fullLayout, xa, ya); - var interpolateGaps = false; - var isV, i, j, k, interpolate, vali; - - setFirstScatter(fullLayout, trace); - - var xAttr = 'x'; - var yAttr = 'y'; - var posAttr; - if(stackGroupOpts) { - Lib.pushUnique(stackGroupOpts.traceIndices, trace._expandedIndex); - isV = stackGroupOpts.orientation === 'v'; - - // size, like we use for bar - if(isV) { - yAttr = 's'; - posAttr = 'x'; - } else { - xAttr = 's'; - posAttr = 'y'; - } - interpolate = stackGroupOpts.stackgaps === 'interpolate'; - } else { - var ppad = calcMarkerSize(trace, serieslen); - calcAxisExpansion(gd, trace, xa, ya, x, y, ppad); - } - - for(i = 0; i < serieslen; i++) { - var cdi = cd[i] = {}; - var xValid = isNumeric(x[i]); - var yValid = isNumeric(y[i]); - if(xValid && yValid) { - cdi[xAttr] = x[i]; - cdi[yAttr] = y[i]; - } else if(stackGroupOpts && (isV ? xValid : yValid)) { - // if we're stacking we need to hold on to all valid positions - // even with invalid sizes - - cdi[posAttr] = isV ? x[i] : y[i]; - cdi.gap = true; - if(interpolate) { - cdi.s = BADNUM; - interpolateGaps = true; - } else { - cdi.s = 0; - } - } else { - cdi[xAttr] = cdi[yAttr] = BADNUM; - } - - if(ids) { - cdi.id = String(ids[i]); - } - } - - arraysToCalcdata(cd, trace); - calcColorscale(gd, trace); - calcSelection(cd, trace); - - if(stackGroupOpts) { - // remove bad positions and sort - // note that original indices get added to cd in arraysToCalcdata - i = 0; - while(i < cd.length) { - if(cd[i][posAttr] === BADNUM) { - cd.splice(i, 1); - } else i++; - } - - Lib.sort(cd, function(a, b) { - return (a[posAttr] - b[posAttr]) || (a.i - b.i); - }); - - if(interpolateGaps) { - // first fill the beginning with constant from the first point - i = 0; - while(i < cd.length - 1 && cd[i].gap) { - i++; - } - vali = cd[i].s; - if(!vali) vali = cd[i].s = 0; // in case of no data AT ALL in this trace - use 0 - for(j = 0; j < i; j++) { - cd[j].s = vali; - } - // then fill the end with constant from the last point - k = cd.length - 1; - while(k > i && cd[k].gap) { - k--; - } - vali = cd[k].s; - for(j = cd.length - 1; j > k; j--) { - cd[j].s = vali; - } - // now interpolate internal gaps linearly - while(i < k) { - i++; - if(cd[i].gap) { - j = i + 1; - while(cd[j].gap) { - j++; - } - var pos0 = cd[i - 1][posAttr]; - var size0 = cd[i - 1].s; - var m = (cd[j].s - size0) / (cd[j][posAttr] - pos0); - while(i < j) { - cd[i].s = size0 + (cd[i][posAttr] - pos0) * m; - i++; - } - } - } - } - } - - return cd; -} - -function calcAxisExpansion(gd, trace, xa, ya, x, y, ppad) { - var serieslen = trace._length; - var fullLayout = gd._fullLayout; - var xId = xa._id; - var yId = ya._id; - var firstScatter = fullLayout._firstScatter[firstScatterGroup(trace)] === trace.uid; - var stackOrientation = (getStackOpts(trace, fullLayout, xa, ya) || {}).orientation; - var fill = trace.fill; - - // cancel minimum tick spacings (only applies to bars and boxes) - xa._minDtick = 0; - ya._minDtick = 0; - - // check whether bounds should be tight, padded, extended to zero... - // most cases both should be padded on both ends, so start with that. - var xOptions = {padded: true}; - var yOptions = {padded: true}; - - if(ppad) { - xOptions.ppad = yOptions.ppad = ppad; - } - - // TODO: text size - - var openEnded = serieslen < 2 || (x[0] !== x[serieslen - 1]) || (y[0] !== y[serieslen - 1]); - - if(openEnded && ( - (fill === 'tozerox') || - ((fill === 'tonextx') && (firstScatter || stackOrientation === 'h')) - )) { - // include zero (tight) and extremes (padded) if fill to zero - // (unless the shape is closed, then it's just filling the shape regardless) - - xOptions.tozero = true; - } else if(!(trace.error_y || {}).visible && ( - // if no error bars, markers or text, or fill to y=0 remove x padding - - (fill === 'tonexty' || fill === 'tozeroy') || - (!subTypes.hasMarkers(trace) && !subTypes.hasText(trace)) - )) { - xOptions.padded = false; - xOptions.ppad = 0; - } - - if(openEnded && ( - (fill === 'tozeroy') || - ((fill === 'tonexty') && (firstScatter || stackOrientation === 'v')) - )) { - // now check for y - rather different logic, though still mostly padded both ends - // include zero (tight) and extremes (padded) if fill to zero - // (unless the shape is closed, then it's just filling the shape regardless) - - yOptions.tozero = true; - } else if(fill === 'tonextx' || fill === 'tozerox') { - // tight y: any x fill - - yOptions.padded = false; - } - - // N.B. asymmetric splom traces call this with blank {} xa or ya - if(xId) trace._extremes[xId] = Axes.findExtremes(xa, x, xOptions); - if(yId) trace._extremes[yId] = Axes.findExtremes(ya, y, yOptions); -} - -function calcMarkerSize(trace, serieslen) { - if(!subTypes.hasMarkers(trace)) return; - - // Treat size like x or y arrays --- Run d2c - // this needs to go before ppad computation - var marker = trace.marker; - var sizeref = 1.6 * (trace.marker.sizeref || 1); - var markerTrans; - - if(trace.marker.sizemode === 'area') { - markerTrans = function(v) { - return Math.max(Math.sqrt((v || 0) / sizeref), 3); - }; - } else { - markerTrans = function(v) { - return Math.max((v || 0) / sizeref, 3); - }; - } - - if(Lib.isArrayOrTypedArray(marker.size)) { - // I tried auto-type but category and dates dont make much sense. - var ax = {type: 'linear'}; - Axes.setConvert(ax); - - var s = ax.makeCalcdata(trace.marker, 'size'); - - var sizeOut = new Array(serieslen); - for(var i = 0; i < serieslen; i++) { - sizeOut[i] = markerTrans(s[i]); - } - return sizeOut; - } else { - return markerTrans(marker.size); - } -} - -/** - * mark the first scatter trace for each subplot - * note that scatter and scattergl each get their own first trace - * note also that I'm doing this during calc rather than supplyDefaults - * so I don't need to worry about transforms, but if we ever do - * per-trace calc this will get confused. - */ -function setFirstScatter(fullLayout, trace) { - var group = firstScatterGroup(trace); - var firstScatter = fullLayout._firstScatter; - if(!firstScatter[group]) firstScatter[group] = trace.uid; -} - -function firstScatterGroup(trace) { - var stackGroup = trace.stackgroup; - return trace.xaxis + trace.yaxis + trace.type + - (stackGroup ? '-' + stackGroup : ''); -} - -function getStackOpts(trace, fullLayout, xa, ya) { - var stackGroup = trace.stackgroup; - if(!stackGroup) return; - var stackOpts = fullLayout._scatterStackOpts[xa._id + ya._id][stackGroup]; - var stackAx = stackOpts.orientation === 'v' ? ya : xa; - // Allow stacking only on numeric axes - // calc is a little late to be figuring this out, but during supplyDefaults - // we don't know the axis type yet - if(stackAx.type === 'linear' || stackAx.type === 'log') return stackOpts; -} - -module.exports = { - calc: calc, - calcMarkerSize: calcMarkerSize, - calcAxisExpansion: calcAxisExpansion, - setFirstScatter: setFirstScatter, - getStackOpts: getStackOpts -}; - -},{"../../constants/numerical":695,"../../lib":719,"../../plots/cartesian/axes":767,"./arrays_to_calcdata":1111,"./calc_selection":1114,"./colorscale_calc":1115,"./subtypes":1135,"fast-isnumeric":225}],1114:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -module.exports = function calcSelection(cd, trace) { - if(Lib.isArrayOrTypedArray(trace.selectedpoints)) { - Lib.tagSelected(cd, trace); - } -}; - -},{"../../lib":719}],1115:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale; -var calcColorscale = _dereq_('../../components/colorscale/calc'); - -var subTypes = _dereq_('./subtypes'); - -module.exports = function calcMarkerColorscale(gd, trace) { - if(subTypes.hasLines(trace) && hasColorscale(trace, 'line')) { - calcColorscale(gd, trace, { - vals: trace.line.color, - containerStr: 'line', - cLetter: 'c' - }); - } - - if(subTypes.hasMarkers(trace)) { - if(hasColorscale(trace, 'marker')) { - calcColorscale(gd, trace, { - vals: trace.marker.color, - containerStr: 'marker', - cLetter: 'c' - }); - } - if(hasColorscale(trace, 'marker.line')) { - calcColorscale(gd, trace, { - vals: trace.marker.line.color, - containerStr: 'marker.line', - cLetter: 'c' - }); - } - } -}; - -},{"../../components/colorscale/calc":601,"../../components/colorscale/helpers":604,"./subtypes":1135}],1116:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = { - PTS_LINESONLY: 20, - - // fixed parameters of clustering and clipping algorithms - - // fraction of clustering tolerance "so close we don't even consider it a new point" - minTolerance: 0.2, - // how fast does clustering tolerance increase as you get away from the visible region - toleranceGrowth: 10, - - // number of viewport sizes away from the visible region - // at which we clip all lines to the perimeter - maxScreensAway: 20, - - eventDataKeys: [] -}; - -},{}],1117:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var calc = _dereq_('./calc'); - -/* - * Scatter stacking & normalization calculations - * runs per subplot, and can handle multiple stacking groups - */ - -module.exports = function crossTraceCalc(gd, plotinfo) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - var subplot = xa._id + ya._id; - - var subplotStackOpts = gd._fullLayout._scatterStackOpts[subplot]; - if(!subplotStackOpts) return; - - var calcTraces = gd.calcdata; - - var i, j, k, i2, cd, cd0, posj, sumj, norm; - var groupOpts, interpolate, groupnorm, posAttr, valAttr; - var hasAnyBlanks; - - for(var stackGroup in subplotStackOpts) { - groupOpts = subplotStackOpts[stackGroup]; - var indices = groupOpts.traceIndices; - - // can get here with no indices if the stack axis is non-numeric - if(!indices.length) continue; - - interpolate = groupOpts.stackgaps === 'interpolate'; - groupnorm = groupOpts.groupnorm; - if(groupOpts.orientation === 'v') { - posAttr = 'x'; - valAttr = 'y'; - } else { - posAttr = 'y'; - valAttr = 'x'; - } - hasAnyBlanks = new Array(indices.length); - for(i = 0; i < hasAnyBlanks.length; i++) { - hasAnyBlanks[i] = false; - } - - // Collect the complete set of all positions across ALL traces. - // Start with the first trace, then interleave items from later traces - // as needed. - // Fill in mising items as we go. - cd0 = calcTraces[indices[0]]; - var allPositions = new Array(cd0.length); - for(i = 0; i < cd0.length; i++) { - allPositions[i] = cd0[i][posAttr]; - } - - for(i = 1; i < indices.length; i++) { - cd = calcTraces[indices[i]]; - - for(j = k = 0; j < cd.length; j++) { - posj = cd[j][posAttr]; - for(; posj > allPositions[k] && k < allPositions.length; k++) { - // the current trace is missing a position from some previous trace(s) - insertBlank(cd, j, allPositions[k], i, hasAnyBlanks, interpolate, posAttr); - j++; - } - if(posj !== allPositions[k]) { - // previous trace(s) are missing a position from the current trace - for(i2 = 0; i2 < i; i2++) { - insertBlank(calcTraces[indices[i2]], k, posj, i2, hasAnyBlanks, interpolate, posAttr); - } - allPositions.splice(k, 0, posj); - } - k++; - } - for(; k < allPositions.length; k++) { - insertBlank(cd, j, allPositions[k], i, hasAnyBlanks, interpolate, posAttr); - j++; - } - } - - var serieslen = allPositions.length; - - // stack (and normalize)! - for(j = 0; j < cd0.length; j++) { - sumj = cd0[j][valAttr] = cd0[j].s; - for(i = 1; i < indices.length; i++) { - cd = calcTraces[indices[i]]; - cd[0].trace._rawLength = cd[0].trace._length; - cd[0].trace._length = serieslen; - sumj += cd[j].s; - cd[j][valAttr] = sumj; - } - - if(groupnorm) { - norm = ((groupnorm === 'fraction') ? sumj : (sumj / 100)) || 1; - for(i = 0; i < indices.length; i++) { - var cdj = calcTraces[indices[i]][j]; - cdj[valAttr] /= norm; - cdj.sNorm = cdj.s / norm; - } - } - } - - // autorange - for(i = 0; i < indices.length; i++) { - cd = calcTraces[indices[i]]; - var trace = cd[0].trace; - var ppad = calc.calcMarkerSize(trace, trace._rawLength); - var arrayPad = Array.isArray(ppad); - if((ppad && hasAnyBlanks[i]) || arrayPad) { - var ppadRaw = ppad; - ppad = new Array(serieslen); - for(j = 0; j < serieslen; j++) { - ppad[j] = cd[j].gap ? 0 : (arrayPad ? ppadRaw[cd[j].i] : ppadRaw); - } - } - var x = new Array(serieslen); - var y = new Array(serieslen); - for(j = 0; j < serieslen; j++) { - x[j] = cd[j].x; - y[j] = cd[j].y; - } - calc.calcAxisExpansion(gd, trace, xa, ya, x, y, ppad); - - // while we're here (in a loop over all traces in the stack) - // record the orientation, so hover can find it easily - cd[0].t.orientation = groupOpts.orientation; - } - } -}; - -function insertBlank(calcTrace, index, position, traceIndex, hasAnyBlanks, interpolate, posAttr) { - hasAnyBlanks[traceIndex] = true; - var newEntry = { - i: null, - gap: true, - s: 0 - }; - newEntry[posAttr] = position; - calcTrace.splice(index, 0, newEntry); - // Even if we're not interpolating, if one trace has multiple - // values at the same position and this trace only has one value there, - // we just duplicate that one value rather than insert a zero. - // We also make it look like a real point - because it's ambiguous which - // one really is the real one! - if(index && position === calcTrace[index - 1][posAttr]) { - var prevEntry = calcTrace[index - 1]; - newEntry.s = prevEntry.s; - // TODO is it going to cause any problems to have multiple - // calcdata points with the same index? - newEntry.i = prevEntry.i; - newEntry.gap = prevEntry.gap; - } else if(interpolate) { - newEntry.s = getInterp(calcTrace, index, position, posAttr); - } - if(!index) { - // t and trace need to stay on the first cd entry - calcTrace[0].t = calcTrace[1].t; - calcTrace[0].trace = calcTrace[1].trace; - delete calcTrace[1].t; - delete calcTrace[1].trace; - } -} - -function getInterp(calcTrace, index, position, posAttr) { - var pt0 = calcTrace[index - 1]; - var pt1 = calcTrace[index + 1]; - if(!pt1) return pt0.s; - if(!pt0) return pt1.s; - return pt0.s + (pt1.s - pt0.s) * (position - pt0[posAttr]) / (pt1[posAttr] - pt0[posAttr]); -} - -},{"./calc":1113}],1118:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -// remove opacity for any trace that has a fill or is filled to -module.exports = function crossTraceDefaults(fullData) { - for(var i = 0; i < fullData.length; i++) { - var tracei = fullData[i]; - if(tracei.type !== 'scatter') continue; - - var filli = tracei.fill; - if(filli === 'none' || filli === 'toself') continue; - - tracei.opacity = undefined; - - if(filli === 'tonexty' || filli === 'tonextx') { - for(var j = i - 1; j >= 0; j--) { - var tracej = fullData[j]; - - if((tracej.type === 'scatter') && - (tracej.xaxis === tracei.xaxis) && - (tracej.yaxis === tracei.yaxis)) { - tracej.opacity = undefined; - break; - } - } - } - } -}; - -},{}],1119:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); - -var attributes = _dereq_('./attributes'); -var constants = _dereq_('./constants'); -var subTypes = _dereq_('./subtypes'); -var handleXYDefaults = _dereq_('./xy_defaults'); -var handleStackDefaults = _dereq_('./stack_defaults'); -var handleMarkerDefaults = _dereq_('./marker_defaults'); -var handleLineDefaults = _dereq_('./line_defaults'); -var handleLineShapeDefaults = _dereq_('./line_shape_defaults'); -var handleTextDefaults = _dereq_('./text_defaults'); -var handleFillColorDefaults = _dereq_('./fillcolor_defaults'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleXYDefaults(traceIn, traceOut, layout, coerce); - if(!len) traceOut.visible = false; - - if(!traceOut.visible) return; - - var stackGroupOpts = handleStackDefaults(traceIn, traceOut, layout, coerce); - - var defaultMode = !stackGroupOpts && (len < constants.PTS_LINESONLY) ? - 'lines+markers' : 'lines'; - coerce('text'); - coerce('hovertext'); - coerce('mode', defaultMode); - - if(subTypes.hasLines(traceOut)) { - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - handleLineShapeDefaults(traceIn, traceOut, coerce); - coerce('connectgaps'); - coerce('line.simplify'); - } - - if(subTypes.hasMarkers(traceOut)) { - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); - } - - if(subTypes.hasText(traceOut)) { - handleTextDefaults(traceIn, traceOut, layout, coerce); - } - - var dfltHoverOn = []; - - if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) { - coerce('cliponaxis'); - coerce('marker.maxdisplayed'); - dfltHoverOn.push('points'); - } - - // It's possible for this default to be changed by a later trace. - // We handle that case in some hacky code inside handleStackDefaults. - coerce('fill', stackGroupOpts ? stackGroupOpts.fillDflt : 'none'); - if(traceOut.fill !== 'none') { - handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); - if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); - } - - var lineColor = (traceOut.line || {}).color; - var markerColor = (traceOut.marker || {}).color; - - if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') { - dfltHoverOn.push('fills'); - } - coerce('hoveron', dfltHoverOn.join('+') || 'points'); - if(traceOut.hoveron !== 'fills') coerce('hovertemplate'); - var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || markerColor || defaultColor, {axis: 'y'}); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || markerColor || defaultColor, {axis: 'x', inherit: 'y'}); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -},{"../../lib":719,"../../registry":847,"./attributes":1112,"./constants":1116,"./fillcolor_defaults":1120,"./line_defaults":1124,"./line_shape_defaults":1126,"./marker_defaults":1130,"./stack_defaults":1133,"./subtypes":1135,"./text_defaults":1136,"./xy_defaults":1137}],1120:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Color = _dereq_('../../components/color'); -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; - -module.exports = function fillColorDefaults(traceIn, traceOut, defaultColor, coerce) { - var inheritColorFromMarker = false; - - if(traceOut.marker) { - // don't try to inherit a color array - var markerColor = traceOut.marker.color; - var markerLineColor = (traceOut.marker.line || {}).color; - - if(markerColor && !isArrayOrTypedArray(markerColor)) { - inheritColorFromMarker = markerColor; - } else if(markerLineColor && !isArrayOrTypedArray(markerLineColor)) { - inheritColorFromMarker = markerLineColor; - } - } - - coerce('fillcolor', Color.addOpacity( - (traceOut.line || {}).color || - inheritColorFromMarker || - defaultColor, 0.5 - )); -}; - -},{"../../components/color":593,"../../lib":719}],1121:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Color = _dereq_('../../components/color'); -var subtypes = _dereq_('./subtypes'); - - -module.exports = function getTraceColor(trace, di) { - var lc, tc; - - // TODO: text modes - - if(trace.mode === 'lines') { - lc = trace.line.color; - return (lc && Color.opacity(lc)) ? - lc : trace.fillcolor; - } else if(trace.mode === 'none') { - return trace.fill ? trace.fillcolor : ''; - } else { - var mc = di.mcc || (trace.marker || {}).color; - var mlc = di.mlcc || ((trace.marker || {}).line || {}).color; - - tc = (mc && Color.opacity(mc)) ? mc : - (mlc && Color.opacity(mlc) && - (di.mlw || ((trace.marker || {}).line || {}).width)) ? mlc : ''; - - if(tc) { - // make sure the points aren't TOO transparent - if(Color.opacity(tc) < 0.3) { - return Color.addOpacity(tc, 0.3); - } else return tc; - } else { - lc = (trace.line || {}).color; - return (lc && Color.opacity(lc) && - subtypes.hasLines(trace) && trace.line.width) ? - lc : trace.fillcolor; - } - } -}; - -},{"../../components/color":593,"./subtypes":1135}],1122:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Fx = _dereq_('../../components/fx'); -var Registry = _dereq_('../../registry'); -var getTraceColor = _dereq_('./get_trace_color'); -var Color = _dereq_('../../components/color'); -var fillText = Lib.fillText; - -module.exports = function hoverPoints(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var trace = cd[0].trace; - var xa = pointData.xa; - var ya = pointData.ya; - var xpx = xa.c2p(xval); - var ypx = ya.c2p(yval); - var pt = [xpx, ypx]; - var hoveron = trace.hoveron || ''; - var minRad = (trace.mode.indexOf('markers') !== -1) ? 3 : 0.5; - - // look for points to hover on first, then take fills only if we - // didn't find a point - if(hoveron.indexOf('points') !== -1) { - var dx = function(di) { - // dx and dy are used in compare modes - here we want to always - // prioritize the closest data point, at least as long as markers are - // the same size or nonexistent, but still try to prioritize small markers too. - var rad = Math.max(3, di.mrc || 0); - var kink = 1 - 1 / rad; - var dxRaw = Math.abs(xa.c2p(di.x) - xpx); - var d = (dxRaw < rad) ? (kink * dxRaw / rad) : (dxRaw - rad + kink); - return d; - }; - var dy = function(di) { - var rad = Math.max(3, di.mrc || 0); - var kink = 1 - 1 / rad; - var dyRaw = Math.abs(ya.c2p(di.y) - ypx); - return (dyRaw < rad) ? (kink * dyRaw / rad) : (dyRaw - rad + kink); - }; - var dxy = function(di) { - // scatter points: d.mrc is the calculated marker radius - // adjust the distance so if you're inside the marker it - // always will show up regardless of point size, but - // prioritize smaller points - var rad = Math.max(minRad, di.mrc || 0); - var dx = xa.c2p(di.x) - xpx; - var dy = ya.c2p(di.y) - ypx; - return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - minRad / rad); - }; - var distfn = Fx.getDistanceFunction(hovermode, dx, dy, dxy); - - Fx.getClosest(cd, distfn, pointData); - - // skip the rest (for this trace) if we didn't find a close point - if(pointData.index !== false) { - // the closest data point - var di = cd[pointData.index]; - var xc = xa.c2p(di.x, true); - var yc = ya.c2p(di.y, true); - var rad = di.mrc || 1; - - // now we're done using the whole `calcdata` array, replace the - // index with the original index (in case of inserted point from - // stacked area) - pointData.index = di.i; - - var orientation = cd[0].t.orientation; - // TODO: for scatter and bar, option to show (sub)totals and - // raw data? Currently stacked and/or normalized bars just show - // the normalized individual sizes, so that's what I'm doing here - // for now. - var sizeVal = orientation && (di.sNorm || di.s); - var xLabelVal = (orientation === 'h') ? sizeVal : di.x; - var yLabelVal = (orientation === 'v') ? sizeVal : di.y; - - Lib.extendFlat(pointData, { - color: getTraceColor(trace, di), - - x0: xc - rad, - x1: xc + rad, - xLabelVal: xLabelVal, - - y0: yc - rad, - y1: yc + rad, - yLabelVal: yLabelVal, - - spikeDistance: dxy(di), - hovertemplate: trace.hovertemplate - }); - - fillText(di, trace, pointData); - Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, pointData); - - return [pointData]; - } - } - - // even if hoveron is 'fills', only use it if we have polygons too - if(hoveron.indexOf('fills') !== -1 && trace._polygons) { - var polygons = trace._polygons; - var polygonsIn = []; - var inside = false; - var xmin = Infinity; - var xmax = -Infinity; - var ymin = Infinity; - var ymax = -Infinity; - - var i, j, polygon, pts, xCross, x0, x1, y0, y1; - - for(i = 0; i < polygons.length; i++) { - polygon = polygons[i]; - // TODO: this is not going to work right for curved edges, it will - // act as though they're straight. That's probably going to need - // the elements themselves to capture the events. Worth it? - if(polygon.contains(pt)) { - inside = !inside; - // TODO: need better than just the overall bounding box - polygonsIn.push(polygon); - ymin = Math.min(ymin, polygon.ymin); - ymax = Math.max(ymax, polygon.ymax); - } - } - - if(inside) { - // constrain ymin/max to the visible plot, so the label goes - // at the middle of the piece you can see - ymin = Math.max(ymin, 0); - ymax = Math.min(ymax, ya._length); - - // find the overall left-most and right-most points of the - // polygon(s) we're inside at their combined vertical midpoint. - // This is where we will draw the hover label. - // Note that this might not be the vertical midpoint of the - // whole trace, if it's disjoint. - var yAvg = (ymin + ymax) / 2; - for(i = 0; i < polygonsIn.length; i++) { - pts = polygonsIn[i].pts; - for(j = 1; j < pts.length; j++) { - y0 = pts[j - 1][1]; - y1 = pts[j][1]; - if((y0 > yAvg) !== (y1 >= yAvg)) { - x0 = pts[j - 1][0]; - x1 = pts[j][0]; - if(y1 - y0) { - xCross = x0 + (x1 - x0) * (yAvg - y0) / (y1 - y0); - xmin = Math.min(xmin, xCross); - xmax = Math.max(xmax, xCross); - } - } - } - } - - // constrain xmin/max to the visible plot now too - xmin = Math.max(xmin, 0); - xmax = Math.min(xmax, xa._length); - - // get only fill or line color for the hover color - var color = Color.defaultLine; - if(Color.opacity(trace.fillcolor)) color = trace.fillcolor; - else if(Color.opacity((trace.line || {}).color)) { - color = trace.line.color; - } - - Lib.extendFlat(pointData, { - // never let a 2D override 1D type as closest point - // also: no spikeDistance, it's not allowed for fills - distance: pointData.maxHoverDistance, - x0: xmin, - x1: xmax, - y0: yAvg, - y1: yAvg, - color: color, - hovertemplate: false - }); - - delete pointData.index; - - if(trace.text && !Array.isArray(trace.text)) { - pointData.text = String(trace.text); - } else pointData.text = trace.name; - - return [pointData]; - } - } -}; - -},{"../../components/color":593,"../../components/fx":632,"../../lib":719,"../../registry":847,"./get_trace_color":1121}],1123:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var subtypes = _dereq_('./subtypes'); - -module.exports = { - hasLines: subtypes.hasLines, - hasMarkers: subtypes.hasMarkers, - hasText: subtypes.hasText, - isBubble: subtypes.isBubble, - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - crossTraceDefaults: _dereq_('./cross_trace_defaults'), - calc: _dereq_('./calc').calc, - crossTraceCalc: _dereq_('./cross_trace_calc'), - arraysToCalcdata: _dereq_('./arrays_to_calcdata'), - plot: _dereq_('./plot'), - colorbar: _dereq_('./marker_colorbar'), - style: _dereq_('./style').style, - styleOnSelect: _dereq_('./style').styleOnSelect, - hoverPoints: _dereq_('./hover'), - selectPoints: _dereq_('./select'), - animatable: true, - - moduleType: 'trace', - name: 'scatter', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: [ - 'cartesian', 'svg', 'symbols', 'errorBarsOK', 'showLegend', 'scatter-like', - 'zoomScale' - ], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"./arrays_to_calcdata":1111,"./attributes":1112,"./calc":1113,"./cross_trace_calc":1117,"./cross_trace_defaults":1118,"./defaults":1119,"./hover":1122,"./marker_colorbar":1129,"./plot":1131,"./select":1132,"./style":1134,"./subtypes":1135}],1124:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; -var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale; -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); - -module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout, coerce, opts) { - var markerColor = (traceIn.marker || {}).color; - - coerce('line.color', defaultColor); - - if(hasColorscale(traceIn, 'line')) { - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'line.', cLetter: 'c'}); - } else { - var lineColorDflt = (isArrayOrTypedArray(markerColor) ? false : markerColor) || defaultColor; - coerce('line.color', lineColorDflt); - } - - coerce('line.width'); - if(!(opts || {}).noDash) coerce('line.dash'); -}; - -},{"../../components/colorscale/defaults":603,"../../components/colorscale/helpers":604,"../../lib":719}],1125:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var numConstants = _dereq_('../../constants/numerical'); -var BADNUM = numConstants.BADNUM; -var LOG_CLIP = numConstants.LOG_CLIP; -var LOG_CLIP_PLUS = LOG_CLIP + 0.5; -var LOG_CLIP_MINUS = LOG_CLIP - 0.5; -var Lib = _dereq_('../../lib'); -var segmentsIntersect = Lib.segmentsIntersect; -var constrain = Lib.constrain; -var constants = _dereq_('./constants'); - - -module.exports = function linePoints(d, opts) { - var xa = opts.xaxis; - var ya = opts.yaxis; - var xLog = xa.type === 'log'; - var yLog = ya.type === 'log'; - var xLen = xa._length; - var yLen = ya._length; - var connectGaps = opts.connectGaps; - var baseTolerance = opts.baseTolerance; - var shape = opts.shape; - var linear = shape === 'linear'; - var fill = opts.fill && opts.fill !== 'none'; - var segments = []; - var minTolerance = constants.minTolerance; - var len = d.length; - var pts = new Array(len); - var pti = 0; - - var i; - - // pt variables are pixel coordinates [x,y] of one point - // these four are the outputs of clustering on a line - var clusterStartPt, clusterEndPt, clusterHighPt, clusterLowPt; - - // "this" is the next point we're considering adding to the cluster - var thisPt; - - // did we encounter the high point first, then a low point, or vice versa? - var clusterHighFirst; - - // the first two points in the cluster determine its unit vector - // so the second is always in the "High" direction - var clusterUnitVector; - - // the pixel delta from clusterStartPt - var thisVector; - - // val variables are (signed) pixel distances along the cluster vector - var clusterRefDist, clusterHighVal, clusterLowVal, thisVal; - - // deviation variables are (signed) pixel distances normal to the cluster vector - var clusterMinDeviation, clusterMaxDeviation, thisDeviation; - - // turn one calcdata point into pixel coordinates - function getPt(index) { - var di = d[index]; - if(!di) return false; - var x = xa.c2p(di.x); - var y = ya.c2p(di.y); - - // if non-positive log values, set them VERY far off-screen - // so the line looks essentially straight from the previous point. - if(x === BADNUM) { - if(xLog) x = xa.c2p(di.x, true); - if(x === BADNUM) return false; - // If BOTH were bad log values, make the line follow a constant - // exponent rather than a constant slope - if(yLog && y === BADNUM) { - x *= Math.abs(xa._m * yLen * (xa._m > 0 ? LOG_CLIP_PLUS : LOG_CLIP_MINUS) / - (ya._m * xLen * (ya._m > 0 ? LOG_CLIP_PLUS : LOG_CLIP_MINUS))); - } - x *= 1000; - } - if(y === BADNUM) { - if(yLog) y = ya.c2p(di.y, true); - if(y === BADNUM) return false; - y *= 1000; - } - return [x, y]; - } - - function crossesViewport(xFrac0, yFrac0, xFrac1, yFrac1) { - var dx = xFrac1 - xFrac0; - var dy = yFrac1 - yFrac0; - var dx0 = 0.5 - xFrac0; - var dy0 = 0.5 - yFrac0; - var norm2 = dx * dx + dy * dy; - var dot = dx * dx0 + dy * dy0; - if(dot > 0 && dot < norm2) { - var cross = dx0 * dy - dy0 * dx; - if(cross * cross < norm2) return true; - } - } - - var latestXFrac, latestYFrac; - // if we're off-screen, increase tolerance over baseTolerance - function getTolerance(pt, nextPt) { - var xFrac = pt[0] / xLen; - var yFrac = pt[1] / yLen; - var offScreenFraction = Math.max(0, -xFrac, xFrac - 1, -yFrac, yFrac - 1); - if(offScreenFraction && (latestXFrac !== undefined) && - crossesViewport(xFrac, yFrac, latestXFrac, latestYFrac) - ) { - offScreenFraction = 0; - } - if(offScreenFraction && nextPt && - crossesViewport(xFrac, yFrac, nextPt[0] / xLen, nextPt[1] / yLen) - ) { - offScreenFraction = 0; - } - - return (1 + constants.toleranceGrowth * offScreenFraction) * baseTolerance; - } - - function ptDist(pt1, pt2) { - var dx = pt1[0] - pt2[0]; - var dy = pt1[1] - pt2[1]; - return Math.sqrt(dx * dx + dy * dy); - } - - // last bit of filtering: clip paths that are VERY far off-screen - // so we don't get near the browser's hard limit (+/- 2^29 px in Chrome and FF) - - var maxScreensAway = constants.maxScreensAway; - - // find the intersections between the segment from pt1 to pt2 - // and the large rectangle maxScreensAway around the viewport - // if one of pt1 and pt2 is inside and the other outside, there - // will be only one intersection. - // if both are outside there will be 0 or 2 intersections - // (or 1 if it's right at a corner - we'll treat that like 0) - // returns an array of intersection pts - var xEdge0 = -xLen * maxScreensAway; - var xEdge1 = xLen * (1 + maxScreensAway); - var yEdge0 = -yLen * maxScreensAway; - var yEdge1 = yLen * (1 + maxScreensAway); - var edges = [ - [xEdge0, yEdge0, xEdge1, yEdge0], - [xEdge1, yEdge0, xEdge1, yEdge1], - [xEdge1, yEdge1, xEdge0, yEdge1], - [xEdge0, yEdge1, xEdge0, yEdge0] - ]; - var xEdge, yEdge, lastXEdge, lastYEdge, lastFarPt, edgePt; - - // for linear line shape, edge intersections should be linearly interpolated - // spline uses this too, which isn't precisely correct but is actually pretty - // good, because Catmull-Rom weights far-away points less in creating the curvature - function getLinearEdgeIntersections(pt1, pt2) { - var out = []; - var ptCount = 0; - for(var i = 0; i < 4; i++) { - var edge = edges[i]; - var ptInt = segmentsIntersect( - pt1[0], pt1[1], pt2[0], pt2[1], - edge[0], edge[1], edge[2], edge[3] - ); - if(ptInt && (!ptCount || - Math.abs(ptInt.x - out[0][0]) > 1 || - Math.abs(ptInt.y - out[0][1]) > 1 - )) { - ptInt = [ptInt.x, ptInt.y]; - // if we have 2 intersections, make sure the closest one to pt1 comes first - if(ptCount && ptDist(ptInt, pt1) < ptDist(out[0], pt1)) out.unshift(ptInt); - else out.push(ptInt); - ptCount++; - } - } - return out; - } - - function onlyConstrainedPoint(pt) { - if(pt[0] < xEdge0 || pt[0] > xEdge1 || pt[1] < yEdge0 || pt[1] > yEdge1) { - return [constrain(pt[0], xEdge0, xEdge1), constrain(pt[1], yEdge0, yEdge1)]; - } - } - - function sameEdge(pt1, pt2) { - if(pt1[0] === pt2[0] && (pt1[0] === xEdge0 || pt1[0] === xEdge1)) return true; - if(pt1[1] === pt2[1] && (pt1[1] === yEdge0 || pt1[1] === yEdge1)) return true; - } - - // for line shapes hv and vh, movement in the two dimensions is decoupled, - // so all we need to do is constrain each dimension independently - function getHVEdgeIntersections(pt1, pt2) { - var out = []; - var ptInt1 = onlyConstrainedPoint(pt1); - var ptInt2 = onlyConstrainedPoint(pt2); - if(ptInt1 && ptInt2 && sameEdge(ptInt1, ptInt2)) return out; - - if(ptInt1) out.push(ptInt1); - if(ptInt2) out.push(ptInt2); - return out; - } - - // hvh and vhv we sometimes have to move one of the intersection points - // out BEYOND the clipping rect, by a maximum of a factor of 2, so that - // the midpoint line is drawn in the right place - function getABAEdgeIntersections(dim, limit0, limit1) { - return function(pt1, pt2) { - var ptInt1 = onlyConstrainedPoint(pt1); - var ptInt2 = onlyConstrainedPoint(pt2); - - var out = []; - if(ptInt1 && ptInt2 && sameEdge(ptInt1, ptInt2)) return out; - - if(ptInt1) out.push(ptInt1); - if(ptInt2) out.push(ptInt2); - - var midShift = 2 * Lib.constrain((pt1[dim] + pt2[dim]) / 2, limit0, limit1) - - ((ptInt1 || pt1)[dim] + (ptInt2 || pt2)[dim]); - if(midShift) { - var ptToAlter; - if(ptInt1 && ptInt2) { - ptToAlter = (midShift > 0 === ptInt1[dim] > ptInt2[dim]) ? ptInt1 : ptInt2; - } else ptToAlter = ptInt1 || ptInt2; - - ptToAlter[dim] += midShift; - } - - return out; - }; - } - - var getEdgeIntersections; - if(shape === 'linear' || shape === 'spline') { - getEdgeIntersections = getLinearEdgeIntersections; - } else if(shape === 'hv' || shape === 'vh') { - getEdgeIntersections = getHVEdgeIntersections; - } else if(shape === 'hvh') getEdgeIntersections = getABAEdgeIntersections(0, xEdge0, xEdge1); - else if(shape === 'vhv') getEdgeIntersections = getABAEdgeIntersections(1, yEdge0, yEdge1); - - // a segment pt1->pt2 entirely outside the nearby region: - // find the corner it gets closest to touching - function getClosestCorner(pt1, pt2) { - var dx = pt2[0] - pt1[0]; - var m = (pt2[1] - pt1[1]) / dx; - var b = (pt1[1] * pt2[0] - pt2[1] * pt1[0]) / dx; - - if(b > 0) return [m > 0 ? xEdge0 : xEdge1, yEdge1]; - else return [m > 0 ? xEdge1 : xEdge0, yEdge0]; - } - - function updateEdge(pt) { - var x = pt[0]; - var y = pt[1]; - var xSame = x === pts[pti - 1][0]; - var ySame = y === pts[pti - 1][1]; - // duplicate point? - if(xSame && ySame) return; - if(pti > 1) { - // backtracking along an edge? - var xSame2 = x === pts[pti - 2][0]; - var ySame2 = y === pts[pti - 2][1]; - if(xSame && (x === xEdge0 || x === xEdge1) && xSame2) { - if(ySame2) pti--; // backtracking exactly - drop prev pt and don't add - else pts[pti - 1] = pt; // not exact: replace the prev pt - } else if(ySame && (y === yEdge0 || y === yEdge1) && ySame2) { - if(xSame2) pti--; - else pts[pti - 1] = pt; - } else pts[pti++] = pt; - } else pts[pti++] = pt; - } - - function updateEdgesForReentry(pt) { - // if we're outside the nearby region and going back in, - // we may need to loop around a corner point - if(pts[pti - 1][0] !== pt[0] && pts[pti - 1][1] !== pt[1]) { - updateEdge([lastXEdge, lastYEdge]); - } - updateEdge(pt); - lastFarPt = null; - lastXEdge = lastYEdge = 0; - } - - function addPt(pt) { - latestXFrac = pt[0] / xLen; - latestYFrac = pt[1] / yLen; - // Are we more than maxScreensAway off-screen any direction? - // if so, clip to this box, but in such a way that on-screen - // drawing is unchanged - xEdge = (pt[0] < xEdge0) ? xEdge0 : (pt[0] > xEdge1) ? xEdge1 : 0; - yEdge = (pt[1] < yEdge0) ? yEdge0 : (pt[1] > yEdge1) ? yEdge1 : 0; - if(xEdge || yEdge) { - if(!pti) { - // to get fills right - if first point is far, push it toward the - // screen in whichever direction(s) are far - - pts[pti++] = [xEdge || pt[0], yEdge || pt[1]]; - } else if(lastFarPt) { - // both this point and the last are outside the nearby region - // check if we're crossing the nearby region - var intersections = getEdgeIntersections(lastFarPt, pt); - if(intersections.length > 1) { - updateEdgesForReentry(intersections[0]); - pts[pti++] = intersections[1]; - } - } else { - // we're leaving the nearby region - add the point where we left it - - edgePt = getEdgeIntersections(pts[pti - 1], pt)[0]; - pts[pti++] = edgePt; - } - - var lastPt = pts[pti - 1]; - if(xEdge && yEdge && (lastPt[0] !== xEdge || lastPt[1] !== yEdge)) { - // we've gone out beyond a new corner: add the corner too - // so that the next point will take the right winding - if(lastFarPt) { - if(lastXEdge !== xEdge && lastYEdge !== yEdge) { - if(lastXEdge && lastYEdge) { - // we've gone around to an opposite corner - we - // need to add the correct extra corner - // in order to get the right winding - updateEdge(getClosestCorner(lastFarPt, pt)); - } else { - // we're coming from a far edge - the extra corner - // we need is determined uniquely by the sectors - updateEdge([lastXEdge || xEdge, lastYEdge || yEdge]); - } - } else if(lastXEdge && lastYEdge) { - updateEdge([lastXEdge, lastYEdge]); - } - } - updateEdge([xEdge, yEdge]); - } else if((lastXEdge - xEdge) && (lastYEdge - yEdge)) { - // we're coming from an edge or far corner to an edge - again the - // extra corner we need is uniquely determined by the sectors - updateEdge([xEdge || lastXEdge, yEdge || lastYEdge]); - } - lastFarPt = pt; - lastXEdge = xEdge; - lastYEdge = yEdge; - } else { - if(lastFarPt) { - // this point is in range but the previous wasn't: add its entry pt first - updateEdgesForReentry(getEdgeIntersections(lastFarPt, pt)[0]); - } - - pts[pti++] = pt; - } - } - - // loop over ALL points in this trace - for(i = 0; i < len; i++) { - clusterStartPt = getPt(i); - if(!clusterStartPt) continue; - - pti = 0; - lastFarPt = null; - addPt(clusterStartPt); - - // loop over one segment of the trace - for(i++; i < len; i++) { - clusterHighPt = getPt(i); - if(!clusterHighPt) { - if(connectGaps) continue; - else break; - } - - // can't decimate if nonlinear line shape - // TODO: we *could* decimate [hv]{2,3} shapes if we restricted clusters to horz or vert again - // but spline would be verrry awkward to decimate - if(!linear || !opts.simplify) { - addPt(clusterHighPt); - continue; - } - - var nextPt = getPt(i + 1); - - clusterRefDist = ptDist(clusterHighPt, clusterStartPt); - - // #3147 - always include the very first and last points for fills - if(!(fill && (pti === 0 || pti === len - 1)) && - clusterRefDist < getTolerance(clusterHighPt, nextPt) * minTolerance) continue; - - clusterUnitVector = [ - (clusterHighPt[0] - clusterStartPt[0]) / clusterRefDist, - (clusterHighPt[1] - clusterStartPt[1]) / clusterRefDist - ]; - - clusterLowPt = clusterStartPt; - clusterHighVal = clusterRefDist; - clusterLowVal = clusterMinDeviation = clusterMaxDeviation = 0; - clusterHighFirst = false; - clusterEndPt = clusterHighPt; - - // loop over one cluster of points that collapse onto one line - for(i++; i < d.length; i++) { - thisPt = nextPt; - nextPt = getPt(i + 1); - if(!thisPt) { - if(connectGaps) continue; - else break; - } - thisVector = [ - thisPt[0] - clusterStartPt[0], - thisPt[1] - clusterStartPt[1] - ]; - // cross product (or dot with normal to the cluster vector) - thisDeviation = thisVector[0] * clusterUnitVector[1] - thisVector[1] * clusterUnitVector[0]; - clusterMinDeviation = Math.min(clusterMinDeviation, thisDeviation); - clusterMaxDeviation = Math.max(clusterMaxDeviation, thisDeviation); - - if(clusterMaxDeviation - clusterMinDeviation > getTolerance(thisPt, nextPt)) break; - - clusterEndPt = thisPt; - thisVal = thisVector[0] * clusterUnitVector[0] + thisVector[1] * clusterUnitVector[1]; - - if(thisVal > clusterHighVal) { - clusterHighVal = thisVal; - clusterHighPt = thisPt; - clusterHighFirst = false; - } else if(thisVal < clusterLowVal) { - clusterLowVal = thisVal; - clusterLowPt = thisPt; - clusterHighFirst = true; - } - } - - // insert this cluster into pts - // we've already inserted the start pt, now check if we have high and low pts - if(clusterHighFirst) { - addPt(clusterHighPt); - if(clusterEndPt !== clusterLowPt) addPt(clusterLowPt); - } else { - if(clusterLowPt !== clusterStartPt) addPt(clusterLowPt); - if(clusterEndPt !== clusterHighPt) addPt(clusterHighPt); - } - // and finally insert the end pt - addPt(clusterEndPt); - - // have we reached the end of this segment? - if(i >= d.length || !thisPt) break; - - // otherwise we have an out-of-cluster point to insert as next clusterStartPt - addPt(thisPt); - clusterStartPt = thisPt; - } - - // to get fills right - repeat what we did at the start - if(lastFarPt) updateEdge([lastXEdge || lastFarPt[0], lastYEdge || lastFarPt[1]]); - - segments.push(pts.slice(0, pti)); - } - - return segments; -}; - -},{"../../constants/numerical":695,"../../lib":719,"./constants":1116}],1126:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -// common to 'scatter' and 'scatterternary' -module.exports = function handleLineShapeDefaults(traceIn, traceOut, coerce) { - var shape = coerce('line.shape'); - if(shape === 'spline') coerce('line.smoothing'); -}; - -},{}],1127:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var LINKEDFILLS = {tonextx: 1, tonexty: 1, tonext: 1}; - -module.exports = function linkTraces(gd, plotinfo, cdscatter) { - var trace, i, group, prevtrace, groupIndex; - - // first sort traces to keep stacks & filled-together groups together - var groupIndices = {}; - var needsSort = false; - var prevGroupIndex = -1; - var nextGroupIndex = 0; - var prevUnstackedGroupIndex = -1; - for(i = 0; i < cdscatter.length; i++) { - trace = cdscatter[i][0].trace; - group = trace.stackgroup || ''; - if(group) { - if(group in groupIndices) { - groupIndex = groupIndices[group]; - } else { - groupIndex = groupIndices[group] = nextGroupIndex; - nextGroupIndex++; - } - } else if(trace.fill in LINKEDFILLS && prevUnstackedGroupIndex >= 0) { - groupIndex = prevUnstackedGroupIndex; - } else { - groupIndex = prevUnstackedGroupIndex = nextGroupIndex; - nextGroupIndex++; - } - - if(groupIndex < prevGroupIndex) needsSort = true; - trace._groupIndex = prevGroupIndex = groupIndex; - } - - var cdscatterSorted = cdscatter.slice(); - if(needsSort) { - cdscatterSorted.sort(function(a, b) { - var traceA = a[0].trace; - var traceB = b[0].trace; - return (traceA._groupIndex - traceB._groupIndex) || - (traceA.index - traceB.index); - }); - } - - // now link traces to each other - var prevtraces = {}; - for(i = 0; i < cdscatterSorted.length; i++) { - trace = cdscatterSorted[i][0].trace; - group = trace.stackgroup || ''; - - // Note: The check which ensures all cdscatter here are for the same axis and - // are either cartesian or scatterternary has been removed. This code assumes - // the passed scattertraces have been filtered to the proper plot types and - // the proper subplots. - if(trace.visible === true) { - trace._nexttrace = null; - - if(trace.fill in LINKEDFILLS) { - prevtrace = prevtraces[group]; - trace._prevtrace = prevtrace || null; - - if(prevtrace) { - prevtrace._nexttrace = trace; - } - } - - trace._ownfill = (trace.fill && ( - trace.fill.substr(0, 6) === 'tozero' || - trace.fill === 'toself' || - (trace.fill.substr(0, 2) === 'to' && !trace._prevtrace) - )); - - prevtraces[group] = trace; - } else { - trace._prevtrace = trace._nexttrace = trace._ownfill = null; - } - } - - return cdscatterSorted; -}; - -},{}],1128:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - - -// used in the drawing step for 'scatter' and 'scattegeo' and -// in the convert step for 'scatter3d' -module.exports = function makeBubbleSizeFn(trace) { - var marker = trace.marker; - var sizeRef = marker.sizeref || 1; - var sizeMin = marker.sizemin || 0; - - // for bubble charts, allow scaling the provided value linearly - // and by area or diameter. - // Note this only applies to the array-value sizes - - var baseFn = (marker.sizemode === 'area') ? - function(v) { return Math.sqrt(v / sizeRef); } : - function(v) { return v / sizeRef; }; - - // TODO add support for position/negative bubbles? - // TODO add 'sizeoffset' attribute? - return function(v) { - var baseSize = baseFn(v / 2); - - // don't show non-numeric and negative sizes - return (isNumeric(baseSize) && (baseSize > 0)) ? - Math.max(baseSize, sizeMin) : - 0; - }; -}; - -},{"fast-isnumeric":225}],1129:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -module.exports = { - container: 'marker', - min: 'cmin', - max: 'cmax' -}; - -},{}],1130:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Color = _dereq_('../../components/color'); -var hasColorscale = _dereq_('../../components/colorscale/helpers').hasColorscale; -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); - -var subTypes = _dereq_('./subtypes'); - -/* - * opts: object of flags to control features not all marker users support - * noLine: caller does not support marker lines - * gradient: caller supports gradients - * noSelect: caller does not support selected/unselected attribute containers - */ -module.exports = function markerDefaults(traceIn, traceOut, defaultColor, layout, coerce, opts) { - var isBubble = subTypes.isBubble(traceIn); - var lineColor = (traceIn.line || {}).color; - var defaultMLC; - - opts = opts || {}; - - // marker.color inherit from line.color (even if line.color is an array) - if(lineColor) defaultColor = lineColor; - - coerce('marker.symbol'); - coerce('marker.opacity', isBubble ? 0.7 : 1); - coerce('marker.size'); - - coerce('marker.color', defaultColor); - if(hasColorscale(traceIn, 'marker')) { - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'marker.', cLetter: 'c'}); - } - - if(!opts.noSelect) { - coerce('selected.marker.color'); - coerce('unselected.marker.color'); - coerce('selected.marker.size'); - coerce('unselected.marker.size'); - } - - if(!opts.noLine) { - // if there's a line with a different color than the marker, use - // that line color as the default marker line color - // (except when it's an array) - // mostly this is for transparent markers to behave nicely - if(lineColor && !Array.isArray(lineColor) && (traceOut.marker.color !== lineColor)) { - defaultMLC = lineColor; - } else if(isBubble) defaultMLC = Color.background; - else defaultMLC = Color.defaultLine; - - coerce('marker.line.color', defaultMLC); - if(hasColorscale(traceIn, 'marker.line')) { - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: 'marker.line.', cLetter: 'c'}); - } - - coerce('marker.line.width', isBubble ? 1 : 0); - } - - if(isBubble) { - coerce('marker.sizeref'); - coerce('marker.sizemin'); - coerce('marker.sizemode'); - } - - if(opts.gradient) { - var gradientType = coerce('marker.gradient.type'); - if(gradientType !== 'none') { - coerce('marker.gradient.color'); - } - } -}; - -},{"../../components/color":593,"../../components/colorscale/defaults":603,"../../components/colorscale/helpers":604,"./subtypes":1135}],1131:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var ensureSingle = Lib.ensureSingle; -var identity = Lib.identity; -var Drawing = _dereq_('../../components/drawing'); - -var subTypes = _dereq_('./subtypes'); -var linePoints = _dereq_('./line_points'); -var linkTraces = _dereq_('./link_traces'); -var polygonTester = _dereq_('../../lib/polygon').tester; - -module.exports = function plot(gd, plotinfo, cdscatter, scatterLayer, transitionOpts, makeOnCompleteCallback) { - var join, onComplete; - - // If transition config is provided, then it is only a partial replot and traces not - // updated are removed. - var isFullReplot = !transitionOpts; - var hasTransition = !!transitionOpts && transitionOpts.duration > 0; - - // Link traces so the z-order of fill layers is correct - var cdscatterSorted = linkTraces(gd, plotinfo, cdscatter); - - join = scatterLayer.selectAll('g.trace') - .data(cdscatterSorted, function(d) { return d[0].trace.uid; }); - - // Append new traces: - join.enter().append('g') - .attr('class', function(d) { - return 'trace scatter trace' + d[0].trace.uid; - }) - .style('stroke-miterlimit', 2); - join.order(); - - createFills(gd, join, plotinfo); - - if(hasTransition) { - if(makeOnCompleteCallback) { - // If it was passed a callback to register completion, make a callback. If - // this is created, then it must be executed on completion, otherwise the - // pos-transition redraw will not execute: - onComplete = makeOnCompleteCallback(); - } - - var transition = d3.transition() - .duration(transitionOpts.duration) - .ease(transitionOpts.easing) - .each('end', function() { - onComplete && onComplete(); - }) - .each('interrupt', function() { - onComplete && onComplete(); - }); - - transition.each(function() { - // Must run the selection again since otherwise enters/updates get grouped together - // and these get executed out of order. Except we need them in order! - scatterLayer.selectAll('g.trace').each(function(d, i) { - plotOne(gd, i, plotinfo, d, cdscatterSorted, this, transitionOpts); - }); - }); - } else { - join.each(function(d, i) { - plotOne(gd, i, plotinfo, d, cdscatterSorted, this, transitionOpts); - }); - } - - if(isFullReplot) { - join.exit().remove(); - } - - // remove paths that didn't get used - scatterLayer.selectAll('path:not([d])').remove(); -}; - -function createFills(gd, traceJoin, plotinfo) { - traceJoin.each(function(d) { - var fills = ensureSingle(d3.select(this), 'g', 'fills'); - Drawing.setClipUrl(fills, plotinfo.layerClipId, gd); - - var trace = d[0].trace; - - var fillData = []; - if(trace._ownfill) fillData.push('_ownFill'); - if(trace._nexttrace) fillData.push('_nextFill'); - - var fillJoin = fills.selectAll('g').data(fillData, identity); - - fillJoin.enter().append('g'); - - fillJoin.exit() - .each(function(d) { trace[d] = null; }) - .remove(); - - fillJoin.order().each(function(d) { - // make a path element inside the fill group, just so - // we can give it its own data later on and the group can - // keep its simple '_*Fill' data - trace[d] = ensureSingle(d3.select(this), 'path', 'js-fill'); - }); - }); -} - -function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transitionOpts) { - var i; - - // Since this has been reorganized and we're executing this on individual traces, - // we need to pass it the full list of cdscatter as well as this trace's index (idx) - // since it does an internal n^2 loop over comparisons with other traces: - selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll); - - var hasTransition = !!transitionOpts && transitionOpts.duration > 0; - - function transition(selection) { - return hasTransition ? selection.transition() : selection; - } - - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - var trace = cdscatter[0].trace; - var line = trace.line; - var tr = d3.select(element); - - var errorBarGroup = ensureSingle(tr, 'g', 'errorbars'); - var lines = ensureSingle(tr, 'g', 'lines'); - var points = ensureSingle(tr, 'g', 'points'); - var text = ensureSingle(tr, 'g', 'text'); - - // error bars are at the bottom - Registry.getComponentMethod('errorbars', 'plot')(gd, errorBarGroup, plotinfo, transitionOpts); - - if(trace.visible !== true) return; - - transition(tr).style('opacity', trace.opacity); - - // BUILD LINES AND FILLS - var ownFillEl3, tonext; - var ownFillDir = trace.fill.charAt(trace.fill.length - 1); - if(ownFillDir !== 'x' && ownFillDir !== 'y') ownFillDir = ''; - - // store node for tweaking by selectPoints - cdscatter[0][plotinfo.isRangePlot ? 'nodeRangePlot3' : 'node3'] = tr; - - var prevRevpath = ''; - var prevPolygons = []; - var prevtrace = trace._prevtrace; - - if(prevtrace) { - prevRevpath = prevtrace._prevRevpath || ''; - tonext = prevtrace._nextFill; - prevPolygons = prevtrace._polygons; - } - - var thispath; - var thisrevpath; - // fullpath is all paths for this curve, joined together straight - // across gaps, for filling - var fullpath = ''; - // revpath is fullpath reversed, for fill-to-next - var revpath = ''; - // functions for converting a point array to a path - var pathfn, revpathbase, revpathfn; - // variables used before and after the data join - var pt0, lastSegment, pt1, thisPolygons; - - // initialize line join data / method - var segments = []; - var makeUpdate = Lib.noop; - - ownFillEl3 = trace._ownFill; - - if(subTypes.hasLines(trace) || trace.fill !== 'none') { - if(tonext) { - // This tells .style which trace to use for fill information: - tonext.datum(cdscatter); - } - - if(['hv', 'vh', 'hvh', 'vhv'].indexOf(line.shape) !== -1) { - pathfn = Drawing.steps(line.shape); - revpathbase = Drawing.steps( - line.shape.split('').reverse().join('') - ); - } else if(line.shape === 'spline') { - pathfn = revpathbase = function(pts) { - var pLast = pts[pts.length - 1]; - if(pts.length > 1 && pts[0][0] === pLast[0] && pts[0][1] === pLast[1]) { - // identical start and end points: treat it as a - // closed curve so we don't get a kink - return Drawing.smoothclosed(pts.slice(1), line.smoothing); - } else { - return Drawing.smoothopen(pts, line.smoothing); - } - }; - } else { - pathfn = revpathbase = function(pts) { - return 'M' + pts.join('L'); - }; - } - - revpathfn = function(pts) { - // note: this is destructive (reverses pts in place) so can't use pts after this - return revpathbase(pts.reverse()); - }; - - segments = linePoints(cdscatter, { - xaxis: xa, - yaxis: ya, - connectGaps: trace.connectgaps, - baseTolerance: Math.max(line.width || 1, 3) / 4, - shape: line.shape, - simplify: line.simplify, - fill: trace.fill - }); - - // since we already have the pixel segments here, use them to make - // polygons for hover on fill - // TODO: can we skip this if hoveron!=fills? That would mean we - // need to redraw when you change hoveron... - thisPolygons = trace._polygons = new Array(segments.length); - for(i = 0; i < segments.length; i++) { - trace._polygons[i] = polygonTester(segments[i]); - } - - if(segments.length) { - pt0 = segments[0][0]; - lastSegment = segments[segments.length - 1]; - pt1 = lastSegment[lastSegment.length - 1]; - } - - makeUpdate = function(isEnter) { - return function(pts) { - thispath = pathfn(pts); - thisrevpath = revpathfn(pts); - if(!fullpath) { - fullpath = thispath; - revpath = thisrevpath; - } else if(ownFillDir) { - fullpath += 'L' + thispath.substr(1); - revpath = thisrevpath + ('L' + revpath.substr(1)); - } else { - fullpath += 'Z' + thispath; - revpath = thisrevpath + 'Z' + revpath; - } - - if(subTypes.hasLines(trace) && pts.length > 1) { - var el = d3.select(this); - - // This makes the coloring work correctly: - el.datum(cdscatter); - - if(isEnter) { - transition(el.style('opacity', 0) - .attr('d', thispath) - .call(Drawing.lineGroupStyle)) - .style('opacity', 1); - } else { - var sel = transition(el); - sel.attr('d', thispath); - Drawing.singleLineStyle(cdscatter, sel); - } - } - }; - }; - } - - var lineJoin = lines.selectAll('.js-line').data(segments); - - transition(lineJoin.exit()) - .style('opacity', 0) - .remove(); - - lineJoin.each(makeUpdate(false)); - - lineJoin.enter().append('path') - .classed('js-line', true) - .style('vector-effect', 'non-scaling-stroke') - .call(Drawing.lineGroupStyle) - .each(makeUpdate(true)); - - Drawing.setClipUrl(lineJoin, plotinfo.layerClipId, gd); - - function clearFill(selection) { - transition(selection).attr('d', 'M0,0Z'); - } - - if(segments.length) { - if(ownFillEl3) { - ownFillEl3.datum(cdscatter); - if(pt0 && pt1) { - if(ownFillDir) { - if(ownFillDir === 'y') { - pt0[1] = pt1[1] = ya.c2p(0, true); - } else if(ownFillDir === 'x') { - pt0[0] = pt1[0] = xa.c2p(0, true); - } - - // fill to zero: full trace path, plus extension of - // the endpoints to the appropriate axis - // For the sake of animations, wrap the points around so that - // the points on the axes are the first two points. Otherwise - // animations get a little crazy if the number of points changes. - transition(ownFillEl3).attr('d', 'M' + pt1 + 'L' + pt0 + 'L' + fullpath.substr(1)) - .call(Drawing.singleFillStyle); - } else { - // fill to self: just join the path to itself - transition(ownFillEl3).attr('d', fullpath + 'Z') - .call(Drawing.singleFillStyle); - } - } - } else if(tonext) { - if(trace.fill.substr(0, 6) === 'tonext' && fullpath && prevRevpath) { - // fill to next: full trace path, plus the previous path reversed - if(trace.fill === 'tonext') { - // tonext: for use by concentric shapes, like manually constructed - // contours, we just add the two paths closed on themselves. - // This makes strange results if one path is *not* entirely - // inside the other, but then that is a strange usage. - transition(tonext).attr('d', fullpath + 'Z' + prevRevpath + 'Z') - .call(Drawing.singleFillStyle); - } else { - // tonextx/y: for now just connect endpoints with lines. This is - // the correct behavior if the endpoints are at the same value of - // y/x, but if they *aren't*, we should ideally do more complicated - // things depending on whether the new endpoint projects onto the - // existing curve or off the end of it - transition(tonext).attr('d', fullpath + 'L' + prevRevpath.substr(1) + 'Z') - .call(Drawing.singleFillStyle); - } - trace._polygons = trace._polygons.concat(prevPolygons); - } else { - clearFill(tonext); - trace._polygons = null; - } - } - trace._prevRevpath = revpath; - trace._prevPolygons = thisPolygons; - } else { - if(ownFillEl3) clearFill(ownFillEl3); - else if(tonext) clearFill(tonext); - trace._polygons = trace._prevRevpath = trace._prevPolygons = null; - } - - - function visFilter(d) { - return d.filter(function(v) { return !v.gap && v.vis; }); - } - - function visFilterWithGaps(d) { - return d.filter(function(v) { return v.vis; }); - } - - function gapFilter(d) { - return d.filter(function(v) { return !v.gap; }); - } - - function keyFunc(d) { - return d.id; - } - - // Returns a function if the trace is keyed, otherwise returns undefined - function getKeyFunc(trace) { - if(trace.ids) { - return keyFunc; - } - } - - function hideFilter() { - return false; - } - - function makePoints(points, text, cdscatter) { - var join, selection, hasNode; - - var trace = cdscatter[0].trace; - var showMarkers = subTypes.hasMarkers(trace); - var showText = subTypes.hasText(trace); - - var keyFunc = getKeyFunc(trace); - var markerFilter = hideFilter; - var textFilter = hideFilter; - - if(showMarkers || showText) { - var showFilter = identity; - // if we're stacking, "infer zero" gap mode gets markers in the - // gap points - because we've inferred a zero there - but other - // modes (currently "interpolate", later "interrupt" hopefully) - // we don't draw generated markers - var stackGroup = trace.stackgroup; - var isInferZero = stackGroup && ( - gd._fullLayout._scatterStackOpts[xa._id + ya._id][stackGroup].stackgaps === 'infer zero'); - if(trace.marker.maxdisplayed || trace._needsCull) { - showFilter = isInferZero ? visFilterWithGaps : visFilter; - } else if(stackGroup && !isInferZero) { - showFilter = gapFilter; - } - - if(showMarkers) markerFilter = showFilter; - if(showText) textFilter = showFilter; - } - - // marker points - - selection = points.selectAll('path.point'); - - join = selection.data(markerFilter, keyFunc); - - var enter = join.enter().append('path') - .classed('point', true); - - if(hasTransition) { - enter - .call(Drawing.pointStyle, trace, gd) - .call(Drawing.translatePoints, xa, ya) - .style('opacity', 0) - .transition() - .style('opacity', 1); - } - - join.order(); - - var styleFns; - if(showMarkers) { - styleFns = Drawing.makePointStyleFns(trace); - } - - join.each(function(d) { - var el = d3.select(this); - var sel = transition(el); - hasNode = Drawing.translatePoint(d, sel, xa, ya); - - if(hasNode) { - Drawing.singlePointStyle(d, sel, trace, styleFns, gd); - - if(plotinfo.layerClipId) { - Drawing.hideOutsideRangePoint(d, sel, xa, ya, trace.xcalendar, trace.ycalendar); - } - - if(trace.customdata) { - el.classed('plotly-customdata', d.data !== null && d.data !== undefined); - } - } else { - sel.remove(); - } - }); - - if(hasTransition) { - join.exit().transition() - .style('opacity', 0) - .remove(); - } else { - join.exit().remove(); - } - - // text points - selection = text.selectAll('g'); - join = selection.data(textFilter, keyFunc); - - // each text needs to go in its own 'g' in case - // it gets converted to mathjax - join.enter().append('g').classed('textpoint', true).append('text'); - - join.order(); - - join.each(function(d) { - var g = d3.select(this); - var sel = transition(g.select('text')); - hasNode = Drawing.translatePoint(d, sel, xa, ya); - - if(hasNode) { - if(plotinfo.layerClipId) { - Drawing.hideOutsideRangePoint(d, g, xa, ya, trace.xcalendar, trace.ycalendar); - } - } else { - g.remove(); - } - }); - - join.selectAll('text') - .call(Drawing.textPointStyle, trace, gd) - .each(function(d) { - // This just *has* to be totally custom becuase of SVG text positioning :( - // It's obviously copied from translatePoint; we just can't use that - var x = xa.c2p(d.x); - var y = ya.c2p(d.y); - - d3.select(this).selectAll('tspan.line').each(function() { - transition(d3.select(this)).attr({x: x, y: y}); - }); - }); - - join.exit().remove(); - } - - points.datum(cdscatter); - text.datum(cdscatter); - makePoints(points, text, cdscatter); - - // lastly, clip points groups of `cliponaxis !== false` traces - // on `plotinfo._hasClipOnAxisFalse === true` subplots - var hasClipOnAxisFalse = trace.cliponaxis === false; - var clipUrl = hasClipOnAxisFalse ? null : plotinfo.layerClipId; - Drawing.setClipUrl(points, clipUrl, gd); - Drawing.setClipUrl(text, clipUrl, gd); -} - -function selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - var xr = d3.extent(Lib.simpleMap(xa.range, xa.r2c)); - var yr = d3.extent(Lib.simpleMap(ya.range, ya.r2c)); - - var trace = cdscatter[0].trace; - if(!subTypes.hasMarkers(trace)) return; - // if marker.maxdisplayed is used, select a maximum of - // mnum markers to show, from the set that are in the viewport - var mnum = trace.marker.maxdisplayed; - - // TODO: remove some as we get away from the viewport? - if(mnum === 0) return; - - var cd = cdscatter.filter(function(v) { - return v.x >= xr[0] && v.x <= xr[1] && v.y >= yr[0] && v.y <= yr[1]; - }); - var inc = Math.ceil(cd.length / mnum); - var tnum = 0; - cdscatterAll.forEach(function(cdj, j) { - var tracei = cdj[0].trace; - if(subTypes.hasMarkers(tracei) && - tracei.marker.maxdisplayed > 0 && j < idx) { - tnum++; - } - }); - - // if multiple traces use maxdisplayed, stagger which markers we - // display this formula offsets successive traces by 1/3 of the - // increment, adding an extra small amount after each triplet so - // it's not quite periodic - var i0 = Math.round(tnum * inc / 3 + Math.floor(tnum / 3) * inc / 7.1); - - // for error bars: save in cd which markers to show - // so we don't have to repeat this - cdscatter.forEach(function(v) { delete v.vis; }); - cd.forEach(function(v, i) { - if(Math.round((i + i0) % inc) === 0) v.vis = true; - }); -} - -},{"../../components/drawing":614,"../../lib":719,"../../lib/polygon":731,"../../registry":847,"./line_points":1125,"./link_traces":1127,"./subtypes":1135,"d3":163}],1132:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var subtypes = _dereq_('./subtypes'); - -module.exports = function selectPoints(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var xa = searchInfo.xaxis; - var ya = searchInfo.yaxis; - var selection = []; - var trace = cd[0].trace; - var i; - var di; - var x; - var y; - - var hasOnlyLines = (!subtypes.hasMarkers(trace) && !subtypes.hasText(trace)); - if(hasOnlyLines) return []; - - if(selectionTester === false) { // clear selection - for(i = 0; i < cd.length; i++) { - cd[i].selected = 0; - } - } else { - for(i = 0; i < cd.length; i++) { - di = cd[i]; - x = xa.c2p(di.x); - y = ya.c2p(di.y); - - if((di.i !== null) && selectionTester.contains([x, y], false, i, searchInfo)) { - selection.push({ - pointNumber: di.i, - x: xa.c2d(di.x), - y: ya.c2d(di.y) - }); - di.selected = 1; - } else { - di.selected = 0; - } - } - } - - return selection; -}; - -},{"./subtypes":1135}],1133:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var perStackAttrs = ['orientation', 'groupnorm', 'stackgaps']; - -module.exports = function handleStackDefaults(traceIn, traceOut, layout, coerce) { - var stackOpts = layout._scatterStackOpts; - - var stackGroup = coerce('stackgroup'); - if(stackGroup) { - // use independent stacking options per subplot - var subplot = traceOut.xaxis + traceOut.yaxis; - var subplotStackOpts = stackOpts[subplot]; - if(!subplotStackOpts) subplotStackOpts = stackOpts[subplot] = {}; - - var groupOpts = subplotStackOpts[stackGroup]; - var firstTrace = false; - if(groupOpts) { - groupOpts.traces.push(traceOut); - } else { - groupOpts = subplotStackOpts[stackGroup] = { - // keep track of trace indices for use during stacking calculations - // this will be filled in during `calc` and used during `crossTraceCalc` - // so it's OK if we don't recreate it during a non-calc edit - traceIndices: [], - // Hold on to the whole set of prior traces - // First one is most important, so we can clear defaults - // there if we find explicit values only in later traces. - // We're only going to *use* the values stored in groupOpts, - // but for the editor and validate we want things self-consistent - // The full set of traces is used only to fix `fill` default if - // we find `orientation: 'h'` beyond the first trace - traces: [traceOut] - }; - firstTrace = true; - } - // TODO: how is this going to work with groupby transforms? - // in principle it should be OK I guess, as long as explicit group styles - // don't override explicit base-trace styles? - - var dflts = { - orientation: (traceOut.x && !traceOut.y) ? 'h' : 'v' - }; - - for(var i = 0; i < perStackAttrs.length; i++) { - var attr = perStackAttrs[i]; - var attrFound = attr + 'Found'; - if(!groupOpts[attrFound]) { - var traceHasAttr = traceIn[attr] !== undefined; - var isOrientation = attr === 'orientation'; - if(traceHasAttr || firstTrace) { - groupOpts[attr] = coerce(attr, dflts[attr]); - - if(isOrientation) { - groupOpts.fillDflt = groupOpts[attr] === 'h' ? - 'tonextx' : 'tonexty'; - } - - if(traceHasAttr) { - // Note: this will show a value here even if it's invalid - // in which case it will revert to default. - groupOpts[attrFound] = true; - - // Note: only one trace in the stack will get a _fullData - // entry for a given stack-wide attribute. If no traces - // (or the first trace) specify that attribute, the - // first trace will get it. If the first trace does NOT - // specify it but some later trace does, then it gets - // removed from the first trace and only included in the - // one that specified it. This is mostly important for - // editors (that want to see the full values to know - // what settings are available) and Plotly.react diffing. - // Editors may want to use fullLayout._scatterStackOpts - // directly and make these settings available from all - // traces in the stack... then set the new value into - // the first trace, and clear all later traces. - if(!firstTrace) { - delete groupOpts.traces[0][attr]; - - // orientation can affect default fill of previous traces - if(isOrientation) { - for(var j = 0; j < groupOpts.traces.length - 1; j++) { - var trace2 = groupOpts.traces[j]; - if(trace2._input.fill !== trace2.fill) { - trace2.fill = groupOpts.fillDflt; - } - } - } - } - } - } - } - } - return groupOpts; - } -}; - -},{}],1134:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); -var Drawing = _dereq_('../../components/drawing'); -var Registry = _dereq_('../../registry'); - -function style(gd) { - var s = d3.select(gd).selectAll('g.trace.scatter'); - - s.style('opacity', function(d) { - return d[0].trace.opacity; - }); - - s.selectAll('g.points').each(function(d) { - var sel = d3.select(this); - var trace = d.trace || d[0].trace; - stylePoints(sel, trace, gd); - }); - - s.selectAll('g.text').each(function(d) { - var sel = d3.select(this); - var trace = d.trace || d[0].trace; - styleText(sel, trace, gd); - }); - - s.selectAll('g.trace path.js-line') - .call(Drawing.lineGroupStyle); - - s.selectAll('g.trace path.js-fill') - .call(Drawing.fillGroupStyle); - - Registry.getComponentMethod('errorbars', 'style')(s); -} - -function stylePoints(sel, trace, gd) { - Drawing.pointStyle(sel.selectAll('path.point'), trace, gd); -} - -function styleText(sel, trace, gd) { - Drawing.textPointStyle(sel.selectAll('text'), trace, gd); -} - -function styleOnSelect(gd, cd, sel) { - var trace = cd[0].trace; - - if(trace.selectedpoints) { - Drawing.selectedPointStyle(sel.selectAll('path.point'), trace); - Drawing.selectedTextStyle(sel.selectAll('text'), trace); - } else { - stylePoints(sel, trace, gd); - styleText(sel, trace, gd); - } -} - -module.exports = { - style: style, - stylePoints: stylePoints, - styleText: styleText, - styleOnSelect: styleOnSelect -}; - -},{"../../components/drawing":614,"../../registry":847,"d3":163}],1135:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -module.exports = { - hasLines: function(trace) { - return trace.visible && trace.mode && - trace.mode.indexOf('lines') !== -1; - }, - - hasMarkers: function(trace) { - return trace.visible && ( - (trace.mode && trace.mode.indexOf('markers') !== -1) || - // until splom implements 'mode' - trace.type === 'splom' - ); - }, - - hasText: function(trace) { - return trace.visible && trace.mode && - trace.mode.indexOf('text') !== -1; - }, - - isBubble: function(trace) { - return Lib.isPlainObject(trace.marker) && - Lib.isArrayOrTypedArray(trace.marker.size); - } -}; - -},{"../../lib":719}],1136:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -/* - * opts: object of flags to control features not all text users support - * noSelect: caller does not support selected/unselected attribute containers - */ -module.exports = function(traceIn, traceOut, layout, coerce, opts) { - opts = opts || {}; - - coerce('textposition'); - Lib.coerceFont(coerce, 'textfont', layout.font); - - if(!opts.noSelect) { - coerce('selected.textfont.color'); - coerce('unselected.textfont.color'); - } -}; - -},{"../../lib":719}],1137:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); - -module.exports = function handleXYDefaults(traceIn, traceOut, layout, coerce) { - var x = coerce('x'); - var y = coerce('y'); - var len; - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, ['x', 'y'], layout); - - if(x) { - var xlen = Lib.minRowLength(x); - if(y) { - len = Math.min(xlen, Lib.minRowLength(y)); - } else { - len = xlen; - coerce('y0'); - coerce('dy'); - } - } else { - if(!y) return 0; - - len = Lib.minRowLength(y); - coerce('x0'); - coerce('dx'); - } - - traceOut._length = len; - - return len; -}; - -},{"../../lib":719,"../../registry":847}],1138:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterAttrs = _dereq_('../scatter/attributes'); -var colorAttributes = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var baseAttrs = _dereq_('../../plots/attributes'); -var DASHES = _dereq_('../../constants/gl3d_dashes'); - -var MARKER_SYMBOLS = _dereq_('../../constants/gl3d_markers'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var scatterLineAttrs = scatterAttrs.line; -var scatterMarkerAttrs = scatterAttrs.marker; -var scatterMarkerLineAttrs = scatterMarkerAttrs.line; - -var lineAttrs = extendFlat({ - width: scatterLineAttrs.width, - dash: { - valType: 'enumerated', - values: Object.keys(DASHES), - dflt: 'solid', - - - } -}, colorAttributes('line')); - -function makeProjectionAttr(axLetter) { - return { - show: { - valType: 'boolean', - - dflt: false, - - }, - opacity: { - valType: 'number', - - min: 0, - max: 1, - dflt: 1, - - }, - scale: { - valType: 'number', - - min: 0, - max: 10, - dflt: 2 / 3, - - } - }; -} - -var attrs = module.exports = overrideAll({ - x: scatterAttrs.x, - y: scatterAttrs.y, - z: { - valType: 'data_array', - - }, - - text: extendFlat({}, scatterAttrs.text, { - - }), - hovertext: extendFlat({}, scatterAttrs.hovertext, { - - }), - hovertemplate: hovertemplateAttrs(), - - mode: extendFlat({}, scatterAttrs.mode, // shouldn't this be on-par with 2D? - {dflt: 'lines+markers'}), - surfaceaxis: { - valType: 'enumerated', - - values: [-1, 0, 1, 2], - dflt: -1, - - }, - surfacecolor: { - valType: 'color', - - - }, - projection: { - x: makeProjectionAttr('x'), - y: makeProjectionAttr('y'), - z: makeProjectionAttr('z') - }, - - connectgaps: scatterAttrs.connectgaps, - line: lineAttrs, - - marker: extendFlat({ // Parity with scatter.js? - symbol: { - valType: 'enumerated', - values: Object.keys(MARKER_SYMBOLS), - - dflt: 'circle', - arrayOk: true, - - }, - size: extendFlat({}, scatterMarkerAttrs.size, {dflt: 8}), - sizeref: scatterMarkerAttrs.sizeref, - sizemin: scatterMarkerAttrs.sizemin, - sizemode: scatterMarkerAttrs.sizemode, - opacity: extendFlat({}, scatterMarkerAttrs.opacity, { - arrayOk: false, - - }), - colorbar: scatterMarkerAttrs.colorbar, - - line: extendFlat({ - width: extendFlat({}, scatterMarkerLineAttrs.width, {arrayOk: false}) - }, - colorAttributes('marker.line') - ) - }, - colorAttributes('marker') - ), - - textposition: extendFlat({}, scatterAttrs.textposition, {dflt: 'top center'}), - textfont: { - color: scatterAttrs.textfont.color, - size: scatterAttrs.textfont.size, - family: extendFlat({}, scatterAttrs.textfont.family, {arrayOk: false}) - }, - - hoverinfo: extendFlat({}, baseAttrs.hoverinfo) -}, 'calc', 'nested'); - -attrs.x.editType = attrs.y.editType = attrs.z.editType = 'calc+clearAxisTypes'; - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../constants/gl3d_dashes":692,"../../constants/gl3d_markers":693,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plots/attributes":764,"../scatter/attributes":1112}],1139:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); -var calcColorscale = _dereq_('../scatter/colorscale_calc'); - -/** - * This is a kludge to put the array attributes into - * calcdata the way Scatter.plot does, so that legends and - * popovers know what to do with them. - */ -module.exports = function calc(gd, trace) { - var cd = [{x: false, y: false, trace: trace, t: {}}]; - - arraysToCalcdata(cd, trace); - calcColorscale(gd, trace); - - return cd; -}; - -},{"../scatter/arrays_to_calcdata":1111,"../scatter/colorscale_calc":1115}],1140:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); - -function calculateAxisErrors(data, params, scaleFactor, axis) { - if(!params || !params.visible) return null; - - var computeError = Registry.getComponentMethod('errorbars', 'makeComputeError')(params); - var result = new Array(data.length); - - for(var i = 0; i < data.length; i++) { - var errors = computeError(+data[i], i); - - if(axis.type === 'log') { - var point = axis.c2l(data[i]); - var min = data[i] - errors[0]; - var max = data[i] + errors[1]; - - result[i] = [ - (axis.c2l(min, true) - point) * scaleFactor, - (axis.c2l(max, true) - point) * scaleFactor - ]; - - // Keep track of the lower error bound which isn't negative! - if(min > 0) { - var lower = axis.c2l(min); - if(!axis._lowerLogErrorBound) axis._lowerLogErrorBound = lower; - axis._lowerErrorBound = Math.min(axis._lowerLogErrorBound, lower); - } - } else { - result[i] = [ - -errors[0] * scaleFactor, - errors[1] * scaleFactor - ]; - } - } - - return result; -} - -function dataLength(array) { - for(var i = 0; i < array.length; i++) { - if(array[i]) return array[i].length; - } - return 0; -} - -function calculateErrors(data, scaleFactor, sceneLayout) { - var errors = [ - calculateAxisErrors(data.x, data.error_x, scaleFactor[0], sceneLayout.xaxis), - calculateAxisErrors(data.y, data.error_y, scaleFactor[1], sceneLayout.yaxis), - calculateAxisErrors(data.z, data.error_z, scaleFactor[2], sceneLayout.zaxis) - ]; - - var n = dataLength(errors); - if(n === 0) return null; - - var errorBounds = new Array(n); - - for(var i = 0; i < n; i++) { - var bound = [[0, 0, 0], [0, 0, 0]]; - - for(var j = 0; j < 3; j++) { - if(errors[j]) { - for(var k = 0; k < 2; k++) { - bound[k][j] = errors[j][i][k]; - } - } - } - - errorBounds[i] = bound; - } - - return errorBounds; -} - -module.exports = calculateErrors; - -},{"../../registry":847}],1141:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var createLinePlot = _dereq_('gl-line3d'); -var createScatterPlot = _dereq_('gl-scatter3d'); -var createErrorBars = _dereq_('gl-error3d'); -var createMesh = _dereq_('gl-mesh3d'); -var triangulate = _dereq_('delaunay-triangulate'); - -var Lib = _dereq_('../../lib'); -var str2RgbaArray = _dereq_('../../lib/str2rgbarray'); -var formatColor = _dereq_('../../lib/gl_format_color').formatColor; -var makeBubbleSizeFn = _dereq_('../scatter/make_bubble_size_func'); -var DASH_PATTERNS = _dereq_('../../constants/gl3d_dashes'); -var MARKER_SYMBOLS = _dereq_('../../constants/gl3d_markers'); - -var calculateError = _dereq_('./calc_errors'); - -function LineWithMarkers(scene, uid) { - this.scene = scene; - this.uid = uid; - this.linePlot = null; - this.scatterPlot = null; - this.errorBars = null; - this.textMarkers = null; - this.delaunayMesh = null; - this.color = null; - this.mode = ''; - this.dataPoints = []; - this.axesBounds = [ - [-Infinity, -Infinity, -Infinity], - [Infinity, Infinity, Infinity] - ]; - this.textLabels = null; - this.data = null; -} - -var proto = LineWithMarkers.prototype; - -proto.handlePick = function(selection) { - if(selection.object && - (selection.object === this.linePlot || - selection.object === this.delaunayMesh || - selection.object === this.textMarkers || - selection.object === this.scatterPlot) - ) { - var ind = selection.index = selection.data.index; - - if(selection.object.highlight) { - selection.object.highlight(null); - } - if(this.scatterPlot) { - selection.object = this.scatterPlot; - this.scatterPlot.highlight(selection.data); - } - - selection.textLabel = ''; - if(this.textLabels) { - if(Array.isArray(this.textLabels)) { - if(this.textLabels[ind] || this.textLabels[ind] === 0) { - selection.textLabel = this.textLabels[ind]; - } - } else { - selection.textLabel = this.textLabels; - } - } - - selection.traceCoordinate = [ - this.data.x[ind], - this.data.y[ind], - this.data.z[ind] - ]; - - return true; - } -}; - -function constructDelaunay(points, color, axis) { - var u = (axis + 1) % 3; - var v = (axis + 2) % 3; - var filteredPoints = []; - var filteredIds = []; - var i; - - for(i = 0; i < points.length; ++i) { - var p = points[i]; - if(isNaN(p[u]) || !isFinite(p[u]) || - isNaN(p[v]) || !isFinite(p[v])) { - continue; - } - filteredPoints.push([p[u], p[v]]); - filteredIds.push(i); - } - var cells = triangulate(filteredPoints); - for(i = 0; i < cells.length; ++i) { - var c = cells[i]; - for(var j = 0; j < c.length; ++j) { - c[j] = filteredIds[c[j]]; - } - } - return { - positions: points, - cells: cells, - meshColor: color - }; -} - -function calculateErrorParams(errors) { - var capSize = [0.0, 0.0, 0.0]; - var color = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]; - var lineWidth = [1.0, 1.0, 1.0]; - - for(var i = 0; i < 3; i++) { - var e = errors[i]; - - if(e && e.copy_zstyle !== false && errors[2].visible !== false) e = errors[2]; - if(!e || !e.visible) continue; - - capSize[i] = e.width / 2; // ballpark rescaling - color[i] = str2RgbaArray(e.color); - lineWidth[i] = e.thickness; - } - - return {capSize: capSize, color: color, lineWidth: lineWidth}; -} - -function parseAlignmentX(a) { - if(a === null || a === undefined) return 0; - - return (a.indexOf('left') > -1) ? -1 : - (a.indexOf('right') > -1) ? 1 : 0; -} - -function parseAlignmentY(a) { - if(a === null || a === undefined) return 0; - - return (a.indexOf('top') > -1) ? -1 : - (a.indexOf('bottom') > -1) ? 1 : 0; -} - -function calculateTextOffset(tp) { - // Read out text properties - - var defaultAlignmentX = 0; - var defaultAlignmentY = 0; - - var textOffset = [ - defaultAlignmentX, - defaultAlignmentY - ]; - - if(Array.isArray(tp)) { - for(var i = 0; i < tp.length; i++) { - textOffset[i] = [ - defaultAlignmentX, - defaultAlignmentY - ]; - if(tp[i]) { - textOffset[i][0] = parseAlignmentX(tp[i]); - textOffset[i][1] = parseAlignmentY(tp[i]); - } - } - } else { - textOffset[0] = parseAlignmentX(tp); - textOffset[1] = parseAlignmentY(tp); - } - - return textOffset; -} - - -function calculateSize(sizeIn, sizeFn) { - // rough parity with Plotly 2D markers - return sizeFn(sizeIn * 4); -} - -function calculateSymbol(symbolIn) { - return MARKER_SYMBOLS[symbolIn]; -} - -function formatParam(paramIn, len, calculate, dflt, extraFn) { - var paramOut = null; - - if(Lib.isArrayOrTypedArray(paramIn)) { - paramOut = []; - - for(var i = 0; i < len; i++) { - if(paramIn[i] === undefined) paramOut[i] = dflt; - else paramOut[i] = calculate(paramIn[i], extraFn); - } - } else paramOut = calculate(paramIn, Lib.identity); - - return paramOut; -} - - -function convertPlotlyOptions(scene, data) { - var points = []; - var sceneLayout = scene.fullSceneLayout; - var scaleFactor = scene.dataScale; - var xaxis = sceneLayout.xaxis; - var yaxis = sceneLayout.yaxis; - var zaxis = sceneLayout.zaxis; - var marker = data.marker; - var line = data.line; - var x = data.x || []; - var y = data.y || []; - var z = data.z || []; - var len = x.length; - var xcalendar = data.xcalendar; - var ycalendar = data.ycalendar; - var zcalendar = data.zcalendar; - var xc, yc, zc; - var params, i; - var text; - - // Convert points - for(i = 0; i < len; i++) { - // sanitize numbers and apply transforms based on axes.type - xc = xaxis.d2l(x[i], 0, xcalendar) * scaleFactor[0]; - yc = yaxis.d2l(y[i], 0, ycalendar) * scaleFactor[1]; - zc = zaxis.d2l(z[i], 0, zcalendar) * scaleFactor[2]; - - points[i] = [xc, yc, zc]; - } - - // convert text - if(Array.isArray(data.text)) text = data.text; - else if(data.text !== undefined) { - text = new Array(len); - for(i = 0; i < len; i++) text[i] = data.text; - } - - // Build object parameters - params = { - position: points, - mode: data.mode, - text: text - }; - - if('line' in data) { - params.lineColor = formatColor(line, 1, len); - params.lineWidth = line.width; - params.lineDashes = line.dash; - } - - if('marker' in data) { - var sizeFn = makeBubbleSizeFn(data); - - params.scatterColor = formatColor(marker, 1, len); - params.scatterSize = formatParam(marker.size, len, calculateSize, 20, sizeFn); - params.scatterMarker = formatParam(marker.symbol, len, calculateSymbol, '●'); - params.scatterLineWidth = marker.line.width; // arrayOk === false - params.scatterLineColor = formatColor(marker.line, 1, len); - params.scatterAngle = 0; - } - - if('textposition' in data) { - params.textOffset = calculateTextOffset(data.textposition); - params.textColor = formatColor(data.textfont, 1, len); - params.textSize = formatParam(data.textfont.size, len, Lib.identity, 12); - params.textFont = data.textfont.family; // arrayOk === false - params.textAngle = 0; - } - - var dims = ['x', 'y', 'z']; - params.project = [false, false, false]; - params.projectScale = [1, 1, 1]; - params.projectOpacity = [1, 1, 1]; - for(i = 0; i < 3; ++i) { - var projection = data.projection[dims[i]]; - if((params.project[i] = projection.show)) { - params.projectOpacity[i] = projection.opacity; - params.projectScale[i] = projection.scale; - } - } - - params.errorBounds = calculateError(data, scaleFactor, sceneLayout); - - var errorParams = calculateErrorParams([data.error_x, data.error_y, data.error_z]); - params.errorColor = errorParams.color; - params.errorLineWidth = errorParams.lineWidth; - params.errorCapSize = errorParams.capSize; - - params.delaunayAxis = data.surfaceaxis; - params.delaunayColor = str2RgbaArray(data.surfacecolor); - - return params; -} - -function arrayToColor(color) { - if(Array.isArray(color)) { - var c = color[0]; - - if(Array.isArray(c)) color = c; - - return 'rgb(' + color.slice(0, 3).map(function(x) { - return Math.round(x * 255); - }) + ')'; - } - - return null; -} - -proto.update = function(data) { - var gl = this.scene.glplot.gl; - var lineOptions; - var scatterOptions; - var errorOptions; - var textOptions; - var dashPattern = DASH_PATTERNS.solid; - - // Save data - this.data = data; - - // Run data conversion - var options = convertPlotlyOptions(this.scene, data); - - if('mode' in options) { - this.mode = options.mode; - } - if('lineDashes' in options) { - if(options.lineDashes in DASH_PATTERNS) { - dashPattern = DASH_PATTERNS[options.lineDashes]; - } - } - - this.color = arrayToColor(options.scatterColor) || - arrayToColor(options.lineColor); - - // Save data points - this.dataPoints = options.position; - - lineOptions = { - gl: this.scene.glplot.gl, - position: options.position, - color: options.lineColor, - lineWidth: options.lineWidth || 1, - dashes: dashPattern[0], - dashScale: dashPattern[1], - opacity: data.opacity, - connectGaps: data.connectgaps - }; - - if(this.mode.indexOf('lines') !== -1) { - if(this.linePlot) this.linePlot.update(lineOptions); - else { - this.linePlot = createLinePlot(lineOptions); - this.linePlot._trace = this; - this.scene.glplot.add(this.linePlot); - } - } else if(this.linePlot) { - this.scene.glplot.remove(this.linePlot); - this.linePlot.dispose(); - this.linePlot = null; - } - - // N.B. marker.opacity must be a scalar for performance - var scatterOpacity = data.opacity; - if(data.marker && data.marker.opacity) scatterOpacity *= data.marker.opacity; - - scatterOptions = { - gl: this.scene.glplot.gl, - position: options.position, - color: options.scatterColor, - size: options.scatterSize, - glyph: options.scatterMarker, - opacity: scatterOpacity, - orthographic: true, - lineWidth: options.scatterLineWidth, - lineColor: options.scatterLineColor, - project: options.project, - projectScale: options.projectScale, - projectOpacity: options.projectOpacity - }; - - if(this.mode.indexOf('markers') !== -1) { - if(this.scatterPlot) this.scatterPlot.update(scatterOptions); - else { - this.scatterPlot = createScatterPlot(scatterOptions); - this.scatterPlot._trace = this; - this.scatterPlot.highlightScale = 1; - this.scene.glplot.add(this.scatterPlot); - } - } else if(this.scatterPlot) { - this.scene.glplot.remove(this.scatterPlot); - this.scatterPlot.dispose(); - this.scatterPlot = null; - } - - textOptions = { - gl: this.scene.glplot.gl, - position: options.position, - glyph: options.text, - color: options.textColor, - size: options.textSize, - angle: options.textAngle, - alignment: options.textOffset, - font: options.textFont, - orthographic: true, - lineWidth: 0, - project: false, - opacity: data.opacity - }; - - this.textLabels = data.hovertext || data.text; - - if(this.mode.indexOf('text') !== -1) { - if(this.textMarkers) this.textMarkers.update(textOptions); - else { - this.textMarkers = createScatterPlot(textOptions); - this.textMarkers._trace = this; - this.textMarkers.highlightScale = 1; - this.scene.glplot.add(this.textMarkers); - } - } else if(this.textMarkers) { - this.scene.glplot.remove(this.textMarkers); - this.textMarkers.dispose(); - this.textMarkers = null; - } - - errorOptions = { - gl: this.scene.glplot.gl, - position: options.position, - color: options.errorColor, - error: options.errorBounds, - lineWidth: options.errorLineWidth, - capSize: options.errorCapSize, - opacity: data.opacity - }; - if(this.errorBars) { - if(options.errorBounds) { - this.errorBars.update(errorOptions); - } else { - this.scene.glplot.remove(this.errorBars); - this.errorBars.dispose(); - this.errorBars = null; - } - } else if(options.errorBounds) { - this.errorBars = createErrorBars(errorOptions); - this.errorBars._trace = this; - this.scene.glplot.add(this.errorBars); - } - - if(options.delaunayAxis >= 0) { - var delaunayOptions = constructDelaunay( - options.position, - options.delaunayColor, - options.delaunayAxis - ); - delaunayOptions.opacity = data.opacity; - - if(this.delaunayMesh) { - this.delaunayMesh.update(delaunayOptions); - } else { - delaunayOptions.gl = gl; - this.delaunayMesh = createMesh(delaunayOptions); - this.delaunayMesh._trace = this; - this.scene.glplot.add(this.delaunayMesh); - } - } else if(this.delaunayMesh) { - this.scene.glplot.remove(this.delaunayMesh); - this.delaunayMesh.dispose(); - this.delaunayMesh = null; - } -}; - -proto.dispose = function() { - if(this.linePlot) { - this.scene.glplot.remove(this.linePlot); - this.linePlot.dispose(); - } - if(this.scatterPlot) { - this.scene.glplot.remove(this.scatterPlot); - this.scatterPlot.dispose(); - } - if(this.errorBars) { - this.scene.glplot.remove(this.errorBars); - this.errorBars.dispose(); - } - if(this.textMarkers) { - this.scene.glplot.remove(this.textMarkers); - this.textMarkers.dispose(); - } - if(this.delaunayMesh) { - this.scene.glplot.remove(this.delaunayMesh); - this.delaunayMesh.dispose(); - } -}; - -function createLineWithMarkers(scene, data) { - var plot = new LineWithMarkers(scene, data.uid); - plot.update(data); - return plot; -} - -module.exports = createLineWithMarkers; - -},{"../../constants/gl3d_dashes":692,"../../constants/gl3d_markers":693,"../../lib":719,"../../lib/gl_format_color":716,"../../lib/str2rgbarray":742,"../scatter/make_bubble_size_func":1128,"./calc_errors":1140,"delaunay-triangulate":165,"gl-error3d":247,"gl-line3d":255,"gl-mesh3d":280,"gl-scatter3d":297}],1142:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); - -var subTypes = _dereq_('../scatter/subtypes'); -var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); -var handleLineDefaults = _dereq_('../scatter/line_defaults'); -var handleTextDefaults = _dereq_('../scatter/text_defaults'); - -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleXYZDefaults(traceIn, traceOut, coerce, layout); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - coerce('mode'); - - if(subTypes.hasLines(traceOut)) { - coerce('connectgaps'); - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - } - - if(subTypes.hasMarkers(traceOut)) { - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noSelect: true}); - } - - if(subTypes.hasText(traceOut)) { - handleTextDefaults(traceIn, traceOut, layout, coerce, {noSelect: true}); - } - - var lineColor = (traceOut.line || {}).color; - var markerColor = (traceOut.marker || {}).color; - if(coerce('surfaceaxis') >= 0) coerce('surfacecolor', lineColor || markerColor); - - var dims = ['x', 'y', 'z']; - for(var i = 0; i < 3; ++i) { - var projection = 'projection.' + dims[i]; - if(coerce(projection + '.show')) { - coerce(projection + '.opacity'); - coerce(projection + '.scale'); - } - } - - var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || markerColor || defaultColor, {axis: 'z'}); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || markerColor || defaultColor, {axis: 'y', inherit: 'z'}); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || markerColor || defaultColor, {axis: 'x', inherit: 'z'}); -}; - -function handleXYZDefaults(traceIn, traceOut, coerce, layout) { - var len = 0; - var x = coerce('x'); - var y = coerce('y'); - var z = coerce('z'); - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout); - - if(x && y && z) { - // TODO: what happens if one is missing? - len = Math.min(x.length, y.length, z.length); - traceOut._length = traceOut._xlength = traceOut._ylength = traceOut._zlength = len; - } - - return len; -} - -},{"../../lib":719,"../../registry":847,"../scatter/line_defaults":1124,"../scatter/marker_defaults":1130,"../scatter/subtypes":1135,"../scatter/text_defaults":1136,"./attributes":1138}],1143:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - plot: _dereq_('./convert'), - attributes: _dereq_('./attributes'), - markerSymbols: _dereq_('../../constants/gl3d_markers'), - supplyDefaults: _dereq_('./defaults'), - colorbar: [ - { - container: 'marker', - min: 'cmin', - max: 'cmax' - }, { - container: 'line', - min: 'cmin', - max: 'cmax' - } - ], - calc: _dereq_('./calc'), - - moduleType: 'trace', - name: 'scatter3d', - basePlotModule: _dereq_('../../plots/gl3d'), - categories: ['gl3d', 'symbols', 'showLegend'], - meta: { - - - } -}; - -},{"../../constants/gl3d_markers":693,"../../plots/gl3d":807,"./attributes":1138,"./calc":1139,"./convert":1141,"./defaults":1142}],1144:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterAttrs = _dereq_('../scatter/attributes'); -var plotAttrs = _dereq_('../../plots/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var scatterMarkerAttrs = scatterAttrs.marker; -var scatterLineAttrs = scatterAttrs.line; -var scatterMarkerLineAttrs = scatterMarkerAttrs.line; - -module.exports = { - carpet: { - valType: 'string', - - editType: 'calc', - - }, - a: { - valType: 'data_array', - editType: 'calc', - - }, - b: { - valType: 'data_array', - editType: 'calc', - - }, - mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}), - text: extendFlat({}, scatterAttrs.text, { - - }), - hovertext: extendFlat({}, scatterAttrs.hovertext, { - - }), - line: { - color: scatterLineAttrs.color, - width: scatterLineAttrs.width, - dash: scatterLineAttrs.dash, - shape: extendFlat({}, scatterLineAttrs.shape, - {values: ['linear', 'spline']}), - smoothing: scatterLineAttrs.smoothing, - editType: 'calc' - }, - connectgaps: scatterAttrs.connectgaps, - fill: extendFlat({}, scatterAttrs.fill, { - values: ['none', 'toself', 'tonext'], - dflt: 'none', - - }), - fillcolor: scatterAttrs.fillcolor, - marker: extendFlat({ - symbol: scatterMarkerAttrs.symbol, - opacity: scatterMarkerAttrs.opacity, - maxdisplayed: scatterMarkerAttrs.maxdisplayed, - size: scatterMarkerAttrs.size, - sizeref: scatterMarkerAttrs.sizeref, - sizemin: scatterMarkerAttrs.sizemin, - sizemode: scatterMarkerAttrs.sizemode, - line: extendFlat({ - width: scatterMarkerLineAttrs.width, - editType: 'calc' - }, - colorScaleAttrs('marker.line') - ), - gradient: scatterMarkerAttrs.gradient, - editType: 'calc' - }, - colorScaleAttrs('marker') - ), - - textfont: scatterAttrs.textfont, - textposition: scatterAttrs.textposition, - - selected: scatterAttrs.selected, - unselected: scatterAttrs.unselected, - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['a', 'b', 'text', 'name'] - }), - hoveron: scatterAttrs.hoveron, - hovertemplate: hovertemplateAttrs() -}; - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../scatter/attributes":1112}],1145:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var calcColorscale = _dereq_('../scatter/colorscale_calc'); -var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); -var calcSelection = _dereq_('../scatter/calc_selection'); -var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; -var lookupCarpet = _dereq_('../carpet/lookup_carpetid'); - -module.exports = function calc(gd, trace) { - var carpet = trace._carpetTrace = lookupCarpet(gd, trace); - if(!carpet || !carpet.visible || carpet.visible === 'legendonly') return; - var i; - - // Transfer this over from carpet before plotting since this is a necessary - // condition in order for cartesian to actually plot this trace: - trace.xaxis = carpet.xaxis; - trace.yaxis = carpet.yaxis; - - // make the calcdata array - var serieslen = trace._length; - var cd = new Array(serieslen); - var a, b; - var needsCull = false; - for(i = 0; i < serieslen; i++) { - a = trace.a[i]; - b = trace.b[i]; - if(isNumeric(a) && isNumeric(b)) { - var xy = carpet.ab2xy(+a, +b, true); - var visible = carpet.isVisible(+a, +b); - if(!visible) needsCull = true; - cd[i] = {x: xy[0], y: xy[1], a: a, b: b, vis: visible}; - } else cd[i] = {x: false, y: false}; - } - - trace._needsCull = needsCull; - - cd[0].carpet = carpet; - cd[0].trace = trace; - - calcMarkerSize(trace, serieslen); - calcColorscale(gd, trace); - arraysToCalcdata(cd, trace); - calcSelection(cd, trace); - - return cd; -}; - -},{"../carpet/lookup_carpetid":915,"../scatter/arrays_to_calcdata":1111,"../scatter/calc":1113,"../scatter/calc_selection":1114,"../scatter/colorscale_calc":1115,"fast-isnumeric":225}],1146:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var constants = _dereq_('../scatter/constants'); -var subTypes = _dereq_('../scatter/subtypes'); -var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); -var handleLineDefaults = _dereq_('../scatter/line_defaults'); -var handleLineShapeDefaults = _dereq_('../scatter/line_shape_defaults'); -var handleTextDefaults = _dereq_('../scatter/text_defaults'); -var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); - -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - coerce('carpet'); - - // XXX: Don't hard code this - traceOut.xaxis = 'x'; - traceOut.yaxis = 'y'; - - var a = coerce('a'); - var b = coerce('b'); - var len = Math.min(a.length, b.length); - - if(!len) { - traceOut.visible = false; - return; - } - - traceOut._length = len; - - coerce('text'); - coerce('hovertext'); - - var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines'; - coerce('mode', defaultMode); - - if(subTypes.hasLines(traceOut)) { - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - handleLineShapeDefaults(traceIn, traceOut, coerce); - coerce('connectgaps'); - } - - if(subTypes.hasMarkers(traceOut)) { - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); - } - - if(subTypes.hasText(traceOut)) { - handleTextDefaults(traceIn, traceOut, layout, coerce); - } - - var dfltHoverOn = []; - - if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) { - coerce('marker.maxdisplayed'); - dfltHoverOn.push('points'); - } - - coerce('fill'); - if(traceOut.fill !== 'none') { - handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); - if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); - } - - if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') { - dfltHoverOn.push('fills'); - } - - var hoverOn = coerce('hoveron', dfltHoverOn.join('+') || 'points'); - if(hoverOn !== 'fills') coerce('hovertemplate'); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -},{"../../lib":719,"../scatter/constants":1116,"../scatter/fillcolor_defaults":1120,"../scatter/line_defaults":1124,"../scatter/line_shape_defaults":1126,"../scatter/marker_defaults":1130,"../scatter/subtypes":1135,"../scatter/text_defaults":1136,"./attributes":1144}],1147:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function eventData(out, pt, trace, cd, pointNumber) { - var cdi = cd[pointNumber]; - - out.a = cdi.a; - out.b = cdi.b; - out.y = cdi.y; - - return out; -}; - -},{}],1148:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterHover = _dereq_('../scatter/hover'); -var fillText = _dereq_('../../lib').fillText; - -module.exports = function hoverPoints(pointData, xval, yval, hovermode) { - var scatterPointData = scatterHover(pointData, xval, yval, hovermode); - if(!scatterPointData || scatterPointData[0].index === false) return; - - var newPointData = scatterPointData[0]; - - // if hovering on a fill, we don't show any point data so the label is - // unchanged from what scatter gives us - except that it needs to - // be constrained to the trianglular plot area, not just the rectangular - // area defined by the synthetic x and y axes - // TODO: in some cases the vertical middle of the shape is not within - // the triangular viewport at all, so the label can become disconnected - // from the shape entirely. But calculating what portion of the shape - // is actually visible, as constrained by the diagonal axis lines, is not - // so easy and anyway we lost the information we would have needed to do - // this inside scatterHover. - if(newPointData.index === undefined) { - var yFracUp = 1 - (newPointData.y0 / pointData.ya._length); - var xLen = pointData.xa._length; - var xMin = xLen * yFracUp / 2; - var xMax = xLen - xMin; - newPointData.x0 = Math.max(Math.min(newPointData.x0, xMax), xMin); - newPointData.x1 = Math.max(Math.min(newPointData.x1, xMax), xMin); - return scatterPointData; - } - - var cdi = newPointData.cd[newPointData.index]; - - newPointData.a = cdi.a; - newPointData.b = cdi.b; - - newPointData.xLabelVal = undefined; - newPointData.yLabelVal = undefined; - // TODO: nice formatting, and label by axis title, for a, b, and c? - - var trace = newPointData.trace; - var carpet = trace._carpet; - - var ij = carpet.ab2ij([cdi.a, cdi.b]); - var i0 = Math.floor(ij[0]); - var ti = ij[0] - i0; - var j0 = Math.floor(ij[1]); - var tj = ij[1] - j0; - var xy = carpet.evalxy([], i0, j0, ti, tj); - newPointData.yLabel = xy[1].toFixed(3); - - delete newPointData.text; - var text = []; - - function textPart(ax, val) { - var prefix; - - if(ax.labelprefix && ax.labelprefix.length > 0) { - prefix = ax.labelprefix.replace(/ = $/, ''); - } else { - prefix = ax._hovertitle; - } - - text.push(prefix + ': ' + val.toFixed(3) + ax.labelsuffix); - } - - - if(!trace.hovertemplate) { - var hoverinfo = cdi.hi || trace.hoverinfo; - var parts = hoverinfo.split('+'); - - if(parts.indexOf('all') !== -1) parts = ['a', 'b', 'text']; - if(parts.indexOf('a') !== -1) textPart(carpet.aaxis, cdi.a); - if(parts.indexOf('b') !== -1) textPart(carpet.baxis, cdi.b); - - text.push('y: ' + newPointData.yLabel); - - if(parts.indexOf('text') !== -1) { - fillText(cdi, trace, text); - } - - newPointData.extraText = text.join('
'); - } - - return scatterPointData; -}; - -},{"../../lib":719,"../scatter/hover":1122}],1149:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../scatter/marker_colorbar'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - style: _dereq_('../scatter/style').style, - styleOnSelect: _dereq_('../scatter/style').styleOnSelect, - hoverPoints: _dereq_('./hover'), - selectPoints: _dereq_('../scatter/select'), - eventData: _dereq_('./event_data'), - - moduleType: 'trace', - name: 'scattercarpet', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['svg', 'carpet', 'symbols', 'showLegend', 'carpetDependent', 'zoomScale'], - meta: { - - - } -}; - -},{"../../plots/cartesian":778,"../scatter/marker_colorbar":1129,"../scatter/select":1132,"../scatter/style":1134,"./attributes":1144,"./calc":1145,"./defaults":1146,"./event_data":1147,"./hover":1148,"./plot":1150}],1150:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var scatterPlot = _dereq_('../scatter/plot'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var Drawing = _dereq_('../../components/drawing'); - -module.exports = function plot(gd, plotinfoproxy, data, layer) { - var i, trace, node; - - var carpet = data[0][0].carpet; - // mimic cartesian plotinfo - var plotinfo = { - xaxis: Axes.getFromId(gd, carpet.xaxis || 'x'), - yaxis: Axes.getFromId(gd, carpet.yaxis || 'y'), - plot: plotinfoproxy.plot, - }; - - scatterPlot(gd, plotinfo, data, layer); - - for(i = 0; i < data.length; i++) { - trace = data[i][0].trace; - - // Note: .select is adequate but seems to mutate the node data, - // which is at least a bit suprising and causes problems elsewhere - node = layer.selectAll('g.trace' + trace.uid + ' .js-line'); - - // Note: it would be more efficient if this didn't need to be applied - // separately to all scattercarpet traces, but that would require - // lots of reorganization of scatter traces that is otherwise not - // necessary. That makes this a potential optimization. - Drawing.setClipUrl(node, data[i][0].carpet._clipPathId, gd); - } -}; - -},{"../../components/drawing":614,"../../plots/cartesian/axes":767,"../scatter/plot":1131}],1151:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var scatterAttrs = _dereq_('../scatter/attributes'); -var plotAttrs = _dereq_('../../plots/attributes'); -var colorAttributes = _dereq_('../../components/colorscale/attributes'); -var dash = _dereq_('../../components/drawing/attributes').dash; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var scatterMarkerAttrs = scatterAttrs.marker; -var scatterLineAttrs = scatterAttrs.line; -var scatterMarkerLineAttrs = scatterMarkerAttrs.line; - -module.exports = overrideAll({ - lon: { - valType: 'data_array', - - }, - lat: { - valType: 'data_array', - - }, - - locations: { - valType: 'data_array', - - }, - locationmode: { - valType: 'enumerated', - values: ['ISO-3', 'USA-states', 'country names'], - - dflt: 'ISO-3', - - }, - - mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}), - - text: extendFlat({}, scatterAttrs.text, { - - }), - hovertext: extendFlat({}, scatterAttrs.hovertext, { - - }), - - textfont: scatterAttrs.textfont, - textposition: scatterAttrs.textposition, - - line: { - color: scatterLineAttrs.color, - width: scatterLineAttrs.width, - dash: dash - }, - connectgaps: scatterAttrs.connectgaps, - - marker: extendFlat({ - symbol: scatterMarkerAttrs.symbol, - opacity: scatterMarkerAttrs.opacity, - size: scatterMarkerAttrs.size, - sizeref: scatterMarkerAttrs.sizeref, - sizemin: scatterMarkerAttrs.sizemin, - sizemode: scatterMarkerAttrs.sizemode, - colorbar: scatterMarkerAttrs.colorbar, - line: extendFlat({ - width: scatterMarkerLineAttrs.width - }, - colorAttributes('marker.line') - ), - gradient: scatterMarkerAttrs.gradient - }, - colorAttributes('marker') - ), - - fill: { - valType: 'enumerated', - values: ['none', 'toself'], - dflt: 'none', - - - }, - fillcolor: scatterAttrs.fillcolor, - - selected: scatterAttrs.selected, - unselected: scatterAttrs.unselected, - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['lon', 'lat', 'location', 'text', 'name'] - }), - hovertemplate: hovertemplateAttrs(), -}, 'calc', 'nested'); - -},{"../../components/colorscale/attributes":600,"../../components/drawing/attributes":613,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plots/attributes":764,"../scatter/attributes":1112}],1152:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -var calcMarkerColorscale = _dereq_('../scatter/colorscale_calc'); -var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); -var calcSelection = _dereq_('../scatter/calc_selection'); - -var _ = _dereq_('../../lib')._; - -module.exports = function calc(gd, trace) { - var hasLocationData = Array.isArray(trace.locations); - var len = hasLocationData ? trace.locations.length : trace._length; - var calcTrace = new Array(len); - - for(var i = 0; i < len; i++) { - var calcPt = calcTrace[i] = {}; - - if(hasLocationData) { - var loc = trace.locations[i]; - calcPt.loc = typeof loc === 'string' ? loc : null; - } else { - var lon = trace.lon[i]; - var lat = trace.lat[i]; - - if(isNumeric(lon) && isNumeric(lat)) calcPt.lonlat = [+lon, +lat]; - else calcPt.lonlat = [BADNUM, BADNUM]; - } - } - - arraysToCalcdata(calcTrace, trace); - calcMarkerColorscale(gd, trace); - calcSelection(calcTrace, trace); - - if(len) { - calcTrace[0].t = { - labels: { - lat: _(gd, 'lat:') + ' ', - lon: _(gd, 'lon:') + ' ' - } - }; - } - - return calcTrace; -}; - -},{"../../constants/numerical":695,"../../lib":719,"../scatter/arrays_to_calcdata":1111,"../scatter/calc_selection":1114,"../scatter/colorscale_calc":1115,"fast-isnumeric":225}],1153:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var subTypes = _dereq_('../scatter/subtypes'); -var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); -var handleLineDefaults = _dereq_('../scatter/line_defaults'); -var handleTextDefaults = _dereq_('../scatter/text_defaults'); -var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); - -var attributes = _dereq_('./attributes'); - - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleLonLatLocDefaults(traceIn, traceOut, coerce); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - coerce('mode'); - - if(subTypes.hasLines(traceOut)) { - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - coerce('connectgaps'); - } - - if(subTypes.hasMarkers(traceOut)) { - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); - } - - if(subTypes.hasText(traceOut)) { - handleTextDefaults(traceIn, traceOut, layout, coerce); - } - - coerce('fill'); - if(traceOut.fill !== 'none') { - handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); - } - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -function handleLonLatLocDefaults(traceIn, traceOut, coerce) { - var len = 0; - var locations = coerce('locations'); - - var lon, lat; - - if(locations) { - coerce('locationmode'); - len = locations.length; - return len; - } - - lon = coerce('lon') || []; - lat = coerce('lat') || []; - len = Math.min(lon.length, lat.length); - traceOut._length = len; - - return len; -} - -},{"../../lib":719,"../scatter/fillcolor_defaults":1120,"../scatter/line_defaults":1124,"../scatter/marker_defaults":1130,"../scatter/subtypes":1135,"../scatter/text_defaults":1136,"./attributes":1151}],1154:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -module.exports = function eventData(out, pt) { - out.lon = pt.lon; - out.lat = pt.lat; - out.location = pt.loc ? pt.loc : null; - - return out; -}; - -},{}],1155:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Fx = _dereq_('../../components/fx'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -var getTraceColor = _dereq_('../scatter/get_trace_color'); -var fillText = _dereq_('../../lib').fillText; -var attributes = _dereq_('./attributes'); - -module.exports = function hoverPoints(pointData, xval, yval) { - var cd = pointData.cd; - var trace = cd[0].trace; - var xa = pointData.xa; - var ya = pointData.ya; - var geo = pointData.subplot; - - var isLonLatOverEdges = geo.projection.isLonLatOverEdges; - var project = geo.project; - - function distFn(d) { - var lonlat = d.lonlat; - - if(lonlat[0] === BADNUM) return Infinity; - if(isLonLatOverEdges(lonlat)) return Infinity; - - var pt = project(lonlat); - var px = project([xval, yval]); - var dx = Math.abs(pt[0] - px[0]); - var dy = Math.abs(pt[1] - px[1]); - var rad = Math.max(3, d.mrc || 0); - - // N.B. d.mrc is the calculated marker radius - // which is only set for trace with 'markers' mode. - - return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - 3 / rad); - } - - Fx.getClosest(cd, distFn, pointData); - - // skip the rest (for this trace) if we didn't find a close point - if(pointData.index === false) return; - - var di = cd[pointData.index]; - var lonlat = di.lonlat; - var pos = [xa.c2p(lonlat), ya.c2p(lonlat)]; - var rad = di.mrc || 1; - - pointData.x0 = pos[0] - rad; - pointData.x1 = pos[0] + rad; - pointData.y0 = pos[1] - rad; - pointData.y1 = pos[1] + rad; - - pointData.loc = di.loc; - pointData.lon = lonlat[0]; - pointData.lat = lonlat[1]; - - var ax = geo.mockAxis; - pointData.lonLabel = Axes.tickText(ax, ax.c2l(pointData.lon), 'hover').text; - pointData.latLabel = Axes.tickText(ax, ax.c2l(pointData.lat), 'hover').text; - - pointData.color = getTraceColor(trace, di); - pointData.extraText = getExtraText(trace, di, pointData, cd[0].t.labels); - pointData.hovertemplate = trace.hovertemplate; - - return [pointData]; -}; - -function getExtraText(trace, pt, pointData, labels) { - if(trace.hovertemplate) return; - - var hoverinfo = pt.hi || trace.hoverinfo; - - var parts = hoverinfo === 'all' ? - attributes.hoverinfo.flags : - hoverinfo.split('+'); - - var hasLocation = parts.indexOf('location') !== -1 && Array.isArray(trace.locations); - var hasLon = (parts.indexOf('lon') !== -1); - var hasLat = (parts.indexOf('lat') !== -1); - var hasText = (parts.indexOf('text') !== -1); - var text = []; - - function format(val) { return val + '\u00B0'; } - - if(hasLocation) { - text.push(pt.loc); - } else if(hasLon && hasLat) { - text.push('(' + format(pointData.lonLabel) + ', ' + format(pointData.latLabel) + ')'); - } else if(hasLon) { - text.push(labels.lon + format(pointData.lonLabel)); - } else if(hasLat) { - text.push(labels.lat + format(pointData.latLabel)); - } - - if(hasText) { - fillText(pt, trace, text); - } - - return text.join('
'); -} - -},{"../../components/fx":632,"../../constants/numerical":695,"../../lib":719,"../../plots/cartesian/axes":767,"../scatter/get_trace_color":1121,"./attributes":1151}],1156:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../scatter/marker_colorbar'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - style: _dereq_('./style'), - styleOnSelect: _dereq_('../scatter/style').styleOnSelect, - hoverPoints: _dereq_('./hover'), - eventData: _dereq_('./event_data'), - selectPoints: _dereq_('./select'), - - moduleType: 'trace', - name: 'scattergeo', - basePlotModule: _dereq_('../../plots/geo'), - categories: ['geo', 'symbols', 'showLegend', 'scatter-like'], - meta: { - - - } -}; - -},{"../../plots/geo":797,"../scatter/marker_colorbar":1129,"../scatter/style":1134,"./attributes":1151,"./calc":1152,"./defaults":1153,"./event_data":1154,"./hover":1155,"./plot":1157,"./select":1158,"./style":1159}],1157:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var d3 = _dereq_('d3'); - -var Lib = _dereq_('../../lib'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; -var getTopojsonFeatures = _dereq_('../../lib/topojson_utils').getTopojsonFeatures; -var locationToFeature = _dereq_('../../lib/geo_location_utils').locationToFeature; -var geoJsonUtils = _dereq_('../../lib/geojson_utils'); -var subTypes = _dereq_('../scatter/subtypes'); -var style = _dereq_('./style'); - -module.exports = function plot(gd, geo, calcData) { - for(var i = 0; i < calcData.length; i++) { - calcGeoJSON(calcData[i], geo.topojson); - } - - function removeBADNUM(d, node) { - if(d.lonlat[0] === BADNUM) { - d3.select(node).remove(); - } - } - - var scatterLayer = geo.layers.frontplot.select('.scatterlayer'); - var gTraces = Lib.makeTraceGroups(scatterLayer, calcData, 'trace scattergeo'); - - // TODO find a way to order the inner nodes on update - gTraces.selectAll('*').remove(); - - gTraces.each(function(calcTrace) { - var s = d3.select(this); - var trace = calcTrace[0].trace; - - if(subTypes.hasLines(trace) || trace.fill !== 'none') { - var lineCoords = geoJsonUtils.calcTraceToLineCoords(calcTrace); - - var lineData = (trace.fill !== 'none') ? - geoJsonUtils.makePolygon(lineCoords) : - geoJsonUtils.makeLine(lineCoords); - - s.selectAll('path.js-line') - .data([{geojson: lineData, trace: trace}]) - .enter().append('path') - .classed('js-line', true) - .style('stroke-miterlimit', 2); - } - - if(subTypes.hasMarkers(trace)) { - s.selectAll('path.point') - .data(Lib.identity) - .enter().append('path') - .classed('point', true) - .each(function(calcPt) { removeBADNUM(calcPt, this); }); - } - - if(subTypes.hasText(trace)) { - s.selectAll('g') - .data(Lib.identity) - .enter().append('g') - .append('text') - .each(function(calcPt) { removeBADNUM(calcPt, this); }); - } - - // call style here within topojson request callback - style(gd, calcTrace); - }); -}; - -function calcGeoJSON(calcTrace, topojson) { - var trace = calcTrace[0].trace; - - if(!Array.isArray(trace.locations)) return; - - var features = getTopojsonFeatures(trace, topojson); - var locationmode = trace.locationmode; - - for(var i = 0; i < calcTrace.length; i++) { - var calcPt = calcTrace[i]; - var feature = locationToFeature(locationmode, calcPt.loc, features); - - calcPt.lonlat = feature ? feature.properties.ct : [BADNUM, BADNUM]; - } -} - -},{"../../constants/numerical":695,"../../lib":719,"../../lib/geo_location_utils":713,"../../lib/geojson_utils":714,"../../lib/topojson_utils":746,"../scatter/subtypes":1135,"./style":1159,"d3":163}],1158:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var subtypes = _dereq_('../scatter/subtypes'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -module.exports = function selectPoints(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var xa = searchInfo.xaxis; - var ya = searchInfo.yaxis; - var selection = []; - var trace = cd[0].trace; - - var di, lonlat, x, y, i; - - var hasOnlyLines = (!subtypes.hasMarkers(trace) && !subtypes.hasText(trace)); - if(hasOnlyLines) return []; - - if(selectionTester === false) { - for(i = 0; i < cd.length; i++) { - cd[i].selected = 0; - } - } else { - for(i = 0; i < cd.length; i++) { - di = cd[i]; - lonlat = di.lonlat; - - // some projection types can't handle BADNUMs - if(lonlat[0] === BADNUM) continue; - - x = xa.c2p(lonlat); - y = ya.c2p(lonlat); - - if(selectionTester.contains([x, y], null, i, searchInfo)) { - selection.push({ - pointNumber: i, - lon: lonlat[0], - lat: lonlat[1] - }); - di.selected = 1; - } else { - di.selected = 0; - } - } - } - - return selection; -}; - -},{"../../constants/numerical":695,"../scatter/subtypes":1135}],1159:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Drawing = _dereq_('../../components/drawing'); -var Color = _dereq_('../../components/color'); - -var scatterStyle = _dereq_('../scatter/style'); -var stylePoints = scatterStyle.stylePoints; -var styleText = scatterStyle.styleText; - -module.exports = function style(gd, calcTrace) { - if(calcTrace) styleTrace(gd, calcTrace); -}; - -function styleTrace(gd, calcTrace) { - var trace = calcTrace[0].trace; - var s = calcTrace[0].node3; - - s.style('opacity', calcTrace[0].trace.opacity); - - stylePoints(s, trace, gd); - styleText(s, trace, gd); - - // this part is incompatible with Drawing.lineGroupStyle - s.selectAll('path.js-line') - .style('fill', 'none') - .each(function(d) { - var path = d3.select(this); - var trace = d.trace; - var line = trace.line || {}; - - path.call(Color.stroke, line.color) - .call(Drawing.dashLine, line.dash || '', line.width || 0); - - if(trace.fill !== 'none') { - path.call(Color.fill, trace.fillcolor); - } - }); -} - -},{"../../components/color":593,"../../components/drawing":614,"../scatter/style":1134,"d3":163}],1160:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var plotAttrs = _dereq_('../../plots/attributes'); -var scatterAttrs = _dereq_('../scatter/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var DASHES = _dereq_('./constants').DASHES; - -var scatterLineAttrs = scatterAttrs.line; -var scatterMarkerAttrs = scatterAttrs.marker; -var scatterMarkerLineAttrs = scatterMarkerAttrs.line; - -var attrs = module.exports = overrideAll({ - x: scatterAttrs.x, - x0: scatterAttrs.x0, - dx: scatterAttrs.dx, - y: scatterAttrs.y, - y0: scatterAttrs.y0, - dy: scatterAttrs.dy, - - text: scatterAttrs.text, - hovertext: scatterAttrs.hovertext, - - textposition: scatterAttrs.textposition, - textfont: scatterAttrs.textfont, - - mode: { - valType: 'flaglist', - flags: ['lines', 'markers', 'text'], - extras: ['none'], - - - }, - line: { - color: scatterLineAttrs.color, - width: scatterLineAttrs.width, - shape: { - valType: 'enumerated', - values: ['linear', 'hv', 'vh', 'hvh', 'vhv'], - dflt: 'linear', - - editType: 'plot', - - }, - dash: { - valType: 'enumerated', - values: Object.keys(DASHES), - dflt: 'solid', - - - } - }, - marker: extendFlat({}, colorScaleAttrs('marker'), { - symbol: scatterMarkerAttrs.symbol, - size: scatterMarkerAttrs.size, - sizeref: scatterMarkerAttrs.sizeref, - sizemin: scatterMarkerAttrs.sizemin, - sizemode: scatterMarkerAttrs.sizemode, - opacity: scatterMarkerAttrs.opacity, - colorbar: scatterMarkerAttrs.colorbar, - line: extendFlat({}, colorScaleAttrs('marker.line'), { - width: scatterMarkerLineAttrs.width - }) - }), - connectgaps: scatterAttrs.connectgaps, - fill: extendFlat({}, scatterAttrs.fill, {dflt: 'none'}), - fillcolor: scatterAttrs.fillcolor, - - // no hoveron - - selected: { - marker: scatterAttrs.selected.marker, - textfont: scatterAttrs.selected.textfont - }, - unselected: { - marker: scatterAttrs.unselected.marker, - textfont: scatterAttrs.unselected.textfont - }, - - opacity: plotAttrs.opacity - -}, 'calc', 'nested'); - -attrs.x.editType = attrs.y.editType = attrs.x0.editType = attrs.y0.editType = 'calc+clearAxisTypes'; -attrs.hovertemplate = scatterAttrs.hovertemplate; - -},{"../../components/colorscale/attributes":600,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plots/attributes":764,"../scatter/attributes":1112,"./constants":1162}],1161:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var cluster = _dereq_('point-cluster'); - -var Lib = _dereq_('../../lib'); -var AxisIDs = _dereq_('../../plots/cartesian/axis_ids'); -var findExtremes = _dereq_('../../plots/cartesian/autorange').findExtremes; - -var scatterCalc = _dereq_('../scatter/calc'); -var calcMarkerSize = scatterCalc.calcMarkerSize; -var calcAxisExpansion = scatterCalc.calcAxisExpansion; -var setFirstScatter = scatterCalc.setFirstScatter; -var calcColorscale = _dereq_('../scatter/colorscale_calc'); -var convert = _dereq_('./convert'); -var sceneUpdate = _dereq_('./scene_update'); - -var BADNUM = _dereq_('../../constants/numerical').BADNUM; -var TOO_MANY_POINTS = _dereq_('./constants').TOO_MANY_POINTS; - -module.exports = function calc(gd, trace) { - var fullLayout = gd._fullLayout; - var xa = AxisIDs.getFromId(gd, trace.xaxis); - var ya = AxisIDs.getFromId(gd, trace.yaxis); - var subplot = fullLayout._plots[trace.xaxis + trace.yaxis]; - var len = trace._length; - var hasTooManyPoints = len >= TOO_MANY_POINTS; - var len2 = len * 2; - var stash = {}; - var i, xx, yy; - - var x = xa.makeCalcdata(trace, 'x'); - var y = ya.makeCalcdata(trace, 'y'); - - // we need hi-precision for scatter2d, - // regl-scatter2d uses NaNs for bad/missing values - var positions = new Array(len2); - for(i = 0; i < len; i++) { - xx = x[i]; - yy = y[i]; - positions[i * 2] = xx === BADNUM ? NaN : xx; - positions[i * 2 + 1] = yy === BADNUM ? NaN : yy; - } - - if(xa.type === 'log') { - for(i = 0; i < len2; i += 2) { - positions[i] = xa.c2l(positions[i]); - } - } - if(ya.type === 'log') { - for(i = 1; i < len2; i += 2) { - positions[i] = ya.c2l(positions[i]); - } - } - - // we don't build a tree for log axes since it takes long to convert log2px - // and it is also - if(hasTooManyPoints && (xa.type !== 'log' && ya.type !== 'log')) { - // FIXME: delegate this to webworker - stash.tree = cluster(positions); - } else { - var ids = stash.ids = new Array(len); - for(i = 0; i < len; i++) { - ids[i] = i; - } - } - - // create scene options and scene - calcColorscale(gd, trace); - var opts = sceneOptions(gd, subplot, trace, positions, x, y); - var scene = sceneUpdate(gd, subplot); - - // Reuse SVG scatter axis expansion routine. - // For graphs with very large number of points and array marker.size, - // use average marker size instead to speed things up. - setFirstScatter(fullLayout, trace); - var ppad; - if(!hasTooManyPoints) { - ppad = calcMarkerSize(trace, len); - } else if(opts.marker) { - ppad = 2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3)); - } - calcAxisExpansion(gd, trace, xa, ya, x, y, ppad); - if(opts.errorX) expandForErrorBars(trace, xa, opts.errorX); - if(opts.errorY) expandForErrorBars(trace, ya, opts.errorY); - - // set flags to create scene renderers - if(opts.fill && !scene.fill2d) scene.fill2d = true; - if(opts.marker && !scene.scatter2d) scene.scatter2d = true; - if(opts.line && !scene.line2d) scene.line2d = true; - if((opts.errorX || opts.errorY) && !scene.error2d) scene.error2d = true; - if(opts.text && !scene.glText) scene.glText = true; - - // FIXME: organize it in a more appropriate manner, probably in sceneOptions - // put point-cluster instance for optimized regl calc - if(opts.marker) { - opts.marker.snap = stash.tree || TOO_MANY_POINTS; - } - - scene.lineOptions.push(opts.line); - scene.errorXOptions.push(opts.errorX); - scene.errorYOptions.push(opts.errorY); - scene.fillOptions.push(opts.fill); - scene.markerOptions.push(opts.marker); - scene.markerSelectedOptions.push(opts.markerSel); - scene.markerUnselectedOptions.push(opts.markerUnsel); - scene.textOptions.push(opts.text); - scene.textSelectedOptions.push(opts.textSel); - scene.textUnselectedOptions.push(opts.textUnsel); - scene.selectBatch.push([]); - scene.unselectBatch.push([]); - - stash._scene = scene; - stash.index = scene.count; - stash.x = x; - stash.y = y; - stash.positions = positions; - scene.count++; - - return [{x: false, y: false, t: stash, trace: trace}]; -}; - -function expandForErrorBars(trace, ax, opts) { - var extremes = trace._extremes[ax._id]; - var errExt = findExtremes(ax, opts._bnds, {padded: true}); - extremes.min = extremes.min.concat(errExt.min); - extremes.max = extremes.max.concat(errExt.max); -} - -function sceneOptions(gd, subplot, trace, positions, x, y) { - var opts = convert.style(gd, trace); - - if(opts.marker) { - opts.marker.positions = positions; - } - - if(opts.line && positions.length > 1) { - Lib.extendFlat( - opts.line, - convert.linePositions(gd, trace, positions) - ); - } - - if(opts.errorX || opts.errorY) { - var errors = convert.errorBarPositions(gd, trace, positions, x, y); - - if(opts.errorX) { - Lib.extendFlat(opts.errorX, errors.x); - } - if(opts.errorY) { - Lib.extendFlat(opts.errorY, errors.y); - } - } - - if(opts.text) { - Lib.extendFlat( - opts.text, - {positions: positions}, - convert.textPosition(gd, trace, opts.text, opts.marker) - ); - Lib.extendFlat( - opts.textSel, - {positions: positions}, - convert.textPosition(gd, trace, opts.text, opts.markerSel) - ); - Lib.extendFlat( - opts.textUnsel, - {positions: positions}, - convert.textPosition(gd, trace, opts.text, opts.markerUnsel) - ); - } - - return opts; -} - -},{"../../constants/numerical":695,"../../lib":719,"../../plots/cartesian/autorange":766,"../../plots/cartesian/axis_ids":770,"../scatter/calc":1113,"../scatter/colorscale_calc":1115,"./constants":1162,"./convert":1163,"./scene_update":1169,"point-cluster":469}],1162:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var SYMBOL_SIZE = 20; - -module.exports = { - TOO_MANY_POINTS: 1e5, - - SYMBOL_SDF_SIZE: 200, - SYMBOL_SIZE: SYMBOL_SIZE, - SYMBOL_STROKE: SYMBOL_SIZE / 20, - - DOT_RE: /-dot/, - OPEN_RE: /-open/, - - DASHES: { - solid: [1], - dot: [1, 1], - dash: [4, 1], - longdash: [8, 1], - dashdot: [4, 1, 1, 1], - longdashdot: [8, 1, 1, 1] - } -}; - -},{}],1163:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var svgSdf = _dereq_('svg-path-sdf'); -var rgba = _dereq_('color-normalize'); - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../../components/drawing'); -var AxisIDs = _dereq_('../../plots/cartesian/axis_ids'); - -var formatColor = _dereq_('../../lib/gl_format_color').formatColor; -var subTypes = _dereq_('../scatter/subtypes'); -var makeBubbleSizeFn = _dereq_('../scatter/make_bubble_size_func'); - -var constants = _dereq_('./constants'); -var DESELECTDIM = _dereq_('../../constants/interactions').DESELECTDIM; - -var TEXTOFFSETSIGN = { - start: 1, left: 1, end: -1, right: -1, middle: 0, center: 0, bottom: 1, top: -1 -}; - -function convertStyle(gd, trace) { - var i; - - var opts = { - marker: undefined, - markerSel: undefined, - markerUnsel: undefined, - line: undefined, - fill: undefined, - errorX: undefined, - errorY: undefined, - text: undefined, - textSel: undefined, - textUnsel: undefined - }; - - if(trace.visible !== true) return opts; - - if(subTypes.hasText(trace)) { - opts.text = convertTextStyle(trace); - opts.textSel = convertTextSelection(trace, trace.selected); - opts.textUnsel = convertTextSelection(trace, trace.unselected); - } - - if(subTypes.hasMarkers(trace)) { - opts.marker = convertMarkerStyle(trace); - opts.markerSel = convertMarkerSelection(trace, trace.selected); - opts.markerUnsel = convertMarkerSelection(trace, trace.unselected); - - if(!trace.unselected && Array.isArray(trace.marker.opacity)) { - var mo = trace.marker.opacity; - opts.markerUnsel.opacity = new Array(mo.length); - for(i = 0; i < mo.length; i++) { - opts.markerUnsel.opacity[i] = DESELECTDIM * mo[i]; - } - } - } - - if(subTypes.hasLines(trace)) { - opts.line = { - overlay: true, - thickness: trace.line.width, - color: trace.line.color, - opacity: trace.opacity - }; - - var dashes = (constants.DASHES[trace.line.dash] || [1]).slice(); - for(i = 0; i < dashes.length; ++i) { - dashes[i] *= trace.line.width; - } - opts.line.dashes = dashes; - } - - if(trace.error_x && trace.error_x.visible) { - opts.errorX = convertErrorBarStyle(trace, trace.error_x); - } - - if(trace.error_y && trace.error_y.visible) { - opts.errorY = convertErrorBarStyle(trace, trace.error_y); - } - - if(!!trace.fill && trace.fill !== 'none') { - opts.fill = { - closed: true, - fill: trace.fillcolor, - thickness: 0 - }; - } - - return opts; -} - -function convertTextStyle(trace) { - var count = trace._length; - var textfontIn = trace.textfont; - var textpositionIn = trace.textposition; - var textPos = Array.isArray(textpositionIn) ? textpositionIn : [textpositionIn]; - var tfc = textfontIn.color; - var tfs = textfontIn.size; - var tff = textfontIn.family; - var optsOut = {}; - var i; - - optsOut.text = trace.text; - optsOut.opacity = trace.opacity; - optsOut.font = {}; - optsOut.align = []; - optsOut.baseline = []; - - for(i = 0; i < textPos.length; i++) { - var tp = textPos[i].split(/\s+/); - - switch(tp[1]) { - case 'left': - optsOut.align.push('right'); - break; - case 'right': - optsOut.align.push('left'); - break; - default: - optsOut.align.push(tp[1]); - } - switch(tp[0]) { - case 'top': - optsOut.baseline.push('bottom'); - break; - case 'bottom': - optsOut.baseline.push('top'); - break; - default: - optsOut.baseline.push(tp[0]); - } - } - - if(Array.isArray(tfc)) { - optsOut.color = new Array(count); - for(i = 0; i < count; i++) { - optsOut.color[i] = tfc[i]; - } - } else { - optsOut.color = tfc; - } - - if(Array.isArray(tfs) || Array.isArray(tff)) { - // if any textfont param is array - make render a batch - optsOut.font = new Array(count); - for(i = 0; i < count; i++) { - var fonti = optsOut.font[i] = {}; - - fonti.size = Array.isArray(tfs) ? - (isNumeric(tfs[i]) ? tfs[i] : 0) : - tfs; - - fonti.family = Array.isArray(tff) ? tff[i] : tff; - } - } else { - // if both are single values, make render fast single-value - optsOut.font = {size: tfs, family: tff}; - } - - return optsOut; -} - - -function convertMarkerStyle(trace) { - var count = trace._length; - var optsIn = trace.marker; - var optsOut = {}; - var i; - - var multiSymbol = Array.isArray(optsIn.symbol); - var multiColor = Lib.isArrayOrTypedArray(optsIn.color); - var multiLineColor = Lib.isArrayOrTypedArray(optsIn.line.color); - var multiOpacity = Lib.isArrayOrTypedArray(optsIn.opacity); - var multiSize = Lib.isArrayOrTypedArray(optsIn.size); - var multiLineWidth = Lib.isArrayOrTypedArray(optsIn.line.width); - - var isOpen; - if(!multiSymbol) isOpen = constants.OPEN_RE.test(optsIn.symbol); - - // prepare colors - if(multiSymbol || multiColor || multiLineColor || multiOpacity) { - optsOut.colors = new Array(count); - optsOut.borderColors = new Array(count); - - var colors = formatColor(optsIn, optsIn.opacity, count); - var borderColors = formatColor(optsIn.line, optsIn.opacity, count); - - if(!Array.isArray(borderColors[0])) { - var borderColor = borderColors; - borderColors = Array(count); - for(i = 0; i < count; i++) { - borderColors[i] = borderColor; - } - } - if(!Array.isArray(colors[0])) { - var color = colors; - colors = Array(count); - for(i = 0; i < count; i++) { - colors[i] = color; - } - } - - optsOut.colors = colors; - optsOut.borderColors = borderColors; - - for(i = 0; i < count; i++) { - if(multiSymbol) { - var symbol = optsIn.symbol[i]; - isOpen = constants.OPEN_RE.test(symbol); - } - if(isOpen) { - borderColors[i] = colors[i].slice(); - colors[i] = colors[i].slice(); - colors[i][3] = 0; - } - } - - optsOut.opacity = trace.opacity; - } else { - if(isOpen) { - optsOut.color = rgba(optsIn.color, 'uint8'); - optsOut.color[3] = 0; - optsOut.borderColor = rgba(optsIn.color, 'uint8'); - } else { - optsOut.color = rgba(optsIn.color, 'uint8'); - optsOut.borderColor = rgba(optsIn.line.color, 'uint8'); - } - - optsOut.opacity = trace.opacity * optsIn.opacity; - } - - // prepare symbols - if(multiSymbol) { - optsOut.markers = new Array(count); - for(i = 0; i < count; i++) { - optsOut.markers[i] = getSymbolSdf(optsIn.symbol[i]); - } - } else { - optsOut.marker = getSymbolSdf(optsIn.symbol); - } - - // prepare sizes - var markerSizeFunc = makeBubbleSizeFn(trace); - var s; - - if(multiSize || multiLineWidth) { - var sizes = optsOut.sizes = new Array(count); - var borderSizes = optsOut.borderSizes = new Array(count); - var sizeTotal = 0; - var sizeAvg; - - if(multiSize) { - for(i = 0; i < count; i++) { - sizes[i] = markerSizeFunc(optsIn.size[i]); - sizeTotal += sizes[i]; - } - sizeAvg = sizeTotal / count; - } else { - s = markerSizeFunc(optsIn.size); - for(i = 0; i < count; i++) { - sizes[i] = s; - } - } - - // See https://github.com/plotly/plotly.js/pull/1781#discussion_r121820798 - if(multiLineWidth) { - for(i = 0; i < count; i++) { - borderSizes[i] = optsIn.line.width[i] / 2; - } - } else { - s = optsIn.line.width / 2; - for(i = 0; i < count; i++) { - borderSizes[i] = s; - } - } - - optsOut.sizeAvg = sizeAvg; - } else { - optsOut.size = markerSizeFunc(optsIn && optsIn.size || 10); - optsOut.borderSizes = markerSizeFunc(optsIn.line.width); - } - - return optsOut; -} - -function convertMarkerSelection(trace, target) { - var optsIn = trace.marker; - var optsOut = {}; - - if(!target) return optsOut; - - if(target.marker && target.marker.symbol) { - optsOut = convertMarkerStyle(Lib.extendFlat({}, optsIn, target.marker)); - } else if(target.marker) { - if(target.marker.size) optsOut.size = target.marker.size / 2; - if(target.marker.color) optsOut.colors = target.marker.color; - if(target.marker.opacity !== undefined) optsOut.opacity = target.marker.opacity; - } - - return optsOut; -} - -function convertTextSelection(trace, target) { - var optsOut = {}; - - if(!target) return optsOut; - - if(target.textfont) { - var optsIn = { - opacity: 1, - text: trace.text, - textposition: trace.textposition, - textfont: Lib.extendFlat({}, trace.textfont) - }; - if(target.textfont) { - Lib.extendFlat(optsIn.textfont, target.textfont); - } - optsOut = convertTextStyle(optsIn); - } - - return optsOut; -} - -function convertErrorBarStyle(trace, target) { - var optsOut = { - capSize: target.width * 2, - lineWidth: target.thickness, - color: target.color - }; - - if(target.copy_ystyle) { - optsOut = trace.error_y; - } - - return optsOut; -} - -var SYMBOL_SDF_SIZE = constants.SYMBOL_SDF_SIZE; -var SYMBOL_SIZE = constants.SYMBOL_SIZE; -var SYMBOL_STROKE = constants.SYMBOL_STROKE; -var SYMBOL_SDF = {}; -var SYMBOL_SVG_CIRCLE = Drawing.symbolFuncs[0](SYMBOL_SIZE * 0.05); - -function getSymbolSdf(symbol) { - if(symbol === 'circle') return null; - - var symbolPath, symbolSdf; - var symbolNumber = Drawing.symbolNumber(symbol); - var symbolFunc = Drawing.symbolFuncs[symbolNumber % 100]; - var symbolNoDot = !!Drawing.symbolNoDot[symbolNumber % 100]; - var symbolNoFill = !!Drawing.symbolNoFill[symbolNumber % 100]; - - var isDot = constants.DOT_RE.test(symbol); - - // get symbol sdf from cache or generate it - if(SYMBOL_SDF[symbol]) return SYMBOL_SDF[symbol]; - - if(isDot && !symbolNoDot) { - symbolPath = symbolFunc(SYMBOL_SIZE * 1.1) + SYMBOL_SVG_CIRCLE; - } else { - symbolPath = symbolFunc(SYMBOL_SIZE); - } - - symbolSdf = svgSdf(symbolPath, { - w: SYMBOL_SDF_SIZE, - h: SYMBOL_SDF_SIZE, - viewBox: [-SYMBOL_SIZE, -SYMBOL_SIZE, SYMBOL_SIZE, SYMBOL_SIZE], - stroke: symbolNoFill ? SYMBOL_STROKE : -SYMBOL_STROKE - }); - SYMBOL_SDF[symbol] = symbolSdf; - - return symbolSdf || null; -} - -function convertLinePositions(gd, trace, positions) { - var len = positions.length; - var count = len / 2; - var linePositions; - var i; - - if(subTypes.hasLines(trace) && count) { - if(trace.line.shape === 'hv') { - linePositions = []; - for(i = 0; i < count - 1; i++) { - if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1])) { - linePositions.push(NaN, NaN, NaN, NaN); - } else { - linePositions.push(positions[i * 2], positions[i * 2 + 1]); - if(!isNaN(positions[i * 2 + 2]) && !isNaN(positions[i * 2 + 3])) { - linePositions.push(positions[i * 2 + 2], positions[i * 2 + 1]); - } else { - linePositions.push(NaN, NaN); - } - } - } - linePositions.push(positions[len - 2], positions[len - 1]); - } else if(trace.line.shape === 'hvh') { - linePositions = []; - for(i = 0; i < count - 1; i++) { - if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1]) || isNaN(positions[i * 2 + 2]) || isNaN(positions[i * 2 + 3])) { - if(!isNaN(positions[i * 2]) && !isNaN(positions[i * 2 + 1])) { - linePositions.push(positions[i * 2], positions[i * 2 + 1]); - } else { - linePositions.push(NaN, NaN); - } - linePositions.push(NaN, NaN); - } else { - var midPtX = (positions[i * 2] + positions[i * 2 + 2]) / 2; - linePositions.push( - positions[i * 2], - positions[i * 2 + 1], - midPtX, - positions[i * 2 + 1], - midPtX, - positions[i * 2 + 3] - ); - } - } - linePositions.push(positions[len - 2], positions[len - 1]); - } else if(trace.line.shape === 'vhv') { - linePositions = []; - for(i = 0; i < count - 1; i++) { - if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1]) || isNaN(positions[i * 2 + 2]) || isNaN(positions[i * 2 + 3])) { - if(!isNaN(positions[i * 2]) && !isNaN(positions[i * 2 + 1])) { - linePositions.push(positions[i * 2], positions[i * 2 + 1]); - } else { - linePositions.push(NaN, NaN); - } - linePositions.push(NaN, NaN); - } else { - var midPtY = (positions[i * 2 + 1] + positions[i * 2 + 3]) / 2; - linePositions.push( - positions[i * 2], - positions[i * 2 + 1], - positions[i * 2], - midPtY, - positions[i * 2 + 2], - midPtY - ); - } - } - linePositions.push(positions[len - 2], positions[len - 1]); - } else if(trace.line.shape === 'vh') { - linePositions = []; - for(i = 0; i < count - 1; i++) { - if(isNaN(positions[i * 2]) || isNaN(positions[i * 2 + 1])) { - linePositions.push(NaN, NaN, NaN, NaN); - } else { - linePositions.push(positions[i * 2], positions[i * 2 + 1]); - if(!isNaN(positions[i * 2 + 2]) && !isNaN(positions[i * 2 + 3])) { - linePositions.push(positions[i * 2], positions[i * 2 + 3]); - } else { - linePositions.push(NaN, NaN); - } - } - } - linePositions.push(positions[len - 2], positions[len - 1]); - } else { - linePositions = positions; - } - } - - // If we have data with gaps, we ought to use rect joins - // FIXME: get rid of this - var hasNaN = false; - for(i = 0; i < linePositions.length; i++) { - if(isNaN(linePositions[i])) { - hasNaN = true; - break; - } - } - - var join = (hasNaN || linePositions.length > constants.TOO_MANY_POINTS) ? 'rect' : - subTypes.hasMarkers(trace) ? 'rect' : 'round'; - - // fill gaps - if(hasNaN && trace.connectgaps) { - var lastX = linePositions[0]; - var lastY = linePositions[1]; - - for(i = 0; i < linePositions.length; i += 2) { - if(isNaN(linePositions[i]) || isNaN(linePositions[i + 1])) { - linePositions[i] = lastX; - linePositions[i + 1] = lastY; - } else { - lastX = linePositions[i]; - lastY = linePositions[i + 1]; - } - } - } - - return { - join: join, - positions: linePositions - }; -} - -function convertErrorBarPositions(gd, trace, positions, x, y) { - var makeComputeError = Registry.getComponentMethod('errorbars', 'makeComputeError'); - var xa = AxisIDs.getFromId(gd, trace.xaxis); - var ya = AxisIDs.getFromId(gd, trace.yaxis); - var count = positions.length / 2; - var out = {}; - - function convertOneAxis(coords, ax) { - var axLetter = ax._id.charAt(0); - var opts = trace['error_' + axLetter]; - - if(opts && opts.visible && (ax.type === 'linear' || ax.type === 'log')) { - var computeError = makeComputeError(opts); - var pOffset = {x: 0, y: 1}[axLetter]; - var eOffset = {x: [0, 1, 2, 3], y: [2, 3, 0, 1]}[axLetter]; - var errors = new Float64Array(4 * count); - var minShoe = Infinity; - var maxHat = -Infinity; - - for(var i = 0, j = 0; i < count; i++, j += 4) { - var dc = coords[i]; - - if(isNumeric(dc)) { - var dl = positions[i * 2 + pOffset]; - var vals = computeError(dc, i); - var lv = vals[0]; - var hv = vals[1]; - - if(isNumeric(lv) && isNumeric(hv)) { - var shoe = dc - lv; - var hat = dc + hv; - - errors[j + eOffset[0]] = dl - ax.c2l(shoe); - errors[j + eOffset[1]] = ax.c2l(hat) - dl; - errors[j + eOffset[2]] = 0; - errors[j + eOffset[3]] = 0; - - minShoe = Math.min(minShoe, dc - lv); - maxHat = Math.max(maxHat, dc + hv); - } - } - } - - out[axLetter] = { - positions: positions, - errors: errors, - _bnds: [minShoe, maxHat] - }; - } - } - - convertOneAxis(x, xa); - convertOneAxis(y, ya); - return out; -} - -function convertTextPosition(gd, trace, textOpts, markerOpts) { - var count = trace._length; - var out = {}; - var i; - - // corresponds to textPointPosition from component.drawing - if(subTypes.hasMarkers(trace)) { - var fontOpts = textOpts.font; - var align = textOpts.align; - var baseline = textOpts.baseline; - out.offset = new Array(count); - - for(i = 0; i < count; i++) { - var ms = markerOpts.sizes ? markerOpts.sizes[i] : markerOpts.size; - var fs = Array.isArray(fontOpts) ? fontOpts[i].size : fontOpts.size; - - var a = Array.isArray(align) ? - (align.length > 1 ? align[i] : align[0]) : - align; - var b = Array.isArray(baseline) ? - (baseline.length > 1 ? baseline[i] : baseline[0]) : - baseline; - - var hSign = TEXTOFFSETSIGN[a]; - var vSign = TEXTOFFSETSIGN[b]; - var xPad = ms ? ms / 0.8 + 1 : 0; - var yPad = -vSign * xPad - vSign * 0.5; - out.offset[i] = [hSign * xPad / fs, yPad / fs]; - } - } - - return out; -} - -module.exports = { - style: convertStyle, - - markerStyle: convertMarkerStyle, - markerSelection: convertMarkerSelection, - - linePositions: convertLinePositions, - errorBarPositions: convertErrorBarPositions, - textPosition: convertTextPosition -}; - -},{"../../components/drawing":614,"../../constants/interactions":694,"../../lib":719,"../../lib/gl_format_color":716,"../../plots/cartesian/axis_ids":770,"../../registry":847,"../scatter/make_bubble_size_func":1128,"../scatter/subtypes":1135,"./constants":1162,"color-normalize":120,"fast-isnumeric":225,"svg-path-sdf":535}],1164:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Registry = _dereq_('../../registry'); - -var attributes = _dereq_('./attributes'); -var constants = _dereq_('../scatter/constants'); -var subTypes = _dereq_('../scatter/subtypes'); -var handleXYDefaults = _dereq_('../scatter/xy_defaults'); -var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); -var handleLineDefaults = _dereq_('../scatter/line_defaults'); -var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); -var handleTextDefaults = _dereq_('../scatter/text_defaults'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var isOpen = traceIn.marker ? /-open/.test(traceIn.marker.symbol) : false; - var isBubble = subTypes.isBubble(traceIn); - - var len = handleXYDefaults(traceIn, traceOut, layout, coerce); - if(!len) { - traceOut.visible = false; - return; - } - var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines'; - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - coerce('mode', defaultMode); - - if(subTypes.hasLines(traceOut)) { - coerce('connectgaps'); - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - coerce('line.shape'); - } - - if(subTypes.hasMarkers(traceOut)) { - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce); - coerce('marker.line.width', isOpen || isBubble ? 1 : 0); - } - - if(subTypes.hasText(traceOut)) { - handleTextDefaults(traceIn, traceOut, layout, coerce); - } - - var lineColor = (traceOut.line || {}).color; - var markerColor = (traceOut.marker || {}).color; - - coerce('fill'); - if(traceOut.fill !== 'none') { - handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); - } - - var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || markerColor || defaultColor, {axis: 'y'}); - errorBarsSupplyDefaults(traceIn, traceOut, lineColor || markerColor || defaultColor, {axis: 'x', inherit: 'y'}); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -},{"../../lib":719,"../../registry":847,"../scatter/constants":1116,"../scatter/fillcolor_defaults":1120,"../scatter/line_defaults":1124,"../scatter/marker_defaults":1130,"../scatter/subtypes":1135,"../scatter/text_defaults":1136,"../scatter/xy_defaults":1137,"./attributes":1160}],1165:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); - -var DESELECTDIM = _dereq_('../../constants/interactions').DESELECTDIM; - -function styleTextSelection(cd) { - var cd0 = cd[0]; - var trace = cd0.trace; - var stash = cd0.t; - var scene = stash._scene; - var index = stash.index; - var els = scene.selectBatch[index]; - var unels = scene.unselectBatch[index]; - var baseOpts = scene.textOptions[index]; - var selOpts = scene.textSelectedOptions[index] || {}; - var unselOpts = scene.textUnselectedOptions[index] || {}; - var opts = Lib.extendFlat({}, baseOpts); - var i, j; - - if(els.length || unels.length) { - var stc = selOpts.color; - var utc = unselOpts.color; - var base = baseOpts.color; - var hasArrayBase = Array.isArray(base); - opts.color = new Array(trace._length); - - for(i = 0; i < els.length; i++) { - j = els[i]; - opts.color[j] = stc || (hasArrayBase ? base[j] : base); - } - for(i = 0; i < unels.length; i++) { - j = unels[i]; - var basej = hasArrayBase ? base[j] : base; - opts.color[j] = utc ? utc : - stc ? basej : Color.addOpacity(basej, DESELECTDIM); - } - } - - scene.glText[index].update(opts); -} - -module.exports = { - styleTextSelection: styleTextSelection -}; - -},{"../../components/color":593,"../../constants/interactions":694,"../../lib":719}],1166:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); -var getTraceColor = _dereq_('../scatter/get_trace_color'); - -function hoverPoints(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var stash = cd[0].t; - var trace = cd[0].trace; - var xa = pointData.xa; - var ya = pointData.ya; - var x = stash.x; - var y = stash.y; - var xpx = xa.c2p(xval); - var ypx = ya.c2p(yval); - var maxDistance = pointData.distance; - var ids; - - // FIXME: make sure this is a proper way to calc search radius - if(stash.tree) { - var xl = xa.p2c(xpx - maxDistance); - var xr = xa.p2c(xpx + maxDistance); - var yl = ya.p2c(ypx - maxDistance); - var yr = ya.p2c(ypx + maxDistance); - - if(hovermode === 'x') { - ids = stash.tree.range( - Math.min(xl, xr), Math.min(ya._rl[0], ya._rl[1]), - Math.max(xl, xr), Math.max(ya._rl[0], ya._rl[1]) - ); - } else { - ids = stash.tree.range( - Math.min(xl, xr), Math.min(yl, yr), - Math.max(xl, xr), Math.max(yl, yr) - ); - } - } else if(stash.ids) { - ids = stash.ids; - } else return [pointData]; - - // pick the id closest to the point - // note that point possibly may not be found - var id, ptx, pty, i, dx, dy, dist, dxy; - - var minDist = maxDistance; - if(hovermode === 'x') { - for(i = 0; i < ids.length; i++) { - ptx = x[ids[i]]; - dx = Math.abs(xa.c2p(ptx) - xpx); - if(dx < minDist) { - minDist = dx; - dy = ya.c2p(y[ids[i]]) - ypx; - dxy = Math.sqrt(dx * dx + dy * dy); - id = ids[i]; - } - } - } else { - for(i = ids.length - 1; i > -1; i--) { - ptx = x[ids[i]]; - pty = y[ids[i]]; - dx = xa.c2p(ptx) - xpx; - dy = ya.c2p(pty) - ypx; - - dist = Math.sqrt(dx * dx + dy * dy); - if(dist < minDist) { - minDist = dxy = dist; - id = ids[i]; - } - } - } - - pointData.index = id; - pointData.distance = minDist; - pointData.dxy = dxy; - - if(id === undefined) return [pointData]; - - calcHover(pointData, x, y, trace); - - return [pointData]; -} - -function calcHover(pointData, x, y, trace) { - var xa = pointData.xa; - var ya = pointData.ya; - var minDist = pointData.distance; - var dxy = pointData.dxy; - var id = pointData.index; - - // the closest data point - var di = { - pointNumber: id, - x: x[id], - y: y[id] - }; - - // that is single-item arrays_to_calcdata excerpt, since we are doing it for a single point and we don't have to do it beforehead for 1e6 points - di.tx = Array.isArray(trace.text) ? trace.text[id] : trace.text; - di.htx = Array.isArray(trace.hovertext) ? trace.hovertext[id] : trace.hovertext; - di.data = Array.isArray(trace.customdata) ? trace.customdata[id] : trace.customdata; - di.tp = Array.isArray(trace.textposition) ? trace.textposition[id] : trace.textposition; - - var font = trace.textfont; - if(font) { - di.ts = Array.isArray(font.size) ? font.size[id] : font.size; - di.tc = Array.isArray(font.color) ? font.color[id] : font.color; - di.tf = Array.isArray(font.family) ? font.family[id] : font.family; - } - - var marker = trace.marker; - if(marker) { - di.ms = Lib.isArrayOrTypedArray(marker.size) ? marker.size[id] : marker.size; - di.mo = Lib.isArrayOrTypedArray(marker.opacity) ? marker.opacity[id] : marker.opacity; - di.mx = Array.isArray(marker.symbol) ? marker.symbol[id] : marker.symbol; - di.mc = Lib.isArrayOrTypedArray(marker.color) ? marker.color[id] : marker.color; - } - - var line = marker && marker.line; - if(line) { - di.mlc = Array.isArray(line.color) ? line.color[id] : line.color; - di.mlw = Lib.isArrayOrTypedArray(line.width) ? line.width[id] : line.width; - } - - var grad = marker && marker.gradient; - if(grad && grad.type !== 'none') { - di.mgt = Array.isArray(grad.type) ? grad.type[id] : grad.type; - di.mgc = Array.isArray(grad.color) ? grad.color[id] : grad.color; - } - - var xp = xa.c2p(di.x, true); - var yp = ya.c2p(di.y, true); - var rad = di.mrc || 1; - - var hoverlabel = trace.hoverlabel; - - if(hoverlabel) { - di.hbg = Array.isArray(hoverlabel.bgcolor) ? hoverlabel.bgcolor[id] : hoverlabel.bgcolor; - di.hbc = Array.isArray(hoverlabel.bordercolor) ? hoverlabel.bordercolor[id] : hoverlabel.bordercolor; - di.hts = Array.isArray(hoverlabel.font.size) ? hoverlabel.font.size[id] : hoverlabel.font.size; - di.htc = Array.isArray(hoverlabel.font.color) ? hoverlabel.font.color[id] : hoverlabel.font.color; - di.htf = Array.isArray(hoverlabel.font.family) ? hoverlabel.font.family[id] : hoverlabel.font.family; - di.hnl = Array.isArray(hoverlabel.namelength) ? hoverlabel.namelength[id] : hoverlabel.namelength; - } - var hoverinfo = trace.hoverinfo; - if(hoverinfo) { - di.hi = Array.isArray(hoverinfo) ? hoverinfo[id] : hoverinfo; - } - - var hovertemplate = trace.hovertemplate; - if(hovertemplate) { - di.ht = Array.isArray(hovertemplate) ? hovertemplate[id] : hovertemplate; - } - - var fakeCd = {}; - fakeCd[pointData.index] = di; - - Lib.extendFlat(pointData, { - color: getTraceColor(trace, di), - - x0: xp - rad, - x1: xp + rad, - xLabelVal: di.x, - - y0: yp - rad, - y1: yp + rad, - yLabelVal: di.y, - - cd: fakeCd, - distance: minDist, - spikeDistance: dxy, - - hovertemplate: di.ht - }); - - if(di.htx) pointData.text = di.htx; - else if(di.tx) pointData.text = di.tx; - else if(trace.text) pointData.text = trace.text; - - Lib.fillText(di, trace, pointData); - Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, pointData); - - return pointData; -} - -module.exports = { - hoverPoints: hoverPoints, - calcHover: calcHover -}; - -},{"../../lib":719,"../../registry":847,"../scatter/get_trace_color":1121}],1167:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hover = _dereq_('./hover'); - -module.exports = { - moduleType: 'trace', - name: 'scattergl', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['gl', 'regl', 'cartesian', 'symbols', 'errorBarsOK', 'showLegend', 'scatter-like'], - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - crossTraceDefaults: _dereq_('../scatter/cross_trace_defaults'), - colorbar: _dereq_('../scatter/marker_colorbar'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - hoverPoints: hover.hoverPoints, - selectPoints: _dereq_('./select'), - - meta: { - - - } -}; - -},{"../../plots/cartesian":778,"../scatter/cross_trace_defaults":1118,"../scatter/marker_colorbar":1129,"./attributes":1160,"./calc":1161,"./defaults":1164,"./hover":1166,"./plot":1168,"./select":1170}],1168:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var createScatter = _dereq_('regl-scatter2d'); -var createLine = _dereq_('regl-line2d'); -var createError = _dereq_('regl-error2d'); -var Text = _dereq_('gl-text'); - -var Lib = _dereq_('../../lib'); -var prepareRegl = _dereq_('../../lib/prepare_regl'); - -var subTypes = _dereq_('../scatter/subtypes'); -var linkTraces = _dereq_('../scatter/link_traces'); - -var styleTextSelection = _dereq_('./edit_style').styleTextSelection; - -function getViewport(fullLayout, xaxis, yaxis) { - var gs = fullLayout._size; - var width = fullLayout.width; - var height = fullLayout.height; - return [ - gs.l + xaxis.domain[0] * gs.w, - gs.b + yaxis.domain[0] * gs.h, - (width - gs.r) - (1 - xaxis.domain[1]) * gs.w, - (height - gs.t) - (1 - yaxis.domain[1]) * gs.h - ]; -} - -module.exports = function plot(gd, subplot, cdata) { - if(!cdata.length) return; - - var fullLayout = gd._fullLayout; - var scene = subplot._scene; - var xaxis = subplot.xaxis; - var yaxis = subplot.yaxis; - var i, j; - - // we may have more subplots than initialized data due to Axes.getSubplots method - if(!scene) return; - - var success = prepareRegl(gd, ['ANGLE_instanced_arrays', 'OES_element_index_uint']); - if(!success) { - scene.init(); - return; - } - - var count = scene.count; - var regl = fullLayout._glcanvas.data()[0].regl; - - // that is needed for fills - linkTraces(gd, subplot, cdata); - - if(scene.dirty) { - // make sure scenes are created - if(scene.error2d === true) { - scene.error2d = createError(regl); - } - if(scene.line2d === true) { - scene.line2d = createLine(regl); - } - if(scene.scatter2d === true) { - scene.scatter2d = createScatter(regl); - } - if(scene.fill2d === true) { - scene.fill2d = createLine(regl); - } - if(scene.glText === true) { - scene.glText = new Array(count); - for(i = 0; i < count; i++) { - scene.glText[i] = new Text(regl); - } - } - - // update main marker options - if(scene.glText) { - if(count > scene.glText.length) { - // add gl text marker - var textsToAdd = count - scene.glText.length; - for(i = 0; i < textsToAdd; i++) { - scene.glText.push(new Text(regl)); - } - } else if(count < scene.glText.length) { - // remove gl text marker - var textsToRemove = scene.glText.length - count; - var removedTexts = scene.glText.splice(count, textsToRemove); - removedTexts.forEach(function(text) { text.destroy(); }); - } - - for(i = 0; i < count; i++) { - scene.glText[i].update(scene.textOptions[i]); - } - } - if(scene.line2d) { - scene.line2d.update(scene.lineOptions); - scene.lineOptions = scene.lineOptions.map(function(lineOptions) { - if(lineOptions && lineOptions.positions) { - var srcPos = lineOptions.positions; - - var firstptdef = 0; - while(firstptdef < srcPos.length && (isNaN(srcPos[firstptdef]) || isNaN(srcPos[firstptdef + 1]))) { - firstptdef += 2; - } - var lastptdef = srcPos.length - 2; - while(lastptdef > firstptdef && (isNaN(srcPos[lastptdef]) || isNaN(srcPos[lastptdef + 1]))) { - lastptdef -= 2; - } - lineOptions.positions = srcPos.slice(firstptdef, lastptdef + 2); - } - return lineOptions; - }); - scene.line2d.update(scene.lineOptions); - } - if(scene.error2d) { - var errorBatch = (scene.errorXOptions || []).concat(scene.errorYOptions || []); - scene.error2d.update(errorBatch); - } - if(scene.scatter2d) { - scene.scatter2d.update(scene.markerOptions); - } - - // fill requires linked traces, so we generate it's positions here - scene.fillOrder = Lib.repeat(null, count); - if(scene.fill2d) { - scene.fillOptions = scene.fillOptions.map(function(fillOptions, i) { - var cdscatter = cdata[i]; - if(!fillOptions || !cdscatter || !cdscatter[0] || !cdscatter[0].trace) return; - var cd = cdscatter[0]; - var trace = cd.trace; - var stash = cd.t; - var lineOptions = scene.lineOptions[i]; - var last, j; - - var fillData = []; - if(trace._ownfill) fillData.push(i); - if(trace._nexttrace) fillData.push(i + 1); - if(fillData.length) scene.fillOrder[i] = fillData; - - var pos = []; - var srcPos = (lineOptions && lineOptions.positions) || stash.positions; - var firstptdef, lastptdef; - - if(trace.fill === 'tozeroy') { - firstptdef = 0; - while(firstptdef < srcPos.length && isNaN(srcPos[firstptdef + 1])) { - firstptdef += 2; - } - lastptdef = srcPos.length - 2; - while(lastptdef > firstptdef && isNaN(srcPos[lastptdef + 1])) { - lastptdef -= 2; - } - if(srcPos[firstptdef + 1] !== 0) { - pos = [srcPos[firstptdef], 0]; - } - pos = pos.concat(srcPos.slice(firstptdef, lastptdef + 2)); - if(srcPos[lastptdef + 1] !== 0) { - pos = pos.concat([srcPos[lastptdef], 0]); - } - } else if(trace.fill === 'tozerox') { - firstptdef = 0; - while(firstptdef < srcPos.length && isNaN(srcPos[firstptdef])) { - firstptdef += 2; - } - lastptdef = srcPos.length - 2; - while(lastptdef > firstptdef && isNaN(srcPos[lastptdef])) { - lastptdef -= 2; - } - if(srcPos[firstptdef] !== 0) { - pos = [0, srcPos[firstptdef + 1]]; - } - pos = pos.concat(srcPos.slice(firstptdef, lastptdef + 2)); - if(srcPos[lastptdef] !== 0) { - pos = pos.concat([ 0, srcPos[lastptdef + 1]]); - } - } else if(trace.fill === 'toself' || trace.fill === 'tonext') { - pos = []; - last = 0; - for(j = 0; j < srcPos.length; j += 2) { - if(isNaN(srcPos[j]) || isNaN(srcPos[j + 1])) { - pos = pos.concat(srcPos.slice(last, j)); - pos.push(srcPos[last], srcPos[last + 1]); - last = j + 2; - } - } - pos = pos.concat(srcPos.slice(last)); - if(last) { - pos.push(srcPos[last], srcPos[last + 1]); - } - } else { - var nextTrace = trace._nexttrace; - - if(nextTrace) { - var nextOptions = scene.lineOptions[i + 1]; - - if(nextOptions) { - var nextPos = nextOptions.positions; - if(trace.fill === 'tonexty') { - pos = srcPos.slice(); - - for(i = Math.floor(nextPos.length / 2); i--;) { - var xx = nextPos[i * 2]; - var yy = nextPos[i * 2 + 1]; - if(isNaN(xx) || isNaN(yy)) continue; - pos.push(xx, yy); - } - fillOptions.fill = nextTrace.fillcolor; - } - } - } - } - - // detect prev trace positions to exclude from current fill - if(trace._prevtrace && trace._prevtrace.fill === 'tonext') { - var prevLinePos = scene.lineOptions[i - 1].positions; - - // FIXME: likely this logic should be tested better - var offset = pos.length / 2; - last = offset; - var hole = [last]; - for(j = 0; j < prevLinePos.length; j += 2) { - if(isNaN(prevLinePos[j]) || isNaN(prevLinePos[j + 1])) { - hole.push(j / 2 + offset + 1); - last = j + 2; - } - } - - pos = pos.concat(prevLinePos); - fillOptions.hole = hole; - } - fillOptions.fillmode = trace.fill; - fillOptions.opacity = trace.opacity; - fillOptions.positions = pos; - - return fillOptions; - }); - - scene.fill2d.update(scene.fillOptions); - } - } - - // form batch arrays, and check for selected points - var dragmode = fullLayout.dragmode; - var selectMode = dragmode === 'lasso' || dragmode === 'select'; - var clickSelectEnabled = fullLayout.clickmode.indexOf('select') > -1; - - for(i = 0; i < count; i++) { - var cd0 = cdata[i][0]; - var trace = cd0.trace; - var stash = cd0.t; - var index = stash.index; - var len = trace._length; - var x = stash.x; - var y = stash.y; - - if(trace.selectedpoints || selectMode || clickSelectEnabled) { - if(!selectMode) selectMode = true; - - // regenerate scene batch, if traces number changed during selection - if(trace.selectedpoints) { - var selPts = scene.selectBatch[index] = Lib.selIndices2selPoints(trace); - - var selDict = {}; - for(j = 0; j < selPts.length; j++) { - selDict[selPts[j]] = 1; - } - var unselPts = []; - for(j = 0; j < len; j++) { - if(!selDict[j]) unselPts.push(j); - } - scene.unselectBatch[index] = unselPts; - } - - // precalculate px coords since we are not going to pan during select - // TODO, could do better here e.g. - // - spin that in a webworker - // - compute selection from polygons in data coordinates - // (maybe just for linear axes) - var xpx = stash.xpx = new Array(len); - var ypx = stash.ypx = new Array(len); - for(j = 0; j < len; j++) { - xpx[j] = xaxis.c2p(x[j]); - ypx[j] = yaxis.c2p(y[j]); - } - } else { - stash.xpx = stash.ypx = null; - } - } - - if(selectMode) { - // create scatter instance by cloning scatter2d - if(!scene.select2d) { - scene.select2d = createScatter(fullLayout._glcanvas.data()[1].regl); - } - - // use unselected styles on 'context' canvas - if(scene.scatter2d) { - var unselOpts = new Array(count); - for(i = 0; i < count; i++) { - unselOpts[i] = scene.selectBatch[i].length || scene.unselectBatch[i].length ? - scene.markerUnselectedOptions[i] : - {}; - } - scene.scatter2d.update(unselOpts); - } - - // use selected style on 'focus' canvas - if(scene.select2d) { - scene.select2d.update(scene.markerOptions); - scene.select2d.update(scene.markerSelectedOptions); - } - - if(scene.glText) { - cdata.forEach(function(cdscatter) { - var trace = ((cdscatter || [])[0] || {}).trace || {}; - if(subTypes.hasText(trace)) { - styleTextSelection(cdscatter); - } - }); - } - } else { - // reset 'context' scatter2d opts to base opts, - // thus unsetting markerUnselectedOptions from selection - if(scene.scatter2d) { - scene.scatter2d.update(scene.markerOptions); - } - } - - // provide viewport and range - var vpRange0 = { - viewport: getViewport(fullLayout, xaxis, yaxis), - // TODO do we need those fallbacks? - range: [ - (xaxis._rl || xaxis.range)[0], - (yaxis._rl || yaxis.range)[0], - (xaxis._rl || xaxis.range)[1], - (yaxis._rl || yaxis.range)[1] - ] - }; - var vpRange = Lib.repeat(vpRange0, scene.count); - - // upload viewport/range data to GPU - if(scene.fill2d) { - scene.fill2d.update(vpRange); - } - if(scene.line2d) { - scene.line2d.update(vpRange); - } - if(scene.error2d) { - scene.error2d.update(vpRange.concat(vpRange)); - } - if(scene.scatter2d) { - scene.scatter2d.update(vpRange); - } - if(scene.select2d) { - scene.select2d.update(vpRange); - } - if(scene.glText) { - scene.glText.forEach(function(text) { text.update(vpRange0); }); - } -}; - -},{"../../lib":719,"../../lib/prepare_regl":732,"../scatter/link_traces":1127,"../scatter/subtypes":1135,"./edit_style":1165,"gl-text":317,"regl-error2d":490,"regl-line2d":491,"regl-scatter2d":497}],1169:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -// make sure scene exists on subplot, return it -module.exports = function sceneUpdate(gd, subplot) { - var scene = subplot._scene; - - var resetOpts = { - // number of traces in subplot, since scene:subplot -> 1:1 - count: 0, - // whether scene requires init hook in plot call (dirty plot call) - dirty: true, - // last used options - lineOptions: [], - fillOptions: [], - markerOptions: [], - markerSelectedOptions: [], - markerUnselectedOptions: [], - errorXOptions: [], - errorYOptions: [], - textOptions: [], - textSelectedOptions: [], - textUnselectedOptions: [], - // selection batches - selectBatch: [], - unselectBatch: [] - }; - - // regl- component stubs, initialized in dirty plot call - var initOpts = { - fill2d: false, - scatter2d: false, - error2d: false, - line2d: false, - glText: false, - select2d: false - }; - - if(!subplot._scene) { - scene = subplot._scene = {}; - - scene.init = function init() { - Lib.extendFlat(scene, initOpts, resetOpts); - }; - - scene.init(); - - // apply new option to all regl components (used on drag) - scene.update = function update(opt) { - var opts = Lib.repeat(opt, scene.count); - - if(scene.fill2d) scene.fill2d.update(opts); - if(scene.scatter2d) scene.scatter2d.update(opts); - if(scene.line2d) scene.line2d.update(opts); - if(scene.error2d) scene.error2d.update(opts.concat(opts)); - if(scene.select2d) scene.select2d.update(opts); - if(scene.glText) { - for(var i = 0; i < scene.count; i++) { - scene.glText[i].update(opt); - } - } - }; - - // draw traces in proper order - scene.draw = function draw() { - var count = scene.count; - var fill2d = scene.fill2d; - var error2d = scene.error2d; - var line2d = scene.line2d; - var scatter2d = scene.scatter2d; - var glText = scene.glText; - var select2d = scene.select2d; - var selectBatch = scene.selectBatch; - var unselectBatch = scene.unselectBatch; - - for(var i = 0; i < count; i++) { - if(fill2d && scene.fillOrder[i]) { - fill2d.draw(scene.fillOrder[i]); - } - if(line2d && scene.lineOptions[i]) { - line2d.draw(i); - } - if(error2d) { - if(scene.errorXOptions[i]) error2d.draw(i); - if(scene.errorYOptions[i]) error2d.draw(i + count); - } - if(scatter2d && scene.markerOptions[i]) { - if(unselectBatch[i].length) { - var arg = Lib.repeat([], scene.count); - arg[i] = unselectBatch[i]; - scatter2d.draw(arg); - } else if(!selectBatch[i].length) { - scatter2d.draw(i); - } - } - if(glText[i] && scene.textOptions[i]) { - glText[i].render(); - } - } - - if(select2d) { - select2d.draw(selectBatch); - } - - scene.dirty = false; - }; - - // remove scene resources - scene.destroy = function destroy() { - if(scene.fill2d && scene.fill2d.destroy) scene.fill2d.destroy(); - if(scene.scatter2d && scene.scatter2d.destroy) scene.scatter2d.destroy(); - if(scene.error2d && scene.error2d.destroy) scene.error2d.destroy(); - if(scene.line2d && scene.line2d.destroy) scene.line2d.destroy(); - if(scene.select2d && scene.select2d.destroy) scene.select2d.destroy(); - if(scene.glText) { - scene.glText.forEach(function(text) { - if(text.destroy) text.destroy(); - }); - } - - scene.lineOptions = null; - scene.fillOptions = null; - scene.markerOptions = null; - scene.markerSelectedOptions = null; - scene.markerUnselectedOptions = null; - scene.errorXOptions = null; - scene.errorYOptions = null; - scene.textOptions = null; - scene.textSelectedOptions = null; - scene.textUnselectedOptions = null; - - scene.selectBatch = null; - scene.unselectBatch = null; - - // we can't just delete _scene, because `destroy` is called in the - // middle of supplyDefaults, before relinkPrivateKeys which will put it back. - subplot._scene = null; - }; - } - - // in case if we have scene from the last calc - reset data - if(!scene.dirty) { - Lib.extendFlat(scene, resetOpts); - } - - return scene; -}; - -},{"../../lib":719}],1170:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var subTypes = _dereq_('../scatter/subtypes'); -var styleTextSelection = _dereq_('./edit_style').styleTextSelection; - -module.exports = function select(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var selection = []; - var trace = cd[0].trace; - var stash = cd[0].t; - var len = trace._length; - var x = stash.x; - var y = stash.y; - var scene = stash._scene; - var index = stash.index; - - if(!scene) return selection; - - var hasText = subTypes.hasText(trace); - var hasMarkers = subTypes.hasMarkers(trace); - var hasOnlyLines = !hasMarkers && !hasText; - - if(trace.visible !== true || hasOnlyLines) return selection; - - var els = []; - var unels = []; - - // degenerate polygon does not enable selection - // filter out points by visible scatter ones - if(selectionTester !== false && !selectionTester.degenerate) { - for(var i = 0; i < len; i++) { - if(selectionTester.contains([stash.xpx[i], stash.ypx[i]], false, i, searchInfo)) { - els.push(i); - selection.push({ - pointNumber: i, - x: x[i], - y: y[i] - }); - } else { - unels.push(i); - } - } - } - - if(hasMarkers) { - var scatter2d = scene.scatter2d; - - if(!els.length && !unels.length) { - // reset to base styles when clearing - var baseOpts = new Array(scene.count); - baseOpts[index] = scene.markerOptions[index]; - scatter2d.update.apply(scatter2d, baseOpts); - } else if(!scene.selectBatch[index].length && !scene.unselectBatch[index].length) { - // set unselected styles on 'context' canvas (if not done already) - var unselOpts = new Array(scene.count); - unselOpts[index] = scene.markerUnselectedOptions[index]; - scatter2d.update.apply(scatter2d, unselOpts); - } - } - - scene.selectBatch[index] = els; - scene.unselectBatch[index] = unels; - - if(hasText) { - styleTextSelection(cd); - } - - return selection; -}; - -},{"../scatter/subtypes":1135,"./edit_style":1165}],1171:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var scatterGeoAttrs = _dereq_('../scattergeo/attributes'); -var scatterAttrs = _dereq_('../scatter/attributes'); -var mapboxAttrs = _dereq_('../../plots/mapbox/layout_attributes'); -var plotAttrs = _dereq_('../../plots/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var lineAttrs = scatterGeoAttrs.line; -var markerAttrs = scatterGeoAttrs.marker; - -module.exports = overrideAll({ - lon: scatterGeoAttrs.lon, - lat: scatterGeoAttrs.lat, - - // locations - // locationmode - - mode: extendFlat({}, scatterAttrs.mode, { - dflt: 'markers', - - }), - - text: extendFlat({}, scatterAttrs.text, { - - }), - hovertext: extendFlat({}, scatterAttrs.hovertext, { - - }), - - line: { - color: lineAttrs.color, - width: lineAttrs.width - - // TODO - // dash: dash - }, - - connectgaps: scatterAttrs.connectgaps, - - marker: extendFlat({ - symbol: { - valType: 'string', - dflt: 'circle', - - arrayOk: true, - - }, - opacity: markerAttrs.opacity, - size: markerAttrs.size, - sizeref: markerAttrs.sizeref, - sizemin: markerAttrs.sizemin, - sizemode: markerAttrs.sizemode - }, - colorScaleAttrs('marker') - // line - ), - - fill: scatterGeoAttrs.fill, - fillcolor: scatterAttrs.fillcolor, - - textfont: mapboxAttrs.layers.symbol.textfont, - textposition: mapboxAttrs.layers.symbol.textposition, - - below: { - valType: 'string', - - - }, - - selected: { - marker: scatterAttrs.selected.marker - }, - unselected: { - marker: scatterAttrs.unselected.marker - }, - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['lon', 'lat', 'text', 'name'] - }), - hovertemplate: hovertemplateAttrs(), -}, 'calc', 'nested'); - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plots/attributes":764,"../../plots/mapbox/layout_attributes":824,"../scatter/attributes":1112,"../scattergeo/attributes":1151}],1172:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; -var geoJsonUtils = _dereq_('../../lib/geojson_utils'); - -var Colorscale = _dereq_('../../components/colorscale'); -var Drawing = _dereq_('../../components/drawing'); -var makeBubbleSizeFn = _dereq_('../scatter/make_bubble_size_func'); -var subTypes = _dereq_('../scatter/subtypes'); -var convertTextOpts = _dereq_('../../plots/mapbox/convert_text_opts'); - -module.exports = function convert(calcTrace) { - var trace = calcTrace[0].trace; - - var isVisible = (trace.visible === true && trace._length !== 0); - var hasFill = (trace.fill !== 'none'); - var hasLines = subTypes.hasLines(trace); - var hasMarkers = subTypes.hasMarkers(trace); - var hasText = subTypes.hasText(trace); - var hasCircles = (hasMarkers && trace.marker.symbol === 'circle'); - var hasSymbols = (hasMarkers && trace.marker.symbol !== 'circle'); - - var fill = initContainer(); - var line = initContainer(); - var circle = initContainer(); - var symbol = initContainer(); - - var opts = { - fill: fill, - line: line, - circle: circle, - symbol: symbol - }; - - // early return if not visible or placeholder - if(!isVisible) return opts; - - // fill layer and line layer use the same coords - var lineCoords; - if(hasFill || hasLines) { - lineCoords = geoJsonUtils.calcTraceToLineCoords(calcTrace); - } - - if(hasFill) { - fill.geojson = geoJsonUtils.makePolygon(lineCoords); - fill.layout.visibility = 'visible'; - - Lib.extendFlat(fill.paint, { - 'fill-color': trace.fillcolor - }); - } - - if(hasLines) { - line.geojson = geoJsonUtils.makeLine(lineCoords); - line.layout.visibility = 'visible'; - - Lib.extendFlat(line.paint, { - 'line-width': trace.line.width, - 'line-color': trace.line.color, - 'line-opacity': trace.opacity - }); - - // TODO convert line.dash into line-dasharray - } - - if(hasCircles) { - var circleOpts = makeCircleOpts(calcTrace); - circle.geojson = circleOpts.geojson; - circle.layout.visibility = 'visible'; - - Lib.extendFlat(circle.paint, { - 'circle-color': circleOpts.mcc, - 'circle-radius': circleOpts.mrc, - 'circle-opacity': circleOpts.mo - }); - } - - if(hasSymbols || hasText) { - symbol.geojson = makeSymbolGeoJSON(calcTrace); - - Lib.extendFlat(symbol.layout, { - visibility: 'visible', - 'icon-image': '{symbol}-15', - 'text-field': '{text}' - }); - - if(hasSymbols) { - Lib.extendFlat(symbol.layout, { - 'icon-size': trace.marker.size / 10 - }); - - Lib.extendFlat(symbol.paint, { - 'icon-opacity': trace.opacity * trace.marker.opacity, - - // TODO does not work ?? - 'icon-color': trace.marker.color - }); - } - - if(hasText) { - var iconSize = (trace.marker || {}).size; - var textOpts = convertTextOpts(trace.textposition, iconSize); - - // all data-driven below !! - - Lib.extendFlat(symbol.layout, { - 'text-size': trace.textfont.size, - 'text-anchor': textOpts.anchor, - 'text-offset': textOpts.offset - - // TODO font family - // 'text-font': symbol.textfont.family.split(', '), - }); - - Lib.extendFlat(symbol.paint, { - 'text-color': trace.textfont.color, - 'text-opacity': trace.opacity - }); - } - } - - return opts; -}; - -function initContainer() { - return { - geojson: geoJsonUtils.makeBlank(), - layout: { visibility: 'none' }, - paint: {} - }; -} - -function makeCircleOpts(calcTrace) { - var trace = calcTrace[0].trace; - var marker = trace.marker; - var selectedpoints = trace.selectedpoints; - var arrayColor = Lib.isArrayOrTypedArray(marker.color); - var arraySize = Lib.isArrayOrTypedArray(marker.size); - var arrayOpacity = Lib.isArrayOrTypedArray(marker.opacity); - var i; - - function addTraceOpacity(o) { return trace.opacity * o; } - - function size2radius(s) { return s / 2; } - - var colorFn; - if(arrayColor) { - if(Colorscale.hasColorscale(trace, 'marker')) { - colorFn = Colorscale.makeColorScaleFuncFromTrace(marker); - } else { - colorFn = Lib.identity; - } - } - - var sizeFn; - if(arraySize) { - sizeFn = makeBubbleSizeFn(trace); - } - - var opacityFn; - if(arrayOpacity) { - opacityFn = function(mo) { - var mo2 = isNumeric(mo) ? +Lib.constrain(mo, 0, 1) : 0; - return addTraceOpacity(mo2); - }; - } - - var features = []; - for(i = 0; i < calcTrace.length; i++) { - var calcPt = calcTrace[i]; - var lonlat = calcPt.lonlat; - - if(isBADNUM(lonlat)) continue; - - var props = {}; - if(colorFn) props.mcc = calcPt.mcc = colorFn(calcPt.mc); - if(sizeFn) props.mrc = calcPt.mrc = sizeFn(calcPt.ms); - if(opacityFn) props.mo = opacityFn(calcPt.mo); - if(selectedpoints) props.selected = calcPt.selected || 0; - - features.push({ - type: 'Feature', - geometry: {type: 'Point', coordinates: lonlat}, - properties: props - }); - } - - var fns; - if(selectedpoints) { - fns = Drawing.makeSelectedPointStyleFns(trace); - - for(i = 0; i < features.length; i++) { - var d = features[i].properties; - - if(fns.selectedOpacityFn) { - d.mo = addTraceOpacity(fns.selectedOpacityFn(d)); - } - if(fns.selectedColorFn) { - d.mcc = fns.selectedColorFn(d); - } - if(fns.selectedSizeFn) { - d.mrc = fns.selectedSizeFn(d); - } - } - } - - return { - geojson: {type: 'FeatureCollection', features: features}, - mcc: arrayColor || (fns && fns.selectedColorFn) ? - {type: 'identity', property: 'mcc'} : - marker.color, - mrc: arraySize || (fns && fns.selectedSizeFn) ? - {type: 'identity', property: 'mrc'} : - size2radius(marker.size), - mo: arrayOpacity || (fns && fns.selectedOpacityFn) ? - {type: 'identity', property: 'mo'} : - addTraceOpacity(marker.opacity) - }; -} - -function makeSymbolGeoJSON(calcTrace) { - var trace = calcTrace[0].trace; - - var marker = trace.marker || {}; - var symbol = marker.symbol; - var text = trace.text; - - var fillSymbol = (symbol !== 'circle') ? - getFillFunc(symbol) : - blankFillFunc; - - var fillText = subTypes.hasText(trace) ? - getFillFunc(text) : - blankFillFunc; - - var features = []; - - for(var i = 0; i < calcTrace.length; i++) { - var calcPt = calcTrace[i]; - - if(isBADNUM(calcPt.lonlat)) continue; - - features.push({ - type: 'Feature', - geometry: { - type: 'Point', - coordinates: calcPt.lonlat - }, - properties: { - symbol: fillSymbol(calcPt.mx), - text: fillText(calcPt.tx) - } - }); - } - - return { - type: 'FeatureCollection', - features: features - }; -} - -function getFillFunc(attr) { - if(Lib.isArrayOrTypedArray(attr)) { - return function(v) { return v; }; - } else if(attr) { - return function() { return attr; }; - } else { - return blankFillFunc; - } -} - -function blankFillFunc() { return ''; } - -// only need to check lon (OR lat) -function isBADNUM(lonlat) { - return lonlat[0] === BADNUM; -} - -},{"../../components/colorscale":605,"../../components/drawing":614,"../../constants/numerical":695,"../../lib":719,"../../lib/geojson_utils":714,"../../plots/mapbox/convert_text_opts":821,"../scatter/make_bubble_size_func":1128,"../scatter/subtypes":1135,"fast-isnumeric":225}],1173:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var subTypes = _dereq_('../scatter/subtypes'); -var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); -var handleLineDefaults = _dereq_('../scatter/line_defaults'); -var handleTextDefaults = _dereq_('../scatter/text_defaults'); -var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleLonLatDefaults(traceIn, traceOut, coerce); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - coerce('mode'); - coerce('below'); - - if(subTypes.hasLines(traceOut)) { - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noDash: true}); - coerce('connectgaps'); - } - - if(subTypes.hasMarkers(traceOut)) { - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noLine: true}); - - // array marker.size and marker.color are only supported with circles - var marker = traceOut.marker; - if(marker.symbol !== 'circle') { - if(Lib.isArrayOrTypedArray(marker.size)) marker.size = marker.size[0]; - if(Lib.isArrayOrTypedArray(marker.color)) marker.color = marker.color[0]; - } - } - - if(subTypes.hasText(traceOut)) { - handleTextDefaults(traceIn, traceOut, layout, coerce, {noSelect: true}); - } - - coerce('fill'); - if(traceOut.fill !== 'none') { - handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); - } - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -function handleLonLatDefaults(traceIn, traceOut, coerce) { - var lon = coerce('lon') || []; - var lat = coerce('lat') || []; - var len = Math.min(lon.length, lat.length); - traceOut._length = len; - - return len; -} - -},{"../../lib":719,"../scatter/fillcolor_defaults":1120,"../scatter/line_defaults":1124,"../scatter/marker_defaults":1130,"../scatter/subtypes":1135,"../scatter/text_defaults":1136,"./attributes":1171}],1174:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - - -module.exports = function eventData(out, pt) { - out.lon = pt.lon; - out.lat = pt.lat; - - return out; -}; - -},{}],1175:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Fx = _dereq_('../../components/fx'); -var Lib = _dereq_('../../lib'); -var getTraceColor = _dereq_('../scatter/get_trace_color'); -var fillText = Lib.fillText; -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -module.exports = function hoverPoints(pointData, xval, yval) { - var cd = pointData.cd; - var trace = cd[0].trace; - var xa = pointData.xa; - var ya = pointData.ya; - var subplot = pointData.subplot; - - // compute winding number about [-180, 180] globe - var winding = (xval >= 0) ? - Math.floor((xval + 180) / 360) : - Math.ceil((xval - 180) / 360); - - // shift longitude to [-180, 180] to determine closest point - var lonShift = winding * 360; - var xval2 = xval - lonShift; - - function distFn(d) { - var lonlat = d.lonlat; - if(lonlat[0] === BADNUM) return Infinity; - - var lon = Lib.modHalf(lonlat[0], 360); - var lat = lonlat[1]; - var pt = subplot.project([lon, lat]); - var dx = pt.x - xa.c2p([xval2, lat]); - var dy = pt.y - ya.c2p([lon, yval]); - var rad = Math.max(3, d.mrc || 0); - - return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - 3 / rad); - } - - Fx.getClosest(cd, distFn, pointData); - - // skip the rest (for this trace) if we didn't find a close point - if(pointData.index === false) return; - - var di = cd[pointData.index]; - var lonlat = di.lonlat; - var lonlatShifted = [Lib.modHalf(lonlat[0], 360) + lonShift, lonlat[1]]; - - // shift labels back to original winded globe - var xc = xa.c2p(lonlatShifted); - var yc = ya.c2p(lonlatShifted); - var rad = di.mrc || 1; - - pointData.x0 = xc - rad; - pointData.x1 = xc + rad; - pointData.y0 = yc - rad; - pointData.y1 = yc + rad; - - pointData.color = getTraceColor(trace, di); - pointData.extraText = getExtraText(trace, di, cd[0].t.labels); - pointData.hovertemplate = trace.hovertemplate; - - return [pointData]; -}; - -function getExtraText(trace, di, labels) { - if(trace.hovertemplate) { - return; - } - - var hoverinfo = di.hi || trace.hoverinfo; - var parts = hoverinfo.split('+'); - var isAll = parts.indexOf('all') !== -1; - var hasLon = parts.indexOf('lon') !== -1; - var hasLat = parts.indexOf('lat') !== -1; - var lonlat = di.lonlat; - var text = []; - - // TODO should we use a mock axis to format hover? - // If so, we'll need to make precision be zoom-level dependent - function format(v) { - return v + '\u00B0'; - } - - if(isAll || (hasLon && hasLat)) { - text.push('(' + format(lonlat[0]) + ', ' + format(lonlat[1]) + ')'); - } else if(hasLon) { - text.push(labels.lon + format(lonlat[0])); - } else if(hasLat) { - text.push(labels.lat + format(lonlat[1])); - } - - if(isAll || parts.indexOf('text') !== -1) { - fillText(di, trace, text); - } - - return text.join('
'); -} - -},{"../../components/fx":632,"../../constants/numerical":695,"../../lib":719,"../scatter/get_trace_color":1121}],1176:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../scatter/marker_colorbar'), - calc: _dereq_('../scattergeo/calc'), - plot: _dereq_('./plot'), - hoverPoints: _dereq_('./hover'), - eventData: _dereq_('./event_data'), - selectPoints: _dereq_('./select'), - - styleOnSelect: function(_, cd) { - if(cd) { - var trace = cd[0].trace; - trace._glTrace.update(cd); - } - }, - - moduleType: 'trace', - name: 'scattermapbox', - basePlotModule: _dereq_('../../plots/mapbox'), - categories: ['mapbox', 'gl', 'symbols', 'showLegend', 'scatterlike'], - meta: { - - - } -}; - -},{"../../plots/mapbox":822,"../scatter/marker_colorbar":1129,"../scattergeo/calc":1152,"./attributes":1171,"./defaults":1173,"./event_data":1174,"./hover":1175,"./plot":1177,"./select":1178}],1177:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var convert = _dereq_('./convert'); -var LAYER_PREFIX = _dereq_('../../plots/mapbox/constants').traceLayerPrefix; -var ORDER = ['fill', 'line', 'circle', 'symbol']; - -function ScatterMapbox(subplot, uid) { - this.subplot = subplot; - this.uid = uid; - - this.sourceIds = { - fill: 'source-' + uid + '-fill', - line: 'source-' + uid + '-line', - circle: 'source-' + uid + '-circle', - symbol: 'source-' + uid + '-symbol' - }; - - this.layerIds = { - fill: LAYER_PREFIX + uid + '-fill', - line: LAYER_PREFIX + uid + '-line', - circle: LAYER_PREFIX + uid + '-circle', - symbol: LAYER_PREFIX + uid + '-symbol' - }; - - // We could merge the 'fill' source with the 'line' source and - // the 'circle' source with the 'symbol' source if ever having - // for up-to 4 sources per 'scattermapbox' traces becomes a problem. - - // previous 'below' value, - // need this to update it properly - this.below = null; -} - -var proto = ScatterMapbox.prototype; - -proto.addSource = function(k, opts) { - this.subplot.map.addSource(this.sourceIds[k], { - type: 'geojson', - data: opts.geojson - }); -}; - -proto.setSourceData = function(k, opts) { - this.subplot.map - .getSource(this.sourceIds[k]) - .setData(opts.geojson); -}; - -proto.addLayer = function(k, opts, below) { - this.subplot.addLayer({ - type: k, - id: this.layerIds[k], - source: this.sourceIds[k], - layout: opts.layout, - paint: opts.paint - }, below); -}; - -proto.update = function update(calcTrace) { - var subplot = this.subplot; - var map = subplot.map; - var optsAll = convert(calcTrace); - var below = subplot.belowLookup['trace-' + this.uid]; - var i, k, opts; - - if(below !== this.below) { - for(i = ORDER.length - 1; i >= 0; i--) { - k = ORDER[i]; - map.removeLayer(this.layerIds[k]); - } - for(i = 0; i < ORDER.length; i++) { - k = ORDER[i]; - opts = optsAll[k]; - this.addLayer(k, opts, below); - } - this.below = below; - } - - for(i = 0; i < ORDER.length; i++) { - k = ORDER[i]; - opts = optsAll[k]; - - subplot.setOptions(this.layerIds[k], 'setLayoutProperty', opts.layout); - - if(opts.layout.visibility === 'visible') { - this.setSourceData(k, opts); - subplot.setOptions(this.layerIds[k], 'setPaintProperty', opts.paint); - } - } - - // link ref for quick update during selections - calcTrace[0].trace._glTrace = this; -}; - -proto.dispose = function dispose() { - var map = this.subplot.map; - - for(var i = ORDER.length - 1; i >= 0; i--) { - var k = ORDER[i]; - map.removeLayer(this.layerIds[k]); - map.removeSource(this.sourceIds[k]); - } -}; - -module.exports = function createScatterMapbox(subplot, calcTrace) { - var trace = calcTrace[0].trace; - var scatterMapbox = new ScatterMapbox(subplot, trace.uid); - var optsAll = convert(calcTrace); - var below = scatterMapbox.below = subplot.belowLookup['trace-' + trace.uid]; - - for(var i = 0; i < ORDER.length; i++) { - var k = ORDER[i]; - var opts = optsAll[k]; - scatterMapbox.addSource(k, opts); - scatterMapbox.addLayer(k, opts, below); - } - - // link ref for quick update during selections - calcTrace[0].trace._glTrace = scatterMapbox; - - return scatterMapbox; -}; - -},{"../../plots/mapbox/constants":820,"./convert":1172}],1178:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var subtypes = _dereq_('../scatter/subtypes'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -module.exports = function selectPoints(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var xa = searchInfo.xaxis; - var ya = searchInfo.yaxis; - var selection = []; - var trace = cd[0].trace; - var i; - - if(!subtypes.hasMarkers(trace)) return []; - - if(selectionTester === false) { - for(i = 0; i < cd.length; i++) { - cd[i].selected = 0; - } - } else { - for(i = 0; i < cd.length; i++) { - var di = cd[i]; - var lonlat = di.lonlat; - - if(lonlat[0] !== BADNUM) { - var lonlat2 = [Lib.modHalf(lonlat[0], 360), lonlat[1]]; - var xy = [xa.c2p(lonlat2), ya.c2p(lonlat2)]; - - if(selectionTester.contains(xy, null, i, searchInfo)) { - selection.push({ - pointNumber: i, - lon: lonlat[0], - lat: lonlat[1] - }); - di.selected = 1; - } else { - di.selected = 0; - } - } - } - } - - return selection; -}; - -},{"../../constants/numerical":695,"../../lib":719,"../scatter/subtypes":1135}],1179:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var scatterAttrs = _dereq_('../scatter/attributes'); -var plotAttrs = _dereq_('../../plots/attributes'); -var lineAttrs = scatterAttrs.line; - -module.exports = { - mode: scatterAttrs.mode, - - r: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - - theta: { - valType: 'data_array', - editType: 'calc+clearAxisTypes', - - }, - - r0: { - valType: 'any', - dflt: 0, - - editType: 'calc+clearAxisTypes', - - }, - dr: { - valType: 'number', - dflt: 1, - - editType: 'calc', - - }, - - theta0: { - valType: 'any', - dflt: 0, - - editType: 'calc+clearAxisTypes', - - }, - dtheta: { - valType: 'number', - - editType: 'calc', - - }, - - thetaunit: { - valType: 'enumerated', - values: ['radians', 'degrees', 'gradians'], - dflt: 'degrees', - - editType: 'calc+clearAxisTypes', - - }, - - text: scatterAttrs.text, - hovertext: scatterAttrs.hovertext, - - line: { - color: lineAttrs.color, - width: lineAttrs.width, - dash: lineAttrs.dash, - shape: extendFlat({}, lineAttrs.shape, { - values: ['linear', 'spline'] - }), - smoothing: lineAttrs.smoothing, - editType: 'calc' - }, - connectgaps: scatterAttrs.connectgaps, - - marker: scatterAttrs.marker, - cliponaxis: extendFlat({}, scatterAttrs.cliponaxis, {dflt: false}), - - textposition: scatterAttrs.textposition, - textfont: scatterAttrs.textfont, - - fill: extendFlat({}, scatterAttrs.fill, { - values: ['none', 'toself', 'tonext'], - dflt: 'none', - - }), - fillcolor: scatterAttrs.fillcolor, - - // TODO error bars - // https://stackoverflow.com/a/26597487/4068492 - // error_x (error_r, error_theta) - // error_y - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['r', 'theta', 'text', 'name'] - }), - hoveron: scatterAttrs.hoveron, - hovertemplate: hovertemplateAttrs(), - - selected: scatterAttrs.selected, - unselected: scatterAttrs.unselected -}; - -},{"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../scatter/attributes":1112}],1180:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -var Axes = _dereq_('../../plots/cartesian/axes'); - -var calcColorscale = _dereq_('../scatter/colorscale_calc'); -var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); -var calcSelection = _dereq_('../scatter/calc_selection'); -var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; - -module.exports = function calc(gd, trace) { - var fullLayout = gd._fullLayout; - var subplotId = trace.subplot; - var radialAxis = fullLayout[subplotId].radialaxis; - var angularAxis = fullLayout[subplotId].angularaxis; - var rArray = radialAxis.makeCalcdata(trace, 'r'); - var thetaArray = angularAxis.makeCalcdata(trace, 'theta'); - var len = trace._length; - var cd = new Array(len); - - for(var i = 0; i < len; i++) { - var r = rArray[i]; - var theta = thetaArray[i]; - var cdi = cd[i] = {}; - - if(isNumeric(r) && isNumeric(theta)) { - cdi.r = r; - cdi.theta = theta; - } else { - cdi.r = BADNUM; - } - } - - var ppad = calcMarkerSize(trace, len); - trace._extremes.x = Axes.findExtremes(radialAxis, rArray, {ppad: ppad}); - - calcColorscale(gd, trace); - arraysToCalcdata(cd, trace); - calcSelection(cd, trace); - - return cd; -}; - -},{"../../constants/numerical":695,"../../plots/cartesian/axes":767,"../scatter/arrays_to_calcdata":1111,"../scatter/calc":1113,"../scatter/calc_selection":1114,"../scatter/colorscale_calc":1115,"fast-isnumeric":225}],1181:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var subTypes = _dereq_('../scatter/subtypes'); -var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); -var handleLineDefaults = _dereq_('../scatter/line_defaults'); -var handleLineShapeDefaults = _dereq_('../scatter/line_shape_defaults'); -var handleTextDefaults = _dereq_('../scatter/text_defaults'); -var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); -var PTS_LINESONLY = _dereq_('../scatter/constants').PTS_LINESONLY; - -var attributes = _dereq_('./attributes'); - -function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleRThetaDefaults(traceIn, traceOut, layout, coerce); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('thetaunit'); - coerce('mode', len < PTS_LINESONLY ? 'lines+markers' : 'lines'); - coerce('text'); - coerce('hovertext'); - if(traceOut.hoveron !== 'fills') coerce('hovertemplate'); - - if(subTypes.hasLines(traceOut)) { - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - handleLineShapeDefaults(traceIn, traceOut, coerce); - coerce('connectgaps'); - } - - if(subTypes.hasMarkers(traceOut)) { - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); - } - - if(subTypes.hasText(traceOut)) { - handleTextDefaults(traceIn, traceOut, layout, coerce); - } - - var dfltHoverOn = []; - - if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) { - coerce('cliponaxis'); - coerce('marker.maxdisplayed'); - dfltHoverOn.push('points'); - } - - coerce('fill'); - - if(traceOut.fill !== 'none') { - handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); - if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); - } - - if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') { - dfltHoverOn.push('fills'); - } - coerce('hoveron', dfltHoverOn.join('+') || 'points'); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -} - -function handleRThetaDefaults(traceIn, traceOut, layout, coerce) { - var r = coerce('r'); - var theta = coerce('theta'); - var len; - - if(r) { - if(theta) { - len = Math.min(r.length, theta.length); - } else { - len = r.length; - coerce('theta0'); - coerce('dtheta'); - } - } else { - if(!theta) return 0; - len = traceOut.theta.length; - coerce('r0'); - coerce('dr'); - } - - traceOut._length = len; - return len; -} - -module.exports = { - handleRThetaDefaults: handleRThetaDefaults, - supplyDefaults: supplyDefaults -}; - -},{"../../lib":719,"../scatter/constants":1116,"../scatter/fillcolor_defaults":1120,"../scatter/line_defaults":1124,"../scatter/line_shape_defaults":1126,"../scatter/marker_defaults":1130,"../scatter/subtypes":1135,"../scatter/text_defaults":1136,"./attributes":1179}],1182:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterHover = _dereq_('../scatter/hover'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var Lib = _dereq_('../../lib'); - -function hoverPoints(pointData, xval, yval, hovermode) { - var scatterPointData = scatterHover(pointData, xval, yval, hovermode); - if(!scatterPointData || scatterPointData[0].index === false) return; - - var newPointData = scatterPointData[0]; - - // hovering on fill case - if(newPointData.index === undefined) { - return scatterPointData; - } - - var subplot = pointData.subplot; - var cdi = newPointData.cd[newPointData.index]; - var trace = newPointData.trace; - - if(!subplot.isPtInside(cdi)) return; - - newPointData.xLabelVal = undefined; - newPointData.yLabelVal = undefined; - makeHoverPointText(cdi, trace, subplot, newPointData); - newPointData.hovertemplate = trace.hovertemplate; - return scatterPointData; -} - -function makeHoverPointText(cdi, trace, subplot, pointData) { - var radialAxis = subplot.radialAxis; - var angularAxis = subplot.angularAxis; - radialAxis._hovertitle = 'r'; - angularAxis._hovertitle = 'θ'; - - var rVal = radialAxis.c2l(cdi.r); - pointData.rLabel = Axes.tickText(radialAxis, rVal, 'hover').text; - - // N.B here the ° sign is part of the formatted value for thetaunit:'degrees' - var thetaVal = angularAxis.thetaunit === 'degrees' ? Lib.rad2deg(cdi.theta) : cdi.theta; - pointData.thetaLabel = Axes.tickText(angularAxis, thetaVal, 'hover').text; - - var hoverinfo = cdi.hi || trace.hoverinfo; - var text = []; - function textPart(ax, val) { - text.push(ax._hovertitle + ': ' + val); - } - - if(!trace.hovertemplate) { - var parts = hoverinfo.split('+'); - - if(parts.indexOf('all') !== -1) parts = ['r', 'theta', 'text']; - if(parts.indexOf('r') !== -1) textPart(radialAxis, pointData.rLabel); - if(parts.indexOf('theta') !== -1) textPart(angularAxis, pointData.thetaLabel); - - if(parts.indexOf('text') !== -1 && pointData.text) { - text.push(pointData.text); - delete pointData.text; - } - - pointData.extraText = text.join('
'); - } -} - -module.exports = { - hoverPoints: hoverPoints, - makeHoverPointText: makeHoverPointText -}; - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../scatter/hover":1122}],1183:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'scatterpolar', - basePlotModule: _dereq_('../../plots/polar'), - categories: ['polar', 'symbols', 'showLegend', 'scatter-like'], - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults').supplyDefaults, - colorbar: _dereq_('../scatter/marker_colorbar'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - style: _dereq_('../scatter/style').style, - styleOnSelect: _dereq_('../scatter/style').styleOnSelect, - hoverPoints: _dereq_('./hover').hoverPoints, - selectPoints: _dereq_('../scatter/select'), - - meta: { - - - } -}; - -},{"../../plots/polar":831,"../scatter/marker_colorbar":1129,"../scatter/select":1132,"../scatter/style":1134,"./attributes":1179,"./calc":1180,"./defaults":1181,"./hover":1182,"./plot":1184}],1184:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterPlot = _dereq_('../scatter/plot'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -module.exports = function plot(gd, subplot, moduleCalcData) { - var mlayer = subplot.layers.frontplot.select('g.scatterlayer'); - - var plotinfo = { - xaxis: subplot.xaxis, - yaxis: subplot.yaxis, - plot: subplot.framework, - layerClipId: subplot._hasClipOnAxisFalse ? subplot.clipIds.forTraces : null - }; - - var radialAxis = subplot.radialAxis; - var angularAxis = subplot.angularAxis; - - // convert: - // 'c' (r,theta) -> 'geometric' (r,theta) -> (x,y) - for(var i = 0; i < moduleCalcData.length; i++) { - var cdi = moduleCalcData[i]; - - for(var j = 0; j < cdi.length; j++) { - var cd = cdi[j]; - var r = cd.r; - - if(r === BADNUM) { - cd.x = cd.y = BADNUM; - } else { - var rg = radialAxis.c2g(r); - var thetag = angularAxis.c2g(cd.theta); - cd.x = rg * Math.cos(thetag); - cd.y = rg * Math.sin(thetag); - } - } - } - - scatterPlot(gd, plotinfo, moduleCalcData, mlayer); -}; - -},{"../../constants/numerical":695,"../scatter/plot":1131}],1185:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterPolarAttrs = _dereq_('../scatterpolar/attributes'); -var scatterGlAttrs = _dereq_('../scattergl/attributes'); - -module.exports = { - mode: scatterPolarAttrs.mode, - r: scatterPolarAttrs.r, - theta: scatterPolarAttrs.theta, - r0: scatterPolarAttrs.r0, - dr: scatterPolarAttrs.dr, - theta0: scatterPolarAttrs.theta0, - dtheta: scatterPolarAttrs.dtheta, - thetaunit: scatterPolarAttrs.thetaunit, - - text: scatterPolarAttrs.text, - hovertext: scatterPolarAttrs.hovertext, - hovertemplate: scatterPolarAttrs.hovertemplate, - - line: scatterGlAttrs.line, - connectgaps: scatterGlAttrs.connectgaps, - - marker: scatterGlAttrs.marker, - // no cliponaxis - - fill: scatterGlAttrs.fill, - fillcolor: scatterGlAttrs.fillcolor, - - textposition: scatterGlAttrs.textposition, - textfont: scatterGlAttrs.textfont, - - hoverinfo: scatterPolarAttrs.hoverinfo, - // no hoveron - - selected: scatterPolarAttrs.selected, - unselected: scatterPolarAttrs.unselected -}; - -},{"../scattergl/attributes":1160,"../scatterpolar/attributes":1179}],1186:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var calcColorscale = _dereq_('../scatter/colorscale_calc'); -var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; -var convert = _dereq_('../scattergl/convert'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var TOO_MANY_POINTS = _dereq_('../scattergl/constants').TOO_MANY_POINTS; - -module.exports = function calc(gd, trace) { - var fullLayout = gd._fullLayout; - var subplotId = trace.subplot; - var radialAxis = fullLayout[subplotId].radialaxis; - var angularAxis = fullLayout[subplotId].angularaxis; - var rArray = radialAxis.makeCalcdata(trace, 'r'); - var thetaArray = angularAxis.makeCalcdata(trace, 'theta'); - var len = trace._length; - var stash = {}; - - if(len < rArray.length) rArray = rArray.slice(0, len); - if(len < thetaArray.length) thetaArray = thetaArray.slice(0, len); - - stash.r = rArray; - stash.theta = thetaArray; - - calcColorscale(gd, trace); - - // only compute 'style' options in calc, as position options - // depend on the radial range and must be set in plot - var opts = stash.opts = convert.style(gd, trace); - - // For graphs with very large number of points and array marker.size, - // use average marker size instead to speed things up. - var ppad; - if(len < TOO_MANY_POINTS) { - ppad = calcMarkerSize(trace, len); - } else if(opts.marker) { - ppad = 2 * (opts.marker.sizeAvg || Math.max(opts.marker.size, 3)); - } - trace._extremes.x = Axes.findExtremes(radialAxis, rArray, {ppad: ppad}); - - return [{x: false, y: false, t: stash, trace: trace}]; -}; - -},{"../../plots/cartesian/axes":767,"../scatter/calc":1113,"../scatter/colorscale_calc":1115,"../scattergl/constants":1162,"../scattergl/convert":1163}],1187:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var subTypes = _dereq_('../scatter/subtypes'); -var handleRThetaDefaults = _dereq_('../scatterpolar/defaults').handleRThetaDefaults; -var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); -var handleLineDefaults = _dereq_('../scatter/line_defaults'); -var handleTextDefaults = _dereq_('../scatter/text_defaults'); -var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); -var PTS_LINESONLY = _dereq_('../scatter/constants').PTS_LINESONLY; - -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleRThetaDefaults(traceIn, traceOut, layout, coerce); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('thetaunit'); - coerce('mode', len < PTS_LINESONLY ? 'lines+markers' : 'lines'); - coerce('text'); - coerce('hovertext'); - if(traceOut.hoveron !== 'fills') coerce('hovertemplate'); - - if(subTypes.hasLines(traceOut)) { - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - coerce('connectgaps'); - } - - if(subTypes.hasMarkers(traceOut)) { - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce); - } - - if(subTypes.hasText(traceOut)) { - handleTextDefaults(traceIn, traceOut, layout, coerce); - } - - coerce('fill'); - if(traceOut.fill !== 'none') { - handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); - } - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -},{"../../lib":719,"../scatter/constants":1116,"../scatter/fillcolor_defaults":1120,"../scatter/line_defaults":1124,"../scatter/marker_defaults":1130,"../scatter/subtypes":1135,"../scatter/text_defaults":1136,"../scatterpolar/defaults":1181,"./attributes":1185}],1188:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hover = _dereq_('../scattergl/hover'); -var makeHoverPointText = _dereq_('../scatterpolar/hover').makeHoverPointText; - -function hoverPoints(pointData, xval, yval, hovermode) { - var cd = pointData.cd; - var stash = cd[0].t; - var rArray = stash.r; - var thetaArray = stash.theta; - - var scatterPointData = hover.hoverPoints(pointData, xval, yval, hovermode); - if(!scatterPointData || scatterPointData[0].index === false) return; - - var newPointData = scatterPointData[0]; - - if(newPointData.index === undefined) { - return scatterPointData; - } - - var subplot = pointData.subplot; - var cdi = newPointData.cd[newPointData.index]; - var trace = newPointData.trace; - - // augment pointData with r/theta param - cdi.r = rArray[newPointData.index]; - cdi.theta = thetaArray[newPointData.index]; - - if(!subplot.isPtInside(cdi)) return; - - newPointData.xLabelVal = undefined; - newPointData.yLabelVal = undefined; - makeHoverPointText(cdi, trace, subplot, newPointData); - - return scatterPointData; -} - -module.exports = { - hoverPoints: hoverPoints -}; - -},{"../scattergl/hover":1166,"../scatterpolar/hover":1182}],1189:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'scatterpolargl', - basePlotModule: _dereq_('../../plots/polar'), - categories: ['gl', 'regl', 'polar', 'symbols', 'showLegend', 'scatter-like'], - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../scatter/marker_colorbar'), - - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - hoverPoints: _dereq_('./hover').hoverPoints, - selectPoints: _dereq_('../scattergl/select'), - - meta: { - - - } -}; - -},{"../../plots/polar":831,"../scatter/marker_colorbar":1129,"../scattergl/select":1170,"./attributes":1185,"./calc":1186,"./defaults":1187,"./hover":1188,"./plot":1190}],1190:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var cluster = _dereq_('point-cluster'); -var isNumeric = _dereq_('fast-isnumeric'); - -var scatterglPlot = _dereq_('../scattergl/plot'); -var sceneUpdate = _dereq_('../scattergl/scene_update'); -var convert = _dereq_('../scattergl/convert'); - -var Lib = _dereq_('../../lib'); - -var TOO_MANY_POINTS = _dereq_('../scattergl/constants').TOO_MANY_POINTS; - -module.exports = function plot(gd, subplot, cdata) { - if(!cdata.length) return; - - var radialAxis = subplot.radialAxis; - var angularAxis = subplot.angularAxis; - var scene = sceneUpdate(gd, subplot); - - cdata.forEach(function(cdscatter) { - if(!cdscatter || !cdscatter[0] || !cdscatter[0].trace) return; - var cd = cdscatter[0]; - var trace = cd.trace; - var stash = cd.t; - var len = trace._length; - var rArray = stash.r; - var thetaArray = stash.theta; - var opts = stash.opts; - var i; - - var subRArray = rArray.slice(); - var subThetaArray = thetaArray.slice(); - - // filter out by range - for(i = 0; i < rArray.length; i++) { - if(!subplot.isPtInside({r: rArray[i], theta: thetaArray[i]})) { - subRArray[i] = NaN; - subThetaArray[i] = NaN; - } - } - - var positions = new Array(len * 2); - var x = Array(len); - var y = Array(len); - - for(i = 0; i < len; i++) { - var r = subRArray[i]; - var xx, yy; - - if(isNumeric(r)) { - var rg = radialAxis.c2g(r); - var thetag = angularAxis.c2g(subThetaArray[i], trace.thetaunit); - xx = rg * Math.cos(thetag); - yy = rg * Math.sin(thetag); - } else { - xx = yy = NaN; - } - x[i] = positions[i * 2] = xx; - y[i] = positions[i * 2 + 1] = yy; - } - - stash.tree = cluster(positions); - - // FIXME: see scattergl.js#109 - if(opts.marker && len >= TOO_MANY_POINTS) { - opts.marker.cluster = stash.tree; - } - - if(opts.marker) { - opts.markerSel.positions = opts.markerUnsel.positions = opts.marker.positions = positions; - } - - if(opts.line && positions.length > 1) { - Lib.extendFlat( - opts.line, - convert.linePositions(gd, trace, positions) - ); - } - - if(opts.text) { - Lib.extendFlat( - opts.text, - {positions: positions}, - convert.textPosition(gd, trace, opts.text, opts.marker) - ); - Lib.extendFlat( - opts.textSel, - {positions: positions}, - convert.textPosition(gd, trace, opts.text, opts.markerSel) - ); - Lib.extendFlat( - opts.textUnsel, - {positions: positions}, - convert.textPosition(gd, trace, opts.text, opts.markerUnsel) - ); - } - - if(opts.fill && !scene.fill2d) scene.fill2d = true; - if(opts.marker && !scene.scatter2d) scene.scatter2d = true; - if(opts.line && !scene.line2d) scene.line2d = true; - if(opts.text && !scene.glText) scene.glText = true; - - scene.lineOptions.push(opts.line); - scene.fillOptions.push(opts.fill); - scene.markerOptions.push(opts.marker); - scene.markerSelectedOptions.push(opts.markerSel); - scene.markerUnselectedOptions.push(opts.markerUnsel); - scene.textOptions.push(opts.text); - scene.textSelectedOptions.push(opts.textSel); - scene.textUnselectedOptions.push(opts.textUnsel); - scene.selectBatch.push([]); - scene.unselectBatch.push([]); - - stash.x = x; - stash.y = y; - stash.rawx = x; - stash.rawy = y; - stash.r = rArray; - stash.theta = thetaArray; - stash.positions = positions; - stash._scene = scene; - stash.index = scene.count; - scene.count++; - }); - - return scatterglPlot(gd, subplot, cdata); -}; - -},{"../../lib":719,"../scattergl/constants":1162,"../scattergl/convert":1163,"../scattergl/plot":1168,"../scattergl/scene_update":1169,"fast-isnumeric":225,"point-cluster":469}],1191:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var scatterAttrs = _dereq_('../scatter/attributes'); -var plotAttrs = _dereq_('../../plots/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var dash = _dereq_('../../components/drawing/attributes').dash; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var scatterMarkerAttrs = scatterAttrs.marker; -var scatterLineAttrs = scatterAttrs.line; -var scatterMarkerLineAttrs = scatterMarkerAttrs.line; - -module.exports = { - a: { - valType: 'data_array', - editType: 'calc', - - }, - b: { - valType: 'data_array', - editType: 'calc', - - }, - c: { - valType: 'data_array', - editType: 'calc', - - }, - sum: { - valType: 'number', - - dflt: 0, - min: 0, - editType: 'calc', - - }, - mode: extendFlat({}, scatterAttrs.mode, {dflt: 'markers'}), - text: extendFlat({}, scatterAttrs.text, { - - }), - hovertext: extendFlat({}, scatterAttrs.hovertext, { - - }), - line: { - color: scatterLineAttrs.color, - width: scatterLineAttrs.width, - dash: dash, - shape: extendFlat({}, scatterLineAttrs.shape, - {values: ['linear', 'spline']}), - smoothing: scatterLineAttrs.smoothing, - editType: 'calc' - }, - connectgaps: scatterAttrs.connectgaps, - cliponaxis: scatterAttrs.cliponaxis, - fill: extendFlat({}, scatterAttrs.fill, { - values: ['none', 'toself', 'tonext'], - dflt: 'none', - - }), - fillcolor: scatterAttrs.fillcolor, - marker: extendFlat({ - symbol: scatterMarkerAttrs.symbol, - opacity: scatterMarkerAttrs.opacity, - maxdisplayed: scatterMarkerAttrs.maxdisplayed, - size: scatterMarkerAttrs.size, - sizeref: scatterMarkerAttrs.sizeref, - sizemin: scatterMarkerAttrs.sizemin, - sizemode: scatterMarkerAttrs.sizemode, - line: extendFlat({ - width: scatterMarkerLineAttrs.width, - editType: 'calc' - }, - colorScaleAttrs('marker.line') - ), - gradient: scatterMarkerAttrs.gradient, - editType: 'calc' - }, - colorScaleAttrs('marker') - ), - - textfont: scatterAttrs.textfont, - textposition: scatterAttrs.textposition, - - selected: scatterAttrs.selected, - unselected: scatterAttrs.unselected, - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['a', 'b', 'c', 'text', 'name'] - }), - hoveron: scatterAttrs.hoveron, - hovertemplate: hovertemplateAttrs(), -}; - -},{"../../components/colorscale/attributes":600,"../../components/drawing/attributes":613,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../scatter/attributes":1112}],1192:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var isNumeric = _dereq_('fast-isnumeric'); - -var calcColorscale = _dereq_('../scatter/colorscale_calc'); -var arraysToCalcdata = _dereq_('../scatter/arrays_to_calcdata'); -var calcSelection = _dereq_('../scatter/calc_selection'); -var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; - -var dataArrays = ['a', 'b', 'c']; -var arraysToFill = {a: ['b', 'c'], b: ['a', 'c'], c: ['a', 'b']}; - -module.exports = function calc(gd, trace) { - var ternary = gd._fullLayout[trace.subplot]; - var displaySum = ternary.sum; - var normSum = trace.sum || displaySum; - var arrays = {a: trace.a, b: trace.b, c: trace.c}; - - var i, j, dataArray, newArray, fillArray1, fillArray2; - - // fill in one missing component - for(i = 0; i < dataArrays.length; i++) { - dataArray = dataArrays[i]; - if(arrays[dataArray]) continue; - - fillArray1 = arrays[arraysToFill[dataArray][0]]; - fillArray2 = arrays[arraysToFill[dataArray][1]]; - newArray = new Array(fillArray1.length); - for(j = 0; j < fillArray1.length; j++) { - newArray[j] = normSum - fillArray1[j] - fillArray2[j]; - } - arrays[dataArray] = newArray; - } - - // make the calcdata array - var serieslen = trace._length; - var cd = new Array(serieslen); - var a, b, c, norm, x, y; - for(i = 0; i < serieslen; i++) { - a = arrays.a[i]; - b = arrays.b[i]; - c = arrays.c[i]; - if(isNumeric(a) && isNumeric(b) && isNumeric(c)) { - a = +a; - b = +b; - c = +c; - norm = displaySum / (a + b + c); - if(norm !== 1) { - a *= norm; - b *= norm; - c *= norm; - } - // map a, b, c onto x and y where the full scale of y - // is [0, sum], and x is [-sum, sum] - // TODO: this makes `a` always the top, `b` the bottom left, - // and `c` the bottom right. Do we want options to rearrange - // these? - y = a; - x = c - b; - cd[i] = {x: x, y: y, a: a, b: b, c: c}; - } else cd[i] = {x: false, y: false}; - } - - calcMarkerSize(trace, serieslen); - calcColorscale(gd, trace); - arraysToCalcdata(cd, trace); - calcSelection(cd, trace); - - return cd; -}; - -},{"../scatter/arrays_to_calcdata":1111,"../scatter/calc":1113,"../scatter/calc_selection":1114,"../scatter/colorscale_calc":1115,"fast-isnumeric":225}],1193:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var constants = _dereq_('../scatter/constants'); -var subTypes = _dereq_('../scatter/subtypes'); -var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); -var handleLineDefaults = _dereq_('../scatter/line_defaults'); -var handleLineShapeDefaults = _dereq_('../scatter/line_shape_defaults'); -var handleTextDefaults = _dereq_('../scatter/text_defaults'); -var handleFillColorDefaults = _dereq_('../scatter/fillcolor_defaults'); - -var attributes = _dereq_('./attributes'); - - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var a = coerce('a'); - var b = coerce('b'); - var c = coerce('c'); - var len; - - // allow any one array to be missing, len is the minimum length of those - // present. Note that after coerce data_array's are either Arrays (which - // are truthy even if empty) or undefined. As in scatter, an empty array - // is different from undefined, because it can signify that this data is - // not known yet but expected in the future - if(a) { - len = a.length; - if(b) { - len = Math.min(len, b.length); - if(c) len = Math.min(len, c.length); - } else if(c) len = Math.min(len, c.length); - else len = 0; - } else if(b && c) { - len = Math.min(b.length, c.length); - } - - if(!len) { - traceOut.visible = false; - return; - } - - traceOut._length = len; - - coerce('sum'); - - coerce('text'); - coerce('hovertext'); - if(traceOut.hoveron !== 'fills') coerce('hovertemplate'); - - var defaultMode = len < constants.PTS_LINESONLY ? 'lines+markers' : 'lines'; - coerce('mode', defaultMode); - - if(subTypes.hasLines(traceOut)) { - handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce); - handleLineShapeDefaults(traceIn, traceOut, coerce); - coerce('connectgaps'); - } - - if(subTypes.hasMarkers(traceOut)) { - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true}); - } - - if(subTypes.hasText(traceOut)) { - handleTextDefaults(traceIn, traceOut, layout, coerce); - } - - var dfltHoverOn = []; - - if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) { - coerce('cliponaxis'); - coerce('marker.maxdisplayed'); - dfltHoverOn.push('points'); - } - - coerce('fill'); - if(traceOut.fill !== 'none') { - handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce); - if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce); - } - - if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') { - dfltHoverOn.push('fills'); - } - coerce('hoveron', dfltHoverOn.join('+') || 'points'); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -},{"../../lib":719,"../scatter/constants":1116,"../scatter/fillcolor_defaults":1120,"../scatter/line_defaults":1124,"../scatter/line_shape_defaults":1126,"../scatter/marker_defaults":1130,"../scatter/subtypes":1135,"../scatter/text_defaults":1136,"./attributes":1191}],1194:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function eventData(out, pt, trace, cd, pointNumber) { - if(pt.xa) out.xaxis = pt.xa; - if(pt.ya) out.yaxis = pt.ya; - - if(cd[pointNumber]) { - var cdi = cd[pointNumber]; - - // N.B. These are the normalized coordinates. - out.a = cdi.a; - out.b = cdi.b; - out.c = cdi.c; - } else { - // for fill-hover only - out.a = pt.a; - out.b = pt.b; - out.c = pt.c; - } - - return out; -}; - -},{}],1195:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var scatterHover = _dereq_('../scatter/hover'); -var Axes = _dereq_('../../plots/cartesian/axes'); - - -module.exports = function hoverPoints(pointData, xval, yval, hovermode) { - var scatterPointData = scatterHover(pointData, xval, yval, hovermode); - if(!scatterPointData || scatterPointData[0].index === false) return; - - var newPointData = scatterPointData[0]; - - // if hovering on a fill, we don't show any point data so the label is - // unchanged from what scatter gives us - except that it needs to - // be constrained to the trianglular plot area, not just the rectangular - // area defined by the synthetic x and y axes - // TODO: in some cases the vertical middle of the shape is not within - // the triangular viewport at all, so the label can become disconnected - // from the shape entirely. But calculating what portion of the shape - // is actually visible, as constrained by the diagonal axis lines, is not - // so easy and anyway we lost the information we would have needed to do - // this inside scatterHover. - if(newPointData.index === undefined) { - var yFracUp = 1 - (newPointData.y0 / pointData.ya._length); - var xLen = pointData.xa._length; - var xMin = xLen * yFracUp / 2; - var xMax = xLen - xMin; - newPointData.x0 = Math.max(Math.min(newPointData.x0, xMax), xMin); - newPointData.x1 = Math.max(Math.min(newPointData.x1, xMax), xMin); - return scatterPointData; - } - - var cdi = newPointData.cd[newPointData.index]; - - newPointData.a = cdi.a; - newPointData.b = cdi.b; - newPointData.c = cdi.c; - - newPointData.xLabelVal = undefined; - newPointData.yLabelVal = undefined; - - var ternary = newPointData.subplot; - newPointData.aLabel = Axes.tickText(ternary.aaxis, cdi.a, 'hover').text; - newPointData.bLabel = Axes.tickText(ternary.baxis, cdi.b, 'hover').text; - newPointData.cLabel = Axes.tickText(ternary.caxis, cdi.c, 'hover').text; - - var trace = newPointData.trace; - var hoverinfo = cdi.hi || trace.hoverinfo; - var text = []; - function textPart(ax, val) { - text.push(ax._hovertitle + ': ' + val); - } - if(!trace.hovertemplate) { - var parts = hoverinfo.split('+'); - if(parts.indexOf('all') !== -1) parts = ['a', 'b', 'c']; - if(parts.indexOf('a') !== -1) textPart(ternary.aaxis, newPointData.aLabel); - if(parts.indexOf('b') !== -1) textPart(ternary.baxis, newPointData.bLabel); - if(parts.indexOf('c') !== -1) textPart(ternary.caxis, newPointData.cLabel); - } - newPointData.extraText = text.join('
'); - newPointData.hovertemplate = trace.hovertemplate; - return scatterPointData; -}; - -},{"../../plots/cartesian/axes":767,"../scatter/hover":1122}],1196:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../scatter/marker_colorbar'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - style: _dereq_('../scatter/style').style, - styleOnSelect: _dereq_('../scatter/style').styleOnSelect, - hoverPoints: _dereq_('./hover'), - selectPoints: _dereq_('../scatter/select'), - eventData: _dereq_('./event_data'), - - moduleType: 'trace', - name: 'scatterternary', - basePlotModule: _dereq_('../../plots/ternary'), - categories: ['ternary', 'symbols', 'showLegend', 'scatter-like'], - meta: { - - - } -}; - -},{"../../plots/ternary":843,"../scatter/marker_colorbar":1129,"../scatter/select":1132,"../scatter/style":1134,"./attributes":1191,"./calc":1192,"./defaults":1193,"./event_data":1194,"./hover":1195,"./plot":1197}],1197:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var scatterPlot = _dereq_('../scatter/plot'); - -module.exports = function plot(gd, ternary, moduleCalcData) { - var plotContainer = ternary.plotContainer; - - // remove all nodes inside the scatter layer - plotContainer.select('.scatterlayer').selectAll('*').remove(); - - // mimic cartesian plotinfo - var plotinfo = { - xaxis: ternary.xaxis, - yaxis: ternary.yaxis, - plot: plotContainer, - layerClipId: ternary._hasClipOnAxisFalse ? ternary.clipIdRelative : null - }; - - var scatterLayer = ternary.layers.frontplot.select('g.scatterlayer'); - - scatterPlot(gd, plotinfo, moduleCalcData, scatterLayer); -}; - -},{"../scatter/plot":1131}],1198:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var scatterAttrs = _dereq_('../scatter/attributes'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var scatterGlAttrs = _dereq_('../scattergl/attributes'); -var cartesianIdRegex = _dereq_('../../plots/cartesian/constants').idRegex; -var templatedArray = _dereq_('../../plot_api/plot_template').templatedArray; -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var scatterMarkerAttrs = scatterAttrs.marker; -var scatterMarkerLineAttrs = scatterMarkerAttrs.line; - -var markerLineAttrs = extendFlat(colorScaleAttrs('marker.line', {editTypeOverride: 'calc'}), { - width: extendFlat({}, scatterMarkerLineAttrs.width, {editType: 'calc'}), - editType: 'calc' -}); - -var markerAttrs = extendFlat(colorScaleAttrs('marker'), { - symbol: scatterMarkerAttrs.symbol, - size: extendFlat({}, scatterMarkerAttrs.size, {editType: 'markerSize'}), - sizeref: scatterMarkerAttrs.sizeref, - sizemin: scatterMarkerAttrs.sizemin, - sizemode: scatterMarkerAttrs.sizemode, - opacity: scatterMarkerAttrs.opacity, - colorbar: scatterMarkerAttrs.colorbar, - line: markerLineAttrs, - editType: 'calc' -}); - -markerAttrs.color.editType = markerAttrs.cmin.editType = markerAttrs.cmax.editType = 'style'; - -function makeAxesValObject(axLetter) { - return { - valType: 'info_array', - freeLength: true, - - editType: 'calc', - items: { - valType: 'subplotid', - regex: cartesianIdRegex[axLetter], - editType: 'plot' - }, - - }; -} - -module.exports = { - dimensions: templatedArray('dimension', { - visible: { - valType: 'boolean', - - dflt: true, - editType: 'calc', - - }, - label: { - valType: 'string', - - editType: 'calc', - - }, - values: { - valType: 'data_array', - - editType: 'calc+clearAxisTypes', - - }, - - axis: { - type: { - valType: 'enumerated', - values: ['linear', 'log', 'date', 'category'], - - editType: 'calc+clearAxisTypes', - - }, - - // TODO make 'true' the default in v2? - matches: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - - editType: 'calc+clearAxisTypes' - }, - - // TODO should add an attribute to pin down x only vars and y only vars - // like https://seaborn.pydata.org/generated/seaborn.pairplot.html - // x_vars and y_vars - - // maybe more axis defaulting option e.g. `showgrid: false` - - editType: 'calc+clearAxisTypes' - }), - - // mode: {}, (only 'markers' for now) - - text: extendFlat({}, scatterGlAttrs.text, { - - }), - hovertext: extendFlat({}, scatterGlAttrs.hovertext, { - - }), - - hovertemplate: hovertemplateAttrs(), - - marker: markerAttrs, - - xaxes: makeAxesValObject('x'), - yaxes: makeAxesValObject('y'), - - diagonal: { - visible: { - valType: 'boolean', - - dflt: true, - editType: 'calc', - - }, - - // type: 'scattergl' | 'histogram' | 'box' | 'violin' - // ... - // more options - - editType: 'calc' - }, - - showupperhalf: { - valType: 'boolean', - - dflt: true, - editType: 'calc', - - }, - showlowerhalf: { - valType: 'boolean', - - dflt: true, - editType: 'calc', - - }, - - selected: { - marker: scatterGlAttrs.selected.marker, - editType: 'calc' - }, - unselected: { - marker: scatterGlAttrs.unselected.marker, - editType: 'calc' - }, - - opacity: scatterGlAttrs.opacity -}; - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plot_api/plot_template":757,"../../plots/cartesian/constants":773,"../scatter/attributes":1112,"../scattergl/attributes":1160}],1199:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var createLine = _dereq_('regl-line2d'); - -var Registry = _dereq_('../../registry'); -var prepareRegl = _dereq_('../../lib/prepare_regl'); -var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; -var Cartesian = _dereq_('../../plots/cartesian'); -var getFromId = _dereq_('../../plots/cartesian/axis_ids').getFromId; -var shouldShowZeroLine = _dereq_('../../plots/cartesian/axes').shouldShowZeroLine; - -var SPLOM = 'splom'; - -function plot(gd) { - var fullLayout = gd._fullLayout; - var _module = Registry.getModule(SPLOM); - var splomCalcData = getModuleCalcData(gd.calcdata, _module)[0]; - - var success = prepareRegl(gd, ['ANGLE_instanced_arrays', 'OES_element_index_uint']); - if(!success) return; - - if(fullLayout._hasOnlyLargeSploms) { - updateGrid(gd); - } - - _module.plot(gd, {}, splomCalcData); -} - -function drag(gd) { - var cd = gd.calcdata; - var fullLayout = gd._fullLayout; - - if(fullLayout._hasOnlyLargeSploms) { - updateGrid(gd); - } - - for(var i = 0; i < cd.length; i++) { - var cd0 = cd[i][0]; - var trace = cd0.trace; - var scene = fullLayout._splomScenes[trace.uid]; - - if(trace.type === 'splom' && scene && scene.matrix) { - dragOne(gd, trace, scene); - } - } -} - -function dragOne(gd, trace, scene) { - var visibleLength = scene.matrixOptions.data.length; - var visibleDims = trace._visibleDims; - var ranges = scene.viewOpts.ranges = new Array(visibleLength); - - for(var k = 0; k < visibleDims.length; k++) { - var i = visibleDims[k]; - var rng = ranges[k] = new Array(4); - - var xa = getFromId(gd, trace._diag[i][0]); - if(xa) { - rng[0] = xa.r2l(xa.range[0]); - rng[2] = xa.r2l(xa.range[1]); - } - - var ya = getFromId(gd, trace._diag[i][1]); - if(ya) { - rng[1] = ya.r2l(ya.range[0]); - rng[3] = ya.r2l(ya.range[1]); - } - } - - if(scene.selectBatch.length || scene.unselectBatch.length) { - scene.matrix.update({ranges: ranges}, {ranges: ranges}); - } else { - scene.matrix.update({ranges: ranges}); - } -} - -function updateGrid(gd) { - var fullLayout = gd._fullLayout; - var regl = fullLayout._glcanvas.data()[0].regl; - var splomGrid = fullLayout._splomGrid; - - if(!splomGrid) { - splomGrid = fullLayout._splomGrid = createLine(regl); - } - splomGrid.update(makeGridData(gd)); -} - -function makeGridData(gd) { - var fullLayout = gd._fullLayout; - var gs = fullLayout._size; - var fullView = [0, 0, fullLayout.width, fullLayout.height]; - var lookup = {}; - var k; - - function push(prefix, ax, x0, x1, y0, y1) { - var lcolor = ax[prefix + 'color']; - var lwidth = ax[prefix + 'width']; - var key = String(lcolor + lwidth); - - if(key in lookup) { - lookup[key].data.push(NaN, NaN, x0, x1, y0, y1); - } else { - lookup[key] = { - data: [x0, x1, y0, y1], - join: 'rect', - thickness: lwidth, - color: lcolor, - viewport: fullView, - range: fullView, - overlay: false - }; - } - } - - for(k in fullLayout._splomSubplots) { - var sp = fullLayout._plots[k]; - var xa = sp.xaxis; - var ya = sp.yaxis; - var xVals = xa._vals; - var yVals = ya._vals; - // ya.l2p assumes top-to-bottom coordinate system (a la SVG), - // we need to compute bottom-to-top offsets and slopes: - var yOffset = gs.b + ya.domain[0] * gs.h; - var ym = -ya._m; - var yb = -ym * ya.r2l(ya.range[0], ya.calendar); - var x, y; - - if(xa.showgrid) { - for(k = 0; k < xVals.length; k++) { - x = xa._offset + xa.l2p(xVals[k].x); - push('grid', xa, x, yOffset, x, yOffset + ya._length); - } - } - if(ya.showgrid) { - for(k = 0; k < yVals.length; k++) { - y = yOffset + yb + ym * yVals[k].x; - push('grid', ya, xa._offset, y, xa._offset + xa._length, y); - } - } - if(shouldShowZeroLine(gd, xa, ya)) { - x = xa._offset + xa.l2p(0); - push('zeroline', xa, x, yOffset, x, yOffset + ya._length); - } - if(shouldShowZeroLine(gd, ya, xa)) { - y = yOffset + yb + 0; - push('zeroline', ya, xa._offset, y, xa._offset + xa._length, y); - } - } - - var gridBatches = []; - for(k in lookup) { - gridBatches.push(lookup[k]); - } - - return gridBatches; -} - -function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var lookup = {}; - var i; - - if(oldFullLayout._splomScenes) { - for(i = 0; i < newFullData.length; i++) { - var newTrace = newFullData[i]; - if(newTrace.type === 'splom') { - lookup[newTrace.uid] = 1; - } - } - for(i = 0; i < oldFullData.length; i++) { - var oldTrace = oldFullData[i]; - if(!lookup[oldTrace.uid]) { - var scene = oldFullLayout._splomScenes[oldTrace.uid]; - if(scene && scene.destroy) scene.destroy(); - // must first set scene to null in order to get garbage collected - oldFullLayout._splomScenes[oldTrace.uid] = null; - delete oldFullLayout._splomScenes[oldTrace.uid]; - } - } - } - - if(Object.keys(oldFullLayout._splomScenes || {}).length === 0) { - delete oldFullLayout._splomScenes; - } - - if(oldFullLayout._splomGrid && - (!newFullLayout._hasOnlyLargeSploms && oldFullLayout._hasOnlyLargeSploms)) { - // must first set scene to null in order to get garbage collected - oldFullLayout._splomGrid.destroy(); - oldFullLayout._splomGrid = null; - delete oldFullLayout._splomGrid; - } - - Cartesian.clean(newFullData, newFullLayout, oldFullData, oldFullLayout); -} - -module.exports = { - name: SPLOM, - attr: Cartesian.attr, - attrRegex: Cartesian.attrRegex, - layoutAttributes: Cartesian.layoutAttributes, - supplyLayoutDefaults: Cartesian.supplyLayoutDefaults, - drawFramework: Cartesian.drawFramework, - plot: plot, - drag: drag, - updateGrid: updateGrid, - clean: clean, - updateFx: Cartesian.updateFx, - toSVG: Cartesian.toSVG -}; - -},{"../../lib/prepare_regl":732,"../../plots/cartesian":778,"../../plots/cartesian/axes":767,"../../plots/cartesian/axis_ids":770,"../../plots/get_data":802,"../../registry":847,"regl-line2d":491}],1200:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var AxisIDs = _dereq_('../../plots/cartesian/axis_ids'); - -var calcMarkerSize = _dereq_('../scatter/calc').calcMarkerSize; -var calcAxisExpansion = _dereq_('../scatter/calc').calcAxisExpansion; -var calcColorscale = _dereq_('../scatter/colorscale_calc'); -var convertMarkerSelection = _dereq_('../scattergl/convert').markerSelection; -var convertMarkerStyle = _dereq_('../scattergl/convert').markerStyle; -var sceneUpdate = _dereq_('./scene_update'); - -var BADNUM = _dereq_('../../constants/numerical').BADNUM; -var TOO_MANY_POINTS = _dereq_('../scattergl/constants').TOO_MANY_POINTS; - -module.exports = function calc(gd, trace) { - var dimensions = trace.dimensions; - var commonLength = trace._length; - var opts = {}; - // 'c' for calculated, 'l' for linear, - // only differ here for log axes, pass ldata to createMatrix as 'data' - var cdata = opts.cdata = []; - var ldata = opts.data = []; - // keep track of visible dimensions - var visibleDims = trace._visibleDims = []; - var i, k, dim, xa, ya; - - function makeCalcdata(ax, dim) { - // call makeCalcdata with fake input - var ccol = ax.makeCalcdata({ - v: dim.values, - vcalendar: trace.calendar - }, 'v'); - - for(var j = 0; j < ccol.length; j++) { - ccol[j] = ccol[j] === BADNUM ? NaN : ccol[j]; - } - cdata.push(ccol); - ldata.push(ax.type === 'log' ? Lib.simpleMap(ccol, ax.c2l) : ccol); - } - - for(i = 0; i < dimensions.length; i++) { - dim = dimensions[i]; - - if(dim.visible) { - xa = AxisIDs.getFromId(gd, trace._diag[i][0]); - ya = AxisIDs.getFromId(gd, trace._diag[i][1]); - - // if corresponding x & y axes don't have matching types, skip dim - if(xa && ya && xa.type !== ya.type) { - Lib.log('Skipping splom dimension ' + i + ' with conflicting axis types'); - continue; - } - - if(xa) { - makeCalcdata(xa, dim); - if(ya && ya.type === 'category') { - ya._categories = xa._categories.slice(); - } - } else { - // should not make it here, if both xa and ya undefined - makeCalcdata(ya, dim); - } - - visibleDims.push(i); - } - } - - calcColorscale(gd, trace); - Lib.extendFlat(opts, convertMarkerStyle(trace)); - - var visibleLength = cdata.length; - var hasTooManyPoints = (visibleLength * commonLength) > TOO_MANY_POINTS; - - // Reuse SVG scatter axis expansion routine. - // For graphs with very large number of points and array marker.size, - // use average marker size instead to speed things up. - var ppad; - if(hasTooManyPoints) { - ppad = 2 * (opts.sizeAvg || Math.max(opts.size, 3)); - } else { - ppad = calcMarkerSize(trace, commonLength); - } - - for(k = 0; k < visibleDims.length; k++) { - i = visibleDims[k]; - dim = dimensions[i]; - xa = AxisIDs.getFromId(gd, trace._diag[i][0]) || {}; - ya = AxisIDs.getFromId(gd, trace._diag[i][1]) || {}; - calcAxisExpansion(gd, trace, xa, ya, cdata[k], cdata[k], ppad); - } - - var scene = sceneUpdate(gd, trace); - if(!scene.matrix) scene.matrix = true; - scene.matrixOptions = opts; - - scene.selectedOptions = convertMarkerSelection(trace, trace.selected); - scene.unselectedOptions = convertMarkerSelection(trace, trace.unselected); - - return [{x: false, y: false, t: {}, trace: trace}]; -}; - -},{"../../constants/numerical":695,"../../lib":719,"../../plots/cartesian/axis_ids":770,"../scatter/calc":1113,"../scatter/colorscale_calc":1115,"../scattergl/constants":1162,"../scattergl/convert":1163,"./scene_update":1207}],1201:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var handleArrayContainerDefaults = _dereq_('../../plots/array_container_defaults'); - -var attributes = _dereq_('./attributes'); -var subTypes = _dereq_('../scatter/subtypes'); -var handleMarkerDefaults = _dereq_('../scatter/marker_defaults'); -var mergeLength = _dereq_('../parcoords/merge_length'); -var OPEN_RE = /-open/; - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var dimensions = handleArrayContainerDefaults(traceIn, traceOut, { - name: 'dimensions', - handleItemDefaults: dimensionDefaults - }); - - var showDiag = coerce('diagonal.visible'); - var showUpper = coerce('showupperhalf'); - var showLower = coerce('showlowerhalf'); - - var dimLength = mergeLength(traceOut, dimensions, 'values'); - - if(!dimLength || (!showDiag && !showUpper && !showLower)) { - traceOut.visible = false; - return; - } - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce); - - var isOpen = OPEN_RE.test(traceOut.marker.symbol); - var isBubble = subTypes.isBubble(traceOut); - coerce('marker.line.width', isOpen || isBubble ? 1 : 0); - - handleAxisDefaults(traceIn, traceOut, layout, coerce); - - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); -}; - -function dimensionDefaults(dimIn, dimOut) { - function coerce(attr, dflt) { - return Lib.coerce(dimIn, dimOut, attributes.dimensions, attr, dflt); - } - - coerce('label'); - var values = coerce('values'); - - if(!(values && values.length)) dimOut.visible = false; - else coerce('visible'); - - coerce('axis.type'); - coerce('axis.matches'); -} - -function handleAxisDefaults(traceIn, traceOut, layout, coerce) { - var dimensions = traceOut.dimensions; - var dimLength = dimensions.length; - var showUpper = traceOut.showupperhalf; - var showLower = traceOut.showlowerhalf; - var showDiag = traceOut.diagonal.visible; - var i, j; - - var xAxesDflt = new Array(dimLength); - var yAxesDflt = new Array(dimLength); - - for(i = 0; i < dimLength; i++) { - var suffix = i ? i + 1 : ''; - xAxesDflt[i] = 'x' + suffix; - yAxesDflt[i] = 'y' + suffix; - } - - var xaxes = coerce('xaxes', xAxesDflt); - var yaxes = coerce('yaxes', yAxesDflt); - - // build list of [x,y] axis corresponding to each dimensions[i], - // very useful for passing options to regl-splom - var diag = traceOut._diag = new Array(dimLength); - - // lookup for 'drawn' x|y axes, to avoid costly indexOf downstream - traceOut._xaxes = {}; - traceOut._yaxes = {}; - - // list of 'drawn' x|y axes, use to generate list of subplots - var xList = []; - var yList = []; - - function fillAxisStashes(axId, counterAxId, dim, list) { - if(!axId) return; - - var axLetter = axId.charAt(0); - var stash = layout._splomAxes[axLetter]; - - traceOut['_' + axLetter + 'axes'][axId] = 1; - list.push(axId); - - if(!(axId in stash)) { - var s = stash[axId] = {}; - if(dim) { - s.label = dim.label || ''; - if(dim.visible && dim.axis) { - if(dim.axis.type) s.type = dim.axis.type; - if(dim.axis.matches) s.matches = counterAxId; - } - } - } - } - - // cases where showDiag and showLower or showUpper are false - // no special treatment as the 'drawn' x-axes and y-axes no longer match - // the dimensions items and xaxes|yaxes 1-to-1 - var mustShiftX = !showDiag && !showLower; - var mustShiftY = !showDiag && !showUpper; - - traceOut._axesDim = {}; - for(i = 0; i < dimLength; i++) { - var dim = dimensions[i]; - var i0 = i === 0; - var iN = i === dimLength - 1; - - var xaId = (i0 && mustShiftX) || (iN && mustShiftY) ? - undefined : - xaxes[i]; - - var yaId = (i0 && mustShiftY) || (iN && mustShiftX) ? - undefined : - yaxes[i]; - - fillAxisStashes(xaId, yaId, dim, xList); - fillAxisStashes(yaId, xaId, dim, yList); - diag[i] = [xaId, yaId]; - traceOut._axesDim[xaId] = i; - traceOut._axesDim[yaId] = i; - } - - // fill in splom subplot keys - for(i = 0; i < xList.length; i++) { - for(j = 0; j < yList.length; j++) { - var id = xList[i] + yList[j]; - - if(i > j && showUpper) { - layout._splomSubplots[id] = 1; - } else if(i < j && showLower) { - layout._splomSubplots[id] = 1; - } else if(i === j && (showDiag || !showLower || !showUpper)) { - // need to include diagonal subplots when - // hiding one half and the diagonal - layout._splomSubplots[id] = 1; - } - } - } - - // when lower half is omitted, or when just the diagonal is gone, - // override grid default to make sure axes remain on - // the left/bottom of the plot area - if(!showLower || (!showDiag && showUpper && showLower)) { - layout._splomGridDflt.xside = 'bottom'; - layout._splomGridDflt.yside = 'left'; - } -} - -},{"../../lib":719,"../../plots/array_container_defaults":763,"../parcoords/merge_length":1083,"../scatter/marker_defaults":1130,"../scatter/subtypes":1135,"./attributes":1198}],1202:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var calcColorscale = _dereq_('../scatter/colorscale_calc'); -var convertMarkerStyle = _dereq_('../scattergl/convert').markerStyle; - -module.exports = function editStyle(gd, cd0) { - var trace = cd0.trace; - var scene = gd._fullLayout._splomScenes[trace.uid]; - - if(scene) { - calcColorscale(gd, trace); - - Lib.extendFlat(scene.matrixOptions, convertMarkerStyle(trace)); - // TODO [un]selected styles? - - var opts = Lib.extendFlat({}, scene.matrixOptions, scene.viewOpts); - - // TODO this is too long for arrayOk attributes! - scene.matrix.update(opts, null); - } -}; - -},{"../../lib":719,"../scatter/colorscale_calc":1115,"../scattergl/convert":1163}],1203:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -exports.getDimIndex = function getDimIndex(trace, ax) { - var axId = ax._id; - var axLetter = axId.charAt(0); - var ind = {x: 0, y: 1}[axLetter]; - var visibleDims = trace._visibleDims; - - for(var k = 0; k < visibleDims.length; k++) { - var i = visibleDims[k]; - if(trace._diag[i][ind] === axId) return k; - } - return false; -}; - -},{}],1204:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var helpers = _dereq_('./helpers'); -var calcHover = _dereq_('../scattergl/hover').calcHover; - -function hoverPoints(pointData, xval, yval) { - var cd = pointData.cd; - var trace = cd[0].trace; - var scene = pointData.scene; - var cdata = scene.matrixOptions.cdata; - var xa = pointData.xa; - var ya = pointData.ya; - var xpx = xa.c2p(xval); - var ypx = ya.c2p(yval); - var maxDistance = pointData.distance; - - var xi = helpers.getDimIndex(trace, xa); - var yi = helpers.getDimIndex(trace, ya); - if(xi === false || yi === false) return [pointData]; - - var x = cdata[xi]; - var y = cdata[yi]; - - var id, dxy; - var minDist = maxDistance; - - for(var i = 0; i < x.length; i++) { - var ptx = x[i]; - var pty = y[i]; - var dx = xa.c2p(ptx) - xpx; - var dy = ya.c2p(pty) - ypx; - var dist = Math.sqrt(dx * dx + dy * dy); - - if(dist < minDist) { - minDist = dxy = dist; - id = i; - } - } - - pointData.index = id; - pointData.distance = minDist; - pointData.dxy = dxy; - - if(id === undefined) return [pointData]; - - calcHover(pointData, x, y, trace); - - return [pointData]; -} - -module.exports = { - hoverPoints: hoverPoints -}; - -},{"../scattergl/hover":1166,"./helpers":1203}],1205:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Grid = _dereq_('../../components/grid'); - -module.exports = { - moduleType: 'trace', - name: 'splom', - - basePlotModule: _dereq_('./base_plot'), - categories: ['gl', 'regl', 'cartesian', 'symbols', 'showLegend', 'scatter-like'], - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: _dereq_('../scatter/marker_colorbar'), - - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - hoverPoints: _dereq_('./hover').hoverPoints, - selectPoints: _dereq_('./select'), - editStyle: _dereq_('./edit_style'), - - meta: { - - } -}; - -// splom traces use the 'grid' component to generate their axes, -// register it here -Registry.register(Grid); - -},{"../../components/grid":636,"../../registry":847,"../scatter/marker_colorbar":1129,"./attributes":1198,"./base_plot":1199,"./calc":1200,"./defaults":1201,"./edit_style":1202,"./hover":1204,"./plot":1206,"./select":1208}],1206:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var createMatrix = _dereq_('regl-splom'); - -var Lib = _dereq_('../../lib'); -var AxisIDs = _dereq_('../../plots/cartesian/axis_ids'); - -module.exports = function plot(gd, _, splomCalcData) { - if(!splomCalcData.length) return; - - for(var i = 0; i < splomCalcData.length; i++) { - plotOne(gd, splomCalcData[i][0]); - } -}; - -function plotOne(gd, cd0) { - var fullLayout = gd._fullLayout; - var gs = fullLayout._size; - var trace = cd0.trace; - var stash = cd0.t; - var scene = fullLayout._splomScenes[trace.uid]; - var matrixOpts = scene.matrixOptions; - var cdata = matrixOpts.cdata; - var regl = fullLayout._glcanvas.data()[0].regl; - var dragmode = fullLayout.dragmode; - var xa, ya; - var i, j, k; - - if(cdata.length === 0) return; - - // augment options with proper upper/lower halves - // regl-splom's default grid starts from bottom-left - matrixOpts.lower = trace.showupperhalf; - matrixOpts.upper = trace.showlowerhalf; - matrixOpts.diagonal = trace.diagonal.visible; - - var visibleDims = trace._visibleDims; - var visibleLength = cdata.length; - var viewOpts = scene.viewOpts = {}; - viewOpts.ranges = new Array(visibleLength); - viewOpts.domains = new Array(visibleLength); - - for(k = 0; k < visibleDims.length; k++) { - i = visibleDims[k]; - - var rng = viewOpts.ranges[k] = new Array(4); - var dmn = viewOpts.domains[k] = new Array(4); - - xa = AxisIDs.getFromId(gd, trace._diag[i][0]); - if(xa) { - rng[0] = xa._rl[0]; - rng[2] = xa._rl[1]; - dmn[0] = xa.domain[0]; - dmn[2] = xa.domain[1]; - } - - ya = AxisIDs.getFromId(gd, trace._diag[i][1]); - if(ya) { - rng[1] = ya._rl[0]; - rng[3] = ya._rl[1]; - dmn[1] = ya.domain[0]; - dmn[3] = ya.domain[1]; - } - } - - viewOpts.viewport = [gs.l, gs.b, gs.w + gs.l, gs.h + gs.b]; - - if(scene.matrix === true) { - scene.matrix = createMatrix(regl); - } - - var clickSelectEnabled = fullLayout.clickmode.indexOf('select') > -1; - var selectMode = dragmode === 'lasso' || dragmode === 'select' || - !!trace.selectedpoints || clickSelectEnabled; - var needsBaseUpdate = true; - - if(selectMode) { - var commonLength = trace._length; - - // regenerate scene batch, if traces number changed during selection - if(trace.selectedpoints) { - scene.selectBatch = trace.selectedpoints; - - var selPts = trace.selectedpoints; - var selDict = {}; - for(i = 0; i < selPts.length; i++) { - selDict[selPts[i]] = true; - } - var unselPts = []; - for(i = 0; i < commonLength; i++) { - if(!selDict[i]) unselPts.push(i); - } - scene.unselectBatch = unselPts; - } - - // precalculate px coords since we are not going to pan during select - var xpx = stash.xpx = new Array(visibleLength); - var ypx = stash.ypx = new Array(visibleLength); - - for(k = 0; k < visibleDims.length; k++) { - i = visibleDims[k]; - - xa = AxisIDs.getFromId(gd, trace._diag[i][0]); - if(xa) { - xpx[k] = new Array(commonLength); - for(j = 0; j < commonLength; j++) { - xpx[k][j] = xa.c2p(cdata[k][j]); - } - } - - ya = AxisIDs.getFromId(gd, trace._diag[i][1]); - if(ya) { - ypx[k] = new Array(commonLength); - for(j = 0; j < commonLength; j++) { - ypx[k][j] = ya.c2p(cdata[k][j]); - } - } - } - - if(scene.selectBatch.length || scene.unselectBatch.length) { - var unselOpts = Lib.extendFlat({}, matrixOpts, scene.unselectedOptions, viewOpts); - var selOpts = Lib.extendFlat({}, matrixOpts, scene.selectedOptions, viewOpts); - scene.matrix.update(unselOpts, selOpts); - needsBaseUpdate = false; - } - } else { - stash.xpx = stash.ypx = null; - } - - if(needsBaseUpdate) { - var opts = Lib.extendFlat({}, matrixOpts, viewOpts); - scene.matrix.update(opts, null); - } -} - -},{"../../lib":719,"../../plots/cartesian/axis_ids":770,"regl-splom":501}],1207:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -module.exports = function sceneUpdate(gd, trace) { - var fullLayout = gd._fullLayout; - var uid = trace.uid; - - // must place ref to 'scene' in fullLayout, so that: - // - it can be relinked properly on updates - // - it can be destroyed properly when needed - var splomScenes = fullLayout._splomScenes; - if(!splomScenes) splomScenes = fullLayout._splomScenes = {}; - - var reset = {dirty: true}; - - var first = { - matrix: false, - selectBatch: [], - unselectBatch: [] - }; - - var scene = splomScenes[trace.uid]; - - if(!scene) { - scene = splomScenes[uid] = Lib.extendFlat({}, reset, first); - - scene.draw = function draw() { - if(scene.matrix && scene.matrix.draw) { - if(scene.selectBatch.length || scene.unselectBatch.length) { - scene.matrix.draw(scene.unselectBatch, scene.selectBatch); - } else { - scene.matrix.draw(); - } - } - - scene.dirty = false; - }; - - // remove scene resources - scene.destroy = function destroy() { - if(scene.matrix && scene.matrix.destroy) { - scene.matrix.destroy(); - } - scene.matrixOptions = null; - scene.selectBatch = null; - scene.unselectBatch = null; - scene = null; - }; - } - - // In case if we have scene from the last calc - reset data - if(!scene.dirty) { - Lib.extendFlat(scene, reset); - } - - return scene; -}; - -},{"../../lib":719}],1208:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var subTypes = _dereq_('../scatter/subtypes'); -var helpers = _dereq_('./helpers'); - -module.exports = function select(searchInfo, selectionTester) { - var cd = searchInfo.cd; - var trace = cd[0].trace; - var stash = cd[0].t; - var scene = searchInfo.scene; - var cdata = scene.matrixOptions.cdata; - var xa = searchInfo.xaxis; - var ya = searchInfo.yaxis; - var selection = []; - - if(!scene) return selection; - - var hasOnlyLines = (!subTypes.hasMarkers(trace) && !subTypes.hasText(trace)); - if(trace.visible !== true || hasOnlyLines) return selection; - - var xi = helpers.getDimIndex(trace, xa); - var yi = helpers.getDimIndex(trace, ya); - if(xi === false || yi === false) return selection; - - var xpx = stash.xpx[xi]; - var ypx = stash.ypx[yi]; - var x = cdata[xi]; - var y = cdata[yi]; - var els = []; - var unels = []; - - // degenerate polygon does not enable selection - // filter out points by visible scatter ones - if(selectionTester !== false && !selectionTester.degenerate) { - for(var i = 0; i < x.length; i++) { - if(selectionTester.contains([xpx[i], ypx[i]], null, i, searchInfo)) { - els.push(i); - selection.push({ - pointNumber: i, - x: x[i], - y: y[i] - }); - } else { - unels.push(i); - } - } - } - - var matrixOpts = scene.matrixOptions; - - if(!els.length && !unels.length) { - scene.matrix.update(matrixOpts, null); - } else if(!scene.selectBatch.length && !scene.unselectBatch.length) { - scene.matrix.update( - scene.unselectedOptions, - Lib.extendFlat({}, matrixOpts, scene.selectedOptions, scene.viewOpts) - ); - } - - scene.selectBatch = els; - scene.unselectBatch = unels; - - return selection; -}; - -},{"../../lib":719,"../scatter/subtypes":1135,"./helpers":1203}],1209:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var mesh3dAttrs = _dereq_('../mesh3d/attributes'); -var baseAttrs = _dereq_('../../plots/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -var attrs = { - x: { - valType: 'data_array', - - editType: 'calc+clearAxisTypes', - - }, - y: { - valType: 'data_array', - - editType: 'calc+clearAxisTypes', - - }, - z: { - valType: 'data_array', - - editType: 'calc+clearAxisTypes', - - }, - - u: { - valType: 'data_array', - editType: 'calc', - - }, - v: { - valType: 'data_array', - editType: 'calc', - - }, - w: { - valType: 'data_array', - editType: 'calc', - - }, - - starts: { - x: { - valType: 'data_array', - editType: 'calc', - - }, - y: { - valType: 'data_array', - editType: 'calc', - - }, - z: { - valType: 'data_array', - editType: 'calc', - - }, - editType: 'calc' - }, - - maxdisplayed: { - valType: 'integer', - min: 0, - dflt: 1000, - - editType: 'calc', - - }, - - // TODO - // - // Should add 'absolute' (like cone traces have), but currently gl-streamtube3d's - // `absoluteTubeSize` doesn't behave well enough for our needs. - // - // 'fixed' would be a nice addition to plot stream 'lines', see - // https://github.com/plotly/plotly.js/commit/812be20750e21e0a1831975001c248d365850f73#r29129877 - // - // sizemode: { - // valType: 'enumerated', - // values: ['scaled', 'absolute', 'fixed'], - // dflt: 'scaled', - // - // editType: 'calc', - // - // }, - - sizeref: { - valType: 'number', - - editType: 'calc', - min: 0, - dflt: 1, - - }, - - text: { - valType: 'string', - - dflt: '', - editType: 'calc', - - }, - hovertext: { - valType: 'string', - - dflt: '', - editType: 'calc', - - }, - hovertemplate: hovertemplateAttrs({editType: 'calc'}, { - keys: [ - 'tubex', 'tubey', 'tubez', - 'tubeu', 'tubev', 'tubew', - 'norm', 'divergence' - ] - }) -}; - -extendFlat(attrs, colorScaleAttrs('', { - colorAttr: 'u/v/w norm', - showScaleDflt: true, - editTypeOverride: 'calc' -})); - -var fromMesh3d = ['opacity', 'lightposition', 'lighting']; -fromMesh3d.forEach(function(k) { - attrs[k] = mesh3dAttrs[k]; -}); - -attrs.hoverinfo = extendFlat({}, baseAttrs.hoverinfo, { - editType: 'calc', - flags: ['x', 'y', 'z', 'u', 'v', 'w', 'norm', 'divergence', 'text', 'name'], - dflt: 'x+y+z+norm+text+name' -}); - -attrs.transforms = undefined; - -module.exports = attrs; - -},{"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../mesh3d/attributes":1053}],1210:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); - -module.exports = function calc(gd, trace) { - var i; - - var u = trace.u; - var v = trace.v; - var w = trace.w; - var x = trace.x; - var y = trace.y; - var z = trace.z; - var len = Math.min(x.length, y.length, z.length, u.length, v.length, w.length); - - var slen = 0; - var startx, starty, startz; - if(trace.starts) { - startx = trace.starts.x || []; - starty = trace.starts.y || []; - startz = trace.starts.z || []; - slen = Math.min(startx.length, starty.length, startz.length); - } - - var normMax = 0; - var normMin = Infinity; - - for(i = 0; i < len; i++) { - var uu = u[i]; - var vv = v[i]; - var ww = w[i]; - var norm = Math.sqrt(uu * uu + vv * vv + ww * ww); - - normMax = Math.max(normMax, norm); - normMin = Math.min(normMin, norm); - } - - colorscaleCalc(gd, trace, { - vals: [normMin, normMax], - containerStr: '', - cLetter: 'c' - }); - - var xMax = -Infinity; - var xMin = Infinity; - var yMax = -Infinity; - var yMin = Infinity; - var zMax = -Infinity; - var zMin = Infinity; - - for(i = 0; i < len; i++) { - var xx = x[i]; - xMax = Math.max(xMax, xx); - xMin = Math.min(xMin, xx); - - var yy = y[i]; - yMax = Math.max(yMax, yy); - yMin = Math.min(yMin, yy); - - var zz = z[i]; - zMax = Math.max(zMax, zz); - zMin = Math.min(zMin, zz); - } - for(i = 0; i < slen; i++) { - var sx = startx[i]; - xMax = Math.max(xMax, sx); - xMin = Math.min(xMin, sx); - - var sy = starty[i]; - yMax = Math.max(yMax, sy); - yMin = Math.min(yMin, sy); - - var sz = startz[i]; - zMax = Math.max(zMax, sz); - zMin = Math.min(zMin, sz); - } - - trace._len = len; - trace._slen = slen; - trace._normMax = normMax; - trace._xbnds = [xMin, xMax]; - trace._ybnds = [yMin, yMax]; - trace._zbnds = [zMin, zMax]; -}; - -},{"../../components/colorscale/calc":601}],1211:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var tube2mesh = _dereq_('gl-streamtube3d'); -var createTubeMesh = tube2mesh.createTubeMesh; - -var Lib = _dereq_('../../lib'); -var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; -var extractOpts = _dereq_('../../components/colorscale').extractOpts; -var zip3 = _dereq_('../../plots/gl3d/zip3'); - -var axisName2scaleIndex = {xaxis: 0, yaxis: 1, zaxis: 2}; - -function Streamtube(scene, uid) { - this.scene = scene; - this.uid = uid; - this.mesh = null; - this.data = null; -} - -var proto = Streamtube.prototype; - -proto.handlePick = function(selection) { - var sceneLayout = this.scene.fullSceneLayout; - var dataScale = this.scene.dataScale; - - function fromDataScale(v, axisName) { - var ax = sceneLayout[axisName]; - var scale = dataScale[axisName2scaleIndex[axisName]]; - return ax.l2c(v) / scale; - } - - if(selection.object === this.mesh) { - var pos = selection.data.position; - var uvx = selection.data.velocity; - - selection.traceCoordinate = [ - fromDataScale(pos[0], 'xaxis'), - fromDataScale(pos[1], 'yaxis'), - fromDataScale(pos[2], 'zaxis'), - - fromDataScale(uvx[0], 'xaxis'), - fromDataScale(uvx[1], 'yaxis'), - fromDataScale(uvx[2], 'zaxis'), - - // u/v/w norm - selection.data.intensity * this.data._normMax, - // divergence - selection.data.divergence - ]; - - selection.textLabel = this.data.hovertext || this.data.text; - - return true; - } -}; - -function distinctVals(col) { - return Lib.distinctVals(col).vals; -} - -function getDfltStartingPositions(vec) { - var len = vec.length; - var s; - - if(len > 2) { - s = vec.slice(1, len - 1); - } else if(len === 2) { - s = [(vec[0] + vec[1]) / 2]; - } else { - s = vec; - } - return s; -} - -function getBoundPads(vec) { - var len = vec.length; - if(len === 1) { - return [0.5, 0.5]; - } else { - return [vec[1] - vec[0], vec[len - 1] - vec[len - 2]]; - } -} - -function convert(scene, trace) { - var sceneLayout = scene.fullSceneLayout; - var dataScale = scene.dataScale; - var len = trace._len; - var tubeOpts = {}; - - function toDataCoords(arr, axisName) { - var ax = sceneLayout[axisName]; - var scale = dataScale[axisName2scaleIndex[axisName]]; - return Lib.simpleMap(arr, function(v) { return ax.d2l(v) * scale; }); - } - - tubeOpts.vectors = zip3( - toDataCoords(trace.u, 'xaxis'), - toDataCoords(trace.v, 'yaxis'), - toDataCoords(trace.w, 'zaxis'), - len - ); - - var valsx = distinctVals(trace.x.slice(0, len)); - var valsy = distinctVals(trace.y.slice(0, len)); - var valsz = distinctVals(trace.z.slice(0, len)); - - // Over-specified mesh case, this would error in tube2mesh - if(valsx.length * valsy.length * valsz.length > len) { - return {positions: [], cells: []}; - } - - var meshx = toDataCoords(valsx, 'xaxis'); - var meshy = toDataCoords(valsy, 'yaxis'); - var meshz = toDataCoords(valsz, 'zaxis'); - - tubeOpts.meshgrid = [meshx, meshy, meshz]; - - if(trace.starts) { - var slen = trace._slen; - tubeOpts.startingPositions = zip3( - toDataCoords(trace.starts.x.slice(0, slen), 'xaxis'), - toDataCoords(trace.starts.y.slice(0, slen), 'yaxis'), - toDataCoords(trace.starts.z.slice(0, slen), 'zaxis') - ); - } else { - // Default starting positions: - // - // if len>2, cut xz plane at min-y, - // takes all x/y/z pts on that plane except those on the edges - // to generate "well-defined" tubes, - // - // if len=2, take position halfway between two the pts, - // - // if len=1, take that pt - var sy0 = meshy[0]; - var sx = getDfltStartingPositions(meshx); - var sz = getDfltStartingPositions(meshz); - var startingPositions = new Array(sx.length * sz.length); - var m = 0; - - for(var i = 0; i < sx.length; i++) { - for(var k = 0; k < sz.length; k++) { - startingPositions[m++] = [sx[i], sy0, sz[k]]; - } - } - tubeOpts.startingPositions = startingPositions; - } - - tubeOpts.colormap = parseColorScale(trace); - tubeOpts.tubeSize = trace.sizeref; - tubeOpts.maxLength = trace.maxdisplayed; - - // add some padding around the bounds - // to e.g. allow tubes starting from a slice of the x/y/z mesh - // to go beyond bounds a little bit w/o getting clipped - var xbnds = toDataCoords(trace._xbnds, 'xaxis'); - var ybnds = toDataCoords(trace._ybnds, 'yaxis'); - var zbnds = toDataCoords(trace._zbnds, 'zaxis'); - var xpads = getBoundPads(meshx); - var ypads = getBoundPads(meshy); - var zpads = getBoundPads(meshz); - - var bounds = [ - [xbnds[0] - xpads[0], ybnds[0] - ypads[0], zbnds[0] - zpads[0]], - [xbnds[1] + xpads[1], ybnds[1] + ypads[1], zbnds[1] + zpads[1]] - ]; - - var meshData = tube2mesh(tubeOpts, bounds); - - // N.B. cmin/cmax correspond to the min/max vector norm - // in the u/v/w arrays, which in general is NOT equal to max - // intensity that colors the tubes. - var cOpts = extractOpts(trace); - meshData.vertexIntensityBounds = [cOpts.min / trace._normMax, cOpts.max / trace._normMax]; - - // pass gl-mesh3d lighting attributes - var lp = trace.lightposition; - meshData.lightPosition = [lp.x, lp.y, lp.z]; - meshData.ambient = trace.lighting.ambient; - meshData.diffuse = trace.lighting.diffuse; - meshData.specular = trace.lighting.specular; - meshData.roughness = trace.lighting.roughness; - meshData.fresnel = trace.lighting.fresnel; - meshData.opacity = trace.opacity; - - // stash autorange pad value - trace._pad = meshData.tubeScale * trace.sizeref * 2; - - return meshData; -} - -proto.update = function(data) { - this.data = data; - - var meshData = convert(this.scene, data); - this.mesh.update(meshData); -}; - -proto.dispose = function() { - this.scene.glplot.remove(this.mesh); - this.mesh.dispose(); -}; - -function createStreamtubeTrace(scene, data) { - var gl = scene.glplot.gl; - - var meshData = convert(scene, data); - var mesh = createTubeMesh(gl, meshData); - - var streamtube = new Streamtube(scene, data.uid); - streamtube.mesh = mesh; - streamtube.data = data; - mesh._trace = streamtube; - - scene.glplot.add(mesh); - - return streamtube; -} - -module.exports = createStreamtubeTrace; - -},{"../../components/colorscale":605,"../../lib":719,"../../lib/gl_format_color":716,"../../plots/gl3d/zip3":818,"gl-streamtube3d":313}],1212:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var u = coerce('u'); - var v = coerce('v'); - var w = coerce('w'); - - var x = coerce('x'); - var y = coerce('y'); - var z = coerce('z'); - - if( - !u || !u.length || !v || !v.length || !w || !w.length || - !x || !x.length || !y || !y.length || !z || !z.length - ) { - traceOut.visible = false; - return; - } - - coerce('starts.x'); - coerce('starts.y'); - coerce('starts.z'); - - coerce('maxdisplayed'); - coerce('sizeref'); - - coerce('lighting.ambient'); - coerce('lighting.diffuse'); - coerce('lighting.specular'); - coerce('lighting.roughness'); - coerce('lighting.fresnel'); - coerce('lightposition.x'); - coerce('lightposition.y'); - coerce('lightposition.z'); - - colorscaleDefaults(traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'}); - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - // disable 1D transforms (for now) - // x/y/z and u/v/w have matching lengths, - // but they don't have to match with starts.(x|y|z) - traceOut._length = null; -}; - -},{"../../components/colorscale/defaults":603,"../../lib":719,"./attributes":1209}],1213:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'streamtube', - basePlotModule: _dereq_('../../plots/gl3d'), - categories: ['gl3d'], - - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: { - min: 'cmin', - max: 'cmax' - }, - calc: _dereq_('./calc'), - plot: _dereq_('./convert'), - eventData: function(out, pt) { - out.tubex = out.x; - out.tubey = out.y; - out.tubez = out.z; - - out.tubeu = pt.traceCoordinate[3]; - out.tubev = pt.traceCoordinate[4]; - out.tubew = pt.traceCoordinate[5]; - - out.norm = pt.traceCoordinate[6]; - out.divergence = pt.traceCoordinate[7]; - - // Does not correspond to input x/y/z, so delete them - delete out.x; - delete out.y; - delete out.z; - - return out; - }, - - meta: { - - } -}; - -},{"../../plots/gl3d":807,"./attributes":1209,"./calc":1210,"./convert":1211,"./defaults":1212}],1214:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var plotAttrs = _dereq_('../../plots/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var domainAttrs = _dereq_('../../plots/domain').attributes; -var pieAtts = _dereq_('../pie/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = { - labels: { - valType: 'data_array', - editType: 'calc', - - }, - parents: { - valType: 'data_array', - editType: 'calc', - - }, - - values: { - valType: 'data_array', - editType: 'calc', - - }, - branchvalues: { - valType: 'enumerated', - values: ['remainder', 'total'], - dflt: 'remainder', - editType: 'calc', - - - }, - - level: { - valType: 'any', - editType: 'plot', - anim: true, - - - }, - maxdepth: { - valType: 'integer', - editType: 'plot', - - dflt: -1, - - }, - - marker: { - colors: { - valType: 'data_array', - editType: 'calc', - - }, - - // colorinheritance: { - // valType: 'enumerated', - // values: ['per-branch', 'per-label', false] - // }, - - line: { - color: extendFlat({}, pieAtts.marker.line.color, { - dflt: null, - - }), - width: extendFlat({}, pieAtts.marker.line.width, {dflt: 1}), - editType: 'calc' - }, - editType: 'calc' - }, - - leaf: { - opacity: { - valType: 'number', - editType: 'style', - - min: 0, - max: 1, - dflt: 0.7, - - }, - editType: 'plot' - }, - - text: pieAtts.text, - textinfo: extendFlat({}, pieAtts.textinfo, { - editType: 'plot', - flags: ['label', 'text', 'value'] - }), - textfont: pieAtts.textfont, - - hovertext: pieAtts.hovertext, - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['label', 'text', 'value', 'name'] - }), - hovertemplate: hovertemplateAttrs(), - - insidetextfont: pieAtts.insidetextfont, - outsidetextfont: pieAtts.outsidetextfont, - - domain: domainAttrs({name: 'sunburst', trace: true, editType: 'calc'}) -}; - -},{"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../../plots/domain":792,"../pie/attributes":1086}],1215:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; - -var name = exports.name = 'sunburst'; - -exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) { - var _module = Registry.getModule(name); - var cdmodule = getModuleCalcData(gd.calcdata, _module)[0]; - _module.plot(gd, cdmodule, transitionOpts, makeOnCompleteCallback); -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var had = (oldFullLayout._has && oldFullLayout._has(name)); - var has = (newFullLayout._has && newFullLayout._has(name)); - - if(had && !has) { - oldFullLayout._sunburstlayer.selectAll('g.trace').remove(); - } -}; - -},{"../../plots/get_data":802,"../../registry":847}],1216:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3Hierarchy = _dereq_('d3-hierarchy'); -var isNumeric = _dereq_('fast-isnumeric'); - -var Lib = _dereq_('../../lib'); -var makePullColorFn = _dereq_('../pie/calc').makePullColorFn; -var generateExtendedColors = _dereq_('../pie/calc').generateExtendedColors; - -var isArrayOrTypedArray = Lib.isArrayOrTypedArray; - -var sunburstExtendedColorWays = {}; - -exports.calc = function(gd, trace) { - var fullLayout = gd._fullLayout; - var ids = trace.ids; - var hasIds = isArrayOrTypedArray(ids); - var labels = trace.labels; - var parents = trace.parents; - var vals = trace.values; - var hasVals = isArrayOrTypedArray(vals); - var cd = []; - - var parent2children = {}; - var refs = {}; - var addToLookup = function(parent, v) { - if(parent2children[parent]) parent2children[parent].push(v); - else parent2children[parent] = [v]; - refs[v] = 1; - }; - - // treat number `0` as valid - var isValidKey = function(k) { - return k || typeof k === 'number'; - }; - - var isValidVal = function(i) { - return !hasVals || (isNumeric(vals[i]) && vals[i] >= 0); - }; - - var len; - var isValid; - var getId; - - if(hasIds) { - len = Math.min(ids.length, parents.length); - isValid = function(i) { return isValidKey(ids[i]) && isValidVal(i); }; - getId = function(i) { return String(ids[i]); }; - } else { - len = Math.min(labels.length, parents.length); - isValid = function(i) { return isValidKey(labels[i]) && isValidVal(i); }; - // TODO We could allow some label / parent duplication - // - // From AJ: - // It would work OK for one level - // (multiple rows with the same name and different parents - - // or even the same parent) but if that name is then used as a parent - // which one is it? - getId = function(i) { return String(labels[i]); }; - } - - if(hasVals) len = Math.min(len, vals.length); - - for(var i = 0; i < len; i++) { - if(isValid(i)) { - var id = getId(i); - var pid = isValidKey(parents[i]) ? String(parents[i]) : ''; - - var cdi = { - i: i, - id: id, - pid: pid, - label: isValidKey(labels[i]) ? String(labels[i]) : '' - }; - - if(hasVals) cdi.v = +vals[i]; - cd.push(cdi); - addToLookup(pid, id); - } - } - - if(!parent2children['']) { - var impliedRoots = []; - var k; - for(k in parent2children) { - if(!refs[k]) { - impliedRoots.push(k); - } - } - - // if an `id` has no ref in the `parents` array, - // take it as being the root node - - if(impliedRoots.length === 1) { - k = impliedRoots[0]; - cd.unshift({ - id: k, - pid: '', - label: k - }); - } else { - return Lib.warn('Multiple implied roots, cannot build sunburst hierarchy.'); - } - } else if(parent2children[''].length > 1) { - var dummyId = Lib.randstr(); - - // if multiple rows linked to the root node, - // add dummy "root of roots" node to make d3 build the hierarchy successfully - - for(var j = 0; j < cd.length; j++) { - if(cd[j].pid === '') { - cd[j].pid = dummyId; - } - } - - cd.unshift({ - hasMultipleRoots: true, - id: dummyId, - pid: '' - }); - } - - // TODO might be better to replace stratify() with our own algorithm - var root; - try { - root = d3Hierarchy.stratify() - .id(function(d) { return d.id; }) - .parentId(function(d) { return d.pid; })(cd); - } catch(e) { - return Lib.warn('Failed to build sunburst hierarchy. Error: ' + e.message); - } - - var hierarchy = d3Hierarchy.hierarchy(root); - var failed = false; - - if(hasVals) { - switch(trace.branchvalues) { - case 'remainder': - hierarchy.sum(function(d) { return d.data.v; }); - break; - case 'total': - hierarchy.each(function(d) { - var v = d.data.data.v; - - if(d.children) { - var partialSum = d.children.reduce(function(a, c) { - return a + c.data.data.v; - }, 0); - if(v < partialSum) { - failed = true; - return Lib.warn([ - 'Total value for node', d.data.data.id, - 'is smaller than the sum of its children.' - ].join(' ')); - } - } - - d.value = v; - }); - break; - } - } else { - hierarchy.count(); - } - - if(failed) return; - - // TODO add way to sort by height also? - hierarchy.sort(function(a, b) { return b.value - a.value; }); - - var colors = trace.marker.colors || []; - var pullColor = makePullColorFn(fullLayout._sunburstcolormap); - - // TODO keep track of 'root-children' (i.e. branch) for hover info etc. - - hierarchy.each(function(d) { - var cdi = d.data.data; - var id = cdi.id; - // N.B. this mutates items in `cd` - cdi.color = pullColor(colors[cdi.i], id); - }); - - cd[0].hierarchy = hierarchy; - - return cd; -}; - -/* - * `calc` filled in (and collated) explicit colors. - * Now we need to propagate these explicit colors to other traces, - * and fill in default colors. - * This is done after sorting, so we pick defaults - * in the order slices will be displayed - */ -exports.crossTraceCalc = function(gd) { - var fullLayout = gd._fullLayout; - var calcdata = gd.calcdata; - var colorWay = fullLayout.sunburstcolorway; - var colorMap = fullLayout._sunburstcolormap; - - if(fullLayout.extendsunburstcolors) { - colorWay = generateExtendedColors(colorWay, sunburstExtendedColorWays); - } - var dfltColorCount = 0; - - function pickColor(d) { - var cdi = d.data.data; - var id = cdi.id; - - if(cdi.color === false) { - if(colorMap[id]) { - // have we seen this label and assigned a color to it in a previous trace? - cdi.color = colorMap[id]; - } else if(d.parent) { - if(d.parent.parent) { - // from third-level on, inherit from parent - cdi.color = d.parent.data.data.color; - } else { - // pick new color for second level - colorMap[id] = cdi.color = colorWay[dfltColorCount % colorWay.length]; - dfltColorCount++; - } - } else { - // root gets no coloring by default - cdi.color = 'rgba(0,0,0,0)'; - } - } - } - - for(var i = 0; i < calcdata.length; i++) { - var cd = calcdata[i]; - var cd0 = cd[0]; - if(cd0.trace.type === 'sunburst' && cd0.hierarchy) { - cd0.hierarchy.each(pickColor); - } - } -}; - -},{"../../lib":719,"../pie/calc":1088,"d3-hierarchy":157,"fast-isnumeric":225}],1217:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - CLICK_TRANSITION_TIME: 750, - CLICK_TRANSITION_EASING: 'linear' -}; - -},{}],1218:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attributes = _dereq_('./attributes'); -var handleDomainDefaults = _dereq_('../../plots/domain').defaults; -var handleText = _dereq_('../bar/defaults').handleText; - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var labels = coerce('labels'); - var parents = coerce('parents'); - - if(!labels || !labels.length || !parents || !parents.length) { - traceOut.visible = false; - return; - } - - var vals = coerce('values'); - if(vals && vals.length) coerce('branchvalues'); - - coerce('level'); - coerce('maxdepth'); - - var lineWidth = coerce('marker.line.width'); - if(lineWidth) coerce('marker.line.color', layout.paper_bgcolor); - - coerce('marker.colors'); - - coerce('leaf.opacity'); - - var text = coerce('text'); - coerce('textinfo', Array.isArray(text) ? 'text+label' : 'label'); - - coerce('hovertext'); - coerce('hovertemplate'); - - var textposition = 'auto'; - handleText(traceIn, traceOut, layout, coerce, textposition, { - moduleHasSelected: false, - moduleHasUnselected: false, - moduleHasConstrain: false, - moduleHasCliponaxis: false, - moduleHasTextangle: false, - moduleHasInsideanchor: false - }); - - handleDomainDefaults(traceOut, layout, coerce); - - // do not support transforms for now - traceOut._length = null; -}; - -},{"../../lib":719,"../../plots/domain":792,"../bar/defaults":861,"./attributes":1214}],1219:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - moduleType: 'trace', - name: 'sunburst', - basePlotModule: _dereq_('./base_plot'), - categories: [], - animatable: true, - - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('./layout_attributes'), - supplyDefaults: _dereq_('./defaults'), - supplyLayoutDefaults: _dereq_('./layout_defaults'), - - calc: _dereq_('./calc').calc, - crossTraceCalc: _dereq_('./calc').crossTraceCalc, - - plot: _dereq_('./plot'), - style: _dereq_('./style').style, - - meta: { - - } -}; - -},{"./attributes":1214,"./base_plot":1215,"./calc":1216,"./defaults":1218,"./layout_attributes":1220,"./layout_defaults":1221,"./plot":1222,"./style":1223}],1220:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - sunburstcolorway: { - valType: 'colorlist', - - editType: 'calc', - - }, - extendsunburstcolors: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - } -}; - -},{}],1221:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var layoutAttributes = _dereq_('./layout_attributes'); - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - coerce('sunburstcolorway', layoutOut.colorway); - coerce('extendsunburstcolors'); -}; - -},{"../../lib":719,"./layout_attributes":1220}],1222:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var d3Hierarchy = _dereq_('d3-hierarchy'); - -var Registry = _dereq_('../../registry'); -var Fx = _dereq_('../../components/fx'); -var Color = _dereq_('../../components/color'); -var Drawing = _dereq_('../../components/drawing'); -var Lib = _dereq_('../../lib'); -var Events = _dereq_('../../lib/events'); -var svgTextUtils = _dereq_('../../lib/svg_text_utils'); -var setCursor = _dereq_('../../lib/setcursor'); -var appendArrayPointValue = _dereq_('../../components/fx/helpers').appendArrayPointValue; - -var transformInsideText = _dereq_('../pie/plot').transformInsideText; -var formatPieValue = _dereq_('../pie/helpers').formatPieValue; -var styleOne = _dereq_('./style').styleOne; - -var constants = _dereq_('./constants'); - -module.exports = function(gd, cdmodule, transitionOpts, makeOnCompleteCallback) { - var fullLayout = gd._fullLayout; - var layer = fullLayout._sunburstlayer; - var join, onComplete; - - // If transition config is provided, then it is only a partial replot and traces not - // updated are removed. - var isFullReplot = !transitionOpts; - var hasTransition = transitionOpts && transitionOpts.duration > 0; - - join = layer.selectAll('g.trace.sunburst') - .data(cdmodule, function(cd) { return cd[0].trace.uid; }); - - // using same 'stroke-linejoin' as pie traces - join.enter().append('g') - .classed('trace', true) - .classed('sunburst', true) - .attr('stroke-linejoin', 'round'); - - join.order(); - - if(hasTransition) { - if(makeOnCompleteCallback) { - // If it was passed a callback to register completion, make a callback. If - // this is created, then it must be executed on completion, otherwise the - // pos-transition redraw will not execute: - onComplete = makeOnCompleteCallback(); - } - - var transition = d3.transition() - .duration(transitionOpts.duration) - .ease(transitionOpts.easing) - .each('end', function() { onComplete && onComplete(); }) - .each('interrupt', function() { onComplete && onComplete(); }); - - transition.each(function() { - // Must run the selection again since otherwise enters/updates get grouped together - // and these get executed out of order. Except we need them in order! - layer.selectAll('g.trace').each(function(cd) { - plotOne(gd, cd, this, transitionOpts); - }); - }); - } else { - join.each(function(cd) { - plotOne(gd, cd, this, transitionOpts); - }); - } - - if(isFullReplot) { - join.exit().remove(); - } -}; - -function plotOne(gd, cd, element, transitionOpts) { - var fullLayout = gd._fullLayout; - // We could optimize hasTransition per trace, - // as sunburst has no cross-trace logic! - var hasTransition = transitionOpts && transitionOpts.duration > 0; - - var gTrace = d3.select(element); - var slices = gTrace.selectAll('g.slice'); - - var cd0 = cd[0]; - var trace = cd0.trace; - var hierarchy = cd0.hierarchy; - var entry = findEntryWithLevel(hierarchy, trace.level); - var maxDepth = trace.maxdepth >= 0 ? trace.maxdepth : Infinity; - - var gs = fullLayout._size; - var domain = trace.domain; - var vpw = gs.w * (domain.x[1] - domain.x[0]); - var vph = gs.h * (domain.y[1] - domain.y[0]); - var rMax = 0.5 * Math.min(vpw, vph); - var cx = cd0.cx = gs.l + gs.w * (domain.x[1] + domain.x[0]) / 2; - var cy = cd0.cy = gs.t + gs.h * (1 - domain.y[0]) - vph / 2; - - if(!entry) { - return slices.remove(); - } - - // previous root 'pt' (can be empty) - var prevEntry = null; - // stash of 'previous' position data used by tweening functions - var prevLookup = {}; - - if(hasTransition) { - // Important: do this before binding new sliceData! - slices.each(function(pt) { - prevLookup[getPtId(pt)] = { - rpx0: pt.rpx0, - rpx1: pt.rpx1, - x0: pt.x0, - x1: pt.x1, - transform: pt.transform - }; - - if(!prevEntry && isEntry(pt)) { - prevEntry = pt; - } - }); - } - - // N.B. slice data isn't the calcdata, - // grab corresponding calcdata item in sliceData[i].data.data - var sliceData = partition(entry).descendants(); - var maxHeight = entry.height + 1; - var yOffset = 0; - var cutoff = maxDepth; - - // N.B. handle multiple-root special case - if(cd0.hasMultipleRoots && isHierachyRoot(entry)) { - sliceData = sliceData.slice(1); - maxHeight -= 1; - yOffset = 1; - cutoff += 1; - } - - // filter out slices that won't show up on graph - sliceData = sliceData.filter(function(pt) { return pt.y1 <= cutoff; }); - - // partition span ('y') to sector radial px value - var maxY = Math.min(maxHeight, maxDepth); - var y2rpx = function(y) { return (y - yOffset) / maxY * rMax; }; - // (radial px value, partition angle ('x')) to px [x,y] - var rx2px = function(r, x) { return [r * Math.cos(x), -r * Math.sin(x)]; }; - // slice path generation fn - var pathSlice = function(d) { return Lib.pathAnnulus(d.rpx0, d.rpx1, d.x0, d.x1, cx, cy); }; - // slice text translate x/y - var transTextX = function(d) { return cx + d.pxmid[0] * d.transform.rCenter + (d.transform.x || 0); }; - var transTextY = function(d) { return cy + d.pxmid[1] * d.transform.rCenter + (d.transform.y || 0); }; - - slices = slices.data(sliceData, function(pt) { return getPtId(pt); }); - - slices.enter().append('g') - .classed('slice', true); - - if(hasTransition) { - slices.exit().transition() - .each(function() { - var sliceTop = d3.select(this); - - var slicePath = sliceTop.select('path.surface'); - slicePath.transition().attrTween('d', function(pt2) { - var interp = makeExitSliceInterpolator(pt2); - return function(t) { return pathSlice(interp(t)); }; - }); - - var sliceTextGroup = sliceTop.select('g.slicetext'); - sliceTextGroup.attr('opacity', 0); - }) - .remove(); - } else { - slices.exit().remove(); - } - - slices.order(); - - // next x1 (i.e. sector end angle) of previous entry - var nextX1ofPrevEntry = null; - if(hasTransition && prevEntry) { - var prevEntryId = getPtId(prevEntry); - slices.each(function(pt) { - if(nextX1ofPrevEntry === null && (getPtId(pt) === prevEntryId)) { - nextX1ofPrevEntry = pt.x1; - } - }); - } - - var updateSlices = slices; - if(hasTransition) { - updateSlices = updateSlices.transition().each('end', function() { - // N.B. gd._transitioning is (still) *true* by the time - // transition updates get hare - var sliceTop = d3.select(this); - setSliceCursor(sliceTop, gd, {isTransitioning: false}); - }); - } - - updateSlices.each(function(pt) { - var sliceTop = d3.select(this); - - var slicePath = Lib.ensureSingle(sliceTop, 'path', 'surface', function(s) { - s.style('pointer-events', 'all'); - }); - - pt.rpx0 = y2rpx(pt.y0); - pt.rpx1 = y2rpx(pt.y1); - pt.xmid = (pt.x0 + pt.x1) / 2; - pt.pxmid = rx2px(pt.rpx1, pt.xmid); - pt.midangle = -(pt.xmid - Math.PI / 2); - pt.halfangle = 0.5 * Math.min(Lib.angleDelta(pt.x0, pt.x1) || Math.PI, Math.PI); - pt.ring = 1 - (pt.rpx0 / pt.rpx1); - pt.rInscribed = getInscribedRadiusFraction(pt, trace); - - if(hasTransition) { - slicePath.transition().attrTween('d', function(pt2) { - var interp = makeUpdateSliceIntepolator(pt2); - return function(t) { return pathSlice(interp(t)); }; - }); - } else { - slicePath.attr('d', pathSlice); - } - - sliceTop - .call(attachFxHandlers, gd, cd) - .call(setSliceCursor, gd, {isTransitioning: gd._transitioning}); - - slicePath.call(styleOne, pt, trace); - - var sliceTextGroup = Lib.ensureSingle(sliceTop, 'g', 'slicetext'); - var sliceText = Lib.ensureSingle(sliceTextGroup, 'text', '', function(s) { - // prohibit tex interpretation until we can handle - // tex and regular text together - s.attr('data-notex', 1); - }); - - sliceText.text(formatSliceLabel(pt, trace, fullLayout)) - .classed('slicetext', true) - .attr('text-anchor', 'middle') - .call(Drawing.font, isHierachyRoot(pt) ? - determineOutsideTextFont(trace, pt, fullLayout.font) : - determineInsideTextFont(trace, pt, fullLayout.font)) - .call(svgTextUtils.convertToTspans, gd); - - // position the text relative to the slice - var textBB = Drawing.bBox(sliceText.node()); - pt.transform = transformInsideText(textBB, pt, cd0); - pt.translateX = transTextX(pt); - pt.translateY = transTextY(pt); - - var strTransform = function(d, textBB) { - return 'translate(' + d.translateX + ',' + d.translateY + ')' + - (d.transform.scale < 1 ? ('scale(' + d.transform.scale + ')') : '') + - (d.transform.rotate ? ('rotate(' + d.transform.rotate + ')') : '') + - 'translate(' + - (-(textBB.left + textBB.right) / 2) + ',' + - (-(textBB.top + textBB.bottom) / 2) + - ')'; - }; - - if(hasTransition) { - sliceText.transition().attrTween('transform', function(pt2) { - var interp = makeUpdateTextInterpolar(pt2); - return function(t) { return strTransform(interp(t), textBB); }; - }); - } else { - sliceText.attr('transform', strTransform(pt, textBB)); - } - }); - - function makeExitSliceInterpolator(pt) { - var id = getPtId(pt); - var prev = prevLookup[id]; - var entryPrev = prevLookup[getPtId(entry)]; - var next; - - if(entryPrev) { - var a = pt.x1 > entryPrev.x1 ? 2 * Math.PI : 0; - // if pt to remove: - // - if 'below' where the root-node used to be: shrink it radially inward - // - otherwise, collapse it clockwise or counterclockwise which ever is shortest to theta=0 - next = pt.rpx1 < entryPrev.rpx1 ? {rpx0: 0, rpx1: 0} : {x0: a, x1: a}; - } else { - // this happens when maxdepth is set, when leaves must - // be removed and the rootPt is new (i.e. does not have a 'prev' object) - var parent; - var parentId = getPtId(pt.parent); - slices.each(function(pt2) { - if(getPtId(pt2) === parentId) { - return parent = pt2; - } - }); - var parentChildren = parent.children; - var ci; - parentChildren.forEach(function(pt2, i) { - if(getPtId(pt2) === id) { - return ci = i; - } - }); - var n = parentChildren.length; - var interp = d3.interpolate(parent.x0, parent.x1); - next = { - rpx0: rMax, rpx1: rMax, - x0: interp(ci / n), x1: interp((ci + 1) / n) - }; - } - - return d3.interpolate(prev, next); - } - - function makeUpdateSliceIntepolator(pt) { - var prev0 = prevLookup[getPtId(pt)]; - var prev; - var next = {x0: pt.x0, x1: pt.x1, rpx0: pt.rpx0, rpx1: pt.rpx1}; - - if(prev0) { - // if pt already on graph, this is easy - prev = prev0; - } else { - // for new pts: - if(prevEntry) { - // if trace was visible before - if(pt.parent) { - if(nextX1ofPrevEntry) { - // if new branch, twist it in clockwise or - // counterclockwise which ever is shorter to - // its final angle - var a = pt.x1 > nextX1ofPrevEntry ? 2 * Math.PI : 0; - prev = {x0: a, x1: a}; - } else { - // if new leaf (when maxdepth is set), - // grow it radially and angularly from - // its parent node - prev = {rpx0: rMax, rpx1: rMax}; - Lib.extendFlat(prev, interpX0X1FromParent(pt)); - } - } else { - // if new root-node, grow it radially - prev = {rpx0: 0, rpx1: 0}; - } - } else { - // start sector of new traces from theta=0 - prev = {x0: 0, x1: 0}; - } - } - - return d3.interpolate(prev, next); - } - - function makeUpdateTextInterpolar(pt) { - var prev0 = prevLookup[getPtId(pt)]; - var prev; - var transform = pt.transform; - - if(prev0) { - prev = prev0; - } else { - prev = { - rpx1: pt.rpx1, - transform: { - scale: 0, - rotate: transform.rotate, - rCenter: transform.rCenter, - x: transform.x, - y: transform.y - } - }; - - // for new pts: - if(prevEntry) { - // if trace was visible before - if(pt.parent) { - if(nextX1ofPrevEntry) { - // if new branch, twist it in clockwise or - // counterclockwise which ever is shorter to - // its final angle - var a = pt.x1 > nextX1ofPrevEntry ? 2 * Math.PI : 0; - prev.x0 = prev.x1 = a; - } else { - // if leaf - Lib.extendFlat(prev, interpX0X1FromParent(pt)); - } - } else { - // if new root-node - prev.x0 = prev.x1 = 0; - } - } else { - // on new traces - prev.x0 = prev.x1 = 0; - } - } - - var rpx1Fn = d3.interpolate(prev.rpx1, pt.rpx1); - var x0Fn = d3.interpolate(prev.x0, pt.x0); - var x1Fn = d3.interpolate(prev.x1, pt.x1); - var scaleFn = d3.interpolate(prev.transform.scale, transform.scale); - var rotateFn = d3.interpolate(prev.transform.rotate, transform.rotate); - - // smooth out start/end from entry, to try to keep text inside sector - // while keeping transition smooth - var pow = transform.rCenter === 0 ? 3 : - prev.transform.rCenter === 0 ? 1 / 3 : - 1; - var _rCenterFn = d3.interpolate(prev.transform.rCenter, transform.rCenter); - var rCenterFn = function(t) { return _rCenterFn(Math.pow(t, pow)); }; - - return function(t) { - var rpx1 = rpx1Fn(t); - var x0 = x0Fn(t); - var x1 = x1Fn(t); - var rCenter = rCenterFn(t); - - var d = { - pxmid: rx2px(rpx1, (x0 + x1) / 2), - transform: { - rCenter: rCenter, - x: transform.x, - y: transform.y - } - }; - - var out = { - rpx1: rpx1Fn(t), - translateX: transTextX(d), - translateY: transTextY(d), - transform: { - scale: scaleFn(t), - rotate: rotateFn(t), - rCenter: rCenter - } - }; - - return out; - }; - } - - function interpX0X1FromParent(pt) { - var parent = pt.parent; - var parentPrev = prevLookup[getPtId(parent)]; - var out = {}; - - if(parentPrev) { - // if parent is visible - var parentChildren = parent.children; - var ci = parentChildren.indexOf(pt); - var n = parentChildren.length; - var interp = d3.interpolate(parentPrev.x0, parentPrev.x1); - out.x0 = interp(ci / n); - out.x1 = interp(ci / n); - } else { - // w/o visible parent - // TODO !!! HOW ??? - out.x0 = out.x1 = 0; - } - - return out; - } -} - -// x[0-1] keys are angles [radians] -// y[0-1] keys are hierarchy heights [integers] -function partition(entry) { - return d3Hierarchy.partition() - .size([2 * Math.PI, entry.height + 1])(entry); -} - -function findEntryWithLevel(hierarchy, level) { - var out; - if(level) { - hierarchy.eachAfter(function(pt) { - if(getPtId(pt) === level) { - return out = pt.copy(); - } - }); - } - return out || hierarchy; -} - -function findEntryWithChild(hierarchy, childId) { - var out; - hierarchy.eachAfter(function(pt) { - var children = pt.children || []; - for(var i = 0; i < children.length; i++) { - var child = children[i]; - if(getPtId(child) === childId) { - return out = pt.copy(); - } - } - }); - return out || hierarchy; -} - -function isHierachyRoot(pt) { - var cdi = pt.data.data; - return cdi.pid === ''; -} - -function isEntry(pt) { - return !pt.parent; -} - -function isLeaf(pt) { - return !pt.children; -} - -function getPtId(pt) { - var cdi = pt.data.data; - return cdi.id; -} - -function setSliceCursor(sliceTop, gd, opts) { - var pt = sliceTop.datum(); - var isTransitioning = (opts || {}).isTransitioning; - setCursor(sliceTop, (isTransitioning || isLeaf(pt) || isHierachyRoot(pt)) ? null : 'pointer'); -} - -function attachFxHandlers(sliceTop, gd, cd) { - var cd0 = cd[0]; - var trace = cd0.trace; - - // hover state vars - // have we drawn a hover label, so it should be cleared later - if(!('_hasHoverLabel' in trace)) trace._hasHoverLabel = false; - // have we emitted a hover event, so later an unhover event should be emitted - // note that click events do not depend on this - you can still get them - // with hovermode: false or if you were earlier dragging, then clicked - // in the same slice that you moused up in - if(!('_hasHoverEvent' in trace)) trace._hasHoverEvent = false; - - sliceTop.on('mouseover', function(pt) { - var fullLayoutNow = gd._fullLayout; - - if(gd._dragging || fullLayoutNow.hovermode === false) return; - - var traceNow = gd._fullData[trace.index]; - var cdi = pt.data.data; - var ptNumber = cdi.i; - - var _cast = function(astr) { - return Lib.castOption(traceNow, ptNumber, astr); - }; - - var hovertemplate = _cast('hovertemplate'); - var hoverinfo = Fx.castHoverinfo(traceNow, fullLayoutNow, ptNumber); - var separators = fullLayoutNow.separators; - - if(hovertemplate || (hoverinfo && hoverinfo !== 'none' && hoverinfo !== 'skip')) { - var rInscribed = pt.rInscribed; - var hoverCenterX = cd0.cx + pt.pxmid[0] * (1 - rInscribed); - var hoverCenterY = cd0.cy + pt.pxmid[1] * (1 - rInscribed); - var hoverPt = {}; - var parts = []; - var thisText = []; - var hasFlag = function(flag) { return parts.indexOf(flag) !== -1; }; - - if(hoverinfo) { - parts = hoverinfo === 'all' ? - traceNow._module.attributes.hoverinfo.flags : - hoverinfo.split('+'); - } - - hoverPt.label = cdi.label; - if(hasFlag('label') && hoverPt.label) thisText.push(hoverPt.label); - - if(cdi.hasOwnProperty('v')) { - hoverPt.value = cdi.v; - hoverPt.valueLabel = formatPieValue(hoverPt.value, separators); - if(hasFlag('value')) thisText.push(hoverPt.valueLabel); - } - - hoverPt.text = _cast('hovertext') || _cast('text'); - if(hasFlag('text')) { - var tx = hoverPt.text; - if(Lib.isValidTextValue(tx)) thisText.push(tx); - } - - Fx.loneHover({ - trace: traceNow, - x0: hoverCenterX - rInscribed * pt.rpx1, - x1: hoverCenterX + rInscribed * pt.rpx1, - y: hoverCenterY, - idealAlign: pt.pxmid[0] < 0 ? 'left' : 'right', - text: thisText.join('
'), - name: (hovertemplate || hasFlag('name')) ? traceNow.name : undefined, - color: _cast('hoverlabel.bgcolor') || cdi.color, - borderColor: _cast('hoverlabel.bordercolor'), - fontFamily: _cast('hoverlabel.font.family'), - fontSize: _cast('hoverlabel.font.size'), - fontColor: _cast('hoverlabel.font.color'), - nameLength: _cast('hoverlabel.namelength'), - textAlign: _cast('hoverlabel.align'), - hovertemplate: hovertemplate, - hovertemplateLabels: hoverPt, - eventData: [makeEventData(pt, traceNow)] - }, { - container: fullLayoutNow._hoverlayer.node(), - outerContainer: fullLayoutNow._paper.node(), - gd: gd - }); - - trace._hasHoverLabel = true; - } - - trace._hasHoverEvent = true; - gd.emit('plotly_hover', { - points: [makeEventData(pt, traceNow)], - event: d3.event - }); - }); - - sliceTop.on('mouseout', function(evt) { - var fullLayoutNow = gd._fullLayout; - var traceNow = gd._fullData[trace.index]; - var pt = d3.select(this).datum(); - - if(trace._hasHoverEvent) { - evt.originalEvent = d3.event; - gd.emit('plotly_unhover', { - points: [makeEventData(pt, traceNow)], - event: d3.event - }); - trace._hasHoverEvent = false; - } - - if(trace._hasHoverLabel) { - Fx.loneUnhover(fullLayoutNow._hoverlayer.node()); - trace._hasHoverLabel = false; - } - }); - - sliceTop.on('click', function(pt) { - // TODO: this does not support right-click. If we want to support it, we - // would likely need to change pie to use dragElement instead of straight - // mapbox event binding. Or perhaps better, make a simple wrapper with the - // right mousedown, mousemove, and mouseup handlers just for a left/right click - // mapbox would use this too. - var fullLayoutNow = gd._fullLayout; - var traceNow = gd._fullData[trace.index]; - - var clickVal = Events.triggerHandler(gd, 'plotly_sunburstclick', { - points: [makeEventData(pt, traceNow)], - event: d3.event - }); - - // 'regular' click event when sunburstclick is disabled or when - // clikcin on leaves or the hierarchy root - if(clickVal === false || isLeaf(pt) || isHierachyRoot(pt)) { - if(fullLayoutNow.hovermode) { - gd._hoverdata = [makeEventData(pt, traceNow)]; - Fx.click(gd, d3.event); - } - return; - } - - // skip if triggered from dragging a nearby cartesian subplot - if(gd._dragging) return; - - // skip during transitions, to avoid potential bugs - // we could remove this check later - if(gd._transitioning) return; - - // store 'old' level in guiEdit stash, so that subsequent Plotly.react - // calls with the same uirevision can start from the same entry - Registry.call('_storeDirectGUIEdit', traceNow, fullLayoutNow._tracePreGUI[traceNow.uid], {level: traceNow.level}); - - var hierarchy = cd0.hierarchy; - var id = getPtId(pt); - var nextEntry = isEntry(pt) ? - findEntryWithChild(hierarchy, id) : - findEntryWithLevel(hierarchy, id); - - var frame = { - data: [{level: getPtId(nextEntry)}], - traces: [trace.index] - }; - - var animOpts = { - frame: { - redraw: false, - duration: constants.CLICK_TRANSITION_TIME - }, - transition: { - duration: constants.CLICK_TRANSITION_TIME, - easing: constants.CLICK_TRANSITION_EASING - }, - mode: 'immediate', - fromcurrent: true - }; - - Fx.loneUnhover(fullLayoutNow._hoverlayer.node()); - Registry.call('animate', gd, frame, animOpts); - }); -} - -function makeEventData(pt, trace) { - var cdi = pt.data.data; - - var out = { - curveNumber: trace.index, - pointNumber: cdi.i, - data: trace._input, - fullData: trace, - - // TODO more things like 'children', 'siblings', 'hierarchy? - }; - - appendArrayPointValue(out, trace, cdi.i); - - return out; -} - -function formatSliceLabel(pt, trace, fullLayout) { - var textinfo = trace.textinfo; - - if(!textinfo || textinfo === 'none') { - return ''; - } - - var cdi = pt.data.data; - var separators = fullLayout.separators; - var parts = textinfo.split('+'); - var hasFlag = function(flag) { return parts.indexOf(flag) !== -1; }; - var thisText = []; - - if(hasFlag('label') && cdi.label) thisText.push(cdi.label); - - if(cdi.hasOwnProperty('v') && hasFlag('value')) { - thisText.push(formatPieValue(cdi.v, separators)); - } - - if(hasFlag('text')) { - var tx = Lib.castOption(trace, cdi.i, 'text'); - if(Lib.isValidTextValue(tx)) thisText.push(tx); - } - - return thisText.join('
'); -} - -function determineOutsideTextFont(trace, pt, layoutFont) { - var cdi = pt.data.data; - var ptNumber = cdi.i; - - var color = Lib.castOption(trace, ptNumber, 'outsidetextfont.color') || - Lib.castOption(trace, ptNumber, 'textfont.color') || - layoutFont.color; - - var family = Lib.castOption(trace, ptNumber, 'outsidetextfont.family') || - Lib.castOption(trace, ptNumber, 'textfont.family') || - layoutFont.family; - - var size = Lib.castOption(trace, ptNumber, 'outsidetextfont.size') || - Lib.castOption(trace, ptNumber, 'textfont.size') || - layoutFont.size; - - return { - color: color, - family: family, - size: size - }; -} - -function determineInsideTextFont(trace, pt, layoutFont) { - var cdi = pt.data.data; - var ptNumber = cdi.i; - - var customColor = Lib.castOption(trace, ptNumber, 'insidetextfont.color'); - if(!customColor && trace._input.textfont) { - // Why not simply using trace.textfont? Because if not set, it - // defaults to layout.font which has a default color. But if - // textfont.color and insidetextfont.color don't supply a value, - // a contrasting color shall be used. - customColor = Lib.castOption(trace._input, ptNumber, 'textfont.color'); - } - - var family = Lib.castOption(trace, ptNumber, 'insidetextfont.family') || - Lib.castOption(trace, ptNumber, 'textfont.family') || - layoutFont.family; - - var size = Lib.castOption(trace, ptNumber, 'insidetextfont.size') || - Lib.castOption(trace, ptNumber, 'textfont.size') || - layoutFont.size; - - return { - color: customColor || Color.contrast(cdi.color), - family: family, - size: size - }; -} - -function getInscribedRadiusFraction(pt) { - if(pt.rpx0 === 0 && Lib.isFullCircle([pt.x0, pt.x1])) { - // special case of 100% with no hole - return 1; - } else { - return Math.max(0, Math.min( - 1 / (1 + 1 / Math.sin(pt.halfangle)), - pt.ring / 2 - )); - } -} - -},{"../../components/color":593,"../../components/drawing":614,"../../components/fx":632,"../../components/fx/helpers":628,"../../lib":719,"../../lib/events":709,"../../lib/setcursor":739,"../../lib/svg_text_utils":743,"../../registry":847,"../pie/helpers":1091,"../pie/plot":1095,"./constants":1217,"./style":1223,"d3":163,"d3-hierarchy":157}],1223:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Color = _dereq_('../../components/color'); -var Lib = _dereq_('../../lib'); - -function style(gd) { - gd._fullLayout._sunburstlayer.selectAll('.trace').each(function(cd) { - var gTrace = d3.select(this); - var cd0 = cd[0]; - var trace = cd0.trace; - - gTrace.style('opacity', trace.opacity); - - gTrace.selectAll('path.surface').each(function(pt) { - d3.select(this).call(styleOne, pt, trace); - }); - }); -} - -function styleOne(s, pt, trace) { - var cdi = pt.data.data; - var isLeaf = !pt.children; - var ptNumber = cdi.i; - var lineColor = Lib.castOption(trace, ptNumber, 'marker.line.color') || Color.defaultLine; - var lineWidth = Lib.castOption(trace, ptNumber, 'marker.line.width') || 0; - - s.style('stroke-width', lineWidth) - .call(Color.fill, cdi.color) - .call(Color.stroke, lineColor) - .style('opacity', isLeaf ? trace.leaf.opacity : null); -} - -module.exports = { - style: style, - styleOne: styleOne -}; - -},{"../../components/color":593,"../../lib":719,"d3":163}],1224:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Color = _dereq_('../../components/color'); -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var baseAttrs = _dereq_('../../plots/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -function makeContourProjAttr(axLetter) { - return { - valType: 'boolean', - - dflt: false, - - }; -} - -function makeContourAttr(axLetter) { - return { - show: { - valType: 'boolean', - - dflt: false, - - }, - start: { - valType: 'number', - dflt: null, - - editType: 'plot', - // impliedEdits: {'^autocontour': false}, - - }, - end: { - valType: 'number', - dflt: null, - - editType: 'plot', - // impliedEdits: {'^autocontour': false}, - - }, - size: { - valType: 'number', - dflt: null, - min: 0, - - editType: 'plot', - // impliedEdits: {'^autocontour': false}, - - }, - project: { - x: makeContourProjAttr('x'), - y: makeContourProjAttr('y'), - z: makeContourProjAttr('z') - }, - color: { - valType: 'color', - - dflt: Color.defaultLine, - - }, - usecolormap: { - valType: 'boolean', - - dflt: false, - - }, - width: { - valType: 'number', - - min: 1, - max: 16, - dflt: 2, - - }, - highlight: { - valType: 'boolean', - - dflt: true, - - }, - highlightcolor: { - valType: 'color', - - dflt: Color.defaultLine, - - }, - highlightwidth: { - valType: 'number', - - min: 1, - max: 16, - dflt: 2, - - } - }; -} - -var attrs = module.exports = overrideAll(extendFlat({ - z: { - valType: 'data_array', - - }, - x: { - valType: 'data_array', - - }, - y: { - valType: 'data_array', - - }, - - text: { - valType: 'string', - - dflt: '', - arrayOk: true, - - }, - hovertext: { - valType: 'string', - - dflt: '', - arrayOk: true, - - }, - hovertemplate: hovertemplateAttrs(), - - connectgaps: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - - surfacecolor: { - valType: 'data_array', - - }, -}, - -colorScaleAttrs('', { - colorAttr: 'z or surfacecolor', - showScaleDflt: true, - autoColorDflt: false, - editTypeOverride: 'calc' -}), { - contours: { - x: makeContourAttr('x'), - y: makeContourAttr('y'), - z: makeContourAttr('z') - }, - hidesurface: { - valType: 'boolean', - - dflt: false, - - }, - - lightposition: { - x: { - valType: 'number', - - min: -1e5, - max: 1e5, - dflt: 10, - - }, - y: { - valType: 'number', - - min: -1e5, - max: 1e5, - dflt: 1e4, - - }, - z: { - valType: 'number', - - min: -1e5, - max: 1e5, - dflt: 0, - - } - }, - - lighting: { - ambient: { - valType: 'number', - - min: 0.00, - max: 1.0, - dflt: 0.8, - - }, - diffuse: { - valType: 'number', - - min: 0.00, - max: 1.00, - dflt: 0.8, - - }, - specular: { - valType: 'number', - - min: 0.00, - max: 2.00, - dflt: 0.05, - - }, - roughness: { - valType: 'number', - - min: 0.00, - max: 1.00, - dflt: 0.5, - - }, - fresnel: { - valType: 'number', - - min: 0.00, - max: 5.00, - dflt: 0.2, - - } - }, - - opacity: { - valType: 'number', - - min: 0, - max: 1, - dflt: 1, - - }, - - _deprecated: { - zauto: extendFlat({}, colorScaleAttrs.zauto, { - - }), - zmin: extendFlat({}, colorScaleAttrs.zmin, { - - }), - zmax: extendFlat({}, colorScaleAttrs.zmax, { - - }) - }, - - hoverinfo: extendFlat({}, baseAttrs.hoverinfo) -}), 'calc', 'nested'); - -attrs.x.editType = attrs.y.editType = attrs.z.editType = 'calc+clearAxisTypes'; -attrs.transforms = undefined; - -},{"../../components/color":593,"../../components/colorscale/attributes":600,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plots/attributes":764}],1225:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var colorscaleCalc = _dereq_('../../components/colorscale/calc'); - - -// Compute auto-z and autocolorscale if applicable -module.exports = function calc(gd, trace) { - if(trace.surfacecolor) { - colorscaleCalc(gd, trace, { - vals: trace.surfacecolor, - containerStr: '', - cLetter: 'c' - }); - } else { - colorscaleCalc(gd, trace, { - vals: trace.z, - containerStr: '', - cLetter: 'c' - }); - } -}; - -},{"../../components/colorscale/calc":601}],1226:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - - -'use strict'; - -var createSurface = _dereq_('gl-surface3d'); - -var ndarray = _dereq_('ndarray'); -var homography = _dereq_('ndarray-homography'); -var fill = _dereq_('ndarray-fill'); - -var isArrayOrTypedArray = _dereq_('../../lib').isArrayOrTypedArray; -var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; -var str2RgbaArray = _dereq_('../../lib/str2rgbarray'); -var extractOpts = _dereq_('../../components/colorscale').extractOpts; - -var interp2d = _dereq_('../heatmap/interp2d'); -var findEmpties = _dereq_('../heatmap/find_empties'); - -function SurfaceTrace(scene, surface, uid) { - this.scene = scene; - this.uid = uid; - this.surface = surface; - this.data = null; - this.showContour = [false, false, false]; - this.contourStart = [null, null, null]; - this.contourEnd = [null, null, null]; - this.contourSize = [0, 0, 0]; - this.minValues = [Infinity, Infinity, Infinity]; - this.maxValues = [-Infinity, -Infinity, -Infinity]; - this.dataScaleX = 1.0; - this.dataScaleY = 1.0; - this.refineData = true; - this.objectOffset = [0, 0, 0]; -} - -var proto = SurfaceTrace.prototype; - -proto.getXat = function(a, b, calendar, axis) { - var v = ( - (!isArrayOrTypedArray(this.data.x)) ? - a : - (isArrayOrTypedArray(this.data.x[0])) ? - this.data.x[b][a] : - this.data.x[a] - ); - - return (calendar === undefined) ? v : axis.d2l(v, 0, calendar); -}; - -proto.getYat = function(a, b, calendar, axis) { - var v = ( - (!isArrayOrTypedArray(this.data.y)) ? - b : - (isArrayOrTypedArray(this.data.y[0])) ? - this.data.y[b][a] : - this.data.y[b] - ); - - return (calendar === undefined) ? v : axis.d2l(v, 0, calendar); -}; - -proto.getZat = function(a, b, calendar, axis) { - var v = this.data.z[b][a]; - - if(v === null && this.data.connectgaps && this.data._interpolatedZ) { - v = this.data._interpolatedZ[b][a]; - } - - return (calendar === undefined) ? v : axis.d2l(v, 0, calendar); -}; - -proto.handlePick = function(selection) { - if(selection.object === this.surface) { - var xRatio = (selection.data.index[0] - 1) / this.dataScaleX - 1; - var yRatio = (selection.data.index[1] - 1) / this.dataScaleY - 1; - - var j = Math.max(Math.min(Math.round(xRatio), this.data.z[0].length - 1), 0); - var k = Math.max(Math.min(Math.round(yRatio), this.data._ylength - 1), 0); - - selection.index = [j, k]; - - selection.traceCoordinate = [ - this.getXat(j, k), - this.getYat(j, k), - this.getZat(j, k) - ]; - - selection.dataCoordinate = [ - this.getXat(j, k, this.data.xcalendar, this.scene.fullSceneLayout.xaxis), - this.getYat(j, k, this.data.ycalendar, this.scene.fullSceneLayout.yaxis), - this.getZat(j, k, this.data.zcalendar, this.scene.fullSceneLayout.zaxis) - ]; - - for(var i = 0; i < 3; i++) { - var v = selection.dataCoordinate[i]; - if(v !== null && v !== undefined) { - selection.dataCoordinate[i] *= this.scene.dataScale[i]; - } - } - - var text = this.data.hovertext || this.data.text; - if(Array.isArray(text) && text[k] && text[k][j] !== undefined) { - selection.textLabel = text[k][j]; - } else if(text) { - selection.textLabel = text; - } else { - selection.textLabel = ''; - } - - selection.data.dataCoordinate = selection.dataCoordinate.slice(); - - this.surface.highlight(selection.data); - - // Snap spikes to data coordinate - this.scene.glplot.spikes.position = selection.dataCoordinate; - - return true; - } -}; - -function isColormapCircular(colormap) { - var first = colormap[0].rgb; - var last = colormap[colormap.length - 1].rgb; - - return ( - first[0] === last[0] && - first[1] === last[1] && - first[2] === last[2] && - first[3] === last[3] - ); -} - -var shortPrimes = [ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, - 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, - 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, - 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, - 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, - 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, - 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, - 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, - 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, - 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, - 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, - 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, - 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, - 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, - 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, - 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, - 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, - 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, - 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, - 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, - 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, - 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, - 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, - 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, - 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, - 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, - 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, - 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, - 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999 -]; - -function getPow(a, b) { - if(a < b) return 0; - var n = 0; - while(Math.floor(a % b) === 0) { - a /= b; - n++; - } - return n; -} - -function getFactors(a) { - var powers = []; - for(var i = 0; i < shortPrimes.length; i++) { - var b = shortPrimes[i]; - powers.push( - getPow(a, b) - ); - } - return powers; -} - -function smallestDivisor(a) { - var A = getFactors(a); - var result = a; - for(var i = 0; i < shortPrimes.length; i++) { - if(A[i] > 0) { - result = shortPrimes[i]; - break; - } - } - return result; -} - -function leastCommonMultiple(a, b) { - if(a < 1 || b < 1) return undefined; - var A = getFactors(a); - var B = getFactors(b); - var n = 1; - for(var i = 0; i < shortPrimes.length; i++) { - n *= Math.pow( - shortPrimes[i], Math.max(A[i], B[i]) - ); - } - return n; -} - -function arrayLCM(A) { - if(A.length === 0) return undefined; - var n = 1; - for(var i = 0; i < A.length; i++) { - n = leastCommonMultiple(n, A[i]); - } - return n; -} - -proto.calcXnums = function(xlen) { - var i; - var nums = []; - for(i = 1; i < xlen; i++) { - var a = this.getXat(i - 1, 0); - var b = this.getXat(i, 0); - - if(b !== a && - a !== undefined && a !== null && - b !== undefined && b !== null) { - nums[i - 1] = Math.abs(b - a); - } else { - nums[i - 1] = 0; - } - } - - var totalDist = 0; - for(i = 1; i < xlen; i++) { - totalDist += nums[i - 1]; - } - - for(i = 1; i < xlen; i++) { - if(nums[i - 1] === 0) { - nums[i - 1] = 1; - } else { - nums[i - 1] = Math.round(totalDist / nums[i - 1]); - } - } - - return nums; -}; - -proto.calcYnums = function(ylen) { - var i; - var nums = []; - for(i = 1; i < ylen; i++) { - var a = this.getYat(0, i - 1); - var b = this.getYat(0, i); - - if(b !== a && - a !== undefined && a !== null && - b !== undefined && b !== null) { - nums[i - 1] = Math.abs(b - a); - } else { - nums[i - 1] = 0; - } - } - - var totalDist = 0; - for(i = 1; i < ylen; i++) { - totalDist += nums[i - 1]; - } - - for(i = 1; i < ylen; i++) { - if(nums[i - 1] === 0) { - nums[i - 1] = 1; - } else { - nums[i - 1] = Math.round(totalDist / nums[i - 1]); - } - } - - return nums; -}; - -var highlyComposites = [1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260]; - -var MIN_RESOLUTION = highlyComposites[9]; -var MAX_RESOLUTION = highlyComposites[13]; - -proto.estimateScale = function(resSrc, axis) { - var nums = (axis === 0) ? - this.calcXnums(resSrc) : - this.calcYnums(resSrc); - - var resDst = 1 + arrayLCM(nums); - - while(resDst < MIN_RESOLUTION) { - resDst *= 2; - } - - while(resDst > MAX_RESOLUTION) { - resDst--; - resDst /= smallestDivisor(resDst); - resDst++; - - if(resDst < MIN_RESOLUTION) { - // resDst = MIN_RESOLUTION; // option 1: use min resolution - resDst = MAX_RESOLUTION; // option 2: use max resolution - } - } - - var scale = Math.round(resDst / resSrc); - return (scale > 1) ? scale : 1; -}; - -proto.refineCoords = function(coords) { - var scaleW = this.dataScaleX; - var scaleH = this.dataScaleY; - - var width = coords[0].shape[0]; - var height = coords[0].shape[1]; - - var newWidth = Math.floor(coords[0].shape[0] * scaleW + 1) | 0; - var newHeight = Math.floor(coords[0].shape[1] * scaleH + 1) | 0; - - // Pad coords by +1 - var padWidth = 1 + width + 1; - var padHeight = 1 + height + 1; - var padImg = ndarray(new Float32Array(padWidth * padHeight), [padWidth, padHeight]); - - for(var i = 0; i < coords.length; ++i) { - this.surface.padField(padImg, coords[i]); - - var scaledImg = ndarray(new Float32Array(newWidth * newHeight), [newWidth, newHeight]); - homography(scaledImg, padImg, - [ - scaleW, 0, 0, - 0, scaleH, 0, - 0, 0, 1 - ] - ); - coords[i] = scaledImg; - } -}; - -function insertIfNewLevel(arr, newValue) { - var found = false; - for(var k = 0; k < arr.length; k++) { - if(newValue === arr[k]) { - found = true; - break; - } - } - if(found === false) arr.push(newValue); -} - -proto.setContourLevels = function() { - var newLevels = [[], [], []]; - var useNewLevels = [false, false, false]; - var needsUpdate = false; - - var i, j, value; - - for(i = 0; i < 3; ++i) { - if(this.showContour[i]) { - needsUpdate = true; - - if( - this.contourSize[i] > 0 && - this.contourStart[i] !== null && - this.contourEnd[i] !== null && - this.contourEnd[i] > this.contourStart[i] - ) { - useNewLevels[i] = true; - - for(j = this.contourStart[i]; j < this.contourEnd[i]; j += this.contourSize[i]) { - value = j * this.scene.dataScale[i]; - - insertIfNewLevel(newLevels[i], value); - } - } - } - } - - if(needsUpdate) { - var allLevels = [[], [], []]; - for(i = 0; i < 3; ++i) { - if(this.showContour[i]) { - allLevels[i] = useNewLevels[i] ? newLevels[i] : this.scene.contourLevels[i]; - } - } - this.surface.update({ levels: allLevels }); - } -}; - -proto.update = function(data) { - var scene = this.scene; - var sceneLayout = scene.fullSceneLayout; - var surface = this.surface; - var alpha = data.opacity; - var colormap = parseColorScale(data, alpha); - var scaleFactor = scene.dataScale; - var xlen = data.z[0].length; - var ylen = data._ylength; - var contourLevels = scene.contourLevels; - - // Save data - this.data = data; - - /* - * Fill and transpose zdata. - * Consistent with 'heatmap' and 'contour', plotly 'surface' - * 'z' are such that sub-arrays correspond to y-coords - * and that the sub-array entries correspond to a x-coords, - * which is the transpose of 'gl-surface-plot'. - */ - - var i, j, k, v; - var rawCoords = []; - for(i = 0; i < 3; i++) { - rawCoords[i] = []; - for(j = 0; j < xlen; j++) { - rawCoords[i][j] = []; - /* - for(k = 0; k < ylen; k++) { - rawCoords[i][j][k] = undefined; - } - */ - } - } - - // coords x, y & z - for(j = 0; j < xlen; j++) { - for(k = 0; k < ylen; k++) { - rawCoords[0][j][k] = this.getXat(j, k, data.xcalendar, sceneLayout.xaxis); - rawCoords[1][j][k] = this.getYat(j, k, data.ycalendar, sceneLayout.yaxis); - rawCoords[2][j][k] = this.getZat(j, k, data.zcalendar, sceneLayout.zaxis); - } - } - - if(data.connectgaps) { - data._emptypoints = findEmpties(rawCoords[2]); - interp2d(rawCoords[2], data._emptypoints); - - data._interpolatedZ = []; - for(j = 0; j < xlen; j++) { - data._interpolatedZ[j] = []; - for(k = 0; k < ylen; k++) { - data._interpolatedZ[j][k] = rawCoords[2][j][k]; - } - } - } - - // Note: log axes are not defined in surfaces yet. - // but they could be defined here... - - for(i = 0; i < 3; i++) { - for(j = 0; j < xlen; j++) { - for(k = 0; k < ylen; k++) { - v = rawCoords[i][j][k]; - if(v === null || v === undefined) { - rawCoords[i][j][k] = NaN; - } else { - v = rawCoords[i][j][k] *= scaleFactor[i]; - } - } - } - } - - for(i = 0; i < 3; i++) { - for(j = 0; j < xlen; j++) { - for(k = 0; k < ylen; k++) { - v = rawCoords[i][j][k]; - if(v !== null && v !== undefined) { - if(this.minValues[i] > v) { - this.minValues[i] = v; - } - if(this.maxValues[i] < v) { - this.maxValues[i] = v; - } - } - } - } - } - - for(i = 0; i < 3; i++) { - this.objectOffset[i] = 0.5 * (this.minValues[i] + this.maxValues[i]); - } - - for(i = 0; i < 3; i++) { - for(j = 0; j < xlen; j++) { - for(k = 0; k < ylen; k++) { - v = rawCoords[i][j][k]; - if(v !== null && v !== undefined) { - rawCoords[i][j][k] -= this.objectOffset[i]; - } - } - } - } - - // convert processed raw data to Float32 matrices - var coords = [ - ndarray(new Float32Array(xlen * ylen), [xlen, ylen]), - ndarray(new Float32Array(xlen * ylen), [xlen, ylen]), - ndarray(new Float32Array(xlen * ylen), [xlen, ylen]) - ]; - fill(coords[0], function(row, col) { return rawCoords[0][row][col]; }); - fill(coords[1], function(row, col) { return rawCoords[1][row][col]; }); - fill(coords[2], function(row, col) { return rawCoords[2][row][col]; }); - rawCoords = []; // free memory - - var params = { - colormap: colormap, - levels: [[], [], []], - showContour: [true, true, true], - showSurface: !data.hidesurface, - contourProject: [ - [false, false, false], - [false, false, false], - [false, false, false] - ], - contourWidth: [1, 1, 1], - contourColor: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], - contourTint: [1, 1, 1], - dynamicColor: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], - dynamicWidth: [1, 1, 1], - dynamicTint: [1, 1, 1], - opacity: data.opacity - }; - - var cOpts = extractOpts(data); - params.intensityBounds = [cOpts.min, cOpts.max]; - - // Refine surface color if necessary - if(data.surfacecolor) { - var intensity = ndarray(new Float32Array(xlen * ylen), [xlen, ylen]); - - fill(intensity, function(row, col) { - return data.surfacecolor[col][row]; - }); - - coords.push(intensity); - } else { - // when 'z' is used as 'intensity', - // we must scale its value - params.intensityBounds[0] *= scaleFactor[2]; - params.intensityBounds[1] *= scaleFactor[2]; - } - - if(MAX_RESOLUTION < coords[0].shape[0] || - MAX_RESOLUTION < coords[0].shape[1]) { - this.refineData = false; - } - - if(this.refineData === true) { - this.dataScaleX = this.estimateScale(coords[0].shape[0], 0); - this.dataScaleY = this.estimateScale(coords[0].shape[1], 1); - if(this.dataScaleX !== 1 || this.dataScaleY !== 1) { - this.refineCoords(coords); - } - } - - if(data.surfacecolor) { - params.intensity = coords.pop(); - } - - var highlightEnable = [true, true, true]; - var axis = ['x', 'y', 'z']; - - for(i = 0; i < 3; ++i) { - var contourParams = data.contours[axis[i]]; - highlightEnable[i] = contourParams.highlight; - - params.showContour[i] = contourParams.show || contourParams.highlight; - if(!params.showContour[i]) continue; - - params.contourProject[i] = [ - contourParams.project.x, - contourParams.project.y, - contourParams.project.z - ]; - - if(contourParams.show) { - this.showContour[i] = true; - params.levels[i] = contourLevels[i]; - surface.highlightColor[i] = params.contourColor[i] = str2RgbaArray(contourParams.color); - - if(contourParams.usecolormap) { - surface.highlightTint[i] = params.contourTint[i] = 0; - } else { - surface.highlightTint[i] = params.contourTint[i] = 1; - } - params.contourWidth[i] = contourParams.width; - - this.contourStart[i] = contourParams.start; - this.contourEnd[i] = contourParams.end; - this.contourSize[i] = contourParams.size; - } else { - this.showContour[i] = false; - - this.contourStart[i] = null; - this.contourEnd[i] = null; - this.contourSize[i] = 0; - } - - if(contourParams.highlight) { - params.dynamicColor[i] = str2RgbaArray(contourParams.highlightcolor); - params.dynamicWidth[i] = contourParams.highlightwidth; - } - } - - // see https://github.com/plotly/plotly.js/issues/940 - if(isColormapCircular(colormap)) { - params.vertexColor = true; - } - - params.objectOffset = this.objectOffset; - - params.coords = coords; - surface.update(params); - - surface.visible = data.visible; - surface.enableDynamic = highlightEnable; - surface.enableHighlight = highlightEnable; - - surface.snapToData = true; - - if('lighting' in data) { - surface.ambientLight = data.lighting.ambient; - surface.diffuseLight = data.lighting.diffuse; - surface.specularLight = data.lighting.specular; - surface.roughness = data.lighting.roughness; - surface.fresnel = data.lighting.fresnel; - } - - if('lightposition' in data) { - surface.lightPosition = [data.lightposition.x, data.lightposition.y, data.lightposition.z]; - } - - if(alpha && alpha < 1) { - surface.supportsTransparency = true; - } -}; - -proto.dispose = function() { - this.scene.glplot.remove(this.surface); - this.surface.dispose(); -}; - -function createSurfaceTrace(scene, data) { - var gl = scene.glplot.gl; - var surface = createSurface({ gl: gl }); - var result = new SurfaceTrace(scene, surface, data.uid); - surface._trace = result; - result.update(data); - scene.glplot.add(surface); - return result; -} - -module.exports = createSurfaceTrace; - -},{"../../components/colorscale":605,"../../lib":719,"../../lib/gl_format_color":716,"../../lib/str2rgbarray":742,"../heatmap/find_empties":1007,"../heatmap/interp2d":1010,"gl-surface3d":316,"ndarray":450,"ndarray-fill":440,"ndarray-homography":442}],1227:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Registry = _dereq_('../../registry'); -var Lib = _dereq_('../../lib'); - -var colorscaleDefaults = _dereq_('../../components/colorscale/defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - var i, j; - - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var x = coerce('x'); - var y = coerce('y'); - - var z = coerce('z'); - if(!z || !z.length || - (x ? (x.length < 1) : false) || - (y ? (y.length < 1) : false) - ) { - traceOut.visible = false; - return; - } - - traceOut._xlength = (Array.isArray(x) && Lib.isArrayOrTypedArray(x[0])) ? z.length : z[0].length; - traceOut._ylength = z.length; - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleTraceDefaults'); - handleCalendarDefaults(traceIn, traceOut, ['x', 'y', 'z'], layout); - - coerce('text'); - coerce('hovertext'); - coerce('hovertemplate'); - - // Coerce remaining properties - [ - 'lighting.ambient', - 'lighting.diffuse', - 'lighting.specular', - 'lighting.roughness', - 'lighting.fresnel', - 'lightposition.x', - 'lightposition.y', - 'lightposition.z', - 'hidesurface', - 'connectgaps', - 'opacity' - ].forEach(function(x) { coerce(x); }); - - var surfaceColor = coerce('surfacecolor'); - - var dims = ['x', 'y', 'z']; - for(i = 0; i < 3; ++i) { - var contourDim = 'contours.' + dims[i]; - var show = coerce(contourDim + '.show'); - var highlight = coerce(contourDim + '.highlight'); - - if(show || highlight) { - for(j = 0; j < 3; ++j) { - coerce(contourDim + '.project.' + dims[j]); - } - } - - if(show) { - coerce(contourDim + '.color'); - coerce(contourDim + '.width'); - coerce(contourDim + '.usecolormap'); - } - - if(highlight) { - coerce(contourDim + '.highlightcolor'); - coerce(contourDim + '.highlightwidth'); - } - - coerce(contourDim + '.start'); - coerce(contourDim + '.end'); - coerce(contourDim + '.size'); - } - - // backward compatibility block - if(!surfaceColor) { - mapLegacy(traceIn, 'zmin', 'cmin'); - mapLegacy(traceIn, 'zmax', 'cmax'); - mapLegacy(traceIn, 'zauto', 'cauto'); - } - - // TODO if contours.?.usecolormap are false and hidesurface is true - // the colorbar shouldn't be shown by default - - colorscaleDefaults( - traceIn, traceOut, layout, coerce, {prefix: '', cLetter: 'c'} - ); - - // disable 1D transforms - currently surface does NOT support column data like heatmap does - // you can use mesh3d for this use case, but not surface - traceOut._length = null; -}; - -function mapLegacy(traceIn, oldAttr, newAttr) { - if(oldAttr in traceIn && !(newAttr in traceIn)) { - traceIn[newAttr] = traceIn[oldAttr]; - } -} - -},{"../../components/colorscale/defaults":603,"../../lib":719,"../../registry":847,"./attributes":1224}],1228:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - colorbar: { - min: 'cmin', - max: 'cmax' - }, - calc: _dereq_('./calc'), - plot: _dereq_('./convert'), - - moduleType: 'trace', - name: 'surface', - basePlotModule: _dereq_('../../plots/gl3d'), - categories: ['gl3d', '2dMap', 'noOpacity'], - meta: { - - } -}; - -},{"../../plots/gl3d":807,"./attributes":1224,"./calc":1225,"./convert":1226,"./defaults":1227}],1229:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var annAttrs = _dereq_('../../components/annotations/attributes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; -var fontAttrs = _dereq_('../../plots/font_attributes'); -var domainAttrs = _dereq_('../../plots/domain').attributes; - -var FORMAT_LINK = _dereq_('../../constants/docs').FORMAT_LINK; - -var attrs = module.exports = overrideAll({ - domain: domainAttrs({name: 'table', trace: true}), - - columnwidth: { - valType: 'number', - arrayOk: true, - dflt: null, - - - }, - - columnorder: { - valType: 'data_array', - - - }, - - header: { - - values: { - valType: 'data_array', - - dflt: [], - - }, - - format: { - valType: 'data_array', - - dflt: [], - - }, - - prefix: { - valType: 'string', - arrayOk: true, - dflt: null, - - - }, - - suffix: { - valType: 'string', - arrayOk: true, - dflt: null, - - - }, - - height: { - valType: 'number', - dflt: 28, - - - }, - - align: extendFlat({}, annAttrs.align, {arrayOk: true}), - - line: { - width: { - valType: 'number', - arrayOk: true, - dflt: 1, - - }, - color: { - valType: 'color', - arrayOk: true, - dflt: 'grey', - - } - }, - - fill: { - color: { - valType: 'color', - arrayOk: true, - dflt: 'white', - - - } - }, - - font: extendFlat({}, fontAttrs({arrayOk: true})) - }, - - cells: { - - values: { - valType: 'data_array', - - dflt: [], - - }, - - format: { - valType: 'data_array', - - dflt: [], - - }, - - prefix: { - valType: 'string', - arrayOk: true, - dflt: null, - - - }, - - suffix: { - valType: 'string', - arrayOk: true, - dflt: null, - - - }, - - height: { - valType: 'number', - dflt: 20, - - - }, - - align: extendFlat({}, annAttrs.align, {arrayOk: true}), - - line: { - width: { - valType: 'number', - arrayOk: true, - dflt: 1, - - }, - color: { - valType: 'color', - arrayOk: true, - dflt: 'grey', - - } - }, - - fill: { - color: { - valType: 'color', - arrayOk: true, - - dflt: 'white', - - } - }, - - font: extendFlat({}, fontAttrs({arrayOk: true})) - } -}, 'calc', 'from-root'); -attrs.transforms = undefined; - -},{"../../components/annotations/attributes":576,"../../constants/docs":690,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plots/domain":792,"../../plots/font_attributes":793}],1230:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var getModuleCalcData = _dereq_('../../plots/get_data').getModuleCalcData; -var tablePlot = _dereq_('./plot'); - -var TABLE = 'table'; - -exports.name = TABLE; - -exports.plot = function(gd) { - var calcData = getModuleCalcData(gd.calcdata, TABLE)[0]; - if(calcData.length) tablePlot(gd, calcData); -}; - -exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) { - var hadTable = (oldFullLayout._has && oldFullLayout._has(TABLE)); - var hasTable = (newFullLayout._has && newFullLayout._has(TABLE)); - - if(hadTable && !hasTable) { - oldFullLayout._paperdiv.selectAll('.table').remove(); - } -}; - -},{"../../plots/get_data":802,"./plot":1237}],1231:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var wrap = _dereq_('../../lib/gup').wrap; - -module.exports = function calc() { - // we don't actually need to include the trace here, since that will be added - // by Plots.doCalcdata, and that's all we actually need later. - return wrap({}); -}; - -},{"../../lib/gup":717}],1232:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - cellPad: 8, - columnExtentOffset: 10, - columnTitleOffset: 28, - emptyHeaderHeight: 16, - latexCheck: /^\$.*\$$/, - goldenRatio: 1.618, - lineBreaker: '
', - maxDimensionCount: 60, - overdrag: 45, - releaseTransitionDuration: 120, - releaseTransitionEase: 'cubic-out', - scrollbarCaptureWidth: 18, - scrollbarHideDelay: 1000, - scrollbarHideDuration: 1000, - scrollbarOffset: 5, - scrollbarWidth: 8, - transitionDuration: 100, - transitionEase: 'cubic-out', - uplift: 5, - wrapSpacer: ' ', - wrapSplitCharacter: ' ', - cn: { - // general class names - table: 'table', - tableControlView: 'table-control-view', - scrollBackground: 'scroll-background', - yColumn: 'y-column', - columnBlock: 'column-block', - scrollAreaClip: 'scroll-area-clip', - scrollAreaClipRect: 'scroll-area-clip-rect', - columnBoundary: 'column-boundary', - columnBoundaryClippath: 'column-boundary-clippath', - columnBoundaryRect: 'column-boundary-rect', - columnCells: 'column-cells', - columnCell: 'column-cell', - cellRect: 'cell-rect', - cellText: 'cell-text', - cellTextHolder: 'cell-text-holder', - - // scroll related class names - scrollbarKit: 'scrollbar-kit', - scrollbar: 'scrollbar', - scrollbarSlider: 'scrollbar-slider', - scrollbarGlyph: 'scrollbar-glyph', - scrollbarCaptureZone: 'scrollbar-capture-zone' - } -}; - -},{}],1233:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var c = _dereq_('./constants'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var isNumeric = _dereq_('fast-isnumeric'); - -// pure functions, don't alter but passes on `gd` and parts of `trace` without deep copying -module.exports = function calc(gd, trace) { - var cellsValues = squareStringMatrix(trace.cells.values); - var slicer = function(a) { - return a.slice(trace.header.values.length, a.length); - }; - var headerValuesIn = squareStringMatrix(trace.header.values); - if(headerValuesIn.length && !headerValuesIn[0].length) { - headerValuesIn[0] = ['']; - headerValuesIn = squareStringMatrix(headerValuesIn); - } - var headerValues = headerValuesIn - .concat(slicer(cellsValues).map(function() { - return emptyStrings((headerValuesIn[0] || ['']).length); - })); - - var domain = trace.domain; - var groupWidth = Math.floor(gd._fullLayout._size.w * (domain.x[1] - domain.x[0])); - var groupHeight = Math.floor(gd._fullLayout._size.h * (domain.y[1] - domain.y[0])); - var headerRowHeights = trace.header.values.length ? - headerValues[0].map(function() { return trace.header.height; }) : - [c.emptyHeaderHeight]; - var rowHeights = cellsValues.length ? cellsValues[0].map(function() { return trace.cells.height; }) : []; - var headerHeight = headerRowHeights.reduce(sum, 0); - var scrollHeight = groupHeight - headerHeight; - var minimumFillHeight = scrollHeight + c.uplift; - var anchorToRowBlock = makeAnchorToRowBlock(rowHeights, minimumFillHeight); - var anchorToHeaderRowBlock = makeAnchorToRowBlock(headerRowHeights, headerHeight); - var headerRowBlocks = makeRowBlock(anchorToHeaderRowBlock, []); - var rowBlocks = makeRowBlock(anchorToRowBlock, headerRowBlocks); - var uniqueKeys = {}; - var columnOrder = trace._fullInput.columnorder.concat(slicer(cellsValues.map(function(d, i) {return i;}))); - var columnWidths = headerValues.map(function(d, i) { - var value = Array.isArray(trace.columnwidth) ? - trace.columnwidth[Math.min(i, trace.columnwidth.length - 1)] : - trace.columnwidth; - return isNumeric(value) ? Number(value) : 1; - }); - var totalColumnWidths = columnWidths.reduce(sum, 0); - - // fit columns in the available vertical space as there's no vertical scrolling now - columnWidths = columnWidths.map(function(d) { return d / totalColumnWidths * groupWidth; }); - - var maxLineWidth = Math.max(arrayMax(trace.header.line.width), arrayMax(trace.cells.line.width)); - - var calcdata = { - // include staticPlot in the key so if it changes we delete and redraw - key: trace.uid + gd._context.staticPlot, - translateX: domain.x[0] * gd._fullLayout._size.w, - translateY: gd._fullLayout._size.h * (1 - domain.y[1]), - size: gd._fullLayout._size, - width: groupWidth, - maxLineWidth: maxLineWidth, - height: groupHeight, - columnOrder: columnOrder, // will be mutated on column move, todo use in callback - groupHeight: groupHeight, - rowBlocks: rowBlocks, - headerRowBlocks: headerRowBlocks, - scrollY: 0, // will be mutated on scroll - cells: extendFlat({}, trace.cells, {values: cellsValues}), - headerCells: extendFlat({}, trace.header, {values: headerValues}), - gdColumns: headerValues.map(function(d) {return d[0];}), - gdColumnsOriginalOrder: headerValues.map(function(d) {return d[0];}), - prevPages: [0, 0], - scrollbarState: {scrollbarScrollInProgress: false}, - columns: headerValues.map(function(label, i) { - var foundKey = uniqueKeys[label]; - uniqueKeys[label] = (foundKey || 0) + 1; - var key = label + '__' + uniqueKeys[label]; - return { - key: key, - label: label, - specIndex: i, - xIndex: columnOrder[i], - xScale: xScale, - x: undefined, // initialized below - calcdata: undefined, // initialized below - columnWidth: columnWidths[i] - }; - }) - }; - - calcdata.columns.forEach(function(col) { - col.calcdata = calcdata; - col.x = xScale(col); - }); - - return calcdata; -}; - -function arrayMax(maybeArray) { - if(Array.isArray(maybeArray)) { - var max = 0; - for(var i = 0; i < maybeArray.length; i++) { - max = Math.max(max, arrayMax(maybeArray[i])); - } - return max; - } - return maybeArray; -} - -function sum(a, b) { return a + b; } - -// fill matrix in place to equal lengths -// and ensure it's uniformly 2D -function squareStringMatrix(matrixIn) { - var matrix = matrixIn.slice(); - var minLen = Infinity; - var maxLen = 0; - var i; - for(i = 0; i < matrix.length; i++) { - if(!Array.isArray(matrix[i])) matrix[i] = [matrix[i]]; - minLen = Math.min(minLen, matrix[i].length); - maxLen = Math.max(maxLen, matrix[i].length); - } - - if(minLen !== maxLen) { - for(i = 0; i < matrix.length; i++) { - var padLen = maxLen - matrix[i].length; - if(padLen) matrix[i] = matrix[i].concat(emptyStrings(padLen)); - } - } - return matrix; -} - -function emptyStrings(len) { - var padArray = new Array(len); - for(var j = 0; j < len; j++) padArray[j] = ''; - return padArray; -} - -function xScale(d) { - return d.calcdata.columns.reduce(function(prev, next) { - return next.xIndex < d.xIndex ? prev + next.columnWidth : prev; - }, 0); -} - -function makeRowBlock(anchorToRowBlock, auxiliary) { - var blockAnchorKeys = Object.keys(anchorToRowBlock); - return blockAnchorKeys.map(function(k) {return extendFlat({}, anchorToRowBlock[k], {auxiliaryBlocks: auxiliary});}); -} - -function makeAnchorToRowBlock(rowHeights, minimumFillHeight) { - var anchorToRowBlock = {}; - var currentRowHeight; - var currentAnchor = 0; - var currentBlockHeight = 0; - var currentBlock = makeIdentity(); - var currentFirstRowIndex = 0; - var blockCounter = 0; - for(var i = 0; i < rowHeights.length; i++) { - currentRowHeight = rowHeights[i]; - currentBlock.rows.push({ - rowIndex: i, - rowHeight: currentRowHeight - }); - currentBlockHeight += currentRowHeight; - if(currentBlockHeight >= minimumFillHeight || i === rowHeights.length - 1) { - anchorToRowBlock[currentAnchor] = currentBlock; - currentBlock.key = blockCounter++; - currentBlock.firstRowIndex = currentFirstRowIndex; - currentBlock.lastRowIndex = i; - currentBlock = makeIdentity(); - currentAnchor += currentBlockHeight; - currentFirstRowIndex = i + 1; - currentBlockHeight = 0; - } - } - - return anchorToRowBlock; -} - -function makeIdentity() { - return { - firstRowIndex: null, - lastRowIndex: null, - rows: [] - }; -} - -},{"../../lib/extend":710,"./constants":1232,"fast-isnumeric":225}],1234:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -// pure functions, don't alter but passes on `gd` and parts of `trace` without deep copying - -exports.splitToPanels = function(d) { - var prevPages = [0, 0]; - var headerPanel = extendFlat({}, d, { - key: 'header', - type: 'header', - page: 0, - prevPages: prevPages, - currentRepaint: [null, null], - dragHandle: true, - values: d.calcdata.headerCells.values[d.specIndex], - rowBlocks: d.calcdata.headerRowBlocks, - calcdata: extendFlat({}, d.calcdata, {cells: d.calcdata.headerCells}) - }); - var revolverPanel1 = extendFlat({}, d, { - key: 'cells1', - type: 'cells', - page: 0, - prevPages: prevPages, - currentRepaint: [null, null], - dragHandle: false, - values: d.calcdata.cells.values[d.specIndex], - rowBlocks: d.calcdata.rowBlocks - }); - var revolverPanel2 = extendFlat({}, d, { - key: 'cells2', - type: 'cells', - page: 1, - prevPages: prevPages, - currentRepaint: [null, null], - dragHandle: false, - values: d.calcdata.cells.values[d.specIndex], - rowBlocks: d.calcdata.rowBlocks - }); - // order due to SVG using painter's algo: - return [revolverPanel1, revolverPanel2, headerPanel]; -}; - -exports.splitToCells = function(d) { - var fromTo = rowFromTo(d); - return (d.values || []).slice(fromTo[0], fromTo[1]).map(function(v, i) { - // By keeping identical key, a DOM node removal, creation and addition is spared, important when visible - // grid has a lot of elements (quadratic with xcol/ycol count). - // But it has to be busted when `svgUtil.convertToTspans` is used as it reshapes cell subtrees asynchronously, - // and by that time the user may have scrolled away, resulting in stale overwrites. The real solution will be - // to turn `svgUtil.convertToTspans` into a cancelable request, in which case no key busting is needed. - var buster = (typeof v === 'string') && v.match(/[<$&> ]/) ? '_keybuster_' + Math.random() : ''; - return { - // keyWithinBlock: /*fromTo[0] + */i, // optimized future version - no busting - // keyWithinBlock: fromTo[0] + i, // initial always-unoptimized version - janky scrolling with 5+ columns - keyWithinBlock: i + buster, // current compromise: regular content is very fast; async content is possible - key: fromTo[0] + i, - column: d, - calcdata: d.calcdata, - page: d.page, - rowBlocks: d.rowBlocks, - value: v - }; - }); -}; - -function rowFromTo(d) { - var rowBlock = d.rowBlocks[d.page]; - // fixme rowBlock truthiness check is due to ugly hack of placing 2nd panel as d.page = -1 - var rowFrom = rowBlock ? rowBlock.rows[0].rowIndex : 0; - var rowTo = rowBlock ? rowFrom + rowBlock.rows.length : 0; - return [rowFrom, rowTo]; -} - -},{"../../lib/extend":710}],1235:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attributes = _dereq_('./attributes'); -var handleDomainDefaults = _dereq_('../../plots/domain').defaults; - -function defaultColumnOrder(traceOut, coerce) { - var specifiedColumnOrder = traceOut.columnorder || []; - var commonLength = traceOut.header.values.length; - var truncated = specifiedColumnOrder.slice(0, commonLength); - var sorted = truncated.slice().sort(function(a, b) {return a - b;}); - var oneStepped = truncated.map(function(d) {return sorted.indexOf(d);}); - for(var i = oneStepped.length; i < commonLength; i++) { - oneStepped.push(i); - } - coerce('columnorder', oneStepped); -} - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - handleDomainDefaults(traceOut, layout, coerce); - - coerce('columnwidth'); - - coerce('header.values'); - coerce('header.format'); - coerce('header.align'); - - coerce('header.prefix'); - coerce('header.suffix'); - coerce('header.height'); - coerce('header.line.width'); - coerce('header.line.color'); - coerce('header.fill.color'); - Lib.coerceFont(coerce, 'header.font', Lib.extendFlat({}, layout.font)); - - defaultColumnOrder(traceOut, coerce); - - coerce('cells.values'); - coerce('cells.format'); - coerce('cells.align'); - coerce('cells.prefix'); - coerce('cells.suffix'); - coerce('cells.height'); - coerce('cells.line.width'); - coerce('cells.line.color'); - coerce('cells.fill.color'); - Lib.coerceFont(coerce, 'cells.font', Lib.extendFlat({}, layout.font)); - - // disable 1D transforms - traceOut._length = null; -}; - -},{"../../lib":719,"../../plots/domain":792,"./attributes":1229}],1236:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('./calc'), - plot: _dereq_('./plot'), - - moduleType: 'trace', - name: 'table', - basePlotModule: _dereq_('./base_plot'), - categories: ['noOpacity'], - meta: { - - } -}; - -},{"./attributes":1229,"./base_plot":1230,"./calc":1231,"./defaults":1235,"./plot":1237}],1237:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var c = _dereq_('./constants'); -var d3 = _dereq_('d3'); -var gup = _dereq_('../../lib/gup'); -var Drawing = _dereq_('../../components/drawing'); -var svgUtil = _dereq_('../../lib/svg_text_utils'); -var raiseToTop = _dereq_('../../lib').raiseToTop; -var cancelEeaseColumn = _dereq_('../../lib').cancelTransition; -var prepareData = _dereq_('./data_preparation_helper'); -var splitData = _dereq_('./data_split_helpers'); -var Color = _dereq_('../../components/color'); - -module.exports = function plot(gd, wrappedTraceHolders) { - var dynamic = !gd._context.staticPlot; - - var table = gd._fullLayout._paper.selectAll('.' + c.cn.table) - .data(wrappedTraceHolders.map(function(wrappedTraceHolder) { - var traceHolder = gup.unwrap(wrappedTraceHolder); - var trace = traceHolder.trace; - return prepareData(gd, trace); - }), gup.keyFun); - - table.exit().remove(); - - table.enter() - .append('g') - .classed(c.cn.table, true) - .attr('overflow', 'visible') - .style('box-sizing', 'content-box') - .style('position', 'absolute') - .style('left', 0) - .style('overflow', 'visible') - .style('shape-rendering', 'crispEdges') - .style('pointer-events', 'all'); - - table - .attr('width', function(d) {return d.width + d.size.l + d.size.r;}) - .attr('height', function(d) {return d.height + d.size.t + d.size.b;}) - .attr('transform', function(d) { - return 'translate(' + d.translateX + ',' + d.translateY + ')'; - }); - - var tableControlView = table.selectAll('.' + c.cn.tableControlView) - .data(gup.repeat, gup.keyFun); - - var cvEnter = tableControlView.enter() - .append('g') - .classed(c.cn.tableControlView, true) - .style('box-sizing', 'content-box'); - if(dynamic) { - cvEnter - .on('mousemove', function(d) { - tableControlView - .filter(function(dd) {return d === dd;}) - .call(renderScrollbarKit, gd); - }) - .on('mousewheel', function(d) { - if(d.scrollbarState.wheeling) return; - d.scrollbarState.wheeling = true; - var newY = d.scrollY + d3.event.deltaY; - var noChange = makeDragRow(gd, tableControlView, null, newY)(d); - if(!noChange) { - d3.event.stopPropagation(); - d3.event.preventDefault(); - } - d.scrollbarState.wheeling = false; - }) - .call(renderScrollbarKit, gd, true); - } - - tableControlView - .attr('transform', function(d) {return 'translate(' + d.size.l + ' ' + d.size.t + ')';}); - - // scrollBackground merely ensures that mouse events are captured even on crazy fast scrollwheeling - // otherwise rendering glitches may occur - var scrollBackground = tableControlView.selectAll('.' + c.cn.scrollBackground) - .data(gup.repeat, gup.keyFun); - - scrollBackground.enter() - .append('rect') - .classed(c.cn.scrollBackground, true) - .attr('fill', 'none'); - - scrollBackground - .attr('width', function(d) {return d.width;}) - .attr('height', function(d) {return d.height;}); - - tableControlView.each(function(d) { - Drawing.setClipUrl(d3.select(this), scrollAreaBottomClipKey(gd, d), gd); - }); - - var yColumn = tableControlView.selectAll('.' + c.cn.yColumn) - .data(function(vm) {return vm.columns;}, gup.keyFun); - - yColumn.enter() - .append('g') - .classed(c.cn.yColumn, true); - - yColumn.exit().remove(); - - yColumn.attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); - - if(dynamic) { - yColumn.call(d3.behavior.drag() - .origin(function(d) { - var movedColumn = d3.select(this); - easeColumn(movedColumn, d, -c.uplift); - raiseToTop(this); - d.calcdata.columnDragInProgress = true; - renderScrollbarKit(tableControlView.filter(function(dd) {return d.calcdata.key === dd.key;}), gd); - return d; - }) - .on('drag', function(d) { - var movedColumn = d3.select(this); - var getter = function(dd) {return (d === dd ? d3.event.x : dd.x) + dd.columnWidth / 2;}; - d.x = Math.max(-c.overdrag, Math.min(d.calcdata.width + c.overdrag - d.columnWidth, d3.event.x)); - - var sortableColumns = flatData(yColumn).filter(function(dd) {return dd.calcdata.key === d.calcdata.key;}); - var newOrder = sortableColumns.sort(function(a, b) {return getter(a) - getter(b);}); - newOrder.forEach(function(dd, i) { - dd.xIndex = i; - dd.x = d === dd ? dd.x : dd.xScale(dd); - }); - - yColumn.filter(function(dd) {return d !== dd;}) - .transition() - .ease(c.transitionEase) - .duration(c.transitionDuration) - .attr('transform', function(d) {return 'translate(' + d.x + ' 0)';}); - movedColumn - .call(cancelEeaseColumn) - .attr('transform', 'translate(' + d.x + ' -' + c.uplift + ' )'); - }) - .on('dragend', function(d) { - var movedColumn = d3.select(this); - var p = d.calcdata; - d.x = d.xScale(d); - d.calcdata.columnDragInProgress = false; - easeColumn(movedColumn, d, 0); - columnMoved(gd, p, p.columns.map(function(dd) {return dd.xIndex;})); - }) - ); - } - - yColumn.each(function(d) { - Drawing.setClipUrl(d3.select(this), columnBoundaryClipKey(gd, d), gd); - }); - - var columnBlock = yColumn.selectAll('.' + c.cn.columnBlock) - .data(splitData.splitToPanels, gup.keyFun); - - columnBlock.enter() - .append('g') - .classed(c.cn.columnBlock, true) - .attr('id', function(d) {return d.key;}); - - columnBlock - .style('cursor', function(d) { - return d.dragHandle ? 'ew-resize' : d.calcdata.scrollbarState.barWiggleRoom ? 'ns-resize' : 'default'; - }); - - var headerColumnBlock = columnBlock.filter(headerBlock); - var cellsColumnBlock = columnBlock.filter(cellsBlock); - - if(dynamic) { - cellsColumnBlock.call(d3.behavior.drag() - .origin(function(d) { - d3.event.stopPropagation(); - return d; - }) - .on('drag', makeDragRow(gd, tableControlView, -1)) - .on('dragend', function() { - // fixme emit plotly notification - }) - ); - } - - // initial rendering: header is rendered first, as it may may have async LaTeX (show header first) - // but blocks are _entered_ the way they are due to painter's algo (header on top) - renderColumnCellTree(gd, tableControlView, headerColumnBlock, columnBlock); - renderColumnCellTree(gd, tableControlView, cellsColumnBlock, columnBlock); - - var scrollAreaClip = tableControlView.selectAll('.' + c.cn.scrollAreaClip) - .data(gup.repeat, gup.keyFun); - - scrollAreaClip.enter() - .append('clipPath') - .classed(c.cn.scrollAreaClip, true) - .attr('id', function(d) {return scrollAreaBottomClipKey(gd, d);}); - - var scrollAreaClipRect = scrollAreaClip.selectAll('.' + c.cn.scrollAreaClipRect) - .data(gup.repeat, gup.keyFun); - - scrollAreaClipRect.enter() - .append('rect') - .classed(c.cn.scrollAreaClipRect, true) - .attr('x', -c.overdrag) - .attr('y', -c.uplift) - .attr('fill', 'none'); - - scrollAreaClipRect - .attr('width', function(d) {return d.width + 2 * c.overdrag;}) - .attr('height', function(d) {return d.height + c.uplift;}); - - var columnBoundary = yColumn.selectAll('.' + c.cn.columnBoundary) - .data(gup.repeat, gup.keyFun); - - columnBoundary.enter() - .append('g') - .classed(c.cn.columnBoundary, true); - - var columnBoundaryClippath = yColumn.selectAll('.' + c.cn.columnBoundaryClippath) - .data(gup.repeat, gup.keyFun); - - // SVG spec doesn't mandate wrapping into a and doesn't seem to cause a speed difference - columnBoundaryClippath.enter() - .append('clipPath') - .classed(c.cn.columnBoundaryClippath, true); - - columnBoundaryClippath - .attr('id', function(d) {return columnBoundaryClipKey(gd, d);}); - - var columnBoundaryRect = columnBoundaryClippath.selectAll('.' + c.cn.columnBoundaryRect) - .data(gup.repeat, gup.keyFun); - - columnBoundaryRect.enter() - .append('rect') - .classed(c.cn.columnBoundaryRect, true) - .attr('fill', 'none'); - - columnBoundaryRect - .attr('width', function(d) { return d.columnWidth + 2 * roundHalfWidth(d); }) - .attr('height', function(d) {return d.calcdata.height + 2 * roundHalfWidth(d) + c.uplift;}) - .attr('x', function(d) { return -roundHalfWidth(d); }) - .attr('y', function(d) { return -roundHalfWidth(d); }); - - updateBlockYPosition(null, cellsColumnBlock, tableControlView); -}; - -function roundHalfWidth(d) { - return Math.ceil(d.calcdata.maxLineWidth / 2); -} - -function scrollAreaBottomClipKey(gd, d) { - return 'clip' + gd._fullLayout._uid + '_scrollAreaBottomClip_' + d.key; -} - -function columnBoundaryClipKey(gd, d) { - return 'clip' + gd._fullLayout._uid + '_columnBoundaryClippath_' + d.calcdata.key + '_' + d.specIndex; -} - -function flatData(selection) { - return [].concat.apply([], selection.map(function(g) {return g;})) - .map(function(g) {return g.__data__;}); -} - -function renderScrollbarKit(tableControlView, gd, bypassVisibleBar) { - function calcTotalHeight(d) { - var blocks = d.rowBlocks; - return firstRowAnchor(blocks, blocks.length - 1) + (blocks.length ? rowsHeight(blocks[blocks.length - 1], Infinity) : 1); - } - - var scrollbarKit = tableControlView.selectAll('.' + c.cn.scrollbarKit) - .data(gup.repeat, gup.keyFun); - - scrollbarKit.enter() - .append('g') - .classed(c.cn.scrollbarKit, true) - .style('shape-rendering', 'geometricPrecision'); - - scrollbarKit - .each(function(d) { - var s = d.scrollbarState; - s.totalHeight = calcTotalHeight(d); - s.scrollableAreaHeight = d.groupHeight - headerHeight(d); - s.currentlyVisibleHeight = Math.min(s.totalHeight, s.scrollableAreaHeight); - s.ratio = s.currentlyVisibleHeight / s.totalHeight; - s.barLength = Math.max(s.ratio * s.currentlyVisibleHeight, c.goldenRatio * c.scrollbarWidth); - s.barWiggleRoom = s.currentlyVisibleHeight - s.barLength; - s.wiggleRoom = Math.max(0, s.totalHeight - s.scrollableAreaHeight); - s.topY = s.barWiggleRoom === 0 ? 0 : (d.scrollY / s.wiggleRoom) * s.barWiggleRoom; - s.bottomY = s.topY + s.barLength; - s.dragMultiplier = s.wiggleRoom / s.barWiggleRoom; - }) - .attr('transform', function(d) { - var xPosition = d.width + c.scrollbarWidth / 2 + c.scrollbarOffset; - return 'translate(' + xPosition + ' ' + headerHeight(d) + ')'; - }); - - var scrollbar = scrollbarKit.selectAll('.' + c.cn.scrollbar) - .data(gup.repeat, gup.keyFun); - - scrollbar.enter() - .append('g') - .classed(c.cn.scrollbar, true); - - var scrollbarSlider = scrollbar.selectAll('.' + c.cn.scrollbarSlider) - .data(gup.repeat, gup.keyFun); - - scrollbarSlider.enter() - .append('g') - .classed(c.cn.scrollbarSlider, true); - - scrollbarSlider - .attr('transform', function(d) { - return 'translate(0 ' + (d.scrollbarState.topY || 0) + ')'; - }); - - var scrollbarGlyph = scrollbarSlider.selectAll('.' + c.cn.scrollbarGlyph) - .data(gup.repeat, gup.keyFun); - - scrollbarGlyph.enter() - .append('line') - .classed(c.cn.scrollbarGlyph, true) - .attr('stroke', 'black') - .attr('stroke-width', c.scrollbarWidth) - .attr('stroke-linecap', 'round') - .attr('y1', c.scrollbarWidth / 2); - - scrollbarGlyph - .attr('y2', function(d) { - return d.scrollbarState.barLength - c.scrollbarWidth / 2; - }) - .attr('stroke-opacity', function(d) { - return d.columnDragInProgress || !d.scrollbarState.barWiggleRoom || bypassVisibleBar ? 0 : 0.4; - }); - - // cancel transition: possible pending (also, delayed) transition - scrollbarGlyph - .transition().delay(0).duration(0); - - scrollbarGlyph - .transition().delay(c.scrollbarHideDelay).duration(c.scrollbarHideDuration) - .attr('stroke-opacity', 0); - - var scrollbarCaptureZone = scrollbar.selectAll('.' + c.cn.scrollbarCaptureZone) - .data(gup.repeat, gup.keyFun); - - scrollbarCaptureZone.enter() - .append('line') - .classed(c.cn.scrollbarCaptureZone, true) - .attr('stroke', 'white') - .attr('stroke-opacity', 0.01) // some browser might get rid of a 0 opacity element - .attr('stroke-width', c.scrollbarCaptureWidth) - .attr('stroke-linecap', 'butt') - .attr('y1', 0) - .on('mousedown', function(d) { - var y = d3.event.y; - var bbox = this.getBoundingClientRect(); - var s = d.scrollbarState; - var pixelVal = y - bbox.top; - var inverseScale = d3.scale.linear().domain([0, s.scrollableAreaHeight]).range([0, s.totalHeight]).clamp(true); - if(!(s.topY <= pixelVal && pixelVal <= s.bottomY)) { - makeDragRow(gd, tableControlView, null, inverseScale(pixelVal - s.barLength / 2))(d); - } - }) - .call(d3.behavior.drag() - .origin(function(d) { - d3.event.stopPropagation(); - d.scrollbarState.scrollbarScrollInProgress = true; - return d; - }) - .on('drag', makeDragRow(gd, tableControlView)) - .on('dragend', function() { - // fixme emit Plotly event - }) - ); - - scrollbarCaptureZone - .attr('y2', function(d) { - return d.scrollbarState.scrollableAreaHeight; - }); - - // Remove scroll glyph and capture zone on static plots - // as they don't render properly when converted to PDF - // in the Chrome PDF viewer - // https://github.com/plotly/streambed/issues/11618 - if(gd._context.staticPlot) { - scrollbarGlyph.remove(); - scrollbarCaptureZone.remove(); - } -} - -function renderColumnCellTree(gd, tableControlView, columnBlock, allColumnBlock) { - // fixme this perf hotspot - // this is performance critical code as scrolling calls it on every revolver switch - // it appears sufficiently fast but there are plenty of low-hanging fruits for performance optimization - - var columnCells = renderColumnCells(columnBlock); - - var columnCell = renderColumnCell(columnCells); - - supplyStylingValues(columnCell); - - var cellRect = renderCellRect(columnCell); - - sizeAndStyleRect(cellRect); - - var cellTextHolder = renderCellTextHolder(columnCell); - - var cellText = renderCellText(cellTextHolder); - - setFont(cellText); - populateCellText(cellText, tableControlView, allColumnBlock, gd); - - // doing this at the end when text, and text stlying are set - setCellHeightAndPositionY(columnCell); -} - -function renderColumnCells(columnBlock) { - var columnCells = columnBlock.selectAll('.' + c.cn.columnCells) - .data(gup.repeat, gup.keyFun); - - columnCells.enter() - .append('g') - .classed(c.cn.columnCells, true); - - columnCells.exit() - .remove(); - - return columnCells; -} - -function renderColumnCell(columnCells) { - var columnCell = columnCells.selectAll('.' + c.cn.columnCell) - .data(splitData.splitToCells, function(d) {return d.keyWithinBlock;}); - - columnCell.enter() - .append('g') - .classed(c.cn.columnCell, true); - - columnCell.exit() - .remove(); - - return columnCell; -} - -function renderCellRect(columnCell) { - var cellRect = columnCell.selectAll('.' + c.cn.cellRect) - .data(gup.repeat, function(d) {return d.keyWithinBlock;}); - - cellRect.enter() - .append('rect') - .classed(c.cn.cellRect, true); - - return cellRect; -} - -function renderCellText(cellTextHolder) { - var cellText = cellTextHolder.selectAll('.' + c.cn.cellText) - .data(gup.repeat, function(d) {return d.keyWithinBlock;}); - - cellText.enter() - .append('text') - .classed(c.cn.cellText, true) - .style('cursor', function() {return 'auto';}) - .on('mousedown', function() {d3.event.stopPropagation();}); - - return cellText; -} - -function renderCellTextHolder(columnCell) { - var cellTextHolder = columnCell.selectAll('.' + c.cn.cellTextHolder) - .data(gup.repeat, function(d) {return d.keyWithinBlock;}); - - cellTextHolder.enter() - .append('g') - .classed(c.cn.cellTextHolder, true) - .style('shape-rendering', 'geometricPrecision'); - - return cellTextHolder; -} - -function supplyStylingValues(columnCell) { - columnCell - .each(function(d, i) { - var spec = d.calcdata.cells.font; - var col = d.column.specIndex; - var font = { - size: gridPick(spec.size, col, i), - color: gridPick(spec.color, col, i), - family: gridPick(spec.family, col, i) - }; - d.rowNumber = d.key; - d.align = gridPick(d.calcdata.cells.align, col, i); - d.cellBorderWidth = gridPick(d.calcdata.cells.line.width, col, i); - d.font = font; - }); -} - -function setFont(cellText) { - cellText - .each(function(d) { - Drawing.font(d3.select(this), d.font); - }); -} - -function sizeAndStyleRect(cellRect) { - cellRect - .attr('width', function(d) {return d.column.columnWidth;}) - .attr('stroke-width', function(d) {return d.cellBorderWidth;}) - .each(function(d) { - var atomicSelection = d3.select(this); - Color.stroke(atomicSelection, gridPick(d.calcdata.cells.line.color, d.column.specIndex, d.rowNumber)); - Color.fill(atomicSelection, gridPick(d.calcdata.cells.fill.color, d.column.specIndex, d.rowNumber)); - }); -} - -function populateCellText(cellText, tableControlView, allColumnBlock, gd) { - cellText - .text(function(d) { - var col = d.column.specIndex; - var row = d.rowNumber; - - var userSuppliedContent = d.value; - var stringSupplied = (typeof userSuppliedContent === 'string'); - var hasBreaks = stringSupplied && userSuppliedContent.match(/
/i); - var userBrokenText = !stringSupplied || hasBreaks; - d.mayHaveMarkup = stringSupplied && userSuppliedContent.match(/[<&>]/); - - var latex = isLatex(userSuppliedContent); - d.latex = latex; - - var prefix = latex ? '' : gridPick(d.calcdata.cells.prefix, col, row) || ''; - var suffix = latex ? '' : gridPick(d.calcdata.cells.suffix, col, row) || ''; - var format = latex ? null : gridPick(d.calcdata.cells.format, col, row) || null; - - var prefixSuffixedText = prefix + (format ? d3.format(format)(d.value) : d.value) + suffix; - - var hasWrapSplitCharacter; - d.wrappingNeeded = !d.wrapped && !userBrokenText && !latex && (hasWrapSplitCharacter = hasWrapCharacter(prefixSuffixedText)); - d.cellHeightMayIncrease = hasBreaks || latex || d.mayHaveMarkup || (hasWrapSplitCharacter === void(0) ? hasWrapCharacter(prefixSuffixedText) : hasWrapSplitCharacter); - d.needsConvertToTspans = d.mayHaveMarkup || d.wrappingNeeded || d.latex; - - var textToRender; - if(d.wrappingNeeded) { - var hrefPreservedText = c.wrapSplitCharacter === ' ' ? prefixSuffixedText.replace(/ pTop) { - pages.push(blockIndex); - } - pTop += rowsHeight; - - // consider this nice final optimization; put it in `for` condition - caveat, currently the - // block.allRowsHeight relies on being invalidated, so enabling this opt may not be safe - // if(pages.length > 1) break; - } - - return pages; -} - -function updateBlockYPosition(gd, cellsColumnBlock, tableControlView) { - var d = flatData(cellsColumnBlock)[0]; - if(d === undefined) return; - var blocks = d.rowBlocks; - var calcdata = d.calcdata; - - var bottom = firstRowAnchor(blocks, blocks.length); - var scrollHeight = d.calcdata.groupHeight - headerHeight(d); - var scrollY = calcdata.scrollY = Math.max(0, Math.min(bottom - scrollHeight, calcdata.scrollY)); - - var pages = findPagesAndCacheHeights(blocks, scrollY, scrollHeight); - if(pages.length === 1) { - if(pages[0] === blocks.length - 1) { - pages.unshift(pages[0] - 1); - } else { - pages.push(pages[0] + 1); - } - } - - // make phased out page jump by 2 while leaving stationary page intact - if(pages[0] % 2) { - pages.reverse(); - } - - cellsColumnBlock - .each(function(d, i) { - // these values will also be needed when a block is translated again due to growing cell height - d.page = pages[i]; - d.scrollY = scrollY; - }); - - cellsColumnBlock - .attr('transform', function(d) { - var yTranslate = firstRowAnchor(d.rowBlocks, d.page) - d.scrollY; - return 'translate(0 ' + yTranslate + ')'; - }); - - // conditionally rerendering panel 0 and 1 - if(gd) { - conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, d.prevPages, d, 0); - conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, d.prevPages, d, 1); - renderScrollbarKit(tableControlView, gd); - } -} - -function makeDragRow(gd, allTableControlView, optionalMultiplier, optionalPosition) { - return function dragRow(eventD) { - // may come from whichever DOM event target: drag, wheel, bar... eventD corresponds to event target - var d = eventD.calcdata ? eventD.calcdata : eventD; - var tableControlView = allTableControlView.filter(function(dd) {return d.key === dd.key;}); - var multiplier = optionalMultiplier || d.scrollbarState.dragMultiplier; - - var initialScrollY = d.scrollY; - - d.scrollY = optionalPosition === void(0) ? d.scrollY + multiplier * d3.event.dy : optionalPosition; - var cellsColumnBlock = tableControlView.selectAll('.' + c.cn.yColumn).selectAll('.' + c.cn.columnBlock).filter(cellsBlock); - updateBlockYPosition(gd, cellsColumnBlock, tableControlView); - - // return false if we've "used" the scroll, ie it did something, - // so the event shouldn't bubble (if appropriate) - return d.scrollY === initialScrollY; - }; -} - -function conditionalPanelRerender(gd, tableControlView, cellsColumnBlock, pages, prevPages, d, revolverIndex) { - var shouldComponentUpdate = pages[revolverIndex] !== prevPages[revolverIndex]; - if(shouldComponentUpdate) { - clearTimeout(d.currentRepaint[revolverIndex]); - d.currentRepaint[revolverIndex] = setTimeout(function() { - // setTimeout might lag rendering but yields a smoother scroll, because fast scrolling makes - // some repaints invisible ie. wasteful (DOM work blocks the main thread) - var toRerender = cellsColumnBlock.filter(function(d, i) {return i === revolverIndex && pages[i] !== prevPages[i];}); - renderColumnCellTree(gd, tableControlView, toRerender, cellsColumnBlock); - prevPages[revolverIndex] = pages[revolverIndex]; - }); - } -} - -function wrapTextMaker(columnBlock, element, tableControlView, gd) { - return function wrapText() { - var cellTextHolder = d3.select(element.parentNode); - cellTextHolder - .each(function(d) { - var fragments = d.fragments; - cellTextHolder.selectAll('tspan.line').each(function(dd, i) { - fragments[i].width = this.getComputedTextLength(); - }); - // last element is only for measuring the separator character, so it's ignored: - var separatorLength = fragments[fragments.length - 1].width; - var rest = fragments.slice(0, -1); - var currentRow = []; - var currentAddition, currentAdditionLength; - var currentRowLength = 0; - var rowLengthLimit = d.column.columnWidth - 2 * c.cellPad; - d.value = ''; - while(rest.length) { - currentAddition = rest.shift(); - currentAdditionLength = currentAddition.width + separatorLength; - if(currentRowLength + currentAdditionLength > rowLengthLimit) { - d.value += currentRow.join(c.wrapSpacer) + c.lineBreaker; - currentRow = []; - currentRowLength = 0; - } - currentRow.push(currentAddition.text); - currentRowLength += currentAdditionLength; - } - if(currentRowLength) { - d.value += currentRow.join(c.wrapSpacer); - } - d.wrapped = true; - }); - - // the pre-wrapped text was rendered only for the text measurements - cellTextHolder.selectAll('tspan.line').remove(); - - // resupply text, now wrapped - populateCellText(cellTextHolder.select('.' + c.cn.cellText), tableControlView, columnBlock, gd); - d3.select(element.parentNode.parentNode).call(setCellHeightAndPositionY); - }; -} - -function updateYPositionMaker(columnBlock, element, tableControlView, gd, d) { - return function updateYPosition() { - if(d.settledY) return; - var cellTextHolder = d3.select(element.parentNode); - var l = getBlock(d); - var rowIndex = d.key - l.firstRowIndex; - - var declaredRowHeight = l.rows[rowIndex].rowHeight; - - var requiredHeight = d.cellHeightMayIncrease ? element.parentNode.getBoundingClientRect().height + 2 * c.cellPad : declaredRowHeight; - - var finalHeight = Math.max(requiredHeight, declaredRowHeight); - var increase = finalHeight - l.rows[rowIndex].rowHeight; - - if(increase) { - // current row height increased - l.rows[rowIndex].rowHeight = finalHeight; - - columnBlock - .selectAll('.' + c.cn.columnCell) - .call(setCellHeightAndPositionY); - - updateBlockYPosition(null, columnBlock.filter(cellsBlock), 0); - - // if d.column.type === 'header', then the scrollbar has to be pushed downward to the scrollable area - // if d.column.type === 'cells', it can still be relevant if total scrolling content height is less than the - // scrollable window, as increases to row heights may need scrollbar updates - renderScrollbarKit(tableControlView, gd, true); - } - - cellTextHolder - .attr('transform', function() { - // this code block is only invoked for items where d.cellHeightMayIncrease is truthy - var element = this; - var columnCellElement = element.parentNode; - var box = columnCellElement.getBoundingClientRect(); - var rectBox = d3.select(element.parentNode).select('.' + c.cn.cellRect).node().getBoundingClientRect(); - var currentTransform = element.transform.baseVal.consolidate(); - var yPosition = rectBox.top - box.top + (currentTransform ? currentTransform.matrix.f : c.cellPad); - return 'translate(' + xPosition(d, d3.select(element.parentNode).select('.' + c.cn.cellTextHolder).node().getBoundingClientRect().width) + ' ' + yPosition + ')'; - }); - - d.settledY = true; - }; -} - -function xPosition(d, optionalWidth) { - switch(d.align) { - case 'left': return c.cellPad; - case 'right': return d.column.columnWidth - (optionalWidth || 0) - c.cellPad; - case 'center': return (d.column.columnWidth - (optionalWidth || 0)) / 2; - default: return c.cellPad; - } -} - -function setCellHeightAndPositionY(columnCell) { - columnCell - .attr('transform', function(d) { - var headerHeight = d.rowBlocks[0].auxiliaryBlocks.reduce(function(p, n) {return p + rowsHeight(n, Infinity);}, 0); - var l = getBlock(d); - var rowAnchor = rowsHeight(l, d.key); - var yOffset = rowAnchor + headerHeight; - return 'translate(0 ' + yOffset + ')'; - }) - .selectAll('.' + c.cn.cellRect) - .attr('height', function(d) {return getRow(getBlock(d), d.key).rowHeight;}); -} - -function firstRowAnchor(blocks, page) { - var total = 0; - for(var i = page - 1; i >= 0; i--) { - total += allRowsHeight(blocks[i]); - } - return total; -} - -function rowsHeight(rowBlock, key) { - var total = 0; - for(var i = 0; i < rowBlock.rows.length && rowBlock.rows[i].rowIndex < key; i++) { - total += rowBlock.rows[i].rowHeight; - } - return total; -} - -function allRowsHeight(rowBlock) { - var cached = rowBlock.allRowsHeight; - - if(cached !== void(0)) { - return cached; - } - - var total = 0; - for(var i = 0; i < rowBlock.rows.length; i++) { - total += rowBlock.rows[i].rowHeight; - } - rowBlock.allRowsHeight = total; - - return total; -} - -function getBlock(d) {return d.rowBlocks[d.page];} -function getRow(l, i) {return l.rows[i - l.firstRowIndex];} - -},{"../../components/color":593,"../../components/drawing":614,"../../lib":719,"../../lib/gup":717,"../../lib/svg_text_utils":743,"./constants":1232,"./data_preparation_helper":1233,"./data_split_helpers":1234,"d3":163}],1238:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var boxAttrs = _dereq_('../box/attributes'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; - -module.exports = { - y: boxAttrs.y, - x: boxAttrs.x, - x0: boxAttrs.x0, - y0: boxAttrs.y0, - name: extendFlat({}, boxAttrs.name, { - - }), - orientation: extendFlat({}, boxAttrs.orientation, { - - }), - - bandwidth: { - valType: 'number', - min: 0, - - editType: 'calc', - - }, - - scalegroup: { - valType: 'string', - - dflt: '', - editType: 'calc', - - }, - scalemode: { - valType: 'enumerated', - values: ['width', 'count'], - dflt: 'width', - - editType: 'calc', - - }, - - spanmode: { - valType: 'enumerated', - values: ['soft', 'hard', 'manual'], - dflt: 'soft', - - editType: 'calc', - - }, - span: { - valType: 'info_array', - items: [ - {valType: 'any', editType: 'calc'}, - {valType: 'any', editType: 'calc'} - ], - - editType: 'calc', - - }, - - line: { - color: { - valType: 'color', - - editType: 'style', - - }, - width: { - valType: 'number', - - min: 0, - dflt: 2, - editType: 'style', - - }, - editType: 'plot' - }, - fillcolor: boxAttrs.fillcolor, - - points: extendFlat({}, boxAttrs.boxpoints, { - - }), - jitter: extendFlat({}, boxAttrs.jitter, { - - }), - pointpos: extendFlat({}, boxAttrs.pointpos, { - - }), - - width: extendFlat({}, boxAttrs.width, { - - }), - - marker: boxAttrs.marker, - text: boxAttrs.text, - hovertext: boxAttrs.hovertext, - hovertemplate: boxAttrs.hovertemplate, - - box: { - visible: { - valType: 'boolean', - dflt: false, - - editType: 'plot', - - }, - width: { - valType: 'number', - min: 0, - max: 1, - dflt: 0.25, - - editType: 'plot', - - }, - fillcolor: { - valType: 'color', - - editType: 'style', - - }, - line: { - color: { - valType: 'color', - - editType: 'style', - - }, - width: { - valType: 'number', - min: 0, - - editType: 'style', - - }, - editType: 'style' - }, - editType: 'plot' - }, - - meanline: { - visible: { - valType: 'boolean', - dflt: false, - - editType: 'plot', - - }, - color: { - valType: 'color', - - editType: 'style', - - }, - width: { - valType: 'number', - min: 0, - - editType: 'style', - - }, - editType: 'plot' - }, - - side: { - valType: 'enumerated', - values: ['both', 'positive', 'negative'], - dflt: 'both', - - editType: 'calc', - - }, - - offsetgroup: boxAttrs.offsetgroup, - alignmentgroup: boxAttrs.alignmentgroup, - - selected: boxAttrs.selected, - unselected: boxAttrs.unselected, - - hoveron: { - valType: 'flaglist', - flags: ['violins', 'points', 'kde'], - dflt: 'violins+points+kde', - extras: ['all'], - - editType: 'style', - - } -}; - -},{"../../lib/extend":710,"../box/attributes":880}],1239:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var boxCalc = _dereq_('../box/calc'); -var helpers = _dereq_('./helpers'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -module.exports = function calc(gd, trace) { - var cd = boxCalc(gd, trace); - - if(cd[0].t.empty) return cd; - - var fullLayout = gd._fullLayout; - var valAxis = Axes.getFromId( - gd, - trace[trace.orientation === 'h' ? 'xaxis' : 'yaxis'] - ); - - var spanMin = Infinity; - var spanMax = -Infinity; - var maxKDE = 0; - var maxCount = 0; - - for(var i = 0; i < cd.length; i++) { - var cdi = cd[i]; - var vals = cdi.pts.map(helpers.extractVal); - - var bandwidth = cdi.bandwidth = calcBandwidth(trace, cdi, vals); - var span = cdi.span = calcSpan(trace, cdi, valAxis, bandwidth); - - if(cdi.min === cdi.max && bandwidth === 0) { - // if span is zero and bandwidth is zero, we want a violin with zero width - span = cdi.span = [cdi.min, cdi.max]; - cdi.density = [{v: 1, t: span[0]}]; - cdi.bandwidth = bandwidth; - maxKDE = Math.max(maxKDE, 1); - } else { - // step that well covers the bandwidth and is multiple of span distance - var dist = span[1] - span[0]; - var n = Math.ceil(dist / (bandwidth / 3)); - var step = dist / n; - - if(!isFinite(step) || !isFinite(n)) { - Lib.error('Something went wrong with computing the violin span'); - cd[0].t.empty = true; - return cd; - } - - var kde = helpers.makeKDE(cdi, trace, vals); - cdi.density = new Array(n); - - for(var k = 0, t = span[0]; t < (span[1] + step / 2); k++, t += step) { - var v = kde(t); - cdi.density[k] = {v: v, t: t}; - maxKDE = Math.max(maxKDE, v); - } - } - - maxCount = Math.max(maxCount, vals.length); - spanMin = Math.min(spanMin, span[0]); - spanMax = Math.max(spanMax, span[1]); - } - - var extremes = Axes.findExtremes(valAxis, [spanMin, spanMax], {padded: true}); - trace._extremes[valAxis._id] = extremes; - - if(trace.width) { - cd[0].t.maxKDE = maxKDE; - } else { - var violinScaleGroupStats = fullLayout._violinScaleGroupStats; - var scaleGroup = trace.scalegroup; - var groupStats = violinScaleGroupStats[scaleGroup]; - - if(groupStats) { - groupStats.maxKDE = Math.max(groupStats.maxKDE, maxKDE); - groupStats.maxCount = Math.max(groupStats.maxCount, maxCount); - } else { - violinScaleGroupStats[scaleGroup] = { - maxKDE: maxKDE, - maxCount: maxCount - }; - } - } - - cd[0].t.labels.kde = Lib._(gd, 'kde:'); - - return cd; -}; - -// Default to Silveman's rule of thumb -// - https://stats.stackexchange.com/a/6671 -// - https://en.wikipedia.org/wiki/Kernel_density_estimation#A_rule-of-thumb_bandwidth_estimator -// - https://github.com/statsmodels/statsmodels/blob/master/statsmodels/nonparametric/bandwidths.py -function silvermanRule(len, ssd, iqr) { - var a = Math.min(ssd, iqr / 1.349); - return 1.059 * a * Math.pow(len, -0.2); -} - -function calcBandwidth(trace, cdi, vals) { - var span = cdi.max - cdi.min; - - // If span is zero - if(!span) { - if(trace.bandwidth) { - return trace.bandwidth; - } else { - // if span is zero and no bandwidth is specified - // it returns zero bandwidth which is a special case - return 0; - } - } - - // Limit how small the bandwidth can be. - // - // Silverman's rule of thumb can be "very" small - // when IQR does a poor job at describing the spread - // of the distribution. - // We also want to limit custom bandwidths - // to not blow up kde computations. - - if(trace.bandwidth) { - return Math.max(trace.bandwidth, span / 1e4); - } else { - var len = vals.length; - var ssd = Lib.stdev(vals, len - 1, cdi.mean); - return Math.max( - silvermanRule(len, ssd, cdi.q3 - cdi.q1), - span / 100 - ); - } -} - -function calcSpan(trace, cdi, valAxis, bandwidth) { - var spanmode = trace.spanmode; - var spanIn = trace.span || []; - var spanTight = [cdi.min, cdi.max]; - var spanLoose = [cdi.min - 2 * bandwidth, cdi.max + 2 * bandwidth]; - var spanOut; - - function calcSpanItem(index) { - var s = spanIn[index]; - var sc = valAxis.type === 'multicategory' ? - valAxis.r2c(s) : - valAxis.d2c(s, 0, trace[cdi.valLetter + 'calendar']); - return sc === BADNUM ? spanLoose[index] : sc; - } - - if(spanmode === 'soft') { - spanOut = spanLoose; - } else if(spanmode === 'hard') { - spanOut = spanTight; - } else { - spanOut = [calcSpanItem(0), calcSpanItem(1)]; - } - - // to reuse the equal-range-item block - var dummyAx = { - type: 'linear', - range: spanOut - }; - Axes.setConvert(dummyAx); - dummyAx.cleanRange(); - - return spanOut; -} - -},{"../../constants/numerical":695,"../../lib":719,"../../plots/cartesian/axes":767,"../box/calc":881,"./helpers":1242}],1240:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var setPositionOffset = _dereq_('../box/cross_trace_calc').setPositionOffset; -var orientations = ['v', 'h']; - -module.exports = function crossTraceCalc(gd, plotinfo) { - var calcdata = gd.calcdata; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - for(var i = 0; i < orientations.length; i++) { - var orientation = orientations[i]; - var posAxis = orientation === 'h' ? ya : xa; - var violinList = []; - - for(var j = 0; j < calcdata.length; j++) { - var cd = calcdata[j]; - var t = cd[0].t; - var trace = cd[0].trace; - - if(trace.visible === true && trace.type === 'violin' && - !t.empty && - trace.orientation === orientation && - trace.xaxis === xa._id && - trace.yaxis === ya._id - ) { - violinList.push(j); - } - } - - setPositionOffset('violin', gd, violinList, posAxis); - } -}; - -},{"../box/cross_trace_calc":882}],1241:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Color = _dereq_('../../components/color'); - -var boxDefaults = _dereq_('../box/defaults'); -var attributes = _dereq_('./attributes'); - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - function coerce2(attr, dflt) { - return Lib.coerce2(traceIn, traceOut, attributes, attr, dflt); - } - - boxDefaults.handleSampleDefaults(traceIn, traceOut, coerce, layout); - if(traceOut.visible === false) return; - - coerce('bandwidth'); - coerce('side'); - - var width = coerce('width'); - if(!width) { - coerce('scalegroup', traceOut.name); - coerce('scalemode'); - } - - var span = coerce('span'); - var spanmodeDflt; - if(Array.isArray(span)) spanmodeDflt = 'manual'; - coerce('spanmode', spanmodeDflt); - - var lineColor = coerce('line.color', (traceIn.marker || {}).color || defaultColor); - var lineWidth = coerce('line.width'); - var fillColor = coerce('fillcolor', Color.addOpacity(traceOut.line.color, 0.5)); - - boxDefaults.handlePointsDefaults(traceIn, traceOut, coerce, {prefix: ''}); - - var boxWidth = coerce2('box.width'); - var boxFillColor = coerce2('box.fillcolor', fillColor); - var boxLineColor = coerce2('box.line.color', lineColor); - var boxLineWidth = coerce2('box.line.width', lineWidth); - var boxVisible = coerce('box.visible', Boolean(boxWidth || boxFillColor || boxLineColor || boxLineWidth)); - if(!boxVisible) traceOut.box = {visible: false}; - - var meanLineColor = coerce2('meanline.color', lineColor); - var meanLineWidth = coerce2('meanline.width', lineWidth); - var meanLineVisible = coerce('meanline.visible', Boolean(meanLineColor || meanLineWidth)); - if(!meanLineVisible) traceOut.meanline = {visible: false}; -}; - -},{"../../components/color":593,"../../lib":719,"../box/defaults":883,"./attributes":1238}],1242:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -// Maybe add kernels more down the road, -// but note that the default `spanmode: 'soft'` bounds might have -// to become kernel-dependent -var kernels = { - gaussian: function(v) { - return (1 / Math.sqrt(2 * Math.PI)) * Math.exp(-0.5 * v * v); - } -}; - -exports.makeKDE = function(calcItem, trace, vals) { - var len = vals.length; - var kernel = kernels.gaussian; - var bandwidth = calcItem.bandwidth; - var factor = 1 / (len * bandwidth); - - // don't use Lib.aggNums to skip isNumeric checks - return function(x) { - var sum = 0; - for(var i = 0; i < len; i++) { - sum += kernel((x - vals[i]) / bandwidth); - } - return factor * sum; - }; -}; - -exports.getPositionOnKdePath = function(calcItem, trace, valuePx) { - var posLetter, valLetter; - - if(trace.orientation === 'h') { - posLetter = 'y'; - valLetter = 'x'; - } else { - posLetter = 'x'; - valLetter = 'y'; - } - - var pointOnPath = Lib.findPointOnPath( - calcItem.path, - valuePx, - valLetter, - {pathLength: calcItem.pathLength} - ); - - var posCenterPx = calcItem.posCenterPx; - var posOnPath0 = pointOnPath[posLetter]; - var posOnPath1 = trace.side === 'both' ? - 2 * posCenterPx - posOnPath0 : - posCenterPx; - - return [posOnPath0, posOnPath1]; -}; - -exports.getKdeValue = function(calcItem, trace, valueDist) { - var vals = calcItem.pts.map(exports.extractVal); - var kde = exports.makeKDE(calcItem, trace, vals); - return kde(valueDist) / calcItem.posDensityScale; -}; - -exports.extractVal = function(o) { return o.v; }; - -},{"../../lib":719}],1243:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var Axes = _dereq_('../../plots/cartesian/axes'); -var boxHoverPoints = _dereq_('../box/hover'); -var helpers = _dereq_('./helpers'); - -module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLayer) { - var cd = pointData.cd; - var trace = cd[0].trace; - var hoveron = trace.hoveron; - var hasHoveronViolins = hoveron.indexOf('violins') !== -1; - var hasHoveronKDE = hoveron.indexOf('kde') !== -1; - var closeData = []; - var closePtData; - var violinLineAttrs; - - if(hasHoveronViolins || hasHoveronKDE) { - var closeBoxData = boxHoverPoints.hoverOnBoxes(pointData, xval, yval, hovermode); - - if(hasHoveronKDE && closeBoxData.length > 0) { - var xa = pointData.xa; - var ya = pointData.ya; - var pLetter, vLetter, pAxis, vAxis, vVal; - - if(trace.orientation === 'h') { - vVal = xval; - pLetter = 'y'; - pAxis = ya; - vLetter = 'x'; - vAxis = xa; - } else { - vVal = yval; - pLetter = 'x'; - pAxis = xa; - vLetter = 'y'; - vAxis = ya; - } - - var di = cd[pointData.index]; - - if(vVal >= di.span[0] && vVal <= di.span[1]) { - var kdePointData = Lib.extendFlat({}, pointData); - var vValPx = vAxis.c2p(vVal, true); - var kdeVal = helpers.getKdeValue(di, trace, vVal); - var pOnPath = helpers.getPositionOnKdePath(di, trace, vValPx); - var paOffset = pAxis._offset; - var paLength = pAxis._length; - - kdePointData[pLetter + '0'] = pOnPath[0]; - kdePointData[pLetter + '1'] = pOnPath[1]; - kdePointData[vLetter + '0'] = kdePointData[vLetter + '1'] = vValPx; - kdePointData[vLetter + 'Label'] = vLetter + ': ' + Axes.hoverLabelText(vAxis, vVal) + ', ' + cd[0].t.labels.kde + ' ' + kdeVal.toFixed(3); - - // move the spike to the KDE point - kdePointData.spikeDistance = closeBoxData[0].spikeDistance; - var spikePosAttr = pLetter + 'Spike'; - kdePointData[spikePosAttr] = closeBoxData[0][spikePosAttr]; - closeBoxData[0].spikeDistance = undefined; - closeBoxData[0][spikePosAttr] = undefined; - - // no hovertemplate support yet - kdePointData.hovertemplate = false; - - closeData.push(kdePointData); - - violinLineAttrs = {stroke: pointData.color}; - violinLineAttrs[pLetter + '1'] = Lib.constrain(paOffset + pOnPath[0], paOffset, paOffset + paLength); - violinLineAttrs[pLetter + '2'] = Lib.constrain(paOffset + pOnPath[1], paOffset, paOffset + paLength); - violinLineAttrs[vLetter + '1'] = violinLineAttrs[vLetter + '2'] = vAxis._offset + vValPx; - } - } - - if(hasHoveronViolins) { - closeData = closeData.concat(closeBoxData); - } - } - - if(hoveron.indexOf('points') !== -1) { - closePtData = boxHoverPoints.hoverOnPoints(pointData, xval, yval); - } - - // update violin line (if any) - var violinLine = hoverLayer.selectAll('.violinline-' + trace.uid) - .data(violinLineAttrs ? [0] : []); - violinLine.enter().append('line') - .classed('violinline-' + trace.uid, true) - .attr('stroke-width', 1.5); - violinLine.exit().remove(); - violinLine.attr(violinLineAttrs); - - // same combine logic as box hoverPoints - if(hovermode === 'closest') { - if(closePtData) return [closePtData]; - return closeData; - } - if(closePtData) { - closeData.push(closePtData); - return closeData; - } - return closeData; -}; - -},{"../../lib":719,"../../plots/cartesian/axes":767,"../box/hover":885,"./helpers":1242}],1244:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('./layout_attributes'), - supplyDefaults: _dereq_('./defaults'), - crossTraceDefaults: _dereq_('../box/defaults').crossTraceDefaults, - supplyLayoutDefaults: _dereq_('./layout_defaults'), - calc: _dereq_('./calc'), - crossTraceCalc: _dereq_('./cross_trace_calc'), - plot: _dereq_('./plot'), - style: _dereq_('./style'), - styleOnSelect: _dereq_('../scatter/style').styleOnSelect, - hoverPoints: _dereq_('./hover'), - selectPoints: _dereq_('../box/select'), - - moduleType: 'trace', - name: 'violin', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['cartesian', 'svg', 'symbols', 'oriented', 'box-violin', 'showLegend', 'violinLayout', 'zoomScale'], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"../box/defaults":883,"../box/select":890,"../scatter/style":1134,"./attributes":1238,"./calc":1239,"./cross_trace_calc":1240,"./defaults":1241,"./hover":1243,"./layout_attributes":1245,"./layout_defaults":1246,"./plot":1247,"./style":1248}],1245:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var boxLayoutAttrs = _dereq_('../box/layout_attributes'); -var extendFlat = _dereq_('../../lib').extendFlat; - -module.exports = { - violinmode: extendFlat({}, boxLayoutAttrs.boxmode, { - - }), - violingap: extendFlat({}, boxLayoutAttrs.boxgap, { - - }), - violingroupgap: extendFlat({}, boxLayoutAttrs.boxgroupgap, { - - }) -}; - -},{"../../lib":719,"../box/layout_attributes":887}],1246:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var layoutAttributes = _dereq_('./layout_attributes'); -var boxLayoutDefaults = _dereq_('../box/layout_defaults'); - -module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - boxLayoutDefaults._supply(layoutIn, layoutOut, fullData, coerce, 'violin'); -}; - -},{"../../lib":719,"../box/layout_defaults":888,"./layout_attributes":1245}],1247:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../../components/drawing'); - -var boxPlot = _dereq_('../box/plot'); -var linePoints = _dereq_('../scatter/line_points'); -var helpers = _dereq_('./helpers'); - -module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) { - var fullLayout = gd._fullLayout; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - function makePath(pts) { - var segments = linePoints(pts, { - xaxis: xa, - yaxis: ya, - connectGaps: true, - baseTolerance: 0.75, - shape: 'spline', - simplify: true - }); - return Drawing.smoothopen(segments[0], 1); - } - - Lib.makeTraceGroups(violinLayer, cdViolins, 'trace violins').each(function(cd) { - var plotGroup = d3.select(this); - var cd0 = cd[0]; - var t = cd0.t; - var trace = cd0.trace; - - if(trace.visible !== true || t.empty) { - plotGroup.remove(); - return; - } - - var bPos = t.bPos; - var bdPos = t.bdPos; - var valAxis = plotinfo[t.valLetter + 'axis']; - var posAxis = plotinfo[t.posLetter + 'axis']; - var hasBothSides = trace.side === 'both'; - var hasPositiveSide = hasBothSides || trace.side === 'positive'; - var hasNegativeSide = hasBothSides || trace.side === 'negative'; - - var violins = plotGroup.selectAll('path.violin').data(Lib.identity); - - violins.enter().append('path') - .style('vector-effect', 'non-scaling-stroke') - .attr('class', 'violin'); - - violins.exit().remove(); - - violins.each(function(d) { - var pathSel = d3.select(this); - var density = d.density; - var len = density.length; - var posCenter = d.pos + bPos; - var posCenterPx = posAxis.c2p(posCenter); - - var scale; - if(trace.width) { - scale = t.maxKDE / bdPos; - } else { - var groupStats = fullLayout._violinScaleGroupStats[trace.scalegroup]; - scale = trace.scalemode === 'count' ? - (groupStats.maxKDE / bdPos) * (groupStats.maxCount / d.pts.length) : - groupStats.maxKDE / bdPos; - } - - var pathPos, pathNeg, path; - var i, k, pts, pt; - - if(hasPositiveSide) { - pts = new Array(len); - for(i = 0; i < len; i++) { - pt = pts[i] = {}; - pt[t.posLetter] = posCenter + (density[i].v / scale); - pt[t.valLetter] = density[i].t; - } - pathPos = makePath(pts); - } - - if(hasNegativeSide) { - pts = new Array(len); - for(k = 0, i = len - 1; k < len; k++, i--) { - pt = pts[k] = {}; - pt[t.posLetter] = posCenter - (density[i].v / scale); - pt[t.valLetter] = density[i].t; - } - pathNeg = makePath(pts); - } - - if(hasBothSides) { - path = pathPos + 'L' + pathNeg.substr(1) + 'Z'; - } else { - var startPt = [posCenterPx, valAxis.c2p(density[0].t)]; - var endPt = [posCenterPx, valAxis.c2p(density[len - 1].t)]; - - if(trace.orientation === 'h') { - startPt.reverse(); - endPt.reverse(); - } - - if(hasPositiveSide) { - path = 'M' + startPt + 'L' + pathPos.substr(1) + 'L' + endPt; - } else { - path = 'M' + endPt + 'L' + pathNeg.substr(1) + 'L' + startPt; - } - } - pathSel.attr('d', path); - - // save a few things used in getPositionOnKdePath, getKdeValue - // on hover and for meanline draw block below - d.posCenterPx = posCenterPx; - d.posDensityScale = scale * bdPos; - d.path = pathSel.node(); - d.pathLength = d.path.getTotalLength() / (hasBothSides ? 2 : 1); - }); - - var boxAttrs = trace.box; - var boxWidth = boxAttrs.width; - var boxLineWidth = (boxAttrs.line || {}).width; - var bdPosScaled; - var bPosPxOffset; - - if(hasBothSides) { - bdPosScaled = bdPos * boxWidth; - bPosPxOffset = 0; - } else if(hasPositiveSide) { - bdPosScaled = [0, bdPos * boxWidth / 2]; - bPosPxOffset = -boxLineWidth; - } else { - bdPosScaled = [bdPos * boxWidth / 2, 0]; - bPosPxOffset = boxLineWidth; - } - - // inner box - boxPlot.plotBoxAndWhiskers(plotGroup, {pos: posAxis, val: valAxis}, trace, { - bPos: bPos, - bdPos: bdPosScaled, - bPosPxOffset: bPosPxOffset - }); - - // meanline insider box - boxPlot.plotBoxMean(plotGroup, {pos: posAxis, val: valAxis}, trace, { - bPos: bPos, - bdPos: bdPosScaled, - bPosPxOffset: bPosPxOffset - }); - - var fn; - if(!trace.box.visible && trace.meanline.visible) { - fn = Lib.identity; - } - - // N.B. use different class name than boxPlot.plotBoxMean, - // to avoid selectAll conflict - var meanPaths = plotGroup.selectAll('path.meanline').data(fn || []); - meanPaths.enter().append('path') - .attr('class', 'meanline') - .style('fill', 'none') - .style('vector-effect', 'non-scaling-stroke'); - meanPaths.exit().remove(); - meanPaths.each(function(d) { - var v = valAxis.c2p(d.mean, true); - var p = helpers.getPositionOnKdePath(d, trace, v); - - d3.select(this).attr('d', - trace.orientation === 'h' ? - 'M' + v + ',' + p[0] + 'V' + p[1] : - 'M' + p[0] + ',' + v + 'H' + p[1] - ); - }); - - boxPlot.plotPoints(plotGroup, {x: xa, y: ya}, trace, t); - }); -}; - -},{"../../components/drawing":614,"../../lib":719,"../box/plot":889,"../scatter/line_points":1125,"./helpers":1242,"d3":163}],1248:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Color = _dereq_('../../components/color'); -var stylePoints = _dereq_('../scatter/style').stylePoints; - -module.exports = function style(gd) { - var s = d3.select(gd).selectAll('g.trace.violins'); - - s.style('opacity', function(d) { return d[0].trace.opacity; }); - - s.each(function(d) { - var trace = d[0].trace; - var sel = d3.select(this); - var box = trace.box || {}; - var boxLine = box.line || {}; - var meanline = trace.meanline || {}; - var meanLineWidth = meanline.width; - - sel.selectAll('path.violin') - .style('stroke-width', trace.line.width + 'px') - .call(Color.stroke, trace.line.color) - .call(Color.fill, trace.fillcolor); - - sel.selectAll('path.box') - .style('stroke-width', boxLine.width + 'px') - .call(Color.stroke, boxLine.color) - .call(Color.fill, box.fillcolor); - - var meanLineStyle = { - 'stroke-width': meanLineWidth + 'px', - 'stroke-dasharray': (2 * meanLineWidth) + 'px,' + meanLineWidth + 'px' - }; - - sel.selectAll('path.mean') - .style(meanLineStyle) - .call(Color.stroke, meanline.color); - - sel.selectAll('path.meanline') - .style(meanLineStyle) - .call(Color.stroke, meanline.color); - - stylePoints(sel, trace, gd); - }); -}; - -},{"../../components/color":593,"../scatter/style":1134,"d3":163}],1249:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var colorScaleAttrs = _dereq_('../../components/colorscale/attributes'); -var isosurfaceAttrs = _dereq_('../isosurface/attributes'); -var baseAttrs = _dereq_('../../plots/attributes'); - -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll; - -var attrs = module.exports = overrideAll(extendFlat({ - x: isosurfaceAttrs.x, - y: isosurfaceAttrs.y, - z: isosurfaceAttrs.z, - value: isosurfaceAttrs.value, - isomin: isosurfaceAttrs.isomin, - isomax: isosurfaceAttrs.isomax, - surface: isosurfaceAttrs.surface, - spaceframe: { - show: { - valType: 'boolean', - - dflt: false, - - }, - fill: { - valType: 'number', - - min: 0, - max: 1, - dflt: 1, - - } - }, - - slices: isosurfaceAttrs.slices, - caps: isosurfaceAttrs.caps, - text: isosurfaceAttrs.text, - hovertext: isosurfaceAttrs.hovertext, - hovertemplate: isosurfaceAttrs.hovertemplate -}, - -colorScaleAttrs('', { - colorAttr: '`value`', - showScaleDflt: true, - editTypeOverride: 'calc' -}), { - - colorbar: isosurfaceAttrs.colorbar, - opacity: isosurfaceAttrs.opacity, - opacityscale: { - valType: 'any', - - editType: 'calc', - - }, - - lightposition: isosurfaceAttrs.lightposition, - lighting: isosurfaceAttrs.lighting, - flatshading: isosurfaceAttrs.flatshading, - contour: isosurfaceAttrs.contour, - - hoverinfo: extendFlat({}, baseAttrs.hoverinfo) -}), 'calc', 'nested'); - -attrs.x.editType = attrs.y.editType = attrs.z.editType = attrs.value.editType = 'calc+clearAxisTypes'; -attrs.transforms = undefined; - -},{"../../components/colorscale/attributes":600,"../../lib/extend":710,"../../plot_api/edit_types":750,"../../plots/attributes":764,"../isosurface/attributes":1048}],1250:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var createMesh = _dereq_('gl-mesh3d'); - -var parseColorScale = _dereq_('../../lib/gl_format_color').parseColorScale; -var str2RgbaArray = _dereq_('../../lib/str2rgbarray'); -var extractOpts = _dereq_('../../components/colorscale').extractOpts; -var zip3 = _dereq_('../../plots/gl3d/zip3'); - -var findNearestOnAxis = _dereq_('../isosurface/convert').findNearestOnAxis; -var generateIsoMeshes = _dereq_('../isosurface/convert').generateIsoMeshes; - -function VolumeTrace(scene, mesh, uid) { - this.scene = scene; - this.uid = uid; - this.mesh = mesh; - this.name = ''; - this.data = null; - this.showContour = false; -} - -var proto = VolumeTrace.prototype; - -proto.handlePick = function(selection) { - if(selection.object === this.mesh) { - var rawId = selection.data.index; - - var x = this.data._x[rawId]; - var y = this.data._y[rawId]; - var z = this.data._z[rawId]; - - var height = this.data._Ys.length; - var depth = this.data._Zs.length; - - var i = findNearestOnAxis(x, this.data._Xs).id; - var j = findNearestOnAxis(y, this.data._Ys).id; - var k = findNearestOnAxis(z, this.data._Zs).id; - - var selectIndex = selection.index = k + depth * j + depth * height * i; - - selection.traceCoordinate = [ - this.data._x[selectIndex], - this.data._y[selectIndex], - this.data._z[selectIndex], - this.data.value[selectIndex] - ]; - - var text = this.data.hovertext || this.data.text; - if(Array.isArray(text) && text[selectIndex] !== undefined) { - selection.textLabel = text[selectIndex]; - } else if(text) { - selection.textLabel = text; - } - - return true; - } -}; - -proto.update = function(data) { - var scene = this.scene; - var layout = scene.fullSceneLayout; - - this.data = generateIsoMeshes(data); - - // Unpack position data - function toDataCoords(axis, coord, scale, calendar) { - return coord.map(function(x) { - return axis.d2l(x, 0, calendar) * scale; - }); - } - - var positions = zip3( - toDataCoords(layout.xaxis, data._x, scene.dataScale[0], data.xcalendar), - toDataCoords(layout.yaxis, data._y, scene.dataScale[1], data.ycalendar), - toDataCoords(layout.zaxis, data._z, scene.dataScale[2], data.zcalendar)); - - var cells = zip3(data._i, data._j, data._k); - - var config = { - positions: positions, - cells: cells, - lightPosition: [data.lightposition.x, data.lightposition.y, data.lightposition.z], - ambient: data.lighting.ambient, - diffuse: data.lighting.diffuse, - specular: data.lighting.specular, - roughness: data.lighting.roughness, - fresnel: data.lighting.fresnel, - vertexNormalsEpsilon: data.lighting.vertexnormalsepsilon, - faceNormalsEpsilon: data.lighting.facenormalsepsilon, - opacity: data.opacity, - opacityscale: data.opacityscale, - contourEnable: data.contour.show, - contourColor: str2RgbaArray(data.contour.color).slice(0, 3), - contourWidth: data.contour.width, - useFacetNormals: data.flatshading - }; - - var cOpts = extractOpts(data); - config.vertexIntensity = data._intensity; - config.vertexIntensityBounds = [cOpts.min, cOpts.max]; - config.colormap = parseColorScale(data); - - // Update mesh - this.mesh.update(config); -}; - -proto.dispose = function() { - this.scene.glplot.remove(this.mesh); - this.mesh.dispose(); -}; - -function createVolumeTrace(scene, data) { - var gl = scene.glplot.gl; - var mesh = createMesh({gl: gl}); - var result = new VolumeTrace(scene, mesh, data.uid); - - mesh._trace = result; - result.update(data); - scene.glplot.add(mesh); - return result; -} - -module.exports = createVolumeTrace; - -},{"../../components/colorscale":605,"../../lib/gl_format_color":716,"../../lib/str2rgbarray":742,"../../plots/gl3d/zip3":818,"../isosurface/convert":1050,"gl-mesh3d":280}],1251:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var attributes = _dereq_('./attributes'); -var supplyIsoDefaults = _dereq_('../isosurface/defaults').supplyIsoDefaults; - -var MIN = 0.1; // Note: often we don't want the data cube to be disappeared - -function createWave(n, minOpacity) { - var arr = []; - var steps = 32; // Max: 256 - for(var i = 0; i < steps; i++) { - var u = i / (steps - 1); - var v = minOpacity + (1 - minOpacity) * (1 - Math.pow(Math.sin(n * u * Math.PI), 2)); - arr.push([ - u, - Math.max(1, Math.min(0, v)) - ]); - } - return arr; -} - -module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - supplyIsoDefaults(traceIn, traceOut, defaultColor, layout, coerce); - - var opacityscale = coerce('opacityscale'); - if(opacityscale === 'max') { - traceOut.opacityscale = [[0, MIN], [1, 1]]; - } else if(opacityscale === 'min') { - traceOut.opacityscale = [[0, 1], [1, MIN]]; - } else if(opacityscale === 'extremes') { - traceOut.opacityscale = createWave(1, MIN); - } else if(!isValidScaleArray(opacityscale)) { - traceOut.opacityscale = undefined; - } -}; - -function isValidScaleArray(scl) { - var highestVal = 0; - - if(!Array.isArray(scl) || scl.length < 2) return false; - - if(!scl[0] || !scl[scl.length - 1]) return false; - - if(+scl[0][0] !== 0 || +scl[scl.length - 1][0] !== 1) return false; - - for(var i = 0; i < scl.length; i++) { - var si = scl[i]; - - if(si.length !== 2 || +si[0] < highestVal) { - return false; - } - - highestVal = +si[0]; - } - - return true; -} - -},{"../../lib":719,"../isosurface/defaults":1051,"./attributes":1249}],1252:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - supplyDefaults: _dereq_('./defaults'), - calc: _dereq_('../isosurface/calc'), - colorbar: { - min: 'cmin', - max: 'cmax' - }, - plot: _dereq_('./convert'), - - moduleType: 'trace', - name: 'volume', - basePlotModule: _dereq_('../../plots/gl3d'), - categories: ['gl3d'], - meta: { - - } -}; - -},{"../../plots/gl3d":807,"../isosurface/calc":1049,"./attributes":1249,"./convert":1250,"./defaults":1251}],1253:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var barAttrs = _dereq_('../bar/attributes'); -var lineAttrs = _dereq_('../scatter/attributes').line; -var plotAttrs = _dereq_('../../plots/attributes'); -var hovertemplateAttrs = _dereq_('../../components/fx/hovertemplate_attributes'); -var constants = _dereq_('./constants'); -var extendFlat = _dereq_('../../lib/extend').extendFlat; -var Color = _dereq_('../../components/color'); - -function directionAttrs(dirTxt) { - return { - marker: { - color: extendFlat({}, barAttrs.marker.color, { - arrayOk: false, - editType: 'style', - - }), - line: { - color: extendFlat({}, barAttrs.marker.line.color, { - arrayOk: false, - editType: 'style', - - }), - width: extendFlat({}, barAttrs.marker.line.width, { - arrayOk: false, - editType: 'style', - - }), - editType: 'style', - }, - editType: 'style' - }, - editType: 'style' - }; -} - -module.exports = { - measure: { - valType: 'data_array', - dflt: [], - - editType: 'calc', - - }, - - base: { - valType: 'number', - dflt: null, - arrayOk: false, - - editType: 'calc', - - }, - - x: barAttrs.x, - x0: barAttrs.x0, - dx: barAttrs.dx, - y: barAttrs.y, - y0: barAttrs.y0, - dy: barAttrs.dy, - - hovertext: barAttrs.hovertext, - hovertemplate: hovertemplateAttrs({}, { - keys: constants.eventDataKeys - }), - - hoverinfo: extendFlat({}, plotAttrs.hoverinfo, { - flags: ['name', 'x', 'y', 'text', 'initial', 'delta', 'final'] - }), - - textinfo: { - valType: 'flaglist', - flags: ['label', 'text', 'initial', 'delta', 'final'], - extras: ['none'], - - editType: 'plot', - arrayOk: false, - - }, - - text: barAttrs.text, - textposition: barAttrs.textposition, - insidetextanchor: barAttrs.insidetextanchor, - textangle: barAttrs.textangle, - textfont: barAttrs.textfont, - insidetextfont: barAttrs.insidetextfont, - outsidetextfont: barAttrs.outsidetextfont, - constraintext: barAttrs.constraintext, - - cliponaxis: barAttrs.cliponaxis, - orientation: barAttrs.orientation, - - offset: barAttrs.offset, - width: barAttrs.width, - - increasing: directionAttrs('increasing'), - decreasing: directionAttrs('decreasing'), - totals: directionAttrs('intermediate sums and total'), - - connector: { - line: { - color: extendFlat({}, lineAttrs.color, {dflt: Color.defaultLine}), - width: extendFlat({}, lineAttrs.width, { - editType: 'plot', // i.e. to adjust bars is mode: 'between'. See https://github.com/plotly/plotly.js/issues/3787 - }), - dash: lineAttrs.dash, - editType: 'plot' - }, - mode: { - valType: 'enumerated', - values: ['spanning', 'between'], - dflt: 'between', - - editType: 'plot', - - }, - visible: { - valType: 'boolean', - dflt: true, - - editType: 'plot', - - }, - editType: 'plot' - }, - - offsetgroup: barAttrs.offsetgroup, - alignmentgroup: barAttrs.alignmentgroup -}; - -},{"../../components/color":593,"../../components/fx/hovertemplate_attributes":631,"../../lib/extend":710,"../../plots/attributes":764,"../bar/attributes":857,"../scatter/attributes":1112,"./constants":1255}],1254:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../../plots/cartesian/axes'); -var mergeArray = _dereq_('../../lib').mergeArray; -var calcSelection = _dereq_('../scatter/calc_selection'); -var BADNUM = _dereq_('../../constants/numerical').BADNUM; - -function isAbsolute(a) { - return (a === 'a' || a === 'absolute'); -} - -function isTotal(a) { - return (a === 't' || a === 'total'); -} - -module.exports = function calc(gd, trace) { - var xa = Axes.getFromId(gd, trace.xaxis || 'x'); - var ya = Axes.getFromId(gd, trace.yaxis || 'y'); - var size, pos; - - if(trace.orientation === 'h') { - size = xa.makeCalcdata(trace, 'x'); - pos = ya.makeCalcdata(trace, 'y'); - } else { - size = ya.makeCalcdata(trace, 'y'); - pos = xa.makeCalcdata(trace, 'x'); - } - - // create the "calculated data" to plot - var serieslen = Math.min(pos.length, size.length); - var cd = new Array(serieslen); - - // set position and size (as well as for waterfall total size) - var previousSum = 0; - var newSize; - // trace-wide flags - var hasTotals = false; - - for(var i = 0; i < serieslen; i++) { - var amount = size[i] || 0; - - var connectToNext = false; - if(size[i] !== BADNUM || isTotal(trace.measure[i]) || isAbsolute(trace.measure[i])) { - if(i + 1 < serieslen && (size[i + 1] !== BADNUM || isTotal(trace.measure[i + 1]) || isAbsolute(trace.measure[i + 1]))) { - connectToNext = true; - } - } - - var cdi = cd[i] = { - i: i, - p: pos[i], - s: amount, - rawS: amount, - cNext: connectToNext - }; - - if(isAbsolute(trace.measure[i])) { - previousSum = cdi.s; - - cdi.isSum = true; - cdi.dir = 'totals'; - cdi.s = previousSum; - } else if(isTotal(trace.measure[i])) { - cdi.isSum = true; - cdi.dir = 'totals'; - cdi.s = previousSum; - } else { - // default: relative - cdi.isSum = false; - cdi.dir = cdi.rawS < 0 ? 'decreasing' : 'increasing'; - newSize = cdi.s; - cdi.s = previousSum + newSize; - previousSum += newSize; - } - - if(cdi.dir === 'totals') { - hasTotals = true; - } - - if(trace.ids) { - cdi.id = String(trace.ids[i]); - } - - cdi.v = (trace.base || 0) + previousSum; - } - - if(cd.length) cd[0].hasTotals = hasTotals; - - mergeArray(trace.text, cd, 'tx'); - mergeArray(trace.hovertext, cd, 'htx'); - calcSelection(cd, trace); - - return cd; -}; - -},{"../../constants/numerical":695,"../../lib":719,"../../plots/cartesian/axes":767,"../scatter/calc_selection":1114}],1255:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - eventDataKeys: [ - 'initial', - 'delta', - 'final' - ] -}; - -},{}],1256:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var setGroupPositions = _dereq_('../bar/cross_trace_calc').setGroupPositions; - -module.exports = function crossTraceCalc(gd, plotinfo) { - var fullLayout = gd._fullLayout; - var fullData = gd._fullData; - var calcdata = gd.calcdata; - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - var waterfalls = []; - var waterfallsVert = []; - var waterfallsHorz = []; - var cd, i; - - for(i = 0; i < fullData.length; i++) { - var fullTrace = fullData[i]; - - if( - fullTrace.visible === true && - fullTrace.xaxis === xa._id && - fullTrace.yaxis === ya._id && - fullTrace.type === 'waterfall' - ) { - cd = calcdata[i]; - - if(fullTrace.orientation === 'h') { - waterfallsHorz.push(cd); - } else { - waterfallsVert.push(cd); - } - - waterfalls.push(cd); - } - } - - var opts = { - mode: fullLayout.waterfallmode, - norm: fullLayout.waterfallnorm, - gap: fullLayout.waterfallgap, - groupgap: fullLayout.waterfallgroupgap - }; - - setGroupPositions(gd, xa, ya, waterfallsVert, opts); - setGroupPositions(gd, ya, xa, waterfallsHorz, opts); - - for(i = 0; i < waterfalls.length; i++) { - cd = waterfalls[i]; - - for(var j = 0; j < cd.length; j++) { - var di = cd[j]; - - if(di.isSum === false) { - di.s0 += (j === 0) ? 0 : cd[j - 1].s; - } - - if(j + 1 < cd.length) { - cd[j].nextP0 = cd[j + 1].p0; - cd[j].nextS0 = cd[j + 1].s0; - } - } - } -}; - -},{"../bar/cross_trace_calc":860}],1257:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); - -var handleGroupingDefaults = _dereq_('../bar/defaults').handleGroupingDefaults; -var handleText = _dereq_('../bar/defaults').handleText; -var handleXYDefaults = _dereq_('../scatter/xy_defaults'); -var attributes = _dereq_('./attributes'); -var Color = _dereq_('../../components/color'); -var delta = _dereq_('../../constants/delta.js'); - -var INCREASING_COLOR = delta.INCREASING.COLOR; -var DECREASING_COLOR = delta.DECREASING.COLOR; -var TOTALS_COLOR = '#4499FF'; - -function handleDirection(coerce, direction, defaultColor) { - coerce(direction + '.marker.color', defaultColor); - coerce(direction + '.marker.line.color', Color.defaultLine); - coerce(direction + '.marker.line.width'); -} - -function supplyDefaults(traceIn, traceOut, defaultColor, layout) { - function coerce(attr, dflt) { - return Lib.coerce(traceIn, traceOut, attributes, attr, dflt); - } - - var len = handleXYDefaults(traceIn, traceOut, layout, coerce); - if(!len) { - traceOut.visible = false; - return; - } - - coerce('measure'); - - coerce('orientation', (traceOut.x && !traceOut.y) ? 'h' : 'v'); - coerce('base'); - coerce('offset'); - coerce('width'); - - coerce('text'); - - coerce('hovertext'); - coerce('hovertemplate'); - - var textposition = coerce('textposition'); - handleText(traceIn, traceOut, layout, coerce, textposition, { - moduleHasSelected: false, - moduleHasUnselected: false, - moduleHasConstrain: true, - moduleHasCliponaxis: true, - moduleHasTextangle: true, - moduleHasInsideanchor: true - }); - - - if(traceOut.textposition !== 'none') { - coerce('textinfo'); - } - - handleDirection(coerce, 'increasing', INCREASING_COLOR); - handleDirection(coerce, 'decreasing', DECREASING_COLOR); - handleDirection(coerce, 'totals', TOTALS_COLOR); - - var connectorVisible = coerce('connector.visible'); - if(connectorVisible) { - coerce('connector.mode'); - var connectorLineWidth = coerce('connector.line.width'); - if(connectorLineWidth) { - coerce('connector.line.color'); - coerce('connector.line.dash'); - } - } -} - -function crossTraceDefaults(fullData, fullLayout) { - var traceIn, traceOut; - - function coerce(attr) { - return Lib.coerce(traceOut._input, traceOut, attributes, attr); - } - - if(fullLayout.waterfallmode === 'group') { - for(var i = 0; i < fullData.length; i++) { - traceOut = fullData[i]; - traceIn = traceOut._input; - - handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); - } - } -} - -module.exports = { - supplyDefaults: supplyDefaults, - crossTraceDefaults: crossTraceDefaults -}; - -},{"../../components/color":593,"../../constants/delta.js":689,"../../lib":719,"../bar/defaults":861,"../scatter/xy_defaults":1137,"./attributes":1253}],1258:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = function eventData(out, pt /* , trace, cd, pointNumber */) { - // standard cartesian event data - out.x = 'xVal' in pt ? pt.xVal : pt.x; - out.y = 'yVal' in pt ? pt.yVal : pt.y; - - // for funnel - if('initial' in pt) out.initial = pt.initial; - if('delta' in pt) out.delta = pt.delta; - if('final' in pt) out.final = pt.final; - - if(pt.xa) out.xaxis = pt.xa; - if(pt.ya) out.yaxis = pt.ya; - - return out; -}; - -},{}],1259:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var hoverLabelText = _dereq_('../../plots/cartesian/axes').hoverLabelText; -var opacity = _dereq_('../../components/color').opacity; -var hoverOnBars = _dereq_('../bar/hover').hoverOnBars; -var delta = _dereq_('../../constants/delta.js'); - -var DIRSYMBOL = { - increasing: delta.INCREASING.SYMBOL, - decreasing: delta.DECREASING.SYMBOL -}; - -module.exports = function hoverPoints(pointData, xval, yval, hovermode) { - var point = hoverOnBars(pointData, xval, yval, hovermode); - if(!point) return; - - var cd = point.cd; - var trace = cd[0].trace; - var isHorizontal = (trace.orientation === 'h'); - - var vAxis = isHorizontal ? pointData.xa : pointData.ya; - - function formatNumber(a) { - return hoverLabelText(vAxis, a); - } - - // the closest data point - var index = point.index; - var di = cd[index]; - - var size = (di.isSum) ? di.b + di.s : di.rawS; - - if(!di.isSum) { - point.initial = di.b + di.s - size; - point.delta = size; - point.final = point.initial + point.delta; - - var v = formatNumber(Math.abs(point.delta)); - point.deltaLabel = size < 0 ? '(' + v + ')' : v; - point.finalLabel = formatNumber(point.final); - point.initialLabel = formatNumber(point.initial); - } - - var hoverinfo = di.hi || trace.hoverinfo; - var text = []; - if(hoverinfo && hoverinfo !== 'none' && hoverinfo !== 'skip') { - var isAll = (hoverinfo === 'all'); - var parts = hoverinfo.split('+'); - - var hasFlag = function(flag) { return isAll || parts.indexOf(flag) !== -1; }; - - if(!di.isSum) { - if(hasFlag('final') && - (isHorizontal ? !hasFlag('x') : !hasFlag('y')) // don't display redundant info. - ) { - text.push(point.finalLabel); - } - if(hasFlag('delta')) { - if(size < 0) { - text.push(point.deltaLabel + ' ' + DIRSYMBOL.decreasing); - } else { - text.push(point.deltaLabel + ' ' + DIRSYMBOL.increasing); - } - } - if(hasFlag('initial')) { - text.push('Initial: ' + point.initialLabel); - } - } - } - - if(text.length) point.extraText = text.join('
'); - - point.color = getTraceColor(trace, di); - - return [point]; -}; - -function getTraceColor(trace, di) { - var cont = trace[di.dir].marker; - var mc = cont.color; - var mlc = cont.line.color; - var mlw = cont.line.width; - if(opacity(mc)) return mc; - else if(opacity(mlc) && mlw) return mlc; -} - -},{"../../components/color":593,"../../constants/delta.js":689,"../../plots/cartesian/axes":767,"../bar/hover":863}],1260:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - attributes: _dereq_('./attributes'), - layoutAttributes: _dereq_('./layout_attributes'), - supplyDefaults: _dereq_('./defaults').supplyDefaults, - crossTraceDefaults: _dereq_('./defaults').crossTraceDefaults, - supplyLayoutDefaults: _dereq_('./layout_defaults'), - calc: _dereq_('./calc'), - crossTraceCalc: _dereq_('./cross_trace_calc'), - plot: _dereq_('./plot'), - style: _dereq_('./style').style, - hoverPoints: _dereq_('./hover'), - eventData: _dereq_('./event_data'), - - selectPoints: _dereq_('../bar/select'), - - moduleType: 'trace', - name: 'waterfall', - basePlotModule: _dereq_('../../plots/cartesian'), - categories: ['bar-like', 'cartesian', 'svg', 'oriented', 'showLegend', 'zoomScale'], - meta: { - - } -}; - -},{"../../plots/cartesian":778,"../bar/select":868,"./attributes":1253,"./calc":1254,"./cross_trace_calc":1256,"./defaults":1257,"./event_data":1258,"./hover":1259,"./layout_attributes":1261,"./layout_defaults":1262,"./plot":1263,"./style":1264}],1261:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -module.exports = { - waterfallmode: { - valType: 'enumerated', - values: ['group', 'overlay'], - dflt: 'group', - - editType: 'calc', - - }, - waterfallgap: { - valType: 'number', - min: 0, - max: 1, - - editType: 'calc', - - }, - waterfallgroupgap: { - valType: 'number', - min: 0, - max: 1, - dflt: 0, - - editType: 'calc', - - } -}; - -},{}],1262:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../../lib'); -var layoutAttributes = _dereq_('./layout_attributes'); - -module.exports = function(layoutIn, layoutOut, fullData) { - var hasTraceType = false; - - function coerce(attr, dflt) { - return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); - } - - for(var i = 0; i < fullData.length; i++) { - var trace = fullData[i]; - - if(trace.visible && trace.type === 'waterfall') { - hasTraceType = true; - break; - } - } - - if(hasTraceType) { - coerce('waterfallmode'); - coerce('waterfallgap', 0.2); - coerce('waterfallgroupgap'); - } -}; - -},{"../../lib":719,"./layout_attributes":1261}],1263:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); -var Lib = _dereq_('../../lib'); -var Drawing = _dereq_('../../components/drawing'); -var barPlot = _dereq_('../bar/plot').plot; - -module.exports = function plot(gd, plotinfo, cdModule, traceLayer) { - var fullLayout = gd._fullLayout; - - barPlot(gd, plotinfo, cdModule, traceLayer, { - mode: fullLayout.waterfallmode, - norm: fullLayout.waterfallmode, - gap: fullLayout.waterfallgap, - groupgap: fullLayout.waterfallgroupgap - }); - - plotConnectors(gd, plotinfo, cdModule, traceLayer); -}; - -function plotConnectors(gd, plotinfo, cdModule, traceLayer) { - var xa = plotinfo.xaxis; - var ya = plotinfo.yaxis; - - Lib.makeTraceGroups(traceLayer, cdModule, 'trace bars').each(function(cd) { - var plotGroup = d3.select(this); - var trace = cd[0].trace; - - var group = Lib.ensureSingle(plotGroup, 'g', 'lines'); - - if(!trace.connector || !trace.connector.visible) { - group.remove(); - return; - } - - var isHorizontal = (trace.orientation === 'h'); - var mode = trace.connector.mode; - - var connectors = group.selectAll('g.line').data(Lib.identity); - - connectors.enter().append('g') - .classed('line', true); - - connectors.exit().remove(); - - var len = connectors.size(); - - connectors.each(function(di, i) { - // don't draw lines between nulls - if(i !== len - 1 && !di.cNext) return; - - var xy = getXY(di, xa, ya, isHorizontal); - var x = xy[0]; - var y = xy[1]; - - var shape = ''; - - if(mode === 'spanning') { - if(!di.isSum && i > 0) { - if(isHorizontal) { - shape += 'M' + x[0] + ',' + y[1] + 'V' + y[0]; - } else { - shape += 'M' + x[1] + ',' + y[0] + 'H' + x[0]; - } - } - } - - if(mode !== 'between') { - if(di.isSum || i < len - 1) { - if(isHorizontal) { - shape += 'M' + x[1] + ',' + y[0] + 'V' + y[1]; - } else { - shape += 'M' + x[0] + ',' + y[1] + 'H' + x[1]; - } - } - } - - if(x[2] !== undefined && y[2] !== undefined) { - if(isHorizontal) { - shape += 'M' + x[1] + ',' + y[1] + 'V' + y[2]; - } else { - shape += 'M' + x[1] + ',' + y[1] + 'H' + x[2]; - } - } - - if(shape === '') shape = 'M0,0Z'; - - Lib.ensureSingle(d3.select(this), 'path') - .attr('d', shape) - .call(Drawing.setClipUrl, plotinfo.layerClipId, gd); - }); - }); -} - -function getXY(di, xa, ya, isHorizontal) { - var s = []; - var p = []; - - var sAxis = isHorizontal ? xa : ya; - var pAxis = isHorizontal ? ya : xa; - - s[0] = sAxis.c2p(di.s0, true); - p[0] = pAxis.c2p(di.p0, true); - - s[1] = sAxis.c2p(di.s1, true); - p[1] = pAxis.c2p(di.p1, true); - - s[2] = sAxis.c2p(di.nextS0, true); - p[2] = pAxis.c2p(di.nextP0, true); - - return isHorizontal ? [s, p] : [p, s]; -} - -},{"../../components/drawing":614,"../../lib":719,"../bar/plot":867,"d3":163}],1264:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var d3 = _dereq_('d3'); - -var Drawing = _dereq_('../../components/drawing'); -var Color = _dereq_('../../components/color'); -var DESELECTDIM = _dereq_('../../constants/interactions').DESELECTDIM; - -var styleTextPoints = _dereq_('../bar/style').styleTextPoints; - -function style(gd, cd, sel) { - var s = sel ? sel : d3.select(gd).selectAll('g.waterfalllayer').selectAll('g.trace'); - - s.style('opacity', function(d) { return d[0].trace.opacity; }); - - s.each(function(d) { - var gTrace = d3.select(this); - var trace = d[0].trace; - - gTrace.selectAll('.point > path').each(function(di) { - if(!di.isBlank) { - var cont = trace[di.dir].marker; - - d3.select(this) - .call(Color.fill, cont.color) - .call(Color.stroke, cont.line.color) - .call(Drawing.dashLine, cont.line.dash, cont.line.width) - .style('opacity', trace.selectedpoints && !di.selected ? DESELECTDIM : 1); - } - }); - - styleTextPoints(gTrace, trace, gd); - - gTrace.selectAll('.lines').each(function() { - var cont = trace.connector.line; - - Drawing.lineGroupStyle( - d3.select(this).selectAll('path'), - cont.width, - cont.color, - cont.dash - ); - }); - }); -} - -module.exports = { - style: style -}; - -},{"../../components/color":593,"../../components/drawing":614,"../../constants/interactions":694,"../bar/style":870,"d3":163}],1265:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Axes = _dereq_('../plots/cartesian/axes'); -var Lib = _dereq_('../lib'); -var PlotSchema = _dereq_('../plot_api/plot_schema'); -var pointsAccessorFunction = _dereq_('./helpers').pointsAccessorFunction; -var BADNUM = _dereq_('../constants/numerical').BADNUM; - -exports.moduleType = 'transform'; - -exports.name = 'aggregate'; - -var attrs = exports.attributes = { - enabled: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - }, - groups: { - // TODO: groupby should support string or array grouping this way too - // currently groupby only allows a grouping array - valType: 'string', - strict: true, - noBlank: true, - arrayOk: true, - dflt: 'x', - - editType: 'calc', - - }, - aggregations: { - _isLinkedToArray: 'aggregation', - target: { - valType: 'string', - - editType: 'calc', - - }, - func: { - valType: 'enumerated', - values: ['count', 'sum', 'avg', 'median', 'mode', 'rms', 'stddev', 'min', 'max', 'first', 'last', 'change', 'range'], - dflt: 'first', - - editType: 'calc', - - }, - funcmode: { - valType: 'enumerated', - values: ['sample', 'population'], - dflt: 'sample', - - editType: 'calc', - - }, - enabled: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - }, - editType: 'calc' - }, - editType: 'calc' -}; - -var aggAttrs = attrs.aggregations; - -/** - * Supply transform attributes defaults - * - * @param {object} transformIn - * object linked to trace.transforms[i] with 'func' set to exports.name - * @param {object} traceOut - * the _fullData trace this transform applies to - * @param {object} layout - * the plot's (not-so-full) layout - * @param {object} traceIn - * the input data trace this transform applies to - * - * @return {object} transformOut - * copy of transformIn that contains attribute defaults - */ -exports.supplyDefaults = function(transformIn, traceOut) { - var transformOut = {}; - var i; - - function coerce(attr, dflt) { - return Lib.coerce(transformIn, transformOut, attrs, attr, dflt); - } - - var enabled = coerce('enabled'); - - if(!enabled) return transformOut; - - /* - * Normally _arrayAttrs is calculated during doCalc, but that comes later. - * Anyway this can change due to *count* aggregations (see below) so it's not - * necessarily the same set. - * - * For performance we turn it into an object of truthy values - * we'll use 1 for arrays we haven't aggregated yet, 0 for finished arrays, - * as distinct from undefined which means this array isn't present in the input - * missing arrays can still be aggregate outputs for *count* aggregations. - */ - var arrayAttrArray = PlotSchema.findArrayAttributes(traceOut); - var arrayAttrs = {}; - for(i = 0; i < arrayAttrArray.length; i++) arrayAttrs[arrayAttrArray[i]] = 1; - - var groups = coerce('groups'); - - if(!Array.isArray(groups)) { - if(!arrayAttrs[groups]) { - transformOut.enabled = false; - return transformOut; - } - arrayAttrs[groups] = 0; - } - - var aggregationsIn = transformIn.aggregations || []; - var aggregationsOut = transformOut.aggregations = new Array(aggregationsIn.length); - var aggregationOut; - - function coercei(attr, dflt) { - return Lib.coerce(aggregationsIn[i], aggregationOut, aggAttrs, attr, dflt); - } - - for(i = 0; i < aggregationsIn.length; i++) { - aggregationOut = {_index: i}; - var target = coercei('target'); - var func = coercei('func'); - var enabledi = coercei('enabled'); - - // add this aggregation to the output only if it's the first instance - // of a valid target attribute - or an unused target attribute with "count" - if(enabledi && target && (arrayAttrs[target] || (func === 'count' && arrayAttrs[target] === undefined))) { - if(func === 'stddev') coercei('funcmode'); - - arrayAttrs[target] = 0; - aggregationsOut[i] = aggregationOut; - } else aggregationsOut[i] = {enabled: false, _index: i}; - } - - // any array attributes we haven't yet covered, fill them with the default aggregation - for(i = 0; i < arrayAttrArray.length; i++) { - if(arrayAttrs[arrayAttrArray[i]]) { - aggregationsOut.push({ - target: arrayAttrArray[i], - func: aggAttrs.func.dflt, - enabled: true, - _index: -1 - }); - } - } - - return transformOut; -}; - - -exports.calcTransform = function(gd, trace, opts) { - if(!opts.enabled) return; - - var groups = opts.groups; - - var groupArray = Lib.getTargetArray(trace, {target: groups}); - if(!groupArray) return; - - var i, vi, groupIndex, newGrouping; - - var groupIndices = {}; - var indexToPoints = {}; - var groupings = []; - - var originalPointsAccessor = pointsAccessorFunction(trace.transforms, opts); - - var len = groupArray.length; - if(trace._length) len = Math.min(len, trace._length); - - for(i = 0; i < len; i++) { - vi = groupArray[i]; - groupIndex = groupIndices[vi]; - if(groupIndex === undefined) { - groupIndices[vi] = groupings.length; - newGrouping = [i]; - groupings.push(newGrouping); - indexToPoints[groupIndices[vi]] = originalPointsAccessor(i); - } else { - groupings[groupIndex].push(i); - indexToPoints[groupIndices[vi]] = (indexToPoints[groupIndices[vi]] || []).concat(originalPointsAccessor(i)); - } - } - - opts._indexToPoints = indexToPoints; - - var aggregations = opts.aggregations; - - for(i = 0; i < aggregations.length; i++) { - aggregateOneArray(gd, trace, groupings, aggregations[i]); - } - - if(typeof groups === 'string') { - aggregateOneArray(gd, trace, groupings, { - target: groups, - func: 'first', - enabled: true - }); - } - - trace._length = groupings.length; -}; - -function aggregateOneArray(gd, trace, groupings, aggregation) { - if(!aggregation.enabled) return; - - var attr = aggregation.target; - var targetNP = Lib.nestedProperty(trace, attr); - var arrayIn = targetNP.get(); - var conversions = Axes.getDataConversions(gd, trace, attr, arrayIn); - var func = getAggregateFunction(aggregation, conversions); - - var arrayOut = new Array(groupings.length); - for(var i = 0; i < groupings.length; i++) { - arrayOut[i] = func(arrayIn, groupings[i]); - } - targetNP.set(arrayOut); - - if(aggregation.func === 'count') { - // count does not depend on an input array, so it's likely not part of _arrayAttrs yet - // but after this transform it most definitely *is* an array attribute. - Lib.pushUnique(trace._arrayAttrs, attr); - } -} - -function getAggregateFunction(opts, conversions) { - var func = opts.func; - var d2c = conversions.d2c; - var c2d = conversions.c2d; - - switch(func) { - // count, first, and last don't depend on anything about the data - // point back to pure functions for performance - case 'count': - return count; - case 'first': - return first; - case 'last': - return last; - - case 'sum': - // This will produce output in all cases even though it's nonsensical - // for date or category data. - return function(array, indices) { - var total = 0; - for(var i = 0; i < indices.length; i++) { - var vi = d2c(array[indices[i]]); - if(vi !== BADNUM) total += vi; - } - return c2d(total); - }; - - case 'avg': - // Generally meaningless for category data but it still does something. - return function(array, indices) { - var total = 0; - var cnt = 0; - for(var i = 0; i < indices.length; i++) { - var vi = d2c(array[indices[i]]); - if(vi !== BADNUM) { - total += vi; - cnt++; - } - } - return cnt ? c2d(total / cnt) : BADNUM; - }; - - case 'min': - return function(array, indices) { - var out = Infinity; - for(var i = 0; i < indices.length; i++) { - var vi = d2c(array[indices[i]]); - if(vi !== BADNUM) out = Math.min(out, vi); - } - return (out === Infinity) ? BADNUM : c2d(out); - }; - - case 'max': - return function(array, indices) { - var out = -Infinity; - for(var i = 0; i < indices.length; i++) { - var vi = d2c(array[indices[i]]); - if(vi !== BADNUM) out = Math.max(out, vi); - } - return (out === -Infinity) ? BADNUM : c2d(out); - }; - - case 'range': - return function(array, indices) { - var min = Infinity; - var max = -Infinity; - for(var i = 0; i < indices.length; i++) { - var vi = d2c(array[indices[i]]); - if(vi !== BADNUM) { - min = Math.min(min, vi); - max = Math.max(max, vi); - } - } - return (max === -Infinity || min === Infinity) ? BADNUM : c2d(max - min); - }; - - case 'change': - return function(array, indices) { - var first = d2c(array[indices[0]]); - var last = d2c(array[indices[indices.length - 1]]); - return (first === BADNUM || last === BADNUM) ? BADNUM : c2d(last - first); - }; - - case 'median': - return function(array, indices) { - var sortCalc = []; - for(var i = 0; i < indices.length; i++) { - var vi = d2c(array[indices[i]]); - if(vi !== BADNUM) sortCalc.push(vi); - } - if(!sortCalc.length) return BADNUM; - sortCalc.sort(); - var mid = (sortCalc.length - 1) / 2; - return c2d((sortCalc[Math.floor(mid)] + sortCalc[Math.ceil(mid)]) / 2); - }; - - case 'mode': - return function(array, indices) { - var counts = {}; - var maxCnt = 0; - var out = BADNUM; - for(var i = 0; i < indices.length; i++) { - var vi = d2c(array[indices[i]]); - if(vi !== BADNUM) { - var counti = counts[vi] = (counts[vi] || 0) + 1; - if(counti > maxCnt) { - maxCnt = counti; - out = vi; - } - } - } - return maxCnt ? c2d(out) : BADNUM; - }; - - case 'rms': - return function(array, indices) { - var total = 0; - var cnt = 0; - for(var i = 0; i < indices.length; i++) { - var vi = d2c(array[indices[i]]); - if(vi !== BADNUM) { - total += vi * vi; - cnt++; - } - } - return cnt ? c2d(Math.sqrt(total / cnt)) : BADNUM; - }; - - case 'stddev': - return function(array, indices) { - // balance numerical stability with performance: - // so that we call d2c once per element but don't need to - // store them, reference all to the first element - var total = 0; - var total2 = 0; - var cnt = 1; - var v0 = BADNUM; - var i; - for(i = 0; i < indices.length && v0 === BADNUM; i++) { - v0 = d2c(array[indices[i]]); - } - if(v0 === BADNUM) return BADNUM; - - for(; i < indices.length; i++) { - var vi = d2c(array[indices[i]]); - if(vi !== BADNUM) { - var dv = vi - v0; - total += dv; - total2 += dv * dv; - cnt++; - } - } - - // This is population std dev, if we want sample std dev - // we would need (...) / (cnt - 1) - // Also note there's no c2d here - that means for dates the result - // is a number of milliseconds, and for categories it's a number - // of category differences, which is not generically meaningful but - // as in other cases we don't forbid it. - var norm = (opts.funcmode === 'sample') ? (cnt - 1) : cnt; - // this is debatable: should a count of 1 return sample stddev of - // 0 or undefined? - if(!norm) return 0; - return Math.sqrt((total2 - (total * total / cnt)) / norm); - }; - } -} - -function count(array, indices) { - return indices.length; -} - -function first(array, indices) { - return array[indices[0]]; -} - -function last(array, indices) { - return array[indices[indices.length - 1]]; -} - -},{"../constants/numerical":695,"../lib":719,"../plot_api/plot_schema":756,"../plots/cartesian/axes":767,"./helpers":1268}],1266:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); -var Registry = _dereq_('../registry'); -var Axes = _dereq_('../plots/cartesian/axes'); -var pointsAccessorFunction = _dereq_('./helpers').pointsAccessorFunction; - -var filterOps = _dereq_('../constants/filter_ops'); -var COMPARISON_OPS = filterOps.COMPARISON_OPS; -var INTERVAL_OPS = filterOps.INTERVAL_OPS; -var SET_OPS = filterOps.SET_OPS; - -exports.moduleType = 'transform'; - -exports.name = 'filter'; - -exports.attributes = { - enabled: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - }, - target: { - valType: 'string', - strict: true, - noBlank: true, - arrayOk: true, - dflt: 'x', - - editType: 'calc', - - }, - operation: { - valType: 'enumerated', - values: [] - .concat(COMPARISON_OPS) - .concat(INTERVAL_OPS) - .concat(SET_OPS), - dflt: '=', - - editType: 'calc', - - }, - value: { - valType: 'any', - dflt: 0, - - editType: 'calc', - - }, - preservegaps: { - valType: 'boolean', - dflt: false, - - editType: 'calc', - - }, - editType: 'calc' -}; - -exports.supplyDefaults = function(transformIn) { - var transformOut = {}; - - function coerce(attr, dflt) { - return Lib.coerce(transformIn, transformOut, exports.attributes, attr, dflt); - } - - var enabled = coerce('enabled'); - - if(enabled) { - var target = coerce('target'); - - if(Lib.isArrayOrTypedArray(target) && target.length === 0) { - transformOut.enabled = false; - return transformOut; - } - - coerce('preservegaps'); - coerce('operation'); - coerce('value'); - - var handleCalendarDefaults = Registry.getComponentMethod('calendars', 'handleDefaults'); - handleCalendarDefaults(transformIn, transformOut, 'valuecalendar', null); - handleCalendarDefaults(transformIn, transformOut, 'targetcalendar', null); - } - - return transformOut; -}; - -exports.calcTransform = function(gd, trace, opts) { - if(!opts.enabled) return; - - var targetArray = Lib.getTargetArray(trace, opts); - if(!targetArray) return; - - var target = opts.target; - - var len = targetArray.length; - if(trace._length) len = Math.min(len, trace._length); - - var targetCalendar = opts.targetcalendar; - var arrayAttrs = trace._arrayAttrs; - var preservegaps = opts.preservegaps; - - // even if you provide targetcalendar, if target is a string and there - // is a calendar attribute matching target it will get used instead. - if(typeof target === 'string') { - var attrTargetCalendar = Lib.nestedProperty(trace, target + 'calendar').get(); - if(attrTargetCalendar) targetCalendar = attrTargetCalendar; - } - - var d2c = Axes.getDataToCoordFunc(gd, trace, target, targetArray); - var filterFunc = getFilterFunc(opts, d2c, targetCalendar); - var originalArrays = {}; - var indexToPoints = {}; - var index = 0; - - function forAllAttrs(fn, index) { - for(var j = 0; j < arrayAttrs.length; j++) { - var np = Lib.nestedProperty(trace, arrayAttrs[j]); - fn(np, index); - } - } - - var initFn; - var fillFn; - if(preservegaps) { - initFn = function(np) { - originalArrays[np.astr] = Lib.extendDeep([], np.get()); - np.set(new Array(len)); - }; - fillFn = function(np, index) { - var val = originalArrays[np.astr][index]; - np.get()[index] = val; - }; - } else { - initFn = function(np) { - originalArrays[np.astr] = Lib.extendDeep([], np.get()); - np.set([]); - }; - fillFn = function(np, index) { - var val = originalArrays[np.astr][index]; - np.get().push(val); - }; - } - - // copy all original array attribute values, and clear arrays in trace - forAllAttrs(initFn); - - var originalPointsAccessor = pointsAccessorFunction(trace.transforms, opts); - - // loop through filter array, fill trace arrays if passed - for(var i = 0; i < len; i++) { - var passed = filterFunc(targetArray[i]); - if(passed) { - forAllAttrs(fillFn, i); - indexToPoints[index++] = originalPointsAccessor(i); - } else if(preservegaps) index++; - } - - opts._indexToPoints = indexToPoints; - trace._length = index; -}; - -function getFilterFunc(opts, d2c, targetCalendar) { - var operation = opts.operation; - var value = opts.value; - var hasArrayValue = Array.isArray(value); - - function isOperationIn(array) { - return array.indexOf(operation) !== -1; - } - - var d2cValue = function(v) { return d2c(v, 0, opts.valuecalendar); }; - var d2cTarget = function(v) { return d2c(v, 0, targetCalendar); }; - - var coercedValue; - - if(isOperationIn(COMPARISON_OPS)) { - coercedValue = hasArrayValue ? d2cValue(value[0]) : d2cValue(value); - } else if(isOperationIn(INTERVAL_OPS)) { - coercedValue = hasArrayValue ? - [d2cValue(value[0]), d2cValue(value[1])] : - [d2cValue(value), d2cValue(value)]; - } else if(isOperationIn(SET_OPS)) { - coercedValue = hasArrayValue ? value.map(d2cValue) : [d2cValue(value)]; - } - - switch(operation) { - case '=': - return function(v) { return d2cTarget(v) === coercedValue; }; - - case '!=': - return function(v) { return d2cTarget(v) !== coercedValue; }; - - case '<': - return function(v) { return d2cTarget(v) < coercedValue; }; - - case '<=': - return function(v) { return d2cTarget(v) <= coercedValue; }; - - case '>': - return function(v) { return d2cTarget(v) > coercedValue; }; - - case '>=': - return function(v) { return d2cTarget(v) >= coercedValue; }; - - case '[]': - return function(v) { - var cv = d2cTarget(v); - return cv >= coercedValue[0] && cv <= coercedValue[1]; - }; - - case '()': - return function(v) { - var cv = d2cTarget(v); - return cv > coercedValue[0] && cv < coercedValue[1]; - }; - - case '[)': - return function(v) { - var cv = d2cTarget(v); - return cv >= coercedValue[0] && cv < coercedValue[1]; - }; - - case '(]': - return function(v) { - var cv = d2cTarget(v); - return cv > coercedValue[0] && cv <= coercedValue[1]; - }; - - case '][': - return function(v) { - var cv = d2cTarget(v); - return cv <= coercedValue[0] || cv >= coercedValue[1]; - }; - - case ')(': - return function(v) { - var cv = d2cTarget(v); - return cv < coercedValue[0] || cv > coercedValue[1]; - }; - - case '](': - return function(v) { - var cv = d2cTarget(v); - return cv <= coercedValue[0] || cv > coercedValue[1]; - }; - - case ')[': - return function(v) { - var cv = d2cTarget(v); - return cv < coercedValue[0] || cv >= coercedValue[1]; - }; - - case '{}': - return function(v) { - return coercedValue.indexOf(d2cTarget(v)) !== -1; - }; - - case '}{': - return function(v) { - return coercedValue.indexOf(d2cTarget(v)) === -1; - }; - } -} - -},{"../constants/filter_ops":691,"../lib":719,"../plots/cartesian/axes":767,"../registry":847,"./helpers":1268}],1267:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); -var PlotSchema = _dereq_('../plot_api/plot_schema'); -var Plots = _dereq_('../plots/plots'); -var pointsAccessorFunction = _dereq_('./helpers').pointsAccessorFunction; - -exports.moduleType = 'transform'; - -exports.name = 'groupby'; - -exports.attributes = { - enabled: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - }, - groups: { - valType: 'data_array', - dflt: [], - - editType: 'calc', - - }, - nameformat: { - valType: 'string', - - editType: 'calc', - - }, - styles: { - _isLinkedToArray: 'style', - target: { - valType: 'string', - - editType: 'calc', - - }, - value: { - valType: 'any', - - dflt: {}, - editType: 'calc', - - _compareAsJSON: true - }, - editType: 'calc' - }, - editType: 'calc' -}; - -/** - * Supply transform attributes defaults - * - * @param {object} transformIn - * object linked to trace.transforms[i] with 'type' set to exports.name - * @param {object} traceOut - * the _fullData trace this transform applies to - * @param {object} layout - * the plot's (not-so-full) layout - * @param {object} traceIn - * the input data trace this transform applies to - * - * @return {object} transformOut - * copy of transformIn that contains attribute defaults - */ -exports.supplyDefaults = function(transformIn, traceOut, layout) { - var i; - var transformOut = {}; - - function coerce(attr, dflt) { - return Lib.coerce(transformIn, transformOut, exports.attributes, attr, dflt); - } - - var enabled = coerce('enabled'); - - if(!enabled) return transformOut; - - coerce('groups'); - coerce('nameformat', layout._dataLength > 1 ? '%{group} (%{trace})' : '%{group}'); - - var styleIn = transformIn.styles; - var styleOut = transformOut.styles = []; - - if(styleIn) { - for(i = 0; i < styleIn.length; i++) { - var thisStyle = styleOut[i] = {}; - Lib.coerce(styleIn[i], styleOut[i], exports.attributes.styles, 'target'); - var value = Lib.coerce(styleIn[i], styleOut[i], exports.attributes.styles, 'value'); - - // so that you can edit value in place and have Plotly.react notice it, or - // rebuild it every time and have Plotly.react NOT think it changed: - // use _compareAsJSON to say we should diff the _JSON_value - if(Lib.isPlainObject(value)) thisStyle.value = Lib.extendDeep({}, value); - else if(value) delete thisStyle.value; - } - } - - return transformOut; -}; - - -/** - * Apply transform !!! - * - * @param {array} data - * array of transformed traces (is [fullTrace] upon first transform) - * - * @param {object} state - * state object which includes: - * - transform {object} full transform attributes - * - fullTrace {object} full trace object which is being transformed - * - fullData {array} full pre-transform(s) data array - * - layout {object} the plot's (not-so-full) layout - * - * @return {object} newData - * array of transformed traces - */ -exports.transform = function(data, state) { - var newTraces, i, j; - var newData = []; - - for(i = 0; i < data.length; i++) { - newTraces = transformOne(data[i], state); - - for(j = 0; j < newTraces.length; j++) { - newData.push(newTraces[j]); - } - } - - return newData; -}; - -function transformOne(trace, state) { - var i, j, k, attr, srcArray, groupName, newTrace, transforms, arrayLookup; - var groupNameObj; - - var opts = state.transform; - var transformIndex = state.transformIndex; - var groups = trace.transforms[transformIndex].groups; - var originalPointsAccessor = pointsAccessorFunction(trace.transforms, opts); - - if(!(Array.isArray(groups)) || groups.length === 0) { - return [trace]; - } - - var groupNames = Lib.filterUnique(groups); - var newData = new Array(groupNames.length); - var len = groups.length; - - var arrayAttrs = PlotSchema.findArrayAttributes(trace); - - var styles = opts.styles || []; - var styleLookup = {}; - for(i = 0; i < styles.length; i++) { - styleLookup[styles[i].target] = styles[i].value; - } - - if(opts.styles) { - groupNameObj = Lib.keyedContainer(opts, 'styles', 'target', 'value.name'); - } - - // An index to map group name --> expanded trace index - var indexLookup = {}; - var indexCnts = {}; - - for(i = 0; i < groupNames.length; i++) { - groupName = groupNames[i]; - indexLookup[groupName] = i; - indexCnts[groupName] = 0; - - // Start with a deep extend that just copies array references. - newTrace = newData[i] = Lib.extendDeepNoArrays({}, trace); - newTrace._group = groupName; - newTrace.transforms[transformIndex]._indexToPoints = {}; - - var suppliedName = null; - if(groupNameObj) { - suppliedName = groupNameObj.get(groupName); - } - - if(suppliedName || suppliedName === '') { - newTrace.name = suppliedName; - } else { - newTrace.name = Lib.templateString(opts.nameformat, { - trace: trace.name, - group: groupName - }); - } - - // In order for groups to apply correctly to other transform data (e.g. - // a filter transform), we have to break the connection and clone the - // transforms so that each group writes grouped values into a different - // destination. This function does not break the array reference - // connection between the split transforms it creates. That's handled in - // initialize, which creates a new empty array for each arrayAttr. - transforms = newTrace.transforms; - newTrace.transforms = []; - for(j = 0; j < transforms.length; j++) { - newTrace.transforms[j] = Lib.extendDeepNoArrays({}, transforms[j]); - } - - // Initialize empty arrays for the arrayAttrs, to be split in the next step - for(j = 0; j < arrayAttrs.length; j++) { - Lib.nestedProperty(newTrace, arrayAttrs[j]).set([]); - } - } - - // For each array attribute including those nested inside this and other - // transforms (small note that we technically only need to do this for - // transforms that have not yet been applied): - for(k = 0; k < arrayAttrs.length; k++) { - attr = arrayAttrs[k]; - - // Cache all the arrays to which we'll push: - for(j = 0, arrayLookup = []; j < groupNames.length; j++) { - arrayLookup[j] = Lib.nestedProperty(newData[j], attr).get(); - } - - // Get the input data: - srcArray = Lib.nestedProperty(trace, attr).get(); - - // Send each data point to the appropriate expanded trace: - for(j = 0; j < len; j++) { - // Map group data --> trace index --> array and push data onto it - arrayLookup[indexLookup[groups[j]]].push(srcArray[j]); - } - } - - for(j = 0; j < len; j++) { - newTrace = newData[indexLookup[groups[j]]]; - - var indexToPoints = newTrace.transforms[transformIndex]._indexToPoints; - indexToPoints[indexCnts[groups[j]]] = originalPointsAccessor(j); - indexCnts[groups[j]]++; - } - - for(i = 0; i < groupNames.length; i++) { - groupName = groupNames[i]; - newTrace = newData[i]; - - Plots.clearExpandedTraceDefaultColors(newTrace); - - // there's no need to coerce styleLookup[groupName] here - // as another round of supplyDefaults is done on the transformed traces - newTrace = Lib.extendDeepNoArrays(newTrace, styleLookup[groupName] || {}); - } - - return newData; -} - -},{"../lib":719,"../plot_api/plot_schema":756,"../plots/plots":828,"./helpers":1268}],1268:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -exports.pointsAccessorFunction = function(transforms, opts) { - var tr; - var prevIndexToPoints; - for(var i = 0; i < transforms.length; i++) { - tr = transforms[i]; - if(tr === opts) break; - if(!tr._indexToPoints || tr.enabled === false) continue; - prevIndexToPoints = tr._indexToPoints; - } - var originalPointsAccessor = prevIndexToPoints ? - function(i) {return prevIndexToPoints[i];} : - function(i) {return [i];}; - return originalPointsAccessor; -}; - -},{}],1269:[function(_dereq_,module,exports){ -/** -* Copyright 2012-2019, Plotly, Inc. -* All rights reserved. -* -* This source code is licensed under the MIT license found in the -* LICENSE file in the root directory of this source tree. -*/ - -'use strict'; - -var Lib = _dereq_('../lib'); -var Axes = _dereq_('../plots/cartesian/axes'); -var pointsAccessorFunction = _dereq_('./helpers').pointsAccessorFunction; - -exports.moduleType = 'transform'; - -exports.name = 'sort'; - -exports.attributes = { - enabled: { - valType: 'boolean', - dflt: true, - - editType: 'calc', - - }, - target: { - valType: 'string', - strict: true, - noBlank: true, - arrayOk: true, - dflt: 'x', - - editType: 'calc', - - }, - order: { - valType: 'enumerated', - values: ['ascending', 'descending'], - dflt: 'ascending', - - editType: 'calc', - - }, - editType: 'calc' -}; - -exports.supplyDefaults = function(transformIn) { - var transformOut = {}; - - function coerce(attr, dflt) { - return Lib.coerce(transformIn, transformOut, exports.attributes, attr, dflt); - } - - var enabled = coerce('enabled'); - - if(enabled) { - coerce('target'); - coerce('order'); - } - - return transformOut; -}; - -exports.calcTransform = function(gd, trace, opts) { - if(!opts.enabled) return; - - var targetArray = Lib.getTargetArray(trace, opts); - if(!targetArray) return; - - var target = opts.target; - - var len = targetArray.length; - if(trace._length) len = Math.min(len, trace._length); - - var arrayAttrs = trace._arrayAttrs; - var d2c = Axes.getDataToCoordFunc(gd, trace, target, targetArray); - var indices = getIndices(opts, targetArray, d2c, len); - var originalPointsAccessor = pointsAccessorFunction(trace.transforms, opts); - var indexToPoints = {}; - var i, j; - - for(i = 0; i < arrayAttrs.length; i++) { - var np = Lib.nestedProperty(trace, arrayAttrs[i]); - var arrayOld = np.get(); - var arrayNew = new Array(len); - - for(j = 0; j < len; j++) { - arrayNew[j] = arrayOld[indices[j]]; - } - - np.set(arrayNew); - } - - for(j = 0; j < len; j++) { - indexToPoints[j] = originalPointsAccessor(indices[j]); - } - - opts._indexToPoints = indexToPoints; - trace._length = len; -}; - -function getIndices(opts, targetArray, d2c, len) { - var sortedArray = new Array(len); - var indices = new Array(len); - var i; - - for(i = 0; i < len; i++) { - sortedArray[i] = {v: targetArray[i], i: i}; - } - - sortedArray.sort(getSortFunc(opts, d2c)); - - for(i = 0; i < len; i++) { - indices[i] = sortedArray[i].i; - } - - return indices; -} - -function getSortFunc(opts, d2c) { - switch(opts.order) { - case 'ascending': - return function(a, b) { return d2c(a.v) - d2c(b.v); }; - case 'descending': - return function(a, b) { return d2c(b.v) - d2c(a.v); }; - } -} - -},{"../lib":719,"../plots/cartesian/axes":767,"./helpers":1268}]},{},[25])(25) -}); - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(35))) - -/***/ }), -/* 12 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_c3__ = __webpack_require__(14); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_c3___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_c3__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__selectBase__ = __webpack_require__(3); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SelectBaseC3; }); - - - -var SelectBaseC3 = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](SelectBaseC3, _super); - function SelectBaseC3(targetElement, question, data, options) { - var _this = _super.call(this, targetElement, question, data, options) || this; - _this.targetElement = targetElement; - _this.chartTypes = ["bar", "line", "pie", "donut"]; - _this.chartType = "bar"; - _this.chartNode = document.createElement("div"); - _this.toolbarChangeHandler = function (e) { - if (_this.chartType !== e.target.value) { - _this.chartType = e.target.value; - _this.chart.destroy(); - _this.chart = _this.getChartC3(_this.chartNode, _this.chartType); - } - }; - return _this; - } - SelectBaseC3.prototype.destroy = function () { - if (!this.chart) - return; - this.chart.destroy(); - }; - SelectBaseC3.prototype.createChart = function () { - this.chart = this.getChartC3(this.chartNode, this.chartType); - }; - SelectBaseC3.prototype.getChartC3 = function (chartNode, chartType) { - var data = this.getData(); - var statistics = data[0]; - var columns = [["x"].concat(this.getLabels())]; - data.forEach(function (dataset, index) { - columns.push(["" + index].concat(dataset)); - }); - return __WEBPACK_IMPORTED_MODULE_1_c3___default.a.generate({ - bindto: chartNode, - data: { - x: "x", - columns: columns, - type: this.chartType - }, - color: { - pattern: this.getColors() - }, - bar: { - width: { - ratio: 0.5 // this makes bar width 50% of length between ticks - } - }, - axis: { - x: { - type: "category" - }, - y: { - tick: { - values: statistics - } - } - }, - tooltip: { - show: true - }, - legend: { - show: false - } - }); - }; - return SelectBaseC3; -}(__WEBPACK_IMPORTED_MODULE_2__selectBase__["a" /* SelectBase */])); - -// VisualizationManager.registerVisualizer("checkbox", SelectBaseC3); -// VisualizationManager.registerVisualizer("radiogroup", SelectBaseC3); -// VisualizationManager.registerVisualizer("dropdown", SelectBaseC3); -// VisualizationManager.registerVisualizer("imagepicker", SelectBaseC3); - - -/***/ }), -/* 13 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__visualizationManager__ = __webpack_require__(1); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__selectBase__ = __webpack_require__(3); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SelectBasePlotly; }); - -var Plotly = __webpack_require__(11); - - -var SelectBasePlotly = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](SelectBasePlotly, _super); - function SelectBasePlotly(targetElement, question, data, options) { - var _this = _super.call(this, targetElement, question, data, options) || this; - _this.targetElement = targetElement; - _this.selectedItem = undefined; - _this.filterText = undefined; - _this.filter = undefined; - _this.chartTypes = SelectBasePlotly.types; - _this.chartType = _this.chartTypes[0]; - return _this; - } - SelectBasePlotly.prototype.update = function (data) { - _super.prototype.update.call(this, data); - this.destroy(); - this.chart = this.getPlotlyChart(this.chartNode, this.chartType); - this.invokeOnUpdate(); - }; - SelectBasePlotly.prototype.destroy = function () { - Plotly.purge(this.chartNode); - }; - SelectBasePlotly.prototype.createChart = function () { - this.chart = this.getPlotlyChart(this.chartNode, this.chartType); - }; - SelectBasePlotly.prototype.setSelection = function (item, clearSelection) { - if (clearSelection === void 0) { clearSelection = false; } - this.selectedItem = item; - this.updateFilter(); - this.onDataItemSelected((item && item.value) || undefined, clearSelection); - }; - SelectBasePlotly.prototype.updateFilter = function () { - this.filter.style.display = !!this.selectedItem ? "inline-block" : "none"; - this.filterText.innerHTML = !!this.selectedItem - ? "Filter: [" + this.selectedItem.text + "]" - : ""; - }; - SelectBasePlotly.prototype.createToolbarItems = function (toolbar) { - var _this = this; - _super.prototype.createToolbarItems.call(this, toolbar); - this.filter = document.createElement("div"); - this.filter.className = "sva-question__filter"; - this.filterText = document.createElement("span"); - this.filterText.className = "sva-question__filter-text"; - this.filter.appendChild(this.filterText); - var filterClear = document.createElement("span"); - filterClear.className = "sva-question__filter-clear"; - filterClear.innerHTML = "Clear"; - filterClear.onclick = function () { - _this.setSelection(undefined); - }; - this.filter.appendChild(filterClear); - // const filterClearAll = document.createElement("span"); - // filterClearAll.className = "sva-question__filter-clear"; - // filterClearAll.innerHTML = "Clear All"; - // filterClearAll.onclick = () => { - // this.setSelection(undefined, true); - // }; - // this.filter.appendChild(filterClearAll); - toolbar.appendChild(this.filter); - this.updateFilter(); - }; - SelectBasePlotly.prototype.getPlotlyChart = function (chartNode, chartType) { - var _this = this; - var question = this.question; - var datasets = this.getData(); - var labels = this.getLabels(); - var traces = []; - var colors = this.getColors(); - var traceConfig = { - type: chartType, - y: labels.map(function (l) { - if (l.length > 30) { - return l.substring(0, 27) + "..."; - } - return l; - }), - text: labels, - orientation: "h", - mode: "markers", - width: 0.5 - }; - if (datasets.length === 1) { - traceConfig["marker"] = { color: colors }; - } - datasets.forEach(function (dataset) { - if (_this.chartType === "pie") { - traces.push(Object.assign({}, traceConfig, { values: dataset })); - } - else { - traces.push(Object.assign({}, traceConfig, { x: dataset })); - } - }); - var height = chartType === "pie" - ? 450 - : (labels.length + (labels.length + 1) * 0.5) * 20; - var layout = { - font: { - family: "Segoe UI, sans-serif", - size: 14, - weight: "normal", - color: "#404040" - }, - height: height, - margin: { - t: 0, - b: 0, - r: 10 - }, - colorway: colors, - yaxis: { - automargin: true, - type: "category", - ticklen: 5, - tickcolor: "transparent" - }, - xaxis: { - automargin: true - }, - plot_bgcolor: this.backgroundColor, - paper_bgcolor: this.backgroundColor - }; - var config = { - displaylogo: false, - responsive: true - }; - var plot = Plotly.newPlot(chartNode, traces, layout, config); - chartNode["on"]("plotly_click", function (data) { - if (data.points.length > 0 && _this.onDataItemSelected) { - var itemText_1 = data.points[0].text; - var item = _this.question.choices.filter(function (choice) { return choice.text === itemText_1; })[0]; - _this.setSelection(item, !data.event.ctrlKey); - } - }); - var dragLayer = (chartNode.getElementsByClassName("nsewdrag")[0]); - chartNode["on"]("plotly_hover", function () { - dragLayer.style.cursor = "pointer"; - }); - chartNode["on"]("plotly_unhover", function () { - dragLayer.style.cursor = ""; - }); - return plot; - }; - SelectBasePlotly.types = ["bar", "pie", "scatter"]; - return SelectBasePlotly; -}(__WEBPACK_IMPORTED_MODULE_2__selectBase__["a" /* SelectBase */])); - -__WEBPACK_IMPORTED_MODULE_1__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("checkbox", SelectBasePlotly); -__WEBPACK_IMPORTED_MODULE_1__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("radiogroup", SelectBasePlotly); -__WEBPACK_IMPORTED_MODULE_1__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("dropdown", SelectBasePlotly); -__WEBPACK_IMPORTED_MODULE_1__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("imagepicker", SelectBasePlotly); - - -/***/ }), -/* 14 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_14__; - -/***/ }), -/* 15 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__matrix__ = __webpack_require__(28); -/* harmony namespace reexport (by used) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__matrix__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__selectBase__ = __webpack_require__(12); -/* harmony namespace reexport (by used) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_1__selectBase__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__rating__ = __webpack_require__(29); -/* harmony namespace reexport (by used) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_2__rating__["a"]; }); - - - - - -/***/ }), -/* 16 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__matrix__ = __webpack_require__(30); -/* harmony namespace reexport (by used) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__matrix__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__selectBase__ = __webpack_require__(6); -/* harmony namespace reexport (by used) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_1__selectBase__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__rating__ = __webpack_require__(31); -/* harmony namespace reexport (by used) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_2__rating__["a"]; }); - - - - - -/***/ }), -/* 17 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_jquery__ = __webpack_require__(38); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_jquery___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_jquery__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__datatables_scss__ = __webpack_require__(22); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__datatables_scss___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__datatables_scss__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return DataTables; }); - - -var DataTables = /** @class */ (function () { - function DataTables(targetNode, survey, data, options) { - var _this = this; - this.targetNode = targetNode; - this.survey = survey; - this.data = data; - this.options = options; - this.groupBy = []; - this.createSelectButton = function (datatableApi, colIdx, columnName) { - var button = document.createElement("button"); - button.innerHTML = "Select Me"; - button.onclick = function (e) { - e.stopPropagation(); - datatableApi.columns().deselect(); - datatableApi.column(colIdx).select(); - !!_this.onColumnSelected && _this.onColumnSelected(columnName); - }; - return button; - }; - this.createGroupingButton = function (datatableApi, columnName) { - var button = document.createElement("button"); - button.innerHTML = "Group By Me"; - button.onclick = function (e) { - e.stopPropagation(); - var index = _this.groupBy.indexOf(columnName); - if (index === -1) { - _this.groupBy.push(columnName); - button.innerHTML = "Ungroup By Me"; - } - else { - button.innerHTML = "Group By Me"; - _this.groupBy.splice(index, 1); - } - datatableApi.rowGroup().enable(_this.groupBy.length > 0); - if (_this.groupBy.length > 0) { - datatableApi.rowGroup().dataSrc(_this.groupBy); - } - datatableApi.draw(); - }; - return button; - }; - } - DataTables.prototype.render = function () { - var tableNode = document.createElement("table"); - var createGroupingButton = this.createGroupingButton; - var createSelectButton = this.createSelectButton; - var columnsData = this.getColumns().map(function (c) { return c.data; }); - var options = this.options || { - buttons: ["copy", "csv", "print"], - dom: "Blfrtip", - data: this.data, - columns: this.getColumns(), - // orderFixed: [[1, "asc"]], - rowGroup: { - dataSrc: columnsData[0], - endRender: function (rows, group) { - return "Count: " + rows.data().count(); - } - }, - select: "api", - headerCallback: function (thead, data, start, end, display) { - var datatableApi = __WEBPACK_IMPORTED_MODULE_0_jquery__(tableNode) - .dataTable() - .api(); - __WEBPACK_IMPORTED_MODULE_0_jquery__(thead) - .children("th") - .each(function (index, node) { - var thNode = __WEBPACK_IMPORTED_MODULE_0_jquery__(this); - if (thNode.has("button").length === 0) { - thNode.prepend(createGroupingButton(datatableApi, columnsData[index])); - thNode.prepend(createSelectButton(datatableApi, index, columnsData[index])); - } - }); - } - }; - this.targetNode.appendChild(tableNode); - tableNode.className = "sa-datatable display dataTable"; - var datatableApi = __WEBPACK_IMPORTED_MODULE_0_jquery__(tableNode).DataTable(options); - datatableApi - .rowGroup() - .enable(false) - .draw(); - // datatableApi.on("rowgroup-datasrc", function(e, dt, val) { - // datatableApi.order.fixed({ pre: [[columnsData.indexOf(val), "asc"]] }).draw(); - // }); - }; - DataTables.prototype.getColumns = function () { - var _this = this; - var columns = this.survey.getAllQuestions().map(function (question) { - var q = question; - return { - data: q.name, - sTitle: (q.title || "").trim() || q.name, - mRender: function (data, type, row) { - _this.survey.data = row; - var displayValue = q.displayValue; - return ((typeof displayValue === "string" - ? displayValue - : JSON.stringify(displayValue)) || ""); - } - }; - }); - return columns; - }; - return DataTables; -}()); - - - -/***/ }), -/* 18 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__selectBase__ = __webpack_require__(13); -/* harmony namespace reexport (by used) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__selectBase__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__rating__ = __webpack_require__(33); -/* harmony namespace reexport (by used) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_1__rating__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__matrix__ = __webpack_require__(32); -/* harmony namespace reexport (by used) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_2__matrix__["a"]; }); - - - - - -/***/ }), -/* 19 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__visualizationManager__ = __webpack_require__(1); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__visualizationPanelDynamic__ = __webpack_require__(8); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return VisualizationMatrixDynamic; }); - - - -var VisualizationMatrixDynamic = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](VisualizationMatrixDynamic, _super); - function VisualizationMatrixDynamic(targetElement, question, data, options) { - return _super.call(this, targetElement, question, data, options) || this; - } - VisualizationMatrixDynamic.prototype.getQuestions = function () { - var matrixdynamic = this.question; - var visibleRows = matrixdynamic.visibleRows; - if (visibleRows.length === 0) - return []; - return visibleRows[0].cells.map(function (c) { return c.question; }); - }; - return VisualizationMatrixDynamic; -}(__WEBPACK_IMPORTED_MODULE_2__visualizationPanelDynamic__["a" /* VisualizationPanelDynamic */])); - -__WEBPACK_IMPORTED_MODULE_1__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("matrixdynamic", VisualizationMatrixDynamic); -__WEBPACK_IMPORTED_MODULE_1__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("matrixdropdown", VisualizationMatrixDynamic); - - -/***/ }), -/* 20 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_wordcloud__ = __webpack_require__(37); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_wordcloud___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_wordcloud__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__visualizerBase__ = __webpack_require__(2); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__visualizationManager__ = __webpack_require__(1); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__stopwords_index__ = __webpack_require__(9); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return WordCloud; }); - - - - - -var WordCloud = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](WordCloud, _super); - function WordCloud(targetElement, question, data, options) { - return _super.call(this, targetElement, question, data, options) || this; - } - WordCloud.prototype.getData = function () { - var _this = this; - var result = {}; - var stopWords = __WEBPACK_IMPORTED_MODULE_4__stopwords_index__["a" /* textHelper */].getStopWords(); - var stopTheWord = function (word) { - if (stopWords.indexOf(word) !== -1) { - return ""; - } - return word; - }; - var processString = function (row) { - row = "" + row; - if (!!row) { - row.split(" ").forEach(function (word) { - word = stopTheWord(word.toLowerCase() || ""); - if (!!word) { - if (!result[word]) { - result[word] = 1; - } - else { - result[word]++; - } - } - }); - } - }; - this.data.forEach(function (row) { - var rowValue = row[_this.question.name]; - if (!!rowValue) { - if (Array.isArray(rowValue)) { - rowValue.forEach(processString); - } - else { - if (typeof rowValue === "object") { - Object.keys(rowValue).forEach(function (key) { return processString(rowValue[key]); }); - } - else { - processString(rowValue); - } - } - } - }); - return Object.keys(result).map(function (key) { - return [key, result[key]]; - }); - }; - WordCloud.prototype.render = function () { - var _this = this; - var data = this.getData(); - var colors = this.getColors(); - var canvasNode = document.createElement("canvas"); - var emptyTextNode = document.createElement("p"); - emptyTextNode.innerHTML = "There is no results yet"; - if (data.length === 0) { - this.targetElement.appendChild(emptyTextNode); - return; - } - this.targetElement.appendChild(canvasNode); - var config = { - list: data, - weightFactor: 20, - fontFamily: "Segoe UI Bold, sans-serif", - color: function (word, weight) { - return _this.getRandomColor(); - }, - rotateRatio: 0.5, - rotationSteps: 2, - backgroundColor: this.backgroundColor, - click: function (item) { - console.log(item[0] + ": " + item[1]); - } - }; - this.cloud = __WEBPACK_IMPORTED_MODULE_1_wordcloud___default()(canvasNode, config); - }; - WordCloud.prototype.destroy = function () { - if (!!this.cloud) { - this.cloud = undefined; - this.targetElement.innerHTML = ""; - } - }; - return WordCloud; -}(__WEBPACK_IMPORTED_MODULE_2__visualizerBase__["a" /* VisualizerBase */])); - -__WEBPACK_IMPORTED_MODULE_3__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("text", WordCloud); -__WEBPACK_IMPORTED_MODULE_3__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("comment", WordCloud); -__WEBPACK_IMPORTED_MODULE_3__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("multipletext", WordCloud); - - -/***/ }), -/* 21 */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/** - * matchesSelector v2.0.2 - * matchesSelector( element, '.selector' ) - * MIT license - */ - -/*jshint browser: true, strict: true, undef: true, unused: true */ - -( function( window, factory ) { - /*global define: false, module: false */ - 'use strict'; - // universal module definition - if ( true ) { - // AMD - !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : - __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if ( typeof module == 'object' && module.exports ) { - // CommonJS - module.exports = factory(); - } else { - // browser global - window.matchesSelector = factory(); - } - -}( window, function factory() { - 'use strict'; - - var matchesMethod = ( function() { - var ElemProto = window.Element.prototype; - // check for the standard method name first - if ( ElemProto.matches ) { - return 'matches'; - } - // check un-prefixed - if ( ElemProto.matchesSelector ) { - return 'matchesSelector'; - } - // check vendor prefixes - var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; - - for ( var i=0; i < prefixes.length; i++ ) { - var prefix = prefixes[i]; - var method = prefix + 'MatchesSelector'; - if ( ElemProto[ method ] ) { - return method; - } - } - })(); - - return function matchesSelector( elem, selector ) { - return elem[ matchesMethod ]( selector ); - }; - -})); - - -/***/ }), -/* 22 */ -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), -/* 23 */ -/***/ (function(module, exports) { - -// removed by extract-text-webpack-plugin - -/***/ }), -/* 24 */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/** - * Fizzy UI utils v2.0.7 - * MIT license - */ - -/*jshint browser: true, undef: true, unused: true, strict: true */ - -( function( window, factory ) { - // universal module definition - /*jshint strict: false */ /*globals define, module, require */ - - if ( true ) { - // AMD - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ - __webpack_require__(21) - ], __WEBPACK_AMD_DEFINE_RESULT__ = function( matchesSelector ) { - return factory( window, matchesSelector ); - }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if ( typeof module == 'object' && module.exports ) { - // CommonJS - module.exports = factory( - window, - require('desandro-matches-selector') - ); - } else { - // browser global - window.fizzyUIUtils = factory( - window, - window.matchesSelector - ); - } - -}( window, function factory( window, matchesSelector ) { - -'use strict'; - -var utils = {}; - -// ----- extend ----- // - -// extends objects -utils.extend = function( a, b ) { - for ( var prop in b ) { - a[ prop ] = b[ prop ]; - } - return a; -}; - -// ----- modulo ----- // - -utils.modulo = function( num, div ) { - return ( ( num % div ) + div ) % div; -}; - -// ----- makeArray ----- // - -var arraySlice = Array.prototype.slice; - -// turn element or nodeList into an array -utils.makeArray = function( obj ) { - if ( Array.isArray( obj ) ) { - // use object if already an array - return obj; - } - // return empty array if undefined or null. #6 - if ( obj === null || obj === undefined ) { - return []; - } - - var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; - if ( isArrayLike ) { - // convert nodeList to array - return arraySlice.call( obj ); - } - - // array of single index - return [ obj ]; -}; - -// ----- removeFrom ----- // - -utils.removeFrom = function( ary, obj ) { - var index = ary.indexOf( obj ); - if ( index != -1 ) { - ary.splice( index, 1 ); - } -}; - -// ----- getParent ----- // - -utils.getParent = function( elem, selector ) { - while ( elem.parentNode && elem != document.body ) { - elem = elem.parentNode; - if ( matchesSelector( elem, selector ) ) { - return elem; - } - } -}; - -// ----- getQueryElement ----- // - -// use element as selector string -utils.getQueryElement = function( elem ) { - if ( typeof elem == 'string' ) { - return document.querySelector( elem ); - } - return elem; -}; - -// ----- handleEvent ----- // - -// enable .ontype to trigger from .addEventListener( elem, 'type' ) -utils.handleEvent = function( event ) { - var method = 'on' + event.type; - if ( this[ method ] ) { - this[ method ]( event ); - } -}; - -// ----- filterFindElements ----- // - -utils.filterFindElements = function( elems, selector ) { - // make array of elems - elems = utils.makeArray( elems ); - var ffElems = []; - - elems.forEach( function( elem ) { - // check that elem is an actual element - if ( !( elem instanceof HTMLElement ) ) { - return; - } - // add elem if no selector - if ( !selector ) { - ffElems.push( elem ); - return; - } - // filter & find items if we have a selector - // filter - if ( matchesSelector( elem, selector ) ) { - ffElems.push( elem ); - } - // find children - var childElems = elem.querySelectorAll( selector ); - // concat childElems to filterFound array - for ( var i=0; i < childElems.length; i++ ) { - ffElems.push( childElems[i] ); - } - }); - - return ffElems; -}; - -// ----- debounceMethod ----- // - -utils.debounceMethod = function( _class, methodName, threshold ) { - threshold = threshold || 100; - // original method - var method = _class.prototype[ methodName ]; - var timeoutName = methodName + 'Timeout'; - - _class.prototype[ methodName ] = function() { - var timeout = this[ timeoutName ]; - clearTimeout( timeout ); - - var args = arguments; - var _this = this; - this[ timeoutName ] = setTimeout( function() { - method.apply( _this, args ); - delete _this[ timeoutName ]; - }, threshold ); - }; -}; - -// ----- docReady ----- // - -utils.docReady = function( callback ) { - var readyState = document.readyState; - if ( readyState == 'complete' || readyState == 'interactive' ) { - // do async to allow for other scripts to run. metafizzy/flickity#441 - setTimeout( callback ); - } else { - document.addEventListener( 'DOMContentLoaded', callback ); - } -}; - -// ----- htmlInit ----- // - -// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ -utils.toDashed = function( str ) { - return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { - return $1 + '-' + $2; - }).toLowerCase(); -}; - -var console = window.console; -/** - * allow user to initialize classes via [data-namespace] or .js-namespace class - * htmlInit( Widget, 'widgetName' ) - * options are parsed from data-namespace-options - */ -utils.htmlInit = function( WidgetClass, namespace ) { - utils.docReady( function() { - var dashedNamespace = utils.toDashed( namespace ); - var dataAttr = 'data-' + dashedNamespace; - var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' ); - var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace ); - var elems = utils.makeArray( dataAttrElems ) - .concat( utils.makeArray( jsDashElems ) ); - var dataOptionsAttr = dataAttr + '-options'; - var jQuery = window.jQuery; - - elems.forEach( function( elem ) { - var attr = elem.getAttribute( dataAttr ) || - elem.getAttribute( dataOptionsAttr ); - var options; - try { - options = attr && JSON.parse( attr ); - } catch ( error ) { - // log error, do not initialize - if ( console ) { - console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className + - ': ' + error ); - } - return; - } - // initialize - var instance = new WidgetClass( elem, options ); - // make available via $().data('namespace') - if ( jQuery ) { - jQuery.data( elem, namespace, instance ); - } - }); - - }); -}; - -// ----- ----- // - -return utils; - -})); - - -/***/ }), -/* 25 */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! - * Masonry v4.2.2 - * Cascading grid layout library - * https://masonry.desandro.com - * MIT License - * by David DeSandro - */ - -( function( window, factory ) { - // universal module definition - /* jshint strict: false */ /*globals define, module, require */ - if ( true ) { - // AMD - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ - __webpack_require__(27), - __webpack_require__(5) - ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if ( typeof module == 'object' && module.exports ) { - // CommonJS - module.exports = factory( - require('outlayer'), - require('get-size') - ); - } else { - // browser global - window.Masonry = factory( - window.Outlayer, - window.getSize - ); - } - -}( window, function factory( Outlayer, getSize ) { - -'use strict'; - -// -------------------------- masonryDefinition -------------------------- // - - // create an Outlayer layout class - var Masonry = Outlayer.create('masonry'); - // isFitWidth -> fitWidth - Masonry.compatOptions.fitWidth = 'isFitWidth'; - - var proto = Masonry.prototype; - - proto._resetLayout = function() { - this.getSize(); - this._getMeasurement( 'columnWidth', 'outerWidth' ); - this._getMeasurement( 'gutter', 'outerWidth' ); - this.measureColumns(); - - // reset column Y - this.colYs = []; - for ( var i=0; i < this.cols; i++ ) { - this.colYs.push( 0 ); - } - - this.maxY = 0; - this.horizontalColIndex = 0; - }; - - proto.measureColumns = function() { - this.getContainerWidth(); - // if columnWidth is 0, default to outerWidth of first item - if ( !this.columnWidth ) { - var firstItem = this.items[0]; - var firstItemElem = firstItem && firstItem.element; - // columnWidth fall back to item of first element - this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || - // if first elem has no width, default to size of container - this.containerWidth; - } - - var columnWidth = this.columnWidth += this.gutter; - - // calculate columns - var containerWidth = this.containerWidth + this.gutter; - var cols = containerWidth / columnWidth; - // fix rounding errors, typically with gutters - var excess = columnWidth - containerWidth % columnWidth; - // if overshoot is less than a pixel, round up, otherwise floor it - var mathMethod = excess && excess < 1 ? 'round' : 'floor'; - cols = Math[ mathMethod ]( cols ); - this.cols = Math.max( cols, 1 ); - }; - - proto.getContainerWidth = function() { - // container is parent if fit width - var isFitWidth = this._getOption('fitWidth'); - var container = isFitWidth ? this.element.parentNode : this.element; - // check that this.size and size are there - // IE8 triggers resize on body size change, so they might not be - var size = getSize( container ); - this.containerWidth = size && size.innerWidth; - }; - - proto._getItemLayoutPosition = function( item ) { - item.getSize(); - // how many columns does this brick span - var remainder = item.size.outerWidth % this.columnWidth; - var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; - // round if off by 1 pixel, otherwise use ceil - var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); - colSpan = Math.min( colSpan, this.cols ); - // use horizontal or top column position - var colPosMethod = this.options.horizontalOrder ? - '_getHorizontalColPosition' : '_getTopColPosition'; - var colPosition = this[ colPosMethod ]( colSpan, item ); - // position the brick - var position = { - x: this.columnWidth * colPosition.col, - y: colPosition.y - }; - // apply setHeight to necessary columns - var setHeight = colPosition.y + item.size.outerHeight; - var setMax = colSpan + colPosition.col; - for ( var i = colPosition.col; i < setMax; i++ ) { - this.colYs[i] = setHeight; - } - - return position; - }; - - proto._getTopColPosition = function( colSpan ) { - var colGroup = this._getTopColGroup( colSpan ); - // get the minimum Y value from the columns - var minimumY = Math.min.apply( Math, colGroup ); - - return { - col: colGroup.indexOf( minimumY ), - y: minimumY, - }; - }; - - /** - * @param {Number} colSpan - number of columns the element spans - * @returns {Array} colGroup - */ - proto._getTopColGroup = function( colSpan ) { - if ( colSpan < 2 ) { - // if brick spans only one column, use all the column Ys - return this.colYs; - } - - var colGroup = []; - // how many different places could this brick fit horizontally - var groupCount = this.cols + 1 - colSpan; - // for each group potential horizontal position - for ( var i = 0; i < groupCount; i++ ) { - colGroup[i] = this._getColGroupY( i, colSpan ); - } - return colGroup; - }; - - proto._getColGroupY = function( col, colSpan ) { - if ( colSpan < 2 ) { - return this.colYs[ col ]; - } - // make an array of colY values for that one group - var groupColYs = this.colYs.slice( col, col + colSpan ); - // and get the max value of the array - return Math.max.apply( Math, groupColYs ); - }; - - // get column position based on horizontal index. #873 - proto._getHorizontalColPosition = function( colSpan, item ) { - var col = this.horizontalColIndex % this.cols; - var isOver = colSpan > 1 && col + colSpan > this.cols; - // shift to next row if item can't fit on current row - col = isOver ? 0 : col; - // don't let zero-size items take up space - var hasSize = item.size.outerWidth && item.size.outerHeight; - this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex; - - return { - col: col, - y: this._getColGroupY( col, colSpan ), - }; - }; - - proto._manageStamp = function( stamp ) { - var stampSize = getSize( stamp ); - var offset = this._getElementOffset( stamp ); - // get the columns that this stamp affects - var isOriginLeft = this._getOption('originLeft'); - var firstX = isOriginLeft ? offset.left : offset.right; - var lastX = firstX + stampSize.outerWidth; - var firstCol = Math.floor( firstX / this.columnWidth ); - firstCol = Math.max( 0, firstCol ); - var lastCol = Math.floor( lastX / this.columnWidth ); - // lastCol should not go over if multiple of columnWidth #425 - lastCol -= lastX % this.columnWidth ? 0 : 1; - lastCol = Math.min( this.cols - 1, lastCol ); - // set colYs to bottom of the stamp - - var isOriginTop = this._getOption('originTop'); - var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) + - stampSize.outerHeight; - for ( var i = firstCol; i <= lastCol; i++ ) { - this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); - } - }; - - proto._getContainerSize = function() { - this.maxY = Math.max.apply( Math, this.colYs ); - var size = { - height: this.maxY - }; - - if ( this._getOption('fitWidth') ) { - size.width = this._getContainerFitWidth(); - } - - return size; - }; - - proto._getContainerFitWidth = function() { - var unusedCols = 0; - // count unused columns - var i = this.cols; - while ( --i ) { - if ( this.colYs[i] !== 0 ) { - break; - } - unusedCols++; - } - // fit container to columns that have been used - return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; - }; - - proto.needsResizeLayout = function() { - var previousWidth = this.containerWidth; - this.getContainerWidth(); - return previousWidth != this.containerWidth; - }; - - return Masonry; - -})); - - -/***/ }), -/* 26 */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/** - * Outlayer Item - */ - -( function( window, factory ) { - // universal module definition - /* jshint strict: false */ /* globals define, module, require */ - if ( true ) { - // AMD - RequireJS - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ - __webpack_require__(10), - __webpack_require__(5) - ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if ( typeof module == 'object' && module.exports ) { - // CommonJS - Browserify, Webpack - module.exports = factory( - require('ev-emitter'), - require('get-size') - ); - } else { - // browser global - window.Outlayer = {}; - window.Outlayer.Item = factory( - window.EvEmitter, - window.getSize - ); - } - -}( window, function factory( EvEmitter, getSize ) { -'use strict'; - -// ----- helpers ----- // - -function isEmptyObj( obj ) { - for ( var prop in obj ) { - return false; - } - prop = null; - return true; -} - -// -------------------------- CSS3 support -------------------------- // - - -var docElemStyle = document.documentElement.style; - -var transitionProperty = typeof docElemStyle.transition == 'string' ? - 'transition' : 'WebkitTransition'; -var transformProperty = typeof docElemStyle.transform == 'string' ? - 'transform' : 'WebkitTransform'; - -var transitionEndEvent = { - WebkitTransition: 'webkitTransitionEnd', - transition: 'transitionend' -}[ transitionProperty ]; - -// cache all vendor properties that could have vendor prefix -var vendorProperties = { - transform: transformProperty, - transition: transitionProperty, - transitionDuration: transitionProperty + 'Duration', - transitionProperty: transitionProperty + 'Property', - transitionDelay: transitionProperty + 'Delay' -}; - -// -------------------------- Item -------------------------- // - -function Item( element, layout ) { - if ( !element ) { - return; - } - - this.element = element; - // parent layout class, i.e. Masonry, Isotope, or Packery - this.layout = layout; - this.position = { - x: 0, - y: 0 - }; - - this._create(); -} - -// inherit EvEmitter -var proto = Item.prototype = Object.create( EvEmitter.prototype ); -proto.constructor = Item; - -proto._create = function() { - // transition objects - this._transn = { - ingProperties: {}, - clean: {}, - onEnd: {} - }; - - this.css({ - position: 'absolute' - }); -}; - -// trigger specified handler for event type -proto.handleEvent = function( event ) { - var method = 'on' + event.type; - if ( this[ method ] ) { - this[ method ]( event ); - } -}; - -proto.getSize = function() { - this.size = getSize( this.element ); -}; - -/** - * apply CSS styles to element - * @param {Object} style - */ -proto.css = function( style ) { - var elemStyle = this.element.style; - - for ( var prop in style ) { - // use vendor property if available - var supportedProp = vendorProperties[ prop ] || prop; - elemStyle[ supportedProp ] = style[ prop ]; - } -}; - - // measure position, and sets it -proto.getPosition = function() { - var style = getComputedStyle( this.element ); - var isOriginLeft = this.layout._getOption('originLeft'); - var isOriginTop = this.layout._getOption('originTop'); - var xValue = style[ isOriginLeft ? 'left' : 'right' ]; - var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; - var x = parseFloat( xValue ); - var y = parseFloat( yValue ); - // convert percent to pixels - var layoutSize = this.layout.size; - if ( xValue.indexOf('%') != -1 ) { - x = ( x / 100 ) * layoutSize.width; - } - if ( yValue.indexOf('%') != -1 ) { - y = ( y / 100 ) * layoutSize.height; - } - // clean up 'auto' or other non-integer values - x = isNaN( x ) ? 0 : x; - y = isNaN( y ) ? 0 : y; - // remove padding from measurement - x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; - y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; - - this.position.x = x; - this.position.y = y; -}; - -// set settled position, apply padding -proto.layoutPosition = function() { - var layoutSize = this.layout.size; - var style = {}; - var isOriginLeft = this.layout._getOption('originLeft'); - var isOriginTop = this.layout._getOption('originTop'); - - // x - var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight'; - var xProperty = isOriginLeft ? 'left' : 'right'; - var xResetProperty = isOriginLeft ? 'right' : 'left'; - - var x = this.position.x + layoutSize[ xPadding ]; - // set in percentage or pixels - style[ xProperty ] = this.getXValue( x ); - // reset other property - style[ xResetProperty ] = ''; - - // y - var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom'; - var yProperty = isOriginTop ? 'top' : 'bottom'; - var yResetProperty = isOriginTop ? 'bottom' : 'top'; - - var y = this.position.y + layoutSize[ yPadding ]; - // set in percentage or pixels - style[ yProperty ] = this.getYValue( y ); - // reset other property - style[ yResetProperty ] = ''; - - this.css( style ); - this.emitEvent( 'layout', [ this ] ); -}; - -proto.getXValue = function( x ) { - var isHorizontal = this.layout._getOption('horizontal'); - return this.layout.options.percentPosition && !isHorizontal ? - ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; -}; - -proto.getYValue = function( y ) { - var isHorizontal = this.layout._getOption('horizontal'); - return this.layout.options.percentPosition && isHorizontal ? - ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; -}; - -proto._transitionTo = function( x, y ) { - this.getPosition(); - // get current x & y from top/left - var curX = this.position.x; - var curY = this.position.y; - - var didNotMove = x == this.position.x && y == this.position.y; - - // save end position - this.setPosition( x, y ); - - // if did not move and not transitioning, just go to layout - if ( didNotMove && !this.isTransitioning ) { - this.layoutPosition(); - return; - } - - var transX = x - curX; - var transY = y - curY; - var transitionStyle = {}; - transitionStyle.transform = this.getTranslate( transX, transY ); - - this.transition({ - to: transitionStyle, - onTransitionEnd: { - transform: this.layoutPosition - }, - isCleaning: true - }); -}; - -proto.getTranslate = function( x, y ) { - // flip cooridinates if origin on right or bottom - var isOriginLeft = this.layout._getOption('originLeft'); - var isOriginTop = this.layout._getOption('originTop'); - x = isOriginLeft ? x : -x; - y = isOriginTop ? y : -y; - return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; -}; - -// non transition + transform support -proto.goTo = function( x, y ) { - this.setPosition( x, y ); - this.layoutPosition(); -}; - -proto.moveTo = proto._transitionTo; - -proto.setPosition = function( x, y ) { - this.position.x = parseFloat( x ); - this.position.y = parseFloat( y ); -}; - -// ----- transition ----- // - -/** - * @param {Object} style - CSS - * @param {Function} onTransitionEnd - */ - -// non transition, just trigger callback -proto._nonTransition = function( args ) { - this.css( args.to ); - if ( args.isCleaning ) { - this._removeStyles( args.to ); - } - for ( var prop in args.onTransitionEnd ) { - args.onTransitionEnd[ prop ].call( this ); - } -}; - -/** - * proper transition - * @param {Object} args - arguments - * @param {Object} to - style to transition to - * @param {Object} from - style to start transition from - * @param {Boolean} isCleaning - removes transition styles after transition - * @param {Function} onTransitionEnd - callback - */ -proto.transition = function( args ) { - // redirect to nonTransition if no transition duration - if ( !parseFloat( this.layout.options.transitionDuration ) ) { - this._nonTransition( args ); - return; - } - - var _transition = this._transn; - // keep track of onTransitionEnd callback by css property - for ( var prop in args.onTransitionEnd ) { - _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; - } - // keep track of properties that are transitioning - for ( prop in args.to ) { - _transition.ingProperties[ prop ] = true; - // keep track of properties to clean up when transition is done - if ( args.isCleaning ) { - _transition.clean[ prop ] = true; - } - } - - // set from styles - if ( args.from ) { - this.css( args.from ); - // force redraw. http://blog.alexmaccaw.com/css-transitions - var h = this.element.offsetHeight; - // hack for JSHint to hush about unused var - h = null; - } - // enable transition - this.enableTransition( args.to ); - // set styles that are transitioning - this.css( args.to ); - - this.isTransitioning = true; - -}; - -// dash before all cap letters, including first for -// WebkitTransform => -webkit-transform -function toDashedAll( str ) { - return str.replace( /([A-Z])/g, function( $1 ) { - return '-' + $1.toLowerCase(); - }); -} - -var transitionProps = 'opacity,' + toDashedAll( transformProperty ); - -proto.enableTransition = function(/* style */) { - // HACK changing transitionProperty during a transition - // will cause transition to jump - if ( this.isTransitioning ) { - return; - } - - // make `transition: foo, bar, baz` from style object - // HACK un-comment this when enableTransition can work - // while a transition is happening - // var transitionValues = []; - // for ( var prop in style ) { - // // dash-ify camelCased properties like WebkitTransition - // prop = vendorProperties[ prop ] || prop; - // transitionValues.push( toDashedAll( prop ) ); - // } - // munge number to millisecond, to match stagger - var duration = this.layout.options.transitionDuration; - duration = typeof duration == 'number' ? duration + 'ms' : duration; - // enable transition styles - this.css({ - transitionProperty: transitionProps, - transitionDuration: duration, - transitionDelay: this.staggerDelay || 0 - }); - // listen for transition end event - this.element.addEventListener( transitionEndEvent, this, false ); -}; - -// ----- events ----- // - -proto.onwebkitTransitionEnd = function( event ) { - this.ontransitionend( event ); -}; - -proto.onotransitionend = function( event ) { - this.ontransitionend( event ); -}; - -// properties that I munge to make my life easier -var dashedVendorProperties = { - '-webkit-transform': 'transform' -}; - -proto.ontransitionend = function( event ) { - // disregard bubbled events from children - if ( event.target !== this.element ) { - return; - } - var _transition = this._transn; - // get property name of transitioned property, convert to prefix-free - var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; - - // remove property that has completed transitioning - delete _transition.ingProperties[ propertyName ]; - // check if any properties are still transitioning - if ( isEmptyObj( _transition.ingProperties ) ) { - // all properties have completed transitioning - this.disableTransition(); - } - // clean style - if ( propertyName in _transition.clean ) { - // clean up style - this.element.style[ event.propertyName ] = ''; - delete _transition.clean[ propertyName ]; - } - // trigger onTransitionEnd callback - if ( propertyName in _transition.onEnd ) { - var onTransitionEnd = _transition.onEnd[ propertyName ]; - onTransitionEnd.call( this ); - delete _transition.onEnd[ propertyName ]; - } - - this.emitEvent( 'transitionEnd', [ this ] ); -}; - -proto.disableTransition = function() { - this.removeTransitionStyles(); - this.element.removeEventListener( transitionEndEvent, this, false ); - this.isTransitioning = false; -}; - -/** - * removes style property from element - * @param {Object} style -**/ -proto._removeStyles = function( style ) { - // clean up transition styles - var cleanStyle = {}; - for ( var prop in style ) { - cleanStyle[ prop ] = ''; - } - this.css( cleanStyle ); -}; - -var cleanTransitionStyle = { - transitionProperty: '', - transitionDuration: '', - transitionDelay: '' -}; - -proto.removeTransitionStyles = function() { - // remove transition - this.css( cleanTransitionStyle ); -}; - -// ----- stagger ----- // - -proto.stagger = function( delay ) { - delay = isNaN( delay ) ? 0 : delay; - this.staggerDelay = delay + 'ms'; -}; - -// ----- show/hide/remove ----- // - -// remove element from DOM -proto.removeElem = function() { - this.element.parentNode.removeChild( this.element ); - // remove display: none - this.css({ display: '' }); - this.emitEvent( 'remove', [ this ] ); -}; - -proto.remove = function() { - // just remove element if no transition support or no transition - if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { - this.removeElem(); - return; - } - - // start transition - this.once( 'transitionEnd', function() { - this.removeElem(); - }); - this.hide(); -}; - -proto.reveal = function() { - delete this.isHidden; - // remove display: none - this.css({ display: '' }); - - var options = this.layout.options; - - var onTransitionEnd = {}; - var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); - onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; - - this.transition({ - from: options.hiddenStyle, - to: options.visibleStyle, - isCleaning: true, - onTransitionEnd: onTransitionEnd - }); -}; - -proto.onRevealTransitionEnd = function() { - // check if still visible - // during transition, item may have been hidden - if ( !this.isHidden ) { - this.emitEvent('reveal'); - } -}; - -/** - * get style property use for hide/reveal transition end - * @param {String} styleProperty - hiddenStyle/visibleStyle - * @returns {String} - */ -proto.getHideRevealTransitionEndProperty = function( styleProperty ) { - var optionStyle = this.layout.options[ styleProperty ]; - // use opacity - if ( optionStyle.opacity ) { - return 'opacity'; - } - // get first property - for ( var prop in optionStyle ) { - return prop; - } -}; - -proto.hide = function() { - // set flag - this.isHidden = true; - // remove display: none - this.css({ display: '' }); - - var options = this.layout.options; - - var onTransitionEnd = {}; - var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); - onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; - - this.transition({ - from: options.visibleStyle, - to: options.hiddenStyle, - // keep hidden stuff hidden - isCleaning: true, - onTransitionEnd: onTransitionEnd - }); -}; - -proto.onHideTransitionEnd = function() { - // check if still hidden - // during transition, item may have been un-hidden - if ( this.isHidden ) { - this.css({ display: 'none' }); - this.emitEvent('hide'); - } -}; - -proto.destroy = function() { - this.css({ - position: '', - left: '', - right: '', - top: '', - bottom: '', - transition: '', - transform: '' - }); -}; - -return Item; - -})); - - -/***/ }), -/* 27 */ -/***/ (function(module, exports, __webpack_require__) { - -var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! - * Outlayer v2.1.1 - * the brains and guts of a layout library - * MIT license - */ - -( function( window, factory ) { - 'use strict'; - // universal module definition - /* jshint strict: false */ /* globals define, module, require */ - if ( true ) { - // AMD - RequireJS - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ - __webpack_require__(10), - __webpack_require__(5), - __webpack_require__(24), - __webpack_require__(26) - ], __WEBPACK_AMD_DEFINE_RESULT__ = function( EvEmitter, getSize, utils, Item ) { - return factory( window, EvEmitter, getSize, utils, Item); - }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if ( typeof module == 'object' && module.exports ) { - // CommonJS - Browserify, Webpack - module.exports = factory( - window, - require('ev-emitter'), - require('get-size'), - require('fizzy-ui-utils'), - require('./item') - ); - } else { - // browser global - window.Outlayer = factory( - window, - window.EvEmitter, - window.getSize, - window.fizzyUIUtils, - window.Outlayer.Item - ); - } - -}( window, function factory( window, EvEmitter, getSize, utils, Item ) { -'use strict'; - -// ----- vars ----- // - -var console = window.console; -var jQuery = window.jQuery; -var noop = function() {}; - -// -------------------------- Outlayer -------------------------- // - -// globally unique identifiers -var GUID = 0; -// internal store of all Outlayer intances -var instances = {}; - - -/** - * @param {Element, String} element - * @param {Object} options - * @constructor - */ -function Outlayer( element, options ) { - var queryElement = utils.getQueryElement( element ); - if ( !queryElement ) { - if ( console ) { - console.error( 'Bad element for ' + this.constructor.namespace + - ': ' + ( queryElement || element ) ); - } - return; - } - this.element = queryElement; - // add jQuery - if ( jQuery ) { - this.$element = jQuery( this.element ); - } - - // options - this.options = utils.extend( {}, this.constructor.defaults ); - this.option( options ); - - // add id for Outlayer.getFromElement - var id = ++GUID; - this.element.outlayerGUID = id; // expando - instances[ id ] = this; // associate via id - - // kick it off - this._create(); - - var isInitLayout = this._getOption('initLayout'); - if ( isInitLayout ) { - this.layout(); - } -} - -// settings are for internal use only -Outlayer.namespace = 'outlayer'; -Outlayer.Item = Item; - -// default options -Outlayer.defaults = { - containerStyle: { - position: 'relative' - }, - initLayout: true, - originLeft: true, - originTop: true, - resize: true, - resizeContainer: true, - // item options - transitionDuration: '0.4s', - hiddenStyle: { - opacity: 0, - transform: 'scale(0.001)' - }, - visibleStyle: { - opacity: 1, - transform: 'scale(1)' - } -}; - -var proto = Outlayer.prototype; -// inherit EvEmitter -utils.extend( proto, EvEmitter.prototype ); - -/** - * set options - * @param {Object} opts - */ -proto.option = function( opts ) { - utils.extend( this.options, opts ); -}; - -/** - * get backwards compatible option value, check old name - */ -proto._getOption = function( option ) { - var oldOption = this.constructor.compatOptions[ option ]; - return oldOption && this.options[ oldOption ] !== undefined ? - this.options[ oldOption ] : this.options[ option ]; -}; - -Outlayer.compatOptions = { - // currentName: oldName - initLayout: 'isInitLayout', - horizontal: 'isHorizontal', - layoutInstant: 'isLayoutInstant', - originLeft: 'isOriginLeft', - originTop: 'isOriginTop', - resize: 'isResizeBound', - resizeContainer: 'isResizingContainer' -}; - -proto._create = function() { - // get items from children - this.reloadItems(); - // elements that affect layout, but are not laid out - this.stamps = []; - this.stamp( this.options.stamp ); - // set container style - utils.extend( this.element.style, this.options.containerStyle ); - - // bind resize method - var canBindResize = this._getOption('resize'); - if ( canBindResize ) { - this.bindResize(); - } -}; - -// goes through all children again and gets bricks in proper order -proto.reloadItems = function() { - // collection of item elements - this.items = this._itemize( this.element.children ); -}; - - -/** - * turn elements into Outlayer.Items to be used in layout - * @param {Array or NodeList or HTMLElement} elems - * @returns {Array} items - collection of new Outlayer Items - */ -proto._itemize = function( elems ) { - - var itemElems = this._filterFindItemElements( elems ); - var Item = this.constructor.Item; - - // create new Outlayer Items for collection - var items = []; - for ( var i=0; i < itemElems.length; i++ ) { - var elem = itemElems[i]; - var item = new Item( elem, this ); - items.push( item ); - } - - return items; -}; - -/** - * get item elements to be used in layout - * @param {Array or NodeList or HTMLElement} elems - * @returns {Array} items - item elements - */ -proto._filterFindItemElements = function( elems ) { - return utils.filterFindElements( elems, this.options.itemSelector ); -}; - -/** - * getter method for getting item elements - * @returns {Array} elems - collection of item elements - */ -proto.getItemElements = function() { - return this.items.map( function( item ) { - return item.element; - }); -}; - -// ----- init & layout ----- // - -/** - * lays out all items - */ -proto.layout = function() { - this._resetLayout(); - this._manageStamps(); - - // don't animate first layout - var layoutInstant = this._getOption('layoutInstant'); - var isInstant = layoutInstant !== undefined ? - layoutInstant : !this._isLayoutInited; - this.layoutItems( this.items, isInstant ); - - // flag for initalized - this._isLayoutInited = true; -}; - -// _init is alias for layout -proto._init = proto.layout; - -/** - * logic before any new layout - */ -proto._resetLayout = function() { - this.getSize(); -}; - - -proto.getSize = function() { - this.size = getSize( this.element ); -}; - -/** - * get measurement from option, for columnWidth, rowHeight, gutter - * if option is String -> get element from selector string, & get size of element - * if option is Element -> get size of element - * else use option as a number - * - * @param {String} measurement - * @param {String} size - width or height - * @private - */ -proto._getMeasurement = function( measurement, size ) { - var option = this.options[ measurement ]; - var elem; - if ( !option ) { - // default to 0 - this[ measurement ] = 0; - } else { - // use option as an element - if ( typeof option == 'string' ) { - elem = this.element.querySelector( option ); - } else if ( option instanceof HTMLElement ) { - elem = option; - } - // use size of element, if element - this[ measurement ] = elem ? getSize( elem )[ size ] : option; - } -}; - -/** - * layout a collection of item elements - * @api public - */ -proto.layoutItems = function( items, isInstant ) { - items = this._getItemsForLayout( items ); - - this._layoutItems( items, isInstant ); - - this._postLayout(); -}; - -/** - * get the items to be laid out - * you may want to skip over some items - * @param {Array} items - * @returns {Array} items - */ -proto._getItemsForLayout = function( items ) { - return items.filter( function( item ) { - return !item.isIgnored; - }); -}; - -/** - * layout items - * @param {Array} items - * @param {Boolean} isInstant - */ -proto._layoutItems = function( items, isInstant ) { - this._emitCompleteOnItems( 'layout', items ); - - if ( !items || !items.length ) { - // no items, emit event with empty array - return; - } - - var queue = []; - - items.forEach( function( item ) { - // get x/y object from method - var position = this._getItemLayoutPosition( item ); - // enqueue - position.item = item; - position.isInstant = isInstant || item.isLayoutInstant; - queue.push( position ); - }, this ); - - this._processLayoutQueue( queue ); -}; - -/** - * get item layout position - * @param {Outlayer.Item} item - * @returns {Object} x and y position - */ -proto._getItemLayoutPosition = function( /* item */ ) { - return { - x: 0, - y: 0 - }; -}; - -/** - * iterate over array and position each item - * Reason being - separating this logic prevents 'layout invalidation' - * thx @paul_irish - * @param {Array} queue - */ -proto._processLayoutQueue = function( queue ) { - this.updateStagger(); - queue.forEach( function( obj, i ) { - this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i ); - }, this ); -}; - -// set stagger from option in milliseconds number -proto.updateStagger = function() { - var stagger = this.options.stagger; - if ( stagger === null || stagger === undefined ) { - this.stagger = 0; - return; - } - this.stagger = getMilliseconds( stagger ); - return this.stagger; -}; - -/** - * Sets position of item in DOM - * @param {Outlayer.Item} item - * @param {Number} x - horizontal position - * @param {Number} y - vertical position - * @param {Boolean} isInstant - disables transitions - */ -proto._positionItem = function( item, x, y, isInstant, i ) { - if ( isInstant ) { - // if not transition, just set CSS - item.goTo( x, y ); - } else { - item.stagger( i * this.stagger ); - item.moveTo( x, y ); - } -}; - -/** - * Any logic you want to do after each layout, - * i.e. size the container - */ -proto._postLayout = function() { - this.resizeContainer(); -}; - -proto.resizeContainer = function() { - var isResizingContainer = this._getOption('resizeContainer'); - if ( !isResizingContainer ) { - return; - } - var size = this._getContainerSize(); - if ( size ) { - this._setContainerMeasure( size.width, true ); - this._setContainerMeasure( size.height, false ); - } -}; - -/** - * Sets width or height of container if returned - * @returns {Object} size - * @param {Number} width - * @param {Number} height - */ -proto._getContainerSize = noop; - -/** - * @param {Number} measure - size of width or height - * @param {Boolean} isWidth - */ -proto._setContainerMeasure = function( measure, isWidth ) { - if ( measure === undefined ) { - return; - } - - var elemSize = this.size; - // add padding and border width if border box - if ( elemSize.isBorderBox ) { - measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + - elemSize.borderLeftWidth + elemSize.borderRightWidth : - elemSize.paddingBottom + elemSize.paddingTop + - elemSize.borderTopWidth + elemSize.borderBottomWidth; - } - - measure = Math.max( measure, 0 ); - this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; -}; - -/** - * emit eventComplete on a collection of items events - * @param {String} eventName - * @param {Array} items - Outlayer.Items - */ -proto._emitCompleteOnItems = function( eventName, items ) { - var _this = this; - function onComplete() { - _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); - } - - var count = items.length; - if ( !items || !count ) { - onComplete(); - return; - } - - var doneCount = 0; - function tick() { - doneCount++; - if ( doneCount == count ) { - onComplete(); - } - } - - // bind callback - items.forEach( function( item ) { - item.once( eventName, tick ); - }); -}; - -/** - * emits events via EvEmitter and jQuery events - * @param {String} type - name of event - * @param {Event} event - original event - * @param {Array} args - extra arguments - */ -proto.dispatchEvent = function( type, event, args ) { - // add original event to arguments - var emitArgs = event ? [ event ].concat( args ) : args; - this.emitEvent( type, emitArgs ); - - if ( jQuery ) { - // set this.$element - this.$element = this.$element || jQuery( this.element ); - if ( event ) { - // create jQuery event - var $event = jQuery.Event( event ); - $event.type = type; - this.$element.trigger( $event, args ); - } else { - // just trigger with type if no event available - this.$element.trigger( type, args ); - } - } -}; - -// -------------------------- ignore & stamps -------------------------- // - - -/** - * keep item in collection, but do not lay it out - * ignored items do not get skipped in layout - * @param {Element} elem - */ -proto.ignore = function( elem ) { - var item = this.getItem( elem ); - if ( item ) { - item.isIgnored = true; - } -}; - -/** - * return item to layout collection - * @param {Element} elem - */ -proto.unignore = function( elem ) { - var item = this.getItem( elem ); - if ( item ) { - delete item.isIgnored; - } -}; - -/** - * adds elements to stamps - * @param {NodeList, Array, Element, or String} elems - */ -proto.stamp = function( elems ) { - elems = this._find( elems ); - if ( !elems ) { - return; - } - - this.stamps = this.stamps.concat( elems ); - // ignore - elems.forEach( this.ignore, this ); -}; - -/** - * removes elements to stamps - * @param {NodeList, Array, or Element} elems - */ -proto.unstamp = function( elems ) { - elems = this._find( elems ); - if ( !elems ){ - return; - } - - elems.forEach( function( elem ) { - // filter out removed stamp elements - utils.removeFrom( this.stamps, elem ); - this.unignore( elem ); - }, this ); -}; - -/** - * finds child elements - * @param {NodeList, Array, Element, or String} elems - * @returns {Array} elems - */ -proto._find = function( elems ) { - if ( !elems ) { - return; - } - // if string, use argument as selector string - if ( typeof elems == 'string' ) { - elems = this.element.querySelectorAll( elems ); - } - elems = utils.makeArray( elems ); - return elems; -}; - -proto._manageStamps = function() { - if ( !this.stamps || !this.stamps.length ) { - return; - } - - this._getBoundingRect(); - - this.stamps.forEach( this._manageStamp, this ); -}; - -// update boundingLeft / Top -proto._getBoundingRect = function() { - // get bounding rect for container element - var boundingRect = this.element.getBoundingClientRect(); - var size = this.size; - this._boundingRect = { - left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, - top: boundingRect.top + size.paddingTop + size.borderTopWidth, - right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), - bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) - }; -}; - -/** - * @param {Element} stamp -**/ -proto._manageStamp = noop; - -/** - * get x/y position of element relative to container element - * @param {Element} elem - * @returns {Object} offset - has left, top, right, bottom - */ -proto._getElementOffset = function( elem ) { - var boundingRect = elem.getBoundingClientRect(); - var thisRect = this._boundingRect; - var size = getSize( elem ); - var offset = { - left: boundingRect.left - thisRect.left - size.marginLeft, - top: boundingRect.top - thisRect.top - size.marginTop, - right: thisRect.right - boundingRect.right - size.marginRight, - bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom - }; - return offset; -}; - -// -------------------------- resize -------------------------- // - -// enable event handlers for listeners -// i.e. resize -> onresize -proto.handleEvent = utils.handleEvent; - -/** - * Bind layout to window resizing - */ -proto.bindResize = function() { - window.addEventListener( 'resize', this ); - this.isResizeBound = true; -}; - -/** - * Unbind layout to window resizing - */ -proto.unbindResize = function() { - window.removeEventListener( 'resize', this ); - this.isResizeBound = false; -}; - -proto.onresize = function() { - this.resize(); -}; - -utils.debounceMethod( Outlayer, 'onresize', 100 ); - -proto.resize = function() { - // don't trigger if size did not change - // or if resize was unbound. See #9 - if ( !this.isResizeBound || !this.needsResizeLayout() ) { - return; - } - - this.layout(); -}; - -/** - * check if layout is needed post layout - * @returns Boolean - */ -proto.needsResizeLayout = function() { - var size = getSize( this.element ); - // check that this.size and size are there - // IE8 triggers resize on body size change, so they might not be - var hasSizes = this.size && size; - return hasSizes && size.innerWidth !== this.size.innerWidth; -}; - -// -------------------------- methods -------------------------- // - -/** - * add items to Outlayer instance - * @param {Array or NodeList or Element} elems - * @returns {Array} items - Outlayer.Items -**/ -proto.addItems = function( elems ) { - var items = this._itemize( elems ); - // add items to collection - if ( items.length ) { - this.items = this.items.concat( items ); - } - return items; -}; - -/** - * Layout newly-appended item elements - * @param {Array or NodeList or Element} elems - */ -proto.appended = function( elems ) { - var items = this.addItems( elems ); - if ( !items.length ) { - return; - } - // layout and reveal just the new items - this.layoutItems( items, true ); - this.reveal( items ); -}; - -/** - * Layout prepended elements - * @param {Array or NodeList or Element} elems - */ -proto.prepended = function( elems ) { - var items = this._itemize( elems ); - if ( !items.length ) { - return; - } - // add items to beginning of collection - var previousItems = this.items.slice(0); - this.items = items.concat( previousItems ); - // start new layout - this._resetLayout(); - this._manageStamps(); - // layout new stuff without transition - this.layoutItems( items, true ); - this.reveal( items ); - // layout previous items - this.layoutItems( previousItems ); -}; - -/** - * reveal a collection of items - * @param {Array of Outlayer.Items} items - */ -proto.reveal = function( items ) { - this._emitCompleteOnItems( 'reveal', items ); - if ( !items || !items.length ) { - return; - } - var stagger = this.updateStagger(); - items.forEach( function( item, i ) { - item.stagger( i * stagger ); - item.reveal(); - }); -}; - -/** - * hide a collection of items - * @param {Array of Outlayer.Items} items - */ -proto.hide = function( items ) { - this._emitCompleteOnItems( 'hide', items ); - if ( !items || !items.length ) { - return; - } - var stagger = this.updateStagger(); - items.forEach( function( item, i ) { - item.stagger( i * stagger ); - item.hide(); - }); -}; - -/** - * reveal item elements - * @param {Array}, {Element}, {NodeList} items - */ -proto.revealItemElements = function( elems ) { - var items = this.getItems( elems ); - this.reveal( items ); -}; - -/** - * hide item elements - * @param {Array}, {Element}, {NodeList} items - */ -proto.hideItemElements = function( elems ) { - var items = this.getItems( elems ); - this.hide( items ); -}; - -/** - * get Outlayer.Item, given an Element - * @param {Element} elem - * @param {Function} callback - * @returns {Outlayer.Item} item - */ -proto.getItem = function( elem ) { - // loop through items to get the one that matches - for ( var i=0; i < this.items.length; i++ ) { - var item = this.items[i]; - if ( item.element == elem ) { - // return item - return item; - } - } -}; - -/** - * get collection of Outlayer.Items, given Elements - * @param {Array} elems - * @returns {Array} items - Outlayer.Items - */ -proto.getItems = function( elems ) { - elems = utils.makeArray( elems ); - var items = []; - elems.forEach( function( elem ) { - var item = this.getItem( elem ); - if ( item ) { - items.push( item ); - } - }, this ); - - return items; -}; - -/** - * remove element(s) from instance and DOM - * @param {Array or NodeList or Element} elems - */ -proto.remove = function( elems ) { - var removeItems = this.getItems( elems ); - - this._emitCompleteOnItems( 'remove', removeItems ); - - // bail if no items to remove - if ( !removeItems || !removeItems.length ) { - return; - } - - removeItems.forEach( function( item ) { - item.remove(); - // remove item from collection - utils.removeFrom( this.items, item ); - }, this ); -}; - -// ----- destroy ----- // - -// remove and disable Outlayer instance -proto.destroy = function() { - // clean up dynamic styles - var style = this.element.style; - style.height = ''; - style.position = ''; - style.width = ''; - // destroy items - this.items.forEach( function( item ) { - item.destroy(); - }); - - this.unbindResize(); - - var id = this.element.outlayerGUID; - delete instances[ id ]; // remove reference to instance by id - delete this.element.outlayerGUID; - // remove data for jQuery - if ( jQuery ) { - jQuery.removeData( this.element, this.constructor.namespace ); - } - -}; - -// -------------------------- data -------------------------- // - -/** - * get Outlayer instance from element - * @param {Element} elem - * @returns {Outlayer} - */ -Outlayer.data = function( elem ) { - elem = utils.getQueryElement( elem ); - var id = elem && elem.outlayerGUID; - return id && instances[ id ]; -}; - - -// -------------------------- create Outlayer class -------------------------- // - -/** - * create a layout class - * @param {String} namespace - */ -Outlayer.create = function( namespace, options ) { - // sub-class Outlayer - var Layout = subclass( Outlayer ); - // apply new options and compatOptions - Layout.defaults = utils.extend( {}, Outlayer.defaults ); - utils.extend( Layout.defaults, options ); - Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions ); - - Layout.namespace = namespace; - - Layout.data = Outlayer.data; - - // sub-class Item - Layout.Item = subclass( Item ); - - // -------------------------- declarative -------------------------- // - - utils.htmlInit( Layout, namespace ); - - // -------------------------- jQuery bridge -------------------------- // - - // make into jQuery plugin - if ( jQuery && jQuery.bridget ) { - jQuery.bridget( namespace, Layout ); - } - - return Layout; -}; - -function subclass( Parent ) { - function SubClass() { - Parent.apply( this, arguments ); - } - - SubClass.prototype = Object.create( Parent.prototype ); - SubClass.prototype.constructor = SubClass; - - return SubClass; -} - -// ----- helpers ----- // - -// how many milliseconds are in each unit -var msUnits = { - ms: 1, - s: 1000 -}; - -// munge time-like parameter into millisecond number -// '0.4s' -> 40 -function getMilliseconds( time ) { - if ( typeof time == 'number' ) { - return time; - } - var matches = time.match( /(^\d*\.?\d*)(\w*)/ ); - var num = matches && matches[1]; - var unit = matches && matches[2]; - if ( !num.length ) { - return 0; - } - num = parseFloat( num ); - var mult = msUnits[ unit ] || 1; - return num * mult; -} - -// ----- fin ----- // - -// back in global -Outlayer.Item = Item; - -return Outlayer; - -})); - - -/***/ }), -/* 28 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_survey_core__ = __webpack_require__(4); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_survey_core___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_survey_core__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__selectBase__ = __webpack_require__(12); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MatrixС3; }); - - - -var MatrixС3 = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](MatrixС3, _super); - function MatrixС3(targetNode, question, data, options) { - var _this = _super.call(this, targetNode, question, data, options) || this; - _this.chartType = "bar"; - return _this; - } - MatrixС3.prototype.valuesSource = function () { - var question = this.question; - return question.columns; - }; - MatrixС3.prototype.getLabels = function () { - var question = this.question; - return question.rows.map(function (row) { - return __WEBPACK_IMPORTED_MODULE_1_survey_core__["ItemValue"].getTextOrHtmlByValue(question.rows, row.value); - }); - }; - MatrixС3.prototype.getData = function () { - var _this = this; - var question = this.question; - var datasets = this.valuesSource().map(function (choice) { - return question.rows.map(function (v) { return 0; }); - }); - this.data.forEach(function (rowData) { - var questionValue = rowData[_this.question.name]; - if (!!questionValue) { - question.rows.forEach(function (row, index) { - _this.getValues().forEach(function (val, dsIndex) { - if (questionValue[row.value] == val) { - datasets[dsIndex][index]++; - } - }); - }); - } - }); - return datasets; - }; - return MatrixС3; -}(__WEBPACK_IMPORTED_MODULE_2__selectBase__["a" /* SelectBaseC3 */])); - -// VisualizationManager.registerVisualizer("matrix", MatrixС3); - - -/***/ }), -/* 29 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__visualizerBase__ = __webpack_require__(2); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_c3__ = __webpack_require__(14); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_c3___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_c3__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return GaugeC3; }); - - - -var GaugeC3 = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](GaugeC3, _super); - function GaugeC3(targetNode, question, data, options) { - var _this = _super.call(this, targetNode, question, data, options) || this; - _this.targetNode = targetNode; - return _this; - } - GaugeC3.prototype.destroy = function () { - if (!this.chart) - return; - this.chart.destroy(); - }; - GaugeC3.prototype.render = function () { - this.chart = __WEBPACK_IMPORTED_MODULE_2_c3___default.a.generate({ - bindto: this.targetNode, - data: { - columns: [[this.question.title, this.result]], - type: "gauge" - }, - gauge: { - min: this.question.rateMin, - max: this.question.rateMax, - label: { - format: function (value, ratio) { - return value; - } - } - }, - color: { - pattern: [this.getRandomColor()] - } - }); - }; - Object.defineProperty(GaugeC3.prototype, "result", { - get: function () { - var _this = this; - if (this._result === undefined) { - var questionValues_1 = []; - this.data.forEach(function (rowData) { - var questionValue = rowData[_this.question.name]; - if (!!questionValue) { - questionValues_1.push(questionValue); - } - }); - this._result = - questionValues_1.reduce(function (a, b) { - return a + b; - }) / questionValues_1.length; - this._result = Math.ceil(this._result * 100) / 100; - } - return this._result; - }, - enumerable: true, - configurable: true - }); - return GaugeC3; -}(__WEBPACK_IMPORTED_MODULE_1__visualizerBase__["a" /* VisualizerBase */])); - -// VisualizationManager.registerVisualizer("rating", GaugeC3); - - -/***/ }), -/* 30 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_survey_core__ = __webpack_require__(4); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_survey_core___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_survey_core__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__selectBase__ = __webpack_require__(6); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MatrixChartJS; }); - - - -var MatrixChartJS = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](MatrixChartJS, _super); - function MatrixChartJS(targetNode, question, data, options) { - var _this = _super.call(this, targetNode, question, data, options) || this; - _this.chartType = "bar"; - return _this; - } - MatrixChartJS.prototype.valuesSource = function () { - var question = this.question; - return question.columns; - }; - MatrixChartJS.prototype.getLabels = function () { - var question = this.question; - return question.rows.map(function (row) { - return __WEBPACK_IMPORTED_MODULE_1_survey_core__["ItemValue"].getTextOrHtmlByValue(question.rows, row.value); - }); - }; - MatrixChartJS.prototype.getOptions = function () { - var options = _super.prototype.getOptions.call(this); - options.scales = undefined; - // options.scales = { - // xAxes: [{ stacked: true }], - // yAxes: [{ stacked: true }] - // } - return options; - }; - MatrixChartJS.prototype.getData = function () { - return undefined; - }; - MatrixChartJS.prototype.getDatasets = function () { - var _this = this; - var question = this.question; - var datasets = this.valuesSource().map(function (choice) { - return { - label: __WEBPACK_IMPORTED_MODULE_1_survey_core__["ItemValue"].getTextOrHtmlByValue(_this.valuesSource(), choice.value), - data: question.rows.map(function () { return 0; }), - backgroundColor: _this.getRandomColor() - }; - }); - this.data.forEach(function (rowData) { - var questionValue = rowData[_this.question.name]; - if (!!questionValue) { - question.rows.forEach(function (row, index) { - _this.getValues().forEach(function (val, dsIndex) { - if (questionValue[row.value] == val) { - datasets[dsIndex].data[index]++; - } - }); - }); - } - }); - return datasets; - }; - return MatrixChartJS; -}(__WEBPACK_IMPORTED_MODULE_2__selectBase__["a" /* SelectBaseChartJS */])); - -// VisualizationManager.registerVisualizer("matrix", MatrixChartJS); - - -/***/ }), -/* 31 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__selectBase__ = __webpack_require__(6); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return RadialGaugeChartJS; }); - - -var RadialGaugeChartJS = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](RadialGaugeChartJS, _super); - function RadialGaugeChartJS(targetNode, question, data, options) { - var _this = _super.call(this, targetNode, question, data, options) || this; - _this.chartTypes = ["doughnut", "pie"]; - _this.chartType = "doughnut"; - return _this; - } - Object.defineProperty(RadialGaugeChartJS.prototype, "result", { - get: function () { - var _this = this; - if (this._result === undefined) { - var questionValues_1 = []; - this.data.forEach(function (rowData) { - var questionValue = rowData[_this.question.name]; - if (!!questionValue) { - questionValues_1.push(questionValue); - } - }); - this._result = - questionValues_1.reduce(function (a, b) { - return a + b; - }) / questionValues_1.length; - this._result = Math.ceil(this._result * 100) / 100; - } - return this._result; - }, - enumerable: true, - configurable: true - }); - RadialGaugeChartJS.prototype.getLabels = function () { - return []; - }; - RadialGaugeChartJS.prototype.getOptions = function () { - var options = { - responsive: true, - maintainAspectRatio: false, - rotation: 1 * Math.PI, - circumference: 1 * Math.PI - }; - return options; - }; - RadialGaugeChartJS.prototype.getData = function () { - return undefined; - }; - RadialGaugeChartJS.prototype.getValues = function () { - return null; - }; - RadialGaugeChartJS.prototype.getDatasets = function () { - return [ - { - data: [ - this.result - this.question.rateMin, - this.question.rateMax - this.question.rateMin - this.result - ], - backgroundColor: [this.getRandomColor(), this.getRandomColor()] - } - ]; - }; - return RadialGaugeChartJS; -}(__WEBPACK_IMPORTED_MODULE_1__selectBase__["a" /* SelectBaseChartJS */])); - -// VisualizationManager.registerVisualizer("rating", RadialGaugeChartJS); - - -/***/ }), -/* 32 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_survey_core__ = __webpack_require__(4); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_survey_core___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_survey_core__); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__visualizationManager__ = __webpack_require__(1); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__selectBase__ = __webpack_require__(13); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MatrixPlotly; }); - - - - -var MatrixPlotly = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](MatrixPlotly, _super); - function MatrixPlotly(targetNode, question, data, options) { - return _super.call(this, targetNode, question, data, options) || this; - } - MatrixPlotly.prototype.valuesSource = function () { - var question = this.question; - return question.columns; - }; - MatrixPlotly.prototype.getLabels = function () { - var question = this.question; - return question.rows.map(function (row) { - return __WEBPACK_IMPORTED_MODULE_1_survey_core__["ItemValue"].getTextOrHtmlByValue(question.rows, row.value); - }); - }; - MatrixPlotly.prototype.getData = function () { - var _this = this; - var question = this.question; - var datasets = this.valuesSource().map(function (choice) { - return question.rows.map(function (v) { return 0; }); - }); - this.data.forEach(function (rowData) { - var questionValue = rowData[_this.question.name]; - if (!!questionValue) { - question.rows.forEach(function (row, index) { - _this.getValues().forEach(function (val, dsIndex) { - if (questionValue[row.value] == val) { - datasets[dsIndex][index]++; - } - }); - }); - } - }); - return datasets; - }; - return MatrixPlotly; -}(__WEBPACK_IMPORTED_MODULE_3__selectBase__["a" /* SelectBasePlotly */])); - -__WEBPACK_IMPORTED_MODULE_2__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("matrix", MatrixPlotly); - - -/***/ }), -/* 33 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_tslib__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__visualizerBase__ = __webpack_require__(2); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__visualizationManager__ = __webpack_require__(1); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return GaugePlotly; }); - -var Plotly = __webpack_require__(11); - - -var GaugePlotly = /** @class */ (function (_super) { - __WEBPACK_IMPORTED_MODULE_0_tslib__["a" /* __extends */](GaugePlotly, _super); - function GaugePlotly(targetElement, question, data, options) { - var _this = _super.call(this, targetElement, question, data, options) || this; - _this.targetElement = targetElement; - _this.chartTypes = ["gauge", "bullet"]; - _this.chartType = "gauge"; - _this.chartNode = document.createElement("div"); - _this.toolbarChangeHandler = function (e) { - if (_this.chartType !== e.target.value) { - _this.chartType = e.target.value; - _this.update(_this.data); - } - }; - return _this; - } - GaugePlotly.prototype.update = function (data) { - _super.prototype.update.call(this, data); - this.destroy(); - this.createChart(); - this.invokeOnUpdate(); - }; - GaugePlotly.prototype.createToolbar = function (container, changeHandler) { - var _this = this; - if (this.chartTypes.length > 0) { - var toolbar_1 = document.createElement("div"); - toolbar_1.className = "sva-question__toolbar"; - var selectWrapper = document.createElement("div"); - selectWrapper.className = "sva-question__select-wrapper"; - var select_1 = document.createElement("select"); - select_1.className = "sva-question__select"; - this.chartTypes.forEach(function (chartType) { - var option = document.createElement("option"); - option.value = chartType; - option.text = chartType; - option.selected = _this.chartType === chartType; - select_1.appendChild(option); - }); - select_1.onchange = changeHandler; - selectWrapper.appendChild(select_1); - toolbar_1.appendChild(selectWrapper); - container.appendChild(toolbar_1); - } - }; - GaugePlotly.prototype.destroy = function () { - Plotly.purge(this.chartNode); - this._result = undefined; - }; - GaugePlotly.prototype.generateText = function (maxValue, minValue, stepsCount) { - var texts = []; - if (stepsCount === 5) { - texts = [ - "very high (" + maxValue + ")", - "high", - "medium", - "low", - "very low (" + minValue + ")" - ]; - } - else { - texts.push(maxValue); - for (var i = 0; i < stepsCount - 2; i++) { - texts.push(""); - } - texts.push(minValue); - } - if (!!GaugePlotly.generateTextsCallback) { - return GaugePlotly.generateTextsCallback(this.question, maxValue, minValue, stepsCount, texts); - } - return texts; - }; - GaugePlotly.prototype.generateValues = function (maxValue, stepsCount) { - var values = []; - for (var i = 0; i < stepsCount; i++) { - values.push(maxValue / stepsCount); - } - values.push(maxValue); - return values; - }; - GaugePlotly.prototype.generateColors = function (maxValue, minValue, stepsCount) { - var palette = this.getColors(); - var colors = []; - for (var i = 0; i < stepsCount; i++) { - colors.push(palette[i]); - } - colors.push("rgba(255, 255, 255, 0)"); - return colors; - }; - GaugePlotly.prototype.createToolbarContainer = function () { - var chartNodeContainer = document.createElement("div"); - var toolbarNodeContainer = document.createElement("div"); - chartNodeContainer.appendChild(toolbarNodeContainer); - chartNodeContainer.appendChild(this.chartNode); - this.targetElement.appendChild(chartNodeContainer); - this.createToolbar(toolbarNodeContainer, this.toolbarChangeHandler); - }; - GaugePlotly.prototype.createChart = function () { - var question = this.question; - var arrowColor = "#4e6198"; - var maxValue = question.rateMax; - var minValue = question.rateMin; - var values = this.generateValues(maxValue, GaugePlotly.stepsCount); - var text = this.generateText(maxValue, minValue, GaugePlotly.stepsCount); - var colors = this.generateColors(maxValue, minValue, GaugePlotly.stepsCount); - // Enter a speed between 0 and 180 - var level = this.result; - var data = [ - { - type: "indicator", - mode: "gauge+number", - gauge: { - shape: this.chartType, - bgcolor: "white", - bar: { color: colors[0] } - }, - value: level, - text: question.name, - domain: { x: [0, 1], y: [0, 1] } - } - ]; - var layout = { - width: 600, - height: 400, - plot_bgcolor: this.backgroundColor, - paper_bgcolor: this.backgroundColor - }; - // this.chartNode.style.maxHeight = "400px"; // fixed chart height - // this.chartNode.style.overflow = "hidden"; - var config = { - displayModeBar: false, - staticPlot: true - }; - this.chart = Plotly.newPlot(this.chartNode, data, layout, config); - }; - GaugePlotly.prototype.render = function () { - this.createToolbarContainer(); - this.createChart(); - }; - Object.defineProperty(GaugePlotly.prototype, "result", { - get: function () { - var _this = this; - if (this._result === undefined) { - var questionValues_1 = []; - this.data.forEach(function (rowData) { - var questionValue = rowData[_this.question.name]; - if (!!questionValue) { - questionValues_1.push(questionValue); - } - }); - this._result = - questionValues_1.reduce(function (a, b) { - return a + b; - }) / questionValues_1.length; - this._result = Math.ceil(this._result * 100) / 100; - } - return this._result; - }, - enumerable: true, - configurable: true - }); - GaugePlotly.stepsCount = 5; - return GaugePlotly; -}(__WEBPACK_IMPORTED_MODULE_1__visualizerBase__["a" /* VisualizerBase */])); - -__WEBPACK_IMPORTED_MODULE_2__visualizationManager__["a" /* VisualizationManager */].registerVisualizer("rating", GaugePlotly); - - -/***/ }), -/* 34 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return stopWords; }); -var stopWords = new Array("a", "about", "above", "across", "after", "again", "against", "all", "almost", "alone", "along", "already", "also", "although", "always", "among", "an", "and", "another", "any", "anybody", "anyone", "anything", "anywhere", "are", "area", "areas", "around", "as", "ask", "asked", "asking", "asks", "at", "away", "b", "back", "backed", "backing", "backs", "be", "became", "because", "become", "becomes", "been", "before", "began", "behind", "being", "beings", "best", "better", "between", "big", "both", "but", "by", "c", "came", "can", "cannot", "case", "cases", "certain", "certainly", "clear", "clearly", "come", "could", "d", "did", "differ", "different", "differently", "do", "does", "done", "down", "down", "downed", "downing", "downs", "during", "e", "each", "early", "either", "end", "ended", "ending", "ends", "enough", "even", "evenly", "ever", "every", "everybody", "everyone", "everything", "everywhere", "f", "face", "faces", "fact", "facts", "far", "felt", "few", "find", "finds", "first", "for", "four", "from", "full", "fully", "further", "furthered", "furthering", "furthers", "g", "gave", "general", "generally", "get", "gets", "give", "given", "gives", "go", "going", "good", "goods", "got", "great", "greater", "greatest", "group", "grouped", "grouping", "groups", "h", "had", "has", "have", "having", "he", "her", "here", "herself", "high", "high", "high", "higher", "highest", "him", "himself", "his", "how", "however", "i", "if", "important", "in", "interest", "interested", "interesting", "interests", "into", "is", "it", "its", "itself", "j", "just", "k", "keep", "keeps", "kind", "knew", "know", "known", "knows", "l", "large", "largely", "last", "later", "latest", "least", "less", "let", "lets", "like", "likely", "long", "longer", "longest", "m", "made", "make", "making", "man", "many", "may", "me", "member", "members", "men", "might", "more", "most", "mostly", "mr", "mrs", "much", "must", "my", "myself", "n", "necessary", "need", "needed", "needing", "needs", "never", "new", "new", "newer", "newest", "next", "no", "nobody", "non", "noone", "not", "nothing", "now", "nowhere", "number", "numbers", "o", "of", "off", "often", "old", "older", "oldest", "on", "once", "one", "only", "open", "opened", "opening", "opens", "or", "order", "ordered", "ordering", "orders", "other", "others", "our", "out", "over", "p", "part", "parted", "parting", "parts", "per", "perhaps", "place", "places", "point", "pointed", "pointing", "points", "possible", "present", "presented", "presenting", "presents", "problem", "problems", "put", "puts", "q", "quite", "r", "rather", "really", "right", "right", "room", "rooms", "s", "said", "same", "saw", "say", "says", "second", "seconds", "see", "seem", "seemed", "seeming", "seems", "sees", "several", "shall", "she", "should", "show", "showed", "showing", "shows", "side", "sides", "since", "small", "smaller", "smallest", "so", "some", "somebody", "someone", "something", "somewhere", "state", "states", "still", "still", "such", "sure", "t", "take", "taken", "than", "that", "the", "their", "them", "then", "there", "therefore", "these", "they", "thing", "things", "think", "thinks", "this", "those", "though", "thought", "thoughts", "three", "through", "thus", "to", "today", "together", "too", "took", "toward", "turn", "turned", "turning", "turns", "two", "u", "under", "until", "up", "upon", "us", "use", "used", "uses", "v", "very", "w", "want", "wanted", "wanting", "wants", "was", "way", "ways", "we", "well", "wells", "went", "were", "what", "when", "where", "whether", "which", "while", "who", "whole", "whose", "why", "will", "with", "within", "without", "work", "worked", "working", "works", "would", "x", "y", "year", "years", "yet", "you", "young", "younger", "youngest", "your", "yours", "z"); - - -/***/ }), -/* 35 */ -/***/ (function(module, exports) { - -var g; - -// This works in non-strict mode -g = (function() { - return this; -})(); - -try { - // This works if eval is allowed (see CSP) - g = g || Function("return this")() || (1,eval)("this"); -} catch(e) { - // This works if the window reference is available - if(typeof window === "object") - g = window; -} - -// g can still be undefined, but nothing to do about it... -// We return undefined, instead of nothing here, so it's -// easier to handle this case. if(!global) { ...} - -module.exports = g; - - -/***/ }), -/* 36 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_36__; - -/***/ }), -/* 37 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_37__; - -/***/ }), -/* 38 */ -/***/ (function(module, exports) { - -module.exports = __WEBPACK_EXTERNAL_MODULE_38__; - -/***/ }), -/* 39 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__visualizerBase__ = __webpack_require__(2); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "VisualizerBase", function() { return __WEBPACK_IMPORTED_MODULE_0__visualizerBase__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__visualizationManager__ = __webpack_require__(1); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "VisualizationManager", function() { return __WEBPACK_IMPORTED_MODULE_1__visualizationManager__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__visualizationPanel__ = __webpack_require__(7); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "VisualizationPanel", function() { return __WEBPACK_IMPORTED_MODULE_2__visualizationPanel__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__visualizationPanelDynamic__ = __webpack_require__(8); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "VisualizationPanelDynamic", function() { return __WEBPACK_IMPORTED_MODULE_3__visualizationPanelDynamic__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__visualizationMatrixDynamic__ = __webpack_require__(19); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "VisualizationMatrixDynamic", function() { return __WEBPACK_IMPORTED_MODULE_4__visualizationMatrixDynamic__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__datatables_datatables__ = __webpack_require__(17); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "DataTables", function() { return __WEBPACK_IMPORTED_MODULE_5__datatables_datatables__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__chartjs_index__ = __webpack_require__(16); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MatrixChartJS", function() { return __WEBPACK_IMPORTED_MODULE_6__chartjs_index__["a"]; }); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "SelectBaseChartJS", function() { return __WEBPACK_IMPORTED_MODULE_6__chartjs_index__["b"]; }); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "RadialGaugeChartJS", function() { return __WEBPACK_IMPORTED_MODULE_6__chartjs_index__["c"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__c3_index__ = __webpack_require__(15); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MatrixС3", function() { return __WEBPACK_IMPORTED_MODULE_7__c3_index__["a"]; }); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "SelectBaseC3", function() { return __WEBPACK_IMPORTED_MODULE_7__c3_index__["b"]; }); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GaugeC3", function() { return __WEBPACK_IMPORTED_MODULE_7__c3_index__["c"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__plotly_index__ = __webpack_require__(18); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "SelectBasePlotly", function() { return __WEBPACK_IMPORTED_MODULE_8__plotly_index__["a"]; }); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GaugePlotly", function() { return __WEBPACK_IMPORTED_MODULE_8__plotly_index__["b"]; }); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MatrixPlotly", function() { return __WEBPACK_IMPORTED_MODULE_8__plotly_index__["c"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__wordcloud_wordcloud__ = __webpack_require__(20); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "WordCloud", function() { return __WEBPACK_IMPORTED_MODULE_9__wordcloud_wordcloud__["a"]; }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__wordcloud_stopwords_index__ = __webpack_require__(9); -/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "textHelper", function() { return __WEBPACK_IMPORTED_MODULE_10__wordcloud_stopwords_index__["a"]; }); - - - - - - - - - - - - - -/***/ }) -/******/ ]); -}); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwid2VicGFjazovLy93ZWJwYWNrL2Jvb3RzdHJhcCBkMGFmZTgwYzg3Njg0ZGVlOGYyNSIsIndlYnBhY2s6Ly8vLi9zcmMvdXRpbHMvaGVscGVycy50cyIsIndlYnBhY2s6Ly8vLi9zcmMvdmlzdWFsaXphdGlvbk1hbmFnZXIudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3Zpc3VhbGl6ZXJCYXNlLnRzIiwid2VicGFjazovLy8uL3NyYy9zZWxlY3RCYXNlLnRzIiwid2VicGFjazovLy9leHRlcm5hbCB7XCJyb290XCI6XCJTdXJ2ZXlcIixcImNvbW1vbmpzMlwiOlwic3VydmV5LWNvcmVcIixcImNvbW1vbmpzXCI6XCJzdXJ2ZXktY29yZVwiLFwiYW1kXCI6XCJzdXJ2ZXktY29yZVwifSIsIndlYnBhY2s6Ly8vLi9+L2dldC1zaXplL2dldC1zaXplLmpzIiwid2VicGFjazovLy8uL3NyYy9jaGFydGpzL3NlbGVjdEJhc2UudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3Zpc3VhbGl6YXRpb25QYW5lbC50cyIsIndlYnBhY2s6Ly8vLi9zcmMvdmlzdWFsaXphdGlvblBhbmVsRHluYW1pYy50cyIsIndlYnBhY2s6Ly8vLi9zcmMvd29yZGNsb3VkL3N0b3B3b3Jkcy9pbmRleC50cyIsIndlYnBhY2s6Ly8vLi9+L2V2LWVtaXR0ZXIvZXYtZW1pdHRlci5qcyIsIndlYnBhY2s6Ly8vLi9+L3Bsb3RseS5qcy1kaXN0L3Bsb3RseS5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvYzMvc2VsZWN0QmFzZS50cyIsIndlYnBhY2s6Ly8vLi9zcmMvcGxvdGx5L3NlbGVjdEJhc2UudHMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIHtcInJvb3RcIjpcImMzXCIsXCJjb21tb25qczJcIjpcImMzXCIsXCJjb21tb25qc1wiOlwiYzNcIixcImFtZFwiOlwiYzNcIn0iLCJ3ZWJwYWNrOi8vLy4vc3JjL2MzL2luZGV4LnRzIiwid2VicGFjazovLy8uL3NyYy9jaGFydGpzL2luZGV4LnRzIiwid2VicGFjazovLy8uL3NyYy9kYXRhdGFibGVzL2RhdGF0YWJsZXMudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3Bsb3RseS9pbmRleC50cyIsIndlYnBhY2s6Ly8vLi9zcmMvdmlzdWFsaXphdGlvbk1hdHJpeER5bmFtaWMudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL3dvcmRjbG91ZC93b3JkY2xvdWQudHMiLCJ3ZWJwYWNrOi8vLy4vfi9kZXNhbmRyby1tYXRjaGVzLXNlbGVjdG9yL21hdGNoZXMtc2VsZWN0b3IuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2RhdGF0YWJsZXMvZGF0YXRhYmxlcy5zY3NzIiwid2VicGFjazovLy8uL3NyYy9pbmRleC5zY3NzIiwid2VicGFjazovLy8uL34vZml6enktdWktdXRpbHMvdXRpbHMuanMiLCJ3ZWJwYWNrOi8vLy4vfi9tYXNvbnJ5LWxheW91dC9tYXNvbnJ5LmpzIiwid2VicGFjazovLy8uL34vb3V0bGF5ZXIvaXRlbS5qcyIsIndlYnBhY2s6Ly8vLi9+L291dGxheWVyL291dGxheWVyLmpzIiwid2VicGFjazovLy8uL3NyYy9jMy9tYXRyaXgudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2MzL3JhdGluZy50cyIsIndlYnBhY2s6Ly8vLi9zcmMvY2hhcnRqcy9tYXRyaXgudHMiLCJ3ZWJwYWNrOi8vLy4vc3JjL2NoYXJ0anMvcmF0aW5nLnRzIiwid2VicGFjazovLy8uL3NyYy9wbG90bHkvbWF0cml4LnRzIiwid2VicGFjazovLy8uL3NyYy9wbG90bHkvcmF0aW5nLnRzIiwid2VicGFjazovLy8uL3NyYy93b3JkY2xvdWQvc3RvcHdvcmRzL2VuZ2xpc2gudHMiLCJ3ZWJwYWNrOi8vLyh3ZWJwYWNrKS9idWlsZGluL2dsb2JhbC5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwge1wicm9vdFwiOlwiQ2hhcnRcIixcImNvbW1vbmpzMlwiOlwiY2hhcnQuanNcIixcImNvbW1vbmpzXCI6XCJjaGFydC5qc1wiLFwiYW1kXCI6XCJjaGFydC5qc1wifSIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwge1wicm9vdFwiOlwiV29yZENsb3VkXCIsXCJjb21tb25qczJcIjpcIndvcmRjbG91ZFwiLFwiY29tbW9uanNcIjpcIndvcmRjbG91ZFwiLFwiYW1kXCI6XCJ3b3JkY2xvdWRcIn0iLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIHtcInJvb3RcIjpcImpRdWVyeVwiLFwiY29tbW9uanMyXCI6XCJqcXVlcnlcIixcImNvbW1vbmpzXCI6XCJqcXVlcnlcIixcImFtZFwiOlwianF1ZXJ5XCJ9Iiwid2VicGFjazovLy8uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRCxPO0FDVkE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsbURBQTJDLGNBQWM7O0FBRXpEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQTJCLDBCQUEwQixFQUFFO0FBQ3ZELHlDQUFpQyxlQUFlO0FBQ2hEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhEQUFzRCwrREFBK0Q7O0FBRXJIO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7Ozs7Ozs7O0FDaEVPLElBQUksUUFBUSxHQUNYLE1BQU8sQ0FBQyxRQUFRLENBQUM7SUFDdkIsVUFBUyxNQUFXO1FBQ2xCLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ25ELENBQUMsR0FB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QUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCOztBQUVsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0NBQW9DO0FBQ3BDLDZCQUE2QixtQ0FBbUM7O0FBRWhFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOzs7QUFHTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFF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QTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNB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QTtBQUNBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxnREFBZ0QsY0FBYzs7QUFFOUQsQ0FBQzs7QUFFRCxDQUFDLEVBQUUsMkZBQTJGO0FBQzlGO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0NBQXNDO0FBQ3RDLENBQUMseURBQXlEOztBQUUxRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2Qjs7QUFFN0I7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFD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Q0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCLGdEQUFnRDs7QUFFaEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNILHNCQUFzQjs7QUFFdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDRDQUE0QyxLQUFLOztBQUVqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsbUNBQW1DLE9BQU87QUFDMUM7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLHlEQUF5RDtBQUN6RDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQjtBQUNBLFdBQVcsU0FBUztBQUNwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyx5SkFBeUo7QUFDMUosQ0FBQyxFQUFFLHFEQUFxRDtBQUN4RDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQSxnQkFBZ0IsTUFBTTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxNQUFNO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEVBQUUsMEJBQTBCO0FBQzdCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0MsU0FBUztBQUMzQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLFNBQVM7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQixTQUFTO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMENBQTBDLFVBQVU7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsdUJBQXVCO0FBQzFCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHVCQUF1QjtBQUMxQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMkdBQTJHO0FBQzlHOztBQUVB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Q0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCLDRCQUE0QixjQUFjO0FBQzFDLDRCQUE0QixjQUFjO0FBQzFDLDRCQUE0QixjQUFjO0FBQzFDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCO0FBQ0Esa0JBQWtCLEdBQUc7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsU0FBUztBQUNoQzs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNDQUFzQyxzQkFBc0I7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsdUJBQXVCLFNBQVM7QUFDaEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLFNBQVM7QUFDMUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1CQUFtQixpQkFBaUI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQixpQkFBaUI7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQiw0QkFBNEI7QUFDN0M7QUFDQTs7QUFFQSxpQkFBaUIsYUFBYTtBQUM5QjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsaUJBQWlCLGFBQWE7QUFDOUI7QUFDQTs7QUFFQTtBQUNBOztBQUVBLFlBQVksZUFBZTtBQUMzQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxxQkFBcUIsZ0JBQWdCO0FBQ3JDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1CQUFtQixpQkFBaUI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsbUJBQW1CLGdCQUFnQjtBQUNuQztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxtQkFBbUIsY0FBYztBQUNqQztBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsY0FBYztBQUNqQztBQUNBOztBQUVBO0FBQ0EsWUFBWSxjQUFjO0FBQzFCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsaUJBQWlCO0FBQ3BDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsY0FBYztBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsNkJBQTZCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsWUFBWSxjQUFjO0FBQzFCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUJBQW1CLGNBQWM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVLDZCQUE2QjtBQUN2QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsWUFBWSxjQUFjO0FBQzFCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsU0FBUztBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0RBQW9ELFdBQVc7QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUIsb0JBQW9CO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9EQUFvRCxXQUFXO0FBQy9EO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVB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QTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsaUJBQWlCO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQixjQUFjO0FBQ25DO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx1QkFBdUIsUUFBUTtBQUMvQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQ0FBaUMsUUFBUTtBQUN6QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUNBQWlDLFFBQVE7QUFDekM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsNkJBQTZCLG1DQUFtQztBQUNoRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw2QkFBNkIsbUNBQW1DO0FBQ2hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsNkJBQTZCLG1DQUFtQztBQUNoRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDZCQUE2QixtQ0FBbUM7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsdUJBQXVCLDBCQUEwQjtBQUNqRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUIsZ0NBQWdDO0FBQ25EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQ0FBaUMsUUFBUTtBQUN6QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsWUFBWTtBQUMvQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCLGtCQUFrQjtBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUIsZ0JBQWdCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLGdCQUFnQjtBQUNuQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLG9CQUFvQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLGdCQUFnQjtBQUNuQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDRCQUE0QixRQUFRO0FBQ3BDO0FBQ0EsNkJBQTZCLFFBQVE7QUFDckM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsRUFBRSxrR0FBa0c7QUFDckc7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsT0FBTztBQUMzQjtBQUNBLG9DO0FBQ0EsdUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixZQUFZO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsWUFBWTtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixZQUFZO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxFQUFFLGtCQUFrQjtBQUNyQjs7QUFFQTs7QUFFQSxzREFBc0QsSUFBSSxVQUFVLE1BQU0sd0JBQXdCLEtBQUssWUFBWSxJQUFJLEtBQUssYUFBYSxxQkFBcUIsV0FBVyxvQkFBb0I7O0FBRTdMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1CQUFtQixVQUFVO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsUUFBUTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0JBQW9CLFlBQVk7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHFCQUFxQixVQUFVO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixXQUFXO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDREQUE0RCxXQUFXO0FBQ3ZFO0FBQ0EsQ0FBQyxjQUFjO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxDQUFDO0FBQ0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsU0FBUztBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsU0FBUztBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsU0FBUztBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsU0FBUztBQUM1QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2YsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQixvREFBb0QsWUFBWTtBQUNyRjtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLFlBQVk7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsdUNBQXVDLFNBQVM7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZUFBZSxpQkFBaUI7QUFDaEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhLGlCQUFpQjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLFNBQVM7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixTQUFTO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixTQUFTO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRCxFQUFFO0FBQ25EO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxpQkFBaUIsU0FBUztBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLGVBQWU7QUFDdkM7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0Esd0JBQXdCLFFBQVE7QUFDaEM7QUFDQSxxQkFBcUIsZUFBZTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixZQUFZO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEscUJBQXFCLFNBQVM7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHFCQUFxQixTQUFTO0FBQzlCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLHFCQUFxQixTQUFTO0FBQzlCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixrQkFBa0I7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCO0FBQ2xCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EseUJBQXlCLFFBQVE7QUFDakM7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1CLFNBQVM7QUFDNUI7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxpQkFBaUI7QUFDaEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLFlBQVk7QUFDN0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlCQUFpQixnQkFBZ0I7QUFDakM7QUFDQTtBQUNB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLGdCQUFnQjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixLQUFLO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDJCQUEyQjtBQUM5Qjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsTUFBTTtBQUNyQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxH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O0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxZQUFZO0FBQ2Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSx5Q0FBeUM7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMscUlBQXFJO0FBQ3RJLENBQUMsRUFBRSxrREFBa0Q7QUFDckQ7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsb0RBQW9EO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsWUFBWTtBQUNm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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEs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LEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLG9JQUFvSTtBQUN2STtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQyxDQUFDLDRCQUE0Qjs7QUFFN0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGtCQUFrQixTQUFTO0FBQzNCLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0RBQWtEO0FBQ2xEOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDJDQUEyQztBQUMzQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EscUVBQXFFLFNB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Q0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw4Q0FBOEMsY0FBYzs7QUFFNUQsQ0FBQzs7QUFFRCxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQztBQUN0QyxDQUFDLDRCQUE0Qjs7QUFFN0IsWUFBWTs7QUFFWjtBQUNBLDhDQUE4QyxJQUFJLE9BQU87QUFDekQ7QUFDQTtB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O0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTCxlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwyQ0FBMkMsT0FBTztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGlCQUFpQixPQUFPO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDBCQUEwQixPQUFPO0FBQ2pDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHlCQUF5QixPQUFPO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxQ0FBcUMsT0FBTztBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLDJDQUEyQyxPQUFPO0FBQ2xEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLDJDQUEyQyxPQUFPO0FBQ2xEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw4Q0FBOEMsY0FBYzs7QUFFNUQsQ0FBQzs7QUFFRCxDQUFDLEVBQUUsdUVBQXVFO0FBQzFFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDLENBQUMsNEJBQTRCOztBQUU3QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0QsT0FBTztBQUMzRDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQyxRQUFRO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0QsT0FBTztBQUN6RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0I7QUFDeEIsa0JBQWtCLGtDQUFrQztBQUNwRDtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQixRQUFRO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsYUFBYSxjQUFjO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxhQUFhLGtCQUFrQjtBQUMvQixtQkFBbUIsY0FBYztBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixjQUFjO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUJBQW1CLE9BQU87QUFDMUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUJBQW1CLHdDQUF3Qzs7QUFFM0Q7QUFDQSxhQUFhLE9BQU87O0FBRXBCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0JBQXdCLE9BQU87QUFDL0I7QUFDQSx3QkFBd0IsT0FBTztBQUMvQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxlQUFlLFVBQVU7QUFDekI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvQ0FBb0Msb0NBQW9DLEtBQUssRUFBRTtBQUMvRTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEIsZ0JBQWdCO0FBQ2hCLGFBQWE7QUFDYixhQUFhO0FBQ2IsYUFBYTtBQUNiLGFBQWE7QUFDYixnQkFBZ0I7QUFDaEIsYUFBYTtBQUNiOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLFFBQVE7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLG9DQUFvQztBQUNwQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVUsUUFBUTtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLHVCQUF1QixPQUFPO0FBQzlEO0FBQ0E7O0FBRUE7QUFDQSxxQkFBcUIsOERBQThEO0FBQ25GO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDZCQUE2QixPQUFPO0FBQ3BDO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlEQUFpRCxPQUFPO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhDQUE4QyxjQUFjOztBQUU1RCxDQUFDOztBQUVELENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDLENBQUMsb0NBQW9DOztBQUVyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGFBQWEsUUFBUTtBQUNyQixRQUFRLFFBQVE7O0FBRWhCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNB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O0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUMsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDBGQUEwRjs7QUFFMUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRDtBQUNuRCxvREFBb0Q7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0MsT0FBTztBQUN6QztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEMsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxnQkFBZ0I7QUFDOUIsK0NBQStDO0FBQy9DO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxZQUFZLGdEQUFnRDtBQUM1RDtBQUNBLG1CQUFtQixPQUFPO0FBQzFCO0FBQ0Esc0NBQXNDLHFEQUFxRDtBQUMzRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsOENBQThDLGNBQWM7O0FBRTVELENBQUM7O0FBRUQsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckMsQ0FBQyxtQ0FBbUM7O0FBRXBDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx5QkFBeUI7QUFDekI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFD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QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLE9BQU87QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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O0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhCQUE4Qiw0QkFBNEI7QUFDMUQsOEJBQThCLGtEQUFrRDtBQUNoRiw4QkFBOEIsNEJBQTRCO0FBQzFELG1DQUFtQztBQUNuQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4QkFBOEI7QUFDOUIsOEJBQThCO0FBQzlCLDhCQUE4QixrR0FBa0c7QUFDaEksOEJBQThCO0FBQzlCLG1DQUFtQztBQUNuQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNB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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRTtBQUN0RSxLQUFLO0FBQ0wsd0ZBQXdGO0FBQ3hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQ7QUFDbkQ7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzRkFBc0YsU0FBUztBQUMvRiw0REFBNEQsU0FBUztBQUNyRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRFQUE0RTtBQUM1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMO0FBQ0Esd0VBQXdFO0FBQ3hFLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELE9BQU87QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlELE9BQU87QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0QsRUFBRTtBQUNwRCxzQkFBc0I7QUFDdEI7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLFNBQVM7QUFDOUM7QUFDQTtBQUNBLHdDQUF3QyxTQUFTO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLFNBQVM7QUFDOUMseURBQXlELFNBQVM7QUFDbEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Q7QUFDaEQ7QUFDQTtBQUNBO0FBQ0Esb0VBQW9FO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscURBQXFEO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsU0FBUztBQUM3QjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixTQUFTO0FBQzdCO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixTQUFTO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLG9CQUFvQixVQUFVO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsY0FBYyxNQUFNO0FBQ3BCO0FBQ0E7QUFDQSxjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DLE9BQU87QUFDM0M7QUFDQTtBQUNBLHVDQUF1QyxPQUFPO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLFNBQVM7QUFDOUMsNEVBQTRFLFVBQVU7QUFDdEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxzQ0FBc0MsT0FBTztBQUM3QyxnRUFBZ0UsT0FBTztBQUN2RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DLE9BQU87QUFDM0Msd0RBQXdELE9BQU87QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBO0FBQ0E7QUFDQSx3Q0FBd0MsU0FBUztBQUNqRDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrRUFBa0U7QUFDbEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkRBQTJELE9BQU87QUFDbEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQSxXQUFXO0FBQ1g7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRFQUE0RTtBQUM1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLE9BQU87QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkMsT0FBTztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QyxPQUFPO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5REFBeUQ7QUFDekQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCx3Q0FBd0M7QUFDOUY7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLGlGQUFpRjtBQUNqRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDQSxTQUFTLGdCQUFnQjtBQUN6QjtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0Esa0JBQWtCLFVBQVU7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUM7QUFDbkM7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseURBQXlEO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwRUFBMEU7QUFDMUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Q7QUFDaEQsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxvREFBb0Q7QUFDcEQ7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixFQUFFO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDO0FBQzNDLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRSw2QkFBNkI7QUFDbkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlEQUF5RCxPQUFPO0FBQ2hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0VBQWdFLFFBQVE7QUFDeEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixPQUFPO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZEQUE2RCxPQUFPO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxPQUFPO0FBQ3JELFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLDJDQUEyQyxRQUFRO0FBQ25ELFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxPQUFPO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUIsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLE9BQU87QUFDOUIsb0VBQW9FLE9BQU87QUFDM0U7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCw0Q0FBNEM7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLGlDQUFpQztBQUNoRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBLGdDQUFnQyxRQUFRO0FBQ3hDLHlCQUF5Qiw4QkFBOEI7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLE9BQU87QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixjQUFjO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQztBQUNsQztBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1Asa0NBQWtDO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLDhCQUE4QjtBQUM1RDtBQUNBLCtDQUErQztBQUMvQyxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkMsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkMsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSwrQkFBK0IsT0FBTztBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsaUJBQWlCLE9BQU87QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0M7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtB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LDhCQUE4QjtBQUNuRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCw4QkFBOEI7QUFDbkY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUM7QUFDbkM7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQjtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxpQkFBaUIsT0FBTztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5REFBeUQsT0FBTywyREFBMkQsaUJBQWlCLE9BQU87QUFDbko7QUFDQSx5REFBeUQsT0FBTywyREFBMkQsaUJBQWlCLE9BQU87QUFDbko7QUFDQSxtREFBbUQsT0FBTyxtREFBbUQsaUJBQWlCLE9BQU87QUFDckk7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLE9BQU87QUFDNUI7QUFDQTtBQUNBLHFCQUFxQixPQUFPO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQSxtQkFBbUIsT0FBTztBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0VBQW9FO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSw4RUFBOEUsT0FBTztBQUNyRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkRBQTJEO0FBQzNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsOEJBQThCLE9BQU87QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQixnQ0FBZ0M7QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsTUFBTSxxQkFBcUIsT0FBTztBQUNsRDtBQUNBLFNBQVM7QUFDVDtBQUNBLGdCQUFnQixRQUFRLHNCQUFzQixPQUFPO0FBQ3JEO0FBQ0EsbUJBQW1CLGNBQWM7QUFDakMsOEJBQThCLGtCQUFrQjtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQ7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9FQUFvRTtBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLHFCQUFxQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvRUFBb0U7QUFDcEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBLHlEQUF5RCxTQUFTO0FBQ2xFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdEO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBLHlEQUF5RCxTQUFTO0FBQ2xFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxTQUFTO0FBQzlDLHlEQUF5RCxTQUFTO0FBQ2xFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLFNBQVM7QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQyxPQUFPO0FBQzNDO0FBQ0Esd0RBQXdELE9BQU87QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DLE9BQU87QUFDM0M7QUFDQSx3REFBd0QsT0FBTztBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQztBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbURBQW1ELDBCQUEwQjtBQUM3RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNB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RUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGLENBQUM7QUFDRDs7QUFFQSxDQUFDLEVBQUUsd0dBQXdHO0FBQzNHOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsWUFBWTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsbUhBQW1IO0FBQ3RIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHdJQUF3STtBQUMzSTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsaUNBQWlDO0FBQ2pDLFlBQVk7QUFDWixJQUFJO0FBQ0o7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUEsQ0FBQyxFQUFFLHdLQUF3SztBQUMzSzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsa0hBQWtIO0FBQ3JIO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGLENBQUM7QUFDRDs7QUFFQSxDQUFDLEVBQUUsd0VBQXdFO0FBQzNFOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxvQkFBb0I7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMscUJBQXFCOztBQUV0QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxpRkFBaUY7O0FBRWpGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsc0JBQXNCOztBQUVoRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlCQUFpQixTQUFTO0FBQzFCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBLENBQUM7QUFDRDtBQUNBLENBQUM7QUFDRDtBQUNBLENBQUM7QUFDRDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLFVBQVUsSUFBSTtBQUNkO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUIsd0JBQXdCO0FBQ3pDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLHVDQUF1QztBQUN4RDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLFVBQVUsTUFBTTtBQUNoQixVQUFVLE9BQU87QUFDakI7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsVUFBVSxNQUFNO0FBQ2hCO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBO0FBQ0EscUJBQXFCLFlBQVk7QUFDakM7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxVQUFVLElBQUk7QUFDZDtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQSxVQUFVLFNBQVM7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0EsWUFBWSxTQUFTO0FBQ3JCLFlBQVksU0FBUztBQUNyQjtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQSxZQUFZLFNB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QUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlCQUFpQixrQkFBa0I7QUFDbkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHlCQUF5QjtBQUM1Qjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLGlCQUFpQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixPQUFPO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLE1BQU07QUFDbkM7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsS0FBSztBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsTUFBTTtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLE1BQU07QUFDakM7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhCQUE4QixVQUFVO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0QsaUJBQWlCOztBQUVuRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixpQkFBaUI7QUFDakM7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsbUJBQW1CO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLGtCQUFrQixpQkFBaUI7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLDZCQUE2QixNQUFNO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLEtBQUs7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsTUFBTTtBQUNqQztBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QixLQUFLO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEdBQUc7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0NBQWdDLE9BQU87QUFDdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsV0FBVztBQUNsQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsa0JBQWtCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxrQkFBa0IsS0FBSztBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsS0FBSztBQUNyQixrQkFBa0IsS0FBSztBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLEtBQUs7O0FBRW5CO0FBQ0E7QUFDQTtBQUNBO0FB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEVBQUUscUZBQXFGO0FBQ3hGOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHVCQUF1QixzQkFBc0I7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsT0FBTztBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLENBQUMsRUFBRSxtQ0FBbUM7QUFDdEM7O0FBRUEsMENBQTBDO0FBQzFDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCO0FBQ0EsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxZQUFZO0FBQzFCO0FBQ0E7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQjtBQUNBLGdCQUFnQixZQUFZO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQjtBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLEtBQUs7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxvQkFBb0IsMEJBQTBCO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsa0JBQWtCLHdCQUF3QjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxrQkFBa0Isb0JBQW9CO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLG9CQUFvQjtBQUNsQztBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxnQkFBZ0I7QUFDOUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxvQkFBb0IsS0FBSztBQUN6QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0Esb0JBQW9CLEtBQUs7QUFDekI7QUFDQTtBQUNBLHNCQUFzQixLQUFLO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0JBQW9CLEtBQUs7QUFDekI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvQkFBb0IsS0FBSztBQUN6QjtBQUNBO0FBQ0Esc0JBQXNCLEtBQUs7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0IsS0FBSztBQUN6Qjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLG9CQUFvQjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsYUFBYTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLG9CQUFvQjtBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMscUJBQXFCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtQkFBbUI7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1CQUFtQix5QkFBeUI7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxtQkFBbUIsa0JBQWtCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxDQUFDLEVBQUUsd0ZBQXdGO0FBQzNGOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG1CQUFtQixPQUFPO0FBQzFCO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGlCQUFpQixjQUFjO0FBQy9CO0FBQ0E7QUFDQSxtQkFBbUIsY0FBYztBQUNqQztBQUNBOztBQUVBLHNCQUFzQixxQkFBcUI7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxzSEFBc0g7QUFDekg7O0FBRUE7O0FBRUE7QUFDQSwrQ0FBK0MsNENBQTRDLGVBQWUsa0VBQWtFLEdBQUc7QUFDL0ssa0RBQWtELCtDQUErQyx1QkFBdUIsd0JBQXdCLHVCQUF1Qiw2QkFBNkIsMkJBQTJCLGlCQUFpQixvRkFBb0Ysc0JBQXNCLHFEQUFxRCxHQUFHO0FBQ2xaLGtEQUFrRCwyQ0FBMkMsdUJBQXVCLHVCQUF1QiwwQkFBMEIsaUJBQWlCLCtCQUErQixrQ0FBa0MsOEJBQThCLGtDQUFrQyx3Q0FBd0Msa0NBQWtDLHdDQUF3QyxrQ0FBa0Msd0NBQXdDLDZCQUE2QixHQUFHO0FBQ25oQixrREFBa0QsK0NBQStDLHdCQUF3Qix3QkFBd0IsdUJBQXVCLDZCQUE2Qix3QkFBd0IsdUJBQXVCLGlCQUFpQixxQkFBcUIsc0JBQXNCLHNGQUFzRixxREFBcUQsR0FBRztBQUM5Yjs7QUFFQSxDQUFDLEVBQUUsY0FBYztBQUNqQjtBQUNBLENBQUMsRUFBRSxVQUFVO0FBQ2I7QUFDQTs7QUFFQSw4Q0FBOEMsNkRBQTZELHVDQUF1Qyx1QkFBdUIsNkJBQTZCLDJCQUEyQix1Q0FBdUMsMkJBQTJCLDZCQUE2QiwrQkFBK0IsMEJBQTBCLG9EQUFvRCxHQUFHLGlCQUFpQix3Q0FBd0MsNENBQTRDLDRDQUE0QywwQ0FBMEMsc0dBQXNHLHNIQUFzSCwrRUFBK0UsK0JBQStCLCtCQUErQixzQkFBc0IsR0FBRztBQUM3K0Isa0RBQWtELG1FQUFtRSw0REFBNEQsR0FBRyw2Q0FBNkMsK0VBQStFLEdBQUcsNkNBQTZDLHVIQUF1SCxHQUFHLDZDQUE2QywyQ0FBMkMsR0FBRyxvQ0FBb0MsZ0NBQWdDLDhCQUE4Qiw0QkFBNEIsa0NBQWtDLGlDQUFpQyw0QkFBNEIsaUJBQWlCLHVIQUF1SCx1RkFBdUYsMEJBQTBCLGNBQWMsS0FBSyx1Q0FBdUMsR0FBRztBQUN4a0MsK0NBQStDLGdKQUFnSiw0QkFBNEIsb0RBQW9ELHNDQUFzQyxLQUFLLHlCQUF5QixrREFBa0QsS0FBSywwQkFBMEIsa0RBQWtELEtBQUssbUNBQW1DLHlFQUF5RSw0Q0FBNEMscURBQXFELHNCQUFzQiw4QkFBOEIsd0JBQXdCLGdDQUFnQywyREFBMkQsOEJBQThCLHdCQUF3QixpQ0FBaUMsMERBQTBELGdEQUFnRCxHQUFHLGdEQUFnRCw0REFBNEQsR0FBRyw2Q0FBNkMsK0VBQStFLEdBQUcsNkNBQTZDLHVIQUF1SCxHQUFHLDZDQUE2QywyQ0FBMkMsR0FBRyx5QkFBeUIsNkJBQTZCLCtCQUErQiwrQkFBK0IseUJBQXlCLGlCQUFpQix5RUFBeUUscUZBQXFGLEdBQUc7O0FBRWwwRDtBQUNBLEdBQUcsK0JBQStCO0FBQ2xDLEdBQUcsbUNBQW1DO0FBQ3RDLEdBQUcsaUNBQWlDO0FBQ3BDLEdBQUcsaUNBQWlDO0FBQ3BDLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSw4QkFBOEI7QUFDakM7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQSxlQUFlLHNCQUFzQjtBQUNyQztBQUNBOztBQUVBO0FBQ0E7O0FBRUEsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQixRQUFRO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdEQUF3RDs7QUFFeEQ7QUFDQTtBQUNBLG9EQUFvRDtBQUNwRCxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1REFBdUQ7QUFDdkQsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLG1CQUFtQixPQUFPO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsc0JBQXNCO0FBQ3JDO0FBQ0E7O0FBRUE7QUFDQSxlQUFlLFNBQVM7QUFDeEIsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixPQUFPO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlCQUFpQixhQUFhO0FBQzlCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtSUFBbUk7QUFDdEk7QUFDQSxDQUFDLEVBQUUsVUFBVTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxLQUFLO0FBQ2hCLFdBQVcsS0FBSztBQUNoQixhQUFhLEtBQUs7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxLQUFLO0FBQ2hCLFdBQVcsS0FBSztBQUNoQixhQUFhLEtBQUs7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsS0FBSztBQUNoQixhQUFhLEtBQUs7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxLQUFLO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsS0FBSztBQUNoQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEtBQUs7QUFDaEIsV0FBVyxNQUFNO0FBQ2pCLGFBQWEsS0FBSztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsS0FBSztBQUNoQixXQUFXLE1BQU07QUFDakIsV0FBVyxLQUFLO0FBQ2hCLGFBQWEsS0FBSztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsS0FBSztBQUNoQixhQUFhLEtBQUs7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsS0FBSztBQUNoQixXQUFXLEtBQUs7QUFDaEIsYUFBYSxLQUFLO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxlO0FBQ0Esb0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEtBQUs7QUFDaEIsV0FBVyxLQUFLO0FBQ2hCLFdBQVcsS0FBSztBQUNoQixXQUFXLEtBQUs7QUFDaEIsYUFBYSxLQUFLO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQyxFQUFFLGlCQUFpQjtBQUNwQjs7QUFFQTtB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QjtBQUNqQyxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSywrQkFBK0I7QUFDcEMsS0FBSyw0QkFBNEI7QUFDakMsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUssK0JBQStCO0FBQ3BDLEtBQUssNEJBQTRCO0FBQ2pDLEtBQUsseUJBQXlCO0FBQzlCLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLLCtCQUErQjtBQUNwQyxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSywrQkFBK0I7QUFDcEMsS0FBSyxpQ0FBaUM7QUFDdEMsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBLENBQUMsRUFBRSxjQUFjO0FBQ2pCOztBQUVBLDBDQUEwQztBQUMxQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7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VztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWMsS0FBSztBQUNuQjtBQUNBOztBQUVBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQSxnQkFBZ0IsS0FBSztBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsZUFBZTtBQUM3QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxlQUFlO0FBQzdCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLENBQUMsRUFBRSw0UEFBNFA7QUFDL1A7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsZ0RBQWdEO0FBQ25EOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxnQkFBZ0IsS0FBSztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxrQkFBa0I7QUFDaEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsbUJBQW1CO0FBQ2pDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsa0JBQWtCO0FBQ2hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxrQkFBa0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsY0FBYyxpQkFBaUI7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFD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QUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixXQUFXO0FBQzNCO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixXQUFXO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixXQUFXO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLGtCQUFrQjtBQUNsQztBQUNBOztBQUVBO0FBQ0E7QUFDQSxnQkFBZ0Isc0JBQXNCO0FBQ3RDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9CQUFvQixXQUFXO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsV0FBVztBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnQkFBZ0IsV0FBVztBQUMzQjtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsV0FBVztBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixXQUFXO0FBQzNCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsS0FBSztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixLQUFLO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxnQkFBZ0IsS0FBSztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLEtBQUs7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixNQUFNO0FBQ3RCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7O0FBRUEsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxnQkFBZ0IsV0FBVztBQUMzQjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGdCQUFnQixXQUFXO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsV0FBVztBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixXQUFXO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQixXQUFXO0FBQzNCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDZQQUE2UDtBQUNoUTs7QUFFQSw4REFBOEQsK0NBQStDLHdCQUF3QiwwQkFBMEIsMkJBQTJCLCtCQUErQiw0QkFBNEIsMkJBQTJCLCtCQUErQiwyQ0FBMkMsaUNBQWlDLDZCQUE2QixHQUFHLGlCQUFpQixpREFBaUQsd0RBQXdELDhNQUE4TSwyQkFBMkIsMkdBQTJHLEtBQUssR0FBRztBQUNqM0IsOERBQThELHVEQUF1RCwrQkFBK0IsMkJBQTJCLGlCQUFpQixpQkFBaUIsbUJBQW1CLDJCQUEyQix5REFBeUQsNkJBQTZCLE9BQU8sT0FBTywrREFBK0QsT0FBTyxLQUFLLE9BQU8sb0RBQW9ELHdCQUF3QixnQkFBZ0IsT0FBTyx3RUFBd0Usb0VBQW9FLEtBQUssR0FBRztBQUM1cUIsOERBQThELCtDQUErQyx3QkFBd0Isd0JBQXdCLDBCQUEwQiwwQkFBMEIsd0JBQXdCLGlCQUFpQixpREFBaUQsd0RBQXdELDZCQUE2QixvQ0FBb0MsZ0NBQWdDLHdDQUF3QyxrQ0FBa0Msd0NBQXdDLGtDQUFrQyx3Q0FBd0Msa0JBQWtCLEdBQUc7QUFDcnBCLDhEQUE4RCwyQ0FBMkMsaUJBQWlCLHdEQUF3RCxzQkFBc0IsY0FBYyxLQUFLLGtDQUFrQyxHQUFHOztBQUVoUSxDQUFDLEVBQUUsY0FBYztBQUNqQjs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxnQkFBZ0I7QUFDOUI7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFlBQVk7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHlFQUF5RTtBQUM1RTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEtBQUs7QUFDaEIsV0FBVyxLQUFLO0FBQ2hCLFdBQVcsS0FBSztBQUNoQixXQUFXLE9BQU87QUFDbEIsYUFBYSxLQUFLO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLGNBQWMsZ0NBQWdDO0FBQzlDLGdCQUFnQixtQ0FBbUM7QUFDbkQ7QUFDQTtBQUNBOztBQUVBLGNBQWMsaUNBQWlDO0FBQy9DLGdCQUFnQixvQ0FBb0M7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsWUFBWSxPQUFPO0FBQ25CO0FBQ0EsWUFBWSxLQUFLO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUMsRUFBRSxxQkFBcUI7QUFDeEI7QUFDQTs7QUFFQSx5REFBeUQsbUVBQW1FLDREQUE0RCxHQUFHLDZDQUE2QywrRUFBK0UsR0FBRyw2Q0FBNkMsdUhBQXVILEdBQUcsNkNBQTZDLDJDQUEyQyxHQUFHLDRCQUE0Qix1QkFBdUIsdUJBQXVCLG9CQUFvQiw2QkFBNkIsK0JBQStCLHVDQUF1Qyw2QkFBNkIsNkJBQTZCLHNCQUFzQiw4QkFBOEIsaUJBQWlCLDZEQUE2RCxvQ0FBb0MsS0FBSyxPQUFPLHdCQUF3Qiw4Q0FBOEMsK0JBQStCLE9BQU8sdURBQXVELCtDQUErQyxtREFBbUQsOEZBQThGLG1DQUFtQywwQkFBMEIsa0JBQWtCLGdDQUFnQyxLQUFLLEdBQUc7QUFDbjhDLDBEQUEwRCxtRUFBbUUsNERBQTRELEdBQUcsNkNBQTZDLCtFQUErRSxHQUFHLDZDQUE2Qyx1SEFBdUgsR0FBRyw2Q0FBNkMsMkNBQTJDLEdBQUcsNEJBQTRCLHVCQUF1Qix1QkFBdUIsb0JBQW9CLHlDQUF5QywwQkFBMEIsNkJBQTZCLDJDQUEyQywyQkFBMkIsNkJBQTZCLHNCQUFzQiw4QkFBOEIsaUJBQWlCLDZEQUE2RCxvQ0FBb0MsS0FBSyxPQUFPLCtCQUErQixxREFBcUQsZ0NBQWdDLE9BQU8seURBQXlELCtDQUErQyxvREFBb0QscUNBQXFDLGtHQUFrRywwQkFBMEIsa0JBQWtCLGdDQUFnQyxLQUFLLEdBQUc7QUFDbGdELHdEQUF3RCxtRUFBbUUsNERBQTRELEdBQUcsNkNBQTZDLCtFQUErRSxHQUFHLDZDQUE2Qyx1SEFBdUgsR0FBRyw2Q0FBNkMsMkNBQTJDLEdBQUcsNEJBQTRCLHVCQUF1Qix1QkFBdUIsb0JBQW9CLGlDQUFpQywyQkFBMkIsdUJBQXVCLHVDQUF1QywwQkFBMEIsNkJBQTZCLGtDQUFrQyw2QkFBNkIsc0JBQXNCLDhCQUE4QixpQkFBaUIsNkRBQTZELG9DQUFvQyxLQUFLLE9BQU8sd0NBQXdDLDhDQUE4QyxpQ0FBaUMsT0FBTywwRUFBMEUsc0hBQXNILDRFQUE0RSxtQ0FBbUMsMEJBQTBCLGtCQUFrQixvQ0FBb0MsS0FBSyxHQUFHO0FBQ2hrRCxrREFBa0QsbUVBQW1FLDREQUE0RCxHQUFHLDZDQUE2QywrRUFBK0UsR0FBRyw2Q0FBNkMsdUhBQXVILEdBQUcsNkNBQTZDLDJDQUEyQyxHQUFHLG1DQUFtQyx3QkFBd0IsNkJBQTZCLDhCQUE4QixpQkFBaUIsa0lBQWtJLHlDQUF5QyxHQUFHO0FBQzEyQixrREFBa0QsbUVBQW1FLDREQUE0RCxHQUFHLDZDQUE2QywrRUFBK0UsR0FBRyw2Q0FBNkMsdUhBQXVILEdBQUcsNkNBQTZDLDJDQUEyQyxHQUFHLG1DQUFtQywwQkFBMEIsd0JBQXdCLDhCQUE4QixpQkFBaUIsa0ZBQWtGLGlEQUFpRCxHQUFHOztBQUUvekI7QUFDQSxHQUFHLCtCQUErQjtBQUNsQyxHQUFHLDRCQUE0QjtBQUMvQixHQUFHLDRCQUE0QjtBQUMvQixHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSw4QkFBOEI7QUFDakM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkIsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCLE1BQU07QUFDdEI7QUFDQTtBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsS0FBSztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsbUJBQW1CLHNCQUFzQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTs7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QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLENBQUMsRUFBRSw4TkFBOE47QUFDak87O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGdCQUFnQixtQkFBbUI7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLFlBQVk7QUFDN0I7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLFlBQVk7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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Q0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixPQUFPO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGFBQWEsT0FBTztBQUNwQjtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7O0FBRUEsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCLGlC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QTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsOFJBQThSO0FBQ2pTOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0Esb0NBQW9DLGNBQWM7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLGlDQUFpQztBQUN0RSxxQ0FBcUMsaUNBQWlDOztBQUV0RTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhCQUE4QjtBQUM5Qjs7QUFFQTtBQUNBOztB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QTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixLQUFLO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsc0RBQXNEO0FBQ3pEO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0Esc0NBQXNDOztBQUV0QztBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxzSEFBc0g7QUFDekg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGlCQUFpQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsaUJBQWlCO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsTUFBTTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLE1BQU07QUFDeEI7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCLE1BQU07QUFDdEI7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZ0JBQWdCLE1BQU07QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdCQUFnQixNQUFNO0FBQ3RCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsdUM7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLE1BQU07QUFDMUI7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQixNQUFNO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixNQUFNO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsY0FBYyx1QkFBdUI7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLE1BQU07QUFDeEI7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxNQUFNO0FBQ3BCO0FBQ0EsZ0JBQWdCLE1BQU07QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxNQUFNO0FBQ3BCO0FBQ0E7QUFDQSxnQkFBZ0IsTUFBTTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLE1BQU07QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxFQUFFLGtEQUFrRDtBQUNyRDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRSwwQkFBMEI7QUFDN0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0VBQXNFLDJCQUEyQjtBQUNqRztBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsaUNBQWlDO0FBQy9DO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQSx5QkFBeUIseUJBQXlCO0FBQ2xEO0FBQ0EsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLGNBQWM7QUFDNUI7QUFDQSxXQUFXO0FBQ1g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLG9CQUFvQjtBQUNsQztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxvQkFBb0I7QUFDbEM7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMEJBQTBCO0FBQzdCOztBQUVBO0FBQ0E7QUFDQSxjQUFjLGFBQWE7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQyxHQUFHO0FBQ0o7QUFDQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHFKQUFxSjtBQUNySjs7QUFFQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLFdBQVc7QUFDN0I7QUFDQTtBQUNBO0FB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O0FBRUg7QUFDQTtBQUNBOztBQUVBLGNBQWMsS0FBSztBQUNuQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLE1BQU07QUFDckM7QUFDQTtBQUNBLDJCQUEyQixLQUFLO0FBQ2hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxFQUFFLHlCQUF5QjtBQUM1Qjs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFD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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixrQkFBa0I7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBOztBQUVBO0FB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QUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLE1BQU07QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQyxFQUFFLGlIQUFpSDtBQUNwSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEVBQUUsb0JBQW9CO0FBQ3ZCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxVQUFVO0FBQ1Y7QUFDQTs7QUFFQSx1R0FBdUc7O0FBRXZHOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU0sV0FBVyxLQUFLO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsb0JBQW9COztBQUV2Qjs7QUFFQTtBQUNBO0FBQ0EsVUFBVTtBQUNWOztBQUVBLGNBQWM7O0FBRWQ7QUFDQTtBQUNBLFVBQVU7QUFDVjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFlBQVk7QUFDWjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FB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O0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEVBQUUsbUdBQW1HO0FBQ3RHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLENBQUMsRUFBRSwrSUFBK0k7QUFDbEo7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSx5QkFBeUIseUJBQXlCO0FBQ2xELEdBQUc7QUFDSDtBQUNBLG9CQUFvQixvQkFBb0I7QUFDeEMsd0JBQXdCLG9CQUFvQjtBQUM1QyxHQUFHO0FBQ0g7QUFDQSwyQkFBMkIsV0FBVztBQUN0QyxHQUFHO0FBQ0g7QUFDQSw4QkFBOEIsV0FBVztBQUN6QyxHQUFHO0FBQ0g7QUFDQSwyQkFBMkIsNkJBQTZCO0FBQ3hELEdBQUc7QUFDSDtBQUNBLDJCQUEyQixXQUFXO0FBQ3RDLEdBQUc7QUFDSDtBQUNBLCtCQUErQix1Q0FBdUM7QUFDdEUsR0FBRztBQUNIO0FBQ0EsMEJBQTBCLFdBQVc7QUFDckMsR0FBRztBQUNIO0FBQ0EsMEJBQTBCLHVDQUF1QztBQUNqRSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsT0FBTztBQUMvQixHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLFlBQVk7QUFDbkMsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSw0QkFBNEIsYUFBYTtBQUN6QyxHQUFHO0FBQ0g7QUFDQSwrQkFBK0IsV0FBVztBQUMxQyxHQUFHO0FBQ0g7QUFDQSxrQ0FBa0MsdUJBQXVCO0FBQ3pELEdBQUc7QUFDSDtBQUNBLGtDQUFrQyx1QkFBdUI7QUFDekQsR0FBRztBQUNIO0FBQ0EsNkJBQTZCLHFCQUFxQjtBQUNsRCxHQUFHO0FBQ0g7QUFDQSwrQkFBK0IsZUFBZTtBQUM5QyxHQUFHO0FBQ0g7QUFDQSwrQkFBK0IsZUFBZTtBQUM5QyxHQUFHO0FBQ0g7QUFDQSxrQ0FBa0MsdUJBQXVCO0FBQ3pELEdBQUc7QUFDSDtBQUNBLGtDQUFrQyx3QkFBd0I7QUFDMUQsR0FBRztBQUNIO0FBQ0EsNkJBQTZCLGlDQUFpQztBQUM5RCxHQUFHO0FBQ0g7QUFDQSw2QkFBNkIsZUFBZTtBQUM1QyxHQUFHO0FBQ0g7QUFDQSw4QkFBOEIsaUNBQWlDO0FBQy9ELEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLG1CQUFtQjtBQUNyQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QiwrQkFBK0I7O0FBRTdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLGtDQUFrQztBQUNoRTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0IsbUJBQW1CO0FBQ3JDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLCtCQUErQjtBQUMvRCxrQkFBa0IsZ0NBQWdDO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLDBCQUEwQjtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLDBCQUEwQjtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQix5QkFBeUI7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsbUJBQW1CO0FBQ3JDO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLDBCQUEwQjtBQUM1QztBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0IsMEJBQTBCO0FBQzVDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLDJCQUEyQjtBQUM1Qzs7QUFFQTs7QUFFQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFdBQVc7QUFDWCxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxZQUFZOztBQUVaO0FBQ0EsOEJBQThCOztBQUU5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQkFBa0I7O0FBRWxCO0FBQ0E7O0FBRUE7QUFDQSxnQkFBZ0I7O0FBRWhCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7QUFFUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBLDJEQUEyRDs7QUFFM0Q7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwwREFBMEQsU0FBUztBQUNuRTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2REFBNkQ7QUFDN0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsbUJBQW1CO0FBQ3JDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWM7O0FBRWQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDLEVBQUUsb0JBQW9CO0FBQ3ZCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSx5QkFBeUI7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFO0FBQ2pFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0EsaUJBQWlCLG1CQUFtQjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGdEQUFnRDtBQUNoRCw0Q0FBNEM7O0FBRTVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEscURBQXFEO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLElBQUk7QUFDSjtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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QjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHNCQUFzQjtBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjs7QUFFQTs7QUFFQTtBQUNBO0FB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OztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUEsMkNBQTJDO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaURBQWlELFNBQVM7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGVBQWUsc0JBQXNCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0NBQXNDLFNBQVM7QUFDL0M7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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EseUJBQXlCO0FBQ3pCLEtBQUs7OztBQUdMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7OztBQUdMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7OztBQUdMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0Q7O0FBRXBEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw0RUFBNEU7O0FBRTVFO0FBQ0E7QUFDQTtBQUNBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbURBQW1EO0FBQ25ELFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTLEVBQUU7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsMENBQTBDOztBQUUxQztBQUNBO0FBQ0EsU0FBUztBQUNULDhCQUE4Qjs7QUFFOUI7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBLHVFQUF1RSxRQUFRO0FBQy9FOztBQUVBLG9GQUFvRjs7QUFFcEY7QUFDQTs7QUFFQSw4QkFBOEIsMkJBQTJCO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsT0FBTztBQUNQO0FBQ0Esa0NBQWtDOztBQUVsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLG9GQUFvRjtBQUNwRjs7QUFFQTtBQUNBO0FBQ0EsS0FBSyxHQUFHOztBQUVSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUJBQXlCLGFBQWE7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7O0FBR0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7O0FBRUEsMkJBQTJCLGNBQWM7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNkJBQTZCLGNBQWM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCOztBQUUzQjs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBLG1DQUFtQyxPQUFPO0FBQzFDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsZUFBZTs7QUFFZjtBQUNBOztBQUVBO0FBQ0EscUJBQXFCLG1CQUFtQjtBQUN4QztBQUNBO0FBQ0EsS0FBSztBQUNMLHVCQUF1QixxQkFBcUI7QUFDNUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsbUJBQW1CLHFCQUFxQjtBQUN4QztBQUNBO0FBQ0EsbUNBQW1DOztBQUVuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7O0FBR0gsdUZBQXVGOztBQUV2Riw4QkFBOEI7O0FBRTlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtRUFBbUU7O0FBRW5FO0FBQ0E7O0FBRUEsa0RBQWtELGdDQUFnQztBQUNsRjtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxrREFBa0Q7O0FBRWxEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTs7QUFFQSxDQUFDLEVBQUUsa09BQWtPO0FBQ3JPO0FBQ0EsQ0FBQyxFQUFFLFVBQVU7QUFDYjs7QUFFQTtBQUNBLENBQUMsRUFBRSxhQUFhO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxnQkFBZ0IsYUFBYTs7QUFFN0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQiwrQkFBK0I7O0FBRS9COztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQjs7QUFFdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBLGdCQUFnQixPQUFPO0FBQ3ZCO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLHVCQUF1QjtBQUMzQztBQUNBLGdCQUFnQjtBQUNoQjtBQUNBLDJDQUEyQyxTQUFTO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOzs7O0FBSUE7QUFDQTtBQUNBLG9CQUFvQjs7QUFFcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsZ0JBQWdCO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1DQUFtQyxTQUFTO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHFCQUFxQjs7QUFFckI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkMsK0JBQStCOztBQUUvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxzQ0FBc0M7O0FBRXRDO0FBQ0E7O0FBRUE7QUFDQSxvRUFBb0U7QUFDcEUsNkJBQTZCO0FBQzdCLHVCQUF1Qjs7QUFFdkI7QUFDQTs7QUFFQSwwQkFBMEI7O0FBRTFCLHFCQUFxQixRQUFRO0FBQzdCOztBQUVBO0FBQ0E7O0FBRUEsaUVBQWlFO0FBQ2pFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQkFBcUIsa0JBQWtCO0FBQ3ZDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGlCQUFpQixXQUFXO0FBQzVCOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQ0FBb0MsT0FBTztBQUMzQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUMsRUFBRSwrS0FBK0s7QUFDbEw7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7O0FBR0E7QUFDQTtBQUNBLGdDQUFnQzs7QUFFaEM7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrREFBa0Q7O0FBRWxEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvQkFBb0I7O0FBRXBCLGdCQUFnQixpQkFBaUI7QUFDakM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQiwwQkFBMEI7QUFDNUM7QUFDQTtBQUNBLGlCQUFpQix3QkFBd0I7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCOztBQUVoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUIsdUJBQXVCO0FBQ3ZCLHVCQUF1Qjs7QUFFdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1CQUFtQixxQkFBcUI7QUFDeEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0IsU0FBUztBQUMzQixpQkFBaUIsT0FBTztBQUN4QixzQ0FBc0M7QUFDdEMsaUNBQWlDO0FBQ2pDLGlDQUFpQzs7QUFFakM7O0FBRUEsNERBQTREOztBQUU1RDtBQUNBO0FBQ0E7QUFDQSxVQUFVLHFEQUFxRDtBQUMvRCxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVLDhDQUE4QztBQUN4RCxVQUFVO0FBQ1Y7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUI7QUFDakIsZ0JBQWdCO0FBQ2hCLGtCQUFrQjtBQUNsQixzQkFBc0I7QUFDdEIsdUJBQXVCO0FBQ3ZCLG1CQUFtQjs7QUFFbkI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixpQkFBaUI7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QztBQUM3QyxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQSwrQkFBK0I7QUFDL0IsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGlJQUFpSTtBQUNwSSxpQkFBaUIsZ0pBQWdKLGtCQUFrQixpQkFBaUIsYUFBYSxZQUFZLFlBQVksZUFBZSx5QkFBeUIseUNBQXlDLDBIQUEwSDtBQUNwYixxRUFBcUUsZUFBZSw0RUFBNEUsS0FBSyxRQUFRLFdBQVcseUJBQXlCLFNBQVMsZUFBZSwrQkFBK0IsY0FBYyxPQUFPLEtBQUssUUFBUSxPQUFPLGVBQWUsV0FBVyxjQUFjLGdCQUFnQixVQUFVLFNBQVMsaUJBQWlCLGNBQWMsbUJBQW1CLGFBQWEsNkNBQTZDO0FBQ3hlLGdFQUFnRSxZQUFZLGFBQWEsV0FBVywyQkFBMkIsRUFBRSx1Q0FBdUMsV0FBVyx5Q0FBeUMsRUFBRSxpQkFBaUIsMkRBQTJELG1CQUFtQixHQUFHLHVDQUF1QyxJQUFJLE9BQU8sOEJBQThCLHVDQUF1QyxtQkFBbUIsaUJBQWlCLGNBQWMsSUFBSTtBQUM3ZSxHQUFHLFNBQVMsYUFBYSxvRUFBb0UsZUFBZSxzQ0FBc0MsZUFBZSxzREFBc0QsZUFBZSxXQUFXLFNBQVMsS0FBSywwRkFBMEYsZ0JBQWdCO0FBQ3pXLDRhQUE0YSxpREFBaUQsT0FBTyxPQUFPO0FBQzNlLEtBQUssa0JBQWtCLFdBQVcsY0FBYyxVQUFVLFVBQVUsd0dBQXdHLDBHQUEwRyxpQkFBaUIsY0FBYyxrQkFBa0IsTUFBTSxJQUFJLHlCQUF5QixVQUFVLFVBQVUsWUFBWSxLQUFLLHNCQUFzQixLQUFLLHNCQUFzQjtBQUNoYyxLQUFLLGdDQUFnQyxPQUFPLGdDQUFnQyxtQ0FBbUMsb0VBQW9FLElBQUksZ0JBQWdCLHVCQUF1QixJQUFJLGNBQWMsU0FBUyxlQUFlLFFBQVEsZUFBZSxPQUFPLGFBQWEsT0FBTyxLQUFLLFlBQVksT0FBTyxLQUFLLFdBQVcsb0JBQW9CLGNBQWMsY0FBYyxHQUFHLGFBQWEsYUFBYSxlQUFlLElBQUksUUFBUSxJQUFJLGNBQWM7QUFDNWQsbUJBQW1CLGNBQWMsK0JBQStCLHFCQUFxQixTQUFTLEVBQUUsT0FBTyx1Q0FBdUMsV0FBVyxVQUFVLG9DQUFvQyxNQUFNLHFDQUFxQyxNQUFNLHVDQUF1QyxNQUFNLHdDQUF3QyxNQUFNLHVDQUF1QyxNQUFNLHdDQUF3QyxNQUFNLHlDQUF5QyxNQUFNLG9CQUFvQjtBQUNqZixvQkFBb0Isc0JBQXNCLGNBQWMsZUFBZSxrTEFBa0wseUJBQXlCLFlBQVksSUFBSSx1QkFBdUIsSUFBSSx1QkFBdUIsSUFBSSxnQkFBZ0IsdUJBQXVCLGtCQUFrQixXQUFXLFlBQVksV0FBVyxtQkFBbUIsc0JBQXNCLFNBQVMsUUFBUSxJQUFJO0FBQ2pmLGdCQUFnQixhQUFhLElBQUksNEJBQTRCLGVBQWUsK0NBQStDLGlCQUFpQixZQUFZLFdBQVcsY0FBYywyQkFBMkIsZ0JBQWdCLElBQUksZ0JBQWdCLElBQUksd0JBQXdCLHFCQUFxQixjQUFjLFlBQVksNkJBQTZCLFlBQVksaUJBQWlCLGtCQUFrQixpQkFBaUIsZ0JBQWdCLHlCQUF5Qix3QkFBd0IsT0FBTyxFQUFFLGtCQUFrQjtBQUNwZixhQUFhLHlCQUF5Qix3QkFBd0IsVUFBVSxxQkFBcUIsc0RBQXNELFFBQVEsY0FBYyxXQUFXLFlBQVksY0FBYyxrQkFBa0IsU0FBUyxtQ0FBbUM7QUFDNVEsb0NBQW9DLG9IQUFvSCxlQUFlLFVBQVUsMENBQTBDLGlGQUFpRiw0QkFBNEIsY0FBYywyQkFBMkIsdUJBQXVCLFNBQVMsb0NBQW9DLGNBQWMsZ0JBQWdCLFlBQVksaUJBQWlCLEtBQUs7QUFDcmYsV0FBVyw0REFBNEQseUJBQXlCLGNBQWMsZUFBZSxhQUFhLDRCQUE0QixxQ0FBcUMsK0JBQStCLFNBQVMsU0FBUyw0Q0FBNEMsUUFBUSxtQ0FBbUMsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLE9BQU8seUJBQXlCLGNBQWMsK0JBQStCO0FBQ2hjLDBKQUEwSixTQUFTLHNHQUFzRyxtREFBbUQsU0FBUyxnQkFBZ0IsZUFBZSxVQUFVLFFBQVEscUJBQXFCLFlBQVksd0JBQXdCLGlCQUFpQixTQUFTLG9DQUFvQywwQkFBMEI7QUFDdmdCLG9DQUFvQyxvQ0FBb0MsUUFBUSw0QkFBNEIsY0FBYyx5R0FBeUcsZUFBZSxVQUFVLDZCQUE2QixpRkFBaUYsMkNBQTJDLHFCQUFxQiw4QkFBOEIsNEJBQTRCLGNBQWM7QUFDbGYsNkJBQTZCLHFCQUFxQixNQUFNLFNBQVMsNEJBQTRCLGNBQWMsZ0JBQWdCLFNBQVMsb0JBQW9CLFNBQVMsMkJBQTJCLFVBQVUsa0JBQWtCLGdCQUFnQixhQUFhLHVCQUF1QixnREFBZ0Qsb0JBQW9CLHlCQUF5QiwwQkFBMEIsOEJBQThCLDREQUE0RCxFQUFFLGdCQUFnQjtBQUMvZSxPQUFPLGNBQWMsWUFBWSxnQkFBZ0IsY0FBYyxnQkFBZ0IsMkJBQTJCLDBCQUEwQixnQkFBZ0IsTUFBTSxRQUFRLHFFQUFxRSxnQ0FBZ0MsZ0hBQWdILElBQUksT0FBTyx1QkFBdUIsMkJBQTJCLE1BQU0sMkJBQTJCLE1BQU0sMkJBQTJCO0FBQ3RmLEVBQUUsU0FBUyxJQUFJLDhEQUE4RCxjQUFjLElBQUksdUVBQXVFLGFBQWEsY0FBYyxrQkFBa0IsZUFBZSxtQkFBbUIsY0FBYyxRQUFRLFFBQVEsd0JBQXdCLDBDQUEwQyw0QkFBNEIsb0JBQW9CLFNBQVMsT0FBTyxxQkFBcUIsY0FBYztBQUN4YixZQUFZLEtBQUsscUNBQXFDLHFDQUFxQyxnTEFBZ0wsb0NBQW9DLGdDQUFnQyxpQkFBaUIsZ0RBQWdELFNBQVMsaURBQWlELGtCQUFrQixLQUFLO0FBQ2plLGNBQWMsd0JBQXdCLGVBQWUsVUFBVSxxQkFBcUIsTUFBTSxTQUFTLDBCQUEwQixjQUFjLGlEQUFpRCx1QkFBdUIsU0FBUywyQkFBMkIsVUFBVSx5QkFBeUIsdUVBQXVFLGtCQUFrQixrQkFBa0IsZUFBZSx5Q0FBeUMsV0FBVyw4QkFBOEI7QUFDdGUsZ0JBQWdCLG9DQUFvQyxLQUFLLFdBQVcsd0RBQXdELGlFQUFpRSxTQUFTLGVBQWUsOEJBQThCLGVBQWUsdUJBQXVCLGVBQWUsZ0VBQWdFLGVBQWUsc0RBQXNELGVBQWUseUNBQXlDLGVBQWU7QUFDcGYsWUFBWSwrQ0FBK0MsaUJBQWlCLHFEQUFxRCx5QkFBeUIsNENBQTRDLFVBQVUsTUFBTSxRQUFRLEtBQUssZUFBZSxTQUFTLGFBQWEsMkJBQTJCLGFBQWEscUNBQXFDLGVBQWUsb0RBQW9ELHVCQUF1QixzQkFBc0IsdUNBQXVDO0FBQzVlLEdBQUcsa0NBQWtDLGtCQUFrQixjQUFjLDBCQUEwQixzQ0FBc0MsZ0JBQWdCLG9DQUFvQywwQkFBMEIsZ0JBQWdCLGtCQUFrQixzQkFBc0IsZ0JBQWdCLDJCQUEyQixnRUFBZ0UsK0JBQStCLGlEQUFpRDtBQUN0YywrQkFBK0IsMkNBQTJDLHVNQUF1TSxZQUFZLGFBQWEsZUFBZSxLQUFLLHNJQUFzSTtBQUNwYywwREFBMEQsY0FBYyw2QkFBNkIsd0NBQXdDLGtDQUFrQyxzQ0FBc0MsYUFBYSxhQUFhLDRCQUE0QixlQUFlLGtCQUFrQixrQkFBa0Isa0JBQWtCLGdCQUFnQixXQUFXLG1HQUFtRyxXQUFXO0FBQ3pkLDZCQUE2QiwrQkFBK0IsZUFBZSw0RUFBNEUsMkhBQTJILGVBQWUseUJBQXlCLElBQUksV0FBVyxlQUFlLGdFQUFnRSxTQUFTLFNBQVMsTUFBTSx3QkFBd0IsY0FBYyxlQUFlLGVBQWU7QUFDcGYsT0FBTyxrRkFBa0YsaUNBQWlDLG1DQUFtQyxPQUFPLE9BQU8sT0FBTyxPQUFPLGNBQWMsVUFBVSxXQUFXLGFBQWEsZ0NBQWdDLGVBQWUsSUFBSSxXQUFXLFVBQVUsV0FBVyxhQUFhLGlFQUFpRSxLQUFLLGtCQUFrQixLQUFLLGtCQUFrQixLQUFLLGdDQUFnQyxRQUFRO0FBQ3JlLHdIQUF3SCw4RUFBOEUsNEZBQTRGLHdGQUF3RixlQUFlLHVCQUF1QixxQkFBcUIsYUFBYSxxQ0FBcUM7QUFDdmUsSUFBSSxRQUFRLFdBQVcsWUFBWSw0Q0FBNEMscUJBQXFCLFFBQVEsY0FBYyxVQUFVLFdBQVcsYUFBYSxnQ0FBZ0MsZ0JBQWdCLHNCQUFzQixxRkFBcUYsS0FBSztBQUM1VCxTQUFTLGFBQWEsc0JBQXNCLGNBQWMsZ0NBQWdDLFVBQVUsVUFBVSxhQUFhLGFBQWEsbUJBQW1CLHFCQUFxQixlQUFlLHNCQUFzQixrQkFBa0Isc0JBQXNCLFlBQVksa0JBQWtCLG9CQUFvQix3QkFBd0IsZ0JBQWdCLFdBQVcscURBQXFELDhEQUE4RCxXQUFXO0FBQ2hlLDBEQUEwRCxpREFBaUQsaUJBQWlCLGdCQUFnQix1QkFBdUIsaUJBQWlCLEtBQUssb0hBQW9ILEtBQUs7QUFDbFQsOENBQThDLGFBQWEsc0JBQXNCLFVBQVUsc0JBQXNCLEtBQUsscUJBQXFCLFNBQVMsZUFBZSx1QkFBdUIsV0FBVyw0QkFBNEIsV0FBVyxhQUFhLG1DQUFtQyw0QkFBNEIsbUJBQW1CLG1CQUFtQixxQkFBcUIsZ0JBQWdCLGlHQUFpRztBQUNwZSxVQUFVLHdCQUF3QixlQUFlLGFBQWEscUVBQXFFLDREQUE0RCxVQUFVLFVBQVUsaURBQWlELGlCQUFpQixLQUFLLHdCQUF3Qix3Q0FBd0Msa0JBQWtCLE1BQU0sdUNBQXVDLE1BQU0sbUNBQW1DLG1DQUFtQyxnQkFBZ0I7QUFDcmYsbUJBQW1CLHFDQUFxQyxpQ0FBaUMsaUNBQWlDLHlFQUF5RSwrREFBK0QsY0FBYyxhQUFhLGVBQWUseUJBQXlCLGFBQWEsZ0JBQWdCLGNBQWMsK0JBQStCLGFBQWEsaUJBQWlCLG1CQUFtQix3QkFBd0IsT0FBTyxFQUFFLGNBQWM7QUFDL2Usa0NBQWtDLGNBQWMsWUFBWSw2REFBNkQsY0FBYyxvQ0FBb0Msa0VBQWtFLG1CQUFtQixlQUFlLGNBQWMsY0FBYyxhQUFhLGVBQWUsaUJBQWlCLFFBQVEsdURBQXVELElBQUksc0NBQXNDLElBQUkseUJBQXlCLE9BQU87QUFDcmUsc0ZBQXNGLFFBQVEscUJBQXFCLElBQUksb0RBQW9ELElBQUksNkdBQTZHLE1BQU0seUNBQXlDLGlEQUFpRCw0REFBNEQsNkJBQTZCLGlDQUFpQztBQUN0ZixLQUFLLDhDQUE4QyxHQUFHLHNDQUFzQywyRkFBMkYsRUFBRSxxQ0FBcUMsb0ZBQW9GLEVBQUUsdUNBQXVDLHNHQUFzRyxFQUFFO0FBQ25jLHlEQUF5RCxtQ0FBbUMsV0FBVywyQkFBMkIsRUFBRSxzQkFBc0Isb0JBQW9CLFNBQVMsbUNBQW1DLFVBQVUsRUFBRSxVQUFVLG1DQUFtQyxXQUFXLEVBQUUsVUFBVSxtQ0FBbUMsV0FBVyxFQUFFLFVBQVUsb0NBQW9DLFlBQVksRUFBRSxVQUFVLG1DQUFtQyxXQUFXLEVBQUUsK0JBQStCO0FBQy9lLEtBQUssdUhBQXVILFNBQVMsR0FBRyxzQkFBc0Isa0RBQWtELFlBQVksRUFBRSxlQUFlLGdCQUFnQixrQkFBa0IsZ0JBQWdCLFFBQVEsWUFBWSxLQUFLLEtBQUssWUFBWSxNQUFNLDBCQUEwQixVQUFVLFdBQVcsSUFBSSxNQUFNLDBEQUEwRCxZQUFZLHlCQUF5QjtBQUN2ZSxjQUFjLFNBQVMsbUJBQW1CLGlCQUFpQixtQkFBbUIsNkJBQTZCLEVBQUUsNkNBQTZDLFFBQVEsbUNBQW1DLG1CQUFtQixFQUFFLFNBQVMsRUFBRSxPQUFPLHVCQUF1QixnQkFBZ0IsZ0JBQWdCLFVBQVUsVUFBVSw2RkFBNkYseUNBQXlDLG9CQUFvQixPQUFPO0FBQ3hkLGdCQUFnQixrQkFBa0IsS0FBSyxVQUFVLFVBQVUsS0FBSyxNQUFNLHVGQUF1Riw2QkFBNkIsa0JBQWtCLHNCQUFzQixzQkFBc0Isb0JBQW9CLG9CQUFvQixTQUFTLGtCQUFrQixVQUFVLGlCQUFpQixPQUFPLDZCQUE2QixLQUFLLEtBQUssS0FBSyxVQUFVLE9BQU8sVUFBVSxXQUFXLE9BQU8sZ0NBQWdDO0FBQ3RkLEVBQUUsS0FBSyxnQkFBZ0IsS0FBSyxLQUFLLFVBQVUsdUJBQXVCLG1CQUFtQixzQ0FBc0Msa0JBQWtCLG9CQUFvQixLQUFLLG9DQUFvQyxhQUFhLEtBQUssb0JBQW9CLGtCQUFrQiw4QkFBOEIsd0RBQXdELHNCQUFzQixLQUFLLGdFQUFnRSxVQUFVLHdCQUF3QixhQUFhO0FBQ2xlLFNBQVMscUJBQXFCLFlBQVksU0FBUyxtQ0FBbUMsd0JBQXdCLGtCQUFrQixVQUFVLFFBQVEsSUFBSSxhQUFhLDRDQUE0QyxJQUFJLGdCQUFnQiw2RkFBNkYsb0RBQW9ELElBQUksMkJBQTJCLGFBQWEsSUFBSSxjQUFjLFVBQVUsc0RBQXNEO0FBQ2xmLG9CQUFvQixtQkFBbUIscUJBQXFCLEtBQUssUUFBUSxJQUFJLG9CQUFvQixXQUFXLEtBQUssdUZBQXVGLDZCQUE2QixrQkFBa0Isc0JBQXNCLHNCQUFzQixvQkFBb0Isb0JBQW9CLFFBQVEsSUFBSSxhQUFhLFNBQVMsbUJBQW1CLFVBQVUsY0FBYyxlQUFlLGdCQUFnQiwrQkFBK0IsS0FBSyxLQUFLLEtBQUssVUFBVTtBQUMvZSxVQUFVLFdBQVcsT0FBTyxnQ0FBZ0MsbUNBQW1DLEtBQUssbUJBQW1CLEtBQUssS0FBSyxVQUFVLHFCQUFxQixLQUFLLGdCQUFnQixrQkFBa0Isb0JBQW9CLEtBQUssWUFBWSxJQUFJLGdCQUFnQixhQUFhLHNFQUFzRSxLQUFLLDZFQUE2RSxXQUFXLDBCQUEwQixhQUFhLDZCQUE2QjtBQUNwZixXQUFXLFlBQVksU0FBUyxrQkFBa0IsWUFBWSxLQUFLLGlFQUFpRSxnQkFBZ0IsY0FBYyxpQkFBaUIsd0JBQXdCLFlBQVksb0JBQW9CLFlBQVksS0FBSyxLQUFLLFlBQVksd0NBQXdDLHlCQUF5Qiw0QkFBNEIsa0NBQWtDLFlBQVksS0FBSztBQUM3Wiw4Q0FBOEMsaUJBQWlCLElBQUksbUdBQW1HLHNCQUFzQixJQUFJLHlCQUF5QixrQkFBa0IsY0FBYyxlQUFlLG9CQUFvQixVQUFVLG1EQUFtRCxhQUFhLGNBQWMsY0FBYyxrR0FBa0csa0JBQWtCO0FBQ3RmLG9GQUFvRixnQkFBZ0Isd0tBQXdLLGNBQWMsNkJBQTZCLDZEQUE2RCxjQUFjLDRFQUE0RSxvQkFBb0I7QUFDbGUsR0FBRywwQkFBMEIsaUNBQWlDLDJDQUEyQyxZQUFZLDBCQUEwQixFQUFFLDJCQUEyQiwyQkFBMkIsY0FBYyxzQ0FBc0Msa0JBQWtCLHFHQUFxRyxhQUFhLFlBQVksZ0JBQWdCLHVDQUF1Qyx5QkFBeUIseUJBQXlCO0FBQ3BmLGlEQUFpRCxjQUFjLDhCQUE4QixxQkFBcUIsdUJBQXVCLDRCQUE0QixjQUFjLG1DQUFtQyxtQkFBbUIscUJBQXFCLGVBQWUsY0FBYyxNQUFNLHVDQUF1Qyx5QkFBeUIsUUFBUSxXQUFXLG9CQUFvQixlQUFlLHdCQUF3QixzREFBc0Q7QUFDcmUsbUJBQW1CLGdEQUFnRCxnREFBZ0QsMkJBQTJCLDZCQUE2QixrQ0FBa0MsZ0NBQWdDLGtCQUFrQix3REFBd0QsYUFBYSxhQUFhLGdCQUFnQixnQkFBZ0Isd0JBQXdCLE9BQU8sNkRBQTZELHNDQUFzQyxXQUFXO0FBQzlmLCtHQUErRyxrRUFBa0UsT0FBTyxxQ0FBcUMsbURBQW1ELHNGQUFzRiwrQ0FBK0Msa0ZBQWtGO0FBQ3ZlLDJFQUEyRSxzRUFBc0UsOEVBQThFLHFHQUFxRyxXQUFXLGdDQUFnQywrQkFBK0IsbUJBQW1CLHdCQUF3QixJQUFJLHNCQUFzQixnQkFBZ0IsaUJBQWlCO0FBQ3BmLDhDQUE4QyxrREFBa0QsdUVBQXVFLE9BQU8sUUFBUSxXQUFXLHdIQUF3SCxTQUFTLFNBQVMsU0FBUyxLQUFLLFVBQVUsV0FBVyxxQkFBcUIsb0JBQW9CLHNCQUFzQiwyQkFBMkIsaUJBQWlCLGFBQWE7QUFDdGUsb0JBQW9CLGdCQUFnQixrQkFBa0IsS0FBSyxTQUFTLFlBQVkscUJBQXFCLE9BQU8sWUFBWSxxQkFBcUIsMkNBQTJDLHNDQUFzQyxpQ0FBaUMsV0FBVyxnQkFBZ0IseUJBQXlCLDJCQUEyQixnQ0FBZ0Msa0JBQWtCLG9CQUFvQixLQUFLLFNBQVMsMkRBQTJELEtBQUssS0FBSyxpQkFBaUIsVUFBVSxjQUFjO0FBQ2hoQixJQUFJLEVBQUUsT0FBTyx3Q0FBd0MsMkNBQTJDLDRCQUE0QiwwREFBMEQsOENBQThDLGdCQUFnQix5REFBeUQsK0NBQStDLGFBQWEsWUFBWSwyQkFBMkIsbUdBQW1HO0FBQ25mLHVCQUF1QixjQUFjLFNBQVMsV0FBVyxZQUFZLFNBQVMsa0JBQWtCLDZCQUE2QixXQUFXLDZHQUE2RyxrRUFBa0UsZ0hBQWdILCtCQUErQixxQ0FBcUM7QUFDM2UsbUNBQW1DLFNBQVMsc0NBQXNDLFdBQVcsY0FBYyxXQUFXLHVCQUF1Qix5QkFBeUIsS0FBSyxJQUFJLHlCQUF5Qix3QkFBd0IsUUFBUSxXQUFXLG9DQUFvQyx3QkFBd0IsUUFBUSxJQUFJLEtBQUssUUFBUSxXQUFXLDhCQUE4QixrRkFBa0YsZ0JBQWdCLGVBQWUsWUFBWTtBQUM5ZSxpQkFBaUIsRUFBRSxlQUFlLEtBQUssWUFBWSwyQkFBMkIsVUFBVSx3QkFBd0IsY0FBYyxRQUFRLFdBQVcsbUJBQW1CLFFBQVEsSUFBSSxtQkFBbUIsbUJBQW1CLFNBQVMsZ0RBQWdELHNCQUFzQixZQUFZLEdBQUcsRUFBRSxrQkFBa0IsZ0JBQWdCLG9CQUFvQixXQUFXLFlBQVksV0FBVyx5QkFBeUIsb0NBQW9DLEtBQUssR0FBRyxFQUFFLGNBQWM7QUFDbmUsb0JBQW9CLGlCQUFpQixZQUFZLG1CQUFtQixlQUFlLHVDQUF1QyxxQkFBcUIsa0JBQWtCLFdBQVcsUUFBUSxJQUFJLGdCQUFnQixPQUFPLGtCQUFrQixVQUFVLHFCQUFxQixvQkFBb0IsWUFBWSxVQUFVLGdCQUFnQixZQUFZLGdCQUFnQixZQUFZLFdBQVcsdUJBQXVCLHlCQUF5QixPQUFPLFVBQVUsa0JBQWtCLGdCQUFnQixXQUFXLE9BQU87QUFDbGUsb0JBQW9CLG1CQUFtQixPQUFPLFNBQVMsZ0JBQWdCLFlBQVksY0FBYyxjQUFjLGtCQUFrQixpQkFBaUIsbUJBQW1CLHdCQUF3QixrQ0FBa0MsRUFBRSxnQkFBZ0IsUUFBUSxvQkFBb0Isb0JBQW9CLGtDQUFrQyxvQkFBb0Isb0JBQW9CLGlCQUFpQixxQ0FBcUMscUNBQXFDLGlCQUFpQixRQUFRLElBQUk7QUFDbmUsMkJBQTJCLFNBQVMsS0FBSyxzQ0FBc0Msa0RBQWtELHNFQUFzRSxpQ0FBaUMsdUNBQXVDLGVBQWUsUUFBUSxJQUFJLGdHQUFnRyxRQUFRLEtBQUssS0FBSyxVQUFVLDZDQUE2QyxRQUFRLHNCQUFzQjtBQUNqZiw2QkFBNkIsRUFBRSxTQUFTLG9DQUFvQyxRQUFRLHNCQUFzQix1REFBdUQsRUFBRSxTQUFTLEVBQUUsT0FBTyxpQkFBaUIsNkJBQTZCLGdCQUFnQixLQUFLLGdCQUFnQixLQUFLLHNCQUFzQiwyQkFBMkIsRUFBRSxXQUFXLEtBQUssZ0JBQWdCLHlCQUF5QixXQUFXLGFBQWEsRUFBRSxXQUFXLDBEQUEwRCxTQUFTLG9CQUFvQjtBQUNyZixHQUFHLEtBQUssWUFBWSxXQUFXLFlBQVksMkJBQTJCLDJCQUEyQixjQUFjLE1BQU0sc0VBQXNFLDhEQUE4RCx1SEFBdUgsSUFBSSxRQUFRLHVFQUF1RSxzQkFBc0I7QUFDemQsR0FBRyxTQUFTLGNBQWMsTUFBTSxVQUFVLDBCQUEwQixZQUFZLE9BQU8sRUFBRSxTQUFTLG1CQUFtQix1Q0FBdUMsZUFBZSxxQ0FBcUMsZUFBZSxzQkFBc0IsY0FBYyxhQUFhLGNBQWMsb0JBQW9CLDhCQUE4QixFQUFFLGVBQWUsY0FBYyxVQUFVLDBFQUEwRSxJQUFJLFNBQVMscUJBQXFCO0FBQ3JlLFdBQVcsY0FBYyxFQUFFLGFBQWEsZ0JBQWdCLHVCQUF1QixHQUFHLDBDQUEwQyxvQkFBb0IseUJBQXlCLEVBQUUsb0RBQW9ELE9BQU8sY0FBYyxHQUFHLHFCQUFxQixnQkFBZ0IsRUFBRSw2QkFBNkIsT0FBTywwQkFBMEIsWUFBWSxXQUFXLDRCQUE0QixVQUFVLFVBQVUsVUFBVSxTQUFTLDRCQUE0QixhQUFhLG1CQUFtQjtBQUNsZixTQUFTLFNBQVMsT0FBTyxZQUFZLElBQUksUUFBUSx1QkFBdUIsaUJBQWlCLDBCQUEwQixtQ0FBbUMsUUFBUSxLQUFLLEVBQUUseUJBQXlCLDBEQUEwRCxZQUFZLGdCQUFnQix5QkFBeUIsWUFBWSxtQkFBbUIseUJBQXlCLFlBQVkscUJBQXFCLFVBQVUsWUFBWSxNQUFNLEdBQUcsc0JBQXNCLFFBQVEsT0FBTyxFQUFFLG9CQUFvQixxQkFBcUI7QUFDcmYsV0FBVyxHQUFHLG1DQUFtQyx1Q0FBdUMsRUFBRSxTQUFTLEdBQUcsc0JBQXNCLEtBQUssZUFBZSxLQUFLLGVBQWUsS0FBSyxLQUFLLHdEQUF3RCxlQUFlLHFDQUFxQyxlQUFlLDRCQUE0QixrREFBa0QsRUFBRSxvQkFBb0IsZUFBZSxrQkFBa0IsZUFBZSxjQUFjLGVBQWU7QUFDMWQsV0FBVyxjQUFjLHlCQUF5QixnQkFBZ0IsYUFBYSwySUFBMkksMkNBQTJDLGNBQWMsMEJBQTBCLGtCQUFrQixXQUFXLFdBQVcsZ0JBQWdCLFFBQVEsa0JBQWtCLFdBQVcsV0FBVyxpRUFBaUUsUUFBUSxhQUFhO0FBQzNlLG9CQUFvQixVQUFVLGNBQWMsd0JBQXdCLFlBQVksb0NBQW9DLG9CQUFvQixFQUFFLGVBQWUsaUJBQWlCLG9DQUFvQyw4RUFBOEUsRUFBRSxxQkFBcUIsb0NBQW9DLGtDQUFrQyxFQUFFLHVCQUF1QixlQUFlLGtEQUFrRDtBQUNuZCxrQ0FBa0Msb0NBQW9DLHNDQUFzQyxtQ0FBbUMsOENBQThDLGlCQUFpQixTQUFTLDBCQUEwQixVQUFVLHNCQUFzQixpQkFBaUIseUJBQXlCLGtCQUFrQixTQUFTLGNBQWMsa0JBQWtCLFlBQVksTUFBTSxrQkFBa0Isa0JBQWtCLGtCQUFrQixTQUFTLEVBQUUsV0FBVyx1QkFBdUI7QUFDM2Usb0JBQW9CLHFCQUFxQixFQUFFLFNBQVMsZ0JBQWdCLDhCQUE4QixzQkFBc0Isb0JBQW9CLGdEQUFnRCwyQkFBMkIsK0JBQStCLFlBQVksd0NBQXdDLDBDQUEwQyxTQUFTLG1CQUFtQixlQUFlLG9DQUFvQyxZQUFZLHFEQUFxRDtBQUNwZSwwQkFBMEIsYUFBYSxFQUFFLHNCQUFzQixvQkFBb0IseUJBQXlCLG1GQUFtRixtQkFBbUIsWUFBWSx1RUFBdUUsMEVBQTBFLFNBQVMsRUFBRSxZQUFZLGtCQUFrQixjQUFjLFdBQVcsV0FBVyxLQUFLLHlCQUF5QjtBQUMxZCwrQkFBK0IsaUZBQWlGLDJCQUEyQix1REFBdUQsUUFBUSwwREFBMEQsaUJBQWlCLEVBQUUsV0FBVyxXQUFXLG9CQUFvQjtBQUNqVSw4REFBOEQsZ0JBQWdCLEVBQUUsMkdBQTJHLFNBQVMsOERBQThELHVCQUF1Qiw2RUFBNkUsT0FBTyw4QkFBOEIsb0JBQW9CLFFBQVEsdURBQXVEO0FBQzlkLCtCQUErQixnQ0FBZ0MsU0FBUyxFQUFFLE9BQU8seUNBQXlDLGNBQWMsY0FBYyxXQUFXLGlCQUFpQixlQUFlLFNBQVMsRUFBRSxPQUFPLFNBQVMsV0FBVyxXQUFXLHlCQUF5QixvQkFBb0IsNENBQTRDLEVBQUUsWUFBWSw2REFBNkQsdURBQXVELGlCQUFpQjtBQUM5ZCx1RkFBdUYsd0JBQXdCLHNDQUFzQyxNQUFNLHNDQUFzQyx3Q0FBd0MsRUFBRSxPQUFPLG1DQUFtQyxnQkFBZ0IsZ0JBQWdCLFdBQVcsYUFBYSx1QkFBdUIsZ0JBQWdCLFNBQVMsRUFBRSxXQUFXLFdBQVcseUJBQXlCLG9CQUFvQixnQkFBZ0IsU0FBUyxFQUFFO0FBQzdkLEdBQUcsYUFBYSxTQUFTLE9BQU8sMkNBQTJDLG1CQUFtQixpQkFBaUIsOERBQThELHNCQUFzQixNQUFNLGdCQUFnQixvQkFBb0IsdUJBQXVCLEVBQUUsVUFBVSxTQUFTLG1CQUFtQixpQkFBaUIseUJBQXlCLGlKQUFpSjtBQUN2ZSx1QkFBdUIsR0FBRyxXQUFXLCtDQUErQyxJQUFJLG9CQUFvQixFQUFFLFlBQVksb0JBQW9CLE9BQU8sZ0NBQWdDLG9CQUFvQixrQkFBa0IsdUJBQXVCLGFBQWEsRUFBRSxvQkFBb0Isa0JBQWtCLHlCQUF5Qiw0Q0FBNEMsMEJBQTBCLEVBQUUsdUNBQXVDLHFDQUFxQyxlQUFlLFNBQVM7QUFDNWUscUNBQXFDLGlCQUFpQixxQ0FBcUMsT0FBTyxvQkFBb0IsZ0JBQWdCLGdCQUFnQixvQkFBb0IsU0FBUyxFQUFFLGdCQUFnQixjQUFjLHlCQUF5QixxQkFBcUIsRUFBRSx3RUFBd0UsZ0RBQWdELGtCQUFrQixzQ0FBc0MsZUFBZSxTQUFTO0FBQzNjLGdEQUFnRCxpQkFBaUIsMkZBQTJGLE9BQU8seUNBQXlDLGdCQUFnQixtQ0FBbUMsdUJBQXVCLGdCQUFnQixXQUFXLGNBQWMsa0JBQWtCLFNBQVMsRUFBRSxnQkFBZ0IsV0FBVyx1QkFBdUIsNEJBQTRCLEdBQUcsV0FBVyxVQUFVLGlPQUFpTyxTQUFTO0FBQzVxQixnQkFBZ0IsU0FBUyxFQUFFLHVDQUF1QyxhQUFhLGlCQUFpQixpREFBaUQsRUFBRSx3Q0FBd0MsU0FBUyxpQkFBaUIscUJBQXFCLHFCQUFxQixZQUFZLEVBQUUsdUNBQXVDLGdKQUFnSixpQkFBaUIsZ0JBQWdCO0FBQ3JlLHlDQUF5Qyx5QkFBeUIsb0hBQW9ILG9DQUFvQyxnQkFBZ0IsRUFBRSwyQ0FBMkMseUNBQXlDLG1EQUFtRCxpQkFBaUIscURBQXFELG9DQUFvQztBQUM3ZCxLQUFLLEdBQUcsK0JBQStCLHlCQUF5QixHQUFHLEtBQUssWUFBWSxFQUFFLHdDQUF3Qyx1QkFBdUIsWUFBWSxFQUFFLGlCQUFpQix1QkFBdUIsOEJBQThCLEVBQUUsRUFBRSx5Q0FBeUMsV0FBVyxpQkFBaUIscUJBQXFCLEVBQUUseUNBQXlDLHdEQUF3RCxpQkFBaUI7QUFDM2IsVUFBVSx3QkFBd0IsMkNBQTJDLGNBQWMsRUFBRSxrRUFBa0Usa0dBQWtHLGlCQUFpQixjQUFjLDBEQUEwRCw2QkFBNkIsdUVBQXVFLEVBQUUsaURBQWlEO0FBQ2pmLGFBQWEsaUJBQWlCLHVCQUF1QixzQkFBc0IsWUFBWSxFQUFFLHNDQUFzQyxRQUFRLHdDQUF3QyxTQUFTLGlCQUFpQiw0Q0FBNEMsRUFBRSxzQ0FBc0MsU0FBUyxpQkFBaUIsU0FBUyxFQUFFLHNDQUFzQyxhQUFhLGlCQUFpQixvQ0FBb0MsRUFBRSxzQ0FBc0MseUJBQXlCLFVBQVUsRUFBRTtBQUN2ZixnQkFBZ0IsdUJBQXVCLHVCQUF1QixFQUFFLEVBQUUsNENBQTRDLHlDQUF5QyxpQkFBaUIsMkNBQTJDLDBCQUEwQixZQUFZLEdBQUcsRUFBRSxTQUFTLGdCQUFnQixtQ0FBbUMsbUNBQW1DLGFBQWEsNERBQTRELFNBQVMsRUFBRSwrQkFBK0Isa0JBQWtCO0FBQ2xlLGtDQUFrQyxpQkFBaUIsRUFBRSxpRUFBaUUsMEJBQTBCLEVBQUUsNkJBQTZCLCtDQUErQyxZQUFZLE9BQU8sR0FBRyxVQUFVLE9BQU8sRUFBRSxtQ0FBbUMsV0FBVyx1QkFBdUIscUJBQXFCLEVBQUUsRUFBRSxTQUFTLGdCQUFnQixtQ0FBbUMsbUNBQW1DLDhCQUE4QjtBQUNsZSx1REFBdUQsS0FBSyxxQkFBcUIsbUNBQW1DLHdCQUF3QixpQkFBaUIsZ0JBQWdCLFVBQVUsbURBQW1ELHdCQUF3QixFQUFFLEtBQUssK0lBQStJLDJCQUEyQixjQUFjLFdBQVcsVUFBVSxTQUFTLGVBQWU7QUFDOWUsV0FBVyxXQUFXLFdBQVcsYUFBYSxxQkFBcUIsb0JBQW9CLHNCQUFzQixPQUFPLGFBQWEsbUNBQW1DLFVBQVUsRUFBRSx1RUFBdUUsY0FBYyxFQUFFLEVBQUUsbUNBQW1DLFdBQVcsdUJBQXVCLGNBQWMsdUJBQXVCLEdBQUcsOERBQThELG1CQUFtQixVQUFVLFVBQVUsbUNBQW1DO0FBQzlmLGVBQWUsRUFBRSx3QkFBd0Isb0JBQW9CLG9CQUFvQiwwQ0FBMEMsa0JBQWtCLElBQUksS0FBSyw2QkFBNkIsYUFBYSxrQkFBa0IsSUFBSSw2QkFBNkIsa0JBQWtCLDBDQUEwQyw0QkFBNEIsOEJBQThCLFlBQVksZ0JBQWdCLElBQUksS0FBSyx1QkFBdUIsa0VBQWtFLEVBQUUsY0FBYyxLQUFLO0FBQzVmLHlCQUF5QixpREFBaUQsSUFBSSxLQUFLLG9DQUFvQyxJQUFJLDREQUE0RCxvQ0FBb0MsR0FBRyxVQUFVLFlBQVksWUFBWSxhQUFhLEtBQUssR0FBRywyQkFBMkIsMkJBQTJCLElBQUksR0FBRyxTQUFTLEVBQUUsRUFBRSxTQUFTLGNBQWMsbUNBQW1DLG1DQUFtQyxXQUFXLHFCQUFxQjtBQUM1ZCxvQ0FBb0MsRUFBRSxFQUFFLG1DQUFtQyxXQUFXLHVCQUF1QixxQkFBcUIsRUFBRSxFQUFFLFNBQVMsc0JBQXNCLGlFQUFpRSxvQkFBb0Isb0JBQW9CLHFCQUFxQiwwQkFBMEIsR0FBRywrQ0FBK0MsaUJBQWlCLGtCQUFrQixvQkFBb0IsaUJBQWlCLFNBQVMsbUJBQW1CO0FBQ25kLG1DQUFtQyxnQkFBZ0IsaUNBQWlDLEdBQUcsRUFBRSxLQUFLLG9CQUFvQix3Q0FBd0Msa0RBQWtELGdEQUFnRCxtQ0FBbUMsNEJBQTRCLEdBQUcsYUFBYSxtREFBbUQsR0FBRyxpRUFBaUUsR0FBRyxJQUFJLEtBQUssc0NBQXNDO0FBQ3BmLGtDQUFrQyxHQUFHLElBQUksZ0JBQWdCLEdBQUcsT0FBTyxHQUFHLGtCQUFrQixxRkFBcUYsdUJBQXVCLE9BQU8sb0JBQW9CLFFBQVEsV0FBVyxPQUFPLE9BQU8saUNBQWlDLDBCQUEwQixFQUFFLDZCQUE2QiwyQkFBMkIsd0NBQXdDLHNCQUFzQixzQkFBc0IsU0FBUyxLQUFLLElBQUk7QUFDM2QsbUVBQW1FLGtDQUFrQyxtQkFBbUIsMEJBQTBCLGtCQUFrQixJQUFJLEVBQUUsbURBQW1ELEdBQUcsS0FBSyxvQkFBb0IsOENBQThDLHVDQUF1QyxXQUFXLGFBQWEsb0JBQW9CLFVBQVUsWUFBWSw0QkFBNEIsd0JBQXdCLHNDQUFzQztBQUMxZSxpQkFBaUIsSUFBSSxrQkFBa0IsR0FBRyxlQUFlLFdBQVcsdUJBQXVCLHNCQUFzQixzQkFBc0IsU0FBUyxLQUFLLEdBQUcsNEJBQTRCLGtCQUFrQixJQUFJLEVBQUUsaUJBQWlCLHdFQUF3RSxzQkFBc0IsYUFBYSx3RUFBd0UsY0FBYyxVQUFVLGNBQWMsR0FBRyx3Q0FBd0Msa0JBQWtCO0FBQ25mLG9EQUFvRCw2QkFBNkIsSUFBSSxjQUFjLDhCQUE4QixHQUFHLHNFQUFzRSxvQkFBb0IsSUFBSSxjQUFjLDBCQUEwQixvQkFBb0IsR0FBRyx5QkFBeUIsR0FBRyxnREFBZ0QsWUFBWSxRQUFRLE1BQU0sVUFBVSwrQ0FBK0MsT0FBTyxnQkFBZ0IsS0FBSztBQUM1ZCxZQUFZLEtBQUssYUFBYSxNQUFNLEdBQUcsWUFBWSxLQUFLLGtCQUFrQixNQUFNLEdBQUcsc0JBQXNCLGNBQWMsVUFBVSwwQ0FBMEMsMENBQTBDLDBDQUEwQyxrQkFBa0Isa0JBQWtCLGFBQWEscUJBQXFCLHNDQUFzQyxHQUFHLGVBQWUsZ0NBQWdDLGtFQUFrRSwwQkFBMEI7QUFDemYsR0FBRyx5Q0FBeUMsc0VBQXNFLGlCQUFpQixpQkFBaUIsb0JBQW9CLDBCQUEwQixFQUFFLGFBQWEsR0FBRyw4Q0FBOEMscURBQXFELHFCQUFxQixJQUFJLGFBQWEsb0JBQW9CLHNDQUFzQyxJQUFJLDBCQUEwQiwwQkFBMEIsZ0JBQWdCO0FBQy9kLFdBQVcsdUJBQXVCLDBCQUEwQixFQUFFLGFBQWEsR0FBRyxrRUFBa0UsVUFBVSwrRUFBK0UsMENBQTBDLFdBQVcsS0FBSyxXQUFXLElBQUksZUFBZSxzQkFBc0IsaUNBQWlDLE1BQU0sZ0JBQWdCLGdCQUFnQixLQUFLLGlCQUFpQix1QkFBdUIsS0FBSyx3Q0FBd0M7QUFDeGYsZUFBZSxFQUFFLDhCQUE4QixFQUFFLHNCQUFzQixnQ0FBZ0MsV0FBVyxLQUFLLDRFQUE0RSxNQUFNLGtCQUFrQixVQUFVLFVBQVUsc0dBQXNHLHVCQUF1QixHQUFHO0FBQy9XLHVEQUF1RCxHQUFHLEtBQUssVUFBVSxpQkFBaUIsTUFBTSxrQkFBa0IsTUFBTSxrQkFBa0IsTUFBTSxrQkFBa0IsTUFBTSxrQkFBa0IsTUFBTSxpQkFBaUIsTUFBTSxrQkFBa0IsTUFBTSxrQkFBa0IsTUFBTSxrQkFBa0IsTUFBTSxrQkFBa0IsTUFBTSxrQkFBa0IsTUFBTSxrQkFBa0Isb0VBQW9FLEdBQUcsU0FBUyxxQkFBcUIsS0FBSyxtQkFBbUI7QUFDOWQsYUFBYSx3REFBd0QscUJBQXFCLElBQUksZ0VBQWdFLHFCQUFxQixJQUFJLEdBQUcsSUFBSSxVQUFVLDZDQUE2QyxvQ0FBb0MsR0FBRyxvQkFBb0IsR0FBRyxTQUFTLDRCQUE0QixNQUFNLDZCQUE2QixJQUFJLE1BQU0sNkJBQTZCLElBQUksTUFBTSw2QkFBNkIsSUFBSSxNQUFNLGlCQUFpQixNQUFNO0FBQzFlLEtBQUssSUFBSSxNQUFNLGtCQUFrQixJQUFJLE1BQU0sa0JBQWtCLElBQUksTUFBTSx5QkFBeUIsTUFBTSx5QkFBeUIsTUFBTSx5QkFBeUIsNEJBQTRCLHNCQUFzQixzRUFBc0Usd0ZBQXdGLGdDQUFnQyxhQUFhLDJCQUEyQixtQkFBbUIsUUFBUSxLQUFLLElBQUksb0JBQW9CLGNBQWM7QUFDNWYsS0FBSyw4RkFBOEYsYUFBYSxhQUFhLHdFQUF3RSxHQUFHLGFBQWEsOENBQThDLEdBQUcsdUJBQXVCLFdBQVcsS0FBSyxXQUFXLFFBQVEsYUFBYSxhQUFhLHdEQUF3RCxHQUFHLGFBQWEsOEJBQThCLEdBQUcsdUJBQXVCLFdBQVcsS0FBSyxXQUFXO0FBQ3JmLElBQUkscURBQXFELHFCQUFxQixNQUFNLGlEQUFpRCxnQkFBZ0IsK0JBQStCLDJEQUEyRCxHQUFHLFNBQVMsK0NBQStDLGtCQUFrQixNQUFNLGlEQUFpRCxnQkFBZ0IsNEJBQTRCLFNBQVMsR0FBRyx3QkFBd0IsZ0JBQWdCLGtCQUFrQixZQUFZLEdBQUc7QUFDcGYsRUFBRSxzQ0FBc0MsOENBQThDLG9FQUFvRSxXQUFXLGlCQUFpQixXQUFXLFlBQVksdUJBQXVCLE1BQU0sbUJBQW1CLHdFQUF3RSxXQUFXLHdCQUF3QixvQkFBb0IsUUFBUSxnQ0FBZ0MsU0FBUyxFQUFFLDhCQUE4QixTQUFTLEVBQUUsV0FBVyxpQkFBaUI7QUFDcGYsaUJBQWlCLFFBQVEsa0JBQWtCLHFCQUFxQixTQUFTLGVBQWUsZUFBZSxtQ0FBbUMsMENBQTBDLEdBQUcsOENBQThDLEtBQUssc0JBQXNCLHlDQUF5QyxtQ0FBbUMsaURBQWlELHFCQUFxQixXQUFXLG9CQUFvQixJQUFJLCtEQUErRDtBQUNwZixxQkFBcUIsYUFBYSxTQUFTLGVBQWUsUUFBUSx3QkFBd0Isc0JBQXNCLFdBQVcscUJBQXFCLGNBQWMsa0NBQWtDLGNBQWMsWUFBWSxRQUFRLHVDQUF1QyxpQkFBaUIsWUFBWSw0QkFBNEIsdUJBQXVCLGVBQWUsU0FBUyxzQkFBc0IsTUFBTSxVQUFVLGtDQUFrQyx5Q0FBeUMsaUJBQWlCO0FBQ25mLDZCQUE2Qiw4SEFBOEgsa0hBQWtILGNBQWMsd0NBQXdDLHNCQUFzQixZQUFZLGlDQUFpQyxJQUFJLGlCQUFpQixjQUFjLGtDQUFrQyx3QkFBd0IsY0FBYztBQUNqZixHQUFHLGNBQWMsMkNBQTJDLDBCQUEwQixFQUFFLDRCQUE0Qix5QkFBeUIscUVBQXFFLG1EQUFtRCxTQUFTLDBCQUEwQixZQUFZLEVBQUUsMENBQTBDLGVBQWUsaUJBQWlCLHFCQUFxQixtQkFBbUIsNkNBQTZDO0FBQ3JkLDRCQUE0QiwrQ0FBK0MsS0FBSyxzQkFBc0IseUNBQXlDLHNDQUFzQyxpREFBaUQsc0JBQXNCLFdBQVcsdUJBQXVCLElBQUksK0RBQStELEdBQUcsaUJBQWlCLGNBQWMsa0JBQWtCLHVDQUF1Qyx3QkFBd0IsZUFBZTtBQUNuZSxrQkFBa0IseUNBQXlDLDZDQUE2Qyw2QkFBNkIsOEJBQThCLDZCQUE2Qix3QkFBd0IsRUFBRSxlQUFlLDBFQUEwRSxnQkFBZ0Isd0NBQXdDLEVBQUUsNENBQTRDLDREQUE0RCxFQUFFLDhDQUE4QztBQUNyZ0IsK0NBQStDLHdDQUF3QyxvQkFBb0IsRUFBRSxFQUFFLFVBQVUsVUFBVSxpREFBaUQseUJBQXlCLElBQUksNkNBQTZDLEdBQUcsZUFBZSxnQ0FBZ0MsNkJBQTZCLFdBQVcsc0NBQXNDLFVBQVUsbUJBQW1CLGdCQUFnQixzQkFBc0IsV0FBVztBQUM1YyxVQUFVLElBQUksRUFBRSxxQkFBcUIsYUFBYSxpRUFBaUUsR0FBRyxzQkFBc0IsV0FBVywySEFBMkgsS0FBSyxlQUFlLGlCQUFpQixtQkFBbUIsTUFBTSwyQkFBMkIsTUFBTSxvREFBb0QsTUFBTSxxQkFBcUIsSUFBSSxJQUFJLEVBQUUsdUNBQXVDO0FBQ2pmLHNDQUFzQyxFQUFFLHVCQUF1QixtQkFBbUIsbURBQW1ELDhDQUE4Qyw0REFBNEQsMkJBQTJCLE1BQU0sWUFBWSxPQUFPLGlCQUFpQix1QkFBdUIsd0NBQXdDLDBEQUEwRCw4Q0FBOEM7QUFDM2QsZ0NBQWdDLG9DQUFvQywrQkFBK0IseUNBQXlDLHNCQUFzQiwrQkFBK0IsZ0NBQWdDLDZCQUE2QixnQ0FBZ0MsZ0RBQWdELHdCQUF3Qix5QkFBeUIsNkNBQTZDLHlCQUF5QixtQ0FBbUM7QUFDeGUsMEJBQTBCLCtEQUErRCw4REFBOEQseUJBQXlCLDRFQUE0RSwwRUFBMEUsUUFBUSxpS0FBaUssS0FBSztBQUNwZiw0RkFBNEYsdUVBQXVFLGlDQUFpQyxlQUFlLEVBQUUsR0FBRyxTQUFTLE9BQU8sb0NBQW9DLDJEQUEyRCxLQUFLLEtBQUssMkNBQTJDLGtCQUFrQixHQUFHLE9BQU8sZUFBZSxNQUFNLG1CQUFtQixZQUFZLGtCQUFrQixLQUFLO0FBQ25lLGlDQUFpQywwQ0FBMEMsZ0RBQWdELGtHQUFrRywrQ0FBK0MsNERBQTRELGtCQUFrQixHQUFHLEtBQUssd0RBQXdELEdBQUcsb0NBQW9DLHlDQUF5QyxhQUFhO0FBQ3ZmLGtCQUFrQixLQUFLLHFCQUFxQixrQkFBa0IsR0FBRyxLQUFLLDJCQUEyQixNQUFNLEdBQUcsRUFBRSxvQ0FBb0Msb0NBQW9DLGVBQWUsb0ZBQW9GLG1CQUFtQixLQUFLLGtCQUFrQiwrQkFBK0IsRUFBRSxvQ0FBb0Msa0NBQWtDLGdCQUFnQixNQUFNLDhDQUE4QztBQUM1ZSxRQUFRLHdCQUF3QixNQUFNLElBQUksS0FBSyxFQUFFLG1CQUFtQiwrQkFBK0IsVUFBVSxrQkFBa0IsNkNBQTZDLFVBQVUsRUFBRSx1QkFBdUIsVUFBVSxFQUFFLGVBQWUsUUFBUSxRQUFRLFFBQVEscUJBQXFCLGlCQUFpQixZQUFZLFdBQVcseUJBQXlCLFNBQVMsb0JBQW9CLDZCQUE2QixXQUFXLG9CQUFvQixTQUFTLFVBQVUsd0NBQXdDO0FBQzVlLFVBQVUsdUJBQXVCLDJEQUEyRCxxQkFBcUIsMENBQTBDLGFBQWEsS0FBSywyREFBMkQsZ0NBQWdDLGFBQWEsd0JBQXdCLDZEQUE2RCwrQkFBK0IsY0FBYyxpRUFBaUUseUJBQXlCLFlBQVksZ0JBQWdCO0FBQzdnQixPQUFPLFlBQVkscUJBQXFCLFFBQVEsNERBQTRELFlBQVksd0VBQXdFLDRCQUE0QixNQUFNLG9CQUFvQixzQkFBc0IsK0NBQStDLDRCQUE0QiwyQkFBMkIsNkNBQTZDLHlCQUF5QixnREFBZ0QsS0FBSztBQUM3ZSxPQUFPLHNCQUFzQixlQUFlLDBCQUEwQixrQ0FBa0MseUVBQXlFLGVBQWUsS0FBSztBQUNyTSwwQ0FBMEMsT0FBTywrT0FBK08sYUFBYTtBQUM3UyxvZkFBb2Y7QUFDcGYsY0FBYyxtUEFBbVAsZUFBZSxzQ0FBc0MsWUFBWSxFQUFFLEtBQUssa0JBQWtCLGFBQWEsU0FBUyx3QkFBd0IsU0FBUywyQkFBMkIsUUFBUSx3QkFBd0IsV0FBVyxZQUFZLFNBQVM7QUFDN2UsR0FBRyxpQkFBaUIsYUFBYSxjQUFjLFFBQVEsSUFBSSxjQUFjLE1BQU0sY0FBYyxPQUFPLFVBQVUsSUFBSSx1QkFBdUIsSUFBSSxnQkFBZ0IsTUFBTSxnQ0FBZ0MsTUFBTSxzQkFBc0IsVUFBVSxLQUFLLDJSQUEyUjtBQUN6Z0IsSUFBSSw2RkFBNkYsS0FBSywwQ0FBMEMsaUNBQWlDLFdBQVcsV0FBVyxXQUFXLFdBQVcsV0FBVyxXQUFXLFdBQVcsUUFBUSx3SEFBd0gsK0dBQStHO0FBQzdlLGtCQUFrQixtQkFBbUIsbUJBQW1CLG1CQUFtQiw0TEFBNEwsV0FBVyxXQUFXLFlBQVksV0FBVyxXQUFXLFNBQVMsV0FBVyxXQUFXLFdBQVcsV0FBVyxZQUFZLFlBQVksV0FBVyxXQUFXLFlBQVksV0FBVyxXQUFXLFlBQVksYUFBYSxZQUFZO0FBQ3plLFlBQVksU0FBUyxXQUFXLFdBQVcsV0FBVyxXQUFXLFdBQVcsV0FBVyxXQUFXLFlBQVksV0FBVyxXQUFXLDJCQUEyQixjQUFjLFlBQVksZ0JBQWdCLG9CQUFvQixrQkFBa0IseUJBQXlCLHdCQUF3QixPQUFPLEVBQUUsY0FBYyxxQkFBcUIsK0JBQStCLHdCQUF3QixvQkFBb0IsYUFBYSxlQUFlLHNCQUFzQixPQUFPO0FBQ2hkLGlEQUFpRCw0QkFBNEIsZ0VBQWdFLDhDQUE4QyxTQUFTLG1DQUFtQyxVQUFVLEVBQUUsYUFBYSw4QkFBOEIsNkJBQTZCLGtEQUFrRCxRQUFRLG1DQUFtQyxtQkFBbUIsRUFBRSxTQUFTLEVBQUUsT0FBTyxxQkFBcUIsZ0JBQWdCO0FBQ3BlLDZQQUE2UDtBQUM3UCxFQUFFLG9DQUFvQyxVQUFVLHNCQUFzQixPQUFPLHVCQUF1QixtQkFBbUIsc0NBQXNDLGtCQUFrQixvQkFBb0IseUNBQXlDLDBDQUEwQyx1REFBdUQsVUFBVSwyQkFBMkIsa0JBQWtCLDZCQUE2QixxQkFBcUIsWUFBWSxTQUFTLGtCQUFrQixnQkFBZ0Isb0JBQW9CLHlCQUF5QjtBQUMxaEIsdUJBQXVCLHlDQUF5Qyx1REFBdUQsRUFBRSxpQ0FBaUMsT0FBTyxXQUFXLFdBQVcsVUFBVSxXQUFXLFdBQVcsWUFBWSw2S0FBNks7QUFDaFosNk5BQTZOLEtBQUssdUtBQXVLLEtBQUs7QUFDOVksWUFBWSxLQUFLLGlCQUFpQiwrQkFBK0IsbUJBQW1CLGFBQWEsMkNBQTJDLFdBQVcsZ0JBQWdCLGtCQUFrQixxQkFBcUIsb0JBQW9CLGtCQUFrQixRQUFRLFVBQVUsVUFBVSwyQ0FBMkMsa0NBQWtDLE9BQU8sdUJBQXVCLDJEQUEyRCxrREFBa0QsVUFBVTtBQUNsZixjQUFjLHFCQUFxQiw4Q0FBOEMsb0NBQW9DLFFBQVEsV0FBVyxVQUFVLGdDQUFnQyxnQ0FBZ0MsT0FBTyxhQUFhLFVBQVUsV0FBVyxLQUFLLFdBQVcsb0lBQW9JLFNBQVMsU0FBUyxXQUFXLFVBQVUsV0FBVyxLQUFLO0FBQ3RjLGlCQUFpQixPQUFPLE9BQU8sOEZBQThGLFlBQVksaUNBQWlDLGdCQUFnQixrQkFBa0Isa0JBQWtCLFlBQVksV0FBVyxvREFBb0QsV0FBVyxXQUFXLG9CQUFvQixXQUFXLGNBQWMsbUJBQW1CLGFBQWEsc0NBQXNDLEtBQUssY0FBYyxJQUFJLHFCQUFxQixLQUFLLEtBQUssV0FBVztBQUNuZixZQUFZLFVBQVUsZUFBZSxhQUFhLGlDQUFpQyxhQUFhLDJCQUEyQixjQUFjLG1CQUFtQixJQUFJLHNCQUFzQixJQUFJLEVBQUUsY0FBYyxhQUFhLFlBQVksWUFBWSxZQUFZLFlBQVksWUFBWSxZQUFZLGVBQWUsa0JBQWtCLElBQUksc0JBQXNCLElBQUksRUFBRSxjQUFjLGNBQWMsUUFBUSxNQUFNLG1DQUFtQyxXQUFXLDBDQUEwQyxFQUFFLE9BQU87QUFDM2UsWUFBWSxjQUFjLEtBQUssV0FBVyxjQUFjLFNBQVMscUJBQXFCLG9CQUFvQixzQkFBc0Isa0JBQWtCLGNBQWMsV0FBVyxXQUFXLFlBQVksbUNBQW1DLGdCQUFnQixHQUFHLFVBQVUsSUFBSSxrQkFBa0Isb0JBQW9CLGlCQUFpQixtR0FBbUcsV0FBVyxXQUFXLFVBQVUsYUFBYSxtQkFBbUIsYUFBYTtBQUM3ZSxTQUFTLEtBQUssR0FBRyw2QkFBNkIsNkRBQTZELHVCQUF1QixNQUFNLHNEQUFzRCx3REFBd0QsSUFBSSwwQkFBMEIsaUNBQWlDLFdBQVcsMEJBQTBCLCtCQUErQiw2QkFBNkIsc0NBQXNDLDBCQUEwQjtBQUN0ZCxZQUFZLDJCQUEyQixFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsUUFBUSxlQUFlLGNBQWMsZ0VBQWdFLDZDQUE2QyxxREFBcUQsV0FBVyxjQUFjLFVBQVUsSUFBSSxPQUFPLGtCQUFrQixhQUFhLGNBQWMsbUJBQW1CLFdBQVcsaUJBQWlCLGNBQWMsU0FBUyxhQUFhLGlDQUFpQyxzQkFBc0I7QUFDL2UsdUVBQXVFLDJGQUEyRixhQUFhLFVBQVUsV0FBVyxJQUFJLGVBQWUsYUFBYSxJQUFJLGtCQUFrQixjQUFjLGFBQWEsbUJBQW1CLFFBQVEsa0JBQWtCLHNDQUFzQyxrQkFBa0IsY0FBYyxrQkFBa0IsY0FBYztBQUN4YSxrREFBa0QsbUZBQW1GLHlKQUF5Six5RkFBeUYsZUFBZSxpRUFBaUUsTUFBTTtBQUM3YyxhQUFhLGtHQUFrRyxpR0FBaUcsbUJBQW1CLGlEQUFpRCxFQUFFLElBQUksT0FBTyxrQkFBa0IsOEZBQThGLElBQUksVUFBVSxtQ0FBbUMsT0FBTyxhQUFhLGVBQWU7QUFDcmUseUVBQXlFLHFCQUFxQiwrQkFBK0Isc0JBQXNCLHNCQUFzQixvSkFBb0osTUFBTSxVQUFVLHlCQUF5QixnQkFBZ0IsTUFBTSxtQkFBbUIsTUFBTSxtQkFBbUIsVUFBVSxPQUFPLGtCQUFrQixZQUFZLFdBQVcsaUJBQWlCO0FBQ25mLGNBQWMsUUFBUSxTQUFTLG1DQUFtQyxnREFBZ0QsMkJBQTJCLFdBQVcsSUFBSSxpR0FBaUcsVUFBVSxVQUFVLFVBQVUsVUFBVSxVQUFVLFVBQVUsYUFBYSxzQkFBc0IsSUFBSSxFQUFFLGtDQUFrQyxJQUFJLGNBQWMsZUFBZSxFQUFFLGlCQUFpQixVQUFVOztBQUVsYyxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsWUFBWSxPQUFPO0FBQ25CO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQSxDQUFDLHFJQUFxSTtBQUN0SSxDQUFDLEdBQUc7QUFDSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixNQUFNO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsS0FBSztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLFlBQVk7QUFDMUI7QUFDQSxvQkFBb0IsWUFBWTtBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQSxnQkFBZ0IsS0FBSztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsZ0JBQWdCLFlBQVk7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7O0FBRUE7QUFDQSxpQ0FBaUMsYUFBYTtBQUM5QyxrQ0FBa0M7QUFDbEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QyxpQkFBaUI7QUFDOUQsY0FBYyxnQkFBZ0I7QUFDOUI7QUFDQSxpREFBaUQ7QUFDakQ7QUFDQSxjQUFjO0FBQ2Qsd0JBQXdCO0FBQ3hCO0FBQ0Esa0NBQWtDO0FBQ2xDLGNBQWM7QUFDZCxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGdCQUFnQjtBQUM5QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDLEVBQUUsNEVBQTRFO0FBQy9FOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsRUFBRSxtQ0FBbUM7QUFDdEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQjtBQUNBLG9CQUFvQixZQUFZO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLGdCQUFnQixZQUFZO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0EsRztBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQSw4REFBOEQ7QUFDOUQsY0FBYyxLQUFLO0FBQ25CLDhDQUE4QztBQUM5QyxnQkFBZ0IsS0FBSztBQUNyQjtBQUNBLDREQUE0RDtBQUM1RDtBQUNBO0FBQ0E7QUFDQSw2REFBNkQsc0JBQXNCO0FBQ25GO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0I7QUFDdEIsc0JBQXNCO0FBQ3RCLHNCQUFzQjs7QUFFdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGVBQWU7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMseUJBQXlCLHVCQUF1QjtBQUM5RjtBQUNBLGNBQWMsZUFBZTtBQUM3QiwyRUFBMkU7QUFDM0U7QUFDQSxjQUFjLGtDQUFrQyxZQUFZLG1CQUFtQixLQUFLLG1CQUFtQixnQkFBZ0I7QUFDdkg7O0FBRUE7O0FBRUE7QUFDQSxjQUFjLGVBQWU7QUFDN0I7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQyxFQUFFLDRFQUE0RTtBQUMvRTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDO0FBQzVDLGNBQWMsS0FBSztBQUNuQjtBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLEtBQUs7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlELGlCQUFpQjtBQUNsRSxjQUFjLGNBQWM7QUFDNUI7QUFDQSxpREFBaUQ7QUFDakQ7QUFDQSxjQUFjLHNCQUFzQixvQ0FBb0MsY0FBYztBQUN0RjtBQUNBO0FBQ0E7QUFDQSxjQUFjLGNBQWM7QUFDNUI7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQyxFQUFFLHlCQUF5QjtBQUM1Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQjtBQUNBLG9CQUFvQixZQUFZO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxnQkFBZ0IsWUFBWTtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRCwrQ0FBK0M7QUFDekcsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsMkJBQTJCLFdBQVc7QUFDdEMsMkJBQTJCLFdBQVc7QUFDdEMsK0I7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxlQUFlO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELHlCQUF5Qix1QkFBdUI7QUFDaEc7QUFDQSxjQUFjLGVBQWU7QUFDN0IsMkVBQTJFO0FBQzNFO0FBQ0EsY0FBYyxrQ0FBa0MsWUFBWSxtQkFBbUIsS0FBSyxtQkFBbUIsZ0JBQWdCO0FBQ3ZIOztBQUVBO0FBQ0E7QUFDQSxjQUFjLGVBQWU7QUFDN0I7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQyxFQUFFLDRFQUE0RTtBQUMvRTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixZQUFZO0FBQzVCO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsZ0JBQWdCLFlBQVk7QUFDNUI7QUFDQSxLO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxFQUFFLG9DQUFvQztBQUN2Qzs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEVBQUUsZ0NBQWdDO0FBQ25DOztBQUVBOztBQUVBOztBQUVBOztBQUVBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDLEVBQUUseUJBQXlCO0FBQzVCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEs7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTtBQUNBLGFBQWE7QUFDYixhQUFhO0FBQ2I7QUFDQTtBQUNBLENBQUMsR0FBRztBQUNKOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxvREFBb0Q7QUFDdkQ7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFlBQVk7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQjtBQUNBO0FBQ0EsZ0JBQWdCLEtBQUs7QUFDckIsa0JBQWtCLEtBQUs7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsTUFBTTtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLE1BQU07QUFDL0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0Esb0JBQW9CLE9BQU87QUFDM0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEVBQUUsa0RBQWtEO0FBQ3JEOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEVBQUUseUJBQXlCO0FBQzVCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGVBQWU7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGFBQWE7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxFQUFFLDhHQUE4RztBQUNqSDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0QsaUJBQWlCO0FBQ3ZFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxpQkFBaUI7QUFDdkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxpQkFBaUI7QUFDdkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxFQUFFLDBDQUEwQztBQUM3Qzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLEVBQUU7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1CLGlCQUFpQjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCO0FBQ0EsK0JBQStCLG9CQUFvQjtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBLHNCQUFzQjtBQUN0QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxHQUFHOztBQUVKLENBQUMsR0FBRztBQUNKOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0Esa0RBQWtEO0FBQ2xEO0FBQ0EscUNBQXFDOztBQUVyQztBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQSxtQ0FBbUMsK0JBQStCO0FBQ2xFOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixrQkFBa0I7QUFDbkM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixrQkFBa0I7QUFDbEM7QUFDQSxzQ0FBc0MsV0FBVztBQUNqRDs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxrQkFBa0I7QUFDckI7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsZUFBZTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEMsMkJBQTJCLFlBQVksT0FBTztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU8sT0FBTztBQUNkLHNDQUFzQztBQUN0QztBQUNBO0FBQ0EsK0JBQStCLE1BQU07QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsZ0JBQWdCO0FBQ3RDLHdCQUF3QixtQkFBbUI7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxlQUFlO0FBQzdCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLHFCQUFxQjtBQUNuQztBQUNBO0FBQ0EsMkJBQTJCLFlBQVksRUFBRTtBQUN6QztBQUNBLGdCQUFnQixZQUFZO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHOztBQUVBLFVBQVU7QUFDVjs7QUFFQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDRCQUE0QjtBQUM1Qjs7QUFFQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQSwwQ0FBMEMsbUJBQW1CO0FBQzdEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGFBQWE7QUFDM0I7QUFDQTtBQUNBO0FBQ0EsY0FBYyxrQkFBa0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0EsY0FBYyxrQkFBa0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtEQUErRDtBQUMvRDtBQUNBO0FBQ0EsY0FBYyxrQkFBa0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLDJDQUEyQyxPQUFPO0FBQ2pHO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBLEdBQUc7QUFDSCw2QkFBNkI7QUFDN0I7QUFDQSxjQUFjLHFCQUFxQjtBQUNuQztBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBLGtGQUFrRixNQUFNO0FBQ3hGO0FBQ0EsMkRBQTJELFVBQVU7QUFDckU7QUFDQTtBQUNBLE87QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixhQUFhO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0Isa0JBQWtCO0FBQ2xDLGtCQUFrQixhQUFhO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGFBQWE7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixhQUFhO0FBQzdCO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHVEQUF1RDtBQUN2RCxhQUFhO0FBQ2I7QUFDQSxlQUFlO0FBQ2Y7QUFDQSx3QkFBd0I7QUFDeEI7O0FBRUE7QUFDQTtBQUNBLGNBQWMsc0JBQXNCO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRDs7QUFFM0Q7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUssYUFBYSxLQUFLO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMLFNBQVMsRUFBRSxxQ0FBcUMsc0JBQXNCLGlDQUFpQyxRQUFRLDhCQUE4Qix1QkFBdUI7O0FBRXBLLGNBQWMscUJBQXFCO0FBQ25DO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFlBQVk7QUFDWixHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEVBQUUsK0VBQStFO0FBQ2xGOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVELGtDQUFrQyxpQ0FBaUMsZUFBZSxlQUFlLGdCQUFnQixvQkFBb0IsTUFBTSwwQ0FBMEMsK0JBQStCLGFBQWEscUJBQXFCLG1DQUFtQyxFQUFFLEVBQUUsY0FBYyxXQUFXLFVBQVUsRUFBRSxVQUFVLE1BQU0seUNBQXlDLEVBQUUsVUFBVSxrQkFBa0IsRUFBRSxFQUFFLGFBQWEsRUFBRSwyQkFBMkIsMEJBQTBCLFlBQVksRUFBRSwyQ0FBMkMsOEJBQThCLEVBQUUsT0FBTyw2RUFBNkUsRUFBRSxHQUFHLEVBQUU7O0FBRXJwQjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLGlCQUFpQixjQUFjO0FBQy9CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFlBQVk7QUFDWixHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBLENBQUMsR0FBRztBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsa0NBQWtDLE9BQU87QUFDekM7O0FBRUEsbUJBQW1CLG1CQUFtQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsOEZBQThGO0FBQ2pHOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQ0FBb0MsU0FBUztBQUM3QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBOztBQUVBLDBCQUEwQixtQkFBbUI7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSw4QkFBOEI7QUFDakM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTs7O0FBR0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxpR0FBaUc7QUFDcEc7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxnQkFBZ0I7QUFDOUI7QUFDQSxnQkFBZ0Is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QSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsVUFBVTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLFVBQVU7QUFDekI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRDtBQUN0RCx3Q0FBd0M7QUFDeEMsd0NBQXdDO0FB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEVBQThFLDRCQUE0QixnQkFBZ0I7QUFDMUgsOEVBQThFLDJCQUEyQixnQkFBZ0I7QUFDekgscURBQXFELG9EQUFvRCxnQkFBZ0I7QUFDekgscURBQXFELG9EQUFvRCxnQkFBZ0I7QUFDekg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQix1QkFBdUI7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9EQUFvRCwwQkFBMEI7QUFDOUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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Q0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsTUFBTTtBQUNwQjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTs7QUFFQSxjQUFjLEtBQUs7QUFDbkI7QUFDQSxnQkFBZ0IsS0FBSztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsTUFBTTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCLEtBQUs7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixLQUFLO0FBQ3JCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsWTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsRUFBRSw4SEFBOEg7QUFDakk7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEdBQUc7QUFDSjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxNQUFNO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxxSUFBcUk7QUFDdEksQ0FBQyxFQUFFLHdDQUF3QztBQUMzQyxhQUFhOztBQUViOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLFNBQVM7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEdBQUc7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLG9DQUFvQyxPQUFPO0FBQzNDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGtCQUFrQjtBQUNyQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsa0JBQWtCLGNBQWM7QUFDaEM7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQSxnQkFBZ0IsS0FBSztBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFlBQVksc0JBQXNCO0FBQ2xDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFlBQVksc0JBQXNCO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsWUFBWSxtQkFBbUI7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsY0FBYyxnQkFBZ0I7QUFDOUI7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixpQkFBaUI7QUFDakM7QUFDQTtBQUNBLGtCQUFrQixnQkFBZ0I7QUFDbEM7QUFDQTtBQUNBLG9CQUFvQixlQUFlO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsU0FBUztBQUNqQztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUseUhBQXlIO0FBQzVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGNBQWM7QUFDNUQ7QUFDQTtBQUNBLDZCQUE2QixjQUFjO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUyxjQUFjO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QztBQUM5Qyx5QkFBeUI7QUFDekI7QUFDQTtBQUNBLGtCQUFrQixXQUFXO0FBQzdCLGlCQUFpQixnQkFBZ0IsVUFBVTtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxvREFBb0QsY0FBYztBQUNsRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxjQUFjO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNEJBQTRCO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QztBQUM1QztBQUNBO0FBQ0E7QUFDQSxXQUFXOztBQUVYLEtBQUs7QUFDTDtBQUNBO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0Msa0JBQWtCO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbURBQW1ELHFCQUFxQjtBQUN4RTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjs7QUFFcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFD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QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGNBQWMsUUFBUTtBQUN0Qjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7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O0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRCxDQUFDLEVBQUUsK0hBQStIO0FBQ2xJO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLFlBQVk7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDhEQUE4RDtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGNBQWMsa0JBQWtCO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWMsbUJBQW1CO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHlDQUF5QztBQUN6Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGNBQWMsd0JBQXdCO0FBQ3RDO0FBQ0E7O0FBRUE7QUFDQSxzQkFBc0IsY0FBYztBQUNwQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsWUFBWTtBQUNaOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSx3RUFBd0U7QUFDM0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsK0JBQStCO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxrQkFBa0Isd0JBQXdCO0FBQzFDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGtEQUFrRDtBQUNyRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCOztBQUVsQixrQkFBa0IsT0FBTztBQUN6Qjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUNiO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0IsMEVBQTBFOztBQUUxRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBOztBQUVB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QTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw2RUFBNkU7QUFDN0U7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0IsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsNkJBQTZCLG9DQUFvQztBQUNqRSw0QkFBNEI7QUFDNUIsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDLGNBQWMsRUFBRTs7QUFFbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQSx3QkFBd0Isc0JBQXNCO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFD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Q0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdDQUFnQyxjQUFjOztBQUU5QztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDZGQUE2RjtBQUNoRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLCtKQUErSjtBQUNsSztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQSxDQUFDLEVBQUUseURBQXlEO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRFQUE0RSx5QkFBeUI7QUFDckcsU0FBUztBQUNUO0FBQ0EsMEJBQTBCLHFCQUFxQjtBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDhGQUE4RjtBQUNqRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUEsa0JBQWtCLGdCQUFnQjtBQUNsQzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGlCQUFpQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnQkFBZ0I7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxvQkFBb0IsRUFBRTtBQUM1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseURBQXlELGVBQWU7QUFDeEU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUscUtBQXFLO0FBQ3hLO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMEZBQTBGO0FBQzdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG9DQUFvQyxvQkFBb0I7QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5Qyw2QkFBNkI7QUFDdEUscUNBQXFDLHNDQUFzQztBQUMzRTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLElBQUk7QUFDZixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCO0FBQ0EsWUFBWSxRQUFRO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQ0FBbUMsYUFBYTtBQUNoRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsYUFBYTtBQUNwRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGFBQWE7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixZQUFZO0FBQ2hDO0FBQ0EsNENBQTRDLFVBQVU7QUFDdEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0I7QUFDcEIsb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQSxhQUFhLHVCQUF1QjtBQUNwQyxxQkFBcUIsdUNBQXVDO0FBQzVELGlCQUFpQiw0Q0FBNEM7QUFDN0QseUJBQXlCLDREQUE0RDtBQUNyRixlQUFlLDRDQUE0QztBQUMzRCx1QkFBdUI7QUFDdkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0EsV0FBVyxZQUFZO0FBQ3ZCLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0EsV0FBVyxNQUFNO0FBQ2pCLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLFNBQVM7QUFDM0I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLHdDQUF3Qzs7QUFFeEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCwrQ0FBK0M7O0FBRS9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pEOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsK0JBQStCO0FBQ3ZEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsZ0JBQWdCO0FBQzFDO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQSxjQUFjLG9CQUFvQjtBQUNsQztBQUNBO0FBQ0E7QUFDQSxjQUFjLG9CQUFvQjtBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esd0JBQXdCLGtDQUFrQztBQUMxRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsV0FBVztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWMsWUFBWTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FB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QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsU0FBUztBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsa0JBQWtCLHFCQUFxQjtBQUN2QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsa0JBQWtCLHNCQUFzQjtBQUN4Qzs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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Q0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQiw4QkFBOEI7QUFDbkQ7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0Q0FBNEMsZ0NBQWdDO0FBQzVFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsdUJBQXVCO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUMsa0NBQWtDLEVBQUU7O0FBRXpFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0JBQW9CLDRCQUE0QjtBQUNoRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixzQkFBc0I7QUFDeEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLHNCQUFzQjtBQUMzQyxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSzs7QUFFTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxRQUFRO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsUUFBUTtBQUMzQztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGtCQUFrQixnQkFBZ0I7QUFDbEM7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0JBQStCLFFBQVE7QUFDdkM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixnQkFBZ0I7QUFDbEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx1Q0FBdUMsUUFBUTtBQUMvQztBQUNBO0FBQ0E7QUFDQSwrQkFBK0IsUUFBUTtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esc0NBQXNDLFFBQVE7O0FBRTlDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0NBQXNDLFFBQVE7QUFDOUM7QUFDQSxzQ0FBc0MsUUFBUTtBQUM5QztBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQ0FBbUMsUUFBUTtBQUMzQztBQUNBLCtCQUErQixRQUFRO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsNkJBQTZCO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EscURBQXFEO0FBQ3JELFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLFFBQVE7QUFDaEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQSxDQUFDLEVBQUUsa1NBQWtTO0FBQ3JTO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnQkFBZ0I7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGlCQUFpQjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDJCQUEyQjtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvQ0FBb0MsZUFBZSxHQUFHLHVCQUF1QjtBQUM3RTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSw4T0FBOE87QUFDalA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxDQUFDO0FBQ0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsb0RBQW9EO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGtCQUFrQixxQkFBcUI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMENBQTBDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxzRUFBc0U7QUFDekU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNB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O0FBRUE7QUFDQSxpQkFBaUI7QUFDakIsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsd0lBQXdJO0FBQzNJO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0EsQ0FBQzs7QUFFRCxDQUFDLEVBQUUseUVBQXlFO0FBQzVFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsbUJBQW1CO0FBQ3JDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxrREFBa0Q7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQjtBQUNsQjs7QUFFQSxrQkFBa0IsT0FBTztBQUN6QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSwrR0FBK0c7QUFDbEg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLDhCQUE4QjtBQUM1Qzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsbUJBQW1CLDRCQUE0QjtBQUMvQyxxQkFBcUIsaUNBQWlDO0FBQ3RELG9CQUFvQjtBQUNwQixTQUFTO0FBQ1Q7QUFDQSxrQkFBa0IsNEJBQTRCO0FBQzlDLHFCQUFxQixpQ0FBaUM7QUFDdEQscUJBQXFCO0FBQ3JCO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSxjQUFjLHdCQUF3QjtBQUN0QztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBLENBQUMsRUFBRSxrR0FBa0c7QUFDckc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSx1SEFBdUg7QUFDMUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDREQUE0RDtBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0IscUJBQXFCO0FBQ3ZDOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDhDQUE4Qyx5QkFBeUI7QUFDdkU7QUFDQTs7QUFFQTtBQUNBLCtDQUErQyx5QkFBeUI7QUFDeEU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSwrSUFBK0k7QUFDbEo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQix1QkFBdUI7QUFDekMsc0JBQXNCLDBCQUEwQjtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSwrREFBK0QsK0JBQStCO0FBQzlGO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBLGdEQUFnRCxtQkFBbUI7QUFDbkU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTs7QUFFQTtBQUNBLGFBQWE7QUFDYixLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsT0FBTztBQUNqRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0Esa0JBQWtCLHNCQUFzQjtBQUN4QztBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0Isc0JBQXNCO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGFBQWE7QUFDYixTQUFTOztBQUVUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUEsQ0FBQyxFQUFFLDhTQUE4UztBQUNqVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4Qzs7QUFFOUM7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQSxpQkFBaUIsK0JBQStCO0FBQ2hELGNBQWMscUJBQXFCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsc0JBQXNCLGVBQWU7QUFDckM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7O0FBRXJCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsa0JBQWtCLG1CQUFtQjtBQUNyQztBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxrQkFBa0IsbUJBQW1CO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFDQUFxQztBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IscUJBQXFCO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDBCQUEwQixxQkFBcUI7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixxQkFBcUI7QUFDM0M7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixxQkFBcUI7QUFDM0MsbUNBQW1DO0FBQ25DOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0Isa0JBQWtCO0FBQ3BDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNCQUFzQix1QkFBdUI7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLGlCQUFpQjtBQUNuQztBQUNBLHNCQUFzQix3QkFBd0I7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUscUNBQXFDO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsK0RBQStEO0FBQ2xFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVCwwQkFBMEIsbUJBQW1CO0FBQzdDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseUNBQXlDLE9BQU8sV0FBVztBQUMzRCx1Q0FBdUMsWUFBWTtBQUNuRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxtQ0FBbUMsaUJBQWlCOztBQUVwRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtB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Q0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7O0FBRUEsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLCtGQUErRjtBQUNsRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7O0FBR0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSxrQkFBa0IseUJBQXlCO0FBQzNDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxrSkFBa0o7QUFDcko7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTOztBQUVUO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsaUJBQWlCO0FBQ25DOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHNQQUFzUDtBQUN6UDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLFNBQVM7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxpREFBaUQ7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHVCQUF1Qiw2Q0FBNkM7O0FBRXBFLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsYUFBYSxpREFBaUQscUJBQXFCO0FBQ25GLGFBQWEsaURBQWlEO0FBQzlEO0FBQ0E7QUFDQSx1QkFBdUIsbUJBQW1COztBQUUxQyxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBLENBQUMsRUFBRSwwQkFBMEI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLGlCQUFpQjtBQUNuQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsNkZBQTZGO0FBQ2hHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLHNCQUFzQixtQkFBbUI7QUFDekM7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxzSUFBc0k7QUFDekk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLDRCQUE0QjtBQUM5QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7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QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFF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QyxFQUFFLHVIQUF1SDtBQUMxSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSxpQkFBaUI7QUFDOUIsYUFBYSxpQkFBaUI7QUFDOUIsYUFBYTtBQUNiOztBQUVBLEtBQUs7QUFDTDtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxLQUFLO0FBQ0wsaUNBQWlDLHNCQUFzQjs7QUFFdkQsS0FBSyxHQUFHLElBQUksVUFBVTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7OztBQUdBLFNBQVM7O0FBRVQ7QUFDQTs7O0FBR0EsU0FBUzs7QUFFVDtBQUNBOzs7QUFHQSxTQUFTOztBQUVUOztBQUVBLFNBQVM7QUFDVCxLQUFLOztBQUVMOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0EsQ0FBQzs7QUFFRCxDQUFDLEVBQUUsc05BQXNOO0FBQ3pOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7O0FBR0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0Esa0JBQWtCLGtCQUFrQjtBQUNwQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDRCQUE0Qjs7QUFFNUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnR0FBZ0c7QUFDbkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQix1QkFBdUI7QUFDekM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLHFCQUFxQjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDBDQUEwQyxlQUFlOztBQUV6RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw0RkFBNEY7QUFDNUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQ7QUFDbkQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsdUNBQXVDO0FBQ3ZDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHVDQUF1QyxtQkFBbUI7O0FBRTFEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNULEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUJBQW1CLCtEQUErRDtBQUNsRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsWUFBWTtBQUM5QjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCLDJCQUEyQjtBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFNQUFxTTtBQUN4TTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtRUFBbUU7QUFDdEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFlBQVk7QUFDdkIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixPQUFPO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsT0FBTztBQUMzQjtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsT0FBTztBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsaUJBQWlCO0FBQ2hDO0FBQ0E7QUFDQSxhQUFhLFVBQVU7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSw0Q0FBNEMsT0FBTztBQUNuRDtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsNkxBQTZMO0FBQ2hNO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsZUFBZTtBQUM1QixhQUFhLGVBQWU7QUFDNUIsYUFBYTtBQUNiOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7OztBQUdBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSzs7QUFFTCw4QkFBOEIsc0JBQXNCOztBQUVwRCxLQUFLOztBQUVMOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRCxDQUFDLEVBQUUsdUxBQXVMO0FBQzFMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7O0FBR0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLHNCQUFzQixjQUFjOztBQUVwQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnR0FBZ0c7QUFDbkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0Esa0JBQWtCLHFCQUFxQjtBQUN2QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsNkNBQTZDLDREQUE0RDtBQUN6RyxTQUFTOztBQUVUO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixZQUFZO0FBQzlCO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxrQkFBa0IsWUFBWTtBQUM5QjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixzQkFBc0I7QUFDakQsMkJBQTJCLHFCQUFxQjtBQUNoRCw0QkFBNEIsb0JBQW9CO0FBQ2hELDRCQUE0Qix1QkFBdUI7QUFDbkQsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsdU5BQXVOO0FBQzFOO0FBQ0EsQ0FBQyxFQUFFLDZFQUE2RTtBQUNoRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUJBQXlCO0FBQ3pCLDJCQUEyQjtBQUMzQiwyQkFBMkI7QUFDM0IscUJBQXFCO0FBQ3JCLHFCQUFxQjs7QUFFckI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEI7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSx5REFBeUQ7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLE1BQU07QUFDdkI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyx3QkFBd0I7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsc3FCQUFzcUI7QUFDenFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxxREFBcUQ7O0FBRXJEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsdUdBQXVHLGVBQWUsU0FBUyxlQUFlLFNBQVMsWUFBWTtBQUNuSztBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FB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QTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTLFdBQVcsZUFBZSxFQUFFOztBQUVyQzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUwsbUNBQW1DO0FBQ25DO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSyxFQUFFO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQzs7QUFFbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixpQkFBaUI7QUFDbkM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHlHQUF5RztBQUM1RztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxzQkFBc0I7QUFDakM7QUFDQSxhQUFhLGVBQWU7QUFDNUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJDQUEyQyxvQkFBb0I7QUFDL0QsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUseUJBQXlCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCLHlCQUF5QjtBQUMzQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxDQUFDLEVBQUUsYUFBYTtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxtQkFBbUI7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsNENBQTRDO0FBQzVDO0FBQ0E7O0FBRUEsa0JBQWtCLFlBQVk7QUFDOUI7O0FBRUE7QUFD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QUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsWUFBWTtBQUNaOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0JBQXNCLHlCQUF5QjtBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZUFBZTtBQUMxQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixPQUFPLE9BQU87QUFDZCxPQUFPLE9BQU87QUFDZCxPQUFPLE9BQU87QUFDZCxZQUFZO0FBQ1o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsWUFBWTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQSxzQkFBc0IsU0FBUztBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSw4SUFBOEk7QUFDako7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsa0JBQWtCOztBQUVsQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QixjQUFjO0FBQ3ZDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6Qjs7QUFFQSxDQUFDLEVBQUUsaUJBQWlCO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsdUNBQXVDLFVBQVU7O0FBRWpELENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtB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QTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHVDQUF1Qzs7QUFFdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0IsaUJBQWlCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQkFBc0IsaUJBQWlCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsaUJBQWlCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLGtCQUFrQixrQkFBa0I7QUFDcEM7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCLGlDQUFpQzs7QUFFbkQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isb0NBQW9DO0FBQzVEO0FBQ0Esd0JBQXdCLGlCQUFpQjtBQUN6QztBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCOztBQUVBO0FBQ0Esa0RBQWtELE9BQU87QUFDekQ7QUFDQSxrQ0FBa0MsU0FBUyxRQUFRLGFBQWE7QUFDaEU7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDBCQUEwQiwwQ0FBMEM7O0FBRXBFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLG9CQUFvQjtBQUNsQztBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYyxvQkFBb0I7QUFDbEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxtQkFBbUI7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxzQkFBc0I7QUFDakMsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsU0FBUztBQUNwQixXQUFXLGVBQWU7QUFDMUIsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNB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QUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxpQkFBaUIsRUFBRTtBQUN6RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsK0RBQStELFNBQVM7QUFDeEU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtB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QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLDBCQUEwQixzQkFBc0I7QUFDaEQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkRBQTJEO0FBQzNELGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBLHNCQUFzQiww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QUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxFQUFFLHloQkFBeWhCO0FBQzVoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQSxnQkFBZ0I7O0FBRWhCLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQSxXQUFX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O0FBQ0E7O0FBRUE7QUFDQSxjQUFjLG1CQUFtQjtBQUNqQzs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0EsY0FBYywwQkFBMEI7QUFDeEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLG1CQUFtQjtBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFD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Q0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixtQkFBbUI7QUFDckM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLGlCQUFpQjtBQUNuQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1EQUFtRDs7QUFFbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCLHFCQUFxQjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsaUJBQWlCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25COztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0Isd0JBQXdCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsV0FBVyxpQkFBaUI7QUFDNUI7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLHFDQUFxQztBQUN4RDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDLE9BQU87QUFDekMsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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Q0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsSUFBSTtBQUNmO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxJQUFJO0FBQ2Y7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsSUFBSTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxxRUFBcUU7QUFDeEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVB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O0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsNkJBQTZCO0FBQ25EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxzSUFBc0k7QUFDekk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxRQUFRLFdBQVc7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQixXQUFXO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLHFCQUFxQjtBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixtQkFBbUI7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwyREFBMkQsZUFBZTtBQUMxRTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDhjQUE4YztBQUNqZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLHNEQUFzRDtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUM7QUFDekM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxrSUFBa0k7QUFDckk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxTQUFTO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0Isa0JBQWtCO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFDQUFxQztBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLGtCQUFrQjtBQUNoQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsa0JBQWtCO0FBQ2hDO0FBQ0E7QUFDQSxxREFBcUQ7QUFDckQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsa0JBQWtCO0FBQ2hDO0FBQ0E7QUFDQSxxREFBcUQ7QUFDckQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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O0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixhQUFhLEVBQUU7QUFDN0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0IscUJBQXFCO0FBQzNDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsOEJBQThCO0FBQzdFOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxDQUFDLEVBQUUsNFNBQTRTO0FBQy9TO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsdUJBQXVCLDZDQUE2Qzs7QUFFcEUsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsYUFBYSxvREFBb0Qsb0JBQW9CLGFBQWE7QUFDbEcsYUFBYSxvREFBb0Qsb0JBQW9CO0FBQ3JGO0FBQ0E7QUFDQSx1QkFBdUIsbUJBQW1CO0FBQzFDOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx1QkFBdUIsbUNBQW1DOztBQUUxRCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQSx1QkFBdUIsbUJBQW1COztBQUUxQyxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBLHVCQUF1QixtQkFBbUI7O0FBRTFDLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0wsNEJBQTRCLFNBQVMsK0JBQStCO0FBQ3BFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixrQ0FBa0M7QUFDbkQsaUJBQWlCO0FBQ2pCO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsYUFBYSxvREFBb0Q7QUFDakUsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVB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QUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQix5QkFBeUI7QUFDbkQ7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHNDQUFzQywwQkFBMEI7QUFDaEU7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjs7QUFFQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQix5QkFBeUI7QUFDbkQ7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQix5QkFBeUI7QUFDL0M7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsc0JBQXNCLHlCQUF5QjtBQUMvQztBQUNBOztBQUVBO0FBQ0Esa0NBQWtDLGdDQUFnQztBQUNsRTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCOztBQUVBLHlCQUF5QjtBQUN6Qjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE1BQU07QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsaUJBQWlCO0FBQ25DO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsTUFBTTtBQUNyQixlQUFlLEVBQUU7QUFDakIsZUFBZSxPQUFPO0FBQ3RCLGVBQWUsT0FBTztBQUN0QjtBQUNBLGdCQUFnQixRQUFRO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixvQkFBb0I7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYyx3QkFBd0I7QUFDdEM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLHFCQUFxQjtBQUNuQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYyx5QkFBeUI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLHlCQUF5QjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsdUNBQXVDO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYyx5QkFBeUI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyx5QkFBeUI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsMEJBQTBCLHdCQUF3QjtBQUNsRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBLDBCQUEwQixrQ0FBa0M7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLDBCQUEwQixrQ0FBa0M7QUFDNUQ7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsaUhBQWlIO0FBQ3BIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxQkFBcUI7O0FBRXJCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLHdCQUF3QjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLHdCQUF3QjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsc0JBQXNCLHdCQUF3QjtBQUM5QztBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBLG9DQUFvQyxxQkFBcUIsRUFBRTtBQUMzRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0Msa0JBQWtCO0FBQ3hELHNDQUFzQyxrQkFBa0I7O0FBRXhEO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMEJBQTBCLDRCQUE0QjtBQUN0RDs7QUFFQTtBQUNBO0FBQ0EsMEJBQTBCLDRCQUE0QjtBQUN0RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlEQUFpRCwwQkFBMEIsRUFBRTtBQUM3RTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrQkFBK0IsNEJBQTRCOztBQUUzRCxrQkFBa0Isb0JBQW9CO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFD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O0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLENBQUMsRUFBRSwwR0FBMEc7QUFDN0c7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0Isc0JBQXNCO0FBQ3hDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsc0VBQXNFO0FBQ3pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRTtBQUN0RTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtRUFBbUU7QUFDbkUsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLE9BQU87QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLGlDQUFpQztBQUNoRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsNENBQTRDLE9BQU87QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxPQUFPO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxRQUFRO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsT0FBTztBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQywyQkFBMkI7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNCQUFzQjtBQUN0QixvQkFBb0I7O0FBRXBCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLDBCQUEwQiw2QkFBNkI7O0FBRXZEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLOztBQUVMO0FBQ0EsaUNBQWlDLGtCQUFrQjtBQUNuRDs7QUFFQTtBQUNBLGtCQUFrQixhQUFhO0FBQy9COztBQUVBO0FBQ0EsaUNBQWlDLGdCQUFnQjtBQUNqRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBLENBQUMsRUFBRSxvSEFBb0g7QUFDdkg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGNBQWMsT0FBTztBQUNyQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0IsUUFBUTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtRUFBbUU7QUFDbkU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBLHVEQUF1RDs7QUFFdkQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxFQUFFLHFEQUFxRDtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsdUJBQXVCO0FBQ3pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsa0JBQWtCLHlCQUF5QjtBQUMzQztBQUNBOztBQUVBLG1DQUFtQztBQUNuQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLHVCQUF1QjtBQUN6QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsdUJBQXVCO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSw4UEFBOFA7QUFDalE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztB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QjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsa0JBQWtCLHlCQUF5QjtBQUMzQzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLHFCQUFxQjtBQUN2QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLHVCQUF1QjtBQUN6QztBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsc1BBQXNQO0FBQ3pQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSx3QkFBd0I7QUFDeEI7QUFDQSxhQUFhLGlEQUFpRCxxQkFBcUI7QUFDbkYsYUFBYSxpREFBaUQ7QUFDOUQ7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUIsU0FBUywyQkFBMkI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQsQ0FBQyxFQUFFLHFJQUFxSTtBQUN4STtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixzQkFBc0I7QUFDeEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0Esd0NBQXdDOztBQUV4Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSwwS0FBMEs7QUFDN0s7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLE9BQU87QUFDekI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDLEVBQUUsbURBQW1EO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHFGQUFxRjtBQUNyRjs7QUFFQSx5QkFBeUI7O0FBRXpCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRDtBQUN0RDtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUssc0JBQXNCLGVBQWU7O0FBRTFDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLFNBQVM7QUFDVDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FB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QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNULGtDQUFrQyx3QkFBd0I7O0FBRTFELFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FB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Q0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLHNCQUFzQixzQkFBc0I7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQjtBQUN0Qjs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSw0REFBNEQ7QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsQ0FBQztBQUNEOztBQUVBO0FBQ0E7O0FBRUEseUJBQXlCLGVBQWU7O0FBRXhDO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7O0FBR0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxTQUFTOztBQUVUO0FBQ0E7OztBQUdBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOzs7QUFHQSxTQUFTOztBQUVUO0FBQ0E7OztBQUdBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLFNBQVM7O0FBRVQ7QUFDQTs7O0FBR0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7OztBQUdBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7OztBQUdBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxhQUFhO0FBQ2I7QUFDQTs7O0FBR0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7OztBQUdBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7OztBQUdBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7O0FBR0EsYUFBYTtBQUNiO0FBQ0EsMkNBQTJDLGlCQUFpQixpQkFBaUI7QUFDN0U7QUFDQSxLQUFLO0FBQ0wsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsQ0FBQyxFQUFFLGtOQUFrTjtBQUNyTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsc0dBQXNHO0FBQ3pHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7OztBQUdMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUOztBQUVBLGtCQUFrQixxQkFBcUI7QUFDdkM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGNBQWMscUJBQXFCO0FBQ25DO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsY0FBYyxtQkFBbUI7QUFDakM7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixpQkFBaUI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0EsY0FBYywyQkFBMkI7QUFDekM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGdCQUFnQjtBQUM5Qjs7QUFFQSxrQkFBa0IscUJBQXFCO0FBQ3ZDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsMEJBQTBCO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQiwwQkFBMEI7QUFDcEQ7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdURBQXVELFdBQVc7O0FBRWxFLHFDQUFxQyx1QkFBdUI7QUFDNUQscUNBQXFDLHVCQUF1Qjs7QUFFNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMERBQTBEO0FBQzFEO0FBQ0E7QUFDQTtB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QUFFQSxrQkFBa0Isd0JBQXdCO0FBQzFDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGNBQWMsZ0JBQWdCO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQix3QkFBd0I7QUFDMUM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLG1CQUFtQjtBQUNqQztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLG1CQUFtQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQkFBa0I7O0FBRWxCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNCQUFzQix1QkFBdUI7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QUFDVCw0Q0FBNEM7QUFDNUM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0Isc0JBQXNCO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFF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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixrREFBa0Q7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4RkFBOEYsb0dBQW9HO0FBQ2xNO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUIsR0FBRztBQUN4QixpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGtGQUFrRjtBQUNsRjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixFQUFFO0FBQ25CO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1RkFBdUY7QUFDdkYsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUM7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNB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O0FBRUE7QUFDQTs7QUFFQTtBQUNBLG9DQUFvQyw4QkFBOEI7QUFDbEU7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSw2QkFBNkIsZUFBZTtBQUM1Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHFCQUFxQiw0QkFBNEIsRUFBRTtBQUNuRCxvQkFBb0IsYUFBYTs7QUFFakM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxvQkFBb0I7QUFDcEIsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkIsb0JBQW9COztBQUUvQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG9CQUFvQjs7QUFFcEI7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxvQkFBb0I7O0FBRXBCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSwwQkFBMEIsNEJBQTRCO0FBQ3REO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSwwaUJBQTBpQjtBQUM3aUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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eEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBLDJFQUEyRTtBQUMzRTtBQUNBLFNBQVMsbUJBQW1COztBQUU1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDhSQUE4UjtBQUNqUztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQiw0QkFBNEI7QUFDOUM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0Esb0NBQW9DLHdCQUF3QixFQUFFO0FBQzlEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsU0FBUzs7QUFFVDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxhQUFhOztBQUUzRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQztBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMkNBQTJDO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSwwREFBMEQsaUJBQWlCO0FBQzNFOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7O0FBRUEsNkJBQTZCLDBCQUEwQjtBQUN2RCw2QkFBNkIsMkRBQTJEO0FBQ3hGLDZCQUE2Qix1REFBdUQ7O0FBRXBGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7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eUJBQXlCO0FBQzNDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0M7QUFDbEM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsNkJBQTZCO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtB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O0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxzREFBc0Q7QUFDekQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxnQ0FBZ0MsaUNBQWlDO0FBQ2pFLGdDQUFnQyxpQ0FBaUM7O0FBRWpFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxzQkFBc0IsOEJBQThCO0FBQ3BEO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDRHQUE0RztBQUMvRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSw2UUFBNlE7QUFDaFI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0IscUJBQXFCO0FBQ3ZDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHFDQUFxQyx1QkFBdUI7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnR0FBZ0c7QUFDbkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQ0FBa0MsbUNBQW1DOztBQUVyRTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsZ0NBQWdDLFFBQVEsdUJBQXVCO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDBIQUEwSDtBQUM3SDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7OztBQUdBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLCtOQUErTjtBQUNsTztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw0Q0FBNEM7QUFDNUM7O0FBRUEsa0JBQWtCLHFCQUFxQjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSwwQ0FBMEM7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSw2R0FBNkc7QUFDaEg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMLHVCQUF1Qjs7QUFFdkIsS0FBSztBQUNMLDRCQUE0Qjs7QUFFNUIsS0FBSztBQUNMOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1QsNkJBQTZCO0FBQzdCLGFBQWEsaUNBQWlDO0FBQzlDLDhCQUE4QjtBQUM5QixhQUFhLDJDQUEyQztBQUN4RCwyQkFBMkI7QUFDM0IsYUFBYSxpQ0FBaUM7QUFDOUMsNEJBQTRCO0FBQzVCLGFBQWEsa0NBQWtDO0FBQy9DO0FBQ0EsZ0NBQWdDO0FBQ2hDLGlCQUFpQjtBQUNqQjtBQUNBLGdDQUFnQztBQUNoQyxpQkFBaUI7QUFDakI7QUFDQTtBQUNBOztBQUVBOztBQUVBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHVLQUF1SztBQUMxSztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLG1CQUFtQjtBQUNqQztBQUNBOztBQUVBO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLHlDQUF5Qzs7QUFFL0Q7QUFDQSxjQUFjLFVBQVU7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx1REFBdUQsYUFBYSxFQUFFOztBQUV0RTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxvREFBb0QsYUFBYTtBQUNqRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsaUJBQWlCLElBQUksYUFBYTtBQUNsQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwrQkFBK0IsY0FBYyxFQUFFO0FBQy9DOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsU0FBUztBQUMzQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLFNBQVM7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNCQUFzQixlQUFlO0FBQ3JDO0FBQ0E7O0FBRUEsMEJBQTBCLGdCQUFnQjtBQUMxQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDBCQUEwQixrQkFBa0I7O0FBRTVDLHdCQUF3QixZQUFZOztBQUVwQyxDQUFDLEVBQUUsc0VBQXNFO0FBQ3pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IseUJBQXlCO0FBQzNDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0JBQXNCLHFCQUFxQjtBQUMzQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxvQkFBb0I7QUFDbEM7QUFDQSxrQkFBa0Isc0JBQXNCO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYyxvQkFBb0I7QUFDbEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFGQUFxRjtBQUNyRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQixzQkFBc0I7QUFDeEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLDBCQUEwQjtBQUNsRCx1QkFBdUIsMEJBQTBCO0FBQ2pELFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxzRkFBc0Y7QUFDekY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLDhDQUE4QztBQUM5QztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLHFEQUFxRCxjQUFjO0FBQ25FOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixxQkFBcUI7QUFDdkM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDJHQUEyRztBQUM5RztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDLCtCQUErQjs7QUFFaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0IsOEJBQThCO0FBQ3BEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnQ0FBZ0M7O0FBRWhDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLGtCQUFrQjtBQUNwQzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQzs7QUFFMUM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLGVBQWU7QUFDakM7O0FBRUEsc0JBQXNCLDJCQUEyQjtBQUNqRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxtQ0FBbUM7QUFDbkM7QUFDQTtBQUNBLGtDQUFrQztBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsd0dBQXdHO0FBQzNHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtT0FBbU87QUFDdE87QUFD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QUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBLENBQUMsRUFBRSxrR0FBa0c7QUFDckc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxtQkFBbUIsd0JBQXdCO0FBQzNDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsZ0JBQWdCO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsaUNBQWlDO0FBQzlDLGFBQWE7QUFDYjs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQSxDQUFDLEVBQUUsbUxBQW1MO0FBQ3RMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx3REFBd0Q7QUFDeEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMlRBQTJUO0FBQzlUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw2REFBNkQsYUFBYTtBQUMxRSw2REFBNkQsYUFBYTs7QUFFMUU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLG9SQUFvUjtBQUN2UjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCLFdBQVc7QUFDekM7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLGdDQUFnQzs7QUFFbkQ7QUFDQSw4QkFBOEIsV0FBVztBQUN6QztBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsZ0NBQWdDOztBQUVuRDtBQUNBLGlDQUFpQyxRQUFRO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixnQ0FBZ0M7O0FBRW5EO0FBQ0EsaUNBQWlDLFFBQVE7QUFDekM7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLGdDQUFnQzs7QUFFbkQ7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixRQUFRO0FBQzlCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCLFFBQVE7QUFDOUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0JBQXNCLFNBQVM7QUFDL0I7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0JBQXNCLFNBQVM7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLGNBQWM7O0FBRTdDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUIsUUFBUTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBLG1CQUFtQixRQUFRO0FBQzNCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxzQkFBc0IseUJBQXlCO0FBQy9DOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLGNBQWM7O0FBRTdDO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG1CQUFtQixTQUFTO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQSx1QkFBdUIsWUFBWTtBQUNuQzs7QUFFQSxzQkFBc0IseUJBQXlCO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHdEQUF3RDtBQUMzRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxjQUFjLHNCQUFzQjtBQUNwQzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSx3REFBd0Q7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCO0FBQ0E7QUFDQSxrQkFBa0IsUUFBUTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsa0JBQWtCLFFBQVE7QUFDMUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGdCQUFnQjtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0RBQWtEO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGVBQWUsVUFBVTtBQUN6QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixRQUFRO0FBQzlCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMEJBQTBCLFFBQVE7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsUUFBUTtBQUNsQztBQUNBLDhCQUE4QixZQUFZO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFVBQVU7QUFDN0IsdUJBQXVCLGNBQWM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixVQUFVO0FBQzdCO0FBQ0EsdUJBQXVCLGNBQWM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxvQ0FBb0M7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0IsbUJBQW1CO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsbUJBQW1CO0FBQ3pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLG1CQUFtQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLG1CQUFtQjtBQUN6QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixtQkFBbUI7QUFDekM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLG1CQUFtQjtBQUN6Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixtQkFBbUI7QUFDekM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLG1CQUFtQjtBQUN6QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0IsbUJBQW1CO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixtQkFBbUI7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixtQkFBbUI7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLG1CQUFtQjtBQUN6QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtSEFBbUg7QUFDdEg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSwwRkFBMEY7QUFDN0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLE9BQU87QUFDekI7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGVBQWU7QUFDN0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWMsaUJBQWlCO0FBQy9CO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsZ0JBQWdCO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLHFCQUFxQjtBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGlMQUFpTDtBQUNwTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsb0xBQW9MO0FBQ3ZMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGtCQUFrQixRQUFRO0FBQzFCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixPQUFPO0FBQ3pCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FB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O0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixzQkFBc0I7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0Isc0JBQXNCO0FBQ3hDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLFFBQVE7QUFDN0M7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtREFBbUQ7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtB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Q0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkJBQTJCLHNCQUFzQjs7QUFFakQsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQixzQkFBc0I7O0FBRWpELFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQixzQkFBc0I7O0FBRWpELFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBLHVCQUF1QjtBQUN2QixLQUFLOztBQUVMO0FBQ0EsNEJBQTRCO0FBQzVCOztBQUVBLFNBQVM7QUFDVCw0QkFBNEI7QUFDNUI7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxnQ0FBZ0M7O0FBRWhDLFNBQVM7QUFDVDtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBLENBQUMsRUFBRSxzUUFBc1E7QUFDelE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxnQ0FBZ0MsMEJBQTBCOztBQUUxRDtBQUNBOztBQUVBLENBQUMsRUFBRSwrRkFBK0Y7QUFDbEc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGNBQWMsUUFBUTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWMsWUFBWTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdDQUF3QyxpQkFBaUI7O0FBRXpEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMEVBQTBFO0FBQzdFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLHNCQUFzQixxREFBcUQ7O0FBRTNFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMEdBQTBHO0FBQzdHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxpREFBaUQ7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQSxDQUFDLEVBQUUsdUZBQXVGO0FBQzFGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxnREFBZ0Q7QUFDaEQ7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxrRUFBa0U7QUFDckU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QixLQUFLOztBQUVMO0FBQ0EsNEJBQTRCOztBQUU1QixTQUFTO0FBQ1Q7QUFDQTtBQUNBLGdDQUFnQzs7QUFFaEMsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUEsQ0FBQyxFQUFFLDBKQUEwSjtBQUM3SjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdDQUF3Qzs7QUFFeEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQsUUFBUTtBQUN6RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsOEJBQThCLGVBQWU7QUFDN0M7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7O0FBRVQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsaUNBQWlDO0FBQ25EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLHlCQUF5QjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQSxDQUFDLEVBQUUscVpBQXFaO0FBQ3haO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUEsNEJBQTRCO0FBQzVCO0FBQ0EsS0FBSztBQUNMO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQSxDQUFDLEVBQUUsdUxBQXVMO0FBQzFMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixTQUFTO0FBQzNCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsNEdBQTRHO0FBQy9HO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixtQkFBbUI7QUFDcEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYyxzQkFBc0I7QUFDcEM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyQkFBMkIsbUNBQW1DO0FBQzlEO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxnQkFBZ0I7QUFDOUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLGFBQWEsZ0NBQWdDO0FBQzdDOztBQUVBO0FBQ0EsS0FBSzs7QUFFTCxvQkFBb0I7QUFDcEI7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsa0tBQWtLO0FBQ3JLO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwyREFBMkQseUJBQXlCO0FBQ3BGOztBQUVBLENBQUMsRUFBRSw4RUFBOEU7QUFDakY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSwrRUFBK0U7QUFDbEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxzQkFBc0Isc0JBQXNCO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtSkFBbUo7QUFDdEo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLHNCQUFzQjtBQUN4QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixzQkFBc0I7QUFDeEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUMsUUFBUTtBQUM3QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtREFBbUQ7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGtCQUFrQixlQUFlOztBQUVqQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnQkFBZ0I7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQSxLQUFLOztBQUVMLDRCQUE0QjtBQUM1QjtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0EsK0JBQStCLDBCQUEwQixhQUFhO0FBQ3RFLG1DQUFtQyw4QkFBOEIsZUFBZTtBQUNoRiw0QkFBNEIsdUJBQXVCLFFBQVE7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw4QkFBOEI7O0FBRTlCLEtBQUs7O0FBRUwseUJBQXlCLG9CQUFvQixlQUFlO0FBQzVELHdCQUF3QixtQkFBbUIsZUFBZTs7QUFFMUQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBLGdDQUFnQyxvQkFBb0Isd0JBQXdCO0FBQzVFLGdDQUFnQztBQUNoQztBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSwyTUFBMk07QUFDOU07QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLGVBQWU7QUFDN0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsZUFBZTtBQUM3QjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDZIQUE2SDtBQUNoSTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLHFCQUFxQjtBQUNuQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsY0FBYyxvQkFBb0I7QUFDbEM7O0FBRUEsc0JBQXNCLGVBQWU7QUFDckM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsOEJBQThCO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQkFBc0IscUJBQXFCO0FBQzNDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLG9IQUFvSDtBQUN2SDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0MsNENBQTRDOztBQUVsRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsZ0VBQWdFO0FBQ25FO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHdPQUF3TztBQUMzTztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLHFCQUFxQjtBQUN2Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMENBQTBDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMEVBQTBFO0FBQzdFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLG9DQUFvQywyQkFBMkIsRUFBRTs7QUFFakU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUOztBQUVBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDJIQUEySDtBQUM5SDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDOztBQUVBLGFBQWE7QUFDYixnQ0FBZ0MsK0JBQStCLFFBQVE7QUFDdkU7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUEsNkJBQTZCOztBQUU3QixLQUFLOztBQUVMLDJCQUEyQjtBQUMzQjtBQUNBLEtBQUs7O0FBRUwsNEJBQTRCO0FBQzVCO0FBQ0EsS0FBSzs7QUFFTCx3Q0FBd0M7QUFDeEM7QUFDQSxLQUFLOztBQUVMLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSzs7QUFFTCx5QkFBeUIsa0RBQWtEOztBQUUzRTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUseUpBQXlKO0FBQzVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGdEQUFnRDtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxnQ0FBZ0MscUJBQXFCO0FBQ3JEOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtQkFBbUI7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGtGQUFrRjtBQUNyRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHlLQUF5SztBQUM1SztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnQ0FBZ0M7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDBDQUEwQztBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw0QkFBNEIsd0JBQXdCOztBQUVwRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7O0FBRXJCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjs7QUFFckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7O0FBRWI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLDRCQUE0QjtBQUM1Qjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMEJBQTBCLFFBQVE7QUFDbEM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsc0JBQXNCO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxzQkFBc0I7QUFDcEM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxzQkFBc0I7QUFDcEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWM7QUFDZCwwQkFBMEIsUUFBUTtBQUNsQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGtKQUFrSjtBQUNySjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhCQUE4Qix1QkFBdUI7O0FBRXJEO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMOztBQUVBLENBQUMsRUFBRSxpQ0FBaUM7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMLG9CQUFvQixtQkFBbUIsZUFBZSxnQkFBZ0I7QUFDdEUscUJBQXFCLG9CQUFvQixlQUFlLGlCQUFpQjtBQUN6RSxxQkFBcUIsb0JBQW9CLGVBQWUsaUJBQWlCO0FBQ3pFLG9CQUFvQixtQkFBbUIsZUFBZSxnQkFBZ0I7QUFDdEUscUJBQXFCLG9CQUFvQixlQUFlLGlCQUFpQjtBQUN6RSxxQkFBcUIsb0JBQW9CLGVBQWUsaUJBQWlCOztBQUV6RTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0EsQ0FBQztBQUNEO0FBQ0EsQ0FBQztBQUNELHlCQUF5QixtQ0FBbUM7QUFDNUQ7O0FBRUEsQ0FBQyxFQUFFLCtLQUErSztBQUNsTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQixrQkFBa0I7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLGtCQUFrQjtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1DQUFtQyxzQkFBc0I7QUFDekQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDhQQUE4UDtBQUNqUTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLGlCQUFpQjtBQUNuQztBQUNBLG9DQUFvQyxvQkFBb0I7QUFDeEQsd0NBQXdDLDJCQUEyQjtBQUNuRSxLQUFLO0FBQ0w7QUFDQSx1Q0FBdUMsdUJBQXVCO0FBQzlELHdDQUF3QywyQkFBMkI7QUFDbkU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLDRCQUE0QjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxjQUFjLFlBQVk7QUFDMUI7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsWUFBWTtBQUM5Qjs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxxRUFBcUU7QUFDeEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWMsMEJBQTBCO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWMsWUFBWTtBQUMxQjtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCLDBCQUEwQjtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLDBCQUEwQjtBQUN4QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDBFQUEwRSw0QkFBNEI7QUFDdEc7O0FBRUE7QUFDQSwwRUFBMEUsNEJBQTRCO0FBQ3RHO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGdEQUFnRDtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLDJEQUEyRCx5QkFBeUI7QUFDcEY7O0FBRUEsQ0FBQyxFQUFFLDZIQUE2SDtBQUNoSTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWMsY0FBYztBQUM1QjtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsZUFBZTtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDBDQUEwQyxRQUFRO0FBQ2xEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHdDQUF3QyxvQkFBb0IsRUFBRTtBQUM5RDs7QUFFQSxDQUFDLEVBQUUsZ0JBQWdCO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCLGVBQWU7QUFDdEM7QUFDQTtBQUNBOztBQUVBO0FBQ0EsdUJBQXVCLGVBQWU7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUEsQ0FBQyxFQUFFLDZHQUE2RztBQUNoSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsOElBQThJO0FBQ2pKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7O0FBRUEsd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHdJQUF3STtBQUMzSTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUEsQ0FBQyxFQUFFLFNBQVM7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FB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Q0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLCtCQUErQjtBQUMzRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsaUJBQWlCO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsZUFBZTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLG1CQUFtQjtBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUJBQXlCLGtCQUFrQjtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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O0FBQ0EsMkRBQTJELHlCQUF5QjtBQUNwRjtBQUNBOztBQUVBLENBQUMsRUFBRSx5SUFBeUk7QUFDNUk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHlEQUF5RDtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBLENBQUMsRUFBRSwwUEFBMFA7QUFDN1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFDQUFxQztBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBLENBQUMsRUFBRSxpSUFBaUk7QUFDcEk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsNklBQTZJO0FBQ2hKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLCtOQUErTjtBQUNsTztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxhQUFhLG9DQUFvQztBQUNqRCxhQUFhO0FBQ2I7QUFDQTs7QUFFQTs7QUFFQSxzREFBc0Q7QUFDdEQ7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBLHlCQUF5QixpREFBaUQ7O0FBRTFFO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVCwyQkFBMkI7O0FBRTNCLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1QsMkJBQTJCOztBQUUzQixTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNULDJCQUEyQjs7QUFFM0IsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsU0FBUztBQUNULDBCQUEwQjtBQUMxQixvQkFBb0IsY0FBYzs7QUFFbEMsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGtDQUFrQztBQUNsQztBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQyxvQkFBb0IsZ0JBQWdCO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7O0FBRXBDLGlCQUFpQjtBQUNqQixvQ0FBb0M7QUFDcEM7O0FBRUEsaUJBQWlCO0FBQ2pCO0FBQ0EsYUFBYTtBQUNiLG9DQUFvQztBQUNwQzs7QUFFQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7OztBQUdBLGFBQWE7QUFDYjtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFTQUFxUztBQUN4UztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnREFBZ0Q7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsZ1RBQWdUO0FBQ25UO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFGQUFxRjtBQUN4RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrREFBa0Q7QUFDbEQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0VBQWdFO0FBQ2hFO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCO0FBQzlCO0FB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OztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBOzs7QUFHQSxLQUFLO0FBQ0w7QUFDQTs7O0FBR0EsS0FBSztBQUNMO0FBQ0E7OztBQUdBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNEJBQTRCO0FBQzVCLENBQUM7O0FBRUQ7QUFDQSw4QkFBOEI7O0FBRTlCO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGdOQUFnTjtBQUNuTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixTQUFTO0FBQzNCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQSxDQUFDLEVBQUUsdUNBQXVDO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLCtCQUErQixPQUFPO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLHVDQUF1QyxTQUFTO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNCQUFzQixjQUFjO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxzQkFBc0IsY0FBYztBQUNwQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCLHFCQUFxQjtBQUMzQztBQUNBOztBQUVBO0FBQ0EsMEJBQTBCLE9BQU87QUFDakM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLHFGQUFxRjs7QUFFckY7QUFDQSxzQkFBc0IsT0FBTztBQUM3QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNCQUFzQixPQUFPO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSwyQkFBMkI7QUFDM0I7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLDJFQUEyRTtBQUMzRTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0Isa0JBQWtCO0FBQ3hDO0FBQ0EsMEJBQTBCLFdBQVc7QUFDckMsOEJBQThCLFlBQVk7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixrQkFBa0I7QUFDeEM7QUFDQSwwQkFBMEIsV0FBVztBQUNyQyw4QkFBOEIsV0FBVztBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGtCQUFrQjtBQUN4QztBQUNBLDBCQUEwQixZQUFZO0FBQ3RDLDhCQUE4QixXQUFXO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNCQUFzQixXQUFXO0FBQ2pDLDBCQUEwQixZQUFZO0FBQ3RDLDhCQUE4QixXQUFXO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixrQkFBa0I7QUFDeEM7QUFDQSwwQkFBMEIsV0FBVztBQUNyQyw4QkFBOEIsWUFBWTtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixrQkFBa0I7QUFDeEM7QUFDQSwwQkFBMEIsV0FBVztBQUNyQyw4QkFBOEIsV0FBVztBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixrQkFBa0I7QUFDeEM7QUFDQSwwQkFBMEIsWUFBWTtBQUN0Qyw4QkFBOEIsV0FBVztBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxzQkFBc0IsT0FBTztBQUM3QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNCQUFzQixXQUFXO0FBQ2pDLDBCQUEwQixZQUFZO0FBQ3RDLDhCQUE4QixXQUFXO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMEJBQTBCLGtCQUFrQjtBQUM1QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwwQkFBMEIsd0JBQXdCO0FBQ2xEOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsNEJBQTRCO0FBQ2xFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyQkFBMkIsT0FBTztBQUNsQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDJKQUEySjtBQUM5SjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLFdBQVcsRUFBRTs7QUFFeEMsMkRBQTJELHlCQUF5Qjs7QUFFcEY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxvR0FBb0c7QUFDdkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSw0RkFBNEY7QUFDL0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7OztBQUdBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTCx1Q0FBdUMsaUJBQWlCOztBQUV4RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQSwyQkFBMkI7O0FBRTNCLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0Esd0JBQXdCLGdDQUFnQyxVQUFVO0FBQ2xFLHdCQUF3QixnQ0FBZ0MsVUFBVTtBQUNsRSx3QkFBd0IsZ0NBQWdDLFFBQVE7QUFDaEU7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBLEtBQUs7O0FBRUwsNEJBQTRCLHdCQUF3QixpQkFBaUI7QUFDckUsQ0FBQzs7QUFFRCxDQUFDLEVBQUUsaUxBQWlMO0FBQ3BMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBLENBQUMsRUFBRSx1Q0FBdUM7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsU0FBUztBQUMzQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixTQUFTO0FBQzNCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLFNBQVM7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsU0FBUztBQUMzQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsU0FBUztBQUMzQiw2REFBNkQ7QUFDN0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyQkFBMkIsT0FBTztBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxFQUFF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QTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLGtCQUFrQjtBQUNwQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSwwQ0FBMEM7O0FBRTFDO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsdUlBQXVJO0FBQzFJO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDRJQUE0STtBQUMvSTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxxQ0FBcUM7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDs7QUFFQSxDQUFDLEVBQUUseUJBQXlCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGtCQUFrQixlQUFlO0FBQ2pDO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsa0JBQWtCLGVBQWU7QUFDakM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7O0FBRUEsQ0FBQyxFQUFFLHFFQUFxRTtBQUN4RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLLGlCQUFpQjtBQUN0Qiw2QkFBNkIseUJBQXlCO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQSx5QkFBeUIsK0NBQStDOztBQUV4RSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSwrTUFBK007QUFDbE47QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHlDQUF5QztBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Es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Q0EsS0FBSzs7QUFFTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSw4TkFBOE47QUFDak87QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFGQUFxRjtBQUN4RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxXQUFXO0FBQ3RCO0FBQ0EsV0FBVyxZQUFZO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsV0FBVztBQUN0QjtBQUNBLFdBQVcsWUFBWTtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZUFBZSxzQkFBc0I7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTtBQUNBLG9CQUFvQixjQUFjO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxzQkFBc0I7QUFDakM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRSw4QkFBOEI7QUFDakc7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMFJBQTBSO0FBQzdSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnQkFBZ0I7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFGQUFxRjtBQUN4RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHlEQUF5RCw4Q0FBOEMsa01BQWtNLDhIQUE4SCxxREFBcUQsa0NBQWtDLDJCQUEyQix5QkFBeUIsNkRBQTZELHNDQUFzQyxvQ0FBb0MsZ0RBQWdELDhDQUE4QywrQkFBK0Isc0RBQXNELEdBQUcsOERBQThELCtFQUErRSwrRUFBK0UsNkNBQTZDLEdBQUcsNEJBQTRCLDZCQUE2QixHQUFHLGdEQUFnRCw2Q0FBNkMsR0FBRyw2Q0FBNkMsdUxBQXVMLEdBQUcsNkNBQTZDLHVMQUF1TCxHQUFHLDZEQUE2RCxrSkFBa0osR0FBRyw0REFBNEQsbUJBQW1CLGtCQUFrQixrQkFBa0Isa0JBQWtCLGtCQUFrQixzQkFBc0IsT0FBTyxPQUFPLHdCQUF3QixPQUFPLE9BQU8sNEJBQTRCLE9BQU8sT0FBTywrWkFBK1osZUFBZSxXQUFXLE9BQU8sbUJBQW1CLEdBQUcsNEVBQTRFLG9DQUFvQyxxQ0FBcUMsNkJBQTZCLHFJQUFxSSxnSUFBZ0ksR0FBRyxpQkFBaUIsb0RBQW9ELG9EQUFvRCxvREFBb0QsbURBQW1ELDRCQUE0Qix5REFBeUQsOElBQThJLEdBQUc7QUFDeGhILDJEQUEyRCw4Q0FBOEMsaUJBQWlCLCtCQUErQixHQUFHO0FBQzVKOztBQUVBOztBQUVBLGdCQUFnQjtBQUNoQjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsOEJBQThCLEVBQUU7QUFDaEQ7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG1DQUFtQztBQUNuQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLFNBQVM7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsaUJBQWlCO0FBQ25DLHNCQUFzQixZQUFZO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsaUJBQWlCO0FBQ25DLHNCQUFzQixPQUFPO0FBQzdCLDBCQUEwQixPQUFPO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCLGFBQWE7QUFDL0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0IsYUFBYTtBQUMvQixrREFBa0QseURBQXlEO0FBQzNHO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLFFBQVE7QUFDMUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNkRBQTZELCtCQUErQjs7QUFFNUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCLFFBQVE7QUFDMUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGtCQUFrQixTQUFTO0FBQzNCO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQix3QkFBd0I7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQzs7QUFFL0M7QUFDQSwwQkFBMEIsbUJBQW1CO0FBQzdDO0FBQ0Esd0NBQXdDLGtCQUFrQjtBQUMxRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLGdCQUFnQjtBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsZ0JBQWdCO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxpREFBaUQ7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxjQUFjO0FBQ3pCLFdBQVcsT0FBTztBQUNsQixXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLHVCQUF1QjtBQUNyQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsdUJBQXVCO0FBQ3JDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBLDZDQUE2QyxhQUFhLEVBQUU7QUFDNUQ7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLDRCQUE0QixxQkFBcUIsYUFBYSxHQUFHOztBQUVqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBLGdDQUFnQztBQUNoQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw4QkFBOEI7O0FBRTlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQsa0NBQWtDLEVBQUU7QUFDckY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EscUNBQXFDLFNBQVMsMkJBQTJCO0FBQ3pFLHFDQUFxQyxzQkFBc0I7QUFDM0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBLDBCQUEwQixxQkFBcUI7QUFDL0M7QUFDQTtBQUNBLGtDQUFrQyxxQkFBcUI7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHVCQUF1QixvQkFBb0IsRUFBRTtBQUN0RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLG1FQUFtRTtBQUMxRyxxQ0FBcUM7QUFDckM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLHFCQUFxQjtBQUN2Qyw0Q0FBNEM7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQixlQUFlO0FBQ2pDLHNCQUFzQixrQkFBa0I7QUFDeEM7QUFDQTs7QUFFQSwwQkFBMEIsdUJBQXVCO0FBQ2pEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0EsNkJBQTZCLGdDQUFnQyxFQUFFO0FBQy9EO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7O0FBRUEsaURBQWlELGVBQWU7O0FBRWhFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhEQUE4RDtBQUM5RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQ7QUFDakQ7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBLHVDQUF1Qyx1QkFBdUI7O0FBRTlEO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0EsMkJBQTJCLHFCQUFxQixFQUFFOztBQUVsRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DO0FBQ0EsaUJBQWlCOztBQUVqQjs7QUFFQTtBQUNBLDZDQUE2Qzs7QUFFN0M7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLDZCQUE2QixVQUFVLEVBQUU7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0NBQXNDLGtCQUFrQixFQUFFO0FBQzFEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjs7QUFFQSxzQ0FBc0MsNENBQTRDLEVBQUU7QUFDcEYsZ0RBQWdELG1EQUFtRCxFQUFFO0FBQ3JHO0FBQ0EsNENBQTRDLDhDQUE4QyxFQUFFO0FBQzVGO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELG9DQUFvQyxFQUFFO0FBQ3RGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUVBQXlFLG9DQUFvQztBQUM3RztBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQixnQkFBZ0IsRUFBRTtBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkJBQTJCLDZCQUE2QixFQUFFO0FBQzFELDJCQUEyQixrREFBa0QsRUFBRTs7QUFFL0U7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkIsOEJBQThCLEVBQUU7QUFDM0QsMkJBQTJCLGtEQUFrRCxFQUFFOztBQUUvRTtBQUNBOztBQUVBLENBQUMsRUFBRSxxUUFBcVE7QUFDeFE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHdEQUF3RCxrQkFBa0IsRUFBRTs7QUFFNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDZCQUE2QjtBQUM3QiwyQ0FBMkMsc0JBQXNCO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBLG9FQUFvRTtBQUNwRSx1RUFBdUU7QUFDdkUsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjs7QUFFQSxvQ0FBb0MsNkJBQTZCO0FBQ2pFOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsaUVBQWlFO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMLDRCQUE0QjtBQUM1QjtBQUNBLEtBQUs7QUFDTCx3Q0FBd0M7QUFDeEM7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0wsMkJBQTJCOztBQUUzQixLQUFLO0FBQ0wsaUNBQWlDOztBQUVqQyxLQUFLO0FBQ0wsa0NBQWtDOztBQUVsQyxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVCwyQkFBMkI7O0FBRTNCLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTOztBQUVUO0FBQ0EsS0FBSzs7QUFFTDtBQUNBLHlCQUF5QiwyQ0FBMkM7O0FBRXBFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVCxnQ0FBZ0M7O0FBRWhDLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDBNQUEwTTtBQUM3TTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnREFBZ0Q7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGtCQUFrQixpQkFBaUI7QUFDbkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYyxlQUFlO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJDQUEyQyxrQkFBa0IsRUFBRTs7QUFFL0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxtQ0FBbUM7QUFDekU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxrQkFBa0IsZUFBZTtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkMscUNBQXFDO0FBQ3JDOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixxQkFBcUI7QUFDdkM7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixlQUFlO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLHNCQUFzQjtBQUN4QztBQUNBOztBQUVBLGtCQUFrQixzQkFBc0I7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxvR0FBb0c7QUFDdkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxtRkFBbUY7QUFDdEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGtDQUFrQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLG9CQUFvQjtBQUN0QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsZ0JBQWdCO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSwyS0FBMks7QUFDOUs7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMkNBQTJDO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDRCQUE0Qix3QkFBd0I7O0FBRXBEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjs7QUFFckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7O0FBRWI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVCxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esa0JBQWtCLHFCQUFxQjtBQUN2QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0Esd0RBQXdEOztBQUV4RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDhDQUE4QztBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDZCQUE2QjtBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDO0FBQ2xDOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLDBDQUEwQztBQUMxQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULHNCQUFzQixTQUFTO0FBQy9CO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUEsc0JBQXNCLFNBQVM7QUFDL0I7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUEsa0JBQWtCLFNBQVM7QUFDM0I7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEVBQTBFLFVBQVU7QUFDcEYsMEVBQTBFLFVBQVU7QUFDcEY7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxFQUFFLDJIQUEySDtBQUM5SDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLG9DQUFvQztBQUN2QztBQUNBO0FB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OztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGtCQUFrQiw4Q0FBOEM7QUFDaEU7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQSxDQUFDLEVBQUUsMEdBQTBHO0FBQzdHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSwwQ0FBMEM7O0FBRTFDO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0RBQXdEOztBQUV4RDtBQUNBO0FBQ0E7QUFDQTs7QUFF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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsZUFBZTs7QUFFakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnQkFBZ0I7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMLHdDQUF3QztBQUN4QztBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNULDJCQUEyQixTQUFTLGtCQUFrQjtBQUN0RDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNULDRDQUE0QyxXQUFXO0FBQ3ZEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMLG1DQUFtQyxXQUFXO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGFBQWE7QUFDYjtBQUNBOztBQUVBOztBQUVBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGFBQWE7QUFDYjtBQUNBOztBQUVBOztBQUVBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxhQUFhO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxxUEFBcVA7QUFDeFA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLGNBQWMsZUFBZTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7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QUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLCtDQUErQztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0IscUJBQXFCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQix1QkFBdUI7QUFDN0M7QUFDQSwwQkFBMEIsZ0JBQWdCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtREFBbUQ7QUFDbkQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7O0FBRUE7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFIQUFxSDtBQUN4SDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMlFBQTJRO0FBQzlRO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJDQUEyQzs7QUFFM0M7O0FBRUE7QUFDQSwrREFBK0QsOEJBQThCO0FBQzdGLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUI7QUFDbkI7O0FBRUEsQ0FBQyxFQUFFLHFHQUFxRztBQUN4RztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFD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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0IsMEJBQTBCO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsOENBQThDLGlDQUFpQztBQUMvRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSw2REFBNkQ7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsZ0JBQWdCO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnQkFBZ0I7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHFDQUFxQztBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLOztBQUVMLHVCQUF1Qjs7QUFFdkIsS0FBSztBQUNMLDRCQUE0Qjs7QUFFNUIsS0FBSztBQUNMOztBQUVBLHVCQUF1QjtBQUN2QixTQUFTLHNCQUFzQjtBQUMvQjtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7OztBQUdBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQSx3QkFBd0I7QUFDeEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsU0FBUztBQUNULDJCQUEyQiw0QkFBNEIs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O0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLFNBQVM7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixTQUFTO0FBQzNCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esb0RBQW9EO0FBQ3BEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQztBQUMvQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsd0NBQXdDO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsb05BQW9OO0FBQ3ZOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxjQUFjLGlCQUFpQjtBQUMvQjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHVGQUF1RjtBQUMxRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMLHVCQUF1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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLFdBQVc7QUFDN0I7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esc0JBQXNCLFdBQVc7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxzQkFBc0IsV0FBVztBQUNqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNCQUFzQixXQUFXO0FBQ2pDO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxzQkFBc0IsV0FBVztBQUNqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0Esc0RBQXNEO0FBQ3RELEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QztBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGVBQWU7QUFDckM7QUFDQTtBQUNB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QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsZ0ZBQWdGO0FBQ25GO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0IsZ0JBQWdCO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCwrQkFBK0IsUUFBUTtBQUN2QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtB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QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNkVBQTZFLGFBQWE7QUFDMUY7QUFDQTs7QUFFQTtBQUNBLCtFQUErRSxhQUFhOztBQUU1RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLCtEQUErRCxlQUFlO0FBQzlFOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxzTUFBc007QUFDek07QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsNEdBQTRHO0FB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixTQUFTO0FBQzNCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0RBQStELFdBQVc7O0FBRTFFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxxTkFBcU47QUFDeE47QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrRUFBK0UsZUFBZTtBQUM5Rjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsd1FBQXdRO0FBQzNRO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSx5RUFBeUU7QUFDNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7OztBQUdBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDRMQUE0TDtBQUMvTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGtCQUFrQiwyQkFBMkI7QUFDN0M7O0FBRUEsc0JBQXNCLGdCQUFnQjtBQUN0QztBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsdURBQXVEO0FBQzFEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxpRUFBaUU7QUFDcEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSwrREFBK0QsV0FBVzs7QUFFMUUsYUFBYSwyQ0FBMkM7QUFDeEQ7O0FBRUEsQ0FBQyxFQUFFLG9KQUFvSjtBQUN2SjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxrUUFBa1E7QUFDclE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSx1REFBdUQ7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7OztBQUdBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHNLQUFzSztBQUN6SztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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VDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrRUFBK0UsZUFBZTtBQUM5Rjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHdRQUF3UTtBQUMzUTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSx5REFBeUQ7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBLENBQUMs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TztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxjQUFjLGVBQWU7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxjQUFjLGVBQWU7QUFDN0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsY0FBYyxrQkFBa0I7QUFDaEMsa0JBQWtCLGtCQUFrQjtBQUNwQzs7QUFFQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSw2S0FBNks7QUFDaEw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsb0NBQW9DOztBQUVwQztBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsOEVBQThFO0FBQ2pGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsV0FBVztBQUMxQjs7QUFFQSxrQkFBa0Isd0JBQXdCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGtCQUFrQixjQUFjO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDJDQUEyQztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSwyTkFBMk47QUFDOU47QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGtCQUFrQiwwQkFBMEI7QUFDNUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYyx3QkFBd0I7QUFDdEM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esc0JBQXNCLG1CQUFtQjtBQUN6QztBQUNBO0FBQ0E7QUFDQSxzQkFBc0Isa0JBQWtCO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0Isd0JBQXdCO0FBQzFDOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQixrQkFBa0I7QUFDNUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQixrQkFBa0I7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2Q0FBNkM7QUFDN0MsMkNBQTJDO0FBQzNDO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0Esb0NBQW9DO0FBQ3BDO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsc0VBQXNFO0FBQ3pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLG9EQUFvRDs7QUFFcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxnQkFBZ0I7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGNBQWM7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDREQUE0RDtBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFROztBQUVSO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSztBQUNMLHVDQUF1QyxpQkFBaUI7QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRCwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTs7QUFFQSxDQUFDLEVBQUUsZ0xBQWdMO0FBQ25MO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGNBQWMsU0FBUztBQUN2QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLFNBQVM7QUFDdkI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsVUFBVTtBQUN4QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSx1Q0FBdUM7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkI7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsMEJBQTBCLEVBQUU7QUFDM0U7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixlQUFlO0FBQ3JDLDBCQUEwQixlQUFlO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxFQUFFLG9JQUFvSTtBQUN2STtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7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QUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLG1GQUFtRjtBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHdKQUF3SjtBQUMzSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsR0FBRztBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDJDQUEyQztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQ0FBc0Msd0JBQXdCLEVBQUU7O0FBRWhFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxxQ0FBcUM7O0FBRTFFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixxQkFBcUI7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsbUNBQW1DOztBQUU3RTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGtHQUFrRyxzQkFBc0I7O0FBRXhIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxvQkFBb0IsMEJBQTBCO0FBQzlDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDLG1DQUFtQztBQUNyRTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsb1ZBQW9WO0FBQ3ZWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxzREFBc0Q7QUFDekQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkJBQTJCLHNCQUFzQjs7QUFFakQsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQixzQkFBc0I7O0FBRWpELFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQixzQkFBc0I7O0FBRWpELFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBOztBQUVBLEtBQUs7QUFDTCxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7O0FBRUw7QUFDQSw0QkFBNEI7O0FBRTVCLFNBQVM7QUFDVCwyQkFBMkI7O0FBRTNCLFNBQVM7QUFDVCwyQkFBMkI7O0FBRTNCLFNBQVM7QUFDVCxLQUFLOztBQUVMLDRCQUE0QjtBQUM1QixDQUFDOztBQUVEO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGlOQUFpTjtBQUNwTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBLENBQUMsRUFBRSx1Q0FBdUM7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0IsT0FBTztBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQ0FBaUMsU0FBUztBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsQ0FBQyxFQUFFLHNQQUFzUDtBQUN6UDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsV0FBVyxFQUFFOztBQUV4Qzs7QUFFQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQkFBc0IsT0FBTztBQUM3QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDRDQUE0QztBQUM1Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSxvR0FBb0c7QUFDdkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSw0RkFBNEY7QUFDL0Y7QUFDQTtB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlEQUFpRDtBQUNqRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0VBQXdFLHlCQUF5QjtBQUNqRzs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFFQUFxRSx5REFBeUQ7QUFDOUg7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEI7QUFDNUIsQ0FBQzs7QUFFRDtBQUNBOztBQUVBLENBQUMsRUFBRSxpS0FBaUs7QUFDcEs7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMkJBQTJCLE9BQU87QUFDbEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDLEVBQUUsd0tBQXdLO0FBQzNLO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjOztBQUVkO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkIsa0JBQWtCLFdBQVc7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQSxrQkFBa0IsZ0JBQWdCO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGtFQUFrRTtBQUNyRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLHdHQUF3RztBQUMzRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTs7QUFFQSxhQUFhO0FBQ2I7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTs7QUFFQSxpQkFBaUI7QUFDakIsb0NBQW9DO0FBQ3BDO0FBQ0E7O0FBRUEsaUJBQWlCO0FBQ2pCO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esd0NBQXdDO0FBQ3hDO0FBQ0EsS0FBSzs7QUFFTCw0QkFBNEI7QUFDNUI7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdDQUFnQyxvQkFBb0Isd0JBQXdCO0FBQzVFLGdDQUFnQztBQUNoQztBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDRNQUE0TTtBQUMvTTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCLGVBQWU7QUFDakM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGtIQUFrSDtBQUNySDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLHFCQUFxQjtBQUNuQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGNBQWMsdUJBQXVCO0FBQ3JDOztBQUVBLHNCQUFzQixlQUFlO0FBQ3JDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDLEVBQUUsOEJBQThCO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7OztBQUdMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQkFBc0IscUJBQXFCO0FBQzNDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLG9KQUFvSjtBQUN2SjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQyxHQUFHO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0MsNENBQTRDOztBQUVsRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLGdIQUFnSDtBQUNuSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUMsRUFBRSxrUEFBa1A7QUFDclA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEdBQUc7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGtCQUFrQixxQkFBcUI7QUFDdkM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDJDQUEyQztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxDQUFDLEVBQUUsMEVBQTBFO0FBQzdFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLG9DQUFvQywyQkFBMkIsRUFBRTs7QUFFakU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQyxFQUFFLDJIQUEySDtBQUM5SDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQSxZQUFZLE9BQU87QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYywyQkFBMkI7O0FBRXpDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsY0FBYywyQkFBMkI7QUFDekMsMEJBQTBCO0FBQzFCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUyw0QkFBNEI7QUFDckM7O0FBRUE7QUFDQSxjQUFjLDJCQUEyQjtBQUN6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBOztBQUVBLGdEQUFnRCxlQUFlO0FBQy9EOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLGNBQWMsU0FBUztBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxjQUFjLHlCQUF5QjtBQUN2QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQkFBa0Isc0JBQXNCO0FBQ3hDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsb0JBQW9CO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixvQkFBb0I7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsb0JBQW9CO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLG9CQUFvQjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLG9CQUFvQjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsb0JBQW9CO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixvQkFBb0I7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixvQkFBb0I7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQixxQ0FBcUM7QUFDL0Q7QUFDQTtBQUNBOztBQUVBLHFCQUFxQixvQkFBb0I7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUMsRUFBRSx1SEFBdUg7QUFDMUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLHVCQUF1QjtBQUN6QztBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMLEdBQUc7QUFDSDs7QUFFQTs7QUFFQTs7QUFFQSxDQUFDOzs7Ozs7O0FDaFBEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FDQTtBQUFBO0FBQUE7QUFBQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOztBQUVEOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGtCQUFrQixlQUFlO0FBQ2pDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQ0FBa0MsWUFBWTtBQUM5QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlLE1BQU07QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLGdCQUFnQjtBQUNwQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsY0FBYztBQUN6QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLENBQUM7Ozs7Ozs7QUM5T0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FDQTtBQUFBO0FBQUE7QUFBQSxvR0FDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixhQUFhO0FBQ2I7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLFNBQVM7QUFDcEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsUUFBUTtBQUNyQixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksY0FBYztBQUMxQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLGNBQWM7O0FBRTFCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FB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QUNWLFNBQVMsRUFDVCxVQUFVLEVBQ1YsS0FBSyxFQUNMLE1BQU0sRUFDTixHQUFHLEVBQ0gsT0FBTyxFQUNQLEdBQUcsRUFDSCxRQUFRLEVBQ1IsUUFBUSxFQUNSLE9BQU8sRUFDUCxPQUFPLEVBQ1AsTUFBTSxFQUNOLE9BQU8sRUFDUCxHQUFHLEVBQ0gsTUFBTSxFQUNOLE1BQU0sRUFDTixLQUFLLEVBQ0wsS0FBSyxFQUNMLE1BQU0sRUFDTixRQUFRLEVBQ1IsU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sUUFBUSxFQUNSLFNBQVMsRUFDVCxPQUFPLEVBQ1AsTUFBTSxFQUNOLFNBQVMsRUFDVCxPQUFPLEVBQ1AsS0FBSyxFQUNMLFFBQVEsRUFDUixNQUFNLEVBQ04sUUFBUSxFQUNSLFNBQVMsRUFDVCxPQUFPLEVBQ1AsTUFBTSxFQUNOLE9BQU8sRUFDUCxPQUFPLEVBQ1AsT0FBTyxFQUNQLFNBQVMsRUFDVCxVQUFVLEVBQ1YsSUFBSSxFQUNKLE1BQU0sRUFDTixVQUFVLEVBQ1YsU0FBUyxFQUNULFdBQVcsRUFDWCxXQUFXLEVBQ1gsT0FBTyxFQUNQLFFBQVEsRUFDUixPQUFPLEVBQ1AsT0FBTyxFQUNQLE1BQU0sRUFDTixNQUFNLEVBQ04sR0FBRyxFQUNILE1BQU0sRUFDTixPQUFPLEVBQ1AsTUFBTSxFQUNOLE1BQU0sRUFDTixLQUFLLEVBQ0wsT0FBTyxFQUNQLE1BQU0sRUFDTixNQUFNLEVBQ04sT0FBTyxFQUNQLFdBQVcsRUFDWCxPQUFPLEVBQ1AsTUFBTSxFQUNOLE9BQU8sRUFDUCxRQUFRLEVBQ1IsT0FBTyxFQUNQLFFBQVEsRUFDUixNQUFNLEVBQ04sT0FBTyxFQUNQLFFBQVEsRUFDUixTQUFTLEVBQ1QsVUFBVSxFQUNWLE9BQU8sRUFDUCxTQUFTLEVBQ1QsTUFBTSxFQUNOLElBQUksRUFDSixPQUFPLEVBQ1AsVUFBVSxFQUNWLEtBQUssRUFDTCxNQUFNLEVBQ04sUUFBUSxFQUNSLE1BQU0sRUFDTixRQUFRLEVBQ1IsU0FBUyxFQUNULE9BQU8sRUFDUCxLQUFLLEVBQ0wsR0FBRyxFQUNILE9BQU8sRUFDUCxPQUFPLEVBQ1AsSUFBSSxFQUNKLE1BQU0sRUFDTixJQUFJLEVBQ0osS0FBSyxFQUNMLE1BQU0sRUFDTixNQUFNLEVBQ04sR0FBRyxFQUNILE1BQU0sRUFDTixHQUFHLEVBQ0gsTUFBTSxFQUNOLFFBQVEsRUFDUixTQUFTLEVBQ1QsT0FBTyxFQUNQLEtBQUssRUFDTCxLQUFLLEVBQ0wsTUFBTSxFQUNOLElBQUksRUFDSixNQUFNLEVBQ04sT0FBTyxFQUNQLE1BQU0sRUFDTixNQUFNLEVBQ04sTUFBTSxFQUNOLE1BQU0sRUFDTixPQUFPLEVBQ1AsU0FBUyxFQUNULE9BQU8sRUFDUCxPQUFPLEVBQ1AsS0FBSyxFQUNMLE9BQU8sRUFDUCxPQUFPLEVBQ1AsS0FBSyxFQUNMLE1BQU0sRUFDTixNQUFNLEVBQ04sUUFBUSxFQUNSLFNBQVMsRUFDVCxNQUFNLEVBQ04sUUFBUSxFQUNSLFNBQVMsRUFDVCxPQUFPLEVBQ1AsT0FBTyxFQUNQLEdBQUcsRUFDSCxHQUFHLEVBQ0gsTUFBTSxFQUNOLE9BQU8sRUFDUCxLQUFLLEVBQ0wsS0FBSyxFQUNMLE9BQU8sRUFDUCxTQUFTLEVBQ1QsVUFBVSxFQUNWLE1BQU0sRUFDTixPQUFPLEVBQ1AsR0FBRyxDQUNKLENBQUM7Ozs7Ozs7QUM5YUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDRDQUE0Qzs7QUFFNUM7Ozs7Ozs7QUNwQkEsZ0Q7Ozs7OztBQ0FBLGdEOzs7Ozs7QUNBQSxnRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDQWlDO0FBQ007QUFDRjtBQUNPO0FBQ0M7QUFFTDtBQUNSO0FBQ0w7QUFDSTtBQUNPO0FBQ00iLCJmaWxlIjoiLi9wYWNrYWdlcy9zdXJ2ZXkuYW5hbHl0aWNzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKFwic3VydmV5LWNvcmVcIiksIHJlcXVpcmUoXCJjM1wiKSwgcmVxdWlyZShcImNoYXJ0LmpzXCIpLCByZXF1aXJlKFwid29yZGNsb3VkXCIpLCByZXF1aXJlKFwianF1ZXJ5XCIpKTtcblx0ZWxzZSBpZih0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpXG5cdFx0ZGVmaW5lKFwiU3VydmV5QW5hbHl0aWNzXCIsIFtcInN1cnZleS1jb3JlXCIsIFwiYzNcIiwgXCJjaGFydC5qc1wiLCBcIndvcmRjbG91ZFwiLCBcImpxdWVyeVwiXSwgZmFjdG9yeSk7XG5cdGVsc2UgaWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnKVxuXHRcdGV4cG9ydHNbXCJTdXJ2ZXlBbmFseXRpY3NcIl0gPSBmYWN0b3J5KHJlcXVpcmUoXCJzdXJ2ZXktY29yZVwiKSwgcmVxdWlyZShcImMzXCIpLCByZXF1aXJlKFwiY2hhcnQuanNcIiksIHJlcXVpcmUoXCJ3b3JkY2xvdWRcIiksIHJlcXVpcmUoXCJqcXVlcnlcIikpO1xuXHRlbHNlXG5cdFx0cm9vdFtcIlN1cnZleUFuYWx5dGljc1wiXSA9IGZhY3Rvcnkocm9vdFtcIlN1cnZleVwiXSwgcm9vdFtcImMzXCJdLCByb290W1wiQ2hhcnRcIl0sIHJvb3RbXCJXb3JkQ2xvdWRcIl0sIHJvb3RbXCJqUXVlcnlcIl0pO1xufSkodGhpcywgZnVuY3Rpb24oX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV80X18sIF9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfMTRfXywgX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV8zNl9fLCBfX1dFQlBBQ0tfRVhURVJOQUxfTU9EVUxFXzM3X18sIF9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfMzhfXykge1xucmV0dXJuIFxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyB3ZWJwYWNrL3VuaXZlcnNhbE1vZHVsZURlZmluaXRpb24iLCIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSlcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcblxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gaWRlbnRpdHkgZnVuY3Rpb24gZm9yIGNhbGxpbmcgaGFybW9ueSBpbXBvcnRzIHdpdGggdGhlIGNvcnJlY3QgY29udGV4dFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5pID0gZnVuY3Rpb24odmFsdWUpIHsgcmV0dXJuIHZhbHVlOyB9O1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4gXHRyZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSAzOSk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gd2VicGFjay9ib290c3RyYXAgZDBhZmU4MGM4NzY4NGRlZThmMjUiLCJleHBvcnQgdmFyIF9fYXNzaWduID1cbiAgKDxhbnk+T2JqZWN0KVtcImFzc2lnblwiXSB8fFxuICBmdW5jdGlvbih0YXJnZXQ6IGFueSkge1xuICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgIGZvciAodmFyIHAgaW4gcylcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdGFyZ2V0W3BdID0gc1twXTtcbiAgICB9XG4gICAgcmV0dXJuIHRhcmdldDtcbiAgfTtcblxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyh0aGlzQ2xhc3M6IGFueSwgYmFzZUNsYXNzOiBhbnkpIHtcbiAgZm9yICh2YXIgcCBpbiBiYXNlQ2xhc3MpXG4gICAgaWYgKGJhc2VDbGFzcy5oYXNPd25Qcm9wZXJ0eShwKSkgdGhpc0NsYXNzW3BdID0gYmFzZUNsYXNzW3BdO1xuICBmdW5jdGlvbiBfXygpIHtcbiAgICB0aGlzLmNvbnN0cnVjdG9yID0gdGhpc0NsYXNzO1xuICB9XG4gIHRoaXNDbGFzcy5wcm90b3R5cGUgPVxuICAgIGJhc2VDbGFzcyA9PT0gbnVsbFxuICAgICAgPyBPYmplY3QuY3JlYXRlKGJhc2VDbGFzcylcbiAgICAgIDogKChfXy5wcm90b3R5cGUgPSBiYXNlQ2xhc3MucHJvdG90eXBlKSwgbmV3ICg8YW55Pl9fKSgpKTtcbn1cblxuZXhwb3J0IHZhciBfX3Jlc3QgPSBmdW5jdGlvbihzb3VyY2U6IGFueSwgZTogYW55KSB7XG4gIHZhciByZXN1bHQ6IGFueSA9IHt9O1xuICBmb3IgKHZhciBwcm9wZXJ0eU5hbWUgaW4gc291cmNlKVxuICAgIGlmIChcbiAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIHByb3BlcnR5TmFtZSkgJiZcbiAgICAgIGUuaW5kZXhPZihwcm9wZXJ0eU5hbWUpIDwgMFxuICAgIClcbiAgICAgIHJlc3VsdFtwcm9wZXJ0eU5hbWVdID0gc291cmNlW3Byb3BlcnR5TmFtZV07XG4gIGlmIChcbiAgICBzb3VyY2UgIT0gbnVsbCAmJlxuICAgIHR5cGVvZiAoPGFueT5PYmplY3QpW1wiZ2V0T3duUHJvcGVydHlTeW1ib2xzXCJdID09PSBcImZ1bmN0aW9uXCJcbiAgKVxuICAgIGZvciAoXG4gICAgICB2YXIgaSA9IDAsXG4gICAgICAgIHByb3BlcnR5U3ltYm9scyA9ICg8YW55Pk9iamVjdClbXCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHNcIl0oc291cmNlKTtcbiAgICAgIGkgPCBwcm9wZXJ0eVN5bWJvbHMubGVuZ3RoO1xuICAgICAgaSsrXG4gICAgKVxuICAgICAgaWYgKGUuaW5kZXhPZihwcm9wZXJ0eVN5bWJvbHNbaV0pIDwgMClcbiAgICAgICAgcmVzdWx0W3Byb3BlcnR5U3ltYm9sc1tpXV0gPSBzb3VyY2VbcHJvcGVydHlTeW1ib2xzW2ldXTtcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbmRlY2xhcmUgdmFyIFJlZmxlY3Q6IGFueTtcblxuZXhwb3J0IHZhciBfX2RlY29yYXRlID0gZnVuY3Rpb24oXG4gIGRlY29yYXRvcnM6IGFueSxcbiAgdGFyZ2V0OiBhbnksXG4gIGtleTogYW55LFxuICBkZXNjOiBhbnlcbikge1xuICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgciA9XG4gICAgICBjIDwgM1xuICAgICAgICA/IHRhcmdldFxuICAgICAgICA6IGRlc2MgPT09IG51bGxcbiAgICAgICAgPyAoZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpKVxuICAgICAgICA6IGRlc2MsXG4gICAgZDtcbiAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpXG4gICAgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xuICBlbHNlXG4gICAgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pXG4gICAgICBpZiAoKGQgPSBkZWNvcmF0b3JzW2ldKSlcbiAgICAgICAgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL3V0aWxzL2hlbHBlcnMudHMiLCJpbXBvcnQgeyBRdWVzdGlvbiB9IGZyb20gXCJzdXJ2ZXktY29yZVwiO1xuaW1wb3J0IHsgVmlzdWFsaXplckJhc2UgfSBmcm9tIFwiLi92aXN1YWxpemVyQmFzZVwiO1xuXG5kZWNsYXJlIHR5cGUgVmlzdWFsaXplckNvbnN0cnVjdG9yID0gbmV3IChcbiAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQsXG4gIHF1ZXN0aW9uOiBRdWVzdGlvbixcbiAgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgb3B0aW9ucz86IE9iamVjdFxuKSA9PiBhbnk7XG5cbmV4cG9ydCBjbGFzcyBWaXN1YWxpemF0aW9uTWFuYWdlciB7XG4gIHN0YXRpYyB2aXp1YWxpemVyczogeyBbaW5kZXg6IHN0cmluZ106IEFycmF5PFZpc3VhbGl6ZXJDb25zdHJ1Y3Rvcj4gfSA9IHt9O1xuICBzdGF0aWMgcmVnaXN0ZXJWaXN1YWxpemVyKFxuICAgIHR5cGVOYW1lOiBzdHJpbmcsXG4gICAgY29uc3RydWN0b3I6IFZpc3VhbGl6ZXJDb25zdHJ1Y3RvclxuICApIHtcbiAgICBsZXQgdml6dWFsaXplcnMgPSBWaXN1YWxpemF0aW9uTWFuYWdlci52aXp1YWxpemVyc1t0eXBlTmFtZV07XG4gICAgaWYgKCF2aXp1YWxpemVycykge1xuICAgICAgdml6dWFsaXplcnMgPSBbXTtcbiAgICAgIFZpc3VhbGl6YXRpb25NYW5hZ2VyLnZpenVhbGl6ZXJzW3R5cGVOYW1lXSA9IHZpenVhbGl6ZXJzO1xuICAgIH1cbiAgICB2aXp1YWxpemVycy5wdXNoKGNvbnN0cnVjdG9yKTtcbiAgfVxuICBzdGF0aWMgZ2V0VmlzdWFsaXplcnModHlwZU5hbWU6IHN0cmluZykge1xuICAgIGxldCB2aXp1YWxpemVycyA9IFZpc3VhbGl6YXRpb25NYW5hZ2VyLnZpenVhbGl6ZXJzW3R5cGVOYW1lXTtcbiAgICBpZiAoIXZpenVhbGl6ZXJzKSB7XG4gICAgICByZXR1cm4gW1Zpc3VhbGl6ZXJCYXNlXTtcbiAgICB9XG4gICAgcmV0dXJuIHZpenVhbGl6ZXJzO1xuICB9XG59XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvdmlzdWFsaXphdGlvbk1hbmFnZXIudHMiLCJpbXBvcnQgeyBRdWVzdGlvbiB9IGZyb20gXCJzdXJ2ZXktY29yZVwiO1xuXG5leHBvcnQgY2xhc3MgVmlzdWFsaXplckJhc2Uge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgcHVibGljIHF1ZXN0aW9uOiBRdWVzdGlvbixcbiAgICBwcm90ZWN0ZWQgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgICBwcm90ZWN0ZWQgb3B0aW9ucz86IE9iamVjdFxuICApIHt9XG5cbiAgdXBkYXRlKGRhdGE6IEFycmF5PHsgW2luZGV4OiBzdHJpbmddOiBhbnkgfT4pIHtcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICB9XG5cbiAgb25VcGRhdGU6ICgpID0+IHZvaWQ7XG5cbiAgZGVzdHJveSgpIHtcbiAgICB0aGlzLnRhcmdldEVsZW1lbnQuaW5uZXJIVE1MID0gXCJcIjtcbiAgfVxuXG4gIHJlbmRlcigpIHtcbiAgICB0aGlzLnRhcmdldEVsZW1lbnQuaW5uZXJIVE1MID0gXCJUaGlzIHF1ZXN0aW9uIHR5cGUgaXMgbm90IHZpc3VhbGl6ZWQgeWV0XCI7XG4gIH1cblxuICBpbnZva2VPblVwZGF0ZSgpIHtcbiAgICB0aGlzLm9uVXBkYXRlICYmIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIGdldFJhbmRvbUNvbG9yKCkge1xuICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuZ2V0Q29sb3JzKCk7XG4gICAgcmV0dXJuIFwiI1wiICsgY29sb3JzW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIGNvbG9ycy5sZW5ndGgpXTtcbiAgfVxuXG4gIGJhY2tncm91bmRDb2xvciA9IFwiI2Y3ZjdmN1wiO1xuXG4gIHN0YXRpYyBjdXN0b21Db2xvcnM6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgc3RhdGljIGNvbG9ycyA9IFtcbiAgICBcIjg2ZTFmYlwiLFxuICAgIFwiMzk5OWZiXCIsXG4gICAgXCJmZjY3NzFcIixcbiAgICBcIjFlYjQ5NlwiLFxuICAgIFwiZmZjMTUyXCIsXG4gICAgXCJhYmExZmZcIixcbiAgICBcIjdkOGRhNVwiLFxuICAgIFwiNGVjNDZjXCIsXG4gICAgXCJjZjM3YTZcIixcbiAgICBcIjRlNjE5OFwiXG4gIF07XG5cbiAgZ2V0Q29sb3JzKGNvdW50ID0gMTApIHtcbiAgICBjb25zdCBjb2xvcnMgPVxuICAgICAgQXJyYXkuaXNBcnJheShWaXN1YWxpemVyQmFzZS5jdXN0b21Db2xvcnMpICYmXG4gICAgICBWaXN1YWxpemVyQmFzZS5jdXN0b21Db2xvcnMubGVuZ3RoID4gMFxuICAgICAgICA/IFZpc3VhbGl6ZXJCYXNlLmN1c3RvbUNvbG9yc1xuICAgICAgICA6IFZpc3VhbGl6ZXJCYXNlLmNvbG9ycztcblxuICAgIGxldCBtYW55Q29sb3JzOiBhbnkgPSBbXTtcblxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBjb3VudDsgaW5kZXgrKykge1xuICAgICAgbWFueUNvbG9ycyA9IG1hbnlDb2xvcnMuY29uY2F0KGNvbG9ycyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1hbnlDb2xvcnM7XG4gIH1cbn1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy92aXN1YWxpemVyQmFzZS50cyIsImltcG9ydCB7IFF1ZXN0aW9uLCBRdWVzdGlvblNlbGVjdEJhc2UsIEl0ZW1WYWx1ZSB9IGZyb20gXCJzdXJ2ZXktY29yZVwiO1xuaW1wb3J0IHsgVmlzdWFsaXplckJhc2UgfSBmcm9tIFwiLi92aXN1YWxpemVyQmFzZVwiO1xuXG5leHBvcnQgY2xhc3MgU2VsZWN0QmFzZSBleHRlbmRzIFZpc3VhbGl6ZXJCYXNlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIHRhcmdldEVsZW1lbnQ6IEhUTUxFbGVtZW50LFxuICAgIHF1ZXN0aW9uOiBRdWVzdGlvbixcbiAgICBkYXRhOiBBcnJheTx7IFtpbmRleDogc3RyaW5nXTogYW55IH0+LFxuICAgIG9wdGlvbnM/OiBPYmplY3RcbiAgKSB7XG4gICAgc3VwZXIodGFyZ2V0RWxlbWVudCwgcXVlc3Rpb24sIGRhdGEsIG9wdGlvbnMpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNoYXJ0VHlwZXM6IHN0cmluZ1tdO1xuICBwcm90ZWN0ZWQgY2hhcnRUeXBlOiBzdHJpbmc7XG4gIHByb3RlY3RlZCBjaGFydE5vZGU6IEhUTUxFbGVtZW50ID0gPEhUTUxFbGVtZW50PmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG5cbiAgcHJvdGVjdGVkIHNldENoYXJ0VHlwZShjaGFydFR5cGU6IHN0cmluZykge1xuICAgIGlmIChcbiAgICAgIHRoaXMuY2hhcnRUeXBlcy5pbmRleE9mKGNoYXJ0VHlwZSkgIT09IC0xICYmXG4gICAgICB0aGlzLmNoYXJ0VHlwZSAhPT0gY2hhcnRUeXBlXG4gICAgKSB7XG4gICAgICB0aGlzLmNoYXJ0VHlwZSA9IGNoYXJ0VHlwZTtcbiAgICAgIHRoaXMuY3JlYXRlQ2hhcnQoKTtcbiAgICAgIHRoaXMuaW52b2tlT25VcGRhdGUoKTtcbiAgICB9XG4gIH1cblxuICBjcmVhdGVDaGFydCgpIHt9XG5cbiAgb25EYXRhSXRlbVNlbGVjdGVkOiAoc2VsZWN0ZWRWYWx1ZTogYW55LCBjbGVhclNlbGVjdGlvbjogYm9vbGVhbikgPT4gdm9pZDtcblxuICByZW5kZXIoKSB7XG4gICAgY29uc3QgY2hhcnROb2RlQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICBjb25zdCB0b29sYmFyTm9kZUNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG5cbiAgICBjaGFydE5vZGVDb250YWluZXIuYXBwZW5kQ2hpbGQodG9vbGJhck5vZGVDb250YWluZXIpO1xuICAgIGNoYXJ0Tm9kZUNvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLmNoYXJ0Tm9kZSk7XG4gICAgdGhpcy50YXJnZXRFbGVtZW50LmFwcGVuZENoaWxkKGNoYXJ0Tm9kZUNvbnRhaW5lcik7XG5cbiAgICB0aGlzLmNyZWF0ZVRvb2xiYXIodG9vbGJhck5vZGVDb250YWluZXIpO1xuXG4gICAgdGhpcy5jcmVhdGVDaGFydCgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNyZWF0ZVRvb2xiYXJJdGVtcyh0b29sYmFyOiBIVE1MRGl2RWxlbWVudCkge1xuICAgIGlmICh0aGlzLmNoYXJ0VHlwZXMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3Qgc2VsZWN0V3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICBzZWxlY3RXcmFwcGVyLmNsYXNzTmFtZSA9IFwic3ZhLXF1ZXN0aW9uX19zZWxlY3Qtd3JhcHBlclwiO1xuICAgICAgY29uc3Qgc2VsZWN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNlbGVjdFwiKTtcbiAgICAgIHNlbGVjdC5jbGFzc05hbWUgPSBcInN2YS1xdWVzdGlvbl9fc2VsZWN0XCI7XG4gICAgICB0aGlzLmNoYXJ0VHlwZXMuZm9yRWFjaChjaGFydFR5cGUgPT4ge1xuICAgICAgICBsZXQgb3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIm9wdGlvblwiKTtcbiAgICAgICAgb3B0aW9uLnZhbHVlID0gY2hhcnRUeXBlO1xuICAgICAgICBvcHRpb24udGV4dCA9IGNoYXJ0VHlwZTtcbiAgICAgICAgb3B0aW9uLnNlbGVjdGVkID0gdGhpcy5jaGFydFR5cGUgPT09IGNoYXJ0VHlwZTtcbiAgICAgICAgc2VsZWN0LmFwcGVuZENoaWxkKG9wdGlvbik7XG4gICAgICB9KTtcbiAgICAgIHNlbGVjdC5vbmNoYW5nZSA9IChlOiBhbnkpID0+IHtcbiAgICAgICAgdGhpcy5zZXRDaGFydFR5cGUoZS50YXJnZXQudmFsdWUpO1xuICAgICAgfTtcbiAgICAgIHNlbGVjdFdyYXBwZXIuYXBwZW5kQ2hpbGQoc2VsZWN0KTtcbiAgICAgIHRvb2xiYXIuYXBwZW5kQ2hpbGQoc2VsZWN0V3JhcHBlcik7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGNyZWF0ZVRvb2xiYXIoY29udGFpbmVyOiBIVE1MRGl2RWxlbWVudCkge1xuICAgIGNvbnN0IHRvb2xiYXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgIHRvb2xiYXIuY2xhc3NOYW1lID0gXCJzdmEtcXVlc3Rpb25fX3Rvb2xiYXJcIjtcbiAgICB0aGlzLmNyZWF0ZVRvb2xiYXJJdGVtcyh0b29sYmFyKTtcbiAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQodG9vbGJhcik7XG4gIH1cblxuICB2YWx1ZXNTb3VyY2UoKTogYW55W10ge1xuICAgIGNvbnN0IHF1ZXN0aW9uID0gPFF1ZXN0aW9uU2VsZWN0QmFzZT50aGlzLnF1ZXN0aW9uO1xuICAgIHJldHVybiBxdWVzdGlvbltcImFjdGl2ZUNob2ljZXNcIl07XG4gIH1cblxuICBnZXRWYWx1ZXMoKTogQXJyYXk8YW55PiB7XG4gICAgY29uc3QgdmFsdWVzOiBBcnJheTxhbnk+ID0gdGhpcy52YWx1ZXNTb3VyY2UoKS5tYXAoY2hvaWNlID0+IGNob2ljZS52YWx1ZSk7XG5cbiAgICBpZiAodGhpcy5xdWVzdGlvbi5oYXNPdGhlcikgdmFsdWVzLnVuc2hpZnQoXCJvdGhlclwiKTtcblxuICAgIHJldHVybiB2YWx1ZXM7XG4gIH1cblxuICBnZXRMYWJlbHMoKTogQXJyYXk8c3RyaW5nPiB7XG4gICAgY29uc3QgbGFiZWxzOiBBcnJheTxzdHJpbmc+ID0gdGhpcy52YWx1ZXNTb3VyY2UoKS5tYXAoY2hvaWNlID0+XG4gICAgICBJdGVtVmFsdWUuZ2V0VGV4dE9ySHRtbEJ5VmFsdWUodGhpcy52YWx1ZXNTb3VyY2UoKSwgY2hvaWNlLnZhbHVlKVxuICAgICk7XG5cbiAgICBpZiAodGhpcy5xdWVzdGlvbi5oYXNPdGhlcikgbGFiZWxzLnVuc2hpZnQoXCJPdGhlclwiKTtcblxuICAgIHJldHVybiBsYWJlbHM7XG4gIH1cblxuICBnZXREYXRhKCk6IGFueVtdIHtcbiAgICBjb25zdCB2YWx1ZXMgPSB0aGlzLmdldFZhbHVlcygpO1xuICAgIGNvbnN0IHN0YXRpc3RpY3MgPSB2YWx1ZXMubWFwKHYgPT4gMCk7XG4gICAgdGhpcy5kYXRhLmZvckVhY2gocm93ID0+IHtcbiAgICAgIGNvbnN0IHJvd1ZhbHVlOiBhbnkgPSByb3dbdGhpcy5xdWVzdGlvbi5uYW1lXTtcbiAgICAgIGlmICghIXJvd1ZhbHVlKSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJvd1ZhbHVlKSkge1xuICAgICAgICAgIHZhbHVlcy5mb3JFYWNoKCh2YWw6IGFueSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgaWYgKHJvd1ZhbHVlLmluZGV4T2YodmFsKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgc3RhdGlzdGljc1tpbmRleF0rKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YWx1ZXMuZm9yRWFjaCgodmFsOiBhbnksIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGlmIChyb3dWYWx1ZSA9PSB2YWwpIHtcbiAgICAgICAgICAgICAgc3RhdGlzdGljc1tpbmRleF0rKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBbc3RhdGlzdGljc107XG4gIH1cbn1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9zZWxlY3RCYXNlLnRzIiwibW9kdWxlLmV4cG9ydHMgPSBfX1dFQlBBQ0tfRVhURVJOQUxfTU9EVUxFXzRfXztcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCB7XCJyb290XCI6XCJTdXJ2ZXlcIixcImNvbW1vbmpzMlwiOlwic3VydmV5LWNvcmVcIixcImNvbW1vbmpzXCI6XCJzdXJ2ZXktY29yZVwiLFwiYW1kXCI6XCJzdXJ2ZXktY29yZVwifVxuLy8gbW9kdWxlIGlkID0gNFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiFcbiAqIGdldFNpemUgdjIuMC4zXG4gKiBtZWFzdXJlIHNpemUgb2YgZWxlbWVudHNcbiAqIE1JVCBsaWNlbnNlXG4gKi9cblxuLyoganNoaW50IGJyb3dzZXI6IHRydWUsIHN0cmljdDogdHJ1ZSwgdW5kZWY6IHRydWUsIHVudXNlZDogdHJ1ZSAqL1xuLyogZ2xvYmFscyBjb25zb2xlOiBmYWxzZSAqL1xuXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIC8qIGpzaGludCBzdHJpY3Q6IGZhbHNlICovIC8qIGdsb2JhbHMgZGVmaW5lLCBtb2R1bGUgKi9cbiAgaWYgKCB0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCApIHtcbiAgICAvLyBBTURcbiAgICBkZWZpbmUoIGZhY3RvcnkgKTtcbiAgfSBlbHNlIGlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgICAvLyBDb21tb25KU1xuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgd2luZG93LmdldFNpemUgPSBmYWN0b3J5KCk7XG4gIH1cblxufSkoIHdpbmRvdywgZnVuY3Rpb24gZmFjdG9yeSgpIHtcbid1c2Ugc3RyaWN0JztcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gaGVscGVycyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4vLyBnZXQgYSBudW1iZXIgZnJvbSBhIHN0cmluZywgbm90IGEgcGVyY2VudGFnZVxuZnVuY3Rpb24gZ2V0U3R5bGVTaXplKCB2YWx1ZSApIHtcbiAgdmFyIG51bSA9IHBhcnNlRmxvYXQoIHZhbHVlICk7XG4gIC8vIG5vdCBhIHBlcmNlbnQgbGlrZSAnMTAwJScsIGFuZCBhIG51bWJlclxuICB2YXIgaXNWYWxpZCA9IHZhbHVlLmluZGV4T2YoJyUnKSA9PSAtMSAmJiAhaXNOYU4oIG51bSApO1xuICByZXR1cm4gaXNWYWxpZCAmJiBudW07XG59XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG52YXIgbG9nRXJyb3IgPSB0eXBlb2YgY29uc29sZSA9PSAndW5kZWZpbmVkJyA/IG5vb3AgOlxuICBmdW5jdGlvbiggbWVzc2FnZSApIHtcbiAgICBjb25zb2xlLmVycm9yKCBtZXNzYWdlICk7XG4gIH07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIG1lYXN1cmVtZW50cyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG52YXIgbWVhc3VyZW1lbnRzID0gW1xuICAncGFkZGluZ0xlZnQnLFxuICAncGFkZGluZ1JpZ2h0JyxcbiAgJ3BhZGRpbmdUb3AnLFxuICAncGFkZGluZ0JvdHRvbScsXG4gICdtYXJnaW5MZWZ0JyxcbiAgJ21hcmdpblJpZ2h0JyxcbiAgJ21hcmdpblRvcCcsXG4gICdtYXJnaW5Cb3R0b20nLFxuICAnYm9yZGVyTGVmdFdpZHRoJyxcbiAgJ2JvcmRlclJpZ2h0V2lkdGgnLFxuICAnYm9yZGVyVG9wV2lkdGgnLFxuICAnYm9yZGVyQm90dG9tV2lkdGgnXG5dO1xuXG52YXIgbWVhc3VyZW1lbnRzTGVuZ3RoID0gbWVhc3VyZW1lbnRzLmxlbmd0aDtcblxuZnVuY3Rpb24gZ2V0WmVyb1NpemUoKSB7XG4gIHZhciBzaXplID0ge1xuICAgIHdpZHRoOiAwLFxuICAgIGhlaWdodDogMCxcbiAgICBpbm5lcldpZHRoOiAwLFxuICAgIGlubmVySGVpZ2h0OiAwLFxuICAgIG91dGVyV2lkdGg6IDAsXG4gICAgb3V0ZXJIZWlnaHQ6IDBcbiAgfTtcbiAgZm9yICggdmFyIGk9MDsgaSA8IG1lYXN1cmVtZW50c0xlbmd0aDsgaSsrICkge1xuICAgIHZhciBtZWFzdXJlbWVudCA9IG1lYXN1cmVtZW50c1tpXTtcbiAgICBzaXplWyBtZWFzdXJlbWVudCBdID0gMDtcbiAgfVxuICByZXR1cm4gc2l6ZTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gZ2V0U3R5bGUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuLyoqXG4gKiBnZXRTdHlsZSwgZ2V0IHN0eWxlIG9mIGVsZW1lbnQsIGNoZWNrIGZvciBGaXJlZm94IGJ1Z1xuICogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9NTQ4Mzk3XG4gKi9cbmZ1bmN0aW9uIGdldFN0eWxlKCBlbGVtICkge1xuICB2YXIgc3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKCBlbGVtICk7XG4gIGlmICggIXN0eWxlICkge1xuICAgIGxvZ0Vycm9yKCAnU3R5bGUgcmV0dXJuZWQgJyArIHN0eWxlICtcbiAgICAgICcuIEFyZSB5b3UgcnVubmluZyB0aGlzIGNvZGUgaW4gYSBoaWRkZW4gaWZyYW1lIG9uIEZpcmVmb3g/ICcgK1xuICAgICAgJ1NlZSBodHRwczovL2JpdC5seS9nZXRzaXplYnVnMScgKTtcbiAgfVxuICByZXR1cm4gc3R5bGU7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHNldHVwIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbnZhciBpc1NldHVwID0gZmFsc2U7XG5cbnZhciBpc0JveFNpemVPdXRlcjtcblxuLyoqXG4gKiBzZXR1cFxuICogY2hlY2sgaXNCb3hTaXplck91dGVyXG4gKiBkbyBvbiBmaXJzdCBnZXRTaXplKCkgcmF0aGVyIHRoYW4gb24gcGFnZSBsb2FkIGZvciBGaXJlZm94IGJ1Z1xuICovXG5mdW5jdGlvbiBzZXR1cCgpIHtcbiAgLy8gc2V0dXAgb25jZVxuICBpZiAoIGlzU2V0dXAgKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlzU2V0dXAgPSB0cnVlO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGJveCBzaXppbmcgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAvKipcbiAgICogQ2hyb21lICYgU2FmYXJpIG1lYXN1cmUgdGhlIG91dGVyLXdpZHRoIG9uIHN0eWxlLndpZHRoIG9uIGJvcmRlci1ib3ggZWxlbXNcbiAgICogSUUxMSAmIEZpcmVmb3g8MjkgbWVhc3VyZXMgdGhlIGlubmVyLXdpZHRoXG4gICAqL1xuICB2YXIgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIGRpdi5zdHlsZS53aWR0aCA9ICcyMDBweCc7XG4gIGRpdi5zdHlsZS5wYWRkaW5nID0gJzFweCAycHggM3B4IDRweCc7XG4gIGRpdi5zdHlsZS5ib3JkZXJTdHlsZSA9ICdzb2xpZCc7XG4gIGRpdi5zdHlsZS5ib3JkZXJXaWR0aCA9ICcxcHggMnB4IDNweCA0cHgnO1xuICBkaXYuc3R5bGUuYm94U2l6aW5nID0gJ2JvcmRlci1ib3gnO1xuXG4gIHZhciBib2R5ID0gZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIGJvZHkuYXBwZW5kQ2hpbGQoIGRpdiApO1xuICB2YXIgc3R5bGUgPSBnZXRTdHlsZSggZGl2ICk7XG4gIC8vIHJvdW5kIHZhbHVlIGZvciBicm93c2VyIHpvb20uIGRlc2FuZHJvL21hc29ucnkjOTI4XG4gIGlzQm94U2l6ZU91dGVyID0gTWF0aC5yb3VuZCggZ2V0U3R5bGVTaXplKCBzdHlsZS53aWR0aCApICkgPT0gMjAwO1xuICBnZXRTaXplLmlzQm94U2l6ZU91dGVyID0gaXNCb3hTaXplT3V0ZXI7XG5cbiAgYm9keS5yZW1vdmVDaGlsZCggZGl2ICk7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGdldFNpemUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuZnVuY3Rpb24gZ2V0U2l6ZSggZWxlbSApIHtcbiAgc2V0dXAoKTtcblxuICAvLyB1c2UgcXVlcnlTZWxldG9yIGlmIGVsZW0gaXMgc3RyaW5nXG4gIGlmICggdHlwZW9mIGVsZW0gPT0gJ3N0cmluZycgKSB7XG4gICAgZWxlbSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIGVsZW0gKTtcbiAgfVxuXG4gIC8vIGRvIG5vdCBwcm9jZWVkIG9uIG5vbi1vYmplY3RzXG4gIGlmICggIWVsZW0gfHwgdHlwZW9mIGVsZW0gIT0gJ29iamVjdCcgfHwgIWVsZW0ubm9kZVR5cGUgKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHN0eWxlID0gZ2V0U3R5bGUoIGVsZW0gKTtcblxuICAvLyBpZiBoaWRkZW4sIGV2ZXJ5dGhpbmcgaXMgMFxuICBpZiAoIHN0eWxlLmRpc3BsYXkgPT0gJ25vbmUnICkge1xuICAgIHJldHVybiBnZXRaZXJvU2l6ZSgpO1xuICB9XG5cbiAgdmFyIHNpemUgPSB7fTtcbiAgc2l6ZS53aWR0aCA9IGVsZW0ub2Zmc2V0V2lkdGg7XG4gIHNpemUuaGVpZ2h0ID0gZWxlbS5vZmZzZXRIZWlnaHQ7XG5cbiAgdmFyIGlzQm9yZGVyQm94ID0gc2l6ZS5pc0JvcmRlckJveCA9IHN0eWxlLmJveFNpemluZyA9PSAnYm9yZGVyLWJveCc7XG5cbiAgLy8gZ2V0IGFsbCBtZWFzdXJlbWVudHNcbiAgZm9yICggdmFyIGk9MDsgaSA8IG1lYXN1cmVtZW50c0xlbmd0aDsgaSsrICkge1xuICAgIHZhciBtZWFzdXJlbWVudCA9IG1lYXN1cmVtZW50c1tpXTtcbiAgICB2YXIgdmFsdWUgPSBzdHlsZVsgbWVhc3VyZW1lbnQgXTtcbiAgICB2YXIgbnVtID0gcGFyc2VGbG9hdCggdmFsdWUgKTtcbiAgICAvLyBhbnkgJ2F1dG8nLCAnbWVkaXVtJyB2YWx1ZSB3aWxsIGJlIDBcbiAgICBzaXplWyBtZWFzdXJlbWVudCBdID0gIWlzTmFOKCBudW0gKSA/IG51bSA6IDA7XG4gIH1cblxuICB2YXIgcGFkZGluZ1dpZHRoID0gc2l6ZS5wYWRkaW5nTGVmdCArIHNpemUucGFkZGluZ1JpZ2h0O1xuICB2YXIgcGFkZGluZ0hlaWdodCA9IHNpemUucGFkZGluZ1RvcCArIHNpemUucGFkZGluZ0JvdHRvbTtcbiAgdmFyIG1hcmdpbldpZHRoID0gc2l6ZS5tYXJnaW5MZWZ0ICsgc2l6ZS5tYXJnaW5SaWdodDtcbiAgdmFyIG1hcmdpbkhlaWdodCA9IHNpemUubWFyZ2luVG9wICsgc2l6ZS5tYXJnaW5Cb3R0b207XG4gIHZhciBib3JkZXJXaWR0aCA9IHNpemUuYm9yZGVyTGVmdFdpZHRoICsgc2l6ZS5ib3JkZXJSaWdodFdpZHRoO1xuICB2YXIgYm9yZGVySGVpZ2h0ID0gc2l6ZS5ib3JkZXJUb3BXaWR0aCArIHNpemUuYm9yZGVyQm90dG9tV2lkdGg7XG5cbiAgdmFyIGlzQm9yZGVyQm94U2l6ZU91dGVyID0gaXNCb3JkZXJCb3ggJiYgaXNCb3hTaXplT3V0ZXI7XG5cbiAgLy8gb3ZlcndyaXRlIHdpZHRoIGFuZCBoZWlnaHQgaWYgd2UgY2FuIGdldCBpdCBmcm9tIHN0eWxlXG4gIHZhciBzdHlsZVdpZHRoID0gZ2V0U3R5bGVTaXplKCBzdHlsZS53aWR0aCApO1xuICBpZiAoIHN0eWxlV2lkdGggIT09IGZhbHNlICkge1xuICAgIHNpemUud2lkdGggPSBzdHlsZVdpZHRoICtcbiAgICAgIC8vIGFkZCBwYWRkaW5nIGFuZCBib3JkZXIgdW5sZXNzIGl0J3MgYWxyZWFkeSBpbmNsdWRpbmcgaXRcbiAgICAgICggaXNCb3JkZXJCb3hTaXplT3V0ZXIgPyAwIDogcGFkZGluZ1dpZHRoICsgYm9yZGVyV2lkdGggKTtcbiAgfVxuXG4gIHZhciBzdHlsZUhlaWdodCA9IGdldFN0eWxlU2l6ZSggc3R5bGUuaGVpZ2h0ICk7XG4gIGlmICggc3R5bGVIZWlnaHQgIT09IGZhbHNlICkge1xuICAgIHNpemUuaGVpZ2h0ID0gc3R5bGVIZWlnaHQgK1xuICAgICAgLy8gYWRkIHBhZGRpbmcgYW5kIGJvcmRlciB1bmxlc3MgaXQncyBhbHJlYWR5IGluY2x1ZGluZyBpdFxuICAgICAgKCBpc0JvcmRlckJveFNpemVPdXRlciA/IDAgOiBwYWRkaW5nSGVpZ2h0ICsgYm9yZGVySGVpZ2h0ICk7XG4gIH1cblxuICBzaXplLmlubmVyV2lkdGggPSBzaXplLndpZHRoIC0gKCBwYWRkaW5nV2lkdGggKyBib3JkZXJXaWR0aCApO1xuICBzaXplLmlubmVySGVpZ2h0ID0gc2l6ZS5oZWlnaHQgLSAoIHBhZGRpbmdIZWlnaHQgKyBib3JkZXJIZWlnaHQgKTtcblxuICBzaXplLm91dGVyV2lkdGggPSBzaXplLndpZHRoICsgbWFyZ2luV2lkdGg7XG4gIHNpemUub3V0ZXJIZWlnaHQgPSBzaXplLmhlaWdodCArIG1hcmdpbkhlaWdodDtcblxuICByZXR1cm4gc2l6ZTtcbn1cblxucmV0dXJuIGdldFNpemU7XG5cbn0pO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2dldC1zaXplL2dldC1zaXplLmpzXG4vLyBtb2R1bGUgaWQgPSA1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImltcG9ydCB7IFF1ZXN0aW9uLCBRdWVzdGlvblNlbGVjdEJhc2UsIFF1ZXN0aW9uTWF0cml4TW9kZWwgfSBmcm9tIFwic3VydmV5LWNvcmVcIjtcbmltcG9ydCBDaGFydCBmcm9tIFwiY2hhcnQuanNcIjtcbmltcG9ydCB7IFZpc3VhbGl6YXRpb25NYW5hZ2VyIH0gZnJvbSBcIi4uL3Zpc3VhbGl6YXRpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBTZWxlY3RCYXNlIH0gZnJvbSBcIi4uL3NlbGVjdEJhc2VcIjtcblxuZXhwb3J0IGNsYXNzIFNlbGVjdEJhc2VDaGFydEpTIGV4dGVuZHMgU2VsZWN0QmFzZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHRhcmdldEVsZW1lbnQ6IEhUTUxFbGVtZW50LFxuICAgIHF1ZXN0aW9uOiBRdWVzdGlvbixcbiAgICBkYXRhOiBBcnJheTx7IFtpbmRleDogc3RyaW5nXTogYW55IH0+LFxuICAgIG9wdGlvbnM/OiBPYmplY3RcbiAgKSB7XG4gICAgc3VwZXIodGFyZ2V0RWxlbWVudCwgcXVlc3Rpb24sIGRhdGEsIG9wdGlvbnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGFydDogQ2hhcnQ7XG5cbiAgcHJvdGVjdGVkIGNoYXJ0VHlwZXMgPSBbXCJiYXJcIiwgXCJob3Jpem9udGFsQmFyXCIsIFwibGluZVwiLCBcInBpZVwiLCBcImRvdWdobnV0XCJdO1xuICBjaGFydFR5cGUgPSBcImhvcml6b250YWxCYXJcIjtcbiAgY2hhcnROb2RlID0gPEhUTUxDYW52YXNFbGVtZW50PmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIik7XG5cbiAgZGVzdHJveSgpIHtcbiAgICBpZiAoISF0aGlzLmNoYXJ0KSB7XG4gICAgICB0aGlzLmNoYXJ0LmRlc3Ryb3koKTtcbiAgICAgIHRoaXMuY2hhcnQgPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLnRhcmdldEVsZW1lbnQuaW5uZXJIVE1MID0gXCJcIjtcbiAgICB9XG4gIH1cblxuICB0b29sYmFyQ2hhbmdlSGFuZGxlciA9IChlOiBhbnkpID0+IHtcbiAgICBpZiAodGhpcy5jaGFydFR5cGUgIT09IGUudGFyZ2V0LnZhbHVlKSB7XG4gICAgICB0aGlzLmNoYXJ0VHlwZSA9IGUudGFyZ2V0LnZhbHVlO1xuICAgICAgdGhpcy5jaGFydC5kZXN0cm95KCk7XG4gICAgICB0aGlzLmNoYXJ0ID0gdGhpcy5nZXRDaGFydEpzKHRoaXMuY2hhcnROb2RlLCB0aGlzLmNoYXJ0VHlwZSk7XG4gICAgfVxuICB9O1xuXG4gIGNyZWF0ZUNoYXJ0KCkge1xuICAgIHRoaXMuY2hhcnQgPSB0aGlzLmdldENoYXJ0SnModGhpcy5jaGFydE5vZGUsIHRoaXMuY2hhcnRUeXBlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q2hhcnRKcyhjaGFydE5vZGU6IEhUTUxFbGVtZW50LCBjaGFydFR5cGU6IHN0cmluZyk6IENoYXJ0IHtcbiAgICBjb25zdCBjdHggPSAoPGFueT5jaGFydE5vZGUpLmdldENvbnRleHQoXCIyZFwiKTtcblxuICAgIHJldHVybiBuZXcgQ2hhcnQoY3R4LCB7XG4gICAgICB0eXBlOiBjaGFydFR5cGUsXG4gICAgICBkYXRhOiB7XG4gICAgICAgIGxhYmVsczogdGhpcy5nZXRMYWJlbHMoKSxcbiAgICAgICAgZGF0YXNldHM6IHRoaXMuZ2V0RGF0YXNldHMoKVxuICAgICAgfSxcbiAgICAgIG9wdGlvbnM6IHRoaXMuZ2V0T3B0aW9ucygpXG4gICAgfSk7XG4gIH1cblxuICBnZXRPcHRpb25zKCk6IENoYXJ0LkNoYXJ0T3B0aW9ucyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3BvbnNpdmU6IHRydWUsXG4gICAgICBtYWludGFpbkFzcGVjdFJhdGlvOiBmYWxzZSxcbiAgICAgIHNjYWxlczpcbiAgICAgICAgW1wicGllXCIsIFwiZG91Z2hudXRcIl0uaW5kZXhPZih0aGlzLmNoYXJ0VHlwZSkgIT09IC0xXG4gICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgeUF4ZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICB0aWNrczoge1xuICAgICAgICAgICAgICAgICAgICBiZWdpbkF0WmVybzogdHJ1ZVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfVxuICAgIH07XG4gIH1cblxuICBnZXREYXRhc2V0cygpOiBhbnlbXSB7XG4gICAgY29uc3QgcXVlc3Rpb246IFF1ZXN0aW9uTWF0cml4TW9kZWwgPSA8YW55PnRoaXMucXVlc3Rpb247XG4gICAgcmV0dXJuIFtcbiAgICAgIHtcbiAgICAgICAgbGFiZWw6IHF1ZXN0aW9uLnRpdGxlLFxuICAgICAgICBkYXRhOiB0aGlzLmdldERhdGEoKVswXSxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLmdldFZhbHVlcygpLm1hcChfID0+IHRoaXMuZ2V0UmFuZG9tQ29sb3IoKSlcbiAgICAgIH1cbiAgICBdO1xuICB9XG59XG5cbi8vIFZpc3VhbGl6YXRpb25NYW5hZ2VyLnJlZ2lzdGVyVmlzdWFsaXplcihcImNoZWNrYm94XCIsIFNlbGVjdEJhc2VDaGFydEpTKTtcbi8vIFZpc3VhbGl6YXRpb25NYW5hZ2VyLnJlZ2lzdGVyVmlzdWFsaXplcihcInJhZGlvZ3JvdXBcIiwgU2VsZWN0QmFzZUNoYXJ0SlMpO1xuLy8gVmlzdWFsaXphdGlvbk1hbmFnZXIucmVnaXN0ZXJWaXN1YWxpemVyKFwiZHJvcGRvd25cIiwgU2VsZWN0QmFzZUNoYXJ0SlMpO1xuLy8gVmlzdWFsaXphdGlvbk1hbmFnZXIucmVnaXN0ZXJWaXN1YWxpemVyKFwiaW1hZ2VwaWNrZXJcIiwgU2VsZWN0QmFzZUNoYXJ0SlMpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2NoYXJ0anMvc2VsZWN0QmFzZS50cyIsImltcG9ydCB7IFZpc3VhbGl6YXRpb25NYW5hZ2VyIH0gZnJvbSBcIi4vdmlzdWFsaXphdGlvbk1hbmFnZXJcIjtcbmltcG9ydCB7IFZpc3VhbGl6ZXJCYXNlIH0gZnJvbSBcIi4vdmlzdWFsaXplckJhc2VcIjtcbmltcG9ydCB7IFF1ZXN0aW9uLCBRdWVzdGlvblBhbmVsRHluYW1pY01vZGVsIH0gZnJvbSBcInN1cnZleS1jb3JlXCI7XG5pbXBvcnQgTWFzb25yeSBmcm9tIFwibWFzb25yeS1sYXlvdXRcIjtcbmltcG9ydCBcIi4vaW5kZXguc2Nzc1wiO1xuaW1wb3J0IHsgU2VsZWN0QmFzZSB9IGZyb20gXCIuL3NlbGVjdEJhc2VcIjtcblxuZXhwb3J0IGNsYXNzIFZpc3VhbGl6YXRpb25QYW5lbCB7XG4gIHByb3RlY3RlZCBmaWx0ZXJlZERhdGE6IEFycmF5PHsgW2luZGV4OiBzdHJpbmddOiBhbnkgfT47XG4gIHByb3RlY3RlZCBmaWx0ZXJWYWx1ZXM6IHsgW2luZGV4OiBzdHJpbmddOiBhbnkgfTtcbiAgcHJvdGVjdGVkIHZpc3VhbGl6ZXJzOiBBcnJheTxWaXN1YWxpemVyQmFzZT4gPSBbXTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgcHJvdGVjdGVkIHF1ZXN0aW9uczogQXJyYXk8YW55PixcbiAgICBwcm90ZWN0ZWQgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgICBwcm90ZWN0ZWQgb3B0aW9ucz86IE9iamVjdFxuICApIHtcbiAgICB0aGlzLmZpbHRlcmVkRGF0YSA9IGRhdGE7XG4gIH1cblxuICByZW5kZXIoKSB7XG4gICAgY29uc3QgZ3JpZFNpemVyQ2xhc3NOYW1lID0gXCJzdmEtZ3JpZF9fZ3JpZC1zaXplclwiO1xuICAgIGNvbnN0IHF1ZXN0aW9uRWxlbWVudENsYXNzTmFtZSA9IFwic3ZhLXF1ZXN0aW9uXCI7XG4gICAgbGV0IG1zbnJ5OiBhbnkgPSB1bmRlZmluZWQ7XG4gICAgbGV0IGdldE1hc29ucnkgPSAoKSA9PiBtc25yeTtcblxuICAgIGNvbnN0IGdyaWRTaXplciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7IC8vTWFzb25yeSBncmlkU2l6ZXIgZW1wdHkgZWxlbWVudCwgb25seSB1c2VkIGZvciBlbGVtZW50IHNpemluZ1xuXG4gICAgdGhpcy50YXJnZXRFbGVtZW50LmNsYXNzTmFtZSA9IFwic3ZhLWdyaWRcIjtcbiAgICBncmlkU2l6ZXIuY2xhc3NOYW1lID0gZ3JpZFNpemVyQ2xhc3NOYW1lO1xuICAgIHRoaXMudGFyZ2V0RWxlbWVudC5hcHBlbmRDaGlsZChncmlkU2l6ZXIpO1xuXG4gICAgdGhpcy5xdWVzdGlvbnMuZm9yRWFjaChxdWVzdGlvbiA9PiB7XG4gICAgICBjb25zdCBxdWVzdGlvbkVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgY29uc3QgcXVlc3Rpb25Db250ZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgIGNvbnN0IHRpdGxlRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJoM1wiKTtcbiAgICAgIGNvbnN0IHZpenVhbGl6ZXJFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcblxuICAgICAgdGl0bGVFbGVtZW50LmlubmVyVGV4dCA9ICg8YW55PnF1ZXN0aW9uKVtcInRpdGxlXCJdO1xuXG4gICAgICBxdWVzdGlvbkVsZW1lbnQuY2xhc3NOYW1lID0gcXVlc3Rpb25FbGVtZW50Q2xhc3NOYW1lO1xuICAgICAgcXVlc3Rpb25Db250ZW50LmNsYXNzTmFtZSA9IHF1ZXN0aW9uRWxlbWVudENsYXNzTmFtZSArIFwiX19jb250ZW50XCI7XG4gICAgICB0aXRsZUVsZW1lbnQuY2xhc3NOYW1lID0gcXVlc3Rpb25FbGVtZW50Q2xhc3NOYW1lICsgXCJfX3RpdGxlXCI7XG5cbiAgICAgIHF1ZXN0aW9uQ29udGVudC5hcHBlbmRDaGlsZCh0aXRsZUVsZW1lbnQpO1xuICAgICAgcXVlc3Rpb25Db250ZW50LmFwcGVuZENoaWxkKHZpenVhbGl6ZXJFbGVtZW50KTtcbiAgICAgIHF1ZXN0aW9uRWxlbWVudC5hcHBlbmRDaGlsZChxdWVzdGlvbkNvbnRlbnQpO1xuICAgICAgdGhpcy50YXJnZXRFbGVtZW50LmFwcGVuZENoaWxkKHF1ZXN0aW9uRWxlbWVudCk7XG5cbiAgICAgIGNvbnN0IHZpc3VhbGl6ZXIgPSB0aGlzLnJlbmRlclF1ZXN0aW9uKFxuICAgICAgICB2aXp1YWxpemVyRWxlbWVudCxcbiAgICAgICAgcXVlc3Rpb24sXG4gICAgICAgIHRoaXMuZmlsdGVyZWREYXRhXG4gICAgICApO1xuXG4gICAgICB2aXN1YWxpemVyLm9uVXBkYXRlID0gKCkgPT4ge1xuICAgICAgICBpZiAoZ2V0TWFzb25yeSgpKSB7XG4gICAgICAgICAgZ2V0TWFzb25yeSgpLmxheW91dCgpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaWYgKHZpc3VhbGl6ZXIgaW5zdGFuY2VvZiBTZWxlY3RCYXNlKSB7XG4gICAgICAgIHZpc3VhbGl6ZXIub25EYXRhSXRlbVNlbGVjdGVkID0gKFxuICAgICAgICAgIHNlbGVjdGVkVmFsdWU6IGFueSxcbiAgICAgICAgICBjbGVhclNlbGVjdGlvbjogYm9vbGVhblxuICAgICAgICApID0+IHtcbiAgICAgICAgICB0aGlzLmFwcGx5RmlsdGVyKHF1ZXN0aW9uLm5hbWUsIHNlbGVjdGVkVmFsdWUsIGNsZWFyU2VsZWN0aW9uKTtcbiAgICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgdGhpcy52aXN1YWxpemVycy5wdXNoKHZpc3VhbGl6ZXIpO1xuICAgIH0pO1xuXG4gICAgbXNucnkgPSBuZXcgTWFzb25yeSh0aGlzLnRhcmdldEVsZW1lbnQsIHtcbiAgICAgIGNvbHVtbldpZHRoOiBcIi5cIiArIGdyaWRTaXplckNsYXNzTmFtZSxcbiAgICAgIGl0ZW1TZWxlY3RvcjogXCIuXCIgKyBxdWVzdGlvbkVsZW1lbnRDbGFzc05hbWVcbiAgICB9KTtcbiAgfVxuXG4gIGRlc3Ryb3koKSB7XG4gICAgdGhpcy50YXJnZXRFbGVtZW50LmlubmVySFRNTCA9IFwiXCI7XG4gICAgdGhpcy52aXN1YWxpemVycy5mb3JFYWNoKHZpc3VhbGl6ZXIgPT4ge1xuICAgICAgdmlzdWFsaXplci5vblVwZGF0ZSA9IHVuZGVmaW5lZDtcbiAgICAgIGlmICh2aXN1YWxpemVyIGluc3RhbmNlb2YgU2VsZWN0QmFzZSkge1xuICAgICAgICB2aXN1YWxpemVyLm9uRGF0YUl0ZW1TZWxlY3RlZCA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHZpc3VhbGl6ZXIuZGVzdHJveSgpO1xuICAgIH0pO1xuICAgIHRoaXMudmlzdWFsaXplcnMgPSBbXTtcbiAgfVxuXG4gIHVwZGF0ZSgpIHtcbiAgICB0aGlzLnZpc3VhbGl6ZXJzLmZvckVhY2godmlzdWFsaXplciA9PlxuICAgICAgc2V0VGltZW91dCgoKSA9PiB2aXN1YWxpemVyLnVwZGF0ZSh0aGlzLmZpbHRlcmVkRGF0YSksIDEwKVxuICAgICk7XG4gIH1cblxuICBhcHBseUZpbHRlcihcbiAgICBxdWVzdGlvbk5hbWU6IHN0cmluZyxcbiAgICBzZWxlY3RlZFZhbHVlOiBhbnksXG4gICAgY2xlYXJTZWxlY3Rpb246IGJvb2xlYW4gPSB0cnVlXG4gICkge1xuICAgIGlmIChjbGVhclNlbGVjdGlvbikge1xuICAgICAgdGhpcy5maWx0ZXJWYWx1ZXMgPSA8YW55Pnt9O1xuICAgIH1cbiAgICBpZiAoc2VsZWN0ZWRWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmZpbHRlclZhbHVlc1txdWVzdGlvbk5hbWVdID0gc2VsZWN0ZWRWYWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVsZXRlIHRoaXMuZmlsdGVyVmFsdWVzW3F1ZXN0aW9uTmFtZV07XG4gICAgfVxuICAgIHRoaXMuZmlsdGVyZWREYXRhID0gdGhpcy5kYXRhLmZpbHRlcihpdGVtID0+IHtcbiAgICAgIHJldHVybiAhT2JqZWN0LmtleXModGhpcy5maWx0ZXJWYWx1ZXMpLnNvbWUoXG4gICAgICAgIGtleSA9PiBpdGVtW2tleV0gIT09IHRoaXMuZmlsdGVyVmFsdWVzW2tleV1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICByZW5kZXJRdWVzdGlvbihcbiAgICB2aXp1YWxpemVyRWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgcXVlc3Rpb246IFF1ZXN0aW9uLFxuICAgIGRhdGE6IEFycmF5PHsgW2luZGV4OiBzdHJpbmddOiBhbnkgfT5cbiAgKSB7XG4gICAgdmFyIHZpc3VhbGl6ZXJzID0gVmlzdWFsaXphdGlvbk1hbmFnZXIuZ2V0VmlzdWFsaXplcnMocXVlc3Rpb24uZ2V0VHlwZSgpKTtcbiAgICB2YXIgdmlzdWFsaXplciA9IG5ldyB2aXN1YWxpemVyc1swXSh2aXp1YWxpemVyRWxlbWVudCwgcXVlc3Rpb24sIGRhdGEpO1xuICAgIHZpc3VhbGl6ZXIucmVuZGVyKCk7XG4gICAgcmV0dXJuIHZpc3VhbGl6ZXI7XG4gIH1cbn1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy92aXN1YWxpemF0aW9uUGFuZWwudHMiLCJpbXBvcnQgeyBWaXN1YWxpemVyQmFzZSB9IGZyb20gXCIuL3Zpc3VhbGl6ZXJCYXNlXCI7XG5pbXBvcnQgeyBWaXN1YWxpemF0aW9uTWFuYWdlciB9IGZyb20gXCIuL3Zpc3VhbGl6YXRpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBWaXN1YWxpemF0aW9uUGFuZWwgfSBmcm9tIFwiLi92aXN1YWxpemF0aW9uUGFuZWxcIjtcbmltcG9ydCB7IFF1ZXN0aW9uLCBRdWVzdGlvblBhbmVsRHluYW1pY01vZGVsIH0gZnJvbSBcInN1cnZleS1jb3JlXCI7XG5cbmV4cG9ydCBjbGFzcyBWaXN1YWxpemF0aW9uUGFuZWxEeW5hbWljIGV4dGVuZHMgVmlzdWFsaXplckJhc2Uge1xuICBjb25zdHJ1Y3RvcihcbiAgICB0YXJnZXROb2RlOiBIVE1MRWxlbWVudCxcbiAgICBxdWVzdGlvbjogUXVlc3Rpb24sXG4gICAgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgICBvcHRpb25zPzogT2JqZWN0XG4gICkge1xuICAgIHN1cGVyKHRhcmdldE5vZGUsIHF1ZXN0aW9uLCBkYXRhLCBvcHRpb25zKTtcbiAgICB0aGlzLmRhdGEgPSBbXTtcbiAgICBkYXRhLmZvckVhY2goXG4gICAgICBkYXRhSXRlbSA9PlxuICAgICAgICAhIWRhdGFJdGVtW3F1ZXN0aW9uLm5hbWVdICYmXG4gICAgICAgICh0aGlzLmRhdGEgPSB0aGlzLmRhdGEuY29uY2F0KGRhdGFJdGVtW3F1ZXN0aW9uLm5hbWVdKSlcbiAgICApO1xuICB9XG5cbiAgZ2V0UXVlc3Rpb25zKCkge1xuICAgIGNvbnN0IHBhbmVsZHluYW1pYzogUXVlc3Rpb25QYW5lbER5bmFtaWNNb2RlbCA9IDxhbnk+dGhpcy5xdWVzdGlvbjtcbiAgICByZXR1cm4gcGFuZWxkeW5hbWljLnBhbmVsc1swXS5xdWVzdGlvbnM7XG4gIH1cblxuICByZW5kZXIoKSB7XG4gICAgdmFyIHZpc1BhbmVsID0gbmV3IFZpc3VhbGl6YXRpb25QYW5lbChcbiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic3VtbWFyeUNvbnRhaW5lclwiKSxcbiAgICAgIHRoaXMuZ2V0UXVlc3Rpb25zKCksXG4gICAgICB0aGlzLmRhdGFcbiAgICApO1xuICAgIHZpc1BhbmVsLnJlbmRlcigpO1xuICB9XG5cbiAgZGVzdHJveSgpIHtcbiAgICB0aGlzLnRhcmdldEVsZW1lbnQuaW5uZXJIVE1MID0gXCJcIjtcbiAgfVxufVxuXG5WaXN1YWxpemF0aW9uTWFuYWdlci5yZWdpc3RlclZpc3VhbGl6ZXIoXG4gIFwicGFuZWxkeW5hbWljXCIsXG4gIFZpc3VhbGl6YXRpb25QYW5lbER5bmFtaWNcbik7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvdmlzdWFsaXphdGlvblBhbmVsRHluYW1pYy50cyIsImltcG9ydCB7IHN0b3BXb3JkcyB9IGZyb20gXCIuL2VuZ2xpc2hcIjtcblxudmFyIHN0b3BXb3Jkc0RpY3Rpb25hcnk6IHsgW2luZGV4OiBzdHJpbmddOiBBcnJheTxzdHJpbmc+IH0gPSB7fTtcbnN0b3BXb3Jkc0RpY3Rpb25hcnlbXCJlblwiXSA9IHN0b3BXb3JkcztcblxuZXhwb3J0IHZhciB0ZXh0SGVscGVyID0ge1xuICBnZXRTdG9wV29yZHM6IChsb2NhbGU6IHN0cmluZyA9IFwiXCIpID0+IHtcbiAgICByZXR1cm4gc3RvcFdvcmRzRGljdGlvbmFyeVtsb2NhbGUgfHwgXCJlblwiXSB8fCBbXTtcbiAgfVxufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy93b3JkY2xvdWQvc3RvcHdvcmRzL2luZGV4LnRzIiwiLyoqXG4gKiBFdkVtaXR0ZXIgdjEuMS4wXG4gKiBMaWwnIGV2ZW50IGVtaXR0ZXJcbiAqIE1JVCBMaWNlbnNlXG4gKi9cblxuLyoganNoaW50IHVudXNlZDogdHJ1ZSwgdW5kZWY6IHRydWUsIHN0cmljdDogdHJ1ZSAqL1xuXG4oIGZ1bmN0aW9uKCBnbG9iYWwsIGZhY3RvcnkgKSB7XG4gIC8vIHVuaXZlcnNhbCBtb2R1bGUgZGVmaW5pdGlvblxuICAvKiBqc2hpbnQgc3RyaWN0OiBmYWxzZSAqLyAvKiBnbG9iYWxzIGRlZmluZSwgbW9kdWxlLCB3aW5kb3cgKi9cbiAgaWYgKCB0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCApIHtcbiAgICAvLyBBTUQgLSBSZXF1aXJlSlNcbiAgICBkZWZpbmUoIGZhY3RvcnkgKTtcbiAgfSBlbHNlIGlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgICAvLyBDb21tb25KUyAtIEJyb3dzZXJpZnksIFdlYnBhY2tcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBCcm93c2VyIGdsb2JhbHNcbiAgICBnbG9iYWwuRXZFbWl0dGVyID0gZmFjdG9yeSgpO1xuICB9XG5cbn0oIHR5cGVvZiB3aW5kb3cgIT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0aGlzLCBmdW5jdGlvbigpIHtcblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmZ1bmN0aW9uIEV2RW1pdHRlcigpIHt9XG5cbnZhciBwcm90byA9IEV2RW1pdHRlci5wcm90b3R5cGU7XG5cbnByb3RvLm9uID0gZnVuY3Rpb24oIGV2ZW50TmFtZSwgbGlzdGVuZXIgKSB7XG4gIGlmICggIWV2ZW50TmFtZSB8fCAhbGlzdGVuZXIgKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIHNldCBldmVudHMgaGFzaFxuICB2YXIgZXZlbnRzID0gdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICAvLyBzZXQgbGlzdGVuZXJzIGFycmF5XG4gIHZhciBsaXN0ZW5lcnMgPSBldmVudHNbIGV2ZW50TmFtZSBdID0gZXZlbnRzWyBldmVudE5hbWUgXSB8fCBbXTtcbiAgLy8gb25seSBhZGQgb25jZVxuICBpZiAoIGxpc3RlbmVycy5pbmRleE9mKCBsaXN0ZW5lciApID09IC0xICkge1xuICAgIGxpc3RlbmVycy5wdXNoKCBsaXN0ZW5lciApO1xuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5wcm90by5vbmNlID0gZnVuY3Rpb24oIGV2ZW50TmFtZSwgbGlzdGVuZXIgKSB7XG4gIGlmICggIWV2ZW50TmFtZSB8fCAhbGlzdGVuZXIgKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIGFkZCBldmVudFxuICB0aGlzLm9uKCBldmVudE5hbWUsIGxpc3RlbmVyICk7XG4gIC8vIHNldCBvbmNlIGZsYWdcbiAgLy8gc2V0IG9uY2VFdmVudHMgaGFzaFxuICB2YXIgb25jZUV2ZW50cyA9IHRoaXMuX29uY2VFdmVudHMgPSB0aGlzLl9vbmNlRXZlbnRzIHx8IHt9O1xuICAvLyBzZXQgb25jZUxpc3RlbmVycyBvYmplY3RcbiAgdmFyIG9uY2VMaXN0ZW5lcnMgPSBvbmNlRXZlbnRzWyBldmVudE5hbWUgXSA9IG9uY2VFdmVudHNbIGV2ZW50TmFtZSBdIHx8IHt9O1xuICAvLyBzZXQgZmxhZ1xuICBvbmNlTGlzdGVuZXJzWyBsaXN0ZW5lciBdID0gdHJ1ZTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbnByb3RvLm9mZiA9IGZ1bmN0aW9uKCBldmVudE5hbWUsIGxpc3RlbmVyICkge1xuICB2YXIgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzICYmIHRoaXMuX2V2ZW50c1sgZXZlbnROYW1lIF07XG4gIGlmICggIWxpc3RlbmVycyB8fCAhbGlzdGVuZXJzLmxlbmd0aCApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIGluZGV4ID0gbGlzdGVuZXJzLmluZGV4T2YoIGxpc3RlbmVyICk7XG4gIGlmICggaW5kZXggIT0gLTEgKSB7XG4gICAgbGlzdGVuZXJzLnNwbGljZSggaW5kZXgsIDEgKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxucHJvdG8uZW1pdEV2ZW50ID0gZnVuY3Rpb24oIGV2ZW50TmFtZSwgYXJncyApIHtcbiAgdmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50cyAmJiB0aGlzLl9ldmVudHNbIGV2ZW50TmFtZSBdO1xuICBpZiAoICFsaXN0ZW5lcnMgfHwgIWxpc3RlbmVycy5sZW5ndGggKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIGNvcHkgb3ZlciB0byBhdm9pZCBpbnRlcmZlcmVuY2UgaWYgLm9mZigpIGluIGxpc3RlbmVyXG4gIGxpc3RlbmVycyA9IGxpc3RlbmVycy5zbGljZSgwKTtcbiAgYXJncyA9IGFyZ3MgfHwgW107XG4gIC8vIG9uY2Ugc3R1ZmZcbiAgdmFyIG9uY2VMaXN0ZW5lcnMgPSB0aGlzLl9vbmNlRXZlbnRzICYmIHRoaXMuX29uY2VFdmVudHNbIGV2ZW50TmFtZSBdO1xuXG4gIGZvciAoIHZhciBpPTA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKysgKSB7XG4gICAgdmFyIGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldXG4gICAgdmFyIGlzT25jZSA9IG9uY2VMaXN0ZW5lcnMgJiYgb25jZUxpc3RlbmVyc1sgbGlzdGVuZXIgXTtcbiAgICBpZiAoIGlzT25jZSApIHtcbiAgICAgIC8vIHJlbW92ZSBsaXN0ZW5lclxuICAgICAgLy8gcmVtb3ZlIGJlZm9yZSB0cmlnZ2VyIHRvIHByZXZlbnQgcmVjdXJzaW9uXG4gICAgICB0aGlzLm9mZiggZXZlbnROYW1lLCBsaXN0ZW5lciApO1xuICAgICAgLy8gdW5zZXQgb25jZSBmbGFnXG4gICAgICBkZWxldGUgb25jZUxpc3RlbmVyc1sgbGlzdGVuZXIgXTtcbiAgICB9XG4gICAgLy8gdHJpZ2dlciBsaXN0ZW5lclxuICAgIGxpc3RlbmVyLmFwcGx5KCB0aGlzLCBhcmdzICk7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbnByb3RvLmFsbE9mZiA9IGZ1bmN0aW9uKCkge1xuICBkZWxldGUgdGhpcy5fZXZlbnRzO1xuICBkZWxldGUgdGhpcy5fb25jZUV2ZW50cztcbn07XG5cbnJldHVybiBFdkVtaXR0ZXI7XG5cbn0pKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9ldi1lbWl0dGVyL2V2LWVtaXR0ZXIuanNcbi8vIG1vZHVsZSBpZCA9IDEwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qKlxuKiBwbG90bHkuanMgdjEuNDkuMVxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlXG4qL1xuKGZ1bmN0aW9uKGYpe2lmKHR5cGVvZiBleHBvcnRzPT09XCJvYmplY3RcIiYmdHlwZW9mIG1vZHVsZSE9PVwidW5kZWZpbmVkXCIpe21vZHVsZS5leHBvcnRzPWYoKX1lbHNlIGlmKHR5cGVvZiBkZWZpbmU9PT1cImZ1bmN0aW9uXCImJmRlZmluZS5hbWQpe2RlZmluZShbXSxmKX1lbHNle3ZhciBnO2lmKHR5cGVvZiB3aW5kb3chPT1cInVuZGVmaW5lZFwiKXtnPXdpbmRvd31lbHNlIGlmKHR5cGVvZiBnbG9iYWwhPT1cInVuZGVmaW5lZFwiKXtnPWdsb2JhbH1lbHNlIGlmKHR5cGVvZiBzZWxmIT09XCJ1bmRlZmluZWRcIil7Zz1zZWxmfWVsc2V7Zz10aGlzfWcuUGxvdGx5ID0gZigpfX0pKGZ1bmN0aW9uKCl7dmFyIGRlZmluZSxtb2R1bGUsZXhwb3J0cztyZXR1cm4gKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSh7MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9zcmMvbGliJyk7XG52YXIgcnVsZXMgPSB7XG4gICAgXCJYLFggZGl2XCI6IFwiZGlyZWN0aW9uOmx0cjtmb250LWZhbWlseTonT3BlbiBTYW5zJywgdmVyZGFuYSwgYXJpYWwsIHNhbnMtc2VyaWY7bWFyZ2luOjA7cGFkZGluZzowO1wiLFxuICAgIFwiWCBpbnB1dCxYIGJ1dHRvblwiOiBcImZvbnQtZmFtaWx5OidPcGVuIFNhbnMnLCB2ZXJkYW5hLCBhcmlhbCwgc2Fucy1zZXJpZjtcIixcbiAgICBcIlggaW5wdXQ6Zm9jdXMsWCBidXR0b246Zm9jdXNcIjogXCJvdXRsaW5lOm5vbmU7XCIsXG4gICAgXCJYIGFcIjogXCJ0ZXh0LWRlY29yYXRpb246bm9uZTtcIixcbiAgICBcIlggYTpob3ZlclwiOiBcInRleHQtZGVjb3JhdGlvbjpub25lO1wiLFxuICAgIFwiWCAuY3Jpc3BcIjogXCJzaGFwZS1yZW5kZXJpbmc6Y3Jpc3BFZGdlcztcIixcbiAgICBcIlggLnVzZXItc2VsZWN0LW5vbmVcIjogXCItd2Via2l0LXVzZXItc2VsZWN0Om5vbmU7LW1vei11c2VyLXNlbGVjdDpub25lOy1tcy11c2VyLXNlbGVjdDpub25lOy1vLXVzZXItc2VsZWN0Om5vbmU7dXNlci1zZWxlY3Q6bm9uZTtcIixcbiAgICBcIlggc3ZnXCI6IFwib3ZlcmZsb3c6aGlkZGVuO1wiLFxuICAgIFwiWCBzdmcgYVwiOiBcImZpbGw6IzQ0N2FkYjtcIixcbiAgICBcIlggc3ZnIGE6aG92ZXJcIjogXCJmaWxsOiMzYzZkYzU7XCIsXG4gICAgXCJYIC5tYWluLXN2Z1wiOiBcInBvc2l0aW9uOmFic29sdXRlO3RvcDowO2xlZnQ6MDtwb2ludGVyLWV2ZW50czpub25lO1wiLFxuICAgIFwiWCAubWFpbi1zdmcgLmRyYWdsYXllclwiOiBcInBvaW50ZXItZXZlbnRzOmFsbDtcIixcbiAgICBcIlggLmN1cnNvci1kZWZhdWx0XCI6IFwiY3Vyc29yOmRlZmF1bHQ7XCIsXG4gICAgXCJYIC5jdXJzb3ItcG9pbnRlclwiOiBcImN1cnNvcjpwb2ludGVyO1wiLFxuICAgIFwiWCAuY3Vyc29yLWNyb3NzaGFpclwiOiBcImN1cnNvcjpjcm9zc2hhaXI7XCIsXG4gICAgXCJYIC5jdXJzb3ItbW92ZVwiOiBcImN1cnNvcjptb3ZlO1wiLFxuICAgIFwiWCAuY3Vyc29yLWNvbC1yZXNpemVcIjogXCJjdXJzb3I6Y29sLXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci1yb3ctcmVzaXplXCI6IFwiY3Vyc29yOnJvdy1yZXNpemU7XCIsXG4gICAgXCJYIC5jdXJzb3ItbnMtcmVzaXplXCI6IFwiY3Vyc29yOm5zLXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci1ldy1yZXNpemVcIjogXCJjdXJzb3I6ZXctcmVzaXplO1wiLFxuICAgIFwiWCAuY3Vyc29yLXN3LXJlc2l6ZVwiOiBcImN1cnNvcjpzdy1yZXNpemU7XCIsXG4gICAgXCJYIC5jdXJzb3Itcy1yZXNpemVcIjogXCJjdXJzb3I6cy1yZXNpemU7XCIsXG4gICAgXCJYIC5jdXJzb3Itc2UtcmVzaXplXCI6IFwiY3Vyc29yOnNlLXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci13LXJlc2l6ZVwiOiBcImN1cnNvcjp3LXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci1lLXJlc2l6ZVwiOiBcImN1cnNvcjplLXJlc2l6ZTtcIixcbiAgICBcIlggLmN1cnNvci1udy1yZXNpemVcIjogXCJjdXJzb3I6bnctcmVzaXplO1wiLFxuICAgIFwiWCAuY3Vyc29yLW4tcmVzaXplXCI6IFwiY3Vyc29yOm4tcmVzaXplO1wiLFxuICAgIFwiWCAuY3Vyc29yLW5lLXJlc2l6ZVwiOiBcImN1cnNvcjpuZS1yZXNpemU7XCIsXG4gICAgXCJYIC5jdXJzb3ItZ3JhYlwiOiBcImN1cnNvcjotd2Via2l0LWdyYWI7Y3Vyc29yOmdyYWI7XCIsXG4gICAgXCJYIC5tb2RlYmFyXCI6IFwicG9zaXRpb246YWJzb2x1dGU7dG9wOjJweDtyaWdodDoycHg7XCIsXG4gICAgXCJYIC5lYXNlLWJnXCI6IFwiLXdlYmtpdC10cmFuc2l0aW9uOmJhY2tncm91bmQtY29sb3IgMC4zcyBlYXNlIDBzOy1tb3otdHJhbnNpdGlvbjpiYWNrZ3JvdW5kLWNvbG9yIDAuM3MgZWFzZSAwczstbXMtdHJhbnNpdGlvbjpiYWNrZ3JvdW5kLWNvbG9yIDAuM3MgZWFzZSAwczstby10cmFuc2l0aW9uOmJhY2tncm91bmQtY29sb3IgMC4zcyBlYXNlIDBzO3RyYW5zaXRpb246YmFja2dyb3VuZC1jb2xvciAwLjNzIGVhc2UgMHM7XCIsXG4gICAgXCJYIC5tb2RlYmFyLS1ob3Zlcj46bm90KC53YXRlcm1hcmspXCI6IFwib3BhY2l0eTowOy13ZWJraXQtdHJhbnNpdGlvbjpvcGFjaXR5IDAuM3MgZWFzZSAwczstbW96LXRyYW5zaXRpb246b3BhY2l0eSAwLjNzIGVhc2UgMHM7LW1zLXRyYW5zaXRpb246b3BhY2l0eSAwLjNzIGVhc2UgMHM7LW8tdHJhbnNpdGlvbjpvcGFjaXR5IDAuM3MgZWFzZSAwczt0cmFuc2l0aW9uOm9wYWNpdHkgMC4zcyBlYXNlIDBzO1wiLFxuICAgIFwiWDpob3ZlciAubW9kZWJhci0taG92ZXIgLm1vZGViYXItZ3JvdXBcIjogXCJvcGFjaXR5OjE7XCIsXG4gICAgXCJYIC5tb2RlYmFyLWdyb3VwXCI6IFwiZmxvYXQ6bGVmdDtkaXNwbGF5OmlubGluZS1ibG9jaztib3gtc2l6aW5nOmJvcmRlci1ib3g7cGFkZGluZy1sZWZ0OjhweDtwb3NpdGlvbjpyZWxhdGl2ZTt2ZXJ0aWNhbC1hbGlnbjptaWRkbGU7d2hpdGUtc3BhY2U6bm93cmFwO1wiLFxuICAgIFwiWCAubW9kZWJhci1idG5cIjogXCJwb3NpdGlvbjpyZWxhdGl2ZTtmb250LXNpemU6MTZweDtwYWRkaW5nOjNweCA0cHg7aGVpZ2h0OjIycHg7Y3Vyc29yOnBvaW50ZXI7bGluZS1oZWlnaHQ6bm9ybWFsO2JveC1zaXppbmc6Ym9yZGVyLWJveDtcIixcbiAgICBcIlggLm1vZGViYXItYnRuIHN2Z1wiOiBcInBvc2l0aW9uOnJlbGF0aXZlO3RvcDoycHg7XCIsXG4gICAgXCJYIC5tb2RlYmFyLnZlcnRpY2FsXCI6IFwiZGlzcGxheTpmbGV4O2ZsZXgtZGlyZWN0aW9uOmNvbHVtbjtmbGV4LXdyYXA6d3JhcDthbGlnbi1jb250ZW50OmZsZXgtZW5kO21heC1oZWlnaHQ6MTAwJTtcIixcbiAgICBcIlggLm1vZGViYXIudmVydGljYWwgc3ZnXCI6IFwidG9wOi0xcHg7XCIsXG4gICAgXCJYIC5tb2RlYmFyLnZlcnRpY2FsIC5tb2RlYmFyLWdyb3VwXCI6IFwiZGlzcGxheTpibG9jaztmbG9hdDpub25lO3BhZGRpbmctbGVmdDowcHg7cGFkZGluZy1ib3R0b206OHB4O1wiLFxuICAgIFwiWCAubW9kZWJhci52ZXJ0aWNhbCAubW9kZWJhci1ncm91cCAubW9kZWJhci1idG5cIjogXCJkaXNwbGF5OmJsb2NrO3RleHQtYWxpZ246Y2VudGVyO1wiLFxuICAgIFwiWCBbZGF0YS10aXRsZV06YmVmb3JlLFggW2RhdGEtdGl0bGVdOmFmdGVyXCI6IFwicG9zaXRpb246YWJzb2x1dGU7LXdlYmtpdC10cmFuc2Zvcm06dHJhbnNsYXRlM2QoMCwgMCwgMCk7LW1vei10cmFuc2Zvcm06dHJhbnNsYXRlM2QoMCwgMCwgMCk7LW1zLXRyYW5zZm9ybTp0cmFuc2xhdGUzZCgwLCAwLCAwKTstby10cmFuc2Zvcm06dHJhbnNsYXRlM2QoMCwgMCwgMCk7dHJhbnNmb3JtOnRyYW5zbGF0ZTNkKDAsIDAsIDApO2Rpc3BsYXk6bm9uZTtvcGFjaXR5OjA7ei1pbmRleDoxMDAxO3BvaW50ZXItZXZlbnRzOm5vbmU7dG9wOjExMCU7cmlnaHQ6NTAlO1wiLFxuICAgIFwiWCBbZGF0YS10aXRsZV06aG92ZXI6YmVmb3JlLFggW2RhdGEtdGl0bGVdOmhvdmVyOmFmdGVyXCI6IFwiZGlzcGxheTpibG9jaztvcGFjaXR5OjE7XCIsXG4gICAgXCJYIFtkYXRhLXRpdGxlXTpiZWZvcmVcIjogXCJjb250ZW50OicnO3Bvc2l0aW9uOmFic29sdXRlO2JhY2tncm91bmQ6dHJhbnNwYXJlbnQ7Ym9yZGVyOjZweCBzb2xpZCB0cmFuc3BhcmVudDt6LWluZGV4OjEwMDI7bWFyZ2luLXRvcDotMTJweDtib3JkZXItYm90dG9tLWNvbG9yOiM2OTczOGE7bWFyZ2luLXJpZ2h0Oi02cHg7XCIsXG4gICAgXCJYIFtkYXRhLXRpdGxlXTphZnRlclwiOiBcImNvbnRlbnQ6YXR0cihkYXRhLXRpdGxlKTtiYWNrZ3JvdW5kOiM2OTczOGE7Y29sb3I6d2hpdGU7cGFkZGluZzo4cHggMTBweDtmb250LXNpemU6MTJweDtsaW5lLWhlaWdodDoxMnB4O3doaXRlLXNwYWNlOm5vd3JhcDttYXJnaW4tcmlnaHQ6LTE4cHg7Ym9yZGVyLXJhZGl1czoycHg7XCIsXG4gICAgXCJYIC52ZXJ0aWNhbCBbZGF0YS10aXRsZV06YmVmb3JlLFggLnZlcnRpY2FsIFtkYXRhLXRpdGxlXTphZnRlclwiOiBcInRvcDowJTtyaWdodDoyMDAlO1wiLFxuICAgIFwiWCAudmVydGljYWwgW2RhdGEtdGl0bGVdOmJlZm9yZVwiOiBcImJvcmRlcjo2cHggc29saWQgdHJhbnNwYXJlbnQ7Ym9yZGVyLWxlZnQtY29sb3I6IzY5NzM4YTttYXJnaW4tdG9wOjhweDttYXJnaW4tcmlnaHQ6LTMwcHg7XCIsXG4gICAgXCJYIC5zZWxlY3Qtb3V0bGluZVwiOiBcImZpbGw6bm9uZTtzdHJva2Utd2lkdGg6MTtzaGFwZS1yZW5kZXJpbmc6Y3Jpc3BFZGdlcztcIixcbiAgICBcIlggLnNlbGVjdC1vdXRsaW5lLTFcIjogXCJzdHJva2U6d2hpdGU7XCIsXG4gICAgXCJYIC5zZWxlY3Qtb3V0bGluZS0yXCI6IFwic3Ryb2tlOmJsYWNrO3N0cm9rZS1kYXNoYXJyYXk6MnB4IDJweDtcIixcbiAgICBZOiBcImZvbnQtZmFtaWx5OidPcGVuIFNhbnMnO3Bvc2l0aW9uOmZpeGVkO3RvcDo1MHB4O3JpZ2h0OjIwcHg7ei1pbmRleDoxMDAwMDtmb250LXNpemU6MTBwdDttYXgtd2lkdGg6MTgwcHg7XCIsXG4gICAgXCJZIHBcIjogXCJtYXJnaW46MDtcIixcbiAgICBcIlkgLm5vdGlmaWVyLW5vdGVcIjogXCJtaW4td2lkdGg6MTgwcHg7bWF4LXdpZHRoOjI1MHB4O2JvcmRlcjoxcHggc29saWQgI2ZmZjt6LWluZGV4OjMwMDA7bWFyZ2luOjA7YmFja2dyb3VuZC1jb2xvcjojOGM5N2FmO2JhY2tncm91bmQtY29sb3I6cmdiYSgxNDAsMTUxLDE3NSwwLjkpO2NvbG9yOiNmZmY7cGFkZGluZzoxMHB4O292ZXJmbG93LXdyYXA6YnJlYWstd29yZDt3b3JkLXdyYXA6YnJlYWstd29yZDstbXMtaHlwaGVuczphdXRvOy13ZWJraXQtaHlwaGVuczphdXRvO2h5cGhlbnM6YXV0bztcIixcbiAgICBcIlkgLm5vdGlmaWVyLWNsb3NlXCI6IFwiY29sb3I6I2ZmZjtvcGFjaXR5OjAuODtmbG9hdDpyaWdodDtwYWRkaW5nOjAgNXB4O2JhY2tncm91bmQ6bm9uZTtib3JkZXI6bm9uZTtmb250LXNpemU6MjBweDtmb250LXdlaWdodDpib2xkO2xpbmUtaGVpZ2h0OjIwcHg7XCIsXG4gICAgXCJZIC5ub3RpZmllci1jbG9zZTpob3ZlclwiOiBcImNvbG9yOiM0NDQ7dGV4dC1kZWNvcmF0aW9uOm5vbmU7Y3Vyc29yOnBvaW50ZXI7XCJcbn07XG5cbmZvcih2YXIgc2VsZWN0b3IgaW4gcnVsZXMpIHtcbiAgICB2YXIgZnVsbFNlbGVjdG9yID0gc2VsZWN0b3IucmVwbGFjZSgvXiwvLCcgLCcpXG4gICAgICAgIC5yZXBsYWNlKC9YL2csICcuanMtcGxvdGx5LXBsb3QgLnBsb3RseScpXG4gICAgICAgIC5yZXBsYWNlKC9ZL2csICcucGxvdGx5LW5vdGlmaWVyJyk7XG4gICAgTGliLmFkZFN0eWxlUnVsZShmdWxsU2VsZWN0b3IsIHJ1bGVzW3NlbGVjdG9yXSk7XG59XG5cbn0se1wiLi4vc3JjL2xpYlwiOjcxOX1dLDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFuc2Zvcm1zL2FnZ3JlZ2F0ZScpO1xuXG59LHtcIi4uL3NyYy90cmFuc2Zvcm1zL2FnZ3JlZ2F0ZVwiOjEyNjV9XSwzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL2JhcicpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvYmFyXCI6ODY0fV0sNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9iYXJwb2xhcicpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvYmFycG9sYXJcIjo4NzZ9XSw1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL2JveCcpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvYm94XCI6ODg2fV0sNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL2NvbXBvbmVudHMvY2FsZW5kYXJzJyk7XG5cbn0se1wiLi4vc3JjL2NvbXBvbmVudHMvY2FsZW5kYXJzXCI6NTkxfV0sNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9jYW5kbGVzdGljaycpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvY2FuZGxlc3RpY2tcIjo4OTV9XSw4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL2NhcnBldCcpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvY2FycGV0XCI6OTE0fV0sOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9jaG9yb3BsZXRoJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9jaG9yb3BsZXRoXCI6OTI4fV0sMTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFjZXMvY2hvcm9wbGV0aG1hcGJveCcpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvY2hvcm9wbGV0aG1hcGJveFwiOjkzNX1dLDExOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL2NvbmUnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL2NvbmVcIjo5NDF9XSwxMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9jb250b3VyJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9jb250b3VyXCI6OTU2fV0sMTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFjZXMvY29udG91cmNhcnBldCcpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvY29udG91cmNhcnBldFwiOjk2N31dLDE0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvY29yZScpO1xuXG59LHtcIi4uL3NyYy9jb3JlXCI6Njk3fV0sMTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFjZXMvZGVuc2l0eW1hcGJveCcpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvZGVuc2l0eW1hcGJveFwiOjk3N31dLDE2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhbnNmb3Jtcy9maWx0ZXInKTtcblxufSx7XCIuLi9zcmMvdHJhbnNmb3Jtcy9maWx0ZXJcIjoxMjY2fV0sMTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFjZXMvZnVubmVsJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9mdW5uZWxcIjo5ODd9XSwxODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9mdW5uZWxhcmVhJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9mdW5uZWxhcmVhXCI6OTk2fV0sMTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFuc2Zvcm1zL2dyb3VwYnknKTtcblxufSx7XCIuLi9zcmMvdHJhbnNmb3Jtcy9ncm91cGJ5XCI6MTI2N31dLDIwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL2hlYXRtYXAnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL2hlYXRtYXBcIjoxMDA5fV0sMjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFjZXMvaGVhdG1hcGdsJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9oZWF0bWFwZ2xcIjoxMDE4fV0sMjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFjZXMvaGlzdG9ncmFtJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9oaXN0b2dyYW1cIjoxMDMwfV0sMjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFjZXMvaGlzdG9ncmFtMmQnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL2hpc3RvZ3JhbTJkXCI6MTAzNn1dLDI0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL2hpc3RvZ3JhbTJkY29udG91cicpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvaGlzdG9ncmFtMmRjb250b3VyXCI6MTA0MH1dLDI1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFBsb3RseSA9IF9kZXJlcV8oJy4vY29yZScpO1xuXG4vLyB0cmFjZXNcblBsb3RseS5yZWdpc3RlcihbXG4gICAgX2RlcmVxXygnLi9iYXInKSxcbiAgICBfZGVyZXFfKCcuL2JveCcpLFxuICAgIF9kZXJlcV8oJy4vaGVhdG1hcCcpLFxuICAgIF9kZXJlcV8oJy4vaGlzdG9ncmFtJyksXG4gICAgX2RlcmVxXygnLi9oaXN0b2dyYW0yZCcpLFxuICAgIF9kZXJlcV8oJy4vaGlzdG9ncmFtMmRjb250b3VyJyksXG4gICAgX2RlcmVxXygnLi9jb250b3VyJyksXG4gICAgX2RlcmVxXygnLi9zY2F0dGVydGVybmFyeScpLFxuICAgIF9kZXJlcV8oJy4vdmlvbGluJyksXG4gICAgX2RlcmVxXygnLi9mdW5uZWwnKSxcbiAgICBfZGVyZXFfKCcuL3dhdGVyZmFsbCcpLFxuXG4gICAgX2RlcmVxXygnLi9waWUnKSxcbiAgICBfZGVyZXFfKCcuL3N1bmJ1cnN0JyksXG4gICAgX2RlcmVxXygnLi9mdW5uZWxhcmVhJyksXG5cbiAgICBfZGVyZXFfKCcuL3NjYXR0ZXIzZCcpLFxuICAgIF9kZXJlcV8oJy4vc3VyZmFjZScpLFxuICAgIF9kZXJlcV8oJy4vaXNvc3VyZmFjZScpLFxuICAgIF9kZXJlcV8oJy4vdm9sdW1lJyksXG4gICAgX2RlcmVxXygnLi9tZXNoM2QnKSxcbiAgICBfZGVyZXFfKCcuL2NvbmUnKSxcbiAgICBfZGVyZXFfKCcuL3N0cmVhbXR1YmUnKSxcblxuICAgIF9kZXJlcV8oJy4vc2NhdHRlcmdlbycpLFxuICAgIF9kZXJlcV8oJy4vY2hvcm9wbGV0aCcpLFxuXG4gICAgX2RlcmVxXygnLi9zY2F0dGVyZ2wnKSxcbiAgICBfZGVyZXFfKCcuL3NwbG9tJyksXG5cbiAgICBfZGVyZXFfKCcuL3BvaW50Y2xvdWQnKSxcbiAgICBfZGVyZXFfKCcuL2hlYXRtYXBnbCcpLFxuXG4gICAgX2RlcmVxXygnLi9wYXJjb29yZHMnKSxcblxuICAgIF9kZXJlcV8oJy4vcGFyY2F0cycpLFxuXG4gICAgX2RlcmVxXygnLi9zY2F0dGVybWFwYm94JyksXG4gICAgX2RlcmVxXygnLi9jaG9yb3BsZXRobWFwYm94JyksXG4gICAgX2RlcmVxXygnLi9kZW5zaXR5bWFwYm94JyksXG5cbiAgICBfZGVyZXFfKCcuL3NhbmtleScpLFxuICAgIF9kZXJlcV8oJy4vaW5kaWNhdG9yJyksXG5cbiAgICBfZGVyZXFfKCcuL3RhYmxlJyksXG5cbiAgICBfZGVyZXFfKCcuL2NhcnBldCcpLFxuICAgIF9kZXJlcV8oJy4vc2NhdHRlcmNhcnBldCcpLFxuICAgIF9kZXJlcV8oJy4vY29udG91cmNhcnBldCcpLFxuXG4gICAgX2RlcmVxXygnLi9vaGxjJyksXG4gICAgX2RlcmVxXygnLi9jYW5kbGVzdGljaycpLFxuXG4gICAgX2RlcmVxXygnLi9zY2F0dGVycG9sYXInKSxcbiAgICBfZGVyZXFfKCcuL3NjYXR0ZXJwb2xhcmdsJyksXG4gICAgX2RlcmVxXygnLi9iYXJwb2xhcicpXG5dKTtcblxuLy8gdHJhbnNmb3Jtc1xuLy9cbi8vIFBsZWFzZSBub3RlIHRoYXQgYWxsICp0cmFuc2Zvcm0qIG1ldGhvZHMgYXJlIGV4ZWN1dGVkIGJlZm9yZVxuLy8gYWxsICpjYWxjVHJhbnNmb3JtKiBtZXRob2RzIC0gd2hpY2ggY291bGQgcG9zc2libHkgbGVhZCB0b1xuLy8gdW5leHBlY3RlZCByZXN1bHRzIHdoZW4gYXBwbHlpbmcgbXVsdGlwbGUgdHJhbnNmb3JtcyBvZiBkaWZmZXJlbnQgdHlwZXNcbi8vIHRvIGEgZ2l2ZW4gdHJhY2UuXG4vL1xuLy8gRm9yIG1vcmUgaW5mbywgc2VlOlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvcHVsbC85NzgjcHVsbHJlcXVlc3RyZXZpZXctMjQwMzM1M1xuLy9cblBsb3RseS5yZWdpc3RlcihbXG4gICAgX2RlcmVxXygnLi9hZ2dyZWdhdGUnKSxcbiAgICBfZGVyZXFfKCcuL2ZpbHRlcicpLFxuICAgIF9kZXJlcV8oJy4vZ3JvdXBieScpLFxuICAgIF9kZXJlcV8oJy4vc29ydCcpXG5dKTtcblxuLy8gY29tcG9uZW50c1xuUGxvdGx5LnJlZ2lzdGVyKFtcbiAgICBfZGVyZXFfKCcuL2NhbGVuZGFycycpXG5dKTtcblxubW9kdWxlLmV4cG9ydHMgPSBQbG90bHk7XG5cbn0se1wiLi9hZ2dyZWdhdGVcIjoyLFwiLi9iYXJcIjozLFwiLi9iYXJwb2xhclwiOjQsXCIuL2JveFwiOjUsXCIuL2NhbGVuZGFyc1wiOjYsXCIuL2NhbmRsZXN0aWNrXCI6NyxcIi4vY2FycGV0XCI6OCxcIi4vY2hvcm9wbGV0aFwiOjksXCIuL2Nob3JvcGxldGhtYXBib3hcIjoxMCxcIi4vY29uZVwiOjExLFwiLi9jb250b3VyXCI6MTIsXCIuL2NvbnRvdXJjYXJwZXRcIjoxMyxcIi4vY29yZVwiOjE0LFwiLi9kZW5zaXR5bWFwYm94XCI6MTUsXCIuL2ZpbHRlclwiOjE2LFwiLi9mdW5uZWxcIjoxNyxcIi4vZnVubmVsYXJlYVwiOjE4LFwiLi9ncm91cGJ5XCI6MTksXCIuL2hlYXRtYXBcIjoyMCxcIi4vaGVhdG1hcGdsXCI6MjEsXCIuL2hpc3RvZ3JhbVwiOjIyLFwiLi9oaXN0b2dyYW0yZFwiOjIzLFwiLi9oaXN0b2dyYW0yZGNvbnRvdXJcIjoyNCxcIi4vaW5kaWNhdG9yXCI6MjYsXCIuL2lzb3N1cmZhY2VcIjoyNyxcIi4vbWVzaDNkXCI6MjgsXCIuL29obGNcIjoyOSxcIi4vcGFyY2F0c1wiOjMwLFwiLi9wYXJjb29yZHNcIjozMSxcIi4vcGllXCI6MzIsXCIuL3BvaW50Y2xvdWRcIjozMyxcIi4vc2Fua2V5XCI6MzQsXCIuL3NjYXR0ZXIzZFwiOjM1LFwiLi9zY2F0dGVyY2FycGV0XCI6MzYsXCIuL3NjYXR0ZXJnZW9cIjozNyxcIi4vc2NhdHRlcmdsXCI6MzgsXCIuL3NjYXR0ZXJtYXBib3hcIjozOSxcIi4vc2NhdHRlcnBvbGFyXCI6NDAsXCIuL3NjYXR0ZXJwb2xhcmdsXCI6NDEsXCIuL3NjYXR0ZXJ0ZXJuYXJ5XCI6NDIsXCIuL3NvcnRcIjo0MyxcIi4vc3Bsb21cIjo0NCxcIi4vc3RyZWFtdHViZVwiOjQ1LFwiLi9zdW5idXJzdFwiOjQ2LFwiLi9zdXJmYWNlXCI6NDcsXCIuL3RhYmxlXCI6NDgsXCIuL3Zpb2xpblwiOjQ5LFwiLi92b2x1bWVcIjo1MCxcIi4vd2F0ZXJmYWxsXCI6NTF9XSwyNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9pbmRpY2F0b3InKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL2luZGljYXRvclwiOjEwNDZ9XSwyNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9pc29zdXJmYWNlJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9pc29zdXJmYWNlXCI6MTA1Mn1dLDI4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL21lc2gzZCcpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvbWVzaDNkXCI6MTA1N31dLDI5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL29obGMnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL29obGNcIjoxMDYyfV0sMzA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFjZXMvcGFyY2F0cycpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvcGFyY2F0c1wiOjEwNzF9XSwzMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9wYXJjb29yZHMnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL3BhcmNvb3Jkc1wiOjEwODF9XSwzMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9waWUnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL3BpZVwiOjEwOTJ9XSwzMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9wb2ludGNsb3VkJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9wb2ludGNsb3VkXCI6MTEwMX1dLDM0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL3NhbmtleScpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvc2Fua2V5XCI6MTEwN31dLDM1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL3NjYXR0ZXIzZCcpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvc2NhdHRlcjNkXCI6MTE0M31dLDM2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL3NjYXR0ZXJjYXJwZXQnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL3NjYXR0ZXJjYXJwZXRcIjoxMTQ5fV0sMzc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFjZXMvc2NhdHRlcmdlbycpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvc2NhdHRlcmdlb1wiOjExNTZ9XSwzODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9zY2F0dGVyZ2wnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL3NjYXR0ZXJnbFwiOjExNjd9XSwzOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9zY2F0dGVybWFwYm94Jyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9zY2F0dGVybWFwYm94XCI6MTE3Nn1dLDQwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL3NjYXR0ZXJwb2xhcicpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvc2NhdHRlcnBvbGFyXCI6MTE4M31dLDQxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL3NjYXR0ZXJwb2xhcmdsJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9zY2F0dGVycG9sYXJnbFwiOjExODl9XSw0MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9zY2F0dGVydGVybmFyeScpO1xuXG59LHtcIi4uL3NyYy90cmFjZXMvc2NhdHRlcnRlcm5hcnlcIjoxMTk2fV0sNDM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4uL3NyYy90cmFuc2Zvcm1zL3NvcnQnKTtcblxufSx7XCIuLi9zcmMvdHJhbnNmb3Jtcy9zb3J0XCI6MTI2OX1dLDQ0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL3NwbG9tJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9zcGxvbVwiOjEyMDV9XSw0NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9zdHJlYW10dWJlJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9zdHJlYW10dWJlXCI6MTIxM31dLDQ2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL3N1bmJ1cnN0Jyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9zdW5idXJzdFwiOjEyMTl9XSw0NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy9zdXJmYWNlJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy9zdXJmYWNlXCI6MTIyOH1dLDQ4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuLi9zcmMvdHJhY2VzL3RhYmxlJyk7XG5cbn0se1wiLi4vc3JjL3RyYWNlcy90YWJsZVwiOjEyMzZ9XSw0OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy92aW9saW4nKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL3Zpb2xpblwiOjEyNDR9XSw1MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy92b2x1bWUnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL3ZvbHVtZVwiOjEyNTJ9XSw1MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi4vc3JjL3RyYWNlcy93YXRlcmZhbGwnKTtcblxufSx7XCIuLi9zcmMvdHJhY2VzL3dhdGVyZmFsbFwiOjEyNjB9XSw1MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVWaWV3Q29udHJvbGxlclxuXG52YXIgY3JlYXRlVHVybnRhYmxlID0gX2RlcmVxXygndHVybnRhYmxlLWNhbWVyYS1jb250cm9sbGVyJylcbnZhciBjcmVhdGVPcmJpdCAgICAgPSBfZGVyZXFfKCdvcmJpdC1jYW1lcmEtY29udHJvbGxlcicpXG52YXIgY3JlYXRlTWF0cml4ICAgID0gX2RlcmVxXygnbWF0cml4LWNhbWVyYS1jb250cm9sbGVyJylcblxuZnVuY3Rpb24gVmlld0NvbnRyb2xsZXIoY29udHJvbGxlcnMsIG1vZGUpIHtcbiAgdGhpcy5fY29udHJvbGxlck5hbWVzID0gT2JqZWN0LmtleXMoY29udHJvbGxlcnMpXG4gIHRoaXMuX2NvbnRyb2xsZXJMaXN0ID0gdGhpcy5fY29udHJvbGxlck5hbWVzLm1hcChmdW5jdGlvbihuKSB7XG4gICAgcmV0dXJuIGNvbnRyb2xsZXJzW25dXG4gIH0pXG4gIHRoaXMuX21vZGUgICA9IG1vZGVcbiAgdGhpcy5fYWN0aXZlID0gY29udHJvbGxlcnNbbW9kZV1cbiAgaWYoIXRoaXMuX2FjdGl2ZSkge1xuICAgIHRoaXMuX21vZGUgICA9ICd0dXJudGFibGUnXG4gICAgdGhpcy5fYWN0aXZlID0gY29udHJvbGxlcnMudHVybnRhYmxlXG4gIH1cbiAgdGhpcy5tb2RlcyA9IHRoaXMuX2NvbnRyb2xsZXJOYW1lc1xuICB0aGlzLmNvbXB1dGVkTWF0cml4ID0gdGhpcy5fYWN0aXZlLmNvbXB1dGVkTWF0cml4XG4gIHRoaXMuY29tcHV0ZWRFeWUgICAgPSB0aGlzLl9hY3RpdmUuY29tcHV0ZWRFeWVcbiAgdGhpcy5jb21wdXRlZFVwICAgICA9IHRoaXMuX2FjdGl2ZS5jb21wdXRlZFVwXG4gIHRoaXMuY29tcHV0ZWRDZW50ZXIgPSB0aGlzLl9hY3RpdmUuY29tcHV0ZWRDZW50ZXJcbiAgdGhpcy5jb21wdXRlZFJhZGl1cyA9IHRoaXMuX2FjdGl2ZS5jb21wdXRlZFJhZGl1c1xufVxuXG52YXIgcHJvdG8gPSBWaWV3Q29udHJvbGxlci5wcm90b3R5cGVcblxudmFyIENPTU1PTl9NRVRIT0RTID0gW1xuICBbJ2ZsdXNoJywgMV0sXG4gIFsnaWRsZScsIDFdLFxuICBbJ2xvb2tBdCcsIDRdLFxuICBbJ3JvdGF0ZScsIDRdLFxuICBbJ3BhbicsIDRdLFxuICBbJ3RyYW5zbGF0ZScsIDRdLFxuICBbJ3NldE1hdHJpeCcsIDJdLFxuICBbJ3NldERpc3RhbmNlTGltaXRzJywgMl0sXG4gIFsnc2V0RGlzdGFuY2UnLCAyXVxuXVxuXG5DT01NT05fTUVUSE9EUy5mb3JFYWNoKGZ1bmN0aW9uKG1ldGhvZCkge1xuICB2YXIgbmFtZSA9IG1ldGhvZFswXVxuICB2YXIgYXJnTmFtZXMgPSBbXVxuICBmb3IodmFyIGk9MDsgaTxtZXRob2RbMV07ICsraSkge1xuICAgIGFyZ05hbWVzLnB1c2goJ2EnK2kpXG4gIH1cbiAgdmFyIGNvZGUgPSAndmFyIGNjPXRoaXMuX2NvbnRyb2xsZXJMaXN0O2Zvcih2YXIgaT0wO2k8Y2MubGVuZ3RoOysraSl7Y2NbaV0uJyttZXRob2RbMF0rJygnK2FyZ05hbWVzLmpvaW4oKSsnKX0nXG4gIHByb3RvW25hbWVdID0gRnVuY3Rpb24uYXBwbHkobnVsbCwgYXJnTmFtZXMuY29uY2F0KGNvZGUpKVxufSlcblxucHJvdG8ucmVjYWxjTWF0cml4ID0gZnVuY3Rpb24odCkge1xuICB0aGlzLl9hY3RpdmUucmVjYWxjTWF0cml4KHQpXG59XG5cbnByb3RvLmdldERpc3RhbmNlID0gZnVuY3Rpb24odCkge1xuICByZXR1cm4gdGhpcy5fYWN0aXZlLmdldERpc3RhbmNlKHQpXG59XG5wcm90by5nZXREaXN0YW5jZUxpbWl0cyA9IGZ1bmN0aW9uKG91dCkge1xuICByZXR1cm4gdGhpcy5fYWN0aXZlLmdldERpc3RhbmNlTGltaXRzKG91dClcbn1cblxucHJvdG8ubGFzdFQgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuX2FjdGl2ZS5sYXN0VCgpXG59XG5cbnByb3RvLnNldE1vZGUgPSBmdW5jdGlvbihtb2RlKSB7XG4gIGlmKG1vZGUgPT09IHRoaXMuX21vZGUpIHtcbiAgICByZXR1cm5cbiAgfVxuICB2YXIgaWR4ID0gdGhpcy5fY29udHJvbGxlck5hbWVzLmluZGV4T2YobW9kZSlcbiAgaWYoaWR4IDwgMCkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBwcmV2ICA9IHRoaXMuX2FjdGl2ZVxuICB2YXIgbmV4dCAgPSB0aGlzLl9jb250cm9sbGVyTGlzdFtpZHhdXG4gIHZhciBsYXN0VCA9IE1hdGgubWF4KHByZXYubGFzdFQoKSwgbmV4dC5sYXN0VCgpKVxuXG4gIHByZXYucmVjYWxjTWF0cml4KGxhc3RUKVxuICBuZXh0LnNldE1hdHJpeChsYXN0VCwgcHJldi5jb21wdXRlZE1hdHJpeClcbiAgXG4gIHRoaXMuX2FjdGl2ZSA9IG5leHRcbiAgdGhpcy5fbW9kZSAgID0gbW9kZVxuXG4gIC8vVXBkYXRlIG1hdHJpeCBwcm9wZXJ0aWVzXG4gIHRoaXMuY29tcHV0ZWRNYXRyaXggPSB0aGlzLl9hY3RpdmUuY29tcHV0ZWRNYXRyaXhcbiAgdGhpcy5jb21wdXRlZEV5ZSAgICA9IHRoaXMuX2FjdGl2ZS5jb21wdXRlZEV5ZVxuICB0aGlzLmNvbXB1dGVkVXAgICAgID0gdGhpcy5fYWN0aXZlLmNvbXB1dGVkVXBcbiAgdGhpcy5jb21wdXRlZENlbnRlciA9IHRoaXMuX2FjdGl2ZS5jb21wdXRlZENlbnRlclxuICB0aGlzLmNvbXB1dGVkUmFkaXVzID0gdGhpcy5fYWN0aXZlLmNvbXB1dGVkUmFkaXVzXG59XG5cbnByb3RvLmdldE1vZGUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuX21vZGVcbn1cblxuZnVuY3Rpb24gY3JlYXRlVmlld0NvbnRyb2xsZXIob3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gIHZhciBleWUgICAgICAgPSBvcHRpb25zLmV5ZSAgICB8fCBbMCwwLDFdXG4gIHZhciBjZW50ZXIgICAgPSBvcHRpb25zLmNlbnRlciB8fCBbMCwwLDBdXG4gIHZhciB1cCAgICAgICAgPSBvcHRpb25zLnVwICAgICB8fCBbMCwxLDBdXG4gIHZhciBsaW1pdHMgICAgPSBvcHRpb25zLmRpc3RhbmNlTGltaXRzIHx8IFswLCBJbmZpbml0eV1cbiAgdmFyIG1vZGUgICAgICA9IG9wdGlvbnMubW9kZSAgIHx8ICd0dXJudGFibGUnXG5cbiAgdmFyIHR1cm50YWJsZSA9IGNyZWF0ZVR1cm50YWJsZSgpXG4gIHZhciBvcmJpdCAgICAgPSBjcmVhdGVPcmJpdCgpXG4gIHZhciBtYXRyaXggICAgPSBjcmVhdGVNYXRyaXgoKVxuXG4gIHR1cm50YWJsZS5zZXREaXN0YW5jZUxpbWl0cyhsaW1pdHNbMF0sIGxpbWl0c1sxXSlcbiAgdHVybnRhYmxlLmxvb2tBdCgwLCBleWUsIGNlbnRlciwgdXApXG4gIG9yYml0LnNldERpc3RhbmNlTGltaXRzKGxpbWl0c1swXSwgbGltaXRzWzFdKVxuICBvcmJpdC5sb29rQXQoMCwgZXllLCBjZW50ZXIsIHVwKVxuICBtYXRyaXguc2V0RGlzdGFuY2VMaW1pdHMobGltaXRzWzBdLCBsaW1pdHNbMV0pXG4gIG1hdHJpeC5sb29rQXQoMCwgZXllLCBjZW50ZXIsIHVwKVxuXG4gIHJldHVybiBuZXcgVmlld0NvbnRyb2xsZXIoe1xuICAgIHR1cm50YWJsZTogdHVybnRhYmxlLFxuICAgIG9yYml0OiBvcmJpdCxcbiAgICBtYXRyaXg6IG1hdHJpeFxuICB9LCBtb2RlKVxufVxufSx7XCJtYXRyaXgtY2FtZXJhLWNvbnRyb2xsZXJcIjo0MzMsXCJvcmJpdC1jYW1lcmEtY29udHJvbGxlclwiOjQ1NixcInR1cm50YWJsZS1jYW1lcmEtY29udHJvbGxlclwiOjU0Mn1dLDUzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cywgX2RlcmVxXygnZDMtYXJyYXknKSwgX2RlcmVxXygnZDMtY29sbGVjdGlvbicpLCBfZGVyZXFfKCdkMy1zaGFwZScpLCBfZGVyZXFfKCdlbGVtZW50YXJ5LWNpcmN1aXRzLWRpcmVjdGVkLWdyYXBoJykpIDpcbiAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cycsICdkMy1hcnJheScsICdkMy1jb2xsZWN0aW9uJywgJ2QzLXNoYXBlJywgJ2VsZW1lbnRhcnktY2lyY3VpdHMtZGlyZWN0ZWQtZ3JhcGgnXSwgZmFjdG9yeSkgOlxuICAoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMyxudWxsKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cyxkM0FycmF5LGQzQ29sbGVjdGlvbixkM1NoYXBlLGZpbmRDaXJjdWl0cykgeyAndXNlIHN0cmljdCc7XG5cbiAgZmluZENpcmN1aXRzID0gZmluZENpcmN1aXRzICYmIGZpbmRDaXJjdWl0cy5oYXNPd25Qcm9wZXJ0eSgnZGVmYXVsdCcpID8gZmluZENpcmN1aXRzWydkZWZhdWx0J10gOiBmaW5kQ2lyY3VpdHM7XG5cbiAgLy8gRm9yIGEgZ2l2ZW4gbGluaywgcmV0dXJuIHRoZSB0YXJnZXQgbm9kZSdzIGRlcHRoXG4gIGZ1bmN0aW9uIHRhcmdldERlcHRoKGQpIHtcbiAgICByZXR1cm4gZC50YXJnZXQuZGVwdGg7XG4gIH1cblxuICAvLyBUaGUgZGVwdGggb2YgYSBub2RlIHdoZW4gdGhlIG5vZGVBbGlnbiAoYWxpZ24pIGlzIHNldCB0byAnbGVmdCdcbiAgZnVuY3Rpb24gbGVmdChub2RlKSB7XG4gICAgcmV0dXJuIG5vZGUuZGVwdGg7XG4gIH1cblxuICAvLyBUaGUgZGVwdGggb2YgYSBub2RlIHdoZW4gdGhlIG5vZGVBbGlnbiAoYWxpZ24pIGlzIHNldCB0byAncmlnaHQnXG4gIGZ1bmN0aW9uIHJpZ2h0KG5vZGUsIG4pIHtcbiAgICByZXR1cm4gbiAtIDEgLSBub2RlLmhlaWdodDtcbiAgfVxuXG4gIC8vIFRoZSBkZXB0aCBvZiBhIG5vZGUgd2hlbiB0aGUgbm9kZUFsaWduIChhbGlnbikgaXMgc2V0IHRvICdqdXN0aWZ5J1xuICBmdW5jdGlvbiBqdXN0aWZ5KG5vZGUsIG4pIHtcbiAgICByZXR1cm4gbm9kZS5zb3VyY2VMaW5rcy5sZW5ndGggPyBub2RlLmRlcHRoIDogbiAtIDE7XG4gIH1cblxuICAvLyBUaGUgZGVwdGggb2YgYSBub2RlIHdoZW4gdGhlIG5vZGVBbGlnbiAoYWxpZ24pIGlzIHNldCB0byAnY2VudGVyJ1xuICBmdW5jdGlvbiBjZW50ZXIobm9kZSkge1xuICAgIHJldHVybiBub2RlLnRhcmdldExpbmtzLmxlbmd0aCA/IG5vZGUuZGVwdGggOiBub2RlLnNvdXJjZUxpbmtzLmxlbmd0aCA/IGQzQXJyYXkubWluKG5vZGUuc291cmNlTGlua3MsIHRhcmdldERlcHRoKSAtIDEgOiAwO1xuICB9XG5cbiAgLy8gcmV0dXJucyBhIGZ1bmN0aW9uLCB1c2luZyB0aGUgcGFyYW1ldGVyIGdpdmVuIHRvIHRoZSBzYW5rZXkgc2V0dGluZ1xuICBmdW5jdGlvbiBjb25zdGFudCh4KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB4O1xuICAgIH07XG4gIH1cblxuICB2YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiB0eXBlb2Ygb2JqO1xuICB9IDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBvYmogJiYgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gU3ltYm9sICYmIG9iaiAhPT0gU3ltYm9sLnByb3RvdHlwZSA/IFwic3ltYm9sXCIgOiB0eXBlb2Ygb2JqO1xuICB9O1xuXG4gIC8vLyBodHRwczovL2dpdGh1Yi5jb20vdG9tc2hhbmxleS9kMy1zYW5rZXlDaXJjdWxhci1jaXJjdWxhclxuXG4gIC8vIHNvcnQgbGlua3MnIGJyZWFkdGggKGllIHRvcCB0byBib3R0b20gaW4gYSBjb2x1bW4pLCBiYXNlZCBvbiB0aGVpciBzb3VyY2Ugbm9kZXMnIGJyZWFkdGhzXG4gIGZ1bmN0aW9uIGFzY2VuZGluZ1NvdXJjZUJyZWFkdGgoYSwgYikge1xuICAgIHJldHVybiBhc2NlbmRpbmdCcmVhZHRoKGEuc291cmNlLCBiLnNvdXJjZSkgfHwgYS5pbmRleCAtIGIuaW5kZXg7XG4gIH1cblxuICAvLyBzb3J0IGxpbmtzJyBicmVhZHRoIChpZSB0b3AgdG8gYm90dG9tIGluIGEgY29sdW1uKSwgYmFzZWQgb24gdGhlaXIgdGFyZ2V0IG5vZGVzJyBicmVhZHRoc1xuICBmdW5jdGlvbiBhc2NlbmRpbmdUYXJnZXRCcmVhZHRoKGEsIGIpIHtcbiAgICByZXR1cm4gYXNjZW5kaW5nQnJlYWR0aChhLnRhcmdldCwgYi50YXJnZXQpIHx8IGEuaW5kZXggLSBiLmluZGV4O1xuICB9XG5cbiAgLy8gc29ydCBub2RlcycgYnJlYWR0aCAoaWUgdG9wIHRvIGJvdHRvbSBpbiBhIGNvbHVtbilcbiAgLy8gaWYgYm90aCBub2RlcyBoYXZlIGNpcmN1bGFyIGxpbmtzLCBvciBib3RoIGRvbid0IGhhdmUgY2lyY3VsYXIgbGlua3MsIHRoZW4gc29ydCBieSB0aGUgdG9wICh5MCkgb2YgdGhlIG5vZGVcbiAgLy8gZWxzZSBwdXNoIG5vZGVzIHRoYXQgaGF2ZSB0b3AgY2lyY3VsYXIgbGlua3MgdG8gdGhlIHRvcCwgYW5kIG5vZGVzIHRoYXQgaGF2ZSBib3R0b20gY2lyY3VsYXIgbGlua3MgdG8gdGhlIGJvdHRvbVxuICBmdW5jdGlvbiBhc2NlbmRpbmdCcmVhZHRoKGEsIGIpIHtcbiAgICBpZiAoYS5wYXJ0T2ZDeWNsZSA9PT0gYi5wYXJ0T2ZDeWNsZSkge1xuICAgICAgcmV0dXJuIGEueTAgLSBiLnkwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYS5jaXJjdWxhckxpbmtUeXBlID09PSAndG9wJyB8fCBiLmNpcmN1bGFyTGlua1R5cGUgPT09ICdib3R0b20nKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIHJldHVybiB0aGUgdmFsdWUgb2YgYSBub2RlIG9yIGxpbmtcbiAgZnVuY3Rpb24gdmFsdWUoZCkge1xuICAgIHJldHVybiBkLnZhbHVlO1xuICB9XG5cbiAgLy8gcmV0dXJuIHRoZSB2ZXJ0aWNhbCBjZW50ZXIgb2YgYSBub2RlXG4gIGZ1bmN0aW9uIG5vZGVDZW50ZXIobm9kZSkge1xuICAgIHJldHVybiAobm9kZS55MCArIG5vZGUueTEpIC8gMjtcbiAgfVxuXG4gIC8vIHJldHVybiB0aGUgdmVydGljYWwgY2VudGVyIG9mIGEgbGluaydzIHNvdXJjZSBub2RlXG4gIGZ1bmN0aW9uIGxpbmtTb3VyY2VDZW50ZXIobGluaykge1xuICAgIHJldHVybiBub2RlQ2VudGVyKGxpbmsuc291cmNlKTtcbiAgfVxuXG4gIC8vIHJldHVybiB0aGUgdmVydGljYWwgY2VudGVyIG9mIGEgbGluaydzIHRhcmdldCBub2RlXG4gIGZ1bmN0aW9uIGxpbmtUYXJnZXRDZW50ZXIobGluaykge1xuICAgIHJldHVybiBub2RlQ2VudGVyKGxpbmsudGFyZ2V0KTtcbiAgfVxuXG4gIC8vIFJldHVybiB0aGUgZGVmYXVsdCB2YWx1ZSBmb3IgSUQgZm9yIG5vZGUsIGQuaW5kZXhcbiAgZnVuY3Rpb24gZGVmYXVsdElkKGQpIHtcbiAgICByZXR1cm4gZC5pbmRleDtcbiAgfVxuXG4gIC8vIFJldHVybiB0aGUgZGVmYXVsdCBvYmplY3QgdGhlIGdyYXBoJ3Mgbm9kZXMsIGdyYXBoLm5vZGVzXG4gIGZ1bmN0aW9uIGRlZmF1bHROb2RlcyhncmFwaCkge1xuICAgIHJldHVybiBncmFwaC5ub2RlcztcbiAgfVxuXG4gIC8vIFJldHVybiB0aGUgZGVmYXVsdCBvYmplY3QgdGhlIGdyYXBoJ3Mgbm9kZXMsIGdyYXBoLmxpbmtzXG4gIGZ1bmN0aW9uIGRlZmF1bHRMaW5rcyhncmFwaCkge1xuICAgIHJldHVybiBncmFwaC5saW5rcztcbiAgfVxuXG4gIC8vIFJldHVybiB0aGUgbm9kZSBmcm9tIHRoZSBjb2xsZWN0aW9uIHRoYXQgbWF0Y2hlcyB0aGUgcHJvdmlkZWQgSUQsIG9yIHRocm93IGFuIGVycm9yIGlmIG5vIG1hdGNoXG4gIGZ1bmN0aW9uIGZpbmQobm9kZUJ5SWQsIGlkKSB7XG4gICAgdmFyIG5vZGUgPSBub2RlQnlJZC5nZXQoaWQpO1xuICAgIGlmICghbm9kZSkgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nOiAnICsgaWQpO1xuICAgIHJldHVybiBub2RlO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0Tm9kZUlEKG5vZGUsIGlkKSB7XG4gICAgcmV0dXJuIGlkKG5vZGUpO1xuICB9XG5cbiAgLy8gVGhlIG1haW4gc2Fua2V5Q2lyY3VsYXIgZnVuY3Rpb25zXG5cbiAgLy8gU29tZSBjb25zdGFudHMgZm9yIGNpcmN1bGFyIGxpbmsgY2FsY3VsYXRpb25zXG4gIHZhciB2ZXJ0aWNhbE1hcmdpbiA9IDI1O1xuICB2YXIgYmFzZVJhZGl1cyA9IDEwO1xuICB2YXIgc2NhbGUgPSAwLjM7IC8vUG9zc2libHkgbGV0IHVzZXIgY29udHJvbCB0aGlzLCBhbHRob3VnaCBhbnl0aGluZyBvdmVyIDAuNSBzdGFydHMgdG8gZ2V0IHRvbyBjcmFtcGVkXG5cbiAgZnVuY3Rpb24gc2Fua2V5Q2lyY3VsYXIgKCkge1xuICAgIC8vIFNldCB0aGUgZGVmYXVsdCB2YWx1ZXNcbiAgICB2YXIgeDAgPSAwLFxuICAgICAgICB5MCA9IDAsXG4gICAgICAgIHgxID0gMSxcbiAgICAgICAgeTEgPSAxLFxuICAgICAgICAvLyBleHRlbnRcbiAgICBkeCA9IDI0LFxuICAgICAgICAvLyBub2RlV2lkdGhcbiAgICBweSxcbiAgICAgICAgLy8gbm9kZVBhZGRpbmcsIGZvciB2ZXJ0aWNhbCBwb3N0aW9uaW5nXG4gICAgaWQgPSBkZWZhdWx0SWQsXG4gICAgICAgIGFsaWduID0ganVzdGlmeSxcbiAgICAgICAgbm9kZXMgPSBkZWZhdWx0Tm9kZXMsXG4gICAgICAgIGxpbmtzID0gZGVmYXVsdExpbmtzLFxuICAgICAgICBpdGVyYXRpb25zID0gMzIsXG4gICAgICAgIGNpcmN1bGFyTGlua0dhcCA9IDIsXG4gICAgICAgIHBhZGRpbmdSYXRpbyxcbiAgICAgICAgc29ydE5vZGVzID0gbnVsbDtcblxuICAgIGZ1bmN0aW9uIHNhbmtleUNpcmN1bGFyKCkge1xuICAgICAgdmFyIGdyYXBoID0ge1xuICAgICAgICBub2Rlczogbm9kZXMuYXBwbHkobnVsbCwgYXJndW1lbnRzKSxcbiAgICAgICAgbGlua3M6IGxpbmtzLmFwcGx5KG51bGwsIGFyZ3VtZW50cylcblxuICAgICAgICAvLyBQcm9jZXNzIHRoZSBncmFwaCdzIG5vZGVzIGFuZCBsaW5rcywgc2V0dGluZyB0aGVpciBwb3NpdGlvbnNcblxuICAgICAgICAvLyAxLiAgQXNzb2NpYXRlIHRoZSBub2RlcyB3aXRoIHRoZWlyIHJlc3BlY3RpdmUgbGlua3MsIGFuZCB2aWNlIHZlcnNhXG4gICAgICB9O2NvbXB1dGVOb2RlTGlua3MoZ3JhcGgpO1xuXG4gICAgICAvLyAyLiAgRGV0ZXJtaW5lIHdoaWNoIGxpbmtzIHJlc3VsdCBpbiBhIGNpcmN1bGFyIHBhdGggaW4gdGhlIGdyYXBoXG4gICAgICBpZGVudGlmeUNpcmNsZXMoZ3JhcGgsIGlkLCBzb3J0Tm9kZXMpO1xuXG4gICAgICAvLyA0LiBDYWxjdWxhdGUgdGhlIG5vZGVzJyB2YWx1ZXMsIGJhc2VkIG9uIHRoZSB2YWx1ZXMgb2YgdGhlIGluY29taW5nIGFuZCBvdXRnb2luZyBsaW5rc1xuICAgICAgY29tcHV0ZU5vZGVWYWx1ZXMoZ3JhcGgpO1xuXG4gICAgICAvLyA1LiAgQ2FsY3VsYXRlIHRoZSBub2RlcycgZGVwdGggYmFzZWQgb24gdGhlIGluY29taW5nIGFuZCBvdXRnb2luZyBsaW5rc1xuICAgICAgLy8gICAgIFNldHMgdGhlIG5vZGVzJzpcbiAgICAgIC8vICAgICAtIGRlcHRoOiAgdGhlIGRlcHRoIGluIHRoZSBncmFwaFxuICAgICAgLy8gICAgIC0gY29sdW1uOiB0aGUgZGVwdGggKDAsIDEsIDIsIGV0YyksIGFzIGlzIHJlbGF0ZXMgdG8gdmlzdWFsIHBvc2l0aW9uIGZyb20gbGVmdCB0byByaWdodFxuICAgICAgLy8gICAgIC0geDAsIHgxOiB0aGUgeCBjb29yZGluYXRlcywgYXMgaXMgcmVsYXRlcyB0byB2aXN1YWwgcG9zaXRpb24gZnJvbSBsZWZ0IHRvIHJpZ2h0XG4gICAgICBjb21wdXRlTm9kZURlcHRocyhncmFwaCk7XG5cbiAgICAgIC8vIDMuICBEZXRlcm1pbmUgaG93IHRoZSBjaXJjdWxhciBsaW5rcyB3aWxsIGJlIGRyYXduLFxuICAgICAgLy8gICAgIGVpdGhlciB0cmF2ZWxsaW5nIGJhY2sgYWJvdmUgdGhlIG1haW4gY2hhcnQgKFwidG9wXCIpXG4gICAgICAvLyAgICAgb3IgYmVsb3cgdGhlIG1haW4gY2hhcnQgKFwiYm90dG9tXCIpXG4gICAgICBzZWxlY3RDaXJjdWxhckxpbmtUeXBlcyhncmFwaCwgaWQpO1xuXG4gICAgICAvLyA2LiAgQ2FsY3VsYXRlIHRoZSBub2RlcycgYW5kIGxpbmtzJyB2ZXJ0aWNhbCBwb3NpdGlvbiB3aXRoaW4gdGhlaXIgcmVzcGVjdGl2ZSBjb2x1bW5cbiAgICAgIC8vICAgICBBbHNvIHJlYWRqdXN0cyBzYW5rZXlDaXJjdWxhciBzaXplIGlmIGNpcmN1bGFyIGxpbmtzIGFyZSBuZWVkZWQsIGFuZCBub2RlIHgnc1xuICAgICAgY29tcHV0ZU5vZGVCcmVhZHRocyhncmFwaCwgaXRlcmF0aW9ucywgaWQpO1xuICAgICAgY29tcHV0ZUxpbmtCcmVhZHRocyhncmFwaCk7XG5cbiAgICAgIC8vIDcuICBTb3J0IGxpbmtzIHBlciBub2RlLCBiYXNlZCBvbiB0aGUgbGlua3MnIHNvdXJjZS90YXJnZXQgbm9kZXMnIGJyZWFkdGhzXG4gICAgICAvLyA4LiAgQWRqdXN0IG5vZGVzIHRoYXQgb3ZlcmxhcCBsaW5rcyB0aGF0IHNwYW4gMisgY29sdW1uc1xuICAgICAgdmFyIGxpbmtTb3J0aW5nSXRlcmF0aW9ucyA9IDQ7IC8vUG9zc2libHkgbGV0IHVzZXIgY29udHJvbCB0aGlzIG51bWJlciwgbGlrZSB0aGUgaXRlcmF0aW9ucyBvdmVyIG5vZGUgcGxhY2VtZW50XG4gICAgICBmb3IgKHZhciBpdGVyYXRpb24gPSAwOyBpdGVyYXRpb24gPCBsaW5rU29ydGluZ0l0ZXJhdGlvbnM7IGl0ZXJhdGlvbisrKSB7XG5cbiAgICAgICAgc29ydFNvdXJjZUxpbmtzKGdyYXBoLCB5MSwgaWQpO1xuICAgICAgICBzb3J0VGFyZ2V0TGlua3MoZ3JhcGgsIHkxLCBpZCk7XG4gICAgICAgIHJlc29sdmVOb2RlTGlua092ZXJsYXBzKGdyYXBoLCB5MCwgeTEsIGlkKTtcbiAgICAgICAgc29ydFNvdXJjZUxpbmtzKGdyYXBoLCB5MSwgaWQpO1xuICAgICAgICBzb3J0VGFyZ2V0TGlua3MoZ3JhcGgsIHkxLCBpZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIDguMSAgQWRqdXN0IG5vZGUgYW5kIGxpbmsgcG9zaXRpb25zIGJhY2sgdG8gZmlsbCBoZWlnaHQgb2YgY2hhcnQgYXJlYSBpZiBjb21wcmVzc2VkXG4gICAgICBmaWxsSGVpZ2h0KGdyYXBoLCB5MCwgeTEpO1xuXG4gICAgICAvLyA5LiBDYWxjdWxhdGUgdmlzdWFsbHkgYXBwZWFsbGluZyBwYXRoIGZvciB0aGUgY2lyY3VsYXIgcGF0aHMsIGFuZCBjcmVhdGUgdGhlIFwiZFwiIHN0cmluZ1xuICAgICAgYWRkQ2lyY3VsYXJQYXRoRGF0YShncmFwaCwgY2lyY3VsYXJMaW5rR2FwLCB5MSwgaWQpO1xuXG4gICAgICByZXR1cm4gZ3JhcGg7XG4gICAgfSAvLyBlbmQgb2Ygc2Fua2V5Q2lyY3VsYXIgZnVuY3Rpb25cblxuXG4gICAgLy8gU2V0IHRoZSBzYW5rZXlDaXJjdWxhciBwYXJhbWV0ZXJzXG4gICAgLy8gbm9kZUlELCBub2RlQWxpZ24sIG5vZGVXaWR0aCwgbm9kZVBhZGRpbmcsIG5vZGVzLCBsaW5rcywgc2l6ZSwgZXh0ZW50LCBpdGVyYXRpb25zLCBub2RlUGFkZGluZ1JhdGlvLCBjaXJjdWxhckxpbmtHYXBcbiAgICBzYW5rZXlDaXJjdWxhci5ub2RlSWQgPSBmdW5jdGlvbiAoXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaWQgPSB0eXBlb2YgXyA9PT0gJ2Z1bmN0aW9uJyA/IF8gOiBjb25zdGFudChfKSwgc2Fua2V5Q2lyY3VsYXIpIDogaWQ7XG4gICAgfTtcblxuICAgIHNhbmtleUNpcmN1bGFyLm5vZGVBbGlnbiA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChhbGlnbiA9IHR5cGVvZiBfID09PSAnZnVuY3Rpb24nID8gXyA6IGNvbnN0YW50KF8pLCBzYW5rZXlDaXJjdWxhcikgOiBhbGlnbjtcbiAgICB9O1xuXG4gICAgc2Fua2V5Q2lyY3VsYXIubm9kZVdpZHRoID0gZnVuY3Rpb24gKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGR4ID0gK18sIHNhbmtleUNpcmN1bGFyKSA6IGR4O1xuICAgIH07XG5cbiAgICBzYW5rZXlDaXJjdWxhci5ub2RlUGFkZGluZyA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChweSA9ICtfLCBzYW5rZXlDaXJjdWxhcikgOiBweTtcbiAgICB9O1xuXG4gICAgc2Fua2V5Q2lyY3VsYXIubm9kZXMgPSBmdW5jdGlvbiAoXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobm9kZXMgPSB0eXBlb2YgXyA9PT0gJ2Z1bmN0aW9uJyA/IF8gOiBjb25zdGFudChfKSwgc2Fua2V5Q2lyY3VsYXIpIDogbm9kZXM7XG4gICAgfTtcblxuICAgIHNhbmtleUNpcmN1bGFyLmxpbmtzID0gZnVuY3Rpb24gKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGxpbmtzID0gdHlwZW9mIF8gPT09ICdmdW5jdGlvbicgPyBfIDogY29uc3RhbnQoXyksIHNhbmtleUNpcmN1bGFyKSA6IGxpbmtzO1xuICAgIH07XG5cbiAgICBzYW5rZXlDaXJjdWxhci5zaXplID0gZnVuY3Rpb24gKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHgwID0geTAgPSAwLCB4MSA9ICtfWzBdLCB5MSA9ICtfWzFdLCBzYW5rZXlDaXJjdWxhcikgOiBbeDEgLSB4MCwgeTEgLSB5MF07XG4gICAgfTtcblxuICAgIHNhbmtleUNpcmN1bGFyLmV4dGVudCA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4MCA9ICtfWzBdWzBdLCB4MSA9ICtfWzFdWzBdLCB5MCA9ICtfWzBdWzFdLCB5MSA9ICtfWzFdWzFdLCBzYW5rZXlDaXJjdWxhcikgOiBbW3gwLCB5MF0sIFt4MSwgeTFdXTtcbiAgICB9O1xuXG4gICAgc2Fua2V5Q2lyY3VsYXIuaXRlcmF0aW9ucyA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpdGVyYXRpb25zID0gK18sIHNhbmtleUNpcmN1bGFyKSA6IGl0ZXJhdGlvbnM7XG4gICAgfTtcblxuICAgIHNhbmtleUNpcmN1bGFyLmNpcmN1bGFyTGlua0dhcCA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjaXJjdWxhckxpbmtHYXAgPSArXywgc2Fua2V5Q2lyY3VsYXIpIDogY2lyY3VsYXJMaW5rR2FwO1xuICAgIH07XG5cbiAgICBzYW5rZXlDaXJjdWxhci5ub2RlUGFkZGluZ1JhdGlvID0gZnVuY3Rpb24gKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBhZGRpbmdSYXRpbyA9ICtfLCBzYW5rZXlDaXJjdWxhcikgOiBwYWRkaW5nUmF0aW87XG4gICAgfTtcblxuICAgIHNhbmtleUNpcmN1bGFyLnNvcnROb2RlcyA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzb3J0Tm9kZXMgPSBfLCBzYW5rZXlDaXJjdWxhcikgOiBzb3J0Tm9kZXM7XG4gICAgfTtcblxuICAgIHNhbmtleUNpcmN1bGFyLnVwZGF0ZSA9IGZ1bmN0aW9uIChncmFwaCkge1xuICAgICAgLy8gNS4gIENhbGN1bGF0ZSB0aGUgbm9kZXMnIGRlcHRoIGJhc2VkIG9uIHRoZSBpbmNvbWluZyBhbmQgb3V0Z29pbmcgbGlua3NcbiAgICAgIC8vICAgICBTZXRzIHRoZSBub2Rlcyc6XG4gICAgICAvLyAgICAgLSBkZXB0aDogIHRoZSBkZXB0aCBpbiB0aGUgZ3JhcGhcbiAgICAgIC8vICAgICAtIGNvbHVtbjogdGhlIGRlcHRoICgwLCAxLCAyLCBldGMpLCBhcyBpcyByZWxhdGVzIHRvIHZpc3VhbCBwb3NpdGlvbiBmcm9tIGxlZnQgdG8gcmlnaHRcbiAgICAgIC8vICAgICAtIHgwLCB4MTogdGhlIHggY29vcmRpbmF0ZXMsIGFzIGlzIHJlbGF0ZXMgdG8gdmlzdWFsIHBvc2l0aW9uIGZyb20gbGVmdCB0byByaWdodFxuICAgICAgLy8gY29tcHV0ZU5vZGVEZXB0aHMoZ3JhcGgpXG5cbiAgICAgIC8vIDMuICBEZXRlcm1pbmUgaG93IHRoZSBjaXJjdWxhciBsaW5rcyB3aWxsIGJlIGRyYXduLFxuICAgICAgLy8gICAgIGVpdGhlciB0cmF2ZWxsaW5nIGJhY2sgYWJvdmUgdGhlIG1haW4gY2hhcnQgKFwidG9wXCIpXG4gICAgICAvLyAgICAgb3IgYmVsb3cgdGhlIG1haW4gY2hhcnQgKFwiYm90dG9tXCIpXG4gICAgICBzZWxlY3RDaXJjdWxhckxpbmtUeXBlcyhncmFwaCwgaWQpO1xuXG4gICAgICAvLyA2LiAgQ2FsY3VsYXRlIHRoZSBub2RlcycgYW5kIGxpbmtzJyB2ZXJ0aWNhbCBwb3NpdGlvbiB3aXRoaW4gdGhlaXIgcmVzcGVjdGl2ZSBjb2x1bW5cbiAgICAgIC8vICAgICBBbHNvIHJlYWRqdXN0cyBzYW5rZXlDaXJjdWxhciBzaXplIGlmIGNpcmN1bGFyIGxpbmtzIGFyZSBuZWVkZWQsIGFuZCBub2RlIHgnc1xuICAgICAgLy8gY29tcHV0ZU5vZGVCcmVhZHRocyhncmFwaCwgaXRlcmF0aW9ucywgaWQpXG4gICAgICBjb21wdXRlTGlua0JyZWFkdGhzKGdyYXBoKTtcblxuICAgICAgLy8gRm9yY2UgcG9zaXRpb24gb2YgY2lyY3VsYXIgbGluayB0eXBlIGJhc2VkIG9uIHBvc2l0aW9uXG4gICAgICBncmFwaC5saW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5rKSB7XG4gICAgICAgIGlmIChsaW5rLmNpcmN1bGFyKSB7XG4gICAgICAgICAgbGluay5jaXJjdWxhckxpbmtUeXBlID0gbGluay55MCArIGxpbmsueTEgPCB5MSA/ICd0b3AnIDogJ2JvdHRvbSc7XG5cbiAgICAgICAgICBsaW5rLnNvdXJjZS5jaXJjdWxhckxpbmtUeXBlID0gbGluay5jaXJjdWxhckxpbmtUeXBlO1xuICAgICAgICAgIGxpbmsudGFyZ2V0LmNpcmN1bGFyTGlua1R5cGUgPSBsaW5rLmNpcmN1bGFyTGlua1R5cGU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBzb3J0U291cmNlTGlua3MoZ3JhcGgsIHkxLCBpZCwgZmFsc2UpOyAvLyBTb3J0IGxpbmtzIGJ1dCBkbyBub3QgbW92ZSBub2Rlc1xuICAgICAgc29ydFRhcmdldExpbmtzKGdyYXBoLCB5MSwgaWQpO1xuXG4gICAgICAvLyA3LiAgU29ydCBsaW5rcyBwZXIgbm9kZSwgYmFzZWQgb24gdGhlIGxpbmtzJyBzb3VyY2UvdGFyZ2V0IG5vZGVzJyBicmVhZHRoc1xuICAgICAgLy8gOC4gIEFkanVzdCBub2RlcyB0aGF0IG92ZXJsYXAgbGlua3MgdGhhdCBzcGFuIDIrIGNvbHVtbnNcbiAgICAgIC8vIHZhciBsaW5rU29ydGluZ0l0ZXJhdGlvbnMgPSA0OyAvL1Bvc3NpYmx5IGxldCB1c2VyIGNvbnRyb2wgdGhpcyBudW1iZXIsIGxpa2UgdGhlIGl0ZXJhdGlvbnMgb3ZlciBub2RlIHBsYWNlbWVudFxuICAgICAgLy8gZm9yICh2YXIgaXRlcmF0aW9uID0gMDsgaXRlcmF0aW9uIDwgbGlua1NvcnRpbmdJdGVyYXRpb25zOyBpdGVyYXRpb24rKykge1xuICAgICAgLy9cbiAgICAgIC8vICAgc29ydFNvdXJjZUxpbmtzKGdyYXBoLCB5MSwgaWQpXG4gICAgICAvLyAgIHNvcnRUYXJnZXRMaW5rcyhncmFwaCwgeTEsIGlkKVxuICAgICAgLy8gICByZXNvbHZlTm9kZUxpbmtPdmVybGFwcyhncmFwaCwgeTAsIHkxLCBpZClcbiAgICAgIC8vICAgc29ydFNvdXJjZUxpbmtzKGdyYXBoLCB5MSwgaWQpXG4gICAgICAvLyAgIHNvcnRUYXJnZXRMaW5rcyhncmFwaCwgeTEsIGlkKVxuICAgICAgLy9cbiAgICAgIC8vIH1cblxuICAgICAgLy8gOC4xICBBZGp1c3Qgbm9kZSBhbmQgbGluayBwb3NpdGlvbnMgYmFjayB0byBmaWxsIGhlaWdodCBvZiBjaGFydCBhcmVhIGlmIGNvbXByZXNzZWRcbiAgICAgIC8vIGZpbGxIZWlnaHQoZ3JhcGgsIHkwLCB5MSlcblxuICAgICAgLy8gOS4gQ2FsY3VsYXRlIHZpc3VhbGx5IGFwcGVhbGxpbmcgcGF0aCBmb3IgdGhlIGNpcmN1bGFyIHBhdGhzLCBhbmQgY3JlYXRlIHRoZSBcImRcIiBzdHJpbmdcbiAgICAgIGFkZENpcmN1bGFyUGF0aERhdGEoZ3JhcGgsIGNpcmN1bGFyTGlua0dhcCwgeTEsIGlkKTtcbiAgICAgIHJldHVybiBncmFwaDtcbiAgICB9O1xuXG4gICAgLy8gUG9wdWxhdGUgdGhlIHNvdXJjZUxpbmtzIGFuZCB0YXJnZXRMaW5rcyBmb3IgZWFjaCBub2RlLlxuICAgIC8vIEFsc28sIGlmIHRoZSBzb3VyY2UgYW5kIHRhcmdldCBhcmUgbm90IG9iamVjdHMsIGFzc3VtZSB0aGV5IGFyZSBpbmRpY2VzLlxuICAgIGZ1bmN0aW9uIGNvbXB1dGVOb2RlTGlua3MoZ3JhcGgpIHtcbiAgICAgIGdyYXBoLm5vZGVzLmZvckVhY2goZnVuY3Rpb24gKG5vZGUsIGkpIHtcbiAgICAgICAgbm9kZS5pbmRleCA9IGk7XG4gICAgICAgIG5vZGUuc291cmNlTGlua3MgPSBbXTtcbiAgICAgICAgbm9kZS50YXJnZXRMaW5rcyA9IFtdO1xuICAgICAgfSk7XG4gICAgICB2YXIgbm9kZUJ5SWQgPSBkM0NvbGxlY3Rpb24ubWFwKGdyYXBoLm5vZGVzLCBpZCk7XG4gICAgICBncmFwaC5saW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5rLCBpKSB7XG4gICAgICAgIGxpbmsuaW5kZXggPSBpO1xuICAgICAgICB2YXIgc291cmNlID0gbGluay5zb3VyY2U7XG4gICAgICAgIHZhciB0YXJnZXQgPSBsaW5rLnRhcmdldDtcbiAgICAgICAgaWYgKCh0eXBlb2Ygc291cmNlID09PSBcInVuZGVmaW5lZFwiID8gXCJ1bmRlZmluZWRcIiA6IF90eXBlb2Yoc291cmNlKSkgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgc291cmNlID0gbGluay5zb3VyY2UgPSBmaW5kKG5vZGVCeUlkLCBzb3VyY2UpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgodHlwZW9mIHRhcmdldCA9PT0gXCJ1bmRlZmluZWRcIiA/IFwidW5kZWZpbmVkXCIgOiBfdHlwZW9mKHRhcmdldCkpICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgIHRhcmdldCA9IGxpbmsudGFyZ2V0ID0gZmluZChub2RlQnlJZCwgdGFyZ2V0KTtcbiAgICAgICAgfVxuICAgICAgICBzb3VyY2Uuc291cmNlTGlua3MucHVzaChsaW5rKTtcbiAgICAgICAgdGFyZ2V0LnRhcmdldExpbmtzLnB1c2gobGluayk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBncmFwaDtcbiAgICB9XG5cbiAgICAvLyBDb21wdXRlIHRoZSB2YWx1ZSAoc2l6ZSkgYW5kIGN5Y2xlbmVzcyBvZiBlYWNoIG5vZGUgYnkgc3VtbWluZyB0aGUgYXNzb2NpYXRlZCBsaW5rcy5cbiAgICBmdW5jdGlvbiBjb21wdXRlTm9kZVZhbHVlcyhncmFwaCkge1xuICAgICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICBub2RlLnBhcnRPZkN5Y2xlID0gZmFsc2U7XG4gICAgICAgIG5vZGUudmFsdWUgPSBNYXRoLm1heChkM0FycmF5LnN1bShub2RlLnNvdXJjZUxpbmtzLCB2YWx1ZSksIGQzQXJyYXkuc3VtKG5vZGUudGFyZ2V0TGlua3MsIHZhbHVlKSk7XG4gICAgICAgIG5vZGUuc291cmNlTGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaykge1xuICAgICAgICAgIGlmIChsaW5rLmNpcmN1bGFyKSB7XG4gICAgICAgICAgICBub2RlLnBhcnRPZkN5Y2xlID0gdHJ1ZTtcbiAgICAgICAgICAgIG5vZGUuY2lyY3VsYXJMaW5rVHlwZSA9IGxpbmsuY2lyY3VsYXJMaW5rVHlwZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBub2RlLnRhcmdldExpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgICAgICBpZiAobGluay5jaXJjdWxhcikge1xuICAgICAgICAgICAgbm9kZS5wYXJ0T2ZDeWNsZSA9IHRydWU7XG4gICAgICAgICAgICBub2RlLmNpcmN1bGFyTGlua1R5cGUgPSBsaW5rLmNpcmN1bGFyTGlua1R5cGU7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldENpcmNsZU1hcmdpbnMoZ3JhcGgpIHtcbiAgICAgIHZhciB0b3RhbFRvcExpbmtzV2lkdGggPSAwLFxuICAgICAgICAgIHRvdGFsQm90dG9tTGlua3NXaWR0aCA9IDAsXG4gICAgICAgICAgdG90YWxSaWdodExpbmtzV2lkdGggPSAwLFxuICAgICAgICAgIHRvdGFsTGVmdExpbmtzV2lkdGggPSAwO1xuXG4gICAgICB2YXIgbWF4Q29sdW1uID0gZDNBcnJheS5tYXgoZ3JhcGgubm9kZXMsIGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgIHJldHVybiBub2RlLmNvbHVtbjtcbiAgICAgIH0pO1xuXG4gICAgICBncmFwaC5saW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5rKSB7XG4gICAgICAgIGlmIChsaW5rLmNpcmN1bGFyKSB7XG4gICAgICAgICAgaWYgKGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9PSAndG9wJykge1xuICAgICAgICAgICAgdG90YWxUb3BMaW5rc1dpZHRoID0gdG90YWxUb3BMaW5rc1dpZHRoICsgbGluay53aWR0aDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdG90YWxCb3R0b21MaW5rc1dpZHRoID0gdG90YWxCb3R0b21MaW5rc1dpZHRoICsgbGluay53aWR0aDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobGluay50YXJnZXQuY29sdW1uID09IDApIHtcbiAgICAgICAgICAgIHRvdGFsTGVmdExpbmtzV2lkdGggPSB0b3RhbExlZnRMaW5rc1dpZHRoICsgbGluay53aWR0aDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobGluay5zb3VyY2UuY29sdW1uID09IG1heENvbHVtbikge1xuICAgICAgICAgICAgdG90YWxSaWdodExpbmtzV2lkdGggPSB0b3RhbFJpZ2h0TGlua3NXaWR0aCArIGxpbmsud2lkdGg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgLy9hY2NvdW50IGZvciByYWRpdXMgb2YgY3VydmVzIGFuZCBwYWRkaW5nIGJldHdlZW4gbGlua3NcbiAgICAgIHRvdGFsVG9wTGlua3NXaWR0aCA9IHRvdGFsVG9wTGlua3NXaWR0aCA+IDAgPyB0b3RhbFRvcExpbmtzV2lkdGggKyB2ZXJ0aWNhbE1hcmdpbiArIGJhc2VSYWRpdXMgOiB0b3RhbFRvcExpbmtzV2lkdGg7XG4gICAgICB0b3RhbEJvdHRvbUxpbmtzV2lkdGggPSB0b3RhbEJvdHRvbUxpbmtzV2lkdGggPiAwID8gdG90YWxCb3R0b21MaW5rc1dpZHRoICsgdmVydGljYWxNYXJnaW4gKyBiYXNlUmFkaXVzIDogdG90YWxCb3R0b21MaW5rc1dpZHRoO1xuICAgICAgdG90YWxSaWdodExpbmtzV2lkdGggPSB0b3RhbFJpZ2h0TGlua3NXaWR0aCA+IDAgPyB0b3RhbFJpZ2h0TGlua3NXaWR0aCArIHZlcnRpY2FsTWFyZ2luICsgYmFzZVJhZGl1cyA6IHRvdGFsUmlnaHRMaW5rc1dpZHRoO1xuICAgICAgdG90YWxMZWZ0TGlua3NXaWR0aCA9IHRvdGFsTGVmdExpbmtzV2lkdGggPiAwID8gdG90YWxMZWZ0TGlua3NXaWR0aCArIHZlcnRpY2FsTWFyZ2luICsgYmFzZVJhZGl1cyA6IHRvdGFsTGVmdExpbmtzV2lkdGg7XG5cbiAgICAgIHJldHVybiB7IFwidG9wXCI6IHRvdGFsVG9wTGlua3NXaWR0aCwgXCJib3R0b21cIjogdG90YWxCb3R0b21MaW5rc1dpZHRoLCBcImxlZnRcIjogdG90YWxMZWZ0TGlua3NXaWR0aCwgXCJyaWdodFwiOiB0b3RhbFJpZ2h0TGlua3NXaWR0aCB9O1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSB0aGUgeDAsIHkwLCB4MSBhbmQgeTEgZm9yIHRoZSBzYW5rZXlDaXJjdWxhciwgdG8gYWxsb3cgc3BhY2UgZm9yIGFueSBjaXJjdWxhciBsaW5rc1xuICAgIGZ1bmN0aW9uIHNjYWxlU2Fua2V5U2l6ZShncmFwaCwgbWFyZ2luKSB7XG5cbiAgICAgIHZhciBtYXhDb2x1bW4gPSBkM0FycmF5Lm1heChncmFwaC5ub2RlcywgZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgcmV0dXJuIG5vZGUuY29sdW1uO1xuICAgICAgfSk7XG5cbiAgICAgIHZhciBjdXJyZW50V2lkdGggPSB4MSAtIHgwO1xuICAgICAgdmFyIGN1cnJlbnRIZWlnaHQgPSB5MSAtIHkwO1xuXG4gICAgICB2YXIgbmV3V2lkdGggPSBjdXJyZW50V2lkdGggKyBtYXJnaW4ucmlnaHQgKyBtYXJnaW4ubGVmdDtcbiAgICAgIHZhciBuZXdIZWlnaHQgPSBjdXJyZW50SGVpZ2h0ICsgbWFyZ2luLnRvcCArIG1hcmdpbi5ib3R0b207XG5cbiAgICAgIHZhciBzY2FsZVggPSBjdXJyZW50V2lkdGggLyBuZXdXaWR0aDtcbiAgICAgIHZhciBzY2FsZVkgPSBjdXJyZW50SGVpZ2h0IC8gbmV3SGVpZ2h0O1xuXG4gICAgICB4MCA9IHgwICogc2NhbGVYICsgbWFyZ2luLmxlZnQ7XG4gICAgICB4MSA9IG1hcmdpbi5yaWdodCA9PSAwID8geDEgOiB4MSAqIHNjYWxlWDtcbiAgICAgIHkwID0geTAgKiBzY2FsZVkgKyBtYXJnaW4udG9wO1xuICAgICAgeTEgPSB5MSAqIHNjYWxlWTtcblxuICAgICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICBub2RlLngwID0geDAgKyBub2RlLmNvbHVtbiAqICgoeDEgLSB4MCAtIGR4KSAvIG1heENvbHVtbik7XG4gICAgICAgIG5vZGUueDEgPSBub2RlLngwICsgZHg7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHNjYWxlWTtcbiAgICB9XG5cbiAgICAvLyBJdGVyYXRpdmVseSBhc3NpZ24gdGhlIGRlcHRoIGZvciBlYWNoIG5vZGUuXG4gICAgLy8gTm9kZXMgYXJlIGFzc2lnbmVkIHRoZSBtYXhpbXVtIGRlcHRoIG9mIGluY29taW5nIG5laWdoYm9ycyBwbHVzIG9uZTtcbiAgICAvLyBub2RlcyB3aXRoIG5vIGluY29taW5nIGxpbmtzIGFyZSBhc3NpZ25lZCBkZXB0aCB6ZXJvLCB3aGlsZVxuICAgIC8vIG5vZGVzIHdpdGggbm8gb3V0Z29pbmcgbGlua3MgYXJlIGFzc2lnbmVkIHRoZSBtYXhpbXVtIGRlcHRoLlxuICAgIGZ1bmN0aW9uIGNvbXB1dGVOb2RlRGVwdGhzKGdyYXBoKSB7XG4gICAgICB2YXIgbm9kZXMsIG5leHQsIHg7XG5cbiAgICAgIGZvciAobm9kZXMgPSBncmFwaC5ub2RlcywgbmV4dCA9IFtdLCB4ID0gMDsgbm9kZXMubGVuZ3RoOyArK3gsIG5vZGVzID0gbmV4dCwgbmV4dCA9IFtdKSB7XG4gICAgICAgIG5vZGVzLmZvckVhY2goZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICBub2RlLmRlcHRoID0geDtcbiAgICAgICAgICBub2RlLnNvdXJjZUxpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgICAgICAgIGlmIChuZXh0LmluZGV4T2YobGluay50YXJnZXQpIDwgMCAmJiAhbGluay5jaXJjdWxhcikge1xuICAgICAgICAgICAgICBuZXh0LnB1c2gobGluay50YXJnZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgZm9yIChub2RlcyA9IGdyYXBoLm5vZGVzLCBuZXh0ID0gW10sIHggPSAwOyBub2Rlcy5sZW5ndGg7ICsreCwgbm9kZXMgPSBuZXh0LCBuZXh0ID0gW10pIHtcbiAgICAgICAgbm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgIG5vZGUuaGVpZ2h0ID0geDtcbiAgICAgICAgICBub2RlLnRhcmdldExpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgICAgICAgIGlmIChuZXh0LmluZGV4T2YobGluay5zb3VyY2UpIDwgMCAmJiAhbGluay5jaXJjdWxhcikge1xuICAgICAgICAgICAgICBuZXh0LnB1c2gobGluay5zb3VyY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gYXNzaWduIGNvbHVtbiBudW1iZXJzLCBhbmQgZ2V0IG1heCB2YWx1ZVxuICAgICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICBub2RlLmNvbHVtbiA9IE1hdGguZmxvb3IoYWxpZ24uY2FsbChudWxsLCBub2RlLCB4KSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBBc3NpZ24gbm9kZXMnIGJyZWFkdGhzLCBhbmQgdGhlbiBzaGlmdCBub2RlcyB0aGF0IG92ZXJsYXAgKHJlc29sdmVDb2xsaXNpb25zKVxuICAgIGZ1bmN0aW9uIGNvbXB1dGVOb2RlQnJlYWR0aHMoZ3JhcGgsIGl0ZXJhdGlvbnMsIGlkKSB7XG4gICAgICB2YXIgY29sdW1ucyA9IGQzQ29sbGVjdGlvbi5uZXN0KCkua2V5KGZ1bmN0aW9uIChkKSB7XG4gICAgICAgIHJldHVybiBkLmNvbHVtbjtcbiAgICAgIH0pLnNvcnRLZXlzKGQzQXJyYXkuYXNjZW5kaW5nKS5lbnRyaWVzKGdyYXBoLm5vZGVzKS5tYXAoZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgcmV0dXJuIGQudmFsdWVzO1xuICAgICAgfSk7XG5cbiAgICAgIGluaXRpYWxpemVOb2RlQnJlYWR0aChpZCk7XG4gICAgICByZXNvbHZlQ29sbGlzaW9ucygpO1xuXG4gICAgICBmb3IgKHZhciBhbHBoYSA9IDEsIG4gPSBpdGVyYXRpb25zOyBuID4gMDsgLS1uKSB7XG4gICAgICAgIHJlbGF4TGVmdEFuZFJpZ2h0KGFscGhhICo9IDAuOTksIGlkKTtcbiAgICAgICAgcmVzb2x2ZUNvbGxpc2lvbnMoKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gaW5pdGlhbGl6ZU5vZGVCcmVhZHRoKGlkKSB7XG5cbiAgICAgICAgLy9vdmVycmlkZSBweSBpZiBub2RlUGFkZGluZyBoYXMgYmVlbiBzZXRcbiAgICAgICAgaWYgKHBhZGRpbmdSYXRpbykge1xuICAgICAgICAgIHZhciBwYWRkaW5nID0gSW5maW5pdHk7XG4gICAgICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uIChub2Rlcykge1xuICAgICAgICAgICAgdmFyIHRoaXNQYWRkaW5nID0geTEgKiBwYWRkaW5nUmF0aW8gLyAobm9kZXMubGVuZ3RoICsgMSk7XG4gICAgICAgICAgICBwYWRkaW5nID0gdGhpc1BhZGRpbmcgPCBwYWRkaW5nID8gdGhpc1BhZGRpbmcgOiBwYWRkaW5nO1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIHB5ID0gcGFkZGluZztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBreSA9IGQzQXJyYXkubWluKGNvbHVtbnMsIGZ1bmN0aW9uIChub2Rlcykge1xuICAgICAgICAgIHJldHVybiAoeTEgLSB5MCAtIChub2Rlcy5sZW5ndGggLSAxKSAqIHB5KSAvIGQzQXJyYXkuc3VtKG5vZGVzLCB2YWx1ZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vY2FsY3VsYXRlIHRoZSB3aWR0aHMgb2YgdGhlIGxpbmtzXG4gICAgICAgIGt5ID0ga3kgKiBzY2FsZTtcblxuICAgICAgICBncmFwaC5saW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5rKSB7XG4gICAgICAgICAgbGluay53aWR0aCA9IGxpbmsudmFsdWUgKiBreTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy9kZXRlcm1pbmUgaG93IG11Y2ggdG8gc2NhbGUgZG93biB0aGUgY2hhcnQsIGJhc2VkIG9uIGNpcmN1bGFyIGxpbmtzXG4gICAgICAgIHZhciBtYXJnaW4gPSBnZXRDaXJjbGVNYXJnaW5zKGdyYXBoKTtcbiAgICAgICAgdmFyIHJhdGlvID0gc2NhbGVTYW5rZXlTaXplKGdyYXBoLCBtYXJnaW4pO1xuXG4gICAgICAgIC8vcmUtY2FsY3VsYXRlIHdpZHRoc1xuICAgICAgICBreSA9IGt5ICogcmF0aW87XG5cbiAgICAgICAgZ3JhcGgubGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaykge1xuICAgICAgICAgIGxpbmsud2lkdGggPSBsaW5rLnZhbHVlICoga3k7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbHVtbnMuZm9yRWFjaChmdW5jdGlvbiAobm9kZXMpIHtcbiAgICAgICAgICB2YXIgbm9kZXNMZW5ndGggPSBub2Rlcy5sZW5ndGg7XG4gICAgICAgICAgbm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSwgaSkge1xuICAgICAgICAgICAgaWYgKG5vZGUuZGVwdGggPT0gY29sdW1ucy5sZW5ndGggLSAxICYmIG5vZGVzTGVuZ3RoID09IDEpIHtcbiAgICAgICAgICAgICAgbm9kZS55MCA9IHkxIC8gMiAtIG5vZGUudmFsdWUgKiBreTtcbiAgICAgICAgICAgICAgbm9kZS55MSA9IG5vZGUueTAgKyBub2RlLnZhbHVlICoga3k7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG5vZGUuZGVwdGggPT0gMCAmJiBub2Rlc0xlbmd0aCA9PSAxKSB7XG4gICAgICAgICAgICAgIG5vZGUueTAgPSB5MSAvIDIgLSBub2RlLnZhbHVlICoga3k7XG4gICAgICAgICAgICAgIG5vZGUueTEgPSBub2RlLnkwICsgbm9kZS52YWx1ZSAqIGt5O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChub2RlLnBhcnRPZkN5Y2xlKSB7XG4gICAgICAgICAgICAgIGlmIChudW1iZXJPZk5vblNlbGZMaW5raW5nQ3ljbGVzKG5vZGUsIGlkKSA9PSAwKSB7XG4gICAgICAgICAgICAgICAgbm9kZS55MCA9IHkxIC8gMiArIGk7XG4gICAgICAgICAgICAgICAgbm9kZS55MSA9IG5vZGUueTAgKyBub2RlLnZhbHVlICoga3k7XG4gICAgICAgICAgICAgIH0gZWxzZSBpZiAobm9kZS5jaXJjdWxhckxpbmtUeXBlID09ICd0b3AnKSB7XG4gICAgICAgICAgICAgICAgbm9kZS55MCA9IHkwICsgaTtcbiAgICAgICAgICAgICAgICBub2RlLnkxID0gbm9kZS55MCArIG5vZGUudmFsdWUgKiBreTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBub2RlLnkwID0geTEgLSBub2RlLnZhbHVlICoga3kgLSBpO1xuICAgICAgICAgICAgICAgIG5vZGUueTEgPSBub2RlLnkwICsgbm9kZS52YWx1ZSAqIGt5O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAobWFyZ2luLnRvcCA9PSAwIHx8IG1hcmdpbi5ib3R0b20gPT0gMCkge1xuICAgICAgICAgICAgICAgIG5vZGUueTAgPSAoeTEgLSB5MCkgLyBub2Rlc0xlbmd0aCAqIGk7XG4gICAgICAgICAgICAgICAgbm9kZS55MSA9IG5vZGUueTAgKyBub2RlLnZhbHVlICoga3k7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbm9kZS55MCA9ICh5MSAtIHkwKSAvIDIgLSBub2Rlc0xlbmd0aCAvIDIgKyBpO1xuICAgICAgICAgICAgICAgIG5vZGUueTEgPSBub2RlLnkwICsgbm9kZS52YWx1ZSAqIGt5O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyBGb3IgZWFjaCBub2RlIGluIGVhY2ggY29sdW1uLCBjaGVjayB0aGUgbm9kZSdzIHZlcnRpY2FsIHBvc2l0aW9uIGluIHJlbGF0aW9uIHRvIGl0cyB0YXJnZXRzIGFuZCBzb3VyY2VzIHZlcnRpY2FsIHBvc2l0aW9uXG4gICAgICAvLyBhbmQgc2hpZnQgdXAvZG93biB0byBiZSBjbG9zZXIgdG8gdGhlIHZlcnRpY2FsIG1pZGRsZSBvZiB0aG9zZSB0YXJnZXRzIGFuZCBzb3VyY2VzXG4gICAgICBmdW5jdGlvbiByZWxheExlZnRBbmRSaWdodChhbHBoYSwgaWQpIHtcbiAgICAgICAgdmFyIGNvbHVtbnNMZW5ndGggPSBjb2x1bW5zLmxlbmd0aDtcblxuICAgICAgICBjb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKG5vZGVzKSB7XG4gICAgICAgICAgdmFyIG4gPSBub2Rlcy5sZW5ndGg7XG4gICAgICAgICAgdmFyIGRlcHRoID0gbm9kZXNbMF0uZGVwdGg7XG5cbiAgICAgICAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgICAgICAvLyBjaGVjayB0aGUgbm9kZSBpcyBub3QgYW4gb3JwaGFuXG4gICAgICAgICAgICB2YXIgbm9kZUhlaWdodDtcbiAgICAgICAgICAgIGlmIChub2RlLnNvdXJjZUxpbmtzLmxlbmd0aCB8fCBub2RlLnRhcmdldExpbmtzLmxlbmd0aCkge1xuICAgICAgICAgICAgICBpZiAobm9kZS5wYXJ0T2ZDeWNsZSAmJiBudW1iZXJPZk5vblNlbGZMaW5raW5nQ3ljbGVzKG5vZGUsIGlkKSA+IDApIDsgZWxzZSBpZiAoZGVwdGggPT0gMCAmJiBuID09IDEpIHtcbiAgICAgICAgICAgICAgICBub2RlSGVpZ2h0ID0gbm9kZS55MSAtIG5vZGUueTA7XG5cbiAgICAgICAgICAgICAgICBub2RlLnkwID0geTEgLyAyIC0gbm9kZUhlaWdodCAvIDI7XG4gICAgICAgICAgICAgICAgbm9kZS55MSA9IHkxIC8gMiArIG5vZGVIZWlnaHQgLyAyO1xuICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRlcHRoID09IGNvbHVtbnNMZW5ndGggLSAxICYmIG4gPT0gMSkge1xuICAgICAgICAgICAgICAgIG5vZGVIZWlnaHQgPSBub2RlLnkxIC0gbm9kZS55MDtcblxuICAgICAgICAgICAgICAgIG5vZGUueTAgPSB5MSAvIDIgLSBub2RlSGVpZ2h0IC8gMjtcbiAgICAgICAgICAgICAgICBub2RlLnkxID0geTEgLyAyICsgbm9kZUhlaWdodCAvIDI7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGF2ZyA9IDA7XG5cbiAgICAgICAgICAgICAgICB2YXIgYXZnVGFyZ2V0WSA9IGQzQXJyYXkubWVhbihub2RlLnNvdXJjZUxpbmtzLCBsaW5rVGFyZ2V0Q2VudGVyKTtcbiAgICAgICAgICAgICAgICB2YXIgYXZnU291cmNlWSA9IGQzQXJyYXkubWVhbihub2RlLnRhcmdldExpbmtzLCBsaW5rU291cmNlQ2VudGVyKTtcblxuICAgICAgICAgICAgICAgIGlmIChhdmdUYXJnZXRZICYmIGF2Z1NvdXJjZVkpIHtcbiAgICAgICAgICAgICAgICAgIGF2ZyA9IChhdmdUYXJnZXRZICsgYXZnU291cmNlWSkgLyAyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBhdmcgPSBhdmdUYXJnZXRZIHx8IGF2Z1NvdXJjZVk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGR5ID0gKGF2ZyAtIG5vZGVDZW50ZXIobm9kZSkpICogYWxwaGE7XG4gICAgICAgICAgICAgICAgLy8gcG9zaXRpdmUgaWYgaXQgbm9kZSBuZWVkcyB0byBtb3ZlIGRvd25cbiAgICAgICAgICAgICAgICBub2RlLnkwICs9IGR5O1xuICAgICAgICAgICAgICAgIG5vZGUueTEgKz0gZHk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIEZvciBlYWNoIGNvbHVtbiwgY2hlY2sgaWYgbm9kZXMgYXJlIG92ZXJsYXBwaW5nLCBhbmQgaWYgc28sIHNoaWZ0IHVwL2Rvd25cbiAgICAgIGZ1bmN0aW9uIHJlc29sdmVDb2xsaXNpb25zKCkge1xuICAgICAgICBjb2x1bW5zLmZvckVhY2goZnVuY3Rpb24gKG5vZGVzKSB7XG4gICAgICAgICAgdmFyIG5vZGUsXG4gICAgICAgICAgICAgIGR5LFxuICAgICAgICAgICAgICB5ID0geTAsXG4gICAgICAgICAgICAgIG4gPSBub2Rlcy5sZW5ndGgsXG4gICAgICAgICAgICAgIGk7XG5cbiAgICAgICAgICAvLyBQdXNoIGFueSBvdmVybGFwcGluZyBub2RlcyBkb3duLlxuICAgICAgICAgIG5vZGVzLnNvcnQoYXNjZW5kaW5nQnJlYWR0aCk7XG5cbiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgICAgICBub2RlID0gbm9kZXNbaV07XG4gICAgICAgICAgICBkeSA9IHkgLSBub2RlLnkwO1xuXG4gICAgICAgICAgICBpZiAoZHkgPiAwKSB7XG4gICAgICAgICAgICAgIG5vZGUueTAgKz0gZHk7XG4gICAgICAgICAgICAgIG5vZGUueTEgKz0gZHk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB5ID0gbm9kZS55MSArIHB5O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIElmIHRoZSBib3R0b21tb3N0IG5vZGUgZ29lcyBvdXRzaWRlIHRoZSBib3VuZHMsIHB1c2ggaXQgYmFjayB1cC5cbiAgICAgICAgICBkeSA9IHkgLSBweSAtIHkxO1xuICAgICAgICAgIGlmIChkeSA+IDApIHtcbiAgICAgICAgICAgIHkgPSBub2RlLnkwIC09IGR5LCBub2RlLnkxIC09IGR5O1xuXG4gICAgICAgICAgICAvLyBQdXNoIGFueSBvdmVybGFwcGluZyBub2RlcyBiYWNrIHVwLlxuICAgICAgICAgICAgZm9yIChpID0gbiAtIDI7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgICAgICAgZHkgPSBub2RlLnkxICsgcHkgLSB5O1xuICAgICAgICAgICAgICBpZiAoZHkgPiAwKSBub2RlLnkwIC09IGR5LCBub2RlLnkxIC09IGR5O1xuICAgICAgICAgICAgICB5ID0gbm9kZS55MDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFzc2lnbiB0aGUgbGlua3MgeTAgYW5kIHkxIGJhc2VkIG9uIHNvdXJjZS90YXJnZXQgbm9kZXMgcG9zaXRpb24sXG4gICAgLy8gcGx1cyB0aGUgbGluaydzIHJlbGF0aXZlIHBvc2l0aW9uIHRvIG90aGVyIGxpbmtzIHRvIHRoZSBzYW1lIG5vZGVcbiAgICBmdW5jdGlvbiBjb21wdXRlTGlua0JyZWFkdGhzKGdyYXBoKSB7XG4gICAgICBncmFwaC5ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgIG5vZGUuc291cmNlTGlua3Muc29ydChhc2NlbmRpbmdUYXJnZXRCcmVhZHRoKTtcbiAgICAgICAgbm9kZS50YXJnZXRMaW5rcy5zb3J0KGFzY2VuZGluZ1NvdXJjZUJyZWFkdGgpO1xuICAgICAgfSk7XG4gICAgICBncmFwaC5ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgIHZhciB5MCA9IG5vZGUueTA7XG4gICAgICAgIHZhciB5MSA9IHkwO1xuXG4gICAgICAgIC8vIHN0YXJ0IGZyb20gdGhlIGJvdHRvbSBvZiB0aGUgbm9kZSBmb3IgY3ljbGUgbGlua3NcbiAgICAgICAgdmFyIHkwY3ljbGUgPSBub2RlLnkxO1xuICAgICAgICB2YXIgeTFjeWNsZSA9IHkwY3ljbGU7XG5cbiAgICAgICAgbm9kZS5zb3VyY2VMaW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5rKSB7XG4gICAgICAgICAgaWYgKGxpbmsuY2lyY3VsYXIpIHtcbiAgICAgICAgICAgIGxpbmsueTAgPSB5MGN5Y2xlIC0gbGluay53aWR0aCAvIDI7XG4gICAgICAgICAgICB5MGN5Y2xlID0geTBjeWNsZSAtIGxpbmsud2lkdGg7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxpbmsueTAgPSB5MCArIGxpbmsud2lkdGggLyAyO1xuICAgICAgICAgICAgeTAgKz0gbGluay53aWR0aDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBub2RlLnRhcmdldExpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgICAgICBpZiAobGluay5jaXJjdWxhcikge1xuICAgICAgICAgICAgbGluay55MSA9IHkxY3ljbGUgLSBsaW5rLndpZHRoIC8gMjtcbiAgICAgICAgICAgIHkxY3ljbGUgPSB5MWN5Y2xlIC0gbGluay53aWR0aDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGluay55MSA9IHkxICsgbGluay53aWR0aCAvIDI7XG4gICAgICAgICAgICB5MSArPSBsaW5rLndpZHRoO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2Fua2V5Q2lyY3VsYXI7XG4gIH1cblxuICAvLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gIC8vIEN5Y2xlIGZ1bmN0aW9uc1xuICAvLyBwb3J0aW9uIG9mIGNvZGUgdG8gZGV0ZWN0IGNpcmN1bGFyIGxpbmtzIGJhc2VkIG9uIENvbGluIEZlcmd1cycgYmwub2NrIGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2NmZXJndXMvMzk1NjA0M1xuXG4gIC8vIElkZW50aWZ5IGNpcmNsZXMgaW4gdGhlIGxpbmsgb2JqZWN0c1xuICBmdW5jdGlvbiBpZGVudGlmeUNpcmNsZXMoZ3JhcGgsIGlkLCBzb3J0Tm9kZXMpIHtcbiAgICB2YXIgY2lyY3VsYXJMaW5rSUQgPSAwO1xuICAgIGlmIChzb3J0Tm9kZXMgPT09IG51bGwpIHtcblxuICAgICAgLy8gQnVpbGRpbmcgYWRqYWNlbmN5IGdyYXBoXG4gICAgICB2YXIgYWRqTGlzdCA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBncmFwaC5saW5rcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGluayA9IGdyYXBoLmxpbmtzW2ldO1xuICAgICAgICB2YXIgc291cmNlID0gbGluay5zb3VyY2UuaW5kZXg7XG4gICAgICAgIHZhciB0YXJnZXQgPSBsaW5rLnRhcmdldC5pbmRleDtcbiAgICAgICAgaWYgKCFhZGpMaXN0W3NvdXJjZV0pIGFkakxpc3Rbc291cmNlXSA9IFtdO1xuICAgICAgICBpZiAoIWFkakxpc3RbdGFyZ2V0XSkgYWRqTGlzdFt0YXJnZXRdID0gW107XG5cbiAgICAgICAgLy8gQWRkIGxpbmtzIGlmIG5vdCBhbHJlYWR5IGluIHNldFxuICAgICAgICBpZiAoYWRqTGlzdFtzb3VyY2VdLmluZGV4T2YodGFyZ2V0KSA9PT0gLTEpIGFkakxpc3Rbc291cmNlXS5wdXNoKHRhcmdldCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEZpbmQgYWxsIGVsZW1lbnRhcnkgY2lyY3VpdHNcbiAgICAgIHZhciBjeWNsZXMgPSBmaW5kQ2lyY3VpdHMoYWRqTGlzdCk7XG5cbiAgICAgIC8vIFNvcnQgYnkgY2lyY3VpdHMgbGVuZ3RoXG4gICAgICBjeWNsZXMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICByZXR1cm4gYS5sZW5ndGggLSBiLmxlbmd0aDtcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgY2lyY3VsYXJMaW5rcyA9IHt9O1xuICAgICAgZm9yIChpID0gMDsgaSA8IGN5Y2xlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY3ljbGUgPSBjeWNsZXNbaV07XG4gICAgICAgIHZhciBsYXN0ID0gY3ljbGUuc2xpY2UoLTIpO1xuICAgICAgICBpZiAoIWNpcmN1bGFyTGlua3NbbGFzdFswXV0pIGNpcmN1bGFyTGlua3NbbGFzdFswXV0gPSB7fTtcbiAgICAgICAgY2lyY3VsYXJMaW5rc1tsYXN0WzBdXVtsYXN0WzFdXSA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGdyYXBoLmxpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgICAgdmFyIHRhcmdldCA9IGxpbmsudGFyZ2V0LmluZGV4O1xuICAgICAgICB2YXIgc291cmNlID0gbGluay5zb3VyY2UuaW5kZXg7XG4gICAgICAgIC8vIElmIHNlbGYtbGlua2luZyBvciBhIGJhY2stZWRnZVxuICAgICAgICBpZiAodGFyZ2V0ID09PSBzb3VyY2UgfHwgY2lyY3VsYXJMaW5rc1tzb3VyY2VdICYmIGNpcmN1bGFyTGlua3Nbc291cmNlXVt0YXJnZXRdKSB7XG4gICAgICAgICAgbGluay5jaXJjdWxhciA9IHRydWU7XG4gICAgICAgICAgbGluay5jaXJjdWxhckxpbmtJRCA9IGNpcmN1bGFyTGlua0lEO1xuICAgICAgICAgIGNpcmN1bGFyTGlua0lEID0gY2lyY3VsYXJMaW5rSUQgKyAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxpbmsuY2lyY3VsYXIgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGdyYXBoLmxpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgICAgaWYgKGxpbmsuc291cmNlW3NvcnROb2Rlc10gPCBsaW5rLnRhcmdldFtzb3J0Tm9kZXNdKSB7XG4gICAgICAgICAgbGluay5jaXJjdWxhciA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxpbmsuY2lyY3VsYXIgPSB0cnVlO1xuICAgICAgICAgIGxpbmsuY2lyY3VsYXJMaW5rSUQgPSBjaXJjdWxhckxpbmtJRDtcbiAgICAgICAgICBjaXJjdWxhckxpbmtJRCA9IGNpcmN1bGFyTGlua0lEICsgMTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLy8gQXNzaWduIGEgY2lyY3VsYXIgbGluayB0eXBlICh0b3Agb3IgYm90dG9tKSwgYmFzZWQgb246XG4gIC8vIC0gaWYgdGhlIHNvdXJjZS90YXJnZXQgbm9kZSBhbHJlYWR5IGhhcyBjaXJjdWxhciBsaW5rcywgdGhlbiB1c2UgdGhlIHNhbWUgdHlwZVxuICAvLyAtIGlmIG5vdCwgY2hvb3NlIHRoZSB0eXBlIHdpdGggZmV3ZXIgbGlua3NcbiAgZnVuY3Rpb24gc2VsZWN0Q2lyY3VsYXJMaW5rVHlwZXMoZ3JhcGgsIGlkKSB7XG4gICAgdmFyIG51bWJlck9mVG9wcyA9IDA7XG4gICAgdmFyIG51bWJlck9mQm90dG9tcyA9IDA7XG4gICAgZ3JhcGgubGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaykge1xuICAgICAgaWYgKGxpbmsuY2lyY3VsYXIpIHtcbiAgICAgICAgLy8gaWYgZWl0aGVyIHNvdWNlIG9yIHRhcmdldCBoYXMgdHlwZSBhbHJlYWR5IHVzZSB0aGF0XG4gICAgICAgIGlmIChsaW5rLnNvdXJjZS5jaXJjdWxhckxpbmtUeXBlIHx8IGxpbmsudGFyZ2V0LmNpcmN1bGFyTGlua1R5cGUpIHtcbiAgICAgICAgICAvLyBkZWZhdWx0IHRvIHNvdXJjZSB0eXBlIGlmIGF2YWlsYWJsZVxuICAgICAgICAgIGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9IGxpbmsuc291cmNlLmNpcmN1bGFyTGlua1R5cGUgPyBsaW5rLnNvdXJjZS5jaXJjdWxhckxpbmtUeXBlIDogbGluay50YXJnZXQuY2lyY3VsYXJMaW5rVHlwZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsaW5rLmNpcmN1bGFyTGlua1R5cGUgPSBudW1iZXJPZlRvcHMgPCBudW1iZXJPZkJvdHRvbXMgPyAndG9wJyA6ICdib3R0b20nO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9PSAndG9wJykge1xuICAgICAgICAgIG51bWJlck9mVG9wcyA9IG51bWJlck9mVG9wcyArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbnVtYmVyT2ZCb3R0b21zID0gbnVtYmVyT2ZCb3R0b21zICsgMTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdyYXBoLm5vZGVzLmZvckVhY2goZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICBpZiAoZ2V0Tm9kZUlEKG5vZGUsIGlkKSA9PSBnZXROb2RlSUQobGluay5zb3VyY2UsIGlkKSB8fCBnZXROb2RlSUQobm9kZSwgaWQpID09IGdldE5vZGVJRChsaW5rLnRhcmdldCwgaWQpKSB7XG4gICAgICAgICAgICBub2RlLmNpcmN1bGFyTGlua1R5cGUgPSBsaW5rLmNpcmN1bGFyTGlua1R5cGU7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vY29ycmVjdCBzZWxmLWxpbmtpbmcgbGlua3MgdG8gYmUgc2FtZSBkaXJlY3Rpb24gYXMgbm9kZVxuICAgIGdyYXBoLmxpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgIGlmIChsaW5rLmNpcmN1bGFyKSB7XG4gICAgICAgIC8vaWYgYm90aCBzb3VyY2UgYW5kIHRhcmdldCBub2RlIGFyZSBzYW1lIHR5cGUsIHRoZW4gbGluayBzaG91bGQgaGF2ZSBzYW1lIHR5cGVcbiAgICAgICAgaWYgKGxpbmsuc291cmNlLmNpcmN1bGFyTGlua1R5cGUgPT0gbGluay50YXJnZXQuY2lyY3VsYXJMaW5rVHlwZSkge1xuICAgICAgICAgIGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9IGxpbmsuc291cmNlLmNpcmN1bGFyTGlua1R5cGU7XG4gICAgICAgIH1cbiAgICAgICAgLy9pZiBsaW5rIGlzIHNlbGZsaW5raW5nLCB0aGVuIGxpbmsgc2hvdWxkIGhhdmUgc2FtZSB0eXBlIGFzIG5vZGVcbiAgICAgICAgaWYgKHNlbGZMaW5raW5nKGxpbmssIGlkKSkge1xuICAgICAgICAgIGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9IGxpbmsuc291cmNlLmNpcmN1bGFyTGlua1R5cGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIFJldHVybiB0aGUgYW5nbGUgYmV0d2VlbiBhIHN0cmFpZ2h0IGxpbmUgYmV0d2VlbiB0aGUgc291cmNlIGFuZCB0YXJnZXQgb2YgdGhlIGxpbmssIGFuZCB0aGUgdmVydGljYWwgcGxhbmUgb2YgdGhlIG5vZGVcbiAgZnVuY3Rpb24gbGlua0FuZ2xlKGxpbmspIHtcbiAgICB2YXIgYWRqYWNlbnQgPSBNYXRoLmFicyhsaW5rLnkxIC0gbGluay55MCk7XG4gICAgdmFyIG9wcG9zaXRlID0gTWF0aC5hYnMobGluay50YXJnZXQueDAgLSBsaW5rLnNvdXJjZS54MSk7XG5cbiAgICByZXR1cm4gTWF0aC5hdGFuKG9wcG9zaXRlIC8gYWRqYWNlbnQpO1xuICB9XG5cbiAgLy8gQ2hlY2sgaWYgdHdvIGNpcmN1bGFyIGxpbmtzIHBvdGVudGlhbGx5IG92ZXJsYXBcbiAgZnVuY3Rpb24gY2lyY3VsYXJMaW5rc0Nyb3NzKGxpbmsxLCBsaW5rMikge1xuICAgIGlmIChsaW5rMS5zb3VyY2UuY29sdW1uIDwgbGluazIudGFyZ2V0LmNvbHVtbikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSBpZiAobGluazEudGFyZ2V0LmNvbHVtbiA+IGxpbmsyLnNvdXJjZS5jb2x1bW4pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgLy8gUmV0dXJuIHRoZSBudW1iZXIgb2YgY2lyY3VsYXIgbGlua3MgZm9yIG5vZGUsIG5vdCBpbmNsdWRpbmcgc2VsZiBsaW5raW5nIGxpbmtzXG4gIGZ1bmN0aW9uIG51bWJlck9mTm9uU2VsZkxpbmtpbmdDeWNsZXMobm9kZSwgaWQpIHtcbiAgICB2YXIgc291cmNlQ291bnQgPSAwO1xuICAgIG5vZGUuc291cmNlTGlua3MuZm9yRWFjaChmdW5jdGlvbiAobCkge1xuICAgICAgc291cmNlQ291bnQgPSBsLmNpcmN1bGFyICYmICFzZWxmTGlua2luZyhsLCBpZCkgPyBzb3VyY2VDb3VudCArIDEgOiBzb3VyY2VDb3VudDtcbiAgICB9KTtcblxuICAgIHZhciB0YXJnZXRDb3VudCA9IDA7XG4gICAgbm9kZS50YXJnZXRMaW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsKSB7XG4gICAgICB0YXJnZXRDb3VudCA9IGwuY2lyY3VsYXIgJiYgIXNlbGZMaW5raW5nKGwsIGlkKSA/IHRhcmdldENvdW50ICsgMSA6IHRhcmdldENvdW50O1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHNvdXJjZUNvdW50ICsgdGFyZ2V0Q291bnQ7XG4gIH1cblxuICAvLyBDaGVjayBpZiBhIGNpcmN1bGFyIGxpbmsgaXMgdGhlIG9ubHkgY2lyY3VsYXIgbGluayBmb3IgYm90aCBpdHMgc291cmNlIGFuZCB0YXJnZXQgbm9kZVxuICBmdW5jdGlvbiBvbmx5Q2lyY3VsYXJMaW5rKGxpbmspIHtcbiAgICB2YXIgbm9kZVNvdXJjZUxpbmtzID0gbGluay5zb3VyY2Uuc291cmNlTGlua3M7XG4gICAgdmFyIHNvdXJjZUNvdW50ID0gMDtcbiAgICBub2RlU291cmNlTGlua3MuZm9yRWFjaChmdW5jdGlvbiAobCkge1xuICAgICAgc291cmNlQ291bnQgPSBsLmNpcmN1bGFyID8gc291cmNlQ291bnQgKyAxIDogc291cmNlQ291bnQ7XG4gICAgfSk7XG5cbiAgICB2YXIgbm9kZVRhcmdldExpbmtzID0gbGluay50YXJnZXQudGFyZ2V0TGlua3M7XG4gICAgdmFyIHRhcmdldENvdW50ID0gMDtcbiAgICBub2RlVGFyZ2V0TGlua3MuZm9yRWFjaChmdW5jdGlvbiAobCkge1xuICAgICAgdGFyZ2V0Q291bnQgPSBsLmNpcmN1bGFyID8gdGFyZ2V0Q291bnQgKyAxIDogdGFyZ2V0Q291bnQ7XG4gICAgfSk7XG5cbiAgICBpZiAoc291cmNlQ291bnQgPiAxIHx8IHRhcmdldENvdW50ID4gMSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICAvLyBjcmVhdGVzIHZlcnRpY2FsIGJ1ZmZlciB2YWx1ZXMgcGVyIHNldCBvZiB0b3AvYm90dG9tIGxpbmtzXG4gIGZ1bmN0aW9uIGNhbGNWZXJ0aWNhbEJ1ZmZlcihsaW5rcywgY2lyY3VsYXJMaW5rR2FwLCBpZCkge1xuICAgIGxpbmtzLnNvcnQoc29ydExpbmtDb2x1bW5Bc2NlbmRpbmcpO1xuICAgIGxpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmssIGkpIHtcbiAgICAgIHZhciBidWZmZXIgPSAwO1xuXG4gICAgICBpZiAoc2VsZkxpbmtpbmcobGluaywgaWQpICYmIG9ubHlDaXJjdWxhckxpbmsobGluaykpIHtcbiAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsQnVmZmVyID0gYnVmZmVyICsgbGluay53aWR0aCAvIDI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaiA9IDA7XG4gICAgICAgIGZvciAoajsgaiA8IGk7IGorKykge1xuICAgICAgICAgIGlmIChjaXJjdWxhckxpbmtzQ3Jvc3MobGlua3NbaV0sIGxpbmtzW2pdKSkge1xuICAgICAgICAgICAgdmFyIGJ1ZmZlck92ZXJUaGlzTGluayA9IGxpbmtzW2pdLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxCdWZmZXIgKyBsaW5rc1tqXS53aWR0aCAvIDIgKyBjaXJjdWxhckxpbmtHYXA7XG4gICAgICAgICAgICBidWZmZXIgPSBidWZmZXJPdmVyVGhpc0xpbmsgPiBidWZmZXIgPyBidWZmZXJPdmVyVGhpc0xpbmsgOiBidWZmZXI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsQnVmZmVyID0gYnVmZmVyICsgbGluay53aWR0aCAvIDI7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gbGlua3M7XG4gIH1cblxuICAvLyBjYWxjdWxhdGUgdGhlIG9wdGltdW0gcGF0aCBmb3IgYSBsaW5rIHRvIHJlZHVjZSBvdmVybGFwc1xuICBmdW5jdGlvbiBhZGRDaXJjdWxhclBhdGhEYXRhKGdyYXBoLCBjaXJjdWxhckxpbmtHYXAsIHkxLCBpZCkge1xuICAgIC8vdmFyIGJhc2VSYWRpdXMgPSAxMFxuICAgIHZhciBidWZmZXIgPSA1O1xuICAgIC8vdmFyIHZlcnRpY2FsTWFyZ2luID0gMjVcblxuICAgIHZhciBtaW5ZID0gZDNBcnJheS5taW4oZ3JhcGgubGlua3MsIGZ1bmN0aW9uIChsaW5rKSB7XG4gICAgICByZXR1cm4gbGluay5zb3VyY2UueTA7XG4gICAgfSk7XG5cbiAgICAvLyBjcmVhdGUgb2JqZWN0IGZvciBjaXJjdWxhciBQYXRoIERhdGFcbiAgICBncmFwaC5saW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5rKSB7XG4gICAgICBpZiAobGluay5jaXJjdWxhcikge1xuICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEgPSB7fTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIGNhbGMgdmVydGljYWwgb2Zmc2V0cyBwZXIgdG9wL2JvdHRvbSBsaW5rc1xuICAgIHZhciB0b3BMaW5rcyA9IGdyYXBoLmxpbmtzLmZpbHRlcihmdW5jdGlvbiAobCkge1xuICAgICAgcmV0dXJuIGwuY2lyY3VsYXJMaW5rVHlwZSA9PSAndG9wJztcbiAgICB9KTtcbiAgICAvKiB0b3BMaW5rcyA9ICovY2FsY1ZlcnRpY2FsQnVmZmVyKHRvcExpbmtzLCBjaXJjdWxhckxpbmtHYXAsIGlkKTtcblxuICAgIHZhciBib3R0b21MaW5rcyA9IGdyYXBoLmxpbmtzLmZpbHRlcihmdW5jdGlvbiAobCkge1xuICAgICAgcmV0dXJuIGwuY2lyY3VsYXJMaW5rVHlwZSA9PSAnYm90dG9tJztcbiAgICB9KTtcbiAgICAvKiBib3R0b21MaW5rcyA9ICovY2FsY1ZlcnRpY2FsQnVmZmVyKGJvdHRvbUxpbmtzLCBjaXJjdWxhckxpbmtHYXAsIGlkKTtcblxuICAgIC8vIGFkZCB0aGUgYmFzZSBkYXRhIGZvciBlYWNoIGxpbmtcbiAgICBncmFwaC5saW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5rKSB7XG4gICAgICBpZiAobGluay5jaXJjdWxhcikge1xuICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEuYXJjUmFkaXVzID0gbGluay53aWR0aCArIGJhc2VSYWRpdXM7XG4gICAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5sZWZ0Tm9kZUJ1ZmZlciA9IGJ1ZmZlcjtcbiAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnJpZ2h0Tm9kZUJ1ZmZlciA9IGJ1ZmZlcjtcbiAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnNvdXJjZVdpZHRoID0gbGluay5zb3VyY2UueDEgLSBsaW5rLnNvdXJjZS54MDtcbiAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnNvdXJjZVggPSBsaW5rLnNvdXJjZS54MCArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5zb3VyY2VXaWR0aDtcbiAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnRhcmdldFggPSBsaW5rLnRhcmdldC54MDtcbiAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnNvdXJjZVkgPSBsaW5rLnkwO1xuICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEudGFyZ2V0WSA9IGxpbmsueTE7XG5cbiAgICAgICAgLy8gZm9yIHNlbGYgbGlua2luZyBwYXRocywgYW5kIHRoYXQgdGhlIG9ubHkgY2lyY3VsYXIgbGluayBpbi9vdXQgb2YgdGhhdCBub2RlXG4gICAgICAgIGlmIChzZWxmTGlua2luZyhsaW5rLCBpZCkgJiYgb25seUNpcmN1bGFyTGluayhsaW5rKSkge1xuICAgICAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5sZWZ0U21hbGxBcmNSYWRpdXMgPSBiYXNlUmFkaXVzICsgbGluay53aWR0aCAvIDI7XG4gICAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRMYXJnZUFyY1JhZGl1cyA9IGJhc2VSYWRpdXMgKyBsaW5rLndpZHRoIC8gMjtcbiAgICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRTbWFsbEFyY1JhZGl1cyA9IGJhc2VSYWRpdXMgKyBsaW5rLndpZHRoIC8gMjtcbiAgICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRMYXJnZUFyY1JhZGl1cyA9IGJhc2VSYWRpdXMgKyBsaW5rLndpZHRoIC8gMjtcblxuICAgICAgICAgIGlmIChsaW5rLmNpcmN1bGFyTGlua1R5cGUgPT0gJ2JvdHRvbScpIHtcbiAgICAgICAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbEZ1bGxFeHRlbnQgPSBsaW5rLnNvdXJjZS55MSArIHZlcnRpY2FsTWFyZ2luICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsQnVmZmVyO1xuICAgICAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsTGVmdElubmVyRXh0ZW50ID0gbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsRnVsbEV4dGVudCAtIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5sZWZ0TGFyZ2VBcmNSYWRpdXM7XG4gICAgICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxSaWdodElubmVyRXh0ZW50ID0gbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsRnVsbEV4dGVudCAtIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodExhcmdlQXJjUmFkaXVzO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0b3AgbGlua3NcbiAgICAgICAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbEZ1bGxFeHRlbnQgPSBsaW5rLnNvdXJjZS55MCAtIHZlcnRpY2FsTWFyZ2luIC0gbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsQnVmZmVyO1xuICAgICAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsTGVmdElubmVyRXh0ZW50ID0gbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsRnVsbEV4dGVudCArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5sZWZ0TGFyZ2VBcmNSYWRpdXM7XG4gICAgICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxSaWdodElubmVyRXh0ZW50ID0gbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsRnVsbEV4dGVudCArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodExhcmdlQXJjUmFkaXVzO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBlbHNlIGNhbGN1bGF0ZSBub3JtYWxseVxuICAgICAgICAgIC8vIGFkZCBsZWZ0IGV4dGVudCBjb29yZGluYXRlcywgYmFzZWQgb24gbGlua3Mgd2l0aCBzYW1lIHNvdXJjZSBjb2x1bW4gYW5kIGNpcmN1bGFyTGluayB0eXBlXG4gICAgICAgICAgdmFyIHRoaXNDb2x1bW4gPSBsaW5rLnNvdXJjZS5jb2x1bW47XG4gICAgICAgICAgdmFyIHRoaXNDaXJjdWxhckxpbmtUeXBlID0gbGluay5jaXJjdWxhckxpbmtUeXBlO1xuICAgICAgICAgIHZhciBzYW1lQ29sdW1uTGlua3MgPSBncmFwaC5saW5rcy5maWx0ZXIoZnVuY3Rpb24gKGwpIHtcbiAgICAgICAgICAgIHJldHVybiBsLnNvdXJjZS5jb2x1bW4gPT0gdGhpc0NvbHVtbiAmJiBsLmNpcmN1bGFyTGlua1R5cGUgPT0gdGhpc0NpcmN1bGFyTGlua1R5cGU7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAobGluay5jaXJjdWxhckxpbmtUeXBlID09ICdib3R0b20nKSB7XG4gICAgICAgICAgICBzYW1lQ29sdW1uTGlua3Muc29ydChzb3J0TGlua1NvdXJjZVlEZXNjZW5kaW5nKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2FtZUNvbHVtbkxpbmtzLnNvcnQoc29ydExpbmtTb3VyY2VZQXNjZW5kaW5nKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcmFkaXVzT2Zmc2V0ID0gMDtcbiAgICAgICAgICBzYW1lQ29sdW1uTGlua3MuZm9yRWFjaChmdW5jdGlvbiAobCwgaSkge1xuICAgICAgICAgICAgaWYgKGwuY2lyY3VsYXJMaW5rSUQgPT0gbGluay5jaXJjdWxhckxpbmtJRCkge1xuICAgICAgICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdFNtYWxsQXJjUmFkaXVzID0gYmFzZVJhZGl1cyArIGxpbmsud2lkdGggLyAyICsgcmFkaXVzT2Zmc2V0O1xuICAgICAgICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdExhcmdlQXJjUmFkaXVzID0gYmFzZVJhZGl1cyArIGxpbmsud2lkdGggLyAyICsgaSAqIGNpcmN1bGFyTGlua0dhcCArIHJhZGl1c09mZnNldDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJhZGl1c09mZnNldCA9IHJhZGl1c09mZnNldCArIGwud2lkdGg7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBhZGQgcmlnaHQgZXh0ZW50IGNvb3JkaW5hdGVzLCBiYXNlZCBvbiBsaW5rcyB3aXRoIHNhbWUgdGFyZ2V0IGNvbHVtbiBhbmQgY2lyY3VsYXJMaW5rIHR5cGVcbiAgICAgICAgICB0aGlzQ29sdW1uID0gbGluay50YXJnZXQuY29sdW1uO1xuICAgICAgICAgIHNhbWVDb2x1bW5MaW5rcyA9IGdyYXBoLmxpbmtzLmZpbHRlcihmdW5jdGlvbiAobCkge1xuICAgICAgICAgICAgcmV0dXJuIGwudGFyZ2V0LmNvbHVtbiA9PSB0aGlzQ29sdW1uICYmIGwuY2lyY3VsYXJMaW5rVHlwZSA9PSB0aGlzQ2lyY3VsYXJMaW5rVHlwZTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAobGluay5jaXJjdWxhckxpbmtUeXBlID09ICdib3R0b20nKSB7XG4gICAgICAgICAgICBzYW1lQ29sdW1uTGlua3Muc29ydChzb3J0TGlua1RhcmdldFlEZXNjZW5kaW5nKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2FtZUNvbHVtbkxpbmtzLnNvcnQoc29ydExpbmtUYXJnZXRZQXNjZW5kaW5nKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByYWRpdXNPZmZzZXQgPSAwO1xuICAgICAgICAgIHNhbWVDb2x1bW5MaW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsLCBpKSB7XG4gICAgICAgICAgICBpZiAobC5jaXJjdWxhckxpbmtJRCA9PSBsaW5rLmNpcmN1bGFyTGlua0lEKSB7XG4gICAgICAgICAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodFNtYWxsQXJjUmFkaXVzID0gYmFzZVJhZGl1cyArIGxpbmsud2lkdGggLyAyICsgcmFkaXVzT2Zmc2V0O1xuICAgICAgICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRMYXJnZUFyY1JhZGl1cyA9IGJhc2VSYWRpdXMgKyBsaW5rLndpZHRoIC8gMiArIGkgKiBjaXJjdWxhckxpbmtHYXAgKyByYWRpdXNPZmZzZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByYWRpdXNPZmZzZXQgPSByYWRpdXNPZmZzZXQgKyBsLndpZHRoO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gYm90dG9tIGxpbmtzXG4gICAgICAgICAgaWYgKGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9PSAnYm90dG9tJykge1xuICAgICAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsRnVsbEV4dGVudCA9IE1hdGgubWF4KHkxLCBsaW5rLnNvdXJjZS55MSwgbGluay50YXJnZXQueTEpICsgdmVydGljYWxNYXJnaW4gKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxCdWZmZXI7XG4gICAgICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxMZWZ0SW5uZXJFeHRlbnQgPSBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxGdWxsRXh0ZW50IC0gbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRMYXJnZUFyY1JhZGl1cztcbiAgICAgICAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbFJpZ2h0SW5uZXJFeHRlbnQgPSBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxGdWxsRXh0ZW50IC0gbGluay5jaXJjdWxhclBhdGhEYXRhLnJpZ2h0TGFyZ2VBcmNSYWRpdXM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRvcCBsaW5rc1xuICAgICAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsRnVsbEV4dGVudCA9IG1pblkgLSB2ZXJ0aWNhbE1hcmdpbiAtIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbEJ1ZmZlcjtcbiAgICAgICAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbExlZnRJbm5lckV4dGVudCA9IGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbEZ1bGxFeHRlbnQgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdExhcmdlQXJjUmFkaXVzO1xuICAgICAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsUmlnaHRJbm5lckV4dGVudCA9IGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbEZ1bGxFeHRlbnQgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRMYXJnZUFyY1JhZGl1cztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhbGwgbGlua3NcbiAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRJbm5lckV4dGVudCA9IGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5zb3VyY2VYICsgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnROb2RlQnVmZmVyO1xuICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRJbm5lckV4dGVudCA9IGxpbmsuY2lyY3VsYXJQYXRoRGF0YS50YXJnZXRYIC0gbGluay5jaXJjdWxhclBhdGhEYXRhLnJpZ2h0Tm9kZUJ1ZmZlcjtcbiAgICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRGdWxsRXh0ZW50ID0gbGluay5jaXJjdWxhclBhdGhEYXRhLnNvdXJjZVggKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdExhcmdlQXJjUmFkaXVzICsgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnROb2RlQnVmZmVyO1xuICAgICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRGdWxsRXh0ZW50ID0gbGluay5jaXJjdWxhclBhdGhEYXRhLnRhcmdldFggLSBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRMYXJnZUFyY1JhZGl1cyAtIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodE5vZGVCdWZmZXI7XG4gICAgICB9XG5cbiAgICAgIGlmIChsaW5rLmNpcmN1bGFyKSB7XG4gICAgICAgIGxpbmsucGF0aCA9IGNyZWF0ZUNpcmN1bGFyUGF0aFN0cmluZyhsaW5rKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBub3JtYWxQYXRoID0gZDNTaGFwZS5saW5rSG9yaXpvbnRhbCgpLnNvdXJjZShmdW5jdGlvbiAoZCkge1xuICAgICAgICAgIHZhciB4ID0gZC5zb3VyY2UueDAgKyAoZC5zb3VyY2UueDEgLSBkLnNvdXJjZS54MCk7XG4gICAgICAgICAgdmFyIHkgPSBkLnkwO1xuICAgICAgICAgIHJldHVybiBbeCwgeV07XG4gICAgICAgIH0pLnRhcmdldChmdW5jdGlvbiAoZCkge1xuICAgICAgICAgIHZhciB4ID0gZC50YXJnZXQueDA7XG4gICAgICAgICAgdmFyIHkgPSBkLnkxO1xuICAgICAgICAgIHJldHVybiBbeCwgeV07XG4gICAgICAgIH0pO1xuICAgICAgICBsaW5rLnBhdGggPSBub3JtYWxQYXRoKGxpbmspO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLy8gY3JlYXRlIGEgZCBwYXRoIHVzaW5nIHRoZSBhZGRDaXJjdWxhclBhdGhEYXRhXG4gIGZ1bmN0aW9uIGNyZWF0ZUNpcmN1bGFyUGF0aFN0cmluZyhsaW5rKSB7XG4gICAgdmFyIHBhdGhTdHJpbmcgPSAnJztcbiAgICAvLyAncGF0aERhdGEnIGlzIGFzc2lnbmVkIGEgdmFsdWUgYnV0IG5ldmVyIHVzZWRcbiAgICAvLyB2YXIgcGF0aERhdGEgPSB7fVxuXG4gICAgaWYgKGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9PSAndG9wJykge1xuICAgICAgcGF0aFN0cmluZyA9XG4gICAgICAvLyBzdGFydCBhdCB0aGUgcmlnaHQgb2YgdGhlIHNvdXJjZSBub2RlXG4gICAgICAnTScgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEuc291cmNlWCArICcgJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5zb3VyY2VZICsgJyAnICtcbiAgICAgIC8vIGxpbmUgcmlnaHQgdG8gYnVmZmVyIHBvaW50XG4gICAgICAnTCcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdElubmVyRXh0ZW50ICsgJyAnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnNvdXJjZVkgKyAnICcgK1xuICAgICAgLy8gQXJjIGFyb3VuZDogQ2VudHJlIG9mIGFyYyBYIGFuZCAgLy9DZW50cmUgb2YgYXJjIFlcbiAgICAgICdBJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5sZWZ0TGFyZ2VBcmNSYWRpdXMgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdFNtYWxsQXJjUmFkaXVzICsgJyAwIDAgMCAnICtcbiAgICAgIC8vIEVuZCBvZiBhcmMgWCAvL0VuZCBvZiBhcmMgWVxuICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRGdWxsRXh0ZW50ICsgJyAnICsgKGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5zb3VyY2VZIC0gbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRTbWFsbEFyY1JhZGl1cykgKyAnICcgKyAvLyBFbmQgb2YgYXJjIFhcbiAgICAgIC8vIGxpbmUgdXAgdG8gYnVmZmVyIHBvaW50XG4gICAgICAnTCcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdEZ1bGxFeHRlbnQgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxMZWZ0SW5uZXJFeHRlbnQgKyAnICcgK1xuICAgICAgLy8gQXJjIGFyb3VuZDogQ2VudHJlIG9mIGFyYyBYIGFuZCAgLy9DZW50cmUgb2YgYXJjIFlcbiAgICAgICdBJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5sZWZ0TGFyZ2VBcmNSYWRpdXMgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdExhcmdlQXJjUmFkaXVzICsgJyAwIDAgMCAnICtcbiAgICAgIC8vIEVuZCBvZiBhcmMgWCAvL0VuZCBvZiBhcmMgWVxuICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRJbm5lckV4dGVudCArICcgJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbEZ1bGxFeHRlbnQgKyAnICcgKyAvLyBFbmQgb2YgYXJjIFhcbiAgICAgIC8vIGxpbmUgbGVmdCB0byBidWZmZXIgcG9pbnRcbiAgICAgICdMJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodElubmVyRXh0ZW50ICsgJyAnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsRnVsbEV4dGVudCArICcgJyArXG4gICAgICAvLyBBcmMgYXJvdW5kOiBDZW50cmUgb2YgYXJjIFggYW5kICAvL0NlbnRyZSBvZiBhcmMgWVxuICAgICAgJ0EnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnJpZ2h0TGFyZ2VBcmNSYWRpdXMgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRMYXJnZUFyY1JhZGl1cyArICcgMCAwIDAgJyArXG4gICAgICAvLyBFbmQgb2YgYXJjIFggLy9FbmQgb2YgYXJjIFlcbiAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodEZ1bGxFeHRlbnQgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxSaWdodElubmVyRXh0ZW50ICsgJyAnICsgLy8gRW5kIG9mIGFyYyBYXG4gICAgICAvLyBsaW5lIGRvd25cbiAgICAgICdMJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodEZ1bGxFeHRlbnQgKyAnICcgKyAobGluay5jaXJjdWxhclBhdGhEYXRhLnRhcmdldFkgLSBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRTbWFsbEFyY1JhZGl1cykgKyAnICcgK1xuICAgICAgLy8gQXJjIGFyb3VuZDogQ2VudHJlIG9mIGFyYyBYIGFuZCAgLy9DZW50cmUgb2YgYXJjIFlcbiAgICAgICdBJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodExhcmdlQXJjUmFkaXVzICsgJyAnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnJpZ2h0U21hbGxBcmNSYWRpdXMgKyAnIDAgMCAwICcgK1xuICAgICAgLy8gRW5kIG9mIGFyYyBYIC8vRW5kIG9mIGFyYyBZXG4gICAgICBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRJbm5lckV4dGVudCArICcgJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS50YXJnZXRZICsgJyAnICsgLy8gRW5kIG9mIGFyYyBYXG4gICAgICAvLyBsaW5lIHRvIGVuZFxuICAgICAgJ0wnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnRhcmdldFggKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEudGFyZ2V0WTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gYm90dG9tIHBhdGhcbiAgICAgIHBhdGhTdHJpbmcgPVxuICAgICAgLy8gc3RhcnQgYXQgdGhlIHJpZ2h0IG9mIHRoZSBzb3VyY2Ugbm9kZVxuICAgICAgJ00nICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnNvdXJjZVggKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEuc291cmNlWSArICcgJyArXG4gICAgICAvLyBsaW5lIHJpZ2h0IHRvIGJ1ZmZlciBwb2ludFxuICAgICAgJ0wnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRJbm5lckV4dGVudCArICcgJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5zb3VyY2VZICsgJyAnICtcbiAgICAgIC8vIEFyYyBhcm91bmQ6IENlbnRyZSBvZiBhcmMgWCBhbmQgIC8vQ2VudHJlIG9mIGFyYyBZXG4gICAgICAnQScgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdExhcmdlQXJjUmFkaXVzICsgJyAnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRTbWFsbEFyY1JhZGl1cyArICcgMCAwIDEgJyArXG4gICAgICAvLyBFbmQgb2YgYXJjIFggLy9FbmQgb2YgYXJjIFlcbiAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5sZWZ0RnVsbEV4dGVudCArICcgJyArIChsaW5rLmNpcmN1bGFyUGF0aERhdGEuc291cmNlWSArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5sZWZ0U21hbGxBcmNSYWRpdXMpICsgJyAnICsgLy8gRW5kIG9mIGFyYyBYXG4gICAgICAvLyBsaW5lIGRvd24gdG8gYnVmZmVyIHBvaW50XG4gICAgICAnTCcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdEZ1bGxFeHRlbnQgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxMZWZ0SW5uZXJFeHRlbnQgKyAnICcgK1xuICAgICAgLy8gQXJjIGFyb3VuZDogQ2VudHJlIG9mIGFyYyBYIGFuZCAgLy9DZW50cmUgb2YgYXJjIFlcbiAgICAgICdBJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5sZWZ0TGFyZ2VBcmNSYWRpdXMgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEubGVmdExhcmdlQXJjUmFkaXVzICsgJyAwIDAgMSAnICtcbiAgICAgIC8vIEVuZCBvZiBhcmMgWCAvL0VuZCBvZiBhcmMgWVxuICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRJbm5lckV4dGVudCArICcgJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbEZ1bGxFeHRlbnQgKyAnICcgKyAvLyBFbmQgb2YgYXJjIFhcbiAgICAgIC8vIGxpbmUgbGVmdCB0byBidWZmZXIgcG9pbnRcbiAgICAgICdMJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodElubmVyRXh0ZW50ICsgJyAnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnZlcnRpY2FsRnVsbEV4dGVudCArICcgJyArXG4gICAgICAvLyBBcmMgYXJvdW5kOiBDZW50cmUgb2YgYXJjIFggYW5kICAvL0NlbnRyZSBvZiBhcmMgWVxuICAgICAgJ0EnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnJpZ2h0TGFyZ2VBcmNSYWRpdXMgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRMYXJnZUFyY1JhZGl1cyArICcgMCAwIDEgJyArXG4gICAgICAvLyBFbmQgb2YgYXJjIFggLy9FbmQgb2YgYXJjIFlcbiAgICAgIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodEZ1bGxFeHRlbnQgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEudmVydGljYWxSaWdodElubmVyRXh0ZW50ICsgJyAnICsgLy8gRW5kIG9mIGFyYyBYXG4gICAgICAvLyBsaW5lIHVwXG4gICAgICAnTCcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRGdWxsRXh0ZW50ICsgJyAnICsgKGxpbmsuY2lyY3VsYXJQYXRoRGF0YS50YXJnZXRZICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnJpZ2h0U21hbGxBcmNSYWRpdXMpICsgJyAnICtcbiAgICAgIC8vIEFyYyBhcm91bmQ6IENlbnRyZSBvZiBhcmMgWCBhbmQgIC8vQ2VudHJlIG9mIGFyYyBZXG4gICAgICAnQScgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEucmlnaHRMYXJnZUFyY1JhZGl1cyArICcgJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodFNtYWxsQXJjUmFkaXVzICsgJyAwIDAgMSAnICtcbiAgICAgIC8vIEVuZCBvZiBhcmMgWCAvL0VuZCBvZiBhcmMgWVxuICAgICAgbGluay5jaXJjdWxhclBhdGhEYXRhLnJpZ2h0SW5uZXJFeHRlbnQgKyAnICcgKyBsaW5rLmNpcmN1bGFyUGF0aERhdGEudGFyZ2V0WSArICcgJyArIC8vIEVuZCBvZiBhcmMgWFxuICAgICAgLy8gbGluZSB0byBlbmRcbiAgICAgICdMJyArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS50YXJnZXRYICsgJyAnICsgbGluay5jaXJjdWxhclBhdGhEYXRhLnRhcmdldFk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhdGhTdHJpbmc7XG4gIH1cblxuICAvLyBzb3J0IGxpbmtzIGJhc2VkIG9uIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBzb3VyY2UgYW5kIHRhcnRnZXQgbm9kZSBjb2x1bW5zXG4gIC8vIGlmIHRoZSBzYW1lLCB0aGVuIHVzZSBZIHBvc2l0aW9uIG9mIHRoZSBzb3VyY2Ugbm9kZVxuICBmdW5jdGlvbiBzb3J0TGlua0NvbHVtbkFzY2VuZGluZyhsaW5rMSwgbGluazIpIHtcbiAgICBpZiAobGlua0NvbHVtbkRpc3RhbmNlKGxpbmsxKSA9PSBsaW5rQ29sdW1uRGlzdGFuY2UobGluazIpKSB7XG4gICAgICByZXR1cm4gbGluazEuY2lyY3VsYXJMaW5rVHlwZSA9PSAnYm90dG9tJyA/IHNvcnRMaW5rU291cmNlWURlc2NlbmRpbmcobGluazEsIGxpbmsyKSA6IHNvcnRMaW5rU291cmNlWUFzY2VuZGluZyhsaW5rMSwgbGluazIpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbGlua0NvbHVtbkRpc3RhbmNlKGxpbmsyKSAtIGxpbmtDb2x1bW5EaXN0YW5jZShsaW5rMSk7XG4gICAgfVxuICB9XG5cbiAgLy8gc29ydCBhc2NlbmRpbmcgbGlua3MgYnkgdGhlaXIgc291cmNlIHZlcnRpY2FsIHBvc2l0aW9uLCB5MFxuICBmdW5jdGlvbiBzb3J0TGlua1NvdXJjZVlBc2NlbmRpbmcobGluazEsIGxpbmsyKSB7XG4gICAgcmV0dXJuIGxpbmsxLnkwIC0gbGluazIueTA7XG4gIH1cblxuICAvLyBzb3J0IGRlc2NlbmRpbmcgbGlua3MgYnkgdGhlaXIgc291cmNlIHZlcnRpY2FsIHBvc2l0aW9uLCB5MFxuICBmdW5jdGlvbiBzb3J0TGlua1NvdXJjZVlEZXNjZW5kaW5nKGxpbmsxLCBsaW5rMikge1xuICAgIHJldHVybiBsaW5rMi55MCAtIGxpbmsxLnkwO1xuICB9XG5cbiAgLy8gc29ydCBhc2NlbmRpbmcgbGlua3MgYnkgdGhlaXIgdGFyZ2V0IHZlcnRpY2FsIHBvc2l0aW9uLCB5MVxuICBmdW5jdGlvbiBzb3J0TGlua1RhcmdldFlBc2NlbmRpbmcobGluazEsIGxpbmsyKSB7XG4gICAgcmV0dXJuIGxpbmsxLnkxIC0gbGluazIueTE7XG4gIH1cblxuICAvLyBzb3J0IGRlc2NlbmRpbmcgbGlua3MgYnkgdGhlaXIgdGFyZ2V0IHZlcnRpY2FsIHBvc2l0aW9uLCB5MVxuICBmdW5jdGlvbiBzb3J0TGlua1RhcmdldFlEZXNjZW5kaW5nKGxpbmsxLCBsaW5rMikge1xuICAgIHJldHVybiBsaW5rMi55MSAtIGxpbmsxLnkxO1xuICB9XG5cbiAgLy8gcmV0dXJuIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBsaW5rJ3MgdGFyZ2V0IGFuZCBzb3VyY2Ugbm9kZSwgaW4gdGVybXMgb2YgdGhlIG5vZGVzJyBjb2x1bW5cbiAgZnVuY3Rpb24gbGlua0NvbHVtbkRpc3RhbmNlKGxpbmspIHtcbiAgICByZXR1cm4gbGluay50YXJnZXQuY29sdW1uIC0gbGluay5zb3VyY2UuY29sdW1uO1xuICB9XG5cbiAgLy8gcmV0dXJuIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBsaW5rJ3MgdGFyZ2V0IGFuZCBzb3VyY2Ugbm9kZSwgaW4gdGVybXMgb2YgdGhlIG5vZGVzJyBYIGNvb3JkaW5hdGVcbiAgZnVuY3Rpb24gbGlua1hMZW5ndGgobGluaykge1xuICAgIHJldHVybiBsaW5rLnRhcmdldC54MCAtIGxpbmsuc291cmNlLngxO1xuICB9XG5cbiAgLy8gUmV0dXJuIHRoZSBZIGNvb3JkaW5hdGUgb24gdGhlIGxvbmdlckxpbmsgcGF0aCAqIHdoaWNoIGlzIHBlcnBlbmRpY3VsYXIgc2hvcnRlckxpbmsncyBzb3VyY2UuXG4gIC8vICogYXBwcm94LCBiYXNlZCBvbiBhIHN0cmFpZ2h0IGxpbmUgZnJvbSB0YXJnZXQgdG8gc291cmNlLCB3aGVuIGluIGZhY3QgdGhlIHBhdGggaXMgYSBiZXppZXJcbiAgZnVuY3Rpb24gbGlua1BlcnBlbmRpY3VsYXJZVG9MaW5rU291cmNlKGxvbmdlckxpbmssIHNob3J0ZXJMaW5rKSB7XG4gICAgLy8gZ2V0IHRoZSBhbmdsZSBmb3IgdGhlIGxvbmdlciBsaW5rXG4gICAgdmFyIGFuZ2xlID0gbGlua0FuZ2xlKGxvbmdlckxpbmspO1xuXG4gICAgLy8gZ2V0IHRoZSBhZGphY2VudCBsZW5ndGggdG8gdGhlIG90aGVyIGxpbmsncyB4IHBvc2l0aW9uXG4gICAgdmFyIGhlaWdodEZyb21ZMVRvUGVwZW5kaWN1bGFyID0gbGlua1hMZW5ndGgoc2hvcnRlckxpbmspIC8gTWF0aC50YW4oYW5nbGUpO1xuXG4gICAgLy8gYWRkIG9yIHN1YnRyYWN0IGZyb20gbG9uZ2VyIGxpbmsxJ3Mgb3JpZ2luYWwgeTEsIGRlcGVuZGluZyBvbiB0aGUgc2xvcGVcbiAgICB2YXIgeVBlcnBlbmRpY3VsYXIgPSBpbmNsaW5lKGxvbmdlckxpbmspID09ICd1cCcgPyBsb25nZXJMaW5rLnkxICsgaGVpZ2h0RnJvbVkxVG9QZXBlbmRpY3VsYXIgOiBsb25nZXJMaW5rLnkxIC0gaGVpZ2h0RnJvbVkxVG9QZXBlbmRpY3VsYXI7XG5cbiAgICByZXR1cm4geVBlcnBlbmRpY3VsYXI7XG4gIH1cblxuICAvLyBSZXR1cm4gdGhlIFkgY29vcmRpbmF0ZSBvbiB0aGUgbG9uZ2VyTGluayBwYXRoICogd2hpY2ggaXMgcGVycGVuZGljdWxhciBzaG9ydGVyTGluaydzIHNvdXJjZS5cbiAgLy8gKiBhcHByb3gsIGJhc2VkIG9uIGEgc3RyYWlnaHQgbGluZSBmcm9tIHRhcmdldCB0byBzb3VyY2UsIHdoZW4gaW4gZmFjdCB0aGUgcGF0aCBpcyBhIGJlemllclxuICBmdW5jdGlvbiBsaW5rUGVycGVuZGljdWxhcllUb0xpbmtUYXJnZXQobG9uZ2VyTGluaywgc2hvcnRlckxpbmspIHtcbiAgICAvLyBnZXQgdGhlIGFuZ2xlIGZvciB0aGUgbG9uZ2VyIGxpbmtcbiAgICB2YXIgYW5nbGUgPSBsaW5rQW5nbGUobG9uZ2VyTGluayk7XG5cbiAgICAvLyBnZXQgdGhlIGFkamFjZW50IGxlbmd0aCB0byB0aGUgb3RoZXIgbGluaydzIHggcG9zaXRpb25cbiAgICB2YXIgaGVpZ2h0RnJvbVkxVG9QZXBlbmRpY3VsYXIgPSBsaW5rWExlbmd0aChzaG9ydGVyTGluaykgLyBNYXRoLnRhbihhbmdsZSk7XG5cbiAgICAvLyBhZGQgb3Igc3VidHJhY3QgZnJvbSBsb25nZXIgbGluaydzIG9yaWdpbmFsIHkxLCBkZXBlbmRpbmcgb24gdGhlIHNsb3BlXG4gICAgdmFyIHlQZXJwZW5kaWN1bGFyID0gaW5jbGluZShsb25nZXJMaW5rKSA9PSAndXAnID8gbG9uZ2VyTGluay55MSAtIGhlaWdodEZyb21ZMVRvUGVwZW5kaWN1bGFyIDogbG9uZ2VyTGluay55MSArIGhlaWdodEZyb21ZMVRvUGVwZW5kaWN1bGFyO1xuXG4gICAgcmV0dXJuIHlQZXJwZW5kaWN1bGFyO1xuICB9XG5cbiAgLy8gTW92ZSBhbnkgbm9kZXMgdGhhdCBvdmVybGFwIGxpbmtzIHdoaWNoIHNwYW4gMisgY29sdW1uc1xuICBmdW5jdGlvbiByZXNvbHZlTm9kZUxpbmtPdmVybGFwcyhncmFwaCwgeTAsIHkxLCBpZCkge1xuXG4gICAgZ3JhcGgubGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaykge1xuICAgICAgaWYgKGxpbmsuY2lyY3VsYXIpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAobGluay50YXJnZXQuY29sdW1uIC0gbGluay5zb3VyY2UuY29sdW1uID4gMSkge1xuICAgICAgICB2YXIgY29sdW1uVG9UZXN0ID0gbGluay5zb3VyY2UuY29sdW1uICsgMTtcbiAgICAgICAgdmFyIG1heENvbHVtblRvVGVzdCA9IGxpbmsudGFyZ2V0LmNvbHVtbiAtIDE7XG5cbiAgICAgICAgdmFyIGkgPSAxO1xuICAgICAgICB2YXIgbnVtYmVyT2ZDb2x1bW5zVG9UZXN0ID0gbWF4Q29sdW1uVG9UZXN0IC0gY29sdW1uVG9UZXN0ICsgMTtcblxuICAgICAgICBmb3IgKGkgPSAxOyBjb2x1bW5Ub1Rlc3QgPD0gbWF4Q29sdW1uVG9UZXN0OyBjb2x1bW5Ub1Rlc3QrKywgaSsrKSB7XG4gICAgICAgICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAgICAgaWYgKG5vZGUuY29sdW1uID09IGNvbHVtblRvVGVzdCkge1xuICAgICAgICAgICAgICB2YXIgdCA9IGkgLyAobnVtYmVyT2ZDb2x1bW5zVG9UZXN0ICsgMSk7XG5cbiAgICAgICAgICAgICAgLy8gRmluZCBhbGwgdGhlIHBvaW50cyBvZiBhIGN1YmljIGJlemllciBjdXJ2ZSBpbiBqYXZhc2NyaXB0XG4gICAgICAgICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzE1Mzk3NTk2L2ZpbmQtYWxsLXRoZS1wb2ludHMtb2YtYS1jdWJpYy1iZXppZXItY3VydmUtaW4tamF2YXNjcmlwdFxuXG4gICAgICAgICAgICAgIHZhciBCMF90ID0gTWF0aC5wb3coMSAtIHQsIDMpO1xuICAgICAgICAgICAgICB2YXIgQjFfdCA9IDMgKiB0ICogTWF0aC5wb3coMSAtIHQsIDIpO1xuICAgICAgICAgICAgICB2YXIgQjJfdCA9IDMgKiBNYXRoLnBvdyh0LCAyKSAqICgxIC0gdCk7XG4gICAgICAgICAgICAgIHZhciBCM190ID0gTWF0aC5wb3codCwgMyk7XG5cbiAgICAgICAgICAgICAgdmFyIHB5X3QgPSBCMF90ICogbGluay55MCArIEIxX3QgKiBsaW5rLnkwICsgQjJfdCAqIGxpbmsueTEgKyBCM190ICogbGluay55MTtcblxuICAgICAgICAgICAgICB2YXIgbGlua1kwQXRDb2x1bW4gPSBweV90IC0gbGluay53aWR0aCAvIDI7XG4gICAgICAgICAgICAgIHZhciBsaW5rWTFBdENvbHVtbiA9IHB5X3QgKyBsaW5rLndpZHRoIC8gMjtcbiAgICAgICAgICAgICAgdmFyIGR5O1xuXG4gICAgICAgICAgICAgIC8vIElmIHRvcCBvZiBsaW5rIG92ZXJsYXBzIG5vZGUsIHB1c2ggbm9kZSB1cFxuICAgICAgICAgICAgICBpZiAobGlua1kwQXRDb2x1bW4gPiBub2RlLnkwICYmIGxpbmtZMEF0Q29sdW1uIDwgbm9kZS55MSkge1xuXG4gICAgICAgICAgICAgICAgZHkgPSBub2RlLnkxIC0gbGlua1kwQXRDb2x1bW4gKyAxMDtcbiAgICAgICAgICAgICAgICBkeSA9IG5vZGUuY2lyY3VsYXJMaW5rVHlwZSA9PSAnYm90dG9tJyA/IGR5IDogLWR5O1xuXG4gICAgICAgICAgICAgICAgbm9kZSA9IGFkanVzdE5vZGVIZWlnaHQobm9kZSwgZHksIHkwLCB5MSk7XG5cbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBvdGhlciBub2RlcyBuZWVkIHRvIG1vdmUgdXAgdG9vXG4gICAgICAgICAgICAgICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbiAob3RoZXJOb2RlKSB7XG4gICAgICAgICAgICAgICAgICAvLyBkb24ndCBuZWVkIHRvIGNoZWNrIGl0c2VsZiBvciBub2RlcyBhdCBkaWZmZXJlbnQgY29sdW1uc1xuICAgICAgICAgICAgICAgICAgaWYgKGdldE5vZGVJRChvdGhlck5vZGUsIGlkKSA9PSBnZXROb2RlSUQobm9kZSwgaWQpIHx8IG90aGVyTm9kZS5jb2x1bW4gIT0gbm9kZS5jb2x1bW4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgaWYgKG5vZGVzT3ZlcmxhcChub2RlLCBvdGhlck5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkanVzdE5vZGVIZWlnaHQob3RoZXJOb2RlLCBkeSwgeTAsIHkxKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChsaW5rWTFBdENvbHVtbiA+IG5vZGUueTAgJiYgbGlua1kxQXRDb2x1bW4gPCBub2RlLnkxKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgYm90dG9tIG9mIGxpbmsgb3ZlcmxhcHMgbm9kZSwgcHVzaCBub2RlIGRvd25cbiAgICAgICAgICAgICAgICBkeSA9IGxpbmtZMUF0Q29sdW1uIC0gbm9kZS55MCArIDEwO1xuXG4gICAgICAgICAgICAgICAgbm9kZSA9IGFkanVzdE5vZGVIZWlnaHQobm9kZSwgZHksIHkwLCB5MSk7XG5cbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiBvdGhlciBub2RlcyBuZWVkIHRvIG1vdmUgZG93biB0b29cbiAgICAgICAgICAgICAgICBncmFwaC5ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChvdGhlck5vZGUpIHtcbiAgICAgICAgICAgICAgICAgIC8vIGRvbid0IG5lZWQgdG8gY2hlY2sgaXRzZWxmIG9yIG5vZGVzIGF0IGRpZmZlcmVudCBjb2x1bW5zXG4gICAgICAgICAgICAgICAgICBpZiAoZ2V0Tm9kZUlEKG90aGVyTm9kZSwgaWQpID09IGdldE5vZGVJRChub2RlLCBpZCkgfHwgb3RoZXJOb2RlLmNvbHVtbiAhPSBub2RlLmNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAob3RoZXJOb2RlLnkwIDwgbm9kZS55MSAmJiBvdGhlck5vZGUueTEgPiBub2RlLnkxKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkanVzdE5vZGVIZWlnaHQob3RoZXJOb2RlLCBkeSwgeTAsIHkxKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfSBlbHNlIGlmIChsaW5rWTBBdENvbHVtbiA8IG5vZGUueTAgJiYgbGlua1kxQXRDb2x1bW4gPiBub2RlLnkxKSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgbGluayBjb21wbGV0ZWx5IG92ZXJsYXBzIG5vZGVcbiAgICAgICAgICAgICAgICBkeSA9IGxpbmtZMUF0Q29sdW1uIC0gbm9kZS55MCArIDEwO1xuXG4gICAgICAgICAgICAgICAgbm9kZSA9IGFkanVzdE5vZGVIZWlnaHQobm9kZSwgZHksIHkwLCB5MSk7XG5cbiAgICAgICAgICAgICAgICBncmFwaC5ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChvdGhlck5vZGUpIHtcbiAgICAgICAgICAgICAgICAgIC8vIGRvbid0IG5lZWQgdG8gY2hlY2sgaXRzZWxmIG9yIG5vZGVzIGF0IGRpZmZlcmVudCBjb2x1bW5zXG4gICAgICAgICAgICAgICAgICBpZiAoZ2V0Tm9kZUlEKG90aGVyTm9kZSwgaWQpID09IGdldE5vZGVJRChub2RlLCBpZCkgfHwgb3RoZXJOb2RlLmNvbHVtbiAhPSBub2RlLmNvbHVtbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAob3RoZXJOb2RlLnkwIDwgbm9kZS55MSAmJiBvdGhlck5vZGUueTEgPiBub2RlLnkxKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkanVzdE5vZGVIZWlnaHQob3RoZXJOb2RlLCBkeSwgeTAsIHkxKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBjaGVjayBpZiB0d28gbm9kZXMgb3ZlcmxhcFxuICBmdW5jdGlvbiBub2Rlc092ZXJsYXAobm9kZUEsIG5vZGVCKSB7XG4gICAgLy8gdGVzdCBpZiBub2RlQSB0b3AgcGFydGlhbGx5IG92ZXJsYXBzIG5vZGVCXG4gICAgaWYgKG5vZGVBLnkwID4gbm9kZUIueTAgJiYgbm9kZUEueTAgPCBub2RlQi55MSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlQS55MSA+IG5vZGVCLnkwICYmIG5vZGVBLnkxIDwgbm9kZUIueTEpIHtcbiAgICAgIC8vIHRlc3QgaWYgbm9kZUEgYm90dG9tIHBhcnRpYWxseSBvdmVybGFwcyBub2RlQlxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChub2RlQS55MCA8IG5vZGVCLnkwICYmIG5vZGVBLnkxID4gbm9kZUIueTEpIHtcbiAgICAgIC8vIHRlc3QgaWYgbm9kZUEgY292ZXJzIG5vZGVCXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8vIHVwZGF0ZSBhIG5vZGUsIGFuZCBpdHMgYXNzb2NpYXRlZCBsaW5rcywgdmVydGljYWwgcG9zaXRpb25zICh5MCwgeTEpXG4gIGZ1bmN0aW9uIGFkanVzdE5vZGVIZWlnaHQobm9kZSwgZHksIHNhbmtleVkwLCBzYW5rZXlZMSkge1xuICAgIGlmIChub2RlLnkwICsgZHkgPj0gc2Fua2V5WTAgJiYgbm9kZS55MSArIGR5IDw9IHNhbmtleVkxKSB7XG4gICAgICBub2RlLnkwID0gbm9kZS55MCArIGR5O1xuICAgICAgbm9kZS55MSA9IG5vZGUueTEgKyBkeTtcblxuICAgICAgbm9kZS50YXJnZXRMaW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsKSB7XG4gICAgICAgIGwueTEgPSBsLnkxICsgZHk7XG4gICAgICB9KTtcblxuICAgICAgbm9kZS5zb3VyY2VMaW5rcy5mb3JFYWNoKGZ1bmN0aW9uIChsKSB7XG4gICAgICAgIGwueTAgPSBsLnkwICsgZHk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG5vZGU7XG4gIH1cblxuICAvLyBzb3J0IGFuZCBzZXQgdGhlIGxpbmtzJyB5MCBmb3IgZWFjaCBub2RlXG4gIGZ1bmN0aW9uIHNvcnRTb3VyY2VMaW5rcyhncmFwaCwgeTEsIGlkLCBtb3ZlTm9kZXMpIHtcbiAgICBncmFwaC5ub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAvLyBtb3ZlIGFueSBub2RlcyB1cCB3aGljaCBhcmUgb2ZmIHRoZSBib3R0b21cbiAgICAgIGlmIChtb3ZlTm9kZXMgJiYgbm9kZS55ICsgKG5vZGUueTEgLSBub2RlLnkwKSA+IHkxKSB7XG4gICAgICAgIG5vZGUueSA9IG5vZGUueSAtIChub2RlLnkgKyAobm9kZS55MSAtIG5vZGUueTApIC0geTEpO1xuICAgICAgfVxuXG4gICAgICB2YXIgbm9kZXNTb3VyY2VMaW5rcyA9IGdyYXBoLmxpbmtzLmZpbHRlcihmdW5jdGlvbiAobCkge1xuICAgICAgICByZXR1cm4gZ2V0Tm9kZUlEKGwuc291cmNlLCBpZCkgPT0gZ2V0Tm9kZUlEKG5vZGUsIGlkKTtcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgbm9kZVNvdXJjZUxpbmtzTGVuZ3RoID0gbm9kZXNTb3VyY2VMaW5rcy5sZW5ndGg7XG5cbiAgICAgIC8vIGlmIG1vcmUgdGhhbiAxIGxpbmsgdGhlbiBzb3J0XG4gICAgICBpZiAobm9kZVNvdXJjZUxpbmtzTGVuZ3RoID4gMSkge1xuICAgICAgICBub2Rlc1NvdXJjZUxpbmtzLnNvcnQoZnVuY3Rpb24gKGxpbmsxLCBsaW5rMikge1xuICAgICAgICAgIC8vIGlmIGJvdGggYXJlIG5vdCBjaXJjdWxhci4uLlxuICAgICAgICAgIGlmICghbGluazEuY2lyY3VsYXIgJiYgIWxpbmsyLmNpcmN1bGFyKSB7XG4gICAgICAgICAgICAvLyBpZiB0aGUgdGFyZ2V0IG5vZGVzIGFyZSB0aGUgc2FtZSBjb2x1bW4sIHRoZW4gc29ydCBieSB0aGUgbGluaydzIHRhcmdldCB5XG4gICAgICAgICAgICBpZiAobGluazEudGFyZ2V0LmNvbHVtbiA9PSBsaW5rMi50YXJnZXQuY29sdW1uKSB7XG4gICAgICAgICAgICAgIHJldHVybiBsaW5rMS55MSAtIGxpbmsyLnkxO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghc2FtZUluY2xpbmVzKGxpbmsxLCBsaW5rMikpIHtcbiAgICAgICAgICAgICAgLy8gaWYgdGhlIGxpbmtzIHNsb3BlIGluIGRpZmZlcmVudCBkaXJlY3Rpb25zLCB0aGVuIHNvcnQgYnkgdGhlIGxpbmsncyB0YXJnZXQgeVxuICAgICAgICAgICAgICByZXR1cm4gbGluazEueTEgLSBsaW5rMi55MTtcblxuICAgICAgICAgICAgICAvLyBpZiB0aGUgbGlua3Mgc2xvcGUgaW4gc2FtZSBkaXJlY3Rpb25zLCB0aGVuIHNvcnQgYnkgYW55IG92ZXJsYXBcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChsaW5rMS50YXJnZXQuY29sdW1uID4gbGluazIudGFyZ2V0LmNvbHVtbikge1xuICAgICAgICAgICAgICAgIHZhciBsaW5rMkFkaiA9IGxpbmtQZXJwZW5kaWN1bGFyWVRvTGlua1RhcmdldChsaW5rMiwgbGluazEpO1xuICAgICAgICAgICAgICAgIHJldHVybiBsaW5rMS55MSAtIGxpbmsyQWRqO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChsaW5rMi50YXJnZXQuY29sdW1uID4gbGluazEudGFyZ2V0LmNvbHVtbikge1xuICAgICAgICAgICAgICAgIHZhciBsaW5rMUFkaiA9IGxpbmtQZXJwZW5kaWN1bGFyWVRvTGlua1RhcmdldChsaW5rMSwgbGluazIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBsaW5rMUFkaiAtIGxpbmsyLnkxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gaWYgb25seSBvbmUgaXMgY2lyY3VsYXIsIHRoZSBtb3ZlIHRvcCBsaW5rcyB1cCwgb3IgYm90dG9tIGxpbmtzIGRvd25cbiAgICAgICAgICBpZiAobGluazEuY2lyY3VsYXIgJiYgIWxpbmsyLmNpcmN1bGFyKSB7XG4gICAgICAgICAgICByZXR1cm4gbGluazEuY2lyY3VsYXJMaW5rVHlwZSA9PSAndG9wJyA/IC0xIDogMTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGxpbmsyLmNpcmN1bGFyICYmICFsaW5rMS5jaXJjdWxhcikge1xuICAgICAgICAgICAgcmV0dXJuIGxpbmsyLmNpcmN1bGFyTGlua1R5cGUgPT0gJ3RvcCcgPyAxIDogLTE7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gaWYgYm90aCBsaW5rcyBhcmUgY2lyY3VsYXIuLi5cbiAgICAgICAgICBpZiAobGluazEuY2lyY3VsYXIgJiYgbGluazIuY2lyY3VsYXIpIHtcbiAgICAgICAgICAgIC8vIC4uLmFuZCB0aGV5IGJvdGggbG9vcCB0aGUgc2FtZSB3YXkgKGJvdGggdG9wKVxuICAgICAgICAgICAgaWYgKGxpbmsxLmNpcmN1bGFyTGlua1R5cGUgPT09IGxpbmsyLmNpcmN1bGFyTGlua1R5cGUgJiYgbGluazEuY2lyY3VsYXJMaW5rVHlwZSA9PSAndG9wJykge1xuICAgICAgICAgICAgICAvLyAuLi5hbmQgdGhleSBib3RoIGNvbm5lY3QgdG8gYSB0YXJnZXQgd2l0aCBzYW1lIGNvbHVtbiwgdGhlbiBzb3J0IGJ5IHRoZSB0YXJnZXQncyB5XG4gICAgICAgICAgICAgIGlmIChsaW5rMS50YXJnZXQuY29sdW1uID09PSBsaW5rMi50YXJnZXQuY29sdW1uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpbmsxLnRhcmdldC55MSAtIGxpbmsyLnRhcmdldC55MTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyAuLi5hbmQgdGhleSBjb25uZWN0IHRvIGRpZmZlcmVudCBjb2x1bW4gdGFyZ2V0cywgdGhlbiBzb3J0IGJ5IGhvdyBmYXIgYmFjayB0aGV5XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpbmsyLnRhcmdldC5jb2x1bW4gLSBsaW5rMS50YXJnZXQuY29sdW1uO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxpbmsxLmNpcmN1bGFyTGlua1R5cGUgPT09IGxpbmsyLmNpcmN1bGFyTGlua1R5cGUgJiYgbGluazEuY2lyY3VsYXJMaW5rVHlwZSA9PSAnYm90dG9tJykge1xuICAgICAgICAgICAgICAvLyAuLi5hbmQgdGhleSBib3RoIGxvb3AgdGhlIHNhbWUgd2F5IChib3RoIGJvdHRvbSlcbiAgICAgICAgICAgICAgLy8gLi4uYW5kIHRoZXkgYm90aCBjb25uZWN0IHRvIGEgdGFyZ2V0IHdpdGggc2FtZSBjb2x1bW4sIHRoZW4gc29ydCBieSB0aGUgdGFyZ2V0J3MgeVxuICAgICAgICAgICAgICBpZiAobGluazEudGFyZ2V0LmNvbHVtbiA9PT0gbGluazIudGFyZ2V0LmNvbHVtbikge1xuICAgICAgICAgICAgICAgIHJldHVybiBsaW5rMi50YXJnZXQueTEgLSBsaW5rMS50YXJnZXQueTE7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gLi4uYW5kIHRoZXkgY29ubmVjdCB0byBkaWZmZXJlbnQgY29sdW1uIHRhcmdldHMsIHRoZW4gc29ydCBieSBob3cgZmFyIGJhY2sgdGhleVxuICAgICAgICAgICAgICAgIHJldHVybiBsaW5rMS50YXJnZXQuY29sdW1uIC0gbGluazIudGFyZ2V0LmNvbHVtbjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gLi4uYW5kIHRoZXkgbG9vcCBhcm91bmQgZGlmZmVyZW50IHdheXMsIHRoZSBtb3ZlIHRvcCB1cCBhbmQgYm90dG9tIGRvd25cbiAgICAgICAgICAgICAgcmV0dXJuIGxpbmsxLmNpcmN1bGFyTGlua1R5cGUgPT0gJ3RvcCcgPyAtMSA6IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gdXBkYXRlIHkwIGZvciBsaW5rc1xuICAgICAgdmFyIHlTb3VyY2VPZmZzZXQgPSBub2RlLnkwO1xuXG4gICAgICBub2Rlc1NvdXJjZUxpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgICAgbGluay55MCA9IHlTb3VyY2VPZmZzZXQgKyBsaW5rLndpZHRoIC8gMjtcbiAgICAgICAgeVNvdXJjZU9mZnNldCA9IHlTb3VyY2VPZmZzZXQgKyBsaW5rLndpZHRoO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIGNvcnJlY3QgYW55IGNpcmN1bGFyIGJvdHRvbSBsaW5rcyBzbyB0aGV5IGFyZSBhdCB0aGUgYm90dG9tIG9mIHRoZSBub2RlXG4gICAgICBub2Rlc1NvdXJjZUxpbmtzLmZvckVhY2goZnVuY3Rpb24gKGxpbmssIGkpIHtcbiAgICAgICAgaWYgKGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9PSAnYm90dG9tJykge1xuICAgICAgICAgIHZhciBqID0gaSArIDE7XG4gICAgICAgICAgdmFyIG9mZnNldEZyb21Cb3R0b20gPSAwO1xuICAgICAgICAgIC8vIHN1bSB0aGUgd2lkdGhzIG9mIGFueSBsaW5rcyB0aGF0IGFyZSBiZWxvdyB0aGlzIGxpbmtcbiAgICAgICAgICBmb3IgKGo7IGogPCBub2RlU291cmNlTGlua3NMZW5ndGg7IGorKykge1xuICAgICAgICAgICAgb2Zmc2V0RnJvbUJvdHRvbSA9IG9mZnNldEZyb21Cb3R0b20gKyBub2Rlc1NvdXJjZUxpbmtzW2pdLndpZHRoO1xuICAgICAgICAgIH1cbiAgICAgICAgICBsaW5rLnkwID0gbm9kZS55MSAtIG9mZnNldEZyb21Cb3R0b20gLSBsaW5rLndpZHRoIC8gMjtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvLyBzb3J0IGFuZCBzZXQgdGhlIGxpbmtzJyB5MSBmb3IgZWFjaCBub2RlXG4gIGZ1bmN0aW9uIHNvcnRUYXJnZXRMaW5rcyhncmFwaCwgeTEsIGlkKSB7XG4gICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xuICAgICAgdmFyIG5vZGVzVGFyZ2V0TGlua3MgPSBncmFwaC5saW5rcy5maWx0ZXIoZnVuY3Rpb24gKGwpIHtcbiAgICAgICAgcmV0dXJuIGdldE5vZGVJRChsLnRhcmdldCwgaWQpID09IGdldE5vZGVJRChub2RlLCBpZCk7XG4gICAgICB9KTtcblxuICAgICAgdmFyIG5vZGVzVGFyZ2V0TGlua3NMZW5ndGggPSBub2Rlc1RhcmdldExpbmtzLmxlbmd0aDtcblxuICAgICAgaWYgKG5vZGVzVGFyZ2V0TGlua3NMZW5ndGggPiAxKSB7XG4gICAgICAgIG5vZGVzVGFyZ2V0TGlua3Muc29ydChmdW5jdGlvbiAobGluazEsIGxpbmsyKSB7XG4gICAgICAgICAgLy8gaWYgYm90aCBhcmUgbm90IGNpcmN1bGFyLCB0aGUgYmFzZSBvbiB0aGUgc291cmNlIHkgcG9zaXRpb25cbiAgICAgICAgICBpZiAoIWxpbmsxLmNpcmN1bGFyICYmICFsaW5rMi5jaXJjdWxhcikge1xuICAgICAgICAgICAgaWYgKGxpbmsxLnNvdXJjZS5jb2x1bW4gPT0gbGluazIuc291cmNlLmNvbHVtbikge1xuICAgICAgICAgICAgICByZXR1cm4gbGluazEueTAgLSBsaW5rMi55MDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIXNhbWVJbmNsaW5lcyhsaW5rMSwgbGluazIpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBsaW5rMS55MCAtIGxpbmsyLnkwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gZ2V0IHRoZSBhbmdsZSBvZiB0aGUgbGluayB0byB0aGUgZnVydGhlciBzb3VyY2Ugbm9kZSAoaWUgdGhlIHNtYWxsZXIgY29sdW1uKVxuICAgICAgICAgICAgICBpZiAobGluazIuc291cmNlLmNvbHVtbiA8IGxpbmsxLnNvdXJjZS5jb2x1bW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgbGluazJBZGogPSBsaW5rUGVycGVuZGljdWxhcllUb0xpbmtTb3VyY2UobGluazIsIGxpbmsxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBsaW5rMS55MCAtIGxpbmsyQWRqO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChsaW5rMS5zb3VyY2UuY29sdW1uIDwgbGluazIuc291cmNlLmNvbHVtbikge1xuICAgICAgICAgICAgICAgIHZhciBsaW5rMUFkaiA9IGxpbmtQZXJwZW5kaWN1bGFyWVRvTGlua1NvdXJjZShsaW5rMSwgbGluazIpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpbmsxQWRqIC0gbGluazIueTA7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBpZiBvbmx5IG9uZSBpcyBjaXJjdWxhciwgdGhlIG1vdmUgdG9wIGxpbmtzIHVwLCBvciBib3R0b20gbGlua3MgZG93blxuICAgICAgICAgIGlmIChsaW5rMS5jaXJjdWxhciAmJiAhbGluazIuY2lyY3VsYXIpIHtcbiAgICAgICAgICAgIHJldHVybiBsaW5rMS5jaXJjdWxhckxpbmtUeXBlID09ICd0b3AnID8gLTEgOiAxO1xuICAgICAgICAgIH0gZWxzZSBpZiAobGluazIuY2lyY3VsYXIgJiYgIWxpbmsxLmNpcmN1bGFyKSB7XG4gICAgICAgICAgICByZXR1cm4gbGluazIuY2lyY3VsYXJMaW5rVHlwZSA9PSAndG9wJyA/IDEgOiAtMTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBpZiBib3RoIGxpbmtzIGFyZSBjaXJjdWxhci4uLlxuICAgICAgICAgIGlmIChsaW5rMS5jaXJjdWxhciAmJiBsaW5rMi5jaXJjdWxhcikge1xuICAgICAgICAgICAgLy8gLi4uYW5kIHRoZXkgYm90aCBsb29wIHRoZSBzYW1lIHdheSAoYm90aCB0b3ApXG4gICAgICAgICAgICBpZiAobGluazEuY2lyY3VsYXJMaW5rVHlwZSA9PT0gbGluazIuY2lyY3VsYXJMaW5rVHlwZSAmJiBsaW5rMS5jaXJjdWxhckxpbmtUeXBlID09ICd0b3AnKSB7XG4gICAgICAgICAgICAgIC8vIC4uLmFuZCB0aGV5IGJvdGggY29ubmVjdCB0byBhIHRhcmdldCB3aXRoIHNhbWUgY29sdW1uLCB0aGVuIHNvcnQgYnkgdGhlIHRhcmdldCdzIHlcbiAgICAgICAgICAgICAgaWYgKGxpbmsxLnNvdXJjZS5jb2x1bW4gPT09IGxpbmsyLnNvdXJjZS5jb2x1bW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGluazEuc291cmNlLnkxIC0gbGluazIuc291cmNlLnkxO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIC4uLmFuZCB0aGV5IGNvbm5lY3QgdG8gZGlmZmVyZW50IGNvbHVtbiB0YXJnZXRzLCB0aGVuIHNvcnQgYnkgaG93IGZhciBiYWNrIHRoZXlcbiAgICAgICAgICAgICAgICByZXR1cm4gbGluazEuc291cmNlLmNvbHVtbiAtIGxpbmsyLnNvdXJjZS5jb2x1bW47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAobGluazEuY2lyY3VsYXJMaW5rVHlwZSA9PT0gbGluazIuY2lyY3VsYXJMaW5rVHlwZSAmJiBsaW5rMS5jaXJjdWxhckxpbmtUeXBlID09ICdib3R0b20nKSB7XG4gICAgICAgICAgICAgIC8vIC4uLmFuZCB0aGV5IGJvdGggbG9vcCB0aGUgc2FtZSB3YXkgKGJvdGggYm90dG9tKVxuICAgICAgICAgICAgICAvLyAuLi5hbmQgdGhleSBib3RoIGNvbm5lY3QgdG8gYSB0YXJnZXQgd2l0aCBzYW1lIGNvbHVtbiwgdGhlbiBzb3J0IGJ5IHRoZSB0YXJnZXQncyB5XG4gICAgICAgICAgICAgIGlmIChsaW5rMS5zb3VyY2UuY29sdW1uID09PSBsaW5rMi5zb3VyY2UuY29sdW1uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpbmsxLnNvdXJjZS55MSAtIGxpbmsyLnNvdXJjZS55MTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyAuLi5hbmQgdGhleSBjb25uZWN0IHRvIGRpZmZlcmVudCBjb2x1bW4gdGFyZ2V0cywgdGhlbiBzb3J0IGJ5IGhvdyBmYXIgYmFjayB0aGV5XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpbmsyLnNvdXJjZS5jb2x1bW4gLSBsaW5rMS5zb3VyY2UuY29sdW1uO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAvLyAuLi5hbmQgdGhleSBsb29wIGFyb3VuZCBkaWZmZXJlbnQgd2F5cywgdGhlIG1vdmUgdG9wIHVwIGFuZCBib3R0b20gZG93blxuICAgICAgICAgICAgICByZXR1cm4gbGluazEuY2lyY3VsYXJMaW5rVHlwZSA9PSAndG9wJyA/IC0xIDogMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyB1cGRhdGUgeTEgZm9yIGxpbmtzXG4gICAgICB2YXIgeVRhcmdldE9mZnNldCA9IG5vZGUueTA7XG5cbiAgICAgIG5vZGVzVGFyZ2V0TGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaykge1xuICAgICAgICBsaW5rLnkxID0geVRhcmdldE9mZnNldCArIGxpbmsud2lkdGggLyAyO1xuICAgICAgICB5VGFyZ2V0T2Zmc2V0ID0geVRhcmdldE9mZnNldCArIGxpbmsud2lkdGg7XG4gICAgICB9KTtcblxuICAgICAgLy8gY29ycmVjdCBhbnkgY2lyY3VsYXIgYm90dG9tIGxpbmtzIHNvIHRoZXkgYXJlIGF0IHRoZSBib3R0b20gb2YgdGhlIG5vZGVcbiAgICAgIG5vZGVzVGFyZ2V0TGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaywgaSkge1xuICAgICAgICBpZiAobGluay5jaXJjdWxhckxpbmtUeXBlID09ICdib3R0b20nKSB7XG4gICAgICAgICAgdmFyIGogPSBpICsgMTtcbiAgICAgICAgICB2YXIgb2Zmc2V0RnJvbUJvdHRvbSA9IDA7XG4gICAgICAgICAgLy8gc3VtIHRoZSB3aWR0aHMgb2YgYW55IGxpbmtzIHRoYXQgYXJlIGJlbG93IHRoaXMgbGlua1xuICAgICAgICAgIGZvciAoajsgaiA8IG5vZGVzVGFyZ2V0TGlua3NMZW5ndGg7IGorKykge1xuICAgICAgICAgICAgb2Zmc2V0RnJvbUJvdHRvbSA9IG9mZnNldEZyb21Cb3R0b20gKyBub2Rlc1RhcmdldExpbmtzW2pdLndpZHRoO1xuICAgICAgICAgIH1cbiAgICAgICAgICBsaW5rLnkxID0gbm9kZS55MSAtIG9mZnNldEZyb21Cb3R0b20gLSBsaW5rLndpZHRoIC8gMjtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvLyB0ZXN0IGlmIGxpbmtzIGJvdGggc2xvcGUgdXAsIG9yIGJvdGggc2xvcGUgZG93blxuICBmdW5jdGlvbiBzYW1lSW5jbGluZXMobGluazEsIGxpbmsyKSB7XG4gICAgcmV0dXJuIGluY2xpbmUobGluazEpID09IGluY2xpbmUobGluazIpO1xuICB9XG5cbiAgLy8gcmV0dXJucyB0aGUgc2xvcGUgb2YgYSBsaW5rLCBmcm9tIHNvdXJjZSB0byB0YXJnZXRcbiAgLy8gdXAgPT4gc2xvcGVzIHVwIGZyb20gc291cmNlIHRvIHRhcmdldFxuICAvLyBkb3duID0+IHNsb3BlcyBkb3duIGZyb20gc291cmNlIHRvIHRhcmdldFxuICBmdW5jdGlvbiBpbmNsaW5lKGxpbmspIHtcbiAgICByZXR1cm4gbGluay55MCAtIGxpbmsueTEgPiAwID8gJ3VwJyA6ICdkb3duJztcbiAgfVxuXG4gIC8vIGNoZWNrIGlmIGxpbmsgaXMgc2VsZiBsaW5raW5nLCBpZSBsaW5rcyBhIG5vZGUgdG8gdGhlIHNhbWUgbm9kZVxuICBmdW5jdGlvbiBzZWxmTGlua2luZyhsaW5rLCBpZCkge1xuICAgIHJldHVybiBnZXROb2RlSUQobGluay5zb3VyY2UsIGlkKSA9PSBnZXROb2RlSUQobGluay50YXJnZXQsIGlkKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbGxIZWlnaHQoZ3JhcGgsIHkwLCB5MSkge1xuXG4gICAgdmFyIG5vZGVzID0gZ3JhcGgubm9kZXM7XG4gICAgdmFyIGxpbmtzID0gZ3JhcGgubGlua3M7XG5cbiAgICB2YXIgdG9wID0gZmFsc2U7XG4gICAgdmFyIGJvdHRvbSA9IGZhbHNlO1xuXG4gICAgbGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaykge1xuICAgICAgaWYgKGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9PSBcInRvcFwiKSB7XG4gICAgICAgIHRvcCA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9PSBcImJvdHRvbVwiKSB7XG4gICAgICAgIGJvdHRvbSA9IHRydWU7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAodG9wID09IGZhbHNlIHx8IGJvdHRvbSA9PSBmYWxzZSkge1xuICAgICAgdmFyIG1pblkwID0gZDNBcnJheS5taW4obm9kZXMsIGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgIHJldHVybiBub2RlLnkwO1xuICAgICAgfSk7XG4gICAgICB2YXIgbWF4WTEgPSBkM0FycmF5Lm1heChub2RlcywgZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgcmV0dXJuIG5vZGUueTE7XG4gICAgICB9KTtcbiAgICAgIHZhciBjdXJyZW50SGVpZ2h0ID0gbWF4WTEgLSBtaW5ZMDtcbiAgICAgIHZhciBjaGFydEhlaWdodCA9IHkxIC0geTA7XG4gICAgICB2YXIgcmF0aW8gPSBjaGFydEhlaWdodCAvIGN1cnJlbnRIZWlnaHQ7XG5cbiAgICAgIG5vZGVzLmZvckVhY2goZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgdmFyIG5vZGVIZWlnaHQgPSAobm9kZS55MSAtIG5vZGUueTApICogcmF0aW87XG4gICAgICAgIG5vZGUueTAgPSAobm9kZS55MCAtIG1pblkwKSAqIHJhdGlvO1xuICAgICAgICBub2RlLnkxID0gbm9kZS55MCArIG5vZGVIZWlnaHQ7XG4gICAgICB9KTtcblxuICAgICAgbGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaykge1xuICAgICAgICBsaW5rLnkwID0gKGxpbmsueTAgLSBtaW5ZMCkgKiByYXRpbztcbiAgICAgICAgbGluay55MSA9IChsaW5rLnkxIC0gbWluWTApICogcmF0aW87XG4gICAgICAgIGxpbmsud2lkdGggPSBsaW5rLndpZHRoICogcmF0aW87XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBleHBvcnRzLnNhbmtleUNpcmN1bGFyID0gc2Fua2V5Q2lyY3VsYXI7XG4gIGV4cG9ydHMuc2Fua2V5Q2VudGVyID0gY2VudGVyO1xuICBleHBvcnRzLnNhbmtleUxlZnQgPSBsZWZ0O1xuICBleHBvcnRzLnNhbmtleVJpZ2h0ID0gcmlnaHQ7XG4gIGV4cG9ydHMuc2Fua2V5SnVzdGlmeSA9IGp1c3RpZnk7XG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcblxufSx7XCJkMy1hcnJheVwiOjE1MixcImQzLWNvbGxlY3Rpb25cIjoxNTMsXCJkMy1zaGFwZVwiOjE2MSxcImVsZW1lbnRhcnktY2lyY3VpdHMtZGlyZWN0ZWQtZ3JhcGhcIjoxNzJ9XSw1NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBodHRwczovL2dpdGh1Yi5jb20vZDMvZDMtc2Fua2V5IFZlcnNpb24gMC43LjIuIENvcHlyaWdodCAyMDE5IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cywgX2RlcmVxXygnZDMtYXJyYXknKSwgX2RlcmVxXygnZDMtY29sbGVjdGlvbicpLCBfZGVyZXFfKCdkMy1zaGFwZScpKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtYXJyYXknLCAnZDMtY29sbGVjdGlvbicsICdkMy1zaGFwZSddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pLGdsb2JhbC5kMyxnbG9iYWwuZDMsZ2xvYmFsLmQzKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cyxkM0FycmF5LGQzQ29sbGVjdGlvbixkM1NoYXBlKSB7ICd1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gdGFyZ2V0RGVwdGgoZCkge1xuICByZXR1cm4gZC50YXJnZXQuZGVwdGg7XG59XG5cbmZ1bmN0aW9uIGxlZnQobm9kZSkge1xuICByZXR1cm4gbm9kZS5kZXB0aDtcbn1cblxuZnVuY3Rpb24gcmlnaHQobm9kZSwgbikge1xuICByZXR1cm4gbiAtIDEgLSBub2RlLmhlaWdodDtcbn1cblxuZnVuY3Rpb24ganVzdGlmeShub2RlLCBuKSB7XG4gIHJldHVybiBub2RlLnNvdXJjZUxpbmtzLmxlbmd0aCA/IG5vZGUuZGVwdGggOiBuIC0gMTtcbn1cblxuZnVuY3Rpb24gY2VudGVyKG5vZGUpIHtcbiAgcmV0dXJuIG5vZGUudGFyZ2V0TGlua3MubGVuZ3RoID8gbm9kZS5kZXB0aFxuICAgICAgOiBub2RlLnNvdXJjZUxpbmtzLmxlbmd0aCA/IGQzQXJyYXkubWluKG5vZGUuc291cmNlTGlua3MsIHRhcmdldERlcHRoKSAtIDFcbiAgICAgIDogMDtcbn1cblxuZnVuY3Rpb24gY29uc3RhbnQoeCkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHg7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGFzY2VuZGluZ1NvdXJjZUJyZWFkdGgoYSwgYikge1xuICByZXR1cm4gYXNjZW5kaW5nQnJlYWR0aChhLnNvdXJjZSwgYi5zb3VyY2UpIHx8IGEuaW5kZXggLSBiLmluZGV4O1xufVxuXG5mdW5jdGlvbiBhc2NlbmRpbmdUYXJnZXRCcmVhZHRoKGEsIGIpIHtcbiAgcmV0dXJuIGFzY2VuZGluZ0JyZWFkdGgoYS50YXJnZXQsIGIudGFyZ2V0KSB8fCBhLmluZGV4IC0gYi5pbmRleDtcbn1cblxuZnVuY3Rpb24gYXNjZW5kaW5nQnJlYWR0aChhLCBiKSB7XG4gIHJldHVybiBhLnkwIC0gYi55MDtcbn1cblxuZnVuY3Rpb24gdmFsdWUoZCkge1xuICByZXR1cm4gZC52YWx1ZTtcbn1cblxuZnVuY3Rpb24gbm9kZUNlbnRlcihub2RlKSB7XG4gIHJldHVybiAobm9kZS55MCArIG5vZGUueTEpIC8gMjtcbn1cblxuZnVuY3Rpb24gd2VpZ2h0ZWRTb3VyY2UobGluaykge1xuICByZXR1cm4gbm9kZUNlbnRlcihsaW5rLnNvdXJjZSkgKiBsaW5rLnZhbHVlO1xufVxuXG5mdW5jdGlvbiB3ZWlnaHRlZFRhcmdldChsaW5rKSB7XG4gIHJldHVybiBub2RlQ2VudGVyKGxpbmsudGFyZ2V0KSAqIGxpbmsudmFsdWU7XG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRJZChkKSB7XG4gIHJldHVybiBkLmluZGV4O1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0Tm9kZXMoZ3JhcGgpIHtcbiAgcmV0dXJuIGdyYXBoLm5vZGVzO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0TGlua3MoZ3JhcGgpIHtcbiAgcmV0dXJuIGdyYXBoLmxpbmtzO1xufVxuXG5mdW5jdGlvbiBmaW5kKG5vZGVCeUlkLCBpZCkge1xuICB2YXIgbm9kZSA9IG5vZGVCeUlkLmdldChpZCk7XG4gIGlmICghbm9kZSkgdGhyb3cgbmV3IEVycm9yKFwibWlzc2luZzogXCIgKyBpZCk7XG4gIHJldHVybiBub2RlO1xufVxuXG52YXIgc2Fua2V5ID0gZnVuY3Rpb24oKSB7XG4gIHZhciB4MCA9IDAsIHkwID0gMCwgeDEgPSAxLCB5MSA9IDEsIC8vIGV4dGVudFxuICAgICAgZHggPSAyNCwgLy8gbm9kZVdpZHRoXG4gICAgICBweSA9IDgsIC8vIG5vZGVQYWRkaW5nXG4gICAgICBpZCA9IGRlZmF1bHRJZCxcbiAgICAgIGFsaWduID0ganVzdGlmeSxcbiAgICAgIG5vZGVzID0gZGVmYXVsdE5vZGVzLFxuICAgICAgbGlua3MgPSBkZWZhdWx0TGlua3MsXG4gICAgICBpdGVyYXRpb25zID0gMzIsXG4gICAgICBtYXhQYWRkZWRTcGFjZSA9IDIgLyAzOyAvLyBEZWZpbmVkIGFzIGEgZnJhY3Rpb24gb2YgdGhlIHRvdGFsIGF2YWlsYWJsZSBzcGFjZVxuXG4gIGZ1bmN0aW9uIHNhbmtleSgpIHtcbiAgICB2YXIgZ3JhcGggPSB7bm9kZXM6IG5vZGVzLmFwcGx5KG51bGwsIGFyZ3VtZW50cyksIGxpbmtzOiBsaW5rcy5hcHBseShudWxsLCBhcmd1bWVudHMpfTtcbiAgICBjb21wdXRlTm9kZUxpbmtzKGdyYXBoKTtcbiAgICBjb21wdXRlTm9kZVZhbHVlcyhncmFwaCk7XG4gICAgY29tcHV0ZU5vZGVEZXB0aHMoZ3JhcGgpO1xuICAgIGNvbXB1dGVOb2RlQnJlYWR0aHMoZ3JhcGgsIGl0ZXJhdGlvbnMpO1xuICAgIGNvbXB1dGVMaW5rQnJlYWR0aHMoZ3JhcGgpO1xuICAgIHJldHVybiBncmFwaDtcbiAgfVxuXG4gIHNhbmtleS51cGRhdGUgPSBmdW5jdGlvbihncmFwaCkge1xuICAgIGNvbXB1dGVMaW5rQnJlYWR0aHMoZ3JhcGgpO1xuICAgIHJldHVybiBncmFwaDtcbiAgfTtcblxuICBzYW5rZXkubm9kZUlkID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGlkID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChfKSwgc2Fua2V5KSA6IGlkO1xuICB9O1xuXG4gIHNhbmtleS5ub2RlQWxpZ24gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYWxpZ24gPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KF8pLCBzYW5rZXkpIDogYWxpZ247XG4gIH07XG5cbiAgc2Fua2V5Lm5vZGVXaWR0aCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkeCA9ICtfLCBzYW5rZXkpIDogZHg7XG4gIH07XG5cbiAgc2Fua2V5Lm5vZGVQYWRkaW5nID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHB5ID0gK18sIHNhbmtleSkgOiBweTtcbiAgfTtcblxuICBzYW5rZXkubm9kZXMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobm9kZXMgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KF8pLCBzYW5rZXkpIDogbm9kZXM7XG4gIH07XG5cbiAgc2Fua2V5LmxpbmtzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGxpbmtzID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChfKSwgc2Fua2V5KSA6IGxpbmtzO1xuICB9O1xuXG4gIHNhbmtleS5zaXplID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHgwID0geTAgPSAwLCB4MSA9ICtfWzBdLCB5MSA9ICtfWzFdLCBzYW5rZXkpIDogW3gxIC0geDAsIHkxIC0geTBdO1xuICB9O1xuXG4gIHNhbmtleS5leHRlbnQgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeDAgPSArX1swXVswXSwgeDEgPSArX1sxXVswXSwgeTAgPSArX1swXVsxXSwgeTEgPSArX1sxXVsxXSwgc2Fua2V5KSA6IFtbeDAsIHkwXSwgW3gxLCB5MV1dO1xuICB9O1xuXG4gIHNhbmtleS5pdGVyYXRpb25zID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGl0ZXJhdGlvbnMgPSArXywgc2Fua2V5KSA6IGl0ZXJhdGlvbnM7XG4gIH07XG5cbiAgLy8gUG9wdWxhdGUgdGhlIHNvdXJjZUxpbmtzIGFuZCB0YXJnZXRMaW5rcyBmb3IgZWFjaCBub2RlLlxuICAvLyBBbHNvLCBpZiB0aGUgc291cmNlIGFuZCB0YXJnZXQgYXJlIG5vdCBvYmplY3RzLCBhc3N1bWUgdGhleSBhcmUgaW5kaWNlcy5cbiAgZnVuY3Rpb24gY29tcHV0ZU5vZGVMaW5rcyhncmFwaCkge1xuICAgIGdyYXBoLm5vZGVzLmZvckVhY2goZnVuY3Rpb24obm9kZSwgaSkge1xuICAgICAgbm9kZS5pbmRleCA9IGk7XG4gICAgICBub2RlLnNvdXJjZUxpbmtzID0gW107XG4gICAgICBub2RlLnRhcmdldExpbmtzID0gW107XG4gICAgfSk7XG5cbiAgICB2YXIgbm9kZUJ5SWQgPSBkM0NvbGxlY3Rpb24ubWFwKGdyYXBoLm5vZGVzLCBpZCk7XG4gICAgZ3JhcGgubGlua3MuZm9yRWFjaChmdW5jdGlvbihsaW5rLCBpKSB7XG4gICAgICBsaW5rLmluZGV4ID0gaTtcbiAgICAgIHZhciBzb3VyY2UgPSBsaW5rLnNvdXJjZSwgdGFyZ2V0ID0gbGluay50YXJnZXQ7XG4gICAgICBpZiAodHlwZW9mIHNvdXJjZSAhPT0gXCJvYmplY3RcIikgc291cmNlID0gbGluay5zb3VyY2UgPSBmaW5kKG5vZGVCeUlkLCBzb3VyY2UpO1xuICAgICAgaWYgKHR5cGVvZiB0YXJnZXQgIT09IFwib2JqZWN0XCIpIHRhcmdldCA9IGxpbmsudGFyZ2V0ID0gZmluZChub2RlQnlJZCwgdGFyZ2V0KTtcbiAgICAgIHNvdXJjZS5zb3VyY2VMaW5rcy5wdXNoKGxpbmspO1xuICAgICAgdGFyZ2V0LnRhcmdldExpbmtzLnB1c2gobGluayk7XG4gICAgfSk7XG4gIH1cblxuICAvLyBDb21wdXRlIHRoZSB2YWx1ZSAoc2l6ZSkgb2YgZWFjaCBub2RlIGJ5IHN1bW1pbmcgdGhlIGFzc29jaWF0ZWQgbGlua3MuXG4gIGZ1bmN0aW9uIGNvbXB1dGVOb2RlVmFsdWVzKGdyYXBoKSB7XG4gICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlLnZhbHVlID0gTWF0aC5tYXgoXG4gICAgICAgIGQzQXJyYXkuc3VtKG5vZGUuc291cmNlTGlua3MsIHZhbHVlKSxcbiAgICAgICAgZDNBcnJheS5zdW0obm9kZS50YXJnZXRMaW5rcywgdmFsdWUpXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gSXRlcmF0aXZlbHkgYXNzaWduIHRoZSBkZXB0aCAoeC1wb3NpdGlvbikgZm9yIGVhY2ggbm9kZS5cbiAgLy8gTm9kZXMgYXJlIGFzc2lnbmVkIHRoZSBtYXhpbXVtIGRlcHRoIG9mIGluY29taW5nIG5laWdoYm9ycyBwbHVzIG9uZTtcbiAgLy8gbm9kZXMgd2l0aCBubyBpbmNvbWluZyBsaW5rcyBhcmUgYXNzaWduZWQgZGVwdGggemVybywgd2hpbGVcbiAgLy8gbm9kZXMgd2l0aCBubyBvdXRnb2luZyBsaW5rcyBhcmUgYXNzaWduZWQgdGhlIG1heGltdW0gZGVwdGguXG4gIGZ1bmN0aW9uIGNvbXB1dGVOb2RlRGVwdGhzKGdyYXBoKSB7XG4gICAgdmFyIG5vZGVzLCBuZXh0LCB4O1xuXG4gICAgZm9yIChub2RlcyA9IGdyYXBoLm5vZGVzLCBuZXh0ID0gW10sIHggPSAwOyBub2Rlcy5sZW5ndGg7ICsreCwgbm9kZXMgPSBuZXh0LCBuZXh0ID0gW10pIHtcbiAgICAgIG5vZGVzLmZvckVhY2goZnVuY3Rpb24obm9kZSkge1xuICAgICAgICBub2RlLmRlcHRoID0geDtcbiAgICAgICAgbm9kZS5zb3VyY2VMaW5rcy5mb3JFYWNoKGZ1bmN0aW9uKGxpbmspIHtcbiAgICAgICAgICBpZiAobmV4dC5pbmRleE9mKGxpbmsudGFyZ2V0KSA8IDApIHtcbiAgICAgICAgICAgIG5leHQucHVzaChsaW5rLnRhcmdldCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAobm9kZXMgPSBncmFwaC5ub2RlcywgbmV4dCA9IFtdLCB4ID0gMDsgbm9kZXMubGVuZ3RoOyArK3gsIG5vZGVzID0gbmV4dCwgbmV4dCA9IFtdKSB7XG4gICAgICBub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgbm9kZS5oZWlnaHQgPSB4O1xuICAgICAgICBub2RlLnRhcmdldExpbmtzLmZvckVhY2goZnVuY3Rpb24obGluaykge1xuICAgICAgICAgIGlmIChuZXh0LmluZGV4T2YobGluay5zb3VyY2UpIDwgMCkge1xuICAgICAgICAgICAgbmV4dC5wdXNoKGxpbmsuc291cmNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIGt4ID0gKHgxIC0geDAgLSBkeCkgLyAoeCAtIDEpO1xuICAgIGdyYXBoLm5vZGVzLmZvckVhY2goZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZS54MSA9IChub2RlLngwID0geDAgKyBNYXRoLm1heCgwLCBNYXRoLm1pbih4IC0gMSwgTWF0aC5mbG9vcihhbGlnbi5jYWxsKG51bGwsIG5vZGUsIHgpKSkpICoga3gpICsgZHg7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBjb21wdXRlTm9kZUJyZWFkdGhzKGdyYXBoKSB7XG4gICAgdmFyIGNvbHVtbnMgPSBkM0NvbGxlY3Rpb24ubmVzdCgpXG4gICAgICAgIC5rZXkoZnVuY3Rpb24oZCkgeyByZXR1cm4gZC54MDsgfSlcbiAgICAgICAgLnNvcnRLZXlzKGQzQXJyYXkuYXNjZW5kaW5nKVxuICAgICAgICAuZW50cmllcyhncmFwaC5ub2RlcylcbiAgICAgICAgLm1hcChmdW5jdGlvbihkKSB7IHJldHVybiBkLnZhbHVlczsgfSk7XG5cbiAgICAvL1xuICAgIGluaXRpYWxpemVOb2RlQnJlYWR0aCgpO1xuICAgIHJlc29sdmVDb2xsaXNpb25zKCk7XG4gICAgZm9yICh2YXIgYWxwaGEgPSAxLCBuID0gaXRlcmF0aW9uczsgbiA+IDA7IC0tbikge1xuICAgICAgcmVsYXhSaWdodFRvTGVmdChhbHBoYSAqPSAwLjk5KTtcbiAgICAgIHJlc29sdmVDb2xsaXNpb25zKCk7XG4gICAgICByZWxheExlZnRUb1JpZ2h0KGFscGhhKTtcbiAgICAgIHJlc29sdmVDb2xsaXNpb25zKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5pdGlhbGl6ZU5vZGVCcmVhZHRoKCkge1xuICAgICAgdmFyIEwgPSBkM0FycmF5Lm1heChjb2x1bW5zLCBmdW5jdGlvbihub2Rlcykge1xuICAgICAgICByZXR1cm4gbm9kZXMubGVuZ3RoO1xuICAgICAgfSk7XG4gICAgICB2YXIgbWF4Tm9kZVBhZGRpbmcgPSBtYXhQYWRkZWRTcGFjZSAqICh5MSAtIHkwKSAvIChMIC0gMSk7XG4gICAgICBpZihweSA+IG1heE5vZGVQYWRkaW5nKSBweSA9IG1heE5vZGVQYWRkaW5nO1xuICAgICAgdmFyIGt5ID0gZDNBcnJheS5taW4oY29sdW1ucywgZnVuY3Rpb24obm9kZXMpIHtcbiAgICAgICAgcmV0dXJuICh5MSAtIHkwIC0gKG5vZGVzLmxlbmd0aCAtIDEpICogcHkpIC8gZDNBcnJheS5zdW0obm9kZXMsIHZhbHVlKTtcbiAgICAgIH0pO1xuXG4gICAgICBjb2x1bW5zLmZvckVhY2goZnVuY3Rpb24obm9kZXMpIHtcbiAgICAgICAgbm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlLCBpKSB7XG4gICAgICAgICAgbm9kZS55MSA9IChub2RlLnkwID0gaSkgKyBub2RlLnZhbHVlICoga3k7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGdyYXBoLmxpbmtzLmZvckVhY2goZnVuY3Rpb24obGluaykge1xuICAgICAgICBsaW5rLndpZHRoID0gbGluay52YWx1ZSAqIGt5O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVsYXhMZWZ0VG9SaWdodChhbHBoYSkge1xuICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGVzKSB7XG4gICAgICAgIG5vZGVzLmZvckVhY2goZnVuY3Rpb24obm9kZSkge1xuICAgICAgICAgIGlmIChub2RlLnRhcmdldExpbmtzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGR5ID0gKGQzQXJyYXkuc3VtKG5vZGUudGFyZ2V0TGlua3MsIHdlaWdodGVkU291cmNlKSAvIGQzQXJyYXkuc3VtKG5vZGUudGFyZ2V0TGlua3MsIHZhbHVlKSAtIG5vZGVDZW50ZXIobm9kZSkpICogYWxwaGE7XG4gICAgICAgICAgICBub2RlLnkwICs9IGR5LCBub2RlLnkxICs9IGR5O1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZWxheFJpZ2h0VG9MZWZ0KGFscGhhKSB7XG4gICAgICBjb2x1bW5zLnNsaWNlKCkucmV2ZXJzZSgpLmZvckVhY2goZnVuY3Rpb24obm9kZXMpIHtcbiAgICAgICAgbm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICAgICAgaWYgKG5vZGUuc291cmNlTGlua3MubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgZHkgPSAoZDNBcnJheS5zdW0obm9kZS5zb3VyY2VMaW5rcywgd2VpZ2h0ZWRUYXJnZXQpIC8gZDNBcnJheS5zdW0obm9kZS5zb3VyY2VMaW5rcywgdmFsdWUpIC0gbm9kZUNlbnRlcihub2RlKSkgKiBhbHBoYTtcbiAgICAgICAgICAgIG5vZGUueTAgKz0gZHksIG5vZGUueTEgKz0gZHk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlc29sdmVDb2xsaXNpb25zKCkge1xuICAgICAgY29sdW1ucy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGVzKSB7XG4gICAgICAgIHZhciBub2RlLFxuICAgICAgICAgICAgZHksXG4gICAgICAgICAgICB5ID0geTAsXG4gICAgICAgICAgICBuID0gbm9kZXMubGVuZ3RoLFxuICAgICAgICAgICAgaTtcblxuICAgICAgICAvLyBQdXNoIGFueSBvdmVybGFwcGluZyBub2RlcyBkb3duLlxuICAgICAgICBub2Rlcy5zb3J0KGFzY2VuZGluZ0JyZWFkdGgpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgICAgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICAgIGR5ID0geSAtIG5vZGUueTA7XG4gICAgICAgICAgaWYgKGR5ID4gMCkgbm9kZS55MCArPSBkeSwgbm9kZS55MSArPSBkeTtcbiAgICAgICAgICB5ID0gbm9kZS55MSArIHB5O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhlIGJvdHRvbW1vc3Qgbm9kZSBnb2VzIG91dHNpZGUgdGhlIGJvdW5kcywgcHVzaCBpdCBiYWNrIHVwLlxuICAgICAgICBkeSA9IHkgLSBweSAtIHkxO1xuICAgICAgICBpZiAoZHkgPiAwKSB7XG4gICAgICAgICAgeSA9IChub2RlLnkwIC09IGR5KSwgbm9kZS55MSAtPSBkeTtcblxuICAgICAgICAgIC8vIFB1c2ggYW55IG92ZXJsYXBwaW5nIG5vZGVzIGJhY2sgdXAuXG4gICAgICAgICAgZm9yIChpID0gbiAtIDI7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBub2RlID0gbm9kZXNbaV07XG4gICAgICAgICAgICBkeSA9IG5vZGUueTEgKyBweSAtIHk7XG4gICAgICAgICAgICBpZiAoZHkgPiAwKSBub2RlLnkwIC09IGR5LCBub2RlLnkxIC09IGR5O1xuICAgICAgICAgICAgeSA9IG5vZGUueTA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjb21wdXRlTGlua0JyZWFkdGhzKGdyYXBoKSB7XG4gICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlLnNvdXJjZUxpbmtzLnNvcnQoYXNjZW5kaW5nVGFyZ2V0QnJlYWR0aCk7XG4gICAgICBub2RlLnRhcmdldExpbmtzLnNvcnQoYXNjZW5kaW5nU291cmNlQnJlYWR0aCk7XG4gICAgfSk7XG4gICAgZ3JhcGgubm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICB2YXIgeTAgPSBub2RlLnkwLCB5MSA9IHkwO1xuICAgICAgbm9kZS5zb3VyY2VMaW5rcy5mb3JFYWNoKGZ1bmN0aW9uKGxpbmspIHtcbiAgICAgICAgbGluay55MCA9IHkwICsgbGluay53aWR0aCAvIDIsIHkwICs9IGxpbmsud2lkdGg7XG4gICAgICB9KTtcbiAgICAgIG5vZGUudGFyZ2V0TGlua3MuZm9yRWFjaChmdW5jdGlvbihsaW5rKSB7XG4gICAgICAgIGxpbmsueTEgPSB5MSArIGxpbmsud2lkdGggLyAyLCB5MSArPSBsaW5rLndpZHRoO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc2Fua2V5O1xufTtcblxuZnVuY3Rpb24gaG9yaXpvbnRhbFNvdXJjZShkKSB7XG4gIHJldHVybiBbZC5zb3VyY2UueDEsIGQueTBdO1xufVxuXG5mdW5jdGlvbiBob3Jpem9udGFsVGFyZ2V0KGQpIHtcbiAgcmV0dXJuIFtkLnRhcmdldC54MCwgZC55MV07XG59XG5cbnZhciBzYW5rZXlMaW5rSG9yaXpvbnRhbCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gZDNTaGFwZS5saW5rSG9yaXpvbnRhbCgpXG4gICAgICAuc291cmNlKGhvcml6b250YWxTb3VyY2UpXG4gICAgICAudGFyZ2V0KGhvcml6b250YWxUYXJnZXQpO1xufTtcblxuZXhwb3J0cy5zYW5rZXkgPSBzYW5rZXk7XG5leHBvcnRzLnNhbmtleUNlbnRlciA9IGNlbnRlcjtcbmV4cG9ydHMuc2Fua2V5TGVmdCA9IGxlZnQ7XG5leHBvcnRzLnNhbmtleVJpZ2h0ID0gcmlnaHQ7XG5leHBvcnRzLnNhbmtleUp1c3RpZnkgPSBqdXN0aWZ5O1xuZXhwb3J0cy5zYW5rZXlMaW5rSG9yaXpvbnRhbCA9IHNhbmtleUxpbmtIb3Jpem9udGFsO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuXG59LHtcImQzLWFycmF5XCI6MTUyLFwiZDMtY29sbGVjdGlvblwiOjE1MyxcImQzLXNoYXBlXCI6MTYxfV0sNTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgbWV0YV8xID0gX2RlcmVxXyhcIkB0dXJmL21ldGFcIik7XG4vLyBOb3RlOiBjaGFuZ2UgUkFESVVTID0+IGVhcnRoUmFkaXVzXG52YXIgUkFESVVTID0gNjM3ODEzNztcbi8qKlxuICogVGFrZXMgb25lIG9yIG1vcmUgZmVhdHVyZXMgYW5kIHJldHVybnMgdGhlaXIgYXJlYSBpbiBzcXVhcmUgbWV0ZXJzLlxuICpcbiAqIEBuYW1lIGFyZWFcbiAqIEBwYXJhbSB7R2VvSlNPTn0gZ2VvanNvbiBpbnB1dCBHZW9KU09OIGZlYXR1cmUocylcbiAqIEByZXR1cm5zIHtudW1iZXJ9IGFyZWEgaW4gc3F1YXJlIG1ldGVyc1xuICogQGV4YW1wbGVcbiAqIHZhciBwb2x5Z29uID0gdHVyZi5wb2x5Z29uKFtbWzEyNSwgLTE1XSwgWzExMywgLTIyXSwgWzE1NCwgLTI3XSwgWzE0NCwgLTE1XSwgWzEyNSwgLTE1XV1dKTtcbiAqXG4gKiB2YXIgYXJlYSA9IHR1cmYuYXJlYShwb2x5Z29uKTtcbiAqXG4gKiAvL2FkZFRvTWFwXG4gKiB2YXIgYWRkVG9NYXAgPSBbcG9seWdvbl1cbiAqIHBvbHlnb24ucHJvcGVydGllcy5hcmVhID0gYXJlYVxuICovXG5mdW5jdGlvbiBhcmVhKGdlb2pzb24pIHtcbiAgICByZXR1cm4gbWV0YV8xLmdlb21SZWR1Y2UoZ2VvanNvbiwgZnVuY3Rpb24gKHZhbHVlLCBnZW9tKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSArIGNhbGN1bGF0ZUFyZWEoZ2VvbSk7XG4gICAgfSwgMCk7XG59XG5leHBvcnRzLmRlZmF1bHQgPSBhcmVhO1xuLyoqXG4gKiBDYWxjdWxhdGUgQXJlYVxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0dlb21ldHJ5fSBnZW9tIEdlb0pTT04gR2VvbWV0cmllc1xuICogQHJldHVybnMge251bWJlcn0gYXJlYVxuICovXG5mdW5jdGlvbiBjYWxjdWxhdGVBcmVhKGdlb20pIHtcbiAgICB2YXIgdG90YWwgPSAwO1xuICAgIHZhciBpO1xuICAgIHN3aXRjaCAoZ2VvbS50eXBlKSB7XG4gICAgICAgIGNhc2UgXCJQb2x5Z29uXCI6XG4gICAgICAgICAgICByZXR1cm4gcG9seWdvbkFyZWEoZ2VvbS5jb29yZGluYXRlcyk7XG4gICAgICAgIGNhc2UgXCJNdWx0aVBvbHlnb25cIjpcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBnZW9tLmNvb3JkaW5hdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdG90YWwgKz0gcG9seWdvbkFyZWEoZ2VvbS5jb29yZGluYXRlc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdG90YWw7XG4gICAgICAgIGNhc2UgXCJQb2ludFwiOlxuICAgICAgICBjYXNlIFwiTXVsdGlQb2ludFwiOlxuICAgICAgICBjYXNlIFwiTGluZVN0cmluZ1wiOlxuICAgICAgICBjYXNlIFwiTXVsdGlMaW5lU3RyaW5nXCI6XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG59XG5mdW5jdGlvbiBwb2x5Z29uQXJlYShjb29yZHMpIHtcbiAgICB2YXIgdG90YWwgPSAwO1xuICAgIGlmIChjb29yZHMgJiYgY29vcmRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdG90YWwgKz0gTWF0aC5hYnMocmluZ0FyZWEoY29vcmRzWzBdKSk7XG4gICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0b3RhbCAtPSBNYXRoLmFicyhyaW5nQXJlYShjb29yZHNbaV0pKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdG90YWw7XG59XG4vKipcbiAqIEBwcml2YXRlXG4gKiBDYWxjdWxhdGUgdGhlIGFwcHJveGltYXRlIGFyZWEgb2YgdGhlIHBvbHlnb24gd2VyZSBpdCBwcm9qZWN0ZWQgb250byB0aGUgZWFydGguXG4gKiBOb3RlIHRoYXQgdGhpcyBhcmVhIHdpbGwgYmUgcG9zaXRpdmUgaWYgcmluZyBpcyBvcmllbnRlZCBjbG9ja3dpc2UsIG90aGVyd2lzZSBpdCB3aWxsIGJlIG5lZ2F0aXZlLlxuICpcbiAqIFJlZmVyZW5jZTpcbiAqIFJvYmVydC4gRy4gQ2hhbWJlcmxhaW4gYW5kIFdpbGxpYW0gSC4gRHVxdWV0dGUsIFwiU29tZSBBbGdvcml0aG1zIGZvciBQb2x5Z29ucyBvbiBhIFNwaGVyZVwiLFxuICogSlBMIFB1YmxpY2F0aW9uIDA3LTAzLCBKZXQgUHJvcHVsc2lvblxuICogTGFib3JhdG9yeSwgUGFzYWRlbmEsIENBLCBKdW5lIDIwMDcgaHR0cDovL3Rycy1uZXcuanBsLm5hc2EuZ292L2RzcGFjZS9oYW5kbGUvMjAxNC80MDQwOVxuICpcbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8bnVtYmVyPj59IGNvb3JkcyBSaW5nIENvb3JkaW5hdGVzXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBUaGUgYXBwcm94aW1hdGUgc2lnbmVkIGdlb2Rlc2ljIGFyZWEgb2YgdGhlIHBvbHlnb24gaW4gc3F1YXJlIG1ldGVycy5cbiAqL1xuZnVuY3Rpb24gcmluZ0FyZWEoY29vcmRzKSB7XG4gICAgdmFyIHAxO1xuICAgIHZhciBwMjtcbiAgICB2YXIgcDM7XG4gICAgdmFyIGxvd2VySW5kZXg7XG4gICAgdmFyIG1pZGRsZUluZGV4O1xuICAgIHZhciB1cHBlckluZGV4O1xuICAgIHZhciBpO1xuICAgIHZhciB0b3RhbCA9IDA7XG4gICAgdmFyIGNvb3Jkc0xlbmd0aCA9IGNvb3Jkcy5sZW5ndGg7XG4gICAgaWYgKGNvb3Jkc0xlbmd0aCA+IDIpIHtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvb3Jkc0xlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoaSA9PT0gY29vcmRzTGVuZ3RoIC0gMikge1xuICAgICAgICAgICAgICAgIGxvd2VySW5kZXggPSBjb29yZHNMZW5ndGggLSAyO1xuICAgICAgICAgICAgICAgIG1pZGRsZUluZGV4ID0gY29vcmRzTGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB1cHBlckluZGV4ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGkgPT09IGNvb3Jkc0xlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICBsb3dlckluZGV4ID0gY29vcmRzTGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICBtaWRkbGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdXBwZXJJbmRleCA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsb3dlckluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICBtaWRkbGVJbmRleCA9IGkgKyAxO1xuICAgICAgICAgICAgICAgIHVwcGVySW5kZXggPSBpICsgMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHAxID0gY29vcmRzW2xvd2VySW5kZXhdO1xuICAgICAgICAgICAgcDIgPSBjb29yZHNbbWlkZGxlSW5kZXhdO1xuICAgICAgICAgICAgcDMgPSBjb29yZHNbdXBwZXJJbmRleF07XG4gICAgICAgICAgICB0b3RhbCArPSAocmFkKHAzWzBdKSAtIHJhZChwMVswXSkpICogTWF0aC5zaW4ocmFkKHAyWzFdKSk7XG4gICAgICAgIH1cbiAgICAgICAgdG90YWwgPSB0b3RhbCAqIFJBRElVUyAqIFJBRElVUyAvIDI7XG4gICAgfVxuICAgIHJldHVybiB0b3RhbDtcbn1cbmZ1bmN0aW9uIHJhZChudW0pIHtcbiAgICByZXR1cm4gbnVtICogTWF0aC5QSSAvIDE4MDtcbn1cblxufSx7XCJAdHVyZi9tZXRhXCI6NTh9XSw1NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhciBtZXRhXzEgPSBfZGVyZXFfKFwiQHR1cmYvbWV0YVwiKTtcbnZhciBoZWxwZXJzXzEgPSBfZGVyZXFfKFwiQHR1cmYvaGVscGVyc1wiKTtcbi8qKlxuICogVGFrZXMgb25lIG9yIG1vcmUgZmVhdHVyZXMgYW5kIGNhbGN1bGF0ZXMgdGhlIGNlbnRyb2lkIHVzaW5nIHRoZSBtZWFuIG9mIGFsbCB2ZXJ0aWNlcy5cbiAqIFRoaXMgbGVzc2VucyB0aGUgZWZmZWN0IG9mIHNtYWxsIGlzbGFuZHMgYW5kIGFydGlmYWN0cyB3aGVuIGNhbGN1bGF0aW5nIHRoZSBjZW50cm9pZCBvZiBhIHNldCBvZiBwb2x5Z29ucy5cbiAqXG4gKiBAbmFtZSBjZW50cm9pZFxuICogQHBhcmFtIHtHZW9KU09OfSBnZW9qc29uIEdlb0pTT04gdG8gYmUgY2VudGVyZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gT3B0aW9uYWwgUGFyYW1ldGVyc1xuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLnByb3BlcnRpZXM9e31dIGFuIE9iamVjdCB0aGF0IGlzIHVzZWQgYXMgdGhlIHtAbGluayBGZWF0dXJlfSdzIHByb3BlcnRpZXNcbiAqIEByZXR1cm5zIHtGZWF0dXJlPFBvaW50Pn0gdGhlIGNlbnRyb2lkIG9mIHRoZSBpbnB1dCBmZWF0dXJlc1xuICogQGV4YW1wbGVcbiAqIHZhciBwb2x5Z29uID0gdHVyZi5wb2x5Z29uKFtbWy04MSwgNDFdLCBbLTg4LCAzNl0sIFstODQsIDMxXSwgWy04MCwgMzNdLCBbLTc3LCAzOV0sIFstODEsIDQxXV1dKTtcbiAqXG4gKiB2YXIgY2VudHJvaWQgPSB0dXJmLmNlbnRyb2lkKHBvbHlnb24pO1xuICpcbiAqIC8vYWRkVG9NYXBcbiAqIHZhciBhZGRUb01hcCA9IFtwb2x5Z29uLCBjZW50cm9pZF1cbiAqL1xuZnVuY3Rpb24gY2VudHJvaWQoZ2VvanNvbiwgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgdmFyIHhTdW0gPSAwO1xuICAgIHZhciB5U3VtID0gMDtcbiAgICB2YXIgbGVuID0gMDtcbiAgICBtZXRhXzEuY29vcmRFYWNoKGdlb2pzb24sIGZ1bmN0aW9uIChjb29yZCkge1xuICAgICAgICB4U3VtICs9IGNvb3JkWzBdO1xuICAgICAgICB5U3VtICs9IGNvb3JkWzFdO1xuICAgICAgICBsZW4rKztcbiAgICB9KTtcbiAgICByZXR1cm4gaGVscGVyc18xLnBvaW50KFt4U3VtIC8gbGVuLCB5U3VtIC8gbGVuXSwgb3B0aW9ucy5wcm9wZXJ0aWVzKTtcbn1cbmV4cG9ydHMuZGVmYXVsdCA9IGNlbnRyb2lkO1xuXG59LHtcIkB0dXJmL2hlbHBlcnNcIjo1NyxcIkB0dXJmL21ldGFcIjo1OH1dLDU3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuLyoqXG4gKiBAbW9kdWxlIGhlbHBlcnNcbiAqL1xuLyoqXG4gKiBFYXJ0aCBSYWRpdXMgdXNlZCB3aXRoIHRoZSBIYXJ2ZXNpbmUgZm9ybXVsYSBhbmQgYXBwcm94aW1hdGVzIHVzaW5nIGEgc3BoZXJpY2FsIChub24tZWxsaXBzb2lkKSBFYXJ0aC5cbiAqXG4gKiBAbWVtYmVyb2YgaGVscGVyc1xuICogQHR5cGUge251bWJlcn1cbiAqL1xuZXhwb3J0cy5lYXJ0aFJhZGl1cyA9IDYzNzEwMDguODtcbi8qKlxuICogVW5pdCBvZiBtZWFzdXJlbWVudCBmYWN0b3JzIHVzaW5nIGEgc3BoZXJpY2FsIChub24tZWxsaXBzb2lkKSBlYXJ0aCByYWRpdXMuXG4gKlxuICogQG1lbWJlcm9mIGhlbHBlcnNcbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbmV4cG9ydHMuZmFjdG9ycyA9IHtcbiAgICBjZW50aW1ldGVyczogZXhwb3J0cy5lYXJ0aFJhZGl1cyAqIDEwMCxcbiAgICBjZW50aW1ldHJlczogZXhwb3J0cy5lYXJ0aFJhZGl1cyAqIDEwMCxcbiAgICBkZWdyZWVzOiBleHBvcnRzLmVhcnRoUmFkaXVzIC8gMTExMzI1LFxuICAgIGZlZXQ6IGV4cG9ydHMuZWFydGhSYWRpdXMgKiAzLjI4MDg0LFxuICAgIGluY2hlczogZXhwb3J0cy5lYXJ0aFJhZGl1cyAqIDM5LjM3MCxcbiAgICBraWxvbWV0ZXJzOiBleHBvcnRzLmVhcnRoUmFkaXVzIC8gMTAwMCxcbiAgICBraWxvbWV0cmVzOiBleHBvcnRzLmVhcnRoUmFkaXVzIC8gMTAwMCxcbiAgICBtZXRlcnM6IGV4cG9ydHMuZWFydGhSYWRpdXMsXG4gICAgbWV0cmVzOiBleHBvcnRzLmVhcnRoUmFkaXVzLFxuICAgIG1pbGVzOiBleHBvcnRzLmVhcnRoUmFkaXVzIC8gMTYwOS4zNDQsXG4gICAgbWlsbGltZXRlcnM6IGV4cG9ydHMuZWFydGhSYWRpdXMgKiAxMDAwLFxuICAgIG1pbGxpbWV0cmVzOiBleHBvcnRzLmVhcnRoUmFkaXVzICogMTAwMCxcbiAgICBuYXV0aWNhbG1pbGVzOiBleHBvcnRzLmVhcnRoUmFkaXVzIC8gMTg1MixcbiAgICByYWRpYW5zOiAxLFxuICAgIHlhcmRzOiBleHBvcnRzLmVhcnRoUmFkaXVzIC8gMS4wOTM2LFxufTtcbi8qKlxuICogVW5pdHMgb2YgbWVhc3VyZW1lbnQgZmFjdG9ycyBiYXNlZCBvbiAxIG1ldGVyLlxuICpcbiAqIEBtZW1iZXJvZiBoZWxwZXJzXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5leHBvcnRzLnVuaXRzRmFjdG9ycyA9IHtcbiAgICBjZW50aW1ldGVyczogMTAwLFxuICAgIGNlbnRpbWV0cmVzOiAxMDAsXG4gICAgZGVncmVlczogMSAvIDExMTMyNSxcbiAgICBmZWV0OiAzLjI4MDg0LFxuICAgIGluY2hlczogMzkuMzcwLFxuICAgIGtpbG9tZXRlcnM6IDEgLyAxMDAwLFxuICAgIGtpbG9tZXRyZXM6IDEgLyAxMDAwLFxuICAgIG1ldGVyczogMSxcbiAgICBtZXRyZXM6IDEsXG4gICAgbWlsZXM6IDEgLyAxNjA5LjM0NCxcbiAgICBtaWxsaW1ldGVyczogMTAwMCxcbiAgICBtaWxsaW1ldHJlczogMTAwMCxcbiAgICBuYXV0aWNhbG1pbGVzOiAxIC8gMTg1MixcbiAgICByYWRpYW5zOiAxIC8gZXhwb3J0cy5lYXJ0aFJhZGl1cyxcbiAgICB5YXJkczogMSAvIDEuMDkzNixcbn07XG4vKipcbiAqIEFyZWEgb2YgbWVhc3VyZW1lbnQgZmFjdG9ycyBiYXNlZCBvbiAxIHNxdWFyZSBtZXRlci5cbiAqXG4gKiBAbWVtYmVyb2YgaGVscGVyc1xuICogQHR5cGUge09iamVjdH1cbiAqL1xuZXhwb3J0cy5hcmVhRmFjdG9ycyA9IHtcbiAgICBhY3JlczogMC4wMDAyNDcxMDUsXG4gICAgY2VudGltZXRlcnM6IDEwMDAwLFxuICAgIGNlbnRpbWV0cmVzOiAxMDAwMCxcbiAgICBmZWV0OiAxMC43NjM5MTA0MTcsXG4gICAgaW5jaGVzOiAxNTUwLjAwMzEwMDAwNixcbiAgICBraWxvbWV0ZXJzOiAwLjAwMDAwMSxcbiAgICBraWxvbWV0cmVzOiAwLjAwMDAwMSxcbiAgICBtZXRlcnM6IDEsXG4gICAgbWV0cmVzOiAxLFxuICAgIG1pbGVzOiAzLjg2ZS03LFxuICAgIG1pbGxpbWV0ZXJzOiAxMDAwMDAwLFxuICAgIG1pbGxpbWV0cmVzOiAxMDAwMDAwLFxuICAgIHlhcmRzOiAxLjE5NTk5MDA0Nixcbn07XG4vKipcbiAqIFdyYXBzIGEgR2VvSlNPTiB7QGxpbmsgR2VvbWV0cnl9IGluIGEgR2VvSlNPTiB7QGxpbmsgRmVhdHVyZX0uXG4gKlxuICogQG5hbWUgZmVhdHVyZVxuICogQHBhcmFtIHtHZW9tZXRyeX0gZ2VvbWV0cnkgaW5wdXQgZ2VvbWV0cnlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbcHJvcGVydGllcz17fV0gYW4gT2JqZWN0IG9mIGtleS12YWx1ZSBwYWlycyB0byBhZGQgYXMgcHJvcGVydGllc1xuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBPcHRpb25hbCBQYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IFtvcHRpb25zLmJib3hdIEJvdW5kaW5nIEJveCBBcnJheSBbd2VzdCwgc291dGgsIGVhc3QsIG5vcnRoXSBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gW29wdGlvbnMuaWRdIElkZW50aWZpZXIgYXNzb2NpYXRlZCB3aXRoIHRoZSBGZWF0dXJlXG4gKiBAcmV0dXJucyB7RmVhdHVyZX0gYSBHZW9KU09OIEZlYXR1cmVcbiAqIEBleGFtcGxlXG4gKiB2YXIgZ2VvbWV0cnkgPSB7XG4gKiAgIFwidHlwZVwiOiBcIlBvaW50XCIsXG4gKiAgIFwiY29vcmRpbmF0ZXNcIjogWzExMCwgNTBdXG4gKiB9O1xuICpcbiAqIHZhciBmZWF0dXJlID0gdHVyZi5mZWF0dXJlKGdlb21ldHJ5KTtcbiAqXG4gKiAvLz1mZWF0dXJlXG4gKi9cbmZ1bmN0aW9uIGZlYXR1cmUoZ2VvbSwgcHJvcGVydGllcywgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgdmFyIGZlYXQgPSB7IHR5cGU6IFwiRmVhdHVyZVwiIH07XG4gICAgaWYgKG9wdGlvbnMuaWQgPT09IDAgfHwgb3B0aW9ucy5pZCkge1xuICAgICAgICBmZWF0LmlkID0gb3B0aW9ucy5pZDtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuYmJveCkge1xuICAgICAgICBmZWF0LmJib3ggPSBvcHRpb25zLmJib3g7XG4gICAgfVxuICAgIGZlYXQucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwge307XG4gICAgZmVhdC5nZW9tZXRyeSA9IGdlb207XG4gICAgcmV0dXJuIGZlYXQ7XG59XG5leHBvcnRzLmZlYXR1cmUgPSBmZWF0dXJlO1xuLyoqXG4gKiBDcmVhdGVzIGEgR2VvSlNPTiB7QGxpbmsgR2VvbWV0cnl9IGZyb20gYSBHZW9tZXRyeSBzdHJpbmcgdHlwZSAmIGNvb3JkaW5hdGVzLlxuICogRm9yIEdlb21ldHJ5Q29sbGVjdGlvbiB0eXBlIHVzZSBgaGVscGVycy5nZW9tZXRyeUNvbGxlY3Rpb25gXG4gKlxuICogQG5hbWUgZ2VvbWV0cnlcbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIEdlb21ldHJ5IFR5cGVcbiAqIEBwYXJhbSB7QXJyYXk8YW55Pn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXNcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gT3B0aW9uYWwgUGFyYW1ldGVyc1xuICogQHJldHVybnMge0dlb21ldHJ5fSBhIEdlb0pTT04gR2VvbWV0cnlcbiAqIEBleGFtcGxlXG4gKiB2YXIgdHlwZSA9IFwiUG9pbnRcIjtcbiAqIHZhciBjb29yZGluYXRlcyA9IFsxMTAsIDUwXTtcbiAqIHZhciBnZW9tZXRyeSA9IHR1cmYuZ2VvbWV0cnkodHlwZSwgY29vcmRpbmF0ZXMpO1xuICogLy8gPT4gZ2VvbWV0cnlcbiAqL1xuZnVuY3Rpb24gZ2VvbWV0cnkodHlwZSwgY29vcmRpbmF0ZXMsIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlIFwiUG9pbnRcIjogcmV0dXJuIHBvaW50KGNvb3JkaW5hdGVzKS5nZW9tZXRyeTtcbiAgICAgICAgY2FzZSBcIkxpbmVTdHJpbmdcIjogcmV0dXJuIGxpbmVTdHJpbmcoY29vcmRpbmF0ZXMpLmdlb21ldHJ5O1xuICAgICAgICBjYXNlIFwiUG9seWdvblwiOiByZXR1cm4gcG9seWdvbihjb29yZGluYXRlcykuZ2VvbWV0cnk7XG4gICAgICAgIGNhc2UgXCJNdWx0aVBvaW50XCI6IHJldHVybiBtdWx0aVBvaW50KGNvb3JkaW5hdGVzKS5nZW9tZXRyeTtcbiAgICAgICAgY2FzZSBcIk11bHRpTGluZVN0cmluZ1wiOiByZXR1cm4gbXVsdGlMaW5lU3RyaW5nKGNvb3JkaW5hdGVzKS5nZW9tZXRyeTtcbiAgICAgICAgY2FzZSBcIk11bHRpUG9seWdvblwiOiByZXR1cm4gbXVsdGlQb2x5Z29uKGNvb3JkaW5hdGVzKS5nZW9tZXRyeTtcbiAgICAgICAgZGVmYXVsdDogdGhyb3cgbmV3IEVycm9yKHR5cGUgKyBcIiBpcyBpbnZhbGlkXCIpO1xuICAgIH1cbn1cbmV4cG9ydHMuZ2VvbWV0cnkgPSBnZW9tZXRyeTtcbi8qKlxuICogQ3JlYXRlcyBhIHtAbGluayBQb2ludH0ge0BsaW5rIEZlYXR1cmV9IGZyb20gYSBQb3NpdGlvbi5cbiAqXG4gKiBAbmFtZSBwb2ludFxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBjb29yZGluYXRlcyBsb25naXR1ZGUsIGxhdGl0dWRlIHBvc2l0aW9uIChlYWNoIGluIGRlY2ltYWwgZGVncmVlcylcbiAqIEBwYXJhbSB7T2JqZWN0fSBbcHJvcGVydGllcz17fV0gYW4gT2JqZWN0IG9mIGtleS12YWx1ZSBwYWlycyB0byBhZGQgYXMgcHJvcGVydGllc1xuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBPcHRpb25hbCBQYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IFtvcHRpb25zLmJib3hdIEJvdW5kaW5nIEJveCBBcnJheSBbd2VzdCwgc291dGgsIGVhc3QsIG5vcnRoXSBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gW29wdGlvbnMuaWRdIElkZW50aWZpZXIgYXNzb2NpYXRlZCB3aXRoIHRoZSBGZWF0dXJlXG4gKiBAcmV0dXJucyB7RmVhdHVyZTxQb2ludD59IGEgUG9pbnQgZmVhdHVyZVxuICogQGV4YW1wbGVcbiAqIHZhciBwb2ludCA9IHR1cmYucG9pbnQoWy03NS4zNDMsIDM5Ljk4NF0pO1xuICpcbiAqIC8vPXBvaW50XG4gKi9cbmZ1bmN0aW9uIHBvaW50KGNvb3JkaW5hdGVzLCBwcm9wZXJ0aWVzLCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICB2YXIgZ2VvbSA9IHtcbiAgICAgICAgdHlwZTogXCJQb2ludFwiLFxuICAgICAgICBjb29yZGluYXRlczogY29vcmRpbmF0ZXMsXG4gICAgfTtcbiAgICByZXR1cm4gZmVhdHVyZShnZW9tLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbn1cbmV4cG9ydHMucG9pbnQgPSBwb2ludDtcbi8qKlxuICogQ3JlYXRlcyBhIHtAbGluayBQb2ludH0ge0BsaW5rIEZlYXR1cmVDb2xsZWN0aW9ufSBmcm9tIGFuIEFycmF5IG9mIFBvaW50IGNvb3JkaW5hdGVzLlxuICpcbiAqIEBuYW1lIHBvaW50c1xuICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gY29vcmRpbmF0ZXMgYW4gYXJyYXkgb2YgUG9pbnRzXG4gKiBAcGFyYW0ge09iamVjdH0gW3Byb3BlcnRpZXM9e31dIFRyYW5zbGF0ZSB0aGVzZSBwcm9wZXJ0aWVzIHRvIGVhY2ggRmVhdHVyZVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBPcHRpb25hbCBQYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IFtvcHRpb25zLmJib3hdIEJvdW5kaW5nIEJveCBBcnJheSBbd2VzdCwgc291dGgsIGVhc3QsIG5vcnRoXVxuICogYXNzb2NpYXRlZCB3aXRoIHRoZSBGZWF0dXJlQ29sbGVjdGlvblxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBbb3B0aW9ucy5pZF0gSWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVDb2xsZWN0aW9uXG4gKiBAcmV0dXJucyB7RmVhdHVyZUNvbGxlY3Rpb248UG9pbnQ+fSBQb2ludCBGZWF0dXJlXG4gKiBAZXhhbXBsZVxuICogdmFyIHBvaW50cyA9IHR1cmYucG9pbnRzKFtcbiAqICAgWy03NSwgMzldLFxuICogICBbLTgwLCA0NV0sXG4gKiAgIFstNzgsIDUwXVxuICogXSk7XG4gKlxuICogLy89cG9pbnRzXG4gKi9cbmZ1bmN0aW9uIHBvaW50cyhjb29yZGluYXRlcywgcHJvcGVydGllcywgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgcmV0dXJuIGZlYXR1cmVDb2xsZWN0aW9uKGNvb3JkaW5hdGVzLm1hcChmdW5jdGlvbiAoY29vcmRzKSB7XG4gICAgICAgIHJldHVybiBwb2ludChjb29yZHMsIHByb3BlcnRpZXMpO1xuICAgIH0pLCBvcHRpb25zKTtcbn1cbmV4cG9ydHMucG9pbnRzID0gcG9pbnRzO1xuLyoqXG4gKiBDcmVhdGVzIGEge0BsaW5rIFBvbHlnb259IHtAbGluayBGZWF0dXJlfSBmcm9tIGFuIEFycmF5IG9mIExpbmVhclJpbmdzLlxuICpcbiAqIEBuYW1lIHBvbHlnb25cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8QXJyYXk8bnVtYmVyPj4+fSBjb29yZGluYXRlcyBhbiBhcnJheSBvZiBMaW5lYXJSaW5nc1xuICogQHBhcmFtIHtPYmplY3R9IFtwcm9wZXJ0aWVzPXt9XSBhbiBPYmplY3Qgb2Yga2V5LXZhbHVlIHBhaXJzIHRvIGFkZCBhcyBwcm9wZXJ0aWVzXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIE9wdGlvbmFsIFBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gW29wdGlvbnMuYmJveF0gQm91bmRpbmcgQm94IEFycmF5IFt3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGhdIGFzc29jaWF0ZWQgd2l0aCB0aGUgRmVhdHVyZVxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBbb3B0aW9ucy5pZF0gSWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVcbiAqIEByZXR1cm5zIHtGZWF0dXJlPFBvbHlnb24+fSBQb2x5Z29uIEZlYXR1cmVcbiAqIEBleGFtcGxlXG4gKiB2YXIgcG9seWdvbiA9IHR1cmYucG9seWdvbihbW1stNSwgNTJdLCBbLTQsIDU2XSwgWy0yLCA1MV0sIFstNywgNTRdLCBbLTUsIDUyXV1dLCB7IG5hbWU6ICdwb2x5MScgfSk7XG4gKlxuICogLy89cG9seWdvblxuICovXG5mdW5jdGlvbiBwb2x5Z29uKGNvb3JkaW5hdGVzLCBwcm9wZXJ0aWVzLCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICBmb3IgKHZhciBfaSA9IDAsIGNvb3JkaW5hdGVzXzEgPSBjb29yZGluYXRlczsgX2kgPCBjb29yZGluYXRlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICB2YXIgcmluZyA9IGNvb3JkaW5hdGVzXzFbX2ldO1xuICAgICAgICBpZiAocmluZy5sZW5ndGggPCA0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFYWNoIExpbmVhclJpbmcgb2YgYSBQb2x5Z29uIG11c3QgaGF2ZSA0IG9yIG1vcmUgUG9zaXRpb25zLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJpbmdbcmluZy5sZW5ndGggLSAxXS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgZmlyc3QgcG9pbnQgb2YgUG9seWdvbiBjb250YWlucyB0d28gbnVtYmVyc1xuICAgICAgICAgICAgaWYgKHJpbmdbcmluZy5sZW5ndGggLSAxXVtqXSAhPT0gcmluZ1swXVtqXSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZpcnN0IGFuZCBsYXN0IFBvc2l0aW9uIGFyZSBub3QgZXF1aXZhbGVudC5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgdmFyIGdlb20gPSB7XG4gICAgICAgIHR5cGU6IFwiUG9seWdvblwiLFxuICAgICAgICBjb29yZGluYXRlczogY29vcmRpbmF0ZXMsXG4gICAgfTtcbiAgICByZXR1cm4gZmVhdHVyZShnZW9tLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbn1cbmV4cG9ydHMucG9seWdvbiA9IHBvbHlnb247XG4vKipcbiAqIENyZWF0ZXMgYSB7QGxpbmsgUG9seWdvbn0ge0BsaW5rIEZlYXR1cmVDb2xsZWN0aW9ufSBmcm9tIGFuIEFycmF5IG9mIFBvbHlnb24gY29vcmRpbmF0ZXMuXG4gKlxuICogQG5hbWUgcG9seWdvbnNcbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8QXJyYXk8QXJyYXk8bnVtYmVyPj4+Pn0gY29vcmRpbmF0ZXMgYW4gYXJyYXkgb2YgUG9seWdvbiBjb29yZGluYXRlc1xuICogQHBhcmFtIHtPYmplY3R9IFtwcm9wZXJ0aWVzPXt9XSBhbiBPYmplY3Qgb2Yga2V5LXZhbHVlIHBhaXJzIHRvIGFkZCBhcyBwcm9wZXJ0aWVzXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIE9wdGlvbmFsIFBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gW29wdGlvbnMuYmJveF0gQm91bmRpbmcgQm94IEFycmF5IFt3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGhdIGFzc29jaWF0ZWQgd2l0aCB0aGUgRmVhdHVyZVxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBbb3B0aW9ucy5pZF0gSWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVDb2xsZWN0aW9uXG4gKiBAcmV0dXJucyB7RmVhdHVyZUNvbGxlY3Rpb248UG9seWdvbj59IFBvbHlnb24gRmVhdHVyZUNvbGxlY3Rpb25cbiAqIEBleGFtcGxlXG4gKiB2YXIgcG9seWdvbnMgPSB0dXJmLnBvbHlnb25zKFtcbiAqICAgW1tbLTUsIDUyXSwgWy00LCA1Nl0sIFstMiwgNTFdLCBbLTcsIDU0XSwgWy01LCA1Ml1dXSxcbiAqICAgW1tbLTE1LCA0Ml0sIFstMTQsIDQ2XSwgWy0xMiwgNDFdLCBbLTE3LCA0NF0sIFstMTUsIDQyXV1dLFxuICogXSk7XG4gKlxuICogLy89cG9seWdvbnNcbiAqL1xuZnVuY3Rpb24gcG9seWdvbnMoY29vcmRpbmF0ZXMsIHByb3BlcnRpZXMsIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgIHJldHVybiBmZWF0dXJlQ29sbGVjdGlvbihjb29yZGluYXRlcy5tYXAoZnVuY3Rpb24gKGNvb3Jkcykge1xuICAgICAgICByZXR1cm4gcG9seWdvbihjb29yZHMsIHByb3BlcnRpZXMpO1xuICAgIH0pLCBvcHRpb25zKTtcbn1cbmV4cG9ydHMucG9seWdvbnMgPSBwb2x5Z29ucztcbi8qKlxuICogQ3JlYXRlcyBhIHtAbGluayBMaW5lU3RyaW5nfSB7QGxpbmsgRmVhdHVyZX0gZnJvbSBhbiBBcnJheSBvZiBQb3NpdGlvbnMuXG4gKlxuICogQG5hbWUgbGluZVN0cmluZ1xuICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gY29vcmRpbmF0ZXMgYW4gYXJyYXkgb2YgUG9zaXRpb25zXG4gKiBAcGFyYW0ge09iamVjdH0gW3Byb3BlcnRpZXM9e31dIGFuIE9iamVjdCBvZiBrZXktdmFsdWUgcGFpcnMgdG8gYWRkIGFzIHByb3BlcnRpZXNcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gT3B0aW9uYWwgUGFyYW1ldGVyc1xuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBbb3B0aW9ucy5iYm94XSBCb3VuZGluZyBCb3ggQXJyYXkgW3dlc3QsIHNvdXRoLCBlYXN0LCBub3J0aF0gYXNzb2NpYXRlZCB3aXRoIHRoZSBGZWF0dXJlXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IFtvcHRpb25zLmlkXSBJZGVudGlmaWVyIGFzc29jaWF0ZWQgd2l0aCB0aGUgRmVhdHVyZVxuICogQHJldHVybnMge0ZlYXR1cmU8TGluZVN0cmluZz59IExpbmVTdHJpbmcgRmVhdHVyZVxuICogQGV4YW1wbGVcbiAqIHZhciBsaW5lc3RyaW5nMSA9IHR1cmYubGluZVN0cmluZyhbWy0yNCwgNjNdLCBbLTIzLCA2MF0sIFstMjUsIDY1XSwgWy0yMCwgNjldXSwge25hbWU6ICdsaW5lIDEnfSk7XG4gKiB2YXIgbGluZXN0cmluZzIgPSB0dXJmLmxpbmVTdHJpbmcoW1stMTQsIDQzXSwgWy0xMywgNDBdLCBbLTE1LCA0NV0sIFstMTAsIDQ5XV0sIHtuYW1lOiAnbGluZSAyJ30pO1xuICpcbiAqIC8vPWxpbmVzdHJpbmcxXG4gKiAvLz1saW5lc3RyaW5nMlxuICovXG5mdW5jdGlvbiBsaW5lU3RyaW5nKGNvb3JkaW5hdGVzLCBwcm9wZXJ0aWVzLCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICBpZiAoY29vcmRpbmF0ZXMubGVuZ3RoIDwgMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb29yZGluYXRlcyBtdXN0IGJlIGFuIGFycmF5IG9mIHR3byBvciBtb3JlIHBvc2l0aW9uc1wiKTtcbiAgICB9XG4gICAgdmFyIGdlb20gPSB7XG4gICAgICAgIHR5cGU6IFwiTGluZVN0cmluZ1wiLFxuICAgICAgICBjb29yZGluYXRlczogY29vcmRpbmF0ZXMsXG4gICAgfTtcbiAgICByZXR1cm4gZmVhdHVyZShnZW9tLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbn1cbmV4cG9ydHMubGluZVN0cmluZyA9IGxpbmVTdHJpbmc7XG4vKipcbiAqIENyZWF0ZXMgYSB7QGxpbmsgTGluZVN0cmluZ30ge0BsaW5rIEZlYXR1cmVDb2xsZWN0aW9ufSBmcm9tIGFuIEFycmF5IG9mIExpbmVTdHJpbmcgY29vcmRpbmF0ZXMuXG4gKlxuICogQG5hbWUgbGluZVN0cmluZ3NcbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8QXJyYXk8bnVtYmVyPj4+fSBjb29yZGluYXRlcyBhbiBhcnJheSBvZiBMaW5lYXJSaW5nc1xuICogQHBhcmFtIHtPYmplY3R9IFtwcm9wZXJ0aWVzPXt9XSBhbiBPYmplY3Qgb2Yga2V5LXZhbHVlIHBhaXJzIHRvIGFkZCBhcyBwcm9wZXJ0aWVzXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIE9wdGlvbmFsIFBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gW29wdGlvbnMuYmJveF0gQm91bmRpbmcgQm94IEFycmF5IFt3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGhdXG4gKiBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVDb2xsZWN0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IFtvcHRpb25zLmlkXSBJZGVudGlmaWVyIGFzc29jaWF0ZWQgd2l0aCB0aGUgRmVhdHVyZUNvbGxlY3Rpb25cbiAqIEByZXR1cm5zIHtGZWF0dXJlQ29sbGVjdGlvbjxMaW5lU3RyaW5nPn0gTGluZVN0cmluZyBGZWF0dXJlQ29sbGVjdGlvblxuICogQGV4YW1wbGVcbiAqIHZhciBsaW5lc3RyaW5ncyA9IHR1cmYubGluZVN0cmluZ3MoW1xuICogICBbWy0yNCwgNjNdLCBbLTIzLCA2MF0sIFstMjUsIDY1XSwgWy0yMCwgNjldXSxcbiAqICAgW1stMTQsIDQzXSwgWy0xMywgNDBdLCBbLTE1LCA0NV0sIFstMTAsIDQ5XV1cbiAqIF0pO1xuICpcbiAqIC8vPWxpbmVzdHJpbmdzXG4gKi9cbmZ1bmN0aW9uIGxpbmVTdHJpbmdzKGNvb3JkaW5hdGVzLCBwcm9wZXJ0aWVzLCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICByZXR1cm4gZmVhdHVyZUNvbGxlY3Rpb24oY29vcmRpbmF0ZXMubWFwKGZ1bmN0aW9uIChjb29yZHMpIHtcbiAgICAgICAgcmV0dXJuIGxpbmVTdHJpbmcoY29vcmRzLCBwcm9wZXJ0aWVzKTtcbiAgICB9KSwgb3B0aW9ucyk7XG59XG5leHBvcnRzLmxpbmVTdHJpbmdzID0gbGluZVN0cmluZ3M7XG4vKipcbiAqIFRha2VzIG9uZSBvciBtb3JlIHtAbGluayBGZWF0dXJlfEZlYXR1cmVzfSBhbmQgY3JlYXRlcyBhIHtAbGluayBGZWF0dXJlQ29sbGVjdGlvbn0uXG4gKlxuICogQG5hbWUgZmVhdHVyZUNvbGxlY3Rpb25cbiAqIEBwYXJhbSB7RmVhdHVyZVtdfSBmZWF0dXJlcyBpbnB1dCBmZWF0dXJlc1xuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBPcHRpb25hbCBQYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IFtvcHRpb25zLmJib3hdIEJvdW5kaW5nIEJveCBBcnJheSBbd2VzdCwgc291dGgsIGVhc3QsIG5vcnRoXSBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gW29wdGlvbnMuaWRdIElkZW50aWZpZXIgYXNzb2NpYXRlZCB3aXRoIHRoZSBGZWF0dXJlXG4gKiBAcmV0dXJucyB7RmVhdHVyZUNvbGxlY3Rpb259IEZlYXR1cmVDb2xsZWN0aW9uIG9mIEZlYXR1cmVzXG4gKiBAZXhhbXBsZVxuICogdmFyIGxvY2F0aW9uQSA9IHR1cmYucG9pbnQoWy03NS4zNDMsIDM5Ljk4NF0sIHtuYW1lOiAnTG9jYXRpb24gQSd9KTtcbiAqIHZhciBsb2NhdGlvbkIgPSB0dXJmLnBvaW50KFstNzUuODMzLCAzOS4yODRdLCB7bmFtZTogJ0xvY2F0aW9uIEInfSk7XG4gKiB2YXIgbG9jYXRpb25DID0gdHVyZi5wb2ludChbLTc1LjUzNCwgMzkuMTIzXSwge25hbWU6ICdMb2NhdGlvbiBDJ30pO1xuICpcbiAqIHZhciBjb2xsZWN0aW9uID0gdHVyZi5mZWF0dXJlQ29sbGVjdGlvbihbXG4gKiAgIGxvY2F0aW9uQSxcbiAqICAgbG9jYXRpb25CLFxuICogICBsb2NhdGlvbkNcbiAqIF0pO1xuICpcbiAqIC8vPWNvbGxlY3Rpb25cbiAqL1xuZnVuY3Rpb24gZmVhdHVyZUNvbGxlY3Rpb24oZmVhdHVyZXMsIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgIHZhciBmYyA9IHsgdHlwZTogXCJGZWF0dXJlQ29sbGVjdGlvblwiIH07XG4gICAgaWYgKG9wdGlvbnMuaWQpIHtcbiAgICAgICAgZmMuaWQgPSBvcHRpb25zLmlkO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5iYm94KSB7XG4gICAgICAgIGZjLmJib3ggPSBvcHRpb25zLmJib3g7XG4gICAgfVxuICAgIGZjLmZlYXR1cmVzID0gZmVhdHVyZXM7XG4gICAgcmV0dXJuIGZjO1xufVxuZXhwb3J0cy5mZWF0dXJlQ29sbGVjdGlvbiA9IGZlYXR1cmVDb2xsZWN0aW9uO1xuLyoqXG4gKiBDcmVhdGVzIGEge0BsaW5rIEZlYXR1cmU8TXVsdGlMaW5lU3RyaW5nPn0gYmFzZWQgb24gYVxuICogY29vcmRpbmF0ZSBhcnJheS4gUHJvcGVydGllcyBjYW4gYmUgYWRkZWQgb3B0aW9uYWxseS5cbiAqXG4gKiBAbmFtZSBtdWx0aUxpbmVTdHJpbmdcbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8QXJyYXk8bnVtYmVyPj4+fSBjb29yZGluYXRlcyBhbiBhcnJheSBvZiBMaW5lU3RyaW5nc1xuICogQHBhcmFtIHtPYmplY3R9IFtwcm9wZXJ0aWVzPXt9XSBhbiBPYmplY3Qgb2Yga2V5LXZhbHVlIHBhaXJzIHRvIGFkZCBhcyBwcm9wZXJ0aWVzXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIE9wdGlvbmFsIFBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gW29wdGlvbnMuYmJveF0gQm91bmRpbmcgQm94IEFycmF5IFt3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGhdIGFzc29jaWF0ZWQgd2l0aCB0aGUgRmVhdHVyZVxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBbb3B0aW9ucy5pZF0gSWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVcbiAqIEByZXR1cm5zIHtGZWF0dXJlPE11bHRpTGluZVN0cmluZz59IGEgTXVsdGlMaW5lU3RyaW5nIGZlYXR1cmVcbiAqIEB0aHJvd3Mge0Vycm9yfSBpZiBubyBjb29yZGluYXRlcyBhcmUgcGFzc2VkXG4gKiBAZXhhbXBsZVxuICogdmFyIG11bHRpTGluZSA9IHR1cmYubXVsdGlMaW5lU3RyaW5nKFtbWzAsMF0sWzEwLDEwXV1dKTtcbiAqXG4gKiAvLz1tdWx0aUxpbmVcbiAqL1xuZnVuY3Rpb24gbXVsdGlMaW5lU3RyaW5nKGNvb3JkaW5hdGVzLCBwcm9wZXJ0aWVzLCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMgPT09IHZvaWQgMCkgeyBvcHRpb25zID0ge307IH1cbiAgICB2YXIgZ2VvbSA9IHtcbiAgICAgICAgdHlwZTogXCJNdWx0aUxpbmVTdHJpbmdcIixcbiAgICAgICAgY29vcmRpbmF0ZXM6IGNvb3JkaW5hdGVzLFxuICAgIH07XG4gICAgcmV0dXJuIGZlYXR1cmUoZ2VvbSwgcHJvcGVydGllcywgb3B0aW9ucyk7XG59XG5leHBvcnRzLm11bHRpTGluZVN0cmluZyA9IG11bHRpTGluZVN0cmluZztcbi8qKlxuICogQ3JlYXRlcyBhIHtAbGluayBGZWF0dXJlPE11bHRpUG9pbnQ+fSBiYXNlZCBvbiBhXG4gKiBjb29yZGluYXRlIGFycmF5LiBQcm9wZXJ0aWVzIGNhbiBiZSBhZGRlZCBvcHRpb25hbGx5LlxuICpcbiAqIEBuYW1lIG11bHRpUG9pbnRcbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8bnVtYmVyPj59IGNvb3JkaW5hdGVzIGFuIGFycmF5IG9mIFBvc2l0aW9uc1xuICogQHBhcmFtIHtPYmplY3R9IFtwcm9wZXJ0aWVzPXt9XSBhbiBPYmplY3Qgb2Yga2V5LXZhbHVlIHBhaXJzIHRvIGFkZCBhcyBwcm9wZXJ0aWVzXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIE9wdGlvbmFsIFBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gW29wdGlvbnMuYmJveF0gQm91bmRpbmcgQm94IEFycmF5IFt3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGhdIGFzc29jaWF0ZWQgd2l0aCB0aGUgRmVhdHVyZVxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBbb3B0aW9ucy5pZF0gSWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVcbiAqIEByZXR1cm5zIHtGZWF0dXJlPE11bHRpUG9pbnQ+fSBhIE11bHRpUG9pbnQgZmVhdHVyZVxuICogQHRocm93cyB7RXJyb3J9IGlmIG5vIGNvb3JkaW5hdGVzIGFyZSBwYXNzZWRcbiAqIEBleGFtcGxlXG4gKiB2YXIgbXVsdGlQdCA9IHR1cmYubXVsdGlQb2ludChbWzAsMF0sWzEwLDEwXV0pO1xuICpcbiAqIC8vPW11bHRpUHRcbiAqL1xuZnVuY3Rpb24gbXVsdGlQb2ludChjb29yZGluYXRlcywgcHJvcGVydGllcywgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgdmFyIGdlb20gPSB7XG4gICAgICAgIHR5cGU6IFwiTXVsdGlQb2ludFwiLFxuICAgICAgICBjb29yZGluYXRlczogY29vcmRpbmF0ZXMsXG4gICAgfTtcbiAgICByZXR1cm4gZmVhdHVyZShnZW9tLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbn1cbmV4cG9ydHMubXVsdGlQb2ludCA9IG11bHRpUG9pbnQ7XG4vKipcbiAqIENyZWF0ZXMgYSB7QGxpbmsgRmVhdHVyZTxNdWx0aVBvbHlnb24+fSBiYXNlZCBvbiBhXG4gKiBjb29yZGluYXRlIGFycmF5LiBQcm9wZXJ0aWVzIGNhbiBiZSBhZGRlZCBvcHRpb25hbGx5LlxuICpcbiAqIEBuYW1lIG11bHRpUG9seWdvblxuICogQHBhcmFtIHtBcnJheTxBcnJheTxBcnJheTxBcnJheTxudW1iZXI+Pj4+fSBjb29yZGluYXRlcyBhbiBhcnJheSBvZiBQb2x5Z29uc1xuICogQHBhcmFtIHtPYmplY3R9IFtwcm9wZXJ0aWVzPXt9XSBhbiBPYmplY3Qgb2Yga2V5LXZhbHVlIHBhaXJzIHRvIGFkZCBhcyBwcm9wZXJ0aWVzXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIE9wdGlvbmFsIFBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gW29wdGlvbnMuYmJveF0gQm91bmRpbmcgQm94IEFycmF5IFt3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGhdIGFzc29jaWF0ZWQgd2l0aCB0aGUgRmVhdHVyZVxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBbb3B0aW9ucy5pZF0gSWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVcbiAqIEByZXR1cm5zIHtGZWF0dXJlPE11bHRpUG9seWdvbj59IGEgbXVsdGlwb2x5Z29uIGZlYXR1cmVcbiAqIEB0aHJvd3Mge0Vycm9yfSBpZiBubyBjb29yZGluYXRlcyBhcmUgcGFzc2VkXG4gKiBAZXhhbXBsZVxuICogdmFyIG11bHRpUG9seSA9IHR1cmYubXVsdGlQb2x5Z29uKFtbW1swLDBdLFswLDEwXSxbMTAsMTBdLFsxMCwwXSxbMCwwXV1dXSk7XG4gKlxuICogLy89bXVsdGlQb2x5XG4gKlxuICovXG5mdW5jdGlvbiBtdWx0aVBvbHlnb24oY29vcmRpbmF0ZXMsIHByb3BlcnRpZXMsIG9wdGlvbnMpIHtcbiAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgIHZhciBnZW9tID0ge1xuICAgICAgICB0eXBlOiBcIk11bHRpUG9seWdvblwiLFxuICAgICAgICBjb29yZGluYXRlczogY29vcmRpbmF0ZXMsXG4gICAgfTtcbiAgICByZXR1cm4gZmVhdHVyZShnZW9tLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbn1cbmV4cG9ydHMubXVsdGlQb2x5Z29uID0gbXVsdGlQb2x5Z29uO1xuLyoqXG4gKiBDcmVhdGVzIGEge0BsaW5rIEZlYXR1cmU8R2VvbWV0cnlDb2xsZWN0aW9uPn0gYmFzZWQgb24gYVxuICogY29vcmRpbmF0ZSBhcnJheS4gUHJvcGVydGllcyBjYW4gYmUgYWRkZWQgb3B0aW9uYWxseS5cbiAqXG4gKiBAbmFtZSBnZW9tZXRyeUNvbGxlY3Rpb25cbiAqIEBwYXJhbSB7QXJyYXk8R2VvbWV0cnk+fSBnZW9tZXRyaWVzIGFuIGFycmF5IG9mIEdlb0pTT04gR2VvbWV0cmllc1xuICogQHBhcmFtIHtPYmplY3R9IFtwcm9wZXJ0aWVzPXt9XSBhbiBPYmplY3Qgb2Yga2V5LXZhbHVlIHBhaXJzIHRvIGFkZCBhcyBwcm9wZXJ0aWVzXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIE9wdGlvbmFsIFBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gW29wdGlvbnMuYmJveF0gQm91bmRpbmcgQm94IEFycmF5IFt3ZXN0LCBzb3V0aCwgZWFzdCwgbm9ydGhdIGFzc29jaWF0ZWQgd2l0aCB0aGUgRmVhdHVyZVxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBbb3B0aW9ucy5pZF0gSWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggdGhlIEZlYXR1cmVcbiAqIEByZXR1cm5zIHtGZWF0dXJlPEdlb21ldHJ5Q29sbGVjdGlvbj59IGEgR2VvSlNPTiBHZW9tZXRyeUNvbGxlY3Rpb24gRmVhdHVyZVxuICogQGV4YW1wbGVcbiAqIHZhciBwdCA9IHR1cmYuZ2VvbWV0cnkoXCJQb2ludFwiLCBbMTAwLCAwXSk7XG4gKiB2YXIgbGluZSA9IHR1cmYuZ2VvbWV0cnkoXCJMaW5lU3RyaW5nXCIsIFtbMTAxLCAwXSwgWzEwMiwgMV1dKTtcbiAqIHZhciBjb2xsZWN0aW9uID0gdHVyZi5nZW9tZXRyeUNvbGxlY3Rpb24oW3B0LCBsaW5lXSk7XG4gKlxuICogLy8gPT4gY29sbGVjdGlvblxuICovXG5mdW5jdGlvbiBnZW9tZXRyeUNvbGxlY3Rpb24oZ2VvbWV0cmllcywgcHJvcGVydGllcywgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zID09PSB2b2lkIDApIHsgb3B0aW9ucyA9IHt9OyB9XG4gICAgdmFyIGdlb20gPSB7XG4gICAgICAgIHR5cGU6IFwiR2VvbWV0cnlDb2xsZWN0aW9uXCIsXG4gICAgICAgIGdlb21ldHJpZXM6IGdlb21ldHJpZXMsXG4gICAgfTtcbiAgICByZXR1cm4gZmVhdHVyZShnZW9tLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbn1cbmV4cG9ydHMuZ2VvbWV0cnlDb2xsZWN0aW9uID0gZ2VvbWV0cnlDb2xsZWN0aW9uO1xuLyoqXG4gKiBSb3VuZCBudW1iZXIgdG8gcHJlY2lzaW9uXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IG51bSBOdW1iZXJcbiAqIEBwYXJhbSB7bnVtYmVyfSBbcHJlY2lzaW9uPTBdIFByZWNpc2lvblxuICogQHJldHVybnMge251bWJlcn0gcm91bmRlZCBudW1iZXJcbiAqIEBleGFtcGxlXG4gKiB0dXJmLnJvdW5kKDEyMC40MzIxKVxuICogLy89MTIwXG4gKlxuICogdHVyZi5yb3VuZCgxMjAuNDMyMSwgMilcbiAqIC8vPTEyMC40M1xuICovXG5mdW5jdGlvbiByb3VuZChudW0sIHByZWNpc2lvbikge1xuICAgIGlmIChwcmVjaXNpb24gPT09IHZvaWQgMCkgeyBwcmVjaXNpb24gPSAwOyB9XG4gICAgaWYgKHByZWNpc2lvbiAmJiAhKHByZWNpc2lvbiA+PSAwKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJwcmVjaXNpb24gbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlclwiKTtcbiAgICB9XG4gICAgdmFyIG11bHRpcGxpZXIgPSBNYXRoLnBvdygxMCwgcHJlY2lzaW9uIHx8IDApO1xuICAgIHJldHVybiBNYXRoLnJvdW5kKG51bSAqIG11bHRpcGxpZXIpIC8gbXVsdGlwbGllcjtcbn1cbmV4cG9ydHMucm91bmQgPSByb3VuZDtcbi8qKlxuICogQ29udmVydCBhIGRpc3RhbmNlIG1lYXN1cmVtZW50IChhc3N1bWluZyBhIHNwaGVyaWNhbCBFYXJ0aCkgZnJvbSByYWRpYW5zIHRvIGEgbW9yZSBmcmllbmRseSB1bml0LlxuICogVmFsaWQgdW5pdHM6IG1pbGVzLCBuYXV0aWNhbG1pbGVzLCBpbmNoZXMsIHlhcmRzLCBtZXRlcnMsIG1ldHJlcywga2lsb21ldGVycywgY2VudGltZXRlcnMsIGZlZXRcbiAqXG4gKiBAbmFtZSByYWRpYW5zVG9MZW5ndGhcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWRpYW5zIGluIHJhZGlhbnMgYWNyb3NzIHRoZSBzcGhlcmVcbiAqIEBwYXJhbSB7c3RyaW5nfSBbdW5pdHM9XCJraWxvbWV0ZXJzXCJdIGNhbiBiZSBkZWdyZWVzLCByYWRpYW5zLCBtaWxlcywgb3Iga2lsb21ldGVycyBpbmNoZXMsIHlhcmRzLCBtZXRyZXMsXG4gKiBtZXRlcnMsIGtpbG9tZXRyZXMsIGtpbG9tZXRlcnMuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBkaXN0YW5jZVxuICovXG5mdW5jdGlvbiByYWRpYW5zVG9MZW5ndGgocmFkaWFucywgdW5pdHMpIHtcbiAgICBpZiAodW5pdHMgPT09IHZvaWQgMCkgeyB1bml0cyA9IFwia2lsb21ldGVyc1wiOyB9XG4gICAgdmFyIGZhY3RvciA9IGV4cG9ydHMuZmFjdG9yc1t1bml0c107XG4gICAgaWYgKCFmYWN0b3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHVuaXRzICsgXCIgdW5pdHMgaXMgaW52YWxpZFwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHJhZGlhbnMgKiBmYWN0b3I7XG59XG5leHBvcnRzLnJhZGlhbnNUb0xlbmd0aCA9IHJhZGlhbnNUb0xlbmd0aDtcbi8qKlxuICogQ29udmVydCBhIGRpc3RhbmNlIG1lYXN1cmVtZW50IChhc3N1bWluZyBhIHNwaGVyaWNhbCBFYXJ0aCkgZnJvbSBhIHJlYWwtd29ybGQgdW5pdCBpbnRvIHJhZGlhbnNcbiAqIFZhbGlkIHVuaXRzOiBtaWxlcywgbmF1dGljYWxtaWxlcywgaW5jaGVzLCB5YXJkcywgbWV0ZXJzLCBtZXRyZXMsIGtpbG9tZXRlcnMsIGNlbnRpbWV0ZXJzLCBmZWV0XG4gKlxuICogQG5hbWUgbGVuZ3RoVG9SYWRpYW5zXG4gKiBAcGFyYW0ge251bWJlcn0gZGlzdGFuY2UgaW4gcmVhbCB1bml0c1xuICogQHBhcmFtIHtzdHJpbmd9IFt1bml0cz1cImtpbG9tZXRlcnNcIl0gY2FuIGJlIGRlZ3JlZXMsIHJhZGlhbnMsIG1pbGVzLCBvciBraWxvbWV0ZXJzIGluY2hlcywgeWFyZHMsIG1ldHJlcyxcbiAqIG1ldGVycywga2lsb21ldHJlcywga2lsb21ldGVycy5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IHJhZGlhbnNcbiAqL1xuZnVuY3Rpb24gbGVuZ3RoVG9SYWRpYW5zKGRpc3RhbmNlLCB1bml0cykge1xuICAgIGlmICh1bml0cyA9PT0gdm9pZCAwKSB7IHVuaXRzID0gXCJraWxvbWV0ZXJzXCI7IH1cbiAgICB2YXIgZmFjdG9yID0gZXhwb3J0cy5mYWN0b3JzW3VuaXRzXTtcbiAgICBpZiAoIWZhY3Rvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IodW5pdHMgKyBcIiB1bml0cyBpcyBpbnZhbGlkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gZGlzdGFuY2UgLyBmYWN0b3I7XG59XG5leHBvcnRzLmxlbmd0aFRvUmFkaWFucyA9IGxlbmd0aFRvUmFkaWFucztcbi8qKlxuICogQ29udmVydCBhIGRpc3RhbmNlIG1lYXN1cmVtZW50IChhc3N1bWluZyBhIHNwaGVyaWNhbCBFYXJ0aCkgZnJvbSBhIHJlYWwtd29ybGQgdW5pdCBpbnRvIGRlZ3JlZXNcbiAqIFZhbGlkIHVuaXRzOiBtaWxlcywgbmF1dGljYWxtaWxlcywgaW5jaGVzLCB5YXJkcywgbWV0ZXJzLCBtZXRyZXMsIGNlbnRpbWV0ZXJzLCBraWxvbWV0cmVzLCBmZWV0XG4gKlxuICogQG5hbWUgbGVuZ3RoVG9EZWdyZWVzXG4gKiBAcGFyYW0ge251bWJlcn0gZGlzdGFuY2UgaW4gcmVhbCB1bml0c1xuICogQHBhcmFtIHtzdHJpbmd9IFt1bml0cz1cImtpbG9tZXRlcnNcIl0gY2FuIGJlIGRlZ3JlZXMsIHJhZGlhbnMsIG1pbGVzLCBvciBraWxvbWV0ZXJzIGluY2hlcywgeWFyZHMsIG1ldHJlcyxcbiAqIG1ldGVycywga2lsb21ldHJlcywga2lsb21ldGVycy5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IGRlZ3JlZXNcbiAqL1xuZnVuY3Rpb24gbGVuZ3RoVG9EZWdyZWVzKGRpc3RhbmNlLCB1bml0cykge1xuICAgIHJldHVybiByYWRpYW5zVG9EZWdyZWVzKGxlbmd0aFRvUmFkaWFucyhkaXN0YW5jZSwgdW5pdHMpKTtcbn1cbmV4cG9ydHMubGVuZ3RoVG9EZWdyZWVzID0gbGVuZ3RoVG9EZWdyZWVzO1xuLyoqXG4gKiBDb252ZXJ0cyBhbnkgYmVhcmluZyBhbmdsZSBmcm9tIHRoZSBub3J0aCBsaW5lIGRpcmVjdGlvbiAocG9zaXRpdmUgY2xvY2t3aXNlKVxuICogYW5kIHJldHVybnMgYW4gYW5nbGUgYmV0d2VlbiAwLTM2MCBkZWdyZWVzIChwb3NpdGl2ZSBjbG9ja3dpc2UpLCAwIGJlaW5nIHRoZSBub3J0aCBsaW5lXG4gKlxuICogQG5hbWUgYmVhcmluZ1RvQXppbXV0aFxuICogQHBhcmFtIHtudW1iZXJ9IGJlYXJpbmcgYW5nbGUsIGJldHdlZW4gLTE4MCBhbmQgKzE4MCBkZWdyZWVzXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBhbmdsZSBiZXR3ZWVuIDAgYW5kIDM2MCBkZWdyZWVzXG4gKi9cbmZ1bmN0aW9uIGJlYXJpbmdUb0F6aW11dGgoYmVhcmluZykge1xuICAgIHZhciBhbmdsZSA9IGJlYXJpbmcgJSAzNjA7XG4gICAgaWYgKGFuZ2xlIDwgMCkge1xuICAgICAgICBhbmdsZSArPSAzNjA7XG4gICAgfVxuICAgIHJldHVybiBhbmdsZTtcbn1cbmV4cG9ydHMuYmVhcmluZ1RvQXppbXV0aCA9IGJlYXJpbmdUb0F6aW11dGg7XG4vKipcbiAqIENvbnZlcnRzIGFuIGFuZ2xlIGluIHJhZGlhbnMgdG8gZGVncmVlc1xuICpcbiAqIEBuYW1lIHJhZGlhbnNUb0RlZ3JlZXNcbiAqIEBwYXJhbSB7bnVtYmVyfSByYWRpYW5zIGFuZ2xlIGluIHJhZGlhbnNcbiAqIEByZXR1cm5zIHtudW1iZXJ9IGRlZ3JlZXMgYmV0d2VlbiAwIGFuZCAzNjAgZGVncmVlc1xuICovXG5mdW5jdGlvbiByYWRpYW5zVG9EZWdyZWVzKHJhZGlhbnMpIHtcbiAgICB2YXIgZGVncmVlcyA9IHJhZGlhbnMgJSAoMiAqIE1hdGguUEkpO1xuICAgIHJldHVybiBkZWdyZWVzICogMTgwIC8gTWF0aC5QSTtcbn1cbmV4cG9ydHMucmFkaWFuc1RvRGVncmVlcyA9IHJhZGlhbnNUb0RlZ3JlZXM7XG4vKipcbiAqIENvbnZlcnRzIGFuIGFuZ2xlIGluIGRlZ3JlZXMgdG8gcmFkaWFuc1xuICpcbiAqIEBuYW1lIGRlZ3JlZXNUb1JhZGlhbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBkZWdyZWVzIGFuZ2xlIGJldHdlZW4gMCBhbmQgMzYwIGRlZ3JlZXNcbiAqIEByZXR1cm5zIHtudW1iZXJ9IGFuZ2xlIGluIHJhZGlhbnNcbiAqL1xuZnVuY3Rpb24gZGVncmVlc1RvUmFkaWFucyhkZWdyZWVzKSB7XG4gICAgdmFyIHJhZGlhbnMgPSBkZWdyZWVzICUgMzYwO1xuICAgIHJldHVybiByYWRpYW5zICogTWF0aC5QSSAvIDE4MDtcbn1cbmV4cG9ydHMuZGVncmVlc1RvUmFkaWFucyA9IGRlZ3JlZXNUb1JhZGlhbnM7XG4vKipcbiAqIENvbnZlcnRzIGEgbGVuZ3RoIHRvIHRoZSByZXF1ZXN0ZWQgdW5pdC5cbiAqIFZhbGlkIHVuaXRzOiBtaWxlcywgbmF1dGljYWxtaWxlcywgaW5jaGVzLCB5YXJkcywgbWV0ZXJzLCBtZXRyZXMsIGtpbG9tZXRlcnMsIGNlbnRpbWV0ZXJzLCBmZWV0XG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGxlbmd0aCB0byBiZSBjb252ZXJ0ZWRcbiAqIEBwYXJhbSB7VW5pdHN9IFtvcmlnaW5hbFVuaXQ9XCJraWxvbWV0ZXJzXCJdIG9mIHRoZSBsZW5ndGhcbiAqIEBwYXJhbSB7VW5pdHN9IFtmaW5hbFVuaXQ9XCJraWxvbWV0ZXJzXCJdIHJldHVybmVkIHVuaXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IHRoZSBjb252ZXJ0ZWQgbGVuZ3RoXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRMZW5ndGgobGVuZ3RoLCBvcmlnaW5hbFVuaXQsIGZpbmFsVW5pdCkge1xuICAgIGlmIChvcmlnaW5hbFVuaXQgPT09IHZvaWQgMCkgeyBvcmlnaW5hbFVuaXQgPSBcImtpbG9tZXRlcnNcIjsgfVxuICAgIGlmIChmaW5hbFVuaXQgPT09IHZvaWQgMCkgeyBmaW5hbFVuaXQgPSBcImtpbG9tZXRlcnNcIjsgfVxuICAgIGlmICghKGxlbmd0aCA+PSAwKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJsZW5ndGggbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlclwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHJhZGlhbnNUb0xlbmd0aChsZW5ndGhUb1JhZGlhbnMobGVuZ3RoLCBvcmlnaW5hbFVuaXQpLCBmaW5hbFVuaXQpO1xufVxuZXhwb3J0cy5jb252ZXJ0TGVuZ3RoID0gY29udmVydExlbmd0aDtcbi8qKlxuICogQ29udmVydHMgYSBhcmVhIHRvIHRoZSByZXF1ZXN0ZWQgdW5pdC5cbiAqIFZhbGlkIHVuaXRzOiBraWxvbWV0ZXJzLCBraWxvbWV0cmVzLCBtZXRlcnMsIG1ldHJlcywgY2VudGltZXRyZXMsIG1pbGxpbWV0ZXJzLCBhY3JlcywgbWlsZXMsIHlhcmRzLCBmZWV0LCBpbmNoZXNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhcmVhIHRvIGJlIGNvbnZlcnRlZFxuICogQHBhcmFtIHtVbml0c30gW29yaWdpbmFsVW5pdD1cIm1ldGVyc1wiXSBvZiB0aGUgZGlzdGFuY2VcbiAqIEBwYXJhbSB7VW5pdHN9IFtmaW5hbFVuaXQ9XCJraWxvbWV0ZXJzXCJdIHJldHVybmVkIHVuaXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IHRoZSBjb252ZXJ0ZWQgZGlzdGFuY2VcbiAqL1xuZnVuY3Rpb24gY29udmVydEFyZWEoYXJlYSwgb3JpZ2luYWxVbml0LCBmaW5hbFVuaXQpIHtcbiAgICBpZiAob3JpZ2luYWxVbml0ID09PSB2b2lkIDApIHsgb3JpZ2luYWxVbml0ID0gXCJtZXRlcnNcIjsgfVxuICAgIGlmIChmaW5hbFVuaXQgPT09IHZvaWQgMCkgeyBmaW5hbFVuaXQgPSBcImtpbG9tZXRlcnNcIjsgfVxuICAgIGlmICghKGFyZWEgPj0gMCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYXJlYSBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyXCIpO1xuICAgIH1cbiAgICB2YXIgc3RhcnRGYWN0b3IgPSBleHBvcnRzLmFyZWFGYWN0b3JzW29yaWdpbmFsVW5pdF07XG4gICAgaWYgKCFzdGFydEZhY3Rvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIG9yaWdpbmFsIHVuaXRzXCIpO1xuICAgIH1cbiAgICB2YXIgZmluYWxGYWN0b3IgPSBleHBvcnRzLmFyZWFGYWN0b3JzW2ZpbmFsVW5pdF07XG4gICAgaWYgKCFmaW5hbEZhY3Rvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIGZpbmFsIHVuaXRzXCIpO1xuICAgIH1cbiAgICByZXR1cm4gKGFyZWEgLyBzdGFydEZhY3RvcikgKiBmaW5hbEZhY3Rvcjtcbn1cbmV4cG9ydHMuY29udmVydEFyZWEgPSBjb252ZXJ0QXJlYTtcbi8qKlxuICogaXNOdW1iZXJcbiAqXG4gKiBAcGFyYW0geyp9IG51bSBOdW1iZXIgdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlL2ZhbHNlXG4gKiBAZXhhbXBsZVxuICogdHVyZi5pc051bWJlcigxMjMpXG4gKiAvLz10cnVlXG4gKiB0dXJmLmlzTnVtYmVyKCdmb28nKVxuICogLy89ZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNOdW1iZXIobnVtKSB7XG4gICAgcmV0dXJuICFpc05hTihudW0pICYmIG51bSAhPT0gbnVsbCAmJiAhQXJyYXkuaXNBcnJheShudW0pICYmICEvXlxccyokLy50ZXN0KG51bSk7XG59XG5leHBvcnRzLmlzTnVtYmVyID0gaXNOdW1iZXI7XG4vKipcbiAqIGlzT2JqZWN0XG4gKlxuICogQHBhcmFtIHsqfSBpbnB1dCB2YXJpYWJsZSB0byB2YWxpZGF0ZVxuICogQHJldHVybnMge2Jvb2xlYW59IHRydWUvZmFsc2VcbiAqIEBleGFtcGxlXG4gKiB0dXJmLmlzT2JqZWN0KHtlbGV2YXRpb246IDEwfSlcbiAqIC8vPXRydWVcbiAqIHR1cmYuaXNPYmplY3QoJ2ZvbycpXG4gKiAvLz1mYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdChpbnB1dCkge1xuICAgIHJldHVybiAoISFpbnB1dCkgJiYgKGlucHV0LmNvbnN0cnVjdG9yID09PSBPYmplY3QpO1xufVxuZXhwb3J0cy5pc09iamVjdCA9IGlzT2JqZWN0O1xuLyoqXG4gKiBWYWxpZGF0ZSBCQm94XG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gYmJveCBCQm94IHRvIHZhbGlkYXRlXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqIEB0aHJvd3MgRXJyb3IgaWYgQkJveCBpcyBub3QgdmFsaWRcbiAqIEBleGFtcGxlXG4gKiB2YWxpZGF0ZUJCb3goWy0xODAsIC00MCwgMTEwLCA1MF0pXG4gKiAvLz1PS1xuICogdmFsaWRhdGVCQm94KFstMTgwLCAtNDBdKVxuICogLy89RXJyb3JcbiAqIHZhbGlkYXRlQkJveCgnRm9vJylcbiAqIC8vPUVycm9yXG4gKiB2YWxpZGF0ZUJCb3goNSlcbiAqIC8vPUVycm9yXG4gKiB2YWxpZGF0ZUJCb3gobnVsbClcbiAqIC8vPUVycm9yXG4gKiB2YWxpZGF0ZUJCb3godW5kZWZpbmVkKVxuICogLy89RXJyb3JcbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVCQm94KGJib3gpIHtcbiAgICBpZiAoIWJib3gpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYmJveCBpcyByZXF1aXJlZFwiKTtcbiAgICB9XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGJib3gpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImJib3ggbXVzdCBiZSBhbiBBcnJheVwiKTtcbiAgICB9XG4gICAgaWYgKGJib3gubGVuZ3RoICE9PSA0ICYmIGJib3gubGVuZ3RoICE9PSA2KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImJib3ggbXVzdCBiZSBhbiBBcnJheSBvZiA0IG9yIDYgbnVtYmVyc1wiKTtcbiAgICB9XG4gICAgYmJveC5mb3JFYWNoKGZ1bmN0aW9uIChudW0pIHtcbiAgICAgICAgaWYgKCFpc051bWJlcihudW0pKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJiYm94IG11c3Qgb25seSBjb250YWluIG51bWJlcnNcIik7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cbmV4cG9ydHMudmFsaWRhdGVCQm94ID0gdmFsaWRhdGVCQm94O1xuLyoqXG4gKiBWYWxpZGF0ZSBJZFxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IGlkIElkIHRvIHZhbGlkYXRlXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqIEB0aHJvd3MgRXJyb3IgaWYgSWQgaXMgbm90IHZhbGlkXG4gKiBAZXhhbXBsZVxuICogdmFsaWRhdGVJZChbLTE4MCwgLTQwLCAxMTAsIDUwXSlcbiAqIC8vPUVycm9yXG4gKiB2YWxpZGF0ZUlkKFstMTgwLCAtNDBdKVxuICogLy89RXJyb3JcbiAqIHZhbGlkYXRlSWQoJ0ZvbycpXG4gKiAvLz1PS1xuICogdmFsaWRhdGVJZCg1KVxuICogLy89T0tcbiAqIHZhbGlkYXRlSWQobnVsbClcbiAqIC8vPUVycm9yXG4gKiB2YWxpZGF0ZUlkKHVuZGVmaW5lZClcbiAqIC8vPUVycm9yXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlSWQoaWQpIHtcbiAgICBpZiAoIWlkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImlkIGlzIHJlcXVpcmVkXCIpO1xuICAgIH1cbiAgICBpZiAoW1wic3RyaW5nXCIsIFwibnVtYmVyXCJdLmluZGV4T2YodHlwZW9mIGlkKSA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaWQgbXVzdCBiZSBhIG51bWJlciBvciBhIHN0cmluZ1wiKTtcbiAgICB9XG59XG5leHBvcnRzLnZhbGlkYXRlSWQgPSB2YWxpZGF0ZUlkO1xuLy8gRGVwcmVjYXRlZCBtZXRob2RzXG5mdW5jdGlvbiByYWRpYW5zMmRlZ3JlZXMoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwibWV0aG9kIGhhcyBiZWVuIHJlbmFtZWQgdG8gYHJhZGlhbnNUb0RlZ3JlZXNgXCIpO1xufVxuZXhwb3J0cy5yYWRpYW5zMmRlZ3JlZXMgPSByYWRpYW5zMmRlZ3JlZXM7XG5mdW5jdGlvbiBkZWdyZWVzMnJhZGlhbnMoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwibWV0aG9kIGhhcyBiZWVuIHJlbmFtZWQgdG8gYGRlZ3JlZXNUb1JhZGlhbnNgXCIpO1xufVxuZXhwb3J0cy5kZWdyZWVzMnJhZGlhbnMgPSBkZWdyZWVzMnJhZGlhbnM7XG5mdW5jdGlvbiBkaXN0YW5jZVRvRGVncmVlcygpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJtZXRob2QgaGFzIGJlZW4gcmVuYW1lZCB0byBgbGVuZ3RoVG9EZWdyZWVzYFwiKTtcbn1cbmV4cG9ydHMuZGlzdGFuY2VUb0RlZ3JlZXMgPSBkaXN0YW5jZVRvRGVncmVlcztcbmZ1bmN0aW9uIGRpc3RhbmNlVG9SYWRpYW5zKCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIm1ldGhvZCBoYXMgYmVlbiByZW5hbWVkIHRvIGBsZW5ndGhUb1JhZGlhbnNgXCIpO1xufVxuZXhwb3J0cy5kaXN0YW5jZVRvUmFkaWFucyA9IGRpc3RhbmNlVG9SYWRpYW5zO1xuZnVuY3Rpb24gcmFkaWFuc1RvRGlzdGFuY2UoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwibWV0aG9kIGhhcyBiZWVuIHJlbmFtZWQgdG8gYHJhZGlhbnNUb0xlbmd0aGBcIik7XG59XG5leHBvcnRzLnJhZGlhbnNUb0Rpc3RhbmNlID0gcmFkaWFuc1RvRGlzdGFuY2U7XG5mdW5jdGlvbiBiZWFyaW5nVG9BbmdsZSgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJtZXRob2QgaGFzIGJlZW4gcmVuYW1lZCB0byBgYmVhcmluZ1RvQXppbXV0aGBcIik7XG59XG5leHBvcnRzLmJlYXJpbmdUb0FuZ2xlID0gYmVhcmluZ1RvQW5nbGU7XG5mdW5jdGlvbiBjb252ZXJ0RGlzdGFuY2UoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwibWV0aG9kIGhhcyBiZWVuIHJlbmFtZWQgdG8gYGNvbnZlcnRMZW5ndGhgXCIpO1xufVxuZXhwb3J0cy5jb252ZXJ0RGlzdGFuY2UgPSBjb252ZXJ0RGlzdGFuY2U7XG5cbn0se31dLDU4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIGhlbHBlcnMgPSBfZGVyZXFfKCdAdHVyZi9oZWxwZXJzJyk7XG5cbi8qKlxuICogQ2FsbGJhY2sgZm9yIGNvb3JkRWFjaFxuICpcbiAqIEBjYWxsYmFjayBjb29yZEVhY2hDYWxsYmFja1xuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBjdXJyZW50Q29vcmQgVGhlIGN1cnJlbnQgY29vcmRpbmF0ZSBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gY29vcmRJbmRleCBUaGUgY3VycmVudCBpbmRleCBvZiB0aGUgY29vcmRpbmF0ZSBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gZmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBGZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtdWx0aUZlYXR1cmVJbmRleCBUaGUgY3VycmVudCBpbmRleCBvZiB0aGUgTXVsdGktRmVhdHVyZSBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gZ2VvbWV0cnlJbmRleCBUaGUgY3VycmVudCBpbmRleCBvZiB0aGUgR2VvbWV0cnkgYmVpbmcgcHJvY2Vzc2VkLlxuICovXG5cbi8qKlxuICogSXRlcmF0ZSBvdmVyIGNvb3JkaW5hdGVzIGluIGFueSBHZW9KU09OIG9iamVjdCwgc2ltaWxhciB0byBBcnJheS5mb3JFYWNoKClcbiAqXG4gKiBAbmFtZSBjb29yZEVhY2hcbiAqIEBwYXJhbSB7RmVhdHVyZUNvbGxlY3Rpb258RmVhdHVyZXxHZW9tZXRyeX0gZ2VvanNvbiBhbnkgR2VvSlNPTiBvYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGEgbWV0aG9kIHRoYXQgdGFrZXMgKGN1cnJlbnRDb29yZCwgY29vcmRJbmRleCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleClcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2V4Y2x1ZGVXcmFwQ29vcmQ9ZmFsc2VdIHdoZXRoZXIgb3Igbm90IHRvIGluY2x1ZGUgdGhlIGZpbmFsIGNvb3JkaW5hdGUgb2YgTGluZWFyUmluZ3MgdGhhdCB3cmFwcyB0aGUgcmluZyBpbiBpdHMgaXRlcmF0aW9uLlxuICogQHJldHVybnMge3ZvaWR9XG4gKiBAZXhhbXBsZVxuICogdmFyIGZlYXR1cmVzID0gdHVyZi5mZWF0dXJlQ29sbGVjdGlvbihbXG4gKiAgIHR1cmYucG9pbnQoWzI2LCAzN10sIHtcImZvb1wiOiBcImJhclwifSksXG4gKiAgIHR1cmYucG9pbnQoWzM2LCA1M10sIHtcImhlbGxvXCI6IFwid29ybGRcIn0pXG4gKiBdKTtcbiAqXG4gKiB0dXJmLmNvb3JkRWFjaChmZWF0dXJlcywgZnVuY3Rpb24gKGN1cnJlbnRDb29yZCwgY29vcmRJbmRleCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCkge1xuICogICAvLz1jdXJyZW50Q29vcmRcbiAqICAgLy89Y29vcmRJbmRleFxuICogICAvLz1mZWF0dXJlSW5kZXhcbiAqICAgLy89bXVsdGlGZWF0dXJlSW5kZXhcbiAqICAgLy89Z2VvbWV0cnlJbmRleFxuICogfSk7XG4gKi9cbmZ1bmN0aW9uIGNvb3JkRWFjaChnZW9qc29uLCBjYWxsYmFjaywgZXhjbHVkZVdyYXBDb29yZCkge1xuICAgIC8vIEhhbmRsZXMgbnVsbCBHZW9tZXRyeSAtLSBTa2lwcyB0aGlzIEdlb0pTT05cbiAgICBpZiAoZ2VvanNvbiA9PT0gbnVsbCkgcmV0dXJuO1xuICAgIHZhciBqLCBrLCBsLCBnZW9tZXRyeSwgc3RvcEcsIGNvb3JkcyxcbiAgICAgICAgZ2VvbWV0cnlNYXliZUNvbGxlY3Rpb24sXG4gICAgICAgIHdyYXBTaHJpbmsgPSAwLFxuICAgICAgICBjb29yZEluZGV4ID0gMCxcbiAgICAgICAgaXNHZW9tZXRyeUNvbGxlY3Rpb24sXG4gICAgICAgIHR5cGUgPSBnZW9qc29uLnR5cGUsXG4gICAgICAgIGlzRmVhdHVyZUNvbGxlY3Rpb24gPSB0eXBlID09PSAnRmVhdHVyZUNvbGxlY3Rpb24nLFxuICAgICAgICBpc0ZlYXR1cmUgPSB0eXBlID09PSAnRmVhdHVyZScsXG4gICAgICAgIHN0b3AgPSBpc0ZlYXR1cmVDb2xsZWN0aW9uID8gZ2VvanNvbi5mZWF0dXJlcy5sZW5ndGggOiAxO1xuXG4gICAgLy8gVGhpcyBsb2dpYyBtYXkgbG9vayBhIGxpdHRsZSB3ZWlyZC4gVGhlIHJlYXNvbiB3aHkgaXQgaXMgdGhhdCB3YXlcbiAgICAvLyBpcyBiZWNhdXNlIGl0J3MgdHJ5aW5nIHRvIGJlIGZhc3QuIEdlb0pTT04gc3VwcG9ydHMgbXVsdGlwbGUga2luZHNcbiAgICAvLyBvZiBvYmplY3RzIGF0IGl0cyByb290OiBGZWF0dXJlQ29sbGVjdGlvbiwgRmVhdHVyZXMsIEdlb21ldHJpZXMuXG4gICAgLy8gVGhpcyBmdW5jdGlvbiBoYXMgdGhlIHJlc3BvbnNpYmlsaXR5IG9mIGhhbmRsaW5nIGFsbCBvZiB0aGVtLCBhbmQgdGhhdFxuICAgIC8vIG1lYW5zIHRoYXQgc29tZSBvZiB0aGUgYGZvcmAgbG9vcHMgeW91IHNlZSBiZWxvdyBhY3R1YWxseSBqdXN0IGRvbid0IGFwcGx5XG4gICAgLy8gdG8gY2VydGFpbiBpbnB1dHMuIEZvciBpbnN0YW5jZSwgaWYgeW91IGdpdmUgdGhpcyBqdXN0IGFcbiAgICAvLyBQb2ludCBnZW9tZXRyeSwgdGhlbiBib3RoIGxvb3BzIGFyZSBzaG9ydC1jaXJjdWl0ZWQgYW5kIGFsbCB3ZSBkb1xuICAgIC8vIGlzIGdyYWR1YWxseSByZW5hbWUgdGhlIGlucHV0IHVudGlsIGl0J3MgY2FsbGVkICdnZW9tZXRyeScuXG4gICAgLy9cbiAgICAvLyBUaGlzIGFsc28gYWltcyB0byBhbGxvY2F0ZSBhcyBmZXcgcmVzb3VyY2VzIGFzIHBvc3NpYmxlOiBqdXN0IGFcbiAgICAvLyBmZXcgbnVtYmVycyBhbmQgYm9vbGVhbnMsIHJhdGhlciB0aGFuIGFueSB0ZW1wb3JhcnkgYXJyYXlzIGFzIHdvdWxkXG4gICAgLy8gYmUgcmVxdWlyZWQgd2l0aCB0aGUgbm9ybWFsaXphdGlvbiBhcHByb2FjaC5cbiAgICBmb3IgKHZhciBmZWF0dXJlSW5kZXggPSAwOyBmZWF0dXJlSW5kZXggPCBzdG9wOyBmZWF0dXJlSW5kZXgrKykge1xuICAgICAgICBnZW9tZXRyeU1heWJlQ29sbGVjdGlvbiA9IChpc0ZlYXR1cmVDb2xsZWN0aW9uID8gZ2VvanNvbi5mZWF0dXJlc1tmZWF0dXJlSW5kZXhdLmdlb21ldHJ5IDpcbiAgICAgICAgICAgIChpc0ZlYXR1cmUgPyBnZW9qc29uLmdlb21ldHJ5IDogZ2VvanNvbikpO1xuICAgICAgICBpc0dlb21ldHJ5Q29sbGVjdGlvbiA9IChnZW9tZXRyeU1heWJlQ29sbGVjdGlvbikgPyBnZW9tZXRyeU1heWJlQ29sbGVjdGlvbi50eXBlID09PSAnR2VvbWV0cnlDb2xsZWN0aW9uJyA6IGZhbHNlO1xuICAgICAgICBzdG9wRyA9IGlzR2VvbWV0cnlDb2xsZWN0aW9uID8gZ2VvbWV0cnlNYXliZUNvbGxlY3Rpb24uZ2VvbWV0cmllcy5sZW5ndGggOiAxO1xuXG4gICAgICAgIGZvciAodmFyIGdlb21JbmRleCA9IDA7IGdlb21JbmRleCA8IHN0b3BHOyBnZW9tSW5kZXgrKykge1xuICAgICAgICAgICAgdmFyIG11bHRpRmVhdHVyZUluZGV4ID0gMDtcbiAgICAgICAgICAgIHZhciBnZW9tZXRyeUluZGV4ID0gMDtcbiAgICAgICAgICAgIGdlb21ldHJ5ID0gaXNHZW9tZXRyeUNvbGxlY3Rpb24gP1xuICAgICAgICAgICAgICAgIGdlb21ldHJ5TWF5YmVDb2xsZWN0aW9uLmdlb21ldHJpZXNbZ2VvbUluZGV4XSA6IGdlb21ldHJ5TWF5YmVDb2xsZWN0aW9uO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGVzIG51bGwgR2VvbWV0cnkgLS0gU2tpcHMgdGhpcyBnZW9tZXRyeVxuICAgICAgICAgICAgaWYgKGdlb21ldHJ5ID09PSBudWxsKSBjb250aW51ZTtcbiAgICAgICAgICAgIGNvb3JkcyA9IGdlb21ldHJ5LmNvb3JkaW5hdGVzO1xuICAgICAgICAgICAgdmFyIGdlb21UeXBlID0gZ2VvbWV0cnkudHlwZTtcblxuICAgICAgICAgICAgd3JhcFNocmluayA9IChleGNsdWRlV3JhcENvb3JkICYmIChnZW9tVHlwZSA9PT0gJ1BvbHlnb24nIHx8IGdlb21UeXBlID09PSAnTXVsdGlQb2x5Z29uJykpID8gMSA6IDA7XG5cbiAgICAgICAgICAgIHN3aXRjaCAoZ2VvbVR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgbnVsbDpcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ1BvaW50JzpcbiAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2soY29vcmRzLCBjb29yZEluZGV4LCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4LCBnZW9tZXRyeUluZGV4KSA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICBjb29yZEluZGV4Kys7XG4gICAgICAgICAgICAgICAgbXVsdGlGZWF0dXJlSW5kZXgrKztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ0xpbmVTdHJpbmcnOlxuICAgICAgICAgICAgY2FzZSAnTXVsdGlQb2ludCc6XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGNvb3Jkcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2FsbGJhY2soY29vcmRzW2pdLCBjb29yZEluZGV4LCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4LCBnZW9tZXRyeUluZGV4KSA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgY29vcmRJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZ2VvbVR5cGUgPT09ICdNdWx0aVBvaW50JykgbXVsdGlGZWF0dXJlSW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGdlb21UeXBlID09PSAnTGluZVN0cmluZycpIG11bHRpRmVhdHVyZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdQb2x5Z29uJzpcbiAgICAgICAgICAgIGNhc2UgJ011bHRpTGluZVN0cmluZyc6XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGNvb3Jkcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGsgPSAwOyBrIDwgY29vcmRzW2pdLmxlbmd0aCAtIHdyYXBTaHJpbms7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrKGNvb3Jkc1tqXVtrXSwgY29vcmRJbmRleCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCkgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb29yZEluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGdlb21UeXBlID09PSAnTXVsdGlMaW5lU3RyaW5nJykgbXVsdGlGZWF0dXJlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdlb21UeXBlID09PSAnUG9seWdvbicpIGdlb21ldHJ5SW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGdlb21UeXBlID09PSAnUG9seWdvbicpIG11bHRpRmVhdHVyZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdNdWx0aVBvbHlnb24nOlxuICAgICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBjb29yZHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cnlJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoayA9IDA7IGsgPCBjb29yZHNbal0ubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobCA9IDA7IGwgPCBjb29yZHNbal1ba10ubGVuZ3RoIC0gd3JhcFNocmluazsgbCsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrKGNvb3Jkc1tqXVtrXVtsXSwgY29vcmRJbmRleCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCkgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29vcmRJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cnlJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG11bHRpRmVhdHVyZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnR2VvbWV0cnlDb2xsZWN0aW9uJzpcbiAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgZ2VvbWV0cnkuZ2VvbWV0cmllcy5sZW5ndGg7IGorKylcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvb3JkRWFjaChnZW9tZXRyeS5nZW9tZXRyaWVzW2pdLCBjYWxsYmFjaywgZXhjbHVkZVdyYXBDb29yZCkgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBHZW9tZXRyeSBUeXBlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgZm9yIGNvb3JkUmVkdWNlXG4gKlxuICogVGhlIGZpcnN0IHRpbWUgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGlzIGNhbGxlZCwgdGhlIHZhbHVlcyBwcm92aWRlZCBhcyBhcmd1bWVudHMgZGVwZW5kXG4gKiBvbiB3aGV0aGVyIHRoZSByZWR1Y2UgbWV0aG9kIGhhcyBhbiBpbml0aWFsVmFsdWUgYXJndW1lbnQuXG4gKlxuICogSWYgYW4gaW5pdGlhbFZhbHVlIGlzIHByb3ZpZGVkIHRvIHRoZSByZWR1Y2UgbWV0aG9kOlxuICogIC0gVGhlIHByZXZpb3VzVmFsdWUgYXJndW1lbnQgaXMgaW5pdGlhbFZhbHVlLlxuICogIC0gVGhlIGN1cnJlbnRWYWx1ZSBhcmd1bWVudCBpcyB0aGUgdmFsdWUgb2YgdGhlIGZpcnN0IGVsZW1lbnQgcHJlc2VudCBpbiB0aGUgYXJyYXkuXG4gKlxuICogSWYgYW4gaW5pdGlhbFZhbHVlIGlzIG5vdCBwcm92aWRlZDpcbiAqICAtIFRoZSBwcmV2aW91c1ZhbHVlIGFyZ3VtZW50IGlzIHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqICAtIFRoZSBjdXJyZW50VmFsdWUgYXJndW1lbnQgaXMgdGhlIHZhbHVlIG9mIHRoZSBzZWNvbmQgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqXG4gKiBAY2FsbGJhY2sgY29vcmRSZWR1Y2VDYWxsYmFja1xuICogQHBhcmFtIHsqfSBwcmV2aW91c1ZhbHVlIFRoZSBhY2N1bXVsYXRlZCB2YWx1ZSBwcmV2aW91c2x5IHJldHVybmVkIGluIHRoZSBsYXN0IGludm9jYXRpb25cbiAqIG9mIHRoZSBjYWxsYmFjaywgb3IgaW5pdGlhbFZhbHVlLCBpZiBzdXBwbGllZC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gY3VycmVudENvb3JkIFRoZSBjdXJyZW50IGNvb3JkaW5hdGUgYmVpbmcgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtudW1iZXJ9IGNvb3JkSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIGNvb3JkaW5hdGUgYmVpbmcgcHJvY2Vzc2VkLlxuICogU3RhcnRzIGF0IGluZGV4IDAsIGlmIGFuIGluaXRpYWxWYWx1ZSBpcyBwcm92aWRlZCwgYW5kIGF0IGluZGV4IDEgb3RoZXJ3aXNlLlxuICogQHBhcmFtIHtudW1iZXJ9IGZlYXR1cmVJbmRleCBUaGUgY3VycmVudCBpbmRleCBvZiB0aGUgRmVhdHVyZSBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gbXVsdGlGZWF0dXJlSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIE11bHRpLUZlYXR1cmUgYmVpbmcgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtudW1iZXJ9IGdlb21ldHJ5SW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIEdlb21ldHJ5IGJlaW5nIHByb2Nlc3NlZC5cbiAqL1xuXG4vKipcbiAqIFJlZHVjZSBjb29yZGluYXRlcyBpbiBhbnkgR2VvSlNPTiBvYmplY3QsIHNpbWlsYXIgdG8gQXJyYXkucmVkdWNlKClcbiAqXG4gKiBAbmFtZSBjb29yZFJlZHVjZVxuICogQHBhcmFtIHtGZWF0dXJlQ29sbGVjdGlvbnxHZW9tZXRyeXxGZWF0dXJlfSBnZW9qc29uIGFueSBHZW9KU09OIG9iamVjdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgYSBtZXRob2QgdGhhdCB0YWtlcyAocHJldmlvdXNWYWx1ZSwgY3VycmVudENvb3JkLCBjb29yZEluZGV4KVxuICogQHBhcmFtIHsqfSBbaW5pdGlhbFZhbHVlXSBWYWx1ZSB0byB1c2UgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHRvIHRoZSBmaXJzdCBjYWxsIG9mIHRoZSBjYWxsYmFjay5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2V4Y2x1ZGVXcmFwQ29vcmQ9ZmFsc2VdIHdoZXRoZXIgb3Igbm90IHRvIGluY2x1ZGUgdGhlIGZpbmFsIGNvb3JkaW5hdGUgb2YgTGluZWFyUmluZ3MgdGhhdCB3cmFwcyB0aGUgcmluZyBpbiBpdHMgaXRlcmF0aW9uLlxuICogQHJldHVybnMgeyp9IFRoZSB2YWx1ZSB0aGF0IHJlc3VsdHMgZnJvbSB0aGUgcmVkdWN0aW9uLlxuICogQGV4YW1wbGVcbiAqIHZhciBmZWF0dXJlcyA9IHR1cmYuZmVhdHVyZUNvbGxlY3Rpb24oW1xuICogICB0dXJmLnBvaW50KFsyNiwgMzddLCB7XCJmb29cIjogXCJiYXJcIn0pLFxuICogICB0dXJmLnBvaW50KFszNiwgNTNdLCB7XCJoZWxsb1wiOiBcIndvcmxkXCJ9KVxuICogXSk7XG4gKlxuICogdHVyZi5jb29yZFJlZHVjZShmZWF0dXJlcywgZnVuY3Rpb24gKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRDb29yZCwgY29vcmRJbmRleCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCkge1xuICogICAvLz1wcmV2aW91c1ZhbHVlXG4gKiAgIC8vPWN1cnJlbnRDb29yZFxuICogICAvLz1jb29yZEluZGV4XG4gKiAgIC8vPWZlYXR1cmVJbmRleFxuICogICAvLz1tdWx0aUZlYXR1cmVJbmRleFxuICogICAvLz1nZW9tZXRyeUluZGV4XG4gKiAgIHJldHVybiBjdXJyZW50Q29vcmQ7XG4gKiB9KTtcbiAqL1xuZnVuY3Rpb24gY29vcmRSZWR1Y2UoZ2VvanNvbiwgY2FsbGJhY2ssIGluaXRpYWxWYWx1ZSwgZXhjbHVkZVdyYXBDb29yZCkge1xuICAgIHZhciBwcmV2aW91c1ZhbHVlID0gaW5pdGlhbFZhbHVlO1xuICAgIGNvb3JkRWFjaChnZW9qc29uLCBmdW5jdGlvbiAoY3VycmVudENvb3JkLCBjb29yZEluZGV4LCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4LCBnZW9tZXRyeUluZGV4KSB7XG4gICAgICAgIGlmIChjb29yZEluZGV4ID09PSAwICYmIGluaXRpYWxWYWx1ZSA9PT0gdW5kZWZpbmVkKSBwcmV2aW91c1ZhbHVlID0gY3VycmVudENvb3JkO1xuICAgICAgICBlbHNlIHByZXZpb3VzVmFsdWUgPSBjYWxsYmFjayhwcmV2aW91c1ZhbHVlLCBjdXJyZW50Q29vcmQsIGNvb3JkSW5kZXgsIGZlYXR1cmVJbmRleCwgbXVsdGlGZWF0dXJlSW5kZXgsIGdlb21ldHJ5SW5kZXgpO1xuICAgIH0sIGV4Y2x1ZGVXcmFwQ29vcmQpO1xuICAgIHJldHVybiBwcmV2aW91c1ZhbHVlO1xufVxuXG4vKipcbiAqIENhbGxiYWNrIGZvciBwcm9wRWFjaFxuICpcbiAqIEBjYWxsYmFjayBwcm9wRWFjaENhbGxiYWNrXG4gKiBAcGFyYW0ge09iamVjdH0gY3VycmVudFByb3BlcnRpZXMgVGhlIGN1cnJlbnQgUHJvcGVydGllcyBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gZmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBGZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqL1xuXG4vKipcbiAqIEl0ZXJhdGUgb3ZlciBwcm9wZXJ0aWVzIGluIGFueSBHZW9KU09OIG9iamVjdCwgc2ltaWxhciB0byBBcnJheS5mb3JFYWNoKClcbiAqXG4gKiBAbmFtZSBwcm9wRWFjaFxuICogQHBhcmFtIHtGZWF0dXJlQ29sbGVjdGlvbnxGZWF0dXJlfSBnZW9qc29uIGFueSBHZW9KU09OIG9iamVjdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgYSBtZXRob2QgdGhhdCB0YWtlcyAoY3VycmVudFByb3BlcnRpZXMsIGZlYXR1cmVJbmRleClcbiAqIEByZXR1cm5zIHt2b2lkfVxuICogQGV4YW1wbGVcbiAqIHZhciBmZWF0dXJlcyA9IHR1cmYuZmVhdHVyZUNvbGxlY3Rpb24oW1xuICogICAgIHR1cmYucG9pbnQoWzI2LCAzN10sIHtmb286ICdiYXInfSksXG4gKiAgICAgdHVyZi5wb2ludChbMzYsIDUzXSwge2hlbGxvOiAnd29ybGQnfSlcbiAqIF0pO1xuICpcbiAqIHR1cmYucHJvcEVhY2goZmVhdHVyZXMsIGZ1bmN0aW9uIChjdXJyZW50UHJvcGVydGllcywgZmVhdHVyZUluZGV4KSB7XG4gKiAgIC8vPWN1cnJlbnRQcm9wZXJ0aWVzXG4gKiAgIC8vPWZlYXR1cmVJbmRleFxuICogfSk7XG4gKi9cbmZ1bmN0aW9uIHByb3BFYWNoKGdlb2pzb24sIGNhbGxiYWNrKSB7XG4gICAgdmFyIGk7XG4gICAgc3dpdGNoIChnZW9qc29uLnR5cGUpIHtcbiAgICBjYXNlICdGZWF0dXJlQ29sbGVjdGlvbic6XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBnZW9qc29uLmZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2soZ2VvanNvbi5mZWF0dXJlc1tpXS5wcm9wZXJ0aWVzLCBpKSA9PT0gZmFsc2UpIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ0ZlYXR1cmUnOlxuICAgICAgICBjYWxsYmFjayhnZW9qc29uLnByb3BlcnRpZXMsIDApO1xuICAgICAgICBicmVhaztcbiAgICB9XG59XG5cblxuLyoqXG4gKiBDYWxsYmFjayBmb3IgcHJvcFJlZHVjZVxuICpcbiAqIFRoZSBmaXJzdCB0aW1lIHRoZSBjYWxsYmFjayBmdW5jdGlvbiBpcyBjYWxsZWQsIHRoZSB2YWx1ZXMgcHJvdmlkZWQgYXMgYXJndW1lbnRzIGRlcGVuZFxuICogb24gd2hldGhlciB0aGUgcmVkdWNlIG1ldGhvZCBoYXMgYW4gaW5pdGlhbFZhbHVlIGFyZ3VtZW50LlxuICpcbiAqIElmIGFuIGluaXRpYWxWYWx1ZSBpcyBwcm92aWRlZCB0byB0aGUgcmVkdWNlIG1ldGhvZDpcbiAqICAtIFRoZSBwcmV2aW91c1ZhbHVlIGFyZ3VtZW50IGlzIGluaXRpYWxWYWx1ZS5cbiAqICAtIFRoZSBjdXJyZW50VmFsdWUgYXJndW1lbnQgaXMgdGhlIHZhbHVlIG9mIHRoZSBmaXJzdCBlbGVtZW50IHByZXNlbnQgaW4gdGhlIGFycmF5LlxuICpcbiAqIElmIGFuIGluaXRpYWxWYWx1ZSBpcyBub3QgcHJvdmlkZWQ6XG4gKiAgLSBUaGUgcHJldmlvdXNWYWx1ZSBhcmd1bWVudCBpcyB0aGUgdmFsdWUgb2YgdGhlIGZpcnN0IGVsZW1lbnQgcHJlc2VudCBpbiB0aGUgYXJyYXkuXG4gKiAgLSBUaGUgY3VycmVudFZhbHVlIGFyZ3VtZW50IGlzIHRoZSB2YWx1ZSBvZiB0aGUgc2Vjb25kIGVsZW1lbnQgcHJlc2VudCBpbiB0aGUgYXJyYXkuXG4gKlxuICogQGNhbGxiYWNrIHByb3BSZWR1Y2VDYWxsYmFja1xuICogQHBhcmFtIHsqfSBwcmV2aW91c1ZhbHVlIFRoZSBhY2N1bXVsYXRlZCB2YWx1ZSBwcmV2aW91c2x5IHJldHVybmVkIGluIHRoZSBsYXN0IGludm9jYXRpb25cbiAqIG9mIHRoZSBjYWxsYmFjaywgb3IgaW5pdGlhbFZhbHVlLCBpZiBzdXBwbGllZC5cbiAqIEBwYXJhbSB7Kn0gY3VycmVudFByb3BlcnRpZXMgVGhlIGN1cnJlbnQgUHJvcGVydGllcyBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gZmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBGZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqL1xuXG4vKipcbiAqIFJlZHVjZSBwcm9wZXJ0aWVzIGluIGFueSBHZW9KU09OIG9iamVjdCBpbnRvIGEgc2luZ2xlIHZhbHVlLFxuICogc2ltaWxhciB0byBob3cgQXJyYXkucmVkdWNlIHdvcmtzLiBIb3dldmVyLCBpbiB0aGlzIGNhc2Ugd2UgbGF6aWx5IHJ1blxuICogdGhlIHJlZHVjdGlvbiwgc28gYW4gYXJyYXkgb2YgYWxsIHByb3BlcnRpZXMgaXMgdW5uZWNlc3NhcnkuXG4gKlxuICogQG5hbWUgcHJvcFJlZHVjZVxuICogQHBhcmFtIHtGZWF0dXJlQ29sbGVjdGlvbnxGZWF0dXJlfSBnZW9qc29uIGFueSBHZW9KU09OIG9iamVjdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgYSBtZXRob2QgdGhhdCB0YWtlcyAocHJldmlvdXNWYWx1ZSwgY3VycmVudFByb3BlcnRpZXMsIGZlYXR1cmVJbmRleClcbiAqIEBwYXJhbSB7Kn0gW2luaXRpYWxWYWx1ZV0gVmFsdWUgdG8gdXNlIGFzIHRoZSBmaXJzdCBhcmd1bWVudCB0byB0aGUgZmlyc3QgY2FsbCBvZiB0aGUgY2FsbGJhY2suXG4gKiBAcmV0dXJucyB7Kn0gVGhlIHZhbHVlIHRoYXQgcmVzdWx0cyBmcm9tIHRoZSByZWR1Y3Rpb24uXG4gKiBAZXhhbXBsZVxuICogdmFyIGZlYXR1cmVzID0gdHVyZi5mZWF0dXJlQ29sbGVjdGlvbihbXG4gKiAgICAgdHVyZi5wb2ludChbMjYsIDM3XSwge2ZvbzogJ2Jhcid9KSxcbiAqICAgICB0dXJmLnBvaW50KFszNiwgNTNdLCB7aGVsbG86ICd3b3JsZCd9KVxuICogXSk7XG4gKlxuICogdHVyZi5wcm9wUmVkdWNlKGZlYXR1cmVzLCBmdW5jdGlvbiAocHJldmlvdXNWYWx1ZSwgY3VycmVudFByb3BlcnRpZXMsIGZlYXR1cmVJbmRleCkge1xuICogICAvLz1wcmV2aW91c1ZhbHVlXG4gKiAgIC8vPWN1cnJlbnRQcm9wZXJ0aWVzXG4gKiAgIC8vPWZlYXR1cmVJbmRleFxuICogICByZXR1cm4gY3VycmVudFByb3BlcnRpZXNcbiAqIH0pO1xuICovXG5mdW5jdGlvbiBwcm9wUmVkdWNlKGdlb2pzb24sIGNhbGxiYWNrLCBpbml0aWFsVmFsdWUpIHtcbiAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IGluaXRpYWxWYWx1ZTtcbiAgICBwcm9wRWFjaChnZW9qc29uLCBmdW5jdGlvbiAoY3VycmVudFByb3BlcnRpZXMsIGZlYXR1cmVJbmRleCkge1xuICAgICAgICBpZiAoZmVhdHVyZUluZGV4ID09PSAwICYmIGluaXRpYWxWYWx1ZSA9PT0gdW5kZWZpbmVkKSBwcmV2aW91c1ZhbHVlID0gY3VycmVudFByb3BlcnRpZXM7XG4gICAgICAgIGVsc2UgcHJldmlvdXNWYWx1ZSA9IGNhbGxiYWNrKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRQcm9wZXJ0aWVzLCBmZWF0dXJlSW5kZXgpO1xuICAgIH0pO1xuICAgIHJldHVybiBwcmV2aW91c1ZhbHVlO1xufVxuXG4vKipcbiAqIENhbGxiYWNrIGZvciBmZWF0dXJlRWFjaFxuICpcbiAqIEBjYWxsYmFjayBmZWF0dXJlRWFjaENhbGxiYWNrXG4gKiBAcGFyYW0ge0ZlYXR1cmU8YW55Pn0gY3VycmVudEZlYXR1cmUgVGhlIGN1cnJlbnQgRmVhdHVyZSBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gZmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBGZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqL1xuXG4vKipcbiAqIEl0ZXJhdGUgb3ZlciBmZWF0dXJlcyBpbiBhbnkgR2VvSlNPTiBvYmplY3QsIHNpbWlsYXIgdG9cbiAqIEFycmF5LmZvckVhY2guXG4gKlxuICogQG5hbWUgZmVhdHVyZUVhY2hcbiAqIEBwYXJhbSB7RmVhdHVyZUNvbGxlY3Rpb258RmVhdHVyZXxHZW9tZXRyeX0gZ2VvanNvbiBhbnkgR2VvSlNPTiBvYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGEgbWV0aG9kIHRoYXQgdGFrZXMgKGN1cnJlbnRGZWF0dXJlLCBmZWF0dXJlSW5kZXgpXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqIEBleGFtcGxlXG4gKiB2YXIgZmVhdHVyZXMgPSB0dXJmLmZlYXR1cmVDb2xsZWN0aW9uKFtcbiAqICAgdHVyZi5wb2ludChbMjYsIDM3XSwge2ZvbzogJ2Jhcid9KSxcbiAqICAgdHVyZi5wb2ludChbMzYsIDUzXSwge2hlbGxvOiAnd29ybGQnfSlcbiAqIF0pO1xuICpcbiAqIHR1cmYuZmVhdHVyZUVhY2goZmVhdHVyZXMsIGZ1bmN0aW9uIChjdXJyZW50RmVhdHVyZSwgZmVhdHVyZUluZGV4KSB7XG4gKiAgIC8vPWN1cnJlbnRGZWF0dXJlXG4gKiAgIC8vPWZlYXR1cmVJbmRleFxuICogfSk7XG4gKi9cbmZ1bmN0aW9uIGZlYXR1cmVFYWNoKGdlb2pzb24sIGNhbGxiYWNrKSB7XG4gICAgaWYgKGdlb2pzb24udHlwZSA9PT0gJ0ZlYXR1cmUnKSB7XG4gICAgICAgIGNhbGxiYWNrKGdlb2pzb24sIDApO1xuICAgIH0gZWxzZSBpZiAoZ2VvanNvbi50eXBlID09PSAnRmVhdHVyZUNvbGxlY3Rpb24nKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZ2VvanNvbi5mZWF0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKGdlb2pzb24uZmVhdHVyZXNbaV0sIGkpID09PSBmYWxzZSkgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgZm9yIGZlYXR1cmVSZWR1Y2VcbiAqXG4gKiBUaGUgZmlyc3QgdGltZSB0aGUgY2FsbGJhY2sgZnVuY3Rpb24gaXMgY2FsbGVkLCB0aGUgdmFsdWVzIHByb3ZpZGVkIGFzIGFyZ3VtZW50cyBkZXBlbmRcbiAqIG9uIHdoZXRoZXIgdGhlIHJlZHVjZSBtZXRob2QgaGFzIGFuIGluaXRpYWxWYWx1ZSBhcmd1bWVudC5cbiAqXG4gKiBJZiBhbiBpbml0aWFsVmFsdWUgaXMgcHJvdmlkZWQgdG8gdGhlIHJlZHVjZSBtZXRob2Q6XG4gKiAgLSBUaGUgcHJldmlvdXNWYWx1ZSBhcmd1bWVudCBpcyBpbml0aWFsVmFsdWUuXG4gKiAgLSBUaGUgY3VycmVudFZhbHVlIGFyZ3VtZW50IGlzIHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqXG4gKiBJZiBhbiBpbml0aWFsVmFsdWUgaXMgbm90IHByb3ZpZGVkOlxuICogIC0gVGhlIHByZXZpb3VzVmFsdWUgYXJndW1lbnQgaXMgdGhlIHZhbHVlIG9mIHRoZSBmaXJzdCBlbGVtZW50IHByZXNlbnQgaW4gdGhlIGFycmF5LlxuICogIC0gVGhlIGN1cnJlbnRWYWx1ZSBhcmd1bWVudCBpcyB0aGUgdmFsdWUgb2YgdGhlIHNlY29uZCBlbGVtZW50IHByZXNlbnQgaW4gdGhlIGFycmF5LlxuICpcbiAqIEBjYWxsYmFjayBmZWF0dXJlUmVkdWNlQ2FsbGJhY2tcbiAqIEBwYXJhbSB7Kn0gcHJldmlvdXNWYWx1ZSBUaGUgYWNjdW11bGF0ZWQgdmFsdWUgcHJldmlvdXNseSByZXR1cm5lZCBpbiB0aGUgbGFzdCBpbnZvY2F0aW9uXG4gKiBvZiB0aGUgY2FsbGJhY2ssIG9yIGluaXRpYWxWYWx1ZSwgaWYgc3VwcGxpZWQuXG4gKiBAcGFyYW0ge0ZlYXR1cmV9IGN1cnJlbnRGZWF0dXJlIFRoZSBjdXJyZW50IEZlYXR1cmUgYmVpbmcgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtudW1iZXJ9IGZlYXR1cmVJbmRleCBUaGUgY3VycmVudCBpbmRleCBvZiB0aGUgRmVhdHVyZSBiZWluZyBwcm9jZXNzZWQuXG4gKi9cblxuLyoqXG4gKiBSZWR1Y2UgZmVhdHVyZXMgaW4gYW55IEdlb0pTT04gb2JqZWN0LCBzaW1pbGFyIHRvIEFycmF5LnJlZHVjZSgpLlxuICpcbiAqIEBuYW1lIGZlYXR1cmVSZWR1Y2VcbiAqIEBwYXJhbSB7RmVhdHVyZUNvbGxlY3Rpb258RmVhdHVyZXxHZW9tZXRyeX0gZ2VvanNvbiBhbnkgR2VvSlNPTiBvYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGEgbWV0aG9kIHRoYXQgdGFrZXMgKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRGZWF0dXJlLCBmZWF0dXJlSW5kZXgpXG4gKiBAcGFyYW0geyp9IFtpbml0aWFsVmFsdWVdIFZhbHVlIHRvIHVzZSBhcyB0aGUgZmlyc3QgYXJndW1lbnQgdG8gdGhlIGZpcnN0IGNhbGwgb2YgdGhlIGNhbGxiYWNrLlxuICogQHJldHVybnMgeyp9IFRoZSB2YWx1ZSB0aGF0IHJlc3VsdHMgZnJvbSB0aGUgcmVkdWN0aW9uLlxuICogQGV4YW1wbGVcbiAqIHZhciBmZWF0dXJlcyA9IHR1cmYuZmVhdHVyZUNvbGxlY3Rpb24oW1xuICogICB0dXJmLnBvaW50KFsyNiwgMzddLCB7XCJmb29cIjogXCJiYXJcIn0pLFxuICogICB0dXJmLnBvaW50KFszNiwgNTNdLCB7XCJoZWxsb1wiOiBcIndvcmxkXCJ9KVxuICogXSk7XG4gKlxuICogdHVyZi5mZWF0dXJlUmVkdWNlKGZlYXR1cmVzLCBmdW5jdGlvbiAocHJldmlvdXNWYWx1ZSwgY3VycmVudEZlYXR1cmUsIGZlYXR1cmVJbmRleCkge1xuICogICAvLz1wcmV2aW91c1ZhbHVlXG4gKiAgIC8vPWN1cnJlbnRGZWF0dXJlXG4gKiAgIC8vPWZlYXR1cmVJbmRleFxuICogICByZXR1cm4gY3VycmVudEZlYXR1cmVcbiAqIH0pO1xuICovXG5mdW5jdGlvbiBmZWF0dXJlUmVkdWNlKGdlb2pzb24sIGNhbGxiYWNrLCBpbml0aWFsVmFsdWUpIHtcbiAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IGluaXRpYWxWYWx1ZTtcbiAgICBmZWF0dXJlRWFjaChnZW9qc29uLCBmdW5jdGlvbiAoY3VycmVudEZlYXR1cmUsIGZlYXR1cmVJbmRleCkge1xuICAgICAgICBpZiAoZmVhdHVyZUluZGV4ID09PSAwICYmIGluaXRpYWxWYWx1ZSA9PT0gdW5kZWZpbmVkKSBwcmV2aW91c1ZhbHVlID0gY3VycmVudEZlYXR1cmU7XG4gICAgICAgIGVsc2UgcHJldmlvdXNWYWx1ZSA9IGNhbGxiYWNrKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRGZWF0dXJlLCBmZWF0dXJlSW5kZXgpO1xuICAgIH0pO1xuICAgIHJldHVybiBwcmV2aW91c1ZhbHVlO1xufVxuXG4vKipcbiAqIEdldCBhbGwgY29vcmRpbmF0ZXMgZnJvbSBhbnkgR2VvSlNPTiBvYmplY3QuXG4gKlxuICogQG5hbWUgY29vcmRBbGxcbiAqIEBwYXJhbSB7RmVhdHVyZUNvbGxlY3Rpb258RmVhdHVyZXxHZW9tZXRyeX0gZ2VvanNvbiBhbnkgR2VvSlNPTiBvYmplY3RcbiAqIEByZXR1cm5zIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gY29vcmRpbmF0ZSBwb3NpdGlvbiBhcnJheVxuICogQGV4YW1wbGVcbiAqIHZhciBmZWF0dXJlcyA9IHR1cmYuZmVhdHVyZUNvbGxlY3Rpb24oW1xuICogICB0dXJmLnBvaW50KFsyNiwgMzddLCB7Zm9vOiAnYmFyJ30pLFxuICogICB0dXJmLnBvaW50KFszNiwgNTNdLCB7aGVsbG86ICd3b3JsZCd9KVxuICogXSk7XG4gKlxuICogdmFyIGNvb3JkcyA9IHR1cmYuY29vcmRBbGwoZmVhdHVyZXMpO1xuICogLy89IFtbMjYsIDM3XSwgWzM2LCA1M11dXG4gKi9cbmZ1bmN0aW9uIGNvb3JkQWxsKGdlb2pzb24pIHtcbiAgICB2YXIgY29vcmRzID0gW107XG4gICAgY29vcmRFYWNoKGdlb2pzb24sIGZ1bmN0aW9uIChjb29yZCkge1xuICAgICAgICBjb29yZHMucHVzaChjb29yZCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGNvb3Jkcztcbn1cblxuLyoqXG4gKiBDYWxsYmFjayBmb3IgZ2VvbUVhY2hcbiAqXG4gKiBAY2FsbGJhY2sgZ2VvbUVhY2hDYWxsYmFja1xuICogQHBhcmFtIHtHZW9tZXRyeX0gY3VycmVudEdlb21ldHJ5IFRoZSBjdXJyZW50IEdlb21ldHJ5IGJlaW5nIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBmZWF0dXJlSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIEZlYXR1cmUgYmVpbmcgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtPYmplY3R9IGZlYXR1cmVQcm9wZXJ0aWVzIFRoZSBjdXJyZW50IEZlYXR1cmUgUHJvcGVydGllcyBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZlYXR1cmVCQm94IFRoZSBjdXJyZW50IEZlYXR1cmUgQkJveCBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IGZlYXR1cmVJZCBUaGUgY3VycmVudCBGZWF0dXJlIElkIGJlaW5nIHByb2Nlc3NlZC5cbiAqL1xuXG4vKipcbiAqIEl0ZXJhdGUgb3ZlciBlYWNoIGdlb21ldHJ5IGluIGFueSBHZW9KU09OIG9iamVjdCwgc2ltaWxhciB0byBBcnJheS5mb3JFYWNoKClcbiAqXG4gKiBAbmFtZSBnZW9tRWFjaFxuICogQHBhcmFtIHtGZWF0dXJlQ29sbGVjdGlvbnxGZWF0dXJlfEdlb21ldHJ5fSBnZW9qc29uIGFueSBHZW9KU09OIG9iamVjdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgYSBtZXRob2QgdGhhdCB0YWtlcyAoY3VycmVudEdlb21ldHJ5LCBmZWF0dXJlSW5kZXgsIGZlYXR1cmVQcm9wZXJ0aWVzLCBmZWF0dXJlQkJveCwgZmVhdHVyZUlkKVxuICogQHJldHVybnMge3ZvaWR9XG4gKiBAZXhhbXBsZVxuICogdmFyIGZlYXR1cmVzID0gdHVyZi5mZWF0dXJlQ29sbGVjdGlvbihbXG4gKiAgICAgdHVyZi5wb2ludChbMjYsIDM3XSwge2ZvbzogJ2Jhcid9KSxcbiAqICAgICB0dXJmLnBvaW50KFszNiwgNTNdLCB7aGVsbG86ICd3b3JsZCd9KVxuICogXSk7XG4gKlxuICogdHVyZi5nZW9tRWFjaChmZWF0dXJlcywgZnVuY3Rpb24gKGN1cnJlbnRHZW9tZXRyeSwgZmVhdHVyZUluZGV4LCBmZWF0dXJlUHJvcGVydGllcywgZmVhdHVyZUJCb3gsIGZlYXR1cmVJZCkge1xuICogICAvLz1jdXJyZW50R2VvbWV0cnlcbiAqICAgLy89ZmVhdHVyZUluZGV4XG4gKiAgIC8vPWZlYXR1cmVQcm9wZXJ0aWVzXG4gKiAgIC8vPWZlYXR1cmVCQm94XG4gKiAgIC8vPWZlYXR1cmVJZFxuICogfSk7XG4gKi9cbmZ1bmN0aW9uIGdlb21FYWNoKGdlb2pzb24sIGNhbGxiYWNrKSB7XG4gICAgdmFyIGksIGosIGcsIGdlb21ldHJ5LCBzdG9wRyxcbiAgICAgICAgZ2VvbWV0cnlNYXliZUNvbGxlY3Rpb24sXG4gICAgICAgIGlzR2VvbWV0cnlDb2xsZWN0aW9uLFxuICAgICAgICBmZWF0dXJlUHJvcGVydGllcyxcbiAgICAgICAgZmVhdHVyZUJCb3gsXG4gICAgICAgIGZlYXR1cmVJZCxcbiAgICAgICAgZmVhdHVyZUluZGV4ID0gMCxcbiAgICAgICAgaXNGZWF0dXJlQ29sbGVjdGlvbiA9IGdlb2pzb24udHlwZSA9PT0gJ0ZlYXR1cmVDb2xsZWN0aW9uJyxcbiAgICAgICAgaXNGZWF0dXJlID0gZ2VvanNvbi50eXBlID09PSAnRmVhdHVyZScsXG4gICAgICAgIHN0b3AgPSBpc0ZlYXR1cmVDb2xsZWN0aW9uID8gZ2VvanNvbi5mZWF0dXJlcy5sZW5ndGggOiAxO1xuXG4gICAgLy8gVGhpcyBsb2dpYyBtYXkgbG9vayBhIGxpdHRsZSB3ZWlyZC4gVGhlIHJlYXNvbiB3aHkgaXQgaXMgdGhhdCB3YXlcbiAgICAvLyBpcyBiZWNhdXNlIGl0J3MgdHJ5aW5nIHRvIGJlIGZhc3QuIEdlb0pTT04gc3VwcG9ydHMgbXVsdGlwbGUga2luZHNcbiAgICAvLyBvZiBvYmplY3RzIGF0IGl0cyByb290OiBGZWF0dXJlQ29sbGVjdGlvbiwgRmVhdHVyZXMsIEdlb21ldHJpZXMuXG4gICAgLy8gVGhpcyBmdW5jdGlvbiBoYXMgdGhlIHJlc3BvbnNpYmlsaXR5IG9mIGhhbmRsaW5nIGFsbCBvZiB0aGVtLCBhbmQgdGhhdFxuICAgIC8vIG1lYW5zIHRoYXQgc29tZSBvZiB0aGUgYGZvcmAgbG9vcHMgeW91IHNlZSBiZWxvdyBhY3R1YWxseSBqdXN0IGRvbid0IGFwcGx5XG4gICAgLy8gdG8gY2VydGFpbiBpbnB1dHMuIEZvciBpbnN0YW5jZSwgaWYgeW91IGdpdmUgdGhpcyBqdXN0IGFcbiAgICAvLyBQb2ludCBnZW9tZXRyeSwgdGhlbiBib3RoIGxvb3BzIGFyZSBzaG9ydC1jaXJjdWl0ZWQgYW5kIGFsbCB3ZSBkb1xuICAgIC8vIGlzIGdyYWR1YWxseSByZW5hbWUgdGhlIGlucHV0IHVudGlsIGl0J3MgY2FsbGVkICdnZW9tZXRyeScuXG4gICAgLy9cbiAgICAvLyBUaGlzIGFsc28gYWltcyB0byBhbGxvY2F0ZSBhcyBmZXcgcmVzb3VyY2VzIGFzIHBvc3NpYmxlOiBqdXN0IGFcbiAgICAvLyBmZXcgbnVtYmVycyBhbmQgYm9vbGVhbnMsIHJhdGhlciB0aGFuIGFueSB0ZW1wb3JhcnkgYXJyYXlzIGFzIHdvdWxkXG4gICAgLy8gYmUgcmVxdWlyZWQgd2l0aCB0aGUgbm9ybWFsaXphdGlvbiBhcHByb2FjaC5cbiAgICBmb3IgKGkgPSAwOyBpIDwgc3RvcDsgaSsrKSB7XG5cbiAgICAgICAgZ2VvbWV0cnlNYXliZUNvbGxlY3Rpb24gPSAoaXNGZWF0dXJlQ29sbGVjdGlvbiA/IGdlb2pzb24uZmVhdHVyZXNbaV0uZ2VvbWV0cnkgOlxuICAgICAgICAgICAgKGlzRmVhdHVyZSA/IGdlb2pzb24uZ2VvbWV0cnkgOiBnZW9qc29uKSk7XG4gICAgICAgIGZlYXR1cmVQcm9wZXJ0aWVzID0gKGlzRmVhdHVyZUNvbGxlY3Rpb24gPyBnZW9qc29uLmZlYXR1cmVzW2ldLnByb3BlcnRpZXMgOlxuICAgICAgICAgICAgKGlzRmVhdHVyZSA/IGdlb2pzb24ucHJvcGVydGllcyA6IHt9KSk7XG4gICAgICAgIGZlYXR1cmVCQm94ID0gKGlzRmVhdHVyZUNvbGxlY3Rpb24gPyBnZW9qc29uLmZlYXR1cmVzW2ldLmJib3ggOlxuICAgICAgICAgICAgKGlzRmVhdHVyZSA/IGdlb2pzb24uYmJveCA6IHVuZGVmaW5lZCkpO1xuICAgICAgICBmZWF0dXJlSWQgPSAoaXNGZWF0dXJlQ29sbGVjdGlvbiA/IGdlb2pzb24uZmVhdHVyZXNbaV0uaWQgOlxuICAgICAgICAgICAgKGlzRmVhdHVyZSA/IGdlb2pzb24uaWQgOiB1bmRlZmluZWQpKTtcbiAgICAgICAgaXNHZW9tZXRyeUNvbGxlY3Rpb24gPSAoZ2VvbWV0cnlNYXliZUNvbGxlY3Rpb24pID8gZ2VvbWV0cnlNYXliZUNvbGxlY3Rpb24udHlwZSA9PT0gJ0dlb21ldHJ5Q29sbGVjdGlvbicgOiBmYWxzZTtcbiAgICAgICAgc3RvcEcgPSBpc0dlb21ldHJ5Q29sbGVjdGlvbiA/IGdlb21ldHJ5TWF5YmVDb2xsZWN0aW9uLmdlb21ldHJpZXMubGVuZ3RoIDogMTtcblxuICAgICAgICBmb3IgKGcgPSAwOyBnIDwgc3RvcEc7IGcrKykge1xuICAgICAgICAgICAgZ2VvbWV0cnkgPSBpc0dlb21ldHJ5Q29sbGVjdGlvbiA/XG4gICAgICAgICAgICAgICAgZ2VvbWV0cnlNYXliZUNvbGxlY3Rpb24uZ2VvbWV0cmllc1tnXSA6IGdlb21ldHJ5TWF5YmVDb2xsZWN0aW9uO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgbnVsbCBHZW9tZXRyeVxuICAgICAgICAgICAgaWYgKGdlb21ldHJ5ID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrKG51bGwsIGZlYXR1cmVJbmRleCwgZmVhdHVyZVByb3BlcnRpZXMsIGZlYXR1cmVCQm94LCBmZWF0dXJlSWQpID09PSBmYWxzZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3dpdGNoIChnZW9tZXRyeS50eXBlKSB7XG4gICAgICAgICAgICBjYXNlICdQb2ludCc6XG4gICAgICAgICAgICBjYXNlICdMaW5lU3RyaW5nJzpcbiAgICAgICAgICAgIGNhc2UgJ011bHRpUG9pbnQnOlxuICAgICAgICAgICAgY2FzZSAnUG9seWdvbic6XG4gICAgICAgICAgICBjYXNlICdNdWx0aUxpbmVTdHJpbmcnOlxuICAgICAgICAgICAgY2FzZSAnTXVsdGlQb2x5Z29uJzoge1xuICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjayhnZW9tZXRyeSwgZmVhdHVyZUluZGV4LCBmZWF0dXJlUHJvcGVydGllcywgZmVhdHVyZUJCb3gsIGZlYXR1cmVJZCkgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlICdHZW9tZXRyeUNvbGxlY3Rpb24nOiB7XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGdlb21ldHJ5Lmdlb21ldHJpZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrKGdlb21ldHJ5Lmdlb21ldHJpZXNbal0sIGZlYXR1cmVJbmRleCwgZmVhdHVyZVByb3BlcnRpZXMsIGZlYXR1cmVCQm94LCBmZWF0dXJlSWQpID09PSBmYWxzZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIEdlb21ldHJ5IFR5cGUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBPbmx5IGluY3JlYXNlIGBmZWF0dXJlSW5kZXhgIHBlciBlYWNoIGZlYXR1cmVcbiAgICAgICAgZmVhdHVyZUluZGV4Kys7XG4gICAgfVxufVxuXG4vKipcbiAqIENhbGxiYWNrIGZvciBnZW9tUmVkdWNlXG4gKlxuICogVGhlIGZpcnN0IHRpbWUgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGlzIGNhbGxlZCwgdGhlIHZhbHVlcyBwcm92aWRlZCBhcyBhcmd1bWVudHMgZGVwZW5kXG4gKiBvbiB3aGV0aGVyIHRoZSByZWR1Y2UgbWV0aG9kIGhhcyBhbiBpbml0aWFsVmFsdWUgYXJndW1lbnQuXG4gKlxuICogSWYgYW4gaW5pdGlhbFZhbHVlIGlzIHByb3ZpZGVkIHRvIHRoZSByZWR1Y2UgbWV0aG9kOlxuICogIC0gVGhlIHByZXZpb3VzVmFsdWUgYXJndW1lbnQgaXMgaW5pdGlhbFZhbHVlLlxuICogIC0gVGhlIGN1cnJlbnRWYWx1ZSBhcmd1bWVudCBpcyB0aGUgdmFsdWUgb2YgdGhlIGZpcnN0IGVsZW1lbnQgcHJlc2VudCBpbiB0aGUgYXJyYXkuXG4gKlxuICogSWYgYW4gaW5pdGlhbFZhbHVlIGlzIG5vdCBwcm92aWRlZDpcbiAqICAtIFRoZSBwcmV2aW91c1ZhbHVlIGFyZ3VtZW50IGlzIHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqICAtIFRoZSBjdXJyZW50VmFsdWUgYXJndW1lbnQgaXMgdGhlIHZhbHVlIG9mIHRoZSBzZWNvbmQgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqXG4gKiBAY2FsbGJhY2sgZ2VvbVJlZHVjZUNhbGxiYWNrXG4gKiBAcGFyYW0geyp9IHByZXZpb3VzVmFsdWUgVGhlIGFjY3VtdWxhdGVkIHZhbHVlIHByZXZpb3VzbHkgcmV0dXJuZWQgaW4gdGhlIGxhc3QgaW52b2NhdGlvblxuICogb2YgdGhlIGNhbGxiYWNrLCBvciBpbml0aWFsVmFsdWUsIGlmIHN1cHBsaWVkLlxuICogQHBhcmFtIHtHZW9tZXRyeX0gY3VycmVudEdlb21ldHJ5IFRoZSBjdXJyZW50IEdlb21ldHJ5IGJlaW5nIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBmZWF0dXJlSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIEZlYXR1cmUgYmVpbmcgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtPYmplY3R9IGZlYXR1cmVQcm9wZXJ0aWVzIFRoZSBjdXJyZW50IEZlYXR1cmUgUHJvcGVydGllcyBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZlYXR1cmVCQm94IFRoZSBjdXJyZW50IEZlYXR1cmUgQkJveCBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IGZlYXR1cmVJZCBUaGUgY3VycmVudCBGZWF0dXJlIElkIGJlaW5nIHByb2Nlc3NlZC5cbiAqL1xuXG4vKipcbiAqIFJlZHVjZSBnZW9tZXRyeSBpbiBhbnkgR2VvSlNPTiBvYmplY3QsIHNpbWlsYXIgdG8gQXJyYXkucmVkdWNlKCkuXG4gKlxuICogQG5hbWUgZ2VvbVJlZHVjZVxuICogQHBhcmFtIHtGZWF0dXJlQ29sbGVjdGlvbnxGZWF0dXJlfEdlb21ldHJ5fSBnZW9qc29uIGFueSBHZW9KU09OIG9iamVjdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgYSBtZXRob2QgdGhhdCB0YWtlcyAocHJldmlvdXNWYWx1ZSwgY3VycmVudEdlb21ldHJ5LCBmZWF0dXJlSW5kZXgsIGZlYXR1cmVQcm9wZXJ0aWVzLCBmZWF0dXJlQkJveCwgZmVhdHVyZUlkKVxuICogQHBhcmFtIHsqfSBbaW5pdGlhbFZhbHVlXSBWYWx1ZSB0byB1c2UgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHRvIHRoZSBmaXJzdCBjYWxsIG9mIHRoZSBjYWxsYmFjay5cbiAqIEByZXR1cm5zIHsqfSBUaGUgdmFsdWUgdGhhdCByZXN1bHRzIGZyb20gdGhlIHJlZHVjdGlvbi5cbiAqIEBleGFtcGxlXG4gKiB2YXIgZmVhdHVyZXMgPSB0dXJmLmZlYXR1cmVDb2xsZWN0aW9uKFtcbiAqICAgICB0dXJmLnBvaW50KFsyNiwgMzddLCB7Zm9vOiAnYmFyJ30pLFxuICogICAgIHR1cmYucG9pbnQoWzM2LCA1M10sIHtoZWxsbzogJ3dvcmxkJ30pXG4gKiBdKTtcbiAqXG4gKiB0dXJmLmdlb21SZWR1Y2UoZmVhdHVyZXMsIGZ1bmN0aW9uIChwcmV2aW91c1ZhbHVlLCBjdXJyZW50R2VvbWV0cnksIGZlYXR1cmVJbmRleCwgZmVhdHVyZVByb3BlcnRpZXMsIGZlYXR1cmVCQm94LCBmZWF0dXJlSWQpIHtcbiAqICAgLy89cHJldmlvdXNWYWx1ZVxuICogICAvLz1jdXJyZW50R2VvbWV0cnlcbiAqICAgLy89ZmVhdHVyZUluZGV4XG4gKiAgIC8vPWZlYXR1cmVQcm9wZXJ0aWVzXG4gKiAgIC8vPWZlYXR1cmVCQm94XG4gKiAgIC8vPWZlYXR1cmVJZFxuICogICByZXR1cm4gY3VycmVudEdlb21ldHJ5XG4gKiB9KTtcbiAqL1xuZnVuY3Rpb24gZ2VvbVJlZHVjZShnZW9qc29uLCBjYWxsYmFjaywgaW5pdGlhbFZhbHVlKSB7XG4gICAgdmFyIHByZXZpb3VzVmFsdWUgPSBpbml0aWFsVmFsdWU7XG4gICAgZ2VvbUVhY2goZ2VvanNvbiwgZnVuY3Rpb24gKGN1cnJlbnRHZW9tZXRyeSwgZmVhdHVyZUluZGV4LCBmZWF0dXJlUHJvcGVydGllcywgZmVhdHVyZUJCb3gsIGZlYXR1cmVJZCkge1xuICAgICAgICBpZiAoZmVhdHVyZUluZGV4ID09PSAwICYmIGluaXRpYWxWYWx1ZSA9PT0gdW5kZWZpbmVkKSBwcmV2aW91c1ZhbHVlID0gY3VycmVudEdlb21ldHJ5O1xuICAgICAgICBlbHNlIHByZXZpb3VzVmFsdWUgPSBjYWxsYmFjayhwcmV2aW91c1ZhbHVlLCBjdXJyZW50R2VvbWV0cnksIGZlYXR1cmVJbmRleCwgZmVhdHVyZVByb3BlcnRpZXMsIGZlYXR1cmVCQm94LCBmZWF0dXJlSWQpO1xuICAgIH0pO1xuICAgIHJldHVybiBwcmV2aW91c1ZhbHVlO1xufVxuXG4vKipcbiAqIENhbGxiYWNrIGZvciBmbGF0dGVuRWFjaFxuICpcbiAqIEBjYWxsYmFjayBmbGF0dGVuRWFjaENhbGxiYWNrXG4gKiBAcGFyYW0ge0ZlYXR1cmV9IGN1cnJlbnRGZWF0dXJlIFRoZSBjdXJyZW50IGZsYXR0ZW5lZCBmZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBmZWF0dXJlSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIEZlYXR1cmUgYmVpbmcgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtudW1iZXJ9IG11bHRpRmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBNdWx0aS1GZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqL1xuXG4vKipcbiAqIEl0ZXJhdGUgb3ZlciBmbGF0dGVuZWQgZmVhdHVyZXMgaW4gYW55IEdlb0pTT04gb2JqZWN0LCBzaW1pbGFyIHRvXG4gKiBBcnJheS5mb3JFYWNoLlxuICpcbiAqIEBuYW1lIGZsYXR0ZW5FYWNoXG4gKiBAcGFyYW0ge0ZlYXR1cmVDb2xsZWN0aW9ufEZlYXR1cmV8R2VvbWV0cnl9IGdlb2pzb24gYW55IEdlb0pTT04gb2JqZWN0XG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBhIG1ldGhvZCB0aGF0IHRha2VzIChjdXJyZW50RmVhdHVyZSwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleClcbiAqIEBleGFtcGxlXG4gKiB2YXIgZmVhdHVyZXMgPSB0dXJmLmZlYXR1cmVDb2xsZWN0aW9uKFtcbiAqICAgICB0dXJmLnBvaW50KFsyNiwgMzddLCB7Zm9vOiAnYmFyJ30pLFxuICogICAgIHR1cmYubXVsdGlQb2ludChbWzQwLCAzMF0sIFszNiwgNTNdXSwge2hlbGxvOiAnd29ybGQnfSlcbiAqIF0pO1xuICpcbiAqIHR1cmYuZmxhdHRlbkVhY2goZmVhdHVyZXMsIGZ1bmN0aW9uIChjdXJyZW50RmVhdHVyZSwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCkge1xuICogICAvLz1jdXJyZW50RmVhdHVyZVxuICogICAvLz1mZWF0dXJlSW5kZXhcbiAqICAgLy89bXVsdGlGZWF0dXJlSW5kZXhcbiAqIH0pO1xuICovXG5mdW5jdGlvbiBmbGF0dGVuRWFjaChnZW9qc29uLCBjYWxsYmFjaykge1xuICAgIGdlb21FYWNoKGdlb2pzb24sIGZ1bmN0aW9uIChnZW9tZXRyeSwgZmVhdHVyZUluZGV4LCBwcm9wZXJ0aWVzLCBiYm94LCBpZCkge1xuICAgICAgICAvLyBDYWxsYmFjayBmb3Igc2luZ2xlIGdlb21ldHJ5XG4gICAgICAgIHZhciB0eXBlID0gKGdlb21ldHJ5ID09PSBudWxsKSA/IG51bGwgOiBnZW9tZXRyeS50eXBlO1xuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSBudWxsOlxuICAgICAgICBjYXNlICdQb2ludCc6XG4gICAgICAgIGNhc2UgJ0xpbmVTdHJpbmcnOlxuICAgICAgICBjYXNlICdQb2x5Z29uJzpcbiAgICAgICAgICAgIGlmIChjYWxsYmFjayhoZWxwZXJzLmZlYXR1cmUoZ2VvbWV0cnksIHByb3BlcnRpZXMsIHtiYm94OiBiYm94LCBpZDogaWR9KSwgZmVhdHVyZUluZGV4LCAwKSA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBnZW9tVHlwZTtcblxuICAgICAgICAvLyBDYWxsYmFjayBmb3IgbXVsdGktZ2VvbWV0cnlcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgIGNhc2UgJ011bHRpUG9pbnQnOlxuICAgICAgICAgICAgZ2VvbVR5cGUgPSAnUG9pbnQnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ011bHRpTGluZVN0cmluZyc6XG4gICAgICAgICAgICBnZW9tVHlwZSA9ICdMaW5lU3RyaW5nJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdNdWx0aVBvbHlnb24nOlxuICAgICAgICAgICAgZ2VvbVR5cGUgPSAnUG9seWdvbic7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIG11bHRpRmVhdHVyZUluZGV4ID0gMDsgbXVsdGlGZWF0dXJlSW5kZXggPCBnZW9tZXRyeS5jb29yZGluYXRlcy5sZW5ndGg7IG11bHRpRmVhdHVyZUluZGV4KyspIHtcbiAgICAgICAgICAgIHZhciBjb29yZGluYXRlID0gZ2VvbWV0cnkuY29vcmRpbmF0ZXNbbXVsdGlGZWF0dXJlSW5kZXhdO1xuICAgICAgICAgICAgdmFyIGdlb20gPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogZ2VvbVR5cGUsXG4gICAgICAgICAgICAgICAgY29vcmRpbmF0ZXM6IGNvb3JkaW5hdGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2soaGVscGVycy5mZWF0dXJlKGdlb20sIHByb3BlcnRpZXMpLCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4KSA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIENhbGxiYWNrIGZvciBmbGF0dGVuUmVkdWNlXG4gKlxuICogVGhlIGZpcnN0IHRpbWUgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGlzIGNhbGxlZCwgdGhlIHZhbHVlcyBwcm92aWRlZCBhcyBhcmd1bWVudHMgZGVwZW5kXG4gKiBvbiB3aGV0aGVyIHRoZSByZWR1Y2UgbWV0aG9kIGhhcyBhbiBpbml0aWFsVmFsdWUgYXJndW1lbnQuXG4gKlxuICogSWYgYW4gaW5pdGlhbFZhbHVlIGlzIHByb3ZpZGVkIHRvIHRoZSByZWR1Y2UgbWV0aG9kOlxuICogIC0gVGhlIHByZXZpb3VzVmFsdWUgYXJndW1lbnQgaXMgaW5pdGlhbFZhbHVlLlxuICogIC0gVGhlIGN1cnJlbnRWYWx1ZSBhcmd1bWVudCBpcyB0aGUgdmFsdWUgb2YgdGhlIGZpcnN0IGVsZW1lbnQgcHJlc2VudCBpbiB0aGUgYXJyYXkuXG4gKlxuICogSWYgYW4gaW5pdGlhbFZhbHVlIGlzIG5vdCBwcm92aWRlZDpcbiAqICAtIFRoZSBwcmV2aW91c1ZhbHVlIGFyZ3VtZW50IGlzIHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqICAtIFRoZSBjdXJyZW50VmFsdWUgYXJndW1lbnQgaXMgdGhlIHZhbHVlIG9mIHRoZSBzZWNvbmQgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqXG4gKiBAY2FsbGJhY2sgZmxhdHRlblJlZHVjZUNhbGxiYWNrXG4gKiBAcGFyYW0geyp9IHByZXZpb3VzVmFsdWUgVGhlIGFjY3VtdWxhdGVkIHZhbHVlIHByZXZpb3VzbHkgcmV0dXJuZWQgaW4gdGhlIGxhc3QgaW52b2NhdGlvblxuICogb2YgdGhlIGNhbGxiYWNrLCBvciBpbml0aWFsVmFsdWUsIGlmIHN1cHBsaWVkLlxuICogQHBhcmFtIHtGZWF0dXJlfSBjdXJyZW50RmVhdHVyZSBUaGUgY3VycmVudCBGZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBmZWF0dXJlSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIEZlYXR1cmUgYmVpbmcgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtudW1iZXJ9IG11bHRpRmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBNdWx0aS1GZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqL1xuXG4vKipcbiAqIFJlZHVjZSBmbGF0dGVuZWQgZmVhdHVyZXMgaW4gYW55IEdlb0pTT04gb2JqZWN0LCBzaW1pbGFyIHRvIEFycmF5LnJlZHVjZSgpLlxuICpcbiAqIEBuYW1lIGZsYXR0ZW5SZWR1Y2VcbiAqIEBwYXJhbSB7RmVhdHVyZUNvbGxlY3Rpb258RmVhdHVyZXxHZW9tZXRyeX0gZ2VvanNvbiBhbnkgR2VvSlNPTiBvYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGEgbWV0aG9kIHRoYXQgdGFrZXMgKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRGZWF0dXJlLCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4KVxuICogQHBhcmFtIHsqfSBbaW5pdGlhbFZhbHVlXSBWYWx1ZSB0byB1c2UgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHRvIHRoZSBmaXJzdCBjYWxsIG9mIHRoZSBjYWxsYmFjay5cbiAqIEByZXR1cm5zIHsqfSBUaGUgdmFsdWUgdGhhdCByZXN1bHRzIGZyb20gdGhlIHJlZHVjdGlvbi5cbiAqIEBleGFtcGxlXG4gKiB2YXIgZmVhdHVyZXMgPSB0dXJmLmZlYXR1cmVDb2xsZWN0aW9uKFtcbiAqICAgICB0dXJmLnBvaW50KFsyNiwgMzddLCB7Zm9vOiAnYmFyJ30pLFxuICogICAgIHR1cmYubXVsdGlQb2ludChbWzQwLCAzMF0sIFszNiwgNTNdXSwge2hlbGxvOiAnd29ybGQnfSlcbiAqIF0pO1xuICpcbiAqIHR1cmYuZmxhdHRlblJlZHVjZShmZWF0dXJlcywgZnVuY3Rpb24gKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRGZWF0dXJlLCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4KSB7XG4gKiAgIC8vPXByZXZpb3VzVmFsdWVcbiAqICAgLy89Y3VycmVudEZlYXR1cmVcbiAqICAgLy89ZmVhdHVyZUluZGV4XG4gKiAgIC8vPW11bHRpRmVhdHVyZUluZGV4XG4gKiAgIHJldHVybiBjdXJyZW50RmVhdHVyZVxuICogfSk7XG4gKi9cbmZ1bmN0aW9uIGZsYXR0ZW5SZWR1Y2UoZ2VvanNvbiwgY2FsbGJhY2ssIGluaXRpYWxWYWx1ZSkge1xuICAgIHZhciBwcmV2aW91c1ZhbHVlID0gaW5pdGlhbFZhbHVlO1xuICAgIGZsYXR0ZW5FYWNoKGdlb2pzb24sIGZ1bmN0aW9uIChjdXJyZW50RmVhdHVyZSwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCkge1xuICAgICAgICBpZiAoZmVhdHVyZUluZGV4ID09PSAwICYmIG11bHRpRmVhdHVyZUluZGV4ID09PSAwICYmIGluaXRpYWxWYWx1ZSA9PT0gdW5kZWZpbmVkKSBwcmV2aW91c1ZhbHVlID0gY3VycmVudEZlYXR1cmU7XG4gICAgICAgIGVsc2UgcHJldmlvdXNWYWx1ZSA9IGNhbGxiYWNrKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRGZWF0dXJlLCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4KTtcbiAgICB9KTtcbiAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcbn1cblxuLyoqXG4gKiBDYWxsYmFjayBmb3Igc2VnbWVudEVhY2hcbiAqXG4gKiBAY2FsbGJhY2sgc2VnbWVudEVhY2hDYWxsYmFja1xuICogQHBhcmFtIHtGZWF0dXJlPExpbmVTdHJpbmc+fSBjdXJyZW50U2VnbWVudCBUaGUgY3VycmVudCBTZWdtZW50IGJlaW5nIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBmZWF0dXJlSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIEZlYXR1cmUgYmVpbmcgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtudW1iZXJ9IG11bHRpRmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBNdWx0aS1GZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBnZW9tZXRyeUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBHZW9tZXRyeSBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gc2VnbWVudEluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBTZWdtZW50IGJlaW5nIHByb2Nlc3NlZC5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5cbi8qKlxuICogSXRlcmF0ZSBvdmVyIDItdmVydGV4IGxpbmUgc2VnbWVudCBpbiBhbnkgR2VvSlNPTiBvYmplY3QsIHNpbWlsYXIgdG8gQXJyYXkuZm9yRWFjaCgpXG4gKiAoTXVsdGkpUG9pbnQgZ2VvbWV0cmllcyBkbyBub3QgY29udGFpbiBzZWdtZW50cyB0aGVyZWZvcmUgdGhleSBhcmUgaWdub3JlZCBkdXJpbmcgdGhpcyBvcGVyYXRpb24uXG4gKlxuICogQHBhcmFtIHtGZWF0dXJlQ29sbGVjdGlvbnxGZWF0dXJlfEdlb21ldHJ5fSBnZW9qc29uIGFueSBHZW9KU09OXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBhIG1ldGhvZCB0aGF0IHRha2VzIChjdXJyZW50U2VnbWVudCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCwgc2VnbWVudEluZGV4KVxuICogQHJldHVybnMge3ZvaWR9XG4gKiBAZXhhbXBsZVxuICogdmFyIHBvbHlnb24gPSB0dXJmLnBvbHlnb24oW1tbLTUwLCA1XSwgWy00MCwgLTEwXSwgWy01MCwgLTEwXSwgWy00MCwgNV0sIFstNTAsIDVdXV0pO1xuICpcbiAqIC8vIEl0ZXJhdGUgb3ZlciBHZW9KU09OIGJ5IDItdmVydGV4IHNlZ21lbnRzXG4gKiB0dXJmLnNlZ21lbnRFYWNoKHBvbHlnb24sIGZ1bmN0aW9uIChjdXJyZW50U2VnbWVudCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCwgc2VnbWVudEluZGV4KSB7XG4gKiAgIC8vPWN1cnJlbnRTZWdtZW50XG4gKiAgIC8vPWZlYXR1cmVJbmRleFxuICogICAvLz1tdWx0aUZlYXR1cmVJbmRleFxuICogICAvLz1nZW9tZXRyeUluZGV4XG4gKiAgIC8vPXNlZ21lbnRJbmRleFxuICogfSk7XG4gKlxuICogLy8gQ2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2Ygc2VnbWVudHNcbiAqIHZhciB0b3RhbCA9IDA7XG4gKiB0dXJmLnNlZ21lbnRFYWNoKHBvbHlnb24sIGZ1bmN0aW9uICgpIHtcbiAqICAgICB0b3RhbCsrO1xuICogfSk7XG4gKi9cbmZ1bmN0aW9uIHNlZ21lbnRFYWNoKGdlb2pzb24sIGNhbGxiYWNrKSB7XG4gICAgZmxhdHRlbkVhY2goZ2VvanNvbiwgZnVuY3Rpb24gKGZlYXR1cmUsIGZlYXR1cmVJbmRleCwgbXVsdGlGZWF0dXJlSW5kZXgpIHtcbiAgICAgICAgdmFyIHNlZ21lbnRJbmRleCA9IDA7XG5cbiAgICAgICAgLy8gRXhjbHVkZSBudWxsIEdlb21ldHJpZXNcbiAgICAgICAgaWYgKCFmZWF0dXJlLmdlb21ldHJ5KSByZXR1cm47XG4gICAgICAgIC8vIChNdWx0aSlQb2ludCBnZW9tZXRyaWVzIGRvIG5vdCBjb250YWluIHNlZ21lbnRzIHRoZXJlZm9yZSB0aGV5IGFyZSBpZ25vcmVkIGR1cmluZyB0aGlzIG9wZXJhdGlvbi5cbiAgICAgICAgdmFyIHR5cGUgPSBmZWF0dXJlLmdlb21ldHJ5LnR5cGU7XG4gICAgICAgIGlmICh0eXBlID09PSAnUG9pbnQnIHx8IHR5cGUgPT09ICdNdWx0aVBvaW50JykgcmV0dXJuO1xuXG4gICAgICAgIC8vIEdlbmVyYXRlIDItdmVydGV4IGxpbmUgc2VnbWVudHNcbiAgICAgICAgdmFyIHByZXZpb3VzQ29vcmRzO1xuICAgICAgICB2YXIgcHJldmlvdXNGZWF0dXJlSW5kZXggPSAwO1xuICAgICAgICB2YXIgcHJldmlvdXNNdWx0aUluZGV4ID0gMDtcbiAgICAgICAgdmFyIHByZXZHZW9tSW5kZXggPSAwO1xuICAgICAgICBpZiAoY29vcmRFYWNoKGZlYXR1cmUsIGZ1bmN0aW9uIChjdXJyZW50Q29vcmQsIGNvb3JkSW5kZXgsIGZlYXR1cmVJbmRleENvb3JkLCBtdWx0aVBhcnRJbmRleENvb3JkLCBnZW9tZXRyeUluZGV4KSB7XG4gICAgICAgICAgICAvLyBTaW11bGF0aW5nIGEgbWV0YS5jb29yZFJlZHVjZSgpIHNpbmNlIGByZWR1Y2VgIG9wZXJhdGlvbnMgY2Fubm90IGJlIHN0b3BwZWQgYnkgcmV0dXJuaW5nIGBmYWxzZWBcbiAgICAgICAgICAgIGlmIChwcmV2aW91c0Nvb3JkcyA9PT0gdW5kZWZpbmVkIHx8IGZlYXR1cmVJbmRleCA+IHByZXZpb3VzRmVhdHVyZUluZGV4IHx8IG11bHRpUGFydEluZGV4Q29vcmQgPiBwcmV2aW91c011bHRpSW5kZXggfHwgZ2VvbWV0cnlJbmRleCA+IHByZXZHZW9tSW5kZXgpIHtcbiAgICAgICAgICAgICAgICBwcmV2aW91c0Nvb3JkcyA9IGN1cnJlbnRDb29yZDtcbiAgICAgICAgICAgICAgICBwcmV2aW91c0ZlYXR1cmVJbmRleCA9IGZlYXR1cmVJbmRleDtcbiAgICAgICAgICAgICAgICBwcmV2aW91c011bHRpSW5kZXggPSBtdWx0aVBhcnRJbmRleENvb3JkO1xuICAgICAgICAgICAgICAgIHByZXZHZW9tSW5kZXggPSBnZW9tZXRyeUluZGV4O1xuICAgICAgICAgICAgICAgIHNlZ21lbnRJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGN1cnJlbnRTZWdtZW50ID0gaGVscGVycy5saW5lU3RyaW5nKFtwcmV2aW91c0Nvb3JkcywgY3VycmVudENvb3JkXSwgZmVhdHVyZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjayhjdXJyZW50U2VnbWVudCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCwgc2VnbWVudEluZGV4KSA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHNlZ21lbnRJbmRleCsrO1xuICAgICAgICAgICAgcHJldmlvdXNDb29yZHMgPSBjdXJyZW50Q29vcmQ7XG4gICAgICAgIH0pID09PSBmYWxzZSkgcmV0dXJuIGZhbHNlO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIENhbGxiYWNrIGZvciBzZWdtZW50UmVkdWNlXG4gKlxuICogVGhlIGZpcnN0IHRpbWUgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIGlzIGNhbGxlZCwgdGhlIHZhbHVlcyBwcm92aWRlZCBhcyBhcmd1bWVudHMgZGVwZW5kXG4gKiBvbiB3aGV0aGVyIHRoZSByZWR1Y2UgbWV0aG9kIGhhcyBhbiBpbml0aWFsVmFsdWUgYXJndW1lbnQuXG4gKlxuICogSWYgYW4gaW5pdGlhbFZhbHVlIGlzIHByb3ZpZGVkIHRvIHRoZSByZWR1Y2UgbWV0aG9kOlxuICogIC0gVGhlIHByZXZpb3VzVmFsdWUgYXJndW1lbnQgaXMgaW5pdGlhbFZhbHVlLlxuICogIC0gVGhlIGN1cnJlbnRWYWx1ZSBhcmd1bWVudCBpcyB0aGUgdmFsdWUgb2YgdGhlIGZpcnN0IGVsZW1lbnQgcHJlc2VudCBpbiB0aGUgYXJyYXkuXG4gKlxuICogSWYgYW4gaW5pdGlhbFZhbHVlIGlzIG5vdCBwcm92aWRlZDpcbiAqICAtIFRoZSBwcmV2aW91c1ZhbHVlIGFyZ3VtZW50IGlzIHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqICAtIFRoZSBjdXJyZW50VmFsdWUgYXJndW1lbnQgaXMgdGhlIHZhbHVlIG9mIHRoZSBzZWNvbmQgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqXG4gKiBAY2FsbGJhY2sgc2VnbWVudFJlZHVjZUNhbGxiYWNrXG4gKiBAcGFyYW0geyp9IHByZXZpb3VzVmFsdWUgVGhlIGFjY3VtdWxhdGVkIHZhbHVlIHByZXZpb3VzbHkgcmV0dXJuZWQgaW4gdGhlIGxhc3QgaW52b2NhdGlvblxuICogb2YgdGhlIGNhbGxiYWNrLCBvciBpbml0aWFsVmFsdWUsIGlmIHN1cHBsaWVkLlxuICogQHBhcmFtIHtGZWF0dXJlPExpbmVTdHJpbmc+fSBjdXJyZW50U2VnbWVudCBUaGUgY3VycmVudCBTZWdtZW50IGJlaW5nIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBmZWF0dXJlSW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIEZlYXR1cmUgYmVpbmcgcHJvY2Vzc2VkLlxuICogQHBhcmFtIHtudW1iZXJ9IG11bHRpRmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBNdWx0aS1GZWF0dXJlIGJlaW5nIHByb2Nlc3NlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBnZW9tZXRyeUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBHZW9tZXRyeSBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gc2VnbWVudEluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBTZWdtZW50IGJlaW5nIHByb2Nlc3NlZC5cbiAqL1xuXG4vKipcbiAqIFJlZHVjZSAyLXZlcnRleCBsaW5lIHNlZ21lbnQgaW4gYW55IEdlb0pTT04gb2JqZWN0LCBzaW1pbGFyIHRvIEFycmF5LnJlZHVjZSgpXG4gKiAoTXVsdGkpUG9pbnQgZ2VvbWV0cmllcyBkbyBub3QgY29udGFpbiBzZWdtZW50cyB0aGVyZWZvcmUgdGhleSBhcmUgaWdub3JlZCBkdXJpbmcgdGhpcyBvcGVyYXRpb24uXG4gKlxuICogQHBhcmFtIHtGZWF0dXJlQ29sbGVjdGlvbnxGZWF0dXJlfEdlb21ldHJ5fSBnZW9qc29uIGFueSBHZW9KU09OXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBhIG1ldGhvZCB0aGF0IHRha2VzIChwcmV2aW91c1ZhbHVlLCBjdXJyZW50U2VnbWVudCwgY3VycmVudEluZGV4KVxuICogQHBhcmFtIHsqfSBbaW5pdGlhbFZhbHVlXSBWYWx1ZSB0byB1c2UgYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHRvIHRoZSBmaXJzdCBjYWxsIG9mIHRoZSBjYWxsYmFjay5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICogQGV4YW1wbGVcbiAqIHZhciBwb2x5Z29uID0gdHVyZi5wb2x5Z29uKFtbWy01MCwgNV0sIFstNDAsIC0xMF0sIFstNTAsIC0xMF0sIFstNDAsIDVdLCBbLTUwLCA1XV1dKTtcbiAqXG4gKiAvLyBJdGVyYXRlIG92ZXIgR2VvSlNPTiBieSAyLXZlcnRleCBzZWdtZW50c1xuICogdHVyZi5zZWdtZW50UmVkdWNlKHBvbHlnb24sIGZ1bmN0aW9uIChwcmV2aW91c1NlZ21lbnQsIGN1cnJlbnRTZWdtZW50LCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4LCBnZW9tZXRyeUluZGV4LCBzZWdtZW50SW5kZXgpIHtcbiAqICAgLy89IHByZXZpb3VzU2VnbWVudFxuICogICAvLz0gY3VycmVudFNlZ21lbnRcbiAqICAgLy89IGZlYXR1cmVJbmRleFxuICogICAvLz0gbXVsdGlGZWF0dXJlSW5kZXhcbiAqICAgLy89IGdlb21ldHJ5SW5kZXhcbiAqICAgLy89IHNlZ21lbnRJbmV4XG4gKiAgIHJldHVybiBjdXJyZW50U2VnbWVudFxuICogfSk7XG4gKlxuICogLy8gQ2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2Ygc2VnbWVudHNcbiAqIHZhciBpbml0aWFsVmFsdWUgPSAwXG4gKiB2YXIgdG90YWwgPSB0dXJmLnNlZ21lbnRSZWR1Y2UocG9seWdvbiwgZnVuY3Rpb24gKHByZXZpb3VzVmFsdWUpIHtcbiAqICAgICBwcmV2aW91c1ZhbHVlKys7XG4gKiAgICAgcmV0dXJuIHByZXZpb3VzVmFsdWU7XG4gKiB9LCBpbml0aWFsVmFsdWUpO1xuICovXG5mdW5jdGlvbiBzZWdtZW50UmVkdWNlKGdlb2pzb24sIGNhbGxiYWNrLCBpbml0aWFsVmFsdWUpIHtcbiAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IGluaXRpYWxWYWx1ZTtcbiAgICB2YXIgc3RhcnRlZCA9IGZhbHNlO1xuICAgIHNlZ21lbnRFYWNoKGdlb2pzb24sIGZ1bmN0aW9uIChjdXJyZW50U2VnbWVudCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCwgc2VnbWVudEluZGV4KSB7XG4gICAgICAgIGlmIChzdGFydGVkID09PSBmYWxzZSAmJiBpbml0aWFsVmFsdWUgPT09IHVuZGVmaW5lZCkgcHJldmlvdXNWYWx1ZSA9IGN1cnJlbnRTZWdtZW50O1xuICAgICAgICBlbHNlIHByZXZpb3VzVmFsdWUgPSBjYWxsYmFjayhwcmV2aW91c1ZhbHVlLCBjdXJyZW50U2VnbWVudCwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCwgc2VnbWVudEluZGV4KTtcbiAgICAgICAgc3RhcnRlZCA9IHRydWU7XG4gICAgfSk7XG4gICAgcmV0dXJuIHByZXZpb3VzVmFsdWU7XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgZm9yIGxpbmVFYWNoXG4gKlxuICogQGNhbGxiYWNrIGxpbmVFYWNoQ2FsbGJhY2tcbiAqIEBwYXJhbSB7RmVhdHVyZTxMaW5lU3RyaW5nPn0gY3VycmVudExpbmUgVGhlIGN1cnJlbnQgTGluZVN0cmluZ3xMaW5lYXJSaW5nIGJlaW5nIHByb2Nlc3NlZFxuICogQHBhcmFtIHtudW1iZXJ9IGZlYXR1cmVJbmRleCBUaGUgY3VycmVudCBpbmRleCBvZiB0aGUgRmVhdHVyZSBiZWluZyBwcm9jZXNzZWRcbiAqIEBwYXJhbSB7bnVtYmVyfSBtdWx0aUZlYXR1cmVJbmRleCBUaGUgY3VycmVudCBpbmRleCBvZiB0aGUgTXVsdGktRmVhdHVyZSBiZWluZyBwcm9jZXNzZWRcbiAqIEBwYXJhbSB7bnVtYmVyfSBnZW9tZXRyeUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBHZW9tZXRyeSBiZWluZyBwcm9jZXNzZWRcbiAqL1xuXG4vKipcbiAqIEl0ZXJhdGUgb3ZlciBsaW5lIG9yIHJpbmcgY29vcmRpbmF0ZXMgaW4gTGluZVN0cmluZywgUG9seWdvbiwgTXVsdGlMaW5lU3RyaW5nLCBNdWx0aVBvbHlnb24gRmVhdHVyZXMgb3IgR2VvbWV0cmllcyxcbiAqIHNpbWlsYXIgdG8gQXJyYXkuZm9yRWFjaC5cbiAqXG4gKiBAbmFtZSBsaW5lRWFjaFxuICogQHBhcmFtIHtHZW9tZXRyeXxGZWF0dXJlPExpbmVTdHJpbmd8UG9seWdvbnxNdWx0aUxpbmVTdHJpbmd8TXVsdGlQb2x5Z29uPn0gZ2VvanNvbiBvYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIGEgbWV0aG9kIHRoYXQgdGFrZXMgKGN1cnJlbnRMaW5lLCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4LCBnZW9tZXRyeUluZGV4KVxuICogQGV4YW1wbGVcbiAqIHZhciBtdWx0aUxpbmUgPSB0dXJmLm11bHRpTGluZVN0cmluZyhbXG4gKiAgIFtbMjYsIDM3XSwgWzM1LCA0NV1dLFxuICogICBbWzM2LCA1M10sIFszOCwgNTBdLCBbNDEsIDU1XV1cbiAqIF0pO1xuICpcbiAqIHR1cmYubGluZUVhY2gobXVsdGlMaW5lLCBmdW5jdGlvbiAoY3VycmVudExpbmUsIGZlYXR1cmVJbmRleCwgbXVsdGlGZWF0dXJlSW5kZXgsIGdlb21ldHJ5SW5kZXgpIHtcbiAqICAgLy89Y3VycmVudExpbmVcbiAqICAgLy89ZmVhdHVyZUluZGV4XG4gKiAgIC8vPW11bHRpRmVhdHVyZUluZGV4XG4gKiAgIC8vPWdlb21ldHJ5SW5kZXhcbiAqIH0pO1xuICovXG5mdW5jdGlvbiBsaW5lRWFjaChnZW9qc29uLCBjYWxsYmFjaykge1xuICAgIC8vIHZhbGlkYXRpb25cbiAgICBpZiAoIWdlb2pzb24pIHRocm93IG5ldyBFcnJvcignZ2VvanNvbiBpcyByZXF1aXJlZCcpO1xuXG4gICAgZmxhdHRlbkVhY2goZ2VvanNvbiwgZnVuY3Rpb24gKGZlYXR1cmUsIGZlYXR1cmVJbmRleCwgbXVsdGlGZWF0dXJlSW5kZXgpIHtcbiAgICAgICAgaWYgKGZlYXR1cmUuZ2VvbWV0cnkgPT09IG51bGwpIHJldHVybjtcbiAgICAgICAgdmFyIHR5cGUgPSBmZWF0dXJlLmdlb21ldHJ5LnR5cGU7XG4gICAgICAgIHZhciBjb29yZHMgPSBmZWF0dXJlLmdlb21ldHJ5LmNvb3JkaW5hdGVzO1xuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSAnTGluZVN0cmluZyc6XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2soZmVhdHVyZSwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgMCwgMCkgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnUG9seWdvbic6XG4gICAgICAgICAgICBmb3IgKHZhciBnZW9tZXRyeUluZGV4ID0gMDsgZ2VvbWV0cnlJbmRleCA8IGNvb3Jkcy5sZW5ndGg7IGdlb21ldHJ5SW5kZXgrKykge1xuICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjayhoZWxwZXJzLmxpbmVTdHJpbmcoY29vcmRzW2dlb21ldHJ5SW5kZXhdLCBmZWF0dXJlLnByb3BlcnRpZXMpLCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4LCBnZW9tZXRyeUluZGV4KSA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgZm9yIGxpbmVSZWR1Y2VcbiAqXG4gKiBUaGUgZmlyc3QgdGltZSB0aGUgY2FsbGJhY2sgZnVuY3Rpb24gaXMgY2FsbGVkLCB0aGUgdmFsdWVzIHByb3ZpZGVkIGFzIGFyZ3VtZW50cyBkZXBlbmRcbiAqIG9uIHdoZXRoZXIgdGhlIHJlZHVjZSBtZXRob2QgaGFzIGFuIGluaXRpYWxWYWx1ZSBhcmd1bWVudC5cbiAqXG4gKiBJZiBhbiBpbml0aWFsVmFsdWUgaXMgcHJvdmlkZWQgdG8gdGhlIHJlZHVjZSBtZXRob2Q6XG4gKiAgLSBUaGUgcHJldmlvdXNWYWx1ZSBhcmd1bWVudCBpcyBpbml0aWFsVmFsdWUuXG4gKiAgLSBUaGUgY3VycmVudFZhbHVlIGFyZ3VtZW50IGlzIHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgZWxlbWVudCBwcmVzZW50IGluIHRoZSBhcnJheS5cbiAqXG4gKiBJZiBhbiBpbml0aWFsVmFsdWUgaXMgbm90IHByb3ZpZGVkOlxuICogIC0gVGhlIHByZXZpb3VzVmFsdWUgYXJndW1lbnQgaXMgdGhlIHZhbHVlIG9mIHRoZSBmaXJzdCBlbGVtZW50IHByZXNlbnQgaW4gdGhlIGFycmF5LlxuICogIC0gVGhlIGN1cnJlbnRWYWx1ZSBhcmd1bWVudCBpcyB0aGUgdmFsdWUgb2YgdGhlIHNlY29uZCBlbGVtZW50IHByZXNlbnQgaW4gdGhlIGFycmF5LlxuICpcbiAqIEBjYWxsYmFjayBsaW5lUmVkdWNlQ2FsbGJhY2tcbiAqIEBwYXJhbSB7Kn0gcHJldmlvdXNWYWx1ZSBUaGUgYWNjdW11bGF0ZWQgdmFsdWUgcHJldmlvdXNseSByZXR1cm5lZCBpbiB0aGUgbGFzdCBpbnZvY2F0aW9uXG4gKiBvZiB0aGUgY2FsbGJhY2ssIG9yIGluaXRpYWxWYWx1ZSwgaWYgc3VwcGxpZWQuXG4gKiBAcGFyYW0ge0ZlYXR1cmU8TGluZVN0cmluZz59IGN1cnJlbnRMaW5lIFRoZSBjdXJyZW50IExpbmVTdHJpbmd8TGluZWFyUmluZyBiZWluZyBwcm9jZXNzZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gZmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBGZWF0dXJlIGJlaW5nIHByb2Nlc3NlZFxuICogQHBhcmFtIHtudW1iZXJ9IG11bHRpRmVhdHVyZUluZGV4IFRoZSBjdXJyZW50IGluZGV4IG9mIHRoZSBNdWx0aS1GZWF0dXJlIGJlaW5nIHByb2Nlc3NlZFxuICogQHBhcmFtIHtudW1iZXJ9IGdlb21ldHJ5SW5kZXggVGhlIGN1cnJlbnQgaW5kZXggb2YgdGhlIEdlb21ldHJ5IGJlaW5nIHByb2Nlc3NlZFxuICovXG5cbi8qKlxuICogUmVkdWNlIGZlYXR1cmVzIGluIGFueSBHZW9KU09OIG9iamVjdCwgc2ltaWxhciB0byBBcnJheS5yZWR1Y2UoKS5cbiAqXG4gKiBAbmFtZSBsaW5lUmVkdWNlXG4gKiBAcGFyYW0ge0dlb21ldHJ5fEZlYXR1cmU8TGluZVN0cmluZ3xQb2x5Z29ufE11bHRpTGluZVN0cmluZ3xNdWx0aVBvbHlnb24+fSBnZW9qc29uIG9iamVjdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgYSBtZXRob2QgdGhhdCB0YWtlcyAocHJldmlvdXNWYWx1ZSwgY3VycmVudExpbmUsIGZlYXR1cmVJbmRleCwgbXVsdGlGZWF0dXJlSW5kZXgsIGdlb21ldHJ5SW5kZXgpXG4gKiBAcGFyYW0geyp9IFtpbml0aWFsVmFsdWVdIFZhbHVlIHRvIHVzZSBhcyB0aGUgZmlyc3QgYXJndW1lbnQgdG8gdGhlIGZpcnN0IGNhbGwgb2YgdGhlIGNhbGxiYWNrLlxuICogQHJldHVybnMgeyp9IFRoZSB2YWx1ZSB0aGF0IHJlc3VsdHMgZnJvbSB0aGUgcmVkdWN0aW9uLlxuICogQGV4YW1wbGVcbiAqIHZhciBtdWx0aVBvbHkgPSB0dXJmLm11bHRpUG9seWdvbihbXG4gKiAgIHR1cmYucG9seWdvbihbW1sxMiw0OF0sWzIsNDFdLFsyNCwzOF0sWzEyLDQ4XV0sIFtbOSw0NF0sWzEzLDQxXSxbMTMsNDVdLFs5LDQ0XV1dKSxcbiAqICAgdHVyZi5wb2x5Z29uKFtbWzUsIDVdLCBbMCwgMF0sIFsyLCAyXSwgWzQsIDRdLCBbNSwgNV1dXSlcbiAqIF0pO1xuICpcbiAqIHR1cmYubGluZVJlZHVjZShtdWx0aVBvbHksIGZ1bmN0aW9uIChwcmV2aW91c1ZhbHVlLCBjdXJyZW50TGluZSwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCkge1xuICogICAvLz1wcmV2aW91c1ZhbHVlXG4gKiAgIC8vPWN1cnJlbnRMaW5lXG4gKiAgIC8vPWZlYXR1cmVJbmRleFxuICogICAvLz1tdWx0aUZlYXR1cmVJbmRleFxuICogICAvLz1nZW9tZXRyeUluZGV4XG4gKiAgIHJldHVybiBjdXJyZW50TGluZVxuICogfSk7XG4gKi9cbmZ1bmN0aW9uIGxpbmVSZWR1Y2UoZ2VvanNvbiwgY2FsbGJhY2ssIGluaXRpYWxWYWx1ZSkge1xuICAgIHZhciBwcmV2aW91c1ZhbHVlID0gaW5pdGlhbFZhbHVlO1xuICAgIGxpbmVFYWNoKGdlb2pzb24sIGZ1bmN0aW9uIChjdXJyZW50TGluZSwgZmVhdHVyZUluZGV4LCBtdWx0aUZlYXR1cmVJbmRleCwgZ2VvbWV0cnlJbmRleCkge1xuICAgICAgICBpZiAoZmVhdHVyZUluZGV4ID09PSAwICYmIGluaXRpYWxWYWx1ZSA9PT0gdW5kZWZpbmVkKSBwcmV2aW91c1ZhbHVlID0gY3VycmVudExpbmU7XG4gICAgICAgIGVsc2UgcHJldmlvdXNWYWx1ZSA9IGNhbGxiYWNrKHByZXZpb3VzVmFsdWUsIGN1cnJlbnRMaW5lLCBmZWF0dXJlSW5kZXgsIG11bHRpRmVhdHVyZUluZGV4LCBnZW9tZXRyeUluZGV4KTtcbiAgICB9KTtcbiAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcbn1cblxuLyoqXG4gKiBGaW5kcyBhIHBhcnRpY3VsYXIgMi12ZXJ0ZXggTGluZVN0cmluZyBTZWdtZW50IGZyb20gYSBHZW9KU09OIHVzaW5nIGBAdHVyZi9tZXRhYCBpbmRleGVzLlxuICpcbiAqIE5lZ2F0aXZlIGluZGV4ZXMgYXJlIHBlcm1pdHRlZC5cbiAqIFBvaW50ICYgTXVsdGlQb2ludCB3aWxsIGFsd2F5cyByZXR1cm4gbnVsbC5cbiAqXG4gKiBAcGFyYW0ge0ZlYXR1cmVDb2xsZWN0aW9ufEZlYXR1cmV8R2VvbWV0cnl9IGdlb2pzb24gQW55IEdlb0pTT04gRmVhdHVyZSBvciBHZW9tZXRyeVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBPcHRpb25hbCBwYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMuZmVhdHVyZUluZGV4PTBdIEZlYXR1cmUgSW5kZXhcbiAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5tdWx0aUZlYXR1cmVJbmRleD0wXSBNdWx0aS1GZWF0dXJlIEluZGV4XG4gKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMuZ2VvbWV0cnlJbmRleD0wXSBHZW9tZXRyeSBJbmRleFxuICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLnNlZ21lbnRJbmRleD0wXSBTZWdtZW50IEluZGV4XG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMucHJvcGVydGllcz17fV0gVHJhbnNsYXRlIFByb3BlcnRpZXMgdG8gb3V0cHV0IExpbmVTdHJpbmdcbiAqIEBwYXJhbSB7QkJveH0gW29wdGlvbnMuYmJveD17fV0gVHJhbnNsYXRlIEJCb3ggdG8gb3V0cHV0IExpbmVTdHJpbmdcbiAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gW29wdGlvbnMuaWQ9e31dIFRyYW5zbGF0ZSBJZCB0byBvdXRwdXQgTGluZVN0cmluZ1xuICogQHJldHVybnMge0ZlYXR1cmU8TGluZVN0cmluZz59IDItdmVydGV4IEdlb0pTT04gRmVhdHVyZSBMaW5lU3RyaW5nXG4gKiBAZXhhbXBsZVxuICogdmFyIG11bHRpTGluZSA9IHR1cmYubXVsdGlMaW5lU3RyaW5nKFtcbiAqICAgICBbWzEwLCAxMF0sIFs1MCwgMzBdLCBbMzAsIDQwXV0sXG4gKiAgICAgW1stMTAsIC0xMF0sIFstNTAsIC0zMF0sIFstMzAsIC00MF1dXG4gKiBdKTtcbiAqXG4gKiAvLyBGaXJzdCBTZWdtZW50IChkZWZhdWx0cyBhcmUgMClcbiAqIHR1cmYuZmluZFNlZ21lbnQobXVsdGlMaW5lKTtcbiAqIC8vID0+IEZlYXR1cmU8TGluZVN0cmluZzxbWzEwLCAxMF0sIFs1MCwgMzBdXT4+XG4gKlxuICogLy8gRmlyc3QgU2VnbWVudCBvZiAybmQgTXVsdGkgRmVhdHVyZVxuICogdHVyZi5maW5kU2VnbWVudChtdWx0aUxpbmUsIHttdWx0aUZlYXR1cmVJbmRleDogMX0pO1xuICogLy8gPT4gRmVhdHVyZTxMaW5lU3RyaW5nPFtbLTEwLCAtMTBdLCBbLTUwLCAtMzBdXT4+XG4gKlxuICogLy8gTGFzdCBTZWdtZW50IG9mIExhc3QgTXVsdGkgRmVhdHVyZVxuICogdHVyZi5maW5kU2VnbWVudChtdWx0aUxpbmUsIHttdWx0aUZlYXR1cmVJbmRleDogLTEsIHNlZ21lbnRJbmRleDogLTF9KTtcbiAqIC8vID0+IEZlYXR1cmU8TGluZVN0cmluZzxbWy01MCwgLTMwXSwgWy0zMCwgLTQwXV0+PlxuICovXG5mdW5jdGlvbiBmaW5kU2VnbWVudChnZW9qc29uLCBvcHRpb25zKSB7XG4gICAgLy8gT3B0aW9uYWwgUGFyYW1ldGVyc1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIGlmICghaGVscGVycy5pc09iamVjdChvcHRpb25zKSkgdGhyb3cgbmV3IEVycm9yKCdvcHRpb25zIGlzIGludmFsaWQnKTtcbiAgICB2YXIgZmVhdHVyZUluZGV4ID0gb3B0aW9ucy5mZWF0dXJlSW5kZXggfHwgMDtcbiAgICB2YXIgbXVsdGlGZWF0dXJlSW5kZXggPSBvcHRpb25zLm11bHRpRmVhdHVyZUluZGV4IHx8IDA7XG4gICAgdmFyIGdlb21ldHJ5SW5kZXggPSBvcHRpb25zLmdlb21ldHJ5SW5kZXggfHwgMDtcbiAgICB2YXIgc2VnbWVudEluZGV4ID0gb3B0aW9ucy5zZWdtZW50SW5kZXggfHwgMDtcblxuICAgIC8vIEZpbmQgRmVhdHVyZUluZGV4XG4gICAgdmFyIHByb3BlcnRpZXMgPSBvcHRpb25zLnByb3BlcnRpZXM7XG4gICAgdmFyIGdlb21ldHJ5O1xuXG4gICAgc3dpdGNoIChnZW9qc29uLnR5cGUpIHtcbiAgICBjYXNlICdGZWF0dXJlQ29sbGVjdGlvbic6XG4gICAgICAgIGlmIChmZWF0dXJlSW5kZXggPCAwKSBmZWF0dXJlSW5kZXggPSBnZW9qc29uLmZlYXR1cmVzLmxlbmd0aCArIGZlYXR1cmVJbmRleDtcbiAgICAgICAgcHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgZ2VvanNvbi5mZWF0dXJlc1tmZWF0dXJlSW5kZXhdLnByb3BlcnRpZXM7XG4gICAgICAgIGdlb21ldHJ5ID0gZ2VvanNvbi5mZWF0dXJlc1tmZWF0dXJlSW5kZXhdLmdlb21ldHJ5O1xuICAgICAgICBicmVhaztcbiAgICBjYXNlICdGZWF0dXJlJzpcbiAgICAgICAgcHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgZ2VvanNvbi5wcm9wZXJ0aWVzO1xuICAgICAgICBnZW9tZXRyeSA9IGdlb2pzb24uZ2VvbWV0cnk7XG4gICAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1BvaW50JzpcbiAgICBjYXNlICdNdWx0aVBvaW50JzpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgY2FzZSAnTGluZVN0cmluZyc6XG4gICAgY2FzZSAnUG9seWdvbic6XG4gICAgY2FzZSAnTXVsdGlMaW5lU3RyaW5nJzpcbiAgICBjYXNlICdNdWx0aVBvbHlnb24nOlxuICAgICAgICBnZW9tZXRyeSA9IGdlb2pzb247XG4gICAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2VvanNvbiBpcyBpbnZhbGlkJyk7XG4gICAgfVxuXG4gICAgLy8gRmluZCBTZWdtZW50SW5kZXhcbiAgICBpZiAoZ2VvbWV0cnkgPT09IG51bGwpIHJldHVybiBudWxsO1xuICAgIHZhciBjb29yZHMgPSBnZW9tZXRyeS5jb29yZGluYXRlcztcbiAgICBzd2l0Y2ggKGdlb21ldHJ5LnR5cGUpIHtcbiAgICBjYXNlICdQb2ludCc6XG4gICAgY2FzZSAnTXVsdGlQb2ludCc6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIGNhc2UgJ0xpbmVTdHJpbmcnOlxuICAgICAgICBpZiAoc2VnbWVudEluZGV4IDwgMCkgc2VnbWVudEluZGV4ID0gY29vcmRzLmxlbmd0aCArIHNlZ21lbnRJbmRleCAtIDE7XG4gICAgICAgIHJldHVybiBoZWxwZXJzLmxpbmVTdHJpbmcoW2Nvb3Jkc1tzZWdtZW50SW5kZXhdLCBjb29yZHNbc2VnbWVudEluZGV4ICsgMV1dLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbiAgICBjYXNlICdQb2x5Z29uJzpcbiAgICAgICAgaWYgKGdlb21ldHJ5SW5kZXggPCAwKSBnZW9tZXRyeUluZGV4ID0gY29vcmRzLmxlbmd0aCArIGdlb21ldHJ5SW5kZXg7XG4gICAgICAgIGlmIChzZWdtZW50SW5kZXggPCAwKSBzZWdtZW50SW5kZXggPSBjb29yZHNbZ2VvbWV0cnlJbmRleF0ubGVuZ3RoICsgc2VnbWVudEluZGV4IC0gMTtcbiAgICAgICAgcmV0dXJuIGhlbHBlcnMubGluZVN0cmluZyhbY29vcmRzW2dlb21ldHJ5SW5kZXhdW3NlZ21lbnRJbmRleF0sIGNvb3Jkc1tnZW9tZXRyeUluZGV4XVtzZWdtZW50SW5kZXggKyAxXV0sIHByb3BlcnRpZXMsIG9wdGlvbnMpO1xuICAgIGNhc2UgJ011bHRpTGluZVN0cmluZyc6XG4gICAgICAgIGlmIChtdWx0aUZlYXR1cmVJbmRleCA8IDApIG11bHRpRmVhdHVyZUluZGV4ID0gY29vcmRzLmxlbmd0aCArIG11bHRpRmVhdHVyZUluZGV4O1xuICAgICAgICBpZiAoc2VnbWVudEluZGV4IDwgMCkgc2VnbWVudEluZGV4ID0gY29vcmRzW211bHRpRmVhdHVyZUluZGV4XS5sZW5ndGggKyBzZWdtZW50SW5kZXggLSAxO1xuICAgICAgICByZXR1cm4gaGVscGVycy5saW5lU3RyaW5nKFtjb29yZHNbbXVsdGlGZWF0dXJlSW5kZXhdW3NlZ21lbnRJbmRleF0sIGNvb3Jkc1ttdWx0aUZlYXR1cmVJbmRleF1bc2VnbWVudEluZGV4ICsgMV1dLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbiAgICBjYXNlICdNdWx0aVBvbHlnb24nOlxuICAgICAgICBpZiAobXVsdGlGZWF0dXJlSW5kZXggPCAwKSBtdWx0aUZlYXR1cmVJbmRleCA9IGNvb3Jkcy5sZW5ndGggKyBtdWx0aUZlYXR1cmVJbmRleDtcbiAgICAgICAgaWYgKGdlb21ldHJ5SW5kZXggPCAwKSBnZW9tZXRyeUluZGV4ID0gY29vcmRzW211bHRpRmVhdHVyZUluZGV4XS5sZW5ndGggKyBnZW9tZXRyeUluZGV4O1xuICAgICAgICBpZiAoc2VnbWVudEluZGV4IDwgMCkgc2VnbWVudEluZGV4ID0gY29vcmRzW211bHRpRmVhdHVyZUluZGV4XVtnZW9tZXRyeUluZGV4XS5sZW5ndGggLSBzZWdtZW50SW5kZXggLSAxO1xuICAgICAgICByZXR1cm4gaGVscGVycy5saW5lU3RyaW5nKFtjb29yZHNbbXVsdGlGZWF0dXJlSW5kZXhdW2dlb21ldHJ5SW5kZXhdW3NlZ21lbnRJbmRleF0sIGNvb3Jkc1ttdWx0aUZlYXR1cmVJbmRleF1bZ2VvbWV0cnlJbmRleF1bc2VnbWVudEluZGV4ICsgMV1dLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnZW9qc29uIGlzIGludmFsaWQnKTtcbn1cblxuLyoqXG4gKiBGaW5kcyBhIHBhcnRpY3VsYXIgUG9pbnQgZnJvbSBhIEdlb0pTT04gdXNpbmcgYEB0dXJmL21ldGFgIGluZGV4ZXMuXG4gKlxuICogTmVnYXRpdmUgaW5kZXhlcyBhcmUgcGVybWl0dGVkLlxuICpcbiAqIEBwYXJhbSB7RmVhdHVyZUNvbGxlY3Rpb258RmVhdHVyZXxHZW9tZXRyeX0gZ2VvanNvbiBBbnkgR2VvSlNPTiBGZWF0dXJlIG9yIEdlb21ldHJ5XG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIE9wdGlvbmFsIHBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5mZWF0dXJlSW5kZXg9MF0gRmVhdHVyZSBJbmRleFxuICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLm11bHRpRmVhdHVyZUluZGV4PTBdIE11bHRpLUZlYXR1cmUgSW5kZXhcbiAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5nZW9tZXRyeUluZGV4PTBdIEdlb21ldHJ5IEluZGV4XG4gKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMuY29vcmRJbmRleD0wXSBDb29yZCBJbmRleFxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLnByb3BlcnRpZXM9e31dIFRyYW5zbGF0ZSBQcm9wZXJ0aWVzIHRvIG91dHB1dCBQb2ludFxuICogQHBhcmFtIHtCQm94fSBbb3B0aW9ucy5iYm94PXt9XSBUcmFuc2xhdGUgQkJveCB0byBvdXRwdXQgUG9pbnRcbiAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gW29wdGlvbnMuaWQ9e31dIFRyYW5zbGF0ZSBJZCB0byBvdXRwdXQgUG9pbnRcbiAqIEByZXR1cm5zIHtGZWF0dXJlPFBvaW50Pn0gMi12ZXJ0ZXggR2VvSlNPTiBGZWF0dXJlIFBvaW50XG4gKiBAZXhhbXBsZVxuICogdmFyIG11bHRpTGluZSA9IHR1cmYubXVsdGlMaW5lU3RyaW5nKFtcbiAqICAgICBbWzEwLCAxMF0sIFs1MCwgMzBdLCBbMzAsIDQwXV0sXG4gKiAgICAgW1stMTAsIC0xMF0sIFstNTAsIC0zMF0sIFstMzAsIC00MF1dXG4gKiBdKTtcbiAqXG4gKiAvLyBGaXJzdCBTZWdtZW50IChkZWZhdWx0cyBhcmUgMClcbiAqIHR1cmYuZmluZFBvaW50KG11bHRpTGluZSk7XG4gKiAvLyA9PiBGZWF0dXJlPFBvaW50PFsxMCwgMTBdPj5cbiAqXG4gKiAvLyBGaXJzdCBTZWdtZW50IG9mIHRoZSAybmQgTXVsdGktRmVhdHVyZVxuICogdHVyZi5maW5kUG9pbnQobXVsdGlMaW5lLCB7bXVsdGlGZWF0dXJlSW5kZXg6IDF9KTtcbiAqIC8vID0+IEZlYXR1cmU8UG9pbnQ8Wy0xMCwgLTEwXT4+XG4gKlxuICogLy8gTGFzdCBTZWdtZW50IG9mIGxhc3QgTXVsdGktRmVhdHVyZVxuICogdHVyZi5maW5kUG9pbnQobXVsdGlMaW5lLCB7bXVsdGlGZWF0dXJlSW5kZXg6IC0xLCBjb29yZEluZGV4OiAtMX0pO1xuICogLy8gPT4gRmVhdHVyZTxQb2ludDxbLTMwLCAtNDBdPj5cbiAqL1xuZnVuY3Rpb24gZmluZFBvaW50KGdlb2pzb24sIG9wdGlvbnMpIHtcbiAgICAvLyBPcHRpb25hbCBQYXJhbWV0ZXJzXG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgaWYgKCFoZWxwZXJzLmlzT2JqZWN0KG9wdGlvbnMpKSB0aHJvdyBuZXcgRXJyb3IoJ29wdGlvbnMgaXMgaW52YWxpZCcpO1xuICAgIHZhciBmZWF0dXJlSW5kZXggPSBvcHRpb25zLmZlYXR1cmVJbmRleCB8fCAwO1xuICAgIHZhciBtdWx0aUZlYXR1cmVJbmRleCA9IG9wdGlvbnMubXVsdGlGZWF0dXJlSW5kZXggfHwgMDtcbiAgICB2YXIgZ2VvbWV0cnlJbmRleCA9IG9wdGlvbnMuZ2VvbWV0cnlJbmRleCB8fCAwO1xuICAgIHZhciBjb29yZEluZGV4ID0gb3B0aW9ucy5jb29yZEluZGV4IHx8IDA7XG5cbiAgICAvLyBGaW5kIEZlYXR1cmVJbmRleFxuICAgIHZhciBwcm9wZXJ0aWVzID0gb3B0aW9ucy5wcm9wZXJ0aWVzO1xuICAgIHZhciBnZW9tZXRyeTtcblxuICAgIHN3aXRjaCAoZ2VvanNvbi50eXBlKSB7XG4gICAgY2FzZSAnRmVhdHVyZUNvbGxlY3Rpb24nOlxuICAgICAgICBpZiAoZmVhdHVyZUluZGV4IDwgMCkgZmVhdHVyZUluZGV4ID0gZ2VvanNvbi5mZWF0dXJlcy5sZW5ndGggKyBmZWF0dXJlSW5kZXg7XG4gICAgICAgIHByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IGdlb2pzb24uZmVhdHVyZXNbZmVhdHVyZUluZGV4XS5wcm9wZXJ0aWVzO1xuICAgICAgICBnZW9tZXRyeSA9IGdlb2pzb24uZmVhdHVyZXNbZmVhdHVyZUluZGV4XS5nZW9tZXRyeTtcbiAgICAgICAgYnJlYWs7XG4gICAgY2FzZSAnRmVhdHVyZSc6XG4gICAgICAgIHByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IGdlb2pzb24ucHJvcGVydGllcztcbiAgICAgICAgZ2VvbWV0cnkgPSBnZW9qc29uLmdlb21ldHJ5O1xuICAgICAgICBicmVhaztcbiAgICBjYXNlICdQb2ludCc6XG4gICAgY2FzZSAnTXVsdGlQb2ludCc6XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIGNhc2UgJ0xpbmVTdHJpbmcnOlxuICAgIGNhc2UgJ1BvbHlnb24nOlxuICAgIGNhc2UgJ011bHRpTGluZVN0cmluZyc6XG4gICAgY2FzZSAnTXVsdGlQb2x5Z29uJzpcbiAgICAgICAgZ2VvbWV0cnkgPSBnZW9qc29uO1xuICAgICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dlb2pzb24gaXMgaW52YWxpZCcpO1xuICAgIH1cblxuICAgIC8vIEZpbmQgQ29vcmQgSW5kZXhcbiAgICBpZiAoZ2VvbWV0cnkgPT09IG51bGwpIHJldHVybiBudWxsO1xuICAgIHZhciBjb29yZHMgPSBnZW9tZXRyeS5jb29yZGluYXRlcztcbiAgICBzd2l0Y2ggKGdlb21ldHJ5LnR5cGUpIHtcbiAgICBjYXNlICdQb2ludCc6XG4gICAgICAgIHJldHVybiBoZWxwZXJzLnBvaW50KGNvb3JkcywgcHJvcGVydGllcywgb3B0aW9ucyk7XG4gICAgY2FzZSAnTXVsdGlQb2ludCc6XG4gICAgICAgIGlmIChtdWx0aUZlYXR1cmVJbmRleCA8IDApIG11bHRpRmVhdHVyZUluZGV4ID0gY29vcmRzLmxlbmd0aCArIG11bHRpRmVhdHVyZUluZGV4O1xuICAgICAgICByZXR1cm4gaGVscGVycy5wb2ludChjb29yZHNbbXVsdGlGZWF0dXJlSW5kZXhdLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbiAgICBjYXNlICdMaW5lU3RyaW5nJzpcbiAgICAgICAgaWYgKGNvb3JkSW5kZXggPCAwKSBjb29yZEluZGV4ID0gY29vcmRzLmxlbmd0aCArIGNvb3JkSW5kZXg7XG4gICAgICAgIHJldHVybiBoZWxwZXJzLnBvaW50KGNvb3Jkc1tjb29yZEluZGV4XSwgcHJvcGVydGllcywgb3B0aW9ucyk7XG4gICAgY2FzZSAnUG9seWdvbic6XG4gICAgICAgIGlmIChnZW9tZXRyeUluZGV4IDwgMCkgZ2VvbWV0cnlJbmRleCA9IGNvb3Jkcy5sZW5ndGggKyBnZW9tZXRyeUluZGV4O1xuICAgICAgICBpZiAoY29vcmRJbmRleCA8IDApIGNvb3JkSW5kZXggPSBjb29yZHNbZ2VvbWV0cnlJbmRleF0ubGVuZ3RoICsgY29vcmRJbmRleDtcbiAgICAgICAgcmV0dXJuIGhlbHBlcnMucG9pbnQoY29vcmRzW2dlb21ldHJ5SW5kZXhdW2Nvb3JkSW5kZXhdLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbiAgICBjYXNlICdNdWx0aUxpbmVTdHJpbmcnOlxuICAgICAgICBpZiAobXVsdGlGZWF0dXJlSW5kZXggPCAwKSBtdWx0aUZlYXR1cmVJbmRleCA9IGNvb3Jkcy5sZW5ndGggKyBtdWx0aUZlYXR1cmVJbmRleDtcbiAgICAgICAgaWYgKGNvb3JkSW5kZXggPCAwKSBjb29yZEluZGV4ID0gY29vcmRzW211bHRpRmVhdHVyZUluZGV4XS5sZW5ndGggKyBjb29yZEluZGV4O1xuICAgICAgICByZXR1cm4gaGVscGVycy5wb2ludChjb29yZHNbbXVsdGlGZWF0dXJlSW5kZXhdW2Nvb3JkSW5kZXhdLCBwcm9wZXJ0aWVzLCBvcHRpb25zKTtcbiAgICBjYXNlICdNdWx0aVBvbHlnb24nOlxuICAgICAgICBpZiAobXVsdGlGZWF0dXJlSW5kZXggPCAwKSBtdWx0aUZlYXR1cmVJbmRleCA9IGNvb3Jkcy5sZW5ndGggKyBtdWx0aUZlYXR1cmVJbmRleDtcbiAgICAgICAgaWYgKGdlb21ldHJ5SW5kZXggPCAwKSBnZW9tZXRyeUluZGV4ID0gY29vcmRzW211bHRpRmVhdHVyZUluZGV4XS5sZW5ndGggKyBnZW9tZXRyeUluZGV4O1xuICAgICAgICBpZiAoY29vcmRJbmRleCA8IDApIGNvb3JkSW5kZXggPSBjb29yZHNbbXVsdGlGZWF0dXJlSW5kZXhdW2dlb21ldHJ5SW5kZXhdLmxlbmd0aCAtIGNvb3JkSW5kZXg7XG4gICAgICAgIHJldHVybiBoZWxwZXJzLnBvaW50KGNvb3Jkc1ttdWx0aUZlYXR1cmVJbmRleF1bZ2VvbWV0cnlJbmRleF1bY29vcmRJbmRleF0sIHByb3BlcnRpZXMsIG9wdGlvbnMpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dlb2pzb24gaXMgaW52YWxpZCcpO1xufVxuXG5leHBvcnRzLmNvb3JkRWFjaCA9IGNvb3JkRWFjaDtcbmV4cG9ydHMuY29vcmRSZWR1Y2UgPSBjb29yZFJlZHVjZTtcbmV4cG9ydHMucHJvcEVhY2ggPSBwcm9wRWFjaDtcbmV4cG9ydHMucHJvcFJlZHVjZSA9IHByb3BSZWR1Y2U7XG5leHBvcnRzLmZlYXR1cmVFYWNoID0gZmVhdHVyZUVhY2g7XG5leHBvcnRzLmZlYXR1cmVSZWR1Y2UgPSBmZWF0dXJlUmVkdWNlO1xuZXhwb3J0cy5jb29yZEFsbCA9IGNvb3JkQWxsO1xuZXhwb3J0cy5nZW9tRWFjaCA9IGdlb21FYWNoO1xuZXhwb3J0cy5nZW9tUmVkdWNlID0gZ2VvbVJlZHVjZTtcbmV4cG9ydHMuZmxhdHRlbkVhY2ggPSBmbGF0dGVuRWFjaDtcbmV4cG9ydHMuZmxhdHRlblJlZHVjZSA9IGZsYXR0ZW5SZWR1Y2U7XG5leHBvcnRzLnNlZ21lbnRFYWNoID0gc2VnbWVudEVhY2g7XG5leHBvcnRzLnNlZ21lbnRSZWR1Y2UgPSBzZWdtZW50UmVkdWNlO1xuZXhwb3J0cy5saW5lRWFjaCA9IGxpbmVFYWNoO1xuZXhwb3J0cy5saW5lUmVkdWNlID0gbGluZVJlZHVjZTtcbmV4cG9ydHMuZmluZFNlZ21lbnQgPSBmaW5kU2VnbWVudDtcbmV4cG9ydHMuZmluZFBvaW50ID0gZmluZFBvaW50O1xuXG59LHtcIkB0dXJmL2hlbHBlcnNcIjo1N31dLDU5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgd2Vha01hcCAgICAgID0gdHlwZW9mIFdlYWtNYXAgPT09ICd1bmRlZmluZWQnID8gX2RlcmVxXygnd2Vhay1tYXAnKSA6IFdlYWtNYXBcbnZhciBjcmVhdGVCdWZmZXIgPSBfZGVyZXFfKCdnbC1idWZmZXInKVxudmFyIGNyZWF0ZVZBTyAgICA9IF9kZXJlcV8oJ2dsLXZhbycpXG5cbnZhciBUcmlhbmdsZUNhY2hlID0gbmV3IHdlYWtNYXAoKVxuXG5mdW5jdGlvbiBjcmVhdGVBQmlnVHJpYW5nbGUoZ2wpIHtcblxuICB2YXIgdHJpYW5nbGVWQU8gPSBUcmlhbmdsZUNhY2hlLmdldChnbClcbiAgdmFyIGhhbmRsZSA9IHRyaWFuZ2xlVkFPICYmICh0cmlhbmdsZVZBTy5fdHJpYW5nbGVCdWZmZXIuaGFuZGxlIHx8IHRyaWFuZ2xlVkFPLl90cmlhbmdsZUJ1ZmZlci5idWZmZXIpXG4gIGlmKCFoYW5kbGUgfHwgIWdsLmlzQnVmZmVyKGhhbmRsZSkpIHtcbiAgICB2YXIgYnVmID0gY3JlYXRlQnVmZmVyKGdsLCBuZXcgRmxvYXQzMkFycmF5KFstMSwgLTEsIC0xLCA0LCA0LCAtMV0pKVxuICAgIHRyaWFuZ2xlVkFPID0gY3JlYXRlVkFPKGdsLCBbXG4gICAgICB7IGJ1ZmZlcjogYnVmLFxuICAgICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgICAgc2l6ZTogMlxuICAgICAgfVxuICAgIF0pXG4gICAgdHJpYW5nbGVWQU8uX3RyaWFuZ2xlQnVmZmVyID0gYnVmXG4gICAgVHJpYW5nbGVDYWNoZS5zZXQoZ2wsIHRyaWFuZ2xlVkFPKVxuICB9XG4gIHRyaWFuZ2xlVkFPLmJpbmQoKVxuICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgMylcbiAgdHJpYW5nbGVWQU8udW5iaW5kKClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVBQmlnVHJpYW5nbGVcblxufSx7XCJnbC1idWZmZXJcIjoyNDEsXCJnbC12YW9cIjozMjcsXCJ3ZWFrLW1hcFwiOjU1Mn1dLDYwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblxubW9kdWxlLmV4cG9ydHMgPSBhYnNvbHV0aXplXG5cbi8qKlxuICogcmVkZWZpbmUgYHBhdGhgIHdpdGggYWJzb2x1dGUgY29vcmRpbmF0ZXNcbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBwYXRoXG4gKiBAcmV0dXJuIHtBcnJheX1cbiAqL1xuXG5mdW5jdGlvbiBhYnNvbHV0aXplKHBhdGgpe1xuXHR2YXIgc3RhcnRYID0gMFxuXHR2YXIgc3RhcnRZID0gMFxuXHR2YXIgeCA9IDBcblx0dmFyIHkgPSAwXG5cblx0cmV0dXJuIHBhdGgubWFwKGZ1bmN0aW9uKHNlZyl7XG5cdFx0c2VnID0gc2VnLnNsaWNlKClcblx0XHR2YXIgdHlwZSA9IHNlZ1swXVxuXHRcdHZhciBjb21tYW5kID0gdHlwZS50b1VwcGVyQ2FzZSgpXG5cblx0XHQvLyBpcyByZWxhdGl2ZVxuXHRcdGlmICh0eXBlICE9IGNvbW1hbmQpIHtcblx0XHRcdHNlZ1swXSA9IGNvbW1hbmRcblx0XHRcdHN3aXRjaCAodHlwZSkge1xuXHRcdFx0XHRjYXNlICdhJzpcblx0XHRcdFx0XHRzZWdbNl0gKz0geFxuXHRcdFx0XHRcdHNlZ1s3XSArPSB5XG5cdFx0XHRcdFx0YnJlYWtcblx0XHRcdFx0Y2FzZSAndic6XG5cdFx0XHRcdFx0c2VnWzFdICs9IHlcblx0XHRcdFx0XHRicmVha1xuXHRcdFx0XHRjYXNlICdoJzpcblx0XHRcdFx0XHRzZWdbMV0gKz0geFxuXHRcdFx0XHRcdGJyZWFrXG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0Zm9yICh2YXIgaSA9IDE7IGkgPCBzZWcubGVuZ3RoOykge1xuXHRcdFx0XHRcdFx0c2VnW2krK10gKz0geFxuXHRcdFx0XHRcdFx0c2VnW2krK10gKz0geVxuXHRcdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyB1cGRhdGUgY3Vyc29yIHN0YXRlXG5cdFx0c3dpdGNoIChjb21tYW5kKSB7XG5cdFx0XHRjYXNlICdaJzpcblx0XHRcdFx0eCA9IHN0YXJ0WFxuXHRcdFx0XHR5ID0gc3RhcnRZXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRjYXNlICdIJzpcblx0XHRcdFx0eCA9IHNlZ1sxXVxuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAnVic6XG5cdFx0XHRcdHkgPSBzZWdbMV1cblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgJ00nOlxuXHRcdFx0XHR4ID0gc3RhcnRYID0gc2VnWzFdXG5cdFx0XHRcdHkgPSBzdGFydFkgPSBzZWdbMl1cblx0XHRcdFx0YnJlYWtcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHggPSBzZWdbc2VnLmxlbmd0aCAtIDJdXG5cdFx0XHRcdHkgPSBzZWdbc2VnLmxlbmd0aCAtIDFdXG5cdFx0fVxuXG5cdFx0cmV0dXJuIHNlZ1xuXHR9KVxufVxuXG59LHt9XSw2MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG52YXIgcGFkTGVmdCA9IF9kZXJlcV8oJ3BhZC1sZWZ0JylcblxubW9kdWxlLmV4cG9ydHMgPSBhZGRMaW5lTnVtYmVyc1xuZnVuY3Rpb24gYWRkTGluZU51bWJlcnMgKHN0cmluZywgc3RhcnQsIGRlbGltKSB7XG4gIHN0YXJ0ID0gdHlwZW9mIHN0YXJ0ID09PSAnbnVtYmVyJyA/IHN0YXJ0IDogMVxuICBkZWxpbSA9IGRlbGltIHx8ICc6ICdcblxuICB2YXIgbGluZXMgPSBzdHJpbmcuc3BsaXQoL1xccj9cXG4vKVxuICB2YXIgdG90YWxEaWdpdHMgPSBTdHJpbmcobGluZXMubGVuZ3RoICsgc3RhcnQgLSAxKS5sZW5ndGhcbiAgcmV0dXJuIGxpbmVzLm1hcChmdW5jdGlvbiAobGluZSwgaSkge1xuICAgIHZhciBjID0gaSArIHN0YXJ0XG4gICAgdmFyIGRpZ2l0cyA9IFN0cmluZyhjKS5sZW5ndGhcbiAgICB2YXIgcHJlZml4ID0gcGFkTGVmdChjLCB0b3RhbERpZ2l0cyAtIGRpZ2l0cylcbiAgICByZXR1cm4gcHJlZml4ICsgZGVsaW0gKyBsaW5lXG4gIH0pLmpvaW4oJ1xcbicpXG59XG5cbn0se1wicGFkLWxlZnRcIjo0NTd9XSw2MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBhZmZpbmVIdWxsXG5cbnZhciBvcmllbnQgPSBfZGVyZXFfKCdyb2J1c3Qtb3JpZW50YXRpb24nKVxuXG5mdW5jdGlvbiBsaW5lYXJseUluZGVwZW5kZW50KHBvaW50cywgZCkge1xuICB2YXIgbmh1bGwgPSBuZXcgQXJyYXkoZCsxKVxuICBmb3IodmFyIGk9MDsgaTxwb2ludHMubGVuZ3RoOyArK2kpIHtcbiAgICBuaHVsbFtpXSA9IHBvaW50c1tpXVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPD1wb2ludHMubGVuZ3RoOyArK2kpIHtcbiAgICBmb3IodmFyIGo9cG9pbnRzLmxlbmd0aDsgajw9ZDsgKytqKSB7XG4gICAgICB2YXIgeCA9IG5ldyBBcnJheShkKVxuICAgICAgZm9yKHZhciBrPTA7IGs8ZDsgKytrKSB7XG4gICAgICAgIHhba10gPSBNYXRoLnBvdyhqKzEtaSwgaylcbiAgICAgIH1cbiAgICAgIG5odWxsW2pdID0geFxuICAgIH1cbiAgICB2YXIgbyA9IG9yaWVudC5hcHBseSh2b2lkIDAsIG5odWxsKVxuICAgIGlmKG8pIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZVxufVxuXG5mdW5jdGlvbiBhZmZpbmVIdWxsKHBvaW50cykge1xuICB2YXIgbiA9IHBvaW50cy5sZW5ndGhcbiAgaWYobiA9PT0gMCkge1xuICAgIHJldHVybiBbXVxuICB9XG4gIGlmKG4gPT09IDEpIHtcbiAgICByZXR1cm4gWzBdXG4gIH1cbiAgdmFyIGQgPSBwb2ludHNbMF0ubGVuZ3RoXG4gIHZhciBmcmFtZSA9IFsgcG9pbnRzWzBdIF1cbiAgdmFyIGluZGV4ID0gWyAwIF1cbiAgZm9yKHZhciBpPTE7IGk8bjsgKytpKSB7XG4gICAgZnJhbWUucHVzaChwb2ludHNbaV0pXG4gICAgaWYoIWxpbmVhcmx5SW5kZXBlbmRlbnQoZnJhbWUsIGQpKSB7XG4gICAgICBmcmFtZS5wb3AoKVxuICAgICAgY29udGludWVcbiAgICB9XG4gICAgaW5kZXgucHVzaChpKVxuICAgIGlmKGluZGV4Lmxlbmd0aCA9PT0gZCsxKSB7XG4gICAgICByZXR1cm4gaW5kZXhcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGluZGV4XG59XG59LHtcInJvYnVzdC1vcmllbnRhdGlvblwiOjUxMH1dLDYzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGFscGhhQ29tcGxleFxuXG52YXIgZGVsYXVuYXkgPSBfZGVyZXFfKCdkZWxhdW5heS10cmlhbmd1bGF0ZScpXG52YXIgY2lyY3VtcmFkaXVzID0gX2RlcmVxXygnY2lyY3VtcmFkaXVzJylcblxuZnVuY3Rpb24gYWxwaGFDb21wbGV4KGFscGhhLCBwb2ludHMpIHtcbiAgcmV0dXJuIGRlbGF1bmF5KHBvaW50cykuZmlsdGVyKGZ1bmN0aW9uKGNlbGwpIHtcbiAgICB2YXIgc2ltcGxleCA9IG5ldyBBcnJheShjZWxsLmxlbmd0aClcbiAgICBmb3IodmFyIGk9MDsgaTxjZWxsLmxlbmd0aDsgKytpKSB7XG4gICAgICBzaW1wbGV4W2ldID0gcG9pbnRzW2NlbGxbaV1dXG4gICAgfVxuICAgIHJldHVybiBjaXJjdW1yYWRpdXMoc2ltcGxleCkgKiBhbHBoYSA8IDFcbiAgfSlcbn1cbn0se1wiY2lyY3VtcmFkaXVzXCI6MTE0LFwiZGVsYXVuYXktdHJpYW5ndWxhdGVcIjoxNjV9XSw2NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGFscGhhU2hhcGVcblxudmFyIGFjID0gX2RlcmVxXygnYWxwaGEtY29tcGxleCcpXG52YXIgYm5kID0gX2RlcmVxXygnc2ltcGxpY2lhbC1jb21wbGV4LWJvdW5kYXJ5JylcblxuZnVuY3Rpb24gYWxwaGFTaGFwZShhbHBoYSwgcG9pbnRzKSB7XG4gIHJldHVybiBibmQoYWMoYWxwaGEsIHBvaW50cykpXG59XG59LHtcImFscGhhLWNvbXBsZXhcIjo2MyxcInNpbXBsaWNpYWwtY29tcGxleC1ib3VuZGFyeVwiOjUxN31dLDY1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBub3JtYWxpemU7XHJcblxyXG5mdW5jdGlvbiBub3JtYWxpemUgKGFyciwgZGltKSB7XHJcblx0aWYgKCFhcnIgfHwgYXJyLmxlbmd0aCA9PSBudWxsKSB0aHJvdyBFcnJvcignQXJndW1lbnQgc2hvdWxkIGJlIGFuIGFycmF5JylcclxuXHJcblx0aWYgKGRpbSA9PSBudWxsKSBkaW0gPSAxXHJcblx0ZWxzZSBkaW0gPSBNYXRoLmZsb29yKGRpbSlcclxuXHJcblx0dmFyIGJvdW5kcyA9IEFycmF5KGRpbSAqIDIpXHJcblxyXG5cdGZvciAodmFyIG9mZnNldCA9IDA7IG9mZnNldCA8IGRpbTsgb2Zmc2V0KyspIHtcclxuXHRcdHZhciBtYXggPSAtSW5maW5pdHksIG1pbiA9IEluZmluaXR5LCBpID0gb2Zmc2V0LCBsID0gYXJyLmxlbmd0aDtcclxuXHJcblx0XHRmb3IgKDsgaSA8IGw7IGkrPWRpbSkge1xyXG5cdFx0XHRpZiAoYXJyW2ldID4gbWF4KSBtYXggPSBhcnJbaV07XHJcblx0XHRcdGlmIChhcnJbaV0gPCBtaW4pIG1pbiA9IGFycltpXTtcclxuXHRcdH1cclxuXHJcblx0XHRib3VuZHNbb2Zmc2V0XSA9IG1pblxyXG5cdFx0Ym91bmRzW2RpbSArIG9mZnNldF0gPSBtYXhcclxuXHR9XHJcblxyXG5cdHJldHVybiBib3VuZHM7XHJcbn1cclxuXG59LHt9XSw2NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcclxuXHJcbnZhciBnZXRCb3VuZHMgPSBfZGVyZXFfKCdhcnJheS1ib3VuZHMnKVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBub3JtYWxpemU7XHJcblxyXG5mdW5jdGlvbiBub3JtYWxpemUgKGFyciwgZGltLCBib3VuZHMpIHtcclxuXHRpZiAoIWFyciB8fCBhcnIubGVuZ3RoID09IG51bGwpIHRocm93IEVycm9yKCdBcmd1bWVudCBzaG91bGQgYmUgYW4gYXJyYXknKVxyXG5cclxuXHRpZiAoZGltID09IG51bGwpIGRpbSA9IDFcclxuXHRpZiAoYm91bmRzID09IG51bGwpIGJvdW5kcyA9IGdldEJvdW5kcyhhcnIsIGRpbSlcclxuXHJcblx0Zm9yICh2YXIgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgZGltOyBvZmZzZXQrKykge1xyXG5cdFx0dmFyIG1heCA9IGJvdW5kc1tkaW0gKyBvZmZzZXRdLCBtaW4gPSBib3VuZHNbb2Zmc2V0XSwgaSA9IG9mZnNldCwgbCA9IGFyci5sZW5ndGg7XHJcblxyXG5cdFx0aWYgKG1heCA9PT0gSW5maW5pdHkgJiYgbWluID09PSAtSW5maW5pdHkpIHtcclxuXHRcdFx0Zm9yIChpID0gb2Zmc2V0OyBpIDwgbDsgaSs9ZGltKSB7XHJcblx0XHRcdFx0YXJyW2ldID0gYXJyW2ldID09PSBtYXggPyAxIDogYXJyW2ldID09PSBtaW4gPyAwIDogLjVcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSBpZiAobWF4ID09PSBJbmZpbml0eSkge1xyXG5cdFx0XHRmb3IgKGkgPSBvZmZzZXQ7IGkgPCBsOyBpKz1kaW0pIHtcclxuXHRcdFx0XHRhcnJbaV0gPSBhcnJbaV0gPT09IG1heCA/IDEgOiAwXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdGVsc2UgaWYgKG1pbiA9PT0gLUluZmluaXR5KSB7XHJcblx0XHRcdGZvciAoaSA9IG9mZnNldDsgaSA8IGw7IGkrPWRpbSkge1xyXG5cdFx0XHRcdGFycltpXSA9IGFycltpXSA9PT0gbWluID8gMCA6IDFcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSB7XHJcblx0XHRcdHZhciByYW5nZSA9IG1heCAtIG1pblxyXG5cdFx0XHRmb3IgKGkgPSBvZmZzZXQ7IGkgPCBsOyBpKz1kaW0pIHtcclxuXHRcdFx0XHRhcnJbaV0gPSByYW5nZSA9PT0gMCA/IC41IDogKGFycltpXSAtIG1pbikgLyByYW5nZVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gYXJyO1xyXG59XHJcblxufSx7XCJhcnJheS1ib3VuZHNcIjo2NX1dLDY3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBuZXdBcnJheShzdGFydCwgZW5kKSB7XG4gICAgdmFyIG4wID0gdHlwZW9mIHN0YXJ0ID09PSAnbnVtYmVyJyxcbiAgICAgICAgbjEgPSB0eXBlb2YgZW5kID09PSAnbnVtYmVyJ1xuXG4gICAgaWYgKG4wICYmICFuMSkge1xuICAgICAgICBlbmQgPSBzdGFydFxuICAgICAgICBzdGFydCA9IDBcbiAgICB9IGVsc2UgaWYgKCFuMCAmJiAhbjEpIHtcbiAgICAgICAgc3RhcnQgPSAwXG4gICAgICAgIGVuZCA9IDBcbiAgICB9XG5cbiAgICBzdGFydCA9IHN0YXJ0fDBcbiAgICBlbmQgPSBlbmR8MFxuICAgIHZhciBsZW4gPSBlbmQtc3RhcnRcbiAgICBpZiAobGVuPDApXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYXJyYXkgbGVuZ3RoIG11c3QgYmUgcG9zaXRpdmUnKVxuICAgIFxuICAgIHZhciBhID0gbmV3IEFycmF5KGxlbilcbiAgICBmb3IgKHZhciBpPTAsIGM9c3RhcnQ7IGk8bGVuOyBpKyssIGMrKylcbiAgICAgICAgYVtpXSA9IGNcbiAgICByZXR1cm4gYVxufVxufSx7fV0sNjg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuKGZ1bmN0aW9uIChnbG9iYWwpe1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgb2JqZWN0QXNzaWduID0gX2RlcmVxXygnb2JqZWN0LWFzc2lnbicpO1xuXG4vLyBjb21wYXJlIGFuZCBpc0J1ZmZlciB0YWtlbiBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL2Jsb2IvNjgwZTllNWU0ODhmMjJhYWMyNzU5OWE1N2RjODQ0YTYzMTU5MjhkZC9pbmRleC5qc1xuLy8gb3JpZ2luYWwgbm90aWNlOlxuXG4vKiFcbiAqIFRoZSBidWZmZXIgbW9kdWxlIGZyb20gbm9kZS5qcywgZm9yIHRoZSBicm93c2VyLlxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxmZXJvc3NAZmVyb3NzLm9yZz4gPGh0dHA6Ly9mZXJvc3Mub3JnPlxuICogQGxpY2Vuc2UgIE1JVFxuICovXG5mdW5jdGlvbiBjb21wYXJlKGEsIGIpIHtcbiAgaWYgKGEgPT09IGIpIHtcbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIHZhciB4ID0gYS5sZW5ndGg7XG4gIHZhciB5ID0gYi5sZW5ndGg7XG5cbiAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IE1hdGgubWluKHgsIHkpOyBpIDwgbGVuOyArK2kpIHtcbiAgICBpZiAoYVtpXSAhPT0gYltpXSkge1xuICAgICAgeCA9IGFbaV07XG4gICAgICB5ID0gYltpXTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGlmICh4IDwgeSkge1xuICAgIHJldHVybiAtMTtcbiAgfVxuICBpZiAoeSA8IHgpIHtcbiAgICByZXR1cm4gMTtcbiAgfVxuICByZXR1cm4gMDtcbn1cbmZ1bmN0aW9uIGlzQnVmZmVyKGIpIHtcbiAgaWYgKGdsb2JhbC5CdWZmZXIgJiYgdHlwZW9mIGdsb2JhbC5CdWZmZXIuaXNCdWZmZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZ2xvYmFsLkJ1ZmZlci5pc0J1ZmZlcihiKTtcbiAgfVxuICByZXR1cm4gISEoYiAhPSBudWxsICYmIGIuX2lzQnVmZmVyKTtcbn1cblxuLy8gYmFzZWQgb24gbm9kZSBhc3NlcnQsIG9yaWdpbmFsIG5vdGljZTpcbi8vIE5COiBUaGUgVVJMIHRvIHRoZSBDb21tb25KUyBzcGVjIGlzIGtlcHQganVzdCBmb3IgdHJhZGl0aW9uLlxuLy8gICAgIG5vZGUtYXNzZXJ0IGhhcyBldm9sdmVkIGEgbG90IHNpbmNlIHRoZW4sIGJvdGggaW4gQVBJIGFuZCBiZWhhdmlvci5cblxuLy8gaHR0cDovL3dpa2kuY29tbW9uanMub3JnL3dpa2kvVW5pdF9UZXN0aW5nLzEuMFxuLy9cbi8vIFRISVMgSVMgTk9UIFRFU1RFRCBOT1IgTElLRUxZIFRPIFdPUksgT1VUU0lERSBWOCFcbi8vXG4vLyBPcmlnaW5hbGx5IGZyb20gbmFyd2hhbC5qcyAoaHR0cDovL25hcndoYWxqcy5vcmcpXG4vLyBDb3B5cmlnaHQgKGMpIDIwMDkgVGhvbWFzIFJvYmluc29uIDwyODBub3J0aC5jb20+XG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgJ1NvZnR3YXJlJyksIHRvXG4vLyBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZVxuLy8gcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICdBUyBJUycsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTlxuLy8gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTlxuLy8gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbnZhciB1dGlsID0gX2RlcmVxXygndXRpbC8nKTtcbnZhciBoYXNPd24gPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O1xudmFyIHBTbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcbnZhciBmdW5jdGlvbnNIYXZlTmFtZXMgPSAoZnVuY3Rpb24gKCkge1xuICByZXR1cm4gZnVuY3Rpb24gZm9vKCkge30ubmFtZSA9PT0gJ2Zvbyc7XG59KCkpO1xuZnVuY3Rpb24gcFRvU3RyaW5nIChvYmopIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopO1xufVxuZnVuY3Rpb24gaXNWaWV3KGFycmJ1Zikge1xuICBpZiAoaXNCdWZmZXIoYXJyYnVmKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAodHlwZW9mIGdsb2JhbC5BcnJheUJ1ZmZlciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAodHlwZW9mIEFycmF5QnVmZmVyLmlzVmlldyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBBcnJheUJ1ZmZlci5pc1ZpZXcoYXJyYnVmKTtcbiAgfVxuICBpZiAoIWFycmJ1Zikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoYXJyYnVmIGluc3RhbmNlb2YgRGF0YVZpZXcpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBpZiAoYXJyYnVmLmJ1ZmZlciAmJiBhcnJidWYuYnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG4vLyAxLiBUaGUgYXNzZXJ0IG1vZHVsZSBwcm92aWRlcyBmdW5jdGlvbnMgdGhhdCB0aHJvd1xuLy8gQXNzZXJ0aW9uRXJyb3IncyB3aGVuIHBhcnRpY3VsYXIgY29uZGl0aW9ucyBhcmUgbm90IG1ldC4gVGhlXG4vLyBhc3NlcnQgbW9kdWxlIG11c3QgY29uZm9ybSB0byB0aGUgZm9sbG93aW5nIGludGVyZmFjZS5cblxudmFyIGFzc2VydCA9IG1vZHVsZS5leHBvcnRzID0gb2s7XG5cbi8vIDIuIFRoZSBBc3NlcnRpb25FcnJvciBpcyBkZWZpbmVkIGluIGFzc2VydC5cbi8vIG5ldyBhc3NlcnQuQXNzZXJ0aW9uRXJyb3IoeyBtZXNzYWdlOiBtZXNzYWdlLFxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdHVhbDogYWN0dWFsLFxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdGVkOiBleHBlY3RlZCB9KVxuXG52YXIgcmVnZXggPSAvXFxzKmZ1bmN0aW9uXFxzKyhbXlxcKFxcc10qKVxccyovO1xuLy8gYmFzZWQgb24gaHR0cHM6Ly9naXRodWIuY29tL2xqaGFyYi9mdW5jdGlvbi5wcm90b3R5cGUubmFtZS9ibG9iL2FkZWVlZWM4YmZjYzYwNjhiMTg3ZDdkOWZiM2Q1YmIxZDNhMzA4OTkvaW1wbGVtZW50YXRpb24uanNcbmZ1bmN0aW9uIGdldE5hbWUoZnVuYykge1xuICBpZiAoIXV0aWwuaXNGdW5jdGlvbihmdW5jKSkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoZnVuY3Rpb25zSGF2ZU5hbWVzKSB7XG4gICAgcmV0dXJuIGZ1bmMubmFtZTtcbiAgfVxuICB2YXIgc3RyID0gZnVuYy50b1N0cmluZygpO1xuICB2YXIgbWF0Y2ggPSBzdHIubWF0Y2gocmVnZXgpO1xuICByZXR1cm4gbWF0Y2ggJiYgbWF0Y2hbMV07XG59XG5hc3NlcnQuQXNzZXJ0aW9uRXJyb3IgPSBmdW5jdGlvbiBBc3NlcnRpb25FcnJvcihvcHRpb25zKSB7XG4gIHRoaXMubmFtZSA9ICdBc3NlcnRpb25FcnJvcic7XG4gIHRoaXMuYWN0dWFsID0gb3B0aW9ucy5hY3R1YWw7XG4gIHRoaXMuZXhwZWN0ZWQgPSBvcHRpb25zLmV4cGVjdGVkO1xuICB0aGlzLm9wZXJhdG9yID0gb3B0aW9ucy5vcGVyYXRvcjtcbiAgaWYgKG9wdGlvbnMubWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZSA9IG9wdGlvbnMubWVzc2FnZTtcbiAgICB0aGlzLmdlbmVyYXRlZE1lc3NhZ2UgPSBmYWxzZTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLm1lc3NhZ2UgPSBnZXRNZXNzYWdlKHRoaXMpO1xuICAgIHRoaXMuZ2VuZXJhdGVkTWVzc2FnZSA9IHRydWU7XG4gIH1cbiAgdmFyIHN0YWNrU3RhcnRGdW5jdGlvbiA9IG9wdGlvbnMuc3RhY2tTdGFydEZ1bmN0aW9uIHx8IGZhaWw7XG4gIGlmIChFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSkge1xuICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHN0YWNrU3RhcnRGdW5jdGlvbik7XG4gIH0gZWxzZSB7XG4gICAgLy8gbm9uIHY4IGJyb3dzZXJzIHNvIHdlIGNhbiBoYXZlIGEgc3RhY2t0cmFjZVxuICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcbiAgICBpZiAoZXJyLnN0YWNrKSB7XG4gICAgICB2YXIgb3V0ID0gZXJyLnN0YWNrO1xuXG4gICAgICAvLyB0cnkgdG8gc3RyaXAgdXNlbGVzcyBmcmFtZXNcbiAgICAgIHZhciBmbl9uYW1lID0gZ2V0TmFtZShzdGFja1N0YXJ0RnVuY3Rpb24pO1xuICAgICAgdmFyIGlkeCA9IG91dC5pbmRleE9mKCdcXG4nICsgZm5fbmFtZSk7XG4gICAgICBpZiAoaWR4ID49IDApIHtcbiAgICAgICAgLy8gb25jZSB3ZSBoYXZlIGxvY2F0ZWQgdGhlIGZ1bmN0aW9uIGZyYW1lXG4gICAgICAgIC8vIHdlIG5lZWQgdG8gc3RyaXAgb3V0IGV2ZXJ5dGhpbmcgYmVmb3JlIGl0IChhbmQgaXRzIGxpbmUpXG4gICAgICAgIHZhciBuZXh0X2xpbmUgPSBvdXQuaW5kZXhPZignXFxuJywgaWR4ICsgMSk7XG4gICAgICAgIG91dCA9IG91dC5zdWJzdHJpbmcobmV4dF9saW5lICsgMSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc3RhY2sgPSBvdXQ7XG4gICAgfVxuICB9XG59O1xuXG4vLyBhc3NlcnQuQXNzZXJ0aW9uRXJyb3IgaW5zdGFuY2VvZiBFcnJvclxudXRpbC5pbmhlcml0cyhhc3NlcnQuQXNzZXJ0aW9uRXJyb3IsIEVycm9yKTtcblxuZnVuY3Rpb24gdHJ1bmNhdGUocywgbikge1xuICBpZiAodHlwZW9mIHMgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHMubGVuZ3RoIDwgbiA/IHMgOiBzLnNsaWNlKDAsIG4pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBzO1xuICB9XG59XG5mdW5jdGlvbiBpbnNwZWN0KHNvbWV0aGluZykge1xuICBpZiAoZnVuY3Rpb25zSGF2ZU5hbWVzIHx8ICF1dGlsLmlzRnVuY3Rpb24oc29tZXRoaW5nKSkge1xuICAgIHJldHVybiB1dGlsLmluc3BlY3Qoc29tZXRoaW5nKTtcbiAgfVxuICB2YXIgcmF3bmFtZSA9IGdldE5hbWUoc29tZXRoaW5nKTtcbiAgdmFyIG5hbWUgPSByYXduYW1lID8gJzogJyArIHJhd25hbWUgOiAnJztcbiAgcmV0dXJuICdbRnVuY3Rpb24nICsgIG5hbWUgKyAnXSc7XG59XG5mdW5jdGlvbiBnZXRNZXNzYWdlKHNlbGYpIHtcbiAgcmV0dXJuIHRydW5jYXRlKGluc3BlY3Qoc2VsZi5hY3R1YWwpLCAxMjgpICsgJyAnICtcbiAgICAgICAgIHNlbGYub3BlcmF0b3IgKyAnICcgK1xuICAgICAgICAgdHJ1bmNhdGUoaW5zcGVjdChzZWxmLmV4cGVjdGVkKSwgMTI4KTtcbn1cblxuLy8gQXQgcHJlc2VudCBvbmx5IHRoZSB0aHJlZSBrZXlzIG1lbnRpb25lZCBhYm92ZSBhcmUgdXNlZCBhbmRcbi8vIHVuZGVyc3Rvb2QgYnkgdGhlIHNwZWMuIEltcGxlbWVudGF0aW9ucyBvciBzdWIgbW9kdWxlcyBjYW4gcGFzc1xuLy8gb3RoZXIga2V5cyB0byB0aGUgQXNzZXJ0aW9uRXJyb3IncyBjb25zdHJ1Y3RvciAtIHRoZXkgd2lsbCBiZVxuLy8gaWdub3JlZC5cblxuLy8gMy4gQWxsIG9mIHRoZSBmb2xsb3dpbmcgZnVuY3Rpb25zIG11c3QgdGhyb3cgYW4gQXNzZXJ0aW9uRXJyb3Jcbi8vIHdoZW4gYSBjb3JyZXNwb25kaW5nIGNvbmRpdGlvbiBpcyBub3QgbWV0LCB3aXRoIGEgbWVzc2FnZSB0aGF0XG4vLyBtYXkgYmUgdW5kZWZpbmVkIGlmIG5vdCBwcm92aWRlZC4gIEFsbCBhc3NlcnRpb24gbWV0aG9kcyBwcm92aWRlXG4vLyBib3RoIHRoZSBhY3R1YWwgYW5kIGV4cGVjdGVkIHZhbHVlcyB0byB0aGUgYXNzZXJ0aW9uIGVycm9yIGZvclxuLy8gZGlzcGxheSBwdXJwb3Nlcy5cblxuZnVuY3Rpb24gZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCBvcGVyYXRvciwgc3RhY2tTdGFydEZ1bmN0aW9uKSB7XG4gIHRocm93IG5ldyBhc3NlcnQuQXNzZXJ0aW9uRXJyb3Ioe1xuICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgYWN0dWFsOiBhY3R1YWwsXG4gICAgZXhwZWN0ZWQ6IGV4cGVjdGVkLFxuICAgIG9wZXJhdG9yOiBvcGVyYXRvcixcbiAgICBzdGFja1N0YXJ0RnVuY3Rpb246IHN0YWNrU3RhcnRGdW5jdGlvblxuICB9KTtcbn1cblxuLy8gRVhURU5TSU9OISBhbGxvd3MgZm9yIHdlbGwgYmVoYXZlZCBlcnJvcnMgZGVmaW5lZCBlbHNld2hlcmUuXG5hc3NlcnQuZmFpbCA9IGZhaWw7XG5cbi8vIDQuIFB1cmUgYXNzZXJ0aW9uIHRlc3RzIHdoZXRoZXIgYSB2YWx1ZSBpcyB0cnV0aHksIGFzIGRldGVybWluZWRcbi8vIGJ5ICEhZ3VhcmQuXG4vLyBhc3NlcnQub2soZ3VhcmQsIG1lc3NhZ2Vfb3B0KTtcbi8vIFRoaXMgc3RhdGVtZW50IGlzIGVxdWl2YWxlbnQgdG8gYXNzZXJ0LmVxdWFsKHRydWUsICEhZ3VhcmQsXG4vLyBtZXNzYWdlX29wdCk7LiBUbyB0ZXN0IHN0cmljdGx5IGZvciB0aGUgdmFsdWUgdHJ1ZSwgdXNlXG4vLyBhc3NlcnQuc3RyaWN0RXF1YWwodHJ1ZSwgZ3VhcmQsIG1lc3NhZ2Vfb3B0KTsuXG5cbmZ1bmN0aW9uIG9rKHZhbHVlLCBtZXNzYWdlKSB7XG4gIGlmICghdmFsdWUpIGZhaWwodmFsdWUsIHRydWUsIG1lc3NhZ2UsICc9PScsIGFzc2VydC5vayk7XG59XG5hc3NlcnQub2sgPSBvaztcblxuLy8gNS4gVGhlIGVxdWFsaXR5IGFzc2VydGlvbiB0ZXN0cyBzaGFsbG93LCBjb2VyY2l2ZSBlcXVhbGl0eSB3aXRoXG4vLyA9PS5cbi8vIGFzc2VydC5lcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlX29wdCk7XG5cbmFzc2VydC5lcXVhbCA9IGZ1bmN0aW9uIGVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UpIHtcbiAgaWYgKGFjdHVhbCAhPSBleHBlY3RlZCkgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCAnPT0nLCBhc3NlcnQuZXF1YWwpO1xufTtcblxuLy8gNi4gVGhlIG5vbi1lcXVhbGl0eSBhc3NlcnRpb24gdGVzdHMgZm9yIHdoZXRoZXIgdHdvIG9iamVjdHMgYXJlIG5vdCBlcXVhbFxuLy8gd2l0aCAhPSBhc3NlcnQubm90RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZV9vcHQpO1xuXG5hc3NlcnQubm90RXF1YWwgPSBmdW5jdGlvbiBub3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG4gIGlmIChhY3R1YWwgPT0gZXhwZWN0ZWQpIHtcbiAgICBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsICchPScsIGFzc2VydC5ub3RFcXVhbCk7XG4gIH1cbn07XG5cbi8vIDcuIFRoZSBlcXVpdmFsZW5jZSBhc3NlcnRpb24gdGVzdHMgYSBkZWVwIGVxdWFsaXR5IHJlbGF0aW9uLlxuLy8gYXNzZXJ0LmRlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlX29wdCk7XG5cbmFzc2VydC5kZWVwRXF1YWwgPSBmdW5jdGlvbiBkZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSkge1xuICBpZiAoIV9kZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgZmFsc2UpKSB7XG4gICAgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCAnZGVlcEVxdWFsJywgYXNzZXJ0LmRlZXBFcXVhbCk7XG4gIH1cbn07XG5cbmFzc2VydC5kZWVwU3RyaWN0RXF1YWwgPSBmdW5jdGlvbiBkZWVwU3RyaWN0RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSkge1xuICBpZiAoIV9kZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgdHJ1ZSkpIHtcbiAgICBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsICdkZWVwU3RyaWN0RXF1YWwnLCBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKTtcbiAgfVxufTtcblxuZnVuY3Rpb24gX2RlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBzdHJpY3QsIG1lbW9zKSB7XG4gIC8vIDcuMS4gQWxsIGlkZW50aWNhbCB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGFzIGRldGVybWluZWQgYnkgPT09LlxuICBpZiAoYWN0dWFsID09PSBleHBlY3RlZCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9IGVsc2UgaWYgKGlzQnVmZmVyKGFjdHVhbCkgJiYgaXNCdWZmZXIoZXhwZWN0ZWQpKSB7XG4gICAgcmV0dXJuIGNvbXBhcmUoYWN0dWFsLCBleHBlY3RlZCkgPT09IDA7XG5cbiAgLy8gNy4yLiBJZiB0aGUgZXhwZWN0ZWQgdmFsdWUgaXMgYSBEYXRlIG9iamVjdCwgdGhlIGFjdHVhbCB2YWx1ZSBpc1xuICAvLyBlcXVpdmFsZW50IGlmIGl0IGlzIGFsc28gYSBEYXRlIG9iamVjdCB0aGF0IHJlZmVycyB0byB0aGUgc2FtZSB0aW1lLlxuICB9IGVsc2UgaWYgKHV0aWwuaXNEYXRlKGFjdHVhbCkgJiYgdXRpbC5pc0RhdGUoZXhwZWN0ZWQpKSB7XG4gICAgcmV0dXJuIGFjdHVhbC5nZXRUaW1lKCkgPT09IGV4cGVjdGVkLmdldFRpbWUoKTtcblxuICAvLyA3LjMgSWYgdGhlIGV4cGVjdGVkIHZhbHVlIGlzIGEgUmVnRXhwIG9iamVjdCwgdGhlIGFjdHVhbCB2YWx1ZSBpc1xuICAvLyBlcXVpdmFsZW50IGlmIGl0IGlzIGFsc28gYSBSZWdFeHAgb2JqZWN0IHdpdGggdGhlIHNhbWUgc291cmNlIGFuZFxuICAvLyBwcm9wZXJ0aWVzIChgZ2xvYmFsYCwgYG11bHRpbGluZWAsIGBsYXN0SW5kZXhgLCBgaWdub3JlQ2FzZWApLlxuICB9IGVsc2UgaWYgKHV0aWwuaXNSZWdFeHAoYWN0dWFsKSAmJiB1dGlsLmlzUmVnRXhwKGV4cGVjdGVkKSkge1xuICAgIHJldHVybiBhY3R1YWwuc291cmNlID09PSBleHBlY3RlZC5zb3VyY2UgJiZcbiAgICAgICAgICAgYWN0dWFsLmdsb2JhbCA9PT0gZXhwZWN0ZWQuZ2xvYmFsICYmXG4gICAgICAgICAgIGFjdHVhbC5tdWx0aWxpbmUgPT09IGV4cGVjdGVkLm11bHRpbGluZSAmJlxuICAgICAgICAgICBhY3R1YWwubGFzdEluZGV4ID09PSBleHBlY3RlZC5sYXN0SW5kZXggJiZcbiAgICAgICAgICAgYWN0dWFsLmlnbm9yZUNhc2UgPT09IGV4cGVjdGVkLmlnbm9yZUNhc2U7XG5cbiAgLy8gNy40LiBPdGhlciBwYWlycyB0aGF0IGRvIG5vdCBib3RoIHBhc3MgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnLFxuICAvLyBlcXVpdmFsZW5jZSBpcyBkZXRlcm1pbmVkIGJ5ID09LlxuICB9IGVsc2UgaWYgKChhY3R1YWwgPT09IG51bGwgfHwgdHlwZW9mIGFjdHVhbCAhPT0gJ29iamVjdCcpICYmXG4gICAgICAgICAgICAgKGV4cGVjdGVkID09PSBudWxsIHx8IHR5cGVvZiBleHBlY3RlZCAhPT0gJ29iamVjdCcpKSB7XG4gICAgcmV0dXJuIHN0cmljdCA/IGFjdHVhbCA9PT0gZXhwZWN0ZWQgOiBhY3R1YWwgPT0gZXhwZWN0ZWQ7XG5cbiAgLy8gSWYgYm90aCB2YWx1ZXMgYXJlIGluc3RhbmNlcyBvZiB0eXBlZCBhcnJheXMsIHdyYXAgdGhlaXIgdW5kZXJseWluZ1xuICAvLyBBcnJheUJ1ZmZlcnMgaW4gYSBCdWZmZXIgZWFjaCB0byBpbmNyZWFzZSBwZXJmb3JtYW5jZVxuICAvLyBUaGlzIG9wdGltaXphdGlvbiByZXF1aXJlcyB0aGUgYXJyYXlzIHRvIGhhdmUgdGhlIHNhbWUgdHlwZSBhcyBjaGVja2VkIGJ5XG4gIC8vIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcgKGFrYSBwVG9TdHJpbmcpLiBOZXZlciBwZXJmb3JtIGJpbmFyeVxuICAvLyBjb21wYXJpc29ucyBmb3IgRmxvYXQqQXJyYXlzLCB0aG91Z2gsIHNpbmNlIGUuZy4gKzAgPT09IC0wIGJ1dCB0aGVpclxuICAvLyBiaXQgcGF0dGVybnMgYXJlIG5vdCBpZGVudGljYWwuXG4gIH0gZWxzZSBpZiAoaXNWaWV3KGFjdHVhbCkgJiYgaXNWaWV3KGV4cGVjdGVkKSAmJlxuICAgICAgICAgICAgIHBUb1N0cmluZyhhY3R1YWwpID09PSBwVG9TdHJpbmcoZXhwZWN0ZWQpICYmXG4gICAgICAgICAgICAgIShhY3R1YWwgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkgfHxcbiAgICAgICAgICAgICAgIGFjdHVhbCBpbnN0YW5jZW9mIEZsb2F0NjRBcnJheSkpIHtcbiAgICByZXR1cm4gY29tcGFyZShuZXcgVWludDhBcnJheShhY3R1YWwuYnVmZmVyKSxcbiAgICAgICAgICAgICAgICAgICBuZXcgVWludDhBcnJheShleHBlY3RlZC5idWZmZXIpKSA9PT0gMDtcblxuICAvLyA3LjUgRm9yIGFsbCBvdGhlciBPYmplY3QgcGFpcnMsIGluY2x1ZGluZyBBcnJheSBvYmplY3RzLCBlcXVpdmFsZW5jZSBpc1xuICAvLyBkZXRlcm1pbmVkIGJ5IGhhdmluZyB0aGUgc2FtZSBudW1iZXIgb2Ygb3duZWQgcHJvcGVydGllcyAoYXMgdmVyaWZpZWRcbiAgLy8gd2l0aCBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwpLCB0aGUgc2FtZSBzZXQgb2Yga2V5c1xuICAvLyAoYWx0aG91Z2ggbm90IG5lY2Vzc2FyaWx5IHRoZSBzYW1lIG9yZGVyKSwgZXF1aXZhbGVudCB2YWx1ZXMgZm9yIGV2ZXJ5XG4gIC8vIGNvcnJlc3BvbmRpbmcga2V5LCBhbmQgYW4gaWRlbnRpY2FsICdwcm90b3R5cGUnIHByb3BlcnR5LiBOb3RlOiB0aGlzXG4gIC8vIGFjY291bnRzIGZvciBib3RoIG5hbWVkIGFuZCBpbmRleGVkIHByb3BlcnRpZXMgb24gQXJyYXlzLlxuICB9IGVsc2UgaWYgKGlzQnVmZmVyKGFjdHVhbCkgIT09IGlzQnVmZmVyKGV4cGVjdGVkKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfSBlbHNlIHtcbiAgICBtZW1vcyA9IG1lbW9zIHx8IHthY3R1YWw6IFtdLCBleHBlY3RlZDogW119O1xuXG4gICAgdmFyIGFjdHVhbEluZGV4ID0gbWVtb3MuYWN0dWFsLmluZGV4T2YoYWN0dWFsKTtcbiAgICBpZiAoYWN0dWFsSW5kZXggIT09IC0xKSB7XG4gICAgICBpZiAoYWN0dWFsSW5kZXggPT09IG1lbW9zLmV4cGVjdGVkLmluZGV4T2YoZXhwZWN0ZWQpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIG1lbW9zLmFjdHVhbC5wdXNoKGFjdHVhbCk7XG4gICAgbWVtb3MuZXhwZWN0ZWQucHVzaChleHBlY3RlZCk7XG5cbiAgICByZXR1cm4gb2JqRXF1aXYoYWN0dWFsLCBleHBlY3RlZCwgc3RyaWN0LCBtZW1vcyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNBcmd1bWVudHMob2JqZWN0KSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqZWN0KSA9PSAnW29iamVjdCBBcmd1bWVudHNdJztcbn1cblxuZnVuY3Rpb24gb2JqRXF1aXYoYSwgYiwgc3RyaWN0LCBhY3R1YWxWaXNpdGVkT2JqZWN0cykge1xuICBpZiAoYSA9PT0gbnVsbCB8fCBhID09PSB1bmRlZmluZWQgfHwgYiA9PT0gbnVsbCB8fCBiID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIGZhbHNlO1xuICAvLyBpZiBvbmUgaXMgYSBwcmltaXRpdmUsIHRoZSBvdGhlciBtdXN0IGJlIHNhbWVcbiAgaWYgKHV0aWwuaXNQcmltaXRpdmUoYSkgfHwgdXRpbC5pc1ByaW1pdGl2ZShiKSlcbiAgICByZXR1cm4gYSA9PT0gYjtcbiAgaWYgKHN0cmljdCAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkgIT09IE9iamVjdC5nZXRQcm90b3R5cGVPZihiKSlcbiAgICByZXR1cm4gZmFsc2U7XG4gIHZhciBhSXNBcmdzID0gaXNBcmd1bWVudHMoYSk7XG4gIHZhciBiSXNBcmdzID0gaXNBcmd1bWVudHMoYik7XG4gIGlmICgoYUlzQXJncyAmJiAhYklzQXJncykgfHwgKCFhSXNBcmdzICYmIGJJc0FyZ3MpKVxuICAgIHJldHVybiBmYWxzZTtcbiAgaWYgKGFJc0FyZ3MpIHtcbiAgICBhID0gcFNsaWNlLmNhbGwoYSk7XG4gICAgYiA9IHBTbGljZS5jYWxsKGIpO1xuICAgIHJldHVybiBfZGVlcEVxdWFsKGEsIGIsIHN0cmljdCk7XG4gIH1cbiAgdmFyIGthID0gb2JqZWN0S2V5cyhhKTtcbiAgdmFyIGtiID0gb2JqZWN0S2V5cyhiKTtcbiAgdmFyIGtleSwgaTtcbiAgLy8gaGF2aW5nIHRoZSBzYW1lIG51bWJlciBvZiBvd25lZCBwcm9wZXJ0aWVzIChrZXlzIGluY29ycG9yYXRlc1xuICAvLyBoYXNPd25Qcm9wZXJ0eSlcbiAgaWYgKGthLmxlbmd0aCAhPT0ga2IubGVuZ3RoKVxuICAgIHJldHVybiBmYWxzZTtcbiAgLy90aGUgc2FtZSBzZXQgb2Yga2V5cyAoYWx0aG91Z2ggbm90IG5lY2Vzc2FyaWx5IHRoZSBzYW1lIG9yZGVyKSxcbiAga2Euc29ydCgpO1xuICBrYi5zb3J0KCk7XG4gIC8vfn5+Y2hlYXAga2V5IHRlc3RcbiAgZm9yIChpID0ga2EubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAoa2FbaV0gIT09IGtiW2ldKVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIC8vZXF1aXZhbGVudCB2YWx1ZXMgZm9yIGV2ZXJ5IGNvcnJlc3BvbmRpbmcga2V5LCBhbmRcbiAgLy9+fn5wb3NzaWJseSBleHBlbnNpdmUgZGVlcCB0ZXN0XG4gIGZvciAoaSA9IGthLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAga2V5ID0ga2FbaV07XG4gICAgaWYgKCFfZGVlcEVxdWFsKGFba2V5XSwgYltrZXldLCBzdHJpY3QsIGFjdHVhbFZpc2l0ZWRPYmplY3RzKSlcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuLy8gOC4gVGhlIG5vbi1lcXVpdmFsZW5jZSBhc3NlcnRpb24gdGVzdHMgZm9yIGFueSBkZWVwIGluZXF1YWxpdHkuXG4vLyBhc3NlcnQubm90RGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2Vfb3B0KTtcblxuYXNzZXJ0Lm5vdERlZXBFcXVhbCA9IGZ1bmN0aW9uIG5vdERlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG4gIGlmIChfZGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIGZhbHNlKSkge1xuICAgIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSwgJ25vdERlZXBFcXVhbCcsIGFzc2VydC5ub3REZWVwRXF1YWwpO1xuICB9XG59O1xuXG5hc3NlcnQubm90RGVlcFN0cmljdEVxdWFsID0gbm90RGVlcFN0cmljdEVxdWFsO1xuZnVuY3Rpb24gbm90RGVlcFN0cmljdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UpIHtcbiAgaWYgKF9kZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgdHJ1ZSkpIHtcbiAgICBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsICdub3REZWVwU3RyaWN0RXF1YWwnLCBub3REZWVwU3RyaWN0RXF1YWwpO1xuICB9XG59XG5cblxuLy8gOS4gVGhlIHN0cmljdCBlcXVhbGl0eSBhc3NlcnRpb24gdGVzdHMgc3RyaWN0IGVxdWFsaXR5LCBhcyBkZXRlcm1pbmVkIGJ5ID09PS5cbi8vIGFzc2VydC5zdHJpY3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlX29wdCk7XG5cbmFzc2VydC5zdHJpY3RFcXVhbCA9IGZ1bmN0aW9uIHN0cmljdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UpIHtcbiAgaWYgKGFjdHVhbCAhPT0gZXhwZWN0ZWQpIHtcbiAgICBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsICc9PT0nLCBhc3NlcnQuc3RyaWN0RXF1YWwpO1xuICB9XG59O1xuXG4vLyAxMC4gVGhlIHN0cmljdCBub24tZXF1YWxpdHkgYXNzZXJ0aW9uIHRlc3RzIGZvciBzdHJpY3QgaW5lcXVhbGl0eSwgYXNcbi8vIGRldGVybWluZWQgYnkgIT09LiAgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2Vfb3B0KTtcblxuYXNzZXJ0Lm5vdFN0cmljdEVxdWFsID0gZnVuY3Rpb24gbm90U3RyaWN0RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSkge1xuICBpZiAoYWN0dWFsID09PSBleHBlY3RlZCkge1xuICAgIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSwgJyE9PScsIGFzc2VydC5ub3RTdHJpY3RFcXVhbCk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGV4cGVjdGVkRXhjZXB0aW9uKGFjdHVhbCwgZXhwZWN0ZWQpIHtcbiAgaWYgKCFhY3R1YWwgfHwgIWV4cGVjdGVkKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChleHBlY3RlZCkgPT0gJ1tvYmplY3QgUmVnRXhwXScpIHtcbiAgICByZXR1cm4gZXhwZWN0ZWQudGVzdChhY3R1YWwpO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBpZiAoYWN0dWFsIGluc3RhbmNlb2YgZXhwZWN0ZWQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vIElnbm9yZS4gIFRoZSBpbnN0YW5jZW9mIGNoZWNrIGRvZXNuJ3Qgd29yayBmb3IgYXJyb3cgZnVuY3Rpb25zLlxuICB9XG5cbiAgaWYgKEVycm9yLmlzUHJvdG90eXBlT2YoZXhwZWN0ZWQpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIGV4cGVjdGVkLmNhbGwoe30sIGFjdHVhbCkgPT09IHRydWU7XG59XG5cbmZ1bmN0aW9uIF90cnlCbG9jayhibG9jaykge1xuICB2YXIgZXJyb3I7XG4gIHRyeSB7XG4gICAgYmxvY2soKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGVycm9yID0gZTtcbiAgfVxuICByZXR1cm4gZXJyb3I7XG59XG5cbmZ1bmN0aW9uIF90aHJvd3Moc2hvdWxkVGhyb3csIGJsb2NrLCBleHBlY3RlZCwgbWVzc2FnZSkge1xuICB2YXIgYWN0dWFsO1xuXG4gIGlmICh0eXBlb2YgYmxvY2sgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImJsb2NrXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gIH1cblxuICBpZiAodHlwZW9mIGV4cGVjdGVkID09PSAnc3RyaW5nJykge1xuICAgIG1lc3NhZ2UgPSBleHBlY3RlZDtcbiAgICBleHBlY3RlZCA9IG51bGw7XG4gIH1cblxuICBhY3R1YWwgPSBfdHJ5QmxvY2soYmxvY2spO1xuXG4gIG1lc3NhZ2UgPSAoZXhwZWN0ZWQgJiYgZXhwZWN0ZWQubmFtZSA/ICcgKCcgKyBleHBlY3RlZC5uYW1lICsgJykuJyA6ICcuJykgK1xuICAgICAgICAgICAgKG1lc3NhZ2UgPyAnICcgKyBtZXNzYWdlIDogJy4nKTtcblxuICBpZiAoc2hvdWxkVGhyb3cgJiYgIWFjdHVhbCkge1xuICAgIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgJ01pc3NpbmcgZXhwZWN0ZWQgZXhjZXB0aW9uJyArIG1lc3NhZ2UpO1xuICB9XG5cbiAgdmFyIHVzZXJQcm92aWRlZE1lc3NhZ2UgPSB0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZyc7XG4gIHZhciBpc1Vud2FudGVkRXhjZXB0aW9uID0gIXNob3VsZFRocm93ICYmIHV0aWwuaXNFcnJvcihhY3R1YWwpO1xuICB2YXIgaXNVbmV4cGVjdGVkRXhjZXB0aW9uID0gIXNob3VsZFRocm93ICYmIGFjdHVhbCAmJiAhZXhwZWN0ZWQ7XG5cbiAgaWYgKChpc1Vud2FudGVkRXhjZXB0aW9uICYmXG4gICAgICB1c2VyUHJvdmlkZWRNZXNzYWdlICYmXG4gICAgICBleHBlY3RlZEV4Y2VwdGlvbihhY3R1YWwsIGV4cGVjdGVkKSkgfHxcbiAgICAgIGlzVW5leHBlY3RlZEV4Y2VwdGlvbikge1xuICAgIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgJ0dvdCB1bndhbnRlZCBleGNlcHRpb24nICsgbWVzc2FnZSk7XG4gIH1cblxuICBpZiAoKHNob3VsZFRocm93ICYmIGFjdHVhbCAmJiBleHBlY3RlZCAmJlxuICAgICAgIWV4cGVjdGVkRXhjZXB0aW9uKGFjdHVhbCwgZXhwZWN0ZWQpKSB8fCAoIXNob3VsZFRocm93ICYmIGFjdHVhbCkpIHtcbiAgICB0aHJvdyBhY3R1YWw7XG4gIH1cbn1cblxuLy8gMTEuIEV4cGVjdGVkIHRvIHRocm93IGFuIGVycm9yOlxuLy8gYXNzZXJ0LnRocm93cyhibG9jaywgRXJyb3Jfb3B0LCBtZXNzYWdlX29wdCk7XG5cbmFzc2VydC50aHJvd3MgPSBmdW5jdGlvbihibG9jaywgLypvcHRpb25hbCovZXJyb3IsIC8qb3B0aW9uYWwqL21lc3NhZ2UpIHtcbiAgX3Rocm93cyh0cnVlLCBibG9jaywgZXJyb3IsIG1lc3NhZ2UpO1xufTtcblxuLy8gRVhURU5TSU9OISBUaGlzIGlzIGFubm95aW5nIHRvIHdyaXRlIG91dHNpZGUgdGhpcyBtb2R1bGUuXG5hc3NlcnQuZG9lc05vdFRocm93ID0gZnVuY3Rpb24oYmxvY2ssIC8qb3B0aW9uYWwqL2Vycm9yLCAvKm9wdGlvbmFsKi9tZXNzYWdlKSB7XG4gIF90aHJvd3MoZmFsc2UsIGJsb2NrLCBlcnJvciwgbWVzc2FnZSk7XG59O1xuXG5hc3NlcnQuaWZFcnJvciA9IGZ1bmN0aW9uKGVycikgeyBpZiAoZXJyKSB0aHJvdyBlcnI7IH07XG5cbi8vIEV4cG9zZSBhIHN0cmljdCBvbmx5IHZhcmlhbnQgb2YgYXNzZXJ0XG5mdW5jdGlvbiBzdHJpY3QodmFsdWUsIG1lc3NhZ2UpIHtcbiAgaWYgKCF2YWx1ZSkgZmFpbCh2YWx1ZSwgdHJ1ZSwgbWVzc2FnZSwgJz09Jywgc3RyaWN0KTtcbn1cbmFzc2VydC5zdHJpY3QgPSBvYmplY3RBc3NpZ24oc3RyaWN0LCBhc3NlcnQsIHtcbiAgZXF1YWw6IGFzc2VydC5zdHJpY3RFcXVhbCxcbiAgZGVlcEVxdWFsOiBhc3NlcnQuZGVlcFN0cmljdEVxdWFsLFxuICBub3RFcXVhbDogYXNzZXJ0Lm5vdFN0cmljdEVxdWFsLFxuICBub3REZWVwRXF1YWw6IGFzc2VydC5ub3REZWVwU3RyaWN0RXF1YWxcbn0pO1xuYXNzZXJ0LnN0cmljdC5zdHJpY3QgPSBhc3NlcnQuc3RyaWN0O1xuXG52YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIChvYmopIHtcbiAgdmFyIGtleXMgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgIGlmIChoYXNPd24uY2FsbChvYmosIGtleSkpIGtleXMucHVzaChrZXkpO1xuICB9XG4gIHJldHVybiBrZXlzO1xufTtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pXG59LHtcIm9iamVjdC1hc3NpZ25cIjo0NTQsXCJ1dGlsL1wiOjcxfV0sNjk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuaWYgKHR5cGVvZiBPYmplY3QuY3JlYXRlID09PSAnZnVuY3Rpb24nKSB7XG4gIC8vIGltcGxlbWVudGF0aW9uIGZyb20gc3RhbmRhcmQgbm9kZS5qcyAndXRpbCcgbW9kdWxlXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICBjdG9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoc3VwZXJDdG9yLnByb3RvdHlwZSwge1xuICAgICAgY29uc3RydWN0b3I6IHtcbiAgICAgICAgdmFsdWU6IGN0b3IsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICB9XG4gICAgfSk7XG4gIH07XG59IGVsc2Uge1xuICAvLyBvbGQgc2Nob29sIHNoaW0gZm9yIG9sZCBicm93c2Vyc1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgdmFyIFRlbXBDdG9yID0gZnVuY3Rpb24gKCkge31cbiAgICBUZW1wQ3Rvci5wcm90b3R5cGUgPSBzdXBlckN0b3IucHJvdG90eXBlXG4gICAgY3Rvci5wcm90b3R5cGUgPSBuZXcgVGVtcEN0b3IoKVxuICAgIGN0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY3RvclxuICB9XG59XG5cbn0se31dLDcwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNCdWZmZXIoYXJnKSB7XG4gIHJldHVybiBhcmcgJiYgdHlwZW9mIGFyZyA9PT0gJ29iamVjdCdcbiAgICAmJiB0eXBlb2YgYXJnLmNvcHkgPT09ICdmdW5jdGlvbidcbiAgICAmJiB0eXBlb2YgYXJnLmZpbGwgPT09ICdmdW5jdGlvbidcbiAgICAmJiB0eXBlb2YgYXJnLnJlYWRVSW50OCA9PT0gJ2Z1bmN0aW9uJztcbn1cbn0se31dLDcxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbihmdW5jdGlvbiAocHJvY2VzcyxnbG9iYWwpe1xuLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbnZhciBmb3JtYXRSZWdFeHAgPSAvJVtzZGolXS9nO1xuZXhwb3J0cy5mb3JtYXQgPSBmdW5jdGlvbihmKSB7XG4gIGlmICghaXNTdHJpbmcoZikpIHtcbiAgICB2YXIgb2JqZWN0cyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBvYmplY3RzLnB1c2goaW5zcGVjdChhcmd1bWVudHNbaV0pKTtcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdHMuam9pbignICcpO1xuICB9XG5cbiAgdmFyIGkgPSAxO1xuICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgdmFyIGxlbiA9IGFyZ3MubGVuZ3RoO1xuICB2YXIgc3RyID0gU3RyaW5nKGYpLnJlcGxhY2UoZm9ybWF0UmVnRXhwLCBmdW5jdGlvbih4KSB7XG4gICAgaWYgKHggPT09ICclJScpIHJldHVybiAnJSc7XG4gICAgaWYgKGkgPj0gbGVuKSByZXR1cm4geDtcbiAgICBzd2l0Y2ggKHgpIHtcbiAgICAgIGNhc2UgJyVzJzogcmV0dXJuIFN0cmluZyhhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWQnOiByZXR1cm4gTnVtYmVyKGFyZ3NbaSsrXSk7XG4gICAgICBjYXNlICclaic6XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGFyZ3NbaSsrXSk7XG4gICAgICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgICAgICByZXR1cm4gJ1tDaXJjdWxhcl0nO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4geDtcbiAgICB9XG4gIH0pO1xuICBmb3IgKHZhciB4ID0gYXJnc1tpXTsgaSA8IGxlbjsgeCA9IGFyZ3NbKytpXSkge1xuICAgIGlmIChpc051bGwoeCkgfHwgIWlzT2JqZWN0KHgpKSB7XG4gICAgICBzdHIgKz0gJyAnICsgeDtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyICs9ICcgJyArIGluc3BlY3QoeCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBzdHI7XG59O1xuXG5cbi8vIE1hcmsgdGhhdCBhIG1ldGhvZCBzaG91bGQgbm90IGJlIHVzZWQuXG4vLyBSZXR1cm5zIGEgbW9kaWZpZWQgZnVuY3Rpb24gd2hpY2ggd2FybnMgb25jZSBieSBkZWZhdWx0LlxuLy8gSWYgLS1uby1kZXByZWNhdGlvbiBpcyBzZXQsIHRoZW4gaXQgaXMgYSBuby1vcC5cbmV4cG9ydHMuZGVwcmVjYXRlID0gZnVuY3Rpb24oZm4sIG1zZykge1xuICAvLyBBbGxvdyBmb3IgZGVwcmVjYXRpbmcgdGhpbmdzIGluIHRoZSBwcm9jZXNzIG9mIHN0YXJ0aW5nIHVwLlxuICBpZiAoaXNVbmRlZmluZWQoZ2xvYmFsLnByb2Nlc3MpKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGV4cG9ydHMuZGVwcmVjYXRlKGZuLCBtc2cpLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfVxuXG4gIGlmIChwcm9jZXNzLm5vRGVwcmVjYXRpb24gPT09IHRydWUpIHtcbiAgICByZXR1cm4gZm47XG4gIH1cblxuICB2YXIgd2FybmVkID0gZmFsc2U7XG4gIGZ1bmN0aW9uIGRlcHJlY2F0ZWQoKSB7XG4gICAgaWYgKCF3YXJuZWQpIHtcbiAgICAgIGlmIChwcm9jZXNzLnRocm93RGVwcmVjYXRpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XG4gICAgICB9IGVsc2UgaWYgKHByb2Nlc3MudHJhY2VEZXByZWNhdGlvbikge1xuICAgICAgICBjb25zb2xlLnRyYWNlKG1zZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLmVycm9yKG1zZyk7XG4gICAgICB9XG4gICAgICB3YXJuZWQgPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIHJldHVybiBkZXByZWNhdGVkO1xufTtcblxuXG52YXIgZGVidWdzID0ge307XG52YXIgZGVidWdFbnZpcm9uO1xuZXhwb3J0cy5kZWJ1Z2xvZyA9IGZ1bmN0aW9uKHNldCkge1xuICBpZiAoaXNVbmRlZmluZWQoZGVidWdFbnZpcm9uKSlcbiAgICBkZWJ1Z0Vudmlyb24gPSBwcm9jZXNzLmVudi5OT0RFX0RFQlVHIHx8ICcnO1xuICBzZXQgPSBzZXQudG9VcHBlckNhc2UoKTtcbiAgaWYgKCFkZWJ1Z3Nbc2V0XSkge1xuICAgIGlmIChuZXcgUmVnRXhwKCdcXFxcYicgKyBzZXQgKyAnXFxcXGInLCAnaScpLnRlc3QoZGVidWdFbnZpcm9uKSkge1xuICAgICAgdmFyIHBpZCA9IHByb2Nlc3MucGlkO1xuICAgICAgZGVidWdzW3NldF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG1zZyA9IGV4cG9ydHMuZm9ybWF0LmFwcGx5KGV4cG9ydHMsIGFyZ3VtZW50cyk7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJyVzICVkOiAlcycsIHNldCwgcGlkLCBtc2cpO1xuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWdzW3NldF0gPSBmdW5jdGlvbigpIHt9O1xuICAgIH1cbiAgfVxuICByZXR1cm4gZGVidWdzW3NldF07XG59O1xuXG5cbi8qKlxuICogRWNob3MgdGhlIHZhbHVlIG9mIGEgdmFsdWUuIFRyeXMgdG8gcHJpbnQgdGhlIHZhbHVlIG91dFxuICogaW4gdGhlIGJlc3Qgd2F5IHBvc3NpYmxlIGdpdmVuIHRoZSBkaWZmZXJlbnQgdHlwZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIHByaW50IG91dC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIE9wdGlvbmFsIG9wdGlvbnMgb2JqZWN0IHRoYXQgYWx0ZXJzIHRoZSBvdXRwdXQuXG4gKi9cbi8qIGxlZ2FjeTogb2JqLCBzaG93SGlkZGVuLCBkZXB0aCwgY29sb3JzKi9cbmZ1bmN0aW9uIGluc3BlY3Qob2JqLCBvcHRzKSB7XG4gIC8vIGRlZmF1bHQgb3B0aW9uc1xuICB2YXIgY3R4ID0ge1xuICAgIHNlZW46IFtdLFxuICAgIHN0eWxpemU6IHN0eWxpemVOb0NvbG9yXG4gIH07XG4gIC8vIGxlZ2FjeS4uLlxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSAzKSBjdHguZGVwdGggPSBhcmd1bWVudHNbMl07XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID49IDQpIGN0eC5jb2xvcnMgPSBhcmd1bWVudHNbM107XG4gIGlmIChpc0Jvb2xlYW4ob3B0cykpIHtcbiAgICAvLyBsZWdhY3kuLi5cbiAgICBjdHguc2hvd0hpZGRlbiA9IG9wdHM7XG4gIH0gZWxzZSBpZiAob3B0cykge1xuICAgIC8vIGdvdCBhbiBcIm9wdGlvbnNcIiBvYmplY3RcbiAgICBleHBvcnRzLl9leHRlbmQoY3R4LCBvcHRzKTtcbiAgfVxuICAvLyBzZXQgZGVmYXVsdCBvcHRpb25zXG4gIGlmIChpc1VuZGVmaW5lZChjdHguc2hvd0hpZGRlbikpIGN0eC5zaG93SGlkZGVuID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguZGVwdGgpKSBjdHguZGVwdGggPSAyO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmNvbG9ycykpIGN0eC5jb2xvcnMgPSBmYWxzZTtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jdXN0b21JbnNwZWN0KSkgY3R4LmN1c3RvbUluc3BlY3QgPSB0cnVlO1xuICBpZiAoY3R4LmNvbG9ycykgY3R4LnN0eWxpemUgPSBzdHlsaXplV2l0aENvbG9yO1xuICByZXR1cm4gZm9ybWF0VmFsdWUoY3R4LCBvYmosIGN0eC5kZXB0aCk7XG59XG5leHBvcnRzLmluc3BlY3QgPSBpbnNwZWN0O1xuXG5cbi8vIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQU5TSV9lc2NhcGVfY29kZSNncmFwaGljc1xuaW5zcGVjdC5jb2xvcnMgPSB7XG4gICdib2xkJyA6IFsxLCAyMl0sXG4gICdpdGFsaWMnIDogWzMsIDIzXSxcbiAgJ3VuZGVybGluZScgOiBbNCwgMjRdLFxuICAnaW52ZXJzZScgOiBbNywgMjddLFxuICAnd2hpdGUnIDogWzM3LCAzOV0sXG4gICdncmV5JyA6IFs5MCwgMzldLFxuICAnYmxhY2snIDogWzMwLCAzOV0sXG4gICdibHVlJyA6IFszNCwgMzldLFxuICAnY3lhbicgOiBbMzYsIDM5XSxcbiAgJ2dyZWVuJyA6IFszMiwgMzldLFxuICAnbWFnZW50YScgOiBbMzUsIDM5XSxcbiAgJ3JlZCcgOiBbMzEsIDM5XSxcbiAgJ3llbGxvdycgOiBbMzMsIDM5XVxufTtcblxuLy8gRG9uJ3QgdXNlICdibHVlJyBub3QgdmlzaWJsZSBvbiBjbWQuZXhlXG5pbnNwZWN0LnN0eWxlcyA9IHtcbiAgJ3NwZWNpYWwnOiAnY3lhbicsXG4gICdudW1iZXInOiAneWVsbG93JyxcbiAgJ2Jvb2xlYW4nOiAneWVsbG93JyxcbiAgJ3VuZGVmaW5lZCc6ICdncmV5JyxcbiAgJ251bGwnOiAnYm9sZCcsXG4gICdzdHJpbmcnOiAnZ3JlZW4nLFxuICAnZGF0ZSc6ICdtYWdlbnRhJyxcbiAgLy8gXCJuYW1lXCI6IGludGVudGlvbmFsbHkgbm90IHN0eWxpbmdcbiAgJ3JlZ2V4cCc6ICdyZWQnXG59O1xuXG5cbmZ1bmN0aW9uIHN0eWxpemVXaXRoQ29sb3Ioc3RyLCBzdHlsZVR5cGUpIHtcbiAgdmFyIHN0eWxlID0gaW5zcGVjdC5zdHlsZXNbc3R5bGVUeXBlXTtcblxuICBpZiAoc3R5bGUpIHtcbiAgICByZXR1cm4gJ1xcdTAwMWJbJyArIGluc3BlY3QuY29sb3JzW3N0eWxlXVswXSArICdtJyArIHN0ciArXG4gICAgICAgICAgICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMV0gKyAnbSc7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHN0cjtcbiAgfVxufVxuXG5cbmZ1bmN0aW9uIHN0eWxpemVOb0NvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHJldHVybiBzdHI7XG59XG5cblxuZnVuY3Rpb24gYXJyYXlUb0hhc2goYXJyYXkpIHtcbiAgdmFyIGhhc2ggPSB7fTtcblxuICBhcnJheS5mb3JFYWNoKGZ1bmN0aW9uKHZhbCwgaWR4KSB7XG4gICAgaGFzaFt2YWxdID0gdHJ1ZTtcbiAgfSk7XG5cbiAgcmV0dXJuIGhhc2g7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0VmFsdWUoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzKSB7XG4gIC8vIFByb3ZpZGUgYSBob29rIGZvciB1c2VyLXNwZWNpZmllZCBpbnNwZWN0IGZ1bmN0aW9ucy5cbiAgLy8gQ2hlY2sgdGhhdCB2YWx1ZSBpcyBhbiBvYmplY3Qgd2l0aCBhbiBpbnNwZWN0IGZ1bmN0aW9uIG9uIGl0XG4gIGlmIChjdHguY3VzdG9tSW5zcGVjdCAmJlxuICAgICAgdmFsdWUgJiZcbiAgICAgIGlzRnVuY3Rpb24odmFsdWUuaW5zcGVjdCkgJiZcbiAgICAgIC8vIEZpbHRlciBvdXQgdGhlIHV0aWwgbW9kdWxlLCBpdCdzIGluc3BlY3QgZnVuY3Rpb24gaXMgc3BlY2lhbFxuICAgICAgdmFsdWUuaW5zcGVjdCAhPT0gZXhwb3J0cy5pbnNwZWN0ICYmXG4gICAgICAvLyBBbHNvIGZpbHRlciBvdXQgYW55IHByb3RvdHlwZSBvYmplY3RzIHVzaW5nIHRoZSBjaXJjdWxhciBjaGVjay5cbiAgICAgICEodmFsdWUuY29uc3RydWN0b3IgJiYgdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlID09PSB2YWx1ZSkpIHtcbiAgICB2YXIgcmV0ID0gdmFsdWUuaW5zcGVjdChyZWN1cnNlVGltZXMsIGN0eCk7XG4gICAgaWYgKCFpc1N0cmluZyhyZXQpKSB7XG4gICAgICByZXQgPSBmb3JtYXRWYWx1ZShjdHgsIHJldCwgcmVjdXJzZVRpbWVzKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIC8vIFByaW1pdGl2ZSB0eXBlcyBjYW5ub3QgaGF2ZSBwcm9wZXJ0aWVzXG4gIHZhciBwcmltaXRpdmUgPSBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSk7XG4gIGlmIChwcmltaXRpdmUpIHtcbiAgICByZXR1cm4gcHJpbWl0aXZlO1xuICB9XG5cbiAgLy8gTG9vayB1cCB0aGUga2V5cyBvZiB0aGUgb2JqZWN0LlxuICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHZhbHVlKTtcbiAgdmFyIHZpc2libGVLZXlzID0gYXJyYXlUb0hhc2goa2V5cyk7XG5cbiAgaWYgKGN0eC5zaG93SGlkZGVuKSB7XG4gICAga2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHZhbHVlKTtcbiAgfVxuXG4gIC8vIElFIGRvZXNuJ3QgbWFrZSBlcnJvciBmaWVsZHMgbm9uLWVudW1lcmFibGVcbiAgLy8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L2llL2R3dzUyc2J0KHY9dnMuOTQpLmFzcHhcbiAgaWYgKGlzRXJyb3IodmFsdWUpXG4gICAgICAmJiAoa2V5cy5pbmRleE9mKCdtZXNzYWdlJykgPj0gMCB8fCBrZXlzLmluZGV4T2YoJ2Rlc2NyaXB0aW9uJykgPj0gMCkpIHtcbiAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgLy8gU29tZSB0eXBlIG9mIG9iamVjdCB3aXRob3V0IHByb3BlcnRpZXMgY2FuIGJlIHNob3J0Y3V0dGVkLlxuICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHtcbiAgICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICAgIHZhciBuYW1lID0gdmFsdWUubmFtZSA/ICc6ICcgKyB2YWx1ZS5uYW1lIDogJyc7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJ1tGdW5jdGlvbicgKyBuYW1lICsgJ10nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgICBpZiAoaXNSZWdFeHAodmFsdWUpKSB7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoUmVnRXhwLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ3JlZ2V4cCcpO1xuICAgIH1cbiAgICBpZiAoaXNEYXRlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKERhdGUucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAnZGF0ZScpO1xuICAgIH1cbiAgICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBmb3JtYXRFcnJvcih2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgdmFyIGJhc2UgPSAnJywgYXJyYXkgPSBmYWxzZSwgYnJhY2VzID0gWyd7JywgJ30nXTtcblxuICAvLyBNYWtlIEFycmF5IHNheSB0aGF0IHRoZXkgYXJlIEFycmF5XG4gIGlmIChpc0FycmF5KHZhbHVlKSkge1xuICAgIGFycmF5ID0gdHJ1ZTtcbiAgICBicmFjZXMgPSBbJ1snLCAnXSddO1xuICB9XG5cbiAgLy8gTWFrZSBmdW5jdGlvbnMgc2F5IHRoYXQgdGhleSBhcmUgZnVuY3Rpb25zXG4gIGlmIChpc0Z1bmN0aW9uKHZhbHVlKSkge1xuICAgIHZhciBuID0gdmFsdWUubmFtZSA/ICc6ICcgKyB2YWx1ZS5uYW1lIDogJyc7XG4gICAgYmFzZSA9ICcgW0Z1bmN0aW9uJyArIG4gKyAnXSc7XG4gIH1cblxuICAvLyBNYWtlIFJlZ0V4cHMgc2F5IHRoYXQgdGhleSBhcmUgUmVnRXhwc1xuICBpZiAoaXNSZWdFeHAodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gIH1cblxuICAvLyBNYWtlIGRhdGVzIHdpdGggcHJvcGVydGllcyBmaXJzdCBzYXkgdGhlIGRhdGVcbiAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgRGF0ZS5wcm90b3R5cGUudG9VVENTdHJpbmcuY2FsbCh2YWx1ZSk7XG4gIH1cblxuICAvLyBNYWtlIGVycm9yIHdpdGggbWVzc2FnZSBmaXJzdCBzYXkgdGhlIGVycm9yXG4gIGlmIChpc0Vycm9yKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBmb3JtYXRFcnJvcih2YWx1ZSk7XG4gIH1cblxuICBpZiAoa2V5cy5sZW5ndGggPT09IDAgJiYgKCFhcnJheSB8fCB2YWx1ZS5sZW5ndGggPT0gMCkpIHtcbiAgICByZXR1cm4gYnJhY2VzWzBdICsgYmFzZSArIGJyYWNlc1sxXTtcbiAgfVxuXG4gIGlmIChyZWN1cnNlVGltZXMgPCAwKSB7XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbT2JqZWN0XScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG5cbiAgY3R4LnNlZW4ucHVzaCh2YWx1ZSk7XG5cbiAgdmFyIG91dHB1dDtcbiAgaWYgKGFycmF5KSB7XG4gICAgb3V0cHV0ID0gZm9ybWF0QXJyYXkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5cyk7XG4gIH0gZWxzZSB7XG4gICAgb3V0cHV0ID0ga2V5cy5tYXAoZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSk7XG4gICAgfSk7XG4gIH1cblxuICBjdHguc2Vlbi5wb3AoKTtcblxuICByZXR1cm4gcmVkdWNlVG9TaW5nbGVTdHJpbmcob3V0cHV0LCBiYXNlLCBicmFjZXMpO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFByaW1pdGl2ZShjdHgsIHZhbHVlKSB7XG4gIGlmIChpc1VuZGVmaW5lZCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCd1bmRlZmluZWQnLCAndW5kZWZpbmVkJyk7XG4gIGlmIChpc1N0cmluZyh2YWx1ZSkpIHtcbiAgICB2YXIgc2ltcGxlID0gJ1xcJycgKyBKU09OLnN0cmluZ2lmeSh2YWx1ZSkucmVwbGFjZSgvXlwifFwiJC9nLCAnJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJykgKyAnXFwnJztcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoc2ltcGxlLCAnc3RyaW5nJyk7XG4gIH1cbiAgaWYgKGlzTnVtYmVyKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ251bWJlcicpO1xuICBpZiAoaXNCb29sZWFuKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ2Jvb2xlYW4nKTtcbiAgLy8gRm9yIHNvbWUgcmVhc29uIHR5cGVvZiBudWxsIGlzIFwib2JqZWN0XCIsIHNvIHNwZWNpYWwgY2FzZSBoZXJlLlxuICBpZiAoaXNOdWxsKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJ251bGwnLCAnbnVsbCcpO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEVycm9yKHZhbHVlKSB7XG4gIHJldHVybiAnWycgKyBFcnJvci5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgKyAnXSc7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0QXJyYXkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5cykge1xuICB2YXIgb3V0cHV0ID0gW107XG4gIGZvciAodmFyIGkgPSAwLCBsID0gdmFsdWUubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgaWYgKGhhc093blByb3BlcnR5KHZhbHVlLCBTdHJpbmcoaSkpKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIFN0cmluZyhpKSwgdHJ1ZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvdXRwdXQucHVzaCgnJyk7XG4gICAgfVxuICB9XG4gIGtleXMuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICBpZiAoIWtleS5tYXRjaCgvXlxcZCskLykpIHtcbiAgICAgIG91dHB1dC5wdXNoKGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsXG4gICAgICAgICAga2V5LCB0cnVlKSk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIG91dHB1dDtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLCBrZXksIGFycmF5KSB7XG4gIHZhciBuYW1lLCBzdHIsIGRlc2M7XG4gIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHZhbHVlLCBrZXkpIHx8IHsgdmFsdWU6IHZhbHVlW2tleV0gfTtcbiAgaWYgKGRlc2MuZ2V0KSB7XG4gICAgaWYgKGRlc2Muc2V0KSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0dldHRlci9TZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKGRlc2Muc2V0KSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuICBpZiAoIWhhc093blByb3BlcnR5KHZpc2libGVLZXlzLCBrZXkpKSB7XG4gICAgbmFtZSA9ICdbJyArIGtleSArICddJztcbiAgfVxuICBpZiAoIXN0cikge1xuICAgIGlmIChjdHguc2Vlbi5pbmRleE9mKGRlc2MudmFsdWUpIDwgMCkge1xuICAgICAgaWYgKGlzTnVsbChyZWN1cnNlVGltZXMpKSB7XG4gICAgICAgIHN0ciA9IGZvcm1hdFZhbHVlKGN0eCwgZGVzYy52YWx1ZSwgbnVsbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIHJlY3Vyc2VUaW1lcyAtIDEpO1xuICAgICAgfVxuICAgICAgaWYgKHN0ci5pbmRleE9mKCdcXG4nKSA+IC0xKSB7XG4gICAgICAgIGlmIChhcnJheSkge1xuICAgICAgICAgIHN0ciA9IHN0ci5zcGxpdCgnXFxuJykubWFwKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgICAgIHJldHVybiAnICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKS5zdWJzdHIoMik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3RyID0gJ1xcbicgKyBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgICcgKyBsaW5lO1xuICAgICAgICAgIH0pLmpvaW4oJ1xcbicpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbQ2lyY3VsYXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKGlzVW5kZWZpbmVkKG5hbWUpKSB7XG4gICAgaWYgKGFycmF5ICYmIGtleS5tYXRjaCgvXlxcZCskLykpIHtcbiAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuICAgIG5hbWUgPSBKU09OLnN0cmluZ2lmeSgnJyArIGtleSk7XG4gICAgaWYgKG5hbWUubWF0Y2goL15cIihbYS16QS1aX11bYS16QS1aXzAtOV0qKVwiJC8pKSB7XG4gICAgICBuYW1lID0gbmFtZS5zdWJzdHIoMSwgbmFtZS5sZW5ndGggLSAyKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnbmFtZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuYW1lID0gbmFtZS5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIilcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFxcIi9nLCAnXCInKVxuICAgICAgICAgICAgICAgICAucmVwbGFjZSgvKF5cInxcIiQpL2csIFwiJ1wiKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnc3RyaW5nJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5hbWUgKyAnOiAnICsgc3RyO1xufVxuXG5cbmZ1bmN0aW9uIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKSB7XG4gIHZhciBudW1MaW5lc0VzdCA9IDA7XG4gIHZhciBsZW5ndGggPSBvdXRwdXQucmVkdWNlKGZ1bmN0aW9uKHByZXYsIGN1cikge1xuICAgIG51bUxpbmVzRXN0Kys7XG4gICAgaWYgKGN1ci5pbmRleE9mKCdcXG4nKSA+PSAwKSBudW1MaW5lc0VzdCsrO1xuICAgIHJldHVybiBwcmV2ICsgY3VyLnJlcGxhY2UoL1xcdTAwMWJcXFtcXGRcXGQ/bS9nLCAnJykubGVuZ3RoICsgMTtcbiAgfSwgMCk7XG5cbiAgaWYgKGxlbmd0aCA+IDYwKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArXG4gICAgICAgICAgIChiYXNlID09PSAnJyA/ICcnIDogYmFzZSArICdcXG4gJykgK1xuICAgICAgICAgICAnICcgK1xuICAgICAgICAgICBvdXRwdXQuam9pbignLFxcbiAgJykgK1xuICAgICAgICAgICAnICcgK1xuICAgICAgICAgICBicmFjZXNbMV07XG4gIH1cblxuICByZXR1cm4gYnJhY2VzWzBdICsgYmFzZSArICcgJyArIG91dHB1dC5qb2luKCcsICcpICsgJyAnICsgYnJhY2VzWzFdO1xufVxuXG5cbi8vIE5PVEU6IFRoZXNlIHR5cGUgY2hlY2tpbmcgZnVuY3Rpb25zIGludGVudGlvbmFsbHkgZG9uJ3QgdXNlIGBpbnN0YW5jZW9mYFxuLy8gYmVjYXVzZSBpdCBpcyBmcmFnaWxlIGFuZCBjYW4gYmUgZWFzaWx5IGZha2VkIHdpdGggYE9iamVjdC5jcmVhdGUoKWAuXG5mdW5jdGlvbiBpc0FycmF5KGFyKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGFyKTtcbn1cbmV4cG9ydHMuaXNBcnJheSA9IGlzQXJyYXk7XG5cbmZ1bmN0aW9uIGlzQm9vbGVhbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdib29sZWFuJztcbn1cbmV4cG9ydHMuaXNCb29sZWFuID0gaXNCb29sZWFuO1xuXG5mdW5jdGlvbiBpc051bGwoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbCA9IGlzTnVsbDtcblxuZnVuY3Rpb24gaXNOdWxsT3JVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT0gbnVsbDtcbn1cbmV4cG9ydHMuaXNOdWxsT3JVbmRlZmluZWQgPSBpc051bGxPclVuZGVmaW5lZDtcblxuZnVuY3Rpb24gaXNOdW1iZXIoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnbnVtYmVyJztcbn1cbmV4cG9ydHMuaXNOdW1iZXIgPSBpc051bWJlcjtcblxuZnVuY3Rpb24gaXNTdHJpbmcoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnc3RyaW5nJztcbn1cbmV4cG9ydHMuaXNTdHJpbmcgPSBpc1N0cmluZztcblxuZnVuY3Rpb24gaXNTeW1ib2woYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnc3ltYm9sJztcbn1cbmV4cG9ydHMuaXNTeW1ib2wgPSBpc1N5bWJvbDtcblxuZnVuY3Rpb24gaXNVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IHZvaWQgMDtcbn1cbmV4cG9ydHMuaXNVbmRlZmluZWQgPSBpc1VuZGVmaW5lZDtcblxuZnVuY3Rpb24gaXNSZWdFeHAocmUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KHJlKSAmJiBvYmplY3RUb1N0cmluZyhyZSkgPT09ICdbb2JqZWN0IFJlZ0V4cF0nO1xufVxuZXhwb3J0cy5pc1JlZ0V4cCA9IGlzUmVnRXhwO1xuXG5mdW5jdGlvbiBpc09iamVjdChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnICYmIGFyZyAhPT0gbnVsbDtcbn1cbmV4cG9ydHMuaXNPYmplY3QgPSBpc09iamVjdDtcblxuZnVuY3Rpb24gaXNEYXRlKGQpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KGQpICYmIG9iamVjdFRvU3RyaW5nKGQpID09PSAnW29iamVjdCBEYXRlXSc7XG59XG5leHBvcnRzLmlzRGF0ZSA9IGlzRGF0ZTtcblxuZnVuY3Rpb24gaXNFcnJvcihlKSB7XG4gIHJldHVybiBpc09iamVjdChlKSAmJlxuICAgICAgKG9iamVjdFRvU3RyaW5nKGUpID09PSAnW29iamVjdCBFcnJvcl0nIHx8IGUgaW5zdGFuY2VvZiBFcnJvcik7XG59XG5leHBvcnRzLmlzRXJyb3IgPSBpc0Vycm9yO1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Z1bmN0aW9uJztcbn1cbmV4cG9ydHMuaXNGdW5jdGlvbiA9IGlzRnVuY3Rpb247XG5cbmZ1bmN0aW9uIGlzUHJpbWl0aXZlKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnYm9vbGVhbicgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdudW1iZXInIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnc3RyaW5nJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcgfHwgIC8vIEVTNiBzeW1ib2xcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICd1bmRlZmluZWQnO1xufVxuZXhwb3J0cy5pc1ByaW1pdGl2ZSA9IGlzUHJpbWl0aXZlO1xuXG5leHBvcnRzLmlzQnVmZmVyID0gX2RlcmVxXygnLi9zdXBwb3J0L2lzQnVmZmVyJyk7XG5cbmZ1bmN0aW9uIG9iamVjdFRvU3RyaW5nKG8pIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTtcbn1cblxuXG5mdW5jdGlvbiBwYWQobikge1xuICByZXR1cm4gbiA8IDEwID8gJzAnICsgbi50b1N0cmluZygxMCkgOiBuLnRvU3RyaW5nKDEwKTtcbn1cblxuXG52YXIgbW9udGhzID0gWydKYW4nLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsICdKdWwnLCAnQXVnJywgJ1NlcCcsXG4gICAgICAgICAgICAgICdPY3QnLCAnTm92JywgJ0RlYyddO1xuXG4vLyAyNiBGZWIgMTY6MTk6MzRcbmZ1bmN0aW9uIHRpbWVzdGFtcCgpIHtcbiAgdmFyIGQgPSBuZXcgRGF0ZSgpO1xuICB2YXIgdGltZSA9IFtwYWQoZC5nZXRIb3VycygpKSxcbiAgICAgICAgICAgICAgcGFkKGQuZ2V0TWludXRlcygpKSxcbiAgICAgICAgICAgICAgcGFkKGQuZ2V0U2Vjb25kcygpKV0uam9pbignOicpO1xuICByZXR1cm4gW2QuZ2V0RGF0ZSgpLCBtb250aHNbZC5nZXRNb250aCgpXSwgdGltZV0uam9pbignICcpO1xufVxuXG5cbi8vIGxvZyBpcyBqdXN0IGEgdGhpbiB3cmFwcGVyIHRvIGNvbnNvbGUubG9nIHRoYXQgcHJlcGVuZHMgYSB0aW1lc3RhbXBcbmV4cG9ydHMubG9nID0gZnVuY3Rpb24oKSB7XG4gIGNvbnNvbGUubG9nKCclcyAtICVzJywgdGltZXN0YW1wKCksIGV4cG9ydHMuZm9ybWF0LmFwcGx5KGV4cG9ydHMsIGFyZ3VtZW50cykpO1xufTtcblxuXG4vKipcbiAqIEluaGVyaXQgdGhlIHByb3RvdHlwZSBtZXRob2RzIGZyb20gb25lIGNvbnN0cnVjdG9yIGludG8gYW5vdGhlci5cbiAqXG4gKiBUaGUgRnVuY3Rpb24ucHJvdG90eXBlLmluaGVyaXRzIGZyb20gbGFuZy5qcyByZXdyaXR0ZW4gYXMgYSBzdGFuZGFsb25lXG4gKiBmdW5jdGlvbiAobm90IG9uIEZ1bmN0aW9uLnByb3RvdHlwZSkuIE5PVEU6IElmIHRoaXMgZmlsZSBpcyB0byBiZSBsb2FkZWRcbiAqIGR1cmluZyBib290c3RyYXBwaW5nIHRoaXMgZnVuY3Rpb24gbmVlZHMgdG8gYmUgcmV3cml0dGVuIHVzaW5nIHNvbWUgbmF0aXZlXG4gKiBmdW5jdGlvbnMgYXMgcHJvdG90eXBlIHNldHVwIHVzaW5nIG5vcm1hbCBKYXZhU2NyaXB0IGRvZXMgbm90IHdvcmsgYXNcbiAqIGV4cGVjdGVkIGR1cmluZyBib290c3RyYXBwaW5nIChzZWUgbWlycm9yLmpzIGluIHIxMTQ5MDMpLlxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGN0b3IgQ29uc3RydWN0b3IgZnVuY3Rpb24gd2hpY2ggbmVlZHMgdG8gaW5oZXJpdCB0aGVcbiAqICAgICBwcm90b3R5cGUuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBzdXBlckN0b3IgQ29uc3RydWN0b3IgZnVuY3Rpb24gdG8gaW5oZXJpdCBwcm90b3R5cGUgZnJvbS5cbiAqL1xuZXhwb3J0cy5pbmhlcml0cyA9IF9kZXJlcV8oJ2luaGVyaXRzJyk7XG5cbmV4cG9ydHMuX2V4dGVuZCA9IGZ1bmN0aW9uKG9yaWdpbiwgYWRkKSB7XG4gIC8vIERvbid0IGRvIGFueXRoaW5nIGlmIGFkZCBpc24ndCBhbiBvYmplY3RcbiAgaWYgKCFhZGQgfHwgIWlzT2JqZWN0KGFkZCkpIHJldHVybiBvcmlnaW47XG5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhhZGQpO1xuICB2YXIgaSA9IGtleXMubGVuZ3RoO1xuICB3aGlsZSAoaS0tKSB7XG4gICAgb3JpZ2luW2tleXNbaV1dID0gYWRkW2tleXNbaV1dO1xuICB9XG4gIHJldHVybiBvcmlnaW47XG59O1xuXG5mdW5jdGlvbiBoYXNPd25Qcm9wZXJ0eShvYmosIHByb3ApIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApO1xufVxuXG59KS5jYWxsKHRoaXMsX2RlcmVxXygnX3Byb2Nlc3MnKSx0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KVxufSx7XCIuL3N1cHBvcnQvaXNCdWZmZXJcIjo3MCxcIl9wcm9jZXNzXCI6NDgyLFwiaW5oZXJpdHNcIjo2OX1dLDcyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gX2F0b2Ioc3RyKSB7XG4gIHJldHVybiBhdG9iKHN0cilcbn1cblxufSx7fV0sNzM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gYmFyeWNlbnRyaWNcblxudmFyIHNvbHZlID0gX2RlcmVxXygncm9idXN0LWxpbmVhci1zb2x2ZScpXG5cbmZ1bmN0aW9uIHJlZHVjZSh4KSB7XG4gIHZhciByID0gMFxuICBmb3IodmFyIGk9MDsgaTx4Lmxlbmd0aDsgKytpKSB7XG4gICAgciArPSB4W2ldXG4gIH1cbiAgcmV0dXJuIHJcbn1cblxuZnVuY3Rpb24gYmFyeWNlbnRyaWMoc2ltcGxleCwgcG9pbnQpIHtcbiAgdmFyIGQgPSBwb2ludC5sZW5ndGhcbiAgdmFyIEEgPSBuZXcgQXJyYXkoZCsxKVxuICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICB2YXIgcm93ID0gbmV3IEFycmF5KGQrMSlcbiAgICBmb3IodmFyIGo9MDsgajw9ZDsgKytqKSB7XG4gICAgICByb3dbal0gPSBzaW1wbGV4W2pdW2ldXG4gICAgfVxuICAgIEFbaV0gPSByb3dcbiAgfVxuICBBW2RdID0gbmV3IEFycmF5KGQrMSlcbiAgZm9yKHZhciBpPTA7IGk8PWQ7ICsraSkge1xuICAgIEFbZF1baV0gPSAxXG4gIH1cblxuICB2YXIgYiA9IG5ldyBBcnJheShkKzEpXG4gIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgIGJbaV0gPSBwb2ludFtpXVxuICB9XG4gIGJbZF0gPSAxLjBcblxuICB2YXIgeCA9IHNvbHZlKEEsIGIpXG4gIHZhciB3ID0gcmVkdWNlKHhbZCsxXSlcbiAgXG4gIGlmKHcgPT09IDApIHtcbiAgICB3ID0gMS4wXG4gIH1cbiAgdmFyIHkgPSBuZXcgQXJyYXkoZCsxKVxuICBmb3IodmFyIGk9MDsgaTw9ZDsgKytpKSB7XG4gICAgeVtpXSA9IHJlZHVjZSh4W2ldKSAvIHdcbiAgfVxuICByZXR1cm4geVxufVxufSx7XCJyb2J1c3QtbGluZWFyLXNvbHZlXCI6NTA5fV0sNzQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbmV4cG9ydHMuYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGhcbmV4cG9ydHMudG9CeXRlQXJyYXkgPSB0b0J5dGVBcnJheVxuZXhwb3J0cy5mcm9tQnl0ZUFycmF5ID0gZnJvbUJ5dGVBcnJheVxuXG52YXIgbG9va3VwID0gW11cbnZhciByZXZMb29rdXAgPSBbXVxudmFyIEFyciA9IHR5cGVvZiBVaW50OEFycmF5ICE9PSAndW5kZWZpbmVkJyA/IFVpbnQ4QXJyYXkgOiBBcnJheVxuXG52YXIgY29kZSA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJ1xuZm9yICh2YXIgaSA9IDAsIGxlbiA9IGNvZGUubGVuZ3RoOyBpIDwgbGVuOyArK2kpIHtcbiAgbG9va3VwW2ldID0gY29kZVtpXVxuICByZXZMb29rdXBbY29kZS5jaGFyQ29kZUF0KGkpXSA9IGlcbn1cblxuLy8gU3VwcG9ydCBkZWNvZGluZyBVUkwtc2FmZSBiYXNlNjQgc3RyaW5ncywgYXMgTm9kZS5qcyBkb2VzLlxuLy8gU2VlOiBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9CYXNlNjQjVVJMX2FwcGxpY2F0aW9uc1xucmV2TG9va3VwWyctJy5jaGFyQ29kZUF0KDApXSA9IDYyXG5yZXZMb29rdXBbJ18nLmNoYXJDb2RlQXQoMCldID0gNjNcblxuZnVuY3Rpb24gZ2V0TGVucyAoYjY0KSB7XG4gIHZhciBsZW4gPSBiNjQubGVuZ3RoXG5cbiAgaWYgKGxlbiAlIDQgPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0cmluZy4gTGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0JylcbiAgfVxuXG4gIC8vIFRyaW0gb2ZmIGV4dHJhIGJ5dGVzIGFmdGVyIHBsYWNlaG9sZGVyIGJ5dGVzIGFyZSBmb3VuZFxuICAvLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9iZWF0Z2FtbWl0L2Jhc2U2NC1qcy9pc3N1ZXMvNDJcbiAgdmFyIHZhbGlkTGVuID0gYjY0LmluZGV4T2YoJz0nKVxuICBpZiAodmFsaWRMZW4gPT09IC0xKSB2YWxpZExlbiA9IGxlblxuXG4gIHZhciBwbGFjZUhvbGRlcnNMZW4gPSB2YWxpZExlbiA9PT0gbGVuXG4gICAgPyAwXG4gICAgOiA0IC0gKHZhbGlkTGVuICUgNClcblxuICByZXR1cm4gW3ZhbGlkTGVuLCBwbGFjZUhvbGRlcnNMZW5dXG59XG5cbi8vIGJhc2U2NCBpcyA0LzMgKyB1cCB0byB0d28gY2hhcmFjdGVycyBvZiB0aGUgb3JpZ2luYWwgZGF0YVxuZnVuY3Rpb24gYnl0ZUxlbmd0aCAoYjY0KSB7XG4gIHZhciBsZW5zID0gZ2V0TGVucyhiNjQpXG4gIHZhciB2YWxpZExlbiA9IGxlbnNbMF1cbiAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IGxlbnNbMV1cbiAgcmV0dXJuICgodmFsaWRMZW4gKyBwbGFjZUhvbGRlcnNMZW4pICogMyAvIDQpIC0gcGxhY2VIb2xkZXJzTGVuXG59XG5cbmZ1bmN0aW9uIF9ieXRlTGVuZ3RoIChiNjQsIHZhbGlkTGVuLCBwbGFjZUhvbGRlcnNMZW4pIHtcbiAgcmV0dXJuICgodmFsaWRMZW4gKyBwbGFjZUhvbGRlcnNMZW4pICogMyAvIDQpIC0gcGxhY2VIb2xkZXJzTGVuXG59XG5cbmZ1bmN0aW9uIHRvQnl0ZUFycmF5IChiNjQpIHtcbiAgdmFyIHRtcFxuICB2YXIgbGVucyA9IGdldExlbnMoYjY0KVxuICB2YXIgdmFsaWRMZW4gPSBsZW5zWzBdXG4gIHZhciBwbGFjZUhvbGRlcnNMZW4gPSBsZW5zWzFdXG5cbiAgdmFyIGFyciA9IG5ldyBBcnIoX2J5dGVMZW5ndGgoYjY0LCB2YWxpZExlbiwgcGxhY2VIb2xkZXJzTGVuKSlcblxuICB2YXIgY3VyQnl0ZSA9IDBcblxuICAvLyBpZiB0aGVyZSBhcmUgcGxhY2Vob2xkZXJzLCBvbmx5IGdldCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSA0IGNoYXJzXG4gIHZhciBsZW4gPSBwbGFjZUhvbGRlcnNMZW4gPiAwXG4gICAgPyB2YWxpZExlbiAtIDRcbiAgICA6IHZhbGlkTGVuXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkgKz0gNCkge1xuICAgIHRtcCA9XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxOCkgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDEyKSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAyKV0gPDwgNikgfFxuICAgICAgcmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAzKV1cbiAgICBhcnJbY3VyQnl0ZSsrXSA9ICh0bXAgPj4gMTYpICYgMHhGRlxuICAgIGFycltjdXJCeXRlKytdID0gKHRtcCA+PiA4KSAmIDB4RkZcbiAgICBhcnJbY3VyQnl0ZSsrXSA9IHRtcCAmIDB4RkZcbiAgfVxuXG4gIGlmIChwbGFjZUhvbGRlcnNMZW4gPT09IDIpIHtcbiAgICB0bXAgPVxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMikgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldID4+IDQpXG4gICAgYXJyW2N1ckJ5dGUrK10gPSB0bXAgJiAweEZGXG4gIH1cblxuICBpZiAocGxhY2VIb2xkZXJzTGVuID09PSAxKSB7XG4gICAgdG1wID1cbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSldIDw8IDEwKSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAxKV0gPDwgNCkgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMildID4+IDIpXG4gICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDgpICYgMHhGRlxuICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIGFyclxufVxuXG5mdW5jdGlvbiB0cmlwbGV0VG9CYXNlNjQgKG51bSkge1xuICByZXR1cm4gbG9va3VwW251bSA+PiAxOCAmIDB4M0ZdICtcbiAgICBsb29rdXBbbnVtID4+IDEyICYgMHgzRl0gK1xuICAgIGxvb2t1cFtudW0gPj4gNiAmIDB4M0ZdICtcbiAgICBsb29rdXBbbnVtICYgMHgzRl1cbn1cblxuZnVuY3Rpb24gZW5jb2RlQ2h1bmsgKHVpbnQ4LCBzdGFydCwgZW5kKSB7XG4gIHZhciB0bXBcbiAgdmFyIG91dHB1dCA9IFtdXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSArPSAzKSB7XG4gICAgdG1wID1cbiAgICAgICgodWludDhbaV0gPDwgMTYpICYgMHhGRjAwMDApICtcbiAgICAgICgodWludDhbaSArIDFdIDw8IDgpICYgMHhGRjAwKSArXG4gICAgICAodWludDhbaSArIDJdICYgMHhGRilcbiAgICBvdXRwdXQucHVzaCh0cmlwbGV0VG9CYXNlNjQodG1wKSlcbiAgfVxuICByZXR1cm4gb3V0cHV0LmpvaW4oJycpXG59XG5cbmZ1bmN0aW9uIGZyb21CeXRlQXJyYXkgKHVpbnQ4KSB7XG4gIHZhciB0bXBcbiAgdmFyIGxlbiA9IHVpbnQ4Lmxlbmd0aFxuICB2YXIgZXh0cmFCeXRlcyA9IGxlbiAlIDMgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcbiAgdmFyIHBhcnRzID0gW11cbiAgdmFyIG1heENodW5rTGVuZ3RoID0gMTYzODMgLy8gbXVzdCBiZSBtdWx0aXBsZSBvZiAzXG5cbiAgLy8gZ28gdGhyb3VnaCB0aGUgYXJyYXkgZXZlcnkgdGhyZWUgYnl0ZXMsIHdlJ2xsIGRlYWwgd2l0aCB0cmFpbGluZyBzdHVmZiBsYXRlclxuICBmb3IgKHZhciBpID0gMCwgbGVuMiA9IGxlbiAtIGV4dHJhQnl0ZXM7IGkgPCBsZW4yOyBpICs9IG1heENodW5rTGVuZ3RoKSB7XG4gICAgcGFydHMucHVzaChlbmNvZGVDaHVuayhcbiAgICAgIHVpbnQ4LCBpLCAoaSArIG1heENodW5rTGVuZ3RoKSA+IGxlbjIgPyBsZW4yIDogKGkgKyBtYXhDaHVua0xlbmd0aClcbiAgICApKVxuICB9XG5cbiAgLy8gcGFkIHRoZSBlbmQgd2l0aCB6ZXJvcywgYnV0IG1ha2Ugc3VyZSB0byBub3QgZm9yZ2V0IHRoZSBleHRyYSBieXRlc1xuICBpZiAoZXh0cmFCeXRlcyA9PT0gMSkge1xuICAgIHRtcCA9IHVpbnQ4W2xlbiAtIDFdXG4gICAgcGFydHMucHVzaChcbiAgICAgIGxvb2t1cFt0bXAgPj4gMl0gK1xuICAgICAgbG9va3VwWyh0bXAgPDwgNCkgJiAweDNGXSArXG4gICAgICAnPT0nXG4gICAgKVxuICB9IGVsc2UgaWYgKGV4dHJhQnl0ZXMgPT09IDIpIHtcbiAgICB0bXAgPSAodWludDhbbGVuIC0gMl0gPDwgOCkgKyB1aW50OFtsZW4gLSAxXVxuICAgIHBhcnRzLnB1c2goXG4gICAgICBsb29rdXBbdG1wID4+IDEwXSArXG4gICAgICBsb29rdXBbKHRtcCA+PiA0KSAmIDB4M0ZdICtcbiAgICAgIGxvb2t1cFsodG1wIDw8IDIpICYgMHgzRl0gK1xuICAgICAgJz0nXG4gICAgKVxuICB9XG5cbiAgcmV0dXJuIHBhcnRzLmpvaW4oJycpXG59XG5cbn0se31dLDc1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgcmF0aW9uYWxpemUgPSBfZGVyZXFfKCcuL2xpYi9yYXRpb25hbGl6ZScpXG5cbm1vZHVsZS5leHBvcnRzID0gYWRkXG5cbmZ1bmN0aW9uIGFkZChhLCBiKSB7XG4gIHJldHVybiByYXRpb25hbGl6ZShcbiAgICBhWzBdLm11bChiWzFdKS5hZGQoYlswXS5tdWwoYVsxXSkpLFxuICAgIGFbMV0ubXVsKGJbMV0pKVxufVxuXG59LHtcIi4vbGliL3JhdGlvbmFsaXplXCI6ODV9XSw3NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjbXBcblxuZnVuY3Rpb24gY21wKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXS5tdWwoYlsxXSkuY21wKGJbMF0ubXVsKGFbMV0pKVxufVxuXG59LHt9XSw3NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIHJhdGlvbmFsaXplID0gX2RlcmVxXygnLi9saWIvcmF0aW9uYWxpemUnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGRpdlxuXG5mdW5jdGlvbiBkaXYoYSwgYikge1xuICByZXR1cm4gcmF0aW9uYWxpemUoYVswXS5tdWwoYlsxXSksIGFbMV0ubXVsKGJbMF0pKVxufVxuXG59LHtcIi4vbGliL3JhdGlvbmFsaXplXCI6ODV9XSw3ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGlzUmF0ID0gX2RlcmVxXygnLi9pcy1yYXQnKVxudmFyIGlzQk4gPSBfZGVyZXFfKCcuL2xpYi9pcy1ibicpXG52YXIgbnVtMmJuID0gX2RlcmVxXygnLi9saWIvbnVtLXRvLWJuJylcbnZhciBzdHIyYm4gPSBfZGVyZXFfKCcuL2xpYi9zdHItdG8tYm4nKVxudmFyIHJhdGlvbmFsaXplID0gX2RlcmVxXygnLi9saWIvcmF0aW9uYWxpemUnKVxudmFyIGRpdiA9IF9kZXJlcV8oJy4vZGl2JylcblxubW9kdWxlLmV4cG9ydHMgPSBtYWtlUmF0aW9uYWxcblxuZnVuY3Rpb24gbWFrZVJhdGlvbmFsKG51bWVyLCBkZW5vbSkge1xuICBpZihpc1JhdChudW1lcikpIHtcbiAgICBpZihkZW5vbSkge1xuICAgICAgcmV0dXJuIGRpdihudW1lciwgbWFrZVJhdGlvbmFsKGRlbm9tKSlcbiAgICB9XG4gICAgcmV0dXJuIFtudW1lclswXS5jbG9uZSgpLCBudW1lclsxXS5jbG9uZSgpXVxuICB9XG4gIHZhciBzaGlmdCA9IDBcbiAgdmFyIGEsIGJcbiAgaWYoaXNCTihudW1lcikpIHtcbiAgICBhID0gbnVtZXIuY2xvbmUoKVxuICB9IGVsc2UgaWYodHlwZW9mIG51bWVyID09PSAnc3RyaW5nJykge1xuICAgIGEgPSBzdHIyYm4obnVtZXIpXG4gIH0gZWxzZSBpZihudW1lciA9PT0gMCkge1xuICAgIHJldHVybiBbbnVtMmJuKDApLCBudW0yYm4oMSldXG4gIH0gZWxzZSBpZihudW1lciA9PT0gTWF0aC5mbG9vcihudW1lcikpIHtcbiAgICBhID0gbnVtMmJuKG51bWVyKVxuICB9IGVsc2Uge1xuICAgIHdoaWxlKG51bWVyICE9PSBNYXRoLmZsb29yKG51bWVyKSkge1xuICAgICAgbnVtZXIgPSBudW1lciAqIE1hdGgucG93KDIsIDI1NilcbiAgICAgIHNoaWZ0IC09IDI1NlxuICAgIH1cbiAgICBhID0gbnVtMmJuKG51bWVyKVxuICB9XG4gIGlmKGlzUmF0KGRlbm9tKSkge1xuICAgIGEubXVsKGRlbm9tWzFdKVxuICAgIGIgPSBkZW5vbVswXS5jbG9uZSgpXG4gIH0gZWxzZSBpZihpc0JOKGRlbm9tKSkge1xuICAgIGIgPSBkZW5vbS5jbG9uZSgpXG4gIH0gZWxzZSBpZih0eXBlb2YgZGVub20gPT09ICdzdHJpbmcnKSB7XG4gICAgYiA9IHN0cjJibihkZW5vbSlcbiAgfSBlbHNlIGlmKCFkZW5vbSkge1xuICAgIGIgPSBudW0yYm4oMSlcbiAgfSBlbHNlIGlmKGRlbm9tID09PSBNYXRoLmZsb29yKGRlbm9tKSkge1xuICAgIGIgPSBudW0yYm4oZGVub20pXG4gIH0gZWxzZSB7XG4gICAgd2hpbGUoZGVub20gIT09IE1hdGguZmxvb3IoZGVub20pKSB7XG4gICAgICBkZW5vbSA9IGRlbm9tICogTWF0aC5wb3coMiwgMjU2KVxuICAgICAgc2hpZnQgKz0gMjU2XG4gICAgfVxuICAgIGIgPSBudW0yYm4oZGVub20pXG4gIH1cbiAgaWYoc2hpZnQgPiAwKSB7XG4gICAgYSA9IGEudXNobG4oc2hpZnQpXG4gIH0gZWxzZSBpZihzaGlmdCA8IDApIHtcbiAgICBiID0gYi51c2hsbigtc2hpZnQpXG4gIH1cbiAgcmV0dXJuIHJhdGlvbmFsaXplKGEsIGIpXG59XG5cbn0se1wiLi9kaXZcIjo3NyxcIi4vaXMtcmF0XCI6NzksXCIuL2xpYi9pcy1iblwiOjgzLFwiLi9saWIvbnVtLXRvLWJuXCI6ODQsXCIuL2xpYi9yYXRpb25hbGl6ZVwiOjg1LFwiLi9saWIvc3RyLXRvLWJuXCI6ODZ9XSw3OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGlzQk4gPSBfZGVyZXFfKCcuL2xpYi9pcy1ibicpXG5cbm1vZHVsZS5leHBvcnRzID0gaXNSYXRcblxuZnVuY3Rpb24gaXNSYXQoeCkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh4KSAmJiB4Lmxlbmd0aCA9PT0gMiAmJiBpc0JOKHhbMF0pICYmIGlzQk4oeFsxXSlcbn1cblxufSx7XCIuL2xpYi9pcy1iblwiOjgzfV0sODA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBCTiA9IF9kZXJlcV8oJ2JuLmpzJylcblxubW9kdWxlLmV4cG9ydHMgPSBzaWduXG5cbmZ1bmN0aW9uIHNpZ24gKHgpIHtcbiAgcmV0dXJuIHguY21wKG5ldyBCTigwKSlcbn1cblxufSx7XCJibi5qc1wiOjk0fV0sODE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBzaWduID0gX2RlcmVxXygnLi9ibi1zaWduJylcblxubW9kdWxlLmV4cG9ydHMgPSBibjJudW1cblxuLy9UT0RPOiBNYWtlIHRoaXMgYmV0dGVyXG5mdW5jdGlvbiBibjJudW0oYikge1xuICB2YXIgbCA9IGIubGVuZ3RoXG4gIHZhciB3b3JkcyA9IGIud29yZHNcbiAgdmFyIG91dCA9IDBcbiAgaWYgKGwgPT09IDEpIHtcbiAgICBvdXQgPSB3b3Jkc1swXVxuICB9IGVsc2UgaWYgKGwgPT09IDIpIHtcbiAgICBvdXQgPSB3b3Jkc1swXSArICh3b3Jkc1sxXSAqIDB4NDAwMDAwMClcbiAgfSBlbHNlIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgdmFyIHcgPSB3b3Jkc1tpXVxuICAgICAgb3V0ICs9IHcgKiBNYXRoLnBvdygweDQwMDAwMDAsIGkpXG4gICAgfVxuICB9XG4gIHJldHVybiBzaWduKGIpICogb3V0XG59XG5cbn0se1wiLi9ibi1zaWduXCI6ODB9XSw4MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGRiID0gX2RlcmVxXygnZG91YmxlLWJpdHMnKVxudmFyIGN0eiA9IF9kZXJlcV8oJ2JpdC10d2lkZGxlJykuY291bnRUcmFpbGluZ1plcm9zXG5cbm1vZHVsZS5leHBvcnRzID0gY3R6TnVtYmVyXG5cbi8vQ291bnRzIHRoZSBudW1iZXIgb2YgdHJhaWxpbmcgemVyb3NcbmZ1bmN0aW9uIGN0ek51bWJlcih4KSB7XG4gIHZhciBsID0gY3R6KGRiLmxvKHgpKVxuICBpZihsIDwgMzIpIHtcbiAgICByZXR1cm4gbFxuICB9XG4gIHZhciBoID0gY3R6KGRiLmhpKHgpKVxuICBpZihoID4gMjApIHtcbiAgICByZXR1cm4gNTJcbiAgfVxuICByZXR1cm4gaCArIDMyXG59XG5cbn0se1wiYml0LXR3aWRkbGVcIjo5MixcImRvdWJsZS1iaXRzXCI6MTY3fV0sODM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBCTiA9IF9kZXJlcV8oJ2JuLmpzJylcblxubW9kdWxlLmV4cG9ydHMgPSBpc0JOXG5cbi8vVGVzdCBpZiB4IGlzIGEgYmlnbnVtYmVyXG4vL0ZJWE1FOiBvYnZpb3VzbHkgdGhpcyBpcyB0aGUgd3Jvbmcgd2F5IHRvIGRvIGl0XG5mdW5jdGlvbiBpc0JOKHgpIHtcbiAgcmV0dXJuIHggJiYgdHlwZW9mIHggPT09ICdvYmplY3QnICYmIEJvb2xlYW4oeC53b3Jkcylcbn1cblxufSx7XCJibi5qc1wiOjk0fV0sODQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBCTiA9IF9kZXJlcV8oJ2JuLmpzJylcbnZhciBkYiA9IF9kZXJlcV8oJ2RvdWJsZS1iaXRzJylcblxubW9kdWxlLmV4cG9ydHMgPSBudW0yYm5cblxuZnVuY3Rpb24gbnVtMmJuKHgpIHtcbiAgdmFyIGUgPSBkYi5leHBvbmVudCh4KVxuICBpZihlIDwgNTIpIHtcbiAgICByZXR1cm4gbmV3IEJOKHgpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIChuZXcgQk4oeCAqIE1hdGgucG93KDIsIDUyLWUpKSkudXNobG4oZS01MilcbiAgfVxufVxuXG59LHtcImJuLmpzXCI6OTQsXCJkb3VibGUtYml0c1wiOjE2N31dLDg1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgbnVtMmJuID0gX2RlcmVxXygnLi9udW0tdG8tYm4nKVxudmFyIHNpZ24gPSBfZGVyZXFfKCcuL2JuLXNpZ24nKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHJhdGlvbmFsaXplXG5cbmZ1bmN0aW9uIHJhdGlvbmFsaXplKG51bWVyLCBkZW5vbSkge1xuICB2YXIgc251bWVyID0gc2lnbihudW1lcilcbiAgdmFyIHNkZW5vbSA9IHNpZ24oZGVub20pXG4gIGlmKHNudW1lciA9PT0gMCkge1xuICAgIHJldHVybiBbbnVtMmJuKDApLCBudW0yYm4oMSldXG4gIH1cbiAgaWYoc2Rlbm9tID09PSAwKSB7XG4gICAgcmV0dXJuIFtudW0yYm4oMCksIG51bTJibigwKV1cbiAgfVxuICBpZihzZGVub20gPCAwKSB7XG4gICAgbnVtZXIgPSBudW1lci5uZWcoKVxuICAgIGRlbm9tID0gZGVub20ubmVnKClcbiAgfVxuICB2YXIgZCA9IG51bWVyLmdjZChkZW5vbSlcbiAgaWYoZC5jbXBuKDEpKSB7XG4gICAgcmV0dXJuIFsgbnVtZXIuZGl2KGQpLCBkZW5vbS5kaXYoZCkgXVxuICB9XG4gIHJldHVybiBbIG51bWVyLCBkZW5vbSBdXG59XG5cbn0se1wiLi9ibi1zaWduXCI6ODAsXCIuL251bS10by1iblwiOjg0fV0sODY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBCTiA9IF9kZXJlcV8oJ2JuLmpzJylcblxubW9kdWxlLmV4cG9ydHMgPSBzdHIyQk5cblxuZnVuY3Rpb24gc3RyMkJOKHgpIHtcbiAgcmV0dXJuIG5ldyBCTih4KVxufVxuXG59LHtcImJuLmpzXCI6OTR9XSw4NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIHJhdGlvbmFsaXplID0gX2RlcmVxXygnLi9saWIvcmF0aW9uYWxpemUnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IG11bFxuXG5mdW5jdGlvbiBtdWwoYSwgYikge1xuICByZXR1cm4gcmF0aW9uYWxpemUoYVswXS5tdWwoYlswXSksIGFbMV0ubXVsKGJbMV0pKVxufVxuXG59LHtcIi4vbGliL3JhdGlvbmFsaXplXCI6ODV9XSw4ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGJuc2lnbiA9IF9kZXJlcV8oJy4vbGliL2JuLXNpZ24nKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHNpZ25cblxuZnVuY3Rpb24gc2lnbih4KSB7XG4gIHJldHVybiBibnNpZ24oeFswXSkgKiBibnNpZ24oeFsxXSlcbn1cblxufSx7XCIuL2xpYi9ibi1zaWduXCI6ODB9XSw4OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIHJhdGlvbmFsaXplID0gX2RlcmVxXygnLi9saWIvcmF0aW9uYWxpemUnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHN1YlxuXG5mdW5jdGlvbiBzdWIoYSwgYikge1xuICByZXR1cm4gcmF0aW9uYWxpemUoYVswXS5tdWwoYlsxXSkuc3ViKGFbMV0ubXVsKGJbMF0pKSwgYVsxXS5tdWwoYlsxXSkpXG59XG5cbn0se1wiLi9saWIvcmF0aW9uYWxpemVcIjo4NX1dLDkwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgYm4ybnVtID0gX2RlcmVxXygnLi9saWIvYm4tdG8tbnVtJylcbnZhciBjdHogPSBfZGVyZXFfKCcuL2xpYi9jdHonKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHJvdW5kUmF0XG5cbi8vIFJvdW5kIGEgcmF0aW9uYWwgdG8gdGhlIGNsb3Nlc3QgZmxvYXRcbmZ1bmN0aW9uIHJvdW5kUmF0IChmKSB7XG4gIHZhciBhID0gZlswXVxuICB2YXIgYiA9IGZbMV1cbiAgaWYgKGEuY21wbigwKSA9PT0gMCkge1xuICAgIHJldHVybiAwXG4gIH1cbiAgdmFyIGggPSBhLmFicygpLmRpdm1vZChiLmFicygpKVxuICB2YXIgaXYgPSBoLmRpdlxuICB2YXIgeCA9IGJuMm51bShpdilcbiAgdmFyIGlyID0gaC5tb2RcbiAgdmFyIHNnbiA9IChhLm5lZ2F0aXZlICE9PSBiLm5lZ2F0aXZlKSA/IC0xIDogMVxuICBpZiAoaXIuY21wbigwKSA9PT0gMCkge1xuICAgIHJldHVybiBzZ24gKiB4XG4gIH1cbiAgaWYgKHgpIHtcbiAgICB2YXIgcyA9IGN0eih4KSArIDRcbiAgICB2YXIgeSA9IGJuMm51bShpci51c2hsbihzKS5kaXZSb3VuZChiKSlcbiAgICByZXR1cm4gc2duICogKHggKyB5ICogTWF0aC5wb3coMiwgLXMpKVxuICB9IGVsc2Uge1xuICAgIHZhciB5Yml0cyA9IGIuYml0TGVuZ3RoKCkgLSBpci5iaXRMZW5ndGgoKSArIDUzXG4gICAgdmFyIHkgPSBibjJudW0oaXIudXNobG4oeWJpdHMpLmRpdlJvdW5kKGIpKVxuICAgIGlmICh5Yml0cyA8IDEwMjMpIHtcbiAgICAgIHJldHVybiBzZ24gKiB5ICogTWF0aC5wb3coMiwgLXliaXRzKVxuICAgIH1cbiAgICB5ICo9IE1hdGgucG93KDIsIC0xMDIzKVxuICAgIHJldHVybiBzZ24gKiB5ICogTWF0aC5wb3coMiwgMTAyMyAtIHliaXRzKVxuICB9XG59XG5cbn0se1wiLi9saWIvYm4tdG8tbnVtXCI6ODEsXCIuL2xpYi9jdHpcIjo4Mn1dLDkxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbmZ1bmN0aW9uIGNvbXBpbGVTZWFyY2goZnVuY05hbWUsIHByZWRpY2F0ZSwgcmV2ZXJzZWQsIGV4dHJhQXJncywgdXNlTmRhcnJheSwgZWFybHlPdXQpIHtcbiAgdmFyIGNvZGUgPSBbXG4gICAgXCJmdW5jdGlvbiBcIiwgZnVuY05hbWUsIFwiKGEsbCxoLFwiLCBleHRyYUFyZ3Muam9pbihcIixcIiksICBcIil7XCIsXG5lYXJseU91dCA/IFwiXCIgOiBcInZhciBpPVwiLCAocmV2ZXJzZWQgPyBcImwtMVwiIDogXCJoKzFcIiksXG5cIjt3aGlsZShsPD1oKXtcXFxudmFyIG09KGwraCk+Pj4xLHg9YVwiLCB1c2VOZGFycmF5ID8gXCIuZ2V0KG0pXCIgOiBcIlttXVwiXVxuICBpZihlYXJseU91dCkge1xuICAgIGlmKHByZWRpY2F0ZS5pbmRleE9mKFwiY1wiKSA8IDApIHtcbiAgICAgIGNvZGUucHVzaChcIjtpZih4PT09eSl7cmV0dXJuIG19ZWxzZSBpZih4PD15KXtcIilcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZS5wdXNoKFwiO3ZhciBwPWMoeCx5KTtpZihwPT09MCl7cmV0dXJuIG19ZWxzZSBpZihwPD0wKXtcIilcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwiO2lmKFwiLCBwcmVkaWNhdGUsIFwiKXtpPW07XCIpXG4gIH1cbiAgaWYocmV2ZXJzZWQpIHtcbiAgICBjb2RlLnB1c2goXCJsPW0rMX1lbHNle2g9bS0xfVwiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcImg9bS0xfWVsc2V7bD1tKzF9XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwifVwiKVxuICBpZihlYXJseU91dCkge1xuICAgIGNvZGUucHVzaChcInJldHVybiAtMX07XCIpXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwicmV0dXJuIGl9O1wiKVxuICB9XG4gIHJldHVybiBjb2RlLmpvaW4oXCJcIilcbn1cblxuZnVuY3Rpb24gY29tcGlsZUJvdW5kc1NlYXJjaChwcmVkaWNhdGUsIHJldmVyc2VkLCBzdWZmaXgsIGVhcmx5T3V0KSB7XG4gIHZhciByZXN1bHQgPSBuZXcgRnVuY3Rpb24oW1xuICBjb21waWxlU2VhcmNoKFwiQVwiLCBcInhcIiArIHByZWRpY2F0ZSArIFwieVwiLCByZXZlcnNlZCwgW1wieVwiXSwgZmFsc2UsIGVhcmx5T3V0KSxcbiAgY29tcGlsZVNlYXJjaChcIkJcIiwgXCJ4XCIgKyBwcmVkaWNhdGUgKyBcInlcIiwgcmV2ZXJzZWQsIFtcInlcIl0sIHRydWUsIGVhcmx5T3V0KSxcbiAgY29tcGlsZVNlYXJjaChcIlBcIiwgXCJjKHgseSlcIiArIHByZWRpY2F0ZSArIFwiMFwiLCByZXZlcnNlZCwgW1wieVwiLCBcImNcIl0sIGZhbHNlLCBlYXJseU91dCksXG4gIGNvbXBpbGVTZWFyY2goXCJRXCIsIFwiYyh4LHkpXCIgKyBwcmVkaWNhdGUgKyBcIjBcIiwgcmV2ZXJzZWQsIFtcInlcIiwgXCJjXCJdLCB0cnVlLCBlYXJseU91dCksXG5cImZ1bmN0aW9uIGRpc3BhdGNoQnNlYXJjaFwiLCBzdWZmaXgsIFwiKGEseSxjLGwsaCl7XFxcbmlmKGEuc2hhcGUpe1xcXG5pZih0eXBlb2YoYyk9PT0nZnVuY3Rpb24nKXtcXFxucmV0dXJuIFEoYSwobD09PXVuZGVmaW5lZCk/MDpsfDAsKGg9PT11bmRlZmluZWQpP2Euc2hhcGVbMF0tMTpofDAseSxjKVxcXG59ZWxzZXtcXFxucmV0dXJuIEIoYSwoYz09PXVuZGVmaW5lZCk/MDpjfDAsKGw9PT11bmRlZmluZWQpP2Euc2hhcGVbMF0tMTpsfDAseSlcXFxufX1lbHNle1xcXG5pZih0eXBlb2YoYyk9PT0nZnVuY3Rpb24nKXtcXFxucmV0dXJuIFAoYSwobD09PXVuZGVmaW5lZCk/MDpsfDAsKGg9PT11bmRlZmluZWQpP2EubGVuZ3RoLTE6aHwwLHksYylcXFxufWVsc2V7XFxcbnJldHVybiBBKGEsKGM9PT11bmRlZmluZWQpPzA6Y3wwLChsPT09dW5kZWZpbmVkKT9hLmxlbmd0aC0xOmx8MCx5KVxcXG59fX1cXFxucmV0dXJuIGRpc3BhdGNoQnNlYXJjaFwiLCBzdWZmaXhdLmpvaW4oXCJcIikpXG4gIHJldHVybiByZXN1bHQoKVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZ2U6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCI+PVwiLCBmYWxzZSwgXCJHRVwiKSxcbiAgZ3Q6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCI+XCIsIGZhbHNlLCBcIkdUXCIpLFxuICBsdDogY29tcGlsZUJvdW5kc1NlYXJjaChcIjxcIiwgdHJ1ZSwgXCJMVFwiKSxcbiAgbGU6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCI8PVwiLCB0cnVlLCBcIkxFXCIpLFxuICBlcTogY29tcGlsZUJvdW5kc1NlYXJjaChcIi1cIiwgdHJ1ZSwgXCJFUVwiLCB0cnVlKVxufVxuXG59LHt9XSw5MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiAqIEJpdCB0d2lkZGxpbmcgaGFja3MgZm9yIEphdmFTY3JpcHQuXG4gKlxuICogQXV0aG9yOiBNaWtvbGEgTHlzZW5rb1xuICpcbiAqIFBvcnRlZCBmcm9tIFN0YW5mb3JkIGJpdCB0d2lkZGxpbmcgaGFjayBsaWJyYXJ5OlxuICogICAgaHR0cDovL2dyYXBoaWNzLnN0YW5mb3JkLmVkdS9+c2VhbmRlci9iaXRoYWNrcy5odG1sXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7IFwidXNlIHJlc3RyaWN0XCI7XG5cbi8vTnVtYmVyIG9mIGJpdHMgaW4gYW4gaW50ZWdlclxudmFyIElOVF9CSVRTID0gMzI7XG5cbi8vQ29uc3RhbnRzXG5leHBvcnRzLklOVF9CSVRTICA9IElOVF9CSVRTO1xuZXhwb3J0cy5JTlRfTUFYICAgPSAgMHg3ZmZmZmZmZjtcbmV4cG9ydHMuSU5UX01JTiAgID0gLTE8PChJTlRfQklUUy0xKTtcblxuLy9SZXR1cm5zIC0xLCAwLCArMSBkZXBlbmRpbmcgb24gc2lnbiBvZiB4XG5leHBvcnRzLnNpZ24gPSBmdW5jdGlvbih2KSB7XG4gIHJldHVybiAodiA+IDApIC0gKHYgPCAwKTtcbn1cblxuLy9Db21wdXRlcyBhYnNvbHV0ZSB2YWx1ZSBvZiBpbnRlZ2VyXG5leHBvcnRzLmFicyA9IGZ1bmN0aW9uKHYpIHtcbiAgdmFyIG1hc2sgPSB2ID4+IChJTlRfQklUUy0xKTtcbiAgcmV0dXJuICh2IF4gbWFzaykgLSBtYXNrO1xufVxuXG4vL0NvbXB1dGVzIG1pbmltdW0gb2YgaW50ZWdlcnMgeCBhbmQgeVxuZXhwb3J0cy5taW4gPSBmdW5jdGlvbih4LCB5KSB7XG4gIHJldHVybiB5IF4gKCh4IF4geSkgJiAtKHggPCB5KSk7XG59XG5cbi8vQ29tcHV0ZXMgbWF4aW11bSBvZiBpbnRlZ2VycyB4IGFuZCB5XG5leHBvcnRzLm1heCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgcmV0dXJuIHggXiAoKHggXiB5KSAmIC0oeCA8IHkpKTtcbn1cblxuLy9DaGVja3MgaWYgYSBudW1iZXIgaXMgYSBwb3dlciBvZiB0d29cbmV4cG9ydHMuaXNQb3cyID0gZnVuY3Rpb24odikge1xuICByZXR1cm4gISh2ICYgKHYtMSkpICYmICghIXYpO1xufVxuXG4vL0NvbXB1dGVzIGxvZyBiYXNlIDIgb2YgdlxuZXhwb3J0cy5sb2cyID0gZnVuY3Rpb24odikge1xuICB2YXIgciwgc2hpZnQ7XG4gIHIgPSAgICAgKHYgPiAweEZGRkYpIDw8IDQ7IHYgPj4+PSByO1xuICBzaGlmdCA9ICh2ID4gMHhGRiAgKSA8PCAzOyB2ID4+Pj0gc2hpZnQ7IHIgfD0gc2hpZnQ7XG4gIHNoaWZ0ID0gKHYgPiAweEYgICApIDw8IDI7IHYgPj4+PSBzaGlmdDsgciB8PSBzaGlmdDtcbiAgc2hpZnQgPSAodiA+IDB4MyAgICkgPDwgMTsgdiA+Pj49IHNoaWZ0OyByIHw9IHNoaWZ0O1xuICByZXR1cm4gciB8ICh2ID4+IDEpO1xufVxuXG4vL0NvbXB1dGVzIGxvZyBiYXNlIDEwIG9mIHZcbmV4cG9ydHMubG9nMTAgPSBmdW5jdGlvbih2KSB7XG4gIHJldHVybiAgKHYgPj0gMTAwMDAwMDAwMCkgPyA5IDogKHYgPj0gMTAwMDAwMDAwKSA/IDggOiAodiA+PSAxMDAwMDAwMCkgPyA3IDpcbiAgICAgICAgICAodiA+PSAxMDAwMDAwKSA/IDYgOiAodiA+PSAxMDAwMDApID8gNSA6ICh2ID49IDEwMDAwKSA/IDQgOlxuICAgICAgICAgICh2ID49IDEwMDApID8gMyA6ICh2ID49IDEwMCkgPyAyIDogKHYgPj0gMTApID8gMSA6IDA7XG59XG5cbi8vQ291bnRzIG51bWJlciBvZiBiaXRzXG5leHBvcnRzLnBvcENvdW50ID0gZnVuY3Rpb24odikge1xuICB2ID0gdiAtICgodiA+Pj4gMSkgJiAweDU1NTU1NTU1KTtcbiAgdiA9ICh2ICYgMHgzMzMzMzMzMykgKyAoKHYgPj4+IDIpICYgMHgzMzMzMzMzMyk7XG4gIHJldHVybiAoKHYgKyAodiA+Pj4gNCkgJiAweEYwRjBGMEYpICogMHgxMDEwMTAxKSA+Pj4gMjQ7XG59XG5cbi8vQ291bnRzIG51bWJlciBvZiB0cmFpbGluZyB6ZXJvc1xuZnVuY3Rpb24gY291bnRUcmFpbGluZ1plcm9zKHYpIHtcbiAgdmFyIGMgPSAzMjtcbiAgdiAmPSAtdjtcbiAgaWYgKHYpIGMtLTtcbiAgaWYgKHYgJiAweDAwMDBGRkZGKSBjIC09IDE2O1xuICBpZiAodiAmIDB4MDBGRjAwRkYpIGMgLT0gODtcbiAgaWYgKHYgJiAweDBGMEYwRjBGKSBjIC09IDQ7XG4gIGlmICh2ICYgMHgzMzMzMzMzMykgYyAtPSAyO1xuICBpZiAodiAmIDB4NTU1NTU1NTUpIGMgLT0gMTtcbiAgcmV0dXJuIGM7XG59XG5leHBvcnRzLmNvdW50VHJhaWxpbmdaZXJvcyA9IGNvdW50VHJhaWxpbmdaZXJvcztcblxuLy9Sb3VuZHMgdG8gbmV4dCBwb3dlciBvZiAyXG5leHBvcnRzLm5leHRQb3cyID0gZnVuY3Rpb24odikge1xuICB2ICs9IHYgPT09IDA7XG4gIC0tdjtcbiAgdiB8PSB2ID4+PiAxO1xuICB2IHw9IHYgPj4+IDI7XG4gIHYgfD0gdiA+Pj4gNDtcbiAgdiB8PSB2ID4+PiA4O1xuICB2IHw9IHYgPj4+IDE2O1xuICByZXR1cm4gdiArIDE7XG59XG5cbi8vUm91bmRzIGRvd24gdG8gcHJldmlvdXMgcG93ZXIgb2YgMlxuZXhwb3J0cy5wcmV2UG93MiA9IGZ1bmN0aW9uKHYpIHtcbiAgdiB8PSB2ID4+PiAxO1xuICB2IHw9IHYgPj4+IDI7XG4gIHYgfD0gdiA+Pj4gNDtcbiAgdiB8PSB2ID4+PiA4O1xuICB2IHw9IHYgPj4+IDE2O1xuICByZXR1cm4gdiAtICh2Pj4+MSk7XG59XG5cbi8vQ29tcHV0ZXMgcGFyaXR5IG9mIHdvcmRcbmV4cG9ydHMucGFyaXR5ID0gZnVuY3Rpb24odikge1xuICB2IF49IHYgPj4+IDE2O1xuICB2IF49IHYgPj4+IDg7XG4gIHYgXj0gdiA+Pj4gNDtcbiAgdiAmPSAweGY7XG4gIHJldHVybiAoMHg2OTk2ID4+PiB2KSAmIDE7XG59XG5cbnZhciBSRVZFUlNFX1RBQkxFID0gbmV3IEFycmF5KDI1Nik7XG5cbihmdW5jdGlvbih0YWIpIHtcbiAgZm9yKHZhciBpPTA7IGk8MjU2OyArK2kpIHtcbiAgICB2YXIgdiA9IGksIHIgPSBpLCBzID0gNztcbiAgICBmb3IgKHYgPj4+PSAxOyB2OyB2ID4+Pj0gMSkge1xuICAgICAgciA8PD0gMTtcbiAgICAgIHIgfD0gdiAmIDE7XG4gICAgICAtLXM7XG4gICAgfVxuICAgIHRhYltpXSA9IChyIDw8IHMpICYgMHhmZjtcbiAgfVxufSkoUkVWRVJTRV9UQUJMRSk7XG5cbi8vUmV2ZXJzZSBiaXRzIGluIGEgMzIgYml0IHdvcmRcbmV4cG9ydHMucmV2ZXJzZSA9IGZ1bmN0aW9uKHYpIHtcbiAgcmV0dXJuICAoUkVWRVJTRV9UQUJMRVsgdiAgICAgICAgICYgMHhmZl0gPDwgMjQpIHxcbiAgICAgICAgICAoUkVWRVJTRV9UQUJMRVsodiA+Pj4gOCkgICYgMHhmZl0gPDwgMTYpIHxcbiAgICAgICAgICAoUkVWRVJTRV9UQUJMRVsodiA+Pj4gMTYpICYgMHhmZl0gPDwgOCkgIHxcbiAgICAgICAgICAgUkVWRVJTRV9UQUJMRVsodiA+Pj4gMjQpICYgMHhmZl07XG59XG5cbi8vSW50ZXJsZWF2ZSBiaXRzIG9mIDIgY29vcmRpbmF0ZXMgd2l0aCAxNiBiaXRzLiAgVXNlZnVsIGZvciBmYXN0IHF1YWR0cmVlIGNvZGVzXG5leHBvcnRzLmludGVybGVhdmUyID0gZnVuY3Rpb24oeCwgeSkge1xuICB4ICY9IDB4RkZGRjtcbiAgeCA9ICh4IHwgKHggPDwgOCkpICYgMHgwMEZGMDBGRjtcbiAgeCA9ICh4IHwgKHggPDwgNCkpICYgMHgwRjBGMEYwRjtcbiAgeCA9ICh4IHwgKHggPDwgMikpICYgMHgzMzMzMzMzMztcbiAgeCA9ICh4IHwgKHggPDwgMSkpICYgMHg1NTU1NTU1NTtcblxuICB5ICY9IDB4RkZGRjtcbiAgeSA9ICh5IHwgKHkgPDwgOCkpICYgMHgwMEZGMDBGRjtcbiAgeSA9ICh5IHwgKHkgPDwgNCkpICYgMHgwRjBGMEYwRjtcbiAgeSA9ICh5IHwgKHkgPDwgMikpICYgMHgzMzMzMzMzMztcbiAgeSA9ICh5IHwgKHkgPDwgMSkpICYgMHg1NTU1NTU1NTtcblxuICByZXR1cm4geCB8ICh5IDw8IDEpO1xufVxuXG4vL0V4dHJhY3RzIHRoZSBudGggaW50ZXJsZWF2ZWQgY29tcG9uZW50XG5leHBvcnRzLmRlaW50ZXJsZWF2ZTIgPSBmdW5jdGlvbih2LCBuKSB7XG4gIHYgPSAodiA+Pj4gbikgJiAweDU1NTU1NTU1O1xuICB2ID0gKHYgfCAodiA+Pj4gMSkpICAmIDB4MzMzMzMzMzM7XG4gIHYgPSAodiB8ICh2ID4+PiAyKSkgICYgMHgwRjBGMEYwRjtcbiAgdiA9ICh2IHwgKHYgPj4+IDQpKSAgJiAweDAwRkYwMEZGO1xuICB2ID0gKHYgfCAodiA+Pj4gMTYpKSAmIDB4MDAwRkZGRjtcbiAgcmV0dXJuICh2IDw8IDE2KSA+PiAxNjtcbn1cblxuXG4vL0ludGVybGVhdmUgYml0cyBvZiAzIGNvb3JkaW5hdGVzLCBlYWNoIHdpdGggMTAgYml0cy4gIFVzZWZ1bCBmb3IgZmFzdCBvY3RyZWUgY29kZXNcbmV4cG9ydHMuaW50ZXJsZWF2ZTMgPSBmdW5jdGlvbih4LCB5LCB6KSB7XG4gIHggJj0gMHgzRkY7XG4gIHggID0gKHggfCAoeDw8MTYpKSAmIDQyNzgxOTAzMzU7XG4gIHggID0gKHggfCAoeDw8OCkpICAmIDI1MTcxOTY5NTtcbiAgeCAgPSAoeCB8ICh4PDw0KSkgICYgMzI3MjM1NjAzNTtcbiAgeCAgPSAoeCB8ICh4PDwyKSkgICYgMTIyNzEzMzUxMztcblxuICB5ICY9IDB4M0ZGO1xuICB5ICA9ICh5IHwgKHk8PDE2KSkgJiA0Mjc4MTkwMzM1O1xuICB5ICA9ICh5IHwgKHk8PDgpKSAgJiAyNTE3MTk2OTU7XG4gIHkgID0gKHkgfCAoeTw8NCkpICAmIDMyNzIzNTYwMzU7XG4gIHkgID0gKHkgfCAoeTw8MikpICAmIDEyMjcxMzM1MTM7XG4gIHggfD0gKHkgPDwgMSk7XG4gIFxuICB6ICY9IDB4M0ZGO1xuICB6ICA9ICh6IHwgKHo8PDE2KSkgJiA0Mjc4MTkwMzM1O1xuICB6ICA9ICh6IHwgKHo8PDgpKSAgJiAyNTE3MTk2OTU7XG4gIHogID0gKHogfCAoejw8NCkpICAmIDMyNzIzNTYwMzU7XG4gIHogID0gKHogfCAoejw8MikpICAmIDEyMjcxMzM1MTM7XG4gIFxuICByZXR1cm4geCB8ICh6IDw8IDIpO1xufVxuXG4vL0V4dHJhY3RzIG50aCBpbnRlcmxlYXZlZCBjb21wb25lbnQgb2YgYSAzLXR1cGxlXG5leHBvcnRzLmRlaW50ZXJsZWF2ZTMgPSBmdW5jdGlvbih2LCBuKSB7XG4gIHYgPSAodiA+Pj4gbikgICAgICAgJiAxMjI3MTMzNTEzO1xuICB2ID0gKHYgfCAodj4+PjIpKSAgICYgMzI3MjM1NjAzNTtcbiAgdiA9ICh2IHwgKHY+Pj40KSkgICAmIDI1MTcxOTY5NTtcbiAgdiA9ICh2IHwgKHY+Pj44KSkgICAmIDQyNzgxOTAzMzU7XG4gIHYgPSAodiB8ICh2Pj4+MTYpKSAgJiAweDNGRjtcbiAgcmV0dXJuICh2PDwyMik+PjIyO1xufVxuXG4vL0NvbXB1dGVzIG5leHQgY29tYmluYXRpb24gaW4gY29sZXhpY29ncmFwaGljIG9yZGVyICh0aGlzIGlzIG1pc3Rha2VubHkgY2FsbGVkIG5leHRQZXJtdXRhdGlvbiBvbiB0aGUgYml0IHR3aWRkbGluZyBoYWNrcyBwYWdlKVxuZXhwb3J0cy5uZXh0Q29tYmluYXRpb24gPSBmdW5jdGlvbih2KSB7XG4gIHZhciB0ID0gdiB8ICh2IC0gMSk7XG4gIHJldHVybiAodCArIDEpIHwgKCgofnQgJiAtfnQpIC0gMSkgPj4+IChjb3VudFRyYWlsaW5nWmVyb3ModikgKyAxKSk7XG59XG5cblxufSx7fV0sOTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgY2xhbXAgPSBfZGVyZXFfKCdjbGFtcCcpXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNhbGNTREZcclxuXHJcbnZhciBJTkYgPSAxZTIwO1xyXG5cclxuZnVuY3Rpb24gY2FsY1NERihzcmMsIG9wdGlvbnMpIHtcclxuICAgIGlmICghb3B0aW9ucykgb3B0aW9ucyA9IHt9XHJcblxyXG4gICAgdmFyIGN1dG9mZiA9IG9wdGlvbnMuY3V0b2ZmID09IG51bGwgPyAwLjI1IDogb3B0aW9ucy5jdXRvZmZcclxuICAgIHZhciByYWRpdXMgPSBvcHRpb25zLnJhZGl1cyA9PSBudWxsID8gOCA6IG9wdGlvbnMucmFkaXVzXHJcbiAgICB2YXIgY2hhbm5lbCA9IG9wdGlvbnMuY2hhbm5lbCB8fCAwXHJcbiAgICB2YXIgdywgaCwgc2l6ZSwgZGF0YSwgaW50RGF0YSwgc3RyaWRlLCBjdHgsIGNhbnZhcywgaW1nRGF0YSwgaSwgbFxyXG5cclxuICAgIC8vIGhhbmRsZSBpbWFnZSBjb250YWluZXJcclxuICAgIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoc3JjKSB8fCBBcnJheS5pc0FycmF5KHNyYykpIHtcclxuICAgICAgICBpZiAoIW9wdGlvbnMud2lkdGggfHwgIW9wdGlvbnMuaGVpZ2h0KSB0aHJvdyBFcnJvcignRm9yIHJhdyBkYXRhIHdpZHRoIGFuZCBoZWlnaHQgc2hvdWxkIGJlIHByb3ZpZGVkIGJ5IG9wdGlvbnMnKVxyXG4gICAgICAgIHcgPSBvcHRpb25zLndpZHRoLCBoID0gb3B0aW9ucy5oZWlnaHRcclxuICAgICAgICBkYXRhID0gc3JjXHJcblxyXG4gICAgICAgIGlmICghb3B0aW9ucy5zdHJpZGUpIHN0cmlkZSA9IE1hdGguZmxvb3Ioc3JjLmxlbmd0aCAvIHcgLyBoKVxyXG4gICAgICAgIGVsc2Ugc3RyaWRlID0gb3B0aW9ucy5zdHJpZGVcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICAgIGlmICh3aW5kb3cuSFRNTENhbnZhc0VsZW1lbnQgJiYgc3JjIGluc3RhbmNlb2Ygd2luZG93LkhUTUxDYW52YXNFbGVtZW50KSB7XHJcbiAgICAgICAgICAgIGNhbnZhcyA9IHNyY1xyXG4gICAgICAgICAgICBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKVxyXG4gICAgICAgICAgICB3ID0gY2FudmFzLndpZHRoLCBoID0gY2FudmFzLmhlaWdodFxyXG4gICAgICAgICAgICBpbWdEYXRhID0gY3R4LmdldEltYWdlRGF0YSgwLCAwLCB3LCBoKVxyXG4gICAgICAgICAgICBkYXRhID0gaW1nRGF0YS5kYXRhXHJcbiAgICAgICAgICAgIHN0cmlkZSA9IDRcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAod2luZG93LkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCAmJiBzcmMgaW5zdGFuY2VvZiB3aW5kb3cuQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKSB7XHJcbiAgICAgICAgICAgIGNhbnZhcyA9IHNyYy5jYW52YXNcclxuICAgICAgICAgICAgY3R4ID0gc3JjXHJcbiAgICAgICAgICAgIHcgPSBjYW52YXMud2lkdGgsIGggPSBjYW52YXMuaGVpZ2h0XHJcbiAgICAgICAgICAgIGltZ0RhdGEgPSBjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHcsIGgpXHJcbiAgICAgICAgICAgIGRhdGEgPSBpbWdEYXRhLmRhdGFcclxuICAgICAgICAgICAgc3RyaWRlID0gNFxyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmICh3aW5kb3cuSW1hZ2VEYXRhICYmIHNyYyBpbnN0YW5jZW9mIHdpbmRvdy5JbWFnZURhdGEpIHtcclxuICAgICAgICAgICAgaW1nRGF0YSA9IHNyY1xyXG4gICAgICAgICAgICB3ID0gc3JjLndpZHRoLCBoID0gc3JjLmhlaWdodFxyXG4gICAgICAgICAgICBkYXRhID0gaW1nRGF0YS5kYXRhXHJcbiAgICAgICAgICAgIHN0cmlkZSA9IDRcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgc2l6ZSA9IE1hdGgubWF4KHcsIGgpXHJcblxyXG4gICAgLy9jb252ZXJ0IGludCBkYXRhIHRvIGZsb2F0c1xyXG4gICAgaWYgKCh3aW5kb3cuVWludDhDbGFtcGVkQXJyYXkgJiYgZGF0YSBpbnN0YW5jZW9mIHdpbmRvdy5VaW50OENsYW1wZWRBcnJheSkgfHwgKHdpbmRvdy5VaW50OEFycmF5ICYmIGRhdGEgaW5zdGFuY2VvZiB3aW5kb3cuVWludDhBcnJheSkpIHtcclxuICAgICAgICBpbnREYXRhID0gZGF0YVxyXG4gICAgICAgIGRhdGEgPSBBcnJheSh3KmgpXHJcblxyXG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBpbnREYXRhLmxlbmd0aDsgaSA8IGw7IGkrKykge1xyXG4gICAgICAgICAgICBkYXRhW2ldID0gaW50RGF0YVtpKnN0cmlkZSArIGNoYW5uZWxdIC8gMjU1XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZWxzZSB7XHJcbiAgICAgICAgaWYgKHN0cmlkZSAhPT0gMSkgdGhyb3cgRXJyb3IoJ1JhdyBkYXRhIGNhbiBoYXZlIG9ubHkgMSB2YWx1ZSBwZXIgcGl4ZWwnKVxyXG4gICAgfVxyXG5cclxuICAgIC8vIHRlbXBvcmFyeSBhcnJheXMgZm9yIHRoZSBkaXN0YW5jZSB0cmFuc2Zvcm1cclxuICAgIHZhciBncmlkT3V0ZXIgPSBBcnJheSh3ICogaClcclxuICAgIHZhciBncmlkSW5uZXIgPSBBcnJheSh3ICogaClcclxuICAgIHZhciBmID0gQXJyYXkoc2l6ZSlcclxuICAgIHZhciBkID0gQXJyYXkoc2l6ZSlcclxuICAgIHZhciB6ID0gQXJyYXkoc2l6ZSArIDEpXHJcbiAgICB2YXIgdiA9IEFycmF5KHNpemUpXHJcblxyXG4gICAgZm9yIChpID0gMCwgbCA9IHcgKiBoOyBpIDwgbDsgaSsrKSB7XHJcbiAgICAgICAgdmFyIGEgPSBkYXRhW2ldXHJcbiAgICAgICAgZ3JpZE91dGVyW2ldID0gYSA9PT0gMSA/IDAgOiBhID09PSAwID8gSU5GIDogTWF0aC5wb3coTWF0aC5tYXgoMCwgMC41IC0gYSksIDIpXHJcbiAgICAgICAgZ3JpZElubmVyW2ldID0gYSA9PT0gMSA/IElORiA6IGEgPT09IDAgPyAwIDogTWF0aC5wb3coTWF0aC5tYXgoMCwgYSAtIDAuNSksIDIpXHJcbiAgICB9XHJcblxyXG4gICAgZWR0KGdyaWRPdXRlciwgdywgaCwgZiwgZCwgdiwgeilcclxuICAgIGVkdChncmlkSW5uZXIsIHcsIGgsIGYsIGQsIHYsIHopXHJcblxyXG4gICAgdmFyIGRpc3QgPSB3aW5kb3cuRmxvYXQzMkFycmF5ID8gbmV3IEZsb2F0MzJBcnJheSh3ICogaCkgOiBuZXcgQXJyYXkodyAqIGgpXHJcblxyXG4gICAgZm9yIChpID0gMCwgbCA9IHcqaDsgaSA8IGw7IGkrKykge1xyXG4gICAgICAgIGRpc3RbaV0gPSBjbGFtcCgxIC0gKCAoZ3JpZE91dGVyW2ldIC0gZ3JpZElubmVyW2ldKSAvIHJhZGl1cyArIGN1dG9mZiksIDAsIDEpXHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGRpc3RcclxufVxyXG5cclxuLy8gMkQgRXVjbGlkZWFuIGRpc3RhbmNlIHRyYW5zZm9ybSBieSBGZWx6ZW5zendhbGIgJiBIdXR0ZW5sb2NoZXIgaHR0cHM6Ly9jcy5icm93bi5lZHUvfnBmZi9kdC9cclxuZnVuY3Rpb24gZWR0KGRhdGEsIHdpZHRoLCBoZWlnaHQsIGYsIGQsIHYsIHopIHtcclxuICAgIGZvciAodmFyIHggPSAwOyB4IDwgd2lkdGg7IHgrKykge1xyXG4gICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHtcclxuICAgICAgICAgICAgZlt5XSA9IGRhdGFbeSAqIHdpZHRoICsgeF1cclxuICAgICAgICB9XHJcbiAgICAgICAgZWR0MWQoZiwgZCwgdiwgeiwgaGVpZ2h0KVxyXG4gICAgICAgIGZvciAoeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xyXG4gICAgICAgICAgICBkYXRhW3kgKiB3aWR0aCArIHhdID0gZFt5XVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGZvciAoeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykge1xyXG4gICAgICAgIGZvciAoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XHJcbiAgICAgICAgICAgIGZbeF0gPSBkYXRhW3kgKiB3aWR0aCArIHhdXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVkdDFkKGYsIGQsIHYsIHosIHdpZHRoKVxyXG4gICAgICAgIGZvciAoeCA9IDA7IHggPCB3aWR0aDsgeCsrKSB7XHJcbiAgICAgICAgICAgIGRhdGFbeSAqIHdpZHRoICsgeF0gPSBNYXRoLnNxcnQoZFt4XSlcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbi8vIDFEIHNxdWFyZWQgZGlzdGFuY2UgdHJhbnNmb3JtXHJcbmZ1bmN0aW9uIGVkdDFkKGYsIGQsIHYsIHosIG4pIHtcclxuICAgIHZbMF0gPSAwO1xyXG4gICAgelswXSA9IC1JTkZcclxuICAgIHpbMV0gPSArSU5GXHJcblxyXG4gICAgZm9yICh2YXIgcSA9IDEsIGsgPSAwOyBxIDwgbjsgcSsrKSB7XHJcbiAgICAgICAgdmFyIHMgPSAoKGZbcV0gKyBxICogcSkgLSAoZlt2W2tdXSArIHZba10gKiB2W2tdKSkgLyAoMiAqIHEgLSAyICogdltrXSlcclxuICAgICAgICB3aGlsZSAocyA8PSB6W2tdKSB7XHJcbiAgICAgICAgICAgIGstLVxyXG4gICAgICAgICAgICBzID0gKChmW3FdICsgcSAqIHEpIC0gKGZbdltrXV0gKyB2W2tdICogdltrXSkpIC8gKDIgKiBxIC0gMiAqIHZba10pXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGsrK1xyXG4gICAgICAgIHZba10gPSBxXHJcbiAgICAgICAgeltrXSA9IHNcclxuICAgICAgICB6W2sgKyAxXSA9ICtJTkZcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKHEgPSAwLCBrID0gMDsgcSA8IG47IHErKykge1xyXG4gICAgICAgIHdoaWxlICh6W2sgKyAxXSA8IHEpIGsrK1xyXG4gICAgICAgIGRbcV0gPSAocSAtIHZba10pICogKHEgLSB2W2tdKSArIGZbdltrXV1cclxuICAgIH1cclxufVxyXG5cbn0se1wiY2xhbXBcIjoxMTV9XSw5NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4oZnVuY3Rpb24gKG1vZHVsZSwgZXhwb3J0cykge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLy8gVXRpbHNcbiAgZnVuY3Rpb24gYXNzZXJ0ICh2YWwsIG1zZykge1xuICAgIGlmICghdmFsKSB0aHJvdyBuZXcgRXJyb3IobXNnIHx8ICdBc3NlcnRpb24gZmFpbGVkJyk7XG4gIH1cblxuICAvLyBDb3VsZCB1c2UgYGluaGVyaXRzYCBtb2R1bGUsIGJ1dCBkb24ndCB3YW50IHRvIG1vdmUgZnJvbSBzaW5nbGUgZmlsZVxuICAvLyBhcmNoaXRlY3R1cmUgeWV0LlxuICBmdW5jdGlvbiBpbmhlcml0cyAoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3I7XG4gICAgdmFyIFRlbXBDdG9yID0gZnVuY3Rpb24gKCkge307XG4gICAgVGVtcEN0b3IucHJvdG90eXBlID0gc3VwZXJDdG9yLnByb3RvdHlwZTtcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpO1xuICAgIGN0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY3RvcjtcbiAgfVxuXG4gIC8vIEJOXG5cbiAgZnVuY3Rpb24gQk4gKG51bWJlciwgYmFzZSwgZW5kaWFuKSB7XG4gICAgaWYgKEJOLmlzQk4obnVtYmVyKSkge1xuICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICB9XG5cbiAgICB0aGlzLm5lZ2F0aXZlID0gMDtcbiAgICB0aGlzLndvcmRzID0gbnVsbDtcbiAgICB0aGlzLmxlbmd0aCA9IDA7XG5cbiAgICAvLyBSZWR1Y3Rpb24gY29udGV4dFxuICAgIHRoaXMucmVkID0gbnVsbDtcblxuICAgIGlmIChudW1iZXIgIT09IG51bGwpIHtcbiAgICAgIGlmIChiYXNlID09PSAnbGUnIHx8IGJhc2UgPT09ICdiZScpIHtcbiAgICAgICAgZW5kaWFuID0gYmFzZTtcbiAgICAgICAgYmFzZSA9IDEwO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9pbml0KG51bWJlciB8fCAwLCBiYXNlIHx8IDEwLCBlbmRpYW4gfHwgJ2JlJyk7XG4gICAgfVxuICB9XG4gIGlmICh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0Jykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gQk47XG4gIH0gZWxzZSB7XG4gICAgZXhwb3J0cy5CTiA9IEJOO1xuICB9XG5cbiAgQk4uQk4gPSBCTjtcbiAgQk4ud29yZFNpemUgPSAyNjtcblxuICB2YXIgQnVmZmVyO1xuICB0cnkge1xuICAgIEJ1ZmZlciA9IF9kZXJlcV8oJ2J1ZmZlcicpLkJ1ZmZlcjtcbiAgfSBjYXRjaCAoZSkge1xuICB9XG5cbiAgQk4uaXNCTiA9IGZ1bmN0aW9uIGlzQk4gKG51bSkge1xuICAgIGlmIChudW0gaW5zdGFuY2VvZiBCTikge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bSAhPT0gbnVsbCAmJiB0eXBlb2YgbnVtID09PSAnb2JqZWN0JyAmJlxuICAgICAgbnVtLmNvbnN0cnVjdG9yLndvcmRTaXplID09PSBCTi53b3JkU2l6ZSAmJiBBcnJheS5pc0FycmF5KG51bS53b3Jkcyk7XG4gIH07XG5cbiAgQk4ubWF4ID0gZnVuY3Rpb24gbWF4IChsZWZ0LCByaWdodCkge1xuICAgIGlmIChsZWZ0LmNtcChyaWdodCkgPiAwKSByZXR1cm4gbGVmdDtcbiAgICByZXR1cm4gcmlnaHQ7XG4gIH07XG5cbiAgQk4ubWluID0gZnVuY3Rpb24gbWluIChsZWZ0LCByaWdodCkge1xuICAgIGlmIChsZWZ0LmNtcChyaWdodCkgPCAwKSByZXR1cm4gbGVmdDtcbiAgICByZXR1cm4gcmlnaHQ7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLl9pbml0ID0gZnVuY3Rpb24gaW5pdCAobnVtYmVyLCBiYXNlLCBlbmRpYW4pIHtcbiAgICBpZiAodHlwZW9mIG51bWJlciA9PT0gJ251bWJlcicpIHtcbiAgICAgIHJldHVybiB0aGlzLl9pbml0TnVtYmVyKG51bWJlciwgYmFzZSwgZW5kaWFuKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG51bWJlciA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiB0aGlzLl9pbml0QXJyYXkobnVtYmVyLCBiYXNlLCBlbmRpYW4pO1xuICAgIH1cblxuICAgIGlmIChiYXNlID09PSAnaGV4Jykge1xuICAgICAgYmFzZSA9IDE2O1xuICAgIH1cbiAgICBhc3NlcnQoYmFzZSA9PT0gKGJhc2UgfCAwKSAmJiBiYXNlID49IDIgJiYgYmFzZSA8PSAzNik7XG5cbiAgICBudW1iZXIgPSBudW1iZXIudG9TdHJpbmcoKS5yZXBsYWNlKC9cXHMrL2csICcnKTtcbiAgICB2YXIgc3RhcnQgPSAwO1xuICAgIGlmIChudW1iZXJbMF0gPT09ICctJykge1xuICAgICAgc3RhcnQrKztcbiAgICB9XG5cbiAgICBpZiAoYmFzZSA9PT0gMTYpIHtcbiAgICAgIHRoaXMuX3BhcnNlSGV4KG51bWJlciwgc3RhcnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9wYXJzZUJhc2UobnVtYmVyLCBiYXNlLCBzdGFydCk7XG4gICAgfVxuXG4gICAgaWYgKG51bWJlclswXSA9PT0gJy0nKSB7XG4gICAgICB0aGlzLm5lZ2F0aXZlID0gMTtcbiAgICB9XG5cbiAgICB0aGlzLnN0cmlwKCk7XG5cbiAgICBpZiAoZW5kaWFuICE9PSAnbGUnKSByZXR1cm47XG5cbiAgICB0aGlzLl9pbml0QXJyYXkodGhpcy50b0FycmF5KCksIGJhc2UsIGVuZGlhbik7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLl9pbml0TnVtYmVyID0gZnVuY3Rpb24gX2luaXROdW1iZXIgKG51bWJlciwgYmFzZSwgZW5kaWFuKSB7XG4gICAgaWYgKG51bWJlciA8IDApIHtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAxO1xuICAgICAgbnVtYmVyID0gLW51bWJlcjtcbiAgICB9XG4gICAgaWYgKG51bWJlciA8IDB4NDAwMDAwMCkge1xuICAgICAgdGhpcy53b3JkcyA9IFsgbnVtYmVyICYgMHgzZmZmZmZmIF07XG4gICAgICB0aGlzLmxlbmd0aCA9IDE7XG4gICAgfSBlbHNlIGlmIChudW1iZXIgPCAweDEwMDAwMDAwMDAwMDAwKSB7XG4gICAgICB0aGlzLndvcmRzID0gW1xuICAgICAgICBudW1iZXIgJiAweDNmZmZmZmYsXG4gICAgICAgIChudW1iZXIgLyAweDQwMDAwMDApICYgMHgzZmZmZmZmXG4gICAgICBdO1xuICAgICAgdGhpcy5sZW5ndGggPSAyO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3NlcnQobnVtYmVyIDwgMHgyMDAwMDAwMDAwMDAwMCk7IC8vIDIgXiA1MyAodW5zYWZlKVxuICAgICAgdGhpcy53b3JkcyA9IFtcbiAgICAgICAgbnVtYmVyICYgMHgzZmZmZmZmLFxuICAgICAgICAobnVtYmVyIC8gMHg0MDAwMDAwKSAmIDB4M2ZmZmZmZixcbiAgICAgICAgMVxuICAgICAgXTtcbiAgICAgIHRoaXMubGVuZ3RoID0gMztcbiAgICB9XG5cbiAgICBpZiAoZW5kaWFuICE9PSAnbGUnKSByZXR1cm47XG5cbiAgICAvLyBSZXZlcnNlIHRoZSBieXRlc1xuICAgIHRoaXMuX2luaXRBcnJheSh0aGlzLnRvQXJyYXkoKSwgYmFzZSwgZW5kaWFuKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuX2luaXRBcnJheSA9IGZ1bmN0aW9uIF9pbml0QXJyYXkgKG51bWJlciwgYmFzZSwgZW5kaWFuKSB7XG4gICAgLy8gUGVyaGFwcyBhIFVpbnQ4QXJyYXlcbiAgICBhc3NlcnQodHlwZW9mIG51bWJlci5sZW5ndGggPT09ICdudW1iZXInKTtcbiAgICBpZiAobnVtYmVyLmxlbmd0aCA8PSAwKSB7XG4gICAgICB0aGlzLndvcmRzID0gWyAwIF07XG4gICAgICB0aGlzLmxlbmd0aCA9IDE7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICB0aGlzLmxlbmd0aCA9IE1hdGguY2VpbChudW1iZXIubGVuZ3RoIC8gMyk7XG4gICAgdGhpcy53b3JkcyA9IG5ldyBBcnJheSh0aGlzLmxlbmd0aCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLndvcmRzW2ldID0gMDtcbiAgICB9XG5cbiAgICB2YXIgaiwgdztcbiAgICB2YXIgb2ZmID0gMDtcbiAgICBpZiAoZW5kaWFuID09PSAnYmUnKSB7XG4gICAgICBmb3IgKGkgPSBudW1iZXIubGVuZ3RoIC0gMSwgaiA9IDA7IGkgPj0gMDsgaSAtPSAzKSB7XG4gICAgICAgIHcgPSBudW1iZXJbaV0gfCAobnVtYmVyW2kgLSAxXSA8PCA4KSB8IChudW1iZXJbaSAtIDJdIDw8IDE2KTtcbiAgICAgICAgdGhpcy53b3Jkc1tqXSB8PSAodyA8PCBvZmYpICYgMHgzZmZmZmZmO1xuICAgICAgICB0aGlzLndvcmRzW2ogKyAxXSA9ICh3ID4+PiAoMjYgLSBvZmYpKSAmIDB4M2ZmZmZmZjtcbiAgICAgICAgb2ZmICs9IDI0O1xuICAgICAgICBpZiAob2ZmID49IDI2KSB7XG4gICAgICAgICAgb2ZmIC09IDI2O1xuICAgICAgICAgIGorKztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZW5kaWFuID09PSAnbGUnKSB7XG4gICAgICBmb3IgKGkgPSAwLCBqID0gMDsgaSA8IG51bWJlci5sZW5ndGg7IGkgKz0gMykge1xuICAgICAgICB3ID0gbnVtYmVyW2ldIHwgKG51bWJlcltpICsgMV0gPDwgOCkgfCAobnVtYmVyW2kgKyAyXSA8PCAxNik7XG4gICAgICAgIHRoaXMud29yZHNbal0gfD0gKHcgPDwgb2ZmKSAmIDB4M2ZmZmZmZjtcbiAgICAgICAgdGhpcy53b3Jkc1tqICsgMV0gPSAodyA+Pj4gKDI2IC0gb2ZmKSkgJiAweDNmZmZmZmY7XG4gICAgICAgIG9mZiArPSAyNDtcbiAgICAgICAgaWYgKG9mZiA+PSAyNikge1xuICAgICAgICAgIG9mZiAtPSAyNjtcbiAgICAgICAgICBqKys7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc3RyaXAoKTtcbiAgfTtcblxuICBmdW5jdGlvbiBwYXJzZUhleCAoc3RyLCBzdGFydCwgZW5kKSB7XG4gICAgdmFyIHIgPSAwO1xuICAgIHZhciBsZW4gPSBNYXRoLm1pbihzdHIubGVuZ3RoLCBlbmQpO1xuICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICB2YXIgYyA9IHN0ci5jaGFyQ29kZUF0KGkpIC0gNDg7XG5cbiAgICAgIHIgPDw9IDQ7XG5cbiAgICAgIC8vICdhJyAtICdmJ1xuICAgICAgaWYgKGMgPj0gNDkgJiYgYyA8PSA1NCkge1xuICAgICAgICByIHw9IGMgLSA0OSArIDB4YTtcblxuICAgICAgLy8gJ0EnIC0gJ0YnXG4gICAgICB9IGVsc2UgaWYgKGMgPj0gMTcgJiYgYyA8PSAyMikge1xuICAgICAgICByIHw9IGMgLSAxNyArIDB4YTtcblxuICAgICAgLy8gJzAnIC0gJzknXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByIHw9IGMgJiAweGY7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByO1xuICB9XG5cbiAgQk4ucHJvdG90eXBlLl9wYXJzZUhleCA9IGZ1bmN0aW9uIF9wYXJzZUhleCAobnVtYmVyLCBzdGFydCkge1xuICAgIC8vIENyZWF0ZSBwb3NzaWJseSBiaWdnZXIgYXJyYXkgdG8gZW5zdXJlIHRoYXQgaXQgZml0cyB0aGUgbnVtYmVyXG4gICAgdGhpcy5sZW5ndGggPSBNYXRoLmNlaWwoKG51bWJlci5sZW5ndGggLSBzdGFydCkgLyA2KTtcbiAgICB0aGlzLndvcmRzID0gbmV3IEFycmF5KHRoaXMubGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMud29yZHNbaV0gPSAwO1xuICAgIH1cblxuICAgIHZhciBqLCB3O1xuICAgIC8vIFNjYW4gMjQtYml0IGNodW5rcyBhbmQgYWRkIHRoZW0gdG8gdGhlIG51bWJlclxuICAgIHZhciBvZmYgPSAwO1xuICAgIGZvciAoaSA9IG51bWJlci5sZW5ndGggLSA2LCBqID0gMDsgaSA+PSBzdGFydDsgaSAtPSA2KSB7XG4gICAgICB3ID0gcGFyc2VIZXgobnVtYmVyLCBpLCBpICsgNik7XG4gICAgICB0aGlzLndvcmRzW2pdIHw9ICh3IDw8IG9mZikgJiAweDNmZmZmZmY7XG4gICAgICAvLyBOT1RFOiBgMHgzZmZmZmZgIGlzIGludGVudGlvbmFsIGhlcmUsIDI2Yml0cyBtYXggc2hpZnQgKyAyNGJpdCBoZXggbGltYlxuICAgICAgdGhpcy53b3Jkc1tqICsgMV0gfD0gdyA+Pj4gKDI2IC0gb2ZmKSAmIDB4M2ZmZmZmO1xuICAgICAgb2ZmICs9IDI0O1xuICAgICAgaWYgKG9mZiA+PSAyNikge1xuICAgICAgICBvZmYgLT0gMjY7XG4gICAgICAgIGorKztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGkgKyA2ICE9PSBzdGFydCkge1xuICAgICAgdyA9IHBhcnNlSGV4KG51bWJlciwgc3RhcnQsIGkgKyA2KTtcbiAgICAgIHRoaXMud29yZHNbal0gfD0gKHcgPDwgb2ZmKSAmIDB4M2ZmZmZmZjtcbiAgICAgIHRoaXMud29yZHNbaiArIDFdIHw9IHcgPj4+ICgyNiAtIG9mZikgJiAweDNmZmZmZjtcbiAgICB9XG4gICAgdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIGZ1bmN0aW9uIHBhcnNlQmFzZSAoc3RyLCBzdGFydCwgZW5kLCBtdWwpIHtcbiAgICB2YXIgciA9IDA7XG4gICAgdmFyIGxlbiA9IE1hdGgubWluKHN0ci5sZW5ndGgsIGVuZCk7XG4gICAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIHZhciBjID0gc3RyLmNoYXJDb2RlQXQoaSkgLSA0ODtcblxuICAgICAgciAqPSBtdWw7XG5cbiAgICAgIC8vICdhJ1xuICAgICAgaWYgKGMgPj0gNDkpIHtcbiAgICAgICAgciArPSBjIC0gNDkgKyAweGE7XG5cbiAgICAgIC8vICdBJ1xuICAgICAgfSBlbHNlIGlmIChjID49IDE3KSB7XG4gICAgICAgIHIgKz0gYyAtIDE3ICsgMHhhO1xuXG4gICAgICAvLyAnMCcgLSAnOSdcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHIgKz0gYztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHI7XG4gIH1cblxuICBCTi5wcm90b3R5cGUuX3BhcnNlQmFzZSA9IGZ1bmN0aW9uIF9wYXJzZUJhc2UgKG51bWJlciwgYmFzZSwgc3RhcnQpIHtcbiAgICAvLyBJbml0aWFsaXplIGFzIHplcm9cbiAgICB0aGlzLndvcmRzID0gWyAwIF07XG4gICAgdGhpcy5sZW5ndGggPSAxO1xuXG4gICAgLy8gRmluZCBsZW5ndGggb2YgbGltYiBpbiBiYXNlXG4gICAgZm9yICh2YXIgbGltYkxlbiA9IDAsIGxpbWJQb3cgPSAxOyBsaW1iUG93IDw9IDB4M2ZmZmZmZjsgbGltYlBvdyAqPSBiYXNlKSB7XG4gICAgICBsaW1iTGVuKys7XG4gICAgfVxuICAgIGxpbWJMZW4tLTtcbiAgICBsaW1iUG93ID0gKGxpbWJQb3cgLyBiYXNlKSB8IDA7XG5cbiAgICB2YXIgdG90YWwgPSBudW1iZXIubGVuZ3RoIC0gc3RhcnQ7XG4gICAgdmFyIG1vZCA9IHRvdGFsICUgbGltYkxlbjtcbiAgICB2YXIgZW5kID0gTWF0aC5taW4odG90YWwsIHRvdGFsIC0gbW9kKSArIHN0YXJ0O1xuXG4gICAgdmFyIHdvcmQgPSAwO1xuICAgIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSArPSBsaW1iTGVuKSB7XG4gICAgICB3b3JkID0gcGFyc2VCYXNlKG51bWJlciwgaSwgaSArIGxpbWJMZW4sIGJhc2UpO1xuXG4gICAgICB0aGlzLmltdWxuKGxpbWJQb3cpO1xuICAgICAgaWYgKHRoaXMud29yZHNbMF0gKyB3b3JkIDwgMHg0MDAwMDAwKSB7XG4gICAgICAgIHRoaXMud29yZHNbMF0gKz0gd29yZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2lhZGRuKHdvcmQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChtb2QgIT09IDApIHtcbiAgICAgIHZhciBwb3cgPSAxO1xuICAgICAgd29yZCA9IHBhcnNlQmFzZShudW1iZXIsIGksIG51bWJlci5sZW5ndGgsIGJhc2UpO1xuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbW9kOyBpKyspIHtcbiAgICAgICAgcG93ICo9IGJhc2U7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuaW11bG4ocG93KTtcbiAgICAgIGlmICh0aGlzLndvcmRzWzBdICsgd29yZCA8IDB4NDAwMDAwMCkge1xuICAgICAgICB0aGlzLndvcmRzWzBdICs9IHdvcmQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9pYWRkbih3b3JkKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5IChkZXN0KSB7XG4gICAgZGVzdC53b3JkcyA9IG5ldyBBcnJheSh0aGlzLmxlbmd0aCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBkZXN0LndvcmRzW2ldID0gdGhpcy53b3Jkc1tpXTtcbiAgICB9XG4gICAgZGVzdC5sZW5ndGggPSB0aGlzLmxlbmd0aDtcbiAgICBkZXN0Lm5lZ2F0aXZlID0gdGhpcy5uZWdhdGl2ZTtcbiAgICBkZXN0LnJlZCA9IHRoaXMucmVkO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uIGNsb25lICgpIHtcbiAgICB2YXIgciA9IG5ldyBCTihudWxsKTtcbiAgICB0aGlzLmNvcHkocik7XG4gICAgcmV0dXJuIHI7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLl9leHBhbmQgPSBmdW5jdGlvbiBfZXhwYW5kIChzaXplKSB7XG4gICAgd2hpbGUgKHRoaXMubGVuZ3RoIDwgc2l6ZSkge1xuICAgICAgdGhpcy53b3Jkc1t0aGlzLmxlbmd0aCsrXSA9IDA7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIC8vIFJlbW92ZSBsZWFkaW5nIGAwYCBmcm9tIGB0aGlzYFxuICBCTi5wcm90b3R5cGUuc3RyaXAgPSBmdW5jdGlvbiBzdHJpcCAoKSB7XG4gICAgd2hpbGUgKHRoaXMubGVuZ3RoID4gMSAmJiB0aGlzLndvcmRzW3RoaXMubGVuZ3RoIC0gMV0gPT09IDApIHtcbiAgICAgIHRoaXMubGVuZ3RoLS07XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9ub3JtU2lnbigpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5fbm9ybVNpZ24gPSBmdW5jdGlvbiBfbm9ybVNpZ24gKCkge1xuICAgIC8vIC0wID0gMFxuICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMSAmJiB0aGlzLndvcmRzWzBdID09PSAwKSB7XG4gICAgICB0aGlzLm5lZ2F0aXZlID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbiBpbnNwZWN0ICgpIHtcbiAgICByZXR1cm4gKHRoaXMucmVkID8gJzxCTi1SOiAnIDogJzxCTjogJykgKyB0aGlzLnRvU3RyaW5nKDE2KSArICc+JztcbiAgfTtcblxuICAvKlxuXG4gIHZhciB6ZXJvcyA9IFtdO1xuICB2YXIgZ3JvdXBTaXplcyA9IFtdO1xuICB2YXIgZ3JvdXBCYXNlcyA9IFtdO1xuXG4gIHZhciBzID0gJyc7XG4gIHZhciBpID0gLTE7XG4gIHdoaWxlICgrK2kgPCBCTi53b3JkU2l6ZSkge1xuICAgIHplcm9zW2ldID0gcztcbiAgICBzICs9ICcwJztcbiAgfVxuICBncm91cFNpemVzWzBdID0gMDtcbiAgZ3JvdXBTaXplc1sxXSA9IDA7XG4gIGdyb3VwQmFzZXNbMF0gPSAwO1xuICBncm91cEJhc2VzWzFdID0gMDtcbiAgdmFyIGJhc2UgPSAyIC0gMTtcbiAgd2hpbGUgKCsrYmFzZSA8IDM2ICsgMSkge1xuICAgIHZhciBncm91cFNpemUgPSAwO1xuICAgIHZhciBncm91cEJhc2UgPSAxO1xuICAgIHdoaWxlIChncm91cEJhc2UgPCAoMSA8PCBCTi53b3JkU2l6ZSkgLyBiYXNlKSB7XG4gICAgICBncm91cEJhc2UgKj0gYmFzZTtcbiAgICAgIGdyb3VwU2l6ZSArPSAxO1xuICAgIH1cbiAgICBncm91cFNpemVzW2Jhc2VdID0gZ3JvdXBTaXplO1xuICAgIGdyb3VwQmFzZXNbYmFzZV0gPSBncm91cEJhc2U7XG4gIH1cblxuICAqL1xuXG4gIHZhciB6ZXJvcyA9IFtcbiAgICAnJyxcbiAgICAnMCcsXG4gICAgJzAwJyxcbiAgICAnMDAwJyxcbiAgICAnMDAwMCcsXG4gICAgJzAwMDAwJyxcbiAgICAnMDAwMDAwJyxcbiAgICAnMDAwMDAwMCcsXG4gICAgJzAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMCcsXG4gICAgJzAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMCcsXG4gICAgJzAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgJzAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgJzAwMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgJzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCdcbiAgXTtcblxuICB2YXIgZ3JvdXBTaXplcyA9IFtcbiAgICAwLCAwLFxuICAgIDI1LCAxNiwgMTIsIDExLCAxMCwgOSwgOCxcbiAgICA4LCA3LCA3LCA3LCA3LCA2LCA2LFxuICAgIDYsIDYsIDYsIDYsIDYsIDUsIDUsXG4gICAgNSwgNSwgNSwgNSwgNSwgNSwgNSxcbiAgICA1LCA1LCA1LCA1LCA1LCA1LCA1XG4gIF07XG5cbiAgdmFyIGdyb3VwQmFzZXMgPSBbXG4gICAgMCwgMCxcbiAgICAzMzU1NDQzMiwgNDMwNDY3MjEsIDE2Nzc3MjE2LCA0ODgyODEyNSwgNjA0NjYxNzYsIDQwMzUzNjA3LCAxNjc3NzIxNixcbiAgICA0MzA0NjcyMSwgMTAwMDAwMDAsIDE5NDg3MTcxLCAzNTgzMTgwOCwgNjI3NDg1MTcsIDc1Mjk1MzYsIDExMzkwNjI1LFxuICAgIDE2Nzc3MjE2LCAyNDEzNzU2OSwgMzQwMTIyMjQsIDQ3MDQ1ODgxLCA2NDAwMDAwMCwgNDA4NDEwMSwgNTE1MzYzMixcbiAgICA2NDM2MzQzLCA3OTYyNjI0LCA5NzY1NjI1LCAxMTg4MTM3NiwgMTQzNDg5MDcsIDE3MjEwMzY4LCAyMDUxMTE0OSxcbiAgICAyNDMwMDAwMCwgMjg2MjkxNTEsIDMzNTU0NDMyLCAzOTEzNTM5MywgNDU0MzU0MjQsIDUyNTIxODc1LCA2MDQ2NjE3NlxuICBdO1xuXG4gIEJOLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nIChiYXNlLCBwYWRkaW5nKSB7XG4gICAgYmFzZSA9IGJhc2UgfHwgMTA7XG4gICAgcGFkZGluZyA9IHBhZGRpbmcgfCAwIHx8IDE7XG5cbiAgICB2YXIgb3V0O1xuICAgIGlmIChiYXNlID09PSAxNiB8fCBiYXNlID09PSAnaGV4Jykge1xuICAgICAgb3V0ID0gJyc7XG4gICAgICB2YXIgb2ZmID0gMDtcbiAgICAgIHZhciBjYXJyeSA9IDA7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHcgPSB0aGlzLndvcmRzW2ldO1xuICAgICAgICB2YXIgd29yZCA9ICgoKHcgPDwgb2ZmKSB8IGNhcnJ5KSAmIDB4ZmZmZmZmKS50b1N0cmluZygxNik7XG4gICAgICAgIGNhcnJ5ID0gKHcgPj4+ICgyNCAtIG9mZikpICYgMHhmZmZmZmY7XG4gICAgICAgIGlmIChjYXJyeSAhPT0gMCB8fCBpICE9PSB0aGlzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICBvdXQgPSB6ZXJvc1s2IC0gd29yZC5sZW5ndGhdICsgd29yZCArIG91dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvdXQgPSB3b3JkICsgb3V0O1xuICAgICAgICB9XG4gICAgICAgIG9mZiArPSAyO1xuICAgICAgICBpZiAob2ZmID49IDI2KSB7XG4gICAgICAgICAgb2ZmIC09IDI2O1xuICAgICAgICAgIGktLTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGNhcnJ5ICE9PSAwKSB7XG4gICAgICAgIG91dCA9IGNhcnJ5LnRvU3RyaW5nKDE2KSArIG91dDtcbiAgICAgIH1cbiAgICAgIHdoaWxlIChvdXQubGVuZ3RoICUgcGFkZGluZyAhPT0gMCkge1xuICAgICAgICBvdXQgPSAnMCcgKyBvdXQ7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgICBvdXQgPSAnLScgKyBvdXQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIGlmIChiYXNlID09PSAoYmFzZSB8IDApICYmIGJhc2UgPj0gMiAmJiBiYXNlIDw9IDM2KSB7XG4gICAgICAvLyB2YXIgZ3JvdXBTaXplID0gTWF0aC5mbG9vcihCTi53b3JkU2l6ZSAqIE1hdGguTE4yIC8gTWF0aC5sb2coYmFzZSkpO1xuICAgICAgdmFyIGdyb3VwU2l6ZSA9IGdyb3VwU2l6ZXNbYmFzZV07XG4gICAgICAvLyB2YXIgZ3JvdXBCYXNlID0gTWF0aC5wb3coYmFzZSwgZ3JvdXBTaXplKTtcbiAgICAgIHZhciBncm91cEJhc2UgPSBncm91cEJhc2VzW2Jhc2VdO1xuICAgICAgb3V0ID0gJyc7XG4gICAgICB2YXIgYyA9IHRoaXMuY2xvbmUoKTtcbiAgICAgIGMubmVnYXRpdmUgPSAwO1xuICAgICAgd2hpbGUgKCFjLmlzWmVybygpKSB7XG4gICAgICAgIHZhciByID0gYy5tb2RuKGdyb3VwQmFzZSkudG9TdHJpbmcoYmFzZSk7XG4gICAgICAgIGMgPSBjLmlkaXZuKGdyb3VwQmFzZSk7XG5cbiAgICAgICAgaWYgKCFjLmlzWmVybygpKSB7XG4gICAgICAgICAgb3V0ID0gemVyb3NbZ3JvdXBTaXplIC0gci5sZW5ndGhdICsgciArIG91dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvdXQgPSByICsgb3V0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5pc1plcm8oKSkge1xuICAgICAgICBvdXQgPSAnMCcgKyBvdXQ7XG4gICAgICB9XG4gICAgICB3aGlsZSAob3V0Lmxlbmd0aCAlIHBhZGRpbmcgIT09IDApIHtcbiAgICAgICAgb3V0ID0gJzAnICsgb3V0O1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMubmVnYXRpdmUgIT09IDApIHtcbiAgICAgICAgb3V0ID0gJy0nICsgb3V0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICBhc3NlcnQoZmFsc2UsICdCYXNlIHNob3VsZCBiZSBiZXR3ZWVuIDIgYW5kIDM2Jyk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnRvTnVtYmVyID0gZnVuY3Rpb24gdG9OdW1iZXIgKCkge1xuICAgIHZhciByZXQgPSB0aGlzLndvcmRzWzBdO1xuICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMikge1xuICAgICAgcmV0ICs9IHRoaXMud29yZHNbMV0gKiAweDQwMDAwMDA7XG4gICAgfSBlbHNlIGlmICh0aGlzLmxlbmd0aCA9PT0gMyAmJiB0aGlzLndvcmRzWzJdID09PSAweDAxKSB7XG4gICAgICAvLyBOT1RFOiBhdCB0aGlzIHN0YWdlIGl0IGlzIGtub3duIHRoYXQgdGhlIHRvcCBiaXQgaXMgc2V0XG4gICAgICByZXQgKz0gMHgxMDAwMDAwMDAwMDAwMCArICh0aGlzLndvcmRzWzFdICogMHg0MDAwMDAwKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubGVuZ3RoID4gMikge1xuICAgICAgYXNzZXJ0KGZhbHNlLCAnTnVtYmVyIGNhbiBvbmx5IHNhZmVseSBzdG9yZSB1cCB0byA1MyBiaXRzJyk7XG4gICAgfVxuICAgIHJldHVybiAodGhpcy5uZWdhdGl2ZSAhPT0gMCkgPyAtcmV0IDogcmV0O1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04gKCkge1xuICAgIHJldHVybiB0aGlzLnRvU3RyaW5nKDE2KTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUudG9CdWZmZXIgPSBmdW5jdGlvbiB0b0J1ZmZlciAoZW5kaWFuLCBsZW5ndGgpIHtcbiAgICBhc3NlcnQodHlwZW9mIEJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcpO1xuICAgIHJldHVybiB0aGlzLnRvQXJyYXlMaWtlKEJ1ZmZlciwgZW5kaWFuLCBsZW5ndGgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS50b0FycmF5ID0gZnVuY3Rpb24gdG9BcnJheSAoZW5kaWFuLCBsZW5ndGgpIHtcbiAgICByZXR1cm4gdGhpcy50b0FycmF5TGlrZShBcnJheSwgZW5kaWFuLCBsZW5ndGgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS50b0FycmF5TGlrZSA9IGZ1bmN0aW9uIHRvQXJyYXlMaWtlIChBcnJheVR5cGUsIGVuZGlhbiwgbGVuZ3RoKSB7XG4gICAgdmFyIGJ5dGVMZW5ndGggPSB0aGlzLmJ5dGVMZW5ndGgoKTtcbiAgICB2YXIgcmVxTGVuZ3RoID0gbGVuZ3RoIHx8IE1hdGgubWF4KDEsIGJ5dGVMZW5ndGgpO1xuICAgIGFzc2VydChieXRlTGVuZ3RoIDw9IHJlcUxlbmd0aCwgJ2J5dGUgYXJyYXkgbG9uZ2VyIHRoYW4gZGVzaXJlZCBsZW5ndGgnKTtcbiAgICBhc3NlcnQocmVxTGVuZ3RoID4gMCwgJ1JlcXVlc3RlZCBhcnJheSBsZW5ndGggPD0gMCcpO1xuXG4gICAgdGhpcy5zdHJpcCgpO1xuICAgIHZhciBsaXR0bGVFbmRpYW4gPSBlbmRpYW4gPT09ICdsZSc7XG4gICAgdmFyIHJlcyA9IG5ldyBBcnJheVR5cGUocmVxTGVuZ3RoKTtcblxuICAgIHZhciBiLCBpO1xuICAgIHZhciBxID0gdGhpcy5jbG9uZSgpO1xuICAgIGlmICghbGl0dGxlRW5kaWFuKSB7XG4gICAgICAvLyBBc3N1bWUgYmlnLWVuZGlhblxuICAgICAgZm9yIChpID0gMDsgaSA8IHJlcUxlbmd0aCAtIGJ5dGVMZW5ndGg7IGkrKykge1xuICAgICAgICByZXNbaV0gPSAwO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGkgPSAwOyAhcS5pc1plcm8oKTsgaSsrKSB7XG4gICAgICAgIGIgPSBxLmFuZGxuKDB4ZmYpO1xuICAgICAgICBxLml1c2hybig4KTtcblxuICAgICAgICByZXNbcmVxTGVuZ3RoIC0gaSAtIDFdID0gYjtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChpID0gMDsgIXEuaXNaZXJvKCk7IGkrKykge1xuICAgICAgICBiID0gcS5hbmRsbigweGZmKTtcbiAgICAgICAgcS5pdXNocm4oOCk7XG5cbiAgICAgICAgcmVzW2ldID0gYjtcbiAgICAgIH1cblxuICAgICAgZm9yICg7IGkgPCByZXFMZW5ndGg7IGkrKykge1xuICAgICAgICByZXNbaV0gPSAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXM7XG4gIH07XG5cbiAgaWYgKE1hdGguY2x6MzIpIHtcbiAgICBCTi5wcm90b3R5cGUuX2NvdW50Qml0cyA9IGZ1bmN0aW9uIF9jb3VudEJpdHMgKHcpIHtcbiAgICAgIHJldHVybiAzMiAtIE1hdGguY2x6MzIodyk7XG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICBCTi5wcm90b3R5cGUuX2NvdW50Qml0cyA9IGZ1bmN0aW9uIF9jb3VudEJpdHMgKHcpIHtcbiAgICAgIHZhciB0ID0gdztcbiAgICAgIHZhciByID0gMDtcbiAgICAgIGlmICh0ID49IDB4MTAwMCkge1xuICAgICAgICByICs9IDEzO1xuICAgICAgICB0ID4+Pj0gMTM7XG4gICAgICB9XG4gICAgICBpZiAodCA+PSAweDQwKSB7XG4gICAgICAgIHIgKz0gNztcbiAgICAgICAgdCA+Pj49IDc7XG4gICAgICB9XG4gICAgICBpZiAodCA+PSAweDgpIHtcbiAgICAgICAgciArPSA0O1xuICAgICAgICB0ID4+Pj0gNDtcbiAgICAgIH1cbiAgICAgIGlmICh0ID49IDB4MDIpIHtcbiAgICAgICAgciArPSAyO1xuICAgICAgICB0ID4+Pj0gMjtcbiAgICAgIH1cbiAgICAgIHJldHVybiByICsgdDtcbiAgICB9O1xuICB9XG5cbiAgQk4ucHJvdG90eXBlLl96ZXJvQml0cyA9IGZ1bmN0aW9uIF96ZXJvQml0cyAodykge1xuICAgIC8vIFNob3J0LWN1dFxuICAgIGlmICh3ID09PSAwKSByZXR1cm4gMjY7XG5cbiAgICB2YXIgdCA9IHc7XG4gICAgdmFyIHIgPSAwO1xuICAgIGlmICgodCAmIDB4MWZmZikgPT09IDApIHtcbiAgICAgIHIgKz0gMTM7XG4gICAgICB0ID4+Pj0gMTM7XG4gICAgfVxuICAgIGlmICgodCAmIDB4N2YpID09PSAwKSB7XG4gICAgICByICs9IDc7XG4gICAgICB0ID4+Pj0gNztcbiAgICB9XG4gICAgaWYgKCh0ICYgMHhmKSA9PT0gMCkge1xuICAgICAgciArPSA0O1xuICAgICAgdCA+Pj49IDQ7XG4gICAgfVxuICAgIGlmICgodCAmIDB4MykgPT09IDApIHtcbiAgICAgIHIgKz0gMjtcbiAgICAgIHQgPj4+PSAyO1xuICAgIH1cbiAgICBpZiAoKHQgJiAweDEpID09PSAwKSB7XG4gICAgICByKys7XG4gICAgfVxuICAgIHJldHVybiByO1xuICB9O1xuXG4gIC8vIFJldHVybiBudW1iZXIgb2YgdXNlZCBiaXRzIGluIGEgQk5cbiAgQk4ucHJvdG90eXBlLmJpdExlbmd0aCA9IGZ1bmN0aW9uIGJpdExlbmd0aCAoKSB7XG4gICAgdmFyIHcgPSB0aGlzLndvcmRzW3RoaXMubGVuZ3RoIC0gMV07XG4gICAgdmFyIGhpID0gdGhpcy5fY291bnRCaXRzKHcpO1xuICAgIHJldHVybiAodGhpcy5sZW5ndGggLSAxKSAqIDI2ICsgaGk7XG4gIH07XG5cbiAgZnVuY3Rpb24gdG9CaXRBcnJheSAobnVtKSB7XG4gICAgdmFyIHcgPSBuZXcgQXJyYXkobnVtLmJpdExlbmd0aCgpKTtcblxuICAgIGZvciAodmFyIGJpdCA9IDA7IGJpdCA8IHcubGVuZ3RoOyBiaXQrKykge1xuICAgICAgdmFyIG9mZiA9IChiaXQgLyAyNikgfCAwO1xuICAgICAgdmFyIHdiaXQgPSBiaXQgJSAyNjtcblxuICAgICAgd1tiaXRdID0gKG51bS53b3Jkc1tvZmZdICYgKDEgPDwgd2JpdCkpID4+PiB3Yml0O1xuICAgIH1cblxuICAgIHJldHVybiB3O1xuICB9XG5cbiAgLy8gTnVtYmVyIG9mIHRyYWlsaW5nIHplcm8gYml0c1xuICBCTi5wcm90b3R5cGUuemVyb0JpdHMgPSBmdW5jdGlvbiB6ZXJvQml0cyAoKSB7XG4gICAgaWYgKHRoaXMuaXNaZXJvKCkpIHJldHVybiAwO1xuXG4gICAgdmFyIHIgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGIgPSB0aGlzLl96ZXJvQml0cyh0aGlzLndvcmRzW2ldKTtcbiAgICAgIHIgKz0gYjtcbiAgICAgIGlmIChiICE9PSAyNikgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiByO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5ieXRlTGVuZ3RoID0gZnVuY3Rpb24gYnl0ZUxlbmd0aCAoKSB7XG4gICAgcmV0dXJuIE1hdGguY2VpbCh0aGlzLmJpdExlbmd0aCgpIC8gOCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnRvVHdvcyA9IGZ1bmN0aW9uIHRvVHdvcyAod2lkdGgpIHtcbiAgICBpZiAodGhpcy5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMuYWJzKCkuaW5vdG4od2lkdGgpLmlhZGRuKDEpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5mcm9tVHdvcyA9IGZ1bmN0aW9uIGZyb21Ud29zICh3aWR0aCkge1xuICAgIGlmICh0aGlzLnRlc3RuKHdpZHRoIC0gMSkpIHtcbiAgICAgIHJldHVybiB0aGlzLm5vdG4od2lkdGgpLmlhZGRuKDEpLmluZWcoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuaXNOZWcgPSBmdW5jdGlvbiBpc05lZyAoKSB7XG4gICAgcmV0dXJuIHRoaXMubmVnYXRpdmUgIT09IDA7XG4gIH07XG5cbiAgLy8gUmV0dXJuIG5lZ2F0aXZlIGNsb25lIG9mIGB0aGlzYFxuICBCTi5wcm90b3R5cGUubmVnID0gZnVuY3Rpb24gbmVnICgpIHtcbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmluZWcoKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuaW5lZyA9IGZ1bmN0aW9uIGluZWcgKCkge1xuICAgIGlmICghdGhpcy5pc1plcm8oKSkge1xuICAgICAgdGhpcy5uZWdhdGl2ZSBePSAxO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIC8vIE9yIGBudW1gIHdpdGggYHRoaXNgIGluLXBsYWNlXG4gIEJOLnByb3RvdHlwZS5pdW9yID0gZnVuY3Rpb24gaXVvciAobnVtKSB7XG4gICAgd2hpbGUgKHRoaXMubGVuZ3RoIDwgbnVtLmxlbmd0aCkge1xuICAgICAgdGhpcy53b3Jkc1t0aGlzLmxlbmd0aCsrXSA9IDA7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW0ubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMud29yZHNbaV0gPSB0aGlzLndvcmRzW2ldIHwgbnVtLndvcmRzW2ldO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmlvciA9IGZ1bmN0aW9uIGlvciAobnVtKSB7XG4gICAgYXNzZXJ0KCh0aGlzLm5lZ2F0aXZlIHwgbnVtLm5lZ2F0aXZlKSA9PT0gMCk7XG4gICAgcmV0dXJuIHRoaXMuaXVvcihudW0pO1xuICB9O1xuXG4gIC8vIE9yIGBudW1gIHdpdGggYHRoaXNgXG4gIEJOLnByb3RvdHlwZS5vciA9IGZ1bmN0aW9uIG9yIChudW0pIHtcbiAgICBpZiAodGhpcy5sZW5ndGggPiBudW0ubGVuZ3RoKSByZXR1cm4gdGhpcy5jbG9uZSgpLmlvcihudW0pO1xuICAgIHJldHVybiBudW0uY2xvbmUoKS5pb3IodGhpcyk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnVvciA9IGZ1bmN0aW9uIHVvciAobnVtKSB7XG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbnVtLmxlbmd0aCkgcmV0dXJuIHRoaXMuY2xvbmUoKS5pdW9yKG51bSk7XG4gICAgcmV0dXJuIG51bS5jbG9uZSgpLml1b3IodGhpcyk7XG4gIH07XG5cbiAgLy8gQW5kIGBudW1gIHdpdGggYHRoaXNgIGluLXBsYWNlXG4gIEJOLnByb3RvdHlwZS5pdWFuZCA9IGZ1bmN0aW9uIGl1YW5kIChudW0pIHtcbiAgICAvLyBiID0gbWluLWxlbmd0aChudW0sIHRoaXMpXG4gICAgdmFyIGI7XG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbnVtLmxlbmd0aCkge1xuICAgICAgYiA9IG51bTtcbiAgICB9IGVsc2Uge1xuICAgICAgYiA9IHRoaXM7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLndvcmRzW2ldID0gdGhpcy53b3Jkc1tpXSAmIG51bS53b3Jkc1tpXTtcbiAgICB9XG5cbiAgICB0aGlzLmxlbmd0aCA9IGIubGVuZ3RoO1xuXG4gICAgcmV0dXJuIHRoaXMuc3RyaXAoKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuaWFuZCA9IGZ1bmN0aW9uIGlhbmQgKG51bSkge1xuICAgIGFzc2VydCgodGhpcy5uZWdhdGl2ZSB8IG51bS5uZWdhdGl2ZSkgPT09IDApO1xuICAgIHJldHVybiB0aGlzLml1YW5kKG51bSk7XG4gIH07XG5cbiAgLy8gQW5kIGBudW1gIHdpdGggYHRoaXNgXG4gIEJOLnByb3RvdHlwZS5hbmQgPSBmdW5jdGlvbiBhbmQgKG51bSkge1xuICAgIGlmICh0aGlzLmxlbmd0aCA+IG51bS5sZW5ndGgpIHJldHVybiB0aGlzLmNsb25lKCkuaWFuZChudW0pO1xuICAgIHJldHVybiBudW0uY2xvbmUoKS5pYW5kKHRoaXMpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS51YW5kID0gZnVuY3Rpb24gdWFuZCAobnVtKSB7XG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbnVtLmxlbmd0aCkgcmV0dXJuIHRoaXMuY2xvbmUoKS5pdWFuZChudW0pO1xuICAgIHJldHVybiBudW0uY2xvbmUoKS5pdWFuZCh0aGlzKTtcbiAgfTtcblxuICAvLyBYb3IgYG51bWAgd2l0aCBgdGhpc2AgaW4tcGxhY2VcbiAgQk4ucHJvdG90eXBlLml1eG9yID0gZnVuY3Rpb24gaXV4b3IgKG51bSkge1xuICAgIC8vIGEubGVuZ3RoID4gYi5sZW5ndGhcbiAgICB2YXIgYTtcbiAgICB2YXIgYjtcbiAgICBpZiAodGhpcy5sZW5ndGggPiBudW0ubGVuZ3RoKSB7XG4gICAgICBhID0gdGhpcztcbiAgICAgIGIgPSBudW07XG4gICAgfSBlbHNlIHtcbiAgICAgIGEgPSBudW07XG4gICAgICBiID0gdGhpcztcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMud29yZHNbaV0gPSBhLndvcmRzW2ldIF4gYi53b3Jkc1tpXTtcbiAgICB9XG5cbiAgICBpZiAodGhpcyAhPT0gYSkge1xuICAgICAgZm9yICg7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMud29yZHNbaV0gPSBhLndvcmRzW2ldO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMubGVuZ3RoID0gYS5sZW5ndGg7XG5cbiAgICByZXR1cm4gdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5peG9yID0gZnVuY3Rpb24gaXhvciAobnVtKSB7XG4gICAgYXNzZXJ0KCh0aGlzLm5lZ2F0aXZlIHwgbnVtLm5lZ2F0aXZlKSA9PT0gMCk7XG4gICAgcmV0dXJuIHRoaXMuaXV4b3IobnVtKTtcbiAgfTtcblxuICAvLyBYb3IgYG51bWAgd2l0aCBgdGhpc2BcbiAgQk4ucHJvdG90eXBlLnhvciA9IGZ1bmN0aW9uIHhvciAobnVtKSB7XG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbnVtLmxlbmd0aCkgcmV0dXJuIHRoaXMuY2xvbmUoKS5peG9yKG51bSk7XG4gICAgcmV0dXJuIG51bS5jbG9uZSgpLml4b3IodGhpcyk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnV4b3IgPSBmdW5jdGlvbiB1eG9yIChudW0pIHtcbiAgICBpZiAodGhpcy5sZW5ndGggPiBudW0ubGVuZ3RoKSByZXR1cm4gdGhpcy5jbG9uZSgpLml1eG9yKG51bSk7XG4gICAgcmV0dXJuIG51bS5jbG9uZSgpLml1eG9yKHRoaXMpO1xuICB9O1xuXG4gIC8vIE5vdCBgYHRoaXNgYCB3aXRoIGBgd2lkdGhgYCBiaXR3aWR0aFxuICBCTi5wcm90b3R5cGUuaW5vdG4gPSBmdW5jdGlvbiBpbm90biAod2lkdGgpIHtcbiAgICBhc3NlcnQodHlwZW9mIHdpZHRoID09PSAnbnVtYmVyJyAmJiB3aWR0aCA+PSAwKTtcblxuICAgIHZhciBieXRlc05lZWRlZCA9IE1hdGguY2VpbCh3aWR0aCAvIDI2KSB8IDA7XG4gICAgdmFyIGJpdHNMZWZ0ID0gd2lkdGggJSAyNjtcblxuICAgIC8vIEV4dGVuZCB0aGUgYnVmZmVyIHdpdGggbGVhZGluZyB6ZXJvZXNcbiAgICB0aGlzLl9leHBhbmQoYnl0ZXNOZWVkZWQpO1xuXG4gICAgaWYgKGJpdHNMZWZ0ID4gMCkge1xuICAgICAgYnl0ZXNOZWVkZWQtLTtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgY29tcGxldGUgd29yZHNcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJ5dGVzTmVlZGVkOyBpKyspIHtcbiAgICAgIHRoaXMud29yZHNbaV0gPSB+dGhpcy53b3Jkc1tpXSAmIDB4M2ZmZmZmZjtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgdGhlIHJlc2lkdWVcbiAgICBpZiAoYml0c0xlZnQgPiAwKSB7XG4gICAgICB0aGlzLndvcmRzW2ldID0gfnRoaXMud29yZHNbaV0gJiAoMHgzZmZmZmZmID4+ICgyNiAtIGJpdHNMZWZ0KSk7XG4gICAgfVxuXG4gICAgLy8gQW5kIHJlbW92ZSBsZWFkaW5nIHplcm9lc1xuICAgIHJldHVybiB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLm5vdG4gPSBmdW5jdGlvbiBub3RuICh3aWR0aCkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaW5vdG4od2lkdGgpO1xuICB9O1xuXG4gIC8vIFNldCBgYml0YCBvZiBgdGhpc2BcbiAgQk4ucHJvdG90eXBlLnNldG4gPSBmdW5jdGlvbiBzZXRuIChiaXQsIHZhbCkge1xuICAgIGFzc2VydCh0eXBlb2YgYml0ID09PSAnbnVtYmVyJyAmJiBiaXQgPj0gMCk7XG5cbiAgICB2YXIgb2ZmID0gKGJpdCAvIDI2KSB8IDA7XG4gICAgdmFyIHdiaXQgPSBiaXQgJSAyNjtcblxuICAgIHRoaXMuX2V4cGFuZChvZmYgKyAxKTtcblxuICAgIGlmICh2YWwpIHtcbiAgICAgIHRoaXMud29yZHNbb2ZmXSA9IHRoaXMud29yZHNbb2ZmXSB8ICgxIDw8IHdiaXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLndvcmRzW29mZl0gPSB0aGlzLndvcmRzW29mZl0gJiB+KDEgPDwgd2JpdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3RyaXAoKTtcbiAgfTtcblxuICAvLyBBZGQgYG51bWAgdG8gYHRoaXNgIGluLXBsYWNlXG4gIEJOLnByb3RvdHlwZS5pYWRkID0gZnVuY3Rpb24gaWFkZCAobnVtKSB7XG4gICAgdmFyIHI7XG5cbiAgICAvLyBuZWdhdGl2ZSArIHBvc2l0aXZlXG4gICAgaWYgKHRoaXMubmVnYXRpdmUgIT09IDAgJiYgbnVtLm5lZ2F0aXZlID09PSAwKSB7XG4gICAgICB0aGlzLm5lZ2F0aXZlID0gMDtcbiAgICAgIHIgPSB0aGlzLmlzdWIobnVtKTtcbiAgICAgIHRoaXMubmVnYXRpdmUgXj0gMTtcbiAgICAgIHJldHVybiB0aGlzLl9ub3JtU2lnbigpO1xuXG4gICAgLy8gcG9zaXRpdmUgKyBuZWdhdGl2ZVxuICAgIH0gZWxzZSBpZiAodGhpcy5uZWdhdGl2ZSA9PT0gMCAmJiBudW0ubmVnYXRpdmUgIT09IDApIHtcbiAgICAgIG51bS5uZWdhdGl2ZSA9IDA7XG4gICAgICByID0gdGhpcy5pc3ViKG51bSk7XG4gICAgICBudW0ubmVnYXRpdmUgPSAxO1xuICAgICAgcmV0dXJuIHIuX25vcm1TaWduKCk7XG4gICAgfVxuXG4gICAgLy8gYS5sZW5ndGggPiBiLmxlbmd0aFxuICAgIHZhciBhLCBiO1xuICAgIGlmICh0aGlzLmxlbmd0aCA+IG51bS5sZW5ndGgpIHtcbiAgICAgIGEgPSB0aGlzO1xuICAgICAgYiA9IG51bTtcbiAgICB9IGVsc2Uge1xuICAgICAgYSA9IG51bTtcbiAgICAgIGIgPSB0aGlzO1xuICAgIH1cblxuICAgIHZhciBjYXJyeSA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiLmxlbmd0aDsgaSsrKSB7XG4gICAgICByID0gKGEud29yZHNbaV0gfCAwKSArIChiLndvcmRzW2ldIHwgMCkgKyBjYXJyeTtcbiAgICAgIHRoaXMud29yZHNbaV0gPSByICYgMHgzZmZmZmZmO1xuICAgICAgY2FycnkgPSByID4+PiAyNjtcbiAgICB9XG4gICAgZm9yICg7IGNhcnJ5ICE9PSAwICYmIGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICByID0gKGEud29yZHNbaV0gfCAwKSArIGNhcnJ5O1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IHIgJiAweDNmZmZmZmY7XG4gICAgICBjYXJyeSA9IHIgPj4+IDI2O1xuICAgIH1cblxuICAgIHRoaXMubGVuZ3RoID0gYS5sZW5ndGg7XG4gICAgaWYgKGNhcnJ5ICE9PSAwKSB7XG4gICAgICB0aGlzLndvcmRzW3RoaXMubGVuZ3RoXSA9IGNhcnJ5O1xuICAgICAgdGhpcy5sZW5ndGgrKztcbiAgICAvLyBDb3B5IHRoZSByZXN0IG9mIHRoZSB3b3Jkc1xuICAgIH0gZWxzZSBpZiAoYSAhPT0gdGhpcykge1xuICAgICAgZm9yICg7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMud29yZHNbaV0gPSBhLndvcmRzW2ldO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIC8vIEFkZCBgbnVtYCB0byBgdGhpc2BcbiAgQk4ucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIGFkZCAobnVtKSB7XG4gICAgdmFyIHJlcztcbiAgICBpZiAobnVtLm5lZ2F0aXZlICE9PSAwICYmIHRoaXMubmVnYXRpdmUgPT09IDApIHtcbiAgICAgIG51bS5uZWdhdGl2ZSA9IDA7XG4gICAgICByZXMgPSB0aGlzLnN1YihudW0pO1xuICAgICAgbnVtLm5lZ2F0aXZlIF49IDE7XG4gICAgICByZXR1cm4gcmVzO1xuICAgIH0gZWxzZSBpZiAobnVtLm5lZ2F0aXZlID09PSAwICYmIHRoaXMubmVnYXRpdmUgIT09IDApIHtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAwO1xuICAgICAgcmVzID0gbnVtLnN1Yih0aGlzKTtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAxO1xuICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBpZiAodGhpcy5sZW5ndGggPiBudW0ubGVuZ3RoKSByZXR1cm4gdGhpcy5jbG9uZSgpLmlhZGQobnVtKTtcblxuICAgIHJldHVybiBudW0uY2xvbmUoKS5pYWRkKHRoaXMpO1xuICB9O1xuXG4gIC8vIFN1YnRyYWN0IGBudW1gIGZyb20gYHRoaXNgIGluLXBsYWNlXG4gIEJOLnByb3RvdHlwZS5pc3ViID0gZnVuY3Rpb24gaXN1YiAobnVtKSB7XG4gICAgLy8gdGhpcyAtICgtbnVtKSA9IHRoaXMgKyBudW1cbiAgICBpZiAobnVtLm5lZ2F0aXZlICE9PSAwKSB7XG4gICAgICBudW0ubmVnYXRpdmUgPSAwO1xuICAgICAgdmFyIHIgPSB0aGlzLmlhZGQobnVtKTtcbiAgICAgIG51bS5uZWdhdGl2ZSA9IDE7XG4gICAgICByZXR1cm4gci5fbm9ybVNpZ24oKTtcblxuICAgIC8vIC10aGlzIC0gbnVtID0gLSh0aGlzICsgbnVtKVxuICAgIH0gZWxzZSBpZiAodGhpcy5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDA7XG4gICAgICB0aGlzLmlhZGQobnVtKTtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAxO1xuICAgICAgcmV0dXJuIHRoaXMuX25vcm1TaWduKCk7XG4gICAgfVxuXG4gICAgLy8gQXQgdGhpcyBwb2ludCBib3RoIG51bWJlcnMgYXJlIHBvc2l0aXZlXG4gICAgdmFyIGNtcCA9IHRoaXMuY21wKG51bSk7XG5cbiAgICAvLyBPcHRpbWl6YXRpb24gLSB6ZXJvaWZ5XG4gICAgaWYgKGNtcCA9PT0gMCkge1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDA7XG4gICAgICB0aGlzLmxlbmd0aCA9IDE7XG4gICAgICB0aGlzLndvcmRzWzBdID0gMDtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8vIGEgPiBiXG4gICAgdmFyIGEsIGI7XG4gICAgaWYgKGNtcCA+IDApIHtcbiAgICAgIGEgPSB0aGlzO1xuICAgICAgYiA9IG51bTtcbiAgICB9IGVsc2Uge1xuICAgICAgYSA9IG51bTtcbiAgICAgIGIgPSB0aGlzO1xuICAgIH1cblxuICAgIHZhciBjYXJyeSA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiLmxlbmd0aDsgaSsrKSB7XG4gICAgICByID0gKGEud29yZHNbaV0gfCAwKSAtIChiLndvcmRzW2ldIHwgMCkgKyBjYXJyeTtcbiAgICAgIGNhcnJ5ID0gciA+PiAyNjtcbiAgICAgIHRoaXMud29yZHNbaV0gPSByICYgMHgzZmZmZmZmO1xuICAgIH1cbiAgICBmb3IgKDsgY2FycnkgIT09IDAgJiYgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgIHIgPSAoYS53b3Jkc1tpXSB8IDApICsgY2Fycnk7XG4gICAgICBjYXJyeSA9IHIgPj4gMjY7XG4gICAgICB0aGlzLndvcmRzW2ldID0gciAmIDB4M2ZmZmZmZjtcbiAgICB9XG5cbiAgICAvLyBDb3B5IHJlc3Qgb2YgdGhlIHdvcmRzXG4gICAgaWYgKGNhcnJ5ID09PSAwICYmIGkgPCBhLmxlbmd0aCAmJiBhICE9PSB0aGlzKSB7XG4gICAgICBmb3IgKDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy53b3Jkc1tpXSA9IGEud29yZHNbaV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5sZW5ndGggPSBNYXRoLm1heCh0aGlzLmxlbmd0aCwgaSk7XG5cbiAgICBpZiAoYSAhPT0gdGhpcykge1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDE7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3RyaXAoKTtcbiAgfTtcblxuICAvLyBTdWJ0cmFjdCBgbnVtYCBmcm9tIGB0aGlzYFxuICBCTi5wcm90b3R5cGUuc3ViID0gZnVuY3Rpb24gc3ViIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmlzdWIobnVtKTtcbiAgfTtcblxuICBmdW5jdGlvbiBzbWFsbE11bFRvIChzZWxmLCBudW0sIG91dCkge1xuICAgIG91dC5uZWdhdGl2ZSA9IG51bS5uZWdhdGl2ZSBeIHNlbGYubmVnYXRpdmU7XG4gICAgdmFyIGxlbiA9IChzZWxmLmxlbmd0aCArIG51bS5sZW5ndGgpIHwgMDtcbiAgICBvdXQubGVuZ3RoID0gbGVuO1xuICAgIGxlbiA9IChsZW4gLSAxKSB8IDA7XG5cbiAgICAvLyBQZWVsIG9uZSBpdGVyYXRpb24gKGNvbXBpbGVyIGNhbid0IGRvIGl0LCBiZWNhdXNlIG9mIGNvZGUgY29tcGxleGl0eSlcbiAgICB2YXIgYSA9IHNlbGYud29yZHNbMF0gfCAwO1xuICAgIHZhciBiID0gbnVtLndvcmRzWzBdIHwgMDtcbiAgICB2YXIgciA9IGEgKiBiO1xuXG4gICAgdmFyIGxvID0gciAmIDB4M2ZmZmZmZjtcbiAgICB2YXIgY2FycnkgPSAociAvIDB4NDAwMDAwMCkgfCAwO1xuICAgIG91dC53b3Jkc1swXSA9IGxvO1xuXG4gICAgZm9yICh2YXIgayA9IDE7IGsgPCBsZW47IGsrKykge1xuICAgICAgLy8gU3VtIGFsbCB3b3JkcyB3aXRoIHRoZSBzYW1lIGBpICsgaiA9IGtgIGFuZCBhY2N1bXVsYXRlIGBuY2FycnlgLFxuICAgICAgLy8gbm90ZSB0aGF0IG5jYXJyeSBjb3VsZCBiZSA+PSAweDNmZmZmZmZcbiAgICAgIHZhciBuY2FycnkgPSBjYXJyeSA+Pj4gMjY7XG4gICAgICB2YXIgcndvcmQgPSBjYXJyeSAmIDB4M2ZmZmZmZjtcbiAgICAgIHZhciBtYXhKID0gTWF0aC5taW4oaywgbnVtLmxlbmd0aCAtIDEpO1xuICAgICAgZm9yICh2YXIgaiA9IE1hdGgubWF4KDAsIGsgLSBzZWxmLmxlbmd0aCArIDEpOyBqIDw9IG1heEo7IGorKykge1xuICAgICAgICB2YXIgaSA9IChrIC0gaikgfCAwO1xuICAgICAgICBhID0gc2VsZi53b3Jkc1tpXSB8IDA7XG4gICAgICAgIGIgPSBudW0ud29yZHNbal0gfCAwO1xuICAgICAgICByID0gYSAqIGIgKyByd29yZDtcbiAgICAgICAgbmNhcnJ5ICs9IChyIC8gMHg0MDAwMDAwKSB8IDA7XG4gICAgICAgIHJ3b3JkID0gciAmIDB4M2ZmZmZmZjtcbiAgICAgIH1cbiAgICAgIG91dC53b3Jkc1trXSA9IHJ3b3JkIHwgMDtcbiAgICAgIGNhcnJ5ID0gbmNhcnJ5IHwgMDtcbiAgICB9XG4gICAgaWYgKGNhcnJ5ICE9PSAwKSB7XG4gICAgICBvdXQud29yZHNba10gPSBjYXJyeSB8IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dC5sZW5ndGgtLTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0LnN0cmlwKCk7XG4gIH1cblxuICAvLyBUT0RPKGluZHV0bnkpOiBpdCBtYXkgYmUgcmVhc29uYWJsZSB0byBvbWl0IGl0IGZvciB1c2VycyB3aG8gZG9uJ3QgbmVlZFxuICAvLyB0byB3b3JrIHdpdGggMjU2LWJpdCBudW1iZXJzLCBvdGhlcndpc2UgaXQgZ2l2ZXMgMjAlIGltcHJvdmVtZW50IGZvciAyNTYtYml0XG4gIC8vIG11bHRpcGxpY2F0aW9uIChsaWtlIGVsbGlwdGljIHNlY3AyNTZrMSkuXG4gIHZhciBjb21iMTBNdWxUbyA9IGZ1bmN0aW9uIGNvbWIxME11bFRvIChzZWxmLCBudW0sIG91dCkge1xuICAgIHZhciBhID0gc2VsZi53b3JkcztcbiAgICB2YXIgYiA9IG51bS53b3JkcztcbiAgICB2YXIgbyA9IG91dC53b3JkcztcbiAgICB2YXIgYyA9IDA7XG4gICAgdmFyIGxvO1xuICAgIHZhciBtaWQ7XG4gICAgdmFyIGhpO1xuICAgIHZhciBhMCA9IGFbMF0gfCAwO1xuICAgIHZhciBhbDAgPSBhMCAmIDB4MWZmZjtcbiAgICB2YXIgYWgwID0gYTAgPj4+IDEzO1xuICAgIHZhciBhMSA9IGFbMV0gfCAwO1xuICAgIHZhciBhbDEgPSBhMSAmIDB4MWZmZjtcbiAgICB2YXIgYWgxID0gYTEgPj4+IDEzO1xuICAgIHZhciBhMiA9IGFbMl0gfCAwO1xuICAgIHZhciBhbDIgPSBhMiAmIDB4MWZmZjtcbiAgICB2YXIgYWgyID0gYTIgPj4+IDEzO1xuICAgIHZhciBhMyA9IGFbM10gfCAwO1xuICAgIHZhciBhbDMgPSBhMyAmIDB4MWZmZjtcbiAgICB2YXIgYWgzID0gYTMgPj4+IDEzO1xuICAgIHZhciBhNCA9IGFbNF0gfCAwO1xuICAgIHZhciBhbDQgPSBhNCAmIDB4MWZmZjtcbiAgICB2YXIgYWg0ID0gYTQgPj4+IDEzO1xuICAgIHZhciBhNSA9IGFbNV0gfCAwO1xuICAgIHZhciBhbDUgPSBhNSAmIDB4MWZmZjtcbiAgICB2YXIgYWg1ID0gYTUgPj4+IDEzO1xuICAgIHZhciBhNiA9IGFbNl0gfCAwO1xuICAgIHZhciBhbDYgPSBhNiAmIDB4MWZmZjtcbiAgICB2YXIgYWg2ID0gYTYgPj4+IDEzO1xuICAgIHZhciBhNyA9IGFbN10gfCAwO1xuICAgIHZhciBhbDcgPSBhNyAmIDB4MWZmZjtcbiAgICB2YXIgYWg3ID0gYTcgPj4+IDEzO1xuICAgIHZhciBhOCA9IGFbOF0gfCAwO1xuICAgIHZhciBhbDggPSBhOCAmIDB4MWZmZjtcbiAgICB2YXIgYWg4ID0gYTggPj4+IDEzO1xuICAgIHZhciBhOSA9IGFbOV0gfCAwO1xuICAgIHZhciBhbDkgPSBhOSAmIDB4MWZmZjtcbiAgICB2YXIgYWg5ID0gYTkgPj4+IDEzO1xuICAgIHZhciBiMCA9IGJbMF0gfCAwO1xuICAgIHZhciBibDAgPSBiMCAmIDB4MWZmZjtcbiAgICB2YXIgYmgwID0gYjAgPj4+IDEzO1xuICAgIHZhciBiMSA9IGJbMV0gfCAwO1xuICAgIHZhciBibDEgPSBiMSAmIDB4MWZmZjtcbiAgICB2YXIgYmgxID0gYjEgPj4+IDEzO1xuICAgIHZhciBiMiA9IGJbMl0gfCAwO1xuICAgIHZhciBibDIgPSBiMiAmIDB4MWZmZjtcbiAgICB2YXIgYmgyID0gYjIgPj4+IDEzO1xuICAgIHZhciBiMyA9IGJbM10gfCAwO1xuICAgIHZhciBibDMgPSBiMyAmIDB4MWZmZjtcbiAgICB2YXIgYmgzID0gYjMgPj4+IDEzO1xuICAgIHZhciBiNCA9IGJbNF0gfCAwO1xuICAgIHZhciBibDQgPSBiNCAmIDB4MWZmZjtcbiAgICB2YXIgYmg0ID0gYjQgPj4+IDEzO1xuICAgIHZhciBiNSA9IGJbNV0gfCAwO1xuICAgIHZhciBibDUgPSBiNSAmIDB4MWZmZjtcbiAgICB2YXIgYmg1ID0gYjUgPj4+IDEzO1xuICAgIHZhciBiNiA9IGJbNl0gfCAwO1xuICAgIHZhciBibDYgPSBiNiAmIDB4MWZmZjtcbiAgICB2YXIgYmg2ID0gYjYgPj4+IDEzO1xuICAgIHZhciBiNyA9IGJbN10gfCAwO1xuICAgIHZhciBibDcgPSBiNyAmIDB4MWZmZjtcbiAgICB2YXIgYmg3ID0gYjcgPj4+IDEzO1xuICAgIHZhciBiOCA9IGJbOF0gfCAwO1xuICAgIHZhciBibDggPSBiOCAmIDB4MWZmZjtcbiAgICB2YXIgYmg4ID0gYjggPj4+IDEzO1xuICAgIHZhciBiOSA9IGJbOV0gfCAwO1xuICAgIHZhciBibDkgPSBiOSAmIDB4MWZmZjtcbiAgICB2YXIgYmg5ID0gYjkgPj4+IDEzO1xuXG4gICAgb3V0Lm5lZ2F0aXZlID0gc2VsZi5uZWdhdGl2ZSBeIG51bS5uZWdhdGl2ZTtcbiAgICBvdXQubGVuZ3RoID0gMTk7XG4gICAgLyogayA9IDAgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDAsIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsMCwgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMCwgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoMCwgYmgwKTtcbiAgICB2YXIgdzAgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcwID4+PiAyNikpIHwgMDtcbiAgICB3MCAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDEgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDEsIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsMSwgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoMSwgYmgwKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDAsIGJsMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMCwgYmgxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgwLCBibDEpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgwLCBiaDEpKSB8IDA7XG4gICAgdmFyIHcxID0gKCgoYyArIGxvKSB8IDApICsgKChtaWQgJiAweDFmZmYpIDw8IDEzKSkgfCAwO1xuICAgIGMgPSAoKChoaSArIChtaWQgPj4+IDEzKSkgfCAwKSArICh3MSA+Pj4gMjYpKSB8IDA7XG4gICAgdzEgJj0gMHgzZmZmZmZmO1xuICAgIC8qIGsgPSAyICovXG4gICAgbG8gPSBNYXRoLmltdWwoYWwyLCBibDApO1xuICAgIG1pZCA9IE1hdGguaW11bChhbDIsIGJoMCk7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDIsIGJsMCkpIHwgMDtcbiAgICBoaSA9IE1hdGguaW11bChhaDIsIGJoMCk7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwxLCBibDEpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDEsIGJoMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmwxKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMSwgYmgxKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMCwgYmwyKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwwLCBiaDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDAsIGJsMikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDAsIGJoMikpIHwgMDtcbiAgICB2YXIgdzIgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcyID4+PiAyNikpIHwgMDtcbiAgICB3MiAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDMgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDMsIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsMywgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMywgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoMywgYmgwKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDIsIGJsMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMiwgYmgxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgyLCBibDEpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgyLCBiaDEpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwxLCBibDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDEsIGJoMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmwyKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMSwgYmgyKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMCwgYmwzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwwLCBiaDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDAsIGJsMykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDAsIGJoMykpIHwgMDtcbiAgICB2YXIgdzMgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHczID4+PiAyNikpIHwgMDtcbiAgICB3MyAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDQgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDQsIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsNCwgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoNCwgYmgwKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDMsIGJsMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMywgYmgxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgzLCBibDEpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgzLCBiaDEpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwyLCBibDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDIsIGJoMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMiwgYmwyKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMiwgYmgyKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMSwgYmwzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwxLCBiaDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDEsIGJsMykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDEsIGJoMykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDAsIGJsNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMCwgYmg0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgwLCBibDQpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgwLCBiaDQpKSB8IDA7XG4gICAgdmFyIHc0ID0gKCgoYyArIGxvKSB8IDApICsgKChtaWQgJiAweDFmZmYpIDw8IDEzKSkgfCAwO1xuICAgIGMgPSAoKChoaSArIChtaWQgPj4+IDEzKSkgfCAwKSArICh3NCA+Pj4gMjYpKSB8IDA7XG4gICAgdzQgJj0gMHgzZmZmZmZmO1xuICAgIC8qIGsgPSA1ICovXG4gICAgbG8gPSBNYXRoLmltdWwoYWw1LCBibDApO1xuICAgIG1pZCA9IE1hdGguaW11bChhbDUsIGJoMCk7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDUsIGJsMCkpIHwgMDtcbiAgICBoaSA9IE1hdGguaW11bChhaDUsIGJoMCk7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw0LCBibDEpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDQsIGJoMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmwxKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNCwgYmgxKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMywgYmwyKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwzLCBiaDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDMsIGJsMikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDMsIGJoMikpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDIsIGJsMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMiwgYmgzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgyLCBibDMpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgyLCBiaDMpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwxLCBibDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDEsIGJoNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmw0KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMSwgYmg0KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMCwgYmw1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwwLCBiaDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDAsIGJsNSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDAsIGJoNSkpIHwgMDtcbiAgICB2YXIgdzUgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHc1ID4+PiAyNikpIHwgMDtcbiAgICB3NSAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDYgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDYsIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsNiwgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNiwgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoNiwgYmgwKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDUsIGJsMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNSwgYmgxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg1LCBibDEpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg1LCBiaDEpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw0LCBibDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDQsIGJoMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmwyKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNCwgYmgyKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMywgYmwzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwzLCBiaDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDMsIGJsMykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDMsIGJoMykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDIsIGJsNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMiwgYmg0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgyLCBibDQpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgyLCBiaDQpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwxLCBibDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDEsIGJoNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmw1KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMSwgYmg1KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMCwgYmw2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwwLCBiaDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDAsIGJsNikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDAsIGJoNikpIHwgMDtcbiAgICB2YXIgdzYgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHc2ID4+PiAyNikpIHwgMDtcbiAgICB3NiAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDcgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDcsIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsNywgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoNywgYmgwKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDYsIGJsMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNiwgYmgxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg2LCBibDEpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg2LCBiaDEpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw1LCBibDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDUsIGJoMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNSwgYmwyKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNSwgYmgyKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNCwgYmwzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw0LCBiaDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDQsIGJsMykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDQsIGJoMykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDMsIGJsNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMywgYmg0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgzLCBibDQpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgzLCBiaDQpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwyLCBibDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDIsIGJoNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMiwgYmw1KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMiwgYmg1KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMSwgYmw2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwxLCBiaDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDEsIGJsNikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDEsIGJoNikpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDAsIGJsNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMCwgYmg3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgwLCBibDcpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgwLCBiaDcpKSB8IDA7XG4gICAgdmFyIHc3ID0gKCgoYyArIGxvKSB8IDApICsgKChtaWQgJiAweDFmZmYpIDw8IDEzKSkgfCAwO1xuICAgIGMgPSAoKChoaSArIChtaWQgPj4+IDEzKSkgfCAwKSArICh3NyA+Pj4gMjYpKSB8IDA7XG4gICAgdzcgJj0gMHgzZmZmZmZmO1xuICAgIC8qIGsgPSA4ICovXG4gICAgbG8gPSBNYXRoLmltdWwoYWw4LCBibDApO1xuICAgIG1pZCA9IE1hdGguaW11bChhbDgsIGJoMCk7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDgsIGJsMCkpIHwgMDtcbiAgICBoaSA9IE1hdGguaW11bChhaDgsIGJoMCk7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw3LCBibDEpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDcsIGJoMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmwxKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNywgYmgxKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNiwgYmwyKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw2LCBiaDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDYsIGJsMikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDYsIGJoMikpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDUsIGJsMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNSwgYmgzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg1LCBibDMpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg1LCBiaDMpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw0LCBibDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDQsIGJoNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmw0KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNCwgYmg0KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMywgYmw1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwzLCBiaDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDMsIGJsNSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDMsIGJoNSkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDIsIGJsNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMiwgYmg2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgyLCBibDYpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgyLCBiaDYpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwxLCBibDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDEsIGJoNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmw3KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMSwgYmg3KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMCwgYmw4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwwLCBiaDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDAsIGJsOCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDAsIGJoOCkpIHwgMDtcbiAgICB2YXIgdzggPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHc4ID4+PiAyNikpIHwgMDtcbiAgICB3OCAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDkgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsMCk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmgwKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmwwKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmgwKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDgsIGJsMSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsOCwgYmgxKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg4LCBibDEpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg4LCBiaDEpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw3LCBibDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDcsIGJoMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmwyKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNywgYmgyKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNiwgYmwzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw2LCBiaDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDYsIGJsMykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDYsIGJoMykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDUsIGJsNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNSwgYmg0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg1LCBibDQpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg1LCBiaDQpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw0LCBibDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDQsIGJoNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmw1KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNCwgYmg1KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMywgYmw2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwzLCBiaDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDMsIGJsNikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDMsIGJoNikpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDIsIGJsNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMiwgYmg3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgyLCBibDcpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgyLCBiaDcpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwxLCBibDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDEsIGJoOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMSwgYmw4KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMSwgYmg4KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMCwgYmw5KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwwLCBiaDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDAsIGJsOSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDAsIGJoOSkpIHwgMDtcbiAgICB2YXIgdzkgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHc5ID4+PiAyNikpIHwgMDtcbiAgICB3OSAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDEwICovXG4gICAgbG8gPSBNYXRoLmltdWwoYWw5LCBibDEpO1xuICAgIG1pZCA9IE1hdGguaW11bChhbDksIGJoMSk7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDksIGJsMSkpIHwgMDtcbiAgICBoaSA9IE1hdGguaW11bChhaDksIGJoMSk7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw4LCBibDIpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDgsIGJoMikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOCwgYmwyKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoOCwgYmgyKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNywgYmwzKSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw3LCBiaDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDcsIGJsMykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDcsIGJoMykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDYsIGJsNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNiwgYmg0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg2LCBibDQpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg2LCBiaDQpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw1LCBibDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDUsIGJoNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNSwgYmw1KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNSwgYmg1KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNCwgYmw2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw0LCBiaDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDQsIGJsNikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDQsIGJoNikpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDMsIGJsNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMywgYmg3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgzLCBibDcpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgzLCBiaDcpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwyLCBibDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDIsIGJoOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMiwgYmw4KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMiwgYmg4KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMSwgYmw5KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwxLCBiaDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDEsIGJsOSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDEsIGJoOSkpIHwgMDtcbiAgICB2YXIgdzEwID0gKCgoYyArIGxvKSB8IDApICsgKChtaWQgJiAweDFmZmYpIDw8IDEzKSkgfCAwO1xuICAgIGMgPSAoKChoaSArIChtaWQgPj4+IDEzKSkgfCAwKSArICh3MTAgPj4+IDI2KSkgfCAwO1xuICAgIHcxMCAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDExICovXG4gICAgbG8gPSBNYXRoLmltdWwoYWw5LCBibDIpO1xuICAgIG1pZCA9IE1hdGguaW11bChhbDksIGJoMik7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDksIGJsMikpIHwgMDtcbiAgICBoaSA9IE1hdGguaW11bChhaDksIGJoMik7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw4LCBibDMpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDgsIGJoMykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOCwgYmwzKSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoOCwgYmgzKSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNywgYmw0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw3LCBiaDQpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDcsIGJsNCkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDcsIGJoNCkpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDYsIGJsNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNiwgYmg1KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg2LCBibDUpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg2LCBiaDUpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw1LCBibDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDUsIGJoNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNSwgYmw2KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNSwgYmg2KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNCwgYmw3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw0LCBiaDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDQsIGJsNykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDQsIGJoNykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDMsIGJsOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsMywgYmg4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWgzLCBibDgpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWgzLCBiaDgpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWwyLCBibDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDIsIGJoOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoMiwgYmw5KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoMiwgYmg5KSkgfCAwO1xuICAgIHZhciB3MTEgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxMSA+Pj4gMjYpKSB8IDA7XG4gICAgdzExICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMTIgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsMyk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmgzKTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmwzKSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmgzKTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDgsIGJsNCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsOCwgYmg0KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg4LCBibDQpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg4LCBiaDQpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw3LCBibDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDcsIGJoNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmw1KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNywgYmg1KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNiwgYmw2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw2LCBiaDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDYsIGJsNikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDYsIGJoNikpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDUsIGJsNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNSwgYmg3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg1LCBibDcpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg1LCBiaDcpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw0LCBibDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDQsIGJoOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNCwgYmw4KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNCwgYmg4KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsMywgYmw5KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWwzLCBiaDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDMsIGJsOSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDMsIGJoOSkpIHwgMDtcbiAgICB2YXIgdzEyID0gKCgoYyArIGxvKSB8IDApICsgKChtaWQgJiAweDFmZmYpIDw8IDEzKSkgfCAwO1xuICAgIGMgPSAoKChoaSArIChtaWQgPj4+IDEzKSkgfCAwKSArICh3MTIgPj4+IDI2KSkgfCAwO1xuICAgIHcxMiAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDEzICovXG4gICAgbG8gPSBNYXRoLmltdWwoYWw5LCBibDQpO1xuICAgIG1pZCA9IE1hdGguaW11bChhbDksIGJoNCk7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDksIGJsNCkpIHwgMDtcbiAgICBoaSA9IE1hdGguaW11bChhaDksIGJoNCk7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw4LCBibDUpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDgsIGJoNSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOCwgYmw1KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoOCwgYmg1KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNywgYmw2KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw3LCBiaDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDcsIGJsNikpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDcsIGJoNikpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDYsIGJsNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNiwgYmg3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg2LCBibDcpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg2LCBiaDcpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw1LCBibDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDUsIGJoOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNSwgYmw4KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNSwgYmg4KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNCwgYmw5KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw0LCBiaDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDQsIGJsOSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDQsIGJoOSkpIHwgMDtcbiAgICB2YXIgdzEzID0gKCgoYyArIGxvKSB8IDApICsgKChtaWQgJiAweDFmZmYpIDw8IDEzKSkgfCAwO1xuICAgIGMgPSAoKChoaSArIChtaWQgPj4+IDEzKSkgfCAwKSArICh3MTMgPj4+IDI2KSkgfCAwO1xuICAgIHcxMyAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDE0ICovXG4gICAgbG8gPSBNYXRoLmltdWwoYWw5LCBibDUpO1xuICAgIG1pZCA9IE1hdGguaW11bChhbDksIGJoNSk7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDksIGJsNSkpIHwgMDtcbiAgICBoaSA9IE1hdGguaW11bChhaDksIGJoNSk7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw4LCBibDYpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDgsIGJoNikpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOCwgYmw2KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoOCwgYmg2KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNywgYmw3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw3LCBiaDcpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDcsIGJsNykpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDcsIGJoNykpIHwgMDtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDYsIGJsOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsNiwgYmg4KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg2LCBibDgpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg2LCBiaDgpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw1LCBibDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDUsIGJoOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNSwgYmw5KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNSwgYmg5KSkgfCAwO1xuICAgIHZhciB3MTQgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxNCA+Pj4gMjYpKSB8IDA7XG4gICAgdzE0ICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMTUgKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsNik7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmg2KTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmw2KSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmg2KTtcbiAgICBsbyA9IChsbyArIE1hdGguaW11bChhbDgsIGJsNykpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFsOCwgYmg3KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWg4LCBibDcpKSB8IDA7XG4gICAgaGkgPSAoaGkgKyBNYXRoLmltdWwoYWg4LCBiaDcpKSB8IDA7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw3LCBibDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDcsIGJoOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoNywgYmw4KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoNywgYmg4KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNiwgYmw5KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw2LCBiaDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDYsIGJsOSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDYsIGJoOSkpIHwgMDtcbiAgICB2YXIgdzE1ID0gKCgoYyArIGxvKSB8IDApICsgKChtaWQgJiAweDFmZmYpIDw8IDEzKSkgfCAwO1xuICAgIGMgPSAoKChoaSArIChtaWQgPj4+IDEzKSkgfCAwKSArICh3MTUgPj4+IDI2KSkgfCAwO1xuICAgIHcxNSAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDE2ICovXG4gICAgbG8gPSBNYXRoLmltdWwoYWw5LCBibDcpO1xuICAgIG1pZCA9IE1hdGguaW11bChhbDksIGJoNyk7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDksIGJsNykpIHwgMDtcbiAgICBoaSA9IE1hdGguaW11bChhaDksIGJoNyk7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw4LCBibDgpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDgsIGJoOCkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOCwgYmw4KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoOCwgYmg4KSkgfCAwO1xuICAgIGxvID0gKGxvICsgTWF0aC5pbXVsKGFsNywgYmw5KSkgfCAwO1xuICAgIG1pZCA9IChtaWQgKyBNYXRoLmltdWwoYWw3LCBiaDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDcsIGJsOSkpIHwgMDtcbiAgICBoaSA9IChoaSArIE1hdGguaW11bChhaDcsIGJoOSkpIHwgMDtcbiAgICB2YXIgdzE2ID0gKCgoYyArIGxvKSB8IDApICsgKChtaWQgJiAweDFmZmYpIDw8IDEzKSkgfCAwO1xuICAgIGMgPSAoKChoaSArIChtaWQgPj4+IDEzKSkgfCAwKSArICh3MTYgPj4+IDI2KSkgfCAwO1xuICAgIHcxNiAmPSAweDNmZmZmZmY7XG4gICAgLyogayA9IDE3ICovXG4gICAgbG8gPSBNYXRoLmltdWwoYWw5LCBibDgpO1xuICAgIG1pZCA9IE1hdGguaW11bChhbDksIGJoOCk7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhaDksIGJsOCkpIHwgMDtcbiAgICBoaSA9IE1hdGguaW11bChhaDksIGJoOCk7XG4gICAgbG8gPSAobG8gKyBNYXRoLmltdWwoYWw4LCBibDkpKSB8IDA7XG4gICAgbWlkID0gKG1pZCArIE1hdGguaW11bChhbDgsIGJoOSkpIHwgMDtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOCwgYmw5KSkgfCAwO1xuICAgIGhpID0gKGhpICsgTWF0aC5pbXVsKGFoOCwgYmg5KSkgfCAwO1xuICAgIHZhciB3MTcgPSAoKChjICsgbG8pIHwgMCkgKyAoKG1pZCAmIDB4MWZmZikgPDwgMTMpKSB8IDA7XG4gICAgYyA9ICgoKGhpICsgKG1pZCA+Pj4gMTMpKSB8IDApICsgKHcxNyA+Pj4gMjYpKSB8IDA7XG4gICAgdzE3ICY9IDB4M2ZmZmZmZjtcbiAgICAvKiBrID0gMTggKi9cbiAgICBsbyA9IE1hdGguaW11bChhbDksIGJsOSk7XG4gICAgbWlkID0gTWF0aC5pbXVsKGFsOSwgYmg5KTtcbiAgICBtaWQgPSAobWlkICsgTWF0aC5pbXVsKGFoOSwgYmw5KSkgfCAwO1xuICAgIGhpID0gTWF0aC5pbXVsKGFoOSwgYmg5KTtcbiAgICB2YXIgdzE4ID0gKCgoYyArIGxvKSB8IDApICsgKChtaWQgJiAweDFmZmYpIDw8IDEzKSkgfCAwO1xuICAgIGMgPSAoKChoaSArIChtaWQgPj4+IDEzKSkgfCAwKSArICh3MTggPj4+IDI2KSkgfCAwO1xuICAgIHcxOCAmPSAweDNmZmZmZmY7XG4gICAgb1swXSA9IHcwO1xuICAgIG9bMV0gPSB3MTtcbiAgICBvWzJdID0gdzI7XG4gICAgb1szXSA9IHczO1xuICAgIG9bNF0gPSB3NDtcbiAgICBvWzVdID0gdzU7XG4gICAgb1s2XSA9IHc2O1xuICAgIG9bN10gPSB3NztcbiAgICBvWzhdID0gdzg7XG4gICAgb1s5XSA9IHc5O1xuICAgIG9bMTBdID0gdzEwO1xuICAgIG9bMTFdID0gdzExO1xuICAgIG9bMTJdID0gdzEyO1xuICAgIG9bMTNdID0gdzEzO1xuICAgIG9bMTRdID0gdzE0O1xuICAgIG9bMTVdID0gdzE1O1xuICAgIG9bMTZdID0gdzE2O1xuICAgIG9bMTddID0gdzE3O1xuICAgIG9bMThdID0gdzE4O1xuICAgIGlmIChjICE9PSAwKSB7XG4gICAgICBvWzE5XSA9IGM7XG4gICAgICBvdXQubGVuZ3RoKys7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH07XG5cbiAgLy8gUG9seWZpbGwgY29tYlxuICBpZiAoIU1hdGguaW11bCkge1xuICAgIGNvbWIxME11bFRvID0gc21hbGxNdWxUbztcbiAgfVxuXG4gIGZ1bmN0aW9uIGJpZ011bFRvIChzZWxmLCBudW0sIG91dCkge1xuICAgIG91dC5uZWdhdGl2ZSA9IG51bS5uZWdhdGl2ZSBeIHNlbGYubmVnYXRpdmU7XG4gICAgb3V0Lmxlbmd0aCA9IHNlbGYubGVuZ3RoICsgbnVtLmxlbmd0aDtcblxuICAgIHZhciBjYXJyeSA9IDA7XG4gICAgdmFyIGhuY2FycnkgPSAwO1xuICAgIGZvciAodmFyIGsgPSAwOyBrIDwgb3V0Lmxlbmd0aCAtIDE7IGsrKykge1xuICAgICAgLy8gU3VtIGFsbCB3b3JkcyB3aXRoIHRoZSBzYW1lIGBpICsgaiA9IGtgIGFuZCBhY2N1bXVsYXRlIGBuY2FycnlgLFxuICAgICAgLy8gbm90ZSB0aGF0IG5jYXJyeSBjb3VsZCBiZSA+PSAweDNmZmZmZmZcbiAgICAgIHZhciBuY2FycnkgPSBobmNhcnJ5O1xuICAgICAgaG5jYXJyeSA9IDA7XG4gICAgICB2YXIgcndvcmQgPSBjYXJyeSAmIDB4M2ZmZmZmZjtcbiAgICAgIHZhciBtYXhKID0gTWF0aC5taW4oaywgbnVtLmxlbmd0aCAtIDEpO1xuICAgICAgZm9yICh2YXIgaiA9IE1hdGgubWF4KDAsIGsgLSBzZWxmLmxlbmd0aCArIDEpOyBqIDw9IG1heEo7IGorKykge1xuICAgICAgICB2YXIgaSA9IGsgLSBqO1xuICAgICAgICB2YXIgYSA9IHNlbGYud29yZHNbaV0gfCAwO1xuICAgICAgICB2YXIgYiA9IG51bS53b3Jkc1tqXSB8IDA7XG4gICAgICAgIHZhciByID0gYSAqIGI7XG5cbiAgICAgICAgdmFyIGxvID0gciAmIDB4M2ZmZmZmZjtcbiAgICAgICAgbmNhcnJ5ID0gKG5jYXJyeSArICgociAvIDB4NDAwMDAwMCkgfCAwKSkgfCAwO1xuICAgICAgICBsbyA9IChsbyArIHJ3b3JkKSB8IDA7XG4gICAgICAgIHJ3b3JkID0gbG8gJiAweDNmZmZmZmY7XG4gICAgICAgIG5jYXJyeSA9IChuY2FycnkgKyAobG8gPj4+IDI2KSkgfCAwO1xuXG4gICAgICAgIGhuY2FycnkgKz0gbmNhcnJ5ID4+PiAyNjtcbiAgICAgICAgbmNhcnJ5ICY9IDB4M2ZmZmZmZjtcbiAgICAgIH1cbiAgICAgIG91dC53b3Jkc1trXSA9IHJ3b3JkO1xuICAgICAgY2FycnkgPSBuY2Fycnk7XG4gICAgICBuY2FycnkgPSBobmNhcnJ5O1xuICAgIH1cbiAgICBpZiAoY2FycnkgIT09IDApIHtcbiAgICAgIG91dC53b3Jkc1trXSA9IGNhcnJ5O1xuICAgIH0gZWxzZSB7XG4gICAgICBvdXQubGVuZ3RoLS07XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dC5zdHJpcCgpO1xuICB9XG5cbiAgZnVuY3Rpb24ganVtYm9NdWxUbyAoc2VsZiwgbnVtLCBvdXQpIHtcbiAgICB2YXIgZmZ0bSA9IG5ldyBGRlRNKCk7XG4gICAgcmV0dXJuIGZmdG0ubXVscChzZWxmLCBudW0sIG91dCk7XG4gIH1cblxuICBCTi5wcm90b3R5cGUubXVsVG8gPSBmdW5jdGlvbiBtdWxUbyAobnVtLCBvdXQpIHtcbiAgICB2YXIgcmVzO1xuICAgIHZhciBsZW4gPSB0aGlzLmxlbmd0aCArIG51bS5sZW5ndGg7XG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAxMCAmJiBudW0ubGVuZ3RoID09PSAxMCkge1xuICAgICAgcmVzID0gY29tYjEwTXVsVG8odGhpcywgbnVtLCBvdXQpO1xuICAgIH0gZWxzZSBpZiAobGVuIDwgNjMpIHtcbiAgICAgIHJlcyA9IHNtYWxsTXVsVG8odGhpcywgbnVtLCBvdXQpO1xuICAgIH0gZWxzZSBpZiAobGVuIDwgMTAyNCkge1xuICAgICAgcmVzID0gYmlnTXVsVG8odGhpcywgbnVtLCBvdXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXMgPSBqdW1ib011bFRvKHRoaXMsIG51bSwgb3V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xuICB9O1xuXG4gIC8vIENvb2xleS1UdWtleSBhbGdvcml0aG0gZm9yIEZGVFxuICAvLyBzbGlnaHRseSByZXZpc2l0ZWQgdG8gcmVseSBvbiBsb29waW5nIGluc3RlYWQgb2YgcmVjdXJzaW9uXG5cbiAgZnVuY3Rpb24gRkZUTSAoeCwgeSkge1xuICAgIHRoaXMueCA9IHg7XG4gICAgdGhpcy55ID0geTtcbiAgfVxuXG4gIEZGVE0ucHJvdG90eXBlLm1ha2VSQlQgPSBmdW5jdGlvbiBtYWtlUkJUIChOKSB7XG4gICAgdmFyIHQgPSBuZXcgQXJyYXkoTik7XG4gICAgdmFyIGwgPSBCTi5wcm90b3R5cGUuX2NvdW50Qml0cyhOKSAtIDE7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBOOyBpKyspIHtcbiAgICAgIHRbaV0gPSB0aGlzLnJldkJpbihpLCBsLCBOKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdDtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGJpbmFyeS1yZXZlcnNlZCByZXByZXNlbnRhdGlvbiBvZiBgeGBcbiAgRkZUTS5wcm90b3R5cGUucmV2QmluID0gZnVuY3Rpb24gcmV2QmluICh4LCBsLCBOKSB7XG4gICAgaWYgKHggPT09IDAgfHwgeCA9PT0gTiAtIDEpIHJldHVybiB4O1xuXG4gICAgdmFyIHJiID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgcmIgfD0gKHggJiAxKSA8PCAobCAtIGkgLSAxKTtcbiAgICAgIHggPj49IDE7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJiO1xuICB9O1xuXG4gIC8vIFBlcmZvcm1zIFwidHdlZWRsaW5nXCIgcGhhc2UsIHRoZXJlZm9yZSAnZW11bGF0aW5nJ1xuICAvLyBiZWhhdmlvdXIgb2YgdGhlIHJlY3Vyc2l2ZSBhbGdvcml0aG1cbiAgRkZUTS5wcm90b3R5cGUucGVybXV0ZSA9IGZ1bmN0aW9uIHBlcm11dGUgKHJidCwgcndzLCBpd3MsIHJ0d3MsIGl0d3MsIE4pIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IE47IGkrKykge1xuICAgICAgcnR3c1tpXSA9IHJ3c1tyYnRbaV1dO1xuICAgICAgaXR3c1tpXSA9IGl3c1tyYnRbaV1dO1xuICAgIH1cbiAgfTtcblxuICBGRlRNLnByb3RvdHlwZS50cmFuc2Zvcm0gPSBmdW5jdGlvbiB0cmFuc2Zvcm0gKHJ3cywgaXdzLCBydHdzLCBpdHdzLCBOLCByYnQpIHtcbiAgICB0aGlzLnBlcm11dGUocmJ0LCByd3MsIGl3cywgcnR3cywgaXR3cywgTik7XG5cbiAgICBmb3IgKHZhciBzID0gMTsgcyA8IE47IHMgPDw9IDEpIHtcbiAgICAgIHZhciBsID0gcyA8PCAxO1xuXG4gICAgICB2YXIgcnR3ZGYgPSBNYXRoLmNvcygyICogTWF0aC5QSSAvIGwpO1xuICAgICAgdmFyIGl0d2RmID0gTWF0aC5zaW4oMiAqIE1hdGguUEkgLyBsKTtcblxuICAgICAgZm9yICh2YXIgcCA9IDA7IHAgPCBOOyBwICs9IGwpIHtcbiAgICAgICAgdmFyIHJ0d2RmXyA9IHJ0d2RmO1xuICAgICAgICB2YXIgaXR3ZGZfID0gaXR3ZGY7XG5cbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBzOyBqKyspIHtcbiAgICAgICAgICB2YXIgcmUgPSBydHdzW3AgKyBqXTtcbiAgICAgICAgICB2YXIgaWUgPSBpdHdzW3AgKyBqXTtcblxuICAgICAgICAgIHZhciBybyA9IHJ0d3NbcCArIGogKyBzXTtcbiAgICAgICAgICB2YXIgaW8gPSBpdHdzW3AgKyBqICsgc107XG5cbiAgICAgICAgICB2YXIgcnggPSBydHdkZl8gKiBybyAtIGl0d2RmXyAqIGlvO1xuXG4gICAgICAgICAgaW8gPSBydHdkZl8gKiBpbyArIGl0d2RmXyAqIHJvO1xuICAgICAgICAgIHJvID0gcng7XG5cbiAgICAgICAgICBydHdzW3AgKyBqXSA9IHJlICsgcm87XG4gICAgICAgICAgaXR3c1twICsgal0gPSBpZSArIGlvO1xuXG4gICAgICAgICAgcnR3c1twICsgaiArIHNdID0gcmUgLSBybztcbiAgICAgICAgICBpdHdzW3AgKyBqICsgc10gPSBpZSAtIGlvO1xuXG4gICAgICAgICAgLyoganNoaW50IG1heGRlcHRoIDogZmFsc2UgKi9cbiAgICAgICAgICBpZiAoaiAhPT0gbCkge1xuICAgICAgICAgICAgcnggPSBydHdkZiAqIHJ0d2RmXyAtIGl0d2RmICogaXR3ZGZfO1xuXG4gICAgICAgICAgICBpdHdkZl8gPSBydHdkZiAqIGl0d2RmXyArIGl0d2RmICogcnR3ZGZfO1xuICAgICAgICAgICAgcnR3ZGZfID0gcng7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIEZGVE0ucHJvdG90eXBlLmd1ZXNzTGVuMTNiID0gZnVuY3Rpb24gZ3Vlc3NMZW4xM2IgKG4sIG0pIHtcbiAgICB2YXIgTiA9IE1hdGgubWF4KG0sIG4pIHwgMTtcbiAgICB2YXIgb2RkID0gTiAmIDE7XG4gICAgdmFyIGkgPSAwO1xuICAgIGZvciAoTiA9IE4gLyAyIHwgMDsgTjsgTiA9IE4gPj4+IDEpIHtcbiAgICAgIGkrKztcbiAgICB9XG5cbiAgICByZXR1cm4gMSA8PCBpICsgMSArIG9kZDtcbiAgfTtcblxuICBGRlRNLnByb3RvdHlwZS5jb25qdWdhdGUgPSBmdW5jdGlvbiBjb25qdWdhdGUgKHJ3cywgaXdzLCBOKSB7XG4gICAgaWYgKE4gPD0gMSkgcmV0dXJuO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBOIC8gMjsgaSsrKSB7XG4gICAgICB2YXIgdCA9IHJ3c1tpXTtcblxuICAgICAgcndzW2ldID0gcndzW04gLSBpIC0gMV07XG4gICAgICByd3NbTiAtIGkgLSAxXSA9IHQ7XG5cbiAgICAgIHQgPSBpd3NbaV07XG5cbiAgICAgIGl3c1tpXSA9IC1pd3NbTiAtIGkgLSAxXTtcbiAgICAgIGl3c1tOIC0gaSAtIDFdID0gLXQ7XG4gICAgfVxuICB9O1xuXG4gIEZGVE0ucHJvdG90eXBlLm5vcm1hbGl6ZTEzYiA9IGZ1bmN0aW9uIG5vcm1hbGl6ZTEzYiAod3MsIE4pIHtcbiAgICB2YXIgY2FycnkgPSAwO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgTiAvIDI7IGkrKykge1xuICAgICAgdmFyIHcgPSBNYXRoLnJvdW5kKHdzWzIgKiBpICsgMV0gLyBOKSAqIDB4MjAwMCArXG4gICAgICAgIE1hdGgucm91bmQod3NbMiAqIGldIC8gTikgK1xuICAgICAgICBjYXJyeTtcblxuICAgICAgd3NbaV0gPSB3ICYgMHgzZmZmZmZmO1xuXG4gICAgICBpZiAodyA8IDB4NDAwMDAwMCkge1xuICAgICAgICBjYXJyeSA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYXJyeSA9IHcgLyAweDQwMDAwMDAgfCAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB3cztcbiAgfTtcblxuICBGRlRNLnByb3RvdHlwZS5jb252ZXJ0MTNiID0gZnVuY3Rpb24gY29udmVydDEzYiAod3MsIGxlbiwgcndzLCBOKSB7XG4gICAgdmFyIGNhcnJ5ID0gMDtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBjYXJyeSA9IGNhcnJ5ICsgKHdzW2ldIHwgMCk7XG5cbiAgICAgIHJ3c1syICogaV0gPSBjYXJyeSAmIDB4MWZmZjsgY2FycnkgPSBjYXJyeSA+Pj4gMTM7XG4gICAgICByd3NbMiAqIGkgKyAxXSA9IGNhcnJ5ICYgMHgxZmZmOyBjYXJyeSA9IGNhcnJ5ID4+PiAxMztcbiAgICB9XG5cbiAgICAvLyBQYWQgd2l0aCB6ZXJvZXNcbiAgICBmb3IgKGkgPSAyICogbGVuOyBpIDwgTjsgKytpKSB7XG4gICAgICByd3NbaV0gPSAwO1xuICAgIH1cblxuICAgIGFzc2VydChjYXJyeSA9PT0gMCk7XG4gICAgYXNzZXJ0KChjYXJyeSAmIH4weDFmZmYpID09PSAwKTtcbiAgfTtcblxuICBGRlRNLnByb3RvdHlwZS5zdHViID0gZnVuY3Rpb24gc3R1YiAoTikge1xuICAgIHZhciBwaCA9IG5ldyBBcnJheShOKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IE47IGkrKykge1xuICAgICAgcGhbaV0gPSAwO1xuICAgIH1cblxuICAgIHJldHVybiBwaDtcbiAgfTtcblxuICBGRlRNLnByb3RvdHlwZS5tdWxwID0gZnVuY3Rpb24gbXVscCAoeCwgeSwgb3V0KSB7XG4gICAgdmFyIE4gPSAyICogdGhpcy5ndWVzc0xlbjEzYih4Lmxlbmd0aCwgeS5sZW5ndGgpO1xuXG4gICAgdmFyIHJidCA9IHRoaXMubWFrZVJCVChOKTtcblxuICAgIHZhciBfID0gdGhpcy5zdHViKE4pO1xuXG4gICAgdmFyIHJ3cyA9IG5ldyBBcnJheShOKTtcbiAgICB2YXIgcndzdCA9IG5ldyBBcnJheShOKTtcbiAgICB2YXIgaXdzdCA9IG5ldyBBcnJheShOKTtcblxuICAgIHZhciBucndzID0gbmV3IEFycmF5KE4pO1xuICAgIHZhciBucndzdCA9IG5ldyBBcnJheShOKTtcbiAgICB2YXIgbml3c3QgPSBuZXcgQXJyYXkoTik7XG5cbiAgICB2YXIgcm13cyA9IG91dC53b3JkcztcbiAgICBybXdzLmxlbmd0aCA9IE47XG5cbiAgICB0aGlzLmNvbnZlcnQxM2IoeC53b3JkcywgeC5sZW5ndGgsIHJ3cywgTik7XG4gICAgdGhpcy5jb252ZXJ0MTNiKHkud29yZHMsIHkubGVuZ3RoLCBucndzLCBOKTtcblxuICAgIHRoaXMudHJhbnNmb3JtKHJ3cywgXywgcndzdCwgaXdzdCwgTiwgcmJ0KTtcbiAgICB0aGlzLnRyYW5zZm9ybShucndzLCBfLCBucndzdCwgbml3c3QsIE4sIHJidCk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IE47IGkrKykge1xuICAgICAgdmFyIHJ4ID0gcndzdFtpXSAqIG5yd3N0W2ldIC0gaXdzdFtpXSAqIG5pd3N0W2ldO1xuICAgICAgaXdzdFtpXSA9IHJ3c3RbaV0gKiBuaXdzdFtpXSArIGl3c3RbaV0gKiBucndzdFtpXTtcbiAgICAgIHJ3c3RbaV0gPSByeDtcbiAgICB9XG5cbiAgICB0aGlzLmNvbmp1Z2F0ZShyd3N0LCBpd3N0LCBOKTtcbiAgICB0aGlzLnRyYW5zZm9ybShyd3N0LCBpd3N0LCBybXdzLCBfLCBOLCByYnQpO1xuICAgIHRoaXMuY29uanVnYXRlKHJtd3MsIF8sIE4pO1xuICAgIHRoaXMubm9ybWFsaXplMTNiKHJtd3MsIE4pO1xuXG4gICAgb3V0Lm5lZ2F0aXZlID0geC5uZWdhdGl2ZSBeIHkubmVnYXRpdmU7XG4gICAgb3V0Lmxlbmd0aCA9IHgubGVuZ3RoICsgeS5sZW5ndGg7XG4gICAgcmV0dXJuIG91dC5zdHJpcCgpO1xuICB9O1xuXG4gIC8vIE11bHRpcGx5IGB0aGlzYCBieSBgbnVtYFxuICBCTi5wcm90b3R5cGUubXVsID0gZnVuY3Rpb24gbXVsIChudW0pIHtcbiAgICB2YXIgb3V0ID0gbmV3IEJOKG51bGwpO1xuICAgIG91dC53b3JkcyA9IG5ldyBBcnJheSh0aGlzLmxlbmd0aCArIG51bS5sZW5ndGgpO1xuICAgIHJldHVybiB0aGlzLm11bFRvKG51bSwgb3V0KTtcbiAgfTtcblxuICAvLyBNdWx0aXBseSBlbXBsb3lpbmcgRkZUXG4gIEJOLnByb3RvdHlwZS5tdWxmID0gZnVuY3Rpb24gbXVsZiAobnVtKSB7XG4gICAgdmFyIG91dCA9IG5ldyBCTihudWxsKTtcbiAgICBvdXQud29yZHMgPSBuZXcgQXJyYXkodGhpcy5sZW5ndGggKyBudW0ubGVuZ3RoKTtcbiAgICByZXR1cm4ganVtYm9NdWxUbyh0aGlzLCBudW0sIG91dCk7XG4gIH07XG5cbiAgLy8gSW4tcGxhY2UgTXVsdGlwbGljYXRpb25cbiAgQk4ucHJvdG90eXBlLmltdWwgPSBmdW5jdGlvbiBpbXVsIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpLm11bFRvKG51bSwgdGhpcyk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmltdWxuID0gZnVuY3Rpb24gaW11bG4gKG51bSkge1xuICAgIGFzc2VydCh0eXBlb2YgbnVtID09PSAnbnVtYmVyJyk7XG4gICAgYXNzZXJ0KG51bSA8IDB4NDAwMDAwMCk7XG5cbiAgICAvLyBDYXJyeVxuICAgIHZhciBjYXJyeSA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgdyA9ICh0aGlzLndvcmRzW2ldIHwgMCkgKiBudW07XG4gICAgICB2YXIgbG8gPSAodyAmIDB4M2ZmZmZmZikgKyAoY2FycnkgJiAweDNmZmZmZmYpO1xuICAgICAgY2FycnkgPj49IDI2O1xuICAgICAgY2FycnkgKz0gKHcgLyAweDQwMDAwMDApIHwgMDtcbiAgICAgIC8vIE5PVEU6IGxvIGlzIDI3Yml0IG1heGltdW1cbiAgICAgIGNhcnJ5ICs9IGxvID4+PiAyNjtcbiAgICAgIHRoaXMud29yZHNbaV0gPSBsbyAmIDB4M2ZmZmZmZjtcbiAgICB9XG5cbiAgICBpZiAoY2FycnkgIT09IDApIHtcbiAgICAgIHRoaXMud29yZHNbaV0gPSBjYXJyeTtcbiAgICAgIHRoaXMubGVuZ3RoKys7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLm11bG4gPSBmdW5jdGlvbiBtdWxuIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmltdWxuKG51bSk7XG4gIH07XG5cbiAgLy8gYHRoaXNgICogYHRoaXNgXG4gIEJOLnByb3RvdHlwZS5zcXIgPSBmdW5jdGlvbiBzcXIgKCkge1xuICAgIHJldHVybiB0aGlzLm11bCh0aGlzKTtcbiAgfTtcblxuICAvLyBgdGhpc2AgKiBgdGhpc2AgaW4tcGxhY2VcbiAgQk4ucHJvdG90eXBlLmlzcXIgPSBmdW5jdGlvbiBpc3FyICgpIHtcbiAgICByZXR1cm4gdGhpcy5pbXVsKHRoaXMuY2xvbmUoKSk7XG4gIH07XG5cbiAgLy8gTWF0aC5wb3coYHRoaXNgLCBgbnVtYClcbiAgQk4ucHJvdG90eXBlLnBvdyA9IGZ1bmN0aW9uIHBvdyAobnVtKSB7XG4gICAgdmFyIHcgPSB0b0JpdEFycmF5KG51bSk7XG4gICAgaWYgKHcubGVuZ3RoID09PSAwKSByZXR1cm4gbmV3IEJOKDEpO1xuXG4gICAgLy8gU2tpcCBsZWFkaW5nIHplcm9lc1xuICAgIHZhciByZXMgPSB0aGlzO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdy5sZW5ndGg7IGkrKywgcmVzID0gcmVzLnNxcigpKSB7XG4gICAgICBpZiAod1tpXSAhPT0gMCkgYnJlYWs7XG4gICAgfVxuXG4gICAgaWYgKCsraSA8IHcubGVuZ3RoKSB7XG4gICAgICBmb3IgKHZhciBxID0gcmVzLnNxcigpOyBpIDwgdy5sZW5ndGg7IGkrKywgcSA9IHEuc3FyKCkpIHtcbiAgICAgICAgaWYgKHdbaV0gPT09IDApIGNvbnRpbnVlO1xuXG4gICAgICAgIHJlcyA9IHJlcy5tdWwocSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcztcbiAgfTtcblxuICAvLyBTaGlmdC1sZWZ0IGluLXBsYWNlXG4gIEJOLnByb3RvdHlwZS5pdXNobG4gPSBmdW5jdGlvbiBpdXNobG4gKGJpdHMpIHtcbiAgICBhc3NlcnQodHlwZW9mIGJpdHMgPT09ICdudW1iZXInICYmIGJpdHMgPj0gMCk7XG4gICAgdmFyIHIgPSBiaXRzICUgMjY7XG4gICAgdmFyIHMgPSAoYml0cyAtIHIpIC8gMjY7XG4gICAgdmFyIGNhcnJ5TWFzayA9ICgweDNmZmZmZmYgPj4+ICgyNiAtIHIpKSA8PCAoMjYgLSByKTtcbiAgICB2YXIgaTtcblxuICAgIGlmIChyICE9PSAwKSB7XG4gICAgICB2YXIgY2FycnkgPSAwO1xuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbmV3Q2FycnkgPSB0aGlzLndvcmRzW2ldICYgY2FycnlNYXNrO1xuICAgICAgICB2YXIgYyA9ICgodGhpcy53b3Jkc1tpXSB8IDApIC0gbmV3Q2FycnkpIDw8IHI7XG4gICAgICAgIHRoaXMud29yZHNbaV0gPSBjIHwgY2Fycnk7XG4gICAgICAgIGNhcnJ5ID0gbmV3Q2FycnkgPj4+ICgyNiAtIHIpO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2FycnkpIHtcbiAgICAgICAgdGhpcy53b3Jkc1tpXSA9IGNhcnJ5O1xuICAgICAgICB0aGlzLmxlbmd0aCsrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzICE9PSAwKSB7XG4gICAgICBmb3IgKGkgPSB0aGlzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHRoaXMud29yZHNbaSArIHNdID0gdGhpcy53b3Jkc1tpXTtcbiAgICAgIH1cblxuICAgICAgZm9yIChpID0gMDsgaSA8IHM7IGkrKykge1xuICAgICAgICB0aGlzLndvcmRzW2ldID0gMDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5sZW5ndGggKz0gcztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5pc2hsbiA9IGZ1bmN0aW9uIGlzaGxuIChiaXRzKSB7XG4gICAgLy8gVE9ETyhpbmR1dG55KTogaW1wbGVtZW50IG1lXG4gICAgYXNzZXJ0KHRoaXMubmVnYXRpdmUgPT09IDApO1xuICAgIHJldHVybiB0aGlzLml1c2hsbihiaXRzKTtcbiAgfTtcblxuICAvLyBTaGlmdC1yaWdodCBpbi1wbGFjZVxuICAvLyBOT1RFOiBgaGludGAgaXMgYSBsb3dlc3QgYml0IGJlZm9yZSB0cmFpbGluZyB6ZXJvZXNcbiAgLy8gTk9URTogaWYgYGV4dGVuZGVkYCBpcyBwcmVzZW50IC0gaXQgd2lsbCBiZSBmaWxsZWQgd2l0aCBkZXN0cm95ZWQgYml0c1xuICBCTi5wcm90b3R5cGUuaXVzaHJuID0gZnVuY3Rpb24gaXVzaHJuIChiaXRzLCBoaW50LCBleHRlbmRlZCkge1xuICAgIGFzc2VydCh0eXBlb2YgYml0cyA9PT0gJ251bWJlcicgJiYgYml0cyA+PSAwKTtcbiAgICB2YXIgaDtcbiAgICBpZiAoaGludCkge1xuICAgICAgaCA9IChoaW50IC0gKGhpbnQgJSAyNikpIC8gMjY7XG4gICAgfSBlbHNlIHtcbiAgICAgIGggPSAwO1xuICAgIH1cblxuICAgIHZhciByID0gYml0cyAlIDI2O1xuICAgIHZhciBzID0gTWF0aC5taW4oKGJpdHMgLSByKSAvIDI2LCB0aGlzLmxlbmd0aCk7XG4gICAgdmFyIG1hc2sgPSAweDNmZmZmZmYgXiAoKDB4M2ZmZmZmZiA+Pj4gcikgPDwgcik7XG4gICAgdmFyIG1hc2tlZFdvcmRzID0gZXh0ZW5kZWQ7XG5cbiAgICBoIC09IHM7XG4gICAgaCA9IE1hdGgubWF4KDAsIGgpO1xuXG4gICAgLy8gRXh0ZW5kZWQgbW9kZSwgY29weSBtYXNrZWQgcGFydFxuICAgIGlmIChtYXNrZWRXb3Jkcykge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzOyBpKyspIHtcbiAgICAgICAgbWFza2VkV29yZHMud29yZHNbaV0gPSB0aGlzLndvcmRzW2ldO1xuICAgICAgfVxuICAgICAgbWFza2VkV29yZHMubGVuZ3RoID0gcztcbiAgICB9XG5cbiAgICBpZiAocyA9PT0gMCkge1xuICAgICAgLy8gTm8tb3AsIHdlIHNob3VsZCBub3QgbW92ZSBhbnl0aGluZyBhdCBhbGxcbiAgICB9IGVsc2UgaWYgKHRoaXMubGVuZ3RoID4gcykge1xuICAgICAgdGhpcy5sZW5ndGggLT0gcztcbiAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMud29yZHNbaV0gPSB0aGlzLndvcmRzW2kgKyBzXTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy53b3Jkc1swXSA9IDA7XG4gICAgICB0aGlzLmxlbmd0aCA9IDE7XG4gICAgfVxuXG4gICAgdmFyIGNhcnJ5ID0gMDtcbiAgICBmb3IgKGkgPSB0aGlzLmxlbmd0aCAtIDE7IGkgPj0gMCAmJiAoY2FycnkgIT09IDAgfHwgaSA+PSBoKTsgaS0tKSB7XG4gICAgICB2YXIgd29yZCA9IHRoaXMud29yZHNbaV0gfCAwO1xuICAgICAgdGhpcy53b3Jkc1tpXSA9IChjYXJyeSA8PCAoMjYgLSByKSkgfCAod29yZCA+Pj4gcik7XG4gICAgICBjYXJyeSA9IHdvcmQgJiBtYXNrO1xuICAgIH1cblxuICAgIC8vIFB1c2ggY2FycmllZCBiaXRzIGFzIGEgbWFza1xuICAgIGlmIChtYXNrZWRXb3JkcyAmJiBjYXJyeSAhPT0gMCkge1xuICAgICAgbWFza2VkV29yZHMud29yZHNbbWFza2VkV29yZHMubGVuZ3RoKytdID0gY2Fycnk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLndvcmRzWzBdID0gMDtcbiAgICAgIHRoaXMubGVuZ3RoID0gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5pc2hybiA9IGZ1bmN0aW9uIGlzaHJuIChiaXRzLCBoaW50LCBleHRlbmRlZCkge1xuICAgIC8vIFRPRE8oaW5kdXRueSk6IGltcGxlbWVudCBtZVxuICAgIGFzc2VydCh0aGlzLm5lZ2F0aXZlID09PSAwKTtcbiAgICByZXR1cm4gdGhpcy5pdXNocm4oYml0cywgaGludCwgZXh0ZW5kZWQpO1xuICB9O1xuXG4gIC8vIFNoaWZ0LWxlZnRcbiAgQk4ucHJvdG90eXBlLnNobG4gPSBmdW5jdGlvbiBzaGxuIChiaXRzKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5pc2hsbihiaXRzKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUudXNobG4gPSBmdW5jdGlvbiB1c2hsbiAoYml0cykge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaXVzaGxuKGJpdHMpO1xuICB9O1xuXG4gIC8vIFNoaWZ0LXJpZ2h0XG4gIEJOLnByb3RvdHlwZS5zaHJuID0gZnVuY3Rpb24gc2hybiAoYml0cykge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaXNocm4oYml0cyk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnVzaHJuID0gZnVuY3Rpb24gdXNocm4gKGJpdHMpIHtcbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpLml1c2hybihiaXRzKTtcbiAgfTtcblxuICAvLyBUZXN0IGlmIG4gYml0IGlzIHNldFxuICBCTi5wcm90b3R5cGUudGVzdG4gPSBmdW5jdGlvbiB0ZXN0biAoYml0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBiaXQgPT09ICdudW1iZXInICYmIGJpdCA+PSAwKTtcbiAgICB2YXIgciA9IGJpdCAlIDI2O1xuICAgIHZhciBzID0gKGJpdCAtIHIpIC8gMjY7XG4gICAgdmFyIHEgPSAxIDw8IHI7XG5cbiAgICAvLyBGYXN0IGNhc2U6IGJpdCBpcyBtdWNoIGhpZ2hlciB0aGFuIGFsbCBleGlzdGluZyB3b3Jkc1xuICAgIGlmICh0aGlzLmxlbmd0aCA8PSBzKSByZXR1cm4gZmFsc2U7XG5cbiAgICAvLyBDaGVjayBiaXQgYW5kIHJldHVyblxuICAgIHZhciB3ID0gdGhpcy53b3Jkc1tzXTtcblxuICAgIHJldHVybiAhISh3ICYgcSk7XG4gIH07XG5cbiAgLy8gUmV0dXJuIG9ubHkgbG93ZXJzIGJpdHMgb2YgbnVtYmVyIChpbi1wbGFjZSlcbiAgQk4ucHJvdG90eXBlLmltYXNrbiA9IGZ1bmN0aW9uIGltYXNrbiAoYml0cykge1xuICAgIGFzc2VydCh0eXBlb2YgYml0cyA9PT0gJ251bWJlcicgJiYgYml0cyA+PSAwKTtcbiAgICB2YXIgciA9IGJpdHMgJSAyNjtcbiAgICB2YXIgcyA9IChiaXRzIC0gcikgLyAyNjtcblxuICAgIGFzc2VydCh0aGlzLm5lZ2F0aXZlID09PSAwLCAnaW1hc2tuIHdvcmtzIG9ubHkgd2l0aCBwb3NpdGl2ZSBudW1iZXJzJyk7XG5cbiAgICBpZiAodGhpcy5sZW5ndGggPD0gcykge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgaWYgKHIgIT09IDApIHtcbiAgICAgIHMrKztcbiAgICB9XG4gICAgdGhpcy5sZW5ndGggPSBNYXRoLm1pbihzLCB0aGlzLmxlbmd0aCk7XG5cbiAgICBpZiAociAhPT0gMCkge1xuICAgICAgdmFyIG1hc2sgPSAweDNmZmZmZmYgXiAoKDB4M2ZmZmZmZiA+Pj4gcikgPDwgcik7XG4gICAgICB0aGlzLndvcmRzW3RoaXMubGVuZ3RoIC0gMV0gJj0gbWFzaztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIC8vIFJldHVybiBvbmx5IGxvd2VycyBiaXRzIG9mIG51bWJlclxuICBCTi5wcm90b3R5cGUubWFza24gPSBmdW5jdGlvbiBtYXNrbiAoYml0cykge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaW1hc2tuKGJpdHMpO1xuICB9O1xuXG4gIC8vIEFkZCBwbGFpbiBudW1iZXIgYG51bWAgdG8gYHRoaXNgXG4gIEJOLnByb3RvdHlwZS5pYWRkbiA9IGZ1bmN0aW9uIGlhZGRuIChudW0pIHtcbiAgICBhc3NlcnQodHlwZW9mIG51bSA9PT0gJ251bWJlcicpO1xuICAgIGFzc2VydChudW0gPCAweDQwMDAwMDApO1xuICAgIGlmIChudW0gPCAwKSByZXR1cm4gdGhpcy5pc3VibigtbnVtKTtcblxuICAgIC8vIFBvc3NpYmxlIHNpZ24gY2hhbmdlXG4gICAgaWYgKHRoaXMubmVnYXRpdmUgIT09IDApIHtcbiAgICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMSAmJiAodGhpcy53b3Jkc1swXSB8IDApIDwgbnVtKSB7XG4gICAgICAgIHRoaXMud29yZHNbMF0gPSBudW0gLSAodGhpcy53b3Jkc1swXSB8IDApO1xuICAgICAgICB0aGlzLm5lZ2F0aXZlID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubmVnYXRpdmUgPSAwO1xuICAgICAgdGhpcy5pc3VibihudW0pO1xuICAgICAgdGhpcy5uZWdhdGl2ZSA9IDE7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyBBZGQgd2l0aG91dCBjaGVja3NcbiAgICByZXR1cm4gdGhpcy5faWFkZG4obnVtKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuX2lhZGRuID0gZnVuY3Rpb24gX2lhZGRuIChudW0pIHtcbiAgICB0aGlzLndvcmRzWzBdICs9IG51bTtcblxuICAgIC8vIENhcnJ5XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aCAmJiB0aGlzLndvcmRzW2ldID49IDB4NDAwMDAwMDsgaSsrKSB7XG4gICAgICB0aGlzLndvcmRzW2ldIC09IDB4NDAwMDAwMDtcbiAgICAgIGlmIChpID09PSB0aGlzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgdGhpcy53b3Jkc1tpICsgMV0gPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy53b3Jkc1tpICsgMV0rKztcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5sZW5ndGggPSBNYXRoLm1heCh0aGlzLmxlbmd0aCwgaSArIDEpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLy8gU3VidHJhY3QgcGxhaW4gbnVtYmVyIGBudW1gIGZyb20gYHRoaXNgXG4gIEJOLnByb3RvdHlwZS5pc3VibiA9IGZ1bmN0aW9uIGlzdWJuIChudW0pIHtcbiAgICBhc3NlcnQodHlwZW9mIG51bSA9PT0gJ251bWJlcicpO1xuICAgIGFzc2VydChudW0gPCAweDQwMDAwMDApO1xuICAgIGlmIChudW0gPCAwKSByZXR1cm4gdGhpcy5pYWRkbigtbnVtKTtcblxuICAgIGlmICh0aGlzLm5lZ2F0aXZlICE9PSAwKSB7XG4gICAgICB0aGlzLm5lZ2F0aXZlID0gMDtcbiAgICAgIHRoaXMuaWFkZG4obnVtKTtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAxO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdGhpcy53b3Jkc1swXSAtPSBudW07XG5cbiAgICBpZiAodGhpcy5sZW5ndGggPT09IDEgJiYgdGhpcy53b3Jkc1swXSA8IDApIHtcbiAgICAgIHRoaXMud29yZHNbMF0gPSAtdGhpcy53b3Jkc1swXTtcbiAgICAgIHRoaXMubmVnYXRpdmUgPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDYXJyeVxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aCAmJiB0aGlzLndvcmRzW2ldIDwgMDsgaSsrKSB7XG4gICAgICAgIHRoaXMud29yZHNbaV0gKz0gMHg0MDAwMDAwO1xuICAgICAgICB0aGlzLndvcmRzW2kgKyAxXSAtPSAxO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmFkZG4gPSBmdW5jdGlvbiBhZGRuIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmlhZGRuKG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnN1Ym4gPSBmdW5jdGlvbiBzdWJuIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmlzdWJuKG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmlhYnMgPSBmdW5jdGlvbiBpYWJzICgpIHtcbiAgICB0aGlzLm5lZ2F0aXZlID0gMDtcblxuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5hYnMgPSBmdW5jdGlvbiBhYnMgKCkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkuaWFicygpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5faXNobG5zdWJtdWwgPSBmdW5jdGlvbiBfaXNobG5zdWJtdWwgKG51bSwgbXVsLCBzaGlmdCkge1xuICAgIHZhciBsZW4gPSBudW0ubGVuZ3RoICsgc2hpZnQ7XG4gICAgdmFyIGk7XG5cbiAgICB0aGlzLl9leHBhbmQobGVuKTtcblxuICAgIHZhciB3O1xuICAgIHZhciBjYXJyeSA9IDA7XG4gICAgZm9yIChpID0gMDsgaSA8IG51bS5sZW5ndGg7IGkrKykge1xuICAgICAgdyA9ICh0aGlzLndvcmRzW2kgKyBzaGlmdF0gfCAwKSArIGNhcnJ5O1xuICAgICAgdmFyIHJpZ2h0ID0gKG51bS53b3Jkc1tpXSB8IDApICogbXVsO1xuICAgICAgdyAtPSByaWdodCAmIDB4M2ZmZmZmZjtcbiAgICAgIGNhcnJ5ID0gKHcgPj4gMjYpIC0gKChyaWdodCAvIDB4NDAwMDAwMCkgfCAwKTtcbiAgICAgIHRoaXMud29yZHNbaSArIHNoaWZ0XSA9IHcgJiAweDNmZmZmZmY7XG4gICAgfVxuICAgIGZvciAoOyBpIDwgdGhpcy5sZW5ndGggLSBzaGlmdDsgaSsrKSB7XG4gICAgICB3ID0gKHRoaXMud29yZHNbaSArIHNoaWZ0XSB8IDApICsgY2Fycnk7XG4gICAgICBjYXJyeSA9IHcgPj4gMjY7XG4gICAgICB0aGlzLndvcmRzW2kgKyBzaGlmdF0gPSB3ICYgMHgzZmZmZmZmO1xuICAgIH1cblxuICAgIGlmIChjYXJyeSA9PT0gMCkgcmV0dXJuIHRoaXMuc3RyaXAoKTtcblxuICAgIC8vIFN1YnRyYWN0aW9uIG92ZXJmbG93XG4gICAgYXNzZXJ0KGNhcnJ5ID09PSAtMSk7XG4gICAgY2FycnkgPSAwO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB3ID0gLSh0aGlzLndvcmRzW2ldIHwgMCkgKyBjYXJyeTtcbiAgICAgIGNhcnJ5ID0gdyA+PiAyNjtcbiAgICAgIHRoaXMud29yZHNbaV0gPSB3ICYgMHgzZmZmZmZmO1xuICAgIH1cbiAgICB0aGlzLm5lZ2F0aXZlID0gMTtcblxuICAgIHJldHVybiB0aGlzLnN0cmlwKCk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLl93b3JkRGl2ID0gZnVuY3Rpb24gX3dvcmREaXYgKG51bSwgbW9kZSkge1xuICAgIHZhciBzaGlmdCA9IHRoaXMubGVuZ3RoIC0gbnVtLmxlbmd0aDtcblxuICAgIHZhciBhID0gdGhpcy5jbG9uZSgpO1xuICAgIHZhciBiID0gbnVtO1xuXG4gICAgLy8gTm9ybWFsaXplXG4gICAgdmFyIGJoaSA9IGIud29yZHNbYi5sZW5ndGggLSAxXSB8IDA7XG4gICAgdmFyIGJoaUJpdHMgPSB0aGlzLl9jb3VudEJpdHMoYmhpKTtcbiAgICBzaGlmdCA9IDI2IC0gYmhpQml0cztcbiAgICBpZiAoc2hpZnQgIT09IDApIHtcbiAgICAgIGIgPSBiLnVzaGxuKHNoaWZ0KTtcbiAgICAgIGEuaXVzaGxuKHNoaWZ0KTtcbiAgICAgIGJoaSA9IGIud29yZHNbYi5sZW5ndGggLSAxXSB8IDA7XG4gICAgfVxuXG4gICAgLy8gSW5pdGlhbGl6ZSBxdW90aWVudFxuICAgIHZhciBtID0gYS5sZW5ndGggLSBiLmxlbmd0aDtcbiAgICB2YXIgcTtcblxuICAgIGlmIChtb2RlICE9PSAnbW9kJykge1xuICAgICAgcSA9IG5ldyBCTihudWxsKTtcbiAgICAgIHEubGVuZ3RoID0gbSArIDE7XG4gICAgICBxLndvcmRzID0gbmV3IEFycmF5KHEubGVuZ3RoKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcS5sZW5ndGg7IGkrKykge1xuICAgICAgICBxLndvcmRzW2ldID0gMDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZGlmZiA9IGEuY2xvbmUoKS5faXNobG5zdWJtdWwoYiwgMSwgbSk7XG4gICAgaWYgKGRpZmYubmVnYXRpdmUgPT09IDApIHtcbiAgICAgIGEgPSBkaWZmO1xuICAgICAgaWYgKHEpIHtcbiAgICAgICAgcS53b3Jkc1ttXSA9IDE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaiA9IG0gLSAxOyBqID49IDA7IGotLSkge1xuICAgICAgdmFyIHFqID0gKGEud29yZHNbYi5sZW5ndGggKyBqXSB8IDApICogMHg0MDAwMDAwICtcbiAgICAgICAgKGEud29yZHNbYi5sZW5ndGggKyBqIC0gMV0gfCAwKTtcblxuICAgICAgLy8gTk9URTogKHFqIC8gYmhpKSBpcyAoMHgzZmZmZmZmICogMHg0MDAwMDAwICsgMHgzZmZmZmZmKSAvIDB4MjAwMDAwMCBtYXhcbiAgICAgIC8vICgweDdmZmZmZmYpXG4gICAgICBxaiA9IE1hdGgubWluKChxaiAvIGJoaSkgfCAwLCAweDNmZmZmZmYpO1xuXG4gICAgICBhLl9pc2hsbnN1Ym11bChiLCBxaiwgaik7XG4gICAgICB3aGlsZSAoYS5uZWdhdGl2ZSAhPT0gMCkge1xuICAgICAgICBxai0tO1xuICAgICAgICBhLm5lZ2F0aXZlID0gMDtcbiAgICAgICAgYS5faXNobG5zdWJtdWwoYiwgMSwgaik7XG4gICAgICAgIGlmICghYS5pc1plcm8oKSkge1xuICAgICAgICAgIGEubmVnYXRpdmUgXj0gMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHEpIHtcbiAgICAgICAgcS53b3Jkc1tqXSA9IHFqO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocSkge1xuICAgICAgcS5zdHJpcCgpO1xuICAgIH1cbiAgICBhLnN0cmlwKCk7XG5cbiAgICAvLyBEZW5vcm1hbGl6ZVxuICAgIGlmIChtb2RlICE9PSAnZGl2JyAmJiBzaGlmdCAhPT0gMCkge1xuICAgICAgYS5pdXNocm4oc2hpZnQpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkaXY6IHEgfHwgbnVsbCxcbiAgICAgIG1vZDogYVxuICAgIH07XG4gIH07XG5cbiAgLy8gTk9URTogMSkgYG1vZGVgIGNhbiBiZSBzZXQgdG8gYG1vZGAgdG8gcmVxdWVzdCBtb2Qgb25seSxcbiAgLy8gICAgICAgdG8gYGRpdmAgdG8gcmVxdWVzdCBkaXYgb25seSwgb3IgYmUgYWJzZW50IHRvXG4gIC8vICAgICAgIHJlcXVlc3QgYm90aCBkaXYgJiBtb2RcbiAgLy8gICAgICAgMikgYHBvc2l0aXZlYCBpcyB0cnVlIGlmIHVuc2lnbmVkIG1vZCBpcyByZXF1ZXN0ZWRcbiAgQk4ucHJvdG90eXBlLmRpdm1vZCA9IGZ1bmN0aW9uIGRpdm1vZCAobnVtLCBtb2RlLCBwb3NpdGl2ZSkge1xuICAgIGFzc2VydCghbnVtLmlzWmVybygpKTtcblxuICAgIGlmICh0aGlzLmlzWmVybygpKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkaXY6IG5ldyBCTigwKSxcbiAgICAgICAgbW9kOiBuZXcgQk4oMClcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGRpdiwgbW9kLCByZXM7XG4gICAgaWYgKHRoaXMubmVnYXRpdmUgIT09IDAgJiYgbnVtLm5lZ2F0aXZlID09PSAwKSB7XG4gICAgICByZXMgPSB0aGlzLm5lZygpLmRpdm1vZChudW0sIG1vZGUpO1xuXG4gICAgICBpZiAobW9kZSAhPT0gJ21vZCcpIHtcbiAgICAgICAgZGl2ID0gcmVzLmRpdi5uZWcoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1vZGUgIT09ICdkaXYnKSB7XG4gICAgICAgIG1vZCA9IHJlcy5tb2QubmVnKCk7XG4gICAgICAgIGlmIChwb3NpdGl2ZSAmJiBtb2QubmVnYXRpdmUgIT09IDApIHtcbiAgICAgICAgICBtb2QuaWFkZChudW0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRpdjogZGl2LFxuICAgICAgICBtb2Q6IG1vZFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5uZWdhdGl2ZSA9PT0gMCAmJiBudW0ubmVnYXRpdmUgIT09IDApIHtcbiAgICAgIHJlcyA9IHRoaXMuZGl2bW9kKG51bS5uZWcoKSwgbW9kZSk7XG5cbiAgICAgIGlmIChtb2RlICE9PSAnbW9kJykge1xuICAgICAgICBkaXYgPSByZXMuZGl2Lm5lZygpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBkaXY6IGRpdixcbiAgICAgICAgbW9kOiByZXMubW9kXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmICgodGhpcy5uZWdhdGl2ZSAmIG51bS5uZWdhdGl2ZSkgIT09IDApIHtcbiAgICAgIHJlcyA9IHRoaXMubmVnKCkuZGl2bW9kKG51bS5uZWcoKSwgbW9kZSk7XG5cbiAgICAgIGlmIChtb2RlICE9PSAnZGl2Jykge1xuICAgICAgICBtb2QgPSByZXMubW9kLm5lZygpO1xuICAgICAgICBpZiAocG9zaXRpdmUgJiYgbW9kLm5lZ2F0aXZlICE9PSAwKSB7XG4gICAgICAgICAgbW9kLmlzdWIobnVtKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBkaXY6IHJlcy5kaXYsXG4gICAgICAgIG1vZDogbW9kXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEJvdGggbnVtYmVycyBhcmUgcG9zaXRpdmUgYXQgdGhpcyBwb2ludFxuXG4gICAgLy8gU3RyaXAgYm90aCBudW1iZXJzIHRvIGFwcHJveGltYXRlIHNoaWZ0IHZhbHVlXG4gICAgaWYgKG51bS5sZW5ndGggPiB0aGlzLmxlbmd0aCB8fCB0aGlzLmNtcChudW0pIDwgMCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZGl2OiBuZXcgQk4oMCksXG4gICAgICAgIG1vZDogdGhpc1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBWZXJ5IHNob3J0IHJlZHVjdGlvblxuICAgIGlmIChudW0ubGVuZ3RoID09PSAxKSB7XG4gICAgICBpZiAobW9kZSA9PT0gJ2RpdicpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBkaXY6IHRoaXMuZGl2bihudW0ud29yZHNbMF0pLFxuICAgICAgICAgIG1vZDogbnVsbFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBpZiAobW9kZSA9PT0gJ21vZCcpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBkaXY6IG51bGwsXG4gICAgICAgICAgbW9kOiBuZXcgQk4odGhpcy5tb2RuKG51bS53b3Jkc1swXSkpXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRpdjogdGhpcy5kaXZuKG51bS53b3Jkc1swXSksXG4gICAgICAgIG1vZDogbmV3IEJOKHRoaXMubW9kbihudW0ud29yZHNbMF0pKVxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fd29yZERpdihudW0sIG1vZGUpO1xuICB9O1xuXG4gIC8vIEZpbmQgYHRoaXNgIC8gYG51bWBcbiAgQk4ucHJvdG90eXBlLmRpdiA9IGZ1bmN0aW9uIGRpdiAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuZGl2bW9kKG51bSwgJ2RpdicsIGZhbHNlKS5kaXY7XG4gIH07XG5cbiAgLy8gRmluZCBgdGhpc2AgJSBgbnVtYFxuICBCTi5wcm90b3R5cGUubW9kID0gZnVuY3Rpb24gbW9kIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5kaXZtb2QobnVtLCAnbW9kJywgZmFsc2UpLm1vZDtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUudW1vZCA9IGZ1bmN0aW9uIHVtb2QgKG51bSkge1xuICAgIHJldHVybiB0aGlzLmRpdm1vZChudW0sICdtb2QnLCB0cnVlKS5tb2Q7XG4gIH07XG5cbiAgLy8gRmluZCBSb3VuZChgdGhpc2AgLyBgbnVtYClcbiAgQk4ucHJvdG90eXBlLmRpdlJvdW5kID0gZnVuY3Rpb24gZGl2Um91bmQgKG51bSkge1xuICAgIHZhciBkbSA9IHRoaXMuZGl2bW9kKG51bSk7XG5cbiAgICAvLyBGYXN0IGNhc2UgLSBleGFjdCBkaXZpc2lvblxuICAgIGlmIChkbS5tb2QuaXNaZXJvKCkpIHJldHVybiBkbS5kaXY7XG5cbiAgICB2YXIgbW9kID0gZG0uZGl2Lm5lZ2F0aXZlICE9PSAwID8gZG0ubW9kLmlzdWIobnVtKSA6IGRtLm1vZDtcblxuICAgIHZhciBoYWxmID0gbnVtLnVzaHJuKDEpO1xuICAgIHZhciByMiA9IG51bS5hbmRsbigxKTtcbiAgICB2YXIgY21wID0gbW9kLmNtcChoYWxmKTtcblxuICAgIC8vIFJvdW5kIGRvd25cbiAgICBpZiAoY21wIDwgMCB8fCByMiA9PT0gMSAmJiBjbXAgPT09IDApIHJldHVybiBkbS5kaXY7XG5cbiAgICAvLyBSb3VuZCB1cFxuICAgIHJldHVybiBkbS5kaXYubmVnYXRpdmUgIT09IDAgPyBkbS5kaXYuaXN1Ym4oMSkgOiBkbS5kaXYuaWFkZG4oMSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLm1vZG4gPSBmdW5jdGlvbiBtb2RuIChudW0pIHtcbiAgICBhc3NlcnQobnVtIDw9IDB4M2ZmZmZmZik7XG4gICAgdmFyIHAgPSAoMSA8PCAyNikgJSBudW07XG5cbiAgICB2YXIgYWNjID0gMDtcbiAgICBmb3IgKHZhciBpID0gdGhpcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgYWNjID0gKHAgKiBhY2MgKyAodGhpcy53b3Jkc1tpXSB8IDApKSAlIG51bTtcbiAgICB9XG5cbiAgICByZXR1cm4gYWNjO1xuICB9O1xuXG4gIC8vIEluLXBsYWNlIGRpdmlzaW9uIGJ5IG51bWJlclxuICBCTi5wcm90b3R5cGUuaWRpdm4gPSBmdW5jdGlvbiBpZGl2biAobnVtKSB7XG4gICAgYXNzZXJ0KG51bSA8PSAweDNmZmZmZmYpO1xuXG4gICAgdmFyIGNhcnJ5ID0gMDtcbiAgICBmb3IgKHZhciBpID0gdGhpcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdmFyIHcgPSAodGhpcy53b3Jkc1tpXSB8IDApICsgY2FycnkgKiAweDQwMDAwMDA7XG4gICAgICB0aGlzLndvcmRzW2ldID0gKHcgLyBudW0pIHwgMDtcbiAgICAgIGNhcnJ5ID0gdyAlIG51bTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zdHJpcCgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5kaXZuID0gZnVuY3Rpb24gZGl2biAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5pZGl2bihudW0pO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5lZ2NkID0gZnVuY3Rpb24gZWdjZCAocCkge1xuICAgIGFzc2VydChwLm5lZ2F0aXZlID09PSAwKTtcbiAgICBhc3NlcnQoIXAuaXNaZXJvKCkpO1xuXG4gICAgdmFyIHggPSB0aGlzO1xuICAgIHZhciB5ID0gcC5jbG9uZSgpO1xuXG4gICAgaWYgKHgubmVnYXRpdmUgIT09IDApIHtcbiAgICAgIHggPSB4LnVtb2QocCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHggPSB4LmNsb25lKCk7XG4gICAgfVxuXG4gICAgLy8gQSAqIHggKyBCICogeSA9IHhcbiAgICB2YXIgQSA9IG5ldyBCTigxKTtcbiAgICB2YXIgQiA9IG5ldyBCTigwKTtcblxuICAgIC8vIEMgKiB4ICsgRCAqIHkgPSB5XG4gICAgdmFyIEMgPSBuZXcgQk4oMCk7XG4gICAgdmFyIEQgPSBuZXcgQk4oMSk7XG5cbiAgICB2YXIgZyA9IDA7XG5cbiAgICB3aGlsZSAoeC5pc0V2ZW4oKSAmJiB5LmlzRXZlbigpKSB7XG4gICAgICB4Lml1c2hybigxKTtcbiAgICAgIHkuaXVzaHJuKDEpO1xuICAgICAgKytnO1xuICAgIH1cblxuICAgIHZhciB5cCA9IHkuY2xvbmUoKTtcbiAgICB2YXIgeHAgPSB4LmNsb25lKCk7XG5cbiAgICB3aGlsZSAoIXguaXNaZXJvKCkpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBpbSA9IDE7ICh4LndvcmRzWzBdICYgaW0pID09PSAwICYmIGkgPCAyNjsgKytpLCBpbSA8PD0gMSk7XG4gICAgICBpZiAoaSA+IDApIHtcbiAgICAgICAgeC5pdXNocm4oaSk7XG4gICAgICAgIHdoaWxlIChpLS0gPiAwKSB7XG4gICAgICAgICAgaWYgKEEuaXNPZGQoKSB8fCBCLmlzT2RkKCkpIHtcbiAgICAgICAgICAgIEEuaWFkZCh5cCk7XG4gICAgICAgICAgICBCLmlzdWIoeHApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIEEuaXVzaHJuKDEpO1xuICAgICAgICAgIEIuaXVzaHJuKDEpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZvciAodmFyIGogPSAwLCBqbSA9IDE7ICh5LndvcmRzWzBdICYgam0pID09PSAwICYmIGogPCAyNjsgKytqLCBqbSA8PD0gMSk7XG4gICAgICBpZiAoaiA+IDApIHtcbiAgICAgICAgeS5pdXNocm4oaik7XG4gICAgICAgIHdoaWxlIChqLS0gPiAwKSB7XG4gICAgICAgICAgaWYgKEMuaXNPZGQoKSB8fCBELmlzT2RkKCkpIHtcbiAgICAgICAgICAgIEMuaWFkZCh5cCk7XG4gICAgICAgICAgICBELmlzdWIoeHApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIEMuaXVzaHJuKDEpO1xuICAgICAgICAgIEQuaXVzaHJuKDEpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh4LmNtcCh5KSA+PSAwKSB7XG4gICAgICAgIHguaXN1Yih5KTtcbiAgICAgICAgQS5pc3ViKEMpO1xuICAgICAgICBCLmlzdWIoRCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB5LmlzdWIoeCk7XG4gICAgICAgIEMuaXN1YihBKTtcbiAgICAgICAgRC5pc3ViKEIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBhOiBDLFxuICAgICAgYjogRCxcbiAgICAgIGdjZDogeS5pdXNobG4oZylcbiAgICB9O1xuICB9O1xuXG4gIC8vIFRoaXMgaXMgcmVkdWNlZCBpbmNhcm5hdGlvbiBvZiB0aGUgYmluYXJ5IEVFQVxuICAvLyBhYm92ZSwgZGVzaWduYXRlZCB0byBpbnZlcnQgbWVtYmVycyBvZiB0aGVcbiAgLy8gX3ByaW1lXyBmaWVsZHMgRihwKSBhdCBhIG1heGltYWwgc3BlZWRcbiAgQk4ucHJvdG90eXBlLl9pbnZtcCA9IGZ1bmN0aW9uIF9pbnZtcCAocCkge1xuICAgIGFzc2VydChwLm5lZ2F0aXZlID09PSAwKTtcbiAgICBhc3NlcnQoIXAuaXNaZXJvKCkpO1xuXG4gICAgdmFyIGEgPSB0aGlzO1xuICAgIHZhciBiID0gcC5jbG9uZSgpO1xuXG4gICAgaWYgKGEubmVnYXRpdmUgIT09IDApIHtcbiAgICAgIGEgPSBhLnVtb2QocCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGEgPSBhLmNsb25lKCk7XG4gICAgfVxuXG4gICAgdmFyIHgxID0gbmV3IEJOKDEpO1xuICAgIHZhciB4MiA9IG5ldyBCTigwKTtcblxuICAgIHZhciBkZWx0YSA9IGIuY2xvbmUoKTtcblxuICAgIHdoaWxlIChhLmNtcG4oMSkgPiAwICYmIGIuY21wbigxKSA+IDApIHtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBpbSA9IDE7IChhLndvcmRzWzBdICYgaW0pID09PSAwICYmIGkgPCAyNjsgKytpLCBpbSA8PD0gMSk7XG4gICAgICBpZiAoaSA+IDApIHtcbiAgICAgICAgYS5pdXNocm4oaSk7XG4gICAgICAgIHdoaWxlIChpLS0gPiAwKSB7XG4gICAgICAgICAgaWYgKHgxLmlzT2RkKCkpIHtcbiAgICAgICAgICAgIHgxLmlhZGQoZGVsdGEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHgxLml1c2hybigxKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBqID0gMCwgam0gPSAxOyAoYi53b3Jkc1swXSAmIGptKSA9PT0gMCAmJiBqIDwgMjY7ICsraiwgam0gPDw9IDEpO1xuICAgICAgaWYgKGogPiAwKSB7XG4gICAgICAgIGIuaXVzaHJuKGopO1xuICAgICAgICB3aGlsZSAoai0tID4gMCkge1xuICAgICAgICAgIGlmICh4Mi5pc09kZCgpKSB7XG4gICAgICAgICAgICB4Mi5pYWRkKGRlbHRhKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB4Mi5pdXNocm4oMSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGEuY21wKGIpID49IDApIHtcbiAgICAgICAgYS5pc3ViKGIpO1xuICAgICAgICB4MS5pc3ViKHgyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGIuaXN1YihhKTtcbiAgICAgICAgeDIuaXN1Yih4MSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlcztcbiAgICBpZiAoYS5jbXBuKDEpID09PSAwKSB7XG4gICAgICByZXMgPSB4MTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzID0geDI7XG4gICAgfVxuXG4gICAgaWYgKHJlcy5jbXBuKDApIDwgMCkge1xuICAgICAgcmVzLmlhZGQocCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcztcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuZ2NkID0gZnVuY3Rpb24gZ2NkIChudW0pIHtcbiAgICBpZiAodGhpcy5pc1plcm8oKSkgcmV0dXJuIG51bS5hYnMoKTtcbiAgICBpZiAobnVtLmlzWmVybygpKSByZXR1cm4gdGhpcy5hYnMoKTtcblxuICAgIHZhciBhID0gdGhpcy5jbG9uZSgpO1xuICAgIHZhciBiID0gbnVtLmNsb25lKCk7XG4gICAgYS5uZWdhdGl2ZSA9IDA7XG4gICAgYi5uZWdhdGl2ZSA9IDA7XG5cbiAgICAvLyBSZW1vdmUgY29tbW9uIGZhY3RvciBvZiB0d29cbiAgICBmb3IgKHZhciBzaGlmdCA9IDA7IGEuaXNFdmVuKCkgJiYgYi5pc0V2ZW4oKTsgc2hpZnQrKykge1xuICAgICAgYS5pdXNocm4oMSk7XG4gICAgICBiLml1c2hybigxKTtcbiAgICB9XG5cbiAgICBkbyB7XG4gICAgICB3aGlsZSAoYS5pc0V2ZW4oKSkge1xuICAgICAgICBhLml1c2hybigxKTtcbiAgICAgIH1cbiAgICAgIHdoaWxlIChiLmlzRXZlbigpKSB7XG4gICAgICAgIGIuaXVzaHJuKDEpO1xuICAgICAgfVxuXG4gICAgICB2YXIgciA9IGEuY21wKGIpO1xuICAgICAgaWYgKHIgPCAwKSB7XG4gICAgICAgIC8vIFN3YXAgYGFgIGFuZCBgYmAgdG8gbWFrZSBgYWAgYWx3YXlzIGJpZ2dlciB0aGFuIGBiYFxuICAgICAgICB2YXIgdCA9IGE7XG4gICAgICAgIGEgPSBiO1xuICAgICAgICBiID0gdDtcbiAgICAgIH0gZWxzZSBpZiAociA9PT0gMCB8fCBiLmNtcG4oMSkgPT09IDApIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGEuaXN1YihiKTtcbiAgICB9IHdoaWxlICh0cnVlKTtcblxuICAgIHJldHVybiBiLml1c2hsbihzaGlmdCk7XG4gIH07XG5cbiAgLy8gSW52ZXJ0IG51bWJlciBpbiB0aGUgZmllbGQgRihudW0pXG4gIEJOLnByb3RvdHlwZS5pbnZtID0gZnVuY3Rpb24gaW52bSAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuZWdjZChudW0pLmEudW1vZChudW0pO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5pc0V2ZW4gPSBmdW5jdGlvbiBpc0V2ZW4gKCkge1xuICAgIHJldHVybiAodGhpcy53b3Jkc1swXSAmIDEpID09PSAwO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5pc09kZCA9IGZ1bmN0aW9uIGlzT2RkICgpIHtcbiAgICByZXR1cm4gKHRoaXMud29yZHNbMF0gJiAxKSA9PT0gMTtcbiAgfTtcblxuICAvLyBBbmQgZmlyc3Qgd29yZCBhbmQgbnVtXG4gIEJOLnByb3RvdHlwZS5hbmRsbiA9IGZ1bmN0aW9uIGFuZGxuIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy53b3Jkc1swXSAmIG51bTtcbiAgfTtcblxuICAvLyBJbmNyZW1lbnQgYXQgdGhlIGJpdCBwb3NpdGlvbiBpbi1saW5lXG4gIEJOLnByb3RvdHlwZS5iaW5jbiA9IGZ1bmN0aW9uIGJpbmNuIChiaXQpIHtcbiAgICBhc3NlcnQodHlwZW9mIGJpdCA9PT0gJ251bWJlcicpO1xuICAgIHZhciByID0gYml0ICUgMjY7XG4gICAgdmFyIHMgPSAoYml0IC0gcikgLyAyNjtcbiAgICB2YXIgcSA9IDEgPDwgcjtcblxuICAgIC8vIEZhc3QgY2FzZTogYml0IGlzIG11Y2ggaGlnaGVyIHRoYW4gYWxsIGV4aXN0aW5nIHdvcmRzXG4gICAgaWYgKHRoaXMubGVuZ3RoIDw9IHMpIHtcbiAgICAgIHRoaXMuX2V4cGFuZChzICsgMSk7XG4gICAgICB0aGlzLndvcmRzW3NdIHw9IHE7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyBBZGQgYml0IGFuZCBwcm9wYWdhdGUsIGlmIG5lZWRlZFxuICAgIHZhciBjYXJyeSA9IHE7XG4gICAgZm9yICh2YXIgaSA9IHM7IGNhcnJ5ICE9PSAwICYmIGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgdyA9IHRoaXMud29yZHNbaV0gfCAwO1xuICAgICAgdyArPSBjYXJyeTtcbiAgICAgIGNhcnJ5ID0gdyA+Pj4gMjY7XG4gICAgICB3ICY9IDB4M2ZmZmZmZjtcbiAgICAgIHRoaXMud29yZHNbaV0gPSB3O1xuICAgIH1cbiAgICBpZiAoY2FycnkgIT09IDApIHtcbiAgICAgIHRoaXMud29yZHNbaV0gPSBjYXJyeTtcbiAgICAgIHRoaXMubGVuZ3RoKys7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5pc1plcm8gPSBmdW5jdGlvbiBpc1plcm8gKCkge1xuICAgIHJldHVybiB0aGlzLmxlbmd0aCA9PT0gMSAmJiB0aGlzLndvcmRzWzBdID09PSAwO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5jbXBuID0gZnVuY3Rpb24gY21wbiAobnVtKSB7XG4gICAgdmFyIG5lZ2F0aXZlID0gbnVtIDwgMDtcblxuICAgIGlmICh0aGlzLm5lZ2F0aXZlICE9PSAwICYmICFuZWdhdGl2ZSkgcmV0dXJuIC0xO1xuICAgIGlmICh0aGlzLm5lZ2F0aXZlID09PSAwICYmIG5lZ2F0aXZlKSByZXR1cm4gMTtcblxuICAgIHRoaXMuc3RyaXAoKTtcblxuICAgIHZhciByZXM7XG4gICAgaWYgKHRoaXMubGVuZ3RoID4gMSkge1xuICAgICAgcmVzID0gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG5lZ2F0aXZlKSB7XG4gICAgICAgIG51bSA9IC1udW07XG4gICAgICB9XG5cbiAgICAgIGFzc2VydChudW0gPD0gMHgzZmZmZmZmLCAnTnVtYmVyIGlzIHRvbyBiaWcnKTtcblxuICAgICAgdmFyIHcgPSB0aGlzLndvcmRzWzBdIHwgMDtcbiAgICAgIHJlcyA9IHcgPT09IG51bSA/IDAgOiB3IDwgbnVtID8gLTEgOiAxO1xuICAgIH1cbiAgICBpZiAodGhpcy5uZWdhdGl2ZSAhPT0gMCkgcmV0dXJuIC1yZXMgfCAwO1xuICAgIHJldHVybiByZXM7XG4gIH07XG5cbiAgLy8gQ29tcGFyZSB0d28gbnVtYmVycyBhbmQgcmV0dXJuOlxuICAvLyAxIC0gaWYgYHRoaXNgID4gYG51bWBcbiAgLy8gMCAtIGlmIGB0aGlzYCA9PSBgbnVtYFxuICAvLyAtMSAtIGlmIGB0aGlzYCA8IGBudW1gXG4gIEJOLnByb3RvdHlwZS5jbXAgPSBmdW5jdGlvbiBjbXAgKG51bSkge1xuICAgIGlmICh0aGlzLm5lZ2F0aXZlICE9PSAwICYmIG51bS5uZWdhdGl2ZSA9PT0gMCkgcmV0dXJuIC0xO1xuICAgIGlmICh0aGlzLm5lZ2F0aXZlID09PSAwICYmIG51bS5uZWdhdGl2ZSAhPT0gMCkgcmV0dXJuIDE7XG5cbiAgICB2YXIgcmVzID0gdGhpcy51Y21wKG51bSk7XG4gICAgaWYgKHRoaXMubmVnYXRpdmUgIT09IDApIHJldHVybiAtcmVzIHwgMDtcbiAgICByZXR1cm4gcmVzO1xuICB9O1xuXG4gIC8vIFVuc2lnbmVkIGNvbXBhcmlzb25cbiAgQk4ucHJvdG90eXBlLnVjbXAgPSBmdW5jdGlvbiB1Y21wIChudW0pIHtcbiAgICAvLyBBdCB0aGlzIHBvaW50IGJvdGggbnVtYmVycyBoYXZlIHRoZSBzYW1lIHNpZ25cbiAgICBpZiAodGhpcy5sZW5ndGggPiBudW0ubGVuZ3RoKSByZXR1cm4gMTtcbiAgICBpZiAodGhpcy5sZW5ndGggPCBudW0ubGVuZ3RoKSByZXR1cm4gLTE7XG5cbiAgICB2YXIgcmVzID0gMDtcbiAgICBmb3IgKHZhciBpID0gdGhpcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdmFyIGEgPSB0aGlzLndvcmRzW2ldIHwgMDtcbiAgICAgIHZhciBiID0gbnVtLndvcmRzW2ldIHwgMDtcblxuICAgICAgaWYgKGEgPT09IGIpIGNvbnRpbnVlO1xuICAgICAgaWYgKGEgPCBiKSB7XG4gICAgICAgIHJlcyA9IC0xO1xuICAgICAgfSBlbHNlIGlmIChhID4gYikge1xuICAgICAgICByZXMgPSAxO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmd0biA9IGZ1bmN0aW9uIGd0biAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY21wbihudW0pID09PSAxO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5ndCA9IGZ1bmN0aW9uIGd0IChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbXAobnVtKSA9PT0gMTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuZ3RlbiA9IGZ1bmN0aW9uIGd0ZW4gKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNtcG4obnVtKSA+PSAwO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5ndGUgPSBmdW5jdGlvbiBndGUgKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNtcChudW0pID49IDA7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmx0biA9IGZ1bmN0aW9uIGx0biAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY21wbihudW0pID09PSAtMTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUubHQgPSBmdW5jdGlvbiBsdCAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY21wKG51bSkgPT09IC0xO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5sdGVuID0gZnVuY3Rpb24gbHRlbiAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY21wbihudW0pIDw9IDA7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmx0ZSA9IGZ1bmN0aW9uIGx0ZSAobnVtKSB7XG4gICAgcmV0dXJuIHRoaXMuY21wKG51bSkgPD0gMDtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuZXFuID0gZnVuY3Rpb24gZXFuIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5jbXBuKG51bSkgPT09IDA7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLmVxID0gZnVuY3Rpb24gZXEgKG51bSkge1xuICAgIHJldHVybiB0aGlzLmNtcChudW0pID09PSAwO1xuICB9O1xuXG4gIC8vXG4gIC8vIEEgcmVkdWNlIGNvbnRleHQsIGNvdWxkIGJlIHVzaW5nIG1vbnRnb21lcnkgb3Igc29tZXRoaW5nIGJldHRlciwgZGVwZW5kaW5nXG4gIC8vIG9uIHRoZSBgbWAgaXRzZWxmLlxuICAvL1xuICBCTi5yZWQgPSBmdW5jdGlvbiByZWQgKG51bSkge1xuICAgIHJldHVybiBuZXcgUmVkKG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnRvUmVkID0gZnVuY3Rpb24gdG9SZWQgKGN0eCkge1xuICAgIGFzc2VydCghdGhpcy5yZWQsICdBbHJlYWR5IGEgbnVtYmVyIGluIHJlZHVjdGlvbiBjb250ZXh0Jyk7XG4gICAgYXNzZXJ0KHRoaXMubmVnYXRpdmUgPT09IDAsICdyZWQgd29ya3Mgb25seSB3aXRoIHBvc2l0aXZlcycpO1xuICAgIHJldHVybiBjdHguY29udmVydFRvKHRoaXMpLl9mb3JjZVJlZChjdHgpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5mcm9tUmVkID0gZnVuY3Rpb24gZnJvbVJlZCAoKSB7XG4gICAgYXNzZXJ0KHRoaXMucmVkLCAnZnJvbVJlZCB3b3JrcyBvbmx5IHdpdGggbnVtYmVycyBpbiByZWR1Y3Rpb24gY29udGV4dCcpO1xuICAgIHJldHVybiB0aGlzLnJlZC5jb252ZXJ0RnJvbSh0aGlzKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuX2ZvcmNlUmVkID0gZnVuY3Rpb24gX2ZvcmNlUmVkIChjdHgpIHtcbiAgICB0aGlzLnJlZCA9IGN0eDtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICBCTi5wcm90b3R5cGUuZm9yY2VSZWQgPSBmdW5jdGlvbiBmb3JjZVJlZCAoY3R4KSB7XG4gICAgYXNzZXJ0KCF0aGlzLnJlZCwgJ0FscmVhZHkgYSBudW1iZXIgaW4gcmVkdWN0aW9uIGNvbnRleHQnKTtcbiAgICByZXR1cm4gdGhpcy5fZm9yY2VSZWQoY3R4KTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUucmVkQWRkID0gZnVuY3Rpb24gcmVkQWRkIChudW0pIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdyZWRBZGQgd29ya3Mgb25seSB3aXRoIHJlZCBudW1iZXJzJyk7XG4gICAgcmV0dXJuIHRoaXMucmVkLmFkZCh0aGlzLCBudW0pO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5yZWRJQWRkID0gZnVuY3Rpb24gcmVkSUFkZCAobnVtKSB7XG4gICAgYXNzZXJ0KHRoaXMucmVkLCAncmVkSUFkZCB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgICByZXR1cm4gdGhpcy5yZWQuaWFkZCh0aGlzLCBudW0pO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5yZWRTdWIgPSBmdW5jdGlvbiByZWRTdWIgKG51bSkge1xuICAgIGFzc2VydCh0aGlzLnJlZCwgJ3JlZFN1YiB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgICByZXR1cm4gdGhpcy5yZWQuc3ViKHRoaXMsIG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnJlZElTdWIgPSBmdW5jdGlvbiByZWRJU3ViIChudW0pIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdyZWRJU3ViIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICAgIHJldHVybiB0aGlzLnJlZC5pc3ViKHRoaXMsIG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnJlZFNobCA9IGZ1bmN0aW9uIHJlZFNobCAobnVtKSB7XG4gICAgYXNzZXJ0KHRoaXMucmVkLCAncmVkU2hsIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICAgIHJldHVybiB0aGlzLnJlZC5zaGwodGhpcywgbnVtKTtcbiAgfTtcblxuICBCTi5wcm90b3R5cGUucmVkTXVsID0gZnVuY3Rpb24gcmVkTXVsIChudW0pIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdyZWRNdWwgd29ya3Mgb25seSB3aXRoIHJlZCBudW1iZXJzJyk7XG4gICAgdGhpcy5yZWQuX3ZlcmlmeTIodGhpcywgbnVtKTtcbiAgICByZXR1cm4gdGhpcy5yZWQubXVsKHRoaXMsIG51bSk7XG4gIH07XG5cbiAgQk4ucHJvdG90eXBlLnJlZElNdWwgPSBmdW5jdGlvbiByZWRJTXVsIChudW0pIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdyZWRNdWwgd29ya3Mgb25seSB3aXRoIHJlZCBudW1iZXJzJyk7XG4gICAgdGhpcy5yZWQuX3ZlcmlmeTIodGhpcywgbnVtKTtcbiAgICByZXR1cm4gdGhpcy5yZWQuaW11bCh0aGlzLCBudW0pO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5yZWRTcXIgPSBmdW5jdGlvbiByZWRTcXIgKCkge1xuICAgIGFzc2VydCh0aGlzLnJlZCwgJ3JlZFNxciB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgICB0aGlzLnJlZC5fdmVyaWZ5MSh0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5yZWQuc3FyKHRoaXMpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5yZWRJU3FyID0gZnVuY3Rpb24gcmVkSVNxciAoKSB7XG4gICAgYXNzZXJ0KHRoaXMucmVkLCAncmVkSVNxciB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgICB0aGlzLnJlZC5fdmVyaWZ5MSh0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5yZWQuaXNxcih0aGlzKTtcbiAgfTtcblxuICAvLyBTcXVhcmUgcm9vdCBvdmVyIHBcbiAgQk4ucHJvdG90eXBlLnJlZFNxcnQgPSBmdW5jdGlvbiByZWRTcXJ0ICgpIHtcbiAgICBhc3NlcnQodGhpcy5yZWQsICdyZWRTcXJ0IHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICAgIHRoaXMucmVkLl92ZXJpZnkxKHRoaXMpO1xuICAgIHJldHVybiB0aGlzLnJlZC5zcXJ0KHRoaXMpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5yZWRJbnZtID0gZnVuY3Rpb24gcmVkSW52bSAoKSB7XG4gICAgYXNzZXJ0KHRoaXMucmVkLCAncmVkSW52bSB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgICB0aGlzLnJlZC5fdmVyaWZ5MSh0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5yZWQuaW52bSh0aGlzKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gbmVnYXRpdmUgY2xvbmUgb2YgYHRoaXNgICUgYHJlZCBtb2R1bG9gXG4gIEJOLnByb3RvdHlwZS5yZWROZWcgPSBmdW5jdGlvbiByZWROZWcgKCkge1xuICAgIGFzc2VydCh0aGlzLnJlZCwgJ3JlZE5lZyB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgICB0aGlzLnJlZC5fdmVyaWZ5MSh0aGlzKTtcbiAgICByZXR1cm4gdGhpcy5yZWQubmVnKHRoaXMpO1xuICB9O1xuXG4gIEJOLnByb3RvdHlwZS5yZWRQb3cgPSBmdW5jdGlvbiByZWRQb3cgKG51bSkge1xuICAgIGFzc2VydCh0aGlzLnJlZCAmJiAhbnVtLnJlZCwgJ3JlZFBvdyhub3JtYWxOdW0pJyk7XG4gICAgdGhpcy5yZWQuX3ZlcmlmeTEodGhpcyk7XG4gICAgcmV0dXJuIHRoaXMucmVkLnBvdyh0aGlzLCBudW0pO1xuICB9O1xuXG4gIC8vIFByaW1lIG51bWJlcnMgd2l0aCBlZmZpY2llbnQgcmVkdWN0aW9uXG4gIHZhciBwcmltZXMgPSB7XG4gICAgazI1NjogbnVsbCxcbiAgICBwMjI0OiBudWxsLFxuICAgIHAxOTI6IG51bGwsXG4gICAgcDI1NTE5OiBudWxsXG4gIH07XG5cbiAgLy8gUHNldWRvLU1lcnNlbm5lIHByaW1lXG4gIGZ1bmN0aW9uIE1QcmltZSAobmFtZSwgcCkge1xuICAgIC8vIFAgPSAyIF4gTiAtIEtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICAgIHRoaXMucCA9IG5ldyBCTihwLCAxNik7XG4gICAgdGhpcy5uID0gdGhpcy5wLmJpdExlbmd0aCgpO1xuICAgIHRoaXMuayA9IG5ldyBCTigxKS5pdXNobG4odGhpcy5uKS5pc3ViKHRoaXMucCk7XG5cbiAgICB0aGlzLnRtcCA9IHRoaXMuX3RtcCgpO1xuICB9XG5cbiAgTVByaW1lLnByb3RvdHlwZS5fdG1wID0gZnVuY3Rpb24gX3RtcCAoKSB7XG4gICAgdmFyIHRtcCA9IG5ldyBCTihudWxsKTtcbiAgICB0bXAud29yZHMgPSBuZXcgQXJyYXkoTWF0aC5jZWlsKHRoaXMubiAvIDEzKSk7XG4gICAgcmV0dXJuIHRtcDtcbiAgfTtcblxuICBNUHJpbWUucHJvdG90eXBlLmlyZWR1Y2UgPSBmdW5jdGlvbiBpcmVkdWNlIChudW0pIHtcbiAgICAvLyBBc3N1bWVzIHRoYXQgYG51bWAgaXMgbGVzcyB0aGFuIGBQXjJgXG4gICAgLy8gbnVtID0gSEkgKiAoMiBeIE4gLSBLKSArIEhJICogSyArIExPID0gSEkgKiBLICsgTE8gKG1vZCBQKVxuICAgIHZhciByID0gbnVtO1xuICAgIHZhciBybGVuO1xuXG4gICAgZG8ge1xuICAgICAgdGhpcy5zcGxpdChyLCB0aGlzLnRtcCk7XG4gICAgICByID0gdGhpcy5pbXVsSyhyKTtcbiAgICAgIHIgPSByLmlhZGQodGhpcy50bXApO1xuICAgICAgcmxlbiA9IHIuYml0TGVuZ3RoKCk7XG4gICAgfSB3aGlsZSAocmxlbiA+IHRoaXMubik7XG5cbiAgICB2YXIgY21wID0gcmxlbiA8IHRoaXMubiA/IC0xIDogci51Y21wKHRoaXMucCk7XG4gICAgaWYgKGNtcCA9PT0gMCkge1xuICAgICAgci53b3Jkc1swXSA9IDA7XG4gICAgICByLmxlbmd0aCA9IDE7XG4gICAgfSBlbHNlIGlmIChjbXAgPiAwKSB7XG4gICAgICByLmlzdWIodGhpcy5wKTtcbiAgICB9IGVsc2Uge1xuICAgICAgci5zdHJpcCgpO1xuICAgIH1cblxuICAgIHJldHVybiByO1xuICB9O1xuXG4gIE1QcmltZS5wcm90b3R5cGUuc3BsaXQgPSBmdW5jdGlvbiBzcGxpdCAoaW5wdXQsIG91dCkge1xuICAgIGlucHV0Lml1c2hybih0aGlzLm4sIDAsIG91dCk7XG4gIH07XG5cbiAgTVByaW1lLnByb3RvdHlwZS5pbXVsSyA9IGZ1bmN0aW9uIGltdWxLIChudW0pIHtcbiAgICByZXR1cm4gbnVtLmltdWwodGhpcy5rKTtcbiAgfTtcblxuICBmdW5jdGlvbiBLMjU2ICgpIHtcbiAgICBNUHJpbWUuY2FsbChcbiAgICAgIHRoaXMsXG4gICAgICAnazI1NicsXG4gICAgICAnZmZmZmZmZmYgZmZmZmZmZmYgZmZmZmZmZmYgZmZmZmZmZmYgZmZmZmZmZmYgZmZmZmZmZmYgZmZmZmZmZmUgZmZmZmZjMmYnKTtcbiAgfVxuICBpbmhlcml0cyhLMjU2LCBNUHJpbWUpO1xuXG4gIEsyNTYucHJvdG90eXBlLnNwbGl0ID0gZnVuY3Rpb24gc3BsaXQgKGlucHV0LCBvdXRwdXQpIHtcbiAgICAvLyAyNTYgPSA5ICogMjYgKyAyMlxuICAgIHZhciBtYXNrID0gMHgzZmZmZmY7XG5cbiAgICB2YXIgb3V0TGVuID0gTWF0aC5taW4oaW5wdXQubGVuZ3RoLCA5KTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG91dExlbjsgaSsrKSB7XG4gICAgICBvdXRwdXQud29yZHNbaV0gPSBpbnB1dC53b3Jkc1tpXTtcbiAgICB9XG4gICAgb3V0cHV0Lmxlbmd0aCA9IG91dExlbjtcblxuICAgIGlmIChpbnB1dC5sZW5ndGggPD0gOSkge1xuICAgICAgaW5wdXQud29yZHNbMF0gPSAwO1xuICAgICAgaW5wdXQubGVuZ3RoID0gMTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBTaGlmdCBieSA5IGxpbWJzXG4gICAgdmFyIHByZXYgPSBpbnB1dC53b3Jkc1s5XTtcbiAgICBvdXRwdXQud29yZHNbb3V0cHV0Lmxlbmd0aCsrXSA9IHByZXYgJiBtYXNrO1xuXG4gICAgZm9yIChpID0gMTA7IGkgPCBpbnB1dC5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIG5leHQgPSBpbnB1dC53b3Jkc1tpXSB8IDA7XG4gICAgICBpbnB1dC53b3Jkc1tpIC0gMTBdID0gKChuZXh0ICYgbWFzaykgPDwgNCkgfCAocHJldiA+Pj4gMjIpO1xuICAgICAgcHJldiA9IG5leHQ7XG4gICAgfVxuICAgIHByZXYgPj4+PSAyMjtcbiAgICBpbnB1dC53b3Jkc1tpIC0gMTBdID0gcHJldjtcbiAgICBpZiAocHJldiA9PT0gMCAmJiBpbnB1dC5sZW5ndGggPiAxMCkge1xuICAgICAgaW5wdXQubGVuZ3RoIC09IDEwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpbnB1dC5sZW5ndGggLT0gOTtcbiAgICB9XG4gIH07XG5cbiAgSzI1Ni5wcm90b3R5cGUuaW11bEsgPSBmdW5jdGlvbiBpbXVsSyAobnVtKSB7XG4gICAgLy8gSyA9IDB4MTAwMDAwM2QxID0gWyAweDQwLCAweDNkMSBdXG4gICAgbnVtLndvcmRzW251bS5sZW5ndGhdID0gMDtcbiAgICBudW0ud29yZHNbbnVtLmxlbmd0aCArIDFdID0gMDtcbiAgICBudW0ubGVuZ3RoICs9IDI7XG5cbiAgICAvLyBib3VuZGVkIGF0OiAweDQwICogMHgzZmZmZmZmICsgMHgzZDAgPSAweDEwMDAwMDM5MFxuICAgIHZhciBsbyA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW0ubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciB3ID0gbnVtLndvcmRzW2ldIHwgMDtcbiAgICAgIGxvICs9IHcgKiAweDNkMTtcbiAgICAgIG51bS53b3Jkc1tpXSA9IGxvICYgMHgzZmZmZmZmO1xuICAgICAgbG8gPSB3ICogMHg0MCArICgobG8gLyAweDQwMDAwMDApIHwgMCk7XG4gICAgfVxuXG4gICAgLy8gRmFzdCBsZW5ndGggcmVkdWN0aW9uXG4gICAgaWYgKG51bS53b3Jkc1tudW0ubGVuZ3RoIC0gMV0gPT09IDApIHtcbiAgICAgIG51bS5sZW5ndGgtLTtcbiAgICAgIGlmIChudW0ud29yZHNbbnVtLmxlbmd0aCAtIDFdID09PSAwKSB7XG4gICAgICAgIG51bS5sZW5ndGgtLTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bTtcbiAgfTtcblxuICBmdW5jdGlvbiBQMjI0ICgpIHtcbiAgICBNUHJpbWUuY2FsbChcbiAgICAgIHRoaXMsXG4gICAgICAncDIyNCcsXG4gICAgICAnZmZmZmZmZmYgZmZmZmZmZmYgZmZmZmZmZmYgZmZmZmZmZmYgMDAwMDAwMDAgMDAwMDAwMDAgMDAwMDAwMDEnKTtcbiAgfVxuICBpbmhlcml0cyhQMjI0LCBNUHJpbWUpO1xuXG4gIGZ1bmN0aW9uIFAxOTIgKCkge1xuICAgIE1QcmltZS5jYWxsKFxuICAgICAgdGhpcyxcbiAgICAgICdwMTkyJyxcbiAgICAgICdmZmZmZmZmZiBmZmZmZmZmZiBmZmZmZmZmZiBmZmZmZmZmZSBmZmZmZmZmZiBmZmZmZmZmZicpO1xuICB9XG4gIGluaGVyaXRzKFAxOTIsIE1QcmltZSk7XG5cbiAgZnVuY3Rpb24gUDI1NTE5ICgpIHtcbiAgICAvLyAyIF4gMjU1IC0gMTlcbiAgICBNUHJpbWUuY2FsbChcbiAgICAgIHRoaXMsXG4gICAgICAnMjU1MTknLFxuICAgICAgJzdmZmZmZmZmZmZmZmZmZmYgZmZmZmZmZmZmZmZmZmZmZiBmZmZmZmZmZmZmZmZmZmZmIGZmZmZmZmZmZmZmZmZmZWQnKTtcbiAgfVxuICBpbmhlcml0cyhQMjU1MTksIE1QcmltZSk7XG5cbiAgUDI1NTE5LnByb3RvdHlwZS5pbXVsSyA9IGZ1bmN0aW9uIGltdWxLIChudW0pIHtcbiAgICAvLyBLID0gMHgxM1xuICAgIHZhciBjYXJyeSA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW0ubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBoaSA9IChudW0ud29yZHNbaV0gfCAwKSAqIDB4MTMgKyBjYXJyeTtcbiAgICAgIHZhciBsbyA9IGhpICYgMHgzZmZmZmZmO1xuICAgICAgaGkgPj4+PSAyNjtcblxuICAgICAgbnVtLndvcmRzW2ldID0gbG87XG4gICAgICBjYXJyeSA9IGhpO1xuICAgIH1cbiAgICBpZiAoY2FycnkgIT09IDApIHtcbiAgICAgIG51bS53b3Jkc1tudW0ubGVuZ3RoKytdID0gY2Fycnk7XG4gICAgfVxuICAgIHJldHVybiBudW07XG4gIH07XG5cbiAgLy8gRXhwb3J0ZWQgbW9zdGx5IGZvciB0ZXN0aW5nIHB1cnBvc2VzLCB1c2UgcGxhaW4gbmFtZSBpbnN0ZWFkXG4gIEJOLl9wcmltZSA9IGZ1bmN0aW9uIHByaW1lIChuYW1lKSB7XG4gICAgLy8gQ2FjaGVkIHZlcnNpb24gb2YgcHJpbWVcbiAgICBpZiAocHJpbWVzW25hbWVdKSByZXR1cm4gcHJpbWVzW25hbWVdO1xuXG4gICAgdmFyIHByaW1lO1xuICAgIGlmIChuYW1lID09PSAnazI1NicpIHtcbiAgICAgIHByaW1lID0gbmV3IEsyNTYoKTtcbiAgICB9IGVsc2UgaWYgKG5hbWUgPT09ICdwMjI0Jykge1xuICAgICAgcHJpbWUgPSBuZXcgUDIyNCgpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ3AxOTInKSB7XG4gICAgICBwcmltZSA9IG5ldyBQMTkyKCk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSAncDI1NTE5Jykge1xuICAgICAgcHJpbWUgPSBuZXcgUDI1NTE5KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBwcmltZSAnICsgbmFtZSk7XG4gICAgfVxuICAgIHByaW1lc1tuYW1lXSA9IHByaW1lO1xuXG4gICAgcmV0dXJuIHByaW1lO1xuICB9O1xuXG4gIC8vXG4gIC8vIEJhc2UgcmVkdWN0aW9uIGVuZ2luZVxuICAvL1xuICBmdW5jdGlvbiBSZWQgKG0pIHtcbiAgICBpZiAodHlwZW9mIG0gPT09ICdzdHJpbmcnKSB7XG4gICAgICB2YXIgcHJpbWUgPSBCTi5fcHJpbWUobSk7XG4gICAgICB0aGlzLm0gPSBwcmltZS5wO1xuICAgICAgdGhpcy5wcmltZSA9IHByaW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3NlcnQobS5ndG4oMSksICdtb2R1bHVzIG11c3QgYmUgZ3JlYXRlciB0aGFuIDEnKTtcbiAgICAgIHRoaXMubSA9IG07XG4gICAgICB0aGlzLnByaW1lID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBSZWQucHJvdG90eXBlLl92ZXJpZnkxID0gZnVuY3Rpb24gX3ZlcmlmeTEgKGEpIHtcbiAgICBhc3NlcnQoYS5uZWdhdGl2ZSA9PT0gMCwgJ3JlZCB3b3JrcyBvbmx5IHdpdGggcG9zaXRpdmVzJyk7XG4gICAgYXNzZXJ0KGEucmVkLCAncmVkIHdvcmtzIG9ubHkgd2l0aCByZWQgbnVtYmVycycpO1xuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUuX3ZlcmlmeTIgPSBmdW5jdGlvbiBfdmVyaWZ5MiAoYSwgYikge1xuICAgIGFzc2VydCgoYS5uZWdhdGl2ZSB8IGIubmVnYXRpdmUpID09PSAwLCAncmVkIHdvcmtzIG9ubHkgd2l0aCBwb3NpdGl2ZXMnKTtcbiAgICBhc3NlcnQoYS5yZWQgJiYgYS5yZWQgPT09IGIucmVkLFxuICAgICAgJ3JlZCB3b3JrcyBvbmx5IHdpdGggcmVkIG51bWJlcnMnKTtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLmltb2QgPSBmdW5jdGlvbiBpbW9kIChhKSB7XG4gICAgaWYgKHRoaXMucHJpbWUpIHJldHVybiB0aGlzLnByaW1lLmlyZWR1Y2UoYSkuX2ZvcmNlUmVkKHRoaXMpO1xuICAgIHJldHVybiBhLnVtb2QodGhpcy5tKS5fZm9yY2VSZWQodGhpcyk7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5uZWcgPSBmdW5jdGlvbiBuZWcgKGEpIHtcbiAgICBpZiAoYS5pc1plcm8oKSkge1xuICAgICAgcmV0dXJuIGEuY2xvbmUoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5tLnN1YihhKS5fZm9yY2VSZWQodGhpcyk7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiBhZGQgKGEsIGIpIHtcbiAgICB0aGlzLl92ZXJpZnkyKGEsIGIpO1xuXG4gICAgdmFyIHJlcyA9IGEuYWRkKGIpO1xuICAgIGlmIChyZXMuY21wKHRoaXMubSkgPj0gMCkge1xuICAgICAgcmVzLmlzdWIodGhpcy5tKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcy5fZm9yY2VSZWQodGhpcyk7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5pYWRkID0gZnVuY3Rpb24gaWFkZCAoYSwgYikge1xuICAgIHRoaXMuX3ZlcmlmeTIoYSwgYik7XG5cbiAgICB2YXIgcmVzID0gYS5pYWRkKGIpO1xuICAgIGlmIChyZXMuY21wKHRoaXMubSkgPj0gMCkge1xuICAgICAgcmVzLmlzdWIodGhpcy5tKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLnN1YiA9IGZ1bmN0aW9uIHN1YiAoYSwgYikge1xuICAgIHRoaXMuX3ZlcmlmeTIoYSwgYik7XG5cbiAgICB2YXIgcmVzID0gYS5zdWIoYik7XG4gICAgaWYgKHJlcy5jbXBuKDApIDwgMCkge1xuICAgICAgcmVzLmlhZGQodGhpcy5tKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcy5fZm9yY2VSZWQodGhpcyk7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5pc3ViID0gZnVuY3Rpb24gaXN1YiAoYSwgYikge1xuICAgIHRoaXMuX3ZlcmlmeTIoYSwgYik7XG5cbiAgICB2YXIgcmVzID0gYS5pc3ViKGIpO1xuICAgIGlmIChyZXMuY21wbigwKSA8IDApIHtcbiAgICAgIHJlcy5pYWRkKHRoaXMubSk7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5zaGwgPSBmdW5jdGlvbiBzaGwgKGEsIG51bSkge1xuICAgIHRoaXMuX3ZlcmlmeTEoYSk7XG4gICAgcmV0dXJuIHRoaXMuaW1vZChhLnVzaGxuKG51bSkpO1xuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUuaW11bCA9IGZ1bmN0aW9uIGltdWwgKGEsIGIpIHtcbiAgICB0aGlzLl92ZXJpZnkyKGEsIGIpO1xuICAgIHJldHVybiB0aGlzLmltb2QoYS5pbXVsKGIpKTtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLm11bCA9IGZ1bmN0aW9uIG11bCAoYSwgYikge1xuICAgIHRoaXMuX3ZlcmlmeTIoYSwgYik7XG4gICAgcmV0dXJuIHRoaXMuaW1vZChhLm11bChiKSk7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5pc3FyID0gZnVuY3Rpb24gaXNxciAoYSkge1xuICAgIHJldHVybiB0aGlzLmltdWwoYSwgYS5jbG9uZSgpKTtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLnNxciA9IGZ1bmN0aW9uIHNxciAoYSkge1xuICAgIHJldHVybiB0aGlzLm11bChhLCBhKTtcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLnNxcnQgPSBmdW5jdGlvbiBzcXJ0IChhKSB7XG4gICAgaWYgKGEuaXNaZXJvKCkpIHJldHVybiBhLmNsb25lKCk7XG5cbiAgICB2YXIgbW9kMyA9IHRoaXMubS5hbmRsbigzKTtcbiAgICBhc3NlcnQobW9kMyAlIDIgPT09IDEpO1xuXG4gICAgLy8gRmFzdCBjYXNlXG4gICAgaWYgKG1vZDMgPT09IDMpIHtcbiAgICAgIHZhciBwb3cgPSB0aGlzLm0uYWRkKG5ldyBCTigxKSkuaXVzaHJuKDIpO1xuICAgICAgcmV0dXJuIHRoaXMucG93KGEsIHBvdyk7XG4gICAgfVxuXG4gICAgLy8gVG9uZWxsaS1TaGFua3MgYWxnb3JpdGhtIChUb3RhbGx5IHVub3B0aW1pemVkIGFuZCBzbG93KVxuICAgIC8vXG4gICAgLy8gRmluZCBRIGFuZCBTLCB0aGF0IFEgKiAyIF4gUyA9IChQIC0gMSlcbiAgICB2YXIgcSA9IHRoaXMubS5zdWJuKDEpO1xuICAgIHZhciBzID0gMDtcbiAgICB3aGlsZSAoIXEuaXNaZXJvKCkgJiYgcS5hbmRsbigxKSA9PT0gMCkge1xuICAgICAgcysrO1xuICAgICAgcS5pdXNocm4oMSk7XG4gICAgfVxuICAgIGFzc2VydCghcS5pc1plcm8oKSk7XG5cbiAgICB2YXIgb25lID0gbmV3IEJOKDEpLnRvUmVkKHRoaXMpO1xuICAgIHZhciBuT25lID0gb25lLnJlZE5lZygpO1xuXG4gICAgLy8gRmluZCBxdWFkcmF0aWMgbm9uLXJlc2lkdWVcbiAgICAvLyBOT1RFOiBNYXggaXMgc3VjaCBiZWNhdXNlIG9mIGdlbmVyYWxpemVkIFJpZW1hbm4gaHlwb3RoZXNpcy5cbiAgICB2YXIgbHBvdyA9IHRoaXMubS5zdWJuKDEpLml1c2hybigxKTtcbiAgICB2YXIgeiA9IHRoaXMubS5iaXRMZW5ndGgoKTtcbiAgICB6ID0gbmV3IEJOKDIgKiB6ICogeikudG9SZWQodGhpcyk7XG5cbiAgICB3aGlsZSAodGhpcy5wb3coeiwgbHBvdykuY21wKG5PbmUpICE9PSAwKSB7XG4gICAgICB6LnJlZElBZGQobk9uZSk7XG4gICAgfVxuXG4gICAgdmFyIGMgPSB0aGlzLnBvdyh6LCBxKTtcbiAgICB2YXIgciA9IHRoaXMucG93KGEsIHEuYWRkbigxKS5pdXNocm4oMSkpO1xuICAgIHZhciB0ID0gdGhpcy5wb3coYSwgcSk7XG4gICAgdmFyIG0gPSBzO1xuICAgIHdoaWxlICh0LmNtcChvbmUpICE9PSAwKSB7XG4gICAgICB2YXIgdG1wID0gdDtcbiAgICAgIGZvciAodmFyIGkgPSAwOyB0bXAuY21wKG9uZSkgIT09IDA7IGkrKykge1xuICAgICAgICB0bXAgPSB0bXAucmVkU3FyKCk7XG4gICAgICB9XG4gICAgICBhc3NlcnQoaSA8IG0pO1xuICAgICAgdmFyIGIgPSB0aGlzLnBvdyhjLCBuZXcgQk4oMSkuaXVzaGxuKG0gLSBpIC0gMSkpO1xuXG4gICAgICByID0gci5yZWRNdWwoYik7XG4gICAgICBjID0gYi5yZWRTcXIoKTtcbiAgICAgIHQgPSB0LnJlZE11bChjKTtcbiAgICAgIG0gPSBpO1xuICAgIH1cblxuICAgIHJldHVybiByO1xuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUuaW52bSA9IGZ1bmN0aW9uIGludm0gKGEpIHtcbiAgICB2YXIgaW52ID0gYS5faW52bXAodGhpcy5tKTtcbiAgICBpZiAoaW52Lm5lZ2F0aXZlICE9PSAwKSB7XG4gICAgICBpbnYubmVnYXRpdmUgPSAwO1xuICAgICAgcmV0dXJuIHRoaXMuaW1vZChpbnYpLnJlZE5lZygpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5pbW9kKGludik7XG4gICAgfVxuICB9O1xuXG4gIFJlZC5wcm90b3R5cGUucG93ID0gZnVuY3Rpb24gcG93IChhLCBudW0pIHtcbiAgICBpZiAobnVtLmlzWmVybygpKSByZXR1cm4gbmV3IEJOKDEpLnRvUmVkKHRoaXMpO1xuICAgIGlmIChudW0uY21wbigxKSA9PT0gMCkgcmV0dXJuIGEuY2xvbmUoKTtcblxuICAgIHZhciB3aW5kb3dTaXplID0gNDtcbiAgICB2YXIgd25kID0gbmV3IEFycmF5KDEgPDwgd2luZG93U2l6ZSk7XG4gICAgd25kWzBdID0gbmV3IEJOKDEpLnRvUmVkKHRoaXMpO1xuICAgIHduZFsxXSA9IGE7XG4gICAgZm9yICh2YXIgaSA9IDI7IGkgPCB3bmQubGVuZ3RoOyBpKyspIHtcbiAgICAgIHduZFtpXSA9IHRoaXMubXVsKHduZFtpIC0gMV0sIGEpO1xuICAgIH1cblxuICAgIHZhciByZXMgPSB3bmRbMF07XG4gICAgdmFyIGN1cnJlbnQgPSAwO1xuICAgIHZhciBjdXJyZW50TGVuID0gMDtcbiAgICB2YXIgc3RhcnQgPSBudW0uYml0TGVuZ3RoKCkgJSAyNjtcbiAgICBpZiAoc3RhcnQgPT09IDApIHtcbiAgICAgIHN0YXJ0ID0gMjY7XG4gICAgfVxuXG4gICAgZm9yIChpID0gbnVtLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB2YXIgd29yZCA9IG51bS53b3Jkc1tpXTtcbiAgICAgIGZvciAodmFyIGogPSBzdGFydCAtIDE7IGogPj0gMDsgai0tKSB7XG4gICAgICAgIHZhciBiaXQgPSAod29yZCA+PiBqKSAmIDE7XG4gICAgICAgIGlmIChyZXMgIT09IHduZFswXSkge1xuICAgICAgICAgIHJlcyA9IHRoaXMuc3FyKHJlcyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYml0ID09PSAwICYmIGN1cnJlbnQgPT09IDApIHtcbiAgICAgICAgICBjdXJyZW50TGVuID0gMDtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGN1cnJlbnQgPDw9IDE7XG4gICAgICAgIGN1cnJlbnQgfD0gYml0O1xuICAgICAgICBjdXJyZW50TGVuKys7XG4gICAgICAgIGlmIChjdXJyZW50TGVuICE9PSB3aW5kb3dTaXplICYmIChpICE9PSAwIHx8IGogIT09IDApKSBjb250aW51ZTtcblxuICAgICAgICByZXMgPSB0aGlzLm11bChyZXMsIHduZFtjdXJyZW50XSk7XG4gICAgICAgIGN1cnJlbnRMZW4gPSAwO1xuICAgICAgICBjdXJyZW50ID0gMDtcbiAgICAgIH1cbiAgICAgIHN0YXJ0ID0gMjY7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcztcbiAgfTtcblxuICBSZWQucHJvdG90eXBlLmNvbnZlcnRUbyA9IGZ1bmN0aW9uIGNvbnZlcnRUbyAobnVtKSB7XG4gICAgdmFyIHIgPSBudW0udW1vZCh0aGlzLm0pO1xuXG4gICAgcmV0dXJuIHIgPT09IG51bSA/IHIuY2xvbmUoKSA6IHI7XG4gIH07XG5cbiAgUmVkLnByb3RvdHlwZS5jb252ZXJ0RnJvbSA9IGZ1bmN0aW9uIGNvbnZlcnRGcm9tIChudW0pIHtcbiAgICB2YXIgcmVzID0gbnVtLmNsb25lKCk7XG4gICAgcmVzLnJlZCA9IG51bGw7XG4gICAgcmV0dXJuIHJlcztcbiAgfTtcblxuICAvL1xuICAvLyBNb250Z29tZXJ5IG1ldGhvZCBlbmdpbmVcbiAgLy9cblxuICBCTi5tb250ID0gZnVuY3Rpb24gbW9udCAobnVtKSB7XG4gICAgcmV0dXJuIG5ldyBNb250KG51bSk7XG4gIH07XG5cbiAgZnVuY3Rpb24gTW9udCAobSkge1xuICAgIFJlZC5jYWxsKHRoaXMsIG0pO1xuXG4gICAgdGhpcy5zaGlmdCA9IHRoaXMubS5iaXRMZW5ndGgoKTtcbiAgICBpZiAodGhpcy5zaGlmdCAlIDI2ICE9PSAwKSB7XG4gICAgICB0aGlzLnNoaWZ0ICs9IDI2IC0gKHRoaXMuc2hpZnQgJSAyNik7XG4gICAgfVxuXG4gICAgdGhpcy5yID0gbmV3IEJOKDEpLml1c2hsbih0aGlzLnNoaWZ0KTtcbiAgICB0aGlzLnIyID0gdGhpcy5pbW9kKHRoaXMuci5zcXIoKSk7XG4gICAgdGhpcy5yaW52ID0gdGhpcy5yLl9pbnZtcCh0aGlzLm0pO1xuXG4gICAgdGhpcy5taW52ID0gdGhpcy5yaW52Lm11bCh0aGlzLnIpLmlzdWJuKDEpLmRpdih0aGlzLm0pO1xuICAgIHRoaXMubWludiA9IHRoaXMubWludi51bW9kKHRoaXMucik7XG4gICAgdGhpcy5taW52ID0gdGhpcy5yLnN1Yih0aGlzLm1pbnYpO1xuICB9XG4gIGluaGVyaXRzKE1vbnQsIFJlZCk7XG5cbiAgTW9udC5wcm90b3R5cGUuY29udmVydFRvID0gZnVuY3Rpb24gY29udmVydFRvIChudW0pIHtcbiAgICByZXR1cm4gdGhpcy5pbW9kKG51bS51c2hsbih0aGlzLnNoaWZ0KSk7XG4gIH07XG5cbiAgTW9udC5wcm90b3R5cGUuY29udmVydEZyb20gPSBmdW5jdGlvbiBjb252ZXJ0RnJvbSAobnVtKSB7XG4gICAgdmFyIHIgPSB0aGlzLmltb2QobnVtLm11bCh0aGlzLnJpbnYpKTtcbiAgICByLnJlZCA9IG51bGw7XG4gICAgcmV0dXJuIHI7XG4gIH07XG5cbiAgTW9udC5wcm90b3R5cGUuaW11bCA9IGZ1bmN0aW9uIGltdWwgKGEsIGIpIHtcbiAgICBpZiAoYS5pc1plcm8oKSB8fCBiLmlzWmVybygpKSB7XG4gICAgICBhLndvcmRzWzBdID0gMDtcbiAgICAgIGEubGVuZ3RoID0gMTtcbiAgICAgIHJldHVybiBhO1xuICAgIH1cblxuICAgIHZhciB0ID0gYS5pbXVsKGIpO1xuICAgIHZhciBjID0gdC5tYXNrbih0aGlzLnNoaWZ0KS5tdWwodGhpcy5taW52KS5pbWFza24odGhpcy5zaGlmdCkubXVsKHRoaXMubSk7XG4gICAgdmFyIHUgPSB0LmlzdWIoYykuaXVzaHJuKHRoaXMuc2hpZnQpO1xuICAgIHZhciByZXMgPSB1O1xuXG4gICAgaWYgKHUuY21wKHRoaXMubSkgPj0gMCkge1xuICAgICAgcmVzID0gdS5pc3ViKHRoaXMubSk7XG4gICAgfSBlbHNlIGlmICh1LmNtcG4oMCkgPCAwKSB7XG4gICAgICByZXMgPSB1LmlhZGQodGhpcy5tKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzLl9mb3JjZVJlZCh0aGlzKTtcbiAgfTtcblxuICBNb250LnByb3RvdHlwZS5tdWwgPSBmdW5jdGlvbiBtdWwgKGEsIGIpIHtcbiAgICBpZiAoYS5pc1plcm8oKSB8fCBiLmlzWmVybygpKSByZXR1cm4gbmV3IEJOKDApLl9mb3JjZVJlZCh0aGlzKTtcblxuICAgIHZhciB0ID0gYS5tdWwoYik7XG4gICAgdmFyIGMgPSB0Lm1hc2tuKHRoaXMuc2hpZnQpLm11bCh0aGlzLm1pbnYpLmltYXNrbih0aGlzLnNoaWZ0KS5tdWwodGhpcy5tKTtcbiAgICB2YXIgdSA9IHQuaXN1YihjKS5pdXNocm4odGhpcy5zaGlmdCk7XG4gICAgdmFyIHJlcyA9IHU7XG4gICAgaWYgKHUuY21wKHRoaXMubSkgPj0gMCkge1xuICAgICAgcmVzID0gdS5pc3ViKHRoaXMubSk7XG4gICAgfSBlbHNlIGlmICh1LmNtcG4oMCkgPCAwKSB7XG4gICAgICByZXMgPSB1LmlhZGQodGhpcy5tKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzLl9mb3JjZVJlZCh0aGlzKTtcbiAgfTtcblxuICBNb250LnByb3RvdHlwZS5pbnZtID0gZnVuY3Rpb24gaW52bSAoYSkge1xuICAgIC8vIChBUileLTEgKiBSXjIgPSAoQV4tMSAqIFJeLTEpICogUl4yID0gQV4tMSAqIFJcbiAgICB2YXIgcmVzID0gdGhpcy5pbW9kKGEuX2ludm1wKHRoaXMubSkubXVsKHRoaXMucjIpKTtcbiAgICByZXR1cm4gcmVzLl9mb3JjZVJlZCh0aGlzKTtcbiAgfTtcbn0pKHR5cGVvZiBtb2R1bGUgPT09ICd1bmRlZmluZWQnIHx8IG1vZHVsZSwgdGhpcyk7XG5cbn0se1wiYnVmZmVyXCI6MTAzfV0sOTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gYm91bmRhcnlcblxuZnVuY3Rpb24gYm91bmRhcnkgKGNlbGxzKSB7XG4gIHZhciBpLCBqLCBrXG4gIHZhciBuID0gY2VsbHMubGVuZ3RoXG4gIHZhciBzeiA9IDBcbiAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgIHN6ICs9IGNlbGxzW2ldLmxlbmd0aFxuICB9XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkoc3opXG4gIHZhciBwdHIgPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgdmFyIGQgPSBjLmxlbmd0aFxuICAgIGZvciAoaiA9IDA7IGogPCBkOyArK2opIHtcbiAgICAgIHZhciBiID0gcmVzdWx0W3B0cisrXSA9IG5ldyBBcnJheShkIC0gMSlcbiAgICAgIHZhciBwID0gMFxuICAgICAgZm9yIChrID0gMDsgayA8IGQ7ICsraykge1xuICAgICAgICBpZiAoayA9PT0gaikge1xuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgICAgYltwKytdID0gY1trXVxuICAgICAgfVxuICAgICAgaWYgKGogJiAxKSB7XG4gICAgICAgIHZhciB0bXAgPSBiWzFdXG4gICAgICAgIGJbMV0gPSBiWzBdXG4gICAgICAgIGJbMF0gPSB0bXBcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG59LHt9XSw5NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBib3hJbnRlcnNlY3RXcmFwcGVyXG5cbnZhciBwb29sID0gX2RlcmVxXygndHlwZWRhcnJheS1wb29sJylcbnZhciBzd2VlcCA9IF9kZXJlcV8oJy4vbGliL3N3ZWVwJylcbnZhciBib3hJbnRlcnNlY3RJdGVyID0gX2RlcmVxXygnLi9saWIvaW50ZXJzZWN0JylcblxuZnVuY3Rpb24gYm94RW1wdHkoZCwgYm94KSB7XG4gIGZvcih2YXIgaj0wOyBqPGQ7ICsraikge1xuICAgIGlmKCEoYm94W2pdIDw9IGJveFtqK2RdKSkge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlXG59XG5cbi8vVW5wYWNrIGJveGVzIGludG8gYSBmbGF0IHR5cGVkIGFycmF5LCByZW1vdmUgZW1wdHkgYm94ZXNcbmZ1bmN0aW9uIGNvbnZlcnRCb3hlcyhib3hlcywgZCwgZGF0YSwgaWRzKSB7XG4gIHZhciBwdHIgPSAwXG4gIHZhciBjb3VudCA9IDBcbiAgZm9yKHZhciBpPTAsIG49Ym94ZXMubGVuZ3RoOyBpPG47ICsraSkge1xuICAgIHZhciBiID0gYm94ZXNbaV1cbiAgICBpZihib3hFbXB0eShkLCBiKSkge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgZm9yKHZhciBqPTA7IGo8MipkOyArK2opIHtcbiAgICAgIGRhdGFbcHRyKytdID0gYltqXVxuICAgIH1cbiAgICBpZHNbY291bnQrK10gPSBpXG4gIH1cbiAgcmV0dXJuIGNvdW50XG59XG5cbi8vUGVyZm9ybSB0eXBlIGNvbnZlcnNpb25zLCBjaGVjayBib3VuZHNcbmZ1bmN0aW9uIGJveEludGVyc2VjdChyZWQsIGJsdWUsIHZpc2l0LCBmdWxsKSB7XG4gIHZhciBuID0gcmVkLmxlbmd0aFxuICB2YXIgbSA9IGJsdWUubGVuZ3RoXG5cbiAgLy9JZiBlaXRoZXIgYXJyYXkgaXMgZW1wdHksIHRoZW4gd2UgY2FuIHNraXAgdGhpcyB3aG9sZSB0aGluZ1xuICBpZihuIDw9IDAgfHwgbSA8PSAwKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICAvL0NvbXB1dGUgZGltZW5zaW9uLCBpZiBpdCBpcyAwIHRoZW4gd2Ugc2tpcFxuICB2YXIgZCA9IChyZWRbMF0ubGVuZ3RoKT4+PjFcbiAgaWYoZCA8PSAwKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICB2YXIgcmV0dmFsXG5cbiAgLy9Db252ZXJ0IHJlZCBib3hlc1xuICB2YXIgcmVkTGlzdCAgPSBwb29sLm1hbGxvY0RvdWJsZSgyKmQqbilcbiAgdmFyIHJlZElkcyAgID0gcG9vbC5tYWxsb2NJbnQzMihuKVxuICBuID0gY29udmVydEJveGVzKHJlZCwgZCwgcmVkTGlzdCwgcmVkSWRzKVxuXG4gIGlmKG4gPiAwKSB7XG4gICAgaWYoZCA9PT0gMSAmJiBmdWxsKSB7XG4gICAgICAvL1NwZWNpYWwgY2FzZTogMWQgY29tcGxldGVcbiAgICAgIHN3ZWVwLmluaXQobilcbiAgICAgIHJldHZhbCA9IHN3ZWVwLnN3ZWVwQ29tcGxldGUoXG4gICAgICAgIGQsIHZpc2l0LCBcbiAgICAgICAgMCwgbiwgcmVkTGlzdCwgcmVkSWRzLFxuICAgICAgICAwLCBuLCByZWRMaXN0LCByZWRJZHMpXG4gICAgfSBlbHNlIHtcblxuICAgICAgLy9Db252ZXJ0IGJsdWUgYm94ZXNcbiAgICAgIHZhciBibHVlTGlzdCA9IHBvb2wubWFsbG9jRG91YmxlKDIqZCptKVxuICAgICAgdmFyIGJsdWVJZHMgID0gcG9vbC5tYWxsb2NJbnQzMihtKVxuICAgICAgbSA9IGNvbnZlcnRCb3hlcyhibHVlLCBkLCBibHVlTGlzdCwgYmx1ZUlkcylcblxuICAgICAgaWYobSA+IDApIHtcbiAgICAgICAgc3dlZXAuaW5pdChuK20pXG5cbiAgICAgICAgaWYoZCA9PT0gMSkge1xuICAgICAgICAgIC8vU3BlY2lhbCBjYXNlOiAxZCBiaXBhcnRpdGVcbiAgICAgICAgICByZXR2YWwgPSBzd2VlcC5zd2VlcEJpcGFydGl0ZShcbiAgICAgICAgICAgIGQsIHZpc2l0LCBcbiAgICAgICAgICAgIDAsIG4sIHJlZExpc3QsICByZWRJZHMsXG4gICAgICAgICAgICAwLCBtLCBibHVlTGlzdCwgYmx1ZUlkcylcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvL0dlbmVyYWwgY2FzZTogIGQ+MVxuICAgICAgICAgIHJldHZhbCA9IGJveEludGVyc2VjdEl0ZXIoXG4gICAgICAgICAgICBkLCB2aXNpdCwgICAgZnVsbCxcbiAgICAgICAgICAgIG4sIHJlZExpc3QsICByZWRJZHMsXG4gICAgICAgICAgICBtLCBibHVlTGlzdCwgYmx1ZUlkcylcbiAgICAgICAgfVxuXG4gICAgICAgIHBvb2wuZnJlZShibHVlTGlzdClcbiAgICAgICAgcG9vbC5mcmVlKGJsdWVJZHMpXG4gICAgICB9XG4gICAgfVxuXG4gICAgcG9vbC5mcmVlKHJlZExpc3QpXG4gICAgcG9vbC5mcmVlKHJlZElkcylcbiAgfVxuXG4gIHJldHVybiByZXR2YWxcbn1cblxuXG52YXIgUkVTVUxUXG5cbmZ1bmN0aW9uIGFwcGVuZEl0ZW0oaSxqKSB7XG4gIFJFU1VMVC5wdXNoKFtpLGpdKVxufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3RGdWxsQXJyYXkoeCkge1xuICBSRVNVTFQgPSBbXVxuICBib3hJbnRlcnNlY3QoeCwgeCwgYXBwZW5kSXRlbSwgdHJ1ZSlcbiAgcmV0dXJuIFJFU1VMVFxufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3RCaXBhcnRpdGVBcnJheSh4LCB5KSB7XG4gIFJFU1VMVCA9IFtdXG4gIGJveEludGVyc2VjdCh4LCB5LCBhcHBlbmRJdGVtLCBmYWxzZSlcbiAgcmV0dXJuIFJFU1VMVFxufVxuXG4vL1VzZXItZnJpZW5kbHkgd3JhcHBlciwgaGFuZGxlIGZ1bGwgaW5wdXQgYW5kIG5vLXZpc2l0b3IgY2FzZXNcbmZ1bmN0aW9uIGJveEludGVyc2VjdFdyYXBwZXIoYXJnMCwgYXJnMSwgYXJnMikge1xuICB2YXIgcmVzdWx0XG4gIHN3aXRjaChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgY2FzZSAxOlxuICAgICAgcmV0dXJuIGludGVyc2VjdEZ1bGxBcnJheShhcmcwKVxuICAgIGNhc2UgMjpcbiAgICAgIGlmKHR5cGVvZiBhcmcxID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBib3hJbnRlcnNlY3QoYXJnMCwgYXJnMCwgYXJnMSwgdHJ1ZSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBpbnRlcnNlY3RCaXBhcnRpdGVBcnJheShhcmcwLCBhcmcxKVxuICAgICAgfVxuICAgIGNhc2UgMzpcbiAgICAgIHJldHVybiBib3hJbnRlcnNlY3QoYXJnMCwgYXJnMSwgYXJnMiwgZmFsc2UpXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignYm94LWludGVyc2VjdDogSW52YWxpZCBhcmd1bWVudHMnKVxuICB9XG59XG59LHtcIi4vbGliL2ludGVyc2VjdFwiOjk4LFwiLi9saWIvc3dlZXBcIjoxMDIsXCJ0eXBlZGFycmF5LXBvb2xcIjo1NDV9XSw5NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIERJTUVOU0lPTiAgID0gJ2QnXG52YXIgQVhJUyAgICAgICAgPSAnYXgnXG52YXIgVklTSVQgICAgICAgPSAndnYnXG52YXIgRkxJUCAgICAgICAgPSAnZnAnXG5cbnZhciBFTEVNX1NJWkUgICA9ICdlcydcblxudmFyIFJFRF9TVEFSVCAgID0gJ3JzJ1xudmFyIFJFRF9FTkQgICAgID0gJ3JlJ1xudmFyIFJFRF9CT1hFUyAgID0gJ3JiJ1xudmFyIFJFRF9JTkRFWCAgID0gJ3JpJ1xudmFyIFJFRF9QVFIgICAgID0gJ3JwJ1xuXG52YXIgQkxVRV9TVEFSVCAgPSAnYnMnXG52YXIgQkxVRV9FTkQgICAgPSAnYmUnXG52YXIgQkxVRV9CT1hFUyAgPSAnYmInXG52YXIgQkxVRV9JTkRFWCAgPSAnYmknXG52YXIgQkxVRV9QVFIgICAgPSAnYnAnXG5cbnZhciBSRVRWQUwgICAgICA9ICdydidcblxudmFyIElOTkVSX0xBQkVMID0gJ1EnXG5cbnZhciBBUkdTID0gW1xuICBESU1FTlNJT04sXG4gIEFYSVMsXG4gIFZJU0lULFxuICBSRURfU1RBUlQsXG4gIFJFRF9FTkQsXG4gIFJFRF9CT1hFUyxcbiAgUkVEX0lOREVYLFxuICBCTFVFX1NUQVJULFxuICBCTFVFX0VORCxcbiAgQkxVRV9CT1hFUyxcbiAgQkxVRV9JTkRFWFxuXVxuXG5mdW5jdGlvbiBnZW5lcmF0ZUJydXRlRm9yY2UocmVkTWFqb3IsIGZsaXAsIGZ1bGwpIHtcbiAgdmFyIGZ1bmNOYW1lID0gJ2JydXRlRm9yY2UnICsgXG4gICAgKHJlZE1ham9yID8gJ1JlZCcgOiAnQmx1ZScpICsgXG4gICAgKGZsaXAgPyAnRmxpcCcgOiAnJykgK1xuICAgIChmdWxsID8gJ0Z1bGwnIDogJycpXG5cbiAgdmFyIGNvZGUgPSBbJ2Z1bmN0aW9uICcsIGZ1bmNOYW1lLCAnKCcsIEFSR1Muam9pbigpLCAnKXsnLFxuICAgICd2YXIgJywgRUxFTV9TSVpFLCAnPTIqJywgRElNRU5TSU9OLCAnOyddXG5cbiAgdmFyIHJlZExvb3AgPSBcbiAgICAnZm9yKHZhciBpPScgKyBSRURfU1RBUlQgKyAnLCcgKyBSRURfUFRSICsgJz0nICsgRUxFTV9TSVpFICsgJyonICsgUkVEX1NUQVJUICsgJzsnICtcbiAgICAgICAgJ2k8JyArIFJFRF9FTkQgKyc7JyArXG4gICAgICAgICcrK2ksJyArIFJFRF9QVFIgKyAnKz0nICsgRUxFTV9TSVpFICsgJyl7JyArXG4gICAgICAgICd2YXIgeDA9JyArIFJFRF9CT1hFUyArICdbJyArIEFYSVMgKyAnKycgKyBSRURfUFRSICsgJ10sJyArXG4gICAgICAgICAgICAneDE9JyArIFJFRF9CT1hFUyArICdbJyArIEFYSVMgKyAnKycgKyBSRURfUFRSICsgJysnICsgRElNRU5TSU9OICsgJ10sJyArXG4gICAgICAgICAgICAneGk9JyArIFJFRF9JTkRFWCArICdbaV07J1xuXG4gIHZhciBibHVlTG9vcCA9IFxuICAgICdmb3IodmFyIGo9JyArIEJMVUVfU1RBUlQgKyAnLCcgKyBCTFVFX1BUUiArICc9JyArIEVMRU1fU0laRSArICcqJyArIEJMVUVfU1RBUlQgKyAnOycgK1xuICAgICAgICAnajwnICsgQkxVRV9FTkQgKyAnOycgK1xuICAgICAgICAnKytqLCcgKyBCTFVFX1BUUiArICcrPScgKyBFTEVNX1NJWkUgKyAnKXsnICtcbiAgICAgICAgJ3ZhciB5MD0nICsgQkxVRV9CT1hFUyArICdbJyArIEFYSVMgKyAnKycgKyBCTFVFX1BUUiArICddLCcgK1xuICAgICAgICAgICAgKGZ1bGwgPyAneTE9JyArIEJMVUVfQk9YRVMgKyAnWycgKyBBWElTICsgJysnICsgQkxVRV9QVFIgKyAnKycgKyBESU1FTlNJT04gKyAnXSwnIDogJycpICtcbiAgICAgICAgICAgICd5aT0nICsgQkxVRV9JTkRFWCArICdbal07J1xuXG4gIGlmKHJlZE1ham9yKSB7XG4gICAgY29kZS5wdXNoKHJlZExvb3AsIElOTkVSX0xBQkVMLCAnOicsIGJsdWVMb29wKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChibHVlTG9vcCwgSU5ORVJfTEFCRUwsICc6JywgcmVkTG9vcClcbiAgfVxuXG4gIGlmKGZ1bGwpIHtcbiAgICBjb2RlLnB1c2goJ2lmKHkxPHgwfHx4MTx5MCljb250aW51ZTsnKVxuICB9IGVsc2UgaWYoZmxpcCkge1xuICAgIGNvZGUucHVzaCgnaWYoeTA8PXgwfHx4MTx5MCljb250aW51ZTsnKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaCgnaWYoeTA8eDB8fHgxPHkwKWNvbnRpbnVlOycpXG4gIH1cblxuICBjb2RlLnB1c2goJ2Zvcih2YXIgaz0nK0FYSVMrJysxO2s8JytESU1FTlNJT04rJzsrK2speycrXG4gICAgJ3ZhciByMD0nK1JFRF9CT1hFUysnW2srJytSRURfUFRSKyddLCcrXG4gICAgICAgICdyMT0nK1JFRF9CT1hFUysnW2srJytESU1FTlNJT04rJysnK1JFRF9QVFIrJ10sJytcbiAgICAgICAgJ2IwPScrQkxVRV9CT1hFUysnW2srJytCTFVFX1BUUisnXSwnK1xuICAgICAgICAnYjE9JytCTFVFX0JPWEVTKydbaysnK0RJTUVOU0lPTisnKycrQkxVRV9QVFIrJ107JytcbiAgICAgICdpZihyMTxiMHx8YjE8cjApY29udGludWUgJyArIElOTkVSX0xBQkVMICsgJzt9JyArXG4gICAgICAndmFyICcgKyBSRVRWQUwgKyAnPScgKyBWSVNJVCArICcoJylcblxuICBpZihmbGlwKSB7XG4gICAgY29kZS5wdXNoKCd5aSx4aScpXG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKCd4aSx5aScpXG4gIH1cblxuICBjb2RlLnB1c2goJyk7aWYoJyArIFJFVFZBTCArICchPT12b2lkIDApcmV0dXJuICcgKyBSRVRWQUwgKyAnO319fScpXG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBmdW5jTmFtZSwgXG4gICAgY29kZTogY29kZS5qb2luKCcnKVxuICB9XG59XG5cbmZ1bmN0aW9uIGJydXRlRm9yY2VQbGFubmVyKGZ1bGwpIHtcbiAgdmFyIGZ1bmNOYW1lID0gJ2JydXRlRm9yY2UnICsgKGZ1bGwgPyAnRnVsbCcgOiAnUGFydGlhbCcpXG4gIHZhciBwcmVmaXggPSBbXVxuICB2YXIgZmFyZ3MgPSBBUkdTLnNsaWNlKClcbiAgaWYoIWZ1bGwpIHtcbiAgICBmYXJncy5zcGxpY2UoMywgMCwgRkxJUClcbiAgfVxuXG4gIHZhciBjb2RlID0gWydmdW5jdGlvbiAnICsgZnVuY05hbWUgKyAnKCcgKyBmYXJncy5qb2luKCkgKyAnKXsnXVxuXG4gIGZ1bmN0aW9uIGludm9rZShyZWRNYWpvciwgZmxpcCkge1xuICAgIHZhciByZXMgPSBnZW5lcmF0ZUJydXRlRm9yY2UocmVkTWFqb3IsIGZsaXAsIGZ1bGwpXG4gICAgcHJlZml4LnB1c2gocmVzLmNvZGUpXG4gICAgY29kZS5wdXNoKCdyZXR1cm4gJyArIHJlcy5uYW1lICsgJygnICsgQVJHUy5qb2luKCkgKyAnKTsnKVxuICB9XG5cbiAgY29kZS5wdXNoKCdpZignICsgUkVEX0VORCArICctJyArIFJFRF9TVEFSVCArICc+JyArXG4gICAgICAgICAgICAgICAgICAgIEJMVUVfRU5EICsgJy0nICsgQkxVRV9TVEFSVCArICcpeycpXG5cbiAgaWYoZnVsbCkge1xuICAgIGludm9rZSh0cnVlLCBmYWxzZSlcbiAgICBjb2RlLnB1c2goJ31lbHNleycpXG4gICAgaW52b2tlKGZhbHNlLCBmYWxzZSlcbiAgfSBlbHNlIHtcbiAgICBjb2RlLnB1c2goJ2lmKCcgKyBGTElQICsgJyl7JylcbiAgICBpbnZva2UodHJ1ZSwgdHJ1ZSlcbiAgICBjb2RlLnB1c2goJ31lbHNleycpXG4gICAgaW52b2tlKHRydWUsIGZhbHNlKVxuICAgIGNvZGUucHVzaCgnfX1lbHNle2lmKCcgKyBGTElQICsgJyl7JylcbiAgICBpbnZva2UoZmFsc2UsIHRydWUpXG4gICAgY29kZS5wdXNoKCd9ZWxzZXsnKVxuICAgIGludm9rZShmYWxzZSwgZmFsc2UpXG4gICAgY29kZS5wdXNoKCd9JylcbiAgfVxuICBjb2RlLnB1c2goJ319cmV0dXJuICcgKyBmdW5jTmFtZSlcblxuICB2YXIgY29kZVN0ciA9IHByZWZpeC5qb2luKCcnKSArIGNvZGUuam9pbignJylcbiAgdmFyIHByb2MgPSBuZXcgRnVuY3Rpb24oY29kZVN0cilcbiAgcmV0dXJuIHByb2MoKVxufVxuXG5cbmV4cG9ydHMucGFydGlhbCA9IGJydXRlRm9yY2VQbGFubmVyKGZhbHNlKVxuZXhwb3J0cy5mdWxsICAgID0gYnJ1dGVGb3JjZVBsYW5uZXIodHJ1ZSlcbn0se31dLDk4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJveEludGVyc2VjdEl0ZXJcblxudmFyIHBvb2wgPSBfZGVyZXFfKCd0eXBlZGFycmF5LXBvb2wnKVxudmFyIGJpdHMgPSBfZGVyZXFfKCdiaXQtdHdpZGRsZScpXG52YXIgYnJ1dGVGb3JjZSA9IF9kZXJlcV8oJy4vYnJ1dGUnKVxudmFyIGJydXRlRm9yY2VQYXJ0aWFsID0gYnJ1dGVGb3JjZS5wYXJ0aWFsXG52YXIgYnJ1dGVGb3JjZUZ1bGwgPSBicnV0ZUZvcmNlLmZ1bGxcbnZhciBzd2VlcCA9IF9kZXJlcV8oJy4vc3dlZXAnKVxudmFyIGZpbmRNZWRpYW4gPSBfZGVyZXFfKCcuL21lZGlhbicpXG52YXIgZ2VuUGFydGl0aW9uID0gX2RlcmVxXygnLi9wYXJ0aXRpb24nKVxuXG4vL1R3aWRkbGUgcGFyYW1ldGVyc1xudmFyIEJSVVRFX0ZPUkNFX0NVVE9GRiAgICA9IDEyOCAgICAgICAvL0N1dCBvZmYgZm9yIGJydXRlIGZvcmNlIHNlYXJjaFxudmFyIFNDQU5fQ1VUT0ZGICAgICAgICAgICA9ICgxPDwyMikgICAvL0N1dCBvZmYgZm9yIHR3byB3YXkgc2NhblxudmFyIFNDQU5fQ09NUExFVEVfQ1VUT0ZGICA9ICgxPDwyMikgIFxuXG4vL1BhcnRpdGlvbiBmdW5jdGlvbnNcbnZhciBwYXJ0aXRpb25JbnRlcmlvckNvbnRhaW5zSW50ZXJ2YWwgPSBnZW5QYXJ0aXRpb24oXG4gICchKGxvPj1wMCkmJiEocDE+PWhpKScsIFxuICBbJ3AwJywgJ3AxJ10pXG5cbnZhciBwYXJ0aXRpb25TdGFydEVxdWFsID0gZ2VuUGFydGl0aW9uKFxuICAnbG89PT1wMCcsXG4gIFsncDAnXSlcblxudmFyIHBhcnRpdGlvblN0YXJ0TGVzc1RoYW4gPSBnZW5QYXJ0aXRpb24oXG4gICdsbzxwMCcsXG4gIFsncDAnXSlcblxudmFyIHBhcnRpdGlvbkVuZExlc3NUaGFuRXF1YWwgPSBnZW5QYXJ0aXRpb24oXG4gICdoaTw9cDAnLFxuICBbJ3AwJ10pXG5cbnZhciBwYXJ0aXRpb25Db250YWluc1BvaW50ID0gZ2VuUGFydGl0aW9uKFxuICAnbG88PXAwJiZwMDw9aGknLFxuICBbJ3AwJ10pXG5cbnZhciBwYXJ0aXRpb25Db250YWluc1BvaW50UHJvcGVyID0gZ2VuUGFydGl0aW9uKFxuICAnbG88cDAmJnAwPD1oaScsXG4gIFsncDAnXSlcblxuLy9GcmFtZSBzaXplIGZvciBpdGVyYXRpdmUgbG9vcFxudmFyIElGUkFNRV9TSVpFID0gNlxudmFyIERGUkFNRV9TSVpFID0gMlxuXG4vL0RhdGEgZm9yIGJveCBzdGF0Y2tcbnZhciBJTklUX0NBUEFDSVRZID0gMTAyNFxudmFyIEJPWF9JU1RBQ0sgID0gcG9vbC5tYWxsb2NJbnQzMihJTklUX0NBUEFDSVRZKVxudmFyIEJPWF9EU1RBQ0sgID0gcG9vbC5tYWxsb2NEb3VibGUoSU5JVF9DQVBBQ0lUWSlcblxuLy9Jbml0aWFsaXplIGl0ZXJhdGl2ZSBsb29wIHF1ZXVlXG5mdW5jdGlvbiBpdGVySW5pdChkLCBjb3VudCkge1xuICB2YXIgbGV2ZWxzID0gKDggKiBiaXRzLmxvZzIoY291bnQrMSkgKiAoZCsxKSl8MFxuICB2YXIgbWF4SW50cyA9IGJpdHMubmV4dFBvdzIoSUZSQU1FX1NJWkUqbGV2ZWxzKVxuICBpZihCT1hfSVNUQUNLLmxlbmd0aCA8IG1heEludHMpIHtcbiAgICBwb29sLmZyZWUoQk9YX0lTVEFDSylcbiAgICBCT1hfSVNUQUNLID0gcG9vbC5tYWxsb2NJbnQzMihtYXhJbnRzKVxuICB9XG4gIHZhciBtYXhEb3VibGVzID0gYml0cy5uZXh0UG93MihERlJBTUVfU0laRSpsZXZlbHMpXG4gIGlmKEJPWF9EU1RBQ0sgPCBtYXhEb3VibGVzKSB7XG4gICAgcG9vbC5mcmVlKEJPWF9EU1RBQ0spXG4gICAgQk9YX0RTVEFDSyA9IHBvb2wubWFsbG9jRG91YmxlKG1heERvdWJsZXMpXG4gIH1cbn1cblxuLy9BcHBlbmQgaXRlbSB0byBxdWV1ZVxuZnVuY3Rpb24gaXRlclB1c2gocHRyLFxuICBheGlzLCBcbiAgcmVkU3RhcnQsIHJlZEVuZCwgXG4gIGJsdWVTdGFydCwgYmx1ZUVuZCwgXG4gIHN0YXRlLCBcbiAgbG8sIGhpKSB7XG5cbiAgdmFyIGlwdHIgPSBJRlJBTUVfU0laRSAqIHB0clxuICBCT1hfSVNUQUNLW2lwdHJdICAgPSBheGlzXG4gIEJPWF9JU1RBQ0tbaXB0cisxXSA9IHJlZFN0YXJ0XG4gIEJPWF9JU1RBQ0tbaXB0cisyXSA9IHJlZEVuZFxuICBCT1hfSVNUQUNLW2lwdHIrM10gPSBibHVlU3RhcnRcbiAgQk9YX0lTVEFDS1tpcHRyKzRdID0gYmx1ZUVuZFxuICBCT1hfSVNUQUNLW2lwdHIrNV0gPSBzdGF0ZVxuXG4gIHZhciBkcHRyID0gREZSQU1FX1NJWkUgKiBwdHJcbiAgQk9YX0RTVEFDS1tkcHRyXSAgID0gbG9cbiAgQk9YX0RTVEFDS1tkcHRyKzFdID0gaGlcbn1cblxuLy9TcGVjaWFsIGNhc2U6ICBJbnRlcnNlY3Qgc2luZ2xlIHBvaW50IHdpdGggbGlzdCBvZiBpbnRlcnZhbHNcbmZ1bmN0aW9uIG9uZVBvaW50UGFydGlhbChcbiAgZCwgYXhpcywgdmlzaXQsIGZsaXAsXG4gIHJlZFN0YXJ0LCByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gIGJsdWVPZmZzZXQsIGJsdWUsIGJsdWVJZCkge1xuXG4gIHZhciBlbGVtU2l6ZSA9IDIgKiBkXG4gIHZhciBibHVlUHRyICA9IGJsdWVPZmZzZXQgKiBlbGVtU2l6ZVxuICB2YXIgYmx1ZVggICAgPSBibHVlW2JsdWVQdHIgKyBheGlzXVxuXG5yZWRfbG9vcDpcbiAgZm9yKHZhciBpPXJlZFN0YXJ0LCByZWRQdHI9cmVkU3RhcnQqZWxlbVNpemU7IGk8cmVkRW5kOyArK2ksIHJlZFB0cis9ZWxlbVNpemUpIHtcbiAgICB2YXIgcjAgPSByZWRbcmVkUHRyK2F4aXNdXG4gICAgdmFyIHIxID0gcmVkW3JlZFB0citheGlzK2RdXG4gICAgaWYoYmx1ZVggPCByMCB8fCByMSA8IGJsdWVYKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBpZihmbGlwICYmIGJsdWVYID09PSByMCkge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgdmFyIHJlZElkID0gcmVkSW5kZXhbaV1cbiAgICBmb3IodmFyIGo9YXhpcysxOyBqPGQ7ICsraikge1xuICAgICAgdmFyIHIwID0gcmVkW3JlZFB0citqXVxuICAgICAgdmFyIHIxID0gcmVkW3JlZFB0citqK2RdXG4gICAgICB2YXIgYjAgPSBibHVlW2JsdWVQdHIral1cbiAgICAgIHZhciBiMSA9IGJsdWVbYmx1ZVB0citqK2RdXG4gICAgICBpZihyMSA8IGIwIHx8IGIxIDwgcjApIHtcbiAgICAgICAgY29udGludWUgcmVkX2xvb3BcbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIHJldHZhbFxuICAgIGlmKGZsaXApIHtcbiAgICAgIHJldHZhbCA9IHZpc2l0KGJsdWVJZCwgcmVkSWQpXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHZhbCA9IHZpc2l0KHJlZElkLCBibHVlSWQpXG4gICAgfVxuICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICByZXR1cm4gcmV0dmFsXG4gICAgfVxuICB9XG59XG5cbi8vU3BlY2lhbCBjYXNlOiAgSW50ZXJzZWN0IG9uZSBwb2ludCB3aXRoIGxpc3Qgb2YgaW50ZXJ2YWxzXG5mdW5jdGlvbiBvbmVQb2ludEZ1bGwoXG4gIGQsIGF4aXMsIHZpc2l0LFxuICByZWRTdGFydCwgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICBibHVlT2Zmc2V0LCBibHVlLCBibHVlSWQpIHtcblxuICB2YXIgZWxlbVNpemUgPSAyICogZFxuICB2YXIgYmx1ZVB0ciAgPSBibHVlT2Zmc2V0ICogZWxlbVNpemVcbiAgdmFyIGJsdWVYICAgID0gYmx1ZVtibHVlUHRyICsgYXhpc11cblxucmVkX2xvb3A6XG4gIGZvcih2YXIgaT1yZWRTdGFydCwgcmVkUHRyPXJlZFN0YXJ0KmVsZW1TaXplOyBpPHJlZEVuZDsgKytpLCByZWRQdHIrPWVsZW1TaXplKSB7XG4gICAgdmFyIHJlZElkID0gcmVkSW5kZXhbaV1cbiAgICBpZihyZWRJZCA9PT0gYmx1ZUlkKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICB2YXIgcjAgPSByZWRbcmVkUHRyK2F4aXNdXG4gICAgdmFyIHIxID0gcmVkW3JlZFB0citheGlzK2RdXG4gICAgaWYoYmx1ZVggPCByMCB8fCByMSA8IGJsdWVYKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBmb3IodmFyIGo9YXhpcysxOyBqPGQ7ICsraikge1xuICAgICAgdmFyIHIwID0gcmVkW3JlZFB0citqXVxuICAgICAgdmFyIHIxID0gcmVkW3JlZFB0citqK2RdXG4gICAgICB2YXIgYjAgPSBibHVlW2JsdWVQdHIral1cbiAgICAgIHZhciBiMSA9IGJsdWVbYmx1ZVB0citqK2RdXG4gICAgICBpZihyMSA8IGIwIHx8IGIxIDwgcjApIHtcbiAgICAgICAgY29udGludWUgcmVkX2xvb3BcbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIHJldHZhbCA9IHZpc2l0KHJlZElkLCBibHVlSWQpXG4gICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgIHJldHVybiByZXR2YWxcbiAgICB9XG4gIH1cbn1cblxuLy9UaGUgbWFpbiBib3ggaW50ZXJzZWN0aW9uIHJvdXRpbmVcbmZ1bmN0aW9uIGJveEludGVyc2VjdEl0ZXIoXG4gIGQsIHZpc2l0LCBpbml0RnVsbCxcbiAgeFNpemUsIHhCb3hlcywgeEluZGV4LFxuICB5U2l6ZSwgeUJveGVzLCB5SW5kZXgpIHtcblxuICAvL1Jlc2VydmUgbWVtb3J5IGZvciBzdGFja1xuICBpdGVySW5pdChkLCB4U2l6ZSArIHlTaXplKVxuXG4gIHZhciB0b3AgID0gMFxuICB2YXIgZWxlbVNpemUgPSAyICogZFxuICB2YXIgcmV0dmFsXG5cbiAgaXRlclB1c2godG9wKyssXG4gICAgICAwLFxuICAgICAgMCwgeFNpemUsXG4gICAgICAwLCB5U2l6ZSxcbiAgICAgIGluaXRGdWxsID8gMTYgOiAwLCBcbiAgICAgIC1JbmZpbml0eSwgSW5maW5pdHkpXG4gIGlmKCFpbml0RnVsbCkge1xuICAgIGl0ZXJQdXNoKHRvcCsrLFxuICAgICAgMCxcbiAgICAgIDAsIHlTaXplLFxuICAgICAgMCwgeFNpemUsXG4gICAgICAxLCBcbiAgICAgIC1JbmZpbml0eSwgSW5maW5pdHkpXG4gIH1cblxuICB3aGlsZSh0b3AgPiAwKSB7XG4gICAgdG9wICAtPSAxXG5cbiAgICB2YXIgaXB0ciA9IHRvcCAqIElGUkFNRV9TSVpFXG4gICAgdmFyIGF4aXMgICAgICA9IEJPWF9JU1RBQ0tbaXB0cl1cbiAgICB2YXIgcmVkU3RhcnQgID0gQk9YX0lTVEFDS1tpcHRyKzFdXG4gICAgdmFyIHJlZEVuZCAgICA9IEJPWF9JU1RBQ0tbaXB0cisyXVxuICAgIHZhciBibHVlU3RhcnQgPSBCT1hfSVNUQUNLW2lwdHIrM11cbiAgICB2YXIgYmx1ZUVuZCAgID0gQk9YX0lTVEFDS1tpcHRyKzRdXG4gICAgdmFyIHN0YXRlICAgICA9IEJPWF9JU1RBQ0tbaXB0cis1XVxuXG4gICAgdmFyIGRwdHIgPSB0b3AgKiBERlJBTUVfU0laRVxuICAgIHZhciBsbyAgICAgICAgPSBCT1hfRFNUQUNLW2RwdHJdXG4gICAgdmFyIGhpICAgICAgICA9IEJPWF9EU1RBQ0tbZHB0cisxXVxuXG4gICAgLy9VbnBhY2sgc3RhdGUgaW5mb1xuICAgIHZhciBmbGlwICAgICAgPSAoc3RhdGUgJiAxKVxuICAgIHZhciBmdWxsICAgICAgPSAhIShzdGF0ZSAmIDE2KVxuXG4gICAgLy9VbnBhY2sgaW5kaWNlc1xuICAgIHZhciByZWQgICAgICAgPSB4Qm94ZXNcbiAgICB2YXIgcmVkSW5kZXggID0geEluZGV4XG4gICAgdmFyIGJsdWUgICAgICA9IHlCb3hlc1xuICAgIHZhciBibHVlSW5kZXggPSB5SW5kZXhcbiAgICBpZihmbGlwKSB7XG4gICAgICByZWQgICAgICAgICA9IHlCb3hlc1xuICAgICAgcmVkSW5kZXggICAgPSB5SW5kZXhcbiAgICAgIGJsdWUgICAgICAgID0geEJveGVzXG4gICAgICBibHVlSW5kZXggICA9IHhJbmRleFxuICAgIH1cblxuICAgIGlmKHN0YXRlICYgMikge1xuICAgICAgcmVkRW5kID0gcGFydGl0aW9uU3RhcnRMZXNzVGhhbihcbiAgICAgICAgZCwgYXhpcyxcbiAgICAgICAgcmVkU3RhcnQsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgICAgICAgaGkpXG4gICAgICBpZihyZWRTdGFydCA+PSByZWRFbmQpIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICB9XG4gICAgaWYoc3RhdGUgJiA0KSB7XG4gICAgICByZWRTdGFydCA9IHBhcnRpdGlvbkVuZExlc3NUaGFuRXF1YWwoXG4gICAgICAgIGQsIGF4aXMsXG4gICAgICAgIHJlZFN0YXJ0LCByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgIGxvKVxuICAgICAgaWYocmVkU3RhcnQgPj0gcmVkRW5kKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIHZhciByZWRDb3VudCAgPSByZWRFbmQgIC0gcmVkU3RhcnRcbiAgICB2YXIgYmx1ZUNvdW50ID0gYmx1ZUVuZCAtIGJsdWVTdGFydFxuXG4gICAgaWYoZnVsbCkge1xuICAgICAgaWYoZCAqIHJlZENvdW50ICogKHJlZENvdW50ICsgYmx1ZUNvdW50KSA8IFNDQU5fQ09NUExFVEVfQ1VUT0ZGKSB7XG4gICAgICAgIHJldHZhbCA9IHN3ZWVwLnNjYW5Db21wbGV0ZShcbiAgICAgICAgICBkLCBheGlzLCB2aXNpdCwgXG4gICAgICAgICAgcmVkU3RhcnQsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgICAgICAgICBibHVlU3RhcnQsIGJsdWVFbmQsIGJsdWUsIGJsdWVJbmRleClcbiAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgIH1cbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYoZCAqIE1hdGgubWluKHJlZENvdW50LCBibHVlQ291bnQpIDwgQlJVVEVfRk9SQ0VfQ1VUT0ZGKSB7XG4gICAgICAgIC8vSWYgaW5wdXQgc21hbGwsIHRoZW4gdXNlIGJydXRlIGZvcmNlXG4gICAgICAgIHJldHZhbCA9IGJydXRlRm9yY2VQYXJ0aWFsKFxuICAgICAgICAgICAgZCwgYXhpcywgdmlzaXQsIGZsaXAsXG4gICAgICAgICAgICByZWRTdGFydCwgIHJlZEVuZCwgIHJlZCwgIHJlZEluZGV4LFxuICAgICAgICAgICAgYmx1ZVN0YXJ0LCBibHVlRW5kLCBibHVlLCBibHVlSW5kZXgpXG4gICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICB9XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9IGVsc2UgaWYoZCAqIHJlZENvdW50ICogYmx1ZUNvdW50IDwgU0NBTl9DVVRPRkYpIHtcbiAgICAgICAgLy9JZiBpbnB1dCBtZWRpdW0gc2l6ZWQsIHRoZW4gdXNlIHN3ZWVwIGFuZCBwcnVuZVxuICAgICAgICByZXR2YWwgPSBzd2VlcC5zY2FuQmlwYXJ0aXRlKFxuICAgICAgICAgIGQsIGF4aXMsIHZpc2l0LCBmbGlwLCBcbiAgICAgICAgICByZWRTdGFydCwgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICAgICAgICAgIGJsdWVTdGFydCwgYmx1ZUVuZCwgYmx1ZSwgYmx1ZUluZGV4KVxuICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgIHJldHVybiByZXR2YWxcbiAgICAgICAgfVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICAvL0ZpcnN0LCBmaW5kIGFsbCByZWQgaW50ZXJ2YWxzIHdob3NlIGludGVyaW9yIGNvbnRhaW5zIChsbyxoaSlcbiAgICB2YXIgcmVkMCA9IHBhcnRpdGlvbkludGVyaW9yQ29udGFpbnNJbnRlcnZhbChcbiAgICAgIGQsIGF4aXMsIFxuICAgICAgcmVkU3RhcnQsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgICAgIGxvLCBoaSlcblxuICAgIC8vTG93ZXIgZGltZW5zaW9uYWwgY2FzZVxuICAgIGlmKHJlZFN0YXJ0IDwgcmVkMCkge1xuXG4gICAgICBpZihkICogKHJlZDAgLSByZWRTdGFydCkgPCBCUlVURV9GT1JDRV9DVVRPRkYpIHtcbiAgICAgICAgLy9TcGVjaWFsIGNhc2UgZm9yIHNtYWxsIGlucHV0czogdXNlIGJydXRlIGZvcmNlXG4gICAgICAgIHJldHZhbCA9IGJydXRlRm9yY2VGdWxsKFxuICAgICAgICAgIGQsIGF4aXMrMSwgdmlzaXQsXG4gICAgICAgICAgcmVkU3RhcnQsIHJlZDAsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgYmx1ZVN0YXJ0LCBibHVlRW5kLCBibHVlLCBibHVlSW5kZXgpXG4gICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYoYXhpcyA9PT0gZC0yKSB7XG4gICAgICAgIGlmKGZsaXApIHtcbiAgICAgICAgICByZXR2YWwgPSBzd2VlcC5zd2VlcEJpcGFydGl0ZShcbiAgICAgICAgICAgIGQsIHZpc2l0LFxuICAgICAgICAgICAgYmx1ZVN0YXJ0LCBibHVlRW5kLCBibHVlLCBibHVlSW5kZXgsXG4gICAgICAgICAgICByZWRTdGFydCwgcmVkMCwgcmVkLCByZWRJbmRleClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR2YWwgPSBzd2VlcC5zd2VlcEJpcGFydGl0ZShcbiAgICAgICAgICAgIGQsIHZpc2l0LFxuICAgICAgICAgICAgcmVkU3RhcnQsIHJlZDAsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgICBibHVlU3RhcnQsIGJsdWVFbmQsIGJsdWUsIGJsdWVJbmRleClcbiAgICAgICAgfVxuICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgIHJldHVybiByZXR2YWxcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaXRlclB1c2godG9wKyssXG4gICAgICAgICAgYXhpcysxLFxuICAgICAgICAgIHJlZFN0YXJ0LCByZWQwLFxuICAgICAgICAgIGJsdWVTdGFydCwgYmx1ZUVuZCxcbiAgICAgICAgICBmbGlwLFxuICAgICAgICAgIC1JbmZpbml0eSwgSW5maW5pdHkpXG4gICAgICAgIGl0ZXJQdXNoKHRvcCsrLFxuICAgICAgICAgIGF4aXMrMSxcbiAgICAgICAgICBibHVlU3RhcnQsIGJsdWVFbmQsXG4gICAgICAgICAgcmVkU3RhcnQsIHJlZDAsXG4gICAgICAgICAgZmxpcF4xLFxuICAgICAgICAgIC1JbmZpbml0eSwgSW5maW5pdHkpXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy9EaXZpZGUgYW5kIGNvbnF1ZXIgcGhhc2VcbiAgICBpZihyZWQwIDwgcmVkRW5kKSB7XG5cbiAgICAgIC8vQ3V0IGJsdWUgaW50byAzIHBhcnRzOlxuICAgICAgLy9cbiAgICAgIC8vICBQb2ludHMgPCBtaWQgcG9pbnRcbiAgICAgIC8vICBQb2ludHMgPSBtaWQgcG9pbnRcbiAgICAgIC8vICBQb2ludHMgPiBtaWQgcG9pbnRcbiAgICAgIC8vXG4gICAgICB2YXIgYmx1ZTAgPSBmaW5kTWVkaWFuKFxuICAgICAgICBkLCBheGlzLCBcbiAgICAgICAgYmx1ZVN0YXJ0LCBibHVlRW5kLCBibHVlLCBibHVlSW5kZXgpXG4gICAgICB2YXIgbWlkID0gYmx1ZVtlbGVtU2l6ZSAqIGJsdWUwICsgYXhpc11cbiAgICAgIHZhciBibHVlMSA9IHBhcnRpdGlvblN0YXJ0RXF1YWwoXG4gICAgICAgIGQsIGF4aXMsXG4gICAgICAgIGJsdWUwLCBibHVlRW5kLCBibHVlLCBibHVlSW5kZXgsXG4gICAgICAgIG1pZClcblxuICAgICAgLy9SaWdodCBjYXNlXG4gICAgICBpZihibHVlMSA8IGJsdWVFbmQpIHtcbiAgICAgICAgaXRlclB1c2godG9wKyssXG4gICAgICAgICAgYXhpcyxcbiAgICAgICAgICByZWQwLCByZWRFbmQsXG4gICAgICAgICAgYmx1ZTEsIGJsdWVFbmQsXG4gICAgICAgICAgKGZsaXB8NCkgKyAoZnVsbCA/IDE2IDogMCksXG4gICAgICAgICAgbWlkLCBoaSlcbiAgICAgIH1cblxuICAgICAgLy9MZWZ0IGNhc2VcbiAgICAgIGlmKGJsdWVTdGFydCA8IGJsdWUwKSB7XG4gICAgICAgIGl0ZXJQdXNoKHRvcCsrLFxuICAgICAgICAgIGF4aXMsXG4gICAgICAgICAgcmVkMCwgcmVkRW5kLFxuICAgICAgICAgIGJsdWVTdGFydCwgYmx1ZTAsXG4gICAgICAgICAgKGZsaXB8MikgKyAoZnVsbCA/IDE2IDogMCksXG4gICAgICAgICAgbG8sIG1pZClcbiAgICAgIH1cblxuICAgICAgLy9DZW50ZXIgY2FzZSAodGhlIGhhcmQgcGFydClcbiAgICAgIGlmKGJsdWUwICsgMSA9PT0gYmx1ZTEpIHtcbiAgICAgICAgLy9PcHRpbWl6YXRpb246IFJhbmdlIHdpdGggZXhhY3RseSAxIHBvaW50LCB1c2UgYSBicnV0ZSBmb3JjZSBzY2FuXG4gICAgICAgIGlmKGZ1bGwpIHtcbiAgICAgICAgICByZXR2YWwgPSBvbmVQb2ludEZ1bGwoXG4gICAgICAgICAgICBkLCBheGlzLCB2aXNpdCxcbiAgICAgICAgICAgIHJlZDAsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgICAgICAgICAgIGJsdWUwLCBibHVlLCBibHVlSW5kZXhbYmx1ZTBdKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHZhbCA9IG9uZVBvaW50UGFydGlhbChcbiAgICAgICAgICAgIGQsIGF4aXMsIHZpc2l0LCBmbGlwLFxuICAgICAgICAgICAgcmVkMCwgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICAgICAgICAgICAgYmx1ZTAsIGJsdWUsIGJsdWVJbmRleFtibHVlMF0pXG4gICAgICAgIH1cbiAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZihibHVlMCA8IGJsdWUxKSB7XG4gICAgICAgIHZhciByZWQxXG4gICAgICAgIGlmKGZ1bGwpIHtcbiAgICAgICAgICAvL0lmIGZ1bGwgaW50ZXJzZWN0aW9uLCBuZWVkIHRvIGhhbmRsZSBzcGVjaWFsIGNhc2VcbiAgICAgICAgICByZWQxID0gcGFydGl0aW9uQ29udGFpbnNQb2ludChcbiAgICAgICAgICAgIGQsIGF4aXMsXG4gICAgICAgICAgICByZWQwLCByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgICBtaWQpXG4gICAgICAgICAgaWYocmVkMCA8IHJlZDEpIHtcbiAgICAgICAgICAgIHZhciByZWRYID0gcGFydGl0aW9uU3RhcnRFcXVhbChcbiAgICAgICAgICAgICAgZCwgYXhpcyxcbiAgICAgICAgICAgICAgcmVkMCwgcmVkMSwgcmVkLCByZWRJbmRleCxcbiAgICAgICAgICAgICAgbWlkKVxuICAgICAgICAgICAgaWYoYXhpcyA9PT0gZC0yKSB7XG4gICAgICAgICAgICAgIC8vRGVnZW5lcmF0ZSBzd2VlcCBpbnRlcnNlY3Rpb246XG4gICAgICAgICAgICAgIC8vICBbcmVkMCwgcmVkWF0gd2l0aCBbYmx1ZTAsIGJsdWUxXVxuICAgICAgICAgICAgICBpZihyZWQwIDwgcmVkWCkge1xuICAgICAgICAgICAgICAgIHJldHZhbCA9IHN3ZWVwLnN3ZWVwQ29tcGxldGUoXG4gICAgICAgICAgICAgICAgICBkLCB2aXNpdCxcbiAgICAgICAgICAgICAgICAgIHJlZDAsIHJlZFgsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgICAgICAgICBibHVlMCwgYmx1ZTEsIGJsdWUsIGJsdWVJbmRleClcbiAgICAgICAgICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIC8vTm9ybWFsIHN3ZWVwIGludGVyc2VjdGlvbjpcbiAgICAgICAgICAgICAgLy8gIFtyZWRYLCByZWQxXSB3aXRoIFtibHVlMCwgYmx1ZTFdXG4gICAgICAgICAgICAgIGlmKHJlZFggPCByZWQxKSB7XG4gICAgICAgICAgICAgICAgcmV0dmFsID0gc3dlZXAuc3dlZXBCaXBhcnRpdGUoXG4gICAgICAgICAgICAgICAgICBkLCB2aXNpdCxcbiAgICAgICAgICAgICAgICAgIHJlZFgsIHJlZDEsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgICAgICAgICBibHVlMCwgYmx1ZTEsIGJsdWUsIGJsdWVJbmRleClcbiAgICAgICAgICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaWYocmVkMCA8IHJlZFgpIHtcbiAgICAgICAgICAgICAgICBpdGVyUHVzaCh0b3ArKyxcbiAgICAgICAgICAgICAgICAgIGF4aXMrMSxcbiAgICAgICAgICAgICAgICAgIHJlZDAsIHJlZFgsXG4gICAgICAgICAgICAgICAgICBibHVlMCwgYmx1ZTEsXG4gICAgICAgICAgICAgICAgICAxNixcbiAgICAgICAgICAgICAgICAgIC1JbmZpbml0eSwgSW5maW5pdHkpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYocmVkWCA8IHJlZDEpIHtcbiAgICAgICAgICAgICAgICBpdGVyUHVzaCh0b3ArKyxcbiAgICAgICAgICAgICAgICAgIGF4aXMrMSxcbiAgICAgICAgICAgICAgICAgIHJlZFgsIHJlZDEsXG4gICAgICAgICAgICAgICAgICBibHVlMCwgYmx1ZTEsXG4gICAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgICAgLUluZmluaXR5LCBJbmZpbml0eSlcbiAgICAgICAgICAgICAgICBpdGVyUHVzaCh0b3ArKyxcbiAgICAgICAgICAgICAgICAgIGF4aXMrMSxcbiAgICAgICAgICAgICAgICAgIGJsdWUwLCBibHVlMSxcbiAgICAgICAgICAgICAgICAgIHJlZFgsIHJlZDEsXG4gICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgLUluZmluaXR5LCBJbmZpbml0eSlcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZihmbGlwKSB7XG4gICAgICAgICAgICByZWQxID0gcGFydGl0aW9uQ29udGFpbnNQb2ludFByb3BlcihcbiAgICAgICAgICAgICAgZCwgYXhpcyxcbiAgICAgICAgICAgICAgcmVkMCwgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICAgICAgICAgICAgICBtaWQpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlZDEgPSBwYXJ0aXRpb25Db250YWluc1BvaW50KFxuICAgICAgICAgICAgICBkLCBheGlzLFxuICAgICAgICAgICAgICByZWQwLCByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gICAgICAgICAgICAgIG1pZClcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYocmVkMCA8IHJlZDEpIHtcbiAgICAgICAgICAgIGlmKGF4aXMgPT09IGQtMikge1xuICAgICAgICAgICAgICBpZihmbGlwKSB7XG4gICAgICAgICAgICAgICAgcmV0dmFsID0gc3dlZXAuc3dlZXBCaXBhcnRpdGUoXG4gICAgICAgICAgICAgICAgICBkLCB2aXNpdCxcbiAgICAgICAgICAgICAgICAgIGJsdWUwLCBibHVlMSwgYmx1ZSwgYmx1ZUluZGV4LFxuICAgICAgICAgICAgICAgICAgcmVkMCwgcmVkMSwgcmVkLCByZWRJbmRleClcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR2YWwgPSBzd2VlcC5zd2VlcEJpcGFydGl0ZShcbiAgICAgICAgICAgICAgICAgIGQsIHZpc2l0LFxuICAgICAgICAgICAgICAgICAgcmVkMCwgcmVkMSwgcmVkLCByZWRJbmRleCxcbiAgICAgICAgICAgICAgICAgIGJsdWUwLCBibHVlMSwgYmx1ZSwgYmx1ZUluZGV4KVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpdGVyUHVzaCh0b3ArKyxcbiAgICAgICAgICAgICAgICBheGlzKzEsXG4gICAgICAgICAgICAgICAgcmVkMCwgcmVkMSxcbiAgICAgICAgICAgICAgICBibHVlMCwgYmx1ZTEsXG4gICAgICAgICAgICAgICAgZmxpcCxcbiAgICAgICAgICAgICAgICAtSW5maW5pdHksIEluZmluaXR5KVxuICAgICAgICAgICAgICBpdGVyUHVzaCh0b3ArKyxcbiAgICAgICAgICAgICAgICBheGlzKzEsXG4gICAgICAgICAgICAgICAgYmx1ZTAsIGJsdWUxLFxuICAgICAgICAgICAgICAgIHJlZDAsIHJlZDEsXG4gICAgICAgICAgICAgICAgZmxpcF4xLFxuICAgICAgICAgICAgICAgIC1JbmZpbml0eSwgSW5maW5pdHkpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG59LHtcIi4vYnJ1dGVcIjo5NyxcIi4vbWVkaWFuXCI6OTksXCIuL3BhcnRpdGlvblwiOjEwMCxcIi4vc3dlZXBcIjoxMDIsXCJiaXQtdHdpZGRsZVwiOjkyLFwidHlwZWRhcnJheS1wb29sXCI6NTQ1fV0sOTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gZmluZE1lZGlhblxuXG52YXIgZ2VuUGFydGl0aW9uID0gX2RlcmVxXygnLi9wYXJ0aXRpb24nKVxuXG52YXIgcGFydGl0aW9uU3RhcnRMZXNzVGhhbiA9IGdlblBhcnRpdGlvbignbG88cDAnLCBbJ3AwJ10pXG5cbnZhciBQQVJUSVRJT05fVEhSRVNIT0xEID0gOCAgIC8vQ3V0IG9mZiBmb3IgdXNpbmcgaW5zZXJ0aW9uIHNvcnQgaW4gZmluZE1lZGlhblxuXG4vL0Jhc2UgY2FzZSBmb3IgbWVkaWFuIGZpbmRpbmc6ICBVc2UgaW5zZXJ0aW9uIHNvcnRcbmZ1bmN0aW9uIGluc2VydGlvblNvcnQoZCwgYXhpcywgc3RhcnQsIGVuZCwgYm94ZXMsIGlkcykge1xuICB2YXIgZWxlbVNpemUgPSAyICogZFxuICB2YXIgYm94UHRyID0gZWxlbVNpemUgKiAoc3RhcnQrMSkgKyBheGlzXG4gIGZvcih2YXIgaT1zdGFydCsxOyBpPGVuZDsgKytpLCBib3hQdHIrPWVsZW1TaXplKSB7XG4gICAgdmFyIHggPSBib3hlc1tib3hQdHJdXG4gICAgZm9yKHZhciBqPWksIHB0cj1lbGVtU2l6ZSooaS0xKTsgXG4gICAgICAgIGo+c3RhcnQgJiYgYm94ZXNbcHRyK2F4aXNdID4geDsgXG4gICAgICAgIC0taiwgcHRyLT1lbGVtU2l6ZSkge1xuICAgICAgLy9Td2FwXG4gICAgICB2YXIgYVB0ciA9IHB0clxuICAgICAgdmFyIGJQdHIgPSBwdHIrZWxlbVNpemVcbiAgICAgIGZvcih2YXIgaz0wOyBrPGVsZW1TaXplOyArK2ssICsrYVB0ciwgKytiUHRyKSB7XG4gICAgICAgIHZhciB5ID0gYm94ZXNbYVB0cl1cbiAgICAgICAgYm94ZXNbYVB0cl0gPSBib3hlc1tiUHRyXVxuICAgICAgICBib3hlc1tiUHRyXSA9IHlcbiAgICAgIH1cbiAgICAgIHZhciB0bXAgPSBpZHNbal1cbiAgICAgIGlkc1tqXSA9IGlkc1tqLTFdXG4gICAgICBpZHNbai0xXSA9IHRtcFxuICAgIH1cbiAgfVxufVxuXG4vL0ZpbmQgbWVkaWFuIHVzaW5nIHF1aWNrIHNlbGVjdCBhbGdvcml0aG1cbi8vICB0YWtlcyBPKG4pIHRpbWUgd2l0aCBoaWdoIHByb2JhYmlsaXR5XG5mdW5jdGlvbiBmaW5kTWVkaWFuKGQsIGF4aXMsIHN0YXJ0LCBlbmQsIGJveGVzLCBpZHMpIHtcbiAgaWYoZW5kIDw9IHN0YXJ0KzEpIHtcbiAgICByZXR1cm4gc3RhcnRcbiAgfVxuXG4gIHZhciBsbyAgICAgICA9IHN0YXJ0XG4gIHZhciBoaSAgICAgICA9IGVuZFxuICB2YXIgbWlkICAgICAgPSAoKGVuZCArIHN0YXJ0KSA+Pj4gMSlcbiAgdmFyIGVsZW1TaXplID0gMipkXG4gIHZhciBwaXZvdCAgICA9IG1pZFxuICB2YXIgdmFsdWUgICAgPSBib3hlc1tlbGVtU2l6ZSptaWQrYXhpc11cbiAgXG4gIHdoaWxlKGxvIDwgaGkpIHtcbiAgICBpZihoaSAtIGxvIDwgUEFSVElUSU9OX1RIUkVTSE9MRCkge1xuICAgICAgaW5zZXJ0aW9uU29ydChkLCBheGlzLCBsbywgaGksIGJveGVzLCBpZHMpXG4gICAgICB2YWx1ZSA9IGJveGVzW2VsZW1TaXplKm1pZCtheGlzXVxuICAgICAgYnJlYWtcbiAgICB9XG4gICAgXG4gICAgLy9TZWxlY3QgcGl2b3QgdXNpbmcgbWVkaWFuLW9mLTNcbiAgICB2YXIgY291bnQgID0gaGkgLSBsb1xuICAgIHZhciBwaXZvdDAgPSAoTWF0aC5yYW5kb20oKSpjb3VudCtsbyl8MFxuICAgIHZhciB2YWx1ZTAgPSBib3hlc1tlbGVtU2l6ZSpwaXZvdDAgKyBheGlzXVxuICAgIHZhciBwaXZvdDEgPSAoTWF0aC5yYW5kb20oKSpjb3VudCtsbyl8MFxuICAgIHZhciB2YWx1ZTEgPSBib3hlc1tlbGVtU2l6ZSpwaXZvdDEgKyBheGlzXVxuICAgIHZhciBwaXZvdDIgPSAoTWF0aC5yYW5kb20oKSpjb3VudCtsbyl8MFxuICAgIHZhciB2YWx1ZTIgPSBib3hlc1tlbGVtU2l6ZSpwaXZvdDIgKyBheGlzXVxuICAgIGlmKHZhbHVlMCA8PSB2YWx1ZTEpIHtcbiAgICAgIGlmKHZhbHVlMiA+PSB2YWx1ZTEpIHtcbiAgICAgICAgcGl2b3QgPSBwaXZvdDFcbiAgICAgICAgdmFsdWUgPSB2YWx1ZTFcbiAgICAgIH0gZWxzZSBpZih2YWx1ZTAgPj0gdmFsdWUyKSB7XG4gICAgICAgIHBpdm90ID0gcGl2b3QwXG4gICAgICAgIHZhbHVlID0gdmFsdWUwXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwaXZvdCA9IHBpdm90MlxuICAgICAgICB2YWx1ZSA9IHZhbHVlMlxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZih2YWx1ZTEgPj0gdmFsdWUyKSB7XG4gICAgICAgIHBpdm90ID0gcGl2b3QxXG4gICAgICAgIHZhbHVlID0gdmFsdWUxXG4gICAgICB9IGVsc2UgaWYodmFsdWUyID49IHZhbHVlMCkge1xuICAgICAgICBwaXZvdCA9IHBpdm90MFxuICAgICAgICB2YWx1ZSA9IHZhbHVlMFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGl2b3QgPSBwaXZvdDJcbiAgICAgICAgdmFsdWUgPSB2YWx1ZTJcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvL1N3YXAgcGl2b3QgdG8gZW5kIG9mIGFycmF5XG4gICAgdmFyIGFQdHIgPSBlbGVtU2l6ZSAqIChoaS0xKVxuICAgIHZhciBiUHRyID0gZWxlbVNpemUgKiBwaXZvdFxuICAgIGZvcih2YXIgaT0wOyBpPGVsZW1TaXplOyArK2ksICsrYVB0ciwgKytiUHRyKSB7XG4gICAgICB2YXIgeCA9IGJveGVzW2FQdHJdXG4gICAgICBib3hlc1thUHRyXSA9IGJveGVzW2JQdHJdXG4gICAgICBib3hlc1tiUHRyXSA9IHhcbiAgICB9XG4gICAgdmFyIHkgPSBpZHNbaGktMV1cbiAgICBpZHNbaGktMV0gPSBpZHNbcGl2b3RdXG4gICAgaWRzW3Bpdm90XSA9IHlcblxuICAgIC8vUGFydGl0aW9uIHVzaW5nIHBpdm90XG4gICAgcGl2b3QgPSBwYXJ0aXRpb25TdGFydExlc3NUaGFuKFxuICAgICAgZCwgYXhpcywgXG4gICAgICBsbywgaGktMSwgYm94ZXMsIGlkcyxcbiAgICAgIHZhbHVlKVxuXG4gICAgLy9Td2FwIHBpdm90IGJhY2tcbiAgICB2YXIgYVB0ciA9IGVsZW1TaXplICogKGhpLTEpXG4gICAgdmFyIGJQdHIgPSBlbGVtU2l6ZSAqIHBpdm90XG4gICAgZm9yKHZhciBpPTA7IGk8ZWxlbVNpemU7ICsraSwgKythUHRyLCArK2JQdHIpIHtcbiAgICAgIHZhciB4ID0gYm94ZXNbYVB0cl1cbiAgICAgIGJveGVzW2FQdHJdID0gYm94ZXNbYlB0cl1cbiAgICAgIGJveGVzW2JQdHJdID0geFxuICAgIH1cbiAgICB2YXIgeSA9IGlkc1toaS0xXVxuICAgIGlkc1toaS0xXSA9IGlkc1twaXZvdF1cbiAgICBpZHNbcGl2b3RdID0geVxuXG4gICAgLy9Td2FwIHBpdm90IHRvIGxhc3QgcGl2b3RcbiAgICBpZihtaWQgPCBwaXZvdCkge1xuICAgICAgaGkgPSBwaXZvdC0xXG4gICAgICB3aGlsZShsbyA8IGhpICYmIFxuICAgICAgICBib3hlc1tlbGVtU2l6ZSooaGktMSkrYXhpc10gPT09IHZhbHVlKSB7XG4gICAgICAgIGhpIC09IDFcbiAgICAgIH1cbiAgICAgIGhpICs9IDFcbiAgICB9IGVsc2UgaWYocGl2b3QgPCBtaWQpIHtcbiAgICAgIGxvID0gcGl2b3QgKyAxXG4gICAgICB3aGlsZShsbyA8IGhpICYmXG4gICAgICAgIGJveGVzW2VsZW1TaXplKmxvK2F4aXNdID09PSB2YWx1ZSkge1xuICAgICAgICBsbyArPSAxXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgLy9NYWtlIHN1cmUgcGl2b3QgaXMgYXQgc3RhcnRcbiAgcmV0dXJuIHBhcnRpdGlvblN0YXJ0TGVzc1RoYW4oXG4gICAgZCwgYXhpcywgXG4gICAgc3RhcnQsIG1pZCwgYm94ZXMsIGlkcyxcbiAgICBib3hlc1tlbGVtU2l6ZSptaWQrYXhpc10pXG59XG59LHtcIi4vcGFydGl0aW9uXCI6MTAwfV0sMTAwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdlblBhcnRpdGlvblxuXG52YXIgY29kZSA9ICdmb3IodmFyIGo9MiphLGs9aipjLGw9ayxtPWMsbj1iLG89YStiLHA9YztkPnA7KytwLGsrPWope3ZhciBfO2lmKCQpaWYobT09PXApbSs9MSxsKz1qO2Vsc2V7Zm9yKHZhciBzPTA7aj5zOysrcyl7dmFyIHQ9ZVtrK3NdO2VbaytzXT1lW2xdLGVbbCsrXT10fXZhciB1PWZbcF07ZltwXT1mW21dLGZbbSsrXT11fX1yZXR1cm4gbSdcblxuZnVuY3Rpb24gZ2VuUGFydGl0aW9uKHByZWRpY2F0ZSwgYXJncykge1xuICB2YXIgZmFyZ3MgPSdhYmNkZWYnLnNwbGl0KCcnKS5jb25jYXQoYXJncylcbiAgdmFyIHJlYWRzID0gW11cbiAgaWYocHJlZGljYXRlLmluZGV4T2YoJ2xvJykgPj0gMCkge1xuICAgIHJlYWRzLnB1c2goJ2xvPWVbaytuXScpXG4gIH1cbiAgaWYocHJlZGljYXRlLmluZGV4T2YoJ2hpJykgPj0gMCkge1xuICAgIHJlYWRzLnB1c2goJ2hpPWVbaytvXScpXG4gIH1cbiAgZmFyZ3MucHVzaChcbiAgICBjb2RlLnJlcGxhY2UoJ18nLCByZWFkcy5qb2luKCkpXG4gICAgICAgIC5yZXBsYWNlKCckJywgcHJlZGljYXRlKSlcbiAgcmV0dXJuIEZ1bmN0aW9uLmFwcGx5KHZvaWQgMCwgZmFyZ3MpXG59XG59LHt9XSwxMDE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xuXG4vL1RoaXMgY29kZSBpcyBleHRyYWN0ZWQgZnJvbSBuZGFycmF5LXNvcnRcbi8vSXQgaXMgaW5saW5lZCBoZXJlIGFzIGEgdGVtcG9yYXJ5IHdvcmthcm91bmRcblxubW9kdWxlLmV4cG9ydHMgPSB3cmFwcGVyO1xuXG52YXIgSU5TRVJUX1NPUlRfQ1VUT0ZGID0gMzJcblxuZnVuY3Rpb24gd3JhcHBlcihkYXRhLCBuMCkge1xuICBpZiAobjAgPD0gNCpJTlNFUlRfU09SVF9DVVRPRkYpIHtcbiAgICBpbnNlcnRpb25Tb3J0KDAsIG4wIC0gMSwgZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgcXVpY2tTb3J0KDAsIG4wIC0gMSwgZGF0YSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaW5zZXJ0aW9uU29ydChsZWZ0LCByaWdodCwgZGF0YSkge1xuICB2YXIgcHRyID0gMioobGVmdCsxKVxuICBmb3IodmFyIGk9bGVmdCsxOyBpPD1yaWdodDsgKytpKSB7XG4gICAgdmFyIGEgPSBkYXRhW3B0cisrXVxuICAgIHZhciBiID0gZGF0YVtwdHIrK11cbiAgICB2YXIgaiA9IGlcbiAgICB2YXIganB0ciA9IHB0ci0yXG4gICAgd2hpbGUoai0tID4gbGVmdCkge1xuICAgICAgdmFyIHggPSBkYXRhW2pwdHItMl1cbiAgICAgIHZhciB5ID0gZGF0YVtqcHRyLTFdXG4gICAgICBpZih4IDwgYSkge1xuICAgICAgICBicmVha1xuICAgICAgfSBlbHNlIGlmKHggPT09IGEgJiYgeSA8IGIpIHtcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIGRhdGFbanB0cl0gICA9IHhcbiAgICAgIGRhdGFbanB0cisxXSA9IHlcbiAgICAgIGpwdHIgLT0gMlxuICAgIH1cbiAgICBkYXRhW2pwdHJdICAgPSBhXG4gICAgZGF0YVtqcHRyKzFdID0gYlxuICB9XG59XG5cbmZ1bmN0aW9uIHN3YXAoaSwgaiwgZGF0YSkge1xuICBpICo9IDJcbiAgaiAqPSAyXG4gIHZhciB4ID0gZGF0YVtpXVxuICB2YXIgeSA9IGRhdGFbaSsxXVxuICBkYXRhW2ldID0gZGF0YVtqXVxuICBkYXRhW2krMV0gPSBkYXRhW2orMV1cbiAgZGF0YVtqXSA9IHhcbiAgZGF0YVtqKzFdID0geVxufVxuXG5mdW5jdGlvbiBtb3ZlKGksIGosIGRhdGEpIHtcbiAgaSAqPSAyXG4gIGogKj0gMlxuICBkYXRhW2ldID0gZGF0YVtqXVxuICBkYXRhW2krMV0gPSBkYXRhW2orMV1cbn1cblxuZnVuY3Rpb24gcm90YXRlKGksIGosIGssIGRhdGEpIHtcbiAgaSAqPSAyXG4gIGogKj0gMlxuICBrICo9IDJcbiAgdmFyIHggPSBkYXRhW2ldXG4gIHZhciB5ID0gZGF0YVtpKzFdXG4gIGRhdGFbaV0gPSBkYXRhW2pdXG4gIGRhdGFbaSsxXSA9IGRhdGFbaisxXVxuICBkYXRhW2pdID0gZGF0YVtrXVxuICBkYXRhW2orMV0gPSBkYXRhW2srMV1cbiAgZGF0YVtrXSA9IHhcbiAgZGF0YVtrKzFdID0geVxufVxuXG5mdW5jdGlvbiBzaHVmZmxlUGl2b3QoaSwgaiwgcHgsIHB5LCBkYXRhKSB7XG4gIGkgKj0gMlxuICBqICo9IDJcbiAgZGF0YVtpXSA9IGRhdGFbal1cbiAgZGF0YVtqXSA9IHB4XG4gIGRhdGFbaSsxXSA9IGRhdGFbaisxXVxuICBkYXRhW2orMV0gPSBweVxufVxuXG5mdW5jdGlvbiBjb21wYXJlKGksIGosIGRhdGEpIHtcbiAgaSAqPSAyXG4gIGogKj0gMlxuICB2YXIgeCA9IGRhdGFbaV0sXG4gICAgICB5ID0gZGF0YVtqXVxuICBpZih4IDwgeSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9IGVsc2UgaWYoeCA9PT0geSkge1xuICAgIHJldHVybiBkYXRhW2krMV0gPiBkYXRhW2orMV1cbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG5mdW5jdGlvbiBjb21wYXJlUGl2b3QoaSwgeSwgYiwgZGF0YSkge1xuICBpICo9IDJcbiAgdmFyIHggPSBkYXRhW2ldXG4gIGlmKHggPCB5KSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfSBlbHNlIGlmKHggPT09IHkpIHtcbiAgICByZXR1cm4gZGF0YVtpKzFdIDwgYlxuICB9XG4gIHJldHVybiBmYWxzZVxufVxuXG5mdW5jdGlvbiBxdWlja1NvcnQobGVmdCwgcmlnaHQsIGRhdGEpIHtcbiAgdmFyIHNpeHRoID0gKHJpZ2h0IC0gbGVmdCArIDEpIC8gNiB8IDAsIFxuICAgICAgaW5kZXgxID0gbGVmdCArIHNpeHRoLCBcbiAgICAgIGluZGV4NSA9IHJpZ2h0IC0gc2l4dGgsIFxuICAgICAgaW5kZXgzID0gbGVmdCArIHJpZ2h0ID4+IDEsIFxuICAgICAgaW5kZXgyID0gaW5kZXgzIC0gc2l4dGgsIFxuICAgICAgaW5kZXg0ID0gaW5kZXgzICsgc2l4dGgsIFxuICAgICAgZWwxID0gaW5kZXgxLCBcbiAgICAgIGVsMiA9IGluZGV4MiwgXG4gICAgICBlbDMgPSBpbmRleDMsIFxuICAgICAgZWw0ID0gaW5kZXg0LCBcbiAgICAgIGVsNSA9IGluZGV4NSwgXG4gICAgICBsZXNzID0gbGVmdCArIDEsIFxuICAgICAgZ3JlYXQgPSByaWdodCAtIDEsIFxuICAgICAgdG1wID0gMFxuICBpZihjb21wYXJlKGVsMSwgZWwyLCBkYXRhKSkge1xuICAgIHRtcCA9IGVsMVxuICAgIGVsMSA9IGVsMlxuICAgIGVsMiA9IHRtcFxuICB9XG4gIGlmKGNvbXBhcmUoZWw0LCBlbDUsIGRhdGEpKSB7XG4gICAgdG1wID0gZWw0XG4gICAgZWw0ID0gZWw1XG4gICAgZWw1ID0gdG1wXG4gIH1cbiAgaWYoY29tcGFyZShlbDEsIGVsMywgZGF0YSkpIHtcbiAgICB0bXAgPSBlbDFcbiAgICBlbDEgPSBlbDNcbiAgICBlbDMgPSB0bXBcbiAgfVxuICBpZihjb21wYXJlKGVsMiwgZWwzLCBkYXRhKSkge1xuICAgIHRtcCA9IGVsMlxuICAgIGVsMiA9IGVsM1xuICAgIGVsMyA9IHRtcFxuICB9XG4gIGlmKGNvbXBhcmUoZWwxLCBlbDQsIGRhdGEpKSB7XG4gICAgdG1wID0gZWwxXG4gICAgZWwxID0gZWw0XG4gICAgZWw0ID0gdG1wXG4gIH1cbiAgaWYoY29tcGFyZShlbDMsIGVsNCwgZGF0YSkpIHtcbiAgICB0bXAgPSBlbDNcbiAgICBlbDMgPSBlbDRcbiAgICBlbDQgPSB0bXBcbiAgfVxuICBpZihjb21wYXJlKGVsMiwgZWw1LCBkYXRhKSkge1xuICAgIHRtcCA9IGVsMlxuICAgIGVsMiA9IGVsNVxuICAgIGVsNSA9IHRtcFxuICB9XG4gIGlmKGNvbXBhcmUoZWwyLCBlbDMsIGRhdGEpKSB7XG4gICAgdG1wID0gZWwyXG4gICAgZWwyID0gZWwzXG4gICAgZWwzID0gdG1wXG4gIH1cbiAgaWYoY29tcGFyZShlbDQsIGVsNSwgZGF0YSkpIHtcbiAgICB0bXAgPSBlbDRcbiAgICBlbDQgPSBlbDVcbiAgICBlbDUgPSB0bXBcbiAgfVxuXG4gIHZhciBwaXZvdDFYID0gZGF0YVsyKmVsMl1cbiAgdmFyIHBpdm90MVkgPSBkYXRhWzIqZWwyKzFdXG4gIHZhciBwaXZvdDJYID0gZGF0YVsyKmVsNF1cbiAgdmFyIHBpdm90MlkgPSBkYXRhWzIqZWw0KzFdXG5cbiAgdmFyIHB0cjAgPSAyICogZWwxO1xuICB2YXIgcHRyMiA9IDIgKiBlbDM7XG4gIHZhciBwdHI0ID0gMiAqIGVsNTtcbiAgdmFyIHB0cjUgPSAyICogaW5kZXgxO1xuICB2YXIgcHRyNiA9IDIgKiBpbmRleDM7XG4gIHZhciBwdHI3ID0gMiAqIGluZGV4NTtcbiAgZm9yICh2YXIgaTEgPSAwOyBpMSA8IDI7ICsraTEpIHtcbiAgICB2YXIgeCA9IGRhdGFbcHRyMCtpMV07XG4gICAgdmFyIHkgPSBkYXRhW3B0cjIraTFdO1xuICAgIHZhciB6ID0gZGF0YVtwdHI0K2kxXTtcbiAgICBkYXRhW3B0cjUraTFdID0geDtcbiAgICBkYXRhW3B0cjYraTFdID0geTtcbiAgICBkYXRhW3B0cjcraTFdID0gejtcbiAgfVxuXG4gIG1vdmUoaW5kZXgyLCBsZWZ0LCBkYXRhKVxuICBtb3ZlKGluZGV4NCwgcmlnaHQsIGRhdGEpXG4gIGZvciAodmFyIGsgPSBsZXNzOyBrIDw9IGdyZWF0OyArK2spIHtcbiAgICBpZiAoY29tcGFyZVBpdm90KGssIHBpdm90MVgsIHBpdm90MVksIGRhdGEpKSB7XG4gICAgICBpZiAoayAhPT0gbGVzcykge1xuICAgICAgICBzd2FwKGssIGxlc3MsIGRhdGEpXG4gICAgICB9XG4gICAgICArK2xlc3M7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghY29tcGFyZVBpdm90KGssIHBpdm90MlgsIHBpdm90MlksIGRhdGEpKSB7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgaWYgKCFjb21wYXJlUGl2b3QoZ3JlYXQsIHBpdm90MlgsIHBpdm90MlksIGRhdGEpKSB7XG4gICAgICAgICAgICBpZiAoLS1ncmVhdCA8IGspIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGNvbXBhcmVQaXZvdChncmVhdCwgcGl2b3QxWCwgcGl2b3QxWSwgZGF0YSkpIHtcbiAgICAgICAgICAgICAgcm90YXRlKGssIGxlc3MsIGdyZWF0LCBkYXRhKVxuICAgICAgICAgICAgICArK2xlc3M7XG4gICAgICAgICAgICAgIC0tZ3JlYXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzd2FwKGssIGdyZWF0LCBkYXRhKVxuICAgICAgICAgICAgICAtLWdyZWF0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHNodWZmbGVQaXZvdChsZWZ0LCBsZXNzLTEsIHBpdm90MVgsIHBpdm90MVksIGRhdGEpXG4gIHNodWZmbGVQaXZvdChyaWdodCwgZ3JlYXQrMSwgcGl2b3QyWCwgcGl2b3QyWSwgZGF0YSlcbiAgaWYgKGxlc3MgLSAyIC0gbGVmdCA8PSBJTlNFUlRfU09SVF9DVVRPRkYpIHtcbiAgICBpbnNlcnRpb25Tb3J0KGxlZnQsIGxlc3MgLSAyLCBkYXRhKTtcbiAgfSBlbHNlIHtcbiAgICBxdWlja1NvcnQobGVmdCwgbGVzcyAtIDIsIGRhdGEpO1xuICB9XG4gIGlmIChyaWdodCAtIChncmVhdCArIDIpIDw9IElOU0VSVF9TT1JUX0NVVE9GRikge1xuICAgIGluc2VydGlvblNvcnQoZ3JlYXQgKyAyLCByaWdodCwgZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgcXVpY2tTb3J0KGdyZWF0ICsgMiwgcmlnaHQsIGRhdGEpO1xuICB9XG4gIGlmIChncmVhdCAtIGxlc3MgPD0gSU5TRVJUX1NPUlRfQ1VUT0ZGKSB7XG4gICAgaW5zZXJ0aW9uU29ydChsZXNzLCBncmVhdCwgZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgcXVpY2tTb3J0KGxlc3MsIGdyZWF0LCBkYXRhKTtcbiAgfVxufVxufSx7fV0sMTAyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgaW5pdDogICAgICAgICAgIHNxSW5pdCxcbiAgc3dlZXBCaXBhcnRpdGU6IHN3ZWVwQmlwYXJ0aXRlLFxuICBzd2VlcENvbXBsZXRlOiAgc3dlZXBDb21wbGV0ZSxcbiAgc2NhbkJpcGFydGl0ZTogIHNjYW5CaXBhcnRpdGUsXG4gIHNjYW5Db21wbGV0ZTogICBzY2FuQ29tcGxldGVcbn1cblxudmFyIHBvb2wgID0gX2RlcmVxXygndHlwZWRhcnJheS1wb29sJylcbnZhciBiaXRzICA9IF9kZXJlcV8oJ2JpdC10d2lkZGxlJylcbnZhciBpc29ydCA9IF9kZXJlcV8oJy4vc29ydCcpXG5cbi8vRmxhZyBmb3IgYmx1ZVxudmFyIEJMVUVfRkxBRyA9ICgxPDwyOClcblxuLy8xRCBzd2VlcCBldmVudCBxdWV1ZSBzdHVmZiAodXNlIHBvb2wgdG8gc2F2ZSBzcGFjZSlcbnZhciBJTklUX0NBUEFDSVRZICAgICAgPSAxMDI0XG52YXIgUkVEX1NXRUVQX1FVRVVFICAgID0gcG9vbC5tYWxsb2NJbnQzMihJTklUX0NBUEFDSVRZKVxudmFyIFJFRF9TV0VFUF9JTkRFWCAgICA9IHBvb2wubWFsbG9jSW50MzIoSU5JVF9DQVBBQ0lUWSlcbnZhciBCTFVFX1NXRUVQX1FVRVVFICAgPSBwb29sLm1hbGxvY0ludDMyKElOSVRfQ0FQQUNJVFkpXG52YXIgQkxVRV9TV0VFUF9JTkRFWCAgID0gcG9vbC5tYWxsb2NJbnQzMihJTklUX0NBUEFDSVRZKVxudmFyIENPTU1PTl9TV0VFUF9RVUVVRSA9IHBvb2wubWFsbG9jSW50MzIoSU5JVF9DQVBBQ0lUWSlcbnZhciBDT01NT05fU1dFRVBfSU5ERVggPSBwb29sLm1hbGxvY0ludDMyKElOSVRfQ0FQQUNJVFkpXG52YXIgU1dFRVBfRVZFTlRTICAgICAgID0gcG9vbC5tYWxsb2NEb3VibGUoSU5JVF9DQVBBQ0lUWSAqIDgpXG5cbi8vUmVzZXJ2ZXMgbWVtb3J5IGZvciB0aGUgMUQgc3dlZXAgZGF0YSBzdHJ1Y3R1cmVzXG5mdW5jdGlvbiBzcUluaXQoY291bnQpIHtcbiAgdmFyIHJjb3VudCA9IGJpdHMubmV4dFBvdzIoY291bnQpXG4gIGlmKFJFRF9TV0VFUF9RVUVVRS5sZW5ndGggPCByY291bnQpIHtcbiAgICBwb29sLmZyZWUoUkVEX1NXRUVQX1FVRVVFKVxuICAgIFJFRF9TV0VFUF9RVUVVRSA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKFJFRF9TV0VFUF9JTkRFWC5sZW5ndGggPCByY291bnQpIHtcbiAgICBwb29sLmZyZWUoUkVEX1NXRUVQX0lOREVYKVxuICAgIFJFRF9TV0VFUF9JTkRFWCA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKEJMVUVfU1dFRVBfUVVFVUUubGVuZ3RoIDwgcmNvdW50KSB7XG4gICAgcG9vbC5mcmVlKEJMVUVfU1dFRVBfUVVFVUUpXG4gICAgQkxVRV9TV0VFUF9RVUVVRSA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKEJMVUVfU1dFRVBfSU5ERVgubGVuZ3RoIDwgcmNvdW50KSB7XG4gICAgcG9vbC5mcmVlKEJMVUVfU1dFRVBfSU5ERVgpXG4gICAgQkxVRV9TV0VFUF9JTkRFWCA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKENPTU1PTl9TV0VFUF9RVUVVRS5sZW5ndGggPCByY291bnQpIHtcbiAgICBwb29sLmZyZWUoQ09NTU9OX1NXRUVQX1FVRVVFKVxuICAgIENPTU1PTl9TV0VFUF9RVUVVRSA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIGlmKENPTU1PTl9TV0VFUF9JTkRFWC5sZW5ndGggPCByY291bnQpIHtcbiAgICBwb29sLmZyZWUoQ09NTU9OX1NXRUVQX0lOREVYKVxuICAgIENPTU1PTl9TV0VFUF9JTkRFWCA9IHBvb2wubWFsbG9jSW50MzIocmNvdW50KVxuICB9XG4gIHZhciBldmVudExlbmd0aCA9IDggKiByY291bnRcbiAgaWYoU1dFRVBfRVZFTlRTLmxlbmd0aCA8IGV2ZW50TGVuZ3RoKSB7XG4gICAgcG9vbC5mcmVlKFNXRUVQX0VWRU5UUylcbiAgICBTV0VFUF9FVkVOVFMgPSBwb29sLm1hbGxvY0RvdWJsZShldmVudExlbmd0aClcbiAgfVxufVxuXG4vL1JlbW92ZSBhbiBpdGVtIGZyb20gdGhlIGFjdGl2ZSBxdWV1ZSBpbiBPKDEpXG5mdW5jdGlvbiBzcVBvcChxdWV1ZSwgaW5kZXgsIGNvdW50LCBpdGVtKSB7XG4gIHZhciBpZHggPSBpbmRleFtpdGVtXVxuICB2YXIgdG9wID0gcXVldWVbY291bnQtMV1cbiAgcXVldWVbaWR4XSA9IHRvcFxuICBpbmRleFt0b3BdID0gaWR4XG59XG5cbi8vSW5zZXJ0IGFuIGl0ZW0gaW50byB0aGUgYWN0aXZlIHF1ZXVlIGluIE8oMSlcbmZ1bmN0aW9uIHNxUHVzaChxdWV1ZSwgaW5kZXgsIGNvdW50LCBpdGVtKSB7XG4gIHF1ZXVlW2NvdW50XSA9IGl0ZW1cbiAgaW5kZXhbaXRlbV0gID0gY291bnRcbn1cblxuLy9SZWN1cnNpb24gYmFzZSBjYXNlOiB1c2UgMUQgc3dlZXAgYWxnb3JpdGhtXG5mdW5jdGlvbiBzd2VlcEJpcGFydGl0ZShcbiAgICBkLCB2aXNpdCxcbiAgICByZWRTdGFydCwgIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgICBibHVlU3RhcnQsIGJsdWVFbmQsIGJsdWUsIGJsdWVJbmRleCkge1xuXG4gIC8vc3RvcmUgZXZlbnRzIGFzIHBhaXJzIFtjb29yZGluYXRlLCBpZHhdXG4gIC8vXG4gIC8vICByZWQgY3JlYXRlOiAgLShpZHgrMSlcbiAgLy8gIHJlZCBkZXN0cm95OiBpZHhcbiAgLy8gIGJsdWUgY3JlYXRlOiAtKGlkeCtCTFVFX0ZMQUcpXG4gIC8vICBibHVlIGRlc3Ryb3k6IGlkeCtCTFVFX0ZMQUdcbiAgLy9cbiAgdmFyIHB0ciAgICAgID0gMFxuICB2YXIgZWxlbVNpemUgPSAyKmRcbiAgdmFyIGlzdGFydCAgID0gZC0xXG4gIHZhciBpZW5kICAgICA9IGVsZW1TaXplLTFcblxuICBmb3IodmFyIGk9cmVkU3RhcnQ7IGk8cmVkRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gcmVkSW5kZXhbaV1cbiAgICB2YXIgcmVkT2Zmc2V0ID0gZWxlbVNpemUqaVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSByZWRbcmVkT2Zmc2V0K2lzdGFydF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gLShpZHgrMSlcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gcmVkW3JlZE9mZnNldCtpZW5kXVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBpZHhcbiAgfVxuXG4gIGZvcih2YXIgaT1ibHVlU3RhcnQ7IGk8Ymx1ZUVuZDsgKytpKSB7XG4gICAgdmFyIGlkeCA9IGJsdWVJbmRleFtpXStCTFVFX0ZMQUdcbiAgICB2YXIgYmx1ZU9mZnNldCA9IGVsZW1TaXplKmlcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gYmx1ZVtibHVlT2Zmc2V0K2lzdGFydF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gLWlkeFxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBibHVlW2JsdWVPZmZzZXQraWVuZF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gaWR4XG4gIH1cblxuICAvL3Byb2Nlc3MgZXZlbnRzIGZyb20gbGVmdC0+cmlnaHRcbiAgdmFyIG4gPSBwdHIgPj4+IDFcbiAgaXNvcnQoU1dFRVBfRVZFTlRTLCBuKVxuICBcbiAgdmFyIHJlZEFjdGl2ZSAgPSAwXG4gIHZhciBibHVlQWN0aXZlID0gMFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICB2YXIgZSA9IFNXRUVQX0VWRU5UU1syKmkrMV18MFxuICAgIGlmKGUgPj0gQkxVRV9GTEFHKSB7XG4gICAgICAvL2JsdWUgZGVzdHJveSBldmVudFxuICAgICAgZSA9IChlLUJMVUVfRkxBRyl8MFxuICAgICAgc3FQb3AoQkxVRV9TV0VFUF9RVUVVRSwgQkxVRV9TV0VFUF9JTkRFWCwgYmx1ZUFjdGl2ZS0tLCBlKVxuICAgIH0gZWxzZSBpZihlID49IDApIHtcbiAgICAgIC8vcmVkIGRlc3Ryb3kgZXZlbnRcbiAgICAgIHNxUG9wKFJFRF9TV0VFUF9RVUVVRSwgUkVEX1NXRUVQX0lOREVYLCByZWRBY3RpdmUtLSwgZSlcbiAgICB9IGVsc2UgaWYoZSA8PSAtQkxVRV9GTEFHKSB7XG4gICAgICAvL2JsdWUgY3JlYXRlIGV2ZW50XG4gICAgICBlID0gKC1lLUJMVUVfRkxBRyl8MFxuICAgICAgZm9yKHZhciBqPTA7IGo8cmVkQWN0aXZlOyArK2opIHtcbiAgICAgICAgdmFyIHJldHZhbCA9IHZpc2l0KFJFRF9TV0VFUF9RVUVVRVtqXSwgZSlcbiAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHNxUHVzaChCTFVFX1NXRUVQX1FVRVVFLCBCTFVFX1NXRUVQX0lOREVYLCBibHVlQWN0aXZlKyssIGUpXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vcmVkIGNyZWF0ZSBldmVudFxuICAgICAgZSA9ICgtZS0xKXwwXG4gICAgICBmb3IodmFyIGo9MDsgajxibHVlQWN0aXZlOyArK2opIHtcbiAgICAgICAgdmFyIHJldHZhbCA9IHZpc2l0KGUsIEJMVUVfU1dFRVBfUVVFVUVbal0pXG4gICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBzcVB1c2goUkVEX1NXRUVQX1FVRVVFLCBSRURfU1dFRVBfSU5ERVgsIHJlZEFjdGl2ZSsrLCBlKVxuICAgIH1cbiAgfVxufVxuXG4vL0NvbXBsZXRlIHN3ZWVwXG5mdW5jdGlvbiBzd2VlcENvbXBsZXRlKGQsIHZpc2l0LCBcbiAgcmVkU3RhcnQsIHJlZEVuZCwgcmVkLCByZWRJbmRleCxcbiAgYmx1ZVN0YXJ0LCBibHVlRW5kLCBibHVlLCBibHVlSW5kZXgpIHtcblxuICB2YXIgcHRyICAgICAgPSAwXG4gIHZhciBlbGVtU2l6ZSA9IDIqZFxuICB2YXIgaXN0YXJ0ICAgPSBkLTFcbiAgdmFyIGllbmQgICAgID0gZWxlbVNpemUtMVxuXG4gIGZvcih2YXIgaT1yZWRTdGFydDsgaTxyZWRFbmQ7ICsraSkge1xuICAgIHZhciBpZHggPSAocmVkSW5kZXhbaV0rMSk8PDFcbiAgICB2YXIgcmVkT2Zmc2V0ID0gZWxlbVNpemUqaVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSByZWRbcmVkT2Zmc2V0K2lzdGFydF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gLWlkeFxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSByZWRbcmVkT2Zmc2V0K2llbmRdXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IGlkeFxuICB9XG5cbiAgZm9yKHZhciBpPWJsdWVTdGFydDsgaTxibHVlRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gKGJsdWVJbmRleFtpXSsxKTw8MVxuICAgIHZhciBibHVlT2Zmc2V0ID0gZWxlbVNpemUqaVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBibHVlW2JsdWVPZmZzZXQraXN0YXJ0XVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSAoLWlkeCl8MVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBibHVlW2JsdWVPZmZzZXQraWVuZF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gaWR4fDFcbiAgfVxuXG4gIC8vcHJvY2VzcyBldmVudHMgZnJvbSBsZWZ0LT5yaWdodFxuICB2YXIgbiA9IHB0ciA+Pj4gMVxuICBpc29ydChTV0VFUF9FVkVOVFMsIG4pXG4gIFxuICB2YXIgcmVkQWN0aXZlICAgID0gMFxuICB2YXIgYmx1ZUFjdGl2ZSAgID0gMFxuICB2YXIgY29tbW9uQWN0aXZlID0gMFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICB2YXIgZSAgICAgPSBTV0VFUF9FVkVOVFNbMippKzFdfDBcbiAgICB2YXIgY29sb3IgPSBlJjFcbiAgICBpZihpIDwgbi0xICYmIChlPj4xKSA9PT0gKFNXRUVQX0VWRU5UU1syKmkrM10+PjEpKSB7XG4gICAgICBjb2xvciA9IDJcbiAgICAgIGkgKz0gMVxuICAgIH1cbiAgICBcbiAgICBpZihlIDwgMCkge1xuICAgICAgLy9DcmVhdGUgZXZlbnRcbiAgICAgIHZhciBpZCA9IC0oZT4+MSkgLSAxXG5cbiAgICAgIC8vSW50ZXJzZWN0IHdpdGggY29tbW9uXG4gICAgICBmb3IodmFyIGo9MDsgajxjb21tb25BY3RpdmU7ICsraikge1xuICAgICAgICB2YXIgcmV0dmFsID0gdmlzaXQoQ09NTU9OX1NXRUVQX1FVRVVFW2pdLCBpZClcbiAgICAgICAgaWYocmV0dmFsICE9PSB2b2lkIDApIHtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYoY29sb3IgIT09IDApIHtcbiAgICAgICAgLy9JbnRlcnNlY3Qgd2l0aCByZWRcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8cmVkQWN0aXZlOyArK2opIHtcbiAgICAgICAgICB2YXIgcmV0dmFsID0gdmlzaXQoUkVEX1NXRUVQX1FVRVVFW2pdLCBpZClcbiAgICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgICAgcmV0dXJuIHJldHZhbFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZihjb2xvciAhPT0gMSkge1xuICAgICAgICAvL0ludGVyc2VjdCB3aXRoIGJsdWVcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8Ymx1ZUFjdGl2ZTsgKytqKSB7XG4gICAgICAgICAgdmFyIHJldHZhbCA9IHZpc2l0KEJMVUVfU1dFRVBfUVVFVUVbal0sIGlkKVxuICAgICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgICByZXR1cm4gcmV0dmFsXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmKGNvbG9yID09PSAwKSB7XG4gICAgICAgIC8vUmVkXG4gICAgICAgIHNxUHVzaChSRURfU1dFRVBfUVVFVUUsIFJFRF9TV0VFUF9JTkRFWCwgcmVkQWN0aXZlKyssIGlkKVxuICAgICAgfSBlbHNlIGlmKGNvbG9yID09PSAxKSB7XG4gICAgICAgIC8vQmx1ZVxuICAgICAgICBzcVB1c2goQkxVRV9TV0VFUF9RVUVVRSwgQkxVRV9TV0VFUF9JTkRFWCwgYmx1ZUFjdGl2ZSsrLCBpZClcbiAgICAgIH0gZWxzZSBpZihjb2xvciA9PT0gMikge1xuICAgICAgICAvL0JvdGhcbiAgICAgICAgc3FQdXNoKENPTU1PTl9TV0VFUF9RVUVVRSwgQ09NTU9OX1NXRUVQX0lOREVYLCBjb21tb25BY3RpdmUrKywgaWQpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vRGVzdHJveSBldmVudFxuICAgICAgdmFyIGlkID0gKGU+PjEpIC0gMVxuICAgICAgaWYoY29sb3IgPT09IDApIHtcbiAgICAgICAgLy9SZWRcbiAgICAgICAgc3FQb3AoUkVEX1NXRUVQX1FVRVVFLCBSRURfU1dFRVBfSU5ERVgsIHJlZEFjdGl2ZS0tLCBpZClcbiAgICAgIH0gZWxzZSBpZihjb2xvciA9PT0gMSkge1xuICAgICAgICAvL0JsdWVcbiAgICAgICAgc3FQb3AoQkxVRV9TV0VFUF9RVUVVRSwgQkxVRV9TV0VFUF9JTkRFWCwgYmx1ZUFjdGl2ZS0tLCBpZClcbiAgICAgIH0gZWxzZSBpZihjb2xvciA9PT0gMikge1xuICAgICAgICAvL0JvdGhcbiAgICAgICAgc3FQb3AoQ09NTU9OX1NXRUVQX1FVRVVFLCBDT01NT05fU1dFRVBfSU5ERVgsIGNvbW1vbkFjdGl2ZS0tLCBpZClcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLy9Td2VlcCBhbmQgcHJ1bmUvc2NhbmxpbmUgYWxnb3JpdGhtOlxuLy8gIFNjYW4gYWxvbmcgYXhpcywgZGV0ZWN0IGludGVyc2VjdGlvbnNcbi8vICBCcnV0ZSBmb3JjZSBhbGwgYm94ZXMgYWxvbmcgYXhpc1xuZnVuY3Rpb24gc2NhbkJpcGFydGl0ZShcbiAgZCwgYXhpcywgdmlzaXQsIGZsaXAsXG4gIHJlZFN0YXJ0LCAgcmVkRW5kLCByZWQsIHJlZEluZGV4LFxuICBibHVlU3RhcnQsIGJsdWVFbmQsIGJsdWUsIGJsdWVJbmRleCkge1xuICBcbiAgdmFyIHB0ciAgICAgID0gMFxuICB2YXIgZWxlbVNpemUgPSAyKmRcbiAgdmFyIGlzdGFydCAgID0gYXhpc1xuICB2YXIgaWVuZCAgICAgPSBheGlzK2RcblxuICB2YXIgcmVkU2hpZnQgID0gMVxuICB2YXIgYmx1ZVNoaWZ0ID0gMVxuICBpZihmbGlwKSB7XG4gICAgYmx1ZVNoaWZ0ID0gQkxVRV9GTEFHXG4gIH0gZWxzZSB7XG4gICAgcmVkU2hpZnQgID0gQkxVRV9GTEFHXG4gIH1cblxuICBmb3IodmFyIGk9cmVkU3RhcnQ7IGk8cmVkRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gaSArIHJlZFNoaWZ0XG4gICAgdmFyIHJlZE9mZnNldCA9IGVsZW1TaXplKmlcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gcmVkW3JlZE9mZnNldCtpc3RhcnRdXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IC1pZHhcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gcmVkW3JlZE9mZnNldCtpZW5kXVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSBpZHhcbiAgfVxuICBmb3IodmFyIGk9Ymx1ZVN0YXJ0OyBpPGJsdWVFbmQ7ICsraSkge1xuICAgIHZhciBpZHggPSBpICsgYmx1ZVNoaWZ0XG4gICAgdmFyIGJsdWVPZmZzZXQgPSBlbGVtU2l6ZSppXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IGJsdWVbYmx1ZU9mZnNldCtpc3RhcnRdXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IC1pZHhcbiAgfVxuXG4gIC8vcHJvY2VzcyBldmVudHMgZnJvbSBsZWZ0LT5yaWdodFxuICB2YXIgbiA9IHB0ciA+Pj4gMVxuICBpc29ydChTV0VFUF9FVkVOVFMsIG4pXG4gIFxuICB2YXIgcmVkQWN0aXZlICAgID0gMFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICB2YXIgZSA9IFNXRUVQX0VWRU5UU1syKmkrMV18MFxuICAgIGlmKGUgPCAwKSB7XG4gICAgICB2YXIgaWR4ICAgPSAtZVxuICAgICAgdmFyIGlzUmVkID0gZmFsc2VcbiAgICAgIGlmKGlkeCA+PSBCTFVFX0ZMQUcpIHtcbiAgICAgICAgaXNSZWQgPSAhZmxpcFxuICAgICAgICBpZHggLT0gQkxVRV9GTEFHIFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaXNSZWQgPSAhIWZsaXBcbiAgICAgICAgaWR4IC09IDFcbiAgICAgIH1cbiAgICAgIGlmKGlzUmVkKSB7XG4gICAgICAgIHNxUHVzaChSRURfU1dFRVBfUVVFVUUsIFJFRF9TV0VFUF9JTkRFWCwgcmVkQWN0aXZlKyssIGlkeClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBibHVlSWQgID0gYmx1ZUluZGV4W2lkeF1cbiAgICAgICAgdmFyIGJsdWVQdHIgPSBlbGVtU2l6ZSAqIGlkeFxuICAgICAgICBcbiAgICAgICAgdmFyIGIwID0gYmx1ZVtibHVlUHRyK2F4aXMrMV1cbiAgICAgICAgdmFyIGIxID0gYmx1ZVtibHVlUHRyK2F4aXMrMStkXVxuXG5yZWRfbG9vcDpcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8cmVkQWN0aXZlOyArK2opIHtcbiAgICAgICAgICB2YXIgb2lkeCAgID0gUkVEX1NXRUVQX1FVRVVFW2pdXG4gICAgICAgICAgdmFyIHJlZFB0ciA9IGVsZW1TaXplICogb2lkeFxuXG4gICAgICAgICAgaWYoYjEgPCByZWRbcmVkUHRyK2F4aXMrMV0gfHwgXG4gICAgICAgICAgICAgcmVkW3JlZFB0citheGlzKzErZF0gPCBiMCkge1xuICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmb3IodmFyIGs9YXhpcysyOyBrPGQ7ICsraykge1xuICAgICAgICAgICAgaWYoYmx1ZVtibHVlUHRyICsgayArIGRdIDwgcmVkW3JlZFB0ciArIGtdIHx8IFxuICAgICAgICAgICAgICAgcmVkW3JlZFB0ciArIGsgKyBkXSA8IGJsdWVbYmx1ZVB0ciArIGtdKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIHJlZF9sb29wXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHJlZElkICA9IHJlZEluZGV4W29pZHhdXG4gICAgICAgICAgdmFyIHJldHZhbFxuICAgICAgICAgIGlmKGZsaXApIHtcbiAgICAgICAgICAgIHJldHZhbCA9IHZpc2l0KGJsdWVJZCwgcmVkSWQpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHZhbCA9IHZpc2l0KHJlZElkLCBibHVlSWQpXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKHJldHZhbCAhPT0gdm9pZCAwKSB7XG4gICAgICAgICAgICByZXR1cm4gcmV0dmFsIFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzcVBvcChSRURfU1dFRVBfUVVFVUUsIFJFRF9TV0VFUF9JTkRFWCwgcmVkQWN0aXZlLS0sIGUgLSByZWRTaGlmdClcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gc2NhbkNvbXBsZXRlKFxuICBkLCBheGlzLCB2aXNpdCxcbiAgcmVkU3RhcnQsICByZWRFbmQsIHJlZCwgcmVkSW5kZXgsXG4gIGJsdWVTdGFydCwgYmx1ZUVuZCwgYmx1ZSwgYmx1ZUluZGV4KSB7XG5cbiAgdmFyIHB0ciAgICAgID0gMFxuICB2YXIgZWxlbVNpemUgPSAyKmRcbiAgdmFyIGlzdGFydCAgID0gYXhpc1xuICB2YXIgaWVuZCAgICAgPSBheGlzK2RcblxuICBmb3IodmFyIGk9cmVkU3RhcnQ7IGk8cmVkRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gaSArIEJMVUVfRkxBR1xuICAgIHZhciByZWRPZmZzZXQgPSBlbGVtU2l6ZSppXG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IHJlZFtyZWRPZmZzZXQraXN0YXJ0XVxuICAgIFNXRUVQX0VWRU5UU1twdHIrK10gPSAtaWR4XG4gICAgU1dFRVBfRVZFTlRTW3B0cisrXSA9IHJlZFtyZWRPZmZzZXQraWVuZF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gaWR4XG4gIH1cbiAgZm9yKHZhciBpPWJsdWVTdGFydDsgaTxibHVlRW5kOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gaSArIDFcbiAgICB2YXIgYmx1ZU9mZnNldCA9IGVsZW1TaXplKmlcbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gYmx1ZVtibHVlT2Zmc2V0K2lzdGFydF1cbiAgICBTV0VFUF9FVkVOVFNbcHRyKytdID0gLWlkeFxuICB9XG5cbiAgLy9wcm9jZXNzIGV2ZW50cyBmcm9tIGxlZnQtPnJpZ2h0XG4gIHZhciBuID0gcHRyID4+PiAxXG4gIGlzb3J0KFNXRUVQX0VWRU5UUywgbilcbiAgXG4gIHZhciByZWRBY3RpdmUgICAgPSAwXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHZhciBlID0gU1dFRVBfRVZFTlRTWzIqaSsxXXwwXG4gICAgaWYoZSA8IDApIHtcbiAgICAgIHZhciBpZHggICA9IC1lXG4gICAgICBpZihpZHggPj0gQkxVRV9GTEFHKSB7XG4gICAgICAgIFJFRF9TV0VFUF9RVUVVRVtyZWRBY3RpdmUrK10gPSBpZHggLSBCTFVFX0ZMQUdcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlkeCAtPSAxXG4gICAgICAgIHZhciBibHVlSWQgID0gYmx1ZUluZGV4W2lkeF1cbiAgICAgICAgdmFyIGJsdWVQdHIgPSBlbGVtU2l6ZSAqIGlkeFxuXG4gICAgICAgIHZhciBiMCA9IGJsdWVbYmx1ZVB0citheGlzKzFdXG4gICAgICAgIHZhciBiMSA9IGJsdWVbYmx1ZVB0citheGlzKzErZF1cblxucmVkX2xvb3A6XG4gICAgICAgIGZvcih2YXIgaj0wOyBqPHJlZEFjdGl2ZTsgKytqKSB7XG4gICAgICAgICAgdmFyIG9pZHggICA9IFJFRF9TV0VFUF9RVUVVRVtqXVxuICAgICAgICAgIHZhciByZWRJZCAgPSByZWRJbmRleFtvaWR4XVxuXG4gICAgICAgICAgaWYocmVkSWQgPT09IGJsdWVJZCkge1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcmVkUHRyID0gZWxlbVNpemUgKiBvaWR4XG4gICAgICAgICAgaWYoYjEgPCByZWRbcmVkUHRyK2F4aXMrMV0gfHwgXG4gICAgICAgICAgICByZWRbcmVkUHRyK2F4aXMrMStkXSA8IGIwKSB7XG4gICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgIH1cbiAgICAgICAgICBmb3IodmFyIGs9YXhpcysyOyBrPGQ7ICsraykge1xuICAgICAgICAgICAgaWYoYmx1ZVtibHVlUHRyICsgayArIGRdIDwgcmVkW3JlZFB0ciArIGtdIHx8IFxuICAgICAgICAgICAgICAgcmVkW3JlZFB0ciArIGsgKyBkXSAgIDwgYmx1ZVtibHVlUHRyICsga10pIHtcbiAgICAgICAgICAgICAgY29udGludWUgcmVkX2xvb3BcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcmV0dmFsID0gdmlzaXQocmVkSWQsIGJsdWVJZClcbiAgICAgICAgICBpZihyZXR2YWwgIT09IHZvaWQgMCkge1xuICAgICAgICAgICAgcmV0dXJuIHJldHZhbCBcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGlkeCA9IGUgLSBCTFVFX0ZMQUdcbiAgICAgIGZvcih2YXIgaj1yZWRBY3RpdmUtMTsgaj49MDsgLS1qKSB7XG4gICAgICAgIGlmKFJFRF9TV0VFUF9RVUVVRVtqXSA9PT0gaWR4KSB7XG4gICAgICAgICAgZm9yKHZhciBrPWorMTsgazxyZWRBY3RpdmU7ICsraykge1xuICAgICAgICAgICAgUkVEX1NXRUVQX1FVRVVFW2stMV0gPSBSRURfU1dFRVBfUVVFVUVba11cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLS1yZWRBY3RpdmVcbiAgICB9XG4gIH1cbn1cbn0se1wiLi9zb3J0XCI6MTAxLFwiYml0LXR3aWRkbGVcIjo5MixcInR5cGVkYXJyYXktcG9vbFwiOjU0NX1dLDEwMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cbn0se31dLDEwNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgb2JqZWN0Q3JlYXRlUG9seWZpbGxcbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgb2JqZWN0S2V5c1BvbHlmaWxsXG52YXIgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kIHx8IGZ1bmN0aW9uQmluZFBvbHlmaWxsXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLCAnX2V2ZW50cycpKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbnZhciBkZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbnZhciBoYXNEZWZpbmVQcm9wZXJ0eTtcbnRyeSB7XG4gIHZhciBvID0ge307XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCAneCcsIHsgdmFsdWU6IDAgfSk7XG4gIGhhc0RlZmluZVByb3BlcnR5ID0gby54ID09PSAwO1xufSBjYXRjaCAoZXJyKSB7IGhhc0RlZmluZVByb3BlcnR5ID0gZmFsc2UgfVxuaWYgKGhhc0RlZmluZVByb3BlcnR5KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFdmVudEVtaXR0ZXIsICdkZWZhdWx0TWF4TGlzdGVuZXJzJywge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIGlucHV0IGlzIGEgcG9zaXRpdmUgbnVtYmVyICh3aG9zZSB2YWx1ZSBpcyB6ZXJvIG9yXG4gICAgICAvLyBncmVhdGVyIGFuZCBub3QgYSBOYU4pLlxuICAgICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgYXJnICE9PSBhcmcpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZGVmYXVsdE1heExpc3RlbmVyc1wiIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgICAgIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSBhcmc7XG4gICAgfVxuICB9KTtcbn0gZWxzZSB7XG4gIEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gZGVmYXVsdE1heExpc3RlbmVycztcbn1cblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcIm5cIiBhcmd1bWVudCBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gJGdldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gJGdldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbi8vIFRoZXNlIHN0YW5kYWxvbmUgZW1pdCogZnVuY3Rpb25zIGFyZSB1c2VkIHRvIG9wdGltaXplIGNhbGxpbmcgb2YgZXZlbnRcbi8vIGhhbmRsZXJzIGZvciBmYXN0IGNhc2VzIGJlY2F1c2UgZW1pdCgpIGl0c2VsZiBvZnRlbiBoYXMgYSB2YXJpYWJsZSBudW1iZXIgb2Zcbi8vIGFyZ3VtZW50cyBhbmQgY2FuIGJlIGRlb3B0aW1pemVkIGJlY2F1c2Ugb2YgdGhhdC4gVGhlc2UgZnVuY3Rpb25zIGFsd2F5cyBoYXZlXG4vLyB0aGUgc2FtZSBudW1iZXIgb2YgYXJndW1lbnRzIGFuZCB0aHVzIGRvIG5vdCBnZXQgZGVvcHRpbWl6ZWQsIHNvIHRoZSBjb2RlXG4vLyBpbnNpZGUgdGhlbSBjYW4gZXhlY3V0ZSBmYXN0ZXIuXG5mdW5jdGlvbiBlbWl0Tm9uZShoYW5kbGVyLCBpc0ZuLCBzZWxmKSB7XG4gIGlmIChpc0ZuKVxuICAgIGhhbmRsZXIuY2FsbChzZWxmKTtcbiAgZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHNlbGYpO1xuICB9XG59XG5mdW5jdGlvbiBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSk7XG4gIH1cbn1cbmZ1bmN0aW9uIGVtaXRUd28oaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJnMSwgYXJnMikge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmNhbGwoc2VsZiwgYXJnMSwgYXJnMik7XG4gIGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBsaXN0ZW5lcnNbaV0uY2FsbChzZWxmLCBhcmcxLCBhcmcyKTtcbiAgfVxufVxuZnVuY3Rpb24gZW1pdFRocmVlKGhhbmRsZXIsIGlzRm4sIHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKGlzRm4pXG4gICAgaGFuZGxlci5jYWxsKHNlbGYsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmNhbGwoc2VsZiwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgc2VsZiwgYXJncykge1xuICBpZiAoaXNGbilcbiAgICBoYW5kbGVyLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICBlbHNlIHtcbiAgICB2YXIgbGVuID0gaGFuZGxlci5sZW5ndGg7XG4gICAgdmFyIGxpc3RlbmVycyA9IGFycmF5Q2xvbmUoaGFuZGxlciwgbGVuKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgZXZlbnRzO1xuICB2YXIgZG9FcnJvciA9ICh0eXBlID09PSAnZXJyb3InKTtcblxuICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMpXG4gICAgZG9FcnJvciA9IChkb0Vycm9yICYmIGV2ZW50cy5lcnJvciA9PSBudWxsKTtcbiAgZWxzZSBpZiAoIWRvRXJyb3IpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKGRvRXJyb3IpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpXG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0IGxlYXN0IGdpdmUgc29tZSBraW5kIG9mIGNvbnRleHQgdG8gdGhlIHVzZXJcbiAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoIWhhbmRsZXIpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpc0ZuID0gdHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbic7XG4gIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHN3aXRjaCAobGVuKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgY2FzZSAxOlxuICAgICAgZW1pdE5vbmUoaGFuZGxlciwgaXNGbiwgdGhpcyk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBlbWl0T25lKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDM6XG4gICAgICBlbWl0VHdvKGhhbmRsZXIsIGlzRm4sIHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNDpcbiAgICAgIGVtaXRUaHJlZShoYW5kbGVyLCBpc0ZuLCB0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdKTtcbiAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgZGVmYXVsdDpcbiAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgZW1pdE1hbnkoaGFuZGxlciwgaXNGbiwgdGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIF9hZGRMaXN0ZW5lcih0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBwcmVwZW5kKSB7XG4gIHZhciBtO1xuICB2YXIgZXZlbnRzO1xuICB2YXIgZXhpc3Rpbmc7XG5cbiAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lcikge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA/IGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gICAgICAvLyBSZS1hc3NpZ24gYGV2ZW50c2AgYmVjYXVzZSBhIG5ld0xpc3RlbmVyIGhhbmRsZXIgY291bGQgaGF2ZSBjYXVzZWQgdGhlXG4gICAgICAvLyB0aGlzLl9ldmVudHMgdG8gYmUgYXNzaWduZWQgdG8gYSBuZXcgb2JqZWN0XG4gICAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgICB9XG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV07XG4gIH1cblxuICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICAgIGlmIChwcmVwZW5kKSB7XG4gICAgICAgIGV4aXN0aW5nLnVuc2hpZnQobGlzdGVuZXIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBpZiAoIWV4aXN0aW5nLndhcm5lZCkge1xuICAgICAgbSA9ICRnZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICAgIGlmIChtICYmIG0gPiAwICYmIGV4aXN0aW5nLmxlbmd0aCA+IG0pIHtcbiAgICAgICAgZXhpc3Rpbmcud2FybmVkID0gdHJ1ZTtcbiAgICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICBleGlzdGluZy5sZW5ndGggKyAnIFwiJyArIFN0cmluZyh0eXBlKSArICdcIiBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgJ2luY3JlYXNlIGxpbWl0LicpO1xuICAgICAgICB3Lm5hbWUgPSAnTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nJztcbiAgICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgICB3LmNvdW50ID0gZXhpc3RpbmcubGVuZ3RoO1xuICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgPT09ICdvYmplY3QnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgIGNvbnNvbGUud2FybignJXM6ICVzJywgdy5uYW1lLCB3Lm1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0pO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0LCBhcmd1bWVudHNbMF0sIGFyZ3VtZW50c1sxXSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQsIGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdLFxuICAgICAgICAgICAgYXJndW1lbnRzWzJdKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJncyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IGJpbmQuY2FsbChvbmNlV3JhcHBlciwgc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lciAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RlbmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmICghbGlzdClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgICAgaWYgKGV2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0Lmxpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbGlzdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwb3NpdGlvbiA9IC0xO1xuXG4gICAgICAgIGZvciAoaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHwgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG9yaWdpbmFsTGlzdGVuZXIgPSBsaXN0W2ldLmxpc3RlbmVyO1xuICAgICAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgICBpZiAocG9zaXRpb24gPT09IDApXG4gICAgICAgICAgbGlzdC5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBvcmlnaW5hbExpc3RlbmVyIHx8IGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmICghZXZlbnRzKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICAgICAgaWYgKCFldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gb2JqZWN0Q3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKGV2ZW50cyk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgICAgICB0aGlzLl9ldmVudHMgPSBvYmplY3RDcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gTElGTyBvcmRlclxuICAgICAgICBmb3IgKGkgPSBsaXN0ZW5lcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuZnVuY3Rpb24gX2xpc3RlbmVycyh0YXJnZXQsIHR5cGUsIHVud3JhcCkge1xuICB2YXIgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG5cbiAgaWYgKCFldmVudHMpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoIWV2bGlzdGVuZXIpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/IHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG5cbiAgICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH0gZWxzZSBpZiAoZXZsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdC5vd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbi8vIEFib3V0IDEuNXggZmFzdGVyIHRoYW4gdGhlIHR3by1hcmcgdmVyc2lvbiBvZiBBcnJheSNzcGxpY2UoKS5cbmZ1bmN0aW9uIHNwbGljZU9uZShsaXN0LCBpbmRleCkge1xuICBmb3IgKHZhciBpID0gaW5kZXgsIGsgPSBpICsgMSwgbiA9IGxpc3QubGVuZ3RoOyBrIDwgbjsgaSArPSAxLCBrICs9IDEpXG4gICAgbGlzdFtpXSA9IGxpc3Rba107XG4gIGxpc3QucG9wKCk7XG59XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb2JqZWN0Q3JlYXRlUG9seWZpbGwocHJvdG8pIHtcbiAgdmFyIEYgPSBmdW5jdGlvbigpIHt9O1xuICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICByZXR1cm4gbmV3IEY7XG59XG5mdW5jdGlvbiBvYmplY3RLZXlzUG9seWZpbGwob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGsgaW4gb2JqKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgaykpIHtcbiAgICBrZXlzLnB1c2goayk7XG4gIH1cbiAgcmV0dXJuIGs7XG59XG5mdW5jdGlvbiBmdW5jdGlvbkJpbmRQb2x5ZmlsbChjb250ZXh0KSB7XG4gIHZhciBmbiA9IHRoaXM7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gIH07XG59XG5cbn0se31dLDEwNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4oZnVuY3Rpb24gKEJ1ZmZlcil7XG4vKiFcbiAqIFRoZSBidWZmZXIgbW9kdWxlIGZyb20gbm9kZS5qcywgZm9yIHRoZSBicm93c2VyLlxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cbi8qIGVzbGludC1kaXNhYmxlIG5vLXByb3RvICovXG5cbid1c2Ugc3RyaWN0J1xuXG52YXIgYmFzZTY0ID0gX2RlcmVxXygnYmFzZTY0LWpzJylcbnZhciBpZWVlNzU0ID0gX2RlcmVxXygnaWVlZTc1NCcpXG5cbmV4cG9ydHMuQnVmZmVyID0gQnVmZmVyXG5leHBvcnRzLlNsb3dCdWZmZXIgPSBTbG93QnVmZmVyXG5leHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTID0gNTBcblxudmFyIEtfTUFYX0xFTkdUSCA9IDB4N2ZmZmZmZmZcbmV4cG9ydHMua01heExlbmd0aCA9IEtfTUFYX0xFTkdUSFxuXG4vKipcbiAqIElmIGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGA6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBQcmludCB3YXJuaW5nIGFuZCByZWNvbW1lbmQgdXNpbmcgYGJ1ZmZlcmAgdjQueCB3aGljaCBoYXMgYW4gT2JqZWN0XG4gKiAgICAgICAgICAgICAgIGltcGxlbWVudGF0aW9uIChtb3N0IGNvbXBhdGlibGUsIGV2ZW4gSUU2KVxuICpcbiAqIEJyb3dzZXJzIHRoYXQgc3VwcG9ydCB0eXBlZCBhcnJheXMgYXJlIElFIDEwKywgRmlyZWZveCA0KywgQ2hyb21lIDcrLCBTYWZhcmkgNS4xKyxcbiAqIE9wZXJhIDExLjYrLCBpT1MgNC4yKy5cbiAqXG4gKiBXZSByZXBvcnQgdGhhdCB0aGUgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IHR5cGVkIGFycmF5cyBpZiB0aGUgYXJlIG5vdCBzdWJjbGFzc2FibGVcbiAqIHVzaW5nIF9fcHJvdG9fXy4gRmlyZWZveCA0LTI5IGxhY2tzIHN1cHBvcnQgZm9yIGFkZGluZyBuZXcgcHJvcGVydGllcyB0byBgVWludDhBcnJheWBcbiAqIChTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY5NTQzOCkuIElFIDEwIGxhY2tzIHN1cHBvcnRcbiAqIGZvciBfX3Byb3RvX18gYW5kIGhhcyBhIGJ1Z2d5IHR5cGVkIGFycmF5IGltcGxlbWVudGF0aW9uLlxuICovXG5CdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCA9IHR5cGVkQXJyYXlTdXBwb3J0KClcblxuaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCAmJiB0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICB0eXBlb2YgY29uc29sZS5lcnJvciA9PT0gJ2Z1bmN0aW9uJykge1xuICBjb25zb2xlLmVycm9yKFxuICAgICdUaGlzIGJyb3dzZXIgbGFja3MgdHlwZWQgYXJyYXkgKFVpbnQ4QXJyYXkpIHN1cHBvcnQgd2hpY2ggaXMgcmVxdWlyZWQgYnkgJyArXG4gICAgJ2BidWZmZXJgIHY1LnguIFVzZSBgYnVmZmVyYCB2NC54IGlmIHlvdSByZXF1aXJlIG9sZCBicm93c2VyIHN1cHBvcnQuJ1xuICApXG59XG5cbmZ1bmN0aW9uIHR5cGVkQXJyYXlTdXBwb3J0ICgpIHtcbiAgLy8gQ2FuIHR5cGVkIGFycmF5IGluc3RhbmNlcyBjYW4gYmUgYXVnbWVudGVkP1xuICB0cnkge1xuICAgIHZhciBhcnIgPSBuZXcgVWludDhBcnJheSgxKVxuICAgIGFyci5fX3Byb3RvX18gPSB7IF9fcHJvdG9fXzogVWludDhBcnJheS5wcm90b3R5cGUsIGZvbzogZnVuY3Rpb24gKCkgeyByZXR1cm4gNDIgfSB9XG4gICAgcmV0dXJuIGFyci5mb28oKSA9PT0gNDJcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShCdWZmZXIucHJvdG90eXBlLCAncGFyZW50Jywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcih0aGlzKSkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIHJldHVybiB0aGlzLmJ1ZmZlclxuICB9XG59KVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQnVmZmVyLnByb3RvdHlwZSwgJ29mZnNldCcsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIodGhpcykpIHJldHVybiB1bmRlZmluZWRcbiAgICByZXR1cm4gdGhpcy5ieXRlT2Zmc2V0XG4gIH1cbn0pXG5cbmZ1bmN0aW9uIGNyZWF0ZUJ1ZmZlciAobGVuZ3RoKSB7XG4gIGlmIChsZW5ndGggPiBLX01BWF9MRU5HVEgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVGhlIHZhbHVlIFwiJyArIGxlbmd0aCArICdcIiBpcyBpbnZhbGlkIGZvciBvcHRpb24gXCJzaXplXCInKVxuICB9XG4gIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gIHZhciBidWYgPSBuZXcgVWludDhBcnJheShsZW5ndGgpXG4gIGJ1Zi5fX3Byb3RvX18gPSBCdWZmZXIucHJvdG90eXBlXG4gIHJldHVybiBidWZcbn1cblxuLyoqXG4gKiBUaGUgQnVmZmVyIGNvbnN0cnVjdG9yIHJldHVybnMgaW5zdGFuY2VzIG9mIGBVaW50OEFycmF5YCB0aGF0IGhhdmUgdGhlaXJcbiAqIHByb3RvdHlwZSBjaGFuZ2VkIHRvIGBCdWZmZXIucHJvdG90eXBlYC4gRnVydGhlcm1vcmUsIGBCdWZmZXJgIGlzIGEgc3ViY2xhc3Mgb2ZcbiAqIGBVaW50OEFycmF5YCwgc28gdGhlIHJldHVybmVkIGluc3RhbmNlcyB3aWxsIGhhdmUgYWxsIHRoZSBub2RlIGBCdWZmZXJgIG1ldGhvZHNcbiAqIGFuZCB0aGUgYFVpbnQ4QXJyYXlgIG1ldGhvZHMuIFNxdWFyZSBicmFja2V0IG5vdGF0aW9uIHdvcmtzIGFzIGV4cGVjdGVkIC0tIGl0XG4gKiByZXR1cm5zIGEgc2luZ2xlIG9jdGV0LlxuICpcbiAqIFRoZSBgVWludDhBcnJheWAgcHJvdG90eXBlIHJlbWFpbnMgdW5tb2RpZmllZC5cbiAqL1xuXG5mdW5jdGlvbiBCdWZmZXIgKGFyZywgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKSB7XG4gIC8vIENvbW1vbiBjYXNlLlxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ251bWJlcicpIHtcbiAgICBpZiAodHlwZW9mIGVuY29kaW5nT3JPZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAnVGhlIFwic3RyaW5nXCIgYXJndW1lbnQgbXVzdCBiZSBvZiB0eXBlIHN0cmluZy4gUmVjZWl2ZWQgdHlwZSBudW1iZXInXG4gICAgICApXG4gICAgfVxuICAgIHJldHVybiBhbGxvY1Vuc2FmZShhcmcpXG4gIH1cbiAgcmV0dXJuIGZyb20oYXJnLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG59XG5cbi8vIEZpeCBzdWJhcnJheSgpIGluIEVTMjAxNi4gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlci9wdWxsLzk3XG5pZiAodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnNwZWNpZXMgIT0gbnVsbCAmJlxuICAgIEJ1ZmZlcltTeW1ib2wuc3BlY2llc10gPT09IEJ1ZmZlcikge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQnVmZmVyLCBTeW1ib2wuc3BlY2llcywge1xuICAgIHZhbHVlOiBudWxsLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICB3cml0YWJsZTogZmFsc2VcbiAgfSlcbn1cblxuQnVmZmVyLnBvb2xTaXplID0gODE5MiAvLyBub3QgdXNlZCBieSB0aGlzIGltcGxlbWVudGF0aW9uXG5cbmZ1bmN0aW9uIGZyb20gKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZnJvbVN0cmluZyh2YWx1ZSwgZW5jb2RpbmdPck9mZnNldClcbiAgfVxuXG4gIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcodmFsdWUpKSB7XG4gICAgcmV0dXJuIGZyb21BcnJheUxpa2UodmFsdWUpXG4gIH1cblxuICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgIHRocm93IFR5cGVFcnJvcihcbiAgICAgICdUaGUgZmlyc3QgYXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdHlwZSBzdHJpbmcsIEJ1ZmZlciwgQXJyYXlCdWZmZXIsIEFycmF5LCAnICtcbiAgICAgICdvciBBcnJheS1saWtlIE9iamVjdC4gUmVjZWl2ZWQgdHlwZSAnICsgKHR5cGVvZiB2YWx1ZSlcbiAgICApXG4gIH1cblxuICBpZiAoaXNJbnN0YW5jZSh2YWx1ZSwgQXJyYXlCdWZmZXIpIHx8XG4gICAgICAodmFsdWUgJiYgaXNJbnN0YW5jZSh2YWx1ZS5idWZmZXIsIEFycmF5QnVmZmVyKSkpIHtcbiAgICByZXR1cm4gZnJvbUFycmF5QnVmZmVyKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnVGhlIFwidmFsdWVcIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBvZiB0eXBlIG51bWJlci4gUmVjZWl2ZWQgdHlwZSBudW1iZXInXG4gICAgKVxuICB9XG5cbiAgdmFyIHZhbHVlT2YgPSB2YWx1ZS52YWx1ZU9mICYmIHZhbHVlLnZhbHVlT2YoKVxuICBpZiAodmFsdWVPZiAhPSBudWxsICYmIHZhbHVlT2YgIT09IHZhbHVlKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHZhbHVlT2YsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbiAgfVxuXG4gIHZhciBiID0gZnJvbU9iamVjdCh2YWx1ZSlcbiAgaWYgKGIpIHJldHVybiBiXG5cbiAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1ByaW1pdGl2ZSAhPSBudWxsICYmXG4gICAgICB0eXBlb2YgdmFsdWVbU3ltYm9sLnRvUHJpbWl0aXZlXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShcbiAgICAgIHZhbHVlW1N5bWJvbC50b1ByaW1pdGl2ZV0oJ3N0cmluZycpLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGhcbiAgICApXG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICdUaGUgZmlyc3QgYXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdHlwZSBzdHJpbmcsIEJ1ZmZlciwgQXJyYXlCdWZmZXIsIEFycmF5LCAnICtcbiAgICAnb3IgQXJyYXktbGlrZSBPYmplY3QuIFJlY2VpdmVkIHR5cGUgJyArICh0eXBlb2YgdmFsdWUpXG4gIClcbn1cblxuLyoqXG4gKiBGdW5jdGlvbmFsbHkgZXF1aXZhbGVudCB0byBCdWZmZXIoYXJnLCBlbmNvZGluZykgYnV0IHRocm93cyBhIFR5cGVFcnJvclxuICogaWYgdmFsdWUgaXMgYSBudW1iZXIuXG4gKiBCdWZmZXIuZnJvbShzdHJbLCBlbmNvZGluZ10pXG4gKiBCdWZmZXIuZnJvbShhcnJheSlcbiAqIEJ1ZmZlci5mcm9tKGJ1ZmZlcilcbiAqIEJ1ZmZlci5mcm9tKGFycmF5QnVmZmVyWywgYnl0ZU9mZnNldFssIGxlbmd0aF1dKVxuICoqL1xuQnVmZmVyLmZyb20gPSBmdW5jdGlvbiAodmFsdWUsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gZnJvbSh2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxufVxuXG4vLyBOb3RlOiBDaGFuZ2UgcHJvdG90eXBlICphZnRlciogQnVmZmVyLmZyb20gaXMgZGVmaW5lZCB0byB3b3JrYXJvdW5kIENocm9tZSBidWc6XG4vLyBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlci9wdWxsLzE0OFxuQnVmZmVyLnByb3RvdHlwZS5fX3Byb3RvX18gPSBVaW50OEFycmF5LnByb3RvdHlwZVxuQnVmZmVyLl9fcHJvdG9fXyA9IFVpbnQ4QXJyYXlcblxuZnVuY3Rpb24gYXNzZXJ0U2l6ZSAoc2l6ZSkge1xuICBpZiAodHlwZW9mIHNpemUgIT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJzaXplXCIgYXJndW1lbnQgbXVzdCBiZSBvZiB0eXBlIG51bWJlcicpXG4gIH0gZWxzZSBpZiAoc2l6ZSA8IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVGhlIHZhbHVlIFwiJyArIHNpemUgKyAnXCIgaXMgaW52YWxpZCBmb3Igb3B0aW9uIFwic2l6ZVwiJylcbiAgfVxufVxuXG5mdW5jdGlvbiBhbGxvYyAoc2l6ZSwgZmlsbCwgZW5jb2RpbmcpIHtcbiAgYXNzZXJ0U2l6ZShzaXplKVxuICBpZiAoc2l6ZSA8PSAwKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUJ1ZmZlcihzaXplKVxuICB9XG4gIGlmIChmaWxsICE9PSB1bmRlZmluZWQpIHtcbiAgICAvLyBPbmx5IHBheSBhdHRlbnRpb24gdG8gZW5jb2RpbmcgaWYgaXQncyBhIHN0cmluZy4gVGhpc1xuICAgIC8vIHByZXZlbnRzIGFjY2lkZW50YWxseSBzZW5kaW5nIGluIGEgbnVtYmVyIHRoYXQgd291bGRcbiAgICAvLyBiZSBpbnRlcnByZXR0ZWQgYXMgYSBzdGFydCBvZmZzZXQuXG4gICAgcmV0dXJuIHR5cGVvZiBlbmNvZGluZyA9PT0gJ3N0cmluZydcbiAgICAgID8gY3JlYXRlQnVmZmVyKHNpemUpLmZpbGwoZmlsbCwgZW5jb2RpbmcpXG4gICAgICA6IGNyZWF0ZUJ1ZmZlcihzaXplKS5maWxsKGZpbGwpXG4gIH1cbiAgcmV0dXJuIGNyZWF0ZUJ1ZmZlcihzaXplKVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqIGFsbG9jKHNpemVbLCBmaWxsWywgZW5jb2RpbmddXSlcbiAqKi9cbkJ1ZmZlci5hbGxvYyA9IGZ1bmN0aW9uIChzaXplLCBmaWxsLCBlbmNvZGluZykge1xuICByZXR1cm4gYWxsb2Moc2l6ZSwgZmlsbCwgZW5jb2RpbmcpXG59XG5cbmZ1bmN0aW9uIGFsbG9jVW5zYWZlIChzaXplKSB7XG4gIGFzc2VydFNpemUoc2l6ZSlcbiAgcmV0dXJuIGNyZWF0ZUJ1ZmZlcihzaXplIDwgMCA/IDAgOiBjaGVja2VkKHNpemUpIHwgMClcbn1cblxuLyoqXG4gKiBFcXVpdmFsZW50IHRvIEJ1ZmZlcihudW0pLCBieSBkZWZhdWx0IGNyZWF0ZXMgYSBub24temVyby1maWxsZWQgQnVmZmVyIGluc3RhbmNlLlxuICogKi9cbkJ1ZmZlci5hbGxvY1Vuc2FmZSA9IGZ1bmN0aW9uIChzaXplKSB7XG4gIHJldHVybiBhbGxvY1Vuc2FmZShzaXplKVxufVxuLyoqXG4gKiBFcXVpdmFsZW50IHRvIFNsb3dCdWZmZXIobnVtKSwgYnkgZGVmYXVsdCBjcmVhdGVzIGEgbm9uLXplcm8tZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqL1xuQnVmZmVyLmFsbG9jVW5zYWZlU2xvdyA9IGZ1bmN0aW9uIChzaXplKSB7XG4gIHJldHVybiBhbGxvY1Vuc2FmZShzaXplKVxufVxuXG5mdW5jdGlvbiBmcm9tU3RyaW5nIChzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmICh0eXBlb2YgZW5jb2RpbmcgIT09ICdzdHJpbmcnIHx8IGVuY29kaW5nID09PSAnJykge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gIH1cblxuICBpZiAoIUJ1ZmZlci5pc0VuY29kaW5nKGVuY29kaW5nKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgfVxuXG4gIHZhciBsZW5ndGggPSBieXRlTGVuZ3RoKHN0cmluZywgZW5jb2RpbmcpIHwgMFxuICB2YXIgYnVmID0gY3JlYXRlQnVmZmVyKGxlbmd0aClcblxuICB2YXIgYWN0dWFsID0gYnVmLndyaXRlKHN0cmluZywgZW5jb2RpbmcpXG5cbiAgaWYgKGFjdHVhbCAhPT0gbGVuZ3RoKSB7XG4gICAgLy8gV3JpdGluZyBhIGhleCBzdHJpbmcsIGZvciBleGFtcGxlLCB0aGF0IGNvbnRhaW5zIGludmFsaWQgY2hhcmFjdGVycyB3aWxsXG4gICAgLy8gY2F1c2UgZXZlcnl0aGluZyBhZnRlciB0aGUgZmlyc3QgaW52YWxpZCBjaGFyYWN0ZXIgdG8gYmUgaWdub3JlZC4gKGUuZy5cbiAgICAvLyAnYWJ4eGNkJyB3aWxsIGJlIHRyZWF0ZWQgYXMgJ2FiJylcbiAgICBidWYgPSBidWYuc2xpY2UoMCwgYWN0dWFsKVxuICB9XG5cbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXlMaWtlIChhcnJheSkge1xuICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoIDwgMCA/IDAgOiBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHZhciBidWYgPSBjcmVhdGVCdWZmZXIobGVuZ3RoKVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgYnVmW2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUJ1ZmZlciAoYXJyYXksIGJ5dGVPZmZzZXQsIGxlbmd0aCkge1xuICBpZiAoYnl0ZU9mZnNldCA8IDAgfHwgYXJyYXkuYnl0ZUxlbmd0aCA8IGJ5dGVPZmZzZXQpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJvZmZzZXRcIiBpcyBvdXRzaWRlIG9mIGJ1ZmZlciBib3VuZHMnKVxuICB9XG5cbiAgaWYgKGFycmF5LmJ5dGVMZW5ndGggPCBieXRlT2Zmc2V0ICsgKGxlbmd0aCB8fCAwKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcImxlbmd0aFwiIGlzIG91dHNpZGUgb2YgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICB2YXIgYnVmXG4gIGlmIChieXRlT2Zmc2V0ID09PSB1bmRlZmluZWQgJiYgbGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBidWYgPSBuZXcgVWludDhBcnJheShhcnJheSlcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGFycmF5LCBieXRlT2Zmc2V0KVxuICB9IGVsc2Uge1xuICAgIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGFycmF5LCBieXRlT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICAvLyBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZVxuICBidWYuX19wcm90b19fID0gQnVmZmVyLnByb3RvdHlwZVxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGZyb21PYmplY3QgKG9iaikge1xuICBpZiAoQnVmZmVyLmlzQnVmZmVyKG9iaikpIHtcbiAgICB2YXIgbGVuID0gY2hlY2tlZChvYmoubGVuZ3RoKSB8IDBcbiAgICB2YXIgYnVmID0gY3JlYXRlQnVmZmVyKGxlbilcblxuICAgIGlmIChidWYubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gYnVmXG4gICAgfVxuXG4gICAgb2JqLmNvcHkoYnVmLCAwLCAwLCBsZW4pXG4gICAgcmV0dXJuIGJ1ZlxuICB9XG5cbiAgaWYgKG9iai5sZW5ndGggIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICh0eXBlb2Ygb2JqLmxlbmd0aCAhPT0gJ251bWJlcicgfHwgbnVtYmVySXNOYU4ob2JqLmxlbmd0aCkpIHtcbiAgICAgIHJldHVybiBjcmVhdGVCdWZmZXIoMClcbiAgICB9XG4gICAgcmV0dXJuIGZyb21BcnJheUxpa2Uob2JqKVxuICB9XG5cbiAgaWYgKG9iai50eXBlID09PSAnQnVmZmVyJyAmJiBBcnJheS5pc0FycmF5KG9iai5kYXRhKSkge1xuICAgIHJldHVybiBmcm9tQXJyYXlMaWtlKG9iai5kYXRhKVxuICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrZWQgKGxlbmd0aCkge1xuICAvLyBOb3RlOiBjYW5ub3QgdXNlIGBsZW5ndGggPCBLX01BWF9MRU5HVEhgIGhlcmUgYmVjYXVzZSB0aGF0IGZhaWxzIHdoZW5cbiAgLy8gbGVuZ3RoIGlzIE5hTiAod2hpY2ggaXMgb3RoZXJ3aXNlIGNvZXJjZWQgdG8gemVyby4pXG4gIGlmIChsZW5ndGggPj0gS19NQVhfTEVOR1RIKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gYWxsb2NhdGUgQnVmZmVyIGxhcmdlciB0aGFuIG1heGltdW0gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemU6IDB4JyArIEtfTUFYX0xFTkdUSC50b1N0cmluZygxNikgKyAnIGJ5dGVzJylcbiAgfVxuICByZXR1cm4gbGVuZ3RoIHwgMFxufVxuXG5mdW5jdGlvbiBTbG93QnVmZmVyIChsZW5ndGgpIHtcbiAgaWYgKCtsZW5ndGggIT0gbGVuZ3RoKSB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgZXFlcWVxXG4gICAgbGVuZ3RoID0gMFxuICB9XG4gIHJldHVybiBCdWZmZXIuYWxsb2MoK2xlbmd0aClcbn1cblxuQnVmZmVyLmlzQnVmZmVyID0gZnVuY3Rpb24gaXNCdWZmZXIgKGIpIHtcbiAgcmV0dXJuIGIgIT0gbnVsbCAmJiBiLl9pc0J1ZmZlciA9PT0gdHJ1ZSAmJlxuICAgIGIgIT09IEJ1ZmZlci5wcm90b3R5cGUgLy8gc28gQnVmZmVyLmlzQnVmZmVyKEJ1ZmZlci5wcm90b3R5cGUpIHdpbGwgYmUgZmFsc2Vcbn1cblxuQnVmZmVyLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlIChhLCBiKSB7XG4gIGlmIChpc0luc3RhbmNlKGEsIFVpbnQ4QXJyYXkpKSBhID0gQnVmZmVyLmZyb20oYSwgYS5vZmZzZXQsIGEuYnl0ZUxlbmd0aClcbiAgaWYgKGlzSW5zdGFuY2UoYiwgVWludDhBcnJheSkpIGIgPSBCdWZmZXIuZnJvbShiLCBiLm9mZnNldCwgYi5ieXRlTGVuZ3RoKVxuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihhKSB8fCAhQnVmZmVyLmlzQnVmZmVyKGIpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdUaGUgXCJidWYxXCIsIFwiYnVmMlwiIGFyZ3VtZW50cyBtdXN0IGJlIG9uZSBvZiB0eXBlIEJ1ZmZlciBvciBVaW50OEFycmF5J1xuICAgIClcbiAgfVxuXG4gIGlmIChhID09PSBiKSByZXR1cm4gMFxuXG4gIHZhciB4ID0gYS5sZW5ndGhcbiAgdmFyIHkgPSBiLmxlbmd0aFxuXG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBNYXRoLm1pbih4LCB5KTsgaSA8IGxlbjsgKytpKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIHtcbiAgICAgIHggPSBhW2ldXG4gICAgICB5ID0gYltpXVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbkJ1ZmZlci5pc0VuY29kaW5nID0gZnVuY3Rpb24gaXNFbmNvZGluZyAoZW5jb2RpbmcpIHtcbiAgc3dpdGNoIChTdHJpbmcoZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnbGF0aW4xJzpcbiAgICBjYXNlICdiaW5hcnknOlxuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQgKGxpc3QsIGxlbmd0aCkge1xuICBpZiAoIUFycmF5LmlzQXJyYXkobGlzdCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RcIiBhcmd1bWVudCBtdXN0IGJlIGFuIEFycmF5IG9mIEJ1ZmZlcnMnKVxuICB9XG5cbiAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5hbGxvYygwKVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbGVuZ3RoID0gMFxuICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBsZW5ndGggKz0gbGlzdFtpXS5sZW5ndGhcbiAgICB9XG4gIH1cblxuICB2YXIgYnVmZmVyID0gQnVmZmVyLmFsbG9jVW5zYWZlKGxlbmd0aClcbiAgdmFyIHBvcyA9IDBcbiAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYnVmID0gbGlzdFtpXVxuICAgIGlmIChpc0luc3RhbmNlKGJ1ZiwgVWludDhBcnJheSkpIHtcbiAgICAgIGJ1ZiA9IEJ1ZmZlci5mcm9tKGJ1ZilcbiAgICB9XG4gICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJylcbiAgICB9XG4gICAgYnVmLmNvcHkoYnVmZmVyLCBwb3MpXG4gICAgcG9zICs9IGJ1Zi5sZW5ndGhcbiAgfVxuICByZXR1cm4gYnVmZmVyXG59XG5cbmZ1bmN0aW9uIGJ5dGVMZW5ndGggKHN0cmluZywgZW5jb2RpbmcpIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihzdHJpbmcpKSB7XG4gICAgcmV0dXJuIHN0cmluZy5sZW5ndGhcbiAgfVxuICBpZiAoQXJyYXlCdWZmZXIuaXNWaWV3KHN0cmluZykgfHwgaXNJbnN0YW5jZShzdHJpbmcsIEFycmF5QnVmZmVyKSkge1xuICAgIHJldHVybiBzdHJpbmcuYnl0ZUxlbmd0aFxuICB9XG4gIGlmICh0eXBlb2Ygc3RyaW5nICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnVGhlIFwic3RyaW5nXCIgYXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdHlwZSBzdHJpbmcsIEJ1ZmZlciwgb3IgQXJyYXlCdWZmZXIuICcgK1xuICAgICAgJ1JlY2VpdmVkIHR5cGUgJyArIHR5cGVvZiBzdHJpbmdcbiAgICApXG4gIH1cblxuICB2YXIgbGVuID0gc3RyaW5nLmxlbmd0aFxuICB2YXIgbXVzdE1hdGNoID0gKGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSA9PT0gdHJ1ZSlcbiAgaWYgKCFtdXN0TWF0Y2ggJiYgbGVuID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIFVzZSBhIGZvciBsb29wIHRvIGF2b2lkIHJlY3Vyc2lvblxuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuICBmb3IgKDs7KSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBsZW5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiBsZW4gKiAyXG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gbGVuID4+PiAxXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0VG9CeXRlcyhzdHJpbmcpLmxlbmd0aFxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB7XG4gICAgICAgICAgcmV0dXJuIG11c3RNYXRjaCA/IC0xIDogdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGggLy8gYXNzdW1lIHV0ZjhcbiAgICAgICAgfVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuQnVmZmVyLmJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoXG5cbmZ1bmN0aW9uIHNsb3dUb1N0cmluZyAoZW5jb2RpbmcsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcblxuICAvLyBObyBuZWVkIHRvIHZlcmlmeSB0aGF0IFwidGhpcy5sZW5ndGggPD0gTUFYX1VJTlQzMlwiIHNpbmNlIGl0J3MgYSByZWFkLW9ubHlcbiAgLy8gcHJvcGVydHkgb2YgYSB0eXBlZCBhcnJheS5cblxuICAvLyBUaGlzIGJlaGF2ZXMgbmVpdGhlciBsaWtlIFN0cmluZyBub3IgVWludDhBcnJheSBpbiB0aGF0IHdlIHNldCBzdGFydC9lbmRcbiAgLy8gdG8gdGhlaXIgdXBwZXIvbG93ZXIgYm91bmRzIGlmIHRoZSB2YWx1ZSBwYXNzZWQgaXMgb3V0IG9mIHJhbmdlLlxuICAvLyB1bmRlZmluZWQgaXMgaGFuZGxlZCBzcGVjaWFsbHkgYXMgcGVyIEVDTUEtMjYyIDZ0aCBFZGl0aW9uLFxuICAvLyBTZWN0aW9uIDEzLjMuMy43IFJ1bnRpbWUgU2VtYW50aWNzOiBLZXllZEJpbmRpbmdJbml0aWFsaXphdGlvbi5cbiAgaWYgKHN0YXJ0ID09PSB1bmRlZmluZWQgfHwgc3RhcnQgPCAwKSB7XG4gICAgc3RhcnQgPSAwXG4gIH1cbiAgLy8gUmV0dXJuIGVhcmx5IGlmIHN0YXJ0ID4gdGhpcy5sZW5ndGguIERvbmUgaGVyZSB0byBwcmV2ZW50IHBvdGVudGlhbCB1aW50MzJcbiAgLy8gY29lcmNpb24gZmFpbCBiZWxvdy5cbiAgaWYgKHN0YXJ0ID4gdGhpcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIGlmIChlbmQgPT09IHVuZGVmaW5lZCB8fCBlbmQgPiB0aGlzLmxlbmd0aCkge1xuICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gIH1cblxuICBpZiAoZW5kIDw9IDApIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIC8vIEZvcmNlIGNvZXJzaW9uIHRvIHVpbnQzMi4gVGhpcyB3aWxsIGFsc28gY29lcmNlIGZhbHNleS9OYU4gdmFsdWVzIHRvIDAuXG4gIGVuZCA+Pj49IDBcbiAgc3RhcnQgPj4+PSAwXG5cbiAgaWYgKGVuZCA8PSBzdGFydCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcblxuICB3aGlsZSAodHJ1ZSkge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBoZXhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICAgIHJldHVybiBhc2NpaVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2xhdGluMSc6XG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gbGF0aW4xU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1dGYxNmxlU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKGVuY29kaW5nICsgJycpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbi8vIFRoaXMgcHJvcGVydHkgaXMgdXNlZCBieSBgQnVmZmVyLmlzQnVmZmVyYCAoYW5kIHRoZSBgaXMtYnVmZmVyYCBucG0gcGFja2FnZSlcbi8vIHRvIGRldGVjdCBhIEJ1ZmZlciBpbnN0YW5jZS4gSXQncyBub3QgcG9zc2libGUgdG8gdXNlIGBpbnN0YW5jZW9mIEJ1ZmZlcmBcbi8vIHJlbGlhYmx5IGluIGEgYnJvd3NlcmlmeSBjb250ZXh0IGJlY2F1c2UgdGhlcmUgY291bGQgYmUgbXVsdGlwbGUgZGlmZmVyZW50XG4vLyBjb3BpZXMgb2YgdGhlICdidWZmZXInIHBhY2thZ2UgaW4gdXNlLiBUaGlzIG1ldGhvZCB3b3JrcyBldmVuIGZvciBCdWZmZXJcbi8vIGluc3RhbmNlcyB0aGF0IHdlcmUgY3JlYXRlZCBmcm9tIGFub3RoZXIgY29weSBvZiB0aGUgYGJ1ZmZlcmAgcGFja2FnZS5cbi8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvaXNzdWVzLzE1NFxuQnVmZmVyLnByb3RvdHlwZS5faXNCdWZmZXIgPSB0cnVlXG5cbmZ1bmN0aW9uIHN3YXAgKGIsIG4sIG0pIHtcbiAgdmFyIGkgPSBiW25dXG4gIGJbbl0gPSBiW21dXG4gIGJbbV0gPSBpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc3dhcDE2ID0gZnVuY3Rpb24gc3dhcDE2ICgpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIGlmIChsZW4gJSAyICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAxNi1iaXRzJylcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSArPSAyKSB7XG4gICAgc3dhcCh0aGlzLCBpLCBpICsgMSlcbiAgfVxuICByZXR1cm4gdGhpc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnN3YXAzMiA9IGZ1bmN0aW9uIHN3YXAzMiAoKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgNCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMzItYml0cycpXG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkgKz0gNCkge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDMpXG4gICAgc3dhcCh0aGlzLCBpICsgMSwgaSArIDIpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwNjQgPSBmdW5jdGlvbiBzd2FwNjQgKCkge1xuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgaWYgKGxlbiAlIDggIT09IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQnVmZmVyIHNpemUgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDY0LWJpdHMnKVxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpICs9IDgpIHtcbiAgICBzd2FwKHRoaXMsIGksIGkgKyA3KVxuICAgIHN3YXAodGhpcywgaSArIDEsIGkgKyA2KVxuICAgIHN3YXAodGhpcywgaSArIDIsIGkgKyA1KVxuICAgIHN3YXAodGhpcywgaSArIDMsIGkgKyA0KVxuICB9XG4gIHJldHVybiB0aGlzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZyAoKSB7XG4gIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuZ3RoID09PSAwKSByZXR1cm4gJydcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHJldHVybiB1dGY4U2xpY2UodGhpcywgMCwgbGVuZ3RoKVxuICByZXR1cm4gc2xvd1RvU3RyaW5nLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b0xvY2FsZVN0cmluZyA9IEJ1ZmZlci5wcm90b3R5cGUudG9TdHJpbmdcblxuQnVmZmVyLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiBlcXVhbHMgKGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICBpZiAodGhpcyA9PT0gYikgcmV0dXJuIHRydWVcbiAgcmV0dXJuIEJ1ZmZlci5jb21wYXJlKHRoaXMsIGIpID09PSAwXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5zcGVjdCA9IGZ1bmN0aW9uIGluc3BlY3QgKCkge1xuICB2YXIgc3RyID0gJydcbiAgdmFyIG1heCA9IGV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVNcbiAgc3RyID0gdGhpcy50b1N0cmluZygnaGV4JywgMCwgbWF4KS5yZXBsYWNlKC8oLnsyfSkvZywgJyQxICcpLnRyaW0oKVxuICBpZiAodGhpcy5sZW5ndGggPiBtYXgpIHN0ciArPSAnIC4uLiAnXG4gIHJldHVybiAnPEJ1ZmZlciAnICsgc3RyICsgJz4nXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKHRhcmdldCwgc3RhcnQsIGVuZCwgdGhpc1N0YXJ0LCB0aGlzRW5kKSB7XG4gIGlmIChpc0luc3RhbmNlKHRhcmdldCwgVWludDhBcnJheSkpIHtcbiAgICB0YXJnZXQgPSBCdWZmZXIuZnJvbSh0YXJnZXQsIHRhcmdldC5vZmZzZXQsIHRhcmdldC5ieXRlTGVuZ3RoKVxuICB9XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKHRhcmdldCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ1RoZSBcInRhcmdldFwiIGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgQnVmZmVyIG9yIFVpbnQ4QXJyYXkuICcgK1xuICAgICAgJ1JlY2VpdmVkIHR5cGUgJyArICh0eXBlb2YgdGFyZ2V0KVxuICAgIClcbiAgfVxuXG4gIGlmIChzdGFydCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgc3RhcnQgPSAwXG4gIH1cbiAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZW5kID0gdGFyZ2V0ID8gdGFyZ2V0Lmxlbmd0aCA6IDBcbiAgfVxuICBpZiAodGhpc1N0YXJ0ID09PSB1bmRlZmluZWQpIHtcbiAgICB0aGlzU3RhcnQgPSAwXG4gIH1cbiAgaWYgKHRoaXNFbmQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRoaXNFbmQgPSB0aGlzLmxlbmd0aFxuICB9XG5cbiAgaWYgKHN0YXJ0IDwgMCB8fCBlbmQgPiB0YXJnZXQubGVuZ3RoIHx8IHRoaXNTdGFydCA8IDAgfHwgdGhpc0VuZCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ291dCBvZiByYW5nZSBpbmRleCcpXG4gIH1cblxuICBpZiAodGhpc1N0YXJ0ID49IHRoaXNFbmQgJiYgc3RhcnQgPj0gZW5kKSB7XG4gICAgcmV0dXJuIDBcbiAgfVxuICBpZiAodGhpc1N0YXJ0ID49IHRoaXNFbmQpIHtcbiAgICByZXR1cm4gLTFcbiAgfVxuICBpZiAoc3RhcnQgPj0gZW5kKSB7XG4gICAgcmV0dXJuIDFcbiAgfVxuXG4gIHN0YXJ0ID4+Pj0gMFxuICBlbmQgPj4+PSAwXG4gIHRoaXNTdGFydCA+Pj49IDBcbiAgdGhpc0VuZCA+Pj49IDBcblxuICBpZiAodGhpcyA9PT0gdGFyZ2V0KSByZXR1cm4gMFxuXG4gIHZhciB4ID0gdGhpc0VuZCAtIHRoaXNTdGFydFxuICB2YXIgeSA9IGVuZCAtIHN0YXJ0XG4gIHZhciBsZW4gPSBNYXRoLm1pbih4LCB5KVxuXG4gIHZhciB0aGlzQ29weSA9IHRoaXMuc2xpY2UodGhpc1N0YXJ0LCB0aGlzRW5kKVxuICB2YXIgdGFyZ2V0Q29weSA9IHRhcmdldC5zbGljZShzdGFydCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICBpZiAodGhpc0NvcHlbaV0gIT09IHRhcmdldENvcHlbaV0pIHtcbiAgICAgIHggPSB0aGlzQ29weVtpXVxuICAgICAgeSA9IHRhcmdldENvcHlbaV1cbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgaWYgKHggPCB5KSByZXR1cm4gLTFcbiAgaWYgKHkgPCB4KSByZXR1cm4gMVxuICByZXR1cm4gMFxufVxuXG4vLyBGaW5kcyBlaXRoZXIgdGhlIGZpcnN0IGluZGV4IG9mIGB2YWxgIGluIGBidWZmZXJgIGF0IG9mZnNldCA+PSBgYnl0ZU9mZnNldGAsXG4vLyBPUiB0aGUgbGFzdCBpbmRleCBvZiBgdmFsYCBpbiBgYnVmZmVyYCBhdCBvZmZzZXQgPD0gYGJ5dGVPZmZzZXRgLlxuLy9cbi8vIEFyZ3VtZW50czpcbi8vIC0gYnVmZmVyIC0gYSBCdWZmZXIgdG8gc2VhcmNoXG4vLyAtIHZhbCAtIGEgc3RyaW5nLCBCdWZmZXIsIG9yIG51bWJlclxuLy8gLSBieXRlT2Zmc2V0IC0gYW4gaW5kZXggaW50byBgYnVmZmVyYDsgd2lsbCBiZSBjbGFtcGVkIHRvIGFuIGludDMyXG4vLyAtIGVuY29kaW5nIC0gYW4gb3B0aW9uYWwgZW5jb2RpbmcsIHJlbGV2YW50IGlzIHZhbCBpcyBhIHN0cmluZ1xuLy8gLSBkaXIgLSB0cnVlIGZvciBpbmRleE9mLCBmYWxzZSBmb3IgbGFzdEluZGV4T2ZcbmZ1bmN0aW9uIGJpZGlyZWN0aW9uYWxJbmRleE9mIChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGRpcikge1xuICAvLyBFbXB0eSBidWZmZXIgbWVhbnMgbm8gbWF0Y2hcbiAgaWYgKGJ1ZmZlci5sZW5ndGggPT09IDApIHJldHVybiAtMVxuXG4gIC8vIE5vcm1hbGl6ZSBieXRlT2Zmc2V0XG4gIGlmICh0eXBlb2YgYnl0ZU9mZnNldCA9PT0gJ3N0cmluZycpIHtcbiAgICBlbmNvZGluZyA9IGJ5dGVPZmZzZXRcbiAgICBieXRlT2Zmc2V0ID0gMFxuICB9IGVsc2UgaWYgKGJ5dGVPZmZzZXQgPiAweDdmZmZmZmZmKSB7XG4gICAgYnl0ZU9mZnNldCA9IDB4N2ZmZmZmZmZcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0IDwgLTB4ODAwMDAwMDApIHtcbiAgICBieXRlT2Zmc2V0ID0gLTB4ODAwMDAwMDBcbiAgfVxuICBieXRlT2Zmc2V0ID0gK2J5dGVPZmZzZXQgLy8gQ29lcmNlIHRvIE51bWJlci5cbiAgaWYgKG51bWJlcklzTmFOKGJ5dGVPZmZzZXQpKSB7XG4gICAgLy8gYnl0ZU9mZnNldDogaXQgaXQncyB1bmRlZmluZWQsIG51bGwsIE5hTiwgXCJmb29cIiwgZXRjLCBzZWFyY2ggd2hvbGUgYnVmZmVyXG4gICAgYnl0ZU9mZnNldCA9IGRpciA/IDAgOiAoYnVmZmVyLmxlbmd0aCAtIDEpXG4gIH1cblxuICAvLyBOb3JtYWxpemUgYnl0ZU9mZnNldDogbmVnYXRpdmUgb2Zmc2V0cyBzdGFydCBmcm9tIHRoZSBlbmQgb2YgdGhlIGJ1ZmZlclxuICBpZiAoYnl0ZU9mZnNldCA8IDApIGJ5dGVPZmZzZXQgPSBidWZmZXIubGVuZ3RoICsgYnl0ZU9mZnNldFxuICBpZiAoYnl0ZU9mZnNldCA+PSBidWZmZXIubGVuZ3RoKSB7XG4gICAgaWYgKGRpcikgcmV0dXJuIC0xXG4gICAgZWxzZSBieXRlT2Zmc2V0ID0gYnVmZmVyLmxlbmd0aCAtIDFcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0IDwgMCkge1xuICAgIGlmIChkaXIpIGJ5dGVPZmZzZXQgPSAwXG4gICAgZWxzZSByZXR1cm4gLTFcbiAgfVxuXG4gIC8vIE5vcm1hbGl6ZSB2YWxcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgdmFsID0gQnVmZmVyLmZyb20odmFsLCBlbmNvZGluZylcbiAgfVxuXG4gIC8vIEZpbmFsbHksIHNlYXJjaCBlaXRoZXIgaW5kZXhPZiAoaWYgZGlyIGlzIHRydWUpIG9yIGxhc3RJbmRleE9mXG4gIGlmIChCdWZmZXIuaXNCdWZmZXIodmFsKSkge1xuICAgIC8vIFNwZWNpYWwgY2FzZTogbG9va2luZyBmb3IgZW1wdHkgc3RyaW5nL2J1ZmZlciBhbHdheXMgZmFpbHNcbiAgICBpZiAodmFsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIC0xXG4gICAgfVxuICAgIHJldHVybiBhcnJheUluZGV4T2YoYnVmZmVyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpXG4gIH0gZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICB2YWwgPSB2YWwgJiAweEZGIC8vIFNlYXJjaCBmb3IgYSBieXRlIHZhbHVlIFswLTI1NV1cbiAgICBpZiAodHlwZW9mIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGlmIChkaXIpIHtcbiAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBVaW50OEFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZi5jYWxsKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0KVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKGJ1ZmZlciwgWyB2YWwgXSwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGRpcilcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZhbCBtdXN0IGJlIHN0cmluZywgbnVtYmVyIG9yIEJ1ZmZlcicpXG59XG5cbmZ1bmN0aW9uIGFycmF5SW5kZXhPZiAoYXJyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpIHtcbiAgdmFyIGluZGV4U2l6ZSA9IDFcbiAgdmFyIGFyckxlbmd0aCA9IGFyci5sZW5ndGhcbiAgdmFyIHZhbExlbmd0aCA9IHZhbC5sZW5ndGhcblxuICBpZiAoZW5jb2RpbmcgIT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgaWYgKGVuY29kaW5nID09PSAndWNzMicgfHwgZW5jb2RpbmcgPT09ICd1Y3MtMicgfHxcbiAgICAgICAgZW5jb2RpbmcgPT09ICd1dGYxNmxlJyB8fCBlbmNvZGluZyA9PT0gJ3V0Zi0xNmxlJykge1xuICAgICAgaWYgKGFyci5sZW5ndGggPCAyIHx8IHZhbC5sZW5ndGggPCAyKSB7XG4gICAgICAgIHJldHVybiAtMVxuICAgICAgfVxuICAgICAgaW5kZXhTaXplID0gMlxuICAgICAgYXJyTGVuZ3RoIC89IDJcbiAgICAgIHZhbExlbmd0aCAvPSAyXG4gICAgICBieXRlT2Zmc2V0IC89IDJcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiByZWFkIChidWYsIGkpIHtcbiAgICBpZiAoaW5kZXhTaXplID09PSAxKSB7XG4gICAgICByZXR1cm4gYnVmW2ldXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBidWYucmVhZFVJbnQxNkJFKGkgKiBpbmRleFNpemUpXG4gICAgfVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKGRpcikge1xuICAgIHZhciBmb3VuZEluZGV4ID0gLTFcbiAgICBmb3IgKGkgPSBieXRlT2Zmc2V0OyBpIDwgYXJyTGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChyZWFkKGFyciwgaSkgPT09IHJlYWQodmFsLCBmb3VuZEluZGV4ID09PSAtMSA/IDAgOiBpIC0gZm91bmRJbmRleCkpIHtcbiAgICAgICAgaWYgKGZvdW5kSW5kZXggPT09IC0xKSBmb3VuZEluZGV4ID0gaVxuICAgICAgICBpZiAoaSAtIGZvdW5kSW5kZXggKyAxID09PSB2YWxMZW5ndGgpIHJldHVybiBmb3VuZEluZGV4ICogaW5kZXhTaXplXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZm91bmRJbmRleCAhPT0gLTEpIGkgLT0gaSAtIGZvdW5kSW5kZXhcbiAgICAgICAgZm91bmRJbmRleCA9IC0xXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChieXRlT2Zmc2V0ICsgdmFsTGVuZ3RoID4gYXJyTGVuZ3RoKSBieXRlT2Zmc2V0ID0gYXJyTGVuZ3RoIC0gdmFsTGVuZ3RoXG4gICAgZm9yIChpID0gYnl0ZU9mZnNldDsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHZhciBmb3VuZCA9IHRydWVcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdmFsTGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWYgKHJlYWQoYXJyLCBpICsgaikgIT09IHJlYWQodmFsLCBqKSkge1xuICAgICAgICAgIGZvdW5kID0gZmFsc2VcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZm91bmQpIHJldHVybiBpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIC0xXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5jbHVkZXMgPSBmdW5jdGlvbiBpbmNsdWRlcyAodmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZykge1xuICByZXR1cm4gdGhpcy5pbmRleE9mKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpICE9PSAtMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluZGV4T2YgPSBmdW5jdGlvbiBpbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSB7XG4gIHJldHVybiBiaWRpcmVjdGlvbmFsSW5kZXhPZih0aGlzLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCB0cnVlKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmxhc3RJbmRleE9mID0gZnVuY3Rpb24gbGFzdEluZGV4T2YgKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIGJpZGlyZWN0aW9uYWxJbmRleE9mKHRoaXMsIHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGZhbHNlKVxufVxuXG5mdW5jdGlvbiBoZXhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcbiAgdmFyIHJlbWFpbmluZyA9IGJ1Zi5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKCFsZW5ndGgpIHtcbiAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgfSBlbHNlIHtcbiAgICBsZW5ndGggPSBOdW1iZXIobGVuZ3RoKVxuICAgIGlmIChsZW5ndGggPiByZW1haW5pbmcpIHtcbiAgICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICAgIH1cbiAgfVxuXG4gIHZhciBzdHJMZW4gPSBzdHJpbmcubGVuZ3RoXG5cbiAgaWYgKGxlbmd0aCA+IHN0ckxlbiAvIDIpIHtcbiAgICBsZW5ndGggPSBzdHJMZW4gLyAyXG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIHZhciBwYXJzZWQgPSBwYXJzZUludChzdHJpbmcuc3Vic3RyKGkgKiAyLCAyKSwgMTYpXG4gICAgaWYgKG51bWJlcklzTmFOKHBhcnNlZCkpIHJldHVybiBpXG4gICAgYnVmW29mZnNldCArIGldID0gcGFyc2VkXG4gIH1cbiAgcmV0dXJuIGlcbn1cblxuZnVuY3Rpb24gdXRmOFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIodXRmOFRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYXNjaWlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKGFzY2lpVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBsYXRpbjFXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBhc2NpaVdyaXRlKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYmFzZTY0V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcihiYXNlNjRUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIHVjczJXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjE2bGVUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiB3cml0ZSAoc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCwgZW5jb2RpbmcpIHtcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZylcbiAgaWYgKG9mZnNldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZW5jb2RpbmcgPSAndXRmOCdcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgZW5jb2RpbmcpXG4gIH0gZWxzZSBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQgJiYgdHlwZW9mIG9mZnNldCA9PT0gJ3N0cmluZycpIHtcbiAgICBlbmNvZGluZyA9IG9mZnNldFxuICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gICAgb2Zmc2V0ID0gMFxuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nLCBvZmZzZXRbLCBsZW5ndGhdWywgZW5jb2RpbmddKVxuICB9IGVsc2UgaWYgKGlzRmluaXRlKG9mZnNldCkpIHtcbiAgICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgICBpZiAoaXNGaW5pdGUobGVuZ3RoKSkge1xuICAgICAgbGVuZ3RoID0gbGVuZ3RoID4+PiAwXG4gICAgICBpZiAoZW5jb2RpbmcgPT09IHVuZGVmaW5lZCkgZW5jb2RpbmcgPSAndXRmOCdcbiAgICB9IGVsc2Uge1xuICAgICAgZW5jb2RpbmcgPSBsZW5ndGhcbiAgICAgIGxlbmd0aCA9IHVuZGVmaW5lZFxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnQnVmZmVyLndyaXRlKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldFssIGxlbmd0aF0pIGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQnXG4gICAgKVxuICB9XG5cbiAgdmFyIHJlbWFpbmluZyA9IHRoaXMubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCB8fCBsZW5ndGggPiByZW1haW5pbmcpIGxlbmd0aCA9IHJlbWFpbmluZ1xuXG4gIGlmICgoc3RyaW5nLmxlbmd0aCA+IDAgJiYgKGxlbmd0aCA8IDAgfHwgb2Zmc2V0IDwgMCkpIHx8IG9mZnNldCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gd3JpdGUgb3V0c2lkZSBidWZmZXIgYm91bmRzJylcbiAgfVxuXG4gIGlmICghZW5jb2RpbmcpIGVuY29kaW5nID0gJ3V0ZjgnXG5cbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcbiAgZm9yICg7Oykge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBoZXhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICAgIHJldHVybiBhc2NpaVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2xhdGluMSc6XG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gbGF0aW4xV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgLy8gV2FybmluZzogbWF4TGVuZ3RoIG5vdCB0YWtlbiBpbnRvIGFjY291bnQgaW4gYmFzZTY0V3JpdGVcbiAgICAgICAgcmV0dXJuIGJhc2U2NFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1Y3MyV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OICgpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnQnVmZmVyJyxcbiAgICBkYXRhOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLl9hcnIgfHwgdGhpcywgMClcbiAgfVxufVxuXG5mdW5jdGlvbiBiYXNlNjRTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGlmIChzdGFydCA9PT0gMCAmJiBlbmQgPT09IGJ1Zi5sZW5ndGgpIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYuc2xpY2Uoc3RhcnQsIGVuZCkpXG4gIH1cbn1cblxuZnVuY3Rpb24gdXRmOFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuICB2YXIgcmVzID0gW11cblxuICB2YXIgaSA9IHN0YXJ0XG4gIHdoaWxlIChpIDwgZW5kKSB7XG4gICAgdmFyIGZpcnN0Qnl0ZSA9IGJ1ZltpXVxuICAgIHZhciBjb2RlUG9pbnQgPSBudWxsXG4gICAgdmFyIGJ5dGVzUGVyU2VxdWVuY2UgPSAoZmlyc3RCeXRlID4gMHhFRikgPyA0XG4gICAgICA6IChmaXJzdEJ5dGUgPiAweERGKSA/IDNcbiAgICAgICAgOiAoZmlyc3RCeXRlID4gMHhCRikgPyAyXG4gICAgICAgICAgOiAxXG5cbiAgICBpZiAoaSArIGJ5dGVzUGVyU2VxdWVuY2UgPD0gZW5kKSB7XG4gICAgICB2YXIgc2Vjb25kQnl0ZSwgdGhpcmRCeXRlLCBmb3VydGhCeXRlLCB0ZW1wQ29kZVBvaW50XG5cbiAgICAgIHN3aXRjaCAoYnl0ZXNQZXJTZXF1ZW5jZSkge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgaWYgKGZpcnN0Qnl0ZSA8IDB4ODApIHtcbiAgICAgICAgICAgIGNvZGVQb2ludCA9IGZpcnN0Qnl0ZVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweDFGKSA8PCAweDYgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0YpIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICB0aGlyZEJ5dGUgPSBidWZbaSArIDJdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4RikgPDwgMHhDIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweDYgfCAodGhpcmRCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHg3RkYgJiYgKHRlbXBDb2RlUG9pbnQgPCAweEQ4MDAgfHwgdGVtcENvZGVQb2ludCA+IDB4REZGRikpIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICB0aGlyZEJ5dGUgPSBidWZbaSArIDJdXG4gICAgICAgICAgZm91cnRoQnl0ZSA9IGJ1ZltpICsgM11cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAodGhpcmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKGZvdXJ0aEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4MTIgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpIDw8IDB4QyB8ICh0aGlyZEJ5dGUgJiAweDNGKSA8PCAweDYgfCAoZm91cnRoQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4RkZGRiAmJiB0ZW1wQ29kZVBvaW50IDwgMHgxMTAwMDApIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY29kZVBvaW50ID09PSBudWxsKSB7XG4gICAgICAvLyB3ZSBkaWQgbm90IGdlbmVyYXRlIGEgdmFsaWQgY29kZVBvaW50IHNvIGluc2VydCBhXG4gICAgICAvLyByZXBsYWNlbWVudCBjaGFyIChVK0ZGRkQpIGFuZCBhZHZhbmNlIG9ubHkgMSBieXRlXG4gICAgICBjb2RlUG9pbnQgPSAweEZGRkRcbiAgICAgIGJ5dGVzUGVyU2VxdWVuY2UgPSAxXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPiAweEZGRkYpIHtcbiAgICAgIC8vIGVuY29kZSB0byB1dGYxNiAoc3Vycm9nYXRlIHBhaXIgZGFuY2UpXG4gICAgICBjb2RlUG9pbnQgLT0gMHgxMDAwMFxuICAgICAgcmVzLnB1c2goY29kZVBvaW50ID4+PiAxMCAmIDB4M0ZGIHwgMHhEODAwKVxuICAgICAgY29kZVBvaW50ID0gMHhEQzAwIHwgY29kZVBvaW50ICYgMHgzRkZcbiAgICB9XG5cbiAgICByZXMucHVzaChjb2RlUG9pbnQpXG4gICAgaSArPSBieXRlc1BlclNlcXVlbmNlXG4gIH1cblxuICByZXR1cm4gZGVjb2RlQ29kZVBvaW50c0FycmF5KHJlcylcbn1cblxuLy8gQmFzZWQgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMjI3NDcyNzIvNjgwNzQyLCB0aGUgYnJvd3NlciB3aXRoXG4vLyB0aGUgbG93ZXN0IGxpbWl0IGlzIENocm9tZSwgd2l0aCAweDEwMDAwIGFyZ3MuXG4vLyBXZSBnbyAxIG1hZ25pdHVkZSBsZXNzLCBmb3Igc2FmZXR5XG52YXIgTUFYX0FSR1VNRU5UU19MRU5HVEggPSAweDEwMDBcblxuZnVuY3Rpb24gZGVjb2RlQ29kZVBvaW50c0FycmF5IChjb2RlUG9pbnRzKSB7XG4gIHZhciBsZW4gPSBjb2RlUG9pbnRzLmxlbmd0aFxuICBpZiAobGVuIDw9IE1BWF9BUkdVTUVOVFNfTEVOR1RIKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjb2RlUG9pbnRzKSAvLyBhdm9pZCBleHRyYSBzbGljZSgpXG4gIH1cblxuICAvLyBEZWNvZGUgaW4gY2h1bmtzIHRvIGF2b2lkIFwiY2FsbCBzdGFjayBzaXplIGV4Y2VlZGVkXCIuXG4gIHZhciByZXMgPSAnJ1xuICB2YXIgaSA9IDBcbiAgd2hpbGUgKGkgPCBsZW4pIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShcbiAgICAgIFN0cmluZyxcbiAgICAgIGNvZGVQb2ludHMuc2xpY2UoaSwgaSArPSBNQVhfQVJHVU1FTlRTX0xFTkdUSClcbiAgICApXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSAmIDB4N0YpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBsYXRpbjFTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBoZXhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG5cbiAgaWYgKCFzdGFydCB8fCBzdGFydCA8IDApIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCB8fCBlbmQgPCAwIHx8IGVuZCA+IGxlbikgZW5kID0gbGVuXG5cbiAgdmFyIG91dCA9ICcnXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgKytpKSB7XG4gICAgb3V0ICs9IHRvSGV4KGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBieXRlcyA9IGJ1Zi5zbGljZShzdGFydCwgZW5kKVxuICB2YXIgcmVzID0gJydcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkgKz0gMikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldICsgKGJ5dGVzW2kgKyAxXSAqIDI1NikpXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24gc2xpY2UgKHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIHN0YXJ0ID0gfn5zdGFydFxuICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCA/IGxlbiA6IH5+ZW5kXG5cbiAgaWYgKHN0YXJ0IDwgMCkge1xuICAgIHN0YXJ0ICs9IGxlblxuICAgIGlmIChzdGFydCA8IDApIHN0YXJ0ID0gMFxuICB9IGVsc2UgaWYgKHN0YXJ0ID4gbGVuKSB7XG4gICAgc3RhcnQgPSBsZW5cbiAgfVxuXG4gIGlmIChlbmQgPCAwKSB7XG4gICAgZW5kICs9IGxlblxuICAgIGlmIChlbmQgPCAwKSBlbmQgPSAwXG4gIH0gZWxzZSBpZiAoZW5kID4gbGVuKSB7XG4gICAgZW5kID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgc3RhcnQpIGVuZCA9IHN0YXJ0XG5cbiAgdmFyIG5ld0J1ZiA9IHRoaXMuc3ViYXJyYXkoc3RhcnQsIGVuZClcbiAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2VcbiAgbmV3QnVmLl9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgcmV0dXJuIG5ld0J1ZlxufVxuXG4vKlxuICogTmVlZCB0byBtYWtlIHN1cmUgdGhhdCBidWZmZXIgaXNuJ3QgdHJ5aW5nIHRvIHdyaXRlIG91dCBvZiBib3VuZHMuXG4gKi9cbmZ1bmN0aW9uIGNoZWNrT2Zmc2V0IChvZmZzZXQsIGV4dCwgbGVuZ3RoKSB7XG4gIGlmICgob2Zmc2V0ICUgMSkgIT09IDAgfHwgb2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ29mZnNldCBpcyBub3QgdWludCcpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBsZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdUcnlpbmcgdG8gYWNjZXNzIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludExFID0gZnVuY3Rpb24gcmVhZFVJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIGldICogbXVsXG4gIH1cblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRCRSA9IGZ1bmN0aW9uIHJlYWRVSW50QkUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuICB9XG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXVxuICB2YXIgbXVsID0gMVxuICB3aGlsZSAoYnl0ZUxlbmd0aCA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdICogbXVsXG4gIH1cblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQ4ID0gZnVuY3Rpb24gcmVhZFVJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gdGhpc1tvZmZzZXRdXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkxFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2QkUgPSBmdW5jdGlvbiByZWFkVUludDE2QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiAodGhpc1tvZmZzZXRdIDw8IDgpIHwgdGhpc1tvZmZzZXQgKyAxXVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJMRSA9IGZ1bmN0aW9uIHJlYWRVSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKCh0aGlzW29mZnNldF0pIHxcbiAgICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSkgK1xuICAgICAgKHRoaXNbb2Zmc2V0ICsgM10gKiAweDEwMDAwMDApXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkJFID0gZnVuY3Rpb24gcmVhZFVJbnQzMkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdICogMHgxMDAwMDAwKSArXG4gICAgKCh0aGlzW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgOCkgfFxuICAgIHRoaXNbb2Zmc2V0ICsgM10pXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludExFID0gZnVuY3Rpb24gcmVhZEludExFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF1cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRCRSA9IGZ1bmN0aW9uIHJlYWRJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgaSA9IGJ5dGVMZW5ndGhcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1pXVxuICB3aGlsZSAoaSA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uIHJlYWRJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICBpZiAoISh0aGlzW29mZnNldF0gJiAweDgwKSkgcmV0dXJuICh0aGlzW29mZnNldF0pXG4gIHJldHVybiAoKDB4ZmYgLSB0aGlzW29mZnNldF0gKyAxKSAqIC0xKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkxFID0gZnVuY3Rpb24gcmVhZEludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2QkUgPSBmdW5jdGlvbiByZWFkSW50MTZCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgMV0gfCAodGhpc1tvZmZzZXRdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJMRSA9IGZ1bmN0aW9uIHJlYWRJbnQzMkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdKSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgM10gPDwgMjQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyQkUgPSBmdW5jdGlvbiByZWFkSW50MzJCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCAyNCkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgOCkgfFxuICAgICh0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdExFID0gZnVuY3Rpb24gcmVhZEZsb2F0TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRCRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdEJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVMRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDUyLCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVCRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCA1MiwgOClcbn1cblxuZnVuY3Rpb24gY2hlY2tJbnQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihidWYpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImJ1ZmZlclwiIGFyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXIgaW5zdGFuY2UnKVxuICBpZiAodmFsdWUgPiBtYXggfHwgdmFsdWUgPCBtaW4pIHRocm93IG5ldyBSYW5nZUVycm9yKCdcInZhbHVlXCIgYXJndW1lbnQgaXMgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnRMRSA9IGZ1bmN0aW9uIHdyaXRlVUludExFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIHZhciBtYXhCeXRlcyA9IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSAtIDFcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBtYXhCeXRlcywgMClcbiAgfVxuXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbWF4Qnl0ZXMgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCkgLSAxXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbWF4Qnl0ZXMsIDApXG4gIH1cblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDggPSBmdW5jdGlvbiB3cml0ZVVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHhmZiwgMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MTZMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFID0gZnVuY3Rpb24gd3JpdGVVSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkJFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDE2KVxuICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludExFID0gZnVuY3Rpb24gd3JpdGVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbGltaXQgPSBNYXRoLnBvdygyLCAoOCAqIGJ5dGVMZW5ndGgpIC0gMSlcblxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIGxpbWl0IC0gMSwgLWxpbWl0KVxuICB9XG5cbiAgdmFyIGkgPSAwXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSAwXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIGlmICh2YWx1ZSA8IDAgJiYgc3ViID09PSAwICYmIHRoaXNbb2Zmc2V0ICsgaSAtIDFdICE9PSAwKSB7XG4gICAgICBzdWIgPSAxXG4gICAgfVxuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRCRSA9IGZ1bmN0aW9uIHdyaXRlSW50QkUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIGxpbWl0ID0gTWF0aC5wb3coMiwgKDggKiBieXRlTGVuZ3RoKSAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHN1YiA9IDBcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICBpZiAodmFsdWUgPCAwICYmIHN1YiA9PT0gMCAmJiB0aGlzW29mZnNldCArIGkgKyAxXSAhPT0gMCkge1xuICAgICAgc3ViID0gMVxuICAgIH1cbiAgICB0aGlzW29mZnNldCArIGldID0gKCh2YWx1ZSAvIG11bCkgPj4gMCkgLSBzdWIgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50OCA9IGZ1bmN0aW9uIHdyaXRlSW50OCAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4N2YsIC0weDgwKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmYgKyB2YWx1ZSArIDFcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2TEUgPSBmdW5jdGlvbiB3cml0ZUludDE2TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweDdmZmYsIC0weDgwMDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkJFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJMRSA9IGZ1bmN0aW9uIHdyaXRlSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkJFID0gZnVuY3Rpb24gd3JpdGVJbnQzMkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZmZmZmZmZiArIHZhbHVlICsgMVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbmZ1bmN0aW9uIGNoZWNrSUVFRTc1NCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbiAgaWYgKG9mZnNldCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxufVxuXG5mdW5jdGlvbiB3cml0ZUZsb2F0IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0lFRUU3NTQoYnVmLCB2YWx1ZSwgb2Zmc2V0LCA0LCAzLjQwMjgyMzQ2NjM4NTI4ODZlKzM4LCAtMy40MDI4MjM0NjYzODUyODg2ZSszOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCAyMywgNClcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0TEUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRCRSA9IGZ1bmN0aW9uIHdyaXRlRmxvYXRCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiB3cml0ZURvdWJsZSAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgOCwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCA1MiwgOClcbiAgcmV0dXJuIG9mZnNldCArIDhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5ICh0YXJnZXQsIHRhcmdldFN0YXJ0LCBzdGFydCwgZW5kKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKHRhcmdldCkpIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FyZ3VtZW50IHNob3VsZCBiZSBhIEJ1ZmZlcicpXG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCAmJiBlbmQgIT09IDApIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXRTdGFydCA+PSB0YXJnZXQubGVuZ3RoKSB0YXJnZXRTdGFydCA9IHRhcmdldC5sZW5ndGhcbiAgaWYgKCF0YXJnZXRTdGFydCkgdGFyZ2V0U3RhcnQgPSAwXG4gIGlmIChlbmQgPiAwICYmIGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIC8vIENvcHkgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuIDBcbiAgaWYgKHRhcmdldC5sZW5ndGggPT09IDAgfHwgdGhpcy5sZW5ndGggPT09IDApIHJldHVybiAwXG5cbiAgLy8gRmF0YWwgZXJyb3IgY29uZGl0aW9uc1xuICBpZiAodGFyZ2V0U3RhcnQgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3RhcmdldFN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICB9XG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxuICBpZiAoZW5kIDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3NvdXJjZUVuZCBvdXQgb2YgYm91bmRzJylcblxuICAvLyBBcmUgd2Ugb29iP1xuICBpZiAoZW5kID4gdGhpcy5sZW5ndGgpIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgPCBlbmQgLSBzdGFydCkge1xuICAgIGVuZCA9IHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCArIHN0YXJ0XG4gIH1cblxuICB2YXIgbGVuID0gZW5kIC0gc3RhcnRcblxuICBpZiAodGhpcyA9PT0gdGFyZ2V0ICYmIHR5cGVvZiBVaW50OEFycmF5LnByb3RvdHlwZS5jb3B5V2l0aGluID09PSAnZnVuY3Rpb24nKSB7XG4gICAgLy8gVXNlIGJ1aWx0LWluIHdoZW4gYXZhaWxhYmxlLCBtaXNzaW5nIGZyb20gSUUxMVxuICAgIHRoaXMuY29weVdpdGhpbih0YXJnZXRTdGFydCwgc3RhcnQsIGVuZClcbiAgfSBlbHNlIGlmICh0aGlzID09PSB0YXJnZXQgJiYgc3RhcnQgPCB0YXJnZXRTdGFydCAmJiB0YXJnZXRTdGFydCA8IGVuZCkge1xuICAgIC8vIGRlc2NlbmRpbmcgY29weSBmcm9tIGVuZFxuICAgIGZvciAodmFyIGkgPSBsZW4gLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRTdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgVWludDhBcnJheS5wcm90b3R5cGUuc2V0LmNhbGwoXG4gICAgICB0YXJnZXQsXG4gICAgICB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpLFxuICAgICAgdGFyZ2V0U3RhcnRcbiAgICApXG4gIH1cblxuICByZXR1cm4gbGVuXG59XG5cbi8vIFVzYWdlOlxuLy8gICAgYnVmZmVyLmZpbGwobnVtYmVyWywgb2Zmc2V0WywgZW5kXV0pXG4vLyAgICBidWZmZXIuZmlsbChidWZmZXJbLCBvZmZzZXRbLCBlbmRdXSlcbi8vICAgIGJ1ZmZlci5maWxsKHN0cmluZ1ssIG9mZnNldFssIGVuZF1dWywgZW5jb2RpbmddKVxuQnVmZmVyLnByb3RvdHlwZS5maWxsID0gZnVuY3Rpb24gZmlsbCAodmFsLCBzdGFydCwgZW5kLCBlbmNvZGluZykge1xuICAvLyBIYW5kbGUgc3RyaW5nIGNhc2VzOlxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICBpZiAodHlwZW9mIHN0YXJ0ID09PSAnc3RyaW5nJykge1xuICAgICAgZW5jb2RpbmcgPSBzdGFydFxuICAgICAgc3RhcnQgPSAwXG4gICAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGVuZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVuY29kaW5nID0gZW5kXG4gICAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICAgIH1cbiAgICBpZiAoZW5jb2RpbmcgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgZW5jb2RpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmNvZGluZyBtdXN0IGJlIGEgc3RyaW5nJylcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBlbmNvZGluZyA9PT0gJ3N0cmluZycgJiYgIUJ1ZmZlci5pc0VuY29kaW5nKGVuY29kaW5nKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgIH1cbiAgICBpZiAodmFsLmxlbmd0aCA9PT0gMSkge1xuICAgICAgdmFyIGNvZGUgPSB2YWwuY2hhckNvZGVBdCgwKVxuICAgICAgaWYgKChlbmNvZGluZyA9PT0gJ3V0ZjgnICYmIGNvZGUgPCAxMjgpIHx8XG4gICAgICAgICAgZW5jb2RpbmcgPT09ICdsYXRpbjEnKSB7XG4gICAgICAgIC8vIEZhc3QgcGF0aDogSWYgYHZhbGAgZml0cyBpbnRvIGEgc2luZ2xlIGJ5dGUsIHVzZSB0aGF0IG51bWVyaWMgdmFsdWUuXG4gICAgICAgIHZhbCA9IGNvZGVcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICB2YWwgPSB2YWwgJiAyNTVcbiAgfVxuXG4gIC8vIEludmFsaWQgcmFuZ2VzIGFyZSBub3Qgc2V0IHRvIGEgZGVmYXVsdCwgc28gY2FuIHJhbmdlIGNoZWNrIGVhcmx5LlxuICBpZiAoc3RhcnQgPCAwIHx8IHRoaXMubGVuZ3RoIDwgc3RhcnQgfHwgdGhpcy5sZW5ndGggPCBlbmQpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignT3V0IG9mIHJhbmdlIGluZGV4JylcbiAgfVxuXG4gIGlmIChlbmQgPD0gc3RhcnQpIHtcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgc3RhcnQgPSBzdGFydCA+Pj4gMFxuICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCA/IHRoaXMubGVuZ3RoIDogZW5kID4+PiAwXG5cbiAgaWYgKCF2YWwpIHZhbCA9IDBcblxuICB2YXIgaVxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgKytpKSB7XG4gICAgICB0aGlzW2ldID0gdmFsXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBieXRlcyA9IEJ1ZmZlci5pc0J1ZmZlcih2YWwpXG4gICAgICA/IHZhbFxuICAgICAgOiBCdWZmZXIuZnJvbSh2YWwsIGVuY29kaW5nKVxuICAgIHZhciBsZW4gPSBieXRlcy5sZW5ndGhcbiAgICBpZiAobGVuID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgdmFsdWUgXCInICsgdmFsICtcbiAgICAgICAgJ1wiIGlzIGludmFsaWQgZm9yIGFyZ3VtZW50IFwidmFsdWVcIicpXG4gICAgfVxuICAgIGZvciAoaSA9IDA7IGkgPCBlbmQgLSBzdGFydDsgKytpKSB7XG4gICAgICB0aGlzW2kgKyBzdGFydF0gPSBieXRlc1tpICUgbGVuXVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzXG59XG5cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT1cblxudmFyIElOVkFMSURfQkFTRTY0X1JFID0gL1teKy8wLTlBLVphLXotX10vZ1xuXG5mdW5jdGlvbiBiYXNlNjRjbGVhbiAoc3RyKSB7XG4gIC8vIE5vZGUgdGFrZXMgZXF1YWwgc2lnbnMgYXMgZW5kIG9mIHRoZSBCYXNlNjQgZW5jb2RpbmdcbiAgc3RyID0gc3RyLnNwbGl0KCc9JylbMF1cbiAgLy8gTm9kZSBzdHJpcHMgb3V0IGludmFsaWQgY2hhcmFjdGVycyBsaWtlIFxcbiBhbmQgXFx0IGZyb20gdGhlIHN0cmluZywgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHN0ciA9IHN0ci50cmltKCkucmVwbGFjZShJTlZBTElEX0JBU0U2NF9SRSwgJycpXG4gIC8vIE5vZGUgY29udmVydHMgc3RyaW5ncyB3aXRoIGxlbmd0aCA8IDIgdG8gJydcbiAgaWYgKHN0ci5sZW5ndGggPCAyKSByZXR1cm4gJydcbiAgLy8gTm9kZSBhbGxvd3MgZm9yIG5vbi1wYWRkZWQgYmFzZTY0IHN0cmluZ3MgKG1pc3NpbmcgdHJhaWxpbmcgPT09KSwgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHdoaWxlIChzdHIubGVuZ3RoICUgNCAhPT0gMCkge1xuICAgIHN0ciA9IHN0ciArICc9J1xuICB9XG4gIHJldHVybiBzdHJcbn1cblxuZnVuY3Rpb24gdG9IZXggKG4pIHtcbiAgaWYgKG4gPCAxNikgcmV0dXJuICcwJyArIG4udG9TdHJpbmcoMTYpXG4gIHJldHVybiBuLnRvU3RyaW5nKDE2KVxufVxuXG5mdW5jdGlvbiB1dGY4VG9CeXRlcyAoc3RyaW5nLCB1bml0cykge1xuICB1bml0cyA9IHVuaXRzIHx8IEluZmluaXR5XG4gIHZhciBjb2RlUG9pbnRcbiAgdmFyIGxlbmd0aCA9IHN0cmluZy5sZW5ndGhcbiAgdmFyIGxlYWRTdXJyb2dhdGUgPSBudWxsXG4gIHZhciBieXRlcyA9IFtdXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGNvZGVQb2ludCA9IHN0cmluZy5jaGFyQ29kZUF0KGkpXG5cbiAgICAvLyBpcyBzdXJyb2dhdGUgY29tcG9uZW50XG4gICAgaWYgKGNvZGVQb2ludCA+IDB4RDdGRiAmJiBjb2RlUG9pbnQgPCAweEUwMDApIHtcbiAgICAgIC8vIGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoIWxlYWRTdXJyb2dhdGUpIHtcbiAgICAgICAgLy8gbm8gbGVhZCB5ZXRcbiAgICAgICAgaWYgKGNvZGVQb2ludCA+IDB4REJGRikge1xuICAgICAgICAgIC8vIHVuZXhwZWN0ZWQgdHJhaWxcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9IGVsc2UgaWYgKGkgKyAxID09PSBsZW5ndGgpIHtcbiAgICAgICAgICAvLyB1bnBhaXJlZCBsZWFkXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHZhbGlkIGxlYWRcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIDIgbGVhZHMgaW4gYSByb3dcbiAgICAgIGlmIChjb2RlUG9pbnQgPCAweERDMDApIHtcbiAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gdmFsaWQgc3Vycm9nYXRlIHBhaXJcbiAgICAgIGNvZGVQb2ludCA9IChsZWFkU3Vycm9nYXRlIC0gMHhEODAwIDw8IDEwIHwgY29kZVBvaW50IC0gMHhEQzAwKSArIDB4MTAwMDBcbiAgICB9IGVsc2UgaWYgKGxlYWRTdXJyb2dhdGUpIHtcbiAgICAgIC8vIHZhbGlkIGJtcCBjaGFyLCBidXQgbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgIH1cblxuICAgIGxlYWRTdXJyb2dhdGUgPSBudWxsXG5cbiAgICAvLyBlbmNvZGUgdXRmOFxuICAgIGlmIChjb2RlUG9pbnQgPCAweDgwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDEpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goY29kZVBvaW50KVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHg4MDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiB8IDB4QzAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDMpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgfCAweEUwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSA0KSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHgxMiB8IDB4RjAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29kZSBwb2ludCcpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpVG9CeXRlcyAoc3RyKSB7XG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkge1xuICAgIC8vIE5vZGUncyBjb2RlIHNlZW1zIHRvIGJlIGRvaW5nIHRoaXMgYW5kIG5vdCAmIDB4N0YuLlxuICAgIGJ5dGVBcnJheS5wdXNoKHN0ci5jaGFyQ29kZUF0KGkpICYgMHhGRilcbiAgfVxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVUb0J5dGVzIChzdHIsIHVuaXRzKSB7XG4gIHZhciBjLCBoaSwgbG9cbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKCh1bml0cyAtPSAyKSA8IDApIGJyZWFrXG5cbiAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSlcbiAgICBoaSA9IGMgPj4gOFxuICAgIGxvID0gYyAlIDI1NlxuICAgIGJ5dGVBcnJheS5wdXNoKGxvKVxuICAgIGJ5dGVBcnJheS5wdXNoKGhpKVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiBiYXNlNjRUb0J5dGVzIChzdHIpIHtcbiAgcmV0dXJuIGJhc2U2NC50b0J5dGVBcnJheShiYXNlNjRjbGVhbihzdHIpKVxufVxuXG5mdW5jdGlvbiBibGl0QnVmZmVyIChzcmMsIGRzdCwgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGlmICgoaSArIG9mZnNldCA+PSBkc3QubGVuZ3RoKSB8fCAoaSA+PSBzcmMubGVuZ3RoKSkgYnJlYWtcbiAgICBkc3RbaSArIG9mZnNldF0gPSBzcmNbaV1cbiAgfVxuICByZXR1cm4gaVxufVxuXG4vLyBBcnJheUJ1ZmZlciBvciBVaW50OEFycmF5IG9iamVjdHMgZnJvbSBvdGhlciBjb250ZXh0cyAoaS5lLiBpZnJhbWVzKSBkbyBub3QgcGFzc1xuLy8gdGhlIGBpbnN0YW5jZW9mYCBjaGVjayBidXQgdGhleSBzaG91bGQgYmUgdHJlYXRlZCBhcyBvZiB0aGF0IHR5cGUuXG4vLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL2lzc3Vlcy8xNjZcbmZ1bmN0aW9uIGlzSW5zdGFuY2UgKG9iaiwgdHlwZSkge1xuICByZXR1cm4gb2JqIGluc3RhbmNlb2YgdHlwZSB8fFxuICAgIChvYmogIT0gbnVsbCAmJiBvYmouY29uc3RydWN0b3IgIT0gbnVsbCAmJiBvYmouY29uc3RydWN0b3IubmFtZSAhPSBudWxsICYmXG4gICAgICBvYmouY29uc3RydWN0b3IubmFtZSA9PT0gdHlwZS5uYW1lKVxufVxuZnVuY3Rpb24gbnVtYmVySXNOYU4gKG9iaikge1xuICAvLyBGb3IgSUUxMSBzdXBwb3J0XG4gIHJldHVybiBvYmogIT09IG9iaiAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXNlbGYtY29tcGFyZVxufVxuXG59KS5jYWxsKHRoaXMsX2RlcmVxXyhcImJ1ZmZlclwiKS5CdWZmZXIpXG59LHtcImJhc2U2NC1qc1wiOjc0LFwiYnVmZmVyXCI6MTA1LFwiaWVlZTc1NFwiOjQxMn1dLDEwNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIG1vbm90b25lVHJpYW5ndWxhdGUgPSBfZGVyZXFfKCcuL2xpYi9tb25vdG9uZScpXG52YXIgbWFrZUluZGV4ID0gX2RlcmVxXygnLi9saWIvdHJpYW5ndWxhdGlvbicpXG52YXIgZGVsYXVuYXlGbGlwID0gX2RlcmVxXygnLi9saWIvZGVsYXVuYXknKVxudmFyIGZpbHRlclRyaWFuZ3VsYXRpb24gPSBfZGVyZXFfKCcuL2xpYi9maWx0ZXInKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNkdDJkXG5cbmZ1bmN0aW9uIGNhbm9uaWNhbGl6ZUVkZ2UoZSkge1xuICByZXR1cm4gW01hdGgubWluKGVbMF0sIGVbMV0pLCBNYXRoLm1heChlWzBdLCBlWzFdKV1cbn1cblxuZnVuY3Rpb24gY29tcGFyZUVkZ2UoYSwgYikge1xuICByZXR1cm4gYVswXS1iWzBdIHx8IGFbMV0tYlsxXVxufVxuXG5mdW5jdGlvbiBjYW5vbmljYWxpemVFZGdlcyhlZGdlcykge1xuICByZXR1cm4gZWRnZXMubWFwKGNhbm9uaWNhbGl6ZUVkZ2UpLnNvcnQoY29tcGFyZUVkZ2UpXG59XG5cbmZ1bmN0aW9uIGdldERlZmF1bHQob3B0aW9ucywgcHJvcGVydHksIGRmbHQpIHtcbiAgaWYocHJvcGVydHkgaW4gb3B0aW9ucykge1xuICAgIHJldHVybiBvcHRpb25zW3Byb3BlcnR5XVxuICB9XG4gIHJldHVybiBkZmx0XG59XG5cbmZ1bmN0aW9uIGNkdDJkKHBvaW50cywgZWRnZXMsIG9wdGlvbnMpIHtcblxuICBpZighQXJyYXkuaXNBcnJheShlZGdlcykpIHtcbiAgICBvcHRpb25zID0gZWRnZXMgfHwge31cbiAgICBlZGdlcyA9IFtdXG4gIH0gZWxzZSB7XG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgICBlZGdlcyA9IGVkZ2VzIHx8IFtdXG4gIH1cblxuICAvL1BhcnNlIG91dCBvcHRpb25zXG4gIHZhciBkZWxhdW5heSA9ICEhZ2V0RGVmYXVsdChvcHRpb25zLCAnZGVsYXVuYXknLCB0cnVlKVxuICB2YXIgaW50ZXJpb3IgPSAhIWdldERlZmF1bHQob3B0aW9ucywgJ2ludGVyaW9yJywgdHJ1ZSlcbiAgdmFyIGV4dGVyaW9yID0gISFnZXREZWZhdWx0KG9wdGlvbnMsICdleHRlcmlvcicsIHRydWUpXG4gIHZhciBpbmZpbml0eSA9ICEhZ2V0RGVmYXVsdChvcHRpb25zLCAnaW5maW5pdHknLCBmYWxzZSlcblxuICAvL0hhbmRsZSB0cml2aWFsIGNhc2VcbiAgaWYoKCFpbnRlcmlvciAmJiAhZXh0ZXJpb3IpIHx8IHBvaW50cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW11cbiAgfVxuXG4gIC8vQ29uc3RydWN0IGluaXRpYWwgdHJpYW5ndWxhdGlvblxuICB2YXIgY2VsbHMgPSBtb25vdG9uZVRyaWFuZ3VsYXRlKHBvaW50cywgZWRnZXMpXG5cbiAgLy9JZiBkZWxhdW5heSByZWZpbmVtZW50IG5lZWRlZCwgdGhlbiBpbXByb3ZlIHF1YWxpdHkgYnkgZWRnZSBmbGlwcGluZ1xuICBpZihkZWxhdW5heSB8fCBpbnRlcmlvciAhPT0gZXh0ZXJpb3IgfHwgaW5maW5pdHkpIHtcblxuICAgIC8vSW5kZXggYWxsIG9mIHRoZSBjZWxscyB0byBzdXBwb3J0IGZhc3QgbmVpZ2hib3Job29kIHF1ZXJpZXNcbiAgICB2YXIgdHJpYW5ndWxhdGlvbiA9IG1ha2VJbmRleChwb2ludHMubGVuZ3RoLCBjYW5vbmljYWxpemVFZGdlcyhlZGdlcykpXG4gICAgZm9yKHZhciBpPTA7IGk8Y2VsbHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBmID0gY2VsbHNbaV1cbiAgICAgIHRyaWFuZ3VsYXRpb24uYWRkVHJpYW5nbGUoZlswXSwgZlsxXSwgZlsyXSlcbiAgICB9XG5cbiAgICAvL1J1biBlZGdlIGZsaXBwaW5nXG4gICAgaWYoZGVsYXVuYXkpIHtcbiAgICAgIGRlbGF1bmF5RmxpcChwb2ludHMsIHRyaWFuZ3VsYXRpb24pXG4gICAgfVxuXG4gICAgLy9GaWx0ZXIgcG9pbnRzXG4gICAgaWYoIWV4dGVyaW9yKSB7XG4gICAgICByZXR1cm4gZmlsdGVyVHJpYW5ndWxhdGlvbih0cmlhbmd1bGF0aW9uLCAtMSlcbiAgICB9IGVsc2UgaWYoIWludGVyaW9yKSB7XG4gICAgICByZXR1cm4gZmlsdGVyVHJpYW5ndWxhdGlvbih0cmlhbmd1bGF0aW9uLCAgMSwgaW5maW5pdHkpXG4gICAgfSBlbHNlIGlmKGluZmluaXR5KSB7XG4gICAgICByZXR1cm4gZmlsdGVyVHJpYW5ndWxhdGlvbih0cmlhbmd1bGF0aW9uLCAwLCBpbmZpbml0eSlcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRyaWFuZ3VsYXRpb24uY2VsbHMoKVxuICAgIH1cbiAgICBcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY2VsbHNcbiAgfVxufVxuXG59LHtcIi4vbGliL2RlbGF1bmF5XCI6MTA3LFwiLi9saWIvZmlsdGVyXCI6MTA4LFwiLi9saWIvbW9ub3RvbmVcIjoxMDksXCIuL2xpYi90cmlhbmd1bGF0aW9uXCI6MTEwfV0sMTA3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgaW5DaXJjbGUgPSBfZGVyZXFfKCdyb2J1c3QtaW4tc3BoZXJlJylbNF1cbnZhciBic2VhcmNoID0gX2RlcmVxXygnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGRlbGF1bmF5UmVmaW5lXG5cbmZ1bmN0aW9uIHRlc3RGbGlwKHBvaW50cywgdHJpYW5ndWxhdGlvbiwgc3RhY2ssIGEsIGIsIHgpIHtcbiAgdmFyIHkgPSB0cmlhbmd1bGF0aW9uLm9wcG9zaXRlKGEsIGIpXG5cbiAgLy9UZXN0IGJvdW5kYXJ5IGVkZ2VcbiAgaWYoeSA8IDApIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vU3dhcCBlZGdlIGlmIG9yZGVyIGZsaXBwZWRcbiAgaWYoYiA8IGEpIHtcbiAgICB2YXIgdG1wID0gYVxuICAgIGEgPSBiXG4gICAgYiA9IHRtcFxuICAgIHRtcCA9IHhcbiAgICB4ID0geVxuICAgIHkgPSB0bXBcbiAgfVxuXG4gIC8vVGVzdCBpZiBlZGdlIGlzIGNvbnN0cmFpbmVkXG4gIGlmKHRyaWFuZ3VsYXRpb24uaXNDb25zdHJhaW50KGEsIGIpKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICAvL1Rlc3QgaWYgZWRnZSBpcyBkZWxhdW5heVxuICBpZihpbkNpcmNsZShwb2ludHNbYV0sIHBvaW50c1tiXSwgcG9pbnRzW3hdLCBwb2ludHNbeV0pIDwgMCkge1xuICAgIHN0YWNrLnB1c2goYSwgYilcbiAgfVxufVxuXG4vL0Fzc3VtZSBlZGdlcyBhcmUgc29ydGVkIGxleGljb2dyYXBoaWNhbGx5XG5mdW5jdGlvbiBkZWxhdW5heVJlZmluZShwb2ludHMsIHRyaWFuZ3VsYXRpb24pIHtcbiAgdmFyIHN0YWNrID0gW11cblxuICB2YXIgbnVtUG9pbnRzID0gcG9pbnRzLmxlbmd0aFxuICB2YXIgc3RhcnMgPSB0cmlhbmd1bGF0aW9uLnN0YXJzXG4gIGZvcih2YXIgYT0wOyBhPG51bVBvaW50czsgKythKSB7XG4gICAgdmFyIHN0YXIgPSBzdGFyc1thXVxuICAgIGZvcih2YXIgaj0xOyBqPHN0YXIubGVuZ3RoOyBqKz0yKSB7XG4gICAgICB2YXIgYiA9IHN0YXJbal1cblxuICAgICAgLy9JZiBvcmRlciBpcyBub3QgY29uc2lzdGVudCwgdGhlbiBza2lwIGVkZ2VcbiAgICAgIGlmKGIgPCBhKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vQ2hlY2sgaWYgZWRnZSBpcyBjb25zdHJhaW5lZFxuICAgICAgaWYodHJpYW5ndWxhdGlvbi5pc0NvbnN0cmFpbnQoYSwgYikpIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy9GaW5kIG9wcG9zaXRlIGVkZ2VcbiAgICAgIHZhciB4ID0gc3RhcltqLTFdLCB5ID0gLTFcbiAgICAgIGZvcih2YXIgaz0xOyBrPHN0YXIubGVuZ3RoOyBrKz0yKSB7XG4gICAgICAgIGlmKHN0YXJbay0xXSA9PT0gYikge1xuICAgICAgICAgIHkgPSBzdGFyW2tdXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvL0lmIHRoaXMgaXMgYSBib3VuZGFyeSBlZGdlLCBkb24ndCBmbGlwIGl0XG4gICAgICBpZih5IDwgMCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvL0lmIGVkZ2UgaXMgaW4gY2lyY2xlLCBmbGlwIGl0XG4gICAgICBpZihpbkNpcmNsZShwb2ludHNbYV0sIHBvaW50c1tiXSwgcG9pbnRzW3hdLCBwb2ludHNbeV0pIDwgMCkge1xuICAgICAgICBzdGFjay5wdXNoKGEsIGIpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgd2hpbGUoc3RhY2subGVuZ3RoID4gMCkge1xuICAgIHZhciBiID0gc3RhY2sucG9wKClcbiAgICB2YXIgYSA9IHN0YWNrLnBvcCgpXG5cbiAgICAvL0ZpbmQgb3Bwb3NpdGUgcGFpcnNcbiAgICB2YXIgeCA9IC0xLCB5ID0gLTFcbiAgICB2YXIgc3RhciA9IHN0YXJzW2FdXG4gICAgZm9yKHZhciBpPTE7IGk8c3Rhci5sZW5ndGg7IGkrPTIpIHtcbiAgICAgIHZhciBzID0gc3RhcltpLTFdXG4gICAgICB2YXIgdCA9IHN0YXJbaV1cbiAgICAgIGlmKHMgPT09IGIpIHtcbiAgICAgICAgeSA9IHRcbiAgICAgIH0gZWxzZSBpZih0ID09PSBiKSB7XG4gICAgICAgIHggPSBzXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy9JZiB4L3kgYXJlIGJvdGggdmFsaWQgdGhlbiBza2lwIGVkZ2VcbiAgICBpZih4IDwgMCB8fCB5IDwgMCkge1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICAvL0lmIGVkZ2UgaXMgbm93IGRlbGF1bmF5LCB0aGVuIGRvbid0IGZsaXAgaXRcbiAgICBpZihpbkNpcmNsZShwb2ludHNbYV0sIHBvaW50c1tiXSwgcG9pbnRzW3hdLCBwb2ludHNbeV0pID49IDApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgLy9GbGlwIHRoZSBlZGdlXG4gICAgdHJpYW5ndWxhdGlvbi5mbGlwKGEsIGIpXG5cbiAgICAvL1Rlc3QgZmxpcHBpbmcgbmVpZ2hib3JpbmcgZWRnZXNcbiAgICB0ZXN0RmxpcChwb2ludHMsIHRyaWFuZ3VsYXRpb24sIHN0YWNrLCB4LCBhLCB5KVxuICAgIHRlc3RGbGlwKHBvaW50cywgdHJpYW5ndWxhdGlvbiwgc3RhY2ssIGEsIHksIHgpXG4gICAgdGVzdEZsaXAocG9pbnRzLCB0cmlhbmd1bGF0aW9uLCBzdGFjaywgeSwgYiwgeClcbiAgICB0ZXN0RmxpcChwb2ludHMsIHRyaWFuZ3VsYXRpb24sIHN0YWNrLCBiLCB4LCB5KVxuICB9XG59XG5cbn0se1wiYmluYXJ5LXNlYXJjaC1ib3VuZHNcIjoxMTEsXCJyb2J1c3QtaW4tc3BoZXJlXCI6NTA4fV0sMTA4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgYnNlYXJjaCA9IF9kZXJlcV8oJ2JpbmFyeS1zZWFyY2gtYm91bmRzJylcblxubW9kdWxlLmV4cG9ydHMgPSBjbGFzc2lmeUZhY2VzXG5cbmZ1bmN0aW9uIEZhY2VJbmRleChjZWxscywgbmVpZ2hib3IsIGNvbnN0cmFpbnQsIGZsYWdzLCBhY3RpdmUsIG5leHQsIGJvdW5kYXJ5KSB7XG4gIHRoaXMuY2VsbHMgICAgICAgPSBjZWxsc1xuICB0aGlzLm5laWdoYm9yICAgID0gbmVpZ2hib3JcbiAgdGhpcy5mbGFncyAgICAgICA9IGZsYWdzXG4gIHRoaXMuY29uc3RyYWludCAgPSBjb25zdHJhaW50XG4gIHRoaXMuYWN0aXZlICAgICAgPSBhY3RpdmVcbiAgdGhpcy5uZXh0ICAgICAgICA9IG5leHRcbiAgdGhpcy5ib3VuZGFyeSAgICA9IGJvdW5kYXJ5XG59XG5cbnZhciBwcm90byA9IEZhY2VJbmRleC5wcm90b3R5cGVcblxuZnVuY3Rpb24gY29tcGFyZUNlbGwoYSwgYikge1xuICByZXR1cm4gYVswXSAtIGJbMF0gfHxcbiAgICAgICAgIGFbMV0gLSBiWzFdIHx8XG4gICAgICAgICBhWzJdIC0gYlsyXVxufVxuXG5wcm90by5sb2NhdGUgPSAoZnVuY3Rpb24oKSB7XG4gIHZhciBrZXkgPSBbMCwwLDBdXG4gIHJldHVybiBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgdmFyIHggPSBhLCB5ID0gYiwgeiA9IGNcbiAgICBpZihiIDwgYykge1xuICAgICAgaWYoYiA8IGEpIHtcbiAgICAgICAgeCA9IGJcbiAgICAgICAgeSA9IGNcbiAgICAgICAgeiA9IGFcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYoYyA8IGEpIHtcbiAgICAgIHggPSBjXG4gICAgICB5ID0gYVxuICAgICAgeiA9IGJcbiAgICB9XG4gICAgaWYoeCA8IDApIHtcbiAgICAgIHJldHVybiAtMVxuICAgIH1cbiAgICBrZXlbMF0gPSB4XG4gICAga2V5WzFdID0geVxuICAgIGtleVsyXSA9IHpcbiAgICByZXR1cm4gYnNlYXJjaC5lcSh0aGlzLmNlbGxzLCBrZXksIGNvbXBhcmVDZWxsKVxuICB9XG59KSgpXG5cbmZ1bmN0aW9uIGluZGV4Q2VsbHModHJpYW5ndWxhdGlvbiwgaW5maW5pdHkpIHtcbiAgLy9GaXJzdCBnZXQgY2VsbHMgYW5kIGNhbm9uaWNhbGl6ZVxuICB2YXIgY2VsbHMgPSB0cmlhbmd1bGF0aW9uLmNlbGxzKClcbiAgdmFyIG5jID0gY2VsbHMubGVuZ3RoXG4gIGZvcih2YXIgaT0wOyBpPG5jOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgdmFyIHggPSBjWzBdLCB5ID0gY1sxXSwgeiA9IGNbMl1cbiAgICBpZih5IDwgeikge1xuICAgICAgaWYoeSA8IHgpIHtcbiAgICAgICAgY1swXSA9IHlcbiAgICAgICAgY1sxXSA9IHpcbiAgICAgICAgY1syXSA9IHhcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYoeiA8IHgpIHtcbiAgICAgIGNbMF0gPSB6XG4gICAgICBjWzFdID0geFxuICAgICAgY1syXSA9IHlcbiAgICB9XG4gIH1cbiAgY2VsbHMuc29ydChjb21wYXJlQ2VsbClcblxuICAvL0luaXRpYWxpemUgZmxhZyBhcnJheVxuICB2YXIgZmxhZ3MgPSBuZXcgQXJyYXkobmMpXG4gIGZvcih2YXIgaT0wOyBpPGZsYWdzLmxlbmd0aDsgKytpKSB7XG4gICAgZmxhZ3NbaV0gPSAwXG4gIH1cblxuICAvL0J1aWxkIG5laWdoYm9yIGluZGV4LCBpbml0aWFsaXplIHF1ZXVlc1xuICB2YXIgYWN0aXZlID0gW11cbiAgdmFyIG5leHQgICA9IFtdXG4gIHZhciBuZWlnaGJvciA9IG5ldyBBcnJheSgzKm5jKVxuICB2YXIgY29uc3RyYWludCA9IG5ldyBBcnJheSgzKm5jKVxuICB2YXIgYm91bmRhcnkgPSBudWxsXG4gIGlmKGluZmluaXR5KSB7XG4gICAgYm91bmRhcnkgPSBbXVxuICB9XG4gIHZhciBpbmRleCA9IG5ldyBGYWNlSW5kZXgoXG4gICAgY2VsbHMsXG4gICAgbmVpZ2hib3IsXG4gICAgY29uc3RyYWludCxcbiAgICBmbGFncyxcbiAgICBhY3RpdmUsXG4gICAgbmV4dCxcbiAgICBib3VuZGFyeSlcbiAgZm9yKHZhciBpPTA7IGk8bmM7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIHZhciB4ID0gY1tqXSwgeSA9IGNbKGorMSklM11cbiAgICAgIHZhciBhID0gbmVpZ2hib3JbMyppK2pdID0gaW5kZXgubG9jYXRlKHksIHgsIHRyaWFuZ3VsYXRpb24ub3Bwb3NpdGUoeSwgeCkpXG4gICAgICB2YXIgYiA9IGNvbnN0cmFpbnRbMyppK2pdID0gdHJpYW5ndWxhdGlvbi5pc0NvbnN0cmFpbnQoeCwgeSlcbiAgICAgIGlmKGEgPCAwKSB7XG4gICAgICAgIGlmKGIpIHtcbiAgICAgICAgICBuZXh0LnB1c2goaSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhY3RpdmUucHVzaChpKVxuICAgICAgICAgIGZsYWdzW2ldID0gMVxuICAgICAgICB9XG4gICAgICAgIGlmKGluZmluaXR5KSB7XG4gICAgICAgICAgYm91bmRhcnkucHVzaChbeSwgeCwgLTFdKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBpbmRleFxufVxuXG5mdW5jdGlvbiBmaWx0ZXJDZWxscyhjZWxscywgZmxhZ3MsIHRhcmdldCkge1xuICB2YXIgcHRyID0gMFxuICBmb3IodmFyIGk9MDsgaTxjZWxscy5sZW5ndGg7ICsraSkge1xuICAgIGlmKGZsYWdzW2ldID09PSB0YXJnZXQpIHtcbiAgICAgIGNlbGxzW3B0cisrXSA9IGNlbGxzW2ldXG4gICAgfVxuICB9XG4gIGNlbGxzLmxlbmd0aCA9IHB0clxuICByZXR1cm4gY2VsbHNcbn1cblxuZnVuY3Rpb24gY2xhc3NpZnlGYWNlcyh0cmlhbmd1bGF0aW9uLCB0YXJnZXQsIGluZmluaXR5KSB7XG4gIHZhciBpbmRleCA9IGluZGV4Q2VsbHModHJpYW5ndWxhdGlvbiwgaW5maW5pdHkpXG5cbiAgaWYodGFyZ2V0ID09PSAwKSB7XG4gICAgaWYoaW5maW5pdHkpIHtcbiAgICAgIHJldHVybiBpbmRleC5jZWxscy5jb25jYXQoaW5kZXguYm91bmRhcnkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpbmRleC5jZWxsc1xuICAgIH1cbiAgfVxuXG4gIHZhciBzaWRlID0gMVxuICB2YXIgYWN0aXZlID0gaW5kZXguYWN0aXZlXG4gIHZhciBuZXh0ID0gaW5kZXgubmV4dFxuICB2YXIgZmxhZ3MgPSBpbmRleC5mbGFnc1xuICB2YXIgY2VsbHMgPSBpbmRleC5jZWxsc1xuICB2YXIgY29uc3RyYWludCA9IGluZGV4LmNvbnN0cmFpbnRcbiAgdmFyIG5laWdoYm9yID0gaW5kZXgubmVpZ2hib3JcblxuICB3aGlsZShhY3RpdmUubGVuZ3RoID4gMCB8fCBuZXh0Lmxlbmd0aCA+IDApIHtcbiAgICB3aGlsZShhY3RpdmUubGVuZ3RoID4gMCkge1xuICAgICAgdmFyIHQgPSBhY3RpdmUucG9wKClcbiAgICAgIGlmKGZsYWdzW3RdID09PSAtc2lkZSkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgZmxhZ3NbdF0gPSBzaWRlXG4gICAgICB2YXIgYyA9IGNlbGxzW3RdXG4gICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgdmFyIGYgPSBuZWlnaGJvclszKnQral1cbiAgICAgICAgaWYoZiA+PSAwICYmIGZsYWdzW2ZdID09PSAwKSB7XG4gICAgICAgICAgaWYoY29uc3RyYWludFszKnQral0pIHtcbiAgICAgICAgICAgIG5leHQucHVzaChmKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhY3RpdmUucHVzaChmKVxuICAgICAgICAgICAgZmxhZ3NbZl0gPSBzaWRlXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy9Td2FwIGFycmF5cyBhbmQgbG9vcFxuICAgIHZhciB0bXAgPSBuZXh0XG4gICAgbmV4dCA9IGFjdGl2ZVxuICAgIGFjdGl2ZSA9IHRtcFxuICAgIG5leHQubGVuZ3RoID0gMFxuICAgIHNpZGUgPSAtc2lkZVxuICB9XG5cbiAgdmFyIHJlc3VsdCA9IGZpbHRlckNlbGxzKGNlbGxzLCBmbGFncywgdGFyZ2V0KVxuICBpZihpbmZpbml0eSkge1xuICAgIHJldHVybiByZXN1bHQuY29uY2F0KGluZGV4LmJvdW5kYXJ5KVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxufSx7XCJiaW5hcnktc2VhcmNoLWJvdW5kc1wiOjExMX1dLDEwOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGJzZWFyY2ggPSBfZGVyZXFfKCdiaW5hcnktc2VhcmNoLWJvdW5kcycpXG52YXIgb3JpZW50ID0gX2RlcmVxXygncm9idXN0LW9yaWVudGF0aW9uJylbM11cblxudmFyIEVWRU5UX1BPSU5UID0gMFxudmFyIEVWRU5UX0VORCAgID0gMVxudmFyIEVWRU5UX1NUQVJUID0gMlxuXG5tb2R1bGUuZXhwb3J0cyA9IG1vbm90b25lVHJpYW5ndWxhdGVcblxuLy9BIHBhcnRpYWwgY29udmV4IGh1bGwgZnJhZ21lbnQsIG1hZGUgb2YgdHdvIHVuaW1vbm90b25lIHBvbHlnb25zXG5mdW5jdGlvbiBQYXJ0aWFsSHVsbChhLCBiLCBpZHgsIGxvd2VySWRzLCB1cHBlcklkcykge1xuICB0aGlzLmEgPSBhXG4gIHRoaXMuYiA9IGJcbiAgdGhpcy5pZHggPSBpZHhcbiAgdGhpcy5sb3dlcklkcyA9IGxvd2VySWRzXG4gIHRoaXMudXBwZXJJZHMgPSB1cHBlcklkc1xufVxuXG4vL0FuIGV2ZW50IGluIHRoZSBzd2VlcCBsaW5lIHByb2NlZHVyZVxuZnVuY3Rpb24gRXZlbnQoYSwgYiwgdHlwZSwgaWR4KSB7XG4gIHRoaXMuYSAgICA9IGFcbiAgdGhpcy5iICAgID0gYlxuICB0aGlzLnR5cGUgPSB0eXBlXG4gIHRoaXMuaWR4ICA9IGlkeFxufVxuXG4vL1RoaXMgaXMgdXNlZCB0byBjb21wYXJlIGV2ZW50cyBmb3IgdGhlIHN3ZWVwIGxpbmUgcHJvY2VkdXJlXG4vLyBQb2ludHMgYXJlOlxuLy8gIDEuIHNvcnRlZCBsZXhpY29ncmFwaGljYWxseVxuLy8gIDIuIHNvcnRlZCBieSB0eXBlICAocG9pbnQgPCBlbmQgPCBzdGFydClcbi8vICAzLiBzZWdtZW50cyBzb3J0ZWQgYnkgd2luZGluZyBvcmRlclxuLy8gIDQuIHNvcnRlZCBieSBpbmRleFxuZnVuY3Rpb24gY29tcGFyZUV2ZW50KGEsIGIpIHtcbiAgdmFyIGQgPVxuICAgIChhLmFbMF0gLSBiLmFbMF0pIHx8XG4gICAgKGEuYVsxXSAtIGIuYVsxXSkgfHxcbiAgICAoYS50eXBlIC0gYi50eXBlKVxuICBpZihkKSB7IHJldHVybiBkIH1cbiAgaWYoYS50eXBlICE9PSBFVkVOVF9QT0lOVCkge1xuICAgIGQgPSBvcmllbnQoYS5hLCBhLmIsIGIuYilcbiAgICBpZihkKSB7IHJldHVybiBkIH1cbiAgfVxuICByZXR1cm4gYS5pZHggLSBiLmlkeFxufVxuXG5mdW5jdGlvbiB0ZXN0UG9pbnQoaHVsbCwgcCkge1xuICByZXR1cm4gb3JpZW50KGh1bGwuYSwgaHVsbC5iLCBwKVxufVxuXG5mdW5jdGlvbiBhZGRQb2ludChjZWxscywgaHVsbHMsIHBvaW50cywgcCwgaWR4KSB7XG4gIHZhciBsbyA9IGJzZWFyY2gubHQoaHVsbHMsIHAsIHRlc3RQb2ludClcbiAgdmFyIGhpID0gYnNlYXJjaC5ndChodWxscywgcCwgdGVzdFBvaW50KVxuICBmb3IodmFyIGk9bG87IGk8aGk7ICsraSkge1xuICAgIHZhciBodWxsID0gaHVsbHNbaV1cblxuICAgIC8vSW5zZXJ0IHAgaW50byBsb3dlciBodWxsXG4gICAgdmFyIGxvd2VySWRzID0gaHVsbC5sb3dlcklkc1xuICAgIHZhciBtID0gbG93ZXJJZHMubGVuZ3RoXG4gICAgd2hpbGUobSA+IDEgJiYgb3JpZW50KFxuICAgICAgICBwb2ludHNbbG93ZXJJZHNbbS0yXV0sXG4gICAgICAgIHBvaW50c1tsb3dlcklkc1ttLTFdXSxcbiAgICAgICAgcCkgPiAwKSB7XG4gICAgICBjZWxscy5wdXNoKFxuICAgICAgICBbbG93ZXJJZHNbbS0xXSxcbiAgICAgICAgIGxvd2VySWRzW20tMl0sXG4gICAgICAgICBpZHhdKVxuICAgICAgbSAtPSAxXG4gICAgfVxuICAgIGxvd2VySWRzLmxlbmd0aCA9IG1cbiAgICBsb3dlcklkcy5wdXNoKGlkeClcblxuICAgIC8vSW5zZXJ0IHAgaW50byB1cHBlciBodWxsXG4gICAgdmFyIHVwcGVySWRzID0gaHVsbC51cHBlcklkc1xuICAgIHZhciBtID0gdXBwZXJJZHMubGVuZ3RoXG4gICAgd2hpbGUobSA+IDEgJiYgb3JpZW50KFxuICAgICAgICBwb2ludHNbdXBwZXJJZHNbbS0yXV0sXG4gICAgICAgIHBvaW50c1t1cHBlcklkc1ttLTFdXSxcbiAgICAgICAgcCkgPCAwKSB7XG4gICAgICBjZWxscy5wdXNoKFxuICAgICAgICBbdXBwZXJJZHNbbS0yXSxcbiAgICAgICAgIHVwcGVySWRzW20tMV0sXG4gICAgICAgICBpZHhdKVxuICAgICAgbSAtPSAxXG4gICAgfVxuICAgIHVwcGVySWRzLmxlbmd0aCA9IG1cbiAgICB1cHBlcklkcy5wdXNoKGlkeClcbiAgfVxufVxuXG5mdW5jdGlvbiBmaW5kU3BsaXQoaHVsbCwgZWRnZSkge1xuICB2YXIgZFxuICBpZihodWxsLmFbMF0gPCBlZGdlLmFbMF0pIHtcbiAgICBkID0gb3JpZW50KGh1bGwuYSwgaHVsbC5iLCBlZGdlLmEpXG4gIH0gZWxzZSB7XG4gICAgZCA9IG9yaWVudChlZGdlLmIsIGVkZ2UuYSwgaHVsbC5hKVxuICB9XG4gIGlmKGQpIHsgcmV0dXJuIGQgfVxuICBpZihlZGdlLmJbMF0gPCBodWxsLmJbMF0pIHtcbiAgICBkID0gb3JpZW50KGh1bGwuYSwgaHVsbC5iLCBlZGdlLmIpXG4gIH0gZWxzZSB7XG4gICAgZCA9IG9yaWVudChlZGdlLmIsIGVkZ2UuYSwgaHVsbC5iKVxuICB9XG4gIHJldHVybiBkIHx8IGh1bGwuaWR4IC0gZWRnZS5pZHhcbn1cblxuZnVuY3Rpb24gc3BsaXRIdWxscyhodWxscywgcG9pbnRzLCBldmVudCkge1xuICB2YXIgc3BsaXRJZHggPSBic2VhcmNoLmxlKGh1bGxzLCBldmVudCwgZmluZFNwbGl0KVxuICB2YXIgaHVsbCA9IGh1bGxzW3NwbGl0SWR4XVxuICB2YXIgdXBwZXJJZHMgPSBodWxsLnVwcGVySWRzXG4gIHZhciB4ID0gdXBwZXJJZHNbdXBwZXJJZHMubGVuZ3RoLTFdXG4gIGh1bGwudXBwZXJJZHMgPSBbeF1cbiAgaHVsbHMuc3BsaWNlKHNwbGl0SWR4KzEsIDAsXG4gICAgbmV3IFBhcnRpYWxIdWxsKGV2ZW50LmEsIGV2ZW50LmIsIGV2ZW50LmlkeCwgW3hdLCB1cHBlcklkcykpXG59XG5cblxuZnVuY3Rpb24gbWVyZ2VIdWxscyhodWxscywgcG9pbnRzLCBldmVudCkge1xuICAvL1N3YXAgcG9pbnRlcnMgZm9yIG1lcmdlIHNlYXJjaFxuICB2YXIgdG1wID0gZXZlbnQuYVxuICBldmVudC5hID0gZXZlbnQuYlxuICBldmVudC5iID0gdG1wXG4gIHZhciBtZXJnZUlkeCA9IGJzZWFyY2guZXEoaHVsbHMsIGV2ZW50LCBmaW5kU3BsaXQpXG4gIHZhciB1cHBlciA9IGh1bGxzW21lcmdlSWR4XVxuICB2YXIgbG93ZXIgPSBodWxsc1ttZXJnZUlkeC0xXVxuICBsb3dlci51cHBlcklkcyA9IHVwcGVyLnVwcGVySWRzXG4gIGh1bGxzLnNwbGljZShtZXJnZUlkeCwgMSlcbn1cblxuXG5mdW5jdGlvbiBtb25vdG9uZVRyaWFuZ3VsYXRlKHBvaW50cywgZWRnZXMpIHtcblxuICB2YXIgbnVtUG9pbnRzID0gcG9pbnRzLmxlbmd0aFxuICB2YXIgbnVtRWRnZXMgPSBlZGdlcy5sZW5ndGhcblxuICB2YXIgZXZlbnRzID0gW11cblxuICAvL0NyZWF0ZSBwb2ludCBldmVudHNcbiAgZm9yKHZhciBpPTA7IGk8bnVtUG9pbnRzOyArK2kpIHtcbiAgICBldmVudHMucHVzaChuZXcgRXZlbnQoXG4gICAgICBwb2ludHNbaV0sXG4gICAgICBudWxsLFxuICAgICAgRVZFTlRfUE9JTlQsXG4gICAgICBpKSlcbiAgfVxuXG4gIC8vQ3JlYXRlIGVkZ2UgZXZlbnRzXG4gIGZvcih2YXIgaT0wOyBpPG51bUVkZ2VzOyArK2kpIHtcbiAgICB2YXIgZSA9IGVkZ2VzW2ldXG4gICAgdmFyIGEgPSBwb2ludHNbZVswXV1cbiAgICB2YXIgYiA9IHBvaW50c1tlWzFdXVxuICAgIGlmKGFbMF0gPCBiWzBdKSB7XG4gICAgICBldmVudHMucHVzaChcbiAgICAgICAgbmV3IEV2ZW50KGEsIGIsIEVWRU5UX1NUQVJULCBpKSxcbiAgICAgICAgbmV3IEV2ZW50KGIsIGEsIEVWRU5UX0VORCwgaSkpXG4gICAgfSBlbHNlIGlmKGFbMF0gPiBiWzBdKSB7XG4gICAgICBldmVudHMucHVzaChcbiAgICAgICAgbmV3IEV2ZW50KGIsIGEsIEVWRU5UX1NUQVJULCBpKSxcbiAgICAgICAgbmV3IEV2ZW50KGEsIGIsIEVWRU5UX0VORCwgaSkpXG4gICAgfVxuICB9XG5cbiAgLy9Tb3J0IGV2ZW50c1xuICBldmVudHMuc29ydChjb21wYXJlRXZlbnQpXG5cbiAgLy9Jbml0aWFsaXplIGh1bGxcbiAgdmFyIG1pblggPSBldmVudHNbMF0uYVswXSAtICgxICsgTWF0aC5hYnMoZXZlbnRzWzBdLmFbMF0pKSAqIE1hdGgucG93KDIsIC01MilcbiAgdmFyIGh1bGwgPSBbIG5ldyBQYXJ0aWFsSHVsbChbbWluWCwgMV0sIFttaW5YLCAwXSwgLTEsIFtdLCBbXSwgW10sIFtdKSBdXG5cbiAgLy9Qcm9jZXNzIGV2ZW50cyBpbiBvcmRlclxuICB2YXIgY2VsbHMgPSBbXVxuICBmb3IodmFyIGk9MCwgbnVtRXZlbnRzPWV2ZW50cy5sZW5ndGg7IGk8bnVtRXZlbnRzOyArK2kpIHtcbiAgICB2YXIgZXZlbnQgPSBldmVudHNbaV1cbiAgICB2YXIgdHlwZSA9IGV2ZW50LnR5cGVcbiAgICBpZih0eXBlID09PSBFVkVOVF9QT0lOVCkge1xuICAgICAgYWRkUG9pbnQoY2VsbHMsIGh1bGwsIHBvaW50cywgZXZlbnQuYSwgZXZlbnQuaWR4KVxuICAgIH0gZWxzZSBpZih0eXBlID09PSBFVkVOVF9TVEFSVCkge1xuICAgICAgc3BsaXRIdWxscyhodWxsLCBwb2ludHMsIGV2ZW50KVxuICAgIH0gZWxzZSB7XG4gICAgICBtZXJnZUh1bGxzKGh1bGwsIHBvaW50cywgZXZlbnQpXG4gICAgfVxuICB9XG5cbiAgLy9SZXR1cm4gdHJpYW5ndWxhdGlvblxuICByZXR1cm4gY2VsbHNcbn1cblxufSx7XCJiaW5hcnktc2VhcmNoLWJvdW5kc1wiOjExMSxcInJvYnVzdC1vcmllbnRhdGlvblwiOjUxMH1dLDExMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGJzZWFyY2ggPSBfZGVyZXFfKCdiaW5hcnktc2VhcmNoLWJvdW5kcycpXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVHJpYW5ndWxhdGlvblxuXG5mdW5jdGlvbiBUcmlhbmd1bGF0aW9uKHN0YXJzLCBlZGdlcykge1xuICB0aGlzLnN0YXJzID0gc3RhcnNcbiAgdGhpcy5lZGdlcyA9IGVkZ2VzXG59XG5cbnZhciBwcm90byA9IFRyaWFuZ3VsYXRpb24ucHJvdG90eXBlXG5cbmZ1bmN0aW9uIHJlbW92ZVBhaXIobGlzdCwgaiwgaykge1xuICBmb3IodmFyIGk9MSwgbj1saXN0Lmxlbmd0aDsgaTxuOyBpKz0yKSB7XG4gICAgaWYobGlzdFtpLTFdID09PSBqICYmIGxpc3RbaV0gPT09IGspIHtcbiAgICAgIGxpc3RbaS0xXSA9IGxpc3Rbbi0yXVxuICAgICAgbGlzdFtpXSA9IGxpc3Rbbi0xXVxuICAgICAgbGlzdC5sZW5ndGggPSBuIC0gMlxuICAgICAgcmV0dXJuXG4gICAgfVxuICB9XG59XG5cbnByb3RvLmlzQ29uc3RyYWludCA9IChmdW5jdGlvbigpIHtcbiAgdmFyIGUgPSBbMCwwXVxuICBmdW5jdGlvbiBjb21wYXJlTGV4KGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAtIGJbMF0gfHwgYVsxXSAtIGJbMV1cbiAgfVxuICByZXR1cm4gZnVuY3Rpb24oaSwgaikge1xuICAgIGVbMF0gPSBNYXRoLm1pbihpLGopXG4gICAgZVsxXSA9IE1hdGgubWF4KGksailcbiAgICByZXR1cm4gYnNlYXJjaC5lcSh0aGlzLmVkZ2VzLCBlLCBjb21wYXJlTGV4KSA+PSAwXG4gIH1cbn0pKClcblxucHJvdG8ucmVtb3ZlVHJpYW5nbGUgPSBmdW5jdGlvbihpLCBqLCBrKSB7XG4gIHZhciBzdGFycyA9IHRoaXMuc3RhcnNcbiAgcmVtb3ZlUGFpcihzdGFyc1tpXSwgaiwgaylcbiAgcmVtb3ZlUGFpcihzdGFyc1tqXSwgaywgaSlcbiAgcmVtb3ZlUGFpcihzdGFyc1trXSwgaSwgailcbn1cblxucHJvdG8uYWRkVHJpYW5nbGUgPSBmdW5jdGlvbihpLCBqLCBrKSB7XG4gIHZhciBzdGFycyA9IHRoaXMuc3RhcnNcbiAgc3RhcnNbaV0ucHVzaChqLCBrKVxuICBzdGFyc1tqXS5wdXNoKGssIGkpXG4gIHN0YXJzW2tdLnB1c2goaSwgailcbn1cblxucHJvdG8ub3Bwb3NpdGUgPSBmdW5jdGlvbihqLCBpKSB7XG4gIHZhciBsaXN0ID0gdGhpcy5zdGFyc1tpXVxuICBmb3IodmFyIGs9MSwgbj1saXN0Lmxlbmd0aDsgazxuOyBrKz0yKSB7XG4gICAgaWYobGlzdFtrXSA9PT0gaikge1xuICAgICAgcmV0dXJuIGxpc3Rbay0xXVxuICAgIH1cbiAgfVxuICByZXR1cm4gLTFcbn1cblxucHJvdG8uZmxpcCA9IGZ1bmN0aW9uKGksIGopIHtcbiAgdmFyIGEgPSB0aGlzLm9wcG9zaXRlKGksIGopXG4gIHZhciBiID0gdGhpcy5vcHBvc2l0ZShqLCBpKVxuICB0aGlzLnJlbW92ZVRyaWFuZ2xlKGksIGosIGEpXG4gIHRoaXMucmVtb3ZlVHJpYW5nbGUoaiwgaSwgYilcbiAgdGhpcy5hZGRUcmlhbmdsZShpLCBiLCBhKVxuICB0aGlzLmFkZFRyaWFuZ2xlKGosIGEsIGIpXG59XG5cbnByb3RvLmVkZ2VzID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzdGFycyA9IHRoaXMuc3RhcnNcbiAgdmFyIHJlc3VsdCA9IFtdXG4gIGZvcih2YXIgaT0wLCBuPXN0YXJzLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICB2YXIgbGlzdCA9IHN0YXJzW2ldXG4gICAgZm9yKHZhciBqPTAsIG09bGlzdC5sZW5ndGg7IGo8bTsgais9Mikge1xuICAgICAgcmVzdWx0LnB1c2goW2xpc3Rbal0sIGxpc3RbaisxXV0pXG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxucHJvdG8uY2VsbHMgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHN0YXJzID0gdGhpcy5zdGFyc1xuICB2YXIgcmVzdWx0ID0gW11cbiAgZm9yKHZhciBpPTAsIG49c3RhcnMubGVuZ3RoOyBpPG47ICsraSkge1xuICAgIHZhciBsaXN0ID0gc3RhcnNbaV1cbiAgICBmb3IodmFyIGo9MCwgbT1saXN0Lmxlbmd0aDsgajxtOyBqKz0yKSB7XG4gICAgICB2YXIgcyA9IGxpc3Rbal1cbiAgICAgIHZhciB0ID0gbGlzdFtqKzFdXG4gICAgICBpZihpIDwgTWF0aC5taW4ocywgdCkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goW2ksIHMsIHRdKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVRyaWFuZ3VsYXRpb24obnVtVmVydHMsIGVkZ2VzKSB7XG4gIHZhciBzdGFycyA9IG5ldyBBcnJheShudW1WZXJ0cylcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydHM7ICsraSkge1xuICAgIHN0YXJzW2ldID0gW11cbiAgfVxuICByZXR1cm4gbmV3IFRyaWFuZ3VsYXRpb24oc3RhcnMsIGVkZ2VzKVxufVxuXG59LHtcImJpbmFyeS1zZWFyY2gtYm91bmRzXCI6MTExfV0sMTExOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbmZ1bmN0aW9uIGNvbXBpbGVTZWFyY2goZnVuY05hbWUsIHByZWRpY2F0ZSwgcmV2ZXJzZWQsIGV4dHJhQXJncywgZWFybHlPdXQpIHtcbiAgdmFyIGNvZGUgPSBbXG4gICAgXCJmdW5jdGlvbiBcIiwgZnVuY05hbWUsIFwiKGEsbCxoLFwiLCBleHRyYUFyZ3Muam9pbihcIixcIiksICBcIil7XCIsXG4gICAgZWFybHlPdXQgPyBcIlwiIDogXCJ2YXIgaT1cIiwgKHJldmVyc2VkID8gXCJsLTFcIiA6IFwiaCsxXCIpLFxuICAgIFwiO3doaWxlKGw8PWgpe3ZhciBtPShsK2gpPj4+MSx4PWFbbV1cIl1cbiAgaWYoZWFybHlPdXQpIHtcbiAgICBpZihwcmVkaWNhdGUuaW5kZXhPZihcImNcIikgPCAwKSB7XG4gICAgICBjb2RlLnB1c2goXCI7aWYoeD09PXkpe3JldHVybiBtfWVsc2UgaWYoeDw9eSl7XCIpXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGUucHVzaChcIjt2YXIgcD1jKHgseSk7aWYocD09PTApe3JldHVybiBtfWVsc2UgaWYocDw9MCl7XCIpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcIjtpZihcIiwgcHJlZGljYXRlLCBcIil7aT1tO1wiKVxuICB9XG4gIGlmKHJldmVyc2VkKSB7XG4gICAgY29kZS5wdXNoKFwibD1tKzF9ZWxzZXtoPW0tMX1cIilcbiAgfSBlbHNlIHtcbiAgICBjb2RlLnB1c2goXCJoPW0tMX1lbHNle2w9bSsxfVwiKVxuICB9XG4gIGNvZGUucHVzaChcIn1cIilcbiAgaWYoZWFybHlPdXQpIHtcbiAgICBjb2RlLnB1c2goXCJyZXR1cm4gLTF9O1wiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcInJldHVybiBpfTtcIilcbiAgfVxuICByZXR1cm4gY29kZS5qb2luKFwiXCIpXG59XG5cbmZ1bmN0aW9uIGNvbXBpbGVCb3VuZHNTZWFyY2gocHJlZGljYXRlLCByZXZlcnNlZCwgc3VmZml4LCBlYXJseU91dCkge1xuICB2YXIgcmVzdWx0ID0gbmV3IEZ1bmN0aW9uKFtcbiAgY29tcGlsZVNlYXJjaChcIkFcIiwgXCJ4XCIgKyBwcmVkaWNhdGUgKyBcInlcIiwgcmV2ZXJzZWQsIFtcInlcIl0sIGVhcmx5T3V0KSxcbiAgY29tcGlsZVNlYXJjaChcIlBcIiwgXCJjKHgseSlcIiArIHByZWRpY2F0ZSArIFwiMFwiLCByZXZlcnNlZCwgW1wieVwiLCBcImNcIl0sIGVhcmx5T3V0KSxcblwiZnVuY3Rpb24gZGlzcGF0Y2hCc2VhcmNoXCIsIHN1ZmZpeCwgXCIoYSx5LGMsbCxoKXtcXFxuaWYodHlwZW9mKGMpPT09J2Z1bmN0aW9uJyl7XFxcbnJldHVybiBQKGEsKGw9PT12b2lkIDApPzA6bHwwLChoPT09dm9pZCAwKT9hLmxlbmd0aC0xOmh8MCx5LGMpXFxcbn1lbHNle1xcXG5yZXR1cm4gQShhLChjPT09dm9pZCAwKT8wOmN8MCwobD09PXZvaWQgMCk/YS5sZW5ndGgtMTpsfDAseSlcXFxufX1cXFxucmV0dXJuIGRpc3BhdGNoQnNlYXJjaFwiLCBzdWZmaXhdLmpvaW4oXCJcIikpXG4gIHJldHVybiByZXN1bHQoKVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZ2U6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCI+PVwiLCBmYWxzZSwgIFwiR0VcIiksXG4gIGd0OiBjb21waWxlQm91bmRzU2VhcmNoKFwiPlwiLCAgZmFsc2UsICBcIkdUXCIpLFxuICBsdDogY29tcGlsZUJvdW5kc1NlYXJjaChcIjxcIiwgIHRydWUsICAgXCJMVFwiKSxcbiAgbGU6IGNvbXBpbGVCb3VuZHNTZWFyY2goXCI8PVwiLCB0cnVlLCAgIFwiTEVcIiksXG4gIGVxOiBjb21waWxlQm91bmRzU2VhcmNoKFwiLVwiLCAgdHJ1ZSwgICBcIkVRXCIsIHRydWUpXG59XG5cbn0se31dLDExMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBvcmllbnRhdGlvblxuXG5mdW5jdGlvbiBvcmllbnRhdGlvbihzKSB7XG4gIHZhciBwID0gMVxuICBmb3IodmFyIGk9MTsgaTxzLmxlbmd0aDsgKytpKSB7XG4gICAgZm9yKHZhciBqPTA7IGo8aTsgKytqKSB7XG4gICAgICBpZihzW2ldIDwgc1tqXSkge1xuICAgICAgICBwID0gLXBcbiAgICAgIH0gZWxzZSBpZihzW2pdID09PSBzW2ldKSB7XG4gICAgICAgIHJldHVybiAwXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBwXG59XG5cbn0se31dLDExMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG52YXIgZHVwID0gX2RlcmVxXyhcImR1cFwiKVxudmFyIHNvbHZlID0gX2RlcmVxXyhcInJvYnVzdC1saW5lYXItc29sdmVcIilcblxuZnVuY3Rpb24gZG90KGEsIGIpIHtcbiAgdmFyIHMgPSAwLjBcbiAgdmFyIGQgPSBhLmxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICBzICs9IGFbaV0gKiBiW2ldXG4gIH1cbiAgcmV0dXJuIHNcbn1cblxuZnVuY3Rpb24gYmFyeWNlbnRyaWNDaXJjdW1jZW50ZXIocG9pbnRzKSB7XG4gIHZhciBOID0gcG9pbnRzLmxlbmd0aFxuICBpZihOID09PSAwKSB7XG4gICAgcmV0dXJuIFtdXG4gIH1cbiAgXG4gIHZhciBEID0gcG9pbnRzWzBdLmxlbmd0aFxuICB2YXIgQSA9IGR1cChbcG9pbnRzLmxlbmd0aCsxLCBwb2ludHMubGVuZ3RoKzFdLCAxLjApXG4gIHZhciBiID0gZHVwKFtwb2ludHMubGVuZ3RoKzFdLCAxLjApXG4gIEFbTl1bTl0gPSAwLjBcbiAgZm9yKHZhciBpPTA7IGk8TjsgKytpKSB7XG4gICAgZm9yKHZhciBqPTA7IGo8PWk7ICsraikge1xuICAgICAgQVtqXVtpXSA9IEFbaV1bal0gPSAyLjAgKiBkb3QocG9pbnRzW2ldLCBwb2ludHNbal0pXG4gICAgfVxuICAgIGJbaV0gPSBkb3QocG9pbnRzW2ldLCBwb2ludHNbaV0pXG4gIH1cbiAgdmFyIHggPSBzb2x2ZShBLCBiKVxuXG4gIHZhciBkZW5vbSA9IDAuMFxuICB2YXIgaCA9IHhbTisxXVxuICBmb3IodmFyIGk9MDsgaTxoLmxlbmd0aDsgKytpKSB7XG4gICAgZGVub20gKz0gaFtpXVxuICB9XG5cbiAgdmFyIHkgPSBuZXcgQXJyYXkoTilcbiAgZm9yKHZhciBpPTA7IGk8TjsgKytpKSB7XG4gICAgdmFyIGggPSB4W2ldXG4gICAgdmFyIG51bWVyID0gMC4wXG4gICAgZm9yKHZhciBqPTA7IGo8aC5sZW5ndGg7ICsraikge1xuICAgICAgbnVtZXIgKz0gaFtqXVxuICAgIH1cbiAgICB5W2ldID0gIG51bWVyIC8gZGVub21cbiAgfVxuXG4gIHJldHVybiB5XG59XG5cbmZ1bmN0aW9uIGNpcmN1bWNlbnRlcihwb2ludHMpIHtcbiAgaWYocG9pbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXVxuICB9XG4gIHZhciBEID0gcG9pbnRzWzBdLmxlbmd0aFxuICB2YXIgcmVzdWx0ID0gZHVwKFtEXSlcbiAgdmFyIHdlaWdodHMgPSBiYXJ5Y2VudHJpY0NpcmN1bWNlbnRlcihwb2ludHMpXG4gIGZvcih2YXIgaT0wOyBpPHBvaW50cy5sZW5ndGg7ICsraSkge1xuICAgIGZvcih2YXIgaj0wOyBqPEQ7ICsraikge1xuICAgICAgcmVzdWx0W2pdICs9IHBvaW50c1tpXVtqXSAqIHdlaWdodHNbaV1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5jaXJjdW1jZW50ZXIuYmFyeWNlbmV0cmljID0gYmFyeWNlbnRyaWNDaXJjdW1jZW50ZXJcbm1vZHVsZS5leHBvcnRzID0gY2lyY3VtY2VudGVyXG59LHtcImR1cFwiOjE3MCxcInJvYnVzdC1saW5lYXItc29sdmVcIjo1MDl9XSwxMTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBjaXJjdW1yYWRpdXNcblxudmFyIGNpcmN1bWNlbnRlciA9IF9kZXJlcV8oJ2NpcmN1bWNlbnRlcicpXG5cbmZ1bmN0aW9uIGNpcmN1bXJhZGl1cyhwb2ludHMpIHtcbiAgdmFyIGNlbnRlciA9IGNpcmN1bWNlbnRlcihwb2ludHMpXG4gIHZhciBhdmdEaXN0ID0gMC4wXG4gIGZvcih2YXIgaT0wOyBpPHBvaW50cy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBwID0gcG9pbnRzW2ldXG4gICAgZm9yKHZhciBqPTA7IGo8Y2VudGVyLmxlbmd0aDsgKytqKSB7XG4gICAgICBhdmdEaXN0ICs9IE1hdGgucG93KHBbal0gLSBjZW50ZXJbal0sIDIpXG4gICAgfVxuICB9XG4gIHJldHVybiBNYXRoLnNxcnQoYXZnRGlzdCAvIHBvaW50cy5sZW5ndGgpXG59XG59LHtcImNpcmN1bWNlbnRlclwiOjExM31dLDExNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGNsYW1wXG5cbmZ1bmN0aW9uIGNsYW1wKHZhbHVlLCBtaW4sIG1heCkge1xuICByZXR1cm4gbWluIDwgbWF4XG4gICAgPyAodmFsdWUgPCBtaW4gPyBtaW4gOiB2YWx1ZSA+IG1heCA/IG1heCA6IHZhbHVlKVxuICAgIDogKHZhbHVlIDwgbWF4ID8gbWF4IDogdmFsdWUgPiBtaW4gPyBtaW4gOiB2YWx1ZSlcbn1cblxufSx7fV0sMTE2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsZWFuUFNMR1xuXG52YXIgVW5pb25GaW5kID0gX2RlcmVxXygndW5pb24tZmluZCcpXG52YXIgYm94SW50ZXJzZWN0ID0gX2RlcmVxXygnYm94LWludGVyc2VjdCcpXG52YXIgc2Vnc2VnID0gX2RlcmVxXygncm9idXN0LXNlZ21lbnQtaW50ZXJzZWN0JylcbnZhciByYXQgPSBfZGVyZXFfKCdiaWctcmF0JylcbnZhciByYXRDbXAgPSBfZGVyZXFfKCdiaWctcmF0L2NtcCcpXG52YXIgcmF0VG9GbG9hdCA9IF9kZXJlcV8oJ2JpZy1yYXQvdG8tZmxvYXQnKVxudmFyIHJhdFZlYyA9IF9kZXJlcV8oJ3JhdC12ZWMnKVxudmFyIG5leHRhZnRlciA9IF9kZXJlcV8oJ25leHRhZnRlcicpXG5cbnZhciBzb2x2ZUludGVyc2VjdGlvbiA9IF9kZXJlcV8oJy4vbGliL3JhdC1zZWctaW50ZXJzZWN0JylcblxuLy8gQm91bmRzIG9uIGEgcmF0aW9uYWwgbnVtYmVyIHdoZW4gcm91bmRlZCB0byBhIGZsb2F0XG5mdW5jdGlvbiBib3VuZFJhdCAocikge1xuICB2YXIgZiA9IHJhdFRvRmxvYXQocilcbiAgcmV0dXJuIFtcbiAgICBuZXh0YWZ0ZXIoZiwgLUluZmluaXR5KSxcbiAgICBuZXh0YWZ0ZXIoZiwgSW5maW5pdHkpXG4gIF1cbn1cblxuLy8gQ29udmVydCBhIGxpc3Qgb2YgZWRnZXMgaW4gYSBwc2xnIHRvIGJvdW5kaW5nIGJveGVzXG5mdW5jdGlvbiBib3VuZEVkZ2VzIChwb2ludHMsIGVkZ2VzKSB7XG4gIHZhciBib3VuZHMgPSBuZXcgQXJyYXkoZWRnZXMubGVuZ3RoKVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGUgPSBlZGdlc1tpXVxuICAgIHZhciBhID0gcG9pbnRzW2VbMF1dXG4gICAgdmFyIGIgPSBwb2ludHNbZVsxXV1cbiAgICBib3VuZHNbaV0gPSBbXG4gICAgICBuZXh0YWZ0ZXIoTWF0aC5taW4oYVswXSwgYlswXSksIC1JbmZpbml0eSksXG4gICAgICBuZXh0YWZ0ZXIoTWF0aC5taW4oYVsxXSwgYlsxXSksIC1JbmZpbml0eSksXG4gICAgICBuZXh0YWZ0ZXIoTWF0aC5tYXgoYVswXSwgYlswXSksIEluZmluaXR5KSxcbiAgICAgIG5leHRhZnRlcihNYXRoLm1heChhWzFdLCBiWzFdKSwgSW5maW5pdHkpXG4gICAgXVxuICB9XG4gIHJldHVybiBib3VuZHNcbn1cblxuLy8gQ29udmVydCBhIGxpc3Qgb2YgcG9pbnRzIGludG8gYm91bmRpbmcgYm94ZXMgYnkgZHVwbGljYXRpbmcgY29vcmRzXG5mdW5jdGlvbiBib3VuZFBvaW50cyAocG9pbnRzKSB7XG4gIHZhciBib3VuZHMgPSBuZXcgQXJyYXkocG9pbnRzLmxlbmd0aClcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcCA9IHBvaW50c1tpXVxuICAgIGJvdW5kc1tpXSA9IFtcbiAgICAgIG5leHRhZnRlcihwWzBdLCAtSW5maW5pdHkpLFxuICAgICAgbmV4dGFmdGVyKHBbMV0sIC1JbmZpbml0eSksXG4gICAgICBuZXh0YWZ0ZXIocFswXSwgSW5maW5pdHkpLFxuICAgICAgbmV4dGFmdGVyKHBbMV0sIEluZmluaXR5KVxuICAgIF1cbiAgfVxuICByZXR1cm4gYm91bmRzXG59XG5cbi8vIEZpbmQgYWxsIHBhaXJzIG9mIGNyb3NzaW5nIGVkZ2VzIGluIGEgcHNsZyAoZ2l2ZW4gZWRnZSBib3VuZHMpXG5mdW5jdGlvbiBnZXRDcm9zc2luZ3MgKHBvaW50cywgZWRnZXMsIGVkZ2VCb3VuZHMpIHtcbiAgdmFyIHJlc3VsdCA9IFtdXG4gIGJveEludGVyc2VjdChlZGdlQm91bmRzLCBmdW5jdGlvbiAoaSwgaikge1xuICAgIHZhciBlID0gZWRnZXNbaV1cbiAgICB2YXIgZiA9IGVkZ2VzW2pdXG4gICAgaWYgKGVbMF0gPT09IGZbMF0gfHwgZVswXSA9PT0gZlsxXSB8fFxuICAgICAgZVsxXSA9PT0gZlswXSB8fCBlWzFdID09PSBmWzFdKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgdmFyIGEgPSBwb2ludHNbZVswXV1cbiAgICB2YXIgYiA9IHBvaW50c1tlWzFdXVxuICAgIHZhciBjID0gcG9pbnRzW2ZbMF1dXG4gICAgdmFyIGQgPSBwb2ludHNbZlsxXV1cbiAgICBpZiAoc2Vnc2VnKGEsIGIsIGMsIGQpKSB7XG4gICAgICByZXN1bHQucHVzaChbaSwgal0pXG4gICAgfVxuICB9KVxuICByZXR1cm4gcmVzdWx0XG59XG5cbi8vIEZpbmQgYWxsIHBhaXJzIG9mIGNyb3NzaW5nIHZlcnRpY2VzIGluIGEgcHNsZyAoZ2l2ZW4gZWRnZS92ZXJ0IGJvdW5kcylcbmZ1bmN0aW9uIGdldFRKdW5jdGlvbnMgKHBvaW50cywgZWRnZXMsIGVkZ2VCb3VuZHMsIHZlcnRCb3VuZHMpIHtcbiAgdmFyIHJlc3VsdCA9IFtdXG4gIGJveEludGVyc2VjdChlZGdlQm91bmRzLCB2ZXJ0Qm91bmRzLCBmdW5jdGlvbiAoaSwgdikge1xuICAgIHZhciBlID0gZWRnZXNbaV1cbiAgICBpZiAoZVswXSA9PT0gdiB8fCBlWzFdID09PSB2KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgdmFyIHAgPSBwb2ludHNbdl1cbiAgICB2YXIgYSA9IHBvaW50c1tlWzBdXVxuICAgIHZhciBiID0gcG9pbnRzW2VbMV1dXG4gICAgaWYgKHNlZ3NlZyhhLCBiLCBwLCBwKSkge1xuICAgICAgcmVzdWx0LnB1c2goW2ksIHZdKVxuICAgIH1cbiAgfSlcbiAgcmV0dXJuIHJlc3VsdFxufVxuXG4vLyBDdXQgZWRnZXMgYWxvbmcgY3Jvc3NpbmdzL3RqdW5jdGlvbnNcbmZ1bmN0aW9uIGN1dEVkZ2VzIChmbG9hdFBvaW50cywgZWRnZXMsIGNyb3NzaW5ncywganVuY3Rpb25zLCB1c2VDb2xvcikge1xuICB2YXIgaSwgZVxuXG4gIC8vIENvbnZlcnQgY3Jvc3NpbmdzIGludG8gdGp1bmN0aW9ucyBieSBjb25zdHJ1Y3RpbmcgcmF0aW9uYWwgcG9pbnRzXG4gIHZhciByYXRQb2ludHMgPSBmbG9hdFBvaW50cy5tYXAoZnVuY3Rpb24ocCkge1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAgICByYXQocFswXSksXG4gICAgICAgICAgcmF0KHBbMV0pXG4gICAgICBdXG4gIH0pXG4gIGZvciAoaSA9IDA7IGkgPCBjcm9zc2luZ3MubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgY3Jvc3NpbmcgPSBjcm9zc2luZ3NbaV1cbiAgICBlID0gY3Jvc3NpbmdbMF1cbiAgICB2YXIgZiA9IGNyb3NzaW5nWzFdXG4gICAgdmFyIGVlID0gZWRnZXNbZV1cbiAgICB2YXIgZWYgPSBlZGdlc1tmXVxuICAgIHZhciB4ID0gc29sdmVJbnRlcnNlY3Rpb24oXG4gICAgICByYXRWZWMoZmxvYXRQb2ludHNbZWVbMF1dKSxcbiAgICAgIHJhdFZlYyhmbG9hdFBvaW50c1tlZVsxXV0pLFxuICAgICAgcmF0VmVjKGZsb2F0UG9pbnRzW2VmWzBdXSksXG4gICAgICByYXRWZWMoZmxvYXRQb2ludHNbZWZbMV1dKSlcbiAgICBpZiAoIXgpIHtcbiAgICAgIC8vIFNlZ21lbnRzIGFyZSBwYXJhbGxlbCwgc2hvdWxkIGFscmVhZHkgYmUgaGFuZGxlZCBieSB0LWp1bmN0aW9uc1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgdmFyIGlkeCA9IGZsb2F0UG9pbnRzLmxlbmd0aFxuICAgIGZsb2F0UG9pbnRzLnB1c2goW3JhdFRvRmxvYXQoeFswXSksIHJhdFRvRmxvYXQoeFsxXSldKVxuICAgIHJhdFBvaW50cy5wdXNoKHgpXG4gICAganVuY3Rpb25zLnB1c2goW2UsIGlkeF0sIFtmLCBpZHhdKVxuICB9XG5cbiAgLy8gU29ydCB0anVuY3Rpb25zXG4gIGp1bmN0aW9ucy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgaWYgKGFbMF0gIT09IGJbMF0pIHtcbiAgICAgIHJldHVybiBhWzBdIC0gYlswXVxuICAgIH1cbiAgICB2YXIgdSA9IHJhdFBvaW50c1thWzFdXVxuICAgIHZhciB2ID0gcmF0UG9pbnRzW2JbMV1dXG4gICAgcmV0dXJuIHJhdENtcCh1WzBdLCB2WzBdKSB8fCByYXRDbXAodVsxXSwgdlsxXSlcbiAgfSlcblxuICAvLyBTcGxpdCBlZGdlcyBhbG9uZyBqdW5jdGlvbnNcbiAgZm9yIChpID0ganVuY3Rpb25zLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgdmFyIGp1bmN0aW9uID0ganVuY3Rpb25zW2ldXG4gICAgZSA9IGp1bmN0aW9uWzBdXG5cbiAgICB2YXIgZWRnZSA9IGVkZ2VzW2VdXG4gICAgdmFyIHMgPSBlZGdlWzBdXG4gICAgdmFyIHQgPSBlZGdlWzFdXG5cbiAgICAvLyBDaGVjayBpZiBlZGdlIGlzIG5vdCBsZXhpY29ncmFwaGljYWxseSBzb3J0ZWRcbiAgICB2YXIgYSA9IGZsb2F0UG9pbnRzW3NdXG4gICAgdmFyIGIgPSBmbG9hdFBvaW50c1t0XVxuICAgIGlmICgoKGFbMF0gLSBiWzBdKSB8fCAoYVsxXSAtIGJbMV0pKSA8IDApIHtcbiAgICAgIHZhciB0bXAgPSBzXG4gICAgICBzID0gdFxuICAgICAgdCA9IHRtcFxuICAgIH1cblxuICAgIC8vIFNwbGl0IGxlYWRpbmcgZWRnZVxuICAgIGVkZ2VbMF0gPSBzXG4gICAgdmFyIGxhc3QgPSBlZGdlWzFdID0ganVuY3Rpb25bMV1cblxuICAgIC8vIElmIHdlIGFyZSBncm91cGluZyBlZGdlcyBieSBjb2xvciwgcmVtZW1iZXIgdG8gdHJhY2sgZGF0YVxuICAgIHZhciBjb2xvclxuICAgIGlmICh1c2VDb2xvcikge1xuICAgICAgY29sb3IgPSBlZGdlWzJdXG4gICAgfVxuXG4gICAgLy8gU3BsaXQgb3RoZXIgZWRnZXNcbiAgICB3aGlsZSAoaSA+IDAgJiYganVuY3Rpb25zW2kgLSAxXVswXSA9PT0gZSkge1xuICAgICAgdmFyIGp1bmN0aW9uID0ganVuY3Rpb25zWy0taV1cbiAgICAgIHZhciBuZXh0ID0ganVuY3Rpb25bMV1cbiAgICAgIGlmICh1c2VDb2xvcikge1xuICAgICAgICBlZGdlcy5wdXNoKFtsYXN0LCBuZXh0LCBjb2xvcl0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlZGdlcy5wdXNoKFtsYXN0LCBuZXh0XSlcbiAgICAgIH1cbiAgICAgIGxhc3QgPSBuZXh0XG4gICAgfVxuXG4gICAgLy8gQWRkIGZpbmFsIGVkZ2VcbiAgICBpZiAodXNlQ29sb3IpIHtcbiAgICAgIGVkZ2VzLnB1c2goW2xhc3QsIHQsIGNvbG9yXSlcbiAgICB9IGVsc2Uge1xuICAgICAgZWRnZXMucHVzaChbbGFzdCwgdF0pXG4gICAgfVxuICB9XG5cbiAgLy8gUmV0dXJuIGNvbnN0cnVjdGVkIHJhdGlvbmFsIHBvaW50c1xuICByZXR1cm4gcmF0UG9pbnRzXG59XG5cbi8vIE1lcmdlIG92ZXJsYXBwaW5nIHBvaW50c1xuZnVuY3Rpb24gZGVkdXBQb2ludHMgKGZsb2F0UG9pbnRzLCByYXRQb2ludHMsIGZsb2F0Qm91bmRzKSB7XG4gIHZhciBudW1Qb2ludHMgPSByYXRQb2ludHMubGVuZ3RoXG4gIHZhciB1ZiA9IG5ldyBVbmlvbkZpbmQobnVtUG9pbnRzKVxuXG4gIC8vIENvbXB1dGUgcmF0aW9uYWwgYm91bmRzXG4gIHZhciBib3VuZHMgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHJhdFBvaW50cy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBwID0gcmF0UG9pbnRzW2ldXG4gICAgdmFyIHhiID0gYm91bmRSYXQocFswXSlcbiAgICB2YXIgeWIgPSBib3VuZFJhdChwWzFdKVxuICAgIGJvdW5kcy5wdXNoKFtcbiAgICAgIG5leHRhZnRlcih4YlswXSwgLUluZmluaXR5KSxcbiAgICAgIG5leHRhZnRlcih5YlswXSwgLUluZmluaXR5KSxcbiAgICAgIG5leHRhZnRlcih4YlsxXSwgSW5maW5pdHkpLFxuICAgICAgbmV4dGFmdGVyKHliWzFdLCBJbmZpbml0eSlcbiAgICBdKVxuICB9XG5cbiAgLy8gTGluayBhbGwgcG9pbnRzIHdpdGggb3ZlciBsYXBwaW5nIGJveGVzXG4gIGJveEludGVyc2VjdChib3VuZHMsIGZ1bmN0aW9uIChpLCBqKSB7XG4gICAgdWYubGluayhpLCBqKVxuICB9KVxuXG4gIC8vIERvIDEgcGFzcyBvdmVyIHBvaW50cyB0byBjb21iaW5lIHBvaW50cyBpbiBsYWJlbCBzZXRzXG4gIHZhciBub0R1cGVzID0gdHJ1ZVxuICB2YXIgbGFiZWxzID0gbmV3IEFycmF5KG51bVBvaW50cylcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW1Qb2ludHM7ICsraSkge1xuICAgIHZhciBqID0gdWYuZmluZChpKVxuICAgIGlmIChqICE9PSBpKSB7XG4gICAgICAvLyBDbGVhciBuby1kdXBlcyBmbGFnLCB6ZXJvIG91dCBsYWJlbFxuICAgICAgbm9EdXBlcyA9IGZhbHNlXG4gICAgICAvLyBNYWtlIGVhY2ggcG9pbnQgdGhlIHRvcC1sZWZ0IHBvaW50IGZyb20gaXRzIGNlbGxcbiAgICAgIGZsb2F0UG9pbnRzW2pdID0gW1xuICAgICAgICBNYXRoLm1pbihmbG9hdFBvaW50c1tpXVswXSwgZmxvYXRQb2ludHNbal1bMF0pLFxuICAgICAgICBNYXRoLm1pbihmbG9hdFBvaW50c1tpXVsxXSwgZmxvYXRQb2ludHNbal1bMV0pXG4gICAgICBdXG4gICAgfVxuICB9XG5cbiAgLy8gSWYgbm8gZHVwbGljYXRlcywgcmV0dXJuIG51bGwgdG8gc2lnbmFsIHRlcm1pbmF0aW9uXG4gIGlmIChub0R1cGVzKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHZhciBwdHIgPSAwXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtUG9pbnRzOyArK2kpIHtcbiAgICB2YXIgaiA9IHVmLmZpbmQoaSlcbiAgICBpZiAoaiA9PT0gaSkge1xuICAgICAgbGFiZWxzW2ldID0gcHRyXG4gICAgICBmbG9hdFBvaW50c1twdHIrK10gPSBmbG9hdFBvaW50c1tpXVxuICAgIH0gZWxzZSB7XG4gICAgICBsYWJlbHNbaV0gPSAtMVxuICAgIH1cbiAgfVxuXG4gIGZsb2F0UG9pbnRzLmxlbmd0aCA9IHB0clxuXG4gIC8vIERvIGEgc2Vjb25kIHBhc3MgdG8gZml4IHVwIG1pc3NpbmcgbGFiZWxzXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtUG9pbnRzOyArK2kpIHtcbiAgICBpZiAobGFiZWxzW2ldIDwgMCkge1xuICAgICAgbGFiZWxzW2ldID0gbGFiZWxzW3VmLmZpbmQoaSldXG4gICAgfVxuICB9XG5cbiAgLy8gUmV0dXJuIHJlc3VsdGluZyB1bmlvbi1maW5kIGRhdGEgc3RydWN0dXJlXG4gIHJldHVybiBsYWJlbHNcbn1cblxuZnVuY3Rpb24gY29tcGFyZUxleDIgKGEsIGIpIHsgcmV0dXJuIChhWzBdIC0gYlswXSkgfHwgKGFbMV0gLSBiWzFdKSB9XG5mdW5jdGlvbiBjb21wYXJlTGV4MyAoYSwgYikge1xuICB2YXIgZCA9IChhWzBdIC0gYlswXSkgfHwgKGFbMV0gLSBiWzFdKVxuICBpZiAoZCkge1xuICAgIHJldHVybiBkXG4gIH1cbiAgaWYgKGFbMl0gPCBiWzJdKSB7XG4gICAgcmV0dXJuIC0xXG4gIH0gZWxzZSBpZiAoYVsyXSA+IGJbMl0pIHtcbiAgICByZXR1cm4gMVxuICB9XG4gIHJldHVybiAwXG59XG5cbi8vIFJlbW92ZSBkdXBsaWNhdGUgZWRnZSBsYWJlbHNcbmZ1bmN0aW9uIGRlZHVwRWRnZXMgKGVkZ2VzLCBsYWJlbHMsIHVzZUNvbG9yKSB7XG4gIGlmIChlZGdlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm5cbiAgfVxuICBpZiAobGFiZWxzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlZGdlcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGUgPSBlZGdlc1tpXVxuICAgICAgdmFyIGEgPSBsYWJlbHNbZVswXV1cbiAgICAgIHZhciBiID0gbGFiZWxzW2VbMV1dXG4gICAgICBlWzBdID0gTWF0aC5taW4oYSwgYilcbiAgICAgIGVbMV0gPSBNYXRoLm1heChhLCBiKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgZSA9IGVkZ2VzW2ldXG4gICAgICB2YXIgYSA9IGVbMF1cbiAgICAgIHZhciBiID0gZVsxXVxuICAgICAgZVswXSA9IE1hdGgubWluKGEsIGIpXG4gICAgICBlWzFdID0gTWF0aC5tYXgoYSwgYilcbiAgICB9XG4gIH1cbiAgaWYgKHVzZUNvbG9yKSB7XG4gICAgZWRnZXMuc29ydChjb21wYXJlTGV4MylcbiAgfSBlbHNlIHtcbiAgICBlZGdlcy5zb3J0KGNvbXBhcmVMZXgyKVxuICB9XG4gIHZhciBwdHIgPSAxXG4gIGZvciAodmFyIGkgPSAxOyBpIDwgZWRnZXMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcHJldiA9IGVkZ2VzW2kgLSAxXVxuICAgIHZhciBuZXh0ID0gZWRnZXNbaV1cbiAgICBpZiAobmV4dFswXSA9PT0gcHJldlswXSAmJiBuZXh0WzFdID09PSBwcmV2WzFdICYmXG4gICAgICAoIXVzZUNvbG9yIHx8IG5leHRbMl0gPT09IHByZXZbMl0pKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBlZGdlc1twdHIrK10gPSBuZXh0XG4gIH1cbiAgZWRnZXMubGVuZ3RoID0gcHRyXG59XG5cbmZ1bmN0aW9uIHByZVJvdW5kIChwb2ludHMsIGVkZ2VzLCB1c2VDb2xvcikge1xuICB2YXIgbGFiZWxzID0gZGVkdXBQb2ludHMocG9pbnRzLCBbXSwgYm91bmRQb2ludHMocG9pbnRzKSlcbiAgZGVkdXBFZGdlcyhlZGdlcywgbGFiZWxzLCB1c2VDb2xvcilcbiAgcmV0dXJuICEhbGFiZWxzXG59XG5cbi8vIFJlcGVhdCB1bnRpbCBjb252ZXJnZW5jZVxuZnVuY3Rpb24gc25hcFJvdW5kIChwb2ludHMsIGVkZ2VzLCB1c2VDb2xvcikge1xuICAvLyAxLiBmaW5kIGVkZ2UgY3Jvc3NpbmdzXG4gIHZhciBlZGdlQm91bmRzID0gYm91bmRFZGdlcyhwb2ludHMsIGVkZ2VzKVxuICB2YXIgY3Jvc3NpbmdzID0gZ2V0Q3Jvc3NpbmdzKHBvaW50cywgZWRnZXMsIGVkZ2VCb3VuZHMpXG5cbiAgLy8gMi4gZmluZCB0LWp1bmN0aW9uc1xuICB2YXIgdmVydEJvdW5kcyA9IGJvdW5kUG9pbnRzKHBvaW50cylcbiAgdmFyIHRqdW5jdGlvbnMgPSBnZXRUSnVuY3Rpb25zKHBvaW50cywgZWRnZXMsIGVkZ2VCb3VuZHMsIHZlcnRCb3VuZHMpXG5cbiAgLy8gMy4gY3V0IGVkZ2VzLCBjb25zdHJ1Y3QgcmF0aW9uYWwgcG9pbnRzXG4gIHZhciByYXRQb2ludHMgPSBjdXRFZGdlcyhwb2ludHMsIGVkZ2VzLCBjcm9zc2luZ3MsIHRqdW5jdGlvbnMsIHVzZUNvbG9yKVxuXG4gIC8vIDQuIGRlZHVwZSB2ZXJ0c1xuICB2YXIgbGFiZWxzID0gZGVkdXBQb2ludHMocG9pbnRzLCByYXRQb2ludHMsIHZlcnRCb3VuZHMpXG5cbiAgLy8gNS4gZGVkdXBlIGVkZ2VzXG4gIGRlZHVwRWRnZXMoZWRnZXMsIGxhYmVscywgdXNlQ29sb3IpXG5cbiAgLy8gNi4gY2hlY2sgdGVybWluYXRpb25cbiAgaWYgKCFsYWJlbHMpIHtcbiAgICByZXR1cm4gKGNyb3NzaW5ncy5sZW5ndGggPiAwIHx8IHRqdW5jdGlvbnMubGVuZ3RoID4gMClcbiAgfVxuXG4gIC8vIE1vcmUgaXRlcmF0aW9ucyBuZWNlc3NhcnlcbiAgcmV0dXJuIHRydWVcbn1cblxuLy8gTWFpbiBsb29wLCBydW5zIFBTTEcgY2xlYW4gdXAgdW50aWwgY29tcGxldGlvblxuZnVuY3Rpb24gY2xlYW5QU0xHIChwb2ludHMsIGVkZ2VzLCBjb2xvcnMpIHtcbiAgLy8gSWYgdXNpbmcgY29sb3JzLCBhdWdtZW50IGVkZ2VzIHdpdGggY29sb3IgZGF0YVxuICB2YXIgcHJldkVkZ2VzXG4gIGlmIChjb2xvcnMpIHtcbiAgICBwcmV2RWRnZXMgPSBlZGdlc1xuICAgIHZhciBhdWdFZGdlcyA9IG5ldyBBcnJheShlZGdlcy5sZW5ndGgpXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlZGdlcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGUgPSBlZGdlc1tpXVxuICAgICAgYXVnRWRnZXNbaV0gPSBbZVswXSwgZVsxXSwgY29sb3JzW2ldXVxuICAgIH1cbiAgICBlZGdlcyA9IGF1Z0VkZ2VzXG4gIH1cblxuICAvLyBGaXJzdCByb3VuZDogcmVtb3ZlIGR1cGxpY2F0ZSBlZGdlcyBhbmQgcG9pbnRzXG4gIHZhciBtb2RpZmllZCA9IHByZVJvdW5kKHBvaW50cywgZWRnZXMsICEhY29sb3JzKVxuXG4gIC8vIFJ1biBzbmFwIHJvdW5kaW5nIHVudGlsIGNvbnZlcmdlbmNlXG4gIHdoaWxlIChzbmFwUm91bmQocG9pbnRzLCBlZGdlcywgISFjb2xvcnMpKSB7XG4gICAgbW9kaWZpZWQgPSB0cnVlXG4gIH1cblxuICAvLyBTdHJpcCBjb2xvciB0YWdzXG4gIGlmICghIWNvbG9ycyAmJiBtb2RpZmllZCkge1xuICAgIHByZXZFZGdlcy5sZW5ndGggPSAwXG4gICAgY29sb3JzLmxlbmd0aCA9IDBcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgZSA9IGVkZ2VzW2ldXG4gICAgICBwcmV2RWRnZXMucHVzaChbZVswXSwgZVsxXV0pXG4gICAgICBjb2xvcnMucHVzaChlWzJdKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtb2RpZmllZFxufVxuXG59LHtcIi4vbGliL3JhdC1zZWctaW50ZXJzZWN0XCI6MTE3LFwiYmlnLXJhdFwiOjc4LFwiYmlnLXJhdC9jbXBcIjo3NixcImJpZy1yYXQvdG8tZmxvYXRcIjo5MCxcImJveC1pbnRlcnNlY3RcIjo5NixcIm5leHRhZnRlclwiOjQ1MSxcInJhdC12ZWNcIjo0ODYsXCJyb2J1c3Qtc2VnbWVudC1pbnRlcnNlY3RcIjo1MTMsXCJ1bmlvbi1maW5kXCI6NTQ2fV0sMTE3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IHNvbHZlSW50ZXJzZWN0aW9uXG5cbnZhciByYXRNdWwgPSBfZGVyZXFfKCdiaWctcmF0L211bCcpXG52YXIgcmF0RGl2ID0gX2RlcmVxXygnYmlnLXJhdC9kaXYnKVxudmFyIHJhdFN1YiA9IF9kZXJlcV8oJ2JpZy1yYXQvc3ViJylcbnZhciByYXRTaWduID0gX2RlcmVxXygnYmlnLXJhdC9zaWduJylcbnZhciBydlN1YiA9IF9kZXJlcV8oJ3JhdC12ZWMvc3ViJylcbnZhciBydkFkZCA9IF9kZXJlcV8oJ3JhdC12ZWMvYWRkJylcbnZhciBydk11bHMgPSBfZGVyZXFfKCdyYXQtdmVjL211bHMnKVxuXG5mdW5jdGlvbiByYXRQZXJwIChhLCBiKSB7XG4gIHJldHVybiByYXRTdWIocmF0TXVsKGFbMF0sIGJbMV0pLCByYXRNdWwoYVsxXSwgYlswXSkpXG59XG5cbi8vIFNvbHZlIGZvciBpbnRlcnNlY3Rpb25cbi8vICB4ID0gYSArIHQgKGItYSlcbi8vICAoeCAtIGMpIF4gKGQtYykgPSAwXG4vLyAgKHQgKiAoYi1hKSArIChhLWMpICkgXiAoZC1jKSA9IDBcbi8vICB0ICogKGItYSleKGQtYykgPSAoZC1jKV4oYS1jKVxuLy8gIHQgPSAoZC1jKV4oYS1jKSAvIChiLWEpXihkLWMpXG5cbmZ1bmN0aW9uIHNvbHZlSW50ZXJzZWN0aW9uIChhLCBiLCBjLCBkKSB7XG4gIHZhciBiYSA9IHJ2U3ViKGIsIGEpXG4gIHZhciBkYyA9IHJ2U3ViKGQsIGMpXG5cbiAgdmFyIGJhWGRjID0gcmF0UGVycChiYSwgZGMpXG5cbiAgaWYgKHJhdFNpZ24oYmFYZGMpID09PSAwKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHZhciBhYyA9IHJ2U3ViKGEsIGMpXG4gIHZhciBkY1hhYyA9IHJhdFBlcnAoZGMsIGFjKVxuXG4gIHZhciB0ID0gcmF0RGl2KGRjWGFjLCBiYVhkYylcbiAgdmFyIHMgPSBydk11bHMoYmEsIHQpXG4gIHZhciByID0gcnZBZGQoYSwgcylcblxuICByZXR1cm4gclxufVxuXG59LHtcImJpZy1yYXQvZGl2XCI6NzcsXCJiaWctcmF0L211bFwiOjg3LFwiYmlnLXJhdC9zaWduXCI6ODgsXCJiaWctcmF0L3N1YlwiOjg5LFwicmF0LXZlYy9hZGRcIjo0ODUsXCJyYXQtdmVjL211bHNcIjo0ODcsXCJyYXQtdmVjL3N1YlwiOjQ4OH1dLDExODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKiogQG1vZHVsZSAgY29sb3ItaWQgKi9cclxuXHJcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGNsYW1wID0gX2RlcmVxXygnY2xhbXAnKVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSB0b051bWJlclxyXG5tb2R1bGUuZXhwb3J0cy50byA9IHRvTnVtYmVyXHJcbm1vZHVsZS5leHBvcnRzLmZyb20gPSBmcm9tTnVtYmVyXHJcblxyXG5mdW5jdGlvbiB0b051bWJlciAocmdiYSwgbm9ybWFsaXplZCkge1xyXG5cdGlmKG5vcm1hbGl6ZWQgPT0gbnVsbCkgbm9ybWFsaXplZCA9IHRydWVcclxuXHJcblx0dmFyIHIgPSByZ2JhWzBdLCBnID0gcmdiYVsxXSwgYiA9IHJnYmFbMl0sIGEgPSByZ2JhWzNdXHJcblxyXG5cdGlmIChhID09IG51bGwpIGEgPSBub3JtYWxpemVkID8gMSA6IDI1NVxyXG5cclxuXHRpZiAobm9ybWFsaXplZCkge1xyXG5cdFx0ciAqPSAyNTVcclxuXHRcdGcgKj0gMjU1XHJcblx0XHRiICo9IDI1NVxyXG5cdFx0YSAqPSAyNTVcclxuXHR9XHJcblxyXG5cdHIgPSBjbGFtcChyLCAwLCAyNTUpICYgMHhGRlxyXG5cdGcgPSBjbGFtcChnLCAwLCAyNTUpICYgMHhGRlxyXG5cdGIgPSBjbGFtcChiLCAwLCAyNTUpICYgMHhGRlxyXG5cdGEgPSBjbGFtcChhLCAwLCAyNTUpICYgMHhGRlxyXG5cclxuXHQvL2hpLW9yZGVyIHNoaWZ0IGNvbnZlcnRzIHRvIC0xLCBzbyB3ZSBjYW4ndCB1c2UgPDwyNFxyXG5cdHZhciBuID0gKHIgKiAweDAxMDAwMDAwKSArIChnIDw8IDE2KSArIChiIDw8IDgpICsgKGEpXHJcblxyXG5cdHJldHVybiBuXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGZyb21OdW1iZXIgKG4sIG5vcm1hbGl6ZWQpIHtcclxuXHRuID0gK25cclxuXHJcblx0dmFyIHIgPSBuID4+PiAyNFxyXG5cdHZhciBnID0gKG4gJiAweDAwZmYwMDAwKSA+Pj4gMTZcclxuXHR2YXIgYiA9IChuICYgMHgwMDAwZmYwMCkgPj4+IDhcclxuXHR2YXIgYSA9IG4gJiAweDAwMDAwMGZmXHJcblxyXG5cdGlmIChub3JtYWxpemVkID09PSBmYWxzZSkgcmV0dXJuIFtyLCBnLCBiLCBhXVxyXG5cclxuXHRyZXR1cm4gW3IvMjU1LCBnLzI1NSwgYi8yNTUsIGEvMjU1XVxyXG59XHJcblxufSx7XCJjbGFtcFwiOjExNX1dLDExOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG5cdFwiYWxpY2VibHVlXCI6IFsyNDAsIDI0OCwgMjU1XSxcclxuXHRcImFudGlxdWV3aGl0ZVwiOiBbMjUwLCAyMzUsIDIxNV0sXHJcblx0XCJhcXVhXCI6IFswLCAyNTUsIDI1NV0sXHJcblx0XCJhcXVhbWFyaW5lXCI6IFsxMjcsIDI1NSwgMjEyXSxcclxuXHRcImF6dXJlXCI6IFsyNDAsIDI1NSwgMjU1XSxcclxuXHRcImJlaWdlXCI6IFsyNDUsIDI0NSwgMjIwXSxcclxuXHRcImJpc3F1ZVwiOiBbMjU1LCAyMjgsIDE5Nl0sXHJcblx0XCJibGFja1wiOiBbMCwgMCwgMF0sXHJcblx0XCJibGFuY2hlZGFsbW9uZFwiOiBbMjU1LCAyMzUsIDIwNV0sXHJcblx0XCJibHVlXCI6IFswLCAwLCAyNTVdLFxyXG5cdFwiYmx1ZXZpb2xldFwiOiBbMTM4LCA0MywgMjI2XSxcclxuXHRcImJyb3duXCI6IFsxNjUsIDQyLCA0Ml0sXHJcblx0XCJidXJseXdvb2RcIjogWzIyMiwgMTg0LCAxMzVdLFxyXG5cdFwiY2FkZXRibHVlXCI6IFs5NSwgMTU4LCAxNjBdLFxyXG5cdFwiY2hhcnRyZXVzZVwiOiBbMTI3LCAyNTUsIDBdLFxyXG5cdFwiY2hvY29sYXRlXCI6IFsyMTAsIDEwNSwgMzBdLFxyXG5cdFwiY29yYWxcIjogWzI1NSwgMTI3LCA4MF0sXHJcblx0XCJjb3JuZmxvd2VyYmx1ZVwiOiBbMTAwLCAxNDksIDIzN10sXHJcblx0XCJjb3Juc2lsa1wiOiBbMjU1LCAyNDgsIDIyMF0sXHJcblx0XCJjcmltc29uXCI6IFsyMjAsIDIwLCA2MF0sXHJcblx0XCJjeWFuXCI6IFswLCAyNTUsIDI1NV0sXHJcblx0XCJkYXJrYmx1ZVwiOiBbMCwgMCwgMTM5XSxcclxuXHRcImRhcmtjeWFuXCI6IFswLCAxMzksIDEzOV0sXHJcblx0XCJkYXJrZ29sZGVucm9kXCI6IFsxODQsIDEzNCwgMTFdLFxyXG5cdFwiZGFya2dyYXlcIjogWzE2OSwgMTY5LCAxNjldLFxyXG5cdFwiZGFya2dyZWVuXCI6IFswLCAxMDAsIDBdLFxyXG5cdFwiZGFya2dyZXlcIjogWzE2OSwgMTY5LCAxNjldLFxyXG5cdFwiZGFya2toYWtpXCI6IFsxODksIDE4MywgMTA3XSxcclxuXHRcImRhcmttYWdlbnRhXCI6IFsxMzksIDAsIDEzOV0sXHJcblx0XCJkYXJrb2xpdmVncmVlblwiOiBbODUsIDEwNywgNDddLFxyXG5cdFwiZGFya29yYW5nZVwiOiBbMjU1LCAxNDAsIDBdLFxyXG5cdFwiZGFya29yY2hpZFwiOiBbMTUzLCA1MCwgMjA0XSxcclxuXHRcImRhcmtyZWRcIjogWzEzOSwgMCwgMF0sXHJcblx0XCJkYXJrc2FsbW9uXCI6IFsyMzMsIDE1MCwgMTIyXSxcclxuXHRcImRhcmtzZWFncmVlblwiOiBbMTQzLCAxODgsIDE0M10sXHJcblx0XCJkYXJrc2xhdGVibHVlXCI6IFs3MiwgNjEsIDEzOV0sXHJcblx0XCJkYXJrc2xhdGVncmF5XCI6IFs0NywgNzksIDc5XSxcclxuXHRcImRhcmtzbGF0ZWdyZXlcIjogWzQ3LCA3OSwgNzldLFxyXG5cdFwiZGFya3R1cnF1b2lzZVwiOiBbMCwgMjA2LCAyMDldLFxyXG5cdFwiZGFya3Zpb2xldFwiOiBbMTQ4LCAwLCAyMTFdLFxyXG5cdFwiZGVlcHBpbmtcIjogWzI1NSwgMjAsIDE0N10sXHJcblx0XCJkZWVwc2t5Ymx1ZVwiOiBbMCwgMTkxLCAyNTVdLFxyXG5cdFwiZGltZ3JheVwiOiBbMTA1LCAxMDUsIDEwNV0sXHJcblx0XCJkaW1ncmV5XCI6IFsxMDUsIDEwNSwgMTA1XSxcclxuXHRcImRvZGdlcmJsdWVcIjogWzMwLCAxNDQsIDI1NV0sXHJcblx0XCJmaXJlYnJpY2tcIjogWzE3OCwgMzQsIDM0XSxcclxuXHRcImZsb3JhbHdoaXRlXCI6IFsyNTUsIDI1MCwgMjQwXSxcclxuXHRcImZvcmVzdGdyZWVuXCI6IFszNCwgMTM5LCAzNF0sXHJcblx0XCJmdWNoc2lhXCI6IFsyNTUsIDAsIDI1NV0sXHJcblx0XCJnYWluc2Jvcm9cIjogWzIyMCwgMjIwLCAyMjBdLFxyXG5cdFwiZ2hvc3R3aGl0ZVwiOiBbMjQ4LCAyNDgsIDI1NV0sXHJcblx0XCJnb2xkXCI6IFsyNTUsIDIxNSwgMF0sXHJcblx0XCJnb2xkZW5yb2RcIjogWzIxOCwgMTY1LCAzMl0sXHJcblx0XCJncmF5XCI6IFsxMjgsIDEyOCwgMTI4XSxcclxuXHRcImdyZWVuXCI6IFswLCAxMjgsIDBdLFxyXG5cdFwiZ3JlZW55ZWxsb3dcIjogWzE3MywgMjU1LCA0N10sXHJcblx0XCJncmV5XCI6IFsxMjgsIDEyOCwgMTI4XSxcclxuXHRcImhvbmV5ZGV3XCI6IFsyNDAsIDI1NSwgMjQwXSxcclxuXHRcImhvdHBpbmtcIjogWzI1NSwgMTA1LCAxODBdLFxyXG5cdFwiaW5kaWFucmVkXCI6IFsyMDUsIDkyLCA5Ml0sXHJcblx0XCJpbmRpZ29cIjogWzc1LCAwLCAxMzBdLFxyXG5cdFwiaXZvcnlcIjogWzI1NSwgMjU1LCAyNDBdLFxyXG5cdFwia2hha2lcIjogWzI0MCwgMjMwLCAxNDBdLFxyXG5cdFwibGF2ZW5kZXJcIjogWzIzMCwgMjMwLCAyNTBdLFxyXG5cdFwibGF2ZW5kZXJibHVzaFwiOiBbMjU1LCAyNDAsIDI0NV0sXHJcblx0XCJsYXduZ3JlZW5cIjogWzEyNCwgMjUyLCAwXSxcclxuXHRcImxlbW9uY2hpZmZvblwiOiBbMjU1LCAyNTAsIDIwNV0sXHJcblx0XCJsaWdodGJsdWVcIjogWzE3MywgMjE2LCAyMzBdLFxyXG5cdFwibGlnaHRjb3JhbFwiOiBbMjQwLCAxMjgsIDEyOF0sXHJcblx0XCJsaWdodGN5YW5cIjogWzIyNCwgMjU1LCAyNTVdLFxyXG5cdFwibGlnaHRnb2xkZW5yb2R5ZWxsb3dcIjogWzI1MCwgMjUwLCAyMTBdLFxyXG5cdFwibGlnaHRncmF5XCI6IFsyMTEsIDIxMSwgMjExXSxcclxuXHRcImxpZ2h0Z3JlZW5cIjogWzE0NCwgMjM4LCAxNDRdLFxyXG5cdFwibGlnaHRncmV5XCI6IFsyMTEsIDIxMSwgMjExXSxcclxuXHRcImxpZ2h0cGlua1wiOiBbMjU1LCAxODIsIDE5M10sXHJcblx0XCJsaWdodHNhbG1vblwiOiBbMjU1LCAxNjAsIDEyMl0sXHJcblx0XCJsaWdodHNlYWdyZWVuXCI6IFszMiwgMTc4LCAxNzBdLFxyXG5cdFwibGlnaHRza3libHVlXCI6IFsxMzUsIDIwNiwgMjUwXSxcclxuXHRcImxpZ2h0c2xhdGVncmF5XCI6IFsxMTksIDEzNiwgMTUzXSxcclxuXHRcImxpZ2h0c2xhdGVncmV5XCI6IFsxMTksIDEzNiwgMTUzXSxcclxuXHRcImxpZ2h0c3RlZWxibHVlXCI6IFsxNzYsIDE5NiwgMjIyXSxcclxuXHRcImxpZ2h0eWVsbG93XCI6IFsyNTUsIDI1NSwgMjI0XSxcclxuXHRcImxpbWVcIjogWzAsIDI1NSwgMF0sXHJcblx0XCJsaW1lZ3JlZW5cIjogWzUwLCAyMDUsIDUwXSxcclxuXHRcImxpbmVuXCI6IFsyNTAsIDI0MCwgMjMwXSxcclxuXHRcIm1hZ2VudGFcIjogWzI1NSwgMCwgMjU1XSxcclxuXHRcIm1hcm9vblwiOiBbMTI4LCAwLCAwXSxcclxuXHRcIm1lZGl1bWFxdWFtYXJpbmVcIjogWzEwMiwgMjA1LCAxNzBdLFxyXG5cdFwibWVkaXVtYmx1ZVwiOiBbMCwgMCwgMjA1XSxcclxuXHRcIm1lZGl1bW9yY2hpZFwiOiBbMTg2LCA4NSwgMjExXSxcclxuXHRcIm1lZGl1bXB1cnBsZVwiOiBbMTQ3LCAxMTIsIDIxOV0sXHJcblx0XCJtZWRpdW1zZWFncmVlblwiOiBbNjAsIDE3OSwgMTEzXSxcclxuXHRcIm1lZGl1bXNsYXRlYmx1ZVwiOiBbMTIzLCAxMDQsIDIzOF0sXHJcblx0XCJtZWRpdW1zcHJpbmdncmVlblwiOiBbMCwgMjUwLCAxNTRdLFxyXG5cdFwibWVkaXVtdHVycXVvaXNlXCI6IFs3MiwgMjA5LCAyMDRdLFxyXG5cdFwibWVkaXVtdmlvbGV0cmVkXCI6IFsxOTksIDIxLCAxMzNdLFxyXG5cdFwibWlkbmlnaHRibHVlXCI6IFsyNSwgMjUsIDExMl0sXHJcblx0XCJtaW50Y3JlYW1cIjogWzI0NSwgMjU1LCAyNTBdLFxyXG5cdFwibWlzdHlyb3NlXCI6IFsyNTUsIDIyOCwgMjI1XSxcclxuXHRcIm1vY2Nhc2luXCI6IFsyNTUsIDIyOCwgMTgxXSxcclxuXHRcIm5hdmFqb3doaXRlXCI6IFsyNTUsIDIyMiwgMTczXSxcclxuXHRcIm5hdnlcIjogWzAsIDAsIDEyOF0sXHJcblx0XCJvbGRsYWNlXCI6IFsyNTMsIDI0NSwgMjMwXSxcclxuXHRcIm9saXZlXCI6IFsxMjgsIDEyOCwgMF0sXHJcblx0XCJvbGl2ZWRyYWJcIjogWzEwNywgMTQyLCAzNV0sXHJcblx0XCJvcmFuZ2VcIjogWzI1NSwgMTY1LCAwXSxcclxuXHRcIm9yYW5nZXJlZFwiOiBbMjU1LCA2OSwgMF0sXHJcblx0XCJvcmNoaWRcIjogWzIxOCwgMTEyLCAyMTRdLFxyXG5cdFwicGFsZWdvbGRlbnJvZFwiOiBbMjM4LCAyMzIsIDE3MF0sXHJcblx0XCJwYWxlZ3JlZW5cIjogWzE1MiwgMjUxLCAxNTJdLFxyXG5cdFwicGFsZXR1cnF1b2lzZVwiOiBbMTc1LCAyMzgsIDIzOF0sXHJcblx0XCJwYWxldmlvbGV0cmVkXCI6IFsyMTksIDExMiwgMTQ3XSxcclxuXHRcInBhcGF5YXdoaXBcIjogWzI1NSwgMjM5LCAyMTNdLFxyXG5cdFwicGVhY2hwdWZmXCI6IFsyNTUsIDIxOCwgMTg1XSxcclxuXHRcInBlcnVcIjogWzIwNSwgMTMzLCA2M10sXHJcblx0XCJwaW5rXCI6IFsyNTUsIDE5MiwgMjAzXSxcclxuXHRcInBsdW1cIjogWzIyMSwgMTYwLCAyMjFdLFxyXG5cdFwicG93ZGVyYmx1ZVwiOiBbMTc2LCAyMjQsIDIzMF0sXHJcblx0XCJwdXJwbGVcIjogWzEyOCwgMCwgMTI4XSxcclxuXHRcInJlYmVjY2FwdXJwbGVcIjogWzEwMiwgNTEsIDE1M10sXHJcblx0XCJyZWRcIjogWzI1NSwgMCwgMF0sXHJcblx0XCJyb3N5YnJvd25cIjogWzE4OCwgMTQzLCAxNDNdLFxyXG5cdFwicm95YWxibHVlXCI6IFs2NSwgMTA1LCAyMjVdLFxyXG5cdFwic2FkZGxlYnJvd25cIjogWzEzOSwgNjksIDE5XSxcclxuXHRcInNhbG1vblwiOiBbMjUwLCAxMjgsIDExNF0sXHJcblx0XCJzYW5keWJyb3duXCI6IFsyNDQsIDE2NCwgOTZdLFxyXG5cdFwic2VhZ3JlZW5cIjogWzQ2LCAxMzksIDg3XSxcclxuXHRcInNlYXNoZWxsXCI6IFsyNTUsIDI0NSwgMjM4XSxcclxuXHRcInNpZW5uYVwiOiBbMTYwLCA4MiwgNDVdLFxyXG5cdFwic2lsdmVyXCI6IFsxOTIsIDE5MiwgMTkyXSxcclxuXHRcInNreWJsdWVcIjogWzEzNSwgMjA2LCAyMzVdLFxyXG5cdFwic2xhdGVibHVlXCI6IFsxMDYsIDkwLCAyMDVdLFxyXG5cdFwic2xhdGVncmF5XCI6IFsxMTIsIDEyOCwgMTQ0XSxcclxuXHRcInNsYXRlZ3JleVwiOiBbMTEyLCAxMjgsIDE0NF0sXHJcblx0XCJzbm93XCI6IFsyNTUsIDI1MCwgMjUwXSxcclxuXHRcInNwcmluZ2dyZWVuXCI6IFswLCAyNTUsIDEyN10sXHJcblx0XCJzdGVlbGJsdWVcIjogWzcwLCAxMzAsIDE4MF0sXHJcblx0XCJ0YW5cIjogWzIxMCwgMTgwLCAxNDBdLFxyXG5cdFwidGVhbFwiOiBbMCwgMTI4LCAxMjhdLFxyXG5cdFwidGhpc3RsZVwiOiBbMjE2LCAxOTEsIDIxNl0sXHJcblx0XCJ0b21hdG9cIjogWzI1NSwgOTksIDcxXSxcclxuXHRcInR1cnF1b2lzZVwiOiBbNjQsIDIyNCwgMjA4XSxcclxuXHRcInZpb2xldFwiOiBbMjM4LCAxMzAsIDIzOF0sXHJcblx0XCJ3aGVhdFwiOiBbMjQ1LCAyMjIsIDE3OV0sXHJcblx0XCJ3aGl0ZVwiOiBbMjU1LCAyNTUsIDI1NV0sXHJcblx0XCJ3aGl0ZXNtb2tlXCI6IFsyNDUsIDI0NSwgMjQ1XSxcclxuXHRcInllbGxvd1wiOiBbMjU1LCAyNTUsIDBdLFxyXG5cdFwieWVsbG93Z3JlZW5cIjogWzE1NCwgMjA1LCA1MF1cclxufTtcclxuXG59LHt9XSwxMjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqIEBtb2R1bGUgIGNvbG9yLW5vcm1hbGl6ZSAqL1xyXG5cclxuJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgcmdiYSA9IF9kZXJlcV8oJ2NvbG9yLXJnYmEnKVxyXG52YXIgY2xhbXAgPSBfZGVyZXFfKCdjbGFtcCcpXHJcbnZhciBkdHlwZSA9IF9kZXJlcV8oJ2R0eXBlJylcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbm9ybWFsaXplIChjb2xvciwgdHlwZSkge1xyXG5cdGlmICh0eXBlID09PSAnZmxvYXQnIHx8ICF0eXBlKSB0eXBlID0gJ2FycmF5J1xyXG5cdGlmICh0eXBlID09PSAndWludCcpIHR5cGUgPSAndWludDgnXHJcblx0aWYgKHR5cGUgPT09ICd1aW50X2NsYW1wZWQnKSB0eXBlID0gJ3VpbnQ4X2NsYW1wZWQnXHJcblx0dmFyIEN0b3IgPSBkdHlwZSh0eXBlKVxyXG5cdHZhciBvdXRwdXQgPSBuZXcgQ3Rvcig0KVxyXG5cclxuXHR2YXIgbm9ybWFsaXplID0gdHlwZSAhPT0gJ3VpbnQ4JyAmJiB0eXBlICE9PSAndWludDhfY2xhbXBlZCdcclxuXHJcblx0Ly8gYXR0ZW1wdCB0byBwYXJzZSBub24tYXJyYXkgYXJndW1lbnRzXHJcblx0aWYgKCFjb2xvci5sZW5ndGggfHwgdHlwZW9mIGNvbG9yID09PSAnc3RyaW5nJykge1xyXG5cdFx0Y29sb3IgPSByZ2JhKGNvbG9yKVxyXG5cdFx0Y29sb3JbMF0gLz0gMjU1XHJcblx0XHRjb2xvclsxXSAvPSAyNTVcclxuXHRcdGNvbG9yWzJdIC89IDI1NVxyXG5cdH1cclxuXHJcblx0Ly8gMCwgMSBhcmUgcG9zc2libGUgY29udHJhZGljdG9yeSB2YWx1ZXMgZm9yIEFycmF5czpcclxuXHQvLyBbMSwxLDFdIGlucHV0IGdpdmVzIFsxLDEsMV0gb3V0cHV0IGluc3RlYWQgb2YgWzEvMjU1LDEvMjU1LDEvMjU1XSwgd2hpY2ggbWF5IGJlIGNvbGxpc2lvbiBpZiBpbnB1dCBpcyBtZWFudCB0byBiZSB1aW50LlxyXG5cdC8vIGNvbnZlcnRpbmcgWzEsMSwxXSB0byBbMS8yNTUsMS8yNTUsMS8yNTVdIGluIGNhc2Ugb2YgZmxvYXQgaW5wdXQgZ2l2ZXMgbGFyZ2VyIG1pc3Rha2Ugc2luY2UgWzEsMSwxXSBmbG9hdCBpcyBmcmVxdWVudCBlZGdlIHZhbHVlLCB3aGVyZWFzIFswLDEsMV0sIFsxLDEsMV0gZXRjLiB1aW50IGlucHV0cyBhcmUgcmVsYXRpdmVseSByYXJlXHJcblx0aWYgKGlzSW50KGNvbG9yKSkge1xyXG5cdFx0b3V0cHV0WzBdID0gY29sb3JbMF1cclxuXHRcdG91dHB1dFsxXSA9IGNvbG9yWzFdXHJcblx0XHRvdXRwdXRbMl0gPSBjb2xvclsyXVxyXG5cdFx0b3V0cHV0WzNdID0gY29sb3JbM10gIT0gbnVsbCA/IGNvbG9yWzNdIDogMjU1XHJcblxyXG5cdFx0aWYgKG5vcm1hbGl6ZSkge1xyXG5cdFx0XHRvdXRwdXRbMF0gLz0gMjU1XHJcblx0XHRcdG91dHB1dFsxXSAvPSAyNTVcclxuXHRcdFx0b3V0cHV0WzJdIC89IDI1NVxyXG5cdFx0XHRvdXRwdXRbM10gLz0gMjU1XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIG91dHB1dFxyXG5cdH1cclxuXHJcblx0aWYgKCFub3JtYWxpemUpIHtcclxuXHRcdG91dHB1dFswXSA9IGNsYW1wKE1hdGguZmxvb3IoY29sb3JbMF0gKiAyNTUpLCAwLCAyNTUpXHJcblx0XHRvdXRwdXRbMV0gPSBjbGFtcChNYXRoLmZsb29yKGNvbG9yWzFdICogMjU1KSwgMCwgMjU1KVxyXG5cdFx0b3V0cHV0WzJdID0gY2xhbXAoTWF0aC5mbG9vcihjb2xvclsyXSAqIDI1NSksIDAsIDI1NSlcclxuXHRcdG91dHB1dFszXSA9IGNvbG9yWzNdID09IG51bGwgPyAyNTUgOiBjbGFtcChNYXRoLmZsb29yKGNvbG9yWzNdICogMjU1KSwgMCwgMjU1KVxyXG5cdH0gZWxzZSB7XHJcblx0XHRvdXRwdXRbMF0gPSBjb2xvclswXVxyXG5cdFx0b3V0cHV0WzFdID0gY29sb3JbMV1cclxuXHRcdG91dHB1dFsyXSA9IGNvbG9yWzJdXHJcblx0XHRvdXRwdXRbM10gPSBjb2xvclszXSAhPSBudWxsID8gY29sb3JbM10gOiAxXHJcblx0fVxyXG5cclxuXHRyZXR1cm4gb3V0cHV0XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGlzSW50KGNvbG9yKSB7XHJcblx0aWYgKGNvbG9yIGluc3RhbmNlb2YgVWludDhBcnJheSB8fCBjb2xvciBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5KSByZXR1cm4gdHJ1ZVxyXG5cclxuXHRpZiAoQXJyYXkuaXNBcnJheShjb2xvcikgJiZcclxuXHRcdChjb2xvclswXSA+IDEgfHwgY29sb3JbMF0gPT09IDApICYmXHJcblx0XHQoY29sb3JbMV0gPiAxIHx8IGNvbG9yWzFdID09PSAwKSAmJlxyXG5cdFx0KGNvbG9yWzJdID4gMSB8fCBjb2xvclsyXSA9PT0gMCkgJiZcclxuXHRcdCghY29sb3JbM10gfHwgY29sb3JbM10gPiAxKVxyXG5cdCkgcmV0dXJuIHRydWVcclxuXHJcblx0cmV0dXJuIGZhbHNlXHJcbn1cclxuXG59LHtcImNsYW1wXCI6MTE1LFwiY29sb3ItcmdiYVwiOjEyMixcImR0eXBlXCI6MTY5fV0sMTIxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbihmdW5jdGlvbiAoZ2xvYmFsKXtcbi8qKlxuICogQG1vZHVsZSBjb2xvci1wYXJzZVxuICovXG5cbid1c2Ugc3RyaWN0J1xuXG52YXIgbmFtZXMgPSBfZGVyZXFfKCdjb2xvci1uYW1lJylcbnZhciBpc09iamVjdCA9IF9kZXJlcV8oJ2lzLXBsYWluLW9iaicpXG52YXIgZGVmaW5lZCA9IF9kZXJlcV8oJ2RlZmluZWQnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHBhcnNlXG5cbi8qKlxuICogQmFzZSBodWVzXG4gKiBodHRwOi8vZGV2LnczLm9yZy9jc3N3Zy9jc3MtY29sb3IvI3R5cGVkZWYtbmFtZWQtaHVlXG4gKi9cbi8vRklYTUU6IHVzZSBleHRlcm5hbCBodWUgZGV0ZWN0b3JcbnZhciBiYXNlSHVlcyA9IHtcblx0cmVkOiAwLFxuXHRvcmFuZ2U6IDYwLFxuXHR5ZWxsb3c6IDEyMCxcblx0Z3JlZW46IDE4MCxcblx0Ymx1ZTogMjQwLFxuXHRwdXJwbGU6IDMwMFxufVxuXG4vKipcbiAqIFBhcnNlIGNvbG9yIGZyb20gdGhlIHN0cmluZyBwYXNzZWRcbiAqXG4gKiBAcmV0dXJuIHtPYmplY3R9IEEgc3BhY2UgaW5kaWNhdG9yIGBzcGFjZWAsIGFuIGFycmF5IGB2YWx1ZXNgIGFuZCBgYWxwaGFgXG4gKi9cbmZ1bmN0aW9uIHBhcnNlIChjc3RyKSB7XG5cdHZhciBtLCBwYXJ0cyA9IFtdLCBhbHBoYSA9IDEsIHNwYWNlXG5cblx0aWYgKHR5cGVvZiBjc3RyID09PSAnc3RyaW5nJykge1xuXHRcdC8va2V5d29yZFxuXHRcdGlmIChuYW1lc1tjc3RyXSkge1xuXHRcdFx0cGFydHMgPSBuYW1lc1tjc3RyXS5zbGljZSgpXG5cdFx0XHRzcGFjZSA9ICdyZ2InXG5cdFx0fVxuXG5cdFx0Ly9yZXNlcnZlZCB3b3Jkc1xuXHRcdGVsc2UgaWYgKGNzdHIgPT09ICd0cmFuc3BhcmVudCcpIHtcblx0XHRcdGFscGhhID0gMFxuXHRcdFx0c3BhY2UgPSAncmdiJ1xuXHRcdFx0cGFydHMgPSBbMCwwLDBdXG5cdFx0fVxuXG5cdFx0Ly9oZXhcblx0XHRlbHNlIGlmICgvXiNbQS1GYS1mMC05XSskLy50ZXN0KGNzdHIpKSB7XG5cdFx0XHR2YXIgYmFzZSA9IGNzdHIuc2xpY2UoMSlcblx0XHRcdHZhciBzaXplID0gYmFzZS5sZW5ndGhcblx0XHRcdHZhciBpc1Nob3J0ID0gc2l6ZSA8PSA0XG5cdFx0XHRhbHBoYSA9IDFcblxuXHRcdFx0aWYgKGlzU2hvcnQpIHtcblx0XHRcdFx0cGFydHMgPSBbXG5cdFx0XHRcdFx0cGFyc2VJbnQoYmFzZVswXSArIGJhc2VbMF0sIDE2KSxcblx0XHRcdFx0XHRwYXJzZUludChiYXNlWzFdICsgYmFzZVsxXSwgMTYpLFxuXHRcdFx0XHRcdHBhcnNlSW50KGJhc2VbMl0gKyBiYXNlWzJdLCAxNilcblx0XHRcdFx0XVxuXHRcdFx0XHRpZiAoc2l6ZSA9PT0gNCkge1xuXHRcdFx0XHRcdGFscGhhID0gcGFyc2VJbnQoYmFzZVszXSArIGJhc2VbM10sIDE2KSAvIDI1NVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0cGFydHMgPSBbXG5cdFx0XHRcdFx0cGFyc2VJbnQoYmFzZVswXSArIGJhc2VbMV0sIDE2KSxcblx0XHRcdFx0XHRwYXJzZUludChiYXNlWzJdICsgYmFzZVszXSwgMTYpLFxuXHRcdFx0XHRcdHBhcnNlSW50KGJhc2VbNF0gKyBiYXNlWzVdLCAxNilcblx0XHRcdFx0XVxuXHRcdFx0XHRpZiAoc2l6ZSA9PT0gOCkge1xuXHRcdFx0XHRcdGFscGhhID0gcGFyc2VJbnQoYmFzZVs2XSArIGJhc2VbN10sIDE2KSAvIDI1NVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICghcGFydHNbMF0pIHBhcnRzWzBdID0gMFxuXHRcdFx0aWYgKCFwYXJ0c1sxXSkgcGFydHNbMV0gPSAwXG5cdFx0XHRpZiAoIXBhcnRzWzJdKSBwYXJ0c1syXSA9IDBcblxuXHRcdFx0c3BhY2UgPSAncmdiJ1xuXHRcdH1cblxuXHRcdC8vY29sb3Igc3BhY2Vcblx0XHRlbHNlIGlmIChtID0gL14oKD86cmdifGhzW2x2Yl18aHdifGNteWs/fHh5W3p5XXxncmF5fGxhYnxsY2h1P3Y/fFtseV11dnxsbXMpYT8pXFxzKlxcKChbXlxcKV0qKVxcKS8uZXhlYyhjc3RyKSkge1xuXHRcdFx0dmFyIG5hbWUgPSBtWzFdXG5cdFx0XHR2YXIgaXNSR0IgPSBuYW1lID09PSAncmdiJ1xuXHRcdFx0dmFyIGJhc2UgPSBuYW1lLnJlcGxhY2UoL2EkLywgJycpXG5cdFx0XHRzcGFjZSA9IGJhc2Vcblx0XHRcdHZhciBzaXplID0gYmFzZSA9PT0gJ2NteWsnID8gNCA6IGJhc2UgPT09ICdncmF5JyA/IDEgOiAzXG5cdFx0XHRwYXJ0cyA9IG1bMl0udHJpbSgpXG5cdFx0XHRcdC5zcGxpdCgvXFxzKixcXHMqLylcblx0XHRcdFx0Lm1hcChmdW5jdGlvbiAoeCwgaSkge1xuXHRcdFx0XHRcdC8vPHBlcmNlbnRhZ2U+XG5cdFx0XHRcdFx0aWYgKC8lJC8udGVzdCh4KSkge1xuXHRcdFx0XHRcdFx0Ly9hbHBoYVxuXHRcdFx0XHRcdFx0aWYgKGkgPT09IHNpemUpXHRyZXR1cm4gcGFyc2VGbG9hdCh4KSAvIDEwMFxuXHRcdFx0XHRcdFx0Ly9yZ2Jcblx0XHRcdFx0XHRcdGlmIChiYXNlID09PSAncmdiJykgcmV0dXJuIHBhcnNlRmxvYXQoeCkgKiAyNTUgLyAxMDBcblx0XHRcdFx0XHRcdHJldHVybiBwYXJzZUZsb2F0KHgpXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdC8vaHVlXG5cdFx0XHRcdFx0ZWxzZSBpZiAoYmFzZVtpXSA9PT0gJ2gnKSB7XG5cdFx0XHRcdFx0XHQvLzxkZWc+XG5cdFx0XHRcdFx0XHRpZiAoL2RlZyQvLnRlc3QoeCkpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHBhcnNlRmxvYXQoeClcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdC8vPGJhc2UtaHVlPlxuXHRcdFx0XHRcdFx0ZWxzZSBpZiAoYmFzZUh1ZXNbeF0gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gYmFzZUh1ZXNbeF1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHBhcnNlRmxvYXQoeClcblx0XHRcdFx0fSlcblxuXHRcdFx0aWYgKG5hbWUgPT09IGJhc2UpIHBhcnRzLnB1c2goMSlcblx0XHRcdGFscGhhID0gKGlzUkdCKSA/IDEgOiAocGFydHNbc2l6ZV0gPT09IHVuZGVmaW5lZCkgPyAxIDogcGFydHNbc2l6ZV1cblx0XHRcdHBhcnRzID0gcGFydHMuc2xpY2UoMCwgc2l6ZSlcblx0XHR9XG5cblx0XHQvL25hbWVkIGNoYW5uZWxzIGNhc2Vcblx0XHRlbHNlIGlmIChjc3RyLmxlbmd0aCA+IDEwICYmIC9bMC05XSg/Olxcc3xcXC8pLy50ZXN0KGNzdHIpKSB7XG5cdFx0XHRwYXJ0cyA9IGNzdHIubWF0Y2goLyhbMC05XSspL2cpLm1hcChmdW5jdGlvbiAodmFsdWUpIHtcblx0XHRcdFx0cmV0dXJuIHBhcnNlRmxvYXQodmFsdWUpXG5cdFx0XHR9KVxuXG5cdFx0XHRzcGFjZSA9IGNzdHIubWF0Y2goLyhbYS16XSkvaWcpLmpvaW4oJycpLnRvTG93ZXJDYXNlKClcblx0XHR9XG5cdH1cblxuXHQvL251bWVyaWMgY2FzZVxuXHRlbHNlIGlmICghaXNOYU4oY3N0cikpIHtcblx0XHRzcGFjZSA9ICdyZ2InXG5cdFx0cGFydHMgPSBbY3N0ciA+Pj4gMTYsIChjc3RyICYgMHgwMGZmMDApID4+PiA4LCBjc3RyICYgMHgwMDAwZmZdXG5cdH1cblxuXHQvL29iamVjdCBjYXNlIC0gZGV0ZWN0cyBjc3MgY2FzZXMgb2YgcmdiIGFuZCBoc2xcblx0ZWxzZSBpZiAoaXNPYmplY3QoY3N0cikpIHtcblx0XHR2YXIgciA9IGRlZmluZWQoY3N0ci5yLCBjc3RyLnJlZCwgY3N0ci5SLCBudWxsKVxuXG5cdFx0aWYgKHIgIT09IG51bGwpIHtcblx0XHRcdHNwYWNlID0gJ3JnYidcblx0XHRcdHBhcnRzID0gW1xuXHRcdFx0XHRyLFxuXHRcdFx0XHRkZWZpbmVkKGNzdHIuZywgY3N0ci5ncmVlbiwgY3N0ci5HKSxcblx0XHRcdFx0ZGVmaW5lZChjc3RyLmIsIGNzdHIuYmx1ZSwgY3N0ci5CKVxuXHRcdFx0XVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHNwYWNlID0gJ2hzbCdcblx0XHRcdHBhcnRzID0gW1xuXHRcdFx0XHRkZWZpbmVkKGNzdHIuaCwgY3N0ci5odWUsIGNzdHIuSCksXG5cdFx0XHRcdGRlZmluZWQoY3N0ci5zLCBjc3RyLnNhdHVyYXRpb24sIGNzdHIuUyksXG5cdFx0XHRcdGRlZmluZWQoY3N0ci5sLCBjc3RyLmxpZ2h0bmVzcywgY3N0ci5MLCBjc3RyLmIsIGNzdHIuYnJpZ2h0bmVzcylcblx0XHRcdF1cblx0XHR9XG5cblx0XHRhbHBoYSA9IGRlZmluZWQoY3N0ci5hLCBjc3RyLmFscGhhLCBjc3RyLm9wYWNpdHksIDEpXG5cblx0XHRpZiAoY3N0ci5vcGFjaXR5ICE9IG51bGwpIGFscGhhIC89IDEwMFxuXHR9XG5cblx0Ly9hcnJheVxuXHRlbHNlIGlmIChBcnJheS5pc0FycmF5KGNzdHIpIHx8IGdsb2JhbC5BcnJheUJ1ZmZlciAmJiBBcnJheUJ1ZmZlci5pc1ZpZXcgJiYgQXJyYXlCdWZmZXIuaXNWaWV3KGNzdHIpKSB7XG5cdFx0cGFydHMgPSBbY3N0clswXSwgY3N0clsxXSwgY3N0clsyXV1cblx0XHRzcGFjZSA9ICdyZ2InXG5cdFx0YWxwaGEgPSBjc3RyLmxlbmd0aCA9PT0gNCA/IGNzdHJbM10gOiAxXG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdHNwYWNlOiBzcGFjZSxcblx0XHR2YWx1ZXM6IHBhcnRzLFxuXHRcdGFscGhhOiBhbHBoYVxuXHR9XG59XG5cbn0pLmNhbGwodGhpcyx0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KVxufSx7XCJjb2xvci1uYW1lXCI6MTE5LFwiZGVmaW5lZFwiOjE2NCxcImlzLXBsYWluLW9ialwiOjQyMn1dLDEyMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKiogQG1vZHVsZSAgY29sb3ItcmdiYSAqL1xuXG4ndXNlIHN0cmljdCdcblxudmFyIHBhcnNlID0gX2RlcmVxXygnY29sb3ItcGFyc2UnKVxudmFyIGhzbCA9IF9kZXJlcV8oJ2NvbG9yLXNwYWNlL2hzbCcpXG52YXIgY2xhbXAgPSBfZGVyZXFfKCdjbGFtcCcpXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcmdiYSAoY29sb3IpIHtcblx0dmFyIHZhbHVlcywgaSwgbFxuXG5cdC8vYXR0ZW1wdCB0byBwYXJzZSBub24tYXJyYXkgYXJndW1lbnRzXG5cdHZhciBwYXJzZWQgPSBwYXJzZShjb2xvcilcblxuXHRpZiAoIXBhcnNlZC5zcGFjZSkgcmV0dXJuIFtdXG5cblx0dmFsdWVzID0gQXJyYXkoMylcblx0dmFsdWVzWzBdID0gY2xhbXAocGFyc2VkLnZhbHVlc1swXSwgMCwgMjU1KVxuXHR2YWx1ZXNbMV0gPSBjbGFtcChwYXJzZWQudmFsdWVzWzFdLCAwLCAyNTUpXG5cdHZhbHVlc1syXSA9IGNsYW1wKHBhcnNlZC52YWx1ZXNbMl0sIDAsIDI1NSlcblxuXHRpZiAocGFyc2VkLnNwYWNlWzBdID09PSAnaCcpIHtcblx0XHR2YWx1ZXMgPSBoc2wucmdiKHZhbHVlcylcblx0fVxuXG5cdHZhbHVlcy5wdXNoKGNsYW1wKHBhcnNlZC5hbHBoYSwgMCwgMSkpXG5cblx0cmV0dXJuIHZhbHVlc1xufVxuXG59LHtcImNsYW1wXCI6MTE1LFwiY29sb3ItcGFyc2VcIjoxMjEsXCJjb2xvci1zcGFjZS9oc2xcIjoxMjN9XSwxMjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4gKiBAbW9kdWxlIGNvbG9yLXNwYWNlL2hzbFxuICovXG4ndXNlIHN0cmljdCdcblxudmFyIHJnYiA9IF9kZXJlcV8oJy4vcmdiJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRuYW1lOiAnaHNsJyxcblx0bWluOiBbMCwwLDBdLFxuXHRtYXg6IFszNjAsMTAwLDEwMF0sXG5cdGNoYW5uZWw6IFsnaHVlJywgJ3NhdHVyYXRpb24nLCAnbGlnaHRuZXNzJ10sXG5cdGFsaWFzOiBbJ0hTTCddLFxuXG5cdHJnYjogZnVuY3Rpb24oaHNsKSB7XG5cdFx0dmFyIGggPSBoc2xbMF0gLyAzNjAsXG5cdFx0XHRcdHMgPSBoc2xbMV0gLyAxMDAsXG5cdFx0XHRcdGwgPSBoc2xbMl0gLyAxMDAsXG5cdFx0XHRcdHQxLCB0MiwgdDMsIHJnYiwgdmFsO1xuXG5cdFx0aWYgKHMgPT09IDApIHtcblx0XHRcdHZhbCA9IGwgKiAyNTU7XG5cdFx0XHRyZXR1cm4gW3ZhbCwgdmFsLCB2YWxdO1xuXHRcdH1cblxuXHRcdGlmIChsIDwgMC41KSB7XG5cdFx0XHR0MiA9IGwgKiAoMSArIHMpO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHQyID0gbCArIHMgLSBsICogcztcblx0XHR9XG5cdFx0dDEgPSAyICogbCAtIHQyO1xuXG5cdFx0cmdiID0gWzAsIDAsIDBdO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgMzsgaSsrKSB7XG5cdFx0XHR0MyA9IGggKyAxIC8gMyAqIC0gKGkgLSAxKTtcblx0XHRcdGlmICh0MyA8IDApIHtcblx0XHRcdFx0dDMrKztcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKHQzID4gMSkge1xuXHRcdFx0XHR0My0tO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoNiAqIHQzIDwgMSkge1xuXHRcdFx0XHR2YWwgPSB0MSArICh0MiAtIHQxKSAqIDYgKiB0Mztcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKDIgKiB0MyA8IDEpIHtcblx0XHRcdFx0dmFsID0gdDI7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICgzICogdDMgPCAyKSB7XG5cdFx0XHRcdHZhbCA9IHQxICsgKHQyIC0gdDEpICogKDIgLyAzIC0gdDMpICogNjtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHR2YWwgPSB0MTtcblx0XHRcdH1cblxuXHRcdFx0cmdiW2ldID0gdmFsICogMjU1O1xuXHRcdH1cblxuXHRcdHJldHVybiByZ2I7XG5cdH1cbn07XG5cblxuLy9leHRlbmQgcmdiXG5yZ2IuaHNsID0gZnVuY3Rpb24ocmdiKSB7XG5cdHZhciByID0gcmdiWzBdLzI1NSxcblx0XHRcdGcgPSByZ2JbMV0vMjU1LFxuXHRcdFx0YiA9IHJnYlsyXS8yNTUsXG5cdFx0XHRtaW4gPSBNYXRoLm1pbihyLCBnLCBiKSxcblx0XHRcdG1heCA9IE1hdGgubWF4KHIsIGcsIGIpLFxuXHRcdFx0ZGVsdGEgPSBtYXggLSBtaW4sXG5cdFx0XHRoLCBzLCBsO1xuXG5cdGlmIChtYXggPT09IG1pbikge1xuXHRcdGggPSAwO1xuXHR9XG5cdGVsc2UgaWYgKHIgPT09IG1heCkge1xuXHRcdGggPSAoZyAtIGIpIC8gZGVsdGE7XG5cdH1cblx0ZWxzZSBpZiAoZyA9PT0gbWF4KSB7XG5cdFx0aCA9IDIgKyAoYiAtIHIpIC8gZGVsdGE7XG5cdH1cblx0ZWxzZSBpZiAoYiA9PT0gbWF4KSB7XG5cdFx0aCA9IDQgKyAociAtIGcpLyBkZWx0YTtcblx0fVxuXG5cdGggPSBNYXRoLm1pbihoICogNjAsIDM2MCk7XG5cblx0aWYgKGggPCAwKSB7XG5cdFx0aCArPSAzNjA7XG5cdH1cblxuXHRsID0gKG1pbiArIG1heCkgLyAyO1xuXG5cdGlmIChtYXggPT09IG1pbikge1xuXHRcdHMgPSAwO1xuXHR9XG5cdGVsc2UgaWYgKGwgPD0gMC41KSB7XG5cdFx0cyA9IGRlbHRhIC8gKG1heCArIG1pbik7XG5cdH1cblx0ZWxzZSB7XG5cdFx0cyA9IGRlbHRhIC8gKDIgLSBtYXggLSBtaW4pO1xuXHR9XG5cblx0cmV0dXJuIFtoLCBzICogMTAwLCBsICogMTAwXTtcbn07XG5cbn0se1wiLi9yZ2JcIjoxMjR9XSwxMjQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4gKiBSR0Igc3BhY2UuXG4gKlxuICogQG1vZHVsZSAgY29sb3Itc3BhY2UvcmdiXG4gKi9cbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0bmFtZTogJ3JnYicsXG5cdG1pbjogWzAsMCwwXSxcblx0bWF4OiBbMjU1LDI1NSwyNTVdLFxuXHRjaGFubmVsOiBbJ3JlZCcsICdncmVlbicsICdibHVlJ10sXG5cdGFsaWFzOiBbJ1JHQiddXG59O1xuXG59LHt9XSwxMjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHM9e1xuXHRcImpldFwiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMCwwLDEzMV19LHtcImluZGV4XCI6MC4xMjUsXCJyZ2JcIjpbMCw2MCwxNzBdfSx7XCJpbmRleFwiOjAuMzc1LFwicmdiXCI6WzUsMjU1LDI1NV19LHtcImluZGV4XCI6MC42MjUsXCJyZ2JcIjpbMjU1LDI1NSwwXX0se1wiaW5kZXhcIjowLjg3NSxcInJnYlwiOlsyNTAsMCwwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzEyOCwwLDBdfV0sXG5cblx0XCJoc3ZcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzI1NSwwLDBdfSx7XCJpbmRleFwiOjAuMTY5LFwicmdiXCI6WzI1MywyNTUsMl19LHtcImluZGV4XCI6MC4xNzMsXCJyZ2JcIjpbMjQ3LDI1NSwyXX0se1wiaW5kZXhcIjowLjMzNyxcInJnYlwiOlswLDI1Miw0XX0se1wiaW5kZXhcIjowLjM0MSxcInJnYlwiOlswLDI1MiwxMF19LHtcImluZGV4XCI6MC41MDYsXCJyZ2JcIjpbMSwyNDksMjU1XX0se1wiaW5kZXhcIjowLjY3MSxcInJnYlwiOlsyLDAsMjUzXX0se1wiaW5kZXhcIjowLjY3NSxcInJnYlwiOls4LDAsMjUzXX0se1wiaW5kZXhcIjowLjgzOSxcInJnYlwiOlsyNTUsMCwyNTFdfSx7XCJpbmRleFwiOjAuODQzLFwicmdiXCI6WzI1NSwwLDI0NV19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMCw2XX1dLFxuXG5cdFwiaG90XCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMF19LHtcImluZGV4XCI6MC4zLFwicmdiXCI6WzIzMCwwLDBdfSx7XCJpbmRleFwiOjAuNixcInJnYlwiOlsyNTUsMjEwLDBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1NSwyNTVdfV0sXG5cblx0XCJjb29sXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDI1NSwyNTVdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDAsMjU1XX1dLFxuXG5cdFwic3ByaW5nXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlsyNTUsMCwyNTVdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1NSwwXX1dLFxuXG5cdFwic3VtbWVyXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDEyOCwxMDJdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1NSwxMDJdfV0sXG5cblx0XCJhdXR1bW5cIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzI1NSwwLDBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1NSwwXX1dLFxuXG5cdFwid2ludGVyXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMjU1XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzAsMjU1LDEyOF19XSxcblxuXHRcImJvbmVcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsMCwwXX0se1wiaW5kZXhcIjowLjM3NixcInJnYlwiOls4NCw4NCwxMTZdfSx7XCJpbmRleFwiOjAuNzUzLFwicmdiXCI6WzE2OSwyMDAsMjAwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1NSwyNTUsMjU1XX1dLFxuXG5cdFwiY29wcGVyXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMF19LHtcImluZGV4XCI6MC44MDQsXCJyZ2JcIjpbMjU1LDE2MCwxMDJdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDE5OSwxMjddfV0sXG5cblx0XCJncmV5c1wiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMCwwLDBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1NSwyNTVdfV0sXG5cblx0XCJ5aWduYnVcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzgsMjksODhdfSx7XCJpbmRleFwiOjAuMTI1LFwicmdiXCI6WzM3LDUyLDE0OF19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOlszNCw5NCwxNjhdfSx7XCJpbmRleFwiOjAuMzc1LFwicmdiXCI6WzI5LDE0NSwxOTJdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOls2NSwxODIsMTk2XX0se1wiaW5kZXhcIjowLjYyNSxcInJnYlwiOlsxMjcsMjA1LDE4N119LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsxOTksMjMzLDE4MF19LHtcImluZGV4XCI6MC44NzUsXCJyZ2JcIjpbMjM3LDI0OCwyMTddfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1NSwyMTddfV0sXG5cblx0XCJncmVlbnNcIjpbe1wiaW5kZXhcIjowLFwicmdiXCI6WzAsNjgsMjddfSx7XCJpbmRleFwiOjAuMTI1LFwicmdiXCI6WzAsMTA5LDQ0XX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzM1LDEzOSw2OV19LHtcImluZGV4XCI6MC4zNzUsXCJyZ2JcIjpbNjUsMTcxLDkzXX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMTE2LDE5NiwxMThdfSx7XCJpbmRleFwiOjAuNjI1LFwicmdiXCI6WzE2MSwyMTcsMTU1XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzE5OSwyMzMsMTkyXX0se1wiaW5kZXhcIjowLjg3NSxcInJnYlwiOlsyMjksMjQ1LDIyNF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNDcsMjUyLDI0NV19XSxcblxuXHRcInlpb3JyZFwiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMTI4LDAsMzhdfSx7XCJpbmRleFwiOjAuMTI1LFwicmdiXCI6WzE4OSwwLDM4XX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzIyNywyNiwyOF19LHtcImluZGV4XCI6MC4zNzUsXCJyZ2JcIjpbMjUyLDc4LDQyXX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMjUzLDE0MSw2MF19LHtcImluZGV4XCI6MC42MjUsXCJyZ2JcIjpbMjU0LDE3OCw3Nl19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsyNTQsMjE3LDExOF19LHtcImluZGV4XCI6MC44NzUsXCJyZ2JcIjpbMjU1LDIzNywxNjBdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1NSwyMDRdfV0sXG5cblx0XCJibHVlcmVkXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMjU1XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1NSwwLDBdfV0sXG5cblx0XCJyZGJ1XCI6W3tcImluZGV4XCI6MCxcInJnYlwiOls1LDEwLDE3Ml19LHtcImluZGV4XCI6MC4zNSxcInJnYlwiOlsxMDYsMTM3LDI0N119LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzE5MCwxOTAsMTkwXX0se1wiaW5kZXhcIjowLjYsXCJyZ2JcIjpbMjIwLDE3MCwxMzJdfSx7XCJpbmRleFwiOjAuNyxcInJnYlwiOlsyMzAsMTQ1LDkwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzE3OCwxMCwyOF19XSxcblxuXHRcInBpY25pY1wiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMCwwLDI1NV19LHtcImluZGV4XCI6MC4xLFwicmdiXCI6WzUxLDE1MywyNTVdfSx7XCJpbmRleFwiOjAuMixcInJnYlwiOlsxMDIsMjA0LDI1NV19LHtcImluZGV4XCI6MC4zLFwicmdiXCI6WzE1MywyMDQsMjU1XX0se1wiaW5kZXhcIjowLjQsXCJyZ2JcIjpbMjA0LDIwNCwyNTVdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsyNTUsMjU1LDI1NV19LHtcImluZGV4XCI6MC42LFwicmdiXCI6WzI1NSwyMDQsMjU1XX0se1wiaW5kZXhcIjowLjcsXCJyZ2JcIjpbMjU1LDE1MywyNTVdfSx7XCJpbmRleFwiOjAuOCxcInJnYlwiOlsyNTUsMTAyLDIwNF19LHtcImluZGV4XCI6MC45LFwicmdiXCI6WzI1NSwxMDIsMTAyXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1NSwwLDBdfV0sXG5cblx0XCJyYWluYm93XCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlsxNTAsMCw5MF19LHtcImluZGV4XCI6MC4xMjUsXCJyZ2JcIjpbMCwwLDIwMF19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOlswLDI1LDI1NV19LHtcImluZGV4XCI6MC4zNzUsXCJyZ2JcIjpbMCwxNTIsMjU1XX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbNDQsMjU1LDE1MF19LHtcImluZGV4XCI6MC42MjUsXCJyZ2JcIjpbMTUxLDI1NSwwXX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzI1NSwyMzQsMF19LHtcImluZGV4XCI6MC44NzUsXCJyZ2JcIjpbMjU1LDExMSwwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1NSwwLDBdfV0sXG5cblx0XCJwb3J0bGFuZFwiOlt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMTIsNTEsMTMxXX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzEwLDEzNiwxODZdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsyNDIsMjExLDU2XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzI0MiwxNDMsNTZdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjE3LDMwLDMwXX1dLFxuXG5cdFwiYmxhY2tib2R5XCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMF19LHtcImluZGV4XCI6MC4yLFwicmdiXCI6WzIzMCwwLDBdfSx7XCJpbmRleFwiOjAuNCxcInJnYlwiOlsyMzAsMjEwLDBdfSx7XCJpbmRleFwiOjAuNyxcInJnYlwiOlsyNTUsMjU1LDI1NV19LHtcImluZGV4XCI6MSxcInJnYlwiOlsxNjAsMjAwLDI1NV19XSxcblxuXHRcImVhcnRoXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMTMwXX0se1wiaW5kZXhcIjowLjEsXCJyZ2JcIjpbMCwxODAsMTgwXX0se1wiaW5kZXhcIjowLjIsXCJyZ2JcIjpbNDAsMjEwLDQwXX0se1wiaW5kZXhcIjowLjQsXCJyZ2JcIjpbMjMwLDIzMCw1MF19LHtcImluZGV4XCI6MC42LFwicmdiXCI6WzEyMCw3MCwyMF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTUsMjU1LDI1NV19XSxcblxuXHRcImVsZWN0cmljXCI6W3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMF19LHtcImluZGV4XCI6MC4xNSxcInJnYlwiOlszMCwwLDEwMF19LHtcImluZGV4XCI6MC40LFwicmdiXCI6WzEyMCwwLDEwMF19LHtcImluZGV4XCI6MC42LFwicmdiXCI6WzE2MCw5MCwwXX0se1wiaW5kZXhcIjowLjgsXCJyZ2JcIjpbMjMwLDIwMCwwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1NSwyNTAsMjIwXX1dLFxuXG5cdFwiYWxwaGFcIjogW3tcImluZGV4XCI6MCwgXCJyZ2JcIjogWzI1NSwyNTUsMjU1LDBdfSx7XCJpbmRleFwiOjEsIFwicmdiXCI6IFsyNTUsMjU1LDI1NSwxXX1dLFxuXG5cdFwidmlyaWRpc1wiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzY4LDEsODRdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbNzEsNDQsMTIyXX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzU5LDgxLDEzOV19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOls0NCwxMTMsMTQyXX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMzMsMTQ0LDE0MV19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlszOSwxNzMsMTI5XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzkyLDIwMCw5OV19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsxNzAsMjIwLDUwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1MywyMzEsMzddfV0sXG5cblx0XCJpbmZlcm5vXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMCwwLDRdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbMzEsMTIsNzJdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbODUsMTUsMTA5XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzEzNiwzNCwxMDZdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsxODYsNTQsODVdfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbMjI3LDg5LDUxXX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzI0OSwxNDAsMTBdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMjQ5LDIwMSw1MF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTIsMjU1LDE2NF19XSxcblxuXHRcIm1hZ21hXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMCwwLDRdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbMjgsMTYsNjhdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbNzksMTgsMTIzXX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzEyOSwzNywxMjldfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsxODEsNTQsMTIyXX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzIyOSw4MCwxMDBdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjUxLDEzNSw5N119LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyNTQsMTk0LDEzNV19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNTIsMjUzLDE5MV19XSxcblxuXHRcInBsYXNtYVwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzEzLDgsMTM1XX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6Wzc1LDMsMTYxXX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzEyNSwzLDE2OF19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsxNjgsMzQsMTUwXX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMjAzLDcwLDEyMV19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlsyMjksMTA3LDkzXX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzI0OCwxNDgsNjVdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMjUzLDE5NSw0MF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNDAsMjQ5LDMzXX1dLFxuXG5cdFwid2FybVwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzEyNSwwLDE3OV19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOlsxNzIsMCwxODddfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMjE5LDAsMTcwXX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzI1NSwwLDEzMF19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzI1NSw2Myw3NF19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlsyNTUsMTIzLDBdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjM0LDE3NiwwXX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzE5MCwyMjgsMF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsxNDcsMjU1LDBdfV0sXG5cblx0XCJjb29sXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMTI1LDAsMTc5XX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzExNiwwLDIxOF19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOls5OCw3NCwyMzddfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbNjgsMTQ2LDIzMV19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzAsMjA0LDE5N119LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlswLDI0NywxNDZdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMCwyNTUsODhdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbNDAsMjU1LDhdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMTQ3LDI1NSwwXX1dLFxuXG5cdFwicmFpbmJvdy1zb2Z0XCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbMTI1LDAsMTc5XX0se1wiaW5kZXhcIjowLjEsXCJyZ2JcIjpbMTk5LDAsMTgwXX0se1wiaW5kZXhcIjowLjIsXCJyZ2JcIjpbMjU1LDAsMTIxXX0se1wiaW5kZXhcIjowLjMsXCJyZ2JcIjpbMjU1LDEwOCwwXX0se1wiaW5kZXhcIjowLjQsXCJyZ2JcIjpbMjIyLDE5NCwwXX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMTUwLDI1NSwwXX0se1wiaW5kZXhcIjowLjYsXCJyZ2JcIjpbMCwyNTUsNTVdfSx7XCJpbmRleFwiOjAuNyxcInJnYlwiOlswLDI0NiwxNTBdfSx7XCJpbmRleFwiOjAuOCxcInJnYlwiOls1MCwxNjcsMjIyXX0se1wiaW5kZXhcIjowLjksXCJyZ2JcIjpbMTAzLDUxLDIzNV19LHtcImluZGV4XCI6MSxcInJnYlwiOlsxMjQsMCwxODZdfV0sXG5cblx0XCJiYXRoeW1ldHJ5XCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbNDAsMjYsNDRdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbNTksNDksOTBdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbNjQsNzYsMTM5XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzYzLDExMCwxNTFdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOls3MiwxNDIsMTU4XX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6Wzg1LDE3NCwxNjNdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMTIwLDIwNiwxNjNdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMTg3LDIzMCwxNzJdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjUzLDI1NCwyMDRdfV0sXG5cblx0XCJjZG9tXCI6IFt7XCJpbmRleFwiOjAsXCJyZ2JcIjpbNDcsMTUsNjJdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbODcsMjMsODZdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMTMwLDI4LDk5XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzE3MSw0MSw5Nl19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzIwNiw2Nyw4Nl19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlsyMzAsMTA2LDg0XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzI0MiwxNDksMTAzXX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzI0OSwxOTMsMTM1XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1NCwyMzcsMTc2XX1dLFxuXG5cdFwiY2hsb3JvcGh5bGxcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOlsxOCwzNiwyMF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOlsyNSw2Myw0MV19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOlsyNCw5MSw1OV19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsxMywxMTksNzJdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsxOCwxNDgsODBdfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbODAsMTczLDg5XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzEzMiwxOTYsMTIyXX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzE3NSwyMjEsMTYyXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzIxNSwyNDksMjA4XX1dLFxuXG5cdFwiZGVuc2l0eVwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzU0LDE0LDM2XX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6Wzg5LDIzLDgwXX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzExMCw0NSwxMzJdfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMTIwLDc3LDE3OF19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzEyMCwxMTMsMjEzXX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzExNSwxNTEsMjI4XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzEzNCwxODUsMjI3XX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzE3NywyMTQsMjI3XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzIzMCwyNDEsMjQxXX1dLFxuXG5cdFwiZnJlZXN1cmZhY2UtYmx1ZVwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzMwLDQsMTEwXX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzQ3LDE0LDE3Nl19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOls0MSw0NSwyMzZdfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMjUsOTksMjEyXX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbNjgsMTMxLDIwMF19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlsxMTQsMTU2LDE5N119LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsxNTcsMTgxLDIwM119LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyMDAsMjA4LDIxNl19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyNDEsMjM3LDIzNl19XSxcblxuXHRcImZyZWVzdXJmYWNlLXJlZFwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzYwLDksMThdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbMTAwLDE3LDI3XX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzE0MiwyMCwyOV19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsxNzcsNDMsMjddfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsxOTIsODcsNjNdfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbMjA1LDEyNSwxMDVdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjE2LDE2MiwxNDhdfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMjI3LDE5OSwxOTNdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjQxLDIzNywyMzZdfV0sXG5cblx0XCJveHlnZW5cIjogW3tcImluZGV4XCI6MCxcInJnYlwiOls2NCw1LDVdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbMTA2LDYsMTVdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMTQ0LDI2LDddfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMTY4LDY0LDNdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsxODgsMTAwLDRdfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbMjA2LDEzNiwxMV19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlsyMjAsMTc0LDI1XX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzIzMSwyMTUsNDRdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjQ4LDI1NCwxMDVdfV0sXG5cblx0XCJwYXJcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOls1MSwyMCwyNF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOls5MCwzMiwzNV19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOlsxMjksNDQsMzRdfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMTU5LDY4LDI1XX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbMTgyLDk5LDE5XX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzE5OSwxMzQsMjJdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjEyLDE3MSwzNV19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyMjEsMjEwLDU0XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzIyNSwyNTMsNzVdfV0sXG5cblx0XCJwaGFzZVwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzE0NSwxMDUsMThdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbMTg0LDcxLDM4XX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzE4Niw1OCwxMTVdfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMTYwLDcxLDE4NV19LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzExMCw5NywyMThdfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbNTAsMTIzLDE2NF19LHtcImluZGV4XCI6MC43NSxcInJnYlwiOlszMSwxMzEsMTEwXX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6Wzc3LDEyOSwzNF19LHtcImluZGV4XCI6MSxcInJnYlwiOlsxNDUsMTA1LDE4XX1dLFxuXG5cdFwic2FsaW5pdHlcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOls0MiwyNCwxMDhdfSx7XCJpbmRleFwiOjAuMTMsXCJyZ2JcIjpbMzMsNTAsMTYyXX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzE1LDkwLDE0NV19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOls0MCwxMTgsMTM3XX0se1wiaW5kZXhcIjowLjUsXCJyZ2JcIjpbNTksMTQ2LDEzNV19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOls3OSwxNzUsMTI2XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzEyMCwyMDMsMTA0XX0se1wiaW5kZXhcIjowLjg4LFwicmdiXCI6WzE5MywyMjEsMTAwXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzI1MywyMzksMTU0XX1dLFxuXG5cdFwidGVtcGVyYXR1cmVcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOls0LDM1LDUxXX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzIzLDUxLDEyMl19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOls4NSw1OSwxNTddfSx7XCJpbmRleFwiOjAuMzgsXCJyZ2JcIjpbMTI5LDc5LDE0M119LHtcImluZGV4XCI6MC41LFwicmdiXCI6WzE3NSw5NSwxMzBdfSx7XCJpbmRleFwiOjAuNjMsXCJyZ2JcIjpbMjIyLDExMiwxMDFdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjQ5LDE0Niw2Nl19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyNDksMTk2LDY1XX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzIzMiwyNTAsOTFdfV0sXG5cblx0XCJ0dXJiaWRpdHlcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOlszNCwzMSwyN119LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOls2NSw1MCw0MV19LHtcImluZGV4XCI6MC4yNSxcInJnYlwiOls5OCw2OSw1Ml19LHtcImluZGV4XCI6MC4zOCxcInJnYlwiOlsxMzEsODksNTddfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOlsxNjEsMTEyLDU5XX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6WzE4NSwxNDAsNjZdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMjAyLDE3NCw4OF19LHtcImluZGV4XCI6MC44OCxcInJnYlwiOlsyMTYsMjA5LDEyNl19LHtcImluZGV4XCI6MSxcInJnYlwiOlsyMzMsMjQ2LDE3MV19XSxcblxuXHRcInZlbG9jaXR5LWJsdWVcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOlsxNywzMiw2NF19LHtcImluZGV4XCI6MC4xMyxcInJnYlwiOlszNSw1MiwxMTZdfSx7XCJpbmRleFwiOjAuMjUsXCJyZ2JcIjpbMjksODEsMTU2XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzMxLDExMywxNjJdfSx7XCJpbmRleFwiOjAuNSxcInJnYlwiOls1MCwxNDQsMTY5XX0se1wiaW5kZXhcIjowLjYzLFwicmdiXCI6Wzg3LDE3MywxNzZdfSx7XCJpbmRleFwiOjAuNzUsXCJyZ2JcIjpbMTQ5LDE5NiwxODldfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMjAzLDIyMSwyMTFdfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU0LDI1MSwyMzBdfV0sXG5cblx0XCJ2ZWxvY2l0eS1ncmVlblwiOiBbe1wiaW5kZXhcIjowLFwicmdiXCI6WzIzLDM1LDE5XX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzI0LDY0LDM4XX0se1wiaW5kZXhcIjowLjI1LFwicmdiXCI6WzExLDk1LDQ1XX0se1wiaW5kZXhcIjowLjM4LFwicmdiXCI6WzM5LDEyMywzNV19LHtcImluZGV4XCI6MC41LFwicmdiXCI6Wzk1LDE0NiwxMl19LHtcImluZGV4XCI6MC42MyxcInJnYlwiOlsxNTIsMTY1LDE4XX0se1wiaW5kZXhcIjowLjc1LFwicmdiXCI6WzIwMSwxODYsNjldfSx7XCJpbmRleFwiOjAuODgsXCJyZ2JcIjpbMjMzLDIxNiwxMzddfSx7XCJpbmRleFwiOjEsXCJyZ2JcIjpbMjU1LDI1MywyMDVdfV0sXG5cblx0XCJjdWJlaGVsaXhcIjogW3tcImluZGV4XCI6MCxcInJnYlwiOlswLDAsMF19LHtcImluZGV4XCI6MC4wNyxcInJnYlwiOlsyMiw1LDU5XX0se1wiaW5kZXhcIjowLjEzLFwicmdiXCI6WzYwLDQsMTA1XX0se1wiaW5kZXhcIjowLjIsXCJyZ2JcIjpbMTA5LDEsMTM1XX0se1wiaW5kZXhcIjowLjI3LFwicmdiXCI6WzE2MSwwLDE0N119LHtcImluZGV4XCI6MC4zMyxcInJnYlwiOlsyMTAsMiwxNDJdfSx7XCJpbmRleFwiOjAuNCxcInJnYlwiOlsyNTEsMTEsMTIzXX0se1wiaW5kZXhcIjowLjQ3LFwicmdiXCI6WzI1NSwyOSw5N119LHtcImluZGV4XCI6MC41MyxcInJnYlwiOlsyNTUsNTQsNjldfSx7XCJpbmRleFwiOjAuNixcInJnYlwiOlsyNTUsODUsNDZdfSx7XCJpbmRleFwiOjAuNjcsXCJyZ2JcIjpbMjU1LDEyMCwzNF19LHtcImluZGV4XCI6MC43MyxcInJnYlwiOlsyNTUsMTU3LDM3XX0se1wiaW5kZXhcIjowLjgsXCJyZ2JcIjpbMjQxLDE5MSw1N119LHtcImluZGV4XCI6MC44NyxcInJnYlwiOlsyMjQsMjIwLDkzXX0se1wiaW5kZXhcIjowLjkzLFwicmdiXCI6WzIxOCwyNDEsMTQyXX0se1wiaW5kZXhcIjoxLFwicmdiXCI6WzIyNywyNTMsMTk4XX1dXG59O1xuXG59LHt9XSwxMjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIEJlbiBQb3N0bGV0aHdhaXRlXG4gKiBKYW51YXJ5IDIwMTNcbiAqIExpY2Vuc2UgTUlUXG4gKi9cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yU2NhbGUgPSBfZGVyZXFfKCcuL2NvbG9yU2NhbGUnKTtcbnZhciBsZXJwID0gX2RlcmVxXygnbGVycCcpXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlQ29sb3JtYXA7XG5cbmZ1bmN0aW9uIGNyZWF0ZUNvbG9ybWFwIChzcGVjKSB7XG4gICAgLypcbiAgICAgKiBEZWZhdWx0IE9wdGlvbnNcbiAgICAgKi9cbiAgICB2YXIgaW5kaWNpZXMsIGZyb21yZ2JhLCB0b3JnYmEsXG4gICAgICAgIG5zdGVwcywgY21hcCwgY29sb3JtYXAsIGZvcm1hdCxcbiAgICAgICAgbnNoYWRlcywgY29sb3JzLCBhbHBoYSwgaTtcblxuICAgIGlmICggIXNwZWMgKSBzcGVjID0ge307XG5cbiAgICBuc2hhZGVzID0gKHNwZWMubnNoYWRlcyB8fCA3MikgLSAxO1xuICAgIGZvcm1hdCA9IHNwZWMuZm9ybWF0IHx8ICdoZXgnO1xuXG4gICAgY29sb3JtYXAgPSBzcGVjLmNvbG9ybWFwO1xuICAgIGlmICghY29sb3JtYXApIGNvbG9ybWFwID0gJ2pldCc7XG5cbiAgICBpZiAodHlwZW9mIGNvbG9ybWFwID09PSAnc3RyaW5nJykge1xuICAgICAgICBjb2xvcm1hcCA9IGNvbG9ybWFwLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgICAgaWYgKCFjb2xvclNjYWxlW2NvbG9ybWFwXSkge1xuICAgICAgICAgICAgdGhyb3cgRXJyb3IoY29sb3JtYXAgKyAnIG5vdCBhIHN1cHBvcnRlZCBjb2xvcnNjYWxlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBjbWFwID0gY29sb3JTY2FsZVtjb2xvcm1hcF07XG5cbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY29sb3JtYXApKSB7XG4gICAgICAgIGNtYXAgPSBjb2xvcm1hcC5zbGljZSgpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ3Vuc3VwcG9ydGVkIGNvbG9ybWFwIG9wdGlvbicsIGNvbG9ybWFwKTtcbiAgICB9XG5cbiAgICBpZiAoY21hcC5sZW5ndGggPiBuc2hhZGVzICsgMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBjb2xvcm1hcCsnIG1hcCByZXF1aXJlcyBuc2hhZGVzIHRvIGJlIGF0IGxlYXN0IHNpemUgJytjbWFwLmxlbmd0aFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGlmICghQXJyYXkuaXNBcnJheShzcGVjLmFscGhhKSkge1xuXG4gICAgICAgIGlmICh0eXBlb2Ygc3BlYy5hbHBoYSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGFscGhhID0gW3NwZWMuYWxwaGEsIHNwZWMuYWxwaGFdO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhbHBoYSA9IFsxLCAxXTtcbiAgICAgICAgfVxuXG4gICAgfSBlbHNlIGlmIChzcGVjLmFscGhhLmxlbmd0aCAhPT0gMikge1xuICAgICAgICBhbHBoYSA9IFsxLCAxXTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIGFscGhhID0gc3BlYy5hbHBoYS5zbGljZSgpO1xuICAgIH1cblxuICAgIC8vIG1hcCBpbmRleCBwb2ludHMgZnJvbSAwLi4xIHRvIDAuLm4tMVxuICAgIGluZGljaWVzID0gY21hcC5tYXAoZnVuY3Rpb24oYykge1xuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChjLmluZGV4ICogbnNoYWRlcyk7XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYWxwaGEgY2hhbm5lbCB0byB0aGUgbWFwXG4gICAgYWxwaGFbMF0gPSBNYXRoLm1pbihNYXRoLm1heChhbHBoYVswXSwgMCksIDEpO1xuICAgIGFscGhhWzFdID0gTWF0aC5taW4oTWF0aC5tYXgoYWxwaGFbMV0sIDApLCAxKTtcblxuICAgIHZhciBzdGVwcyA9IGNtYXAubWFwKGZ1bmN0aW9uKGMsIGkpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gY21hcFtpXS5pbmRleFxuXG4gICAgICAgIHZhciByZ2JhID0gY21hcFtpXS5yZ2Iuc2xpY2UoKTtcblxuICAgICAgICAvLyBpZiB1c2VyIHN1cHBsaWVzIHRoZWlyIG93biBtYXAgdXNlIGl0XG4gICAgICAgIGlmIChyZ2JhLmxlbmd0aCA9PT0gNCAmJiByZ2JhWzNdID49IDAgJiYgcmdiYVszXSA8PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gcmdiYVxuICAgICAgICB9XG4gICAgICAgIHJnYmFbM10gPSBhbHBoYVswXSArIChhbHBoYVsxXSAtIGFscGhhWzBdKSppbmRleDtcblxuICAgICAgICByZXR1cm4gcmdiYVxuICAgIH0pXG5cblxuICAgIC8qXG4gICAgICogbWFwIGluY3JlYXNpbmcgbGluZWFyIHZhbHVlcyBiZXR3ZWVuIGluZGljaWVzIHRvXG4gICAgICogbGluZWFyIHN0ZXBzIGluIGNvbG9ydmFsdWVzXG4gICAgICovXG4gICAgdmFyIGNvbG9ycyA9IFtdXG4gICAgZm9yIChpID0gMDsgaSA8IGluZGljaWVzLmxlbmd0aC0xOyArK2kpIHtcbiAgICAgICAgbnN0ZXBzID0gaW5kaWNpZXNbaSsxXSAtIGluZGljaWVzW2ldO1xuICAgICAgICBmcm9tcmdiYSA9IHN0ZXBzW2ldO1xuICAgICAgICB0b3JnYmEgPSBzdGVwc1tpKzFdO1xuXG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbnN0ZXBzOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBhbXQgPSBqIC8gbnN0ZXBzXG4gICAgICAgICAgICBjb2xvcnMucHVzaChbXG4gICAgICAgICAgICAgICAgTWF0aC5yb3VuZChsZXJwKGZyb21yZ2JhWzBdLCB0b3JnYmFbMF0sIGFtdCkpLFxuICAgICAgICAgICAgICAgIE1hdGgucm91bmQobGVycChmcm9tcmdiYVsxXSwgdG9yZ2JhWzFdLCBhbXQpKSxcbiAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKGxlcnAoZnJvbXJnYmFbMl0sIHRvcmdiYVsyXSwgYW10KSksXG4gICAgICAgICAgICAgICAgbGVycChmcm9tcmdiYVszXSwgdG9yZ2JhWzNdLCBhbXQpXG4gICAgICAgICAgICBdKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy9hZGQgMSBzdGVwIGFzIGxhc3QgdmFsdWVcbiAgICBjb2xvcnMucHVzaChjbWFwW2NtYXAubGVuZ3RoIC0gMV0ucmdiLmNvbmNhdChhbHBoYVsxXSkpXG5cbiAgICBpZiAoZm9ybWF0ID09PSAnaGV4JykgY29sb3JzID0gY29sb3JzLm1hcCggcmdiMmhleCApO1xuICAgIGVsc2UgaWYgKGZvcm1hdCA9PT0gJ3JnYmFTdHJpbmcnKSBjb2xvcnMgPSBjb2xvcnMubWFwKCByZ2JhU3RyICk7XG4gICAgZWxzZSBpZiAoZm9ybWF0ID09PSAnZmxvYXQnKSBjb2xvcnMgPSBjb2xvcnMubWFwKCByZ2IyZmxvYXQgKTtcblxuICAgIHJldHVybiBjb2xvcnM7XG59O1xuXG5mdW5jdGlvbiByZ2IyZmxvYXQgKHJnYmEpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICByZ2JhWzBdIC8gMjU1LFxuICAgICAgICByZ2JhWzFdIC8gMjU1LFxuICAgICAgICByZ2JhWzJdIC8gMjU1LFxuICAgICAgICByZ2JhWzNdXG4gICAgXVxufVxuXG5mdW5jdGlvbiByZ2IyaGV4IChyZ2JhKSB7XG4gICAgdmFyIGRpZywgaGV4ID0gJyMnO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIGRpZyA9IHJnYmFbaV07XG4gICAgICAgIGRpZyA9IGRpZy50b1N0cmluZygxNik7XG4gICAgICAgIGhleCArPSAoJzAwJyArIGRpZykuc3Vic3RyKCBkaWcubGVuZ3RoICk7XG4gICAgfVxuICAgIHJldHVybiBoZXg7XG59XG5cbmZ1bmN0aW9uIHJnYmFTdHIgKHJnYmEpIHtcbiAgICByZXR1cm4gJ3JnYmEoJyArIHJnYmEuam9pbignLCcpICsgJyknO1xufVxuXG59LHtcIi4vY29sb3JTY2FsZVwiOjEyNSxcImxlcnBcIjo0MjV9XSwxMjc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBjb21wYXJlQW5nbGVcblxudmFyIG9yaWVudCA9IF9kZXJlcV8oXCJyb2J1c3Qtb3JpZW50YXRpb25cIilcbnZhciBzZ24gPSBfZGVyZXFfKFwic2lnbnVtXCIpXG52YXIgdHdvU3VtID0gX2RlcmVxXyhcInR3by1zdW1cIilcbnZhciByb2J1c3RQcm9kdWN0ID0gX2RlcmVxXyhcInJvYnVzdC1wcm9kdWN0XCIpXG52YXIgcm9idXN0U3VtID0gX2RlcmVxXyhcInJvYnVzdC1zdW1cIilcblxuZnVuY3Rpb24gdGVzdEludGVyaW9yKGEsIGIsIGMpIHtcbiAgdmFyIHgwID0gdHdvU3VtKGFbMF0sIC1iWzBdKVxuICB2YXIgeTAgPSB0d29TdW0oYVsxXSwgLWJbMV0pXG4gIHZhciB4MSA9IHR3b1N1bShjWzBdLCAtYlswXSlcbiAgdmFyIHkxID0gdHdvU3VtKGNbMV0sIC1iWzFdKVxuXG4gIHZhciBkID0gcm9idXN0U3VtKFxuICAgIHJvYnVzdFByb2R1Y3QoeDAsIHgxKSxcbiAgICByb2J1c3RQcm9kdWN0KHkwLCB5MSkpXG5cbiAgcmV0dXJuIGRbZC5sZW5ndGgtMV0gPj0gMFxufVxuXG5mdW5jdGlvbiBjb21wYXJlQW5nbGUoYSwgYiwgYywgZCkge1xuICB2YXIgYmNkID0gb3JpZW50KGIsIGMsIGQpXG4gIGlmKGJjZCA9PT0gMCkge1xuICAgIC8vSGFuZGxlIGRlZ2VuZXJhdGUgY2FzZXNcbiAgICB2YXIgc2FiYyA9IHNnbihvcmllbnQoYSwgYiwgYykpXG4gICAgdmFyIHNhYmQgPSBzZ24ob3JpZW50KGEsIGIsIGQpKVxuICAgIGlmKHNhYmMgPT09IHNhYmQpIHtcbiAgICAgIGlmKHNhYmMgPT09IDApIHtcbiAgICAgICAgdmFyIGljID0gdGVzdEludGVyaW9yKGEsIGIsIGMpXG4gICAgICAgIHZhciBpZCA9IHRlc3RJbnRlcmlvcihhLCBiLCBkKVxuICAgICAgICBpZihpYyA9PT0gaWQpIHtcbiAgICAgICAgICByZXR1cm4gMFxuICAgICAgICB9IGVsc2UgaWYoaWMpIHtcbiAgICAgICAgICByZXR1cm4gMVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiAtMVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gMFxuICAgIH0gZWxzZSBpZihzYWJkID09PSAwKSB7XG4gICAgICBpZihzYWJjID4gMCkge1xuICAgICAgICByZXR1cm4gLTFcbiAgICAgIH0gZWxzZSBpZih0ZXN0SW50ZXJpb3IoYSwgYiwgZCkpIHtcbiAgICAgICAgcmV0dXJuIC0xXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gMVxuICAgICAgfVxuICAgIH0gZWxzZSBpZihzYWJjID09PSAwKSB7XG4gICAgICBpZihzYWJkID4gMCkge1xuICAgICAgICByZXR1cm4gMVxuICAgICAgfSBlbHNlIGlmKHRlc3RJbnRlcmlvcihhLCBiLCBjKSkge1xuICAgICAgICByZXR1cm4gMVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIC0xXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzZ24oc2FiZCAtIHNhYmMpXG4gIH1cbiAgdmFyIGFiYyA9IG9yaWVudChhLCBiLCBjKVxuICBpZihhYmMgPiAwKSB7XG4gICAgaWYoYmNkID4gMCAmJiBvcmllbnQoYSwgYiwgZCkgPiAwKSB7XG4gICAgICByZXR1cm4gMVxuICAgIH1cbiAgICByZXR1cm4gLTFcbiAgfSBlbHNlIGlmKGFiYyA8IDApIHtcbiAgICBpZihiY2QgPiAwIHx8IG9yaWVudChhLCBiLCBkKSA+IDApIHtcbiAgICAgIHJldHVybiAxXG4gICAgfVxuICAgIHJldHVybiAtMVxuICB9IGVsc2Uge1xuICAgIHZhciBhYmQgPSBvcmllbnQoYSwgYiwgZClcbiAgICBpZihhYmQgPiAwKSB7XG4gICAgICByZXR1cm4gMVxuICAgIH0gZWxzZSB7XG4gICAgICBpZih0ZXN0SW50ZXJpb3IoYSwgYiwgYykpIHtcbiAgICAgICAgcmV0dXJuIDFcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAtMVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxufSx7XCJyb2J1c3Qtb3JpZW50YXRpb25cIjo1MTAsXCJyb2J1c3QtcHJvZHVjdFwiOjUxMSxcInJvYnVzdC1zdW1cIjo1MTUsXCJzaWdudW1cIjo1MTYsXCJ0d28tc3VtXCI6NTQ0fV0sMTI4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gY29tcGFyZUNlbGxzXG5cbnZhciBtaW4gPSBNYXRoLm1pblxuXG5mdW5jdGlvbiBjb21wYXJlSW50KGEsIGIpIHtcbiAgcmV0dXJuIGEgLSBiXG59XG5cbmZ1bmN0aW9uIGNvbXBhcmVDZWxscyhhLCBiKSB7XG4gIHZhciBuID0gYS5sZW5ndGhcbiAgICAsIHQgPSBhLmxlbmd0aCAtIGIubGVuZ3RoXG4gIGlmKHQpIHtcbiAgICByZXR1cm4gdFxuICB9XG4gIHN3aXRjaChuKSB7XG4gICAgY2FzZSAwOlxuICAgICAgcmV0dXJuIDBcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gYVswXSAtIGJbMF1cbiAgICBjYXNlIDI6XG4gICAgICByZXR1cm4gKGFbMF0rYVsxXS1iWzBdLWJbMV0pIHx8XG4gICAgICAgICAgICAgbWluKGFbMF0sYVsxXSkgLSBtaW4oYlswXSxiWzFdKVxuICAgIGNhc2UgMzpcbiAgICAgIHZhciBsMSA9IGFbMF0rYVsxXVxuICAgICAgICAsIG0xID0gYlswXStiWzFdXG4gICAgICB0ID0gbDErYVsyXSAtIChtMStiWzJdKVxuICAgICAgaWYodCkge1xuICAgICAgICByZXR1cm4gdFxuICAgICAgfVxuICAgICAgdmFyIGwwID0gbWluKGFbMF0sIGFbMV0pXG4gICAgICAgICwgbTAgPSBtaW4oYlswXSwgYlsxXSlcbiAgICAgIHJldHVybiBtaW4obDAsIGFbMl0pIC0gbWluKG0wLCBiWzJdKSB8fFxuICAgICAgICAgICAgIG1pbihsMCthWzJdLCBsMSkgLSBtaW4obTArYlsyXSwgbTEpXG4gICAgY2FzZSA0OlxuICAgICAgdmFyIGF3PWFbMF0sIGF4PWFbMV0sIGF5PWFbMl0sIGF6PWFbM11cbiAgICAgICAgLCBidz1iWzBdLCBieD1iWzFdLCBieT1iWzJdLCBiej1iWzNdXG4gICAgICByZXR1cm4gKGF3K2F4K2F5K2F6KS0oYncrYngrYnkrYnopIHx8XG4gICAgICAgICAgICAgbWluKGF3LGF4LGF5LGF6KS1taW4oYncsYngsYnksYnosYncpIHx8XG4gICAgICAgICAgICAgbWluKGF3K2F4LGF3K2F5LGF3K2F6LGF4K2F5LGF4K2F6LGF5K2F6KSAtXG4gICAgICAgICAgICAgICBtaW4oYncrYngsYncrYnksYncrYnosYngrYnksYngrYnosYnkrYnopIHx8XG4gICAgICAgICAgICAgbWluKGF3K2F4K2F5LGF3K2F4K2F6LGF3K2F5K2F6LGF4K2F5K2F6KSAtXG4gICAgICAgICAgICAgICBtaW4oYncrYngrYnksYncrYngrYnosYncrYnkrYnosYngrYnkrYnopXG4gICAgZGVmYXVsdDpcbiAgICAgIHZhciBhcyA9IGEuc2xpY2UoKS5zb3J0KGNvbXBhcmVJbnQpXG4gICAgICB2YXIgYnMgPSBiLnNsaWNlKCkuc29ydChjb21wYXJlSW50KVxuICAgICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgICAgIHQgPSBhc1tpXSAtIGJzW2ldXG4gICAgICAgIGlmKHQpIHtcbiAgICAgICAgICByZXR1cm4gdFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gMFxuICB9XG59XG5cbn0se31dLDEyOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGNvbXBhcmVDZWxscyA9IF9kZXJlcV8oJ2NvbXBhcmUtY2VsbCcpXG52YXIgcGFyaXR5ID0gX2RlcmVxXygnY2VsbC1vcmllbnRhdGlvbicpXG5cbm1vZHVsZS5leHBvcnRzID0gY29tcGFyZU9yaWVudGVkQ2VsbHNcblxuZnVuY3Rpb24gY29tcGFyZU9yaWVudGVkQ2VsbHMoYSwgYikge1xuICByZXR1cm4gY29tcGFyZUNlbGxzKGEsIGIpIHx8IHBhcml0eShhKSAtIHBhcml0eShiKVxufVxuXG59LHtcImNlbGwtb3JpZW50YXRpb25cIjoxMTIsXCJjb21wYXJlLWNlbGxcIjoxMjh9XSwxMzA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxudmFyIGNvbnZleEh1bGwxZCA9IF9kZXJlcV8oJy4vbGliL2NoMWQnKVxudmFyIGNvbnZleEh1bGwyZCA9IF9kZXJlcV8oJy4vbGliL2NoMmQnKVxudmFyIGNvbnZleEh1bGxuZCA9IF9kZXJlcV8oJy4vbGliL2NobmQnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbnZleEh1bGxcblxuZnVuY3Rpb24gY29udmV4SHVsbChwb2ludHMpIHtcbiAgdmFyIG4gPSBwb2ludHMubGVuZ3RoXG4gIGlmKG4gPT09IDApIHtcbiAgICByZXR1cm4gW11cbiAgfSBlbHNlIGlmKG4gPT09IDEpIHtcbiAgICByZXR1cm4gW1swXV1cbiAgfVxuICB2YXIgZCA9IHBvaW50c1swXS5sZW5ndGhcbiAgaWYoZCA9PT0gMCkge1xuICAgIHJldHVybiBbXVxuICB9IGVsc2UgaWYoZCA9PT0gMSkge1xuICAgIHJldHVybiBjb252ZXhIdWxsMWQocG9pbnRzKVxuICB9IGVsc2UgaWYoZCA9PT0gMikge1xuICAgIHJldHVybiBjb252ZXhIdWxsMmQocG9pbnRzKVxuICB9XG4gIHJldHVybiBjb252ZXhIdWxsbmQocG9pbnRzLCBkKVxufVxufSx7XCIuL2xpYi9jaDFkXCI6MTMxLFwiLi9saWIvY2gyZFwiOjEzMixcIi4vbGliL2NobmRcIjoxMzN9XSwxMzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBjb252ZXhIdWxsMWRcblxuZnVuY3Rpb24gY29udmV4SHVsbDFkKHBvaW50cykge1xuICB2YXIgbG8gPSAwXG4gIHZhciBoaSA9IDBcbiAgZm9yKHZhciBpPTE7IGk8cG9pbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgaWYocG9pbnRzW2ldWzBdIDwgcG9pbnRzW2xvXVswXSkge1xuICAgICAgbG8gPSBpXG4gICAgfVxuICAgIGlmKHBvaW50c1tpXVswXSA+IHBvaW50c1toaV1bMF0pIHtcbiAgICAgIGhpID0gaVxuICAgIH1cbiAgfVxuICBpZihsbyA8IGhpKSB7XG4gICAgcmV0dXJuIFtbbG9dLCBbaGldXVxuICB9IGVsc2UgaWYobG8gPiBoaSkge1xuICAgIHJldHVybiBbW2hpXSwgW2xvXV1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gW1tsb11dXG4gIH1cbn1cbn0se31dLDEzMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjb252ZXhIdWxsMkRcblxudmFyIG1vbm90b25lSHVsbCA9IF9kZXJlcV8oJ21vbm90b25lLWNvbnZleC1odWxsLTJkJylcblxuZnVuY3Rpb24gY29udmV4SHVsbDJEKHBvaW50cykge1xuICB2YXIgaHVsbCA9IG1vbm90b25lSHVsbChwb2ludHMpXG4gIHZhciBoID0gaHVsbC5sZW5ndGhcbiAgaWYoaCA8PSAyKSB7XG4gICAgcmV0dXJuIFtdXG4gIH1cbiAgdmFyIGVkZ2VzID0gbmV3IEFycmF5KGgpXG4gIHZhciBhID0gaHVsbFtoLTFdXG4gIGZvcih2YXIgaT0wOyBpPGg7ICsraSkge1xuICAgIHZhciBiID0gaHVsbFtpXVxuICAgIGVkZ2VzW2ldID0gW2EsYl1cbiAgICBhID0gYlxuICB9XG4gIHJldHVybiBlZGdlc1xufVxuXG59LHtcIm1vbm90b25lLWNvbnZleC1odWxsLTJkXCI6NDM0fV0sMTMzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbnZleEh1bGxuRFxuXG52YXIgaWNoID0gX2RlcmVxXygnaW5jcmVtZW50YWwtY29udmV4LWh1bGwnKVxudmFyIGFmZiA9IF9kZXJlcV8oJ2FmZmluZS1odWxsJylcblxuZnVuY3Rpb24gcGVybXV0ZShwb2ludHMsIGZyb250KSB7XG4gIHZhciBuID0gcG9pbnRzLmxlbmd0aFxuICB2YXIgbnBvaW50cyA9IG5ldyBBcnJheShuKVxuICBmb3IodmFyIGk9MDsgaTxmcm9udC5sZW5ndGg7ICsraSkge1xuICAgIG5wb2ludHNbaV0gPSBwb2ludHNbZnJvbnRbaV1dXG4gIH1cbiAgdmFyIHB0ciA9IGZyb250Lmxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICBpZihmcm9udC5pbmRleE9mKGkpIDwgMCkge1xuICAgICAgbnBvaW50c1twdHIrK10gPSBwb2ludHNbaV1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5wb2ludHNcbn1cblxuZnVuY3Rpb24gaW52UGVybXV0ZShjZWxscywgZnJvbnQpIHtcbiAgdmFyIG5jID0gY2VsbHMubGVuZ3RoXG4gIHZhciBuZiA9IGZyb250Lmxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxuYzsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPGMubGVuZ3RoOyArK2opIHtcbiAgICAgIHZhciB4ID0gY1tqXVxuICAgICAgaWYoeCA8IG5mKSB7XG4gICAgICAgIGNbal0gPSBmcm9udFt4XVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeCA9IHggLSBuZlxuICAgICAgICBmb3IodmFyIGs9MDsgazxuZjsgKytrKSB7XG4gICAgICAgICAgaWYoeCA+PSBmcm9udFtrXSkge1xuICAgICAgICAgICAgeCArPSAxXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNbal0gPSB4XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBjZWxsc1xufVxuXG5mdW5jdGlvbiBjb252ZXhIdWxsbkQocG9pbnRzLCBkKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGljaChwb2ludHMsIHRydWUpXG4gIH0gY2F0Y2goZSkge1xuICAgIC8vSWYgcG9pbnQgc2V0IGlzIGRlZ2VuZXJhdGUsIHRyeSB0byBmaW5kIGEgYmFzaXMgYW5kIHJlcnVuIGl0XG4gICAgdmFyIGFoID0gYWZmKHBvaW50cylcbiAgICBpZihhaC5sZW5ndGggPD0gZCkge1xuICAgICAgLy9ObyBiYXNpcywgbm8gdHJ5XG4gICAgICByZXR1cm4gW11cbiAgICB9XG4gICAgdmFyIG5wb2ludHMgPSBwZXJtdXRlKHBvaW50cywgYWgpXG4gICAgdmFyIG5odWxsICAgPSBpY2gobnBvaW50cywgdHJ1ZSlcbiAgICByZXR1cm4gaW52UGVybXV0ZShuaHVsbCwgYWgpXG4gIH1cbn1cbn0se1wiYWZmaW5lLWh1bGxcIjo2MixcImluY3JlbWVudGFsLWNvbnZleC1odWxsXCI6NDEzfV0sMTM0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0ge1xuICBBRkc6ICdhZmdoYW4nLFxuICBBTEE6ICdcXFxcYlxcXFx3bGFuZCcsXG4gIEFMQjogJ2FsYmFuaWEnLFxuICBEWkE6ICdhbGdlcmlhJyxcbiAgQVNNOiAnXig/PS4qYW1lcmljKS4qc2Ftb2EnLFxuICBBTkQ6ICdhbmRvcnJhJyxcbiAgQUdPOiAnYW5nb2xhJyxcbiAgQUlBOiAnYW5ndWlsbD9hJyxcbiAgQVRBOiAnYW50YXJjdGljYScsXG4gIEFURzogJ2FudGlndWEnLFxuICBBUkc6ICdhcmdlbnRpbicsXG4gIEFSTTogJ2FybWVuaWEnLFxuICBBQlc6ICdeKD8hLipib25haXJlKS4qXFxcXGJhcnViYScsXG4gIEFVUzogJ2F1c3RyYWxpYScsXG4gIEFVVDogJ14oPyEuKmh1bmdhcnkpLiphdXN0cmlhfFxcXFxiYXVzdHJpLipcXFxcYmVtcCcsXG4gIEFaRTogJ2F6ZXJiYWlqYW4nLFxuICBCSFM6ICdiYWhhbWFzJyxcbiAgQkhSOiAnYmFocmFpbicsXG4gIEJHRDogJ2JhbmdsYWRlc2h8Xig/PS4qZWFzdCkuKnBha2k/c3RhbicsXG4gIEJSQjogJ2JhcmJhZG9zJyxcbiAgQkxSOiAnYmVsYXJ1c3xieWVsbycsXG4gIEJFTDogJ14oPyEuKmx1eGVtKS4qYmVsZ2l1bScsXG4gIEJMWjogJ2JlbGl6ZXxeKD89Lipicml0aXNoKS4qaG9uZHVyYXMnLFxuICBCRU46ICdiZW5pbnxkYWhvbWUnLFxuICBCTVU6ICdiZXJtdWRhJyxcbiAgQlROOiAnYmh1dGFuJyxcbiAgQk9MOiAnYm9saXZpYScsXG4gIEJFUzogJ14oPz0uKmJvbmFpcmUpLipldXN0YXRpdXN8Xig/PS4qY2FyaWIpLipuZXRoZXJsYW5kc3xcXFxcYmJlcy4/aXNsYW5kcycsXG4gIEJJSDogJ2hlcnplZ292aW5hfGJvc25pYScsXG4gIEJXQTogJ2JvdHN3YW5hfGJlY2h1YW5hJyxcbiAgQlZUOiAnYm91dmV0JyxcbiAgQlJBOiAnYnJhemlsJyxcbiAgSU9UOiAnYnJpdGlzaC4/aW5kaWFuLj9vY2VhbicsXG4gIEJSTjogJ2JydW5laScsXG4gIEJHUjogJ2J1bGdhcmlhJyxcbiAgQkZBOiAnYnVya2luYXxcXFxcYmZhc298dXBwZXIuP3ZvbHRhJyxcbiAgQkRJOiAnYnVydW5kaScsXG4gIENQVjogJ3ZlcmRlJyxcbiAgS0hNOiAnY2FtYm9kaWF8a2FtcHVjaGVhfGtobWVyJyxcbiAgQ01SOiAnY2FtZXJvb24nLFxuICBDQU46ICdjYW5hZGEnLFxuICBDWU06ICdjYXltYW4nLFxuICBDQUY6ICdcXFxcYmNlbnRyYWwuYWZyaWNhbi5yZXB1YmxpYycsXG4gIFRDRDogJ1xcXFxiY2hhZCcsXG4gIENITDogJ1xcXFxiY2hpbGUnLFxuICBDSE46ICdeKD8hLipcXFxcYm1hYykoPyEuKlxcXFxiaG9uZykoPyEuKlxcXFxidGFpKSg/IS4qXFxcXGJyZXApLipjaGluYXxeKD89LipwZW8pKD89LipyZXApLipjaGluYScsXG4gIENYUjogJ2NocmlzdG1hcycsXG4gIENDSzogJ1xcXFxiY29jb3N8a2VlbGluZycsXG4gIENPTDogJ2NvbG9tYmlhJyxcbiAgQ09NOiAnY29tb3JvJyxcbiAgQ09HOiAnXig/IS4qXFxcXGJkZW0pKD8hLipcXFxcYmRbXFxcXC5dP3IpKD8hLipraW5zaGFzYSkoPyEuKnphaXJlKSg/IS4qYmVsZykoPyEuKmwub3BvbGR2aWxsZSkoPyEuKmZyZWUpLipcXFxcYmNvbmdvJyxcbiAgQ09LOiAnXFxcXGJjb29rJyxcbiAgQ1JJOiAnY29zdGEuP3JpY2EnLFxuICBDSVY6ICdpdm9pcmV8aXZvcnknLFxuICBIUlY6ICdjcm9hdGlhJyxcbiAgQ1VCOiAnXFxcXGJjdWJhJyxcbiAgQ1VXOiAnXig/IS4qYm9uYWlyZSkuKlxcXFxiY3VyYShjfMOnKWFvJyxcbiAgQ1lQOiAnY3lwcnVzJyxcbiAgQ1NLOiAnY3plY2hvc2xvdmFraWEnLFxuICBDWkU6ICdeKD89LipyZXApLipjemVjaHxjemVjaGlhfGJvaGVtaWEnLFxuICBDT0Q6ICdcXFxcYmRlbS4qY29uZ298Y29uZ28uKlxcXFxiZGVtfGNvbmdvLipcXFxcYmRbXFxcXC5dP3J8XFxcXGJkW1xcXFwuXT9yLipjb25nb3xiZWxnaWFuLj9jb25nb3xjb25nby4/ZnJlZS4/c3RhdGV8a2luc2hhc2F8emFpcmV8bC5vcG9sZHZpbGxlfGRyY3xkcm9jfHJkYycsXG4gIEROSzogJ2Rlbm1hcmsnLFxuICBESkk6ICdkamlib3V0aScsXG4gIERNQTogJ2RvbWluaWNhKD8hbiknLFxuICBET006ICdkb21pbmljYW4ucmVwJyxcbiAgRUNVOiAnZWN1YWRvcicsXG4gIEVHWTogJ2VneXB0JyxcbiAgU0xWOiAnZWwuP3NhbHZhZG9yJyxcbiAgR05ROiAnZ3VpbmUuKmVxfGVxLipndWluZXxeKD89LipzcGFuKS4qZ3VpbmVhJyxcbiAgRVJJOiAnZXJpdHJlYScsXG4gIEVTVDogJ2VzdG9uaWEnLFxuICBFVEg6ICdldGhpb3BpYXxhYnlzc2luaWEnLFxuICBGTEs6ICdmYWxrbGFuZHxtYWx2aW5hcycsXG4gIEZSTzogJ2Zhcm9lfGZhZXJvZScsXG4gIEZKSTogJ2ZpamknLFxuICBGSU46ICdmaW5sYW5kJyxcbiAgRlJBOiAnXig/IS4qXFxcXGJkZXApKD8hLiptYXJ0aW5pcXVlKS4qZnJhbmNlfGZyZW5jaC4/cmVwdWJsaWN8XFxcXGJnYXVsJyxcbiAgR1VGOiAnXig/PS4qZnJlbmNoKS4qZ3VpYW5hJyxcbiAgUFlGOiAnZnJlbmNoLj9wb2x5bmVzaWF8dGFoaXRpJyxcbiAgQVRGOiAnZnJlbmNoLj9zb3V0aGVybicsXG4gIEdBQjogJ2dhYm9uJyxcbiAgR01COiAnZ2FtYmlhJyxcbiAgR0VPOiAnXig/IS4qc291dGgpLipnZW9yZ2lhJyxcbiAgRERSOiAnZ2VybWFuLj9kZW1vY3JhdGljLj9yZXB1YmxpY3xkZW1vY3JhdGljLj9yZXB1YmxpYy4qZ2VybWFueXxlYXN0Lmdlcm1hbnknLFxuICBERVU6ICdeKD8hLiplYXN0KS4qZ2VybWFueXxeKD89LipcXFxcYmZlZC4qXFxcXGJyZXApLipnZXJtYW4nLFxuICBHSEE6ICdnaGFuYXxnb2xkLj9jb2FzdCcsXG4gIEdJQjogJ2dpYnJhbHRhcicsXG4gIEdSQzogJ2dyZWVjZXxoZWxsZW5pY3xoZWxsYXMnLFxuICBHUkw6ICdncmVlbmxhbmQnLFxuICBHUkQ6ICdncmVuYWRhJyxcbiAgR0xQOiAnZ3VhZGVsb3VwZScsXG4gIEdVTTogJ1xcXFxiZ3VhbScsXG4gIEdUTTogJ2d1YXRlbWFsYScsXG4gIEdHWTogJ2d1ZXJuc2V5JyxcbiAgR0lOOiAnXig/IS4qZXEpKD8hLipzcGFuKSg/IS4qYmlzc2F1KSg/IS4qcG9ydHUpKD8hLipuZXcpLipndWluZWEnLFxuICBHTkI6ICdiaXNzYXV8Xig/PS4qcG9ydHUpLipndWluZWEnLFxuICBHVVk6ICdndXlhbmF8YnJpdGlzaC4/Z3VpYW5hJyxcbiAgSFRJOiAnaGFpdGknLFxuICBITUQ6ICdoZWFyZC4qbWNkb25hbGQnLFxuICBWQVQ6ICdob2x5Lj9zZWV8dmF0aWNhbnxwYXBhbC4/c3QnLFxuICBITkQ6ICdeKD8hLipicml0KS4qaG9uZHVyYXMnLFxuICBIS0c6ICdob25nLj9rb25nJyxcbiAgSFVOOiAnXig/IS4qYXVzdHIpLipodW5nYXJ5JyxcbiAgSVNMOiAnaWNlbGFuZCcsXG4gIElORDogJ2luZGlhKD8hLipvY2VhKScsXG4gIElETjogJ2luZG9uZXNpYScsXG4gIElSTjogJ1xcXFxiaXJhbnxwZXJzaWEnLFxuICBJUlE6ICdcXFxcYmlyYXF8bWVzb3BvdGFtaWEnLFxuICBJUkw6ICcoXmlyZWxhbmQpfChecmVwdWJsaWMuKmlyZWxhbmQpJyxcbiAgSU1OOiAnXig/PS4qaXNsZSkuKlxcXFxibWFuJyxcbiAgSVNSOiAnaXNyYWVsJyxcbiAgSVRBOiAnaXRhbHknLFxuICBKQU06ICdqYW1haWNhJyxcbiAgSlBOOiAnamFwYW4nLFxuICBKRVk6ICdqZXJzZXknLFxuICBKT1I6ICdqb3JkYW4nLFxuICBLQVo6ICdrYXphaycsXG4gIEtFTjogJ2tlbnlhfGJyaXRpc2guP2Vhc3QuP2FmcmljYXxlYXN0Lj9hZnJpY2EuP3Byb3QnLFxuICBLSVI6ICdraXJpYmF0aScsXG4gIFBSSzogJ14oPz0uKmRlbW9jcmF0fHBlb3BsZXxub3J0aHxkLipwLioucikuKlxcXFxia29yZWF8ZHBya3xrb3JlYS4qKGQuKnAuKnIpJyxcbiAgS1dUOiAna3V3YWl0JyxcbiAgS0daOiAna3lyZ3l6fGtpcmdoaXonLFxuICBMQU86ICdcXFxcYmxhb3M/XFxcXGInLFxuICBMVkE6ICdsYXR2aWEnLFxuICBMQk46ICdsZWJhbm9uJyxcbiAgTFNPOiAnbGVzb3Rob3xiYXN1dG8nLFxuICBMQlI6ICdsaWJlcmlhJyxcbiAgTEJZOiAnbGlieWEnLFxuICBMSUU6ICdsaWVjaHRlbnN0ZWluJyxcbiAgTFRVOiAnbGl0aHVhbmlhJyxcbiAgTFVYOiAnXig/IS4qYmVsZykuKmx1eGVtJyxcbiAgTUFDOiAnbWFjYShvfHUpJyxcbiAgTURHOiAnbWFkYWdhc2NhcnxtYWxhZ2FzeScsXG4gIE1XSTogJ21hbGF3aXxueWFzYScsXG4gIE1ZUzogJ21hbGF5c2lhJyxcbiAgTURWOiAnbWFsZGl2ZScsXG4gIE1MSTogJ1xcXFxibWFsaVxcXFxiJyxcbiAgTUxUOiAnXFxcXGJtYWx0YScsXG4gIE1ITDogJ21hcnNoYWxsJyxcbiAgTVRROiAnbWFydGluaXF1ZScsXG4gIE1SVDogJ21hdXJpdGFuaWEnLFxuICBNVVM6ICdtYXVyaXRpdXMnLFxuICBNWVQ6ICdcXFxcYm1heW90dGUnLFxuICBNRVg6ICdcXFxcYm1leGljJyxcbiAgRlNNOiAnZmVkLiptaWNyb25lc2lhfG1pY3JvbmVzaWEuKmZlZCcsXG4gIE1DTzogJ21vbmFjbycsXG4gIE1ORzogJ21vbmdvbGlhJyxcbiAgTU5FOiAnXig/IS4qc2VyYmlhKS4qbW9udGVuZWdybycsXG4gIE1TUjogJ21vbnRzZXJyYXQnLFxuICBNQVI6ICdtb3JvY2NvfFxcXFxibWFyb2MnLFxuICBNT1o6ICdtb3phbWJpcXVlJyxcbiAgTU1SOiAnbXlhbm1hcnxidXJtYScsXG4gIE5BTTogJ25hbWliaWEnLFxuICBOUlU6ICduYXVydScsXG4gIE5QTDogJ25lcGFsJyxcbiAgTkxEOiAnXig/IS4qXFxcXGJhbnQpKD8hLipcXFxcYmNhcmliKS4qbmV0aGVybGFuZHMnLFxuICBBTlQ6ICdeKD89LipcXFxcYmFudCkuKihuZXRoZXJ8ZHV0Y2gpJyxcbiAgTkNMOiAnbmV3Lj9jYWxlZG9uaWEnLFxuICBOWkw6ICduZXcuP3plYWxhbmQnLFxuICBOSUM6ICduaWNhcmFndWEnLFxuICBORVI6ICdcXFxcYm5pZ2VyKD8haWEpJyxcbiAgTkdBOiAnbmlnZXJpYScsXG4gIE5JVTogJ25pdWUnLFxuICBORks6ICdub3Jmb2xrJyxcbiAgTU5QOiAnbWFyaWFuYScsXG4gIE5PUjogJ25vcndheScsXG4gIE9NTjogJ1xcXFxib21hbnx0cnVjaWFsJyxcbiAgUEFLOiAnXig/IS4qZWFzdCkuKnBha2k/c3RhbicsXG4gIFBMVzogJ3BhbGF1JyxcbiAgUFNFOiAncGFsZXN0aW58XFxcXGJnYXphfHdlc3QuP2JhbmsnLFxuICBQQU46ICdwYW5hbWEnLFxuICBQTkc6ICdwYXB1YXxuZXcuP2d1aW5lYScsXG4gIFBSWTogJ3BhcmFndWF5JyxcbiAgUEVSOiAncGVydScsXG4gIFBITDogJ3BoaWxpcHBpbmVzJyxcbiAgUENOOiAncGl0Y2Fpcm4nLFxuICBQT0w6ICdwb2xhbmQnLFxuICBQUlQ6ICdwb3J0dWdhbCcsXG4gIFBSSTogJ3B1ZXJ0by4/cmljbycsXG4gIFFBVDogJ3FhdGFyJyxcbiAgS09SOiAnXig/IS4qZC4qcC4qcikoPyEuKmRlbW9jcmF0KSg/IS4qcGVvcGxlKSg/IS4qbm9ydGgpLipcXFxcYmtvcmVhKD8hLipkLipwLipyKScsXG4gIE1EQTogJ21vbGRvdnxiKGF8ZSlzc2FyYWJpYScsXG4gIFJFVTogJ3IoZXzDqSl1bmlvbicsXG4gIFJPVTogJ3Iob3x1fG91KW1hbmlhJyxcbiAgUlVTOiAnXFxcXGJydXNzaWF8c292aWV0Lj91bmlvbnx1XFxcXC4/c1xcXFwuP3NcXFxcLj9yfHNvY2lhbGlzdC4/cmVwdWJsaWNzJyxcbiAgUldBOiAncndhbmRhJyxcbiAgQkxNOiAnYmFydGgoZXzDqSlsZW15JyxcbiAgU0hOOiAnaGVsZW5hJyxcbiAgS05BOiAna2l0dHN8XFxcXGJuZXZpcycsXG4gIExDQTogJ1xcXFxibHVjaWEnLFxuICBNQUY6ICdeKD89Lipjb2xsZWN0aXZpdHkpLiptYXJ0aW58Xig/PS4qZnJhbmNlKS4qbWFydGluKD8haXF1ZSl8Xig/PS4qZnJlbmNoKS4qbWFydGluKD8haXF1ZSknLFxuICBTUE06ICdtaXF1ZWxvbicsXG4gIFZDVDogJ3ZpbmNlbnQnLFxuICBXU006ICdeKD8hLiphbWVyKS4qc2Ftb2EnLFxuICBTTVI6ICdzYW4uP21hcmlubycsXG4gIFNUUDogJ1xcXFxicyhhfMOjKW8uP3RvbShlfMOpKScsXG4gIFNBVTogJ1xcXFxic2FcXFxcdyouP2FyYWJpYScsXG4gIFNFTjogJ3NlbmVnYWwnLFxuICBTUkI6ICdeKD8hLiptb250ZSkuKnNlcmJpYScsXG4gIFNZQzogJ3NleWNoZWxsJyxcbiAgU0xFOiAnc2llcnJhJyxcbiAgU0dQOiAnc2luZ2Fwb3JlJyxcbiAgU1hNOiAnXig/IS4qbWFydGluKSg/IS4qc2FiYSkuKm1hYXJ0ZW4nLFxuICBTVks6ICdeKD8hLipjemUpLipzbG92YWsnLFxuICBTVk46ICdzbG92ZW5pYScsXG4gIFNMQjogJ3NvbG9tb24nLFxuICBTT006ICdzb21hbGknLFxuICBaQUY6ICdzb3V0aC5hZnJpY2F8c1xcXFxcXFxcLi4/YWZyaWNhJyxcbiAgU0dTOiAnc291dGguP2dlb3JnaWF8c2FuZHdpY2gnLFxuICBTU0Q6ICdcXFxcYnNcXFxcdyouP3N1ZGFuJyxcbiAgRVNQOiAnc3BhaW4nLFxuICBMS0E6ICdzcmkuP2xhbmthfGNleWxvbicsXG4gIFNETjogJ14oPyEuKlxcXFxicyg/IXUpKS4qc3VkYW4nLFxuICBTVVI6ICdzdXJpbmFtfGR1dGNoLj9ndWlhbmEnLFxuICBTSk06ICdzdmFsYmFyZCcsXG4gIFNXWjogJ3N3YXppbGFuZCcsXG4gIFNXRTogJ3N3ZWRlbicsXG4gIENIRTogJ3N3aXR6fHN3aXNzJyxcbiAgU1lSOiAnc3lyaWEnLFxuICBUV046ICd0YWl3YW58dGFpcGVpfGZvcm1vc2F8Xig/IS4qcGVvKSg/PS4qcmVwKS4qY2hpbmEnLFxuICBUSks6ICd0YWppaycsXG4gIFRIQTogJ3RoYWlsYW5kfFxcXFxic2lhbScsXG4gIE1LRDogJ21hY2Vkb25pYXxmeXJvbScsXG4gIFRMUzogJ14oPz0uKmxlc3RlKS4qdGltb3J8Xig/PS4qZWFzdCkuKnRpbW9yJyxcbiAgVEdPOiAndG9nbycsXG4gIFRLTDogJ3Rva2VsYXUnLFxuICBUT046ICd0b25nYScsXG4gIFRUTzogJ3RyaW5pZGFkfHRvYmFnbycsXG4gIFRVTjogJ3R1bmlzaWEnLFxuICBUVVI6ICd0dXJrZXknLFxuICBUS006ICd0dXJrbWVuJyxcbiAgVENBOiAndHVya3MnLFxuICBUVVY6ICd0dXZhbHUnLFxuICBVR0E6ICd1Z2FuZGEnLFxuICBVS1I6ICd1a3JhaW4nLFxuICBBUkU6ICdlbWlyYXRlc3xedVxcXFwuP2FcXFxcLj9lXFxcXC4/JHx1bml0ZWQuP2FyYWIuP2VtJyxcbiAgR0JSOiAndW5pdGVkLj9raW5nZG9tfGJyaXRhaW58XnVcXFxcLj9rXFxcXC4/JCcsXG4gIFRaQTogJ3RhbnphbmlhJyxcbiAgVVNBOiAndW5pdGVkLj9zdGF0ZXNcXFxcYig/IS4qaXNsYW5kcyl8XFxcXGJ1XFxcXC4/c1xcXFwuP2FcXFxcLj9cXFxcYnxeXFxcXHMqdVxcXFwuP3NcXFxcLj9cXFxcYig/IS4qaXNsYW5kcyknLFxuICBVTUk6ICdtaW5vci4/b3V0bHlpbmcuP2lzJyxcbiAgVVJZOiAndXJ1Z3VheScsXG4gIFVaQjogJ3V6YmVrJyxcbiAgVlVUOiAndmFudWF0dXxuZXcuP2hlYnJpZGVzJyxcbiAgVkVOOiAndmVuZXp1ZWxhJyxcbiAgVk5NOiAnXig/IS4qcmVwdWJsaWMpLip2aWV0Lj9uYW18Xig/PS4qc29jaWFsaXN0KS4qdmlldC4/bmFtJyxcbiAgVkdCOiAnXig/PS4qXFxcXGJ1XFxcXC4/XFxcXHM/aykuKnZpcmdpbnxeKD89Lipicml0KS4qdmlyZ2lufF4oPz0uKmtpbmdkb20pLip2aXJnaW4nLFxuICBWSVI6ICdeKD89LipcXFxcYnVcXFxcLj9cXFxccz9zKS4qdmlyZ2lufF4oPz0uKnN0YXRlcykuKnZpcmdpbicsXG4gIFdMRjogJ2Z1dHVuYXx3YWxsaXMnLFxuICBFU0g6ICd3ZXN0ZXJuLnNhaGFyYScsXG4gIFlFTTogJ14oPyEuKmFyYWIpKD8hLipub3J0aCkoPyEuKnNhbmEpKD8hLipwZW8pKD8hLipkZW0pKD8hLipzb3V0aCkoPyEuKmFkZW4pKD8hLipcXFxcYnBcXFxcLj9kXFxcXC4/cikuKnllbWVuJyxcbiAgWU1EOiAnXig/PS4qcGVvKS4qeWVtZW58Xig/IS4qcmVwKSg/PS4qZGVtKS4qeWVtZW58Xig/PS4qc291dGgpLip5ZW1lbnxeKD89LiphZGVuKS4qeWVtZW58Xig/PS4qXFxcXGJwXFxcXC4/ZFxcXFwuP3IpLip5ZW1lbicsXG4gIFlVRzogJ3l1Z29zbGF2aWEnLFxuICBaTUI6ICd6YW1iaWF8bm9ydGhlcm4uP3Job2Rlc2lhJyxcbiAgRUFaOiAnemFuemliYXInLFxuICBaV0U6ICd6aW1iYWJ3ZXxeKD8hLipub3J0aGVybikuKnJob2Rlc2lhJ1xufVxuXG59LHt9XSwxMzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHM9W1xyXG5cdFwieHgtc21hbGxcIixcclxuXHRcIngtc21hbGxcIixcclxuXHRcInNtYWxsXCIsXHJcblx0XCJtZWRpdW1cIixcclxuXHRcImxhcmdlXCIsXHJcblx0XCJ4LWxhcmdlXCIsXHJcblx0XCJ4eC1sYXJnZVwiLFxyXG5cdFwibGFyZ2VyXCIsXHJcblx0XCJzbWFsbGVyXCJcclxuXVxyXG5cbn0se31dLDEzNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cz1bXHJcblx0XCJub3JtYWxcIixcclxuXHRcImNvbmRlbnNlZFwiLFxyXG5cdFwic2VtaS1jb25kZW5zZWRcIixcclxuXHRcImV4dHJhLWNvbmRlbnNlZFwiLFxyXG5cdFwidWx0cmEtY29uZGVuc2VkXCIsXHJcblx0XCJleHBhbmRlZFwiLFxyXG5cdFwic2VtaS1leHBhbmRlZFwiLFxyXG5cdFwiZXh0cmEtZXhwYW5kZWRcIixcclxuXHRcInVsdHJhLWV4cGFuZGVkXCJcclxuXVxyXG5cbn0se31dLDEzNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cz1bXHJcblx0XCJub3JtYWxcIixcclxuXHRcIml0YWxpY1wiLFxyXG5cdFwib2JsaXF1ZVwiXHJcbl1cclxuXG59LHt9XSwxMzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHM9W1xyXG5cdFwibm9ybWFsXCIsXHJcblx0XCJib2xkXCIsXHJcblx0XCJib2xkZXJcIixcclxuXHRcImxpZ2h0ZXJcIixcclxuXHRcIjEwMFwiLFxyXG5cdFwiMjAwXCIsXHJcblx0XCIzMDBcIixcclxuXHRcIjQwMFwiLFxyXG5cdFwiNTAwXCIsXHJcblx0XCI2MDBcIixcclxuXHRcIjcwMFwiLFxyXG5cdFwiODAwXCIsXHJcblx0XCI5MDBcIlxyXG5dXHJcblxufSx7fV0sMTM5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSB7XHJcblx0cGFyc2U6IF9kZXJlcV8oJy4vcGFyc2UnKSxcclxuXHRzdHJpbmdpZnk6IF9kZXJlcV8oJy4vc3RyaW5naWZ5JylcclxufVxyXG5cbn0se1wiLi9wYXJzZVwiOjE0MSxcIi4vc3RyaW5naWZ5XCI6MTQyfV0sMTQwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIHNpemVzID0gX2RlcmVxXygnY3NzLWZvbnQtc2l6ZS1rZXl3b3JkcycpXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHtcclxuXHRpc1NpemU6IGZ1bmN0aW9uIGlzU2l6ZSh2YWx1ZSkge1xyXG5cdFx0cmV0dXJuIC9eW1xcZFxcLl0vLnRlc3QodmFsdWUpXHJcblx0XHRcdHx8IHZhbHVlLmluZGV4T2YoJy8nKSAhPT0gLTFcclxuXHRcdFx0fHwgc2l6ZXMuaW5kZXhPZih2YWx1ZSkgIT09IC0xXHJcblx0fVxyXG59XHJcblxufSx7XCJjc3MtZm9udC1zaXplLWtleXdvcmRzXCI6MTM1fV0sMTQxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIHVucXVvdGUgPSBfZGVyZXFfKCd1bnF1b3RlJylcclxudmFyIGdsb2JhbEtleXdvcmRzID0gX2RlcmVxXygnY3NzLWdsb2JhbC1rZXl3b3JkcycpXHJcbnZhciBzeXN0ZW1Gb250S2V5d29yZHMgPSBfZGVyZXFfKCdjc3Mtc3lzdGVtLWZvbnQta2V5d29yZHMnKVxyXG52YXIgZm9udFdlaWdodEtleXdvcmRzID0gX2RlcmVxXygnY3NzLWZvbnQtd2VpZ2h0LWtleXdvcmRzJylcclxudmFyIGZvbnRTdHlsZUtleXdvcmRzID0gX2RlcmVxXygnY3NzLWZvbnQtc3R5bGUta2V5d29yZHMnKVxyXG52YXIgZm9udFN0cmV0Y2hLZXl3b3JkcyA9IF9kZXJlcV8oJ2Nzcy1mb250LXN0cmV0Y2gta2V5d29yZHMnKVxyXG52YXIgc3BsaXRCeSA9IF9kZXJlcV8oJ3N0cmluZy1zcGxpdC1ieScpXHJcbnZhciBpc1NpemUgPSBfZGVyZXFfKCcuL2xpYi91dGlsJykuaXNTaXplXHJcblxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBwYXJzZUZvbnRcclxuXHJcblxyXG52YXIgY2FjaGUgPSBwYXJzZUZvbnQuY2FjaGUgPSB7fVxyXG5cclxuXHJcbmZ1bmN0aW9uIHBhcnNlRm9udCAodmFsdWUpIHtcclxuXHRpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykgdGhyb3cgbmV3IEVycm9yKCdGb250IGFyZ3VtZW50IG11c3QgYmUgYSBzdHJpbmcuJylcclxuXHJcblx0aWYgKGNhY2hlW3ZhbHVlXSkgcmV0dXJuIGNhY2hlW3ZhbHVlXVxyXG5cclxuXHRpZiAodmFsdWUgPT09ICcnKSB7XHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBwYXJzZSBhbiBlbXB0eSBzdHJpbmcuJylcclxuXHR9XHJcblxyXG5cdGlmIChzeXN0ZW1Gb250S2V5d29yZHMuaW5kZXhPZih2YWx1ZSkgIT09IC0xKSB7XHJcblx0XHRyZXR1cm4gY2FjaGVbdmFsdWVdID0ge3N5c3RlbTogdmFsdWV9XHJcblx0fVxyXG5cclxuXHR2YXIgZm9udCA9IHtcclxuXHRcdHN0eWxlOiAnbm9ybWFsJyxcclxuXHRcdHZhcmlhbnQ6ICdub3JtYWwnLFxyXG5cdFx0d2VpZ2h0OiAnbm9ybWFsJyxcclxuXHRcdHN0cmV0Y2g6ICdub3JtYWwnLFxyXG5cdFx0bGluZUhlaWdodDogJ25vcm1hbCcsXHJcblx0XHRzaXplOiAnMXJlbScsXHJcblx0XHRmYW1pbHk6IFsnc2VyaWYnXVxyXG5cdH1cclxuXHJcblx0dmFyIHRva2VucyA9IHNwbGl0QnkodmFsdWUsIC9cXHMrLylcclxuXHR2YXIgdG9rZW5cclxuXHJcblx0d2hpbGUgKHRva2VuID0gdG9rZW5zLnNoaWZ0KCkpIHtcclxuXHRcdGlmIChnbG9iYWxLZXl3b3Jkcy5pbmRleE9mKHRva2VuKSAhPT0gLTEpIHtcclxuXHRcdFx0WydzdHlsZScsICd2YXJpYW50JywgJ3dlaWdodCcsICdzdHJldGNoJ10uZm9yRWFjaChmdW5jdGlvbihwcm9wKSB7XHJcblx0XHRcdFx0Zm9udFtwcm9wXSA9IHRva2VuXHJcblx0XHRcdH0pXHJcblxyXG5cdFx0XHRyZXR1cm4gY2FjaGVbdmFsdWVdID0gZm9udFxyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChmb250U3R5bGVLZXl3b3Jkcy5pbmRleE9mKHRva2VuKSAhPT0gLTEpIHtcclxuXHRcdFx0Zm9udC5zdHlsZSA9IHRva2VuXHJcblx0XHRcdGNvbnRpbnVlXHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHRva2VuID09PSAnbm9ybWFsJyB8fCB0b2tlbiA9PT0gJ3NtYWxsLWNhcHMnKSB7XHJcblx0XHRcdGZvbnQudmFyaWFudCA9IHRva2VuXHJcblx0XHRcdGNvbnRpbnVlXHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGZvbnRTdHJldGNoS2V5d29yZHMuaW5kZXhPZih0b2tlbikgIT09IC0xKSB7XHJcblx0XHRcdGZvbnQuc3RyZXRjaCA9IHRva2VuXHJcblx0XHRcdGNvbnRpbnVlXHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGZvbnRXZWlnaHRLZXl3b3Jkcy5pbmRleE9mKHRva2VuKSAhPT0gLTEpIHtcclxuXHRcdFx0Zm9udC53ZWlnaHQgPSB0b2tlblxyXG5cdFx0XHRjb250aW51ZVxyXG5cdFx0fVxyXG5cclxuXHJcblx0XHRpZiAoaXNTaXplKHRva2VuKSkge1xyXG5cdFx0XHR2YXIgcGFydHMgPSBzcGxpdEJ5KHRva2VuLCAnLycpXHJcblx0XHRcdGZvbnQuc2l6ZSA9IHBhcnRzWzBdXHJcblx0XHRcdGlmIChwYXJ0c1sxXSAhPSBudWxsKSB7XHJcblx0XHRcdFx0Zm9udC5saW5lSGVpZ2h0ID0gcGFyc2VMaW5lSGVpZ2h0KHBhcnRzWzFdKVxyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2UgaWYgKHRva2Vuc1swXSA9PT0gJy8nKSB7XHJcblx0XHRcdFx0dG9rZW5zLnNoaWZ0KClcclxuXHRcdFx0XHRmb250LmxpbmVIZWlnaHQgPSBwYXJzZUxpbmVIZWlnaHQodG9rZW5zLnNoaWZ0KCkpXHJcbiBcdFx0XHR9XHJcblxyXG5cdFx0XHRpZiAoIXRva2Vucy5sZW5ndGgpIHtcclxuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgZm9udC1mYW1pbHkuJylcclxuXHRcdFx0fVxyXG5cdFx0XHRmb250LmZhbWlseSA9IHNwbGl0QnkodG9rZW5zLmpvaW4oJyAnKSwgL1xccyosXFxzKi8pLm1hcCh1bnF1b3RlKVxyXG5cclxuXHRcdFx0cmV0dXJuIGNhY2hlW3ZhbHVlXSA9IGZvbnRcclxuXHRcdH1cclxuXHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gb3IgdW5zdXBwb3J0ZWQgZm9udCB0b2tlbjogJyArIHRva2VuKVxyXG5cdH1cclxuXHJcblx0dGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIGZvbnQtc2l6ZS4nKVxyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gcGFyc2VMaW5lSGVpZ2h0KHZhbHVlKSB7XHJcblx0dmFyIHBhcnNlZCA9IHBhcnNlRmxvYXQodmFsdWUpXHJcblx0aWYgKHBhcnNlZC50b1N0cmluZygpID09PSB2YWx1ZSkge1xyXG5cdFx0cmV0dXJuIHBhcnNlZFxyXG5cdH1cclxuXHRyZXR1cm4gdmFsdWVcclxufVxyXG5cbn0se1wiLi9saWIvdXRpbFwiOjE0MCxcImNzcy1mb250LXN0cmV0Y2gta2V5d29yZHNcIjoxMzYsXCJjc3MtZm9udC1zdHlsZS1rZXl3b3Jkc1wiOjEzNyxcImNzcy1mb250LXdlaWdodC1rZXl3b3Jkc1wiOjEzOCxcImNzcy1nbG9iYWwta2V5d29yZHNcIjoxNDMsXCJjc3Mtc3lzdGVtLWZvbnQta2V5d29yZHNcIjoxNDQsXCJzdHJpbmctc3BsaXQtYnlcIjo1MjksXCJ1bnF1b3RlXCI6NTQ4fV0sMTQyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIHBpY2sgPSBfZGVyZXFfKCdwaWNrLWJ5LWFsaWFzJylcclxudmFyIGlzU2l6ZSA9IF9kZXJlcV8oJy4vbGliL3V0aWwnKS5pc1NpemVcclxuXHJcbnZhciBnbG9iYWxzID0gYTJvKF9kZXJlcV8oJ2Nzcy1nbG9iYWwta2V5d29yZHMnKSlcclxudmFyIHN5c3RlbXMgPSBhMm8oX2RlcmVxXygnY3NzLXN5c3RlbS1mb250LWtleXdvcmRzJykpXHJcbnZhciB3ZWlnaHRzID0gYTJvKF9kZXJlcV8oJ2Nzcy1mb250LXdlaWdodC1rZXl3b3JkcycpKVxyXG52YXIgc3R5bGVzID0gYTJvKF9kZXJlcV8oJ2Nzcy1mb250LXN0eWxlLWtleXdvcmRzJykpXHJcbnZhciBzdHJldGNoZXMgPSBhMm8oX2RlcmVxXygnY3NzLWZvbnQtc3RyZXRjaC1rZXl3b3JkcycpKVxyXG5cclxudmFyIHZhcmlhbnRzID0geydub3JtYWwnOiAxLCAnc21hbGwtY2Fwcyc6IDF9XHJcbnZhciBmYW1zID0ge1xyXG5cdCdzZXJpZic6IDEsXHJcblx0J3NhbnMtc2VyaWYnOiAxLFxyXG5cdCdtb25vc3BhY2UnOiAxLFxyXG5cdCdjdXJzaXZlJzogMSxcclxuXHQnZmFudGFzeSc6IDEsXHJcblx0J3N5c3RlbS11aSc6IDFcclxufVxyXG5cclxudmFyIGRlZmF1bHRzID0ge1xyXG5cdHN0eWxlOiAnbm9ybWFsJyxcclxuXHR2YXJpYW50OiAnbm9ybWFsJyxcclxuXHR3ZWlnaHQ6ICdub3JtYWwnLFxyXG5cdHN0cmV0Y2g6ICdub3JtYWwnLFxyXG5cdHNpemU6ICcxcmVtJyxcclxuXHRsaW5lSGVpZ2h0OiAnbm9ybWFsJyxcclxuXHRmYW1pbHk6ICdzZXJpZidcclxufVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHJpbmdpZnlGb250IChvKSB7XHJcblx0byA9IHBpY2sobywge1xyXG5cdFx0c3R5bGU6ICdzdHlsZSBmb250c3R5bGUgZm9udFN0eWxlIGZvbnQtc3R5bGUgc2xvcGUgZGlzdGluY3Rpb24nLFxyXG5cdFx0dmFyaWFudDogJ3ZhcmlhbnQgZm9udC12YXJpYW50IGZvbnRWYXJpYW50IGZvbnR2YXJpYW50IHZhciBjYXBpdGFsaXphdGlvbicsXHJcblx0XHR3ZWlnaHQ6ICd3ZWlnaHQgdyBmb250LXdlaWdodCBmb250V2VpZ2h0IGZvbnR3ZWlnaHQnLFxyXG5cdFx0c3RyZXRjaDogJ3N0cmV0Y2ggZm9udC1zdHJldGNoIGZvbnRTdHJldGNoIGZvbnRzdHJldGNoIHdpZHRoJyxcclxuXHRcdHNpemU6ICdzaXplIHMgZm9udC1zaXplIGZvbnRTaXplIGZvbnRzaXplIGhlaWdodCBlbSBlbVNpemUnLFxyXG5cdFx0bGluZUhlaWdodDogJ2xoIGxpbmUtaGVpZ2h0IGxpbmVIZWlnaHQgbGluZWhlaWdodCBsZWFkaW5nJyxcclxuXHRcdGZhbWlseTogJ2ZvbnQgZmFtaWx5IGZvbnRGYW1pbHkgZm9udC1mYW1pbHkgZm9udGZhbWlseSB0eXBlIHR5cGVmYWNlIGZhY2UnLFxyXG5cdFx0c3lzdGVtOiAnc3lzdGVtIHJlc2VydmVkIGRlZmF1bHQgZ2xvYmFsJyxcclxuXHR9KVxyXG5cclxuXHRpZiAoby5zeXN0ZW0pIHtcclxuXHRcdGlmIChvLnN5c3RlbSkgdmVyaWZ5KG8uc3lzdGVtLCBzeXN0ZW1zKVxyXG5cdFx0cmV0dXJuIG8uc3lzdGVtXHJcblx0fVxyXG5cclxuXHR2ZXJpZnkoby5zdHlsZSwgc3R5bGVzKVxyXG5cdHZlcmlmeShvLnZhcmlhbnQsIHZhcmlhbnRzKVxyXG5cdHZlcmlmeShvLndlaWdodCwgd2VpZ2h0cylcclxuXHR2ZXJpZnkoby5zdHJldGNoLCBzdHJldGNoZXMpXHJcblxyXG5cdC8vIGRlZmF1bHQgcm9vdCB2YWx1ZSBpcyBtZWRpdW0sIGJ1dCBieSBkZWZhdWx0IGl0J3MgaW5oZXJpdGVkXHJcblx0aWYgKG8uc2l6ZSA9PSBudWxsKSBvLnNpemUgPSBkZWZhdWx0cy5zaXplXHJcblx0aWYgKHR5cGVvZiBvLnNpemUgPT09ICdudW1iZXInKSBvLnNpemUgKz0gJ3B4J1xyXG5cclxuXHRpZiAoIWlzU2l6ZSkgdGhyb3cgRXJyb3IoJ0JhZCBzaXplIHZhbHVlIGAnICsgby5zaXplICsgJ2AnKVxyXG5cclxuXHQvLyBtYW55IHVzZXItYWdlbnRzIHVzZSBzZXJpZiwgd2UgZG9uJ3QgZGV0ZWN0IHRoYXQgZm9yIGNvbnNpc3RlbmN5XHJcblx0aWYgKCFvLmZhbWlseSkgby5mYW1pbHkgPSBkZWZhdWx0cy5mYW1pbHlcclxuXHRpZiAoQXJyYXkuaXNBcnJheShvLmZhbWlseSkpIHtcclxuXHRcdGlmICghby5mYW1pbHkubGVuZ3RoKSBvLmZhbWlseSA9IFtkZWZhdWx0cy5mYW1pbHldXHJcblx0XHRvLmZhbWlseSA9IG8uZmFtaWx5Lm1hcChmdW5jdGlvbiAoZikge1xyXG5cdFx0XHRyZXR1cm4gZmFtc1tmXSA/IGYgOiAnXCInICsgZiArICdcIidcclxuXHRcdH0pLmpvaW4oJywgJylcclxuXHR9XHJcblxyXG5cdC8vIFsgWyA8J2ZvbnQtc3R5bGUnPiB8fCA8Zm9udC12YXJpYW50LWNzczIxPiB8fCA8J2ZvbnQtd2VpZ2h0Jz4gfHwgPCdmb250LXN0cmV0Y2gnPiBdPyA8J2ZvbnQtc2l6ZSc+IFsgLyA8J2xpbmUtaGVpZ2h0Jz4gXT8gPCdmb250LWZhbWlseSc+IF1cclxuXHR2YXIgcmVzdWx0ID0gW11cclxuXHJcblx0cmVzdWx0LnB1c2goby5zdHlsZSlcclxuXHRpZiAoby52YXJpYW50ICE9PSBvLnN0eWxlKSByZXN1bHQucHVzaChvLnZhcmlhbnQpXHJcblxyXG5cdGlmIChvLndlaWdodCAhPT0gby52YXJpYW50ICYmXHJcblx0XHRvLndlaWdodCAhPT0gby5zdHlsZSkgcmVzdWx0LnB1c2goby53ZWlnaHQpXHJcblxyXG5cdGlmIChvLnN0cmV0Y2ggIT09IG8ud2VpZ2h0ICYmXHJcblx0XHRvLnN0cmV0Y2ggIT09IG8udmFyaWFudCAmJlxyXG5cdFx0by5zdHJldGNoICE9PSBvLnN0eWxlKSByZXN1bHQucHVzaChvLnN0cmV0Y2gpXHJcblxyXG5cdHJlc3VsdC5wdXNoKG8uc2l6ZSArIChvLmxpbmVIZWlnaHQgPT0gbnVsbCB8fCBvLmxpbmVIZWlnaHQgPT09ICdub3JtYWwnIHx8IChvLmxpbmVIZWlnaHQgKyAnJyA9PT0gJzEnKSAgPyAnJyA6ICgnLycgKyBvLmxpbmVIZWlnaHQpKSlcclxuXHRyZXN1bHQucHVzaChvLmZhbWlseSlcclxuXHJcblx0cmV0dXJuIHJlc3VsdC5maWx0ZXIoQm9vbGVhbikuam9pbignICcpXHJcbn1cclxuXHJcbmZ1bmN0aW9uIHZlcmlmeSAodmFsdWUsIHZhbHVlcykge1xyXG5cdGlmICh2YWx1ZSAmJiAhdmFsdWVzW3ZhbHVlXSAmJiAhZ2xvYmFsc1t2YWx1ZV0pIHRocm93IEVycm9yKCdVbmtub3duIGtleXdvcmQgYCcgKyB2YWx1ZSArJ2AnKVxyXG5cclxuXHRyZXR1cm4gdmFsdWVcclxufVxyXG5cclxuXHJcbi8vIFsnYScsICdiJ10gLT4ge2E6IHRydWUsIGI6IHRydWV9XHJcbmZ1bmN0aW9uIGEybyAoYSkge1xyXG5cdHZhciBvID0ge31cclxuXHRmb3IgKHZhciBpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcclxuXHRcdG9bYVtpXV0gPSAxXHJcblx0fVxyXG5cdHJldHVybiBvXHJcbn1cclxuXG59LHtcIi4vbGliL3V0aWxcIjoxNDAsXCJjc3MtZm9udC1zdHJldGNoLWtleXdvcmRzXCI6MTM2LFwiY3NzLWZvbnQtc3R5bGUta2V5d29yZHNcIjoxMzcsXCJjc3MtZm9udC13ZWlnaHQta2V5d29yZHNcIjoxMzgsXCJjc3MtZ2xvYmFsLWtleXdvcmRzXCI6MTQzLFwiY3NzLXN5c3RlbS1mb250LWtleXdvcmRzXCI6MTQ0LFwicGljay1ieS1hbGlhc1wiOjQ2NX1dLDE0MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cz1bXHJcblx0XCJpbmhlcml0XCIsXHJcblx0XCJpbml0aWFsXCIsXHJcblx0XCJ1bnNldFwiXHJcbl1cclxuXG59LHt9XSwxNDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHM9W1xyXG5cdFwiY2FwdGlvblwiLFxyXG5cdFwiaWNvblwiLFxyXG5cdFwibWVudVwiLFxyXG5cdFwibWVzc2FnZS1ib3hcIixcclxuXHRcInNtYWxsLWNhcHRpb25cIixcclxuXHRcInN0YXR1cy1iYXJcIlxyXG5dXHJcblxufSx7fV0sMTQ1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbmZ1bmN0aW9uIGRjdWJpY0hlcm1pdGUocDAsIHYwLCBwMSwgdjEsIHQsIGYpIHtcbiAgdmFyIGRoMDAgPSA2KnQqdC02KnQsXG4gICAgICBkaDEwID0gMyp0KnQtNCp0ICsgMSxcbiAgICAgIGRoMDEgPSAtNip0KnQrNip0LFxuICAgICAgZGgxMSA9IDMqdCp0LTIqdFxuICBpZihwMC5sZW5ndGgpIHtcbiAgICBpZighZikge1xuICAgICAgZiA9IG5ldyBBcnJheShwMC5sZW5ndGgpXG4gICAgfVxuICAgIGZvcih2YXIgaT1wMC5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgICBmW2ldID0gZGgwMCpwMFtpXSArIGRoMTAqdjBbaV0gKyBkaDAxKnAxW2ldICsgZGgxMSp2MVtpXVxuICAgIH1cbiAgICByZXR1cm4gZlxuICB9XG4gIHJldHVybiBkaDAwKnAwICsgZGgxMCp2MCArIGRoMDEqcDFbaV0gKyBkaDExKnYxXG59XG5cbmZ1bmN0aW9uIGN1YmljSGVybWl0ZShwMCwgdjAsIHAxLCB2MSwgdCwgZikge1xuICB2YXIgdGkgID0gKHQtMSksIHQyID0gdCp0LCB0aTIgPSB0aSp0aSxcbiAgICAgIGgwMCA9ICgxKzIqdCkqdGkyLFxuICAgICAgaDEwID0gdCp0aTIsXG4gICAgICBoMDEgPSB0MiooMy0yKnQpLFxuICAgICAgaDExID0gdDIqdGlcbiAgaWYocDAubGVuZ3RoKSB7XG4gICAgaWYoIWYpIHtcbiAgICAgIGYgPSBuZXcgQXJyYXkocDAubGVuZ3RoKVxuICAgIH1cbiAgICBmb3IodmFyIGk9cDAubGVuZ3RoLTE7IGk+PTA7IC0taSkge1xuICAgICAgZltpXSA9IGgwMCpwMFtpXSArIGgxMCp2MFtpXSArIGgwMSpwMVtpXSArIGgxMSp2MVtpXVxuICAgIH1cbiAgICByZXR1cm4gZlxuICB9XG4gIHJldHVybiBoMDAqcDAgKyBoMTAqdjAgKyBoMDEqcDEgKyBoMTEqdjFcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjdWJpY0hlcm1pdGVcbm1vZHVsZS5leHBvcnRzLmRlcml2YXRpdmUgPSBkY3ViaWNIZXJtaXRlXG59LHt9XSwxNDY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxudmFyIGNyZWF0ZVRodW5rID0gX2RlcmVxXyhcIi4vbGliL3RodW5rLmpzXCIpXG5cbmZ1bmN0aW9uIFByb2NlZHVyZSgpIHtcbiAgdGhpcy5hcmdUeXBlcyA9IFtdXG4gIHRoaXMuc2hpbUFyZ3MgPSBbXVxuICB0aGlzLmFycmF5QXJncyA9IFtdXG4gIHRoaXMuYXJyYXlCbG9ja0luZGljZXMgPSBbXVxuICB0aGlzLnNjYWxhckFyZ3MgPSBbXVxuICB0aGlzLm9mZnNldEFyZ3MgPSBbXVxuICB0aGlzLm9mZnNldEFyZ0luZGV4ID0gW11cbiAgdGhpcy5pbmRleEFyZ3MgPSBbXVxuICB0aGlzLnNoYXBlQXJncyA9IFtdXG4gIHRoaXMuZnVuY05hbWUgPSBcIlwiXG4gIHRoaXMucHJlID0gbnVsbFxuICB0aGlzLmJvZHkgPSBudWxsXG4gIHRoaXMucG9zdCA9IG51bGxcbiAgdGhpcy5kZWJ1ZyA9IGZhbHNlXG59XG5cbmZ1bmN0aW9uIGNvbXBpbGVDd2lzZSh1c2VyX2FyZ3MpIHtcbiAgLy9DcmVhdGUgcHJvY2VkdXJlXG4gIHZhciBwcm9jID0gbmV3IFByb2NlZHVyZSgpXG4gIFxuICAvL1BhcnNlIGJsb2Nrc1xuICBwcm9jLnByZSAgICA9IHVzZXJfYXJncy5wcmVcbiAgcHJvYy5ib2R5ICAgPSB1c2VyX2FyZ3MuYm9keVxuICBwcm9jLnBvc3QgICA9IHVzZXJfYXJncy5wb3N0XG5cbiAgLy9QYXJzZSBhcmd1bWVudHNcbiAgdmFyIHByb2NfYXJncyA9IHVzZXJfYXJncy5hcmdzLnNsaWNlKDApXG4gIHByb2MuYXJnVHlwZXMgPSBwcm9jX2FyZ3NcbiAgZm9yKHZhciBpPTA7IGk8cHJvY19hcmdzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGFyZ190eXBlID0gcHJvY19hcmdzW2ldXG4gICAgaWYoYXJnX3R5cGUgPT09IFwiYXJyYXlcIiB8fCAodHlwZW9mIGFyZ190eXBlID09PSBcIm9iamVjdFwiICYmIGFyZ190eXBlLmJsb2NrSW5kaWNlcykpIHtcbiAgICAgIHByb2MuYXJnVHlwZXNbaV0gPSBcImFycmF5XCJcbiAgICAgIHByb2MuYXJyYXlBcmdzLnB1c2goaSlcbiAgICAgIHByb2MuYXJyYXlCbG9ja0luZGljZXMucHVzaChhcmdfdHlwZS5ibG9ja0luZGljZXMgPyBhcmdfdHlwZS5ibG9ja0luZGljZXMgOiAwKVxuICAgICAgcHJvYy5zaGltQXJncy5wdXNoKFwiYXJyYXlcIiArIGkpXG4gICAgICBpZihpIDwgcHJvYy5wcmUuYXJncy5sZW5ndGggJiYgcHJvYy5wcmUuYXJnc1tpXS5jb3VudD4wKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBwcmUoKSBibG9jayBtYXkgbm90IHJlZmVyZW5jZSBhcnJheSBhcmdzXCIpXG4gICAgICB9XG4gICAgICBpZihpIDwgcHJvYy5wb3N0LmFyZ3MubGVuZ3RoICYmIHByb2MucG9zdC5hcmdzW2ldLmNvdW50PjApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY3dpc2U6IHBvc3QoKSBibG9jayBtYXkgbm90IHJlZmVyZW5jZSBhcnJheSBhcmdzXCIpXG4gICAgICB9XG4gICAgfSBlbHNlIGlmKGFyZ190eXBlID09PSBcInNjYWxhclwiKSB7XG4gICAgICBwcm9jLnNjYWxhckFyZ3MucHVzaChpKVxuICAgICAgcHJvYy5zaGltQXJncy5wdXNoKFwic2NhbGFyXCIgKyBpKVxuICAgIH0gZWxzZSBpZihhcmdfdHlwZSA9PT0gXCJpbmRleFwiKSB7XG4gICAgICBwcm9jLmluZGV4QXJncy5wdXNoKGkpXG4gICAgICBpZihpIDwgcHJvYy5wcmUuYXJncy5sZW5ndGggJiYgcHJvYy5wcmUuYXJnc1tpXS5jb3VudCA+IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY3dpc2U6IHByZSgpIGJsb2NrIG1heSBub3QgcmVmZXJlbmNlIGFycmF5IGluZGV4XCIpXG4gICAgICB9XG4gICAgICBpZihpIDwgcHJvYy5ib2R5LmFyZ3MubGVuZ3RoICYmIHByb2MuYm9keS5hcmdzW2ldLmx2YWx1ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogYm9keSgpIGJsb2NrIG1heSBub3Qgd3JpdGUgdG8gYXJyYXkgaW5kZXhcIilcbiAgICAgIH1cbiAgICAgIGlmKGkgPCBwcm9jLnBvc3QuYXJncy5sZW5ndGggJiYgcHJvYy5wb3N0LmFyZ3NbaV0uY291bnQgPiAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBwb3N0KCkgYmxvY2sgbWF5IG5vdCByZWZlcmVuY2UgYXJyYXkgaW5kZXhcIilcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYoYXJnX3R5cGUgPT09IFwic2hhcGVcIikge1xuICAgICAgcHJvYy5zaGFwZUFyZ3MucHVzaChpKVxuICAgICAgaWYoaSA8IHByb2MucHJlLmFyZ3MubGVuZ3RoICYmIHByb2MucHJlLmFyZ3NbaV0ubHZhbHVlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBwcmUoKSBibG9jayBtYXkgbm90IHdyaXRlIHRvIGFycmF5IHNoYXBlXCIpXG4gICAgICB9XG4gICAgICBpZihpIDwgcHJvYy5ib2R5LmFyZ3MubGVuZ3RoICYmIHByb2MuYm9keS5hcmdzW2ldLmx2YWx1ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogYm9keSgpIGJsb2NrIG1heSBub3Qgd3JpdGUgdG8gYXJyYXkgc2hhcGVcIilcbiAgICAgIH1cbiAgICAgIGlmKGkgPCBwcm9jLnBvc3QuYXJncy5sZW5ndGggJiYgcHJvYy5wb3N0LmFyZ3NbaV0ubHZhbHVlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcImN3aXNlOiBwb3N0KCkgYmxvY2sgbWF5IG5vdCB3cml0ZSB0byBhcnJheSBzaGFwZVwiKVxuICAgICAgfVxuICAgIH0gZWxzZSBpZih0eXBlb2YgYXJnX3R5cGUgPT09IFwib2JqZWN0XCIgJiYgYXJnX3R5cGUub2Zmc2V0KSB7XG4gICAgICBwcm9jLmFyZ1R5cGVzW2ldID0gXCJvZmZzZXRcIlxuICAgICAgcHJvYy5vZmZzZXRBcmdzLnB1c2goeyBhcnJheTogYXJnX3R5cGUuYXJyYXksIG9mZnNldDphcmdfdHlwZS5vZmZzZXQgfSlcbiAgICAgIHByb2Mub2Zmc2V0QXJnSW5kZXgucHVzaChpKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogVW5rbm93biBhcmd1bWVudCB0eXBlIFwiICsgcHJvY19hcmdzW2ldKVxuICAgIH1cbiAgfVxuICBcbiAgLy9NYWtlIHN1cmUgYXQgbGVhc3Qgb25lIGFycmF5IGFyZ3VtZW50IHdhcyBzcGVjaWZpZWRcbiAgaWYocHJvYy5hcnJheUFyZ3MubGVuZ3RoIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogTm8gYXJyYXkgYXJndW1lbnRzIHNwZWNpZmllZFwiKVxuICB9XG4gIFxuICAvL01ha2Ugc3VyZSBhcmd1bWVudHMgYXJlIGNvcnJlY3RcbiAgaWYocHJvYy5wcmUuYXJncy5sZW5ndGggPiBwcm9jX2FyZ3MubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY3dpc2U6IFRvbyBtYW55IGFyZ3VtZW50cyBpbiBwcmUoKSBibG9ja1wiKVxuICB9XG4gIGlmKHByb2MuYm9keS5hcmdzLmxlbmd0aCA+IHByb2NfYXJncy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogVG9vIG1hbnkgYXJndW1lbnRzIGluIGJvZHkoKSBibG9ja1wiKVxuICB9XG4gIGlmKHByb2MucG9zdC5hcmdzLmxlbmd0aCA+IHByb2NfYXJncy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogVG9vIG1hbnkgYXJndW1lbnRzIGluIHBvc3QoKSBibG9ja1wiKVxuICB9XG5cbiAgLy9DaGVjayBkZWJ1ZyBmbGFnXG4gIHByb2MuZGVidWcgPSAhIXVzZXJfYXJncy5wcmludENvZGUgfHwgISF1c2VyX2FyZ3MuZGVidWdcbiAgXG4gIC8vUmV0cmlldmUgbmFtZVxuICBwcm9jLmZ1bmNOYW1lID0gdXNlcl9hcmdzLmZ1bmNOYW1lIHx8IFwiY3dpc2VcIlxuICBcbiAgLy9SZWFkIGluIGJsb2NrIHNpemVcbiAgcHJvYy5ibG9ja1NpemUgPSB1c2VyX2FyZ3MuYmxvY2tTaXplIHx8IDY0XG5cbiAgcmV0dXJuIGNyZWF0ZVRodW5rKHByb2MpXG59XG5cbm1vZHVsZS5leHBvcnRzID0gY29tcGlsZUN3aXNlXG5cbn0se1wiLi9saWIvdGh1bmsuanNcIjoxNDh9XSwxNDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxudmFyIHVuaXEgPSBfZGVyZXFfKFwidW5pcVwiKVxuXG4vLyBUaGlzIGZ1bmN0aW9uIGdlbmVyYXRlcyB2ZXJ5IHNpbXBsZSBsb29wcyBhbmFsb2dvdXMgdG8gaG93IHlvdSB0eXBpY2FsbHkgdHJhdmVyc2UgYXJyYXlzICh0aGUgb3V0ZXJtb3N0IGxvb3AgY29ycmVzcG9uZHMgdG8gdGhlIHNsb3dlc3QgY2hhbmdpbmcgaW5kZXgsIHRoZSBpbm5lcm1vc3QgbG9vcCB0byB0aGUgZmFzdGVzdCBjaGFuZ2luZyBpbmRleClcbi8vIFRPRE86IElmIHR3byBhcnJheXMgaGF2ZSB0aGUgc2FtZSBzdHJpZGVzIChhbmQgb2Zmc2V0cykgdGhlcmUgaXMgcG90ZW50aWFsIGZvciBkZWNyZWFzaW5nIHRoZSBudW1iZXIgb2YgXCJwb2ludGVyc1wiIGFuZCByZWxhdGVkIHZhcmlhYmxlcy4gVGhlIGRyYXdiYWNrIGlzIHRoYXQgdGhlIHR5cGUgc2lnbmF0dXJlIHdvdWxkIGJlY29tZSBtb3JlIHNwZWNpZmljIGFuZCB0aGF0IHRoZXJlIHdvdWxkIHRodXMgYmUgbGVzcyBwb3RlbnRpYWwgZm9yIGNhY2hpbmcsIGJ1dCBpdCBtaWdodCBzdGlsbCBiZSB3b3J0aCBpdCwgZXNwZWNpYWxseSB3aGVuIGRlYWxpbmcgd2l0aCBsYXJnZSBudW1iZXJzIG9mIGFyZ3VtZW50cy5cbmZ1bmN0aW9uIGlubmVyRmlsbChvcmRlciwgcHJvYywgYm9keSkge1xuICB2YXIgZGltZW5zaW9uID0gb3JkZXIubGVuZ3RoXG4gICAgLCBuYXJncyA9IHByb2MuYXJyYXlBcmdzLmxlbmd0aFxuICAgICwgaGFzX2luZGV4ID0gcHJvYy5pbmRleEFyZ3MubGVuZ3RoPjBcbiAgICAsIGNvZGUgPSBbXVxuICAgICwgdmFycyA9IFtdXG4gICAgLCBpZHg9MCwgcGlkeD0wLCBpLCBqXG4gIGZvcihpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHsgLy8gSXRlcmF0aW9uIHZhcmlhYmxlc1xuICAgIHZhcnMucHVzaChbXCJpXCIsaSxcIj0wXCJdLmpvaW4oXCJcIikpXG4gIH1cbiAgLy9Db21wdXRlIHNjYW4gZGVsdGFzXG4gIGZvcihqPTA7IGo8bmFyZ3M7ICsraikge1xuICAgIGZvcihpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICAgIHBpZHggPSBpZHhcbiAgICAgIGlkeCA9IG9yZGVyW2ldXG4gICAgICBpZihpID09PSAwKSB7IC8vIFRoZSBpbm5lcm1vc3QvZmFzdGVzdCBkaW1lbnNpb24ncyBkZWx0YSBpcyBzaW1wbHkgaXRzIHN0cmlkZVxuICAgICAgICB2YXJzLnB1c2goW1wiZFwiLGosXCJzXCIsaSxcIj10XCIsaixcInBcIixpZHhdLmpvaW4oXCJcIikpXG4gICAgICB9IGVsc2UgeyAvLyBGb3Igb3RoZXIgZGltZW5zaW9ucyB0aGUgZGVsdGEgaXMgYmFzaWNhbGx5IHRoZSBzdHJpZGUgbWludXMgc29tZXRoaW5nIHdoaWNoIGVzc2VudGlhbGx5IFwicmV3aW5kc1wiIHRoZSBwcmV2aW91cyAobW9yZSBpbm5lcikgZGltZW5zaW9uXG4gICAgICAgIHZhcnMucHVzaChbXCJkXCIsaixcInNcIixpLFwiPSh0XCIsaixcInBcIixpZHgsXCItc1wiLHBpZHgsXCIqdFwiLGosXCJwXCIscGlkeCxcIilcIl0uam9pbihcIlwiKSlcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgaWYgKHZhcnMubGVuZ3RoID4gMCkge1xuICAgIGNvZGUucHVzaChcInZhciBcIiArIHZhcnMuam9pbihcIixcIikpXG4gIH0gIFxuICAvL1NjYW4gbG9vcFxuICBmb3IoaT1kaW1lbnNpb24tMTsgaT49MDsgLS1pKSB7IC8vIFN0YXJ0IGF0IGxhcmdlc3Qgc3RyaWRlIGFuZCB3b3JrIHlvdXIgd2F5IGlud2FyZHNcbiAgICBpZHggPSBvcmRlcltpXVxuICAgIGNvZGUucHVzaChbXCJmb3IoaVwiLGksXCI9MDtpXCIsaSxcIjxzXCIsaWR4LFwiOysraVwiLGksXCIpe1wiXS5qb2luKFwiXCIpKVxuICB9XG4gIC8vUHVzaCBib2R5IG9mIGlubmVyIGxvb3BcbiAgY29kZS5wdXNoKGJvZHkpXG4gIC8vQWR2YW5jZSBzY2FuIHBvaW50ZXJzXG4gIGZvcihpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBwaWR4ID0gaWR4XG4gICAgaWR4ID0gb3JkZXJbaV1cbiAgICBmb3Ioaj0wOyBqPG5hcmdzOyArK2opIHtcbiAgICAgIGNvZGUucHVzaChbXCJwXCIsaixcIis9ZFwiLGosXCJzXCIsaV0uam9pbihcIlwiKSlcbiAgICB9XG4gICAgaWYoaGFzX2luZGV4KSB7XG4gICAgICBpZihpID4gMCkge1xuICAgICAgICBjb2RlLnB1c2goW1wiaW5kZXhbXCIscGlkeCxcIl0tPXNcIixwaWR4XS5qb2luKFwiXCIpKVxuICAgICAgfVxuICAgICAgY29kZS5wdXNoKFtcIisraW5kZXhbXCIsaWR4LFwiXVwiXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgICBjb2RlLnB1c2goXCJ9XCIpXG4gIH1cbiAgcmV0dXJuIGNvZGUuam9pbihcIlxcblwiKVxufVxuXG4vLyBHZW5lcmF0ZSBcIm91dGVyXCIgbG9vcHMgdGhhdCBsb29wIG92ZXIgYmxvY2tzIG9mIGRhdGEsIGFwcGx5aW5nIFwiaW5uZXJcIiBsb29wcyB0byB0aGUgYmxvY2tzIGJ5IG1hbmlwdWxhdGluZyB0aGUgbG9jYWwgdmFyaWFibGVzIGluIHN1Y2ggYSB3YXkgdGhhdCB0aGUgaW5uZXIgbG9vcCBvbmx5IFwic2Vlc1wiIHRoZSBjdXJyZW50IGJsb2NrLlxuLy8gVE9ETzogSWYgdGhpcyBpcyB1c2VkLCB0aGVuIHRoZSBwcmV2aW91cyBkZWNsYXJhdGlvbiAoZG9uZSBieSBnZW5lcmF0ZUN3aXNlT3ApIG9mIHMqIGlzIGVzc2VudGlhbGx5IHVubmVjZXNzYXJ5LlxuLy8gICAgICAgSSBiZWxpZXZlIHRoZSBzKiBhcmUgbm90IHVzZWQgZWxzZXdoZXJlIChpbiBwYXJ0aWN1bGFyLCBJIGRvbid0IHRoaW5rIHRoZXkncmUgdXNlZCBpbiB0aGUgcHJlL3Bvc3QgcGFydHMgYW5kIFwic2hhcGVcIiBpcyBkZWZpbmVkIGluZGVwZW5kZW50bHkpLCBzbyBpdCB3b3VsZCBiZSBwb3NzaWJsZSB0byBtYWtlIGRlZmluaW5nIHRoZSBzKiBkZXBlbmRlbnQgb24gd2hhdCBsb29wIG1ldGhvZCBpcyBiZWluZyB1c2VkLlxuZnVuY3Rpb24gb3V0ZXJGaWxsKG1hdGNoZWQsIG9yZGVyLCBwcm9jLCBib2R5KSB7XG4gIHZhciBkaW1lbnNpb24gPSBvcmRlci5sZW5ndGhcbiAgICAsIG5hcmdzID0gcHJvYy5hcnJheUFyZ3MubGVuZ3RoXG4gICAgLCBibG9ja1NpemUgPSBwcm9jLmJsb2NrU2l6ZVxuICAgICwgaGFzX2luZGV4ID0gcHJvYy5pbmRleEFyZ3MubGVuZ3RoID4gMFxuICAgICwgY29kZSA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPG5hcmdzOyArK2kpIHtcbiAgICBjb2RlLnB1c2goW1widmFyIG9mZnNldFwiLGksXCI9cFwiLGldLmpvaW4oXCJcIikpXG4gIH1cbiAgLy9HZW5lcmF0ZSBsb29wcyBmb3IgdW5tYXRjaGVkIGRpbWVuc2lvbnNcbiAgLy8gVGhlIG9yZGVyIGluIHdoaWNoIHRoZXNlIGRpbWVuc2lvbnMgYXJlIHRyYXZlcnNlZCBpcyBmYWlybHkgYXJiaXRyYXJ5IChmcm9tIHNtYWxsIHN0cmlkZSB0byBsYXJnZSBzdHJpZGUsIGZvciB0aGUgZmlyc3QgYXJndW1lbnQpXG4gIC8vIFRPRE86IEl0IHdvdWxkIGJlIG5pY2UgaWYgdGhlIG9yZGVyIGluIHdoaWNoIHRoZXNlIGxvb3BzIGFyZSBwbGFjZWQgd291bGQgYWxzbyBiZSBzb21laG93IFwib3B0aW1hbFwiIChhdCB0aGUgdmVyeSBsZWFzdCB3ZSBzaG91bGQgY2hlY2sgdGhhdCBpdCByZWFsbHkgZG9lc24ndCBodXJ0IHVzIGlmIHRoZXkncmUgbm90KS5cbiAgZm9yKHZhciBpPW1hdGNoZWQ7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBjb2RlLnB1c2goW1wiZm9yKHZhciBqXCIraStcIj1TU1tcIiwgb3JkZXJbaV0sIFwiXXwwO2pcIiwgaSwgXCI+MDspe1wiXS5qb2luKFwiXCIpKSAvLyBJdGVyYXRlIGJhY2sgdG8gZnJvbnRcbiAgICBjb2RlLnB1c2goW1wiaWYoalwiLGksXCI8XCIsYmxvY2tTaXplLFwiKXtcIl0uam9pbihcIlwiKSkgLy8gRWl0aGVyIGRlY3JlYXNlIGogYnkgYmxvY2tTaXplIChzID0gYmxvY2tTaXplKSwgb3Igc2V0IGl0IHRvIHplcm8gKGFmdGVyIHNldHRpbmcgcyA9IGopLlxuICAgIGNvZGUucHVzaChbXCJzXCIsb3JkZXJbaV0sXCI9alwiLGldLmpvaW4oXCJcIikpXG4gICAgY29kZS5wdXNoKFtcImpcIixpLFwiPTBcIl0uam9pbihcIlwiKSlcbiAgICBjb2RlLnB1c2goW1wifWVsc2V7c1wiLG9yZGVyW2ldLFwiPVwiLGJsb2NrU2l6ZV0uam9pbihcIlwiKSlcbiAgICBjb2RlLnB1c2goW1wialwiLGksXCItPVwiLGJsb2NrU2l6ZSxcIn1cIl0uam9pbihcIlwiKSlcbiAgICBpZihoYXNfaW5kZXgpIHtcbiAgICAgIGNvZGUucHVzaChbXCJpbmRleFtcIixvcmRlcltpXSxcIl09alwiLGldLmpvaW4oXCJcIikpXG4gICAgfVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPG5hcmdzOyArK2kpIHtcbiAgICB2YXIgaW5kZXhTdHIgPSBbXCJvZmZzZXRcIitpXVxuICAgIGZvcih2YXIgaj1tYXRjaGVkOyBqPGRpbWVuc2lvbjsgKytqKSB7XG4gICAgICBpbmRleFN0ci5wdXNoKFtcImpcIixqLFwiKnRcIixpLFwicFwiLG9yZGVyW2pdXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgICBjb2RlLnB1c2goW1wicFwiLGksXCI9KFwiLGluZGV4U3RyLmpvaW4oXCIrXCIpLFwiKVwiXS5qb2luKFwiXCIpKVxuICB9XG4gIGNvZGUucHVzaChpbm5lckZpbGwob3JkZXIsIHByb2MsIGJvZHkpKVxuICBmb3IodmFyIGk9bWF0Y2hlZDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGNvZGUucHVzaChcIn1cIilcbiAgfVxuICByZXR1cm4gY29kZS5qb2luKFwiXFxuXCIpXG59XG5cbi8vQ291bnQgdGhlIG51bWJlciBvZiBjb21wYXRpYmxlIGlubmVyIG9yZGVyc1xuLy8gVGhpcyBpcyB0aGUgbGVuZ3RoIG9mIHRoZSBsb25nZXN0IGNvbW1vbiBwcmVmaXggb2YgdGhlIGFycmF5cyBpbiBvcmRlcnMuXG4vLyBFYWNoIGFycmF5IGluIG9yZGVycyBsaXN0cyB0aGUgZGltZW5zaW9ucyBvZiB0aGUgY29ycmVzcG9uZCBuZGFycmF5IGluIG9yZGVyIG9mIGluY3JlYXNpbmcgc3RyaWRlLlxuLy8gVGhpcyBpcyB0aHVzIHRoZSBtYXhpbXVtIG51bWJlciBvZiBkaW1lbnNpb25zIHRoYXQgY2FuIGJlIGVmZmljaWVudGx5IHRyYXZlcnNlZCBieSBzaW1wbGUgbmVzdGVkIGxvb3BzIGZvciBhbGwgYXJyYXlzLlxuZnVuY3Rpb24gY291bnRNYXRjaGVzKG9yZGVycykge1xuICB2YXIgbWF0Y2hlZCA9IDAsIGRpbWVuc2lvbiA9IG9yZGVyc1swXS5sZW5ndGhcbiAgd2hpbGUobWF0Y2hlZCA8IGRpbWVuc2lvbikge1xuICAgIGZvcih2YXIgaj0xOyBqPG9yZGVycy5sZW5ndGg7ICsraikge1xuICAgICAgaWYob3JkZXJzW2pdW21hdGNoZWRdICE9PSBvcmRlcnNbMF1bbWF0Y2hlZF0pIHtcbiAgICAgICAgcmV0dXJuIG1hdGNoZWRcbiAgICAgIH1cbiAgICB9XG4gICAgKyttYXRjaGVkXG4gIH1cbiAgcmV0dXJuIG1hdGNoZWRcbn1cblxuLy9Qcm9jZXNzZXMgYSBibG9jayBhY2NvcmRpbmcgdG8gdGhlIGdpdmVuIGRhdGEgdHlwZXNcbi8vIFJlcGxhY2VzIHZhcmlhYmxlIG5hbWVzIGJ5IGRpZmZlcmVudCBvbmVzLCBlaXRoZXIgXCJsb2NhbFwiIG9uZXMgKHRoYXQgYXJlIHRoZW4gZmVycmllZCBpbiBhbmQgb3V0IG9mIHRoZSBnaXZlbiBhcnJheSkgb3Igb25lcyBtYXRjaGluZyB0aGUgYXJndW1lbnRzIHRoYXQgdGhlIGZ1bmN0aW9uIHBlcmZvcm1pbmcgdGhlIHVsdGltYXRlIGxvb3Agd2lsbCBhY2NlcHQuXG5mdW5jdGlvbiBwcm9jZXNzQmxvY2soYmxvY2ssIHByb2MsIGR0eXBlcykge1xuICB2YXIgY29kZSA9IGJsb2NrLmJvZHlcbiAgdmFyIHByZSA9IFtdXG4gIHZhciBwb3N0ID0gW11cbiAgZm9yKHZhciBpPTA7IGk8YmxvY2suYXJncy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBjYXJnID0gYmxvY2suYXJnc1tpXVxuICAgIGlmKGNhcmcuY291bnQgPD0gMCkge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgdmFyIHJlID0gbmV3IFJlZ0V4cChjYXJnLm5hbWUsIFwiZ1wiKVxuICAgIHZhciBwdHJTdHIgPSBcIlwiXG4gICAgdmFyIGFyck51bSA9IHByb2MuYXJyYXlBcmdzLmluZGV4T2YoaSlcbiAgICBzd2l0Y2gocHJvYy5hcmdUeXBlc1tpXSkge1xuICAgICAgY2FzZSBcIm9mZnNldFwiOlxuICAgICAgICB2YXIgb2ZmQXJnSW5kZXggPSBwcm9jLm9mZnNldEFyZ0luZGV4LmluZGV4T2YoaSlcbiAgICAgICAgdmFyIG9mZkFyZyA9IHByb2Mub2Zmc2V0QXJnc1tvZmZBcmdJbmRleF1cbiAgICAgICAgYXJyTnVtID0gb2ZmQXJnLmFycmF5XG4gICAgICAgIHB0clN0ciA9IFwiK3FcIiArIG9mZkFyZ0luZGV4IC8vIEFkZHMgb2Zmc2V0IHRvIHRoZSBcInBvaW50ZXJcIiBpbiB0aGUgYXJyYXlcbiAgICAgIGNhc2UgXCJhcnJheVwiOlxuICAgICAgICBwdHJTdHIgPSBcInBcIiArIGFyck51bSArIHB0clN0clxuICAgICAgICB2YXIgbG9jYWxTdHIgPSBcImxcIiArIGlcbiAgICAgICAgdmFyIGFyclN0ciA9IFwiYVwiICsgYXJyTnVtXG4gICAgICAgIGlmIChwcm9jLmFycmF5QmxvY2tJbmRpY2VzW2Fyck51bV0gPT09IDApIHsgLy8gQXJndW1lbnQgdG8gYm9keSBpcyBqdXN0IGEgc2luZ2xlIHZhbHVlIGZyb20gdGhpcyBhcnJheVxuICAgICAgICAgIGlmKGNhcmcuY291bnQgPT09IDEpIHsgLy8gQXJndW1lbnQvYXJyYXkgdXNlZCBvbmx5IG9uY2UoPylcbiAgICAgICAgICAgIGlmKGR0eXBlc1thcnJOdW1dID09PSBcImdlbmVyaWNcIikge1xuICAgICAgICAgICAgICBpZihjYXJnLmx2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHByZS5wdXNoKFtcInZhciBcIiwgbG9jYWxTdHIsIFwiPVwiLCBhcnJTdHIsIFwiLmdldChcIiwgcHRyU3RyLCBcIilcIl0uam9pbihcIlwiKSkgLy8gSXMgdGhpcyBuZWNlc3NhcnkgaWYgdGhlIGFyZ3VtZW50IGlzIE9OTFkgdXNlZCBhcyBhbiBsdmFsdWU/IChrZWVwIGluIG1pbmQgdGhhdCB3ZSBjYW4gaGF2ZSBhICs9IHNvbWV0aGluZywgc28gd2Ugd291bGQgYWN0dWFsbHkgbmVlZCB0byBjaGVjayBjYXJnLnJ2YWx1ZSlcbiAgICAgICAgICAgICAgICBjb2RlID0gY29kZS5yZXBsYWNlKHJlLCBsb2NhbFN0cilcbiAgICAgICAgICAgICAgICBwb3N0LnB1c2goW2FyclN0ciwgXCIuc2V0KFwiLCBwdHJTdHIsIFwiLFwiLCBsb2NhbFN0cixcIilcIl0uam9pbihcIlwiKSlcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb2RlID0gY29kZS5yZXBsYWNlKHJlLCBbYXJyU3RyLCBcIi5nZXQoXCIsIHB0clN0ciwgXCIpXCJdLmpvaW4oXCJcIikpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNvZGUgPSBjb2RlLnJlcGxhY2UocmUsIFthcnJTdHIsIFwiW1wiLCBwdHJTdHIsIFwiXVwiXS5qb2luKFwiXCIpKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZihkdHlwZXNbYXJyTnVtXSA9PT0gXCJnZW5lcmljXCIpIHtcbiAgICAgICAgICAgIHByZS5wdXNoKFtcInZhciBcIiwgbG9jYWxTdHIsIFwiPVwiLCBhcnJTdHIsIFwiLmdldChcIiwgcHRyU3RyLCBcIilcIl0uam9pbihcIlwiKSkgLy8gVE9ETzogQ291bGQgd2Ugb3B0aW1pemUgYnkgY2hlY2tpbmcgZm9yIGNhcmcucnZhbHVlP1xuICAgICAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZShyZSwgbG9jYWxTdHIpXG4gICAgICAgICAgICBpZihjYXJnLmx2YWx1ZSkge1xuICAgICAgICAgICAgICBwb3N0LnB1c2goW2FyclN0ciwgXCIuc2V0KFwiLCBwdHJTdHIsIFwiLFwiLCBsb2NhbFN0cixcIilcIl0uam9pbihcIlwiKSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJlLnB1c2goW1widmFyIFwiLCBsb2NhbFN0ciwgXCI9XCIsIGFyclN0ciwgXCJbXCIsIHB0clN0ciwgXCJdXCJdLmpvaW4oXCJcIikpIC8vIFRPRE86IENvdWxkIHdlIG9wdGltaXplIGJ5IGNoZWNraW5nIGZvciBjYXJnLnJ2YWx1ZT9cbiAgICAgICAgICAgIGNvZGUgPSBjb2RlLnJlcGxhY2UocmUsIGxvY2FsU3RyKVxuICAgICAgICAgICAgaWYoY2FyZy5sdmFsdWUpIHtcbiAgICAgICAgICAgICAgcG9zdC5wdXNoKFthcnJTdHIsIFwiW1wiLCBwdHJTdHIsIFwiXT1cIiwgbG9jYWxTdHJdLmpvaW4oXCJcIikpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgeyAvLyBBcmd1bWVudCB0byBib2R5IGlzIGEgXCJibG9ja1wiXG4gICAgICAgICAgdmFyIHJlU3RyQXJyID0gW2NhcmcubmFtZV0sIHB0clN0ckFyciA9IFtwdHJTdHJdXG4gICAgICAgICAgZm9yKHZhciBqPTA7IGo8TWF0aC5hYnMocHJvYy5hcnJheUJsb2NrSW5kaWNlc1thcnJOdW1dKTsgaisrKSB7XG4gICAgICAgICAgICByZVN0ckFyci5wdXNoKFwiXFxcXHMqXFxcXFsoW15cXFxcXV0rKVxcXFxdXCIpXG4gICAgICAgICAgICBwdHJTdHJBcnIucHVzaChcIiRcIiArIChqKzEpICsgXCIqdFwiICsgYXJyTnVtICsgXCJiXCIgKyBqKSAvLyBNYXRjaGVkIGluZGV4IHRpbWVzIHN0cmlkZVxuICAgICAgICAgIH1cbiAgICAgICAgICByZSA9IG5ldyBSZWdFeHAocmVTdHJBcnIuam9pbihcIlwiKSwgXCJnXCIpXG4gICAgICAgICAgcHRyU3RyID0gcHRyU3RyQXJyLmpvaW4oXCIrXCIpXG4gICAgICAgICAgaWYoZHR5cGVzW2Fyck51bV0gPT09IFwiZ2VuZXJpY1wiKSB7XG4gICAgICAgICAgICAvKmlmKGNhcmcubHZhbHVlKSB7XG4gICAgICAgICAgICAgIHByZS5wdXNoKFtcInZhciBcIiwgbG9jYWxTdHIsIFwiPVwiLCBhcnJTdHIsIFwiLmdldChcIiwgcHRyU3RyLCBcIilcIl0uam9pbihcIlwiKSkgLy8gSXMgdGhpcyBuZWNlc3NhcnkgaWYgdGhlIGFyZ3VtZW50IGlzIE9OTFkgdXNlZCBhcyBhbiBsdmFsdWU/IChrZWVwIGluIG1pbmQgdGhhdCB3ZSBjYW4gaGF2ZSBhICs9IHNvbWV0aGluZywgc28gd2Ugd291bGQgYWN0dWFsbHkgbmVlZCB0byBjaGVjayBjYXJnLnJ2YWx1ZSlcbiAgICAgICAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZShyZSwgbG9jYWxTdHIpXG4gICAgICAgICAgICAgIHBvc3QucHVzaChbYXJyU3RyLCBcIi5zZXQoXCIsIHB0clN0ciwgXCIsXCIsIGxvY2FsU3RyLFwiKVwiXS5qb2luKFwiXCIpKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZShyZSwgW2FyclN0ciwgXCIuZ2V0KFwiLCBwdHJTdHIsIFwiKVwiXS5qb2luKFwiXCIpKVxuICAgICAgICAgICAgfSovXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjd2lzZTogR2VuZXJpYyBhcnJheXMgbm90IHN1cHBvcnRlZCBpbiBjb21iaW5hdGlvbiB3aXRoIGJsb2NrcyFcIilcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhpcyBkb2VzIG5vdCBwcm9kdWNlIGFueSBsb2NhbCB2YXJpYWJsZXMsIGV2ZW4gaWYgdmFyaWFibGVzIGFyZSB1c2VkIG11bHRpcGxlIHRpbWVzLiBJdCB3b3VsZCBiZSBwb3NzaWJsZSB0byBkbyBzbywgYnV0IGl0IHdvdWxkIGNvbXBsaWNhdGUgdGhpbmdzIHF1aXRlIGEgYml0LlxuICAgICAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZShyZSwgW2FyclN0ciwgXCJbXCIsIHB0clN0ciwgXCJdXCJdLmpvaW4oXCJcIikpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBicmVha1xuICAgICAgY2FzZSBcInNjYWxhclwiOlxuICAgICAgICBjb2RlID0gY29kZS5yZXBsYWNlKHJlLCBcIllcIiArIHByb2Muc2NhbGFyQXJncy5pbmRleE9mKGkpKVxuICAgICAgYnJlYWtcbiAgICAgIGNhc2UgXCJpbmRleFwiOlxuICAgICAgICBjb2RlID0gY29kZS5yZXBsYWNlKHJlLCBcImluZGV4XCIpXG4gICAgICBicmVha1xuICAgICAgY2FzZSBcInNoYXBlXCI6XG4gICAgICAgIGNvZGUgPSBjb2RlLnJlcGxhY2UocmUsIFwic2hhcGVcIilcbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG4gIHJldHVybiBbcHJlLmpvaW4oXCJcXG5cIiksIGNvZGUsIHBvc3Quam9pbihcIlxcblwiKV0uam9pbihcIlxcblwiKS50cmltKClcbn1cblxuZnVuY3Rpb24gdHlwZVN1bW1hcnkoZHR5cGVzKSB7XG4gIHZhciBzdW1tYXJ5ID0gbmV3IEFycmF5KGR0eXBlcy5sZW5ndGgpXG4gIHZhciBhbGxFcXVhbCA9IHRydWVcbiAgZm9yKHZhciBpPTA7IGk8ZHR5cGVzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHQgPSBkdHlwZXNbaV1cbiAgICB2YXIgZGlnaXRzID0gdC5tYXRjaCgvXFxkKy8pXG4gICAgaWYoIWRpZ2l0cykge1xuICAgICAgZGlnaXRzID0gXCJcIlxuICAgIH0gZWxzZSB7XG4gICAgICBkaWdpdHMgPSBkaWdpdHNbMF1cbiAgICB9XG4gICAgaWYodC5jaGFyQXQoMCkgPT09IDApIHtcbiAgICAgIHN1bW1hcnlbaV0gPSBcInVcIiArIHQuY2hhckF0KDEpICsgZGlnaXRzXG4gICAgfSBlbHNlIHtcbiAgICAgIHN1bW1hcnlbaV0gPSB0LmNoYXJBdCgwKSArIGRpZ2l0c1xuICAgIH1cbiAgICBpZihpID4gMCkge1xuICAgICAgYWxsRXF1YWwgPSBhbGxFcXVhbCAmJiBzdW1tYXJ5W2ldID09PSBzdW1tYXJ5W2ktMV1cbiAgICB9XG4gIH1cbiAgaWYoYWxsRXF1YWwpIHtcbiAgICByZXR1cm4gc3VtbWFyeVswXVxuICB9XG4gIHJldHVybiBzdW1tYXJ5LmpvaW4oXCJcIilcbn1cblxuLy9HZW5lcmF0ZXMgYSBjd2lzZSBvcGVyYXRvclxuZnVuY3Rpb24gZ2VuZXJhdGVDV2lzZU9wKHByb2MsIHR5cGVzaWcpIHtcblxuICAvL0NvbXB1dGUgZGltZW5zaW9uXG4gIC8vIEFycmF5cyBnZXQgcHV0IGZpcnN0IGluIHR5cGVzaWcsIGFuZCB0aGVyZSBhcmUgdHdvIGVudHJpZXMgcGVyIGFycmF5IChkdHlwZSBhbmQgb3JkZXIpLCBzbyB0aGlzIGdldHMgdGhlIG51bWJlciBvZiBkaW1lbnNpb25zIGluIHRoZSBmaXJzdCBhcnJheSBhcmcuXG4gIHZhciBkaW1lbnNpb24gPSAodHlwZXNpZ1sxXS5sZW5ndGggLSBNYXRoLmFicyhwcm9jLmFycmF5QmxvY2tJbmRpY2VzWzBdKSl8MFxuICB2YXIgb3JkZXJzID0gbmV3IEFycmF5KHByb2MuYXJyYXlBcmdzLmxlbmd0aClcbiAgdmFyIGR0eXBlcyA9IG5ldyBBcnJheShwcm9jLmFycmF5QXJncy5sZW5ndGgpXG4gIGZvcih2YXIgaT0wOyBpPHByb2MuYXJyYXlBcmdzLmxlbmd0aDsgKytpKSB7XG4gICAgZHR5cGVzW2ldID0gdHlwZXNpZ1syKmldXG4gICAgb3JkZXJzW2ldID0gdHlwZXNpZ1syKmkrMV1cbiAgfVxuICBcbiAgLy9EZXRlcm1pbmUgd2hlcmUgYmxvY2sgYW5kIGxvb3AgaW5kaWNlcyBzdGFydCBhbmQgZW5kXG4gIHZhciBibG9ja0JlZ2luID0gW10sIGJsb2NrRW5kID0gW10gLy8gVGhlc2UgaW5kaWNlcyBhcmUgZXhwb3NlZCBhcyBibG9ja3NcbiAgdmFyIGxvb3BCZWdpbiA9IFtdLCBsb29wRW5kID0gW10gLy8gVGhlc2UgaW5kaWNlcyBhcmUgaXRlcmF0ZWQgb3ZlclxuICB2YXIgbG9vcE9yZGVycyA9IFtdIC8vIG9yZGVycyByZXN0cmljdGVkIHRvIHRoZSBsb29wIGluZGljZXNcbiAgZm9yKHZhciBpPTA7IGk8cHJvYy5hcnJheUFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAocHJvYy5hcnJheUJsb2NrSW5kaWNlc1tpXTwwKSB7XG4gICAgICBsb29wQmVnaW4ucHVzaCgwKVxuICAgICAgbG9vcEVuZC5wdXNoKGRpbWVuc2lvbilcbiAgICAgIGJsb2NrQmVnaW4ucHVzaChkaW1lbnNpb24pXG4gICAgICBibG9ja0VuZC5wdXNoKGRpbWVuc2lvbitwcm9jLmFycmF5QmxvY2tJbmRpY2VzW2ldKVxuICAgIH0gZWxzZSB7XG4gICAgICBsb29wQmVnaW4ucHVzaChwcm9jLmFycmF5QmxvY2tJbmRpY2VzW2ldKSAvLyBOb24tbmVnYXRpdmVcbiAgICAgIGxvb3BFbmQucHVzaChwcm9jLmFycmF5QmxvY2tJbmRpY2VzW2ldK2RpbWVuc2lvbilcbiAgICAgIGJsb2NrQmVnaW4ucHVzaCgwKVxuICAgICAgYmxvY2tFbmQucHVzaChwcm9jLmFycmF5QmxvY2tJbmRpY2VzW2ldKVxuICAgIH1cbiAgICB2YXIgbmV3T3JkZXIgPSBbXVxuICAgIGZvcih2YXIgaj0wOyBqPG9yZGVyc1tpXS5sZW5ndGg7IGorKykge1xuICAgICAgaWYgKGxvb3BCZWdpbltpXTw9b3JkZXJzW2ldW2pdICYmIG9yZGVyc1tpXVtqXTxsb29wRW5kW2ldKSB7XG4gICAgICAgIG5ld09yZGVyLnB1c2gob3JkZXJzW2ldW2pdLWxvb3BCZWdpbltpXSkgLy8gSWYgdGhpcyBpcyBhIGxvb3AgaW5kZXgsIHB1dCBpdCBpbiBuZXdPcmRlciwgc3VidHJhY3RpbmcgbG9vcEJlZ2luLCB0byBtYWtlIHN1cmUgdGhhdCBhbGwgbG9vcE9yZGVycyBhcmUgdXNpbmcgYSBjb21tb24gc2V0IG9mIGluZGljZXMuXG4gICAgICB9XG4gICAgfVxuICAgIGxvb3BPcmRlcnMucHVzaChuZXdPcmRlcilcbiAgfVxuXG4gIC8vRmlyc3QgY3JlYXRlIGFyZ3VtZW50cyBmb3IgcHJvY2VkdXJlXG4gIHZhciBhcmdsaXN0ID0gW1wiU1NcIl0gLy8gU1MgaXMgdGhlIG92ZXJhbGwgc2hhcGUgb3ZlciB3aGljaCB3ZSBpdGVyYXRlXG4gIHZhciBjb2RlID0gW1wiJ3VzZSBzdHJpY3QnXCJdXG4gIHZhciB2YXJzID0gW11cbiAgXG4gIGZvcih2YXIgaj0wOyBqPGRpbWVuc2lvbjsgKytqKSB7XG4gICAgdmFycy5wdXNoKFtcInNcIiwgaiwgXCI9U1NbXCIsIGosIFwiXVwiXS5qb2luKFwiXCIpKSAvLyBUaGUgbGltaXRzIGZvciBlYWNoIGRpbWVuc2lvbi5cbiAgfVxuICBmb3IodmFyIGk9MDsgaTxwcm9jLmFycmF5QXJncy5sZW5ndGg7ICsraSkge1xuICAgIGFyZ2xpc3QucHVzaChcImFcIitpKSAvLyBBY3R1YWwgZGF0YSBhcnJheVxuICAgIGFyZ2xpc3QucHVzaChcInRcIitpKSAvLyBTdHJpZGVzXG4gICAgYXJnbGlzdC5wdXNoKFwicFwiK2kpIC8vIE9mZnNldCBpbiB0aGUgYXJyYXkgYXQgd2hpY2ggdGhlIGRhdGEgc3RhcnRzIChhbHNvIHVzZWQgZm9yIGl0ZXJhdGluZyBvdmVyIHRoZSBkYXRhKVxuICAgIFxuICAgIGZvcih2YXIgaj0wOyBqPGRpbWVuc2lvbjsgKytqKSB7IC8vIFVucGFjayB0aGUgc3RyaWRlcyBpbnRvIHZhcnMgZm9yIGxvb3BpbmdcbiAgICAgIHZhcnMucHVzaChbXCJ0XCIsaSxcInBcIixqLFwiPXRcIixpLFwiW1wiLGxvb3BCZWdpbltpXStqLFwiXVwiXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgICBcbiAgICBmb3IodmFyIGo9MDsgajxNYXRoLmFicyhwcm9jLmFycmF5QmxvY2tJbmRpY2VzW2ldKTsgKytqKSB7IC8vIFVucGFjayB0aGUgc3RyaWRlcyBpbnRvIHZhcnMgZm9yIGJsb2NrIGl0ZXJhdGlvblxuICAgICAgdmFycy5wdXNoKFtcInRcIixpLFwiYlwiLGosXCI9dFwiLGksXCJbXCIsYmxvY2tCZWdpbltpXStqLFwiXVwiXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgfVxuICBmb3IodmFyIGk9MDsgaTxwcm9jLnNjYWxhckFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICBhcmdsaXN0LnB1c2goXCJZXCIgKyBpKVxuICB9XG4gIGlmKHByb2Muc2hhcGVBcmdzLmxlbmd0aCA+IDApIHtcbiAgICB2YXJzLnB1c2goXCJzaGFwZT1TUy5zbGljZSgwKVwiKSAvLyBNYWtlcyB0aGUgc2hhcGUgb3ZlciB3aGljaCB3ZSBpdGVyYXRlIGF2YWlsYWJsZSB0byB0aGUgdXNlciBkZWZpbmVkIGZ1bmN0aW9ucyAoc28geW91IGNhbiB1c2Ugd2lkdGgvaGVpZ2h0IGZvciBleGFtcGxlKVxuICB9XG4gIGlmKHByb2MuaW5kZXhBcmdzLmxlbmd0aCA+IDApIHtcbiAgICAvLyBQcmVwYXJlIGFuIGFycmF5IHRvIGtlZXAgdHJhY2sgb2YgdGhlIChsb2dpY2FsKSBpbmRpY2VzLCBpbml0aWFsaXplZCB0byBkaW1lbnNpb24gemVyb2VzLlxuICAgIHZhciB6ZXJvcyA9IG5ldyBBcnJheShkaW1lbnNpb24pXG4gICAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICAgIHplcm9zW2ldID0gXCIwXCJcbiAgICB9XG4gICAgdmFycy5wdXNoKFtcImluZGV4PVtcIiwgemVyb3Muam9pbihcIixcIiksIFwiXVwiXS5qb2luKFwiXCIpKVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPHByb2Mub2Zmc2V0QXJncy5sZW5ndGg7ICsraSkgeyAvLyBPZmZzZXQgYXJndW1lbnRzIHVzZWQgZm9yIHN0ZW5jaWwgb3BlcmF0aW9uc1xuICAgIHZhciBvZmZfYXJnID0gcHJvYy5vZmZzZXRBcmdzW2ldXG4gICAgdmFyIGluaXRfc3RyaW5nID0gW11cbiAgICBmb3IodmFyIGo9MDsgajxvZmZfYXJnLm9mZnNldC5sZW5ndGg7ICsraikge1xuICAgICAgaWYob2ZmX2FyZy5vZmZzZXRbal0gPT09IDApIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH0gZWxzZSBpZihvZmZfYXJnLm9mZnNldFtqXSA9PT0gMSkge1xuICAgICAgICBpbml0X3N0cmluZy5wdXNoKFtcInRcIiwgb2ZmX2FyZy5hcnJheSwgXCJwXCIsIGpdLmpvaW4oXCJcIikpICAgICAgXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbml0X3N0cmluZy5wdXNoKFtvZmZfYXJnLm9mZnNldFtqXSwgXCIqdFwiLCBvZmZfYXJnLmFycmF5LCBcInBcIiwgal0uam9pbihcIlwiKSlcbiAgICAgIH1cbiAgICB9XG4gICAgaWYoaW5pdF9zdHJpbmcubGVuZ3RoID09PSAwKSB7XG4gICAgICB2YXJzLnB1c2goXCJxXCIgKyBpICsgXCI9MFwiKVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXJzLnB1c2goW1wicVwiLCBpLCBcIj1cIiwgaW5pdF9zdHJpbmcuam9pbihcIitcIildLmpvaW4oXCJcIikpXG4gICAgfVxuICB9XG5cbiAgLy9QcmVwYXJlIHRoaXMgdmFyaWFibGVzXG4gIHZhciB0aGlzVmFycyA9IHVuaXEoW10uY29uY2F0KHByb2MucHJlLnRoaXNWYXJzKVxuICAgICAgICAgICAgICAgICAgICAgIC5jb25jYXQocHJvYy5ib2R5LnRoaXNWYXJzKVxuICAgICAgICAgICAgICAgICAgICAgIC5jb25jYXQocHJvYy5wb3N0LnRoaXNWYXJzKSlcbiAgdmFycyA9IHZhcnMuY29uY2F0KHRoaXNWYXJzKVxuICBpZiAodmFycy5sZW5ndGggPiAwKSB7XG4gICAgY29kZS5wdXNoKFwidmFyIFwiICsgdmFycy5qb2luKFwiLFwiKSlcbiAgfVxuICBmb3IodmFyIGk9MDsgaTxwcm9jLmFycmF5QXJncy5sZW5ndGg7ICsraSkge1xuICAgIGNvZGUucHVzaChcInBcIitpK1wifD0wXCIpXG4gIH1cbiAgXG4gIC8vSW5saW5lIHByZWx1ZGVcbiAgaWYocHJvYy5wcmUuYm9keS5sZW5ndGggPiAzKSB7XG4gICAgY29kZS5wdXNoKHByb2Nlc3NCbG9jayhwcm9jLnByZSwgcHJvYywgZHR5cGVzKSlcbiAgfVxuXG4gIC8vUHJvY2VzcyBib2R5XG4gIHZhciBib2R5ID0gcHJvY2Vzc0Jsb2NrKHByb2MuYm9keSwgcHJvYywgZHR5cGVzKVxuICB2YXIgbWF0Y2hlZCA9IGNvdW50TWF0Y2hlcyhsb29wT3JkZXJzKVxuICBpZihtYXRjaGVkIDwgZGltZW5zaW9uKSB7XG4gICAgY29kZS5wdXNoKG91dGVyRmlsbChtYXRjaGVkLCBsb29wT3JkZXJzWzBdLCBwcm9jLCBib2R5KSkgLy8gVE9ETzogUmF0aGVyIHRoYW4gcGFzc2luZyBsb29wT3JkZXJzWzBdLCBpdCBtaWdodCBiZSBpbnRlcmVzdGluZyB0byBsb29rIGF0IHBhc3NpbmcgYW4gb3JkZXIgdGhhdCByZXByZXNlbnRzIHRoZSBtYWpvcml0eSBvZiB0aGUgYXJndW1lbnRzIGZvciBleGFtcGxlLlxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChpbm5lckZpbGwobG9vcE9yZGVyc1swXSwgcHJvYywgYm9keSkpXG4gIH1cblxuICAvL0lubGluZSBlcGlsb2dcbiAgaWYocHJvYy5wb3N0LmJvZHkubGVuZ3RoID4gMykge1xuICAgIGNvZGUucHVzaChwcm9jZXNzQmxvY2socHJvYy5wb3N0LCBwcm9jLCBkdHlwZXMpKVxuICB9XG4gIFxuICBpZihwcm9jLmRlYnVnKSB7XG4gICAgY29uc29sZS5sb2coXCItLS0tLUdlbmVyYXRlZCBjd2lzZSByb3V0aW5lIGZvciBcIiwgdHlwZXNpZywgXCI6XFxuXCIgKyBjb2RlLmpvaW4oXCJcXG5cIikgKyBcIlxcbi0tLS0tLS0tLS1cIilcbiAgfVxuICBcbiAgdmFyIGxvb3BOYW1lID0gWyhwcm9jLmZ1bmNOYW1lfHxcInVubmFtZWRcIiksIFwiX2N3aXNlX2xvb3BfXCIsIG9yZGVyc1swXS5qb2luKFwic1wiKSxcIm1cIixtYXRjaGVkLHR5cGVTdW1tYXJ5KGR0eXBlcyldLmpvaW4oXCJcIilcbiAgdmFyIGYgPSBuZXcgRnVuY3Rpb24oW1wiZnVuY3Rpb24gXCIsbG9vcE5hbWUsXCIoXCIsIGFyZ2xpc3Quam9pbihcIixcIiksXCIpe1wiLCBjb2RlLmpvaW4oXCJcXG5cIiksXCJ9IHJldHVybiBcIiwgbG9vcE5hbWVdLmpvaW4oXCJcIikpXG4gIHJldHVybiBmKClcbn1cbm1vZHVsZS5leHBvcnRzID0gZ2VuZXJhdGVDV2lzZU9wXG5cbn0se1widW5pcVwiOjU0N31dLDE0ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG4vLyBUaGUgZnVuY3Rpb24gYmVsb3cgaXMgY2FsbGVkIHdoZW4gY29uc3RydWN0aW5nIGEgY3dpc2UgZnVuY3Rpb24gb2JqZWN0LCBhbmQgZG9lcyB0aGUgZm9sbG93aW5nOlxuLy8gQSBmdW5jdGlvbiBvYmplY3QgaXMgY29uc3RydWN0ZWQgd2hpY2ggYWNjZXB0cyBhcyBhcmd1bWVudCBhIGNvbXBpbGF0aW9uIGZ1bmN0aW9uIGFuZCByZXR1cm5zIGFub3RoZXIgZnVuY3Rpb24uXG4vLyBJdCBpcyB0aGlzIG90aGVyIGZ1bmN0aW9uIHRoYXQgaXMgZXZlbnR1YWxseSByZXR1cm5lZCBieSBjcmVhdGVUaHVuaywgYW5kIHRoaXMgZnVuY3Rpb24gaXMgdGhlIG9uZSB0aGF0IGFjdHVhbGx5XG4vLyBjaGVja3Mgd2hldGhlciBhIGNlcnRhaW4gcGF0dGVybiBvZiBhcmd1bWVudHMgaGFzIGFscmVhZHkgYmVlbiB1c2VkIGJlZm9yZSBhbmQgY29tcGlsZXMgbmV3IGxvb3BzIGFzIG5lZWRlZC5cbi8vIFRoZSBjb21waWxhdGlvbiBwYXNzZWQgdG8gdGhlIGZpcnN0IGZ1bmN0aW9uIG9iamVjdCBpcyB1c2VkIGZvciBjb21waWxpbmcgbmV3IGZ1bmN0aW9ucy5cbi8vIE9uY2UgdGhpcyBmdW5jdGlvbiBvYmplY3QgaXMgY3JlYXRlZCwgaXQgaXMgY2FsbGVkIHdpdGggY29tcGlsZSBhcyBhcmd1bWVudCwgd2hlcmUgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIGNvbXBpbGVcbi8vIGlzIGJvdW5kIHRvIFwicHJvY1wiIChlc3NlbnRpYWxseSBjb250YWluaW5nIGEgcHJlcHJvY2Vzc2VkIHZlcnNpb24gb2YgdGhlIHVzZXIgYXJndW1lbnRzIHRvIGN3aXNlKS5cbi8vIFNvIGNyZWF0ZVRodW5rIHJvdWdobHkgd29ya3MgbGlrZSB0aGlzOlxuLy8gZnVuY3Rpb24gY3JlYXRlVGh1bmsocHJvYykge1xuLy8gICB2YXIgdGh1bmsgPSBmdW5jdGlvbihjb21waWxlQm91bmQpIHtcbi8vICAgICB2YXIgQ0FDSEVEID0ge31cbi8vICAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXlzIGFuZCBzY2FsYXJzKSB7XG4vLyAgICAgICBpZiAoZHR5cGUgYW5kIG9yZGVyIG9mIGFycmF5cyBpbiBDQUNIRUQpIHtcbi8vICAgICAgICAgdmFyIGZ1bmMgPSBDQUNIRURbZHR5cGUgYW5kIG9yZGVyIG9mIGFycmF5c11cbi8vICAgICAgIH0gZWxzZSB7XG4vLyAgICAgICAgIHZhciBmdW5jID0gQ0FDSEVEW2R0eXBlIGFuZCBvcmRlciBvZiBhcnJheXNdID0gY29tcGlsZUJvdW5kKGR0eXBlIGFuZCBvcmRlciBvZiBhcnJheXMpXG4vLyAgICAgICB9XG4vLyAgICAgICByZXR1cm4gZnVuYyhhcnJheXMgYW5kIHNjYWxhcnMpXG4vLyAgICAgfVxuLy8gICB9XG4vLyAgIHJldHVybiB0aHVuayhjb21waWxlLmJpbmQxKHByb2MpKVxuLy8gfVxuXG52YXIgY29tcGlsZSA9IF9kZXJlcV8oXCIuL2NvbXBpbGUuanNcIilcblxuZnVuY3Rpb24gY3JlYXRlVGh1bmsocHJvYykge1xuICB2YXIgY29kZSA9IFtcIid1c2Ugc3RyaWN0J1wiLCBcInZhciBDQUNIRUQ9e31cIl1cbiAgdmFyIHZhcnMgPSBbXVxuICB2YXIgdGh1bmtOYW1lID0gcHJvYy5mdW5jTmFtZSArIFwiX2N3aXNlX3RodW5rXCJcbiAgXG4gIC8vQnVpbGQgdGh1bmtcbiAgY29kZS5wdXNoKFtcInJldHVybiBmdW5jdGlvbiBcIiwgdGh1bmtOYW1lLCBcIihcIiwgcHJvYy5zaGltQXJncy5qb2luKFwiLFwiKSwgXCIpe1wiXS5qb2luKFwiXCIpKVxuICB2YXIgdHlwZXNpZyA9IFtdXG4gIHZhciBzdHJpbmdfdHlwZXNpZyA9IFtdXG4gIHZhciBwcm9jX2FyZ3MgPSBbW1wiYXJyYXlcIixwcm9jLmFycmF5QXJnc1swXSxcIi5zaGFwZS5zbGljZShcIiwgLy8gU2xpY2Ugc2hhcGUgc28gdGhhdCB3ZSBvbmx5IHJldGFpbiB0aGUgc2hhcGUgb3ZlciB3aGljaCB3ZSBpdGVyYXRlICh3aGljaCBnZXRzIHBhc3NlZCB0byB0aGUgY3dpc2Ugb3BlcmF0b3IgYXMgU1MpLlxuICAgICAgICAgICAgICAgICAgICBNYXRoLm1heCgwLHByb2MuYXJyYXlCbG9ja0luZGljZXNbMF0pLHByb2MuYXJyYXlCbG9ja0luZGljZXNbMF08MD8oXCIsXCIrcHJvYy5hcnJheUJsb2NrSW5kaWNlc1swXStcIilcIik6XCIpXCJdLmpvaW4oXCJcIildXG4gIHZhciBzaGFwZUxlbmd0aENvbmRpdGlvbnMgPSBbXSwgc2hhcGVDb25kaXRpb25zID0gW11cbiAgLy8gUHJvY2VzcyBhcnJheSBhcmd1bWVudHNcbiAgZm9yKHZhciBpPTA7IGk8cHJvYy5hcnJheUFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgaiA9IHByb2MuYXJyYXlBcmdzW2ldXG4gICAgdmFycy5wdXNoKFtcInRcIiwgaiwgXCI9YXJyYXlcIiwgaiwgXCIuZHR5cGUsXCIsXG4gICAgICAgICAgICAgICBcInJcIiwgaiwgXCI9YXJyYXlcIiwgaiwgXCIub3JkZXJcIl0uam9pbihcIlwiKSlcbiAgICB0eXBlc2lnLnB1c2goXCJ0XCIgKyBqKVxuICAgIHR5cGVzaWcucHVzaChcInJcIiArIGopXG4gICAgc3RyaW5nX3R5cGVzaWcucHVzaChcInRcIitqKVxuICAgIHN0cmluZ190eXBlc2lnLnB1c2goXCJyXCIraitcIi5qb2luKClcIilcbiAgICBwcm9jX2FyZ3MucHVzaChcImFycmF5XCIgKyBqICsgXCIuZGF0YVwiKVxuICAgIHByb2NfYXJncy5wdXNoKFwiYXJyYXlcIiArIGogKyBcIi5zdHJpZGVcIilcbiAgICBwcm9jX2FyZ3MucHVzaChcImFycmF5XCIgKyBqICsgXCIub2Zmc2V0fDBcIilcbiAgICBpZiAoaT4wKSB7IC8vIEdhdGhlciBjb25kaXRpb25zIHRvIGNoZWNrIGZvciBzaGFwZSBlcXVhbGl0eSAoaWdub3JpbmcgYmxvY2sgaW5kaWNlcylcbiAgICAgIHNoYXBlTGVuZ3RoQ29uZGl0aW9ucy5wdXNoKFwiYXJyYXlcIiArIHByb2MuYXJyYXlBcmdzWzBdICsgXCIuc2hhcGUubGVuZ3RoPT09YXJyYXlcIiArIGogKyBcIi5zaGFwZS5sZW5ndGgrXCIgKyAoTWF0aC5hYnMocHJvYy5hcnJheUJsb2NrSW5kaWNlc1swXSktTWF0aC5hYnMocHJvYy5hcnJheUJsb2NrSW5kaWNlc1tpXSkpKVxuICAgICAgc2hhcGVDb25kaXRpb25zLnB1c2goXCJhcnJheVwiICsgcHJvYy5hcnJheUFyZ3NbMF0gKyBcIi5zaGFwZVtzaGFwZUluZGV4K1wiICsgTWF0aC5tYXgoMCxwcm9jLmFycmF5QmxvY2tJbmRpY2VzWzBdKSArIFwiXT09PWFycmF5XCIgKyBqICsgXCIuc2hhcGVbc2hhcGVJbmRleCtcIiArIE1hdGgubWF4KDAscHJvYy5hcnJheUJsb2NrSW5kaWNlc1tpXSkgKyBcIl1cIilcbiAgICB9XG4gIH1cbiAgLy8gQ2hlY2sgZm9yIHNoYXBlIGVxdWFsaXR5XG4gIGlmIChwcm9jLmFycmF5QXJncy5sZW5ndGggPiAxKSB7XG4gICAgY29kZS5wdXNoKFwiaWYgKCEoXCIgKyBzaGFwZUxlbmd0aENvbmRpdGlvbnMuam9pbihcIiAmJiBcIikgKyBcIikpIHRocm93IG5ldyBFcnJvcignY3dpc2U6IEFycmF5cyBkbyBub3QgYWxsIGhhdmUgdGhlIHNhbWUgZGltZW5zaW9uYWxpdHkhJylcIilcbiAgICBjb2RlLnB1c2goXCJmb3IodmFyIHNoYXBlSW5kZXg9YXJyYXlcIiArIHByb2MuYXJyYXlBcmdzWzBdICsgXCIuc2hhcGUubGVuZ3RoLVwiICsgTWF0aC5hYnMocHJvYy5hcnJheUJsb2NrSW5kaWNlc1swXSkgKyBcIjsgc2hhcGVJbmRleC0tPjA7KSB7XCIpXG4gICAgY29kZS5wdXNoKFwiaWYgKCEoXCIgKyBzaGFwZUNvbmRpdGlvbnMuam9pbihcIiAmJiBcIikgKyBcIikpIHRocm93IG5ldyBFcnJvcignY3dpc2U6IEFycmF5cyBkbyBub3QgYWxsIGhhdmUgdGhlIHNhbWUgc2hhcGUhJylcIilcbiAgICBjb2RlLnB1c2goXCJ9XCIpXG4gIH1cbiAgLy8gUHJvY2VzcyBzY2FsYXIgYXJndW1lbnRzXG4gIGZvcih2YXIgaT0wOyBpPHByb2Muc2NhbGFyQXJncy5sZW5ndGg7ICsraSkge1xuICAgIHByb2NfYXJncy5wdXNoKFwic2NhbGFyXCIgKyBwcm9jLnNjYWxhckFyZ3NbaV0pXG4gIH1cbiAgLy8gQ2hlY2sgZm9yIGNhY2hlZCBmdW5jdGlvbiAoYW5kIGlmIG5vdCBwcmVzZW50LCBnZW5lcmF0ZSBpdClcbiAgdmFycy5wdXNoKFtcInR5cGU9W1wiLCBzdHJpbmdfdHlwZXNpZy5qb2luKFwiLFwiKSwgXCJdLmpvaW4oKVwiXS5qb2luKFwiXCIpKVxuICB2YXJzLnB1c2goXCJwcm9jPUNBQ0hFRFt0eXBlXVwiKVxuICBjb2RlLnB1c2goXCJ2YXIgXCIgKyB2YXJzLmpvaW4oXCIsXCIpKVxuICBcbiAgY29kZS5wdXNoKFtcImlmKCFwcm9jKXtcIixcbiAgICAgICAgICAgICBcIkNBQ0hFRFt0eXBlXT1wcm9jPWNvbXBpbGUoW1wiLCB0eXBlc2lnLmpvaW4oXCIsXCIpLCBcIl0pfVwiLFxuICAgICAgICAgICAgIFwicmV0dXJuIHByb2MoXCIsIHByb2NfYXJncy5qb2luKFwiLFwiKSwgXCIpfVwiXS5qb2luKFwiXCIpKVxuXG4gIGlmKHByb2MuZGVidWcpIHtcbiAgICBjb25zb2xlLmxvZyhcIi0tLS0tR2VuZXJhdGVkIHRodW5rOlxcblwiICsgY29kZS5qb2luKFwiXFxuXCIpICsgXCJcXG4tLS0tLS0tLS0tXCIpXG4gIH1cbiAgXG4gIC8vQ29tcGlsZSB0aHVua1xuICB2YXIgdGh1bmsgPSBuZXcgRnVuY3Rpb24oXCJjb21waWxlXCIsIGNvZGUuam9pbihcIlxcblwiKSlcbiAgcmV0dXJuIHRodW5rKGNvbXBpbGUuYmluZCh1bmRlZmluZWQsIHByb2MpKVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVRodW5rXG5cbn0se1wiLi9jb21waWxlLmpzXCI6MTQ3fV0sMTQ5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXyhcImN3aXNlLWNvbXBpbGVyXCIpXG59LHtcImN3aXNlLWNvbXBpbGVyXCI6MTQ2fV0sMTUwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0JztcblxudmFyIGNvcHkgICAgICAgICAgICAgPSBfZGVyZXFfKCdlczUtZXh0L29iamVjdC9jb3B5JylcbiAgLCBub3JtYWxpemVPcHRpb25zID0gX2RlcmVxXygnZXM1LWV4dC9vYmplY3Qvbm9ybWFsaXplLW9wdGlvbnMnKVxuICAsIGVuc3VyZUNhbGxhYmxlICAgPSBfZGVyZXFfKCdlczUtZXh0L29iamVjdC92YWxpZC1jYWxsYWJsZScpXG4gICwgbWFwICAgICAgICAgICAgICA9IF9kZXJlcV8oJ2VzNS1leHQvb2JqZWN0L21hcCcpXG4gICwgY2FsbGFibGUgICAgICAgICA9IF9kZXJlcV8oJ2VzNS1leHQvb2JqZWN0L3ZhbGlkLWNhbGxhYmxlJylcbiAgLCB2YWxpZFZhbHVlICAgICAgID0gX2RlcmVxXygnZXM1LWV4dC9vYmplY3QvdmFsaWQtdmFsdWUnKVxuXG4gICwgYmluZCA9IEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kLCBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eVxuICAsIGhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eVxuICAsIGRlZmluZTtcblxuZGVmaW5lID0gZnVuY3Rpb24gKG5hbWUsIGRlc2MsIG9wdGlvbnMpIHtcblx0dmFyIHZhbHVlID0gdmFsaWRWYWx1ZShkZXNjKSAmJiBjYWxsYWJsZShkZXNjLnZhbHVlKSwgZGdzO1xuXHRkZ3MgPSBjb3B5KGRlc2MpO1xuXHRkZWxldGUgZGdzLndyaXRhYmxlO1xuXHRkZWxldGUgZGdzLnZhbHVlO1xuXHRkZ3MuZ2V0ID0gZnVuY3Rpb24gKCkge1xuXHRcdGlmICghb3B0aW9ucy5vdmVyd3JpdGVEZWZpbml0aW9uICYmIGhhc093blByb3BlcnR5LmNhbGwodGhpcywgbmFtZSkpIHJldHVybiB2YWx1ZTtcblx0XHRkZXNjLnZhbHVlID0gYmluZC5jYWxsKHZhbHVlLCBvcHRpb25zLnJlc29sdmVDb250ZXh0ID8gb3B0aW9ucy5yZXNvbHZlQ29udGV4dCh0aGlzKSA6IHRoaXMpO1xuXHRcdGRlZmluZVByb3BlcnR5KHRoaXMsIG5hbWUsIGRlc2MpO1xuXHRcdHJldHVybiB0aGlzW25hbWVdO1xuXHR9O1xuXHRyZXR1cm4gZGdzO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocHJvcHMvKiwgb3B0aW9ucyovKSB7XG5cdHZhciBvcHRpb25zID0gbm9ybWFsaXplT3B0aW9ucyhhcmd1bWVudHNbMV0pO1xuXHRpZiAob3B0aW9ucy5yZXNvbHZlQ29udGV4dCAhPSBudWxsKSBlbnN1cmVDYWxsYWJsZShvcHRpb25zLnJlc29sdmVDb250ZXh0KTtcblx0cmV0dXJuIG1hcChwcm9wcywgZnVuY3Rpb24gKGRlc2MsIG5hbWUpIHsgcmV0dXJuIGRlZmluZShuYW1lLCBkZXNjLCBvcHRpb25zKTsgfSk7XG59O1xuXG59LHtcImVzNS1leHQvb2JqZWN0L2NvcHlcIjoxODksXCJlczUtZXh0L29iamVjdC9tYXBcIjoxOTgsXCJlczUtZXh0L29iamVjdC9ub3JtYWxpemUtb3B0aW9uc1wiOjE5OSxcImVzNS1leHQvb2JqZWN0L3ZhbGlkLWNhbGxhYmxlXCI6MjAzLFwiZXM1LWV4dC9vYmplY3QvdmFsaWQtdmFsdWVcIjoyMDV9XSwxNTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXNzaWduICAgICAgICA9IF9kZXJlcV8oJ2VzNS1leHQvb2JqZWN0L2Fzc2lnbicpXG4gICwgbm9ybWFsaXplT3B0cyA9IF9kZXJlcV8oJ2VzNS1leHQvb2JqZWN0L25vcm1hbGl6ZS1vcHRpb25zJylcbiAgLCBpc0NhbGxhYmxlICAgID0gX2RlcmVxXygnZXM1LWV4dC9vYmplY3QvaXMtY2FsbGFibGUnKVxuICAsIGNvbnRhaW5zICAgICAgPSBfZGVyZXFfKCdlczUtZXh0L3N0cmluZy8jL2NvbnRhaW5zJylcblxuICAsIGQ7XG5cbmQgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChkc2NyLCB2YWx1ZS8qLCBvcHRpb25zKi8pIHtcblx0dmFyIGMsIGUsIHcsIG9wdGlvbnMsIGRlc2M7XG5cdGlmICgoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHx8ICh0eXBlb2YgZHNjciAhPT0gJ3N0cmluZycpKSB7XG5cdFx0b3B0aW9ucyA9IHZhbHVlO1xuXHRcdHZhbHVlID0gZHNjcjtcblx0XHRkc2NyID0gbnVsbDtcblx0fSBlbHNlIHtcblx0XHRvcHRpb25zID0gYXJndW1lbnRzWzJdO1xuXHR9XG5cdGlmIChkc2NyID09IG51bGwpIHtcblx0XHRjID0gdyA9IHRydWU7XG5cdFx0ZSA9IGZhbHNlO1xuXHR9IGVsc2Uge1xuXHRcdGMgPSBjb250YWlucy5jYWxsKGRzY3IsICdjJyk7XG5cdFx0ZSA9IGNvbnRhaW5zLmNhbGwoZHNjciwgJ2UnKTtcblx0XHR3ID0gY29udGFpbnMuY2FsbChkc2NyLCAndycpO1xuXHR9XG5cblx0ZGVzYyA9IHsgdmFsdWU6IHZhbHVlLCBjb25maWd1cmFibGU6IGMsIGVudW1lcmFibGU6IGUsIHdyaXRhYmxlOiB3IH07XG5cdHJldHVybiAhb3B0aW9ucyA/IGRlc2MgOiBhc3NpZ24obm9ybWFsaXplT3B0cyhvcHRpb25zKSwgZGVzYyk7XG59O1xuXG5kLmdzID0gZnVuY3Rpb24gKGRzY3IsIGdldCwgc2V0LyosIG9wdGlvbnMqLykge1xuXHR2YXIgYywgZSwgb3B0aW9ucywgZGVzYztcblx0aWYgKHR5cGVvZiBkc2NyICE9PSAnc3RyaW5nJykge1xuXHRcdG9wdGlvbnMgPSBzZXQ7XG5cdFx0c2V0ID0gZ2V0O1xuXHRcdGdldCA9IGRzY3I7XG5cdFx0ZHNjciA9IG51bGw7XG5cdH0gZWxzZSB7XG5cdFx0b3B0aW9ucyA9IGFyZ3VtZW50c1szXTtcblx0fVxuXHRpZiAoZ2V0ID09IG51bGwpIHtcblx0XHRnZXQgPSB1bmRlZmluZWQ7XG5cdH0gZWxzZSBpZiAoIWlzQ2FsbGFibGUoZ2V0KSkge1xuXHRcdG9wdGlvbnMgPSBnZXQ7XG5cdFx0Z2V0ID0gc2V0ID0gdW5kZWZpbmVkO1xuXHR9IGVsc2UgaWYgKHNldCA9PSBudWxsKSB7XG5cdFx0c2V0ID0gdW5kZWZpbmVkO1xuXHR9IGVsc2UgaWYgKCFpc0NhbGxhYmxlKHNldCkpIHtcblx0XHRvcHRpb25zID0gc2V0O1xuXHRcdHNldCA9IHVuZGVmaW5lZDtcblx0fVxuXHRpZiAoZHNjciA9PSBudWxsKSB7XG5cdFx0YyA9IHRydWU7XG5cdFx0ZSA9IGZhbHNlO1xuXHR9IGVsc2Uge1xuXHRcdGMgPSBjb250YWlucy5jYWxsKGRzY3IsICdjJyk7XG5cdFx0ZSA9IGNvbnRhaW5zLmNhbGwoZHNjciwgJ2UnKTtcblx0fVxuXG5cdGRlc2MgPSB7IGdldDogZ2V0LCBzZXQ6IHNldCwgY29uZmlndXJhYmxlOiBjLCBlbnVtZXJhYmxlOiBlIH07XG5cdHJldHVybiAhb3B0aW9ucyA/IGRlc2MgOiBhc3NpZ24obm9ybWFsaXplT3B0cyhvcHRpb25zKSwgZGVzYyk7XG59O1xuXG59LHtcImVzNS1leHQvb2JqZWN0L2Fzc2lnblwiOjE4NixcImVzNS1leHQvb2JqZWN0L2lzLWNhbGxhYmxlXCI6MTkyLFwiZXM1LWV4dC9vYmplY3Qvbm9ybWFsaXplLW9wdGlvbnNcIjoxOTksXCJlczUtZXh0L3N0cmluZy8jL2NvbnRhaW5zXCI6MjA2fV0sMTUyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtYXJyYXkvIHYxLjIuNCBDb3B5cmlnaHQgMjAxOCBNaWtlIEJvc3RvY2tcbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG50eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcbnR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuKGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgcmV0dXJuIGEgPCBiID8gLTEgOiBhID4gYiA/IDEgOiBhID49IGIgPyAwIDogTmFOO1xufVxuXG5mdW5jdGlvbiBiaXNlY3Rvcihjb21wYXJlKSB7XG4gIGlmIChjb21wYXJlLmxlbmd0aCA9PT0gMSkgY29tcGFyZSA9IGFzY2VuZGluZ0NvbXBhcmF0b3IoY29tcGFyZSk7XG4gIHJldHVybiB7XG4gICAgbGVmdDogZnVuY3Rpb24oYSwgeCwgbG8sIGhpKSB7XG4gICAgICBpZiAobG8gPT0gbnVsbCkgbG8gPSAwO1xuICAgICAgaWYgKGhpID09IG51bGwpIGhpID0gYS5sZW5ndGg7XG4gICAgICB3aGlsZSAobG8gPCBoaSkge1xuICAgICAgICB2YXIgbWlkID0gbG8gKyBoaSA+Pj4gMTtcbiAgICAgICAgaWYgKGNvbXBhcmUoYVttaWRdLCB4KSA8IDApIGxvID0gbWlkICsgMTtcbiAgICAgICAgZWxzZSBoaSA9IG1pZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBsbztcbiAgICB9LFxuICAgIHJpZ2h0OiBmdW5jdGlvbihhLCB4LCBsbywgaGkpIHtcbiAgICAgIGlmIChsbyA9PSBudWxsKSBsbyA9IDA7XG4gICAgICBpZiAoaGkgPT0gbnVsbCkgaGkgPSBhLmxlbmd0aDtcbiAgICAgIHdoaWxlIChsbyA8IGhpKSB7XG4gICAgICAgIHZhciBtaWQgPSBsbyArIGhpID4+PiAxO1xuICAgICAgICBpZiAoY29tcGFyZShhW21pZF0sIHgpID4gMCkgaGkgPSBtaWQ7XG4gICAgICAgIGVsc2UgbG8gPSBtaWQgKyAxO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxvO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gYXNjZW5kaW5nQ29tcGFyYXRvcihmKSB7XG4gIHJldHVybiBmdW5jdGlvbihkLCB4KSB7XG4gICAgcmV0dXJuIGFzY2VuZGluZyhmKGQpLCB4KTtcbiAgfTtcbn1cblxudmFyIGFzY2VuZGluZ0Jpc2VjdCA9IGJpc2VjdG9yKGFzY2VuZGluZyk7XG52YXIgYmlzZWN0UmlnaHQgPSBhc2NlbmRpbmdCaXNlY3QucmlnaHQ7XG52YXIgYmlzZWN0TGVmdCA9IGFzY2VuZGluZ0Jpc2VjdC5sZWZ0O1xuXG5mdW5jdGlvbiBwYWlycyhhcnJheSwgZikge1xuICBpZiAoZiA9PSBudWxsKSBmID0gcGFpcjtcbiAgdmFyIGkgPSAwLCBuID0gYXJyYXkubGVuZ3RoIC0gMSwgcCA9IGFycmF5WzBdLCBwYWlycyA9IG5ldyBBcnJheShuIDwgMCA/IDAgOiBuKTtcbiAgd2hpbGUgKGkgPCBuKSBwYWlyc1tpXSA9IGYocCwgcCA9IGFycmF5WysraV0pO1xuICByZXR1cm4gcGFpcnM7XG59XG5cbmZ1bmN0aW9uIHBhaXIoYSwgYikge1xuICByZXR1cm4gW2EsIGJdO1xufVxuXG5mdW5jdGlvbiBjcm9zcyh2YWx1ZXMwLCB2YWx1ZXMxLCByZWR1Y2UpIHtcbiAgdmFyIG4wID0gdmFsdWVzMC5sZW5ndGgsXG4gICAgICBuMSA9IHZhbHVlczEubGVuZ3RoLFxuICAgICAgdmFsdWVzID0gbmV3IEFycmF5KG4wICogbjEpLFxuICAgICAgaTAsXG4gICAgICBpMSxcbiAgICAgIGksXG4gICAgICB2YWx1ZTA7XG5cbiAgaWYgKHJlZHVjZSA9PSBudWxsKSByZWR1Y2UgPSBwYWlyO1xuXG4gIGZvciAoaTAgPSBpID0gMDsgaTAgPCBuMDsgKytpMCkge1xuICAgIGZvciAodmFsdWUwID0gdmFsdWVzMFtpMF0sIGkxID0gMDsgaTEgPCBuMTsgKytpMSwgKytpKSB7XG4gICAgICB2YWx1ZXNbaV0gPSByZWR1Y2UodmFsdWUwLCB2YWx1ZXMxW2kxXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHZhbHVlcztcbn1cblxuZnVuY3Rpb24gZGVzY2VuZGluZyhhLCBiKSB7XG4gIHJldHVybiBiIDwgYSA/IC0xIDogYiA+IGEgPyAxIDogYiA+PSBhID8gMCA6IE5hTjtcbn1cblxuZnVuY3Rpb24gbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGwgPyBOYU4gOiAreDtcbn1cblxuZnVuY3Rpb24gdmFyaWFuY2UodmFsdWVzLCB2YWx1ZW9mKSB7XG4gIHZhciBuID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgIG0gPSAwLFxuICAgICAgaSA9IC0xLFxuICAgICAgbWVhbiA9IDAsXG4gICAgICB2YWx1ZSxcbiAgICAgIGRlbHRhLFxuICAgICAgc3VtID0gMDtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICghaXNOYU4odmFsdWUgPSBudW1iZXIodmFsdWVzW2ldKSkpIHtcbiAgICAgICAgZGVsdGEgPSB2YWx1ZSAtIG1lYW47XG4gICAgICAgIG1lYW4gKz0gZGVsdGEgLyArK207XG4gICAgICAgIHN1bSArPSBkZWx0YSAqICh2YWx1ZSAtIG1lYW4pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAoIWlzTmFOKHZhbHVlID0gbnVtYmVyKHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSkpIHtcbiAgICAgICAgZGVsdGEgPSB2YWx1ZSAtIG1lYW47XG4gICAgICAgIG1lYW4gKz0gZGVsdGEgLyArK207XG4gICAgICAgIHN1bSArPSBkZWx0YSAqICh2YWx1ZSAtIG1lYW4pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChtID4gMSkgcmV0dXJuIHN1bSAvIChtIC0gMSk7XG59XG5cbmZ1bmN0aW9uIGRldmlhdGlvbihhcnJheSwgZikge1xuICB2YXIgdiA9IHZhcmlhbmNlKGFycmF5LCBmKTtcbiAgcmV0dXJuIHYgPyBNYXRoLnNxcnQodikgOiB2O1xufVxuXG5mdW5jdGlvbiBleHRlbnQodmFsdWVzLCB2YWx1ZW9mKSB7XG4gIHZhciBuID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgIGkgPSAtMSxcbiAgICAgIHZhbHVlLFxuICAgICAgbWluLFxuICAgICAgbWF4O1xuXG4gIGlmICh2YWx1ZW9mID09IG51bGwpIHtcbiAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBGaW5kIHRoZSBmaXJzdCBjb21wYXJhYmxlIHZhbHVlLlxuICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlc1tpXSkgIT0gbnVsbCAmJiB2YWx1ZSA+PSB2YWx1ZSkge1xuICAgICAgICBtaW4gPSBtYXggPSB2YWx1ZTtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIHsgLy8gQ29tcGFyZSB0aGUgcmVtYWluaW5nIHZhbHVlcy5cbiAgICAgICAgICBpZiAoKHZhbHVlID0gdmFsdWVzW2ldKSAhPSBudWxsKSB7XG4gICAgICAgICAgICBpZiAobWluID4gdmFsdWUpIG1pbiA9IHZhbHVlO1xuICAgICAgICAgICAgaWYgKG1heCA8IHZhbHVlKSBtYXggPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBlbHNlIHtcbiAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBGaW5kIHRoZSBmaXJzdCBjb21wYXJhYmxlIHZhbHVlLlxuICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSAhPSBudWxsICYmIHZhbHVlID49IHZhbHVlKSB7XG4gICAgICAgIG1pbiA9IG1heCA9IHZhbHVlO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBDb21wYXJlIHRoZSByZW1haW5pbmcgdmFsdWVzLlxuICAgICAgICAgIGlmICgodmFsdWUgPSB2YWx1ZW9mKHZhbHVlc1tpXSwgaSwgdmFsdWVzKSkgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKG1pbiA+IHZhbHVlKSBtaW4gPSB2YWx1ZTtcbiAgICAgICAgICAgIGlmIChtYXggPCB2YWx1ZSkgbWF4ID0gdmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFttaW4sIG1heF07XG59XG5cbnZhciBhcnJheSA9IEFycmF5LnByb3RvdHlwZTtcblxudmFyIHNsaWNlID0gYXJyYXkuc2xpY2U7XG52YXIgbWFwID0gYXJyYXkubWFwO1xuXG5mdW5jdGlvbiBjb25zdGFudCh4KSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4geDtcbiAgfTtcbn1cblxuZnVuY3Rpb24gaWRlbnRpdHkoeCkge1xuICByZXR1cm4geDtcbn1cblxuZnVuY3Rpb24gcmFuZ2Uoc3RhcnQsIHN0b3AsIHN0ZXApIHtcbiAgc3RhcnQgPSArc3RhcnQsIHN0b3AgPSArc3RvcCwgc3RlcCA9IChuID0gYXJndW1lbnRzLmxlbmd0aCkgPCAyID8gKHN0b3AgPSBzdGFydCwgc3RhcnQgPSAwLCAxKSA6IG4gPCAzID8gMSA6ICtzdGVwO1xuXG4gIHZhciBpID0gLTEsXG4gICAgICBuID0gTWF0aC5tYXgoMCwgTWF0aC5jZWlsKChzdG9wIC0gc3RhcnQpIC8gc3RlcCkpIHwgMCxcbiAgICAgIHJhbmdlID0gbmV3IEFycmF5KG4pO1xuXG4gIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgcmFuZ2VbaV0gPSBzdGFydCArIGkgKiBzdGVwO1xuICB9XG5cbiAgcmV0dXJuIHJhbmdlO1xufVxuXG52YXIgZTEwID0gTWF0aC5zcXJ0KDUwKSxcbiAgICBlNSA9IE1hdGguc3FydCgxMCksXG4gICAgZTIgPSBNYXRoLnNxcnQoMik7XG5cbmZ1bmN0aW9uIHRpY2tzKHN0YXJ0LCBzdG9wLCBjb3VudCkge1xuICB2YXIgcmV2ZXJzZSxcbiAgICAgIGkgPSAtMSxcbiAgICAgIG4sXG4gICAgICB0aWNrcyxcbiAgICAgIHN0ZXA7XG5cbiAgc3RvcCA9ICtzdG9wLCBzdGFydCA9ICtzdGFydCwgY291bnQgPSArY291bnQ7XG4gIGlmIChzdGFydCA9PT0gc3RvcCAmJiBjb3VudCA+IDApIHJldHVybiBbc3RhcnRdO1xuICBpZiAocmV2ZXJzZSA9IHN0b3AgPCBzdGFydCkgbiA9IHN0YXJ0LCBzdGFydCA9IHN0b3AsIHN0b3AgPSBuO1xuICBpZiAoKHN0ZXAgPSB0aWNrSW5jcmVtZW50KHN0YXJ0LCBzdG9wLCBjb3VudCkpID09PSAwIHx8ICFpc0Zpbml0ZShzdGVwKSkgcmV0dXJuIFtdO1xuXG4gIGlmIChzdGVwID4gMCkge1xuICAgIHN0YXJ0ID0gTWF0aC5jZWlsKHN0YXJ0IC8gc3RlcCk7XG4gICAgc3RvcCA9IE1hdGguZmxvb3Ioc3RvcCAvIHN0ZXApO1xuICAgIHRpY2tzID0gbmV3IEFycmF5KG4gPSBNYXRoLmNlaWwoc3RvcCAtIHN0YXJ0ICsgMSkpO1xuICAgIHdoaWxlICgrK2kgPCBuKSB0aWNrc1tpXSA9IChzdGFydCArIGkpICogc3RlcDtcbiAgfSBlbHNlIHtcbiAgICBzdGFydCA9IE1hdGguZmxvb3Ioc3RhcnQgKiBzdGVwKTtcbiAgICBzdG9wID0gTWF0aC5jZWlsKHN0b3AgKiBzdGVwKTtcbiAgICB0aWNrcyA9IG5ldyBBcnJheShuID0gTWF0aC5jZWlsKHN0YXJ0IC0gc3RvcCArIDEpKTtcbiAgICB3aGlsZSAoKytpIDwgbikgdGlja3NbaV0gPSAoc3RhcnQgLSBpKSAvIHN0ZXA7XG4gIH1cblxuICBpZiAocmV2ZXJzZSkgdGlja3MucmV2ZXJzZSgpO1xuXG4gIHJldHVybiB0aWNrcztcbn1cblxuZnVuY3Rpb24gdGlja0luY3JlbWVudChzdGFydCwgc3RvcCwgY291bnQpIHtcbiAgdmFyIHN0ZXAgPSAoc3RvcCAtIHN0YXJ0KSAvIE1hdGgubWF4KDAsIGNvdW50KSxcbiAgICAgIHBvd2VyID0gTWF0aC5mbG9vcihNYXRoLmxvZyhzdGVwKSAvIE1hdGguTE4xMCksXG4gICAgICBlcnJvciA9IHN0ZXAgLyBNYXRoLnBvdygxMCwgcG93ZXIpO1xuICByZXR1cm4gcG93ZXIgPj0gMFxuICAgICAgPyAoZXJyb3IgPj0gZTEwID8gMTAgOiBlcnJvciA+PSBlNSA/IDUgOiBlcnJvciA+PSBlMiA/IDIgOiAxKSAqIE1hdGgucG93KDEwLCBwb3dlcilcbiAgICAgIDogLU1hdGgucG93KDEwLCAtcG93ZXIpIC8gKGVycm9yID49IGUxMCA/IDEwIDogZXJyb3IgPj0gZTUgPyA1IDogZXJyb3IgPj0gZTIgPyAyIDogMSk7XG59XG5cbmZ1bmN0aW9uIHRpY2tTdGVwKHN0YXJ0LCBzdG9wLCBjb3VudCkge1xuICB2YXIgc3RlcDAgPSBNYXRoLmFicyhzdG9wIC0gc3RhcnQpIC8gTWF0aC5tYXgoMCwgY291bnQpLFxuICAgICAgc3RlcDEgPSBNYXRoLnBvdygxMCwgTWF0aC5mbG9vcihNYXRoLmxvZyhzdGVwMCkgLyBNYXRoLkxOMTApKSxcbiAgICAgIGVycm9yID0gc3RlcDAgLyBzdGVwMTtcbiAgaWYgKGVycm9yID49IGUxMCkgc3RlcDEgKj0gMTA7XG4gIGVsc2UgaWYgKGVycm9yID49IGU1KSBzdGVwMSAqPSA1O1xuICBlbHNlIGlmIChlcnJvciA+PSBlMikgc3RlcDEgKj0gMjtcbiAgcmV0dXJuIHN0b3AgPCBzdGFydCA/IC1zdGVwMSA6IHN0ZXAxO1xufVxuXG5mdW5jdGlvbiBzdHVyZ2VzKHZhbHVlcykge1xuICByZXR1cm4gTWF0aC5jZWlsKE1hdGgubG9nKHZhbHVlcy5sZW5ndGgpIC8gTWF0aC5MTjIpICsgMTtcbn1cblxuZnVuY3Rpb24gaGlzdG9ncmFtKCkge1xuICB2YXIgdmFsdWUgPSBpZGVudGl0eSxcbiAgICAgIGRvbWFpbiA9IGV4dGVudCxcbiAgICAgIHRocmVzaG9sZCA9IHN0dXJnZXM7XG5cbiAgZnVuY3Rpb24gaGlzdG9ncmFtKGRhdGEpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgbiA9IGRhdGEubGVuZ3RoLFxuICAgICAgICB4LFxuICAgICAgICB2YWx1ZXMgPSBuZXcgQXJyYXkobik7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICB2YWx1ZXNbaV0gPSB2YWx1ZShkYXRhW2ldLCBpLCBkYXRhKTtcbiAgICB9XG5cbiAgICB2YXIgeHogPSBkb21haW4odmFsdWVzKSxcbiAgICAgICAgeDAgPSB4elswXSxcbiAgICAgICAgeDEgPSB4elsxXSxcbiAgICAgICAgdHogPSB0aHJlc2hvbGQodmFsdWVzLCB4MCwgeDEpO1xuXG4gICAgLy8gQ29udmVydCBudW1iZXIgb2YgdGhyZXNob2xkcyBpbnRvIHVuaWZvcm0gdGhyZXNob2xkcy5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodHopKSB7XG4gICAgICB0eiA9IHRpY2tTdGVwKHgwLCB4MSwgdHopO1xuICAgICAgdHogPSByYW5nZShNYXRoLmNlaWwoeDAgLyB0eikgKiB0eiwgeDEsIHR6KTsgLy8gZXhjbHVzaXZlXG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIGFueSB0aHJlc2hvbGRzIG91dHNpZGUgdGhlIGRvbWFpbi5cbiAgICB2YXIgbSA9IHR6Lmxlbmd0aDtcbiAgICB3aGlsZSAodHpbMF0gPD0geDApIHR6LnNoaWZ0KCksIC0tbTtcbiAgICB3aGlsZSAodHpbbSAtIDFdID4geDEpIHR6LnBvcCgpLCAtLW07XG5cbiAgICB2YXIgYmlucyA9IG5ldyBBcnJheShtICsgMSksXG4gICAgICAgIGJpbjtcblxuICAgIC8vIEluaXRpYWxpemUgYmlucy5cbiAgICBmb3IgKGkgPSAwOyBpIDw9IG07ICsraSkge1xuICAgICAgYmluID0gYmluc1tpXSA9IFtdO1xuICAgICAgYmluLngwID0gaSA+IDAgPyB0eltpIC0gMV0gOiB4MDtcbiAgICAgIGJpbi54MSA9IGkgPCBtID8gdHpbaV0gOiB4MTtcbiAgICB9XG5cbiAgICAvLyBBc3NpZ24gZGF0YSB0byBiaW5zIGJ5IHZhbHVlLCBpZ25vcmluZyBhbnkgb3V0c2lkZSB0aGUgZG9tYWluLlxuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHggPSB2YWx1ZXNbaV07XG4gICAgICBpZiAoeDAgPD0geCAmJiB4IDw9IHgxKSB7XG4gICAgICAgIGJpbnNbYmlzZWN0UmlnaHQodHosIHgsIDAsIG0pXS5wdXNoKGRhdGFbaV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBiaW5zO1xuICB9XG5cbiAgaGlzdG9ncmFtLnZhbHVlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChfKSwgaGlzdG9ncmFtKSA6IHZhbHVlO1xuICB9O1xuXG4gIGhpc3RvZ3JhbS5kb21haW4gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChbX1swXSwgX1sxXV0pLCBoaXN0b2dyYW0pIDogZG9tYWluO1xuICB9O1xuXG4gIGhpc3RvZ3JhbS50aHJlc2hvbGRzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRocmVzaG9sZCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogQXJyYXkuaXNBcnJheShfKSA/IGNvbnN0YW50KHNsaWNlLmNhbGwoXykpIDogY29uc3RhbnQoXyksIGhpc3RvZ3JhbSkgOiB0aHJlc2hvbGQ7XG4gIH07XG5cbiAgcmV0dXJuIGhpc3RvZ3JhbTtcbn1cblxuZnVuY3Rpb24gcXVhbnRpbGUodmFsdWVzLCBwLCB2YWx1ZW9mKSB7XG4gIGlmICh2YWx1ZW9mID09IG51bGwpIHZhbHVlb2YgPSBudW1iZXI7XG4gIGlmICghKG4gPSB2YWx1ZXMubGVuZ3RoKSkgcmV0dXJuO1xuICBpZiAoKHAgPSArcCkgPD0gMCB8fCBuIDwgMikgcmV0dXJuICt2YWx1ZW9mKHZhbHVlc1swXSwgMCwgdmFsdWVzKTtcbiAgaWYgKHAgPj0gMSkgcmV0dXJuICt2YWx1ZW9mKHZhbHVlc1tuIC0gMV0sIG4gLSAxLCB2YWx1ZXMpO1xuICB2YXIgbixcbiAgICAgIGkgPSAobiAtIDEpICogcCxcbiAgICAgIGkwID0gTWF0aC5mbG9vcihpKSxcbiAgICAgIHZhbHVlMCA9ICt2YWx1ZW9mKHZhbHVlc1tpMF0sIGkwLCB2YWx1ZXMpLFxuICAgICAgdmFsdWUxID0gK3ZhbHVlb2YodmFsdWVzW2kwICsgMV0sIGkwICsgMSwgdmFsdWVzKTtcbiAgcmV0dXJuIHZhbHVlMCArICh2YWx1ZTEgLSB2YWx1ZTApICogKGkgLSBpMCk7XG59XG5cbmZ1bmN0aW9uIGZyZWVkbWFuRGlhY29uaXModmFsdWVzLCBtaW4sIG1heCkge1xuICB2YWx1ZXMgPSBtYXAuY2FsbCh2YWx1ZXMsIG51bWJlcikuc29ydChhc2NlbmRpbmcpO1xuICByZXR1cm4gTWF0aC5jZWlsKChtYXggLSBtaW4pIC8gKDIgKiAocXVhbnRpbGUodmFsdWVzLCAwLjc1KSAtIHF1YW50aWxlKHZhbHVlcywgMC4yNSkpICogTWF0aC5wb3codmFsdWVzLmxlbmd0aCwgLTEgLyAzKSkpO1xufVxuXG5mdW5jdGlvbiBzY290dCh2YWx1ZXMsIG1pbiwgbWF4KSB7XG4gIHJldHVybiBNYXRoLmNlaWwoKG1heCAtIG1pbikgLyAoMy41ICogZGV2aWF0aW9uKHZhbHVlcykgKiBNYXRoLnBvdyh2YWx1ZXMubGVuZ3RoLCAtMSAvIDMpKSk7XG59XG5cbmZ1bmN0aW9uIG1heCh2YWx1ZXMsIHZhbHVlb2YpIHtcbiAgdmFyIG4gPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgaSA9IC0xLFxuICAgICAgdmFsdWUsXG4gICAgICBtYXg7XG5cbiAgaWYgKHZhbHVlb2YgPT0gbnVsbCkge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVzW2ldKSAhPSBudWxsICYmIHZhbHVlID49IHZhbHVlKSB7XG4gICAgICAgIG1heCA9IHZhbHVlO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBDb21wYXJlIHRoZSByZW1haW5pbmcgdmFsdWVzLlxuICAgICAgICAgIGlmICgodmFsdWUgPSB2YWx1ZXNbaV0pICE9IG51bGwgJiYgdmFsdWUgPiBtYXgpIHtcbiAgICAgICAgICAgIG1heCA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVvZih2YWx1ZXNbaV0sIGksIHZhbHVlcykpICE9IG51bGwgJiYgdmFsdWUgPj0gdmFsdWUpIHtcbiAgICAgICAgbWF4ID0gdmFsdWU7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIENvbXBhcmUgdGhlIHJlbWFpbmluZyB2YWx1ZXMuXG4gICAgICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSAhPSBudWxsICYmIHZhbHVlID4gbWF4KSB7XG4gICAgICAgICAgICBtYXggPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWF4O1xufVxuXG5mdW5jdGlvbiBtZWFuKHZhbHVlcywgdmFsdWVvZikge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICBtID0gbixcbiAgICAgIGkgPSAtMSxcbiAgICAgIHZhbHVlLFxuICAgICAgc3VtID0gMDtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICghaXNOYU4odmFsdWUgPSBudW1iZXIodmFsdWVzW2ldKSkpIHN1bSArPSB2YWx1ZTtcbiAgICAgIGVsc2UgLS1tO1xuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAoIWlzTmFOKHZhbHVlID0gbnVtYmVyKHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSkpIHN1bSArPSB2YWx1ZTtcbiAgICAgIGVsc2UgLS1tO1xuICAgIH1cbiAgfVxuXG4gIGlmIChtKSByZXR1cm4gc3VtIC8gbTtcbn1cblxuZnVuY3Rpb24gbWVkaWFuKHZhbHVlcywgdmFsdWVvZikge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICBpID0gLTEsXG4gICAgICB2YWx1ZSxcbiAgICAgIG51bWJlcnMgPSBbXTtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICghaXNOYU4odmFsdWUgPSBudW1iZXIodmFsdWVzW2ldKSkpIHtcbiAgICAgICAgbnVtYmVycy5wdXNoKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBlbHNlIHtcbiAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgaWYgKCFpc05hTih2YWx1ZSA9IG51bWJlcih2YWx1ZW9mKHZhbHVlc1tpXSwgaSwgdmFsdWVzKSkpKSB7XG4gICAgICAgIG51bWJlcnMucHVzaCh2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHF1YW50aWxlKG51bWJlcnMuc29ydChhc2NlbmRpbmcpLCAwLjUpO1xufVxuXG5mdW5jdGlvbiBtZXJnZShhcnJheXMpIHtcbiAgdmFyIG4gPSBhcnJheXMubGVuZ3RoLFxuICAgICAgbSxcbiAgICAgIGkgPSAtMSxcbiAgICAgIGogPSAwLFxuICAgICAgbWVyZ2VkLFxuICAgICAgYXJyYXk7XG5cbiAgd2hpbGUgKCsraSA8IG4pIGogKz0gYXJyYXlzW2ldLmxlbmd0aDtcbiAgbWVyZ2VkID0gbmV3IEFycmF5KGopO1xuXG4gIHdoaWxlICgtLW4gPj0gMCkge1xuICAgIGFycmF5ID0gYXJyYXlzW25dO1xuICAgIG0gPSBhcnJheS5sZW5ndGg7XG4gICAgd2hpbGUgKC0tbSA+PSAwKSB7XG4gICAgICBtZXJnZWRbLS1qXSA9IGFycmF5W21dO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtZXJnZWQ7XG59XG5cbmZ1bmN0aW9uIG1pbih2YWx1ZXMsIHZhbHVlb2YpIHtcbiAgdmFyIG4gPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgaSA9IC0xLFxuICAgICAgdmFsdWUsXG4gICAgICBtaW47XG5cbiAgaWYgKHZhbHVlb2YgPT0gbnVsbCkge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVzW2ldKSAhPSBudWxsICYmIHZhbHVlID49IHZhbHVlKSB7XG4gICAgICAgIG1pbiA9IHZhbHVlO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBDb21wYXJlIHRoZSByZW1haW5pbmcgdmFsdWVzLlxuICAgICAgICAgIGlmICgodmFsdWUgPSB2YWx1ZXNbaV0pICE9IG51bGwgJiYgbWluID4gdmFsdWUpIHtcbiAgICAgICAgICAgIG1pbiA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVvZih2YWx1ZXNbaV0sIGksIHZhbHVlcykpICE9IG51bGwgJiYgdmFsdWUgPj0gdmFsdWUpIHtcbiAgICAgICAgbWluID0gdmFsdWU7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIENvbXBhcmUgdGhlIHJlbWFpbmluZyB2YWx1ZXMuXG4gICAgICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSAhPSBudWxsICYmIG1pbiA+IHZhbHVlKSB7XG4gICAgICAgICAgICBtaW4gPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWluO1xufVxuXG5mdW5jdGlvbiBwZXJtdXRlKGFycmF5LCBpbmRleGVzKSB7XG4gIHZhciBpID0gaW5kZXhlcy5sZW5ndGgsIHBlcm11dGVzID0gbmV3IEFycmF5KGkpO1xuICB3aGlsZSAoaS0tKSBwZXJtdXRlc1tpXSA9IGFycmF5W2luZGV4ZXNbaV1dO1xuICByZXR1cm4gcGVybXV0ZXM7XG59XG5cbmZ1bmN0aW9uIHNjYW4odmFsdWVzLCBjb21wYXJlKSB7XG4gIGlmICghKG4gPSB2YWx1ZXMubGVuZ3RoKSkgcmV0dXJuO1xuICB2YXIgbixcbiAgICAgIGkgPSAwLFxuICAgICAgaiA9IDAsXG4gICAgICB4aSxcbiAgICAgIHhqID0gdmFsdWVzW2pdO1xuXG4gIGlmIChjb21wYXJlID09IG51bGwpIGNvbXBhcmUgPSBhc2NlbmRpbmc7XG5cbiAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICBpZiAoY29tcGFyZSh4aSA9IHZhbHVlc1tpXSwgeGopIDwgMCB8fCBjb21wYXJlKHhqLCB4aikgIT09IDApIHtcbiAgICAgIHhqID0geGksIGogPSBpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjb21wYXJlKHhqLCB4aikgPT09IDApIHJldHVybiBqO1xufVxuXG5mdW5jdGlvbiBzaHVmZmxlKGFycmF5LCBpMCwgaTEpIHtcbiAgdmFyIG0gPSAoaTEgPT0gbnVsbCA/IGFycmF5Lmxlbmd0aCA6IGkxKSAtIChpMCA9IGkwID09IG51bGwgPyAwIDogK2kwKSxcbiAgICAgIHQsXG4gICAgICBpO1xuXG4gIHdoaWxlIChtKSB7XG4gICAgaSA9IE1hdGgucmFuZG9tKCkgKiBtLS0gfCAwO1xuICAgIHQgPSBhcnJheVttICsgaTBdO1xuICAgIGFycmF5W20gKyBpMF0gPSBhcnJheVtpICsgaTBdO1xuICAgIGFycmF5W2kgKyBpMF0gPSB0O1xuICB9XG5cbiAgcmV0dXJuIGFycmF5O1xufVxuXG5mdW5jdGlvbiBzdW0odmFsdWVzLCB2YWx1ZW9mKSB7XG4gIHZhciBuID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgIGkgPSAtMSxcbiAgICAgIHZhbHVlLFxuICAgICAgc3VtID0gMDtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICh2YWx1ZSA9ICt2YWx1ZXNbaV0pIHN1bSArPSB2YWx1ZTsgLy8gTm90ZTogemVybyBhbmQgbnVsbCBhcmUgZXF1aXZhbGVudC5cbiAgICB9XG4gIH1cblxuICBlbHNlIHtcbiAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgaWYgKHZhbHVlID0gK3ZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSBzdW0gKz0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHN1bTtcbn1cblxuZnVuY3Rpb24gdHJhbnNwb3NlKG1hdHJpeCkge1xuICBpZiAoIShuID0gbWF0cml4Lmxlbmd0aCkpIHJldHVybiBbXTtcbiAgZm9yICh2YXIgaSA9IC0xLCBtID0gbWluKG1hdHJpeCwgbGVuZ3RoKSwgdHJhbnNwb3NlID0gbmV3IEFycmF5KG0pOyArK2kgPCBtOykge1xuICAgIGZvciAodmFyIGogPSAtMSwgbiwgcm93ID0gdHJhbnNwb3NlW2ldID0gbmV3IEFycmF5KG4pOyArK2ogPCBuOykge1xuICAgICAgcm93W2pdID0gbWF0cml4W2pdW2ldO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJhbnNwb3NlO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgoZCkge1xuICByZXR1cm4gZC5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIHppcCgpIHtcbiAgcmV0dXJuIHRyYW5zcG9zZShhcmd1bWVudHMpO1xufVxuXG5leHBvcnRzLmJpc2VjdCA9IGJpc2VjdFJpZ2h0O1xuZXhwb3J0cy5iaXNlY3RSaWdodCA9IGJpc2VjdFJpZ2h0O1xuZXhwb3J0cy5iaXNlY3RMZWZ0ID0gYmlzZWN0TGVmdDtcbmV4cG9ydHMuYXNjZW5kaW5nID0gYXNjZW5kaW5nO1xuZXhwb3J0cy5iaXNlY3RvciA9IGJpc2VjdG9yO1xuZXhwb3J0cy5jcm9zcyA9IGNyb3NzO1xuZXhwb3J0cy5kZXNjZW5kaW5nID0gZGVzY2VuZGluZztcbmV4cG9ydHMuZGV2aWF0aW9uID0gZGV2aWF0aW9uO1xuZXhwb3J0cy5leHRlbnQgPSBleHRlbnQ7XG5leHBvcnRzLmhpc3RvZ3JhbSA9IGhpc3RvZ3JhbTtcbmV4cG9ydHMudGhyZXNob2xkRnJlZWRtYW5EaWFjb25pcyA9IGZyZWVkbWFuRGlhY29uaXM7XG5leHBvcnRzLnRocmVzaG9sZFNjb3R0ID0gc2NvdHQ7XG5leHBvcnRzLnRocmVzaG9sZFN0dXJnZXMgPSBzdHVyZ2VzO1xuZXhwb3J0cy5tYXggPSBtYXg7XG5leHBvcnRzLm1lYW4gPSBtZWFuO1xuZXhwb3J0cy5tZWRpYW4gPSBtZWRpYW47XG5leHBvcnRzLm1lcmdlID0gbWVyZ2U7XG5leHBvcnRzLm1pbiA9IG1pbjtcbmV4cG9ydHMucGFpcnMgPSBwYWlycztcbmV4cG9ydHMucGVybXV0ZSA9IHBlcm11dGU7XG5leHBvcnRzLnF1YW50aWxlID0gcXVhbnRpbGU7XG5leHBvcnRzLnJhbmdlID0gcmFuZ2U7XG5leHBvcnRzLnNjYW4gPSBzY2FuO1xuZXhwb3J0cy5zaHVmZmxlID0gc2h1ZmZsZTtcbmV4cG9ydHMuc3VtID0gc3VtO1xuZXhwb3J0cy50aWNrcyA9IHRpY2tzO1xuZXhwb3J0cy50aWNrSW5jcmVtZW50ID0gdGlja0luY3JlbWVudDtcbmV4cG9ydHMudGlja1N0ZXAgPSB0aWNrU3RlcDtcbmV4cG9ydHMudHJhbnNwb3NlID0gdHJhbnNwb3NlO1xuZXhwb3J0cy52YXJpYW5jZSA9IHZhcmlhbmNlO1xuZXhwb3J0cy56aXAgPSB6aXA7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG5cbn0se31dLDE1MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBodHRwczovL2QzanMub3JnL2QzLWNvbGxlY3Rpb24vIFZlcnNpb24gMS4wLjQuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIHByZWZpeCA9IFwiJFwiO1xuXG5mdW5jdGlvbiBNYXAoKSB7fVxuXG5NYXAucHJvdG90eXBlID0gbWFwLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IE1hcCxcbiAgaGFzOiBmdW5jdGlvbihrZXkpIHtcbiAgICByZXR1cm4gKHByZWZpeCArIGtleSkgaW4gdGhpcztcbiAgfSxcbiAgZ2V0OiBmdW5jdGlvbihrZXkpIHtcbiAgICByZXR1cm4gdGhpc1twcmVmaXggKyBrZXldO1xuICB9LFxuICBzZXQ6IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICB0aGlzW3ByZWZpeCArIGtleV0gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgcmVtb3ZlOiBmdW5jdGlvbihrZXkpIHtcbiAgICB2YXIgcHJvcGVydHkgPSBwcmVmaXggKyBrZXk7XG4gICAgcmV0dXJuIHByb3BlcnR5IGluIHRoaXMgJiYgZGVsZXRlIHRoaXNbcHJvcGVydHldO1xuICB9LFxuICBjbGVhcjogZnVuY3Rpb24oKSB7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gdGhpcykgaWYgKHByb3BlcnR5WzBdID09PSBwcmVmaXgpIGRlbGV0ZSB0aGlzW3Byb3BlcnR5XTtcbiAgfSxcbiAga2V5czogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiB0aGlzKSBpZiAocHJvcGVydHlbMF0gPT09IHByZWZpeCkga2V5cy5wdXNoKHByb3BlcnR5LnNsaWNlKDEpKTtcbiAgICByZXR1cm4ga2V5cztcbiAgfSxcbiAgdmFsdWVzOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsdWVzID0gW107XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gdGhpcykgaWYgKHByb3BlcnR5WzBdID09PSBwcmVmaXgpIHZhbHVlcy5wdXNoKHRoaXNbcHJvcGVydHldKTtcbiAgICByZXR1cm4gdmFsdWVzO1xuICB9LFxuICBlbnRyaWVzOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgZW50cmllcyA9IFtdO1xuICAgIGZvciAodmFyIHByb3BlcnR5IGluIHRoaXMpIGlmIChwcm9wZXJ0eVswXSA9PT0gcHJlZml4KSBlbnRyaWVzLnB1c2goe2tleTogcHJvcGVydHkuc2xpY2UoMSksIHZhbHVlOiB0aGlzW3Byb3BlcnR5XX0pO1xuICAgIHJldHVybiBlbnRyaWVzO1xuICB9LFxuICBzaXplOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgc2l6ZSA9IDA7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gdGhpcykgaWYgKHByb3BlcnR5WzBdID09PSBwcmVmaXgpICsrc2l6ZTtcbiAgICByZXR1cm4gc2l6ZTtcbiAgfSxcbiAgZW1wdHk6IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIHByb3BlcnR5IGluIHRoaXMpIGlmIChwcm9wZXJ0eVswXSA9PT0gcHJlZml4KSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG4gIGVhY2g6IGZ1bmN0aW9uKGYpIHtcbiAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiB0aGlzKSBpZiAocHJvcGVydHlbMF0gPT09IHByZWZpeCkgZih0aGlzW3Byb3BlcnR5XSwgcHJvcGVydHkuc2xpY2UoMSksIHRoaXMpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBtYXAob2JqZWN0LCBmKSB7XG4gIHZhciBtYXAgPSBuZXcgTWFwO1xuXG4gIC8vIENvcHkgY29uc3RydWN0b3IuXG4gIGlmIChvYmplY3QgaW5zdGFuY2VvZiBNYXApIG9iamVjdC5lYWNoKGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHsgbWFwLnNldChrZXksIHZhbHVlKTsgfSk7XG5cbiAgLy8gSW5kZXggYXJyYXkgYnkgbnVtZXJpYyBpbmRleCBvciBzcGVjaWZpZWQga2V5IGZ1bmN0aW9uLlxuICBlbHNlIGlmIChBcnJheS5pc0FycmF5KG9iamVjdCkpIHtcbiAgICB2YXIgaSA9IC0xLFxuICAgICAgICBuID0gb2JqZWN0Lmxlbmd0aCxcbiAgICAgICAgbztcblxuICAgIGlmIChmID09IG51bGwpIHdoaWxlICgrK2kgPCBuKSBtYXAuc2V0KGksIG9iamVjdFtpXSk7XG4gICAgZWxzZSB3aGlsZSAoKytpIDwgbikgbWFwLnNldChmKG8gPSBvYmplY3RbaV0sIGksIG9iamVjdCksIG8pO1xuICB9XG5cbiAgLy8gQ29udmVydCBvYmplY3QgdG8gbWFwLlxuICBlbHNlIGlmIChvYmplY3QpIGZvciAodmFyIGtleSBpbiBvYmplY3QpIG1hcC5zZXQoa2V5LCBvYmplY3Rba2V5XSk7XG5cbiAgcmV0dXJuIG1hcDtcbn1cblxudmFyIG5lc3QgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGtleXMgPSBbXSxcbiAgICAgIHNvcnRLZXlzID0gW10sXG4gICAgICBzb3J0VmFsdWVzLFxuICAgICAgcm9sbHVwLFxuICAgICAgbmVzdDtcblxuICBmdW5jdGlvbiBhcHBseShhcnJheSwgZGVwdGgsIGNyZWF0ZVJlc3VsdCwgc2V0UmVzdWx0KSB7XG4gICAgaWYgKGRlcHRoID49IGtleXMubGVuZ3RoKSB7XG4gICAgICBpZiAoc29ydFZhbHVlcyAhPSBudWxsKSBhcnJheS5zb3J0KHNvcnRWYWx1ZXMpO1xuICAgICAgcmV0dXJuIHJvbGx1cCAhPSBudWxsID8gcm9sbHVwKGFycmF5KSA6IGFycmF5O1xuICAgIH1cblxuICAgIHZhciBpID0gLTEsXG4gICAgICAgIG4gPSBhcnJheS5sZW5ndGgsXG4gICAgICAgIGtleSA9IGtleXNbZGVwdGgrK10sXG4gICAgICAgIGtleVZhbHVlLFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgdmFsdWVzQnlLZXkgPSBtYXAoKSxcbiAgICAgICAgdmFsdWVzLFxuICAgICAgICByZXN1bHQgPSBjcmVhdGVSZXN1bHQoKTtcblxuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAodmFsdWVzID0gdmFsdWVzQnlLZXkuZ2V0KGtleVZhbHVlID0ga2V5KHZhbHVlID0gYXJyYXlbaV0pICsgXCJcIikpIHtcbiAgICAgICAgdmFsdWVzLnB1c2godmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWVzQnlLZXkuc2V0KGtleVZhbHVlLCBbdmFsdWVdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YWx1ZXNCeUtleS5lYWNoKGZ1bmN0aW9uKHZhbHVlcywga2V5KSB7XG4gICAgICBzZXRSZXN1bHQocmVzdWx0LCBrZXksIGFwcGx5KHZhbHVlcywgZGVwdGgsIGNyZWF0ZVJlc3VsdCwgc2V0UmVzdWx0KSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gZW50cmllcyhtYXAkJDEsIGRlcHRoKSB7XG4gICAgaWYgKCsrZGVwdGggPiBrZXlzLmxlbmd0aCkgcmV0dXJuIG1hcCQkMTtcbiAgICB2YXIgYXJyYXksIHNvcnRLZXkgPSBzb3J0S2V5c1tkZXB0aCAtIDFdO1xuICAgIGlmIChyb2xsdXAgIT0gbnVsbCAmJiBkZXB0aCA+PSBrZXlzLmxlbmd0aCkgYXJyYXkgPSBtYXAkJDEuZW50cmllcygpO1xuICAgIGVsc2UgYXJyYXkgPSBbXSwgbWFwJCQxLmVhY2goZnVuY3Rpb24odiwgaykgeyBhcnJheS5wdXNoKHtrZXk6IGssIHZhbHVlczogZW50cmllcyh2LCBkZXB0aCl9KTsgfSk7XG4gICAgcmV0dXJuIHNvcnRLZXkgIT0gbnVsbCA/IGFycmF5LnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gc29ydEtleShhLmtleSwgYi5rZXkpOyB9KSA6IGFycmF5O1xuICB9XG5cbiAgcmV0dXJuIG5lc3QgPSB7XG4gICAgb2JqZWN0OiBmdW5jdGlvbihhcnJheSkgeyByZXR1cm4gYXBwbHkoYXJyYXksIDAsIGNyZWF0ZU9iamVjdCwgc2V0T2JqZWN0KTsgfSxcbiAgICBtYXA6IGZ1bmN0aW9uKGFycmF5KSB7IHJldHVybiBhcHBseShhcnJheSwgMCwgY3JlYXRlTWFwLCBzZXRNYXApOyB9LFxuICAgIGVudHJpZXM6IGZ1bmN0aW9uKGFycmF5KSB7IHJldHVybiBlbnRyaWVzKGFwcGx5KGFycmF5LCAwLCBjcmVhdGVNYXAsIHNldE1hcCksIDApOyB9LFxuICAgIGtleTogZnVuY3Rpb24oZCkgeyBrZXlzLnB1c2goZCk7IHJldHVybiBuZXN0OyB9LFxuICAgIHNvcnRLZXlzOiBmdW5jdGlvbihvcmRlcikgeyBzb3J0S2V5c1trZXlzLmxlbmd0aCAtIDFdID0gb3JkZXI7IHJldHVybiBuZXN0OyB9LFxuICAgIHNvcnRWYWx1ZXM6IGZ1bmN0aW9uKG9yZGVyKSB7IHNvcnRWYWx1ZXMgPSBvcmRlcjsgcmV0dXJuIG5lc3Q7IH0sXG4gICAgcm9sbHVwOiBmdW5jdGlvbihmKSB7IHJvbGx1cCA9IGY7IHJldHVybiBuZXN0OyB9XG4gIH07XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVPYmplY3QoKSB7XG4gIHJldHVybiB7fTtcbn1cblxuZnVuY3Rpb24gc2V0T2JqZWN0KG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICBvYmplY3Rba2V5XSA9IHZhbHVlO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVNYXAoKSB7XG4gIHJldHVybiBtYXAoKTtcbn1cblxuZnVuY3Rpb24gc2V0TWFwKG1hcCQkMSwga2V5LCB2YWx1ZSkge1xuICBtYXAkJDEuc2V0KGtleSwgdmFsdWUpO1xufVxuXG5mdW5jdGlvbiBTZXQoKSB7fVxuXG52YXIgcHJvdG8gPSBtYXAucHJvdG90eXBlO1xuXG5TZXQucHJvdG90eXBlID0gc2V0LnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IFNldCxcbiAgaGFzOiBwcm90by5oYXMsXG4gIGFkZDogZnVuY3Rpb24odmFsdWUpIHtcbiAgICB2YWx1ZSArPSBcIlwiO1xuICAgIHRoaXNbcHJlZml4ICsgdmFsdWVdID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIHJlbW92ZTogcHJvdG8ucmVtb3ZlLFxuICBjbGVhcjogcHJvdG8uY2xlYXIsXG4gIHZhbHVlczogcHJvdG8ua2V5cyxcbiAgc2l6ZTogcHJvdG8uc2l6ZSxcbiAgZW1wdHk6IHByb3RvLmVtcHR5LFxuICBlYWNoOiBwcm90by5lYWNoXG59O1xuXG5mdW5jdGlvbiBzZXQob2JqZWN0LCBmKSB7XG4gIHZhciBzZXQgPSBuZXcgU2V0O1xuXG4gIC8vIENvcHkgY29uc3RydWN0b3IuXG4gIGlmIChvYmplY3QgaW5zdGFuY2VvZiBTZXQpIG9iamVjdC5lYWNoKGZ1bmN0aW9uKHZhbHVlKSB7IHNldC5hZGQodmFsdWUpOyB9KTtcblxuICAvLyBPdGhlcndpc2UsIGFzc3VtZSBpdOKAmXMgYW4gYXJyYXkuXG4gIGVsc2UgaWYgKG9iamVjdCkge1xuICAgIHZhciBpID0gLTEsIG4gPSBvYmplY3QubGVuZ3RoO1xuICAgIGlmIChmID09IG51bGwpIHdoaWxlICgrK2kgPCBuKSBzZXQuYWRkKG9iamVjdFtpXSk7XG4gICAgZWxzZSB3aGlsZSAoKytpIDwgbikgc2V0LmFkZChmKG9iamVjdFtpXSwgaSwgb2JqZWN0KSk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG52YXIga2V5cyA9IGZ1bmN0aW9uKG1hcCkge1xuICB2YXIga2V5cyA9IFtdO1xuICBmb3IgKHZhciBrZXkgaW4gbWFwKSBrZXlzLnB1c2goa2V5KTtcbiAgcmV0dXJuIGtleXM7XG59O1xuXG52YXIgdmFsdWVzID0gZnVuY3Rpb24obWFwKSB7XG4gIHZhciB2YWx1ZXMgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIG1hcCkgdmFsdWVzLnB1c2gobWFwW2tleV0pO1xuICByZXR1cm4gdmFsdWVzO1xufTtcblxudmFyIGVudHJpZXMgPSBmdW5jdGlvbihtYXApIHtcbiAgdmFyIGVudHJpZXMgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIG1hcCkgZW50cmllcy5wdXNoKHtrZXk6IGtleSwgdmFsdWU6IG1hcFtrZXldfSk7XG4gIHJldHVybiBlbnRyaWVzO1xufTtcblxuZXhwb3J0cy5uZXN0ID0gbmVzdDtcbmV4cG9ydHMuc2V0ID0gc2V0O1xuZXhwb3J0cy5tYXAgPSBtYXA7XG5leHBvcnRzLmtleXMgPSBrZXlzO1xuZXhwb3J0cy52YWx1ZXMgPSB2YWx1ZXM7XG5leHBvcnRzLmVudHJpZXMgPSBlbnRyaWVzO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuXG59LHt9XSwxNTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1jb2xvci8gdjEuMi4zIENvcHlyaWdodCAyMDE4IE1pa2UgQm9zdG9ja1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbnR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxudHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG4oZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBkZWZpbmUoY29uc3RydWN0b3IsIGZhY3RvcnksIHByb3RvdHlwZSkge1xuICBjb25zdHJ1Y3Rvci5wcm90b3R5cGUgPSBmYWN0b3J5LnByb3RvdHlwZSA9IHByb3RvdHlwZTtcbiAgcHJvdG90eXBlLmNvbnN0cnVjdG9yID0gY29uc3RydWN0b3I7XG59XG5cbmZ1bmN0aW9uIGV4dGVuZChwYXJlbnQsIGRlZmluaXRpb24pIHtcbiAgdmFyIHByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUocGFyZW50LnByb3RvdHlwZSk7XG4gIGZvciAodmFyIGtleSBpbiBkZWZpbml0aW9uKSBwcm90b3R5cGVba2V5XSA9IGRlZmluaXRpb25ba2V5XTtcbiAgcmV0dXJuIHByb3RvdHlwZTtcbn1cblxuZnVuY3Rpb24gQ29sb3IoKSB7fVxuXG52YXIgZGFya2VyID0gMC43O1xudmFyIGJyaWdodGVyID0gMSAvIGRhcmtlcjtcblxudmFyIHJlSSA9IFwiXFxcXHMqKFsrLV0/XFxcXGQrKVxcXFxzKlwiLFxuICAgIHJlTiA9IFwiXFxcXHMqKFsrLV0/XFxcXGQqXFxcXC4/XFxcXGQrKD86W2VFXVsrLV0/XFxcXGQrKT8pXFxcXHMqXCIsXG4gICAgcmVQID0gXCJcXFxccyooWystXT9cXFxcZCpcXFxcLj9cXFxcZCsoPzpbZUVdWystXT9cXFxcZCspPyklXFxcXHMqXCIsXG4gICAgcmVIZXgzID0gL14jKFswLTlhLWZdezN9KSQvLFxuICAgIHJlSGV4NiA9IC9eIyhbMC05YS1mXXs2fSkkLyxcbiAgICByZVJnYkludGVnZXIgPSBuZXcgUmVnRXhwKFwiXnJnYlxcXFwoXCIgKyBbcmVJLCByZUksIHJlSV0gKyBcIlxcXFwpJFwiKSxcbiAgICByZVJnYlBlcmNlbnQgPSBuZXcgUmVnRXhwKFwiXnJnYlxcXFwoXCIgKyBbcmVQLCByZVAsIHJlUF0gKyBcIlxcXFwpJFwiKSxcbiAgICByZVJnYmFJbnRlZ2VyID0gbmV3IFJlZ0V4cChcIl5yZ2JhXFxcXChcIiArIFtyZUksIHJlSSwgcmVJLCByZU5dICsgXCJcXFxcKSRcIiksXG4gICAgcmVSZ2JhUGVyY2VudCA9IG5ldyBSZWdFeHAoXCJecmdiYVxcXFwoXCIgKyBbcmVQLCByZVAsIHJlUCwgcmVOXSArIFwiXFxcXCkkXCIpLFxuICAgIHJlSHNsUGVyY2VudCA9IG5ldyBSZWdFeHAoXCJeaHNsXFxcXChcIiArIFtyZU4sIHJlUCwgcmVQXSArIFwiXFxcXCkkXCIpLFxuICAgIHJlSHNsYVBlcmNlbnQgPSBuZXcgUmVnRXhwKFwiXmhzbGFcXFxcKFwiICsgW3JlTiwgcmVQLCByZVAsIHJlTl0gKyBcIlxcXFwpJFwiKTtcblxudmFyIG5hbWVkID0ge1xuICBhbGljZWJsdWU6IDB4ZjBmOGZmLFxuICBhbnRpcXVld2hpdGU6IDB4ZmFlYmQ3LFxuICBhcXVhOiAweDAwZmZmZixcbiAgYXF1YW1hcmluZTogMHg3ZmZmZDQsXG4gIGF6dXJlOiAweGYwZmZmZixcbiAgYmVpZ2U6IDB4ZjVmNWRjLFxuICBiaXNxdWU6IDB4ZmZlNGM0LFxuICBibGFjazogMHgwMDAwMDAsXG4gIGJsYW5jaGVkYWxtb25kOiAweGZmZWJjZCxcbiAgYmx1ZTogMHgwMDAwZmYsXG4gIGJsdWV2aW9sZXQ6IDB4OGEyYmUyLFxuICBicm93bjogMHhhNTJhMmEsXG4gIGJ1cmx5d29vZDogMHhkZWI4ODcsXG4gIGNhZGV0Ymx1ZTogMHg1ZjllYTAsXG4gIGNoYXJ0cmV1c2U6IDB4N2ZmZjAwLFxuICBjaG9jb2xhdGU6IDB4ZDI2OTFlLFxuICBjb3JhbDogMHhmZjdmNTAsXG4gIGNvcm5mbG93ZXJibHVlOiAweDY0OTVlZCxcbiAgY29ybnNpbGs6IDB4ZmZmOGRjLFxuICBjcmltc29uOiAweGRjMTQzYyxcbiAgY3lhbjogMHgwMGZmZmYsXG4gIGRhcmtibHVlOiAweDAwMDA4YixcbiAgZGFya2N5YW46IDB4MDA4YjhiLFxuICBkYXJrZ29sZGVucm9kOiAweGI4ODYwYixcbiAgZGFya2dyYXk6IDB4YTlhOWE5LFxuICBkYXJrZ3JlZW46IDB4MDA2NDAwLFxuICBkYXJrZ3JleTogMHhhOWE5YTksXG4gIGRhcmtraGFraTogMHhiZGI3NmIsXG4gIGRhcmttYWdlbnRhOiAweDhiMDA4YixcbiAgZGFya29saXZlZ3JlZW46IDB4NTU2YjJmLFxuICBkYXJrb3JhbmdlOiAweGZmOGMwMCxcbiAgZGFya29yY2hpZDogMHg5OTMyY2MsXG4gIGRhcmtyZWQ6IDB4OGIwMDAwLFxuICBkYXJrc2FsbW9uOiAweGU5OTY3YSxcbiAgZGFya3NlYWdyZWVuOiAweDhmYmM4ZixcbiAgZGFya3NsYXRlYmx1ZTogMHg0ODNkOGIsXG4gIGRhcmtzbGF0ZWdyYXk6IDB4MmY0ZjRmLFxuICBkYXJrc2xhdGVncmV5OiAweDJmNGY0ZixcbiAgZGFya3R1cnF1b2lzZTogMHgwMGNlZDEsXG4gIGRhcmt2aW9sZXQ6IDB4OTQwMGQzLFxuICBkZWVwcGluazogMHhmZjE0OTMsXG4gIGRlZXBza3libHVlOiAweDAwYmZmZixcbiAgZGltZ3JheTogMHg2OTY5NjksXG4gIGRpbWdyZXk6IDB4Njk2OTY5LFxuICBkb2RnZXJibHVlOiAweDFlOTBmZixcbiAgZmlyZWJyaWNrOiAweGIyMjIyMixcbiAgZmxvcmFsd2hpdGU6IDB4ZmZmYWYwLFxuICBmb3Jlc3RncmVlbjogMHgyMjhiMjIsXG4gIGZ1Y2hzaWE6IDB4ZmYwMGZmLFxuICBnYWluc2Jvcm86IDB4ZGNkY2RjLFxuICBnaG9zdHdoaXRlOiAweGY4ZjhmZixcbiAgZ29sZDogMHhmZmQ3MDAsXG4gIGdvbGRlbnJvZDogMHhkYWE1MjAsXG4gIGdyYXk6IDB4ODA4MDgwLFxuICBncmVlbjogMHgwMDgwMDAsXG4gIGdyZWVueWVsbG93OiAweGFkZmYyZixcbiAgZ3JleTogMHg4MDgwODAsXG4gIGhvbmV5ZGV3OiAweGYwZmZmMCxcbiAgaG90cGluazogMHhmZjY5YjQsXG4gIGluZGlhbnJlZDogMHhjZDVjNWMsXG4gIGluZGlnbzogMHg0YjAwODIsXG4gIGl2b3J5OiAweGZmZmZmMCxcbiAga2hha2k6IDB4ZjBlNjhjLFxuICBsYXZlbmRlcjogMHhlNmU2ZmEsXG4gIGxhdmVuZGVyYmx1c2g6IDB4ZmZmMGY1LFxuICBsYXduZ3JlZW46IDB4N2NmYzAwLFxuICBsZW1vbmNoaWZmb246IDB4ZmZmYWNkLFxuICBsaWdodGJsdWU6IDB4YWRkOGU2LFxuICBsaWdodGNvcmFsOiAweGYwODA4MCxcbiAgbGlnaHRjeWFuOiAweGUwZmZmZixcbiAgbGlnaHRnb2xkZW5yb2R5ZWxsb3c6IDB4ZmFmYWQyLFxuICBsaWdodGdyYXk6IDB4ZDNkM2QzLFxuICBsaWdodGdyZWVuOiAweDkwZWU5MCxcbiAgbGlnaHRncmV5OiAweGQzZDNkMyxcbiAgbGlnaHRwaW5rOiAweGZmYjZjMSxcbiAgbGlnaHRzYWxtb246IDB4ZmZhMDdhLFxuICBsaWdodHNlYWdyZWVuOiAweDIwYjJhYSxcbiAgbGlnaHRza3libHVlOiAweDg3Y2VmYSxcbiAgbGlnaHRzbGF0ZWdyYXk6IDB4Nzc4ODk5LFxuICBsaWdodHNsYXRlZ3JleTogMHg3Nzg4OTksXG4gIGxpZ2h0c3RlZWxibHVlOiAweGIwYzRkZSxcbiAgbGlnaHR5ZWxsb3c6IDB4ZmZmZmUwLFxuICBsaW1lOiAweDAwZmYwMCxcbiAgbGltZWdyZWVuOiAweDMyY2QzMixcbiAgbGluZW46IDB4ZmFmMGU2LFxuICBtYWdlbnRhOiAweGZmMDBmZixcbiAgbWFyb29uOiAweDgwMDAwMCxcbiAgbWVkaXVtYXF1YW1hcmluZTogMHg2NmNkYWEsXG4gIG1lZGl1bWJsdWU6IDB4MDAwMGNkLFxuICBtZWRpdW1vcmNoaWQ6IDB4YmE1NWQzLFxuICBtZWRpdW1wdXJwbGU6IDB4OTM3MGRiLFxuICBtZWRpdW1zZWFncmVlbjogMHgzY2IzNzEsXG4gIG1lZGl1bXNsYXRlYmx1ZTogMHg3YjY4ZWUsXG4gIG1lZGl1bXNwcmluZ2dyZWVuOiAweDAwZmE5YSxcbiAgbWVkaXVtdHVycXVvaXNlOiAweDQ4ZDFjYyxcbiAgbWVkaXVtdmlvbGV0cmVkOiAweGM3MTU4NSxcbiAgbWlkbmlnaHRibHVlOiAweDE5MTk3MCxcbiAgbWludGNyZWFtOiAweGY1ZmZmYSxcbiAgbWlzdHlyb3NlOiAweGZmZTRlMSxcbiAgbW9jY2FzaW46IDB4ZmZlNGI1LFxuICBuYXZham93aGl0ZTogMHhmZmRlYWQsXG4gIG5hdnk6IDB4MDAwMDgwLFxuICBvbGRsYWNlOiAweGZkZjVlNixcbiAgb2xpdmU6IDB4ODA4MDAwLFxuICBvbGl2ZWRyYWI6IDB4NmI4ZTIzLFxuICBvcmFuZ2U6IDB4ZmZhNTAwLFxuICBvcmFuZ2VyZWQ6IDB4ZmY0NTAwLFxuICBvcmNoaWQ6IDB4ZGE3MGQ2LFxuICBwYWxlZ29sZGVucm9kOiAweGVlZThhYSxcbiAgcGFsZWdyZWVuOiAweDk4ZmI5OCxcbiAgcGFsZXR1cnF1b2lzZTogMHhhZmVlZWUsXG4gIHBhbGV2aW9sZXRyZWQ6IDB4ZGI3MDkzLFxuICBwYXBheWF3aGlwOiAweGZmZWZkNSxcbiAgcGVhY2hwdWZmOiAweGZmZGFiOSxcbiAgcGVydTogMHhjZDg1M2YsXG4gIHBpbms6IDB4ZmZjMGNiLFxuICBwbHVtOiAweGRkYTBkZCxcbiAgcG93ZGVyYmx1ZTogMHhiMGUwZTYsXG4gIHB1cnBsZTogMHg4MDAwODAsXG4gIHJlYmVjY2FwdXJwbGU6IDB4NjYzMzk5LFxuICByZWQ6IDB4ZmYwMDAwLFxuICByb3N5YnJvd246IDB4YmM4ZjhmLFxuICByb3lhbGJsdWU6IDB4NDE2OWUxLFxuICBzYWRkbGVicm93bjogMHg4YjQ1MTMsXG4gIHNhbG1vbjogMHhmYTgwNzIsXG4gIHNhbmR5YnJvd246IDB4ZjRhNDYwLFxuICBzZWFncmVlbjogMHgyZThiNTcsXG4gIHNlYXNoZWxsOiAweGZmZjVlZSxcbiAgc2llbm5hOiAweGEwNTIyZCxcbiAgc2lsdmVyOiAweGMwYzBjMCxcbiAgc2t5Ymx1ZTogMHg4N2NlZWIsXG4gIHNsYXRlYmx1ZTogMHg2YTVhY2QsXG4gIHNsYXRlZ3JheTogMHg3MDgwOTAsXG4gIHNsYXRlZ3JleTogMHg3MDgwOTAsXG4gIHNub3c6IDB4ZmZmYWZhLFxuICBzcHJpbmdncmVlbjogMHgwMGZmN2YsXG4gIHN0ZWVsYmx1ZTogMHg0NjgyYjQsXG4gIHRhbjogMHhkMmI0OGMsXG4gIHRlYWw6IDB4MDA4MDgwLFxuICB0aGlzdGxlOiAweGQ4YmZkOCxcbiAgdG9tYXRvOiAweGZmNjM0NyxcbiAgdHVycXVvaXNlOiAweDQwZTBkMCxcbiAgdmlvbGV0OiAweGVlODJlZSxcbiAgd2hlYXQ6IDB4ZjVkZWIzLFxuICB3aGl0ZTogMHhmZmZmZmYsXG4gIHdoaXRlc21va2U6IDB4ZjVmNWY1LFxuICB5ZWxsb3c6IDB4ZmZmZjAwLFxuICB5ZWxsb3dncmVlbjogMHg5YWNkMzJcbn07XG5cbmRlZmluZShDb2xvciwgY29sb3IsIHtcbiAgZGlzcGxheWFibGU6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnJnYigpLmRpc3BsYXlhYmxlKCk7XG4gIH0sXG4gIGhleDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMucmdiKCkuaGV4KCk7XG4gIH0sXG4gIHRvU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5yZ2IoKSArIFwiXCI7XG4gIH1cbn0pO1xuXG5mdW5jdGlvbiBjb2xvcihmb3JtYXQpIHtcbiAgdmFyIG07XG4gIGZvcm1hdCA9IChmb3JtYXQgKyBcIlwiKS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIChtID0gcmVIZXgzLmV4ZWMoZm9ybWF0KSkgPyAobSA9IHBhcnNlSW50KG1bMV0sIDE2KSwgbmV3IFJnYigobSA+PiA4ICYgMHhmKSB8IChtID4+IDQgJiAweDBmMCksIChtID4+IDQgJiAweGYpIHwgKG0gJiAweGYwKSwgKChtICYgMHhmKSA8PCA0KSB8IChtICYgMHhmKSwgMSkpIC8vICNmMDBcbiAgICAgIDogKG0gPSByZUhleDYuZXhlYyhmb3JtYXQpKSA/IHJnYm4ocGFyc2VJbnQobVsxXSwgMTYpKSAvLyAjZmYwMDAwXG4gICAgICA6IChtID0gcmVSZ2JJbnRlZ2VyLmV4ZWMoZm9ybWF0KSkgPyBuZXcgUmdiKG1bMV0sIG1bMl0sIG1bM10sIDEpIC8vIHJnYigyNTUsIDAsIDApXG4gICAgICA6IChtID0gcmVSZ2JQZXJjZW50LmV4ZWMoZm9ybWF0KSkgPyBuZXcgUmdiKG1bMV0gKiAyNTUgLyAxMDAsIG1bMl0gKiAyNTUgLyAxMDAsIG1bM10gKiAyNTUgLyAxMDAsIDEpIC8vIHJnYigxMDAlLCAwJSwgMCUpXG4gICAgICA6IChtID0gcmVSZ2JhSW50ZWdlci5leGVjKGZvcm1hdCkpID8gcmdiYShtWzFdLCBtWzJdLCBtWzNdLCBtWzRdKSAvLyByZ2JhKDI1NSwgMCwgMCwgMSlcbiAgICAgIDogKG0gPSByZVJnYmFQZXJjZW50LmV4ZWMoZm9ybWF0KSkgPyByZ2JhKG1bMV0gKiAyNTUgLyAxMDAsIG1bMl0gKiAyNTUgLyAxMDAsIG1bM10gKiAyNTUgLyAxMDAsIG1bNF0pIC8vIHJnYigxMDAlLCAwJSwgMCUsIDEpXG4gICAgICA6IChtID0gcmVIc2xQZXJjZW50LmV4ZWMoZm9ybWF0KSkgPyBoc2xhKG1bMV0sIG1bMl0gLyAxMDAsIG1bM10gLyAxMDAsIDEpIC8vIGhzbCgxMjAsIDUwJSwgNTAlKVxuICAgICAgOiAobSA9IHJlSHNsYVBlcmNlbnQuZXhlYyhmb3JtYXQpKSA/IGhzbGEobVsxXSwgbVsyXSAvIDEwMCwgbVszXSAvIDEwMCwgbVs0XSkgLy8gaHNsYSgxMjAsIDUwJSwgNTAlLCAxKVxuICAgICAgOiBuYW1lZC5oYXNPd25Qcm9wZXJ0eShmb3JtYXQpID8gcmdibihuYW1lZFtmb3JtYXRdKVxuICAgICAgOiBmb3JtYXQgPT09IFwidHJhbnNwYXJlbnRcIiA/IG5ldyBSZ2IoTmFOLCBOYU4sIE5hTiwgMClcbiAgICAgIDogbnVsbDtcbn1cblxuZnVuY3Rpb24gcmdibihuKSB7XG4gIHJldHVybiBuZXcgUmdiKG4gPj4gMTYgJiAweGZmLCBuID4+IDggJiAweGZmLCBuICYgMHhmZiwgMSk7XG59XG5cbmZ1bmN0aW9uIHJnYmEociwgZywgYiwgYSkge1xuICBpZiAoYSA8PSAwKSByID0gZyA9IGIgPSBOYU47XG4gIHJldHVybiBuZXcgUmdiKHIsIGcsIGIsIGEpO1xufVxuXG5mdW5jdGlvbiByZ2JDb252ZXJ0KG8pIHtcbiAgaWYgKCEobyBpbnN0YW5jZW9mIENvbG9yKSkgbyA9IGNvbG9yKG8pO1xuICBpZiAoIW8pIHJldHVybiBuZXcgUmdiO1xuICBvID0gby5yZ2IoKTtcbiAgcmV0dXJuIG5ldyBSZ2Ioby5yLCBvLmcsIG8uYiwgby5vcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gcmdiKHIsIGcsIGIsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyByZ2JDb252ZXJ0KHIpIDogbmV3IFJnYihyLCBnLCBiLCBvcGFjaXR5ID09IG51bGwgPyAxIDogb3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIFJnYihyLCBnLCBiLCBvcGFjaXR5KSB7XG4gIHRoaXMuciA9ICtyO1xuICB0aGlzLmcgPSArZztcbiAgdGhpcy5iID0gK2I7XG4gIHRoaXMub3BhY2l0eSA9ICtvcGFjaXR5O1xufVxuXG5kZWZpbmUoUmdiLCByZ2IsIGV4dGVuZChDb2xvciwge1xuICBicmlnaHRlcjogZnVuY3Rpb24oaykge1xuICAgIGsgPSBrID09IG51bGwgPyBicmlnaHRlciA6IE1hdGgucG93KGJyaWdodGVyLCBrKTtcbiAgICByZXR1cm4gbmV3IFJnYih0aGlzLnIgKiBrLCB0aGlzLmcgKiBrLCB0aGlzLmIgKiBrLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICBkYXJrZXI6IGZ1bmN0aW9uKGspIHtcbiAgICBrID0gayA9PSBudWxsID8gZGFya2VyIDogTWF0aC5wb3coZGFya2VyLCBrKTtcbiAgICByZXR1cm4gbmV3IFJnYih0aGlzLnIgKiBrLCB0aGlzLmcgKiBrLCB0aGlzLmIgKiBrLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICByZ2I6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBkaXNwbGF5YWJsZTogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICgwIDw9IHRoaXMuciAmJiB0aGlzLnIgPD0gMjU1KVxuICAgICAgICAmJiAoMCA8PSB0aGlzLmcgJiYgdGhpcy5nIDw9IDI1NSlcbiAgICAgICAgJiYgKDAgPD0gdGhpcy5iICYmIHRoaXMuYiA8PSAyNTUpXG4gICAgICAgICYmICgwIDw9IHRoaXMub3BhY2l0eSAmJiB0aGlzLm9wYWNpdHkgPD0gMSk7XG4gIH0sXG4gIGhleDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIFwiI1wiICsgaGV4KHRoaXMucikgKyBoZXgodGhpcy5nKSArIGhleCh0aGlzLmIpO1xuICB9LFxuICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGEgPSB0aGlzLm9wYWNpdHk7IGEgPSBpc05hTihhKSA/IDEgOiBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBhKSk7XG4gICAgcmV0dXJuIChhID09PSAxID8gXCJyZ2IoXCIgOiBcInJnYmEoXCIpXG4gICAgICAgICsgTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBNYXRoLnJvdW5kKHRoaXMucikgfHwgMCkpICsgXCIsIFwiXG4gICAgICAgICsgTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBNYXRoLnJvdW5kKHRoaXMuZykgfHwgMCkpICsgXCIsIFwiXG4gICAgICAgICsgTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBNYXRoLnJvdW5kKHRoaXMuYikgfHwgMCkpXG4gICAgICAgICsgKGEgPT09IDEgPyBcIilcIiA6IFwiLCBcIiArIGEgKyBcIilcIik7XG4gIH1cbn0pKTtcblxuZnVuY3Rpb24gaGV4KHZhbHVlKSB7XG4gIHZhbHVlID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBNYXRoLnJvdW5kKHZhbHVlKSB8fCAwKSk7XG4gIHJldHVybiAodmFsdWUgPCAxNiA/IFwiMFwiIDogXCJcIikgKyB2YWx1ZS50b1N0cmluZygxNik7XG59XG5cbmZ1bmN0aW9uIGhzbGEoaCwgcywgbCwgYSkge1xuICBpZiAoYSA8PSAwKSBoID0gcyA9IGwgPSBOYU47XG4gIGVsc2UgaWYgKGwgPD0gMCB8fCBsID49IDEpIGggPSBzID0gTmFOO1xuICBlbHNlIGlmIChzIDw9IDApIGggPSBOYU47XG4gIHJldHVybiBuZXcgSHNsKGgsIHMsIGwsIGEpO1xufVxuXG5mdW5jdGlvbiBoc2xDb252ZXJ0KG8pIHtcbiAgaWYgKG8gaW5zdGFuY2VvZiBIc2wpIHJldHVybiBuZXcgSHNsKG8uaCwgby5zLCBvLmwsIG8ub3BhY2l0eSk7XG4gIGlmICghKG8gaW5zdGFuY2VvZiBDb2xvcikpIG8gPSBjb2xvcihvKTtcbiAgaWYgKCFvKSByZXR1cm4gbmV3IEhzbDtcbiAgaWYgKG8gaW5zdGFuY2VvZiBIc2wpIHJldHVybiBvO1xuICBvID0gby5yZ2IoKTtcbiAgdmFyIHIgPSBvLnIgLyAyNTUsXG4gICAgICBnID0gby5nIC8gMjU1LFxuICAgICAgYiA9IG8uYiAvIDI1NSxcbiAgICAgIG1pbiA9IE1hdGgubWluKHIsIGcsIGIpLFxuICAgICAgbWF4ID0gTWF0aC5tYXgociwgZywgYiksXG4gICAgICBoID0gTmFOLFxuICAgICAgcyA9IG1heCAtIG1pbixcbiAgICAgIGwgPSAobWF4ICsgbWluKSAvIDI7XG4gIGlmIChzKSB7XG4gICAgaWYgKHIgPT09IG1heCkgaCA9IChnIC0gYikgLyBzICsgKGcgPCBiKSAqIDY7XG4gICAgZWxzZSBpZiAoZyA9PT0gbWF4KSBoID0gKGIgLSByKSAvIHMgKyAyO1xuICAgIGVsc2UgaCA9IChyIC0gZykgLyBzICsgNDtcbiAgICBzIC89IGwgPCAwLjUgPyBtYXggKyBtaW4gOiAyIC0gbWF4IC0gbWluO1xuICAgIGggKj0gNjA7XG4gIH0gZWxzZSB7XG4gICAgcyA9IGwgPiAwICYmIGwgPCAxID8gMCA6IGg7XG4gIH1cbiAgcmV0dXJuIG5ldyBIc2woaCwgcywgbCwgby5vcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gaHNsKGgsIHMsIGwsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyBoc2xDb252ZXJ0KGgpIDogbmV3IEhzbChoLCBzLCBsLCBvcGFjaXR5ID09IG51bGwgPyAxIDogb3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIEhzbChoLCBzLCBsLCBvcGFjaXR5KSB7XG4gIHRoaXMuaCA9ICtoO1xuICB0aGlzLnMgPSArcztcbiAgdGhpcy5sID0gK2w7XG4gIHRoaXMub3BhY2l0eSA9ICtvcGFjaXR5O1xufVxuXG5kZWZpbmUoSHNsLCBoc2wsIGV4dGVuZChDb2xvciwge1xuICBicmlnaHRlcjogZnVuY3Rpb24oaykge1xuICAgIGsgPSBrID09IG51bGwgPyBicmlnaHRlciA6IE1hdGgucG93KGJyaWdodGVyLCBrKTtcbiAgICByZXR1cm4gbmV3IEhzbCh0aGlzLmgsIHRoaXMucywgdGhpcy5sICogaywgdGhpcy5vcGFjaXR5KTtcbiAgfSxcbiAgZGFya2VyOiBmdW5jdGlvbihrKSB7XG4gICAgayA9IGsgPT0gbnVsbCA/IGRhcmtlciA6IE1hdGgucG93KGRhcmtlciwgayk7XG4gICAgcmV0dXJuIG5ldyBIc2wodGhpcy5oLCB0aGlzLnMsIHRoaXMubCAqIGssIHRoaXMub3BhY2l0eSk7XG4gIH0sXG4gIHJnYjogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGggPSB0aGlzLmggJSAzNjAgKyAodGhpcy5oIDwgMCkgKiAzNjAsXG4gICAgICAgIHMgPSBpc05hTihoKSB8fCBpc05hTih0aGlzLnMpID8gMCA6IHRoaXMucyxcbiAgICAgICAgbCA9IHRoaXMubCxcbiAgICAgICAgbTIgPSBsICsgKGwgPCAwLjUgPyBsIDogMSAtIGwpICogcyxcbiAgICAgICAgbTEgPSAyICogbCAtIG0yO1xuICAgIHJldHVybiBuZXcgUmdiKFxuICAgICAgaHNsMnJnYihoID49IDI0MCA/IGggLSAyNDAgOiBoICsgMTIwLCBtMSwgbTIpLFxuICAgICAgaHNsMnJnYihoLCBtMSwgbTIpLFxuICAgICAgaHNsMnJnYihoIDwgMTIwID8gaCArIDI0MCA6IGggLSAxMjAsIG0xLCBtMiksXG4gICAgICB0aGlzLm9wYWNpdHlcbiAgICApO1xuICB9LFxuICBkaXNwbGF5YWJsZTogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICgwIDw9IHRoaXMucyAmJiB0aGlzLnMgPD0gMSB8fCBpc05hTih0aGlzLnMpKVxuICAgICAgICAmJiAoMCA8PSB0aGlzLmwgJiYgdGhpcy5sIDw9IDEpXG4gICAgICAgICYmICgwIDw9IHRoaXMub3BhY2l0eSAmJiB0aGlzLm9wYWNpdHkgPD0gMSk7XG4gIH1cbn0pKTtcblxuLyogRnJvbSBGdkQgMTMuMzcsIENTUyBDb2xvciBNb2R1bGUgTGV2ZWwgMyAqL1xuZnVuY3Rpb24gaHNsMnJnYihoLCBtMSwgbTIpIHtcbiAgcmV0dXJuIChoIDwgNjAgPyBtMSArIChtMiAtIG0xKSAqIGggLyA2MFxuICAgICAgOiBoIDwgMTgwID8gbTJcbiAgICAgIDogaCA8IDI0MCA/IG0xICsgKG0yIC0gbTEpICogKDI0MCAtIGgpIC8gNjBcbiAgICAgIDogbTEpICogMjU1O1xufVxuXG52YXIgZGVnMnJhZCA9IE1hdGguUEkgLyAxODA7XG52YXIgcmFkMmRlZyA9IDE4MCAvIE1hdGguUEk7XG5cbi8vIGh0dHBzOi8vYmV0YS5vYnNlcnZhYmxlaHEuY29tL0BtYm9zdG9jay9sYWItYW5kLXJnYlxudmFyIEsgPSAxOCxcbiAgICBYbiA9IDAuOTY0MjIsXG4gICAgWW4gPSAxLFxuICAgIFpuID0gMC44MjUyMSxcbiAgICB0MCA9IDQgLyAyOSxcbiAgICB0MSA9IDYgLyAyOSxcbiAgICB0MiA9IDMgKiB0MSAqIHQxLFxuICAgIHQzID0gdDEgKiB0MSAqIHQxO1xuXG5mdW5jdGlvbiBsYWJDb252ZXJ0KG8pIHtcbiAgaWYgKG8gaW5zdGFuY2VvZiBMYWIpIHJldHVybiBuZXcgTGFiKG8ubCwgby5hLCBvLmIsIG8ub3BhY2l0eSk7XG4gIGlmIChvIGluc3RhbmNlb2YgSGNsKSB7XG4gICAgaWYgKGlzTmFOKG8uaCkpIHJldHVybiBuZXcgTGFiKG8ubCwgMCwgMCwgby5vcGFjaXR5KTtcbiAgICB2YXIgaCA9IG8uaCAqIGRlZzJyYWQ7XG4gICAgcmV0dXJuIG5ldyBMYWIoby5sLCBNYXRoLmNvcyhoKSAqIG8uYywgTWF0aC5zaW4oaCkgKiBvLmMsIG8ub3BhY2l0eSk7XG4gIH1cbiAgaWYgKCEobyBpbnN0YW5jZW9mIFJnYikpIG8gPSByZ2JDb252ZXJ0KG8pO1xuICB2YXIgciA9IHJnYjJscmdiKG8uciksXG4gICAgICBnID0gcmdiMmxyZ2Ioby5nKSxcbiAgICAgIGIgPSByZ2IybHJnYihvLmIpLFxuICAgICAgeSA9IHh5ejJsYWIoKDAuMjIyNTA0NSAqIHIgKyAwLjcxNjg3ODYgKiBnICsgMC4wNjA2MTY5ICogYikgLyBZbiksIHgsIHo7XG4gIGlmIChyID09PSBnICYmIGcgPT09IGIpIHggPSB6ID0geTsgZWxzZSB7XG4gICAgeCA9IHh5ejJsYWIoKDAuNDM2MDc0NyAqIHIgKyAwLjM4NTA2NDkgKiBnICsgMC4xNDMwODA0ICogYikgLyBYbik7XG4gICAgeiA9IHh5ejJsYWIoKDAuMDEzOTMyMiAqIHIgKyAwLjA5NzEwNDUgKiBnICsgMC43MTQxNzMzICogYikgLyBabik7XG4gIH1cbiAgcmV0dXJuIG5ldyBMYWIoMTE2ICogeSAtIDE2LCA1MDAgKiAoeCAtIHkpLCAyMDAgKiAoeSAtIHopLCBvLm9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBncmF5KGwsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIG5ldyBMYWIobCwgMCwgMCwgb3BhY2l0eSA9PSBudWxsID8gMSA6IG9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBsYWIobCwgYSwgYiwgb3BhY2l0eSkge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/IGxhYkNvbnZlcnQobCkgOiBuZXcgTGFiKGwsIGEsIGIsIG9wYWNpdHkgPT0gbnVsbCA/IDEgOiBvcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gTGFiKGwsIGEsIGIsIG9wYWNpdHkpIHtcbiAgdGhpcy5sID0gK2w7XG4gIHRoaXMuYSA9ICthO1xuICB0aGlzLmIgPSArYjtcbiAgdGhpcy5vcGFjaXR5ID0gK29wYWNpdHk7XG59XG5cbmRlZmluZShMYWIsIGxhYiwgZXh0ZW5kKENvbG9yLCB7XG4gIGJyaWdodGVyOiBmdW5jdGlvbihrKSB7XG4gICAgcmV0dXJuIG5ldyBMYWIodGhpcy5sICsgSyAqIChrID09IG51bGwgPyAxIDogayksIHRoaXMuYSwgdGhpcy5iLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICBkYXJrZXI6IGZ1bmN0aW9uKGspIHtcbiAgICByZXR1cm4gbmV3IExhYih0aGlzLmwgLSBLICogKGsgPT0gbnVsbCA/IDEgOiBrKSwgdGhpcy5hLCB0aGlzLmIsIHRoaXMub3BhY2l0eSk7XG4gIH0sXG4gIHJnYjogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHkgPSAodGhpcy5sICsgMTYpIC8gMTE2LFxuICAgICAgICB4ID0gaXNOYU4odGhpcy5hKSA/IHkgOiB5ICsgdGhpcy5hIC8gNTAwLFxuICAgICAgICB6ID0gaXNOYU4odGhpcy5iKSA/IHkgOiB5IC0gdGhpcy5iIC8gMjAwO1xuICAgIHggPSBYbiAqIGxhYjJ4eXooeCk7XG4gICAgeSA9IFluICogbGFiMnh5eih5KTtcbiAgICB6ID0gWm4gKiBsYWIyeHl6KHopO1xuICAgIHJldHVybiBuZXcgUmdiKFxuICAgICAgbHJnYjJyZ2IoIDMuMTMzODU2MSAqIHggLSAxLjYxNjg2NjcgKiB5IC0gMC40OTA2MTQ2ICogeiksXG4gICAgICBscmdiMnJnYigtMC45Nzg3Njg0ICogeCArIDEuOTE2MTQxNSAqIHkgKyAwLjAzMzQ1NDAgKiB6KSxcbiAgICAgIGxyZ2IycmdiKCAwLjA3MTk0NTMgKiB4IC0gMC4yMjg5OTE0ICogeSArIDEuNDA1MjQyNyAqIHopLFxuICAgICAgdGhpcy5vcGFjaXR5XG4gICAgKTtcbiAgfVxufSkpO1xuXG5mdW5jdGlvbiB4eXoybGFiKHQpIHtcbiAgcmV0dXJuIHQgPiB0MyA/IE1hdGgucG93KHQsIDEgLyAzKSA6IHQgLyB0MiArIHQwO1xufVxuXG5mdW5jdGlvbiBsYWIyeHl6KHQpIHtcbiAgcmV0dXJuIHQgPiB0MSA/IHQgKiB0ICogdCA6IHQyICogKHQgLSB0MCk7XG59XG5cbmZ1bmN0aW9uIGxyZ2IycmdiKHgpIHtcbiAgcmV0dXJuIDI1NSAqICh4IDw9IDAuMDAzMTMwOCA/IDEyLjkyICogeCA6IDEuMDU1ICogTWF0aC5wb3coeCwgMSAvIDIuNCkgLSAwLjA1NSk7XG59XG5cbmZ1bmN0aW9uIHJnYjJscmdiKHgpIHtcbiAgcmV0dXJuICh4IC89IDI1NSkgPD0gMC4wNDA0NSA/IHggLyAxMi45MiA6IE1hdGgucG93KCh4ICsgMC4wNTUpIC8gMS4wNTUsIDIuNCk7XG59XG5cbmZ1bmN0aW9uIGhjbENvbnZlcnQobykge1xuICBpZiAobyBpbnN0YW5jZW9mIEhjbCkgcmV0dXJuIG5ldyBIY2woby5oLCBvLmMsIG8ubCwgby5vcGFjaXR5KTtcbiAgaWYgKCEobyBpbnN0YW5jZW9mIExhYikpIG8gPSBsYWJDb252ZXJ0KG8pO1xuICBpZiAoby5hID09PSAwICYmIG8uYiA9PT0gMCkgcmV0dXJuIG5ldyBIY2woTmFOLCAwLCBvLmwsIG8ub3BhY2l0eSk7XG4gIHZhciBoID0gTWF0aC5hdGFuMihvLmIsIG8uYSkgKiByYWQyZGVnO1xuICByZXR1cm4gbmV3IEhjbChoIDwgMCA/IGggKyAzNjAgOiBoLCBNYXRoLnNxcnQoby5hICogby5hICsgby5iICogby5iKSwgby5sLCBvLm9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBsY2gobCwgYywgaCwgb3BhY2l0eSkge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/IGhjbENvbnZlcnQobCkgOiBuZXcgSGNsKGgsIGMsIGwsIG9wYWNpdHkgPT0gbnVsbCA/IDEgOiBvcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gaGNsKGgsIGMsIGwsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyBoY2xDb252ZXJ0KGgpIDogbmV3IEhjbChoLCBjLCBsLCBvcGFjaXR5ID09IG51bGwgPyAxIDogb3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIEhjbChoLCBjLCBsLCBvcGFjaXR5KSB7XG4gIHRoaXMuaCA9ICtoO1xuICB0aGlzLmMgPSArYztcbiAgdGhpcy5sID0gK2w7XG4gIHRoaXMub3BhY2l0eSA9ICtvcGFjaXR5O1xufVxuXG5kZWZpbmUoSGNsLCBoY2wsIGV4dGVuZChDb2xvciwge1xuICBicmlnaHRlcjogZnVuY3Rpb24oaykge1xuICAgIHJldHVybiBuZXcgSGNsKHRoaXMuaCwgdGhpcy5jLCB0aGlzLmwgKyBLICogKGsgPT0gbnVsbCA/IDEgOiBrKSwgdGhpcy5vcGFjaXR5KTtcbiAgfSxcbiAgZGFya2VyOiBmdW5jdGlvbihrKSB7XG4gICAgcmV0dXJuIG5ldyBIY2wodGhpcy5oLCB0aGlzLmMsIHRoaXMubCAtIEsgKiAoayA9PSBudWxsID8gMSA6IGspLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICByZ2I6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBsYWJDb252ZXJ0KHRoaXMpLnJnYigpO1xuICB9XG59KSk7XG5cbnZhciBBID0gLTAuMTQ4NjEsXG4gICAgQiA9ICsxLjc4Mjc3LFxuICAgIEMgPSAtMC4yOTIyNyxcbiAgICBEID0gLTAuOTA2NDksXG4gICAgRSA9ICsxLjk3Mjk0LFxuICAgIEVEID0gRSAqIEQsXG4gICAgRUIgPSBFICogQixcbiAgICBCQ19EQSA9IEIgKiBDIC0gRCAqIEE7XG5cbmZ1bmN0aW9uIGN1YmVoZWxpeENvbnZlcnQobykge1xuICBpZiAobyBpbnN0YW5jZW9mIEN1YmVoZWxpeCkgcmV0dXJuIG5ldyBDdWJlaGVsaXgoby5oLCBvLnMsIG8ubCwgby5vcGFjaXR5KTtcbiAgaWYgKCEobyBpbnN0YW5jZW9mIFJnYikpIG8gPSByZ2JDb252ZXJ0KG8pO1xuICB2YXIgciA9IG8uciAvIDI1NSxcbiAgICAgIGcgPSBvLmcgLyAyNTUsXG4gICAgICBiID0gby5iIC8gMjU1LFxuICAgICAgbCA9IChCQ19EQSAqIGIgKyBFRCAqIHIgLSBFQiAqIGcpIC8gKEJDX0RBICsgRUQgLSBFQiksXG4gICAgICBibCA9IGIgLSBsLFxuICAgICAgayA9IChFICogKGcgLSBsKSAtIEMgKiBibCkgLyBELFxuICAgICAgcyA9IE1hdGguc3FydChrICogayArIGJsICogYmwpIC8gKEUgKiBsICogKDEgLSBsKSksIC8vIE5hTiBpZiBsPTAgb3IgbD0xXG4gICAgICBoID0gcyA/IE1hdGguYXRhbjIoaywgYmwpICogcmFkMmRlZyAtIDEyMCA6IE5hTjtcbiAgcmV0dXJuIG5ldyBDdWJlaGVsaXgoaCA8IDAgPyBoICsgMzYwIDogaCwgcywgbCwgby5vcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gY3ViZWhlbGl4KGgsIHMsIGwsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyBjdWJlaGVsaXhDb252ZXJ0KGgpIDogbmV3IEN1YmVoZWxpeChoLCBzLCBsLCBvcGFjaXR5ID09IG51bGwgPyAxIDogb3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIEN1YmVoZWxpeChoLCBzLCBsLCBvcGFjaXR5KSB7XG4gIHRoaXMuaCA9ICtoO1xuICB0aGlzLnMgPSArcztcbiAgdGhpcy5sID0gK2w7XG4gIHRoaXMub3BhY2l0eSA9ICtvcGFjaXR5O1xufVxuXG5kZWZpbmUoQ3ViZWhlbGl4LCBjdWJlaGVsaXgsIGV4dGVuZChDb2xvciwge1xuICBicmlnaHRlcjogZnVuY3Rpb24oaykge1xuICAgIGsgPSBrID09IG51bGwgPyBicmlnaHRlciA6IE1hdGgucG93KGJyaWdodGVyLCBrKTtcbiAgICByZXR1cm4gbmV3IEN1YmVoZWxpeCh0aGlzLmgsIHRoaXMucywgdGhpcy5sICogaywgdGhpcy5vcGFjaXR5KTtcbiAgfSxcbiAgZGFya2VyOiBmdW5jdGlvbihrKSB7XG4gICAgayA9IGsgPT0gbnVsbCA/IGRhcmtlciA6IE1hdGgucG93KGRhcmtlciwgayk7XG4gICAgcmV0dXJuIG5ldyBDdWJlaGVsaXgodGhpcy5oLCB0aGlzLnMsIHRoaXMubCAqIGssIHRoaXMub3BhY2l0eSk7XG4gIH0sXG4gIHJnYjogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGggPSBpc05hTih0aGlzLmgpID8gMCA6ICh0aGlzLmggKyAxMjApICogZGVnMnJhZCxcbiAgICAgICAgbCA9ICt0aGlzLmwsXG4gICAgICAgIGEgPSBpc05hTih0aGlzLnMpID8gMCA6IHRoaXMucyAqIGwgKiAoMSAtIGwpLFxuICAgICAgICBjb3NoID0gTWF0aC5jb3MoaCksXG4gICAgICAgIHNpbmggPSBNYXRoLnNpbihoKTtcbiAgICByZXR1cm4gbmV3IFJnYihcbiAgICAgIDI1NSAqIChsICsgYSAqIChBICogY29zaCArIEIgKiBzaW5oKSksXG4gICAgICAyNTUgKiAobCArIGEgKiAoQyAqIGNvc2ggKyBEICogc2luaCkpLFxuICAgICAgMjU1ICogKGwgKyBhICogKEUgKiBjb3NoKSksXG4gICAgICB0aGlzLm9wYWNpdHlcbiAgICApO1xuICB9XG59KSk7XG5cbmV4cG9ydHMuY29sb3IgPSBjb2xvcjtcbmV4cG9ydHMucmdiID0gcmdiO1xuZXhwb3J0cy5oc2wgPSBoc2w7XG5leHBvcnRzLmxhYiA9IGxhYjtcbmV4cG9ydHMuaGNsID0gaGNsO1xuZXhwb3J0cy5sY2ggPSBsY2g7XG5leHBvcnRzLmdyYXkgPSBncmF5O1xuZXhwb3J0cy5jdWJlaGVsaXggPSBjdWJlaGVsaXg7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG5cbn0se31dLDE1NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBodHRwczovL2QzanMub3JnL2QzLWRpc3BhdGNoLyBWZXJzaW9uIDEuMC4zLiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciBub29wID0ge3ZhbHVlOiBmdW5jdGlvbigpIHt9fTtcblxuZnVuY3Rpb24gZGlzcGF0Y2goKSB7XG4gIGZvciAodmFyIGkgPSAwLCBuID0gYXJndW1lbnRzLmxlbmd0aCwgXyA9IHt9LCB0OyBpIDwgbjsgKytpKSB7XG4gICAgaWYgKCEodCA9IGFyZ3VtZW50c1tpXSArIFwiXCIpIHx8ICh0IGluIF8pKSB0aHJvdyBuZXcgRXJyb3IoXCJpbGxlZ2FsIHR5cGU6IFwiICsgdCk7XG4gICAgX1t0XSA9IFtdO1xuICB9XG4gIHJldHVybiBuZXcgRGlzcGF0Y2goXyk7XG59XG5cbmZ1bmN0aW9uIERpc3BhdGNoKF8pIHtcbiAgdGhpcy5fID0gXztcbn1cblxuZnVuY3Rpb24gcGFyc2VUeXBlbmFtZXModHlwZW5hbWVzLCB0eXBlcykge1xuICByZXR1cm4gdHlwZW5hbWVzLnRyaW0oKS5zcGxpdCgvXnxcXHMrLykubWFwKGZ1bmN0aW9uKHQpIHtcbiAgICB2YXIgbmFtZSA9IFwiXCIsIGkgPSB0LmluZGV4T2YoXCIuXCIpO1xuICAgIGlmIChpID49IDApIG5hbWUgPSB0LnNsaWNlKGkgKyAxKSwgdCA9IHQuc2xpY2UoMCwgaSk7XG4gICAgaWYgKHQgJiYgIXR5cGVzLmhhc093blByb3BlcnR5KHQpKSB0aHJvdyBuZXcgRXJyb3IoXCJ1bmtub3duIHR5cGU6IFwiICsgdCk7XG4gICAgcmV0dXJuIHt0eXBlOiB0LCBuYW1lOiBuYW1lfTtcbiAgfSk7XG59XG5cbkRpc3BhdGNoLnByb3RvdHlwZSA9IGRpc3BhdGNoLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IERpc3BhdGNoLFxuICBvbjogZnVuY3Rpb24odHlwZW5hbWUsIGNhbGxiYWNrKSB7XG4gICAgdmFyIF8gPSB0aGlzLl8sXG4gICAgICAgIFQgPSBwYXJzZVR5cGVuYW1lcyh0eXBlbmFtZSArIFwiXCIsIF8pLFxuICAgICAgICB0LFxuICAgICAgICBpID0gLTEsXG4gICAgICAgIG4gPSBULmxlbmd0aDtcblxuICAgIC8vIElmIG5vIGNhbGxiYWNrIHdhcyBzcGVjaWZpZWQsIHJldHVybiB0aGUgY2FsbGJhY2sgb2YgdGhlIGdpdmVuIHR5cGUgYW5kIG5hbWUuXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKCh0ID0gKHR5cGVuYW1lID0gVFtpXSkudHlwZSkgJiYgKHQgPSBnZXQoX1t0XSwgdHlwZW5hbWUubmFtZSkpKSByZXR1cm4gdDtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBJZiBhIHR5cGUgd2FzIHNwZWNpZmllZCwgc2V0IHRoZSBjYWxsYmFjayBmb3IgdGhlIGdpdmVuIHR5cGUgYW5kIG5hbWUuXG4gICAgLy8gT3RoZXJ3aXNlLCBpZiBhIG51bGwgY2FsbGJhY2sgd2FzIHNwZWNpZmllZCwgcmVtb3ZlIGNhbGxiYWNrcyBvZiB0aGUgZ2l2ZW4gbmFtZS5cbiAgICBpZiAoY2FsbGJhY2sgIT0gbnVsbCAmJiB0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBjYWxsYmFjazogXCIgKyBjYWxsYmFjayk7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICh0ID0gKHR5cGVuYW1lID0gVFtpXSkudHlwZSkgX1t0XSA9IHNldChfW3RdLCB0eXBlbmFtZS5uYW1lLCBjYWxsYmFjayk7XG4gICAgICBlbHNlIGlmIChjYWxsYmFjayA9PSBudWxsKSBmb3IgKHQgaW4gXykgX1t0XSA9IHNldChfW3RdLCB0eXBlbmFtZS5uYW1lLCBudWxsKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgY29weTogZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNvcHkgPSB7fSwgXyA9IHRoaXMuXztcbiAgICBmb3IgKHZhciB0IGluIF8pIGNvcHlbdF0gPSBfW3RdLnNsaWNlKCk7XG4gICAgcmV0dXJuIG5ldyBEaXNwYXRjaChjb3B5KTtcbiAgfSxcbiAgY2FsbDogZnVuY3Rpb24odHlwZSwgdGhhdCkge1xuICAgIGlmICgobiA9IGFyZ3VtZW50cy5sZW5ndGggLSAyKSA+IDApIGZvciAodmFyIGFyZ3MgPSBuZXcgQXJyYXkobiksIGkgPSAwLCBuLCB0OyBpIDwgbjsgKytpKSBhcmdzW2ldID0gYXJndW1lbnRzW2kgKyAyXTtcbiAgICBpZiAoIXRoaXMuXy5oYXNPd25Qcm9wZXJ0eSh0eXBlKSkgdGhyb3cgbmV3IEVycm9yKFwidW5rbm93biB0eXBlOiBcIiArIHR5cGUpO1xuICAgIGZvciAodCA9IHRoaXMuX1t0eXBlXSwgaSA9IDAsIG4gPSB0Lmxlbmd0aDsgaSA8IG47ICsraSkgdFtpXS52YWx1ZS5hcHBseSh0aGF0LCBhcmdzKTtcbiAgfSxcbiAgYXBwbHk6IGZ1bmN0aW9uKHR5cGUsIHRoYXQsIGFyZ3MpIHtcbiAgICBpZiAoIXRoaXMuXy5oYXNPd25Qcm9wZXJ0eSh0eXBlKSkgdGhyb3cgbmV3IEVycm9yKFwidW5rbm93biB0eXBlOiBcIiArIHR5cGUpO1xuICAgIGZvciAodmFyIHQgPSB0aGlzLl9bdHlwZV0sIGkgPSAwLCBuID0gdC5sZW5ndGg7IGkgPCBuOyArK2kpIHRbaV0udmFsdWUuYXBwbHkodGhhdCwgYXJncyk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGdldCh0eXBlLCBuYW1lKSB7XG4gIGZvciAodmFyIGkgPSAwLCBuID0gdHlwZS5sZW5ndGgsIGM7IGkgPCBuOyArK2kpIHtcbiAgICBpZiAoKGMgPSB0eXBlW2ldKS5uYW1lID09PSBuYW1lKSB7XG4gICAgICByZXR1cm4gYy52YWx1ZTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gc2V0KHR5cGUsIG5hbWUsIGNhbGxiYWNrKSB7XG4gIGZvciAodmFyIGkgPSAwLCBuID0gdHlwZS5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICBpZiAodHlwZVtpXS5uYW1lID09PSBuYW1lKSB7XG4gICAgICB0eXBlW2ldID0gbm9vcCwgdHlwZSA9IHR5cGUuc2xpY2UoMCwgaSkuY29uY2F0KHR5cGUuc2xpY2UoaSArIDEpKTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICBpZiAoY2FsbGJhY2sgIT0gbnVsbCkgdHlwZS5wdXNoKHtuYW1lOiBuYW1lLCB2YWx1ZTogY2FsbGJhY2t9KTtcbiAgcmV0dXJuIHR5cGU7XG59XG5cbmV4cG9ydHMuZGlzcGF0Y2ggPSBkaXNwYXRjaDtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcblxufSx7fV0sMTU2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtZm9yY2UvIFZlcnNpb24gMS4xLjAuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cywgX2RlcmVxXygnZDMtcXVhZHRyZWUnKSwgX2RlcmVxXygnZDMtY29sbGVjdGlvbicpLCBfZGVyZXFfKCdkMy1kaXNwYXRjaCcpLCBfZGVyZXFfKCdkMy10aW1lcicpKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtcXVhZHRyZWUnLCAnZDMtY29sbGVjdGlvbicsICdkMy1kaXNwYXRjaCcsICdkMy10aW1lciddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pLGdsb2JhbC5kMyxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMykpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMsZDNRdWFkdHJlZSxkM0NvbGxlY3Rpb24sZDNEaXNwYXRjaCxkM1RpbWVyKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIGNlbnRlciA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgdmFyIG5vZGVzO1xuXG4gIGlmICh4ID09IG51bGwpIHggPSAwO1xuICBpZiAoeSA9PSBudWxsKSB5ID0gMDtcblxuICBmdW5jdGlvbiBmb3JjZSgpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgICAgbm9kZSxcbiAgICAgICAgc3ggPSAwLFxuICAgICAgICBzeSA9IDA7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBub2RlID0gbm9kZXNbaV0sIHN4ICs9IG5vZGUueCwgc3kgKz0gbm9kZS55O1xuICAgIH1cblxuICAgIGZvciAoc3ggPSBzeCAvIG4gLSB4LCBzeSA9IHN5IC8gbiAtIHksIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBub2RlID0gbm9kZXNbaV0sIG5vZGUueCAtPSBzeCwgbm9kZS55IC09IHN5O1xuICAgIH1cbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfO1xuICB9O1xuXG4gIGZvcmNlLnggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeCA9ICtfLCBmb3JjZSkgOiB4O1xuICB9O1xuXG4gIGZvcmNlLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSA9ICtfLCBmb3JjZSkgOiB5O1xuICB9O1xuXG4gIHJldHVybiBmb3JjZTtcbn07XG5cbnZhciBjb25zdGFudCA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufTtcblxudmFyIGppZ2dsZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gKE1hdGgucmFuZG9tKCkgLSAwLjUpICogMWUtNjtcbn07XG5cbmZ1bmN0aW9uIHgoZCkge1xuICByZXR1cm4gZC54ICsgZC52eDtcbn1cblxuZnVuY3Rpb24geShkKSB7XG4gIHJldHVybiBkLnkgKyBkLnZ5O1xufVxuXG52YXIgY29sbGlkZSA9IGZ1bmN0aW9uKHJhZGl1cykge1xuICB2YXIgbm9kZXMsXG4gICAgICByYWRpaSxcbiAgICAgIHN0cmVuZ3RoID0gMSxcbiAgICAgIGl0ZXJhdGlvbnMgPSAxO1xuXG4gIGlmICh0eXBlb2YgcmFkaXVzICE9PSBcImZ1bmN0aW9uXCIpIHJhZGl1cyA9IGNvbnN0YW50KHJhZGl1cyA9PSBudWxsID8gMSA6ICtyYWRpdXMpO1xuXG4gIGZ1bmN0aW9uIGZvcmNlKCkge1xuICAgIHZhciBpLCBuID0gbm9kZXMubGVuZ3RoLFxuICAgICAgICB0cmVlLFxuICAgICAgICBub2RlLFxuICAgICAgICB4aSxcbiAgICAgICAgeWksXG4gICAgICAgIHJpLFxuICAgICAgICByaTI7XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IGl0ZXJhdGlvbnM7ICsraykge1xuICAgICAgdHJlZSA9IGQzUXVhZHRyZWUucXVhZHRyZWUobm9kZXMsIHgsIHkpLnZpc2l0QWZ0ZXIocHJlcGFyZSk7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgcmkgPSByYWRpaVtub2RlLmluZGV4XSwgcmkyID0gcmkgKiByaTtcbiAgICAgICAgeGkgPSBub2RlLnggKyBub2RlLnZ4O1xuICAgICAgICB5aSA9IG5vZGUueSArIG5vZGUudnk7XG4gICAgICAgIHRyZWUudmlzaXQoYXBwbHkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFwcGx5KHF1YWQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gICAgICB2YXIgZGF0YSA9IHF1YWQuZGF0YSwgcmogPSBxdWFkLnIsIHIgPSByaSArIHJqO1xuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgaWYgKGRhdGEuaW5kZXggPiBub2RlLmluZGV4KSB7XG4gICAgICAgICAgdmFyIHggPSB4aSAtIGRhdGEueCAtIGRhdGEudngsXG4gICAgICAgICAgICAgIHkgPSB5aSAtIGRhdGEueSAtIGRhdGEudnksXG4gICAgICAgICAgICAgIGwgPSB4ICogeCArIHkgKiB5O1xuICAgICAgICAgIGlmIChsIDwgciAqIHIpIHtcbiAgICAgICAgICAgIGlmICh4ID09PSAwKSB4ID0gamlnZ2xlKCksIGwgKz0geCAqIHg7XG4gICAgICAgICAgICBpZiAoeSA9PT0gMCkgeSA9IGppZ2dsZSgpLCBsICs9IHkgKiB5O1xuICAgICAgICAgICAgbCA9IChyIC0gKGwgPSBNYXRoLnNxcnQobCkpKSAvIGwgKiBzdHJlbmd0aDtcbiAgICAgICAgICAgIG5vZGUudnggKz0gKHggKj0gbCkgKiAociA9IChyaiAqPSByaikgLyAocmkyICsgcmopKTtcbiAgICAgICAgICAgIG5vZGUudnkgKz0gKHkgKj0gbCkgKiByO1xuICAgICAgICAgICAgZGF0YS52eCAtPSB4ICogKHIgPSAxIC0gcik7XG4gICAgICAgICAgICBkYXRhLnZ5IC09IHkgKiByO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICByZXR1cm4geDAgPiB4aSArIHIgfHwgeDEgPCB4aSAtIHIgfHwgeTAgPiB5aSArIHIgfHwgeTEgPCB5aSAtIHI7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcHJlcGFyZShxdWFkKSB7XG4gICAgaWYgKHF1YWQuZGF0YSkgcmV0dXJuIHF1YWQuciA9IHJhZGlpW3F1YWQuZGF0YS5pbmRleF07XG4gICAgZm9yICh2YXIgaSA9IHF1YWQuciA9IDA7IGkgPCA0OyArK2kpIHtcbiAgICAgIGlmIChxdWFkW2ldICYmIHF1YWRbaV0uciA+IHF1YWQucikge1xuICAgICAgICBxdWFkLnIgPSBxdWFkW2ldLnI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG4gICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGgsIG5vZGU7XG4gICAgcmFkaWkgPSBuZXcgQXJyYXkobik7XG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkgbm9kZSA9IG5vZGVzW2ldLCByYWRpaVtub2RlLmluZGV4XSA9ICtyYWRpdXMobm9kZSwgaSwgbm9kZXMpO1xuICB9XG5cbiAgZm9yY2UuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICBub2RlcyA9IF87XG4gICAgaW5pdGlhbGl6ZSgpO1xuICB9O1xuXG4gIGZvcmNlLml0ZXJhdGlvbnMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaXRlcmF0aW9ucyA9ICtfLCBmb3JjZSkgOiBpdGVyYXRpb25zO1xuICB9O1xuXG4gIGZvcmNlLnN0cmVuZ3RoID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0cmVuZ3RoID0gK18sIGZvcmNlKSA6IHN0cmVuZ3RoO1xuICB9O1xuXG4gIGZvcmNlLnJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyYWRpdXMgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgaW5pdGlhbGl6ZSgpLCBmb3JjZSkgOiByYWRpdXM7XG4gIH07XG5cbiAgcmV0dXJuIGZvcmNlO1xufTtcblxuZnVuY3Rpb24gaW5kZXgoZCkge1xuICByZXR1cm4gZC5pbmRleDtcbn1cblxuZnVuY3Rpb24gZmluZChub2RlQnlJZCwgbm9kZUlkKSB7XG4gIHZhciBub2RlID0gbm9kZUJ5SWQuZ2V0KG5vZGVJZCk7XG4gIGlmICghbm9kZSkgdGhyb3cgbmV3IEVycm9yKFwibWlzc2luZzogXCIgKyBub2RlSWQpO1xuICByZXR1cm4gbm9kZTtcbn1cblxudmFyIGxpbmsgPSBmdW5jdGlvbihsaW5rcykge1xuICB2YXIgaWQgPSBpbmRleCxcbiAgICAgIHN0cmVuZ3RoID0gZGVmYXVsdFN0cmVuZ3RoLFxuICAgICAgc3RyZW5ndGhzLFxuICAgICAgZGlzdGFuY2UgPSBjb25zdGFudCgzMCksXG4gICAgICBkaXN0YW5jZXMsXG4gICAgICBub2RlcyxcbiAgICAgIGNvdW50LFxuICAgICAgYmlhcyxcbiAgICAgIGl0ZXJhdGlvbnMgPSAxO1xuXG4gIGlmIChsaW5rcyA9PSBudWxsKSBsaW5rcyA9IFtdO1xuXG4gIGZ1bmN0aW9uIGRlZmF1bHRTdHJlbmd0aChsaW5rKSB7XG4gICAgcmV0dXJuIDEgLyBNYXRoLm1pbihjb3VudFtsaW5rLnNvdXJjZS5pbmRleF0sIGNvdW50W2xpbmsudGFyZ2V0LmluZGV4XSk7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JjZShhbHBoYSkge1xuICAgIGZvciAodmFyIGsgPSAwLCBuID0gbGlua3MubGVuZ3RoOyBrIDwgaXRlcmF0aW9uczsgKytrKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgbGluaywgc291cmNlLCB0YXJnZXQsIHgsIHksIGwsIGI7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgbGluayA9IGxpbmtzW2ldLCBzb3VyY2UgPSBsaW5rLnNvdXJjZSwgdGFyZ2V0ID0gbGluay50YXJnZXQ7XG4gICAgICAgIHggPSB0YXJnZXQueCArIHRhcmdldC52eCAtIHNvdXJjZS54IC0gc291cmNlLnZ4IHx8IGppZ2dsZSgpO1xuICAgICAgICB5ID0gdGFyZ2V0LnkgKyB0YXJnZXQudnkgLSBzb3VyY2UueSAtIHNvdXJjZS52eSB8fCBqaWdnbGUoKTtcbiAgICAgICAgbCA9IE1hdGguc3FydCh4ICogeCArIHkgKiB5KTtcbiAgICAgICAgbCA9IChsIC0gZGlzdGFuY2VzW2ldKSAvIGwgKiBhbHBoYSAqIHN0cmVuZ3Roc1tpXTtcbiAgICAgICAgeCAqPSBsLCB5ICo9IGw7XG4gICAgICAgIHRhcmdldC52eCAtPSB4ICogKGIgPSBiaWFzW2ldKTtcbiAgICAgICAgdGFyZ2V0LnZ5IC09IHkgKiBiO1xuICAgICAgICBzb3VyY2UudnggKz0geCAqIChiID0gMSAtIGIpO1xuICAgICAgICBzb3VyY2UudnkgKz0geSAqIGI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG5cbiAgICB2YXIgaSxcbiAgICAgICAgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgICAgbSA9IGxpbmtzLmxlbmd0aCxcbiAgICAgICAgbm9kZUJ5SWQgPSBkM0NvbGxlY3Rpb24ubWFwKG5vZGVzLCBpZCksXG4gICAgICAgIGxpbms7XG5cbiAgICBmb3IgKGkgPSAwLCBjb3VudCA9IG5ldyBBcnJheShuKTsgaSA8IG07ICsraSkge1xuICAgICAgbGluayA9IGxpbmtzW2ldLCBsaW5rLmluZGV4ID0gaTtcbiAgICAgIGlmICh0eXBlb2YgbGluay5zb3VyY2UgIT09IFwib2JqZWN0XCIpIGxpbmsuc291cmNlID0gZmluZChub2RlQnlJZCwgbGluay5zb3VyY2UpO1xuICAgICAgaWYgKHR5cGVvZiBsaW5rLnRhcmdldCAhPT0gXCJvYmplY3RcIikgbGluay50YXJnZXQgPSBmaW5kKG5vZGVCeUlkLCBsaW5rLnRhcmdldCk7XG4gICAgICBjb3VudFtsaW5rLnNvdXJjZS5pbmRleF0gPSAoY291bnRbbGluay5zb3VyY2UuaW5kZXhdIHx8IDApICsgMTtcbiAgICAgIGNvdW50W2xpbmsudGFyZ2V0LmluZGV4XSA9IChjb3VudFtsaW5rLnRhcmdldC5pbmRleF0gfHwgMCkgKyAxO1xuICAgIH1cblxuICAgIGZvciAoaSA9IDAsIGJpYXMgPSBuZXcgQXJyYXkobSk7IGkgPCBtOyArK2kpIHtcbiAgICAgIGxpbmsgPSBsaW5rc1tpXSwgYmlhc1tpXSA9IGNvdW50W2xpbmsuc291cmNlLmluZGV4XSAvIChjb3VudFtsaW5rLnNvdXJjZS5pbmRleF0gKyBjb3VudFtsaW5rLnRhcmdldC5pbmRleF0pO1xuICAgIH1cblxuICAgIHN0cmVuZ3RocyA9IG5ldyBBcnJheShtKSwgaW5pdGlhbGl6ZVN0cmVuZ3RoKCk7XG4gICAgZGlzdGFuY2VzID0gbmV3IEFycmF5KG0pLCBpbml0aWFsaXplRGlzdGFuY2UoKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemVTdHJlbmd0aCgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbiA9IGxpbmtzLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgc3RyZW5ndGhzW2ldID0gK3N0cmVuZ3RoKGxpbmtzW2ldLCBpLCBsaW5rcyk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZURpc3RhbmNlKCkge1xuICAgIGlmICghbm9kZXMpIHJldHVybjtcblxuICAgIGZvciAodmFyIGkgPSAwLCBuID0gbGlua3MubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICBkaXN0YW5jZXNbaV0gPSArZGlzdGFuY2UobGlua3NbaV0sIGksIGxpbmtzKTtcbiAgICB9XG4gIH1cblxuICBmb3JjZS5pbml0aWFsaXplID0gZnVuY3Rpb24oXykge1xuICAgIG5vZGVzID0gXztcbiAgICBpbml0aWFsaXplKCk7XG4gIH07XG5cbiAgZm9yY2UubGlua3MgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobGlua3MgPSBfLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IGxpbmtzO1xuICB9O1xuXG4gIGZvcmNlLmlkID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGlkID0gXywgZm9yY2UpIDogaWQ7XG4gIH07XG5cbiAgZm9yY2UuaXRlcmF0aW9ucyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpdGVyYXRpb25zID0gK18sIGZvcmNlKSA6IGl0ZXJhdGlvbnM7XG4gIH07XG5cbiAgZm9yY2Uuc3RyZW5ndGggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3RyZW5ndGggPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgaW5pdGlhbGl6ZVN0cmVuZ3RoKCksIGZvcmNlKSA6IHN0cmVuZ3RoO1xuICB9O1xuXG4gIGZvcmNlLmRpc3RhbmNlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRpc3RhbmNlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemVEaXN0YW5jZSgpLCBmb3JjZSkgOiBkaXN0YW5jZTtcbiAgfTtcblxuICByZXR1cm4gZm9yY2U7XG59O1xuXG5mdW5jdGlvbiB4JDEoZCkge1xuICByZXR1cm4gZC54O1xufVxuXG5mdW5jdGlvbiB5JDEoZCkge1xuICByZXR1cm4gZC55O1xufVxuXG52YXIgaW5pdGlhbFJhZGl1cyA9IDEwO1xudmFyIGluaXRpYWxBbmdsZSA9IE1hdGguUEkgKiAoMyAtIE1hdGguc3FydCg1KSk7XG5cbnZhciBzaW11bGF0aW9uID0gZnVuY3Rpb24obm9kZXMpIHtcbiAgdmFyIHNpbXVsYXRpb24sXG4gICAgICBhbHBoYSA9IDEsXG4gICAgICBhbHBoYU1pbiA9IDAuMDAxLFxuICAgICAgYWxwaGFEZWNheSA9IDEgLSBNYXRoLnBvdyhhbHBoYU1pbiwgMSAvIDMwMCksXG4gICAgICBhbHBoYVRhcmdldCA9IDAsXG4gICAgICB2ZWxvY2l0eURlY2F5ID0gMC42LFxuICAgICAgZm9yY2VzID0gZDNDb2xsZWN0aW9uLm1hcCgpLFxuICAgICAgc3RlcHBlciA9IGQzVGltZXIudGltZXIoc3RlcCksXG4gICAgICBldmVudCA9IGQzRGlzcGF0Y2guZGlzcGF0Y2goXCJ0aWNrXCIsIFwiZW5kXCIpO1xuXG4gIGlmIChub2RlcyA9PSBudWxsKSBub2RlcyA9IFtdO1xuXG4gIGZ1bmN0aW9uIHN0ZXAoKSB7XG4gICAgdGljaygpO1xuICAgIGV2ZW50LmNhbGwoXCJ0aWNrXCIsIHNpbXVsYXRpb24pO1xuICAgIGlmIChhbHBoYSA8IGFscGhhTWluKSB7XG4gICAgICBzdGVwcGVyLnN0b3AoKTtcbiAgICAgIGV2ZW50LmNhbGwoXCJlbmRcIiwgc2ltdWxhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdGljaygpIHtcbiAgICB2YXIgaSwgbiA9IG5vZGVzLmxlbmd0aCwgbm9kZTtcblxuICAgIGFscGhhICs9IChhbHBoYVRhcmdldCAtIGFscGhhKSAqIGFscGhhRGVjYXk7XG5cbiAgICBmb3JjZXMuZWFjaChmdW5jdGlvbihmb3JjZSkge1xuICAgICAgZm9yY2UoYWxwaGEpO1xuICAgIH0pO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgaWYgKG5vZGUuZnggPT0gbnVsbCkgbm9kZS54ICs9IG5vZGUudnggKj0gdmVsb2NpdHlEZWNheTtcbiAgICAgIGVsc2Ugbm9kZS54ID0gbm9kZS5meCwgbm9kZS52eCA9IDA7XG4gICAgICBpZiAobm9kZS5meSA9PSBudWxsKSBub2RlLnkgKz0gbm9kZS52eSAqPSB2ZWxvY2l0eURlY2F5O1xuICAgICAgZWxzZSBub2RlLnkgPSBub2RlLmZ5LCBub2RlLnZ5ID0gMDtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBpbml0aWFsaXplTm9kZXMoKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBub2Rlcy5sZW5ndGgsIG5vZGU7IGkgPCBuOyArK2kpIHtcbiAgICAgIG5vZGUgPSBub2Rlc1tpXSwgbm9kZS5pbmRleCA9IGk7XG4gICAgICBpZiAoaXNOYU4obm9kZS54KSB8fCBpc05hTihub2RlLnkpKSB7XG4gICAgICAgIHZhciByYWRpdXMgPSBpbml0aWFsUmFkaXVzICogTWF0aC5zcXJ0KGkpLCBhbmdsZSA9IGkgKiBpbml0aWFsQW5nbGU7XG4gICAgICAgIG5vZGUueCA9IHJhZGl1cyAqIE1hdGguY29zKGFuZ2xlKTtcbiAgICAgICAgbm9kZS55ID0gcmFkaXVzICogTWF0aC5zaW4oYW5nbGUpO1xuICAgICAgfVxuICAgICAgaWYgKGlzTmFOKG5vZGUudngpIHx8IGlzTmFOKG5vZGUudnkpKSB7XG4gICAgICAgIG5vZGUudnggPSBub2RlLnZ5ID0gMDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBpbml0aWFsaXplRm9yY2UoZm9yY2UpIHtcbiAgICBpZiAoZm9yY2UuaW5pdGlhbGl6ZSkgZm9yY2UuaW5pdGlhbGl6ZShub2Rlcyk7XG4gICAgcmV0dXJuIGZvcmNlO1xuICB9XG5cbiAgaW5pdGlhbGl6ZU5vZGVzKCk7XG5cbiAgcmV0dXJuIHNpbXVsYXRpb24gPSB7XG4gICAgdGljazogdGljayxcblxuICAgIHJlc3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHN0ZXBwZXIucmVzdGFydChzdGVwKSwgc2ltdWxhdGlvbjtcbiAgICB9LFxuXG4gICAgc3RvcDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gc3RlcHBlci5zdG9wKCksIHNpbXVsYXRpb247XG4gICAgfSxcblxuICAgIG5vZGVzOiBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChub2RlcyA9IF8sIGluaXRpYWxpemVOb2RlcygpLCBmb3JjZXMuZWFjaChpbml0aWFsaXplRm9yY2UpLCBzaW11bGF0aW9uKSA6IG5vZGVzO1xuICAgIH0sXG5cbiAgICBhbHBoYTogZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYWxwaGEgPSArXywgc2ltdWxhdGlvbikgOiBhbHBoYTtcbiAgICB9LFxuXG4gICAgYWxwaGFNaW46IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGFscGhhTWluID0gK18sIHNpbXVsYXRpb24pIDogYWxwaGFNaW47XG4gICAgfSxcblxuICAgIGFscGhhRGVjYXk6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGFscGhhRGVjYXkgPSArXywgc2ltdWxhdGlvbikgOiArYWxwaGFEZWNheTtcbiAgICB9LFxuXG4gICAgYWxwaGFUYXJnZXQ6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGFscGhhVGFyZ2V0ID0gK18sIHNpbXVsYXRpb24pIDogYWxwaGFUYXJnZXQ7XG4gICAgfSxcblxuICAgIHZlbG9jaXR5RGVjYXk6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZlbG9jaXR5RGVjYXkgPSAxIC0gXywgc2ltdWxhdGlvbikgOiAxIC0gdmVsb2NpdHlEZWNheTtcbiAgICB9LFxuXG4gICAgZm9yY2U6IGZ1bmN0aW9uKG5hbWUsIF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID4gMSA/ICgoXyA9PSBudWxsID8gZm9yY2VzLnJlbW92ZShuYW1lKSA6IGZvcmNlcy5zZXQobmFtZSwgaW5pdGlhbGl6ZUZvcmNlKF8pKSksIHNpbXVsYXRpb24pIDogZm9yY2VzLmdldChuYW1lKTtcbiAgICB9LFxuXG4gICAgZmluZDogZnVuY3Rpb24oeCwgeSwgcmFkaXVzKSB7XG4gICAgICB2YXIgaSA9IDAsXG4gICAgICAgICAgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgICAgICBkeCxcbiAgICAgICAgICBkeSxcbiAgICAgICAgICBkMixcbiAgICAgICAgICBub2RlLFxuICAgICAgICAgIGNsb3Nlc3Q7XG5cbiAgICAgIGlmIChyYWRpdXMgPT0gbnVsbCkgcmFkaXVzID0gSW5maW5pdHk7XG4gICAgICBlbHNlIHJhZGl1cyAqPSByYWRpdXM7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICBkeCA9IHggLSBub2RlLng7XG4gICAgICAgIGR5ID0geSAtIG5vZGUueTtcbiAgICAgICAgZDIgPSBkeCAqIGR4ICsgZHkgKiBkeTtcbiAgICAgICAgaWYgKGQyIDwgcmFkaXVzKSBjbG9zZXN0ID0gbm9kZSwgcmFkaXVzID0gZDI7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjbG9zZXN0O1xuICAgIH0sXG5cbiAgICBvbjogZnVuY3Rpb24obmFtZSwgXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gKGV2ZW50Lm9uKG5hbWUsIF8pLCBzaW11bGF0aW9uKSA6IGV2ZW50Lm9uKG5hbWUpO1xuICAgIH1cbiAgfTtcbn07XG5cbnZhciBtYW55Qm9keSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgbm9kZXMsXG4gICAgICBub2RlLFxuICAgICAgYWxwaGEsXG4gICAgICBzdHJlbmd0aCA9IGNvbnN0YW50KC0zMCksXG4gICAgICBzdHJlbmd0aHMsXG4gICAgICBkaXN0YW5jZU1pbjIgPSAxLFxuICAgICAgZGlzdGFuY2VNYXgyID0gSW5maW5pdHksXG4gICAgICB0aGV0YTIgPSAwLjgxO1xuXG4gIGZ1bmN0aW9uIGZvcmNlKF8pIHtcbiAgICB2YXIgaSwgbiA9IG5vZGVzLmxlbmd0aCwgdHJlZSA9IGQzUXVhZHRyZWUucXVhZHRyZWUobm9kZXMsIHgkMSwgeSQxKS52aXNpdEFmdGVyKGFjY3VtdWxhdGUpO1xuICAgIGZvciAoYWxwaGEgPSBfLCBpID0gMDsgaSA8IG47ICsraSkgbm9kZSA9IG5vZGVzW2ldLCB0cmVlLnZpc2l0KGFwcGx5KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG4gICAgaWYgKCFub2RlcykgcmV0dXJuO1xuICAgIHZhciBpLCBuID0gbm9kZXMubGVuZ3RoLCBub2RlO1xuICAgIHN0cmVuZ3RocyA9IG5ldyBBcnJheShuKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSBub2RlID0gbm9kZXNbaV0sIHN0cmVuZ3Roc1tub2RlLmluZGV4XSA9ICtzdHJlbmd0aChub2RlLCBpLCBub2Rlcyk7XG4gIH1cblxuICBmdW5jdGlvbiBhY2N1bXVsYXRlKHF1YWQpIHtcbiAgICB2YXIgc3RyZW5ndGggPSAwLCBxLCBjLCB3ZWlnaHQgPSAwLCB4LCB5LCBpO1xuXG4gICAgLy8gRm9yIGludGVybmFsIG5vZGVzLCBhY2N1bXVsYXRlIGZvcmNlcyBmcm9tIGNoaWxkIHF1YWRyYW50cy5cbiAgICBpZiAocXVhZC5sZW5ndGgpIHtcbiAgICAgIGZvciAoeCA9IHkgPSBpID0gMDsgaSA8IDQ7ICsraSkge1xuICAgICAgICBpZiAoKHEgPSBxdWFkW2ldKSAmJiAoYyA9IE1hdGguYWJzKHEudmFsdWUpKSkge1xuICAgICAgICAgIHN0cmVuZ3RoICs9IHEudmFsdWUsIHdlaWdodCArPSBjLCB4ICs9IGMgKiBxLngsIHkgKz0gYyAqIHEueTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcXVhZC54ID0geCAvIHdlaWdodDtcbiAgICAgIHF1YWQueSA9IHkgLyB3ZWlnaHQ7XG4gICAgfVxuXG4gICAgLy8gRm9yIGxlYWYgbm9kZXMsIGFjY3VtdWxhdGUgZm9yY2VzIGZyb20gY29pbmNpZGVudCBxdWFkcmFudHMuXG4gICAgZWxzZSB7XG4gICAgICBxID0gcXVhZDtcbiAgICAgIHEueCA9IHEuZGF0YS54O1xuICAgICAgcS55ID0gcS5kYXRhLnk7XG4gICAgICBkbyBzdHJlbmd0aCArPSBzdHJlbmd0aHNbcS5kYXRhLmluZGV4XTtcbiAgICAgIHdoaWxlIChxID0gcS5uZXh0KTtcbiAgICB9XG5cbiAgICBxdWFkLnZhbHVlID0gc3RyZW5ndGg7XG4gIH1cblxuICBmdW5jdGlvbiBhcHBseShxdWFkLCB4MSwgXywgeDIpIHtcbiAgICBpZiAoIXF1YWQudmFsdWUpIHJldHVybiB0cnVlO1xuXG4gICAgdmFyIHggPSBxdWFkLnggLSBub2RlLngsXG4gICAgICAgIHkgPSBxdWFkLnkgLSBub2RlLnksXG4gICAgICAgIHcgPSB4MiAtIHgxLFxuICAgICAgICBsID0geCAqIHggKyB5ICogeTtcblxuICAgIC8vIEFwcGx5IHRoZSBCYXJuZXMtSHV0IGFwcHJveGltYXRpb24gaWYgcG9zc2libGUuXG4gICAgLy8gTGltaXQgZm9yY2VzIGZvciB2ZXJ5IGNsb3NlIG5vZGVzOyByYW5kb21pemUgZGlyZWN0aW9uIGlmIGNvaW5jaWRlbnQuXG4gICAgaWYgKHcgKiB3IC8gdGhldGEyIDwgbCkge1xuICAgICAgaWYgKGwgPCBkaXN0YW5jZU1heDIpIHtcbiAgICAgICAgaWYgKHggPT09IDApIHggPSBqaWdnbGUoKSwgbCArPSB4ICogeDtcbiAgICAgICAgaWYgKHkgPT09IDApIHkgPSBqaWdnbGUoKSwgbCArPSB5ICogeTtcbiAgICAgICAgaWYgKGwgPCBkaXN0YW5jZU1pbjIpIGwgPSBNYXRoLnNxcnQoZGlzdGFuY2VNaW4yICogbCk7XG4gICAgICAgIG5vZGUudnggKz0geCAqIHF1YWQudmFsdWUgKiBhbHBoYSAvIGw7XG4gICAgICAgIG5vZGUudnkgKz0geSAqIHF1YWQudmFsdWUgKiBhbHBoYSAvIGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBPdGhlcndpc2UsIHByb2Nlc3MgcG9pbnRzIGRpcmVjdGx5LlxuICAgIGVsc2UgaWYgKHF1YWQubGVuZ3RoIHx8IGwgPj0gZGlzdGFuY2VNYXgyKSByZXR1cm47XG5cbiAgICAvLyBMaW1pdCBmb3JjZXMgZm9yIHZlcnkgY2xvc2Ugbm9kZXM7IHJhbmRvbWl6ZSBkaXJlY3Rpb24gaWYgY29pbmNpZGVudC5cbiAgICBpZiAocXVhZC5kYXRhICE9PSBub2RlIHx8IHF1YWQubmV4dCkge1xuICAgICAgaWYgKHggPT09IDApIHggPSBqaWdnbGUoKSwgbCArPSB4ICogeDtcbiAgICAgIGlmICh5ID09PSAwKSB5ID0gamlnZ2xlKCksIGwgKz0geSAqIHk7XG4gICAgICBpZiAobCA8IGRpc3RhbmNlTWluMikgbCA9IE1hdGguc3FydChkaXN0YW5jZU1pbjIgKiBsKTtcbiAgICB9XG5cbiAgICBkbyBpZiAocXVhZC5kYXRhICE9PSBub2RlKSB7XG4gICAgICB3ID0gc3RyZW5ndGhzW3F1YWQuZGF0YS5pbmRleF0gKiBhbHBoYSAvIGw7XG4gICAgICBub2RlLnZ4ICs9IHggKiB3O1xuICAgICAgbm9kZS52eSArPSB5ICogdztcbiAgICB9IHdoaWxlIChxdWFkID0gcXVhZC5uZXh0KTtcbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfO1xuICAgIGluaXRpYWxpemUoKTtcbiAgfTtcblxuICBmb3JjZS5zdHJlbmd0aCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzdHJlbmd0aCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IHN0cmVuZ3RoO1xuICB9O1xuXG4gIGZvcmNlLmRpc3RhbmNlTWluID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRpc3RhbmNlTWluMiA9IF8gKiBfLCBmb3JjZSkgOiBNYXRoLnNxcnQoZGlzdGFuY2VNaW4yKTtcbiAgfTtcblxuICBmb3JjZS5kaXN0YW5jZU1heCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkaXN0YW5jZU1heDIgPSBfICogXywgZm9yY2UpIDogTWF0aC5zcXJ0KGRpc3RhbmNlTWF4Mik7XG4gIH07XG5cbiAgZm9yY2UudGhldGEgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGhldGEyID0gXyAqIF8sIGZvcmNlKSA6IE1hdGguc3FydCh0aGV0YTIpO1xuICB9O1xuXG4gIHJldHVybiBmb3JjZTtcbn07XG5cbnZhciByYWRpYWwgPSBmdW5jdGlvbihyYWRpdXMsIHgsIHkpIHtcbiAgdmFyIG5vZGVzLFxuICAgICAgc3RyZW5ndGggPSBjb25zdGFudCgwLjEpLFxuICAgICAgc3RyZW5ndGhzLFxuICAgICAgcmFkaXVzZXM7XG5cbiAgaWYgKHR5cGVvZiByYWRpdXMgIT09IFwiZnVuY3Rpb25cIikgcmFkaXVzID0gY29uc3RhbnQoK3JhZGl1cyk7XG4gIGlmICh4ID09IG51bGwpIHggPSAwO1xuICBpZiAoeSA9PSBudWxsKSB5ID0gMDtcblxuICBmdW5jdGlvbiBmb3JjZShhbHBoYSkge1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gbm9kZXMubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICB2YXIgbm9kZSA9IG5vZGVzW2ldLFxuICAgICAgICAgIGR4ID0gbm9kZS54IC0geCB8fCAxZS02LFxuICAgICAgICAgIGR5ID0gbm9kZS55IC0geSB8fCAxZS02LFxuICAgICAgICAgIHIgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpLFxuICAgICAgICAgIGsgPSAocmFkaXVzZXNbaV0gLSByKSAqIHN0cmVuZ3Roc1tpXSAqIGFscGhhIC8gcjtcbiAgICAgIG5vZGUudnggKz0gZHggKiBrO1xuICAgICAgbm9kZS52eSArPSBkeSAqIGs7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG4gICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGg7XG4gICAgc3RyZW5ndGhzID0gbmV3IEFycmF5KG4pO1xuICAgIHJhZGl1c2VzID0gbmV3IEFycmF5KG4pO1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHJhZGl1c2VzW2ldID0gK3JhZGl1cyhub2Rlc1tpXSwgaSwgbm9kZXMpO1xuICAgICAgc3RyZW5ndGhzW2ldID0gaXNOYU4ocmFkaXVzZXNbaV0pID8gMCA6ICtzdHJlbmd0aChub2Rlc1tpXSwgaSwgbm9kZXMpO1xuICAgIH1cbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfLCBpbml0aWFsaXplKCk7XG4gIH07XG5cbiAgZm9yY2Uuc3RyZW5ndGggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3RyZW5ndGggPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgaW5pdGlhbGl6ZSgpLCBmb3JjZSkgOiBzdHJlbmd0aDtcbiAgfTtcblxuICBmb3JjZS5yYWRpdXMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFkaXVzID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemUoKSwgZm9yY2UpIDogcmFkaXVzO1xuICB9O1xuXG4gIGZvcmNlLnggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeCA9ICtfLCBmb3JjZSkgOiB4O1xuICB9O1xuXG4gIGZvcmNlLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSA9ICtfLCBmb3JjZSkgOiB5O1xuICB9O1xuXG4gIHJldHVybiBmb3JjZTtcbn07XG5cbnZhciB4JDIgPSBmdW5jdGlvbih4KSB7XG4gIHZhciBzdHJlbmd0aCA9IGNvbnN0YW50KDAuMSksXG4gICAgICBub2RlcyxcbiAgICAgIHN0cmVuZ3RocyxcbiAgICAgIHh6O1xuXG4gIGlmICh0eXBlb2YgeCAhPT0gXCJmdW5jdGlvblwiKSB4ID0gY29uc3RhbnQoeCA9PSBudWxsID8gMCA6ICt4KTtcblxuICBmdW5jdGlvbiBmb3JjZShhbHBoYSkge1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gbm9kZXMubGVuZ3RoLCBub2RlOyBpIDwgbjsgKytpKSB7XG4gICAgICBub2RlID0gbm9kZXNbaV0sIG5vZGUudnggKz0gKHh6W2ldIC0gbm9kZS54KSAqIHN0cmVuZ3Roc1tpXSAqIGFscGhhO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG4gICAgaWYgKCFub2RlcykgcmV0dXJuO1xuICAgIHZhciBpLCBuID0gbm9kZXMubGVuZ3RoO1xuICAgIHN0cmVuZ3RocyA9IG5ldyBBcnJheShuKTtcbiAgICB4eiA9IG5ldyBBcnJheShuKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBzdHJlbmd0aHNbaV0gPSBpc05hTih4eltpXSA9ICt4KG5vZGVzW2ldLCBpLCBub2RlcykpID8gMCA6ICtzdHJlbmd0aChub2Rlc1tpXSwgaSwgbm9kZXMpO1xuICAgIH1cbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfO1xuICAgIGluaXRpYWxpemUoKTtcbiAgfTtcblxuICBmb3JjZS5zdHJlbmd0aCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzdHJlbmd0aCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IHN0cmVuZ3RoO1xuICB9O1xuXG4gIGZvcmNlLnggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IHg7XG4gIH07XG5cbiAgcmV0dXJuIGZvcmNlO1xufTtcblxudmFyIHkkMiA9IGZ1bmN0aW9uKHkpIHtcbiAgdmFyIHN0cmVuZ3RoID0gY29uc3RhbnQoMC4xKSxcbiAgICAgIG5vZGVzLFxuICAgICAgc3RyZW5ndGhzLFxuICAgICAgeXo7XG5cbiAgaWYgKHR5cGVvZiB5ICE9PSBcImZ1bmN0aW9uXCIpIHkgPSBjb25zdGFudCh5ID09IG51bGwgPyAwIDogK3kpO1xuXG4gIGZ1bmN0aW9uIGZvcmNlKGFscGhhKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBub2Rlcy5sZW5ndGgsIG5vZGU7IGkgPCBuOyArK2kpIHtcbiAgICAgIG5vZGUgPSBub2Rlc1tpXSwgbm9kZS52eSArPSAoeXpbaV0gLSBub2RlLnkpICogc3RyZW5ndGhzW2ldICogYWxwaGE7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG4gICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGg7XG4gICAgc3RyZW5ndGhzID0gbmV3IEFycmF5KG4pO1xuICAgIHl6ID0gbmV3IEFycmF5KG4pO1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHN0cmVuZ3Roc1tpXSA9IGlzTmFOKHl6W2ldID0gK3kobm9kZXNbaV0sIGksIG5vZGVzKSkgPyAwIDogK3N0cmVuZ3RoKG5vZGVzW2ldLCBpLCBub2Rlcyk7XG4gICAgfVxuICB9XG5cbiAgZm9yY2UuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICBub2RlcyA9IF87XG4gICAgaW5pdGlhbGl6ZSgpO1xuICB9O1xuXG4gIGZvcmNlLnN0cmVuZ3RoID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0cmVuZ3RoID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemUoKSwgZm9yY2UpIDogc3RyZW5ndGg7XG4gIH07XG5cbiAgZm9yY2UueSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5ID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemUoKSwgZm9yY2UpIDogeTtcbiAgfTtcblxuICByZXR1cm4gZm9yY2U7XG59O1xuXG5leHBvcnRzLmZvcmNlQ2VudGVyID0gY2VudGVyO1xuZXhwb3J0cy5mb3JjZUNvbGxpZGUgPSBjb2xsaWRlO1xuZXhwb3J0cy5mb3JjZUxpbmsgPSBsaW5rO1xuZXhwb3J0cy5mb3JjZU1hbnlCb2R5ID0gbWFueUJvZHk7XG5leHBvcnRzLmZvcmNlUmFkaWFsID0gcmFkaWFsO1xuZXhwb3J0cy5mb3JjZVNpbXVsYXRpb24gPSBzaW11bGF0aW9uO1xuZXhwb3J0cy5mb3JjZVggPSB4JDI7XG5leHBvcnRzLmZvcmNlWSA9IHkkMjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcblxufSx7XCJkMy1jb2xsZWN0aW9uXCI6MTUzLFwiZDMtZGlzcGF0Y2hcIjoxNTUsXCJkMy1xdWFkdHJlZVwiOjE2MCxcImQzLXRpbWVyXCI6MTYyfV0sMTU3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtaGllcmFyY2h5LyB2MS4xLjggQ29weXJpZ2h0IDIwMTggTWlrZSBCb3N0b2NrXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xudHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG50eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcbihmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXBhcmF0aW9uKGEsIGIpIHtcbiAgcmV0dXJuIGEucGFyZW50ID09PSBiLnBhcmVudCA/IDEgOiAyO1xufVxuXG5mdW5jdGlvbiBtZWFuWChjaGlsZHJlbikge1xuICByZXR1cm4gY2hpbGRyZW4ucmVkdWNlKG1lYW5YUmVkdWNlLCAwKSAvIGNoaWxkcmVuLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gbWVhblhSZWR1Y2UoeCwgYykge1xuICByZXR1cm4geCArIGMueDtcbn1cblxuZnVuY3Rpb24gbWF4WShjaGlsZHJlbikge1xuICByZXR1cm4gMSArIGNoaWxkcmVuLnJlZHVjZShtYXhZUmVkdWNlLCAwKTtcbn1cblxuZnVuY3Rpb24gbWF4WVJlZHVjZSh5LCBjKSB7XG4gIHJldHVybiBNYXRoLm1heCh5LCBjLnkpO1xufVxuXG5mdW5jdGlvbiBsZWFmTGVmdChub2RlKSB7XG4gIHZhciBjaGlsZHJlbjtcbiAgd2hpbGUgKGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbikgbm9kZSA9IGNoaWxkcmVuWzBdO1xuICByZXR1cm4gbm9kZTtcbn1cblxuZnVuY3Rpb24gbGVhZlJpZ2h0KG5vZGUpIHtcbiAgdmFyIGNoaWxkcmVuO1xuICB3aGlsZSAoY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuKSBub2RlID0gY2hpbGRyZW5bY2hpbGRyZW4ubGVuZ3RoIC0gMV07XG4gIHJldHVybiBub2RlO1xufVxuXG5mdW5jdGlvbiBjbHVzdGVyKCkge1xuICB2YXIgc2VwYXJhdGlvbiA9IGRlZmF1bHRTZXBhcmF0aW9uLFxuICAgICAgZHggPSAxLFxuICAgICAgZHkgPSAxLFxuICAgICAgbm9kZVNpemUgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBjbHVzdGVyKHJvb3QpIHtcbiAgICB2YXIgcHJldmlvdXNOb2RlLFxuICAgICAgICB4ID0gMDtcblxuICAgIC8vIEZpcnN0IHdhbGssIGNvbXB1dGluZyB0aGUgaW5pdGlhbCB4ICYgeSB2YWx1ZXMuXG4gICAgcm9vdC5lYWNoQWZ0ZXIoZnVuY3Rpb24obm9kZSkge1xuICAgICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcbiAgICAgIGlmIChjaGlsZHJlbikge1xuICAgICAgICBub2RlLnggPSBtZWFuWChjaGlsZHJlbik7XG4gICAgICAgIG5vZGUueSA9IG1heFkoY2hpbGRyZW4pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9kZS54ID0gcHJldmlvdXNOb2RlID8geCArPSBzZXBhcmF0aW9uKG5vZGUsIHByZXZpb3VzTm9kZSkgOiAwO1xuICAgICAgICBub2RlLnkgPSAwO1xuICAgICAgICBwcmV2aW91c05vZGUgPSBub2RlO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFyIGxlZnQgPSBsZWFmTGVmdChyb290KSxcbiAgICAgICAgcmlnaHQgPSBsZWFmUmlnaHQocm9vdCksXG4gICAgICAgIHgwID0gbGVmdC54IC0gc2VwYXJhdGlvbihsZWZ0LCByaWdodCkgLyAyLFxuICAgICAgICB4MSA9IHJpZ2h0LnggKyBzZXBhcmF0aW9uKHJpZ2h0LCBsZWZ0KSAvIDI7XG5cbiAgICAvLyBTZWNvbmQgd2Fsaywgbm9ybWFsaXppbmcgeCAmIHkgdG8gdGhlIGRlc2lyZWQgc2l6ZS5cbiAgICByZXR1cm4gcm9vdC5lYWNoQWZ0ZXIobm9kZVNpemUgPyBmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlLnggPSAobm9kZS54IC0gcm9vdC54KSAqIGR4O1xuICAgICAgbm9kZS55ID0gKHJvb3QueSAtIG5vZGUueSkgKiBkeTtcbiAgICB9IDogZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZS54ID0gKG5vZGUueCAtIHgwKSAvICh4MSAtIHgwKSAqIGR4O1xuICAgICAgbm9kZS55ID0gKDEgLSAocm9vdC55ID8gbm9kZS55IC8gcm9vdC55IDogMSkpICogZHk7XG4gICAgfSk7XG4gIH1cblxuICBjbHVzdGVyLnNlcGFyYXRpb24gPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2VwYXJhdGlvbiA9IHgsIGNsdXN0ZXIpIDogc2VwYXJhdGlvbjtcbiAgfTtcblxuICBjbHVzdGVyLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobm9kZVNpemUgPSBmYWxzZSwgZHggPSAreFswXSwgZHkgPSAreFsxXSwgY2x1c3RlcikgOiAobm9kZVNpemUgPyBudWxsIDogW2R4LCBkeV0pO1xuICB9O1xuXG4gIGNsdXN0ZXIubm9kZVNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobm9kZVNpemUgPSB0cnVlLCBkeCA9ICt4WzBdLCBkeSA9ICt4WzFdLCBjbHVzdGVyKSA6IChub2RlU2l6ZSA/IFtkeCwgZHldIDogbnVsbCk7XG4gIH07XG5cbiAgcmV0dXJuIGNsdXN0ZXI7XG59XG5cbmZ1bmN0aW9uIGNvdW50KG5vZGUpIHtcbiAgdmFyIHN1bSA9IDAsXG4gICAgICBjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW4sXG4gICAgICBpID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoO1xuICBpZiAoIWkpIHN1bSA9IDE7XG4gIGVsc2Ugd2hpbGUgKC0taSA+PSAwKSBzdW0gKz0gY2hpbGRyZW5baV0udmFsdWU7XG4gIG5vZGUudmFsdWUgPSBzdW07XG59XG5cbmZ1bmN0aW9uIG5vZGVfY291bnQoKSB7XG4gIHJldHVybiB0aGlzLmVhY2hBZnRlcihjb3VudCk7XG59XG5cbmZ1bmN0aW9uIG5vZGVfZWFjaChjYWxsYmFjaykge1xuICB2YXIgbm9kZSA9IHRoaXMsIGN1cnJlbnQsIG5leHQgPSBbbm9kZV0sIGNoaWxkcmVuLCBpLCBuO1xuICBkbyB7XG4gICAgY3VycmVudCA9IG5leHQucmV2ZXJzZSgpLCBuZXh0ID0gW107XG4gICAgd2hpbGUgKG5vZGUgPSBjdXJyZW50LnBvcCgpKSB7XG4gICAgICBjYWxsYmFjayhub2RlKSwgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuO1xuICAgICAgaWYgKGNoaWxkcmVuKSBmb3IgKGkgPSAwLCBuID0gY2hpbGRyZW4ubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIG5leHQucHVzaChjaGlsZHJlbltpXSk7XG4gICAgICB9XG4gICAgfVxuICB9IHdoaWxlIChuZXh0Lmxlbmd0aCk7XG4gIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBub2RlX2VhY2hCZWZvcmUoY2FsbGJhY2spIHtcbiAgdmFyIG5vZGUgPSB0aGlzLCBub2RlcyA9IFtub2RlXSwgY2hpbGRyZW4sIGk7XG4gIHdoaWxlIChub2RlID0gbm9kZXMucG9wKCkpIHtcbiAgICBjYWxsYmFjayhub2RlKSwgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuO1xuICAgIGlmIChjaGlsZHJlbikgZm9yIChpID0gY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIG5vZGVzLnB1c2goY2hpbGRyZW5baV0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gbm9kZV9lYWNoQWZ0ZXIoY2FsbGJhY2spIHtcbiAgdmFyIG5vZGUgPSB0aGlzLCBub2RlcyA9IFtub2RlXSwgbmV4dCA9IFtdLCBjaGlsZHJlbiwgaSwgbjtcbiAgd2hpbGUgKG5vZGUgPSBub2Rlcy5wb3AoKSkge1xuICAgIG5leHQucHVzaChub2RlKSwgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuO1xuICAgIGlmIChjaGlsZHJlbikgZm9yIChpID0gMCwgbiA9IGNoaWxkcmVuLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgbm9kZXMucHVzaChjaGlsZHJlbltpXSk7XG4gICAgfVxuICB9XG4gIHdoaWxlIChub2RlID0gbmV4dC5wb3AoKSkge1xuICAgIGNhbGxiYWNrKG5vZGUpO1xuICB9XG4gIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBub2RlX3N1bSh2YWx1ZSkge1xuICByZXR1cm4gdGhpcy5lYWNoQWZ0ZXIoZnVuY3Rpb24obm9kZSkge1xuICAgIHZhciBzdW0gPSArdmFsdWUobm9kZS5kYXRhKSB8fCAwLFxuICAgICAgICBjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW4sXG4gICAgICAgIGkgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGg7XG4gICAgd2hpbGUgKC0taSA+PSAwKSBzdW0gKz0gY2hpbGRyZW5baV0udmFsdWU7XG4gICAgbm9kZS52YWx1ZSA9IHN1bTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG5vZGVfc29ydChjb21wYXJlKSB7XG4gIHJldHVybiB0aGlzLmVhY2hCZWZvcmUoZnVuY3Rpb24obm9kZSkge1xuICAgIGlmIChub2RlLmNoaWxkcmVuKSB7XG4gICAgICBub2RlLmNoaWxkcmVuLnNvcnQoY29tcGFyZSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gbm9kZV9wYXRoKGVuZCkge1xuICB2YXIgc3RhcnQgPSB0aGlzLFxuICAgICAgYW5jZXN0b3IgPSBsZWFzdENvbW1vbkFuY2VzdG9yKHN0YXJ0LCBlbmQpLFxuICAgICAgbm9kZXMgPSBbc3RhcnRdO1xuICB3aGlsZSAoc3RhcnQgIT09IGFuY2VzdG9yKSB7XG4gICAgc3RhcnQgPSBzdGFydC5wYXJlbnQ7XG4gICAgbm9kZXMucHVzaChzdGFydCk7XG4gIH1cbiAgdmFyIGsgPSBub2Rlcy5sZW5ndGg7XG4gIHdoaWxlIChlbmQgIT09IGFuY2VzdG9yKSB7XG4gICAgbm9kZXMuc3BsaWNlKGssIDAsIGVuZCk7XG4gICAgZW5kID0gZW5kLnBhcmVudDtcbiAgfVxuICByZXR1cm4gbm9kZXM7XG59XG5cbmZ1bmN0aW9uIGxlYXN0Q29tbW9uQW5jZXN0b3IoYSwgYikge1xuICBpZiAoYSA9PT0gYikgcmV0dXJuIGE7XG4gIHZhciBhTm9kZXMgPSBhLmFuY2VzdG9ycygpLFxuICAgICAgYk5vZGVzID0gYi5hbmNlc3RvcnMoKSxcbiAgICAgIGMgPSBudWxsO1xuICBhID0gYU5vZGVzLnBvcCgpO1xuICBiID0gYk5vZGVzLnBvcCgpO1xuICB3aGlsZSAoYSA9PT0gYikge1xuICAgIGMgPSBhO1xuICAgIGEgPSBhTm9kZXMucG9wKCk7XG4gICAgYiA9IGJOb2Rlcy5wb3AoKTtcbiAgfVxuICByZXR1cm4gYztcbn1cblxuZnVuY3Rpb24gbm9kZV9hbmNlc3RvcnMoKSB7XG4gIHZhciBub2RlID0gdGhpcywgbm9kZXMgPSBbbm9kZV07XG4gIHdoaWxlIChub2RlID0gbm9kZS5wYXJlbnQpIHtcbiAgICBub2Rlcy5wdXNoKG5vZGUpO1xuICB9XG4gIHJldHVybiBub2Rlcztcbn1cblxuZnVuY3Rpb24gbm9kZV9kZXNjZW5kYW50cygpIHtcbiAgdmFyIG5vZGVzID0gW107XG4gIHRoaXMuZWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgbm9kZXMucHVzaChub2RlKTtcbiAgfSk7XG4gIHJldHVybiBub2Rlcztcbn1cblxuZnVuY3Rpb24gbm9kZV9sZWF2ZXMoKSB7XG4gIHZhciBsZWF2ZXMgPSBbXTtcbiAgdGhpcy5lYWNoQmVmb3JlKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICBpZiAoIW5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIGxlYXZlcy5wdXNoKG5vZGUpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBsZWF2ZXM7XG59XG5cbmZ1bmN0aW9uIG5vZGVfbGlua3MoKSB7XG4gIHZhciByb290ID0gdGhpcywgbGlua3MgPSBbXTtcbiAgcm9vdC5lYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICBpZiAobm9kZSAhPT0gcm9vdCkgeyAvLyBEb27igJl0IGluY2x1ZGUgdGhlIHJvb3TigJlzIHBhcmVudCwgaWYgYW55LlxuICAgICAgbGlua3MucHVzaCh7c291cmNlOiBub2RlLnBhcmVudCwgdGFyZ2V0OiBub2RlfSk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIGxpbmtzO1xufVxuXG5mdW5jdGlvbiBoaWVyYXJjaHkoZGF0YSwgY2hpbGRyZW4pIHtcbiAgdmFyIHJvb3QgPSBuZXcgTm9kZShkYXRhKSxcbiAgICAgIHZhbHVlZCA9ICtkYXRhLnZhbHVlICYmIChyb290LnZhbHVlID0gZGF0YS52YWx1ZSksXG4gICAgICBub2RlLFxuICAgICAgbm9kZXMgPSBbcm9vdF0sXG4gICAgICBjaGlsZCxcbiAgICAgIGNoaWxkcyxcbiAgICAgIGksXG4gICAgICBuO1xuXG4gIGlmIChjaGlsZHJlbiA9PSBudWxsKSBjaGlsZHJlbiA9IGRlZmF1bHRDaGlsZHJlbjtcblxuICB3aGlsZSAobm9kZSA9IG5vZGVzLnBvcCgpKSB7XG4gICAgaWYgKHZhbHVlZCkgbm9kZS52YWx1ZSA9ICtub2RlLmRhdGEudmFsdWU7XG4gICAgaWYgKChjaGlsZHMgPSBjaGlsZHJlbihub2RlLmRhdGEpKSAmJiAobiA9IGNoaWxkcy5sZW5ndGgpKSB7XG4gICAgICBub2RlLmNoaWxkcmVuID0gbmV3IEFycmF5KG4pO1xuICAgICAgZm9yIChpID0gbiAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgIG5vZGVzLnB1c2goY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldID0gbmV3IE5vZGUoY2hpbGRzW2ldKSk7XG4gICAgICAgIGNoaWxkLnBhcmVudCA9IG5vZGU7XG4gICAgICAgIGNoaWxkLmRlcHRoID0gbm9kZS5kZXB0aCArIDE7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJvb3QuZWFjaEJlZm9yZShjb21wdXRlSGVpZ2h0KTtcbn1cblxuZnVuY3Rpb24gbm9kZV9jb3B5KCkge1xuICByZXR1cm4gaGllcmFyY2h5KHRoaXMpLmVhY2hCZWZvcmUoY29weURhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0Q2hpbGRyZW4oZCkge1xuICByZXR1cm4gZC5jaGlsZHJlbjtcbn1cblxuZnVuY3Rpb24gY29weURhdGEobm9kZSkge1xuICBub2RlLmRhdGEgPSBub2RlLmRhdGEuZGF0YTtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZUhlaWdodChub2RlKSB7XG4gIHZhciBoZWlnaHQgPSAwO1xuICBkbyBub2RlLmhlaWdodCA9IGhlaWdodDtcbiAgd2hpbGUgKChub2RlID0gbm9kZS5wYXJlbnQpICYmIChub2RlLmhlaWdodCA8ICsraGVpZ2h0KSk7XG59XG5cbmZ1bmN0aW9uIE5vZGUoZGF0YSkge1xuICB0aGlzLmRhdGEgPSBkYXRhO1xuICB0aGlzLmRlcHRoID1cbiAgdGhpcy5oZWlnaHQgPSAwO1xuICB0aGlzLnBhcmVudCA9IG51bGw7XG59XG5cbk5vZGUucHJvdG90eXBlID0gaGllcmFyY2h5LnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IE5vZGUsXG4gIGNvdW50OiBub2RlX2NvdW50LFxuICBlYWNoOiBub2RlX2VhY2gsXG4gIGVhY2hBZnRlcjogbm9kZV9lYWNoQWZ0ZXIsXG4gIGVhY2hCZWZvcmU6IG5vZGVfZWFjaEJlZm9yZSxcbiAgc3VtOiBub2RlX3N1bSxcbiAgc29ydDogbm9kZV9zb3J0LFxuICBwYXRoOiBub2RlX3BhdGgsXG4gIGFuY2VzdG9yczogbm9kZV9hbmNlc3RvcnMsXG4gIGRlc2NlbmRhbnRzOiBub2RlX2Rlc2NlbmRhbnRzLFxuICBsZWF2ZXM6IG5vZGVfbGVhdmVzLFxuICBsaW5rczogbm9kZV9saW5rcyxcbiAgY29weTogbm9kZV9jb3B5XG59O1xuXG52YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG5cbmZ1bmN0aW9uIHNodWZmbGUoYXJyYXkpIHtcbiAgdmFyIG0gPSBhcnJheS5sZW5ndGgsXG4gICAgICB0LFxuICAgICAgaTtcblxuICB3aGlsZSAobSkge1xuICAgIGkgPSBNYXRoLnJhbmRvbSgpICogbS0tIHwgMDtcbiAgICB0ID0gYXJyYXlbbV07XG4gICAgYXJyYXlbbV0gPSBhcnJheVtpXTtcbiAgICBhcnJheVtpXSA9IHQ7XG4gIH1cblxuICByZXR1cm4gYXJyYXk7XG59XG5cbmZ1bmN0aW9uIGVuY2xvc2UoY2lyY2xlcykge1xuICB2YXIgaSA9IDAsIG4gPSAoY2lyY2xlcyA9IHNodWZmbGUoc2xpY2UuY2FsbChjaXJjbGVzKSkpLmxlbmd0aCwgQiA9IFtdLCBwLCBlO1xuXG4gIHdoaWxlIChpIDwgbikge1xuICAgIHAgPSBjaXJjbGVzW2ldO1xuICAgIGlmIChlICYmIGVuY2xvc2VzV2VhayhlLCBwKSkgKytpO1xuICAgIGVsc2UgZSA9IGVuY2xvc2VCYXNpcyhCID0gZXh0ZW5kQmFzaXMoQiwgcCkpLCBpID0gMDtcbiAgfVxuXG4gIHJldHVybiBlO1xufVxuXG5mdW5jdGlvbiBleHRlbmRCYXNpcyhCLCBwKSB7XG4gIHZhciBpLCBqO1xuXG4gIGlmIChlbmNsb3Nlc1dlYWtBbGwocCwgQikpIHJldHVybiBbcF07XG5cbiAgLy8gSWYgd2UgZ2V0IGhlcmUgdGhlbiBCIG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgZWxlbWVudC5cbiAgZm9yIChpID0gMDsgaSA8IEIubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoZW5jbG9zZXNOb3QocCwgQltpXSlcbiAgICAgICAgJiYgZW5jbG9zZXNXZWFrQWxsKGVuY2xvc2VCYXNpczIoQltpXSwgcCksIEIpKSB7XG4gICAgICByZXR1cm4gW0JbaV0sIHBdO1xuICAgIH1cbiAgfVxuXG4gIC8vIElmIHdlIGdldCBoZXJlIHRoZW4gQiBtdXN0IGhhdmUgYXQgbGVhc3QgdHdvIGVsZW1lbnRzLlxuICBmb3IgKGkgPSAwOyBpIDwgQi5sZW5ndGggLSAxOyArK2kpIHtcbiAgICBmb3IgKGogPSBpICsgMTsgaiA8IEIubGVuZ3RoOyArK2opIHtcbiAgICAgIGlmIChlbmNsb3Nlc05vdChlbmNsb3NlQmFzaXMyKEJbaV0sIEJbal0pLCBwKVxuICAgICAgICAgICYmIGVuY2xvc2VzTm90KGVuY2xvc2VCYXNpczIoQltpXSwgcCksIEJbal0pXG4gICAgICAgICAgJiYgZW5jbG9zZXNOb3QoZW5jbG9zZUJhc2lzMihCW2pdLCBwKSwgQltpXSlcbiAgICAgICAgICAmJiBlbmNsb3Nlc1dlYWtBbGwoZW5jbG9zZUJhc2lzMyhCW2ldLCBCW2pdLCBwKSwgQikpIHtcbiAgICAgICAgcmV0dXJuIFtCW2ldLCBCW2pdLCBwXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBJZiB3ZSBnZXQgaGVyZSB0aGVuIHNvbWV0aGluZyBpcyB2ZXJ5IHdyb25nLlxuICB0aHJvdyBuZXcgRXJyb3I7XG59XG5cbmZ1bmN0aW9uIGVuY2xvc2VzTm90KGEsIGIpIHtcbiAgdmFyIGRyID0gYS5yIC0gYi5yLCBkeCA9IGIueCAtIGEueCwgZHkgPSBiLnkgLSBhLnk7XG4gIHJldHVybiBkciA8IDAgfHwgZHIgKiBkciA8IGR4ICogZHggKyBkeSAqIGR5O1xufVxuXG5mdW5jdGlvbiBlbmNsb3Nlc1dlYWsoYSwgYikge1xuICB2YXIgZHIgPSBhLnIgLSBiLnIgKyAxZS02LCBkeCA9IGIueCAtIGEueCwgZHkgPSBiLnkgLSBhLnk7XG4gIHJldHVybiBkciA+IDAgJiYgZHIgKiBkciA+IGR4ICogZHggKyBkeSAqIGR5O1xufVxuXG5mdW5jdGlvbiBlbmNsb3Nlc1dlYWtBbGwoYSwgQikge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IEIubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoIWVuY2xvc2VzV2VhayhhLCBCW2ldKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gZW5jbG9zZUJhc2lzKEIpIHtcbiAgc3dpdGNoIChCLmxlbmd0aCkge1xuICAgIGNhc2UgMTogcmV0dXJuIGVuY2xvc2VCYXNpczEoQlswXSk7XG4gICAgY2FzZSAyOiByZXR1cm4gZW5jbG9zZUJhc2lzMihCWzBdLCBCWzFdKTtcbiAgICBjYXNlIDM6IHJldHVybiBlbmNsb3NlQmFzaXMzKEJbMF0sIEJbMV0sIEJbMl0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVuY2xvc2VCYXNpczEoYSkge1xuICByZXR1cm4ge1xuICAgIHg6IGEueCxcbiAgICB5OiBhLnksXG4gICAgcjogYS5yXG4gIH07XG59XG5cbmZ1bmN0aW9uIGVuY2xvc2VCYXNpczIoYSwgYikge1xuICB2YXIgeDEgPSBhLngsIHkxID0gYS55LCByMSA9IGEucixcbiAgICAgIHgyID0gYi54LCB5MiA9IGIueSwgcjIgPSBiLnIsXG4gICAgICB4MjEgPSB4MiAtIHgxLCB5MjEgPSB5MiAtIHkxLCByMjEgPSByMiAtIHIxLFxuICAgICAgbCA9IE1hdGguc3FydCh4MjEgKiB4MjEgKyB5MjEgKiB5MjEpO1xuICByZXR1cm4ge1xuICAgIHg6ICh4MSArIHgyICsgeDIxIC8gbCAqIHIyMSkgLyAyLFxuICAgIHk6ICh5MSArIHkyICsgeTIxIC8gbCAqIHIyMSkgLyAyLFxuICAgIHI6IChsICsgcjEgKyByMikgLyAyXG4gIH07XG59XG5cbmZ1bmN0aW9uIGVuY2xvc2VCYXNpczMoYSwgYiwgYykge1xuICB2YXIgeDEgPSBhLngsIHkxID0gYS55LCByMSA9IGEucixcbiAgICAgIHgyID0gYi54LCB5MiA9IGIueSwgcjIgPSBiLnIsXG4gICAgICB4MyA9IGMueCwgeTMgPSBjLnksIHIzID0gYy5yLFxuICAgICAgYTIgPSB4MSAtIHgyLFxuICAgICAgYTMgPSB4MSAtIHgzLFxuICAgICAgYjIgPSB5MSAtIHkyLFxuICAgICAgYjMgPSB5MSAtIHkzLFxuICAgICAgYzIgPSByMiAtIHIxLFxuICAgICAgYzMgPSByMyAtIHIxLFxuICAgICAgZDEgPSB4MSAqIHgxICsgeTEgKiB5MSAtIHIxICogcjEsXG4gICAgICBkMiA9IGQxIC0geDIgKiB4MiAtIHkyICogeTIgKyByMiAqIHIyLFxuICAgICAgZDMgPSBkMSAtIHgzICogeDMgLSB5MyAqIHkzICsgcjMgKiByMyxcbiAgICAgIGFiID0gYTMgKiBiMiAtIGEyICogYjMsXG4gICAgICB4YSA9IChiMiAqIGQzIC0gYjMgKiBkMikgLyAoYWIgKiAyKSAtIHgxLFxuICAgICAgeGIgPSAoYjMgKiBjMiAtIGIyICogYzMpIC8gYWIsXG4gICAgICB5YSA9IChhMyAqIGQyIC0gYTIgKiBkMykgLyAoYWIgKiAyKSAtIHkxLFxuICAgICAgeWIgPSAoYTIgKiBjMyAtIGEzICogYzIpIC8gYWIsXG4gICAgICBBID0geGIgKiB4YiArIHliICogeWIgLSAxLFxuICAgICAgQiA9IDIgKiAocjEgKyB4YSAqIHhiICsgeWEgKiB5YiksXG4gICAgICBDID0geGEgKiB4YSArIHlhICogeWEgLSByMSAqIHIxLFxuICAgICAgciA9IC0oQSA/IChCICsgTWF0aC5zcXJ0KEIgKiBCIC0gNCAqIEEgKiBDKSkgLyAoMiAqIEEpIDogQyAvIEIpO1xuICByZXR1cm4ge1xuICAgIHg6IHgxICsgeGEgKyB4YiAqIHIsXG4gICAgeTogeTEgKyB5YSArIHliICogcixcbiAgICByOiByXG4gIH07XG59XG5cbmZ1bmN0aW9uIHBsYWNlKGIsIGEsIGMpIHtcbiAgdmFyIGR4ID0gYi54IC0gYS54LCB4LCBhMixcbiAgICAgIGR5ID0gYi55IC0gYS55LCB5LCBiMixcbiAgICAgIGQyID0gZHggKiBkeCArIGR5ICogZHk7XG4gIGlmIChkMikge1xuICAgIGEyID0gYS5yICsgYy5yLCBhMiAqPSBhMjtcbiAgICBiMiA9IGIuciArIGMuciwgYjIgKj0gYjI7XG4gICAgaWYgKGEyID4gYjIpIHtcbiAgICAgIHggPSAoZDIgKyBiMiAtIGEyKSAvICgyICogZDIpO1xuICAgICAgeSA9IE1hdGguc3FydChNYXRoLm1heCgwLCBiMiAvIGQyIC0geCAqIHgpKTtcbiAgICAgIGMueCA9IGIueCAtIHggKiBkeCAtIHkgKiBkeTtcbiAgICAgIGMueSA9IGIueSAtIHggKiBkeSArIHkgKiBkeDtcbiAgICB9IGVsc2Uge1xuICAgICAgeCA9IChkMiArIGEyIC0gYjIpIC8gKDIgKiBkMik7XG4gICAgICB5ID0gTWF0aC5zcXJ0KE1hdGgubWF4KDAsIGEyIC8gZDIgLSB4ICogeCkpO1xuICAgICAgYy54ID0gYS54ICsgeCAqIGR4IC0geSAqIGR5O1xuICAgICAgYy55ID0gYS55ICsgeCAqIGR5ICsgeSAqIGR4O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjLnggPSBhLnggKyBjLnI7XG4gICAgYy55ID0gYS55O1xuICB9XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdHMoYSwgYikge1xuICB2YXIgZHIgPSBhLnIgKyBiLnIgLSAxZS02LCBkeCA9IGIueCAtIGEueCwgZHkgPSBiLnkgLSBhLnk7XG4gIHJldHVybiBkciA+IDAgJiYgZHIgKiBkciA+IGR4ICogZHggKyBkeSAqIGR5O1xufVxuXG5mdW5jdGlvbiBzY29yZShub2RlKSB7XG4gIHZhciBhID0gbm9kZS5fLFxuICAgICAgYiA9IG5vZGUubmV4dC5fLFxuICAgICAgYWIgPSBhLnIgKyBiLnIsXG4gICAgICBkeCA9IChhLnggKiBiLnIgKyBiLnggKiBhLnIpIC8gYWIsXG4gICAgICBkeSA9IChhLnkgKiBiLnIgKyBiLnkgKiBhLnIpIC8gYWI7XG4gIHJldHVybiBkeCAqIGR4ICsgZHkgKiBkeTtcbn1cblxuZnVuY3Rpb24gTm9kZSQxKGNpcmNsZSkge1xuICB0aGlzLl8gPSBjaXJjbGU7XG4gIHRoaXMubmV4dCA9IG51bGw7XG4gIHRoaXMucHJldmlvdXMgPSBudWxsO1xufVxuXG5mdW5jdGlvbiBwYWNrRW5jbG9zZShjaXJjbGVzKSB7XG4gIGlmICghKG4gPSBjaXJjbGVzLmxlbmd0aCkpIHJldHVybiAwO1xuXG4gIHZhciBhLCBiLCBjLCBuLCBhYSwgY2EsIGksIGosIGssIHNqLCBzaztcblxuICAvLyBQbGFjZSB0aGUgZmlyc3QgY2lyY2xlLlxuICBhID0gY2lyY2xlc1swXSwgYS54ID0gMCwgYS55ID0gMDtcbiAgaWYgKCEobiA+IDEpKSByZXR1cm4gYS5yO1xuXG4gIC8vIFBsYWNlIHRoZSBzZWNvbmQgY2lyY2xlLlxuICBiID0gY2lyY2xlc1sxXSwgYS54ID0gLWIuciwgYi54ID0gYS5yLCBiLnkgPSAwO1xuICBpZiAoIShuID4gMikpIHJldHVybiBhLnIgKyBiLnI7XG5cbiAgLy8gUGxhY2UgdGhlIHRoaXJkIGNpcmNsZS5cbiAgcGxhY2UoYiwgYSwgYyA9IGNpcmNsZXNbMl0pO1xuXG4gIC8vIEluaXRpYWxpemUgdGhlIGZyb250LWNoYWluIHVzaW5nIHRoZSBmaXJzdCB0aHJlZSBjaXJjbGVzIGEsIGIgYW5kIGMuXG4gIGEgPSBuZXcgTm9kZSQxKGEpLCBiID0gbmV3IE5vZGUkMShiKSwgYyA9IG5ldyBOb2RlJDEoYyk7XG4gIGEubmV4dCA9IGMucHJldmlvdXMgPSBiO1xuICBiLm5leHQgPSBhLnByZXZpb3VzID0gYztcbiAgYy5uZXh0ID0gYi5wcmV2aW91cyA9IGE7XG5cbiAgLy8gQXR0ZW1wdCB0byBwbGFjZSBlYWNoIHJlbWFpbmluZyBjaXJjbGXigKZcbiAgcGFjazogZm9yIChpID0gMzsgaSA8IG47ICsraSkge1xuICAgIHBsYWNlKGEuXywgYi5fLCBjID0gY2lyY2xlc1tpXSksIGMgPSBuZXcgTm9kZSQxKGMpO1xuXG4gICAgLy8gRmluZCB0aGUgY2xvc2VzdCBpbnRlcnNlY3RpbmcgY2lyY2xlIG9uIHRoZSBmcm9udC1jaGFpbiwgaWYgYW55LlxuICAgIC8vIOKAnENsb3NlbmVzc+KAnSBpcyBkZXRlcm1pbmVkIGJ5IGxpbmVhciBkaXN0YW5jZSBhbG9uZyB0aGUgZnJvbnQtY2hhaW4uXG4gICAgLy8g4oCcQWhlYWTigJ0gb3Ig4oCcYmVoaW5k4oCdIGlzIGxpa2V3aXNlIGRldGVybWluZWQgYnkgbGluZWFyIGRpc3RhbmNlLlxuICAgIGogPSBiLm5leHQsIGsgPSBhLnByZXZpb3VzLCBzaiA9IGIuXy5yLCBzayA9IGEuXy5yO1xuICAgIGRvIHtcbiAgICAgIGlmIChzaiA8PSBzaykge1xuICAgICAgICBpZiAoaW50ZXJzZWN0cyhqLl8sIGMuXykpIHtcbiAgICAgICAgICBiID0gaiwgYS5uZXh0ID0gYiwgYi5wcmV2aW91cyA9IGEsIC0taTtcbiAgICAgICAgICBjb250aW51ZSBwYWNrO1xuICAgICAgICB9XG4gICAgICAgIHNqICs9IGouXy5yLCBqID0gai5uZXh0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGludGVyc2VjdHMoay5fLCBjLl8pKSB7XG4gICAgICAgICAgYSA9IGssIGEubmV4dCA9IGIsIGIucHJldmlvdXMgPSBhLCAtLWk7XG4gICAgICAgICAgY29udGludWUgcGFjaztcbiAgICAgICAgfVxuICAgICAgICBzayArPSBrLl8uciwgayA9IGsucHJldmlvdXM7XG4gICAgICB9XG4gICAgfSB3aGlsZSAoaiAhPT0gay5uZXh0KTtcblxuICAgIC8vIFN1Y2Nlc3MhIEluc2VydCB0aGUgbmV3IGNpcmNsZSBjIGJldHdlZW4gYSBhbmQgYi5cbiAgICBjLnByZXZpb3VzID0gYSwgYy5uZXh0ID0gYiwgYS5uZXh0ID0gYi5wcmV2aW91cyA9IGIgPSBjO1xuXG4gICAgLy8gQ29tcHV0ZSB0aGUgbmV3IGNsb3Nlc3QgY2lyY2xlIHBhaXIgdG8gdGhlIGNlbnRyb2lkLlxuICAgIGFhID0gc2NvcmUoYSk7XG4gICAgd2hpbGUgKChjID0gYy5uZXh0KSAhPT0gYikge1xuICAgICAgaWYgKChjYSA9IHNjb3JlKGMpKSA8IGFhKSB7XG4gICAgICAgIGEgPSBjLCBhYSA9IGNhO1xuICAgICAgfVxuICAgIH1cbiAgICBiID0gYS5uZXh0O1xuICB9XG5cbiAgLy8gQ29tcHV0ZSB0aGUgZW5jbG9zaW5nIGNpcmNsZSBvZiB0aGUgZnJvbnQgY2hhaW4uXG4gIGEgPSBbYi5fXSwgYyA9IGI7IHdoaWxlICgoYyA9IGMubmV4dCkgIT09IGIpIGEucHVzaChjLl8pOyBjID0gZW5jbG9zZShhKTtcblxuICAvLyBUcmFuc2xhdGUgdGhlIGNpcmNsZXMgdG8gcHV0IHRoZSBlbmNsb3NpbmcgY2lyY2xlIGFyb3VuZCB0aGUgb3JpZ2luLlxuICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSBhID0gY2lyY2xlc1tpXSwgYS54IC09IGMueCwgYS55IC09IGMueTtcblxuICByZXR1cm4gYy5yO1xufVxuXG5mdW5jdGlvbiBzaWJsaW5ncyhjaXJjbGVzKSB7XG4gIHBhY2tFbmNsb3NlKGNpcmNsZXMpO1xuICByZXR1cm4gY2lyY2xlcztcbn1cblxuZnVuY3Rpb24gb3B0aW9uYWwoZikge1xuICByZXR1cm4gZiA9PSBudWxsID8gbnVsbCA6IHJlcXVpcmVkKGYpO1xufVxuXG5mdW5jdGlvbiByZXF1aXJlZChmKSB7XG4gIGlmICh0eXBlb2YgZiAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgRXJyb3I7XG4gIHJldHVybiBmO1xufVxuXG5mdW5jdGlvbiBjb25zdGFudFplcm8oKSB7XG4gIHJldHVybiAwO1xufVxuXG5mdW5jdGlvbiBjb25zdGFudCh4KSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4geDtcbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdFJhZGl1cyhkKSB7XG4gIHJldHVybiBNYXRoLnNxcnQoZC52YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGluZGV4KCkge1xuICB2YXIgcmFkaXVzID0gbnVsbCxcbiAgICAgIGR4ID0gMSxcbiAgICAgIGR5ID0gMSxcbiAgICAgIHBhZGRpbmcgPSBjb25zdGFudFplcm87XG5cbiAgZnVuY3Rpb24gcGFjayhyb290KSB7XG4gICAgcm9vdC54ID0gZHggLyAyLCByb290LnkgPSBkeSAvIDI7XG4gICAgaWYgKHJhZGl1cykge1xuICAgICAgcm9vdC5lYWNoQmVmb3JlKHJhZGl1c0xlYWYocmFkaXVzKSlcbiAgICAgICAgICAuZWFjaEFmdGVyKHBhY2tDaGlsZHJlbihwYWRkaW5nLCAwLjUpKVxuICAgICAgICAgIC5lYWNoQmVmb3JlKHRyYW5zbGF0ZUNoaWxkKDEpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcm9vdC5lYWNoQmVmb3JlKHJhZGl1c0xlYWYoZGVmYXVsdFJhZGl1cykpXG4gICAgICAgICAgLmVhY2hBZnRlcihwYWNrQ2hpbGRyZW4oY29uc3RhbnRaZXJvLCAxKSlcbiAgICAgICAgICAuZWFjaEFmdGVyKHBhY2tDaGlsZHJlbihwYWRkaW5nLCByb290LnIgLyBNYXRoLm1pbihkeCwgZHkpKSlcbiAgICAgICAgICAuZWFjaEJlZm9yZSh0cmFuc2xhdGVDaGlsZChNYXRoLm1pbihkeCwgZHkpIC8gKDIgKiByb290LnIpKSk7XG4gICAgfVxuICAgIHJldHVybiByb290O1xuICB9XG5cbiAgcGFjay5yYWRpdXMgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFkaXVzID0gb3B0aW9uYWwoeCksIHBhY2spIDogcmFkaXVzO1xuICB9O1xuXG4gIHBhY2suc2l6ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkeCA9ICt4WzBdLCBkeSA9ICt4WzFdLCBwYWNrKSA6IFtkeCwgZHldO1xuICB9O1xuXG4gIHBhY2sucGFkZGluZyA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwYWRkaW5nID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiBjb25zdGFudCgreCksIHBhY2spIDogcGFkZGluZztcbiAgfTtcblxuICByZXR1cm4gcGFjaztcbn1cblxuZnVuY3Rpb24gcmFkaXVzTGVhZihyYWRpdXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICBpZiAoIW5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIG5vZGUuciA9IE1hdGgubWF4KDAsICtyYWRpdXMobm9kZSkgfHwgMCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBwYWNrQ2hpbGRyZW4ocGFkZGluZywgaykge1xuICByZXR1cm4gZnVuY3Rpb24obm9kZSkge1xuICAgIGlmIChjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIHZhciBjaGlsZHJlbixcbiAgICAgICAgICBpLFxuICAgICAgICAgIG4gPSBjaGlsZHJlbi5sZW5ndGgsXG4gICAgICAgICAgciA9IHBhZGRpbmcobm9kZSkgKiBrIHx8IDAsXG4gICAgICAgICAgZTtcblxuICAgICAgaWYgKHIpIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIGNoaWxkcmVuW2ldLnIgKz0gcjtcbiAgICAgIGUgPSBwYWNrRW5jbG9zZShjaGlsZHJlbik7XG4gICAgICBpZiAocikgZm9yIChpID0gMDsgaSA8IG47ICsraSkgY2hpbGRyZW5baV0uciAtPSByO1xuICAgICAgbm9kZS5yID0gZSArIHI7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiB0cmFuc2xhdGVDaGlsZChrKSB7XG4gIHJldHVybiBmdW5jdGlvbihub2RlKSB7XG4gICAgdmFyIHBhcmVudCA9IG5vZGUucGFyZW50O1xuICAgIG5vZGUuciAqPSBrO1xuICAgIGlmIChwYXJlbnQpIHtcbiAgICAgIG5vZGUueCA9IHBhcmVudC54ICsgayAqIG5vZGUueDtcbiAgICAgIG5vZGUueSA9IHBhcmVudC55ICsgayAqIG5vZGUueTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJvdW5kTm9kZShub2RlKSB7XG4gIG5vZGUueDAgPSBNYXRoLnJvdW5kKG5vZGUueDApO1xuICBub2RlLnkwID0gTWF0aC5yb3VuZChub2RlLnkwKTtcbiAgbm9kZS54MSA9IE1hdGgucm91bmQobm9kZS54MSk7XG4gIG5vZGUueTEgPSBNYXRoLnJvdW5kKG5vZGUueTEpO1xufVxuXG5mdW5jdGlvbiB0cmVlbWFwRGljZShwYXJlbnQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gIHZhciBub2RlcyA9IHBhcmVudC5jaGlsZHJlbixcbiAgICAgIG5vZGUsXG4gICAgICBpID0gLTEsXG4gICAgICBuID0gbm9kZXMubGVuZ3RoLFxuICAgICAgayA9IHBhcmVudC52YWx1ZSAmJiAoeDEgLSB4MCkgLyBwYXJlbnQudmFsdWU7XG5cbiAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICBub2RlID0gbm9kZXNbaV0sIG5vZGUueTAgPSB5MCwgbm9kZS55MSA9IHkxO1xuICAgIG5vZGUueDAgPSB4MCwgbm9kZS54MSA9IHgwICs9IG5vZGUudmFsdWUgKiBrO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnRpdGlvbigpIHtcbiAgdmFyIGR4ID0gMSxcbiAgICAgIGR5ID0gMSxcbiAgICAgIHBhZGRpbmcgPSAwLFxuICAgICAgcm91bmQgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBwYXJ0aXRpb24ocm9vdCkge1xuICAgIHZhciBuID0gcm9vdC5oZWlnaHQgKyAxO1xuICAgIHJvb3QueDAgPVxuICAgIHJvb3QueTAgPSBwYWRkaW5nO1xuICAgIHJvb3QueDEgPSBkeDtcbiAgICByb290LnkxID0gZHkgLyBuO1xuICAgIHJvb3QuZWFjaEJlZm9yZShwb3NpdGlvbk5vZGUoZHksIG4pKTtcbiAgICBpZiAocm91bmQpIHJvb3QuZWFjaEJlZm9yZShyb3VuZE5vZGUpO1xuICAgIHJldHVybiByb290O1xuICB9XG5cbiAgZnVuY3Rpb24gcG9zaXRpb25Ob2RlKGR5LCBuKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIGlmIChub2RlLmNoaWxkcmVuKSB7XG4gICAgICAgIHRyZWVtYXBEaWNlKG5vZGUsIG5vZGUueDAsIGR5ICogKG5vZGUuZGVwdGggKyAxKSAvIG4sIG5vZGUueDEsIGR5ICogKG5vZGUuZGVwdGggKyAyKSAvIG4pO1xuICAgICAgfVxuICAgICAgdmFyIHgwID0gbm9kZS54MCxcbiAgICAgICAgICB5MCA9IG5vZGUueTAsXG4gICAgICAgICAgeDEgPSBub2RlLngxIC0gcGFkZGluZyxcbiAgICAgICAgICB5MSA9IG5vZGUueTEgLSBwYWRkaW5nO1xuICAgICAgaWYgKHgxIDwgeDApIHgwID0geDEgPSAoeDAgKyB4MSkgLyAyO1xuICAgICAgaWYgKHkxIDwgeTApIHkwID0geTEgPSAoeTAgKyB5MSkgLyAyO1xuICAgICAgbm9kZS54MCA9IHgwO1xuICAgICAgbm9kZS55MCA9IHkwO1xuICAgICAgbm9kZS54MSA9IHgxO1xuICAgICAgbm9kZS55MSA9IHkxO1xuICAgIH07XG4gIH1cblxuICBwYXJ0aXRpb24ucm91bmQgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocm91bmQgPSAhIXgsIHBhcnRpdGlvbikgOiByb3VuZDtcbiAgfTtcblxuICBwYXJ0aXRpb24uc2l6ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkeCA9ICt4WzBdLCBkeSA9ICt4WzFdLCBwYXJ0aXRpb24pIDogW2R4LCBkeV07XG4gIH07XG5cbiAgcGFydGl0aW9uLnBhZGRpbmcgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkZGluZyA9ICt4LCBwYXJ0aXRpb24pIDogcGFkZGluZztcbiAgfTtcblxuICByZXR1cm4gcGFydGl0aW9uO1xufVxuXG52YXIga2V5UHJlZml4ID0gXCIkXCIsIC8vIFByb3RlY3QgYWdhaW5zdCBrZXlzIGxpa2Ug4oCcX19wcm90b19f4oCdLlxuICAgIHByZXJvb3QgPSB7ZGVwdGg6IC0xfSxcbiAgICBhbWJpZ3VvdXMgPSB7fTtcblxuZnVuY3Rpb24gZGVmYXVsdElkKGQpIHtcbiAgcmV0dXJuIGQuaWQ7XG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRQYXJlbnRJZChkKSB7XG4gIHJldHVybiBkLnBhcmVudElkO1xufVxuXG5mdW5jdGlvbiBzdHJhdGlmeSgpIHtcbiAgdmFyIGlkID0gZGVmYXVsdElkLFxuICAgICAgcGFyZW50SWQgPSBkZWZhdWx0UGFyZW50SWQ7XG5cbiAgZnVuY3Rpb24gc3RyYXRpZnkoZGF0YSkge1xuICAgIHZhciBkLFxuICAgICAgICBpLFxuICAgICAgICBuID0gZGF0YS5sZW5ndGgsXG4gICAgICAgIHJvb3QsXG4gICAgICAgIHBhcmVudCxcbiAgICAgICAgbm9kZSxcbiAgICAgICAgbm9kZXMgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIG5vZGVJZCxcbiAgICAgICAgbm9kZUtleSxcbiAgICAgICAgbm9kZUJ5S2V5ID0ge307XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBkID0gZGF0YVtpXSwgbm9kZSA9IG5vZGVzW2ldID0gbmV3IE5vZGUoZCk7XG4gICAgICBpZiAoKG5vZGVJZCA9IGlkKGQsIGksIGRhdGEpKSAhPSBudWxsICYmIChub2RlSWQgKz0gXCJcIikpIHtcbiAgICAgICAgbm9kZUtleSA9IGtleVByZWZpeCArIChub2RlLmlkID0gbm9kZUlkKTtcbiAgICAgICAgbm9kZUJ5S2V5W25vZGVLZXldID0gbm9kZUtleSBpbiBub2RlQnlLZXkgPyBhbWJpZ3VvdXMgOiBub2RlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIG5vZGUgPSBub2Rlc1tpXSwgbm9kZUlkID0gcGFyZW50SWQoZGF0YVtpXSwgaSwgZGF0YSk7XG4gICAgICBpZiAobm9kZUlkID09IG51bGwgfHwgIShub2RlSWQgKz0gXCJcIikpIHtcbiAgICAgICAgaWYgKHJvb3QpIHRocm93IG5ldyBFcnJvcihcIm11bHRpcGxlIHJvb3RzXCIpO1xuICAgICAgICByb290ID0gbm9kZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhcmVudCA9IG5vZGVCeUtleVtrZXlQcmVmaXggKyBub2RlSWRdO1xuICAgICAgICBpZiAoIXBhcmVudCkgdGhyb3cgbmV3IEVycm9yKFwibWlzc2luZzogXCIgKyBub2RlSWQpO1xuICAgICAgICBpZiAocGFyZW50ID09PSBhbWJpZ3VvdXMpIHRocm93IG5ldyBFcnJvcihcImFtYmlndW91czogXCIgKyBub2RlSWQpO1xuICAgICAgICBpZiAocGFyZW50LmNoaWxkcmVuKSBwYXJlbnQuY2hpbGRyZW4ucHVzaChub2RlKTtcbiAgICAgICAgZWxzZSBwYXJlbnQuY2hpbGRyZW4gPSBbbm9kZV07XG4gICAgICAgIG5vZGUucGFyZW50ID0gcGFyZW50O1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghcm9vdCkgdGhyb3cgbmV3IEVycm9yKFwibm8gcm9vdFwiKTtcbiAgICByb290LnBhcmVudCA9IHByZXJvb3Q7XG4gICAgcm9vdC5lYWNoQmVmb3JlKGZ1bmN0aW9uKG5vZGUpIHsgbm9kZS5kZXB0aCA9IG5vZGUucGFyZW50LmRlcHRoICsgMTsgLS1uOyB9KS5lYWNoQmVmb3JlKGNvbXB1dGVIZWlnaHQpO1xuICAgIHJvb3QucGFyZW50ID0gbnVsbDtcbiAgICBpZiAobiA+IDApIHRocm93IG5ldyBFcnJvcihcImN5Y2xlXCIpO1xuXG4gICAgcmV0dXJuIHJvb3Q7XG4gIH1cblxuICBzdHJhdGlmeS5pZCA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpZCA9IHJlcXVpcmVkKHgpLCBzdHJhdGlmeSkgOiBpZDtcbiAgfTtcblxuICBzdHJhdGlmeS5wYXJlbnRJZCA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwYXJlbnRJZCA9IHJlcXVpcmVkKHgpLCBzdHJhdGlmeSkgOiBwYXJlbnRJZDtcbiAgfTtcblxuICByZXR1cm4gc3RyYXRpZnk7XG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXBhcmF0aW9uJDEoYSwgYikge1xuICByZXR1cm4gYS5wYXJlbnQgPT09IGIucGFyZW50ID8gMSA6IDI7XG59XG5cbi8vIGZ1bmN0aW9uIHJhZGlhbFNlcGFyYXRpb24oYSwgYikge1xuLy8gICByZXR1cm4gKGEucGFyZW50ID09PSBiLnBhcmVudCA/IDEgOiAyKSAvIGEuZGVwdGg7XG4vLyB9XG5cbi8vIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCB0byB0cmF2ZXJzZSB0aGUgbGVmdCBjb250b3VyIG9mIGEgc3VidHJlZSAob3Jcbi8vIHN1YmZvcmVzdCkuIEl0IHJldHVybnMgdGhlIHN1Y2Nlc3NvciBvZiB2IG9uIHRoaXMgY29udG91ci4gVGhpcyBzdWNjZXNzb3IgaXNcbi8vIGVpdGhlciBnaXZlbiBieSB0aGUgbGVmdG1vc3QgY2hpbGQgb2YgdiBvciBieSB0aGUgdGhyZWFkIG9mIHYuIFRoZSBmdW5jdGlvblxuLy8gcmV0dXJucyBudWxsIGlmIGFuZCBvbmx5IGlmIHYgaXMgb24gdGhlIGhpZ2hlc3QgbGV2ZWwgb2YgaXRzIHN1YnRyZWUuXG5mdW5jdGlvbiBuZXh0TGVmdCh2KSB7XG4gIHZhciBjaGlsZHJlbiA9IHYuY2hpbGRyZW47XG4gIHJldHVybiBjaGlsZHJlbiA/IGNoaWxkcmVuWzBdIDogdi50O1xufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIHdvcmtzIGFuYWxvZ291c2x5IHRvIG5leHRMZWZ0LlxuZnVuY3Rpb24gbmV4dFJpZ2h0KHYpIHtcbiAgdmFyIGNoaWxkcmVuID0gdi5jaGlsZHJlbjtcbiAgcmV0dXJuIGNoaWxkcmVuID8gY2hpbGRyZW5bY2hpbGRyZW4ubGVuZ3RoIC0gMV0gOiB2LnQ7XG59XG5cbi8vIFNoaWZ0cyB0aGUgY3VycmVudCBzdWJ0cmVlIHJvb3RlZCBhdCB3Ky4gVGhpcyBpcyBkb25lIGJ5IGluY3JlYXNpbmdcbi8vIHByZWxpbSh3KykgYW5kIG1vZCh3KykgYnkgc2hpZnQuXG5mdW5jdGlvbiBtb3ZlU3VidHJlZSh3bSwgd3AsIHNoaWZ0KSB7XG4gIHZhciBjaGFuZ2UgPSBzaGlmdCAvICh3cC5pIC0gd20uaSk7XG4gIHdwLmMgLT0gY2hhbmdlO1xuICB3cC5zICs9IHNoaWZ0O1xuICB3bS5jICs9IGNoYW5nZTtcbiAgd3AueiArPSBzaGlmdDtcbiAgd3AubSArPSBzaGlmdDtcbn1cblxuLy8gQWxsIG90aGVyIHNoaWZ0cywgYXBwbGllZCB0byB0aGUgc21hbGxlciBzdWJ0cmVlcyBiZXR3ZWVuIHctIGFuZCB3KywgYXJlXG4vLyBwZXJmb3JtZWQgYnkgdGhpcyBmdW5jdGlvbi4gVG8gcHJlcGFyZSB0aGUgc2hpZnRzLCB3ZSBoYXZlIHRvIGFkanVzdFxuLy8gY2hhbmdlKHcrKSwgc2hpZnQodyspLCBhbmQgY2hhbmdlKHctKS5cbmZ1bmN0aW9uIGV4ZWN1dGVTaGlmdHModikge1xuICB2YXIgc2hpZnQgPSAwLFxuICAgICAgY2hhbmdlID0gMCxcbiAgICAgIGNoaWxkcmVuID0gdi5jaGlsZHJlbixcbiAgICAgIGkgPSBjaGlsZHJlbi5sZW5ndGgsXG4gICAgICB3O1xuICB3aGlsZSAoLS1pID49IDApIHtcbiAgICB3ID0gY2hpbGRyZW5baV07XG4gICAgdy56ICs9IHNoaWZ0O1xuICAgIHcubSArPSBzaGlmdDtcbiAgICBzaGlmdCArPSB3LnMgKyAoY2hhbmdlICs9IHcuYyk7XG4gIH1cbn1cblxuLy8gSWYgdmkt4oCZcyBhbmNlc3RvciBpcyBhIHNpYmxpbmcgb2YgdiwgcmV0dXJucyB2aS3igJlzIGFuY2VzdG9yLiBPdGhlcndpc2UsXG4vLyByZXR1cm5zIHRoZSBzcGVjaWZpZWQgKGRlZmF1bHQpIGFuY2VzdG9yLlxuZnVuY3Rpb24gbmV4dEFuY2VzdG9yKHZpbSwgdiwgYW5jZXN0b3IpIHtcbiAgcmV0dXJuIHZpbS5hLnBhcmVudCA9PT0gdi5wYXJlbnQgPyB2aW0uYSA6IGFuY2VzdG9yO1xufVxuXG5mdW5jdGlvbiBUcmVlTm9kZShub2RlLCBpKSB7XG4gIHRoaXMuXyA9IG5vZGU7XG4gIHRoaXMucGFyZW50ID0gbnVsbDtcbiAgdGhpcy5jaGlsZHJlbiA9IG51bGw7XG4gIHRoaXMuQSA9IG51bGw7IC8vIGRlZmF1bHQgYW5jZXN0b3JcbiAgdGhpcy5hID0gdGhpczsgLy8gYW5jZXN0b3JcbiAgdGhpcy56ID0gMDsgLy8gcHJlbGltXG4gIHRoaXMubSA9IDA7IC8vIG1vZFxuICB0aGlzLmMgPSAwOyAvLyBjaGFuZ2VcbiAgdGhpcy5zID0gMDsgLy8gc2hpZnRcbiAgdGhpcy50ID0gbnVsbDsgLy8gdGhyZWFkXG4gIHRoaXMuaSA9IGk7IC8vIG51bWJlclxufVxuXG5UcmVlTm9kZS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKE5vZGUucHJvdG90eXBlKTtcblxuZnVuY3Rpb24gdHJlZVJvb3Qocm9vdCkge1xuICB2YXIgdHJlZSA9IG5ldyBUcmVlTm9kZShyb290LCAwKSxcbiAgICAgIG5vZGUsXG4gICAgICBub2RlcyA9IFt0cmVlXSxcbiAgICAgIGNoaWxkLFxuICAgICAgY2hpbGRyZW4sXG4gICAgICBpLFxuICAgICAgbjtcblxuICB3aGlsZSAobm9kZSA9IG5vZGVzLnBvcCgpKSB7XG4gICAgaWYgKGNoaWxkcmVuID0gbm9kZS5fLmNoaWxkcmVuKSB7XG4gICAgICBub2RlLmNoaWxkcmVuID0gbmV3IEFycmF5KG4gPSBjaGlsZHJlbi5sZW5ndGgpO1xuICAgICAgZm9yIChpID0gbiAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgIG5vZGVzLnB1c2goY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldID0gbmV3IFRyZWVOb2RlKGNoaWxkcmVuW2ldLCBpKSk7XG4gICAgICAgIGNoaWxkLnBhcmVudCA9IG5vZGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgKHRyZWUucGFyZW50ID0gbmV3IFRyZWVOb2RlKG51bGwsIDApKS5jaGlsZHJlbiA9IFt0cmVlXTtcbiAgcmV0dXJuIHRyZWU7XG59XG5cbi8vIE5vZGUtbGluayB0cmVlIGRpYWdyYW0gdXNpbmcgdGhlIFJlaW5nb2xkLVRpbGZvcmQgXCJ0aWR5XCIgYWxnb3JpdGhtXG5mdW5jdGlvbiB0cmVlKCkge1xuICB2YXIgc2VwYXJhdGlvbiA9IGRlZmF1bHRTZXBhcmF0aW9uJDEsXG4gICAgICBkeCA9IDEsXG4gICAgICBkeSA9IDEsXG4gICAgICBub2RlU2l6ZSA9IG51bGw7XG5cbiAgZnVuY3Rpb24gdHJlZShyb290KSB7XG4gICAgdmFyIHQgPSB0cmVlUm9vdChyb290KTtcblxuICAgIC8vIENvbXB1dGUgdGhlIGxheW91dCB1c2luZyBCdWNoaGVpbSBldCBhbC7igJlzIGFsZ29yaXRobS5cbiAgICB0LmVhY2hBZnRlcihmaXJzdFdhbGspLCB0LnBhcmVudC5tID0gLXQuejtcbiAgICB0LmVhY2hCZWZvcmUoc2Vjb25kV2Fsayk7XG5cbiAgICAvLyBJZiBhIGZpeGVkIG5vZGUgc2l6ZSBpcyBzcGVjaWZpZWQsIHNjYWxlIHggYW5kIHkuXG4gICAgaWYgKG5vZGVTaXplKSByb290LmVhY2hCZWZvcmUoc2l6ZU5vZGUpO1xuXG4gICAgLy8gSWYgYSBmaXhlZCB0cmVlIHNpemUgaXMgc3BlY2lmaWVkLCBzY2FsZSB4IGFuZCB5IGJhc2VkIG9uIHRoZSBleHRlbnQuXG4gICAgLy8gQ29tcHV0ZSB0aGUgbGVmdC1tb3N0LCByaWdodC1tb3N0LCBhbmQgZGVwdGgtbW9zdCBub2RlcyBmb3IgZXh0ZW50cy5cbiAgICBlbHNlIHtcbiAgICAgIHZhciBsZWZ0ID0gcm9vdCxcbiAgICAgICAgICByaWdodCA9IHJvb3QsXG4gICAgICAgICAgYm90dG9tID0gcm9vdDtcbiAgICAgIHJvb3QuZWFjaEJlZm9yZShmdW5jdGlvbihub2RlKSB7XG4gICAgICAgIGlmIChub2RlLnggPCBsZWZ0LngpIGxlZnQgPSBub2RlO1xuICAgICAgICBpZiAobm9kZS54ID4gcmlnaHQueCkgcmlnaHQgPSBub2RlO1xuICAgICAgICBpZiAobm9kZS5kZXB0aCA+IGJvdHRvbS5kZXB0aCkgYm90dG9tID0gbm9kZTtcbiAgICAgIH0pO1xuICAgICAgdmFyIHMgPSBsZWZ0ID09PSByaWdodCA/IDEgOiBzZXBhcmF0aW9uKGxlZnQsIHJpZ2h0KSAvIDIsXG4gICAgICAgICAgdHggPSBzIC0gbGVmdC54LFxuICAgICAgICAgIGt4ID0gZHggLyAocmlnaHQueCArIHMgKyB0eCksXG4gICAgICAgICAga3kgPSBkeSAvIChib3R0b20uZGVwdGggfHwgMSk7XG4gICAgICByb290LmVhY2hCZWZvcmUoZnVuY3Rpb24obm9kZSkge1xuICAgICAgICBub2RlLnggPSAobm9kZS54ICsgdHgpICoga3g7XG4gICAgICAgIG5vZGUueSA9IG5vZGUuZGVwdGggKiBreTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiByb290O1xuICB9XG5cbiAgLy8gQ29tcHV0ZXMgYSBwcmVsaW1pbmFyeSB4LWNvb3JkaW5hdGUgZm9yIHYuIEJlZm9yZSB0aGF0LCBGSVJTVCBXQUxLIGlzXG4gIC8vIGFwcGxpZWQgcmVjdXJzaXZlbHkgdG8gdGhlIGNoaWxkcmVuIG9mIHYsIGFzIHdlbGwgYXMgdGhlIGZ1bmN0aW9uXG4gIC8vIEFQUE9SVElPTi4gQWZ0ZXIgc3BhY2luZyBvdXQgdGhlIGNoaWxkcmVuIGJ5IGNhbGxpbmcgRVhFQ1VURSBTSElGVFMsIHRoZVxuICAvLyBub2RlIHYgaXMgcGxhY2VkIHRvIHRoZSBtaWRwb2ludCBvZiBpdHMgb3V0ZXJtb3N0IGNoaWxkcmVuLlxuICBmdW5jdGlvbiBmaXJzdFdhbGsodikge1xuICAgIHZhciBjaGlsZHJlbiA9IHYuY2hpbGRyZW4sXG4gICAgICAgIHNpYmxpbmdzID0gdi5wYXJlbnQuY2hpbGRyZW4sXG4gICAgICAgIHcgPSB2LmkgPyBzaWJsaW5nc1t2LmkgLSAxXSA6IG51bGw7XG4gICAgaWYgKGNoaWxkcmVuKSB7XG4gICAgICBleGVjdXRlU2hpZnRzKHYpO1xuICAgICAgdmFyIG1pZHBvaW50ID0gKGNoaWxkcmVuWzBdLnogKyBjaGlsZHJlbltjaGlsZHJlbi5sZW5ndGggLSAxXS56KSAvIDI7XG4gICAgICBpZiAodykge1xuICAgICAgICB2LnogPSB3LnogKyBzZXBhcmF0aW9uKHYuXywgdy5fKTtcbiAgICAgICAgdi5tID0gdi56IC0gbWlkcG9pbnQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2LnogPSBtaWRwb2ludDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHcpIHtcbiAgICAgIHYueiA9IHcueiArIHNlcGFyYXRpb24odi5fLCB3Ll8pO1xuICAgIH1cbiAgICB2LnBhcmVudC5BID0gYXBwb3J0aW9uKHYsIHcsIHYucGFyZW50LkEgfHwgc2libGluZ3NbMF0pO1xuICB9XG5cbiAgLy8gQ29tcHV0ZXMgYWxsIHJlYWwgeC1jb29yZGluYXRlcyBieSBzdW1taW5nIHVwIHRoZSBtb2RpZmllcnMgcmVjdXJzaXZlbHkuXG4gIGZ1bmN0aW9uIHNlY29uZFdhbGsodikge1xuICAgIHYuXy54ID0gdi56ICsgdi5wYXJlbnQubTtcbiAgICB2Lm0gKz0gdi5wYXJlbnQubTtcbiAgfVxuXG4gIC8vIFRoZSBjb3JlIG9mIHRoZSBhbGdvcml0aG0uIEhlcmUsIGEgbmV3IHN1YnRyZWUgaXMgY29tYmluZWQgd2l0aCB0aGVcbiAgLy8gcHJldmlvdXMgc3VidHJlZXMuIFRocmVhZHMgYXJlIHVzZWQgdG8gdHJhdmVyc2UgdGhlIGluc2lkZSBhbmQgb3V0c2lkZVxuICAvLyBjb250b3VycyBvZiB0aGUgbGVmdCBhbmQgcmlnaHQgc3VidHJlZSB1cCB0byB0aGUgaGlnaGVzdCBjb21tb24gbGV2ZWwuIFRoZVxuICAvLyB2ZXJ0aWNlcyB1c2VkIGZvciB0aGUgdHJhdmVyc2FscyBhcmUgdmkrLCB2aS0sIHZvLSwgYW5kIHZvKywgd2hlcmUgdGhlXG4gIC8vIHN1cGVyc2NyaXB0IG8gbWVhbnMgb3V0c2lkZSBhbmQgaSBtZWFucyBpbnNpZGUsIHRoZSBzdWJzY3JpcHQgLSBtZWFucyBsZWZ0XG4gIC8vIHN1YnRyZWUgYW5kICsgbWVhbnMgcmlnaHQgc3VidHJlZS4gRm9yIHN1bW1pbmcgdXAgdGhlIG1vZGlmaWVycyBhbG9uZyB0aGVcbiAgLy8gY29udG91ciwgd2UgdXNlIHJlc3BlY3RpdmUgdmFyaWFibGVzIHNpKywgc2ktLCBzby0sIGFuZCBzbysuIFdoZW5ldmVyIHR3b1xuICAvLyBub2RlcyBvZiB0aGUgaW5zaWRlIGNvbnRvdXJzIGNvbmZsaWN0LCB3ZSBjb21wdXRlIHRoZSBsZWZ0IG9uZSBvZiB0aGVcbiAgLy8gZ3JlYXRlc3QgdW5jb21tb24gYW5jZXN0b3JzIHVzaW5nIHRoZSBmdW5jdGlvbiBBTkNFU1RPUiBhbmQgY2FsbCBNT1ZFXG4gIC8vIFNVQlRSRUUgdG8gc2hpZnQgdGhlIHN1YnRyZWUgYW5kIHByZXBhcmUgdGhlIHNoaWZ0cyBvZiBzbWFsbGVyIHN1YnRyZWVzLlxuICAvLyBGaW5hbGx5LCB3ZSBhZGQgYSBuZXcgdGhyZWFkIChpZiBuZWNlc3NhcnkpLlxuICBmdW5jdGlvbiBhcHBvcnRpb24odiwgdywgYW5jZXN0b3IpIHtcbiAgICBpZiAodykge1xuICAgICAgdmFyIHZpcCA9IHYsXG4gICAgICAgICAgdm9wID0gdixcbiAgICAgICAgICB2aW0gPSB3LFxuICAgICAgICAgIHZvbSA9IHZpcC5wYXJlbnQuY2hpbGRyZW5bMF0sXG4gICAgICAgICAgc2lwID0gdmlwLm0sXG4gICAgICAgICAgc29wID0gdm9wLm0sXG4gICAgICAgICAgc2ltID0gdmltLm0sXG4gICAgICAgICAgc29tID0gdm9tLm0sXG4gICAgICAgICAgc2hpZnQ7XG4gICAgICB3aGlsZSAodmltID0gbmV4dFJpZ2h0KHZpbSksIHZpcCA9IG5leHRMZWZ0KHZpcCksIHZpbSAmJiB2aXApIHtcbiAgICAgICAgdm9tID0gbmV4dExlZnQodm9tKTtcbiAgICAgICAgdm9wID0gbmV4dFJpZ2h0KHZvcCk7XG4gICAgICAgIHZvcC5hID0gdjtcbiAgICAgICAgc2hpZnQgPSB2aW0ueiArIHNpbSAtIHZpcC56IC0gc2lwICsgc2VwYXJhdGlvbih2aW0uXywgdmlwLl8pO1xuICAgICAgICBpZiAoc2hpZnQgPiAwKSB7XG4gICAgICAgICAgbW92ZVN1YnRyZWUobmV4dEFuY2VzdG9yKHZpbSwgdiwgYW5jZXN0b3IpLCB2LCBzaGlmdCk7XG4gICAgICAgICAgc2lwICs9IHNoaWZ0O1xuICAgICAgICAgIHNvcCArPSBzaGlmdDtcbiAgICAgICAgfVxuICAgICAgICBzaW0gKz0gdmltLm07XG4gICAgICAgIHNpcCArPSB2aXAubTtcbiAgICAgICAgc29tICs9IHZvbS5tO1xuICAgICAgICBzb3AgKz0gdm9wLm07XG4gICAgICB9XG4gICAgICBpZiAodmltICYmICFuZXh0UmlnaHQodm9wKSkge1xuICAgICAgICB2b3AudCA9IHZpbTtcbiAgICAgICAgdm9wLm0gKz0gc2ltIC0gc29wO1xuICAgICAgfVxuICAgICAgaWYgKHZpcCAmJiAhbmV4dExlZnQodm9tKSkge1xuICAgICAgICB2b20udCA9IHZpcDtcbiAgICAgICAgdm9tLm0gKz0gc2lwIC0gc29tO1xuICAgICAgICBhbmNlc3RvciA9IHY7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhbmNlc3RvcjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNpemVOb2RlKG5vZGUpIHtcbiAgICBub2RlLnggKj0gZHg7XG4gICAgbm9kZS55ID0gbm9kZS5kZXB0aCAqIGR5O1xuICB9XG5cbiAgdHJlZS5zZXBhcmF0aW9uID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNlcGFyYXRpb24gPSB4LCB0cmVlKSA6IHNlcGFyYXRpb247XG4gIH07XG5cbiAgdHJlZS5zaXplID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG5vZGVTaXplID0gZmFsc2UsIGR4ID0gK3hbMF0sIGR5ID0gK3hbMV0sIHRyZWUpIDogKG5vZGVTaXplID8gbnVsbCA6IFtkeCwgZHldKTtcbiAgfTtcblxuICB0cmVlLm5vZGVTaXplID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG5vZGVTaXplID0gdHJ1ZSwgZHggPSAreFswXSwgZHkgPSAreFsxXSwgdHJlZSkgOiAobm9kZVNpemUgPyBbZHgsIGR5XSA6IG51bGwpO1xuICB9O1xuXG4gIHJldHVybiB0cmVlO1xufVxuXG5mdW5jdGlvbiB0cmVlbWFwU2xpY2UocGFyZW50LCB4MCwgeTAsIHgxLCB5MSkge1xuICB2YXIgbm9kZXMgPSBwYXJlbnQuY2hpbGRyZW4sXG4gICAgICBub2RlLFxuICAgICAgaSA9IC0xLFxuICAgICAgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgIGsgPSBwYXJlbnQudmFsdWUgJiYgKHkxIC0geTApIC8gcGFyZW50LnZhbHVlO1xuXG4gIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgbm9kZSA9IG5vZGVzW2ldLCBub2RlLngwID0geDAsIG5vZGUueDEgPSB4MTtcbiAgICBub2RlLnkwID0geTAsIG5vZGUueTEgPSB5MCArPSBub2RlLnZhbHVlICogaztcbiAgfVxufVxuXG52YXIgcGhpID0gKDEgKyBNYXRoLnNxcnQoNSkpIC8gMjtcblxuZnVuY3Rpb24gc3F1YXJpZnlSYXRpbyhyYXRpbywgcGFyZW50LCB4MCwgeTAsIHgxLCB5MSkge1xuICB2YXIgcm93cyA9IFtdLFxuICAgICAgbm9kZXMgPSBwYXJlbnQuY2hpbGRyZW4sXG4gICAgICByb3csXG4gICAgICBub2RlVmFsdWUsXG4gICAgICBpMCA9IDAsXG4gICAgICBpMSA9IDAsXG4gICAgICBuID0gbm9kZXMubGVuZ3RoLFxuICAgICAgZHgsIGR5LFxuICAgICAgdmFsdWUgPSBwYXJlbnQudmFsdWUsXG4gICAgICBzdW1WYWx1ZSxcbiAgICAgIG1pblZhbHVlLFxuICAgICAgbWF4VmFsdWUsXG4gICAgICBuZXdSYXRpbyxcbiAgICAgIG1pblJhdGlvLFxuICAgICAgYWxwaGEsXG4gICAgICBiZXRhO1xuXG4gIHdoaWxlIChpMCA8IG4pIHtcbiAgICBkeCA9IHgxIC0geDAsIGR5ID0geTEgLSB5MDtcblxuICAgIC8vIEZpbmQgdGhlIG5leHQgbm9uLWVtcHR5IG5vZGUuXG4gICAgZG8gc3VtVmFsdWUgPSBub2Rlc1tpMSsrXS52YWx1ZTsgd2hpbGUgKCFzdW1WYWx1ZSAmJiBpMSA8IG4pO1xuICAgIG1pblZhbHVlID0gbWF4VmFsdWUgPSBzdW1WYWx1ZTtcbiAgICBhbHBoYSA9IE1hdGgubWF4KGR5IC8gZHgsIGR4IC8gZHkpIC8gKHZhbHVlICogcmF0aW8pO1xuICAgIGJldGEgPSBzdW1WYWx1ZSAqIHN1bVZhbHVlICogYWxwaGE7XG4gICAgbWluUmF0aW8gPSBNYXRoLm1heChtYXhWYWx1ZSAvIGJldGEsIGJldGEgLyBtaW5WYWx1ZSk7XG5cbiAgICAvLyBLZWVwIGFkZGluZyBub2RlcyB3aGlsZSB0aGUgYXNwZWN0IHJhdGlvIG1haW50YWlucyBvciBpbXByb3Zlcy5cbiAgICBmb3IgKDsgaTEgPCBuOyArK2kxKSB7XG4gICAgICBzdW1WYWx1ZSArPSBub2RlVmFsdWUgPSBub2Rlc1tpMV0udmFsdWU7XG4gICAgICBpZiAobm9kZVZhbHVlIDwgbWluVmFsdWUpIG1pblZhbHVlID0gbm9kZVZhbHVlO1xuICAgICAgaWYgKG5vZGVWYWx1ZSA+IG1heFZhbHVlKSBtYXhWYWx1ZSA9IG5vZGVWYWx1ZTtcbiAgICAgIGJldGEgPSBzdW1WYWx1ZSAqIHN1bVZhbHVlICogYWxwaGE7XG4gICAgICBuZXdSYXRpbyA9IE1hdGgubWF4KG1heFZhbHVlIC8gYmV0YSwgYmV0YSAvIG1pblZhbHVlKTtcbiAgICAgIGlmIChuZXdSYXRpbyA+IG1pblJhdGlvKSB7IHN1bVZhbHVlIC09IG5vZGVWYWx1ZTsgYnJlYWs7IH1cbiAgICAgIG1pblJhdGlvID0gbmV3UmF0aW87XG4gICAgfVxuXG4gICAgLy8gUG9zaXRpb24gYW5kIHJlY29yZCB0aGUgcm93IG9yaWVudGF0aW9uLlxuICAgIHJvd3MucHVzaChyb3cgPSB7dmFsdWU6IHN1bVZhbHVlLCBkaWNlOiBkeCA8IGR5LCBjaGlsZHJlbjogbm9kZXMuc2xpY2UoaTAsIGkxKX0pO1xuICAgIGlmIChyb3cuZGljZSkgdHJlZW1hcERpY2Uocm93LCB4MCwgeTAsIHgxLCB2YWx1ZSA/IHkwICs9IGR5ICogc3VtVmFsdWUgLyB2YWx1ZSA6IHkxKTtcbiAgICBlbHNlIHRyZWVtYXBTbGljZShyb3csIHgwLCB5MCwgdmFsdWUgPyB4MCArPSBkeCAqIHN1bVZhbHVlIC8gdmFsdWUgOiB4MSwgeTEpO1xuICAgIHZhbHVlIC09IHN1bVZhbHVlLCBpMCA9IGkxO1xuICB9XG5cbiAgcmV0dXJuIHJvd3M7XG59XG5cbnZhciBzcXVhcmlmeSA9IChmdW5jdGlvbiBjdXN0b20ocmF0aW8pIHtcblxuICBmdW5jdGlvbiBzcXVhcmlmeShwYXJlbnQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gICAgc3F1YXJpZnlSYXRpbyhyYXRpbywgcGFyZW50LCB4MCwgeTAsIHgxLCB5MSk7XG4gIH1cblxuICBzcXVhcmlmeS5yYXRpbyA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gY3VzdG9tKCh4ID0gK3gpID4gMSA/IHggOiAxKTtcbiAgfTtcblxuICByZXR1cm4gc3F1YXJpZnk7XG59KShwaGkpO1xuXG5mdW5jdGlvbiBpbmRleCQxKCkge1xuICB2YXIgdGlsZSA9IHNxdWFyaWZ5LFxuICAgICAgcm91bmQgPSBmYWxzZSxcbiAgICAgIGR4ID0gMSxcbiAgICAgIGR5ID0gMSxcbiAgICAgIHBhZGRpbmdTdGFjayA9IFswXSxcbiAgICAgIHBhZGRpbmdJbm5lciA9IGNvbnN0YW50WmVybyxcbiAgICAgIHBhZGRpbmdUb3AgPSBjb25zdGFudFplcm8sXG4gICAgICBwYWRkaW5nUmlnaHQgPSBjb25zdGFudFplcm8sXG4gICAgICBwYWRkaW5nQm90dG9tID0gY29uc3RhbnRaZXJvLFxuICAgICAgcGFkZGluZ0xlZnQgPSBjb25zdGFudFplcm87XG5cbiAgZnVuY3Rpb24gdHJlZW1hcChyb290KSB7XG4gICAgcm9vdC54MCA9XG4gICAgcm9vdC55MCA9IDA7XG4gICAgcm9vdC54MSA9IGR4O1xuICAgIHJvb3QueTEgPSBkeTtcbiAgICByb290LmVhY2hCZWZvcmUocG9zaXRpb25Ob2RlKTtcbiAgICBwYWRkaW5nU3RhY2sgPSBbMF07XG4gICAgaWYgKHJvdW5kKSByb290LmVhY2hCZWZvcmUocm91bmROb2RlKTtcbiAgICByZXR1cm4gcm9vdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBvc2l0aW9uTm9kZShub2RlKSB7XG4gICAgdmFyIHAgPSBwYWRkaW5nU3RhY2tbbm9kZS5kZXB0aF0sXG4gICAgICAgIHgwID0gbm9kZS54MCArIHAsXG4gICAgICAgIHkwID0gbm9kZS55MCArIHAsXG4gICAgICAgIHgxID0gbm9kZS54MSAtIHAsXG4gICAgICAgIHkxID0gbm9kZS55MSAtIHA7XG4gICAgaWYgKHgxIDwgeDApIHgwID0geDEgPSAoeDAgKyB4MSkgLyAyO1xuICAgIGlmICh5MSA8IHkwKSB5MCA9IHkxID0gKHkwICsgeTEpIC8gMjtcbiAgICBub2RlLngwID0geDA7XG4gICAgbm9kZS55MCA9IHkwO1xuICAgIG5vZGUueDEgPSB4MTtcbiAgICBub2RlLnkxID0geTE7XG4gICAgaWYgKG5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIHAgPSBwYWRkaW5nU3RhY2tbbm9kZS5kZXB0aCArIDFdID0gcGFkZGluZ0lubmVyKG5vZGUpIC8gMjtcbiAgICAgIHgwICs9IHBhZGRpbmdMZWZ0KG5vZGUpIC0gcDtcbiAgICAgIHkwICs9IHBhZGRpbmdUb3Aobm9kZSkgLSBwO1xuICAgICAgeDEgLT0gcGFkZGluZ1JpZ2h0KG5vZGUpIC0gcDtcbiAgICAgIHkxIC09IHBhZGRpbmdCb3R0b20obm9kZSkgLSBwO1xuICAgICAgaWYgKHgxIDwgeDApIHgwID0geDEgPSAoeDAgKyB4MSkgLyAyO1xuICAgICAgaWYgKHkxIDwgeTApIHkwID0geTEgPSAoeTAgKyB5MSkgLyAyO1xuICAgICAgdGlsZShub2RlLCB4MCwgeTAsIHgxLCB5MSk7XG4gICAgfVxuICB9XG5cbiAgdHJlZW1hcC5yb3VuZCA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyb3VuZCA9ICEheCwgdHJlZW1hcCkgOiByb3VuZDtcbiAgfTtcblxuICB0cmVlbWFwLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZHggPSAreFswXSwgZHkgPSAreFsxXSwgdHJlZW1hcCkgOiBbZHgsIGR5XTtcbiAgfTtcblxuICB0cmVlbWFwLnRpbGUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlsZSA9IHJlcXVpcmVkKHgpLCB0cmVlbWFwKSA6IHRpbGU7XG4gIH07XG5cbiAgdHJlZW1hcC5wYWRkaW5nID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gdHJlZW1hcC5wYWRkaW5nSW5uZXIoeCkucGFkZGluZ091dGVyKHgpIDogdHJlZW1hcC5wYWRkaW5nSW5uZXIoKTtcbiAgfTtcblxuICB0cmVlbWFwLnBhZGRpbmdJbm5lciA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwYWRkaW5nSW5uZXIgPSB0eXBlb2YgeCA9PT0gXCJmdW5jdGlvblwiID8geCA6IGNvbnN0YW50KCt4KSwgdHJlZW1hcCkgOiBwYWRkaW5nSW5uZXI7XG4gIH07XG5cbiAgdHJlZW1hcC5wYWRkaW5nT3V0ZXIgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyB0cmVlbWFwLnBhZGRpbmdUb3AoeCkucGFkZGluZ1JpZ2h0KHgpLnBhZGRpbmdCb3R0b20oeCkucGFkZGluZ0xlZnQoeCkgOiB0cmVlbWFwLnBhZGRpbmdUb3AoKTtcbiAgfTtcblxuICB0cmVlbWFwLnBhZGRpbmdUb3AgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkZGluZ1RvcCA9IHR5cGVvZiB4ID09PSBcImZ1bmN0aW9uXCIgPyB4IDogY29uc3RhbnQoK3gpLCB0cmVlbWFwKSA6IHBhZGRpbmdUb3A7XG4gIH07XG5cbiAgdHJlZW1hcC5wYWRkaW5nUmlnaHQgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkZGluZ1JpZ2h0ID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiBjb25zdGFudCgreCksIHRyZWVtYXApIDogcGFkZGluZ1JpZ2h0O1xuICB9O1xuXG4gIHRyZWVtYXAucGFkZGluZ0JvdHRvbSA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwYWRkaW5nQm90dG9tID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiBjb25zdGFudCgreCksIHRyZWVtYXApIDogcGFkZGluZ0JvdHRvbTtcbiAgfTtcblxuICB0cmVlbWFwLnBhZGRpbmdMZWZ0ID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBhZGRpbmdMZWZ0ID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiBjb25zdGFudCgreCksIHRyZWVtYXApIDogcGFkZGluZ0xlZnQ7XG4gIH07XG5cbiAgcmV0dXJuIHRyZWVtYXA7XG59XG5cbmZ1bmN0aW9uIGJpbmFyeShwYXJlbnQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gIHZhciBub2RlcyA9IHBhcmVudC5jaGlsZHJlbixcbiAgICAgIGksIG4gPSBub2Rlcy5sZW5ndGgsXG4gICAgICBzdW0sIHN1bXMgPSBuZXcgQXJyYXkobiArIDEpO1xuXG4gIGZvciAoc3Vtc1swXSA9IHN1bSA9IGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgc3Vtc1tpICsgMV0gPSBzdW0gKz0gbm9kZXNbaV0udmFsdWU7XG4gIH1cblxuICBwYXJ0aXRpb24oMCwgbiwgcGFyZW50LnZhbHVlLCB4MCwgeTAsIHgxLCB5MSk7XG5cbiAgZnVuY3Rpb24gcGFydGl0aW9uKGksIGosIHZhbHVlLCB4MCwgeTAsIHgxLCB5MSkge1xuICAgIGlmIChpID49IGogLSAxKSB7XG4gICAgICB2YXIgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgbm9kZS54MCA9IHgwLCBub2RlLnkwID0geTA7XG4gICAgICBub2RlLngxID0geDEsIG5vZGUueTEgPSB5MTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgdmFsdWVPZmZzZXQgPSBzdW1zW2ldLFxuICAgICAgICB2YWx1ZVRhcmdldCA9ICh2YWx1ZSAvIDIpICsgdmFsdWVPZmZzZXQsXG4gICAgICAgIGsgPSBpICsgMSxcbiAgICAgICAgaGkgPSBqIC0gMTtcblxuICAgIHdoaWxlIChrIDwgaGkpIHtcbiAgICAgIHZhciBtaWQgPSBrICsgaGkgPj4+IDE7XG4gICAgICBpZiAoc3Vtc1ttaWRdIDwgdmFsdWVUYXJnZXQpIGsgPSBtaWQgKyAxO1xuICAgICAgZWxzZSBoaSA9IG1pZDtcbiAgICB9XG5cbiAgICBpZiAoKHZhbHVlVGFyZ2V0IC0gc3Vtc1trIC0gMV0pIDwgKHN1bXNba10gLSB2YWx1ZVRhcmdldCkgJiYgaSArIDEgPCBrKSAtLWs7XG5cbiAgICB2YXIgdmFsdWVMZWZ0ID0gc3Vtc1trXSAtIHZhbHVlT2Zmc2V0LFxuICAgICAgICB2YWx1ZVJpZ2h0ID0gdmFsdWUgLSB2YWx1ZUxlZnQ7XG5cbiAgICBpZiAoKHgxIC0geDApID4gKHkxIC0geTApKSB7XG4gICAgICB2YXIgeGsgPSAoeDAgKiB2YWx1ZVJpZ2h0ICsgeDEgKiB2YWx1ZUxlZnQpIC8gdmFsdWU7XG4gICAgICBwYXJ0aXRpb24oaSwgaywgdmFsdWVMZWZ0LCB4MCwgeTAsIHhrLCB5MSk7XG4gICAgICBwYXJ0aXRpb24oaywgaiwgdmFsdWVSaWdodCwgeGssIHkwLCB4MSwgeTEpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgeWsgPSAoeTAgKiB2YWx1ZVJpZ2h0ICsgeTEgKiB2YWx1ZUxlZnQpIC8gdmFsdWU7XG4gICAgICBwYXJ0aXRpb24oaSwgaywgdmFsdWVMZWZ0LCB4MCwgeTAsIHgxLCB5ayk7XG4gICAgICBwYXJ0aXRpb24oaywgaiwgdmFsdWVSaWdodCwgeDAsIHlrLCB4MSwgeTEpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBzbGljZURpY2UocGFyZW50LCB4MCwgeTAsIHgxLCB5MSkge1xuICAocGFyZW50LmRlcHRoICYgMSA/IHRyZWVtYXBTbGljZSA6IHRyZWVtYXBEaWNlKShwYXJlbnQsIHgwLCB5MCwgeDEsIHkxKTtcbn1cblxudmFyIHJlc3F1YXJpZnkgPSAoZnVuY3Rpb24gY3VzdG9tKHJhdGlvKSB7XG5cbiAgZnVuY3Rpb24gcmVzcXVhcmlmeShwYXJlbnQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gICAgaWYgKChyb3dzID0gcGFyZW50Ll9zcXVhcmlmeSkgJiYgKHJvd3MucmF0aW8gPT09IHJhdGlvKSkge1xuICAgICAgdmFyIHJvd3MsXG4gICAgICAgICAgcm93LFxuICAgICAgICAgIG5vZGVzLFxuICAgICAgICAgIGksXG4gICAgICAgICAgaiA9IC0xLFxuICAgICAgICAgIG4sXG4gICAgICAgICAgbSA9IHJvd3MubGVuZ3RoLFxuICAgICAgICAgIHZhbHVlID0gcGFyZW50LnZhbHVlO1xuXG4gICAgICB3aGlsZSAoKytqIDwgbSkge1xuICAgICAgICByb3cgPSByb3dzW2pdLCBub2RlcyA9IHJvdy5jaGlsZHJlbjtcbiAgICAgICAgZm9yIChpID0gcm93LnZhbHVlID0gMCwgbiA9IG5vZGVzLmxlbmd0aDsgaSA8IG47ICsraSkgcm93LnZhbHVlICs9IG5vZGVzW2ldLnZhbHVlO1xuICAgICAgICBpZiAocm93LmRpY2UpIHRyZWVtYXBEaWNlKHJvdywgeDAsIHkwLCB4MSwgeTAgKz0gKHkxIC0geTApICogcm93LnZhbHVlIC8gdmFsdWUpO1xuICAgICAgICBlbHNlIHRyZWVtYXBTbGljZShyb3csIHgwLCB5MCwgeDAgKz0gKHgxIC0geDApICogcm93LnZhbHVlIC8gdmFsdWUsIHkxKTtcbiAgICAgICAgdmFsdWUgLT0gcm93LnZhbHVlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBwYXJlbnQuX3NxdWFyaWZ5ID0gcm93cyA9IHNxdWFyaWZ5UmF0aW8ocmF0aW8sIHBhcmVudCwgeDAsIHkwLCB4MSwgeTEpO1xuICAgICAgcm93cy5yYXRpbyA9IHJhdGlvO1xuICAgIH1cbiAgfVxuXG4gIHJlc3F1YXJpZnkucmF0aW8gPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGN1c3RvbSgoeCA9ICt4KSA+IDEgPyB4IDogMSk7XG4gIH07XG5cbiAgcmV0dXJuIHJlc3F1YXJpZnk7XG59KShwaGkpO1xuXG5leHBvcnRzLmNsdXN0ZXIgPSBjbHVzdGVyO1xuZXhwb3J0cy5oaWVyYXJjaHkgPSBoaWVyYXJjaHk7XG5leHBvcnRzLnBhY2sgPSBpbmRleDtcbmV4cG9ydHMucGFja1NpYmxpbmdzID0gc2libGluZ3M7XG5leHBvcnRzLnBhY2tFbmNsb3NlID0gZW5jbG9zZTtcbmV4cG9ydHMucGFydGl0aW9uID0gcGFydGl0aW9uO1xuZXhwb3J0cy5zdHJhdGlmeSA9IHN0cmF0aWZ5O1xuZXhwb3J0cy50cmVlID0gdHJlZTtcbmV4cG9ydHMudHJlZW1hcCA9IGluZGV4JDE7XG5leHBvcnRzLnRyZWVtYXBCaW5hcnkgPSBiaW5hcnk7XG5leHBvcnRzLnRyZWVtYXBEaWNlID0gdHJlZW1hcERpY2U7XG5leHBvcnRzLnRyZWVtYXBTbGljZSA9IHRyZWVtYXBTbGljZTtcbmV4cG9ydHMudHJlZW1hcFNsaWNlRGljZSA9IHNsaWNlRGljZTtcbmV4cG9ydHMudHJlZW1hcFNxdWFyaWZ5ID0gc3F1YXJpZnk7XG5leHBvcnRzLnRyZWVtYXBSZXNxdWFyaWZ5ID0gcmVzcXVhcmlmeTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcblxufSx7fV0sMTU4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtaW50ZXJwb2xhdGUvIHYxLjMuMiBDb3B5cmlnaHQgMjAxOCBNaWtlIEJvc3RvY2tcbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG50eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMsIF9kZXJlcV8oJ2QzLWNvbG9yJykpIDpcbnR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtY29sb3InXSwgZmFjdG9yeSkgOlxuKGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSksZ2xvYmFsLmQzKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cyxkM0NvbG9yKSB7ICd1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gYmFzaXModDEsIHYwLCB2MSwgdjIsIHYzKSB7XG4gIHZhciB0MiA9IHQxICogdDEsIHQzID0gdDIgKiB0MTtcbiAgcmV0dXJuICgoMSAtIDMgKiB0MSArIDMgKiB0MiAtIHQzKSAqIHYwXG4gICAgICArICg0IC0gNiAqIHQyICsgMyAqIHQzKSAqIHYxXG4gICAgICArICgxICsgMyAqIHQxICsgMyAqIHQyIC0gMyAqIHQzKSAqIHYyXG4gICAgICArIHQzICogdjMpIC8gNjtcbn1cblxuZnVuY3Rpb24gYmFzaXMkMSh2YWx1ZXMpIHtcbiAgdmFyIG4gPSB2YWx1ZXMubGVuZ3RoIC0gMTtcbiAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICB2YXIgaSA9IHQgPD0gMCA/ICh0ID0gMCkgOiB0ID49IDEgPyAodCA9IDEsIG4gLSAxKSA6IE1hdGguZmxvb3IodCAqIG4pLFxuICAgICAgICB2MSA9IHZhbHVlc1tpXSxcbiAgICAgICAgdjIgPSB2YWx1ZXNbaSArIDFdLFxuICAgICAgICB2MCA9IGkgPiAwID8gdmFsdWVzW2kgLSAxXSA6IDIgKiB2MSAtIHYyLFxuICAgICAgICB2MyA9IGkgPCBuIC0gMSA/IHZhbHVlc1tpICsgMl0gOiAyICogdjIgLSB2MTtcbiAgICByZXR1cm4gYmFzaXMoKHQgLSBpIC8gbikgKiBuLCB2MCwgdjEsIHYyLCB2Myk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGJhc2lzQ2xvc2VkKHZhbHVlcykge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGg7XG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgdmFyIGkgPSBNYXRoLmZsb29yKCgodCAlPSAxKSA8IDAgPyArK3QgOiB0KSAqIG4pLFxuICAgICAgICB2MCA9IHZhbHVlc1soaSArIG4gLSAxKSAlIG5dLFxuICAgICAgICB2MSA9IHZhbHVlc1tpICUgbl0sXG4gICAgICAgIHYyID0gdmFsdWVzWyhpICsgMSkgJSBuXSxcbiAgICAgICAgdjMgPSB2YWx1ZXNbKGkgKyAyKSAlIG5dO1xuICAgIHJldHVybiBiYXNpcygodCAtIGkgLyBuKSAqIG4sIHYwLCB2MSwgdjIsIHYzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gY29uc3RhbnQoeCkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHg7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGxpbmVhcihhLCBkKSB7XG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuIGEgKyB0ICogZDtcbiAgfTtcbn1cblxuZnVuY3Rpb24gZXhwb25lbnRpYWwoYSwgYiwgeSkge1xuICByZXR1cm4gYSA9IE1hdGgucG93KGEsIHkpLCBiID0gTWF0aC5wb3coYiwgeSkgLSBhLCB5ID0gMSAvIHksIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gTWF0aC5wb3coYSArIHQgKiBiLCB5KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gaHVlKGEsIGIpIHtcbiAgdmFyIGQgPSBiIC0gYTtcbiAgcmV0dXJuIGQgPyBsaW5lYXIoYSwgZCA+IDE4MCB8fCBkIDwgLTE4MCA/IGQgLSAzNjAgKiBNYXRoLnJvdW5kKGQgLyAzNjApIDogZCkgOiBjb25zdGFudChpc05hTihhKSA/IGIgOiBhKTtcbn1cblxuZnVuY3Rpb24gZ2FtbWEoeSkge1xuICByZXR1cm4gKHkgPSAreSkgPT09IDEgPyBub2dhbW1hIDogZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBiIC0gYSA/IGV4cG9uZW50aWFsKGEsIGIsIHkpIDogY29uc3RhbnQoaXNOYU4oYSkgPyBiIDogYSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG5vZ2FtbWEoYSwgYikge1xuICB2YXIgZCA9IGIgLSBhO1xuICByZXR1cm4gZCA/IGxpbmVhcihhLCBkKSA6IGNvbnN0YW50KGlzTmFOKGEpID8gYiA6IGEpO1xufVxuXG52YXIgcmdiID0gKGZ1bmN0aW9uIHJnYkdhbW1hKHkpIHtcbiAgdmFyIGNvbG9yID0gZ2FtbWEoeSk7XG5cbiAgZnVuY3Rpb24gcmdiKHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgciA9IGNvbG9yKChzdGFydCA9IGQzQ29sb3IucmdiKHN0YXJ0KSkuciwgKGVuZCA9IGQzQ29sb3IucmdiKGVuZCkpLnIpLFxuICAgICAgICBnID0gY29sb3Ioc3RhcnQuZywgZW5kLmcpLFxuICAgICAgICBiID0gY29sb3Ioc3RhcnQuYiwgZW5kLmIpLFxuICAgICAgICBvcGFjaXR5ID0gbm9nYW1tYShzdGFydC5vcGFjaXR5LCBlbmQub3BhY2l0eSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIHN0YXJ0LnIgPSByKHQpO1xuICAgICAgc3RhcnQuZyA9IGcodCk7XG4gICAgICBzdGFydC5iID0gYih0KTtcbiAgICAgIHN0YXJ0Lm9wYWNpdHkgPSBvcGFjaXR5KHQpO1xuICAgICAgcmV0dXJuIHN0YXJ0ICsgXCJcIjtcbiAgICB9O1xuICB9XG5cbiAgcmdiLmdhbW1hID0gcmdiR2FtbWE7XG5cbiAgcmV0dXJuIHJnYjtcbn0pKDEpO1xuXG5mdW5jdGlvbiByZ2JTcGxpbmUoc3BsaW5lKSB7XG4gIHJldHVybiBmdW5jdGlvbihjb2xvcnMpIHtcbiAgICB2YXIgbiA9IGNvbG9ycy5sZW5ndGgsXG4gICAgICAgIHIgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGcgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGIgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGksIGNvbG9yO1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGNvbG9yID0gZDNDb2xvci5yZ2IoY29sb3JzW2ldKTtcbiAgICAgIHJbaV0gPSBjb2xvci5yIHx8IDA7XG4gICAgICBnW2ldID0gY29sb3IuZyB8fCAwO1xuICAgICAgYltpXSA9IGNvbG9yLmIgfHwgMDtcbiAgICB9XG4gICAgciA9IHNwbGluZShyKTtcbiAgICBnID0gc3BsaW5lKGcpO1xuICAgIGIgPSBzcGxpbmUoYik7XG4gICAgY29sb3Iub3BhY2l0eSA9IDE7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIGNvbG9yLnIgPSByKHQpO1xuICAgICAgY29sb3IuZyA9IGcodCk7XG4gICAgICBjb2xvci5iID0gYih0KTtcbiAgICAgIHJldHVybiBjb2xvciArIFwiXCI7XG4gICAgfTtcbiAgfTtcbn1cblxudmFyIHJnYkJhc2lzID0gcmdiU3BsaW5lKGJhc2lzJDEpO1xudmFyIHJnYkJhc2lzQ2xvc2VkID0gcmdiU3BsaW5lKGJhc2lzQ2xvc2VkKTtcblxuZnVuY3Rpb24gYXJyYXkoYSwgYikge1xuICB2YXIgbmIgPSBiID8gYi5sZW5ndGggOiAwLFxuICAgICAgbmEgPSBhID8gTWF0aC5taW4obmIsIGEubGVuZ3RoKSA6IDAsXG4gICAgICB4ID0gbmV3IEFycmF5KG5hKSxcbiAgICAgIGMgPSBuZXcgQXJyYXkobmIpLFxuICAgICAgaTtcblxuICBmb3IgKGkgPSAwOyBpIDwgbmE7ICsraSkgeFtpXSA9IHZhbHVlKGFbaV0sIGJbaV0pO1xuICBmb3IgKDsgaSA8IG5iOyArK2kpIGNbaV0gPSBiW2ldO1xuXG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgZm9yIChpID0gMDsgaSA8IG5hOyArK2kpIGNbaV0gPSB4W2ldKHQpO1xuICAgIHJldHVybiBjO1xuICB9O1xufVxuXG5mdW5jdGlvbiBkYXRlKGEsIGIpIHtcbiAgdmFyIGQgPSBuZXcgRGF0ZTtcbiAgcmV0dXJuIGEgPSArYSwgYiAtPSBhLCBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuIGQuc2V0VGltZShhICsgYiAqIHQpLCBkO1xuICB9O1xufVxuXG5mdW5jdGlvbiBudW1iZXIoYSwgYikge1xuICByZXR1cm4gYSA9ICthLCBiIC09IGEsIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gYSArIGIgKiB0O1xuICB9O1xufVxuXG5mdW5jdGlvbiBvYmplY3QoYSwgYikge1xuICB2YXIgaSA9IHt9LFxuICAgICAgYyA9IHt9LFxuICAgICAgaztcblxuICBpZiAoYSA9PT0gbnVsbCB8fCB0eXBlb2YgYSAhPT0gXCJvYmplY3RcIikgYSA9IHt9O1xuICBpZiAoYiA9PT0gbnVsbCB8fCB0eXBlb2YgYiAhPT0gXCJvYmplY3RcIikgYiA9IHt9O1xuXG4gIGZvciAoayBpbiBiKSB7XG4gICAgaWYgKGsgaW4gYSkge1xuICAgICAgaVtrXSA9IHZhbHVlKGFba10sIGJba10pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjW2tdID0gYltrXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgIGZvciAoayBpbiBpKSBjW2tdID0gaVtrXSh0KTtcbiAgICByZXR1cm4gYztcbiAgfTtcbn1cblxudmFyIHJlQSA9IC9bLStdPyg/OlxcZCtcXC4/XFxkKnxcXC4/XFxkKykoPzpbZUVdWy0rXT9cXGQrKT8vZyxcbiAgICByZUIgPSBuZXcgUmVnRXhwKHJlQS5zb3VyY2UsIFwiZ1wiKTtcblxuZnVuY3Rpb24gemVybyhiKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gb25lKGIpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gYih0KSArIFwiXCI7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHN0cmluZyhhLCBiKSB7XG4gIHZhciBiaSA9IHJlQS5sYXN0SW5kZXggPSByZUIubGFzdEluZGV4ID0gMCwgLy8gc2NhbiBpbmRleCBmb3IgbmV4dCBudW1iZXIgaW4gYlxuICAgICAgYW0sIC8vIGN1cnJlbnQgbWF0Y2ggaW4gYVxuICAgICAgYm0sIC8vIGN1cnJlbnQgbWF0Y2ggaW4gYlxuICAgICAgYnMsIC8vIHN0cmluZyBwcmVjZWRpbmcgY3VycmVudCBudW1iZXIgaW4gYiwgaWYgYW55XG4gICAgICBpID0gLTEsIC8vIGluZGV4IGluIHNcbiAgICAgIHMgPSBbXSwgLy8gc3RyaW5nIGNvbnN0YW50cyBhbmQgcGxhY2Vob2xkZXJzXG4gICAgICBxID0gW107IC8vIG51bWJlciBpbnRlcnBvbGF0b3JzXG5cbiAgLy8gQ29lcmNlIGlucHV0cyB0byBzdHJpbmdzLlxuICBhID0gYSArIFwiXCIsIGIgPSBiICsgXCJcIjtcblxuICAvLyBJbnRlcnBvbGF0ZSBwYWlycyBvZiBudW1iZXJzIGluIGEgJiBiLlxuICB3aGlsZSAoKGFtID0gcmVBLmV4ZWMoYSkpXG4gICAgICAmJiAoYm0gPSByZUIuZXhlYyhiKSkpIHtcbiAgICBpZiAoKGJzID0gYm0uaW5kZXgpID4gYmkpIHsgLy8gYSBzdHJpbmcgcHJlY2VkZXMgdGhlIG5leHQgbnVtYmVyIGluIGJcbiAgICAgIGJzID0gYi5zbGljZShiaSwgYnMpO1xuICAgICAgaWYgKHNbaV0pIHNbaV0gKz0gYnM7IC8vIGNvYWxlc2NlIHdpdGggcHJldmlvdXMgc3RyaW5nXG4gICAgICBlbHNlIHNbKytpXSA9IGJzO1xuICAgIH1cbiAgICBpZiAoKGFtID0gYW1bMF0pID09PSAoYm0gPSBibVswXSkpIHsgLy8gbnVtYmVycyBpbiBhICYgYiBtYXRjaFxuICAgICAgaWYgKHNbaV0pIHNbaV0gKz0gYm07IC8vIGNvYWxlc2NlIHdpdGggcHJldmlvdXMgc3RyaW5nXG4gICAgICBlbHNlIHNbKytpXSA9IGJtO1xuICAgIH0gZWxzZSB7IC8vIGludGVycG9sYXRlIG5vbi1tYXRjaGluZyBudW1iZXJzXG4gICAgICBzWysraV0gPSBudWxsO1xuICAgICAgcS5wdXNoKHtpOiBpLCB4OiBudW1iZXIoYW0sIGJtKX0pO1xuICAgIH1cbiAgICBiaSA9IHJlQi5sYXN0SW5kZXg7XG4gIH1cblxuICAvLyBBZGQgcmVtYWlucyBvZiBiLlxuICBpZiAoYmkgPCBiLmxlbmd0aCkge1xuICAgIGJzID0gYi5zbGljZShiaSk7XG4gICAgaWYgKHNbaV0pIHNbaV0gKz0gYnM7IC8vIGNvYWxlc2NlIHdpdGggcHJldmlvdXMgc3RyaW5nXG4gICAgZWxzZSBzWysraV0gPSBicztcbiAgfVxuXG4gIC8vIFNwZWNpYWwgb3B0aW1pemF0aW9uIGZvciBvbmx5IGEgc2luZ2xlIG1hdGNoLlxuICAvLyBPdGhlcndpc2UsIGludGVycG9sYXRlIGVhY2ggb2YgdGhlIG51bWJlcnMgYW5kIHJlam9pbiB0aGUgc3RyaW5nLlxuICByZXR1cm4gcy5sZW5ndGggPCAyID8gKHFbMF1cbiAgICAgID8gb25lKHFbMF0ueClcbiAgICAgIDogemVybyhiKSlcbiAgICAgIDogKGIgPSBxLmxlbmd0aCwgZnVuY3Rpb24odCkge1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBvOyBpIDwgYjsgKytpKSBzWyhvID0gcVtpXSkuaV0gPSBvLngodCk7XG4gICAgICAgICAgcmV0dXJuIHMuam9pbihcIlwiKTtcbiAgICAgICAgfSk7XG59XG5cbmZ1bmN0aW9uIHZhbHVlKGEsIGIpIHtcbiAgdmFyIHQgPSB0eXBlb2YgYiwgYztcbiAgcmV0dXJuIGIgPT0gbnVsbCB8fCB0ID09PSBcImJvb2xlYW5cIiA/IGNvbnN0YW50KGIpXG4gICAgICA6ICh0ID09PSBcIm51bWJlclwiID8gbnVtYmVyXG4gICAgICA6IHQgPT09IFwic3RyaW5nXCIgPyAoKGMgPSBkM0NvbG9yLmNvbG9yKGIpKSA/IChiID0gYywgcmdiKSA6IHN0cmluZylcbiAgICAgIDogYiBpbnN0YW5jZW9mIGQzQ29sb3IuY29sb3IgPyByZ2JcbiAgICAgIDogYiBpbnN0YW5jZW9mIERhdGUgPyBkYXRlXG4gICAgICA6IEFycmF5LmlzQXJyYXkoYikgPyBhcnJheVxuICAgICAgOiB0eXBlb2YgYi52YWx1ZU9mICE9PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGIudG9TdHJpbmcgIT09IFwiZnVuY3Rpb25cIiB8fCBpc05hTihiKSA/IG9iamVjdFxuICAgICAgOiBudW1iZXIpKGEsIGIpO1xufVxuXG5mdW5jdGlvbiBkaXNjcmV0ZShyYW5nZSkge1xuICB2YXIgbiA9IHJhbmdlLmxlbmd0aDtcbiAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gcmFuZ2VbTWF0aC5tYXgoMCwgTWF0aC5taW4obiAtIDEsIE1hdGguZmxvb3IodCAqIG4pKSldO1xuICB9O1xufVxuXG5mdW5jdGlvbiBodWUkMShhLCBiKSB7XG4gIHZhciBpID0gaHVlKCthLCArYik7XG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgdmFyIHggPSBpKHQpO1xuICAgIHJldHVybiB4IC0gMzYwICogTWF0aC5mbG9vcih4IC8gMzYwKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcm91bmQoYSwgYikge1xuICByZXR1cm4gYSA9ICthLCBiIC09IGEsIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChhICsgYiAqIHQpO1xuICB9O1xufVxuXG52YXIgZGVncmVlcyA9IDE4MCAvIE1hdGguUEk7XG5cbnZhciBpZGVudGl0eSA9IHtcbiAgdHJhbnNsYXRlWDogMCxcbiAgdHJhbnNsYXRlWTogMCxcbiAgcm90YXRlOiAwLFxuICBza2V3WDogMCxcbiAgc2NhbGVYOiAxLFxuICBzY2FsZVk6IDFcbn07XG5cbmZ1bmN0aW9uIGRlY29tcG9zZShhLCBiLCBjLCBkLCBlLCBmKSB7XG4gIHZhciBzY2FsZVgsIHNjYWxlWSwgc2tld1g7XG4gIGlmIChzY2FsZVggPSBNYXRoLnNxcnQoYSAqIGEgKyBiICogYikpIGEgLz0gc2NhbGVYLCBiIC89IHNjYWxlWDtcbiAgaWYgKHNrZXdYID0gYSAqIGMgKyBiICogZCkgYyAtPSBhICogc2tld1gsIGQgLT0gYiAqIHNrZXdYO1xuICBpZiAoc2NhbGVZID0gTWF0aC5zcXJ0KGMgKiBjICsgZCAqIGQpKSBjIC89IHNjYWxlWSwgZCAvPSBzY2FsZVksIHNrZXdYIC89IHNjYWxlWTtcbiAgaWYgKGEgKiBkIDwgYiAqIGMpIGEgPSAtYSwgYiA9IC1iLCBza2V3WCA9IC1za2V3WCwgc2NhbGVYID0gLXNjYWxlWDtcbiAgcmV0dXJuIHtcbiAgICB0cmFuc2xhdGVYOiBlLFxuICAgIHRyYW5zbGF0ZVk6IGYsXG4gICAgcm90YXRlOiBNYXRoLmF0YW4yKGIsIGEpICogZGVncmVlcyxcbiAgICBza2V3WDogTWF0aC5hdGFuKHNrZXdYKSAqIGRlZ3JlZXMsXG4gICAgc2NhbGVYOiBzY2FsZVgsXG4gICAgc2NhbGVZOiBzY2FsZVlcbiAgfTtcbn1cblxudmFyIGNzc05vZGUsXG4gICAgY3NzUm9vdCxcbiAgICBjc3NWaWV3LFxuICAgIHN2Z05vZGU7XG5cbmZ1bmN0aW9uIHBhcnNlQ3NzKHZhbHVlKSB7XG4gIGlmICh2YWx1ZSA9PT0gXCJub25lXCIpIHJldHVybiBpZGVudGl0eTtcbiAgaWYgKCFjc3NOb2RlKSBjc3NOb2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIkRJVlwiKSwgY3NzUm9vdCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgY3NzVmlldyA9IGRvY3VtZW50LmRlZmF1bHRWaWV3O1xuICBjc3NOb2RlLnN0eWxlLnRyYW5zZm9ybSA9IHZhbHVlO1xuICB2YWx1ZSA9IGNzc1ZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShjc3NSb290LmFwcGVuZENoaWxkKGNzc05vZGUpLCBudWxsKS5nZXRQcm9wZXJ0eVZhbHVlKFwidHJhbnNmb3JtXCIpO1xuICBjc3NSb290LnJlbW92ZUNoaWxkKGNzc05vZGUpO1xuICB2YWx1ZSA9IHZhbHVlLnNsaWNlKDcsIC0xKS5zcGxpdChcIixcIik7XG4gIHJldHVybiBkZWNvbXBvc2UoK3ZhbHVlWzBdLCArdmFsdWVbMV0sICt2YWx1ZVsyXSwgK3ZhbHVlWzNdLCArdmFsdWVbNF0sICt2YWx1ZVs1XSk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlU3ZnKHZhbHVlKSB7XG4gIGlmICh2YWx1ZSA9PSBudWxsKSByZXR1cm4gaWRlbnRpdHk7XG4gIGlmICghc3ZnTm9kZSkgc3ZnTm9kZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsIFwiZ1wiKTtcbiAgc3ZnTm9kZS5zZXRBdHRyaWJ1dGUoXCJ0cmFuc2Zvcm1cIiwgdmFsdWUpO1xuICBpZiAoISh2YWx1ZSA9IHN2Z05vZGUudHJhbnNmb3JtLmJhc2VWYWwuY29uc29saWRhdGUoKSkpIHJldHVybiBpZGVudGl0eTtcbiAgdmFsdWUgPSB2YWx1ZS5tYXRyaXg7XG4gIHJldHVybiBkZWNvbXBvc2UodmFsdWUuYSwgdmFsdWUuYiwgdmFsdWUuYywgdmFsdWUuZCwgdmFsdWUuZSwgdmFsdWUuZik7XG59XG5cbmZ1bmN0aW9uIGludGVycG9sYXRlVHJhbnNmb3JtKHBhcnNlLCBweENvbW1hLCBweFBhcmVuLCBkZWdQYXJlbikge1xuXG4gIGZ1bmN0aW9uIHBvcChzKSB7XG4gICAgcmV0dXJuIHMubGVuZ3RoID8gcy5wb3AoKSArIFwiIFwiIDogXCJcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRyYW5zbGF0ZSh4YSwgeWEsIHhiLCB5YiwgcywgcSkge1xuICAgIGlmICh4YSAhPT0geGIgfHwgeWEgIT09IHliKSB7XG4gICAgICB2YXIgaSA9IHMucHVzaChcInRyYW5zbGF0ZShcIiwgbnVsbCwgcHhDb21tYSwgbnVsbCwgcHhQYXJlbik7XG4gICAgICBxLnB1c2goe2k6IGkgLSA0LCB4OiBudW1iZXIoeGEsIHhiKX0sIHtpOiBpIC0gMiwgeDogbnVtYmVyKHlhLCB5Yil9KTtcbiAgICB9IGVsc2UgaWYgKHhiIHx8IHliKSB7XG4gICAgICBzLnB1c2goXCJ0cmFuc2xhdGUoXCIgKyB4YiArIHB4Q29tbWEgKyB5YiArIHB4UGFyZW4pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHJvdGF0ZShhLCBiLCBzLCBxKSB7XG4gICAgaWYgKGEgIT09IGIpIHtcbiAgICAgIGlmIChhIC0gYiA+IDE4MCkgYiArPSAzNjA7IGVsc2UgaWYgKGIgLSBhID4gMTgwKSBhICs9IDM2MDsgLy8gc2hvcnRlc3QgcGF0aFxuICAgICAgcS5wdXNoKHtpOiBzLnB1c2gocG9wKHMpICsgXCJyb3RhdGUoXCIsIG51bGwsIGRlZ1BhcmVuKSAtIDIsIHg6IG51bWJlcihhLCBiKX0pO1xuICAgIH0gZWxzZSBpZiAoYikge1xuICAgICAgcy5wdXNoKHBvcChzKSArIFwicm90YXRlKFwiICsgYiArIGRlZ1BhcmVuKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBza2V3WChhLCBiLCBzLCBxKSB7XG4gICAgaWYgKGEgIT09IGIpIHtcbiAgICAgIHEucHVzaCh7aTogcy5wdXNoKHBvcChzKSArIFwic2tld1goXCIsIG51bGwsIGRlZ1BhcmVuKSAtIDIsIHg6IG51bWJlcihhLCBiKX0pO1xuICAgIH0gZWxzZSBpZiAoYikge1xuICAgICAgcy5wdXNoKHBvcChzKSArIFwic2tld1goXCIgKyBiICsgZGVnUGFyZW4pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNjYWxlKHhhLCB5YSwgeGIsIHliLCBzLCBxKSB7XG4gICAgaWYgKHhhICE9PSB4YiB8fCB5YSAhPT0geWIpIHtcbiAgICAgIHZhciBpID0gcy5wdXNoKHBvcChzKSArIFwic2NhbGUoXCIsIG51bGwsIFwiLFwiLCBudWxsLCBcIilcIik7XG4gICAgICBxLnB1c2goe2k6IGkgLSA0LCB4OiBudW1iZXIoeGEsIHhiKX0sIHtpOiBpIC0gMiwgeDogbnVtYmVyKHlhLCB5Yil9KTtcbiAgICB9IGVsc2UgaWYgKHhiICE9PSAxIHx8IHliICE9PSAxKSB7XG4gICAgICBzLnB1c2gocG9wKHMpICsgXCJzY2FsZShcIiArIHhiICsgXCIsXCIgKyB5YiArIFwiKVwiKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24oYSwgYikge1xuICAgIHZhciBzID0gW10sIC8vIHN0cmluZyBjb25zdGFudHMgYW5kIHBsYWNlaG9sZGVyc1xuICAgICAgICBxID0gW107IC8vIG51bWJlciBpbnRlcnBvbGF0b3JzXG4gICAgYSA9IHBhcnNlKGEpLCBiID0gcGFyc2UoYik7XG4gICAgdHJhbnNsYXRlKGEudHJhbnNsYXRlWCwgYS50cmFuc2xhdGVZLCBiLnRyYW5zbGF0ZVgsIGIudHJhbnNsYXRlWSwgcywgcSk7XG4gICAgcm90YXRlKGEucm90YXRlLCBiLnJvdGF0ZSwgcywgcSk7XG4gICAgc2tld1goYS5za2V3WCwgYi5za2V3WCwgcywgcSk7XG4gICAgc2NhbGUoYS5zY2FsZVgsIGEuc2NhbGVZLCBiLnNjYWxlWCwgYi5zY2FsZVksIHMsIHEpO1xuICAgIGEgPSBiID0gbnVsbDsgLy8gZ2NcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IHEubGVuZ3RoLCBvO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHNbKG8gPSBxW2ldKS5pXSA9IG8ueCh0KTtcbiAgICAgIHJldHVybiBzLmpvaW4oXCJcIik7XG4gICAgfTtcbiAgfTtcbn1cblxudmFyIGludGVycG9sYXRlVHJhbnNmb3JtQ3NzID0gaW50ZXJwb2xhdGVUcmFuc2Zvcm0ocGFyc2VDc3MsIFwicHgsIFwiLCBcInB4KVwiLCBcImRlZylcIik7XG52YXIgaW50ZXJwb2xhdGVUcmFuc2Zvcm1TdmcgPSBpbnRlcnBvbGF0ZVRyYW5zZm9ybShwYXJzZVN2ZywgXCIsIFwiLCBcIilcIiwgXCIpXCIpO1xuXG52YXIgcmhvID0gTWF0aC5TUVJUMixcbiAgICByaG8yID0gMixcbiAgICByaG80ID0gNCxcbiAgICBlcHNpbG9uMiA9IDFlLTEyO1xuXG5mdW5jdGlvbiBjb3NoKHgpIHtcbiAgcmV0dXJuICgoeCA9IE1hdGguZXhwKHgpKSArIDEgLyB4KSAvIDI7XG59XG5cbmZ1bmN0aW9uIHNpbmgoeCkge1xuICByZXR1cm4gKCh4ID0gTWF0aC5leHAoeCkpIC0gMSAvIHgpIC8gMjtcbn1cblxuZnVuY3Rpb24gdGFuaCh4KSB7XG4gIHJldHVybiAoKHggPSBNYXRoLmV4cCgyICogeCkpIC0gMSkgLyAoeCArIDEpO1xufVxuXG4vLyBwMCA9IFt1eDAsIHV5MCwgdzBdXG4vLyBwMSA9IFt1eDEsIHV5MSwgdzFdXG5mdW5jdGlvbiB6b29tKHAwLCBwMSkge1xuICB2YXIgdXgwID0gcDBbMF0sIHV5MCA9IHAwWzFdLCB3MCA9IHAwWzJdLFxuICAgICAgdXgxID0gcDFbMF0sIHV5MSA9IHAxWzFdLCB3MSA9IHAxWzJdLFxuICAgICAgZHggPSB1eDEgLSB1eDAsXG4gICAgICBkeSA9IHV5MSAtIHV5MCxcbiAgICAgIGQyID0gZHggKiBkeCArIGR5ICogZHksXG4gICAgICBpLFxuICAgICAgUztcblxuICAvLyBTcGVjaWFsIGNhc2UgZm9yIHUwIOKJhSB1MS5cbiAgaWYgKGQyIDwgZXBzaWxvbjIpIHtcbiAgICBTID0gTWF0aC5sb2codzEgLyB3MCkgLyByaG87XG4gICAgaSA9IGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIHV4MCArIHQgKiBkeCxcbiAgICAgICAgdXkwICsgdCAqIGR5LFxuICAgICAgICB3MCAqIE1hdGguZXhwKHJobyAqIHQgKiBTKVxuICAgICAgXTtcbiAgICB9O1xuICB9XG5cbiAgLy8gR2VuZXJhbCBjYXNlLlxuICBlbHNlIHtcbiAgICB2YXIgZDEgPSBNYXRoLnNxcnQoZDIpLFxuICAgICAgICBiMCA9ICh3MSAqIHcxIC0gdzAgKiB3MCArIHJobzQgKiBkMikgLyAoMiAqIHcwICogcmhvMiAqIGQxKSxcbiAgICAgICAgYjEgPSAodzEgKiB3MSAtIHcwICogdzAgLSByaG80ICogZDIpIC8gKDIgKiB3MSAqIHJobzIgKiBkMSksXG4gICAgICAgIHIwID0gTWF0aC5sb2coTWF0aC5zcXJ0KGIwICogYjAgKyAxKSAtIGIwKSxcbiAgICAgICAgcjEgPSBNYXRoLmxvZyhNYXRoLnNxcnQoYjEgKiBiMSArIDEpIC0gYjEpO1xuICAgIFMgPSAocjEgLSByMCkgLyByaG87XG4gICAgaSA9IGZ1bmN0aW9uKHQpIHtcbiAgICAgIHZhciBzID0gdCAqIFMsXG4gICAgICAgICAgY29zaHIwID0gY29zaChyMCksXG4gICAgICAgICAgdSA9IHcwIC8gKHJobzIgKiBkMSkgKiAoY29zaHIwICogdGFuaChyaG8gKiBzICsgcjApIC0gc2luaChyMCkpO1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAgdXgwICsgdSAqIGR4LFxuICAgICAgICB1eTAgKyB1ICogZHksXG4gICAgICAgIHcwICogY29zaHIwIC8gY29zaChyaG8gKiBzICsgcjApXG4gICAgICBdO1xuICAgIH07XG4gIH1cblxuICBpLmR1cmF0aW9uID0gUyAqIDEwMDA7XG5cbiAgcmV0dXJuIGk7XG59XG5cbmZ1bmN0aW9uIGhzbChodWUkJDEpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgaCA9IGh1ZSQkMSgoc3RhcnQgPSBkM0NvbG9yLmhzbChzdGFydCkpLmgsIChlbmQgPSBkM0NvbG9yLmhzbChlbmQpKS5oKSxcbiAgICAgICAgcyA9IG5vZ2FtbWEoc3RhcnQucywgZW5kLnMpLFxuICAgICAgICBsID0gbm9nYW1tYShzdGFydC5sLCBlbmQubCksXG4gICAgICAgIG9wYWNpdHkgPSBub2dhbW1hKHN0YXJ0Lm9wYWNpdHksIGVuZC5vcGFjaXR5KTtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgc3RhcnQuaCA9IGgodCk7XG4gICAgICBzdGFydC5zID0gcyh0KTtcbiAgICAgIHN0YXJ0LmwgPSBsKHQpO1xuICAgICAgc3RhcnQub3BhY2l0eSA9IG9wYWNpdHkodCk7XG4gICAgICByZXR1cm4gc3RhcnQgKyBcIlwiO1xuICAgIH07XG4gIH1cbn1cblxudmFyIGhzbCQxID0gaHNsKGh1ZSk7XG52YXIgaHNsTG9uZyA9IGhzbChub2dhbW1hKTtcblxuZnVuY3Rpb24gbGFiKHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGwgPSBub2dhbW1hKChzdGFydCA9IGQzQ29sb3IubGFiKHN0YXJ0KSkubCwgKGVuZCA9IGQzQ29sb3IubGFiKGVuZCkpLmwpLFxuICAgICAgYSA9IG5vZ2FtbWEoc3RhcnQuYSwgZW5kLmEpLFxuICAgICAgYiA9IG5vZ2FtbWEoc3RhcnQuYiwgZW5kLmIpLFxuICAgICAgb3BhY2l0eSA9IG5vZ2FtbWEoc3RhcnQub3BhY2l0eSwgZW5kLm9wYWNpdHkpO1xuICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgIHN0YXJ0LmwgPSBsKHQpO1xuICAgIHN0YXJ0LmEgPSBhKHQpO1xuICAgIHN0YXJ0LmIgPSBiKHQpO1xuICAgIHN0YXJ0Lm9wYWNpdHkgPSBvcGFjaXR5KHQpO1xuICAgIHJldHVybiBzdGFydCArIFwiXCI7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGhjbChodWUkJDEpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICB2YXIgaCA9IGh1ZSQkMSgoc3RhcnQgPSBkM0NvbG9yLmhjbChzdGFydCkpLmgsIChlbmQgPSBkM0NvbG9yLmhjbChlbmQpKS5oKSxcbiAgICAgICAgYyA9IG5vZ2FtbWEoc3RhcnQuYywgZW5kLmMpLFxuICAgICAgICBsID0gbm9nYW1tYShzdGFydC5sLCBlbmQubCksXG4gICAgICAgIG9wYWNpdHkgPSBub2dhbW1hKHN0YXJ0Lm9wYWNpdHksIGVuZC5vcGFjaXR5KTtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgc3RhcnQuaCA9IGgodCk7XG4gICAgICBzdGFydC5jID0gYyh0KTtcbiAgICAgIHN0YXJ0LmwgPSBsKHQpO1xuICAgICAgc3RhcnQub3BhY2l0eSA9IG9wYWNpdHkodCk7XG4gICAgICByZXR1cm4gc3RhcnQgKyBcIlwiO1xuICAgIH07XG4gIH1cbn1cblxudmFyIGhjbCQxID0gaGNsKGh1ZSk7XG52YXIgaGNsTG9uZyA9IGhjbChub2dhbW1hKTtcblxuZnVuY3Rpb24gY3ViZWhlbGl4KGh1ZSQkMSkge1xuICByZXR1cm4gKGZ1bmN0aW9uIGN1YmVoZWxpeEdhbW1hKHkpIHtcbiAgICB5ID0gK3k7XG5cbiAgICBmdW5jdGlvbiBjdWJlaGVsaXgoc3RhcnQsIGVuZCkge1xuICAgICAgdmFyIGggPSBodWUkJDEoKHN0YXJ0ID0gZDNDb2xvci5jdWJlaGVsaXgoc3RhcnQpKS5oLCAoZW5kID0gZDNDb2xvci5jdWJlaGVsaXgoZW5kKSkuaCksXG4gICAgICAgICAgcyA9IG5vZ2FtbWEoc3RhcnQucywgZW5kLnMpLFxuICAgICAgICAgIGwgPSBub2dhbW1hKHN0YXJ0LmwsIGVuZC5sKSxcbiAgICAgICAgICBvcGFjaXR5ID0gbm9nYW1tYShzdGFydC5vcGFjaXR5LCBlbmQub3BhY2l0eSk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgICBzdGFydC5oID0gaCh0KTtcbiAgICAgICAgc3RhcnQucyA9IHModCk7XG4gICAgICAgIHN0YXJ0LmwgPSBsKE1hdGgucG93KHQsIHkpKTtcbiAgICAgICAgc3RhcnQub3BhY2l0eSA9IG9wYWNpdHkodCk7XG4gICAgICAgIHJldHVybiBzdGFydCArIFwiXCI7XG4gICAgICB9O1xuICAgIH1cblxuICAgIGN1YmVoZWxpeC5nYW1tYSA9IGN1YmVoZWxpeEdhbW1hO1xuXG4gICAgcmV0dXJuIGN1YmVoZWxpeDtcbiAgfSkoMSk7XG59XG5cbnZhciBjdWJlaGVsaXgkMSA9IGN1YmVoZWxpeChodWUpO1xudmFyIGN1YmVoZWxpeExvbmcgPSBjdWJlaGVsaXgobm9nYW1tYSk7XG5cbmZ1bmN0aW9uIHBpZWNld2lzZShpbnRlcnBvbGF0ZSwgdmFsdWVzKSB7XG4gIHZhciBpID0gMCwgbiA9IHZhbHVlcy5sZW5ndGggLSAxLCB2ID0gdmFsdWVzWzBdLCBJID0gbmV3IEFycmF5KG4gPCAwID8gMCA6IG4pO1xuICB3aGlsZSAoaSA8IG4pIElbaV0gPSBpbnRlcnBvbGF0ZSh2LCB2ID0gdmFsdWVzWysraV0pO1xuICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgIHZhciBpID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obiAtIDEsIE1hdGguZmxvb3IodCAqPSBuKSkpO1xuICAgIHJldHVybiBJW2ldKHQgLSBpKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcXVhbnRpemUoaW50ZXJwb2xhdG9yLCBuKSB7XG4gIHZhciBzYW1wbGVzID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkgc2FtcGxlc1tpXSA9IGludGVycG9sYXRvcihpIC8gKG4gLSAxKSk7XG4gIHJldHVybiBzYW1wbGVzO1xufVxuXG5leHBvcnRzLmludGVycG9sYXRlID0gdmFsdWU7XG5leHBvcnRzLmludGVycG9sYXRlQXJyYXkgPSBhcnJheTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVCYXNpcyA9IGJhc2lzJDE7XG5leHBvcnRzLmludGVycG9sYXRlQmFzaXNDbG9zZWQgPSBiYXNpc0Nsb3NlZDtcbmV4cG9ydHMuaW50ZXJwb2xhdGVEYXRlID0gZGF0ZTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVEaXNjcmV0ZSA9IGRpc2NyZXRlO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZUh1ZSA9IGh1ZSQxO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZU51bWJlciA9IG51bWJlcjtcbmV4cG9ydHMuaW50ZXJwb2xhdGVPYmplY3QgPSBvYmplY3Q7XG5leHBvcnRzLmludGVycG9sYXRlUm91bmQgPSByb3VuZDtcbmV4cG9ydHMuaW50ZXJwb2xhdGVTdHJpbmcgPSBzdHJpbmc7XG5leHBvcnRzLmludGVycG9sYXRlVHJhbnNmb3JtQ3NzID0gaW50ZXJwb2xhdGVUcmFuc2Zvcm1Dc3M7XG5leHBvcnRzLmludGVycG9sYXRlVHJhbnNmb3JtU3ZnID0gaW50ZXJwb2xhdGVUcmFuc2Zvcm1Tdmc7XG5leHBvcnRzLmludGVycG9sYXRlWm9vbSA9IHpvb207XG5leHBvcnRzLmludGVycG9sYXRlUmdiID0gcmdiO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZVJnYkJhc2lzID0gcmdiQmFzaXM7XG5leHBvcnRzLmludGVycG9sYXRlUmdiQmFzaXNDbG9zZWQgPSByZ2JCYXNpc0Nsb3NlZDtcbmV4cG9ydHMuaW50ZXJwb2xhdGVIc2wgPSBoc2wkMTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVIc2xMb25nID0gaHNsTG9uZztcbmV4cG9ydHMuaW50ZXJwb2xhdGVMYWIgPSBsYWI7XG5leHBvcnRzLmludGVycG9sYXRlSGNsID0gaGNsJDE7XG5leHBvcnRzLmludGVycG9sYXRlSGNsTG9uZyA9IGhjbExvbmc7XG5leHBvcnRzLmludGVycG9sYXRlQ3ViZWhlbGl4ID0gY3ViZWhlbGl4JDE7XG5leHBvcnRzLmludGVycG9sYXRlQ3ViZWhlbGl4TG9uZyA9IGN1YmVoZWxpeExvbmc7XG5leHBvcnRzLnBpZWNld2lzZSA9IHBpZWNld2lzZTtcbmV4cG9ydHMucXVhbnRpemUgPSBxdWFudGl6ZTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcblxufSx7XCJkMy1jb2xvclwiOjE1NH1dLDE1OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBodHRwczovL2QzanMub3JnL2QzLXBhdGgvIHYxLjAuNyBDb3B5cmlnaHQgMjAxOCBNaWtlIEJvc3RvY2tcbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG50eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcbnR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuKGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIHBpID0gTWF0aC5QSSxcbiAgICB0YXUgPSAyICogcGksXG4gICAgZXBzaWxvbiA9IDFlLTYsXG4gICAgdGF1RXBzaWxvbiA9IHRhdSAtIGVwc2lsb247XG5cbmZ1bmN0aW9uIFBhdGgoKSB7XG4gIHRoaXMuX3gwID0gdGhpcy5feTAgPSAvLyBzdGFydCBvZiBjdXJyZW50IHN1YnBhdGhcbiAgdGhpcy5feDEgPSB0aGlzLl95MSA9IG51bGw7IC8vIGVuZCBvZiBjdXJyZW50IHN1YnBhdGhcbiAgdGhpcy5fID0gXCJcIjtcbn1cblxuZnVuY3Rpb24gcGF0aCgpIHtcbiAgcmV0dXJuIG5ldyBQYXRoO1xufVxuXG5QYXRoLnByb3RvdHlwZSA9IHBhdGgucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogUGF0aCxcbiAgbW92ZVRvOiBmdW5jdGlvbih4LCB5KSB7XG4gICAgdGhpcy5fICs9IFwiTVwiICsgKHRoaXMuX3gwID0gdGhpcy5feDEgPSAreCkgKyBcIixcIiArICh0aGlzLl95MCA9IHRoaXMuX3kxID0gK3kpO1xuICB9LFxuICBjbG9zZVBhdGg6IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLl94MSAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5feDEgPSB0aGlzLl94MCwgdGhpcy5feTEgPSB0aGlzLl95MDtcbiAgICAgIHRoaXMuXyArPSBcIlpcIjtcbiAgICB9XG4gIH0sXG4gIGxpbmVUbzogZnVuY3Rpb24oeCwgeSkge1xuICAgIHRoaXMuXyArPSBcIkxcIiArICh0aGlzLl94MSA9ICt4KSArIFwiLFwiICsgKHRoaXMuX3kxID0gK3kpO1xuICB9LFxuICBxdWFkcmF0aWNDdXJ2ZVRvOiBmdW5jdGlvbih4MSwgeTEsIHgsIHkpIHtcbiAgICB0aGlzLl8gKz0gXCJRXCIgKyAoK3gxKSArIFwiLFwiICsgKCt5MSkgKyBcIixcIiArICh0aGlzLl94MSA9ICt4KSArIFwiLFwiICsgKHRoaXMuX3kxID0gK3kpO1xuICB9LFxuICBiZXppZXJDdXJ2ZVRvOiBmdW5jdGlvbih4MSwgeTEsIHgyLCB5MiwgeCwgeSkge1xuICAgIHRoaXMuXyArPSBcIkNcIiArICgreDEpICsgXCIsXCIgKyAoK3kxKSArIFwiLFwiICsgKCt4MikgKyBcIixcIiArICgreTIpICsgXCIsXCIgKyAodGhpcy5feDEgPSAreCkgKyBcIixcIiArICh0aGlzLl95MSA9ICt5KTtcbiAgfSxcbiAgYXJjVG86IGZ1bmN0aW9uKHgxLCB5MSwgeDIsIHkyLCByKSB7XG4gICAgeDEgPSAreDEsIHkxID0gK3kxLCB4MiA9ICt4MiwgeTIgPSAreTIsIHIgPSArcjtcbiAgICB2YXIgeDAgPSB0aGlzLl94MSxcbiAgICAgICAgeTAgPSB0aGlzLl95MSxcbiAgICAgICAgeDIxID0geDIgLSB4MSxcbiAgICAgICAgeTIxID0geTIgLSB5MSxcbiAgICAgICAgeDAxID0geDAgLSB4MSxcbiAgICAgICAgeTAxID0geTAgLSB5MSxcbiAgICAgICAgbDAxXzIgPSB4MDEgKiB4MDEgKyB5MDEgKiB5MDE7XG5cbiAgICAvLyBJcyB0aGUgcmFkaXVzIG5lZ2F0aXZlPyBFcnJvci5cbiAgICBpZiAociA8IDApIHRocm93IG5ldyBFcnJvcihcIm5lZ2F0aXZlIHJhZGl1czogXCIgKyByKTtcblxuICAgIC8vIElzIHRoaXMgcGF0aCBlbXB0eT8gTW92ZSB0byAoeDEseTEpLlxuICAgIGlmICh0aGlzLl94MSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5fICs9IFwiTVwiICsgKHRoaXMuX3gxID0geDEpICsgXCIsXCIgKyAodGhpcy5feTEgPSB5MSk7XG4gICAgfVxuXG4gICAgLy8gT3IsIGlzICh4MSx5MSkgY29pbmNpZGVudCB3aXRoICh4MCx5MCk/IERvIG5vdGhpbmcuXG4gICAgZWxzZSBpZiAoIShsMDFfMiA+IGVwc2lsb24pKTtcblxuICAgIC8vIE9yLCBhcmUgKHgwLHkwKSwgKHgxLHkxKSBhbmQgKHgyLHkyKSBjb2xsaW5lYXI/XG4gICAgLy8gRXF1aXZhbGVudGx5LCBpcyAoeDEseTEpIGNvaW5jaWRlbnQgd2l0aCAoeDIseTIpP1xuICAgIC8vIE9yLCBpcyB0aGUgcmFkaXVzIHplcm8/IExpbmUgdG8gKHgxLHkxKS5cbiAgICBlbHNlIGlmICghKE1hdGguYWJzKHkwMSAqIHgyMSAtIHkyMSAqIHgwMSkgPiBlcHNpbG9uKSB8fCAhcikge1xuICAgICAgdGhpcy5fICs9IFwiTFwiICsgKHRoaXMuX3gxID0geDEpICsgXCIsXCIgKyAodGhpcy5feTEgPSB5MSk7XG4gICAgfVxuXG4gICAgLy8gT3RoZXJ3aXNlLCBkcmF3IGFuIGFyYyFcbiAgICBlbHNlIHtcbiAgICAgIHZhciB4MjAgPSB4MiAtIHgwLFxuICAgICAgICAgIHkyMCA9IHkyIC0geTAsXG4gICAgICAgICAgbDIxXzIgPSB4MjEgKiB4MjEgKyB5MjEgKiB5MjEsXG4gICAgICAgICAgbDIwXzIgPSB4MjAgKiB4MjAgKyB5MjAgKiB5MjAsXG4gICAgICAgICAgbDIxID0gTWF0aC5zcXJ0KGwyMV8yKSxcbiAgICAgICAgICBsMDEgPSBNYXRoLnNxcnQobDAxXzIpLFxuICAgICAgICAgIGwgPSByICogTWF0aC50YW4oKHBpIC0gTWF0aC5hY29zKChsMjFfMiArIGwwMV8yIC0gbDIwXzIpIC8gKDIgKiBsMjEgKiBsMDEpKSkgLyAyKSxcbiAgICAgICAgICB0MDEgPSBsIC8gbDAxLFxuICAgICAgICAgIHQyMSA9IGwgLyBsMjE7XG5cbiAgICAgIC8vIElmIHRoZSBzdGFydCB0YW5nZW50IGlzIG5vdCBjb2luY2lkZW50IHdpdGggKHgwLHkwKSwgbGluZSB0by5cbiAgICAgIGlmIChNYXRoLmFicyh0MDEgLSAxKSA+IGVwc2lsb24pIHtcbiAgICAgICAgdGhpcy5fICs9IFwiTFwiICsgKHgxICsgdDAxICogeDAxKSArIFwiLFwiICsgKHkxICsgdDAxICogeTAxKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fICs9IFwiQVwiICsgciArIFwiLFwiICsgciArIFwiLDAsMCxcIiArICgrKHkwMSAqIHgyMCA+IHgwMSAqIHkyMCkpICsgXCIsXCIgKyAodGhpcy5feDEgPSB4MSArIHQyMSAqIHgyMSkgKyBcIixcIiArICh0aGlzLl95MSA9IHkxICsgdDIxICogeTIxKTtcbiAgICB9XG4gIH0sXG4gIGFyYzogZnVuY3Rpb24oeCwgeSwgciwgYTAsIGExLCBjY3cpIHtcbiAgICB4ID0gK3gsIHkgPSAreSwgciA9ICtyO1xuICAgIHZhciBkeCA9IHIgKiBNYXRoLmNvcyhhMCksXG4gICAgICAgIGR5ID0gciAqIE1hdGguc2luKGEwKSxcbiAgICAgICAgeDAgPSB4ICsgZHgsXG4gICAgICAgIHkwID0geSArIGR5LFxuICAgICAgICBjdyA9IDEgXiBjY3csXG4gICAgICAgIGRhID0gY2N3ID8gYTAgLSBhMSA6IGExIC0gYTA7XG5cbiAgICAvLyBJcyB0aGUgcmFkaXVzIG5lZ2F0aXZlPyBFcnJvci5cbiAgICBpZiAociA8IDApIHRocm93IG5ldyBFcnJvcihcIm5lZ2F0aXZlIHJhZGl1czogXCIgKyByKTtcblxuICAgIC8vIElzIHRoaXMgcGF0aCBlbXB0eT8gTW92ZSB0byAoeDAseTApLlxuICAgIGlmICh0aGlzLl94MSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5fICs9IFwiTVwiICsgeDAgKyBcIixcIiArIHkwO1xuICAgIH1cblxuICAgIC8vIE9yLCBpcyAoeDAseTApIG5vdCBjb2luY2lkZW50IHdpdGggdGhlIHByZXZpb3VzIHBvaW50PyBMaW5lIHRvICh4MCx5MCkuXG4gICAgZWxzZSBpZiAoTWF0aC5hYnModGhpcy5feDEgLSB4MCkgPiBlcHNpbG9uIHx8IE1hdGguYWJzKHRoaXMuX3kxIC0geTApID4gZXBzaWxvbikge1xuICAgICAgdGhpcy5fICs9IFwiTFwiICsgeDAgKyBcIixcIiArIHkwO1xuICAgIH1cblxuICAgIC8vIElzIHRoaXMgYXJjIGVtcHR5PyBXZeKAmXJlIGRvbmUuXG4gICAgaWYgKCFyKSByZXR1cm47XG5cbiAgICAvLyBEb2VzIHRoZSBhbmdsZSBnbyB0aGUgd3Jvbmcgd2F5PyBGbGlwIHRoZSBkaXJlY3Rpb24uXG4gICAgaWYgKGRhIDwgMCkgZGEgPSBkYSAlIHRhdSArIHRhdTtcblxuICAgIC8vIElzIHRoaXMgYSBjb21wbGV0ZSBjaXJjbGU/IERyYXcgdHdvIGFyY3MgdG8gY29tcGxldGUgdGhlIGNpcmNsZS5cbiAgICBpZiAoZGEgPiB0YXVFcHNpbG9uKSB7XG4gICAgICB0aGlzLl8gKz0gXCJBXCIgKyByICsgXCIsXCIgKyByICsgXCIsMCwxLFwiICsgY3cgKyBcIixcIiArICh4IC0gZHgpICsgXCIsXCIgKyAoeSAtIGR5KSArIFwiQVwiICsgciArIFwiLFwiICsgciArIFwiLDAsMSxcIiArIGN3ICsgXCIsXCIgKyAodGhpcy5feDEgPSB4MCkgKyBcIixcIiArICh0aGlzLl95MSA9IHkwKTtcbiAgICB9XG5cbiAgICAvLyBJcyB0aGlzIGFyYyBub24tZW1wdHk/IERyYXcgYW4gYXJjIVxuICAgIGVsc2UgaWYgKGRhID4gZXBzaWxvbikge1xuICAgICAgdGhpcy5fICs9IFwiQVwiICsgciArIFwiLFwiICsgciArIFwiLDAsXCIgKyAoKyhkYSA+PSBwaSkpICsgXCIsXCIgKyBjdyArIFwiLFwiICsgKHRoaXMuX3gxID0geCArIHIgKiBNYXRoLmNvcyhhMSkpICsgXCIsXCIgKyAodGhpcy5feTEgPSB5ICsgciAqIE1hdGguc2luKGExKSk7XG4gICAgfVxuICB9LFxuICByZWN0OiBmdW5jdGlvbih4LCB5LCB3LCBoKSB7XG4gICAgdGhpcy5fICs9IFwiTVwiICsgKHRoaXMuX3gwID0gdGhpcy5feDEgPSAreCkgKyBcIixcIiArICh0aGlzLl95MCA9IHRoaXMuX3kxID0gK3kpICsgXCJoXCIgKyAoK3cpICsgXCJ2XCIgKyAoK2gpICsgXCJoXCIgKyAoLXcpICsgXCJaXCI7XG4gIH0sXG4gIHRvU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fO1xuICB9XG59O1xuXG5leHBvcnRzLnBhdGggPSBwYXRoO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuXG59LHt9XSwxNjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1xdWFkdHJlZS8gVmVyc2lvbiAxLjAuMy4gQ29weXJpZ2h0IDIwMTcgTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG52YXIgdHJlZV9hZGQgPSBmdW5jdGlvbihkKSB7XG4gIHZhciB4ID0gK3RoaXMuX3guY2FsbChudWxsLCBkKSxcbiAgICAgIHkgPSArdGhpcy5feS5jYWxsKG51bGwsIGQpO1xuICByZXR1cm4gYWRkKHRoaXMuY292ZXIoeCwgeSksIHgsIHksIGQpO1xufTtcblxuZnVuY3Rpb24gYWRkKHRyZWUsIHgsIHksIGQpIHtcbiAgaWYgKGlzTmFOKHgpIHx8IGlzTmFOKHkpKSByZXR1cm4gdHJlZTsgLy8gaWdub3JlIGludmFsaWQgcG9pbnRzXG5cbiAgdmFyIHBhcmVudCxcbiAgICAgIG5vZGUgPSB0cmVlLl9yb290LFxuICAgICAgbGVhZiA9IHtkYXRhOiBkfSxcbiAgICAgIHgwID0gdHJlZS5feDAsXG4gICAgICB5MCA9IHRyZWUuX3kwLFxuICAgICAgeDEgPSB0cmVlLl94MSxcbiAgICAgIHkxID0gdHJlZS5feTEsXG4gICAgICB4bSxcbiAgICAgIHltLFxuICAgICAgeHAsXG4gICAgICB5cCxcbiAgICAgIHJpZ2h0LFxuICAgICAgYm90dG9tLFxuICAgICAgaSxcbiAgICAgIGo7XG5cbiAgLy8gSWYgdGhlIHRyZWUgaXMgZW1wdHksIGluaXRpYWxpemUgdGhlIHJvb3QgYXMgYSBsZWFmLlxuICBpZiAoIW5vZGUpIHJldHVybiB0cmVlLl9yb290ID0gbGVhZiwgdHJlZTtcblxuICAvLyBGaW5kIHRoZSBleGlzdGluZyBsZWFmIGZvciB0aGUgbmV3IHBvaW50LCBvciBhZGQgaXQuXG4gIHdoaWxlIChub2RlLmxlbmd0aCkge1xuICAgIGlmIChyaWdodCA9IHggPj0gKHhtID0gKHgwICsgeDEpIC8gMikpIHgwID0geG07IGVsc2UgeDEgPSB4bTtcbiAgICBpZiAoYm90dG9tID0geSA+PSAoeW0gPSAoeTAgKyB5MSkgLyAyKSkgeTAgPSB5bTsgZWxzZSB5MSA9IHltO1xuICAgIGlmIChwYXJlbnQgPSBub2RlLCAhKG5vZGUgPSBub2RlW2kgPSBib3R0b20gPDwgMSB8IHJpZ2h0XSkpIHJldHVybiBwYXJlbnRbaV0gPSBsZWFmLCB0cmVlO1xuICB9XG5cbiAgLy8gSXMgdGhlIG5ldyBwb2ludCBpcyBleGFjdGx5IGNvaW5jaWRlbnQgd2l0aCB0aGUgZXhpc3RpbmcgcG9pbnQ/XG4gIHhwID0gK3RyZWUuX3guY2FsbChudWxsLCBub2RlLmRhdGEpO1xuICB5cCA9ICt0cmVlLl95LmNhbGwobnVsbCwgbm9kZS5kYXRhKTtcbiAgaWYgKHggPT09IHhwICYmIHkgPT09IHlwKSByZXR1cm4gbGVhZi5uZXh0ID0gbm9kZSwgcGFyZW50ID8gcGFyZW50W2ldID0gbGVhZiA6IHRyZWUuX3Jvb3QgPSBsZWFmLCB0cmVlO1xuXG4gIC8vIE90aGVyd2lzZSwgc3BsaXQgdGhlIGxlYWYgbm9kZSB1bnRpbCB0aGUgb2xkIGFuZCBuZXcgcG9pbnQgYXJlIHNlcGFyYXRlZC5cbiAgZG8ge1xuICAgIHBhcmVudCA9IHBhcmVudCA/IHBhcmVudFtpXSA9IG5ldyBBcnJheSg0KSA6IHRyZWUuX3Jvb3QgPSBuZXcgQXJyYXkoNCk7XG4gICAgaWYgKHJpZ2h0ID0geCA+PSAoeG0gPSAoeDAgKyB4MSkgLyAyKSkgeDAgPSB4bTsgZWxzZSB4MSA9IHhtO1xuICAgIGlmIChib3R0b20gPSB5ID49ICh5bSA9ICh5MCArIHkxKSAvIDIpKSB5MCA9IHltOyBlbHNlIHkxID0geW07XG4gIH0gd2hpbGUgKChpID0gYm90dG9tIDw8IDEgfCByaWdodCkgPT09IChqID0gKHlwID49IHltKSA8PCAxIHwgKHhwID49IHhtKSkpO1xuICByZXR1cm4gcGFyZW50W2pdID0gbm9kZSwgcGFyZW50W2ldID0gbGVhZiwgdHJlZTtcbn1cblxuZnVuY3Rpb24gYWRkQWxsKGRhdGEpIHtcbiAgdmFyIGQsIGksIG4gPSBkYXRhLmxlbmd0aCxcbiAgICAgIHgsXG4gICAgICB5LFxuICAgICAgeHogPSBuZXcgQXJyYXkobiksXG4gICAgICB5eiA9IG5ldyBBcnJheShuKSxcbiAgICAgIHgwID0gSW5maW5pdHksXG4gICAgICB5MCA9IEluZmluaXR5LFxuICAgICAgeDEgPSAtSW5maW5pdHksXG4gICAgICB5MSA9IC1JbmZpbml0eTtcblxuICAvLyBDb21wdXRlIHRoZSBwb2ludHMgYW5kIHRoZWlyIGV4dGVudC5cbiAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgIGlmIChpc05hTih4ID0gK3RoaXMuX3guY2FsbChudWxsLCBkID0gZGF0YVtpXSkpIHx8IGlzTmFOKHkgPSArdGhpcy5feS5jYWxsKG51bGwsIGQpKSkgY29udGludWU7XG4gICAgeHpbaV0gPSB4O1xuICAgIHl6W2ldID0geTtcbiAgICBpZiAoeCA8IHgwKSB4MCA9IHg7XG4gICAgaWYgKHggPiB4MSkgeDEgPSB4O1xuICAgIGlmICh5IDwgeTApIHkwID0geTtcbiAgICBpZiAoeSA+IHkxKSB5MSA9IHk7XG4gIH1cblxuICAvLyBJZiB0aGVyZSB3ZXJlIG5vICh2YWxpZCkgcG9pbnRzLCBpbmhlcml0IHRoZSBleGlzdGluZyBleHRlbnQuXG4gIGlmICh4MSA8IHgwKSB4MCA9IHRoaXMuX3gwLCB4MSA9IHRoaXMuX3gxO1xuICBpZiAoeTEgPCB5MCkgeTAgPSB0aGlzLl95MCwgeTEgPSB0aGlzLl95MTtcblxuICAvLyBFeHBhbmQgdGhlIHRyZWUgdG8gY292ZXIgdGhlIG5ldyBwb2ludHMuXG4gIHRoaXMuY292ZXIoeDAsIHkwKS5jb3Zlcih4MSwgeTEpO1xuXG4gIC8vIEFkZCB0aGUgbmV3IHBvaW50cy5cbiAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgIGFkZCh0aGlzLCB4eltpXSwgeXpbaV0sIGRhdGFbaV0pO1xuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59XG5cbnZhciB0cmVlX2NvdmVyID0gZnVuY3Rpb24oeCwgeSkge1xuICBpZiAoaXNOYU4oeCA9ICt4KSB8fCBpc05hTih5ID0gK3kpKSByZXR1cm4gdGhpczsgLy8gaWdub3JlIGludmFsaWQgcG9pbnRzXG5cbiAgdmFyIHgwID0gdGhpcy5feDAsXG4gICAgICB5MCA9IHRoaXMuX3kwLFxuICAgICAgeDEgPSB0aGlzLl94MSxcbiAgICAgIHkxID0gdGhpcy5feTE7XG5cbiAgLy8gSWYgdGhlIHF1YWR0cmVlIGhhcyBubyBleHRlbnQsIGluaXRpYWxpemUgdGhlbS5cbiAgLy8gSW50ZWdlciBleHRlbnQgYXJlIG5lY2Vzc2FyeSBzbyB0aGF0IGlmIHdlIGxhdGVyIGRvdWJsZSB0aGUgZXh0ZW50LFxuICAvLyB0aGUgZXhpc3RpbmcgcXVhZHJhbnQgYm91bmRhcmllcyBkb27igJl0IGNoYW5nZSBkdWUgdG8gZmxvYXRpbmcgcG9pbnQgZXJyb3IhXG4gIGlmIChpc05hTih4MCkpIHtcbiAgICB4MSA9ICh4MCA9IE1hdGguZmxvb3IoeCkpICsgMTtcbiAgICB5MSA9ICh5MCA9IE1hdGguZmxvb3IoeSkpICsgMTtcbiAgfVxuXG4gIC8vIE90aGVyd2lzZSwgZG91YmxlIHJlcGVhdGVkbHkgdG8gY292ZXIuXG4gIGVsc2UgaWYgKHgwID4geCB8fCB4ID4geDEgfHwgeTAgPiB5IHx8IHkgPiB5MSkge1xuICAgIHZhciB6ID0geDEgLSB4MCxcbiAgICAgICAgbm9kZSA9IHRoaXMuX3Jvb3QsXG4gICAgICAgIHBhcmVudCxcbiAgICAgICAgaTtcblxuICAgIHN3aXRjaCAoaSA9ICh5IDwgKHkwICsgeTEpIC8gMikgPDwgMSB8ICh4IDwgKHgwICsgeDEpIC8gMikpIHtcbiAgICAgIGNhc2UgMDoge1xuICAgICAgICBkbyBwYXJlbnQgPSBuZXcgQXJyYXkoNCksIHBhcmVudFtpXSA9IG5vZGUsIG5vZGUgPSBwYXJlbnQ7XG4gICAgICAgIHdoaWxlICh6ICo9IDIsIHgxID0geDAgKyB6LCB5MSA9IHkwICsgeiwgeCA+IHgxIHx8IHkgPiB5MSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAxOiB7XG4gICAgICAgIGRvIHBhcmVudCA9IG5ldyBBcnJheSg0KSwgcGFyZW50W2ldID0gbm9kZSwgbm9kZSA9IHBhcmVudDtcbiAgICAgICAgd2hpbGUgKHogKj0gMiwgeDAgPSB4MSAtIHosIHkxID0geTAgKyB6LCB4MCA+IHggfHwgeSA+IHkxKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIDI6IHtcbiAgICAgICAgZG8gcGFyZW50ID0gbmV3IEFycmF5KDQpLCBwYXJlbnRbaV0gPSBub2RlLCBub2RlID0gcGFyZW50O1xuICAgICAgICB3aGlsZSAoeiAqPSAyLCB4MSA9IHgwICsgeiwgeTAgPSB5MSAtIHosIHggPiB4MSB8fCB5MCA+IHkpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgMzoge1xuICAgICAgICBkbyBwYXJlbnQgPSBuZXcgQXJyYXkoNCksIHBhcmVudFtpXSA9IG5vZGUsIG5vZGUgPSBwYXJlbnQ7XG4gICAgICAgIHdoaWxlICh6ICo9IDIsIHgwID0geDEgLSB6LCB5MCA9IHkxIC0geiwgeDAgPiB4IHx8IHkwID4geSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLl9yb290ICYmIHRoaXMuX3Jvb3QubGVuZ3RoKSB0aGlzLl9yb290ID0gbm9kZTtcbiAgfVxuXG4gIC8vIElmIHRoZSBxdWFkdHJlZSBjb3ZlcnMgdGhlIHBvaW50IGFscmVhZHksIGp1c3QgcmV0dXJuLlxuICBlbHNlIHJldHVybiB0aGlzO1xuXG4gIHRoaXMuX3gwID0geDA7XG4gIHRoaXMuX3kwID0geTA7XG4gIHRoaXMuX3gxID0geDE7XG4gIHRoaXMuX3kxID0geTE7XG4gIHJldHVybiB0aGlzO1xufTtcblxudmFyIHRyZWVfZGF0YSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgZGF0YSA9IFtdO1xuICB0aGlzLnZpc2l0KGZ1bmN0aW9uKG5vZGUpIHtcbiAgICBpZiAoIW5vZGUubGVuZ3RoKSBkbyBkYXRhLnB1c2gobm9kZS5kYXRhKTsgd2hpbGUgKG5vZGUgPSBub2RlLm5leHQpXG4gIH0pO1xuICByZXR1cm4gZGF0YTtcbn07XG5cbnZhciB0cmVlX2V4dGVudCA9IGZ1bmN0aW9uKF8pIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGhcbiAgICAgID8gdGhpcy5jb3ZlcigrX1swXVswXSwgK19bMF1bMV0pLmNvdmVyKCtfWzFdWzBdLCArX1sxXVsxXSlcbiAgICAgIDogaXNOYU4odGhpcy5feDApID8gdW5kZWZpbmVkIDogW1t0aGlzLl94MCwgdGhpcy5feTBdLCBbdGhpcy5feDEsIHRoaXMuX3kxXV07XG59O1xuXG52YXIgUXVhZCA9IGZ1bmN0aW9uKG5vZGUsIHgwLCB5MCwgeDEsIHkxKSB7XG4gIHRoaXMubm9kZSA9IG5vZGU7XG4gIHRoaXMueDAgPSB4MDtcbiAgdGhpcy55MCA9IHkwO1xuICB0aGlzLngxID0geDE7XG4gIHRoaXMueTEgPSB5MTtcbn07XG5cbnZhciB0cmVlX2ZpbmQgPSBmdW5jdGlvbih4LCB5LCByYWRpdXMpIHtcbiAgdmFyIGRhdGEsXG4gICAgICB4MCA9IHRoaXMuX3gwLFxuICAgICAgeTAgPSB0aGlzLl95MCxcbiAgICAgIHgxLFxuICAgICAgeTEsXG4gICAgICB4MixcbiAgICAgIHkyLFxuICAgICAgeDMgPSB0aGlzLl94MSxcbiAgICAgIHkzID0gdGhpcy5feTEsXG4gICAgICBxdWFkcyA9IFtdLFxuICAgICAgbm9kZSA9IHRoaXMuX3Jvb3QsXG4gICAgICBxLFxuICAgICAgaTtcblxuICBpZiAobm9kZSkgcXVhZHMucHVzaChuZXcgUXVhZChub2RlLCB4MCwgeTAsIHgzLCB5MykpO1xuICBpZiAocmFkaXVzID09IG51bGwpIHJhZGl1cyA9IEluZmluaXR5O1xuICBlbHNlIHtcbiAgICB4MCA9IHggLSByYWRpdXMsIHkwID0geSAtIHJhZGl1cztcbiAgICB4MyA9IHggKyByYWRpdXMsIHkzID0geSArIHJhZGl1cztcbiAgICByYWRpdXMgKj0gcmFkaXVzO1xuICB9XG5cbiAgd2hpbGUgKHEgPSBxdWFkcy5wb3AoKSkge1xuXG4gICAgLy8gU3RvcCBzZWFyY2hpbmcgaWYgdGhpcyBxdWFkcmFudCBjYW7igJl0IGNvbnRhaW4gYSBjbG9zZXIgbm9kZS5cbiAgICBpZiAoIShub2RlID0gcS5ub2RlKVxuICAgICAgICB8fCAoeDEgPSBxLngwKSA+IHgzXG4gICAgICAgIHx8ICh5MSA9IHEueTApID4geTNcbiAgICAgICAgfHwgKHgyID0gcS54MSkgPCB4MFxuICAgICAgICB8fCAoeTIgPSBxLnkxKSA8IHkwKSBjb250aW51ZTtcblxuICAgIC8vIEJpc2VjdCB0aGUgY3VycmVudCBxdWFkcmFudC5cbiAgICBpZiAobm9kZS5sZW5ndGgpIHtcbiAgICAgIHZhciB4bSA9ICh4MSArIHgyKSAvIDIsXG4gICAgICAgICAgeW0gPSAoeTEgKyB5MikgLyAyO1xuXG4gICAgICBxdWFkcy5wdXNoKFxuICAgICAgICBuZXcgUXVhZChub2RlWzNdLCB4bSwgeW0sIHgyLCB5MiksXG4gICAgICAgIG5ldyBRdWFkKG5vZGVbMl0sIHgxLCB5bSwgeG0sIHkyKSxcbiAgICAgICAgbmV3IFF1YWQobm9kZVsxXSwgeG0sIHkxLCB4MiwgeW0pLFxuICAgICAgICBuZXcgUXVhZChub2RlWzBdLCB4MSwgeTEsIHhtLCB5bSlcbiAgICAgICk7XG5cbiAgICAgIC8vIFZpc2l0IHRoZSBjbG9zZXN0IHF1YWRyYW50IGZpcnN0LlxuICAgICAgaWYgKGkgPSAoeSA+PSB5bSkgPDwgMSB8ICh4ID49IHhtKSkge1xuICAgICAgICBxID0gcXVhZHNbcXVhZHMubGVuZ3RoIC0gMV07XG4gICAgICAgIHF1YWRzW3F1YWRzLmxlbmd0aCAtIDFdID0gcXVhZHNbcXVhZHMubGVuZ3RoIC0gMSAtIGldO1xuICAgICAgICBxdWFkc1txdWFkcy5sZW5ndGggLSAxIC0gaV0gPSBxO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFZpc2l0IHRoaXMgcG9pbnQuIChWaXNpdGluZyBjb2luY2lkZW50IHBvaW50cyBpc27igJl0IG5lY2Vzc2FyeSEpXG4gICAgZWxzZSB7XG4gICAgICB2YXIgZHggPSB4IC0gK3RoaXMuX3guY2FsbChudWxsLCBub2RlLmRhdGEpLFxuICAgICAgICAgIGR5ID0geSAtICt0aGlzLl95LmNhbGwobnVsbCwgbm9kZS5kYXRhKSxcbiAgICAgICAgICBkMiA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgaWYgKGQyIDwgcmFkaXVzKSB7XG4gICAgICAgIHZhciBkID0gTWF0aC5zcXJ0KHJhZGl1cyA9IGQyKTtcbiAgICAgICAgeDAgPSB4IC0gZCwgeTAgPSB5IC0gZDtcbiAgICAgICAgeDMgPSB4ICsgZCwgeTMgPSB5ICsgZDtcbiAgICAgICAgZGF0YSA9IG5vZGUuZGF0YTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gZGF0YTtcbn07XG5cbnZhciB0cmVlX3JlbW92ZSA9IGZ1bmN0aW9uKGQpIHtcbiAgaWYgKGlzTmFOKHggPSArdGhpcy5feC5jYWxsKG51bGwsIGQpKSB8fCBpc05hTih5ID0gK3RoaXMuX3kuY2FsbChudWxsLCBkKSkpIHJldHVybiB0aGlzOyAvLyBpZ25vcmUgaW52YWxpZCBwb2ludHNcblxuICB2YXIgcGFyZW50LFxuICAgICAgbm9kZSA9IHRoaXMuX3Jvb3QsXG4gICAgICByZXRhaW5lcixcbiAgICAgIHByZXZpb3VzLFxuICAgICAgbmV4dCxcbiAgICAgIHgwID0gdGhpcy5feDAsXG4gICAgICB5MCA9IHRoaXMuX3kwLFxuICAgICAgeDEgPSB0aGlzLl94MSxcbiAgICAgIHkxID0gdGhpcy5feTEsXG4gICAgICB4LFxuICAgICAgeSxcbiAgICAgIHhtLFxuICAgICAgeW0sXG4gICAgICByaWdodCxcbiAgICAgIGJvdHRvbSxcbiAgICAgIGksXG4gICAgICBqO1xuXG4gIC8vIElmIHRoZSB0cmVlIGlzIGVtcHR5LCBpbml0aWFsaXplIHRoZSByb290IGFzIGEgbGVhZi5cbiAgaWYgKCFub2RlKSByZXR1cm4gdGhpcztcblxuICAvLyBGaW5kIHRoZSBsZWFmIG5vZGUgZm9yIHRoZSBwb2ludC5cbiAgLy8gV2hpbGUgZGVzY2VuZGluZywgYWxzbyByZXRhaW4gdGhlIGRlZXBlc3QgcGFyZW50IHdpdGggYSBub24tcmVtb3ZlZCBzaWJsaW5nLlxuICBpZiAobm9kZS5sZW5ndGgpIHdoaWxlICh0cnVlKSB7XG4gICAgaWYgKHJpZ2h0ID0geCA+PSAoeG0gPSAoeDAgKyB4MSkgLyAyKSkgeDAgPSB4bTsgZWxzZSB4MSA9IHhtO1xuICAgIGlmIChib3R0b20gPSB5ID49ICh5bSA9ICh5MCArIHkxKSAvIDIpKSB5MCA9IHltOyBlbHNlIHkxID0geW07XG4gICAgaWYgKCEocGFyZW50ID0gbm9kZSwgbm9kZSA9IG5vZGVbaSA9IGJvdHRvbSA8PCAxIHwgcmlnaHRdKSkgcmV0dXJuIHRoaXM7XG4gICAgaWYgKCFub2RlLmxlbmd0aCkgYnJlYWs7XG4gICAgaWYgKHBhcmVudFsoaSArIDEpICYgM10gfHwgcGFyZW50WyhpICsgMikgJiAzXSB8fCBwYXJlbnRbKGkgKyAzKSAmIDNdKSByZXRhaW5lciA9IHBhcmVudCwgaiA9IGk7XG4gIH1cblxuICAvLyBGaW5kIHRoZSBwb2ludCB0byByZW1vdmUuXG4gIHdoaWxlIChub2RlLmRhdGEgIT09IGQpIGlmICghKHByZXZpb3VzID0gbm9kZSwgbm9kZSA9IG5vZGUubmV4dCkpIHJldHVybiB0aGlzO1xuICBpZiAobmV4dCA9IG5vZGUubmV4dCkgZGVsZXRlIG5vZGUubmV4dDtcblxuICAvLyBJZiB0aGVyZSBhcmUgbXVsdGlwbGUgY29pbmNpZGVudCBwb2ludHMsIHJlbW92ZSBqdXN0IHRoZSBwb2ludC5cbiAgaWYgKHByZXZpb3VzKSByZXR1cm4gKG5leHQgPyBwcmV2aW91cy5uZXh0ID0gbmV4dCA6IGRlbGV0ZSBwcmV2aW91cy5uZXh0KSwgdGhpcztcblxuICAvLyBJZiB0aGlzIGlzIHRoZSByb290IHBvaW50LCByZW1vdmUgaXQuXG4gIGlmICghcGFyZW50KSByZXR1cm4gdGhpcy5fcm9vdCA9IG5leHQsIHRoaXM7XG5cbiAgLy8gUmVtb3ZlIHRoaXMgbGVhZi5cbiAgbmV4dCA/IHBhcmVudFtpXSA9IG5leHQgOiBkZWxldGUgcGFyZW50W2ldO1xuXG4gIC8vIElmIHRoZSBwYXJlbnQgbm93IGNvbnRhaW5zIGV4YWN0bHkgb25lIGxlYWYsIGNvbGxhcHNlIHN1cGVyZmx1b3VzIHBhcmVudHMuXG4gIGlmICgobm9kZSA9IHBhcmVudFswXSB8fCBwYXJlbnRbMV0gfHwgcGFyZW50WzJdIHx8IHBhcmVudFszXSlcbiAgICAgICYmIG5vZGUgPT09IChwYXJlbnRbM10gfHwgcGFyZW50WzJdIHx8IHBhcmVudFsxXSB8fCBwYXJlbnRbMF0pXG4gICAgICAmJiAhbm9kZS5sZW5ndGgpIHtcbiAgICBpZiAocmV0YWluZXIpIHJldGFpbmVyW2pdID0gbm9kZTtcbiAgICBlbHNlIHRoaXMuX3Jvb3QgPSBub2RlO1xuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5mdW5jdGlvbiByZW1vdmVBbGwoZGF0YSkge1xuICBmb3IgKHZhciBpID0gMCwgbiA9IGRhdGEubGVuZ3RoOyBpIDwgbjsgKytpKSB0aGlzLnJlbW92ZShkYXRhW2ldKTtcbiAgcmV0dXJuIHRoaXM7XG59XG5cbnZhciB0cmVlX3Jvb3QgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuX3Jvb3Q7XG59O1xuXG52YXIgdHJlZV9zaXplID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzaXplID0gMDtcbiAgdGhpcy52aXNpdChmdW5jdGlvbihub2RlKSB7XG4gICAgaWYgKCFub2RlLmxlbmd0aCkgZG8gKytzaXplOyB3aGlsZSAobm9kZSA9IG5vZGUubmV4dClcbiAgfSk7XG4gIHJldHVybiBzaXplO1xufTtcblxudmFyIHRyZWVfdmlzaXQgPSBmdW5jdGlvbihjYWxsYmFjaykge1xuICB2YXIgcXVhZHMgPSBbXSwgcSwgbm9kZSA9IHRoaXMuX3Jvb3QsIGNoaWxkLCB4MCwgeTAsIHgxLCB5MTtcbiAgaWYgKG5vZGUpIHF1YWRzLnB1c2gobmV3IFF1YWQobm9kZSwgdGhpcy5feDAsIHRoaXMuX3kwLCB0aGlzLl94MSwgdGhpcy5feTEpKTtcbiAgd2hpbGUgKHEgPSBxdWFkcy5wb3AoKSkge1xuICAgIGlmICghY2FsbGJhY2sobm9kZSA9IHEubm9kZSwgeDAgPSBxLngwLCB5MCA9IHEueTAsIHgxID0gcS54MSwgeTEgPSBxLnkxKSAmJiBub2RlLmxlbmd0aCkge1xuICAgICAgdmFyIHhtID0gKHgwICsgeDEpIC8gMiwgeW0gPSAoeTAgKyB5MSkgLyAyO1xuICAgICAgaWYgKGNoaWxkID0gbm9kZVszXSkgcXVhZHMucHVzaChuZXcgUXVhZChjaGlsZCwgeG0sIHltLCB4MSwgeTEpKTtcbiAgICAgIGlmIChjaGlsZCA9IG5vZGVbMl0pIHF1YWRzLnB1c2gobmV3IFF1YWQoY2hpbGQsIHgwLCB5bSwgeG0sIHkxKSk7XG4gICAgICBpZiAoY2hpbGQgPSBub2RlWzFdKSBxdWFkcy5wdXNoKG5ldyBRdWFkKGNoaWxkLCB4bSwgeTAsIHgxLCB5bSkpO1xuICAgICAgaWYgKGNoaWxkID0gbm9kZVswXSkgcXVhZHMucHVzaChuZXcgUXVhZChjaGlsZCwgeDAsIHkwLCB4bSwgeW0pKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG52YXIgdHJlZV92aXNpdEFmdGVyID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgdmFyIHF1YWRzID0gW10sIG5leHQgPSBbXSwgcTtcbiAgaWYgKHRoaXMuX3Jvb3QpIHF1YWRzLnB1c2gobmV3IFF1YWQodGhpcy5fcm9vdCwgdGhpcy5feDAsIHRoaXMuX3kwLCB0aGlzLl94MSwgdGhpcy5feTEpKTtcbiAgd2hpbGUgKHEgPSBxdWFkcy5wb3AoKSkge1xuICAgIHZhciBub2RlID0gcS5ub2RlO1xuICAgIGlmIChub2RlLmxlbmd0aCkge1xuICAgICAgdmFyIGNoaWxkLCB4MCA9IHEueDAsIHkwID0gcS55MCwgeDEgPSBxLngxLCB5MSA9IHEueTEsIHhtID0gKHgwICsgeDEpIC8gMiwgeW0gPSAoeTAgKyB5MSkgLyAyO1xuICAgICAgaWYgKGNoaWxkID0gbm9kZVswXSkgcXVhZHMucHVzaChuZXcgUXVhZChjaGlsZCwgeDAsIHkwLCB4bSwgeW0pKTtcbiAgICAgIGlmIChjaGlsZCA9IG5vZGVbMV0pIHF1YWRzLnB1c2gobmV3IFF1YWQoY2hpbGQsIHhtLCB5MCwgeDEsIHltKSk7XG4gICAgICBpZiAoY2hpbGQgPSBub2RlWzJdKSBxdWFkcy5wdXNoKG5ldyBRdWFkKGNoaWxkLCB4MCwgeW0sIHhtLCB5MSkpO1xuICAgICAgaWYgKGNoaWxkID0gbm9kZVszXSkgcXVhZHMucHVzaChuZXcgUXVhZChjaGlsZCwgeG0sIHltLCB4MSwgeTEpKTtcbiAgICB9XG4gICAgbmV4dC5wdXNoKHEpO1xuICB9XG4gIHdoaWxlIChxID0gbmV4dC5wb3AoKSkge1xuICAgIGNhbGxiYWNrKHEubm9kZSwgcS54MCwgcS55MCwgcS54MSwgcS55MSk7XG4gIH1cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5mdW5jdGlvbiBkZWZhdWx0WChkKSB7XG4gIHJldHVybiBkWzBdO1xufVxuXG52YXIgdHJlZV94ID0gZnVuY3Rpb24oXykge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aGlzLl94ID0gXywgdGhpcykgOiB0aGlzLl94O1xufTtcblxuZnVuY3Rpb24gZGVmYXVsdFkoZCkge1xuICByZXR1cm4gZFsxXTtcbn1cblxudmFyIHRyZWVfeSA9IGZ1bmN0aW9uKF8pIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGhpcy5feSA9IF8sIHRoaXMpIDogdGhpcy5feTtcbn07XG5cbmZ1bmN0aW9uIHF1YWR0cmVlKG5vZGVzLCB4LCB5KSB7XG4gIHZhciB0cmVlID0gbmV3IFF1YWR0cmVlKHggPT0gbnVsbCA/IGRlZmF1bHRYIDogeCwgeSA9PSBudWxsID8gZGVmYXVsdFkgOiB5LCBOYU4sIE5hTiwgTmFOLCBOYU4pO1xuICByZXR1cm4gbm9kZXMgPT0gbnVsbCA/IHRyZWUgOiB0cmVlLmFkZEFsbChub2Rlcyk7XG59XG5cbmZ1bmN0aW9uIFF1YWR0cmVlKHgsIHksIHgwLCB5MCwgeDEsIHkxKSB7XG4gIHRoaXMuX3ggPSB4O1xuICB0aGlzLl95ID0geTtcbiAgdGhpcy5feDAgPSB4MDtcbiAgdGhpcy5feTAgPSB5MDtcbiAgdGhpcy5feDEgPSB4MTtcbiAgdGhpcy5feTEgPSB5MTtcbiAgdGhpcy5fcm9vdCA9IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gbGVhZl9jb3B5KGxlYWYpIHtcbiAgdmFyIGNvcHkgPSB7ZGF0YTogbGVhZi5kYXRhfSwgbmV4dCA9IGNvcHk7XG4gIHdoaWxlIChsZWFmID0gbGVhZi5uZXh0KSBuZXh0ID0gbmV4dC5uZXh0ID0ge2RhdGE6IGxlYWYuZGF0YX07XG4gIHJldHVybiBjb3B5O1xufVxuXG52YXIgdHJlZVByb3RvID0gcXVhZHRyZWUucHJvdG90eXBlID0gUXVhZHRyZWUucHJvdG90eXBlO1xuXG50cmVlUHJvdG8uY29weSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgY29weSA9IG5ldyBRdWFkdHJlZSh0aGlzLl94LCB0aGlzLl95LCB0aGlzLl94MCwgdGhpcy5feTAsIHRoaXMuX3gxLCB0aGlzLl95MSksXG4gICAgICBub2RlID0gdGhpcy5fcm9vdCxcbiAgICAgIG5vZGVzLFxuICAgICAgY2hpbGQ7XG5cbiAgaWYgKCFub2RlKSByZXR1cm4gY29weTtcblxuICBpZiAoIW5vZGUubGVuZ3RoKSByZXR1cm4gY29weS5fcm9vdCA9IGxlYWZfY29weShub2RlKSwgY29weTtcblxuICBub2RlcyA9IFt7c291cmNlOiBub2RlLCB0YXJnZXQ6IGNvcHkuX3Jvb3QgPSBuZXcgQXJyYXkoNCl9XTtcbiAgd2hpbGUgKG5vZGUgPSBub2Rlcy5wb3AoKSkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNDsgKytpKSB7XG4gICAgICBpZiAoY2hpbGQgPSBub2RlLnNvdXJjZVtpXSkge1xuICAgICAgICBpZiAoY2hpbGQubGVuZ3RoKSBub2Rlcy5wdXNoKHtzb3VyY2U6IGNoaWxkLCB0YXJnZXQ6IG5vZGUudGFyZ2V0W2ldID0gbmV3IEFycmF5KDQpfSk7XG4gICAgICAgIGVsc2Ugbm9kZS50YXJnZXRbaV0gPSBsZWFmX2NvcHkoY2hpbGQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjb3B5O1xufTtcblxudHJlZVByb3RvLmFkZCA9IHRyZWVfYWRkO1xudHJlZVByb3RvLmFkZEFsbCA9IGFkZEFsbDtcbnRyZWVQcm90by5jb3ZlciA9IHRyZWVfY292ZXI7XG50cmVlUHJvdG8uZGF0YSA9IHRyZWVfZGF0YTtcbnRyZWVQcm90by5leHRlbnQgPSB0cmVlX2V4dGVudDtcbnRyZWVQcm90by5maW5kID0gdHJlZV9maW5kO1xudHJlZVByb3RvLnJlbW92ZSA9IHRyZWVfcmVtb3ZlO1xudHJlZVByb3RvLnJlbW92ZUFsbCA9IHJlbW92ZUFsbDtcbnRyZWVQcm90by5yb290ID0gdHJlZV9yb290O1xudHJlZVByb3RvLnNpemUgPSB0cmVlX3NpemU7XG50cmVlUHJvdG8udmlzaXQgPSB0cmVlX3Zpc2l0O1xudHJlZVByb3RvLnZpc2l0QWZ0ZXIgPSB0cmVlX3Zpc2l0QWZ0ZXI7XG50cmVlUHJvdG8ueCA9IHRyZWVfeDtcbnRyZWVQcm90by55ID0gdHJlZV95O1xuXG5leHBvcnRzLnF1YWR0cmVlID0gcXVhZHRyZWU7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG5cbn0se31dLDE2MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBodHRwczovL2QzanMub3JnL2QzLXNoYXBlLyB2MS4zLjQgQ29weXJpZ2h0IDIwMTkgTWlrZSBCb3N0b2NrXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xudHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzLCBfZGVyZXFfKCdkMy1wYXRoJykpIDpcbnR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtcGF0aCddLCBmYWN0b3J5KSA6XG4oZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzLGQzUGF0aCkgeyAndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIGNvbnN0YW50KHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIGNvbnN0YW50KCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufVxuXG52YXIgYWJzID0gTWF0aC5hYnM7XG52YXIgYXRhbjIgPSBNYXRoLmF0YW4yO1xudmFyIGNvcyA9IE1hdGguY29zO1xudmFyIG1heCA9IE1hdGgubWF4O1xudmFyIG1pbiA9IE1hdGgubWluO1xudmFyIHNpbiA9IE1hdGguc2luO1xudmFyIHNxcnQgPSBNYXRoLnNxcnQ7XG5cbnZhciBlcHNpbG9uID0gMWUtMTI7XG52YXIgcGkgPSBNYXRoLlBJO1xudmFyIGhhbGZQaSA9IHBpIC8gMjtcbnZhciB0YXUgPSAyICogcGk7XG5cbmZ1bmN0aW9uIGFjb3MoeCkge1xuICByZXR1cm4geCA+IDEgPyAwIDogeCA8IC0xID8gcGkgOiBNYXRoLmFjb3MoeCk7XG59XG5cbmZ1bmN0aW9uIGFzaW4oeCkge1xuICByZXR1cm4geCA+PSAxID8gaGFsZlBpIDogeCA8PSAtMSA/IC1oYWxmUGkgOiBNYXRoLmFzaW4oeCk7XG59XG5cbmZ1bmN0aW9uIGFyY0lubmVyUmFkaXVzKGQpIHtcbiAgcmV0dXJuIGQuaW5uZXJSYWRpdXM7XG59XG5cbmZ1bmN0aW9uIGFyY091dGVyUmFkaXVzKGQpIHtcbiAgcmV0dXJuIGQub3V0ZXJSYWRpdXM7XG59XG5cbmZ1bmN0aW9uIGFyY1N0YXJ0QW5nbGUoZCkge1xuICByZXR1cm4gZC5zdGFydEFuZ2xlO1xufVxuXG5mdW5jdGlvbiBhcmNFbmRBbmdsZShkKSB7XG4gIHJldHVybiBkLmVuZEFuZ2xlO1xufVxuXG5mdW5jdGlvbiBhcmNQYWRBbmdsZShkKSB7XG4gIHJldHVybiBkICYmIGQucGFkQW5nbGU7IC8vIE5vdGU6IG9wdGlvbmFsIVxufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3QoeDAsIHkwLCB4MSwgeTEsIHgyLCB5MiwgeDMsIHkzKSB7XG4gIHZhciB4MTAgPSB4MSAtIHgwLCB5MTAgPSB5MSAtIHkwLFxuICAgICAgeDMyID0geDMgLSB4MiwgeTMyID0geTMgLSB5MixcbiAgICAgIHQgPSB5MzIgKiB4MTAgLSB4MzIgKiB5MTA7XG4gIGlmICh0ICogdCA8IGVwc2lsb24pIHJldHVybjtcbiAgdCA9ICh4MzIgKiAoeTAgLSB5MikgLSB5MzIgKiAoeDAgLSB4MikpIC8gdDtcbiAgcmV0dXJuIFt4MCArIHQgKiB4MTAsIHkwICsgdCAqIHkxMF07XG59XG5cbi8vIENvbXB1dGUgcGVycGVuZGljdWxhciBvZmZzZXQgbGluZSBvZiBsZW5ndGggcmMuXG4vLyBodHRwOi8vbWF0aHdvcmxkLndvbGZyYW0uY29tL0NpcmNsZS1MaW5lSW50ZXJzZWN0aW9uLmh0bWxcbmZ1bmN0aW9uIGNvcm5lclRhbmdlbnRzKHgwLCB5MCwgeDEsIHkxLCByMSwgcmMsIGN3KSB7XG4gIHZhciB4MDEgPSB4MCAtIHgxLFxuICAgICAgeTAxID0geTAgLSB5MSxcbiAgICAgIGxvID0gKGN3ID8gcmMgOiAtcmMpIC8gc3FydCh4MDEgKiB4MDEgKyB5MDEgKiB5MDEpLFxuICAgICAgb3ggPSBsbyAqIHkwMSxcbiAgICAgIG95ID0gLWxvICogeDAxLFxuICAgICAgeDExID0geDAgKyBveCxcbiAgICAgIHkxMSA9IHkwICsgb3ksXG4gICAgICB4MTAgPSB4MSArIG94LFxuICAgICAgeTEwID0geTEgKyBveSxcbiAgICAgIHgwMCA9ICh4MTEgKyB4MTApIC8gMixcbiAgICAgIHkwMCA9ICh5MTEgKyB5MTApIC8gMixcbiAgICAgIGR4ID0geDEwIC0geDExLFxuICAgICAgZHkgPSB5MTAgLSB5MTEsXG4gICAgICBkMiA9IGR4ICogZHggKyBkeSAqIGR5LFxuICAgICAgciA9IHIxIC0gcmMsXG4gICAgICBEID0geDExICogeTEwIC0geDEwICogeTExLFxuICAgICAgZCA9IChkeSA8IDAgPyAtMSA6IDEpICogc3FydChtYXgoMCwgciAqIHIgKiBkMiAtIEQgKiBEKSksXG4gICAgICBjeDAgPSAoRCAqIGR5IC0gZHggKiBkKSAvIGQyLFxuICAgICAgY3kwID0gKC1EICogZHggLSBkeSAqIGQpIC8gZDIsXG4gICAgICBjeDEgPSAoRCAqIGR5ICsgZHggKiBkKSAvIGQyLFxuICAgICAgY3kxID0gKC1EICogZHggKyBkeSAqIGQpIC8gZDIsXG4gICAgICBkeDAgPSBjeDAgLSB4MDAsXG4gICAgICBkeTAgPSBjeTAgLSB5MDAsXG4gICAgICBkeDEgPSBjeDEgLSB4MDAsXG4gICAgICBkeTEgPSBjeTEgLSB5MDA7XG5cbiAgLy8gUGljayB0aGUgY2xvc2VyIG9mIHRoZSB0d28gaW50ZXJzZWN0aW9uIHBvaW50cy5cbiAgLy8gVE9ETyBJcyB0aGVyZSBhIGZhc3RlciB3YXkgdG8gZGV0ZXJtaW5lIHdoaWNoIGludGVyc2VjdGlvbiB0byB1c2U/XG4gIGlmIChkeDAgKiBkeDAgKyBkeTAgKiBkeTAgPiBkeDEgKiBkeDEgKyBkeTEgKiBkeTEpIGN4MCA9IGN4MSwgY3kwID0gY3kxO1xuXG4gIHJldHVybiB7XG4gICAgY3g6IGN4MCxcbiAgICBjeTogY3kwLFxuICAgIHgwMTogLW94LFxuICAgIHkwMTogLW95LFxuICAgIHgxMTogY3gwICogKHIxIC8gciAtIDEpLFxuICAgIHkxMTogY3kwICogKHIxIC8gciAtIDEpXG4gIH07XG59XG5cbmZ1bmN0aW9uIGFyYygpIHtcbiAgdmFyIGlubmVyUmFkaXVzID0gYXJjSW5uZXJSYWRpdXMsXG4gICAgICBvdXRlclJhZGl1cyA9IGFyY091dGVyUmFkaXVzLFxuICAgICAgY29ybmVyUmFkaXVzID0gY29uc3RhbnQoMCksXG4gICAgICBwYWRSYWRpdXMgPSBudWxsLFxuICAgICAgc3RhcnRBbmdsZSA9IGFyY1N0YXJ0QW5nbGUsXG4gICAgICBlbmRBbmdsZSA9IGFyY0VuZEFuZ2xlLFxuICAgICAgcGFkQW5nbGUgPSBhcmNQYWRBbmdsZSxcbiAgICAgIGNvbnRleHQgPSBudWxsO1xuXG4gIGZ1bmN0aW9uIGFyYygpIHtcbiAgICB2YXIgYnVmZmVyLFxuICAgICAgICByLFxuICAgICAgICByMCA9ICtpbm5lclJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpLFxuICAgICAgICByMSA9ICtvdXRlclJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpLFxuICAgICAgICBhMCA9IHN0YXJ0QW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSAtIGhhbGZQaSxcbiAgICAgICAgYTEgPSBlbmRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIC0gaGFsZlBpLFxuICAgICAgICBkYSA9IGFicyhhMSAtIGEwKSxcbiAgICAgICAgY3cgPSBhMSA+IGEwO1xuXG4gICAgaWYgKCFjb250ZXh0KSBjb250ZXh0ID0gYnVmZmVyID0gZDNQYXRoLnBhdGgoKTtcblxuICAgIC8vIEVuc3VyZSB0aGF0IHRoZSBvdXRlciByYWRpdXMgaXMgYWx3YXlzIGxhcmdlciB0aGFuIHRoZSBpbm5lciByYWRpdXMuXG4gICAgaWYgKHIxIDwgcjApIHIgPSByMSwgcjEgPSByMCwgcjAgPSByO1xuXG4gICAgLy8gSXMgaXQgYSBwb2ludD9cbiAgICBpZiAoIShyMSA+IGVwc2lsb24pKSBjb250ZXh0Lm1vdmVUbygwLCAwKTtcblxuICAgIC8vIE9yIGlzIGl0IGEgY2lyY2xlIG9yIGFubnVsdXM/XG4gICAgZWxzZSBpZiAoZGEgPiB0YXUgLSBlcHNpbG9uKSB7XG4gICAgICBjb250ZXh0Lm1vdmVUbyhyMSAqIGNvcyhhMCksIHIxICogc2luKGEwKSk7XG4gICAgICBjb250ZXh0LmFyYygwLCAwLCByMSwgYTAsIGExLCAhY3cpO1xuICAgICAgaWYgKHIwID4gZXBzaWxvbikge1xuICAgICAgICBjb250ZXh0Lm1vdmVUbyhyMCAqIGNvcyhhMSksIHIwICogc2luKGExKSk7XG4gICAgICAgIGNvbnRleHQuYXJjKDAsIDAsIHIwLCBhMSwgYTAsIGN3KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBPciBpcyBpdCBhIGNpcmN1bGFyIG9yIGFubnVsYXIgc2VjdG9yP1xuICAgIGVsc2Uge1xuICAgICAgdmFyIGEwMSA9IGEwLFxuICAgICAgICAgIGExMSA9IGExLFxuICAgICAgICAgIGEwMCA9IGEwLFxuICAgICAgICAgIGExMCA9IGExLFxuICAgICAgICAgIGRhMCA9IGRhLFxuICAgICAgICAgIGRhMSA9IGRhLFxuICAgICAgICAgIGFwID0gcGFkQW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSAvIDIsXG4gICAgICAgICAgcnAgPSAoYXAgPiBlcHNpbG9uKSAmJiAocGFkUmFkaXVzID8gK3BhZFJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogc3FydChyMCAqIHIwICsgcjEgKiByMSkpLFxuICAgICAgICAgIHJjID0gbWluKGFicyhyMSAtIHIwKSAvIDIsICtjb3JuZXJSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSksXG4gICAgICAgICAgcmMwID0gcmMsXG4gICAgICAgICAgcmMxID0gcmMsXG4gICAgICAgICAgdDAsXG4gICAgICAgICAgdDE7XG5cbiAgICAgIC8vIEFwcGx5IHBhZGRpbmc/IE5vdGUgdGhhdCBzaW5jZSByMSDiiaUgcjAsIGRhMSDiiaUgZGEwLlxuICAgICAgaWYgKHJwID4gZXBzaWxvbikge1xuICAgICAgICB2YXIgcDAgPSBhc2luKHJwIC8gcjAgKiBzaW4oYXApKSxcbiAgICAgICAgICAgIHAxID0gYXNpbihycCAvIHIxICogc2luKGFwKSk7XG4gICAgICAgIGlmICgoZGEwIC09IHAwICogMikgPiBlcHNpbG9uKSBwMCAqPSAoY3cgPyAxIDogLTEpLCBhMDAgKz0gcDAsIGExMCAtPSBwMDtcbiAgICAgICAgZWxzZSBkYTAgPSAwLCBhMDAgPSBhMTAgPSAoYTAgKyBhMSkgLyAyO1xuICAgICAgICBpZiAoKGRhMSAtPSBwMSAqIDIpID4gZXBzaWxvbikgcDEgKj0gKGN3ID8gMSA6IC0xKSwgYTAxICs9IHAxLCBhMTEgLT0gcDE7XG4gICAgICAgIGVsc2UgZGExID0gMCwgYTAxID0gYTExID0gKGEwICsgYTEpIC8gMjtcbiAgICAgIH1cblxuICAgICAgdmFyIHgwMSA9IHIxICogY29zKGEwMSksXG4gICAgICAgICAgeTAxID0gcjEgKiBzaW4oYTAxKSxcbiAgICAgICAgICB4MTAgPSByMCAqIGNvcyhhMTApLFxuICAgICAgICAgIHkxMCA9IHIwICogc2luKGExMCk7XG5cbiAgICAgIC8vIEFwcGx5IHJvdW5kZWQgY29ybmVycz9cbiAgICAgIGlmIChyYyA+IGVwc2lsb24pIHtcbiAgICAgICAgdmFyIHgxMSA9IHIxICogY29zKGExMSksXG4gICAgICAgICAgICB5MTEgPSByMSAqIHNpbihhMTEpLFxuICAgICAgICAgICAgeDAwID0gcjAgKiBjb3MoYTAwKSxcbiAgICAgICAgICAgIHkwMCA9IHIwICogc2luKGEwMCksXG4gICAgICAgICAgICBvYztcblxuICAgICAgICAvLyBSZXN0cmljdCB0aGUgY29ybmVyIHJhZGl1cyBhY2NvcmRpbmcgdG8gdGhlIHNlY3RvciBhbmdsZS5cbiAgICAgICAgaWYgKGRhIDwgcGkgJiYgKG9jID0gaW50ZXJzZWN0KHgwMSwgeTAxLCB4MDAsIHkwMCwgeDExLCB5MTEsIHgxMCwgeTEwKSkpIHtcbiAgICAgICAgICB2YXIgYXggPSB4MDEgLSBvY1swXSxcbiAgICAgICAgICAgICAgYXkgPSB5MDEgLSBvY1sxXSxcbiAgICAgICAgICAgICAgYnggPSB4MTEgLSBvY1swXSxcbiAgICAgICAgICAgICAgYnkgPSB5MTEgLSBvY1sxXSxcbiAgICAgICAgICAgICAga2MgPSAxIC8gc2luKGFjb3MoKGF4ICogYnggKyBheSAqIGJ5KSAvIChzcXJ0KGF4ICogYXggKyBheSAqIGF5KSAqIHNxcnQoYnggKiBieCArIGJ5ICogYnkpKSkgLyAyKSxcbiAgICAgICAgICAgICAgbGMgPSBzcXJ0KG9jWzBdICogb2NbMF0gKyBvY1sxXSAqIG9jWzFdKTtcbiAgICAgICAgICByYzAgPSBtaW4ocmMsIChyMCAtIGxjKSAvIChrYyAtIDEpKTtcbiAgICAgICAgICByYzEgPSBtaW4ocmMsIChyMSAtIGxjKSAvIChrYyArIDEpKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBJcyB0aGUgc2VjdG9yIGNvbGxhcHNlZCB0byBhIGxpbmU/XG4gICAgICBpZiAoIShkYTEgPiBlcHNpbG9uKSkgY29udGV4dC5tb3ZlVG8oeDAxLCB5MDEpO1xuXG4gICAgICAvLyBEb2VzIHRoZSBzZWN0b3LigJlzIG91dGVyIHJpbmcgaGF2ZSByb3VuZGVkIGNvcm5lcnM/XG4gICAgICBlbHNlIGlmIChyYzEgPiBlcHNpbG9uKSB7XG4gICAgICAgIHQwID0gY29ybmVyVGFuZ2VudHMoeDAwLCB5MDAsIHgwMSwgeTAxLCByMSwgcmMxLCBjdyk7XG4gICAgICAgIHQxID0gY29ybmVyVGFuZ2VudHMoeDExLCB5MTEsIHgxMCwgeTEwLCByMSwgcmMxLCBjdyk7XG5cbiAgICAgICAgY29udGV4dC5tb3ZlVG8odDAuY3ggKyB0MC54MDEsIHQwLmN5ICsgdDAueTAxKTtcblxuICAgICAgICAvLyBIYXZlIHRoZSBjb3JuZXJzIG1lcmdlZD9cbiAgICAgICAgaWYgKHJjMSA8IHJjKSBjb250ZXh0LmFyYyh0MC5jeCwgdDAuY3ksIHJjMSwgYXRhbjIodDAueTAxLCB0MC54MDEpLCBhdGFuMih0MS55MDEsIHQxLngwMSksICFjdyk7XG5cbiAgICAgICAgLy8gT3RoZXJ3aXNlLCBkcmF3IHRoZSB0d28gY29ybmVycyBhbmQgdGhlIHJpbmcuXG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGNvbnRleHQuYXJjKHQwLmN4LCB0MC5jeSwgcmMxLCBhdGFuMih0MC55MDEsIHQwLngwMSksIGF0YW4yKHQwLnkxMSwgdDAueDExKSwgIWN3KTtcbiAgICAgICAgICBjb250ZXh0LmFyYygwLCAwLCByMSwgYXRhbjIodDAuY3kgKyB0MC55MTEsIHQwLmN4ICsgdDAueDExKSwgYXRhbjIodDEuY3kgKyB0MS55MTEsIHQxLmN4ICsgdDEueDExKSwgIWN3KTtcbiAgICAgICAgICBjb250ZXh0LmFyYyh0MS5jeCwgdDEuY3ksIHJjMSwgYXRhbjIodDEueTExLCB0MS54MTEpLCBhdGFuMih0MS55MDEsIHQxLngwMSksICFjdyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gT3IgaXMgdGhlIG91dGVyIHJpbmcganVzdCBhIGNpcmN1bGFyIGFyYz9cbiAgICAgIGVsc2UgY29udGV4dC5tb3ZlVG8oeDAxLCB5MDEpLCBjb250ZXh0LmFyYygwLCAwLCByMSwgYTAxLCBhMTEsICFjdyk7XG5cbiAgICAgIC8vIElzIHRoZXJlIG5vIGlubmVyIHJpbmcsIGFuZCBpdOKAmXMgYSBjaXJjdWxhciBzZWN0b3I/XG4gICAgICAvLyBPciBwZXJoYXBzIGl04oCZcyBhbiBhbm51bGFyIHNlY3RvciBjb2xsYXBzZWQgZHVlIHRvIHBhZGRpbmc/XG4gICAgICBpZiAoIShyMCA+IGVwc2lsb24pIHx8ICEoZGEwID4gZXBzaWxvbikpIGNvbnRleHQubGluZVRvKHgxMCwgeTEwKTtcblxuICAgICAgLy8gRG9lcyB0aGUgc2VjdG9y4oCZcyBpbm5lciByaW5nIChvciBwb2ludCkgaGF2ZSByb3VuZGVkIGNvcm5lcnM/XG4gICAgICBlbHNlIGlmIChyYzAgPiBlcHNpbG9uKSB7XG4gICAgICAgIHQwID0gY29ybmVyVGFuZ2VudHMoeDEwLCB5MTAsIHgxMSwgeTExLCByMCwgLXJjMCwgY3cpO1xuICAgICAgICB0MSA9IGNvcm5lclRhbmdlbnRzKHgwMSwgeTAxLCB4MDAsIHkwMCwgcjAsIC1yYzAsIGN3KTtcblxuICAgICAgICBjb250ZXh0LmxpbmVUbyh0MC5jeCArIHQwLngwMSwgdDAuY3kgKyB0MC55MDEpO1xuXG4gICAgICAgIC8vIEhhdmUgdGhlIGNvcm5lcnMgbWVyZ2VkP1xuICAgICAgICBpZiAocmMwIDwgcmMpIGNvbnRleHQuYXJjKHQwLmN4LCB0MC5jeSwgcmMwLCBhdGFuMih0MC55MDEsIHQwLngwMSksIGF0YW4yKHQxLnkwMSwgdDEueDAxKSwgIWN3KTtcblxuICAgICAgICAvLyBPdGhlcndpc2UsIGRyYXcgdGhlIHR3byBjb3JuZXJzIGFuZCB0aGUgcmluZy5cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgY29udGV4dC5hcmModDAuY3gsIHQwLmN5LCByYzAsIGF0YW4yKHQwLnkwMSwgdDAueDAxKSwgYXRhbjIodDAueTExLCB0MC54MTEpLCAhY3cpO1xuICAgICAgICAgIGNvbnRleHQuYXJjKDAsIDAsIHIwLCBhdGFuMih0MC5jeSArIHQwLnkxMSwgdDAuY3ggKyB0MC54MTEpLCBhdGFuMih0MS5jeSArIHQxLnkxMSwgdDEuY3ggKyB0MS54MTEpLCBjdyk7XG4gICAgICAgICAgY29udGV4dC5hcmModDEuY3gsIHQxLmN5LCByYzAsIGF0YW4yKHQxLnkxMSwgdDEueDExKSwgYXRhbjIodDEueTAxLCB0MS54MDEpLCAhY3cpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIE9yIGlzIHRoZSBpbm5lciByaW5nIGp1c3QgYSBjaXJjdWxhciBhcmM/XG4gICAgICBlbHNlIGNvbnRleHQuYXJjKDAsIDAsIHIwLCBhMTAsIGEwMCwgY3cpO1xuICAgIH1cblxuICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG5cbiAgICBpZiAoYnVmZmVyKSByZXR1cm4gY29udGV4dCA9IG51bGwsIGJ1ZmZlciArIFwiXCIgfHwgbnVsbDtcbiAgfVxuXG4gIGFyYy5jZW50cm9pZCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByID0gKCtpbm5lclJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpICsgK291dGVyUmFkaXVzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpIC8gMixcbiAgICAgICAgYSA9ICgrc3RhcnRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpICsgK2VuZEFuZ2xlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpIC8gMiAtIHBpIC8gMjtcbiAgICByZXR1cm4gW2NvcyhhKSAqIHIsIHNpbihhKSAqIHJdO1xuICB9O1xuXG4gIGFyYy5pbm5lclJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpbm5lclJhZGl1cyA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBhcmMpIDogaW5uZXJSYWRpdXM7XG4gIH07XG5cbiAgYXJjLm91dGVyUmFkaXVzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG91dGVyUmFkaXVzID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGFyYykgOiBvdXRlclJhZGl1cztcbiAgfTtcblxuICBhcmMuY29ybmVyUmFkaXVzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvcm5lclJhZGl1cyA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBhcmMpIDogY29ybmVyUmFkaXVzO1xuICB9O1xuXG4gIGFyYy5wYWRSYWRpdXMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkUmFkaXVzID0gXyA9PSBudWxsID8gbnVsbCA6IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBhcmMpIDogcGFkUmFkaXVzO1xuICB9O1xuXG4gIGFyYy5zdGFydEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0YXJ0QW5nbGUgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgYXJjKSA6IHN0YXJ0QW5nbGU7XG4gIH07XG5cbiAgYXJjLmVuZEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVuZEFuZ2xlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGFyYykgOiBlbmRBbmdsZTtcbiAgfTtcblxuICBhcmMucGFkQW5nbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkQW5nbGUgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgYXJjKSA6IHBhZEFuZ2xlO1xuICB9O1xuXG4gIGFyYy5jb250ZXh0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKChjb250ZXh0ID0gXyA9PSBudWxsID8gbnVsbCA6IF8pLCBhcmMpIDogY29udGV4dDtcbiAgfTtcblxuICByZXR1cm4gYXJjO1xufVxuXG5mdW5jdGlvbiBMaW5lYXIoY29udGV4dCkge1xuICB0aGlzLl9jb250ZXh0ID0gY29udGV4dDtcbn1cblxuTGluZWFyLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gMDtcbiAgfSxcbiAgYXJlYUVuZDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IE5hTjtcbiAgfSxcbiAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLl9saW5lIHx8ICh0aGlzLl9saW5lICE9PSAwICYmIHRoaXMuX3BvaW50ID09PSAxKSkgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICB0aGlzLl9saW5lID0gMSAtIHRoaXMuX2xpbmU7XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgeCA9ICt4LCB5ID0gK3k7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAwOiB0aGlzLl9wb2ludCA9IDE7IHRoaXMuX2xpbmUgPyB0aGlzLl9jb250ZXh0LmxpbmVUbyh4LCB5KSA6IHRoaXMuX2NvbnRleHQubW92ZVRvKHgsIHkpOyBicmVhaztcbiAgICAgIGNhc2UgMTogdGhpcy5fcG9pbnQgPSAyOyAvLyBwcm9jZWVkXG4gICAgICBkZWZhdWx0OiB0aGlzLl9jb250ZXh0LmxpbmVUbyh4LCB5KTsgYnJlYWs7XG4gICAgfVxuICB9XG59O1xuXG5mdW5jdGlvbiBjdXJ2ZUxpbmVhcihjb250ZXh0KSB7XG4gIHJldHVybiBuZXcgTGluZWFyKGNvbnRleHQpO1xufVxuXG5mdW5jdGlvbiB4KHApIHtcbiAgcmV0dXJuIHBbMF07XG59XG5cbmZ1bmN0aW9uIHkocCkge1xuICByZXR1cm4gcFsxXTtcbn1cblxuZnVuY3Rpb24gbGluZSgpIHtcbiAgdmFyIHgkJDEgPSB4LFxuICAgICAgeSQkMSA9IHksXG4gICAgICBkZWZpbmVkID0gY29uc3RhbnQodHJ1ZSksXG4gICAgICBjb250ZXh0ID0gbnVsbCxcbiAgICAgIGN1cnZlID0gY3VydmVMaW5lYXIsXG4gICAgICBvdXRwdXQgPSBudWxsO1xuXG4gIGZ1bmN0aW9uIGxpbmUoZGF0YSkge1xuICAgIHZhciBpLFxuICAgICAgICBuID0gZGF0YS5sZW5ndGgsXG4gICAgICAgIGQsXG4gICAgICAgIGRlZmluZWQwID0gZmFsc2UsXG4gICAgICAgIGJ1ZmZlcjtcblxuICAgIGlmIChjb250ZXh0ID09IG51bGwpIG91dHB1dCA9IGN1cnZlKGJ1ZmZlciA9IGQzUGF0aC5wYXRoKCkpO1xuXG4gICAgZm9yIChpID0gMDsgaSA8PSBuOyArK2kpIHtcbiAgICAgIGlmICghKGkgPCBuICYmIGRlZmluZWQoZCA9IGRhdGFbaV0sIGksIGRhdGEpKSA9PT0gZGVmaW5lZDApIHtcbiAgICAgICAgaWYgKGRlZmluZWQwID0gIWRlZmluZWQwKSBvdXRwdXQubGluZVN0YXJ0KCk7XG4gICAgICAgIGVsc2Ugb3V0cHV0LmxpbmVFbmQoKTtcbiAgICAgIH1cbiAgICAgIGlmIChkZWZpbmVkMCkgb3V0cHV0LnBvaW50KCt4JCQxKGQsIGksIGRhdGEpLCAreSQkMShkLCBpLCBkYXRhKSk7XG4gICAgfVxuXG4gICAgaWYgKGJ1ZmZlcikgcmV0dXJuIG91dHB1dCA9IG51bGwsIGJ1ZmZlciArIFwiXCIgfHwgbnVsbDtcbiAgfVxuXG4gIGxpbmUueCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4JCQxID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGxpbmUpIDogeCQkMTtcbiAgfTtcblxuICBsaW5lLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSQkMSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBsaW5lKSA6IHkkJDE7XG4gIH07XG5cbiAgbGluZS5kZWZpbmVkID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRlZmluZWQgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCEhXyksIGxpbmUpIDogZGVmaW5lZDtcbiAgfTtcblxuICBsaW5lLmN1cnZlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGN1cnZlID0gXywgY29udGV4dCAhPSBudWxsICYmIChvdXRwdXQgPSBjdXJ2ZShjb250ZXh0KSksIGxpbmUpIDogY3VydmU7XG4gIH07XG5cbiAgbGluZS5jb250ZXh0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKF8gPT0gbnVsbCA/IGNvbnRleHQgPSBvdXRwdXQgPSBudWxsIDogb3V0cHV0ID0gY3VydmUoY29udGV4dCA9IF8pLCBsaW5lKSA6IGNvbnRleHQ7XG4gIH07XG5cbiAgcmV0dXJuIGxpbmU7XG59XG5cbmZ1bmN0aW9uIGFyZWEoKSB7XG4gIHZhciB4MCA9IHgsXG4gICAgICB4MSA9IG51bGwsXG4gICAgICB5MCA9IGNvbnN0YW50KDApLFxuICAgICAgeTEgPSB5LFxuICAgICAgZGVmaW5lZCA9IGNvbnN0YW50KHRydWUpLFxuICAgICAgY29udGV4dCA9IG51bGwsXG4gICAgICBjdXJ2ZSA9IGN1cnZlTGluZWFyLFxuICAgICAgb3V0cHV0ID0gbnVsbDtcblxuICBmdW5jdGlvbiBhcmVhKGRhdGEpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgaixcbiAgICAgICAgayxcbiAgICAgICAgbiA9IGRhdGEubGVuZ3RoLFxuICAgICAgICBkLFxuICAgICAgICBkZWZpbmVkMCA9IGZhbHNlLFxuICAgICAgICBidWZmZXIsXG4gICAgICAgIHgweiA9IG5ldyBBcnJheShuKSxcbiAgICAgICAgeTB6ID0gbmV3IEFycmF5KG4pO1xuXG4gICAgaWYgKGNvbnRleHQgPT0gbnVsbCkgb3V0cHV0ID0gY3VydmUoYnVmZmVyID0gZDNQYXRoLnBhdGgoKSk7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDw9IG47ICsraSkge1xuICAgICAgaWYgKCEoaSA8IG4gJiYgZGVmaW5lZChkID0gZGF0YVtpXSwgaSwgZGF0YSkpID09PSBkZWZpbmVkMCkge1xuICAgICAgICBpZiAoZGVmaW5lZDAgPSAhZGVmaW5lZDApIHtcbiAgICAgICAgICBqID0gaTtcbiAgICAgICAgICBvdXRwdXQuYXJlYVN0YXJ0KCk7XG4gICAgICAgICAgb3V0cHV0LmxpbmVTdGFydCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG91dHB1dC5saW5lRW5kKCk7XG4gICAgICAgICAgb3V0cHV0LmxpbmVTdGFydCgpO1xuICAgICAgICAgIGZvciAoayA9IGkgLSAxOyBrID49IGo7IC0taykge1xuICAgICAgICAgICAgb3V0cHV0LnBvaW50KHgweltrXSwgeTB6W2tdKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgb3V0cHV0LmxpbmVFbmQoKTtcbiAgICAgICAgICBvdXRwdXQuYXJlYUVuZCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZGVmaW5lZDApIHtcbiAgICAgICAgeDB6W2ldID0gK3gwKGQsIGksIGRhdGEpLCB5MHpbaV0gPSAreTAoZCwgaSwgZGF0YSk7XG4gICAgICAgIG91dHB1dC5wb2ludCh4MSA/ICt4MShkLCBpLCBkYXRhKSA6IHgweltpXSwgeTEgPyAreTEoZCwgaSwgZGF0YSkgOiB5MHpbaV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChidWZmZXIpIHJldHVybiBvdXRwdXQgPSBudWxsLCBidWZmZXIgKyBcIlwiIHx8IG51bGw7XG4gIH1cblxuICBmdW5jdGlvbiBhcmVhbGluZSgpIHtcbiAgICByZXR1cm4gbGluZSgpLmRlZmluZWQoZGVmaW5lZCkuY3VydmUoY3VydmUpLmNvbnRleHQoY29udGV4dCk7XG4gIH1cblxuICBhcmVhLnggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeDAgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgeDEgPSBudWxsLCBhcmVhKSA6IHgwO1xuICB9O1xuXG4gIGFyZWEueDAgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeDAgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgYXJlYSkgOiB4MDtcbiAgfTtcblxuICBhcmVhLngxID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHgxID0gXyA9PSBudWxsID8gbnVsbCA6IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBhcmVhKSA6IHgxO1xuICB9O1xuXG4gIGFyZWEueSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5MCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCB5MSA9IG51bGwsIGFyZWEpIDogeTA7XG4gIH07XG5cbiAgYXJlYS55MCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh5MCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBhcmVhKSA6IHkwO1xuICB9O1xuXG4gIGFyZWEueTEgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeTEgPSBfID09IG51bGwgPyBudWxsIDogdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGFyZWEpIDogeTE7XG4gIH07XG5cbiAgYXJlYS5saW5lWDAgPVxuICBhcmVhLmxpbmVZMCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBhcmVhbGluZSgpLngoeDApLnkoeTApO1xuICB9O1xuXG4gIGFyZWEubGluZVkxID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGFyZWFsaW5lKCkueCh4MCkueSh5MSk7XG4gIH07XG5cbiAgYXJlYS5saW5lWDEgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXJlYWxpbmUoKS54KHgxKS55KHkwKTtcbiAgfTtcblxuICBhcmVhLmRlZmluZWQgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGVmaW5lZCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoISFfKSwgYXJlYSkgOiBkZWZpbmVkO1xuICB9O1xuXG4gIGFyZWEuY3VydmUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY3VydmUgPSBfLCBjb250ZXh0ICE9IG51bGwgJiYgKG91dHB1dCA9IGN1cnZlKGNvbnRleHQpKSwgYXJlYSkgOiBjdXJ2ZTtcbiAgfTtcblxuICBhcmVhLmNvbnRleHQgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoXyA9PSBudWxsID8gY29udGV4dCA9IG91dHB1dCA9IG51bGwgOiBvdXRwdXQgPSBjdXJ2ZShjb250ZXh0ID0gXyksIGFyZWEpIDogY29udGV4dDtcbiAgfTtcblxuICByZXR1cm4gYXJlYTtcbn1cblxuZnVuY3Rpb24gZGVzY2VuZGluZyhhLCBiKSB7XG4gIHJldHVybiBiIDwgYSA/IC0xIDogYiA+IGEgPyAxIDogYiA+PSBhID8gMCA6IE5hTjtcbn1cblxuZnVuY3Rpb24gaWRlbnRpdHkoZCkge1xuICByZXR1cm4gZDtcbn1cblxuZnVuY3Rpb24gcGllKCkge1xuICB2YXIgdmFsdWUgPSBpZGVudGl0eSxcbiAgICAgIHNvcnRWYWx1ZXMgPSBkZXNjZW5kaW5nLFxuICAgICAgc29ydCA9IG51bGwsXG4gICAgICBzdGFydEFuZ2xlID0gY29uc3RhbnQoMCksXG4gICAgICBlbmRBbmdsZSA9IGNvbnN0YW50KHRhdSksXG4gICAgICBwYWRBbmdsZSA9IGNvbnN0YW50KDApO1xuXG4gIGZ1bmN0aW9uIHBpZShkYXRhKSB7XG4gICAgdmFyIGksXG4gICAgICAgIG4gPSBkYXRhLmxlbmd0aCxcbiAgICAgICAgaixcbiAgICAgICAgayxcbiAgICAgICAgc3VtID0gMCxcbiAgICAgICAgaW5kZXggPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGFyY3MgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGEwID0gK3N0YXJ0QW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSxcbiAgICAgICAgZGEgPSBNYXRoLm1pbih0YXUsIE1hdGgubWF4KC10YXUsIGVuZEFuZ2xlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgLSBhMCkpLFxuICAgICAgICBhMSxcbiAgICAgICAgcCA9IE1hdGgubWluKE1hdGguYWJzKGRhKSAvIG4sIHBhZEFuZ2xlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpLFxuICAgICAgICBwYSA9IHAgKiAoZGEgPCAwID8gLTEgOiAxKSxcbiAgICAgICAgdjtcblxuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGlmICgodiA9IGFyY3NbaW5kZXhbaV0gPSBpXSA9ICt2YWx1ZShkYXRhW2ldLCBpLCBkYXRhKSkgPiAwKSB7XG4gICAgICAgIHN1bSArPSB2O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE9wdGlvbmFsbHkgc29ydCB0aGUgYXJjcyBieSBwcmV2aW91c2x5LWNvbXB1dGVkIHZhbHVlcyBvciBieSBkYXRhLlxuICAgIGlmIChzb3J0VmFsdWVzICE9IG51bGwpIGluZGV4LnNvcnQoZnVuY3Rpb24oaSwgaikgeyByZXR1cm4gc29ydFZhbHVlcyhhcmNzW2ldLCBhcmNzW2pdKTsgfSk7XG4gICAgZWxzZSBpZiAoc29ydCAhPSBudWxsKSBpbmRleC5zb3J0KGZ1bmN0aW9uKGksIGopIHsgcmV0dXJuIHNvcnQoZGF0YVtpXSwgZGF0YVtqXSk7IH0pO1xuXG4gICAgLy8gQ29tcHV0ZSB0aGUgYXJjcyEgVGhleSBhcmUgc3RvcmVkIGluIHRoZSBvcmlnaW5hbCBkYXRhJ3Mgb3JkZXIuXG4gICAgZm9yIChpID0gMCwgayA9IHN1bSA/IChkYSAtIG4gKiBwYSkgLyBzdW0gOiAwOyBpIDwgbjsgKytpLCBhMCA9IGExKSB7XG4gICAgICBqID0gaW5kZXhbaV0sIHYgPSBhcmNzW2pdLCBhMSA9IGEwICsgKHYgPiAwID8gdiAqIGsgOiAwKSArIHBhLCBhcmNzW2pdID0ge1xuICAgICAgICBkYXRhOiBkYXRhW2pdLFxuICAgICAgICBpbmRleDogaSxcbiAgICAgICAgdmFsdWU6IHYsXG4gICAgICAgIHN0YXJ0QW5nbGU6IGEwLFxuICAgICAgICBlbmRBbmdsZTogYTEsXG4gICAgICAgIHBhZEFuZ2xlOiBwXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBhcmNzO1xuICB9XG5cbiAgcGllLnZhbHVlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIHBpZSkgOiB2YWx1ZTtcbiAgfTtcblxuICBwaWUuc29ydFZhbHVlcyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzb3J0VmFsdWVzID0gXywgc29ydCA9IG51bGwsIHBpZSkgOiBzb3J0VmFsdWVzO1xuICB9O1xuXG4gIHBpZS5zb3J0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNvcnQgPSBfLCBzb3J0VmFsdWVzID0gbnVsbCwgcGllKSA6IHNvcnQ7XG4gIH07XG5cbiAgcGllLnN0YXJ0QW5nbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3RhcnRBbmdsZSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBwaWUpIDogc3RhcnRBbmdsZTtcbiAgfTtcblxuICBwaWUuZW5kQW5nbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZW5kQW5nbGUgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgcGllKSA6IGVuZEFuZ2xlO1xuICB9O1xuXG4gIHBpZS5wYWRBbmdsZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwYWRBbmdsZSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBwaWUpIDogcGFkQW5nbGU7XG4gIH07XG5cbiAgcmV0dXJuIHBpZTtcbn1cblxudmFyIGN1cnZlUmFkaWFsTGluZWFyID0gY3VydmVSYWRpYWwoY3VydmVMaW5lYXIpO1xuXG5mdW5jdGlvbiBSYWRpYWwoY3VydmUpIHtcbiAgdGhpcy5fY3VydmUgPSBjdXJ2ZTtcbn1cblxuUmFkaWFsLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9jdXJ2ZS5hcmVhU3RhcnQoKTtcbiAgfSxcbiAgYXJlYUVuZDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fY3VydmUuYXJlYUVuZCgpO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2N1cnZlLmxpbmVTdGFydCgpO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9jdXJ2ZS5saW5lRW5kKCk7XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbihhLCByKSB7XG4gICAgdGhpcy5fY3VydmUucG9pbnQociAqIE1hdGguc2luKGEpLCByICogLU1hdGguY29zKGEpKTtcbiAgfVxufTtcblxuZnVuY3Rpb24gY3VydmVSYWRpYWwoY3VydmUpIHtcblxuICBmdW5jdGlvbiByYWRpYWwoY29udGV4dCkge1xuICAgIHJldHVybiBuZXcgUmFkaWFsKGN1cnZlKGNvbnRleHQpKTtcbiAgfVxuXG4gIHJhZGlhbC5fY3VydmUgPSBjdXJ2ZTtcblxuICByZXR1cm4gcmFkaWFsO1xufVxuXG5mdW5jdGlvbiBsaW5lUmFkaWFsKGwpIHtcbiAgdmFyIGMgPSBsLmN1cnZlO1xuXG4gIGwuYW5nbGUgPSBsLngsIGRlbGV0ZSBsLng7XG4gIGwucmFkaXVzID0gbC55LCBkZWxldGUgbC55O1xuXG4gIGwuY3VydmUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyBjKGN1cnZlUmFkaWFsKF8pKSA6IGMoKS5fY3VydmU7XG4gIH07XG5cbiAgcmV0dXJuIGw7XG59XG5cbmZ1bmN0aW9uIGxpbmVSYWRpYWwkMSgpIHtcbiAgcmV0dXJuIGxpbmVSYWRpYWwobGluZSgpLmN1cnZlKGN1cnZlUmFkaWFsTGluZWFyKSk7XG59XG5cbmZ1bmN0aW9uIGFyZWFSYWRpYWwoKSB7XG4gIHZhciBhID0gYXJlYSgpLmN1cnZlKGN1cnZlUmFkaWFsTGluZWFyKSxcbiAgICAgIGMgPSBhLmN1cnZlLFxuICAgICAgeDAgPSBhLmxpbmVYMCxcbiAgICAgIHgxID0gYS5saW5lWDEsXG4gICAgICB5MCA9IGEubGluZVkwLFxuICAgICAgeTEgPSBhLmxpbmVZMTtcblxuICBhLmFuZ2xlID0gYS54LCBkZWxldGUgYS54O1xuICBhLnN0YXJ0QW5nbGUgPSBhLngwLCBkZWxldGUgYS54MDtcbiAgYS5lbmRBbmdsZSA9IGEueDEsIGRlbGV0ZSBhLngxO1xuICBhLnJhZGl1cyA9IGEueSwgZGVsZXRlIGEueTtcbiAgYS5pbm5lclJhZGl1cyA9IGEueTAsIGRlbGV0ZSBhLnkwO1xuICBhLm91dGVyUmFkaXVzID0gYS55MSwgZGVsZXRlIGEueTE7XG4gIGEubGluZVN0YXJ0QW5nbGUgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGxpbmVSYWRpYWwoeDAoKSk7IH0sIGRlbGV0ZSBhLmxpbmVYMDtcbiAgYS5saW5lRW5kQW5nbGUgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGxpbmVSYWRpYWwoeDEoKSk7IH0sIGRlbGV0ZSBhLmxpbmVYMTtcbiAgYS5saW5lSW5uZXJSYWRpdXMgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGxpbmVSYWRpYWwoeTAoKSk7IH0sIGRlbGV0ZSBhLmxpbmVZMDtcbiAgYS5saW5lT3V0ZXJSYWRpdXMgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGxpbmVSYWRpYWwoeTEoKSk7IH0sIGRlbGV0ZSBhLmxpbmVZMTtcblxuICBhLmN1cnZlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gYyhjdXJ2ZVJhZGlhbChfKSkgOiBjKCkuX2N1cnZlO1xuICB9O1xuXG4gIHJldHVybiBhO1xufVxuXG5mdW5jdGlvbiBwb2ludFJhZGlhbCh4LCB5KSB7XG4gIHJldHVybiBbKHkgPSAreSkgKiBNYXRoLmNvcyh4IC09IE1hdGguUEkgLyAyKSwgeSAqIE1hdGguc2luKHgpXTtcbn1cblxudmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuXG5mdW5jdGlvbiBsaW5rU291cmNlKGQpIHtcbiAgcmV0dXJuIGQuc291cmNlO1xufVxuXG5mdW5jdGlvbiBsaW5rVGFyZ2V0KGQpIHtcbiAgcmV0dXJuIGQudGFyZ2V0O1xufVxuXG5mdW5jdGlvbiBsaW5rKGN1cnZlKSB7XG4gIHZhciBzb3VyY2UgPSBsaW5rU291cmNlLFxuICAgICAgdGFyZ2V0ID0gbGlua1RhcmdldCxcbiAgICAgIHgkJDEgPSB4LFxuICAgICAgeSQkMSA9IHksXG4gICAgICBjb250ZXh0ID0gbnVsbDtcblxuICBmdW5jdGlvbiBsaW5rKCkge1xuICAgIHZhciBidWZmZXIsIGFyZ3YgPSBzbGljZS5jYWxsKGFyZ3VtZW50cyksIHMgPSBzb3VyY2UuYXBwbHkodGhpcywgYXJndiksIHQgPSB0YXJnZXQuYXBwbHkodGhpcywgYXJndik7XG4gICAgaWYgKCFjb250ZXh0KSBjb250ZXh0ID0gYnVmZmVyID0gZDNQYXRoLnBhdGgoKTtcbiAgICBjdXJ2ZShjb250ZXh0LCAreCQkMS5hcHBseSh0aGlzLCAoYXJndlswXSA9IHMsIGFyZ3YpKSwgK3kkJDEuYXBwbHkodGhpcywgYXJndiksICt4JCQxLmFwcGx5KHRoaXMsIChhcmd2WzBdID0gdCwgYXJndikpLCAreSQkMS5hcHBseSh0aGlzLCBhcmd2KSk7XG4gICAgaWYgKGJ1ZmZlcikgcmV0dXJuIGNvbnRleHQgPSBudWxsLCBidWZmZXIgKyBcIlwiIHx8IG51bGw7XG4gIH1cblxuICBsaW5rLnNvdXJjZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzb3VyY2UgPSBfLCBsaW5rKSA6IHNvdXJjZTtcbiAgfTtcblxuICBsaW5rLnRhcmdldCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0YXJnZXQgPSBfLCBsaW5rKSA6IHRhcmdldDtcbiAgfTtcblxuICBsaW5rLnggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeCQkMSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBsaW5rKSA6IHgkJDE7XG4gIH07XG5cbiAgbGluay55ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHkkJDEgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgbGluaykgOiB5JCQxO1xuICB9O1xuXG4gIGxpbmsuY29udGV4dCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICgoY29udGV4dCA9IF8gPT0gbnVsbCA/IG51bGwgOiBfKSwgbGluaykgOiBjb250ZXh0O1xuICB9O1xuXG4gIHJldHVybiBsaW5rO1xufVxuXG5mdW5jdGlvbiBjdXJ2ZUhvcml6b250YWwoY29udGV4dCwgeDAsIHkwLCB4MSwgeTEpIHtcbiAgY29udGV4dC5tb3ZlVG8oeDAsIHkwKTtcbiAgY29udGV4dC5iZXppZXJDdXJ2ZVRvKHgwID0gKHgwICsgeDEpIC8gMiwgeTAsIHgwLCB5MSwgeDEsIHkxKTtcbn1cblxuZnVuY3Rpb24gY3VydmVWZXJ0aWNhbChjb250ZXh0LCB4MCwgeTAsIHgxLCB5MSkge1xuICBjb250ZXh0Lm1vdmVUbyh4MCwgeTApO1xuICBjb250ZXh0LmJlemllckN1cnZlVG8oeDAsIHkwID0gKHkwICsgeTEpIC8gMiwgeDEsIHkwLCB4MSwgeTEpO1xufVxuXG5mdW5jdGlvbiBjdXJ2ZVJhZGlhbCQxKGNvbnRleHQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gIHZhciBwMCA9IHBvaW50UmFkaWFsKHgwLCB5MCksXG4gICAgICBwMSA9IHBvaW50UmFkaWFsKHgwLCB5MCA9ICh5MCArIHkxKSAvIDIpLFxuICAgICAgcDIgPSBwb2ludFJhZGlhbCh4MSwgeTApLFxuICAgICAgcDMgPSBwb2ludFJhZGlhbCh4MSwgeTEpO1xuICBjb250ZXh0Lm1vdmVUbyhwMFswXSwgcDBbMV0pO1xuICBjb250ZXh0LmJlemllckN1cnZlVG8ocDFbMF0sIHAxWzFdLCBwMlswXSwgcDJbMV0sIHAzWzBdLCBwM1sxXSk7XG59XG5cbmZ1bmN0aW9uIGxpbmtIb3Jpem9udGFsKCkge1xuICByZXR1cm4gbGluayhjdXJ2ZUhvcml6b250YWwpO1xufVxuXG5mdW5jdGlvbiBsaW5rVmVydGljYWwoKSB7XG4gIHJldHVybiBsaW5rKGN1cnZlVmVydGljYWwpO1xufVxuXG5mdW5jdGlvbiBsaW5rUmFkaWFsKCkge1xuICB2YXIgbCA9IGxpbmsoY3VydmVSYWRpYWwkMSk7XG4gIGwuYW5nbGUgPSBsLngsIGRlbGV0ZSBsLng7XG4gIGwucmFkaXVzID0gbC55LCBkZWxldGUgbC55O1xuICByZXR1cm4gbDtcbn1cblxudmFyIGNpcmNsZSA9IHtcbiAgZHJhdzogZnVuY3Rpb24oY29udGV4dCwgc2l6ZSkge1xuICAgIHZhciByID0gTWF0aC5zcXJ0KHNpemUgLyBwaSk7XG4gICAgY29udGV4dC5tb3ZlVG8ociwgMCk7XG4gICAgY29udGV4dC5hcmMoMCwgMCwgciwgMCwgdGF1KTtcbiAgfVxufTtcblxudmFyIGNyb3NzID0ge1xuICBkcmF3OiBmdW5jdGlvbihjb250ZXh0LCBzaXplKSB7XG4gICAgdmFyIHIgPSBNYXRoLnNxcnQoc2l6ZSAvIDUpIC8gMjtcbiAgICBjb250ZXh0Lm1vdmVUbygtMyAqIHIsIC1yKTtcbiAgICBjb250ZXh0LmxpbmVUbygtciwgLXIpO1xuICAgIGNvbnRleHQubGluZVRvKC1yLCAtMyAqIHIpO1xuICAgIGNvbnRleHQubGluZVRvKHIsIC0zICogcik7XG4gICAgY29udGV4dC5saW5lVG8ociwgLXIpO1xuICAgIGNvbnRleHQubGluZVRvKDMgKiByLCAtcik7XG4gICAgY29udGV4dC5saW5lVG8oMyAqIHIsIHIpO1xuICAgIGNvbnRleHQubGluZVRvKHIsIHIpO1xuICAgIGNvbnRleHQubGluZVRvKHIsIDMgKiByKTtcbiAgICBjb250ZXh0LmxpbmVUbygtciwgMyAqIHIpO1xuICAgIGNvbnRleHQubGluZVRvKC1yLCByKTtcbiAgICBjb250ZXh0LmxpbmVUbygtMyAqIHIsIHIpO1xuICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG4gIH1cbn07XG5cbnZhciB0YW4zMCA9IE1hdGguc3FydCgxIC8gMyksXG4gICAgdGFuMzBfMiA9IHRhbjMwICogMjtcblxudmFyIGRpYW1vbmQgPSB7XG4gIGRyYXc6IGZ1bmN0aW9uKGNvbnRleHQsIHNpemUpIHtcbiAgICB2YXIgeSA9IE1hdGguc3FydChzaXplIC8gdGFuMzBfMiksXG4gICAgICAgIHggPSB5ICogdGFuMzA7XG4gICAgY29udGV4dC5tb3ZlVG8oMCwgLXkpO1xuICAgIGNvbnRleHQubGluZVRvKHgsIDApO1xuICAgIGNvbnRleHQubGluZVRvKDAsIHkpO1xuICAgIGNvbnRleHQubGluZVRvKC14LCAwKTtcbiAgICBjb250ZXh0LmNsb3NlUGF0aCgpO1xuICB9XG59O1xuXG52YXIga2EgPSAwLjg5MDgxMzA5MTUyOTI4NTIyODEwLFxuICAgIGtyID0gTWF0aC5zaW4ocGkgLyAxMCkgLyBNYXRoLnNpbig3ICogcGkgLyAxMCksXG4gICAga3ggPSBNYXRoLnNpbih0YXUgLyAxMCkgKiBrcixcbiAgICBreSA9IC1NYXRoLmNvcyh0YXUgLyAxMCkgKiBrcjtcblxudmFyIHN0YXIgPSB7XG4gIGRyYXc6IGZ1bmN0aW9uKGNvbnRleHQsIHNpemUpIHtcbiAgICB2YXIgciA9IE1hdGguc3FydChzaXplICoga2EpLFxuICAgICAgICB4ID0ga3ggKiByLFxuICAgICAgICB5ID0ga3kgKiByO1xuICAgIGNvbnRleHQubW92ZVRvKDAsIC1yKTtcbiAgICBjb250ZXh0LmxpbmVUbyh4LCB5KTtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8IDU7ICsraSkge1xuICAgICAgdmFyIGEgPSB0YXUgKiBpIC8gNSxcbiAgICAgICAgICBjID0gTWF0aC5jb3MoYSksXG4gICAgICAgICAgcyA9IE1hdGguc2luKGEpO1xuICAgICAgY29udGV4dC5saW5lVG8ocyAqIHIsIC1jICogcik7XG4gICAgICBjb250ZXh0LmxpbmVUbyhjICogeCAtIHMgKiB5LCBzICogeCArIGMgKiB5KTtcbiAgICB9XG4gICAgY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgfVxufTtcblxudmFyIHNxdWFyZSA9IHtcbiAgZHJhdzogZnVuY3Rpb24oY29udGV4dCwgc2l6ZSkge1xuICAgIHZhciB3ID0gTWF0aC5zcXJ0KHNpemUpLFxuICAgICAgICB4ID0gLXcgLyAyO1xuICAgIGNvbnRleHQucmVjdCh4LCB4LCB3LCB3KTtcbiAgfVxufTtcblxudmFyIHNxcnQzID0gTWF0aC5zcXJ0KDMpO1xuXG52YXIgdHJpYW5nbGUgPSB7XG4gIGRyYXc6IGZ1bmN0aW9uKGNvbnRleHQsIHNpemUpIHtcbiAgICB2YXIgeSA9IC1NYXRoLnNxcnQoc2l6ZSAvIChzcXJ0MyAqIDMpKTtcbiAgICBjb250ZXh0Lm1vdmVUbygwLCB5ICogMik7XG4gICAgY29udGV4dC5saW5lVG8oLXNxcnQzICogeSwgLXkpO1xuICAgIGNvbnRleHQubGluZVRvKHNxcnQzICogeSwgLXkpO1xuICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG4gIH1cbn07XG5cbnZhciBjID0gLTAuNSxcbiAgICBzID0gTWF0aC5zcXJ0KDMpIC8gMixcbiAgICBrID0gMSAvIE1hdGguc3FydCgxMiksXG4gICAgYSA9IChrIC8gMiArIDEpICogMztcblxudmFyIHd5ZSA9IHtcbiAgZHJhdzogZnVuY3Rpb24oY29udGV4dCwgc2l6ZSkge1xuICAgIHZhciByID0gTWF0aC5zcXJ0KHNpemUgLyBhKSxcbiAgICAgICAgeDAgPSByIC8gMixcbiAgICAgICAgeTAgPSByICogayxcbiAgICAgICAgeDEgPSB4MCxcbiAgICAgICAgeTEgPSByICogayArIHIsXG4gICAgICAgIHgyID0gLXgxLFxuICAgICAgICB5MiA9IHkxO1xuICAgIGNvbnRleHQubW92ZVRvKHgwLCB5MCk7XG4gICAgY29udGV4dC5saW5lVG8oeDEsIHkxKTtcbiAgICBjb250ZXh0LmxpbmVUbyh4MiwgeTIpO1xuICAgIGNvbnRleHQubGluZVRvKGMgKiB4MCAtIHMgKiB5MCwgcyAqIHgwICsgYyAqIHkwKTtcbiAgICBjb250ZXh0LmxpbmVUbyhjICogeDEgLSBzICogeTEsIHMgKiB4MSArIGMgKiB5MSk7XG4gICAgY29udGV4dC5saW5lVG8oYyAqIHgyIC0gcyAqIHkyLCBzICogeDIgKyBjICogeTIpO1xuICAgIGNvbnRleHQubGluZVRvKGMgKiB4MCArIHMgKiB5MCwgYyAqIHkwIC0gcyAqIHgwKTtcbiAgICBjb250ZXh0LmxpbmVUbyhjICogeDEgKyBzICogeTEsIGMgKiB5MSAtIHMgKiB4MSk7XG4gICAgY29udGV4dC5saW5lVG8oYyAqIHgyICsgcyAqIHkyLCBjICogeTIgLSBzICogeDIpO1xuICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG4gIH1cbn07XG5cbnZhciBzeW1ib2xzID0gW1xuICBjaXJjbGUsXG4gIGNyb3NzLFxuICBkaWFtb25kLFxuICBzcXVhcmUsXG4gIHN0YXIsXG4gIHRyaWFuZ2xlLFxuICB3eWVcbl07XG5cbmZ1bmN0aW9uIHN5bWJvbCgpIHtcbiAgdmFyIHR5cGUgPSBjb25zdGFudChjaXJjbGUpLFxuICAgICAgc2l6ZSA9IGNvbnN0YW50KDY0KSxcbiAgICAgIGNvbnRleHQgPSBudWxsO1xuXG4gIGZ1bmN0aW9uIHN5bWJvbCgpIHtcbiAgICB2YXIgYnVmZmVyO1xuICAgIGlmICghY29udGV4dCkgY29udGV4dCA9IGJ1ZmZlciA9IGQzUGF0aC5wYXRoKCk7XG4gICAgdHlwZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpLmRyYXcoY29udGV4dCwgK3NpemUuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gICAgaWYgKGJ1ZmZlcikgcmV0dXJuIGNvbnRleHQgPSBudWxsLCBidWZmZXIgKyBcIlwiIHx8IG51bGw7XG4gIH1cblxuICBzeW1ib2wudHlwZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0eXBlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChfKSwgc3ltYm9sKSA6IHR5cGU7XG4gIH07XG5cbiAgc3ltYm9sLnNpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2l6ZSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBzeW1ib2wpIDogc2l6ZTtcbiAgfTtcblxuICBzeW1ib2wuY29udGV4dCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb250ZXh0ID0gXyA9PSBudWxsID8gbnVsbCA6IF8sIHN5bWJvbCkgOiBjb250ZXh0O1xuICB9O1xuXG4gIHJldHVybiBzeW1ib2w7XG59XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG5mdW5jdGlvbiBwb2ludCh0aGF0LCB4LCB5KSB7XG4gIHRoYXQuX2NvbnRleHQuYmV6aWVyQ3VydmVUbyhcbiAgICAoMiAqIHRoYXQuX3gwICsgdGhhdC5feDEpIC8gMyxcbiAgICAoMiAqIHRoYXQuX3kwICsgdGhhdC5feTEpIC8gMyxcbiAgICAodGhhdC5feDAgKyAyICogdGhhdC5feDEpIC8gMyxcbiAgICAodGhhdC5feTAgKyAyICogdGhhdC5feTEpIC8gMyxcbiAgICAodGhhdC5feDAgKyA0ICogdGhhdC5feDEgKyB4KSAvIDYsXG4gICAgKHRoYXQuX3kwICsgNCAqIHRoYXQuX3kxICsgeSkgLyA2XG4gICk7XG59XG5cbmZ1bmN0aW9uIEJhc2lzKGNvbnRleHQpIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG59XG5cbkJhc2lzLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gMDtcbiAgfSxcbiAgYXJlYUVuZDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IE5hTjtcbiAgfSxcbiAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxID1cbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxID0gTmFOO1xuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAzOiBwb2ludCh0aGlzLCB0aGlzLl94MSwgdGhpcy5feTEpOyAvLyBwcm9jZWVkXG4gICAgICBjYXNlIDI6IHRoaXMuX2NvbnRleHQubGluZVRvKHRoaXMuX3gxLCB0aGlzLl95MSk7IGJyZWFrO1xuICAgIH1cbiAgICBpZiAodGhpcy5fbGluZSB8fCAodGhpcy5fbGluZSAhPT0gMCAmJiB0aGlzLl9wb2ludCA9PT0gMSkpIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgdGhpcy5fbGluZSA9IDEgLSB0aGlzLl9saW5lO1xuICB9LFxuICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgIHggPSAreCwgeSA9ICt5O1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyB0aGlzLl9saW5lID8gdGhpcy5fY29udGV4dC5saW5lVG8oeCwgeSkgOiB0aGlzLl9jb250ZXh0Lm1vdmVUbyh4LCB5KTsgYnJlYWs7XG4gICAgICBjYXNlIDE6IHRoaXMuX3BvaW50ID0gMjsgYnJlYWs7XG4gICAgICBjYXNlIDI6IHRoaXMuX3BvaW50ID0gMzsgdGhpcy5fY29udGV4dC5saW5lVG8oKDUgKiB0aGlzLl94MCArIHRoaXMuX3gxKSAvIDYsICg1ICogdGhpcy5feTAgKyB0aGlzLl95MSkgLyA2KTsgLy8gcHJvY2VlZFxuICAgICAgZGVmYXVsdDogcG9pbnQodGhpcywgeCwgeSk7IGJyZWFrO1xuICAgIH1cbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxLCB0aGlzLl94MSA9IHg7XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSwgdGhpcy5feTEgPSB5O1xuICB9XG59O1xuXG5mdW5jdGlvbiBiYXNpcyhjb250ZXh0KSB7XG4gIHJldHVybiBuZXcgQmFzaXMoY29udGV4dCk7XG59XG5cbmZ1bmN0aW9uIEJhc2lzQ2xvc2VkKGNvbnRleHQpIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG59XG5cbkJhc2lzQ2xvc2VkLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBub29wLFxuICBhcmVhRW5kOiBub29wLFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPSB0aGlzLl94MiA9IHRoaXMuX3gzID0gdGhpcy5feDQgPVxuICAgIHRoaXMuX3kwID0gdGhpcy5feTEgPSB0aGlzLl95MiA9IHRoaXMuX3kzID0gdGhpcy5feTQgPSBOYU47XG4gICAgdGhpcy5fcG9pbnQgPSAwO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDE6IHtcbiAgICAgICAgdGhpcy5fY29udGV4dC5tb3ZlVG8odGhpcy5feDIsIHRoaXMuX3kyKTtcbiAgICAgICAgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIDI6IHtcbiAgICAgICAgdGhpcy5fY29udGV4dC5tb3ZlVG8oKHRoaXMuX3gyICsgMiAqIHRoaXMuX3gzKSAvIDMsICh0aGlzLl95MiArIDIgKiB0aGlzLl95MykgLyAzKTtcbiAgICAgICAgdGhpcy5fY29udGV4dC5saW5lVG8oKHRoaXMuX3gzICsgMiAqIHRoaXMuX3gyKSAvIDMsICh0aGlzLl95MyArIDIgKiB0aGlzLl95MikgLyAzKTtcbiAgICAgICAgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIDM6IHtcbiAgICAgICAgdGhpcy5wb2ludCh0aGlzLl94MiwgdGhpcy5feTIpO1xuICAgICAgICB0aGlzLnBvaW50KHRoaXMuX3gzLCB0aGlzLl95Myk7XG4gICAgICAgIHRoaXMucG9pbnQodGhpcy5feDQsIHRoaXMuX3k0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9LFxuICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgIHggPSAreCwgeSA9ICt5O1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyB0aGlzLl94MiA9IHgsIHRoaXMuX3kyID0geTsgYnJlYWs7XG4gICAgICBjYXNlIDE6IHRoaXMuX3BvaW50ID0gMjsgdGhpcy5feDMgPSB4LCB0aGlzLl95MyA9IHk7IGJyZWFrO1xuICAgICAgY2FzZSAyOiB0aGlzLl9wb2ludCA9IDM7IHRoaXMuX3g0ID0geCwgdGhpcy5feTQgPSB5OyB0aGlzLl9jb250ZXh0Lm1vdmVUbygodGhpcy5feDAgKyA0ICogdGhpcy5feDEgKyB4KSAvIDYsICh0aGlzLl95MCArIDQgKiB0aGlzLl95MSArIHkpIC8gNik7IGJyZWFrO1xuICAgICAgZGVmYXVsdDogcG9pbnQodGhpcywgeCwgeSk7IGJyZWFrO1xuICAgIH1cbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxLCB0aGlzLl94MSA9IHg7XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSwgdGhpcy5feTEgPSB5O1xuICB9XG59O1xuXG5mdW5jdGlvbiBiYXNpc0Nsb3NlZChjb250ZXh0KSB7XG4gIHJldHVybiBuZXcgQmFzaXNDbG9zZWQoY29udGV4dCk7XG59XG5cbmZ1bmN0aW9uIEJhc2lzT3Blbihjb250ZXh0KSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xufVxuXG5CYXNpc09wZW4ucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSAwO1xuICB9LFxuICBhcmVhRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gTmFOO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPVxuICAgIHRoaXMuX3kwID0gdGhpcy5feTEgPSBOYU47XG4gICAgdGhpcy5fcG9pbnQgPSAwO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5fbGluZSB8fCAodGhpcy5fbGluZSAhPT0gMCAmJiB0aGlzLl9wb2ludCA9PT0gMykpIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgdGhpcy5fbGluZSA9IDEgLSB0aGlzLl9saW5lO1xuICB9LFxuICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgIHggPSAreCwgeSA9ICt5O1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyBicmVhaztcbiAgICAgIGNhc2UgMTogdGhpcy5fcG9pbnQgPSAyOyBicmVhaztcbiAgICAgIGNhc2UgMjogdGhpcy5fcG9pbnQgPSAzOyB2YXIgeDAgPSAodGhpcy5feDAgKyA0ICogdGhpcy5feDEgKyB4KSAvIDYsIHkwID0gKHRoaXMuX3kwICsgNCAqIHRoaXMuX3kxICsgeSkgLyA2OyB0aGlzLl9saW5lID8gdGhpcy5fY29udGV4dC5saW5lVG8oeDAsIHkwKSA6IHRoaXMuX2NvbnRleHQubW92ZVRvKHgwLCB5MCk7IGJyZWFrO1xuICAgICAgY2FzZSAzOiB0aGlzLl9wb2ludCA9IDQ7IC8vIHByb2NlZWRcbiAgICAgIGRlZmF1bHQ6IHBvaW50KHRoaXMsIHgsIHkpOyBicmVhaztcbiAgICB9XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSwgdGhpcy5feDEgPSB4O1xuICAgIHRoaXMuX3kwID0gdGhpcy5feTEsIHRoaXMuX3kxID0geTtcbiAgfVxufTtcblxuZnVuY3Rpb24gYmFzaXNPcGVuKGNvbnRleHQpIHtcbiAgcmV0dXJuIG5ldyBCYXNpc09wZW4oY29udGV4dCk7XG59XG5cbmZ1bmN0aW9uIEJ1bmRsZShjb250ZXh0LCBiZXRhKSB7XG4gIHRoaXMuX2Jhc2lzID0gbmV3IEJhc2lzKGNvbnRleHQpO1xuICB0aGlzLl9iZXRhID0gYmV0YTtcbn1cblxuQnVuZGxlLnByb3RvdHlwZSA9IHtcbiAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl94ID0gW107XG4gICAgdGhpcy5feSA9IFtdO1xuICAgIHRoaXMuX2Jhc2lzLmxpbmVTdGFydCgpO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgeCA9IHRoaXMuX3gsXG4gICAgICAgIHkgPSB0aGlzLl95LFxuICAgICAgICBqID0geC5sZW5ndGggLSAxO1xuXG4gICAgaWYgKGogPiAwKSB7XG4gICAgICB2YXIgeDAgPSB4WzBdLFxuICAgICAgICAgIHkwID0geVswXSxcbiAgICAgICAgICBkeCA9IHhbal0gLSB4MCxcbiAgICAgICAgICBkeSA9IHlbal0gLSB5MCxcbiAgICAgICAgICBpID0gLTEsXG4gICAgICAgICAgdDtcblxuICAgICAgd2hpbGUgKCsraSA8PSBqKSB7XG4gICAgICAgIHQgPSBpIC8gajtcbiAgICAgICAgdGhpcy5fYmFzaXMucG9pbnQoXG4gICAgICAgICAgdGhpcy5fYmV0YSAqIHhbaV0gKyAoMSAtIHRoaXMuX2JldGEpICogKHgwICsgdCAqIGR4KSxcbiAgICAgICAgICB0aGlzLl9iZXRhICogeVtpXSArICgxIC0gdGhpcy5fYmV0YSkgKiAoeTAgKyB0ICogZHkpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5feCA9IHRoaXMuX3kgPSBudWxsO1xuICAgIHRoaXMuX2Jhc2lzLmxpbmVFbmQoKTtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB0aGlzLl94LnB1c2goK3gpO1xuICAgIHRoaXMuX3kucHVzaCgreSk7XG4gIH1cbn07XG5cbnZhciBidW5kbGUgPSAoZnVuY3Rpb24gY3VzdG9tKGJldGEpIHtcblxuICBmdW5jdGlvbiBidW5kbGUoY29udGV4dCkge1xuICAgIHJldHVybiBiZXRhID09PSAxID8gbmV3IEJhc2lzKGNvbnRleHQpIDogbmV3IEJ1bmRsZShjb250ZXh0LCBiZXRhKTtcbiAgfVxuXG4gIGJ1bmRsZS5iZXRhID0gZnVuY3Rpb24oYmV0YSkge1xuICAgIHJldHVybiBjdXN0b20oK2JldGEpO1xuICB9O1xuXG4gIHJldHVybiBidW5kbGU7XG59KSgwLjg1KTtcblxuZnVuY3Rpb24gcG9pbnQkMSh0aGF0LCB4LCB5KSB7XG4gIHRoYXQuX2NvbnRleHQuYmV6aWVyQ3VydmVUbyhcbiAgICB0aGF0Ll94MSArIHRoYXQuX2sgKiAodGhhdC5feDIgLSB0aGF0Ll94MCksXG4gICAgdGhhdC5feTEgKyB0aGF0Ll9rICogKHRoYXQuX3kyIC0gdGhhdC5feTApLFxuICAgIHRoYXQuX3gyICsgdGhhdC5fayAqICh0aGF0Ll94MSAtIHgpLFxuICAgIHRoYXQuX3kyICsgdGhhdC5fayAqICh0aGF0Ll95MSAtIHkpLFxuICAgIHRoYXQuX3gyLFxuICAgIHRoYXQuX3kyXG4gICk7XG59XG5cbmZ1bmN0aW9uIENhcmRpbmFsKGNvbnRleHQsIHRlbnNpb24pIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG4gIHRoaXMuX2sgPSAoMSAtIHRlbnNpb24pIC8gNjtcbn1cblxuQ2FyZGluYWwucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSAwO1xuICB9LFxuICBhcmVhRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gTmFOO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPSB0aGlzLl94MiA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9IHRoaXMuX3kyID0gTmFOO1xuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAyOiB0aGlzLl9jb250ZXh0LmxpbmVUbyh0aGlzLl94MiwgdGhpcy5feTIpOyBicmVhaztcbiAgICAgIGNhc2UgMzogcG9pbnQkMSh0aGlzLCB0aGlzLl94MSwgdGhpcy5feTEpOyBicmVhaztcbiAgICB9XG4gICAgaWYgKHRoaXMuX2xpbmUgfHwgKHRoaXMuX2xpbmUgIT09IDAgJiYgdGhpcy5fcG9pbnQgPT09IDEpKSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgIHRoaXMuX2xpbmUgPSAxIC0gdGhpcy5fbGluZTtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB4ID0gK3gsIHkgPSAreTtcbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDA6IHRoaXMuX3BvaW50ID0gMTsgdGhpcy5fbGluZSA/IHRoaXMuX2NvbnRleHQubGluZVRvKHgsIHkpIDogdGhpcy5fY29udGV4dC5tb3ZlVG8oeCwgeSk7IGJyZWFrO1xuICAgICAgY2FzZSAxOiB0aGlzLl9wb2ludCA9IDI7IHRoaXMuX3gxID0geCwgdGhpcy5feTEgPSB5OyBicmVhaztcbiAgICAgIGNhc2UgMjogdGhpcy5fcG9pbnQgPSAzOyAvLyBwcm9jZWVkXG4gICAgICBkZWZhdWx0OiBwb2ludCQxKHRoaXMsIHgsIHkpOyBicmVhaztcbiAgICB9XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSwgdGhpcy5feDEgPSB0aGlzLl94MiwgdGhpcy5feDIgPSB4O1xuICAgIHRoaXMuX3kwID0gdGhpcy5feTEsIHRoaXMuX3kxID0gdGhpcy5feTIsIHRoaXMuX3kyID0geTtcbiAgfVxufTtcblxudmFyIGNhcmRpbmFsID0gKGZ1bmN0aW9uIGN1c3RvbSh0ZW5zaW9uKSB7XG5cbiAgZnVuY3Rpb24gY2FyZGluYWwoY29udGV4dCkge1xuICAgIHJldHVybiBuZXcgQ2FyZGluYWwoY29udGV4dCwgdGVuc2lvbik7XG4gIH1cblxuICBjYXJkaW5hbC50ZW5zaW9uID0gZnVuY3Rpb24odGVuc2lvbikge1xuICAgIHJldHVybiBjdXN0b20oK3RlbnNpb24pO1xuICB9O1xuXG4gIHJldHVybiBjYXJkaW5hbDtcbn0pKDApO1xuXG5mdW5jdGlvbiBDYXJkaW5hbENsb3NlZChjb250ZXh0LCB0ZW5zaW9uKSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xuICB0aGlzLl9rID0gKDEgLSB0ZW5zaW9uKSAvIDY7XG59XG5cbkNhcmRpbmFsQ2xvc2VkLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBub29wLFxuICBhcmVhRW5kOiBub29wLFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPSB0aGlzLl94MiA9IHRoaXMuX3gzID0gdGhpcy5feDQgPSB0aGlzLl94NSA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9IHRoaXMuX3kyID0gdGhpcy5feTMgPSB0aGlzLl95NCA9IHRoaXMuX3k1ID0gTmFOO1xuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAxOiB7XG4gICAgICAgIHRoaXMuX2NvbnRleHQubW92ZVRvKHRoaXMuX3gzLCB0aGlzLl95Myk7XG4gICAgICAgIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAyOiB7XG4gICAgICAgIHRoaXMuX2NvbnRleHQubGluZVRvKHRoaXMuX3gzLCB0aGlzLl95Myk7XG4gICAgICAgIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAzOiB7XG4gICAgICAgIHRoaXMucG9pbnQodGhpcy5feDMsIHRoaXMuX3kzKTtcbiAgICAgICAgdGhpcy5wb2ludCh0aGlzLl94NCwgdGhpcy5feTQpO1xuICAgICAgICB0aGlzLnBvaW50KHRoaXMuX3g1LCB0aGlzLl95NSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB4ID0gK3gsIHkgPSAreTtcbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDA6IHRoaXMuX3BvaW50ID0gMTsgdGhpcy5feDMgPSB4LCB0aGlzLl95MyA9IHk7IGJyZWFrO1xuICAgICAgY2FzZSAxOiB0aGlzLl9wb2ludCA9IDI7IHRoaXMuX2NvbnRleHQubW92ZVRvKHRoaXMuX3g0ID0geCwgdGhpcy5feTQgPSB5KTsgYnJlYWs7XG4gICAgICBjYXNlIDI6IHRoaXMuX3BvaW50ID0gMzsgdGhpcy5feDUgPSB4LCB0aGlzLl95NSA9IHk7IGJyZWFrO1xuICAgICAgZGVmYXVsdDogcG9pbnQkMSh0aGlzLCB4LCB5KTsgYnJlYWs7XG4gICAgfVxuICAgIHRoaXMuX3gwID0gdGhpcy5feDEsIHRoaXMuX3gxID0gdGhpcy5feDIsIHRoaXMuX3gyID0geDtcbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxLCB0aGlzLl95MSA9IHRoaXMuX3kyLCB0aGlzLl95MiA9IHk7XG4gIH1cbn07XG5cbnZhciBjYXJkaW5hbENsb3NlZCA9IChmdW5jdGlvbiBjdXN0b20odGVuc2lvbikge1xuXG4gIGZ1bmN0aW9uIGNhcmRpbmFsJCQxKGNvbnRleHQpIHtcbiAgICByZXR1cm4gbmV3IENhcmRpbmFsQ2xvc2VkKGNvbnRleHQsIHRlbnNpb24pO1xuICB9XG5cbiAgY2FyZGluYWwkJDEudGVuc2lvbiA9IGZ1bmN0aW9uKHRlbnNpb24pIHtcbiAgICByZXR1cm4gY3VzdG9tKCt0ZW5zaW9uKTtcbiAgfTtcblxuICByZXR1cm4gY2FyZGluYWwkJDE7XG59KSgwKTtcblxuZnVuY3Rpb24gQ2FyZGluYWxPcGVuKGNvbnRleHQsIHRlbnNpb24pIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG4gIHRoaXMuX2sgPSAoMSAtIHRlbnNpb24pIC8gNjtcbn1cblxuQ2FyZGluYWxPcGVuLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gMDtcbiAgfSxcbiAgYXJlYUVuZDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IE5hTjtcbiAgfSxcbiAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxID0gdGhpcy5feDIgPVxuICAgIHRoaXMuX3kwID0gdGhpcy5feTEgPSB0aGlzLl95MiA9IE5hTjtcbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLl9saW5lIHx8ICh0aGlzLl9saW5lICE9PSAwICYmIHRoaXMuX3BvaW50ID09PSAzKSkgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICB0aGlzLl9saW5lID0gMSAtIHRoaXMuX2xpbmU7XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgeCA9ICt4LCB5ID0gK3k7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAwOiB0aGlzLl9wb2ludCA9IDE7IGJyZWFrO1xuICAgICAgY2FzZSAxOiB0aGlzLl9wb2ludCA9IDI7IGJyZWFrO1xuICAgICAgY2FzZSAyOiB0aGlzLl9wb2ludCA9IDM7IHRoaXMuX2xpbmUgPyB0aGlzLl9jb250ZXh0LmxpbmVUbyh0aGlzLl94MiwgdGhpcy5feTIpIDogdGhpcy5fY29udGV4dC5tb3ZlVG8odGhpcy5feDIsIHRoaXMuX3kyKTsgYnJlYWs7XG4gICAgICBjYXNlIDM6IHRoaXMuX3BvaW50ID0gNDsgLy8gcHJvY2VlZFxuICAgICAgZGVmYXVsdDogcG9pbnQkMSh0aGlzLCB4LCB5KTsgYnJlYWs7XG4gICAgfVxuICAgIHRoaXMuX3gwID0gdGhpcy5feDEsIHRoaXMuX3gxID0gdGhpcy5feDIsIHRoaXMuX3gyID0geDtcbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxLCB0aGlzLl95MSA9IHRoaXMuX3kyLCB0aGlzLl95MiA9IHk7XG4gIH1cbn07XG5cbnZhciBjYXJkaW5hbE9wZW4gPSAoZnVuY3Rpb24gY3VzdG9tKHRlbnNpb24pIHtcblxuICBmdW5jdGlvbiBjYXJkaW5hbCQkMShjb250ZXh0KSB7XG4gICAgcmV0dXJuIG5ldyBDYXJkaW5hbE9wZW4oY29udGV4dCwgdGVuc2lvbik7XG4gIH1cblxuICBjYXJkaW5hbCQkMS50ZW5zaW9uID0gZnVuY3Rpb24odGVuc2lvbikge1xuICAgIHJldHVybiBjdXN0b20oK3RlbnNpb24pO1xuICB9O1xuXG4gIHJldHVybiBjYXJkaW5hbCQkMTtcbn0pKDApO1xuXG5mdW5jdGlvbiBwb2ludCQyKHRoYXQsIHgsIHkpIHtcbiAgdmFyIHgxID0gdGhhdC5feDEsXG4gICAgICB5MSA9IHRoYXQuX3kxLFxuICAgICAgeDIgPSB0aGF0Ll94MixcbiAgICAgIHkyID0gdGhhdC5feTI7XG5cbiAgaWYgKHRoYXQuX2wwMV9hID4gZXBzaWxvbikge1xuICAgIHZhciBhID0gMiAqIHRoYXQuX2wwMV8yYSArIDMgKiB0aGF0Ll9sMDFfYSAqIHRoYXQuX2wxMl9hICsgdGhhdC5fbDEyXzJhLFxuICAgICAgICBuID0gMyAqIHRoYXQuX2wwMV9hICogKHRoYXQuX2wwMV9hICsgdGhhdC5fbDEyX2EpO1xuICAgIHgxID0gKHgxICogYSAtIHRoYXQuX3gwICogdGhhdC5fbDEyXzJhICsgdGhhdC5feDIgKiB0aGF0Ll9sMDFfMmEpIC8gbjtcbiAgICB5MSA9ICh5MSAqIGEgLSB0aGF0Ll95MCAqIHRoYXQuX2wxMl8yYSArIHRoYXQuX3kyICogdGhhdC5fbDAxXzJhKSAvIG47XG4gIH1cblxuICBpZiAodGhhdC5fbDIzX2EgPiBlcHNpbG9uKSB7XG4gICAgdmFyIGIgPSAyICogdGhhdC5fbDIzXzJhICsgMyAqIHRoYXQuX2wyM19hICogdGhhdC5fbDEyX2EgKyB0aGF0Ll9sMTJfMmEsXG4gICAgICAgIG0gPSAzICogdGhhdC5fbDIzX2EgKiAodGhhdC5fbDIzX2EgKyB0aGF0Ll9sMTJfYSk7XG4gICAgeDIgPSAoeDIgKiBiICsgdGhhdC5feDEgKiB0aGF0Ll9sMjNfMmEgLSB4ICogdGhhdC5fbDEyXzJhKSAvIG07XG4gICAgeTIgPSAoeTIgKiBiICsgdGhhdC5feTEgKiB0aGF0Ll9sMjNfMmEgLSB5ICogdGhhdC5fbDEyXzJhKSAvIG07XG4gIH1cblxuICB0aGF0Ll9jb250ZXh0LmJlemllckN1cnZlVG8oeDEsIHkxLCB4MiwgeTIsIHRoYXQuX3gyLCB0aGF0Ll95Mik7XG59XG5cbmZ1bmN0aW9uIENhdG11bGxSb20oY29udGV4dCwgYWxwaGEpIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG4gIHRoaXMuX2FscGhhID0gYWxwaGE7XG59XG5cbkNhdG11bGxSb20ucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSAwO1xuICB9LFxuICBhcmVhRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gTmFOO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPSB0aGlzLl94MiA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9IHRoaXMuX3kyID0gTmFOO1xuICAgIHRoaXMuX2wwMV9hID0gdGhpcy5fbDEyX2EgPSB0aGlzLl9sMjNfYSA9XG4gICAgdGhpcy5fbDAxXzJhID0gdGhpcy5fbDEyXzJhID0gdGhpcy5fbDIzXzJhID1cbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMjogdGhpcy5fY29udGV4dC5saW5lVG8odGhpcy5feDIsIHRoaXMuX3kyKTsgYnJlYWs7XG4gICAgICBjYXNlIDM6IHRoaXMucG9pbnQodGhpcy5feDIsIHRoaXMuX3kyKTsgYnJlYWs7XG4gICAgfVxuICAgIGlmICh0aGlzLl9saW5lIHx8ICh0aGlzLl9saW5lICE9PSAwICYmIHRoaXMuX3BvaW50ID09PSAxKSkgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICB0aGlzLl9saW5lID0gMSAtIHRoaXMuX2xpbmU7XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgeCA9ICt4LCB5ID0gK3k7XG5cbiAgICBpZiAodGhpcy5fcG9pbnQpIHtcbiAgICAgIHZhciB4MjMgPSB0aGlzLl94MiAtIHgsXG4gICAgICAgICAgeTIzID0gdGhpcy5feTIgLSB5O1xuICAgICAgdGhpcy5fbDIzX2EgPSBNYXRoLnNxcnQodGhpcy5fbDIzXzJhID0gTWF0aC5wb3coeDIzICogeDIzICsgeTIzICogeTIzLCB0aGlzLl9hbHBoYSkpO1xuICAgIH1cblxuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyB0aGlzLl9saW5lID8gdGhpcy5fY29udGV4dC5saW5lVG8oeCwgeSkgOiB0aGlzLl9jb250ZXh0Lm1vdmVUbyh4LCB5KTsgYnJlYWs7XG4gICAgICBjYXNlIDE6IHRoaXMuX3BvaW50ID0gMjsgYnJlYWs7XG4gICAgICBjYXNlIDI6IHRoaXMuX3BvaW50ID0gMzsgLy8gcHJvY2VlZFxuICAgICAgZGVmYXVsdDogcG9pbnQkMih0aGlzLCB4LCB5KTsgYnJlYWs7XG4gICAgfVxuXG4gICAgdGhpcy5fbDAxX2EgPSB0aGlzLl9sMTJfYSwgdGhpcy5fbDEyX2EgPSB0aGlzLl9sMjNfYTtcbiAgICB0aGlzLl9sMDFfMmEgPSB0aGlzLl9sMTJfMmEsIHRoaXMuX2wxMl8yYSA9IHRoaXMuX2wyM18yYTtcbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxLCB0aGlzLl94MSA9IHRoaXMuX3gyLCB0aGlzLl94MiA9IHg7XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSwgdGhpcy5feTEgPSB0aGlzLl95MiwgdGhpcy5feTIgPSB5O1xuICB9XG59O1xuXG52YXIgY2F0bXVsbFJvbSA9IChmdW5jdGlvbiBjdXN0b20oYWxwaGEpIHtcblxuICBmdW5jdGlvbiBjYXRtdWxsUm9tKGNvbnRleHQpIHtcbiAgICByZXR1cm4gYWxwaGEgPyBuZXcgQ2F0bXVsbFJvbShjb250ZXh0LCBhbHBoYSkgOiBuZXcgQ2FyZGluYWwoY29udGV4dCwgMCk7XG4gIH1cblxuICBjYXRtdWxsUm9tLmFscGhhID0gZnVuY3Rpb24oYWxwaGEpIHtcbiAgICByZXR1cm4gY3VzdG9tKCthbHBoYSk7XG4gIH07XG5cbiAgcmV0dXJuIGNhdG11bGxSb207XG59KSgwLjUpO1xuXG5mdW5jdGlvbiBDYXRtdWxsUm9tQ2xvc2VkKGNvbnRleHQsIGFscGhhKSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xuICB0aGlzLl9hbHBoYSA9IGFscGhhO1xufVxuXG5DYXRtdWxsUm9tQ2xvc2VkLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBub29wLFxuICBhcmVhRW5kOiBub29wLFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPSB0aGlzLl94MiA9IHRoaXMuX3gzID0gdGhpcy5feDQgPSB0aGlzLl94NSA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9IHRoaXMuX3kyID0gdGhpcy5feTMgPSB0aGlzLl95NCA9IHRoaXMuX3k1ID0gTmFOO1xuICAgIHRoaXMuX2wwMV9hID0gdGhpcy5fbDEyX2EgPSB0aGlzLl9sMjNfYSA9XG4gICAgdGhpcy5fbDAxXzJhID0gdGhpcy5fbDEyXzJhID0gdGhpcy5fbDIzXzJhID1cbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMToge1xuICAgICAgICB0aGlzLl9jb250ZXh0Lm1vdmVUbyh0aGlzLl94MywgdGhpcy5feTMpO1xuICAgICAgICB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgMjoge1xuICAgICAgICB0aGlzLl9jb250ZXh0LmxpbmVUbyh0aGlzLl94MywgdGhpcy5feTMpO1xuICAgICAgICB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgMzoge1xuICAgICAgICB0aGlzLnBvaW50KHRoaXMuX3gzLCB0aGlzLl95Myk7XG4gICAgICAgIHRoaXMucG9pbnQodGhpcy5feDQsIHRoaXMuX3k0KTtcbiAgICAgICAgdGhpcy5wb2ludCh0aGlzLl94NSwgdGhpcy5feTUpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgeCA9ICt4LCB5ID0gK3k7XG5cbiAgICBpZiAodGhpcy5fcG9pbnQpIHtcbiAgICAgIHZhciB4MjMgPSB0aGlzLl94MiAtIHgsXG4gICAgICAgICAgeTIzID0gdGhpcy5feTIgLSB5O1xuICAgICAgdGhpcy5fbDIzX2EgPSBNYXRoLnNxcnQodGhpcy5fbDIzXzJhID0gTWF0aC5wb3coeDIzICogeDIzICsgeTIzICogeTIzLCB0aGlzLl9hbHBoYSkpO1xuICAgIH1cblxuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyB0aGlzLl94MyA9IHgsIHRoaXMuX3kzID0geTsgYnJlYWs7XG4gICAgICBjYXNlIDE6IHRoaXMuX3BvaW50ID0gMjsgdGhpcy5fY29udGV4dC5tb3ZlVG8odGhpcy5feDQgPSB4LCB0aGlzLl95NCA9IHkpOyBicmVhaztcbiAgICAgIGNhc2UgMjogdGhpcy5fcG9pbnQgPSAzOyB0aGlzLl94NSA9IHgsIHRoaXMuX3k1ID0geTsgYnJlYWs7XG4gICAgICBkZWZhdWx0OiBwb2ludCQyKHRoaXMsIHgsIHkpOyBicmVhaztcbiAgICB9XG5cbiAgICB0aGlzLl9sMDFfYSA9IHRoaXMuX2wxMl9hLCB0aGlzLl9sMTJfYSA9IHRoaXMuX2wyM19hO1xuICAgIHRoaXMuX2wwMV8yYSA9IHRoaXMuX2wxMl8yYSwgdGhpcy5fbDEyXzJhID0gdGhpcy5fbDIzXzJhO1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEsIHRoaXMuX3gxID0gdGhpcy5feDIsIHRoaXMuX3gyID0geDtcbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxLCB0aGlzLl95MSA9IHRoaXMuX3kyLCB0aGlzLl95MiA9IHk7XG4gIH1cbn07XG5cbnZhciBjYXRtdWxsUm9tQ2xvc2VkID0gKGZ1bmN0aW9uIGN1c3RvbShhbHBoYSkge1xuXG4gIGZ1bmN0aW9uIGNhdG11bGxSb20kJDEoY29udGV4dCkge1xuICAgIHJldHVybiBhbHBoYSA/IG5ldyBDYXRtdWxsUm9tQ2xvc2VkKGNvbnRleHQsIGFscGhhKSA6IG5ldyBDYXJkaW5hbENsb3NlZChjb250ZXh0LCAwKTtcbiAgfVxuXG4gIGNhdG11bGxSb20kJDEuYWxwaGEgPSBmdW5jdGlvbihhbHBoYSkge1xuICAgIHJldHVybiBjdXN0b20oK2FscGhhKTtcbiAgfTtcblxuICByZXR1cm4gY2F0bXVsbFJvbSQkMTtcbn0pKDAuNSk7XG5cbmZ1bmN0aW9uIENhdG11bGxSb21PcGVuKGNvbnRleHQsIGFscGhhKSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xuICB0aGlzLl9hbHBoYSA9IGFscGhhO1xufVxuXG5DYXRtdWxsUm9tT3Blbi5wcm90b3R5cGUgPSB7XG4gIGFyZWFTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IDA7XG4gIH0sXG4gIGFyZWFFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSBOYU47XG4gIH0sXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSA9IHRoaXMuX3gyID1cbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxID0gdGhpcy5feTIgPSBOYU47XG4gICAgdGhpcy5fbDAxX2EgPSB0aGlzLl9sMTJfYSA9IHRoaXMuX2wyM19hID1cbiAgICB0aGlzLl9sMDFfMmEgPSB0aGlzLl9sMTJfMmEgPSB0aGlzLl9sMjNfMmEgPVxuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMuX2xpbmUgfHwgKHRoaXMuX2xpbmUgIT09IDAgJiYgdGhpcy5fcG9pbnQgPT09IDMpKSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgIHRoaXMuX2xpbmUgPSAxIC0gdGhpcy5fbGluZTtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB4ID0gK3gsIHkgPSAreTtcblxuICAgIGlmICh0aGlzLl9wb2ludCkge1xuICAgICAgdmFyIHgyMyA9IHRoaXMuX3gyIC0geCxcbiAgICAgICAgICB5MjMgPSB0aGlzLl95MiAtIHk7XG4gICAgICB0aGlzLl9sMjNfYSA9IE1hdGguc3FydCh0aGlzLl9sMjNfMmEgPSBNYXRoLnBvdyh4MjMgKiB4MjMgKyB5MjMgKiB5MjMsIHRoaXMuX2FscGhhKSk7XG4gICAgfVxuXG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAwOiB0aGlzLl9wb2ludCA9IDE7IGJyZWFrO1xuICAgICAgY2FzZSAxOiB0aGlzLl9wb2ludCA9IDI7IGJyZWFrO1xuICAgICAgY2FzZSAyOiB0aGlzLl9wb2ludCA9IDM7IHRoaXMuX2xpbmUgPyB0aGlzLl9jb250ZXh0LmxpbmVUbyh0aGlzLl94MiwgdGhpcy5feTIpIDogdGhpcy5fY29udGV4dC5tb3ZlVG8odGhpcy5feDIsIHRoaXMuX3kyKTsgYnJlYWs7XG4gICAgICBjYXNlIDM6IHRoaXMuX3BvaW50ID0gNDsgLy8gcHJvY2VlZFxuICAgICAgZGVmYXVsdDogcG9pbnQkMih0aGlzLCB4LCB5KTsgYnJlYWs7XG4gICAgfVxuXG4gICAgdGhpcy5fbDAxX2EgPSB0aGlzLl9sMTJfYSwgdGhpcy5fbDEyX2EgPSB0aGlzLl9sMjNfYTtcbiAgICB0aGlzLl9sMDFfMmEgPSB0aGlzLl9sMTJfMmEsIHRoaXMuX2wxMl8yYSA9IHRoaXMuX2wyM18yYTtcbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxLCB0aGlzLl94MSA9IHRoaXMuX3gyLCB0aGlzLl94MiA9IHg7XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSwgdGhpcy5feTEgPSB0aGlzLl95MiwgdGhpcy5feTIgPSB5O1xuICB9XG59O1xuXG52YXIgY2F0bXVsbFJvbU9wZW4gPSAoZnVuY3Rpb24gY3VzdG9tKGFscGhhKSB7XG5cbiAgZnVuY3Rpb24gY2F0bXVsbFJvbSQkMShjb250ZXh0KSB7XG4gICAgcmV0dXJuIGFscGhhID8gbmV3IENhdG11bGxSb21PcGVuKGNvbnRleHQsIGFscGhhKSA6IG5ldyBDYXJkaW5hbE9wZW4oY29udGV4dCwgMCk7XG4gIH1cblxuICBjYXRtdWxsUm9tJCQxLmFscGhhID0gZnVuY3Rpb24oYWxwaGEpIHtcbiAgICByZXR1cm4gY3VzdG9tKCthbHBoYSk7XG4gIH07XG5cbiAgcmV0dXJuIGNhdG11bGxSb20kJDE7XG59KSgwLjUpO1xuXG5mdW5jdGlvbiBMaW5lYXJDbG9zZWQoY29udGV4dCkge1xuICB0aGlzLl9jb250ZXh0ID0gY29udGV4dDtcbn1cblxuTGluZWFyQ2xvc2VkLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBub29wLFxuICBhcmVhRW5kOiBub29wLFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMuX3BvaW50KSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICB9LFxuICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgIHggPSAreCwgeSA9ICt5O1xuICAgIGlmICh0aGlzLl9wb2ludCkgdGhpcy5fY29udGV4dC5saW5lVG8oeCwgeSk7XG4gICAgZWxzZSB0aGlzLl9wb2ludCA9IDEsIHRoaXMuX2NvbnRleHQubW92ZVRvKHgsIHkpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBsaW5lYXJDbG9zZWQoY29udGV4dCkge1xuICByZXR1cm4gbmV3IExpbmVhckNsb3NlZChjb250ZXh0KTtcbn1cblxuZnVuY3Rpb24gc2lnbih4KSB7XG4gIHJldHVybiB4IDwgMCA/IC0xIDogMTtcbn1cblxuLy8gQ2FsY3VsYXRlIHRoZSBzbG9wZXMgb2YgdGhlIHRhbmdlbnRzIChIZXJtaXRlLXR5cGUgaW50ZXJwb2xhdGlvbikgYmFzZWQgb25cbi8vIHRoZSBmb2xsb3dpbmcgcGFwZXI6IFN0ZWZmZW4sIE0uIDE5OTAuIEEgU2ltcGxlIE1ldGhvZCBmb3IgTW9ub3RvbmljXG4vLyBJbnRlcnBvbGF0aW9uIGluIE9uZSBEaW1lbnNpb24uIEFzdHJvbm9teSBhbmQgQXN0cm9waHlzaWNzLCBWb2wuIDIzOSwgTk8uXG4vLyBOT1YoSUkpLCBQLiA0NDMsIDE5OTAuXG5mdW5jdGlvbiBzbG9wZTModGhhdCwgeDIsIHkyKSB7XG4gIHZhciBoMCA9IHRoYXQuX3gxIC0gdGhhdC5feDAsXG4gICAgICBoMSA9IHgyIC0gdGhhdC5feDEsXG4gICAgICBzMCA9ICh0aGF0Ll95MSAtIHRoYXQuX3kwKSAvIChoMCB8fCBoMSA8IDAgJiYgLTApLFxuICAgICAgczEgPSAoeTIgLSB0aGF0Ll95MSkgLyAoaDEgfHwgaDAgPCAwICYmIC0wKSxcbiAgICAgIHAgPSAoczAgKiBoMSArIHMxICogaDApIC8gKGgwICsgaDEpO1xuICByZXR1cm4gKHNpZ24oczApICsgc2lnbihzMSkpICogTWF0aC5taW4oTWF0aC5hYnMoczApLCBNYXRoLmFicyhzMSksIDAuNSAqIE1hdGguYWJzKHApKSB8fCAwO1xufVxuXG4vLyBDYWxjdWxhdGUgYSBvbmUtc2lkZWQgc2xvcGUuXG5mdW5jdGlvbiBzbG9wZTIodGhhdCwgdCkge1xuICB2YXIgaCA9IHRoYXQuX3gxIC0gdGhhdC5feDA7XG4gIHJldHVybiBoID8gKDMgKiAodGhhdC5feTEgLSB0aGF0Ll95MCkgLyBoIC0gdCkgLyAyIDogdDtcbn1cblxuLy8gQWNjb3JkaW5nIHRvIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0N1YmljX0hlcm1pdGVfc3BsaW5lI1JlcHJlc2VudGF0aW9uc1xuLy8gXCJ5b3UgY2FuIGV4cHJlc3MgY3ViaWMgSGVybWl0ZSBpbnRlcnBvbGF0aW9uIGluIHRlcm1zIG9mIGN1YmljIELDqXppZXIgY3VydmVzXG4vLyB3aXRoIHJlc3BlY3QgdG8gdGhlIGZvdXIgdmFsdWVzIHAwLCBwMCArIG0wIC8gMywgcDEgLSBtMSAvIDMsIHAxXCIuXG5mdW5jdGlvbiBwb2ludCQzKHRoYXQsIHQwLCB0MSkge1xuICB2YXIgeDAgPSB0aGF0Ll94MCxcbiAgICAgIHkwID0gdGhhdC5feTAsXG4gICAgICB4MSA9IHRoYXQuX3gxLFxuICAgICAgeTEgPSB0aGF0Ll95MSxcbiAgICAgIGR4ID0gKHgxIC0geDApIC8gMztcbiAgdGhhdC5fY29udGV4dC5iZXppZXJDdXJ2ZVRvKHgwICsgZHgsIHkwICsgZHggKiB0MCwgeDEgLSBkeCwgeTEgLSBkeCAqIHQxLCB4MSwgeTEpO1xufVxuXG5mdW5jdGlvbiBNb25vdG9uZVgoY29udGV4dCkge1xuICB0aGlzLl9jb250ZXh0ID0gY29udGV4dDtcbn1cblxuTW9ub3RvbmVYLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gMDtcbiAgfSxcbiAgYXJlYUVuZDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IE5hTjtcbiAgfSxcbiAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxID1cbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxID1cbiAgICB0aGlzLl90MCA9IE5hTjtcbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMjogdGhpcy5fY29udGV4dC5saW5lVG8odGhpcy5feDEsIHRoaXMuX3kxKTsgYnJlYWs7XG4gICAgICBjYXNlIDM6IHBvaW50JDModGhpcywgdGhpcy5fdDAsIHNsb3BlMih0aGlzLCB0aGlzLl90MCkpOyBicmVhaztcbiAgICB9XG4gICAgaWYgKHRoaXMuX2xpbmUgfHwgKHRoaXMuX2xpbmUgIT09IDAgJiYgdGhpcy5fcG9pbnQgPT09IDEpKSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgIHRoaXMuX2xpbmUgPSAxIC0gdGhpcy5fbGluZTtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB2YXIgdDEgPSBOYU47XG5cbiAgICB4ID0gK3gsIHkgPSAreTtcbiAgICBpZiAoeCA9PT0gdGhpcy5feDEgJiYgeSA9PT0gdGhpcy5feTEpIHJldHVybjsgLy8gSWdub3JlIGNvaW5jaWRlbnQgcG9pbnRzLlxuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyB0aGlzLl9saW5lID8gdGhpcy5fY29udGV4dC5saW5lVG8oeCwgeSkgOiB0aGlzLl9jb250ZXh0Lm1vdmVUbyh4LCB5KTsgYnJlYWs7XG4gICAgICBjYXNlIDE6IHRoaXMuX3BvaW50ID0gMjsgYnJlYWs7XG4gICAgICBjYXNlIDI6IHRoaXMuX3BvaW50ID0gMzsgcG9pbnQkMyh0aGlzLCBzbG9wZTIodGhpcywgdDEgPSBzbG9wZTModGhpcywgeCwgeSkpLCB0MSk7IGJyZWFrO1xuICAgICAgZGVmYXVsdDogcG9pbnQkMyh0aGlzLCB0aGlzLl90MCwgdDEgPSBzbG9wZTModGhpcywgeCwgeSkpOyBicmVhaztcbiAgICB9XG5cbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxLCB0aGlzLl94MSA9IHg7XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSwgdGhpcy5feTEgPSB5O1xuICAgIHRoaXMuX3QwID0gdDE7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIE1vbm90b25lWShjb250ZXh0KSB7XG4gIHRoaXMuX2NvbnRleHQgPSBuZXcgUmVmbGVjdENvbnRleHQoY29udGV4dCk7XG59XG5cbihNb25vdG9uZVkucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShNb25vdG9uZVgucHJvdG90eXBlKSkucG9pbnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gIE1vbm90b25lWC5wcm90b3R5cGUucG9pbnQuY2FsbCh0aGlzLCB5LCB4KTtcbn07XG5cbmZ1bmN0aW9uIFJlZmxlY3RDb250ZXh0KGNvbnRleHQpIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG59XG5cblJlZmxlY3RDb250ZXh0LnByb3RvdHlwZSA9IHtcbiAgbW92ZVRvOiBmdW5jdGlvbih4LCB5KSB7IHRoaXMuX2NvbnRleHQubW92ZVRvKHksIHgpOyB9LFxuICBjbG9zZVBhdGg6IGZ1bmN0aW9uKCkgeyB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpOyB9LFxuICBsaW5lVG86IGZ1bmN0aW9uKHgsIHkpIHsgdGhpcy5fY29udGV4dC5saW5lVG8oeSwgeCk7IH0sXG4gIGJlemllckN1cnZlVG86IGZ1bmN0aW9uKHgxLCB5MSwgeDIsIHkyLCB4LCB5KSB7IHRoaXMuX2NvbnRleHQuYmV6aWVyQ3VydmVUbyh5MSwgeDEsIHkyLCB4MiwgeSwgeCk7IH1cbn07XG5cbmZ1bmN0aW9uIG1vbm90b25lWChjb250ZXh0KSB7XG4gIHJldHVybiBuZXcgTW9ub3RvbmVYKGNvbnRleHQpO1xufVxuXG5mdW5jdGlvbiBtb25vdG9uZVkoY29udGV4dCkge1xuICByZXR1cm4gbmV3IE1vbm90b25lWShjb250ZXh0KTtcbn1cblxuZnVuY3Rpb24gTmF0dXJhbChjb250ZXh0KSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xufVxuXG5OYXR1cmFsLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gMDtcbiAgfSxcbiAgYXJlYUVuZDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IE5hTjtcbiAgfSxcbiAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl94ID0gW107XG4gICAgdGhpcy5feSA9IFtdO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgeCA9IHRoaXMuX3gsXG4gICAgICAgIHkgPSB0aGlzLl95LFxuICAgICAgICBuID0geC5sZW5ndGg7XG5cbiAgICBpZiAobikge1xuICAgICAgdGhpcy5fbGluZSA/IHRoaXMuX2NvbnRleHQubGluZVRvKHhbMF0sIHlbMF0pIDogdGhpcy5fY29udGV4dC5tb3ZlVG8oeFswXSwgeVswXSk7XG4gICAgICBpZiAobiA9PT0gMikge1xuICAgICAgICB0aGlzLl9jb250ZXh0LmxpbmVUbyh4WzFdLCB5WzFdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBweCA9IGNvbnRyb2xQb2ludHMoeCksXG4gICAgICAgICAgICBweSA9IGNvbnRyb2xQb2ludHMoeSk7XG4gICAgICAgIGZvciAodmFyIGkwID0gMCwgaTEgPSAxOyBpMSA8IG47ICsraTAsICsraTEpIHtcbiAgICAgICAgICB0aGlzLl9jb250ZXh0LmJlemllckN1cnZlVG8ocHhbMF1baTBdLCBweVswXVtpMF0sIHB4WzFdW2kwXSwgcHlbMV1baTBdLCB4W2kxXSwgeVtpMV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2xpbmUgfHwgKHRoaXMuX2xpbmUgIT09IDAgJiYgbiA9PT0gMSkpIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgdGhpcy5fbGluZSA9IDEgLSB0aGlzLl9saW5lO1xuICAgIHRoaXMuX3ggPSB0aGlzLl95ID0gbnVsbDtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB0aGlzLl94LnB1c2goK3gpO1xuICAgIHRoaXMuX3kucHVzaCgreSk7XG4gIH1cbn07XG5cbi8vIFNlZSBodHRwczovL3d3dy5wYXJ0aWNsZWluY2VsbC5jb20vMjAxMi9iZXppZXItc3BsaW5lcy8gZm9yIGRlcml2YXRpb24uXG5mdW5jdGlvbiBjb250cm9sUG9pbnRzKHgpIHtcbiAgdmFyIGksXG4gICAgICBuID0geC5sZW5ndGggLSAxLFxuICAgICAgbSxcbiAgICAgIGEgPSBuZXcgQXJyYXkobiksXG4gICAgICBiID0gbmV3IEFycmF5KG4pLFxuICAgICAgciA9IG5ldyBBcnJheShuKTtcbiAgYVswXSA9IDAsIGJbMF0gPSAyLCByWzBdID0geFswXSArIDIgKiB4WzFdO1xuICBmb3IgKGkgPSAxOyBpIDwgbiAtIDE7ICsraSkgYVtpXSA9IDEsIGJbaV0gPSA0LCByW2ldID0gNCAqIHhbaV0gKyAyICogeFtpICsgMV07XG4gIGFbbiAtIDFdID0gMiwgYltuIC0gMV0gPSA3LCByW24gLSAxXSA9IDggKiB4W24gLSAxXSArIHhbbl07XG4gIGZvciAoaSA9IDE7IGkgPCBuOyArK2kpIG0gPSBhW2ldIC8gYltpIC0gMV0sIGJbaV0gLT0gbSwgcltpXSAtPSBtICogcltpIC0gMV07XG4gIGFbbiAtIDFdID0gcltuIC0gMV0gLyBiW24gLSAxXTtcbiAgZm9yIChpID0gbiAtIDI7IGkgPj0gMDsgLS1pKSBhW2ldID0gKHJbaV0gLSBhW2kgKyAxXSkgLyBiW2ldO1xuICBiW24gLSAxXSA9ICh4W25dICsgYVtuIC0gMV0pIC8gMjtcbiAgZm9yIChpID0gMDsgaSA8IG4gLSAxOyArK2kpIGJbaV0gPSAyICogeFtpICsgMV0gLSBhW2kgKyAxXTtcbiAgcmV0dXJuIFthLCBiXTtcbn1cblxuZnVuY3Rpb24gbmF0dXJhbChjb250ZXh0KSB7XG4gIHJldHVybiBuZXcgTmF0dXJhbChjb250ZXh0KTtcbn1cblxuZnVuY3Rpb24gU3RlcChjb250ZXh0LCB0KSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xuICB0aGlzLl90ID0gdDtcbn1cblxuU3RlcC5wcm90b3R5cGUgPSB7XG4gIGFyZWFTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IDA7XG4gIH0sXG4gIGFyZWFFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSBOYU47XG4gIH0sXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feCA9IHRoaXMuX3kgPSBOYU47XG4gICAgdGhpcy5fcG9pbnQgPSAwO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICBpZiAoMCA8IHRoaXMuX3QgJiYgdGhpcy5fdCA8IDEgJiYgdGhpcy5fcG9pbnQgPT09IDIpIHRoaXMuX2NvbnRleHQubGluZVRvKHRoaXMuX3gsIHRoaXMuX3kpO1xuICAgIGlmICh0aGlzLl9saW5lIHx8ICh0aGlzLl9saW5lICE9PSAwICYmIHRoaXMuX3BvaW50ID09PSAxKSkgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICBpZiAodGhpcy5fbGluZSA+PSAwKSB0aGlzLl90ID0gMSAtIHRoaXMuX3QsIHRoaXMuX2xpbmUgPSAxIC0gdGhpcy5fbGluZTtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB4ID0gK3gsIHkgPSAreTtcbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDA6IHRoaXMuX3BvaW50ID0gMTsgdGhpcy5fbGluZSA/IHRoaXMuX2NvbnRleHQubGluZVRvKHgsIHkpIDogdGhpcy5fY29udGV4dC5tb3ZlVG8oeCwgeSk7IGJyZWFrO1xuICAgICAgY2FzZSAxOiB0aGlzLl9wb2ludCA9IDI7IC8vIHByb2NlZWRcbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgaWYgKHRoaXMuX3QgPD0gMCkge1xuICAgICAgICAgIHRoaXMuX2NvbnRleHQubGluZVRvKHRoaXMuX3gsIHkpO1xuICAgICAgICAgIHRoaXMuX2NvbnRleHQubGluZVRvKHgsIHkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciB4MSA9IHRoaXMuX3ggKiAoMSAtIHRoaXMuX3QpICsgeCAqIHRoaXMuX3Q7XG4gICAgICAgICAgdGhpcy5fY29udGV4dC5saW5lVG8oeDEsIHRoaXMuX3kpO1xuICAgICAgICAgIHRoaXMuX2NvbnRleHQubGluZVRvKHgxLCB5KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5feCA9IHgsIHRoaXMuX3kgPSB5O1xuICB9XG59O1xuXG5mdW5jdGlvbiBzdGVwKGNvbnRleHQpIHtcbiAgcmV0dXJuIG5ldyBTdGVwKGNvbnRleHQsIDAuNSk7XG59XG5cbmZ1bmN0aW9uIHN0ZXBCZWZvcmUoY29udGV4dCkge1xuICByZXR1cm4gbmV3IFN0ZXAoY29udGV4dCwgMCk7XG59XG5cbmZ1bmN0aW9uIHN0ZXBBZnRlcihjb250ZXh0KSB7XG4gIHJldHVybiBuZXcgU3RlcChjb250ZXh0LCAxKTtcbn1cblxuZnVuY3Rpb24gbm9uZShzZXJpZXMsIG9yZGVyKSB7XG4gIGlmICghKChuID0gc2VyaWVzLmxlbmd0aCkgPiAxKSkgcmV0dXJuO1xuICBmb3IgKHZhciBpID0gMSwgaiwgczAsIHMxID0gc2VyaWVzW29yZGVyWzBdXSwgbiwgbSA9IHMxLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgIHMwID0gczEsIHMxID0gc2VyaWVzW29yZGVyW2ldXTtcbiAgICBmb3IgKGogPSAwOyBqIDwgbTsgKytqKSB7XG4gICAgICBzMVtqXVsxXSArPSBzMVtqXVswXSA9IGlzTmFOKHMwW2pdWzFdKSA/IHMwW2pdWzBdIDogczBbal1bMV07XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIG5vbmUkMShzZXJpZXMpIHtcbiAgdmFyIG4gPSBzZXJpZXMubGVuZ3RoLCBvID0gbmV3IEFycmF5KG4pO1xuICB3aGlsZSAoLS1uID49IDApIG9bbl0gPSBuO1xuICByZXR1cm4gbztcbn1cblxuZnVuY3Rpb24gc3RhY2tWYWx1ZShkLCBrZXkpIHtcbiAgcmV0dXJuIGRba2V5XTtcbn1cblxuZnVuY3Rpb24gc3RhY2soKSB7XG4gIHZhciBrZXlzID0gY29uc3RhbnQoW10pLFxuICAgICAgb3JkZXIgPSBub25lJDEsXG4gICAgICBvZmZzZXQgPSBub25lLFxuICAgICAgdmFsdWUgPSBzdGFja1ZhbHVlO1xuXG4gIGZ1bmN0aW9uIHN0YWNrKGRhdGEpIHtcbiAgICB2YXIga3ogPSBrZXlzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgIGksXG4gICAgICAgIG0gPSBkYXRhLmxlbmd0aCxcbiAgICAgICAgbiA9IGt6Lmxlbmd0aCxcbiAgICAgICAgc3ogPSBuZXcgQXJyYXkobiksXG4gICAgICAgIG96O1xuXG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgZm9yICh2YXIga2kgPSBreltpXSwgc2kgPSBzeltpXSA9IG5ldyBBcnJheShtKSwgaiA9IDAsIHNpajsgaiA8IG07ICsraikge1xuICAgICAgICBzaVtqXSA9IHNpaiA9IFswLCArdmFsdWUoZGF0YVtqXSwga2ksIGosIGRhdGEpXTtcbiAgICAgICAgc2lqLmRhdGEgPSBkYXRhW2pdO1xuICAgICAgfVxuICAgICAgc2kua2V5ID0ga2k7XG4gICAgfVxuXG4gICAgZm9yIChpID0gMCwgb3ogPSBvcmRlcihzeik7IGkgPCBuOyArK2kpIHtcbiAgICAgIHN6W296W2ldXS5pbmRleCA9IGk7XG4gICAgfVxuXG4gICAgb2Zmc2V0KHN6LCBveik7XG4gICAgcmV0dXJuIHN6O1xuICB9XG5cbiAgc3RhY2sua2V5cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChrZXlzID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChzbGljZS5jYWxsKF8pKSwgc3RhY2spIDoga2V5cztcbiAgfTtcblxuICBzdGFjay52YWx1ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBzdGFjaykgOiB2YWx1ZTtcbiAgfTtcblxuICBzdGFjay5vcmRlciA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvcmRlciA9IF8gPT0gbnVsbCA/IG5vbmUkMSA6IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoc2xpY2UuY2FsbChfKSksIHN0YWNrKSA6IG9yZGVyO1xuICB9O1xuXG4gIHN0YWNrLm9mZnNldCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvZmZzZXQgPSBfID09IG51bGwgPyBub25lIDogXywgc3RhY2spIDogb2Zmc2V0O1xuICB9O1xuXG4gIHJldHVybiBzdGFjaztcbn1cblxuZnVuY3Rpb24gZXhwYW5kKHNlcmllcywgb3JkZXIpIHtcbiAgaWYgKCEoKG4gPSBzZXJpZXMubGVuZ3RoKSA+IDApKSByZXR1cm47XG4gIGZvciAodmFyIGksIG4sIGogPSAwLCBtID0gc2VyaWVzWzBdLmxlbmd0aCwgeTsgaiA8IG07ICsraikge1xuICAgIGZvciAoeSA9IGkgPSAwOyBpIDwgbjsgKytpKSB5ICs9IHNlcmllc1tpXVtqXVsxXSB8fCAwO1xuICAgIGlmICh5KSBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSBzZXJpZXNbaV1bal1bMV0gLz0geTtcbiAgfVxuICBub25lKHNlcmllcywgb3JkZXIpO1xufVxuXG5mdW5jdGlvbiBkaXZlcmdpbmcoc2VyaWVzLCBvcmRlcikge1xuICBpZiAoISgobiA9IHNlcmllcy5sZW5ndGgpID4gMSkpIHJldHVybjtcbiAgZm9yICh2YXIgaSwgaiA9IDAsIGQsIGR5LCB5cCwgeW4sIG4sIG0gPSBzZXJpZXNbb3JkZXJbMF1dLmxlbmd0aDsgaiA8IG07ICsraikge1xuICAgIGZvciAoeXAgPSB5biA9IDAsIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAoKGR5ID0gKGQgPSBzZXJpZXNbb3JkZXJbaV1dW2pdKVsxXSAtIGRbMF0pID49IDApIHtcbiAgICAgICAgZFswXSA9IHlwLCBkWzFdID0geXAgKz0gZHk7XG4gICAgICB9IGVsc2UgaWYgKGR5IDwgMCkge1xuICAgICAgICBkWzFdID0geW4sIGRbMF0gPSB5biArPSBkeTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRbMF0gPSB5cDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gc2lsaG91ZXR0ZShzZXJpZXMsIG9yZGVyKSB7XG4gIGlmICghKChuID0gc2VyaWVzLmxlbmd0aCkgPiAwKSkgcmV0dXJuO1xuICBmb3IgKHZhciBqID0gMCwgczAgPSBzZXJpZXNbb3JkZXJbMF1dLCBuLCBtID0gczAubGVuZ3RoOyBqIDwgbTsgKytqKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIHkgPSAwOyBpIDwgbjsgKytpKSB5ICs9IHNlcmllc1tpXVtqXVsxXSB8fCAwO1xuICAgIHMwW2pdWzFdICs9IHMwW2pdWzBdID0gLXkgLyAyO1xuICB9XG4gIG5vbmUoc2VyaWVzLCBvcmRlcik7XG59XG5cbmZ1bmN0aW9uIHdpZ2dsZShzZXJpZXMsIG9yZGVyKSB7XG4gIGlmICghKChuID0gc2VyaWVzLmxlbmd0aCkgPiAwKSB8fCAhKChtID0gKHMwID0gc2VyaWVzW29yZGVyWzBdXSkubGVuZ3RoKSA+IDApKSByZXR1cm47XG4gIGZvciAodmFyIHkgPSAwLCBqID0gMSwgczAsIG0sIG47IGogPCBtOyArK2opIHtcbiAgICBmb3IgKHZhciBpID0gMCwgczEgPSAwLCBzMiA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHZhciBzaSA9IHNlcmllc1tvcmRlcltpXV0sXG4gICAgICAgICAgc2lqMCA9IHNpW2pdWzFdIHx8IDAsXG4gICAgICAgICAgc2lqMSA9IHNpW2ogLSAxXVsxXSB8fCAwLFxuICAgICAgICAgIHMzID0gKHNpajAgLSBzaWoxKSAvIDI7XG4gICAgICBmb3IgKHZhciBrID0gMDsgayA8IGk7ICsraykge1xuICAgICAgICB2YXIgc2sgPSBzZXJpZXNbb3JkZXJba11dLFxuICAgICAgICAgICAgc2tqMCA9IHNrW2pdWzFdIHx8IDAsXG4gICAgICAgICAgICBza2oxID0gc2tbaiAtIDFdWzFdIHx8IDA7XG4gICAgICAgIHMzICs9IHNrajAgLSBza2oxO1xuICAgICAgfVxuICAgICAgczEgKz0gc2lqMCwgczIgKz0gczMgKiBzaWowO1xuICAgIH1cbiAgICBzMFtqIC0gMV1bMV0gKz0gczBbaiAtIDFdWzBdID0geTtcbiAgICBpZiAoczEpIHkgLT0gczIgLyBzMTtcbiAgfVxuICBzMFtqIC0gMV1bMV0gKz0gczBbaiAtIDFdWzBdID0geTtcbiAgbm9uZShzZXJpZXMsIG9yZGVyKTtcbn1cblxuZnVuY3Rpb24gYXBwZWFyYW5jZShzZXJpZXMpIHtcbiAgdmFyIHBlYWtzID0gc2VyaWVzLm1hcChwZWFrKTtcbiAgcmV0dXJuIG5vbmUkMShzZXJpZXMpLnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gcGVha3NbYV0gLSBwZWFrc1tiXTsgfSk7XG59XG5cbmZ1bmN0aW9uIHBlYWsoc2VyaWVzKSB7XG4gIHZhciBpID0gLTEsIGogPSAwLCBuID0gc2VyaWVzLmxlbmd0aCwgdmksIHZqID0gLUluZmluaXR5O1xuICB3aGlsZSAoKytpIDwgbikgaWYgKCh2aSA9ICtzZXJpZXNbaV1bMV0pID4gdmopIHZqID0gdmksIGogPSBpO1xuICByZXR1cm4gajtcbn1cblxuZnVuY3Rpb24gYXNjZW5kaW5nKHNlcmllcykge1xuICB2YXIgc3VtcyA9IHNlcmllcy5tYXAoc3VtKTtcbiAgcmV0dXJuIG5vbmUkMShzZXJpZXMpLnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gc3Vtc1thXSAtIHN1bXNbYl07IH0pO1xufVxuXG5mdW5jdGlvbiBzdW0oc2VyaWVzKSB7XG4gIHZhciBzID0gMCwgaSA9IC0xLCBuID0gc2VyaWVzLmxlbmd0aCwgdjtcbiAgd2hpbGUgKCsraSA8IG4pIGlmICh2ID0gK3Nlcmllc1tpXVsxXSkgcyArPSB2O1xuICByZXR1cm4gcztcbn1cblxuZnVuY3Rpb24gZGVzY2VuZGluZyQxKHNlcmllcykge1xuICByZXR1cm4gYXNjZW5kaW5nKHNlcmllcykucmV2ZXJzZSgpO1xufVxuXG5mdW5jdGlvbiBpbnNpZGVPdXQoc2VyaWVzKSB7XG4gIHZhciBuID0gc2VyaWVzLmxlbmd0aCxcbiAgICAgIGksXG4gICAgICBqLFxuICAgICAgc3VtcyA9IHNlcmllcy5tYXAoc3VtKSxcbiAgICAgIG9yZGVyID0gYXBwZWFyYW5jZShzZXJpZXMpLFxuICAgICAgdG9wID0gMCxcbiAgICAgIGJvdHRvbSA9IDAsXG4gICAgICB0b3BzID0gW10sXG4gICAgICBib3R0b21zID0gW107XG5cbiAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgIGogPSBvcmRlcltpXTtcbiAgICBpZiAodG9wIDwgYm90dG9tKSB7XG4gICAgICB0b3AgKz0gc3Vtc1tqXTtcbiAgICAgIHRvcHMucHVzaChqKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYm90dG9tICs9IHN1bXNbal07XG4gICAgICBib3R0b21zLnB1c2goaik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJvdHRvbXMucmV2ZXJzZSgpLmNvbmNhdCh0b3BzKTtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShzZXJpZXMpIHtcbiAgcmV0dXJuIG5vbmUkMShzZXJpZXMpLnJldmVyc2UoKTtcbn1cblxuZXhwb3J0cy5hcmMgPSBhcmM7XG5leHBvcnRzLmFyZWEgPSBhcmVhO1xuZXhwb3J0cy5saW5lID0gbGluZTtcbmV4cG9ydHMucGllID0gcGllO1xuZXhwb3J0cy5hcmVhUmFkaWFsID0gYXJlYVJhZGlhbDtcbmV4cG9ydHMucmFkaWFsQXJlYSA9IGFyZWFSYWRpYWw7XG5leHBvcnRzLmxpbmVSYWRpYWwgPSBsaW5lUmFkaWFsJDE7XG5leHBvcnRzLnJhZGlhbExpbmUgPSBsaW5lUmFkaWFsJDE7XG5leHBvcnRzLnBvaW50UmFkaWFsID0gcG9pbnRSYWRpYWw7XG5leHBvcnRzLmxpbmtIb3Jpem9udGFsID0gbGlua0hvcml6b250YWw7XG5leHBvcnRzLmxpbmtWZXJ0aWNhbCA9IGxpbmtWZXJ0aWNhbDtcbmV4cG9ydHMubGlua1JhZGlhbCA9IGxpbmtSYWRpYWw7XG5leHBvcnRzLnN5bWJvbCA9IHN5bWJvbDtcbmV4cG9ydHMuc3ltYm9scyA9IHN5bWJvbHM7XG5leHBvcnRzLnN5bWJvbENpcmNsZSA9IGNpcmNsZTtcbmV4cG9ydHMuc3ltYm9sQ3Jvc3MgPSBjcm9zcztcbmV4cG9ydHMuc3ltYm9sRGlhbW9uZCA9IGRpYW1vbmQ7XG5leHBvcnRzLnN5bWJvbFNxdWFyZSA9IHNxdWFyZTtcbmV4cG9ydHMuc3ltYm9sU3RhciA9IHN0YXI7XG5leHBvcnRzLnN5bWJvbFRyaWFuZ2xlID0gdHJpYW5nbGU7XG5leHBvcnRzLnN5bWJvbFd5ZSA9IHd5ZTtcbmV4cG9ydHMuY3VydmVCYXNpc0Nsb3NlZCA9IGJhc2lzQ2xvc2VkO1xuZXhwb3J0cy5jdXJ2ZUJhc2lzT3BlbiA9IGJhc2lzT3BlbjtcbmV4cG9ydHMuY3VydmVCYXNpcyA9IGJhc2lzO1xuZXhwb3J0cy5jdXJ2ZUJ1bmRsZSA9IGJ1bmRsZTtcbmV4cG9ydHMuY3VydmVDYXJkaW5hbENsb3NlZCA9IGNhcmRpbmFsQ2xvc2VkO1xuZXhwb3J0cy5jdXJ2ZUNhcmRpbmFsT3BlbiA9IGNhcmRpbmFsT3BlbjtcbmV4cG9ydHMuY3VydmVDYXJkaW5hbCA9IGNhcmRpbmFsO1xuZXhwb3J0cy5jdXJ2ZUNhdG11bGxSb21DbG9zZWQgPSBjYXRtdWxsUm9tQ2xvc2VkO1xuZXhwb3J0cy5jdXJ2ZUNhdG11bGxSb21PcGVuID0gY2F0bXVsbFJvbU9wZW47XG5leHBvcnRzLmN1cnZlQ2F0bXVsbFJvbSA9IGNhdG11bGxSb207XG5leHBvcnRzLmN1cnZlTGluZWFyQ2xvc2VkID0gbGluZWFyQ2xvc2VkO1xuZXhwb3J0cy5jdXJ2ZUxpbmVhciA9IGN1cnZlTGluZWFyO1xuZXhwb3J0cy5jdXJ2ZU1vbm90b25lWCA9IG1vbm90b25lWDtcbmV4cG9ydHMuY3VydmVNb25vdG9uZVkgPSBtb25vdG9uZVk7XG5leHBvcnRzLmN1cnZlTmF0dXJhbCA9IG5hdHVyYWw7XG5leHBvcnRzLmN1cnZlU3RlcCA9IHN0ZXA7XG5leHBvcnRzLmN1cnZlU3RlcEFmdGVyID0gc3RlcEFmdGVyO1xuZXhwb3J0cy5jdXJ2ZVN0ZXBCZWZvcmUgPSBzdGVwQmVmb3JlO1xuZXhwb3J0cy5zdGFjayA9IHN0YWNrO1xuZXhwb3J0cy5zdGFja09mZnNldEV4cGFuZCA9IGV4cGFuZDtcbmV4cG9ydHMuc3RhY2tPZmZzZXREaXZlcmdpbmcgPSBkaXZlcmdpbmc7XG5leHBvcnRzLnN0YWNrT2Zmc2V0Tm9uZSA9IG5vbmU7XG5leHBvcnRzLnN0YWNrT2Zmc2V0U2lsaG91ZXR0ZSA9IHNpbGhvdWV0dGU7XG5leHBvcnRzLnN0YWNrT2Zmc2V0V2lnZ2xlID0gd2lnZ2xlO1xuZXhwb3J0cy5zdGFja09yZGVyQXBwZWFyYW5jZSA9IGFwcGVhcmFuY2U7XG5leHBvcnRzLnN0YWNrT3JkZXJBc2NlbmRpbmcgPSBhc2NlbmRpbmc7XG5leHBvcnRzLnN0YWNrT3JkZXJEZXNjZW5kaW5nID0gZGVzY2VuZGluZyQxO1xuZXhwb3J0cy5zdGFja09yZGVySW5zaWRlT3V0ID0gaW5zaWRlT3V0O1xuZXhwb3J0cy5zdGFja09yZGVyTm9uZSA9IG5vbmUkMTtcbmV4cG9ydHMuc3RhY2tPcmRlclJldmVyc2UgPSByZXZlcnNlO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuXG59LHtcImQzLXBhdGhcIjoxNTl9XSwxNjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy10aW1lci8gVmVyc2lvbiAxLjAuNy4gQ29weXJpZ2h0IDIwMTcgTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG52YXIgZnJhbWUgPSAwO1xudmFyIHRpbWVvdXQgPSAwO1xudmFyIGludGVydmFsID0gMDtcbnZhciBwb2tlRGVsYXkgPSAxMDAwO1xudmFyIHRhc2tIZWFkO1xudmFyIHRhc2tUYWlsO1xudmFyIGNsb2NrTGFzdCA9IDA7XG52YXIgY2xvY2tOb3cgPSAwO1xudmFyIGNsb2NrU2tldyA9IDA7XG52YXIgY2xvY2sgPSB0eXBlb2YgcGVyZm9ybWFuY2UgPT09IFwib2JqZWN0XCIgJiYgcGVyZm9ybWFuY2Uubm93ID8gcGVyZm9ybWFuY2UgOiBEYXRlO1xudmFyIHNldEZyYW1lID0gdHlwZW9mIHdpbmRvdyA9PT0gXCJvYmplY3RcIiAmJiB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lID8gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZS5iaW5kKHdpbmRvdykgOiBmdW5jdGlvbihmKSB7IHNldFRpbWVvdXQoZiwgMTcpOyB9O1xuXG5mdW5jdGlvbiBub3coKSB7XG4gIHJldHVybiBjbG9ja05vdyB8fCAoc2V0RnJhbWUoY2xlYXJOb3cpLCBjbG9ja05vdyA9IGNsb2NrLm5vdygpICsgY2xvY2tTa2V3KTtcbn1cblxuZnVuY3Rpb24gY2xlYXJOb3coKSB7XG4gIGNsb2NrTm93ID0gMDtcbn1cblxuZnVuY3Rpb24gVGltZXIoKSB7XG4gIHRoaXMuX2NhbGwgPVxuICB0aGlzLl90aW1lID1cbiAgdGhpcy5fbmV4dCA9IG51bGw7XG59XG5cblRpbWVyLnByb3RvdHlwZSA9IHRpbWVyLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IFRpbWVyLFxuICByZXN0YXJ0OiBmdW5jdGlvbihjYWxsYmFjaywgZGVsYXksIHRpbWUpIHtcbiAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvblwiKTtcbiAgICB0aW1lID0gKHRpbWUgPT0gbnVsbCA/IG5vdygpIDogK3RpbWUpICsgKGRlbGF5ID09IG51bGwgPyAwIDogK2RlbGF5KTtcbiAgICBpZiAoIXRoaXMuX25leHQgJiYgdGFza1RhaWwgIT09IHRoaXMpIHtcbiAgICAgIGlmICh0YXNrVGFpbCkgdGFza1RhaWwuX25leHQgPSB0aGlzO1xuICAgICAgZWxzZSB0YXNrSGVhZCA9IHRoaXM7XG4gICAgICB0YXNrVGFpbCA9IHRoaXM7XG4gICAgfVxuICAgIHRoaXMuX2NhbGwgPSBjYWxsYmFjaztcbiAgICB0aGlzLl90aW1lID0gdGltZTtcbiAgICBzbGVlcCgpO1xuICB9LFxuICBzdG9wOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5fY2FsbCkge1xuICAgICAgdGhpcy5fY2FsbCA9IG51bGw7XG4gICAgICB0aGlzLl90aW1lID0gSW5maW5pdHk7XG4gICAgICBzbGVlcCgpO1xuICAgIH1cbiAgfVxufTtcblxuZnVuY3Rpb24gdGltZXIoY2FsbGJhY2ssIGRlbGF5LCB0aW1lKSB7XG4gIHZhciB0ID0gbmV3IFRpbWVyO1xuICB0LnJlc3RhcnQoY2FsbGJhY2ssIGRlbGF5LCB0aW1lKTtcbiAgcmV0dXJuIHQ7XG59XG5cbmZ1bmN0aW9uIHRpbWVyRmx1c2goKSB7XG4gIG5vdygpOyAvLyBHZXQgdGhlIGN1cnJlbnQgdGltZSwgaWYgbm90IGFscmVhZHkgc2V0LlxuICArK2ZyYW1lOyAvLyBQcmV0ZW5kIHdl4oCZdmUgc2V0IGFuIGFsYXJtLCBpZiB3ZSBoYXZlbuKAmXQgYWxyZWFkeS5cbiAgdmFyIHQgPSB0YXNrSGVhZCwgZTtcbiAgd2hpbGUgKHQpIHtcbiAgICBpZiAoKGUgPSBjbG9ja05vdyAtIHQuX3RpbWUpID49IDApIHQuX2NhbGwuY2FsbChudWxsLCBlKTtcbiAgICB0ID0gdC5fbmV4dDtcbiAgfVxuICAtLWZyYW1lO1xufVxuXG5mdW5jdGlvbiB3YWtlKCkge1xuICBjbG9ja05vdyA9IChjbG9ja0xhc3QgPSBjbG9jay5ub3coKSkgKyBjbG9ja1NrZXc7XG4gIGZyYW1lID0gdGltZW91dCA9IDA7XG4gIHRyeSB7XG4gICAgdGltZXJGbHVzaCgpO1xuICB9IGZpbmFsbHkge1xuICAgIGZyYW1lID0gMDtcbiAgICBuYXAoKTtcbiAgICBjbG9ja05vdyA9IDA7XG4gIH1cbn1cblxuZnVuY3Rpb24gcG9rZSgpIHtcbiAgdmFyIG5vdyA9IGNsb2NrLm5vdygpLCBkZWxheSA9IG5vdyAtIGNsb2NrTGFzdDtcbiAgaWYgKGRlbGF5ID4gcG9rZURlbGF5KSBjbG9ja1NrZXcgLT0gZGVsYXksIGNsb2NrTGFzdCA9IG5vdztcbn1cblxuZnVuY3Rpb24gbmFwKCkge1xuICB2YXIgdDAsIHQxID0gdGFza0hlYWQsIHQyLCB0aW1lID0gSW5maW5pdHk7XG4gIHdoaWxlICh0MSkge1xuICAgIGlmICh0MS5fY2FsbCkge1xuICAgICAgaWYgKHRpbWUgPiB0MS5fdGltZSkgdGltZSA9IHQxLl90aW1lO1xuICAgICAgdDAgPSB0MSwgdDEgPSB0MS5fbmV4dDtcbiAgICB9IGVsc2Uge1xuICAgICAgdDIgPSB0MS5fbmV4dCwgdDEuX25leHQgPSBudWxsO1xuICAgICAgdDEgPSB0MCA/IHQwLl9uZXh0ID0gdDIgOiB0YXNrSGVhZCA9IHQyO1xuICAgIH1cbiAgfVxuICB0YXNrVGFpbCA9IHQwO1xuICBzbGVlcCh0aW1lKTtcbn1cblxuZnVuY3Rpb24gc2xlZXAodGltZSkge1xuICBpZiAoZnJhbWUpIHJldHVybjsgLy8gU29vbmVzdCBhbGFybSBhbHJlYWR5IHNldCwgb3Igd2lsbCBiZS5cbiAgaWYgKHRpbWVvdXQpIHRpbWVvdXQgPSBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gIHZhciBkZWxheSA9IHRpbWUgLSBjbG9ja05vdzsgLy8gU3RyaWN0bHkgbGVzcyB0aGFuIGlmIHdlIHJlY29tcHV0ZWQgY2xvY2tOb3cuXG4gIGlmIChkZWxheSA+IDI0KSB7XG4gICAgaWYgKHRpbWUgPCBJbmZpbml0eSkgdGltZW91dCA9IHNldFRpbWVvdXQod2FrZSwgdGltZSAtIGNsb2NrLm5vdygpIC0gY2xvY2tTa2V3KTtcbiAgICBpZiAoaW50ZXJ2YWwpIGludGVydmFsID0gY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFpbnRlcnZhbCkgY2xvY2tMYXN0ID0gY2xvY2subm93KCksIGludGVydmFsID0gc2V0SW50ZXJ2YWwocG9rZSwgcG9rZURlbGF5KTtcbiAgICBmcmFtZSA9IDEsIHNldEZyYW1lKHdha2UpO1xuICB9XG59XG5cbnZhciB0aW1lb3V0JDEgPSBmdW5jdGlvbihjYWxsYmFjaywgZGVsYXksIHRpbWUpIHtcbiAgdmFyIHQgPSBuZXcgVGltZXI7XG4gIGRlbGF5ID0gZGVsYXkgPT0gbnVsbCA/IDAgOiArZGVsYXk7XG4gIHQucmVzdGFydChmdW5jdGlvbihlbGFwc2VkKSB7XG4gICAgdC5zdG9wKCk7XG4gICAgY2FsbGJhY2soZWxhcHNlZCArIGRlbGF5KTtcbiAgfSwgZGVsYXksIHRpbWUpO1xuICByZXR1cm4gdDtcbn07XG5cbnZhciBpbnRlcnZhbCQxID0gZnVuY3Rpb24oY2FsbGJhY2ssIGRlbGF5LCB0aW1lKSB7XG4gIHZhciB0ID0gbmV3IFRpbWVyLCB0b3RhbCA9IGRlbGF5O1xuICBpZiAoZGVsYXkgPT0gbnVsbCkgcmV0dXJuIHQucmVzdGFydChjYWxsYmFjaywgZGVsYXksIHRpbWUpLCB0O1xuICBkZWxheSA9ICtkZWxheSwgdGltZSA9IHRpbWUgPT0gbnVsbCA/IG5vdygpIDogK3RpbWU7XG4gIHQucmVzdGFydChmdW5jdGlvbiB0aWNrKGVsYXBzZWQpIHtcbiAgICBlbGFwc2VkICs9IHRvdGFsO1xuICAgIHQucmVzdGFydCh0aWNrLCB0b3RhbCArPSBkZWxheSwgdGltZSk7XG4gICAgY2FsbGJhY2soZWxhcHNlZCk7XG4gIH0sIGRlbGF5LCB0aW1lKTtcbiAgcmV0dXJuIHQ7XG59O1xuXG5leHBvcnRzLm5vdyA9IG5vdztcbmV4cG9ydHMudGltZXIgPSB0aW1lcjtcbmV4cG9ydHMudGltZXJGbHVzaCA9IHRpbWVyRmx1c2g7XG5leHBvcnRzLnRpbWVvdXQgPSB0aW1lb3V0JDE7XG5leHBvcnRzLmludGVydmFsID0gaW50ZXJ2YWwkMTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcblxufSx7fV0sMTYzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbiFmdW5jdGlvbigpIHtcbiAgdmFyIGQzID0ge1xuICAgIHZlcnNpb246IFwiMy41LjE3XCJcbiAgfTtcbiAgdmFyIGQzX2FycmF5U2xpY2UgPSBbXS5zbGljZSwgZDNfYXJyYXkgPSBmdW5jdGlvbihsaXN0KSB7XG4gICAgcmV0dXJuIGQzX2FycmF5U2xpY2UuY2FsbChsaXN0KTtcbiAgfTtcbiAgdmFyIGQzX2RvY3VtZW50ID0gdGhpcy5kb2N1bWVudDtcbiAgZnVuY3Rpb24gZDNfZG9jdW1lbnRFbGVtZW50KG5vZGUpIHtcbiAgICByZXR1cm4gbm9kZSAmJiAobm9kZS5vd25lckRvY3VtZW50IHx8IG5vZGUuZG9jdW1lbnQgfHwgbm9kZSkuZG9jdW1lbnRFbGVtZW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3dpbmRvdyhub2RlKSB7XG4gICAgcmV0dXJuIG5vZGUgJiYgKG5vZGUub3duZXJEb2N1bWVudCAmJiBub2RlLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcgfHwgbm9kZS5kb2N1bWVudCAmJiBub2RlIHx8IG5vZGUuZGVmYXVsdFZpZXcpO1xuICB9XG4gIGlmIChkM19kb2N1bWVudCkge1xuICAgIHRyeSB7XG4gICAgICBkM19hcnJheShkM19kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2hpbGROb2RlcylbMF0ubm9kZVR5cGU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZDNfYXJyYXkgPSBmdW5jdGlvbihsaXN0KSB7XG4gICAgICAgIHZhciBpID0gbGlzdC5sZW5ndGgsIGFycmF5ID0gbmV3IEFycmF5KGkpO1xuICAgICAgICB3aGlsZSAoaS0tKSBhcnJheVtpXSA9IGxpc3RbaV07XG4gICAgICAgIHJldHVybiBhcnJheTtcbiAgICAgIH07XG4gICAgfVxuICB9XG4gIGlmICghRGF0ZS5ub3cpIERhdGUubm93ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICtuZXcgRGF0ZSgpO1xuICB9O1xuICBpZiAoZDNfZG9jdW1lbnQpIHtcbiAgICB0cnkge1xuICAgICAgZDNfZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIkRJVlwiKS5zdHlsZS5zZXRQcm9wZXJ0eShcIm9wYWNpdHlcIiwgMCwgXCJcIik7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHZhciBkM19lbGVtZW50X3Byb3RvdHlwZSA9IHRoaXMuRWxlbWVudC5wcm90b3R5cGUsIGQzX2VsZW1lbnRfc2V0QXR0cmlidXRlID0gZDNfZWxlbWVudF9wcm90b3R5cGUuc2V0QXR0cmlidXRlLCBkM19lbGVtZW50X3NldEF0dHJpYnV0ZU5TID0gZDNfZWxlbWVudF9wcm90b3R5cGUuc2V0QXR0cmlidXRlTlMsIGQzX3N0eWxlX3Byb3RvdHlwZSA9IHRoaXMuQ1NTU3R5bGVEZWNsYXJhdGlvbi5wcm90b3R5cGUsIGQzX3N0eWxlX3NldFByb3BlcnR5ID0gZDNfc3R5bGVfcHJvdG90eXBlLnNldFByb3BlcnR5O1xuICAgICAgZDNfZWxlbWVudF9wcm90b3R5cGUuc2V0QXR0cmlidXRlID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHtcbiAgICAgICAgZDNfZWxlbWVudF9zZXRBdHRyaWJ1dGUuY2FsbCh0aGlzLCBuYW1lLCB2YWx1ZSArIFwiXCIpO1xuICAgICAgfTtcbiAgICAgIGQzX2VsZW1lbnRfcHJvdG90eXBlLnNldEF0dHJpYnV0ZU5TID0gZnVuY3Rpb24oc3BhY2UsIGxvY2FsLCB2YWx1ZSkge1xuICAgICAgICBkM19lbGVtZW50X3NldEF0dHJpYnV0ZU5TLmNhbGwodGhpcywgc3BhY2UsIGxvY2FsLCB2YWx1ZSArIFwiXCIpO1xuICAgICAgfTtcbiAgICAgIGQzX3N0eWxlX3Byb3RvdHlwZS5zZXRQcm9wZXJ0eSA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlLCBwcmlvcml0eSkge1xuICAgICAgICBkM19zdHlsZV9zZXRQcm9wZXJ0eS5jYWxsKHRoaXMsIG5hbWUsIHZhbHVlICsgXCJcIiwgcHJpb3JpdHkpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cbiAgZDMuYXNjZW5kaW5nID0gZDNfYXNjZW5kaW5nO1xuICBmdW5jdGlvbiBkM19hc2NlbmRpbmcoYSwgYikge1xuICAgIHJldHVybiBhIDwgYiA/IC0xIDogYSA+IGIgPyAxIDogYSA+PSBiID8gMCA6IE5hTjtcbiAgfVxuICBkMy5kZXNjZW5kaW5nID0gZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBiIDwgYSA/IC0xIDogYiA+IGEgPyAxIDogYiA+PSBhID8gMCA6IE5hTjtcbiAgfTtcbiAgZDMubWluID0gZnVuY3Rpb24oYXJyYXksIGYpIHtcbiAgICB2YXIgaSA9IC0xLCBuID0gYXJyYXkubGVuZ3RoLCBhLCBiO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gYXJyYXlbaV0pICE9IG51bGwgJiYgYiA+PSBiKSB7XG4gICAgICAgIGEgPSBiO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBhcnJheVtpXSkgIT0gbnVsbCAmJiBhID4gYikgYSA9IGI7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBmLmNhbGwoYXJyYXksIGFycmF5W2ldLCBpKSkgIT0gbnVsbCAmJiBiID49IGIpIHtcbiAgICAgICAgYSA9IGI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmICgoYiA9IGYuY2FsbChhcnJheSwgYXJyYXlbaV0sIGkpKSAhPSBudWxsICYmIGEgPiBiKSBhID0gYjtcbiAgICB9XG4gICAgcmV0dXJuIGE7XG4gIH07XG4gIGQzLm1heCA9IGZ1bmN0aW9uKGFycmF5LCBmKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IGFycmF5Lmxlbmd0aCwgYSwgYjtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmICgoYiA9IGFycmF5W2ldKSAhPSBudWxsICYmIGIgPj0gYikge1xuICAgICAgICBhID0gYjtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gYXJyYXlbaV0pICE9IG51bGwgJiYgYiA+IGEpIGEgPSBiO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpICE9IG51bGwgJiYgYiA+PSBiKSB7XG4gICAgICAgIGEgPSBiO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBmLmNhbGwoYXJyYXksIGFycmF5W2ldLCBpKSkgIT0gbnVsbCAmJiBiID4gYSkgYSA9IGI7XG4gICAgfVxuICAgIHJldHVybiBhO1xuICB9O1xuICBkMy5leHRlbnQgPSBmdW5jdGlvbihhcnJheSwgZikge1xuICAgIHZhciBpID0gLTEsIG4gPSBhcnJheS5sZW5ndGgsIGEsIGIsIGM7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBhcnJheVtpXSkgIT0gbnVsbCAmJiBiID49IGIpIHtcbiAgICAgICAgYSA9IGMgPSBiO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoKGIgPSBhcnJheVtpXSkgIT0gbnVsbCkge1xuICAgICAgICBpZiAoYSA+IGIpIGEgPSBiO1xuICAgICAgICBpZiAoYyA8IGIpIGMgPSBiO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpICE9IG51bGwgJiYgYiA+PSBiKSB7XG4gICAgICAgIGEgPSBjID0gYjtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKChiID0gZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpICE9IG51bGwpIHtcbiAgICAgICAgaWYgKGEgPiBiKSBhID0gYjtcbiAgICAgICAgaWYgKGMgPCBiKSBjID0gYjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFsgYSwgYyBdO1xuICB9O1xuICBmdW5jdGlvbiBkM19udW1iZXIoeCkge1xuICAgIHJldHVybiB4ID09PSBudWxsID8gTmFOIDogK3g7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbnVtZXJpYyh4KSB7XG4gICAgcmV0dXJuICFpc05hTih4KTtcbiAgfVxuICBkMy5zdW0gPSBmdW5jdGlvbihhcnJheSwgZikge1xuICAgIHZhciBzID0gMCwgbiA9IGFycmF5Lmxlbmd0aCwgYSwgaSA9IC0xO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikgaWYgKGQzX251bWVyaWMoYSA9ICthcnJheVtpXSkpIHMgKz0gYTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmIChkM19udW1lcmljKGEgPSArZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpKSBzICs9IGE7XG4gICAgfVxuICAgIHJldHVybiBzO1xuICB9O1xuICBkMy5tZWFuID0gZnVuY3Rpb24oYXJyYXksIGYpIHtcbiAgICB2YXIgcyA9IDAsIG4gPSBhcnJheS5sZW5ndGgsIGEsIGkgPSAtMSwgaiA9IG47XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoZDNfbnVtZXJpYyhhID0gZDNfbnVtYmVyKGFycmF5W2ldKSkpIHMgKz0gYTsgZWxzZSAtLWo7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoZDNfbnVtZXJpYyhhID0gZDNfbnVtYmVyKGYuY2FsbChhcnJheSwgYXJyYXlbaV0sIGkpKSkpIHMgKz0gYTsgZWxzZSAtLWo7XG4gICAgfVxuICAgIGlmIChqKSByZXR1cm4gcyAvIGo7XG4gIH07XG4gIGQzLnF1YW50aWxlID0gZnVuY3Rpb24odmFsdWVzLCBwKSB7XG4gICAgdmFyIEggPSAodmFsdWVzLmxlbmd0aCAtIDEpICogcCArIDEsIGggPSBNYXRoLmZsb29yKEgpLCB2ID0gK3ZhbHVlc1toIC0gMV0sIGUgPSBIIC0gaDtcbiAgICByZXR1cm4gZSA/IHYgKyBlICogKHZhbHVlc1toXSAtIHYpIDogdjtcbiAgfTtcbiAgZDMubWVkaWFuID0gZnVuY3Rpb24oYXJyYXksIGYpIHtcbiAgICB2YXIgbnVtYmVycyA9IFtdLCBuID0gYXJyYXkubGVuZ3RoLCBhLCBpID0gLTE7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoZDNfbnVtZXJpYyhhID0gZDNfbnVtYmVyKGFycmF5W2ldKSkpIG51bWJlcnMucHVzaChhKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmIChkM19udW1lcmljKGEgPSBkM19udW1iZXIoZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpKSkgbnVtYmVycy5wdXNoKGEpO1xuICAgIH1cbiAgICBpZiAobnVtYmVycy5sZW5ndGgpIHJldHVybiBkMy5xdWFudGlsZShudW1iZXJzLnNvcnQoZDNfYXNjZW5kaW5nKSwgLjUpO1xuICB9O1xuICBkMy52YXJpYW5jZSA9IGZ1bmN0aW9uKGFycmF5LCBmKSB7XG4gICAgdmFyIG4gPSBhcnJheS5sZW5ndGgsIG0gPSAwLCBhLCBkLCBzID0gMCwgaSA9IC0xLCBqID0gMDtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgaWYgKGQzX251bWVyaWMoYSA9IGQzX251bWJlcihhcnJheVtpXSkpKSB7XG4gICAgICAgICAgZCA9IGEgLSBtO1xuICAgICAgICAgIG0gKz0gZCAvICsrajtcbiAgICAgICAgICBzICs9IGQgKiAoYSAtIG0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIGlmIChkM19udW1lcmljKGEgPSBkM19udW1iZXIoZi5jYWxsKGFycmF5LCBhcnJheVtpXSwgaSkpKSkge1xuICAgICAgICAgIGQgPSBhIC0gbTtcbiAgICAgICAgICBtICs9IGQgLyArK2o7XG4gICAgICAgICAgcyArPSBkICogKGEgLSBtKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAoaiA+IDEpIHJldHVybiBzIC8gKGogLSAxKTtcbiAgfTtcbiAgZDMuZGV2aWF0aW9uID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHYgPSBkMy52YXJpYW5jZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiB2ID8gTWF0aC5zcXJ0KHYpIDogdjtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfYmlzZWN0b3IoY29tcGFyZSkge1xuICAgIHJldHVybiB7XG4gICAgICBsZWZ0OiBmdW5jdGlvbihhLCB4LCBsbywgaGkpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAzKSBsbyA9IDA7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgNCkgaGkgPSBhLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKGxvIDwgaGkpIHtcbiAgICAgICAgICB2YXIgbWlkID0gbG8gKyBoaSA+Pj4gMTtcbiAgICAgICAgICBpZiAoY29tcGFyZShhW21pZF0sIHgpIDwgMCkgbG8gPSBtaWQgKyAxOyBlbHNlIGhpID0gbWlkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsbztcbiAgICAgIH0sXG4gICAgICByaWdodDogZnVuY3Rpb24oYSwgeCwgbG8sIGhpKSB7XG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMykgbG8gPSAwO1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDQpIGhpID0gYS5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChsbyA8IGhpKSB7XG4gICAgICAgICAgdmFyIG1pZCA9IGxvICsgaGkgPj4+IDE7XG4gICAgICAgICAgaWYgKGNvbXBhcmUoYVttaWRdLCB4KSA+IDApIGhpID0gbWlkOyBlbHNlIGxvID0gbWlkICsgMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbG87XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICB2YXIgZDNfYmlzZWN0ID0gZDNfYmlzZWN0b3IoZDNfYXNjZW5kaW5nKTtcbiAgZDMuYmlzZWN0TGVmdCA9IGQzX2Jpc2VjdC5sZWZ0O1xuICBkMy5iaXNlY3QgPSBkMy5iaXNlY3RSaWdodCA9IGQzX2Jpc2VjdC5yaWdodDtcbiAgZDMuYmlzZWN0b3IgPSBmdW5jdGlvbihmKSB7XG4gICAgcmV0dXJuIGQzX2Jpc2VjdG9yKGYubGVuZ3RoID09PSAxID8gZnVuY3Rpb24oZCwgeCkge1xuICAgICAgcmV0dXJuIGQzX2FzY2VuZGluZyhmKGQpLCB4KTtcbiAgICB9IDogZik7XG4gIH07XG4gIGQzLnNodWZmbGUgPSBmdW5jdGlvbihhcnJheSwgaTAsIGkxKSB7XG4gICAgaWYgKChtID0gYXJndW1lbnRzLmxlbmd0aCkgPCAzKSB7XG4gICAgICBpMSA9IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmIChtIDwgMikgaTAgPSAwO1xuICAgIH1cbiAgICB2YXIgbSA9IGkxIC0gaTAsIHQsIGk7XG4gICAgd2hpbGUgKG0pIHtcbiAgICAgIGkgPSBNYXRoLnJhbmRvbSgpICogbS0tIHwgMDtcbiAgICAgIHQgPSBhcnJheVttICsgaTBdLCBhcnJheVttICsgaTBdID0gYXJyYXlbaSArIGkwXSwgYXJyYXlbaSArIGkwXSA9IHQ7XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbiAgfTtcbiAgZDMucGVybXV0ZSA9IGZ1bmN0aW9uKGFycmF5LCBpbmRleGVzKSB7XG4gICAgdmFyIGkgPSBpbmRleGVzLmxlbmd0aCwgcGVybXV0ZXMgPSBuZXcgQXJyYXkoaSk7XG4gICAgd2hpbGUgKGktLSkgcGVybXV0ZXNbaV0gPSBhcnJheVtpbmRleGVzW2ldXTtcbiAgICByZXR1cm4gcGVybXV0ZXM7XG4gIH07XG4gIGQzLnBhaXJzID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICB2YXIgaSA9IDAsIG4gPSBhcnJheS5sZW5ndGggLSAxLCBwMCwgcDEgPSBhcnJheVswXSwgcGFpcnMgPSBuZXcgQXJyYXkobiA8IDAgPyAwIDogbik7XG4gICAgd2hpbGUgKGkgPCBuKSBwYWlyc1tpXSA9IFsgcDAgPSBwMSwgcDEgPSBhcnJheVsrK2ldIF07XG4gICAgcmV0dXJuIHBhaXJzO1xuICB9O1xuICBkMy50cmFuc3Bvc2UgPSBmdW5jdGlvbihtYXRyaXgpIHtcbiAgICBpZiAoIShuID0gbWF0cml4Lmxlbmd0aCkpIHJldHVybiBbXTtcbiAgICBmb3IgKHZhciBpID0gLTEsIG0gPSBkMy5taW4obWF0cml4LCBkM190cmFuc3Bvc2VMZW5ndGgpLCB0cmFuc3Bvc2UgPSBuZXcgQXJyYXkobSk7ICsraSA8IG07ICkge1xuICAgICAgZm9yICh2YXIgaiA9IC0xLCBuLCByb3cgPSB0cmFuc3Bvc2VbaV0gPSBuZXcgQXJyYXkobik7ICsraiA8IG47ICkge1xuICAgICAgICByb3dbal0gPSBtYXRyaXhbal1baV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cmFuc3Bvc2U7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RyYW5zcG9zZUxlbmd0aChkKSB7XG4gICAgcmV0dXJuIGQubGVuZ3RoO1xuICB9XG4gIGQzLnppcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkMy50cmFuc3Bvc2UoYXJndW1lbnRzKTtcbiAgfTtcbiAgZDMua2V5cyA9IGZ1bmN0aW9uKG1hcCkge1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG1hcCkga2V5cy5wdXNoKGtleSk7XG4gICAgcmV0dXJuIGtleXM7XG4gIH07XG4gIGQzLnZhbHVlcyA9IGZ1bmN0aW9uKG1hcCkge1xuICAgIHZhciB2YWx1ZXMgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gbWFwKSB2YWx1ZXMucHVzaChtYXBba2V5XSk7XG4gICAgcmV0dXJuIHZhbHVlcztcbiAgfTtcbiAgZDMuZW50cmllcyA9IGZ1bmN0aW9uKG1hcCkge1xuICAgIHZhciBlbnRyaWVzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG1hcCkgZW50cmllcy5wdXNoKHtcbiAgICAgIGtleToga2V5LFxuICAgICAgdmFsdWU6IG1hcFtrZXldXG4gICAgfSk7XG4gICAgcmV0dXJuIGVudHJpZXM7XG4gIH07XG4gIGQzLm1lcmdlID0gZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgdmFyIG4gPSBhcnJheXMubGVuZ3RoLCBtLCBpID0gLTEsIGogPSAwLCBtZXJnZWQsIGFycmF5O1xuICAgIHdoaWxlICgrK2kgPCBuKSBqICs9IGFycmF5c1tpXS5sZW5ndGg7XG4gICAgbWVyZ2VkID0gbmV3IEFycmF5KGopO1xuICAgIHdoaWxlICgtLW4gPj0gMCkge1xuICAgICAgYXJyYXkgPSBhcnJheXNbbl07XG4gICAgICBtID0gYXJyYXkubGVuZ3RoO1xuICAgICAgd2hpbGUgKC0tbSA+PSAwKSB7XG4gICAgICAgIG1lcmdlZFstLWpdID0gYXJyYXlbbV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBtZXJnZWQ7XG4gIH07XG4gIHZhciBhYnMgPSBNYXRoLmFicztcbiAgZDMucmFuZ2UgPSBmdW5jdGlvbihzdGFydCwgc3RvcCwgc3RlcCkge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMykge1xuICAgICAgc3RlcCA9IDE7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgc3RvcCA9IHN0YXJ0O1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICgoc3RvcCAtIHN0YXJ0KSAvIHN0ZXAgPT09IEluZmluaXR5KSB0aHJvdyBuZXcgRXJyb3IoXCJpbmZpbml0ZSByYW5nZVwiKTtcbiAgICB2YXIgcmFuZ2UgPSBbXSwgayA9IGQzX3JhbmdlX2ludGVnZXJTY2FsZShhYnMoc3RlcCkpLCBpID0gLTEsIGo7XG4gICAgc3RhcnQgKj0gaywgc3RvcCAqPSBrLCBzdGVwICo9IGs7XG4gICAgaWYgKHN0ZXAgPCAwKSB3aGlsZSAoKGogPSBzdGFydCArIHN0ZXAgKiArK2kpID4gc3RvcCkgcmFuZ2UucHVzaChqIC8gayk7IGVsc2Ugd2hpbGUgKChqID0gc3RhcnQgKyBzdGVwICogKytpKSA8IHN0b3ApIHJhbmdlLnB1c2goaiAvIGspO1xuICAgIHJldHVybiByYW5nZTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfcmFuZ2VfaW50ZWdlclNjYWxlKHgpIHtcbiAgICB2YXIgayA9IDE7XG4gICAgd2hpbGUgKHggKiBrICUgMSkgayAqPSAxMDtcbiAgICByZXR1cm4gaztcbiAgfVxuICBmdW5jdGlvbiBkM19jbGFzcyhjdG9yLCBwcm9wZXJ0aWVzKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHByb3BlcnRpZXMpIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjdG9yLnByb3RvdHlwZSwga2V5LCB7XG4gICAgICAgIHZhbHVlOiBwcm9wZXJ0aWVzW2tleV0sXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbiAgZDMubWFwID0gZnVuY3Rpb24ob2JqZWN0LCBmKSB7XG4gICAgdmFyIG1hcCA9IG5ldyBkM19NYXAoKTtcbiAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgZDNfTWFwKSB7XG4gICAgICBvYmplY3QuZm9yRWFjaChmdW5jdGlvbihrZXksIHZhbHVlKSB7XG4gICAgICAgIG1hcC5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkob2JqZWN0KSkge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IG9iamVjdC5sZW5ndGgsIG87XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgd2hpbGUgKCsraSA8IG4pIG1hcC5zZXQoaSwgb2JqZWN0W2ldKTsgZWxzZSB3aGlsZSAoKytpIDwgbikgbWFwLnNldChmLmNhbGwob2JqZWN0LCBvID0gb2JqZWN0W2ldLCBpKSwgbyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIG1hcC5zZXQoa2V5LCBvYmplY3Rba2V5XSk7XG4gICAgfVxuICAgIHJldHVybiBtYXA7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX01hcCgpIHtcbiAgICB0aGlzLl8gPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICB9XG4gIHZhciBkM19tYXBfcHJvdG8gPSBcIl9fcHJvdG9fX1wiLCBkM19tYXBfemVybyA9IFwiXFx4MDBcIjtcbiAgZDNfY2xhc3MoZDNfTWFwLCB7XG4gICAgaGFzOiBkM19tYXBfaGFzLFxuICAgIGdldDogZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gdGhpcy5fW2QzX21hcF9lc2NhcGUoa2V5KV07XG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICAgIHJldHVybiB0aGlzLl9bZDNfbWFwX2VzY2FwZShrZXkpXSA9IHZhbHVlO1xuICAgIH0sXG4gICAgcmVtb3ZlOiBkM19tYXBfcmVtb3ZlLFxuICAgIGtleXM6IGQzX21hcF9rZXlzLFxuICAgIHZhbHVlczogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdmFsdWVzID0gW107XG4gICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5fKSB2YWx1ZXMucHVzaCh0aGlzLl9ba2V5XSk7XG4gICAgICByZXR1cm4gdmFsdWVzO1xuICAgIH0sXG4gICAgZW50cmllczogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgZW50cmllcyA9IFtdO1xuICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMuXykgZW50cmllcy5wdXNoKHtcbiAgICAgICAga2V5OiBkM19tYXBfdW5lc2NhcGUoa2V5KSxcbiAgICAgICAgdmFsdWU6IHRoaXMuX1trZXldXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBlbnRyaWVzO1xuICAgIH0sXG4gICAgc2l6ZTogZDNfbWFwX3NpemUsXG4gICAgZW1wdHk6IGQzX21hcF9lbXB0eSxcbiAgICBmb3JFYWNoOiBmdW5jdGlvbihmKSB7XG4gICAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5fKSBmLmNhbGwodGhpcywgZDNfbWFwX3VuZXNjYXBlKGtleSksIHRoaXMuX1trZXldKTtcbiAgICB9XG4gIH0pO1xuICBmdW5jdGlvbiBkM19tYXBfZXNjYXBlKGtleSkge1xuICAgIHJldHVybiAoa2V5ICs9IFwiXCIpID09PSBkM19tYXBfcHJvdG8gfHwga2V5WzBdID09PSBkM19tYXBfemVybyA/IGQzX21hcF96ZXJvICsga2V5IDoga2V5O1xuICB9XG4gIGZ1bmN0aW9uIGQzX21hcF91bmVzY2FwZShrZXkpIHtcbiAgICByZXR1cm4gKGtleSArPSBcIlwiKVswXSA9PT0gZDNfbWFwX3plcm8gPyBrZXkuc2xpY2UoMSkgOiBrZXk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbWFwX2hhcyhrZXkpIHtcbiAgICByZXR1cm4gZDNfbWFwX2VzY2FwZShrZXkpIGluIHRoaXMuXztcbiAgfVxuICBmdW5jdGlvbiBkM19tYXBfcmVtb3ZlKGtleSkge1xuICAgIHJldHVybiAoa2V5ID0gZDNfbWFwX2VzY2FwZShrZXkpKSBpbiB0aGlzLl8gJiYgZGVsZXRlIHRoaXMuX1trZXldO1xuICB9XG4gIGZ1bmN0aW9uIGQzX21hcF9rZXlzKCkge1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMuXykga2V5cy5wdXNoKGQzX21hcF91bmVzY2FwZShrZXkpKTtcbiAgICByZXR1cm4ga2V5cztcbiAgfVxuICBmdW5jdGlvbiBkM19tYXBfc2l6ZSgpIHtcbiAgICB2YXIgc2l6ZSA9IDA7XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMuXykgKytzaXplO1xuICAgIHJldHVybiBzaXplO1xuICB9XG4gIGZ1bmN0aW9uIGQzX21hcF9lbXB0eSgpIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gdGhpcy5fKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgZDMubmVzdCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBuZXN0ID0ge30sIGtleXMgPSBbXSwgc29ydEtleXMgPSBbXSwgc29ydFZhbHVlcywgcm9sbHVwO1xuICAgIGZ1bmN0aW9uIG1hcChtYXBUeXBlLCBhcnJheSwgZGVwdGgpIHtcbiAgICAgIGlmIChkZXB0aCA+PSBrZXlzLmxlbmd0aCkgcmV0dXJuIHJvbGx1cCA/IHJvbGx1cC5jYWxsKG5lc3QsIGFycmF5KSA6IHNvcnRWYWx1ZXMgPyBhcnJheS5zb3J0KHNvcnRWYWx1ZXMpIDogYXJyYXk7XG4gICAgICB2YXIgaSA9IC0xLCBuID0gYXJyYXkubGVuZ3RoLCBrZXkgPSBrZXlzW2RlcHRoKytdLCBrZXlWYWx1ZSwgb2JqZWN0LCBzZXR0ZXIsIHZhbHVlc0J5S2V5ID0gbmV3IGQzX01hcCgpLCB2YWx1ZXM7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBpZiAodmFsdWVzID0gdmFsdWVzQnlLZXkuZ2V0KGtleVZhbHVlID0ga2V5KG9iamVjdCA9IGFycmF5W2ldKSkpIHtcbiAgICAgICAgICB2YWx1ZXMucHVzaChvYmplY3QpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlc0J5S2V5LnNldChrZXlWYWx1ZSwgWyBvYmplY3QgXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChtYXBUeXBlKSB7XG4gICAgICAgIG9iamVjdCA9IG1hcFR5cGUoKTtcbiAgICAgICAgc2V0dGVyID0gZnVuY3Rpb24oa2V5VmFsdWUsIHZhbHVlcykge1xuICAgICAgICAgIG9iamVjdC5zZXQoa2V5VmFsdWUsIG1hcChtYXBUeXBlLCB2YWx1ZXMsIGRlcHRoKSk7XG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvYmplY3QgPSB7fTtcbiAgICAgICAgc2V0dGVyID0gZnVuY3Rpb24oa2V5VmFsdWUsIHZhbHVlcykge1xuICAgICAgICAgIG9iamVjdFtrZXlWYWx1ZV0gPSBtYXAobWFwVHlwZSwgdmFsdWVzLCBkZXB0aCk7XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICB2YWx1ZXNCeUtleS5mb3JFYWNoKHNldHRlcik7XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBlbnRyaWVzKG1hcCwgZGVwdGgpIHtcbiAgICAgIGlmIChkZXB0aCA+PSBrZXlzLmxlbmd0aCkgcmV0dXJuIG1hcDtcbiAgICAgIHZhciBhcnJheSA9IFtdLCBzb3J0S2V5ID0gc29ydEtleXNbZGVwdGgrK107XG4gICAgICBtYXAuZm9yRWFjaChmdW5jdGlvbihrZXksIGtleU1hcCkge1xuICAgICAgICBhcnJheS5wdXNoKHtcbiAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICB2YWx1ZXM6IGVudHJpZXMoa2V5TWFwLCBkZXB0aClcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBzb3J0S2V5ID8gYXJyYXkuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBzb3J0S2V5KGEua2V5LCBiLmtleSk7XG4gICAgICB9KSA6IGFycmF5O1xuICAgIH1cbiAgICBuZXN0Lm1hcCA9IGZ1bmN0aW9uKGFycmF5LCBtYXBUeXBlKSB7XG4gICAgICByZXR1cm4gbWFwKG1hcFR5cGUsIGFycmF5LCAwKTtcbiAgICB9O1xuICAgIG5lc3QuZW50cmllcyA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgICByZXR1cm4gZW50cmllcyhtYXAoZDMubWFwLCBhcnJheSwgMCksIDApO1xuICAgIH07XG4gICAgbmVzdC5rZXkgPSBmdW5jdGlvbihkKSB7XG4gICAgICBrZXlzLnB1c2goZCk7XG4gICAgICByZXR1cm4gbmVzdDtcbiAgICB9O1xuICAgIG5lc3Quc29ydEtleXMgPSBmdW5jdGlvbihvcmRlcikge1xuICAgICAgc29ydEtleXNba2V5cy5sZW5ndGggLSAxXSA9IG9yZGVyO1xuICAgICAgcmV0dXJuIG5lc3Q7XG4gICAgfTtcbiAgICBuZXN0LnNvcnRWYWx1ZXMgPSBmdW5jdGlvbihvcmRlcikge1xuICAgICAgc29ydFZhbHVlcyA9IG9yZGVyO1xuICAgICAgcmV0dXJuIG5lc3Q7XG4gICAgfTtcbiAgICBuZXN0LnJvbGx1cCA9IGZ1bmN0aW9uKGYpIHtcbiAgICAgIHJvbGx1cCA9IGY7XG4gICAgICByZXR1cm4gbmVzdDtcbiAgICB9O1xuICAgIHJldHVybiBuZXN0O1xuICB9O1xuICBkMy5zZXQgPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHZhciBzZXQgPSBuZXcgZDNfU2V0KCk7XG4gICAgaWYgKGFycmF5KSBmb3IgKHZhciBpID0gMCwgbiA9IGFycmF5Lmxlbmd0aDsgaSA8IG47ICsraSkgc2V0LmFkZChhcnJheVtpXSk7XG4gICAgcmV0dXJuIHNldDtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfU2V0KCkge1xuICAgIHRoaXMuXyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gIH1cbiAgZDNfY2xhc3MoZDNfU2V0LCB7XG4gICAgaGFzOiBkM19tYXBfaGFzLFxuICAgIGFkZDogZnVuY3Rpb24oa2V5KSB7XG4gICAgICB0aGlzLl9bZDNfbWFwX2VzY2FwZShrZXkgKz0gXCJcIildID0gdHJ1ZTtcbiAgICAgIHJldHVybiBrZXk7XG4gICAgfSxcbiAgICByZW1vdmU6IGQzX21hcF9yZW1vdmUsXG4gICAgdmFsdWVzOiBkM19tYXBfa2V5cyxcbiAgICBzaXplOiBkM19tYXBfc2l6ZSxcbiAgICBlbXB0eTogZDNfbWFwX2VtcHR5LFxuICAgIGZvckVhY2g6IGZ1bmN0aW9uKGYpIHtcbiAgICAgIGZvciAodmFyIGtleSBpbiB0aGlzLl8pIGYuY2FsbCh0aGlzLCBkM19tYXBfdW5lc2NhcGUoa2V5KSk7XG4gICAgfVxuICB9KTtcbiAgZDMuYmVoYXZpb3IgPSB7fTtcbiAgZnVuY3Rpb24gZDNfaWRlbnRpdHkoZCkge1xuICAgIHJldHVybiBkO1xuICB9XG4gIGQzLnJlYmluZCA9IGZ1bmN0aW9uKHRhcmdldCwgc291cmNlKSB7XG4gICAgdmFyIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aCwgbWV0aG9kO1xuICAgIHdoaWxlICgrK2kgPCBuKSB0YXJnZXRbbWV0aG9kID0gYXJndW1lbnRzW2ldXSA9IGQzX3JlYmluZCh0YXJnZXQsIHNvdXJjZSwgc291cmNlW21ldGhvZF0pO1xuICAgIHJldHVybiB0YXJnZXQ7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3JlYmluZCh0YXJnZXQsIHNvdXJjZSwgbWV0aG9kKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHZhbHVlID0gbWV0aG9kLmFwcGx5KHNvdXJjZSwgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gc291cmNlID8gdGFyZ2V0IDogdmFsdWU7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM192ZW5kb3JTeW1ib2wob2JqZWN0LCBuYW1lKSB7XG4gICAgaWYgKG5hbWUgaW4gb2JqZWN0KSByZXR1cm4gbmFtZTtcbiAgICBuYW1lID0gbmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIG5hbWUuc2xpY2UoMSk7XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBkM192ZW5kb3JQcmVmaXhlcy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgIHZhciBwcmVmaXhOYW1lID0gZDNfdmVuZG9yUHJlZml4ZXNbaV0gKyBuYW1lO1xuICAgICAgaWYgKHByZWZpeE5hbWUgaW4gb2JqZWN0KSByZXR1cm4gcHJlZml4TmFtZTtcbiAgICB9XG4gIH1cbiAgdmFyIGQzX3ZlbmRvclByZWZpeGVzID0gWyBcIndlYmtpdFwiLCBcIm1zXCIsIFwibW96XCIsIFwiTW96XCIsIFwib1wiLCBcIk9cIiBdO1xuICBmdW5jdGlvbiBkM19ub29wKCkge31cbiAgZDMuZGlzcGF0Y2ggPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZGlzcGF0Y2ggPSBuZXcgZDNfZGlzcGF0Y2goKSwgaSA9IC0xLCBuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICB3aGlsZSAoKytpIDwgbikgZGlzcGF0Y2hbYXJndW1lbnRzW2ldXSA9IGQzX2Rpc3BhdGNoX2V2ZW50KGRpc3BhdGNoKTtcbiAgICByZXR1cm4gZGlzcGF0Y2g7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2Rpc3BhdGNoKCkge31cbiAgZDNfZGlzcGF0Y2gucHJvdG90eXBlLm9uID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgICB2YXIgaSA9IHR5cGUuaW5kZXhPZihcIi5cIiksIG5hbWUgPSBcIlwiO1xuICAgIGlmIChpID49IDApIHtcbiAgICAgIG5hbWUgPSB0eXBlLnNsaWNlKGkgKyAxKTtcbiAgICAgIHR5cGUgPSB0eXBlLnNsaWNlKDAsIGkpO1xuICAgIH1cbiAgICBpZiAodHlwZSkgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPCAyID8gdGhpc1t0eXBlXS5vbihuYW1lKSA6IHRoaXNbdHlwZV0ub24obmFtZSwgbGlzdGVuZXIpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyKSB7XG4gICAgICBpZiAobGlzdGVuZXIgPT0gbnVsbCkgZm9yICh0eXBlIGluIHRoaXMpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkodHlwZSkpIHRoaXNbdHlwZV0ub24obmFtZSwgbnVsbCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2Rpc3BhdGNoX2V2ZW50KGRpc3BhdGNoKSB7XG4gICAgdmFyIGxpc3RlbmVycyA9IFtdLCBsaXN0ZW5lckJ5TmFtZSA9IG5ldyBkM19NYXAoKTtcbiAgICBmdW5jdGlvbiBldmVudCgpIHtcbiAgICAgIHZhciB6ID0gbGlzdGVuZXJzLCBpID0gLTEsIG4gPSB6Lmxlbmd0aCwgbDtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBpZiAobCA9IHpbaV0ub24pIGwuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiBkaXNwYXRjaDtcbiAgICB9XG4gICAgZXZlbnQub24gPSBmdW5jdGlvbihuYW1lLCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGwgPSBsaXN0ZW5lckJ5TmFtZS5nZXQobmFtZSksIGk7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHJldHVybiBsICYmIGwub247XG4gICAgICBpZiAobCkge1xuICAgICAgICBsLm9uID0gbnVsbDtcbiAgICAgICAgbGlzdGVuZXJzID0gbGlzdGVuZXJzLnNsaWNlKDAsIGkgPSBsaXN0ZW5lcnMuaW5kZXhPZihsKSkuY29uY2F0KGxpc3RlbmVycy5zbGljZShpICsgMSkpO1xuICAgICAgICBsaXN0ZW5lckJ5TmFtZS5yZW1vdmUobmFtZSk7XG4gICAgICB9XG4gICAgICBpZiAobGlzdGVuZXIpIGxpc3RlbmVycy5wdXNoKGxpc3RlbmVyQnlOYW1lLnNldChuYW1lLCB7XG4gICAgICAgIG9uOiBsaXN0ZW5lclxuICAgICAgfSkpO1xuICAgICAgcmV0dXJuIGRpc3BhdGNoO1xuICAgIH07XG4gICAgcmV0dXJuIGV2ZW50O1xuICB9XG4gIGQzLmV2ZW50ID0gbnVsbDtcbiAgZnVuY3Rpb24gZDNfZXZlbnRQcmV2ZW50RGVmYXVsdCgpIHtcbiAgICBkMy5ldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2V2ZW50U291cmNlKCkge1xuICAgIHZhciBlID0gZDMuZXZlbnQsIHM7XG4gICAgd2hpbGUgKHMgPSBlLnNvdXJjZUV2ZW50KSBlID0gcztcbiAgICByZXR1cm4gZTtcbiAgfVxuICBmdW5jdGlvbiBkM19ldmVudERpc3BhdGNoKHRhcmdldCkge1xuICAgIHZhciBkaXNwYXRjaCA9IG5ldyBkM19kaXNwYXRjaCgpLCBpID0gMCwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgd2hpbGUgKCsraSA8IG4pIGRpc3BhdGNoW2FyZ3VtZW50c1tpXV0gPSBkM19kaXNwYXRjaF9ldmVudChkaXNwYXRjaCk7XG4gICAgZGlzcGF0Y2gub2YgPSBmdW5jdGlvbih0aGl6LCBhcmd1bWVudHopIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihlMSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHZhciBlMCA9IGUxLnNvdXJjZUV2ZW50ID0gZDMuZXZlbnQ7XG4gICAgICAgICAgZTEudGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgICAgIGQzLmV2ZW50ID0gZTE7XG4gICAgICAgICAgZGlzcGF0Y2hbZTEudHlwZV0uYXBwbHkodGhpeiwgYXJndW1lbnR6KTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBkMy5ldmVudCA9IGUwO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH07XG4gICAgcmV0dXJuIGRpc3BhdGNoO1xuICB9XG4gIGQzLnJlcXVvdGUgPSBmdW5jdGlvbihzKSB7XG4gICAgcmV0dXJuIHMucmVwbGFjZShkM19yZXF1b3RlX3JlLCBcIlxcXFwkJlwiKTtcbiAgfTtcbiAgdmFyIGQzX3JlcXVvdGVfcmUgPSAvW1xcXFxcXF5cXCRcXCpcXCtcXD9cXHxcXFtcXF1cXChcXClcXC5cXHtcXH1dL2c7XG4gIHZhciBkM19zdWJjbGFzcyA9IHt9Ll9fcHJvdG9fXyA/IGZ1bmN0aW9uKG9iamVjdCwgcHJvdG90eXBlKSB7XG4gICAgb2JqZWN0Ll9fcHJvdG9fXyA9IHByb3RvdHlwZTtcbiAgfSA6IGZ1bmN0aW9uKG9iamVjdCwgcHJvdG90eXBlKSB7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gcHJvdG90eXBlKSBvYmplY3RbcHJvcGVydHldID0gcHJvdG90eXBlW3Byb3BlcnR5XTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uKGdyb3Vwcykge1xuICAgIGQzX3N1YmNsYXNzKGdyb3VwcywgZDNfc2VsZWN0aW9uUHJvdG90eXBlKTtcbiAgICByZXR1cm4gZ3JvdXBzO1xuICB9XG4gIHZhciBkM19zZWxlY3QgPSBmdW5jdGlvbihzLCBuKSB7XG4gICAgcmV0dXJuIG4ucXVlcnlTZWxlY3RvcihzKTtcbiAgfSwgZDNfc2VsZWN0QWxsID0gZnVuY3Rpb24ocywgbikge1xuICAgIHJldHVybiBuLnF1ZXJ5U2VsZWN0b3JBbGwocyk7XG4gIH0sIGQzX3NlbGVjdE1hdGNoZXMgPSBmdW5jdGlvbihuLCBzKSB7XG4gICAgdmFyIGQzX3NlbGVjdE1hdGNoZXIgPSBuLm1hdGNoZXMgfHwgbltkM192ZW5kb3JTeW1ib2wobiwgXCJtYXRjaGVzU2VsZWN0b3JcIildO1xuICAgIGQzX3NlbGVjdE1hdGNoZXMgPSBmdW5jdGlvbihuLCBzKSB7XG4gICAgICByZXR1cm4gZDNfc2VsZWN0TWF0Y2hlci5jYWxsKG4sIHMpO1xuICAgIH07XG4gICAgcmV0dXJuIGQzX3NlbGVjdE1hdGNoZXMobiwgcyk7XG4gIH07XG4gIGlmICh0eXBlb2YgU2l6emxlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICBkM19zZWxlY3QgPSBmdW5jdGlvbihzLCBuKSB7XG4gICAgICByZXR1cm4gU2l6emxlKHMsIG4pWzBdIHx8IG51bGw7XG4gICAgfTtcbiAgICBkM19zZWxlY3RBbGwgPSBTaXp6bGU7XG4gICAgZDNfc2VsZWN0TWF0Y2hlcyA9IFNpenpsZS5tYXRjaGVzU2VsZWN0b3I7XG4gIH1cbiAgZDMuc2VsZWN0aW9uID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzLnNlbGVjdChkM19kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpO1xuICB9O1xuICB2YXIgZDNfc2VsZWN0aW9uUHJvdG90eXBlID0gZDMuc2VsZWN0aW9uLnByb3RvdHlwZSA9IFtdO1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuc2VsZWN0ID0gZnVuY3Rpb24oc2VsZWN0b3IpIHtcbiAgICB2YXIgc3ViZ3JvdXBzID0gW10sIHN1Ymdyb3VwLCBzdWJub2RlLCBncm91cCwgbm9kZTtcbiAgICBzZWxlY3RvciA9IGQzX3NlbGVjdGlvbl9zZWxlY3RvcihzZWxlY3Rvcik7XG4gICAgZm9yICh2YXIgaiA9IC0xLCBtID0gdGhpcy5sZW5ndGg7ICsraiA8IG07ICkge1xuICAgICAgc3ViZ3JvdXBzLnB1c2goc3ViZ3JvdXAgPSBbXSk7XG4gICAgICBzdWJncm91cC5wYXJlbnROb2RlID0gKGdyb3VwID0gdGhpc1tqXSkucGFyZW50Tm9kZTtcbiAgICAgIGZvciAodmFyIGkgPSAtMSwgbiA9IGdyb3VwLmxlbmd0aDsgKytpIDwgbjsgKSB7XG4gICAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIHtcbiAgICAgICAgICBzdWJncm91cC5wdXNoKHN1Ym5vZGUgPSBzZWxlY3Rvci5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGksIGopKTtcbiAgICAgICAgICBpZiAoc3Vibm9kZSAmJiBcIl9fZGF0YV9fXCIgaW4gbm9kZSkgc3Vibm9kZS5fX2RhdGFfXyA9IG5vZGUuX19kYXRhX187XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3ViZ3JvdXAucHVzaChudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uKHN1Ymdyb3Vwcyk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9zZWxlY3RvcihzZWxlY3Rvcikge1xuICAgIHJldHVybiB0eXBlb2Ygc2VsZWN0b3IgPT09IFwiZnVuY3Rpb25cIiA/IHNlbGVjdG9yIDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2VsZWN0KHNlbGVjdG9yLCB0aGlzKTtcbiAgICB9O1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5zZWxlY3RBbGwgPSBmdW5jdGlvbihzZWxlY3Rvcikge1xuICAgIHZhciBzdWJncm91cHMgPSBbXSwgc3ViZ3JvdXAsIG5vZGU7XG4gICAgc2VsZWN0b3IgPSBkM19zZWxlY3Rpb25fc2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuICAgIGZvciAodmFyIGogPSAtMSwgbSA9IHRoaXMubGVuZ3RoOyArK2ogPCBtOyApIHtcbiAgICAgIGZvciAodmFyIGdyb3VwID0gdGhpc1tqXSwgaSA9IC0xLCBuID0gZ3JvdXAubGVuZ3RoOyArK2kgPCBuOyApIHtcbiAgICAgICAgaWYgKG5vZGUgPSBncm91cFtpXSkge1xuICAgICAgICAgIHN1Ymdyb3Vwcy5wdXNoKHN1Ymdyb3VwID0gZDNfYXJyYXkoc2VsZWN0b3IuY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKSkpO1xuICAgICAgICAgIHN1Ymdyb3VwLnBhcmVudE5vZGUgPSBub2RlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkM19zZWxlY3Rpb24oc3ViZ3JvdXBzKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX3NlbGVjdG9yQWxsKHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJmdW5jdGlvblwiID8gc2VsZWN0b3IgOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkM19zZWxlY3RBbGwoc2VsZWN0b3IsIHRoaXMpO1xuICAgIH07XG4gIH1cbiAgdmFyIGQzX25zWGh0bWwgPSBcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWxcIjtcbiAgdmFyIGQzX25zUHJlZml4ID0ge1xuICAgIHN2ZzogXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFxuICAgIHhodG1sOiBkM19uc1hodG1sLFxuICAgIHhsaW5rOiBcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmtcIixcbiAgICB4bWw6IFwiaHR0cDovL3d3dy53My5vcmcvWE1MLzE5OTgvbmFtZXNwYWNlXCIsXG4gICAgeG1sbnM6IFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC94bWxucy9cIlxuICB9O1xuICBkMy5ucyA9IHtcbiAgICBwcmVmaXg6IGQzX25zUHJlZml4LFxuICAgIHF1YWxpZnk6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHZhciBpID0gbmFtZS5pbmRleE9mKFwiOlwiKSwgcHJlZml4ID0gbmFtZTtcbiAgICAgIGlmIChpID49IDAgJiYgKHByZWZpeCA9IG5hbWUuc2xpY2UoMCwgaSkpICE9PSBcInhtbG5zXCIpIG5hbWUgPSBuYW1lLnNsaWNlKGkgKyAxKTtcbiAgICAgIHJldHVybiBkM19uc1ByZWZpeC5oYXNPd25Qcm9wZXJ0eShwcmVmaXgpID8ge1xuICAgICAgICBzcGFjZTogZDNfbnNQcmVmaXhbcHJlZml4XSxcbiAgICAgICAgbG9jYWw6IG5hbWVcbiAgICAgIH0gOiBuYW1lO1xuICAgIH1cbiAgfTtcbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLmF0dHIgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikge1xuICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHZhciBub2RlID0gdGhpcy5ub2RlKCk7XG4gICAgICAgIG5hbWUgPSBkMy5ucy5xdWFsaWZ5KG5hbWUpO1xuICAgICAgICByZXR1cm4gbmFtZS5sb2NhbCA/IG5vZGUuZ2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCkgOiBub2RlLmdldEF0dHJpYnV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICAgIGZvciAodmFsdWUgaW4gbmFtZSkgdGhpcy5lYWNoKGQzX3NlbGVjdGlvbl9hdHRyKHZhbHVlLCBuYW1lW3ZhbHVlXSkpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmVhY2goZDNfc2VsZWN0aW9uX2F0dHIobmFtZSwgdmFsdWUpKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX2F0dHIobmFtZSwgdmFsdWUpIHtcbiAgICBuYW1lID0gZDMubnMucXVhbGlmeShuYW1lKTtcbiAgICBmdW5jdGlvbiBhdHRyTnVsbCgpIHtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyTnVsbE5TKCkge1xuICAgICAgdGhpcy5yZW1vdmVBdHRyaWJ1dGVOUyhuYW1lLnNwYWNlLCBuYW1lLmxvY2FsKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXR0ckNvbnN0YW50KCkge1xuICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUobmFtZSwgdmFsdWUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyQ29uc3RhbnROUygpIHtcbiAgICAgIHRoaXMuc2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCwgdmFsdWUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyRnVuY3Rpb24oKSB7XG4gICAgICB2YXIgeCA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICBpZiAoeCA9PSBudWxsKSB0aGlzLnJlbW92ZUF0dHJpYnV0ZShuYW1lKTsgZWxzZSB0aGlzLnNldEF0dHJpYnV0ZShuYW1lLCB4KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXR0ckZ1bmN0aW9uTlMoKSB7XG4gICAgICB2YXIgeCA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICBpZiAoeCA9PSBudWxsKSB0aGlzLnJlbW92ZUF0dHJpYnV0ZU5TKG5hbWUuc3BhY2UsIG5hbWUubG9jYWwpOyBlbHNlIHRoaXMuc2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCwgeCk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZSA9PSBudWxsID8gbmFtZS5sb2NhbCA/IGF0dHJOdWxsTlMgOiBhdHRyTnVsbCA6IHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gbmFtZS5sb2NhbCA/IGF0dHJGdW5jdGlvbk5TIDogYXR0ckZ1bmN0aW9uIDogbmFtZS5sb2NhbCA/IGF0dHJDb25zdGFudE5TIDogYXR0ckNvbnN0YW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2NvbGxhcHNlKHMpIHtcbiAgICByZXR1cm4gcy50cmltKCkucmVwbGFjZSgvXFxzKy9nLCBcIiBcIik7XG4gIH1cbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLmNsYXNzZWQgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikge1xuICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHZhciBub2RlID0gdGhpcy5ub2RlKCksIG4gPSAobmFtZSA9IGQzX3NlbGVjdGlvbl9jbGFzc2VzKG5hbWUpKS5sZW5ndGgsIGkgPSAtMTtcbiAgICAgICAgaWYgKHZhbHVlID0gbm9kZS5jbGFzc0xpc3QpIHtcbiAgICAgICAgICB3aGlsZSAoKytpIDwgbikgaWYgKCF2YWx1ZS5jb250YWlucyhuYW1lW2ldKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlID0gbm9kZS5nZXRBdHRyaWJ1dGUoXCJjbGFzc1wiKTtcbiAgICAgICAgICB3aGlsZSAoKytpIDwgbikgaWYgKCFkM19zZWxlY3Rpb25fY2xhc3NlZFJlKG5hbWVbaV0pLnRlc3QodmFsdWUpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICBmb3IgKHZhbHVlIGluIG5hbWUpIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fY2xhc3NlZCh2YWx1ZSwgbmFtZVt2YWx1ZV0pKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lYWNoKGQzX3NlbGVjdGlvbl9jbGFzc2VkKG5hbWUsIHZhbHVlKSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9jbGFzc2VkUmUobmFtZSkge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKFwiKD86XnxcXFxccyspXCIgKyBkMy5yZXF1b3RlKG5hbWUpICsgXCIoPzpcXFxccyt8JClcIiwgXCJnXCIpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9jbGFzc2VzKG5hbWUpIHtcbiAgICByZXR1cm4gKG5hbWUgKyBcIlwiKS50cmltKCkuc3BsaXQoL158XFxzKy8pO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9jbGFzc2VkKG5hbWUsIHZhbHVlKSB7XG4gICAgbmFtZSA9IGQzX3NlbGVjdGlvbl9jbGFzc2VzKG5hbWUpLm1hcChkM19zZWxlY3Rpb25fY2xhc3NlZE5hbWUpO1xuICAgIHZhciBuID0gbmFtZS5sZW5ndGg7XG4gICAgZnVuY3Rpb24gY2xhc3NlZENvbnN0YW50KCkge1xuICAgICAgdmFyIGkgPSAtMTtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBuYW1lW2ldKHRoaXMsIHZhbHVlKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY2xhc3NlZEZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGkgPSAtMSwgeCA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB3aGlsZSAoKytpIDwgbikgbmFtZVtpXSh0aGlzLCB4KTtcbiAgICB9XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gY2xhc3NlZEZ1bmN0aW9uIDogY2xhc3NlZENvbnN0YW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9jbGFzc2VkTmFtZShuYW1lKSB7XG4gICAgdmFyIHJlID0gZDNfc2VsZWN0aW9uX2NsYXNzZWRSZShuYW1lKTtcbiAgICByZXR1cm4gZnVuY3Rpb24obm9kZSwgdmFsdWUpIHtcbiAgICAgIGlmIChjID0gbm9kZS5jbGFzc0xpc3QpIHJldHVybiB2YWx1ZSA/IGMuYWRkKG5hbWUpIDogYy5yZW1vdmUobmFtZSk7XG4gICAgICB2YXIgYyA9IG5vZGUuZ2V0QXR0cmlidXRlKFwiY2xhc3NcIikgfHwgXCJcIjtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICByZS5sYXN0SW5kZXggPSAwO1xuICAgICAgICBpZiAoIXJlLnRlc3QoYykpIG5vZGUuc2V0QXR0cmlidXRlKFwiY2xhc3NcIiwgZDNfY29sbGFwc2UoYyArIFwiIFwiICsgbmFtZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoXCJjbGFzc1wiLCBkM19jb2xsYXBzZShjLnJlcGxhY2UocmUsIFwiIFwiKSkpO1xuICAgICAgfVxuICAgIH07XG4gIH1cbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLnN0eWxlID0gZnVuY3Rpb24obmFtZSwgdmFsdWUsIHByaW9yaXR5KSB7XG4gICAgdmFyIG4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIGlmIChuIDwgMykge1xuICAgICAgaWYgKHR5cGVvZiBuYW1lICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIGlmIChuIDwgMikgdmFsdWUgPSBcIlwiO1xuICAgICAgICBmb3IgKHByaW9yaXR5IGluIG5hbWUpIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fc3R5bGUocHJpb3JpdHksIG5hbWVbcHJpb3JpdHldLCB2YWx1ZSkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cbiAgICAgIGlmIChuIDwgMikge1xuICAgICAgICB2YXIgbm9kZSA9IHRoaXMubm9kZSgpO1xuICAgICAgICByZXR1cm4gZDNfd2luZG93KG5vZGUpLmdldENvbXB1dGVkU3R5bGUobm9kZSwgbnVsbCkuZ2V0UHJvcGVydHlWYWx1ZShuYW1lKTtcbiAgICAgIH1cbiAgICAgIHByaW9yaXR5ID0gXCJcIjtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fc3R5bGUobmFtZSwgdmFsdWUsIHByaW9yaXR5KSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9zdHlsZShuYW1lLCB2YWx1ZSwgcHJpb3JpdHkpIHtcbiAgICBmdW5jdGlvbiBzdHlsZU51bGwoKSB7XG4gICAgICB0aGlzLnN0eWxlLnJlbW92ZVByb3BlcnR5KG5hbWUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdHlsZUNvbnN0YW50KCkge1xuICAgICAgdGhpcy5zdHlsZS5zZXRQcm9wZXJ0eShuYW1lLCB2YWx1ZSwgcHJpb3JpdHkpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdHlsZUZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHggPSB2YWx1ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgaWYgKHggPT0gbnVsbCkgdGhpcy5zdHlsZS5yZW1vdmVQcm9wZXJ0eShuYW1lKTsgZWxzZSB0aGlzLnN0eWxlLnNldFByb3BlcnR5KG5hbWUsIHgsIHByaW9yaXR5KTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlID09IG51bGwgPyBzdHlsZU51bGwgOiB0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIiA/IHN0eWxlRnVuY3Rpb24gOiBzdHlsZUNvbnN0YW50O1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5wcm9wZXJ0eSA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICBpZiAodHlwZW9mIG5hbWUgPT09IFwic3RyaW5nXCIpIHJldHVybiB0aGlzLm5vZGUoKVtuYW1lXTtcbiAgICAgIGZvciAodmFsdWUgaW4gbmFtZSkgdGhpcy5lYWNoKGQzX3NlbGVjdGlvbl9wcm9wZXJ0eSh2YWx1ZSwgbmFtZVt2YWx1ZV0pKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lYWNoKGQzX3NlbGVjdGlvbl9wcm9wZXJ0eShuYW1lLCB2YWx1ZSkpO1xuICB9O1xuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25fcHJvcGVydHkobmFtZSwgdmFsdWUpIHtcbiAgICBmdW5jdGlvbiBwcm9wZXJ0eU51bGwoKSB7XG4gICAgICBkZWxldGUgdGhpc1tuYW1lXTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcHJvcGVydHlDb25zdGFudCgpIHtcbiAgICAgIHRoaXNbbmFtZV0gPSB2YWx1ZTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcHJvcGVydHlGdW5jdGlvbigpIHtcbiAgICAgIHZhciB4ID0gdmFsdWUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIGlmICh4ID09IG51bGwpIGRlbGV0ZSB0aGlzW25hbWVdOyBlbHNlIHRoaXNbbmFtZV0gPSB4O1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWUgPT0gbnVsbCA/IHByb3BlcnR5TnVsbCA6IHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gcHJvcGVydHlGdW5jdGlvbiA6IHByb3BlcnR5Q29uc3RhbnQ7XG4gIH1cbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLnRleHQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gdGhpcy5lYWNoKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdiA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB0aGlzLnRleHRDb250ZW50ID0gdiA9PSBudWxsID8gXCJcIiA6IHY7XG4gICAgfSA6IHZhbHVlID09IG51bGwgPyBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMudGV4dENvbnRlbnQgPSBcIlwiO1xuICAgIH0gOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMudGV4dENvbnRlbnQgPSB2YWx1ZTtcbiAgICB9KSA6IHRoaXMubm9kZSgpLnRleHRDb250ZW50O1xuICB9O1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuaHRtbCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyB0aGlzLmVhY2godHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCIgPyBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2ID0gdmFsdWUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHRoaXMuaW5uZXJIVE1MID0gdiA9PSBudWxsID8gXCJcIiA6IHY7XG4gICAgfSA6IHZhbHVlID09IG51bGwgPyBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuaW5uZXJIVE1MID0gXCJcIjtcbiAgICB9IDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLmlubmVySFRNTCA9IHZhbHVlO1xuICAgIH0pIDogdGhpcy5ub2RlKCkuaW5uZXJIVE1MO1xuICB9O1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuYXBwZW5kID0gZnVuY3Rpb24obmFtZSkge1xuICAgIG5hbWUgPSBkM19zZWxlY3Rpb25fY3JlYXRvcihuYW1lKTtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3QoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5hcHBlbmRDaGlsZChuYW1lLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpO1xuICAgIH0pO1xuICB9O1xuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25fY3JlYXRvcihuYW1lKSB7XG4gICAgZnVuY3Rpb24gY3JlYXRlKCkge1xuICAgICAgdmFyIGRvY3VtZW50ID0gdGhpcy5vd25lckRvY3VtZW50LCBuYW1lc3BhY2UgPSB0aGlzLm5hbWVzcGFjZVVSSTtcbiAgICAgIHJldHVybiBuYW1lc3BhY2UgPT09IGQzX25zWGh0bWwgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50Lm5hbWVzcGFjZVVSSSA9PT0gZDNfbnNYaHRtbCA/IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQobmFtZSkgOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMobmFtZXNwYWNlLCBuYW1lKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY3JlYXRlTlMoKSB7XG4gICAgICByZXR1cm4gdGhpcy5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhuYW1lLnNwYWNlLCBuYW1lLmxvY2FsKTtcbiAgICB9XG4gICAgcmV0dXJuIHR5cGVvZiBuYW1lID09PSBcImZ1bmN0aW9uXCIgPyBuYW1lIDogKG5hbWUgPSBkMy5ucy5xdWFsaWZ5KG5hbWUpKS5sb2NhbCA/IGNyZWF0ZU5TIDogY3JlYXRlO1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5pbnNlcnQgPSBmdW5jdGlvbihuYW1lLCBiZWZvcmUpIHtcbiAgICBuYW1lID0gZDNfc2VsZWN0aW9uX2NyZWF0b3IobmFtZSk7XG4gICAgYmVmb3JlID0gZDNfc2VsZWN0aW9uX3NlbGVjdG9yKGJlZm9yZSk7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0KGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuaW5zZXJ0QmVmb3JlKG5hbWUuYXBwbHkodGhpcywgYXJndW1lbnRzKSwgYmVmb3JlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgbnVsbCk7XG4gICAgfSk7XG4gIH07XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5lYWNoKGQzX3NlbGVjdGlvblJlbW92ZSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvblJlbW92ZSgpIHtcbiAgICB2YXIgcGFyZW50ID0gdGhpcy5wYXJlbnROb2RlO1xuICAgIGlmIChwYXJlbnQpIHBhcmVudC5yZW1vdmVDaGlsZCh0aGlzKTtcbiAgfVxuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuZGF0YSA9IGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICB2YXIgaSA9IC0xLCBuID0gdGhpcy5sZW5ndGgsIGdyb3VwLCBub2RlO1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgdmFsdWUgPSBuZXcgQXJyYXkobiA9IChncm91cCA9IHRoaXNbMF0pLmxlbmd0aCk7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICAgICAgdmFsdWVbaV0gPSBub2RlLl9fZGF0YV9fO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGJpbmQoZ3JvdXAsIGdyb3VwRGF0YSkge1xuICAgICAgdmFyIGksIG4gPSBncm91cC5sZW5ndGgsIG0gPSBncm91cERhdGEubGVuZ3RoLCBuMCA9IE1hdGgubWluKG4sIG0pLCB1cGRhdGVOb2RlcyA9IG5ldyBBcnJheShtKSwgZW50ZXJOb2RlcyA9IG5ldyBBcnJheShtKSwgZXhpdE5vZGVzID0gbmV3IEFycmF5KG4pLCBub2RlLCBub2RlRGF0YTtcbiAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgdmFyIG5vZGVCeUtleVZhbHVlID0gbmV3IGQzX01hcCgpLCBrZXlWYWx1ZXMgPSBuZXcgQXJyYXkobiksIGtleVZhbHVlO1xuICAgICAgICBmb3IgKGkgPSAtMTsgKytpIDwgbjsgKSB7XG4gICAgICAgICAgaWYgKG5vZGUgPSBncm91cFtpXSkge1xuICAgICAgICAgICAgaWYgKG5vZGVCeUtleVZhbHVlLmhhcyhrZXlWYWx1ZSA9IGtleS5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGkpKSkge1xuICAgICAgICAgICAgICBleGl0Tm9kZXNbaV0gPSBub2RlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgbm9kZUJ5S2V5VmFsdWUuc2V0KGtleVZhbHVlLCBub2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGtleVZhbHVlc1tpXSA9IGtleVZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAtMTsgKytpIDwgbTsgKSB7XG4gICAgICAgICAgaWYgKCEobm9kZSA9IG5vZGVCeUtleVZhbHVlLmdldChrZXlWYWx1ZSA9IGtleS5jYWxsKGdyb3VwRGF0YSwgbm9kZURhdGEgPSBncm91cERhdGFbaV0sIGkpKSkpIHtcbiAgICAgICAgICAgIGVudGVyTm9kZXNbaV0gPSBkM19zZWxlY3Rpb25fZGF0YU5vZGUobm9kZURhdGEpO1xuICAgICAgICAgIH0gZWxzZSBpZiAobm9kZSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgdXBkYXRlTm9kZXNbaV0gPSBub2RlO1xuICAgICAgICAgICAgbm9kZS5fX2RhdGFfXyA9IG5vZGVEYXRhO1xuICAgICAgICAgIH1cbiAgICAgICAgICBub2RlQnlLZXlWYWx1ZS5zZXQoa2V5VmFsdWUsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IC0xOyArK2kgPCBuOyApIHtcbiAgICAgICAgICBpZiAoaSBpbiBrZXlWYWx1ZXMgJiYgbm9kZUJ5S2V5VmFsdWUuZ2V0KGtleVZhbHVlc1tpXSkgIT09IHRydWUpIHtcbiAgICAgICAgICAgIGV4aXROb2Rlc1tpXSA9IGdyb3VwW2ldO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9yIChpID0gLTE7ICsraSA8IG4wOyApIHtcbiAgICAgICAgICBub2RlID0gZ3JvdXBbaV07XG4gICAgICAgICAgbm9kZURhdGEgPSBncm91cERhdGFbaV07XG4gICAgICAgICAgaWYgKG5vZGUpIHtcbiAgICAgICAgICAgIG5vZGUuX19kYXRhX18gPSBub2RlRGF0YTtcbiAgICAgICAgICAgIHVwZGF0ZU5vZGVzW2ldID0gbm9kZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZW50ZXJOb2Rlc1tpXSA9IGQzX3NlbGVjdGlvbl9kYXRhTm9kZShub2RlRGF0YSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAoO2kgPCBtOyArK2kpIHtcbiAgICAgICAgICBlbnRlck5vZGVzW2ldID0gZDNfc2VsZWN0aW9uX2RhdGFOb2RlKGdyb3VwRGF0YVtpXSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yICg7aSA8IG47ICsraSkge1xuICAgICAgICAgIGV4aXROb2Rlc1tpXSA9IGdyb3VwW2ldO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBlbnRlck5vZGVzLnVwZGF0ZSA9IHVwZGF0ZU5vZGVzO1xuICAgICAgZW50ZXJOb2Rlcy5wYXJlbnROb2RlID0gdXBkYXRlTm9kZXMucGFyZW50Tm9kZSA9IGV4aXROb2Rlcy5wYXJlbnROb2RlID0gZ3JvdXAucGFyZW50Tm9kZTtcbiAgICAgIGVudGVyLnB1c2goZW50ZXJOb2Rlcyk7XG4gICAgICB1cGRhdGUucHVzaCh1cGRhdGVOb2Rlcyk7XG4gICAgICBleGl0LnB1c2goZXhpdE5vZGVzKTtcbiAgICB9XG4gICAgdmFyIGVudGVyID0gZDNfc2VsZWN0aW9uX2VudGVyKFtdKSwgdXBkYXRlID0gZDNfc2VsZWN0aW9uKFtdKSwgZXhpdCA9IGQzX3NlbGVjdGlvbihbXSk7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBiaW5kKGdyb3VwID0gdGhpc1tpXSwgdmFsdWUuY2FsbChncm91cCwgZ3JvdXAucGFyZW50Tm9kZS5fX2RhdGFfXywgaSkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBiaW5kKGdyb3VwID0gdGhpc1tpXSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgICB1cGRhdGUuZW50ZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBlbnRlcjtcbiAgICB9O1xuICAgIHVwZGF0ZS5leGl0ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZXhpdDtcbiAgICB9O1xuICAgIHJldHVybiB1cGRhdGU7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9kYXRhTm9kZShkYXRhKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIF9fZGF0YV9fOiBkYXRhXG4gICAgfTtcbiAgfVxuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuZGF0dW0gPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gdGhpcy5wcm9wZXJ0eShcIl9fZGF0YV9fXCIsIHZhbHVlKSA6IHRoaXMucHJvcGVydHkoXCJfX2RhdGFfX1wiKTtcbiAgfTtcbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLmZpbHRlciA9IGZ1bmN0aW9uKGZpbHRlcikge1xuICAgIHZhciBzdWJncm91cHMgPSBbXSwgc3ViZ3JvdXAsIGdyb3VwLCBub2RlO1xuICAgIGlmICh0eXBlb2YgZmlsdGVyICE9PSBcImZ1bmN0aW9uXCIpIGZpbHRlciA9IGQzX3NlbGVjdGlvbl9maWx0ZXIoZmlsdGVyKTtcbiAgICBmb3IgKHZhciBqID0gMCwgbSA9IHRoaXMubGVuZ3RoOyBqIDwgbTsgaisrKSB7XG4gICAgICBzdWJncm91cHMucHVzaChzdWJncm91cCA9IFtdKTtcbiAgICAgIHN1Ymdyb3VwLnBhcmVudE5vZGUgPSAoZ3JvdXAgPSB0aGlzW2pdKS5wYXJlbnROb2RlO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIG4gPSBncm91cC5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgaWYgKChub2RlID0gZ3JvdXBbaV0pICYmIGZpbHRlci5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGksIGopKSB7XG4gICAgICAgICAgc3ViZ3JvdXAucHVzaChub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uKHN1Ymdyb3Vwcyk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9maWx0ZXIoc2VsZWN0b3IpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2VsZWN0TWF0Y2hlcyh0aGlzLCBzZWxlY3Rvcik7XG4gICAgfTtcbiAgfVxuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUub3JkZXIgPSBmdW5jdGlvbigpIHtcbiAgICBmb3IgKHZhciBqID0gLTEsIG0gPSB0aGlzLmxlbmd0aDsgKytqIDwgbTsgKSB7XG4gICAgICBmb3IgKHZhciBncm91cCA9IHRoaXNbal0sIGkgPSBncm91cC5sZW5ndGggLSAxLCBuZXh0ID0gZ3JvdXBbaV0sIG5vZGU7IC0taSA+PSAwOyApIHtcbiAgICAgICAgaWYgKG5vZGUgPSBncm91cFtpXSkge1xuICAgICAgICAgIGlmIChuZXh0ICYmIG5leHQgIT09IG5vZGUubmV4dFNpYmxpbmcpIG5leHQucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgbmV4dCk7XG4gICAgICAgICAgbmV4dCA9IG5vZGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5zb3J0ID0gZnVuY3Rpb24oY29tcGFyYXRvcikge1xuICAgIGNvbXBhcmF0b3IgPSBkM19zZWxlY3Rpb25fc29ydENvbXBhcmF0b3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICBmb3IgKHZhciBqID0gLTEsIG0gPSB0aGlzLmxlbmd0aDsgKytqIDwgbTsgKSB0aGlzW2pdLnNvcnQoY29tcGFyYXRvcik7XG4gICAgcmV0dXJuIHRoaXMub3JkZXIoKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX3NvcnRDb21wYXJhdG9yKGNvbXBhcmF0b3IpIHtcbiAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIGNvbXBhcmF0b3IgPSBkM19hc2NlbmRpbmc7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgIHJldHVybiBhICYmIGIgPyBjb21wYXJhdG9yKGEuX19kYXRhX18sIGIuX19kYXRhX18pIDogIWEgLSAhYjtcbiAgICB9O1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5lYWNoID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uX2VhY2godGhpcywgZnVuY3Rpb24obm9kZSwgaSwgaikge1xuICAgICAgY2FsbGJhY2suY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKTtcbiAgICB9KTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX2VhY2goZ3JvdXBzLCBjYWxsYmFjaykge1xuICAgIGZvciAodmFyIGogPSAwLCBtID0gZ3JvdXBzLmxlbmd0aDsgaiA8IG07IGorKykge1xuICAgICAgZm9yICh2YXIgZ3JvdXAgPSBncm91cHNbal0sIGkgPSAwLCBuID0gZ3JvdXAubGVuZ3RoLCBub2RlOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIGNhbGxiYWNrKG5vZGUsIGksIGopO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZ3JvdXBzO1xuICB9XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5jYWxsID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICB2YXIgYXJncyA9IGQzX2FycmF5KGFyZ3VtZW50cyk7XG4gICAgY2FsbGJhY2suYXBwbHkoYXJnc1swXSA9IHRoaXMsIGFyZ3MpO1xuICAgIHJldHVybiB0aGlzO1xuICB9O1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUuZW1wdHkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gIXRoaXMubm9kZSgpO1xuICB9O1xuICBkM19zZWxlY3Rpb25Qcm90b3R5cGUubm9kZSA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIGogPSAwLCBtID0gdGhpcy5sZW5ndGg7IGogPCBtOyBqKyspIHtcbiAgICAgIGZvciAodmFyIGdyb3VwID0gdGhpc1tqXSwgaSA9IDAsIG4gPSBncm91cC5sZW5ndGg7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgdmFyIG5vZGUgPSBncm91cFtpXTtcbiAgICAgICAgaWYgKG5vZGUpIHJldHVybiBub2RlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfTtcbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLnNpemUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbiA9IDA7XG4gICAgZDNfc2VsZWN0aW9uX2VhY2godGhpcywgZnVuY3Rpb24oKSB7XG4gICAgICArK247XG4gICAgfSk7XG4gICAgcmV0dXJuIG47XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9lbnRlcihzZWxlY3Rpb24pIHtcbiAgICBkM19zdWJjbGFzcyhzZWxlY3Rpb24sIGQzX3NlbGVjdGlvbl9lbnRlclByb3RvdHlwZSk7XG4gICAgcmV0dXJuIHNlbGVjdGlvbjtcbiAgfVxuICB2YXIgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlID0gW107XG4gIGQzLnNlbGVjdGlvbi5lbnRlciA9IGQzX3NlbGVjdGlvbl9lbnRlcjtcbiAgZDMuc2VsZWN0aW9uLmVudGVyLnByb3RvdHlwZSA9IGQzX3NlbGVjdGlvbl9lbnRlclByb3RvdHlwZTtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLmFwcGVuZCA9IGQzX3NlbGVjdGlvblByb3RvdHlwZS5hcHBlbmQ7XG4gIGQzX3NlbGVjdGlvbl9lbnRlclByb3RvdHlwZS5lbXB0eSA9IGQzX3NlbGVjdGlvblByb3RvdHlwZS5lbXB0eTtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLm5vZGUgPSBkM19zZWxlY3Rpb25Qcm90b3R5cGUubm9kZTtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLmNhbGwgPSBkM19zZWxlY3Rpb25Qcm90b3R5cGUuY2FsbDtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLnNpemUgPSBkM19zZWxlY3Rpb25Qcm90b3R5cGUuc2l6ZTtcbiAgZDNfc2VsZWN0aW9uX2VudGVyUHJvdG90eXBlLnNlbGVjdCA9IGZ1bmN0aW9uKHNlbGVjdG9yKSB7XG4gICAgdmFyIHN1Ymdyb3VwcyA9IFtdLCBzdWJncm91cCwgc3Vibm9kZSwgdXBncm91cCwgZ3JvdXAsIG5vZGU7XG4gICAgZm9yICh2YXIgaiA9IC0xLCBtID0gdGhpcy5sZW5ndGg7ICsraiA8IG07ICkge1xuICAgICAgdXBncm91cCA9IChncm91cCA9IHRoaXNbal0pLnVwZGF0ZTtcbiAgICAgIHN1Ymdyb3Vwcy5wdXNoKHN1Ymdyb3VwID0gW10pO1xuICAgICAgc3ViZ3JvdXAucGFyZW50Tm9kZSA9IGdyb3VwLnBhcmVudE5vZGU7XG4gICAgICBmb3IgKHZhciBpID0gLTEsIG4gPSBncm91cC5sZW5ndGg7ICsraSA8IG47ICkge1xuICAgICAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICAgICAgc3ViZ3JvdXAucHVzaCh1cGdyb3VwW2ldID0gc3Vibm9kZSA9IHNlbGVjdG9yLmNhbGwoZ3JvdXAucGFyZW50Tm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgaikpO1xuICAgICAgICAgIHN1Ym5vZGUuX19kYXRhX18gPSBub2RlLl9fZGF0YV9fO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN1Ymdyb3VwLnB1c2gobnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGQzX3NlbGVjdGlvbihzdWJncm91cHMpO1xuICB9O1xuICBkM19zZWxlY3Rpb25fZW50ZXJQcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24obmFtZSwgYmVmb3JlKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSBiZWZvcmUgPSBkM19zZWxlY3Rpb25fZW50ZXJJbnNlcnRCZWZvcmUodGhpcyk7XG4gICAgcmV0dXJuIGQzX3NlbGVjdGlvblByb3RvdHlwZS5pbnNlcnQuY2FsbCh0aGlzLCBuYW1lLCBiZWZvcmUpO1xuICB9O1xuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25fZW50ZXJJbnNlcnRCZWZvcmUoZW50ZXIpIHtcbiAgICB2YXIgaTAsIGowO1xuICAgIHJldHVybiBmdW5jdGlvbihkLCBpLCBqKSB7XG4gICAgICB2YXIgZ3JvdXAgPSBlbnRlcltqXS51cGRhdGUsIG4gPSBncm91cC5sZW5ndGgsIG5vZGU7XG4gICAgICBpZiAoaiAhPSBqMCkgajAgPSBqLCBpMCA9IDA7XG4gICAgICBpZiAoaSA+PSBpMCkgaTAgPSBpICsgMTtcbiAgICAgIHdoaWxlICghKG5vZGUgPSBncm91cFtpMF0pICYmICsraTAgPCBuKSA7XG4gICAgICByZXR1cm4gbm9kZTtcbiAgICB9O1xuICB9XG4gIGQzLnNlbGVjdCA9IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICB2YXIgZ3JvdXA7XG4gICAgaWYgKHR5cGVvZiBub2RlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBncm91cCA9IFsgZDNfc2VsZWN0KG5vZGUsIGQzX2RvY3VtZW50KSBdO1xuICAgICAgZ3JvdXAucGFyZW50Tm9kZSA9IGQzX2RvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgZ3JvdXAgPSBbIG5vZGUgXTtcbiAgICAgIGdyb3VwLnBhcmVudE5vZGUgPSBkM19kb2N1bWVudEVsZW1lbnQobm9kZSk7XG4gICAgfVxuICAgIHJldHVybiBkM19zZWxlY3Rpb24oWyBncm91cCBdKTtcbiAgfTtcbiAgZDMuc2VsZWN0QWxsID0gZnVuY3Rpb24obm9kZXMpIHtcbiAgICB2YXIgZ3JvdXA7XG4gICAgaWYgKHR5cGVvZiBub2RlcyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgZ3JvdXAgPSBkM19hcnJheShkM19zZWxlY3RBbGwobm9kZXMsIGQzX2RvY3VtZW50KSk7XG4gICAgICBncm91cC5wYXJlbnROb2RlID0gZDNfZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgIH0gZWxzZSB7XG4gICAgICBncm91cCA9IGQzX2FycmF5KG5vZGVzKTtcbiAgICAgIGdyb3VwLnBhcmVudE5vZGUgPSBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uKFsgZ3JvdXAgXSk7XG4gIH07XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyLCBjYXB0dXJlKSB7XG4gICAgdmFyIG4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIGlmIChuIDwgMykge1xuICAgICAgaWYgKHR5cGVvZiB0eXBlICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIGlmIChuIDwgMikgbGlzdGVuZXIgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjYXB0dXJlIGluIHR5cGUpIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fb24oY2FwdHVyZSwgdHlwZVtjYXB0dXJlXSwgbGlzdGVuZXIpKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG4gICAgICBpZiAobiA8IDIpIHJldHVybiAobiA9IHRoaXMubm9kZSgpW1wiX19vblwiICsgdHlwZV0pICYmIG4uXztcbiAgICAgIGNhcHR1cmUgPSBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZWFjaChkM19zZWxlY3Rpb25fb24odHlwZSwgbGlzdGVuZXIsIGNhcHR1cmUpKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2VsZWN0aW9uX29uKHR5cGUsIGxpc3RlbmVyLCBjYXB0dXJlKSB7XG4gICAgdmFyIG5hbWUgPSBcIl9fb25cIiArIHR5cGUsIGkgPSB0eXBlLmluZGV4T2YoXCIuXCIpLCB3cmFwID0gZDNfc2VsZWN0aW9uX29uTGlzdGVuZXI7XG4gICAgaWYgKGkgPiAwKSB0eXBlID0gdHlwZS5zbGljZSgwLCBpKTtcbiAgICB2YXIgZmlsdGVyID0gZDNfc2VsZWN0aW9uX29uRmlsdGVycy5nZXQodHlwZSk7XG4gICAgaWYgKGZpbHRlcikgdHlwZSA9IGZpbHRlciwgd3JhcCA9IGQzX3NlbGVjdGlvbl9vbkZpbHRlcjtcbiAgICBmdW5jdGlvbiBvblJlbW92ZSgpIHtcbiAgICAgIHZhciBsID0gdGhpc1tuYW1lXTtcbiAgICAgIGlmIChsKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcih0eXBlLCBsLCBsLiQpO1xuICAgICAgICBkZWxldGUgdGhpc1tuYW1lXTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gb25BZGQoKSB7XG4gICAgICB2YXIgbCA9IHdyYXAobGlzdGVuZXIsIGQzX2FycmF5KGFyZ3VtZW50cykpO1xuICAgICAgb25SZW1vdmUuY2FsbCh0aGlzKTtcbiAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCB0aGlzW25hbWVdID0gbCwgbC4kID0gY2FwdHVyZSk7XG4gICAgICBsLl8gPSBsaXN0ZW5lcjtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVtb3ZlQWxsKCkge1xuICAgICAgdmFyIHJlID0gbmV3IFJlZ0V4cChcIl5fX29uKFteLl0rKVwiICsgZDMucmVxdW90ZSh0eXBlKSArIFwiJFwiKSwgbWF0Y2g7XG4gICAgICBmb3IgKHZhciBuYW1lIGluIHRoaXMpIHtcbiAgICAgICAgaWYgKG1hdGNoID0gbmFtZS5tYXRjaChyZSkpIHtcbiAgICAgICAgICB2YXIgbCA9IHRoaXNbbmFtZV07XG4gICAgICAgICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKG1hdGNoWzFdLCBsLCBsLiQpO1xuICAgICAgICAgIGRlbGV0ZSB0aGlzW25hbWVdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBpID8gbGlzdGVuZXIgPyBvbkFkZCA6IG9uUmVtb3ZlIDogbGlzdGVuZXIgPyBkM19ub29wIDogcmVtb3ZlQWxsO1xuICB9XG4gIHZhciBkM19zZWxlY3Rpb25fb25GaWx0ZXJzID0gZDMubWFwKHtcbiAgICBtb3VzZWVudGVyOiBcIm1vdXNlb3ZlclwiLFxuICAgIG1vdXNlbGVhdmU6IFwibW91c2VvdXRcIlxuICB9KTtcbiAgaWYgKGQzX2RvY3VtZW50KSB7XG4gICAgZDNfc2VsZWN0aW9uX29uRmlsdGVycy5mb3JFYWNoKGZ1bmN0aW9uKGspIHtcbiAgICAgIGlmIChcIm9uXCIgKyBrIGluIGQzX2RvY3VtZW50KSBkM19zZWxlY3Rpb25fb25GaWx0ZXJzLnJlbW92ZShrKTtcbiAgICB9KTtcbiAgfVxuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25fb25MaXN0ZW5lcihsaXN0ZW5lciwgYXJndW1lbnR6KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGUpIHtcbiAgICAgIHZhciBvID0gZDMuZXZlbnQ7XG4gICAgICBkMy5ldmVudCA9IGU7XG4gICAgICBhcmd1bWVudHpbMF0gPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGlzdGVuZXIuYXBwbHkodGhpcywgYXJndW1lbnR6KTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGQzLmV2ZW50ID0gbztcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NlbGVjdGlvbl9vbkZpbHRlcihsaXN0ZW5lciwgYXJndW1lbnR6KSB7XG4gICAgdmFyIGwgPSBkM19zZWxlY3Rpb25fb25MaXN0ZW5lcihsaXN0ZW5lciwgYXJndW1lbnR6KTtcbiAgICByZXR1cm4gZnVuY3Rpb24oZSkge1xuICAgICAgdmFyIHRhcmdldCA9IHRoaXMsIHJlbGF0ZWQgPSBlLnJlbGF0ZWRUYXJnZXQ7XG4gICAgICBpZiAoIXJlbGF0ZWQgfHwgcmVsYXRlZCAhPT0gdGFyZ2V0ICYmICEocmVsYXRlZC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbih0YXJnZXQpICYgOCkpIHtcbiAgICAgICAgbC5jYWxsKHRhcmdldCwgZSk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICB2YXIgZDNfZXZlbnRfZHJhZ1NlbGVjdCwgZDNfZXZlbnRfZHJhZ0lkID0gMDtcbiAgZnVuY3Rpb24gZDNfZXZlbnRfZHJhZ1N1cHByZXNzKG5vZGUpIHtcbiAgICB2YXIgbmFtZSA9IFwiLmRyYWdzdXBwcmVzcy1cIiArICsrZDNfZXZlbnRfZHJhZ0lkLCBjbGljayA9IFwiY2xpY2tcIiArIG5hbWUsIHcgPSBkMy5zZWxlY3QoZDNfd2luZG93KG5vZGUpKS5vbihcInRvdWNobW92ZVwiICsgbmFtZSwgZDNfZXZlbnRQcmV2ZW50RGVmYXVsdCkub24oXCJkcmFnc3RhcnRcIiArIG5hbWUsIGQzX2V2ZW50UHJldmVudERlZmF1bHQpLm9uKFwic2VsZWN0c3RhcnRcIiArIG5hbWUsIGQzX2V2ZW50UHJldmVudERlZmF1bHQpO1xuICAgIGlmIChkM19ldmVudF9kcmFnU2VsZWN0ID09IG51bGwpIHtcbiAgICAgIGQzX2V2ZW50X2RyYWdTZWxlY3QgPSBcIm9uc2VsZWN0c3RhcnRcIiBpbiBub2RlID8gZmFsc2UgOiBkM192ZW5kb3JTeW1ib2wobm9kZS5zdHlsZSwgXCJ1c2VyU2VsZWN0XCIpO1xuICAgIH1cbiAgICBpZiAoZDNfZXZlbnRfZHJhZ1NlbGVjdCkge1xuICAgICAgdmFyIHN0eWxlID0gZDNfZG9jdW1lbnRFbGVtZW50KG5vZGUpLnN0eWxlLCBzZWxlY3QgPSBzdHlsZVtkM19ldmVudF9kcmFnU2VsZWN0XTtcbiAgICAgIHN0eWxlW2QzX2V2ZW50X2RyYWdTZWxlY3RdID0gXCJub25lXCI7XG4gICAgfVxuICAgIHJldHVybiBmdW5jdGlvbihzdXBwcmVzc0NsaWNrKSB7XG4gICAgICB3Lm9uKG5hbWUsIG51bGwpO1xuICAgICAgaWYgKGQzX2V2ZW50X2RyYWdTZWxlY3QpIHN0eWxlW2QzX2V2ZW50X2RyYWdTZWxlY3RdID0gc2VsZWN0O1xuICAgICAgaWYgKHN1cHByZXNzQ2xpY2spIHtcbiAgICAgICAgdmFyIG9mZiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHcub24oY2xpY2ssIG51bGwpO1xuICAgICAgICB9O1xuICAgICAgICB3Lm9uKGNsaWNrLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBkM19ldmVudFByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgb2ZmKCk7XG4gICAgICAgIH0sIHRydWUpO1xuICAgICAgICBzZXRUaW1lb3V0KG9mZiwgMCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICBkMy5tb3VzZSA9IGZ1bmN0aW9uKGNvbnRhaW5lcikge1xuICAgIHJldHVybiBkM19tb3VzZVBvaW50KGNvbnRhaW5lciwgZDNfZXZlbnRTb3VyY2UoKSk7XG4gIH07XG4gIHZhciBkM19tb3VzZV9idWc0NDA4MyA9IHRoaXMubmF2aWdhdG9yICYmIC9XZWJLaXQvLnRlc3QodGhpcy5uYXZpZ2F0b3IudXNlckFnZW50KSA/IC0xIDogMDtcbiAgZnVuY3Rpb24gZDNfbW91c2VQb2ludChjb250YWluZXIsIGUpIHtcbiAgICBpZiAoZS5jaGFuZ2VkVG91Y2hlcykgZSA9IGUuY2hhbmdlZFRvdWNoZXNbMF07XG4gICAgdmFyIHN2ZyA9IGNvbnRhaW5lci5vd25lclNWR0VsZW1lbnQgfHwgY29udGFpbmVyO1xuICAgIGlmIChzdmcuY3JlYXRlU1ZHUG9pbnQpIHtcbiAgICAgIHZhciBwb2ludCA9IHN2Zy5jcmVhdGVTVkdQb2ludCgpO1xuICAgICAgaWYgKGQzX21vdXNlX2J1ZzQ0MDgzIDwgMCkge1xuICAgICAgICB2YXIgd2luZG93ID0gZDNfd2luZG93KGNvbnRhaW5lcik7XG4gICAgICAgIGlmICh3aW5kb3cuc2Nyb2xsWCB8fCB3aW5kb3cuc2Nyb2xsWSkge1xuICAgICAgICAgIHN2ZyA9IGQzLnNlbGVjdChcImJvZHlcIikuYXBwZW5kKFwic3ZnXCIpLnN0eWxlKHtcbiAgICAgICAgICAgIHBvc2l0aW9uOiBcImFic29sdXRlXCIsXG4gICAgICAgICAgICB0b3A6IDAsXG4gICAgICAgICAgICBsZWZ0OiAwLFxuICAgICAgICAgICAgbWFyZ2luOiAwLFxuICAgICAgICAgICAgcGFkZGluZzogMCxcbiAgICAgICAgICAgIGJvcmRlcjogXCJub25lXCJcbiAgICAgICAgICB9LCBcImltcG9ydGFudFwiKTtcbiAgICAgICAgICB2YXIgY3RtID0gc3ZnWzBdWzBdLmdldFNjcmVlbkNUTSgpO1xuICAgICAgICAgIGQzX21vdXNlX2J1ZzQ0MDgzID0gIShjdG0uZiB8fCBjdG0uZSk7XG4gICAgICAgICAgc3ZnLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZDNfbW91c2VfYnVnNDQwODMpIHBvaW50LnggPSBlLnBhZ2VYLCBwb2ludC55ID0gZS5wYWdlWTsgZWxzZSBwb2ludC54ID0gZS5jbGllbnRYLCBcbiAgICAgIHBvaW50LnkgPSBlLmNsaWVudFk7XG4gICAgICBwb2ludCA9IHBvaW50Lm1hdHJpeFRyYW5zZm9ybShjb250YWluZXIuZ2V0U2NyZWVuQ1RNKCkuaW52ZXJzZSgpKTtcbiAgICAgIHJldHVybiBbIHBvaW50LngsIHBvaW50LnkgXTtcbiAgICB9XG4gICAgdmFyIHJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgcmV0dXJuIFsgZS5jbGllbnRYIC0gcmVjdC5sZWZ0IC0gY29udGFpbmVyLmNsaWVudExlZnQsIGUuY2xpZW50WSAtIHJlY3QudG9wIC0gY29udGFpbmVyLmNsaWVudFRvcCBdO1xuICB9XG4gIGQzLnRvdWNoID0gZnVuY3Rpb24oY29udGFpbmVyLCB0b3VjaGVzLCBpZGVudGlmaWVyKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAzKSBpZGVudGlmaWVyID0gdG91Y2hlcywgdG91Y2hlcyA9IGQzX2V2ZW50U291cmNlKCkuY2hhbmdlZFRvdWNoZXM7XG4gICAgaWYgKHRvdWNoZXMpIGZvciAodmFyIGkgPSAwLCBuID0gdG91Y2hlcy5sZW5ndGgsIHRvdWNoOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAoKHRvdWNoID0gdG91Y2hlc1tpXSkuaWRlbnRpZmllciA9PT0gaWRlbnRpZmllcikge1xuICAgICAgICByZXR1cm4gZDNfbW91c2VQb2ludChjb250YWluZXIsIHRvdWNoKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIGQzLmJlaGF2aW9yLmRyYWcgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZXZlbnQgPSBkM19ldmVudERpc3BhdGNoKGRyYWcsIFwiZHJhZ1wiLCBcImRyYWdzdGFydFwiLCBcImRyYWdlbmRcIiksIG9yaWdpbiA9IG51bGwsIG1vdXNlZG93biA9IGRyYWdzdGFydChkM19ub29wLCBkMy5tb3VzZSwgZDNfd2luZG93LCBcIm1vdXNlbW92ZVwiLCBcIm1vdXNldXBcIiksIHRvdWNoc3RhcnQgPSBkcmFnc3RhcnQoZDNfYmVoYXZpb3JfZHJhZ1RvdWNoSWQsIGQzLnRvdWNoLCBkM19pZGVudGl0eSwgXCJ0b3VjaG1vdmVcIiwgXCJ0b3VjaGVuZFwiKTtcbiAgICBmdW5jdGlvbiBkcmFnKCkge1xuICAgICAgdGhpcy5vbihcIm1vdXNlZG93bi5kcmFnXCIsIG1vdXNlZG93bikub24oXCJ0b3VjaHN0YXJ0LmRyYWdcIiwgdG91Y2hzdGFydCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRyYWdzdGFydChpZCwgcG9zaXRpb24sIHN1YmplY3QsIG1vdmUsIGVuZCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdGhhdCA9IHRoaXMsIHRhcmdldCA9IGQzLmV2ZW50LnRhcmdldC5jb3JyZXNwb25kaW5nRWxlbWVudCB8fCBkMy5ldmVudC50YXJnZXQsIHBhcmVudCA9IHRoYXQucGFyZW50Tm9kZSwgZGlzcGF0Y2ggPSBldmVudC5vZih0aGF0LCBhcmd1bWVudHMpLCBkcmFnZ2VkID0gMCwgZHJhZ0lkID0gaWQoKSwgZHJhZ05hbWUgPSBcIi5kcmFnXCIgKyAoZHJhZ0lkID09IG51bGwgPyBcIlwiIDogXCItXCIgKyBkcmFnSWQpLCBkcmFnT2Zmc2V0LCBkcmFnU3ViamVjdCA9IGQzLnNlbGVjdChzdWJqZWN0KHRhcmdldCkpLm9uKG1vdmUgKyBkcmFnTmFtZSwgbW92ZWQpLm9uKGVuZCArIGRyYWdOYW1lLCBlbmRlZCksIGRyYWdSZXN0b3JlID0gZDNfZXZlbnRfZHJhZ1N1cHByZXNzKHRhcmdldCksIHBvc2l0aW9uMCA9IHBvc2l0aW9uKHBhcmVudCwgZHJhZ0lkKTtcbiAgICAgICAgaWYgKG9yaWdpbikge1xuICAgICAgICAgIGRyYWdPZmZzZXQgPSBvcmlnaW4uYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgICAgICAgICBkcmFnT2Zmc2V0ID0gWyBkcmFnT2Zmc2V0LnggLSBwb3NpdGlvbjBbMF0sIGRyYWdPZmZzZXQueSAtIHBvc2l0aW9uMFsxXSBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRyYWdPZmZzZXQgPSBbIDAsIDAgXTtcbiAgICAgICAgfVxuICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgdHlwZTogXCJkcmFnc3RhcnRcIlxuICAgICAgICB9KTtcbiAgICAgICAgZnVuY3Rpb24gbW92ZWQoKSB7XG4gICAgICAgICAgdmFyIHBvc2l0aW9uMSA9IHBvc2l0aW9uKHBhcmVudCwgZHJhZ0lkKSwgZHgsIGR5O1xuICAgICAgICAgIGlmICghcG9zaXRpb24xKSByZXR1cm47XG4gICAgICAgICAgZHggPSBwb3NpdGlvbjFbMF0gLSBwb3NpdGlvbjBbMF07XG4gICAgICAgICAgZHkgPSBwb3NpdGlvbjFbMV0gLSBwb3NpdGlvbjBbMV07XG4gICAgICAgICAgZHJhZ2dlZCB8PSBkeCB8IGR5O1xuICAgICAgICAgIHBvc2l0aW9uMCA9IHBvc2l0aW9uMTtcbiAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiBcImRyYWdcIixcbiAgICAgICAgICAgIHg6IHBvc2l0aW9uMVswXSArIGRyYWdPZmZzZXRbMF0sXG4gICAgICAgICAgICB5OiBwb3NpdGlvbjFbMV0gKyBkcmFnT2Zmc2V0WzFdLFxuICAgICAgICAgICAgZHg6IGR4LFxuICAgICAgICAgICAgZHk6IGR5XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZW5kZWQoKSB7XG4gICAgICAgICAgaWYgKCFwb3NpdGlvbihwYXJlbnQsIGRyYWdJZCkpIHJldHVybjtcbiAgICAgICAgICBkcmFnU3ViamVjdC5vbihtb3ZlICsgZHJhZ05hbWUsIG51bGwpLm9uKGVuZCArIGRyYWdOYW1lLCBudWxsKTtcbiAgICAgICAgICBkcmFnUmVzdG9yZShkcmFnZ2VkKTtcbiAgICAgICAgICBkaXNwYXRjaCh7XG4gICAgICAgICAgICB0eXBlOiBcImRyYWdlbmRcIlxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICBkcmFnLm9yaWdpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG9yaWdpbjtcbiAgICAgIG9yaWdpbiA9IHg7XG4gICAgICByZXR1cm4gZHJhZztcbiAgICB9O1xuICAgIHJldHVybiBkMy5yZWJpbmQoZHJhZywgZXZlbnQsIFwib25cIik7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2JlaGF2aW9yX2RyYWdUb3VjaElkKCkge1xuICAgIHJldHVybiBkMy5ldmVudC5jaGFuZ2VkVG91Y2hlc1swXS5pZGVudGlmaWVyO1xuICB9XG4gIGQzLnRvdWNoZXMgPSBmdW5jdGlvbihjb250YWluZXIsIHRvdWNoZXMpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHRvdWNoZXMgPSBkM19ldmVudFNvdXJjZSgpLnRvdWNoZXM7XG4gICAgcmV0dXJuIHRvdWNoZXMgPyBkM19hcnJheSh0b3VjaGVzKS5tYXAoZnVuY3Rpb24odG91Y2gpIHtcbiAgICAgIHZhciBwb2ludCA9IGQzX21vdXNlUG9pbnQoY29udGFpbmVyLCB0b3VjaCk7XG4gICAgICBwb2ludC5pZGVudGlmaWVyID0gdG91Y2guaWRlbnRpZmllcjtcbiAgICAgIHJldHVybiBwb2ludDtcbiAgICB9KSA6IFtdO1xuICB9O1xuICB2YXIgzrUgPSAxZS02LCDOtTIgPSDOtSAqIM61LCDPgCA9IE1hdGguUEksIM+EID0gMiAqIM+ALCDPhM61ID0gz4QgLSDOtSwgaGFsZs+AID0gz4AgLyAyLCBkM19yYWRpYW5zID0gz4AgLyAxODAsIGQzX2RlZ3JlZXMgPSAxODAgLyDPgDtcbiAgZnVuY3Rpb24gZDNfc2duKHgpIHtcbiAgICByZXR1cm4geCA+IDAgPyAxIDogeCA8IDAgPyAtMSA6IDA7XG4gIH1cbiAgZnVuY3Rpb24gZDNfY3Jvc3MyZChhLCBiLCBjKSB7XG4gICAgcmV0dXJuIChiWzBdIC0gYVswXSkgKiAoY1sxXSAtIGFbMV0pIC0gKGJbMV0gLSBhWzFdKSAqIChjWzBdIC0gYVswXSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfYWNvcyh4KSB7XG4gICAgcmV0dXJuIHggPiAxID8gMCA6IHggPCAtMSA/IM+AIDogTWF0aC5hY29zKHgpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2FzaW4oeCkge1xuICAgIHJldHVybiB4ID4gMSA/IGhhbGbPgCA6IHggPCAtMSA/IC1oYWxmz4AgOiBNYXRoLmFzaW4oeCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2luaCh4KSB7XG4gICAgcmV0dXJuICgoeCA9IE1hdGguZXhwKHgpKSAtIDEgLyB4KSAvIDI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfY29zaCh4KSB7XG4gICAgcmV0dXJuICgoeCA9IE1hdGguZXhwKHgpKSArIDEgLyB4KSAvIDI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGFuaCh4KSB7XG4gICAgcmV0dXJuICgoeCA9IE1hdGguZXhwKDIgKiB4KSkgLSAxKSAvICh4ICsgMSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfaGF2ZXJzaW4oeCkge1xuICAgIHJldHVybiAoeCA9IE1hdGguc2luKHggLyAyKSkgKiB4O1xuICB9XG4gIHZhciDPgSA9IE1hdGguU1FSVDIsIM+BMiA9IDIsIM+BNCA9IDQ7XG4gIGQzLmludGVycG9sYXRlWm9vbSA9IGZ1bmN0aW9uKHAwLCBwMSkge1xuICAgIHZhciB1eDAgPSBwMFswXSwgdXkwID0gcDBbMV0sIHcwID0gcDBbMl0sIHV4MSA9IHAxWzBdLCB1eTEgPSBwMVsxXSwgdzEgPSBwMVsyXSwgZHggPSB1eDEgLSB1eDAsIGR5ID0gdXkxIC0gdXkwLCBkMiA9IGR4ICogZHggKyBkeSAqIGR5LCBpLCBTO1xuICAgIGlmIChkMiA8IM61Mikge1xuICAgICAgUyA9IE1hdGgubG9nKHcxIC8gdzApIC8gz4E7XG4gICAgICBpID0gZnVuY3Rpb24odCkge1xuICAgICAgICByZXR1cm4gWyB1eDAgKyB0ICogZHgsIHV5MCArIHQgKiBkeSwgdzAgKiBNYXRoLmV4cCjPgSAqIHQgKiBTKSBdO1xuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGQxID0gTWF0aC5zcXJ0KGQyKSwgYjAgPSAodzEgKiB3MSAtIHcwICogdzAgKyDPgTQgKiBkMikgLyAoMiAqIHcwICogz4EyICogZDEpLCBiMSA9ICh3MSAqIHcxIC0gdzAgKiB3MCAtIM+BNCAqIGQyKSAvICgyICogdzEgKiDPgTIgKiBkMSksIHIwID0gTWF0aC5sb2coTWF0aC5zcXJ0KGIwICogYjAgKyAxKSAtIGIwKSwgcjEgPSBNYXRoLmxvZyhNYXRoLnNxcnQoYjEgKiBiMSArIDEpIC0gYjEpO1xuICAgICAgUyA9IChyMSAtIHIwKSAvIM+BO1xuICAgICAgaSA9IGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgdmFyIHMgPSB0ICogUywgY29zaHIwID0gZDNfY29zaChyMCksIHUgPSB3MCAvICjPgTIgKiBkMSkgKiAoY29zaHIwICogZDNfdGFuaCjPgSAqIHMgKyByMCkgLSBkM19zaW5oKHIwKSk7XG4gICAgICAgIHJldHVybiBbIHV4MCArIHUgKiBkeCwgdXkwICsgdSAqIGR5LCB3MCAqIGNvc2hyMCAvIGQzX2Nvc2goz4EgKiBzICsgcjApIF07XG4gICAgICB9O1xuICAgIH1cbiAgICBpLmR1cmF0aW9uID0gUyAqIDFlMztcbiAgICByZXR1cm4gaTtcbiAgfTtcbiAgZDMuYmVoYXZpb3Iuem9vbSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB2aWV3ID0ge1xuICAgICAgeDogMCxcbiAgICAgIHk6IDAsXG4gICAgICBrOiAxXG4gICAgfSwgdHJhbnNsYXRlMCwgY2VudGVyMCwgY2VudGVyLCBzaXplID0gWyA5NjAsIDUwMCBdLCBzY2FsZUV4dGVudCA9IGQzX2JlaGF2aW9yX3pvb21JbmZpbml0eSwgZHVyYXRpb24gPSAyNTAsIHpvb21pbmcgPSAwLCBtb3VzZWRvd24gPSBcIm1vdXNlZG93bi56b29tXCIsIG1vdXNlbW92ZSA9IFwibW91c2Vtb3ZlLnpvb21cIiwgbW91c2V1cCA9IFwibW91c2V1cC56b29tXCIsIG1vdXNld2hlZWxUaW1lciwgdG91Y2hzdGFydCA9IFwidG91Y2hzdGFydC56b29tXCIsIHRvdWNodGltZSwgZXZlbnQgPSBkM19ldmVudERpc3BhdGNoKHpvb20sIFwiem9vbXN0YXJ0XCIsIFwiem9vbVwiLCBcInpvb21lbmRcIiksIHgwLCB4MSwgeTAsIHkxO1xuICAgIGlmICghZDNfYmVoYXZpb3Jfem9vbVdoZWVsKSB7XG4gICAgICBkM19iZWhhdmlvcl96b29tV2hlZWwgPSBcIm9ud2hlZWxcIiBpbiBkM19kb2N1bWVudCA/IChkM19iZWhhdmlvcl96b29tRGVsdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIC1kMy5ldmVudC5kZWx0YVkgKiAoZDMuZXZlbnQuZGVsdGFNb2RlID8gMTIwIDogMSk7XG4gICAgICB9LCBcIndoZWVsXCIpIDogXCJvbm1vdXNld2hlZWxcIiBpbiBkM19kb2N1bWVudCA/IChkM19iZWhhdmlvcl96b29tRGVsdGEgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGQzLmV2ZW50LndoZWVsRGVsdGE7XG4gICAgICB9LCBcIm1vdXNld2hlZWxcIikgOiAoZDNfYmVoYXZpb3Jfem9vbURlbHRhID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAtZDMuZXZlbnQuZGV0YWlsO1xuICAgICAgfSwgXCJNb3pNb3VzZVBpeGVsU2Nyb2xsXCIpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB6b29tKGcpIHtcbiAgICAgIGcub24obW91c2Vkb3duLCBtb3VzZWRvd25lZCkub24oZDNfYmVoYXZpb3Jfem9vbVdoZWVsICsgXCIuem9vbVwiLCBtb3VzZXdoZWVsZWQpLm9uKFwiZGJsY2xpY2suem9vbVwiLCBkYmxjbGlja2VkKS5vbih0b3VjaHN0YXJ0LCB0b3VjaHN0YXJ0ZWQpO1xuICAgIH1cbiAgICB6b29tLmV2ZW50ID0gZnVuY3Rpb24oZykge1xuICAgICAgZy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZGlzcGF0Y2ggPSBldmVudC5vZih0aGlzLCBhcmd1bWVudHMpLCB2aWV3MSA9IHZpZXc7XG4gICAgICAgIGlmIChkM190cmFuc2l0aW9uSW5oZXJpdElkKSB7XG4gICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnRyYW5zaXRpb24oKS5lYWNoKFwic3RhcnQuem9vbVwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZpZXcgPSB0aGlzLl9fY2hhcnRfXyB8fCB7XG4gICAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAgIGs6IDFcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB6b29tc3RhcnRlZChkaXNwYXRjaCk7XG4gICAgICAgICAgfSkudHdlZW4oXCJ6b29tOnpvb21cIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgZHggPSBzaXplWzBdLCBkeSA9IHNpemVbMV0sIGN4ID0gY2VudGVyMCA/IGNlbnRlcjBbMF0gOiBkeCAvIDIsIGN5ID0gY2VudGVyMCA/IGNlbnRlcjBbMV0gOiBkeSAvIDIsIGkgPSBkMy5pbnRlcnBvbGF0ZVpvb20oWyAoY3ggLSB2aWV3LngpIC8gdmlldy5rLCAoY3kgLSB2aWV3LnkpIC8gdmlldy5rLCBkeCAvIHZpZXcuayBdLCBbIChjeCAtIHZpZXcxLngpIC8gdmlldzEuaywgKGN5IC0gdmlldzEueSkgLyB2aWV3MS5rLCBkeCAvIHZpZXcxLmsgXSk7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgICAgICAgICB2YXIgbCA9IGkodCksIGsgPSBkeCAvIGxbMl07XG4gICAgICAgICAgICAgIHRoaXMuX19jaGFydF9fID0gdmlldyA9IHtcbiAgICAgICAgICAgICAgICB4OiBjeCAtIGxbMF0gKiBrLFxuICAgICAgICAgICAgICAgIHk6IGN5IC0gbFsxXSAqIGssXG4gICAgICAgICAgICAgICAgazoga1xuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICB6b29tZWQoZGlzcGF0Y2gpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KS5lYWNoKFwiaW50ZXJydXB0Lnpvb21cIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB6b29tZW5kZWQoZGlzcGF0Y2gpO1xuICAgICAgICAgIH0pLmVhY2goXCJlbmQuem9vbVwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHpvb21lbmRlZChkaXNwYXRjaCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fX2NoYXJ0X18gPSB2aWV3O1xuICAgICAgICAgIHpvb21zdGFydGVkKGRpc3BhdGNoKTtcbiAgICAgICAgICB6b29tZWQoZGlzcGF0Y2gpO1xuICAgICAgICAgIHpvb21lbmRlZChkaXNwYXRjaCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG4gICAgem9vbS50cmFuc2xhdGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIHZpZXcueCwgdmlldy55IF07XG4gICAgICB2aWV3ID0ge1xuICAgICAgICB4OiArX1swXSxcbiAgICAgICAgeTogK19bMV0sXG4gICAgICAgIGs6IHZpZXcua1xuICAgICAgfTtcbiAgICAgIHJlc2NhbGUoKTtcbiAgICAgIHJldHVybiB6b29tO1xuICAgIH07XG4gICAgem9vbS5zY2FsZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHZpZXcuaztcbiAgICAgIHZpZXcgPSB7XG4gICAgICAgIHg6IHZpZXcueCxcbiAgICAgICAgeTogdmlldy55LFxuICAgICAgICBrOiBudWxsXG4gICAgICB9O1xuICAgICAgc2NhbGVUbygrXyk7XG4gICAgICByZXNjYWxlKCk7XG4gICAgICByZXR1cm4gem9vbTtcbiAgICB9O1xuICAgIHpvb20uc2NhbGVFeHRlbnQgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzY2FsZUV4dGVudDtcbiAgICAgIHNjYWxlRXh0ZW50ID0gXyA9PSBudWxsID8gZDNfYmVoYXZpb3Jfem9vbUluZmluaXR5IDogWyArX1swXSwgK19bMV0gXTtcbiAgICAgIHJldHVybiB6b29tO1xuICAgIH07XG4gICAgem9vbS5jZW50ZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjZW50ZXI7XG4gICAgICBjZW50ZXIgPSBfICYmIFsgK19bMF0sICtfWzFdIF07XG4gICAgICByZXR1cm4gem9vbTtcbiAgICB9O1xuICAgIHpvb20uc2l6ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNpemU7XG4gICAgICBzaXplID0gXyAmJiBbICtfWzBdLCArX1sxXSBdO1xuICAgICAgcmV0dXJuIHpvb207XG4gICAgfTtcbiAgICB6b29tLmR1cmF0aW9uID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZHVyYXRpb247XG4gICAgICBkdXJhdGlvbiA9ICtfO1xuICAgICAgcmV0dXJuIHpvb207XG4gICAgfTtcbiAgICB6b29tLnggPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB4MTtcbiAgICAgIHgxID0gejtcbiAgICAgIHgwID0gei5jb3B5KCk7XG4gICAgICB2aWV3ID0ge1xuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLFxuICAgICAgICBrOiAxXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHpvb207XG4gICAgfTtcbiAgICB6b29tLnkgPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB5MTtcbiAgICAgIHkxID0gejtcbiAgICAgIHkwID0gei5jb3B5KCk7XG4gICAgICB2aWV3ID0ge1xuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLFxuICAgICAgICBrOiAxXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHpvb207XG4gICAgfTtcbiAgICBmdW5jdGlvbiBsb2NhdGlvbihwKSB7XG4gICAgICByZXR1cm4gWyAocFswXSAtIHZpZXcueCkgLyB2aWV3LmssIChwWzFdIC0gdmlldy55KSAvIHZpZXcuayBdO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb2ludChsKSB7XG4gICAgICByZXR1cm4gWyBsWzBdICogdmlldy5rICsgdmlldy54LCBsWzFdICogdmlldy5rICsgdmlldy55IF07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNjYWxlVG8ocykge1xuICAgICAgdmlldy5rID0gTWF0aC5tYXgoc2NhbGVFeHRlbnRbMF0sIE1hdGgubWluKHNjYWxlRXh0ZW50WzFdLCBzKSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zbGF0ZVRvKHAsIGwpIHtcbiAgICAgIGwgPSBwb2ludChsKTtcbiAgICAgIHZpZXcueCArPSBwWzBdIC0gbFswXTtcbiAgICAgIHZpZXcueSArPSBwWzFdIC0gbFsxXTtcbiAgICB9XG4gICAgZnVuY3Rpb24gem9vbVRvKHRoYXQsIHAsIGwsIGspIHtcbiAgICAgIHRoYXQuX19jaGFydF9fID0ge1xuICAgICAgICB4OiB2aWV3LngsXG4gICAgICAgIHk6IHZpZXcueSxcbiAgICAgICAgazogdmlldy5rXG4gICAgICB9O1xuICAgICAgc2NhbGVUbyhNYXRoLnBvdygyLCBrKSk7XG4gICAgICB0cmFuc2xhdGVUbyhjZW50ZXIwID0gcCwgbCk7XG4gICAgICB0aGF0ID0gZDMuc2VsZWN0KHRoYXQpO1xuICAgICAgaWYgKGR1cmF0aW9uID4gMCkgdGhhdCA9IHRoYXQudHJhbnNpdGlvbigpLmR1cmF0aW9uKGR1cmF0aW9uKTtcbiAgICAgIHRoYXQuY2FsbCh6b29tLmV2ZW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVzY2FsZSgpIHtcbiAgICAgIGlmICh4MSkgeDEuZG9tYWluKHgwLnJhbmdlKCkubWFwKGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgcmV0dXJuICh4IC0gdmlldy54KSAvIHZpZXcuaztcbiAgICAgIH0pLm1hcCh4MC5pbnZlcnQpKTtcbiAgICAgIGlmICh5MSkgeTEuZG9tYWluKHkwLnJhbmdlKCkubWFwKGZ1bmN0aW9uKHkpIHtcbiAgICAgICAgcmV0dXJuICh5IC0gdmlldy55KSAvIHZpZXcuaztcbiAgICAgIH0pLm1hcCh5MC5pbnZlcnQpKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gem9vbXN0YXJ0ZWQoZGlzcGF0Y2gpIHtcbiAgICAgIGlmICghem9vbWluZysrKSBkaXNwYXRjaCh7XG4gICAgICAgIHR5cGU6IFwiem9vbXN0YXJ0XCJcbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiB6b29tZWQoZGlzcGF0Y2gpIHtcbiAgICAgIHJlc2NhbGUoKTtcbiAgICAgIGRpc3BhdGNoKHtcbiAgICAgICAgdHlwZTogXCJ6b29tXCIsXG4gICAgICAgIHNjYWxlOiB2aWV3LmssXG4gICAgICAgIHRyYW5zbGF0ZTogWyB2aWV3LngsIHZpZXcueSBdXG4gICAgICB9KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gem9vbWVuZGVkKGRpc3BhdGNoKSB7XG4gICAgICBpZiAoIS0tem9vbWluZykgZGlzcGF0Y2goe1xuICAgICAgICB0eXBlOiBcInpvb21lbmRcIlxuICAgICAgfSksIGNlbnRlcjAgPSBudWxsO1xuICAgIH1cbiAgICBmdW5jdGlvbiBtb3VzZWRvd25lZCgpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcywgZGlzcGF0Y2ggPSBldmVudC5vZih0aGF0LCBhcmd1bWVudHMpLCBkcmFnZ2VkID0gMCwgc3ViamVjdCA9IGQzLnNlbGVjdChkM193aW5kb3codGhhdCkpLm9uKG1vdXNlbW92ZSwgbW92ZWQpLm9uKG1vdXNldXAsIGVuZGVkKSwgbG9jYXRpb24wID0gbG9jYXRpb24oZDMubW91c2UodGhhdCkpLCBkcmFnUmVzdG9yZSA9IGQzX2V2ZW50X2RyYWdTdXBwcmVzcyh0aGF0KTtcbiAgICAgIGQzX3NlbGVjdGlvbl9pbnRlcnJ1cHQuY2FsbCh0aGF0KTtcbiAgICAgIHpvb21zdGFydGVkKGRpc3BhdGNoKTtcbiAgICAgIGZ1bmN0aW9uIG1vdmVkKCkge1xuICAgICAgICBkcmFnZ2VkID0gMTtcbiAgICAgICAgdHJhbnNsYXRlVG8oZDMubW91c2UodGhhdCksIGxvY2F0aW9uMCk7XG4gICAgICAgIHpvb21lZChkaXNwYXRjaCk7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBlbmRlZCgpIHtcbiAgICAgICAgc3ViamVjdC5vbihtb3VzZW1vdmUsIG51bGwpLm9uKG1vdXNldXAsIG51bGwpO1xuICAgICAgICBkcmFnUmVzdG9yZShkcmFnZ2VkKTtcbiAgICAgICAgem9vbWVuZGVkKGRpc3BhdGNoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gdG91Y2hzdGFydGVkKCkge1xuICAgICAgdmFyIHRoYXQgPSB0aGlzLCBkaXNwYXRjaCA9IGV2ZW50Lm9mKHRoYXQsIGFyZ3VtZW50cyksIGxvY2F0aW9uczAgPSB7fSwgZGlzdGFuY2UwID0gMCwgc2NhbGUwLCB6b29tTmFtZSA9IFwiLnpvb20tXCIgKyBkMy5ldmVudC5jaGFuZ2VkVG91Y2hlc1swXS5pZGVudGlmaWVyLCB0b3VjaG1vdmUgPSBcInRvdWNobW92ZVwiICsgem9vbU5hbWUsIHRvdWNoZW5kID0gXCJ0b3VjaGVuZFwiICsgem9vbU5hbWUsIHRhcmdldHMgPSBbXSwgc3ViamVjdCA9IGQzLnNlbGVjdCh0aGF0KSwgZHJhZ1Jlc3RvcmUgPSBkM19ldmVudF9kcmFnU3VwcHJlc3ModGhhdCk7XG4gICAgICBzdGFydGVkKCk7XG4gICAgICB6b29tc3RhcnRlZChkaXNwYXRjaCk7XG4gICAgICBzdWJqZWN0Lm9uKG1vdXNlZG93biwgbnVsbCkub24odG91Y2hzdGFydCwgc3RhcnRlZCk7XG4gICAgICBmdW5jdGlvbiByZWxvY2F0ZSgpIHtcbiAgICAgICAgdmFyIHRvdWNoZXMgPSBkMy50b3VjaGVzKHRoYXQpO1xuICAgICAgICBzY2FsZTAgPSB2aWV3Lms7XG4gICAgICAgIHRvdWNoZXMuZm9yRWFjaChmdW5jdGlvbih0KSB7XG4gICAgICAgICAgaWYgKHQuaWRlbnRpZmllciBpbiBsb2NhdGlvbnMwKSBsb2NhdGlvbnMwW3QuaWRlbnRpZmllcl0gPSBsb2NhdGlvbih0KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0b3VjaGVzO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gc3RhcnRlZCgpIHtcbiAgICAgICAgdmFyIHRhcmdldCA9IGQzLmV2ZW50LnRhcmdldDtcbiAgICAgICAgZDMuc2VsZWN0KHRhcmdldCkub24odG91Y2htb3ZlLCBtb3ZlZCkub24odG91Y2hlbmQsIGVuZGVkKTtcbiAgICAgICAgdGFyZ2V0cy5wdXNoKHRhcmdldCk7XG4gICAgICAgIHZhciBjaGFuZ2VkID0gZDMuZXZlbnQuY2hhbmdlZFRvdWNoZXM7XG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gY2hhbmdlZC5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICBsb2NhdGlvbnMwW2NoYW5nZWRbaV0uaWRlbnRpZmllcl0gPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0b3VjaGVzID0gcmVsb2NhdGUoKSwgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgaWYgKHRvdWNoZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgaWYgKG5vdyAtIHRvdWNodGltZSA8IDUwMCkge1xuICAgICAgICAgICAgdmFyIHAgPSB0b3VjaGVzWzBdO1xuICAgICAgICAgICAgem9vbVRvKHRoYXQsIHAsIGxvY2F0aW9uczBbcC5pZGVudGlmaWVyXSwgTWF0aC5mbG9vcihNYXRoLmxvZyh2aWV3LmspIC8gTWF0aC5MTjIpICsgMSk7XG4gICAgICAgICAgICBkM19ldmVudFByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRvdWNodGltZSA9IG5vdztcbiAgICAgICAgfSBlbHNlIGlmICh0b3VjaGVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICB2YXIgcCA9IHRvdWNoZXNbMF0sIHEgPSB0b3VjaGVzWzFdLCBkeCA9IHBbMF0gLSBxWzBdLCBkeSA9IHBbMV0gLSBxWzFdO1xuICAgICAgICAgIGRpc3RhbmNlMCA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBtb3ZlZCgpIHtcbiAgICAgICAgdmFyIHRvdWNoZXMgPSBkMy50b3VjaGVzKHRoYXQpLCBwMCwgbDAsIHAxLCBsMTtcbiAgICAgICAgZDNfc2VsZWN0aW9uX2ludGVycnVwdC5jYWxsKHRoYXQpO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbiA9IHRvdWNoZXMubGVuZ3RoOyBpIDwgbjsgKytpLCBsMSA9IG51bGwpIHtcbiAgICAgICAgICBwMSA9IHRvdWNoZXNbaV07XG4gICAgICAgICAgaWYgKGwxID0gbG9jYXRpb25zMFtwMS5pZGVudGlmaWVyXSkge1xuICAgICAgICAgICAgaWYgKGwwKSBicmVhaztcbiAgICAgICAgICAgIHAwID0gcDEsIGwwID0gbDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChsMSkge1xuICAgICAgICAgIHZhciBkaXN0YW5jZTEgPSAoZGlzdGFuY2UxID0gcDFbMF0gLSBwMFswXSkgKiBkaXN0YW5jZTEgKyAoZGlzdGFuY2UxID0gcDFbMV0gLSBwMFsxXSkgKiBkaXN0YW5jZTEsIHNjYWxlMSA9IGRpc3RhbmNlMCAmJiBNYXRoLnNxcnQoZGlzdGFuY2UxIC8gZGlzdGFuY2UwKTtcbiAgICAgICAgICBwMCA9IFsgKHAwWzBdICsgcDFbMF0pIC8gMiwgKHAwWzFdICsgcDFbMV0pIC8gMiBdO1xuICAgICAgICAgIGwwID0gWyAobDBbMF0gKyBsMVswXSkgLyAyLCAobDBbMV0gKyBsMVsxXSkgLyAyIF07XG4gICAgICAgICAgc2NhbGVUbyhzY2FsZTEgKiBzY2FsZTApO1xuICAgICAgICB9XG4gICAgICAgIHRvdWNodGltZSA9IG51bGw7XG4gICAgICAgIHRyYW5zbGF0ZVRvKHAwLCBsMCk7XG4gICAgICAgIHpvb21lZChkaXNwYXRjaCk7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBlbmRlZCgpIHtcbiAgICAgICAgaWYgKGQzLmV2ZW50LnRvdWNoZXMubGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIGNoYW5nZWQgPSBkMy5ldmVudC5jaGFuZ2VkVG91Y2hlcztcbiAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbiA9IGNoYW5nZWQubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICAgICAgICBkZWxldGUgbG9jYXRpb25zMFtjaGFuZ2VkW2ldLmlkZW50aWZpZXJdO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmb3IgKHZhciBpZGVudGlmaWVyIGluIGxvY2F0aW9uczApIHtcbiAgICAgICAgICAgIHJldHVybiB2b2lkIHJlbG9jYXRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGQzLnNlbGVjdEFsbCh0YXJnZXRzKS5vbih6b29tTmFtZSwgbnVsbCk7XG4gICAgICAgIHN1YmplY3Qub24obW91c2Vkb3duLCBtb3VzZWRvd25lZCkub24odG91Y2hzdGFydCwgdG91Y2hzdGFydGVkKTtcbiAgICAgICAgZHJhZ1Jlc3RvcmUoKTtcbiAgICAgICAgem9vbWVuZGVkKGRpc3BhdGNoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gbW91c2V3aGVlbGVkKCkge1xuICAgICAgdmFyIGRpc3BhdGNoID0gZXZlbnQub2YodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIGlmIChtb3VzZXdoZWVsVGltZXIpIGNsZWFyVGltZW91dChtb3VzZXdoZWVsVGltZXIpOyBlbHNlIGQzX3NlbGVjdGlvbl9pbnRlcnJ1cHQuY2FsbCh0aGlzKSwgXG4gICAgICB0cmFuc2xhdGUwID0gbG9jYXRpb24oY2VudGVyMCA9IGNlbnRlciB8fCBkMy5tb3VzZSh0aGlzKSksIHpvb21zdGFydGVkKGRpc3BhdGNoKTtcbiAgICAgIG1vdXNld2hlZWxUaW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgIG1vdXNld2hlZWxUaW1lciA9IG51bGw7XG4gICAgICAgIHpvb21lbmRlZChkaXNwYXRjaCk7XG4gICAgICB9LCA1MCk7XG4gICAgICBkM19ldmVudFByZXZlbnREZWZhdWx0KCk7XG4gICAgICBzY2FsZVRvKE1hdGgucG93KDIsIGQzX2JlaGF2aW9yX3pvb21EZWx0YSgpICogLjAwMikgKiB2aWV3LmspO1xuICAgICAgdHJhbnNsYXRlVG8oY2VudGVyMCwgdHJhbnNsYXRlMCk7XG4gICAgICB6b29tZWQoZGlzcGF0Y2gpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkYmxjbGlja2VkKCkge1xuICAgICAgdmFyIHAgPSBkMy5tb3VzZSh0aGlzKSwgayA9IE1hdGgubG9nKHZpZXcuaykgLyBNYXRoLkxOMjtcbiAgICAgIHpvb21Ubyh0aGlzLCBwLCBsb2NhdGlvbihwKSwgZDMuZXZlbnQuc2hpZnRLZXkgPyBNYXRoLmNlaWwoaykgLSAxIDogTWF0aC5mbG9vcihrKSArIDEpO1xuICAgIH1cbiAgICByZXR1cm4gZDMucmViaW5kKHpvb20sIGV2ZW50LCBcIm9uXCIpO1xuICB9O1xuICB2YXIgZDNfYmVoYXZpb3Jfem9vbUluZmluaXR5ID0gWyAwLCBJbmZpbml0eSBdLCBkM19iZWhhdmlvcl96b29tRGVsdGEsIGQzX2JlaGF2aW9yX3pvb21XaGVlbDtcbiAgZDMuY29sb3IgPSBkM19jb2xvcjtcbiAgZnVuY3Rpb24gZDNfY29sb3IoKSB7fVxuICBkM19jb2xvci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5yZ2IoKSArIFwiXCI7XG4gIH07XG4gIGQzLmhzbCA9IGQzX2hzbDtcbiAgZnVuY3Rpb24gZDNfaHNsKGgsIHMsIGwpIHtcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIGQzX2hzbCA/IHZvaWQgKHRoaXMuaCA9ICtoLCB0aGlzLnMgPSArcywgdGhpcy5sID0gK2wpIDogYXJndW1lbnRzLmxlbmd0aCA8IDIgPyBoIGluc3RhbmNlb2YgZDNfaHNsID8gbmV3IGQzX2hzbChoLmgsIGgucywgaC5sKSA6IGQzX3JnYl9wYXJzZShcIlwiICsgaCwgZDNfcmdiX2hzbCwgZDNfaHNsKSA6IG5ldyBkM19oc2woaCwgcywgbCk7XG4gIH1cbiAgdmFyIGQzX2hzbFByb3RvdHlwZSA9IGQzX2hzbC5wcm90b3R5cGUgPSBuZXcgZDNfY29sb3IoKTtcbiAgZDNfaHNsUHJvdG90eXBlLmJyaWdodGVyID0gZnVuY3Rpb24oaykge1xuICAgIGsgPSBNYXRoLnBvdyguNywgYXJndW1lbnRzLmxlbmd0aCA/IGsgOiAxKTtcbiAgICByZXR1cm4gbmV3IGQzX2hzbCh0aGlzLmgsIHRoaXMucywgdGhpcy5sIC8gayk7XG4gIH07XG4gIGQzX2hzbFByb3RvdHlwZS5kYXJrZXIgPSBmdW5jdGlvbihrKSB7XG4gICAgayA9IE1hdGgucG93KC43LCBhcmd1bWVudHMubGVuZ3RoID8gayA6IDEpO1xuICAgIHJldHVybiBuZXcgZDNfaHNsKHRoaXMuaCwgdGhpcy5zLCBrICogdGhpcy5sKTtcbiAgfTtcbiAgZDNfaHNsUHJvdG90eXBlLnJnYiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19oc2xfcmdiKHRoaXMuaCwgdGhpcy5zLCB0aGlzLmwpO1xuICB9O1xuICBmdW5jdGlvbiBkM19oc2xfcmdiKGgsIHMsIGwpIHtcbiAgICB2YXIgbTEsIG0yO1xuICAgIGggPSBpc05hTihoKSA/IDAgOiAoaCAlPSAzNjApIDwgMCA/IGggKyAzNjAgOiBoO1xuICAgIHMgPSBpc05hTihzKSA/IDAgOiBzIDwgMCA/IDAgOiBzID4gMSA/IDEgOiBzO1xuICAgIGwgPSBsIDwgMCA/IDAgOiBsID4gMSA/IDEgOiBsO1xuICAgIG0yID0gbCA8PSAuNSA/IGwgKiAoMSArIHMpIDogbCArIHMgLSBsICogcztcbiAgICBtMSA9IDIgKiBsIC0gbTI7XG4gICAgZnVuY3Rpb24gdihoKSB7XG4gICAgICBpZiAoaCA+IDM2MCkgaCAtPSAzNjA7IGVsc2UgaWYgKGggPCAwKSBoICs9IDM2MDtcbiAgICAgIGlmIChoIDwgNjApIHJldHVybiBtMSArIChtMiAtIG0xKSAqIGggLyA2MDtcbiAgICAgIGlmIChoIDwgMTgwKSByZXR1cm4gbTI7XG4gICAgICBpZiAoaCA8IDI0MCkgcmV0dXJuIG0xICsgKG0yIC0gbTEpICogKDI0MCAtIGgpIC8gNjA7XG4gICAgICByZXR1cm4gbTE7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHZ2KGgpIHtcbiAgICAgIHJldHVybiBNYXRoLnJvdW5kKHYoaCkgKiAyNTUpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IGQzX3JnYih2dihoICsgMTIwKSwgdnYoaCksIHZ2KGggLSAxMjApKTtcbiAgfVxuICBkMy5oY2wgPSBkM19oY2w7XG4gIGZ1bmN0aW9uIGQzX2hjbChoLCBjLCBsKSB7XG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBkM19oY2wgPyB2b2lkICh0aGlzLmggPSAraCwgdGhpcy5jID0gK2MsIHRoaXMubCA9ICtsKSA6IGFyZ3VtZW50cy5sZW5ndGggPCAyID8gaCBpbnN0YW5jZW9mIGQzX2hjbCA/IG5ldyBkM19oY2woaC5oLCBoLmMsIGgubCkgOiBoIGluc3RhbmNlb2YgZDNfbGFiID8gZDNfbGFiX2hjbChoLmwsIGguYSwgaC5iKSA6IGQzX2xhYl9oY2woKGggPSBkM19yZ2JfbGFiKChoID0gZDMucmdiKGgpKS5yLCBoLmcsIGguYikpLmwsIGguYSwgaC5iKSA6IG5ldyBkM19oY2woaCwgYywgbCk7XG4gIH1cbiAgdmFyIGQzX2hjbFByb3RvdHlwZSA9IGQzX2hjbC5wcm90b3R5cGUgPSBuZXcgZDNfY29sb3IoKTtcbiAgZDNfaGNsUHJvdG90eXBlLmJyaWdodGVyID0gZnVuY3Rpb24oaykge1xuICAgIHJldHVybiBuZXcgZDNfaGNsKHRoaXMuaCwgdGhpcy5jLCBNYXRoLm1pbigxMDAsIHRoaXMubCArIGQzX2xhYl9LICogKGFyZ3VtZW50cy5sZW5ndGggPyBrIDogMSkpKTtcbiAgfTtcbiAgZDNfaGNsUHJvdG90eXBlLmRhcmtlciA9IGZ1bmN0aW9uKGspIHtcbiAgICByZXR1cm4gbmV3IGQzX2hjbCh0aGlzLmgsIHRoaXMuYywgTWF0aC5tYXgoMCwgdGhpcy5sIC0gZDNfbGFiX0sgKiAoYXJndW1lbnRzLmxlbmd0aCA/IGsgOiAxKSkpO1xuICB9O1xuICBkM19oY2xQcm90b3R5cGUucmdiID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX2hjbF9sYWIodGhpcy5oLCB0aGlzLmMsIHRoaXMubCkucmdiKCk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2hjbF9sYWIoaCwgYywgbCkge1xuICAgIGlmIChpc05hTihoKSkgaCA9IDA7XG4gICAgaWYgKGlzTmFOKGMpKSBjID0gMDtcbiAgICByZXR1cm4gbmV3IGQzX2xhYihsLCBNYXRoLmNvcyhoICo9IGQzX3JhZGlhbnMpICogYywgTWF0aC5zaW4oaCkgKiBjKTtcbiAgfVxuICBkMy5sYWIgPSBkM19sYWI7XG4gIGZ1bmN0aW9uIGQzX2xhYihsLCBhLCBiKSB7XG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBkM19sYWIgPyB2b2lkICh0aGlzLmwgPSArbCwgdGhpcy5hID0gK2EsIHRoaXMuYiA9ICtiKSA6IGFyZ3VtZW50cy5sZW5ndGggPCAyID8gbCBpbnN0YW5jZW9mIGQzX2xhYiA/IG5ldyBkM19sYWIobC5sLCBsLmEsIGwuYikgOiBsIGluc3RhbmNlb2YgZDNfaGNsID8gZDNfaGNsX2xhYihsLmgsIGwuYywgbC5sKSA6IGQzX3JnYl9sYWIoKGwgPSBkM19yZ2IobCkpLnIsIGwuZywgbC5iKSA6IG5ldyBkM19sYWIobCwgYSwgYik7XG4gIH1cbiAgdmFyIGQzX2xhYl9LID0gMTg7XG4gIHZhciBkM19sYWJfWCA9IC45NTA0NywgZDNfbGFiX1kgPSAxLCBkM19sYWJfWiA9IDEuMDg4ODM7XG4gIHZhciBkM19sYWJQcm90b3R5cGUgPSBkM19sYWIucHJvdG90eXBlID0gbmV3IGQzX2NvbG9yKCk7XG4gIGQzX2xhYlByb3RvdHlwZS5icmlnaHRlciA9IGZ1bmN0aW9uKGspIHtcbiAgICByZXR1cm4gbmV3IGQzX2xhYihNYXRoLm1pbigxMDAsIHRoaXMubCArIGQzX2xhYl9LICogKGFyZ3VtZW50cy5sZW5ndGggPyBrIDogMSkpLCB0aGlzLmEsIHRoaXMuYik7XG4gIH07XG4gIGQzX2xhYlByb3RvdHlwZS5kYXJrZXIgPSBmdW5jdGlvbihrKSB7XG4gICAgcmV0dXJuIG5ldyBkM19sYWIoTWF0aC5tYXgoMCwgdGhpcy5sIC0gZDNfbGFiX0sgKiAoYXJndW1lbnRzLmxlbmd0aCA/IGsgOiAxKSksIHRoaXMuYSwgdGhpcy5iKTtcbiAgfTtcbiAgZDNfbGFiUHJvdG90eXBlLnJnYiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19sYWJfcmdiKHRoaXMubCwgdGhpcy5hLCB0aGlzLmIpO1xuICB9O1xuICBmdW5jdGlvbiBkM19sYWJfcmdiKGwsIGEsIGIpIHtcbiAgICB2YXIgeSA9IChsICsgMTYpIC8gMTE2LCB4ID0geSArIGEgLyA1MDAsIHogPSB5IC0gYiAvIDIwMDtcbiAgICB4ID0gZDNfbGFiX3h5eih4KSAqIGQzX2xhYl9YO1xuICAgIHkgPSBkM19sYWJfeHl6KHkpICogZDNfbGFiX1k7XG4gICAgeiA9IGQzX2xhYl94eXooeikgKiBkM19sYWJfWjtcbiAgICByZXR1cm4gbmV3IGQzX3JnYihkM194eXpfcmdiKDMuMjQwNDU0MiAqIHggLSAxLjUzNzEzODUgKiB5IC0gLjQ5ODUzMTQgKiB6KSwgZDNfeHl6X3JnYigtLjk2OTI2NiAqIHggKyAxLjg3NjAxMDggKiB5ICsgLjA0MTU1NiAqIHopLCBkM194eXpfcmdiKC4wNTU2NDM0ICogeCAtIC4yMDQwMjU5ICogeSArIDEuMDU3MjI1MiAqIHopKTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYWJfaGNsKGwsIGEsIGIpIHtcbiAgICByZXR1cm4gbCA+IDAgPyBuZXcgZDNfaGNsKE1hdGguYXRhbjIoYiwgYSkgKiBkM19kZWdyZWVzLCBNYXRoLnNxcnQoYSAqIGEgKyBiICogYiksIGwpIDogbmV3IGQzX2hjbChOYU4sIE5hTiwgbCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGFiX3h5eih4KSB7XG4gICAgcmV0dXJuIHggPiAuMjA2ODkzMDM0ID8geCAqIHggKiB4IDogKHggLSA0IC8gMjkpIC8gNy43ODcwMzc7XG4gIH1cbiAgZnVuY3Rpb24gZDNfeHl6X2xhYih4KSB7XG4gICAgcmV0dXJuIHggPiAuMDA4ODU2ID8gTWF0aC5wb3coeCwgMSAvIDMpIDogNy43ODcwMzcgKiB4ICsgNCAvIDI5O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3h5el9yZ2Iocikge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKDI1NSAqIChyIDw9IC4wMDMwNCA/IDEyLjkyICogciA6IDEuMDU1ICogTWF0aC5wb3cociwgMSAvIDIuNCkgLSAuMDU1KSk7XG4gIH1cbiAgZDMucmdiID0gZDNfcmdiO1xuICBmdW5jdGlvbiBkM19yZ2IociwgZywgYikge1xuICAgIHJldHVybiB0aGlzIGluc3RhbmNlb2YgZDNfcmdiID8gdm9pZCAodGhpcy5yID0gfn5yLCB0aGlzLmcgPSB+fmcsIHRoaXMuYiA9IH5+YikgOiBhcmd1bWVudHMubGVuZ3RoIDwgMiA/IHIgaW5zdGFuY2VvZiBkM19yZ2IgPyBuZXcgZDNfcmdiKHIuciwgci5nLCByLmIpIDogZDNfcmdiX3BhcnNlKFwiXCIgKyByLCBkM19yZ2IsIGQzX2hzbF9yZ2IpIDogbmV3IGQzX3JnYihyLCBnLCBiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19yZ2JOdW1iZXIodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IGQzX3JnYih2YWx1ZSA+PiAxNiwgdmFsdWUgPj4gOCAmIDI1NSwgdmFsdWUgJiAyNTUpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3JnYlN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBkM19yZ2JOdW1iZXIodmFsdWUpICsgXCJcIjtcbiAgfVxuICB2YXIgZDNfcmdiUHJvdG90eXBlID0gZDNfcmdiLnByb3RvdHlwZSA9IG5ldyBkM19jb2xvcigpO1xuICBkM19yZ2JQcm90b3R5cGUuYnJpZ2h0ZXIgPSBmdW5jdGlvbihrKSB7XG4gICAgayA9IE1hdGgucG93KC43LCBhcmd1bWVudHMubGVuZ3RoID8gayA6IDEpO1xuICAgIHZhciByID0gdGhpcy5yLCBnID0gdGhpcy5nLCBiID0gdGhpcy5iLCBpID0gMzA7XG4gICAgaWYgKCFyICYmICFnICYmICFiKSByZXR1cm4gbmV3IGQzX3JnYihpLCBpLCBpKTtcbiAgICBpZiAociAmJiByIDwgaSkgciA9IGk7XG4gICAgaWYgKGcgJiYgZyA8IGkpIGcgPSBpO1xuICAgIGlmIChiICYmIGIgPCBpKSBiID0gaTtcbiAgICByZXR1cm4gbmV3IGQzX3JnYihNYXRoLm1pbigyNTUsIHIgLyBrKSwgTWF0aC5taW4oMjU1LCBnIC8gayksIE1hdGgubWluKDI1NSwgYiAvIGspKTtcbiAgfTtcbiAgZDNfcmdiUHJvdG90eXBlLmRhcmtlciA9IGZ1bmN0aW9uKGspIHtcbiAgICBrID0gTWF0aC5wb3coLjcsIGFyZ3VtZW50cy5sZW5ndGggPyBrIDogMSk7XG4gICAgcmV0dXJuIG5ldyBkM19yZ2IoayAqIHRoaXMuciwgayAqIHRoaXMuZywgayAqIHRoaXMuYik7XG4gIH07XG4gIGQzX3JnYlByb3RvdHlwZS5oc2wgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfcmdiX2hzbCh0aGlzLnIsIHRoaXMuZywgdGhpcy5iKTtcbiAgfTtcbiAgZDNfcmdiUHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIFwiI1wiICsgZDNfcmdiX2hleCh0aGlzLnIpICsgZDNfcmdiX2hleCh0aGlzLmcpICsgZDNfcmdiX2hleCh0aGlzLmIpO1xuICB9O1xuICBmdW5jdGlvbiBkM19yZ2JfaGV4KHYpIHtcbiAgICByZXR1cm4gdiA8IDE2ID8gXCIwXCIgKyBNYXRoLm1heCgwLCB2KS50b1N0cmluZygxNikgOiBNYXRoLm1pbigyNTUsIHYpLnRvU3RyaW5nKDE2KTtcbiAgfVxuICBmdW5jdGlvbiBkM19yZ2JfcGFyc2UoZm9ybWF0LCByZ2IsIGhzbCkge1xuICAgIHZhciByID0gMCwgZyA9IDAsIGIgPSAwLCBtMSwgbTIsIGNvbG9yO1xuICAgIG0xID0gLyhbYS16XSspXFwoKC4qKVxcKS8uZXhlYyhmb3JtYXQgPSBmb3JtYXQudG9Mb3dlckNhc2UoKSk7XG4gICAgaWYgKG0xKSB7XG4gICAgICBtMiA9IG0xWzJdLnNwbGl0KFwiLFwiKTtcbiAgICAgIHN3aXRjaCAobTFbMV0pIHtcbiAgICAgICBjYXNlIFwiaHNsXCI6XG4gICAgICAgIHtcbiAgICAgICAgICByZXR1cm4gaHNsKHBhcnNlRmxvYXQobTJbMF0pLCBwYXJzZUZsb2F0KG0yWzFdKSAvIDEwMCwgcGFyc2VGbG9hdChtMlsyXSkgLyAxMDApO1xuICAgICAgICB9XG5cbiAgICAgICBjYXNlIFwicmdiXCI6XG4gICAgICAgIHtcbiAgICAgICAgICByZXR1cm4gcmdiKGQzX3JnYl9wYXJzZU51bWJlcihtMlswXSksIGQzX3JnYl9wYXJzZU51bWJlcihtMlsxXSksIGQzX3JnYl9wYXJzZU51bWJlcihtMlsyXSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChjb2xvciA9IGQzX3JnYl9uYW1lcy5nZXQoZm9ybWF0KSkge1xuICAgICAgcmV0dXJuIHJnYihjb2xvci5yLCBjb2xvci5nLCBjb2xvci5iKTtcbiAgICB9XG4gICAgaWYgKGZvcm1hdCAhPSBudWxsICYmIGZvcm1hdC5jaGFyQXQoMCkgPT09IFwiI1wiICYmICFpc05hTihjb2xvciA9IHBhcnNlSW50KGZvcm1hdC5zbGljZSgxKSwgMTYpKSkge1xuICAgICAgaWYgKGZvcm1hdC5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgciA9IChjb2xvciAmIDM4NDApID4+IDQ7XG4gICAgICAgIHIgPSByID4+IDQgfCByO1xuICAgICAgICBnID0gY29sb3IgJiAyNDA7XG4gICAgICAgIGcgPSBnID4+IDQgfCBnO1xuICAgICAgICBiID0gY29sb3IgJiAxNTtcbiAgICAgICAgYiA9IGIgPDwgNCB8IGI7XG4gICAgICB9IGVsc2UgaWYgKGZvcm1hdC5sZW5ndGggPT09IDcpIHtcbiAgICAgICAgciA9IChjb2xvciAmIDE2NzExNjgwKSA+PiAxNjtcbiAgICAgICAgZyA9IChjb2xvciAmIDY1MjgwKSA+PiA4O1xuICAgICAgICBiID0gY29sb3IgJiAyNTU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZ2IociwgZywgYik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfcmdiX2hzbChyLCBnLCBiKSB7XG4gICAgdmFyIG1pbiA9IE1hdGgubWluKHIgLz0gMjU1LCBnIC89IDI1NSwgYiAvPSAyNTUpLCBtYXggPSBNYXRoLm1heChyLCBnLCBiKSwgZCA9IG1heCAtIG1pbiwgaCwgcywgbCA9IChtYXggKyBtaW4pIC8gMjtcbiAgICBpZiAoZCkge1xuICAgICAgcyA9IGwgPCAuNSA/IGQgLyAobWF4ICsgbWluKSA6IGQgLyAoMiAtIG1heCAtIG1pbik7XG4gICAgICBpZiAociA9PSBtYXgpIGggPSAoZyAtIGIpIC8gZCArIChnIDwgYiA/IDYgOiAwKTsgZWxzZSBpZiAoZyA9PSBtYXgpIGggPSAoYiAtIHIpIC8gZCArIDI7IGVsc2UgaCA9IChyIC0gZykgLyBkICsgNDtcbiAgICAgIGggKj0gNjA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGggPSBOYU47XG4gICAgICBzID0gbCA+IDAgJiYgbCA8IDEgPyAwIDogaDtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBkM19oc2woaCwgcywgbCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfcmdiX2xhYihyLCBnLCBiKSB7XG4gICAgciA9IGQzX3JnYl94eXoocik7XG4gICAgZyA9IGQzX3JnYl94eXooZyk7XG4gICAgYiA9IGQzX3JnYl94eXooYik7XG4gICAgdmFyIHggPSBkM194eXpfbGFiKCguNDEyNDU2NCAqIHIgKyAuMzU3NTc2MSAqIGcgKyAuMTgwNDM3NSAqIGIpIC8gZDNfbGFiX1gpLCB5ID0gZDNfeHl6X2xhYigoLjIxMjY3MjkgKiByICsgLjcxNTE1MjIgKiBnICsgLjA3MjE3NSAqIGIpIC8gZDNfbGFiX1kpLCB6ID0gZDNfeHl6X2xhYigoLjAxOTMzMzkgKiByICsgLjExOTE5MiAqIGcgKyAuOTUwMzA0MSAqIGIpIC8gZDNfbGFiX1opO1xuICAgIHJldHVybiBkM19sYWIoMTE2ICogeSAtIDE2LCA1MDAgKiAoeCAtIHkpLCAyMDAgKiAoeSAtIHopKTtcbiAgfVxuICBmdW5jdGlvbiBkM19yZ2JfeHl6KHIpIHtcbiAgICByZXR1cm4gKHIgLz0gMjU1KSA8PSAuMDQwNDUgPyByIC8gMTIuOTIgOiBNYXRoLnBvdygociArIC4wNTUpIC8gMS4wNTUsIDIuNCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfcmdiX3BhcnNlTnVtYmVyKGMpIHtcbiAgICB2YXIgZiA9IHBhcnNlRmxvYXQoYyk7XG4gICAgcmV0dXJuIGMuY2hhckF0KGMubGVuZ3RoIC0gMSkgPT09IFwiJVwiID8gTWF0aC5yb3VuZChmICogMi41NSkgOiBmO1xuICB9XG4gIHZhciBkM19yZ2JfbmFtZXMgPSBkMy5tYXAoe1xuICAgIGFsaWNlYmx1ZTogMTU3OTIzODMsXG4gICAgYW50aXF1ZXdoaXRlOiAxNjQ0NDM3NSxcbiAgICBhcXVhOiA2NTUzNSxcbiAgICBhcXVhbWFyaW5lOiA4Mzg4NTY0LFxuICAgIGF6dXJlOiAxNTc5NDE3NSxcbiAgICBiZWlnZTogMTYxMTkyNjAsXG4gICAgYmlzcXVlOiAxNjc3MDI0NCxcbiAgICBibGFjazogMCxcbiAgICBibGFuY2hlZGFsbW9uZDogMTY3NzIwNDUsXG4gICAgYmx1ZTogMjU1LFxuICAgIGJsdWV2aW9sZXQ6IDkwNTUyMDIsXG4gICAgYnJvd246IDEwODI0MjM0LFxuICAgIGJ1cmx5d29vZDogMTQ1OTYyMzEsXG4gICAgY2FkZXRibHVlOiA2MjY2NTI4LFxuICAgIGNoYXJ0cmV1c2U6IDgzODgzNTIsXG4gICAgY2hvY29sYXRlOiAxMzc4OTQ3MCxcbiAgICBjb3JhbDogMTY3NDQyNzIsXG4gICAgY29ybmZsb3dlcmJsdWU6IDY1OTE5ODEsXG4gICAgY29ybnNpbGs6IDE2Nzc1Mzg4LFxuICAgIGNyaW1zb246IDE0NDIzMTAwLFxuICAgIGN5YW46IDY1NTM1LFxuICAgIGRhcmtibHVlOiAxMzksXG4gICAgZGFya2N5YW46IDM1NzIzLFxuICAgIGRhcmtnb2xkZW5yb2Q6IDEyMDkyOTM5LFxuICAgIGRhcmtncmF5OiAxMTExOTAxNyxcbiAgICBkYXJrZ3JlZW46IDI1NjAwLFxuICAgIGRhcmtncmV5OiAxMTExOTAxNyxcbiAgICBkYXJra2hha2k6IDEyNDMzMjU5LFxuICAgIGRhcmttYWdlbnRhOiA5MTA5NjQzLFxuICAgIGRhcmtvbGl2ZWdyZWVuOiA1NTk3OTk5LFxuICAgIGRhcmtvcmFuZ2U6IDE2NzQ3NTIwLFxuICAgIGRhcmtvcmNoaWQ6IDEwMDQwMDEyLFxuICAgIGRhcmtyZWQ6IDkxMDk1MDQsXG4gICAgZGFya3NhbG1vbjogMTUzMDg0MTAsXG4gICAgZGFya3NlYWdyZWVuOiA5NDE5OTE5LFxuICAgIGRhcmtzbGF0ZWJsdWU6IDQ3MzQzNDcsXG4gICAgZGFya3NsYXRlZ3JheTogMzEwMDQ5NSxcbiAgICBkYXJrc2xhdGVncmV5OiAzMTAwNDk1LFxuICAgIGRhcmt0dXJxdW9pc2U6IDUyOTQ1LFxuICAgIGRhcmt2aW9sZXQ6IDk2OTk1MzksXG4gICAgZGVlcHBpbms6IDE2NzE2OTQ3LFxuICAgIGRlZXBza3libHVlOiA0OTE1MSxcbiAgICBkaW1ncmF5OiA2OTA4MjY1LFxuICAgIGRpbWdyZXk6IDY5MDgyNjUsXG4gICAgZG9kZ2VyYmx1ZTogMjAwMzE5OSxcbiAgICBmaXJlYnJpY2s6IDExNjc0MTQ2LFxuICAgIGZsb3JhbHdoaXRlOiAxNjc3NTkyMCxcbiAgICBmb3Jlc3RncmVlbjogMjI2Mzg0MixcbiAgICBmdWNoc2lhOiAxNjcxMTkzNSxcbiAgICBnYWluc2Jvcm86IDE0NDc0NDYwLFxuICAgIGdob3N0d2hpdGU6IDE2MzE2NjcxLFxuICAgIGdvbGQ6IDE2NzY2NzIwLFxuICAgIGdvbGRlbnJvZDogMTQzMjkxMjAsXG4gICAgZ3JheTogODQyMTUwNCxcbiAgICBncmVlbjogMzI3NjgsXG4gICAgZ3JlZW55ZWxsb3c6IDExNDAzMDU1LFxuICAgIGdyZXk6IDg0MjE1MDQsXG4gICAgaG9uZXlkZXc6IDE1Nzk0MTYwLFxuICAgIGhvdHBpbms6IDE2NzM4NzQwLFxuICAgIGluZGlhbnJlZDogMTM0NTg1MjQsXG4gICAgaW5kaWdvOiA0OTE1MzMwLFxuICAgIGl2b3J5OiAxNjc3NzIwMCxcbiAgICBraGFraTogMTU3ODc2NjAsXG4gICAgbGF2ZW5kZXI6IDE1MTMyNDEwLFxuICAgIGxhdmVuZGVyYmx1c2g6IDE2NzczMzY1LFxuICAgIGxhd25ncmVlbjogODE5MDk3NixcbiAgICBsZW1vbmNoaWZmb246IDE2Nzc1ODg1LFxuICAgIGxpZ2h0Ymx1ZTogMTEzOTMyNTQsXG4gICAgbGlnaHRjb3JhbDogMTU3NjE1MzYsXG4gICAgbGlnaHRjeWFuOiAxNDc0NTU5OSxcbiAgICBsaWdodGdvbGRlbnJvZHllbGxvdzogMTY0NDgyMTAsXG4gICAgbGlnaHRncmF5OiAxMzg4MjMyMyxcbiAgICBsaWdodGdyZWVuOiA5NDk4MjU2LFxuICAgIGxpZ2h0Z3JleTogMTM4ODIzMjMsXG4gICAgbGlnaHRwaW5rOiAxNjc1ODQ2NSxcbiAgICBsaWdodHNhbG1vbjogMTY3NTI3NjIsXG4gICAgbGlnaHRzZWFncmVlbjogMjE0Mjg5MCxcbiAgICBsaWdodHNreWJsdWU6IDg5MDAzNDYsXG4gICAgbGlnaHRzbGF0ZWdyYXk6IDc4MzM3NTMsXG4gICAgbGlnaHRzbGF0ZWdyZXk6IDc4MzM3NTMsXG4gICAgbGlnaHRzdGVlbGJsdWU6IDExNTg0NzM0LFxuICAgIGxpZ2h0eWVsbG93OiAxNjc3NzE4NCxcbiAgICBsaW1lOiA2NTI4MCxcbiAgICBsaW1lZ3JlZW46IDMzMjkzMzAsXG4gICAgbGluZW46IDE2NDQ1NjcwLFxuICAgIG1hZ2VudGE6IDE2NzExOTM1LFxuICAgIG1hcm9vbjogODM4ODYwOCxcbiAgICBtZWRpdW1hcXVhbWFyaW5lOiA2NzM3MzIyLFxuICAgIG1lZGl1bWJsdWU6IDIwNSxcbiAgICBtZWRpdW1vcmNoaWQ6IDEyMjExNjY3LFxuICAgIG1lZGl1bXB1cnBsZTogOTY2MjY4MyxcbiAgICBtZWRpdW1zZWFncmVlbjogMzk3ODA5NyxcbiAgICBtZWRpdW1zbGF0ZWJsdWU6IDgwODc3OTAsXG4gICAgbWVkaXVtc3ByaW5nZ3JlZW46IDY0MTU0LFxuICAgIG1lZGl1bXR1cnF1b2lzZTogNDc3MjMwMCxcbiAgICBtZWRpdW12aW9sZXRyZWQ6IDEzMDQ3MTczLFxuICAgIG1pZG5pZ2h0Ymx1ZTogMTY0NDkxMixcbiAgICBtaW50Y3JlYW06IDE2MTIxODUwLFxuICAgIG1pc3R5cm9zZTogMTY3NzAyNzMsXG4gICAgbW9jY2FzaW46IDE2NzcwMjI5LFxuICAgIG5hdmFqb3doaXRlOiAxNjc2ODY4NSxcbiAgICBuYXZ5OiAxMjgsXG4gICAgb2xkbGFjZTogMTY2NDM1NTgsXG4gICAgb2xpdmU6IDg0MjEzNzYsXG4gICAgb2xpdmVkcmFiOiA3MDQ4NzM5LFxuICAgIG9yYW5nZTogMTY3NTM5MjAsXG4gICAgb3JhbmdlcmVkOiAxNjcyOTM0NCxcbiAgICBvcmNoaWQ6IDE0MzE1NzM0LFxuICAgIHBhbGVnb2xkZW5yb2Q6IDE1NjU3MTMwLFxuICAgIHBhbGVncmVlbjogMTAwMjU4ODAsXG4gICAgcGFsZXR1cnF1b2lzZTogMTE1Mjk5NjYsXG4gICAgcGFsZXZpb2xldHJlZDogMTQzODEyMDMsXG4gICAgcGFwYXlhd2hpcDogMTY3NzMwNzcsXG4gICAgcGVhY2hwdWZmOiAxNjc2NzY3MyxcbiAgICBwZXJ1OiAxMzQ2ODk5MSxcbiAgICBwaW5rOiAxNjc2MTAzNSxcbiAgICBwbHVtOiAxNDUyNDYzNyxcbiAgICBwb3dkZXJibHVlOiAxMTU5MTkxMCxcbiAgICBwdXJwbGU6IDgzODg3MzYsXG4gICAgcmViZWNjYXB1cnBsZTogNjY5Nzg4MSxcbiAgICByZWQ6IDE2NzExNjgwLFxuICAgIHJvc3licm93bjogMTIzNTc1MTksXG4gICAgcm95YWxibHVlOiA0Mjg2OTQ1LFxuICAgIHNhZGRsZWJyb3duOiA5MTI3MTg3LFxuICAgIHNhbG1vbjogMTY0MTY4ODIsXG4gICAgc2FuZHlicm93bjogMTYwMzI4NjQsXG4gICAgc2VhZ3JlZW46IDMwNTAzMjcsXG4gICAgc2Vhc2hlbGw6IDE2Nzc0NjM4LFxuICAgIHNpZW5uYTogMTA1MDY3OTcsXG4gICAgc2lsdmVyOiAxMjYzMjI1NixcbiAgICBza3libHVlOiA4OTAwMzMxLFxuICAgIHNsYXRlYmx1ZTogNjk3MDA2MSxcbiAgICBzbGF0ZWdyYXk6IDczNzI5NDQsXG4gICAgc2xhdGVncmV5OiA3MzcyOTQ0LFxuICAgIHNub3c6IDE2Nzc1OTMwLFxuICAgIHNwcmluZ2dyZWVuOiA2NTQwNyxcbiAgICBzdGVlbGJsdWU6IDQ2MjA5ODAsXG4gICAgdGFuOiAxMzgwODc4MCxcbiAgICB0ZWFsOiAzMjg5NixcbiAgICB0aGlzdGxlOiAxNDIwNDg4OCxcbiAgICB0b21hdG86IDE2NzM3MDk1LFxuICAgIHR1cnF1b2lzZTogNDI1MTg1NixcbiAgICB2aW9sZXQ6IDE1NjMxMDg2LFxuICAgIHdoZWF0OiAxNjExMzMzMSxcbiAgICB3aGl0ZTogMTY3NzcyMTUsXG4gICAgd2hpdGVzbW9rZTogMTYxMTkyODUsXG4gICAgeWVsbG93OiAxNjc3Njk2MCxcbiAgICB5ZWxsb3dncmVlbjogMTAxNDUwNzRcbiAgfSk7XG4gIGQzX3JnYl9uYW1lcy5mb3JFYWNoKGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICBkM19yZ2JfbmFtZXMuc2V0KGtleSwgZDNfcmdiTnVtYmVyKHZhbHVlKSk7XG4gIH0pO1xuICBmdW5jdGlvbiBkM19mdW5jdG9yKHYpIHtcbiAgICByZXR1cm4gdHlwZW9mIHYgPT09IFwiZnVuY3Rpb25cIiA/IHYgOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB2O1xuICAgIH07XG4gIH1cbiAgZDMuZnVuY3RvciA9IGQzX2Z1bmN0b3I7XG4gIGQzLnhociA9IGQzX3hoclR5cGUoZDNfaWRlbnRpdHkpO1xuICBmdW5jdGlvbiBkM194aHJUeXBlKHJlc3BvbnNlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHVybCwgbWltZVR5cGUsIGNhbGxiYWNrKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMiAmJiB0eXBlb2YgbWltZVR5cGUgPT09IFwiZnVuY3Rpb25cIikgY2FsbGJhY2sgPSBtaW1lVHlwZSwgXG4gICAgICBtaW1lVHlwZSA9IG51bGw7XG4gICAgICByZXR1cm4gZDNfeGhyKHVybCwgbWltZVR5cGUsIHJlc3BvbnNlLCBjYWxsYmFjayk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM194aHIodXJsLCBtaW1lVHlwZSwgcmVzcG9uc2UsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHhociA9IHt9LCBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoKFwiYmVmb3Jlc2VuZFwiLCBcInByb2dyZXNzXCIsIFwibG9hZFwiLCBcImVycm9yXCIpLCBoZWFkZXJzID0ge30sIHJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKSwgcmVzcG9uc2VUeXBlID0gbnVsbDtcbiAgICBpZiAodGhpcy5YRG9tYWluUmVxdWVzdCAmJiAhKFwid2l0aENyZWRlbnRpYWxzXCIgaW4gcmVxdWVzdCkgJiYgL14oaHR0cChzKT86KT9cXC9cXC8vLnRlc3QodXJsKSkgcmVxdWVzdCA9IG5ldyBYRG9tYWluUmVxdWVzdCgpO1xuICAgIFwib25sb2FkXCIgaW4gcmVxdWVzdCA/IHJlcXVlc3Qub25sb2FkID0gcmVxdWVzdC5vbmVycm9yID0gcmVzcG9uZCA6IHJlcXVlc3Qub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXF1ZXN0LnJlYWR5U3RhdGUgPiAzICYmIHJlc3BvbmQoKTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHJlc3BvbmQoKSB7XG4gICAgICB2YXIgc3RhdHVzID0gcmVxdWVzdC5zdGF0dXMsIHJlc3VsdDtcbiAgICAgIGlmICghc3RhdHVzICYmIGQzX3hockhhc1Jlc3BvbnNlKHJlcXVlc3QpIHx8IHN0YXR1cyA+PSAyMDAgJiYgc3RhdHVzIDwgMzAwIHx8IHN0YXR1cyA9PT0gMzA0KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmVzdWx0ID0gcmVzcG9uc2UuY2FsbCh4aHIsIHJlcXVlc3QpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgZGlzcGF0Y2guZXJyb3IuY2FsbCh4aHIsIGUpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkaXNwYXRjaC5sb2FkLmNhbGwoeGhyLCByZXN1bHQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGlzcGF0Y2guZXJyb3IuY2FsbCh4aHIsIHJlcXVlc3QpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXF1ZXN0Lm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbihldmVudCkge1xuICAgICAgdmFyIG8gPSBkMy5ldmVudDtcbiAgICAgIGQzLmV2ZW50ID0gZXZlbnQ7XG4gICAgICB0cnkge1xuICAgICAgICBkaXNwYXRjaC5wcm9ncmVzcy5jYWxsKHhociwgcmVxdWVzdCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBkMy5ldmVudCA9IG87XG4gICAgICB9XG4gICAgfTtcbiAgICB4aHIuaGVhZGVyID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHtcbiAgICAgIG5hbWUgPSAobmFtZSArIFwiXCIpLnRvTG93ZXJDYXNlKCk7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHJldHVybiBoZWFkZXJzW25hbWVdO1xuICAgICAgaWYgKHZhbHVlID09IG51bGwpIGRlbGV0ZSBoZWFkZXJzW25hbWVdOyBlbHNlIGhlYWRlcnNbbmFtZV0gPSB2YWx1ZSArIFwiXCI7XG4gICAgICByZXR1cm4geGhyO1xuICAgIH07XG4gICAgeGhyLm1pbWVUeXBlID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG1pbWVUeXBlO1xuICAgICAgbWltZVR5cGUgPSB2YWx1ZSA9PSBudWxsID8gbnVsbCA6IHZhbHVlICsgXCJcIjtcbiAgICAgIHJldHVybiB4aHI7XG4gICAgfTtcbiAgICB4aHIucmVzcG9uc2VUeXBlID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHJlc3BvbnNlVHlwZTtcbiAgICAgIHJlc3BvbnNlVHlwZSA9IHZhbHVlO1xuICAgICAgcmV0dXJuIHhocjtcbiAgICB9O1xuICAgIHhoci5yZXNwb25zZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXNwb25zZSA9IHZhbHVlO1xuICAgICAgcmV0dXJuIHhocjtcbiAgICB9O1xuICAgIFsgXCJnZXRcIiwgXCJwb3N0XCIgXS5mb3JFYWNoKGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgICAgeGhyW21ldGhvZF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHhoci5zZW5kLmFwcGx5KHhociwgWyBtZXRob2QgXS5jb25jYXQoZDNfYXJyYXkoYXJndW1lbnRzKSkpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgICB4aHIuc2VuZCA9IGZ1bmN0aW9uKG1ldGhvZCwgZGF0YSwgY2FsbGJhY2spIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAyICYmIHR5cGVvZiBkYXRhID09PSBcImZ1bmN0aW9uXCIpIGNhbGxiYWNrID0gZGF0YSwgZGF0YSA9IG51bGw7XG4gICAgICByZXF1ZXN0Lm9wZW4obWV0aG9kLCB1cmwsIHRydWUpO1xuICAgICAgaWYgKG1pbWVUeXBlICE9IG51bGwgJiYgIShcImFjY2VwdFwiIGluIGhlYWRlcnMpKSBoZWFkZXJzW1wiYWNjZXB0XCJdID0gbWltZVR5cGUgKyBcIiwqLypcIjtcbiAgICAgIGlmIChyZXF1ZXN0LnNldFJlcXVlc3RIZWFkZXIpIGZvciAodmFyIG5hbWUgaW4gaGVhZGVycykgcmVxdWVzdC5zZXRSZXF1ZXN0SGVhZGVyKG5hbWUsIGhlYWRlcnNbbmFtZV0pO1xuICAgICAgaWYgKG1pbWVUeXBlICE9IG51bGwgJiYgcmVxdWVzdC5vdmVycmlkZU1pbWVUeXBlKSByZXF1ZXN0Lm92ZXJyaWRlTWltZVR5cGUobWltZVR5cGUpO1xuICAgICAgaWYgKHJlc3BvbnNlVHlwZSAhPSBudWxsKSByZXF1ZXN0LnJlc3BvbnNlVHlwZSA9IHJlc3BvbnNlVHlwZTtcbiAgICAgIGlmIChjYWxsYmFjayAhPSBudWxsKSB4aHIub24oXCJlcnJvclwiLCBjYWxsYmFjaykub24oXCJsb2FkXCIsIGZ1bmN0aW9uKHJlcXVlc3QpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgcmVxdWVzdCk7XG4gICAgICB9KTtcbiAgICAgIGRpc3BhdGNoLmJlZm9yZXNlbmQuY2FsbCh4aHIsIHJlcXVlc3QpO1xuICAgICAgcmVxdWVzdC5zZW5kKGRhdGEgPT0gbnVsbCA/IG51bGwgOiBkYXRhKTtcbiAgICAgIHJldHVybiB4aHI7XG4gICAgfTtcbiAgICB4aHIuYWJvcnQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJlcXVlc3QuYWJvcnQoKTtcbiAgICAgIHJldHVybiB4aHI7XG4gICAgfTtcbiAgICBkMy5yZWJpbmQoeGhyLCBkaXNwYXRjaCwgXCJvblwiKTtcbiAgICByZXR1cm4gY2FsbGJhY2sgPT0gbnVsbCA/IHhociA6IHhoci5nZXQoZDNfeGhyX2ZpeENhbGxiYWNrKGNhbGxiYWNrKSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfeGhyX2ZpeENhbGxiYWNrKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGNhbGxiYWNrLmxlbmd0aCA9PT0gMSA/IGZ1bmN0aW9uKGVycm9yLCByZXF1ZXN0KSB7XG4gICAgICBjYWxsYmFjayhlcnJvciA9PSBudWxsID8gcmVxdWVzdCA6IG51bGwpO1xuICAgIH0gOiBjYWxsYmFjaztcbiAgfVxuICBmdW5jdGlvbiBkM194aHJIYXNSZXNwb25zZShyZXF1ZXN0KSB7XG4gICAgdmFyIHR5cGUgPSByZXF1ZXN0LnJlc3BvbnNlVHlwZTtcbiAgICByZXR1cm4gdHlwZSAmJiB0eXBlICE9PSBcInRleHRcIiA/IHJlcXVlc3QucmVzcG9uc2UgOiByZXF1ZXN0LnJlc3BvbnNlVGV4dDtcbiAgfVxuICBkMy5kc3YgPSBmdW5jdGlvbihkZWxpbWl0ZXIsIG1pbWVUeXBlKSB7XG4gICAgdmFyIHJlRm9ybWF0ID0gbmV3IFJlZ0V4cCgnW1wiJyArIGRlbGltaXRlciArIFwiXFxuXVwiKSwgZGVsaW1pdGVyQ29kZSA9IGRlbGltaXRlci5jaGFyQ29kZUF0KDApO1xuICAgIGZ1bmN0aW9uIGRzdih1cmwsIHJvdywgY2FsbGJhY2spIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMykgY2FsbGJhY2sgPSByb3csIHJvdyA9IG51bGw7XG4gICAgICB2YXIgeGhyID0gZDNfeGhyKHVybCwgbWltZVR5cGUsIHJvdyA9PSBudWxsID8gcmVzcG9uc2UgOiB0eXBlZFJlc3BvbnNlKHJvdyksIGNhbGxiYWNrKTtcbiAgICAgIHhoci5yb3cgPSBmdW5jdGlvbihfKSB7XG4gICAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8geGhyLnJlc3BvbnNlKChyb3cgPSBfKSA9PSBudWxsID8gcmVzcG9uc2UgOiB0eXBlZFJlc3BvbnNlKF8pKSA6IHJvdztcbiAgICAgIH07XG4gICAgICByZXR1cm4geGhyO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNwb25zZShyZXF1ZXN0KSB7XG4gICAgICByZXR1cm4gZHN2LnBhcnNlKHJlcXVlc3QucmVzcG9uc2VUZXh0KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHlwZWRSZXNwb25zZShmKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ocmVxdWVzdCkge1xuICAgICAgICByZXR1cm4gZHN2LnBhcnNlKHJlcXVlc3QucmVzcG9uc2VUZXh0LCBmKTtcbiAgICAgIH07XG4gICAgfVxuICAgIGRzdi5wYXJzZSA9IGZ1bmN0aW9uKHRleHQsIGYpIHtcbiAgICAgIHZhciBvO1xuICAgICAgcmV0dXJuIGRzdi5wYXJzZVJvd3ModGV4dCwgZnVuY3Rpb24ocm93LCBpKSB7XG4gICAgICAgIGlmIChvKSByZXR1cm4gbyhyb3csIGkgLSAxKTtcbiAgICAgICAgdmFyIGEgPSBuZXcgRnVuY3Rpb24oXCJkXCIsIFwicmV0dXJuIHtcIiArIHJvdy5tYXAoZnVuY3Rpb24obmFtZSwgaSkge1xuICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShuYW1lKSArIFwiOiBkW1wiICsgaSArIFwiXVwiO1xuICAgICAgICB9KS5qb2luKFwiLFwiKSArIFwifVwiKTtcbiAgICAgICAgbyA9IGYgPyBmdW5jdGlvbihyb3csIGkpIHtcbiAgICAgICAgICByZXR1cm4gZihhKHJvdyksIGkpO1xuICAgICAgICB9IDogYTtcbiAgICAgIH0pO1xuICAgIH07XG4gICAgZHN2LnBhcnNlUm93cyA9IGZ1bmN0aW9uKHRleHQsIGYpIHtcbiAgICAgIHZhciBFT0wgPSB7fSwgRU9GID0ge30sIHJvd3MgPSBbXSwgTiA9IHRleHQubGVuZ3RoLCBJID0gMCwgbiA9IDAsIHQsIGVvbDtcbiAgICAgIGZ1bmN0aW9uIHRva2VuKCkge1xuICAgICAgICBpZiAoSSA+PSBOKSByZXR1cm4gRU9GO1xuICAgICAgICBpZiAoZW9sKSByZXR1cm4gZW9sID0gZmFsc2UsIEVPTDtcbiAgICAgICAgdmFyIGogPSBJO1xuICAgICAgICBpZiAodGV4dC5jaGFyQ29kZUF0KGopID09PSAzNCkge1xuICAgICAgICAgIHZhciBpID0gajtcbiAgICAgICAgICB3aGlsZSAoaSsrIDwgTikge1xuICAgICAgICAgICAgaWYgKHRleHQuY2hhckNvZGVBdChpKSA9PT0gMzQpIHtcbiAgICAgICAgICAgICAgaWYgKHRleHQuY2hhckNvZGVBdChpICsgMSkgIT09IDM0KSBicmVhaztcbiAgICAgICAgICAgICAgKytpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBJID0gaSArIDI7XG4gICAgICAgICAgdmFyIGMgPSB0ZXh0LmNoYXJDb2RlQXQoaSArIDEpO1xuICAgICAgICAgIGlmIChjID09PSAxMykge1xuICAgICAgICAgICAgZW9sID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0ZXh0LmNoYXJDb2RlQXQoaSArIDIpID09PSAxMCkgKytJO1xuICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gMTApIHtcbiAgICAgICAgICAgIGVvbCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0ZXh0LnNsaWNlKGogKyAxLCBpKS5yZXBsYWNlKC9cIlwiL2csICdcIicpO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChJIDwgTikge1xuICAgICAgICAgIHZhciBjID0gdGV4dC5jaGFyQ29kZUF0KEkrKyksIGsgPSAxO1xuICAgICAgICAgIGlmIChjID09PSAxMCkgZW9sID0gdHJ1ZTsgZWxzZSBpZiAoYyA9PT0gMTMpIHtcbiAgICAgICAgICAgIGVvbCA9IHRydWU7XG4gICAgICAgICAgICBpZiAodGV4dC5jaGFyQ29kZUF0KEkpID09PSAxMCkgKytJLCArK2s7XG4gICAgICAgICAgfSBlbHNlIGlmIChjICE9PSBkZWxpbWl0ZXJDb2RlKSBjb250aW51ZTtcbiAgICAgICAgICByZXR1cm4gdGV4dC5zbGljZShqLCBJIC0gayk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRleHQuc2xpY2Uoaik7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKHQgPSB0b2tlbigpKSAhPT0gRU9GKSB7XG4gICAgICAgIHZhciBhID0gW107XG4gICAgICAgIHdoaWxlICh0ICE9PSBFT0wgJiYgdCAhPT0gRU9GKSB7XG4gICAgICAgICAgYS5wdXNoKHQpO1xuICAgICAgICAgIHQgPSB0b2tlbigpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmICYmIChhID0gZihhLCBuKyspKSA9PSBudWxsKSBjb250aW51ZTtcbiAgICAgICAgcm93cy5wdXNoKGEpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJvd3M7XG4gICAgfTtcbiAgICBkc3YuZm9ybWF0ID0gZnVuY3Rpb24ocm93cykge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkocm93c1swXSkpIHJldHVybiBkc3YuZm9ybWF0Um93cyhyb3dzKTtcbiAgICAgIHZhciBmaWVsZFNldCA9IG5ldyBkM19TZXQoKSwgZmllbGRzID0gW107XG4gICAgICByb3dzLmZvckVhY2goZnVuY3Rpb24ocm93KSB7XG4gICAgICAgIGZvciAodmFyIGZpZWxkIGluIHJvdykge1xuICAgICAgICAgIGlmICghZmllbGRTZXQuaGFzKGZpZWxkKSkge1xuICAgICAgICAgICAgZmllbGRzLnB1c2goZmllbGRTZXQuYWRkKGZpZWxkKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBbIGZpZWxkcy5tYXAoZm9ybWF0VmFsdWUpLmpvaW4oZGVsaW1pdGVyKSBdLmNvbmNhdChyb3dzLm1hcChmdW5jdGlvbihyb3cpIHtcbiAgICAgICAgcmV0dXJuIGZpZWxkcy5tYXAoZnVuY3Rpb24oZmllbGQpIHtcbiAgICAgICAgICByZXR1cm4gZm9ybWF0VmFsdWUocm93W2ZpZWxkXSk7XG4gICAgICAgIH0pLmpvaW4oZGVsaW1pdGVyKTtcbiAgICAgIH0pKS5qb2luKFwiXFxuXCIpO1xuICAgIH07XG4gICAgZHN2LmZvcm1hdFJvd3MgPSBmdW5jdGlvbihyb3dzKSB7XG4gICAgICByZXR1cm4gcm93cy5tYXAoZm9ybWF0Um93KS5qb2luKFwiXFxuXCIpO1xuICAgIH07XG4gICAgZnVuY3Rpb24gZm9ybWF0Um93KHJvdykge1xuICAgICAgcmV0dXJuIHJvdy5tYXAoZm9ybWF0VmFsdWUpLmpvaW4oZGVsaW1pdGVyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZm9ybWF0VmFsdWUodGV4dCkge1xuICAgICAgcmV0dXJuIHJlRm9ybWF0LnRlc3QodGV4dCkgPyAnXCInICsgdGV4dC5yZXBsYWNlKC9cXFwiL2csICdcIlwiJykgKyAnXCInIDogdGV4dDtcbiAgICB9XG4gICAgcmV0dXJuIGRzdjtcbiAgfTtcbiAgZDMuY3N2ID0gZDMuZHN2KFwiLFwiLCBcInRleHQvY3N2XCIpO1xuICBkMy50c3YgPSBkMy5kc3YoXCJcdFwiLCBcInRleHQvdGFiLXNlcGFyYXRlZC12YWx1ZXNcIik7XG4gIHZhciBkM190aW1lcl9xdWV1ZUhlYWQsIGQzX3RpbWVyX3F1ZXVlVGFpbCwgZDNfdGltZXJfaW50ZXJ2YWwsIGQzX3RpbWVyX3RpbWVvdXQsIGQzX3RpbWVyX2ZyYW1lID0gdGhpc1tkM192ZW5kb3JTeW1ib2wodGhpcywgXCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWVcIildIHx8IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgc2V0VGltZW91dChjYWxsYmFjaywgMTcpO1xuICB9O1xuICBkMy50aW1lciA9IGZ1bmN0aW9uKCkge1xuICAgIGQzX3RpbWVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RpbWVyKGNhbGxiYWNrLCBkZWxheSwgdGhlbikge1xuICAgIHZhciBuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICBpZiAobiA8IDIpIGRlbGF5ID0gMDtcbiAgICBpZiAobiA8IDMpIHRoZW4gPSBEYXRlLm5vdygpO1xuICAgIHZhciB0aW1lID0gdGhlbiArIGRlbGF5LCB0aW1lciA9IHtcbiAgICAgIGM6IGNhbGxiYWNrLFxuICAgICAgdDogdGltZSxcbiAgICAgIG46IG51bGxcbiAgICB9O1xuICAgIGlmIChkM190aW1lcl9xdWV1ZVRhaWwpIGQzX3RpbWVyX3F1ZXVlVGFpbC5uID0gdGltZXI7IGVsc2UgZDNfdGltZXJfcXVldWVIZWFkID0gdGltZXI7XG4gICAgZDNfdGltZXJfcXVldWVUYWlsID0gdGltZXI7XG4gICAgaWYgKCFkM190aW1lcl9pbnRlcnZhbCkge1xuICAgICAgZDNfdGltZXJfdGltZW91dCA9IGNsZWFyVGltZW91dChkM190aW1lcl90aW1lb3V0KTtcbiAgICAgIGQzX3RpbWVyX2ludGVydmFsID0gMTtcbiAgICAgIGQzX3RpbWVyX2ZyYW1lKGQzX3RpbWVyX3N0ZXApO1xuICAgIH1cbiAgICByZXR1cm4gdGltZXI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZXJfc3RlcCgpIHtcbiAgICB2YXIgbm93ID0gZDNfdGltZXJfbWFyaygpLCBkZWxheSA9IGQzX3RpbWVyX3N3ZWVwKCkgLSBub3c7XG4gICAgaWYgKGRlbGF5ID4gMjQpIHtcbiAgICAgIGlmIChpc0Zpbml0ZShkZWxheSkpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KGQzX3RpbWVyX3RpbWVvdXQpO1xuICAgICAgICBkM190aW1lcl90aW1lb3V0ID0gc2V0VGltZW91dChkM190aW1lcl9zdGVwLCBkZWxheSk7XG4gICAgICB9XG4gICAgICBkM190aW1lcl9pbnRlcnZhbCA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGQzX3RpbWVyX2ludGVydmFsID0gMTtcbiAgICAgIGQzX3RpbWVyX2ZyYW1lKGQzX3RpbWVyX3N0ZXApO1xuICAgIH1cbiAgfVxuICBkMy50aW1lci5mbHVzaCA9IGZ1bmN0aW9uKCkge1xuICAgIGQzX3RpbWVyX21hcmsoKTtcbiAgICBkM190aW1lcl9zd2VlcCgpO1xuICB9O1xuICBmdW5jdGlvbiBkM190aW1lcl9tYXJrKCkge1xuICAgIHZhciBub3cgPSBEYXRlLm5vdygpLCB0aW1lciA9IGQzX3RpbWVyX3F1ZXVlSGVhZDtcbiAgICB3aGlsZSAodGltZXIpIHtcbiAgICAgIGlmIChub3cgPj0gdGltZXIudCAmJiB0aW1lci5jKG5vdyAtIHRpbWVyLnQpKSB0aW1lci5jID0gbnVsbDtcbiAgICAgIHRpbWVyID0gdGltZXIubjtcbiAgICB9XG4gICAgcmV0dXJuIG5vdztcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lcl9zd2VlcCgpIHtcbiAgICB2YXIgdDAsIHQxID0gZDNfdGltZXJfcXVldWVIZWFkLCB0aW1lID0gSW5maW5pdHk7XG4gICAgd2hpbGUgKHQxKSB7XG4gICAgICBpZiAodDEuYykge1xuICAgICAgICBpZiAodDEudCA8IHRpbWUpIHRpbWUgPSB0MS50O1xuICAgICAgICB0MSA9ICh0MCA9IHQxKS5uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdDEgPSB0MCA/IHQwLm4gPSB0MS5uIDogZDNfdGltZXJfcXVldWVIZWFkID0gdDEubjtcbiAgICAgIH1cbiAgICB9XG4gICAgZDNfdGltZXJfcXVldWVUYWlsID0gdDA7XG4gICAgcmV0dXJuIHRpbWU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZm9ybWF0X3ByZWNpc2lvbih4LCBwKSB7XG4gICAgcmV0dXJuIHAgLSAoeCA/IE1hdGguY2VpbChNYXRoLmxvZyh4KSAvIE1hdGguTE4xMCkgOiAxKTtcbiAgfVxuICBkMy5yb3VuZCA9IGZ1bmN0aW9uKHgsIG4pIHtcbiAgICByZXR1cm4gbiA/IE1hdGgucm91bmQoeCAqIChuID0gTWF0aC5wb3coMTAsIG4pKSkgLyBuIDogTWF0aC5yb3VuZCh4KTtcbiAgfTtcbiAgdmFyIGQzX2Zvcm1hdFByZWZpeGVzID0gWyBcInlcIiwgXCJ6XCIsIFwiYVwiLCBcImZcIiwgXCJwXCIsIFwiblwiLCBcIsK1XCIsIFwibVwiLCBcIlwiLCBcImtcIiwgXCJNXCIsIFwiR1wiLCBcIlRcIiwgXCJQXCIsIFwiRVwiLCBcIlpcIiwgXCJZXCIgXS5tYXAoZDNfZm9ybWF0UHJlZml4KTtcbiAgZDMuZm9ybWF0UHJlZml4ID0gZnVuY3Rpb24odmFsdWUsIHByZWNpc2lvbikge1xuICAgIHZhciBpID0gMDtcbiAgICBpZiAodmFsdWUgPSArdmFsdWUpIHtcbiAgICAgIGlmICh2YWx1ZSA8IDApIHZhbHVlICo9IC0xO1xuICAgICAgaWYgKHByZWNpc2lvbikgdmFsdWUgPSBkMy5yb3VuZCh2YWx1ZSwgZDNfZm9ybWF0X3ByZWNpc2lvbih2YWx1ZSwgcHJlY2lzaW9uKSk7XG4gICAgICBpID0gMSArIE1hdGguZmxvb3IoMWUtMTIgKyBNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMTApO1xuICAgICAgaSA9IE1hdGgubWF4KC0yNCwgTWF0aC5taW4oMjQsIE1hdGguZmxvb3IoKGkgLSAxKSAvIDMpICogMykpO1xuICAgIH1cbiAgICByZXR1cm4gZDNfZm9ybWF0UHJlZml4ZXNbOCArIGkgLyAzXTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZm9ybWF0UHJlZml4KGQsIGkpIHtcbiAgICB2YXIgayA9IE1hdGgucG93KDEwLCBhYnMoOCAtIGkpICogMyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNjYWxlOiBpID4gOCA/IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGQgLyBrO1xuICAgICAgfSA6IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGQgKiBrO1xuICAgICAgfSxcbiAgICAgIHN5bWJvbDogZFxuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfbG9jYWxlX251bWJlckZvcm1hdChsb2NhbGUpIHtcbiAgICB2YXIgbG9jYWxlX2RlY2ltYWwgPSBsb2NhbGUuZGVjaW1hbCwgbG9jYWxlX3Rob3VzYW5kcyA9IGxvY2FsZS50aG91c2FuZHMsIGxvY2FsZV9ncm91cGluZyA9IGxvY2FsZS5ncm91cGluZywgbG9jYWxlX2N1cnJlbmN5ID0gbG9jYWxlLmN1cnJlbmN5LCBmb3JtYXRHcm91cCA9IGxvY2FsZV9ncm91cGluZyAmJiBsb2NhbGVfdGhvdXNhbmRzID8gZnVuY3Rpb24odmFsdWUsIHdpZHRoKSB7XG4gICAgICB2YXIgaSA9IHZhbHVlLmxlbmd0aCwgdCA9IFtdLCBqID0gMCwgZyA9IGxvY2FsZV9ncm91cGluZ1swXSwgbGVuZ3RoID0gMDtcbiAgICAgIHdoaWxlIChpID4gMCAmJiBnID4gMCkge1xuICAgICAgICBpZiAobGVuZ3RoICsgZyArIDEgPiB3aWR0aCkgZyA9IE1hdGgubWF4KDEsIHdpZHRoIC0gbGVuZ3RoKTtcbiAgICAgICAgdC5wdXNoKHZhbHVlLnN1YnN0cmluZyhpIC09IGcsIGkgKyBnKSk7XG4gICAgICAgIGlmICgobGVuZ3RoICs9IGcgKyAxKSA+IHdpZHRoKSBicmVhaztcbiAgICAgICAgZyA9IGxvY2FsZV9ncm91cGluZ1tqID0gKGogKyAxKSAlIGxvY2FsZV9ncm91cGluZy5sZW5ndGhdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHQucmV2ZXJzZSgpLmpvaW4obG9jYWxlX3Rob3VzYW5kcyk7XG4gICAgfSA6IGQzX2lkZW50aXR5O1xuICAgIHJldHVybiBmdW5jdGlvbihzcGVjaWZpZXIpIHtcbiAgICAgIHZhciBtYXRjaCA9IGQzX2Zvcm1hdF9yZS5leGVjKHNwZWNpZmllciksIGZpbGwgPSBtYXRjaFsxXSB8fCBcIiBcIiwgYWxpZ24gPSBtYXRjaFsyXSB8fCBcIj5cIiwgc2lnbiA9IG1hdGNoWzNdIHx8IFwiLVwiLCBzeW1ib2wgPSBtYXRjaFs0XSB8fCBcIlwiLCB6ZmlsbCA9IG1hdGNoWzVdLCB3aWR0aCA9ICttYXRjaFs2XSwgY29tbWEgPSBtYXRjaFs3XSwgcHJlY2lzaW9uID0gbWF0Y2hbOF0sIHR5cGUgPSBtYXRjaFs5XSwgc2NhbGUgPSAxLCBwcmVmaXggPSBcIlwiLCBzdWZmaXggPSBcIlwiLCBpbnRlZ2VyID0gZmFsc2UsIGV4cG9uZW50ID0gdHJ1ZTtcbiAgICAgIGlmIChwcmVjaXNpb24pIHByZWNpc2lvbiA9ICtwcmVjaXNpb24uc3Vic3RyaW5nKDEpO1xuICAgICAgaWYgKHpmaWxsIHx8IGZpbGwgPT09IFwiMFwiICYmIGFsaWduID09PSBcIj1cIikge1xuICAgICAgICB6ZmlsbCA9IGZpbGwgPSBcIjBcIjtcbiAgICAgICAgYWxpZ24gPSBcIj1cIjtcbiAgICAgIH1cbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgIGNhc2UgXCJuXCI6XG4gICAgICAgIGNvbW1hID0gdHJ1ZTtcbiAgICAgICAgdHlwZSA9IFwiZ1wiO1xuICAgICAgICBicmVhaztcblxuICAgICAgIGNhc2UgXCIlXCI6XG4gICAgICAgIHNjYWxlID0gMTAwO1xuICAgICAgICBzdWZmaXggPSBcIiVcIjtcbiAgICAgICAgdHlwZSA9IFwiZlwiO1xuICAgICAgICBicmVhaztcblxuICAgICAgIGNhc2UgXCJwXCI6XG4gICAgICAgIHNjYWxlID0gMTAwO1xuICAgICAgICBzdWZmaXggPSBcIiVcIjtcbiAgICAgICAgdHlwZSA9IFwiclwiO1xuICAgICAgICBicmVhaztcblxuICAgICAgIGNhc2UgXCJiXCI6XG4gICAgICAgY2FzZSBcIm9cIjpcbiAgICAgICBjYXNlIFwieFwiOlxuICAgICAgIGNhc2UgXCJYXCI6XG4gICAgICAgIGlmIChzeW1ib2wgPT09IFwiI1wiKSBwcmVmaXggPSBcIjBcIiArIHR5cGUudG9Mb3dlckNhc2UoKTtcblxuICAgICAgIGNhc2UgXCJjXCI6XG4gICAgICAgIGV4cG9uZW50ID0gZmFsc2U7XG5cbiAgICAgICBjYXNlIFwiZFwiOlxuICAgICAgICBpbnRlZ2VyID0gdHJ1ZTtcbiAgICAgICAgcHJlY2lzaW9uID0gMDtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgICBjYXNlIFwic1wiOlxuICAgICAgICBzY2FsZSA9IC0xO1xuICAgICAgICB0eXBlID0gXCJyXCI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKHN5bWJvbCA9PT0gXCIkXCIpIHByZWZpeCA9IGxvY2FsZV9jdXJyZW5jeVswXSwgc3VmZml4ID0gbG9jYWxlX2N1cnJlbmN5WzFdO1xuICAgICAgaWYgKHR5cGUgPT0gXCJyXCIgJiYgIXByZWNpc2lvbikgdHlwZSA9IFwiZ1wiO1xuICAgICAgaWYgKHByZWNpc2lvbiAhPSBudWxsKSB7XG4gICAgICAgIGlmICh0eXBlID09IFwiZ1wiKSBwcmVjaXNpb24gPSBNYXRoLm1heCgxLCBNYXRoLm1pbigyMSwgcHJlY2lzaW9uKSk7IGVsc2UgaWYgKHR5cGUgPT0gXCJlXCIgfHwgdHlwZSA9PSBcImZcIikgcHJlY2lzaW9uID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjAsIHByZWNpc2lvbikpO1xuICAgICAgfVxuICAgICAgdHlwZSA9IGQzX2Zvcm1hdF90eXBlcy5nZXQodHlwZSkgfHwgZDNfZm9ybWF0X3R5cGVEZWZhdWx0O1xuICAgICAgdmFyIHpjb21tYSA9IHpmaWxsICYmIGNvbW1hO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHZhciBmdWxsU3VmZml4ID0gc3VmZml4O1xuICAgICAgICBpZiAoaW50ZWdlciAmJiB2YWx1ZSAlIDEpIHJldHVybiBcIlwiO1xuICAgICAgICB2YXIgbmVnYXRpdmUgPSB2YWx1ZSA8IDAgfHwgdmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCA/ICh2YWx1ZSA9IC12YWx1ZSwgXCItXCIpIDogc2lnbiA9PT0gXCItXCIgPyBcIlwiIDogc2lnbjtcbiAgICAgICAgaWYgKHNjYWxlIDwgMCkge1xuICAgICAgICAgIHZhciB1bml0ID0gZDMuZm9ybWF0UHJlZml4KHZhbHVlLCBwcmVjaXNpb24pO1xuICAgICAgICAgIHZhbHVlID0gdW5pdC5zY2FsZSh2YWx1ZSk7XG4gICAgICAgICAgZnVsbFN1ZmZpeCA9IHVuaXQuc3ltYm9sICsgc3VmZml4O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlICo9IHNjYWxlO1xuICAgICAgICB9XG4gICAgICAgIHZhbHVlID0gdHlwZSh2YWx1ZSwgcHJlY2lzaW9uKTtcbiAgICAgICAgdmFyIGkgPSB2YWx1ZS5sYXN0SW5kZXhPZihcIi5cIiksIGJlZm9yZSwgYWZ0ZXI7XG4gICAgICAgIGlmIChpIDwgMCkge1xuICAgICAgICAgIHZhciBqID0gZXhwb25lbnQgPyB2YWx1ZS5sYXN0SW5kZXhPZihcImVcIikgOiAtMTtcbiAgICAgICAgICBpZiAoaiA8IDApIGJlZm9yZSA9IHZhbHVlLCBhZnRlciA9IFwiXCI7IGVsc2UgYmVmb3JlID0gdmFsdWUuc3Vic3RyaW5nKDAsIGopLCBhZnRlciA9IHZhbHVlLnN1YnN0cmluZyhqKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBiZWZvcmUgPSB2YWx1ZS5zdWJzdHJpbmcoMCwgaSk7XG4gICAgICAgICAgYWZ0ZXIgPSBsb2NhbGVfZGVjaW1hbCArIHZhbHVlLnN1YnN0cmluZyhpICsgMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF6ZmlsbCAmJiBjb21tYSkgYmVmb3JlID0gZm9ybWF0R3JvdXAoYmVmb3JlLCBJbmZpbml0eSk7XG4gICAgICAgIHZhciBsZW5ndGggPSBwcmVmaXgubGVuZ3RoICsgYmVmb3JlLmxlbmd0aCArIGFmdGVyLmxlbmd0aCArICh6Y29tbWEgPyAwIDogbmVnYXRpdmUubGVuZ3RoKSwgcGFkZGluZyA9IGxlbmd0aCA8IHdpZHRoID8gbmV3IEFycmF5KGxlbmd0aCA9IHdpZHRoIC0gbGVuZ3RoICsgMSkuam9pbihmaWxsKSA6IFwiXCI7XG4gICAgICAgIGlmICh6Y29tbWEpIGJlZm9yZSA9IGZvcm1hdEdyb3VwKHBhZGRpbmcgKyBiZWZvcmUsIHBhZGRpbmcubGVuZ3RoID8gd2lkdGggLSBhZnRlci5sZW5ndGggOiBJbmZpbml0eSk7XG4gICAgICAgIG5lZ2F0aXZlICs9IHByZWZpeDtcbiAgICAgICAgdmFsdWUgPSBiZWZvcmUgKyBhZnRlcjtcbiAgICAgICAgcmV0dXJuIChhbGlnbiA9PT0gXCI8XCIgPyBuZWdhdGl2ZSArIHZhbHVlICsgcGFkZGluZyA6IGFsaWduID09PSBcIj5cIiA/IHBhZGRpbmcgKyBuZWdhdGl2ZSArIHZhbHVlIDogYWxpZ24gPT09IFwiXlwiID8gcGFkZGluZy5zdWJzdHJpbmcoMCwgbGVuZ3RoID4+PSAxKSArIG5lZ2F0aXZlICsgdmFsdWUgKyBwYWRkaW5nLnN1YnN0cmluZyhsZW5ndGgpIDogbmVnYXRpdmUgKyAoemNvbW1hID8gdmFsdWUgOiBwYWRkaW5nICsgdmFsdWUpKSArIGZ1bGxTdWZmaXg7XG4gICAgICB9O1xuICAgIH07XG4gIH1cbiAgdmFyIGQzX2Zvcm1hdF9yZSA9IC8oPzooW157XSk/KFs8Pj1eXSkpPyhbK1xcLSBdKT8oWyQjXSk/KDApPyhcXGQrKT8oLCk/KFxcLi0/XFxkKyk/KFthLXolXSk/L2k7XG4gIHZhciBkM19mb3JtYXRfdHlwZXMgPSBkMy5tYXAoe1xuICAgIGI6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiB4LnRvU3RyaW5nKDIpO1xuICAgIH0sXG4gICAgYzogZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoeCk7XG4gICAgfSxcbiAgICBvOiBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4geC50b1N0cmluZyg4KTtcbiAgICB9LFxuICAgIHg6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiB4LnRvU3RyaW5nKDE2KTtcbiAgICB9LFxuICAgIFg6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiB4LnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xuICAgIH0sXG4gICAgZzogZnVuY3Rpb24oeCwgcCkge1xuICAgICAgcmV0dXJuIHgudG9QcmVjaXNpb24ocCk7XG4gICAgfSxcbiAgICBlOiBmdW5jdGlvbih4LCBwKSB7XG4gICAgICByZXR1cm4geC50b0V4cG9uZW50aWFsKHApO1xuICAgIH0sXG4gICAgZjogZnVuY3Rpb24oeCwgcCkge1xuICAgICAgcmV0dXJuIHgudG9GaXhlZChwKTtcbiAgICB9LFxuICAgIHI6IGZ1bmN0aW9uKHgsIHApIHtcbiAgICAgIHJldHVybiAoeCA9IGQzLnJvdW5kKHgsIGQzX2Zvcm1hdF9wcmVjaXNpb24oeCwgcCkpKS50b0ZpeGVkKE1hdGgubWF4KDAsIE1hdGgubWluKDIwLCBkM19mb3JtYXRfcHJlY2lzaW9uKHggKiAoMSArIDFlLTE1KSwgcCkpKSk7XG4gICAgfVxuICB9KTtcbiAgZnVuY3Rpb24gZDNfZm9ybWF0X3R5cGVEZWZhdWx0KHgpIHtcbiAgICByZXR1cm4geCArIFwiXCI7XG4gIH1cbiAgdmFyIGQzX3RpbWUgPSBkMy50aW1lID0ge30sIGQzX2RhdGUgPSBEYXRlO1xuICBmdW5jdGlvbiBkM19kYXRlX3V0YygpIHtcbiAgICB0aGlzLl8gPSBuZXcgRGF0ZShhcmd1bWVudHMubGVuZ3RoID4gMSA/IERhdGUuVVRDLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgOiBhcmd1bWVudHNbMF0pO1xuICB9XG4gIGQzX2RhdGVfdXRjLnByb3RvdHlwZSA9IHtcbiAgICBnZXREYXRlOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl8uZ2V0VVRDRGF0ZSgpO1xuICAgIH0sXG4gICAgZ2V0RGF5OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl8uZ2V0VVRDRGF5KCk7XG4gICAgfSxcbiAgICBnZXRGdWxsWWVhcjogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLmdldFVUQ0Z1bGxZZWFyKCk7XG4gICAgfSxcbiAgICBnZXRIb3VyczogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLmdldFVUQ0hvdXJzKCk7XG4gICAgfSxcbiAgICBnZXRNaWxsaXNlY29uZHM6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuXy5nZXRVVENNaWxsaXNlY29uZHMoKTtcbiAgICB9LFxuICAgIGdldE1pbnV0ZXM6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuXy5nZXRVVENNaW51dGVzKCk7XG4gICAgfSxcbiAgICBnZXRNb250aDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLmdldFVUQ01vbnRoKCk7XG4gICAgfSxcbiAgICBnZXRTZWNvbmRzOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl8uZ2V0VVRDU2Vjb25kcygpO1xuICAgIH0sXG4gICAgZ2V0VGltZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLmdldFRpbWUoKTtcbiAgICB9LFxuICAgIGdldFRpbWV6b25lT2Zmc2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0sXG4gICAgdmFsdWVPZjogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fLnZhbHVlT2YoKTtcbiAgICB9LFxuICAgIHNldERhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfdGltZV9wcm90b3R5cGUuc2V0VVRDRGF0ZS5hcHBseSh0aGlzLl8sIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICBzZXREYXk6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfdGltZV9wcm90b3R5cGUuc2V0VVRDRGF5LmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldEZ1bGxZZWFyOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX3RpbWVfcHJvdG90eXBlLnNldFVUQ0Z1bGxZZWFyLmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldEhvdXJzOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX3RpbWVfcHJvdG90eXBlLnNldFVUQ0hvdXJzLmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldE1pbGxpc2Vjb25kczogZnVuY3Rpb24oKSB7XG4gICAgICBkM190aW1lX3Byb3RvdHlwZS5zZXRVVENNaWxsaXNlY29uZHMuYXBwbHkodGhpcy5fLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgc2V0TWludXRlczogZnVuY3Rpb24oKSB7XG4gICAgICBkM190aW1lX3Byb3RvdHlwZS5zZXRVVENNaW51dGVzLmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldE1vbnRoOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX3RpbWVfcHJvdG90eXBlLnNldFVUQ01vbnRoLmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNldFNlY29uZHM6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfdGltZV9wcm90b3R5cGUuc2V0VVRDU2Vjb25kcy5hcHBseSh0aGlzLl8sIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICBzZXRUaW1lOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX3RpbWVfcHJvdG90eXBlLnNldFRpbWUuYXBwbHkodGhpcy5fLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfTtcbiAgdmFyIGQzX3RpbWVfcHJvdG90eXBlID0gRGF0ZS5wcm90b3R5cGU7XG4gIGZ1bmN0aW9uIGQzX3RpbWVfaW50ZXJ2YWwobG9jYWwsIHN0ZXAsIG51bWJlcikge1xuICAgIGZ1bmN0aW9uIHJvdW5kKGRhdGUpIHtcbiAgICAgIHZhciBkMCA9IGxvY2FsKGRhdGUpLCBkMSA9IG9mZnNldChkMCwgMSk7XG4gICAgICByZXR1cm4gZGF0ZSAtIGQwIDwgZDEgLSBkYXRlID8gZDAgOiBkMTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY2VpbChkYXRlKSB7XG4gICAgICBzdGVwKGRhdGUgPSBsb2NhbChuZXcgZDNfZGF0ZShkYXRlIC0gMSkpLCAxKTtcbiAgICAgIHJldHVybiBkYXRlO1xuICAgIH1cbiAgICBmdW5jdGlvbiBvZmZzZXQoZGF0ZSwgaykge1xuICAgICAgc3RlcChkYXRlID0gbmV3IGQzX2RhdGUoK2RhdGUpLCBrKTtcbiAgICAgIHJldHVybiBkYXRlO1xuICAgIH1cbiAgICBmdW5jdGlvbiByYW5nZSh0MCwgdDEsIGR0KSB7XG4gICAgICB2YXIgdGltZSA9IGNlaWwodDApLCB0aW1lcyA9IFtdO1xuICAgICAgaWYgKGR0ID4gMSkge1xuICAgICAgICB3aGlsZSAodGltZSA8IHQxKSB7XG4gICAgICAgICAgaWYgKCEobnVtYmVyKHRpbWUpICUgZHQpKSB0aW1lcy5wdXNoKG5ldyBEYXRlKCt0aW1lKSk7XG4gICAgICAgICAgc3RlcCh0aW1lLCAxKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2hpbGUgKHRpbWUgPCB0MSkgdGltZXMucHVzaChuZXcgRGF0ZSgrdGltZSkpLCBzdGVwKHRpbWUsIDEpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRpbWVzO1xuICAgIH1cbiAgICBmdW5jdGlvbiByYW5nZV91dGModDAsIHQxLCBkdCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZDNfZGF0ZSA9IGQzX2RhdGVfdXRjO1xuICAgICAgICB2YXIgdXRjID0gbmV3IGQzX2RhdGVfdXRjKCk7XG4gICAgICAgIHV0Yy5fID0gdDA7XG4gICAgICAgIHJldHVybiByYW5nZSh1dGMsIHQxLCBkdCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICBkM19kYXRlID0gRGF0ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgbG9jYWwuZmxvb3IgPSBsb2NhbDtcbiAgICBsb2NhbC5yb3VuZCA9IHJvdW5kO1xuICAgIGxvY2FsLmNlaWwgPSBjZWlsO1xuICAgIGxvY2FsLm9mZnNldCA9IG9mZnNldDtcbiAgICBsb2NhbC5yYW5nZSA9IHJhbmdlO1xuICAgIHZhciB1dGMgPSBsb2NhbC51dGMgPSBkM190aW1lX2ludGVydmFsX3V0Yyhsb2NhbCk7XG4gICAgdXRjLmZsb29yID0gdXRjO1xuICAgIHV0Yy5yb3VuZCA9IGQzX3RpbWVfaW50ZXJ2YWxfdXRjKHJvdW5kKTtcbiAgICB1dGMuY2VpbCA9IGQzX3RpbWVfaW50ZXJ2YWxfdXRjKGNlaWwpO1xuICAgIHV0Yy5vZmZzZXQgPSBkM190aW1lX2ludGVydmFsX3V0YyhvZmZzZXQpO1xuICAgIHV0Yy5yYW5nZSA9IHJhbmdlX3V0YztcbiAgICByZXR1cm4gbG9jYWw7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9pbnRlcnZhbF91dGMobWV0aG9kKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGRhdGUsIGspIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGQzX2RhdGUgPSBkM19kYXRlX3V0YztcbiAgICAgICAgdmFyIHV0YyA9IG5ldyBkM19kYXRlX3V0YygpO1xuICAgICAgICB1dGMuXyA9IGRhdGU7XG4gICAgICAgIHJldHVybiBtZXRob2QodXRjLCBrKS5fO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgZDNfZGF0ZSA9IERhdGU7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICBkM190aW1lLnllYXIgPSBkM190aW1lX2ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlID0gZDNfdGltZS5kYXkoZGF0ZSk7XG4gICAgZGF0ZS5zZXRNb250aCgwLCAxKTtcbiAgICByZXR1cm4gZGF0ZTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRGdWxsWWVhcihkYXRlLmdldEZ1bGxZZWFyKCkgKyBvZmZzZXQpO1xuICB9LCBmdW5jdGlvbihkYXRlKSB7XG4gICAgcmV0dXJuIGRhdGUuZ2V0RnVsbFllYXIoKTtcbiAgfSk7XG4gIGQzX3RpbWUueWVhcnMgPSBkM190aW1lLnllYXIucmFuZ2U7XG4gIGQzX3RpbWUueWVhcnMudXRjID0gZDNfdGltZS55ZWFyLnV0Yy5yYW5nZTtcbiAgZDNfdGltZS5kYXkgPSBkM190aW1lX2ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICB2YXIgZGF5ID0gbmV3IGQzX2RhdGUoMmUzLCAwKTtcbiAgICBkYXkuc2V0RnVsbFllYXIoZGF0ZS5nZXRGdWxsWWVhcigpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RGF0ZSgpKTtcbiAgICByZXR1cm4gZGF5O1xuICB9LCBmdW5jdGlvbihkYXRlLCBvZmZzZXQpIHtcbiAgICBkYXRlLnNldERhdGUoZGF0ZS5nZXREYXRlKCkgKyBvZmZzZXQpO1xuICB9LCBmdW5jdGlvbihkYXRlKSB7XG4gICAgcmV0dXJuIGRhdGUuZ2V0RGF0ZSgpIC0gMTtcbiAgfSk7XG4gIGQzX3RpbWUuZGF5cyA9IGQzX3RpbWUuZGF5LnJhbmdlO1xuICBkM190aW1lLmRheXMudXRjID0gZDNfdGltZS5kYXkudXRjLnJhbmdlO1xuICBkM190aW1lLmRheU9mWWVhciA9IGZ1bmN0aW9uKGRhdGUpIHtcbiAgICB2YXIgeWVhciA9IGQzX3RpbWUueWVhcihkYXRlKTtcbiAgICByZXR1cm4gTWF0aC5mbG9vcigoZGF0ZSAtIHllYXIgLSAoZGF0ZS5nZXRUaW1lem9uZU9mZnNldCgpIC0geWVhci5nZXRUaW1lem9uZU9mZnNldCgpKSAqIDZlNCkgLyA4NjRlNSk7XG4gIH07XG4gIFsgXCJzdW5kYXlcIiwgXCJtb25kYXlcIiwgXCJ0dWVzZGF5XCIsIFwid2VkbmVzZGF5XCIsIFwidGh1cnNkYXlcIiwgXCJmcmlkYXlcIiwgXCJzYXR1cmRheVwiIF0uZm9yRWFjaChmdW5jdGlvbihkYXksIGkpIHtcbiAgICBpID0gNyAtIGk7XG4gICAgdmFyIGludGVydmFsID0gZDNfdGltZVtkYXldID0gZDNfdGltZV9pbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgICAoZGF0ZSA9IGQzX3RpbWUuZGF5KGRhdGUpKS5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpIC0gKGRhdGUuZ2V0RGF5KCkgKyBpKSAlIDcpO1xuICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgICBkYXRlLnNldERhdGUoZGF0ZS5nZXREYXRlKCkgKyBNYXRoLmZsb29yKG9mZnNldCkgKiA3KTtcbiAgICB9LCBmdW5jdGlvbihkYXRlKSB7XG4gICAgICB2YXIgZGF5ID0gZDNfdGltZS55ZWFyKGRhdGUpLmdldERheSgpO1xuICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGQzX3RpbWUuZGF5T2ZZZWFyKGRhdGUpICsgKGRheSArIGkpICUgNykgLyA3KSAtIChkYXkgIT09IGkpO1xuICAgIH0pO1xuICAgIGQzX3RpbWVbZGF5ICsgXCJzXCJdID0gaW50ZXJ2YWwucmFuZ2U7XG4gICAgZDNfdGltZVtkYXkgKyBcInNcIl0udXRjID0gaW50ZXJ2YWwudXRjLnJhbmdlO1xuICAgIGQzX3RpbWVbZGF5ICsgXCJPZlllYXJcIl0gPSBmdW5jdGlvbihkYXRlKSB7XG4gICAgICB2YXIgZGF5ID0gZDNfdGltZS55ZWFyKGRhdGUpLmdldERheSgpO1xuICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGQzX3RpbWUuZGF5T2ZZZWFyKGRhdGUpICsgKGRheSArIGkpICUgNykgLyA3KTtcbiAgICB9O1xuICB9KTtcbiAgZDNfdGltZS53ZWVrID0gZDNfdGltZS5zdW5kYXk7XG4gIGQzX3RpbWUud2Vla3MgPSBkM190aW1lLnN1bmRheS5yYW5nZTtcbiAgZDNfdGltZS53ZWVrcy51dGMgPSBkM190aW1lLnN1bmRheS51dGMucmFuZ2U7XG4gIGQzX3RpbWUud2Vla09mWWVhciA9IGQzX3RpbWUuc3VuZGF5T2ZZZWFyO1xuICBmdW5jdGlvbiBkM19sb2NhbGVfdGltZUZvcm1hdChsb2NhbGUpIHtcbiAgICB2YXIgbG9jYWxlX2RhdGVUaW1lID0gbG9jYWxlLmRhdGVUaW1lLCBsb2NhbGVfZGF0ZSA9IGxvY2FsZS5kYXRlLCBsb2NhbGVfdGltZSA9IGxvY2FsZS50aW1lLCBsb2NhbGVfcGVyaW9kcyA9IGxvY2FsZS5wZXJpb2RzLCBsb2NhbGVfZGF5cyA9IGxvY2FsZS5kYXlzLCBsb2NhbGVfc2hvcnREYXlzID0gbG9jYWxlLnNob3J0RGF5cywgbG9jYWxlX21vbnRocyA9IGxvY2FsZS5tb250aHMsIGxvY2FsZV9zaG9ydE1vbnRocyA9IGxvY2FsZS5zaG9ydE1vbnRocztcbiAgICBmdW5jdGlvbiBkM190aW1lX2Zvcm1hdCh0ZW1wbGF0ZSkge1xuICAgICAgdmFyIG4gPSB0ZW1wbGF0ZS5sZW5ndGg7XG4gICAgICBmdW5jdGlvbiBmb3JtYXQoZGF0ZSkge1xuICAgICAgICB2YXIgc3RyaW5nID0gW10sIGkgPSAtMSwgaiA9IDAsIGMsIHAsIGY7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgaWYgKHRlbXBsYXRlLmNoYXJDb2RlQXQoaSkgPT09IDM3KSB7XG4gICAgICAgICAgICBzdHJpbmcucHVzaCh0ZW1wbGF0ZS5zbGljZShqLCBpKSk7XG4gICAgICAgICAgICBpZiAoKHAgPSBkM190aW1lX2Zvcm1hdFBhZHNbYyA9IHRlbXBsYXRlLmNoYXJBdCgrK2kpXSkgIT0gbnVsbCkgYyA9IHRlbXBsYXRlLmNoYXJBdCgrK2kpO1xuICAgICAgICAgICAgaWYgKGYgPSBkM190aW1lX2Zvcm1hdHNbY10pIGMgPSBmKGRhdGUsIHAgPT0gbnVsbCA/IGMgPT09IFwiZVwiID8gXCIgXCIgOiBcIjBcIiA6IHApO1xuICAgICAgICAgICAgc3RyaW5nLnB1c2goYyk7XG4gICAgICAgICAgICBqID0gaSArIDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0cmluZy5wdXNoKHRlbXBsYXRlLnNsaWNlKGosIGkpKTtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5qb2luKFwiXCIpO1xuICAgICAgfVxuICAgICAgZm9ybWF0LnBhcnNlID0gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICAgIHZhciBkID0ge1xuICAgICAgICAgIHk6IDE5MDAsXG4gICAgICAgICAgbTogMCxcbiAgICAgICAgICBkOiAxLFxuICAgICAgICAgIEg6IDAsXG4gICAgICAgICAgTTogMCxcbiAgICAgICAgICBTOiAwLFxuICAgICAgICAgIEw6IDAsXG4gICAgICAgICAgWjogbnVsbFxuICAgICAgICB9LCBpID0gZDNfdGltZV9wYXJzZShkLCB0ZW1wbGF0ZSwgc3RyaW5nLCAwKTtcbiAgICAgICAgaWYgKGkgIT0gc3RyaW5nLmxlbmd0aCkgcmV0dXJuIG51bGw7XG4gICAgICAgIGlmIChcInBcIiBpbiBkKSBkLkggPSBkLkggJSAxMiArIGQucCAqIDEyO1xuICAgICAgICB2YXIgbG9jYWxaID0gZC5aICE9IG51bGwgJiYgZDNfZGF0ZSAhPT0gZDNfZGF0ZV91dGMsIGRhdGUgPSBuZXcgKGxvY2FsWiA/IGQzX2RhdGVfdXRjIDogZDNfZGF0ZSkoKTtcbiAgICAgICAgaWYgKFwialwiIGluIGQpIGRhdGUuc2V0RnVsbFllYXIoZC55LCAwLCBkLmopOyBlbHNlIGlmIChcIldcIiBpbiBkIHx8IFwiVVwiIGluIGQpIHtcbiAgICAgICAgICBpZiAoIShcIndcIiBpbiBkKSkgZC53ID0gXCJXXCIgaW4gZCA/IDEgOiAwO1xuICAgICAgICAgIGRhdGUuc2V0RnVsbFllYXIoZC55LCAwLCAxKTtcbiAgICAgICAgICBkYXRlLnNldEZ1bGxZZWFyKGQueSwgMCwgXCJXXCIgaW4gZCA/IChkLncgKyA2KSAlIDcgKyBkLlcgKiA3IC0gKGRhdGUuZ2V0RGF5KCkgKyA1KSAlIDcgOiBkLncgKyBkLlUgKiA3IC0gKGRhdGUuZ2V0RGF5KCkgKyA2KSAlIDcpO1xuICAgICAgICB9IGVsc2UgZGF0ZS5zZXRGdWxsWWVhcihkLnksIGQubSwgZC5kKTtcbiAgICAgICAgZGF0ZS5zZXRIb3VycyhkLkggKyAoZC5aIC8gMTAwIHwgMCksIGQuTSArIGQuWiAlIDEwMCwgZC5TLCBkLkwpO1xuICAgICAgICByZXR1cm4gbG9jYWxaID8gZGF0ZS5fIDogZGF0ZTtcbiAgICAgIH07XG4gICAgICBmb3JtYXQudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRlbXBsYXRlO1xuICAgICAgfTtcbiAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2UoZGF0ZSwgdGVtcGxhdGUsIHN0cmluZywgaikge1xuICAgICAgdmFyIGMsIHAsIHQsIGkgPSAwLCBuID0gdGVtcGxhdGUubGVuZ3RoLCBtID0gc3RyaW5nLmxlbmd0aDtcbiAgICAgIHdoaWxlIChpIDwgbikge1xuICAgICAgICBpZiAoaiA+PSBtKSByZXR1cm4gLTE7XG4gICAgICAgIGMgPSB0ZW1wbGF0ZS5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICAgIGlmIChjID09PSAzNykge1xuICAgICAgICAgIHQgPSB0ZW1wbGF0ZS5jaGFyQXQoaSsrKTtcbiAgICAgICAgICBwID0gZDNfdGltZV9wYXJzZXJzW3QgaW4gZDNfdGltZV9mb3JtYXRQYWRzID8gdGVtcGxhdGUuY2hhckF0KGkrKykgOiB0XTtcbiAgICAgICAgICBpZiAoIXAgfHwgKGogPSBwKGRhdGUsIHN0cmluZywgaikpIDwgMCkgcmV0dXJuIC0xO1xuICAgICAgICB9IGVsc2UgaWYgKGMgIT0gc3RyaW5nLmNoYXJDb2RlQXQoaisrKSkge1xuICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGo7XG4gICAgfVxuICAgIGQzX3RpbWVfZm9ybWF0LnV0YyA9IGZ1bmN0aW9uKHRlbXBsYXRlKSB7XG4gICAgICB2YXIgbG9jYWwgPSBkM190aW1lX2Zvcm1hdCh0ZW1wbGF0ZSk7XG4gICAgICBmdW5jdGlvbiBmb3JtYXQoZGF0ZSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGQzX2RhdGUgPSBkM19kYXRlX3V0YztcbiAgICAgICAgICB2YXIgdXRjID0gbmV3IGQzX2RhdGUoKTtcbiAgICAgICAgICB1dGMuXyA9IGRhdGU7XG4gICAgICAgICAgcmV0dXJuIGxvY2FsKHV0Yyk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgZDNfZGF0ZSA9IERhdGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZvcm1hdC5wYXJzZSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGQzX2RhdGUgPSBkM19kYXRlX3V0YztcbiAgICAgICAgICB2YXIgZGF0ZSA9IGxvY2FsLnBhcnNlKHN0cmluZyk7XG4gICAgICAgICAgcmV0dXJuIGRhdGUgJiYgZGF0ZS5fO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIGQzX2RhdGUgPSBEYXRlO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgZm9ybWF0LnRvU3RyaW5nID0gbG9jYWwudG9TdHJpbmc7XG4gICAgICByZXR1cm4gZm9ybWF0O1xuICAgIH07XG4gICAgZDNfdGltZV9mb3JtYXQubXVsdGkgPSBkM190aW1lX2Zvcm1hdC51dGMubXVsdGkgPSBkM190aW1lX2Zvcm1hdE11bHRpO1xuICAgIHZhciBkM190aW1lX3BlcmlvZExvb2t1cCA9IGQzLm1hcCgpLCBkM190aW1lX2RheVJlID0gZDNfdGltZV9mb3JtYXRSZShsb2NhbGVfZGF5cyksIGQzX3RpbWVfZGF5TG9va3VwID0gZDNfdGltZV9mb3JtYXRMb29rdXAobG9jYWxlX2RheXMpLCBkM190aW1lX2RheUFiYnJldlJlID0gZDNfdGltZV9mb3JtYXRSZShsb2NhbGVfc2hvcnREYXlzKSwgZDNfdGltZV9kYXlBYmJyZXZMb29rdXAgPSBkM190aW1lX2Zvcm1hdExvb2t1cChsb2NhbGVfc2hvcnREYXlzKSwgZDNfdGltZV9tb250aFJlID0gZDNfdGltZV9mb3JtYXRSZShsb2NhbGVfbW9udGhzKSwgZDNfdGltZV9tb250aExvb2t1cCA9IGQzX3RpbWVfZm9ybWF0TG9va3VwKGxvY2FsZV9tb250aHMpLCBkM190aW1lX21vbnRoQWJicmV2UmUgPSBkM190aW1lX2Zvcm1hdFJlKGxvY2FsZV9zaG9ydE1vbnRocyksIGQzX3RpbWVfbW9udGhBYmJyZXZMb29rdXAgPSBkM190aW1lX2Zvcm1hdExvb2t1cChsb2NhbGVfc2hvcnRNb250aHMpO1xuICAgIGxvY2FsZV9wZXJpb2RzLmZvckVhY2goZnVuY3Rpb24ocCwgaSkge1xuICAgICAgZDNfdGltZV9wZXJpb2RMb29rdXAuc2V0KHAudG9Mb3dlckNhc2UoKSwgaSk7XG4gICAgfSk7XG4gICAgdmFyIGQzX3RpbWVfZm9ybWF0cyA9IHtcbiAgICAgIGE6IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZV9zaG9ydERheXNbZC5nZXREYXkoKV07XG4gICAgICB9LFxuICAgICAgQTogZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gbG9jYWxlX2RheXNbZC5nZXREYXkoKV07XG4gICAgICB9LFxuICAgICAgYjogZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gbG9jYWxlX3Nob3J0TW9udGhzW2QuZ2V0TW9udGgoKV07XG4gICAgICB9LFxuICAgICAgQjogZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gbG9jYWxlX21vbnRoc1tkLmdldE1vbnRoKCldO1xuICAgICAgfSxcbiAgICAgIGM6IGQzX3RpbWVfZm9ybWF0KGxvY2FsZV9kYXRlVGltZSksXG4gICAgICBkOiBmdW5jdGlvbihkLCBwKSB7XG4gICAgICAgIHJldHVybiBkM190aW1lX2Zvcm1hdFBhZChkLmdldERhdGUoKSwgcCwgMik7XG4gICAgICB9LFxuICAgICAgZTogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXREYXRlKCksIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIEg6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKGQuZ2V0SG91cnMoKSwgcCwgMik7XG4gICAgICB9LFxuICAgICAgSTogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRIb3VycygpICUgMTIgfHwgMTIsIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIGo6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKDEgKyBkM190aW1lLmRheU9mWWVhcihkKSwgcCwgMyk7XG4gICAgICB9LFxuICAgICAgTDogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRNaWxsaXNlY29uZHMoKSwgcCwgMyk7XG4gICAgICB9LFxuICAgICAgbTogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRNb250aCgpICsgMSwgcCwgMik7XG4gICAgICB9LFxuICAgICAgTTogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRNaW51dGVzKCksIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIHA6IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZV9wZXJpb2RzWysoZC5nZXRIb3VycygpID49IDEyKV07XG4gICAgICB9LFxuICAgICAgUzogZnVuY3Rpb24oZCwgcCkge1xuICAgICAgICByZXR1cm4gZDNfdGltZV9mb3JtYXRQYWQoZC5nZXRTZWNvbmRzKCksIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIFU6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKGQzX3RpbWUuc3VuZGF5T2ZZZWFyKGQpLCBwLCAyKTtcbiAgICAgIH0sXG4gICAgICB3OiBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBkLmdldERheSgpO1xuICAgICAgfSxcbiAgICAgIFc6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKGQzX3RpbWUubW9uZGF5T2ZZZWFyKGQpLCBwLCAyKTtcbiAgICAgIH0sXG4gICAgICB4OiBkM190aW1lX2Zvcm1hdChsb2NhbGVfZGF0ZSksXG4gICAgICBYOiBkM190aW1lX2Zvcm1hdChsb2NhbGVfdGltZSksXG4gICAgICB5OiBmdW5jdGlvbihkLCBwKSB7XG4gICAgICAgIHJldHVybiBkM190aW1lX2Zvcm1hdFBhZChkLmdldEZ1bGxZZWFyKCkgJSAxMDAsIHAsIDIpO1xuICAgICAgfSxcbiAgICAgIFk6IGZ1bmN0aW9uKGQsIHApIHtcbiAgICAgICAgcmV0dXJuIGQzX3RpbWVfZm9ybWF0UGFkKGQuZ2V0RnVsbFllYXIoKSAlIDFlNCwgcCwgNCk7XG4gICAgICB9LFxuICAgICAgWjogZDNfdGltZV96b25lLFxuICAgICAgXCIlXCI6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gXCIlXCI7XG4gICAgICB9XG4gICAgfTtcbiAgICB2YXIgZDNfdGltZV9wYXJzZXJzID0ge1xuICAgICAgYTogZDNfdGltZV9wYXJzZVdlZWtkYXlBYmJyZXYsXG4gICAgICBBOiBkM190aW1lX3BhcnNlV2Vla2RheSxcbiAgICAgIGI6IGQzX3RpbWVfcGFyc2VNb250aEFiYnJldixcbiAgICAgIEI6IGQzX3RpbWVfcGFyc2VNb250aCxcbiAgICAgIGM6IGQzX3RpbWVfcGFyc2VMb2NhbGVGdWxsLFxuICAgICAgZDogZDNfdGltZV9wYXJzZURheSxcbiAgICAgIGU6IGQzX3RpbWVfcGFyc2VEYXksXG4gICAgICBIOiBkM190aW1lX3BhcnNlSG91cjI0LFxuICAgICAgSTogZDNfdGltZV9wYXJzZUhvdXIyNCxcbiAgICAgIGo6IGQzX3RpbWVfcGFyc2VEYXlPZlllYXIsXG4gICAgICBMOiBkM190aW1lX3BhcnNlTWlsbGlzZWNvbmRzLFxuICAgICAgbTogZDNfdGltZV9wYXJzZU1vbnRoTnVtYmVyLFxuICAgICAgTTogZDNfdGltZV9wYXJzZU1pbnV0ZXMsXG4gICAgICBwOiBkM190aW1lX3BhcnNlQW1QbSxcbiAgICAgIFM6IGQzX3RpbWVfcGFyc2VTZWNvbmRzLFxuICAgICAgVTogZDNfdGltZV9wYXJzZVdlZWtOdW1iZXJTdW5kYXksXG4gICAgICB3OiBkM190aW1lX3BhcnNlV2Vla2RheU51bWJlcixcbiAgICAgIFc6IGQzX3RpbWVfcGFyc2VXZWVrTnVtYmVyTW9uZGF5LFxuICAgICAgeDogZDNfdGltZV9wYXJzZUxvY2FsZURhdGUsXG4gICAgICBYOiBkM190aW1lX3BhcnNlTG9jYWxlVGltZSxcbiAgICAgIHk6IGQzX3RpbWVfcGFyc2VZZWFyLFxuICAgICAgWTogZDNfdGltZV9wYXJzZUZ1bGxZZWFyLFxuICAgICAgWjogZDNfdGltZV9wYXJzZVpvbmUsXG4gICAgICBcIiVcIjogZDNfdGltZV9wYXJzZUxpdGVyYWxQZXJjZW50XG4gICAgfTtcbiAgICBmdW5jdGlvbiBkM190aW1lX3BhcnNlV2Vla2RheUFiYnJldihkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICAgIGQzX3RpbWVfZGF5QWJicmV2UmUubGFzdEluZGV4ID0gMDtcbiAgICAgIHZhciBuID0gZDNfdGltZV9kYXlBYmJyZXZSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgICByZXR1cm4gbiA/IChkYXRlLncgPSBkM190aW1lX2RheUFiYnJldkxvb2t1cC5nZXQoblswXS50b0xvd2VyQ2FzZSgpKSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkM190aW1lX3BhcnNlV2Vla2RheShkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICAgIGQzX3RpbWVfZGF5UmUubGFzdEluZGV4ID0gMDtcbiAgICAgIHZhciBuID0gZDNfdGltZV9kYXlSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgICByZXR1cm4gbiA/IChkYXRlLncgPSBkM190aW1lX2RheUxvb2t1cC5nZXQoblswXS50b0xvd2VyQ2FzZSgpKSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkM190aW1lX3BhcnNlTW9udGhBYmJyZXYoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgICBkM190aW1lX21vbnRoQWJicmV2UmUubGFzdEluZGV4ID0gMDtcbiAgICAgIHZhciBuID0gZDNfdGltZV9tb250aEFiYnJldlJlLmV4ZWMoc3RyaW5nLnNsaWNlKGkpKTtcbiAgICAgIHJldHVybiBuID8gKGRhdGUubSA9IGQzX3RpbWVfbW9udGhBYmJyZXZMb29rdXAuZ2V0KG5bMF0udG9Mb3dlckNhc2UoKSksIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZU1vbnRoKGRhdGUsIHN0cmluZywgaSkge1xuICAgICAgZDNfdGltZV9tb250aFJlLmxhc3RJbmRleCA9IDA7XG4gICAgICB2YXIgbiA9IGQzX3RpbWVfbW9udGhSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgICByZXR1cm4gbiA/IChkYXRlLm0gPSBkM190aW1lX21vbnRoTG9va3VwLmdldChuWzBdLnRvTG93ZXJDYXNlKCkpLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VMb2NhbGVGdWxsKGRhdGUsIHN0cmluZywgaSkge1xuICAgICAgcmV0dXJuIGQzX3RpbWVfcGFyc2UoZGF0ZSwgZDNfdGltZV9mb3JtYXRzLmMudG9TdHJpbmcoKSwgc3RyaW5nLCBpKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZUxvY2FsZURhdGUoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgICByZXR1cm4gZDNfdGltZV9wYXJzZShkYXRlLCBkM190aW1lX2Zvcm1hdHMueC50b1N0cmluZygpLCBzdHJpbmcsIGkpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkM190aW1lX3BhcnNlTG9jYWxlVGltZShkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICAgIHJldHVybiBkM190aW1lX3BhcnNlKGRhdGUsIGQzX3RpbWVfZm9ybWF0cy5YLnRvU3RyaW5nKCksIHN0cmluZywgaSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VBbVBtKGRhdGUsIHN0cmluZywgaSkge1xuICAgICAgdmFyIG4gPSBkM190aW1lX3BlcmlvZExvb2t1cC5nZXQoc3RyaW5nLnNsaWNlKGksIGkgKz0gMikudG9Mb3dlckNhc2UoKSk7XG4gICAgICByZXR1cm4gbiA9PSBudWxsID8gLTEgOiAoZGF0ZS5wID0gbiwgaSk7XG4gICAgfVxuICAgIHJldHVybiBkM190aW1lX2Zvcm1hdDtcbiAgfVxuICB2YXIgZDNfdGltZV9mb3JtYXRQYWRzID0ge1xuICAgIFwiLVwiOiBcIlwiLFxuICAgIF86IFwiIFwiLFxuICAgIFwiMFwiOiBcIjBcIlxuICB9LCBkM190aW1lX251bWJlclJlID0gL15cXHMqXFxkKy8sIGQzX3RpbWVfcGVyY2VudFJlID0gL14lLztcbiAgZnVuY3Rpb24gZDNfdGltZV9mb3JtYXRQYWQodmFsdWUsIGZpbGwsIHdpZHRoKSB7XG4gICAgdmFyIHNpZ24gPSB2YWx1ZSA8IDAgPyBcIi1cIiA6IFwiXCIsIHN0cmluZyA9IChzaWduID8gLXZhbHVlIDogdmFsdWUpICsgXCJcIiwgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aDtcbiAgICByZXR1cm4gc2lnbiArIChsZW5ndGggPCB3aWR0aCA/IG5ldyBBcnJheSh3aWR0aCAtIGxlbmd0aCArIDEpLmpvaW4oZmlsbCkgKyBzdHJpbmcgOiBzdHJpbmcpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RpbWVfZm9ybWF0UmUobmFtZXMpIHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChcIl4oPzpcIiArIG5hbWVzLm1hcChkMy5yZXF1b3RlKS5qb2luKFwifFwiKSArIFwiKVwiLCBcImlcIik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9mb3JtYXRMb29rdXAobmFtZXMpIHtcbiAgICB2YXIgbWFwID0gbmV3IGQzX01hcCgpLCBpID0gLTEsIG4gPSBuYW1lcy5sZW5ndGg7XG4gICAgd2hpbGUgKCsraSA8IG4pIG1hcC5zZXQobmFtZXNbaV0udG9Mb3dlckNhc2UoKSwgaSk7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3BhcnNlV2Vla2RheU51bWJlcihkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICBkM190aW1lX251bWJlclJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX251bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAxKSk7XG4gICAgcmV0dXJuIG4gPyAoZGF0ZS53ID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3BhcnNlV2Vla051bWJlclN1bmRheShkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICBkM190aW1lX251bWJlclJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX251bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGkpKTtcbiAgICByZXR1cm4gbiA/IChkYXRlLlUgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VXZWVrTnVtYmVyTW9uZGF5KGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfbnVtYmVyUmUubGFzdEluZGV4ID0gMDtcbiAgICB2YXIgbiA9IGQzX3RpbWVfbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSkpO1xuICAgIHJldHVybiBuID8gKGRhdGUuVyA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZUZ1bGxZZWFyKGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfbnVtYmVyUmUubGFzdEluZGV4ID0gMDtcbiAgICB2YXIgbiA9IGQzX3RpbWVfbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDQpKTtcbiAgICByZXR1cm4gbiA/IChkYXRlLnkgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VZZWFyKGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfbnVtYmVyUmUubGFzdEluZGV4ID0gMDtcbiAgICB2YXIgbiA9IGQzX3RpbWVfbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDIpKTtcbiAgICByZXR1cm4gbiA/IChkYXRlLnkgPSBkM190aW1lX2V4cGFuZFllYXIoK25bMF0pLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZVpvbmUoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgcmV0dXJuIC9eWystXVxcZHs0fSQvLnRlc3Qoc3RyaW5nID0gc3RyaW5nLnNsaWNlKGksIGkgKyA1KSkgPyAoZGF0ZS5aID0gLXN0cmluZywgXG4gICAgaSArIDUpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9leHBhbmRZZWFyKGQpIHtcbiAgICByZXR1cm4gZCArIChkID4gNjggPyAxOTAwIDogMmUzKTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3BhcnNlTW9udGhOdW1iZXIoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgZDNfdGltZV9udW1iZXJSZS5sYXN0SW5kZXggPSAwO1xuICAgIHZhciBuID0gZDNfdGltZV9udW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICAgIHJldHVybiBuID8gKGRhdGUubSA9IG5bMF0gLSAxLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZURheShkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICBkM190aW1lX251bWJlclJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX251bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAyKSk7XG4gICAgcmV0dXJuIG4gPyAoZGF0ZS5kID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3BhcnNlRGF5T2ZZZWFyKGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfbnVtYmVyUmUubGFzdEluZGV4ID0gMDtcbiAgICB2YXIgbiA9IGQzX3RpbWVfbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDMpKTtcbiAgICByZXR1cm4gbiA/IChkYXRlLmogPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RpbWVfcGFyc2VIb3VyMjQoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgZDNfdGltZV9udW1iZXJSZS5sYXN0SW5kZXggPSAwO1xuICAgIHZhciBuID0gZDNfdGltZV9udW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICAgIHJldHVybiBuID8gKGRhdGUuSCA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZU1pbnV0ZXMoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgZDNfdGltZV9udW1iZXJSZS5sYXN0SW5kZXggPSAwO1xuICAgIHZhciBuID0gZDNfdGltZV9udW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICAgIHJldHVybiBuID8gKGRhdGUuTSA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZVNlY29uZHMoZGF0ZSwgc3RyaW5nLCBpKSB7XG4gICAgZDNfdGltZV9udW1iZXJSZS5sYXN0SW5kZXggPSAwO1xuICAgIHZhciBuID0gZDNfdGltZV9udW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICAgIHJldHVybiBuID8gKGRhdGUuUyA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZU1pbGxpc2Vjb25kcyhkYXRlLCBzdHJpbmcsIGkpIHtcbiAgICBkM190aW1lX251bWJlclJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX251bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAzKSk7XG4gICAgcmV0dXJuIG4gPyAoZGF0ZS5MID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3pvbmUoZCkge1xuICAgIHZhciB6ID0gZC5nZXRUaW1lem9uZU9mZnNldCgpLCB6cyA9IHogPiAwID8gXCItXCIgOiBcIitcIiwgemggPSBhYnMoeikgLyA2MCB8IDAsIHptID0gYWJzKHopICUgNjA7XG4gICAgcmV0dXJuIHpzICsgZDNfdGltZV9mb3JtYXRQYWQoemgsIFwiMFwiLCAyKSArIGQzX3RpbWVfZm9ybWF0UGFkKHptLCBcIjBcIiwgMik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9wYXJzZUxpdGVyYWxQZXJjZW50KGRhdGUsIHN0cmluZywgaSkge1xuICAgIGQzX3RpbWVfcGVyY2VudFJlLmxhc3RJbmRleCA9IDA7XG4gICAgdmFyIG4gPSBkM190aW1lX3BlcmNlbnRSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMSkpO1xuICAgIHJldHVybiBuID8gaSArIG5bMF0ubGVuZ3RoIDogLTE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdGltZV9mb3JtYXRNdWx0aShmb3JtYXRzKSB7XG4gICAgdmFyIG4gPSBmb3JtYXRzLmxlbmd0aCwgaSA9IC0xO1xuICAgIHdoaWxlICgrK2kgPCBuKSBmb3JtYXRzW2ldWzBdID0gdGhpcyhmb3JtYXRzW2ldWzBdKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oZGF0ZSkge1xuICAgICAgdmFyIGkgPSAwLCBmID0gZm9ybWF0c1tpXTtcbiAgICAgIHdoaWxlICghZlsxXShkYXRlKSkgZiA9IGZvcm1hdHNbKytpXTtcbiAgICAgIHJldHVybiBmWzBdKGRhdGUpO1xuICAgIH07XG4gIH1cbiAgZDMubG9jYWxlID0gZnVuY3Rpb24obG9jYWxlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG51bWJlckZvcm1hdDogZDNfbG9jYWxlX251bWJlckZvcm1hdChsb2NhbGUpLFxuICAgICAgdGltZUZvcm1hdDogZDNfbG9jYWxlX3RpbWVGb3JtYXQobG9jYWxlKVxuICAgIH07XG4gIH07XG4gIHZhciBkM19sb2NhbGVfZW5VUyA9IGQzLmxvY2FsZSh7XG4gICAgZGVjaW1hbDogXCIuXCIsXG4gICAgdGhvdXNhbmRzOiBcIixcIixcbiAgICBncm91cGluZzogWyAzIF0sXG4gICAgY3VycmVuY3k6IFsgXCIkXCIsIFwiXCIgXSxcbiAgICBkYXRlVGltZTogXCIlYSAlYiAlZSAlWCAlWVwiLFxuICAgIGRhdGU6IFwiJW0vJWQvJVlcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogWyBcIkFNXCIsIFwiUE1cIiBdLFxuICAgIGRheXM6IFsgXCJTdW5kYXlcIiwgXCJNb25kYXlcIiwgXCJUdWVzZGF5XCIsIFwiV2VkbmVzZGF5XCIsIFwiVGh1cnNkYXlcIiwgXCJGcmlkYXlcIiwgXCJTYXR1cmRheVwiIF0sXG4gICAgc2hvcnREYXlzOiBbIFwiU3VuXCIsIFwiTW9uXCIsIFwiVHVlXCIsIFwiV2VkXCIsIFwiVGh1XCIsIFwiRnJpXCIsIFwiU2F0XCIgXSxcbiAgICBtb250aHM6IFsgXCJKYW51YXJ5XCIsIFwiRmVicnVhcnlcIiwgXCJNYXJjaFwiLCBcIkFwcmlsXCIsIFwiTWF5XCIsIFwiSnVuZVwiLCBcIkp1bHlcIiwgXCJBdWd1c3RcIiwgXCJTZXB0ZW1iZXJcIiwgXCJPY3RvYmVyXCIsIFwiTm92ZW1iZXJcIiwgXCJEZWNlbWJlclwiIF0sXG4gICAgc2hvcnRNb250aHM6IFsgXCJKYW5cIiwgXCJGZWJcIiwgXCJNYXJcIiwgXCJBcHJcIiwgXCJNYXlcIiwgXCJKdW5cIiwgXCJKdWxcIiwgXCJBdWdcIiwgXCJTZXBcIiwgXCJPY3RcIiwgXCJOb3ZcIiwgXCJEZWNcIiBdXG4gIH0pO1xuICBkMy5mb3JtYXQgPSBkM19sb2NhbGVfZW5VUy5udW1iZXJGb3JtYXQ7XG4gIGQzLmdlbyA9IHt9O1xuICBmdW5jdGlvbiBkM19hZGRlcigpIHt9XG4gIGQzX2FkZGVyLnByb3RvdHlwZSA9IHtcbiAgICBzOiAwLFxuICAgIHQ6IDAsXG4gICAgYWRkOiBmdW5jdGlvbih5KSB7XG4gICAgICBkM19hZGRlclN1bSh5LCB0aGlzLnQsIGQzX2FkZGVyVGVtcCk7XG4gICAgICBkM19hZGRlclN1bShkM19hZGRlclRlbXAucywgdGhpcy5zLCB0aGlzKTtcbiAgICAgIGlmICh0aGlzLnMpIHRoaXMudCArPSBkM19hZGRlclRlbXAudDsgZWxzZSB0aGlzLnMgPSBkM19hZGRlclRlbXAudDtcbiAgICB9LFxuICAgIHJlc2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMucyA9IHRoaXMudCA9IDA7XG4gICAgfSxcbiAgICB2YWx1ZU9mOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLnM7XG4gICAgfVxuICB9O1xuICB2YXIgZDNfYWRkZXJUZW1wID0gbmV3IGQzX2FkZGVyKCk7XG4gIGZ1bmN0aW9uIGQzX2FkZGVyU3VtKGEsIGIsIG8pIHtcbiAgICB2YXIgeCA9IG8ucyA9IGEgKyBiLCBidiA9IHggLSBhLCBhdiA9IHggLSBidjtcbiAgICBvLnQgPSBhIC0gYXYgKyAoYiAtIGJ2KTtcbiAgfVxuICBkMy5nZW8uc3RyZWFtID0gZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgIGlmIChvYmplY3QgJiYgZDNfZ2VvX3N0cmVhbU9iamVjdFR5cGUuaGFzT3duUHJvcGVydHkob2JqZWN0LnR5cGUpKSB7XG4gICAgICBkM19nZW9fc3RyZWFtT2JqZWN0VHlwZVtvYmplY3QudHlwZV0ob2JqZWN0LCBsaXN0ZW5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGQzX2dlb19zdHJlYW1HZW9tZXRyeShvYmplY3QsIGxpc3RlbmVyKTtcbiAgICB9XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19zdHJlYW1HZW9tZXRyeShnZW9tZXRyeSwgbGlzdGVuZXIpIHtcbiAgICBpZiAoZ2VvbWV0cnkgJiYgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5VHlwZS5oYXNPd25Qcm9wZXJ0eShnZW9tZXRyeS50eXBlKSkge1xuICAgICAgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5VHlwZVtnZW9tZXRyeS50eXBlXShnZW9tZXRyeSwgbGlzdGVuZXIpO1xuICAgIH1cbiAgfVxuICB2YXIgZDNfZ2VvX3N0cmVhbU9iamVjdFR5cGUgPSB7XG4gICAgRmVhdHVyZTogZnVuY3Rpb24oZmVhdHVyZSwgbGlzdGVuZXIpIHtcbiAgICAgIGQzX2dlb19zdHJlYW1HZW9tZXRyeShmZWF0dXJlLmdlb21ldHJ5LCBsaXN0ZW5lcik7XG4gICAgfSxcbiAgICBGZWF0dXJlQ29sbGVjdGlvbjogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGZlYXR1cmVzID0gb2JqZWN0LmZlYXR1cmVzLCBpID0gLTEsIG4gPSBmZWF0dXJlcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5KGZlYXR1cmVzW2ldLmdlb21ldHJ5LCBsaXN0ZW5lcik7XG4gICAgfVxuICB9O1xuICB2YXIgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5VHlwZSA9IHtcbiAgICBTcGhlcmU6IGZ1bmN0aW9uKG9iamVjdCwgbGlzdGVuZXIpIHtcbiAgICAgIGxpc3RlbmVyLnNwaGVyZSgpO1xuICAgIH0sXG4gICAgUG9pbnQ6IGZ1bmN0aW9uKG9iamVjdCwgbGlzdGVuZXIpIHtcbiAgICAgIG9iamVjdCA9IG9iamVjdC5jb29yZGluYXRlcztcbiAgICAgIGxpc3RlbmVyLnBvaW50KG9iamVjdFswXSwgb2JqZWN0WzFdLCBvYmplY3RbMl0pO1xuICAgIH0sXG4gICAgTXVsdGlQb2ludDogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGNvb3JkaW5hdGVzID0gb2JqZWN0LmNvb3JkaW5hdGVzLCBpID0gLTEsIG4gPSBjb29yZGluYXRlcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgb2JqZWN0ID0gY29vcmRpbmF0ZXNbaV0sIGxpc3RlbmVyLnBvaW50KG9iamVjdFswXSwgb2JqZWN0WzFdLCBvYmplY3RbMl0pO1xuICAgIH0sXG4gICAgTGluZVN0cmluZzogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgZDNfZ2VvX3N0cmVhbUxpbmUob2JqZWN0LmNvb3JkaW5hdGVzLCBsaXN0ZW5lciwgMCk7XG4gICAgfSxcbiAgICBNdWx0aUxpbmVTdHJpbmc6IGZ1bmN0aW9uKG9iamVjdCwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBjb29yZGluYXRlcyA9IG9iamVjdC5jb29yZGluYXRlcywgaSA9IC0xLCBuID0gY29vcmRpbmF0ZXMubGVuZ3RoO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGQzX2dlb19zdHJlYW1MaW5lKGNvb3JkaW5hdGVzW2ldLCBsaXN0ZW5lciwgMCk7XG4gICAgfSxcbiAgICBQb2x5Z29uOiBmdW5jdGlvbihvYmplY3QsIGxpc3RlbmVyKSB7XG4gICAgICBkM19nZW9fc3RyZWFtUG9seWdvbihvYmplY3QuY29vcmRpbmF0ZXMsIGxpc3RlbmVyKTtcbiAgICB9LFxuICAgIE11bHRpUG9seWdvbjogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGNvb3JkaW5hdGVzID0gb2JqZWN0LmNvb3JkaW5hdGVzLCBpID0gLTEsIG4gPSBjb29yZGluYXRlcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgZDNfZ2VvX3N0cmVhbVBvbHlnb24oY29vcmRpbmF0ZXNbaV0sIGxpc3RlbmVyKTtcbiAgICB9LFxuICAgIEdlb21ldHJ5Q29sbGVjdGlvbjogZnVuY3Rpb24ob2JqZWN0LCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGdlb21ldHJpZXMgPSBvYmplY3QuZ2VvbWV0cmllcywgaSA9IC0xLCBuID0gZ2VvbWV0cmllcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgZDNfZ2VvX3N0cmVhbUdlb21ldHJ5KGdlb21ldHJpZXNbaV0sIGxpc3RlbmVyKTtcbiAgICB9XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19zdHJlYW1MaW5lKGNvb3JkaW5hdGVzLCBsaXN0ZW5lciwgY2xvc2VkKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IGNvb3JkaW5hdGVzLmxlbmd0aCAtIGNsb3NlZCwgY29vcmRpbmF0ZTtcbiAgICBsaXN0ZW5lci5saW5lU3RhcnQoKTtcbiAgICB3aGlsZSAoKytpIDwgbikgY29vcmRpbmF0ZSA9IGNvb3JkaW5hdGVzW2ldLCBsaXN0ZW5lci5wb2ludChjb29yZGluYXRlWzBdLCBjb29yZGluYXRlWzFdLCBjb29yZGluYXRlWzJdKTtcbiAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3N0cmVhbVBvbHlnb24oY29vcmRpbmF0ZXMsIGxpc3RlbmVyKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IGNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICBsaXN0ZW5lci5wb2x5Z29uU3RhcnQoKTtcbiAgICB3aGlsZSAoKytpIDwgbikgZDNfZ2VvX3N0cmVhbUxpbmUoY29vcmRpbmF0ZXNbaV0sIGxpc3RlbmVyLCAxKTtcbiAgICBsaXN0ZW5lci5wb2x5Z29uRW5kKCk7XG4gIH1cbiAgZDMuZ2VvLmFyZWEgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBkM19nZW9fYXJlYVN1bSA9IDA7XG4gICAgZDMuZ2VvLnN0cmVhbShvYmplY3QsIGQzX2dlb19hcmVhKTtcbiAgICByZXR1cm4gZDNfZ2VvX2FyZWFTdW07XG4gIH07XG4gIHZhciBkM19nZW9fYXJlYVN1bSwgZDNfZ2VvX2FyZWFSaW5nU3VtID0gbmV3IGQzX2FkZGVyKCk7XG4gIHZhciBkM19nZW9fYXJlYSA9IHtcbiAgICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfZ2VvX2FyZWFTdW0gKz0gNCAqIM+AO1xuICAgIH0sXG4gICAgcG9pbnQ6IGQzX25vb3AsXG4gICAgbGluZVN0YXJ0OiBkM19ub29wLFxuICAgIGxpbmVFbmQ6IGQzX25vb3AsXG4gICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX2dlb19hcmVhUmluZ1N1bS5yZXNldCgpO1xuICAgICAgZDNfZ2VvX2FyZWEubGluZVN0YXJ0ID0gZDNfZ2VvX2FyZWFSaW5nU3RhcnQ7XG4gICAgfSxcbiAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBhcmVhID0gMiAqIGQzX2dlb19hcmVhUmluZ1N1bTtcbiAgICAgIGQzX2dlb19hcmVhU3VtICs9IGFyZWEgPCAwID8gNCAqIM+AICsgYXJlYSA6IGFyZWE7XG4gICAgICBkM19nZW9fYXJlYS5saW5lU3RhcnQgPSBkM19nZW9fYXJlYS5saW5lRW5kID0gZDNfZ2VvX2FyZWEucG9pbnQgPSBkM19ub29wO1xuICAgIH1cbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX2FyZWFSaW5nU3RhcnQoKSB7XG4gICAgdmFyIM67MDAsIM+GMDAsIM67MCwgY29zz4YwLCBzaW7PhjA7XG4gICAgZDNfZ2VvX2FyZWEucG9pbnQgPSBmdW5jdGlvbijOuywgz4YpIHtcbiAgICAgIGQzX2dlb19hcmVhLnBvaW50ID0gbmV4dFBvaW50O1xuICAgICAgzrswID0gKM67MDAgPSDOuykgKiBkM19yYWRpYW5zLCBjb3PPhjAgPSBNYXRoLmNvcyjPhiA9ICjPhjAwID0gz4YpICogZDNfcmFkaWFucyAvIDIgKyDPgCAvIDQpLCBcbiAgICAgIHNpbs+GMCA9IE1hdGguc2luKM+GKTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIG5leHRQb2ludCjOuywgz4YpIHtcbiAgICAgIM67ICo9IGQzX3JhZGlhbnM7XG4gICAgICDPhiA9IM+GICogZDNfcmFkaWFucyAvIDIgKyDPgCAvIDQ7XG4gICAgICB2YXIgZM67ID0gzrsgLSDOuzAsIHNkzrsgPSBkzrsgPj0gMCA/IDEgOiAtMSwgYWTOuyA9IHNkzrsgKiBkzrssIGNvc8+GID0gTWF0aC5jb3Moz4YpLCBzaW7PhiA9IE1hdGguc2luKM+GKSwgayA9IHNpbs+GMCAqIHNpbs+GLCB1ID0gY29zz4YwICogY29zz4YgKyBrICogTWF0aC5jb3MoYWTOuyksIHYgPSBrICogc2TOuyAqIE1hdGguc2luKGFkzrspO1xuICAgICAgZDNfZ2VvX2FyZWFSaW5nU3VtLmFkZChNYXRoLmF0YW4yKHYsIHUpKTtcbiAgICAgIM67MCA9IM67LCBjb3PPhjAgPSBjb3PPhiwgc2luz4YwID0gc2luz4Y7XG4gICAgfVxuICAgIGQzX2dlb19hcmVhLmxpbmVFbmQgPSBmdW5jdGlvbigpIHtcbiAgICAgIG5leHRQb2ludCjOuzAwLCDPhjAwKTtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jYXJ0ZXNpYW4oc3BoZXJpY2FsKSB7XG4gICAgdmFyIM67ID0gc3BoZXJpY2FsWzBdLCDPhiA9IHNwaGVyaWNhbFsxXSwgY29zz4YgPSBNYXRoLmNvcyjPhik7XG4gICAgcmV0dXJuIFsgY29zz4YgKiBNYXRoLmNvcyjOuyksIGNvc8+GICogTWF0aC5zaW4ozrspLCBNYXRoLnNpbijPhikgXTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2FydGVzaWFuRG90KGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jYXJ0ZXNpYW5Dcm9zcyhhLCBiKSB7XG4gICAgcmV0dXJuIFsgYVsxXSAqIGJbMl0gLSBhWzJdICogYlsxXSwgYVsyXSAqIGJbMF0gLSBhWzBdICogYlsyXSwgYVswXSAqIGJbMV0gLSBhWzFdICogYlswXSBdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jYXJ0ZXNpYW5BZGQoYSwgYikge1xuICAgIGFbMF0gKz0gYlswXTtcbiAgICBhWzFdICs9IGJbMV07XG4gICAgYVsyXSArPSBiWzJdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jYXJ0ZXNpYW5TY2FsZSh2ZWN0b3IsIGspIHtcbiAgICByZXR1cm4gWyB2ZWN0b3JbMF0gKiBrLCB2ZWN0b3JbMV0gKiBrLCB2ZWN0b3JbMl0gKiBrIF07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NhcnRlc2lhbk5vcm1hbGl6ZShkKSB7XG4gICAgdmFyIGwgPSBNYXRoLnNxcnQoZFswXSAqIGRbMF0gKyBkWzFdICogZFsxXSArIGRbMl0gKiBkWzJdKTtcbiAgICBkWzBdIC89IGw7XG4gICAgZFsxXSAvPSBsO1xuICAgIGRbMl0gLz0gbDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fc3BoZXJpY2FsKGNhcnRlc2lhbikge1xuICAgIHJldHVybiBbIE1hdGguYXRhbjIoY2FydGVzaWFuWzFdLCBjYXJ0ZXNpYW5bMF0pLCBkM19hc2luKGNhcnRlc2lhblsyXSkgXTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fc3BoZXJpY2FsRXF1YWwoYSwgYikge1xuICAgIHJldHVybiBhYnMoYVswXSAtIGJbMF0pIDwgzrUgJiYgYWJzKGFbMV0gLSBiWzFdKSA8IM61O1xuICB9XG4gIGQzLmdlby5ib3VuZHMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgzrswLCDPhjAsIM67MSwgz4YxLCDOu18sIM67X18sIM+GX18sIHAwLCBkzrtTdW0sIHJhbmdlcywgcmFuZ2U7XG4gICAgdmFyIGJvdW5kID0ge1xuICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgbGluZVN0YXJ0OiBsaW5lU3RhcnQsXG4gICAgICBsaW5lRW5kOiBsaW5lRW5kLFxuICAgICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgYm91bmQucG9pbnQgPSByaW5nUG9pbnQ7XG4gICAgICAgIGJvdW5kLmxpbmVTdGFydCA9IHJpbmdTdGFydDtcbiAgICAgICAgYm91bmQubGluZUVuZCA9IHJpbmdFbmQ7XG4gICAgICAgIGTOu1N1bSA9IDA7XG4gICAgICAgIGQzX2dlb19hcmVhLnBvbHlnb25TdGFydCgpO1xuICAgICAgfSxcbiAgICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBkM19nZW9fYXJlYS5wb2x5Z29uRW5kKCk7XG4gICAgICAgIGJvdW5kLnBvaW50ID0gcG9pbnQ7XG4gICAgICAgIGJvdW5kLmxpbmVTdGFydCA9IGxpbmVTdGFydDtcbiAgICAgICAgYm91bmQubGluZUVuZCA9IGxpbmVFbmQ7XG4gICAgICAgIGlmIChkM19nZW9fYXJlYVJpbmdTdW0gPCAwKSDOuzAgPSAtKM67MSA9IDE4MCksIM+GMCA9IC0oz4YxID0gOTApOyBlbHNlIGlmIChkzrtTdW0gPiDOtSkgz4YxID0gOTA7IGVsc2UgaWYgKGTOu1N1bSA8IC3OtSkgz4YwID0gLTkwO1xuICAgICAgICByYW5nZVswXSA9IM67MCwgcmFuZ2VbMV0gPSDOuzE7XG4gICAgICB9XG4gICAgfTtcbiAgICBmdW5jdGlvbiBwb2ludCjOuywgz4YpIHtcbiAgICAgIHJhbmdlcy5wdXNoKHJhbmdlID0gWyDOuzAgPSDOuywgzrsxID0gzrsgXSk7XG4gICAgICBpZiAoz4YgPCDPhjApIM+GMCA9IM+GO1xuICAgICAgaWYgKM+GID4gz4YxKSDPhjEgPSDPhjtcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZVBvaW50KM67LCDPhikge1xuICAgICAgdmFyIHAgPSBkM19nZW9fY2FydGVzaWFuKFsgzrsgKiBkM19yYWRpYW5zLCDPhiAqIGQzX3JhZGlhbnMgXSk7XG4gICAgICBpZiAocDApIHtcbiAgICAgICAgdmFyIG5vcm1hbCA9IGQzX2dlb19jYXJ0ZXNpYW5Dcm9zcyhwMCwgcCksIGVxdWF0b3JpYWwgPSBbIG5vcm1hbFsxXSwgLW5vcm1hbFswXSwgMCBdLCBpbmZsZWN0aW9uID0gZDNfZ2VvX2NhcnRlc2lhbkNyb3NzKGVxdWF0b3JpYWwsIG5vcm1hbCk7XG4gICAgICAgIGQzX2dlb19jYXJ0ZXNpYW5Ob3JtYWxpemUoaW5mbGVjdGlvbik7XG4gICAgICAgIGluZmxlY3Rpb24gPSBkM19nZW9fc3BoZXJpY2FsKGluZmxlY3Rpb24pO1xuICAgICAgICB2YXIgZM67ID0gzrsgLSDOu18sIHMgPSBkzrsgPiAwID8gMSA6IC0xLCDOu2kgPSBpbmZsZWN0aW9uWzBdICogZDNfZGVncmVlcyAqIHMsIGFudGltZXJpZGlhbiA9IGFicyhkzrspID4gMTgwO1xuICAgICAgICBpZiAoYW50aW1lcmlkaWFuIF4gKHMgKiDOu18gPCDOu2kgJiYgzrtpIDwgcyAqIM67KSkge1xuICAgICAgICAgIHZhciDPhmkgPSBpbmZsZWN0aW9uWzFdICogZDNfZGVncmVlcztcbiAgICAgICAgICBpZiAoz4ZpID4gz4YxKSDPhjEgPSDPhmk7XG4gICAgICAgIH0gZWxzZSBpZiAozrtpID0gKM67aSArIDM2MCkgJSAzNjAgLSAxODAsIGFudGltZXJpZGlhbiBeIChzICogzrtfIDwgzrtpICYmIM67aSA8IHMgKiDOuykpIHtcbiAgICAgICAgICB2YXIgz4ZpID0gLWluZmxlY3Rpb25bMV0gKiBkM19kZWdyZWVzO1xuICAgICAgICAgIGlmICjPhmkgPCDPhjApIM+GMCA9IM+GaTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoz4YgPCDPhjApIM+GMCA9IM+GO1xuICAgICAgICAgIGlmICjPhiA+IM+GMSkgz4YxID0gz4Y7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFudGltZXJpZGlhbikge1xuICAgICAgICAgIGlmICjOuyA8IM67Xykge1xuICAgICAgICAgICAgaWYgKGFuZ2xlKM67MCwgzrspID4gYW5nbGUozrswLCDOuzEpKSDOuzEgPSDOuztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGFuZ2xlKM67LCDOuzEpID4gYW5nbGUozrswLCDOuzEpKSDOuzAgPSDOuztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKM67MSA+PSDOuzApIHtcbiAgICAgICAgICAgIGlmICjOuyA8IM67MCkgzrswID0gzrs7XG4gICAgICAgICAgICBpZiAozrsgPiDOuzEpIM67MSA9IM67O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAozrsgPiDOu18pIHtcbiAgICAgICAgICAgICAgaWYgKGFuZ2xlKM67MCwgzrspID4gYW5nbGUozrswLCDOuzEpKSDOuzEgPSDOuztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChhbmdsZSjOuywgzrsxKSA+IGFuZ2xlKM67MCwgzrsxKSkgzrswID0gzrs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwb2ludCjOuywgz4YpO1xuICAgICAgfVxuICAgICAgcDAgPSBwLCDOu18gPSDOuztcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZVN0YXJ0KCkge1xuICAgICAgYm91bmQucG9pbnQgPSBsaW5lUG9pbnQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGxpbmVFbmQoKSB7XG4gICAgICByYW5nZVswXSA9IM67MCwgcmFuZ2VbMV0gPSDOuzE7XG4gICAgICBib3VuZC5wb2ludCA9IHBvaW50O1xuICAgICAgcDAgPSBudWxsO1xuICAgIH1cbiAgICBmdW5jdGlvbiByaW5nUG9pbnQozrssIM+GKSB7XG4gICAgICBpZiAocDApIHtcbiAgICAgICAgdmFyIGTOuyA9IM67IC0gzrtfO1xuICAgICAgICBkzrtTdW0gKz0gYWJzKGTOuykgPiAxODAgPyBkzrsgKyAoZM67ID4gMCA/IDM2MCA6IC0zNjApIDogZM67O1xuICAgICAgfSBlbHNlIM67X18gPSDOuywgz4ZfXyA9IM+GO1xuICAgICAgZDNfZ2VvX2FyZWEucG9pbnQozrssIM+GKTtcbiAgICAgIGxpbmVQb2ludCjOuywgz4YpO1xuICAgIH1cbiAgICBmdW5jdGlvbiByaW5nU3RhcnQoKSB7XG4gICAgICBkM19nZW9fYXJlYS5saW5lU3RhcnQoKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmluZ0VuZCgpIHtcbiAgICAgIHJpbmdQb2ludCjOu19fLCDPhl9fKTtcbiAgICAgIGQzX2dlb19hcmVhLmxpbmVFbmQoKTtcbiAgICAgIGlmIChhYnMoZM67U3VtKSA+IM61KSDOuzAgPSAtKM67MSA9IDE4MCk7XG4gICAgICByYW5nZVswXSA9IM67MCwgcmFuZ2VbMV0gPSDOuzE7XG4gICAgICBwMCA9IG51bGw7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFuZ2xlKM67MCwgzrsxKSB7XG4gICAgICByZXR1cm4gKM67MSAtPSDOuzApIDwgMCA/IM67MSArIDM2MCA6IM67MTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY29tcGFyZVJhbmdlcyhhLCBiKSB7XG4gICAgICByZXR1cm4gYVswXSAtIGJbMF07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHdpdGhpblJhbmdlKHgsIHJhbmdlKSB7XG4gICAgICByZXR1cm4gcmFuZ2VbMF0gPD0gcmFuZ2VbMV0gPyByYW5nZVswXSA8PSB4ICYmIHggPD0gcmFuZ2VbMV0gOiB4IDwgcmFuZ2VbMF0gfHwgcmFuZ2VbMV0gPCB4O1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb24oZmVhdHVyZSkge1xuICAgICAgz4YxID0gzrsxID0gLSjOuzAgPSDPhjAgPSBJbmZpbml0eSk7XG4gICAgICByYW5nZXMgPSBbXTtcbiAgICAgIGQzLmdlby5zdHJlYW0oZmVhdHVyZSwgYm91bmQpO1xuICAgICAgdmFyIG4gPSByYW5nZXMubGVuZ3RoO1xuICAgICAgaWYgKG4pIHtcbiAgICAgICAgcmFuZ2VzLnNvcnQoY29tcGFyZVJhbmdlcyk7XG4gICAgICAgIGZvciAodmFyIGkgPSAxLCBhID0gcmFuZ2VzWzBdLCBiLCBtZXJnZWQgPSBbIGEgXTsgaSA8IG47ICsraSkge1xuICAgICAgICAgIGIgPSByYW5nZXNbaV07XG4gICAgICAgICAgaWYgKHdpdGhpblJhbmdlKGJbMF0sIGEpIHx8IHdpdGhpblJhbmdlKGJbMV0sIGEpKSB7XG4gICAgICAgICAgICBpZiAoYW5nbGUoYVswXSwgYlsxXSkgPiBhbmdsZShhWzBdLCBhWzFdKSkgYVsxXSA9IGJbMV07XG4gICAgICAgICAgICBpZiAoYW5nbGUoYlswXSwgYVsxXSkgPiBhbmdsZShhWzBdLCBhWzFdKSkgYVswXSA9IGJbMF07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1lcmdlZC5wdXNoKGEgPSBiKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJlc3QgPSAtSW5maW5pdHksIGTOuztcbiAgICAgICAgZm9yICh2YXIgbiA9IG1lcmdlZC5sZW5ndGggLSAxLCBpID0gMCwgYSA9IG1lcmdlZFtuXSwgYjsgaSA8PSBuOyBhID0gYiwgKytpKSB7XG4gICAgICAgICAgYiA9IG1lcmdlZFtpXTtcbiAgICAgICAgICBpZiAoKGTOuyA9IGFuZ2xlKGFbMV0sIGJbMF0pKSA+IGJlc3QpIGJlc3QgPSBkzrssIM67MCA9IGJbMF0sIM67MSA9IGFbMV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJhbmdlcyA9IHJhbmdlID0gbnVsbDtcbiAgICAgIHJldHVybiDOuzAgPT09IEluZmluaXR5IHx8IM+GMCA9PT0gSW5maW5pdHkgPyBbIFsgTmFOLCBOYU4gXSwgWyBOYU4sIE5hTiBdIF0gOiBbIFsgzrswLCDPhjAgXSwgWyDOuzEsIM+GMSBdIF07XG4gICAgfTtcbiAgfSgpO1xuICBkMy5nZW8uY2VudHJvaWQgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBkM19nZW9fY2VudHJvaWRXMCA9IGQzX2dlb19jZW50cm9pZFcxID0gZDNfZ2VvX2NlbnRyb2lkWDAgPSBkM19nZW9fY2VudHJvaWRZMCA9IGQzX2dlb19jZW50cm9pZFowID0gZDNfZ2VvX2NlbnRyb2lkWDEgPSBkM19nZW9fY2VudHJvaWRZMSA9IGQzX2dlb19jZW50cm9pZFoxID0gZDNfZ2VvX2NlbnRyb2lkWDIgPSBkM19nZW9fY2VudHJvaWRZMiA9IGQzX2dlb19jZW50cm9pZFoyID0gMDtcbiAgICBkMy5nZW8uc3RyZWFtKG9iamVjdCwgZDNfZ2VvX2NlbnRyb2lkKTtcbiAgICB2YXIgeCA9IGQzX2dlb19jZW50cm9pZFgyLCB5ID0gZDNfZ2VvX2NlbnRyb2lkWTIsIHogPSBkM19nZW9fY2VudHJvaWRaMiwgbSA9IHggKiB4ICsgeSAqIHkgKyB6ICogejtcbiAgICBpZiAobSA8IM61Mikge1xuICAgICAgeCA9IGQzX2dlb19jZW50cm9pZFgxLCB5ID0gZDNfZ2VvX2NlbnRyb2lkWTEsIHogPSBkM19nZW9fY2VudHJvaWRaMTtcbiAgICAgIGlmIChkM19nZW9fY2VudHJvaWRXMSA8IM61KSB4ID0gZDNfZ2VvX2NlbnRyb2lkWDAsIHkgPSBkM19nZW9fY2VudHJvaWRZMCwgeiA9IGQzX2dlb19jZW50cm9pZFowO1xuICAgICAgbSA9IHggKiB4ICsgeSAqIHkgKyB6ICogejtcbiAgICAgIGlmIChtIDwgzrUyKSByZXR1cm4gWyBOYU4sIE5hTiBdO1xuICAgIH1cbiAgICByZXR1cm4gWyBNYXRoLmF0YW4yKHksIHgpICogZDNfZGVncmVlcywgZDNfYXNpbih6IC8gTWF0aC5zcXJ0KG0pKSAqIGQzX2RlZ3JlZXMgXTtcbiAgfTtcbiAgdmFyIGQzX2dlb19jZW50cm9pZFcwLCBkM19nZW9fY2VudHJvaWRXMSwgZDNfZ2VvX2NlbnRyb2lkWDAsIGQzX2dlb19jZW50cm9pZFkwLCBkM19nZW9fY2VudHJvaWRaMCwgZDNfZ2VvX2NlbnRyb2lkWDEsIGQzX2dlb19jZW50cm9pZFkxLCBkM19nZW9fY2VudHJvaWRaMSwgZDNfZ2VvX2NlbnRyb2lkWDIsIGQzX2dlb19jZW50cm9pZFkyLCBkM19nZW9fY2VudHJvaWRaMjtcbiAgdmFyIGQzX2dlb19jZW50cm9pZCA9IHtcbiAgICBzcGhlcmU6IGQzX25vb3AsXG4gICAgcG9pbnQ6IGQzX2dlb19jZW50cm9pZFBvaW50LFxuICAgIGxpbmVTdGFydDogZDNfZ2VvX2NlbnRyb2lkTGluZVN0YXJ0LFxuICAgIGxpbmVFbmQ6IGQzX2dlb19jZW50cm9pZExpbmVFbmQsXG4gICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX2dlb19jZW50cm9pZC5saW5lU3RhcnQgPSBkM19nZW9fY2VudHJvaWRSaW5nU3RhcnQ7XG4gICAgfSxcbiAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX2dlb19jZW50cm9pZC5saW5lU3RhcnQgPSBkM19nZW9fY2VudHJvaWRMaW5lU3RhcnQ7XG4gICAgfVxuICB9O1xuICBmdW5jdGlvbiBkM19nZW9fY2VudHJvaWRQb2ludCjOuywgz4YpIHtcbiAgICDOuyAqPSBkM19yYWRpYW5zO1xuICAgIHZhciBjb3PPhiA9IE1hdGguY29zKM+GICo9IGQzX3JhZGlhbnMpO1xuICAgIGQzX2dlb19jZW50cm9pZFBvaW50WFlaKGNvc8+GICogTWF0aC5jb3MozrspLCBjb3PPhiAqIE1hdGguc2luKM67KSwgTWF0aC5zaW4oz4YpKTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2VudHJvaWRQb2ludFhZWih4LCB5LCB6KSB7XG4gICAgKytkM19nZW9fY2VudHJvaWRXMDtcbiAgICBkM19nZW9fY2VudHJvaWRYMCArPSAoeCAtIGQzX2dlb19jZW50cm9pZFgwKSAvIGQzX2dlb19jZW50cm9pZFcwO1xuICAgIGQzX2dlb19jZW50cm9pZFkwICs9ICh5IC0gZDNfZ2VvX2NlbnRyb2lkWTApIC8gZDNfZ2VvX2NlbnRyb2lkVzA7XG4gICAgZDNfZ2VvX2NlbnRyb2lkWjAgKz0gKHogLSBkM19nZW9fY2VudHJvaWRaMCkgLyBkM19nZW9fY2VudHJvaWRXMDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2VudHJvaWRMaW5lU3RhcnQoKSB7XG4gICAgdmFyIHgwLCB5MCwgejA7XG4gICAgZDNfZ2VvX2NlbnRyb2lkLnBvaW50ID0gZnVuY3Rpb24ozrssIM+GKSB7XG4gICAgICDOuyAqPSBkM19yYWRpYW5zO1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YgKj0gZDNfcmFkaWFucyk7XG4gICAgICB4MCA9IGNvc8+GICogTWF0aC5jb3MozrspO1xuICAgICAgeTAgPSBjb3PPhiAqIE1hdGguc2luKM67KTtcbiAgICAgIHowID0gTWF0aC5zaW4oz4YpO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkLnBvaW50ID0gbmV4dFBvaW50O1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkUG9pbnRYWVooeDAsIHkwLCB6MCk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBuZXh0UG9pbnQozrssIM+GKSB7XG4gICAgICDOuyAqPSBkM19yYWRpYW5zO1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YgKj0gZDNfcmFkaWFucyksIHggPSBjb3PPhiAqIE1hdGguY29zKM67KSwgeSA9IGNvc8+GICogTWF0aC5zaW4ozrspLCB6ID0gTWF0aC5zaW4oz4YpLCB3ID0gTWF0aC5hdGFuMihNYXRoLnNxcnQoKHcgPSB5MCAqIHogLSB6MCAqIHkpICogdyArICh3ID0gejAgKiB4IC0geDAgKiB6KSAqIHcgKyAodyA9IHgwICogeSAtIHkwICogeCkgKiB3KSwgeDAgKiB4ICsgeTAgKiB5ICsgejAgKiB6KTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFcxICs9IHc7XG4gICAgICBkM19nZW9fY2VudHJvaWRYMSArPSB3ICogKHgwICsgKHgwID0geCkpO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWTEgKz0gdyAqICh5MCArICh5MCA9IHkpKTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoxICs9IHcgKiAoejAgKyAoejAgPSB6KSk7XG4gICAgICBkM19nZW9fY2VudHJvaWRQb2ludFhZWih4MCwgeTAsIHowKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NlbnRyb2lkTGluZUVuZCgpIHtcbiAgICBkM19nZW9fY2VudHJvaWQucG9pbnQgPSBkM19nZW9fY2VudHJvaWRQb2ludDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2VudHJvaWRSaW5nU3RhcnQoKSB7XG4gICAgdmFyIM67MDAsIM+GMDAsIHgwLCB5MCwgejA7XG4gICAgZDNfZ2VvX2NlbnRyb2lkLnBvaW50ID0gZnVuY3Rpb24ozrssIM+GKSB7XG4gICAgICDOuzAwID0gzrssIM+GMDAgPSDPhjtcbiAgICAgIGQzX2dlb19jZW50cm9pZC5wb2ludCA9IG5leHRQb2ludDtcbiAgICAgIM67ICo9IGQzX3JhZGlhbnM7XG4gICAgICB2YXIgY29zz4YgPSBNYXRoLmNvcyjPhiAqPSBkM19yYWRpYW5zKTtcbiAgICAgIHgwID0gY29zz4YgKiBNYXRoLmNvcyjOuyk7XG4gICAgICB5MCA9IGNvc8+GICogTWF0aC5zaW4ozrspO1xuICAgICAgejAgPSBNYXRoLnNpbijPhik7XG4gICAgICBkM19nZW9fY2VudHJvaWRQb2ludFhZWih4MCwgeTAsIHowKTtcbiAgICB9O1xuICAgIGQzX2dlb19jZW50cm9pZC5saW5lRW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICBuZXh0UG9pbnQozrswMCwgz4YwMCk7XG4gICAgICBkM19nZW9fY2VudHJvaWQubGluZUVuZCA9IGQzX2dlb19jZW50cm9pZExpbmVFbmQ7XG4gICAgICBkM19nZW9fY2VudHJvaWQucG9pbnQgPSBkM19nZW9fY2VudHJvaWRQb2ludDtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIG5leHRQb2ludCjOuywgz4YpIHtcbiAgICAgIM67ICo9IGQzX3JhZGlhbnM7XG4gICAgICB2YXIgY29zz4YgPSBNYXRoLmNvcyjPhiAqPSBkM19yYWRpYW5zKSwgeCA9IGNvc8+GICogTWF0aC5jb3MozrspLCB5ID0gY29zz4YgKiBNYXRoLnNpbijOuyksIHogPSBNYXRoLnNpbijPhiksIGN4ID0geTAgKiB6IC0gejAgKiB5LCBjeSA9IHowICogeCAtIHgwICogeiwgY3ogPSB4MCAqIHkgLSB5MCAqIHgsIG0gPSBNYXRoLnNxcnQoY3ggKiBjeCArIGN5ICogY3kgKyBjeiAqIGN6KSwgdSA9IHgwICogeCArIHkwICogeSArIHowICogeiwgdiA9IG0gJiYgLWQzX2Fjb3ModSkgLyBtLCB3ID0gTWF0aC5hdGFuMihtLCB1KTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFgyICs9IHYgKiBjeDtcbiAgICAgIGQzX2dlb19jZW50cm9pZFkyICs9IHYgKiBjeTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoyICs9IHYgKiBjejtcbiAgICAgIGQzX2dlb19jZW50cm9pZFcxICs9IHc7XG4gICAgICBkM19nZW9fY2VudHJvaWRYMSArPSB3ICogKHgwICsgKHgwID0geCkpO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWTEgKz0gdyAqICh5MCArICh5MCA9IHkpKTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoxICs9IHcgKiAoejAgKyAoejAgPSB6KSk7XG4gICAgICBkM19nZW9fY2VudHJvaWRQb2ludFhZWih4MCwgeTAsIHowKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NvbXBvc2UoYSwgYikge1xuICAgIGZ1bmN0aW9uIGNvbXBvc2UoeCwgeSkge1xuICAgICAgcmV0dXJuIHggPSBhKHgsIHkpLCBiKHhbMF0sIHhbMV0pO1xuICAgIH1cbiAgICBpZiAoYS5pbnZlcnQgJiYgYi5pbnZlcnQpIGNvbXBvc2UuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgICAgcmV0dXJuIHggPSBiLmludmVydCh4LCB5KSwgeCAmJiBhLmludmVydCh4WzBdLCB4WzFdKTtcbiAgICB9O1xuICAgIHJldHVybiBjb21wb3NlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RydWUoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBQb2x5Z29uKHNlZ21lbnRzLCBjb21wYXJlLCBjbGlwU3RhcnRJbnNpZGUsIGludGVycG9sYXRlLCBsaXN0ZW5lcikge1xuICAgIHZhciBzdWJqZWN0ID0gW10sIGNsaXAgPSBbXTtcbiAgICBzZWdtZW50cy5mb3JFYWNoKGZ1bmN0aW9uKHNlZ21lbnQpIHtcbiAgICAgIGlmICgobiA9IHNlZ21lbnQubGVuZ3RoIC0gMSkgPD0gMCkgcmV0dXJuO1xuICAgICAgdmFyIG4sIHAwID0gc2VnbWVudFswXSwgcDEgPSBzZWdtZW50W25dO1xuICAgICAgaWYgKGQzX2dlb19zcGhlcmljYWxFcXVhbChwMCwgcDEpKSB7XG4gICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkgbGlzdGVuZXIucG9pbnQoKHAwID0gc2VnbWVudFtpXSlbMF0sIHAwWzFdKTtcbiAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgYSA9IG5ldyBkM19nZW9fY2xpcFBvbHlnb25JbnRlcnNlY3Rpb24ocDAsIHNlZ21lbnQsIG51bGwsIHRydWUpLCBiID0gbmV3IGQzX2dlb19jbGlwUG9seWdvbkludGVyc2VjdGlvbihwMCwgbnVsbCwgYSwgZmFsc2UpO1xuICAgICAgYS5vID0gYjtcbiAgICAgIHN1YmplY3QucHVzaChhKTtcbiAgICAgIGNsaXAucHVzaChiKTtcbiAgICAgIGEgPSBuZXcgZDNfZ2VvX2NsaXBQb2x5Z29uSW50ZXJzZWN0aW9uKHAxLCBzZWdtZW50LCBudWxsLCBmYWxzZSk7XG4gICAgICBiID0gbmV3IGQzX2dlb19jbGlwUG9seWdvbkludGVyc2VjdGlvbihwMSwgbnVsbCwgYSwgdHJ1ZSk7XG4gICAgICBhLm8gPSBiO1xuICAgICAgc3ViamVjdC5wdXNoKGEpO1xuICAgICAgY2xpcC5wdXNoKGIpO1xuICAgIH0pO1xuICAgIGNsaXAuc29ydChjb21wYXJlKTtcbiAgICBkM19nZW9fY2xpcFBvbHlnb25MaW5rQ2lyY3VsYXIoc3ViamVjdCk7XG4gICAgZDNfZ2VvX2NsaXBQb2x5Z29uTGlua0NpcmN1bGFyKGNsaXApO1xuICAgIGlmICghc3ViamVjdC5sZW5ndGgpIHJldHVybjtcbiAgICBmb3IgKHZhciBpID0gMCwgZW50cnkgPSBjbGlwU3RhcnRJbnNpZGUsIG4gPSBjbGlwLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgY2xpcFtpXS5lID0gZW50cnkgPSAhZW50cnk7XG4gICAgfVxuICAgIHZhciBzdGFydCA9IHN1YmplY3RbMF0sIHBvaW50cywgcG9pbnQ7XG4gICAgd2hpbGUgKDEpIHtcbiAgICAgIHZhciBjdXJyZW50ID0gc3RhcnQsIGlzU3ViamVjdCA9IHRydWU7XG4gICAgICB3aGlsZSAoY3VycmVudC52KSBpZiAoKGN1cnJlbnQgPSBjdXJyZW50Lm4pID09PSBzdGFydCkgcmV0dXJuO1xuICAgICAgcG9pbnRzID0gY3VycmVudC56O1xuICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICBkbyB7XG4gICAgICAgIGN1cnJlbnQudiA9IGN1cnJlbnQuby52ID0gdHJ1ZTtcbiAgICAgICAgaWYgKGN1cnJlbnQuZSkge1xuICAgICAgICAgIGlmIChpc1N1YmplY3QpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gcG9pbnRzLmxlbmd0aDsgaSA8IG47ICsraSkgbGlzdGVuZXIucG9pbnQoKHBvaW50ID0gcG9pbnRzW2ldKVswXSwgcG9pbnRbMV0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpbnRlcnBvbGF0ZShjdXJyZW50LngsIGN1cnJlbnQubi54LCAxLCBsaXN0ZW5lcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50Lm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGlzU3ViamVjdCkge1xuICAgICAgICAgICAgcG9pbnRzID0gY3VycmVudC5wLno7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gcG9pbnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSBsaXN0ZW5lci5wb2ludCgocG9pbnQgPSBwb2ludHNbaV0pWzBdLCBwb2ludFsxXSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGludGVycG9sYXRlKGN1cnJlbnQueCwgY3VycmVudC5wLngsIC0xLCBsaXN0ZW5lcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50LnA7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudCA9IGN1cnJlbnQubztcbiAgICAgICAgcG9pbnRzID0gY3VycmVudC56O1xuICAgICAgICBpc1N1YmplY3QgPSAhaXNTdWJqZWN0O1xuICAgICAgfSB3aGlsZSAoIWN1cnJlbnQudik7XG4gICAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwUG9seWdvbkxpbmtDaXJjdWxhcihhcnJheSkge1xuICAgIGlmICghKG4gPSBhcnJheS5sZW5ndGgpKSByZXR1cm47XG4gICAgdmFyIG4sIGkgPSAwLCBhID0gYXJyYXlbMF0sIGI7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGEubiA9IGIgPSBhcnJheVtpXTtcbiAgICAgIGIucCA9IGE7XG4gICAgICBhID0gYjtcbiAgICB9XG4gICAgYS5uID0gYiA9IGFycmF5WzBdO1xuICAgIGIucCA9IGE7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBQb2x5Z29uSW50ZXJzZWN0aW9uKHBvaW50LCBwb2ludHMsIG90aGVyLCBlbnRyeSkge1xuICAgIHRoaXMueCA9IHBvaW50O1xuICAgIHRoaXMueiA9IHBvaW50cztcbiAgICB0aGlzLm8gPSBvdGhlcjtcbiAgICB0aGlzLmUgPSBlbnRyeTtcbiAgICB0aGlzLnYgPSBmYWxzZTtcbiAgICB0aGlzLm4gPSB0aGlzLnAgPSBudWxsO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwKHBvaW50VmlzaWJsZSwgY2xpcExpbmUsIGludGVycG9sYXRlLCBjbGlwU3RhcnQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ocm90YXRlLCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGxpbmUgPSBjbGlwTGluZShsaXN0ZW5lciksIHJvdGF0ZWRDbGlwU3RhcnQgPSByb3RhdGUuaW52ZXJ0KGNsaXBTdGFydFswXSwgY2xpcFN0YXJ0WzFdKTtcbiAgICAgIHZhciBjbGlwID0ge1xuICAgICAgICBwb2ludDogcG9pbnQsXG4gICAgICAgIGxpbmVTdGFydDogbGluZVN0YXJ0LFxuICAgICAgICBsaW5lRW5kOiBsaW5lRW5kLFxuICAgICAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGNsaXAucG9pbnQgPSBwb2ludFJpbmc7XG4gICAgICAgICAgY2xpcC5saW5lU3RhcnQgPSByaW5nU3RhcnQ7XG4gICAgICAgICAgY2xpcC5saW5lRW5kID0gcmluZ0VuZDtcbiAgICAgICAgICBzZWdtZW50cyA9IFtdO1xuICAgICAgICAgIHBvbHlnb24gPSBbXTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9seWdvbkVuZDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgY2xpcC5wb2ludCA9IHBvaW50O1xuICAgICAgICAgIGNsaXAubGluZVN0YXJ0ID0gbGluZVN0YXJ0O1xuICAgICAgICAgIGNsaXAubGluZUVuZCA9IGxpbmVFbmQ7XG4gICAgICAgICAgc2VnbWVudHMgPSBkMy5tZXJnZShzZWdtZW50cyk7XG4gICAgICAgICAgdmFyIGNsaXBTdGFydEluc2lkZSA9IGQzX2dlb19wb2ludEluUG9seWdvbihyb3RhdGVkQ2xpcFN0YXJ0LCBwb2x5Z29uKTtcbiAgICAgICAgICBpZiAoc2VnbWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIXBvbHlnb25TdGFydGVkKSBsaXN0ZW5lci5wb2x5Z29uU3RhcnQoKSwgcG9seWdvblN0YXJ0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgZDNfZ2VvX2NsaXBQb2x5Z29uKHNlZ21lbnRzLCBkM19nZW9fY2xpcFNvcnQsIGNsaXBTdGFydEluc2lkZSwgaW50ZXJwb2xhdGUsIGxpc3RlbmVyKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGNsaXBTdGFydEluc2lkZSkge1xuICAgICAgICAgICAgaWYgKCFwb2x5Z29uU3RhcnRlZCkgbGlzdGVuZXIucG9seWdvblN0YXJ0KCksIHBvbHlnb25TdGFydGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgICAgaW50ZXJwb2xhdGUobnVsbCwgbnVsbCwgMSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocG9seWdvblN0YXJ0ZWQpIGxpc3RlbmVyLnBvbHlnb25FbmQoKSwgcG9seWdvblN0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgICBzZWdtZW50cyA9IHBvbHlnb24gPSBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxpc3RlbmVyLnBvbHlnb25TdGFydCgpO1xuICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgIGludGVycG9sYXRlKG51bGwsIG51bGwsIDEsIGxpc3RlbmVyKTtcbiAgICAgICAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgICAgICAgbGlzdGVuZXIucG9seWdvbkVuZCgpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgZnVuY3Rpb24gcG9pbnQozrssIM+GKSB7XG4gICAgICAgIHZhciBwb2ludCA9IHJvdGF0ZSjOuywgz4YpO1xuICAgICAgICBpZiAocG9pbnRWaXNpYmxlKM67ID0gcG9pbnRbMF0sIM+GID0gcG9pbnRbMV0pKSBsaXN0ZW5lci5wb2ludCjOuywgz4YpO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gcG9pbnRMaW5lKM67LCDPhikge1xuICAgICAgICB2YXIgcG9pbnQgPSByb3RhdGUozrssIM+GKTtcbiAgICAgICAgbGluZS5wb2ludChwb2ludFswXSwgcG9pbnRbMV0pO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gbGluZVN0YXJ0KCkge1xuICAgICAgICBjbGlwLnBvaW50ID0gcG9pbnRMaW5lO1xuICAgICAgICBsaW5lLmxpbmVTdGFydCgpO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gbGluZUVuZCgpIHtcbiAgICAgICAgY2xpcC5wb2ludCA9IHBvaW50O1xuICAgICAgICBsaW5lLmxpbmVFbmQoKTtcbiAgICAgIH1cbiAgICAgIHZhciBzZWdtZW50cztcbiAgICAgIHZhciBidWZmZXIgPSBkM19nZW9fY2xpcEJ1ZmZlckxpc3RlbmVyKCksIHJpbmdMaXN0ZW5lciA9IGNsaXBMaW5lKGJ1ZmZlciksIHBvbHlnb25TdGFydGVkID0gZmFsc2UsIHBvbHlnb24sIHJpbmc7XG4gICAgICBmdW5jdGlvbiBwb2ludFJpbmcozrssIM+GKSB7XG4gICAgICAgIHJpbmcucHVzaChbIM67LCDPhiBdKTtcbiAgICAgICAgdmFyIHBvaW50ID0gcm90YXRlKM67LCDPhik7XG4gICAgICAgIHJpbmdMaXN0ZW5lci5wb2ludChwb2ludFswXSwgcG9pbnRbMV0pO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gcmluZ1N0YXJ0KCkge1xuICAgICAgICByaW5nTGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgIHJpbmcgPSBbXTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJpbmdFbmQoKSB7XG4gICAgICAgIHBvaW50UmluZyhyaW5nWzBdWzBdLCByaW5nWzBdWzFdKTtcbiAgICAgICAgcmluZ0xpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgICAgdmFyIGNsZWFuID0gcmluZ0xpc3RlbmVyLmNsZWFuKCksIHJpbmdTZWdtZW50cyA9IGJ1ZmZlci5idWZmZXIoKSwgc2VnbWVudCwgbiA9IHJpbmdTZWdtZW50cy5sZW5ndGg7XG4gICAgICAgIHJpbmcucG9wKCk7XG4gICAgICAgIHBvbHlnb24ucHVzaChyaW5nKTtcbiAgICAgICAgcmluZyA9IG51bGw7XG4gICAgICAgIGlmICghbikgcmV0dXJuO1xuICAgICAgICBpZiAoY2xlYW4gJiAxKSB7XG4gICAgICAgICAgc2VnbWVudCA9IHJpbmdTZWdtZW50c1swXTtcbiAgICAgICAgICB2YXIgbiA9IHNlZ21lbnQubGVuZ3RoIC0gMSwgaSA9IC0xLCBwb2ludDtcbiAgICAgICAgICBpZiAobiA+IDApIHtcbiAgICAgICAgICAgIGlmICghcG9seWdvblN0YXJ0ZWQpIGxpc3RlbmVyLnBvbHlnb25TdGFydCgpLCBwb2x5Z29uU3RhcnRlZCA9IHRydWU7XG4gICAgICAgICAgICBsaXN0ZW5lci5saW5lU3RhcnQoKTtcbiAgICAgICAgICAgIHdoaWxlICgrK2kgPCBuKSBsaXN0ZW5lci5wb2ludCgocG9pbnQgPSBzZWdtZW50W2ldKVswXSwgcG9pbnRbMV0pO1xuICAgICAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG4gPiAxICYmIGNsZWFuICYgMikgcmluZ1NlZ21lbnRzLnB1c2gocmluZ1NlZ21lbnRzLnBvcCgpLmNvbmNhdChyaW5nU2VnbWVudHMuc2hpZnQoKSkpO1xuICAgICAgICBzZWdtZW50cy5wdXNoKHJpbmdTZWdtZW50cy5maWx0ZXIoZDNfZ2VvX2NsaXBTZWdtZW50TGVuZ3RoMSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNsaXA7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2xpcFNlZ21lbnRMZW5ndGgxKHNlZ21lbnQpIHtcbiAgICByZXR1cm4gc2VnbWVudC5sZW5ndGggPiAxO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwQnVmZmVyTGlzdGVuZXIoKSB7XG4gICAgdmFyIGxpbmVzID0gW10sIGxpbmU7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGxpbmVzLnB1c2gobGluZSA9IFtdKTtcbiAgICAgIH0sXG4gICAgICBwb2ludDogZnVuY3Rpb24ozrssIM+GKSB7XG4gICAgICAgIGxpbmUucHVzaChbIM67LCDPhiBdKTtcbiAgICAgIH0sXG4gICAgICBsaW5lRW5kOiBkM19ub29wLFxuICAgICAgYnVmZmVyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGJ1ZmZlciA9IGxpbmVzO1xuICAgICAgICBsaW5lcyA9IFtdO1xuICAgICAgICBsaW5lID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIGJ1ZmZlcjtcbiAgICAgIH0sXG4gICAgICByZWpvaW46IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAobGluZXMubGVuZ3RoID4gMSkgbGluZXMucHVzaChsaW5lcy5wb3AoKS5jb25jYXQobGluZXMuc2hpZnQoKSkpO1xuICAgICAgfVxuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBTb3J0KGEsIGIpIHtcbiAgICByZXR1cm4gKChhID0gYS54KVswXSA8IDAgPyBhWzFdIC0gaGFsZs+AIC0gzrUgOiBoYWxmz4AgLSBhWzFdKSAtICgoYiA9IGIueClbMF0gPCAwID8gYlsxXSAtIGhhbGbPgCAtIM61IDogaGFsZs+AIC0gYlsxXSk7XG4gIH1cbiAgdmFyIGQzX2dlb19jbGlwQW50aW1lcmlkaWFuID0gZDNfZ2VvX2NsaXAoZDNfdHJ1ZSwgZDNfZ2VvX2NsaXBBbnRpbWVyaWRpYW5MaW5lLCBkM19nZW9fY2xpcEFudGltZXJpZGlhbkludGVycG9sYXRlLCBbIC3PgCwgLc+AIC8gMiBdKTtcbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBBbnRpbWVyaWRpYW5MaW5lKGxpc3RlbmVyKSB7XG4gICAgdmFyIM67MCA9IE5hTiwgz4YwID0gTmFOLCBzzrswID0gTmFOLCBjbGVhbjtcbiAgICByZXR1cm4ge1xuICAgICAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgIGNsZWFuID0gMTtcbiAgICAgIH0sXG4gICAgICBwb2ludDogZnVuY3Rpb24ozrsxLCDPhjEpIHtcbiAgICAgICAgdmFyIHPOuzEgPSDOuzEgPiAwID8gz4AgOiAtz4AsIGTOuyA9IGFicyjOuzEgLSDOuzApO1xuICAgICAgICBpZiAoYWJzKGTOuyAtIM+AKSA8IM61KSB7XG4gICAgICAgICAgbGlzdGVuZXIucG9pbnQozrswLCDPhjAgPSAoz4YwICsgz4YxKSAvIDIgPiAwID8gaGFsZs+AIDogLWhhbGbPgCk7XG4gICAgICAgICAgbGlzdGVuZXIucG9pbnQoc867MCwgz4YwKTtcbiAgICAgICAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgICAgbGlzdGVuZXIucG9pbnQoc867MSwgz4YwKTtcbiAgICAgICAgICBsaXN0ZW5lci5wb2ludCjOuzEsIM+GMCk7XG4gICAgICAgICAgY2xlYW4gPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKHPOuzAgIT09IHPOuzEgJiYgZM67ID49IM+AKSB7XG4gICAgICAgICAgaWYgKGFicyjOuzAgLSBzzrswKSA8IM61KSDOuzAgLT0gc867MCAqIM61O1xuICAgICAgICAgIGlmIChhYnMozrsxIC0gc867MSkgPCDOtSkgzrsxIC09IHPOuzEgKiDOtTtcbiAgICAgICAgICDPhjAgPSBkM19nZW9fY2xpcEFudGltZXJpZGlhbkludGVyc2VjdCjOuzAsIM+GMCwgzrsxLCDPhjEpO1xuICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHPOuzAsIM+GMCk7XG4gICAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHPOuzEsIM+GMCk7XG4gICAgICAgICAgY2xlYW4gPSAwO1xuICAgICAgICB9XG4gICAgICAgIGxpc3RlbmVyLnBvaW50KM67MCA9IM67MSwgz4YwID0gz4YxKTtcbiAgICAgICAgc867MCA9IHPOuzE7XG4gICAgICB9LFxuICAgICAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGxpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgICAgzrswID0gz4YwID0gTmFOO1xuICAgICAgfSxcbiAgICAgIGNsZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIDIgLSBjbGVhbjtcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwQW50aW1lcmlkaWFuSW50ZXJzZWN0KM67MCwgz4YwLCDOuzEsIM+GMSkge1xuICAgIHZhciBjb3PPhjAsIGNvc8+GMSwgc2luzrswX867MSA9IE1hdGguc2luKM67MCAtIM67MSk7XG4gICAgcmV0dXJuIGFicyhzaW7OuzBfzrsxKSA+IM61ID8gTWF0aC5hdGFuKChNYXRoLnNpbijPhjApICogKGNvc8+GMSA9IE1hdGguY29zKM+GMSkpICogTWF0aC5zaW4ozrsxKSAtIE1hdGguc2luKM+GMSkgKiAoY29zz4YwID0gTWF0aC5jb3Moz4YwKSkgKiBNYXRoLnNpbijOuzApKSAvIChjb3PPhjAgKiBjb3PPhjEgKiBzaW7OuzBfzrsxKSkgOiAoz4YwICsgz4YxKSAvIDI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NsaXBBbnRpbWVyaWRpYW5JbnRlcnBvbGF0ZShmcm9tLCB0bywgZGlyZWN0aW9uLCBsaXN0ZW5lcikge1xuICAgIHZhciDPhjtcbiAgICBpZiAoZnJvbSA9PSBudWxsKSB7XG4gICAgICDPhiA9IGRpcmVjdGlvbiAqIGhhbGbPgDtcbiAgICAgIGxpc3RlbmVyLnBvaW50KC3PgCwgz4YpO1xuICAgICAgbGlzdGVuZXIucG9pbnQoMCwgz4YpO1xuICAgICAgbGlzdGVuZXIucG9pbnQoz4AsIM+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KM+ALCAwKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KM+ALCAtz4YpO1xuICAgICAgbGlzdGVuZXIucG9pbnQoMCwgLc+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KC3PgCwgLc+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KC3PgCwgMCk7XG4gICAgICBsaXN0ZW5lci5wb2ludCgtz4AsIM+GKTtcbiAgICB9IGVsc2UgaWYgKGFicyhmcm9tWzBdIC0gdG9bMF0pID4gzrUpIHtcbiAgICAgIHZhciBzID0gZnJvbVswXSA8IHRvWzBdID8gz4AgOiAtz4A7XG4gICAgICDPhiA9IGRpcmVjdGlvbiAqIHMgLyAyO1xuICAgICAgbGlzdGVuZXIucG9pbnQoLXMsIM+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KDAsIM+GKTtcbiAgICAgIGxpc3RlbmVyLnBvaW50KHMsIM+GKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGlzdGVuZXIucG9pbnQodG9bMF0sIHRvWzFdKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3BvaW50SW5Qb2x5Z29uKHBvaW50LCBwb2x5Z29uKSB7XG4gICAgdmFyIG1lcmlkaWFuID0gcG9pbnRbMF0sIHBhcmFsbGVsID0gcG9pbnRbMV0sIG1lcmlkaWFuTm9ybWFsID0gWyBNYXRoLnNpbihtZXJpZGlhbiksIC1NYXRoLmNvcyhtZXJpZGlhbiksIDAgXSwgcG9sYXJBbmdsZSA9IDAsIHdpbmRpbmcgPSAwO1xuICAgIGQzX2dlb19hcmVhUmluZ1N1bS5yZXNldCgpO1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gcG9seWdvbi5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgIHZhciByaW5nID0gcG9seWdvbltpXSwgbSA9IHJpbmcubGVuZ3RoO1xuICAgICAgaWYgKCFtKSBjb250aW51ZTtcbiAgICAgIHZhciBwb2ludDAgPSByaW5nWzBdLCDOuzAgPSBwb2ludDBbMF0sIM+GMCA9IHBvaW50MFsxXSAvIDIgKyDPgCAvIDQsIHNpbs+GMCA9IE1hdGguc2luKM+GMCksIGNvc8+GMCA9IE1hdGguY29zKM+GMCksIGogPSAxO1xuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKGogPT09IG0pIGogPSAwO1xuICAgICAgICBwb2ludCA9IHJpbmdbal07XG4gICAgICAgIHZhciDOuyA9IHBvaW50WzBdLCDPhiA9IHBvaW50WzFdIC8gMiArIM+AIC8gNCwgc2luz4YgPSBNYXRoLnNpbijPhiksIGNvc8+GID0gTWF0aC5jb3Moz4YpLCBkzrsgPSDOuyAtIM67MCwgc2TOuyA9IGTOuyA+PSAwID8gMSA6IC0xLCBhZM67ID0gc2TOuyAqIGTOuywgYW50aW1lcmlkaWFuID0gYWTOuyA+IM+ALCBrID0gc2luz4YwICogc2luz4Y7XG4gICAgICAgIGQzX2dlb19hcmVhUmluZ1N1bS5hZGQoTWF0aC5hdGFuMihrICogc2TOuyAqIE1hdGguc2luKGFkzrspLCBjb3PPhjAgKiBjb3PPhiArIGsgKiBNYXRoLmNvcyhhZM67KSkpO1xuICAgICAgICBwb2xhckFuZ2xlICs9IGFudGltZXJpZGlhbiA/IGTOuyArIHNkzrsgKiDPhCA6IGTOuztcbiAgICAgICAgaWYgKGFudGltZXJpZGlhbiBeIM67MCA+PSBtZXJpZGlhbiBeIM67ID49IG1lcmlkaWFuKSB7XG4gICAgICAgICAgdmFyIGFyYyA9IGQzX2dlb19jYXJ0ZXNpYW5Dcm9zcyhkM19nZW9fY2FydGVzaWFuKHBvaW50MCksIGQzX2dlb19jYXJ0ZXNpYW4ocG9pbnQpKTtcbiAgICAgICAgICBkM19nZW9fY2FydGVzaWFuTm9ybWFsaXplKGFyYyk7XG4gICAgICAgICAgdmFyIGludGVyc2VjdGlvbiA9IGQzX2dlb19jYXJ0ZXNpYW5Dcm9zcyhtZXJpZGlhbk5vcm1hbCwgYXJjKTtcbiAgICAgICAgICBkM19nZW9fY2FydGVzaWFuTm9ybWFsaXplKGludGVyc2VjdGlvbik7XG4gICAgICAgICAgdmFyIM+GYXJjID0gKGFudGltZXJpZGlhbiBeIGTOuyA+PSAwID8gLTEgOiAxKSAqIGQzX2FzaW4oaW50ZXJzZWN0aW9uWzJdKTtcbiAgICAgICAgICBpZiAocGFyYWxsZWwgPiDPhmFyYyB8fCBwYXJhbGxlbCA9PT0gz4ZhcmMgJiYgKGFyY1swXSB8fCBhcmNbMV0pKSB7XG4gICAgICAgICAgICB3aW5kaW5nICs9IGFudGltZXJpZGlhbiBeIGTOuyA+PSAwID8gMSA6IC0xO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWorKykgYnJlYWs7XG4gICAgICAgIM67MCA9IM67LCBzaW7PhjAgPSBzaW7PhiwgY29zz4YwID0gY29zz4YsIHBvaW50MCA9IHBvaW50O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gKHBvbGFyQW5nbGUgPCAtzrUgfHwgcG9sYXJBbmdsZSA8IM61ICYmIGQzX2dlb19hcmVhUmluZ1N1bSA8IC3OtSkgXiB3aW5kaW5nICYgMTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fY2xpcENpcmNsZShyYWRpdXMpIHtcbiAgICB2YXIgY3IgPSBNYXRoLmNvcyhyYWRpdXMpLCBzbWFsbFJhZGl1cyA9IGNyID4gMCwgbm90SGVtaXNwaGVyZSA9IGFicyhjcikgPiDOtSwgaW50ZXJwb2xhdGUgPSBkM19nZW9fY2lyY2xlSW50ZXJwb2xhdGUocmFkaXVzLCA2ICogZDNfcmFkaWFucyk7XG4gICAgcmV0dXJuIGQzX2dlb19jbGlwKHZpc2libGUsIGNsaXBMaW5lLCBpbnRlcnBvbGF0ZSwgc21hbGxSYWRpdXMgPyBbIDAsIC1yYWRpdXMgXSA6IFsgLc+ALCByYWRpdXMgLSDPgCBdKTtcbiAgICBmdW5jdGlvbiB2aXNpYmxlKM67LCDPhikge1xuICAgICAgcmV0dXJuIE1hdGguY29zKM67KSAqIE1hdGguY29zKM+GKSA+IGNyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjbGlwTGluZShsaXN0ZW5lcikge1xuICAgICAgdmFyIHBvaW50MCwgYzAsIHYwLCB2MDAsIGNsZWFuO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICB2MDAgPSB2MCA9IGZhbHNlO1xuICAgICAgICAgIGNsZWFuID0gMTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9pbnQ6IGZ1bmN0aW9uKM67LCDPhikge1xuICAgICAgICAgIHZhciBwb2ludDEgPSBbIM67LCDPhiBdLCBwb2ludDIsIHYgPSB2aXNpYmxlKM67LCDPhiksIGMgPSBzbWFsbFJhZGl1cyA/IHYgPyAwIDogY29kZSjOuywgz4YpIDogdiA/IGNvZGUozrsgKyAozrsgPCAwID8gz4AgOiAtz4ApLCDPhikgOiAwO1xuICAgICAgICAgIGlmICghcG9pbnQwICYmICh2MDAgPSB2MCA9IHYpKSBsaXN0ZW5lci5saW5lU3RhcnQoKTtcbiAgICAgICAgICBpZiAodiAhPT0gdjApIHtcbiAgICAgICAgICAgIHBvaW50MiA9IGludGVyc2VjdChwb2ludDAsIHBvaW50MSk7XG4gICAgICAgICAgICBpZiAoZDNfZ2VvX3NwaGVyaWNhbEVxdWFsKHBvaW50MCwgcG9pbnQyKSB8fCBkM19nZW9fc3BoZXJpY2FsRXF1YWwocG9pbnQxLCBwb2ludDIpKSB7XG4gICAgICAgICAgICAgIHBvaW50MVswXSArPSDOtTtcbiAgICAgICAgICAgICAgcG9pbnQxWzFdICs9IM61O1xuICAgICAgICAgICAgICB2ID0gdmlzaWJsZShwb2ludDFbMF0sIHBvaW50MVsxXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICh2ICE9PSB2MCkge1xuICAgICAgICAgICAgY2xlYW4gPSAwO1xuICAgICAgICAgICAgaWYgKHYpIHtcbiAgICAgICAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICAgIHBvaW50MiA9IGludGVyc2VjdChwb2ludDEsIHBvaW50MCk7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHBvaW50MlswXSwgcG9pbnQyWzFdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBvaW50MiA9IGludGVyc2VjdChwb2ludDAsIHBvaW50MSk7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHBvaW50MlswXSwgcG9pbnQyWzFdKTtcbiAgICAgICAgICAgICAgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcG9pbnQwID0gcG9pbnQyO1xuICAgICAgICAgIH0gZWxzZSBpZiAobm90SGVtaXNwaGVyZSAmJiBwb2ludDAgJiYgc21hbGxSYWRpdXMgXiB2KSB7XG4gICAgICAgICAgICB2YXIgdDtcbiAgICAgICAgICAgIGlmICghKGMgJiBjMCkgJiYgKHQgPSBpbnRlcnNlY3QocG9pbnQxLCBwb2ludDAsIHRydWUpKSkge1xuICAgICAgICAgICAgICBjbGVhbiA9IDA7XG4gICAgICAgICAgICAgIGlmIChzbWFsbFJhZGl1cykge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHRbMF1bMF0sIHRbMF1bMV0pO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHRbMV1bMF0sIHRbMV1bMV0pO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lci5wb2ludCh0WzFdWzBdLCB0WzFdWzFdKTtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXIucG9pbnQodFswXVswXSwgdFswXVsxXSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHYgJiYgKCFwb2ludDAgfHwgIWQzX2dlb19zcGhlcmljYWxFcXVhbChwb2ludDAsIHBvaW50MSkpKSB7XG4gICAgICAgICAgICBsaXN0ZW5lci5wb2ludChwb2ludDFbMF0sIHBvaW50MVsxXSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHBvaW50MCA9IHBvaW50MSwgdjAgPSB2LCBjMCA9IGM7XG4gICAgICAgIH0sXG4gICAgICAgIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmICh2MCkgbGlzdGVuZXIubGluZUVuZCgpO1xuICAgICAgICAgIHBvaW50MCA9IG51bGw7XG4gICAgICAgIH0sXG4gICAgICAgIGNsZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gY2xlYW4gfCAodjAwICYmIHYwKSA8PCAxO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBpbnRlcnNlY3QoYSwgYiwgdHdvKSB7XG4gICAgICB2YXIgcGEgPSBkM19nZW9fY2FydGVzaWFuKGEpLCBwYiA9IGQzX2dlb19jYXJ0ZXNpYW4oYik7XG4gICAgICB2YXIgbjEgPSBbIDEsIDAsIDAgXSwgbjIgPSBkM19nZW9fY2FydGVzaWFuQ3Jvc3MocGEsIHBiKSwgbjJuMiA9IGQzX2dlb19jYXJ0ZXNpYW5Eb3QobjIsIG4yKSwgbjFuMiA9IG4yWzBdLCBkZXRlcm1pbmFudCA9IG4ybjIgLSBuMW4yICogbjFuMjtcbiAgICAgIGlmICghZGV0ZXJtaW5hbnQpIHJldHVybiAhdHdvICYmIGE7XG4gICAgICB2YXIgYzEgPSBjciAqIG4ybjIgLyBkZXRlcm1pbmFudCwgYzIgPSAtY3IgKiBuMW4yIC8gZGV0ZXJtaW5hbnQsIG4xeG4yID0gZDNfZ2VvX2NhcnRlc2lhbkNyb3NzKG4xLCBuMiksIEEgPSBkM19nZW9fY2FydGVzaWFuU2NhbGUobjEsIGMxKSwgQiA9IGQzX2dlb19jYXJ0ZXNpYW5TY2FsZShuMiwgYzIpO1xuICAgICAgZDNfZ2VvX2NhcnRlc2lhbkFkZChBLCBCKTtcbiAgICAgIHZhciB1ID0gbjF4bjIsIHcgPSBkM19nZW9fY2FydGVzaWFuRG90KEEsIHUpLCB1dSA9IGQzX2dlb19jYXJ0ZXNpYW5Eb3QodSwgdSksIHQyID0gdyAqIHcgLSB1dSAqIChkM19nZW9fY2FydGVzaWFuRG90KEEsIEEpIC0gMSk7XG4gICAgICBpZiAodDIgPCAwKSByZXR1cm47XG4gICAgICB2YXIgdCA9IE1hdGguc3FydCh0MiksIHEgPSBkM19nZW9fY2FydGVzaWFuU2NhbGUodSwgKC13IC0gdCkgLyB1dSk7XG4gICAgICBkM19nZW9fY2FydGVzaWFuQWRkKHEsIEEpO1xuICAgICAgcSA9IGQzX2dlb19zcGhlcmljYWwocSk7XG4gICAgICBpZiAoIXR3bykgcmV0dXJuIHE7XG4gICAgICB2YXIgzrswID0gYVswXSwgzrsxID0gYlswXSwgz4YwID0gYVsxXSwgz4YxID0gYlsxXSwgejtcbiAgICAgIGlmICjOuzEgPCDOuzApIHogPSDOuzAsIM67MCA9IM67MSwgzrsxID0gejtcbiAgICAgIHZhciDOtM67ID0gzrsxIC0gzrswLCBwb2xhciA9IGFicyjOtM67IC0gz4ApIDwgzrUsIG1lcmlkaWFuID0gcG9sYXIgfHwgzrTOuyA8IM61O1xuICAgICAgaWYgKCFwb2xhciAmJiDPhjEgPCDPhjApIHogPSDPhjAsIM+GMCA9IM+GMSwgz4YxID0gejtcbiAgICAgIGlmIChtZXJpZGlhbiA/IHBvbGFyID8gz4YwICsgz4YxID4gMCBeIHFbMV0gPCAoYWJzKHFbMF0gLSDOuzApIDwgzrUgPyDPhjAgOiDPhjEpIDogz4YwIDw9IHFbMV0gJiYgcVsxXSA8PSDPhjEgOiDOtM67ID4gz4AgXiAozrswIDw9IHFbMF0gJiYgcVswXSA8PSDOuzEpKSB7XG4gICAgICAgIHZhciBxMSA9IGQzX2dlb19jYXJ0ZXNpYW5TY2FsZSh1LCAoLXcgKyB0KSAvIHV1KTtcbiAgICAgICAgZDNfZ2VvX2NhcnRlc2lhbkFkZChxMSwgQSk7XG4gICAgICAgIHJldHVybiBbIHEsIGQzX2dlb19zcGhlcmljYWwocTEpIF07XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNvZGUozrssIM+GKSB7XG4gICAgICB2YXIgciA9IHNtYWxsUmFkaXVzID8gcmFkaXVzIDogz4AgLSByYWRpdXMsIGNvZGUgPSAwO1xuICAgICAgaWYgKM67IDwgLXIpIGNvZGUgfD0gMTsgZWxzZSBpZiAozrsgPiByKSBjb2RlIHw9IDI7XG4gICAgICBpZiAoz4YgPCAtcikgY29kZSB8PSA0OyBlbHNlIGlmICjPhiA+IHIpIGNvZGUgfD0gODtcbiAgICAgIHJldHVybiBjb2RlO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX2NsaXBMaW5lKHgwLCB5MCwgeDEsIHkxKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgIHZhciBhID0gbGluZS5hLCBiID0gbGluZS5iLCBheCA9IGEueCwgYXkgPSBhLnksIGJ4ID0gYi54LCBieSA9IGIueSwgdDAgPSAwLCB0MSA9IDEsIGR4ID0gYnggLSBheCwgZHkgPSBieSAtIGF5LCByO1xuICAgICAgciA9IHgwIC0gYXg7XG4gICAgICBpZiAoIWR4ICYmIHIgPiAwKSByZXR1cm47XG4gICAgICByIC89IGR4O1xuICAgICAgaWYgKGR4IDwgMCkge1xuICAgICAgICBpZiAociA8IHQwKSByZXR1cm47XG4gICAgICAgIGlmIChyIDwgdDEpIHQxID0gcjtcbiAgICAgIH0gZWxzZSBpZiAoZHggPiAwKSB7XG4gICAgICAgIGlmIChyID4gdDEpIHJldHVybjtcbiAgICAgICAgaWYgKHIgPiB0MCkgdDAgPSByO1xuICAgICAgfVxuICAgICAgciA9IHgxIC0gYXg7XG4gICAgICBpZiAoIWR4ICYmIHIgPCAwKSByZXR1cm47XG4gICAgICByIC89IGR4O1xuICAgICAgaWYgKGR4IDwgMCkge1xuICAgICAgICBpZiAociA+IHQxKSByZXR1cm47XG4gICAgICAgIGlmIChyID4gdDApIHQwID0gcjtcbiAgICAgIH0gZWxzZSBpZiAoZHggPiAwKSB7XG4gICAgICAgIGlmIChyIDwgdDApIHJldHVybjtcbiAgICAgICAgaWYgKHIgPCB0MSkgdDEgPSByO1xuICAgICAgfVxuICAgICAgciA9IHkwIC0gYXk7XG4gICAgICBpZiAoIWR5ICYmIHIgPiAwKSByZXR1cm47XG4gICAgICByIC89IGR5O1xuICAgICAgaWYgKGR5IDwgMCkge1xuICAgICAgICBpZiAociA8IHQwKSByZXR1cm47XG4gICAgICAgIGlmIChyIDwgdDEpIHQxID0gcjtcbiAgICAgIH0gZWxzZSBpZiAoZHkgPiAwKSB7XG4gICAgICAgIGlmIChyID4gdDEpIHJldHVybjtcbiAgICAgICAgaWYgKHIgPiB0MCkgdDAgPSByO1xuICAgICAgfVxuICAgICAgciA9IHkxIC0gYXk7XG4gICAgICBpZiAoIWR5ICYmIHIgPCAwKSByZXR1cm47XG4gICAgICByIC89IGR5O1xuICAgICAgaWYgKGR5IDwgMCkge1xuICAgICAgICBpZiAociA+IHQxKSByZXR1cm47XG4gICAgICAgIGlmIChyID4gdDApIHQwID0gcjtcbiAgICAgIH0gZWxzZSBpZiAoZHkgPiAwKSB7XG4gICAgICAgIGlmIChyIDwgdDApIHJldHVybjtcbiAgICAgICAgaWYgKHIgPCB0MSkgdDEgPSByO1xuICAgICAgfVxuICAgICAgaWYgKHQwID4gMCkgbGluZS5hID0ge1xuICAgICAgICB4OiBheCArIHQwICogZHgsXG4gICAgICAgIHk6IGF5ICsgdDAgKiBkeVxuICAgICAgfTtcbiAgICAgIGlmICh0MSA8IDEpIGxpbmUuYiA9IHtcbiAgICAgICAgeDogYXggKyB0MSAqIGR4LFxuICAgICAgICB5OiBheSArIHQxICogZHlcbiAgICAgIH07XG4gICAgICByZXR1cm4gbGluZTtcbiAgICB9O1xuICB9XG4gIHZhciBkM19nZW9fY2xpcEV4dGVudE1BWCA9IDFlOTtcbiAgZDMuZ2VvLmNsaXBFeHRlbnQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgeDAsIHkwLCB4MSwgeTEsIHN0cmVhbSwgY2xpcCwgY2xpcEV4dGVudCA9IHtcbiAgICAgIHN0cmVhbTogZnVuY3Rpb24ob3V0cHV0KSB7XG4gICAgICAgIGlmIChzdHJlYW0pIHN0cmVhbS52YWxpZCA9IGZhbHNlO1xuICAgICAgICBzdHJlYW0gPSBjbGlwKG91dHB1dCk7XG4gICAgICAgIHN0cmVhbS52YWxpZCA9IHRydWU7XG4gICAgICAgIHJldHVybiBzdHJlYW07XG4gICAgICB9LFxuICAgICAgZXh0ZW50OiBmdW5jdGlvbihfKSB7XG4gICAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIFsgWyB4MCwgeTAgXSwgWyB4MSwgeTEgXSBdO1xuICAgICAgICBjbGlwID0gZDNfZ2VvX2NsaXBFeHRlbnQoeDAgPSArX1swXVswXSwgeTAgPSArX1swXVsxXSwgeDEgPSArX1sxXVswXSwgeTEgPSArX1sxXVsxXSk7XG4gICAgICAgIGlmIChzdHJlYW0pIHN0cmVhbS52YWxpZCA9IGZhbHNlLCBzdHJlYW0gPSBudWxsO1xuICAgICAgICByZXR1cm4gY2xpcEV4dGVudDtcbiAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBjbGlwRXh0ZW50LmV4dGVudChbIFsgMCwgMCBdLCBbIDk2MCwgNTAwIF0gXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19jbGlwRXh0ZW50KHgwLCB5MCwgeDEsIHkxKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGxpc3RlbmVyKSB7XG4gICAgICB2YXIgbGlzdGVuZXJfID0gbGlzdGVuZXIsIGJ1ZmZlckxpc3RlbmVyID0gZDNfZ2VvX2NsaXBCdWZmZXJMaXN0ZW5lcigpLCBjbGlwTGluZSA9IGQzX2dlb21fY2xpcExpbmUoeDAsIHkwLCB4MSwgeTEpLCBzZWdtZW50cywgcG9seWdvbiwgcmluZztcbiAgICAgIHZhciBjbGlwID0ge1xuICAgICAgICBwb2ludDogcG9pbnQsXG4gICAgICAgIGxpbmVTdGFydDogbGluZVN0YXJ0LFxuICAgICAgICBsaW5lRW5kOiBsaW5lRW5kLFxuICAgICAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxpc3RlbmVyID0gYnVmZmVyTGlzdGVuZXI7XG4gICAgICAgICAgc2VnbWVudHMgPSBbXTtcbiAgICAgICAgICBwb2x5Z29uID0gW107XG4gICAgICAgICAgY2xlYW4gPSB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBsaXN0ZW5lciA9IGxpc3RlbmVyXztcbiAgICAgICAgICBzZWdtZW50cyA9IGQzLm1lcmdlKHNlZ21lbnRzKTtcbiAgICAgICAgICB2YXIgY2xpcFN0YXJ0SW5zaWRlID0gaW5zaWRlUG9seWdvbihbIHgwLCB5MSBdKSwgaW5zaWRlID0gY2xlYW4gJiYgY2xpcFN0YXJ0SW5zaWRlLCB2aXNpYmxlID0gc2VnbWVudHMubGVuZ3RoO1xuICAgICAgICAgIGlmIChpbnNpZGUgfHwgdmlzaWJsZSkge1xuICAgICAgICAgICAgbGlzdGVuZXIucG9seWdvblN0YXJ0KCk7XG4gICAgICAgICAgICBpZiAoaW5zaWRlKSB7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgICAgICBpbnRlcnBvbGF0ZShudWxsLCBudWxsLCAxLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh2aXNpYmxlKSB7XG4gICAgICAgICAgICAgIGQzX2dlb19jbGlwUG9seWdvbihzZWdtZW50cywgY29tcGFyZSwgY2xpcFN0YXJ0SW5zaWRlLCBpbnRlcnBvbGF0ZSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGlzdGVuZXIucG9seWdvbkVuZCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzZWdtZW50cyA9IHBvbHlnb24gPSByaW5nID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGZ1bmN0aW9uIGluc2lkZVBvbHlnb24ocCkge1xuICAgICAgICB2YXIgd24gPSAwLCBuID0gcG9seWdvbi5sZW5ndGgsIHkgPSBwWzFdO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICAgIGZvciAodmFyIGogPSAxLCB2ID0gcG9seWdvbltpXSwgbSA9IHYubGVuZ3RoLCBhID0gdlswXSwgYjsgaiA8IG07ICsraikge1xuICAgICAgICAgICAgYiA9IHZbal07XG4gICAgICAgICAgICBpZiAoYVsxXSA8PSB5KSB7XG4gICAgICAgICAgICAgIGlmIChiWzFdID4geSAmJiBkM19jcm9zczJkKGEsIGIsIHApID4gMCkgKyt3bjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChiWzFdIDw9IHkgJiYgZDNfY3Jvc3MyZChhLCBiLCBwKSA8IDApIC0td247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhID0gYjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHduICE9PSAwO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gaW50ZXJwb2xhdGUoZnJvbSwgdG8sIGRpcmVjdGlvbiwgbGlzdGVuZXIpIHtcbiAgICAgICAgdmFyIGEgPSAwLCBhMSA9IDA7XG4gICAgICAgIGlmIChmcm9tID09IG51bGwgfHwgKGEgPSBjb3JuZXIoZnJvbSwgZGlyZWN0aW9uKSkgIT09IChhMSA9IGNvcm5lcih0bywgZGlyZWN0aW9uKSkgfHwgY29tcGFyZVBvaW50cyhmcm9tLCB0bykgPCAwIF4gZGlyZWN0aW9uID4gMCkge1xuICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KGEgPT09IDAgfHwgYSA9PT0gMyA/IHgwIDogeDEsIGEgPiAxID8geTEgOiB5MCk7XG4gICAgICAgICAgfSB3aGlsZSAoKGEgPSAoYSArIGRpcmVjdGlvbiArIDQpICUgNCkgIT09IGExKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsaXN0ZW5lci5wb2ludCh0b1swXSwgdG9bMV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBwb2ludFZpc2libGUoeCwgeSkge1xuICAgICAgICByZXR1cm4geDAgPD0geCAmJiB4IDw9IHgxICYmIHkwIDw9IHkgJiYgeSA8PSB5MTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHBvaW50KHgsIHkpIHtcbiAgICAgICAgaWYgKHBvaW50VmlzaWJsZSh4LCB5KSkgbGlzdGVuZXIucG9pbnQoeCwgeSk7XG4gICAgICB9XG4gICAgICB2YXIgeF9fLCB5X18sIHZfXywgeF8sIHlfLCB2XywgZmlyc3QsIGNsZWFuO1xuICAgICAgZnVuY3Rpb24gbGluZVN0YXJ0KCkge1xuICAgICAgICBjbGlwLnBvaW50ID0gbGluZVBvaW50O1xuICAgICAgICBpZiAocG9seWdvbikgcG9seWdvbi5wdXNoKHJpbmcgPSBbXSk7XG4gICAgICAgIGZpcnN0ID0gdHJ1ZTtcbiAgICAgICAgdl8gPSBmYWxzZTtcbiAgICAgICAgeF8gPSB5XyA9IE5hTjtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGxpbmVFbmQoKSB7XG4gICAgICAgIGlmIChzZWdtZW50cykge1xuICAgICAgICAgIGxpbmVQb2ludCh4X18sIHlfXyk7XG4gICAgICAgICAgaWYgKHZfXyAmJiB2XykgYnVmZmVyTGlzdGVuZXIucmVqb2luKCk7XG4gICAgICAgICAgc2VnbWVudHMucHVzaChidWZmZXJMaXN0ZW5lci5idWZmZXIoKSk7XG4gICAgICAgIH1cbiAgICAgICAgY2xpcC5wb2ludCA9IHBvaW50O1xuICAgICAgICBpZiAodl8pIGxpc3RlbmVyLmxpbmVFbmQoKTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGxpbmVQb2ludCh4LCB5KSB7XG4gICAgICAgIHggPSBNYXRoLm1heCgtZDNfZ2VvX2NsaXBFeHRlbnRNQVgsIE1hdGgubWluKGQzX2dlb19jbGlwRXh0ZW50TUFYLCB4KSk7XG4gICAgICAgIHkgPSBNYXRoLm1heCgtZDNfZ2VvX2NsaXBFeHRlbnRNQVgsIE1hdGgubWluKGQzX2dlb19jbGlwRXh0ZW50TUFYLCB5KSk7XG4gICAgICAgIHZhciB2ID0gcG9pbnRWaXNpYmxlKHgsIHkpO1xuICAgICAgICBpZiAocG9seWdvbikgcmluZy5wdXNoKFsgeCwgeSBdKTtcbiAgICAgICAgaWYgKGZpcnN0KSB7XG4gICAgICAgICAgeF9fID0geCwgeV9fID0geSwgdl9fID0gdjtcbiAgICAgICAgICBmaXJzdCA9IGZhbHNlO1xuICAgICAgICAgIGlmICh2KSB7XG4gICAgICAgICAgICBsaXN0ZW5lci5saW5lU3RhcnQoKTtcbiAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHgsIHkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAodiAmJiB2XykgbGlzdGVuZXIucG9pbnQoeCwgeSk7IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGwgPSB7XG4gICAgICAgICAgICAgIGE6IHtcbiAgICAgICAgICAgICAgICB4OiB4XyxcbiAgICAgICAgICAgICAgICB5OiB5X1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBiOiB7XG4gICAgICAgICAgICAgICAgeDogeCxcbiAgICAgICAgICAgICAgICB5OiB5XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoY2xpcExpbmUobCkpIHtcbiAgICAgICAgICAgICAgaWYgKCF2Xykge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLmxpbmVTdGFydCgpO1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KGwuYS54LCBsLmEueSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgbGlzdGVuZXIucG9pbnQobC5iLngsIGwuYi55KTtcbiAgICAgICAgICAgICAgaWYgKCF2KSBsaXN0ZW5lci5saW5lRW5kKCk7XG4gICAgICAgICAgICAgIGNsZWFuID0gZmFsc2U7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHYpIHtcbiAgICAgICAgICAgICAgbGlzdGVuZXIubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICAgIGxpc3RlbmVyLnBvaW50KHgsIHkpO1xuICAgICAgICAgICAgICBjbGVhbiA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB4XyA9IHgsIHlfID0geSwgdl8gPSB2O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNsaXA7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBjb3JuZXIocCwgZGlyZWN0aW9uKSB7XG4gICAgICByZXR1cm4gYWJzKHBbMF0gLSB4MCkgPCDOtSA/IGRpcmVjdGlvbiA+IDAgPyAwIDogMyA6IGFicyhwWzBdIC0geDEpIDwgzrUgPyBkaXJlY3Rpb24gPiAwID8gMiA6IDEgOiBhYnMocFsxXSAtIHkwKSA8IM61ID8gZGlyZWN0aW9uID4gMCA/IDEgOiAwIDogZGlyZWN0aW9uID4gMCA/IDMgOiAyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjb21wYXJlKGEsIGIpIHtcbiAgICAgIHJldHVybiBjb21wYXJlUG9pbnRzKGEueCwgYi54KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY29tcGFyZVBvaW50cyhhLCBiKSB7XG4gICAgICB2YXIgY2EgPSBjb3JuZXIoYSwgMSksIGNiID0gY29ybmVyKGIsIDEpO1xuICAgICAgcmV0dXJuIGNhICE9PSBjYiA/IGNhIC0gY2IgOiBjYSA9PT0gMCA/IGJbMV0gLSBhWzFdIDogY2EgPT09IDEgPyBhWzBdIC0gYlswXSA6IGNhID09PSAyID8gYVsxXSAtIGJbMV0gOiBiWzBdIC0gYVswXTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NvbmljKHByb2plY3RBdCkge1xuICAgIHZhciDPhjAgPSAwLCDPhjEgPSDPgCAvIDMsIG0gPSBkM19nZW9fcHJvamVjdGlvbk11dGF0b3IocHJvamVjdEF0KSwgcCA9IG0oz4YwLCDPhjEpO1xuICAgIHAucGFyYWxsZWxzID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gWyDPhjAgLyDPgCAqIDE4MCwgz4YxIC8gz4AgKiAxODAgXTtcbiAgICAgIHJldHVybiBtKM+GMCA9IF9bMF0gKiDPgCAvIDE4MCwgz4YxID0gX1sxXSAqIM+AIC8gMTgwKTtcbiAgICB9O1xuICAgIHJldHVybiBwO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19jb25pY0VxdWFsQXJlYSjPhjAsIM+GMSkge1xuICAgIHZhciBzaW7PhjAgPSBNYXRoLnNpbijPhjApLCBuID0gKHNpbs+GMCArIE1hdGguc2luKM+GMSkpIC8gMiwgQyA9IDEgKyBzaW7PhjAgKiAoMiAqIG4gLSBzaW7PhjApLCDPgTAgPSBNYXRoLnNxcnQoQykgLyBuO1xuICAgIGZ1bmN0aW9uIGZvcndhcmQozrssIM+GKSB7XG4gICAgICB2YXIgz4EgPSBNYXRoLnNxcnQoQyAtIDIgKiBuICogTWF0aC5zaW4oz4YpKSAvIG47XG4gICAgICByZXR1cm4gWyDPgSAqIE1hdGguc2luKM67ICo9IG4pLCDPgTAgLSDPgSAqIE1hdGguY29zKM67KSBdO1xuICAgIH1cbiAgICBmb3J3YXJkLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciDPgTBfeSA9IM+BMCAtIHk7XG4gICAgICByZXR1cm4gWyBNYXRoLmF0YW4yKHgsIM+BMF95KSAvIG4sIGQzX2FzaW4oKEMgLSAoeCAqIHggKyDPgTBfeSAqIM+BMF95KSAqIG4gKiBuKSAvICgyICogbikpIF07XG4gICAgfTtcbiAgICByZXR1cm4gZm9yd2FyZDtcbiAgfVxuICAoZDMuZ2VvLmNvbmljRXF1YWxBcmVhID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX2dlb19jb25pYyhkM19nZW9fY29uaWNFcXVhbEFyZWEpO1xuICB9KS5yYXcgPSBkM19nZW9fY29uaWNFcXVhbEFyZWE7XG4gIGQzLmdlby5hbGJlcnMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDMuZ2VvLmNvbmljRXF1YWxBcmVhKCkucm90YXRlKFsgOTYsIDAgXSkuY2VudGVyKFsgLS42LCAzOC43IF0pLnBhcmFsbGVscyhbIDI5LjUsIDQ1LjUgXSkuc2NhbGUoMTA3MCk7XG4gIH07XG4gIGQzLmdlby5hbGJlcnNVc2EgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbG93ZXI0OCA9IGQzLmdlby5hbGJlcnMoKTtcbiAgICB2YXIgYWxhc2thID0gZDMuZ2VvLmNvbmljRXF1YWxBcmVhKCkucm90YXRlKFsgMTU0LCAwIF0pLmNlbnRlcihbIC0yLCA1OC41IF0pLnBhcmFsbGVscyhbIDU1LCA2NSBdKTtcbiAgICB2YXIgaGF3YWlpID0gZDMuZ2VvLmNvbmljRXF1YWxBcmVhKCkucm90YXRlKFsgMTU3LCAwIF0pLmNlbnRlcihbIC0zLCAxOS45IF0pLnBhcmFsbGVscyhbIDgsIDE4IF0pO1xuICAgIHZhciBwb2ludCwgcG9pbnRTdHJlYW0gPSB7XG4gICAgICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgICAgICBwb2ludCA9IFsgeCwgeSBdO1xuICAgICAgfVxuICAgIH0sIGxvd2VyNDhQb2ludCwgYWxhc2thUG9pbnQsIGhhd2FpaVBvaW50O1xuICAgIGZ1bmN0aW9uIGFsYmVyc1VzYShjb29yZGluYXRlcykge1xuICAgICAgdmFyIHggPSBjb29yZGluYXRlc1swXSwgeSA9IGNvb3JkaW5hdGVzWzFdO1xuICAgICAgcG9pbnQgPSBudWxsO1xuICAgICAgKGxvd2VyNDhQb2ludCh4LCB5KSwgcG9pbnQpIHx8IChhbGFza2FQb2ludCh4LCB5KSwgcG9pbnQpIHx8IGhhd2FpaVBvaW50KHgsIHkpO1xuICAgICAgcmV0dXJuIHBvaW50O1xuICAgIH1cbiAgICBhbGJlcnNVc2EuaW52ZXJ0ID0gZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHtcbiAgICAgIHZhciBrID0gbG93ZXI0OC5zY2FsZSgpLCB0ID0gbG93ZXI0OC50cmFuc2xhdGUoKSwgeCA9IChjb29yZGluYXRlc1swXSAtIHRbMF0pIC8gaywgeSA9IChjb29yZGluYXRlc1sxXSAtIHRbMV0pIC8gaztcbiAgICAgIHJldHVybiAoeSA+PSAuMTIgJiYgeSA8IC4yMzQgJiYgeCA+PSAtLjQyNSAmJiB4IDwgLS4yMTQgPyBhbGFza2EgOiB5ID49IC4xNjYgJiYgeSA8IC4yMzQgJiYgeCA+PSAtLjIxNCAmJiB4IDwgLS4xMTUgPyBoYXdhaWkgOiBsb3dlcjQ4KS5pbnZlcnQoY29vcmRpbmF0ZXMpO1xuICAgIH07XG4gICAgYWxiZXJzVXNhLnN0cmVhbSA9IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgdmFyIGxvd2VyNDhTdHJlYW0gPSBsb3dlcjQ4LnN0cmVhbShzdHJlYW0pLCBhbGFza2FTdHJlYW0gPSBhbGFza2Euc3RyZWFtKHN0cmVhbSksIGhhd2FpaVN0cmVhbSA9IGhhd2FpaS5zdHJlYW0oc3RyZWFtKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgICAgICAgbG93ZXI0OFN0cmVhbS5wb2ludCh4LCB5KTtcbiAgICAgICAgICBhbGFza2FTdHJlYW0ucG9pbnQoeCwgeSk7XG4gICAgICAgICAgaGF3YWlpU3RyZWFtLnBvaW50KHgsIHkpO1xuICAgICAgICB9LFxuICAgICAgICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxvd2VyNDhTdHJlYW0uc3BoZXJlKCk7XG4gICAgICAgICAgYWxhc2thU3RyZWFtLnNwaGVyZSgpO1xuICAgICAgICAgIGhhd2FpaVN0cmVhbS5zcGhlcmUoKTtcbiAgICAgICAgfSxcbiAgICAgICAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBsb3dlcjQ4U3RyZWFtLmxpbmVTdGFydCgpO1xuICAgICAgICAgIGFsYXNrYVN0cmVhbS5saW5lU3RhcnQoKTtcbiAgICAgICAgICBoYXdhaWlTdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgIH0sXG4gICAgICAgIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxvd2VyNDhTdHJlYW0ubGluZUVuZCgpO1xuICAgICAgICAgIGFsYXNrYVN0cmVhbS5saW5lRW5kKCk7XG4gICAgICAgICAgaGF3YWlpU3RyZWFtLmxpbmVFbmQoKTtcbiAgICAgICAgfSxcbiAgICAgICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBsb3dlcjQ4U3RyZWFtLnBvbHlnb25TdGFydCgpO1xuICAgICAgICAgIGFsYXNrYVN0cmVhbS5wb2x5Z29uU3RhcnQoKTtcbiAgICAgICAgICBoYXdhaWlTdHJlYW0ucG9seWdvblN0YXJ0KCk7XG4gICAgICAgIH0sXG4gICAgICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGxvd2VyNDhTdHJlYW0ucG9seWdvbkVuZCgpO1xuICAgICAgICAgIGFsYXNrYVN0cmVhbS5wb2x5Z29uRW5kKCk7XG4gICAgICAgICAgaGF3YWlpU3RyZWFtLnBvbHlnb25FbmQoKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9O1xuICAgIGFsYmVyc1VzYS5wcmVjaXNpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsb3dlcjQ4LnByZWNpc2lvbigpO1xuICAgICAgbG93ZXI0OC5wcmVjaXNpb24oXyk7XG4gICAgICBhbGFza2EucHJlY2lzaW9uKF8pO1xuICAgICAgaGF3YWlpLnByZWNpc2lvbihfKTtcbiAgICAgIHJldHVybiBhbGJlcnNVc2E7XG4gICAgfTtcbiAgICBhbGJlcnNVc2Euc2NhbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsb3dlcjQ4LnNjYWxlKCk7XG4gICAgICBsb3dlcjQ4LnNjYWxlKF8pO1xuICAgICAgYWxhc2thLnNjYWxlKF8gKiAuMzUpO1xuICAgICAgaGF3YWlpLnNjYWxlKF8pO1xuICAgICAgcmV0dXJuIGFsYmVyc1VzYS50cmFuc2xhdGUobG93ZXI0OC50cmFuc2xhdGUoKSk7XG4gICAgfTtcbiAgICBhbGJlcnNVc2EudHJhbnNsYXRlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbG93ZXI0OC50cmFuc2xhdGUoKTtcbiAgICAgIHZhciBrID0gbG93ZXI0OC5zY2FsZSgpLCB4ID0gK19bMF0sIHkgPSArX1sxXTtcbiAgICAgIGxvd2VyNDhQb2ludCA9IGxvd2VyNDgudHJhbnNsYXRlKF8pLmNsaXBFeHRlbnQoWyBbIHggLSAuNDU1ICogaywgeSAtIC4yMzggKiBrIF0sIFsgeCArIC40NTUgKiBrLCB5ICsgLjIzOCAqIGsgXSBdKS5zdHJlYW0ocG9pbnRTdHJlYW0pLnBvaW50O1xuICAgICAgYWxhc2thUG9pbnQgPSBhbGFza2EudHJhbnNsYXRlKFsgeCAtIC4zMDcgKiBrLCB5ICsgLjIwMSAqIGsgXSkuY2xpcEV4dGVudChbIFsgeCAtIC40MjUgKiBrICsgzrUsIHkgKyAuMTIgKiBrICsgzrUgXSwgWyB4IC0gLjIxNCAqIGsgLSDOtSwgeSArIC4yMzQgKiBrIC0gzrUgXSBdKS5zdHJlYW0ocG9pbnRTdHJlYW0pLnBvaW50O1xuICAgICAgaGF3YWlpUG9pbnQgPSBoYXdhaWkudHJhbnNsYXRlKFsgeCAtIC4yMDUgKiBrLCB5ICsgLjIxMiAqIGsgXSkuY2xpcEV4dGVudChbIFsgeCAtIC4yMTQgKiBrICsgzrUsIHkgKyAuMTY2ICogayArIM61IF0sIFsgeCAtIC4xMTUgKiBrIC0gzrUsIHkgKyAuMjM0ICogayAtIM61IF0gXSkuc3RyZWFtKHBvaW50U3RyZWFtKS5wb2ludDtcbiAgICAgIHJldHVybiBhbGJlcnNVc2E7XG4gICAgfTtcbiAgICByZXR1cm4gYWxiZXJzVXNhLnNjYWxlKDEwNzApO1xuICB9O1xuICB2YXIgZDNfZ2VvX3BhdGhBcmVhU3VtLCBkM19nZW9fcGF0aEFyZWFQb2x5Z29uLCBkM19nZW9fcGF0aEFyZWEgPSB7XG4gICAgcG9pbnQ6IGQzX25vb3AsXG4gICAgbGluZVN0YXJ0OiBkM19ub29wLFxuICAgIGxpbmVFbmQ6IGQzX25vb3AsXG4gICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIGQzX2dlb19wYXRoQXJlYVBvbHlnb24gPSAwO1xuICAgICAgZDNfZ2VvX3BhdGhBcmVhLmxpbmVTdGFydCA9IGQzX2dlb19wYXRoQXJlYVJpbmdTdGFydDtcbiAgICB9LFxuICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfZ2VvX3BhdGhBcmVhLmxpbmVTdGFydCA9IGQzX2dlb19wYXRoQXJlYS5saW5lRW5kID0gZDNfZ2VvX3BhdGhBcmVhLnBvaW50ID0gZDNfbm9vcDtcbiAgICAgIGQzX2dlb19wYXRoQXJlYVN1bSArPSBhYnMoZDNfZ2VvX3BhdGhBcmVhUG9seWdvbiAvIDIpO1xuICAgIH1cbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3BhdGhBcmVhUmluZ1N0YXJ0KCkge1xuICAgIHZhciB4MDAsIHkwMCwgeDAsIHkwO1xuICAgIGQzX2dlb19wYXRoQXJlYS5wb2ludCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIGQzX2dlb19wYXRoQXJlYS5wb2ludCA9IG5leHRQb2ludDtcbiAgICAgIHgwMCA9IHgwID0geCwgeTAwID0geTAgPSB5O1xuICAgIH07XG4gICAgZnVuY3Rpb24gbmV4dFBvaW50KHgsIHkpIHtcbiAgICAgIGQzX2dlb19wYXRoQXJlYVBvbHlnb24gKz0geTAgKiB4IC0geDAgKiB5O1xuICAgICAgeDAgPSB4LCB5MCA9IHk7XG4gICAgfVxuICAgIGQzX2dlb19wYXRoQXJlYS5saW5lRW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICBuZXh0UG9pbnQoeDAwLCB5MDApO1xuICAgIH07XG4gIH1cbiAgdmFyIGQzX2dlb19wYXRoQm91bmRzWDAsIGQzX2dlb19wYXRoQm91bmRzWTAsIGQzX2dlb19wYXRoQm91bmRzWDEsIGQzX2dlb19wYXRoQm91bmRzWTE7XG4gIHZhciBkM19nZW9fcGF0aEJvdW5kcyA9IHtcbiAgICBwb2ludDogZDNfZ2VvX3BhdGhCb3VuZHNQb2ludCxcbiAgICBsaW5lU3RhcnQ6IGQzX25vb3AsXG4gICAgbGluZUVuZDogZDNfbm9vcCxcbiAgICBwb2x5Z29uU3RhcnQ6IGQzX25vb3AsXG4gICAgcG9seWdvbkVuZDogZDNfbm9vcFxuICB9O1xuICBmdW5jdGlvbiBkM19nZW9fcGF0aEJvdW5kc1BvaW50KHgsIHkpIHtcbiAgICBpZiAoeCA8IGQzX2dlb19wYXRoQm91bmRzWDApIGQzX2dlb19wYXRoQm91bmRzWDAgPSB4O1xuICAgIGlmICh4ID4gZDNfZ2VvX3BhdGhCb3VuZHNYMSkgZDNfZ2VvX3BhdGhCb3VuZHNYMSA9IHg7XG4gICAgaWYgKHkgPCBkM19nZW9fcGF0aEJvdW5kc1kwKSBkM19nZW9fcGF0aEJvdW5kc1kwID0geTtcbiAgICBpZiAoeSA+IGQzX2dlb19wYXRoQm91bmRzWTEpIGQzX2dlb19wYXRoQm91bmRzWTEgPSB5O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19wYXRoQnVmZmVyKCkge1xuICAgIHZhciBwb2ludENpcmNsZSA9IGQzX2dlb19wYXRoQnVmZmVyQ2lyY2xlKDQuNSksIGJ1ZmZlciA9IFtdO1xuICAgIHZhciBzdHJlYW0gPSB7XG4gICAgICBwb2ludDogcG9pbnQsXG4gICAgICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBzdHJlYW0ucG9pbnQgPSBwb2ludExpbmVTdGFydDtcbiAgICAgIH0sXG4gICAgICBsaW5lRW5kOiBsaW5lRW5kLFxuICAgICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgc3RyZWFtLmxpbmVFbmQgPSBsaW5lRW5kUG9seWdvbjtcbiAgICAgIH0sXG4gICAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgc3RyZWFtLmxpbmVFbmQgPSBsaW5lRW5kO1xuICAgICAgICBzdHJlYW0ucG9pbnQgPSBwb2ludDtcbiAgICAgIH0sXG4gICAgICBwb2ludFJhZGl1czogZnVuY3Rpb24oXykge1xuICAgICAgICBwb2ludENpcmNsZSA9IGQzX2dlb19wYXRoQnVmZmVyQ2lyY2xlKF8pO1xuICAgICAgICByZXR1cm4gc3RyZWFtO1xuICAgICAgfSxcbiAgICAgIHJlc3VsdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmIChidWZmZXIubGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGJ1ZmZlci5qb2luKFwiXCIpO1xuICAgICAgICAgIGJ1ZmZlciA9IFtdO1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICAgIGZ1bmN0aW9uIHBvaW50KHgsIHkpIHtcbiAgICAgIGJ1ZmZlci5wdXNoKFwiTVwiLCB4LCBcIixcIiwgeSwgcG9pbnRDaXJjbGUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb2ludExpbmVTdGFydCh4LCB5KSB7XG4gICAgICBidWZmZXIucHVzaChcIk1cIiwgeCwgXCIsXCIsIHkpO1xuICAgICAgc3RyZWFtLnBvaW50ID0gcG9pbnRMaW5lO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb2ludExpbmUoeCwgeSkge1xuICAgICAgYnVmZmVyLnB1c2goXCJMXCIsIHgsIFwiLFwiLCB5KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZUVuZCgpIHtcbiAgICAgIHN0cmVhbS5wb2ludCA9IHBvaW50O1xuICAgIH1cbiAgICBmdW5jdGlvbiBsaW5lRW5kUG9seWdvbigpIHtcbiAgICAgIGJ1ZmZlci5wdXNoKFwiWlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0cmVhbTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcGF0aEJ1ZmZlckNpcmNsZShyYWRpdXMpIHtcbiAgICByZXR1cm4gXCJtMCxcIiArIHJhZGl1cyArIFwiYVwiICsgcmFkaXVzICsgXCIsXCIgKyByYWRpdXMgKyBcIiAwIDEsMSAwLFwiICsgLTIgKiByYWRpdXMgKyBcImFcIiArIHJhZGl1cyArIFwiLFwiICsgcmFkaXVzICsgXCIgMCAxLDEgMCxcIiArIDIgKiByYWRpdXMgKyBcInpcIjtcbiAgfVxuICB2YXIgZDNfZ2VvX3BhdGhDZW50cm9pZCA9IHtcbiAgICBwb2ludDogZDNfZ2VvX3BhdGhDZW50cm9pZFBvaW50LFxuICAgIGxpbmVTdGFydDogZDNfZ2VvX3BhdGhDZW50cm9pZExpbmVTdGFydCxcbiAgICBsaW5lRW5kOiBkM19nZW9fcGF0aENlbnRyb2lkTGluZUVuZCxcbiAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5saW5lU3RhcnQgPSBkM19nZW9fcGF0aENlbnRyb2lkUmluZ1N0YXJ0O1xuICAgIH0sXG4gICAgcG9seWdvbkVuZDogZnVuY3Rpb24oKSB7XG4gICAgICBkM19nZW9fcGF0aENlbnRyb2lkLnBvaW50ID0gZDNfZ2VvX3BhdGhDZW50cm9pZFBvaW50O1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5saW5lU3RhcnQgPSBkM19nZW9fcGF0aENlbnRyb2lkTGluZVN0YXJ0O1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5saW5lRW5kID0gZDNfZ2VvX3BhdGhDZW50cm9pZExpbmVFbmQ7XG4gICAgfVxuICB9O1xuICBmdW5jdGlvbiBkM19nZW9fcGF0aENlbnRyb2lkUG9pbnQoeCwgeSkge1xuICAgIGQzX2dlb19jZW50cm9pZFgwICs9IHg7XG4gICAgZDNfZ2VvX2NlbnRyb2lkWTAgKz0geTtcbiAgICArK2QzX2dlb19jZW50cm9pZFowO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19wYXRoQ2VudHJvaWRMaW5lU3RhcnQoKSB7XG4gICAgdmFyIHgwLCB5MDtcbiAgICBkM19nZW9fcGF0aENlbnRyb2lkLnBvaW50ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5wb2ludCA9IG5leHRQb2ludDtcbiAgICAgIGQzX2dlb19wYXRoQ2VudHJvaWRQb2ludCh4MCA9IHgsIHkwID0geSk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBuZXh0UG9pbnQoeCwgeSkge1xuICAgICAgdmFyIGR4ID0geCAtIHgwLCBkeSA9IHkgLSB5MCwgeiA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gICAgICBkM19nZW9fY2VudHJvaWRYMSArPSB6ICogKHgwICsgeCkgLyAyO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWTEgKz0geiAqICh5MCArIHkpIC8gMjtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoxICs9IHo7XG4gICAgICBkM19nZW9fcGF0aENlbnRyb2lkUG9pbnQoeDAgPSB4LCB5MCA9IHkpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcGF0aENlbnRyb2lkTGluZUVuZCgpIHtcbiAgICBkM19nZW9fcGF0aENlbnRyb2lkLnBvaW50ID0gZDNfZ2VvX3BhdGhDZW50cm9pZFBvaW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19wYXRoQ2VudHJvaWRSaW5nU3RhcnQoKSB7XG4gICAgdmFyIHgwMCwgeTAwLCB4MCwgeTA7XG4gICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5wb2ludCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIGQzX2dlb19wYXRoQ2VudHJvaWQucG9pbnQgPSBuZXh0UG9pbnQ7XG4gICAgICBkM19nZW9fcGF0aENlbnRyb2lkUG9pbnQoeDAwID0geDAgPSB4LCB5MDAgPSB5MCA9IHkpO1xuICAgIH07XG4gICAgZnVuY3Rpb24gbmV4dFBvaW50KHgsIHkpIHtcbiAgICAgIHZhciBkeCA9IHggLSB4MCwgZHkgPSB5IC0geTAsIHogPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWDEgKz0geiAqICh4MCArIHgpIC8gMjtcbiAgICAgIGQzX2dlb19jZW50cm9pZFkxICs9IHogKiAoeTAgKyB5KSAvIDI7XG4gICAgICBkM19nZW9fY2VudHJvaWRaMSArPSB6O1xuICAgICAgeiA9IHkwICogeCAtIHgwICogeTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFgyICs9IHogKiAoeDAgKyB4KTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFkyICs9IHogKiAoeTAgKyB5KTtcbiAgICAgIGQzX2dlb19jZW50cm9pZFoyICs9IHogKiAzO1xuICAgICAgZDNfZ2VvX3BhdGhDZW50cm9pZFBvaW50KHgwID0geCwgeTAgPSB5KTtcbiAgICB9XG4gICAgZDNfZ2VvX3BhdGhDZW50cm9pZC5saW5lRW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICBuZXh0UG9pbnQoeDAwLCB5MDApO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3BhdGhDb250ZXh0KGNvbnRleHQpIHtcbiAgICB2YXIgcG9pbnRSYWRpdXMgPSA0LjU7XG4gICAgdmFyIHN0cmVhbSA9IHtcbiAgICAgIHBvaW50OiBwb2ludCxcbiAgICAgIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHN0cmVhbS5wb2ludCA9IHBvaW50TGluZVN0YXJ0O1xuICAgICAgfSxcbiAgICAgIGxpbmVFbmQ6IGxpbmVFbmQsXG4gICAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBzdHJlYW0ubGluZUVuZCA9IGxpbmVFbmRQb2x5Z29uO1xuICAgICAgfSxcbiAgICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBzdHJlYW0ubGluZUVuZCA9IGxpbmVFbmQ7XG4gICAgICAgIHN0cmVhbS5wb2ludCA9IHBvaW50O1xuICAgICAgfSxcbiAgICAgIHBvaW50UmFkaXVzOiBmdW5jdGlvbihfKSB7XG4gICAgICAgIHBvaW50UmFkaXVzID0gXztcbiAgICAgICAgcmV0dXJuIHN0cmVhbTtcbiAgICAgIH0sXG4gICAgICByZXN1bHQ6IGQzX25vb3BcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHBvaW50KHgsIHkpIHtcbiAgICAgIGNvbnRleHQubW92ZVRvKHggKyBwb2ludFJhZGl1cywgeSk7XG4gICAgICBjb250ZXh0LmFyYyh4LCB5LCBwb2ludFJhZGl1cywgMCwgz4QpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb2ludExpbmVTdGFydCh4LCB5KSB7XG4gICAgICBjb250ZXh0Lm1vdmVUbyh4LCB5KTtcbiAgICAgIHN0cmVhbS5wb2ludCA9IHBvaW50TGluZTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcG9pbnRMaW5lKHgsIHkpIHtcbiAgICAgIGNvbnRleHQubGluZVRvKHgsIHkpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBsaW5lRW5kKCkge1xuICAgICAgc3RyZWFtLnBvaW50ID0gcG9pbnQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGxpbmVFbmRQb2x5Z29uKCkge1xuICAgICAgY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0cmVhbTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcmVzYW1wbGUocHJvamVjdCkge1xuICAgIHZhciDOtDIgPSAuNSwgY29zTWluRGlzdGFuY2UgPSBNYXRoLmNvcygzMCAqIGQzX3JhZGlhbnMpLCBtYXhEZXB0aCA9IDE2O1xuICAgIGZ1bmN0aW9uIHJlc2FtcGxlKHN0cmVhbSkge1xuICAgICAgcmV0dXJuIChtYXhEZXB0aCA/IHJlc2FtcGxlUmVjdXJzaXZlIDogcmVzYW1wbGVOb25lKShzdHJlYW0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNhbXBsZU5vbmUoc3RyZWFtKSB7XG4gICAgICByZXR1cm4gZDNfZ2VvX3RyYW5zZm9ybVBvaW50KHN0cmVhbSwgZnVuY3Rpb24oeCwgeSkge1xuICAgICAgICB4ID0gcHJvamVjdCh4LCB5KTtcbiAgICAgICAgc3RyZWFtLnBvaW50KHhbMF0sIHhbMV0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc2FtcGxlUmVjdXJzaXZlKHN0cmVhbSkge1xuICAgICAgdmFyIM67MDAsIM+GMDAsIHgwMCwgeTAwLCBhMDAsIGIwMCwgYzAwLCDOuzAsIHgwLCB5MCwgYTAsIGIwLCBjMDtcbiAgICAgIHZhciByZXNhbXBsZSA9IHtcbiAgICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgICBsaW5lU3RhcnQ6IGxpbmVTdGFydCxcbiAgICAgICAgbGluZUVuZDogbGluZUVuZCxcbiAgICAgICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBzdHJlYW0ucG9seWdvblN0YXJ0KCk7XG4gICAgICAgICAgcmVzYW1wbGUubGluZVN0YXJ0ID0gcmluZ1N0YXJ0O1xuICAgICAgICB9LFxuICAgICAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICBzdHJlYW0ucG9seWdvbkVuZCgpO1xuICAgICAgICAgIHJlc2FtcGxlLmxpbmVTdGFydCA9IGxpbmVTdGFydDtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGZ1bmN0aW9uIHBvaW50KHgsIHkpIHtcbiAgICAgICAgeCA9IHByb2plY3QoeCwgeSk7XG4gICAgICAgIHN0cmVhbS5wb2ludCh4WzBdLCB4WzFdKTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGxpbmVTdGFydCgpIHtcbiAgICAgICAgeDAgPSBOYU47XG4gICAgICAgIHJlc2FtcGxlLnBvaW50ID0gbGluZVBvaW50O1xuICAgICAgICBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBsaW5lUG9pbnQozrssIM+GKSB7XG4gICAgICAgIHZhciBjID0gZDNfZ2VvX2NhcnRlc2lhbihbIM67LCDPhiBdKSwgcCA9IHByb2plY3QozrssIM+GKTtcbiAgICAgICAgcmVzYW1wbGVMaW5lVG8oeDAsIHkwLCDOuzAsIGEwLCBiMCwgYzAsIHgwID0gcFswXSwgeTAgPSBwWzFdLCDOuzAgPSDOuywgYTAgPSBjWzBdLCBiMCA9IGNbMV0sIGMwID0gY1syXSwgbWF4RGVwdGgsIHN0cmVhbSk7XG4gICAgICAgIHN0cmVhbS5wb2ludCh4MCwgeTApO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gbGluZUVuZCgpIHtcbiAgICAgICAgcmVzYW1wbGUucG9pbnQgPSBwb2ludDtcbiAgICAgICAgc3RyZWFtLmxpbmVFbmQoKTtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJpbmdTdGFydCgpIHtcbiAgICAgICAgbGluZVN0YXJ0KCk7XG4gICAgICAgIHJlc2FtcGxlLnBvaW50ID0gcmluZ1BvaW50O1xuICAgICAgICByZXNhbXBsZS5saW5lRW5kID0gcmluZ0VuZDtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJpbmdQb2ludCjOuywgz4YpIHtcbiAgICAgICAgbGluZVBvaW50KM67MDAgPSDOuywgz4YwMCA9IM+GKSwgeDAwID0geDAsIHkwMCA9IHkwLCBhMDAgPSBhMCwgYjAwID0gYjAsIGMwMCA9IGMwO1xuICAgICAgICByZXNhbXBsZS5wb2ludCA9IGxpbmVQb2ludDtcbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIHJpbmdFbmQoKSB7XG4gICAgICAgIHJlc2FtcGxlTGluZVRvKHgwLCB5MCwgzrswLCBhMCwgYjAsIGMwLCB4MDAsIHkwMCwgzrswMCwgYTAwLCBiMDAsIGMwMCwgbWF4RGVwdGgsIHN0cmVhbSk7XG4gICAgICAgIHJlc2FtcGxlLmxpbmVFbmQgPSBsaW5lRW5kO1xuICAgICAgICBsaW5lRW5kKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzYW1wbGU7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc2FtcGxlTGluZVRvKHgwLCB5MCwgzrswLCBhMCwgYjAsIGMwLCB4MSwgeTEsIM67MSwgYTEsIGIxLCBjMSwgZGVwdGgsIHN0cmVhbSkge1xuICAgICAgdmFyIGR4ID0geDEgLSB4MCwgZHkgPSB5MSAtIHkwLCBkMiA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgaWYgKGQyID4gNCAqIM60MiAmJiBkZXB0aC0tKSB7XG4gICAgICAgIHZhciBhID0gYTAgKyBhMSwgYiA9IGIwICsgYjEsIGMgPSBjMCArIGMxLCBtID0gTWF0aC5zcXJ0KGEgKiBhICsgYiAqIGIgKyBjICogYyksIM+GMiA9IE1hdGguYXNpbihjIC89IG0pLCDOuzIgPSBhYnMoYWJzKGMpIC0gMSkgPCDOtSB8fCBhYnMozrswIC0gzrsxKSA8IM61ID8gKM67MCArIM67MSkgLyAyIDogTWF0aC5hdGFuMihiLCBhKSwgcCA9IHByb2plY3QozrsyLCDPhjIpLCB4MiA9IHBbMF0sIHkyID0gcFsxXSwgZHgyID0geDIgLSB4MCwgZHkyID0geTIgLSB5MCwgZHogPSBkeSAqIGR4MiAtIGR4ICogZHkyO1xuICAgICAgICBpZiAoZHogKiBkeiAvIGQyID4gzrQyIHx8IGFicygoZHggKiBkeDIgKyBkeSAqIGR5MikgLyBkMiAtIC41KSA+IC4zIHx8IGEwICogYTEgKyBiMCAqIGIxICsgYzAgKiBjMSA8IGNvc01pbkRpc3RhbmNlKSB7XG4gICAgICAgICAgcmVzYW1wbGVMaW5lVG8oeDAsIHkwLCDOuzAsIGEwLCBiMCwgYzAsIHgyLCB5MiwgzrsyLCBhIC89IG0sIGIgLz0gbSwgYywgZGVwdGgsIHN0cmVhbSk7XG4gICAgICAgICAgc3RyZWFtLnBvaW50KHgyLCB5Mik7XG4gICAgICAgICAgcmVzYW1wbGVMaW5lVG8oeDIsIHkyLCDOuzIsIGEsIGIsIGMsIHgxLCB5MSwgzrsxLCBhMSwgYjEsIGMxLCBkZXB0aCwgc3RyZWFtKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXNhbXBsZS5wcmVjaXNpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBNYXRoLnNxcnQozrQyKTtcbiAgICAgIG1heERlcHRoID0gKM60MiA9IF8gKiBfKSA+IDAgJiYgMTY7XG4gICAgICByZXR1cm4gcmVzYW1wbGU7XG4gICAgfTtcbiAgICByZXR1cm4gcmVzYW1wbGU7XG4gIH1cbiAgZDMuZ2VvLnBhdGggPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcG9pbnRSYWRpdXMgPSA0LjUsIHByb2plY3Rpb24sIGNvbnRleHQsIHByb2plY3RTdHJlYW0sIGNvbnRleHRTdHJlYW0sIGNhY2hlU3RyZWFtO1xuICAgIGZ1bmN0aW9uIHBhdGgob2JqZWN0KSB7XG4gICAgICBpZiAob2JqZWN0KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcG9pbnRSYWRpdXMgPT09IFwiZnVuY3Rpb25cIikgY29udGV4dFN0cmVhbS5wb2ludFJhZGl1cygrcG9pbnRSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gICAgICAgIGlmICghY2FjaGVTdHJlYW0gfHwgIWNhY2hlU3RyZWFtLnZhbGlkKSBjYWNoZVN0cmVhbSA9IHByb2plY3RTdHJlYW0oY29udGV4dFN0cmVhbSk7XG4gICAgICAgIGQzLmdlby5zdHJlYW0ob2JqZWN0LCBjYWNoZVN0cmVhbSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29udGV4dFN0cmVhbS5yZXN1bHQoKTtcbiAgICB9XG4gICAgcGF0aC5hcmVhID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICBkM19nZW9fcGF0aEFyZWFTdW0gPSAwO1xuICAgICAgZDMuZ2VvLnN0cmVhbShvYmplY3QsIHByb2plY3RTdHJlYW0oZDNfZ2VvX3BhdGhBcmVhKSk7XG4gICAgICByZXR1cm4gZDNfZ2VvX3BhdGhBcmVhU3VtO1xuICAgIH07XG4gICAgcGF0aC5jZW50cm9pZCA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgZDNfZ2VvX2NlbnRyb2lkWDAgPSBkM19nZW9fY2VudHJvaWRZMCA9IGQzX2dlb19jZW50cm9pZFowID0gZDNfZ2VvX2NlbnRyb2lkWDEgPSBkM19nZW9fY2VudHJvaWRZMSA9IGQzX2dlb19jZW50cm9pZFoxID0gZDNfZ2VvX2NlbnRyb2lkWDIgPSBkM19nZW9fY2VudHJvaWRZMiA9IGQzX2dlb19jZW50cm9pZFoyID0gMDtcbiAgICAgIGQzLmdlby5zdHJlYW0ob2JqZWN0LCBwcm9qZWN0U3RyZWFtKGQzX2dlb19wYXRoQ2VudHJvaWQpKTtcbiAgICAgIHJldHVybiBkM19nZW9fY2VudHJvaWRaMiA/IFsgZDNfZ2VvX2NlbnRyb2lkWDIgLyBkM19nZW9fY2VudHJvaWRaMiwgZDNfZ2VvX2NlbnRyb2lkWTIgLyBkM19nZW9fY2VudHJvaWRaMiBdIDogZDNfZ2VvX2NlbnRyb2lkWjEgPyBbIGQzX2dlb19jZW50cm9pZFgxIC8gZDNfZ2VvX2NlbnRyb2lkWjEsIGQzX2dlb19jZW50cm9pZFkxIC8gZDNfZ2VvX2NlbnRyb2lkWjEgXSA6IGQzX2dlb19jZW50cm9pZFowID8gWyBkM19nZW9fY2VudHJvaWRYMCAvIGQzX2dlb19jZW50cm9pZFowLCBkM19nZW9fY2VudHJvaWRZMCAvIGQzX2dlb19jZW50cm9pZFowIF0gOiBbIE5hTiwgTmFOIF07XG4gICAgfTtcbiAgICBwYXRoLmJvdW5kcyA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgZDNfZ2VvX3BhdGhCb3VuZHNYMSA9IGQzX2dlb19wYXRoQm91bmRzWTEgPSAtKGQzX2dlb19wYXRoQm91bmRzWDAgPSBkM19nZW9fcGF0aEJvdW5kc1kwID0gSW5maW5pdHkpO1xuICAgICAgZDMuZ2VvLnN0cmVhbShvYmplY3QsIHByb2plY3RTdHJlYW0oZDNfZ2VvX3BhdGhCb3VuZHMpKTtcbiAgICAgIHJldHVybiBbIFsgZDNfZ2VvX3BhdGhCb3VuZHNYMCwgZDNfZ2VvX3BhdGhCb3VuZHNZMCBdLCBbIGQzX2dlb19wYXRoQm91bmRzWDEsIGQzX2dlb19wYXRoQm91bmRzWTEgXSBdO1xuICAgIH07XG4gICAgcGF0aC5wcm9qZWN0aW9uID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcHJvamVjdGlvbjtcbiAgICAgIHByb2plY3RTdHJlYW0gPSAocHJvamVjdGlvbiA9IF8pID8gXy5zdHJlYW0gfHwgZDNfZ2VvX3BhdGhQcm9qZWN0U3RyZWFtKF8pIDogZDNfaWRlbnRpdHk7XG4gICAgICByZXR1cm4gcmVzZXQoKTtcbiAgICB9O1xuICAgIHBhdGguY29udGV4dCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGNvbnRleHQ7XG4gICAgICBjb250ZXh0U3RyZWFtID0gKGNvbnRleHQgPSBfKSA9PSBudWxsID8gbmV3IGQzX2dlb19wYXRoQnVmZmVyKCkgOiBuZXcgZDNfZ2VvX3BhdGhDb250ZXh0KF8pO1xuICAgICAgaWYgKHR5cGVvZiBwb2ludFJhZGl1cyAhPT0gXCJmdW5jdGlvblwiKSBjb250ZXh0U3RyZWFtLnBvaW50UmFkaXVzKHBvaW50UmFkaXVzKTtcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gICAgcGF0aC5wb2ludFJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHBvaW50UmFkaXVzO1xuICAgICAgcG9pbnRSYWRpdXMgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IChjb250ZXh0U3RyZWFtLnBvaW50UmFkaXVzKCtfKSwgK18pO1xuICAgICAgcmV0dXJuIHBhdGg7XG4gICAgfTtcbiAgICBmdW5jdGlvbiByZXNldCgpIHtcbiAgICAgIGNhY2hlU3RyZWFtID0gbnVsbDtcbiAgICAgIHJldHVybiBwYXRoO1xuICAgIH1cbiAgICByZXR1cm4gcGF0aC5wcm9qZWN0aW9uKGQzLmdlby5hbGJlcnNVc2EoKSkuY29udGV4dChudWxsKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3BhdGhQcm9qZWN0U3RyZWFtKHByb2plY3QpIHtcbiAgICB2YXIgcmVzYW1wbGUgPSBkM19nZW9fcmVzYW1wbGUoZnVuY3Rpb24oeCwgeSkge1xuICAgICAgcmV0dXJuIHByb2plY3QoWyB4ICogZDNfZGVncmVlcywgeSAqIGQzX2RlZ3JlZXMgXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0aW9uUmFkaWFucyhyZXNhbXBsZShzdHJlYW0pKTtcbiAgICB9O1xuICB9XG4gIGQzLmdlby50cmFuc2Zvcm0gPSBmdW5jdGlvbihtZXRob2RzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0cmVhbTogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICAgIHZhciB0cmFuc2Zvcm0gPSBuZXcgZDNfZ2VvX3RyYW5zZm9ybShzdHJlYW0pO1xuICAgICAgICBmb3IgKHZhciBrIGluIG1ldGhvZHMpIHRyYW5zZm9ybVtrXSA9IG1ldGhvZHNba107XG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm07XG4gICAgICB9XG4gICAgfTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3RyYW5zZm9ybShzdHJlYW0pIHtcbiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgfVxuICBkM19nZW9fdHJhbnNmb3JtLnByb3RvdHlwZSA9IHtcbiAgICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgICAgdGhpcy5zdHJlYW0ucG9pbnQoeCwgeSk7XG4gICAgfSxcbiAgICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5zdHJlYW0uc3BoZXJlKCk7XG4gICAgfSxcbiAgICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5zdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgfSxcbiAgICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuc3RyZWFtLmxpbmVFbmQoKTtcbiAgICB9LFxuICAgIHBvbHlnb25TdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLnN0cmVhbS5wb2x5Z29uU3RhcnQoKTtcbiAgICB9LFxuICAgIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5zdHJlYW0ucG9seWdvbkVuZCgpO1xuICAgIH1cbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3RyYW5zZm9ybVBvaW50KHN0cmVhbSwgcG9pbnQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgc3BoZXJlOiBmdW5jdGlvbigpIHtcbiAgICAgICAgc3RyZWFtLnNwaGVyZSgpO1xuICAgICAgfSxcbiAgICAgIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHN0cmVhbS5saW5lU3RhcnQoKTtcbiAgICAgIH0sXG4gICAgICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgc3RyZWFtLmxpbmVFbmQoKTtcbiAgICAgIH0sXG4gICAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBzdHJlYW0ucG9seWdvblN0YXJ0KCk7XG4gICAgICB9LFxuICAgICAgcG9seWdvbkVuZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHN0cmVhbS5wb2x5Z29uRW5kKCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuICBkMy5nZW8ucHJvamVjdGlvbiA9IGQzX2dlb19wcm9qZWN0aW9uO1xuICBkMy5nZW8ucHJvamVjdGlvbk11dGF0b3IgPSBkM19nZW9fcHJvamVjdGlvbk11dGF0b3I7XG4gIGZ1bmN0aW9uIGQzX2dlb19wcm9qZWN0aW9uKHByb2plY3QpIHtcbiAgICByZXR1cm4gZDNfZ2VvX3Byb2plY3Rpb25NdXRhdG9yKGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHByb2plY3Q7XG4gICAgfSkoKTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcHJvamVjdGlvbk11dGF0b3IocHJvamVjdEF0KSB7XG4gICAgdmFyIHByb2plY3QsIHJvdGF0ZSwgcHJvamVjdFJvdGF0ZSwgcHJvamVjdFJlc2FtcGxlID0gZDNfZ2VvX3Jlc2FtcGxlKGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHggPSBwcm9qZWN0KHgsIHkpO1xuICAgICAgcmV0dXJuIFsgeFswXSAqIGsgKyDOtHgsIM60eSAtIHhbMV0gKiBrIF07XG4gICAgfSksIGsgPSAxNTAsIHggPSA0ODAsIHkgPSAyNTAsIM67ID0gMCwgz4YgPSAwLCDOtM67ID0gMCwgzrTPhiA9IDAsIM60zrMgPSAwLCDOtHgsIM60eSwgcHJlY2xpcCA9IGQzX2dlb19jbGlwQW50aW1lcmlkaWFuLCBwb3N0Y2xpcCA9IGQzX2lkZW50aXR5LCBjbGlwQW5nbGUgPSBudWxsLCBjbGlwRXh0ZW50ID0gbnVsbCwgc3RyZWFtO1xuICAgIGZ1bmN0aW9uIHByb2plY3Rpb24ocG9pbnQpIHtcbiAgICAgIHBvaW50ID0gcHJvamVjdFJvdGF0ZShwb2ludFswXSAqIGQzX3JhZGlhbnMsIHBvaW50WzFdICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gWyBwb2ludFswXSAqIGsgKyDOtHgsIM60eSAtIHBvaW50WzFdICogayBdO1xuICAgIH1cbiAgICBmdW5jdGlvbiBpbnZlcnQocG9pbnQpIHtcbiAgICAgIHBvaW50ID0gcHJvamVjdFJvdGF0ZS5pbnZlcnQoKHBvaW50WzBdIC0gzrR4KSAvIGssICjOtHkgLSBwb2ludFsxXSkgLyBrKTtcbiAgICAgIHJldHVybiBwb2ludCAmJiBbIHBvaW50WzBdICogZDNfZGVncmVlcywgcG9pbnRbMV0gKiBkM19kZWdyZWVzIF07XG4gICAgfVxuICAgIHByb2plY3Rpb24uc3RyZWFtID0gZnVuY3Rpb24ob3V0cHV0KSB7XG4gICAgICBpZiAoc3RyZWFtKSBzdHJlYW0udmFsaWQgPSBmYWxzZTtcbiAgICAgIHN0cmVhbSA9IGQzX2dlb19wcm9qZWN0aW9uUmFkaWFucyhwcmVjbGlwKHJvdGF0ZSwgcHJvamVjdFJlc2FtcGxlKHBvc3RjbGlwKG91dHB1dCkpKSk7XG4gICAgICBzdHJlYW0udmFsaWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIHN0cmVhbTtcbiAgICB9O1xuICAgIHByb2plY3Rpb24uY2xpcEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY2xpcEFuZ2xlO1xuICAgICAgcHJlY2xpcCA9IF8gPT0gbnVsbCA/IChjbGlwQW5nbGUgPSBfLCBkM19nZW9fY2xpcEFudGltZXJpZGlhbikgOiBkM19nZW9fY2xpcENpcmNsZSgoY2xpcEFuZ2xlID0gK18pICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gaW52YWxpZGF0ZSgpO1xuICAgIH07XG4gICAgcHJvamVjdGlvbi5jbGlwRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY2xpcEV4dGVudDtcbiAgICAgIGNsaXBFeHRlbnQgPSBfO1xuICAgICAgcG9zdGNsaXAgPSBfID8gZDNfZ2VvX2NsaXBFeHRlbnQoX1swXVswXSwgX1swXVsxXSwgX1sxXVswXSwgX1sxXVsxXSkgOiBkM19pZGVudGl0eTtcbiAgICAgIHJldHVybiBpbnZhbGlkYXRlKCk7XG4gICAgfTtcbiAgICBwcm9qZWN0aW9uLnNjYWxlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gaztcbiAgICAgIGsgPSArXztcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gICAgcHJvamVjdGlvbi50cmFuc2xhdGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIHgsIHkgXTtcbiAgICAgIHggPSArX1swXTtcbiAgICAgIHkgPSArX1sxXTtcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gICAgcHJvamVjdGlvbi5jZW50ZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIM67ICogZDNfZGVncmVlcywgz4YgKiBkM19kZWdyZWVzIF07XG4gICAgICDOuyA9IF9bMF0gJSAzNjAgKiBkM19yYWRpYW5zO1xuICAgICAgz4YgPSBfWzFdICUgMzYwICogZDNfcmFkaWFucztcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gICAgcHJvamVjdGlvbi5yb3RhdGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIM60zrsgKiBkM19kZWdyZWVzLCDOtM+GICogZDNfZGVncmVlcywgzrTOsyAqIGQzX2RlZ3JlZXMgXTtcbiAgICAgIM60zrsgPSBfWzBdICUgMzYwICogZDNfcmFkaWFucztcbiAgICAgIM60z4YgPSBfWzFdICUgMzYwICogZDNfcmFkaWFucztcbiAgICAgIM60zrMgPSBfLmxlbmd0aCA+IDIgPyBfWzJdICUgMzYwICogZDNfcmFkaWFucyA6IDA7XG4gICAgICByZXR1cm4gcmVzZXQoKTtcbiAgICB9O1xuICAgIGQzLnJlYmluZChwcm9qZWN0aW9uLCBwcm9qZWN0UmVzYW1wbGUsIFwicHJlY2lzaW9uXCIpO1xuICAgIGZ1bmN0aW9uIHJlc2V0KCkge1xuICAgICAgcHJvamVjdFJvdGF0ZSA9IGQzX2dlb19jb21wb3NlKHJvdGF0ZSA9IGQzX2dlb19yb3RhdGlvbijOtM67LCDOtM+GLCDOtM6zKSwgcHJvamVjdCk7XG4gICAgICB2YXIgY2VudGVyID0gcHJvamVjdCjOuywgz4YpO1xuICAgICAgzrR4ID0geCAtIGNlbnRlclswXSAqIGs7XG4gICAgICDOtHkgPSB5ICsgY2VudGVyWzFdICogaztcbiAgICAgIHJldHVybiBpbnZhbGlkYXRlKCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGludmFsaWRhdGUoKSB7XG4gICAgICBpZiAoc3RyZWFtKSBzdHJlYW0udmFsaWQgPSBmYWxzZSwgc3RyZWFtID0gbnVsbDtcbiAgICAgIHJldHVybiBwcm9qZWN0aW9uO1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBwcm9qZWN0ID0gcHJvamVjdEF0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICBwcm9qZWN0aW9uLmludmVydCA9IHByb2plY3QuaW52ZXJ0ICYmIGludmVydDtcbiAgICAgIHJldHVybiByZXNldCgpO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3Byb2plY3Rpb25SYWRpYW5zKHN0cmVhbSkge1xuICAgIHJldHVybiBkM19nZW9fdHJhbnNmb3JtUG9pbnQoc3RyZWFtLCBmdW5jdGlvbih4LCB5KSB7XG4gICAgICBzdHJlYW0ucG9pbnQoeCAqIGQzX3JhZGlhbnMsIHkgKiBkM19yYWRpYW5zKTtcbiAgICB9KTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fZXF1aXJlY3Rhbmd1bGFyKM67LCDPhikge1xuICAgIHJldHVybiBbIM67LCDPhiBdO1xuICB9XG4gIChkMy5nZW8uZXF1aXJlY3Rhbmd1bGFyID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0aW9uKGQzX2dlb19lcXVpcmVjdGFuZ3VsYXIpO1xuICB9KS5yYXcgPSBkM19nZW9fZXF1aXJlY3Rhbmd1bGFyLmludmVydCA9IGQzX2dlb19lcXVpcmVjdGFuZ3VsYXI7XG4gIGQzLmdlby5yb3RhdGlvbiA9IGZ1bmN0aW9uKHJvdGF0ZSkge1xuICAgIHJvdGF0ZSA9IGQzX2dlb19yb3RhdGlvbihyb3RhdGVbMF0gJSAzNjAgKiBkM19yYWRpYW5zLCByb3RhdGVbMV0gKiBkM19yYWRpYW5zLCByb3RhdGUubGVuZ3RoID4gMiA/IHJvdGF0ZVsyXSAqIGQzX3JhZGlhbnMgOiAwKTtcbiAgICBmdW5jdGlvbiBmb3J3YXJkKGNvb3JkaW5hdGVzKSB7XG4gICAgICBjb29yZGluYXRlcyA9IHJvdGF0ZShjb29yZGluYXRlc1swXSAqIGQzX3JhZGlhbnMsIGNvb3JkaW5hdGVzWzFdICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gY29vcmRpbmF0ZXNbMF0gKj0gZDNfZGVncmVlcywgY29vcmRpbmF0ZXNbMV0gKj0gZDNfZGVncmVlcywgY29vcmRpbmF0ZXM7XG4gICAgfVxuICAgIGZvcndhcmQuaW52ZXJ0ID0gZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHtcbiAgICAgIGNvb3JkaW5hdGVzID0gcm90YXRlLmludmVydChjb29yZGluYXRlc1swXSAqIGQzX3JhZGlhbnMsIGNvb3JkaW5hdGVzWzFdICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gY29vcmRpbmF0ZXNbMF0gKj0gZDNfZGVncmVlcywgY29vcmRpbmF0ZXNbMV0gKj0gZDNfZGVncmVlcywgY29vcmRpbmF0ZXM7XG4gICAgfTtcbiAgICByZXR1cm4gZm9yd2FyZDtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX2lkZW50aXR5Um90YXRpb24ozrssIM+GKSB7XG4gICAgcmV0dXJuIFsgzrsgPiDPgCA/IM67IC0gz4QgOiDOuyA8IC3PgCA/IM67ICsgz4QgOiDOuywgz4YgXTtcbiAgfVxuICBkM19nZW9faWRlbnRpdHlSb3RhdGlvbi5pbnZlcnQgPSBkM19nZW9fZXF1aXJlY3Rhbmd1bGFyO1xuICBmdW5jdGlvbiBkM19nZW9fcm90YXRpb24ozrTOuywgzrTPhiwgzrTOsykge1xuICAgIHJldHVybiDOtM67ID8gzrTPhiB8fCDOtM6zID8gZDNfZ2VvX2NvbXBvc2UoZDNfZ2VvX3JvdGF0aW9uzrsozrTOuyksIGQzX2dlb19yb3RhdGlvbs+GzrMozrTPhiwgzrTOsykpIDogZDNfZ2VvX3JvdGF0aW9uzrsozrTOuykgOiDOtM+GIHx8IM60zrMgPyBkM19nZW9fcm90YXRpb27Phs6zKM60z4YsIM60zrMpIDogZDNfZ2VvX2lkZW50aXR5Um90YXRpb247XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2ZvcndhcmRSb3RhdGlvbs67KM60zrspIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ozrssIM+GKSB7XG4gICAgICByZXR1cm4gzrsgKz0gzrTOuywgWyDOuyA+IM+AID8gzrsgLSDPhCA6IM67IDwgLc+AID8gzrsgKyDPhCA6IM67LCDPhiBdO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX3JvdGF0aW9uzrsozrTOuykge1xuICAgIHZhciByb3RhdGlvbiA9IGQzX2dlb19mb3J3YXJkUm90YXRpb27OuyjOtM67KTtcbiAgICByb3RhdGlvbi5pbnZlcnQgPSBkM19nZW9fZm9yd2FyZFJvdGF0aW9uzrsoLc60zrspO1xuICAgIHJldHVybiByb3RhdGlvbjtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcm90YXRpb27Phs6zKM60z4YsIM60zrMpIHtcbiAgICB2YXIgY29zzrTPhiA9IE1hdGguY29zKM60z4YpLCBzaW7OtM+GID0gTWF0aC5zaW4ozrTPhiksIGNvc860zrMgPSBNYXRoLmNvcyjOtM6zKSwgc2luzrTOsyA9IE1hdGguc2luKM60zrMpO1xuICAgIGZ1bmN0aW9uIHJvdGF0aW9uKM67LCDPhikge1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YpLCB4ID0gTWF0aC5jb3MozrspICogY29zz4YsIHkgPSBNYXRoLnNpbijOuykgKiBjb3PPhiwgeiA9IE1hdGguc2luKM+GKSwgayA9IHogKiBjb3POtM+GICsgeCAqIHNpbs60z4Y7XG4gICAgICByZXR1cm4gWyBNYXRoLmF0YW4yKHkgKiBjb3POtM6zIC0gayAqIHNpbs60zrMsIHggKiBjb3POtM+GIC0geiAqIHNpbs60z4YpLCBkM19hc2luKGsgKiBjb3POtM6zICsgeSAqIHNpbs60zrMpIF07XG4gICAgfVxuICAgIHJvdGF0aW9uLmludmVydCA9IGZ1bmN0aW9uKM67LCDPhikge1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YpLCB4ID0gTWF0aC5jb3MozrspICogY29zz4YsIHkgPSBNYXRoLnNpbijOuykgKiBjb3PPhiwgeiA9IE1hdGguc2luKM+GKSwgayA9IHogKiBjb3POtM6zIC0geSAqIHNpbs60zrM7XG4gICAgICByZXR1cm4gWyBNYXRoLmF0YW4yKHkgKiBjb3POtM6zICsgeiAqIHNpbs60zrMsIHggKiBjb3POtM+GICsgayAqIHNpbs60z4YpLCBkM19hc2luKGsgKiBjb3POtM+GIC0geCAqIHNpbs60z4YpIF07XG4gICAgfTtcbiAgICByZXR1cm4gcm90YXRpb247XG4gIH1cbiAgZDMuZ2VvLmNpcmNsZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBvcmlnaW4gPSBbIDAsIDAgXSwgYW5nbGUsIHByZWNpc2lvbiA9IDYsIGludGVycG9sYXRlO1xuICAgIGZ1bmN0aW9uIGNpcmNsZSgpIHtcbiAgICAgIHZhciBjZW50ZXIgPSB0eXBlb2Ygb3JpZ2luID09PSBcImZ1bmN0aW9uXCIgPyBvcmlnaW4uYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IG9yaWdpbiwgcm90YXRlID0gZDNfZ2VvX3JvdGF0aW9uKC1jZW50ZXJbMF0gKiBkM19yYWRpYW5zLCAtY2VudGVyWzFdICogZDNfcmFkaWFucywgMCkuaW52ZXJ0LCByaW5nID0gW107XG4gICAgICBpbnRlcnBvbGF0ZShudWxsLCBudWxsLCAxLCB7XG4gICAgICAgIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgICAgICAgcmluZy5wdXNoKHggPSByb3RhdGUoeCwgeSkpO1xuICAgICAgICAgIHhbMF0gKj0gZDNfZGVncmVlcywgeFsxXSAqPSBkM19kZWdyZWVzO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiUG9seWdvblwiLFxuICAgICAgICBjb29yZGluYXRlczogWyByaW5nIF1cbiAgICAgIH07XG4gICAgfVxuICAgIGNpcmNsZS5vcmlnaW4gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBvcmlnaW47XG4gICAgICBvcmlnaW4gPSB4O1xuICAgICAgcmV0dXJuIGNpcmNsZTtcbiAgICB9O1xuICAgIGNpcmNsZS5hbmdsZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGFuZ2xlO1xuICAgICAgaW50ZXJwb2xhdGUgPSBkM19nZW9fY2lyY2xlSW50ZXJwb2xhdGUoKGFuZ2xlID0gK3gpICogZDNfcmFkaWFucywgcHJlY2lzaW9uICogZDNfcmFkaWFucyk7XG4gICAgICByZXR1cm4gY2lyY2xlO1xuICAgIH07XG4gICAgY2lyY2xlLnByZWNpc2lvbiA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHByZWNpc2lvbjtcbiAgICAgIGludGVycG9sYXRlID0gZDNfZ2VvX2NpcmNsZUludGVycG9sYXRlKGFuZ2xlICogZDNfcmFkaWFucywgKHByZWNpc2lvbiA9ICtfKSAqIGQzX3JhZGlhbnMpO1xuICAgICAgcmV0dXJuIGNpcmNsZTtcbiAgICB9O1xuICAgIHJldHVybiBjaXJjbGUuYW5nbGUoOTApO1xuICB9O1xuICBmdW5jdGlvbiBkM19nZW9fY2lyY2xlSW50ZXJwb2xhdGUocmFkaXVzLCBwcmVjaXNpb24pIHtcbiAgICB2YXIgY3IgPSBNYXRoLmNvcyhyYWRpdXMpLCBzciA9IE1hdGguc2luKHJhZGl1cyk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGZyb20sIHRvLCBkaXJlY3Rpb24sIGxpc3RlbmVyKSB7XG4gICAgICB2YXIgc3RlcCA9IGRpcmVjdGlvbiAqIHByZWNpc2lvbjtcbiAgICAgIGlmIChmcm9tICE9IG51bGwpIHtcbiAgICAgICAgZnJvbSA9IGQzX2dlb19jaXJjbGVBbmdsZShjciwgZnJvbSk7XG4gICAgICAgIHRvID0gZDNfZ2VvX2NpcmNsZUFuZ2xlKGNyLCB0byk7XG4gICAgICAgIGlmIChkaXJlY3Rpb24gPiAwID8gZnJvbSA8IHRvIDogZnJvbSA+IHRvKSBmcm9tICs9IGRpcmVjdGlvbiAqIM+EO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZnJvbSA9IHJhZGl1cyArIGRpcmVjdGlvbiAqIM+EO1xuICAgICAgICB0byA9IHJhZGl1cyAtIC41ICogc3RlcDtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIHBvaW50LCB0ID0gZnJvbTsgZGlyZWN0aW9uID4gMCA/IHQgPiB0byA6IHQgPCB0bzsgdCAtPSBzdGVwKSB7XG4gICAgICAgIGxpc3RlbmVyLnBvaW50KChwb2ludCA9IGQzX2dlb19zcGhlcmljYWwoWyBjciwgLXNyICogTWF0aC5jb3ModCksIC1zciAqIE1hdGguc2luKHQpIF0pKVswXSwgcG9pbnRbMV0pO1xuICAgICAgfVxuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvX2NpcmNsZUFuZ2xlKGNyLCBwb2ludCkge1xuICAgIHZhciBhID0gZDNfZ2VvX2NhcnRlc2lhbihwb2ludCk7XG4gICAgYVswXSAtPSBjcjtcbiAgICBkM19nZW9fY2FydGVzaWFuTm9ybWFsaXplKGEpO1xuICAgIHZhciBhbmdsZSA9IGQzX2Fjb3MoLWFbMV0pO1xuICAgIHJldHVybiAoKC1hWzJdIDwgMCA/IC1hbmdsZSA6IGFuZ2xlKSArIDIgKiBNYXRoLlBJIC0gzrUpICUgKDIgKiBNYXRoLlBJKTtcbiAgfVxuICBkMy5nZW8uZGlzdGFuY2UgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIM6UzrsgPSAoYlswXSAtIGFbMF0pICogZDNfcmFkaWFucywgz4YwID0gYVsxXSAqIGQzX3JhZGlhbnMsIM+GMSA9IGJbMV0gKiBkM19yYWRpYW5zLCBzaW7OlM67ID0gTWF0aC5zaW4ozpTOuyksIGNvc86UzrsgPSBNYXRoLmNvcyjOlM67KSwgc2luz4YwID0gTWF0aC5zaW4oz4YwKSwgY29zz4YwID0gTWF0aC5jb3Moz4YwKSwgc2luz4YxID0gTWF0aC5zaW4oz4YxKSwgY29zz4YxID0gTWF0aC5jb3Moz4YxKSwgdDtcbiAgICByZXR1cm4gTWF0aC5hdGFuMihNYXRoLnNxcnQoKHQgPSBjb3PPhjEgKiBzaW7OlM67KSAqIHQgKyAodCA9IGNvc8+GMCAqIHNpbs+GMSAtIHNpbs+GMCAqIGNvc8+GMSAqIGNvc86UzrspICogdCksIHNpbs+GMCAqIHNpbs+GMSArIGNvc8+GMCAqIGNvc8+GMSAqIGNvc86UzrspO1xuICB9O1xuICBkMy5nZW8uZ3JhdGljdWxlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHgxLCB4MCwgWDEsIFgwLCB5MSwgeTAsIFkxLCBZMCwgZHggPSAxMCwgZHkgPSBkeCwgRFggPSA5MCwgRFkgPSAzNjAsIHgsIHksIFgsIFksIHByZWNpc2lvbiA9IDIuNTtcbiAgICBmdW5jdGlvbiBncmF0aWN1bGUoKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcIk11bHRpTGluZVN0cmluZ1wiLFxuICAgICAgICBjb29yZGluYXRlczogbGluZXMoKVxuICAgICAgfTtcbiAgICB9XG4gICAgZnVuY3Rpb24gbGluZXMoKSB7XG4gICAgICByZXR1cm4gZDMucmFuZ2UoTWF0aC5jZWlsKFgwIC8gRFgpICogRFgsIFgxLCBEWCkubWFwKFgpLmNvbmNhdChkMy5yYW5nZShNYXRoLmNlaWwoWTAgLyBEWSkgKiBEWSwgWTEsIERZKS5tYXAoWSkpLmNvbmNhdChkMy5yYW5nZShNYXRoLmNlaWwoeDAgLyBkeCkgKiBkeCwgeDEsIGR4KS5maWx0ZXIoZnVuY3Rpb24oeCkge1xuICAgICAgICByZXR1cm4gYWJzKHggJSBEWCkgPiDOtTtcbiAgICAgIH0pLm1hcCh4KSkuY29uY2F0KGQzLnJhbmdlKE1hdGguY2VpbCh5MCAvIGR5KSAqIGR5LCB5MSwgZHkpLmZpbHRlcihmdW5jdGlvbih5KSB7XG4gICAgICAgIHJldHVybiBhYnMoeSAlIERZKSA+IM61O1xuICAgICAgfSkubWFwKHkpKTtcbiAgICB9XG4gICAgZ3JhdGljdWxlLmxpbmVzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gbGluZXMoKS5tYXAoZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiBcIkxpbmVTdHJpbmdcIixcbiAgICAgICAgICBjb29yZGluYXRlczogY29vcmRpbmF0ZXNcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH07XG4gICAgZ3JhdGljdWxlLm91dGxpbmUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiUG9seWdvblwiLFxuICAgICAgICBjb29yZGluYXRlczogWyBYKFgwKS5jb25jYXQoWShZMSkuc2xpY2UoMSksIFgoWDEpLnJldmVyc2UoKS5zbGljZSgxKSwgWShZMCkucmV2ZXJzZSgpLnNsaWNlKDEpKSBdXG4gICAgICB9O1xuICAgIH07XG4gICAgZ3JhdGljdWxlLmV4dGVudCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGdyYXRpY3VsZS5taW5vckV4dGVudCgpO1xuICAgICAgcmV0dXJuIGdyYXRpY3VsZS5tYWpvckV4dGVudChfKS5taW5vckV4dGVudChfKTtcbiAgICB9O1xuICAgIGdyYXRpY3VsZS5tYWpvckV4dGVudCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIFsgWyBYMCwgWTAgXSwgWyBYMSwgWTEgXSBdO1xuICAgICAgWDAgPSArX1swXVswXSwgWDEgPSArX1sxXVswXTtcbiAgICAgIFkwID0gK19bMF1bMV0sIFkxID0gK19bMV1bMV07XG4gICAgICBpZiAoWDAgPiBYMSkgXyA9IFgwLCBYMCA9IFgxLCBYMSA9IF87XG4gICAgICBpZiAoWTAgPiBZMSkgXyA9IFkwLCBZMCA9IFkxLCBZMSA9IF87XG4gICAgICByZXR1cm4gZ3JhdGljdWxlLnByZWNpc2lvbihwcmVjaXNpb24pO1xuICAgIH07XG4gICAgZ3JhdGljdWxlLm1pbm9yRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gWyBbIHgwLCB5MCBdLCBbIHgxLCB5MSBdIF07XG4gICAgICB4MCA9ICtfWzBdWzBdLCB4MSA9ICtfWzFdWzBdO1xuICAgICAgeTAgPSArX1swXVsxXSwgeTEgPSArX1sxXVsxXTtcbiAgICAgIGlmICh4MCA+IHgxKSBfID0geDAsIHgwID0geDEsIHgxID0gXztcbiAgICAgIGlmICh5MCA+IHkxKSBfID0geTAsIHkwID0geTEsIHkxID0gXztcbiAgICAgIHJldHVybiBncmF0aWN1bGUucHJlY2lzaW9uKHByZWNpc2lvbik7XG4gICAgfTtcbiAgICBncmF0aWN1bGUuc3RlcCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGdyYXRpY3VsZS5taW5vclN0ZXAoKTtcbiAgICAgIHJldHVybiBncmF0aWN1bGUubWFqb3JTdGVwKF8pLm1pbm9yU3RlcChfKTtcbiAgICB9O1xuICAgIGdyYXRpY3VsZS5tYWpvclN0ZXAgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIERYLCBEWSBdO1xuICAgICAgRFggPSArX1swXSwgRFkgPSArX1sxXTtcbiAgICAgIHJldHVybiBncmF0aWN1bGU7XG4gICAgfTtcbiAgICBncmF0aWN1bGUubWlub3JTdGVwID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gWyBkeCwgZHkgXTtcbiAgICAgIGR4ID0gK19bMF0sIGR5ID0gK19bMV07XG4gICAgICByZXR1cm4gZ3JhdGljdWxlO1xuICAgIH07XG4gICAgZ3JhdGljdWxlLnByZWNpc2lvbiA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHByZWNpc2lvbjtcbiAgICAgIHByZWNpc2lvbiA9ICtfO1xuICAgICAgeCA9IGQzX2dlb19ncmF0aWN1bGVYKHkwLCB5MSwgOTApO1xuICAgICAgeSA9IGQzX2dlb19ncmF0aWN1bGVZKHgwLCB4MSwgcHJlY2lzaW9uKTtcbiAgICAgIFggPSBkM19nZW9fZ3JhdGljdWxlWChZMCwgWTEsIDkwKTtcbiAgICAgIFkgPSBkM19nZW9fZ3JhdGljdWxlWShYMCwgWDEsIHByZWNpc2lvbik7XG4gICAgICByZXR1cm4gZ3JhdGljdWxlO1xuICAgIH07XG4gICAgcmV0dXJuIGdyYXRpY3VsZS5tYWpvckV4dGVudChbIFsgLTE4MCwgLTkwICsgzrUgXSwgWyAxODAsIDkwIC0gzrUgXSBdKS5taW5vckV4dGVudChbIFsgLTE4MCwgLTgwIC0gzrUgXSwgWyAxODAsIDgwICsgzrUgXSBdKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX2dyYXRpY3VsZVgoeTAsIHkxLCBkeSkge1xuICAgIHZhciB5ID0gZDMucmFuZ2UoeTAsIHkxIC0gzrUsIGR5KS5jb25jYXQoeTEpO1xuICAgIHJldHVybiBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4geS5tYXAoZnVuY3Rpb24oeSkge1xuICAgICAgICByZXR1cm4gWyB4LCB5IF07XG4gICAgICB9KTtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19ncmF0aWN1bGVZKHgwLCB4MSwgZHgpIHtcbiAgICB2YXIgeCA9IGQzLnJhbmdlKHgwLCB4MSAtIM61LCBkeCkuY29uY2F0KHgxKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oeSkge1xuICAgICAgcmV0dXJuIHgubWFwKGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgcmV0dXJuIFsgeCwgeSBdO1xuICAgICAgfSk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19zb3VyY2UoZCkge1xuICAgIHJldHVybiBkLnNvdXJjZTtcbiAgfVxuICBmdW5jdGlvbiBkM190YXJnZXQoZCkge1xuICAgIHJldHVybiBkLnRhcmdldDtcbiAgfVxuICBkMy5nZW8uZ3JlYXRBcmMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc291cmNlID0gZDNfc291cmNlLCBzb3VyY2VfLCB0YXJnZXQgPSBkM190YXJnZXQsIHRhcmdldF87XG4gICAgZnVuY3Rpb24gZ3JlYXRBcmMoKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcIkxpbmVTdHJpbmdcIixcbiAgICAgICAgY29vcmRpbmF0ZXM6IFsgc291cmNlXyB8fCBzb3VyY2UuYXBwbHkodGhpcywgYXJndW1lbnRzKSwgdGFyZ2V0XyB8fCB0YXJnZXQuYXBwbHkodGhpcywgYXJndW1lbnRzKSBdXG4gICAgICB9O1xuICAgIH1cbiAgICBncmVhdEFyYy5kaXN0YW5jZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzLmdlby5kaXN0YW5jZShzb3VyY2VfIHx8IHNvdXJjZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCB0YXJnZXRfIHx8IHRhcmdldC5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTtcbiAgICB9O1xuICAgIGdyZWF0QXJjLnNvdXJjZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNvdXJjZTtcbiAgICAgIHNvdXJjZSA9IF8sIHNvdXJjZV8gPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gbnVsbCA6IF87XG4gICAgICByZXR1cm4gZ3JlYXRBcmM7XG4gICAgfTtcbiAgICBncmVhdEFyYy50YXJnZXQgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB0YXJnZXQ7XG4gICAgICB0YXJnZXQgPSBfLCB0YXJnZXRfID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IG51bGwgOiBfO1xuICAgICAgcmV0dXJuIGdyZWF0QXJjO1xuICAgIH07XG4gICAgZ3JlYXRBcmMucHJlY2lzaW9uID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IGdyZWF0QXJjIDogMDtcbiAgICB9O1xuICAgIHJldHVybiBncmVhdEFyYztcbiAgfTtcbiAgZDMuZ2VvLmludGVycG9sYXRlID0gZnVuY3Rpb24oc291cmNlLCB0YXJnZXQpIHtcbiAgICByZXR1cm4gZDNfZ2VvX2ludGVycG9sYXRlKHNvdXJjZVswXSAqIGQzX3JhZGlhbnMsIHNvdXJjZVsxXSAqIGQzX3JhZGlhbnMsIHRhcmdldFswXSAqIGQzX3JhZGlhbnMsIHRhcmdldFsxXSAqIGQzX3JhZGlhbnMpO1xuICB9O1xuICBmdW5jdGlvbiBkM19nZW9faW50ZXJwb2xhdGUoeDAsIHkwLCB4MSwgeTEpIHtcbiAgICB2YXIgY3kwID0gTWF0aC5jb3MoeTApLCBzeTAgPSBNYXRoLnNpbih5MCksIGN5MSA9IE1hdGguY29zKHkxKSwgc3kxID0gTWF0aC5zaW4oeTEpLCBreDAgPSBjeTAgKiBNYXRoLmNvcyh4MCksIGt5MCA9IGN5MCAqIE1hdGguc2luKHgwKSwga3gxID0gY3kxICogTWF0aC5jb3MoeDEpLCBreTEgPSBjeTEgKiBNYXRoLnNpbih4MSksIGQgPSAyICogTWF0aC5hc2luKE1hdGguc3FydChkM19oYXZlcnNpbih5MSAtIHkwKSArIGN5MCAqIGN5MSAqIGQzX2hhdmVyc2luKHgxIC0geDApKSksIGsgPSAxIC8gTWF0aC5zaW4oZCk7XG4gICAgdmFyIGludGVycG9sYXRlID0gZCA/IGZ1bmN0aW9uKHQpIHtcbiAgICAgIHZhciBCID0gTWF0aC5zaW4odCAqPSBkKSAqIGssIEEgPSBNYXRoLnNpbihkIC0gdCkgKiBrLCB4ID0gQSAqIGt4MCArIEIgKiBreDEsIHkgPSBBICoga3kwICsgQiAqIGt5MSwgeiA9IEEgKiBzeTAgKyBCICogc3kxO1xuICAgICAgcmV0dXJuIFsgTWF0aC5hdGFuMih5LCB4KSAqIGQzX2RlZ3JlZXMsIE1hdGguYXRhbjIoeiwgTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkpKSAqIGQzX2RlZ3JlZXMgXTtcbiAgICB9IDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gWyB4MCAqIGQzX2RlZ3JlZXMsIHkwICogZDNfZGVncmVlcyBdO1xuICAgIH07XG4gICAgaW50ZXJwb2xhdGUuZGlzdGFuY2UgPSBkO1xuICAgIHJldHVybiBpbnRlcnBvbGF0ZTtcbiAgfVxuICBkMy5nZW8ubGVuZ3RoID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgZDNfZ2VvX2xlbmd0aFN1bSA9IDA7XG4gICAgZDMuZ2VvLnN0cmVhbShvYmplY3QsIGQzX2dlb19sZW5ndGgpO1xuICAgIHJldHVybiBkM19nZW9fbGVuZ3RoU3VtO1xuICB9O1xuICB2YXIgZDNfZ2VvX2xlbmd0aFN1bTtcbiAgdmFyIGQzX2dlb19sZW5ndGggPSB7XG4gICAgc3BoZXJlOiBkM19ub29wLFxuICAgIHBvaW50OiBkM19ub29wLFxuICAgIGxpbmVTdGFydDogZDNfZ2VvX2xlbmd0aExpbmVTdGFydCxcbiAgICBsaW5lRW5kOiBkM19ub29wLFxuICAgIHBvbHlnb25TdGFydDogZDNfbm9vcCxcbiAgICBwb2x5Z29uRW5kOiBkM19ub29wXG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19sZW5ndGhMaW5lU3RhcnQoKSB7XG4gICAgdmFyIM67MCwgc2luz4YwLCBjb3PPhjA7XG4gICAgZDNfZ2VvX2xlbmd0aC5wb2ludCA9IGZ1bmN0aW9uKM67LCDPhikge1xuICAgICAgzrswID0gzrsgKiBkM19yYWRpYW5zLCBzaW7PhjAgPSBNYXRoLnNpbijPhiAqPSBkM19yYWRpYW5zKSwgY29zz4YwID0gTWF0aC5jb3Moz4YpO1xuICAgICAgZDNfZ2VvX2xlbmd0aC5wb2ludCA9IG5leHRQb2ludDtcbiAgICB9O1xuICAgIGQzX2dlb19sZW5ndGgubGluZUVuZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgZDNfZ2VvX2xlbmd0aC5wb2ludCA9IGQzX2dlb19sZW5ndGgubGluZUVuZCA9IGQzX25vb3A7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBuZXh0UG9pbnQozrssIM+GKSB7XG4gICAgICB2YXIgc2luz4YgPSBNYXRoLnNpbijPhiAqPSBkM19yYWRpYW5zKSwgY29zz4YgPSBNYXRoLmNvcyjPhiksIHQgPSBhYnMoKM67ICo9IGQzX3JhZGlhbnMpIC0gzrswKSwgY29zzpTOuyA9IE1hdGguY29zKHQpO1xuICAgICAgZDNfZ2VvX2xlbmd0aFN1bSArPSBNYXRoLmF0YW4yKE1hdGguc3FydCgodCA9IGNvc8+GICogTWF0aC5zaW4odCkpICogdCArICh0ID0gY29zz4YwICogc2luz4YgLSBzaW7PhjAgKiBjb3PPhiAqIGNvc86UzrspICogdCksIHNpbs+GMCAqIHNpbs+GICsgY29zz4YwICogY29zz4YgKiBjb3POlM67KTtcbiAgICAgIM67MCA9IM67LCBzaW7PhjAgPSBzaW7PhiwgY29zz4YwID0gY29zz4Y7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb19hemltdXRoYWwoc2NhbGUsIGFuZ2xlKSB7XG4gICAgZnVuY3Rpb24gYXppbXV0aGFsKM67LCDPhikge1xuICAgICAgdmFyIGNvc867ID0gTWF0aC5jb3MozrspLCBjb3PPhiA9IE1hdGguY29zKM+GKSwgayA9IHNjYWxlKGNvc867ICogY29zz4YpO1xuICAgICAgcmV0dXJuIFsgayAqIGNvc8+GICogTWF0aC5zaW4ozrspLCBrICogTWF0aC5zaW4oz4YpIF07XG4gICAgfVxuICAgIGF6aW11dGhhbC5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgICB2YXIgz4EgPSBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSksIGMgPSBhbmdsZSjPgSksIHNpbmMgPSBNYXRoLnNpbihjKSwgY29zYyA9IE1hdGguY29zKGMpO1xuICAgICAgcmV0dXJuIFsgTWF0aC5hdGFuMih4ICogc2luYywgz4EgKiBjb3NjKSwgTWF0aC5hc2luKM+BICYmIHkgKiBzaW5jIC8gz4EpIF07XG4gICAgfTtcbiAgICByZXR1cm4gYXppbXV0aGFsO1xuICB9XG4gIHZhciBkM19nZW9fYXppbXV0aGFsRXF1YWxBcmVhID0gZDNfZ2VvX2F6aW11dGhhbChmdW5jdGlvbihjb3POu2Nvc8+GKSB7XG4gICAgcmV0dXJuIE1hdGguc3FydCgyIC8gKDEgKyBjb3POu2Nvc8+GKSk7XG4gIH0sIGZ1bmN0aW9uKM+BKSB7XG4gICAgcmV0dXJuIDIgKiBNYXRoLmFzaW4oz4EgLyAyKTtcbiAgfSk7XG4gIChkMy5nZW8uYXppbXV0aGFsRXF1YWxBcmVhID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0aW9uKGQzX2dlb19hemltdXRoYWxFcXVhbEFyZWEpO1xuICB9KS5yYXcgPSBkM19nZW9fYXppbXV0aGFsRXF1YWxBcmVhO1xuICB2YXIgZDNfZ2VvX2F6aW11dGhhbEVxdWlkaXN0YW50ID0gZDNfZ2VvX2F6aW11dGhhbChmdW5jdGlvbihjb3POu2Nvc8+GKSB7XG4gICAgdmFyIGMgPSBNYXRoLmFjb3MoY29zzrtjb3PPhik7XG4gICAgcmV0dXJuIGMgJiYgYyAvIE1hdGguc2luKGMpO1xuICB9LCBkM19pZGVudGl0eSk7XG4gIChkMy5nZW8uYXppbXV0aGFsRXF1aWRpc3RhbnQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfZ2VvX3Byb2plY3Rpb24oZDNfZ2VvX2F6aW11dGhhbEVxdWlkaXN0YW50KTtcbiAgfSkucmF3ID0gZDNfZ2VvX2F6aW11dGhhbEVxdWlkaXN0YW50O1xuICBmdW5jdGlvbiBkM19nZW9fY29uaWNDb25mb3JtYWwoz4YwLCDPhjEpIHtcbiAgICB2YXIgY29zz4YwID0gTWF0aC5jb3Moz4YwKSwgdCA9IGZ1bmN0aW9uKM+GKSB7XG4gICAgICByZXR1cm4gTWF0aC50YW4oz4AgLyA0ICsgz4YgLyAyKTtcbiAgICB9LCBuID0gz4YwID09PSDPhjEgPyBNYXRoLnNpbijPhjApIDogTWF0aC5sb2coY29zz4YwIC8gTWF0aC5jb3Moz4YxKSkgLyBNYXRoLmxvZyh0KM+GMSkgLyB0KM+GMCkpLCBGID0gY29zz4YwICogTWF0aC5wb3codCjPhjApLCBuKSAvIG47XG4gICAgaWYgKCFuKSByZXR1cm4gZDNfZ2VvX21lcmNhdG9yO1xuICAgIGZ1bmN0aW9uIGZvcndhcmQozrssIM+GKSB7XG4gICAgICBpZiAoRiA+IDApIHtcbiAgICAgICAgaWYgKM+GIDwgLWhhbGbPgCArIM61KSDPhiA9IC1oYWxmz4AgKyDOtTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICjPhiA+IGhhbGbPgCAtIM61KSDPhiA9IGhhbGbPgCAtIM61O1xuICAgICAgfVxuICAgICAgdmFyIM+BID0gRiAvIE1hdGgucG93KHQoz4YpLCBuKTtcbiAgICAgIHJldHVybiBbIM+BICogTWF0aC5zaW4obiAqIM67KSwgRiAtIM+BICogTWF0aC5jb3MobiAqIM67KSBdO1xuICAgIH1cbiAgICBmb3J3YXJkLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciDPgTBfeSA9IEYgLSB5LCDPgSA9IGQzX3NnbihuKSAqIE1hdGguc3FydCh4ICogeCArIM+BMF95ICogz4EwX3kpO1xuICAgICAgcmV0dXJuIFsgTWF0aC5hdGFuMih4LCDPgTBfeSkgLyBuLCAyICogTWF0aC5hdGFuKE1hdGgucG93KEYgLyDPgSwgMSAvIG4pKSAtIGhhbGbPgCBdO1xuICAgIH07XG4gICAgcmV0dXJuIGZvcndhcmQ7XG4gIH1cbiAgKGQzLmdlby5jb25pY0NvbmZvcm1hbCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19nZW9fY29uaWMoZDNfZ2VvX2NvbmljQ29uZm9ybWFsKTtcbiAgfSkucmF3ID0gZDNfZ2VvX2NvbmljQ29uZm9ybWFsO1xuICBmdW5jdGlvbiBkM19nZW9fY29uaWNFcXVpZGlzdGFudCjPhjAsIM+GMSkge1xuICAgIHZhciBjb3PPhjAgPSBNYXRoLmNvcyjPhjApLCBuID0gz4YwID09PSDPhjEgPyBNYXRoLnNpbijPhjApIDogKGNvc8+GMCAtIE1hdGguY29zKM+GMSkpIC8gKM+GMSAtIM+GMCksIEcgPSBjb3PPhjAgLyBuICsgz4YwO1xuICAgIGlmIChhYnMobikgPCDOtSkgcmV0dXJuIGQzX2dlb19lcXVpcmVjdGFuZ3VsYXI7XG4gICAgZnVuY3Rpb24gZm9yd2FyZCjOuywgz4YpIHtcbiAgICAgIHZhciDPgSA9IEcgLSDPhjtcbiAgICAgIHJldHVybiBbIM+BICogTWF0aC5zaW4obiAqIM67KSwgRyAtIM+BICogTWF0aC5jb3MobiAqIM67KSBdO1xuICAgIH1cbiAgICBmb3J3YXJkLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciDPgTBfeSA9IEcgLSB5O1xuICAgICAgcmV0dXJuIFsgTWF0aC5hdGFuMih4LCDPgTBfeSkgLyBuLCBHIC0gZDNfc2duKG4pICogTWF0aC5zcXJ0KHggKiB4ICsgz4EwX3kgKiDPgTBfeSkgXTtcbiAgICB9O1xuICAgIHJldHVybiBmb3J3YXJkO1xuICB9XG4gIChkMy5nZW8uY29uaWNFcXVpZGlzdGFudCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19nZW9fY29uaWMoZDNfZ2VvX2NvbmljRXF1aWRpc3RhbnQpO1xuICB9KS5yYXcgPSBkM19nZW9fY29uaWNFcXVpZGlzdGFudDtcbiAgdmFyIGQzX2dlb19nbm9tb25pYyA9IGQzX2dlb19hemltdXRoYWwoZnVuY3Rpb24oY29zzrtjb3PPhikge1xuICAgIHJldHVybiAxIC8gY29zzrtjb3PPhjtcbiAgfSwgTWF0aC5hdGFuKTtcbiAgKGQzLmdlby5nbm9tb25pYyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19nZW9fcHJvamVjdGlvbihkM19nZW9fZ25vbW9uaWMpO1xuICB9KS5yYXcgPSBkM19nZW9fZ25vbW9uaWM7XG4gIGZ1bmN0aW9uIGQzX2dlb19tZXJjYXRvcijOuywgz4YpIHtcbiAgICByZXR1cm4gWyDOuywgTWF0aC5sb2coTWF0aC50YW4oz4AgLyA0ICsgz4YgLyAyKSkgXTtcbiAgfVxuICBkM19nZW9fbWVyY2F0b3IuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHJldHVybiBbIHgsIDIgKiBNYXRoLmF0YW4oTWF0aC5leHAoeSkpIC0gaGFsZs+AIF07XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb19tZXJjYXRvclByb2plY3Rpb24ocHJvamVjdCkge1xuICAgIHZhciBtID0gZDNfZ2VvX3Byb2plY3Rpb24ocHJvamVjdCksIHNjYWxlID0gbS5zY2FsZSwgdHJhbnNsYXRlID0gbS50cmFuc2xhdGUsIGNsaXBFeHRlbnQgPSBtLmNsaXBFeHRlbnQsIGNsaXBBdXRvO1xuICAgIG0uc2NhbGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2ID0gc2NhbGUuYXBwbHkobSwgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiB2ID09PSBtID8gY2xpcEF1dG8gPyBtLmNsaXBFeHRlbnQobnVsbCkgOiBtIDogdjtcbiAgICB9O1xuICAgIG0udHJhbnNsYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdiA9IHRyYW5zbGF0ZS5hcHBseShtLCBhcmd1bWVudHMpO1xuICAgICAgcmV0dXJuIHYgPT09IG0gPyBjbGlwQXV0byA/IG0uY2xpcEV4dGVudChudWxsKSA6IG0gOiB2O1xuICAgIH07XG4gICAgbS5jbGlwRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgdmFyIHYgPSBjbGlwRXh0ZW50LmFwcGx5KG0sIGFyZ3VtZW50cyk7XG4gICAgICBpZiAodiA9PT0gbSkge1xuICAgICAgICBpZiAoY2xpcEF1dG8gPSBfID09IG51bGwpIHtcbiAgICAgICAgICB2YXIgayA9IM+AICogc2NhbGUoKSwgdCA9IHRyYW5zbGF0ZSgpO1xuICAgICAgICAgIGNsaXBFeHRlbnQoWyBbIHRbMF0gLSBrLCB0WzFdIC0gayBdLCBbIHRbMF0gKyBrLCB0WzFdICsgayBdIF0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGNsaXBBdXRvKSB7XG4gICAgICAgIHYgPSBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHY7XG4gICAgfTtcbiAgICByZXR1cm4gbS5jbGlwRXh0ZW50KG51bGwpO1xuICB9XG4gIChkMy5nZW8ubWVyY2F0b3IgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfZ2VvX21lcmNhdG9yUHJvamVjdGlvbihkM19nZW9fbWVyY2F0b3IpO1xuICB9KS5yYXcgPSBkM19nZW9fbWVyY2F0b3I7XG4gIHZhciBkM19nZW9fb3J0aG9ncmFwaGljID0gZDNfZ2VvX2F6aW11dGhhbChmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gMTtcbiAgfSwgTWF0aC5hc2luKTtcbiAgKGQzLmdlby5vcnRob2dyYXBoaWMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfZ2VvX3Byb2plY3Rpb24oZDNfZ2VvX29ydGhvZ3JhcGhpYyk7XG4gIH0pLnJhdyA9IGQzX2dlb19vcnRob2dyYXBoaWM7XG4gIHZhciBkM19nZW9fc3RlcmVvZ3JhcGhpYyA9IGQzX2dlb19hemltdXRoYWwoZnVuY3Rpb24oY29zzrtjb3PPhikge1xuICAgIHJldHVybiAxIC8gKDEgKyBjb3POu2Nvc8+GKTtcbiAgfSwgZnVuY3Rpb24oz4EpIHtcbiAgICByZXR1cm4gMiAqIE1hdGguYXRhbijPgSk7XG4gIH0pO1xuICAoZDMuZ2VvLnN0ZXJlb2dyYXBoaWMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfZ2VvX3Byb2plY3Rpb24oZDNfZ2VvX3N0ZXJlb2dyYXBoaWMpO1xuICB9KS5yYXcgPSBkM19nZW9fc3RlcmVvZ3JhcGhpYztcbiAgZnVuY3Rpb24gZDNfZ2VvX3RyYW5zdmVyc2VNZXJjYXRvcijOuywgz4YpIHtcbiAgICByZXR1cm4gWyBNYXRoLmxvZyhNYXRoLnRhbijPgCAvIDQgKyDPhiAvIDIpKSwgLc67IF07XG4gIH1cbiAgZDNfZ2VvX3RyYW5zdmVyc2VNZXJjYXRvci5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgcmV0dXJuIFsgLXksIDIgKiBNYXRoLmF0YW4oTWF0aC5leHAoeCkpIC0gaGFsZs+AIF07XG4gIH07XG4gIChkMy5nZW8udHJhbnN2ZXJzZU1lcmNhdG9yID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHByb2plY3Rpb24gPSBkM19nZW9fbWVyY2F0b3JQcm9qZWN0aW9uKGQzX2dlb190cmFuc3ZlcnNlTWVyY2F0b3IpLCBjZW50ZXIgPSBwcm9qZWN0aW9uLmNlbnRlciwgcm90YXRlID0gcHJvamVjdGlvbi5yb3RhdGU7XG4gICAgcHJvamVjdGlvbi5jZW50ZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gXyA/IGNlbnRlcihbIC1fWzFdLCBfWzBdIF0pIDogKF8gPSBjZW50ZXIoKSwgWyBfWzFdLCAtX1swXSBdKTtcbiAgICB9O1xuICAgIHByb2plY3Rpb24ucm90YXRlID0gZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIF8gPyByb3RhdGUoWyBfWzBdLCBfWzFdLCBfLmxlbmd0aCA+IDIgPyBfWzJdICsgOTAgOiA5MCBdKSA6IChfID0gcm90YXRlKCksIFxuICAgICAgWyBfWzBdLCBfWzFdLCBfWzJdIC0gOTAgXSk7XG4gICAgfTtcbiAgICByZXR1cm4gcm90YXRlKFsgMCwgMCwgOTAgXSk7XG4gIH0pLnJhdyA9IGQzX2dlb190cmFuc3ZlcnNlTWVyY2F0b3I7XG4gIGQzLmdlb20gPSB7fTtcbiAgZnVuY3Rpb24gZDNfZ2VvbV9wb2ludFgoZCkge1xuICAgIHJldHVybiBkWzBdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fcG9pbnRZKGQpIHtcbiAgICByZXR1cm4gZFsxXTtcbiAgfVxuICBkMy5nZW9tLmh1bGwgPSBmdW5jdGlvbih2ZXJ0aWNlcykge1xuICAgIHZhciB4ID0gZDNfZ2VvbV9wb2ludFgsIHkgPSBkM19nZW9tX3BvaW50WTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGh1bGwodmVydGljZXMpO1xuICAgIGZ1bmN0aW9uIGh1bGwoZGF0YSkge1xuICAgICAgaWYgKGRhdGEubGVuZ3RoIDwgMykgcmV0dXJuIFtdO1xuICAgICAgdmFyIGZ4ID0gZDNfZnVuY3Rvcih4KSwgZnkgPSBkM19mdW5jdG9yKHkpLCBpLCBuID0gZGF0YS5sZW5ndGgsIHBvaW50cyA9IFtdLCBmbGlwcGVkUG9pbnRzID0gW107XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIHBvaW50cy5wdXNoKFsgK2Z4LmNhbGwodGhpcywgZGF0YVtpXSwgaSksICtmeS5jYWxsKHRoaXMsIGRhdGFbaV0sIGkpLCBpIF0pO1xuICAgICAgfVxuICAgICAgcG9pbnRzLnNvcnQoZDNfZ2VvbV9odWxsT3JkZXIpO1xuICAgICAgZm9yIChpID0gMDsgaSA8IG47IGkrKykgZmxpcHBlZFBvaW50cy5wdXNoKFsgcG9pbnRzW2ldWzBdLCAtcG9pbnRzW2ldWzFdIF0pO1xuICAgICAgdmFyIHVwcGVyID0gZDNfZ2VvbV9odWxsVXBwZXIocG9pbnRzKSwgbG93ZXIgPSBkM19nZW9tX2h1bGxVcHBlcihmbGlwcGVkUG9pbnRzKTtcbiAgICAgIHZhciBza2lwTGVmdCA9IGxvd2VyWzBdID09PSB1cHBlclswXSwgc2tpcFJpZ2h0ID0gbG93ZXJbbG93ZXIubGVuZ3RoIC0gMV0gPT09IHVwcGVyW3VwcGVyLmxlbmd0aCAtIDFdLCBwb2x5Z29uID0gW107XG4gICAgICBmb3IgKGkgPSB1cHBlci5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgcG9seWdvbi5wdXNoKGRhdGFbcG9pbnRzW3VwcGVyW2ldXVsyXV0pO1xuICAgICAgZm9yIChpID0gK3NraXBMZWZ0OyBpIDwgbG93ZXIubGVuZ3RoIC0gc2tpcFJpZ2h0OyArK2kpIHBvbHlnb24ucHVzaChkYXRhW3BvaW50c1tsb3dlcltpXV1bMl1dKTtcbiAgICAgIHJldHVybiBwb2x5Z29uO1xuICAgIH1cbiAgICBodWxsLnggPSBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4ID0gXywgaHVsbCkgOiB4O1xuICAgIH07XG4gICAgaHVsbC55ID0gZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSA9IF8sIGh1bGwpIDogeTtcbiAgICB9O1xuICAgIHJldHVybiBodWxsO1xuICB9O1xuICBmdW5jdGlvbiBkM19nZW9tX2h1bGxVcHBlcihwb2ludHMpIHtcbiAgICB2YXIgbiA9IHBvaW50cy5sZW5ndGgsIGh1bGwgPSBbIDAsIDEgXSwgaHMgPSAyO1xuICAgIGZvciAodmFyIGkgPSAyOyBpIDwgbjsgaSsrKSB7XG4gICAgICB3aGlsZSAoaHMgPiAxICYmIGQzX2Nyb3NzMmQocG9pbnRzW2h1bGxbaHMgLSAyXV0sIHBvaW50c1todWxsW2hzIC0gMV1dLCBwb2ludHNbaV0pIDw9IDApIC0taHM7XG4gICAgICBodWxsW2hzKytdID0gaTtcbiAgICB9XG4gICAgcmV0dXJuIGh1bGwuc2xpY2UoMCwgaHMpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21faHVsbE9yZGVyKGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAtIGJbMF0gfHwgYVsxXSAtIGJbMV07XG4gIH1cbiAgZDMuZ2VvbS5wb2x5Z29uID0gZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHtcbiAgICBkM19zdWJjbGFzcyhjb29yZGluYXRlcywgZDNfZ2VvbV9wb2x5Z29uUHJvdG90eXBlKTtcbiAgICByZXR1cm4gY29vcmRpbmF0ZXM7XG4gIH07XG4gIHZhciBkM19nZW9tX3BvbHlnb25Qcm90b3R5cGUgPSBkMy5nZW9tLnBvbHlnb24ucHJvdG90eXBlID0gW107XG4gIGQzX2dlb21fcG9seWdvblByb3RvdHlwZS5hcmVhID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IHRoaXMubGVuZ3RoLCBhLCBiID0gdGhpc1tuIC0gMV0sIGFyZWEgPSAwO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBhID0gYjtcbiAgICAgIGIgPSB0aGlzW2ldO1xuICAgICAgYXJlYSArPSBhWzFdICogYlswXSAtIGFbMF0gKiBiWzFdO1xuICAgIH1cbiAgICByZXR1cm4gYXJlYSAqIC41O1xuICB9O1xuICBkM19nZW9tX3BvbHlnb25Qcm90b3R5cGUuY2VudHJvaWQgPSBmdW5jdGlvbihrKSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IHRoaXMubGVuZ3RoLCB4ID0gMCwgeSA9IDAsIGEsIGIgPSB0aGlzW24gLSAxXSwgYztcbiAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIGsgPSAtMSAvICg2ICogdGhpcy5hcmVhKCkpO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBhID0gYjtcbiAgICAgIGIgPSB0aGlzW2ldO1xuICAgICAgYyA9IGFbMF0gKiBiWzFdIC0gYlswXSAqIGFbMV07XG4gICAgICB4ICs9IChhWzBdICsgYlswXSkgKiBjO1xuICAgICAgeSArPSAoYVsxXSArIGJbMV0pICogYztcbiAgICB9XG4gICAgcmV0dXJuIFsgeCAqIGssIHkgKiBrIF07XG4gIH07XG4gIGQzX2dlb21fcG9seWdvblByb3RvdHlwZS5jbGlwID0gZnVuY3Rpb24oc3ViamVjdCkge1xuICAgIHZhciBpbnB1dCwgY2xvc2VkID0gZDNfZ2VvbV9wb2x5Z29uQ2xvc2VkKHN1YmplY3QpLCBpID0gLTEsIG4gPSB0aGlzLmxlbmd0aCAtIGQzX2dlb21fcG9seWdvbkNsb3NlZCh0aGlzKSwgaiwgbSwgYSA9IHRoaXNbbiAtIDFdLCBiLCBjLCBkO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpbnB1dCA9IHN1YmplY3Quc2xpY2UoKTtcbiAgICAgIHN1YmplY3QubGVuZ3RoID0gMDtcbiAgICAgIGIgPSB0aGlzW2ldO1xuICAgICAgYyA9IGlucHV0WyhtID0gaW5wdXQubGVuZ3RoIC0gY2xvc2VkKSAtIDFdO1xuICAgICAgaiA9IC0xO1xuICAgICAgd2hpbGUgKCsraiA8IG0pIHtcbiAgICAgICAgZCA9IGlucHV0W2pdO1xuICAgICAgICBpZiAoZDNfZ2VvbV9wb2x5Z29uSW5zaWRlKGQsIGEsIGIpKSB7XG4gICAgICAgICAgaWYgKCFkM19nZW9tX3BvbHlnb25JbnNpZGUoYywgYSwgYikpIHtcbiAgICAgICAgICAgIHN1YmplY3QucHVzaChkM19nZW9tX3BvbHlnb25JbnRlcnNlY3QoYywgZCwgYSwgYikpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzdWJqZWN0LnB1c2goZCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZDNfZ2VvbV9wb2x5Z29uSW5zaWRlKGMsIGEsIGIpKSB7XG4gICAgICAgICAgc3ViamVjdC5wdXNoKGQzX2dlb21fcG9seWdvbkludGVyc2VjdChjLCBkLCBhLCBiKSk7XG4gICAgICAgIH1cbiAgICAgICAgYyA9IGQ7XG4gICAgICB9XG4gICAgICBpZiAoY2xvc2VkKSBzdWJqZWN0LnB1c2goc3ViamVjdFswXSk7XG4gICAgICBhID0gYjtcbiAgICB9XG4gICAgcmV0dXJuIHN1YmplY3Q7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb21fcG9seWdvbkluc2lkZShwLCBhLCBiKSB7XG4gICAgcmV0dXJuIChiWzBdIC0gYVswXSkgKiAocFsxXSAtIGFbMV0pIDwgKGJbMV0gLSBhWzFdKSAqIChwWzBdIC0gYVswXSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9wb2x5Z29uSW50ZXJzZWN0KGMsIGQsIGEsIGIpIHtcbiAgICB2YXIgeDEgPSBjWzBdLCB4MyA9IGFbMF0sIHgyMSA9IGRbMF0gLSB4MSwgeDQzID0gYlswXSAtIHgzLCB5MSA9IGNbMV0sIHkzID0gYVsxXSwgeTIxID0gZFsxXSAtIHkxLCB5NDMgPSBiWzFdIC0geTMsIHVhID0gKHg0MyAqICh5MSAtIHkzKSAtIHk0MyAqICh4MSAtIHgzKSkgLyAoeTQzICogeDIxIC0geDQzICogeTIxKTtcbiAgICByZXR1cm4gWyB4MSArIHVhICogeDIxLCB5MSArIHVhICogeTIxIF07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9wb2x5Z29uQ2xvc2VkKGNvb3JkaW5hdGVzKSB7XG4gICAgdmFyIGEgPSBjb29yZGluYXRlc1swXSwgYiA9IGNvb3JkaW5hdGVzW2Nvb3JkaW5hdGVzLmxlbmd0aCAtIDFdO1xuICAgIHJldHVybiAhKGFbMF0gLSBiWzBdIHx8IGFbMV0gLSBiWzFdKTtcbiAgfVxuICB2YXIgZDNfZ2VvbV92b3Jvbm9pRWRnZXMsIGQzX2dlb21fdm9yb25vaUNlbGxzLCBkM19nZW9tX3Zvcm9ub2lCZWFjaGVzLCBkM19nZW9tX3Zvcm9ub2lCZWFjaFBvb2wgPSBbXSwgZDNfZ2VvbV92b3Jvbm9pRmlyc3RDaXJjbGUsIGQzX2dlb21fdm9yb25vaUNpcmNsZXMsIGQzX2dlb21fdm9yb25vaUNpcmNsZVBvb2wgPSBbXTtcbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pQmVhY2goKSB7XG4gICAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tOb2RlKHRoaXMpO1xuICAgIHRoaXMuZWRnZSA9IHRoaXMuc2l0ZSA9IHRoaXMuY2lyY2xlID0gbnVsbDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lDcmVhdGVCZWFjaChzaXRlKSB7XG4gICAgdmFyIGJlYWNoID0gZDNfZ2VvbV92b3Jvbm9pQmVhY2hQb29sLnBvcCgpIHx8IG5ldyBkM19nZW9tX3Zvcm9ub2lCZWFjaCgpO1xuICAgIGJlYWNoLnNpdGUgPSBzaXRlO1xuICAgIHJldHVybiBiZWFjaDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lEZXRhY2hCZWFjaChiZWFjaCkge1xuICAgIGQzX2dlb21fdm9yb25vaURldGFjaENpcmNsZShiZWFjaCk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pQmVhY2hlcy5yZW1vdmUoYmVhY2gpO1xuICAgIGQzX2dlb21fdm9yb25vaUJlYWNoUG9vbC5wdXNoKGJlYWNoKTtcbiAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja05vZGUoYmVhY2gpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaVJlbW92ZUJlYWNoKGJlYWNoKSB7XG4gICAgdmFyIGNpcmNsZSA9IGJlYWNoLmNpcmNsZSwgeCA9IGNpcmNsZS54LCB5ID0gY2lyY2xlLmN5LCB2ZXJ0ZXggPSB7XG4gICAgICB4OiB4LFxuICAgICAgeTogeVxuICAgIH0sIHByZXZpb3VzID0gYmVhY2guUCwgbmV4dCA9IGJlYWNoLk4sIGRpc2FwcGVhcmluZyA9IFsgYmVhY2ggXTtcbiAgICBkM19nZW9tX3Zvcm9ub2lEZXRhY2hCZWFjaChiZWFjaCk7XG4gICAgdmFyIGxBcmMgPSBwcmV2aW91cztcbiAgICB3aGlsZSAobEFyYy5jaXJjbGUgJiYgYWJzKHggLSBsQXJjLmNpcmNsZS54KSA8IM61ICYmIGFicyh5IC0gbEFyYy5jaXJjbGUuY3kpIDwgzrUpIHtcbiAgICAgIHByZXZpb3VzID0gbEFyYy5QO1xuICAgICAgZGlzYXBwZWFyaW5nLnVuc2hpZnQobEFyYyk7XG4gICAgICBkM19nZW9tX3Zvcm9ub2lEZXRhY2hCZWFjaChsQXJjKTtcbiAgICAgIGxBcmMgPSBwcmV2aW91cztcbiAgICB9XG4gICAgZGlzYXBwZWFyaW5nLnVuc2hpZnQobEFyYyk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pRGV0YWNoQ2lyY2xlKGxBcmMpO1xuICAgIHZhciByQXJjID0gbmV4dDtcbiAgICB3aGlsZSAockFyYy5jaXJjbGUgJiYgYWJzKHggLSByQXJjLmNpcmNsZS54KSA8IM61ICYmIGFicyh5IC0gckFyYy5jaXJjbGUuY3kpIDwgzrUpIHtcbiAgICAgIG5leHQgPSByQXJjLk47XG4gICAgICBkaXNhcHBlYXJpbmcucHVzaChyQXJjKTtcbiAgICAgIGQzX2dlb21fdm9yb25vaURldGFjaEJlYWNoKHJBcmMpO1xuICAgICAgckFyYyA9IG5leHQ7XG4gICAgfVxuICAgIGRpc2FwcGVhcmluZy5wdXNoKHJBcmMpO1xuICAgIGQzX2dlb21fdm9yb25vaURldGFjaENpcmNsZShyQXJjKTtcbiAgICB2YXIgbkFyY3MgPSBkaXNhcHBlYXJpbmcubGVuZ3RoLCBpQXJjO1xuICAgIGZvciAoaUFyYyA9IDE7IGlBcmMgPCBuQXJjczsgKytpQXJjKSB7XG4gICAgICByQXJjID0gZGlzYXBwZWFyaW5nW2lBcmNdO1xuICAgICAgbEFyYyA9IGRpc2FwcGVhcmluZ1tpQXJjIC0gMV07XG4gICAgICBkM19nZW9tX3Zvcm9ub2lTZXRFZGdlRW5kKHJBcmMuZWRnZSwgbEFyYy5zaXRlLCByQXJjLnNpdGUsIHZlcnRleCk7XG4gICAgfVxuICAgIGxBcmMgPSBkaXNhcHBlYXJpbmdbMF07XG4gICAgckFyYyA9IGRpc2FwcGVhcmluZ1tuQXJjcyAtIDFdO1xuICAgIHJBcmMuZWRnZSA9IGQzX2dlb21fdm9yb25vaUNyZWF0ZUVkZ2UobEFyYy5zaXRlLCByQXJjLnNpdGUsIG51bGwsIHZlcnRleCk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pQXR0YWNoQ2lyY2xlKGxBcmMpO1xuICAgIGQzX2dlb21fdm9yb25vaUF0dGFjaENpcmNsZShyQXJjKTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lBZGRCZWFjaChzaXRlKSB7XG4gICAgdmFyIHggPSBzaXRlLngsIGRpcmVjdHJpeCA9IHNpdGUueSwgbEFyYywgckFyYywgZHhsLCBkeHIsIG5vZGUgPSBkM19nZW9tX3Zvcm9ub2lCZWFjaGVzLl87XG4gICAgd2hpbGUgKG5vZGUpIHtcbiAgICAgIGR4bCA9IGQzX2dlb21fdm9yb25vaUxlZnRCcmVha1BvaW50KG5vZGUsIGRpcmVjdHJpeCkgLSB4O1xuICAgICAgaWYgKGR4bCA+IM61KSBub2RlID0gbm9kZS5MOyBlbHNlIHtcbiAgICAgICAgZHhyID0geCAtIGQzX2dlb21fdm9yb25vaVJpZ2h0QnJlYWtQb2ludChub2RlLCBkaXJlY3RyaXgpO1xuICAgICAgICBpZiAoZHhyID4gzrUpIHtcbiAgICAgICAgICBpZiAoIW5vZGUuUikge1xuICAgICAgICAgICAgbEFyYyA9IG5vZGU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgbm9kZSA9IG5vZGUuUjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoZHhsID4gLc61KSB7XG4gICAgICAgICAgICBsQXJjID0gbm9kZS5QO1xuICAgICAgICAgICAgckFyYyA9IG5vZGU7XG4gICAgICAgICAgfSBlbHNlIGlmIChkeHIgPiAtzrUpIHtcbiAgICAgICAgICAgIGxBcmMgPSBub2RlO1xuICAgICAgICAgICAgckFyYyA9IG5vZGUuTjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbEFyYyA9IHJBcmMgPSBub2RlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICB2YXIgbmV3QXJjID0gZDNfZ2VvbV92b3Jvbm9pQ3JlYXRlQmVhY2goc2l0ZSk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pQmVhY2hlcy5pbnNlcnQobEFyYywgbmV3QXJjKTtcbiAgICBpZiAoIWxBcmMgJiYgIXJBcmMpIHJldHVybjtcbiAgICBpZiAobEFyYyA9PT0gckFyYykge1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pRGV0YWNoQ2lyY2xlKGxBcmMpO1xuICAgICAgckFyYyA9IGQzX2dlb21fdm9yb25vaUNyZWF0ZUJlYWNoKGxBcmMuc2l0ZSk7XG4gICAgICBkM19nZW9tX3Zvcm9ub2lCZWFjaGVzLmluc2VydChuZXdBcmMsIHJBcmMpO1xuICAgICAgbmV3QXJjLmVkZ2UgPSByQXJjLmVkZ2UgPSBkM19nZW9tX3Zvcm9ub2lDcmVhdGVFZGdlKGxBcmMuc2l0ZSwgbmV3QXJjLnNpdGUpO1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pQXR0YWNoQ2lyY2xlKGxBcmMpO1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pQXR0YWNoQ2lyY2xlKHJBcmMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXJBcmMpIHtcbiAgICAgIG5ld0FyYy5lZGdlID0gZDNfZ2VvbV92b3Jvbm9pQ3JlYXRlRWRnZShsQXJjLnNpdGUsIG5ld0FyYy5zaXRlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZDNfZ2VvbV92b3Jvbm9pRGV0YWNoQ2lyY2xlKGxBcmMpO1xuICAgIGQzX2dlb21fdm9yb25vaURldGFjaENpcmNsZShyQXJjKTtcbiAgICB2YXIgbFNpdGUgPSBsQXJjLnNpdGUsIGF4ID0gbFNpdGUueCwgYXkgPSBsU2l0ZS55LCBieCA9IHNpdGUueCAtIGF4LCBieSA9IHNpdGUueSAtIGF5LCByU2l0ZSA9IHJBcmMuc2l0ZSwgY3ggPSByU2l0ZS54IC0gYXgsIGN5ID0gclNpdGUueSAtIGF5LCBkID0gMiAqIChieCAqIGN5IC0gYnkgKiBjeCksIGhiID0gYnggKiBieCArIGJ5ICogYnksIGhjID0gY3ggKiBjeCArIGN5ICogY3ksIHZlcnRleCA9IHtcbiAgICAgIHg6IChjeSAqIGhiIC0gYnkgKiBoYykgLyBkICsgYXgsXG4gICAgICB5OiAoYnggKiBoYyAtIGN4ICogaGIpIC8gZCArIGF5XG4gICAgfTtcbiAgICBkM19nZW9tX3Zvcm9ub2lTZXRFZGdlRW5kKHJBcmMuZWRnZSwgbFNpdGUsIHJTaXRlLCB2ZXJ0ZXgpO1xuICAgIG5ld0FyYy5lZGdlID0gZDNfZ2VvbV92b3Jvbm9pQ3JlYXRlRWRnZShsU2l0ZSwgc2l0ZSwgbnVsbCwgdmVydGV4KTtcbiAgICByQXJjLmVkZ2UgPSBkM19nZW9tX3Zvcm9ub2lDcmVhdGVFZGdlKHNpdGUsIHJTaXRlLCBudWxsLCB2ZXJ0ZXgpO1xuICAgIGQzX2dlb21fdm9yb25vaUF0dGFjaENpcmNsZShsQXJjKTtcbiAgICBkM19nZW9tX3Zvcm9ub2lBdHRhY2hDaXJjbGUockFyYyk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pTGVmdEJyZWFrUG9pbnQoYXJjLCBkaXJlY3RyaXgpIHtcbiAgICB2YXIgc2l0ZSA9IGFyYy5zaXRlLCByZm9jeCA9IHNpdGUueCwgcmZvY3kgPSBzaXRlLnksIHBieTIgPSByZm9jeSAtIGRpcmVjdHJpeDtcbiAgICBpZiAoIXBieTIpIHJldHVybiByZm9jeDtcbiAgICB2YXIgbEFyYyA9IGFyYy5QO1xuICAgIGlmICghbEFyYykgcmV0dXJuIC1JbmZpbml0eTtcbiAgICBzaXRlID0gbEFyYy5zaXRlO1xuICAgIHZhciBsZm9jeCA9IHNpdGUueCwgbGZvY3kgPSBzaXRlLnksIHBsYnkyID0gbGZvY3kgLSBkaXJlY3RyaXg7XG4gICAgaWYgKCFwbGJ5MikgcmV0dXJuIGxmb2N4O1xuICAgIHZhciBobCA9IGxmb2N4IC0gcmZvY3gsIGFieTIgPSAxIC8gcGJ5MiAtIDEgLyBwbGJ5MiwgYiA9IGhsIC8gcGxieTI7XG4gICAgaWYgKGFieTIpIHJldHVybiAoLWIgKyBNYXRoLnNxcnQoYiAqIGIgLSAyICogYWJ5MiAqIChobCAqIGhsIC8gKC0yICogcGxieTIpIC0gbGZvY3kgKyBwbGJ5MiAvIDIgKyByZm9jeSAtIHBieTIgLyAyKSkpIC8gYWJ5MiArIHJmb2N4O1xuICAgIHJldHVybiAocmZvY3ggKyBsZm9jeCkgLyAyO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaVJpZ2h0QnJlYWtQb2ludChhcmMsIGRpcmVjdHJpeCkge1xuICAgIHZhciByQXJjID0gYXJjLk47XG4gICAgaWYgKHJBcmMpIHJldHVybiBkM19nZW9tX3Zvcm9ub2lMZWZ0QnJlYWtQb2ludChyQXJjLCBkaXJlY3RyaXgpO1xuICAgIHZhciBzaXRlID0gYXJjLnNpdGU7XG4gICAgcmV0dXJuIHNpdGUueSA9PT0gZGlyZWN0cml4ID8gc2l0ZS54IDogSW5maW5pdHk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pQ2VsbChzaXRlKSB7XG4gICAgdGhpcy5zaXRlID0gc2l0ZTtcbiAgICB0aGlzLmVkZ2VzID0gW107XG4gIH1cbiAgZDNfZ2VvbV92b3Jvbm9pQ2VsbC5wcm90b3R5cGUucHJlcGFyZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoYWxmRWRnZXMgPSB0aGlzLmVkZ2VzLCBpSGFsZkVkZ2UgPSBoYWxmRWRnZXMubGVuZ3RoLCBlZGdlO1xuICAgIHdoaWxlIChpSGFsZkVkZ2UtLSkge1xuICAgICAgZWRnZSA9IGhhbGZFZGdlc1tpSGFsZkVkZ2VdLmVkZ2U7XG4gICAgICBpZiAoIWVkZ2UuYiB8fCAhZWRnZS5hKSBoYWxmRWRnZXMuc3BsaWNlKGlIYWxmRWRnZSwgMSk7XG4gICAgfVxuICAgIGhhbGZFZGdlcy5zb3J0KGQzX2dlb21fdm9yb25vaUhhbGZFZGdlT3JkZXIpO1xuICAgIHJldHVybiBoYWxmRWRnZXMubGVuZ3RoO1xuICB9O1xuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lDbG9zZUNlbGxzKGV4dGVudCkge1xuICAgIHZhciB4MCA9IGV4dGVudFswXVswXSwgeDEgPSBleHRlbnRbMV1bMF0sIHkwID0gZXh0ZW50WzBdWzFdLCB5MSA9IGV4dGVudFsxXVsxXSwgeDIsIHkyLCB4MywgeTMsIGNlbGxzID0gZDNfZ2VvbV92b3Jvbm9pQ2VsbHMsIGlDZWxsID0gY2VsbHMubGVuZ3RoLCBjZWxsLCBpSGFsZkVkZ2UsIGhhbGZFZGdlcywgbkhhbGZFZGdlcywgc3RhcnQsIGVuZDtcbiAgICB3aGlsZSAoaUNlbGwtLSkge1xuICAgICAgY2VsbCA9IGNlbGxzW2lDZWxsXTtcbiAgICAgIGlmICghY2VsbCB8fCAhY2VsbC5wcmVwYXJlKCkpIGNvbnRpbnVlO1xuICAgICAgaGFsZkVkZ2VzID0gY2VsbC5lZGdlcztcbiAgICAgIG5IYWxmRWRnZXMgPSBoYWxmRWRnZXMubGVuZ3RoO1xuICAgICAgaUhhbGZFZGdlID0gMDtcbiAgICAgIHdoaWxlIChpSGFsZkVkZ2UgPCBuSGFsZkVkZ2VzKSB7XG4gICAgICAgIGVuZCA9IGhhbGZFZGdlc1tpSGFsZkVkZ2VdLmVuZCgpLCB4MyA9IGVuZC54LCB5MyA9IGVuZC55O1xuICAgICAgICBzdGFydCA9IGhhbGZFZGdlc1srK2lIYWxmRWRnZSAlIG5IYWxmRWRnZXNdLnN0YXJ0KCksIHgyID0gc3RhcnQueCwgeTIgPSBzdGFydC55O1xuICAgICAgICBpZiAoYWJzKHgzIC0geDIpID4gzrUgfHwgYWJzKHkzIC0geTIpID4gzrUpIHtcbiAgICAgICAgICBoYWxmRWRnZXMuc3BsaWNlKGlIYWxmRWRnZSwgMCwgbmV3IGQzX2dlb21fdm9yb25vaUhhbGZFZGdlKGQzX2dlb21fdm9yb25vaUNyZWF0ZUJvcmRlckVkZ2UoY2VsbC5zaXRlLCBlbmQsIGFicyh4MyAtIHgwKSA8IM61ICYmIHkxIC0geTMgPiDOtSA/IHtcbiAgICAgICAgICAgIHg6IHgwLFxuICAgICAgICAgICAgeTogYWJzKHgyIC0geDApIDwgzrUgPyB5MiA6IHkxXG4gICAgICAgICAgfSA6IGFicyh5MyAtIHkxKSA8IM61ICYmIHgxIC0geDMgPiDOtSA/IHtcbiAgICAgICAgICAgIHg6IGFicyh5MiAtIHkxKSA8IM61ID8geDIgOiB4MSxcbiAgICAgICAgICAgIHk6IHkxXG4gICAgICAgICAgfSA6IGFicyh4MyAtIHgxKSA8IM61ICYmIHkzIC0geTAgPiDOtSA/IHtcbiAgICAgICAgICAgIHg6IHgxLFxuICAgICAgICAgICAgeTogYWJzKHgyIC0geDEpIDwgzrUgPyB5MiA6IHkwXG4gICAgICAgICAgfSA6IGFicyh5MyAtIHkwKSA8IM61ICYmIHgzIC0geDAgPiDOtSA/IHtcbiAgICAgICAgICAgIHg6IGFicyh5MiAtIHkwKSA8IM61ID8geDIgOiB4MCxcbiAgICAgICAgICAgIHk6IHkwXG4gICAgICAgICAgfSA6IG51bGwpLCBjZWxsLnNpdGUsIG51bGwpKTtcbiAgICAgICAgICArK25IYWxmRWRnZXM7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pSGFsZkVkZ2VPcmRlcihhLCBiKSB7XG4gICAgcmV0dXJuIGIuYW5nbGUgLSBhLmFuZ2xlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaUNpcmNsZSgpIHtcbiAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja05vZGUodGhpcyk7XG4gICAgdGhpcy54ID0gdGhpcy55ID0gdGhpcy5hcmMgPSB0aGlzLnNpdGUgPSB0aGlzLmN5ID0gbnVsbDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lBdHRhY2hDaXJjbGUoYXJjKSB7XG4gICAgdmFyIGxBcmMgPSBhcmMuUCwgckFyYyA9IGFyYy5OO1xuICAgIGlmICghbEFyYyB8fCAhckFyYykgcmV0dXJuO1xuICAgIHZhciBsU2l0ZSA9IGxBcmMuc2l0ZSwgY1NpdGUgPSBhcmMuc2l0ZSwgclNpdGUgPSByQXJjLnNpdGU7XG4gICAgaWYgKGxTaXRlID09PSByU2l0ZSkgcmV0dXJuO1xuICAgIHZhciBieCA9IGNTaXRlLngsIGJ5ID0gY1NpdGUueSwgYXggPSBsU2l0ZS54IC0gYngsIGF5ID0gbFNpdGUueSAtIGJ5LCBjeCA9IHJTaXRlLnggLSBieCwgY3kgPSByU2l0ZS55IC0gYnk7XG4gICAgdmFyIGQgPSAyICogKGF4ICogY3kgLSBheSAqIGN4KTtcbiAgICBpZiAoZCA+PSAtzrUyKSByZXR1cm47XG4gICAgdmFyIGhhID0gYXggKiBheCArIGF5ICogYXksIGhjID0gY3ggKiBjeCArIGN5ICogY3ksIHggPSAoY3kgKiBoYSAtIGF5ICogaGMpIC8gZCwgeSA9IChheCAqIGhjIC0gY3ggKiBoYSkgLyBkLCBjeSA9IHkgKyBieTtcbiAgICB2YXIgY2lyY2xlID0gZDNfZ2VvbV92b3Jvbm9pQ2lyY2xlUG9vbC5wb3AoKSB8fCBuZXcgZDNfZ2VvbV92b3Jvbm9pQ2lyY2xlKCk7XG4gICAgY2lyY2xlLmFyYyA9IGFyYztcbiAgICBjaXJjbGUuc2l0ZSA9IGNTaXRlO1xuICAgIGNpcmNsZS54ID0geCArIGJ4O1xuICAgIGNpcmNsZS55ID0gY3kgKyBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSk7XG4gICAgY2lyY2xlLmN5ID0gY3k7XG4gICAgYXJjLmNpcmNsZSA9IGNpcmNsZTtcbiAgICB2YXIgYmVmb3JlID0gbnVsbCwgbm9kZSA9IGQzX2dlb21fdm9yb25vaUNpcmNsZXMuXztcbiAgICB3aGlsZSAobm9kZSkge1xuICAgICAgaWYgKGNpcmNsZS55IDwgbm9kZS55IHx8IGNpcmNsZS55ID09PSBub2RlLnkgJiYgY2lyY2xlLnggPD0gbm9kZS54KSB7XG4gICAgICAgIGlmIChub2RlLkwpIG5vZGUgPSBub2RlLkw7IGVsc2Uge1xuICAgICAgICAgIGJlZm9yZSA9IG5vZGUuUDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKG5vZGUuUikgbm9kZSA9IG5vZGUuUjsgZWxzZSB7XG4gICAgICAgICAgYmVmb3JlID0gbm9kZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBkM19nZW9tX3Zvcm9ub2lDaXJjbGVzLmluc2VydChiZWZvcmUsIGNpcmNsZSk7XG4gICAgaWYgKCFiZWZvcmUpIGQzX2dlb21fdm9yb25vaUZpcnN0Q2lyY2xlID0gY2lyY2xlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaURldGFjaENpcmNsZShhcmMpIHtcbiAgICB2YXIgY2lyY2xlID0gYXJjLmNpcmNsZTtcbiAgICBpZiAoY2lyY2xlKSB7XG4gICAgICBpZiAoIWNpcmNsZS5QKSBkM19nZW9tX3Zvcm9ub2lGaXJzdENpcmNsZSA9IGNpcmNsZS5OO1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pQ2lyY2xlcy5yZW1vdmUoY2lyY2xlKTtcbiAgICAgIGQzX2dlb21fdm9yb25vaUNpcmNsZVBvb2wucHVzaChjaXJjbGUpO1xuICAgICAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tOb2RlKGNpcmNsZSk7XG4gICAgICBhcmMuY2lyY2xlID0gbnVsbDtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pQ2xpcEVkZ2VzKGV4dGVudCkge1xuICAgIHZhciBlZGdlcyA9IGQzX2dlb21fdm9yb25vaUVkZ2VzLCBjbGlwID0gZDNfZ2VvbV9jbGlwTGluZShleHRlbnRbMF1bMF0sIGV4dGVudFswXVsxXSwgZXh0ZW50WzFdWzBdLCBleHRlbnRbMV1bMV0pLCBpID0gZWRnZXMubGVuZ3RoLCBlO1xuICAgIHdoaWxlIChpLS0pIHtcbiAgICAgIGUgPSBlZGdlc1tpXTtcbiAgICAgIGlmICghZDNfZ2VvbV92b3Jvbm9pQ29ubmVjdEVkZ2UoZSwgZXh0ZW50KSB8fCAhY2xpcChlKSB8fCBhYnMoZS5hLnggLSBlLmIueCkgPCDOtSAmJiBhYnMoZS5hLnkgLSBlLmIueSkgPCDOtSkge1xuICAgICAgICBlLmEgPSBlLmIgPSBudWxsO1xuICAgICAgICBlZGdlcy5zcGxpY2UoaSwgMSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaUNvbm5lY3RFZGdlKGVkZ2UsIGV4dGVudCkge1xuICAgIHZhciB2YiA9IGVkZ2UuYjtcbiAgICBpZiAodmIpIHJldHVybiB0cnVlO1xuICAgIHZhciB2YSA9IGVkZ2UuYSwgeDAgPSBleHRlbnRbMF1bMF0sIHgxID0gZXh0ZW50WzFdWzBdLCB5MCA9IGV4dGVudFswXVsxXSwgeTEgPSBleHRlbnRbMV1bMV0sIGxTaXRlID0gZWRnZS5sLCByU2l0ZSA9IGVkZ2UuciwgbHggPSBsU2l0ZS54LCBseSA9IGxTaXRlLnksIHJ4ID0gclNpdGUueCwgcnkgPSByU2l0ZS55LCBmeCA9IChseCArIHJ4KSAvIDIsIGZ5ID0gKGx5ICsgcnkpIC8gMiwgZm0sIGZiO1xuICAgIGlmIChyeSA9PT0gbHkpIHtcbiAgICAgIGlmIChmeCA8IHgwIHx8IGZ4ID49IHgxKSByZXR1cm47XG4gICAgICBpZiAobHggPiByeCkge1xuICAgICAgICBpZiAoIXZhKSB2YSA9IHtcbiAgICAgICAgICB4OiBmeCxcbiAgICAgICAgICB5OiB5MFxuICAgICAgICB9OyBlbHNlIGlmICh2YS55ID49IHkxKSByZXR1cm47XG4gICAgICAgIHZiID0ge1xuICAgICAgICAgIHg6IGZ4LFxuICAgICAgICAgIHk6IHkxXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIXZhKSB2YSA9IHtcbiAgICAgICAgICB4OiBmeCxcbiAgICAgICAgICB5OiB5MVxuICAgICAgICB9OyBlbHNlIGlmICh2YS55IDwgeTApIHJldHVybjtcbiAgICAgICAgdmIgPSB7XG4gICAgICAgICAgeDogZngsXG4gICAgICAgICAgeTogeTBcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm0gPSAobHggLSByeCkgLyAocnkgLSBseSk7XG4gICAgICBmYiA9IGZ5IC0gZm0gKiBmeDtcbiAgICAgIGlmIChmbSA8IC0xIHx8IGZtID4gMSkge1xuICAgICAgICBpZiAobHggPiByeCkge1xuICAgICAgICAgIGlmICghdmEpIHZhID0ge1xuICAgICAgICAgICAgeDogKHkwIC0gZmIpIC8gZm0sXG4gICAgICAgICAgICB5OiB5MFxuICAgICAgICAgIH07IGVsc2UgaWYgKHZhLnkgPj0geTEpIHJldHVybjtcbiAgICAgICAgICB2YiA9IHtcbiAgICAgICAgICAgIHg6ICh5MSAtIGZiKSAvIGZtLFxuICAgICAgICAgICAgeTogeTFcbiAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghdmEpIHZhID0ge1xuICAgICAgICAgICAgeDogKHkxIC0gZmIpIC8gZm0sXG4gICAgICAgICAgICB5OiB5MVxuICAgICAgICAgIH07IGVsc2UgaWYgKHZhLnkgPCB5MCkgcmV0dXJuO1xuICAgICAgICAgIHZiID0ge1xuICAgICAgICAgICAgeDogKHkwIC0gZmIpIC8gZm0sXG4gICAgICAgICAgICB5OiB5MFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChseSA8IHJ5KSB7XG4gICAgICAgICAgaWYgKCF2YSkgdmEgPSB7XG4gICAgICAgICAgICB4OiB4MCxcbiAgICAgICAgICAgIHk6IGZtICogeDAgKyBmYlxuICAgICAgICAgIH07IGVsc2UgaWYgKHZhLnggPj0geDEpIHJldHVybjtcbiAgICAgICAgICB2YiA9IHtcbiAgICAgICAgICAgIHg6IHgxLFxuICAgICAgICAgICAgeTogZm0gKiB4MSArIGZiXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoIXZhKSB2YSA9IHtcbiAgICAgICAgICAgIHg6IHgxLFxuICAgICAgICAgICAgeTogZm0gKiB4MSArIGZiXG4gICAgICAgICAgfTsgZWxzZSBpZiAodmEueCA8IHgwKSByZXR1cm47XG4gICAgICAgICAgdmIgPSB7XG4gICAgICAgICAgICB4OiB4MCxcbiAgICAgICAgICAgIHk6IGZtICogeDAgKyBmYlxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgZWRnZS5hID0gdmE7XG4gICAgZWRnZS5iID0gdmI7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pRWRnZShsU2l0ZSwgclNpdGUpIHtcbiAgICB0aGlzLmwgPSBsU2l0ZTtcbiAgICB0aGlzLnIgPSByU2l0ZTtcbiAgICB0aGlzLmEgPSB0aGlzLmIgPSBudWxsO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaUNyZWF0ZUVkZ2UobFNpdGUsIHJTaXRlLCB2YSwgdmIpIHtcbiAgICB2YXIgZWRnZSA9IG5ldyBkM19nZW9tX3Zvcm9ub2lFZGdlKGxTaXRlLCByU2l0ZSk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pRWRnZXMucHVzaChlZGdlKTtcbiAgICBpZiAodmEpIGQzX2dlb21fdm9yb25vaVNldEVkZ2VFbmQoZWRnZSwgbFNpdGUsIHJTaXRlLCB2YSk7XG4gICAgaWYgKHZiKSBkM19nZW9tX3Zvcm9ub2lTZXRFZGdlRW5kKGVkZ2UsIHJTaXRlLCBsU2l0ZSwgdmIpO1xuICAgIGQzX2dlb21fdm9yb25vaUNlbGxzW2xTaXRlLmldLmVkZ2VzLnB1c2gobmV3IGQzX2dlb21fdm9yb25vaUhhbGZFZGdlKGVkZ2UsIGxTaXRlLCByU2l0ZSkpO1xuICAgIGQzX2dlb21fdm9yb25vaUNlbGxzW3JTaXRlLmldLmVkZ2VzLnB1c2gobmV3IGQzX2dlb21fdm9yb25vaUhhbGZFZGdlKGVkZ2UsIHJTaXRlLCBsU2l0ZSkpO1xuICAgIHJldHVybiBlZGdlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaUNyZWF0ZUJvcmRlckVkZ2UobFNpdGUsIHZhLCB2Yikge1xuICAgIHZhciBlZGdlID0gbmV3IGQzX2dlb21fdm9yb25vaUVkZ2UobFNpdGUsIG51bGwpO1xuICAgIGVkZ2UuYSA9IHZhO1xuICAgIGVkZ2UuYiA9IHZiO1xuICAgIGQzX2dlb21fdm9yb25vaUVkZ2VzLnB1c2goZWRnZSk7XG4gICAgcmV0dXJuIGVkZ2U7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pU2V0RWRnZUVuZChlZGdlLCBsU2l0ZSwgclNpdGUsIHZlcnRleCkge1xuICAgIGlmICghZWRnZS5hICYmICFlZGdlLmIpIHtcbiAgICAgIGVkZ2UuYSA9IHZlcnRleDtcbiAgICAgIGVkZ2UubCA9IGxTaXRlO1xuICAgICAgZWRnZS5yID0gclNpdGU7XG4gICAgfSBlbHNlIGlmIChlZGdlLmwgPT09IHJTaXRlKSB7XG4gICAgICBlZGdlLmIgPSB2ZXJ0ZXg7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVkZ2UuYSA9IHZlcnRleDtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pSGFsZkVkZ2UoZWRnZSwgbFNpdGUsIHJTaXRlKSB7XG4gICAgdmFyIHZhID0gZWRnZS5hLCB2YiA9IGVkZ2UuYjtcbiAgICB0aGlzLmVkZ2UgPSBlZGdlO1xuICAgIHRoaXMuc2l0ZSA9IGxTaXRlO1xuICAgIHRoaXMuYW5nbGUgPSByU2l0ZSA/IE1hdGguYXRhbjIoclNpdGUueSAtIGxTaXRlLnksIHJTaXRlLnggLSBsU2l0ZS54KSA6IGVkZ2UubCA9PT0gbFNpdGUgPyBNYXRoLmF0YW4yKHZiLnggLSB2YS54LCB2YS55IC0gdmIueSkgOiBNYXRoLmF0YW4yKHZhLnggLSB2Yi54LCB2Yi55IC0gdmEueSk7XG4gIH1cbiAgZDNfZ2VvbV92b3Jvbm9pSGFsZkVkZ2UucHJvdG90eXBlID0ge1xuICAgIHN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLmVkZ2UubCA9PT0gdGhpcy5zaXRlID8gdGhpcy5lZGdlLmEgOiB0aGlzLmVkZ2UuYjtcbiAgICB9LFxuICAgIGVuZDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5lZGdlLmwgPT09IHRoaXMuc2l0ZSA/IHRoaXMuZWRnZS5iIDogdGhpcy5lZGdlLmE7XG4gICAgfVxuICB9O1xuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1RyZWUoKSB7XG4gICAgdGhpcy5fID0gbnVsbDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja05vZGUobm9kZSkge1xuICAgIG5vZGUuVSA9IG5vZGUuQyA9IG5vZGUuTCA9IG5vZGUuUiA9IG5vZGUuUCA9IG5vZGUuTiA9IG51bGw7XG4gIH1cbiAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tUcmVlLnByb3RvdHlwZSA9IHtcbiAgICBpbnNlcnQ6IGZ1bmN0aW9uKGFmdGVyLCBub2RlKSB7XG4gICAgICB2YXIgcGFyZW50LCBncmFuZHBhLCB1bmNsZTtcbiAgICAgIGlmIChhZnRlcikge1xuICAgICAgICBub2RlLlAgPSBhZnRlcjtcbiAgICAgICAgbm9kZS5OID0gYWZ0ZXIuTjtcbiAgICAgICAgaWYgKGFmdGVyLk4pIGFmdGVyLk4uUCA9IG5vZGU7XG4gICAgICAgIGFmdGVyLk4gPSBub2RlO1xuICAgICAgICBpZiAoYWZ0ZXIuUikge1xuICAgICAgICAgIGFmdGVyID0gYWZ0ZXIuUjtcbiAgICAgICAgICB3aGlsZSAoYWZ0ZXIuTCkgYWZ0ZXIgPSBhZnRlci5MO1xuICAgICAgICAgIGFmdGVyLkwgPSBub2RlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFmdGVyLlIgPSBub2RlO1xuICAgICAgICB9XG4gICAgICAgIHBhcmVudCA9IGFmdGVyO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLl8pIHtcbiAgICAgICAgYWZ0ZXIgPSBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja0ZpcnN0KHRoaXMuXyk7XG4gICAgICAgIG5vZGUuUCA9IG51bGw7XG4gICAgICAgIG5vZGUuTiA9IGFmdGVyO1xuICAgICAgICBhZnRlci5QID0gYWZ0ZXIuTCA9IG5vZGU7XG4gICAgICAgIHBhcmVudCA9IGFmdGVyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9kZS5QID0gbm9kZS5OID0gbnVsbDtcbiAgICAgICAgdGhpcy5fID0gbm9kZTtcbiAgICAgICAgcGFyZW50ID0gbnVsbDtcbiAgICAgIH1cbiAgICAgIG5vZGUuTCA9IG5vZGUuUiA9IG51bGw7XG4gICAgICBub2RlLlUgPSBwYXJlbnQ7XG4gICAgICBub2RlLkMgPSB0cnVlO1xuICAgICAgYWZ0ZXIgPSBub2RlO1xuICAgICAgd2hpbGUgKHBhcmVudCAmJiBwYXJlbnQuQykge1xuICAgICAgICBncmFuZHBhID0gcGFyZW50LlU7XG4gICAgICAgIGlmIChwYXJlbnQgPT09IGdyYW5kcGEuTCkge1xuICAgICAgICAgIHVuY2xlID0gZ3JhbmRwYS5SO1xuICAgICAgICAgIGlmICh1bmNsZSAmJiB1bmNsZS5DKSB7XG4gICAgICAgICAgICBwYXJlbnQuQyA9IHVuY2xlLkMgPSBmYWxzZTtcbiAgICAgICAgICAgIGdyYW5kcGEuQyA9IHRydWU7XG4gICAgICAgICAgICBhZnRlciA9IGdyYW5kcGE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChhZnRlciA9PT0gcGFyZW50LlIpIHtcbiAgICAgICAgICAgICAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tSb3RhdGVMZWZ0KHRoaXMsIHBhcmVudCk7XG4gICAgICAgICAgICAgIGFmdGVyID0gcGFyZW50O1xuICAgICAgICAgICAgICBwYXJlbnQgPSBhZnRlci5VO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGFyZW50LkMgPSBmYWxzZTtcbiAgICAgICAgICAgIGdyYW5kcGEuQyA9IHRydWU7XG4gICAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1JvdGF0ZVJpZ2h0KHRoaXMsIGdyYW5kcGEpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB1bmNsZSA9IGdyYW5kcGEuTDtcbiAgICAgICAgICBpZiAodW5jbGUgJiYgdW5jbGUuQykge1xuICAgICAgICAgICAgcGFyZW50LkMgPSB1bmNsZS5DID0gZmFsc2U7XG4gICAgICAgICAgICBncmFuZHBhLkMgPSB0cnVlO1xuICAgICAgICAgICAgYWZ0ZXIgPSBncmFuZHBhO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoYWZ0ZXIgPT09IHBhcmVudC5MKSB7XG4gICAgICAgICAgICAgIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlUmlnaHQodGhpcywgcGFyZW50KTtcbiAgICAgICAgICAgICAgYWZ0ZXIgPSBwYXJlbnQ7XG4gICAgICAgICAgICAgIHBhcmVudCA9IGFmdGVyLlU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYXJlbnQuQyA9IGZhbHNlO1xuICAgICAgICAgICAgZ3JhbmRwYS5DID0gdHJ1ZTtcbiAgICAgICAgICAgIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlTGVmdCh0aGlzLCBncmFuZHBhKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcGFyZW50ID0gYWZ0ZXIuVTtcbiAgICAgIH1cbiAgICAgIHRoaXMuXy5DID0gZmFsc2U7XG4gICAgfSxcbiAgICByZW1vdmU6IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIGlmIChub2RlLk4pIG5vZGUuTi5QID0gbm9kZS5QO1xuICAgICAgaWYgKG5vZGUuUCkgbm9kZS5QLk4gPSBub2RlLk47XG4gICAgICBub2RlLk4gPSBub2RlLlAgPSBudWxsO1xuICAgICAgdmFyIHBhcmVudCA9IG5vZGUuVSwgc2libGluZywgbGVmdCA9IG5vZGUuTCwgcmlnaHQgPSBub2RlLlIsIG5leHQsIHJlZDtcbiAgICAgIGlmICghbGVmdCkgbmV4dCA9IHJpZ2h0OyBlbHNlIGlmICghcmlnaHQpIG5leHQgPSBsZWZ0OyBlbHNlIG5leHQgPSBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja0ZpcnN0KHJpZ2h0KTtcbiAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgaWYgKHBhcmVudC5MID09PSBub2RlKSBwYXJlbnQuTCA9IG5leHQ7IGVsc2UgcGFyZW50LlIgPSBuZXh0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fID0gbmV4dDtcbiAgICAgIH1cbiAgICAgIGlmIChsZWZ0ICYmIHJpZ2h0KSB7XG4gICAgICAgIHJlZCA9IG5leHQuQztcbiAgICAgICAgbmV4dC5DID0gbm9kZS5DO1xuICAgICAgICBuZXh0LkwgPSBsZWZ0O1xuICAgICAgICBsZWZ0LlUgPSBuZXh0O1xuICAgICAgICBpZiAobmV4dCAhPT0gcmlnaHQpIHtcbiAgICAgICAgICBwYXJlbnQgPSBuZXh0LlU7XG4gICAgICAgICAgbmV4dC5VID0gbm9kZS5VO1xuICAgICAgICAgIG5vZGUgPSBuZXh0LlI7XG4gICAgICAgICAgcGFyZW50LkwgPSBub2RlO1xuICAgICAgICAgIG5leHQuUiA9IHJpZ2h0O1xuICAgICAgICAgIHJpZ2h0LlUgPSBuZXh0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQuVSA9IHBhcmVudDtcbiAgICAgICAgICBwYXJlbnQgPSBuZXh0O1xuICAgICAgICAgIG5vZGUgPSBuZXh0LlI7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlZCA9IG5vZGUuQztcbiAgICAgICAgbm9kZSA9IG5leHQ7XG4gICAgICB9XG4gICAgICBpZiAobm9kZSkgbm9kZS5VID0gcGFyZW50O1xuICAgICAgaWYgKHJlZCkgcmV0dXJuO1xuICAgICAgaWYgKG5vZGUgJiYgbm9kZS5DKSB7XG4gICAgICAgIG5vZGUuQyA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBkbyB7XG4gICAgICAgIGlmIChub2RlID09PSB0aGlzLl8pIGJyZWFrO1xuICAgICAgICBpZiAobm9kZSA9PT0gcGFyZW50LkwpIHtcbiAgICAgICAgICBzaWJsaW5nID0gcGFyZW50LlI7XG4gICAgICAgICAgaWYgKHNpYmxpbmcuQykge1xuICAgICAgICAgICAgc2libGluZy5DID0gZmFsc2U7XG4gICAgICAgICAgICBwYXJlbnQuQyA9IHRydWU7XG4gICAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1JvdGF0ZUxlZnQodGhpcywgcGFyZW50KTtcbiAgICAgICAgICAgIHNpYmxpbmcgPSBwYXJlbnQuUjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHNpYmxpbmcuTCAmJiBzaWJsaW5nLkwuQyB8fCBzaWJsaW5nLlIgJiYgc2libGluZy5SLkMpIHtcbiAgICAgICAgICAgIGlmICghc2libGluZy5SIHx8ICFzaWJsaW5nLlIuQykge1xuICAgICAgICAgICAgICBzaWJsaW5nLkwuQyA9IGZhbHNlO1xuICAgICAgICAgICAgICBzaWJsaW5nLkMgPSB0cnVlO1xuICAgICAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1JvdGF0ZVJpZ2h0KHRoaXMsIHNpYmxpbmcpO1xuICAgICAgICAgICAgICBzaWJsaW5nID0gcGFyZW50LlI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaWJsaW5nLkMgPSBwYXJlbnQuQztcbiAgICAgICAgICAgIHBhcmVudC5DID0gc2libGluZy5SLkMgPSBmYWxzZTtcbiAgICAgICAgICAgIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlTGVmdCh0aGlzLCBwYXJlbnQpO1xuICAgICAgICAgICAgbm9kZSA9IHRoaXMuXztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzaWJsaW5nID0gcGFyZW50Lkw7XG4gICAgICAgICAgaWYgKHNpYmxpbmcuQykge1xuICAgICAgICAgICAgc2libGluZy5DID0gZmFsc2U7XG4gICAgICAgICAgICBwYXJlbnQuQyA9IHRydWU7XG4gICAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1JvdGF0ZVJpZ2h0KHRoaXMsIHBhcmVudCk7XG4gICAgICAgICAgICBzaWJsaW5nID0gcGFyZW50Lkw7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzaWJsaW5nLkwgJiYgc2libGluZy5MLkMgfHwgc2libGluZy5SICYmIHNpYmxpbmcuUi5DKSB7XG4gICAgICAgICAgICBpZiAoIXNpYmxpbmcuTCB8fCAhc2libGluZy5MLkMpIHtcbiAgICAgICAgICAgICAgc2libGluZy5SLkMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgc2libGluZy5DID0gdHJ1ZTtcbiAgICAgICAgICAgICAgZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tSb3RhdGVMZWZ0KHRoaXMsIHNpYmxpbmcpO1xuICAgICAgICAgICAgICBzaWJsaW5nID0gcGFyZW50Lkw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaWJsaW5nLkMgPSBwYXJlbnQuQztcbiAgICAgICAgICAgIHBhcmVudC5DID0gc2libGluZy5MLkMgPSBmYWxzZTtcbiAgICAgICAgICAgIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlUmlnaHQodGhpcywgcGFyZW50KTtcbiAgICAgICAgICAgIG5vZGUgPSB0aGlzLl87XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc2libGluZy5DID0gdHJ1ZTtcbiAgICAgICAgbm9kZSA9IHBhcmVudDtcbiAgICAgICAgcGFyZW50ID0gcGFyZW50LlU7XG4gICAgICB9IHdoaWxlICghbm9kZS5DKTtcbiAgICAgIGlmIChub2RlKSBub2RlLkMgPSBmYWxzZTtcbiAgICB9XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaVJlZEJsYWNrUm90YXRlTGVmdCh0cmVlLCBub2RlKSB7XG4gICAgdmFyIHAgPSBub2RlLCBxID0gbm9kZS5SLCBwYXJlbnQgPSBwLlU7XG4gICAgaWYgKHBhcmVudCkge1xuICAgICAgaWYgKHBhcmVudC5MID09PSBwKSBwYXJlbnQuTCA9IHE7IGVsc2UgcGFyZW50LlIgPSBxO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cmVlLl8gPSBxO1xuICAgIH1cbiAgICBxLlUgPSBwYXJlbnQ7XG4gICAgcC5VID0gcTtcbiAgICBwLlIgPSBxLkw7XG4gICAgaWYgKHAuUikgcC5SLlUgPSBwO1xuICAgIHEuTCA9IHA7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tSb3RhdGVSaWdodCh0cmVlLCBub2RlKSB7XG4gICAgdmFyIHAgPSBub2RlLCBxID0gbm9kZS5MLCBwYXJlbnQgPSBwLlU7XG4gICAgaWYgKHBhcmVudCkge1xuICAgICAgaWYgKHBhcmVudC5MID09PSBwKSBwYXJlbnQuTCA9IHE7IGVsc2UgcGFyZW50LlIgPSBxO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cmVlLl8gPSBxO1xuICAgIH1cbiAgICBxLlUgPSBwYXJlbnQ7XG4gICAgcC5VID0gcTtcbiAgICBwLkwgPSBxLlI7XG4gICAgaWYgKHAuTCkgcC5MLlUgPSBwO1xuICAgIHEuUiA9IHA7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pUmVkQmxhY2tGaXJzdChub2RlKSB7XG4gICAgd2hpbGUgKG5vZGUuTCkgbm9kZSA9IG5vZGUuTDtcbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3Zvcm9ub2koc2l0ZXMsIGJib3gpIHtcbiAgICB2YXIgc2l0ZSA9IHNpdGVzLnNvcnQoZDNfZ2VvbV92b3Jvbm9pVmVydGV4T3JkZXIpLnBvcCgpLCB4MCwgeTAsIGNpcmNsZTtcbiAgICBkM19nZW9tX3Zvcm9ub2lFZGdlcyA9IFtdO1xuICAgIGQzX2dlb21fdm9yb25vaUNlbGxzID0gbmV3IEFycmF5KHNpdGVzLmxlbmd0aCk7XG4gICAgZDNfZ2VvbV92b3Jvbm9pQmVhY2hlcyA9IG5ldyBkM19nZW9tX3Zvcm9ub2lSZWRCbGFja1RyZWUoKTtcbiAgICBkM19nZW9tX3Zvcm9ub2lDaXJjbGVzID0gbmV3IGQzX2dlb21fdm9yb25vaVJlZEJsYWNrVHJlZSgpO1xuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjaXJjbGUgPSBkM19nZW9tX3Zvcm9ub2lGaXJzdENpcmNsZTtcbiAgICAgIGlmIChzaXRlICYmICghY2lyY2xlIHx8IHNpdGUueSA8IGNpcmNsZS55IHx8IHNpdGUueSA9PT0gY2lyY2xlLnkgJiYgc2l0ZS54IDwgY2lyY2xlLngpKSB7XG4gICAgICAgIGlmIChzaXRlLnggIT09IHgwIHx8IHNpdGUueSAhPT0geTApIHtcbiAgICAgICAgICBkM19nZW9tX3Zvcm9ub2lDZWxsc1tzaXRlLmldID0gbmV3IGQzX2dlb21fdm9yb25vaUNlbGwoc2l0ZSk7XG4gICAgICAgICAgZDNfZ2VvbV92b3Jvbm9pQWRkQmVhY2goc2l0ZSk7XG4gICAgICAgICAgeDAgPSBzaXRlLngsIHkwID0gc2l0ZS55O1xuICAgICAgICB9XG4gICAgICAgIHNpdGUgPSBzaXRlcy5wb3AoKTtcbiAgICAgIH0gZWxzZSBpZiAoY2lyY2xlKSB7XG4gICAgICAgIGQzX2dlb21fdm9yb25vaVJlbW92ZUJlYWNoKGNpcmNsZS5hcmMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChiYm94KSBkM19nZW9tX3Zvcm9ub2lDbGlwRWRnZXMoYmJveCksIGQzX2dlb21fdm9yb25vaUNsb3NlQ2VsbHMoYmJveCk7XG4gICAgdmFyIGRpYWdyYW0gPSB7XG4gICAgICBjZWxsczogZDNfZ2VvbV92b3Jvbm9pQ2VsbHMsXG4gICAgICBlZGdlczogZDNfZ2VvbV92b3Jvbm9pRWRnZXNcbiAgICB9O1xuICAgIGQzX2dlb21fdm9yb25vaUJlYWNoZXMgPSBkM19nZW9tX3Zvcm9ub2lDaXJjbGVzID0gZDNfZ2VvbV92b3Jvbm9pRWRnZXMgPSBkM19nZW9tX3Zvcm9ub2lDZWxscyA9IG51bGw7XG4gICAgcmV0dXJuIGRpYWdyYW07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV92b3Jvbm9pVmVydGV4T3JkZXIoYSwgYikge1xuICAgIHJldHVybiBiLnkgLSBhLnkgfHwgYi54IC0gYS54O1xuICB9XG4gIGQzLmdlb20udm9yb25vaSA9IGZ1bmN0aW9uKHBvaW50cykge1xuICAgIHZhciB4ID0gZDNfZ2VvbV9wb2ludFgsIHkgPSBkM19nZW9tX3BvaW50WSwgZnggPSB4LCBmeSA9IHksIGNsaXBFeHRlbnQgPSBkM19nZW9tX3Zvcm9ub2lDbGlwRXh0ZW50O1xuICAgIGlmIChwb2ludHMpIHJldHVybiB2b3Jvbm9pKHBvaW50cyk7XG4gICAgZnVuY3Rpb24gdm9yb25vaShkYXRhKSB7XG4gICAgICB2YXIgcG9seWdvbnMgPSBuZXcgQXJyYXkoZGF0YS5sZW5ndGgpLCB4MCA9IGNsaXBFeHRlbnRbMF1bMF0sIHkwID0gY2xpcEV4dGVudFswXVsxXSwgeDEgPSBjbGlwRXh0ZW50WzFdWzBdLCB5MSA9IGNsaXBFeHRlbnRbMV1bMV07XG4gICAgICBkM19nZW9tX3Zvcm9ub2koc2l0ZXMoZGF0YSksIGNsaXBFeHRlbnQpLmNlbGxzLmZvckVhY2goZnVuY3Rpb24oY2VsbCwgaSkge1xuICAgICAgICB2YXIgZWRnZXMgPSBjZWxsLmVkZ2VzLCBzaXRlID0gY2VsbC5zaXRlLCBwb2x5Z29uID0gcG9seWdvbnNbaV0gPSBlZGdlcy5sZW5ndGggPyBlZGdlcy5tYXAoZnVuY3Rpb24oZSkge1xuICAgICAgICAgIHZhciBzID0gZS5zdGFydCgpO1xuICAgICAgICAgIHJldHVybiBbIHMueCwgcy55IF07XG4gICAgICAgIH0pIDogc2l0ZS54ID49IHgwICYmIHNpdGUueCA8PSB4MSAmJiBzaXRlLnkgPj0geTAgJiYgc2l0ZS55IDw9IHkxID8gWyBbIHgwLCB5MSBdLCBbIHgxLCB5MSBdLCBbIHgxLCB5MCBdLCBbIHgwLCB5MCBdIF0gOiBbXTtcbiAgICAgICAgcG9seWdvbi5wb2ludCA9IGRhdGFbaV07XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBwb2x5Z29ucztcbiAgICB9XG4gICAgZnVuY3Rpb24gc2l0ZXMoZGF0YSkge1xuICAgICAgcmV0dXJuIGRhdGEubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB4OiBNYXRoLnJvdW5kKGZ4KGQsIGkpIC8gzrUpICogzrUsXG4gICAgICAgICAgeTogTWF0aC5yb3VuZChmeShkLCBpKSAvIM61KSAqIM61LFxuICAgICAgICAgIGk6IGlcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICB2b3Jvbm9pLmxpbmtzID0gZnVuY3Rpb24oZGF0YSkge1xuICAgICAgcmV0dXJuIGQzX2dlb21fdm9yb25vaShzaXRlcyhkYXRhKSkuZWRnZXMuZmlsdGVyKGZ1bmN0aW9uKGVkZ2UpIHtcbiAgICAgICAgcmV0dXJuIGVkZ2UubCAmJiBlZGdlLnI7XG4gICAgICB9KS5tYXAoZnVuY3Rpb24oZWRnZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHNvdXJjZTogZGF0YVtlZGdlLmwuaV0sXG4gICAgICAgICAgdGFyZ2V0OiBkYXRhW2VkZ2Uuci5pXVxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfTtcbiAgICB2b3Jvbm9pLnRyaWFuZ2xlcyA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgIHZhciB0cmlhbmdsZXMgPSBbXTtcbiAgICAgIGQzX2dlb21fdm9yb25vaShzaXRlcyhkYXRhKSkuY2VsbHMuZm9yRWFjaChmdW5jdGlvbihjZWxsLCBpKSB7XG4gICAgICAgIHZhciBzaXRlID0gY2VsbC5zaXRlLCBlZGdlcyA9IGNlbGwuZWRnZXMuc29ydChkM19nZW9tX3Zvcm9ub2lIYWxmRWRnZU9yZGVyKSwgaiA9IC0xLCBtID0gZWRnZXMubGVuZ3RoLCBlMCwgczAsIGUxID0gZWRnZXNbbSAtIDFdLmVkZ2UsIHMxID0gZTEubCA9PT0gc2l0ZSA/IGUxLnIgOiBlMS5sO1xuICAgICAgICB3aGlsZSAoKytqIDwgbSkge1xuICAgICAgICAgIGUwID0gZTE7XG4gICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICBlMSA9IGVkZ2VzW2pdLmVkZ2U7XG4gICAgICAgICAgczEgPSBlMS5sID09PSBzaXRlID8gZTEuciA6IGUxLmw7XG4gICAgICAgICAgaWYgKGkgPCBzMC5pICYmIGkgPCBzMS5pICYmIGQzX2dlb21fdm9yb25vaVRyaWFuZ2xlQXJlYShzaXRlLCBzMCwgczEpIDwgMCkge1xuICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goWyBkYXRhW2ldLCBkYXRhW3MwLmldLCBkYXRhW3MxLmldIF0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gdHJpYW5nbGVzO1xuICAgIH07XG4gICAgdm9yb25vaS54ID0gZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZnggPSBkM19mdW5jdG9yKHggPSBfKSwgdm9yb25vaSkgOiB4O1xuICAgIH07XG4gICAgdm9yb25vaS55ID0gZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZnkgPSBkM19mdW5jdG9yKHkgPSBfKSwgdm9yb25vaSkgOiB5O1xuICAgIH07XG4gICAgdm9yb25vaS5jbGlwRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY2xpcEV4dGVudCA9PT0gZDNfZ2VvbV92b3Jvbm9pQ2xpcEV4dGVudCA/IG51bGwgOiBjbGlwRXh0ZW50O1xuICAgICAgY2xpcEV4dGVudCA9IF8gPT0gbnVsbCA/IGQzX2dlb21fdm9yb25vaUNsaXBFeHRlbnQgOiBfO1xuICAgICAgcmV0dXJuIHZvcm9ub2k7XG4gICAgfTtcbiAgICB2b3Jvbm9pLnNpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjbGlwRXh0ZW50ID09PSBkM19nZW9tX3Zvcm9ub2lDbGlwRXh0ZW50ID8gbnVsbCA6IGNsaXBFeHRlbnQgJiYgY2xpcEV4dGVudFsxXTtcbiAgICAgIHJldHVybiB2b3Jvbm9pLmNsaXBFeHRlbnQoXyAmJiBbIFsgMCwgMCBdLCBfIF0pO1xuICAgIH07XG4gICAgcmV0dXJuIHZvcm9ub2k7XG4gIH07XG4gIHZhciBkM19nZW9tX3Zvcm9ub2lDbGlwRXh0ZW50ID0gWyBbIC0xZTYsIC0xZTYgXSwgWyAxZTYsIDFlNiBdIF07XG4gIGZ1bmN0aW9uIGQzX2dlb21fdm9yb25vaVRyaWFuZ2xlQXJlYShhLCBiLCBjKSB7XG4gICAgcmV0dXJuIChhLnggLSBjLngpICogKGIueSAtIGEueSkgLSAoYS54IC0gYi54KSAqIChjLnkgLSBhLnkpO1xuICB9XG4gIGQzLmdlb20uZGVsYXVuYXkgPSBmdW5jdGlvbih2ZXJ0aWNlcykge1xuICAgIHJldHVybiBkMy5nZW9tLnZvcm9ub2koKS50cmlhbmdsZXModmVydGljZXMpO1xuICB9O1xuICBkMy5nZW9tLnF1YWR0cmVlID0gZnVuY3Rpb24ocG9pbnRzLCB4MSwgeTEsIHgyLCB5Mikge1xuICAgIHZhciB4ID0gZDNfZ2VvbV9wb2ludFgsIHkgPSBkM19nZW9tX3BvaW50WSwgY29tcGF0O1xuICAgIGlmIChjb21wYXQgPSBhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICB4ID0gZDNfZ2VvbV9xdWFkdHJlZUNvbXBhdFg7XG4gICAgICB5ID0gZDNfZ2VvbV9xdWFkdHJlZUNvbXBhdFk7XG4gICAgICBpZiAoY29tcGF0ID09PSAzKSB7XG4gICAgICAgIHkyID0geTE7XG4gICAgICAgIHgyID0geDE7XG4gICAgICAgIHkxID0geDEgPSAwO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHF1YWR0cmVlKHBvaW50cyk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHF1YWR0cmVlKGRhdGEpIHtcbiAgICAgIHZhciBkLCBmeCA9IGQzX2Z1bmN0b3IoeCksIGZ5ID0gZDNfZnVuY3Rvcih5KSwgeHMsIHlzLCBpLCBuLCB4MV8sIHkxXywgeDJfLCB5Ml87XG4gICAgICBpZiAoeDEgIT0gbnVsbCkge1xuICAgICAgICB4MV8gPSB4MSwgeTFfID0geTEsIHgyXyA9IHgyLCB5Ml8gPSB5MjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHgyXyA9IHkyXyA9IC0oeDFfID0geTFfID0gSW5maW5pdHkpO1xuICAgICAgICB4cyA9IFtdLCB5cyA9IFtdO1xuICAgICAgICBuID0gZGF0YS5sZW5ndGg7XG4gICAgICAgIGlmIChjb21wYXQpIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICBkID0gZGF0YVtpXTtcbiAgICAgICAgICBpZiAoZC54IDwgeDFfKSB4MV8gPSBkLng7XG4gICAgICAgICAgaWYgKGQueSA8IHkxXykgeTFfID0gZC55O1xuICAgICAgICAgIGlmIChkLnggPiB4Ml8pIHgyXyA9IGQueDtcbiAgICAgICAgICBpZiAoZC55ID4geTJfKSB5Ml8gPSBkLnk7XG4gICAgICAgICAgeHMucHVzaChkLngpO1xuICAgICAgICAgIHlzLnB1c2goZC55KTtcbiAgICAgICAgfSBlbHNlIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICB2YXIgeF8gPSArZngoZCA9IGRhdGFbaV0sIGkpLCB5XyA9ICtmeShkLCBpKTtcbiAgICAgICAgICBpZiAoeF8gPCB4MV8pIHgxXyA9IHhfO1xuICAgICAgICAgIGlmICh5XyA8IHkxXykgeTFfID0geV87XG4gICAgICAgICAgaWYgKHhfID4geDJfKSB4Ml8gPSB4XztcbiAgICAgICAgICBpZiAoeV8gPiB5Ml8pIHkyXyA9IHlfO1xuICAgICAgICAgIHhzLnB1c2goeF8pO1xuICAgICAgICAgIHlzLnB1c2goeV8pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB2YXIgZHggPSB4Ml8gLSB4MV8sIGR5ID0geTJfIC0geTFfO1xuICAgICAgaWYgKGR4ID4gZHkpIHkyXyA9IHkxXyArIGR4OyBlbHNlIHgyXyA9IHgxXyArIGR5O1xuICAgICAgZnVuY3Rpb24gaW5zZXJ0KG4sIGQsIHgsIHksIHgxLCB5MSwgeDIsIHkyKSB7XG4gICAgICAgIGlmIChpc05hTih4KSB8fCBpc05hTih5KSkgcmV0dXJuO1xuICAgICAgICBpZiAobi5sZWFmKSB7XG4gICAgICAgICAgdmFyIG54ID0gbi54LCBueSA9IG4ueTtcbiAgICAgICAgICBpZiAobnggIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKGFicyhueCAtIHgpICsgYWJzKG55IC0geSkgPCAuMDEpIHtcbiAgICAgICAgICAgICAgaW5zZXJ0Q2hpbGQobiwgZCwgeCwgeSwgeDEsIHkxLCB4MiwgeTIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdmFyIG5Qb2ludCA9IG4ucG9pbnQ7XG4gICAgICAgICAgICAgIG4ueCA9IG4ueSA9IG4ucG9pbnQgPSBudWxsO1xuICAgICAgICAgICAgICBpbnNlcnRDaGlsZChuLCBuUG9pbnQsIG54LCBueSwgeDEsIHkxLCB4MiwgeTIpO1xuICAgICAgICAgICAgICBpbnNlcnRDaGlsZChuLCBkLCB4LCB5LCB4MSwgeTEsIHgyLCB5Mik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG4ueCA9IHgsIG4ueSA9IHksIG4ucG9pbnQgPSBkO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbnNlcnRDaGlsZChuLCBkLCB4LCB5LCB4MSwgeTEsIHgyLCB5Mik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZ1bmN0aW9uIGluc2VydENoaWxkKG4sIGQsIHgsIHksIHgxLCB5MSwgeDIsIHkyKSB7XG4gICAgICAgIHZhciB4bSA9ICh4MSArIHgyKSAqIC41LCB5bSA9ICh5MSArIHkyKSAqIC41LCByaWdodCA9IHggPj0geG0sIGJlbG93ID0geSA+PSB5bSwgaSA9IGJlbG93IDw8IDEgfCByaWdodDtcbiAgICAgICAgbi5sZWFmID0gZmFsc2U7XG4gICAgICAgIG4gPSBuLm5vZGVzW2ldIHx8IChuLm5vZGVzW2ldID0gZDNfZ2VvbV9xdWFkdHJlZU5vZGUoKSk7XG4gICAgICAgIGlmIChyaWdodCkgeDEgPSB4bTsgZWxzZSB4MiA9IHhtO1xuICAgICAgICBpZiAoYmVsb3cpIHkxID0geW07IGVsc2UgeTIgPSB5bTtcbiAgICAgICAgaW5zZXJ0KG4sIGQsIHgsIHksIHgxLCB5MSwgeDIsIHkyKTtcbiAgICAgIH1cbiAgICAgIHZhciByb290ID0gZDNfZ2VvbV9xdWFkdHJlZU5vZGUoKTtcbiAgICAgIHJvb3QuYWRkID0gZnVuY3Rpb24oZCkge1xuICAgICAgICBpbnNlcnQocm9vdCwgZCwgK2Z4KGQsICsraSksICtmeShkLCBpKSwgeDFfLCB5MV8sIHgyXywgeTJfKTtcbiAgICAgIH07XG4gICAgICByb290LnZpc2l0ID0gZnVuY3Rpb24oZikge1xuICAgICAgICBkM19nZW9tX3F1YWR0cmVlVmlzaXQoZiwgcm9vdCwgeDFfLCB5MV8sIHgyXywgeTJfKTtcbiAgICAgIH07XG4gICAgICByb290LmZpbmQgPSBmdW5jdGlvbihwb2ludCkge1xuICAgICAgICByZXR1cm4gZDNfZ2VvbV9xdWFkdHJlZUZpbmQocm9vdCwgcG9pbnRbMF0sIHBvaW50WzFdLCB4MV8sIHkxXywgeDJfLCB5Ml8pO1xuICAgICAgfTtcbiAgICAgIGkgPSAtMTtcbiAgICAgIGlmICh4MSA9PSBudWxsKSB7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgaW5zZXJ0KHJvb3QsIGRhdGFbaV0sIHhzW2ldLCB5c1tpXSwgeDFfLCB5MV8sIHgyXywgeTJfKTtcbiAgICAgICAgfVxuICAgICAgICAtLWk7XG4gICAgICB9IGVsc2UgZGF0YS5mb3JFYWNoKHJvb3QuYWRkKTtcbiAgICAgIHhzID0geXMgPSBkYXRhID0gZCA9IG51bGw7XG4gICAgICByZXR1cm4gcm9vdDtcbiAgICB9XG4gICAgcXVhZHRyZWUueCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHggPSBfLCBxdWFkdHJlZSkgOiB4O1xuICAgIH07XG4gICAgcXVhZHRyZWUueSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHkgPSBfLCBxdWFkdHJlZSkgOiB5O1xuICAgIH07XG4gICAgcXVhZHRyZWUuZXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDEgPT0gbnVsbCA/IG51bGwgOiBbIFsgeDEsIHkxIF0sIFsgeDIsIHkyIF0gXTtcbiAgICAgIGlmIChfID09IG51bGwpIHgxID0geTEgPSB4MiA9IHkyID0gbnVsbDsgZWxzZSB4MSA9ICtfWzBdWzBdLCB5MSA9ICtfWzBdWzFdLCB4MiA9ICtfWzFdWzBdLCBcbiAgICAgIHkyID0gK19bMV1bMV07XG4gICAgICByZXR1cm4gcXVhZHRyZWU7XG4gICAgfTtcbiAgICBxdWFkdHJlZS5zaXplID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDEgPT0gbnVsbCA/IG51bGwgOiBbIHgyIC0geDEsIHkyIC0geTEgXTtcbiAgICAgIGlmIChfID09IG51bGwpIHgxID0geTEgPSB4MiA9IHkyID0gbnVsbDsgZWxzZSB4MSA9IHkxID0gMCwgeDIgPSArX1swXSwgeTIgPSArX1sxXTtcbiAgICAgIHJldHVybiBxdWFkdHJlZTtcbiAgICB9O1xuICAgIHJldHVybiBxdWFkdHJlZTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvbV9xdWFkdHJlZUNvbXBhdFgoZCkge1xuICAgIHJldHVybiBkLng7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9xdWFkdHJlZUNvbXBhdFkoZCkge1xuICAgIHJldHVybiBkLnk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9xdWFkdHJlZU5vZGUoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxlYWY6IHRydWUsXG4gICAgICBub2RlczogW10sXG4gICAgICBwb2ludDogbnVsbCxcbiAgICAgIHg6IG51bGwsXG4gICAgICB5OiBudWxsXG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9tX3F1YWR0cmVlVmlzaXQoZiwgbm9kZSwgeDEsIHkxLCB4MiwgeTIpIHtcbiAgICBpZiAoIWYobm9kZSwgeDEsIHkxLCB4MiwgeTIpKSB7XG4gICAgICB2YXIgc3ggPSAoeDEgKyB4MikgKiAuNSwgc3kgPSAoeTEgKyB5MikgKiAuNSwgY2hpbGRyZW4gPSBub2RlLm5vZGVzO1xuICAgICAgaWYgKGNoaWxkcmVuWzBdKSBkM19nZW9tX3F1YWR0cmVlVmlzaXQoZiwgY2hpbGRyZW5bMF0sIHgxLCB5MSwgc3gsIHN5KTtcbiAgICAgIGlmIChjaGlsZHJlblsxXSkgZDNfZ2VvbV9xdWFkdHJlZVZpc2l0KGYsIGNoaWxkcmVuWzFdLCBzeCwgeTEsIHgyLCBzeSk7XG4gICAgICBpZiAoY2hpbGRyZW5bMl0pIGQzX2dlb21fcXVhZHRyZWVWaXNpdChmLCBjaGlsZHJlblsyXSwgeDEsIHN5LCBzeCwgeTIpO1xuICAgICAgaWYgKGNoaWxkcmVuWzNdKSBkM19nZW9tX3F1YWR0cmVlVmlzaXQoZiwgY2hpbGRyZW5bM10sIHN4LCBzeSwgeDIsIHkyKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfZ2VvbV9xdWFkdHJlZUZpbmQocm9vdCwgeCwgeSwgeDAsIHkwLCB4MywgeTMpIHtcbiAgICB2YXIgbWluRGlzdGFuY2UyID0gSW5maW5pdHksIGNsb3Nlc3RQb2ludDtcbiAgICAoZnVuY3Rpb24gZmluZChub2RlLCB4MSwgeTEsIHgyLCB5Mikge1xuICAgICAgaWYgKHgxID4geDMgfHwgeTEgPiB5MyB8fCB4MiA8IHgwIHx8IHkyIDwgeTApIHJldHVybjtcbiAgICAgIGlmIChwb2ludCA9IG5vZGUucG9pbnQpIHtcbiAgICAgICAgdmFyIHBvaW50LCBkeCA9IHggLSBub2RlLngsIGR5ID0geSAtIG5vZGUueSwgZGlzdGFuY2UyID0gZHggKiBkeCArIGR5ICogZHk7XG4gICAgICAgIGlmIChkaXN0YW5jZTIgPCBtaW5EaXN0YW5jZTIpIHtcbiAgICAgICAgICB2YXIgZGlzdGFuY2UgPSBNYXRoLnNxcnQobWluRGlzdGFuY2UyID0gZGlzdGFuY2UyKTtcbiAgICAgICAgICB4MCA9IHggLSBkaXN0YW5jZSwgeTAgPSB5IC0gZGlzdGFuY2U7XG4gICAgICAgICAgeDMgPSB4ICsgZGlzdGFuY2UsIHkzID0geSArIGRpc3RhbmNlO1xuICAgICAgICAgIGNsb3Nlc3RQb2ludCA9IHBvaW50O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB2YXIgY2hpbGRyZW4gPSBub2RlLm5vZGVzLCB4bSA9ICh4MSArIHgyKSAqIC41LCB5bSA9ICh5MSArIHkyKSAqIC41LCByaWdodCA9IHggPj0geG0sIGJlbG93ID0geSA+PSB5bTtcbiAgICAgIGZvciAodmFyIGkgPSBiZWxvdyA8PCAxIHwgcmlnaHQsIGogPSBpICsgNDsgaSA8IGo7ICsraSkge1xuICAgICAgICBpZiAobm9kZSA9IGNoaWxkcmVuW2kgJiAzXSkgc3dpdGNoIChpICYgMykge1xuICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGZpbmQobm9kZSwgeDEsIHkxLCB4bSwgeW0pO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgZmluZChub2RlLCB4bSwgeTEsIHgyLCB5bSk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBmaW5kKG5vZGUsIHgxLCB5bSwgeG0sIHkyKTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIGZpbmQobm9kZSwgeG0sIHltLCB4MiwgeTIpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSkocm9vdCwgeDAsIHkwLCB4MywgeTMpO1xuICAgIHJldHVybiBjbG9zZXN0UG9pbnQ7XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVSZ2IgPSBkM19pbnRlcnBvbGF0ZVJnYjtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVSZ2IoYSwgYikge1xuICAgIGEgPSBkMy5yZ2IoYSk7XG4gICAgYiA9IGQzLnJnYihiKTtcbiAgICB2YXIgYXIgPSBhLnIsIGFnID0gYS5nLCBhYiA9IGEuYiwgYnIgPSBiLnIgLSBhciwgYmcgPSBiLmcgLSBhZywgYmIgPSBiLmIgLSBhYjtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIFwiI1wiICsgZDNfcmdiX2hleChNYXRoLnJvdW5kKGFyICsgYnIgKiB0KSkgKyBkM19yZ2JfaGV4KE1hdGgucm91bmQoYWcgKyBiZyAqIHQpKSArIGQzX3JnYl9oZXgoTWF0aC5yb3VuZChhYiArIGJiICogdCkpO1xuICAgIH07XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVPYmplY3QgPSBkM19pbnRlcnBvbGF0ZU9iamVjdDtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVPYmplY3QoYSwgYikge1xuICAgIHZhciBpID0ge30sIGMgPSB7fSwgaztcbiAgICBmb3IgKGsgaW4gYSkge1xuICAgICAgaWYgKGsgaW4gYikge1xuICAgICAgICBpW2tdID0gZDNfaW50ZXJwb2xhdGUoYVtrXSwgYltrXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjW2tdID0gYVtrXTtcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yIChrIGluIGIpIHtcbiAgICAgIGlmICghKGsgaW4gYSkpIHtcbiAgICAgICAgY1trXSA9IGJba107XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICBmb3IgKGsgaW4gaSkgY1trXSA9IGlba10odCk7XG4gICAgICByZXR1cm4gYztcbiAgICB9O1xuICB9XG4gIGQzLmludGVycG9sYXRlTnVtYmVyID0gZDNfaW50ZXJwb2xhdGVOdW1iZXI7XG4gIGZ1bmN0aW9uIGQzX2ludGVycG9sYXRlTnVtYmVyKGEsIGIpIHtcbiAgICBhID0gK2EsIGIgPSArYjtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGEgKiAoMSAtIHQpICsgYiAqIHQ7XG4gICAgfTtcbiAgfVxuICBkMy5pbnRlcnBvbGF0ZVN0cmluZyA9IGQzX2ludGVycG9sYXRlU3RyaW5nO1xuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVN0cmluZyhhLCBiKSB7XG4gICAgdmFyIGJpID0gZDNfaW50ZXJwb2xhdGVfbnVtYmVyQS5sYXN0SW5kZXggPSBkM19pbnRlcnBvbGF0ZV9udW1iZXJCLmxhc3RJbmRleCA9IDAsIGFtLCBibSwgYnMsIGkgPSAtMSwgcyA9IFtdLCBxID0gW107XG4gICAgYSA9IGEgKyBcIlwiLCBiID0gYiArIFwiXCI7XG4gICAgd2hpbGUgKChhbSA9IGQzX2ludGVycG9sYXRlX251bWJlckEuZXhlYyhhKSkgJiYgKGJtID0gZDNfaW50ZXJwb2xhdGVfbnVtYmVyQi5leGVjKGIpKSkge1xuICAgICAgaWYgKChicyA9IGJtLmluZGV4KSA+IGJpKSB7XG4gICAgICAgIGJzID0gYi5zbGljZShiaSwgYnMpO1xuICAgICAgICBpZiAoc1tpXSkgc1tpXSArPSBiczsgZWxzZSBzWysraV0gPSBicztcbiAgICAgIH1cbiAgICAgIGlmICgoYW0gPSBhbVswXSkgPT09IChibSA9IGJtWzBdKSkge1xuICAgICAgICBpZiAoc1tpXSkgc1tpXSArPSBibTsgZWxzZSBzWysraV0gPSBibTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNbKytpXSA9IG51bGw7XG4gICAgICAgIHEucHVzaCh7XG4gICAgICAgICAgaTogaSxcbiAgICAgICAgICB4OiBkM19pbnRlcnBvbGF0ZU51bWJlcihhbSwgYm0pXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgYmkgPSBkM19pbnRlcnBvbGF0ZV9udW1iZXJCLmxhc3RJbmRleDtcbiAgICB9XG4gICAgaWYgKGJpIDwgYi5sZW5ndGgpIHtcbiAgICAgIGJzID0gYi5zbGljZShiaSk7XG4gICAgICBpZiAoc1tpXSkgc1tpXSArPSBiczsgZWxzZSBzWysraV0gPSBicztcbiAgICB9XG4gICAgcmV0dXJuIHMubGVuZ3RoIDwgMiA/IHFbMF0gPyAoYiA9IHFbMF0ueCwgZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGIodCkgKyBcIlwiO1xuICAgIH0pIDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gYjtcbiAgICB9IDogKGIgPSBxLmxlbmd0aCwgZnVuY3Rpb24odCkge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIG87IGkgPCBiOyArK2kpIHNbKG8gPSBxW2ldKS5pXSA9IG8ueCh0KTtcbiAgICAgIHJldHVybiBzLmpvaW4oXCJcIik7XG4gICAgfSk7XG4gIH1cbiAgdmFyIGQzX2ludGVycG9sYXRlX251bWJlckEgPSAvWy0rXT8oPzpcXGQrXFwuP1xcZCp8XFwuP1xcZCspKD86W2VFXVstK10/XFxkKyk/L2csIGQzX2ludGVycG9sYXRlX251bWJlckIgPSBuZXcgUmVnRXhwKGQzX2ludGVycG9sYXRlX251bWJlckEuc291cmNlLCBcImdcIik7XG4gIGQzLmludGVycG9sYXRlID0gZDNfaW50ZXJwb2xhdGU7XG4gIGZ1bmN0aW9uIGQzX2ludGVycG9sYXRlKGEsIGIpIHtcbiAgICB2YXIgaSA9IGQzLmludGVycG9sYXRvcnMubGVuZ3RoLCBmO1xuICAgIHdoaWxlICgtLWkgPj0gMCAmJiAhKGYgPSBkMy5pbnRlcnBvbGF0b3JzW2ldKGEsIGIpKSkgO1xuICAgIHJldHVybiBmO1xuICB9XG4gIGQzLmludGVycG9sYXRvcnMgPSBbIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgdCA9IHR5cGVvZiBiO1xuICAgIHJldHVybiAodCA9PT0gXCJzdHJpbmdcIiA/IGQzX3JnYl9uYW1lcy5oYXMoYi50b0xvd2VyQ2FzZSgpKSB8fCAvXigjfHJnYlxcKHxoc2xcXCgpL2kudGVzdChiKSA/IGQzX2ludGVycG9sYXRlUmdiIDogZDNfaW50ZXJwb2xhdGVTdHJpbmcgOiBiIGluc3RhbmNlb2YgZDNfY29sb3IgPyBkM19pbnRlcnBvbGF0ZVJnYiA6IEFycmF5LmlzQXJyYXkoYikgPyBkM19pbnRlcnBvbGF0ZUFycmF5IDogdCA9PT0gXCJvYmplY3RcIiAmJiBpc05hTihiKSA/IGQzX2ludGVycG9sYXRlT2JqZWN0IDogZDNfaW50ZXJwb2xhdGVOdW1iZXIpKGEsIGIpO1xuICB9IF07XG4gIGQzLmludGVycG9sYXRlQXJyYXkgPSBkM19pbnRlcnBvbGF0ZUFycmF5O1xuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZUFycmF5KGEsIGIpIHtcbiAgICB2YXIgeCA9IFtdLCBjID0gW10sIG5hID0gYS5sZW5ndGgsIG5iID0gYi5sZW5ndGgsIG4wID0gTWF0aC5taW4oYS5sZW5ndGgsIGIubGVuZ3RoKSwgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjA7ICsraSkgeC5wdXNoKGQzX2ludGVycG9sYXRlKGFbaV0sIGJbaV0pKTtcbiAgICBmb3IgKDtpIDwgbmE7ICsraSkgY1tpXSA9IGFbaV07XG4gICAgZm9yICg7aSA8IG5iOyArK2kpIGNbaV0gPSBiW2ldO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjA7ICsraSkgY1tpXSA9IHhbaV0odCk7XG4gICAgICByZXR1cm4gYztcbiAgICB9O1xuICB9XG4gIHZhciBkM19lYXNlX2RlZmF1bHQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfaWRlbnRpdHk7XG4gIH07XG4gIHZhciBkM19lYXNlID0gZDMubWFwKHtcbiAgICBsaW5lYXI6IGQzX2Vhc2VfZGVmYXVsdCxcbiAgICBwb2x5OiBkM19lYXNlX3BvbHksXG4gICAgcXVhZDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfZWFzZV9xdWFkO1xuICAgIH0sXG4gICAgY3ViaWM6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX2Vhc2VfY3ViaWM7XG4gICAgfSxcbiAgICBzaW46IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX2Vhc2Vfc2luO1xuICAgIH0sXG4gICAgZXhwOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkM19lYXNlX2V4cDtcbiAgICB9LFxuICAgIGNpcmNsZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfZWFzZV9jaXJjbGU7XG4gICAgfSxcbiAgICBlbGFzdGljOiBkM19lYXNlX2VsYXN0aWMsXG4gICAgYmFjazogZDNfZWFzZV9iYWNrLFxuICAgIGJvdW5jZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfZWFzZV9ib3VuY2U7XG4gICAgfVxuICB9KTtcbiAgdmFyIGQzX2Vhc2VfbW9kZSA9IGQzLm1hcCh7XG4gICAgXCJpblwiOiBkM19pZGVudGl0eSxcbiAgICBvdXQ6IGQzX2Vhc2VfcmV2ZXJzZSxcbiAgICBcImluLW91dFwiOiBkM19lYXNlX3JlZmxlY3QsXG4gICAgXCJvdXQtaW5cIjogZnVuY3Rpb24oZikge1xuICAgICAgcmV0dXJuIGQzX2Vhc2VfcmVmbGVjdChkM19lYXNlX3JldmVyc2UoZikpO1xuICAgIH1cbiAgfSk7XG4gIGQzLmVhc2UgPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgdmFyIGkgPSBuYW1lLmluZGV4T2YoXCItXCIpLCB0ID0gaSA+PSAwID8gbmFtZS5zbGljZSgwLCBpKSA6IG5hbWUsIG0gPSBpID49IDAgPyBuYW1lLnNsaWNlKGkgKyAxKSA6IFwiaW5cIjtcbiAgICB0ID0gZDNfZWFzZS5nZXQodCkgfHwgZDNfZWFzZV9kZWZhdWx0O1xuICAgIG0gPSBkM19lYXNlX21vZGUuZ2V0KG0pIHx8IGQzX2lkZW50aXR5O1xuICAgIHJldHVybiBkM19lYXNlX2NsYW1wKG0odC5hcHBseShudWxsLCBkM19hcnJheVNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSkpKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZWFzZV9jbGFtcChmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiB0IDw9IDAgPyAwIDogdCA+PSAxID8gMSA6IGYodCk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX3JldmVyc2UoZikge1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICByZXR1cm4gMSAtIGYoMSAtIHQpO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfZWFzZV9yZWZsZWN0KGYpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIC41ICogKHQgPCAuNSA/IGYoMiAqIHQpIDogMiAtIGYoMiAtIDIgKiB0KSk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX3F1YWQodCkge1xuICAgIHJldHVybiB0ICogdDtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX2N1YmljKHQpIHtcbiAgICByZXR1cm4gdCAqIHQgKiB0O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2VfY3ViaWNJbk91dCh0KSB7XG4gICAgaWYgKHQgPD0gMCkgcmV0dXJuIDA7XG4gICAgaWYgKHQgPj0gMSkgcmV0dXJuIDE7XG4gICAgdmFyIHQyID0gdCAqIHQsIHQzID0gdDIgKiB0O1xuICAgIHJldHVybiA0ICogKHQgPCAuNSA/IHQzIDogMyAqICh0IC0gdDIpICsgdDMgLSAuNzUpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2VfcG9seShlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIHJldHVybiBNYXRoLnBvdyh0LCBlKTtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2Vfc2luKHQpIHtcbiAgICByZXR1cm4gMSAtIE1hdGguY29zKHQgKiBoYWxmz4ApO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2VfZXhwKHQpIHtcbiAgICByZXR1cm4gTWF0aC5wb3coMiwgMTAgKiAodCAtIDEpKTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX2NpcmNsZSh0KSB7XG4gICAgcmV0dXJuIDEgLSBNYXRoLnNxcnQoMSAtIHQgKiB0KTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX2VsYXN0aWMoYSwgcCkge1xuICAgIHZhciBzO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikgcCA9IC40NTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCkgcyA9IHAgLyDPhCAqIE1hdGguYXNpbigxIC8gYSk7IGVsc2UgYSA9IDEsIHMgPSBwIC8gNDtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIDEgKyBhICogTWF0aC5wb3coMiwgLTEwICogdCkgKiBNYXRoLnNpbigodCAtIHMpICogz4QgLyBwKTtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2Vhc2VfYmFjayhzKSB7XG4gICAgaWYgKCFzKSBzID0gMS43MDE1ODtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIHQgKiB0ICogKChzICsgMSkgKiB0IC0gcyk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19lYXNlX2JvdW5jZSh0KSB7XG4gICAgcmV0dXJuIHQgPCAxIC8gMi43NSA/IDcuNTYyNSAqIHQgKiB0IDogdCA8IDIgLyAyLjc1ID8gNy41NjI1ICogKHQgLT0gMS41IC8gMi43NSkgKiB0ICsgLjc1IDogdCA8IDIuNSAvIDIuNzUgPyA3LjU2MjUgKiAodCAtPSAyLjI1IC8gMi43NSkgKiB0ICsgLjkzNzUgOiA3LjU2MjUgKiAodCAtPSAyLjYyNSAvIDIuNzUpICogdCArIC45ODQzNzU7XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVIY2wgPSBkM19pbnRlcnBvbGF0ZUhjbDtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVIY2woYSwgYikge1xuICAgIGEgPSBkMy5oY2woYSk7XG4gICAgYiA9IGQzLmhjbChiKTtcbiAgICB2YXIgYWggPSBhLmgsIGFjID0gYS5jLCBhbCA9IGEubCwgYmggPSBiLmggLSBhaCwgYmMgPSBiLmMgLSBhYywgYmwgPSBiLmwgLSBhbDtcbiAgICBpZiAoaXNOYU4oYmMpKSBiYyA9IDAsIGFjID0gaXNOYU4oYWMpID8gYi5jIDogYWM7XG4gICAgaWYgKGlzTmFOKGJoKSkgYmggPSAwLCBhaCA9IGlzTmFOKGFoKSA/IGIuaCA6IGFoOyBlbHNlIGlmIChiaCA+IDE4MCkgYmggLT0gMzYwOyBlbHNlIGlmIChiaCA8IC0xODApIGJoICs9IDM2MDtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGQzX2hjbF9sYWIoYWggKyBiaCAqIHQsIGFjICsgYmMgKiB0LCBhbCArIGJsICogdCkgKyBcIlwiO1xuICAgIH07XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVIc2wgPSBkM19pbnRlcnBvbGF0ZUhzbDtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVIc2woYSwgYikge1xuICAgIGEgPSBkMy5oc2woYSk7XG4gICAgYiA9IGQzLmhzbChiKTtcbiAgICB2YXIgYWggPSBhLmgsIGFzID0gYS5zLCBhbCA9IGEubCwgYmggPSBiLmggLSBhaCwgYnMgPSBiLnMgLSBhcywgYmwgPSBiLmwgLSBhbDtcbiAgICBpZiAoaXNOYU4oYnMpKSBicyA9IDAsIGFzID0gaXNOYU4oYXMpID8gYi5zIDogYXM7XG4gICAgaWYgKGlzTmFOKGJoKSkgYmggPSAwLCBhaCA9IGlzTmFOKGFoKSA/IGIuaCA6IGFoOyBlbHNlIGlmIChiaCA+IDE4MCkgYmggLT0gMzYwOyBlbHNlIGlmIChiaCA8IC0xODApIGJoICs9IDM2MDtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGQzX2hzbF9yZ2IoYWggKyBiaCAqIHQsIGFzICsgYnMgKiB0LCBhbCArIGJsICogdCkgKyBcIlwiO1xuICAgIH07XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVMYWIgPSBkM19pbnRlcnBvbGF0ZUxhYjtcbiAgZnVuY3Rpb24gZDNfaW50ZXJwb2xhdGVMYWIoYSwgYikge1xuICAgIGEgPSBkMy5sYWIoYSk7XG4gICAgYiA9IGQzLmxhYihiKTtcbiAgICB2YXIgYWwgPSBhLmwsIGFhID0gYS5hLCBhYiA9IGEuYiwgYmwgPSBiLmwgLSBhbCwgYmEgPSBiLmEgLSBhYSwgYmIgPSBiLmIgLSBhYjtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIGQzX2xhYl9yZ2IoYWwgKyBibCAqIHQsIGFhICsgYmEgKiB0LCBhYiArIGJiICogdCkgKyBcIlwiO1xuICAgIH07XG4gIH1cbiAgZDMuaW50ZXJwb2xhdGVSb3VuZCA9IGQzX2ludGVycG9sYXRlUm91bmQ7XG4gIGZ1bmN0aW9uIGQzX2ludGVycG9sYXRlUm91bmQoYSwgYikge1xuICAgIGIgLT0gYTtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIE1hdGgucm91bmQoYSArIGIgKiB0KTtcbiAgICB9O1xuICB9XG4gIGQzLnRyYW5zZm9ybSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgIHZhciBnID0gZDNfZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKGQzLm5zLnByZWZpeC5zdmcsIFwiZ1wiKTtcbiAgICByZXR1cm4gKGQzLnRyYW5zZm9ybSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgaWYgKHN0cmluZyAhPSBudWxsKSB7XG4gICAgICAgIGcuc2V0QXR0cmlidXRlKFwidHJhbnNmb3JtXCIsIHN0cmluZyk7XG4gICAgICAgIHZhciB0ID0gZy50cmFuc2Zvcm0uYmFzZVZhbC5jb25zb2xpZGF0ZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBkM190cmFuc2Zvcm0odCA/IHQubWF0cml4IDogZDNfdHJhbnNmb3JtSWRlbnRpdHkpO1xuICAgIH0pKHN0cmluZyk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RyYW5zZm9ybShtKSB7XG4gICAgdmFyIHIwID0gWyBtLmEsIG0uYiBdLCByMSA9IFsgbS5jLCBtLmQgXSwga3ggPSBkM190cmFuc2Zvcm1Ob3JtYWxpemUocjApLCBreiA9IGQzX3RyYW5zZm9ybURvdChyMCwgcjEpLCBreSA9IGQzX3RyYW5zZm9ybU5vcm1hbGl6ZShkM190cmFuc2Zvcm1Db21iaW5lKHIxLCByMCwgLWt6KSkgfHwgMDtcbiAgICBpZiAocjBbMF0gKiByMVsxXSA8IHIxWzBdICogcjBbMV0pIHtcbiAgICAgIHIwWzBdICo9IC0xO1xuICAgICAgcjBbMV0gKj0gLTE7XG4gICAgICBreCAqPSAtMTtcbiAgICAgIGt6ICo9IC0xO1xuICAgIH1cbiAgICB0aGlzLnJvdGF0ZSA9IChreCA/IE1hdGguYXRhbjIocjBbMV0sIHIwWzBdKSA6IE1hdGguYXRhbjIoLXIxWzBdLCByMVsxXSkpICogZDNfZGVncmVlcztcbiAgICB0aGlzLnRyYW5zbGF0ZSA9IFsgbS5lLCBtLmYgXTtcbiAgICB0aGlzLnNjYWxlID0gWyBreCwga3kgXTtcbiAgICB0aGlzLnNrZXcgPSBreSA/IE1hdGguYXRhbjIoa3osIGt5KSAqIGQzX2RlZ3JlZXMgOiAwO1xuICB9XG4gIGQzX3RyYW5zZm9ybS5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gXCJ0cmFuc2xhdGUoXCIgKyB0aGlzLnRyYW5zbGF0ZSArIFwiKXJvdGF0ZShcIiArIHRoaXMucm90YXRlICsgXCIpc2tld1goXCIgKyB0aGlzLnNrZXcgKyBcIilzY2FsZShcIiArIHRoaXMuc2NhbGUgKyBcIilcIjtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfdHJhbnNmb3JtRG90KGEsIGIpIHtcbiAgICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXTtcbiAgfVxuICBmdW5jdGlvbiBkM190cmFuc2Zvcm1Ob3JtYWxpemUoYSkge1xuICAgIHZhciBrID0gTWF0aC5zcXJ0KGQzX3RyYW5zZm9ybURvdChhLCBhKSk7XG4gICAgaWYgKGspIHtcbiAgICAgIGFbMF0gLz0gaztcbiAgICAgIGFbMV0gLz0gaztcbiAgICB9XG4gICAgcmV0dXJuIGs7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdHJhbnNmb3JtQ29tYmluZShhLCBiLCBrKSB7XG4gICAgYVswXSArPSBrICogYlswXTtcbiAgICBhWzFdICs9IGsgKiBiWzFdO1xuICAgIHJldHVybiBhO1xuICB9XG4gIHZhciBkM190cmFuc2Zvcm1JZGVudGl0eSA9IHtcbiAgICBhOiAxLFxuICAgIGI6IDAsXG4gICAgYzogMCxcbiAgICBkOiAxLFxuICAgIGU6IDAsXG4gICAgZjogMFxuICB9O1xuICBkMy5pbnRlcnBvbGF0ZVRyYW5zZm9ybSA9IGQzX2ludGVycG9sYXRlVHJhbnNmb3JtO1xuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVRyYW5zZm9ybVBvcChzKSB7XG4gICAgcmV0dXJuIHMubGVuZ3RoID8gcy5wb3AoKSArIFwiLFwiIDogXCJcIjtcbiAgfVxuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVRyYW5zbGF0ZSh0YSwgdGIsIHMsIHEpIHtcbiAgICBpZiAodGFbMF0gIT09IHRiWzBdIHx8IHRhWzFdICE9PSB0YlsxXSkge1xuICAgICAgdmFyIGkgPSBzLnB1c2goXCJ0cmFuc2xhdGUoXCIsIG51bGwsIFwiLFwiLCBudWxsLCBcIilcIik7XG4gICAgICBxLnB1c2goe1xuICAgICAgICBpOiBpIC0gNCxcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIodGFbMF0sIHRiWzBdKVxuICAgICAgfSwge1xuICAgICAgICBpOiBpIC0gMixcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIodGFbMV0sIHRiWzFdKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmICh0YlswXSB8fCB0YlsxXSkge1xuICAgICAgcy5wdXNoKFwidHJhbnNsYXRlKFwiICsgdGIgKyBcIilcIik7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2ludGVycG9sYXRlUm90YXRlKHJhLCByYiwgcywgcSkge1xuICAgIGlmIChyYSAhPT0gcmIpIHtcbiAgICAgIGlmIChyYSAtIHJiID4gMTgwKSByYiArPSAzNjA7IGVsc2UgaWYgKHJiIC0gcmEgPiAxODApIHJhICs9IDM2MDtcbiAgICAgIHEucHVzaCh7XG4gICAgICAgIGk6IHMucHVzaChkM19pbnRlcnBvbGF0ZVRyYW5zZm9ybVBvcChzKSArIFwicm90YXRlKFwiLCBudWxsLCBcIilcIikgLSAyLFxuICAgICAgICB4OiBkM19pbnRlcnBvbGF0ZU51bWJlcihyYSwgcmIpXG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKHJiKSB7XG4gICAgICBzLnB1c2goZDNfaW50ZXJwb2xhdGVUcmFuc2Zvcm1Qb3AocykgKyBcInJvdGF0ZShcIiArIHJiICsgXCIpXCIpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVNrZXcod2EsIHdiLCBzLCBxKSB7XG4gICAgaWYgKHdhICE9PSB3Yikge1xuICAgICAgcS5wdXNoKHtcbiAgICAgICAgaTogcy5wdXNoKGQzX2ludGVycG9sYXRlVHJhbnNmb3JtUG9wKHMpICsgXCJza2V3WChcIiwgbnVsbCwgXCIpXCIpIC0gMixcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIod2EsIHdiKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmICh3Yikge1xuICAgICAgcy5wdXNoKGQzX2ludGVycG9sYXRlVHJhbnNmb3JtUG9wKHMpICsgXCJza2V3WChcIiArIHdiICsgXCIpXCIpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVNjYWxlKGthLCBrYiwgcywgcSkge1xuICAgIGlmIChrYVswXSAhPT0ga2JbMF0gfHwga2FbMV0gIT09IGtiWzFdKSB7XG4gICAgICB2YXIgaSA9IHMucHVzaChkM19pbnRlcnBvbGF0ZVRyYW5zZm9ybVBvcChzKSArIFwic2NhbGUoXCIsIG51bGwsIFwiLFwiLCBudWxsLCBcIilcIik7XG4gICAgICBxLnB1c2goe1xuICAgICAgICBpOiBpIC0gNCxcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIoa2FbMF0sIGtiWzBdKVxuICAgICAgfSwge1xuICAgICAgICBpOiBpIC0gMixcbiAgICAgICAgeDogZDNfaW50ZXJwb2xhdGVOdW1iZXIoa2FbMV0sIGtiWzFdKVxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChrYlswXSAhPT0gMSB8fCBrYlsxXSAhPT0gMSkge1xuICAgICAgcy5wdXNoKGQzX2ludGVycG9sYXRlVHJhbnNmb3JtUG9wKHMpICsgXCJzY2FsZShcIiArIGtiICsgXCIpXCIpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBkM19pbnRlcnBvbGF0ZVRyYW5zZm9ybShhLCBiKSB7XG4gICAgdmFyIHMgPSBbXSwgcSA9IFtdO1xuICAgIGEgPSBkMy50cmFuc2Zvcm0oYSksIGIgPSBkMy50cmFuc2Zvcm0oYik7XG4gICAgZDNfaW50ZXJwb2xhdGVUcmFuc2xhdGUoYS50cmFuc2xhdGUsIGIudHJhbnNsYXRlLCBzLCBxKTtcbiAgICBkM19pbnRlcnBvbGF0ZVJvdGF0ZShhLnJvdGF0ZSwgYi5yb3RhdGUsIHMsIHEpO1xuICAgIGQzX2ludGVycG9sYXRlU2tldyhhLnNrZXcsIGIuc2tldywgcywgcSk7XG4gICAgZDNfaW50ZXJwb2xhdGVTY2FsZShhLnNjYWxlLCBiLnNjYWxlLCBzLCBxKTtcbiAgICBhID0gYiA9IG51bGw7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIHZhciBpID0gLTEsIG4gPSBxLmxlbmd0aCwgbztcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBzWyhvID0gcVtpXSkuaV0gPSBvLngodCk7XG4gICAgICByZXR1cm4gcy5qb2luKFwiXCIpO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gZDNfdW5pbnRlcnBvbGF0ZU51bWJlcihhLCBiKSB7XG4gICAgYiA9IChiIC09IGEgPSArYSkgfHwgMSAvIGI7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiAoeCAtIGEpIC8gYjtcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3VuaW50ZXJwb2xhdGVDbGFtcChhLCBiKSB7XG4gICAgYiA9IChiIC09IGEgPSArYSkgfHwgMSAvIGI7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCAoeCAtIGEpIC8gYikpO1xuICAgIH07XG4gIH1cbiAgZDMubGF5b3V0ID0ge307XG4gIGQzLmxheW91dC5idW5kbGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24obGlua3MpIHtcbiAgICAgIHZhciBwYXRocyA9IFtdLCBpID0gLTEsIG4gPSBsaW5rcy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKytpIDwgbikgcGF0aHMucHVzaChkM19sYXlvdXRfYnVuZGxlUGF0aChsaW5rc1tpXSkpO1xuICAgICAgcmV0dXJuIHBhdGhzO1xuICAgIH07XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9idW5kbGVQYXRoKGxpbmspIHtcbiAgICB2YXIgc3RhcnQgPSBsaW5rLnNvdXJjZSwgZW5kID0gbGluay50YXJnZXQsIGxjYSA9IGQzX2xheW91dF9idW5kbGVMZWFzdENvbW1vbkFuY2VzdG9yKHN0YXJ0LCBlbmQpLCBwb2ludHMgPSBbIHN0YXJ0IF07XG4gICAgd2hpbGUgKHN0YXJ0ICE9PSBsY2EpIHtcbiAgICAgIHN0YXJ0ID0gc3RhcnQucGFyZW50O1xuICAgICAgcG9pbnRzLnB1c2goc3RhcnQpO1xuICAgIH1cbiAgICB2YXIgayA9IHBvaW50cy5sZW5ndGg7XG4gICAgd2hpbGUgKGVuZCAhPT0gbGNhKSB7XG4gICAgICBwb2ludHMuc3BsaWNlKGssIDAsIGVuZCk7XG4gICAgICBlbmQgPSBlbmQucGFyZW50O1xuICAgIH1cbiAgICByZXR1cm4gcG9pbnRzO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9idW5kbGVBbmNlc3RvcnMobm9kZSkge1xuICAgIHZhciBhbmNlc3RvcnMgPSBbXSwgcGFyZW50ID0gbm9kZS5wYXJlbnQ7XG4gICAgd2hpbGUgKHBhcmVudCAhPSBudWxsKSB7XG4gICAgICBhbmNlc3RvcnMucHVzaChub2RlKTtcbiAgICAgIG5vZGUgPSBwYXJlbnQ7XG4gICAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50O1xuICAgIH1cbiAgICBhbmNlc3RvcnMucHVzaChub2RlKTtcbiAgICByZXR1cm4gYW5jZXN0b3JzO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9idW5kbGVMZWFzdENvbW1vbkFuY2VzdG9yKGEsIGIpIHtcbiAgICBpZiAoYSA9PT0gYikgcmV0dXJuIGE7XG4gICAgdmFyIGFOb2RlcyA9IGQzX2xheW91dF9idW5kbGVBbmNlc3RvcnMoYSksIGJOb2RlcyA9IGQzX2xheW91dF9idW5kbGVBbmNlc3RvcnMoYiksIGFOb2RlID0gYU5vZGVzLnBvcCgpLCBiTm9kZSA9IGJOb2Rlcy5wb3AoKSwgc2hhcmVkTm9kZSA9IG51bGw7XG4gICAgd2hpbGUgKGFOb2RlID09PSBiTm9kZSkge1xuICAgICAgc2hhcmVkTm9kZSA9IGFOb2RlO1xuICAgICAgYU5vZGUgPSBhTm9kZXMucG9wKCk7XG4gICAgICBiTm9kZSA9IGJOb2Rlcy5wb3AoKTtcbiAgICB9XG4gICAgcmV0dXJuIHNoYXJlZE5vZGU7XG4gIH1cbiAgZDMubGF5b3V0LmNob3JkID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNob3JkID0ge30sIGNob3JkcywgZ3JvdXBzLCBtYXRyaXgsIG4sIHBhZGRpbmcgPSAwLCBzb3J0R3JvdXBzLCBzb3J0U3ViZ3JvdXBzLCBzb3J0Q2hvcmRzO1xuICAgIGZ1bmN0aW9uIHJlbGF5b3V0KCkge1xuICAgICAgdmFyIHN1Ymdyb3VwcyA9IHt9LCBncm91cFN1bXMgPSBbXSwgZ3JvdXBJbmRleCA9IGQzLnJhbmdlKG4pLCBzdWJncm91cEluZGV4ID0gW10sIGssIHgsIHgwLCBpLCBqO1xuICAgICAgY2hvcmRzID0gW107XG4gICAgICBncm91cHMgPSBbXTtcbiAgICAgIGsgPSAwLCBpID0gLTE7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICB4ID0gMCwgaiA9IC0xO1xuICAgICAgICB3aGlsZSAoKytqIDwgbikge1xuICAgICAgICAgIHggKz0gbWF0cml4W2ldW2pdO1xuICAgICAgICB9XG4gICAgICAgIGdyb3VwU3Vtcy5wdXNoKHgpO1xuICAgICAgICBzdWJncm91cEluZGV4LnB1c2goZDMucmFuZ2UobikpO1xuICAgICAgICBrICs9IHg7XG4gICAgICB9XG4gICAgICBpZiAoc29ydEdyb3Vwcykge1xuICAgICAgICBncm91cEluZGV4LnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgIHJldHVybiBzb3J0R3JvdXBzKGdyb3VwU3Vtc1thXSwgZ3JvdXBTdW1zW2JdKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICBpZiAoc29ydFN1Ymdyb3Vwcykge1xuICAgICAgICBzdWJncm91cEluZGV4LmZvckVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgIGQuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gc29ydFN1Ymdyb3VwcyhtYXRyaXhbaV1bYV0sIG1hdHJpeFtpXVtiXSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgayA9ICjPhCAtIHBhZGRpbmcgKiBuKSAvIGs7XG4gICAgICB4ID0gMCwgaSA9IC0xO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgeDAgPSB4LCBqID0gLTE7XG4gICAgICAgIHdoaWxlICgrK2ogPCBuKSB7XG4gICAgICAgICAgdmFyIGRpID0gZ3JvdXBJbmRleFtpXSwgZGogPSBzdWJncm91cEluZGV4W2RpXVtqXSwgdiA9IG1hdHJpeFtkaV1bZGpdLCBhMCA9IHgsIGExID0geCArPSB2ICogaztcbiAgICAgICAgICBzdWJncm91cHNbZGkgKyBcIi1cIiArIGRqXSA9IHtcbiAgICAgICAgICAgIGluZGV4OiBkaSxcbiAgICAgICAgICAgIHN1YmluZGV4OiBkaixcbiAgICAgICAgICAgIHN0YXJ0QW5nbGU6IGEwLFxuICAgICAgICAgICAgZW5kQW5nbGU6IGExLFxuICAgICAgICAgICAgdmFsdWU6IHZcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGdyb3Vwc1tkaV0gPSB7XG4gICAgICAgICAgaW5kZXg6IGRpLFxuICAgICAgICAgIHN0YXJ0QW5nbGU6IHgwLFxuICAgICAgICAgIGVuZEFuZ2xlOiB4LFxuICAgICAgICAgIHZhbHVlOiBncm91cFN1bXNbZGldXG4gICAgICAgIH07XG4gICAgICAgIHggKz0gcGFkZGluZztcbiAgICAgIH1cbiAgICAgIGkgPSAtMTtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIGogPSBpIC0gMTtcbiAgICAgICAgd2hpbGUgKCsraiA8IG4pIHtcbiAgICAgICAgICB2YXIgc291cmNlID0gc3ViZ3JvdXBzW2kgKyBcIi1cIiArIGpdLCB0YXJnZXQgPSBzdWJncm91cHNbaiArIFwiLVwiICsgaV07XG4gICAgICAgICAgaWYgKHNvdXJjZS52YWx1ZSB8fCB0YXJnZXQudmFsdWUpIHtcbiAgICAgICAgICAgIGNob3Jkcy5wdXNoKHNvdXJjZS52YWx1ZSA8IHRhcmdldC52YWx1ZSA/IHtcbiAgICAgICAgICAgICAgc291cmNlOiB0YXJnZXQsXG4gICAgICAgICAgICAgIHRhcmdldDogc291cmNlXG4gICAgICAgICAgICB9IDoge1xuICAgICAgICAgICAgICBzb3VyY2U6IHNvdXJjZSxcbiAgICAgICAgICAgICAgdGFyZ2V0OiB0YXJnZXRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHNvcnRDaG9yZHMpIHJlc29ydCgpO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNvcnQoKSB7XG4gICAgICBjaG9yZHMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBzb3J0Q2hvcmRzKChhLnNvdXJjZS52YWx1ZSArIGEudGFyZ2V0LnZhbHVlKSAvIDIsIChiLnNvdXJjZS52YWx1ZSArIGIudGFyZ2V0LnZhbHVlKSAvIDIpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGNob3JkLm1hdHJpeCA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG1hdHJpeDtcbiAgICAgIG4gPSAobWF0cml4ID0geCkgJiYgbWF0cml4Lmxlbmd0aDtcbiAgICAgIGNob3JkcyA9IGdyb3VwcyA9IG51bGw7XG4gICAgICByZXR1cm4gY2hvcmQ7XG4gICAgfTtcbiAgICBjaG9yZC5wYWRkaW5nID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcGFkZGluZztcbiAgICAgIHBhZGRpbmcgPSB4O1xuICAgICAgY2hvcmRzID0gZ3JvdXBzID0gbnVsbDtcbiAgICAgIHJldHVybiBjaG9yZDtcbiAgICB9O1xuICAgIGNob3JkLnNvcnRHcm91cHMgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzb3J0R3JvdXBzO1xuICAgICAgc29ydEdyb3VwcyA9IHg7XG4gICAgICBjaG9yZHMgPSBncm91cHMgPSBudWxsO1xuICAgICAgcmV0dXJuIGNob3JkO1xuICAgIH07XG4gICAgY2hvcmQuc29ydFN1Ymdyb3VwcyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNvcnRTdWJncm91cHM7XG4gICAgICBzb3J0U3ViZ3JvdXBzID0geDtcbiAgICAgIGNob3JkcyA9IG51bGw7XG4gICAgICByZXR1cm4gY2hvcmQ7XG4gICAgfTtcbiAgICBjaG9yZC5zb3J0Q2hvcmRzID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc29ydENob3JkcztcbiAgICAgIHNvcnRDaG9yZHMgPSB4O1xuICAgICAgaWYgKGNob3JkcykgcmVzb3J0KCk7XG4gICAgICByZXR1cm4gY2hvcmQ7XG4gICAgfTtcbiAgICBjaG9yZC5jaG9yZHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghY2hvcmRzKSByZWxheW91dCgpO1xuICAgICAgcmV0dXJuIGNob3JkcztcbiAgICB9O1xuICAgIGNob3JkLmdyb3VwcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCFncm91cHMpIHJlbGF5b3V0KCk7XG4gICAgICByZXR1cm4gZ3JvdXBzO1xuICAgIH07XG4gICAgcmV0dXJuIGNob3JkO1xuICB9O1xuICBkMy5sYXlvdXQuZm9yY2UgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZm9yY2UgPSB7fSwgZXZlbnQgPSBkMy5kaXNwYXRjaChcInN0YXJ0XCIsIFwidGlja1wiLCBcImVuZFwiKSwgdGltZXIsIHNpemUgPSBbIDEsIDEgXSwgZHJhZywgYWxwaGEsIGZyaWN0aW9uID0gLjksIGxpbmtEaXN0YW5jZSA9IGQzX2xheW91dF9mb3JjZUxpbmtEaXN0YW5jZSwgbGlua1N0cmVuZ3RoID0gZDNfbGF5b3V0X2ZvcmNlTGlua1N0cmVuZ3RoLCBjaGFyZ2UgPSAtMzAsIGNoYXJnZURpc3RhbmNlMiA9IGQzX2xheW91dF9mb3JjZUNoYXJnZURpc3RhbmNlMiwgZ3Jhdml0eSA9IC4xLCB0aGV0YTIgPSAuNjQsIG5vZGVzID0gW10sIGxpbmtzID0gW10sIGRpc3RhbmNlcywgc3RyZW5ndGhzLCBjaGFyZ2VzO1xuICAgIGZ1bmN0aW9uIHJlcHVsc2Uobm9kZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHF1YWQsIHgxLCBfLCB4Mikge1xuICAgICAgICBpZiAocXVhZC5wb2ludCAhPT0gbm9kZSkge1xuICAgICAgICAgIHZhciBkeCA9IHF1YWQuY3ggLSBub2RlLngsIGR5ID0gcXVhZC5jeSAtIG5vZGUueSwgZHcgPSB4MiAtIHgxLCBkbiA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgICAgIGlmIChkdyAqIGR3IC8gdGhldGEyIDwgZG4pIHtcbiAgICAgICAgICAgIGlmIChkbiA8IGNoYXJnZURpc3RhbmNlMikge1xuICAgICAgICAgICAgICB2YXIgayA9IHF1YWQuY2hhcmdlIC8gZG47XG4gICAgICAgICAgICAgIG5vZGUucHggLT0gZHggKiBrO1xuICAgICAgICAgICAgICBub2RlLnB5IC09IGR5ICogaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocXVhZC5wb2ludCAmJiBkbiAmJiBkbiA8IGNoYXJnZURpc3RhbmNlMikge1xuICAgICAgICAgICAgdmFyIGsgPSBxdWFkLnBvaW50Q2hhcmdlIC8gZG47XG4gICAgICAgICAgICBub2RlLnB4IC09IGR4ICogaztcbiAgICAgICAgICAgIG5vZGUucHkgLT0gZHkgKiBrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gIXF1YWQuY2hhcmdlO1xuICAgICAgfTtcbiAgICB9XG4gICAgZm9yY2UudGljayA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKChhbHBoYSAqPSAuOTkpIDwgLjAwNSkge1xuICAgICAgICB0aW1lciA9IG51bGw7XG4gICAgICAgIGV2ZW50LmVuZCh7XG4gICAgICAgICAgdHlwZTogXCJlbmRcIixcbiAgICAgICAgICBhbHBoYTogYWxwaGEgPSAwXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHZhciBuID0gbm9kZXMubGVuZ3RoLCBtID0gbGlua3MubGVuZ3RoLCBxLCBpLCBvLCBzLCB0LCBsLCBrLCB4LCB5O1xuICAgICAgZm9yIChpID0gMDsgaSA8IG07ICsraSkge1xuICAgICAgICBvID0gbGlua3NbaV07XG4gICAgICAgIHMgPSBvLnNvdXJjZTtcbiAgICAgICAgdCA9IG8udGFyZ2V0O1xuICAgICAgICB4ID0gdC54IC0gcy54O1xuICAgICAgICB5ID0gdC55IC0gcy55O1xuICAgICAgICBpZiAobCA9IHggKiB4ICsgeSAqIHkpIHtcbiAgICAgICAgICBsID0gYWxwaGEgKiBzdHJlbmd0aHNbaV0gKiAoKGwgPSBNYXRoLnNxcnQobCkpIC0gZGlzdGFuY2VzW2ldKSAvIGw7XG4gICAgICAgICAgeCAqPSBsO1xuICAgICAgICAgIHkgKj0gbDtcbiAgICAgICAgICB0LnggLT0geCAqIChrID0gcy53ZWlnaHQgKyB0LndlaWdodCA/IHMud2VpZ2h0IC8gKHMud2VpZ2h0ICsgdC53ZWlnaHQpIDogLjUpO1xuICAgICAgICAgIHQueSAtPSB5ICogaztcbiAgICAgICAgICBzLnggKz0geCAqIChrID0gMSAtIGspO1xuICAgICAgICAgIHMueSArPSB5ICogaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGsgPSBhbHBoYSAqIGdyYXZpdHkpIHtcbiAgICAgICAgeCA9IHNpemVbMF0gLyAyO1xuICAgICAgICB5ID0gc2l6ZVsxXSAvIDI7XG4gICAgICAgIGkgPSAtMTtcbiAgICAgICAgaWYgKGspIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgbyA9IG5vZGVzW2ldO1xuICAgICAgICAgIG8ueCArPSAoeCAtIG8ueCkgKiBrO1xuICAgICAgICAgIG8ueSArPSAoeSAtIG8ueSkgKiBrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoY2hhcmdlKSB7XG4gICAgICAgIGQzX2xheW91dF9mb3JjZUFjY3VtdWxhdGUocSA9IGQzLmdlb20ucXVhZHRyZWUobm9kZXMpLCBhbHBoYSwgY2hhcmdlcyk7XG4gICAgICAgIGkgPSAtMTtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgICBpZiAoIShvID0gbm9kZXNbaV0pLmZpeGVkKSB7XG4gICAgICAgICAgICBxLnZpc2l0KHJlcHVsc2UobykpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaSA9IC0xO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgbyA9IG5vZGVzW2ldO1xuICAgICAgICBpZiAoby5maXhlZCkge1xuICAgICAgICAgIG8ueCA9IG8ucHg7XG4gICAgICAgICAgby55ID0gby5weTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvLnggLT0gKG8ucHggLSAoby5weCA9IG8ueCkpICogZnJpY3Rpb247XG4gICAgICAgICAgby55IC09IChvLnB5IC0gKG8ucHkgPSBvLnkpKSAqIGZyaWN0aW9uO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBldmVudC50aWNrKHtcbiAgICAgICAgdHlwZTogXCJ0aWNrXCIsXG4gICAgICAgIGFscGhhOiBhbHBoYVxuICAgICAgfSk7XG4gICAgfTtcbiAgICBmb3JjZS5ub2RlcyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG5vZGVzO1xuICAgICAgbm9kZXMgPSB4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UubGlua3MgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsaW5rcztcbiAgICAgIGxpbmtzID0geDtcbiAgICAgIHJldHVybiBmb3JjZTtcbiAgICB9O1xuICAgIGZvcmNlLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzaXplO1xuICAgICAgc2l6ZSA9IHg7XG4gICAgICByZXR1cm4gZm9yY2U7XG4gICAgfTtcbiAgICBmb3JjZS5saW5rRGlzdGFuY2UgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsaW5rRGlzdGFuY2U7XG4gICAgICBsaW5rRGlzdGFuY2UgPSB0eXBlb2YgeCA9PT0gXCJmdW5jdGlvblwiID8geCA6ICt4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UuZGlzdGFuY2UgPSBmb3JjZS5saW5rRGlzdGFuY2U7XG4gICAgZm9yY2UubGlua1N0cmVuZ3RoID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbGlua1N0cmVuZ3RoO1xuICAgICAgbGlua1N0cmVuZ3RoID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiAreDtcbiAgICAgIHJldHVybiBmb3JjZTtcbiAgICB9O1xuICAgIGZvcmNlLmZyaWN0aW9uID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZnJpY3Rpb247XG4gICAgICBmcmljdGlvbiA9ICt4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UuY2hhcmdlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY2hhcmdlO1xuICAgICAgY2hhcmdlID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiAreDtcbiAgICAgIHJldHVybiBmb3JjZTtcbiAgICB9O1xuICAgIGZvcmNlLmNoYXJnZURpc3RhbmNlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gTWF0aC5zcXJ0KGNoYXJnZURpc3RhbmNlMik7XG4gICAgICBjaGFyZ2VEaXN0YW5jZTIgPSB4ICogeDtcbiAgICAgIHJldHVybiBmb3JjZTtcbiAgICB9O1xuICAgIGZvcmNlLmdyYXZpdHkgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBncmF2aXR5O1xuICAgICAgZ3Jhdml0eSA9ICt4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UudGhldGEgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBNYXRoLnNxcnQodGhldGEyKTtcbiAgICAgIHRoZXRhMiA9IHggKiB4O1xuICAgICAgcmV0dXJuIGZvcmNlO1xuICAgIH07XG4gICAgZm9yY2UuYWxwaGEgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBhbHBoYTtcbiAgICAgIHggPSAreDtcbiAgICAgIGlmIChhbHBoYSkge1xuICAgICAgICBpZiAoeCA+IDApIHtcbiAgICAgICAgICBhbHBoYSA9IHg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGltZXIuYyA9IG51bGwsIHRpbWVyLnQgPSBOYU4sIHRpbWVyID0gbnVsbDtcbiAgICAgICAgICBldmVudC5lbmQoe1xuICAgICAgICAgICAgdHlwZTogXCJlbmRcIixcbiAgICAgICAgICAgIGFscGhhOiBhbHBoYSA9IDBcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh4ID4gMCkge1xuICAgICAgICBldmVudC5zdGFydCh7XG4gICAgICAgICAgdHlwZTogXCJzdGFydFwiLFxuICAgICAgICAgIGFscGhhOiBhbHBoYSA9IHhcbiAgICAgICAgfSk7XG4gICAgICAgIHRpbWVyID0gZDNfdGltZXIoZm9yY2UudGljayk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZm9yY2U7XG4gICAgfTtcbiAgICBmb3JjZS5zdGFydCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGgsIG0gPSBsaW5rcy5sZW5ndGgsIHcgPSBzaXplWzBdLCBoID0gc2l6ZVsxXSwgbmVpZ2hib3JzLCBvO1xuICAgICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICAobyA9IG5vZGVzW2ldKS5pbmRleCA9IGk7XG4gICAgICAgIG8ud2VpZ2h0ID0gMDtcbiAgICAgIH1cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBtOyArK2kpIHtcbiAgICAgICAgbyA9IGxpbmtzW2ldO1xuICAgICAgICBpZiAodHlwZW9mIG8uc291cmNlID09IFwibnVtYmVyXCIpIG8uc291cmNlID0gbm9kZXNbby5zb3VyY2VdO1xuICAgICAgICBpZiAodHlwZW9mIG8udGFyZ2V0ID09IFwibnVtYmVyXCIpIG8udGFyZ2V0ID0gbm9kZXNbby50YXJnZXRdO1xuICAgICAgICArK28uc291cmNlLndlaWdodDtcbiAgICAgICAgKytvLnRhcmdldC53ZWlnaHQ7XG4gICAgICB9XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIG8gPSBub2Rlc1tpXTtcbiAgICAgICAgaWYgKGlzTmFOKG8ueCkpIG8ueCA9IHBvc2l0aW9uKFwieFwiLCB3KTtcbiAgICAgICAgaWYgKGlzTmFOKG8ueSkpIG8ueSA9IHBvc2l0aW9uKFwieVwiLCBoKTtcbiAgICAgICAgaWYgKGlzTmFOKG8ucHgpKSBvLnB4ID0gby54O1xuICAgICAgICBpZiAoaXNOYU4oby5weSkpIG8ucHkgPSBvLnk7XG4gICAgICB9XG4gICAgICBkaXN0YW5jZXMgPSBbXTtcbiAgICAgIGlmICh0eXBlb2YgbGlua0Rpc3RhbmNlID09PSBcImZ1bmN0aW9uXCIpIGZvciAoaSA9IDA7IGkgPCBtOyArK2kpIGRpc3RhbmNlc1tpXSA9ICtsaW5rRGlzdGFuY2UuY2FsbCh0aGlzLCBsaW5rc1tpXSwgaSk7IGVsc2UgZm9yIChpID0gMDsgaSA8IG07ICsraSkgZGlzdGFuY2VzW2ldID0gbGlua0Rpc3RhbmNlO1xuICAgICAgc3RyZW5ndGhzID0gW107XG4gICAgICBpZiAodHlwZW9mIGxpbmtTdHJlbmd0aCA9PT0gXCJmdW5jdGlvblwiKSBmb3IgKGkgPSAwOyBpIDwgbTsgKytpKSBzdHJlbmd0aHNbaV0gPSArbGlua1N0cmVuZ3RoLmNhbGwodGhpcywgbGlua3NbaV0sIGkpOyBlbHNlIGZvciAoaSA9IDA7IGkgPCBtOyArK2kpIHN0cmVuZ3Roc1tpXSA9IGxpbmtTdHJlbmd0aDtcbiAgICAgIGNoYXJnZXMgPSBbXTtcbiAgICAgIGlmICh0eXBlb2YgY2hhcmdlID09PSBcImZ1bmN0aW9uXCIpIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIGNoYXJnZXNbaV0gPSArY2hhcmdlLmNhbGwodGhpcywgbm9kZXNbaV0sIGkpOyBlbHNlIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIGNoYXJnZXNbaV0gPSBjaGFyZ2U7XG4gICAgICBmdW5jdGlvbiBwb3NpdGlvbihkaW1lbnNpb24sIHNpemUpIHtcbiAgICAgICAgaWYgKCFuZWlnaGJvcnMpIHtcbiAgICAgICAgICBuZWlnaGJvcnMgPSBuZXcgQXJyYXkobik7XG4gICAgICAgICAgZm9yIChqID0gMDsgaiA8IG47ICsraikge1xuICAgICAgICAgICAgbmVpZ2hib3JzW2pdID0gW107XG4gICAgICAgICAgfVxuICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICAgICAgICAgIHZhciBvID0gbGlua3Nbal07XG4gICAgICAgICAgICBuZWlnaGJvcnNbby5zb3VyY2UuaW5kZXhdLnB1c2goby50YXJnZXQpO1xuICAgICAgICAgICAgbmVpZ2hib3JzW28udGFyZ2V0LmluZGV4XS5wdXNoKG8uc291cmNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNhbmRpZGF0ZXMgPSBuZWlnaGJvcnNbaV0sIGogPSAtMSwgbCA9IGNhbmRpZGF0ZXMubGVuZ3RoLCB4O1xuICAgICAgICB3aGlsZSAoKytqIDwgbCkgaWYgKCFpc05hTih4ID0gY2FuZGlkYXRlc1tqXVtkaW1lbnNpb25dKSkgcmV0dXJuIHg7XG4gICAgICAgIHJldHVybiBNYXRoLnJhbmRvbSgpICogc2l6ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmb3JjZS5yZXN1bWUoKTtcbiAgICB9O1xuICAgIGZvcmNlLnJlc3VtZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGZvcmNlLmFscGhhKC4xKTtcbiAgICB9O1xuICAgIGZvcmNlLnN0b3AgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBmb3JjZS5hbHBoYSgwKTtcbiAgICB9O1xuICAgIGZvcmNlLmRyYWcgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghZHJhZykgZHJhZyA9IGQzLmJlaGF2aW9yLmRyYWcoKS5vcmlnaW4oZDNfaWRlbnRpdHkpLm9uKFwiZHJhZ3N0YXJ0LmZvcmNlXCIsIGQzX2xheW91dF9mb3JjZURyYWdzdGFydCkub24oXCJkcmFnLmZvcmNlXCIsIGRyYWdtb3ZlKS5vbihcImRyYWdlbmQuZm9yY2VcIiwgZDNfbGF5b3V0X2ZvcmNlRHJhZ2VuZCk7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBkcmFnO1xuICAgICAgdGhpcy5vbihcIm1vdXNlb3Zlci5mb3JjZVwiLCBkM19sYXlvdXRfZm9yY2VNb3VzZW92ZXIpLm9uKFwibW91c2VvdXQuZm9yY2VcIiwgZDNfbGF5b3V0X2ZvcmNlTW91c2VvdXQpLmNhbGwoZHJhZyk7XG4gICAgfTtcbiAgICBmdW5jdGlvbiBkcmFnbW92ZShkKSB7XG4gICAgICBkLnB4ID0gZDMuZXZlbnQueCwgZC5weSA9IGQzLmV2ZW50Lnk7XG4gICAgICBmb3JjZS5yZXN1bWUoKTtcbiAgICB9XG4gICAgcmV0dXJuIGQzLnJlYmluZChmb3JjZSwgZXZlbnQsIFwib25cIik7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9mb3JjZURyYWdzdGFydChkKSB7XG4gICAgZC5maXhlZCB8PSAyO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9mb3JjZURyYWdlbmQoZCkge1xuICAgIGQuZml4ZWQgJj0gfjY7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2ZvcmNlTW91c2VvdmVyKGQpIHtcbiAgICBkLmZpeGVkIHw9IDQ7XG4gICAgZC5weCA9IGQueCwgZC5weSA9IGQueTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfZm9yY2VNb3VzZW91dChkKSB7XG4gICAgZC5maXhlZCAmPSB+NDtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfZm9yY2VBY2N1bXVsYXRlKHF1YWQsIGFscGhhLCBjaGFyZ2VzKSB7XG4gICAgdmFyIGN4ID0gMCwgY3kgPSAwO1xuICAgIHF1YWQuY2hhcmdlID0gMDtcbiAgICBpZiAoIXF1YWQubGVhZikge1xuICAgICAgdmFyIG5vZGVzID0gcXVhZC5ub2RlcywgbiA9IG5vZGVzLmxlbmd0aCwgaSA9IC0xLCBjO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgYyA9IG5vZGVzW2ldO1xuICAgICAgICBpZiAoYyA9PSBudWxsKSBjb250aW51ZTtcbiAgICAgICAgZDNfbGF5b3V0X2ZvcmNlQWNjdW11bGF0ZShjLCBhbHBoYSwgY2hhcmdlcyk7XG4gICAgICAgIHF1YWQuY2hhcmdlICs9IGMuY2hhcmdlO1xuICAgICAgICBjeCArPSBjLmNoYXJnZSAqIGMuY3g7XG4gICAgICAgIGN5ICs9IGMuY2hhcmdlICogYy5jeTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHF1YWQucG9pbnQpIHtcbiAgICAgIGlmICghcXVhZC5sZWFmKSB7XG4gICAgICAgIHF1YWQucG9pbnQueCArPSBNYXRoLnJhbmRvbSgpIC0gLjU7XG4gICAgICAgIHF1YWQucG9pbnQueSArPSBNYXRoLnJhbmRvbSgpIC0gLjU7XG4gICAgICB9XG4gICAgICB2YXIgayA9IGFscGhhICogY2hhcmdlc1txdWFkLnBvaW50LmluZGV4XTtcbiAgICAgIHF1YWQuY2hhcmdlICs9IHF1YWQucG9pbnRDaGFyZ2UgPSBrO1xuICAgICAgY3ggKz0gayAqIHF1YWQucG9pbnQueDtcbiAgICAgIGN5ICs9IGsgKiBxdWFkLnBvaW50Lnk7XG4gICAgfVxuICAgIHF1YWQuY3ggPSBjeCAvIHF1YWQuY2hhcmdlO1xuICAgIHF1YWQuY3kgPSBjeSAvIHF1YWQuY2hhcmdlO1xuICB9XG4gIHZhciBkM19sYXlvdXRfZm9yY2VMaW5rRGlzdGFuY2UgPSAyMCwgZDNfbGF5b3V0X2ZvcmNlTGlua1N0cmVuZ3RoID0gMSwgZDNfbGF5b3V0X2ZvcmNlQ2hhcmdlRGlzdGFuY2UyID0gSW5maW5pdHk7XG4gIGQzLmxheW91dC5oaWVyYXJjaHkgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc29ydCA9IGQzX2xheW91dF9oaWVyYXJjaHlTb3J0LCBjaGlsZHJlbiA9IGQzX2xheW91dF9oaWVyYXJjaHlDaGlsZHJlbiwgdmFsdWUgPSBkM19sYXlvdXRfaGllcmFyY2h5VmFsdWU7XG4gICAgZnVuY3Rpb24gaGllcmFyY2h5KHJvb3QpIHtcbiAgICAgIHZhciBzdGFjayA9IFsgcm9vdCBdLCBub2RlcyA9IFtdLCBub2RlO1xuICAgICAgcm9vdC5kZXB0aCA9IDA7XG4gICAgICB3aGlsZSAoKG5vZGUgPSBzdGFjay5wb3AoKSkgIT0gbnVsbCkge1xuICAgICAgICBub2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgICBpZiAoKGNoaWxkcyA9IGNoaWxkcmVuLmNhbGwoaGllcmFyY2h5LCBub2RlLCBub2RlLmRlcHRoKSkgJiYgKG4gPSBjaGlsZHMubGVuZ3RoKSkge1xuICAgICAgICAgIHZhciBuLCBjaGlsZHMsIGNoaWxkO1xuICAgICAgICAgIHdoaWxlICgtLW4gPj0gMCkge1xuICAgICAgICAgICAgc3RhY2sucHVzaChjaGlsZCA9IGNoaWxkc1tuXSk7XG4gICAgICAgICAgICBjaGlsZC5wYXJlbnQgPSBub2RlO1xuICAgICAgICAgICAgY2hpbGQuZGVwdGggPSBub2RlLmRlcHRoICsgMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHZhbHVlKSBub2RlLnZhbHVlID0gMDtcbiAgICAgICAgICBub2RlLmNoaWxkcmVuID0gY2hpbGRzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICh2YWx1ZSkgbm9kZS52YWx1ZSA9ICt2YWx1ZS5jYWxsKGhpZXJhcmNoeSwgbm9kZSwgbm9kZS5kZXB0aCkgfHwgMDtcbiAgICAgICAgICBkZWxldGUgbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QWZ0ZXIocm9vdCwgZnVuY3Rpb24obm9kZSkge1xuICAgICAgICB2YXIgY2hpbGRzLCBwYXJlbnQ7XG4gICAgICAgIGlmIChzb3J0ICYmIChjaGlsZHMgPSBub2RlLmNoaWxkcmVuKSkgY2hpbGRzLnNvcnQoc29ydCk7XG4gICAgICAgIGlmICh2YWx1ZSAmJiAocGFyZW50ID0gbm9kZS5wYXJlbnQpKSBwYXJlbnQudmFsdWUgKz0gbm9kZS52YWx1ZTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5vZGVzO1xuICAgIH1cbiAgICBoaWVyYXJjaHkuc29ydCA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNvcnQ7XG4gICAgICBzb3J0ID0geDtcbiAgICAgIHJldHVybiBoaWVyYXJjaHk7XG4gICAgfTtcbiAgICBoaWVyYXJjaHkuY2hpbGRyZW4gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjaGlsZHJlbjtcbiAgICAgIGNoaWxkcmVuID0geDtcbiAgICAgIHJldHVybiBoaWVyYXJjaHk7XG4gICAgfTtcbiAgICBoaWVyYXJjaHkudmFsdWUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB2YWx1ZTtcbiAgICAgIHZhbHVlID0geDtcbiAgICAgIHJldHVybiBoaWVyYXJjaHk7XG4gICAgfTtcbiAgICBoaWVyYXJjaHkucmV2YWx1ZSA9IGZ1bmN0aW9uKHJvb3QpIHtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRCZWZvcmUocm9vdCwgZnVuY3Rpb24obm9kZSkge1xuICAgICAgICAgIGlmIChub2RlLmNoaWxkcmVuKSBub2RlLnZhbHVlID0gMDtcbiAgICAgICAgfSk7XG4gICAgICAgIGQzX2xheW91dF9oaWVyYXJjaHlWaXNpdEFmdGVyKHJvb3QsIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgICB2YXIgcGFyZW50O1xuICAgICAgICAgIGlmICghbm9kZS5jaGlsZHJlbikgbm9kZS52YWx1ZSA9ICt2YWx1ZS5jYWxsKGhpZXJhcmNoeSwgbm9kZSwgbm9kZS5kZXB0aCkgfHwgMDtcbiAgICAgICAgICBpZiAocGFyZW50ID0gbm9kZS5wYXJlbnQpIHBhcmVudC52YWx1ZSArPSBub2RlLnZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByb290O1xuICAgIH07XG4gICAgcmV0dXJuIGhpZXJhcmNoeTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2hpZXJhcmNoeVJlYmluZChvYmplY3QsIGhpZXJhcmNoeSkge1xuICAgIGQzLnJlYmluZChvYmplY3QsIGhpZXJhcmNoeSwgXCJzb3J0XCIsIFwiY2hpbGRyZW5cIiwgXCJ2YWx1ZVwiKTtcbiAgICBvYmplY3Qubm9kZXMgPSBvYmplY3Q7XG4gICAgb2JqZWN0LmxpbmtzID0gZDNfbGF5b3V0X2hpZXJhcmNoeUxpbmtzO1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QmVmb3JlKG5vZGUsIGNhbGxiYWNrKSB7XG4gICAgdmFyIG5vZGVzID0gWyBub2RlIF07XG4gICAgd2hpbGUgKChub2RlID0gbm9kZXMucG9wKCkpICE9IG51bGwpIHtcbiAgICAgIGNhbGxiYWNrKG5vZGUpO1xuICAgICAgaWYgKChjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW4pICYmIChuID0gY2hpbGRyZW4ubGVuZ3RoKSkge1xuICAgICAgICB2YXIgbiwgY2hpbGRyZW47XG4gICAgICAgIHdoaWxlICgtLW4gPj0gMCkgbm9kZXMucHVzaChjaGlsZHJlbltuXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9oaWVyYXJjaHlWaXNpdEFmdGVyKG5vZGUsIGNhbGxiYWNrKSB7XG4gICAgdmFyIG5vZGVzID0gWyBub2RlIF0sIG5vZGVzMiA9IFtdO1xuICAgIHdoaWxlICgobm9kZSA9IG5vZGVzLnBvcCgpKSAhPSBudWxsKSB7XG4gICAgICBub2RlczIucHVzaChub2RlKTtcbiAgICAgIGlmICgoY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuKSAmJiAobiA9IGNoaWxkcmVuLmxlbmd0aCkpIHtcbiAgICAgICAgdmFyIGkgPSAtMSwgbiwgY2hpbGRyZW47XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSBub2Rlcy5wdXNoKGNoaWxkcmVuW2ldKTtcbiAgICAgIH1cbiAgICB9XG4gICAgd2hpbGUgKChub2RlID0gbm9kZXMyLnBvcCgpKSAhPSBudWxsKSB7XG4gICAgICBjYWxsYmFjayhub2RlKTtcbiAgICB9XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2hpZXJhcmNoeUNoaWxkcmVuKGQpIHtcbiAgICByZXR1cm4gZC5jaGlsZHJlbjtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfaGllcmFyY2h5VmFsdWUoZCkge1xuICAgIHJldHVybiBkLnZhbHVlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9oaWVyYXJjaHlTb3J0KGEsIGIpIHtcbiAgICByZXR1cm4gYi52YWx1ZSAtIGEudmFsdWU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2hpZXJhcmNoeUxpbmtzKG5vZGVzKSB7XG4gICAgcmV0dXJuIGQzLm1lcmdlKG5vZGVzLm1hcChmdW5jdGlvbihwYXJlbnQpIHtcbiAgICAgIHJldHVybiAocGFyZW50LmNoaWxkcmVuIHx8IFtdKS5tYXAoZnVuY3Rpb24oY2hpbGQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzb3VyY2U6IHBhcmVudCxcbiAgICAgICAgICB0YXJnZXQ6IGNoaWxkXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9KSk7XG4gIH1cbiAgZDMubGF5b3V0LnBhcnRpdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoaWVyYXJjaHkgPSBkMy5sYXlvdXQuaGllcmFyY2h5KCksIHNpemUgPSBbIDEsIDEgXTtcbiAgICBmdW5jdGlvbiBwb3NpdGlvbihub2RlLCB4LCBkeCwgZHkpIHtcbiAgICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW47XG4gICAgICBub2RlLnggPSB4O1xuICAgICAgbm9kZS55ID0gbm9kZS5kZXB0aCAqIGR5O1xuICAgICAgbm9kZS5keCA9IGR4O1xuICAgICAgbm9kZS5keSA9IGR5O1xuICAgICAgaWYgKGNoaWxkcmVuICYmIChuID0gY2hpbGRyZW4ubGVuZ3RoKSkge1xuICAgICAgICB2YXIgaSA9IC0xLCBuLCBjLCBkO1xuICAgICAgICBkeCA9IG5vZGUudmFsdWUgPyBkeCAvIG5vZGUudmFsdWUgOiAwO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICAgIHBvc2l0aW9uKGMgPSBjaGlsZHJlbltpXSwgeCwgZCA9IGMudmFsdWUgKiBkeCwgZHkpO1xuICAgICAgICAgIHggKz0gZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBkZXB0aChub2RlKSB7XG4gICAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuLCBkID0gMDtcbiAgICAgIGlmIChjaGlsZHJlbiAmJiAobiA9IGNoaWxkcmVuLmxlbmd0aCkpIHtcbiAgICAgICAgdmFyIGkgPSAtMSwgbjtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIGQgPSBNYXRoLm1heChkLCBkZXB0aChjaGlsZHJlbltpXSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIDEgKyBkO1xuICAgIH1cbiAgICBmdW5jdGlvbiBwYXJ0aXRpb24oZCwgaSkge1xuICAgICAgdmFyIG5vZGVzID0gaGllcmFyY2h5LmNhbGwodGhpcywgZCwgaSk7XG4gICAgICBwb3NpdGlvbihub2Rlc1swXSwgMCwgc2l6ZVswXSwgc2l6ZVsxXSAvIGRlcHRoKG5vZGVzWzBdKSk7XG4gICAgICByZXR1cm4gbm9kZXM7XG4gICAgfVxuICAgIHBhcnRpdGlvbi5zaXplID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc2l6ZTtcbiAgICAgIHNpemUgPSB4O1xuICAgICAgcmV0dXJuIHBhcnRpdGlvbjtcbiAgICB9O1xuICAgIHJldHVybiBkM19sYXlvdXRfaGllcmFyY2h5UmViaW5kKHBhcnRpdGlvbiwgaGllcmFyY2h5KTtcbiAgfTtcbiAgZDMubGF5b3V0LnBpZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB2YWx1ZSA9IE51bWJlciwgc29ydCA9IGQzX2xheW91dF9waWVTb3J0QnlWYWx1ZSwgc3RhcnRBbmdsZSA9IDAsIGVuZEFuZ2xlID0gz4QsIHBhZEFuZ2xlID0gMDtcbiAgICBmdW5jdGlvbiBwaWUoZGF0YSkge1xuICAgICAgdmFyIG4gPSBkYXRhLmxlbmd0aCwgdmFsdWVzID0gZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICByZXR1cm4gK3ZhbHVlLmNhbGwocGllLCBkLCBpKTtcbiAgICAgIH0pLCBhID0gKyh0eXBlb2Ygc3RhcnRBbmdsZSA9PT0gXCJmdW5jdGlvblwiID8gc3RhcnRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogc3RhcnRBbmdsZSksIGRhID0gKHR5cGVvZiBlbmRBbmdsZSA9PT0gXCJmdW5jdGlvblwiID8gZW5kQW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IGVuZEFuZ2xlKSAtIGEsIHAgPSBNYXRoLm1pbihNYXRoLmFicyhkYSkgLyBuLCArKHR5cGVvZiBwYWRBbmdsZSA9PT0gXCJmdW5jdGlvblwiID8gcGFkQW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IHBhZEFuZ2xlKSksIHBhID0gcCAqIChkYSA8IDAgPyAtMSA6IDEpLCBzdW0gPSBkMy5zdW0odmFsdWVzKSwgayA9IHN1bSA/IChkYSAtIG4gKiBwYSkgLyBzdW0gOiAwLCBpbmRleCA9IGQzLnJhbmdlKG4pLCBhcmNzID0gW10sIHY7XG4gICAgICBpZiAoc29ydCAhPSBudWxsKSBpbmRleC5zb3J0KHNvcnQgPT09IGQzX2xheW91dF9waWVTb3J0QnlWYWx1ZSA/IGZ1bmN0aW9uKGksIGopIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlc1tqXSAtIHZhbHVlc1tpXTtcbiAgICAgIH0gOiBmdW5jdGlvbihpLCBqKSB7XG4gICAgICAgIHJldHVybiBzb3J0KGRhdGFbaV0sIGRhdGFbal0pO1xuICAgICAgfSk7XG4gICAgICBpbmRleC5mb3JFYWNoKGZ1bmN0aW9uKGkpIHtcbiAgICAgICAgYXJjc1tpXSA9IHtcbiAgICAgICAgICBkYXRhOiBkYXRhW2ldLFxuICAgICAgICAgIHZhbHVlOiB2ID0gdmFsdWVzW2ldLFxuICAgICAgICAgIHN0YXJ0QW5nbGU6IGEsXG4gICAgICAgICAgZW5kQW5nbGU6IGEgKz0gdiAqIGsgKyBwYSxcbiAgICAgICAgICBwYWRBbmdsZTogcFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYXJjcztcbiAgICB9XG4gICAgcGllLnZhbHVlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdmFsdWU7XG4gICAgICB2YWx1ZSA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcGllLnNvcnQgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzb3J0O1xuICAgICAgc29ydCA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcGllLnN0YXJ0QW5nbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzdGFydEFuZ2xlO1xuICAgICAgc3RhcnRBbmdsZSA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcGllLmVuZEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZW5kQW5nbGU7XG4gICAgICBlbmRBbmdsZSA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcGllLnBhZEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcGFkQW5nbGU7XG4gICAgICBwYWRBbmdsZSA9IF87XG4gICAgICByZXR1cm4gcGllO1xuICAgIH07XG4gICAgcmV0dXJuIHBpZTtcbiAgfTtcbiAgdmFyIGQzX2xheW91dF9waWVTb3J0QnlWYWx1ZSA9IHt9O1xuICBkMy5sYXlvdXQuc3RhY2sgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsdWVzID0gZDNfaWRlbnRpdHksIG9yZGVyID0gZDNfbGF5b3V0X3N0YWNrT3JkZXJEZWZhdWx0LCBvZmZzZXQgPSBkM19sYXlvdXRfc3RhY2tPZmZzZXRaZXJvLCBvdXQgPSBkM19sYXlvdXRfc3RhY2tPdXQsIHggPSBkM19sYXlvdXRfc3RhY2tYLCB5ID0gZDNfbGF5b3V0X3N0YWNrWTtcbiAgICBmdW5jdGlvbiBzdGFjayhkYXRhLCBpbmRleCkge1xuICAgICAgaWYgKCEobiA9IGRhdGEubGVuZ3RoKSkgcmV0dXJuIGRhdGE7XG4gICAgICB2YXIgc2VyaWVzID0gZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICByZXR1cm4gdmFsdWVzLmNhbGwoc3RhY2ssIGQsIGkpO1xuICAgICAgfSk7XG4gICAgICB2YXIgcG9pbnRzID0gc2VyaWVzLm1hcChmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBkLm1hcChmdW5jdGlvbih2LCBpKSB7XG4gICAgICAgICAgcmV0dXJuIFsgeC5jYWxsKHN0YWNrLCB2LCBpKSwgeS5jYWxsKHN0YWNrLCB2LCBpKSBdO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgdmFyIG9yZGVycyA9IG9yZGVyLmNhbGwoc3RhY2ssIHBvaW50cywgaW5kZXgpO1xuICAgICAgc2VyaWVzID0gZDMucGVybXV0ZShzZXJpZXMsIG9yZGVycyk7XG4gICAgICBwb2ludHMgPSBkMy5wZXJtdXRlKHBvaW50cywgb3JkZXJzKTtcbiAgICAgIHZhciBvZmZzZXRzID0gb2Zmc2V0LmNhbGwoc3RhY2ssIHBvaW50cywgaW5kZXgpO1xuICAgICAgdmFyIG0gPSBzZXJpZXNbMF0ubGVuZ3RoLCBuLCBpLCBqLCBvO1xuICAgICAgZm9yIChqID0gMDsgaiA8IG07ICsraikge1xuICAgICAgICBvdXQuY2FsbChzdGFjaywgc2VyaWVzWzBdW2pdLCBvID0gb2Zmc2V0c1tqXSwgcG9pbnRzWzBdW2pdWzFdKTtcbiAgICAgICAgZm9yIChpID0gMTsgaSA8IG47ICsraSkge1xuICAgICAgICAgIG91dC5jYWxsKHN0YWNrLCBzZXJpZXNbaV1bal0sIG8gKz0gcG9pbnRzW2kgLSAxXVtqXVsxXSwgcG9pbnRzW2ldW2pdWzFdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIHN0YWNrLnZhbHVlcyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHZhbHVlcztcbiAgICAgIHZhbHVlcyA9IHg7XG4gICAgICByZXR1cm4gc3RhY2s7XG4gICAgfTtcbiAgICBzdGFjay5vcmRlciA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG9yZGVyO1xuICAgICAgb3JkZXIgPSB0eXBlb2YgeCA9PT0gXCJmdW5jdGlvblwiID8geCA6IGQzX2xheW91dF9zdGFja09yZGVycy5nZXQoeCkgfHwgZDNfbGF5b3V0X3N0YWNrT3JkZXJEZWZhdWx0O1xuICAgICAgcmV0dXJuIHN0YWNrO1xuICAgIH07XG4gICAgc3RhY2sub2Zmc2V0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gb2Zmc2V0O1xuICAgICAgb2Zmc2V0ID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiBkM19sYXlvdXRfc3RhY2tPZmZzZXRzLmdldCh4KSB8fCBkM19sYXlvdXRfc3RhY2tPZmZzZXRaZXJvO1xuICAgICAgcmV0dXJuIHN0YWNrO1xuICAgIH07XG4gICAgc3RhY2sueCA9IGZ1bmN0aW9uKHopIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHg7XG4gICAgICB4ID0gejtcbiAgICAgIHJldHVybiBzdGFjaztcbiAgICB9O1xuICAgIHN0YWNrLnkgPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB5O1xuICAgICAgeSA9IHo7XG4gICAgICByZXR1cm4gc3RhY2s7XG4gICAgfTtcbiAgICBzdGFjay5vdXQgPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBvdXQ7XG4gICAgICBvdXQgPSB6O1xuICAgICAgcmV0dXJuIHN0YWNrO1xuICAgIH07XG4gICAgcmV0dXJuIHN0YWNrO1xuICB9O1xuICBmdW5jdGlvbiBkM19sYXlvdXRfc3RhY2tYKGQpIHtcbiAgICByZXR1cm4gZC54O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9zdGFja1koZCkge1xuICAgIHJldHVybiBkLnk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3N0YWNrT3V0KGQsIHkwLCB5KSB7XG4gICAgZC55MCA9IHkwO1xuICAgIGQueSA9IHk7XG4gIH1cbiAgdmFyIGQzX2xheW91dF9zdGFja09yZGVycyA9IGQzLm1hcCh7XG4gICAgXCJpbnNpZGUtb3V0XCI6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgIHZhciBuID0gZGF0YS5sZW5ndGgsIGksIGosIG1heCA9IGRhdGEubWFwKGQzX2xheW91dF9zdGFja01heEluZGV4KSwgc3VtcyA9IGRhdGEubWFwKGQzX2xheW91dF9zdGFja1JlZHVjZVN1bSksIGluZGV4ID0gZDMucmFuZ2Uobikuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBtYXhbYV0gLSBtYXhbYl07XG4gICAgICB9KSwgdG9wID0gMCwgYm90dG9tID0gMCwgdG9wcyA9IFtdLCBib3R0b21zID0gW107XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIGogPSBpbmRleFtpXTtcbiAgICAgICAgaWYgKHRvcCA8IGJvdHRvbSkge1xuICAgICAgICAgIHRvcCArPSBzdW1zW2pdO1xuICAgICAgICAgIHRvcHMucHVzaChqKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBib3R0b20gKz0gc3Vtc1tqXTtcbiAgICAgICAgICBib3R0b21zLnB1c2goaik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBib3R0b21zLnJldmVyc2UoKS5jb25jYXQodG9wcyk7XG4gICAgfSxcbiAgICByZXZlcnNlOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICByZXR1cm4gZDMucmFuZ2UoZGF0YS5sZW5ndGgpLnJldmVyc2UoKTtcbiAgICB9LFxuICAgIFwiZGVmYXVsdFwiOiBkM19sYXlvdXRfc3RhY2tPcmRlckRlZmF1bHRcbiAgfSk7XG4gIHZhciBkM19sYXlvdXRfc3RhY2tPZmZzZXRzID0gZDMubWFwKHtcbiAgICBzaWxob3VldHRlOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICB2YXIgbiA9IGRhdGEubGVuZ3RoLCBtID0gZGF0YVswXS5sZW5ndGgsIHN1bXMgPSBbXSwgbWF4ID0gMCwgaSwgaiwgbywgeTAgPSBbXTtcbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICAgICAgZm9yIChpID0gMCwgbyA9IDA7IGkgPCBuOyBpKyspIG8gKz0gZGF0YVtpXVtqXVsxXTtcbiAgICAgICAgaWYgKG8gPiBtYXgpIG1heCA9IG87XG4gICAgICAgIHN1bXMucHVzaChvKTtcbiAgICAgIH1cbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICAgICAgeTBbal0gPSAobWF4IC0gc3Vtc1tqXSkgLyAyO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHkwO1xuICAgIH0sXG4gICAgd2lnZ2xlOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICB2YXIgbiA9IGRhdGEubGVuZ3RoLCB4ID0gZGF0YVswXSwgbSA9IHgubGVuZ3RoLCBpLCBqLCBrLCBzMSwgczIsIHMzLCBkeCwgbywgbzAsIHkwID0gW107XG4gICAgICB5MFswXSA9IG8gPSBvMCA9IDA7XG4gICAgICBmb3IgKGogPSAxOyBqIDwgbTsgKytqKSB7XG4gICAgICAgIGZvciAoaSA9IDAsIHMxID0gMDsgaSA8IG47ICsraSkgczEgKz0gZGF0YVtpXVtqXVsxXTtcbiAgICAgICAgZm9yIChpID0gMCwgczIgPSAwLCBkeCA9IHhbal1bMF0gLSB4W2ogLSAxXVswXTsgaSA8IG47ICsraSkge1xuICAgICAgICAgIGZvciAoayA9IDAsIHMzID0gKGRhdGFbaV1bal1bMV0gLSBkYXRhW2ldW2ogLSAxXVsxXSkgLyAoMiAqIGR4KTsgayA8IGk7ICsraykge1xuICAgICAgICAgICAgczMgKz0gKGRhdGFba11bal1bMV0gLSBkYXRhW2tdW2ogLSAxXVsxXSkgLyBkeDtcbiAgICAgICAgICB9XG4gICAgICAgICAgczIgKz0gczMgKiBkYXRhW2ldW2pdWzFdO1xuICAgICAgICB9XG4gICAgICAgIHkwW2pdID0gbyAtPSBzMSA/IHMyIC8gczEgKiBkeCA6IDA7XG4gICAgICAgIGlmIChvIDwgbzApIG8wID0gbztcbiAgICAgIH1cbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHkwW2pdIC09IG8wO1xuICAgICAgcmV0dXJuIHkwO1xuICAgIH0sXG4gICAgZXhwYW5kOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgICB2YXIgbiA9IGRhdGEubGVuZ3RoLCBtID0gZGF0YVswXS5sZW5ndGgsIGsgPSAxIC8gbiwgaSwgaiwgbywgeTAgPSBbXTtcbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICAgICAgZm9yIChpID0gMCwgbyA9IDA7IGkgPCBuOyBpKyspIG8gKz0gZGF0YVtpXVtqXVsxXTtcbiAgICAgICAgaWYgKG8pIGZvciAoaSA9IDA7IGkgPCBuOyBpKyspIGRhdGFbaV1bal1bMV0gLz0gbzsgZWxzZSBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKSBkYXRhW2ldW2pdWzFdID0gaztcbiAgICAgIH1cbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIHkwW2pdID0gMDtcbiAgICAgIHJldHVybiB5MDtcbiAgICB9LFxuICAgIHplcm86IGQzX2xheW91dF9zdGFja09mZnNldFplcm9cbiAgfSk7XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9zdGFja09yZGVyRGVmYXVsdChkYXRhKSB7XG4gICAgcmV0dXJuIGQzLnJhbmdlKGRhdGEubGVuZ3RoKTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfc3RhY2tPZmZzZXRaZXJvKGRhdGEpIHtcbiAgICB2YXIgaiA9IC0xLCBtID0gZGF0YVswXS5sZW5ndGgsIHkwID0gW107XG4gICAgd2hpbGUgKCsraiA8IG0pIHkwW2pdID0gMDtcbiAgICByZXR1cm4geTA7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3N0YWNrTWF4SW5kZXgoYXJyYXkpIHtcbiAgICB2YXIgaSA9IDEsIGogPSAwLCB2ID0gYXJyYXlbMF1bMV0sIGssIG4gPSBhcnJheS5sZW5ndGg7XG4gICAgZm9yICg7aSA8IG47ICsraSkge1xuICAgICAgaWYgKChrID0gYXJyYXlbaV1bMV0pID4gdikge1xuICAgICAgICBqID0gaTtcbiAgICAgICAgdiA9IGs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBqO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9zdGFja1JlZHVjZVN1bShkKSB7XG4gICAgcmV0dXJuIGQucmVkdWNlKGQzX2xheW91dF9zdGFja1N1bSwgMCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3N0YWNrU3VtKHAsIGQpIHtcbiAgICByZXR1cm4gcCArIGRbMV07XG4gIH1cbiAgZDMubGF5b3V0Lmhpc3RvZ3JhbSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBmcmVxdWVuY3kgPSB0cnVlLCB2YWx1ZXIgPSBOdW1iZXIsIHJhbmdlciA9IGQzX2xheW91dF9oaXN0b2dyYW1SYW5nZSwgYmlubmVyID0gZDNfbGF5b3V0X2hpc3RvZ3JhbUJpblN0dXJnZXM7XG4gICAgZnVuY3Rpb24gaGlzdG9ncmFtKGRhdGEsIGkpIHtcbiAgICAgIHZhciBiaW5zID0gW10sIHZhbHVlcyA9IGRhdGEubWFwKHZhbHVlciwgdGhpcyksIHJhbmdlID0gcmFuZ2VyLmNhbGwodGhpcywgdmFsdWVzLCBpKSwgdGhyZXNob2xkcyA9IGJpbm5lci5jYWxsKHRoaXMsIHJhbmdlLCB2YWx1ZXMsIGkpLCBiaW4sIGkgPSAtMSwgbiA9IHZhbHVlcy5sZW5ndGgsIG0gPSB0aHJlc2hvbGRzLmxlbmd0aCAtIDEsIGsgPSBmcmVxdWVuY3kgPyAxIDogMSAvIG4sIHg7XG4gICAgICB3aGlsZSAoKytpIDwgbSkge1xuICAgICAgICBiaW4gPSBiaW5zW2ldID0gW107XG4gICAgICAgIGJpbi5keCA9IHRocmVzaG9sZHNbaSArIDFdIC0gKGJpbi54ID0gdGhyZXNob2xkc1tpXSk7XG4gICAgICAgIGJpbi55ID0gMDtcbiAgICAgIH1cbiAgICAgIGlmIChtID4gMCkge1xuICAgICAgICBpID0gLTE7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgeCA9IHZhbHVlc1tpXTtcbiAgICAgICAgICBpZiAoeCA+PSByYW5nZVswXSAmJiB4IDw9IHJhbmdlWzFdKSB7XG4gICAgICAgICAgICBiaW4gPSBiaW5zW2QzLmJpc2VjdCh0aHJlc2hvbGRzLCB4LCAxLCBtKSAtIDFdO1xuICAgICAgICAgICAgYmluLnkgKz0gaztcbiAgICAgICAgICAgIGJpbi5wdXNoKGRhdGFbaV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGJpbnM7XG4gICAgfVxuICAgIGhpc3RvZ3JhbS52YWx1ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHZhbHVlcjtcbiAgICAgIHZhbHVlciA9IHg7XG4gICAgICByZXR1cm4gaGlzdG9ncmFtO1xuICAgIH07XG4gICAgaGlzdG9ncmFtLnJhbmdlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmFuZ2VyO1xuICAgICAgcmFuZ2VyID0gZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBoaXN0b2dyYW07XG4gICAgfTtcbiAgICBoaXN0b2dyYW0uYmlucyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGJpbm5lcjtcbiAgICAgIGJpbm5lciA9IHR5cGVvZiB4ID09PSBcIm51bWJlclwiID8gZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIGQzX2xheW91dF9oaXN0b2dyYW1CaW5GaXhlZChyYW5nZSwgeCk7XG4gICAgICB9IDogZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBoaXN0b2dyYW07XG4gICAgfTtcbiAgICBoaXN0b2dyYW0uZnJlcXVlbmN5ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZnJlcXVlbmN5O1xuICAgICAgZnJlcXVlbmN5ID0gISF4O1xuICAgICAgcmV0dXJuIGhpc3RvZ3JhbTtcbiAgICB9O1xuICAgIHJldHVybiBoaXN0b2dyYW07XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9oaXN0b2dyYW1CaW5TdHVyZ2VzKHJhbmdlLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gZDNfbGF5b3V0X2hpc3RvZ3JhbUJpbkZpeGVkKHJhbmdlLCBNYXRoLmNlaWwoTWF0aC5sb2codmFsdWVzLmxlbmd0aCkgLyBNYXRoLkxOMiArIDEpKTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfaGlzdG9ncmFtQmluRml4ZWQocmFuZ2UsIG4pIHtcbiAgICB2YXIgeCA9IC0xLCBiID0gK3JhbmdlWzBdLCBtID0gKHJhbmdlWzFdIC0gYikgLyBuLCBmID0gW107XG4gICAgd2hpbGUgKCsreCA8PSBuKSBmW3hdID0gbSAqIHggKyBiO1xuICAgIHJldHVybiBmO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9oaXN0b2dyYW1SYW5nZSh2YWx1ZXMpIHtcbiAgICByZXR1cm4gWyBkMy5taW4odmFsdWVzKSwgZDMubWF4KHZhbHVlcykgXTtcbiAgfVxuICBkMy5sYXlvdXQucGFjayA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoaWVyYXJjaHkgPSBkMy5sYXlvdXQuaGllcmFyY2h5KCkuc29ydChkM19sYXlvdXRfcGFja1NvcnQpLCBwYWRkaW5nID0gMCwgc2l6ZSA9IFsgMSwgMSBdLCByYWRpdXM7XG4gICAgZnVuY3Rpb24gcGFjayhkLCBpKSB7XG4gICAgICB2YXIgbm9kZXMgPSBoaWVyYXJjaHkuY2FsbCh0aGlzLCBkLCBpKSwgcm9vdCA9IG5vZGVzWzBdLCB3ID0gc2l6ZVswXSwgaCA9IHNpemVbMV0sIHIgPSByYWRpdXMgPT0gbnVsbCA/IE1hdGguc3FydCA6IHR5cGVvZiByYWRpdXMgPT09IFwiZnVuY3Rpb25cIiA/IHJhZGl1cyA6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gcmFkaXVzO1xuICAgICAgfTtcbiAgICAgIHJvb3QueCA9IHJvb3QueSA9IDA7XG4gICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRBZnRlcihyb290LCBmdW5jdGlvbihkKSB7XG4gICAgICAgIGQuciA9ICtyKGQudmFsdWUpO1xuICAgICAgfSk7XG4gICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRBZnRlcihyb290LCBkM19sYXlvdXRfcGFja1NpYmxpbmdzKTtcbiAgICAgIGlmIChwYWRkaW5nKSB7XG4gICAgICAgIHZhciBkciA9IHBhZGRpbmcgKiAocmFkaXVzID8gMSA6IE1hdGgubWF4KDIgKiByb290LnIgLyB3LCAyICogcm9vdC5yIC8gaCkpIC8gMjtcbiAgICAgICAgZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QWZ0ZXIocm9vdCwgZnVuY3Rpb24oZCkge1xuICAgICAgICAgIGQuciArPSBkcjtcbiAgICAgICAgfSk7XG4gICAgICAgIGQzX2xheW91dF9oaWVyYXJjaHlWaXNpdEFmdGVyKHJvb3QsIGQzX2xheW91dF9wYWNrU2libGluZ3MpO1xuICAgICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRBZnRlcihyb290LCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgZC5yIC09IGRyO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGQzX2xheW91dF9wYWNrVHJhbnNmb3JtKHJvb3QsIHcgLyAyLCBoIC8gMiwgcmFkaXVzID8gMSA6IDEgLyBNYXRoLm1heCgyICogcm9vdC5yIC8gdywgMiAqIHJvb3QuciAvIGgpKTtcbiAgICAgIHJldHVybiBub2RlcztcbiAgICB9XG4gICAgcGFjay5zaXplID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc2l6ZTtcbiAgICAgIHNpemUgPSBfO1xuICAgICAgcmV0dXJuIHBhY2s7XG4gICAgfTtcbiAgICBwYWNrLnJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHJhZGl1cztcbiAgICAgIHJhZGl1cyA9IF8gPT0gbnVsbCB8fCB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6ICtfO1xuICAgICAgcmV0dXJuIHBhY2s7XG4gICAgfTtcbiAgICBwYWNrLnBhZGRpbmcgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBwYWRkaW5nO1xuICAgICAgcGFkZGluZyA9ICtfO1xuICAgICAgcmV0dXJuIHBhY2s7XG4gICAgfTtcbiAgICByZXR1cm4gZDNfbGF5b3V0X2hpZXJhcmNoeVJlYmluZChwYWNrLCBoaWVyYXJjaHkpO1xuICB9O1xuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja1NvcnQoYSwgYikge1xuICAgIHJldHVybiBhLnZhbHVlIC0gYi52YWx1ZTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja0luc2VydChhLCBiKSB7XG4gICAgdmFyIGMgPSBhLl9wYWNrX25leHQ7XG4gICAgYS5fcGFja19uZXh0ID0gYjtcbiAgICBiLl9wYWNrX3ByZXYgPSBhO1xuICAgIGIuX3BhY2tfbmV4dCA9IGM7XG4gICAgYy5fcGFja19wcmV2ID0gYjtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja1NwbGljZShhLCBiKSB7XG4gICAgYS5fcGFja19uZXh0ID0gYjtcbiAgICBiLl9wYWNrX3ByZXYgPSBhO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9wYWNrSW50ZXJzZWN0cyhhLCBiKSB7XG4gICAgdmFyIGR4ID0gYi54IC0gYS54LCBkeSA9IGIueSAtIGEueSwgZHIgPSBhLnIgKyBiLnI7XG4gICAgcmV0dXJuIC45OTkgKiBkciAqIGRyID4gZHggKiBkeCArIGR5ICogZHk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3BhY2tTaWJsaW5ncyhub2RlKSB7XG4gICAgaWYgKCEobm9kZXMgPSBub2RlLmNoaWxkcmVuKSB8fCAhKG4gPSBub2Rlcy5sZW5ndGgpKSByZXR1cm47XG4gICAgdmFyIG5vZGVzLCB4TWluID0gSW5maW5pdHksIHhNYXggPSAtSW5maW5pdHksIHlNaW4gPSBJbmZpbml0eSwgeU1heCA9IC1JbmZpbml0eSwgYSwgYiwgYywgaSwgaiwgaywgbjtcbiAgICBmdW5jdGlvbiBib3VuZChub2RlKSB7XG4gICAgICB4TWluID0gTWF0aC5taW4obm9kZS54IC0gbm9kZS5yLCB4TWluKTtcbiAgICAgIHhNYXggPSBNYXRoLm1heChub2RlLnggKyBub2RlLnIsIHhNYXgpO1xuICAgICAgeU1pbiA9IE1hdGgubWluKG5vZGUueSAtIG5vZGUuciwgeU1pbik7XG4gICAgICB5TWF4ID0gTWF0aC5tYXgobm9kZS55ICsgbm9kZS5yLCB5TWF4KTtcbiAgICB9XG4gICAgbm9kZXMuZm9yRWFjaChkM19sYXlvdXRfcGFja0xpbmspO1xuICAgIGEgPSBub2Rlc1swXTtcbiAgICBhLnggPSAtYS5yO1xuICAgIGEueSA9IDA7XG4gICAgYm91bmQoYSk7XG4gICAgaWYgKG4gPiAxKSB7XG4gICAgICBiID0gbm9kZXNbMV07XG4gICAgICBiLnggPSBiLnI7XG4gICAgICBiLnkgPSAwO1xuICAgICAgYm91bmQoYik7XG4gICAgICBpZiAobiA+IDIpIHtcbiAgICAgICAgYyA9IG5vZGVzWzJdO1xuICAgICAgICBkM19sYXlvdXRfcGFja1BsYWNlKGEsIGIsIGMpO1xuICAgICAgICBib3VuZChjKTtcbiAgICAgICAgZDNfbGF5b3V0X3BhY2tJbnNlcnQoYSwgYyk7XG4gICAgICAgIGEuX3BhY2tfcHJldiA9IGM7XG4gICAgICAgIGQzX2xheW91dF9wYWNrSW5zZXJ0KGMsIGIpO1xuICAgICAgICBiID0gYS5fcGFja19uZXh0O1xuICAgICAgICBmb3IgKGkgPSAzOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgZDNfbGF5b3V0X3BhY2tQbGFjZShhLCBiLCBjID0gbm9kZXNbaV0pO1xuICAgICAgICAgIHZhciBpc2VjdCA9IDAsIHMxID0gMSwgczIgPSAxO1xuICAgICAgICAgIGZvciAoaiA9IGIuX3BhY2tfbmV4dDsgaiAhPT0gYjsgaiA9IGouX3BhY2tfbmV4dCwgczErKykge1xuICAgICAgICAgICAgaWYgKGQzX2xheW91dF9wYWNrSW50ZXJzZWN0cyhqLCBjKSkge1xuICAgICAgICAgICAgICBpc2VjdCA9IDE7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoaXNlY3QgPT0gMSkge1xuICAgICAgICAgICAgZm9yIChrID0gYS5fcGFja19wcmV2OyBrICE9PSBqLl9wYWNrX3ByZXY7IGsgPSBrLl9wYWNrX3ByZXYsIHMyKyspIHtcbiAgICAgICAgICAgICAgaWYgKGQzX2xheW91dF9wYWNrSW50ZXJzZWN0cyhrLCBjKSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChpc2VjdCkge1xuICAgICAgICAgICAgaWYgKHMxIDwgczIgfHwgczEgPT0gczIgJiYgYi5yIDwgYS5yKSBkM19sYXlvdXRfcGFja1NwbGljZShhLCBiID0gaik7IGVsc2UgZDNfbGF5b3V0X3BhY2tTcGxpY2UoYSA9IGssIGIpO1xuICAgICAgICAgICAgaS0tO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkM19sYXlvdXRfcGFja0luc2VydChhLCBjKTtcbiAgICAgICAgICAgIGIgPSBjO1xuICAgICAgICAgICAgYm91bmQoYyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHZhciBjeCA9ICh4TWluICsgeE1heCkgLyAyLCBjeSA9ICh5TWluICsgeU1heCkgLyAyLCBjciA9IDA7XG4gICAgZm9yIChpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgYyA9IG5vZGVzW2ldO1xuICAgICAgYy54IC09IGN4O1xuICAgICAgYy55IC09IGN5O1xuICAgICAgY3IgPSBNYXRoLm1heChjciwgYy5yICsgTWF0aC5zcXJ0KGMueCAqIGMueCArIGMueSAqIGMueSkpO1xuICAgIH1cbiAgICBub2RlLnIgPSBjcjtcbiAgICBub2Rlcy5mb3JFYWNoKGQzX2xheW91dF9wYWNrVW5saW5rKTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja0xpbmsobm9kZSkge1xuICAgIG5vZGUuX3BhY2tfbmV4dCA9IG5vZGUuX3BhY2tfcHJldiA9IG5vZGU7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3BhY2tVbmxpbmsobm9kZSkge1xuICAgIGRlbGV0ZSBub2RlLl9wYWNrX25leHQ7XG4gICAgZGVsZXRlIG5vZGUuX3BhY2tfcHJldjtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfcGFja1RyYW5zZm9ybShub2RlLCB4LCB5LCBrKSB7XG4gICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcbiAgICBub2RlLnggPSB4ICs9IGsgKiBub2RlLng7XG4gICAgbm9kZS55ID0geSArPSBrICogbm9kZS55O1xuICAgIG5vZGUuciAqPSBrO1xuICAgIGlmIChjaGlsZHJlbikge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSBkM19sYXlvdXRfcGFja1RyYW5zZm9ybShjaGlsZHJlbltpXSwgeCwgeSwgayk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF9wYWNrUGxhY2UoYSwgYiwgYykge1xuICAgIHZhciBkYiA9IGEuciArIGMuciwgZHggPSBiLnggLSBhLngsIGR5ID0gYi55IC0gYS55O1xuICAgIGlmIChkYiAmJiAoZHggfHwgZHkpKSB7XG4gICAgICB2YXIgZGEgPSBiLnIgKyBjLnIsIGRjID0gZHggKiBkeCArIGR5ICogZHk7XG4gICAgICBkYSAqPSBkYTtcbiAgICAgIGRiICo9IGRiO1xuICAgICAgdmFyIHggPSAuNSArIChkYiAtIGRhKSAvICgyICogZGMpLCB5ID0gTWF0aC5zcXJ0KE1hdGgubWF4KDAsIDIgKiBkYSAqIChkYiArIGRjKSAtIChkYiAtPSBkYykgKiBkYiAtIGRhICogZGEpKSAvICgyICogZGMpO1xuICAgICAgYy54ID0gYS54ICsgeCAqIGR4ICsgeSAqIGR5O1xuICAgICAgYy55ID0gYS55ICsgeCAqIGR5IC0geSAqIGR4O1xuICAgIH0gZWxzZSB7XG4gICAgICBjLnggPSBhLnggKyBkYjtcbiAgICAgIGMueSA9IGEueTtcbiAgICB9XG4gIH1cbiAgZDMubGF5b3V0LnRyZWUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaGllcmFyY2h5ID0gZDMubGF5b3V0LmhpZXJhcmNoeSgpLnNvcnQobnVsbCkudmFsdWUobnVsbCksIHNlcGFyYXRpb24gPSBkM19sYXlvdXRfdHJlZVNlcGFyYXRpb24sIHNpemUgPSBbIDEsIDEgXSwgbm9kZVNpemUgPSBudWxsO1xuICAgIGZ1bmN0aW9uIHRyZWUoZCwgaSkge1xuICAgICAgdmFyIG5vZGVzID0gaGllcmFyY2h5LmNhbGwodGhpcywgZCwgaSksIHJvb3QwID0gbm9kZXNbMF0sIHJvb3QxID0gd3JhcFRyZWUocm9vdDApO1xuICAgICAgZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QWZ0ZXIocm9vdDEsIGZpcnN0V2FsayksIHJvb3QxLnBhcmVudC5tID0gLXJvb3QxLno7XG4gICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRCZWZvcmUocm9vdDEsIHNlY29uZFdhbGspO1xuICAgICAgaWYgKG5vZGVTaXplKSBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRCZWZvcmUocm9vdDAsIHNpemVOb2RlKTsgZWxzZSB7XG4gICAgICAgIHZhciBsZWZ0ID0gcm9vdDAsIHJpZ2h0ID0gcm9vdDAsIGJvdHRvbSA9IHJvb3QwO1xuICAgICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRCZWZvcmUocm9vdDAsIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgICBpZiAobm9kZS54IDwgbGVmdC54KSBsZWZ0ID0gbm9kZTtcbiAgICAgICAgICBpZiAobm9kZS54ID4gcmlnaHQueCkgcmlnaHQgPSBub2RlO1xuICAgICAgICAgIGlmIChub2RlLmRlcHRoID4gYm90dG9tLmRlcHRoKSBib3R0b20gPSBub2RlO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIHR4ID0gc2VwYXJhdGlvbihsZWZ0LCByaWdodCkgLyAyIC0gbGVmdC54LCBreCA9IHNpemVbMF0gLyAocmlnaHQueCArIHNlcGFyYXRpb24ocmlnaHQsIGxlZnQpIC8gMiArIHR4KSwga3kgPSBzaXplWzFdIC8gKGJvdHRvbS5kZXB0aCB8fCAxKTtcbiAgICAgICAgZDNfbGF5b3V0X2hpZXJhcmNoeVZpc2l0QmVmb3JlKHJvb3QwLCBmdW5jdGlvbihub2RlKSB7XG4gICAgICAgICAgbm9kZS54ID0gKG5vZGUueCArIHR4KSAqIGt4O1xuICAgICAgICAgIG5vZGUueSA9IG5vZGUuZGVwdGggKiBreTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbm9kZXM7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHdyYXBUcmVlKHJvb3QwKSB7XG4gICAgICB2YXIgcm9vdDEgPSB7XG4gICAgICAgIEE6IG51bGwsXG4gICAgICAgIGNoaWxkcmVuOiBbIHJvb3QwIF1cbiAgICAgIH0sIHF1ZXVlID0gWyByb290MSBdLCBub2RlMTtcbiAgICAgIHdoaWxlICgobm9kZTEgPSBxdWV1ZS5wb3AoKSkgIT0gbnVsbCkge1xuICAgICAgICBmb3IgKHZhciBjaGlsZHJlbiA9IG5vZGUxLmNoaWxkcmVuLCBjaGlsZCwgaSA9IDAsIG4gPSBjaGlsZHJlbi5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICBxdWV1ZS5wdXNoKChjaGlsZHJlbltpXSA9IGNoaWxkID0ge1xuICAgICAgICAgICAgXzogY2hpbGRyZW5baV0sXG4gICAgICAgICAgICBwYXJlbnQ6IG5vZGUxLFxuICAgICAgICAgICAgY2hpbGRyZW46IChjaGlsZCA9IGNoaWxkcmVuW2ldLmNoaWxkcmVuKSAmJiBjaGlsZC5zbGljZSgpIHx8IFtdLFxuICAgICAgICAgICAgQTogbnVsbCxcbiAgICAgICAgICAgIGE6IG51bGwsXG4gICAgICAgICAgICB6OiAwLFxuICAgICAgICAgICAgbTogMCxcbiAgICAgICAgICAgIGM6IDAsXG4gICAgICAgICAgICBzOiAwLFxuICAgICAgICAgICAgdDogbnVsbCxcbiAgICAgICAgICAgIGk6IGlcbiAgICAgICAgICB9KS5hID0gY2hpbGQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcm9vdDEuY2hpbGRyZW5bMF07XG4gICAgfVxuICAgIGZ1bmN0aW9uIGZpcnN0V2Fsayh2KSB7XG4gICAgICB2YXIgY2hpbGRyZW4gPSB2LmNoaWxkcmVuLCBzaWJsaW5ncyA9IHYucGFyZW50LmNoaWxkcmVuLCB3ID0gdi5pID8gc2libGluZ3Nbdi5pIC0gMV0gOiBudWxsO1xuICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICBkM19sYXlvdXRfdHJlZVNoaWZ0KHYpO1xuICAgICAgICB2YXIgbWlkcG9pbnQgPSAoY2hpbGRyZW5bMF0ueiArIGNoaWxkcmVuW2NoaWxkcmVuLmxlbmd0aCAtIDFdLnopIC8gMjtcbiAgICAgICAgaWYgKHcpIHtcbiAgICAgICAgICB2LnogPSB3LnogKyBzZXBhcmF0aW9uKHYuXywgdy5fKTtcbiAgICAgICAgICB2Lm0gPSB2LnogLSBtaWRwb2ludDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2LnogPSBtaWRwb2ludDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh3KSB7XG4gICAgICAgIHYueiA9IHcueiArIHNlcGFyYXRpb24odi5fLCB3Ll8pO1xuICAgICAgfVxuICAgICAgdi5wYXJlbnQuQSA9IGFwcG9ydGlvbih2LCB3LCB2LnBhcmVudC5BIHx8IHNpYmxpbmdzWzBdKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2Vjb25kV2Fsayh2KSB7XG4gICAgICB2Ll8ueCA9IHYueiArIHYucGFyZW50Lm07XG4gICAgICB2Lm0gKz0gdi5wYXJlbnQubTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXBwb3J0aW9uKHYsIHcsIGFuY2VzdG9yKSB7XG4gICAgICBpZiAodykge1xuICAgICAgICB2YXIgdmlwID0gdiwgdm9wID0gdiwgdmltID0gdywgdm9tID0gdmlwLnBhcmVudC5jaGlsZHJlblswXSwgc2lwID0gdmlwLm0sIHNvcCA9IHZvcC5tLCBzaW0gPSB2aW0ubSwgc29tID0gdm9tLm0sIHNoaWZ0O1xuICAgICAgICB3aGlsZSAodmltID0gZDNfbGF5b3V0X3RyZWVSaWdodCh2aW0pLCB2aXAgPSBkM19sYXlvdXRfdHJlZUxlZnQodmlwKSwgdmltICYmIHZpcCkge1xuICAgICAgICAgIHZvbSA9IGQzX2xheW91dF90cmVlTGVmdCh2b20pO1xuICAgICAgICAgIHZvcCA9IGQzX2xheW91dF90cmVlUmlnaHQodm9wKTtcbiAgICAgICAgICB2b3AuYSA9IHY7XG4gICAgICAgICAgc2hpZnQgPSB2aW0ueiArIHNpbSAtIHZpcC56IC0gc2lwICsgc2VwYXJhdGlvbih2aW0uXywgdmlwLl8pO1xuICAgICAgICAgIGlmIChzaGlmdCA+IDApIHtcbiAgICAgICAgICAgIGQzX2xheW91dF90cmVlTW92ZShkM19sYXlvdXRfdHJlZUFuY2VzdG9yKHZpbSwgdiwgYW5jZXN0b3IpLCB2LCBzaGlmdCk7XG4gICAgICAgICAgICBzaXAgKz0gc2hpZnQ7XG4gICAgICAgICAgICBzb3AgKz0gc2hpZnQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNpbSArPSB2aW0ubTtcbiAgICAgICAgICBzaXAgKz0gdmlwLm07XG4gICAgICAgICAgc29tICs9IHZvbS5tO1xuICAgICAgICAgIHNvcCArPSB2b3AubTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmltICYmICFkM19sYXlvdXRfdHJlZVJpZ2h0KHZvcCkpIHtcbiAgICAgICAgICB2b3AudCA9IHZpbTtcbiAgICAgICAgICB2b3AubSArPSBzaW0gLSBzb3A7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZpcCAmJiAhZDNfbGF5b3V0X3RyZWVMZWZ0KHZvbSkpIHtcbiAgICAgICAgICB2b20udCA9IHZpcDtcbiAgICAgICAgICB2b20ubSArPSBzaXAgLSBzb207XG4gICAgICAgICAgYW5jZXN0b3IgPSB2O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gYW5jZXN0b3I7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNpemVOb2RlKG5vZGUpIHtcbiAgICAgIG5vZGUueCAqPSBzaXplWzBdO1xuICAgICAgbm9kZS55ID0gbm9kZS5kZXB0aCAqIHNpemVbMV07XG4gICAgfVxuICAgIHRyZWUuc2VwYXJhdGlvbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNlcGFyYXRpb247XG4gICAgICBzZXBhcmF0aW9uID0geDtcbiAgICAgIHJldHVybiB0cmVlO1xuICAgIH07XG4gICAgdHJlZS5zaXplID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbm9kZVNpemUgPyBudWxsIDogc2l6ZTtcbiAgICAgIG5vZGVTaXplID0gKHNpemUgPSB4KSA9PSBudWxsID8gc2l6ZU5vZGUgOiBudWxsO1xuICAgICAgcmV0dXJuIHRyZWU7XG4gICAgfTtcbiAgICB0cmVlLm5vZGVTaXplID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gbm9kZVNpemUgPyBzaXplIDogbnVsbDtcbiAgICAgIG5vZGVTaXplID0gKHNpemUgPSB4KSA9PSBudWxsID8gbnVsbCA6IHNpemVOb2RlO1xuICAgICAgcmV0dXJuIHRyZWU7XG4gICAgfTtcbiAgICByZXR1cm4gZDNfbGF5b3V0X2hpZXJhcmNoeVJlYmluZCh0cmVlLCBoaWVyYXJjaHkpO1xuICB9O1xuICBmdW5jdGlvbiBkM19sYXlvdXRfdHJlZVNlcGFyYXRpb24oYSwgYikge1xuICAgIHJldHVybiBhLnBhcmVudCA9PSBiLnBhcmVudCA/IDEgOiAyO1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlTGVmdCh2KSB7XG4gICAgdmFyIGNoaWxkcmVuID0gdi5jaGlsZHJlbjtcbiAgICByZXR1cm4gY2hpbGRyZW4ubGVuZ3RoID8gY2hpbGRyZW5bMF0gOiB2LnQ7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X3RyZWVSaWdodCh2KSB7XG4gICAgdmFyIGNoaWxkcmVuID0gdi5jaGlsZHJlbiwgbjtcbiAgICByZXR1cm4gKG4gPSBjaGlsZHJlbi5sZW5ndGgpID8gY2hpbGRyZW5bbiAtIDFdIDogdi50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlTW92ZSh3bSwgd3AsIHNoaWZ0KSB7XG4gICAgdmFyIGNoYW5nZSA9IHNoaWZ0IC8gKHdwLmkgLSB3bS5pKTtcbiAgICB3cC5jIC09IGNoYW5nZTtcbiAgICB3cC5zICs9IHNoaWZ0O1xuICAgIHdtLmMgKz0gY2hhbmdlO1xuICAgIHdwLnogKz0gc2hpZnQ7XG4gICAgd3AubSArPSBzaGlmdDtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfdHJlZVNoaWZ0KHYpIHtcbiAgICB2YXIgc2hpZnQgPSAwLCBjaGFuZ2UgPSAwLCBjaGlsZHJlbiA9IHYuY2hpbGRyZW4sIGkgPSBjaGlsZHJlbi5sZW5ndGgsIHc7XG4gICAgd2hpbGUgKC0taSA+PSAwKSB7XG4gICAgICB3ID0gY2hpbGRyZW5baV07XG4gICAgICB3LnogKz0gc2hpZnQ7XG4gICAgICB3Lm0gKz0gc2hpZnQ7XG4gICAgICBzaGlmdCArPSB3LnMgKyAoY2hhbmdlICs9IHcuYyk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlQW5jZXN0b3IodmltLCB2LCBhbmNlc3Rvcikge1xuICAgIHJldHVybiB2aW0uYS5wYXJlbnQgPT09IHYucGFyZW50ID8gdmltLmEgOiBhbmNlc3RvcjtcbiAgfVxuICBkMy5sYXlvdXQuY2x1c3RlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoaWVyYXJjaHkgPSBkMy5sYXlvdXQuaGllcmFyY2h5KCkuc29ydChudWxsKS52YWx1ZShudWxsKSwgc2VwYXJhdGlvbiA9IGQzX2xheW91dF90cmVlU2VwYXJhdGlvbiwgc2l6ZSA9IFsgMSwgMSBdLCBub2RlU2l6ZSA9IGZhbHNlO1xuICAgIGZ1bmN0aW9uIGNsdXN0ZXIoZCwgaSkge1xuICAgICAgdmFyIG5vZGVzID0gaGllcmFyY2h5LmNhbGwodGhpcywgZCwgaSksIHJvb3QgPSBub2Rlc1swXSwgcHJldmlvdXNOb2RlLCB4ID0gMDtcbiAgICAgIGQzX2xheW91dF9oaWVyYXJjaHlWaXNpdEFmdGVyKHJvb3QsIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgaWYgKGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgIG5vZGUueCA9IGQzX2xheW91dF9jbHVzdGVyWChjaGlsZHJlbik7XG4gICAgICAgICAgbm9kZS55ID0gZDNfbGF5b3V0X2NsdXN0ZXJZKGNoaWxkcmVuKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBub2RlLnggPSBwcmV2aW91c05vZGUgPyB4ICs9IHNlcGFyYXRpb24obm9kZSwgcHJldmlvdXNOb2RlKSA6IDA7XG4gICAgICAgICAgbm9kZS55ID0gMDtcbiAgICAgICAgICBwcmV2aW91c05vZGUgPSBub2RlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHZhciBsZWZ0ID0gZDNfbGF5b3V0X2NsdXN0ZXJMZWZ0KHJvb3QpLCByaWdodCA9IGQzX2xheW91dF9jbHVzdGVyUmlnaHQocm9vdCksIHgwID0gbGVmdC54IC0gc2VwYXJhdGlvbihsZWZ0LCByaWdodCkgLyAyLCB4MSA9IHJpZ2h0LnggKyBzZXBhcmF0aW9uKHJpZ2h0LCBsZWZ0KSAvIDI7XG4gICAgICBkM19sYXlvdXRfaGllcmFyY2h5VmlzaXRBZnRlcihyb290LCBub2RlU2l6ZSA/IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgbm9kZS54ID0gKG5vZGUueCAtIHJvb3QueCkgKiBzaXplWzBdO1xuICAgICAgICBub2RlLnkgPSAocm9vdC55IC0gbm9kZS55KSAqIHNpemVbMV07XG4gICAgICB9IDogZnVuY3Rpb24obm9kZSkge1xuICAgICAgICBub2RlLnggPSAobm9kZS54IC0geDApIC8gKHgxIC0geDApICogc2l6ZVswXTtcbiAgICAgICAgbm9kZS55ID0gKDEgLSAocm9vdC55ID8gbm9kZS55IC8gcm9vdC55IDogMSkpICogc2l6ZVsxXTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG5vZGVzO1xuICAgIH1cbiAgICBjbHVzdGVyLnNlcGFyYXRpb24gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzZXBhcmF0aW9uO1xuICAgICAgc2VwYXJhdGlvbiA9IHg7XG4gICAgICByZXR1cm4gY2x1c3RlcjtcbiAgICB9O1xuICAgIGNsdXN0ZXIuc2l6ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG5vZGVTaXplID8gbnVsbCA6IHNpemU7XG4gICAgICBub2RlU2l6ZSA9IChzaXplID0geCkgPT0gbnVsbDtcbiAgICAgIHJldHVybiBjbHVzdGVyO1xuICAgIH07XG4gICAgY2x1c3Rlci5ub2RlU2l6ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG5vZGVTaXplID8gc2l6ZSA6IG51bGw7XG4gICAgICBub2RlU2l6ZSA9IChzaXplID0geCkgIT0gbnVsbDtcbiAgICAgIHJldHVybiBjbHVzdGVyO1xuICAgIH07XG4gICAgcmV0dXJuIGQzX2xheW91dF9oaWVyYXJjaHlSZWJpbmQoY2x1c3RlciwgaGllcmFyY2h5KTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2NsdXN0ZXJZKGNoaWxkcmVuKSB7XG4gICAgcmV0dXJuIDEgKyBkMy5tYXgoY2hpbGRyZW4sIGZ1bmN0aW9uKGNoaWxkKSB7XG4gICAgICByZXR1cm4gY2hpbGQueTtcbiAgICB9KTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfY2x1c3RlclgoY2hpbGRyZW4pIHtcbiAgICByZXR1cm4gY2hpbGRyZW4ucmVkdWNlKGZ1bmN0aW9uKHgsIGNoaWxkKSB7XG4gICAgICByZXR1cm4geCArIGNoaWxkLng7XG4gICAgfSwgMCkgLyBjaGlsZHJlbi5sZW5ndGg7XG4gIH1cbiAgZnVuY3Rpb24gZDNfbGF5b3V0X2NsdXN0ZXJMZWZ0KG5vZGUpIHtcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuO1xuICAgIHJldHVybiBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggPyBkM19sYXlvdXRfY2x1c3RlckxlZnQoY2hpbGRyZW5bMF0pIDogbm9kZTtcbiAgfVxuICBmdW5jdGlvbiBkM19sYXlvdXRfY2x1c3RlclJpZ2h0KG5vZGUpIHtcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuLCBuO1xuICAgIHJldHVybiBjaGlsZHJlbiAmJiAobiA9IGNoaWxkcmVuLmxlbmd0aCkgPyBkM19sYXlvdXRfY2x1c3RlclJpZ2h0KGNoaWxkcmVuW24gLSAxXSkgOiBub2RlO1xuICB9XG4gIGQzLmxheW91dC50cmVlbWFwID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGhpZXJhcmNoeSA9IGQzLmxheW91dC5oaWVyYXJjaHkoKSwgcm91bmQgPSBNYXRoLnJvdW5kLCBzaXplID0gWyAxLCAxIF0sIHBhZGRpbmcgPSBudWxsLCBwYWQgPSBkM19sYXlvdXRfdHJlZW1hcFBhZE51bGwsIHN0aWNreSA9IGZhbHNlLCBzdGlja2llcywgbW9kZSA9IFwic3F1YXJpZnlcIiwgcmF0aW8gPSAuNSAqICgxICsgTWF0aC5zcXJ0KDUpKTtcbiAgICBmdW5jdGlvbiBzY2FsZShjaGlsZHJlbiwgaykge1xuICAgICAgdmFyIGkgPSAtMSwgbiA9IGNoaWxkcmVuLmxlbmd0aCwgY2hpbGQsIGFyZWE7XG4gICAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgICBhcmVhID0gKGNoaWxkID0gY2hpbGRyZW5baV0pLnZhbHVlICogKGsgPCAwID8gMCA6IGspO1xuICAgICAgICBjaGlsZC5hcmVhID0gaXNOYU4oYXJlYSkgfHwgYXJlYSA8PSAwID8gMCA6IGFyZWE7XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNxdWFyaWZ5KG5vZGUpIHtcbiAgICAgIHZhciBjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW47XG4gICAgICBpZiAoY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgIHZhciByZWN0ID0gcGFkKG5vZGUpLCByb3cgPSBbXSwgcmVtYWluaW5nID0gY2hpbGRyZW4uc2xpY2UoKSwgY2hpbGQsIGJlc3QgPSBJbmZpbml0eSwgc2NvcmUsIHUgPSBtb2RlID09PSBcInNsaWNlXCIgPyByZWN0LmR4IDogbW9kZSA9PT0gXCJkaWNlXCIgPyByZWN0LmR5IDogbW9kZSA9PT0gXCJzbGljZS1kaWNlXCIgPyBub2RlLmRlcHRoICYgMSA/IHJlY3QuZHkgOiByZWN0LmR4IDogTWF0aC5taW4ocmVjdC5keCwgcmVjdC5keSksIG47XG4gICAgICAgIHNjYWxlKHJlbWFpbmluZywgcmVjdC5keCAqIHJlY3QuZHkgLyBub2RlLnZhbHVlKTtcbiAgICAgICAgcm93LmFyZWEgPSAwO1xuICAgICAgICB3aGlsZSAoKG4gPSByZW1haW5pbmcubGVuZ3RoKSA+IDApIHtcbiAgICAgICAgICByb3cucHVzaChjaGlsZCA9IHJlbWFpbmluZ1tuIC0gMV0pO1xuICAgICAgICAgIHJvdy5hcmVhICs9IGNoaWxkLmFyZWE7XG4gICAgICAgICAgaWYgKG1vZGUgIT09IFwic3F1YXJpZnlcIiB8fCAoc2NvcmUgPSB3b3JzdChyb3csIHUpKSA8PSBiZXN0KSB7XG4gICAgICAgICAgICByZW1haW5pbmcucG9wKCk7XG4gICAgICAgICAgICBiZXN0ID0gc2NvcmU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJvdy5hcmVhIC09IHJvdy5wb3AoKS5hcmVhO1xuICAgICAgICAgICAgcG9zaXRpb24ocm93LCB1LCByZWN0LCBmYWxzZSk7XG4gICAgICAgICAgICB1ID0gTWF0aC5taW4ocmVjdC5keCwgcmVjdC5keSk7XG4gICAgICAgICAgICByb3cubGVuZ3RoID0gcm93LmFyZWEgPSAwO1xuICAgICAgICAgICAgYmVzdCA9IEluZmluaXR5O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAocm93Lmxlbmd0aCkge1xuICAgICAgICAgIHBvc2l0aW9uKHJvdywgdSwgcmVjdCwgdHJ1ZSk7XG4gICAgICAgICAgcm93Lmxlbmd0aCA9IHJvdy5hcmVhID0gMDtcbiAgICAgICAgfVxuICAgICAgICBjaGlsZHJlbi5mb3JFYWNoKHNxdWFyaWZ5KTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gc3RpY2tpZnkobm9kZSkge1xuICAgICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcbiAgICAgIGlmIChjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgdmFyIHJlY3QgPSBwYWQobm9kZSksIHJlbWFpbmluZyA9IGNoaWxkcmVuLnNsaWNlKCksIGNoaWxkLCByb3cgPSBbXTtcbiAgICAgICAgc2NhbGUocmVtYWluaW5nLCByZWN0LmR4ICogcmVjdC5keSAvIG5vZGUudmFsdWUpO1xuICAgICAgICByb3cuYXJlYSA9IDA7XG4gICAgICAgIHdoaWxlIChjaGlsZCA9IHJlbWFpbmluZy5wb3AoKSkge1xuICAgICAgICAgIHJvdy5wdXNoKGNoaWxkKTtcbiAgICAgICAgICByb3cuYXJlYSArPSBjaGlsZC5hcmVhO1xuICAgICAgICAgIGlmIChjaGlsZC56ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHBvc2l0aW9uKHJvdywgY2hpbGQueiA/IHJlY3QuZHggOiByZWN0LmR5LCByZWN0LCAhcmVtYWluaW5nLmxlbmd0aCk7XG4gICAgICAgICAgICByb3cubGVuZ3RoID0gcm93LmFyZWEgPSAwO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjaGlsZHJlbi5mb3JFYWNoKHN0aWNraWZ5KTtcbiAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gd29yc3Qocm93LCB1KSB7XG4gICAgICB2YXIgcyA9IHJvdy5hcmVhLCByLCBybWF4ID0gMCwgcm1pbiA9IEluZmluaXR5LCBpID0gLTEsIG4gPSByb3cubGVuZ3RoO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgaWYgKCEociA9IHJvd1tpXS5hcmVhKSkgY29udGludWU7XG4gICAgICAgIGlmIChyIDwgcm1pbikgcm1pbiA9IHI7XG4gICAgICAgIGlmIChyID4gcm1heCkgcm1heCA9IHI7XG4gICAgICB9XG4gICAgICBzICo9IHM7XG4gICAgICB1ICo9IHU7XG4gICAgICByZXR1cm4gcyA/IE1hdGgubWF4KHUgKiBybWF4ICogcmF0aW8gLyBzLCBzIC8gKHUgKiBybWluICogcmF0aW8pKSA6IEluZmluaXR5O1xuICAgIH1cbiAgICBmdW5jdGlvbiBwb3NpdGlvbihyb3csIHUsIHJlY3QsIGZsdXNoKSB7XG4gICAgICB2YXIgaSA9IC0xLCBuID0gcm93Lmxlbmd0aCwgeCA9IHJlY3QueCwgeSA9IHJlY3QueSwgdiA9IHUgPyByb3VuZChyb3cuYXJlYSAvIHUpIDogMCwgbztcbiAgICAgIGlmICh1ID09IHJlY3QuZHgpIHtcbiAgICAgICAgaWYgKGZsdXNoIHx8IHYgPiByZWN0LmR5KSB2ID0gcmVjdC5keTtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgICBvID0gcm93W2ldO1xuICAgICAgICAgIG8ueCA9IHg7XG4gICAgICAgICAgby55ID0geTtcbiAgICAgICAgICBvLmR5ID0gdjtcbiAgICAgICAgICB4ICs9IG8uZHggPSBNYXRoLm1pbihyZWN0LnggKyByZWN0LmR4IC0geCwgdiA/IHJvdW5kKG8uYXJlYSAvIHYpIDogMCk7XG4gICAgICAgIH1cbiAgICAgICAgby56ID0gdHJ1ZTtcbiAgICAgICAgby5keCArPSByZWN0LnggKyByZWN0LmR4IC0geDtcbiAgICAgICAgcmVjdC55ICs9IHY7XG4gICAgICAgIHJlY3QuZHkgLT0gdjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmbHVzaCB8fCB2ID4gcmVjdC5keCkgdiA9IHJlY3QuZHg7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgbyA9IHJvd1tpXTtcbiAgICAgICAgICBvLnggPSB4O1xuICAgICAgICAgIG8ueSA9IHk7XG4gICAgICAgICAgby5keCA9IHY7XG4gICAgICAgICAgeSArPSBvLmR5ID0gTWF0aC5taW4ocmVjdC55ICsgcmVjdC5keSAtIHksIHYgPyByb3VuZChvLmFyZWEgLyB2KSA6IDApO1xuICAgICAgICB9XG4gICAgICAgIG8ueiA9IGZhbHNlO1xuICAgICAgICBvLmR5ICs9IHJlY3QueSArIHJlY3QuZHkgLSB5O1xuICAgICAgICByZWN0LnggKz0gdjtcbiAgICAgICAgcmVjdC5keCAtPSB2O1xuICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiB0cmVlbWFwKGQpIHtcbiAgICAgIHZhciBub2RlcyA9IHN0aWNraWVzIHx8IGhpZXJhcmNoeShkKSwgcm9vdCA9IG5vZGVzWzBdO1xuICAgICAgcm9vdC54ID0gcm9vdC55ID0gMDtcbiAgICAgIGlmIChyb290LnZhbHVlKSByb290LmR4ID0gc2l6ZVswXSwgcm9vdC5keSA9IHNpemVbMV07IGVsc2Ugcm9vdC5keCA9IHJvb3QuZHkgPSAwO1xuICAgICAgaWYgKHN0aWNraWVzKSBoaWVyYXJjaHkucmV2YWx1ZShyb290KTtcbiAgICAgIHNjYWxlKFsgcm9vdCBdLCByb290LmR4ICogcm9vdC5keSAvIHJvb3QudmFsdWUpO1xuICAgICAgKHN0aWNraWVzID8gc3RpY2tpZnkgOiBzcXVhcmlmeSkocm9vdCk7XG4gICAgICBpZiAoc3RpY2t5KSBzdGlja2llcyA9IG5vZGVzO1xuICAgICAgcmV0dXJuIG5vZGVzO1xuICAgIH1cbiAgICB0cmVlbWFwLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzaXplO1xuICAgICAgc2l6ZSA9IHg7XG4gICAgICByZXR1cm4gdHJlZW1hcDtcbiAgICB9O1xuICAgIHRyZWVtYXAucGFkZGluZyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHBhZGRpbmc7XG4gICAgICBmdW5jdGlvbiBwYWRGdW5jdGlvbihub2RlKSB7XG4gICAgICAgIHZhciBwID0geC5jYWxsKHRyZWVtYXAsIG5vZGUsIG5vZGUuZGVwdGgpO1xuICAgICAgICByZXR1cm4gcCA9PSBudWxsID8gZDNfbGF5b3V0X3RyZWVtYXBQYWROdWxsKG5vZGUpIDogZDNfbGF5b3V0X3RyZWVtYXBQYWQobm9kZSwgdHlwZW9mIHAgPT09IFwibnVtYmVyXCIgPyBbIHAsIHAsIHAsIHAgXSA6IHApO1xuICAgICAgfVxuICAgICAgZnVuY3Rpb24gcGFkQ29uc3RhbnQobm9kZSkge1xuICAgICAgICByZXR1cm4gZDNfbGF5b3V0X3RyZWVtYXBQYWQobm9kZSwgeCk7XG4gICAgICB9XG4gICAgICB2YXIgdHlwZTtcbiAgICAgIHBhZCA9IChwYWRkaW5nID0geCkgPT0gbnVsbCA/IGQzX2xheW91dF90cmVlbWFwUGFkTnVsbCA6ICh0eXBlID0gdHlwZW9mIHgpID09PSBcImZ1bmN0aW9uXCIgPyBwYWRGdW5jdGlvbiA6IHR5cGUgPT09IFwibnVtYmVyXCIgPyAoeCA9IFsgeCwgeCwgeCwgeCBdLCBcbiAgICAgIHBhZENvbnN0YW50KSA6IHBhZENvbnN0YW50O1xuICAgICAgcmV0dXJuIHRyZWVtYXA7XG4gICAgfTtcbiAgICB0cmVlbWFwLnJvdW5kID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcm91bmQgIT0gTnVtYmVyO1xuICAgICAgcm91bmQgPSB4ID8gTWF0aC5yb3VuZCA6IE51bWJlcjtcbiAgICAgIHJldHVybiB0cmVlbWFwO1xuICAgIH07XG4gICAgdHJlZW1hcC5zdGlja3kgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzdGlja3k7XG4gICAgICBzdGlja3kgPSB4O1xuICAgICAgc3RpY2tpZXMgPSBudWxsO1xuICAgICAgcmV0dXJuIHRyZWVtYXA7XG4gICAgfTtcbiAgICB0cmVlbWFwLnJhdGlvID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmF0aW87XG4gICAgICByYXRpbyA9IHg7XG4gICAgICByZXR1cm4gdHJlZW1hcDtcbiAgICB9O1xuICAgIHRyZWVtYXAubW9kZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIG1vZGU7XG4gICAgICBtb2RlID0geCArIFwiXCI7XG4gICAgICByZXR1cm4gdHJlZW1hcDtcbiAgICB9O1xuICAgIHJldHVybiBkM19sYXlvdXRfaGllcmFyY2h5UmViaW5kKHRyZWVtYXAsIGhpZXJhcmNoeSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlbWFwUGFkTnVsbChub2RlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IG5vZGUueCxcbiAgICAgIHk6IG5vZGUueSxcbiAgICAgIGR4OiBub2RlLmR4LFxuICAgICAgZHk6IG5vZGUuZHlcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX2xheW91dF90cmVlbWFwUGFkKG5vZGUsIHBhZGRpbmcpIHtcbiAgICB2YXIgeCA9IG5vZGUueCArIHBhZGRpbmdbM10sIHkgPSBub2RlLnkgKyBwYWRkaW5nWzBdLCBkeCA9IG5vZGUuZHggLSBwYWRkaW5nWzFdIC0gcGFkZGluZ1szXSwgZHkgPSBub2RlLmR5IC0gcGFkZGluZ1swXSAtIHBhZGRpbmdbMl07XG4gICAgaWYgKGR4IDwgMCkge1xuICAgICAgeCArPSBkeCAvIDI7XG4gICAgICBkeCA9IDA7XG4gICAgfVxuICAgIGlmIChkeSA8IDApIHtcbiAgICAgIHkgKz0gZHkgLyAyO1xuICAgICAgZHkgPSAwO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgeDogeCxcbiAgICAgIHk6IHksXG4gICAgICBkeDogZHgsXG4gICAgICBkeTogZHlcbiAgICB9O1xuICB9XG4gIGQzLnJhbmRvbSA9IHtcbiAgICBub3JtYWw6IGZ1bmN0aW9uKMK1LCDPgykge1xuICAgICAgdmFyIG4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgICAgaWYgKG4gPCAyKSDPgyA9IDE7XG4gICAgICBpZiAobiA8IDEpIMK1ID0gMDtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHgsIHksIHI7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICB4ID0gTWF0aC5yYW5kb20oKSAqIDIgLSAxO1xuICAgICAgICAgIHkgPSBNYXRoLnJhbmRvbSgpICogMiAtIDE7XG4gICAgICAgICAgciA9IHggKiB4ICsgeSAqIHk7XG4gICAgICAgIH0gd2hpbGUgKCFyIHx8IHIgPiAxKTtcbiAgICAgICAgcmV0dXJuIMK1ICsgz4MgKiB4ICogTWF0aC5zcXJ0KC0yICogTWF0aC5sb2cocikgLyByKTtcbiAgICAgIH07XG4gICAgfSxcbiAgICBsb2dOb3JtYWw6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHJhbmRvbSA9IGQzLnJhbmRvbS5ub3JtYWwuYXBwbHkoZDMsIGFyZ3VtZW50cyk7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmV4cChyYW5kb20oKSk7XG4gICAgICB9O1xuICAgIH0sXG4gICAgYmF0ZXM6IGZ1bmN0aW9uKG0pIHtcbiAgICAgIHZhciByYW5kb20gPSBkMy5yYW5kb20uaXJ3aW5IYWxsKG0pO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gcmFuZG9tKCkgLyBtO1xuICAgICAgfTtcbiAgICB9LFxuICAgIGlyd2luSGFsbDogZnVuY3Rpb24obSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICBmb3IgKHZhciBzID0gMCwgaiA9IDA7IGogPCBtOyBqKyspIHMgKz0gTWF0aC5yYW5kb20oKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgICB9O1xuICAgIH1cbiAgfTtcbiAgZDMuc2NhbGUgPSB7fTtcbiAgZnVuY3Rpb24gZDNfc2NhbGVFeHRlbnQoZG9tYWluKSB7XG4gICAgdmFyIHN0YXJ0ID0gZG9tYWluWzBdLCBzdG9wID0gZG9tYWluW2RvbWFpbi5sZW5ndGggLSAxXTtcbiAgICByZXR1cm4gc3RhcnQgPCBzdG9wID8gWyBzdGFydCwgc3RvcCBdIDogWyBzdG9wLCBzdGFydCBdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NjYWxlUmFuZ2Uoc2NhbGUpIHtcbiAgICByZXR1cm4gc2NhbGUucmFuZ2VFeHRlbnQgPyBzY2FsZS5yYW5nZUV4dGVudCgpIDogZDNfc2NhbGVFeHRlbnQoc2NhbGUucmFuZ2UoKSk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2NhbGVfYmlsaW5lYXIoZG9tYWluLCByYW5nZSwgdW5pbnRlcnBvbGF0ZSwgaW50ZXJwb2xhdGUpIHtcbiAgICB2YXIgdSA9IHVuaW50ZXJwb2xhdGUoZG9tYWluWzBdLCBkb21haW5bMV0pLCBpID0gaW50ZXJwb2xhdGUocmFuZ2VbMF0sIHJhbmdlWzFdKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIGkodSh4KSk7XG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19zY2FsZV9uaWNlKGRvbWFpbiwgbmljZSkge1xuICAgIHZhciBpMCA9IDAsIGkxID0gZG9tYWluLmxlbmd0aCAtIDEsIHgwID0gZG9tYWluW2kwXSwgeDEgPSBkb21haW5baTFdLCBkeDtcbiAgICBpZiAoeDEgPCB4MCkge1xuICAgICAgZHggPSBpMCwgaTAgPSBpMSwgaTEgPSBkeDtcbiAgICAgIGR4ID0geDAsIHgwID0geDEsIHgxID0gZHg7XG4gICAgfVxuICAgIGRvbWFpbltpMF0gPSBuaWNlLmZsb29yKHgwKTtcbiAgICBkb21haW5baTFdID0gbmljZS5jZWlsKHgxKTtcbiAgICByZXR1cm4gZG9tYWluO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX25pY2VTdGVwKHN0ZXApIHtcbiAgICByZXR1cm4gc3RlcCA/IHtcbiAgICAgIGZsb29yOiBmdW5jdGlvbih4KSB7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKHggLyBzdGVwKSAqIHN0ZXA7XG4gICAgICB9LFxuICAgICAgY2VpbDogZnVuY3Rpb24oeCkge1xuICAgICAgICByZXR1cm4gTWF0aC5jZWlsKHggLyBzdGVwKSAqIHN0ZXA7XG4gICAgICB9XG4gICAgfSA6IGQzX3NjYWxlX25pY2VJZGVudGl0eTtcbiAgfVxuICB2YXIgZDNfc2NhbGVfbmljZUlkZW50aXR5ID0ge1xuICAgIGZsb29yOiBkM19pZGVudGl0eSxcbiAgICBjZWlsOiBkM19pZGVudGl0eVxuICB9O1xuICBmdW5jdGlvbiBkM19zY2FsZV9wb2x5bGluZWFyKGRvbWFpbiwgcmFuZ2UsIHVuaW50ZXJwb2xhdGUsIGludGVycG9sYXRlKSB7XG4gICAgdmFyIHUgPSBbXSwgaSA9IFtdLCBqID0gMCwgayA9IE1hdGgubWluKGRvbWFpbi5sZW5ndGgsIHJhbmdlLmxlbmd0aCkgLSAxO1xuICAgIGlmIChkb21haW5ba10gPCBkb21haW5bMF0pIHtcbiAgICAgIGRvbWFpbiA9IGRvbWFpbi5zbGljZSgpLnJldmVyc2UoKTtcbiAgICAgIHJhbmdlID0gcmFuZ2Uuc2xpY2UoKS5yZXZlcnNlKCk7XG4gICAgfVxuICAgIHdoaWxlICgrK2ogPD0gaykge1xuICAgICAgdS5wdXNoKHVuaW50ZXJwb2xhdGUoZG9tYWluW2ogLSAxXSwgZG9tYWluW2pdKSk7XG4gICAgICBpLnB1c2goaW50ZXJwb2xhdGUocmFuZ2VbaiAtIDFdLCByYW5nZVtqXSkpO1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb24oeCkge1xuICAgICAgdmFyIGogPSBkMy5iaXNlY3QoZG9tYWluLCB4LCAxLCBrKSAtIDE7XG4gICAgICByZXR1cm4gaVtqXSh1W2pdKHgpKTtcbiAgICB9O1xuICB9XG4gIGQzLnNjYWxlLmxpbmVhciA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zY2FsZV9saW5lYXIoWyAwLCAxIF0sIFsgMCwgMSBdLCBkM19pbnRlcnBvbGF0ZSwgZmFsc2UpO1xuICB9O1xuICBmdW5jdGlvbiBkM19zY2FsZV9saW5lYXIoZG9tYWluLCByYW5nZSwgaW50ZXJwb2xhdGUsIGNsYW1wKSB7XG4gICAgdmFyIG91dHB1dCwgaW5wdXQ7XG4gICAgZnVuY3Rpb24gcmVzY2FsZSgpIHtcbiAgICAgIHZhciBsaW5lYXIgPSBNYXRoLm1pbihkb21haW4ubGVuZ3RoLCByYW5nZS5sZW5ndGgpID4gMiA/IGQzX3NjYWxlX3BvbHlsaW5lYXIgOiBkM19zY2FsZV9iaWxpbmVhciwgdW5pbnRlcnBvbGF0ZSA9IGNsYW1wID8gZDNfdW5pbnRlcnBvbGF0ZUNsYW1wIDogZDNfdW5pbnRlcnBvbGF0ZU51bWJlcjtcbiAgICAgIG91dHB1dCA9IGxpbmVhcihkb21haW4sIHJhbmdlLCB1bmludGVycG9sYXRlLCBpbnRlcnBvbGF0ZSk7XG4gICAgICBpbnB1dCA9IGxpbmVhcihyYW5nZSwgZG9tYWluLCB1bmludGVycG9sYXRlLCBkM19pbnRlcnBvbGF0ZSk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNjYWxlKHgpIHtcbiAgICAgIHJldHVybiBvdXRwdXQoeCk7XG4gICAgfVxuICAgIHNjYWxlLmludmVydCA9IGZ1bmN0aW9uKHkpIHtcbiAgICAgIHJldHVybiBpbnB1dCh5KTtcbiAgICB9O1xuICAgIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRvbWFpbjtcbiAgICAgIGRvbWFpbiA9IHgubWFwKE51bWJlcik7XG4gICAgICByZXR1cm4gcmVzY2FsZSgpO1xuICAgIH07XG4gICAgc2NhbGUucmFuZ2UgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiByYW5nZTtcbiAgICAgIHJhbmdlID0geDtcbiAgICAgIHJldHVybiByZXNjYWxlKCk7XG4gICAgfTtcbiAgICBzY2FsZS5yYW5nZVJvdW5kID0gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHNjYWxlLnJhbmdlKHgpLmludGVycG9sYXRlKGQzX2ludGVycG9sYXRlUm91bmQpO1xuICAgIH07XG4gICAgc2NhbGUuY2xhbXAgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjbGFtcDtcbiAgICAgIGNsYW1wID0geDtcbiAgICAgIHJldHVybiByZXNjYWxlKCk7XG4gICAgfTtcbiAgICBzY2FsZS5pbnRlcnBvbGF0ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGludGVycG9sYXRlO1xuICAgICAgaW50ZXJwb2xhdGUgPSB4O1xuICAgICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgICB9O1xuICAgIHNjYWxlLnRpY2tzID0gZnVuY3Rpb24obSkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclRpY2tzKGRvbWFpbiwgbSk7XG4gICAgfTtcbiAgICBzY2FsZS50aWNrRm9ybWF0ID0gZnVuY3Rpb24obSwgZm9ybWF0KSB7XG4gICAgICByZXR1cm4gZDNfc2NhbGVfbGluZWFyVGlja0Zvcm1hdChkb21haW4sIG0sIGZvcm1hdCk7XG4gICAgfTtcbiAgICBzY2FsZS5uaWNlID0gZnVuY3Rpb24obSkge1xuICAgICAgZDNfc2NhbGVfbGluZWFyTmljZShkb21haW4sIG0pO1xuICAgICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgICB9O1xuICAgIHNjYWxlLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBkM19zY2FsZV9saW5lYXIoZG9tYWluLCByYW5nZSwgaW50ZXJwb2xhdGUsIGNsYW1wKTtcbiAgICB9O1xuICAgIHJldHVybiByZXNjYWxlKCk7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2NhbGVfbGluZWFyUmViaW5kKHNjYWxlLCBsaW5lYXIpIHtcbiAgICByZXR1cm4gZDMucmViaW5kKHNjYWxlLCBsaW5lYXIsIFwicmFuZ2VcIiwgXCJyYW5nZVJvdW5kXCIsIFwiaW50ZXJwb2xhdGVcIiwgXCJjbGFtcFwiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zY2FsZV9saW5lYXJOaWNlKGRvbWFpbiwgbSkge1xuICAgIGQzX3NjYWxlX25pY2UoZG9tYWluLCBkM19zY2FsZV9uaWNlU3RlcChkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZG9tYWluLCBtKVsyXSkpO1xuICAgIGQzX3NjYWxlX25pY2UoZG9tYWluLCBkM19zY2FsZV9uaWNlU3RlcChkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZG9tYWluLCBtKVsyXSkpO1xuICAgIHJldHVybiBkb21haW47XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2NhbGVfbGluZWFyVGlja1JhbmdlKGRvbWFpbiwgbSkge1xuICAgIGlmIChtID09IG51bGwpIG0gPSAxMDtcbiAgICB2YXIgZXh0ZW50ID0gZDNfc2NhbGVFeHRlbnQoZG9tYWluKSwgc3BhbiA9IGV4dGVudFsxXSAtIGV4dGVudFswXSwgc3RlcCA9IE1hdGgucG93KDEwLCBNYXRoLmZsb29yKE1hdGgubG9nKHNwYW4gLyBtKSAvIE1hdGguTE4xMCkpLCBlcnIgPSBtIC8gc3BhbiAqIHN0ZXA7XG4gICAgaWYgKGVyciA8PSAuMTUpIHN0ZXAgKj0gMTA7IGVsc2UgaWYgKGVyciA8PSAuMzUpIHN0ZXAgKj0gNTsgZWxzZSBpZiAoZXJyIDw9IC43NSkgc3RlcCAqPSAyO1xuICAgIGV4dGVudFswXSA9IE1hdGguY2VpbChleHRlbnRbMF0gLyBzdGVwKSAqIHN0ZXA7XG4gICAgZXh0ZW50WzFdID0gTWF0aC5mbG9vcihleHRlbnRbMV0gLyBzdGVwKSAqIHN0ZXAgKyBzdGVwICogLjU7XG4gICAgZXh0ZW50WzJdID0gc3RlcDtcbiAgICByZXR1cm4gZXh0ZW50O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX2xpbmVhclRpY2tzKGRvbWFpbiwgbSkge1xuICAgIHJldHVybiBkMy5yYW5nZS5hcHBseShkMywgZDNfc2NhbGVfbGluZWFyVGlja1JhbmdlKGRvbWFpbiwgbSkpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX2xpbmVhclRpY2tGb3JtYXQoZG9tYWluLCBtLCBmb3JtYXQpIHtcbiAgICB2YXIgcmFuZ2UgPSBkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZG9tYWluLCBtKTtcbiAgICBpZiAoZm9ybWF0KSB7XG4gICAgICB2YXIgbWF0Y2ggPSBkM19mb3JtYXRfcmUuZXhlYyhmb3JtYXQpO1xuICAgICAgbWF0Y2guc2hpZnQoKTtcbiAgICAgIGlmIChtYXRjaFs4XSA9PT0gXCJzXCIpIHtcbiAgICAgICAgdmFyIHByZWZpeCA9IGQzLmZvcm1hdFByZWZpeChNYXRoLm1heChhYnMocmFuZ2VbMF0pLCBhYnMocmFuZ2VbMV0pKSk7XG4gICAgICAgIGlmICghbWF0Y2hbN10pIG1hdGNoWzddID0gXCIuXCIgKyBkM19zY2FsZV9saW5lYXJQcmVjaXNpb24ocHJlZml4LnNjYWxlKHJhbmdlWzJdKSk7XG4gICAgICAgIG1hdGNoWzhdID0gXCJmXCI7XG4gICAgICAgIGZvcm1hdCA9IGQzLmZvcm1hdChtYXRjaC5qb2luKFwiXCIpKTtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICByZXR1cm4gZm9ybWF0KHByZWZpeC5zY2FsZShkKSkgKyBwcmVmaXguc3ltYm9sO1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgaWYgKCFtYXRjaFs3XSkgbWF0Y2hbN10gPSBcIi5cIiArIGQzX3NjYWxlX2xpbmVhckZvcm1hdFByZWNpc2lvbihtYXRjaFs4XSwgcmFuZ2UpO1xuICAgICAgZm9ybWF0ID0gbWF0Y2guam9pbihcIlwiKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9ybWF0ID0gXCIsLlwiICsgZDNfc2NhbGVfbGluZWFyUHJlY2lzaW9uKHJhbmdlWzJdKSArIFwiZlwiO1xuICAgIH1cbiAgICByZXR1cm4gZDMuZm9ybWF0KGZvcm1hdCk7XG4gIH1cbiAgdmFyIGQzX3NjYWxlX2xpbmVhckZvcm1hdFNpZ25pZmljYW50ID0ge1xuICAgIHM6IDEsXG4gICAgZzogMSxcbiAgICBwOiAxLFxuICAgIHI6IDEsXG4gICAgZTogMVxuICB9O1xuICBmdW5jdGlvbiBkM19zY2FsZV9saW5lYXJQcmVjaXNpb24odmFsdWUpIHtcbiAgICByZXR1cm4gLU1hdGguZmxvb3IoTWF0aC5sb2codmFsdWUpIC8gTWF0aC5MTjEwICsgLjAxKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zY2FsZV9saW5lYXJGb3JtYXRQcmVjaXNpb24odHlwZSwgcmFuZ2UpIHtcbiAgICB2YXIgcCA9IGQzX3NjYWxlX2xpbmVhclByZWNpc2lvbihyYW5nZVsyXSk7XG4gICAgcmV0dXJuIHR5cGUgaW4gZDNfc2NhbGVfbGluZWFyRm9ybWF0U2lnbmlmaWNhbnQgPyBNYXRoLmFicyhwIC0gZDNfc2NhbGVfbGluZWFyUHJlY2lzaW9uKE1hdGgubWF4KGFicyhyYW5nZVswXSksIGFicyhyYW5nZVsxXSkpKSkgKyArKHR5cGUgIT09IFwiZVwiKSA6IHAgLSAodHlwZSA9PT0gXCIlXCIpICogMjtcbiAgfVxuICBkMy5zY2FsZS5sb2cgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfc2NhbGVfbG9nKGQzLnNjYWxlLmxpbmVhcigpLmRvbWFpbihbIDAsIDEgXSksIDEwLCB0cnVlLCBbIDEsIDEwIF0pO1xuICB9O1xuICBmdW5jdGlvbiBkM19zY2FsZV9sb2cobGluZWFyLCBiYXNlLCBwb3NpdGl2ZSwgZG9tYWluKSB7XG4gICAgZnVuY3Rpb24gbG9nKHgpIHtcbiAgICAgIHJldHVybiAocG9zaXRpdmUgPyBNYXRoLmxvZyh4IDwgMCA/IDAgOiB4KSA6IC1NYXRoLmxvZyh4ID4gMCA/IDAgOiAteCkpIC8gTWF0aC5sb2coYmFzZSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHBvdyh4KSB7XG4gICAgICByZXR1cm4gcG9zaXRpdmUgPyBNYXRoLnBvdyhiYXNlLCB4KSA6IC1NYXRoLnBvdyhiYXNlLCAteCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNjYWxlKHgpIHtcbiAgICAgIHJldHVybiBsaW5lYXIobG9nKHgpKTtcbiAgICB9XG4gICAgc2NhbGUuaW52ZXJ0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHBvdyhsaW5lYXIuaW52ZXJ0KHgpKTtcbiAgICB9O1xuICAgIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRvbWFpbjtcbiAgICAgIHBvc2l0aXZlID0geFswXSA+PSAwO1xuICAgICAgbGluZWFyLmRvbWFpbigoZG9tYWluID0geC5tYXAoTnVtYmVyKSkubWFwKGxvZykpO1xuICAgICAgcmV0dXJuIHNjYWxlO1xuICAgIH07XG4gICAgc2NhbGUuYmFzZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGJhc2U7XG4gICAgICBiYXNlID0gK187XG4gICAgICBsaW5lYXIuZG9tYWluKGRvbWFpbi5tYXAobG9nKSk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBzY2FsZS5uaWNlID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbmljZWQgPSBkM19zY2FsZV9uaWNlKGRvbWFpbi5tYXAobG9nKSwgcG9zaXRpdmUgPyBNYXRoIDogZDNfc2NhbGVfbG9nTmljZU5lZ2F0aXZlKTtcbiAgICAgIGxpbmVhci5kb21haW4obmljZWQpO1xuICAgICAgZG9tYWluID0gbmljZWQubWFwKHBvdyk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBzY2FsZS50aWNrcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGV4dGVudCA9IGQzX3NjYWxlRXh0ZW50KGRvbWFpbiksIHRpY2tzID0gW10sIHUgPSBleHRlbnRbMF0sIHYgPSBleHRlbnRbMV0sIGkgPSBNYXRoLmZsb29yKGxvZyh1KSksIGogPSBNYXRoLmNlaWwobG9nKHYpKSwgbiA9IGJhc2UgJSAxID8gMiA6IGJhc2U7XG4gICAgICBpZiAoaXNGaW5pdGUoaiAtIGkpKSB7XG4gICAgICAgIGlmIChwb3NpdGl2ZSkge1xuICAgICAgICAgIGZvciAoO2kgPCBqOyBpKyspIGZvciAodmFyIGsgPSAxOyBrIDwgbjsgaysrKSB0aWNrcy5wdXNoKHBvdyhpKSAqIGspO1xuICAgICAgICAgIHRpY2tzLnB1c2gocG93KGkpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aWNrcy5wdXNoKHBvdyhpKSk7XG4gICAgICAgICAgZm9yICg7aSsrIDwgajsgKSBmb3IgKHZhciBrID0gbiAtIDE7IGsgPiAwOyBrLS0pIHRpY2tzLnB1c2gocG93KGkpICogayk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgdGlja3NbaV0gPCB1OyBpKyspIHt9XG4gICAgICAgIGZvciAoaiA9IHRpY2tzLmxlbmd0aDsgdGlja3NbaiAtIDFdID4gdjsgai0tKSB7fVxuICAgICAgICB0aWNrcyA9IHRpY2tzLnNsaWNlKGksIGopO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRpY2tzO1xuICAgIH07XG4gICAgc2NhbGUudGlja0Zvcm1hdCA9IGZ1bmN0aW9uKG4sIGZvcm1hdCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZDNfc2NhbGVfbG9nRm9ybWF0O1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSBmb3JtYXQgPSBkM19zY2FsZV9sb2dGb3JtYXQ7IGVsc2UgaWYgKHR5cGVvZiBmb3JtYXQgIT09IFwiZnVuY3Rpb25cIikgZm9ybWF0ID0gZDMuZm9ybWF0KGZvcm1hdCk7XG4gICAgICB2YXIgayA9IE1hdGgubWF4KDEsIGJhc2UgKiBuIC8gc2NhbGUudGlja3MoKS5sZW5ndGgpO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGkgPSBkIC8gcG93KE1hdGgucm91bmQobG9nKGQpKSk7XG4gICAgICAgIGlmIChpICogYmFzZSA8IGJhc2UgLSAuNSkgaSAqPSBiYXNlO1xuICAgICAgICByZXR1cm4gaSA8PSBrID8gZm9ybWF0KGQpIDogXCJcIjtcbiAgICAgIH07XG4gICAgfTtcbiAgICBzY2FsZS5jb3B5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2NhbGVfbG9nKGxpbmVhci5jb3B5KCksIGJhc2UsIHBvc2l0aXZlLCBkb21haW4pO1xuICAgIH07XG4gICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclJlYmluZChzY2FsZSwgbGluZWFyKTtcbiAgfVxuICB2YXIgZDNfc2NhbGVfbG9nRm9ybWF0ID0gZDMuZm9ybWF0KFwiLjBlXCIpLCBkM19zY2FsZV9sb2dOaWNlTmVnYXRpdmUgPSB7XG4gICAgZmxvb3I6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiAtTWF0aC5jZWlsKC14KTtcbiAgICB9LFxuICAgIGNlaWw6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiAtTWF0aC5mbG9vcigteCk7XG4gICAgfVxuICB9O1xuICBkMy5zY2FsZS5wb3cgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfc2NhbGVfcG93KGQzLnNjYWxlLmxpbmVhcigpLCAxLCBbIDAsIDEgXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX3BvdyhsaW5lYXIsIGV4cG9uZW50LCBkb21haW4pIHtcbiAgICB2YXIgcG93cCA9IGQzX3NjYWxlX3Bvd1BvdyhleHBvbmVudCksIHBvd2IgPSBkM19zY2FsZV9wb3dQb3coMSAvIGV4cG9uZW50KTtcbiAgICBmdW5jdGlvbiBzY2FsZSh4KSB7XG4gICAgICByZXR1cm4gbGluZWFyKHBvd3AoeCkpO1xuICAgIH1cbiAgICBzY2FsZS5pbnZlcnQgPSBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gcG93YihsaW5lYXIuaW52ZXJ0KHgpKTtcbiAgICB9O1xuICAgIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRvbWFpbjtcbiAgICAgIGxpbmVhci5kb21haW4oKGRvbWFpbiA9IHgubWFwKE51bWJlcikpLm1hcChwb3dwKSk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBzY2FsZS50aWNrcyA9IGZ1bmN0aW9uKG0pIHtcbiAgICAgIHJldHVybiBkM19zY2FsZV9saW5lYXJUaWNrcyhkb21haW4sIG0pO1xuICAgIH07XG4gICAgc2NhbGUudGlja0Zvcm1hdCA9IGZ1bmN0aW9uKG0sIGZvcm1hdCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclRpY2tGb3JtYXQoZG9tYWluLCBtLCBmb3JtYXQpO1xuICAgIH07XG4gICAgc2NhbGUubmljZSA9IGZ1bmN0aW9uKG0pIHtcbiAgICAgIHJldHVybiBzY2FsZS5kb21haW4oZDNfc2NhbGVfbGluZWFyTmljZShkb21haW4sIG0pKTtcbiAgICB9O1xuICAgIHNjYWxlLmV4cG9uZW50ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZXhwb25lbnQ7XG4gICAgICBwb3dwID0gZDNfc2NhbGVfcG93UG93KGV4cG9uZW50ID0geCk7XG4gICAgICBwb3diID0gZDNfc2NhbGVfcG93UG93KDEgLyBleHBvbmVudCk7XG4gICAgICBsaW5lYXIuZG9tYWluKGRvbWFpbi5tYXAocG93cCkpO1xuICAgICAgcmV0dXJuIHNjYWxlO1xuICAgIH07XG4gICAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX3BvdyhsaW5lYXIuY29weSgpLCBleHBvbmVudCwgZG9tYWluKTtcbiAgICB9O1xuICAgIHJldHVybiBkM19zY2FsZV9saW5lYXJSZWJpbmQoc2NhbGUsIGxpbmVhcik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc2NhbGVfcG93UG93KGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHggPCAwID8gLU1hdGgucG93KC14LCBlKSA6IE1hdGgucG93KHgsIGUpO1xuICAgIH07XG4gIH1cbiAgZDMuc2NhbGUuc3FydCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkMy5zY2FsZS5wb3coKS5leHBvbmVudCguNSk7XG4gIH07XG4gIGQzLnNjYWxlLm9yZGluYWwgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfc2NhbGVfb3JkaW5hbChbXSwge1xuICAgICAgdDogXCJyYW5nZVwiLFxuICAgICAgYTogWyBbXSBdXG4gICAgfSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX29yZGluYWwoZG9tYWluLCByYW5nZXIpIHtcbiAgICB2YXIgaW5kZXgsIHJhbmdlLCByYW5nZUJhbmQ7XG4gICAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgICAgcmV0dXJuIHJhbmdlWygoaW5kZXguZ2V0KHgpIHx8IChyYW5nZXIudCA9PT0gXCJyYW5nZVwiID8gaW5kZXguc2V0KHgsIGRvbWFpbi5wdXNoKHgpKSA6IE5hTikpIC0gMSkgJSByYW5nZS5sZW5ndGhdO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdGVwcyhzdGFydCwgc3RlcCkge1xuICAgICAgcmV0dXJuIGQzLnJhbmdlKGRvbWFpbi5sZW5ndGgpLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICAgIHJldHVybiBzdGFydCArIHN0ZXAgKiBpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRvbWFpbjtcbiAgICAgIGRvbWFpbiA9IFtdO1xuICAgICAgaW5kZXggPSBuZXcgZDNfTWFwKCk7XG4gICAgICB2YXIgaSA9IC0xLCBuID0geC5sZW5ndGgsIHhpO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmICghaW5kZXguaGFzKHhpID0geFtpXSkpIGluZGV4LnNldCh4aSwgZG9tYWluLnB1c2goeGkpKTtcbiAgICAgIHJldHVybiBzY2FsZVtyYW5nZXIudF0uYXBwbHkoc2NhbGUsIHJhbmdlci5hKTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmFuZ2U7XG4gICAgICByYW5nZSA9IHg7XG4gICAgICByYW5nZUJhbmQgPSAwO1xuICAgICAgcmFuZ2VyID0ge1xuICAgICAgICB0OiBcInJhbmdlXCIsXG4gICAgICAgIGE6IGFyZ3VtZW50c1xuICAgICAgfTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlUG9pbnRzID0gZnVuY3Rpb24oeCwgcGFkZGluZykge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSBwYWRkaW5nID0gMDtcbiAgICAgIHZhciBzdGFydCA9IHhbMF0sIHN0b3AgPSB4WzFdLCBzdGVwID0gZG9tYWluLmxlbmd0aCA8IDIgPyAoc3RhcnQgPSAoc3RhcnQgKyBzdG9wKSAvIDIsIFxuICAgICAgMCkgOiAoc3RvcCAtIHN0YXJ0KSAvIChkb21haW4ubGVuZ3RoIC0gMSArIHBhZGRpbmcpO1xuICAgICAgcmFuZ2UgPSBzdGVwcyhzdGFydCArIHN0ZXAgKiBwYWRkaW5nIC8gMiwgc3RlcCk7XG4gICAgICByYW5nZUJhbmQgPSAwO1xuICAgICAgcmFuZ2VyID0ge1xuICAgICAgICB0OiBcInJhbmdlUG9pbnRzXCIsXG4gICAgICAgIGE6IGFyZ3VtZW50c1xuICAgICAgfTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlUm91bmRQb2ludHMgPSBmdW5jdGlvbih4LCBwYWRkaW5nKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHBhZGRpbmcgPSAwO1xuICAgICAgdmFyIHN0YXJ0ID0geFswXSwgc3RvcCA9IHhbMV0sIHN0ZXAgPSBkb21haW4ubGVuZ3RoIDwgMiA/IChzdGFydCA9IHN0b3AgPSBNYXRoLnJvdW5kKChzdGFydCArIHN0b3ApIC8gMiksIFxuICAgICAgMCkgOiAoc3RvcCAtIHN0YXJ0KSAvIChkb21haW4ubGVuZ3RoIC0gMSArIHBhZGRpbmcpIHwgMDtcbiAgICAgIHJhbmdlID0gc3RlcHMoc3RhcnQgKyBNYXRoLnJvdW5kKHN0ZXAgKiBwYWRkaW5nIC8gMiArIChzdG9wIC0gc3RhcnQgLSAoZG9tYWluLmxlbmd0aCAtIDEgKyBwYWRkaW5nKSAqIHN0ZXApIC8gMiksIHN0ZXApO1xuICAgICAgcmFuZ2VCYW5kID0gMDtcbiAgICAgIHJhbmdlciA9IHtcbiAgICAgICAgdDogXCJyYW5nZVJvdW5kUG9pbnRzXCIsXG4gICAgICAgIGE6IGFyZ3VtZW50c1xuICAgICAgfTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlQmFuZHMgPSBmdW5jdGlvbih4LCBwYWRkaW5nLCBvdXRlclBhZGRpbmcpIHtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikgcGFkZGluZyA9IDA7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDMpIG91dGVyUGFkZGluZyA9IHBhZGRpbmc7XG4gICAgICB2YXIgcmV2ZXJzZSA9IHhbMV0gPCB4WzBdLCBzdGFydCA9IHhbcmV2ZXJzZSAtIDBdLCBzdG9wID0geFsxIC0gcmV2ZXJzZV0sIHN0ZXAgPSAoc3RvcCAtIHN0YXJ0KSAvIChkb21haW4ubGVuZ3RoIC0gcGFkZGluZyArIDIgKiBvdXRlclBhZGRpbmcpO1xuICAgICAgcmFuZ2UgPSBzdGVwcyhzdGFydCArIHN0ZXAgKiBvdXRlclBhZGRpbmcsIHN0ZXApO1xuICAgICAgaWYgKHJldmVyc2UpIHJhbmdlLnJldmVyc2UoKTtcbiAgICAgIHJhbmdlQmFuZCA9IHN0ZXAgKiAoMSAtIHBhZGRpbmcpO1xuICAgICAgcmFuZ2VyID0ge1xuICAgICAgICB0OiBcInJhbmdlQmFuZHNcIixcbiAgICAgICAgYTogYXJndW1lbnRzXG4gICAgICB9O1xuICAgICAgcmV0dXJuIHNjYWxlO1xuICAgIH07XG4gICAgc2NhbGUucmFuZ2VSb3VuZEJhbmRzID0gZnVuY3Rpb24oeCwgcGFkZGluZywgb3V0ZXJQYWRkaW5nKSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHBhZGRpbmcgPSAwO1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAzKSBvdXRlclBhZGRpbmcgPSBwYWRkaW5nO1xuICAgICAgdmFyIHJldmVyc2UgPSB4WzFdIDwgeFswXSwgc3RhcnQgPSB4W3JldmVyc2UgLSAwXSwgc3RvcCA9IHhbMSAtIHJldmVyc2VdLCBzdGVwID0gTWF0aC5mbG9vcigoc3RvcCAtIHN0YXJ0KSAvIChkb21haW4ubGVuZ3RoIC0gcGFkZGluZyArIDIgKiBvdXRlclBhZGRpbmcpKTtcbiAgICAgIHJhbmdlID0gc3RlcHMoc3RhcnQgKyBNYXRoLnJvdW5kKChzdG9wIC0gc3RhcnQgLSAoZG9tYWluLmxlbmd0aCAtIHBhZGRpbmcpICogc3RlcCkgLyAyKSwgc3RlcCk7XG4gICAgICBpZiAocmV2ZXJzZSkgcmFuZ2UucmV2ZXJzZSgpO1xuICAgICAgcmFuZ2VCYW5kID0gTWF0aC5yb3VuZChzdGVwICogKDEgLSBwYWRkaW5nKSk7XG4gICAgICByYW5nZXIgPSB7XG4gICAgICAgIHQ6IFwicmFuZ2VSb3VuZEJhbmRzXCIsXG4gICAgICAgIGE6IGFyZ3VtZW50c1xuICAgICAgfTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlQmFuZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHJhbmdlQmFuZDtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlRXh0ZW50ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2NhbGVFeHRlbnQocmFuZ2VyLmFbMF0pO1xuICAgIH07XG4gICAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX29yZGluYWwoZG9tYWluLCByYW5nZXIpO1xuICAgIH07XG4gICAgcmV0dXJuIHNjYWxlLmRvbWFpbihkb21haW4pO1xuICB9XG4gIGQzLnNjYWxlLmNhdGVnb3J5MTAgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDMuc2NhbGUub3JkaW5hbCgpLnJhbmdlKGQzX2NhdGVnb3J5MTApO1xuICB9O1xuICBkMy5zY2FsZS5jYXRlZ29yeTIwID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzLnNjYWxlLm9yZGluYWwoKS5yYW5nZShkM19jYXRlZ29yeTIwKTtcbiAgfTtcbiAgZDMuc2NhbGUuY2F0ZWdvcnkyMGIgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDMuc2NhbGUub3JkaW5hbCgpLnJhbmdlKGQzX2NhdGVnb3J5MjBiKTtcbiAgfTtcbiAgZDMuc2NhbGUuY2F0ZWdvcnkyMGMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDMuc2NhbGUub3JkaW5hbCgpLnJhbmdlKGQzX2NhdGVnb3J5MjBjKTtcbiAgfTtcbiAgdmFyIGQzX2NhdGVnb3J5MTAgPSBbIDIwNjIyNjAsIDE2NzQ0MjA2LCAyOTI0NTg4LCAxNDAzNDcyOCwgOTcyNTg4NSwgOTE5NzEzMSwgMTQ5MDczMzAsIDgzNTU3MTEsIDEyMzY5MTg2LCAxNTU2MTc1IF0ubWFwKGQzX3JnYlN0cmluZyk7XG4gIHZhciBkM19jYXRlZ29yeTIwID0gWyAyMDYyMjYwLCAxMTQ1NDQ0MCwgMTY3NDQyMDYsIDE2NzU5NjcyLCAyOTI0NTg4LCAxMDAxODY5OCwgMTQwMzQ3MjgsIDE2NzUwNzQyLCA5NzI1ODg1LCAxMjk1NTg2MSwgOTE5NzEzMSwgMTI4ODUxNDAsIDE0OTA3MzMwLCAxNjIzNDE5NCwgODM1NTcxMSwgMTMwOTI4MDcsIDEyMzY5MTg2LCAxNDQwODU4OSwgMTU1NjE3NSwgMTA0MTA3MjUgXS5tYXAoZDNfcmdiU3RyaW5nKTtcbiAgdmFyIGQzX2NhdGVnb3J5MjBiID0gWyAzNzUwNzc3LCA1Mzk1NjE5LCA3MDQwNzE5LCAxMDI2NDI4NiwgNjUxOTA5NywgOTIxNjU5NCwgMTE5MTUxMTUsIDEzNTU2NjM2LCA5MjAyOTkzLCAxMjQyNjgwOSwgMTUxODY1MTQsIDE1MTkwOTMyLCA4NjY2MTY5LCAxMTM1NjQ5MCwgMTQwNDk2NDMsIDE1MTc3MzcyLCA4MDc3NjgzLCAxMDgzNDMyNCwgMTM1Mjg1MDksIDE0NTg5NjU0IF0ubWFwKGQzX3JnYlN0cmluZyk7XG4gIHZhciBkM19jYXRlZ29yeTIwYyA9IFsgMzI0NDczMywgNzA1NzExMCwgMTA0MDY2MjUsIDEzMDMyNDMxLCAxNTA5NTA1MywgMTY2MTY3NjQsIDE2NjI1MjU5LCAxNjYzNDAxOCwgMzI1MzA3NiwgNzY1MjQ3MCwgMTA2MDcwMDMsIDEzMTAxNTA0LCA3Njk1MjgxLCAxMDM5NDMxMiwgMTIzNjkzNzIsIDE0MzQyODkxLCA2NTEzNTA3LCA5ODY4OTUwLCAxMjQzNDg3NywgMTQyNzcwODEgXS5tYXAoZDNfcmdiU3RyaW5nKTtcbiAgZDMuc2NhbGUucXVhbnRpbGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfc2NhbGVfcXVhbnRpbGUoW10sIFtdKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc2NhbGVfcXVhbnRpbGUoZG9tYWluLCByYW5nZSkge1xuICAgIHZhciB0aHJlc2hvbGRzO1xuICAgIGZ1bmN0aW9uIHJlc2NhbGUoKSB7XG4gICAgICB2YXIgayA9IDAsIHEgPSByYW5nZS5sZW5ndGg7XG4gICAgICB0aHJlc2hvbGRzID0gW107XG4gICAgICB3aGlsZSAoKytrIDwgcSkgdGhyZXNob2xkc1trIC0gMV0gPSBkMy5xdWFudGlsZShkb21haW4sIGsgLyBxKTtcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgICAgaWYgKCFpc05hTih4ID0gK3gpKSByZXR1cm4gcmFuZ2VbZDMuYmlzZWN0KHRocmVzaG9sZHMsIHgpXTtcbiAgICB9XG4gICAgc2NhbGUuZG9tYWluID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZG9tYWluO1xuICAgICAgZG9tYWluID0geC5tYXAoZDNfbnVtYmVyKS5maWx0ZXIoZDNfbnVtZXJpYykuc29ydChkM19hc2NlbmRpbmcpO1xuICAgICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmFuZ2U7XG4gICAgICByYW5nZSA9IHg7XG4gICAgICByZXR1cm4gcmVzY2FsZSgpO1xuICAgIH07XG4gICAgc2NhbGUucXVhbnRpbGVzID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhyZXNob2xkcztcbiAgICB9O1xuICAgIHNjYWxlLmludmVydEV4dGVudCA9IGZ1bmN0aW9uKHkpIHtcbiAgICAgIHkgPSByYW5nZS5pbmRleE9mKHkpO1xuICAgICAgcmV0dXJuIHkgPCAwID8gWyBOYU4sIE5hTiBdIDogWyB5ID4gMCA/IHRocmVzaG9sZHNbeSAtIDFdIDogZG9tYWluWzBdLCB5IDwgdGhyZXNob2xkcy5sZW5ndGggPyB0aHJlc2hvbGRzW3ldIDogZG9tYWluW2RvbWFpbi5sZW5ndGggLSAxXSBdO1xuICAgIH07XG4gICAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX3F1YW50aWxlKGRvbWFpbiwgcmFuZ2UpO1xuICAgIH07XG4gICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgfVxuICBkMy5zY2FsZS5xdWFudGl6ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zY2FsZV9xdWFudGl6ZSgwLCAxLCBbIDAsIDEgXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX3F1YW50aXplKHgwLCB4MSwgcmFuZ2UpIHtcbiAgICB2YXIga3gsIGk7XG4gICAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgICAgcmV0dXJuIHJhbmdlW01hdGgubWF4KDAsIE1hdGgubWluKGksIE1hdGguZmxvb3Ioa3ggKiAoeCAtIHgwKSkpKV07XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc2NhbGUoKSB7XG4gICAgICBreCA9IHJhbmdlLmxlbmd0aCAvICh4MSAtIHgwKTtcbiAgICAgIGkgPSByYW5nZS5sZW5ndGggLSAxO1xuICAgICAgcmV0dXJuIHNjYWxlO1xuICAgIH1cbiAgICBzY2FsZS5kb21haW4gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBbIHgwLCB4MSBdO1xuICAgICAgeDAgPSAreFswXTtcbiAgICAgIHgxID0gK3hbeC5sZW5ndGggLSAxXTtcbiAgICAgIHJldHVybiByZXNjYWxlKCk7XG4gICAgfTtcbiAgICBzY2FsZS5yYW5nZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHJhbmdlO1xuICAgICAgcmFuZ2UgPSB4O1xuICAgICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgICB9O1xuICAgIHNjYWxlLmludmVydEV4dGVudCA9IGZ1bmN0aW9uKHkpIHtcbiAgICAgIHkgPSByYW5nZS5pbmRleE9mKHkpO1xuICAgICAgeSA9IHkgPCAwID8gTmFOIDogeSAvIGt4ICsgeDA7XG4gICAgICByZXR1cm4gWyB5LCB5ICsgMSAvIGt4IF07XG4gICAgfTtcbiAgICBzY2FsZS5jb3B5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfc2NhbGVfcXVhbnRpemUoeDAsIHgxLCByYW5nZSk7XG4gICAgfTtcbiAgICByZXR1cm4gcmVzY2FsZSgpO1xuICB9XG4gIGQzLnNjYWxlLnRocmVzaG9sZCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zY2FsZV90aHJlc2hvbGQoWyAuNSBdLCBbIDAsIDEgXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX3RocmVzaG9sZChkb21haW4sIHJhbmdlKSB7XG4gICAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgICAgaWYgKHggPD0geCkgcmV0dXJuIHJhbmdlW2QzLmJpc2VjdChkb21haW4sIHgpXTtcbiAgICB9XG4gICAgc2NhbGUuZG9tYWluID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZG9tYWluO1xuICAgICAgZG9tYWluID0gXztcbiAgICAgIHJldHVybiBzY2FsZTtcbiAgICB9O1xuICAgIHNjYWxlLnJhbmdlID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmFuZ2U7XG4gICAgICByYW5nZSA9IF87XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBzY2FsZS5pbnZlcnRFeHRlbnQgPSBmdW5jdGlvbih5KSB7XG4gICAgICB5ID0gcmFuZ2UuaW5kZXhPZih5KTtcbiAgICAgIHJldHVybiBbIGRvbWFpblt5IC0gMV0sIGRvbWFpblt5XSBdO1xuICAgIH07XG4gICAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX3RocmVzaG9sZChkb21haW4sIHJhbmdlKTtcbiAgICB9O1xuICAgIHJldHVybiBzY2FsZTtcbiAgfVxuICBkMy5zY2FsZS5pZGVudGl0eSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zY2FsZV9pZGVudGl0eShbIDAsIDEgXSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3NjYWxlX2lkZW50aXR5KGRvbWFpbikge1xuICAgIGZ1bmN0aW9uIGlkZW50aXR5KHgpIHtcbiAgICAgIHJldHVybiAreDtcbiAgICB9XG4gICAgaWRlbnRpdHkuaW52ZXJ0ID0gaWRlbnRpdHk7XG4gICAgaWRlbnRpdHkuZG9tYWluID0gaWRlbnRpdHkucmFuZ2UgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBkb21haW47XG4gICAgICBkb21haW4gPSB4Lm1hcChpZGVudGl0eSk7XG4gICAgICByZXR1cm4gaWRlbnRpdHk7XG4gICAgfTtcbiAgICBpZGVudGl0eS50aWNrcyA9IGZ1bmN0aW9uKG0pIHtcbiAgICAgIHJldHVybiBkM19zY2FsZV9saW5lYXJUaWNrcyhkb21haW4sIG0pO1xuICAgIH07XG4gICAgaWRlbnRpdHkudGlja0Zvcm1hdCA9IGZ1bmN0aW9uKG0sIGZvcm1hdCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclRpY2tGb3JtYXQoZG9tYWluLCBtLCBmb3JtYXQpO1xuICAgIH07XG4gICAgaWRlbnRpdHkuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGQzX3NjYWxlX2lkZW50aXR5KGRvbWFpbik7XG4gICAgfTtcbiAgICByZXR1cm4gaWRlbnRpdHk7XG4gIH1cbiAgZDMuc3ZnID0ge307XG4gIGZ1bmN0aW9uIGQzX3plcm8oKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgZDMuc3ZnLmFyYyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpbm5lclJhZGl1cyA9IGQzX3N2Z19hcmNJbm5lclJhZGl1cywgb3V0ZXJSYWRpdXMgPSBkM19zdmdfYXJjT3V0ZXJSYWRpdXMsIGNvcm5lclJhZGl1cyA9IGQzX3plcm8sIHBhZFJhZGl1cyA9IGQzX3N2Z19hcmNBdXRvLCBzdGFydEFuZ2xlID0gZDNfc3ZnX2FyY1N0YXJ0QW5nbGUsIGVuZEFuZ2xlID0gZDNfc3ZnX2FyY0VuZEFuZ2xlLCBwYWRBbmdsZSA9IGQzX3N2Z19hcmNQYWRBbmdsZTtcbiAgICBmdW5jdGlvbiBhcmMoKSB7XG4gICAgICB2YXIgcjAgPSBNYXRoLm1heCgwLCAraW5uZXJSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSksIHIxID0gTWF0aC5tYXgoMCwgK291dGVyUmFkaXVzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpLCBhMCA9IHN0YXJ0QW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSAtIGhhbGbPgCwgYTEgPSBlbmRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIC0gaGFsZs+ALCBkYSA9IE1hdGguYWJzKGExIC0gYTApLCBjdyA9IGEwID4gYTEgPyAwIDogMTtcbiAgICAgIGlmIChyMSA8IHIwKSByYyA9IHIxLCByMSA9IHIwLCByMCA9IHJjO1xuICAgICAgaWYgKGRhID49IM+EzrUpIHJldHVybiBjaXJjbGVTZWdtZW50KHIxLCBjdykgKyAocjAgPyBjaXJjbGVTZWdtZW50KHIwLCAxIC0gY3cpIDogXCJcIikgKyBcIlpcIjtcbiAgICAgIHZhciByYywgY3IsIHJwLCBhcCwgcDAgPSAwLCBwMSA9IDAsIHgwLCB5MCwgeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgcGF0aCA9IFtdO1xuICAgICAgaWYgKGFwID0gKCtwYWRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IDApIC8gMikge1xuICAgICAgICBycCA9IHBhZFJhZGl1cyA9PT0gZDNfc3ZnX2FyY0F1dG8gPyBNYXRoLnNxcnQocjAgKiByMCArIHIxICogcjEpIDogK3BhZFJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICBpZiAoIWN3KSBwMSAqPSAtMTtcbiAgICAgICAgaWYgKHIxKSBwMSA9IGQzX2FzaW4ocnAgLyByMSAqIE1hdGguc2luKGFwKSk7XG4gICAgICAgIGlmIChyMCkgcDAgPSBkM19hc2luKHJwIC8gcjAgKiBNYXRoLnNpbihhcCkpO1xuICAgICAgfVxuICAgICAgaWYgKHIxKSB7XG4gICAgICAgIHgwID0gcjEgKiBNYXRoLmNvcyhhMCArIHAxKTtcbiAgICAgICAgeTAgPSByMSAqIE1hdGguc2luKGEwICsgcDEpO1xuICAgICAgICB4MSA9IHIxICogTWF0aC5jb3MoYTEgLSBwMSk7XG4gICAgICAgIHkxID0gcjEgKiBNYXRoLnNpbihhMSAtIHAxKTtcbiAgICAgICAgdmFyIGwxID0gTWF0aC5hYnMoYTEgLSBhMCAtIDIgKiBwMSkgPD0gz4AgPyAwIDogMTtcbiAgICAgICAgaWYgKHAxICYmIGQzX3N2Z19hcmNTd2VlcCh4MCwgeTAsIHgxLCB5MSkgPT09IGN3IF4gbDEpIHtcbiAgICAgICAgICB2YXIgaDEgPSAoYTAgKyBhMSkgLyAyO1xuICAgICAgICAgIHgwID0gcjEgKiBNYXRoLmNvcyhoMSk7XG4gICAgICAgICAgeTAgPSByMSAqIE1hdGguc2luKGgxKTtcbiAgICAgICAgICB4MSA9IHkxID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeDAgPSB5MCA9IDA7XG4gICAgICB9XG4gICAgICBpZiAocjApIHtcbiAgICAgICAgeDIgPSByMCAqIE1hdGguY29zKGExIC0gcDApO1xuICAgICAgICB5MiA9IHIwICogTWF0aC5zaW4oYTEgLSBwMCk7XG4gICAgICAgIHgzID0gcjAgKiBNYXRoLmNvcyhhMCArIHAwKTtcbiAgICAgICAgeTMgPSByMCAqIE1hdGguc2luKGEwICsgcDApO1xuICAgICAgICB2YXIgbDAgPSBNYXRoLmFicyhhMCAtIGExICsgMiAqIHAwKSA8PSDPgCA/IDAgOiAxO1xuICAgICAgICBpZiAocDAgJiYgZDNfc3ZnX2FyY1N3ZWVwKHgyLCB5MiwgeDMsIHkzKSA9PT0gMSAtIGN3IF4gbDApIHtcbiAgICAgICAgICB2YXIgaDAgPSAoYTAgKyBhMSkgLyAyO1xuICAgICAgICAgIHgyID0gcjAgKiBNYXRoLmNvcyhoMCk7XG4gICAgICAgICAgeTIgPSByMCAqIE1hdGguc2luKGgwKTtcbiAgICAgICAgICB4MyA9IHkzID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeDIgPSB5MiA9IDA7XG4gICAgICB9XG4gICAgICBpZiAoZGEgPiDOtSAmJiAocmMgPSBNYXRoLm1pbihNYXRoLmFicyhyMSAtIHIwKSAvIDIsICtjb3JuZXJSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSkpID4gLjAwMSkge1xuICAgICAgICBjciA9IHIwIDwgcjEgXiBjdyA/IDAgOiAxO1xuICAgICAgICB2YXIgcmMxID0gcmMsIHJjMCA9IHJjO1xuICAgICAgICBpZiAoZGEgPCDPgCkge1xuICAgICAgICAgIHZhciBvYyA9IHgzID09IG51bGwgPyBbIHgyLCB5MiBdIDogeDEgPT0gbnVsbCA/IFsgeDAsIHkwIF0gOiBkM19nZW9tX3BvbHlnb25JbnRlcnNlY3QoWyB4MCwgeTAgXSwgWyB4MywgeTMgXSwgWyB4MSwgeTEgXSwgWyB4MiwgeTIgXSksIGF4ID0geDAgLSBvY1swXSwgYXkgPSB5MCAtIG9jWzFdLCBieCA9IHgxIC0gb2NbMF0sIGJ5ID0geTEgLSBvY1sxXSwga2MgPSAxIC8gTWF0aC5zaW4oTWF0aC5hY29zKChheCAqIGJ4ICsgYXkgKiBieSkgLyAoTWF0aC5zcXJ0KGF4ICogYXggKyBheSAqIGF5KSAqIE1hdGguc3FydChieCAqIGJ4ICsgYnkgKiBieSkpKSAvIDIpLCBsYyA9IE1hdGguc3FydChvY1swXSAqIG9jWzBdICsgb2NbMV0gKiBvY1sxXSk7XG4gICAgICAgICAgcmMwID0gTWF0aC5taW4ocmMsIChyMCAtIGxjKSAvIChrYyAtIDEpKTtcbiAgICAgICAgICByYzEgPSBNYXRoLm1pbihyYywgKHIxIC0gbGMpIC8gKGtjICsgMSkpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh4MSAhPSBudWxsKSB7XG4gICAgICAgICAgdmFyIHQzMCA9IGQzX3N2Z19hcmNDb3JuZXJUYW5nZW50cyh4MyA9PSBudWxsID8gWyB4MiwgeTIgXSA6IFsgeDMsIHkzIF0sIFsgeDAsIHkwIF0sIHIxLCByYzEsIGN3KSwgdDEyID0gZDNfc3ZnX2FyY0Nvcm5lclRhbmdlbnRzKFsgeDEsIHkxIF0sIFsgeDIsIHkyIF0sIHIxLCByYzEsIGN3KTtcbiAgICAgICAgICBpZiAocmMgPT09IHJjMSkge1xuICAgICAgICAgICAgcGF0aC5wdXNoKFwiTVwiLCB0MzBbMF0sIFwiQVwiLCByYzEsIFwiLFwiLCByYzEsIFwiIDAgMCxcIiwgY3IsIFwiIFwiLCB0MzBbMV0sIFwiQVwiLCByMSwgXCIsXCIsIHIxLCBcIiAwIFwiLCAxIC0gY3cgXiBkM19zdmdfYXJjU3dlZXAodDMwWzFdWzBdLCB0MzBbMV1bMV0sIHQxMlsxXVswXSwgdDEyWzFdWzFdKSwgXCIsXCIsIGN3LCBcIiBcIiwgdDEyWzFdLCBcIkFcIiwgcmMxLCBcIixcIiwgcmMxLCBcIiAwIDAsXCIsIGNyLCBcIiBcIiwgdDEyWzBdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGF0aC5wdXNoKFwiTVwiLCB0MzBbMF0sIFwiQVwiLCByYzEsIFwiLFwiLCByYzEsIFwiIDAgMSxcIiwgY3IsIFwiIFwiLCB0MTJbMF0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwYXRoLnB1c2goXCJNXCIsIHgwLCBcIixcIiwgeTApO1xuICAgICAgICB9XG4gICAgICAgIGlmICh4MyAhPSBudWxsKSB7XG4gICAgICAgICAgdmFyIHQwMyA9IGQzX3N2Z19hcmNDb3JuZXJUYW5nZW50cyhbIHgwLCB5MCBdLCBbIHgzLCB5MyBdLCByMCwgLXJjMCwgY3cpLCB0MjEgPSBkM19zdmdfYXJjQ29ybmVyVGFuZ2VudHMoWyB4MiwgeTIgXSwgeDEgPT0gbnVsbCA/IFsgeDAsIHkwIF0gOiBbIHgxLCB5MSBdLCByMCwgLXJjMCwgY3cpO1xuICAgICAgICAgIGlmIChyYyA9PT0gcmMwKSB7XG4gICAgICAgICAgICBwYXRoLnB1c2goXCJMXCIsIHQyMVswXSwgXCJBXCIsIHJjMCwgXCIsXCIsIHJjMCwgXCIgMCAwLFwiLCBjciwgXCIgXCIsIHQyMVsxXSwgXCJBXCIsIHIwLCBcIixcIiwgcjAsIFwiIDAgXCIsIGN3IF4gZDNfc3ZnX2FyY1N3ZWVwKHQyMVsxXVswXSwgdDIxWzFdWzFdLCB0MDNbMV1bMF0sIHQwM1sxXVsxXSksIFwiLFwiLCAxIC0gY3csIFwiIFwiLCB0MDNbMV0sIFwiQVwiLCByYzAsIFwiLFwiLCByYzAsIFwiIDAgMCxcIiwgY3IsIFwiIFwiLCB0MDNbMF0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwYXRoLnB1c2goXCJMXCIsIHQyMVswXSwgXCJBXCIsIHJjMCwgXCIsXCIsIHJjMCwgXCIgMCAwLFwiLCBjciwgXCIgXCIsIHQwM1swXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBhdGgucHVzaChcIkxcIiwgeDIsIFwiLFwiLCB5Mik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdGgucHVzaChcIk1cIiwgeDAsIFwiLFwiLCB5MCk7XG4gICAgICAgIGlmICh4MSAhPSBudWxsKSBwYXRoLnB1c2goXCJBXCIsIHIxLCBcIixcIiwgcjEsIFwiIDAgXCIsIGwxLCBcIixcIiwgY3csIFwiIFwiLCB4MSwgXCIsXCIsIHkxKTtcbiAgICAgICAgcGF0aC5wdXNoKFwiTFwiLCB4MiwgXCIsXCIsIHkyKTtcbiAgICAgICAgaWYgKHgzICE9IG51bGwpIHBhdGgucHVzaChcIkFcIiwgcjAsIFwiLFwiLCByMCwgXCIgMCBcIiwgbDAsIFwiLFwiLCAxIC0gY3csIFwiIFwiLCB4MywgXCIsXCIsIHkzKTtcbiAgICAgIH1cbiAgICAgIHBhdGgucHVzaChcIlpcIik7XG4gICAgICByZXR1cm4gcGF0aC5qb2luKFwiXCIpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjaXJjbGVTZWdtZW50KHIxLCBjdykge1xuICAgICAgcmV0dXJuIFwiTTAsXCIgKyByMSArIFwiQVwiICsgcjEgKyBcIixcIiArIHIxICsgXCIgMCAxLFwiICsgY3cgKyBcIiAwLFwiICsgLXIxICsgXCJBXCIgKyByMSArIFwiLFwiICsgcjEgKyBcIiAwIDEsXCIgKyBjdyArIFwiIDAsXCIgKyByMTtcbiAgICB9XG4gICAgYXJjLmlubmVyUmFkaXVzID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gaW5uZXJSYWRpdXM7XG4gICAgICBpbm5lclJhZGl1cyA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLm91dGVyUmFkaXVzID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gb3V0ZXJSYWRpdXM7XG4gICAgICBvdXRlclJhZGl1cyA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLmNvcm5lclJhZGl1cyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGNvcm5lclJhZGl1cztcbiAgICAgIGNvcm5lclJhZGl1cyA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLnBhZFJhZGl1cyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHBhZFJhZGl1cztcbiAgICAgIHBhZFJhZGl1cyA9IHYgPT0gZDNfc3ZnX2FyY0F1dG8gPyBkM19zdmdfYXJjQXV0byA6IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLnN0YXJ0QW5nbGUgPSBmdW5jdGlvbih2KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzdGFydEFuZ2xlO1xuICAgICAgc3RhcnRBbmdsZSA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLmVuZEFuZ2xlID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZW5kQW5nbGU7XG4gICAgICBlbmRBbmdsZSA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLnBhZEFuZ2xlID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcGFkQW5nbGU7XG4gICAgICBwYWRBbmdsZSA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gYXJjO1xuICAgIH07XG4gICAgYXJjLmNlbnRyb2lkID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgciA9ICgraW5uZXJSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICtvdXRlclJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSAvIDIsIGEgPSAoK3N0YXJ0QW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICtlbmRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSAvIDIgLSBoYWxmz4A7XG4gICAgICByZXR1cm4gWyBNYXRoLmNvcyhhKSAqIHIsIE1hdGguc2luKGEpICogciBdO1xuICAgIH07XG4gICAgcmV0dXJuIGFyYztcbiAgfTtcbiAgdmFyIGQzX3N2Z19hcmNBdXRvID0gXCJhdXRvXCI7XG4gIGZ1bmN0aW9uIGQzX3N2Z19hcmNJbm5lclJhZGl1cyhkKSB7XG4gICAgcmV0dXJuIGQuaW5uZXJSYWRpdXM7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX2FyY091dGVyUmFkaXVzKGQpIHtcbiAgICByZXR1cm4gZC5vdXRlclJhZGl1cztcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJjU3RhcnRBbmdsZShkKSB7XG4gICAgcmV0dXJuIGQuc3RhcnRBbmdsZTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJjRW5kQW5nbGUoZCkge1xuICAgIHJldHVybiBkLmVuZEFuZ2xlO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19hcmNQYWRBbmdsZShkKSB7XG4gICAgcmV0dXJuIGQgJiYgZC5wYWRBbmdsZTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJjU3dlZXAoeDAsIHkwLCB4MSwgeTEpIHtcbiAgICByZXR1cm4gKHgwIC0geDEpICogeTAgLSAoeTAgLSB5MSkgKiB4MCA+IDAgPyAwIDogMTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJjQ29ybmVyVGFuZ2VudHMocDAsIHAxLCByMSwgcmMsIGN3KSB7XG4gICAgdmFyIHgwMSA9IHAwWzBdIC0gcDFbMF0sIHkwMSA9IHAwWzFdIC0gcDFbMV0sIGxvID0gKGN3ID8gcmMgOiAtcmMpIC8gTWF0aC5zcXJ0KHgwMSAqIHgwMSArIHkwMSAqIHkwMSksIG94ID0gbG8gKiB5MDEsIG95ID0gLWxvICogeDAxLCB4MSA9IHAwWzBdICsgb3gsIHkxID0gcDBbMV0gKyBveSwgeDIgPSBwMVswXSArIG94LCB5MiA9IHAxWzFdICsgb3ksIHgzID0gKHgxICsgeDIpIC8gMiwgeTMgPSAoeTEgKyB5MikgLyAyLCBkeCA9IHgyIC0geDEsIGR5ID0geTIgLSB5MSwgZDIgPSBkeCAqIGR4ICsgZHkgKiBkeSwgciA9IHIxIC0gcmMsIEQgPSB4MSAqIHkyIC0geDIgKiB5MSwgZCA9IChkeSA8IDAgPyAtMSA6IDEpICogTWF0aC5zcXJ0KE1hdGgubWF4KDAsIHIgKiByICogZDIgLSBEICogRCkpLCBjeDAgPSAoRCAqIGR5IC0gZHggKiBkKSAvIGQyLCBjeTAgPSAoLUQgKiBkeCAtIGR5ICogZCkgLyBkMiwgY3gxID0gKEQgKiBkeSArIGR4ICogZCkgLyBkMiwgY3kxID0gKC1EICogZHggKyBkeSAqIGQpIC8gZDIsIGR4MCA9IGN4MCAtIHgzLCBkeTAgPSBjeTAgLSB5MywgZHgxID0gY3gxIC0geDMsIGR5MSA9IGN5MSAtIHkzO1xuICAgIGlmIChkeDAgKiBkeDAgKyBkeTAgKiBkeTAgPiBkeDEgKiBkeDEgKyBkeTEgKiBkeTEpIGN4MCA9IGN4MSwgY3kwID0gY3kxO1xuICAgIHJldHVybiBbIFsgY3gwIC0gb3gsIGN5MCAtIG95IF0sIFsgY3gwICogcjEgLyByLCBjeTAgKiByMSAvIHIgXSBdO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lKHByb2plY3Rpb24pIHtcbiAgICB2YXIgeCA9IGQzX2dlb21fcG9pbnRYLCB5ID0gZDNfZ2VvbV9wb2ludFksIGRlZmluZWQgPSBkM190cnVlLCBpbnRlcnBvbGF0ZSA9IGQzX3N2Z19saW5lTGluZWFyLCBpbnRlcnBvbGF0ZUtleSA9IGludGVycG9sYXRlLmtleSwgdGVuc2lvbiA9IC43O1xuICAgIGZ1bmN0aW9uIGxpbmUoZGF0YSkge1xuICAgICAgdmFyIHNlZ21lbnRzID0gW10sIHBvaW50cyA9IFtdLCBpID0gLTEsIG4gPSBkYXRhLmxlbmd0aCwgZCwgZnggPSBkM19mdW5jdG9yKHgpLCBmeSA9IGQzX2Z1bmN0b3IoeSk7XG4gICAgICBmdW5jdGlvbiBzZWdtZW50KCkge1xuICAgICAgICBzZWdtZW50cy5wdXNoKFwiTVwiLCBpbnRlcnBvbGF0ZShwcm9qZWN0aW9uKHBvaW50cyksIHRlbnNpb24pKTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIGlmIChkZWZpbmVkLmNhbGwodGhpcywgZCA9IGRhdGFbaV0sIGkpKSB7XG4gICAgICAgICAgcG9pbnRzLnB1c2goWyArZnguY2FsbCh0aGlzLCBkLCBpKSwgK2Z5LmNhbGwodGhpcywgZCwgaSkgXSk7XG4gICAgICAgIH0gZWxzZSBpZiAocG9pbnRzLmxlbmd0aCkge1xuICAgICAgICAgIHNlZ21lbnQoKTtcbiAgICAgICAgICBwb2ludHMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHBvaW50cy5sZW5ndGgpIHNlZ21lbnQoKTtcbiAgICAgIHJldHVybiBzZWdtZW50cy5sZW5ndGggPyBzZWdtZW50cy5qb2luKFwiXCIpIDogbnVsbDtcbiAgICB9XG4gICAgbGluZS54ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDtcbiAgICAgIHggPSBfO1xuICAgICAgcmV0dXJuIGxpbmU7XG4gICAgfTtcbiAgICBsaW5lLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB5O1xuICAgICAgeSA9IF87XG4gICAgICByZXR1cm4gbGluZTtcbiAgICB9O1xuICAgIGxpbmUuZGVmaW5lZCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRlZmluZWQ7XG4gICAgICBkZWZpbmVkID0gXztcbiAgICAgIHJldHVybiBsaW5lO1xuICAgIH07XG4gICAgbGluZS5pbnRlcnBvbGF0ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGludGVycG9sYXRlS2V5O1xuICAgICAgaWYgKHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIpIGludGVycG9sYXRlS2V5ID0gaW50ZXJwb2xhdGUgPSBfOyBlbHNlIGludGVycG9sYXRlS2V5ID0gKGludGVycG9sYXRlID0gZDNfc3ZnX2xpbmVJbnRlcnBvbGF0b3JzLmdldChfKSB8fCBkM19zdmdfbGluZUxpbmVhcikua2V5O1xuICAgICAgcmV0dXJuIGxpbmU7XG4gICAgfTtcbiAgICBsaW5lLnRlbnNpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB0ZW5zaW9uO1xuICAgICAgdGVuc2lvbiA9IF87XG4gICAgICByZXR1cm4gbGluZTtcbiAgICB9O1xuICAgIHJldHVybiBsaW5lO1xuICB9XG4gIGQzLnN2Zy5saW5lID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX3N2Z19saW5lKGQzX2lkZW50aXR5KTtcbiAgfTtcbiAgdmFyIGQzX3N2Z19saW5lSW50ZXJwb2xhdG9ycyA9IGQzLm1hcCh7XG4gICAgbGluZWFyOiBkM19zdmdfbGluZUxpbmVhcixcbiAgICBcImxpbmVhci1jbG9zZWRcIjogZDNfc3ZnX2xpbmVMaW5lYXJDbG9zZWQsXG4gICAgc3RlcDogZDNfc3ZnX2xpbmVTdGVwLFxuICAgIFwic3RlcC1iZWZvcmVcIjogZDNfc3ZnX2xpbmVTdGVwQmVmb3JlLFxuICAgIFwic3RlcC1hZnRlclwiOiBkM19zdmdfbGluZVN0ZXBBZnRlcixcbiAgICBiYXNpczogZDNfc3ZnX2xpbmVCYXNpcyxcbiAgICBcImJhc2lzLW9wZW5cIjogZDNfc3ZnX2xpbmVCYXNpc09wZW4sXG4gICAgXCJiYXNpcy1jbG9zZWRcIjogZDNfc3ZnX2xpbmVCYXNpc0Nsb3NlZCxcbiAgICBidW5kbGU6IGQzX3N2Z19saW5lQnVuZGxlLFxuICAgIGNhcmRpbmFsOiBkM19zdmdfbGluZUNhcmRpbmFsLFxuICAgIFwiY2FyZGluYWwtb3BlblwiOiBkM19zdmdfbGluZUNhcmRpbmFsT3BlbixcbiAgICBcImNhcmRpbmFsLWNsb3NlZFwiOiBkM19zdmdfbGluZUNhcmRpbmFsQ2xvc2VkLFxuICAgIG1vbm90b25lOiBkM19zdmdfbGluZU1vbm90b25lXG4gIH0pO1xuICBkM19zdmdfbGluZUludGVycG9sYXRvcnMuZm9yRWFjaChmdW5jdGlvbihrZXksIHZhbHVlKSB7XG4gICAgdmFsdWUua2V5ID0ga2V5O1xuICAgIHZhbHVlLmNsb3NlZCA9IC8tY2xvc2VkJC8udGVzdChrZXkpO1xuICB9KTtcbiAgZnVuY3Rpb24gZDNfc3ZnX2xpbmVMaW5lYXIocG9pbnRzKSB7XG4gICAgcmV0dXJuIHBvaW50cy5sZW5ndGggPiAxID8gcG9pbnRzLmpvaW4oXCJMXCIpIDogcG9pbnRzICsgXCJaXCI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX2xpbmVMaW5lYXJDbG9zZWQocG9pbnRzKSB7XG4gICAgcmV0dXJuIHBvaW50cy5qb2luKFwiTFwiKSArIFwiWlwiO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lU3RlcChwb2ludHMpIHtcbiAgICB2YXIgaSA9IDAsIG4gPSBwb2ludHMubGVuZ3RoLCBwID0gcG9pbnRzWzBdLCBwYXRoID0gWyBwWzBdLCBcIixcIiwgcFsxXSBdO1xuICAgIHdoaWxlICgrK2kgPCBuKSBwYXRoLnB1c2goXCJIXCIsIChwWzBdICsgKHAgPSBwb2ludHNbaV0pWzBdKSAvIDIsIFwiVlwiLCBwWzFdKTtcbiAgICBpZiAobiA+IDEpIHBhdGgucHVzaChcIkhcIiwgcFswXSk7XG4gICAgcmV0dXJuIHBhdGguam9pbihcIlwiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZVN0ZXBCZWZvcmUocG9pbnRzKSB7XG4gICAgdmFyIGkgPSAwLCBuID0gcG9pbnRzLmxlbmd0aCwgcCA9IHBvaW50c1swXSwgcGF0aCA9IFsgcFswXSwgXCIsXCIsIHBbMV0gXTtcbiAgICB3aGlsZSAoKytpIDwgbikgcGF0aC5wdXNoKFwiVlwiLCAocCA9IHBvaW50c1tpXSlbMV0sIFwiSFwiLCBwWzBdKTtcbiAgICByZXR1cm4gcGF0aC5qb2luKFwiXCIpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lU3RlcEFmdGVyKHBvaW50cykge1xuICAgIHZhciBpID0gMCwgbiA9IHBvaW50cy5sZW5ndGgsIHAgPSBwb2ludHNbMF0sIHBhdGggPSBbIHBbMF0sIFwiLFwiLCBwWzFdIF07XG4gICAgd2hpbGUgKCsraSA8IG4pIHBhdGgucHVzaChcIkhcIiwgKHAgPSBwb2ludHNbaV0pWzBdLCBcIlZcIiwgcFsxXSk7XG4gICAgcmV0dXJuIHBhdGguam9pbihcIlwiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUNhcmRpbmFsT3Blbihwb2ludHMsIHRlbnNpb24pIHtcbiAgICByZXR1cm4gcG9pbnRzLmxlbmd0aCA8IDQgPyBkM19zdmdfbGluZUxpbmVhcihwb2ludHMpIDogcG9pbnRzWzFdICsgZDNfc3ZnX2xpbmVIZXJtaXRlKHBvaW50cy5zbGljZSgxLCAtMSksIGQzX3N2Z19saW5lQ2FyZGluYWxUYW5nZW50cyhwb2ludHMsIHRlbnNpb24pKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUNhcmRpbmFsQ2xvc2VkKHBvaW50cywgdGVuc2lvbikge1xuICAgIHJldHVybiBwb2ludHMubGVuZ3RoIDwgMyA/IGQzX3N2Z19saW5lTGluZWFyQ2xvc2VkKHBvaW50cykgOiBwb2ludHNbMF0gKyBkM19zdmdfbGluZUhlcm1pdGUoKHBvaW50cy5wdXNoKHBvaW50c1swXSksIFxuICAgIHBvaW50cyksIGQzX3N2Z19saW5lQ2FyZGluYWxUYW5nZW50cyhbIHBvaW50c1twb2ludHMubGVuZ3RoIC0gMl0gXS5jb25jYXQocG9pbnRzLCBbIHBvaW50c1sxXSBdKSwgdGVuc2lvbikpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lQ2FyZGluYWwocG9pbnRzLCB0ZW5zaW9uKSB7XG4gICAgcmV0dXJuIHBvaW50cy5sZW5ndGggPCAzID8gZDNfc3ZnX2xpbmVMaW5lYXIocG9pbnRzKSA6IHBvaW50c1swXSArIGQzX3N2Z19saW5lSGVybWl0ZShwb2ludHMsIGQzX3N2Z19saW5lQ2FyZGluYWxUYW5nZW50cyhwb2ludHMsIHRlbnNpb24pKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUhlcm1pdGUocG9pbnRzLCB0YW5nZW50cykge1xuICAgIGlmICh0YW5nZW50cy5sZW5ndGggPCAxIHx8IHBvaW50cy5sZW5ndGggIT0gdGFuZ2VudHMubGVuZ3RoICYmIHBvaW50cy5sZW5ndGggIT0gdGFuZ2VudHMubGVuZ3RoICsgMikge1xuICAgICAgcmV0dXJuIGQzX3N2Z19saW5lTGluZWFyKHBvaW50cyk7XG4gICAgfVxuICAgIHZhciBxdWFkID0gcG9pbnRzLmxlbmd0aCAhPSB0YW5nZW50cy5sZW5ndGgsIHBhdGggPSBcIlwiLCBwMCA9IHBvaW50c1swXSwgcCA9IHBvaW50c1sxXSwgdDAgPSB0YW5nZW50c1swXSwgdCA9IHQwLCBwaSA9IDE7XG4gICAgaWYgKHF1YWQpIHtcbiAgICAgIHBhdGggKz0gXCJRXCIgKyAocFswXSAtIHQwWzBdICogMiAvIDMpICsgXCIsXCIgKyAocFsxXSAtIHQwWzFdICogMiAvIDMpICsgXCIsXCIgKyBwWzBdICsgXCIsXCIgKyBwWzFdO1xuICAgICAgcDAgPSBwb2ludHNbMV07XG4gICAgICBwaSA9IDI7XG4gICAgfVxuICAgIGlmICh0YW5nZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICB0ID0gdGFuZ2VudHNbMV07XG4gICAgICBwID0gcG9pbnRzW3BpXTtcbiAgICAgIHBpKys7XG4gICAgICBwYXRoICs9IFwiQ1wiICsgKHAwWzBdICsgdDBbMF0pICsgXCIsXCIgKyAocDBbMV0gKyB0MFsxXSkgKyBcIixcIiArIChwWzBdIC0gdFswXSkgKyBcIixcIiArIChwWzFdIC0gdFsxXSkgKyBcIixcIiArIHBbMF0gKyBcIixcIiArIHBbMV07XG4gICAgICBmb3IgKHZhciBpID0gMjsgaSA8IHRhbmdlbnRzLmxlbmd0aDsgaSsrLCBwaSsrKSB7XG4gICAgICAgIHAgPSBwb2ludHNbcGldO1xuICAgICAgICB0ID0gdGFuZ2VudHNbaV07XG4gICAgICAgIHBhdGggKz0gXCJTXCIgKyAocFswXSAtIHRbMF0pICsgXCIsXCIgKyAocFsxXSAtIHRbMV0pICsgXCIsXCIgKyBwWzBdICsgXCIsXCIgKyBwWzFdO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocXVhZCkge1xuICAgICAgdmFyIGxwID0gcG9pbnRzW3BpXTtcbiAgICAgIHBhdGggKz0gXCJRXCIgKyAocFswXSArIHRbMF0gKiAyIC8gMykgKyBcIixcIiArIChwWzFdICsgdFsxXSAqIDIgLyAzKSArIFwiLFwiICsgbHBbMF0gKyBcIixcIiArIGxwWzFdO1xuICAgIH1cbiAgICByZXR1cm4gcGF0aDtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUNhcmRpbmFsVGFuZ2VudHMocG9pbnRzLCB0ZW5zaW9uKSB7XG4gICAgdmFyIHRhbmdlbnRzID0gW10sIGEgPSAoMSAtIHRlbnNpb24pIC8gMiwgcDAsIHAxID0gcG9pbnRzWzBdLCBwMiA9IHBvaW50c1sxXSwgaSA9IDEsIG4gPSBwb2ludHMubGVuZ3RoO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBwMCA9IHAxO1xuICAgICAgcDEgPSBwMjtcbiAgICAgIHAyID0gcG9pbnRzW2ldO1xuICAgICAgdGFuZ2VudHMucHVzaChbIGEgKiAocDJbMF0gLSBwMFswXSksIGEgKiAocDJbMV0gLSBwMFsxXSkgXSk7XG4gICAgfVxuICAgIHJldHVybiB0YW5nZW50cztcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUJhc2lzKHBvaW50cykge1xuICAgIGlmIChwb2ludHMubGVuZ3RoIDwgMykgcmV0dXJuIGQzX3N2Z19saW5lTGluZWFyKHBvaW50cyk7XG4gICAgdmFyIGkgPSAxLCBuID0gcG9pbnRzLmxlbmd0aCwgcGkgPSBwb2ludHNbMF0sIHgwID0gcGlbMF0sIHkwID0gcGlbMV0sIHB4ID0gWyB4MCwgeDAsIHgwLCAocGkgPSBwb2ludHNbMV0pWzBdIF0sIHB5ID0gWyB5MCwgeTAsIHkwLCBwaVsxXSBdLCBwYXRoID0gWyB4MCwgXCIsXCIsIHkwLCBcIkxcIiwgZDNfc3ZnX2xpbmVEb3Q0KGQzX3N2Z19saW5lQmFzaXNCZXppZXIzLCBweCksIFwiLFwiLCBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjMsIHB5KSBdO1xuICAgIHBvaW50cy5wdXNoKHBvaW50c1tuIC0gMV0pO1xuICAgIHdoaWxlICgrK2kgPD0gbikge1xuICAgICAgcGkgPSBwb2ludHNbaV07XG4gICAgICBweC5zaGlmdCgpO1xuICAgICAgcHgucHVzaChwaVswXSk7XG4gICAgICBweS5zaGlmdCgpO1xuICAgICAgcHkucHVzaChwaVsxXSk7XG4gICAgICBkM19zdmdfbGluZUJhc2lzQmV6aWVyKHBhdGgsIHB4LCBweSk7XG4gICAgfVxuICAgIHBvaW50cy5wb3AoKTtcbiAgICBwYXRoLnB1c2goXCJMXCIsIHBpKTtcbiAgICByZXR1cm4gcGF0aC5qb2luKFwiXCIpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lQmFzaXNPcGVuKHBvaW50cykge1xuICAgIGlmIChwb2ludHMubGVuZ3RoIDwgNCkgcmV0dXJuIGQzX3N2Z19saW5lTGluZWFyKHBvaW50cyk7XG4gICAgdmFyIHBhdGggPSBbXSwgaSA9IC0xLCBuID0gcG9pbnRzLmxlbmd0aCwgcGksIHB4ID0gWyAwIF0sIHB5ID0gWyAwIF07XG4gICAgd2hpbGUgKCsraSA8IDMpIHtcbiAgICAgIHBpID0gcG9pbnRzW2ldO1xuICAgICAgcHgucHVzaChwaVswXSk7XG4gICAgICBweS5wdXNoKHBpWzFdKTtcbiAgICB9XG4gICAgcGF0aC5wdXNoKGQzX3N2Z19saW5lRG90NChkM19zdmdfbGluZUJhc2lzQmV6aWVyMywgcHgpICsgXCIsXCIgKyBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjMsIHB5KSk7XG4gICAgLS1pO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBwaSA9IHBvaW50c1tpXTtcbiAgICAgIHB4LnNoaWZ0KCk7XG4gICAgICBweC5wdXNoKHBpWzBdKTtcbiAgICAgIHB5LnNoaWZ0KCk7XG4gICAgICBweS5wdXNoKHBpWzFdKTtcbiAgICAgIGQzX3N2Z19saW5lQmFzaXNCZXppZXIocGF0aCwgcHgsIHB5KTtcbiAgICB9XG4gICAgcmV0dXJuIHBhdGguam9pbihcIlwiKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUJhc2lzQ2xvc2VkKHBvaW50cykge1xuICAgIHZhciBwYXRoLCBpID0gLTEsIG4gPSBwb2ludHMubGVuZ3RoLCBtID0gbiArIDQsIHBpLCBweCA9IFtdLCBweSA9IFtdO1xuICAgIHdoaWxlICgrK2kgPCA0KSB7XG4gICAgICBwaSA9IHBvaW50c1tpICUgbl07XG4gICAgICBweC5wdXNoKHBpWzBdKTtcbiAgICAgIHB5LnB1c2gocGlbMV0pO1xuICAgIH1cbiAgICBwYXRoID0gWyBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjMsIHB4KSwgXCIsXCIsIGQzX3N2Z19saW5lRG90NChkM19zdmdfbGluZUJhc2lzQmV6aWVyMywgcHkpIF07XG4gICAgLS1pO1xuICAgIHdoaWxlICgrK2kgPCBtKSB7XG4gICAgICBwaSA9IHBvaW50c1tpICUgbl07XG4gICAgICBweC5zaGlmdCgpO1xuICAgICAgcHgucHVzaChwaVswXSk7XG4gICAgICBweS5zaGlmdCgpO1xuICAgICAgcHkucHVzaChwaVsxXSk7XG4gICAgICBkM19zdmdfbGluZUJhc2lzQmV6aWVyKHBhdGgsIHB4LCBweSk7XG4gICAgfVxuICAgIHJldHVybiBwYXRoLmpvaW4oXCJcIik7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX2xpbmVCdW5kbGUocG9pbnRzLCB0ZW5zaW9uKSB7XG4gICAgdmFyIG4gPSBwb2ludHMubGVuZ3RoIC0gMTtcbiAgICBpZiAobikge1xuICAgICAgdmFyIHgwID0gcG9pbnRzWzBdWzBdLCB5MCA9IHBvaW50c1swXVsxXSwgZHggPSBwb2ludHNbbl1bMF0gLSB4MCwgZHkgPSBwb2ludHNbbl1bMV0gLSB5MCwgaSA9IC0xLCBwLCB0O1xuICAgICAgd2hpbGUgKCsraSA8PSBuKSB7XG4gICAgICAgIHAgPSBwb2ludHNbaV07XG4gICAgICAgIHQgPSBpIC8gbjtcbiAgICAgICAgcFswXSA9IHRlbnNpb24gKiBwWzBdICsgKDEgLSB0ZW5zaW9uKSAqICh4MCArIHQgKiBkeCk7XG4gICAgICAgIHBbMV0gPSB0ZW5zaW9uICogcFsxXSArICgxIC0gdGVuc2lvbikgKiAoeTAgKyB0ICogZHkpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZDNfc3ZnX2xpbmVCYXNpcyhwb2ludHMpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lRG90NChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV0gKyBhWzJdICogYlsyXSArIGFbM10gKiBiWzNdO1xuICB9XG4gIHZhciBkM19zdmdfbGluZUJhc2lzQmV6aWVyMSA9IFsgMCwgMiAvIDMsIDEgLyAzLCAwIF0sIGQzX3N2Z19saW5lQmFzaXNCZXppZXIyID0gWyAwLCAxIC8gMywgMiAvIDMsIDAgXSwgZDNfc3ZnX2xpbmVCYXNpc0JlemllcjMgPSBbIDAsIDEgLyA2LCAyIC8gMywgMSAvIDYgXTtcbiAgZnVuY3Rpb24gZDNfc3ZnX2xpbmVCYXNpc0JlemllcihwYXRoLCB4LCB5KSB7XG4gICAgcGF0aC5wdXNoKFwiQ1wiLCBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjEsIHgpLCBcIixcIiwgZDNfc3ZnX2xpbmVEb3Q0KGQzX3N2Z19saW5lQmFzaXNCZXppZXIxLCB5KSwgXCIsXCIsIGQzX3N2Z19saW5lRG90NChkM19zdmdfbGluZUJhc2lzQmV6aWVyMiwgeCksIFwiLFwiLCBkM19zdmdfbGluZURvdDQoZDNfc3ZnX2xpbmVCYXNpc0JlemllcjIsIHkpLCBcIixcIiwgZDNfc3ZnX2xpbmVEb3Q0KGQzX3N2Z19saW5lQmFzaXNCZXppZXIzLCB4KSwgXCIsXCIsIGQzX3N2Z19saW5lRG90NChkM19zdmdfbGluZUJhc2lzQmV6aWVyMywgeSkpO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lU2xvcGUocDAsIHAxKSB7XG4gICAgcmV0dXJuIChwMVsxXSAtIHAwWzFdKSAvIChwMVswXSAtIHAwWzBdKTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZUZpbml0ZURpZmZlcmVuY2VzKHBvaW50cykge1xuICAgIHZhciBpID0gMCwgaiA9IHBvaW50cy5sZW5ndGggLSAxLCBtID0gW10sIHAwID0gcG9pbnRzWzBdLCBwMSA9IHBvaW50c1sxXSwgZCA9IG1bMF0gPSBkM19zdmdfbGluZVNsb3BlKHAwLCBwMSk7XG4gICAgd2hpbGUgKCsraSA8IGopIHtcbiAgICAgIG1baV0gPSAoZCArIChkID0gZDNfc3ZnX2xpbmVTbG9wZShwMCA9IHAxLCBwMSA9IHBvaW50c1tpICsgMV0pKSkgLyAyO1xuICAgIH1cbiAgICBtW2ldID0gZDtcbiAgICByZXR1cm4gbTtcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfbGluZU1vbm90b25lVGFuZ2VudHMocG9pbnRzKSB7XG4gICAgdmFyIHRhbmdlbnRzID0gW10sIGQsIGEsIGIsIHMsIG0gPSBkM19zdmdfbGluZUZpbml0ZURpZmZlcmVuY2VzKHBvaW50cyksIGkgPSAtMSwgaiA9IHBvaW50cy5sZW5ndGggLSAxO1xuICAgIHdoaWxlICgrK2kgPCBqKSB7XG4gICAgICBkID0gZDNfc3ZnX2xpbmVTbG9wZShwb2ludHNbaV0sIHBvaW50c1tpICsgMV0pO1xuICAgICAgaWYgKGFicyhkKSA8IM61KSB7XG4gICAgICAgIG1baV0gPSBtW2kgKyAxXSA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhID0gbVtpXSAvIGQ7XG4gICAgICAgIGIgPSBtW2kgKyAxXSAvIGQ7XG4gICAgICAgIHMgPSBhICogYSArIGIgKiBiO1xuICAgICAgICBpZiAocyA+IDkpIHtcbiAgICAgICAgICBzID0gZCAqIDMgLyBNYXRoLnNxcnQocyk7XG4gICAgICAgICAgbVtpXSA9IHMgKiBhO1xuICAgICAgICAgIG1baSArIDFdID0gcyAqIGI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaSA9IC0xO1xuICAgIHdoaWxlICgrK2kgPD0gaikge1xuICAgICAgcyA9IChwb2ludHNbTWF0aC5taW4oaiwgaSArIDEpXVswXSAtIHBvaW50c1tNYXRoLm1heCgwLCBpIC0gMSldWzBdKSAvICg2ICogKDEgKyBtW2ldICogbVtpXSkpO1xuICAgICAgdGFuZ2VudHMucHVzaChbIHMgfHwgMCwgbVtpXSAqIHMgfHwgMCBdKTtcbiAgICB9XG4gICAgcmV0dXJuIHRhbmdlbnRzO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19saW5lTW9ub3RvbmUocG9pbnRzKSB7XG4gICAgcmV0dXJuIHBvaW50cy5sZW5ndGggPCAzID8gZDNfc3ZnX2xpbmVMaW5lYXIocG9pbnRzKSA6IHBvaW50c1swXSArIGQzX3N2Z19saW5lSGVybWl0ZShwb2ludHMsIGQzX3N2Z19saW5lTW9ub3RvbmVUYW5nZW50cyhwb2ludHMpKTtcbiAgfVxuICBkMy5zdmcubGluZS5yYWRpYWwgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbGluZSA9IGQzX3N2Z19saW5lKGQzX3N2Z19saW5lUmFkaWFsKTtcbiAgICBsaW5lLnJhZGl1cyA9IGxpbmUueCwgZGVsZXRlIGxpbmUueDtcbiAgICBsaW5lLmFuZ2xlID0gbGluZS55LCBkZWxldGUgbGluZS55O1xuICAgIHJldHVybiBsaW5lO1xuICB9O1xuICBmdW5jdGlvbiBkM19zdmdfbGluZVJhZGlhbChwb2ludHMpIHtcbiAgICB2YXIgcG9pbnQsIGkgPSAtMSwgbiA9IHBvaW50cy5sZW5ndGgsIHIsIGE7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIHBvaW50ID0gcG9pbnRzW2ldO1xuICAgICAgciA9IHBvaW50WzBdO1xuICAgICAgYSA9IHBvaW50WzFdIC0gaGFsZs+AO1xuICAgICAgcG9pbnRbMF0gPSByICogTWF0aC5jb3MoYSk7XG4gICAgICBwb2ludFsxXSA9IHIgKiBNYXRoLnNpbihhKTtcbiAgICB9XG4gICAgcmV0dXJuIHBvaW50cztcbiAgfVxuICBmdW5jdGlvbiBkM19zdmdfYXJlYShwcm9qZWN0aW9uKSB7XG4gICAgdmFyIHgwID0gZDNfZ2VvbV9wb2ludFgsIHgxID0gZDNfZ2VvbV9wb2ludFgsIHkwID0gMCwgeTEgPSBkM19nZW9tX3BvaW50WSwgZGVmaW5lZCA9IGQzX3RydWUsIGludGVycG9sYXRlID0gZDNfc3ZnX2xpbmVMaW5lYXIsIGludGVycG9sYXRlS2V5ID0gaW50ZXJwb2xhdGUua2V5LCBpbnRlcnBvbGF0ZVJldmVyc2UgPSBpbnRlcnBvbGF0ZSwgTCA9IFwiTFwiLCB0ZW5zaW9uID0gLjc7XG4gICAgZnVuY3Rpb24gYXJlYShkYXRhKSB7XG4gICAgICB2YXIgc2VnbWVudHMgPSBbXSwgcG9pbnRzMCA9IFtdLCBwb2ludHMxID0gW10sIGkgPSAtMSwgbiA9IGRhdGEubGVuZ3RoLCBkLCBmeDAgPSBkM19mdW5jdG9yKHgwKSwgZnkwID0gZDNfZnVuY3Rvcih5MCksIGZ4MSA9IHgwID09PSB4MSA/IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4geDtcbiAgICAgIH0gOiBkM19mdW5jdG9yKHgxKSwgZnkxID0geTAgPT09IHkxID8gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB5O1xuICAgICAgfSA6IGQzX2Z1bmN0b3IoeTEpLCB4LCB5O1xuICAgICAgZnVuY3Rpb24gc2VnbWVudCgpIHtcbiAgICAgICAgc2VnbWVudHMucHVzaChcIk1cIiwgaW50ZXJwb2xhdGUocHJvamVjdGlvbihwb2ludHMxKSwgdGVuc2lvbiksIEwsIGludGVycG9sYXRlUmV2ZXJzZShwcm9qZWN0aW9uKHBvaW50czAucmV2ZXJzZSgpKSwgdGVuc2lvbiksIFwiWlwiKTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIGlmIChkZWZpbmVkLmNhbGwodGhpcywgZCA9IGRhdGFbaV0sIGkpKSB7XG4gICAgICAgICAgcG9pbnRzMC5wdXNoKFsgeCA9ICtmeDAuY2FsbCh0aGlzLCBkLCBpKSwgeSA9ICtmeTAuY2FsbCh0aGlzLCBkLCBpKSBdKTtcbiAgICAgICAgICBwb2ludHMxLnB1c2goWyArZngxLmNhbGwodGhpcywgZCwgaSksICtmeTEuY2FsbCh0aGlzLCBkLCBpKSBdKTtcbiAgICAgICAgfSBlbHNlIGlmIChwb2ludHMwLmxlbmd0aCkge1xuICAgICAgICAgIHNlZ21lbnQoKTtcbiAgICAgICAgICBwb2ludHMwID0gW107XG4gICAgICAgICAgcG9pbnRzMSA9IFtdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAocG9pbnRzMC5sZW5ndGgpIHNlZ21lbnQoKTtcbiAgICAgIHJldHVybiBzZWdtZW50cy5sZW5ndGggPyBzZWdtZW50cy5qb2luKFwiXCIpIDogbnVsbDtcbiAgICB9XG4gICAgYXJlYS54ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDE7XG4gICAgICB4MCA9IHgxID0gXztcbiAgICAgIHJldHVybiBhcmVhO1xuICAgIH07XG4gICAgYXJlYS54MCA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHgwO1xuICAgICAgeDAgPSBfO1xuICAgICAgcmV0dXJuIGFyZWE7XG4gICAgfTtcbiAgICBhcmVhLngxID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4geDE7XG4gICAgICB4MSA9IF87XG4gICAgICByZXR1cm4gYXJlYTtcbiAgICB9O1xuICAgIGFyZWEueSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHkxO1xuICAgICAgeTAgPSB5MSA9IF87XG4gICAgICByZXR1cm4gYXJlYTtcbiAgICB9O1xuICAgIGFyZWEueTAgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB5MDtcbiAgICAgIHkwID0gXztcbiAgICAgIHJldHVybiBhcmVhO1xuICAgIH07XG4gICAgYXJlYS55MSA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHkxO1xuICAgICAgeTEgPSBfO1xuICAgICAgcmV0dXJuIGFyZWE7XG4gICAgfTtcbiAgICBhcmVhLmRlZmluZWQgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBkZWZpbmVkO1xuICAgICAgZGVmaW5lZCA9IF87XG4gICAgICByZXR1cm4gYXJlYTtcbiAgICB9O1xuICAgIGFyZWEuaW50ZXJwb2xhdGUgPSBmdW5jdGlvbihfKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBpbnRlcnBvbGF0ZUtleTtcbiAgICAgIGlmICh0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiKSBpbnRlcnBvbGF0ZUtleSA9IGludGVycG9sYXRlID0gXzsgZWxzZSBpbnRlcnBvbGF0ZUtleSA9IChpbnRlcnBvbGF0ZSA9IGQzX3N2Z19saW5lSW50ZXJwb2xhdG9ycy5nZXQoXykgfHwgZDNfc3ZnX2xpbmVMaW5lYXIpLmtleTtcbiAgICAgIGludGVycG9sYXRlUmV2ZXJzZSA9IGludGVycG9sYXRlLnJldmVyc2UgfHwgaW50ZXJwb2xhdGU7XG4gICAgICBMID0gaW50ZXJwb2xhdGUuY2xvc2VkID8gXCJNXCIgOiBcIkxcIjtcbiAgICAgIHJldHVybiBhcmVhO1xuICAgIH07XG4gICAgYXJlYS50ZW5zaW9uID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGVuc2lvbjtcbiAgICAgIHRlbnNpb24gPSBfO1xuICAgICAgcmV0dXJuIGFyZWE7XG4gICAgfTtcbiAgICByZXR1cm4gYXJlYTtcbiAgfVxuICBkM19zdmdfbGluZVN0ZXBCZWZvcmUucmV2ZXJzZSA9IGQzX3N2Z19saW5lU3RlcEFmdGVyO1xuICBkM19zdmdfbGluZVN0ZXBBZnRlci5yZXZlcnNlID0gZDNfc3ZnX2xpbmVTdGVwQmVmb3JlO1xuICBkMy5zdmcuYXJlYSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBkM19zdmdfYXJlYShkM19pZGVudGl0eSk7XG4gIH07XG4gIGQzLnN2Zy5hcmVhLnJhZGlhbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBhcmVhID0gZDNfc3ZnX2FyZWEoZDNfc3ZnX2xpbmVSYWRpYWwpO1xuICAgIGFyZWEucmFkaXVzID0gYXJlYS54LCBkZWxldGUgYXJlYS54O1xuICAgIGFyZWEuaW5uZXJSYWRpdXMgPSBhcmVhLngwLCBkZWxldGUgYXJlYS54MDtcbiAgICBhcmVhLm91dGVyUmFkaXVzID0gYXJlYS54MSwgZGVsZXRlIGFyZWEueDE7XG4gICAgYXJlYS5hbmdsZSA9IGFyZWEueSwgZGVsZXRlIGFyZWEueTtcbiAgICBhcmVhLnN0YXJ0QW5nbGUgPSBhcmVhLnkwLCBkZWxldGUgYXJlYS55MDtcbiAgICBhcmVhLmVuZEFuZ2xlID0gYXJlYS55MSwgZGVsZXRlIGFyZWEueTE7XG4gICAgcmV0dXJuIGFyZWE7XG4gIH07XG4gIGQzLnN2Zy5jaG9yZCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBzb3VyY2UgPSBkM19zb3VyY2UsIHRhcmdldCA9IGQzX3RhcmdldCwgcmFkaXVzID0gZDNfc3ZnX2Nob3JkUmFkaXVzLCBzdGFydEFuZ2xlID0gZDNfc3ZnX2FyY1N0YXJ0QW5nbGUsIGVuZEFuZ2xlID0gZDNfc3ZnX2FyY0VuZEFuZ2xlO1xuICAgIGZ1bmN0aW9uIGNob3JkKGQsIGkpIHtcbiAgICAgIHZhciBzID0gc3ViZ3JvdXAodGhpcywgc291cmNlLCBkLCBpKSwgdCA9IHN1Ymdyb3VwKHRoaXMsIHRhcmdldCwgZCwgaSk7XG4gICAgICByZXR1cm4gXCJNXCIgKyBzLnAwICsgYXJjKHMuciwgcy5wMSwgcy5hMSAtIHMuYTApICsgKGVxdWFscyhzLCB0KSA/IGN1cnZlKHMuciwgcy5wMSwgcy5yLCBzLnAwKSA6IGN1cnZlKHMuciwgcy5wMSwgdC5yLCB0LnAwKSArIGFyYyh0LnIsIHQucDEsIHQuYTEgLSB0LmEwKSArIGN1cnZlKHQuciwgdC5wMSwgcy5yLCBzLnAwKSkgKyBcIlpcIjtcbiAgICB9XG4gICAgZnVuY3Rpb24gc3ViZ3JvdXAoc2VsZiwgZiwgZCwgaSkge1xuICAgICAgdmFyIHN1Ymdyb3VwID0gZi5jYWxsKHNlbGYsIGQsIGkpLCByID0gcmFkaXVzLmNhbGwoc2VsZiwgc3ViZ3JvdXAsIGkpLCBhMCA9IHN0YXJ0QW5nbGUuY2FsbChzZWxmLCBzdWJncm91cCwgaSkgLSBoYWxmz4AsIGExID0gZW5kQW5nbGUuY2FsbChzZWxmLCBzdWJncm91cCwgaSkgLSBoYWxmz4A7XG4gICAgICByZXR1cm4ge1xuICAgICAgICByOiByLFxuICAgICAgICBhMDogYTAsXG4gICAgICAgIGExOiBhMSxcbiAgICAgICAgcDA6IFsgciAqIE1hdGguY29zKGEwKSwgciAqIE1hdGguc2luKGEwKSBdLFxuICAgICAgICBwMTogWyByICogTWF0aC5jb3MoYTEpLCByICogTWF0aC5zaW4oYTEpIF1cbiAgICAgIH07XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVxdWFscyhhLCBiKSB7XG4gICAgICByZXR1cm4gYS5hMCA9PSBiLmEwICYmIGEuYTEgPT0gYi5hMTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXJjKHIsIHAsIGEpIHtcbiAgICAgIHJldHVybiBcIkFcIiArIHIgKyBcIixcIiArIHIgKyBcIiAwIFwiICsgKyhhID4gz4ApICsgXCIsMSBcIiArIHA7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGN1cnZlKHIwLCBwMCwgcjEsIHAxKSB7XG4gICAgICByZXR1cm4gXCJRIDAsMCBcIiArIHAxO1xuICAgIH1cbiAgICBjaG9yZC5yYWRpdXMgPSBmdW5jdGlvbih2KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiByYWRpdXM7XG4gICAgICByYWRpdXMgPSBkM19mdW5jdG9yKHYpO1xuICAgICAgcmV0dXJuIGNob3JkO1xuICAgIH07XG4gICAgY2hvcmQuc291cmNlID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc291cmNlO1xuICAgICAgc291cmNlID0gZDNfZnVuY3Rvcih2KTtcbiAgICAgIHJldHVybiBjaG9yZDtcbiAgICB9O1xuICAgIGNob3JkLnRhcmdldCA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHRhcmdldDtcbiAgICAgIHRhcmdldCA9IGQzX2Z1bmN0b3Iodik7XG4gICAgICByZXR1cm4gY2hvcmQ7XG4gICAgfTtcbiAgICBjaG9yZC5zdGFydEFuZ2xlID0gZnVuY3Rpb24odikge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc3RhcnRBbmdsZTtcbiAgICAgIHN0YXJ0QW5nbGUgPSBkM19mdW5jdG9yKHYpO1xuICAgICAgcmV0dXJuIGNob3JkO1xuICAgIH07XG4gICAgY2hvcmQuZW5kQW5nbGUgPSBmdW5jdGlvbih2KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBlbmRBbmdsZTtcbiAgICAgIGVuZEFuZ2xlID0gZDNfZnVuY3Rvcih2KTtcbiAgICAgIHJldHVybiBjaG9yZDtcbiAgICB9O1xuICAgIHJldHVybiBjaG9yZDtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc3ZnX2Nob3JkUmFkaXVzKGQpIHtcbiAgICByZXR1cm4gZC5yYWRpdXM7XG4gIH1cbiAgZDMuc3ZnLmRpYWdvbmFsID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHNvdXJjZSA9IGQzX3NvdXJjZSwgdGFyZ2V0ID0gZDNfdGFyZ2V0LCBwcm9qZWN0aW9uID0gZDNfc3ZnX2RpYWdvbmFsUHJvamVjdGlvbjtcbiAgICBmdW5jdGlvbiBkaWFnb25hbChkLCBpKSB7XG4gICAgICB2YXIgcDAgPSBzb3VyY2UuY2FsbCh0aGlzLCBkLCBpKSwgcDMgPSB0YXJnZXQuY2FsbCh0aGlzLCBkLCBpKSwgbSA9IChwMC55ICsgcDMueSkgLyAyLCBwID0gWyBwMCwge1xuICAgICAgICB4OiBwMC54LFxuICAgICAgICB5OiBtXG4gICAgICB9LCB7XG4gICAgICAgIHg6IHAzLngsXG4gICAgICAgIHk6IG1cbiAgICAgIH0sIHAzIF07XG4gICAgICBwID0gcC5tYXAocHJvamVjdGlvbik7XG4gICAgICByZXR1cm4gXCJNXCIgKyBwWzBdICsgXCJDXCIgKyBwWzFdICsgXCIgXCIgKyBwWzJdICsgXCIgXCIgKyBwWzNdO1xuICAgIH1cbiAgICBkaWFnb25hbC5zb3VyY2UgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBzb3VyY2U7XG4gICAgICBzb3VyY2UgPSBkM19mdW5jdG9yKHgpO1xuICAgICAgcmV0dXJuIGRpYWdvbmFsO1xuICAgIH07XG4gICAgZGlhZ29uYWwudGFyZ2V0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGFyZ2V0O1xuICAgICAgdGFyZ2V0ID0gZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBkaWFnb25hbDtcbiAgICB9O1xuICAgIGRpYWdvbmFsLnByb2plY3Rpb24gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBwcm9qZWN0aW9uO1xuICAgICAgcHJvamVjdGlvbiA9IHg7XG4gICAgICByZXR1cm4gZGlhZ29uYWw7XG4gICAgfTtcbiAgICByZXR1cm4gZGlhZ29uYWw7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3N2Z19kaWFnb25hbFByb2plY3Rpb24oZCkge1xuICAgIHJldHVybiBbIGQueCwgZC55IF07XG4gIH1cbiAgZDMuc3ZnLmRpYWdvbmFsLnJhZGlhbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBkaWFnb25hbCA9IGQzLnN2Zy5kaWFnb25hbCgpLCBwcm9qZWN0aW9uID0gZDNfc3ZnX2RpYWdvbmFsUHJvamVjdGlvbiwgcHJvamVjdGlvbl8gPSBkaWFnb25hbC5wcm9qZWN0aW9uO1xuICAgIGRpYWdvbmFsLnByb2plY3Rpb24gPSBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IHByb2plY3Rpb25fKGQzX3N2Z19kaWFnb25hbFJhZGlhbFByb2plY3Rpb24ocHJvamVjdGlvbiA9IHgpKSA6IHByb2plY3Rpb247XG4gICAgfTtcbiAgICByZXR1cm4gZGlhZ29uYWw7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3N2Z19kaWFnb25hbFJhZGlhbFByb2plY3Rpb24ocHJvamVjdGlvbikge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBkID0gcHJvamVjdGlvbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCByID0gZFswXSwgYSA9IGRbMV0gLSBoYWxmz4A7XG4gICAgICByZXR1cm4gWyByICogTWF0aC5jb3MoYSksIHIgKiBNYXRoLnNpbihhKSBdO1xuICAgIH07XG4gIH1cbiAgZDMuc3ZnLnN5bWJvbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0eXBlID0gZDNfc3ZnX3N5bWJvbFR5cGUsIHNpemUgPSBkM19zdmdfc3ltYm9sU2l6ZTtcbiAgICBmdW5jdGlvbiBzeW1ib2woZCwgaSkge1xuICAgICAgcmV0dXJuIChkM19zdmdfc3ltYm9scy5nZXQodHlwZS5jYWxsKHRoaXMsIGQsIGkpKSB8fCBkM19zdmdfc3ltYm9sQ2lyY2xlKShzaXplLmNhbGwodGhpcywgZCwgaSkpO1xuICAgIH1cbiAgICBzeW1ib2wudHlwZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHR5cGU7XG4gICAgICB0eXBlID0gZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBzeW1ib2w7XG4gICAgfTtcbiAgICBzeW1ib2wuc2l6ZSA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHNpemU7XG4gICAgICBzaXplID0gZDNfZnVuY3Rvcih4KTtcbiAgICAgIHJldHVybiBzeW1ib2w7XG4gICAgfTtcbiAgICByZXR1cm4gc3ltYm9sO1xuICB9O1xuICBmdW5jdGlvbiBkM19zdmdfc3ltYm9sU2l6ZSgpIHtcbiAgICByZXR1cm4gNjQ7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX3N5bWJvbFR5cGUoKSB7XG4gICAgcmV0dXJuIFwiY2lyY2xlXCI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfc3ZnX3N5bWJvbENpcmNsZShzaXplKSB7XG4gICAgdmFyIHIgPSBNYXRoLnNxcnQoc2l6ZSAvIM+AKTtcbiAgICByZXR1cm4gXCJNMCxcIiArIHIgKyBcIkFcIiArIHIgKyBcIixcIiArIHIgKyBcIiAwIDEsMSAwLFwiICsgLXIgKyBcIkFcIiArIHIgKyBcIixcIiArIHIgKyBcIiAwIDEsMSAwLFwiICsgciArIFwiWlwiO1xuICB9XG4gIHZhciBkM19zdmdfc3ltYm9scyA9IGQzLm1hcCh7XG4gICAgY2lyY2xlOiBkM19zdmdfc3ltYm9sQ2lyY2xlLFxuICAgIGNyb3NzOiBmdW5jdGlvbihzaXplKSB7XG4gICAgICB2YXIgciA9IE1hdGguc3FydChzaXplIC8gNSkgLyAyO1xuICAgICAgcmV0dXJuIFwiTVwiICsgLTMgKiByICsgXCIsXCIgKyAtciArIFwiSFwiICsgLXIgKyBcIlZcIiArIC0zICogciArIFwiSFwiICsgciArIFwiVlwiICsgLXIgKyBcIkhcIiArIDMgKiByICsgXCJWXCIgKyByICsgXCJIXCIgKyByICsgXCJWXCIgKyAzICogciArIFwiSFwiICsgLXIgKyBcIlZcIiArIHIgKyBcIkhcIiArIC0zICogciArIFwiWlwiO1xuICAgIH0sXG4gICAgZGlhbW9uZDogZnVuY3Rpb24oc2l6ZSkge1xuICAgICAgdmFyIHJ5ID0gTWF0aC5zcXJ0KHNpemUgLyAoMiAqIGQzX3N2Z19zeW1ib2xUYW4zMCkpLCByeCA9IHJ5ICogZDNfc3ZnX3N5bWJvbFRhbjMwO1xuICAgICAgcmV0dXJuIFwiTTAsXCIgKyAtcnkgKyBcIkxcIiArIHJ4ICsgXCIsMFwiICsgXCIgMCxcIiArIHJ5ICsgXCIgXCIgKyAtcnggKyBcIiwwXCIgKyBcIlpcIjtcbiAgICB9LFxuICAgIHNxdWFyZTogZnVuY3Rpb24oc2l6ZSkge1xuICAgICAgdmFyIHIgPSBNYXRoLnNxcnQoc2l6ZSkgLyAyO1xuICAgICAgcmV0dXJuIFwiTVwiICsgLXIgKyBcIixcIiArIC1yICsgXCJMXCIgKyByICsgXCIsXCIgKyAtciArIFwiIFwiICsgciArIFwiLFwiICsgciArIFwiIFwiICsgLXIgKyBcIixcIiArIHIgKyBcIlpcIjtcbiAgICB9LFxuICAgIFwidHJpYW5nbGUtZG93blwiOiBmdW5jdGlvbihzaXplKSB7XG4gICAgICB2YXIgcnggPSBNYXRoLnNxcnQoc2l6ZSAvIGQzX3N2Z19zeW1ib2xTcXJ0MyksIHJ5ID0gcnggKiBkM19zdmdfc3ltYm9sU3FydDMgLyAyO1xuICAgICAgcmV0dXJuIFwiTTAsXCIgKyByeSArIFwiTFwiICsgcnggKyBcIixcIiArIC1yeSArIFwiIFwiICsgLXJ4ICsgXCIsXCIgKyAtcnkgKyBcIlpcIjtcbiAgICB9LFxuICAgIFwidHJpYW5nbGUtdXBcIjogZnVuY3Rpb24oc2l6ZSkge1xuICAgICAgdmFyIHJ4ID0gTWF0aC5zcXJ0KHNpemUgLyBkM19zdmdfc3ltYm9sU3FydDMpLCByeSA9IHJ4ICogZDNfc3ZnX3N5bWJvbFNxcnQzIC8gMjtcbiAgICAgIHJldHVybiBcIk0wLFwiICsgLXJ5ICsgXCJMXCIgKyByeCArIFwiLFwiICsgcnkgKyBcIiBcIiArIC1yeCArIFwiLFwiICsgcnkgKyBcIlpcIjtcbiAgICB9XG4gIH0pO1xuICBkMy5zdmcuc3ltYm9sVHlwZXMgPSBkM19zdmdfc3ltYm9scy5rZXlzKCk7XG4gIHZhciBkM19zdmdfc3ltYm9sU3FydDMgPSBNYXRoLnNxcnQoMyksIGQzX3N2Z19zeW1ib2xUYW4zMCA9IE1hdGgudGFuKDMwICogZDNfcmFkaWFucyk7XG4gIGQzX3NlbGVjdGlvblByb3RvdHlwZS50cmFuc2l0aW9uID0gZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBpZCA9IGQzX3RyYW5zaXRpb25Jbmhlcml0SWQgfHwgKytkM190cmFuc2l0aW9uSWQsIG5zID0gZDNfdHJhbnNpdGlvbk5hbWVzcGFjZShuYW1lKSwgc3ViZ3JvdXBzID0gW10sIHN1Ymdyb3VwLCBub2RlLCB0cmFuc2l0aW9uID0gZDNfdHJhbnNpdGlvbkluaGVyaXQgfHwge1xuICAgICAgdGltZTogRGF0ZS5ub3coKSxcbiAgICAgIGVhc2U6IGQzX2Vhc2VfY3ViaWNJbk91dCxcbiAgICAgIGRlbGF5OiAwLFxuICAgICAgZHVyYXRpb246IDI1MFxuICAgIH07XG4gICAgZm9yICh2YXIgaiA9IC0xLCBtID0gdGhpcy5sZW5ndGg7ICsraiA8IG07ICkge1xuICAgICAgc3ViZ3JvdXBzLnB1c2goc3ViZ3JvdXAgPSBbXSk7XG4gICAgICBmb3IgKHZhciBncm91cCA9IHRoaXNbal0sIGkgPSAtMSwgbiA9IGdyb3VwLmxlbmd0aDsgKytpIDwgbjsgKSB7XG4gICAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIGQzX3RyYW5zaXRpb25Ob2RlKG5vZGUsIGksIG5zLCBpZCwgdHJhbnNpdGlvbik7XG4gICAgICAgIHN1Ymdyb3VwLnB1c2gobm9kZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkM190cmFuc2l0aW9uKHN1Ymdyb3VwcywgbnMsIGlkKTtcbiAgfTtcbiAgZDNfc2VsZWN0aW9uUHJvdG90eXBlLmludGVycnVwdCA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5lYWNoKG5hbWUgPT0gbnVsbCA/IGQzX3NlbGVjdGlvbl9pbnRlcnJ1cHQgOiBkM19zZWxlY3Rpb25faW50ZXJydXB0TlMoZDNfdHJhbnNpdGlvbk5hbWVzcGFjZShuYW1lKSkpO1xuICB9O1xuICB2YXIgZDNfc2VsZWN0aW9uX2ludGVycnVwdCA9IGQzX3NlbGVjdGlvbl9pbnRlcnJ1cHROUyhkM190cmFuc2l0aW9uTmFtZXNwYWNlKCkpO1xuICBmdW5jdGlvbiBkM19zZWxlY3Rpb25faW50ZXJydXB0TlMobnMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbG9jaywgYWN0aXZlSWQsIGFjdGl2ZTtcbiAgICAgIGlmICgobG9jayA9IHRoaXNbbnNdKSAmJiAoYWN0aXZlID0gbG9ja1thY3RpdmVJZCA9IGxvY2suYWN0aXZlXSkpIHtcbiAgICAgICAgYWN0aXZlLnRpbWVyLmMgPSBudWxsO1xuICAgICAgICBhY3RpdmUudGltZXIudCA9IE5hTjtcbiAgICAgICAgaWYgKC0tbG9jay5jb3VudCkgZGVsZXRlIGxvY2tbYWN0aXZlSWRdOyBlbHNlIGRlbGV0ZSB0aGlzW25zXTtcbiAgICAgICAgbG9jay5hY3RpdmUgKz0gLjU7XG4gICAgICAgIGFjdGl2ZS5ldmVudCAmJiBhY3RpdmUuZXZlbnQuaW50ZXJydXB0LmNhbGwodGhpcywgdGhpcy5fX2RhdGFfXywgYWN0aXZlLmluZGV4KTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGQzX3RyYW5zaXRpb24oZ3JvdXBzLCBucywgaWQpIHtcbiAgICBkM19zdWJjbGFzcyhncm91cHMsIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUpO1xuICAgIGdyb3Vwcy5uYW1lc3BhY2UgPSBucztcbiAgICBncm91cHMuaWQgPSBpZDtcbiAgICByZXR1cm4gZ3JvdXBzO1xuICB9XG4gIHZhciBkM190cmFuc2l0aW9uUHJvdG90eXBlID0gW10sIGQzX3RyYW5zaXRpb25JZCA9IDAsIGQzX3RyYW5zaXRpb25Jbmhlcml0SWQsIGQzX3RyYW5zaXRpb25Jbmhlcml0O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmNhbGwgPSBkM19zZWxlY3Rpb25Qcm90b3R5cGUuY2FsbDtcbiAgZDNfdHJhbnNpdGlvblByb3RvdHlwZS5lbXB0eSA9IGQzX3NlbGVjdGlvblByb3RvdHlwZS5lbXB0eTtcbiAgZDNfdHJhbnNpdGlvblByb3RvdHlwZS5ub2RlID0gZDNfc2VsZWN0aW9uUHJvdG90eXBlLm5vZGU7XG4gIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUuc2l6ZSA9IGQzX3NlbGVjdGlvblByb3RvdHlwZS5zaXplO1xuICBkMy50cmFuc2l0aW9uID0gZnVuY3Rpb24oc2VsZWN0aW9uLCBuYW1lKSB7XG4gICAgcmV0dXJuIHNlbGVjdGlvbiAmJiBzZWxlY3Rpb24udHJhbnNpdGlvbiA/IGQzX3RyYW5zaXRpb25Jbmhlcml0SWQgPyBzZWxlY3Rpb24udHJhbnNpdGlvbihuYW1lKSA6IHNlbGVjdGlvbiA6IGQzLnNlbGVjdGlvbigpLnRyYW5zaXRpb24oc2VsZWN0aW9uKTtcbiAgfTtcbiAgZDMudHJhbnNpdGlvbi5wcm90b3R5cGUgPSBkM190cmFuc2l0aW9uUHJvdG90eXBlO1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnNlbGVjdCA9IGZ1bmN0aW9uKHNlbGVjdG9yKSB7XG4gICAgdmFyIGlkID0gdGhpcy5pZCwgbnMgPSB0aGlzLm5hbWVzcGFjZSwgc3ViZ3JvdXBzID0gW10sIHN1Ymdyb3VwLCBzdWJub2RlLCBub2RlO1xuICAgIHNlbGVjdG9yID0gZDNfc2VsZWN0aW9uX3NlbGVjdG9yKHNlbGVjdG9yKTtcbiAgICBmb3IgKHZhciBqID0gLTEsIG0gPSB0aGlzLmxlbmd0aDsgKytqIDwgbTsgKSB7XG4gICAgICBzdWJncm91cHMucHVzaChzdWJncm91cCA9IFtdKTtcbiAgICAgIGZvciAodmFyIGdyb3VwID0gdGhpc1tqXSwgaSA9IC0xLCBuID0gZ3JvdXAubGVuZ3RoOyArK2kgPCBuOyApIHtcbiAgICAgICAgaWYgKChub2RlID0gZ3JvdXBbaV0pICYmIChzdWJub2RlID0gc2VsZWN0b3IuY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKSkpIHtcbiAgICAgICAgICBpZiAoXCJfX2RhdGFfX1wiIGluIG5vZGUpIHN1Ym5vZGUuX19kYXRhX18gPSBub2RlLl9fZGF0YV9fO1xuICAgICAgICAgIGQzX3RyYW5zaXRpb25Ob2RlKHN1Ym5vZGUsIGksIG5zLCBpZCwgbm9kZVtuc11baWRdKTtcbiAgICAgICAgICBzdWJncm91cC5wdXNoKHN1Ym5vZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN1Ymdyb3VwLnB1c2gobnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGQzX3RyYW5zaXRpb24oc3ViZ3JvdXBzLCBucywgaWQpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnNlbGVjdEFsbCA9IGZ1bmN0aW9uKHNlbGVjdG9yKSB7XG4gICAgdmFyIGlkID0gdGhpcy5pZCwgbnMgPSB0aGlzLm5hbWVzcGFjZSwgc3ViZ3JvdXBzID0gW10sIHN1Ymdyb3VwLCBzdWJub2Rlcywgbm9kZSwgc3Vibm9kZSwgdHJhbnNpdGlvbjtcbiAgICBzZWxlY3RvciA9IGQzX3NlbGVjdGlvbl9zZWxlY3RvckFsbChzZWxlY3Rvcik7XG4gICAgZm9yICh2YXIgaiA9IC0xLCBtID0gdGhpcy5sZW5ndGg7ICsraiA8IG07ICkge1xuICAgICAgZm9yICh2YXIgZ3JvdXAgPSB0aGlzW2pdLCBpID0gLTEsIG4gPSBncm91cC5sZW5ndGg7ICsraSA8IG47ICkge1xuICAgICAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICAgICAgdHJhbnNpdGlvbiA9IG5vZGVbbnNdW2lkXTtcbiAgICAgICAgICBzdWJub2RlcyA9IHNlbGVjdG9yLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgaik7XG4gICAgICAgICAgc3ViZ3JvdXBzLnB1c2goc3ViZ3JvdXAgPSBbXSk7XG4gICAgICAgICAgZm9yICh2YXIgayA9IC0xLCBvID0gc3Vibm9kZXMubGVuZ3RoOyArK2sgPCBvOyApIHtcbiAgICAgICAgICAgIGlmIChzdWJub2RlID0gc3Vibm9kZXNba10pIGQzX3RyYW5zaXRpb25Ob2RlKHN1Ym5vZGUsIGssIG5zLCBpZCwgdHJhbnNpdGlvbik7XG4gICAgICAgICAgICBzdWJncm91cC5wdXNoKHN1Ym5vZGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZDNfdHJhbnNpdGlvbihzdWJncm91cHMsIG5zLCBpZCk7XG4gIH07XG4gIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUuZmlsdGVyID0gZnVuY3Rpb24oZmlsdGVyKSB7XG4gICAgdmFyIHN1Ymdyb3VwcyA9IFtdLCBzdWJncm91cCwgZ3JvdXAsIG5vZGU7XG4gICAgaWYgKHR5cGVvZiBmaWx0ZXIgIT09IFwiZnVuY3Rpb25cIikgZmlsdGVyID0gZDNfc2VsZWN0aW9uX2ZpbHRlcihmaWx0ZXIpO1xuICAgIGZvciAodmFyIGogPSAwLCBtID0gdGhpcy5sZW5ndGg7IGogPCBtOyBqKyspIHtcbiAgICAgIHN1Ymdyb3Vwcy5wdXNoKHN1Ymdyb3VwID0gW10pO1xuICAgICAgZm9yICh2YXIgZ3JvdXAgPSB0aGlzW2pdLCBpID0gMCwgbiA9IGdyb3VwLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICBpZiAoKG5vZGUgPSBncm91cFtpXSkgJiYgZmlsdGVyLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgaikpIHtcbiAgICAgICAgICBzdWJncm91cC5wdXNoKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkM190cmFuc2l0aW9uKHN1Ymdyb3VwcywgdGhpcy5uYW1lc3BhY2UsIHRoaXMuaWQpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnR3ZWVuID0gZnVuY3Rpb24obmFtZSwgdHdlZW4pIHtcbiAgICB2YXIgaWQgPSB0aGlzLmlkLCBucyA9IHRoaXMubmFtZXNwYWNlO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikgcmV0dXJuIHRoaXMubm9kZSgpW25zXVtpZF0udHdlZW4uZ2V0KG5hbWUpO1xuICAgIHJldHVybiBkM19zZWxlY3Rpb25fZWFjaCh0aGlzLCB0d2VlbiA9PSBudWxsID8gZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZVtuc11baWRdLnR3ZWVuLnJlbW92ZShuYW1lKTtcbiAgICB9IDogZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZVtuc11baWRdLnR3ZWVuLnNldChuYW1lLCB0d2Vlbik7XG4gICAgfSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RyYW5zaXRpb25fdHdlZW4oZ3JvdXBzLCBuYW1lLCB2YWx1ZSwgdHdlZW4pIHtcbiAgICB2YXIgaWQgPSBncm91cHMuaWQsIG5zID0gZ3JvdXBzLm5hbWVzcGFjZTtcbiAgICByZXR1cm4gZDNfc2VsZWN0aW9uX2VhY2goZ3JvdXBzLCB0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIiA/IGZ1bmN0aW9uKG5vZGUsIGksIGopIHtcbiAgICAgIG5vZGVbbnNdW2lkXS50d2Vlbi5zZXQobmFtZSwgdHdlZW4odmFsdWUuY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKSkpO1xuICAgIH0gOiAodmFsdWUgPSB0d2Vlbih2YWx1ZSksIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIG5vZGVbbnNdW2lkXS50d2Vlbi5zZXQobmFtZSwgdmFsdWUpO1xuICAgIH0pKTtcbiAgfVxuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmF0dHIgPSBmdW5jdGlvbihuYW1lTlMsIHZhbHVlKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICBmb3IgKHZhbHVlIGluIG5hbWVOUykgdGhpcy5hdHRyKHZhbHVlLCBuYW1lTlNbdmFsdWVdKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICB2YXIgaW50ZXJwb2xhdGUgPSBuYW1lTlMgPT0gXCJ0cmFuc2Zvcm1cIiA/IGQzX2ludGVycG9sYXRlVHJhbnNmb3JtIDogZDNfaW50ZXJwb2xhdGUsIG5hbWUgPSBkMy5ucy5xdWFsaWZ5KG5hbWVOUyk7XG4gICAgZnVuY3Rpb24gYXR0ck51bGwoKSB7XG4gICAgICB0aGlzLnJlbW92ZUF0dHJpYnV0ZShuYW1lKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXR0ck51bGxOUygpIHtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGF0dHJUd2VlbihiKSB7XG4gICAgICByZXR1cm4gYiA9PSBudWxsID8gYXR0ck51bGwgOiAoYiArPSBcIlwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGEgPSB0aGlzLmdldEF0dHJpYnV0ZShuYW1lKSwgaTtcbiAgICAgICAgcmV0dXJuIGEgIT09IGIgJiYgKGkgPSBpbnRlcnBvbGF0ZShhLCBiKSwgZnVuY3Rpb24odCkge1xuICAgICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKG5hbWUsIGkodCkpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyVHdlZW5OUyhiKSB7XG4gICAgICByZXR1cm4gYiA9PSBudWxsID8gYXR0ck51bGxOUyA6IChiICs9IFwiXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYSA9IHRoaXMuZ2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCksIGk7XG4gICAgICAgIHJldHVybiBhICE9PSBiICYmIChpID0gaW50ZXJwb2xhdGUoYSwgYiksIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZU5TKG5hbWUuc3BhY2UsIG5hbWUubG9jYWwsIGkodCkpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gZDNfdHJhbnNpdGlvbl90d2Vlbih0aGlzLCBcImF0dHIuXCIgKyBuYW1lTlMsIHZhbHVlLCBuYW1lLmxvY2FsID8gYXR0clR3ZWVuTlMgOiBhdHRyVHdlZW4pO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmF0dHJUd2VlbiA9IGZ1bmN0aW9uKG5hbWVOUywgdHdlZW4pIHtcbiAgICB2YXIgbmFtZSA9IGQzLm5zLnF1YWxpZnkobmFtZU5TKTtcbiAgICBmdW5jdGlvbiBhdHRyVHdlZW4oZCwgaSkge1xuICAgICAgdmFyIGYgPSB0d2Vlbi5jYWxsKHRoaXMsIGQsIGksIHRoaXMuZ2V0QXR0cmlidXRlKG5hbWUpKTtcbiAgICAgIHJldHVybiBmICYmIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUobmFtZSwgZih0KSk7XG4gICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBhdHRyVHdlZW5OUyhkLCBpKSB7XG4gICAgICB2YXIgZiA9IHR3ZWVuLmNhbGwodGhpcywgZCwgaSwgdGhpcy5nZXRBdHRyaWJ1dGVOUyhuYW1lLnNwYWNlLCBuYW1lLmxvY2FsKSk7XG4gICAgICByZXR1cm4gZiAmJiBmdW5jdGlvbih0KSB7XG4gICAgICAgIHRoaXMuc2V0QXR0cmlidXRlTlMobmFtZS5zcGFjZSwgbmFtZS5sb2NhbCwgZih0KSk7XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy50d2VlbihcImF0dHIuXCIgKyBuYW1lTlMsIG5hbWUubG9jYWwgPyBhdHRyVHdlZW5OUyA6IGF0dHJUd2Vlbik7XG4gIH07XG4gIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUuc3R5bGUgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSwgcHJpb3JpdHkpIHtcbiAgICB2YXIgbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgaWYgKG4gPCAzKSB7XG4gICAgICBpZiAodHlwZW9mIG5hbWUgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgaWYgKG4gPCAyKSB2YWx1ZSA9IFwiXCI7XG4gICAgICAgIGZvciAocHJpb3JpdHkgaW4gbmFtZSkgdGhpcy5zdHlsZShwcmlvcml0eSwgbmFtZVtwcmlvcml0eV0sIHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG4gICAgICBwcmlvcml0eSA9IFwiXCI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHN0eWxlTnVsbCgpIHtcbiAgICAgIHRoaXMuc3R5bGUucmVtb3ZlUHJvcGVydHkobmFtZSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHN0eWxlU3RyaW5nKGIpIHtcbiAgICAgIHJldHVybiBiID09IG51bGwgPyBzdHlsZU51bGwgOiAoYiArPSBcIlwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGEgPSBkM193aW5kb3codGhpcykuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLCBudWxsKS5nZXRQcm9wZXJ0eVZhbHVlKG5hbWUpLCBpO1xuICAgICAgICByZXR1cm4gYSAhPT0gYiAmJiAoaSA9IGQzX2ludGVycG9sYXRlKGEsIGIpLCBmdW5jdGlvbih0KSB7XG4gICAgICAgICAgdGhpcy5zdHlsZS5zZXRQcm9wZXJ0eShuYW1lLCBpKHQpLCBwcmlvcml0eSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBkM190cmFuc2l0aW9uX3R3ZWVuKHRoaXMsIFwic3R5bGUuXCIgKyBuYW1lLCB2YWx1ZSwgc3R5bGVTdHJpbmcpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnN0eWxlVHdlZW4gPSBmdW5jdGlvbihuYW1lLCB0d2VlbiwgcHJpb3JpdHkpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDMpIHByaW9yaXR5ID0gXCJcIjtcbiAgICBmdW5jdGlvbiBzdHlsZVR3ZWVuKGQsIGkpIHtcbiAgICAgIHZhciBmID0gdHdlZW4uY2FsbCh0aGlzLCBkLCBpLCBkM193aW5kb3codGhpcykuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLCBudWxsKS5nZXRQcm9wZXJ0eVZhbHVlKG5hbWUpKTtcbiAgICAgIHJldHVybiBmICYmIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgdGhpcy5zdHlsZS5zZXRQcm9wZXJ0eShuYW1lLCBmKHQpLCBwcmlvcml0eSk7XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy50d2VlbihcInN0eWxlLlwiICsgbmFtZSwgc3R5bGVUd2Vlbik7XG4gIH07XG4gIGQzX3RyYW5zaXRpb25Qcm90b3R5cGUudGV4dCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIGQzX3RyYW5zaXRpb25fdHdlZW4odGhpcywgXCJ0ZXh0XCIsIHZhbHVlLCBkM190cmFuc2l0aW9uX3RleHQpO1xuICB9O1xuICBmdW5jdGlvbiBkM190cmFuc2l0aW9uX3RleHQoYikge1xuICAgIGlmIChiID09IG51bGwpIGIgPSBcIlwiO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMudGV4dENvbnRlbnQgPSBiO1xuICAgIH07XG4gIH1cbiAgZDNfdHJhbnNpdGlvblByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbnMgPSB0aGlzLm5hbWVzcGFjZTtcbiAgICByZXR1cm4gdGhpcy5lYWNoKFwiZW5kLnRyYW5zaXRpb25cIiwgZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcDtcbiAgICAgIGlmICh0aGlzW25zXS5jb3VudCA8IDIgJiYgKHAgPSB0aGlzLnBhcmVudE5vZGUpKSBwLnJlbW92ZUNoaWxkKHRoaXMpO1xuICAgIH0pO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmVhc2UgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHZhciBpZCA9IHRoaXMuaWQsIG5zID0gdGhpcy5uYW1lc3BhY2U7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAxKSByZXR1cm4gdGhpcy5ub2RlKClbbnNdW2lkXS5lYXNlO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwiZnVuY3Rpb25cIikgdmFsdWUgPSBkMy5lYXNlLmFwcGx5KGQzLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiBkM19zZWxlY3Rpb25fZWFjaCh0aGlzLCBmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlW25zXVtpZF0uZWFzZSA9IHZhbHVlO1xuICAgIH0pO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmRlbGF5ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICB2YXIgaWQgPSB0aGlzLmlkLCBucyA9IHRoaXMubmFtZXNwYWNlO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMSkgcmV0dXJuIHRoaXMubm9kZSgpW25zXVtpZF0uZGVsYXk7XG4gICAgcmV0dXJuIGQzX3NlbGVjdGlvbl9lYWNoKHRoaXMsIHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gZnVuY3Rpb24obm9kZSwgaSwgaikge1xuICAgICAgbm9kZVtuc11baWRdLmRlbGF5ID0gK3ZhbHVlLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgaik7XG4gICAgfSA6ICh2YWx1ZSA9ICt2YWx1ZSwgZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZVtuc11baWRdLmRlbGF5ID0gdmFsdWU7XG4gICAgfSkpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmR1cmF0aW9uID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICB2YXIgaWQgPSB0aGlzLmlkLCBucyA9IHRoaXMubmFtZXNwYWNlO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMSkgcmV0dXJuIHRoaXMubm9kZSgpW25zXVtpZF0uZHVyYXRpb247XG4gICAgcmV0dXJuIGQzX3NlbGVjdGlvbl9lYWNoKHRoaXMsIHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiID8gZnVuY3Rpb24obm9kZSwgaSwgaikge1xuICAgICAgbm9kZVtuc11baWRdLmR1cmF0aW9uID0gTWF0aC5tYXgoMSwgdmFsdWUuY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBqKSk7XG4gICAgfSA6ICh2YWx1ZSA9IE1hdGgubWF4KDEsIHZhbHVlKSwgZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZVtuc11baWRdLmR1cmF0aW9uID0gdmFsdWU7XG4gICAgfSkpO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLmVhY2ggPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICAgIHZhciBpZCA9IHRoaXMuaWQsIG5zID0gdGhpcy5uYW1lc3BhY2U7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgICB2YXIgaW5oZXJpdCA9IGQzX3RyYW5zaXRpb25Jbmhlcml0LCBpbmhlcml0SWQgPSBkM190cmFuc2l0aW9uSW5oZXJpdElkO1xuICAgICAgdHJ5IHtcbiAgICAgICAgZDNfdHJhbnNpdGlvbkluaGVyaXRJZCA9IGlkO1xuICAgICAgICBkM19zZWxlY3Rpb25fZWFjaCh0aGlzLCBmdW5jdGlvbihub2RlLCBpLCBqKSB7XG4gICAgICAgICAgZDNfdHJhbnNpdGlvbkluaGVyaXQgPSBub2RlW25zXVtpZF07XG4gICAgICAgICAgdHlwZS5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGksIGopO1xuICAgICAgICB9KTtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGQzX3RyYW5zaXRpb25Jbmhlcml0ID0gaW5oZXJpdDtcbiAgICAgICAgZDNfdHJhbnNpdGlvbkluaGVyaXRJZCA9IGluaGVyaXRJZDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZDNfc2VsZWN0aW9uX2VhY2godGhpcywgZnVuY3Rpb24obm9kZSkge1xuICAgICAgICB2YXIgdHJhbnNpdGlvbiA9IG5vZGVbbnNdW2lkXTtcbiAgICAgICAgKHRyYW5zaXRpb24uZXZlbnQgfHwgKHRyYW5zaXRpb24uZXZlbnQgPSBkMy5kaXNwYXRjaChcInN0YXJ0XCIsIFwiZW5kXCIsIFwiaW50ZXJydXB0XCIpKSkub24odHlwZSwgbGlzdGVuZXIpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9O1xuICBkM190cmFuc2l0aW9uUHJvdG90eXBlLnRyYW5zaXRpb24gPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaWQwID0gdGhpcy5pZCwgaWQxID0gKytkM190cmFuc2l0aW9uSWQsIG5zID0gdGhpcy5uYW1lc3BhY2UsIHN1Ymdyb3VwcyA9IFtdLCBzdWJncm91cCwgZ3JvdXAsIG5vZGUsIHRyYW5zaXRpb247XG4gICAgZm9yICh2YXIgaiA9IDAsIG0gPSB0aGlzLmxlbmd0aDsgaiA8IG07IGorKykge1xuICAgICAgc3ViZ3JvdXBzLnB1c2goc3ViZ3JvdXAgPSBbXSk7XG4gICAgICBmb3IgKHZhciBncm91cCA9IHRoaXNbal0sIGkgPSAwLCBuID0gZ3JvdXAubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIHtcbiAgICAgICAgICB0cmFuc2l0aW9uID0gbm9kZVtuc11baWQwXTtcbiAgICAgICAgICBkM190cmFuc2l0aW9uTm9kZShub2RlLCBpLCBucywgaWQxLCB7XG4gICAgICAgICAgICB0aW1lOiB0cmFuc2l0aW9uLnRpbWUsXG4gICAgICAgICAgICBlYXNlOiB0cmFuc2l0aW9uLmVhc2UsXG4gICAgICAgICAgICBkZWxheTogdHJhbnNpdGlvbi5kZWxheSArIHRyYW5zaXRpb24uZHVyYXRpb24sXG4gICAgICAgICAgICBkdXJhdGlvbjogdHJhbnNpdGlvbi5kdXJhdGlvblxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHN1Ymdyb3VwLnB1c2gobm9kZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBkM190cmFuc2l0aW9uKHN1Ymdyb3VwcywgbnMsIGlkMSk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX3RyYW5zaXRpb25OYW1lc3BhY2UobmFtZSkge1xuICAgIHJldHVybiBuYW1lID09IG51bGwgPyBcIl9fdHJhbnNpdGlvbl9fXCIgOiBcIl9fdHJhbnNpdGlvbl9cIiArIG5hbWUgKyBcIl9fXCI7XG4gIH1cbiAgZnVuY3Rpb24gZDNfdHJhbnNpdGlvbk5vZGUobm9kZSwgaSwgbnMsIGlkLCBpbmhlcml0KSB7XG4gICAgdmFyIGxvY2sgPSBub2RlW25zXSB8fCAobm9kZVtuc10gPSB7XG4gICAgICBhY3RpdmU6IDAsXG4gICAgICBjb3VudDogMFxuICAgIH0pLCB0cmFuc2l0aW9uID0gbG9ja1tpZF0sIHRpbWUsIHRpbWVyLCBkdXJhdGlvbiwgZWFzZSwgdHdlZW5zO1xuICAgIGZ1bmN0aW9uIHNjaGVkdWxlKGVsYXBzZWQpIHtcbiAgICAgIHZhciBkZWxheSA9IHRyYW5zaXRpb24uZGVsYXk7XG4gICAgICB0aW1lci50ID0gZGVsYXkgKyB0aW1lO1xuICAgICAgaWYgKGRlbGF5IDw9IGVsYXBzZWQpIHJldHVybiBzdGFydChlbGFwc2VkIC0gZGVsYXkpO1xuICAgICAgdGltZXIuYyA9IHN0YXJ0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdGFydChlbGFwc2VkKSB7XG4gICAgICB2YXIgYWN0aXZlSWQgPSBsb2NrLmFjdGl2ZSwgYWN0aXZlID0gbG9ja1thY3RpdmVJZF07XG4gICAgICBpZiAoYWN0aXZlKSB7XG4gICAgICAgIGFjdGl2ZS50aW1lci5jID0gbnVsbDtcbiAgICAgICAgYWN0aXZlLnRpbWVyLnQgPSBOYU47XG4gICAgICAgIC0tbG9jay5jb3VudDtcbiAgICAgICAgZGVsZXRlIGxvY2tbYWN0aXZlSWRdO1xuICAgICAgICBhY3RpdmUuZXZlbnQgJiYgYWN0aXZlLmV2ZW50LmludGVycnVwdC5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGFjdGl2ZS5pbmRleCk7XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBjYW5jZWxJZCBpbiBsb2NrKSB7XG4gICAgICAgIGlmICgrY2FuY2VsSWQgPCBpZCkge1xuICAgICAgICAgIHZhciBjYW5jZWwgPSBsb2NrW2NhbmNlbElkXTtcbiAgICAgICAgICBjYW5jZWwudGltZXIuYyA9IG51bGw7XG4gICAgICAgICAgY2FuY2VsLnRpbWVyLnQgPSBOYU47XG4gICAgICAgICAgLS1sb2NrLmNvdW50O1xuICAgICAgICAgIGRlbGV0ZSBsb2NrW2NhbmNlbElkXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGltZXIuYyA9IHRpY2s7XG4gICAgICBkM190aW1lcihmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRpbWVyLmMgJiYgdGljayhlbGFwc2VkIHx8IDEpKSB7XG4gICAgICAgICAgdGltZXIuYyA9IG51bGw7XG4gICAgICAgICAgdGltZXIudCA9IE5hTjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH0sIDAsIHRpbWUpO1xuICAgICAgbG9jay5hY3RpdmUgPSBpZDtcbiAgICAgIHRyYW5zaXRpb24uZXZlbnQgJiYgdHJhbnNpdGlvbi5ldmVudC5zdGFydC5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGkpO1xuICAgICAgdHdlZW5zID0gW107XG4gICAgICB0cmFuc2l0aW9uLnR3ZWVuLmZvckVhY2goZnVuY3Rpb24oa2V5LCB2YWx1ZSkge1xuICAgICAgICBpZiAodmFsdWUgPSB2YWx1ZS5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGkpKSB7XG4gICAgICAgICAgdHdlZW5zLnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGVhc2UgPSB0cmFuc2l0aW9uLmVhc2U7XG4gICAgICBkdXJhdGlvbiA9IHRyYW5zaXRpb24uZHVyYXRpb247XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRpY2soZWxhcHNlZCkge1xuICAgICAgdmFyIHQgPSBlbGFwc2VkIC8gZHVyYXRpb24sIGUgPSBlYXNlKHQpLCBuID0gdHdlZW5zLmxlbmd0aDtcbiAgICAgIHdoaWxlIChuID4gMCkge1xuICAgICAgICB0d2VlbnNbLS1uXS5jYWxsKG5vZGUsIGUpO1xuICAgICAgfVxuICAgICAgaWYgKHQgPj0gMSkge1xuICAgICAgICB0cmFuc2l0aW9uLmV2ZW50ICYmIHRyYW5zaXRpb24uZXZlbnQuZW5kLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSk7XG4gICAgICAgIGlmICgtLWxvY2suY291bnQpIGRlbGV0ZSBsb2NrW2lkXTsgZWxzZSBkZWxldGUgbm9kZVtuc107XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIXRyYW5zaXRpb24pIHtcbiAgICAgIHRpbWUgPSBpbmhlcml0LnRpbWU7XG4gICAgICB0aW1lciA9IGQzX3RpbWVyKHNjaGVkdWxlLCAwLCB0aW1lKTtcbiAgICAgIHRyYW5zaXRpb24gPSBsb2NrW2lkXSA9IHtcbiAgICAgICAgdHdlZW46IG5ldyBkM19NYXAoKSxcbiAgICAgICAgdGltZTogdGltZSxcbiAgICAgICAgdGltZXI6IHRpbWVyLFxuICAgICAgICBkZWxheTogaW5oZXJpdC5kZWxheSxcbiAgICAgICAgZHVyYXRpb246IGluaGVyaXQuZHVyYXRpb24sXG4gICAgICAgIGVhc2U6IGluaGVyaXQuZWFzZSxcbiAgICAgICAgaW5kZXg6IGlcbiAgICAgIH07XG4gICAgICBpbmhlcml0ID0gbnVsbDtcbiAgICAgICsrbG9jay5jb3VudDtcbiAgICB9XG4gIH1cbiAgZDMuc3ZnLmF4aXMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc2NhbGUgPSBkMy5zY2FsZS5saW5lYXIoKSwgb3JpZW50ID0gZDNfc3ZnX2F4aXNEZWZhdWx0T3JpZW50LCBpbm5lclRpY2tTaXplID0gNiwgb3V0ZXJUaWNrU2l6ZSA9IDYsIHRpY2tQYWRkaW5nID0gMywgdGlja0FyZ3VtZW50c18gPSBbIDEwIF0sIHRpY2tWYWx1ZXMgPSBudWxsLCB0aWNrRm9ybWF0XztcbiAgICBmdW5jdGlvbiBheGlzKGcpIHtcbiAgICAgIGcuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGcgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBzY2FsZTAgPSB0aGlzLl9fY2hhcnRfXyB8fCBzY2FsZSwgc2NhbGUxID0gdGhpcy5fX2NoYXJ0X18gPSBzY2FsZS5jb3B5KCk7XG4gICAgICAgIHZhciB0aWNrcyA9IHRpY2tWYWx1ZXMgPT0gbnVsbCA/IHNjYWxlMS50aWNrcyA/IHNjYWxlMS50aWNrcy5hcHBseShzY2FsZTEsIHRpY2tBcmd1bWVudHNfKSA6IHNjYWxlMS5kb21haW4oKSA6IHRpY2tWYWx1ZXMsIHRpY2tGb3JtYXQgPSB0aWNrRm9ybWF0XyA9PSBudWxsID8gc2NhbGUxLnRpY2tGb3JtYXQgPyBzY2FsZTEudGlja0Zvcm1hdC5hcHBseShzY2FsZTEsIHRpY2tBcmd1bWVudHNfKSA6IGQzX2lkZW50aXR5IDogdGlja0Zvcm1hdF8sIHRpY2sgPSBnLnNlbGVjdEFsbChcIi50aWNrXCIpLmRhdGEodGlja3MsIHNjYWxlMSksIHRpY2tFbnRlciA9IHRpY2suZW50ZXIoKS5pbnNlcnQoXCJnXCIsIFwiLmRvbWFpblwiKS5hdHRyKFwiY2xhc3NcIiwgXCJ0aWNrXCIpLnN0eWxlKFwib3BhY2l0eVwiLCDOtSksIHRpY2tFeGl0ID0gZDMudHJhbnNpdGlvbih0aWNrLmV4aXQoKSkuc3R5bGUoXCJvcGFjaXR5XCIsIM61KS5yZW1vdmUoKSwgdGlja1VwZGF0ZSA9IGQzLnRyYW5zaXRpb24odGljay5vcmRlcigpKS5zdHlsZShcIm9wYWNpdHlcIiwgMSksIHRpY2tTcGFjaW5nID0gTWF0aC5tYXgoaW5uZXJUaWNrU2l6ZSwgMCkgKyB0aWNrUGFkZGluZywgdGlja1RyYW5zZm9ybTtcbiAgICAgICAgdmFyIHJhbmdlID0gZDNfc2NhbGVSYW5nZShzY2FsZTEpLCBwYXRoID0gZy5zZWxlY3RBbGwoXCIuZG9tYWluXCIpLmRhdGEoWyAwIF0pLCBwYXRoVXBkYXRlID0gKHBhdGguZW50ZXIoKS5hcHBlbmQoXCJwYXRoXCIpLmF0dHIoXCJjbGFzc1wiLCBcImRvbWFpblwiKSwgXG4gICAgICAgIGQzLnRyYW5zaXRpb24ocGF0aCkpO1xuICAgICAgICB0aWNrRW50ZXIuYXBwZW5kKFwibGluZVwiKTtcbiAgICAgICAgdGlja0VudGVyLmFwcGVuZChcInRleHRcIik7XG4gICAgICAgIHZhciBsaW5lRW50ZXIgPSB0aWNrRW50ZXIuc2VsZWN0KFwibGluZVwiKSwgbGluZVVwZGF0ZSA9IHRpY2tVcGRhdGUuc2VsZWN0KFwibGluZVwiKSwgdGV4dCA9IHRpY2suc2VsZWN0KFwidGV4dFwiKS50ZXh0KHRpY2tGb3JtYXQpLCB0ZXh0RW50ZXIgPSB0aWNrRW50ZXIuc2VsZWN0KFwidGV4dFwiKSwgdGV4dFVwZGF0ZSA9IHRpY2tVcGRhdGUuc2VsZWN0KFwidGV4dFwiKSwgc2lnbiA9IG9yaWVudCA9PT0gXCJ0b3BcIiB8fCBvcmllbnQgPT09IFwibGVmdFwiID8gLTEgOiAxLCB4MSwgeDIsIHkxLCB5MjtcbiAgICAgICAgaWYgKG9yaWVudCA9PT0gXCJib3R0b21cIiB8fCBvcmllbnQgPT09IFwidG9wXCIpIHtcbiAgICAgICAgICB0aWNrVHJhbnNmb3JtID0gZDNfc3ZnX2F4aXNYLCB4MSA9IFwieFwiLCB5MSA9IFwieVwiLCB4MiA9IFwieDJcIiwgeTIgPSBcInkyXCI7XG4gICAgICAgICAgdGV4dC5hdHRyKFwiZHlcIiwgc2lnbiA8IDAgPyBcIjBlbVwiIDogXCIuNzFlbVwiKS5zdHlsZShcInRleHQtYW5jaG9yXCIsIFwibWlkZGxlXCIpO1xuICAgICAgICAgIHBhdGhVcGRhdGUuYXR0cihcImRcIiwgXCJNXCIgKyByYW5nZVswXSArIFwiLFwiICsgc2lnbiAqIG91dGVyVGlja1NpemUgKyBcIlYwSFwiICsgcmFuZ2VbMV0gKyBcIlZcIiArIHNpZ24gKiBvdXRlclRpY2tTaXplKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aWNrVHJhbnNmb3JtID0gZDNfc3ZnX2F4aXNZLCB4MSA9IFwieVwiLCB5MSA9IFwieFwiLCB4MiA9IFwieTJcIiwgeTIgPSBcIngyXCI7XG4gICAgICAgICAgdGV4dC5hdHRyKFwiZHlcIiwgXCIuMzJlbVwiKS5zdHlsZShcInRleHQtYW5jaG9yXCIsIHNpZ24gPCAwID8gXCJlbmRcIiA6IFwic3RhcnRcIik7XG4gICAgICAgICAgcGF0aFVwZGF0ZS5hdHRyKFwiZFwiLCBcIk1cIiArIHNpZ24gKiBvdXRlclRpY2tTaXplICsgXCIsXCIgKyByYW5nZVswXSArIFwiSDBWXCIgKyByYW5nZVsxXSArIFwiSFwiICsgc2lnbiAqIG91dGVyVGlja1NpemUpO1xuICAgICAgICB9XG4gICAgICAgIGxpbmVFbnRlci5hdHRyKHkyLCBzaWduICogaW5uZXJUaWNrU2l6ZSk7XG4gICAgICAgIHRleHRFbnRlci5hdHRyKHkxLCBzaWduICogdGlja1NwYWNpbmcpO1xuICAgICAgICBsaW5lVXBkYXRlLmF0dHIoeDIsIDApLmF0dHIoeTIsIHNpZ24gKiBpbm5lclRpY2tTaXplKTtcbiAgICAgICAgdGV4dFVwZGF0ZS5hdHRyKHgxLCAwKS5hdHRyKHkxLCBzaWduICogdGlja1NwYWNpbmcpO1xuICAgICAgICBpZiAoc2NhbGUxLnJhbmdlQmFuZCkge1xuICAgICAgICAgIHZhciB4ID0gc2NhbGUxLCBkeCA9IHgucmFuZ2VCYW5kKCkgLyAyO1xuICAgICAgICAgIHNjYWxlMCA9IHNjYWxlMSA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiB4KGQpICsgZHg7XG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIGlmIChzY2FsZTAucmFuZ2VCYW5kKSB7XG4gICAgICAgICAgc2NhbGUwID0gc2NhbGUxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRpY2tFeGl0LmNhbGwodGlja1RyYW5zZm9ybSwgc2NhbGUxLCBzY2FsZTApO1xuICAgICAgICB9XG4gICAgICAgIHRpY2tFbnRlci5jYWxsKHRpY2tUcmFuc2Zvcm0sIHNjYWxlMCwgc2NhbGUxKTtcbiAgICAgICAgdGlja1VwZGF0ZS5jYWxsKHRpY2tUcmFuc2Zvcm0sIHNjYWxlMSwgc2NhbGUxKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBheGlzLnNjYWxlID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gc2NhbGU7XG4gICAgICBzY2FsZSA9IHg7XG4gICAgICByZXR1cm4gYXhpcztcbiAgICB9O1xuICAgIGF4aXMub3JpZW50ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gb3JpZW50O1xuICAgICAgb3JpZW50ID0geCBpbiBkM19zdmdfYXhpc09yaWVudHMgPyB4ICsgXCJcIiA6IGQzX3N2Z19heGlzRGVmYXVsdE9yaWVudDtcbiAgICAgIHJldHVybiBheGlzO1xuICAgIH07XG4gICAgYXhpcy50aWNrcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGlja0FyZ3VtZW50c187XG4gICAgICB0aWNrQXJndW1lbnRzXyA9IGQzX2FycmF5KGFyZ3VtZW50cyk7XG4gICAgICByZXR1cm4gYXhpcztcbiAgICB9O1xuICAgIGF4aXMudGlja1ZhbHVlcyA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHRpY2tWYWx1ZXM7XG4gICAgICB0aWNrVmFsdWVzID0geDtcbiAgICAgIHJldHVybiBheGlzO1xuICAgIH07XG4gICAgYXhpcy50aWNrRm9ybWF0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGlja0Zvcm1hdF87XG4gICAgICB0aWNrRm9ybWF0XyA9IHg7XG4gICAgICByZXR1cm4gYXhpcztcbiAgICB9O1xuICAgIGF4aXMudGlja1NpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICB2YXIgbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICBpZiAoIW4pIHJldHVybiBpbm5lclRpY2tTaXplO1xuICAgICAgaW5uZXJUaWNrU2l6ZSA9ICt4O1xuICAgICAgb3V0ZXJUaWNrU2l6ZSA9ICthcmd1bWVudHNbbiAtIDFdO1xuICAgICAgcmV0dXJuIGF4aXM7XG4gICAgfTtcbiAgICBheGlzLmlubmVyVGlja1NpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBpbm5lclRpY2tTaXplO1xuICAgICAgaW5uZXJUaWNrU2l6ZSA9ICt4O1xuICAgICAgcmV0dXJuIGF4aXM7XG4gICAgfTtcbiAgICBheGlzLm91dGVyVGlja1NpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBvdXRlclRpY2tTaXplO1xuICAgICAgb3V0ZXJUaWNrU2l6ZSA9ICt4O1xuICAgICAgcmV0dXJuIGF4aXM7XG4gICAgfTtcbiAgICBheGlzLnRpY2tQYWRkaW5nID0gZnVuY3Rpb24oeCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gdGlja1BhZGRpbmc7XG4gICAgICB0aWNrUGFkZGluZyA9ICt4O1xuICAgICAgcmV0dXJuIGF4aXM7XG4gICAgfTtcbiAgICBheGlzLnRpY2tTdWJkaXZpZGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoICYmIGF4aXM7XG4gICAgfTtcbiAgICByZXR1cm4gYXhpcztcbiAgfTtcbiAgdmFyIGQzX3N2Z19heGlzRGVmYXVsdE9yaWVudCA9IFwiYm90dG9tXCIsIGQzX3N2Z19heGlzT3JpZW50cyA9IHtcbiAgICB0b3A6IDEsXG4gICAgcmlnaHQ6IDEsXG4gICAgYm90dG9tOiAxLFxuICAgIGxlZnQ6IDFcbiAgfTtcbiAgZnVuY3Rpb24gZDNfc3ZnX2F4aXNYKHNlbGVjdGlvbiwgeDAsIHgxKSB7XG4gICAgc2VsZWN0aW9uLmF0dHIoXCJ0cmFuc2Zvcm1cIiwgZnVuY3Rpb24oZCkge1xuICAgICAgdmFyIHYwID0geDAoZCk7XG4gICAgICByZXR1cm4gXCJ0cmFuc2xhdGUoXCIgKyAoaXNGaW5pdGUodjApID8gdjAgOiB4MShkKSkgKyBcIiwwKVwiO1xuICAgIH0pO1xuICB9XG4gIGZ1bmN0aW9uIGQzX3N2Z19heGlzWShzZWxlY3Rpb24sIHkwLCB5MSkge1xuICAgIHNlbGVjdGlvbi5hdHRyKFwidHJhbnNmb3JtXCIsIGZ1bmN0aW9uKGQpIHtcbiAgICAgIHZhciB2MCA9IHkwKGQpO1xuICAgICAgcmV0dXJuIFwidHJhbnNsYXRlKDAsXCIgKyAoaXNGaW5pdGUodjApID8gdjAgOiB5MShkKSkgKyBcIilcIjtcbiAgICB9KTtcbiAgfVxuICBkMy5zdmcuYnJ1c2ggPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZXZlbnQgPSBkM19ldmVudERpc3BhdGNoKGJydXNoLCBcImJydXNoc3RhcnRcIiwgXCJicnVzaFwiLCBcImJydXNoZW5kXCIpLCB4ID0gbnVsbCwgeSA9IG51bGwsIHhFeHRlbnQgPSBbIDAsIDAgXSwgeUV4dGVudCA9IFsgMCwgMCBdLCB4RXh0ZW50RG9tYWluLCB5RXh0ZW50RG9tYWluLCB4Q2xhbXAgPSB0cnVlLCB5Q2xhbXAgPSB0cnVlLCByZXNpemVzID0gZDNfc3ZnX2JydXNoUmVzaXplc1swXTtcbiAgICBmdW5jdGlvbiBicnVzaChnKSB7XG4gICAgICBnLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBnID0gZDMuc2VsZWN0KHRoaXMpLnN0eWxlKFwicG9pbnRlci1ldmVudHNcIiwgXCJhbGxcIikuc3R5bGUoXCItd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3JcIiwgXCJyZ2JhKDAsMCwwLDApXCIpLm9uKFwibW91c2Vkb3duLmJydXNoXCIsIGJydXNoc3RhcnQpLm9uKFwidG91Y2hzdGFydC5icnVzaFwiLCBicnVzaHN0YXJ0KTtcbiAgICAgICAgdmFyIGJhY2tncm91bmQgPSBnLnNlbGVjdEFsbChcIi5iYWNrZ3JvdW5kXCIpLmRhdGEoWyAwIF0pO1xuICAgICAgICBiYWNrZ3JvdW5kLmVudGVyKCkuYXBwZW5kKFwicmVjdFwiKS5hdHRyKFwiY2xhc3NcIiwgXCJiYWNrZ3JvdW5kXCIpLnN0eWxlKFwidmlzaWJpbGl0eVwiLCBcImhpZGRlblwiKS5zdHlsZShcImN1cnNvclwiLCBcImNyb3NzaGFpclwiKTtcbiAgICAgICAgZy5zZWxlY3RBbGwoXCIuZXh0ZW50XCIpLmRhdGEoWyAwIF0pLmVudGVyKCkuYXBwZW5kKFwicmVjdFwiKS5hdHRyKFwiY2xhc3NcIiwgXCJleHRlbnRcIikuc3R5bGUoXCJjdXJzb3JcIiwgXCJtb3ZlXCIpO1xuICAgICAgICB2YXIgcmVzaXplID0gZy5zZWxlY3RBbGwoXCIucmVzaXplXCIpLmRhdGEocmVzaXplcywgZDNfaWRlbnRpdHkpO1xuICAgICAgICByZXNpemUuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICByZXNpemUuZW50ZXIoKS5hcHBlbmQoXCJnXCIpLmF0dHIoXCJjbGFzc1wiLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgcmV0dXJuIFwicmVzaXplIFwiICsgZDtcbiAgICAgICAgfSkuc3R5bGUoXCJjdXJzb3JcIiwgZnVuY3Rpb24oZCkge1xuICAgICAgICAgIHJldHVybiBkM19zdmdfYnJ1c2hDdXJzb3JbZF07XG4gICAgICAgIH0pLmFwcGVuZChcInJlY3RcIikuYXR0cihcInhcIiwgZnVuY3Rpb24oZCkge1xuICAgICAgICAgIHJldHVybiAvW2V3XSQvLnRlc3QoZCkgPyAtMyA6IG51bGw7XG4gICAgICAgIH0pLmF0dHIoXCJ5XCIsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICByZXR1cm4gL15bbnNdLy50ZXN0KGQpID8gLTMgOiBudWxsO1xuICAgICAgICB9KS5hdHRyKFwid2lkdGhcIiwgNikuYXR0cihcImhlaWdodFwiLCA2KS5zdHlsZShcInZpc2liaWxpdHlcIiwgXCJoaWRkZW5cIik7XG4gICAgICAgIHJlc2l6ZS5zdHlsZShcImRpc3BsYXlcIiwgYnJ1c2guZW1wdHkoKSA/IFwibm9uZVwiIDogbnVsbCk7XG4gICAgICAgIHZhciBnVXBkYXRlID0gZDMudHJhbnNpdGlvbihnKSwgYmFja2dyb3VuZFVwZGF0ZSA9IGQzLnRyYW5zaXRpb24oYmFja2dyb3VuZCksIHJhbmdlO1xuICAgICAgICBpZiAoeCkge1xuICAgICAgICAgIHJhbmdlID0gZDNfc2NhbGVSYW5nZSh4KTtcbiAgICAgICAgICBiYWNrZ3JvdW5kVXBkYXRlLmF0dHIoXCJ4XCIsIHJhbmdlWzBdKS5hdHRyKFwid2lkdGhcIiwgcmFuZ2VbMV0gLSByYW5nZVswXSk7XG4gICAgICAgICAgcmVkcmF3WChnVXBkYXRlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoeSkge1xuICAgICAgICAgIHJhbmdlID0gZDNfc2NhbGVSYW5nZSh5KTtcbiAgICAgICAgICBiYWNrZ3JvdW5kVXBkYXRlLmF0dHIoXCJ5XCIsIHJhbmdlWzBdKS5hdHRyKFwiaGVpZ2h0XCIsIHJhbmdlWzFdIC0gcmFuZ2VbMF0pO1xuICAgICAgICAgIHJlZHJhd1koZ1VwZGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVkcmF3KGdVcGRhdGUpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGJydXNoLmV2ZW50ID0gZnVuY3Rpb24oZykge1xuICAgICAgZy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZXZlbnRfID0gZXZlbnQub2YodGhpcywgYXJndW1lbnRzKSwgZXh0ZW50MSA9IHtcbiAgICAgICAgICB4OiB4RXh0ZW50LFxuICAgICAgICAgIHk6IHlFeHRlbnQsXG4gICAgICAgICAgaTogeEV4dGVudERvbWFpbixcbiAgICAgICAgICBqOiB5RXh0ZW50RG9tYWluXG4gICAgICAgIH0sIGV4dGVudDAgPSB0aGlzLl9fY2hhcnRfXyB8fCBleHRlbnQxO1xuICAgICAgICB0aGlzLl9fY2hhcnRfXyA9IGV4dGVudDE7XG4gICAgICAgIGlmIChkM190cmFuc2l0aW9uSW5oZXJpdElkKSB7XG4gICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnRyYW5zaXRpb24oKS5lYWNoKFwic3RhcnQuYnJ1c2hcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB4RXh0ZW50RG9tYWluID0gZXh0ZW50MC5pO1xuICAgICAgICAgICAgeUV4dGVudERvbWFpbiA9IGV4dGVudDAuajtcbiAgICAgICAgICAgIHhFeHRlbnQgPSBleHRlbnQwLng7XG4gICAgICAgICAgICB5RXh0ZW50ID0gZXh0ZW50MC55O1xuICAgICAgICAgICAgZXZlbnRfKHtcbiAgICAgICAgICAgICAgdHlwZTogXCJicnVzaHN0YXJ0XCJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pLnR3ZWVuKFwiYnJ1c2g6YnJ1c2hcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgeGkgPSBkM19pbnRlcnBvbGF0ZUFycmF5KHhFeHRlbnQsIGV4dGVudDEueCksIHlpID0gZDNfaW50ZXJwb2xhdGVBcnJheSh5RXh0ZW50LCBleHRlbnQxLnkpO1xuICAgICAgICAgICAgeEV4dGVudERvbWFpbiA9IHlFeHRlbnREb21haW4gPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgeEV4dGVudCA9IGV4dGVudDEueCA9IHhpKHQpO1xuICAgICAgICAgICAgICB5RXh0ZW50ID0gZXh0ZW50MS55ID0geWkodCk7XG4gICAgICAgICAgICAgIGV2ZW50Xyh7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJicnVzaFwiLFxuICAgICAgICAgICAgICAgIG1vZGU6IFwicmVzaXplXCJcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pLmVhY2goXCJlbmQuYnJ1c2hcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB4RXh0ZW50RG9tYWluID0gZXh0ZW50MS5pO1xuICAgICAgICAgICAgeUV4dGVudERvbWFpbiA9IGV4dGVudDEuajtcbiAgICAgICAgICAgIGV2ZW50Xyh7XG4gICAgICAgICAgICAgIHR5cGU6IFwiYnJ1c2hcIixcbiAgICAgICAgICAgICAgbW9kZTogXCJyZXNpemVcIlxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBldmVudF8oe1xuICAgICAgICAgICAgICB0eXBlOiBcImJydXNoZW5kXCJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGV2ZW50Xyh7XG4gICAgICAgICAgICB0eXBlOiBcImJydXNoc3RhcnRcIlxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGV2ZW50Xyh7XG4gICAgICAgICAgICB0eXBlOiBcImJydXNoXCIsXG4gICAgICAgICAgICBtb2RlOiBcInJlc2l6ZVwiXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgZXZlbnRfKHtcbiAgICAgICAgICAgIHR5cGU6IFwiYnJ1c2hlbmRcIlxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHJlZHJhdyhnKSB7XG4gICAgICBnLnNlbGVjdEFsbChcIi5yZXNpemVcIikuYXR0cihcInRyYW5zZm9ybVwiLCBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBcInRyYW5zbGF0ZShcIiArIHhFeHRlbnRbKy9lJC8udGVzdChkKV0gKyBcIixcIiArIHlFeHRlbnRbKy9ecy8udGVzdChkKV0gKyBcIilcIjtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZWRyYXdYKGcpIHtcbiAgICAgIGcuc2VsZWN0KFwiLmV4dGVudFwiKS5hdHRyKFwieFwiLCB4RXh0ZW50WzBdKTtcbiAgICAgIGcuc2VsZWN0QWxsKFwiLmV4dGVudCwubj5yZWN0LC5zPnJlY3RcIikuYXR0cihcIndpZHRoXCIsIHhFeHRlbnRbMV0gLSB4RXh0ZW50WzBdKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVkcmF3WShnKSB7XG4gICAgICBnLnNlbGVjdChcIi5leHRlbnRcIikuYXR0cihcInlcIiwgeUV4dGVudFswXSk7XG4gICAgICBnLnNlbGVjdEFsbChcIi5leHRlbnQsLmU+cmVjdCwudz5yZWN0XCIpLmF0dHIoXCJoZWlnaHRcIiwgeUV4dGVudFsxXSAtIHlFeHRlbnRbMF0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBicnVzaHN0YXJ0KCkge1xuICAgICAgdmFyIHRhcmdldCA9IHRoaXMsIGV2ZW50VGFyZ2V0ID0gZDMuc2VsZWN0KGQzLmV2ZW50LnRhcmdldCksIGV2ZW50XyA9IGV2ZW50Lm9mKHRhcmdldCwgYXJndW1lbnRzKSwgZyA9IGQzLnNlbGVjdCh0YXJnZXQpLCByZXNpemluZyA9IGV2ZW50VGFyZ2V0LmRhdHVtKCksIHJlc2l6aW5nWCA9ICEvXihufHMpJC8udGVzdChyZXNpemluZykgJiYgeCwgcmVzaXppbmdZID0gIS9eKGV8dykkLy50ZXN0KHJlc2l6aW5nKSAmJiB5LCBkcmFnZ2luZyA9IGV2ZW50VGFyZ2V0LmNsYXNzZWQoXCJleHRlbnRcIiksIGRyYWdSZXN0b3JlID0gZDNfZXZlbnRfZHJhZ1N1cHByZXNzKHRhcmdldCksIGNlbnRlciwgb3JpZ2luID0gZDMubW91c2UodGFyZ2V0KSwgb2Zmc2V0O1xuICAgICAgdmFyIHcgPSBkMy5zZWxlY3QoZDNfd2luZG93KHRhcmdldCkpLm9uKFwia2V5ZG93bi5icnVzaFwiLCBrZXlkb3duKS5vbihcImtleXVwLmJydXNoXCIsIGtleXVwKTtcbiAgICAgIGlmIChkMy5ldmVudC5jaGFuZ2VkVG91Y2hlcykge1xuICAgICAgICB3Lm9uKFwidG91Y2htb3ZlLmJydXNoXCIsIGJydXNobW92ZSkub24oXCJ0b3VjaGVuZC5icnVzaFwiLCBicnVzaGVuZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3Lm9uKFwibW91c2Vtb3ZlLmJydXNoXCIsIGJydXNobW92ZSkub24oXCJtb3VzZXVwLmJydXNoXCIsIGJydXNoZW5kKTtcbiAgICAgIH1cbiAgICAgIGcuaW50ZXJydXB0KCkuc2VsZWN0QWxsKFwiKlwiKS5pbnRlcnJ1cHQoKTtcbiAgICAgIGlmIChkcmFnZ2luZykge1xuICAgICAgICBvcmlnaW5bMF0gPSB4RXh0ZW50WzBdIC0gb3JpZ2luWzBdO1xuICAgICAgICBvcmlnaW5bMV0gPSB5RXh0ZW50WzBdIC0gb3JpZ2luWzFdO1xuICAgICAgfSBlbHNlIGlmIChyZXNpemluZykge1xuICAgICAgICB2YXIgZXggPSArL3ckLy50ZXN0KHJlc2l6aW5nKSwgZXkgPSArL15uLy50ZXN0KHJlc2l6aW5nKTtcbiAgICAgICAgb2Zmc2V0ID0gWyB4RXh0ZW50WzEgLSBleF0gLSBvcmlnaW5bMF0sIHlFeHRlbnRbMSAtIGV5XSAtIG9yaWdpblsxXSBdO1xuICAgICAgICBvcmlnaW5bMF0gPSB4RXh0ZW50W2V4XTtcbiAgICAgICAgb3JpZ2luWzFdID0geUV4dGVudFtleV07XG4gICAgICB9IGVsc2UgaWYgKGQzLmV2ZW50LmFsdEtleSkgY2VudGVyID0gb3JpZ2luLnNsaWNlKCk7XG4gICAgICBnLnN0eWxlKFwicG9pbnRlci1ldmVudHNcIiwgXCJub25lXCIpLnNlbGVjdEFsbChcIi5yZXNpemVcIikuc3R5bGUoXCJkaXNwbGF5XCIsIG51bGwpO1xuICAgICAgZDMuc2VsZWN0KFwiYm9keVwiKS5zdHlsZShcImN1cnNvclwiLCBldmVudFRhcmdldC5zdHlsZShcImN1cnNvclwiKSk7XG4gICAgICBldmVudF8oe1xuICAgICAgICB0eXBlOiBcImJydXNoc3RhcnRcIlxuICAgICAgfSk7XG4gICAgICBicnVzaG1vdmUoKTtcbiAgICAgIGZ1bmN0aW9uIGtleWRvd24oKSB7XG4gICAgICAgIGlmIChkMy5ldmVudC5rZXlDb2RlID09IDMyKSB7XG4gICAgICAgICAgaWYgKCFkcmFnZ2luZykge1xuICAgICAgICAgICAgY2VudGVyID0gbnVsbDtcbiAgICAgICAgICAgIG9yaWdpblswXSAtPSB4RXh0ZW50WzFdO1xuICAgICAgICAgICAgb3JpZ2luWzFdIC09IHlFeHRlbnRbMV07XG4gICAgICAgICAgICBkcmFnZ2luZyA9IDI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGQzX2V2ZW50UHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZnVuY3Rpb24ga2V5dXAoKSB7XG4gICAgICAgIGlmIChkMy5ldmVudC5rZXlDb2RlID09IDMyICYmIGRyYWdnaW5nID09IDIpIHtcbiAgICAgICAgICBvcmlnaW5bMF0gKz0geEV4dGVudFsxXTtcbiAgICAgICAgICBvcmlnaW5bMV0gKz0geUV4dGVudFsxXTtcbiAgICAgICAgICBkcmFnZ2luZyA9IDA7XG4gICAgICAgICAgZDNfZXZlbnRQcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBicnVzaG1vdmUoKSB7XG4gICAgICAgIHZhciBwb2ludCA9IGQzLm1vdXNlKHRhcmdldCksIG1vdmVkID0gZmFsc2U7XG4gICAgICAgIGlmIChvZmZzZXQpIHtcbiAgICAgICAgICBwb2ludFswXSArPSBvZmZzZXRbMF07XG4gICAgICAgICAgcG9pbnRbMV0gKz0gb2Zmc2V0WzFdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZHJhZ2dpbmcpIHtcbiAgICAgICAgICBpZiAoZDMuZXZlbnQuYWx0S2V5KSB7XG4gICAgICAgICAgICBpZiAoIWNlbnRlcikgY2VudGVyID0gWyAoeEV4dGVudFswXSArIHhFeHRlbnRbMV0pIC8gMiwgKHlFeHRlbnRbMF0gKyB5RXh0ZW50WzFdKSAvIDIgXTtcbiAgICAgICAgICAgIG9yaWdpblswXSA9IHhFeHRlbnRbKyhwb2ludFswXSA8IGNlbnRlclswXSldO1xuICAgICAgICAgICAgb3JpZ2luWzFdID0geUV4dGVudFsrKHBvaW50WzFdIDwgY2VudGVyWzFdKV07XG4gICAgICAgICAgfSBlbHNlIGNlbnRlciA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc2l6aW5nWCAmJiBtb3ZlMShwb2ludCwgeCwgMCkpIHtcbiAgICAgICAgICByZWRyYXdYKGcpO1xuICAgICAgICAgIG1vdmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzaXppbmdZICYmIG1vdmUxKHBvaW50LCB5LCAxKSkge1xuICAgICAgICAgIHJlZHJhd1koZyk7XG4gICAgICAgICAgbW92ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtb3ZlZCkge1xuICAgICAgICAgIHJlZHJhdyhnKTtcbiAgICAgICAgICBldmVudF8oe1xuICAgICAgICAgICAgdHlwZTogXCJicnVzaFwiLFxuICAgICAgICAgICAgbW9kZTogZHJhZ2dpbmcgPyBcIm1vdmVcIiA6IFwicmVzaXplXCJcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZnVuY3Rpb24gbW92ZTEocG9pbnQsIHNjYWxlLCBpKSB7XG4gICAgICAgIHZhciByYW5nZSA9IGQzX3NjYWxlUmFuZ2Uoc2NhbGUpLCByMCA9IHJhbmdlWzBdLCByMSA9IHJhbmdlWzFdLCBwb3NpdGlvbiA9IG9yaWdpbltpXSwgZXh0ZW50ID0gaSA/IHlFeHRlbnQgOiB4RXh0ZW50LCBzaXplID0gZXh0ZW50WzFdIC0gZXh0ZW50WzBdLCBtaW4sIG1heDtcbiAgICAgICAgaWYgKGRyYWdnaW5nKSB7XG4gICAgICAgICAgcjAgLT0gcG9zaXRpb247XG4gICAgICAgICAgcjEgLT0gc2l6ZSArIHBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgICAgIG1pbiA9IChpID8geUNsYW1wIDogeENsYW1wKSA/IE1hdGgubWF4KHIwLCBNYXRoLm1pbihyMSwgcG9pbnRbaV0pKSA6IHBvaW50W2ldO1xuICAgICAgICBpZiAoZHJhZ2dpbmcpIHtcbiAgICAgICAgICBtYXggPSAobWluICs9IHBvc2l0aW9uKSArIHNpemU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGNlbnRlcikgcG9zaXRpb24gPSBNYXRoLm1heChyMCwgTWF0aC5taW4ocjEsIDIgKiBjZW50ZXJbaV0gLSBtaW4pKTtcbiAgICAgICAgICBpZiAocG9zaXRpb24gPCBtaW4pIHtcbiAgICAgICAgICAgIG1heCA9IG1pbjtcbiAgICAgICAgICAgIG1pbiA9IHBvc2l0aW9uO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYXggPSBwb3NpdGlvbjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV4dGVudFswXSAhPSBtaW4gfHwgZXh0ZW50WzFdICE9IG1heCkge1xuICAgICAgICAgIGlmIChpKSB5RXh0ZW50RG9tYWluID0gbnVsbDsgZWxzZSB4RXh0ZW50RG9tYWluID0gbnVsbDtcbiAgICAgICAgICBleHRlbnRbMF0gPSBtaW47XG4gICAgICAgICAgZXh0ZW50WzFdID0gbWF4O1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmdW5jdGlvbiBicnVzaGVuZCgpIHtcbiAgICAgICAgYnJ1c2htb3ZlKCk7XG4gICAgICAgIGcuc3R5bGUoXCJwb2ludGVyLWV2ZW50c1wiLCBcImFsbFwiKS5zZWxlY3RBbGwoXCIucmVzaXplXCIpLnN0eWxlKFwiZGlzcGxheVwiLCBicnVzaC5lbXB0eSgpID8gXCJub25lXCIgOiBudWxsKTtcbiAgICAgICAgZDMuc2VsZWN0KFwiYm9keVwiKS5zdHlsZShcImN1cnNvclwiLCBudWxsKTtcbiAgICAgICAgdy5vbihcIm1vdXNlbW92ZS5icnVzaFwiLCBudWxsKS5vbihcIm1vdXNldXAuYnJ1c2hcIiwgbnVsbCkub24oXCJ0b3VjaG1vdmUuYnJ1c2hcIiwgbnVsbCkub24oXCJ0b3VjaGVuZC5icnVzaFwiLCBudWxsKS5vbihcImtleWRvd24uYnJ1c2hcIiwgbnVsbCkub24oXCJrZXl1cC5icnVzaFwiLCBudWxsKTtcbiAgICAgICAgZHJhZ1Jlc3RvcmUoKTtcbiAgICAgICAgZXZlbnRfKHtcbiAgICAgICAgICB0eXBlOiBcImJydXNoZW5kXCJcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIGJydXNoLnggPSBmdW5jdGlvbih6KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiB4O1xuICAgICAgeCA9IHo7XG4gICAgICByZXNpemVzID0gZDNfc3ZnX2JydXNoUmVzaXplc1sheCA8PCAxIHwgIXldO1xuICAgICAgcmV0dXJuIGJydXNoO1xuICAgIH07XG4gICAgYnJ1c2gueSA9IGZ1bmN0aW9uKHopIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHk7XG4gICAgICB5ID0gejtcbiAgICAgIHJlc2l6ZXMgPSBkM19zdmdfYnJ1c2hSZXNpemVzWyF4IDw8IDEgfCAheV07XG4gICAgICByZXR1cm4gYnJ1c2g7XG4gICAgfTtcbiAgICBicnVzaC5jbGFtcCA9IGZ1bmN0aW9uKHopIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHggJiYgeSA/IFsgeENsYW1wLCB5Q2xhbXAgXSA6IHggPyB4Q2xhbXAgOiB5ID8geUNsYW1wIDogbnVsbDtcbiAgICAgIGlmICh4ICYmIHkpIHhDbGFtcCA9ICEhelswXSwgeUNsYW1wID0gISF6WzFdOyBlbHNlIGlmICh4KSB4Q2xhbXAgPSAhIXo7IGVsc2UgaWYgKHkpIHlDbGFtcCA9ICEhejtcbiAgICAgIHJldHVybiBicnVzaDtcbiAgICB9O1xuICAgIGJydXNoLmV4dGVudCA9IGZ1bmN0aW9uKHopIHtcbiAgICAgIHZhciB4MCwgeDEsIHkwLCB5MSwgdDtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICBpZiAoeCkge1xuICAgICAgICAgIGlmICh4RXh0ZW50RG9tYWluKSB7XG4gICAgICAgICAgICB4MCA9IHhFeHRlbnREb21haW5bMF0sIHgxID0geEV4dGVudERvbWFpblsxXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgeDAgPSB4RXh0ZW50WzBdLCB4MSA9IHhFeHRlbnRbMV07XG4gICAgICAgICAgICBpZiAoeC5pbnZlcnQpIHgwID0geC5pbnZlcnQoeDApLCB4MSA9IHguaW52ZXJ0KHgxKTtcbiAgICAgICAgICAgIGlmICh4MSA8IHgwKSB0ID0geDAsIHgwID0geDEsIHgxID0gdDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHkpIHtcbiAgICAgICAgICBpZiAoeUV4dGVudERvbWFpbikge1xuICAgICAgICAgICAgeTAgPSB5RXh0ZW50RG9tYWluWzBdLCB5MSA9IHlFeHRlbnREb21haW5bMV07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHkwID0geUV4dGVudFswXSwgeTEgPSB5RXh0ZW50WzFdO1xuICAgICAgICAgICAgaWYgKHkuaW52ZXJ0KSB5MCA9IHkuaW52ZXJ0KHkwKSwgeTEgPSB5LmludmVydCh5MSk7XG4gICAgICAgICAgICBpZiAoeTEgPCB5MCkgdCA9IHkwLCB5MCA9IHkxLCB5MSA9IHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB4ICYmIHkgPyBbIFsgeDAsIHkwIF0sIFsgeDEsIHkxIF0gXSA6IHggPyBbIHgwLCB4MSBdIDogeSAmJiBbIHkwLCB5MSBdO1xuICAgICAgfVxuICAgICAgaWYgKHgpIHtcbiAgICAgICAgeDAgPSB6WzBdLCB4MSA9IHpbMV07XG4gICAgICAgIGlmICh5KSB4MCA9IHgwWzBdLCB4MSA9IHgxWzBdO1xuICAgICAgICB4RXh0ZW50RG9tYWluID0gWyB4MCwgeDEgXTtcbiAgICAgICAgaWYgKHguaW52ZXJ0KSB4MCA9IHgoeDApLCB4MSA9IHgoeDEpO1xuICAgICAgICBpZiAoeDEgPCB4MCkgdCA9IHgwLCB4MCA9IHgxLCB4MSA9IHQ7XG4gICAgICAgIGlmICh4MCAhPSB4RXh0ZW50WzBdIHx8IHgxICE9IHhFeHRlbnRbMV0pIHhFeHRlbnQgPSBbIHgwLCB4MSBdO1xuICAgICAgfVxuICAgICAgaWYgKHkpIHtcbiAgICAgICAgeTAgPSB6WzBdLCB5MSA9IHpbMV07XG4gICAgICAgIGlmICh4KSB5MCA9IHkwWzFdLCB5MSA9IHkxWzFdO1xuICAgICAgICB5RXh0ZW50RG9tYWluID0gWyB5MCwgeTEgXTtcbiAgICAgICAgaWYgKHkuaW52ZXJ0KSB5MCA9IHkoeTApLCB5MSA9IHkoeTEpO1xuICAgICAgICBpZiAoeTEgPCB5MCkgdCA9IHkwLCB5MCA9IHkxLCB5MSA9IHQ7XG4gICAgICAgIGlmICh5MCAhPSB5RXh0ZW50WzBdIHx8IHkxICE9IHlFeHRlbnRbMV0pIHlFeHRlbnQgPSBbIHkwLCB5MSBdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJydXNoO1xuICAgIH07XG4gICAgYnJ1c2guY2xlYXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghYnJ1c2guZW1wdHkoKSkge1xuICAgICAgICB4RXh0ZW50ID0gWyAwLCAwIF0sIHlFeHRlbnQgPSBbIDAsIDAgXTtcbiAgICAgICAgeEV4dGVudERvbWFpbiA9IHlFeHRlbnREb21haW4gPSBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJydXNoO1xuICAgIH07XG4gICAgYnJ1c2guZW1wdHkgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAhIXggJiYgeEV4dGVudFswXSA9PSB4RXh0ZW50WzFdIHx8ICEheSAmJiB5RXh0ZW50WzBdID09IHlFeHRlbnRbMV07XG4gICAgfTtcbiAgICByZXR1cm4gZDMucmViaW5kKGJydXNoLCBldmVudCwgXCJvblwiKTtcbiAgfTtcbiAgdmFyIGQzX3N2Z19icnVzaEN1cnNvciA9IHtcbiAgICBuOiBcIm5zLXJlc2l6ZVwiLFxuICAgIGU6IFwiZXctcmVzaXplXCIsXG4gICAgczogXCJucy1yZXNpemVcIixcbiAgICB3OiBcImV3LXJlc2l6ZVwiLFxuICAgIG53OiBcIm53c2UtcmVzaXplXCIsXG4gICAgbmU6IFwibmVzdy1yZXNpemVcIixcbiAgICBzZTogXCJud3NlLXJlc2l6ZVwiLFxuICAgIHN3OiBcIm5lc3ctcmVzaXplXCJcbiAgfTtcbiAgdmFyIGQzX3N2Z19icnVzaFJlc2l6ZXMgPSBbIFsgXCJuXCIsIFwiZVwiLCBcInNcIiwgXCJ3XCIsIFwibndcIiwgXCJuZVwiLCBcInNlXCIsIFwic3dcIiBdLCBbIFwiZVwiLCBcIndcIiBdLCBbIFwiblwiLCBcInNcIiBdLCBbXSBdO1xuICB2YXIgZDNfdGltZV9mb3JtYXQgPSBkM190aW1lLmZvcm1hdCA9IGQzX2xvY2FsZV9lblVTLnRpbWVGb3JtYXQ7XG4gIHZhciBkM190aW1lX2Zvcm1hdFV0YyA9IGQzX3RpbWVfZm9ybWF0LnV0YztcbiAgdmFyIGQzX3RpbWVfZm9ybWF0SXNvID0gZDNfdGltZV9mb3JtYXRVdGMoXCIlWS0lbS0lZFQlSDolTTolUy4lTFpcIik7XG4gIGQzX3RpbWVfZm9ybWF0LmlzbyA9IERhdGUucHJvdG90eXBlLnRvSVNPU3RyaW5nICYmICtuZXcgRGF0ZShcIjIwMDAtMDEtMDFUMDA6MDA6MDAuMDAwWlwiKSA/IGQzX3RpbWVfZm9ybWF0SXNvTmF0aXZlIDogZDNfdGltZV9mb3JtYXRJc287XG4gIGZ1bmN0aW9uIGQzX3RpbWVfZm9ybWF0SXNvTmF0aXZlKGRhdGUpIHtcbiAgICByZXR1cm4gZGF0ZS50b0lTT1N0cmluZygpO1xuICB9XG4gIGQzX3RpbWVfZm9ybWF0SXNvTmF0aXZlLnBhcnNlID0gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgdmFyIGRhdGUgPSBuZXcgRGF0ZShzdHJpbmcpO1xuICAgIHJldHVybiBpc05hTihkYXRlKSA/IG51bGwgOiBkYXRlO1xuICB9O1xuICBkM190aW1lX2Zvcm1hdElzb05hdGl2ZS50b1N0cmluZyA9IGQzX3RpbWVfZm9ybWF0SXNvLnRvU3RyaW5nO1xuICBkM190aW1lLnNlY29uZCA9IGQzX3RpbWVfaW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIHJldHVybiBuZXcgZDNfZGF0ZShNYXRoLmZsb29yKGRhdGUgLyAxZTMpICogMWUzKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpICsgTWF0aC5mbG9vcihvZmZzZXQpICogMWUzKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSkge1xuICAgIHJldHVybiBkYXRlLmdldFNlY29uZHMoKTtcbiAgfSk7XG4gIGQzX3RpbWUuc2Vjb25kcyA9IGQzX3RpbWUuc2Vjb25kLnJhbmdlO1xuICBkM190aW1lLnNlY29uZHMudXRjID0gZDNfdGltZS5zZWNvbmQudXRjLnJhbmdlO1xuICBkM190aW1lLm1pbnV0ZSA9IGQzX3RpbWVfaW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIHJldHVybiBuZXcgZDNfZGF0ZShNYXRoLmZsb29yKGRhdGUgLyA2ZTQpICogNmU0KTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpICsgTWF0aC5mbG9vcihvZmZzZXQpICogNmU0KTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSkge1xuICAgIHJldHVybiBkYXRlLmdldE1pbnV0ZXMoKTtcbiAgfSk7XG4gIGQzX3RpbWUubWludXRlcyA9IGQzX3RpbWUubWludXRlLnJhbmdlO1xuICBkM190aW1lLm1pbnV0ZXMudXRjID0gZDNfdGltZS5taW51dGUudXRjLnJhbmdlO1xuICBkM190aW1lLmhvdXIgPSBkM190aW1lX2ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICB2YXIgdGltZXpvbmUgPSBkYXRlLmdldFRpbWV6b25lT2Zmc2V0KCkgLyA2MDtcbiAgICByZXR1cm4gbmV3IGQzX2RhdGUoKE1hdGguZmxvb3IoZGF0ZSAvIDM2ZTUgLSB0aW1lem9uZSkgKyB0aW1lem9uZSkgKiAzNmU1KTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpICsgTWF0aC5mbG9vcihvZmZzZXQpICogMzZlNSk7XG4gIH0sIGZ1bmN0aW9uKGRhdGUpIHtcbiAgICByZXR1cm4gZGF0ZS5nZXRIb3VycygpO1xuICB9KTtcbiAgZDNfdGltZS5ob3VycyA9IGQzX3RpbWUuaG91ci5yYW5nZTtcbiAgZDNfdGltZS5ob3Vycy51dGMgPSBkM190aW1lLmhvdXIudXRjLnJhbmdlO1xuICBkM190aW1lLm1vbnRoID0gZDNfdGltZV9pbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgZGF0ZSA9IGQzX3RpbWUuZGF5KGRhdGUpO1xuICAgIGRhdGUuc2V0RGF0ZSgxKTtcbiAgICByZXR1cm4gZGF0ZTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgb2Zmc2V0KSB7XG4gICAgZGF0ZS5zZXRNb250aChkYXRlLmdldE1vbnRoKCkgKyBvZmZzZXQpO1xuICB9LCBmdW5jdGlvbihkYXRlKSB7XG4gICAgcmV0dXJuIGRhdGUuZ2V0TW9udGgoKTtcbiAgfSk7XG4gIGQzX3RpbWUubW9udGhzID0gZDNfdGltZS5tb250aC5yYW5nZTtcbiAgZDNfdGltZS5tb250aHMudXRjID0gZDNfdGltZS5tb250aC51dGMucmFuZ2U7XG4gIGZ1bmN0aW9uIGQzX3RpbWVfc2NhbGUobGluZWFyLCBtZXRob2RzLCBmb3JtYXQpIHtcbiAgICBmdW5jdGlvbiBzY2FsZSh4KSB7XG4gICAgICByZXR1cm4gbGluZWFyKHgpO1xuICAgIH1cbiAgICBzY2FsZS5pbnZlcnQgPSBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gZDNfdGltZV9zY2FsZURhdGUobGluZWFyLmludmVydCh4KSk7XG4gICAgfTtcbiAgICBzY2FsZS5kb21haW4gPSBmdW5jdGlvbih4KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsaW5lYXIuZG9tYWluKCkubWFwKGQzX3RpbWVfc2NhbGVEYXRlKTtcbiAgICAgIGxpbmVhci5kb21haW4oeCk7XG4gICAgICByZXR1cm4gc2NhbGU7XG4gICAgfTtcbiAgICBmdW5jdGlvbiB0aWNrTWV0aG9kKGV4dGVudCwgY291bnQpIHtcbiAgICAgIHZhciBzcGFuID0gZXh0ZW50WzFdIC0gZXh0ZW50WzBdLCB0YXJnZXQgPSBzcGFuIC8gY291bnQsIGkgPSBkMy5iaXNlY3QoZDNfdGltZV9zY2FsZVN0ZXBzLCB0YXJnZXQpO1xuICAgICAgcmV0dXJuIGkgPT0gZDNfdGltZV9zY2FsZVN0ZXBzLmxlbmd0aCA/IFsgbWV0aG9kcy55ZWFyLCBkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZXh0ZW50Lm1hcChmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBkIC8gMzE1MzZlNjtcbiAgICAgIH0pLCBjb3VudClbMl0gXSA6ICFpID8gWyBkM190aW1lX3NjYWxlTWlsbGlzZWNvbmRzLCBkM19zY2FsZV9saW5lYXJUaWNrUmFuZ2UoZXh0ZW50LCBjb3VudClbMl0gXSA6IG1ldGhvZHNbdGFyZ2V0IC8gZDNfdGltZV9zY2FsZVN0ZXBzW2kgLSAxXSA8IGQzX3RpbWVfc2NhbGVTdGVwc1tpXSAvIHRhcmdldCA/IGkgLSAxIDogaV07XG4gICAgfVxuICAgIHNjYWxlLm5pY2UgPSBmdW5jdGlvbihpbnRlcnZhbCwgc2tpcCkge1xuICAgICAgdmFyIGRvbWFpbiA9IHNjYWxlLmRvbWFpbigpLCBleHRlbnQgPSBkM19zY2FsZUV4dGVudChkb21haW4pLCBtZXRob2QgPSBpbnRlcnZhbCA9PSBudWxsID8gdGlja01ldGhvZChleHRlbnQsIDEwKSA6IHR5cGVvZiBpbnRlcnZhbCA9PT0gXCJudW1iZXJcIiAmJiB0aWNrTWV0aG9kKGV4dGVudCwgaW50ZXJ2YWwpO1xuICAgICAgaWYgKG1ldGhvZCkgaW50ZXJ2YWwgPSBtZXRob2RbMF0sIHNraXAgPSBtZXRob2RbMV07XG4gICAgICBmdW5jdGlvbiBza2lwcGVkKGRhdGUpIHtcbiAgICAgICAgcmV0dXJuICFpc05hTihkYXRlKSAmJiAhaW50ZXJ2YWwucmFuZ2UoZGF0ZSwgZDNfdGltZV9zY2FsZURhdGUoK2RhdGUgKyAxKSwgc2tpcCkubGVuZ3RoO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNjYWxlLmRvbWFpbihkM19zY2FsZV9uaWNlKGRvbWFpbiwgc2tpcCA+IDEgPyB7XG4gICAgICAgIGZsb29yOiBmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgICAgd2hpbGUgKHNraXBwZWQoZGF0ZSA9IGludGVydmFsLmZsb29yKGRhdGUpKSkgZGF0ZSA9IGQzX3RpbWVfc2NhbGVEYXRlKGRhdGUgLSAxKTtcbiAgICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICAgICAgfSxcbiAgICAgICAgY2VpbDogZnVuY3Rpb24oZGF0ZSkge1xuICAgICAgICAgIHdoaWxlIChza2lwcGVkKGRhdGUgPSBpbnRlcnZhbC5jZWlsKGRhdGUpKSkgZGF0ZSA9IGQzX3RpbWVfc2NhbGVEYXRlKCtkYXRlICsgMSk7XG4gICAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgICAgIH1cbiAgICAgIH0gOiBpbnRlcnZhbCkpO1xuICAgIH07XG4gICAgc2NhbGUudGlja3MgPSBmdW5jdGlvbihpbnRlcnZhbCwgc2tpcCkge1xuICAgICAgdmFyIGV4dGVudCA9IGQzX3NjYWxlRXh0ZW50KHNjYWxlLmRvbWFpbigpKSwgbWV0aG9kID0gaW50ZXJ2YWwgPT0gbnVsbCA/IHRpY2tNZXRob2QoZXh0ZW50LCAxMCkgOiB0eXBlb2YgaW50ZXJ2YWwgPT09IFwibnVtYmVyXCIgPyB0aWNrTWV0aG9kKGV4dGVudCwgaW50ZXJ2YWwpIDogIWludGVydmFsLnJhbmdlICYmIFsge1xuICAgICAgICByYW5nZTogaW50ZXJ2YWxcbiAgICAgIH0sIHNraXAgXTtcbiAgICAgIGlmIChtZXRob2QpIGludGVydmFsID0gbWV0aG9kWzBdLCBza2lwID0gbWV0aG9kWzFdO1xuICAgICAgcmV0dXJuIGludGVydmFsLnJhbmdlKGV4dGVudFswXSwgZDNfdGltZV9zY2FsZURhdGUoK2V4dGVudFsxXSArIDEpLCBza2lwIDwgMSA/IDEgOiBza2lwKTtcbiAgICB9O1xuICAgIHNjYWxlLnRpY2tGb3JtYXQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgfTtcbiAgICBzY2FsZS5jb3B5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZDNfdGltZV9zY2FsZShsaW5lYXIuY29weSgpLCBtZXRob2RzLCBmb3JtYXQpO1xuICAgIH07XG4gICAgcmV0dXJuIGQzX3NjYWxlX2xpbmVhclJlYmluZChzY2FsZSwgbGluZWFyKTtcbiAgfVxuICBmdW5jdGlvbiBkM190aW1lX3NjYWxlRGF0ZSh0KSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHQpO1xuICB9XG4gIHZhciBkM190aW1lX3NjYWxlU3RlcHMgPSBbIDFlMywgNWUzLCAxNWUzLCAzZTQsIDZlNCwgM2U1LCA5ZTUsIDE4ZTUsIDM2ZTUsIDEwOGU1LCAyMTZlNSwgNDMyZTUsIDg2NGU1LCAxNzI4ZTUsIDYwNDhlNSwgMjU5MmU2LCA3Nzc2ZTYsIDMxNTM2ZTYgXTtcbiAgdmFyIGQzX3RpbWVfc2NhbGVMb2NhbE1ldGhvZHMgPSBbIFsgZDNfdGltZS5zZWNvbmQsIDEgXSwgWyBkM190aW1lLnNlY29uZCwgNSBdLCBbIGQzX3RpbWUuc2Vjb25kLCAxNSBdLCBbIGQzX3RpbWUuc2Vjb25kLCAzMCBdLCBbIGQzX3RpbWUubWludXRlLCAxIF0sIFsgZDNfdGltZS5taW51dGUsIDUgXSwgWyBkM190aW1lLm1pbnV0ZSwgMTUgXSwgWyBkM190aW1lLm1pbnV0ZSwgMzAgXSwgWyBkM190aW1lLmhvdXIsIDEgXSwgWyBkM190aW1lLmhvdXIsIDMgXSwgWyBkM190aW1lLmhvdXIsIDYgXSwgWyBkM190aW1lLmhvdXIsIDEyIF0sIFsgZDNfdGltZS5kYXksIDEgXSwgWyBkM190aW1lLmRheSwgMiBdLCBbIGQzX3RpbWUud2VlaywgMSBdLCBbIGQzX3RpbWUubW9udGgsIDEgXSwgWyBkM190aW1lLm1vbnRoLCAzIF0sIFsgZDNfdGltZS55ZWFyLCAxIF0gXTtcbiAgdmFyIGQzX3RpbWVfc2NhbGVMb2NhbEZvcm1hdCA9IGQzX3RpbWVfZm9ybWF0Lm11bHRpKFsgWyBcIi4lTFwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0TWlsbGlzZWNvbmRzKCk7XG4gIH0gXSwgWyBcIjolU1wiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0U2Vjb25kcygpO1xuICB9IF0sIFsgXCIlSTolTVwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0TWludXRlcygpO1xuICB9IF0sIFsgXCIlSSAlcFwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0SG91cnMoKTtcbiAgfSBdLCBbIFwiJWEgJWRcIiwgZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiBkLmdldERheSgpICYmIGQuZ2V0RGF0ZSgpICE9IDE7XG4gIH0gXSwgWyBcIiViICVkXCIsIGZ1bmN0aW9uKGQpIHtcbiAgICByZXR1cm4gZC5nZXREYXRlKCkgIT0gMTtcbiAgfSBdLCBbIFwiJUJcIiwgZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiBkLmdldE1vbnRoKCk7XG4gIH0gXSwgWyBcIiVZXCIsIGQzX3RydWUgXSBdKTtcbiAgdmFyIGQzX3RpbWVfc2NhbGVNaWxsaXNlY29uZHMgPSB7XG4gICAgcmFuZ2U6IGZ1bmN0aW9uKHN0YXJ0LCBzdG9wLCBzdGVwKSB7XG4gICAgICByZXR1cm4gZDMucmFuZ2UoTWF0aC5jZWlsKHN0YXJ0IC8gc3RlcCkgKiBzdGVwLCArc3RvcCwgc3RlcCkubWFwKGQzX3RpbWVfc2NhbGVEYXRlKTtcbiAgICB9LFxuICAgIGZsb29yOiBkM19pZGVudGl0eSxcbiAgICBjZWlsOiBkM19pZGVudGl0eVxuICB9O1xuICBkM190aW1lX3NjYWxlTG9jYWxNZXRob2RzLnllYXIgPSBkM190aW1lLnllYXI7XG4gIGQzX3RpbWUuc2NhbGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZDNfdGltZV9zY2FsZShkMy5zY2FsZS5saW5lYXIoKSwgZDNfdGltZV9zY2FsZUxvY2FsTWV0aG9kcywgZDNfdGltZV9zY2FsZUxvY2FsRm9ybWF0KTtcbiAgfTtcbiAgdmFyIGQzX3RpbWVfc2NhbGVVdGNNZXRob2RzID0gZDNfdGltZV9zY2FsZUxvY2FsTWV0aG9kcy5tYXAoZnVuY3Rpb24obSkge1xuICAgIHJldHVybiBbIG1bMF0udXRjLCBtWzFdIF07XG4gIH0pO1xuICB2YXIgZDNfdGltZV9zY2FsZVV0Y0Zvcm1hdCA9IGQzX3RpbWVfZm9ybWF0VXRjLm11bHRpKFsgWyBcIi4lTFwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0VVRDTWlsbGlzZWNvbmRzKCk7XG4gIH0gXSwgWyBcIjolU1wiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0VVRDU2Vjb25kcygpO1xuICB9IF0sIFsgXCIlSTolTVwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0VVRDTWludXRlcygpO1xuICB9IF0sIFsgXCIlSSAlcFwiLCBmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGQuZ2V0VVRDSG91cnMoKTtcbiAgfSBdLCBbIFwiJWEgJWRcIiwgZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiBkLmdldFVUQ0RheSgpICYmIGQuZ2V0VVRDRGF0ZSgpICE9IDE7XG4gIH0gXSwgWyBcIiViICVkXCIsIGZ1bmN0aW9uKGQpIHtcbiAgICByZXR1cm4gZC5nZXRVVENEYXRlKCkgIT0gMTtcbiAgfSBdLCBbIFwiJUJcIiwgZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiBkLmdldFVUQ01vbnRoKCk7XG4gIH0gXSwgWyBcIiVZXCIsIGQzX3RydWUgXSBdKTtcbiAgZDNfdGltZV9zY2FsZVV0Y01ldGhvZHMueWVhciA9IGQzX3RpbWUueWVhci51dGM7XG4gIGQzX3RpbWUuc2NhbGUudXRjID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGQzX3RpbWVfc2NhbGUoZDMuc2NhbGUubGluZWFyKCksIGQzX3RpbWVfc2NhbGVVdGNNZXRob2RzLCBkM190aW1lX3NjYWxlVXRjRm9ybWF0KTtcbiAgfTtcbiAgZDMudGV4dCA9IGQzX3hoclR5cGUoZnVuY3Rpb24ocmVxdWVzdCkge1xuICAgIHJldHVybiByZXF1ZXN0LnJlc3BvbnNlVGV4dDtcbiAgfSk7XG4gIGQzLmpzb24gPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGQzX3hocih1cmwsIFwiYXBwbGljYXRpb24vanNvblwiLCBkM19qc29uLCBjYWxsYmFjayk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2pzb24ocmVxdWVzdCkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKHJlcXVlc3QucmVzcG9uc2VUZXh0KTtcbiAgfVxuICBkMy5odG1sID0gZnVuY3Rpb24odXJsLCBjYWxsYmFjaykge1xuICAgIHJldHVybiBkM194aHIodXJsLCBcInRleHQvaHRtbFwiLCBkM19odG1sLCBjYWxsYmFjayk7XG4gIH07XG4gIGZ1bmN0aW9uIGQzX2h0bWwocmVxdWVzdCkge1xuICAgIHZhciByYW5nZSA9IGQzX2RvY3VtZW50LmNyZWF0ZVJhbmdlKCk7XG4gICAgcmFuZ2Uuc2VsZWN0Tm9kZShkM19kb2N1bWVudC5ib2R5KTtcbiAgICByZXR1cm4gcmFuZ2UuY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50KHJlcXVlc3QucmVzcG9uc2VUZXh0KTtcbiAgfVxuICBkMy54bWwgPSBkM194aHJUeXBlKGZ1bmN0aW9uKHJlcXVlc3QpIHtcbiAgICByZXR1cm4gcmVxdWVzdC5yZXNwb25zZVhNTDtcbiAgfSk7XG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkgdGhpcy5kMyA9IGQzLCBkZWZpbmUoZDMpOyBlbHNlIGlmICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIG1vZHVsZS5leHBvcnRzKSBtb2R1bGUuZXhwb3J0cyA9IGQzOyBlbHNlIHRoaXMuZDMgPSBkMztcbn0oKTtcbn0se31dLDE2NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoYXJndW1lbnRzW2ldICE9PSB1bmRlZmluZWQpIHJldHVybiBhcmd1bWVudHNbaV07XG4gICAgfVxufTtcblxufSx7fV0sMTY1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciBjaCA9IF9kZXJlcV8oXCJpbmNyZW1lbnRhbC1jb252ZXgtaHVsbFwiKVxudmFyIHVuaXEgPSBfZGVyZXFfKFwidW5pcVwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRyaWFuZ3VsYXRlXG5cbmZ1bmN0aW9uIExpZnRlZFBvaW50KHAsIGkpIHtcbiAgdGhpcy5wb2ludCA9IHBcbiAgdGhpcy5pbmRleCA9IGlcbn1cblxuZnVuY3Rpb24gY29tcGFyZUxpZnRlZChhLCBiKSB7XG4gIHZhciBhcCA9IGEucG9pbnRcbiAgdmFyIGJwID0gYi5wb2ludFxuICB2YXIgZCA9IGFwLmxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICB2YXIgcyA9IGJwW2ldIC0gYXBbaV1cbiAgICBpZihzKSB7XG4gICAgICByZXR1cm4gc1xuICAgIH1cbiAgfVxuICByZXR1cm4gMFxufVxuXG5mdW5jdGlvbiB0cmlhbmd1bGF0ZTFEKG4sIHBvaW50cywgaW5jbHVkZVBvaW50QXRJbmZpbml0eSkge1xuICBpZihuID09PSAxKSB7XG4gICAgaWYoaW5jbHVkZVBvaW50QXRJbmZpbml0eSkge1xuICAgICAgcmV0dXJuIFsgWy0xLCAwXSBdXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBbXVxuICAgIH1cbiAgfVxuICB2YXIgbGlmdGVkID0gcG9pbnRzLm1hcChmdW5jdGlvbihwLCBpKSB7XG4gICAgcmV0dXJuIFsgcFswXSwgaSBdXG4gIH0pXG4gIGxpZnRlZC5zb3J0KGZ1bmN0aW9uKGEsYikge1xuICAgIHJldHVybiBhWzBdIC0gYlswXVxuICB9KVxuICB2YXIgY2VsbHMgPSBuZXcgQXJyYXkobiAtIDEpXG4gIGZvcih2YXIgaT0xOyBpPG47ICsraSkge1xuICAgIHZhciBhID0gbGlmdGVkW2ktMV1cbiAgICB2YXIgYiA9IGxpZnRlZFtpXVxuICAgIGNlbGxzW2ktMV0gPSBbIGFbMV0sIGJbMV0gXVxuICB9XG4gIGlmKGluY2x1ZGVQb2ludEF0SW5maW5pdHkpIHtcbiAgICBjZWxscy5wdXNoKFxuICAgICAgWyAtMSwgY2VsbHNbMF1bMV0sIF0sXG4gICAgICBbIGNlbGxzW24tMV1bMV0sIC0xIF0pXG4gIH1cbiAgcmV0dXJuIGNlbGxzXG59XG5cbmZ1bmN0aW9uIHRyaWFuZ3VsYXRlKHBvaW50cywgaW5jbHVkZVBvaW50QXRJbmZpbml0eSkge1xuICB2YXIgbiA9IHBvaW50cy5sZW5ndGhcbiAgaWYobiA9PT0gMCkge1xuICAgIHJldHVybiBbXVxuICB9XG4gIFxuICB2YXIgZCA9IHBvaW50c1swXS5sZW5ndGhcbiAgaWYoZCA8IDEpIHtcbiAgICByZXR1cm4gW11cbiAgfVxuXG4gIC8vU3BlY2lhbCBjYXNlOiAgRm9yIDFEIHdlIGNhbiBqdXN0IHNvcnQgdGhlIHBvaW50c1xuICBpZihkID09PSAxKSB7XG4gICAgcmV0dXJuIHRyaWFuZ3VsYXRlMUQobiwgcG9pbnRzLCBpbmNsdWRlUG9pbnRBdEluZmluaXR5KVxuICB9XG4gIFxuICAvL0xpZnQgcG9pbnRzLCBzb3J0XG4gIHZhciBsaWZ0ZWQgPSBuZXcgQXJyYXkobilcbiAgdmFyIHVwcGVyID0gMS4wXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHZhciBwID0gcG9pbnRzW2ldXG4gICAgdmFyIHggPSBuZXcgQXJyYXkoZCsxKVxuICAgIHZhciBsID0gMC4wXG4gICAgZm9yKHZhciBqPTA7IGo8ZDsgKytqKSB7XG4gICAgICB2YXIgdiA9IHBbal1cbiAgICAgIHhbal0gPSB2XG4gICAgICBsICs9IHYgKiB2XG4gICAgfVxuICAgIHhbZF0gPSBsXG4gICAgbGlmdGVkW2ldID0gbmV3IExpZnRlZFBvaW50KHgsIGkpXG4gICAgdXBwZXIgPSBNYXRoLm1heChsLCB1cHBlcilcbiAgfVxuICB1bmlxKGxpZnRlZCwgY29tcGFyZUxpZnRlZClcbiAgXG4gIC8vRG91YmxlIHBvaW50c1xuICBuID0gbGlmdGVkLmxlbmd0aFxuXG4gIC8vQ3JlYXRlIG5ldyBsaXN0IG9mIHBvaW50c1xuICB2YXIgZHBvaW50cyA9IG5ldyBBcnJheShuICsgZCArIDEpXG4gIHZhciBkaW5kZXggPSBuZXcgQXJyYXkobiArIGQgKyAxKVxuXG4gIC8vQWRkIHN0ZWluZXIgcG9pbnRzIGF0IHRvcFxuICB2YXIgdSA9IChkKzEpICogKGQrMSkgKiB1cHBlclxuICB2YXIgeSA9IG5ldyBBcnJheShkKzEpXG4gIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICB5W2ldID0gMC4wXG4gIH1cbiAgeVtkXSA9IHVcblxuICBkcG9pbnRzWzBdID0geS5zbGljZSgpXG4gIGRpbmRleFswXSA9IC0xXG5cbiAgZm9yKHZhciBpPTA7IGk8PWQ7ICsraSkge1xuICAgIHZhciB4ID0geS5zbGljZSgpXG4gICAgeFtpXSA9IDFcbiAgICBkcG9pbnRzW2krMV0gPSB4XG4gICAgZGluZGV4W2krMV0gPSAtMVxuICB9XG5cbiAgLy9Db3B5IHJlc3Qgb2YgdGhlIHBvaW50cyBvdmVyXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHZhciBoID0gbGlmdGVkW2ldXG4gICAgZHBvaW50c1tpICsgZCArIDFdID0gaC5wb2ludFxuICAgIGRpbmRleFtpICsgZCArIDFdID0gIGguaW5kZXhcbiAgfVxuXG4gIC8vQ29uc3RydWN0IGNvbnZleCBodWxsXG4gIHZhciBodWxsID0gY2goZHBvaW50cywgZmFsc2UpXG4gIGlmKGluY2x1ZGVQb2ludEF0SW5maW5pdHkpIHtcbiAgICBodWxsID0gaHVsbC5maWx0ZXIoZnVuY3Rpb24oY2VsbCkge1xuICAgICAgdmFyIGNvdW50ID0gMFxuICAgICAgZm9yKHZhciBqPTA7IGo8PWQ7ICsraikge1xuICAgICAgICB2YXIgdiA9IGRpbmRleFtjZWxsW2pdXVxuICAgICAgICBpZih2IDwgMCkge1xuICAgICAgICAgIGlmKCsrY291bnQgPj0gMikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNlbGxbal0gPSB2XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0pXG4gIH0gZWxzZSB7XG4gICAgaHVsbCA9IGh1bGwuZmlsdGVyKGZ1bmN0aW9uKGNlbGwpIHtcbiAgICAgIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICAgICAgdmFyIHYgPSBkaW5kZXhbY2VsbFtpXV1cbiAgICAgICAgaWYodiA8IDApIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgICAgfVxuICAgICAgICBjZWxsW2ldID0gdlxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9KVxuICB9XG5cbiAgaWYoZCAmIDEpIHtcbiAgICBmb3IodmFyIGk9MDsgaTxodWxsLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgaCA9IGh1bGxbaV1cbiAgICAgIHZhciB4ID0gaFswXVxuICAgICAgaFswXSA9IGhbMV1cbiAgICAgIGhbMV0gPSB4XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGh1bGxcbn1cbn0se1wiaW5jcmVtZW50YWwtY29udmV4LWh1bGxcIjo0MTMsXCJ1bmlxXCI6NTQ3fV0sMTY2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0ga2VybmluZ1xyXG5cclxuXHJcbnZhciBjYW52YXMgPSBrZXJuaW5nLmNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXHJcbnZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKVxyXG52YXIgYXNjaWlQYWlycyA9IGNyZWF0ZVBhaXJzKFszMiwgMTI2XSlcclxuXHJcbmtlcm5pbmcuY3JlYXRlUGFpcnMgPSBjcmVhdGVQYWlyc1xyXG5rZXJuaW5nLmFzY2lpID0gYXNjaWlQYWlyc1xyXG5cclxuXHJcbmZ1bmN0aW9uIGtlcm5pbmcgKGZhbWlseSwgbykge1xyXG5cdGlmIChBcnJheS5pc0FycmF5KGZhbWlseSkpIGZhbWlseSA9IGZhbWlseS5qb2luKCcsICcpXHJcblxyXG5cdHZhciB0YWJsZSA9IHt9LCBwYWlycywgZnMgPSAxNiwgdGhyZXNob2xkID0gLjA1XHJcblxyXG5cdGlmIChvKSB7XHJcblx0XHRpZiAoby5sZW5ndGggPT09IDIgJiYgdHlwZW9mIG9bMF0gPT09ICdudW1iZXInKSB7XHJcblx0XHRcdHBhaXJzID0gY3JlYXRlUGFpcnMobylcclxuXHRcdH1cclxuXHRcdGVsc2UgaWYgKEFycmF5LmlzQXJyYXkobykpIHtcclxuXHRcdFx0cGFpcnMgPSBvXHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0aWYgKG8ubykgcGFpcnMgPSBjcmVhdGVQYWlycyhvLm8pXHJcblx0XHRcdGVsc2UgaWYgKG8ucGFpcnMpIHBhaXJzID0gby5wYWlyc1xyXG5cclxuXHRcdFx0aWYgKG8uZm9udFNpemUpIGZzID0gby5mb250U2l6ZVxyXG5cdFx0XHRpZiAoby50aHJlc2hvbGQgIT0gbnVsbCkgdGhyZXNob2xkID0gby50aHJlc2hvbGRcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGlmICghcGFpcnMpIHBhaXJzID0gYXNjaWlQYWlyc1xyXG5cclxuXHRjdHguZm9udCA9IGZzICsgJ3B4ICcgKyBmYW1pbHlcclxuXHJcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwYWlycy5sZW5ndGg7IGkrKykge1xyXG5cdFx0dmFyIHBhaXIgPSBwYWlyc1tpXVxyXG5cdFx0dmFyIHdpZHRoID0gY3R4Lm1lYXN1cmVUZXh0KHBhaXJbMF0pLndpZHRoICsgY3R4Lm1lYXN1cmVUZXh0KHBhaXJbMV0pLndpZHRoXHJcblx0XHR2YXIga2VybmluZ1dpZHRoID0gY3R4Lm1lYXN1cmVUZXh0KHBhaXIpLndpZHRoXHJcblx0XHRpZiAoTWF0aC5hYnMod2lkdGggLSBrZXJuaW5nV2lkdGgpID4gZnMgKiB0aHJlc2hvbGQpIHtcclxuXHRcdFx0dmFyIGVtV2lkdGggPSAoa2VybmluZ1dpZHRoIC0gd2lkdGgpIC8gZnNcclxuXHRcdFx0dGFibGVbcGFpcl0gPSBlbVdpZHRoICogMTAwMFxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIHRhYmxlXHJcbn1cclxuXHJcblxyXG5mdW5jdGlvbiBjcmVhdGVQYWlycyAocmFuZ2UpIHtcclxuXHR2YXIgcGFpcnMgPSBbXVxyXG5cclxuICAgIGZvciAodmFyIGkgPSByYW5nZVswXTsgaSA8PSByYW5nZVsxXTsgaSsrKSB7XHJcblx0XHR2YXIgbGVmdENoYXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGkpXHJcblx0XHRmb3IgKHZhciBqID0gcmFuZ2VbMF07IGogPCByYW5nZVsxXTsgaisrKSB7XHJcblx0XHRcdHZhciByaWdodENoYXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGopXHJcblx0XHRcdHZhciBwYWlyID0gbGVmdENoYXIgKyByaWdodENoYXJcclxuXHJcblx0XHRcdHBhaXJzLnB1c2gocGFpcilcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHJldHVybiBwYWlyc1xyXG59XHJcblxufSx7fV0sMTY3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbihmdW5jdGlvbiAoQnVmZmVyKXtcbnZhciBoYXNUeXBlZEFycmF5cyA9IGZhbHNlXG5pZih0eXBlb2YgRmxvYXQ2NEFycmF5ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gIHZhciBET1VCTEVfVklFVyA9IG5ldyBGbG9hdDY0QXJyYXkoMSlcbiAgICAsIFVJTlRfVklFVyAgID0gbmV3IFVpbnQzMkFycmF5KERPVUJMRV9WSUVXLmJ1ZmZlcilcbiAgRE9VQkxFX1ZJRVdbMF0gPSAxLjBcbiAgaGFzVHlwZWRBcnJheXMgPSB0cnVlXG4gIGlmKFVJTlRfVklFV1sxXSA9PT0gMHgzZmYwMDAwMCkge1xuICAgIC8vVXNlIGxpdHRsZSBlbmRpYW5cbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRvdWJsZUJpdHNMRShuKSB7XG4gICAgICBET1VCTEVfVklFV1swXSA9IG5cbiAgICAgIHJldHVybiBbIFVJTlRfVklFV1swXSwgVUlOVF9WSUVXWzFdIF1cbiAgICB9XG4gICAgZnVuY3Rpb24gdG9Eb3VibGVMRShsbywgaGkpIHtcbiAgICAgIFVJTlRfVklFV1swXSA9IGxvXG4gICAgICBVSU5UX1ZJRVdbMV0gPSBoaVxuICAgICAgcmV0dXJuIERPVUJMRV9WSUVXWzBdXG4gICAgfVxuICAgIG1vZHVsZS5leHBvcnRzLnBhY2sgPSB0b0RvdWJsZUxFXG4gICAgZnVuY3Rpb24gbG93VWludExFKG4pIHtcbiAgICAgIERPVUJMRV9WSUVXWzBdID0gblxuICAgICAgcmV0dXJuIFVJTlRfVklFV1swXVxuICAgIH1cbiAgICBtb2R1bGUuZXhwb3J0cy5sbyA9IGxvd1VpbnRMRVxuICAgIGZ1bmN0aW9uIGhpZ2hVaW50TEUobikge1xuICAgICAgRE9VQkxFX1ZJRVdbMF0gPSBuXG4gICAgICByZXR1cm4gVUlOVF9WSUVXWzFdXG4gICAgfVxuICAgIG1vZHVsZS5leHBvcnRzLmhpID0gaGlnaFVpbnRMRVxuICB9IGVsc2UgaWYoVUlOVF9WSUVXWzBdID09PSAweDNmZjAwMDAwKSB7XG4gICAgLy9Vc2UgYmlnIGVuZGlhblxuICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZG91YmxlQml0c0JFKG4pIHtcbiAgICAgIERPVUJMRV9WSUVXWzBdID0gblxuICAgICAgcmV0dXJuIFsgVUlOVF9WSUVXWzFdLCBVSU5UX1ZJRVdbMF0gXVxuICAgIH1cbiAgICBmdW5jdGlvbiB0b0RvdWJsZUJFKGxvLCBoaSkge1xuICAgICAgVUlOVF9WSUVXWzFdID0gbG9cbiAgICAgIFVJTlRfVklFV1swXSA9IGhpXG4gICAgICByZXR1cm4gRE9VQkxFX1ZJRVdbMF1cbiAgICB9XG4gICAgbW9kdWxlLmV4cG9ydHMucGFjayA9IHRvRG91YmxlQkVcbiAgICBmdW5jdGlvbiBsb3dVaW50QkUobikge1xuICAgICAgRE9VQkxFX1ZJRVdbMF0gPSBuXG4gICAgICByZXR1cm4gVUlOVF9WSUVXWzFdXG4gICAgfVxuICAgIG1vZHVsZS5leHBvcnRzLmxvID0gbG93VWludEJFXG4gICAgZnVuY3Rpb24gaGlnaFVpbnRCRShuKSB7XG4gICAgICBET1VCTEVfVklFV1swXSA9IG5cbiAgICAgIHJldHVybiBVSU5UX1ZJRVdbMF1cbiAgICB9XG4gICAgbW9kdWxlLmV4cG9ydHMuaGkgPSBoaWdoVWludEJFXG4gIH0gZWxzZSB7XG4gICAgaGFzVHlwZWRBcnJheXMgPSBmYWxzZVxuICB9XG59XG5pZighaGFzVHlwZWRBcnJheXMpIHtcbiAgdmFyIGJ1ZmZlciA9IG5ldyBCdWZmZXIoOClcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkb3VibGVCaXRzKG4pIHtcbiAgICBidWZmZXIud3JpdGVEb3VibGVMRShuLCAwLCB0cnVlKVxuICAgIHJldHVybiBbIGJ1ZmZlci5yZWFkVUludDMyTEUoMCwgdHJ1ZSksIGJ1ZmZlci5yZWFkVUludDMyTEUoNCwgdHJ1ZSkgXVxuICB9XG4gIGZ1bmN0aW9uIHRvRG91YmxlKGxvLCBoaSkge1xuICAgIGJ1ZmZlci53cml0ZVVJbnQzMkxFKGxvLCAwLCB0cnVlKVxuICAgIGJ1ZmZlci53cml0ZVVJbnQzMkxFKGhpLCA0LCB0cnVlKVxuICAgIHJldHVybiBidWZmZXIucmVhZERvdWJsZUxFKDAsIHRydWUpXG4gIH1cbiAgbW9kdWxlLmV4cG9ydHMucGFjayA9IHRvRG91YmxlICBcbiAgZnVuY3Rpb24gbG93VWludChuKSB7XG4gICAgYnVmZmVyLndyaXRlRG91YmxlTEUobiwgMCwgdHJ1ZSlcbiAgICByZXR1cm4gYnVmZmVyLnJlYWRVSW50MzJMRSgwLCB0cnVlKVxuICB9XG4gIG1vZHVsZS5leHBvcnRzLmxvID0gbG93VWludFxuICBmdW5jdGlvbiBoaWdoVWludChuKSB7XG4gICAgYnVmZmVyLndyaXRlRG91YmxlTEUobiwgMCwgdHJ1ZSlcbiAgICByZXR1cm4gYnVmZmVyLnJlYWRVSW50MzJMRSg0LCB0cnVlKVxuICB9XG4gIG1vZHVsZS5leHBvcnRzLmhpID0gaGlnaFVpbnRcbn1cblxubW9kdWxlLmV4cG9ydHMuc2lnbiA9IGZ1bmN0aW9uKG4pIHtcbiAgcmV0dXJuIG1vZHVsZS5leHBvcnRzLmhpKG4pID4+PiAzMVxufVxuXG5tb2R1bGUuZXhwb3J0cy5leHBvbmVudCA9IGZ1bmN0aW9uKG4pIHtcbiAgdmFyIGIgPSBtb2R1bGUuZXhwb3J0cy5oaShuKVxuICByZXR1cm4gKChiPDwxKSA+Pj4gMjEpIC0gMTAyM1xufVxuXG5tb2R1bGUuZXhwb3J0cy5mcmFjdGlvbiA9IGZ1bmN0aW9uKG4pIHtcbiAgdmFyIGxvID0gbW9kdWxlLmV4cG9ydHMubG8obilcbiAgdmFyIGhpID0gbW9kdWxlLmV4cG9ydHMuaGkobilcbiAgdmFyIGIgPSBoaSAmICgoMTw8MjApIC0gMSlcbiAgaWYoaGkgJiAweDdmZjAwMDAwKSB7XG4gICAgYiArPSAoMTw8MjApXG4gIH1cbiAgcmV0dXJuIFtsbywgYl1cbn1cblxubW9kdWxlLmV4cG9ydHMuZGVub3JtYWxpemVkID0gZnVuY3Rpb24obikge1xuICB2YXIgaGkgPSBtb2R1bGUuZXhwb3J0cy5oaShuKVxuICByZXR1cm4gIShoaSAmIDB4N2ZmMDAwMDApXG59XG59KS5jYWxsKHRoaXMsX2RlcmVxXyhcImJ1ZmZlclwiKS5CdWZmZXIpXG59LHtcImJ1ZmZlclwiOjEwNX1dLDE2ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG52YXIgYWJzID0gX2RlcmVxXygnYWJzLXN2Zy1wYXRoJylcbnZhciBub3JtYWxpemUgPSBfZGVyZXFfKCdub3JtYWxpemUtc3ZnLXBhdGgnKVxuXG52YXIgbWV0aG9kcyA9IHtcbiAgJ00nOiAnbW92ZVRvJyxcbiAgJ0MnOiAnYmV6aWVyQ3VydmVUbydcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihjb250ZXh0LCBzZWdtZW50cykge1xuICBjb250ZXh0LmJlZ2luUGF0aCgpXG5cbiAgLy8gTWFrZSBwYXRoIGVhc3kgdG8gcmVwcm9kdWNlLlxuICBub3JtYWxpemUoYWJzKHNlZ21lbnRzKSkuZm9yRWFjaChcbiAgICBmdW5jdGlvbihzZWdtZW50KSB7XG4gICAgICB2YXIgY29tbWFuZCA9IHNlZ21lbnRbMF1cbiAgICAgIHZhciBhcmdzID0gc2VnbWVudC5zbGljZSgxKVxuXG4gICAgICAvLyBDb252ZXJ0IHRoZSBwYXRoIGNvbW1hbmQgdG8gYSBjb250ZXh0IG1ldGhvZC5cbiAgICAgIGNvbnRleHRbbWV0aG9kc1tjb21tYW5kXV0uYXBwbHkoY29udGV4dCwgYXJncylcbiAgICB9XG4gIClcblxuICBjb250ZXh0LmNsb3NlUGF0aCgpXG59XG5cbn0se1wiYWJzLXN2Zy1wYXRoXCI6NjAsXCJub3JtYWxpemUtc3ZnLXBhdGhcIjo0NTJ9XSwxNjk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihkdHlwZSkge1xuICBzd2l0Y2ggKGR0eXBlKSB7XG4gICAgY2FzZSAnaW50OCc6XG4gICAgICByZXR1cm4gSW50OEFycmF5XG4gICAgY2FzZSAnaW50MTYnOlxuICAgICAgcmV0dXJuIEludDE2QXJyYXlcbiAgICBjYXNlICdpbnQzMic6XG4gICAgICByZXR1cm4gSW50MzJBcnJheVxuICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICAgIHJldHVybiBVaW50OEFycmF5XG4gICAgY2FzZSAndWludDE2JzpcbiAgICAgIHJldHVybiBVaW50MTZBcnJheVxuICAgIGNhc2UgJ3VpbnQzMic6XG4gICAgICByZXR1cm4gVWludDMyQXJyYXlcbiAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgIHJldHVybiBGbG9hdDMyQXJyYXlcbiAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgIHJldHVybiBGbG9hdDY0QXJyYXlcbiAgICBjYXNlICdhcnJheSc6XG4gICAgICByZXR1cm4gQXJyYXlcbiAgICBjYXNlICd1aW50OF9jbGFtcGVkJzpcbiAgICAgIHJldHVybiBVaW50OENsYW1wZWRBcnJheVxuICB9XG59XG5cbn0se31dLDE3MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5mdW5jdGlvbiBkdXBlX2FycmF5KGNvdW50LCB2YWx1ZSwgaSkge1xuICB2YXIgYyA9IGNvdW50W2ldfDBcbiAgaWYoYyA8PSAwKSB7XG4gICAgcmV0dXJuIFtdXG4gIH1cbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShjKSwgalxuICBpZihpID09PSBjb3VudC5sZW5ndGgtMSkge1xuICAgIGZvcihqPTA7IGo8YzsgKytqKSB7XG4gICAgICByZXN1bHRbal0gPSB2YWx1ZVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBmb3Ioaj0wOyBqPGM7ICsraikge1xuICAgICAgcmVzdWx0W2pdID0gZHVwZV9hcnJheShjb3VudCwgdmFsdWUsIGkrMSlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBkdXBlX251bWJlcihjb3VudCwgdmFsdWUpIHtcbiAgdmFyIHJlc3VsdCwgaVxuICByZXN1bHQgPSBuZXcgQXJyYXkoY291bnQpXG4gIGZvcihpPTA7IGk8Y291bnQ7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IHZhbHVlXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBkdXBlKGNvdW50LCB2YWx1ZSkge1xuICBpZih0eXBlb2YgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICB2YWx1ZSA9IDBcbiAgfVxuICBzd2l0Y2godHlwZW9mIGNvdW50KSB7XG4gICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgaWYoY291bnQgPiAwKSB7XG4gICAgICAgIHJldHVybiBkdXBlX251bWJlcihjb3VudHwwLCB2YWx1ZSlcbiAgICAgIH1cbiAgICBicmVha1xuICAgIGNhc2UgXCJvYmplY3RcIjpcbiAgICAgIGlmKHR5cGVvZiAoY291bnQubGVuZ3RoKSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICByZXR1cm4gZHVwZV9hcnJheShjb3VudCwgdmFsdWUsIDApXG4gICAgICB9XG4gICAgYnJlYWtcbiAgfVxuICByZXR1cm4gW11cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBkdXBlXG59LHt9XSwxNzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBlZGdlVG9BZGphY2VuY3lcblxudmFyIHVuaXEgPSBfZGVyZXFfKFwidW5pcVwiKVxuXG5mdW5jdGlvbiBlZGdlVG9BZGphY2VuY3koZWRnZXMsIG51bVZlcnRpY2VzKSB7XG4gIHZhciBudW1FZGdlcyA9IGVkZ2VzLmxlbmd0aFxuICBpZih0eXBlb2YgbnVtVmVydGljZXMgIT09IFwibnVtYmVyXCIpIHtcbiAgICBudW1WZXJ0aWNlcyA9IDBcbiAgICBmb3IodmFyIGk9MDsgaTxudW1FZGdlczsgKytpKSB7XG4gICAgICB2YXIgZSA9IGVkZ2VzW2ldXG4gICAgICBudW1WZXJ0aWNlcyA9IE1hdGgubWF4KG51bVZlcnRpY2VzLCBlWzBdLCBlWzFdKVxuICAgIH1cbiAgICBudW1WZXJ0aWNlcyA9IChudW1WZXJ0aWNlc3wwKSArIDFcbiAgfVxuICBudW1WZXJ0aWNlcyA9IG51bVZlcnRpY2VzfDBcbiAgdmFyIGFkaiA9IG5ldyBBcnJheShudW1WZXJ0aWNlcylcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydGljZXM7ICsraSkge1xuICAgIGFkaltpXSA9IFtdXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8bnVtRWRnZXM7ICsraSkge1xuICAgIHZhciBlID0gZWRnZXNbaV1cbiAgICBhZGpbZVswXV0ucHVzaChlWzFdKVxuICAgIGFkaltlWzFdXS5wdXNoKGVbMF0pXG4gIH1cbiAgZm9yKHZhciBqPTA7IGo8bnVtVmVydGljZXM7ICsraikge1xuICAgIHVuaXEoYWRqW2pdLCBmdW5jdGlvbihhLCBiKSB7XG4gICAgICByZXR1cm4gYSAtIGJcbiAgICB9KVxuICB9XG4gIHJldHVybiBhZGpcbn1cbn0se1widW5pcVwiOjU0N31dLDE3MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG52YXIgdGFyamFuID0gX2RlcmVxXygnc3Ryb25nbHktY29ubmVjdGVkLWNvbXBvbmVudHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBmaW5kQ2lyY3VpdHMoZWRnZXMpIHtcbiAgICB2YXIgY2lyY3VpdHMgPSBbXTsgLy8gT3V0cHV0XG5cbiAgICB2YXIgc3RhY2sgPSBbXTtcbiAgICB2YXIgYmxvY2tlZCA9IFtdO1xuICAgIHZhciBCID0ge307XG4gICAgdmFyIEFrID0gW107XG4gICAgdmFyIHM7XG5cbiAgICBmdW5jdGlvbiB1bmJsb2NrKHUpIHtcbiAgICAgICAgYmxvY2tlZFt1XSA9IGZhbHNlO1xuICAgICAgICBpZihCLmhhc093blByb3BlcnR5KHUpKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhCW3VdKS5mb3JFYWNoKGZ1bmN0aW9uKHcpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgQlt1XVt3XTtcbiAgICAgICAgICAgICAgICBpZihibG9ja2VkW3ddKSB7dW5ibG9jayh3KTt9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNpcmN1aXQodikge1xuICAgICAgICB2YXIgZm91bmQgPSBmYWxzZTtcblxuICAgICAgICBzdGFjay5wdXNoKHYpO1xuICAgICAgICBibG9ja2VkW3ZdID0gdHJ1ZTtcblxuICAgICAgICAvLyBMMVxuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHc7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IEFrW3ZdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB3ID0gQWtbdl1baV07XG4gICAgICAgICAgICBpZih3ID09PSBzKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0KHMsIHN0YWNrKTtcbiAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYoIWJsb2NrZWRbd10pIHtcbiAgICAgICAgICAgICAgICBmb3VuZCA9IGNpcmN1aXQodyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMMlxuICAgICAgICBpZihmb3VuZCkge1xuICAgICAgICAgICAgdW5ibG9jayh2KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IEFrW3ZdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdyA9IEFrW3ZdW2ldO1xuICAgICAgICAgICAgICAgIHZhciBlbnRyeSA9IEJbd107XG5cbiAgICAgICAgICAgICAgICBpZighZW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgZW50cnkgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgQlt3XSA9IGVudHJ5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGVudHJ5W3ddID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGFjay5wb3AoKTtcbiAgICAgICAgcmV0dXJuIGZvdW5kO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG91dHB1dChzdGFydCwgc3RhY2spIHtcbiAgICAgICAgdmFyIGN5Y2xlID0gW10uY29uY2F0KHN0YWNrKS5jb25jYXQoc3RhcnQpO1xuICAgICAgICBjaXJjdWl0cy5wdXNoKGN5Y2xlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdWJncmFwaChtaW5JZCkge1xuICAgICAgLy8gUmVtb3ZlIGVkZ2VzIHdpdGggaW5kaWNlIHNtYWxsZXIgdGhhbiBtaW5JZFxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgZWRnZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGkgPCBtaW5JZCkgZWRnZXNbaV0gPSBbXTtcbiAgICAgICAgICAgIGVkZ2VzW2ldID0gZWRnZXNbaV0uZmlsdGVyKGZ1bmN0aW9uKGkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaSA+PSBtaW5JZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRqYWNlbmN5U3RydWN0dXJlU0NDKGZyb20pIHtcbiAgICAgIC8vIE1ha2Ugc3ViZ3JhcGggc3RhcnRpbmcgZnJvbSB2ZXJ0ZXggbWluSWRcbiAgICAgICAgc3ViZ3JhcGgoZnJvbSk7XG4gICAgICAgIHZhciBnID0gZWRnZXM7XG5cbiAgICAgIC8vIEZpbmQgc3Ryb25nbHkgY29ubmVjdGVkIGNvbXBvbmVudHMgdXNpbmcgVGFyamFuIGFsZ29yaXRobVxuICAgICAgICB2YXIgc2NjcyA9IHRhcmphbihnKTtcblxuICAgICAgLy8gRmlsdGVyIG91dCB0cml2aWFsIGNvbm5lY3RlZCBjb21wb25lbnRzIChpZS4gbWFkZSBvZiBvbmUgbm9kZSlcbiAgICAgICAgdmFyIGNjcyA9IHNjY3MuY29tcG9uZW50cy5maWx0ZXIoZnVuY3Rpb24oc2NjKSB7XG4gICAgICAgICAgICByZXR1cm4gc2NjLmxlbmd0aCA+IDE7XG4gICAgICAgIH0pO1xuXG4gICAgICAvLyBGaW5kIGxlYXN0IHZlcnRleFxuICAgICAgICB2YXIgbGVhc3RWZXJ0ZXggPSBJbmZpbml0eTtcbiAgICAgICAgdmFyIGxlYXN0VmVydGV4Q29tcG9uZW50O1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2NzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2NzW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYoY2NzW2ldW2pdIDwgbGVhc3RWZXJ0ZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVhc3RWZXJ0ZXggPSBjY3NbaV1bal07XG4gICAgICAgICAgICAgICAgICAgIGxlYXN0VmVydGV4Q29tcG9uZW50ID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY2MgPSBjY3NbbGVhc3RWZXJ0ZXhDb21wb25lbnRdO1xuXG4gICAgICAgIGlmKCFjYykgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAvLyBSZXR1cm4gdGhlIGFkamFjZW5jeSBsaXN0IG9mIGZpcnN0IGNvbXBvbmVudFxuICAgICAgICB2YXIgYWRqTGlzdCA9IGVkZ2VzLm1hcChmdW5jdGlvbihsLCBpbmRleCkge1xuICAgICAgICAgICAgaWYoY2MuaW5kZXhPZihpbmRleCkgPT09IC0xKSByZXR1cm4gW107XG4gICAgICAgICAgICByZXR1cm4gbC5maWx0ZXIoZnVuY3Rpb24oaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjYy5pbmRleE9mKGkpICE9PSAtMTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbGVhc3RWZXJ0ZXg6IGxlYXN0VmVydGV4LFxuICAgICAgICAgICAgYWRqTGlzdDogYWRqTGlzdFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHMgPSAwO1xuICAgIHZhciBuID0gZWRnZXMubGVuZ3RoO1xuICAgIHdoaWxlKHMgPCBuKSB7XG4gICAgICAgIC8vIGZpbmQgc3Ryb25nIGNvbXBvbmVudCB3aXRoIGxlYXN0IHZlcnRleCBpblxuICAgICAgICAvLyBzdWJncmFwaCBzdGFydGluZyBmcm9tIHZlcnRleCBgc2BcbiAgICAgICAgdmFyIHAgPSBhZGphY2VuY3lTdHJ1Y3R1cmVTQ0Mocyk7XG5cbiAgICAgICAgLy8gSXRzIGxlYXN0IHZlcnRleFxuICAgICAgICBzID0gcC5sZWFzdFZlcnRleDtcbiAgICAgICAgLy8gSXRzIGFkamFjZW5jeSBsaXN0XG4gICAgICAgIEFrID0gcC5hZGpMaXN0O1xuXG4gICAgICAgIGlmKEFrKSB7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgQWsubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgQWtbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZlcnRleElkID0gQWtbaV1bal07XG4gICAgICAgICAgICAgICAgICAgIGJsb2NrZWRbK3ZlcnRleElkXSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBCW3ZlcnRleElkXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNpcmN1aXQocyk7XG4gICAgICAgICAgICBzID0gcyArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzID0gbjtcbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgcmV0dXJuIGNpcmN1aXRzO1xufTtcblxufSx7XCJzdHJvbmdseS1jb25uZWN0ZWQtY29tcG9uZW50c1wiOjUzMH1dLDE3MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBJbnNwaXJlZCBieSBHb29nbGUgQ2xvc3VyZTpcbi8vIGh0dHA6Ly9jbG9zdXJlLWxpYnJhcnkuZ29vZ2xlY29kZS5jb20vc3ZuL2RvY3MvXG4vLyBjbG9zdXJlX2dvb2dfYXJyYXlfYXJyYXkuanMuaHRtbCNnb29nLmFycmF5LmNsZWFyXG5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgdmFsdWUgPSBfZGVyZXFfKFwiLi4vLi4vb2JqZWN0L3ZhbGlkLXZhbHVlXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcblx0dmFsdWUodGhpcykubGVuZ3RoID0gMDtcblx0cmV0dXJuIHRoaXM7XG59O1xuXG59LHtcIi4uLy4uL29iamVjdC92YWxpZC12YWx1ZVwiOjIwNX1dLDE3NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKFwiLi9pcy1pbXBsZW1lbnRlZFwiKSgpXG5cdD8gQXJyYXkuZnJvbVxuXHQ6IF9kZXJlcV8oXCIuL3NoaW1cIik7XG5cbn0se1wiLi9pcy1pbXBsZW1lbnRlZFwiOjE3NSxcIi4vc2hpbVwiOjE3Nn1dLDE3NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciBmcm9tID0gQXJyYXkuZnJvbSwgYXJyLCByZXN1bHQ7XG5cdGlmICh0eXBlb2YgZnJvbSAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4gZmFsc2U7XG5cdGFyciA9IFtcInJhelwiLCBcImR3YVwiXTtcblx0cmVzdWx0ID0gZnJvbShhcnIpO1xuXHRyZXR1cm4gQm9vbGVhbihyZXN1bHQgJiYgKHJlc3VsdCAhPT0gYXJyKSAmJiAocmVzdWx0WzFdID09PSBcImR3YVwiKSk7XG59O1xuXG59LHt9XSwxNzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpdGVyYXRvclN5bWJvbCA9IF9kZXJlcV8oXCJlczYtc3ltYm9sXCIpLml0ZXJhdG9yXG4gICwgaXNBcmd1bWVudHMgICAgPSBfZGVyZXFfKFwiLi4vLi4vZnVuY3Rpb24vaXMtYXJndW1lbnRzXCIpXG4gICwgaXNGdW5jdGlvbiAgICAgPSBfZGVyZXFfKFwiLi4vLi4vZnVuY3Rpb24vaXMtZnVuY3Rpb25cIilcbiAgLCB0b1Bvc0ludCAgICAgICA9IF9kZXJlcV8oXCIuLi8uLi9udW1iZXIvdG8tcG9zLWludGVnZXJcIilcbiAgLCBjYWxsYWJsZSAgICAgICA9IF9kZXJlcV8oXCIuLi8uLi9vYmplY3QvdmFsaWQtY2FsbGFibGVcIilcbiAgLCB2YWxpZFZhbHVlICAgICA9IF9kZXJlcV8oXCIuLi8uLi9vYmplY3QvdmFsaWQtdmFsdWVcIilcbiAgLCBpc1ZhbHVlICAgICAgICA9IF9kZXJlcV8oXCIuLi8uLi9vYmplY3QvaXMtdmFsdWVcIilcbiAgLCBpc1N0cmluZyAgICAgICA9IF9kZXJlcV8oXCIuLi8uLi9zdHJpbmcvaXMtc3RyaW5nXCIpXG4gICwgaXNBcnJheSAgICAgICAgPSBBcnJheS5pc0FycmF5XG4gICwgY2FsbCAgICAgICAgICAgPSBGdW5jdGlvbi5wcm90b3R5cGUuY2FsbFxuICAsIGRlc2MgICAgICAgICAgID0geyBjb25maWd1cmFibGU6IHRydWUsIGVudW1lcmFibGU6IHRydWUsIHdyaXRhYmxlOiB0cnVlLCB2YWx1ZTogbnVsbCB9XG4gICwgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb21wbGV4aXR5XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcnJheUxpa2UgLyosIG1hcEZuLCB0aGlzQXJnKi8pIHtcblx0dmFyIG1hcEZuID0gYXJndW1lbnRzWzFdXG5cdCAgLCB0aGlzQXJnID0gYXJndW1lbnRzWzJdXG5cdCAgLCBDb250ZXh0XG5cdCAgLCBpXG5cdCAgLCBqXG5cdCAgLCBhcnJcblx0ICAsIGxlbmd0aFxuXHQgICwgY29kZVxuXHQgICwgaXRlcmF0b3Jcblx0ICAsIHJlc3VsdFxuXHQgICwgZ2V0SXRlcmF0b3Jcblx0ICAsIHZhbHVlO1xuXG5cdGFycmF5TGlrZSA9IE9iamVjdCh2YWxpZFZhbHVlKGFycmF5TGlrZSkpO1xuXG5cdGlmIChpc1ZhbHVlKG1hcEZuKSkgY2FsbGFibGUobWFwRm4pO1xuXHRpZiAoIXRoaXMgfHwgdGhpcyA9PT0gQXJyYXkgfHwgIWlzRnVuY3Rpb24odGhpcykpIHtcblx0XHQvLyBSZXN1bHQ6IFBsYWluIGFycmF5XG5cdFx0aWYgKCFtYXBGbikge1xuXHRcdFx0aWYgKGlzQXJndW1lbnRzKGFycmF5TGlrZSkpIHtcblx0XHRcdFx0Ly8gU291cmNlOiBBcmd1bWVudHNcblx0XHRcdFx0bGVuZ3RoID0gYXJyYXlMaWtlLmxlbmd0aDtcblx0XHRcdFx0aWYgKGxlbmd0aCAhPT0gMSkgcmV0dXJuIEFycmF5LmFwcGx5KG51bGwsIGFycmF5TGlrZSk7XG5cdFx0XHRcdGFyciA9IG5ldyBBcnJheSgxKTtcblx0XHRcdFx0YXJyWzBdID0gYXJyYXlMaWtlWzBdO1xuXHRcdFx0XHRyZXR1cm4gYXJyO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGlzQXJyYXkoYXJyYXlMaWtlKSkge1xuXHRcdFx0XHQvLyBTb3VyY2U6IEFycmF5XG5cdFx0XHRcdGFyciA9IG5ldyBBcnJheShsZW5ndGggPSBhcnJheUxpa2UubGVuZ3RoKTtcblx0XHRcdFx0Zm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSBhcnJbaV0gPSBhcnJheUxpa2VbaV07XG5cdFx0XHRcdHJldHVybiBhcnI7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGFyciA9IFtdO1xuXHR9IGVsc2Uge1xuXHRcdC8vIFJlc3VsdDogTm9uIHBsYWluIGFycmF5XG5cdFx0Q29udGV4dCA9IHRoaXM7XG5cdH1cblxuXHRpZiAoIWlzQXJyYXkoYXJyYXlMaWtlKSkge1xuXHRcdGlmICgoZ2V0SXRlcmF0b3IgPSBhcnJheUxpa2VbaXRlcmF0b3JTeW1ib2xdKSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHQvLyBTb3VyY2U6IEl0ZXJhdG9yXG5cdFx0XHRpdGVyYXRvciA9IGNhbGxhYmxlKGdldEl0ZXJhdG9yKS5jYWxsKGFycmF5TGlrZSk7XG5cdFx0XHRpZiAoQ29udGV4dCkgYXJyID0gbmV3IENvbnRleHQoKTtcblx0XHRcdHJlc3VsdCA9IGl0ZXJhdG9yLm5leHQoKTtcblx0XHRcdGkgPSAwO1xuXHRcdFx0d2hpbGUgKCFyZXN1bHQuZG9uZSkge1xuXHRcdFx0XHR2YWx1ZSA9IG1hcEZuID8gY2FsbC5jYWxsKG1hcEZuLCB0aGlzQXJnLCByZXN1bHQudmFsdWUsIGkpIDogcmVzdWx0LnZhbHVlO1xuXHRcdFx0XHRpZiAoQ29udGV4dCkge1xuXHRcdFx0XHRcdGRlc2MudmFsdWUgPSB2YWx1ZTtcblx0XHRcdFx0XHRkZWZpbmVQcm9wZXJ0eShhcnIsIGksIGRlc2MpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGFycltpXSA9IHZhbHVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJlc3VsdCA9IGl0ZXJhdG9yLm5leHQoKTtcblx0XHRcdFx0KytpO1xuXHRcdFx0fVxuXHRcdFx0bGVuZ3RoID0gaTtcblx0XHR9IGVsc2UgaWYgKGlzU3RyaW5nKGFycmF5TGlrZSkpIHtcblx0XHRcdC8vIFNvdXJjZTogU3RyaW5nXG5cdFx0XHRsZW5ndGggPSBhcnJheUxpa2UubGVuZ3RoO1xuXHRcdFx0aWYgKENvbnRleHQpIGFyciA9IG5ldyBDb250ZXh0KCk7XG5cdFx0XHRmb3IgKGkgPSAwLCBqID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7XG5cdFx0XHRcdHZhbHVlID0gYXJyYXlMaWtlW2ldO1xuXHRcdFx0XHRpZiAoaSArIDEgPCBsZW5ndGgpIHtcblx0XHRcdFx0XHRjb2RlID0gdmFsdWUuY2hhckNvZGVBdCgwKTtcblx0XHRcdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWRlcHRoXG5cdFx0XHRcdFx0aWYgKGNvZGUgPj0gMHhkODAwICYmIGNvZGUgPD0gMHhkYmZmKSB2YWx1ZSArPSBhcnJheUxpa2VbKytpXTtcblx0XHRcdFx0fVxuXHRcdFx0XHR2YWx1ZSA9IG1hcEZuID8gY2FsbC5jYWxsKG1hcEZuLCB0aGlzQXJnLCB2YWx1ZSwgaikgOiB2YWx1ZTtcblx0XHRcdFx0aWYgKENvbnRleHQpIHtcblx0XHRcdFx0XHRkZXNjLnZhbHVlID0gdmFsdWU7XG5cdFx0XHRcdFx0ZGVmaW5lUHJvcGVydHkoYXJyLCBqLCBkZXNjKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRhcnJbal0gPSB2YWx1ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHQrK2o7XG5cdFx0XHR9XG5cdFx0XHRsZW5ndGggPSBqO1xuXHRcdH1cblx0fVxuXHRpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHtcblx0XHQvLyBTb3VyY2U6IGFycmF5IG9yIGFycmF5LWxpa2Vcblx0XHRsZW5ndGggPSB0b1Bvc0ludChhcnJheUxpa2UubGVuZ3RoKTtcblx0XHRpZiAoQ29udGV4dCkgYXJyID0gbmV3IENvbnRleHQobGVuZ3RoKTtcblx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcblx0XHRcdHZhbHVlID0gbWFwRm4gPyBjYWxsLmNhbGwobWFwRm4sIHRoaXNBcmcsIGFycmF5TGlrZVtpXSwgaSkgOiBhcnJheUxpa2VbaV07XG5cdFx0XHRpZiAoQ29udGV4dCkge1xuXHRcdFx0XHRkZXNjLnZhbHVlID0gdmFsdWU7XG5cdFx0XHRcdGRlZmluZVByb3BlcnR5KGFyciwgaSwgZGVzYyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRhcnJbaV0gPSB2YWx1ZTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0aWYgKENvbnRleHQpIHtcblx0XHRkZXNjLnZhbHVlID0gbnVsbDtcblx0XHRhcnIubGVuZ3RoID0gbGVuZ3RoO1xuXHR9XG5cdHJldHVybiBhcnI7XG59O1xuXG59LHtcIi4uLy4uL2Z1bmN0aW9uL2lzLWFyZ3VtZW50c1wiOjE3NyxcIi4uLy4uL2Z1bmN0aW9uL2lzLWZ1bmN0aW9uXCI6MTc4LFwiLi4vLi4vbnVtYmVyL3RvLXBvcy1pbnRlZ2VyXCI6MTg0LFwiLi4vLi4vb2JqZWN0L2lzLXZhbHVlXCI6MTk0LFwiLi4vLi4vb2JqZWN0L3ZhbGlkLWNhbGxhYmxlXCI6MjAzLFwiLi4vLi4vb2JqZWN0L3ZhbGlkLXZhbHVlXCI6MjA1LFwiLi4vLi4vc3RyaW5nL2lzLXN0cmluZ1wiOjIwOSxcImVzNi1zeW1ib2xcIjoyMTl9XSwxNzc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBvYmpUb1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdcbiAgLCBpZCA9IG9ialRvU3RyaW5nLmNhbGwoXG5cdChmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIGFyZ3VtZW50cztcblx0fSkoKVxuKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0cmV0dXJuIG9ialRvU3RyaW5nLmNhbGwodmFsdWUpID09PSBpZDtcbn07XG5cbn0se31dLDE3ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxudmFyIG9ialRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZywgaWQgPSBvYmpUb1N0cmluZy5jYWxsKF9kZXJlcV8oXCIuL25vb3BcIikpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT09IGlkO1xufTtcblxufSx7XCIuL25vb3BcIjoxNzl9XSwxNzk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1lbXB0eS1mdW5jdGlvblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7fTtcblxufSx7fV0sMTgwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oXCIuL2lzLWltcGxlbWVudGVkXCIpKClcblx0PyBNYXRoLnNpZ25cblx0OiBfZGVyZXFfKFwiLi9zaGltXCIpO1xuXG59LHtcIi4vaXMtaW1wbGVtZW50ZWRcIjoxODEsXCIuL3NoaW1cIjoxODJ9XSwxODE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXHR2YXIgc2lnbiA9IE1hdGguc2lnbjtcblx0aWYgKHR5cGVvZiBzaWduICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiBmYWxzZTtcblx0cmV0dXJuIChzaWduKDEwKSA9PT0gMSkgJiYgKHNpZ24oLTIwKSA9PT0gLTEpO1xufTtcblxufSx7fV0sMTgyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHR2YWx1ZSA9IE51bWJlcih2YWx1ZSk7XG5cdGlmIChpc05hTih2YWx1ZSkgfHwgKHZhbHVlID09PSAwKSkgcmV0dXJuIHZhbHVlO1xuXHRyZXR1cm4gdmFsdWUgPiAwID8gMSA6IC0xO1xufTtcblxufSx7fV0sMTgzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgc2lnbiA9IF9kZXJlcV8oXCIuLi9tYXRoL3NpZ25cIilcblxuICAsIGFicyA9IE1hdGguYWJzLCBmbG9vciA9IE1hdGguZmxvb3I7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdGlmIChpc05hTih2YWx1ZSkpIHJldHVybiAwO1xuXHR2YWx1ZSA9IE51bWJlcih2YWx1ZSk7XG5cdGlmICgodmFsdWUgPT09IDApIHx8ICFpc0Zpbml0ZSh2YWx1ZSkpIHJldHVybiB2YWx1ZTtcblx0cmV0dXJuIHNpZ24odmFsdWUpICogZmxvb3IoYWJzKHZhbHVlKSk7XG59O1xuXG59LHtcIi4uL21hdGgvc2lnblwiOjE4MH1dLDE4NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxudmFyIHRvSW50ZWdlciA9IF9kZXJlcV8oXCIuL3RvLWludGVnZXJcIilcblxuICAsIG1heCA9IE1hdGgubWF4O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuIHJldHVybiBtYXgoMCwgdG9JbnRlZ2VyKHZhbHVlKSk7XG59O1xuXG59LHtcIi4vdG8taW50ZWdlclwiOjE4M31dLDE4NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBJbnRlcm5hbCBtZXRob2QsIHVzZWQgYnkgaXRlcmF0aW9uIGZ1bmN0aW9ucy5cbi8vIENhbGxzIGEgZnVuY3Rpb24gZm9yIGVhY2gga2V5LXZhbHVlIHBhaXIgZm91bmQgaW4gb2JqZWN0XG4vLyBPcHRpb25hbGx5IHRha2VzIGNvbXBhcmVGbiB0byBpdGVyYXRlIG9iamVjdCBpbiBzcGVjaWZpYyBvcmRlclxuXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGNhbGxhYmxlICAgICAgICAgICAgICAgID0gX2RlcmVxXyhcIi4vdmFsaWQtY2FsbGFibGVcIilcbiAgLCB2YWx1ZSAgICAgICAgICAgICAgICAgICA9IF9kZXJlcV8oXCIuL3ZhbGlkLXZhbHVlXCIpXG4gICwgYmluZCAgICAgICAgICAgICAgICAgICAgPSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZFxuICAsIGNhbGwgICAgICAgICAgICAgICAgICAgID0gRnVuY3Rpb24ucHJvdG90eXBlLmNhbGxcbiAgLCBrZXlzICAgICAgICAgICAgICAgICAgICA9IE9iamVjdC5rZXlzXG4gICwgb2JqUHJvcGVydHlJc0VudW1lcmFibGUgPSBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChtZXRob2QsIGRlZlZhbCkge1xuXHRyZXR1cm4gZnVuY3Rpb24gKG9iaiwgY2IgLyosIHRoaXNBcmcsIGNvbXBhcmVGbiovKSB7XG5cdFx0dmFyIGxpc3QsIHRoaXNBcmcgPSBhcmd1bWVudHNbMl0sIGNvbXBhcmVGbiA9IGFyZ3VtZW50c1szXTtcblx0XHRvYmogPSBPYmplY3QodmFsdWUob2JqKSk7XG5cdFx0Y2FsbGFibGUoY2IpO1xuXG5cdFx0bGlzdCA9IGtleXMob2JqKTtcblx0XHRpZiAoY29tcGFyZUZuKSB7XG5cdFx0XHRsaXN0LnNvcnQodHlwZW9mIGNvbXBhcmVGbiA9PT0gXCJmdW5jdGlvblwiID8gYmluZC5jYWxsKGNvbXBhcmVGbiwgb2JqKSA6IHVuZGVmaW5lZCk7XG5cdFx0fVxuXHRcdGlmICh0eXBlb2YgbWV0aG9kICE9PSBcImZ1bmN0aW9uXCIpIG1ldGhvZCA9IGxpc3RbbWV0aG9kXTtcblx0XHRyZXR1cm4gY2FsbC5jYWxsKG1ldGhvZCwgbGlzdCwgZnVuY3Rpb24gKGtleSwgaW5kZXgpIHtcblx0XHRcdGlmICghb2JqUHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChvYmosIGtleSkpIHJldHVybiBkZWZWYWw7XG5cdFx0XHRyZXR1cm4gY2FsbC5jYWxsKGNiLCB0aGlzQXJnLCBvYmpba2V5XSwga2V5LCBvYmosIGluZGV4KTtcblx0XHR9KTtcblx0fTtcbn07XG5cbn0se1wiLi92YWxpZC1jYWxsYWJsZVwiOjIwMyxcIi4vdmFsaWQtdmFsdWVcIjoyMDV9XSwxODY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXyhcIi4vaXMtaW1wbGVtZW50ZWRcIikoKVxuXHQ/IE9iamVjdC5hc3NpZ25cblx0OiBfZGVyZXFfKFwiLi9zaGltXCIpO1xuXG59LHtcIi4vaXMtaW1wbGVtZW50ZWRcIjoxODcsXCIuL3NoaW1cIjoxODh9XSwxODc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXHR2YXIgYXNzaWduID0gT2JqZWN0LmFzc2lnbiwgb2JqO1xuXHRpZiAodHlwZW9mIGFzc2lnbiAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4gZmFsc2U7XG5cdG9iaiA9IHsgZm9vOiBcInJhelwiIH07XG5cdGFzc2lnbihvYmosIHsgYmFyOiBcImR3YVwiIH0sIHsgdHJ6eTogXCJ0cnp5XCIgfSk7XG5cdHJldHVybiAob2JqLmZvbyArIG9iai5iYXIgKyBvYmoudHJ6eSkgPT09IFwicmF6ZHdhdHJ6eVwiO1xufTtcblxufSx7fV0sMTg4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIga2V5cyAgPSBfZGVyZXFfKFwiLi4va2V5c1wiKVxuICAsIHZhbHVlID0gX2RlcmVxXyhcIi4uL3ZhbGlkLXZhbHVlXCIpXG4gICwgbWF4ICAgPSBNYXRoLm1heDtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZGVzdCwgc3JjIC8qLCDigKZzcmNuKi8pIHtcblx0dmFyIGVycm9yLCBpLCBsZW5ndGggPSBtYXgoYXJndW1lbnRzLmxlbmd0aCwgMiksIGFzc2lnbjtcblx0ZGVzdCA9IE9iamVjdCh2YWx1ZShkZXN0KSk7XG5cdGFzc2lnbiA9IGZ1bmN0aW9uIChrZXkpIHtcblx0XHR0cnkge1xuXHRcdFx0ZGVzdFtrZXldID0gc3JjW2tleV07XG5cdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0aWYgKCFlcnJvcikgZXJyb3IgPSBlO1xuXHRcdH1cblx0fTtcblx0Zm9yIChpID0gMTsgaSA8IGxlbmd0aDsgKytpKSB7XG5cdFx0c3JjID0gYXJndW1lbnRzW2ldO1xuXHRcdGtleXMoc3JjKS5mb3JFYWNoKGFzc2lnbik7XG5cdH1cblx0aWYgKGVycm9yICE9PSB1bmRlZmluZWQpIHRocm93IGVycm9yO1xuXHRyZXR1cm4gZGVzdDtcbn07XG5cbn0se1wiLi4va2V5c1wiOjE5NSxcIi4uL3ZhbGlkLXZhbHVlXCI6MjA1fV0sMTg5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgYUZyb20gID0gX2RlcmVxXyhcIi4uL2FycmF5L2Zyb21cIilcbiAgLCBhc3NpZ24gPSBfZGVyZXFfKFwiLi9hc3NpZ25cIilcbiAgLCB2YWx1ZSAgPSBfZGVyZXFfKFwiLi92YWxpZC12YWx1ZVwiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqLyosIHByb3BlcnR5TmFtZXMsIG9wdGlvbnMqLykge1xuXHR2YXIgY29weSA9IE9iamVjdCh2YWx1ZShvYmopKSwgcHJvcGVydHlOYW1lcyA9IGFyZ3VtZW50c1sxXSwgb3B0aW9ucyA9IE9iamVjdChhcmd1bWVudHNbMl0pO1xuXHRpZiAoY29weSAhPT0gb2JqICYmICFwcm9wZXJ0eU5hbWVzKSByZXR1cm4gY29weTtcblx0dmFyIHJlc3VsdCA9IHt9O1xuXHRpZiAocHJvcGVydHlOYW1lcykge1xuXHRcdGFGcm9tKHByb3BlcnR5TmFtZXMsIGZ1bmN0aW9uIChwcm9wZXJ0eU5hbWUpIHtcblx0XHRcdGlmIChvcHRpb25zLmVuc3VyZSB8fCBwcm9wZXJ0eU5hbWUgaW4gb2JqKSByZXN1bHRbcHJvcGVydHlOYW1lXSA9IG9ialtwcm9wZXJ0eU5hbWVdO1xuXHRcdH0pO1xuXHR9IGVsc2Uge1xuXHRcdGFzc2lnbihyZXN1bHQsIG9iaik7XG5cdH1cblx0cmV0dXJuIHJlc3VsdDtcbn07XG5cbn0se1wiLi4vYXJyYXkvZnJvbVwiOjE3NCxcIi4vYXNzaWduXCI6MTg2LFwiLi92YWxpZC12YWx1ZVwiOjIwNX1dLDE5MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBXb3JrYXJvdW5kIGZvciBodHRwOi8vY29kZS5nb29nbGUuY29tL3AvdjgvaXNzdWVzL2RldGFpbD9pZD0yODA0XG5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgY3JlYXRlID0gT2JqZWN0LmNyZWF0ZSwgc2hpbTtcblxuaWYgKCFfZGVyZXFfKFwiLi9zZXQtcHJvdG90eXBlLW9mL2lzLWltcGxlbWVudGVkXCIpKCkpIHtcblx0c2hpbSA9IF9kZXJlcV8oXCIuL3NldC1wcm90b3R5cGUtb2Yvc2hpbVwiKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gKCkge1xuXHR2YXIgbnVsbE9iamVjdCwgcG9seVByb3BzLCBkZXNjO1xuXHRpZiAoIXNoaW0pIHJldHVybiBjcmVhdGU7XG5cdGlmIChzaGltLmxldmVsICE9PSAxKSByZXR1cm4gY3JlYXRlO1xuXG5cdG51bGxPYmplY3QgPSB7fTtcblx0cG9seVByb3BzID0ge307XG5cdGRlc2MgPSB7XG5cdFx0Y29uZmlndXJhYmxlOiBmYWxzZSxcblx0XHRlbnVtZXJhYmxlOiBmYWxzZSxcblx0XHR3cml0YWJsZTogdHJ1ZSxcblx0XHR2YWx1ZTogdW5kZWZpbmVkXG5cdH07XG5cdE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKE9iamVjdC5wcm90b3R5cGUpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcblx0XHRpZiAobmFtZSA9PT0gXCJfX3Byb3RvX19cIikge1xuXHRcdFx0cG9seVByb3BzW25hbWVdID0ge1xuXHRcdFx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cdFx0XHRcdGVudW1lcmFibGU6IGZhbHNlLFxuXHRcdFx0XHR3cml0YWJsZTogdHJ1ZSxcblx0XHRcdFx0dmFsdWU6IHVuZGVmaW5lZFxuXHRcdFx0fTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0cG9seVByb3BzW25hbWVdID0gZGVzYztcblx0fSk7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKG51bGxPYmplY3QsIHBvbHlQcm9wcyk7XG5cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KHNoaW0sIFwibnVsbFBvbHlmaWxsXCIsIHtcblx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuXHRcdGVudW1lcmFibGU6IGZhbHNlLFxuXHRcdHdyaXRhYmxlOiBmYWxzZSxcblx0XHR2YWx1ZTogbnVsbE9iamVjdFxuXHR9KTtcblxuXHRyZXR1cm4gZnVuY3Rpb24gKHByb3RvdHlwZSwgcHJvcHMpIHtcblx0XHRyZXR1cm4gY3JlYXRlKHByb3RvdHlwZSA9PT0gbnVsbCA/IG51bGxPYmplY3QgOiBwcm90b3R5cGUsIHByb3BzKTtcblx0fTtcbn0oKSk7XG5cbn0se1wiLi9zZXQtcHJvdG90eXBlLW9mL2lzLWltcGxlbWVudGVkXCI6MjAxLFwiLi9zZXQtcHJvdG90eXBlLW9mL3NoaW1cIjoyMDJ9XSwxOTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXyhcIi4vX2l0ZXJhdGVcIikoXCJmb3JFYWNoXCIpO1xuXG59LHtcIi4vX2l0ZXJhdGVcIjoxODV9XSwxOTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gRGVwcmVjYXRlZFxuXG5cInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gcmV0dXJuIHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIjtcbn07XG5cbn0se31dLDE5MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGlzVmFsdWUgPSBfZGVyZXFfKFwiLi9pcy12YWx1ZVwiKTtcblxudmFyIG1hcCA9IHsgZnVuY3Rpb246IHRydWUsIG9iamVjdDogdHJ1ZSB9O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRyZXR1cm4gKGlzVmFsdWUodmFsdWUpICYmIG1hcFt0eXBlb2YgdmFsdWVdKSB8fCBmYWxzZTtcbn07XG5cbn0se1wiLi9pcy12YWx1ZVwiOjE5NH1dLDE5NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxudmFyIF91bmRlZmluZWQgPSBfZGVyZXFfKFwiLi4vZnVuY3Rpb24vbm9vcFwiKSgpOyAvLyBTdXBwb3J0IEVTMyBlbmdpbmVzXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbCkge1xuIHJldHVybiAodmFsICE9PSBfdW5kZWZpbmVkKSAmJiAodmFsICE9PSBudWxsKTtcbn07XG5cbn0se1wiLi4vZnVuY3Rpb24vbm9vcFwiOjE3OX1dLDE5NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKFwiLi9pcy1pbXBsZW1lbnRlZFwiKSgpID8gT2JqZWN0LmtleXMgOiBfZGVyZXFfKFwiLi9zaGltXCIpO1xuXG59LHtcIi4vaXMtaW1wbGVtZW50ZWRcIjoxOTYsXCIuL3NoaW1cIjoxOTd9XSwxOTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXHR0cnkge1xuXHRcdE9iamVjdC5rZXlzKFwicHJpbWl0aXZlXCIpO1xuXHRcdHJldHVybiB0cnVlO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59O1xuXG59LHt9XSwxOTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc1ZhbHVlID0gX2RlcmVxXyhcIi4uL2lzLXZhbHVlXCIpO1xuXG52YXIga2V5cyA9IE9iamVjdC5rZXlzO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmplY3QpIHsgcmV0dXJuIGtleXMoaXNWYWx1ZShvYmplY3QpID8gT2JqZWN0KG9iamVjdCkgOiBvYmplY3QpOyB9O1xuXG59LHtcIi4uL2lzLXZhbHVlXCI6MTk0fV0sMTk4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgY2FsbGFibGUgPSBfZGVyZXFfKFwiLi92YWxpZC1jYWxsYWJsZVwiKVxuICAsIGZvckVhY2ggID0gX2RlcmVxXyhcIi4vZm9yLWVhY2hcIilcbiAgLCBjYWxsICAgICA9IEZ1bmN0aW9uLnByb3RvdHlwZS5jYWxsO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmosIGNiIC8qLCB0aGlzQXJnKi8pIHtcblx0dmFyIHJlc3VsdCA9IHt9LCB0aGlzQXJnID0gYXJndW1lbnRzWzJdO1xuXHRjYWxsYWJsZShjYik7XG5cdGZvckVhY2gob2JqLCBmdW5jdGlvbiAodmFsdWUsIGtleSwgdGFyZ2V0T2JqLCBpbmRleCkge1xuXHRcdHJlc3VsdFtrZXldID0gY2FsbC5jYWxsKGNiLCB0aGlzQXJnLCB2YWx1ZSwga2V5LCB0YXJnZXRPYmosIGluZGV4KTtcblx0fSk7XG5cdHJldHVybiByZXN1bHQ7XG59O1xuXG59LHtcIi4vZm9yLWVhY2hcIjoxOTEsXCIuL3ZhbGlkLWNhbGxhYmxlXCI6MjAzfV0sMTk5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgaXNWYWx1ZSA9IF9kZXJlcV8oXCIuL2lzLXZhbHVlXCIpO1xuXG52YXIgZm9yRWFjaCA9IEFycmF5LnByb3RvdHlwZS5mb3JFYWNoLCBjcmVhdGUgPSBPYmplY3QuY3JlYXRlO1xuXG52YXIgcHJvY2VzcyA9IGZ1bmN0aW9uIChzcmMsIG9iaikge1xuXHR2YXIga2V5O1xuXHRmb3IgKGtleSBpbiBzcmMpIG9ialtrZXldID0gc3JjW2tleV07XG59O1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9wdHMxIC8qLCDigKZvcHRpb25zKi8pIHtcblx0dmFyIHJlc3VsdCA9IGNyZWF0ZShudWxsKTtcblx0Zm9yRWFjaC5jYWxsKGFyZ3VtZW50cywgZnVuY3Rpb24gKG9wdGlvbnMpIHtcblx0XHRpZiAoIWlzVmFsdWUob3B0aW9ucykpIHJldHVybjtcblx0XHRwcm9jZXNzKE9iamVjdChvcHRpb25zKSwgcmVzdWx0KTtcblx0fSk7XG5cdHJldHVybiByZXN1bHQ7XG59O1xuXG59LHtcIi4vaXMtdmFsdWVcIjoxOTR9XSwyMDA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXyhcIi4vaXMtaW1wbGVtZW50ZWRcIikoKVxuXHQ/IE9iamVjdC5zZXRQcm90b3R5cGVPZlxuXHQ6IF9kZXJlcV8oXCIuL3NoaW1cIik7XG5cbn0se1wiLi9pcy1pbXBsZW1lbnRlZFwiOjIwMSxcIi4vc2hpbVwiOjIwMn1dLDIwMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGNyZWF0ZSA9IE9iamVjdC5jcmVhdGUsIGdldFByb3RvdHlwZU9mID0gT2JqZWN0LmdldFByb3RvdHlwZU9mLCBwbGFpbk9iamVjdCA9IHt9O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgvKiBDdXN0b21DcmVhdGUqLykge1xuXHR2YXIgc2V0UHJvdG90eXBlT2YgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YsIGN1c3RvbUNyZWF0ZSA9IGFyZ3VtZW50c1swXSB8fCBjcmVhdGU7XG5cdGlmICh0eXBlb2Ygc2V0UHJvdG90eXBlT2YgIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIGZhbHNlO1xuXHRyZXR1cm4gZ2V0UHJvdG90eXBlT2Yoc2V0UHJvdG90eXBlT2YoY3VzdG9tQ3JlYXRlKG51bGwpLCBwbGFpbk9iamVjdCkpID09PSBwbGFpbk9iamVjdDtcbn07XG5cbn0se31dLDIwMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKiBlc2xpbnQgbm8tcHJvdG86IFwib2ZmXCIgKi9cblxuLy8gQmlnIHRoYW5rcyB0byBAV2ViUmVmbGVjdGlvbiBmb3Igc29ydGluZyB0aGlzIG91dFxuLy8gaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vV2ViUmVmbGVjdGlvbi81NTkzNTU0XG5cblwidXNlIHN0cmljdFwiO1xuXG52YXIgaXNPYmplY3QgICAgICAgID0gX2RlcmVxXyhcIi4uL2lzLW9iamVjdFwiKVxuICAsIHZhbHVlICAgICAgICAgICA9IF9kZXJlcV8oXCIuLi92YWxpZC12YWx1ZVwiKVxuICAsIG9iaklzUHJvdG90eXBlT2YgPSBPYmplY3QucHJvdG90eXBlLmlzUHJvdG90eXBlT2ZcbiAgLCBkZWZpbmVQcm9wZXJ0eSAgPSBPYmplY3QuZGVmaW5lUHJvcGVydHlcbiAgLCBudWxsRGVzYyAgICAgICAgPSB7XG5cdGNvbmZpZ3VyYWJsZTogdHJ1ZSxcblx0ZW51bWVyYWJsZTogZmFsc2UsXG5cdHdyaXRhYmxlOiB0cnVlLFxuXHR2YWx1ZTogdW5kZWZpbmVkXG59XG4gICwgdmFsaWRhdGU7XG5cbnZhbGlkYXRlID0gZnVuY3Rpb24gKG9iaiwgcHJvdG90eXBlKSB7XG5cdHZhbHVlKG9iaik7XG5cdGlmIChwcm90b3R5cGUgPT09IG51bGwgfHwgaXNPYmplY3QocHJvdG90eXBlKSkgcmV0dXJuIG9iajtcblx0dGhyb3cgbmV3IFR5cGVFcnJvcihcIlByb3RvdHlwZSBtdXN0IGJlIG51bGwgb3IgYW4gb2JqZWN0XCIpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gKHN0YXR1cykge1xuXHR2YXIgZm4sIHNldDtcblx0aWYgKCFzdGF0dXMpIHJldHVybiBudWxsO1xuXHRpZiAoc3RhdHVzLmxldmVsID09PSAyKSB7XG5cdFx0aWYgKHN0YXR1cy5zZXQpIHtcblx0XHRcdHNldCA9IHN0YXR1cy5zZXQ7XG5cdFx0XHRmbiA9IGZ1bmN0aW9uIChvYmosIHByb3RvdHlwZSkge1xuXHRcdFx0XHRzZXQuY2FsbCh2YWxpZGF0ZShvYmosIHByb3RvdHlwZSksIHByb3RvdHlwZSk7XG5cdFx0XHRcdHJldHVybiBvYmo7XG5cdFx0XHR9O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRmbiA9IGZ1bmN0aW9uIChvYmosIHByb3RvdHlwZSkge1xuXHRcdFx0XHR2YWxpZGF0ZShvYmosIHByb3RvdHlwZSkuX19wcm90b19fID0gcHJvdG90eXBlO1xuXHRcdFx0XHRyZXR1cm4gb2JqO1xuXHRcdFx0fTtcblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0Zm4gPSBmdW5jdGlvbiBzZWxmKG9iaiwgcHJvdG90eXBlKSB7XG5cdFx0XHR2YXIgaXNOdWxsQmFzZTtcblx0XHRcdHZhbGlkYXRlKG9iaiwgcHJvdG90eXBlKTtcblx0XHRcdGlzTnVsbEJhc2UgPSBvYmpJc1Byb3RvdHlwZU9mLmNhbGwoc2VsZi5udWxsUG9seWZpbGwsIG9iaik7XG5cdFx0XHRpZiAoaXNOdWxsQmFzZSkgZGVsZXRlIHNlbGYubnVsbFBvbHlmaWxsLl9fcHJvdG9fXztcblx0XHRcdGlmIChwcm90b3R5cGUgPT09IG51bGwpIHByb3RvdHlwZSA9IHNlbGYubnVsbFBvbHlmaWxsO1xuXHRcdFx0b2JqLl9fcHJvdG9fXyA9IHByb3RvdHlwZTtcblx0XHRcdGlmIChpc051bGxCYXNlKSBkZWZpbmVQcm9wZXJ0eShzZWxmLm51bGxQb2x5ZmlsbCwgXCJfX3Byb3RvX19cIiwgbnVsbERlc2MpO1xuXHRcdFx0cmV0dXJuIG9iajtcblx0XHR9O1xuXHR9XG5cdHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoZm4sIFwibGV2ZWxcIiwge1xuXHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG5cdFx0ZW51bWVyYWJsZTogZmFsc2UsXG5cdFx0d3JpdGFibGU6IGZhbHNlLFxuXHRcdHZhbHVlOiBzdGF0dXMubGV2ZWxcblx0fSk7XG59KFxuXHQoZnVuY3Rpb24gKCkge1xuXHRcdHZhciB0bXBPYmoxID0gT2JqZWN0LmNyZWF0ZShudWxsKVxuXHRcdCAgLCB0bXBPYmoyID0ge31cblx0XHQgICwgc2V0XG5cdFx0ICAsIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE9iamVjdC5wcm90b3R5cGUsIFwiX19wcm90b19fXCIpO1xuXG5cdFx0aWYgKGRlc2MpIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHNldCA9IGRlc2Muc2V0OyAvLyBPcGVyYSBjcmFzaGVzIGF0IHRoaXMgcG9pbnRcblx0XHRcdFx0c2V0LmNhbGwodG1wT2JqMSwgdG1wT2JqMik7XG5cdFx0XHR9IGNhdGNoIChpZ25vcmUpIHt9XG5cdFx0XHRpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKHRtcE9iajEpID09PSB0bXBPYmoyKSByZXR1cm4geyBzZXQ6IHNldCwgbGV2ZWw6IDIgfTtcblx0XHR9XG5cblx0XHR0bXBPYmoxLl9fcHJvdG9fXyA9IHRtcE9iajI7XG5cdFx0aWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZih0bXBPYmoxKSA9PT0gdG1wT2JqMikgcmV0dXJuIHsgbGV2ZWw6IDIgfTtcblxuXHRcdHRtcE9iajEgPSB7fTtcblx0XHR0bXBPYmoxLl9fcHJvdG9fXyA9IHRtcE9iajI7XG5cdFx0aWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZih0bXBPYmoxKSA9PT0gdG1wT2JqMikgcmV0dXJuIHsgbGV2ZWw6IDEgfTtcblxuXHRcdHJldHVybiBmYWxzZTtcblx0fSkoKVxuKSk7XG5cbl9kZXJlcV8oXCIuLi9jcmVhdGVcIik7XG5cbn0se1wiLi4vY3JlYXRlXCI6MTkwLFwiLi4vaXMtb2JqZWN0XCI6MTkzLFwiLi4vdmFsaWQtdmFsdWVcIjoyMDV9XSwyMDM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZuKSB7XG5cdGlmICh0eXBlb2YgZm4gIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihmbiArIFwiIGlzIG5vdCBhIGZ1bmN0aW9uXCIpO1xuXHRyZXR1cm4gZm47XG59O1xuXG59LHt9XSwyMDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc09iamVjdCA9IF9kZXJlcV8oXCIuL2lzLW9iamVjdFwiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0aWYgKCFpc09iamVjdCh2YWx1ZSkpIHRocm93IG5ldyBUeXBlRXJyb3IodmFsdWUgKyBcIiBpcyBub3QgYW4gT2JqZWN0XCIpO1xuXHRyZXR1cm4gdmFsdWU7XG59O1xuXG59LHtcIi4vaXMtb2JqZWN0XCI6MTkzfV0sMjA1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgaXNWYWx1ZSA9IF9kZXJlcV8oXCIuL2lzLXZhbHVlXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRpZiAoIWlzVmFsdWUodmFsdWUpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHVzZSBudWxsIG9yIHVuZGVmaW5lZFwiKTtcblx0cmV0dXJuIHZhbHVlO1xufTtcblxufSx7XCIuL2lzLXZhbHVlXCI6MTk0fV0sMjA2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oXCIuL2lzLWltcGxlbWVudGVkXCIpKClcblx0PyBTdHJpbmcucHJvdG90eXBlLmNvbnRhaW5zXG5cdDogX2RlcmVxXyhcIi4vc2hpbVwiKTtcblxufSx7XCIuL2lzLWltcGxlbWVudGVkXCI6MjA3LFwiLi9zaGltXCI6MjA4fV0sMjA3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgc3RyID0gXCJyYXpkd2F0cnp5XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXHRpZiAodHlwZW9mIHN0ci5jb250YWlucyAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4gZmFsc2U7XG5cdHJldHVybiAoc3RyLmNvbnRhaW5zKFwiZHdhXCIpID09PSB0cnVlKSAmJiAoc3RyLmNvbnRhaW5zKFwiZm9vXCIpID09PSBmYWxzZSk7XG59O1xuXG59LHt9XSwyMDg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpbmRleE9mID0gU3RyaW5nLnByb3RvdHlwZS5pbmRleE9mO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzZWFyY2hTdHJpbmcvKiwgcG9zaXRpb24qLykge1xuXHRyZXR1cm4gaW5kZXhPZi5jYWxsKHRoaXMsIHNlYXJjaFN0cmluZywgYXJndW1lbnRzWzFdKSA+IC0xO1xufTtcblxufSx7fV0sMjA5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgb2JqVG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLCBpZCA9IG9ialRvU3RyaW5nLmNhbGwoXCJcIik7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdHJldHVybiAoXG5cdFx0dHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiIHx8XG5cdFx0KHZhbHVlICYmXG5cdFx0XHR0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIgJiZcblx0XHRcdCh2YWx1ZSBpbnN0YW5jZW9mIFN0cmluZyB8fCBvYmpUb1N0cmluZy5jYWxsKHZhbHVlKSA9PT0gaWQpKSB8fFxuXHRcdGZhbHNlXG5cdCk7XG59O1xuXG59LHt9XSwyMTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBnZW5lcmF0ZWQgPSBPYmplY3QuY3JlYXRlKG51bGwpLCByYW5kb20gPSBNYXRoLnJhbmRvbTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciBzdHI7XG5cdGRvIHtcblx0XHRzdHIgPSByYW5kb20oKVxuXHRcdFx0LnRvU3RyaW5nKDM2KVxuXHRcdFx0LnNsaWNlKDIpO1xuXHR9IHdoaWxlIChnZW5lcmF0ZWRbc3RyXSk7XG5cdHJldHVybiBzdHI7XG59O1xuXG59LHt9XSwyMTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBzZXRQcm90b3R5cGVPZiA9IF9kZXJlcV8oXCJlczUtZXh0L29iamVjdC9zZXQtcHJvdG90eXBlLW9mXCIpXG4gICwgY29udGFpbnMgICAgICAgPSBfZGVyZXFfKFwiZXM1LWV4dC9zdHJpbmcvIy9jb250YWluc1wiKVxuICAsIGQgICAgICAgICAgICAgID0gX2RlcmVxXyhcImRcIilcbiAgLCBTeW1ib2wgICAgICAgICA9IF9kZXJlcV8oXCJlczYtc3ltYm9sXCIpXG4gICwgSXRlcmF0b3IgICAgICAgPSBfZGVyZXFfKFwiLi9cIik7XG5cbnZhciBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSwgQXJyYXlJdGVyYXRvcjtcblxuQXJyYXlJdGVyYXRvciA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyciwga2luZCkge1xuXHRpZiAoISh0aGlzIGluc3RhbmNlb2YgQXJyYXlJdGVyYXRvcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDb25zdHJ1Y3RvciByZXF1aXJlcyAnbmV3J1wiKTtcblx0SXRlcmF0b3IuY2FsbCh0aGlzLCBhcnIpO1xuXHRpZiAoIWtpbmQpIGtpbmQgPSBcInZhbHVlXCI7XG5cdGVsc2UgaWYgKGNvbnRhaW5zLmNhbGwoa2luZCwgXCJrZXkrdmFsdWVcIikpIGtpbmQgPSBcImtleSt2YWx1ZVwiO1xuXHRlbHNlIGlmIChjb250YWlucy5jYWxsKGtpbmQsIFwia2V5XCIpKSBraW5kID0gXCJrZXlcIjtcblx0ZWxzZSBraW5kID0gXCJ2YWx1ZVwiO1xuXHRkZWZpbmVQcm9wZXJ0eSh0aGlzLCBcIl9fa2luZF9fXCIsIGQoXCJcIiwga2luZCkpO1xufTtcbmlmIChzZXRQcm90b3R5cGVPZikgc2V0UHJvdG90eXBlT2YoQXJyYXlJdGVyYXRvciwgSXRlcmF0b3IpO1xuXG4vLyBJbnRlcm5hbCAlQXJyYXlJdGVyYXRvclByb3RvdHlwZSUgZG9lc24ndCBleHBvc2UgaXRzIGNvbnN0cnVjdG9yXG5kZWxldGUgQXJyYXlJdGVyYXRvci5wcm90b3R5cGUuY29uc3RydWN0b3I7XG5cbkFycmF5SXRlcmF0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShJdGVyYXRvci5wcm90b3R5cGUsIHtcblx0X3Jlc29sdmU6IGQoZnVuY3Rpb24gKGkpIHtcblx0XHRpZiAodGhpcy5fX2tpbmRfXyA9PT0gXCJ2YWx1ZVwiKSByZXR1cm4gdGhpcy5fX2xpc3RfX1tpXTtcblx0XHRpZiAodGhpcy5fX2tpbmRfXyA9PT0gXCJrZXkrdmFsdWVcIikgcmV0dXJuIFtpLCB0aGlzLl9fbGlzdF9fW2ldXTtcblx0XHRyZXR1cm4gaTtcblx0fSlcbn0pO1xuZGVmaW5lUHJvcGVydHkoQXJyYXlJdGVyYXRvci5wcm90b3R5cGUsIFN5bWJvbC50b1N0cmluZ1RhZywgZChcImNcIiwgXCJBcnJheSBJdGVyYXRvclwiKSk7XG5cbn0se1wiLi9cIjoyMTQsXCJkXCI6MTUxLFwiZXM1LWV4dC9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZlwiOjIwMCxcImVzNS1leHQvc3RyaW5nLyMvY29udGFpbnNcIjoyMDYsXCJlczYtc3ltYm9sXCI6MjE5fV0sMjEyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgaXNBcmd1bWVudHMgPSBfZGVyZXFfKFwiZXM1LWV4dC9mdW5jdGlvbi9pcy1hcmd1bWVudHNcIilcbiAgLCBjYWxsYWJsZSAgICA9IF9kZXJlcV8oXCJlczUtZXh0L29iamVjdC92YWxpZC1jYWxsYWJsZVwiKVxuICAsIGlzU3RyaW5nICAgID0gX2RlcmVxXyhcImVzNS1leHQvc3RyaW5nL2lzLXN0cmluZ1wiKVxuICAsIGdldCAgICAgICAgID0gX2RlcmVxXyhcIi4vZ2V0XCIpO1xuXG52YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXksIGNhbGwgPSBGdW5jdGlvbi5wcm90b3R5cGUuY2FsbCwgc29tZSA9IEFycmF5LnByb3RvdHlwZS5zb21lO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdGVyYWJsZSwgY2IgLyosIHRoaXNBcmcqLykge1xuXHR2YXIgbW9kZSwgdGhpc0FyZyA9IGFyZ3VtZW50c1syXSwgcmVzdWx0LCBkb0JyZWFrLCBicm9rZW4sIGksIGxlbmd0aCwgY2hhciwgY29kZTtcblx0aWYgKGlzQXJyYXkoaXRlcmFibGUpIHx8IGlzQXJndW1lbnRzKGl0ZXJhYmxlKSkgbW9kZSA9IFwiYXJyYXlcIjtcblx0ZWxzZSBpZiAoaXNTdHJpbmcoaXRlcmFibGUpKSBtb2RlID0gXCJzdHJpbmdcIjtcblx0ZWxzZSBpdGVyYWJsZSA9IGdldChpdGVyYWJsZSk7XG5cblx0Y2FsbGFibGUoY2IpO1xuXHRkb0JyZWFrID0gZnVuY3Rpb24gKCkge1xuXHRcdGJyb2tlbiA9IHRydWU7XG5cdH07XG5cdGlmIChtb2RlID09PSBcImFycmF5XCIpIHtcblx0XHRzb21lLmNhbGwoaXRlcmFibGUsIGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRcdFx0Y2FsbC5jYWxsKGNiLCB0aGlzQXJnLCB2YWx1ZSwgZG9CcmVhayk7XG5cdFx0XHRyZXR1cm4gYnJva2VuO1xuXHRcdH0pO1xuXHRcdHJldHVybjtcblx0fVxuXHRpZiAobW9kZSA9PT0gXCJzdHJpbmdcIikge1xuXHRcdGxlbmd0aCA9IGl0ZXJhYmxlLmxlbmd0aDtcblx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcblx0XHRcdGNoYXIgPSBpdGVyYWJsZVtpXTtcblx0XHRcdGlmIChpICsgMSA8IGxlbmd0aCkge1xuXHRcdFx0XHRjb2RlID0gY2hhci5jaGFyQ29kZUF0KDApO1xuXHRcdFx0XHRpZiAoY29kZSA+PSAweGQ4MDAgJiYgY29kZSA8PSAweGRiZmYpIGNoYXIgKz0gaXRlcmFibGVbKytpXTtcblx0XHRcdH1cblx0XHRcdGNhbGwuY2FsbChjYiwgdGhpc0FyZywgY2hhciwgZG9CcmVhayk7XG5cdFx0XHRpZiAoYnJva2VuKSBicmVhaztcblx0XHR9XG5cdFx0cmV0dXJuO1xuXHR9XG5cdHJlc3VsdCA9IGl0ZXJhYmxlLm5leHQoKTtcblxuXHR3aGlsZSAoIXJlc3VsdC5kb25lKSB7XG5cdFx0Y2FsbC5jYWxsKGNiLCB0aGlzQXJnLCByZXN1bHQudmFsdWUsIGRvQnJlYWspO1xuXHRcdGlmIChicm9rZW4pIHJldHVybjtcblx0XHRyZXN1bHQgPSBpdGVyYWJsZS5uZXh0KCk7XG5cdH1cbn07XG5cbn0se1wiLi9nZXRcIjoyMTMsXCJlczUtZXh0L2Z1bmN0aW9uL2lzLWFyZ3VtZW50c1wiOjE3NyxcImVzNS1leHQvb2JqZWN0L3ZhbGlkLWNhbGxhYmxlXCI6MjAzLFwiZXM1LWV4dC9zdHJpbmcvaXMtc3RyaW5nXCI6MjA5fV0sMjEzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgaXNBcmd1bWVudHMgICAgPSBfZGVyZXFfKFwiZXM1LWV4dC9mdW5jdGlvbi9pcy1hcmd1bWVudHNcIilcbiAgLCBpc1N0cmluZyAgICAgICA9IF9kZXJlcV8oXCJlczUtZXh0L3N0cmluZy9pcy1zdHJpbmdcIilcbiAgLCBBcnJheUl0ZXJhdG9yICA9IF9kZXJlcV8oXCIuL2FycmF5XCIpXG4gICwgU3RyaW5nSXRlcmF0b3IgPSBfZGVyZXFfKFwiLi9zdHJpbmdcIilcbiAgLCBpdGVyYWJsZSAgICAgICA9IF9kZXJlcV8oXCIuL3ZhbGlkLWl0ZXJhYmxlXCIpXG4gICwgaXRlcmF0b3JTeW1ib2wgPSBfZGVyZXFfKFwiZXM2LXN5bWJvbFwiKS5pdGVyYXRvcjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG5cdGlmICh0eXBlb2YgaXRlcmFibGUob2JqKVtpdGVyYXRvclN5bWJvbF0gPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIG9ialtpdGVyYXRvclN5bWJvbF0oKTtcblx0aWYgKGlzQXJndW1lbnRzKG9iaikpIHJldHVybiBuZXcgQXJyYXlJdGVyYXRvcihvYmopO1xuXHRpZiAoaXNTdHJpbmcob2JqKSkgcmV0dXJuIG5ldyBTdHJpbmdJdGVyYXRvcihvYmopO1xuXHRyZXR1cm4gbmV3IEFycmF5SXRlcmF0b3Iob2JqKTtcbn07XG5cbn0se1wiLi9hcnJheVwiOjIxMSxcIi4vc3RyaW5nXCI6MjE2LFwiLi92YWxpZC1pdGVyYWJsZVwiOjIxNyxcImVzNS1leHQvZnVuY3Rpb24vaXMtYXJndW1lbnRzXCI6MTc3LFwiZXM1LWV4dC9zdHJpbmcvaXMtc3RyaW5nXCI6MjA5LFwiZXM2LXN5bWJvbFwiOjIxOX1dLDIxNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGNsZWFyICAgID0gX2RlcmVxXyhcImVzNS1leHQvYXJyYXkvIy9jbGVhclwiKVxuICAsIGFzc2lnbiAgID0gX2RlcmVxXyhcImVzNS1leHQvb2JqZWN0L2Fzc2lnblwiKVxuICAsIGNhbGxhYmxlID0gX2RlcmVxXyhcImVzNS1leHQvb2JqZWN0L3ZhbGlkLWNhbGxhYmxlXCIpXG4gICwgdmFsdWUgICAgPSBfZGVyZXFfKFwiZXM1LWV4dC9vYmplY3QvdmFsaWQtdmFsdWVcIilcbiAgLCBkICAgICAgICA9IF9kZXJlcV8oXCJkXCIpXG4gICwgYXV0b0JpbmQgPSBfZGVyZXFfKFwiZC9hdXRvLWJpbmRcIilcbiAgLCBTeW1ib2wgICA9IF9kZXJlcV8oXCJlczYtc3ltYm9sXCIpO1xuXG52YXIgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHksIGRlZmluZVByb3BlcnRpZXMgPSBPYmplY3QuZGVmaW5lUHJvcGVydGllcywgSXRlcmF0b3I7XG5cbm1vZHVsZS5leHBvcnRzID0gSXRlcmF0b3IgPSBmdW5jdGlvbiAobGlzdCwgY29udGV4dCkge1xuXHRpZiAoISh0aGlzIGluc3RhbmNlb2YgSXRlcmF0b3IpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ29uc3RydWN0b3IgcmVxdWlyZXMgJ25ldydcIik7XG5cdGRlZmluZVByb3BlcnRpZXModGhpcywge1xuXHRcdF9fbGlzdF9fOiBkKFwid1wiLCB2YWx1ZShsaXN0KSksXG5cdFx0X19jb250ZXh0X186IGQoXCJ3XCIsIGNvbnRleHQpLFxuXHRcdF9fbmV4dEluZGV4X186IGQoXCJ3XCIsIDApXG5cdH0pO1xuXHRpZiAoIWNvbnRleHQpIHJldHVybjtcblx0Y2FsbGFibGUoY29udGV4dC5vbik7XG5cdGNvbnRleHQub24oXCJfYWRkXCIsIHRoaXMuX29uQWRkKTtcblx0Y29udGV4dC5vbihcIl9kZWxldGVcIiwgdGhpcy5fb25EZWxldGUpO1xuXHRjb250ZXh0Lm9uKFwiX2NsZWFyXCIsIHRoaXMuX29uQ2xlYXIpO1xufTtcblxuLy8gSW50ZXJuYWwgJUl0ZXJhdG9yUHJvdG90eXBlJSBkb2Vzbid0IGV4cG9zZSBpdHMgY29uc3RydWN0b3JcbmRlbGV0ZSBJdGVyYXRvci5wcm90b3R5cGUuY29uc3RydWN0b3I7XG5cbmRlZmluZVByb3BlcnRpZXMoXG5cdEl0ZXJhdG9yLnByb3RvdHlwZSxcblx0YXNzaWduKFxuXHRcdHtcblx0XHRcdF9uZXh0OiBkKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0dmFyIGk7XG5cdFx0XHRcdGlmICghdGhpcy5fX2xpc3RfXykgcmV0dXJuIHVuZGVmaW5lZDtcblx0XHRcdFx0aWYgKHRoaXMuX19yZWRvX18pIHtcblx0XHRcdFx0XHRpID0gdGhpcy5fX3JlZG9fXy5zaGlmdCgpO1xuXHRcdFx0XHRcdGlmIChpICE9PSB1bmRlZmluZWQpIHJldHVybiBpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICh0aGlzLl9fbmV4dEluZGV4X18gPCB0aGlzLl9fbGlzdF9fLmxlbmd0aCkgcmV0dXJuIHRoaXMuX19uZXh0SW5kZXhfXysrO1xuXHRcdFx0XHR0aGlzLl91bkJpbmQoKTtcblx0XHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHRcdH0pLFxuXHRcdFx0bmV4dDogZChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLl9jcmVhdGVSZXN1bHQodGhpcy5fbmV4dCgpKTtcblx0XHRcdH0pLFxuXHRcdFx0X2NyZWF0ZVJlc3VsdDogZChmdW5jdGlvbiAoaSkge1xuXHRcdFx0XHRpZiAoaSA9PT0gdW5kZWZpbmVkKSByZXR1cm4geyBkb25lOiB0cnVlLCB2YWx1ZTogdW5kZWZpbmVkIH07XG5cdFx0XHRcdHJldHVybiB7IGRvbmU6IGZhbHNlLCB2YWx1ZTogdGhpcy5fcmVzb2x2ZShpKSB9O1xuXHRcdFx0fSksXG5cdFx0XHRfcmVzb2x2ZTogZChmdW5jdGlvbiAoaSkge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fX2xpc3RfX1tpXTtcblx0XHRcdH0pLFxuXHRcdFx0X3VuQmluZDogZChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHRoaXMuX19saXN0X18gPSBudWxsO1xuXHRcdFx0XHRkZWxldGUgdGhpcy5fX3JlZG9fXztcblx0XHRcdFx0aWYgKCF0aGlzLl9fY29udGV4dF9fKSByZXR1cm47XG5cdFx0XHRcdHRoaXMuX19jb250ZXh0X18ub2ZmKFwiX2FkZFwiLCB0aGlzLl9vbkFkZCk7XG5cdFx0XHRcdHRoaXMuX19jb250ZXh0X18ub2ZmKFwiX2RlbGV0ZVwiLCB0aGlzLl9vbkRlbGV0ZSk7XG5cdFx0XHRcdHRoaXMuX19jb250ZXh0X18ub2ZmKFwiX2NsZWFyXCIsIHRoaXMuX29uQ2xlYXIpO1xuXHRcdFx0XHR0aGlzLl9fY29udGV4dF9fID0gbnVsbDtcblx0XHRcdH0pLFxuXHRcdFx0dG9TdHJpbmc6IGQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRyZXR1cm4gXCJbb2JqZWN0IFwiICsgKHRoaXNbU3ltYm9sLnRvU3RyaW5nVGFnXSB8fCBcIk9iamVjdFwiKSArIFwiXVwiO1xuXHRcdFx0fSlcblx0XHR9LFxuXHRcdGF1dG9CaW5kKHtcblx0XHRcdF9vbkFkZDogZChmdW5jdGlvbiAoaW5kZXgpIHtcblx0XHRcdFx0aWYgKGluZGV4ID49IHRoaXMuX19uZXh0SW5kZXhfXykgcmV0dXJuO1xuXHRcdFx0XHQrK3RoaXMuX19uZXh0SW5kZXhfXztcblx0XHRcdFx0aWYgKCF0aGlzLl9fcmVkb19fKSB7XG5cdFx0XHRcdFx0ZGVmaW5lUHJvcGVydHkodGhpcywgXCJfX3JlZG9fX1wiLCBkKFwiY1wiLCBbaW5kZXhdKSk7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMuX19yZWRvX18uZm9yRWFjaChmdW5jdGlvbiAocmVkbywgaSkge1xuXHRcdFx0XHRcdGlmIChyZWRvID49IGluZGV4KSB0aGlzLl9fcmVkb19fW2ldID0gKytyZWRvO1xuXHRcdFx0XHR9LCB0aGlzKTtcblx0XHRcdFx0dGhpcy5fX3JlZG9fXy5wdXNoKGluZGV4KTtcblx0XHRcdH0pLFxuXHRcdFx0X29uRGVsZXRlOiBkKGZ1bmN0aW9uIChpbmRleCkge1xuXHRcdFx0XHR2YXIgaTtcblx0XHRcdFx0aWYgKGluZGV4ID49IHRoaXMuX19uZXh0SW5kZXhfXykgcmV0dXJuO1xuXHRcdFx0XHQtLXRoaXMuX19uZXh0SW5kZXhfXztcblx0XHRcdFx0aWYgKCF0aGlzLl9fcmVkb19fKSByZXR1cm47XG5cdFx0XHRcdGkgPSB0aGlzLl9fcmVkb19fLmluZGV4T2YoaW5kZXgpO1xuXHRcdFx0XHRpZiAoaSAhPT0gLTEpIHRoaXMuX19yZWRvX18uc3BsaWNlKGksIDEpO1xuXHRcdFx0XHR0aGlzLl9fcmVkb19fLmZvckVhY2goZnVuY3Rpb24gKHJlZG8sIGopIHtcblx0XHRcdFx0XHRpZiAocmVkbyA+IGluZGV4KSB0aGlzLl9fcmVkb19fW2pdID0gLS1yZWRvO1xuXHRcdFx0XHR9LCB0aGlzKTtcblx0XHRcdH0pLFxuXHRcdFx0X29uQ2xlYXI6IGQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRpZiAodGhpcy5fX3JlZG9fXykgY2xlYXIuY2FsbCh0aGlzLl9fcmVkb19fKTtcblx0XHRcdFx0dGhpcy5fX25leHRJbmRleF9fID0gMDtcblx0XHRcdH0pXG5cdFx0fSlcblx0KVxuKTtcblxuZGVmaW5lUHJvcGVydHkoXG5cdEl0ZXJhdG9yLnByb3RvdHlwZSxcblx0U3ltYm9sLml0ZXJhdG9yLFxuXHRkKGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcztcblx0fSlcbik7XG5cbn0se1wiZFwiOjE1MSxcImQvYXV0by1iaW5kXCI6MTUwLFwiZXM1LWV4dC9hcnJheS8jL2NsZWFyXCI6MTczLFwiZXM1LWV4dC9vYmplY3QvYXNzaWduXCI6MTg2LFwiZXM1LWV4dC9vYmplY3QvdmFsaWQtY2FsbGFibGVcIjoyMDMsXCJlczUtZXh0L29iamVjdC92YWxpZC12YWx1ZVwiOjIwNSxcImVzNi1zeW1ib2xcIjoyMTl9XSwyMTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc0FyZ3VtZW50cyA9IF9kZXJlcV8oXCJlczUtZXh0L2Z1bmN0aW9uL2lzLWFyZ3VtZW50c1wiKVxuICAsIGlzVmFsdWUgICAgID0gX2RlcmVxXyhcImVzNS1leHQvb2JqZWN0L2lzLXZhbHVlXCIpXG4gICwgaXNTdHJpbmcgICAgPSBfZGVyZXFfKFwiZXM1LWV4dC9zdHJpbmcvaXMtc3RyaW5nXCIpO1xuXG52YXIgaXRlcmF0b3JTeW1ib2wgPSBfZGVyZXFfKFwiZXM2LXN5bWJvbFwiKS5pdGVyYXRvclxuICAsIGlzQXJyYXkgICAgICAgID0gQXJyYXkuaXNBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0aWYgKCFpc1ZhbHVlKHZhbHVlKSkgcmV0dXJuIGZhbHNlO1xuXHRpZiAoaXNBcnJheSh2YWx1ZSkpIHJldHVybiB0cnVlO1xuXHRpZiAoaXNTdHJpbmcodmFsdWUpKSByZXR1cm4gdHJ1ZTtcblx0aWYgKGlzQXJndW1lbnRzKHZhbHVlKSkgcmV0dXJuIHRydWU7XG5cdHJldHVybiB0eXBlb2YgdmFsdWVbaXRlcmF0b3JTeW1ib2xdID09PSBcImZ1bmN0aW9uXCI7XG59O1xuXG59LHtcImVzNS1leHQvZnVuY3Rpb24vaXMtYXJndW1lbnRzXCI6MTc3LFwiZXM1LWV4dC9vYmplY3QvaXMtdmFsdWVcIjoxOTQsXCJlczUtZXh0L3N0cmluZy9pcy1zdHJpbmdcIjoyMDksXCJlczYtc3ltYm9sXCI6MjE5fV0sMjE2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vIFRoYW5rcyBAbWF0aGlhc2J5bmVuc1xuLy8gaHR0cDovL21hdGhpYXNieW5lbnMuYmUvbm90ZXMvamF2YXNjcmlwdC11bmljb2RlI2l0ZXJhdGluZy1vdmVyLXN5bWJvbHNcblxuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBzZXRQcm90b3R5cGVPZiA9IF9kZXJlcV8oXCJlczUtZXh0L29iamVjdC9zZXQtcHJvdG90eXBlLW9mXCIpXG4gICwgZCAgICAgICAgICAgICAgPSBfZGVyZXFfKFwiZFwiKVxuICAsIFN5bWJvbCAgICAgICAgID0gX2RlcmVxXyhcImVzNi1zeW1ib2xcIilcbiAgLCBJdGVyYXRvciAgICAgICA9IF9kZXJlcV8oXCIuL1wiKTtcblxudmFyIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5LCBTdHJpbmdJdGVyYXRvcjtcblxuU3RyaW5nSXRlcmF0b3IgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzdHIpIHtcblx0aWYgKCEodGhpcyBpbnN0YW5jZW9mIFN0cmluZ0l0ZXJhdG9yKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNvbnN0cnVjdG9yIHJlcXVpcmVzICduZXcnXCIpO1xuXHRzdHIgPSBTdHJpbmcoc3RyKTtcblx0SXRlcmF0b3IuY2FsbCh0aGlzLCBzdHIpO1xuXHRkZWZpbmVQcm9wZXJ0eSh0aGlzLCBcIl9fbGVuZ3RoX19cIiwgZChcIlwiLCBzdHIubGVuZ3RoKSk7XG59O1xuaWYgKHNldFByb3RvdHlwZU9mKSBzZXRQcm90b3R5cGVPZihTdHJpbmdJdGVyYXRvciwgSXRlcmF0b3IpO1xuXG4vLyBJbnRlcm5hbCAlQXJyYXlJdGVyYXRvclByb3RvdHlwZSUgZG9lc24ndCBleHBvc2UgaXRzIGNvbnN0cnVjdG9yXG5kZWxldGUgU3RyaW5nSXRlcmF0b3IucHJvdG90eXBlLmNvbnN0cnVjdG9yO1xuXG5TdHJpbmdJdGVyYXRvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEl0ZXJhdG9yLnByb3RvdHlwZSwge1xuXHRfbmV4dDogZChmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCF0aGlzLl9fbGlzdF9fKSByZXR1cm4gdW5kZWZpbmVkO1xuXHRcdGlmICh0aGlzLl9fbmV4dEluZGV4X18gPCB0aGlzLl9fbGVuZ3RoX18pIHJldHVybiB0aGlzLl9fbmV4dEluZGV4X18rKztcblx0XHR0aGlzLl91bkJpbmQoKTtcblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9KSxcblx0X3Jlc29sdmU6IGQoZnVuY3Rpb24gKGkpIHtcblx0XHR2YXIgY2hhciA9IHRoaXMuX19saXN0X19baV0sIGNvZGU7XG5cdFx0aWYgKHRoaXMuX19uZXh0SW5kZXhfXyA9PT0gdGhpcy5fX2xlbmd0aF9fKSByZXR1cm4gY2hhcjtcblx0XHRjb2RlID0gY2hhci5jaGFyQ29kZUF0KDApO1xuXHRcdGlmIChjb2RlID49IDB4ZDgwMCAmJiBjb2RlIDw9IDB4ZGJmZikgcmV0dXJuIGNoYXIgKyB0aGlzLl9fbGlzdF9fW3RoaXMuX19uZXh0SW5kZXhfXysrXTtcblx0XHRyZXR1cm4gY2hhcjtcblx0fSlcbn0pO1xuZGVmaW5lUHJvcGVydHkoU3RyaW5nSXRlcmF0b3IucHJvdG90eXBlLCBTeW1ib2wudG9TdHJpbmdUYWcsIGQoXCJjXCIsIFwiU3RyaW5nIEl0ZXJhdG9yXCIpKTtcblxufSx7XCIuL1wiOjIxNCxcImRcIjoxNTEsXCJlczUtZXh0L29iamVjdC9zZXQtcHJvdG90eXBlLW9mXCI6MjAwLFwiZXM2LXN5bWJvbFwiOjIxOX1dLDIxNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGlzSXRlcmFibGUgPSBfZGVyZXFfKFwiLi9pcy1pdGVyYWJsZVwiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0aWYgKCFpc0l0ZXJhYmxlKHZhbHVlKSkgdGhyb3cgbmV3IFR5cGVFcnJvcih2YWx1ZSArIFwiIGlzIG5vdCBpdGVyYWJsZVwiKTtcblx0cmV0dXJuIHZhbHVlO1xufTtcblxufSx7XCIuL2lzLWl0ZXJhYmxlXCI6MjE1fV0sMjE4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbihmdW5jdGlvbiAocHJvY2VzcyxnbG9iYWwpe1xuLyohXG4gKiBAb3ZlcnZpZXcgZXM2LXByb21pc2UgLSBhIHRpbnkgaW1wbGVtZW50YXRpb24gb2YgUHJvbWlzZXMvQSsuXG4gKiBAY29weXJpZ2h0IENvcHlyaWdodCAoYykgMjAxNCBZZWh1ZGEgS2F0eiwgVG9tIERhbGUsIFN0ZWZhbiBQZW5uZXIgYW5kIGNvbnRyaWJ1dG9ycyAoQ29udmVyc2lvbiB0byBFUzYgQVBJIGJ5IEpha2UgQXJjaGliYWxkKVxuICogQGxpY2Vuc2UgICBMaWNlbnNlZCB1bmRlciBNSVQgbGljZW5zZVxuICogICAgICAgICAgICBTZWUgaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3N0ZWZhbnBlbm5lci9lczYtcHJvbWlzZS9tYXN0ZXIvTElDRU5TRVxuICogQHZlcnNpb24gICAzLjMuMVxuICovXG5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCkgOlxuICAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShmYWN0b3J5KSA6XG4gICAgKGdsb2JhbC5FUzZQcm9taXNlID0gZmFjdG9yeSgpKTtcbn0odGhpcywgKGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBvYmplY3RPckZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nIHx8IHR5cGVvZiB4ID09PSAnb2JqZWN0JyAmJiB4ICE9PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nO1xufVxuXG52YXIgX2lzQXJyYXkgPSB1bmRlZmluZWQ7XG5pZiAoIUFycmF5LmlzQXJyYXkpIHtcbiAgX2lzQXJyYXkgPSBmdW5jdGlvbiAoeCkge1xuICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoeCkgPT09ICdbb2JqZWN0IEFycmF5XSc7XG4gIH07XG59IGVsc2Uge1xuICBfaXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG59XG5cbnZhciBpc0FycmF5ID0gX2lzQXJyYXk7XG5cbnZhciBsZW4gPSAwO1xudmFyIHZlcnR4TmV4dCA9IHVuZGVmaW5lZDtcbnZhciBjdXN0b21TY2hlZHVsZXJGbiA9IHVuZGVmaW5lZDtcblxudmFyIGFzYXAgPSBmdW5jdGlvbiBhc2FwKGNhbGxiYWNrLCBhcmcpIHtcbiAgcXVldWVbbGVuXSA9IGNhbGxiYWNrO1xuICBxdWV1ZVtsZW4gKyAxXSA9IGFyZztcbiAgbGVuICs9IDI7XG4gIGlmIChsZW4gPT09IDIpIHtcbiAgICAvLyBJZiBsZW4gaXMgMiwgdGhhdCBtZWFucyB0aGF0IHdlIG5lZWQgdG8gc2NoZWR1bGUgYW4gYXN5bmMgZmx1c2guXG4gICAgLy8gSWYgYWRkaXRpb25hbCBjYWxsYmFja3MgYXJlIHF1ZXVlZCBiZWZvcmUgdGhlIHF1ZXVlIGlzIGZsdXNoZWQsIHRoZXlcbiAgICAvLyB3aWxsIGJlIHByb2Nlc3NlZCBieSB0aGlzIGZsdXNoIHRoYXQgd2UgYXJlIHNjaGVkdWxpbmcuXG4gICAgaWYgKGN1c3RvbVNjaGVkdWxlckZuKSB7XG4gICAgICBjdXN0b21TY2hlZHVsZXJGbihmbHVzaCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNjaGVkdWxlRmx1c2goKTtcbiAgICB9XG4gIH1cbn07XG5cbmZ1bmN0aW9uIHNldFNjaGVkdWxlcihzY2hlZHVsZUZuKSB7XG4gIGN1c3RvbVNjaGVkdWxlckZuID0gc2NoZWR1bGVGbjtcbn1cblxuZnVuY3Rpb24gc2V0QXNhcChhc2FwRm4pIHtcbiAgYXNhcCA9IGFzYXBGbjtcbn1cblxudmFyIGJyb3dzZXJXaW5kb3cgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHVuZGVmaW5lZDtcbnZhciBicm93c2VyR2xvYmFsID0gYnJvd3NlcldpbmRvdyB8fCB7fTtcbnZhciBCcm93c2VyTXV0YXRpb25PYnNlcnZlciA9IGJyb3dzZXJHbG9iYWwuTXV0YXRpb25PYnNlcnZlciB8fCBicm93c2VyR2xvYmFsLldlYktpdE11dGF0aW9uT2JzZXJ2ZXI7XG52YXIgaXNOb2RlID0gdHlwZW9mIHNlbGYgPT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiAoe30pLnRvU3RyaW5nLmNhbGwocHJvY2VzcykgPT09ICdbb2JqZWN0IHByb2Nlc3NdJztcblxuLy8gdGVzdCBmb3Igd2ViIHdvcmtlciBidXQgbm90IGluIElFMTBcbnZhciBpc1dvcmtlciA9IHR5cGVvZiBVaW50OENsYW1wZWRBcnJheSAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIGltcG9ydFNjcmlwdHMgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBNZXNzYWdlQ2hhbm5lbCAhPT0gJ3VuZGVmaW5lZCc7XG5cbi8vIG5vZGVcbmZ1bmN0aW9uIHVzZU5leHRUaWNrKCkge1xuICAvLyBub2RlIHZlcnNpb24gMC4xMC54IGRpc3BsYXlzIGEgZGVwcmVjYXRpb24gd2FybmluZyB3aGVuIG5leHRUaWNrIGlzIHVzZWQgcmVjdXJzaXZlbHlcbiAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9jdWpvanMvd2hlbi9pc3N1ZXMvNDEwIGZvciBkZXRhaWxzXG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHByb2Nlc3MubmV4dFRpY2soZmx1c2gpO1xuICB9O1xufVxuXG4vLyB2ZXJ0eFxuZnVuY3Rpb24gdXNlVmVydHhUaW1lcigpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2ZXJ0eE5leHQoZmx1c2gpO1xuICB9O1xufVxuXG5mdW5jdGlvbiB1c2VNdXRhdGlvbk9ic2VydmVyKCkge1xuICB2YXIgaXRlcmF0aW9ucyA9IDA7XG4gIHZhciBvYnNlcnZlciA9IG5ldyBCcm93c2VyTXV0YXRpb25PYnNlcnZlcihmbHVzaCk7XG4gIHZhciBub2RlID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpO1xuICBvYnNlcnZlci5vYnNlcnZlKG5vZGUsIHsgY2hhcmFjdGVyRGF0YTogdHJ1ZSB9KTtcblxuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIG5vZGUuZGF0YSA9IGl0ZXJhdGlvbnMgPSArK2l0ZXJhdGlvbnMgJSAyO1xuICB9O1xufVxuXG4vLyB3ZWIgd29ya2VyXG5mdW5jdGlvbiB1c2VNZXNzYWdlQ2hhbm5lbCgpIHtcbiAgdmFyIGNoYW5uZWwgPSBuZXcgTWVzc2FnZUNoYW5uZWwoKTtcbiAgY2hhbm5lbC5wb3J0MS5vbm1lc3NhZ2UgPSBmbHVzaDtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gY2hhbm5lbC5wb3J0Mi5wb3N0TWVzc2FnZSgwKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gdXNlU2V0VGltZW91dCgpIHtcbiAgLy8gU3RvcmUgc2V0VGltZW91dCByZWZlcmVuY2Ugc28gZXM2LXByb21pc2Ugd2lsbCBiZSB1bmFmZmVjdGVkIGJ5XG4gIC8vIG90aGVyIGNvZGUgbW9kaWZ5aW5nIHNldFRpbWVvdXQgKGxpa2Ugc2lub24udXNlRmFrZVRpbWVycygpKVxuICB2YXIgZ2xvYmFsU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGdsb2JhbFNldFRpbWVvdXQoZmx1c2gsIDEpO1xuICB9O1xufVxuXG52YXIgcXVldWUgPSBuZXcgQXJyYXkoMTAwMCk7XG5mdW5jdGlvbiBmbHVzaCgpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkgKz0gMikge1xuICAgIHZhciBjYWxsYmFjayA9IHF1ZXVlW2ldO1xuICAgIHZhciBhcmcgPSBxdWV1ZVtpICsgMV07XG5cbiAgICBjYWxsYmFjayhhcmcpO1xuXG4gICAgcXVldWVbaV0gPSB1bmRlZmluZWQ7XG4gICAgcXVldWVbaSArIDFdID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgbGVuID0gMDtcbn1cblxuZnVuY3Rpb24gYXR0ZW1wdFZlcnR4KCkge1xuICB0cnkge1xuICAgIHZhciByID0gX2RlcmVxXztcbiAgICB2YXIgdmVydHggPSByKCd2ZXJ0eCcpO1xuICAgIHZlcnR4TmV4dCA9IHZlcnR4LnJ1bk9uTG9vcCB8fCB2ZXJ0eC5ydW5PbkNvbnRleHQ7XG4gICAgcmV0dXJuIHVzZVZlcnR4VGltZXIoKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiB1c2VTZXRUaW1lb3V0KCk7XG4gIH1cbn1cblxudmFyIHNjaGVkdWxlRmx1c2ggPSB1bmRlZmluZWQ7XG4vLyBEZWNpZGUgd2hhdCBhc3luYyBtZXRob2QgdG8gdXNlIHRvIHRyaWdnZXJpbmcgcHJvY2Vzc2luZyBvZiBxdWV1ZWQgY2FsbGJhY2tzOlxuaWYgKGlzTm9kZSkge1xuICBzY2hlZHVsZUZsdXNoID0gdXNlTmV4dFRpY2soKTtcbn0gZWxzZSBpZiAoQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIpIHtcbiAgc2NoZWR1bGVGbHVzaCA9IHVzZU11dGF0aW9uT2JzZXJ2ZXIoKTtcbn0gZWxzZSBpZiAoaXNXb3JrZXIpIHtcbiAgc2NoZWR1bGVGbHVzaCA9IHVzZU1lc3NhZ2VDaGFubmVsKCk7XG59IGVsc2UgaWYgKGJyb3dzZXJXaW5kb3cgPT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgX2RlcmVxXyA9PT0gJ2Z1bmN0aW9uJykge1xuICBzY2hlZHVsZUZsdXNoID0gYXR0ZW1wdFZlcnR4KCk7XG59IGVsc2Uge1xuICBzY2hlZHVsZUZsdXNoID0gdXNlU2V0VGltZW91dCgpO1xufVxuXG5mdW5jdGlvbiB0aGVuKG9uRnVsZmlsbG1lbnQsIG9uUmVqZWN0aW9uKSB7XG4gIHZhciBfYXJndW1lbnRzID0gYXJndW1lbnRzO1xuXG4gIHZhciBwYXJlbnQgPSB0aGlzO1xuXG4gIHZhciBjaGlsZCA9IG5ldyB0aGlzLmNvbnN0cnVjdG9yKG5vb3ApO1xuXG4gIGlmIChjaGlsZFtQUk9NSVNFX0lEXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbWFrZVByb21pc2UoY2hpbGQpO1xuICB9XG5cbiAgdmFyIF9zdGF0ZSA9IHBhcmVudC5fc3RhdGU7XG5cbiAgaWYgKF9zdGF0ZSkge1xuICAgIChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgY2FsbGJhY2sgPSBfYXJndW1lbnRzW19zdGF0ZSAtIDFdO1xuICAgICAgYXNhcChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBpbnZva2VDYWxsYmFjayhfc3RhdGUsIGNoaWxkLCBjYWxsYmFjaywgcGFyZW50Ll9yZXN1bHQpO1xuICAgICAgfSk7XG4gICAgfSkoKTtcbiAgfSBlbHNlIHtcbiAgICBzdWJzY3JpYmUocGFyZW50LCBjaGlsZCwgb25GdWxmaWxsbWVudCwgb25SZWplY3Rpb24pO1xuICB9XG5cbiAgcmV0dXJuIGNoaWxkO1xufVxuXG4vKipcbiAgYFByb21pc2UucmVzb2x2ZWAgcmV0dXJucyBhIHByb21pc2UgdGhhdCB3aWxsIGJlY29tZSByZXNvbHZlZCB3aXRoIHRoZVxuICBwYXNzZWQgYHZhbHVlYC4gSXQgaXMgc2hvcnRoYW5kIGZvciB0aGUgZm9sbG93aW5nOlxuXG4gIGBgYGphdmFzY3JpcHRcbiAgbGV0IHByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgIHJlc29sdmUoMSk7XG4gIH0pO1xuXG4gIHByb21pc2UudGhlbihmdW5jdGlvbih2YWx1ZSl7XG4gICAgLy8gdmFsdWUgPT09IDFcbiAgfSk7XG4gIGBgYFxuXG4gIEluc3RlYWQgb2Ygd3JpdGluZyB0aGUgYWJvdmUsIHlvdXIgY29kZSBub3cgc2ltcGx5IGJlY29tZXMgdGhlIGZvbGxvd2luZzpcblxuICBgYGBqYXZhc2NyaXB0XG4gIGxldCBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKDEpO1xuXG4gIHByb21pc2UudGhlbihmdW5jdGlvbih2YWx1ZSl7XG4gICAgLy8gdmFsdWUgPT09IDFcbiAgfSk7XG4gIGBgYFxuXG4gIEBtZXRob2QgcmVzb2x2ZVxuICBAc3RhdGljXG4gIEBwYXJhbSB7QW55fSB2YWx1ZSB2YWx1ZSB0aGF0IHRoZSByZXR1cm5lZCBwcm9taXNlIHdpbGwgYmUgcmVzb2x2ZWQgd2l0aFxuICBVc2VmdWwgZm9yIHRvb2xpbmcuXG4gIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB0aGF0IHdpbGwgYmVjb21lIGZ1bGZpbGxlZCB3aXRoIHRoZSBnaXZlblxuICBgdmFsdWVgXG4qL1xuZnVuY3Rpb24gcmVzb2x2ZShvYmplY3QpIHtcbiAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUgKi9cbiAgdmFyIENvbnN0cnVjdG9yID0gdGhpcztcblxuICBpZiAob2JqZWN0ICYmIHR5cGVvZiBvYmplY3QgPT09ICdvYmplY3QnICYmIG9iamVjdC5jb25zdHJ1Y3RvciA9PT0gQ29uc3RydWN0b3IpIHtcbiAgICByZXR1cm4gb2JqZWN0O1xuICB9XG5cbiAgdmFyIHByb21pc2UgPSBuZXcgQ29uc3RydWN0b3Iobm9vcCk7XG4gIF9yZXNvbHZlKHByb21pc2UsIG9iamVjdCk7XG4gIHJldHVybiBwcm9taXNlO1xufVxuXG52YXIgUFJPTUlTRV9JRCA9IE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cmluZygxNik7XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG52YXIgUEVORElORyA9IHZvaWQgMDtcbnZhciBGVUxGSUxMRUQgPSAxO1xudmFyIFJFSkVDVEVEID0gMjtcblxudmFyIEdFVF9USEVOX0VSUk9SID0gbmV3IEVycm9yT2JqZWN0KCk7XG5cbmZ1bmN0aW9uIHNlbGZGdWxmaWxsbWVudCgpIHtcbiAgcmV0dXJuIG5ldyBUeXBlRXJyb3IoXCJZb3UgY2Fubm90IHJlc29sdmUgYSBwcm9taXNlIHdpdGggaXRzZWxmXCIpO1xufVxuXG5mdW5jdGlvbiBjYW5ub3RSZXR1cm5Pd24oKSB7XG4gIHJldHVybiBuZXcgVHlwZUVycm9yKCdBIHByb21pc2VzIGNhbGxiYWNrIGNhbm5vdCByZXR1cm4gdGhhdCBzYW1lIHByb21pc2UuJyk7XG59XG5cbmZ1bmN0aW9uIGdldFRoZW4ocHJvbWlzZSkge1xuICB0cnkge1xuICAgIHJldHVybiBwcm9taXNlLnRoZW47XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgR0VUX1RIRU5fRVJST1IuZXJyb3IgPSBlcnJvcjtcbiAgICByZXR1cm4gR0VUX1RIRU5fRVJST1I7XG4gIH1cbn1cblxuZnVuY3Rpb24gdHJ5VGhlbih0aGVuLCB2YWx1ZSwgZnVsZmlsbG1lbnRIYW5kbGVyLCByZWplY3Rpb25IYW5kbGVyKSB7XG4gIHRyeSB7XG4gICAgdGhlbi5jYWxsKHZhbHVlLCBmdWxmaWxsbWVudEhhbmRsZXIsIHJlamVjdGlvbkhhbmRsZXIpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGU7XG4gIH1cbn1cblxuZnVuY3Rpb24gaGFuZGxlRm9yZWlnblRoZW5hYmxlKHByb21pc2UsIHRoZW5hYmxlLCB0aGVuKSB7XG4gIGFzYXAoZnVuY3Rpb24gKHByb21pc2UpIHtcbiAgICB2YXIgc2VhbGVkID0gZmFsc2U7XG4gICAgdmFyIGVycm9yID0gdHJ5VGhlbih0aGVuLCB0aGVuYWJsZSwgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICBpZiAoc2VhbGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHNlYWxlZCA9IHRydWU7XG4gICAgICBpZiAodGhlbmFibGUgIT09IHZhbHVlKSB7XG4gICAgICAgIF9yZXNvbHZlKHByb21pc2UsIHZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgIGlmIChzZWFsZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgc2VhbGVkID0gdHJ1ZTtcblxuICAgICAgX3JlamVjdChwcm9taXNlLCByZWFzb24pO1xuICAgIH0sICdTZXR0bGU6ICcgKyAocHJvbWlzZS5fbGFiZWwgfHwgJyB1bmtub3duIHByb21pc2UnKSk7XG5cbiAgICBpZiAoIXNlYWxlZCAmJiBlcnJvcikge1xuICAgICAgc2VhbGVkID0gdHJ1ZTtcbiAgICAgIF9yZWplY3QocHJvbWlzZSwgZXJyb3IpO1xuICAgIH1cbiAgfSwgcHJvbWlzZSk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZU93blRoZW5hYmxlKHByb21pc2UsIHRoZW5hYmxlKSB7XG4gIGlmICh0aGVuYWJsZS5fc3RhdGUgPT09IEZVTEZJTExFRCkge1xuICAgIGZ1bGZpbGwocHJvbWlzZSwgdGhlbmFibGUuX3Jlc3VsdCk7XG4gIH0gZWxzZSBpZiAodGhlbmFibGUuX3N0YXRlID09PSBSRUpFQ1RFRCkge1xuICAgIF9yZWplY3QocHJvbWlzZSwgdGhlbmFibGUuX3Jlc3VsdCk7XG4gIH0gZWxzZSB7XG4gICAgc3Vic2NyaWJlKHRoZW5hYmxlLCB1bmRlZmluZWQsIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgcmV0dXJuIF9yZXNvbHZlKHByb21pc2UsIHZhbHVlKTtcbiAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICByZXR1cm4gX3JlamVjdChwcm9taXNlLCByZWFzb24pO1xuICAgIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGhhbmRsZU1heWJlVGhlbmFibGUocHJvbWlzZSwgbWF5YmVUaGVuYWJsZSwgdGhlbiQkKSB7XG4gIGlmIChtYXliZVRoZW5hYmxlLmNvbnN0cnVjdG9yID09PSBwcm9taXNlLmNvbnN0cnVjdG9yICYmIHRoZW4kJCA9PT0gdGhlbiAmJiBtYXliZVRoZW5hYmxlLmNvbnN0cnVjdG9yLnJlc29sdmUgPT09IHJlc29sdmUpIHtcbiAgICBoYW5kbGVPd25UaGVuYWJsZShwcm9taXNlLCBtYXliZVRoZW5hYmxlKTtcbiAgfSBlbHNlIHtcbiAgICBpZiAodGhlbiQkID09PSBHRVRfVEhFTl9FUlJPUikge1xuICAgICAgX3JlamVjdChwcm9taXNlLCBHRVRfVEhFTl9FUlJPUi5lcnJvcik7XG4gICAgfSBlbHNlIGlmICh0aGVuJCQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgZnVsZmlsbChwcm9taXNlLCBtYXliZVRoZW5hYmxlKTtcbiAgICB9IGVsc2UgaWYgKGlzRnVuY3Rpb24odGhlbiQkKSkge1xuICAgICAgaGFuZGxlRm9yZWlnblRoZW5hYmxlKHByb21pc2UsIG1heWJlVGhlbmFibGUsIHRoZW4kJCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZ1bGZpbGwocHJvbWlzZSwgbWF5YmVUaGVuYWJsZSk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIF9yZXNvbHZlKHByb21pc2UsIHZhbHVlKSB7XG4gIGlmIChwcm9taXNlID09PSB2YWx1ZSkge1xuICAgIF9yZWplY3QocHJvbWlzZSwgc2VsZkZ1bGZpbGxtZW50KCkpO1xuICB9IGVsc2UgaWYgKG9iamVjdE9yRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgaGFuZGxlTWF5YmVUaGVuYWJsZShwcm9taXNlLCB2YWx1ZSwgZ2V0VGhlbih2YWx1ZSkpO1xuICB9IGVsc2Uge1xuICAgIGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHB1Ymxpc2hSZWplY3Rpb24ocHJvbWlzZSkge1xuICBpZiAocHJvbWlzZS5fb25lcnJvcikge1xuICAgIHByb21pc2UuX29uZXJyb3IocHJvbWlzZS5fcmVzdWx0KTtcbiAgfVxuXG4gIHB1Ymxpc2gocHJvbWlzZSk7XG59XG5cbmZ1bmN0aW9uIGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpIHtcbiAgaWYgKHByb21pc2UuX3N0YXRlICE9PSBQRU5ESU5HKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvbWlzZS5fcmVzdWx0ID0gdmFsdWU7XG4gIHByb21pc2UuX3N0YXRlID0gRlVMRklMTEVEO1xuXG4gIGlmIChwcm9taXNlLl9zdWJzY3JpYmVycy5sZW5ndGggIT09IDApIHtcbiAgICBhc2FwKHB1Ymxpc2gsIHByb21pc2UpO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9yZWplY3QocHJvbWlzZSwgcmVhc29uKSB7XG4gIGlmIChwcm9taXNlLl9zdGF0ZSAhPT0gUEVORElORykge1xuICAgIHJldHVybjtcbiAgfVxuICBwcm9taXNlLl9zdGF0ZSA9IFJFSkVDVEVEO1xuICBwcm9taXNlLl9yZXN1bHQgPSByZWFzb247XG5cbiAgYXNhcChwdWJsaXNoUmVqZWN0aW9uLCBwcm9taXNlKTtcbn1cblxuZnVuY3Rpb24gc3Vic2NyaWJlKHBhcmVudCwgY2hpbGQsIG9uRnVsZmlsbG1lbnQsIG9uUmVqZWN0aW9uKSB7XG4gIHZhciBfc3Vic2NyaWJlcnMgPSBwYXJlbnQuX3N1YnNjcmliZXJzO1xuICB2YXIgbGVuZ3RoID0gX3N1YnNjcmliZXJzLmxlbmd0aDtcblxuICBwYXJlbnQuX29uZXJyb3IgPSBudWxsO1xuXG4gIF9zdWJzY3JpYmVyc1tsZW5ndGhdID0gY2hpbGQ7XG4gIF9zdWJzY3JpYmVyc1tsZW5ndGggKyBGVUxGSUxMRURdID0gb25GdWxmaWxsbWVudDtcbiAgX3N1YnNjcmliZXJzW2xlbmd0aCArIFJFSkVDVEVEXSA9IG9uUmVqZWN0aW9uO1xuXG4gIGlmIChsZW5ndGggPT09IDAgJiYgcGFyZW50Ll9zdGF0ZSkge1xuICAgIGFzYXAocHVibGlzaCwgcGFyZW50KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBwdWJsaXNoKHByb21pc2UpIHtcbiAgdmFyIHN1YnNjcmliZXJzID0gcHJvbWlzZS5fc3Vic2NyaWJlcnM7XG4gIHZhciBzZXR0bGVkID0gcHJvbWlzZS5fc3RhdGU7XG5cbiAgaWYgKHN1YnNjcmliZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBjaGlsZCA9IHVuZGVmaW5lZCxcbiAgICAgIGNhbGxiYWNrID0gdW5kZWZpbmVkLFxuICAgICAgZGV0YWlsID0gcHJvbWlzZS5fcmVzdWx0O1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3Vic2NyaWJlcnMubGVuZ3RoOyBpICs9IDMpIHtcbiAgICBjaGlsZCA9IHN1YnNjcmliZXJzW2ldO1xuICAgIGNhbGxiYWNrID0gc3Vic2NyaWJlcnNbaSArIHNldHRsZWRdO1xuXG4gICAgaWYgKGNoaWxkKSB7XG4gICAgICBpbnZva2VDYWxsYmFjayhzZXR0bGVkLCBjaGlsZCwgY2FsbGJhY2ssIGRldGFpbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrKGRldGFpbCk7XG4gICAgfVxuICB9XG5cbiAgcHJvbWlzZS5fc3Vic2NyaWJlcnMubGVuZ3RoID0gMDtcbn1cblxuZnVuY3Rpb24gRXJyb3JPYmplY3QoKSB7XG4gIHRoaXMuZXJyb3IgPSBudWxsO1xufVxuXG52YXIgVFJZX0NBVENIX0VSUk9SID0gbmV3IEVycm9yT2JqZWN0KCk7XG5cbmZ1bmN0aW9uIHRyeUNhdGNoKGNhbGxiYWNrLCBkZXRhaWwpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gY2FsbGJhY2soZGV0YWlsKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIFRSWV9DQVRDSF9FUlJPUi5lcnJvciA9IGU7XG4gICAgcmV0dXJuIFRSWV9DQVRDSF9FUlJPUjtcbiAgfVxufVxuXG5mdW5jdGlvbiBpbnZva2VDYWxsYmFjayhzZXR0bGVkLCBwcm9taXNlLCBjYWxsYmFjaywgZGV0YWlsKSB7XG4gIHZhciBoYXNDYWxsYmFjayA9IGlzRnVuY3Rpb24oY2FsbGJhY2spLFxuICAgICAgdmFsdWUgPSB1bmRlZmluZWQsXG4gICAgICBlcnJvciA9IHVuZGVmaW5lZCxcbiAgICAgIHN1Y2NlZWRlZCA9IHVuZGVmaW5lZCxcbiAgICAgIGZhaWxlZCA9IHVuZGVmaW5lZDtcblxuICBpZiAoaGFzQ2FsbGJhY2spIHtcbiAgICB2YWx1ZSA9IHRyeUNhdGNoKGNhbGxiYWNrLCBkZXRhaWwpO1xuXG4gICAgaWYgKHZhbHVlID09PSBUUllfQ0FUQ0hfRVJST1IpIHtcbiAgICAgIGZhaWxlZCA9IHRydWU7XG4gICAgICBlcnJvciA9IHZhbHVlLmVycm9yO1xuICAgICAgdmFsdWUgPSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdWNjZWVkZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChwcm9taXNlID09PSB2YWx1ZSkge1xuICAgICAgX3JlamVjdChwcm9taXNlLCBjYW5ub3RSZXR1cm5Pd24oKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhbHVlID0gZGV0YWlsO1xuICAgIHN1Y2NlZWRlZCA9IHRydWU7XG4gIH1cblxuICBpZiAocHJvbWlzZS5fc3RhdGUgIT09IFBFTkRJTkcpIHtcbiAgICAvLyBub29wXG4gIH0gZWxzZSBpZiAoaGFzQ2FsbGJhY2sgJiYgc3VjY2VlZGVkKSB7XG4gICAgICBfcmVzb2x2ZShwcm9taXNlLCB2YWx1ZSk7XG4gICAgfSBlbHNlIGlmIChmYWlsZWQpIHtcbiAgICAgIF9yZWplY3QocHJvbWlzZSwgZXJyb3IpO1xuICAgIH0gZWxzZSBpZiAoc2V0dGxlZCA9PT0gRlVMRklMTEVEKSB7XG4gICAgICBmdWxmaWxsKHByb21pc2UsIHZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHNldHRsZWQgPT09IFJFSkVDVEVEKSB7XG4gICAgICBfcmVqZWN0KHByb21pc2UsIHZhbHVlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVQcm9taXNlKHByb21pc2UsIHJlc29sdmVyKSB7XG4gIHRyeSB7XG4gICAgcmVzb2x2ZXIoZnVuY3Rpb24gcmVzb2x2ZVByb21pc2UodmFsdWUpIHtcbiAgICAgIF9yZXNvbHZlKHByb21pc2UsIHZhbHVlKTtcbiAgICB9LCBmdW5jdGlvbiByZWplY3RQcm9taXNlKHJlYXNvbikge1xuICAgICAgX3JlamVjdChwcm9taXNlLCByZWFzb24pO1xuICAgIH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgX3JlamVjdChwcm9taXNlLCBlKTtcbiAgfVxufVxuXG52YXIgaWQgPSAwO1xuZnVuY3Rpb24gbmV4dElkKCkge1xuICByZXR1cm4gaWQrKztcbn1cblxuZnVuY3Rpb24gbWFrZVByb21pc2UocHJvbWlzZSkge1xuICBwcm9taXNlW1BST01JU0VfSURdID0gaWQrKztcbiAgcHJvbWlzZS5fc3RhdGUgPSB1bmRlZmluZWQ7XG4gIHByb21pc2UuX3Jlc3VsdCA9IHVuZGVmaW5lZDtcbiAgcHJvbWlzZS5fc3Vic2NyaWJlcnMgPSBbXTtcbn1cblxuZnVuY3Rpb24gRW51bWVyYXRvcihDb25zdHJ1Y3RvciwgaW5wdXQpIHtcbiAgdGhpcy5faW5zdGFuY2VDb25zdHJ1Y3RvciA9IENvbnN0cnVjdG9yO1xuICB0aGlzLnByb21pc2UgPSBuZXcgQ29uc3RydWN0b3Iobm9vcCk7XG5cbiAgaWYgKCF0aGlzLnByb21pc2VbUFJPTUlTRV9JRF0pIHtcbiAgICBtYWtlUHJvbWlzZSh0aGlzLnByb21pc2UpO1xuICB9XG5cbiAgaWYgKGlzQXJyYXkoaW5wdXQpKSB7XG4gICAgdGhpcy5faW5wdXQgPSBpbnB1dDtcbiAgICB0aGlzLmxlbmd0aCA9IGlucHV0Lmxlbmd0aDtcbiAgICB0aGlzLl9yZW1haW5pbmcgPSBpbnB1dC5sZW5ndGg7XG5cbiAgICB0aGlzLl9yZXN1bHQgPSBuZXcgQXJyYXkodGhpcy5sZW5ndGgpO1xuXG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBmdWxmaWxsKHRoaXMucHJvbWlzZSwgdGhpcy5fcmVzdWx0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5sZW5ndGggPSB0aGlzLmxlbmd0aCB8fCAwO1xuICAgICAgdGhpcy5fZW51bWVyYXRlKCk7XG4gICAgICBpZiAodGhpcy5fcmVtYWluaW5nID09PSAwKSB7XG4gICAgICAgIGZ1bGZpbGwodGhpcy5wcm9taXNlLCB0aGlzLl9yZXN1bHQpO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBfcmVqZWN0KHRoaXMucHJvbWlzZSwgdmFsaWRhdGlvbkVycm9yKCkpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRpb25FcnJvcigpIHtcbiAgcmV0dXJuIG5ldyBFcnJvcignQXJyYXkgTWV0aG9kcyBtdXN0IGJlIHByb3ZpZGVkIGFuIEFycmF5Jyk7XG59O1xuXG5FbnVtZXJhdG9yLnByb3RvdHlwZS5fZW51bWVyYXRlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgbGVuZ3RoID0gdGhpcy5sZW5ndGg7XG4gIHZhciBfaW5wdXQgPSB0aGlzLl9pbnB1dDtcblxuICBmb3IgKHZhciBpID0gMDsgdGhpcy5fc3RhdGUgPT09IFBFTkRJTkcgJiYgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgdGhpcy5fZWFjaEVudHJ5KF9pbnB1dFtpXSwgaSk7XG4gIH1cbn07XG5cbkVudW1lcmF0b3IucHJvdG90eXBlLl9lYWNoRW50cnkgPSBmdW5jdGlvbiAoZW50cnksIGkpIHtcbiAgdmFyIGMgPSB0aGlzLl9pbnN0YW5jZUNvbnN0cnVjdG9yO1xuICB2YXIgcmVzb2x2ZSQkID0gYy5yZXNvbHZlO1xuXG4gIGlmIChyZXNvbHZlJCQgPT09IHJlc29sdmUpIHtcbiAgICB2YXIgX3RoZW4gPSBnZXRUaGVuKGVudHJ5KTtcblxuICAgIGlmIChfdGhlbiA9PT0gdGhlbiAmJiBlbnRyeS5fc3RhdGUgIT09IFBFTkRJTkcpIHtcbiAgICAgIHRoaXMuX3NldHRsZWRBdChlbnRyeS5fc3RhdGUsIGksIGVudHJ5Ll9yZXN1bHQpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIF90aGVuICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aGlzLl9yZW1haW5pbmctLTtcbiAgICAgIHRoaXMuX3Jlc3VsdFtpXSA9IGVudHJ5O1xuICAgIH0gZWxzZSBpZiAoYyA9PT0gUHJvbWlzZSkge1xuICAgICAgdmFyIHByb21pc2UgPSBuZXcgYyhub29wKTtcbiAgICAgIGhhbmRsZU1heWJlVGhlbmFibGUocHJvbWlzZSwgZW50cnksIF90aGVuKTtcbiAgICAgIHRoaXMuX3dpbGxTZXR0bGVBdChwcm9taXNlLCBpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fd2lsbFNldHRsZUF0KG5ldyBjKGZ1bmN0aW9uIChyZXNvbHZlJCQpIHtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUkJChlbnRyeSk7XG4gICAgICB9KSwgaSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRoaXMuX3dpbGxTZXR0bGVBdChyZXNvbHZlJCQoZW50cnkpLCBpKTtcbiAgfVxufTtcblxuRW51bWVyYXRvci5wcm90b3R5cGUuX3NldHRsZWRBdCA9IGZ1bmN0aW9uIChzdGF0ZSwgaSwgdmFsdWUpIHtcbiAgdmFyIHByb21pc2UgPSB0aGlzLnByb21pc2U7XG5cbiAgaWYgKHByb21pc2UuX3N0YXRlID09PSBQRU5ESU5HKSB7XG4gICAgdGhpcy5fcmVtYWluaW5nLS07XG5cbiAgICBpZiAoc3RhdGUgPT09IFJFSkVDVEVEKSB7XG4gICAgICBfcmVqZWN0KHByb21pc2UsIHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcmVzdWx0W2ldID0gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRoaXMuX3JlbWFpbmluZyA9PT0gMCkge1xuICAgIGZ1bGZpbGwocHJvbWlzZSwgdGhpcy5fcmVzdWx0KTtcbiAgfVxufTtcblxuRW51bWVyYXRvci5wcm90b3R5cGUuX3dpbGxTZXR0bGVBdCA9IGZ1bmN0aW9uIChwcm9taXNlLCBpKSB7XG4gIHZhciBlbnVtZXJhdG9yID0gdGhpcztcblxuICBzdWJzY3JpYmUocHJvbWlzZSwgdW5kZWZpbmVkLCBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gZW51bWVyYXRvci5fc2V0dGxlZEF0KEZVTEZJTExFRCwgaSwgdmFsdWUpO1xuICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgcmV0dXJuIGVudW1lcmF0b3IuX3NldHRsZWRBdChSRUpFQ1RFRCwgaSwgcmVhc29uKTtcbiAgfSk7XG59O1xuXG4vKipcbiAgYFByb21pc2UuYWxsYCBhY2NlcHRzIGFuIGFycmF5IG9mIHByb21pc2VzLCBhbmQgcmV0dXJucyBhIG5ldyBwcm9taXNlIHdoaWNoXG4gIGlzIGZ1bGZpbGxlZCB3aXRoIGFuIGFycmF5IG9mIGZ1bGZpbGxtZW50IHZhbHVlcyBmb3IgdGhlIHBhc3NlZCBwcm9taXNlcywgb3JcbiAgcmVqZWN0ZWQgd2l0aCB0aGUgcmVhc29uIG9mIHRoZSBmaXJzdCBwYXNzZWQgcHJvbWlzZSB0byBiZSByZWplY3RlZC4gSXQgY2FzdHMgYWxsXG4gIGVsZW1lbnRzIG9mIHRoZSBwYXNzZWQgaXRlcmFibGUgdG8gcHJvbWlzZXMgYXMgaXQgcnVucyB0aGlzIGFsZ29yaXRobS5cblxuICBFeGFtcGxlOlxuXG4gIGBgYGphdmFzY3JpcHRcbiAgbGV0IHByb21pc2UxID0gcmVzb2x2ZSgxKTtcbiAgbGV0IHByb21pc2UyID0gcmVzb2x2ZSgyKTtcbiAgbGV0IHByb21pc2UzID0gcmVzb2x2ZSgzKTtcbiAgbGV0IHByb21pc2VzID0gWyBwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzIF07XG5cbiAgUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oYXJyYXkpe1xuICAgIC8vIFRoZSBhcnJheSBoZXJlIHdvdWxkIGJlIFsgMSwgMiwgMyBdO1xuICB9KTtcbiAgYGBgXG5cbiAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBhbGxgIGFyZSByZWplY3RlZCwgdGhlIGZpcnN0IHByb21pc2VcbiAgdGhhdCBpcyByZWplY3RlZCB3aWxsIGJlIGdpdmVuIGFzIGFuIGFyZ3VtZW50IHRvIHRoZSByZXR1cm5lZCBwcm9taXNlcydzXG4gIHJlamVjdGlvbiBoYW5kbGVyLiBGb3IgZXhhbXBsZTpcblxuICBFeGFtcGxlOlxuXG4gIGBgYGphdmFzY3JpcHRcbiAgbGV0IHByb21pc2UxID0gcmVzb2x2ZSgxKTtcbiAgbGV0IHByb21pc2UyID0gcmVqZWN0KG5ldyBFcnJvcihcIjJcIikpO1xuICBsZXQgcHJvbWlzZTMgPSByZWplY3QobmV3IEVycm9yKFwiM1wiKSk7XG4gIGxldCBwcm9taXNlcyA9IFsgcHJvbWlzZTEsIHByb21pc2UyLCBwcm9taXNlMyBdO1xuXG4gIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKGZ1bmN0aW9uKGFycmF5KXtcbiAgICAvLyBDb2RlIGhlcmUgbmV2ZXIgcnVucyBiZWNhdXNlIHRoZXJlIGFyZSByZWplY3RlZCBwcm9taXNlcyFcbiAgfSwgZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAvLyBlcnJvci5tZXNzYWdlID09PSBcIjJcIlxuICB9KTtcbiAgYGBgXG5cbiAgQG1ldGhvZCBhbGxcbiAgQHN0YXRpY1xuICBAcGFyYW0ge0FycmF5fSBlbnRyaWVzIGFycmF5IG9mIHByb21pc2VzXG4gIEBwYXJhbSB7U3RyaW5nfSBsYWJlbCBvcHRpb25hbCBzdHJpbmcgZm9yIGxhYmVsaW5nIHRoZSBwcm9taXNlLlxuICBVc2VmdWwgZm9yIHRvb2xpbmcuXG4gIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UgdGhhdCBpcyBmdWxmaWxsZWQgd2hlbiBhbGwgYHByb21pc2VzYCBoYXZlIGJlZW5cbiAgZnVsZmlsbGVkLCBvciByZWplY3RlZCBpZiBhbnkgb2YgdGhlbSBiZWNvbWUgcmVqZWN0ZWQuXG4gIEBzdGF0aWNcbiovXG5mdW5jdGlvbiBhbGwoZW50cmllcykge1xuICByZXR1cm4gbmV3IEVudW1lcmF0b3IodGhpcywgZW50cmllcykucHJvbWlzZTtcbn1cblxuLyoqXG4gIGBQcm9taXNlLnJhY2VgIHJldHVybnMgYSBuZXcgcHJvbWlzZSB3aGljaCBpcyBzZXR0bGVkIGluIHRoZSBzYW1lIHdheSBhcyB0aGVcbiAgZmlyc3QgcGFzc2VkIHByb21pc2UgdG8gc2V0dGxlLlxuXG4gIEV4YW1wbGU6XG5cbiAgYGBgamF2YXNjcmlwdFxuICBsZXQgcHJvbWlzZTEgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcbiAgICAgIHJlc29sdmUoJ3Byb21pc2UgMScpO1xuICAgIH0sIDIwMCk7XG4gIH0pO1xuXG4gIGxldCBwcm9taXNlMiA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgcmVzb2x2ZSgncHJvbWlzZSAyJyk7XG4gICAgfSwgMTAwKTtcbiAgfSk7XG5cbiAgUHJvbWlzZS5yYWNlKFtwcm9taXNlMSwgcHJvbWlzZTJdKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCl7XG4gICAgLy8gcmVzdWx0ID09PSAncHJvbWlzZSAyJyBiZWNhdXNlIGl0IHdhcyByZXNvbHZlZCBiZWZvcmUgcHJvbWlzZTFcbiAgICAvLyB3YXMgcmVzb2x2ZWQuXG4gIH0pO1xuICBgYGBcblxuICBgUHJvbWlzZS5yYWNlYCBpcyBkZXRlcm1pbmlzdGljIGluIHRoYXQgb25seSB0aGUgc3RhdGUgb2YgdGhlIGZpcnN0XG4gIHNldHRsZWQgcHJvbWlzZSBtYXR0ZXJzLiBGb3IgZXhhbXBsZSwgZXZlbiBpZiBvdGhlciBwcm9taXNlcyBnaXZlbiB0byB0aGVcbiAgYHByb21pc2VzYCBhcnJheSBhcmd1bWVudCBhcmUgcmVzb2x2ZWQsIGJ1dCB0aGUgZmlyc3Qgc2V0dGxlZCBwcm9taXNlIGhhc1xuICBiZWNvbWUgcmVqZWN0ZWQgYmVmb3JlIHRoZSBvdGhlciBwcm9taXNlcyBiZWNhbWUgZnVsZmlsbGVkLCB0aGUgcmV0dXJuZWRcbiAgcHJvbWlzZSB3aWxsIGJlY29tZSByZWplY3RlZDpcblxuICBgYGBqYXZhc2NyaXB0XG4gIGxldCBwcm9taXNlMSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgcmVzb2x2ZSgncHJvbWlzZSAxJyk7XG4gICAgfSwgMjAwKTtcbiAgfSk7XG5cbiAgbGV0IHByb21pc2UyID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICByZWplY3QobmV3IEVycm9yKCdwcm9taXNlIDInKSk7XG4gICAgfSwgMTAwKTtcbiAgfSk7XG5cbiAgUHJvbWlzZS5yYWNlKFtwcm9taXNlMSwgcHJvbWlzZTJdKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCl7XG4gICAgLy8gQ29kZSBoZXJlIG5ldmVyIHJ1bnNcbiAgfSwgZnVuY3Rpb24ocmVhc29uKXtcbiAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gJ3Byb21pc2UgMicgYmVjYXVzZSBwcm9taXNlIDIgYmVjYW1lIHJlamVjdGVkIGJlZm9yZVxuICAgIC8vIHByb21pc2UgMSBiZWNhbWUgZnVsZmlsbGVkXG4gIH0pO1xuICBgYGBcblxuICBBbiBleGFtcGxlIHJlYWwtd29ybGQgdXNlIGNhc2UgaXMgaW1wbGVtZW50aW5nIHRpbWVvdXRzOlxuXG4gIGBgYGphdmFzY3JpcHRcbiAgUHJvbWlzZS5yYWNlKFthamF4KCdmb28uanNvbicpLCB0aW1lb3V0KDUwMDApXSlcbiAgYGBgXG5cbiAgQG1ldGhvZCByYWNlXG4gIEBzdGF0aWNcbiAgQHBhcmFtIHtBcnJheX0gcHJvbWlzZXMgYXJyYXkgb2YgcHJvbWlzZXMgdG8gb2JzZXJ2ZVxuICBVc2VmdWwgZm9yIHRvb2xpbmcuXG4gIEByZXR1cm4ge1Byb21pc2V9IGEgcHJvbWlzZSB3aGljaCBzZXR0bGVzIGluIHRoZSBzYW1lIHdheSBhcyB0aGUgZmlyc3QgcGFzc2VkXG4gIHByb21pc2UgdG8gc2V0dGxlLlxuKi9cbmZ1bmN0aW9uIHJhY2UoZW50cmllcykge1xuICAvKmpzaGludCB2YWxpZHRoaXM6dHJ1ZSAqL1xuICB2YXIgQ29uc3RydWN0b3IgPSB0aGlzO1xuXG4gIGlmICghaXNBcnJheShlbnRyaWVzKSkge1xuICAgIHJldHVybiBuZXcgQ29uc3RydWN0b3IoZnVuY3Rpb24gKF8sIHJlamVjdCkge1xuICAgICAgcmV0dXJuIHJlamVjdChuZXcgVHlwZUVycm9yKCdZb3UgbXVzdCBwYXNzIGFuIGFycmF5IHRvIHJhY2UuJykpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBuZXcgQ29uc3RydWN0b3IoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGVudHJpZXMubGVuZ3RoO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBDb25zdHJ1Y3Rvci5yZXNvbHZlKGVudHJpZXNbaV0pLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAgYFByb21pc2UucmVqZWN0YCByZXR1cm5zIGEgcHJvbWlzZSByZWplY3RlZCB3aXRoIHRoZSBwYXNzZWQgYHJlYXNvbmAuXG4gIEl0IGlzIHNob3J0aGFuZCBmb3IgdGhlIGZvbGxvd2luZzpcblxuICBgYGBqYXZhc2NyaXB0XG4gIGxldCBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXtcbiAgICByZWplY3QobmV3IEVycm9yKCdXSE9PUFMnKSk7XG4gIH0pO1xuXG4gIHByb21pc2UudGhlbihmdW5jdGlvbih2YWx1ZSl7XG4gICAgLy8gQ29kZSBoZXJlIGRvZXNuJ3QgcnVuIGJlY2F1c2UgdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQhXG4gIH0sIGZ1bmN0aW9uKHJlYXNvbil7XG4gICAgLy8gcmVhc29uLm1lc3NhZ2UgPT09ICdXSE9PUFMnXG4gIH0pO1xuICBgYGBcblxuICBJbnN0ZWFkIG9mIHdyaXRpbmcgdGhlIGFib3ZlLCB5b3VyIGNvZGUgbm93IHNpbXBseSBiZWNvbWVzIHRoZSBmb2xsb3dpbmc6XG5cbiAgYGBgamF2YXNjcmlwdFxuICBsZXQgcHJvbWlzZSA9IFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignV0hPT1BTJykpO1xuXG4gIHByb21pc2UudGhlbihmdW5jdGlvbih2YWx1ZSl7XG4gICAgLy8gQ29kZSBoZXJlIGRvZXNuJ3QgcnVuIGJlY2F1c2UgdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQhXG4gIH0sIGZ1bmN0aW9uKHJlYXNvbil7XG4gICAgLy8gcmVhc29uLm1lc3NhZ2UgPT09ICdXSE9PUFMnXG4gIH0pO1xuICBgYGBcblxuICBAbWV0aG9kIHJlamVjdFxuICBAc3RhdGljXG4gIEBwYXJhbSB7QW55fSByZWFzb24gdmFsdWUgdGhhdCB0aGUgcmV0dXJuZWQgcHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkIHdpdGguXG4gIFVzZWZ1bCBmb3IgdG9vbGluZy5cbiAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHJlamVjdGVkIHdpdGggdGhlIGdpdmVuIGByZWFzb25gLlxuKi9cbmZ1bmN0aW9uIHJlamVjdChyZWFzb24pIHtcbiAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUgKi9cbiAgdmFyIENvbnN0cnVjdG9yID0gdGhpcztcbiAgdmFyIHByb21pc2UgPSBuZXcgQ29uc3RydWN0b3Iobm9vcCk7XG4gIF9yZWplY3QocHJvbWlzZSwgcmVhc29uKTtcbiAgcmV0dXJuIHByb21pc2U7XG59XG5cbmZ1bmN0aW9uIG5lZWRzUmVzb2x2ZXIoKSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ1lvdSBtdXN0IHBhc3MgYSByZXNvbHZlciBmdW5jdGlvbiBhcyB0aGUgZmlyc3QgYXJndW1lbnQgdG8gdGhlIHByb21pc2UgY29uc3RydWN0b3InKTtcbn1cblxuZnVuY3Rpb24gbmVlZHNOZXcoKSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJGYWlsZWQgdG8gY29uc3RydWN0ICdQcm9taXNlJzogUGxlYXNlIHVzZSB0aGUgJ25ldycgb3BlcmF0b3IsIHRoaXMgb2JqZWN0IGNvbnN0cnVjdG9yIGNhbm5vdCBiZSBjYWxsZWQgYXMgYSBmdW5jdGlvbi5cIik7XG59XG5cbi8qKlxuICBQcm9taXNlIG9iamVjdHMgcmVwcmVzZW50IHRoZSBldmVudHVhbCByZXN1bHQgb2YgYW4gYXN5bmNocm9ub3VzIG9wZXJhdGlvbi4gVGhlXG4gIHByaW1hcnkgd2F5IG9mIGludGVyYWN0aW5nIHdpdGggYSBwcm9taXNlIGlzIHRocm91Z2ggaXRzIGB0aGVuYCBtZXRob2QsIHdoaWNoXG4gIHJlZ2lzdGVycyBjYWxsYmFja3MgdG8gcmVjZWl2ZSBlaXRoZXIgYSBwcm9taXNlJ3MgZXZlbnR1YWwgdmFsdWUgb3IgdGhlIHJlYXNvblxuICB3aHkgdGhlIHByb21pc2UgY2Fubm90IGJlIGZ1bGZpbGxlZC5cblxuICBUZXJtaW5vbG9neVxuICAtLS0tLS0tLS0tLVxuXG4gIC0gYHByb21pc2VgIGlzIGFuIG9iamVjdCBvciBmdW5jdGlvbiB3aXRoIGEgYHRoZW5gIG1ldGhvZCB3aG9zZSBiZWhhdmlvciBjb25mb3JtcyB0byB0aGlzIHNwZWNpZmljYXRpb24uXG4gIC0gYHRoZW5hYmxlYCBpcyBhbiBvYmplY3Qgb3IgZnVuY3Rpb24gdGhhdCBkZWZpbmVzIGEgYHRoZW5gIG1ldGhvZC5cbiAgLSBgdmFsdWVgIGlzIGFueSBsZWdhbCBKYXZhU2NyaXB0IHZhbHVlIChpbmNsdWRpbmcgdW5kZWZpbmVkLCBhIHRoZW5hYmxlLCBvciBhIHByb21pc2UpLlxuICAtIGBleGNlcHRpb25gIGlzIGEgdmFsdWUgdGhhdCBpcyB0aHJvd24gdXNpbmcgdGhlIHRocm93IHN0YXRlbWVudC5cbiAgLSBgcmVhc29uYCBpcyBhIHZhbHVlIHRoYXQgaW5kaWNhdGVzIHdoeSBhIHByb21pc2Ugd2FzIHJlamVjdGVkLlxuICAtIGBzZXR0bGVkYCB0aGUgZmluYWwgcmVzdGluZyBzdGF0ZSBvZiBhIHByb21pc2UsIGZ1bGZpbGxlZCBvciByZWplY3RlZC5cblxuICBBIHByb21pc2UgY2FuIGJlIGluIG9uZSBvZiB0aHJlZSBzdGF0ZXM6IHBlbmRpbmcsIGZ1bGZpbGxlZCwgb3IgcmVqZWN0ZWQuXG5cbiAgUHJvbWlzZXMgdGhhdCBhcmUgZnVsZmlsbGVkIGhhdmUgYSBmdWxmaWxsbWVudCB2YWx1ZSBhbmQgYXJlIGluIHRoZSBmdWxmaWxsZWRcbiAgc3RhdGUuICBQcm9taXNlcyB0aGF0IGFyZSByZWplY3RlZCBoYXZlIGEgcmVqZWN0aW9uIHJlYXNvbiBhbmQgYXJlIGluIHRoZVxuICByZWplY3RlZCBzdGF0ZS4gIEEgZnVsZmlsbG1lbnQgdmFsdWUgaXMgbmV2ZXIgYSB0aGVuYWJsZS5cblxuICBQcm9taXNlcyBjYW4gYWxzbyBiZSBzYWlkIHRvICpyZXNvbHZlKiBhIHZhbHVlLiAgSWYgdGhpcyB2YWx1ZSBpcyBhbHNvIGFcbiAgcHJvbWlzZSwgdGhlbiB0aGUgb3JpZ2luYWwgcHJvbWlzZSdzIHNldHRsZWQgc3RhdGUgd2lsbCBtYXRjaCB0aGUgdmFsdWUnc1xuICBzZXR0bGVkIHN0YXRlLiAgU28gYSBwcm9taXNlIHRoYXQgKnJlc29sdmVzKiBhIHByb21pc2UgdGhhdCByZWplY3RzIHdpbGxcbiAgaXRzZWxmIHJlamVjdCwgYW5kIGEgcHJvbWlzZSB0aGF0ICpyZXNvbHZlcyogYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgd2lsbFxuICBpdHNlbGYgZnVsZmlsbC5cblxuXG4gIEJhc2ljIFVzYWdlOlxuICAtLS0tLS0tLS0tLS1cblxuICBgYGBqc1xuICBsZXQgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgIC8vIG9uIHN1Y2Nlc3NcbiAgICByZXNvbHZlKHZhbHVlKTtcblxuICAgIC8vIG9uIGZhaWx1cmVcbiAgICByZWplY3QocmVhc29uKTtcbiAgfSk7XG5cbiAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgLy8gb24gZnVsZmlsbG1lbnRcbiAgfSwgZnVuY3Rpb24ocmVhc29uKSB7XG4gICAgLy8gb24gcmVqZWN0aW9uXG4gIH0pO1xuICBgYGBcblxuICBBZHZhbmNlZCBVc2FnZTpcbiAgLS0tLS0tLS0tLS0tLS0tXG5cbiAgUHJvbWlzZXMgc2hpbmUgd2hlbiBhYnN0cmFjdGluZyBhd2F5IGFzeW5jaHJvbm91cyBpbnRlcmFjdGlvbnMgc3VjaCBhc1xuICBgWE1MSHR0cFJlcXVlc3Rgcy5cblxuICBgYGBqc1xuICBmdW5jdGlvbiBnZXRKU09OKHVybCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgICAgbGV0IHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuXG4gICAgICB4aHIub3BlbignR0VUJywgdXJsKTtcbiAgICAgIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBoYW5kbGVyO1xuICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9ICdqc29uJztcbiAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKCdBY2NlcHQnLCAnYXBwbGljYXRpb24vanNvbicpO1xuICAgICAgeGhyLnNlbmQoKTtcblxuICAgICAgZnVuY3Rpb24gaGFuZGxlcigpIHtcbiAgICAgICAgaWYgKHRoaXMucmVhZHlTdGF0ZSA9PT0gdGhpcy5ET05FKSB7XG4gICAgICAgICAgaWYgKHRoaXMuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5yZXNwb25zZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ2dldEpTT046IGAnICsgdXJsICsgJ2AgZmFpbGVkIHdpdGggc3RhdHVzOiBbJyArIHRoaXMuc3RhdHVzICsgJ10nKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgZ2V0SlNPTignL3Bvc3RzLmpzb24nKS50aGVuKGZ1bmN0aW9uKGpzb24pIHtcbiAgICAvLyBvbiBmdWxmaWxsbWVudFxuICB9LCBmdW5jdGlvbihyZWFzb24pIHtcbiAgICAvLyBvbiByZWplY3Rpb25cbiAgfSk7XG4gIGBgYFxuXG4gIFVubGlrZSBjYWxsYmFja3MsIHByb21pc2VzIGFyZSBncmVhdCBjb21wb3NhYmxlIHByaW1pdGl2ZXMuXG5cbiAgYGBganNcbiAgUHJvbWlzZS5hbGwoW1xuICAgIGdldEpTT04oJy9wb3N0cycpLFxuICAgIGdldEpTT04oJy9jb21tZW50cycpXG4gIF0pLnRoZW4oZnVuY3Rpb24odmFsdWVzKXtcbiAgICB2YWx1ZXNbMF0gLy8gPT4gcG9zdHNKU09OXG4gICAgdmFsdWVzWzFdIC8vID0+IGNvbW1lbnRzSlNPTlxuXG4gICAgcmV0dXJuIHZhbHVlcztcbiAgfSk7XG4gIGBgYFxuXG4gIEBjbGFzcyBQcm9taXNlXG4gIEBwYXJhbSB7ZnVuY3Rpb259IHJlc29sdmVyXG4gIFVzZWZ1bCBmb3IgdG9vbGluZy5cbiAgQGNvbnN0cnVjdG9yXG4qL1xuZnVuY3Rpb24gUHJvbWlzZShyZXNvbHZlcikge1xuICB0aGlzW1BST01JU0VfSURdID0gbmV4dElkKCk7XG4gIHRoaXMuX3Jlc3VsdCA9IHRoaXMuX3N0YXRlID0gdW5kZWZpbmVkO1xuICB0aGlzLl9zdWJzY3JpYmVycyA9IFtdO1xuXG4gIGlmIChub29wICE9PSByZXNvbHZlcikge1xuICAgIHR5cGVvZiByZXNvbHZlciAhPT0gJ2Z1bmN0aW9uJyAmJiBuZWVkc1Jlc29sdmVyKCk7XG4gICAgdGhpcyBpbnN0YW5jZW9mIFByb21pc2UgPyBpbml0aWFsaXplUHJvbWlzZSh0aGlzLCByZXNvbHZlcikgOiBuZWVkc05ldygpO1xuICB9XG59XG5cblByb21pc2UuYWxsID0gYWxsO1xuUHJvbWlzZS5yYWNlID0gcmFjZTtcblByb21pc2UucmVzb2x2ZSA9IHJlc29sdmU7XG5Qcm9taXNlLnJlamVjdCA9IHJlamVjdDtcblByb21pc2UuX3NldFNjaGVkdWxlciA9IHNldFNjaGVkdWxlcjtcblByb21pc2UuX3NldEFzYXAgPSBzZXRBc2FwO1xuUHJvbWlzZS5fYXNhcCA9IGFzYXA7XG5cblByb21pc2UucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogUHJvbWlzZSxcblxuICAvKipcbiAgICBUaGUgcHJpbWFyeSB3YXkgb2YgaW50ZXJhY3Rpbmcgd2l0aCBhIHByb21pc2UgaXMgdGhyb3VnaCBpdHMgYHRoZW5gIG1ldGhvZCxcbiAgICB3aGljaCByZWdpc3RlcnMgY2FsbGJhY2tzIHRvIHJlY2VpdmUgZWl0aGVyIGEgcHJvbWlzZSdzIGV2ZW50dWFsIHZhbHVlIG9yIHRoZVxuICAgIHJlYXNvbiB3aHkgdGhlIHByb21pc2UgY2Fubm90IGJlIGZ1bGZpbGxlZC5cbiAgXG4gICAgYGBganNcbiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24odXNlcil7XG4gICAgICAvLyB1c2VyIGlzIGF2YWlsYWJsZVxuICAgIH0sIGZ1bmN0aW9uKHJlYXNvbil7XG4gICAgICAvLyB1c2VyIGlzIHVuYXZhaWxhYmxlLCBhbmQgeW91IGFyZSBnaXZlbiB0aGUgcmVhc29uIHdoeVxuICAgIH0pO1xuICAgIGBgYFxuICBcbiAgICBDaGFpbmluZ1xuICAgIC0tLS0tLS0tXG4gIFxuICAgIFRoZSByZXR1cm4gdmFsdWUgb2YgYHRoZW5gIGlzIGl0c2VsZiBhIHByb21pc2UuICBUaGlzIHNlY29uZCwgJ2Rvd25zdHJlYW0nXG4gICAgcHJvbWlzZSBpcyByZXNvbHZlZCB3aXRoIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGZpcnN0IHByb21pc2UncyBmdWxmaWxsbWVudFxuICAgIG9yIHJlamVjdGlvbiBoYW5kbGVyLCBvciByZWplY3RlZCBpZiB0aGUgaGFuZGxlciB0aHJvd3MgYW4gZXhjZXB0aW9uLlxuICBcbiAgICBgYGBqc1xuICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikge1xuICAgICAgcmV0dXJuIHVzZXIubmFtZTtcbiAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICByZXR1cm4gJ2RlZmF1bHQgbmFtZSc7XG4gICAgfSkudGhlbihmdW5jdGlvbiAodXNlck5hbWUpIHtcbiAgICAgIC8vIElmIGBmaW5kVXNlcmAgZnVsZmlsbGVkLCBgdXNlck5hbWVgIHdpbGwgYmUgdGhlIHVzZXIncyBuYW1lLCBvdGhlcndpc2UgaXRcbiAgICAgIC8vIHdpbGwgYmUgYCdkZWZhdWx0IG5hbWUnYFxuICAgIH0pO1xuICBcbiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24gKHVzZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRm91bmQgdXNlciwgYnV0IHN0aWxsIHVuaGFwcHknKTtcbiAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2BmaW5kVXNlcmAgcmVqZWN0ZWQgYW5kIHdlJ3JlIHVuaGFwcHknKTtcbiAgICB9KS50aGVuKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgLy8gbmV2ZXIgcmVhY2hlZFxuICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgIC8vIGlmIGBmaW5kVXNlcmAgZnVsZmlsbGVkLCBgcmVhc29uYCB3aWxsIGJlICdGb3VuZCB1c2VyLCBidXQgc3RpbGwgdW5oYXBweScuXG4gICAgICAvLyBJZiBgZmluZFVzZXJgIHJlamVjdGVkLCBgcmVhc29uYCB3aWxsIGJlICdgZmluZFVzZXJgIHJlamVjdGVkIGFuZCB3ZSdyZSB1bmhhcHB5Jy5cbiAgICB9KTtcbiAgICBgYGBcbiAgICBJZiB0aGUgZG93bnN0cmVhbSBwcm9taXNlIGRvZXMgbm90IHNwZWNpZnkgYSByZWplY3Rpb24gaGFuZGxlciwgcmVqZWN0aW9uIHJlYXNvbnMgd2lsbCBiZSBwcm9wYWdhdGVkIGZ1cnRoZXIgZG93bnN0cmVhbS5cbiAgXG4gICAgYGBganNcbiAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24gKHVzZXIpIHtcbiAgICAgIHRocm93IG5ldyBQZWRhZ29naWNhbEV4Y2VwdGlvbignVXBzdHJlYW0gZXJyb3InKTtcbiAgICB9KS50aGVuKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgLy8gbmV2ZXIgcmVhY2hlZFxuICAgIH0pLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAvLyBuZXZlciByZWFjaGVkXG4gICAgfSwgZnVuY3Rpb24gKHJlYXNvbikge1xuICAgICAgLy8gVGhlIGBQZWRnYWdvY2lhbEV4Y2VwdGlvbmAgaXMgcHJvcGFnYXRlZCBhbGwgdGhlIHdheSBkb3duIHRvIGhlcmVcbiAgICB9KTtcbiAgICBgYGBcbiAgXG4gICAgQXNzaW1pbGF0aW9uXG4gICAgLS0tLS0tLS0tLS0tXG4gIFxuICAgIFNvbWV0aW1lcyB0aGUgdmFsdWUgeW91IHdhbnQgdG8gcHJvcGFnYXRlIHRvIGEgZG93bnN0cmVhbSBwcm9taXNlIGNhbiBvbmx5IGJlXG4gICAgcmV0cmlldmVkIGFzeW5jaHJvbm91c2x5LiBUaGlzIGNhbiBiZSBhY2hpZXZlZCBieSByZXR1cm5pbmcgYSBwcm9taXNlIGluIHRoZVxuICAgIGZ1bGZpbGxtZW50IG9yIHJlamVjdGlvbiBoYW5kbGVyLiBUaGUgZG93bnN0cmVhbSBwcm9taXNlIHdpbGwgdGhlbiBiZSBwZW5kaW5nXG4gICAgdW50aWwgdGhlIHJldHVybmVkIHByb21pc2UgaXMgc2V0dGxlZC4gVGhpcyBpcyBjYWxsZWQgKmFzc2ltaWxhdGlvbiouXG4gIFxuICAgIGBgYGpzXG4gICAgZmluZFVzZXIoKS50aGVuKGZ1bmN0aW9uICh1c2VyKSB7XG4gICAgICByZXR1cm4gZmluZENvbW1lbnRzQnlBdXRob3IodXNlcik7XG4gICAgfSkudGhlbihmdW5jdGlvbiAoY29tbWVudHMpIHtcbiAgICAgIC8vIFRoZSB1c2VyJ3MgY29tbWVudHMgYXJlIG5vdyBhdmFpbGFibGVcbiAgICB9KTtcbiAgICBgYGBcbiAgXG4gICAgSWYgdGhlIGFzc2ltbGlhdGVkIHByb21pc2UgcmVqZWN0cywgdGhlbiB0aGUgZG93bnN0cmVhbSBwcm9taXNlIHdpbGwgYWxzbyByZWplY3QuXG4gIFxuICAgIGBgYGpzXG4gICAgZmluZFVzZXIoKS50aGVuKGZ1bmN0aW9uICh1c2VyKSB7XG4gICAgICByZXR1cm4gZmluZENvbW1lbnRzQnlBdXRob3IodXNlcik7XG4gICAgfSkudGhlbihmdW5jdGlvbiAoY29tbWVudHMpIHtcbiAgICAgIC8vIElmIGBmaW5kQ29tbWVudHNCeUF1dGhvcmAgZnVsZmlsbHMsIHdlJ2xsIGhhdmUgdGhlIHZhbHVlIGhlcmVcbiAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICAvLyBJZiBgZmluZENvbW1lbnRzQnlBdXRob3JgIHJlamVjdHMsIHdlJ2xsIGhhdmUgdGhlIHJlYXNvbiBoZXJlXG4gICAgfSk7XG4gICAgYGBgXG4gIFxuICAgIFNpbXBsZSBFeGFtcGxlXG4gICAgLS0tLS0tLS0tLS0tLS1cbiAgXG4gICAgU3luY2hyb25vdXMgRXhhbXBsZVxuICBcbiAgICBgYGBqYXZhc2NyaXB0XG4gICAgbGV0IHJlc3VsdDtcbiAgXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGZpbmRSZXN1bHQoKTtcbiAgICAgIC8vIHN1Y2Nlc3NcbiAgICB9IGNhdGNoKHJlYXNvbikge1xuICAgICAgLy8gZmFpbHVyZVxuICAgIH1cbiAgICBgYGBcbiAgXG4gICAgRXJyYmFjayBFeGFtcGxlXG4gIFxuICAgIGBgYGpzXG4gICAgZmluZFJlc3VsdChmdW5jdGlvbihyZXN1bHQsIGVycil7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIC8vIGZhaWx1cmVcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHN1Y2Nlc3NcbiAgICAgIH1cbiAgICB9KTtcbiAgICBgYGBcbiAgXG4gICAgUHJvbWlzZSBFeGFtcGxlO1xuICBcbiAgICBgYGBqYXZhc2NyaXB0XG4gICAgZmluZFJlc3VsdCgpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXtcbiAgICAgIC8vIHN1Y2Nlc3NcbiAgICB9LCBmdW5jdGlvbihyZWFzb24pe1xuICAgICAgLy8gZmFpbHVyZVxuICAgIH0pO1xuICAgIGBgYFxuICBcbiAgICBBZHZhbmNlZCBFeGFtcGxlXG4gICAgLS0tLS0tLS0tLS0tLS1cbiAgXG4gICAgU3luY2hyb25vdXMgRXhhbXBsZVxuICBcbiAgICBgYGBqYXZhc2NyaXB0XG4gICAgbGV0IGF1dGhvciwgYm9va3M7XG4gIFxuICAgIHRyeSB7XG4gICAgICBhdXRob3IgPSBmaW5kQXV0aG9yKCk7XG4gICAgICBib29rcyAgPSBmaW5kQm9va3NCeUF1dGhvcihhdXRob3IpO1xuICAgICAgLy8gc3VjY2Vzc1xuICAgIH0gY2F0Y2gocmVhc29uKSB7XG4gICAgICAvLyBmYWlsdXJlXG4gICAgfVxuICAgIGBgYFxuICBcbiAgICBFcnJiYWNrIEV4YW1wbGVcbiAgXG4gICAgYGBganNcbiAgXG4gICAgZnVuY3Rpb24gZm91bmRCb29rcyhib29rcykge1xuICBcbiAgICB9XG4gIFxuICAgIGZ1bmN0aW9uIGZhaWx1cmUocmVhc29uKSB7XG4gIFxuICAgIH1cbiAgXG4gICAgZmluZEF1dGhvcihmdW5jdGlvbihhdXRob3IsIGVycil7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIGZhaWx1cmUoZXJyKTtcbiAgICAgICAgLy8gZmFpbHVyZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmaW5kQm9vb2tzQnlBdXRob3IoYXV0aG9yLCBmdW5jdGlvbihib29rcywgZXJyKSB7XG4gICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgIGZhaWx1cmUoZXJyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgZm91bmRCb29rcyhib29rcyk7XG4gICAgICAgICAgICAgIH0gY2F0Y2gocmVhc29uKSB7XG4gICAgICAgICAgICAgICAgZmFpbHVyZShyZWFzb24pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAgICAgICBmYWlsdXJlKGVycik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gc3VjY2Vzc1xuICAgICAgfVxuICAgIH0pO1xuICAgIGBgYFxuICBcbiAgICBQcm9taXNlIEV4YW1wbGU7XG4gIFxuICAgIGBgYGphdmFzY3JpcHRcbiAgICBmaW5kQXV0aG9yKCkuXG4gICAgICB0aGVuKGZpbmRCb29rc0J5QXV0aG9yKS5cbiAgICAgIHRoZW4oZnVuY3Rpb24oYm9va3Mpe1xuICAgICAgICAvLyBmb3VuZCBib29rc1xuICAgIH0pLmNhdGNoKGZ1bmN0aW9uKHJlYXNvbil7XG4gICAgICAvLyBzb21ldGhpbmcgd2VudCB3cm9uZ1xuICAgIH0pO1xuICAgIGBgYFxuICBcbiAgICBAbWV0aG9kIHRoZW5cbiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvbkZ1bGZpbGxlZFxuICAgIEBwYXJhbSB7RnVuY3Rpb259IG9uUmVqZWN0ZWRcbiAgICBVc2VmdWwgZm9yIHRvb2xpbmcuXG4gICAgQHJldHVybiB7UHJvbWlzZX1cbiAgKi9cbiAgdGhlbjogdGhlbixcblxuICAvKipcbiAgICBgY2F0Y2hgIGlzIHNpbXBseSBzdWdhciBmb3IgYHRoZW4odW5kZWZpbmVkLCBvblJlamVjdGlvbilgIHdoaWNoIG1ha2VzIGl0IHRoZSBzYW1lXG4gICAgYXMgdGhlIGNhdGNoIGJsb2NrIG9mIGEgdHJ5L2NhdGNoIHN0YXRlbWVudC5cbiAgXG4gICAgYGBganNcbiAgICBmdW5jdGlvbiBmaW5kQXV0aG9yKCl7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkbid0IGZpbmQgdGhhdCBhdXRob3InKTtcbiAgICB9XG4gIFxuICAgIC8vIHN5bmNocm9ub3VzXG4gICAgdHJ5IHtcbiAgICAgIGZpbmRBdXRob3IoKTtcbiAgICB9IGNhdGNoKHJlYXNvbikge1xuICAgICAgLy8gc29tZXRoaW5nIHdlbnQgd3JvbmdcbiAgICB9XG4gIFxuICAgIC8vIGFzeW5jIHdpdGggcHJvbWlzZXNcbiAgICBmaW5kQXV0aG9yKCkuY2F0Y2goZnVuY3Rpb24ocmVhc29uKXtcbiAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nXG4gICAgfSk7XG4gICAgYGBgXG4gIFxuICAgIEBtZXRob2QgY2F0Y2hcbiAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGlvblxuICAgIFVzZWZ1bCBmb3IgdG9vbGluZy5cbiAgICBAcmV0dXJuIHtQcm9taXNlfVxuICAqL1xuICAnY2F0Y2gnOiBmdW5jdGlvbiBfY2F0Y2gob25SZWplY3Rpb24pIHtcbiAgICByZXR1cm4gdGhpcy50aGVuKG51bGwsIG9uUmVqZWN0aW9uKTtcbiAgfVxufTtcblxuZnVuY3Rpb24gcG9seWZpbGwoKSB7XG4gICAgdmFyIGxvY2FsID0gdW5kZWZpbmVkO1xuXG4gICAgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGxvY2FsID0gZ2xvYmFsO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGxvY2FsID0gc2VsZjtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbG9jYWwgPSBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BvbHlmaWxsIGZhaWxlZCBiZWNhdXNlIGdsb2JhbCBvYmplY3QgaXMgdW5hdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIFAgPSBsb2NhbC5Qcm9taXNlO1xuXG4gICAgaWYgKFApIHtcbiAgICAgICAgdmFyIHByb21pc2VUb1N0cmluZyA9IG51bGw7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBwcm9taXNlVG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoUC5yZXNvbHZlKCkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvLyBzaWxlbnRseSBpZ25vcmVkXG4gICAgICAgIH1cblxuICAgICAgICBpZiAocHJvbWlzZVRvU3RyaW5nID09PSAnW29iamVjdCBQcm9taXNlXScgJiYgIVAuY2FzdCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbG9jYWwuUHJvbWlzZSA9IFByb21pc2U7XG59XG5cbnBvbHlmaWxsKCk7XG4vLyBTdHJhbmdlIGNvbXBhdC4uXG5Qcm9taXNlLnBvbHlmaWxsID0gcG9seWZpbGw7XG5Qcm9taXNlLlByb21pc2UgPSBQcm9taXNlO1xuXG5yZXR1cm4gUHJvbWlzZTtcblxufSkpKTtcblxufSkuY2FsbCh0aGlzLF9kZXJlcV8oJ19wcm9jZXNzJyksdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSlcbn0se1wiX3Byb2Nlc3NcIjo0ODJ9XSwyMTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4vaXMtaW1wbGVtZW50ZWQnKSgpID8gU3ltYm9sIDogX2RlcmVxXygnLi9wb2x5ZmlsbCcpO1xuXG59LHtcIi4vaXMtaW1wbGVtZW50ZWRcIjoyMjAsXCIuL3BvbHlmaWxsXCI6MjIyfV0sMjIwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0JztcblxudmFyIHZhbGlkVHlwZXMgPSB7IG9iamVjdDogdHJ1ZSwgc3ltYm9sOiB0cnVlIH07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXHR2YXIgc3ltYm9sO1xuXHRpZiAodHlwZW9mIFN5bWJvbCAhPT0gJ2Z1bmN0aW9uJykgcmV0dXJuIGZhbHNlO1xuXHRzeW1ib2wgPSBTeW1ib2woJ3Rlc3Qgc3ltYm9sJyk7XG5cdHRyeSB7IFN0cmluZyhzeW1ib2wpOyB9IGNhdGNoIChlKSB7IHJldHVybiBmYWxzZTsgfVxuXG5cdC8vIFJldHVybiAndHJ1ZScgYWxzbyBmb3IgcG9seWZpbGxzXG5cdGlmICghdmFsaWRUeXBlc1t0eXBlb2YgU3ltYm9sLml0ZXJhdG9yXSkgcmV0dXJuIGZhbHNlO1xuXHRpZiAoIXZhbGlkVHlwZXNbdHlwZW9mIFN5bWJvbC50b1ByaW1pdGl2ZV0pIHJldHVybiBmYWxzZTtcblx0aWYgKCF2YWxpZFR5cGVzW3R5cGVvZiBTeW1ib2wudG9TdHJpbmdUYWddKSByZXR1cm4gZmFsc2U7XG5cblx0cmV0dXJuIHRydWU7XG59O1xuXG59LHt9XSwyMjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh4KSB7XG5cdGlmICgheCkgcmV0dXJuIGZhbHNlO1xuXHRpZiAodHlwZW9mIHggPT09ICdzeW1ib2wnKSByZXR1cm4gdHJ1ZTtcblx0aWYgKCF4LmNvbnN0cnVjdG9yKSByZXR1cm4gZmFsc2U7XG5cdGlmICh4LmNvbnN0cnVjdG9yLm5hbWUgIT09ICdTeW1ib2wnKSByZXR1cm4gZmFsc2U7XG5cdHJldHVybiAoeFt4LmNvbnN0cnVjdG9yLnRvU3RyaW5nVGFnXSA9PT0gJ1N5bWJvbCcpO1xufTtcblxufSx7fV0sMjIyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vIEVTMjAxNSBTeW1ib2wgcG9seWZpbGwgZm9yIGVudmlyb25tZW50cyB0aGF0IGRvIG5vdCAob3IgcGFydGlhbGx5KSBzdXBwb3J0IGl0XG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQgICAgICAgICAgICAgID0gX2RlcmVxXygnZCcpXG4gICwgdmFsaWRhdGVTeW1ib2wgPSBfZGVyZXFfKCcuL3ZhbGlkYXRlLXN5bWJvbCcpXG5cbiAgLCBjcmVhdGUgPSBPYmplY3QuY3JlYXRlLCBkZWZpbmVQcm9wZXJ0aWVzID0gT2JqZWN0LmRlZmluZVByb3BlcnRpZXNcbiAgLCBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSwgb2JqUHJvdG90eXBlID0gT2JqZWN0LnByb3RvdHlwZVxuICAsIE5hdGl2ZVN5bWJvbCwgU3ltYm9sUG9seWZpbGwsIEhpZGRlblN5bWJvbCwgZ2xvYmFsU3ltYm9scyA9IGNyZWF0ZShudWxsKVxuICAsIGlzTmF0aXZlU2FmZTtcblxuaWYgKHR5cGVvZiBTeW1ib2wgPT09ICdmdW5jdGlvbicpIHtcblx0TmF0aXZlU3ltYm9sID0gU3ltYm9sO1xuXHR0cnkge1xuXHRcdFN0cmluZyhOYXRpdmVTeW1ib2woKSk7XG5cdFx0aXNOYXRpdmVTYWZlID0gdHJ1ZTtcblx0fSBjYXRjaCAoaWdub3JlKSB7fVxufVxuXG52YXIgZ2VuZXJhdGVOYW1lID0gKGZ1bmN0aW9uICgpIHtcblx0dmFyIGNyZWF0ZWQgPSBjcmVhdGUobnVsbCk7XG5cdHJldHVybiBmdW5jdGlvbiAoZGVzYykge1xuXHRcdHZhciBwb3N0Zml4ID0gMCwgbmFtZSwgaWUxMUJ1Z1dvcmthcm91bmQ7XG5cdFx0d2hpbGUgKGNyZWF0ZWRbZGVzYyArIChwb3N0Zml4IHx8ICcnKV0pICsrcG9zdGZpeDtcblx0XHRkZXNjICs9IChwb3N0Zml4IHx8ICcnKTtcblx0XHRjcmVhdGVkW2Rlc2NdID0gdHJ1ZTtcblx0XHRuYW1lID0gJ0BAJyArIGRlc2M7XG5cdFx0ZGVmaW5lUHJvcGVydHkob2JqUHJvdG90eXBlLCBuYW1lLCBkLmdzKG51bGwsIGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRcdFx0Ly8gRm9yIElFMTEgaXNzdWUgc2VlOlxuXHRcdFx0Ly8gaHR0cHM6Ly9jb25uZWN0Lm1pY3Jvc29mdC5jb20vSUUvZmVlZGJhY2tkZXRhaWwvdmlldy8xOTI4NTA4L1xuXHRcdFx0Ly8gICAgaWUxMS1icm9rZW4tZ2V0dGVycy1vbi1kb20tb2JqZWN0c1xuXHRcdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL21lZGlrb28vZXM2LXN5bWJvbC9pc3N1ZXMvMTJcblx0XHRcdGlmIChpZTExQnVnV29ya2Fyb3VuZCkgcmV0dXJuO1xuXHRcdFx0aWUxMUJ1Z1dvcmthcm91bmQgPSB0cnVlO1xuXHRcdFx0ZGVmaW5lUHJvcGVydHkodGhpcywgbmFtZSwgZCh2YWx1ZSkpO1xuXHRcdFx0aWUxMUJ1Z1dvcmthcm91bmQgPSBmYWxzZTtcblx0XHR9KSk7XG5cdFx0cmV0dXJuIG5hbWU7XG5cdH07XG59KCkpO1xuXG4vLyBJbnRlcm5hbCBjb25zdHJ1Y3RvciAobm90IG9uZSBleHBvc2VkKSBmb3IgY3JlYXRpbmcgU3ltYm9sIGluc3RhbmNlcy5cbi8vIFRoaXMgb25lIGlzIHVzZWQgdG8gZW5zdXJlIHRoYXQgYHNvbWVTeW1ib2wgaW5zdGFuY2VvZiBTeW1ib2xgIGFsd2F5cyByZXR1cm4gZmFsc2VcbkhpZGRlblN5bWJvbCA9IGZ1bmN0aW9uIFN5bWJvbChkZXNjcmlwdGlvbikge1xuXHRpZiAodGhpcyBpbnN0YW5jZW9mIEhpZGRlblN5bWJvbCkgdGhyb3cgbmV3IFR5cGVFcnJvcignU3ltYm9sIGlzIG5vdCBhIGNvbnN0cnVjdG9yJyk7XG5cdHJldHVybiBTeW1ib2xQb2x5ZmlsbChkZXNjcmlwdGlvbik7XG59O1xuXG4vLyBFeHBvc2VkIGBTeW1ib2xgIGNvbnN0cnVjdG9yXG4vLyAocmV0dXJucyBpbnN0YW5jZXMgb2YgSGlkZGVuU3ltYm9sKVxubW9kdWxlLmV4cG9ydHMgPSBTeW1ib2xQb2x5ZmlsbCA9IGZ1bmN0aW9uIFN5bWJvbChkZXNjcmlwdGlvbikge1xuXHR2YXIgc3ltYm9sO1xuXHRpZiAodGhpcyBpbnN0YW5jZW9mIFN5bWJvbCkgdGhyb3cgbmV3IFR5cGVFcnJvcignU3ltYm9sIGlzIG5vdCBhIGNvbnN0cnVjdG9yJyk7XG5cdGlmIChpc05hdGl2ZVNhZmUpIHJldHVybiBOYXRpdmVTeW1ib2woZGVzY3JpcHRpb24pO1xuXHRzeW1ib2wgPSBjcmVhdGUoSGlkZGVuU3ltYm9sLnByb3RvdHlwZSk7XG5cdGRlc2NyaXB0aW9uID0gKGRlc2NyaXB0aW9uID09PSB1bmRlZmluZWQgPyAnJyA6IFN0cmluZyhkZXNjcmlwdGlvbikpO1xuXHRyZXR1cm4gZGVmaW5lUHJvcGVydGllcyhzeW1ib2wsIHtcblx0XHRfX2Rlc2NyaXB0aW9uX186IGQoJycsIGRlc2NyaXB0aW9uKSxcblx0XHRfX25hbWVfXzogZCgnJywgZ2VuZXJhdGVOYW1lKGRlc2NyaXB0aW9uKSlcblx0fSk7XG59O1xuZGVmaW5lUHJvcGVydGllcyhTeW1ib2xQb2x5ZmlsbCwge1xuXHRmb3I6IGQoZnVuY3Rpb24gKGtleSkge1xuXHRcdGlmIChnbG9iYWxTeW1ib2xzW2tleV0pIHJldHVybiBnbG9iYWxTeW1ib2xzW2tleV07XG5cdFx0cmV0dXJuIChnbG9iYWxTeW1ib2xzW2tleV0gPSBTeW1ib2xQb2x5ZmlsbChTdHJpbmcoa2V5KSkpO1xuXHR9KSxcblx0a2V5Rm9yOiBkKGZ1bmN0aW9uIChzKSB7XG5cdFx0dmFyIGtleTtcblx0XHR2YWxpZGF0ZVN5bWJvbChzKTtcblx0XHRmb3IgKGtleSBpbiBnbG9iYWxTeW1ib2xzKSBpZiAoZ2xvYmFsU3ltYm9sc1trZXldID09PSBzKSByZXR1cm4ga2V5O1xuXHR9KSxcblxuXHQvLyBUbyBlbnN1cmUgcHJvcGVyIGludGVyb3BlcmFiaWxpdHkgd2l0aCBvdGhlciBuYXRpdmUgZnVuY3Rpb25zIChlLmcuIEFycmF5LmZyb20pXG5cdC8vIGZhbGxiYWNrIHRvIGV2ZW50dWFsIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbiBvZiBnaXZlbiBzeW1ib2xcblx0aGFzSW5zdGFuY2U6IGQoJycsIChOYXRpdmVTeW1ib2wgJiYgTmF0aXZlU3ltYm9sLmhhc0luc3RhbmNlKSB8fCBTeW1ib2xQb2x5ZmlsbCgnaGFzSW5zdGFuY2UnKSksXG5cdGlzQ29uY2F0U3ByZWFkYWJsZTogZCgnJywgKE5hdGl2ZVN5bWJvbCAmJiBOYXRpdmVTeW1ib2wuaXNDb25jYXRTcHJlYWRhYmxlKSB8fFxuXHRcdFN5bWJvbFBvbHlmaWxsKCdpc0NvbmNhdFNwcmVhZGFibGUnKSksXG5cdGl0ZXJhdG9yOiBkKCcnLCAoTmF0aXZlU3ltYm9sICYmIE5hdGl2ZVN5bWJvbC5pdGVyYXRvcikgfHwgU3ltYm9sUG9seWZpbGwoJ2l0ZXJhdG9yJykpLFxuXHRtYXRjaDogZCgnJywgKE5hdGl2ZVN5bWJvbCAmJiBOYXRpdmVTeW1ib2wubWF0Y2gpIHx8IFN5bWJvbFBvbHlmaWxsKCdtYXRjaCcpKSxcblx0cmVwbGFjZTogZCgnJywgKE5hdGl2ZVN5bWJvbCAmJiBOYXRpdmVTeW1ib2wucmVwbGFjZSkgfHwgU3ltYm9sUG9seWZpbGwoJ3JlcGxhY2UnKSksXG5cdHNlYXJjaDogZCgnJywgKE5hdGl2ZVN5bWJvbCAmJiBOYXRpdmVTeW1ib2wuc2VhcmNoKSB8fCBTeW1ib2xQb2x5ZmlsbCgnc2VhcmNoJykpLFxuXHRzcGVjaWVzOiBkKCcnLCAoTmF0aXZlU3ltYm9sICYmIE5hdGl2ZVN5bWJvbC5zcGVjaWVzKSB8fCBTeW1ib2xQb2x5ZmlsbCgnc3BlY2llcycpKSxcblx0c3BsaXQ6IGQoJycsIChOYXRpdmVTeW1ib2wgJiYgTmF0aXZlU3ltYm9sLnNwbGl0KSB8fCBTeW1ib2xQb2x5ZmlsbCgnc3BsaXQnKSksXG5cdHRvUHJpbWl0aXZlOiBkKCcnLCAoTmF0aXZlU3ltYm9sICYmIE5hdGl2ZVN5bWJvbC50b1ByaW1pdGl2ZSkgfHwgU3ltYm9sUG9seWZpbGwoJ3RvUHJpbWl0aXZlJykpLFxuXHR0b1N0cmluZ1RhZzogZCgnJywgKE5hdGl2ZVN5bWJvbCAmJiBOYXRpdmVTeW1ib2wudG9TdHJpbmdUYWcpIHx8IFN5bWJvbFBvbHlmaWxsKCd0b1N0cmluZ1RhZycpKSxcblx0dW5zY29wYWJsZXM6IGQoJycsIChOYXRpdmVTeW1ib2wgJiYgTmF0aXZlU3ltYm9sLnVuc2NvcGFibGVzKSB8fCBTeW1ib2xQb2x5ZmlsbCgndW5zY29wYWJsZXMnKSlcbn0pO1xuXG4vLyBJbnRlcm5hbCB0d2Vha3MgZm9yIHJlYWwgc3ltYm9sIHByb2R1Y2VyXG5kZWZpbmVQcm9wZXJ0aWVzKEhpZGRlblN5bWJvbC5wcm90b3R5cGUsIHtcblx0Y29uc3RydWN0b3I6IGQoU3ltYm9sUG9seWZpbGwpLFxuXHR0b1N0cmluZzogZCgnJywgZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fX25hbWVfXzsgfSlcbn0pO1xuXG4vLyBQcm9wZXIgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBleHBvc2VkIG9uIFN5bWJvbC5wcm90b3R5cGVcbi8vIFRoZXkgd29uJ3QgYmUgYWNjZXNzaWJsZSBvbiBwcm9kdWNlZCBzeW1ib2wgaW5zdGFuY2VzIGFzIHRoZXkgZGVyaXZlIGZyb20gSGlkZGVuU3ltYm9sLnByb3RvdHlwZVxuZGVmaW5lUHJvcGVydGllcyhTeW1ib2xQb2x5ZmlsbC5wcm90b3R5cGUsIHtcblx0dG9TdHJpbmc6IGQoZnVuY3Rpb24gKCkgeyByZXR1cm4gJ1N5bWJvbCAoJyArIHZhbGlkYXRlU3ltYm9sKHRoaXMpLl9fZGVzY3JpcHRpb25fXyArICcpJzsgfSksXG5cdHZhbHVlT2Y6IGQoZnVuY3Rpb24gKCkgeyByZXR1cm4gdmFsaWRhdGVTeW1ib2wodGhpcyk7IH0pXG59KTtcbmRlZmluZVByb3BlcnR5KFN5bWJvbFBvbHlmaWxsLnByb3RvdHlwZSwgU3ltYm9sUG9seWZpbGwudG9QcmltaXRpdmUsIGQoJycsIGZ1bmN0aW9uICgpIHtcblx0dmFyIHN5bWJvbCA9IHZhbGlkYXRlU3ltYm9sKHRoaXMpO1xuXHRpZiAodHlwZW9mIHN5bWJvbCA9PT0gJ3N5bWJvbCcpIHJldHVybiBzeW1ib2w7XG5cdHJldHVybiBzeW1ib2wudG9TdHJpbmcoKTtcbn0pKTtcbmRlZmluZVByb3BlcnR5KFN5bWJvbFBvbHlmaWxsLnByb3RvdHlwZSwgU3ltYm9sUG9seWZpbGwudG9TdHJpbmdUYWcsIGQoJ2MnLCAnU3ltYm9sJykpO1xuXG4vLyBQcm9wZXIgaW1wbGVtZW50YXRvbiBvZiB0b1ByaW1pdGl2ZSBhbmQgdG9TdHJpbmdUYWcgZm9yIHJldHVybmVkIHN5bWJvbCBpbnN0YW5jZXNcbmRlZmluZVByb3BlcnR5KEhpZGRlblN5bWJvbC5wcm90b3R5cGUsIFN5bWJvbFBvbHlmaWxsLnRvU3RyaW5nVGFnLFxuXHRkKCdjJywgU3ltYm9sUG9seWZpbGwucHJvdG90eXBlW1N5bWJvbFBvbHlmaWxsLnRvU3RyaW5nVGFnXSkpO1xuXG4vLyBOb3RlOiBJdCdzIGltcG9ydGFudCB0byBkZWZpbmUgYHRvUHJpbWl0aXZlYCBhcyBsYXN0IG9uZSwgYXMgc29tZSBpbXBsZW1lbnRhdGlvbnNcbi8vIGltcGxlbWVudCBgdG9QcmltaXRpdmVgIG5hdGl2ZWx5IHdpdGhvdXQgaW1wbGVtZW50aW5nIGB0b1N0cmluZ1RhZ2AgKG9yIG90aGVyIHNwZWNpZmllZCBzeW1ib2xzKVxuLy8gQW5kIHRoYXQgbWF5IGludm9rZSBlcnJvciBpbiBkZWZpbml0aW9uIGZsb3c6XG4vLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9tZWRpa29vL2VzNi1zeW1ib2wvaXNzdWVzLzEzI2lzc3VlY29tbWVudC0xNjQxNDYxNDlcbmRlZmluZVByb3BlcnR5KEhpZGRlblN5bWJvbC5wcm90b3R5cGUsIFN5bWJvbFBvbHlmaWxsLnRvUHJpbWl0aXZlLFxuXHRkKCdjJywgU3ltYm9sUG9seWZpbGwucHJvdG90eXBlW1N5bWJvbFBvbHlmaWxsLnRvUHJpbWl0aXZlXSkpO1xuXG59LHtcIi4vdmFsaWRhdGUtc3ltYm9sXCI6MjIzLFwiZFwiOjE1MX1dLDIyMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc1N5bWJvbCA9IF9kZXJlcV8oJy4vaXMtc3ltYm9sJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdGlmICghaXNTeW1ib2wodmFsdWUpKSB0aHJvdyBuZXcgVHlwZUVycm9yKHZhbHVlICsgXCIgaXMgbm90IGEgc3ltYm9sXCIpO1xuXHRyZXR1cm4gdmFsdWU7XG59O1xuXG59LHtcIi4vaXMtc3ltYm9sXCI6MjIxfV0sMjI0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gZXh0cmFjdFBsYW5lc1xuXG5mdW5jdGlvbiBleHRyYWN0UGxhbmVzKE0sIHpOZWFyLCB6RmFyKSB7XG4gIHZhciB6ICA9IHpOZWFyIHx8IDAuMFxuICB2YXIgemYgPSB6RmFyIHx8IDEuMFxuICByZXR1cm4gW1xuICAgIFsgTVsxMl0gKyBNWzBdLCBNWzEzXSArIE1bMV0sIE1bMTRdICsgTVsyXSwgTVsxNV0gKyBNWzNdIF0sXG4gICAgWyBNWzEyXSAtIE1bMF0sIE1bMTNdIC0gTVsxXSwgTVsxNF0gLSBNWzJdLCBNWzE1XSAtIE1bM10gXSxcbiAgICBbIE1bMTJdICsgTVs0XSwgTVsxM10gKyBNWzVdLCBNWzE0XSArIE1bNl0sIE1bMTVdICsgTVs3XSBdLFxuICAgIFsgTVsxMl0gLSBNWzRdLCBNWzEzXSAtIE1bNV0sIE1bMTRdIC0gTVs2XSwgTVsxNV0gLSBNWzddIF0sXG4gICAgWyB6Kk1bMTJdICsgTVs4XSwgeipNWzEzXSArIE1bOV0sIHoqTVsxNF0gKyBNWzEwXSwgeipNWzE1XSArIE1bMTFdIF0sXG4gICAgWyB6ZipNWzEyXSAtIE1bOF0sIHpmKk1bMTNdIC0gTVs5XSwgemYqTVsxNF0gLSBNWzEwXSwgemYqTVsxNV0gLSBNWzExXSBdXG4gIF1cbn1cbn0se31dLDIyNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiAqIGluc3BpcmVkIGJ5IGlzLW51bWJlciA8aHR0cHM6Ly9naXRodWIuY29tL2pvbnNjaGxpbmtlcnQvaXMtbnVtYmVyPlxuICogYnV0IHNpZ25pZmljYW50bHkgc2ltcGxpZmllZCBhbmQgc3BlZCB1cCBieSBpZ25vcmluZyBudW1iZXIgYW5kIHN0cmluZyBjb25zdHJ1Y3RvcnNcbiAqIGllIHRoZXNlIHJldHVybiBmYWxzZTpcbiAqICAgbmV3IE51bWJlcigxKVxuICogICBuZXcgU3RyaW5nKCcxJylcbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBhbGxCbGFua0NoYXJDb2RlcyA9IF9kZXJlcV8oJ2lzLXN0cmluZy1ibGFuaycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG4pIHtcbiAgICB2YXIgdHlwZSA9IHR5cGVvZiBuO1xuICAgIGlmKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHZhciBvcmlnaW5hbCA9IG47XG4gICAgICAgIG4gPSArbjtcbiAgICAgICAgLy8gd2hpdGVzcGFjZSBzdHJpbmdzIGNhc3QgdG8gemVybyAtIGZpbHRlciB0aGVtIG91dFxuICAgICAgICBpZihuPT09MCAmJiBhbGxCbGFua0NoYXJDb2RlcyhvcmlnaW5hbCkpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZWxzZSBpZih0eXBlICE9PSAnbnVtYmVyJykgcmV0dXJuIGZhbHNlO1xuXG4gICAgcmV0dXJuIG4gLSBuIDwgMTtcbn07XG5cbn0se1wiaXMtc3RyaW5nLWJsYW5rXCI6NDIzfV0sMjI2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUZpbHRlcmVkVmVjdG9yXG5cbnZhciBjdWJpY0hlcm1pdGUgPSBfZGVyZXFfKCdjdWJpYy1oZXJtaXRlJylcbnZhciBic2VhcmNoID0gX2RlcmVxXygnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxuXG5mdW5jdGlvbiBjbGFtcChsbywgaGksIHgpIHtcbiAgcmV0dXJuIE1hdGgubWluKGhpLCBNYXRoLm1heChsbywgeCkpXG59XG5cbmZ1bmN0aW9uIEZpbHRlcmVkVmVjdG9yKHN0YXRlMCwgdmVsb2NpdHkwLCB0MCkge1xuICB0aGlzLmRpbWVuc2lvbiAgPSBzdGF0ZTAubGVuZ3RoXG4gIHRoaXMuYm91bmRzICAgICA9IFsgbmV3IEFycmF5KHRoaXMuZGltZW5zaW9uKSwgbmV3IEFycmF5KHRoaXMuZGltZW5zaW9uKSBdXG4gIGZvcih2YXIgaT0wOyBpPHRoaXMuZGltZW5zaW9uOyArK2kpIHtcbiAgICB0aGlzLmJvdW5kc1swXVtpXSA9IC1JbmZpbml0eVxuICAgIHRoaXMuYm91bmRzWzFdW2ldID0gSW5maW5pdHlcbiAgfVxuICB0aGlzLl9zdGF0ZSAgICAgPSBzdGF0ZTAuc2xpY2UoKS5yZXZlcnNlKClcbiAgdGhpcy5fdmVsb2NpdHkgID0gdmVsb2NpdHkwLnNsaWNlKCkucmV2ZXJzZSgpXG4gIHRoaXMuX3RpbWUgICAgICA9IFsgdDAgXVxuICB0aGlzLl9zY3JhdGNoICAgPSBbIHN0YXRlMC5zbGljZSgpLCBzdGF0ZTAuc2xpY2UoKSwgc3RhdGUwLnNsaWNlKCksIHN0YXRlMC5zbGljZSgpLCBzdGF0ZTAuc2xpY2UoKSBdXG59XG5cbnZhciBwcm90byA9IEZpbHRlcmVkVmVjdG9yLnByb3RvdHlwZVxuXG5wcm90by5mbHVzaCA9IGZ1bmN0aW9uKHQpIHtcbiAgdmFyIGlkeCA9IGJzZWFyY2guZ3QodGhpcy5fdGltZSwgdCkgLSAxXG4gIGlmKGlkeCA8PSAwKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdGhpcy5fdGltZS5zcGxpY2UoMCwgaWR4KVxuICB0aGlzLl9zdGF0ZS5zcGxpY2UoMCwgaWR4ICogdGhpcy5kaW1lbnNpb24pXG4gIHRoaXMuX3ZlbG9jaXR5LnNwbGljZSgwLCBpZHggKiB0aGlzLmRpbWVuc2lvbilcbn1cblxucHJvdG8uY3VydmUgPSBmdW5jdGlvbih0KSB7XG4gIHZhciB0aW1lICAgICAgPSB0aGlzLl90aW1lXG4gIHZhciBuICAgICAgICAgPSB0aW1lLmxlbmd0aFxuICB2YXIgaWR4ICAgICAgID0gYnNlYXJjaC5sZSh0aW1lLCB0KVxuICB2YXIgcmVzdWx0ICAgID0gdGhpcy5fc2NyYXRjaFswXVxuICB2YXIgc3RhdGUgICAgID0gdGhpcy5fc3RhdGVcbiAgdmFyIHZlbG9jaXR5ICA9IHRoaXMuX3ZlbG9jaXR5XG4gIHZhciBkICAgICAgICAgPSB0aGlzLmRpbWVuc2lvblxuICB2YXIgYm91bmRzICAgID0gdGhpcy5ib3VuZHNcbiAgaWYoaWR4IDwgMCkge1xuICAgIHZhciBwdHIgPSBkLTFcbiAgICBmb3IodmFyIGk9MDsgaTxkOyArK2ksIC0tcHRyKSB7XG4gICAgICByZXN1bHRbaV0gPSBzdGF0ZVtwdHJdXG4gICAgfVxuICB9IGVsc2UgaWYoaWR4ID49IG4tMSkge1xuICAgIHZhciBwdHIgPSBzdGF0ZS5sZW5ndGgtMVxuICAgIHZhciB0ZiA9IHQgLSB0aW1lW24tMV1cbiAgICBmb3IodmFyIGk9MDsgaTxkOyArK2ksIC0tcHRyKSB7XG4gICAgICByZXN1bHRbaV0gPSBzdGF0ZVtwdHJdICsgdGYgKiB2ZWxvY2l0eVtwdHJdXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBwdHIgPSBkICogKGlkeCsxKSAtIDFcbiAgICB2YXIgdDAgID0gdGltZVtpZHhdXG4gICAgdmFyIHQxICA9IHRpbWVbaWR4KzFdXG4gICAgdmFyIGR0ICA9ICh0MSAtIHQwKSB8fCAxLjBcbiAgICB2YXIgeDAgID0gdGhpcy5fc2NyYXRjaFsxXVxuICAgIHZhciB4MSAgPSB0aGlzLl9zY3JhdGNoWzJdXG4gICAgdmFyIHYwICA9IHRoaXMuX3NjcmF0Y2hbM11cbiAgICB2YXIgdjEgID0gdGhpcy5fc2NyYXRjaFs0XVxuICAgIHZhciBzdGVhZHkgPSB0cnVlXG4gICAgZm9yKHZhciBpPTA7IGk8ZDsgKytpLCAtLXB0cikge1xuICAgICAgeDBbaV0gPSBzdGF0ZVtwdHJdXG4gICAgICB2MFtpXSA9IHZlbG9jaXR5W3B0cl0gKiBkdFxuICAgICAgeDFbaV0gPSBzdGF0ZVtwdHIrZF1cbiAgICAgIHYxW2ldID0gdmVsb2NpdHlbcHRyK2RdICogZHRcbiAgICAgIHN0ZWFkeSA9IHN0ZWFkeSAmJiAoeDBbaV0gPT09IHgxW2ldICYmIHYwW2ldID09PSB2MVtpXSAmJiB2MFtpXSA9PT0gMC4wKVxuICAgIH1cbiAgICBpZihzdGVhZHkpIHtcbiAgICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgICAgICByZXN1bHRbaV0gPSB4MFtpXVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjdWJpY0hlcm1pdGUoeDAsIHYwLCB4MSwgdjEsICh0LXQwKS9kdCwgcmVzdWx0KVxuICAgIH1cbiAgfVxuICB2YXIgbG8gPSBib3VuZHNbMF1cbiAgdmFyIGhpID0gYm91bmRzWzFdXG4gIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IGNsYW1wKGxvW2ldLCBoaVtpXSwgcmVzdWx0W2ldKVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxucHJvdG8uZGN1cnZlID0gZnVuY3Rpb24odCkge1xuICB2YXIgdGltZSAgICAgPSB0aGlzLl90aW1lXG4gIHZhciBuICAgICAgICA9IHRpbWUubGVuZ3RoXG4gIHZhciBpZHggICAgICA9IGJzZWFyY2gubGUodGltZSwgdClcbiAgdmFyIHJlc3VsdCAgID0gdGhpcy5fc2NyYXRjaFswXVxuICB2YXIgc3RhdGUgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgPSB0aGlzLl92ZWxvY2l0eVxuICB2YXIgZCAgICAgICAgPSB0aGlzLmRpbWVuc2lvblxuICBpZihpZHggPj0gbi0xKSB7XG4gICAgdmFyIHB0ciA9IHN0YXRlLmxlbmd0aC0xXG4gICAgdmFyIHRmID0gdCAtIHRpbWVbbi0xXVxuICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSwgLS1wdHIpIHtcbiAgICAgIHJlc3VsdFtpXSA9IHZlbG9jaXR5W3B0cl1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFyIHB0ciA9IGQgKiAoaWR4KzEpIC0gMVxuICAgIHZhciB0MCA9IHRpbWVbaWR4XVxuICAgIHZhciB0MSA9IHRpbWVbaWR4KzFdXG4gICAgdmFyIGR0ID0gKHQxIC0gdDApIHx8IDEuMFxuICAgIHZhciB4MCA9IHRoaXMuX3NjcmF0Y2hbMV1cbiAgICB2YXIgeDEgPSB0aGlzLl9zY3JhdGNoWzJdXG4gICAgdmFyIHYwID0gdGhpcy5fc2NyYXRjaFszXVxuICAgIHZhciB2MSA9IHRoaXMuX3NjcmF0Y2hbNF1cbiAgICB2YXIgc3RlYWR5ID0gdHJ1ZVxuICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSwgLS1wdHIpIHtcbiAgICAgIHgwW2ldID0gc3RhdGVbcHRyXVxuICAgICAgdjBbaV0gPSB2ZWxvY2l0eVtwdHJdICogZHRcbiAgICAgIHgxW2ldID0gc3RhdGVbcHRyK2RdXG4gICAgICB2MVtpXSA9IHZlbG9jaXR5W3B0citkXSAqIGR0XG4gICAgICBzdGVhZHkgPSBzdGVhZHkgJiYgKHgwW2ldID09PSB4MVtpXSAmJiB2MFtpXSA9PT0gdjFbaV0gJiYgdjBbaV0gPT09IDAuMClcbiAgICB9XG4gICAgaWYoc3RlYWR5KSB7XG4gICAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICAgICAgcmVzdWx0W2ldID0gMC4wXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGN1YmljSGVybWl0ZS5kZXJpdmF0aXZlKHgwLCB2MCwgeDEsIHYxLCAodC10MCkvZHQsIHJlc3VsdClcbiAgICAgIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgICAgICByZXN1bHRbaV0gLz0gZHRcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5wcm90by5sYXN0VCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgdGltZSA9IHRoaXMuX3RpbWVcbiAgcmV0dXJuIHRpbWVbdGltZS5sZW5ndGgtMV1cbn1cblxucHJvdG8uc3RhYmxlID0gZnVuY3Rpb24oKSB7XG4gIHZhciB2ZWxvY2l0eSA9IHRoaXMuX3ZlbG9jaXR5XG4gIHZhciBwdHIgPSB2ZWxvY2l0eS5sZW5ndGhcbiAgZm9yKHZhciBpPXRoaXMuZGltZW5zaW9uLTE7IGk+PTA7IC0taSkge1xuICAgIGlmKHZlbG9jaXR5Wy0tcHRyXSkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlXG59XG5cbnByb3RvLmp1bXAgPSBmdW5jdGlvbih0KSB7XG4gIHZhciB0MCA9IHRoaXMubGFzdFQoKVxuICB2YXIgZCAgPSB0aGlzLmRpbWVuc2lvblxuICBpZih0IDwgdDAgfHwgYXJndW1lbnRzLmxlbmd0aCAhPT0gZCsxKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdmFyIHN0YXRlICAgICA9IHRoaXMuX3N0YXRlXG4gIHZhciB2ZWxvY2l0eSAgPSB0aGlzLl92ZWxvY2l0eVxuICB2YXIgcHRyICAgICAgID0gc3RhdGUubGVuZ3RoLXRoaXMuZGltZW5zaW9uXG4gIHZhciBib3VuZHMgICAgPSB0aGlzLmJvdW5kc1xuICB2YXIgbG8gICAgICAgID0gYm91bmRzWzBdXG4gIHZhciBoaSAgICAgICAgPSBib3VuZHNbMV1cbiAgdGhpcy5fdGltZS5wdXNoKHQwLCB0KVxuICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcbiAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICAgIHN0YXRlLnB1c2goc3RhdGVbcHRyKytdKVxuICAgICAgdmVsb2NpdHkucHVzaCgwKVxuICAgIH1cbiAgfVxuICB0aGlzLl90aW1lLnB1c2godClcbiAgZm9yKHZhciBpPWQ7IGk+MDsgLS1pKSB7XG4gICAgc3RhdGUucHVzaChjbGFtcChsb1tpLTFdLCBoaVtpLTFdLCBhcmd1bWVudHNbaV0pKVxuICAgIHZlbG9jaXR5LnB1c2goMClcbiAgfVxufVxuXG5wcm90by5wdXNoID0gZnVuY3Rpb24odCkge1xuICB2YXIgdDAgPSB0aGlzLmxhc3RUKClcbiAgdmFyIGQgID0gdGhpcy5kaW1lbnNpb25cbiAgaWYodCA8IHQwIHx8IGFyZ3VtZW50cy5sZW5ndGggIT09IGQrMSkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBzdGF0ZSAgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgID0gdGhpcy5fdmVsb2NpdHlcbiAgdmFyIHB0ciAgICAgICA9IHN0YXRlLmxlbmd0aC10aGlzLmRpbWVuc2lvblxuICB2YXIgZHQgICAgICAgID0gdCAtIHQwXG4gIHZhciBib3VuZHMgICAgPSB0aGlzLmJvdW5kc1xuICB2YXIgbG8gICAgICAgID0gYm91bmRzWzBdXG4gIHZhciBoaSAgICAgICAgPSBib3VuZHNbMV1cbiAgdmFyIHNmICAgICAgICA9IChkdCA+IDFlLTYpID8gMS9kdCA6IDBcbiAgdGhpcy5fdGltZS5wdXNoKHQpXG4gIGZvcih2YXIgaT1kOyBpPjA7IC0taSkge1xuICAgIHZhciB4YyA9IGNsYW1wKGxvW2ktMV0sIGhpW2ktMV0sIGFyZ3VtZW50c1tpXSlcbiAgICBzdGF0ZS5wdXNoKHhjKVxuICAgIHZlbG9jaXR5LnB1c2goKHhjIC0gc3RhdGVbcHRyKytdKSAqIHNmKVxuICB9XG59XG5cbnByb3RvLnNldCA9IGZ1bmN0aW9uKHQpIHtcbiAgdmFyIGQgPSB0aGlzLmRpbWVuc2lvblxuICBpZih0IDwgdGhpcy5sYXN0VCgpIHx8IGFyZ3VtZW50cy5sZW5ndGggIT09IGQrMSkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBzdGF0ZSAgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgID0gdGhpcy5fdmVsb2NpdHlcbiAgdmFyIGJvdW5kcyAgICA9IHRoaXMuYm91bmRzXG4gIHZhciBsbyAgICAgICAgPSBib3VuZHNbMF1cbiAgdmFyIGhpICAgICAgICA9IGJvdW5kc1sxXVxuICB0aGlzLl90aW1lLnB1c2godClcbiAgZm9yKHZhciBpPWQ7IGk+MDsgLS1pKSB7XG4gICAgc3RhdGUucHVzaChjbGFtcChsb1tpLTFdLCBoaVtpLTFdLCBhcmd1bWVudHNbaV0pKVxuICAgIHZlbG9jaXR5LnB1c2goMClcbiAgfVxufVxuXG5wcm90by5tb3ZlID0gZnVuY3Rpb24odCkge1xuICB2YXIgdDAgPSB0aGlzLmxhc3RUKClcbiAgdmFyIGQgID0gdGhpcy5kaW1lbnNpb25cbiAgaWYodCA8PSB0MCB8fCBhcmd1bWVudHMubGVuZ3RoICE9PSBkKzEpIHtcbiAgICByZXR1cm5cbiAgfVxuICB2YXIgc3RhdGUgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgPSB0aGlzLl92ZWxvY2l0eVxuICB2YXIgc3RhdGVQdHIgPSBzdGF0ZS5sZW5ndGggLSB0aGlzLmRpbWVuc2lvblxuICB2YXIgYm91bmRzICAgPSB0aGlzLmJvdW5kc1xuICB2YXIgbG8gICAgICAgPSBib3VuZHNbMF1cbiAgdmFyIGhpICAgICAgID0gYm91bmRzWzFdXG4gIHZhciBkdCAgICAgICA9IHQgLSB0MFxuICB2YXIgc2YgICAgICAgPSAoZHQgPiAxZS02KSA/IDEvZHQgOiAwLjBcbiAgdGhpcy5fdGltZS5wdXNoKHQpXG4gIGZvcih2YXIgaT1kOyBpPjA7IC0taSkge1xuICAgIHZhciBkeCA9IGFyZ3VtZW50c1tpXVxuICAgIHN0YXRlLnB1c2goY2xhbXAobG9baS0xXSwgaGlbaS0xXSwgc3RhdGVbc3RhdGVQdHIrK10gKyBkeCkpXG4gICAgdmVsb2NpdHkucHVzaChkeCAqIHNmKVxuICB9XG59XG5cbnByb3RvLmlkbGUgPSBmdW5jdGlvbih0KSB7XG4gIHZhciB0MCA9IHRoaXMubGFzdFQoKVxuICBpZih0IDwgdDApIHtcbiAgICByZXR1cm5cbiAgfVxuICB2YXIgZCAgICAgICAgPSB0aGlzLmRpbWVuc2lvblxuICB2YXIgc3RhdGUgICAgPSB0aGlzLl9zdGF0ZVxuICB2YXIgdmVsb2NpdHkgPSB0aGlzLl92ZWxvY2l0eVxuICB2YXIgc3RhdGVQdHIgPSBzdGF0ZS5sZW5ndGgtZFxuICB2YXIgYm91bmRzICAgPSB0aGlzLmJvdW5kc1xuICB2YXIgbG8gICAgICAgPSBib3VuZHNbMF1cbiAgdmFyIGhpICAgICAgID0gYm91bmRzWzFdXG4gIHZhciBkdCAgICAgICA9IHQgLSB0MFxuICB0aGlzLl90aW1lLnB1c2godClcbiAgZm9yKHZhciBpPWQtMTsgaT49MDsgLS1pKSB7XG4gICAgc3RhdGUucHVzaChjbGFtcChsb1tpXSwgaGlbaV0sIHN0YXRlW3N0YXRlUHRyXSArIGR0ICogdmVsb2NpdHlbc3RhdGVQdHJdKSlcbiAgICB2ZWxvY2l0eS5wdXNoKDApXG4gICAgc3RhdGVQdHIgKz0gMVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldFplcm8oZCkge1xuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KGQpXG4gIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IDAuMFxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gY3JlYXRlRmlsdGVyZWRWZWN0b3IoaW5pdFN0YXRlLCBpbml0VmVsb2NpdHksIGluaXRUaW1lKSB7XG4gIHN3aXRjaChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgY2FzZSAwOlxuICAgICAgcmV0dXJuIG5ldyBGaWx0ZXJlZFZlY3RvcihbMF0sIFswXSwgMClcbiAgICBjYXNlIDE6XG4gICAgICBpZih0eXBlb2YgaW5pdFN0YXRlID09PSAnbnVtYmVyJykge1xuICAgICAgICB2YXIgemVybyA9IGdldFplcm8oaW5pdFN0YXRlKVxuICAgICAgICByZXR1cm4gbmV3IEZpbHRlcmVkVmVjdG9yKHplcm8sIHplcm8sIDApXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbmV3IEZpbHRlcmVkVmVjdG9yKGluaXRTdGF0ZSwgZ2V0WmVybyhpbml0U3RhdGUubGVuZ3RoKSwgMClcbiAgICAgIH1cbiAgICBjYXNlIDI6XG4gICAgICBpZih0eXBlb2YgaW5pdFZlbG9jaXR5ID09PSAnbnVtYmVyJykge1xuICAgICAgICB2YXIgemVybyA9IGdldFplcm8oaW5pdFN0YXRlLmxlbmd0aClcbiAgICAgICAgcmV0dXJuIG5ldyBGaWx0ZXJlZFZlY3Rvcihpbml0U3RhdGUsIHplcm8sICtpbml0VmVsb2NpdHkpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbml0VGltZSA9IDBcbiAgICAgIH1cbiAgICBjYXNlIDM6XG4gICAgICBpZihpbml0U3RhdGUubGVuZ3RoICE9PSBpbml0VmVsb2NpdHkubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignc3RhdGUgYW5kIHZlbG9jaXR5IGxlbmd0aHMgbXVzdCBtYXRjaCcpXG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IEZpbHRlcmVkVmVjdG9yKGluaXRTdGF0ZSwgaW5pdFZlbG9jaXR5LCBpbml0VGltZSlcbiAgfVxufVxuXG59LHtcImJpbmFyeS1zZWFyY2gtYm91bmRzXCI6OTEsXCJjdWJpYy1oZXJtaXRlXCI6MTQ1fV0sMjI3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qZXNsaW50IG5ldy1jYXA6MCovXG52YXIgZHR5cGUgPSBfZGVyZXFfKCdkdHlwZScpXG5cbm1vZHVsZS5leHBvcnRzID0gZmxhdHRlblZlcnRleERhdGFcblxuZnVuY3Rpb24gZmxhdHRlblZlcnRleERhdGEgKGRhdGEsIG91dHB1dCwgb2Zmc2V0KSB7XG4gIGlmICghZGF0YSkgdGhyb3cgbmV3IFR5cGVFcnJvcignbXVzdCBzcGVjaWZ5IGRhdGEgYXMgZmlyc3QgcGFyYW1ldGVyJylcbiAgb2Zmc2V0ID0gKyhvZmZzZXQgfHwgMCkgfCAwXG5cbiAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkgJiYgKGRhdGFbMF0gJiYgdHlwZW9mIGRhdGFbMF1bMF0gPT09ICdudW1iZXInKSkge1xuICAgIHZhciBkaW0gPSBkYXRhWzBdLmxlbmd0aFxuICAgIHZhciBsZW5ndGggPSBkYXRhLmxlbmd0aCAqIGRpbVxuICAgIHZhciBpLCBqLCBrLCBsXG5cbiAgICAvLyBubyBvdXRwdXQgc3BlY2lmaWVkLCBjcmVhdGUgYSBuZXcgdHlwZWQgYXJyYXlcbiAgICBpZiAoIW91dHB1dCB8fCB0eXBlb2Ygb3V0cHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgb3V0cHV0ID0gbmV3IChkdHlwZShvdXRwdXQgfHwgJ2Zsb2F0MzInKSkobGVuZ3RoICsgb2Zmc2V0KVxuICAgIH1cblxuICAgIHZhciBkc3RMZW5ndGggPSBvdXRwdXQubGVuZ3RoIC0gb2Zmc2V0XG4gICAgaWYgKGxlbmd0aCAhPT0gZHN0TGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NvdXJjZSBsZW5ndGggJyArIGxlbmd0aCArICcgKCcgKyBkaW0gKyAneCcgKyBkYXRhLmxlbmd0aCArICcpJyArXG4gICAgICAgICcgZG9lcyBub3QgbWF0Y2ggZGVzdGluYXRpb24gbGVuZ3RoICcgKyBkc3RMZW5ndGgpXG4gICAgfVxuXG4gICAgZm9yIChpID0gMCwgayA9IG9mZnNldDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGZvciAoaiA9IDA7IGogPCBkaW07IGorKykge1xuICAgICAgICBvdXRwdXRbaysrXSA9IGRhdGFbaV1bal0gPT09IG51bGwgPyBOYU4gOiBkYXRhW2ldW2pdXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmICghb3V0cHV0IHx8IHR5cGVvZiBvdXRwdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAvLyBubyBvdXRwdXQsIGNyZWF0ZSBhIG5ldyBvbmVcbiAgICAgIHZhciBDdG9yID0gZHR5cGUob3V0cHV0IHx8ICdmbG9hdDMyJylcblxuICAgICAgLy8gaGFuZGxlIGFycmF5cyBzZXBhcmF0ZWx5IGR1ZSB0byBwb3NzaWJsZSBudWxsc1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkgfHwgb3V0cHV0ID09PSAnYXJyYXknKSB7XG4gICAgICAgIG91dHB1dCA9IG5ldyBDdG9yKGRhdGEubGVuZ3RoICsgb2Zmc2V0KVxuICAgICAgICBmb3IgKGkgPSAwLCBrID0gb2Zmc2V0LCBsID0gb3V0cHV0Lmxlbmd0aDsgayA8IGw7IGsrKywgaSsrKSB7XG4gICAgICAgICAgb3V0cHV0W2tdID0gZGF0YVtpXSA9PT0gbnVsbCA/IE5hTiA6IGRhdGFbaV1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKG9mZnNldCA9PT0gMCkge1xuICAgICAgICAgIG91dHB1dCA9IG5ldyBDdG9yKGRhdGEpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3V0cHV0ID0gbmV3IEN0b3IoZGF0YS5sZW5ndGggKyBvZmZzZXQpXG5cbiAgICAgICAgICBvdXRwdXQuc2V0KGRhdGEsIG9mZnNldClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBzdG9yZSBvdXRwdXQgaW4gZXhpc3RpbmcgYXJyYXlcbiAgICAgIG91dHB1dC5zZXQoZGF0YSwgb2Zmc2V0KVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvdXRwdXRcbn1cblxufSx7XCJkdHlwZVwiOjE2OX1dLDIyODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcclxuXHJcbnZhciBzdHJpbmdpZnlGb250ID0gX2RlcmVxXygnY3NzLWZvbnQvc3RyaW5naWZ5JylcclxudmFyIGRlZmF1bHRDaGFycyA9IFszMiwgMTI2XVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBhdGxhc1xyXG5cclxuZnVuY3Rpb24gYXRsYXMob3B0aW9ucykge1xyXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XHJcblxyXG4gIHZhciBzaGFwZSAgPSBvcHRpb25zLnNoYXBlID8gb3B0aW9ucy5zaGFwZSA6IG9wdGlvbnMuY2FudmFzID8gW29wdGlvbnMuY2FudmFzLndpZHRoLCBvcHRpb25zLmNhbnZhcy5oZWlnaHRdIDogWzUxMiwgNTEyXVxyXG4gIHZhciBjYW52YXMgPSBvcHRpb25zLmNhbnZhcyB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxyXG4gIHZhciBmb250ICAgPSBvcHRpb25zLmZvbnRcclxuICB2YXIgc3RlcCAgID0gdHlwZW9mIG9wdGlvbnMuc3RlcCA9PT0gJ251bWJlcicgPyBbb3B0aW9ucy5zdGVwLCBvcHRpb25zLnN0ZXBdIDogb3B0aW9ucy5zdGVwIHx8IFszMiwgMzJdXHJcbiAgdmFyIGNoYXJzICA9IG9wdGlvbnMuY2hhcnMgfHwgZGVmYXVsdENoYXJzXHJcblxyXG4gIGlmIChmb250ICYmIHR5cGVvZiBmb250ICE9PSAnc3RyaW5nJykgZm9udCA9IHN0cmluZ2lmeUZvbnQoZm9udClcclxuXHJcbiAgaWYgKCFBcnJheS5pc0FycmF5KGNoYXJzKSkge1xyXG4gICAgY2hhcnMgPSBTdHJpbmcoY2hhcnMpLnNwbGl0KCcnKVxyXG4gIH0gZWxzZVxyXG4gIGlmIChjaGFycy5sZW5ndGggPT09IDJcclxuICAgICYmIHR5cGVvZiBjaGFyc1swXSA9PT0gJ251bWJlcidcclxuICAgICYmIHR5cGVvZiBjaGFyc1sxXSA9PT0gJ251bWJlcidcclxuICApIHtcclxuICAgIHZhciBuZXdjaGFycyA9IFtdXHJcblxyXG4gICAgZm9yICh2YXIgaSA9IGNoYXJzWzBdLCBqID0gMDsgaSA8PSBjaGFyc1sxXTsgaSsrKSB7XHJcbiAgICAgIG5ld2NoYXJzW2orK10gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGkpXHJcbiAgICB9XHJcblxyXG4gICAgY2hhcnMgPSBuZXdjaGFyc1xyXG4gIH1cclxuXHJcbiAgc2hhcGUgPSBzaGFwZS5zbGljZSgpXHJcbiAgY2FudmFzLndpZHRoICA9IHNoYXBlWzBdXHJcbiAgY2FudmFzLmhlaWdodCA9IHNoYXBlWzFdXHJcblxyXG4gIHZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKVxyXG5cclxuICBjdHguZmlsbFN0eWxlID0gJyMwMDAnXHJcbiAgY3R4LmZpbGxSZWN0KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodClcclxuXHJcbiAgY3R4LmZvbnQgPSBmb250XHJcbiAgY3R4LnRleHRBbGlnbiA9ICdjZW50ZXInXHJcbiAgY3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnXHJcbiAgY3R4LmZpbGxTdHlsZSA9ICcjZmZmJ1xyXG5cclxuICB2YXIgeCA9IHN0ZXBbMF0gLyAyXHJcbiAgdmFyIHkgPSBzdGVwWzFdIC8gMlxyXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgY2hhcnMubGVuZ3RoOyBpKyspIHtcclxuICAgIGN0eC5maWxsVGV4dChjaGFyc1tpXSwgeCwgeSlcclxuICAgIGlmICgoeCArPSBzdGVwWzBdKSA+IHNoYXBlWzBdIC0gc3RlcFswXS8yKSAoeCA9IHN0ZXBbMF0vMiksICh5ICs9IHN0ZXBbMV0pXHJcbiAgfVxyXG5cclxuICByZXR1cm4gY2FudmFzXHJcbn1cclxuXG59LHtcImNzcy1mb250L3N0cmluZ2lmeVwiOjE0Mn1dLDIyOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gbWVhc3VyZVxyXG5cclxubWVhc3VyZS5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxyXG5tZWFzdXJlLmNhY2hlID0ge31cclxuXHJcbmZ1bmN0aW9uIG1lYXN1cmUgKGZvbnQsIG8pIHtcclxuXHRpZiAoIW8pIG8gPSB7fVxyXG5cclxuXHRpZiAodHlwZW9mIGZvbnQgPT09ICdzdHJpbmcnIHx8IEFycmF5LmlzQXJyYXkoZm9udCkpIHtcclxuXHRcdG8uZmFtaWx5ID0gZm9udFxyXG5cdH1cclxuXHJcblx0dmFyIGZhbWlseSA9IEFycmF5LmlzQXJyYXkoby5mYW1pbHkpID8gby5mYW1pbHkuam9pbignLCAnKSA6IG8uZmFtaWx5XHJcblx0aWYgKCFmYW1pbHkpIHRocm93IEVycm9yKCdgZmFtaWx5YCBtdXN0IGJlIGRlZmluZWQnKVxyXG5cclxuXHR2YXIgZnMgPSBvLnNpemUgfHwgby5mb250U2l6ZSB8fCBvLmVtIHx8IDQ4XHJcblx0dmFyIHdlaWdodCA9IG8ud2VpZ2h0IHx8IG8uZm9udFdlaWdodCB8fCAnJ1xyXG5cdHZhciBzdHlsZSA9IG8uc3R5bGUgfHwgby5mb250U3R5bGUgfHwgJydcclxuXHR2YXIgZm9udCA9IFtzdHlsZSwgd2VpZ2h0LCBmc10uam9pbignICcpICsgJ3B4ICcgKyBmYW1pbHlcclxuXHR2YXIgb3JpZ2luID0gby5vcmlnaW4gfHwgJ3RvcCdcclxuXHJcblx0aWYgKG1lYXN1cmUuY2FjaGVbZmFtaWx5XSkge1xyXG5cdFx0Ly8gcmV0dXJuIG1vcmUgcHJlY2lzZSB2YWx1ZXMgaWYgY2FjaGUgaGFzIHRoZW1cclxuXHRcdGlmIChmcyA8PSBtZWFzdXJlLmNhY2hlW2ZhbWlseV0uZW0pIHtcclxuXHRcdFx0cmV0dXJuIGFwcGx5T3JpZ2luKG1lYXN1cmUuY2FjaGVbZmFtaWx5XSwgb3JpZ2luKVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0dmFyIGNhbnZhcyA9IG8uY2FudmFzIHx8IG1lYXN1cmUuY2FudmFzXHJcblx0dmFyIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpXHJcblx0dmFyIGNoYXJzID0ge1xyXG5cdFx0dXBwZXI6IG8udXBwZXIgIT09IHVuZGVmaW5lZCA/IG8udXBwZXIgOiAnSCcsXHJcblx0XHRsb3dlcjogby5sb3dlciAhPT0gdW5kZWZpbmVkID8gby5sb3dlciA6ICd4JyxcclxuXHRcdGRlc2NlbnQ6IG8uZGVzY2VudCAhPT0gdW5kZWZpbmVkID8gby5kZXNjZW50IDogJ3AnLFxyXG5cdFx0YXNjZW50OiBvLmFzY2VudCAhPT0gdW5kZWZpbmVkID8gby5hc2NlbnQgOiAnaCcsXHJcblx0XHR0aXR0bGU6IG8udGl0dGxlICE9PSB1bmRlZmluZWQgPyBvLnRpdHRsZSA6ICdpJyxcclxuXHRcdG92ZXJzaG9vdDogby5vdmVyc2hvb3QgIT09IHVuZGVmaW5lZCA/IG8ub3ZlcnNob290IDogJ08nXHJcblx0fVxyXG5cdHZhciBsID0gTWF0aC5jZWlsKGZzICogMS41KVxyXG5cdGNhbnZhcy5oZWlnaHQgPSBsXHJcblx0Y2FudmFzLndpZHRoID0gbCAqIC41XHJcblx0Y3R4LmZvbnQgPSBmb250XHJcblxyXG5cdHZhciBjaGFyID0gJ0gnXHJcblx0dmFyIHJlc3VsdCA9IHtcclxuXHRcdHRvcDogMFxyXG5cdH1cclxuXHJcblx0Ly8gbWVhc3VyZSBsaW5lLWhlaWdodFxyXG5cdGN0eC5jbGVhclJlY3QoMCwgMCwgbCwgbClcclxuXHRjdHgudGV4dEJhc2VsaW5lID0gJ3RvcCdcclxuXHRjdHguZmlsbFN0eWxlID0gJ2JsYWNrJ1xyXG5cdGN0eC5maWxsVGV4dChjaGFyLCAwLCAwKVxyXG5cdHZhciB0b3BQeCA9IGZpcnN0VG9wKGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgbCwgbCkpXHJcblx0Y3R4LmNsZWFyUmVjdCgwLCAwLCBsLCBsKVxyXG5cdGN0eC50ZXh0QmFzZWxpbmUgPSAnYm90dG9tJ1xyXG5cdGN0eC5maWxsVGV4dChjaGFyLCAwLCBsKVxyXG5cdHZhciBib3R0b21QeCA9IGZpcnN0VG9wKGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgbCwgbCkpXHJcblx0cmVzdWx0LmxpbmVIZWlnaHQgPVxyXG5cdHJlc3VsdC5ib3R0b20gPSBsIC0gYm90dG9tUHggKyB0b3BQeFxyXG5cclxuXHQvLyBtZWFzdXJlIGJhc2VsaW5lXHJcblx0Y3R4LmNsZWFyUmVjdCgwLCAwLCBsLCBsKVxyXG5cdGN0eC50ZXh0QmFzZWxpbmUgPSAnYWxwaGFiZXRpYydcclxuXHRjdHguZmlsbFRleHQoY2hhciwgMCwgbClcclxuXHR2YXIgYmFzZWxpbmVQeCA9IGZpcnN0VG9wKGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgbCwgbCkpXHJcblx0dmFyIGJhc2VsaW5lID0gbCAtIGJhc2VsaW5lUHggLSAxICsgdG9wUHhcclxuXHRyZXN1bHQuYmFzZWxpbmUgPVxyXG5cdHJlc3VsdC5hbHBoYWJldGljID0gYmFzZWxpbmVcclxuXHJcblx0Ly8gbWVhc3VyZSBtZWRpYW5cclxuXHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0Y3R4LnRleHRCYXNlbGluZSA9ICdtaWRkbGUnXHJcblx0Y3R4LmZpbGxUZXh0KGNoYXIsIDAsIGwgKiAuNSlcclxuXHR2YXIgbWVkaWFuUHggPSBmaXJzdFRvcChjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIGwsIGwpKVxyXG5cdHJlc3VsdC5tZWRpYW4gPVxyXG5cdHJlc3VsdC5taWRkbGUgPSBsIC0gbWVkaWFuUHggLSAxICsgdG9wUHggLSBsICogLjVcclxuXHJcblx0Ly8gbWVhc3VyZSBoYW5naW5nXHJcblx0Y3R4LmNsZWFyUmVjdCgwLCAwLCBsLCBsKVxyXG5cdGN0eC50ZXh0QmFzZWxpbmUgPSAnaGFuZ2luZydcclxuXHRjdHguZmlsbFRleHQoY2hhciwgMCwgbCAqIC41KVxyXG5cdHZhciBoYW5naW5nUHggPSBmaXJzdFRvcChjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIGwsIGwpKVxyXG5cdHJlc3VsdC5oYW5naW5nID0gbCAtIGhhbmdpbmdQeCAtIDEgKyB0b3BQeCAtIGwgKiAuNVxyXG5cclxuXHQvLyBtZWFzdXJlIGlkZW9ncmFwaGljXHJcblx0Y3R4LmNsZWFyUmVjdCgwLCAwLCBsLCBsKVxyXG5cdGN0eC50ZXh0QmFzZWxpbmUgPSAnaWRlb2dyYXBoaWMnXHJcblx0Y3R4LmZpbGxUZXh0KGNoYXIsIDAsIGwpXHJcblx0dmFyIGlkZW9ncmFwaGljUHggPSBmaXJzdFRvcChjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIGwsIGwpKVxyXG5cdHJlc3VsdC5pZGVvZ3JhcGhpYyA9IGwgLSBpZGVvZ3JhcGhpY1B4IC0gMSArIHRvcFB4XHJcblxyXG5cdC8vIG1lYXN1cmUgY2FwXHJcblx0aWYgKGNoYXJzLnVwcGVyKSB7XHJcblx0XHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0XHRjdHgudGV4dEJhc2VsaW5lID0gJ3RvcCdcclxuXHRcdGN0eC5maWxsVGV4dChjaGFycy51cHBlciwgMCwgMClcclxuXHRcdHJlc3VsdC51cHBlciA9IGZpcnN0VG9wKGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgbCwgbCkpXHJcblx0XHRyZXN1bHQuY2FwSGVpZ2h0ID0gKHJlc3VsdC5iYXNlbGluZSAtIHJlc3VsdC51cHBlcilcclxuXHR9XHJcblxyXG5cdC8vIG1lYXN1cmUgeFxyXG5cdGlmIChjaGFycy5sb3dlcikge1xyXG5cdFx0Y3R4LmNsZWFyUmVjdCgwLCAwLCBsLCBsKVxyXG5cdFx0Y3R4LnRleHRCYXNlbGluZSA9ICd0b3AnXHJcblx0XHRjdHguZmlsbFRleHQoY2hhcnMubG93ZXIsIDAsIDApXHJcblx0XHRyZXN1bHQubG93ZXIgPSBmaXJzdFRvcChjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIGwsIGwpKVxyXG5cdFx0cmVzdWx0LnhIZWlnaHQgPSAocmVzdWx0LmJhc2VsaW5lIC0gcmVzdWx0Lmxvd2VyKVxyXG5cdH1cclxuXHJcblx0Ly8gbWVhc3VyZSB0aXR0bGVcclxuXHRpZiAoY2hhcnMudGl0dGxlKSB7XHJcblx0XHRjdHguY2xlYXJSZWN0KDAsIDAsIGwsIGwpXHJcblx0XHRjdHgudGV4dEJhc2VsaW5lID0gJ3RvcCdcclxuXHRcdGN0eC5maWxsVGV4dChjaGFycy50aXR0bGUsIDAsIDApXHJcblx0XHRyZXN1bHQudGl0dGxlID0gZmlyc3RUb3AoY3R4LmdldEltYWdlRGF0YSgwLCAwLCBsLCBsKSlcclxuXHR9XHJcblxyXG5cdC8vIG1lYXN1cmUgYXNjZW50XHJcblx0aWYgKGNoYXJzLmFzY2VudCkge1xyXG5cdFx0Y3R4LmNsZWFyUmVjdCgwLCAwLCBsLCBsKVxyXG5cdFx0Y3R4LnRleHRCYXNlbGluZSA9ICd0b3AnXHJcblx0XHRjdHguZmlsbFRleHQoY2hhcnMuYXNjZW50LCAwLCAwKVxyXG5cdFx0cmVzdWx0LmFzY2VudCA9IGZpcnN0VG9wKGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgbCwgbCkpXHJcblx0fVxyXG5cclxuXHQvLyBtZWFzdXJlIGRlc2NlbnRcclxuXHRpZiAoY2hhcnMuZGVzY2VudCkge1xyXG5cdFx0Y3R4LmNsZWFyUmVjdCgwLCAwLCBsLCBsKVxyXG5cdFx0Y3R4LnRleHRCYXNlbGluZSA9ICd0b3AnXHJcblx0XHRjdHguZmlsbFRleHQoY2hhcnMuZGVzY2VudCwgMCwgMClcclxuXHRcdHJlc3VsdC5kZXNjZW50ID0gZmlyc3RCb3R0b20oY3R4LmdldEltYWdlRGF0YSgwLCAwLCBsLCBsKSlcclxuXHR9XHJcblxyXG5cdC8vIG1lYXN1cmUgb3ZlcnNob290XHJcblx0aWYgKGNoYXJzLm92ZXJzaG9vdCkge1xyXG5cdFx0Y3R4LmNsZWFyUmVjdCgwLCAwLCBsLCBsKVxyXG5cdFx0Y3R4LnRleHRCYXNlbGluZSA9ICd0b3AnXHJcblx0XHRjdHguZmlsbFRleHQoY2hhcnMub3ZlcnNob290LCAwLCAwKVxyXG5cdFx0dmFyIG92ZXJzaG9vdFB4ID0gZmlyc3RCb3R0b20oY3R4LmdldEltYWdlRGF0YSgwLCAwLCBsLCBsKSlcclxuXHRcdHJlc3VsdC5vdmVyc2hvb3QgPSBvdmVyc2hvb3RQeCAtIGJhc2VsaW5lXHJcblx0fVxyXG5cclxuXHQvLyBub3JtYWxpemUgcmVzdWx0XHJcblx0Zm9yICh2YXIgbmFtZSBpbiByZXN1bHQpIHtcclxuXHRcdHJlc3VsdFtuYW1lXSAvPSBmc1xyXG5cdH1cclxuXHJcblx0cmVzdWx0LmVtID0gZnNcclxuXHRtZWFzdXJlLmNhY2hlW2ZhbWlseV0gPSByZXN1bHRcclxuXHJcblx0cmV0dXJuIGFwcGx5T3JpZ2luKHJlc3VsdCwgb3JpZ2luKVxyXG59XHJcblxyXG5mdW5jdGlvbiBhcHBseU9yaWdpbihvYmosIG9yaWdpbikge1xyXG5cdHZhciByZXMgPSB7fVxyXG5cdGlmICh0eXBlb2Ygb3JpZ2luID09PSAnc3RyaW5nJykgb3JpZ2luID0gb2JqW29yaWdpbl1cclxuXHRmb3IgKHZhciBuYW1lIGluIG9iaikge1xyXG5cdFx0aWYgKG5hbWUgPT09ICdlbScpIGNvbnRpbnVlXHJcblx0XHRyZXNbbmFtZV0gPSBvYmpbbmFtZV0gLSBvcmlnaW5cclxuXHR9XHJcblx0cmV0dXJuIHJlc1xyXG59XHJcblxyXG5mdW5jdGlvbiBmaXJzdFRvcChpRGF0YSkge1xyXG5cdHZhciBsID0gaURhdGEuaGVpZ2h0XHJcblx0dmFyIGRhdGEgPSBpRGF0YS5kYXRhXHJcblx0Zm9yICh2YXIgaSA9IDM7IGkgPCBkYXRhLmxlbmd0aDsgaSs9NCkge1xyXG5cdFx0aWYgKGRhdGFbaV0gIT09IDApIHtcclxuXHRcdFx0cmV0dXJuIE1hdGguZmxvb3IoKGkgLSAzKSAqLjI1IC8gbClcclxuXHRcdH1cclxuXHR9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGZpcnN0Qm90dG9tKGlEYXRhKSB7XHJcblx0dmFyIGwgPSBpRGF0YS5oZWlnaHRcclxuXHR2YXIgZGF0YSA9IGlEYXRhLmRhdGFcclxuXHRmb3IgKHZhciBpID0gZGF0YS5sZW5ndGggLSAxOyBpID4gMDsgaSAtPSA0KSB7XHJcblx0XHRpZiAoZGF0YVtpXSAhPT0gMCkge1xyXG5cdFx0XHRyZXR1cm4gTWF0aC5mbG9vcigoaSAtIDMpICouMjUgLyBsKVxyXG5cdFx0fVxyXG5cdH1cclxufVxyXG5cbn0se31dLDIzMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVJCVHJlZVxuXG52YXIgUkVEICAgPSAwXG52YXIgQkxBQ0sgPSAxXG5cbmZ1bmN0aW9uIFJCTm9kZShjb2xvciwga2V5LCB2YWx1ZSwgbGVmdCwgcmlnaHQsIGNvdW50KSB7XG4gIHRoaXMuX2NvbG9yID0gY29sb3JcbiAgdGhpcy5rZXkgPSBrZXlcbiAgdGhpcy52YWx1ZSA9IHZhbHVlXG4gIHRoaXMubGVmdCA9IGxlZnRcbiAgdGhpcy5yaWdodCA9IHJpZ2h0XG4gIHRoaXMuX2NvdW50ID0gY291bnRcbn1cblxuZnVuY3Rpb24gY2xvbmVOb2RlKG5vZGUpIHtcbiAgcmV0dXJuIG5ldyBSQk5vZGUobm9kZS5fY29sb3IsIG5vZGUua2V5LCBub2RlLnZhbHVlLCBub2RlLmxlZnQsIG5vZGUucmlnaHQsIG5vZGUuX2NvdW50KVxufVxuXG5mdW5jdGlvbiByZXBhaW50KGNvbG9yLCBub2RlKSB7XG4gIHJldHVybiBuZXcgUkJOb2RlKGNvbG9yLCBub2RlLmtleSwgbm9kZS52YWx1ZSwgbm9kZS5sZWZ0LCBub2RlLnJpZ2h0LCBub2RlLl9jb3VudClcbn1cblxuZnVuY3Rpb24gcmVjb3VudChub2RlKSB7XG4gIG5vZGUuX2NvdW50ID0gMSArIChub2RlLmxlZnQgPyBub2RlLmxlZnQuX2NvdW50IDogMCkgKyAobm9kZS5yaWdodCA/IG5vZGUucmlnaHQuX2NvdW50IDogMClcbn1cblxuZnVuY3Rpb24gUmVkQmxhY2tUcmVlKGNvbXBhcmUsIHJvb3QpIHtcbiAgdGhpcy5fY29tcGFyZSA9IGNvbXBhcmVcbiAgdGhpcy5yb290ID0gcm9vdFxufVxuXG52YXIgcHJvdG8gPSBSZWRCbGFja1RyZWUucHJvdG90eXBlXG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywgXCJrZXlzXCIsIHtcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICB2YXIgcmVzdWx0ID0gW11cbiAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24oayx2KSB7XG4gICAgICByZXN1bHQucHVzaChrKVxuICAgIH0pXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG59KVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sIFwidmFsdWVzXCIsIHtcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICB2YXIgcmVzdWx0ID0gW11cbiAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24oayx2KSB7XG4gICAgICByZXN1bHQucHVzaCh2KVxuICAgIH0pXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG59KVxuXG4vL1JldHVybnMgdGhlIG51bWJlciBvZiBub2RlcyBpbiB0aGUgdHJlZVxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCBcImxlbmd0aFwiLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5yb290KSB7XG4gICAgICByZXR1cm4gdGhpcy5yb290Ll9jb3VudFxuICAgIH1cbiAgICByZXR1cm4gMFxuICB9XG59KVxuXG4vL0luc2VydCBhIG5ldyBpdGVtIGludG8gdGhlIHRyZWVcbnByb3RvLmluc2VydCA9IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgdmFyIGNtcCA9IHRoaXMuX2NvbXBhcmVcbiAgLy9GaW5kIHBvaW50IHRvIGluc2VydCBuZXcgbm9kZSBhdFxuICB2YXIgbiA9IHRoaXMucm9vdFxuICB2YXIgbl9zdGFjayA9IFtdXG4gIHZhciBkX3N0YWNrID0gW11cbiAgd2hpbGUobikge1xuICAgIHZhciBkID0gY21wKGtleSwgbi5rZXkpXG4gICAgbl9zdGFjay5wdXNoKG4pXG4gICAgZF9zdGFjay5wdXNoKGQpXG4gICAgaWYoZCA8PSAwKSB7XG4gICAgICBuID0gbi5sZWZ0XG4gICAgfSBlbHNlIHtcbiAgICAgIG4gPSBuLnJpZ2h0XG4gICAgfVxuICB9XG4gIC8vUmVidWlsZCBwYXRoIHRvIGxlYWYgbm9kZVxuICBuX3N0YWNrLnB1c2gobmV3IFJCTm9kZShSRUQsIGtleSwgdmFsdWUsIG51bGwsIG51bGwsIDEpKVxuICBmb3IodmFyIHM9bl9zdGFjay5sZW5ndGgtMjsgcz49MDsgLS1zKSB7XG4gICAgdmFyIG4gPSBuX3N0YWNrW3NdXG4gICAgaWYoZF9zdGFja1tzXSA8PSAwKSB7XG4gICAgICBuX3N0YWNrW3NdID0gbmV3IFJCTm9kZShuLl9jb2xvciwgbi5rZXksIG4udmFsdWUsIG5fc3RhY2tbcysxXSwgbi5yaWdodCwgbi5fY291bnQrMSlcbiAgICB9IGVsc2Uge1xuICAgICAgbl9zdGFja1tzXSA9IG5ldyBSQk5vZGUobi5fY29sb3IsIG4ua2V5LCBuLnZhbHVlLCBuLmxlZnQsIG5fc3RhY2tbcysxXSwgbi5fY291bnQrMSlcbiAgICB9XG4gIH1cbiAgLy9SZWJhbGFuY2UgdHJlZSB1c2luZyByb3RhdGlvbnNcbiAgLy9jb25zb2xlLmxvZyhcInN0YXJ0IGluc2VydFwiLCBrZXksIGRfc3RhY2spXG4gIGZvcih2YXIgcz1uX3N0YWNrLmxlbmd0aC0xOyBzPjE7IC0tcykge1xuICAgIHZhciBwID0gbl9zdGFja1tzLTFdXG4gICAgdmFyIG4gPSBuX3N0YWNrW3NdXG4gICAgaWYocC5fY29sb3IgPT09IEJMQUNLIHx8IG4uX2NvbG9yID09PSBCTEFDSykge1xuICAgICAgYnJlYWtcbiAgICB9XG4gICAgdmFyIHBwID0gbl9zdGFja1tzLTJdXG4gICAgaWYocHAubGVmdCA9PT0gcCkge1xuICAgICAgaWYocC5sZWZ0ID09PSBuKSB7XG4gICAgICAgIHZhciB5ID0gcHAucmlnaHRcbiAgICAgICAgaWYoeSAmJiB5Ll9jb2xvciA9PT0gUkVEKSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcIkxMclwiKVxuICAgICAgICAgIHAuX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgICBwcC5yaWdodCA9IHJlcGFpbnQoQkxBQ0ssIHkpXG4gICAgICAgICAgcHAuX2NvbG9yID0gUkVEXG4gICAgICAgICAgcyAtPSAxXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcIkxMYlwiKVxuICAgICAgICAgIHBwLl9jb2xvciA9IFJFRFxuICAgICAgICAgIHBwLmxlZnQgPSBwLnJpZ2h0XG4gICAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICAgIHAucmlnaHQgPSBwcFxuICAgICAgICAgIG5fc3RhY2tbcy0yXSA9IHBcbiAgICAgICAgICBuX3N0YWNrW3MtMV0gPSBuXG4gICAgICAgICAgcmVjb3VudChwcClcbiAgICAgICAgICByZWNvdW50KHApXG4gICAgICAgICAgaWYocyA+PSAzKSB7XG4gICAgICAgICAgICB2YXIgcHBwID0gbl9zdGFja1tzLTNdXG4gICAgICAgICAgICBpZihwcHAubGVmdCA9PT0gcHApIHtcbiAgICAgICAgICAgICAgcHBwLmxlZnQgPSBwXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwcHAucmlnaHQgPSBwXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB5ID0gcHAucmlnaHRcbiAgICAgICAgaWYoeSAmJiB5Ll9jb2xvciA9PT0gUkVEKSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcIkxSclwiKVxuICAgICAgICAgIHAuX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgICBwcC5yaWdodCA9IHJlcGFpbnQoQkxBQ0ssIHkpXG4gICAgICAgICAgcHAuX2NvbG9yID0gUkVEXG4gICAgICAgICAgcyAtPSAxXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcIkxSYlwiKVxuICAgICAgICAgIHAucmlnaHQgPSBuLmxlZnRcbiAgICAgICAgICBwcC5fY29sb3IgPSBSRURcbiAgICAgICAgICBwcC5sZWZ0ID0gbi5yaWdodFxuICAgICAgICAgIG4uX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgICBuLmxlZnQgPSBwXG4gICAgICAgICAgbi5yaWdodCA9IHBwXG4gICAgICAgICAgbl9zdGFja1tzLTJdID0gblxuICAgICAgICAgIG5fc3RhY2tbcy0xXSA9IHBcbiAgICAgICAgICByZWNvdW50KHBwKVxuICAgICAgICAgIHJlY291bnQocClcbiAgICAgICAgICByZWNvdW50KG4pXG4gICAgICAgICAgaWYocyA+PSAzKSB7XG4gICAgICAgICAgICB2YXIgcHBwID0gbl9zdGFja1tzLTNdXG4gICAgICAgICAgICBpZihwcHAubGVmdCA9PT0gcHApIHtcbiAgICAgICAgICAgICAgcHBwLmxlZnQgPSBuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwcHAucmlnaHQgPSBuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYocC5yaWdodCA9PT0gbikge1xuICAgICAgICB2YXIgeSA9IHBwLmxlZnRcbiAgICAgICAgaWYoeSAmJiB5Ll9jb2xvciA9PT0gUkVEKSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcIlJSclwiLCB5LmtleSlcbiAgICAgICAgICBwLl9jb2xvciA9IEJMQUNLXG4gICAgICAgICAgcHAubGVmdCA9IHJlcGFpbnQoQkxBQ0ssIHkpXG4gICAgICAgICAgcHAuX2NvbG9yID0gUkVEXG4gICAgICAgICAgcyAtPSAxXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcIlJSYlwiKVxuICAgICAgICAgIHBwLl9jb2xvciA9IFJFRFxuICAgICAgICAgIHBwLnJpZ2h0ID0gcC5sZWZ0XG4gICAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICAgIHAubGVmdCA9IHBwXG4gICAgICAgICAgbl9zdGFja1tzLTJdID0gcFxuICAgICAgICAgIG5fc3RhY2tbcy0xXSA9IG5cbiAgICAgICAgICByZWNvdW50KHBwKVxuICAgICAgICAgIHJlY291bnQocClcbiAgICAgICAgICBpZihzID49IDMpIHtcbiAgICAgICAgICAgIHZhciBwcHAgPSBuX3N0YWNrW3MtM11cbiAgICAgICAgICAgIGlmKHBwcC5yaWdodCA9PT0gcHApIHtcbiAgICAgICAgICAgICAgcHBwLnJpZ2h0ID0gcFxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcHBwLmxlZnQgPSBwXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB5ID0gcHAubGVmdFxuICAgICAgICBpZih5ICYmIHkuX2NvbG9yID09PSBSRUQpIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiUkxyXCIpXG4gICAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICAgIHBwLmxlZnQgPSByZXBhaW50KEJMQUNLLCB5KVxuICAgICAgICAgIHBwLl9jb2xvciA9IFJFRFxuICAgICAgICAgIHMgLT0gMVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vY29uc29sZS5sb2coXCJSTGJcIilcbiAgICAgICAgICBwLmxlZnQgPSBuLnJpZ2h0XG4gICAgICAgICAgcHAuX2NvbG9yID0gUkVEXG4gICAgICAgICAgcHAucmlnaHQgPSBuLmxlZnRcbiAgICAgICAgICBuLl9jb2xvciA9IEJMQUNLXG4gICAgICAgICAgbi5yaWdodCA9IHBcbiAgICAgICAgICBuLmxlZnQgPSBwcFxuICAgICAgICAgIG5fc3RhY2tbcy0yXSA9IG5cbiAgICAgICAgICBuX3N0YWNrW3MtMV0gPSBwXG4gICAgICAgICAgcmVjb3VudChwcClcbiAgICAgICAgICByZWNvdW50KHApXG4gICAgICAgICAgcmVjb3VudChuKVxuICAgICAgICAgIGlmKHMgPj0gMykge1xuICAgICAgICAgICAgdmFyIHBwcCA9IG5fc3RhY2tbcy0zXVxuICAgICAgICAgICAgaWYocHBwLnJpZ2h0ID09PSBwcCkge1xuICAgICAgICAgICAgICBwcHAucmlnaHQgPSBuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwcHAubGVmdCA9IG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICAvL1JldHVybiBuZXcgdHJlZVxuICBuX3N0YWNrWzBdLl9jb2xvciA9IEJMQUNLXG4gIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlKGNtcCwgbl9zdGFja1swXSlcbn1cblxuXG4vL1Zpc2l0IGFsbCBub2RlcyBpbm9yZGVyXG5mdW5jdGlvbiBkb1Zpc2l0RnVsbCh2aXNpdCwgbm9kZSkge1xuICBpZihub2RlLmxlZnQpIHtcbiAgICB2YXIgdiA9IGRvVmlzaXRGdWxsKHZpc2l0LCBub2RlLmxlZnQpXG4gICAgaWYodikgeyByZXR1cm4gdiB9XG4gIH1cbiAgdmFyIHYgPSB2aXNpdChub2RlLmtleSwgbm9kZS52YWx1ZSlcbiAgaWYodikgeyByZXR1cm4gdiB9XG4gIGlmKG5vZGUucmlnaHQpIHtcbiAgICByZXR1cm4gZG9WaXNpdEZ1bGwodmlzaXQsIG5vZGUucmlnaHQpXG4gIH1cbn1cblxuLy9WaXNpdCBoYWxmIG5vZGVzIGluIG9yZGVyXG5mdW5jdGlvbiBkb1Zpc2l0SGFsZihsbywgY29tcGFyZSwgdmlzaXQsIG5vZGUpIHtcbiAgdmFyIGwgPSBjb21wYXJlKGxvLCBub2RlLmtleSlcbiAgaWYobCA8PSAwKSB7XG4gICAgaWYobm9kZS5sZWZ0KSB7XG4gICAgICB2YXIgdiA9IGRvVmlzaXRIYWxmKGxvLCBjb21wYXJlLCB2aXNpdCwgbm9kZS5sZWZ0KVxuICAgICAgaWYodikgeyByZXR1cm4gdiB9XG4gICAgfVxuICAgIHZhciB2ID0gdmlzaXQobm9kZS5rZXksIG5vZGUudmFsdWUpXG4gICAgaWYodikgeyByZXR1cm4gdiB9XG4gIH1cbiAgaWYobm9kZS5yaWdodCkge1xuICAgIHJldHVybiBkb1Zpc2l0SGFsZihsbywgY29tcGFyZSwgdmlzaXQsIG5vZGUucmlnaHQpXG4gIH1cbn1cblxuLy9WaXNpdCBhbGwgbm9kZXMgd2l0aGluIGEgcmFuZ2VcbmZ1bmN0aW9uIGRvVmlzaXQobG8sIGhpLCBjb21wYXJlLCB2aXNpdCwgbm9kZSkge1xuICB2YXIgbCA9IGNvbXBhcmUobG8sIG5vZGUua2V5KVxuICB2YXIgaCA9IGNvbXBhcmUoaGksIG5vZGUua2V5KVxuICB2YXIgdlxuICBpZihsIDw9IDApIHtcbiAgICBpZihub2RlLmxlZnQpIHtcbiAgICAgIHYgPSBkb1Zpc2l0KGxvLCBoaSwgY29tcGFyZSwgdmlzaXQsIG5vZGUubGVmdClcbiAgICAgIGlmKHYpIHsgcmV0dXJuIHYgfVxuICAgIH1cbiAgICBpZihoID4gMCkge1xuICAgICAgdiA9IHZpc2l0KG5vZGUua2V5LCBub2RlLnZhbHVlKVxuICAgICAgaWYodikgeyByZXR1cm4gdiB9XG4gICAgfVxuICB9XG4gIGlmKGggPiAwICYmIG5vZGUucmlnaHQpIHtcbiAgICByZXR1cm4gZG9WaXNpdChsbywgaGksIGNvbXBhcmUsIHZpc2l0LCBub2RlLnJpZ2h0KVxuICB9XG59XG5cblxucHJvdG8uZm9yRWFjaCA9IGZ1bmN0aW9uIHJiVHJlZUZvckVhY2godmlzaXQsIGxvLCBoaSkge1xuICBpZighdGhpcy5yb290KSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgc3dpdGNoKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gZG9WaXNpdEZ1bGwodmlzaXQsIHRoaXMucm9vdClcbiAgICBicmVha1xuXG4gICAgY2FzZSAyOlxuICAgICAgcmV0dXJuIGRvVmlzaXRIYWxmKGxvLCB0aGlzLl9jb21wYXJlLCB2aXNpdCwgdGhpcy5yb290KVxuICAgIGJyZWFrXG5cbiAgICBjYXNlIDM6XG4gICAgICBpZih0aGlzLl9jb21wYXJlKGxvLCBoaSkgPj0gMCkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIHJldHVybiBkb1Zpc2l0KGxvLCBoaSwgdGhpcy5fY29tcGFyZSwgdmlzaXQsIHRoaXMucm9vdClcbiAgICBicmVha1xuICB9XG59XG5cbi8vRmlyc3QgaXRlbSBpbiBsaXN0XG5PYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sIFwiYmVnaW5cIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBzdGFjayA9IFtdXG4gICAgdmFyIG4gPSB0aGlzLnJvb3RcbiAgICB3aGlsZShuKSB7XG4gICAgICBzdGFjay5wdXNoKG4pXG4gICAgICBuID0gbi5sZWZ0XG4gICAgfVxuICAgIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlSXRlcmF0b3IodGhpcywgc3RhY2spXG4gIH1cbn0pXG5cbi8vTGFzdCBpdGVtIGluIGxpc3Rcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90bywgXCJlbmRcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBzdGFjayA9IFtdXG4gICAgdmFyIG4gPSB0aGlzLnJvb3RcbiAgICB3aGlsZShuKSB7XG4gICAgICBzdGFjay5wdXNoKG4pXG4gICAgICBuID0gbi5yaWdodFxuICAgIH1cbiAgICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZUl0ZXJhdG9yKHRoaXMsIHN0YWNrKVxuICB9XG59KVxuXG4vL0ZpbmQgdGhlIGl0aCBpdGVtIGluIHRoZSB0cmVlXG5wcm90by5hdCA9IGZ1bmN0aW9uKGlkeCkge1xuICBpZihpZHggPCAwKSB7XG4gICAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWVJdGVyYXRvcih0aGlzLCBbXSlcbiAgfVxuICB2YXIgbiA9IHRoaXMucm9vdFxuICB2YXIgc3RhY2sgPSBbXVxuICB3aGlsZSh0cnVlKSB7XG4gICAgc3RhY2sucHVzaChuKVxuICAgIGlmKG4ubGVmdCkge1xuICAgICAgaWYoaWR4IDwgbi5sZWZ0Ll9jb3VudCkge1xuICAgICAgICBuID0gbi5sZWZ0XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBpZHggLT0gbi5sZWZ0Ll9jb3VudFxuICAgIH1cbiAgICBpZighaWR4KSB7XG4gICAgICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZUl0ZXJhdG9yKHRoaXMsIHN0YWNrKVxuICAgIH1cbiAgICBpZHggLT0gMVxuICAgIGlmKG4ucmlnaHQpIHtcbiAgICAgIGlmKGlkeCA+PSBuLnJpZ2h0Ll9jb3VudCkge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgICAgbiA9IG4ucmlnaHRcbiAgICB9IGVsc2Uge1xuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWVJdGVyYXRvcih0aGlzLCBbXSlcbn1cblxucHJvdG8uZ2UgPSBmdW5jdGlvbihrZXkpIHtcbiAgdmFyIGNtcCA9IHRoaXMuX2NvbXBhcmVcbiAgdmFyIG4gPSB0aGlzLnJvb3RcbiAgdmFyIHN0YWNrID0gW11cbiAgdmFyIGxhc3RfcHRyID0gMFxuICB3aGlsZShuKSB7XG4gICAgdmFyIGQgPSBjbXAoa2V5LCBuLmtleSlcbiAgICBzdGFjay5wdXNoKG4pXG4gICAgaWYoZCA8PSAwKSB7XG4gICAgICBsYXN0X3B0ciA9IHN0YWNrLmxlbmd0aFxuICAgIH1cbiAgICBpZihkIDw9IDApIHtcbiAgICAgIG4gPSBuLmxlZnRcbiAgICB9IGVsc2Uge1xuICAgICAgbiA9IG4ucmlnaHRcbiAgICB9XG4gIH1cbiAgc3RhY2subGVuZ3RoID0gbGFzdF9wdHJcbiAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWVJdGVyYXRvcih0aGlzLCBzdGFjaylcbn1cblxucHJvdG8uZ3QgPSBmdW5jdGlvbihrZXkpIHtcbiAgdmFyIGNtcCA9IHRoaXMuX2NvbXBhcmVcbiAgdmFyIG4gPSB0aGlzLnJvb3RcbiAgdmFyIHN0YWNrID0gW11cbiAgdmFyIGxhc3RfcHRyID0gMFxuICB3aGlsZShuKSB7XG4gICAgdmFyIGQgPSBjbXAoa2V5LCBuLmtleSlcbiAgICBzdGFjay5wdXNoKG4pXG4gICAgaWYoZCA8IDApIHtcbiAgICAgIGxhc3RfcHRyID0gc3RhY2subGVuZ3RoXG4gICAgfVxuICAgIGlmKGQgPCAwKSB7XG4gICAgICBuID0gbi5sZWZ0XG4gICAgfSBlbHNlIHtcbiAgICAgIG4gPSBuLnJpZ2h0XG4gICAgfVxuICB9XG4gIHN0YWNrLmxlbmd0aCA9IGxhc3RfcHRyXG4gIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlSXRlcmF0b3IodGhpcywgc3RhY2spXG59XG5cbnByb3RvLmx0ID0gZnVuY3Rpb24oa2V5KSB7XG4gIHZhciBjbXAgPSB0aGlzLl9jb21wYXJlXG4gIHZhciBuID0gdGhpcy5yb290XG4gIHZhciBzdGFjayA9IFtdXG4gIHZhciBsYXN0X3B0ciA9IDBcbiAgd2hpbGUobikge1xuICAgIHZhciBkID0gY21wKGtleSwgbi5rZXkpXG4gICAgc3RhY2sucHVzaChuKVxuICAgIGlmKGQgPiAwKSB7XG4gICAgICBsYXN0X3B0ciA9IHN0YWNrLmxlbmd0aFxuICAgIH1cbiAgICBpZihkIDw9IDApIHtcbiAgICAgIG4gPSBuLmxlZnRcbiAgICB9IGVsc2Uge1xuICAgICAgbiA9IG4ucmlnaHRcbiAgICB9XG4gIH1cbiAgc3RhY2subGVuZ3RoID0gbGFzdF9wdHJcbiAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWVJdGVyYXRvcih0aGlzLCBzdGFjaylcbn1cblxucHJvdG8ubGUgPSBmdW5jdGlvbihrZXkpIHtcbiAgdmFyIGNtcCA9IHRoaXMuX2NvbXBhcmVcbiAgdmFyIG4gPSB0aGlzLnJvb3RcbiAgdmFyIHN0YWNrID0gW11cbiAgdmFyIGxhc3RfcHRyID0gMFxuICB3aGlsZShuKSB7XG4gICAgdmFyIGQgPSBjbXAoa2V5LCBuLmtleSlcbiAgICBzdGFjay5wdXNoKG4pXG4gICAgaWYoZCA+PSAwKSB7XG4gICAgICBsYXN0X3B0ciA9IHN0YWNrLmxlbmd0aFxuICAgIH1cbiAgICBpZihkIDwgMCkge1xuICAgICAgbiA9IG4ubGVmdFxuICAgIH0gZWxzZSB7XG4gICAgICBuID0gbi5yaWdodFxuICAgIH1cbiAgfVxuICBzdGFjay5sZW5ndGggPSBsYXN0X3B0clxuICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZUl0ZXJhdG9yKHRoaXMsIHN0YWNrKVxufVxuXG4vL0ZpbmRzIHRoZSBpdGVtIHdpdGgga2V5IGlmIGl0IGV4aXN0c1xucHJvdG8uZmluZCA9IGZ1bmN0aW9uKGtleSkge1xuICB2YXIgY21wID0gdGhpcy5fY29tcGFyZVxuICB2YXIgbiA9IHRoaXMucm9vdFxuICB2YXIgc3RhY2sgPSBbXVxuICB3aGlsZShuKSB7XG4gICAgdmFyIGQgPSBjbXAoa2V5LCBuLmtleSlcbiAgICBzdGFjay5wdXNoKG4pXG4gICAgaWYoZCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWVJdGVyYXRvcih0aGlzLCBzdGFjaylcbiAgICB9XG4gICAgaWYoZCA8PSAwKSB7XG4gICAgICBuID0gbi5sZWZ0XG4gICAgfSBlbHNlIHtcbiAgICAgIG4gPSBuLnJpZ2h0XG4gICAgfVxuICB9XG4gIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlSXRlcmF0b3IodGhpcywgW10pXG59XG5cbi8vUmVtb3ZlcyBpdGVtIHdpdGgga2V5IGZyb20gdHJlZVxucHJvdG8ucmVtb3ZlID0gZnVuY3Rpb24oa2V5KSB7XG4gIHZhciBpdGVyID0gdGhpcy5maW5kKGtleSlcbiAgaWYoaXRlcikge1xuICAgIHJldHVybiBpdGVyLnJlbW92ZSgpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuLy9SZXR1cm5zIHRoZSBpdGVtIGF0IGBrZXlgXG5wcm90by5nZXQgPSBmdW5jdGlvbihrZXkpIHtcbiAgdmFyIGNtcCA9IHRoaXMuX2NvbXBhcmVcbiAgdmFyIG4gPSB0aGlzLnJvb3RcbiAgd2hpbGUobikge1xuICAgIHZhciBkID0gY21wKGtleSwgbi5rZXkpXG4gICAgaWYoZCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG4udmFsdWVcbiAgICB9XG4gICAgaWYoZCA8PSAwKSB7XG4gICAgICBuID0gbi5sZWZ0XG4gICAgfSBlbHNlIHtcbiAgICAgIG4gPSBuLnJpZ2h0XG4gICAgfVxuICB9XG4gIHJldHVyblxufVxuXG4vL0l0ZXJhdG9yIGZvciByZWQgYmxhY2sgdHJlZVxuZnVuY3Rpb24gUmVkQmxhY2tUcmVlSXRlcmF0b3IodHJlZSwgc3RhY2spIHtcbiAgdGhpcy50cmVlID0gdHJlZVxuICB0aGlzLl9zdGFjayA9IHN0YWNrXG59XG5cbnZhciBpcHJvdG8gPSBSZWRCbGFja1RyZWVJdGVyYXRvci5wcm90b3R5cGVcblxuLy9UZXN0IGlmIGl0ZXJhdG9yIGlzIHZhbGlkXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoaXByb3RvLCBcInZhbGlkXCIsIHtcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhY2subGVuZ3RoID4gMFxuICB9XG59KVxuXG4vL05vZGUgb2YgdGhlIGl0ZXJhdG9yXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoaXByb3RvLCBcIm5vZGVcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmKHRoaXMuX3N0YWNrLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiB0aGlzLl9zdGFja1t0aGlzLl9zdGFjay5sZW5ndGgtMV1cbiAgICB9XG4gICAgcmV0dXJuIG51bGxcbiAgfSxcbiAgZW51bWVyYWJsZTogdHJ1ZVxufSlcblxuLy9NYWtlcyBhIGNvcHkgb2YgYW4gaXRlcmF0b3Jcbmlwcm90by5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZUl0ZXJhdG9yKHRoaXMudHJlZSwgdGhpcy5fc3RhY2suc2xpY2UoKSlcbn1cblxuLy9Td2FwcyB0d28gbm9kZXNcbmZ1bmN0aW9uIHN3YXBOb2RlKG4sIHYpIHtcbiAgbi5rZXkgPSB2LmtleVxuICBuLnZhbHVlID0gdi52YWx1ZVxuICBuLmxlZnQgPSB2LmxlZnRcbiAgbi5yaWdodCA9IHYucmlnaHRcbiAgbi5fY29sb3IgPSB2Ll9jb2xvclxuICBuLl9jb3VudCA9IHYuX2NvdW50XG59XG5cbi8vRml4IHVwIGEgZG91YmxlIGJsYWNrIG5vZGUgaW4gYSB0cmVlXG5mdW5jdGlvbiBmaXhEb3VibGVCbGFjayhzdGFjaykge1xuICB2YXIgbiwgcCwgcywgelxuICBmb3IodmFyIGk9c3RhY2subGVuZ3RoLTE7IGk+PTA7IC0taSkge1xuICAgIG4gPSBzdGFja1tpXVxuICAgIGlmKGkgPT09IDApIHtcbiAgICAgIG4uX2NvbG9yID0gQkxBQ0tcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICAvL2NvbnNvbGUubG9nKFwidmlzaXQgbm9kZTpcIiwgbi5rZXksIGksIHN0YWNrW2ldLmtleSwgc3RhY2tbaS0xXS5rZXkpXG4gICAgcCA9IHN0YWNrW2ktMV1cbiAgICBpZihwLmxlZnQgPT09IG4pIHtcbiAgICAgIC8vY29uc29sZS5sb2coXCJsZWZ0IGNoaWxkXCIpXG4gICAgICBzID0gcC5yaWdodFxuICAgICAgaWYocy5yaWdodCAmJiBzLnJpZ2h0Ll9jb2xvciA9PT0gUkVEKSB7XG4gICAgICAgIC8vY29uc29sZS5sb2coXCJjYXNlIDE6IHJpZ2h0IHNpYmxpbmcgY2hpbGQgcmVkXCIpXG4gICAgICAgIHMgPSBwLnJpZ2h0ID0gY2xvbmVOb2RlKHMpXG4gICAgICAgIHogPSBzLnJpZ2h0ID0gY2xvbmVOb2RlKHMucmlnaHQpXG4gICAgICAgIHAucmlnaHQgPSBzLmxlZnRcbiAgICAgICAgcy5sZWZ0ID0gcFxuICAgICAgICBzLnJpZ2h0ID0gelxuICAgICAgICBzLl9jb2xvciA9IHAuX2NvbG9yXG4gICAgICAgIG4uX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgcC5fY29sb3IgPSBCTEFDS1xuICAgICAgICB6Ll9jb2xvciA9IEJMQUNLXG4gICAgICAgIHJlY291bnQocClcbiAgICAgICAgcmVjb3VudChzKVxuICAgICAgICBpZihpID4gMSkge1xuICAgICAgICAgIHZhciBwcCA9IHN0YWNrW2ktMl1cbiAgICAgICAgICBpZihwcC5sZWZ0ID09PSBwKSB7XG4gICAgICAgICAgICBwcC5sZWZ0ID0gc1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcC5yaWdodCA9IHNcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhY2tbaS0xXSA9IHNcbiAgICAgICAgcmV0dXJuXG4gICAgICB9IGVsc2UgaWYocy5sZWZ0ICYmIHMubGVmdC5fY29sb3IgPT09IFJFRCkge1xuICAgICAgICAvL2NvbnNvbGUubG9nKFwiY2FzZSAxOiBsZWZ0IHNpYmxpbmcgY2hpbGQgcmVkXCIpXG4gICAgICAgIHMgPSBwLnJpZ2h0ID0gY2xvbmVOb2RlKHMpXG4gICAgICAgIHogPSBzLmxlZnQgPSBjbG9uZU5vZGUocy5sZWZ0KVxuICAgICAgICBwLnJpZ2h0ID0gei5sZWZ0XG4gICAgICAgIHMubGVmdCA9IHoucmlnaHRcbiAgICAgICAgei5sZWZ0ID0gcFxuICAgICAgICB6LnJpZ2h0ID0gc1xuICAgICAgICB6Ll9jb2xvciA9IHAuX2NvbG9yXG4gICAgICAgIHAuX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgcy5fY29sb3IgPSBCTEFDS1xuICAgICAgICBuLl9jb2xvciA9IEJMQUNLXG4gICAgICAgIHJlY291bnQocClcbiAgICAgICAgcmVjb3VudChzKVxuICAgICAgICByZWNvdW50KHopXG4gICAgICAgIGlmKGkgPiAxKSB7XG4gICAgICAgICAgdmFyIHBwID0gc3RhY2tbaS0yXVxuICAgICAgICAgIGlmKHBwLmxlZnQgPT09IHApIHtcbiAgICAgICAgICAgIHBwLmxlZnQgPSB6XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBwLnJpZ2h0ID0gelxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGFja1tpLTFdID0gelxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIGlmKHMuX2NvbG9yID09PSBCTEFDSykge1xuICAgICAgICBpZihwLl9jb2xvciA9PT0gUkVEKSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcImNhc2UgMjogYmxhY2sgc2libGluZywgcmVkIHBhcmVudFwiLCBwLnJpZ2h0LnZhbHVlKVxuICAgICAgICAgIHAuX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgICBwLnJpZ2h0ID0gcmVwYWludChSRUQsIHMpXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcImNhc2UgMjogYmxhY2sgc2libGluZywgYmxhY2sgcGFyZW50XCIsIHAucmlnaHQudmFsdWUpXG4gICAgICAgICAgcC5yaWdodCA9IHJlcGFpbnQoUkVELCBzKVxuICAgICAgICAgIGNvbnRpbnVlICBcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy9jb25zb2xlLmxvZyhcImNhc2UgMzogcmVkIHNpYmxpbmdcIilcbiAgICAgICAgcyA9IGNsb25lTm9kZShzKVxuICAgICAgICBwLnJpZ2h0ID0gcy5sZWZ0XG4gICAgICAgIHMubGVmdCA9IHBcbiAgICAgICAgcy5fY29sb3IgPSBwLl9jb2xvclxuICAgICAgICBwLl9jb2xvciA9IFJFRFxuICAgICAgICByZWNvdW50KHApXG4gICAgICAgIHJlY291bnQocylcbiAgICAgICAgaWYoaSA+IDEpIHtcbiAgICAgICAgICB2YXIgcHAgPSBzdGFja1tpLTJdXG4gICAgICAgICAgaWYocHAubGVmdCA9PT0gcCkge1xuICAgICAgICAgICAgcHAubGVmdCA9IHNcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHAucmlnaHQgPSBzXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN0YWNrW2ktMV0gPSBzXG4gICAgICAgIHN0YWNrW2ldID0gcFxuICAgICAgICBpZihpKzEgPCBzdGFjay5sZW5ndGgpIHtcbiAgICAgICAgICBzdGFja1tpKzFdID0gblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0YWNrLnB1c2gobilcbiAgICAgICAgfVxuICAgICAgICBpID0gaSsyXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vY29uc29sZS5sb2coXCJyaWdodCBjaGlsZFwiKVxuICAgICAgcyA9IHAubGVmdFxuICAgICAgaWYocy5sZWZ0ICYmIHMubGVmdC5fY29sb3IgPT09IFJFRCkge1xuICAgICAgICAvL2NvbnNvbGUubG9nKFwiY2FzZSAxOiBsZWZ0IHNpYmxpbmcgY2hpbGQgcmVkXCIsIHAudmFsdWUsIHAuX2NvbG9yKVxuICAgICAgICBzID0gcC5sZWZ0ID0gY2xvbmVOb2RlKHMpXG4gICAgICAgIHogPSBzLmxlZnQgPSBjbG9uZU5vZGUocy5sZWZ0KVxuICAgICAgICBwLmxlZnQgPSBzLnJpZ2h0XG4gICAgICAgIHMucmlnaHQgPSBwXG4gICAgICAgIHMubGVmdCA9IHpcbiAgICAgICAgcy5fY29sb3IgPSBwLl9jb2xvclxuICAgICAgICBuLl9jb2xvciA9IEJMQUNLXG4gICAgICAgIHAuX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgei5fY29sb3IgPSBCTEFDS1xuICAgICAgICByZWNvdW50KHApXG4gICAgICAgIHJlY291bnQocylcbiAgICAgICAgaWYoaSA+IDEpIHtcbiAgICAgICAgICB2YXIgcHAgPSBzdGFja1tpLTJdXG4gICAgICAgICAgaWYocHAucmlnaHQgPT09IHApIHtcbiAgICAgICAgICAgIHBwLnJpZ2h0ID0gc1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcC5sZWZ0ID0gc1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGFja1tpLTFdID0gc1xuICAgICAgICByZXR1cm5cbiAgICAgIH0gZWxzZSBpZihzLnJpZ2h0ICYmIHMucmlnaHQuX2NvbG9yID09PSBSRUQpIHtcbiAgICAgICAgLy9jb25zb2xlLmxvZyhcImNhc2UgMTogcmlnaHQgc2libGluZyBjaGlsZCByZWRcIilcbiAgICAgICAgcyA9IHAubGVmdCA9IGNsb25lTm9kZShzKVxuICAgICAgICB6ID0gcy5yaWdodCA9IGNsb25lTm9kZShzLnJpZ2h0KVxuICAgICAgICBwLmxlZnQgPSB6LnJpZ2h0XG4gICAgICAgIHMucmlnaHQgPSB6LmxlZnRcbiAgICAgICAgei5yaWdodCA9IHBcbiAgICAgICAgei5sZWZ0ID0gc1xuICAgICAgICB6Ll9jb2xvciA9IHAuX2NvbG9yXG4gICAgICAgIHAuX2NvbG9yID0gQkxBQ0tcbiAgICAgICAgcy5fY29sb3IgPSBCTEFDS1xuICAgICAgICBuLl9jb2xvciA9IEJMQUNLXG4gICAgICAgIHJlY291bnQocClcbiAgICAgICAgcmVjb3VudChzKVxuICAgICAgICByZWNvdW50KHopXG4gICAgICAgIGlmKGkgPiAxKSB7XG4gICAgICAgICAgdmFyIHBwID0gc3RhY2tbaS0yXVxuICAgICAgICAgIGlmKHBwLnJpZ2h0ID09PSBwKSB7XG4gICAgICAgICAgICBwcC5yaWdodCA9IHpcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHAubGVmdCA9IHpcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhY2tbaS0xXSA9IHpcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBpZihzLl9jb2xvciA9PT0gQkxBQ0spIHtcbiAgICAgICAgaWYocC5fY29sb3IgPT09IFJFRCkge1xuICAgICAgICAgIC8vY29uc29sZS5sb2coXCJjYXNlIDI6IGJsYWNrIHNpYmxpbmcsIHJlZCBwYXJlbnRcIilcbiAgICAgICAgICBwLl9jb2xvciA9IEJMQUNLXG4gICAgICAgICAgcC5sZWZ0ID0gcmVwYWludChSRUQsIHMpXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9jb25zb2xlLmxvZyhcImNhc2UgMjogYmxhY2sgc2libGluZywgYmxhY2sgcGFyZW50XCIpXG4gICAgICAgICAgcC5sZWZ0ID0gcmVwYWludChSRUQsIHMpXG4gICAgICAgICAgY29udGludWUgIFxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvL2NvbnNvbGUubG9nKFwiY2FzZSAzOiByZWQgc2libGluZ1wiKVxuICAgICAgICBzID0gY2xvbmVOb2RlKHMpXG4gICAgICAgIHAubGVmdCA9IHMucmlnaHRcbiAgICAgICAgcy5yaWdodCA9IHBcbiAgICAgICAgcy5fY29sb3IgPSBwLl9jb2xvclxuICAgICAgICBwLl9jb2xvciA9IFJFRFxuICAgICAgICByZWNvdW50KHApXG4gICAgICAgIHJlY291bnQocylcbiAgICAgICAgaWYoaSA+IDEpIHtcbiAgICAgICAgICB2YXIgcHAgPSBzdGFja1tpLTJdXG4gICAgICAgICAgaWYocHAucmlnaHQgPT09IHApIHtcbiAgICAgICAgICAgIHBwLnJpZ2h0ID0gc1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcC5sZWZ0ID0gc1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGFja1tpLTFdID0gc1xuICAgICAgICBzdGFja1tpXSA9IHBcbiAgICAgICAgaWYoaSsxIDwgc3RhY2subGVuZ3RoKSB7XG4gICAgICAgICAgc3RhY2tbaSsxXSA9IG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdGFjay5wdXNoKG4pXG4gICAgICAgIH1cbiAgICAgICAgaSA9IGkrMlxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vL1JlbW92ZXMgaXRlbSBhdCBpdGVyYXRvciBmcm9tIHRyZWVcbmlwcm90by5yZW1vdmUgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHN0YWNrID0gdGhpcy5fc3RhY2tcbiAgaWYoc3RhY2subGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHRoaXMudHJlZVxuICB9XG4gIC8vRmlyc3QgY29weSBwYXRoIHRvIG5vZGVcbiAgdmFyIGNzdGFjayA9IG5ldyBBcnJheShzdGFjay5sZW5ndGgpXG4gIHZhciBuID0gc3RhY2tbc3RhY2subGVuZ3RoLTFdXG4gIGNzdGFja1tjc3RhY2subGVuZ3RoLTFdID0gbmV3IFJCTm9kZShuLl9jb2xvciwgbi5rZXksIG4udmFsdWUsIG4ubGVmdCwgbi5yaWdodCwgbi5fY291bnQpXG4gIGZvcih2YXIgaT1zdGFjay5sZW5ndGgtMjsgaT49MDsgLS1pKSB7XG4gICAgdmFyIG4gPSBzdGFja1tpXVxuICAgIGlmKG4ubGVmdCA9PT0gc3RhY2tbaSsxXSkge1xuICAgICAgY3N0YWNrW2ldID0gbmV3IFJCTm9kZShuLl9jb2xvciwgbi5rZXksIG4udmFsdWUsIGNzdGFja1tpKzFdLCBuLnJpZ2h0LCBuLl9jb3VudClcbiAgICB9IGVsc2Uge1xuICAgICAgY3N0YWNrW2ldID0gbmV3IFJCTm9kZShuLl9jb2xvciwgbi5rZXksIG4udmFsdWUsIG4ubGVmdCwgY3N0YWNrW2krMV0sIG4uX2NvdW50KVxuICAgIH1cbiAgfVxuXG4gIC8vR2V0IG5vZGVcbiAgbiA9IGNzdGFja1tjc3RhY2subGVuZ3RoLTFdXG4gIC8vY29uc29sZS5sb2coXCJzdGFydCByZW1vdmU6IFwiLCBuLnZhbHVlKVxuXG4gIC8vSWYgbm90IGxlYWYsIHRoZW4gc3dhcCB3aXRoIHByZXZpb3VzIG5vZGVcbiAgaWYobi5sZWZ0ICYmIG4ucmlnaHQpIHtcbiAgICAvL2NvbnNvbGUubG9nKFwibW92aW5nIHRvIGxlYWZcIilcblxuICAgIC8vRmlyc3Qgd2FsayB0byBwcmV2aW91cyBsZWFmXG4gICAgdmFyIHNwbGl0ID0gY3N0YWNrLmxlbmd0aFxuICAgIG4gPSBuLmxlZnRcbiAgICB3aGlsZShuLnJpZ2h0KSB7XG4gICAgICBjc3RhY2sucHVzaChuKVxuICAgICAgbiA9IG4ucmlnaHRcbiAgICB9XG4gICAgLy9Db3B5IHBhdGggdG8gbGVhZlxuICAgIHZhciB2ID0gY3N0YWNrW3NwbGl0LTFdXG4gICAgY3N0YWNrLnB1c2gobmV3IFJCTm9kZShuLl9jb2xvciwgdi5rZXksIHYudmFsdWUsIG4ubGVmdCwgbi5yaWdodCwgbi5fY291bnQpKVxuICAgIGNzdGFja1tzcGxpdC0xXS5rZXkgPSBuLmtleVxuICAgIGNzdGFja1tzcGxpdC0xXS52YWx1ZSA9IG4udmFsdWVcblxuICAgIC8vRml4IHVwIHN0YWNrXG4gICAgZm9yKHZhciBpPWNzdGFjay5sZW5ndGgtMjsgaT49c3BsaXQ7IC0taSkge1xuICAgICAgbiA9IGNzdGFja1tpXVxuICAgICAgY3N0YWNrW2ldID0gbmV3IFJCTm9kZShuLl9jb2xvciwgbi5rZXksIG4udmFsdWUsIG4ubGVmdCwgY3N0YWNrW2krMV0sIG4uX2NvdW50KVxuICAgIH1cbiAgICBjc3RhY2tbc3BsaXQtMV0ubGVmdCA9IGNzdGFja1tzcGxpdF1cbiAgfVxuICAvL2NvbnNvbGUubG9nKFwic3RhY2s9XCIsIGNzdGFjay5tYXAoZnVuY3Rpb24odikgeyByZXR1cm4gdi52YWx1ZSB9KSlcblxuICAvL1JlbW92ZSBsZWFmIG5vZGVcbiAgbiA9IGNzdGFja1tjc3RhY2subGVuZ3RoLTFdXG4gIGlmKG4uX2NvbG9yID09PSBSRUQpIHtcbiAgICAvL0Vhc3kgY2FzZTogcmVtb3ZpbmcgcmVkIGxlYWZcbiAgICAvL2NvbnNvbGUubG9nKFwiUkVEIGxlYWZcIilcbiAgICB2YXIgcCA9IGNzdGFja1tjc3RhY2subGVuZ3RoLTJdXG4gICAgaWYocC5sZWZ0ID09PSBuKSB7XG4gICAgICBwLmxlZnQgPSBudWxsXG4gICAgfSBlbHNlIGlmKHAucmlnaHQgPT09IG4pIHtcbiAgICAgIHAucmlnaHQgPSBudWxsXG4gICAgfVxuICAgIGNzdGFjay5wb3AoKVxuICAgIGZvcih2YXIgaT0wOyBpPGNzdGFjay5sZW5ndGg7ICsraSkge1xuICAgICAgY3N0YWNrW2ldLl9jb3VudC0tXG4gICAgfVxuICAgIHJldHVybiBuZXcgUmVkQmxhY2tUcmVlKHRoaXMudHJlZS5fY29tcGFyZSwgY3N0YWNrWzBdKVxuICB9IGVsc2Uge1xuICAgIGlmKG4ubGVmdCB8fCBuLnJpZ2h0KSB7XG4gICAgICAvL1NlY29uZCBlYXN5IGNhc2U6ICBTaW5nbGUgY2hpbGQgYmxhY2sgcGFyZW50XG4gICAgICAvL2NvbnNvbGUubG9nKFwiQkxBQ0sgc2luZ2xlIGNoaWxkXCIpXG4gICAgICBpZihuLmxlZnQpIHtcbiAgICAgICAgc3dhcE5vZGUobiwgbi5sZWZ0KVxuICAgICAgfSBlbHNlIGlmKG4ucmlnaHQpIHtcbiAgICAgICAgc3dhcE5vZGUobiwgbi5yaWdodClcbiAgICAgIH1cbiAgICAgIC8vQ2hpbGQgbXVzdCBiZSByZWQsIHNvIHJlcGFpbnQgaXQgYmxhY2sgdG8gYmFsYW5jZSBjb2xvclxuICAgICAgbi5fY29sb3IgPSBCTEFDS1xuICAgICAgZm9yKHZhciBpPTA7IGk8Y3N0YWNrLmxlbmd0aC0xOyArK2kpIHtcbiAgICAgICAgY3N0YWNrW2ldLl9jb3VudC0tXG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZSh0aGlzLnRyZWUuX2NvbXBhcmUsIGNzdGFja1swXSlcbiAgICB9IGVsc2UgaWYoY3N0YWNrLmxlbmd0aCA9PT0gMSkge1xuICAgICAgLy9UaGlyZCBlYXN5IGNhc2U6IHJvb3RcbiAgICAgIC8vY29uc29sZS5sb2coXCJST09UXCIpXG4gICAgICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZSh0aGlzLnRyZWUuX2NvbXBhcmUsIG51bGwpXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vSGFyZCBjYXNlOiBSZXBhaW50IG4sIGFuZCB0aGVuIGRvIHNvbWUgbmFzdHkgc3R1ZmZcbiAgICAgIC8vY29uc29sZS5sb2coXCJCTEFDSyBsZWFmIG5vIGNoaWxkcmVuXCIpXG4gICAgICBmb3IodmFyIGk9MDsgaTxjc3RhY2subGVuZ3RoOyArK2kpIHtcbiAgICAgICAgY3N0YWNrW2ldLl9jb3VudC0tXG4gICAgICB9XG4gICAgICB2YXIgcGFyZW50ID0gY3N0YWNrW2NzdGFjay5sZW5ndGgtMl1cbiAgICAgIGZpeERvdWJsZUJsYWNrKGNzdGFjaylcbiAgICAgIC8vRml4IHVwIGxpbmtzXG4gICAgICBpZihwYXJlbnQubGVmdCA9PT0gbikge1xuICAgICAgICBwYXJlbnQubGVmdCA9IG51bGxcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhcmVudC5yaWdodCA9IG51bGxcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWUodGhpcy50cmVlLl9jb21wYXJlLCBjc3RhY2tbMF0pXG59XG5cbi8vUmV0dXJucyBrZXlcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShpcHJvdG8sIFwia2V5XCIsIHtcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICBpZih0aGlzLl9zdGFjay5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5fc3RhY2tbdGhpcy5fc3RhY2subGVuZ3RoLTFdLmtleVxuICAgIH1cbiAgICByZXR1cm5cbiAgfSxcbiAgZW51bWVyYWJsZTogdHJ1ZVxufSlcblxuLy9SZXR1cm5zIHZhbHVlXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoaXByb3RvLCBcInZhbHVlXCIsIHtcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICBpZih0aGlzLl9zdGFjay5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5fc3RhY2tbdGhpcy5fc3RhY2subGVuZ3RoLTFdLnZhbHVlXG4gICAgfVxuICAgIHJldHVyblxuICB9LFxuICBlbnVtZXJhYmxlOiB0cnVlXG59KVxuXG5cbi8vUmV0dXJucyB0aGUgcG9zaXRpb24gb2YgdGhpcyBpdGVyYXRvciBpbiB0aGUgc29ydGVkIGxpc3Rcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShpcHJvdG8sIFwiaW5kZXhcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpZHggPSAwXG4gICAgdmFyIHN0YWNrID0gdGhpcy5fc3RhY2tcbiAgICBpZihzdGFjay5sZW5ndGggPT09IDApIHtcbiAgICAgIHZhciByID0gdGhpcy50cmVlLnJvb3RcbiAgICAgIGlmKHIpIHtcbiAgICAgICAgcmV0dXJuIHIuX2NvdW50XG4gICAgICB9XG4gICAgICByZXR1cm4gMFxuICAgIH0gZWxzZSBpZihzdGFja1tzdGFjay5sZW5ndGgtMV0ubGVmdCkge1xuICAgICAgaWR4ID0gc3RhY2tbc3RhY2subGVuZ3RoLTFdLmxlZnQuX2NvdW50XG4gICAgfVxuICAgIGZvcih2YXIgcz1zdGFjay5sZW5ndGgtMjsgcz49MDsgLS1zKSB7XG4gICAgICBpZihzdGFja1tzKzFdID09PSBzdGFja1tzXS5yaWdodCkge1xuICAgICAgICArK2lkeFxuICAgICAgICBpZihzdGFja1tzXS5sZWZ0KSB7XG4gICAgICAgICAgaWR4ICs9IHN0YWNrW3NdLmxlZnQuX2NvdW50XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGlkeFxuICB9LFxuICBlbnVtZXJhYmxlOiB0cnVlXG59KVxuXG4vL0FkdmFuY2VzIGl0ZXJhdG9yIHRvIG5leHQgZWxlbWVudCBpbiBsaXN0XG5pcHJvdG8ubmV4dCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc3RhY2sgPSB0aGlzLl9zdGFja1xuICBpZihzdGFjay5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm5cbiAgfVxuICB2YXIgbiA9IHN0YWNrW3N0YWNrLmxlbmd0aC0xXVxuICBpZihuLnJpZ2h0KSB7XG4gICAgbiA9IG4ucmlnaHRcbiAgICB3aGlsZShuKSB7XG4gICAgICBzdGFjay5wdXNoKG4pXG4gICAgICBuID0gbi5sZWZ0XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHN0YWNrLnBvcCgpXG4gICAgd2hpbGUoc3RhY2subGVuZ3RoID4gMCAmJiBzdGFja1tzdGFjay5sZW5ndGgtMV0ucmlnaHQgPT09IG4pIHtcbiAgICAgIG4gPSBzdGFja1tzdGFjay5sZW5ndGgtMV1cbiAgICAgIHN0YWNrLnBvcCgpXG4gICAgfVxuICB9XG59XG5cbi8vQ2hlY2tzIGlmIGl0ZXJhdG9yIGlzIGF0IGVuZCBvZiB0cmVlXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoaXByb3RvLCBcImhhc05leHRcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBzdGFjayA9IHRoaXMuX3N0YWNrXG4gICAgaWYoc3RhY2subGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgaWYoc3RhY2tbc3RhY2subGVuZ3RoLTFdLnJpZ2h0KSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgICBmb3IodmFyIHM9c3RhY2subGVuZ3RoLTE7IHM+MDsgLS1zKSB7XG4gICAgICBpZihzdGFja1tzLTFdLmxlZnQgPT09IHN0YWNrW3NdKSB7XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZVxuICB9XG59KVxuXG4vL1VwZGF0ZSB2YWx1ZVxuaXByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHZhciBzdGFjayA9IHRoaXMuX3N0YWNrXG4gIGlmKHN0YWNrLmxlbmd0aCA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IHVwZGF0ZSBlbXB0eSBub2RlIVwiKVxuICB9XG4gIHZhciBjc3RhY2sgPSBuZXcgQXJyYXkoc3RhY2subGVuZ3RoKVxuICB2YXIgbiA9IHN0YWNrW3N0YWNrLmxlbmd0aC0xXVxuICBjc3RhY2tbY3N0YWNrLmxlbmd0aC0xXSA9IG5ldyBSQk5vZGUobi5fY29sb3IsIG4ua2V5LCB2YWx1ZSwgbi5sZWZ0LCBuLnJpZ2h0LCBuLl9jb3VudClcbiAgZm9yKHZhciBpPXN0YWNrLmxlbmd0aC0yOyBpPj0wOyAtLWkpIHtcbiAgICBuID0gc3RhY2tbaV1cbiAgICBpZihuLmxlZnQgPT09IHN0YWNrW2krMV0pIHtcbiAgICAgIGNzdGFja1tpXSA9IG5ldyBSQk5vZGUobi5fY29sb3IsIG4ua2V5LCBuLnZhbHVlLCBjc3RhY2tbaSsxXSwgbi5yaWdodCwgbi5fY291bnQpXG4gICAgfSBlbHNlIHtcbiAgICAgIGNzdGFja1tpXSA9IG5ldyBSQk5vZGUobi5fY29sb3IsIG4ua2V5LCBuLnZhbHVlLCBuLmxlZnQsIGNzdGFja1tpKzFdLCBuLl9jb3VudClcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5ldyBSZWRCbGFja1RyZWUodGhpcy50cmVlLl9jb21wYXJlLCBjc3RhY2tbMF0pXG59XG5cbi8vTW92ZXMgaXRlcmF0b3IgYmFja3dhcmQgb25lIGVsZW1lbnRcbmlwcm90by5wcmV2ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzdGFjayA9IHRoaXMuX3N0YWNrXG4gIGlmKHN0YWNrLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBuID0gc3RhY2tbc3RhY2subGVuZ3RoLTFdXG4gIGlmKG4ubGVmdCkge1xuICAgIG4gPSBuLmxlZnRcbiAgICB3aGlsZShuKSB7XG4gICAgICBzdGFjay5wdXNoKG4pXG4gICAgICBuID0gbi5yaWdodFxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBzdGFjay5wb3AoKVxuICAgIHdoaWxlKHN0YWNrLmxlbmd0aCA+IDAgJiYgc3RhY2tbc3RhY2subGVuZ3RoLTFdLmxlZnQgPT09IG4pIHtcbiAgICAgIG4gPSBzdGFja1tzdGFjay5sZW5ndGgtMV1cbiAgICAgIHN0YWNrLnBvcCgpXG4gICAgfVxuICB9XG59XG5cbi8vQ2hlY2tzIGlmIGl0ZXJhdG9yIGlzIGF0IHN0YXJ0IG9mIHRyZWVcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShpcHJvdG8sIFwiaGFzUHJldlwiLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHN0YWNrID0gdGhpcy5fc3RhY2tcbiAgICBpZihzdGFjay5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBpZihzdGFja1tzdGFjay5sZW5ndGgtMV0ubGVmdCkge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gICAgZm9yKHZhciBzPXN0YWNrLmxlbmd0aC0xOyBzPjA7IC0tcykge1xuICAgICAgaWYoc3RhY2tbcy0xXS5yaWdodCA9PT0gc3RhY2tbc10pIHtcbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbn0pXG5cbi8vRGVmYXVsdCBjb21wYXJpc29uIGZ1bmN0aW9uXG5mdW5jdGlvbiBkZWZhdWx0Q29tcGFyZShhLCBiKSB7XG4gIGlmKGEgPCBiKSB7XG4gICAgcmV0dXJuIC0xXG4gIH1cbiAgaWYoYSA+IGIpIHtcbiAgICByZXR1cm4gMVxuICB9XG4gIHJldHVybiAwXG59XG5cbi8vQnVpbGQgYSB0cmVlXG5mdW5jdGlvbiBjcmVhdGVSQlRyZWUoY29tcGFyZSkge1xuICByZXR1cm4gbmV3IFJlZEJsYWNrVHJlZShjb21wYXJlIHx8IGRlZmF1bHRDb21wYXJlLCBudWxsKVxufVxufSx7fV0sMjMxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vIHRyYW5zbGl0ZXJhdGVkIGZyb20gdGhlIHB5dGhvbiBzbmlwcGV0IGhlcmU6XG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xhbmN6b3NfYXBwcm94aW1hdGlvblxuXG52YXIgZyA9IDc7XG52YXIgcCA9IFtcbiAgICAwLjk5OTk5OTk5OTk5OTgwOTkzLFxuICAgIDY3Ni41MjAzNjgxMjE4ODUxLFxuICAgIC0xMjU5LjEzOTIxNjcyMjQwMjgsXG4gICAgNzcxLjMyMzQyODc3NzY1MzEzLFxuICAgIC0xNzYuNjE1MDI5MTYyMTQwNTksXG4gICAgMTIuNTA3MzQzMjc4Njg2OTA1LFxuICAgIC0wLjEzODU3MTA5NTI2NTcyMDEyLFxuICAgIDkuOTg0MzY5NTc4MDE5NTcxNmUtNixcbiAgICAxLjUwNTYzMjczNTE0OTMxMTZlLTdcbl07XG5cbnZhciBnX2xuID0gNjA3LzEyODtcbnZhciBwX2xuID0gW1xuICAgIDAuOTk5OTk5OTk5OTk5OTk3MDkxODIsXG4gICAgNTcuMTU2MjM1NjY1ODYyOTIzNTE3LFxuICAgIC01OS41OTc5NjAzNTU0NzU0OTEyNDgsXG4gICAgMTQuMTM2MDk3OTc0NzQxNzQ3MTc0LFxuICAgIC0wLjQ5MTkxMzgxNjA5NzYyMDE5OTc4LFxuICAgIDAuMzM5OTQ2NDk5ODQ4MTE4ODg2OTllLTQsXG4gICAgMC40NjUyMzYyODkyNzA0ODU3NTY2NWUtNCxcbiAgICAtMC45ODM3NDQ3NTMwNDg3OTU2NDY3N2UtNCxcbiAgICAwLjE1ODA4ODcwMzIyNDkxMjQ4ODg0ZS0zLFxuICAgIC0wLjIxMDI2NDQ0MTcyNDEwNDg4MzE5ZS0zLFxuICAgIDAuMjE3NDM5NjE4MTE1MjEyNjQzMjBlLTMsXG4gICAgLTAuMTY0MzE4MTA2NTM2NzYzODkwMjJlLTMsXG4gICAgMC44NDQxODIyMzk4Mzg1Mjc0MzI5M2UtNCxcbiAgICAtMC4yNjE5MDgzODQwMTU4MTQwODY3MGUtNCxcbiAgICAwLjM2ODk5MTgyNjU5NTMxNjIyNzA0ZS01XG5dO1xuXG4vLyBTcG91Z2UgYXBwcm94aW1hdGlvbiAoc3VpdGFibGUgZm9yIGxhcmdlIGFyZ3VtZW50cylcbmZ1bmN0aW9uIGxuZ2FtbWEoeikge1xuXG4gICAgaWYoeiA8IDApIHJldHVybiBOdW1iZXIoJzAvMCcpO1xuICAgIHZhciB4ID0gcF9sblswXTtcbiAgICBmb3IodmFyIGkgPSBwX2xuLmxlbmd0aCAtIDE7IGkgPiAwOyAtLWkpIHggKz0gcF9sbltpXSAvICh6ICsgaSk7XG4gICAgdmFyIHQgPSB6ICsgZ19sbiArIDAuNTtcbiAgICByZXR1cm4gLjUqTWF0aC5sb2coMipNYXRoLlBJKSsoeisuNSkqTWF0aC5sb2codCktdCtNYXRoLmxvZyh4KS1NYXRoLmxvZyh6KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBnYW1tYSAoeikge1xuICAgIGlmICh6IDwgMC41KSB7XG4gICAgICAgIHJldHVybiBNYXRoLlBJIC8gKE1hdGguc2luKE1hdGguUEkgKiB6KSAqIGdhbW1hKDEgLSB6KSk7XG4gICAgfVxuICAgIGVsc2UgaWYoeiA+IDEwMCkgcmV0dXJuIE1hdGguZXhwKGxuZ2FtbWEoeikpO1xuICAgIGVsc2Uge1xuICAgICAgICB6IC09IDE7XG4gICAgICAgIHZhciB4ID0gcFswXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBnICsgMjsgaSsrKSB7XG4gICAgICAgICAgICB4ICs9IHBbaV0gLyAoeiArIGkpO1xuICAgICAgICB9XG4gICAgICAgIHZhciB0ID0geiArIGcgKyAwLjU7XG5cbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCgyICogTWF0aC5QSSlcbiAgICAgICAgICAgICogTWF0aC5wb3codCwgeiArIDAuNSlcbiAgICAgICAgICAgICogTWF0aC5leHAoLXQpXG4gICAgICAgICAgICAqIHhcbiAgICAgICAgO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzLmxvZyA9IGxuZ2FtbWE7XG5cbn0se31dLDIzMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGdldENhbnZhc0NvbnRleHRcbmZ1bmN0aW9uIGdldENhbnZhc0NvbnRleHQgKHR5cGUsIG9wdHMpIHtcbiAgaWYgKHR5cGVvZiB0eXBlICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ211c3Qgc3BlY2lmeSB0eXBlIHN0cmluZycpXG4gIH1cblxuICBvcHRzID0gb3B0cyB8fCB7fVxuXG4gIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnICYmICFvcHRzLmNhbnZhcykge1xuICAgIHJldHVybiBudWxsIC8vIGNoZWNrIGZvciBOb2RlXG4gIH1cblxuICB2YXIgY2FudmFzID0gb3B0cy5jYW52YXMgfHwgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcbiAgaWYgKHR5cGVvZiBvcHRzLndpZHRoID09PSAnbnVtYmVyJykge1xuICAgIGNhbnZhcy53aWR0aCA9IG9wdHMud2lkdGhcbiAgfVxuICBpZiAodHlwZW9mIG9wdHMuaGVpZ2h0ID09PSAnbnVtYmVyJykge1xuICAgIGNhbnZhcy5oZWlnaHQgPSBvcHRzLmhlaWdodFxuICB9XG5cbiAgdmFyIGF0dHJpYnMgPSBvcHRzXG4gIHZhciBnbFxuICB0cnkge1xuICAgIHZhciBuYW1lcyA9IFsgdHlwZSBdXG4gICAgLy8gcHJlZml4IEdMIGNvbnRleHRzXG4gICAgaWYgKHR5cGUuaW5kZXhPZignd2ViZ2wnKSA9PT0gMCkge1xuICAgICAgbmFtZXMucHVzaCgnZXhwZXJpbWVudGFsLScgKyB0eXBlKVxuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGdsID0gY2FudmFzLmdldENvbnRleHQobmFtZXNbaV0sIGF0dHJpYnMpXG4gICAgICBpZiAoZ2wpIHJldHVybiBnbFxuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIGdsID0gbnVsbFxuICB9XG4gIHJldHVybiAoZ2wgfHwgbnVsbCkgLy8gZW5zdXJlIG51bGwgb24gZmFpbFxufVxuXG59LHt9XSwyMzM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlQXhlc1xuXG52YXIgY3JlYXRlVGV4dCAgICAgICAgPSBfZGVyZXFfKCcuL2xpYi90ZXh0LmpzJylcbnZhciBjcmVhdGVMaW5lcyAgICAgICA9IF9kZXJlcV8oJy4vbGliL2xpbmVzLmpzJylcbnZhciBjcmVhdGVCYWNrZ3JvdW5kICA9IF9kZXJlcV8oJy4vbGliL2JhY2tncm91bmQuanMnKVxudmFyIGdldEN1YmVQcm9wZXJ0aWVzID0gX2RlcmVxXygnLi9saWIvY3ViZS5qcycpXG52YXIgVGlja3MgICAgICAgICAgICAgPSBfZGVyZXFfKCcuL2xpYi90aWNrcy5qcycpXG5cbnZhciBpZGVudGl0eSA9IG5ldyBGbG9hdDMyQXJyYXkoW1xuICAxLCAwLCAwLCAwLFxuICAwLCAxLCAwLCAwLFxuICAwLCAwLCAxLCAwLFxuICAwLCAwLCAwLCAxXSlcblxuZnVuY3Rpb24gY29weVZlYzMoYSwgYikge1xuICBhWzBdID0gYlswXVxuICBhWzFdID0gYlsxXVxuICBhWzJdID0gYlsyXVxuICByZXR1cm4gYVxufVxuXG5mdW5jdGlvbiBBeGVzKGdsKSB7XG4gIHRoaXMuZ2wgICAgICAgICAgICAgPSBnbFxuXG4gIHRoaXMucGl4ZWxSYXRpbyAgICAgPSAxXG5cbiAgdGhpcy5ib3VuZHMgICAgICAgICA9IFsgWy0xMCwgLTEwLCAtMTBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBbIDEwLCAgMTAsICAxMF0gXVxuICB0aGlzLnRpY2tzICAgICAgICAgID0gWyBbXSwgW10sIFtdIF1cbiAgdGhpcy5hdXRvVGlja3MgICAgICA9IHRydWVcbiAgdGhpcy50aWNrU3BhY2luZyAgICA9IFsgMSwgMSwgMSBdXG5cbiAgdGhpcy50aWNrRW5hYmxlICAgICA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdXG4gIHRoaXMudGlja0ZvbnQgICAgICAgPSBbICdzYW5zLXNlcmlmJywgJ3NhbnMtc2VyaWYnLCAnc2Fucy1zZXJpZicgXVxuICB0aGlzLnRpY2tTaXplICAgICAgID0gWyAxMiwgMTIsIDEyIF1cbiAgdGhpcy50aWNrQW5nbGUgICAgICA9IFsgMCwgMCwgMCBdXG4gIHRoaXMudGlja0FsaWduICAgICAgPSBbICdhdXRvJywgJ2F1dG8nLCAnYXV0bycgXVxuICB0aGlzLnRpY2tDb2xvciAgICAgID0gWyBbMCwwLDAsMV0sIFswLDAsMCwxXSwgWzAsMCwwLDFdIF1cbiAgdGhpcy50aWNrUGFkICAgICAgICA9IFsgMTAsIDEwLCAxMCBdXG5cbiAgdGhpcy5sYXN0Q3ViZVByb3BzICA9IHtcbiAgICBjdWJlRWRnZXM6IFswLDAsMF0sXG4gICAgYXhpczogICAgICBbMCwwLDBdXG4gIH1cblxuICB0aGlzLmxhYmVscyAgICAgICAgID0gWyAneCcsICd5JywgJ3onIF1cbiAgdGhpcy5sYWJlbEVuYWJsZSAgICA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdXG4gIHRoaXMubGFiZWxGb250ICAgICAgPSAnc2Fucy1zZXJpZidcbiAgdGhpcy5sYWJlbFNpemUgICAgICA9IFsgMjAsIDIwLCAyMCBdXG4gIHRoaXMubGFiZWxBbmdsZSAgICAgPSBbIDAsIDAsIDAgXVxuICB0aGlzLmxhYmVsQWxpZ24gICAgID0gWyAnYXV0bycsICdhdXRvJywgJ2F1dG8nIF1cbiAgdGhpcy5sYWJlbENvbG9yICAgICA9IFsgWzAsMCwwLDFdLCBbMCwwLDAsMV0sIFswLDAsMCwxXSBdXG4gIHRoaXMubGFiZWxQYWQgICAgICAgPSBbIDEwLCAxMCwgMTAgXVxuXG4gIHRoaXMubGluZUVuYWJsZSAgICAgPSBbIHRydWUsIHRydWUsIHRydWUgXVxuICB0aGlzLmxpbmVNaXJyb3IgICAgID0gWyBmYWxzZSwgZmFsc2UsIGZhbHNlIF1cbiAgdGhpcy5saW5lV2lkdGggICAgICA9IFsgMSwgMSwgMSBdXG4gIHRoaXMubGluZUNvbG9yICAgICAgPSBbIFswLDAsMCwxXSwgWzAsMCwwLDFdLCBbMCwwLDAsMV0gXVxuXG4gIHRoaXMubGluZVRpY2tFbmFibGUgPSBbIHRydWUsIHRydWUsIHRydWUgXVxuICB0aGlzLmxpbmVUaWNrTWlycm9yID0gWyBmYWxzZSwgZmFsc2UsIGZhbHNlIF1cbiAgdGhpcy5saW5lVGlja0xlbmd0aCA9IFsgMCwgMCwgMCBdXG4gIHRoaXMubGluZVRpY2tXaWR0aCAgPSBbIDEsIDEsIDEgXVxuICB0aGlzLmxpbmVUaWNrQ29sb3IgID0gWyBbMCwwLDAsMV0sIFswLDAsMCwxXSwgWzAsMCwwLDFdIF1cblxuICB0aGlzLmdyaWRFbmFibGUgICAgID0gWyB0cnVlLCB0cnVlLCB0cnVlIF1cbiAgdGhpcy5ncmlkV2lkdGggICAgICA9IFsgMSwgMSwgMSBdXG4gIHRoaXMuZ3JpZENvbG9yICAgICAgPSBbIFswLDAsMCwxXSwgWzAsMCwwLDFdLCBbMCwwLDAsMV0gXVxuXG4gIHRoaXMuemVyb0VuYWJsZSAgICAgPSBbIHRydWUsIHRydWUsIHRydWUgXVxuICB0aGlzLnplcm9MaW5lQ29sb3IgID0gWyBbMCwwLDAsMV0sIFswLDAsMCwxXSwgWzAsMCwwLDFdIF1cbiAgdGhpcy56ZXJvTGluZVdpZHRoICA9IFsgMiwgMiwgMiBdXG5cbiAgdGhpcy5iYWNrZ3JvdW5kRW5hYmxlID0gWyBmYWxzZSwgZmFsc2UsIGZhbHNlIF1cbiAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgID0gWyBbMC44LCAwLjgsIDAuOCwgMC41XSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMC44LCAwLjgsIDAuOCwgMC41XSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMC44LCAwLjgsIDAuOCwgMC41XSBdXG5cbiAgdGhpcy5fZmlyc3RJbml0ID0gdHJ1ZVxuICB0aGlzLl90ZXh0ICA9IG51bGxcbiAgdGhpcy5fbGluZXMgPSBudWxsXG4gIHRoaXMuX2JhY2tncm91bmQgPSBjcmVhdGVCYWNrZ3JvdW5kKGdsKVxufVxuXG52YXIgcHJvdG8gPSBBeGVzLnByb3RvdHlwZVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgLy9PcHRpb24gcGFyc2luZyBoZWxwZXIgZnVuY3Rpb25zXG4gIGZ1bmN0aW9uIHBhcnNlT3B0aW9uKG5lc3QsIGNvbnMsIG5hbWUpIHtcbiAgICBpZihuYW1lIGluIG9wdGlvbnMpIHtcbiAgICAgIHZhciBvcHQgPSBvcHRpb25zW25hbWVdXG4gICAgICB2YXIgcHJldiA9IHRoaXNbbmFtZV1cbiAgICAgIHZhciBuZXh0XG4gICAgICBpZihuZXN0ID8gKEFycmF5LmlzQXJyYXkob3B0KSAmJiBBcnJheS5pc0FycmF5KG9wdFswXSkpIDpcbiAgICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShvcHQpICkge1xuICAgICAgICB0aGlzW25hbWVdID0gbmV4dCA9IFsgY29ucyhvcHRbMF0pLCBjb25zKG9wdFsxXSksIGNvbnMob3B0WzJdKSBdXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzW25hbWVdID0gbmV4dCA9IFsgY29ucyhvcHQpLCBjb25zKG9wdCksIGNvbnMob3B0KSBdXG4gICAgICB9XG4gICAgICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICAgICAgaWYobmV4dFtpXSAhPT0gcHJldltpXSkge1xuICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICB2YXIgTlVNQkVSICA9IHBhcnNlT3B0aW9uLmJpbmQodGhpcywgZmFsc2UsIE51bWJlcilcbiAgdmFyIEJPT0xFQU4gPSBwYXJzZU9wdGlvbi5iaW5kKHRoaXMsIGZhbHNlLCBCb29sZWFuKVxuICB2YXIgU1RSSU5HICA9IHBhcnNlT3B0aW9uLmJpbmQodGhpcywgZmFsc2UsIFN0cmluZylcbiAgdmFyIENPTE9SICAgPSBwYXJzZU9wdGlvbi5iaW5kKHRoaXMsIHRydWUsIGZ1bmN0aW9uKHYpIHtcbiAgICBpZihBcnJheS5pc0FycmF5KHYpKSB7XG4gICAgICBpZih2Lmxlbmd0aCA9PT0gMykge1xuICAgICAgICByZXR1cm4gWyArdlswXSwgK3ZbMV0sICt2WzJdLCAxLjAgXVxuICAgICAgfSBlbHNlIGlmKHYubGVuZ3RoID09PSA0KSB7XG4gICAgICAgIHJldHVybiBbICt2WzBdLCArdlsxXSwgK3ZbMl0sICt2WzNdIF1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFsgMCwgMCwgMCwgMSBdXG4gIH0pXG5cbiAgLy9UaWNrIG1hcmtzIGFuZCBib3VuZHNcbiAgdmFyIG5leHRUaWNrc1xuICB2YXIgdGlja3NVcGRhdGUgICA9IGZhbHNlXG4gIHZhciBib3VuZHNDaGFuZ2VkID0gZmFsc2VcbiAgaWYoJ2JvdW5kcycgaW4gb3B0aW9ucykge1xuICAgIHZhciBib3VuZHMgPSBvcHRpb25zLmJvdW5kc1xuaV9sb29wOlxuICAgIGZvcih2YXIgaT0wOyBpPDI7ICsraSkge1xuICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICAgIGlmKGJvdW5kc1tpXVtqXSAhPT0gdGhpcy5ib3VuZHNbaV1bal0pIHtcbiAgICAgICAgICBib3VuZHNDaGFuZ2VkID0gdHJ1ZVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuYm91bmRzW2ldW2pdID0gYm91bmRzW2ldW2pdXG4gICAgICB9XG4gICAgfVxuICB9XG4gIGlmKCd0aWNrcycgaW4gb3B0aW9ucykge1xuICAgIG5leHRUaWNrcyAgICAgID0gb3B0aW9ucy50aWNrc1xuICAgIHRpY2tzVXBkYXRlICAgID0gdHJ1ZVxuICAgIHRoaXMuYXV0b1RpY2tzID0gZmFsc2VcbiAgICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICAgIHRoaXMudGlja1NwYWNpbmdbaV0gPSAwLjBcbiAgICB9XG4gIH0gZWxzZSBpZihOVU1CRVIoJ3RpY2tTcGFjaW5nJykpIHtcbiAgICB0aGlzLmF1dG9UaWNrcyAgPSB0cnVlXG4gICAgYm91bmRzQ2hhbmdlZCAgID0gdHJ1ZVxuICB9XG5cbiAgaWYodGhpcy5fZmlyc3RJbml0KSB7XG4gICAgaWYoISgndGlja3MnIGluIG9wdGlvbnMgfHwgJ3RpY2tTcGFjaW5nJyBpbiBvcHRpb25zKSkge1xuICAgICAgdGhpcy5hdXRvVGlja3MgPSB0cnVlXG4gICAgfVxuXG4gICAgLy9Gb3JjZSB0aWNrIHJlY29tcHV0YXRpb24gb24gZmlyc3QgdXBkYXRlXG4gICAgYm91bmRzQ2hhbmdlZCAgID0gdHJ1ZVxuICAgIHRpY2tzVXBkYXRlICAgICA9IHRydWVcbiAgICB0aGlzLl9maXJzdEluaXQgPSBmYWxzZVxuICB9XG5cbiAgaWYoYm91bmRzQ2hhbmdlZCAmJiB0aGlzLmF1dG9UaWNrcykge1xuICAgIG5leHRUaWNrcyA9IFRpY2tzLmNyZWF0ZSh0aGlzLmJvdW5kcywgdGhpcy50aWNrU3BhY2luZylcbiAgICB0aWNrc1VwZGF0ZSA9IHRydWVcbiAgfVxuXG4gIC8vQ29tcGFyZSBuZXh0IHRpY2tzIHRvIHByZXZpb3VzIHRpY2tzLCBvbmx5IHVwZGF0ZSBpZiBuZWVkZWRcbiAgaWYodGlja3NVcGRhdGUpIHtcbiAgICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICAgIG5leHRUaWNrc1tpXS5zb3J0KGZ1bmN0aW9uKGEsYikge1xuICAgICAgICByZXR1cm4gYS54LWIueFxuICAgICAgfSlcbiAgICB9XG4gICAgaWYoVGlja3MuZXF1YWwobmV4dFRpY2tzLCB0aGlzLnRpY2tzKSkge1xuICAgICAgdGlja3NVcGRhdGUgPSBmYWxzZVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnRpY2tzID0gbmV4dFRpY2tzXG4gICAgfVxuICB9XG5cbiAgLy9QYXJzZSB0aWNrIHByb3BlcnRpZXNcbiAgQk9PTEVBTigndGlja0VuYWJsZScpXG4gIGlmKFNUUklORygndGlja0ZvbnQnKSkge1xuICAgIHRpY2tzVXBkYXRlID0gdHJ1ZSAgLy9JZiBmb250IGNoYW5nZXMsIG11c3QgcmVidWlsZCB2Ym9cbiAgfVxuICBOVU1CRVIoJ3RpY2tTaXplJylcbiAgTlVNQkVSKCd0aWNrQW5nbGUnKVxuICBOVU1CRVIoJ3RpY2tQYWQnKVxuICBDT0xPUigndGlja0NvbG9yJylcblxuICAvL0F4aXMgbGFiZWxzXG4gIHZhciBsYWJlbFVwZGF0ZSA9IFNUUklORygnbGFiZWxzJylcbiAgaWYoU1RSSU5HKCdsYWJlbEZvbnQnKSkge1xuICAgIGxhYmVsVXBkYXRlID0gdHJ1ZVxuICB9XG4gIEJPT0xFQU4oJ2xhYmVsRW5hYmxlJylcbiAgTlVNQkVSKCdsYWJlbFNpemUnKVxuICBOVU1CRVIoJ2xhYmVsUGFkJylcbiAgQ09MT1IoJ2xhYmVsQ29sb3InKVxuXG4gIC8vQXhpcyBsaW5lc1xuICBCT09MRUFOKCdsaW5lRW5hYmxlJylcbiAgQk9PTEVBTignbGluZU1pcnJvcicpXG4gIE5VTUJFUignbGluZVdpZHRoJylcbiAgQ09MT1IoJ2xpbmVDb2xvcicpXG5cbiAgLy9BeGlzIGxpbmUgdGlja3NcbiAgQk9PTEVBTignbGluZVRpY2tFbmFibGUnKVxuICBCT09MRUFOKCdsaW5lVGlja01pcnJvcicpXG4gIE5VTUJFUignbGluZVRpY2tMZW5ndGgnKVxuICBOVU1CRVIoJ2xpbmVUaWNrV2lkdGgnKVxuICBDT0xPUignbGluZVRpY2tDb2xvcicpXG5cbiAgLy9HcmlkIGxpbmVzXG4gIEJPT0xFQU4oJ2dyaWRFbmFibGUnKVxuICBOVU1CRVIoJ2dyaWRXaWR0aCcpXG4gIENPTE9SKCdncmlkQ29sb3InKVxuXG4gIC8vWmVybyBsaW5lXG4gIEJPT0xFQU4oJ3plcm9FbmFibGUnKVxuICBDT0xPUignemVyb0xpbmVDb2xvcicpXG4gIE5VTUJFUignemVyb0xpbmVXaWR0aCcpXG5cbiAgLy9CYWNrZ3JvdW5kXG4gIEJPT0xFQU4oJ2JhY2tncm91bmRFbmFibGUnKVxuICBDT0xPUignYmFja2dyb3VuZENvbG9yJylcblxuICAvL1VwZGF0ZSB0ZXh0IGlmIG5lY2Vzc2FyeVxuICBpZighdGhpcy5fdGV4dCkge1xuICAgIHRoaXMuX3RleHQgPSBjcmVhdGVUZXh0KFxuICAgICAgdGhpcy5nbCxcbiAgICAgIHRoaXMuYm91bmRzLFxuICAgICAgdGhpcy5sYWJlbHMsXG4gICAgICB0aGlzLmxhYmVsRm9udCxcbiAgICAgIHRoaXMudGlja3MsXG4gICAgICB0aGlzLnRpY2tGb250KVxuICB9IGVsc2UgaWYodGhpcy5fdGV4dCAmJiAobGFiZWxVcGRhdGUgfHwgdGlja3NVcGRhdGUpKSB7XG4gICAgdGhpcy5fdGV4dC51cGRhdGUoXG4gICAgICB0aGlzLmJvdW5kcyxcbiAgICAgIHRoaXMubGFiZWxzLFxuICAgICAgdGhpcy5sYWJlbEZvbnQsXG4gICAgICB0aGlzLnRpY2tzLFxuICAgICAgdGhpcy50aWNrRm9udClcbiAgfVxuXG4gIC8vVXBkYXRlIGxpbmVzIGlmIG5lY2Vzc2FyeVxuICBpZih0aGlzLl9saW5lcyAmJiB0aWNrc1VwZGF0ZSkge1xuICAgIHRoaXMuX2xpbmVzLmRpc3Bvc2UoKVxuICAgIHRoaXMuX2xpbmVzID0gbnVsbFxuICB9XG4gIGlmKCF0aGlzLl9saW5lcykge1xuICAgIHRoaXMuX2xpbmVzID0gY3JlYXRlTGluZXModGhpcy5nbCwgdGhpcy5ib3VuZHMsIHRoaXMudGlja3MpXG4gIH1cbn1cblxuZnVuY3Rpb24gT2Zmc2V0SW5mbygpIHtcbiAgdGhpcy5wcmltYWxPZmZzZXQgPSBbMCwwLDBdXG4gIHRoaXMucHJpbWFsTWlub3IgID0gWzAsMCwwXVxuICB0aGlzLm1pcnJvck9mZnNldCA9IFswLDAsMF1cbiAgdGhpcy5taXJyb3JNaW5vciAgPSBbMCwwLDBdXG59XG5cbnZhciBMSU5FX09GRlNFVCA9IFsgbmV3IE9mZnNldEluZm8oKSwgbmV3IE9mZnNldEluZm8oKSwgbmV3IE9mZnNldEluZm8oKSBdXG5cbmZ1bmN0aW9uIGNvbXB1dGVMaW5lT2Zmc2V0KHJlc3VsdCwgaSwgYm91bmRzLCBjdWJlRWRnZXMsIGN1YmVBeGlzKSB7XG4gIHZhciBwcmltYWxPZmZzZXQgPSByZXN1bHQucHJpbWFsT2Zmc2V0XG4gIHZhciBwcmltYWxNaW5vciAgPSByZXN1bHQucHJpbWFsTWlub3JcbiAgdmFyIGR1YWxPZmZzZXQgICA9IHJlc3VsdC5taXJyb3JPZmZzZXRcbiAgdmFyIGR1YWxNaW5vciAgICA9IHJlc3VsdC5taXJyb3JNaW5vclxuICB2YXIgZSA9IGN1YmVFZGdlc1tpXVxuXG4gIC8vQ2FsY3VsYXRlIG9mZnNldHNcbiAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgaWYoaSA9PT0gaikge1xuICAgICAgY29udGludWVcbiAgICB9XG4gICAgdmFyIGEgPSBwcmltYWxPZmZzZXQsXG4gICAgICAgIGIgPSBkdWFsT2Zmc2V0LFxuICAgICAgICBjID0gcHJpbWFsTWlub3IsXG4gICAgICAgIGQgPSBkdWFsTWlub3JcbiAgICBpZihlICYgKDE8PGopKSB7XG4gICAgICBhID0gZHVhbE9mZnNldFxuICAgICAgYiA9IHByaW1hbE9mZnNldFxuICAgICAgYyA9IGR1YWxNaW5vclxuICAgICAgZCA9IHByaW1hbE1pbm9yXG4gICAgfVxuICAgIGFbal0gPSBib3VuZHNbMF1bal1cbiAgICBiW2pdID0gYm91bmRzWzFdW2pdXG4gICAgaWYoY3ViZUF4aXNbal0gPiAwKSB7XG4gICAgICBjW2pdID0gLTFcbiAgICAgIGRbal0gPSAwXG4gICAgfSBlbHNlIHtcbiAgICAgIGNbal0gPSAwXG4gICAgICBkW2pdID0gKzFcbiAgICB9XG4gIH1cbn1cblxudmFyIENVQkVfRU5BQkxFID0gWzAsMCwwXVxudmFyIERFRkFVTFRfUEFSQU1TID0ge1xuICBtb2RlbDogICAgICBpZGVudGl0eSxcbiAgdmlldzogICAgICAgaWRlbnRpdHksXG4gIHByb2plY3Rpb246IGlkZW50aXR5LFxuICBfb3J0aG86ICAgICAgZmFsc2Vcbn1cblxucHJvdG8uaXNPcGFxdWUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRydWVcbn1cblxucHJvdG8uaXNUcmFuc3BhcmVudCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gZmFsc2Vcbn1cblxucHJvdG8uZHJhd1RyYW5zcGFyZW50ID0gZnVuY3Rpb24ocGFyYW1zKSB7fVxuXG52YXIgQUxJR05fT1BUSU9OX0FVVE8gPSAwIC8vIGkuZS4gYXMgZGVmaW5lZCBpbiB0aGUgc2hhZGVyIHRoZSB0ZXh0IHdvdWxkIHJvdGF0ZSB0byBzdGF5IHVwd2FyZHMgcmFuZ2U6IFstOTAsOTBdXG5cbnZhciBQUklNQUxfTUlOT1IgID0gWzAsMCwwXVxudmFyIE1JUlJPUl9NSU5PUiAgPSBbMCwwLDBdXG52YXIgUFJJTUFMX09GRlNFVCA9IFswLDAsMF1cblxucHJvdG8uZHJhdyA9IGZ1bmN0aW9uKHBhcmFtcykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwgREVGQVVMVF9QQVJBTVNcblxuICB2YXIgZ2wgPSB0aGlzLmdsXG5cbiAgLy9HZW9tZXRyeSBmb3IgY2FtZXJhIGFuZCBheGVzXG4gIHZhciBtb2RlbCAgICAgICA9IHBhcmFtcy5tb2RlbCB8fCBpZGVudGl0eVxuICB2YXIgdmlldyAgICAgICAgPSBwYXJhbXMudmlldyB8fCBpZGVudGl0eVxuICB2YXIgcHJvamVjdGlvbiAgPSBwYXJhbXMucHJvamVjdGlvbiB8fCBpZGVudGl0eVxuICB2YXIgYm91bmRzICAgICAgPSB0aGlzLmJvdW5kc1xuICB2YXIgaXNPcnRobyAgICAgPSBwYXJhbXMuX29ydGhvIHx8IGZhbHNlXG5cbiAgLy9VbnBhY2sgYXhpcyBpbmZvXG4gIHZhciBjdWJlUGFyYW1zICA9IGdldEN1YmVQcm9wZXJ0aWVzKG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uLCBib3VuZHMsIGlzT3J0aG8pXG4gIHZhciBjdWJlRWRnZXMgICA9IGN1YmVQYXJhbXMuY3ViZUVkZ2VzXG4gIHZhciBjdWJlQXhpcyAgICA9IGN1YmVQYXJhbXMuYXhpc1xuXG4gIHZhciBjeCA9IHZpZXdbMTJdXG4gIHZhciBjeSA9IHZpZXdbMTNdXG4gIHZhciBjeiA9IHZpZXdbMTRdXG4gIHZhciBjdyA9IHZpZXdbMTVdXG5cbiAgdmFyIG9ydGhvRml4ID0gKGlzT3J0aG8pID8gMiA6IDEgLy8gZG91YmxlIHVwIHBhZGRpbmcgZm9yIG9ydGhvZ3JhcGhpYyB0aWNrcyAmIGxhYmVsc1xuICB2YXIgcGl4ZWxTY2FsZUYgPSBvcnRob0ZpeCAqIHRoaXMucGl4ZWxSYXRpbyAqIChwcm9qZWN0aW9uWzNdKmN4ICsgcHJvamVjdGlvbls3XSpjeSArIHByb2plY3Rpb25bMTFdKmN6ICsgcHJvamVjdGlvblsxNV0qY3cpIC8gZ2wuZHJhd2luZ0J1ZmZlckhlaWdodFxuXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHRoaXMubGFzdEN1YmVQcm9wcy5jdWJlRWRnZXNbaV0gPSBjdWJlRWRnZXNbaV1cbiAgICB0aGlzLmxhc3RDdWJlUHJvcHMuYXhpc1tpXSA9IGN1YmVBeGlzW2ldXG4gIH1cblxuICAvL0NvbXB1dGUgYXhpcyBpbmZvXG4gIHZhciBsaW5lT2Zmc2V0ICA9IExJTkVfT0ZGU0VUXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIGNvbXB1dGVMaW5lT2Zmc2V0KFxuICAgICAgTElORV9PRkZTRVRbaV0sXG4gICAgICBpLFxuICAgICAgdGhpcy5ib3VuZHMsXG4gICAgICBjdWJlRWRnZXMsXG4gICAgICBjdWJlQXhpcylcbiAgfVxuXG4gIC8vU2V0IHVwIHN0YXRlIHBhcmFtZXRlcnNcbiAgdmFyIGdsID0gdGhpcy5nbFxuXG4gIC8vRHJhdyBiYWNrZ3JvdW5kIGZpcnN0XG4gIHZhciBjdWJlRW5hYmxlID0gQ1VCRV9FTkFCTEVcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgaWYodGhpcy5iYWNrZ3JvdW5kRW5hYmxlW2ldKSB7XG4gICAgICBjdWJlRW5hYmxlW2ldID0gY3ViZUF4aXNbaV1cbiAgICB9IGVsc2Uge1xuICAgICAgY3ViZUVuYWJsZVtpXSA9IDBcbiAgICB9XG4gIH1cblxuICB0aGlzLl9iYWNrZ3JvdW5kLmRyYXcoXG4gICAgbW9kZWwsXG4gICAgdmlldyxcbiAgICBwcm9qZWN0aW9uLFxuICAgIGJvdW5kcyxcbiAgICBjdWJlRW5hYmxlLFxuICAgIHRoaXMuYmFja2dyb3VuZENvbG9yKVxuXG4gIC8vRHJhdyBsaW5lc1xuICB0aGlzLl9saW5lcy5iaW5kKFxuICAgIG1vZGVsLFxuICAgIHZpZXcsXG4gICAgcHJvamVjdGlvbixcbiAgICB0aGlzKVxuXG4gIC8vRmlyc3QgZHJhdyBncmlkIGxpbmVzIGFuZCB6ZXJvIGxpbmVzXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHZhciB4ID0gWzAsMCwwXVxuICAgIGlmKGN1YmVBeGlzW2ldID4gMCkge1xuICAgICAgeFtpXSA9IGJvdW5kc1sxXVtpXVxuICAgIH0gZWxzZSB7XG4gICAgICB4W2ldID0gYm91bmRzWzBdW2ldXG4gICAgfVxuXG4gICAgLy9EcmF3IGdyaWQgbGluZXNcbiAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcbiAgICAgIHZhciB1ID0gKGkgKyAxICsgaikgJSAzXG4gICAgICB2YXIgdiA9IChpICsgMSArIChqXjEpKSAlIDNcbiAgICAgIGlmKHRoaXMuZ3JpZEVuYWJsZVt1XSkge1xuICAgICAgICB0aGlzLl9saW5lcy5kcmF3R3JpZCh1LCB2LCB0aGlzLmJvdW5kcywgeCwgdGhpcy5ncmlkQ29sb3JbdV0sIHRoaXMuZ3JpZFdpZHRoW3VdKnRoaXMucGl4ZWxSYXRpbylcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvL0RyYXcgemVybyBsaW5lcyAobmVlZCB0byBkbyB0aGlzIEFGVEVSIGFsbCBncmlkIGxpbmVzIGFyZSBkcmF3bilcbiAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcbiAgICAgIHZhciB1ID0gKGkgKyAxICsgaikgJSAzXG4gICAgICB2YXIgdiA9IChpICsgMSArIChqXjEpKSAlIDNcbiAgICAgIGlmKHRoaXMuemVyb0VuYWJsZVt2XSkge1xuICAgICAgICAvL0NoZWNrIGlmIHplcm8gbGluZSBpbiBib3VuZHNcbiAgICAgICAgaWYoTWF0aC5taW4oYm91bmRzWzBdW3ZdLCBib3VuZHNbMV1bdl0pIDw9IDAgJiYgTWF0aC5tYXgoYm91bmRzWzBdW3ZdLCBib3VuZHNbMV1bdl0pID49IDApIHtcbiAgICAgICAgICB0aGlzLl9saW5lcy5kcmF3WmVybyh1LCB2LCB0aGlzLmJvdW5kcywgeCwgdGhpcy56ZXJvTGluZUNvbG9yW3ZdLCB0aGlzLnplcm9MaW5lV2lkdGhbdl0qdGhpcy5waXhlbFJhdGlvKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9UaGVuIGRyYXcgYXhpcyBsaW5lcyBhbmQgdGljayBtYXJrc1xuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcblxuICAgIC8vRHJhdyBheGlzIGxpbmVzXG4gICAgaWYodGhpcy5saW5lRW5hYmxlW2ldKSB7XG4gICAgICB0aGlzLl9saW5lcy5kcmF3QXhpc0xpbmUoaSwgdGhpcy5ib3VuZHMsIGxpbmVPZmZzZXRbaV0ucHJpbWFsT2Zmc2V0LCB0aGlzLmxpbmVDb2xvcltpXSwgdGhpcy5saW5lV2lkdGhbaV0qdGhpcy5waXhlbFJhdGlvKVxuICAgIH1cbiAgICBpZih0aGlzLmxpbmVNaXJyb3JbaV0pIHtcbiAgICAgIHRoaXMuX2xpbmVzLmRyYXdBeGlzTGluZShpLCB0aGlzLmJvdW5kcywgbGluZU9mZnNldFtpXS5taXJyb3JPZmZzZXQsIHRoaXMubGluZUNvbG9yW2ldLCB0aGlzLmxpbmVXaWR0aFtpXSp0aGlzLnBpeGVsUmF0aW8pXG4gICAgfVxuXG4gICAgLy9Db21wdXRlIG1pbm9yIGF4ZXNcbiAgICB2YXIgcHJpbWFsTWlub3IgPSBjb3B5VmVjMyhQUklNQUxfTUlOT1IsIGxpbmVPZmZzZXRbaV0ucHJpbWFsTWlub3IpXG4gICAgdmFyIG1pcnJvck1pbm9yID0gY29weVZlYzMoTUlSUk9SX01JTk9SLCBsaW5lT2Zmc2V0W2ldLm1pcnJvck1pbm9yKVxuICAgIHZhciB0aWNrTGVuZ3RoICA9IHRoaXMubGluZVRpY2tMZW5ndGhcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIHZhciBzY2FsZUZhY3RvciA9IHBpeGVsU2NhbGVGIC8gbW9kZWxbNSpqXVxuICAgICAgcHJpbWFsTWlub3Jbal0gKj0gdGlja0xlbmd0aFtqXSAqIHNjYWxlRmFjdG9yXG4gICAgICBtaXJyb3JNaW5vcltqXSAqPSB0aWNrTGVuZ3RoW2pdICogc2NhbGVGYWN0b3JcbiAgICB9XG5cblxuXG4gICAgLy9EcmF3IGF4aXMgbGluZSB0aWNrc1xuICAgIGlmKHRoaXMubGluZVRpY2tFbmFibGVbaV0pIHtcbiAgICAgIHRoaXMuX2xpbmVzLmRyYXdBeGlzVGlja3MoaSwgbGluZU9mZnNldFtpXS5wcmltYWxPZmZzZXQsIHByaW1hbE1pbm9yLCB0aGlzLmxpbmVUaWNrQ29sb3JbaV0sIHRoaXMubGluZVRpY2tXaWR0aFtpXSp0aGlzLnBpeGVsUmF0aW8pXG4gICAgfVxuICAgIGlmKHRoaXMubGluZVRpY2tNaXJyb3JbaV0pIHtcbiAgICAgIHRoaXMuX2xpbmVzLmRyYXdBeGlzVGlja3MoaSwgbGluZU9mZnNldFtpXS5taXJyb3JPZmZzZXQsIG1pcnJvck1pbm9yLCB0aGlzLmxpbmVUaWNrQ29sb3JbaV0sIHRoaXMubGluZVRpY2tXaWR0aFtpXSp0aGlzLnBpeGVsUmF0aW8pXG4gICAgfVxuICB9XG4gIHRoaXMuX2xpbmVzLnVuYmluZCgpXG5cbiAgLy9EcmF3IHRleHQgc3ByaXRlc1xuICB0aGlzLl90ZXh0LmJpbmQoXG4gICAgbW9kZWwsXG4gICAgdmlldyxcbiAgICBwcm9qZWN0aW9uLFxuICAgIHRoaXMucGl4ZWxSYXRpbylcblxuICB2YXIgYWxpZ25PcHQgLy8gb3B0aW9ucyBpbiBzaGFkZXIgYXJlIGZyb20gdGhpcyBsaXN0IHstMSwgMCwgMSwgMiwgMywgLi4uLCBufVxuICAvLyAtMTogYmFja3dhcmQgY29tcGF0aWJsZVxuICAvLyAgMDogcmF3IGRhdGFcbiAgLy8gIDE6IGF1dG8gYWxpZ24sIGZyZWUgYW5nbGVzXG4gIC8vICAyOiBhdXRvIGFsaWduLCBob3Jpem9udGFsIG9yIHZlcnRpY2FsXG4gIC8vMy1uOiBhdXRvIGFsaWduLCByb3VuZCB0byBuIGRpcmVjdGlvbnMgZS5nLiAxMiAtPiByb3VuZCB0byBhbmdsZXMgd2l0aCAzMC1kZWdyZWUgc3RlcHNcblxuICB2YXIgaHZfcmF0aW8gPSAwLjUgLy8gY2FuIGhhdmUgYW4gZWZmZWN0IG9uIHRoZSByYXRpbyBiZXR3ZWVuIGhvcml6b250YWxzIGFuZCB2ZXJ0aWNhbHMgd2hlbiB1c2luZyBvcHRpb24gMlxuXG4gIHZhciBlbmFibGVBbGlnblxuICB2YXIgYWxpZ25EaXJcblxuICBmdW5jdGlvbiBhbGlnblRvKGkpIHtcbiAgICBhbGlnbkRpciA9IFswLDAsMF1cbiAgICBhbGlnbkRpcltpXSA9IDFcbiAgfVxuXG4gIGZ1bmN0aW9uIHNvbHZlVGlja0FsaWdubWVudHMoaSwgbWlub3IsIG1ham9yKSB7XG5cbiAgICB2YXIgaTEgPSAoaSArIDEpICUgM1xuICAgIHZhciBpMiA9IChpICsgMikgJSAzXG5cbiAgICB2YXIgQSA9IG1pbm9yW2kxXVxuICAgIHZhciBCID0gbWlub3JbaTJdXG4gICAgdmFyIEMgPSBtYWpvcltpMV1cbiAgICB2YXIgRCA9IG1ham9yW2kyXVxuXG4gICAgICAgICBpZiAoKEEgPiAwKSAmJiAoRCA+IDApKSB7IGFsaWduVG8oaTEpOyByZXR1cm47IH1cbiAgICBlbHNlIGlmICgoQSA+IDApICYmIChEIDwgMCkpIHsgYWxpZ25UbyhpMSk7IHJldHVybjsgfVxuICAgIGVsc2UgaWYgKChBIDwgMCkgJiYgKEQgPiAwKSkgeyBhbGlnblRvKGkxKTsgcmV0dXJuOyB9XG4gICAgZWxzZSBpZiAoKEEgPCAwKSAmJiAoRCA8IDApKSB7IGFsaWduVG8oaTEpOyByZXR1cm47IH1cbiAgICBlbHNlIGlmICgoQiA+IDApICYmIChDID4gMCkpIHsgYWxpZ25UbyhpMik7IHJldHVybjsgfVxuICAgIGVsc2UgaWYgKChCID4gMCkgJiYgKEMgPCAwKSkgeyBhbGlnblRvKGkyKTsgcmV0dXJuOyB9XG4gICAgZWxzZSBpZiAoKEIgPCAwKSAmJiAoQyA+IDApKSB7IGFsaWduVG8oaTIpOyByZXR1cm47IH1cbiAgICBlbHNlIGlmICgoQiA8IDApICYmIChDIDwgMCkpIHsgYWxpZ25UbyhpMik7IHJldHVybjsgfVxuICB9XG5cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG5cbiAgICB2YXIgbWlub3IgICAgICA9IGxpbmVPZmZzZXRbaV0ucHJpbWFsTWlub3JcbiAgICB2YXIgbWFqb3IgICAgICA9IGxpbmVPZmZzZXRbaV0ubWlycm9yTWlub3JcblxuICAgIHZhciBvZmZzZXQgICAgID0gY29weVZlYzMoUFJJTUFMX09GRlNFVCwgbGluZU9mZnNldFtpXS5wcmltYWxPZmZzZXQpXG5cbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIGlmKHRoaXMubGluZVRpY2tFbmFibGVbaV0pIHtcbiAgICAgICAgb2Zmc2V0W2pdICs9IHBpeGVsU2NhbGVGICogbWlub3Jbal0gKiBNYXRoLm1heCh0aGlzLmxpbmVUaWNrTGVuZ3RoW2pdLCAwKSAgLyBtb2RlbFs1KmpdXG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGF4aXMgPSBbMCwwLDBdXG4gICAgYXhpc1tpXSA9IDFcblxuICAgIC8vRHJhdyB0aWNrIHRleHRcbiAgICBpZih0aGlzLnRpY2tFbmFibGVbaV0pIHtcblxuICAgICAgaWYodGhpcy50aWNrQW5nbGVbaV0gPT09IC0zNjAwKSB7XG4gICAgICAgIHRoaXMudGlja0FuZ2xlW2ldID0gMFxuICAgICAgICB0aGlzLnRpY2tBbGlnbltpXSA9ICdhdXRvJ1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy50aWNrQWxpZ25baV0gPSAtMVxuICAgICAgfVxuXG4gICAgICBlbmFibGVBbGlnbiA9IDE7XG5cbiAgICAgIGFsaWduT3B0ID0gW3RoaXMudGlja0FsaWduW2ldLCBodl9yYXRpbywgZW5hYmxlQWxpZ25dXG4gICAgICBpZihhbGlnbk9wdFswXSA9PT0gJ2F1dG8nKSBhbGlnbk9wdFswXSA9IEFMSUdOX09QVElPTl9BVVRPXG4gICAgICBlbHNlIGFsaWduT3B0WzBdID0gcGFyc2VJbnQoJycgKyBhbGlnbk9wdFswXSlcblxuICAgICAgYWxpZ25EaXIgPSBbMCwwLDBdXG4gICAgICBzb2x2ZVRpY2tBbGlnbm1lbnRzKGksIG1pbm9yLCBtYWpvcilcblxuICAgICAgLy9BZGQgdGljayBwYWRkaW5nXG4gICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgb2Zmc2V0W2pdICs9IHBpeGVsU2NhbGVGICogbWlub3Jbal0gKiB0aGlzLnRpY2tQYWRbal0gLyBtb2RlbFs1KmpdXG4gICAgICB9XG5cbiAgICAgIC8vRHJhdyBheGlzXG4gICAgICB0aGlzLl90ZXh0LmRyYXdUaWNrcyhcbiAgICAgICAgaSxcbiAgICAgICAgdGhpcy50aWNrU2l6ZVtpXSxcbiAgICAgICAgdGhpcy50aWNrQW5nbGVbaV0sXG4gICAgICAgIG9mZnNldCxcbiAgICAgICAgdGhpcy50aWNrQ29sb3JbaV0sXG4gICAgICAgIGF4aXMsXG4gICAgICAgIGFsaWduRGlyLFxuICAgICAgICBhbGlnbk9wdClcbiAgICB9XG5cbiAgICAvL0RyYXcgbGFiZWxzXG4gICAgaWYodGhpcy5sYWJlbEVuYWJsZVtpXSkge1xuXG4gICAgICBlbmFibGVBbGlnbiA9IDBcbiAgICAgIGFsaWduRGlyID0gWzAsMCwwXVxuICAgICAgaWYodGhpcy5sYWJlbHNbaV0ubGVuZ3RoID4gNCkgeyAvLyBmb3IgbGFyZ2UgbGFiZWwgYXhpcyBlbmFibGUgYWxpZ25EaXIgdG8gYXhpc1xuICAgICAgICBhbGlnblRvKGkpXG4gICAgICAgIGVuYWJsZUFsaWduID0gMVxuICAgICAgfVxuXG4gICAgICBhbGlnbk9wdCA9IFt0aGlzLmxhYmVsQWxpZ25baV0sIGh2X3JhdGlvLCBlbmFibGVBbGlnbl1cbiAgICAgIGlmKGFsaWduT3B0WzBdID09PSAnYXV0bycpIGFsaWduT3B0WzBdID0gQUxJR05fT1BUSU9OX0FVVE9cbiAgICAgIGVsc2UgYWxpZ25PcHRbMF0gPSBwYXJzZUludCgnJyArIGFsaWduT3B0WzBdKVxuXG4gICAgICAvL0FkZCBsYWJlbCBwYWRkaW5nXG4gICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgb2Zmc2V0W2pdICs9IHBpeGVsU2NhbGVGICogbWlub3Jbal0gKiB0aGlzLmxhYmVsUGFkW2pdIC8gbW9kZWxbNSpqXVxuICAgICAgfVxuICAgICAgb2Zmc2V0W2ldICs9IDAuNSAqIChib3VuZHNbMF1baV0gKyBib3VuZHNbMV1baV0pXG5cbiAgICAgIC8vRHJhdyBheGlzXG4gICAgICB0aGlzLl90ZXh0LmRyYXdMYWJlbChcbiAgICAgICAgaSxcbiAgICAgICAgdGhpcy5sYWJlbFNpemVbaV0sXG4gICAgICAgIHRoaXMubGFiZWxBbmdsZVtpXSxcbiAgICAgICAgb2Zmc2V0LFxuICAgICAgICB0aGlzLmxhYmVsQ29sb3JbaV0sXG4gICAgICAgIFswLDAsMF0sXG4gICAgICAgIGFsaWduRGlyLFxuICAgICAgICBhbGlnbk9wdClcbiAgICB9XG4gIH1cblxuICB0aGlzLl90ZXh0LnVuYmluZCgpXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5fdGV4dC5kaXNwb3NlKClcbiAgdGhpcy5fbGluZXMuZGlzcG9zZSgpXG4gIHRoaXMuX2JhY2tncm91bmQuZGlzcG9zZSgpXG4gIHRoaXMuX2xpbmVzID0gbnVsbFxuICB0aGlzLl90ZXh0ID0gbnVsbFxuICB0aGlzLl9iYWNrZ3JvdW5kID0gbnVsbFxuICB0aGlzLmdsID0gbnVsbFxufVxuXG5mdW5jdGlvbiBjcmVhdGVBeGVzKGdsLCBvcHRpb25zKSB7XG4gIHZhciBheGVzID0gbmV3IEF4ZXMoZ2wpXG4gIGF4ZXMudXBkYXRlKG9wdGlvbnMpXG4gIHJldHVybiBheGVzXG59XG5cbn0se1wiLi9saWIvYmFja2dyb3VuZC5qc1wiOjIzNCxcIi4vbGliL2N1YmUuanNcIjoyMzUsXCIuL2xpYi9saW5lcy5qc1wiOjIzNixcIi4vbGliL3RleHQuanNcIjoyMzgsXCIuL2xpYi90aWNrcy5qc1wiOjIzOX1dLDIzNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCYWNrZ3JvdW5kQ3ViZVxuXG52YXIgY3JlYXRlQnVmZmVyID0gX2RlcmVxXygnZ2wtYnVmZmVyJylcbnZhciBjcmVhdGVWQU8gICAgPSBfZGVyZXFfKCdnbC12YW8nKVxudmFyIGNyZWF0ZVNoYWRlciA9IF9kZXJlcV8oJy4vc2hhZGVycycpLmJnXG5cbmZ1bmN0aW9uIEJhY2tncm91bmRDdWJlKGdsLCBidWZmZXIsIHZhbywgc2hhZGVyKSB7XG4gIHRoaXMuZ2wgPSBnbFxuICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlclxuICB0aGlzLnZhbyA9IHZhb1xuICB0aGlzLnNoYWRlciA9IHNoYWRlclxufVxuXG52YXIgcHJvdG8gPSBCYWNrZ3JvdW5kQ3ViZS5wcm90b3R5cGVcblxucHJvdG8uZHJhdyA9IGZ1bmN0aW9uKG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uLCBib3VuZHMsIGVuYWJsZSwgY29sb3JzKSB7XG4gIHZhciBuZWVkc0JHID0gZmFsc2VcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgbmVlZHNCRyA9IG5lZWRzQkcgfHwgZW5hYmxlW2ldXG4gIH1cbiAgaWYoIW5lZWRzQkcpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHZhciBnbCA9IHRoaXMuZ2xcblxuICBnbC5lbmFibGUoZ2wuUE9MWUdPTl9PRkZTRVRfRklMTClcbiAgZ2wucG9seWdvbk9mZnNldCgxLCAyKVxuXG4gIHRoaXMuc2hhZGVyLmJpbmQoKVxuICB0aGlzLnNoYWRlci51bmlmb3JtcyA9IHtcbiAgICBtb2RlbDogbW9kZWwsXG4gICAgdmlldzogdmlldyxcbiAgICBwcm9qZWN0aW9uOiBwcm9qZWN0aW9uLFxuICAgIGJvdW5kczogYm91bmRzLFxuICAgIGVuYWJsZTogZW5hYmxlLFxuICAgIGNvbG9yczogY29sb3JzXG4gIH1cbiAgdGhpcy52YW8uYmluZCgpXG4gIHRoaXMudmFvLmRyYXcodGhpcy5nbC5UUklBTkdMRVMsIDM2KVxuICB0aGlzLnZhby51bmJpbmQoKVxuXG4gIGdsLmRpc2FibGUoZ2wuUE9MWUdPTl9PRkZTRVRfRklMTClcbn1cblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnZhby5kaXNwb3NlKClcbiAgdGhpcy5idWZmZXIuZGlzcG9zZSgpXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVCYWNrZ3JvdW5kQ3ViZShnbCkge1xuICAvL0NyZWF0ZSBjdWJlIHZlcnRpY2VzXG4gIHZhciB2ZXJ0aWNlcyA9IFtdXG4gIHZhciBpbmRpY2VzICA9IFtdXG4gIHZhciBwdHIgPSAwXG4gIGZvcih2YXIgZD0wOyBkPDM7ICsrZCkge1xuICAgIHZhciB1ID0gKGQrMSkgJSAzXG4gICAgdmFyIHYgPSAoZCsyKSAlIDNcbiAgICB2YXIgeCA9IFswLDAsMF1cbiAgICB2YXIgYyA9IFswLDAsMF1cbiAgICBmb3IodmFyIHM9LTE7IHM8PTE7IHMrPTIpIHtcbiAgICAgIGluZGljZXMucHVzaChwdHIsICAgcHRyKzIsIHB0cisxLFxuICAgICAgICAgICAgICAgICAgIHB0cisxLCBwdHIrMiwgcHRyKzMpXG4gICAgICB4W2RdID0gc1xuICAgICAgY1tkXSA9IHNcbiAgICAgIGZvcih2YXIgaT0tMTsgaTw9MTsgaSs9Mikge1xuICAgICAgICB4W3VdID0gaVxuICAgICAgICBmb3IodmFyIGo9LTE7IGo8PTE7IGorPTIpIHtcbiAgICAgICAgICB4W3ZdID0galxuICAgICAgICAgIHZlcnRpY2VzLnB1c2goeFswXSwgeFsxXSwgeFsyXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNbMF0sIGNbMV0sIGNbMl0pXG4gICAgICAgICAgcHRyICs9IDFcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy9Td2FwIHUgYW5kIHZcbiAgICAgIHZhciB0dCA9IHVcbiAgICAgIHUgPSB2XG4gICAgICB2ID0gdHRcbiAgICB9XG4gIH1cblxuICAvL0FsbG9jYXRlIGJ1ZmZlciBhbmQgdmVydGV4IGFycmF5XG4gIHZhciBidWZmZXIgPSBjcmVhdGVCdWZmZXIoZ2wsIG5ldyBGbG9hdDMyQXJyYXkodmVydGljZXMpKVxuICB2YXIgZWxlbWVudHMgPSBjcmVhdGVCdWZmZXIoZ2wsIG5ldyBVaW50MTZBcnJheShpbmRpY2VzKSwgZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIpXG4gIHZhciB2YW8gPSBjcmVhdGVWQU8oZ2wsIFtcbiAgICAgIHtcbiAgICAgICAgYnVmZmVyOiBidWZmZXIsXG4gICAgICAgIHR5cGU6IGdsLkZMT0FULFxuICAgICAgICBzaXplOiAzLFxuICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgIHN0cmlkZTogMjRcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGJ1ZmZlcjogYnVmZmVyLFxuICAgICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgICAgc2l6ZTogMyxcbiAgICAgICAgb2Zmc2V0OiAxMixcbiAgICAgICAgc3RyaWRlOiAyNFxuICAgICAgfVxuICAgIF0sIGVsZW1lbnRzKVxuXG4gIC8vQ3JlYXRlIHNoYWRlciBvYmplY3RcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbClcbiAgc2hhZGVyLmF0dHJpYnV0ZXMucG9zaXRpb24ubG9jYXRpb24gPSAwXG4gIHNoYWRlci5hdHRyaWJ1dGVzLm5vcm1hbC5sb2NhdGlvbiA9IDFcblxuICByZXR1cm4gbmV3IEJhY2tncm91bmRDdWJlKGdsLCBidWZmZXIsIHZhbywgc2hhZGVyKVxufVxuXG59LHtcIi4vc2hhZGVyc1wiOjIzNyxcImdsLWJ1ZmZlclwiOjI0MSxcImdsLXZhb1wiOjMyN31dLDIzNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IGdldEN1YmVFZGdlc1xuXG52YXIgYml0cyAgICAgID0gX2RlcmVxXygnYml0LXR3aWRkbGUnKVxudmFyIG11bHRpcGx5ICA9IF9kZXJlcV8oJ2dsLW1hdDQvbXVsdGlwbHknKVxudmFyIHNwbGl0UG9seSA9IF9kZXJlcV8oJ3NwbGl0LXBvbHlnb24nKVxudmFyIG9yaWVudCAgICA9IF9kZXJlcV8oJ3JvYnVzdC1vcmllbnRhdGlvbicpXG5cbnZhciBtdnAgICAgICAgID0gbmV3IEFycmF5KDE2KVxudmFyIHBDdWJlVmVydHMgPSBuZXcgQXJyYXkoOClcbnZhciBjdWJlVmVydHMgID0gbmV3IEFycmF5KDgpXG52YXIgeCAgICAgICAgICA9IG5ldyBBcnJheSgzKVxudmFyIHplcm8zICAgICAgPSBbMCwwLDBdXG5cbjsoZnVuY3Rpb24oKSB7XG4gIGZvcih2YXIgaT0wOyBpPDg7ICsraSkge1xuICAgIHBDdWJlVmVydHNbaV0gPVsxLDEsMSwxXVxuICAgIGN1YmVWZXJ0c1tpXSA9IFsxLDEsMV1cbiAgfVxufSkoKVxuXG5cbmZ1bmN0aW9uIHRyYW5zZm9ybUhnKHJlc3VsdCwgeCwgbWF0KSB7XG4gIGZvcih2YXIgaT0wOyBpPDQ7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IG1hdFsxMitpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgcmVzdWx0W2ldICs9IHhbal0qbWF0WzQqaitpXVxuICAgIH1cbiAgfVxufVxuXG52YXIgRlJVU1RVTV9QTEFORVMgPSBbXG4gIFsgMCwgMCwgMSwgMCwgMF0sXG4gIFsgMCwgMCwtMSwgMSwgMF0sXG4gIFsgMCwtMSwgMCwgMSwgMF0sXG4gIFsgMCwgMSwgMCwgMSwgMF0sXG4gIFstMSwgMCwgMCwgMSwgMF0sXG4gIFsgMSwgMCwgMCwgMSwgMF1cbl1cblxuZnVuY3Rpb24gcG9seWdvbkFyZWEocCkge1xuICBmb3IodmFyIGk9MDsgaTxGUlVTVFVNX1BMQU5FUy5sZW5ndGg7ICsraSkge1xuICAgIHAgPSBzcGxpdFBvbHkucG9zaXRpdmUocCwgRlJVU1RVTV9QTEFORVNbaV0pXG4gICAgaWYocC5sZW5ndGggPCAzKSB7XG4gICAgICByZXR1cm4gMFxuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gcFswXVxuICB2YXIgYXggPSBiYXNlWzBdIC8gYmFzZVszXVxuICB2YXIgYXkgPSBiYXNlWzFdIC8gYmFzZVszXVxuICB2YXIgYXJlYSA9IDAuMFxuICBmb3IodmFyIGk9MTsgaSsxPHAubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYiA9IHBbaV1cbiAgICB2YXIgYyA9IHBbaSsxXVxuXG4gICAgdmFyIGJ4ID0gYlswXS9iWzNdXG4gICAgdmFyIGJ5ID0gYlsxXS9iWzNdXG4gICAgdmFyIGN4ID0gY1swXS9jWzNdXG4gICAgdmFyIGN5ID0gY1sxXS9jWzNdXG5cbiAgICB2YXIgdXggPSBieCAtIGF4XG4gICAgdmFyIHV5ID0gYnkgLSBheVxuXG4gICAgdmFyIHZ4ID0gY3ggLSBheFxuICAgIHZhciB2eSA9IGN5IC0gYXlcblxuICAgIGFyZWEgKz0gTWF0aC5hYnModXggKiB2eSAtIHV5ICogdngpXG4gIH1cblxuICByZXR1cm4gYXJlYVxufVxuXG52YXIgQ1VCRV9FREdFUyA9IFsxLDEsMV1cbnZhciBDVUJFX0FYSVMgID0gWzAsMCwwXVxudmFyIENVQkVfUkVTVUxUID0ge1xuICBjdWJlRWRnZXM6IENVQkVfRURHRVMsXG4gIGF4aXM6IENVQkVfQVhJU1xufVxuXG5mdW5jdGlvbiBnZXRDdWJlRWRnZXMobW9kZWwsIHZpZXcsIHByb2plY3Rpb24sIGJvdW5kcywgb3J0aG8pIHtcblxuICAvL0NvbmNhdGVuYXRlIG1hdHJpY2VzXG4gIG11bHRpcGx5KG12cCwgdmlldywgbW9kZWwpXG4gIG11bHRpcGx5KG12cCwgcHJvamVjdGlvbiwgbXZwKVxuXG4gIC8vRmlyc3QgcHJvamVjdCBjdWJlIHZlcnRpY2VzXG4gIHZhciBwdHIgPSAwXG4gIGZvcih2YXIgaT0wOyBpPDI7ICsraSkge1xuICAgIHhbMl0gPSBib3VuZHNbaV1bMl1cbiAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcbiAgICAgIHhbMV0gPSBib3VuZHNbal1bMV1cbiAgICAgIGZvcih2YXIgaz0wOyBrPDI7ICsraykge1xuICAgICAgICB4WzBdID0gYm91bmRzW2tdWzBdXG4gICAgICAgIHRyYW5zZm9ybUhnKHBDdWJlVmVydHNbcHRyXSwgeCwgbXZwKVxuICAgICAgICBwdHIgKz0gMVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vQ2xhc3NpZnkgY2FtZXJhIGFnYWluc3QgY3ViZSBmYWNlc1xuICB2YXIgY2xvc2VzdCA9IC0xXG5cbiAgZm9yKHZhciBpPTA7IGk8ODsgKytpKSB7XG4gICAgdmFyIHcgPSBwQ3ViZVZlcnRzW2ldWzNdXG4gICAgZm9yKHZhciBsPTA7IGw8MzsgKytsKSB7XG4gICAgICBjdWJlVmVydHNbaV1bbF0gPSBwQ3ViZVZlcnRzW2ldW2xdIC8gd1xuICAgIH1cblxuICAgIGlmKG9ydGhvKSBjdWJlVmVydHNbaV1bMl0gKj0gLTE7XG5cbiAgICBpZih3IDwgMCkge1xuICAgICAgaWYoY2xvc2VzdCA8IDApIHtcbiAgICAgICAgY2xvc2VzdCA9IGlcbiAgICAgIH0gZWxzZSBpZihjdWJlVmVydHNbaV1bMl0gPCBjdWJlVmVydHNbY2xvc2VzdF1bMl0pIHtcbiAgICAgICAgY2xvc2VzdCA9IGlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZihjbG9zZXN0IDwgMCkge1xuICAgIGNsb3Nlc3QgPSAwXG4gICAgZm9yKHZhciBkPTA7IGQ8MzsgKytkKSB7XG4gICAgICB2YXIgdSA9IChkKzIpICUgM1xuICAgICAgdmFyIHYgPSAoZCsxKSAlIDNcbiAgICAgIHZhciBvMCA9IC0xXG4gICAgICB2YXIgbzEgPSAtMVxuICAgICAgZm9yKHZhciBzPTA7IHM8MjsgKytzKSB7XG4gICAgICAgIHZhciBmMCA9IChzPDxkKVxuICAgICAgICB2YXIgZjEgPSBmMCArIChzIDw8IHUpICsgKCgxLXMpIDw8IHYpXG4gICAgICAgIHZhciBmMiA9IGYwICsgKCgxLXMpIDw8IHUpICsgKHMgPDwgdilcbiAgICAgICAgaWYob3JpZW50KGN1YmVWZXJ0c1tmMF0sIGN1YmVWZXJ0c1tmMV0sIGN1YmVWZXJ0c1tmMl0sIHplcm8zKSA8IDApIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIGlmKHMpIHtcbiAgICAgICAgICBvMCA9IDFcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvMSA9IDFcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYobzAgPCAwIHx8IG8xIDwgMCkge1xuICAgICAgICBpZihvMSA+IG8wKSB7XG4gICAgICAgICAgY2xvc2VzdCB8PSAxPDxkXG4gICAgICAgIH1cbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGZvcih2YXIgcz0wOyBzPDI7ICsrcykge1xuICAgICAgICB2YXIgZjAgPSAoczw8ZClcbiAgICAgICAgdmFyIGYxID0gZjAgKyAocyA8PCB1KSArICgoMS1zKSA8PCB2KVxuICAgICAgICB2YXIgZjIgPSBmMCArICgoMS1zKSA8PCB1KSArIChzIDw8IHYpXG4gICAgICAgIHZhciBvID0gcG9seWdvbkFyZWEoW1xuICAgICAgICAgICAgcEN1YmVWZXJ0c1tmMF0sXG4gICAgICAgICAgICBwQ3ViZVZlcnRzW2YxXSxcbiAgICAgICAgICAgIHBDdWJlVmVydHNbZjJdLFxuICAgICAgICAgICAgcEN1YmVWZXJ0c1tmMCsoMTw8dSkrKDE8PHYpXV0pXG4gICAgICAgIGlmKHMpIHtcbiAgICAgICAgICBvMCA9IG9cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvMSA9IG9cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYobzEgPiBvMCkge1xuICAgICAgICBjbG9zZXN0IHw9IDE8PGRcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB2YXIgZmFydGhlc3QgPSA3XmNsb3Nlc3RcblxuICAvL0ZpbmQgbG93ZXN0IHZlcnRleCB3aGljaCBpcyBub3QgY2xvc2VzdCBjbG9zZXN0XG4gIHZhciBib3R0b20gPSAtMVxuICBmb3IodmFyIGk9MDsgaTw4OyArK2kpIHtcbiAgICBpZihpID09PSBjbG9zZXN0IHx8IGkgPT09IGZhcnRoZXN0KSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBpZihib3R0b20gPCAwKSB7XG4gICAgICBib3R0b20gPSBpXG4gICAgfSBlbHNlIGlmKGN1YmVWZXJ0c1tib3R0b21dWzFdID4gY3ViZVZlcnRzW2ldWzFdKSB7XG4gICAgICBib3R0b20gPSBpXG4gICAgfVxuICB9XG5cbiAgLy9GaW5kIGxlZnQvcmlnaHQgbmVpZ2hib3JzIG9mIGJvdHRvbSB2ZXJ0ZXhcbiAgdmFyIGxlZnQgPSAtMVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICB2YXIgaWR4ID0gYm90dG9tIF4gKDE8PGkpXG4gICAgaWYoaWR4ID09PSBjbG9zZXN0IHx8IGlkeCA9PT0gZmFydGhlc3QpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGlmKGxlZnQgPCAwKSB7XG4gICAgICBsZWZ0ID0gaWR4XG4gICAgfVxuICAgIHZhciB2ID0gY3ViZVZlcnRzW2lkeF1cbiAgICBpZih2WzBdIDwgY3ViZVZlcnRzW2xlZnRdWzBdKSB7XG4gICAgICBsZWZ0ID0gaWR4XG4gICAgfVxuICB9XG4gIHZhciByaWdodCA9IC0xXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHZhciBpZHggPSBib3R0b20gXiAoMTw8aSlcbiAgICBpZihpZHggPT09IGNsb3Nlc3QgfHwgaWR4ID09PSBmYXJ0aGVzdCB8fCBpZHggPT09IGxlZnQpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGlmKHJpZ2h0IDwgMCkge1xuICAgICAgcmlnaHQgPSBpZHhcbiAgICB9XG4gICAgdmFyIHYgPSBjdWJlVmVydHNbaWR4XVxuICAgIGlmKHZbMF0gPiBjdWJlVmVydHNbcmlnaHRdWzBdKSB7XG4gICAgICByaWdodCA9IGlkeFxuICAgIH1cbiAgfVxuXG4gIC8vRGV0ZXJtaW5lIGVkZ2UgYXhpcyBjb29yZGluYXRlc1xuICB2YXIgY3ViZUVkZ2VzID0gQ1VCRV9FREdFU1xuICBjdWJlRWRnZXNbMF0gPSBjdWJlRWRnZXNbMV0gPSBjdWJlRWRnZXNbMl0gPSAwXG4gIGN1YmVFZGdlc1tiaXRzLmxvZzIobGVmdF5ib3R0b20pXSA9IGJvdHRvbSZsZWZ0XG4gIGN1YmVFZGdlc1tiaXRzLmxvZzIoYm90dG9tXnJpZ2h0KV0gPSBib3R0b20mcmlnaHRcbiAgdmFyIHRvcCA9IHJpZ2h0IF4gN1xuICBpZih0b3AgPT09IGNsb3Nlc3QgfHwgdG9wID09PSBmYXJ0aGVzdCkge1xuICAgIHRvcCA9IGxlZnQgXiA3XG4gICAgY3ViZUVkZ2VzW2JpdHMubG9nMihyaWdodF50b3ApXSA9IHRvcCZyaWdodFxuICB9IGVsc2Uge1xuICAgIGN1YmVFZGdlc1tiaXRzLmxvZzIobGVmdF50b3ApXSA9IHRvcCZsZWZ0XG4gIH1cblxuICAvL0RldGVybWluZSB2aXNpYmxlIGZhY2VzXG4gIHZhciBheGlzID0gQ1VCRV9BWElTXG4gIHZhciBjdXRDb3JuZXIgPSBjbG9zZXN0XG4gIGZvcih2YXIgZD0wOyBkPDM7ICsrZCkge1xuICAgIGlmKGN1dENvcm5lciAmICgxPDxkKSkge1xuICAgICAgYXhpc1tkXSA9IC0xXG4gICAgfSBlbHNlIHtcbiAgICAgIGF4aXNbZF0gPSAxXG4gICAgfVxuICB9XG5cbiAgLy9SZXR1cm4gcmVzdWx0XG4gIHJldHVybiBDVUJFX1JFU1VMVFxufVxufSx7XCJiaXQtdHdpZGRsZVwiOjkyLFwiZ2wtbWF0NC9tdWx0aXBseVwiOjI2NyxcInJvYnVzdC1vcmllbnRhdGlvblwiOjUxMCxcInNwbGl0LXBvbHlnb25cIjo1Mjd9XSwyMzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzICAgID0gY3JlYXRlTGluZXNcblxudmFyIGNyZWF0ZUJ1ZmZlciAgPSBfZGVyZXFfKCdnbC1idWZmZXInKVxudmFyIGNyZWF0ZVZBTyAgICAgPSBfZGVyZXFfKCdnbC12YW8nKVxudmFyIGNyZWF0ZVNoYWRlciAgPSBfZGVyZXFfKCcuL3NoYWRlcnMnKS5saW5lXG5cbnZhciBNQUpPUl9BWElTID0gWzAsMCwwXVxudmFyIE1JTk9SX0FYSVMgPSBbMCwwLDBdXG52YXIgU0NSRUVOX0FYSVMgPSBbMCwwLDBdXG52YXIgT0ZGU0VUX1ZFQyA9IFswLDAsMF1cbnZhciBTSEFQRSA9IFsxLDFdXG5cbmZ1bmN0aW9uIHplcm9WZWMoYSkge1xuICBhWzBdID0gYVsxXSA9IGFbMl0gPSAwXG4gIHJldHVybiBhXG59XG5cbmZ1bmN0aW9uIGNvcHlWZWMoYSxiKSB7XG4gIGFbMF0gPSBiWzBdXG4gIGFbMV0gPSBiWzFdXG4gIGFbMl0gPSBiWzJdXG4gIHJldHVybiBhXG59XG5cbmZ1bmN0aW9uIExpbmVzKGdsLCB2ZXJ0QnVmZmVyLCB2YW8sIHNoYWRlciwgdGlja0NvdW50LCB0aWNrT2Zmc2V0LCBncmlkQ291bnQsIGdyaWRPZmZzZXQpIHtcbiAgdGhpcy5nbCAgICAgICAgID0gZ2xcbiAgdGhpcy52ZXJ0QnVmZmVyID0gdmVydEJ1ZmZlclxuICB0aGlzLnZhbyAgICAgICAgPSB2YW9cbiAgdGhpcy5zaGFkZXIgICAgID0gc2hhZGVyXG4gIHRoaXMudGlja0NvdW50ICA9IHRpY2tDb3VudFxuICB0aGlzLnRpY2tPZmZzZXQgPSB0aWNrT2Zmc2V0XG4gIHRoaXMuZ3JpZENvdW50ICA9IGdyaWRDb3VudFxuICB0aGlzLmdyaWRPZmZzZXQgPSBncmlkT2Zmc2V0XG59XG5cbnZhciBwcm90byA9IExpbmVzLnByb3RvdHlwZVxuXG5wcm90by5iaW5kID0gZnVuY3Rpb24obW9kZWwsIHZpZXcsIHByb2plY3Rpb24pIHtcbiAgdGhpcy5zaGFkZXIuYmluZCgpXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm1vZGVsID0gbW9kZWxcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMudmlldyA9IHZpZXdcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMucHJvamVjdGlvbiA9IHByb2plY3Rpb25cblxuICBTSEFQRVswXSA9IHRoaXMuZ2wuZHJhd2luZ0J1ZmZlcldpZHRoXG4gIFNIQVBFWzFdID0gdGhpcy5nbC5kcmF3aW5nQnVmZmVySGVpZ2h0XG5cbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuc2NyZWVuU2hhcGUgPSBTSEFQRVxuICB0aGlzLnZhby5iaW5kKClcbn1cblxucHJvdG8udW5iaW5kID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMudmFvLnVuYmluZCgpXG59XG5cbnByb3RvLmRyYXdBeGlzTGluZSA9IGZ1bmN0aW9uKGosIGJvdW5kcywgb2Zmc2V0LCBjb2xvciwgbGluZVdpZHRoKSB7XG4gIHZhciBtaW5vckF4aXMgPSB6ZXJvVmVjKE1JTk9SX0FYSVMpXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm1ham9yQXhpcyA9IE1JTk9SX0FYSVNcblxuICBtaW5vckF4aXNbal0gPSBib3VuZHNbMV1bal0gLSBib3VuZHNbMF1bal1cbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMubWlub3JBeGlzID0gbWlub3JBeGlzXG5cbiAgdmFyIG5vZmZzZXQgPSBjb3B5VmVjKE9GRlNFVF9WRUMsIG9mZnNldClcbiAgbm9mZnNldFtqXSArPSBib3VuZHNbMF1bal1cbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMub2Zmc2V0ID0gbm9mZnNldFxuXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLmxpbmVXaWR0aCA9IGxpbmVXaWR0aFxuXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLmNvbG9yID0gY29sb3JcblxuICB2YXIgc2NyZWVuQXhpcyA9IHplcm9WZWMoU0NSRUVOX0FYSVMpXG4gIHNjcmVlbkF4aXNbKGorMiklM10gPSAxXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnNjcmVlbkF4aXMgPSBzY3JlZW5BeGlzXG4gIHRoaXMudmFvLmRyYXcodGhpcy5nbC5UUklBTkdMRVMsIDYpXG5cbiAgdmFyIHNjcmVlbkF4aXMgPSB6ZXJvVmVjKFNDUkVFTl9BWElTKVxuICBzY3JlZW5BeGlzWyhqKzEpJTNdID0gMVxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5zY3JlZW5BeGlzID0gc2NyZWVuQXhpc1xuICB0aGlzLnZhby5kcmF3KHRoaXMuZ2wuVFJJQU5HTEVTLCA2KVxufVxuXG5wcm90by5kcmF3QXhpc1RpY2tzID0gZnVuY3Rpb24oaiwgb2Zmc2V0LCBtaW5vckF4aXMsIGNvbG9yLCBsaW5lV2lkdGgpIHtcbiAgaWYoIXRoaXMudGlja0NvdW50W2pdKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICB2YXIgbWFqb3JBeGlzID0gemVyb1ZlYyhNQUpPUl9BWElTKVxuICBtYWpvckF4aXNbal0gID0gMVxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5tYWpvckF4aXMgPSBtYWpvckF4aXNcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMub2Zmc2V0ICAgID0gb2Zmc2V0XG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm1pbm9yQXhpcyA9IG1pbm9yQXhpc1xuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5jb2xvciAgICAgPSBjb2xvclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5saW5lV2lkdGggPSBsaW5lV2lkdGhcblxuICB2YXIgc2NyZWVuQXhpcyA9IHplcm9WZWMoU0NSRUVOX0FYSVMpXG4gIHNjcmVlbkF4aXNbal0gPSAxXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnNjcmVlbkF4aXMgPSBzY3JlZW5BeGlzXG4gIHRoaXMudmFvLmRyYXcodGhpcy5nbC5UUklBTkdMRVMsIHRoaXMudGlja0NvdW50W2pdLCB0aGlzLnRpY2tPZmZzZXRbal0pXG59XG5cblxucHJvdG8uZHJhd0dyaWQgPSBmdW5jdGlvbihpLCBqLCBib3VuZHMsIG9mZnNldCwgY29sb3IsIGxpbmVXaWR0aCkge1xuICBpZighdGhpcy5ncmlkQ291bnRbaV0pIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHZhciBtaW5vckF4aXMgPSB6ZXJvVmVjKE1JTk9SX0FYSVMpXG4gIG1pbm9yQXhpc1tqXSAgPSBib3VuZHNbMV1bal0gLSBib3VuZHNbMF1bal1cbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMubWlub3JBeGlzID0gbWlub3JBeGlzXG5cbiAgdmFyIG5vZmZzZXQgPSBjb3B5VmVjKE9GRlNFVF9WRUMsIG9mZnNldClcbiAgbm9mZnNldFtqXSArPSBib3VuZHNbMF1bal1cbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMub2Zmc2V0ID0gbm9mZnNldFxuXG4gIHZhciBtYWpvckF4aXMgPSB6ZXJvVmVjKE1BSk9SX0FYSVMpXG4gIG1ham9yQXhpc1tpXSAgPSAxXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm1ham9yQXhpcyA9IG1ham9yQXhpc1xuXG4gIHZhciBzY3JlZW5BeGlzID0gemVyb1ZlYyhTQ1JFRU5fQVhJUylcbiAgc2NyZWVuQXhpc1tpXSA9IDFcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuc2NyZWVuQXhpcyA9IHNjcmVlbkF4aXNcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMubGluZVdpZHRoID0gbGluZVdpZHRoXG5cbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuY29sb3IgPSBjb2xvclxuICB0aGlzLnZhby5kcmF3KHRoaXMuZ2wuVFJJQU5HTEVTLCB0aGlzLmdyaWRDb3VudFtpXSwgdGhpcy5ncmlkT2Zmc2V0W2ldKVxufVxuXG5wcm90by5kcmF3WmVybyA9IGZ1bmN0aW9uKGosIGksIGJvdW5kcywgb2Zmc2V0LCBjb2xvciwgbGluZVdpZHRoKSB7XG4gIHZhciBtaW5vckF4aXMgPSB6ZXJvVmVjKE1JTk9SX0FYSVMpXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLm1ham9yQXhpcyA9IG1pbm9yQXhpc1xuXG4gIG1pbm9yQXhpc1tqXSA9IGJvdW5kc1sxXVtqXSAtIGJvdW5kc1swXVtqXVxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5taW5vckF4aXMgPSBtaW5vckF4aXNcblxuICB2YXIgbm9mZnNldCA9IGNvcHlWZWMoT0ZGU0VUX1ZFQywgb2Zmc2V0KVxuICBub2Zmc2V0W2pdICs9IGJvdW5kc1swXVtqXVxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5vZmZzZXQgPSBub2Zmc2V0XG5cbiAgdmFyIHNjcmVlbkF4aXMgPSB6ZXJvVmVjKFNDUkVFTl9BWElTKVxuICBzY3JlZW5BeGlzW2ldID0gMVxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5zY3JlZW5BeGlzID0gc2NyZWVuQXhpc1xuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5saW5lV2lkdGggPSBsaW5lV2lkdGhcblxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5jb2xvciA9IGNvbG9yXG4gIHRoaXMudmFvLmRyYXcodGhpcy5nbC5UUklBTkdMRVMsIDYpXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy52YW8uZGlzcG9zZSgpXG4gIHRoaXMudmVydEJ1ZmZlci5kaXNwb3NlKClcbiAgdGhpcy5zaGFkZXIuZGlzcG9zZSgpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUxpbmVzKGdsLCBib3VuZHMsIHRpY2tzKSB7XG4gIHZhciB2ZXJ0aWNlcyAgICA9IFtdXG4gIHZhciB0aWNrT2Zmc2V0ICA9IFswLDAsMF1cbiAgdmFyIHRpY2tDb3VudCAgID0gWzAsMCwwXVxuXG4gIC8vQ3JlYXRlIGdyaWQgbGluZXMgZm9yIGVhY2ggYXhpcy9kaXJlY3Rpb25cbiAgdmFyIGdyaWRPZmZzZXQgPSBbMCwwLDBdXG4gIHZhciBncmlkQ291bnQgID0gWzAsMCwwXVxuXG4gIC8vQWRkIHplcm8gbGluZVxuICB2ZXJ0aWNlcy5wdXNoKFxuICAgIDAsMCwxLCAgIDAsMSwxLCAgIDAsMCwtMSxcbiAgICAwLDAsLTEsICAwLDEsMSwgICAwLDEsLTEpXG5cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgLy9BeGlzIHRpY2sgbWFya3NcbiAgICB2YXIgc3RhcnQgPSAoKHZlcnRpY2VzLmxlbmd0aCAvIDMpfDApXG4gICAgZm9yKHZhciBqPTA7IGo8dGlja3NbaV0ubGVuZ3RoOyArK2opIHtcbiAgICAgIHZhciB4ID0gK3RpY2tzW2ldW2pdLnhcbiAgICAgIHZlcnRpY2VzLnB1c2goXG4gICAgICAgIHgsMCwxLCAgIHgsMSwxLCAgIHgsMCwtMSxcbiAgICAgICAgeCwwLC0xLCAgeCwxLDEsICAgeCwxLC0xKVxuICAgIH1cbiAgICB2YXIgZW5kID0gKCh2ZXJ0aWNlcy5sZW5ndGggLyAzKXwwKVxuICAgIHRpY2tPZmZzZXRbaV0gPSBzdGFydFxuICAgIHRpY2tDb3VudFtpXSAgPSBlbmQgLSBzdGFydFxuXG4gICAgLy9HcmlkIGxpbmVzXG4gICAgdmFyIHN0YXJ0ID0gKCh2ZXJ0aWNlcy5sZW5ndGggLyAzKXwwKVxuICAgIGZvcih2YXIgaz0wOyBrPHRpY2tzW2ldLmxlbmd0aDsgKytrKSB7XG4gICAgICB2YXIgeCA9ICt0aWNrc1tpXVtrXS54XG4gICAgICB2ZXJ0aWNlcy5wdXNoKFxuICAgICAgICB4LDAsMSwgICB4LDEsMSwgICB4LDAsLTEsXG4gICAgICAgIHgsMCwtMSwgIHgsMSwxLCAgIHgsMSwtMSlcbiAgICB9XG4gICAgdmFyIGVuZCA9ICgodmVydGljZXMubGVuZ3RoIC8gMyl8MClcbiAgICBncmlkT2Zmc2V0W2ldID0gc3RhcnRcbiAgICBncmlkQ291bnRbaV0gID0gZW5kIC0gc3RhcnRcbiAgfVxuXG4gIC8vQ3JlYXRlIGN1YmUgVkFPXG4gIHZhciB2ZXJ0QnVmID0gY3JlYXRlQnVmZmVyKGdsLCBuZXcgRmxvYXQzMkFycmF5KHZlcnRpY2VzKSlcbiAgdmFyIHZhbyA9IGNyZWF0ZVZBTyhnbCwgW1xuICAgIHsgXCJidWZmZXJcIjogdmVydEJ1ZixcbiAgICAgIFwidHlwZVwiOiBnbC5GTE9BVCxcbiAgICAgIFwic2l6ZVwiOiAzLFxuICAgICAgXCJzdHJpZGVcIjogMCxcbiAgICAgIFwib2Zmc2V0XCI6IDBcbiAgICB9XG4gIF0pXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICByZXR1cm4gbmV3IExpbmVzKGdsLCB2ZXJ0QnVmLCB2YW8sIHNoYWRlciwgdGlja0NvdW50LCB0aWNrT2Zmc2V0LCBncmlkQ291bnQsIGdyaWRPZmZzZXQpXG59XG5cbn0se1wiLi9zaGFkZXJzXCI6MjM3LFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtdmFvXCI6MzI3fV0sMjM3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgZ2xzbGlmeSA9IF9kZXJlcV8oJ2dsc2xpZnknKVxudmFyIGNyZWF0ZVNoYWRlciA9IF9kZXJlcV8oJ2dsLXNoYWRlcicpXG5cbnZhciBsaW5lVmVydCA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMyBvZmZzZXQsIG1ham9yQXhpcywgbWlub3JBeGlzLCBzY3JlZW5BeGlzO1xcbnVuaWZvcm0gZmxvYXQgbGluZVdpZHRoO1xcbnVuaWZvcm0gdmVjMiBzY3JlZW5TaGFwZTtcXG5cXG52ZWMzIHByb2plY3QodmVjMyBwKSB7XFxuICB2ZWM0IHBwID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQocCwgMS4wKTtcXG4gIHJldHVybiBwcC54eXogLyBtYXgocHAudywgMC4wMDAxKTtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMyBtYWpvciA9IHBvc2l0aW9uLnggKiBtYWpvckF4aXM7XFxuICB2ZWMzIG1pbm9yID0gcG9zaXRpb24ueSAqIG1pbm9yQXhpcztcXG5cXG4gIHZlYzMgdlBvc2l0aW9uID0gbWFqb3IgKyBtaW5vciArIG9mZnNldDtcXG4gIHZlYzMgcFBvc2l0aW9uID0gcHJvamVjdCh2UG9zaXRpb24pO1xcbiAgdmVjMyBvZmZzZXQgPSBwcm9qZWN0KHZQb3NpdGlvbiArIHNjcmVlbkF4aXMgKiBwb3NpdGlvbi56KTtcXG5cXG4gIHZlYzIgc2NyZWVuID0gbm9ybWFsaXplKChvZmZzZXQgLSBwUG9zaXRpb24pLnh5ICogc2NyZWVuU2hhcGUpIC8gc2NyZWVuU2hhcGU7XFxuXFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQocFBvc2l0aW9uICsgdmVjMygwLjUgKiBzY3JlZW4gKiBsaW5lV2lkdGgsIDApLCAxLjApO1xcbn1cXG5cIl0pXG52YXIgbGluZUZyYWcgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnVuaWZvcm0gdmVjNCBjb2xvcjtcXG52b2lkIG1haW4oKSB7XFxuICBnbF9GcmFnQ29sb3IgPSBjb2xvcjtcXG59XCJdKVxuZXhwb3J0cy5saW5lID0gZnVuY3Rpb24oZ2wpIHtcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgbGluZVZlcnQsIGxpbmVGcmFnLCBudWxsLCBbXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ31cbiAgXSlcbn1cblxudmFyIHRleHRWZXJ0ID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbjtcXG5cXG51bmlmb3JtIG1hdDQgbW9kZWwsIHZpZXcsIHByb2plY3Rpb247XFxudW5pZm9ybSB2ZWMzIG9mZnNldCwgYXhpcywgYWxpZ25EaXIsIGFsaWduT3B0O1xcbnVuaWZvcm0gZmxvYXQgc2NhbGUsIGFuZ2xlLCBwaXhlbFNjYWxlO1xcbnVuaWZvcm0gdmVjMiByZXNvbHV0aW9uO1xcblxcbnZlYzMgcHJvamVjdCh2ZWMzIHApIHtcXG4gIHZlYzQgcHAgPSBwcm9qZWN0aW9uICogdmlldyAqIG1vZGVsICogdmVjNChwLCAxLjApO1xcbiAgcmV0dXJuIHBwLnh5eiAvIG1heChwcC53LCAwLjAwMDEpO1xcbn1cXG5cXG5mbG9hdCBjb21wdXRlVmlld0FuZ2xlKHZlYzMgYSwgdmVjMyBiKSB7XFxuICB2ZWMzIEEgPSBwcm9qZWN0KGEpO1xcbiAgdmVjMyBCID0gcHJvamVjdChiKTtcXG5cXG4gIHJldHVybiBhdGFuKFxcbiAgICAoQi55IC0gQS55KSAqIHJlc29sdXRpb24ueSxcXG4gICAgKEIueCAtIEEueCkgKiByZXNvbHV0aW9uLnhcXG4gICk7XFxufVxcblxcbmNvbnN0IGZsb2F0IFBJID0gMy4xNDE1OTI7XFxuY29uc3QgZmxvYXQgVFdPX1BJID0gMi4wICogUEk7XFxuY29uc3QgZmxvYXQgSEFMRl9QSSA9IDAuNSAqIFBJO1xcbmNvbnN0IGZsb2F0IE9ORV9BTkRfSEFMRl9QSSA9IDEuNSAqIFBJO1xcblxcbmludCBvcHRpb24gPSBpbnQoZmxvb3IoYWxpZ25PcHQueCArIDAuMDAxKSk7XFxuZmxvYXQgaHZfcmF0aW8gPSAgICAgICBhbGlnbk9wdC55O1xcbmJvb2wgZW5hYmxlQWxpZ24gPSAgICAoYWxpZ25PcHQueiAhPSAwLjApO1xcblxcbmZsb2F0IG1vZF9hbmdsZShmbG9hdCBhKSB7XFxuICByZXR1cm4gbW9kKGEsIFBJKTtcXG59XFxuXFxuZmxvYXQgcG9zaXRpdmVfYW5nbGUoZmxvYXQgYSkge1xcbiAgcmV0dXJuIG1vZF9hbmdsZSgoYSA8IDAuMCkgP1xcbiAgICBhICsgVFdPX1BJIDpcXG4gICAgYVxcbiAgKTtcXG59XFxuXFxuZmxvYXQgbG9va191cHdhcmRzKGZsb2F0IGEpIHtcXG4gIGZsb2F0IGIgPSBwb3NpdGl2ZV9hbmdsZShhKTtcXG4gIHJldHVybiAoKGIgPiBIQUxGX1BJKSAmJiAoYiA8PSBPTkVfQU5EX0hBTEZfUEkpKSA/XFxuICAgIGIgLSBQSSA6XFxuICAgIGI7XFxufVxcblxcbmZsb2F0IGxvb2tfaG9yaXpvbnRhbF9vcl92ZXJ0aWNhbChmbG9hdCBhLCBmbG9hdCByYXRpbykge1xcbiAgLy8gcmF0aW8gY29udHJvbHMgdGhlIHJhdGlvIGJldHdlZW4gYmVpbmcgaG9yaXpvbnRhbCB0byAodmVydGljYWwgKyBob3Jpem9udGFsKVxcbiAgLy8gaWYgcmF0aW8gaXMgc2V0IHRvIDAuNSB0aGVuIGl0IGlzIDUwJSwgNTAlLlxcbiAgLy8gd2hlbiB1c2luZyBhIGhpZ2hlciByYXRpbyBlLmcuIDAuNzUgdGhlIHJlc3VsdCB3b3VsZFxcbiAgLy8gbGlrZWx5IGJlIG1vcmUgaG9yaXpvbnRhbCB0aGFuIHZlcnRpY2FsLlxcblxcbiAgZmxvYXQgYiA9IHBvc2l0aXZlX2FuZ2xlKGEpO1xcblxcbiAgcmV0dXJuXFxuICAgIChiIDwgKCAgICAgIHJhdGlvKSAqIEhBTEZfUEkpID8gMC4wIDpcXG4gICAgKGIgPCAoMi4wIC0gcmF0aW8pICogSEFMRl9QSSkgPyAtSEFMRl9QSSA6XFxuICAgIChiIDwgKDIuMCArIHJhdGlvKSAqIEhBTEZfUEkpID8gMC4wIDpcXG4gICAgKGIgPCAoNC4wIC0gcmF0aW8pICogSEFMRl9QSSkgPyBIQUxGX1BJIDpcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLjA7XFxufVxcblxcbmZsb2F0IHJvdW5kVG8oZmxvYXQgYSwgZmxvYXQgYikge1xcbiAgcmV0dXJuIGZsb2F0KGIgKiBmbG9vcigoYSArIDAuNSAqIGIpIC8gYikpO1xcbn1cXG5cXG5mbG9hdCBsb29rX3JvdW5kX25fZGlyZWN0aW9ucyhmbG9hdCBhLCBpbnQgbikge1xcbiAgZmxvYXQgYiA9IHBvc2l0aXZlX2FuZ2xlKGEpO1xcbiAgZmxvYXQgZGl2ID0gVFdPX1BJIC8gZmxvYXQobik7XFxuICBmbG9hdCBjID0gcm91bmRUbyhiLCBkaXYpO1xcbiAgcmV0dXJuIGxvb2tfdXB3YXJkcyhjKTtcXG59XFxuXFxuZmxvYXQgYXBwbHlBbGlnbk9wdGlvbihmbG9hdCByYXdBbmdsZSwgZmxvYXQgZGVsdGEpIHtcXG4gIHJldHVyblxcbiAgICAob3B0aW9uID4gIDIpID8gbG9va19yb3VuZF9uX2RpcmVjdGlvbnMocmF3QW5nbGUgKyBkZWx0YSwgb3B0aW9uKSA6ICAgICAgIC8vIG9wdGlvbiAzLW46IHJvdW5kIHRvIG4gZGlyZWN0aW9uc1xcbiAgICAob3B0aW9uID09IDIpID8gbG9va19ob3Jpem9udGFsX29yX3ZlcnRpY2FsKHJhd0FuZ2xlICsgZGVsdGEsIGh2X3JhdGlvKSA6IC8vIGhvcml6b250YWwgb3IgdmVydGljYWxcXG4gICAgKG9wdGlvbiA9PSAxKSA/IHJhd0FuZ2xlICsgZGVsdGEgOiAgICAgICAvLyB1c2UgZnJlZSBhbmdsZSwgYW5kIGZsaXAgdG8gYWxpZ24gd2l0aCBvbmUgZGlyZWN0aW9uIG9mIHRoZSBheGlzXFxuICAgIChvcHRpb24gPT0gMCkgPyBsb29rX3Vwd2FyZHMocmF3QW5nbGUpIDogLy8gdXNlIGZyZWUgYW5nbGUsIGFuZCBzdGF5IHVwd2FyZHNcXG4gICAgKG9wdGlvbiA9PS0xKSA/IDAuMCA6ICAgICAgICAgICAgICAgICAgICAvLyB1c2VmdWwgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHksIGFsbCB0ZXh0cyByZW1haW5zIGhvcml6b250YWxcXG4gICAgICAgICAgICAgICAgICAgIHJhd0FuZ2xlOyAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgcmV0dXJuIGJhY2sgcmF3IGlucHV0IGFuZ2xlXFxufVxcblxcbmJvb2wgaXNBeGlzVGl0bGUgPSAoYXhpcy54ID09IDAuMCkgJiZcXG4gICAgICAgICAgICAgICAgICAgKGF4aXMueSA9PSAwLjApICYmXFxuICAgICAgICAgICAgICAgICAgIChheGlzLnogPT0gMC4wKTtcXG5cXG52b2lkIG1haW4oKSB7XFxuICAvL0NvbXB1dGUgd29ybGQgb2Zmc2V0XFxuICBmbG9hdCBheGlzRGlzdGFuY2UgPSBwb3NpdGlvbi56O1xcbiAgdmVjMyBkYXRhUG9zaXRpb24gPSBheGlzRGlzdGFuY2UgKiBheGlzICsgb2Zmc2V0O1xcblxcbiAgZmxvYXQgYmV0YSA9IGFuZ2xlOyAvLyBpLmUuIHVzZXIgZGVmaW5lZCBhdHRyaWJ1dGVzIGZvciBlYWNoIHRpY2tcXG5cXG4gIGZsb2F0IGF4aXNBbmdsZTtcXG4gIGZsb2F0IGNsaXBBbmdsZTtcXG4gIGZsb2F0IGZsaXA7XFxuXFxuICBpZiAoZW5hYmxlQWxpZ24pIHtcXG4gICAgYXhpc0FuZ2xlID0gKGlzQXhpc1RpdGxlKSA/IEhBTEZfUEkgOlxcbiAgICAgICAgICAgICAgICAgICAgICBjb21wdXRlVmlld0FuZ2xlKGRhdGFQb3NpdGlvbiwgZGF0YVBvc2l0aW9uICsgYXhpcyk7XFxuICAgIGNsaXBBbmdsZSA9IGNvbXB1dGVWaWV3QW5nbGUoZGF0YVBvc2l0aW9uLCBkYXRhUG9zaXRpb24gKyBhbGlnbkRpcik7XFxuXFxuICAgIGF4aXNBbmdsZSArPSAoc2luKGF4aXNBbmdsZSkgPCAwLjApID8gUEkgOiAwLjA7XFxuICAgIGNsaXBBbmdsZSArPSAoc2luKGNsaXBBbmdsZSkgPCAwLjApID8gUEkgOiAwLjA7XFxuXFxuICAgIGZsaXAgPSAoZG90KHZlYzIoY29zKGF4aXNBbmdsZSksIHNpbihheGlzQW5nbGUpKSxcXG4gICAgICAgICAgICAgICAgdmVjMihzaW4oY2xpcEFuZ2xlKSwtY29zKGNsaXBBbmdsZSkpKSA+IDAuMCkgPyAxLjAgOiAwLjA7XFxuXFxuICAgIGJldGEgKz0gYXBwbHlBbGlnbk9wdGlvbihjbGlwQW5nbGUsIGZsaXAgKiBQSSk7XFxuICB9XFxuXFxuICAvL0NvbXB1dGUgcGxhbmUgb2Zmc2V0XFxuICB2ZWMyIHBsYW5lQ29vcmQgPSBwb3NpdGlvbi54eSAqIHBpeGVsU2NhbGU7XFxuXFxuICBtYXQyIHBsYW5lWGZvcm0gPSBzY2FsZSAqIG1hdDIoXFxuICAgICBjb3MoYmV0YSksIHNpbihiZXRhKSxcXG4gICAgLXNpbihiZXRhKSwgY29zKGJldGEpXFxuICApO1xcblxcbiAgdmVjMiB2aWV3T2Zmc2V0ID0gMi4wICogcGxhbmVYZm9ybSAqIHBsYW5lQ29vcmQgLyByZXNvbHV0aW9uO1xcblxcbiAgLy9Db21wdXRlIGNsaXAgcG9zaXRpb25cXG4gIHZlYzMgY2xpcFBvc2l0aW9uID0gcHJvamVjdChkYXRhUG9zaXRpb24pO1xcblxcbiAgLy9BcHBseSB0ZXh0IG9mZnNldCBpbiBjbGlwIGNvb3JkaW5hdGVzXFxuICBjbGlwUG9zaXRpb24gKz0gdmVjMyh2aWV3T2Zmc2V0LCAwLjApO1xcblxcbiAgLy9Eb25lXFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQoY2xpcFBvc2l0aW9uLCAxLjApO1xcbn1cIl0pXG52YXIgdGV4dEZyYWcgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnVuaWZvcm0gdmVjNCBjb2xvcjtcXG52b2lkIG1haW4oKSB7XFxuICBnbF9GcmFnQ29sb3IgPSBjb2xvcjtcXG59XCJdKVxuZXhwb3J0cy50ZXh0ID0gZnVuY3Rpb24oZ2wpIHtcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgdGV4dFZlcnQsIHRleHRGcmFnLCBudWxsLCBbXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ31cbiAgXSlcbn1cblxudmFyIGJnVmVydCA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzMgbm9ybWFsO1xcblxcbnVuaWZvcm0gbWF0NCBtb2RlbCwgdmlldywgcHJvamVjdGlvbjtcXG51bmlmb3JtIHZlYzMgZW5hYmxlO1xcbnVuaWZvcm0gdmVjMyBib3VuZHNbMl07XFxuXFxudmFyeWluZyB2ZWMzIGNvbG9yQ2hhbm5lbDtcXG5cXG52b2lkIG1haW4oKSB7XFxuXFxuICB2ZWMzIHNpZ25BeGlzID0gc2lnbihib3VuZHNbMV0gLSBib3VuZHNbMF0pO1xcblxcbiAgdmVjMyByZWFsTm9ybWFsID0gc2lnbkF4aXMgKiBub3JtYWw7XFxuXFxuICBpZihkb3QocmVhbE5vcm1hbCwgZW5hYmxlKSA+IDAuMCkge1xcbiAgICB2ZWMzIG1pblJhbmdlID0gbWluKGJvdW5kc1swXSwgYm91bmRzWzFdKTtcXG4gICAgdmVjMyBtYXhSYW5nZSA9IG1heChib3VuZHNbMF0sIGJvdW5kc1sxXSk7XFxuICAgIHZlYzMgblBvc2l0aW9uID0gbWl4KG1pblJhbmdlLCBtYXhSYW5nZSwgMC41ICogKHBvc2l0aW9uICsgMS4wKSk7XFxuICAgIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQoblBvc2l0aW9uLCAxLjApO1xcbiAgfSBlbHNlIHtcXG4gICAgZ2xfUG9zaXRpb24gPSB2ZWM0KDAsMCwwLDApO1xcbiAgfVxcblxcbiAgY29sb3JDaGFubmVsID0gYWJzKHJlYWxOb3JtYWwpO1xcbn1cIl0pXG52YXIgYmdGcmFnID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG51bmlmb3JtIHZlYzQgY29sb3JzWzNdO1xcblxcbnZhcnlpbmcgdmVjMyBjb2xvckNoYW5uZWw7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZ2xfRnJhZ0NvbG9yID0gY29sb3JDaGFubmVsLnggKiBjb2xvcnNbMF0gK1xcbiAgICAgICAgICAgICAgICAgY29sb3JDaGFubmVsLnkgKiBjb2xvcnNbMV0gK1xcbiAgICAgICAgICAgICAgICAgY29sb3JDaGFubmVsLnogKiBjb2xvcnNbMl07XFxufVwiXSlcbmV4cG9ydHMuYmcgPSBmdW5jdGlvbihnbCkge1xuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCBiZ1ZlcnQsIGJnRnJhZywgbnVsbCwgW1xuICAgIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjMyd9LFxuICAgIHtuYW1lOiAnbm9ybWFsJywgdHlwZTogJ3ZlYzMnfVxuICBdKVxufVxuXG59LHtcImdsLXNoYWRlclwiOjMwMSxcImdsc2xpZnlcIjo0MDl9XSwyMzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuKGZ1bmN0aW9uIChwcm9jZXNzKXtcblwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVGV4dFNwcml0ZXNcblxudmFyIGNyZWF0ZUJ1ZmZlciAgPSBfZGVyZXFfKCdnbC1idWZmZXInKVxudmFyIGNyZWF0ZVZBTyAgICAgPSBfZGVyZXFfKCdnbC12YW8nKVxudmFyIHZlY3Rvcml6ZVRleHQgPSBfZGVyZXFfKCd2ZWN0b3JpemUtdGV4dCcpXG52YXIgY3JlYXRlU2hhZGVyICA9IF9kZXJlcV8oJy4vc2hhZGVycycpLnRleHRcblxudmFyIGdsb2JhbHMgPSB3aW5kb3cgfHwgcHJvY2Vzcy5nbG9iYWwgfHwge31cbnZhciBfX1RFWFRfQ0FDSEUgID0gZ2xvYmFscy5fX1RFWFRfQ0FDSEUgfHwge31cbmdsb2JhbHMuX19URVhUX0NBQ0hFID0ge31cblxuLy9WZXJ0ZXggYnVmZmVyIGZvcm1hdCBmb3IgdGV4dCBpczpcbi8vXG4vLy8gW3gseSx6XSA9IFNwYXRpYWwgY29vcmRpbmF0ZVxuLy9cblxudmFyIFZFUlRFWF9TSVpFID0gM1xuXG5mdW5jdGlvbiBUZXh0U3ByaXRlcyhcbiAgZ2wsXG4gIHNoYWRlcixcbiAgYnVmZmVyLFxuICB2YW8pIHtcbiAgdGhpcy5nbCAgICAgICAgICAgPSBnbFxuICB0aGlzLnNoYWRlciAgICAgICA9IHNoYWRlclxuICB0aGlzLmJ1ZmZlciAgICAgICA9IGJ1ZmZlclxuICB0aGlzLnZhbyAgICAgICAgICA9IHZhb1xuICB0aGlzLnRpY2tPZmZzZXQgICA9XG4gIHRoaXMudGlja0NvdW50ICAgID1cbiAgdGhpcy5sYWJlbE9mZnNldCAgPVxuICB0aGlzLmxhYmVsQ291bnQgICA9IG51bGxcbn1cblxudmFyIHByb3RvID0gVGV4dFNwcml0ZXMucHJvdG90eXBlXG5cbi8vQmluZCB0ZXh0dXJlcyBmb3IgcmVuZGVyaW5nXG52YXIgU0hBUEUgPSBbMCwwXVxucHJvdG8uYmluZCA9IGZ1bmN0aW9uKG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uLCBwaXhlbFNjYWxlKSB7XG4gIHRoaXMudmFvLmJpbmQoKVxuICB0aGlzLnNoYWRlci5iaW5kKClcbiAgdmFyIHVuaWZvcm1zID0gdGhpcy5zaGFkZXIudW5pZm9ybXNcbiAgdW5pZm9ybXMubW9kZWwgPSBtb2RlbFxuICB1bmlmb3Jtcy52aWV3ID0gdmlld1xuICB1bmlmb3Jtcy5wcm9qZWN0aW9uID0gcHJvamVjdGlvblxuICB1bmlmb3Jtcy5waXhlbFNjYWxlID0gcGl4ZWxTY2FsZVxuICBTSEFQRVswXSA9IHRoaXMuZ2wuZHJhd2luZ0J1ZmZlcldpZHRoXG4gIFNIQVBFWzFdID0gdGhpcy5nbC5kcmF3aW5nQnVmZmVySGVpZ2h0XG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnJlc29sdXRpb24gPSBTSEFQRVxufVxuXG5wcm90by51bmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy52YW8udW5iaW5kKClcbn1cblxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24oYm91bmRzLCBsYWJlbHMsIGxhYmVsRm9udCwgdGlja3MsIHRpY2tGb250KSB7XG4gIHZhciBkYXRhID0gW11cblxuICBmdW5jdGlvbiBhZGRJdGVtKHQsIHRleHQsIGZvbnQsIHNpemUsIGxpbmVTcGFjaW5nLCBzdHlsZXRhZ3MpIHtcbiAgICB2YXIgZm9udGNhY2hlID0gX19URVhUX0NBQ0hFW2ZvbnRdXG4gICAgaWYoIWZvbnRjYWNoZSkge1xuICAgICAgZm9udGNhY2hlID0gX19URVhUX0NBQ0hFW2ZvbnRdID0ge31cbiAgICB9XG4gICAgdmFyIG1lc2ggPSBmb250Y2FjaGVbdGV4dF1cbiAgICBpZighbWVzaCkge1xuICAgICAgbWVzaCA9IGZvbnRjYWNoZVt0ZXh0XSA9IHRyeVZlY3Rvcml6ZVRleHQodGV4dCwge1xuICAgICAgICB0cmlhbmdsZXM6IHRydWUsXG4gICAgICAgIGZvbnQ6IGZvbnQsXG4gICAgICAgIHRleHRBbGlnbjogJ2NlbnRlcicsXG4gICAgICAgIHRleHRCYXNlbGluZTogJ21pZGRsZScsXG4gICAgICAgIGxpbmVTcGFjaW5nOiBsaW5lU3BhY2luZyxcbiAgICAgICAgc3R5bGV0YWdzOiBzdHlsZXRhZ3NcbiAgICAgIH0pXG4gICAgfVxuICAgIHZhciBzY2FsZSA9IChzaXplIHx8IDEyKSAvIDEyXG4gICAgdmFyIHBvc2l0aW9ucyA9IG1lc2gucG9zaXRpb25zXG4gICAgdmFyIGNlbGxzID0gbWVzaC5jZWxsc1xuICAgIGZvcih2YXIgaT0wLCBuYz1jZWxscy5sZW5ndGg7IGk8bmM7ICsraSkge1xuICAgICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgICAgZm9yKHZhciBqPTI7IGo+PTA7IC0taikge1xuICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1tjW2pdXVxuICAgICAgICBkYXRhLnB1c2goc2NhbGUqcFswXSwgLXNjYWxlKnBbMV0sIHQpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9HZW5lcmF0ZSBzcHJpdGVzIGZvciBhbGwgMyBheGVzLCBzdG9yZSBkYXRhIGluIHRleHR1cmUgYXRsYXNlc1xuICB2YXIgdGlja09mZnNldCAgPSBbMCwwLDBdXG4gIHZhciB0aWNrQ291bnQgICA9IFswLDAsMF1cbiAgdmFyIGxhYmVsT2Zmc2V0ID0gWzAsMCwwXVxuICB2YXIgbGFiZWxDb3VudCAgPSBbMCwwLDBdXG4gIHZhciBsaW5lU3BhY2luZyA9IDEuMjVcbiAgdmFyIHN0eWxldGFncyA9IHtcbiAgICBicmVha2xpbmVzOnRydWUsXG4gICAgYm9sZHM6IHRydWUsXG4gICAgaXRhbGljczogdHJ1ZSxcbiAgICBzdWJzY3JpcHRzOnRydWUsXG4gICAgc3VwZXJzY3JpcHRzOnRydWVcbiAgfVxuICBmb3IodmFyIGQ9MDsgZDwzOyArK2QpIHtcblxuICAgIC8vR2VuZXJhdGUgbGFiZWxcbiAgICBsYWJlbE9mZnNldFtkXSA9IChkYXRhLmxlbmd0aC9WRVJURVhfU0laRSl8MFxuICAgIGFkZEl0ZW0oXG4gICAgICAwLjUqKGJvdW5kc1swXVtkXStib3VuZHNbMV1bZF0pLFxuICAgICAgbGFiZWxzW2RdLFxuICAgICAgbGFiZWxGb250W2RdLFxuICAgICAgMTIsIC8vIGxhYmVsRm9udFNpemVcbiAgICAgIGxpbmVTcGFjaW5nLFxuICAgICAgc3R5bGV0YWdzXG4gICAgKVxuICAgIGxhYmVsQ291bnRbZF0gPSAoKGRhdGEubGVuZ3RoL1ZFUlRFWF9TSVpFKXwwKSAtIGxhYmVsT2Zmc2V0W2RdXG5cbiAgICAvL0dlbmVyYXRlIHNwcml0ZXMgZm9yIHRpY2sgbWFya3NcbiAgICB0aWNrT2Zmc2V0W2RdID0gKGRhdGEubGVuZ3RoL1ZFUlRFWF9TSVpFKXwwXG4gICAgZm9yKHZhciBpPTA7IGk8dGlja3NbZF0ubGVuZ3RoOyArK2kpIHtcbiAgICAgIGlmKCF0aWNrc1tkXVtpXS50ZXh0KSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBhZGRJdGVtKFxuICAgICAgICB0aWNrc1tkXVtpXS54LFxuICAgICAgICB0aWNrc1tkXVtpXS50ZXh0LFxuICAgICAgICB0aWNrc1tkXVtpXS5mb250IHx8IHRpY2tGb250LFxuICAgICAgICB0aWNrc1tkXVtpXS5mb250U2l6ZSB8fCAxMixcbiAgICAgICAgbGluZVNwYWNpbmcsXG4gICAgICAgIHN0eWxldGFnc1xuICAgICAgKVxuICAgIH1cbiAgICB0aWNrQ291bnRbZF0gPSAoKGRhdGEubGVuZ3RoL1ZFUlRFWF9TSVpFKXwwKSAtIHRpY2tPZmZzZXRbZF1cbiAgfVxuXG4gIHRoaXMuYnVmZmVyLnVwZGF0ZShkYXRhKVxuICB0aGlzLnRpY2tPZmZzZXQgPSB0aWNrT2Zmc2V0XG4gIHRoaXMudGlja0NvdW50ID0gdGlja0NvdW50XG4gIHRoaXMubGFiZWxPZmZzZXQgPSBsYWJlbE9mZnNldFxuICB0aGlzLmxhYmVsQ291bnQgPSBsYWJlbENvdW50XG59XG5cbi8vRHJhd3MgdGhlIHRpY2sgbWFya3MgZm9yIGFuIGF4aXNcbnByb3RvLmRyYXdUaWNrcyA9IGZ1bmN0aW9uKGQsIHNjYWxlLCBhbmdsZSwgb2Zmc2V0LCBjb2xvciwgYXhpcywgYWxpZ25EaXIsIGFsaWduT3B0KSB7XG4gIGlmKCF0aGlzLnRpY2tDb3VudFtkXSkge1xuICAgIHJldHVyblxuICB9XG5cbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuYXhpcyA9IGF4aXNcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuY29sb3IgPSBjb2xvclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5hbmdsZSA9IGFuZ2xlXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLnNjYWxlID0gc2NhbGVcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMub2Zmc2V0ID0gb2Zmc2V0XG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLmFsaWduRGlyID0gYWxpZ25EaXJcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuYWxpZ25PcHQgPSBhbGlnbk9wdFxuICB0aGlzLnZhby5kcmF3KHRoaXMuZ2wuVFJJQU5HTEVTLCB0aGlzLnRpY2tDb3VudFtkXSwgdGhpcy50aWNrT2Zmc2V0W2RdKVxufVxuXG4vL0RyYXdzIHRoZSB0ZXh0IGxhYmVsIGZvciBhbiBheGlzXG5wcm90by5kcmF3TGFiZWwgPSBmdW5jdGlvbihkLCBzY2FsZSwgYW5nbGUsIG9mZnNldCwgY29sb3IsIGF4aXMsIGFsaWduRGlyLCBhbGlnbk9wdCkge1xuICBpZighdGhpcy5sYWJlbENvdW50W2RdKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5heGlzID0gYXhpc1xuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5jb2xvciA9IGNvbG9yXG4gIHRoaXMuc2hhZGVyLnVuaWZvcm1zLmFuZ2xlID0gYW5nbGVcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuc2NhbGUgPSBzY2FsZVxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5vZmZzZXQgPSBvZmZzZXRcbiAgdGhpcy5zaGFkZXIudW5pZm9ybXMuYWxpZ25EaXIgPSBhbGlnbkRpclxuICB0aGlzLnNoYWRlci51bmlmb3Jtcy5hbGlnbk9wdCA9IGFsaWduT3B0XG4gIHRoaXMudmFvLmRyYXcodGhpcy5nbC5UUklBTkdMRVMsIHRoaXMubGFiZWxDb3VudFtkXSwgdGhpcy5sYWJlbE9mZnNldFtkXSlcbn1cblxuLy9SZWxlYXNlcyBhbGwgcmVzb3VyY2VzIGF0dGFjaGVkIHRvIHRoaXMgb2JqZWN0XG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxuICB0aGlzLnZhby5kaXNwb3NlKClcbiAgdGhpcy5idWZmZXIuZGlzcG9zZSgpXG59XG5cbmZ1bmN0aW9uIHRyeVZlY3Rvcml6ZVRleHQodGV4dCwgb3B0aW9ucykge1xuICB0cnkge1xuICAgIHJldHVybiB2ZWN0b3JpemVUZXh0KHRleHQsIG9wdGlvbnMpXG4gIH0gY2F0Y2goZSkge1xuICAgIGNvbnNvbGUud2FybignZXJyb3IgdmVjdG9yaXppbmcgdGV4dDpcIicgKyB0ZXh0ICsgJ1wiIGVycm9yOicsIGUpXG4gICAgcmV0dXJuIHtcbiAgICAgIGNlbGxzOiBbXSxcbiAgICAgIHBvc2l0aW9uczogW11cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlVGV4dFNwcml0ZXMoXG4gICAgZ2wsXG4gICAgYm91bmRzLFxuICAgIGxhYmVscyxcbiAgICBsYWJlbEZvbnQsXG4gICAgdGlja3MsXG4gICAgdGlja0ZvbnQpIHtcblxuICB2YXIgYnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgdmFvID0gY3JlYXRlVkFPKGdsLCBbXG4gICAgeyBcImJ1ZmZlclwiOiBidWZmZXIsXG4gICAgICBcInNpemVcIjogM1xuICAgIH1cbiAgXSlcblxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsKVxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcblxuICB2YXIgcmVzdWx0ID0gbmV3IFRleHRTcHJpdGVzKFxuICAgIGdsLFxuICAgIHNoYWRlcixcbiAgICBidWZmZXIsXG4gICAgdmFvKVxuXG4gIHJlc3VsdC51cGRhdGUoYm91bmRzLCBsYWJlbHMsIGxhYmVsRm9udCwgdGlja3MsIHRpY2tGb250KVxuXG4gIHJldHVybiByZXN1bHRcbn1cblxufSkuY2FsbCh0aGlzLF9kZXJlcV8oJ19wcm9jZXNzJykpXG59LHtcIi4vc2hhZGVyc1wiOjIzNyxcIl9wcm9jZXNzXCI6NDgyLFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtdmFvXCI6MzI3LFwidmVjdG9yaXplLXRleHRcIjo1NTB9XSwyMzk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbmV4cG9ydHMuY3JlYXRlICAgPSBkZWZhdWx0VGlja3NcbmV4cG9ydHMuZXF1YWwgICAgPSB0aWNrc0VxdWFsXG5cbmZ1bmN0aW9uIHByZXR0eVByaW50KHNwYWNpbmcsIGkpIHtcbiAgdmFyIHN0ZXBTdHIgPSBzcGFjaW5nICsgXCJcIlxuICB2YXIgdSA9IHN0ZXBTdHIuaW5kZXhPZihcIi5cIilcbiAgdmFyIHNpZ0ZpZ3MgPSAwXG4gIGlmKHUgPj0gMCkge1xuICAgIHNpZ0ZpZ3MgPSBzdGVwU3RyLmxlbmd0aCAtIHUgLSAxXG4gIH1cbiAgdmFyIHNoaWZ0ID0gTWF0aC5wb3coMTAsIHNpZ0ZpZ3MpXG4gIHZhciB4ID0gTWF0aC5yb3VuZChzcGFjaW5nICogaSAqIHNoaWZ0KVxuICB2YXIgeHN0ciA9IHggKyBcIlwiXG4gIGlmKHhzdHIuaW5kZXhPZihcImVcIikgPj0gMCkge1xuICAgIHJldHVybiB4c3RyXG4gIH1cbiAgdmFyIHhpID0geCAvIHNoaWZ0LCB4ZiA9IHggJSBzaGlmdFxuICBpZih4IDwgMCkge1xuICAgIHhpID0gLU1hdGguY2VpbCh4aSl8MFxuICAgIHhmID0gKC14Zil8MFxuICB9IGVsc2Uge1xuICAgIHhpID0gTWF0aC5mbG9vcih4aSl8MFxuICAgIHhmID0geGZ8MFxuICB9XG4gIHZhciB4aXMgPSBcIlwiICsgeGkgXG4gIGlmKHggPCAwKSB7XG4gICAgeGlzID0gXCItXCIgKyB4aXNcbiAgfVxuICBpZihzaWdGaWdzKSB7XG4gICAgdmFyIHhzID0gXCJcIiArIHhmXG4gICAgd2hpbGUoeHMubGVuZ3RoIDwgc2lnRmlncykge1xuICAgICAgeHMgPSBcIjBcIiArIHhzXG4gICAgfVxuICAgIHJldHVybiB4aXMgKyBcIi5cIiArIHhzXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHhpc1xuICB9XG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRUaWNrcyhib3VuZHMsIHRpY2tTcGFjaW5nKSB7XG4gIHZhciBhcnJheSA9IFtdXG4gIGZvcih2YXIgZD0wOyBkPDM7ICsrZCkge1xuICAgIHZhciB0aWNrcyA9IFtdXG4gICAgdmFyIG0gPSAwLjUqKGJvdW5kc1swXVtkXStib3VuZHNbMV1bZF0pXG4gICAgZm9yKHZhciB0PTA7IHQqdGlja1NwYWNpbmdbZF08PWJvdW5kc1sxXVtkXTsgKyt0KSB7XG4gICAgICB0aWNrcy5wdXNoKHt4OiB0KnRpY2tTcGFjaW5nW2RdLCB0ZXh0OiBwcmV0dHlQcmludCh0aWNrU3BhY2luZ1tkXSwgdCl9KVxuICAgIH1cbiAgICBmb3IodmFyIHQ9LTE7IHQqdGlja1NwYWNpbmdbZF0+PWJvdW5kc1swXVtkXTsgLS10KSB7XG4gICAgICB0aWNrcy5wdXNoKHt4OiB0KnRpY2tTcGFjaW5nW2RdLCB0ZXh0OiBwcmV0dHlQcmludCh0aWNrU3BhY2luZ1tkXSwgdCl9KVxuICAgIH1cbiAgICBhcnJheS5wdXNoKHRpY2tzKVxuICB9XG4gIHJldHVybiBhcnJheVxufVxuXG5mdW5jdGlvbiB0aWNrc0VxdWFsKHRpY2tzQSwgdGlja3NCKSB7XG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIGlmKHRpY2tzQVtpXS5sZW5ndGggIT09IHRpY2tzQltpXS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICBmb3IodmFyIGo9MDsgajx0aWNrc0FbaV0ubGVuZ3RoOyArK2opIHtcbiAgICAgIHZhciBhID0gdGlja3NBW2ldW2pdXG4gICAgICB2YXIgYiA9IHRpY2tzQltpXVtqXVxuICAgICAgaWYoXG4gICAgICAgIGEueCAhPT0gYi54IHx8XG4gICAgICAgIGEudGV4dCAhPT0gYi50ZXh0IHx8XG4gICAgICAgIGEuZm9udCAhPT0gYi5mb250IHx8XG4gICAgICAgIGEuZm9udENvbG9yICE9PSBiLmZvbnRDb2xvciB8fFxuICAgICAgICBhLmZvbnRTaXplICE9PSBiLmZvbnRTaXplIHx8XG4gICAgICAgIGEuZHggIT09IGIuZHggfHxcbiAgICAgICAgYS5keSAhPT0gYi5keVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxufSx7fV0sMjQwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gYXhlc1Byb3BlcnRpZXNcblxudmFyIGdldFBsYW5lcyAgID0gX2RlcmVxXyhcImV4dHJhY3QtZnJ1c3R1bS1wbGFuZXNcIilcbnZhciBzcGxpdFBvbHkgICA9IF9kZXJlcV8oXCJzcGxpdC1wb2x5Z29uXCIpXG52YXIgY3ViZVBhcmFtcyAgPSBfZGVyZXFfKFwiLi9saWIvY3ViZS5qc1wiKVxudmFyIG00bXVsICAgICAgID0gX2RlcmVxXyhcImdsLW1hdDQvbXVsdGlwbHlcIilcbnZhciBtNHRyYW5zcG9zZSA9IF9kZXJlcV8oXCJnbC1tYXQ0L3RyYW5zcG9zZVwiKVxudmFyIHY0dHJhbnNmb3JtTWF0NCA9IF9kZXJlcV8oXCJnbC12ZWM0L3RyYW5zZm9ybU1hdDRcIilcblxudmFyIGlkZW50aXR5ICAgID0gbmV3IEZsb2F0MzJBcnJheShbXG4gICAgMSwgMCwgMCwgMCxcbiAgICAwLCAxLCAwLCAwLFxuICAgIDAsIDAsIDEsIDAsXG4gICAgMCwgMCwgMCwgMVxuICBdKVxuXG52YXIgbXZwICAgICAgICAgPSBuZXcgRmxvYXQzMkFycmF5KDE2KVxuXG5mdW5jdGlvbiBBeGVzUmFuZ2UzRChsbywgaGksIHBpeGVsc1BlckRhdGFVbml0KSB7XG4gIHRoaXMubG8gPSBsb1xuICB0aGlzLmhpID0gaGlcbiAgdGhpcy5waXhlbHNQZXJEYXRhVW5pdCA9IHBpeGVsc1BlckRhdGFVbml0XG59XG5cbnZhciBTQ1JBVENIX1AgPSBbMCwwLDAsMV1cbnZhciBTQ1JBVENIX1EgPSBbMCwwLDAsMV1cblxuZnVuY3Rpb24gZ3JhZGllbnQocmVzdWx0LCBNLCB2LCB3aWR0aCwgaGVpZ2h0KSB7XG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHZhciBwID0gU0NSQVRDSF9QXG4gICAgdmFyIHEgPSBTQ1JBVENIX1FcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIHFbal0gPSBwW2pdID0gdltqXVxuICAgIH1cbiAgICBxWzNdID0gcFszXSA9IDFcblxuICAgIHFbaV0gKz0gMVxuICAgIHY0dHJhbnNmb3JtTWF0NChxLCBxLCBNKVxuICAgIGlmKHFbM10gPCAwKSB7XG4gICAgICByZXN1bHRbaV0gPSBJbmZpbml0eVxuICAgIH1cblxuICAgIHBbaV0gLT0gMVxuICAgIHY0dHJhbnNmb3JtTWF0NChwLCBwLCBNKVxuICAgIGlmKHBbM10gPCAwKSB7XG4gICAgICByZXN1bHRbaV0gPSBJbmZpbml0eVxuICAgIH1cblxuICAgIHZhciBkeCA9IChwWzBdL3BbM10gLSBxWzBdL3FbM10pICogd2lkdGhcbiAgICB2YXIgZHkgPSAocFsxXS9wWzNdIC0gcVsxXS9xWzNdKSAqIGhlaWdodFxuXG4gICAgcmVzdWx0W2ldID0gMC4yNSAqIE1hdGguc3FydChkeCpkeCArIGR5KmR5KVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxudmFyIFJBTkdFUyA9IFtcbiAgbmV3IEF4ZXNSYW5nZTNEKEluZmluaXR5LCAtSW5maW5pdHksIEluZmluaXR5KSxcbiAgbmV3IEF4ZXNSYW5nZTNEKEluZmluaXR5LCAtSW5maW5pdHksIEluZmluaXR5KSxcbiAgbmV3IEF4ZXNSYW5nZTNEKEluZmluaXR5LCAtSW5maW5pdHksIEluZmluaXR5KVxuXVxuXG52YXIgU0NSQVRDSF9YID0gWzAsMCwwXVxuXG5mdW5jdGlvbiBheGVzUHJvcGVydGllcyhheGVzLCBjYW1lcmEsIHdpZHRoLCBoZWlnaHQsIHBhcmFtcykge1xuICB2YXIgbW9kZWwgICAgICAgPSBjYW1lcmEubW9kZWwgfHwgaWRlbnRpdHlcbiAgdmFyIHZpZXcgICAgICAgID0gY2FtZXJhLnZpZXcgfHwgaWRlbnRpdHlcbiAgdmFyIHByb2plY3Rpb24gID0gY2FtZXJhLnByb2plY3Rpb24gfHwgaWRlbnRpdHlcbiAgdmFyIGlzT3J0aG8gICAgID0gY2FtZXJhLl9vcnRobyB8fCBmYWxzZVxuICB2YXIgYm91bmRzICAgICAgPSBheGVzLmJvdW5kc1xuICB2YXIgcGFyYW1zICAgICAgPSBwYXJhbXMgfHwgY3ViZVBhcmFtcyhtb2RlbCwgdmlldywgcHJvamVjdGlvbiwgYm91bmRzLCBpc09ydGhvKVxuICB2YXIgYXhpcyAgICAgICAgPSBwYXJhbXMuYXhpc1xuXG4gIG00bXVsKG12cCwgdmlldywgbW9kZWwpXG4gIG00bXVsKG12cCwgcHJvamVjdGlvbiwgbXZwKVxuXG4gIC8vQ2FsY3VsYXRlIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyBmb3IgZWFjaCBheGlzOlxuICAvL1xuICAvLyAqIGxvIC0gc3RhcnQgb2YgdmlzaWJsZSByYW5nZSBmb3IgZWFjaCBheGlzIGluIHRpY2sgY29vcmRpbmF0ZXNcbiAgLy8gKiBoaSAtIGVuZCBvZiB2aXNpYmxlIHJhbmdlIGZvciBlYWNoIGF4aXMgaW4gdGljayBjb29yZGluYXRlc1xuICAvLyAqIHRpY2tzUGVyUGl4ZWwgLSBwaXhlbCBkZW5zaXR5IG9mIHRpY2sgbWFya3MgZm9yIHRoZSBheGlzXG4gIC8vXG4gIHZhciByYW5nZXMgPSBSQU5HRVNcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgcmFuZ2VzW2ldLmxvID0gSW5maW5pdHlcbiAgICByYW5nZXNbaV0uaGkgPSAtSW5maW5pdHlcbiAgICByYW5nZXNbaV0ucGl4ZWxzUGVyRGF0YVVuaXQgPSBJbmZpbml0eVxuICB9XG5cbiAgLy9Db21wdXRlIGZydXN0dW0gcGxhbmVzLCBpbnRlcnNlY3Qgd2l0aCBib3hcbiAgdmFyIGZydXN0dW0gPSBnZXRQbGFuZXMobTR0cmFuc3Bvc2UobXZwLCBtdnApKVxuICBtNHRyYW5zcG9zZShtdnAsIG12cClcblxuICAvL0xvb3Agb3ZlciB2ZXJ0aWNlcyBvZiB2aWV3YWJsZSBib3hcbiAgZm9yKHZhciBkPTA7IGQ8MzsgKytkKSB7XG4gICAgdmFyIHUgPSAoZCsxKSUzXG4gICAgdmFyIHYgPSAoZCsyKSUzXG4gICAgdmFyIHggPSBTQ1JBVENIX1hcbmlfbG9vcDpcbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcbiAgICAgIHZhciBwb2x5ID0gW11cblxuICAgICAgaWYoKGF4aXNbZF0gPCAwKSA9PT0gISFpKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIHhbZF0gPSBib3VuZHNbaV1bZF1cbiAgICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xuICAgICAgICB4W3VdID0gYm91bmRzW2peaV1bdV1cbiAgICAgICAgZm9yKHZhciBrPTA7IGs8MjsgKytrKSB7XG4gICAgICAgICAgeFt2XSA9IGJvdW5kc1trXmpeaV1bdl1cbiAgICAgICAgICBwb2x5LnB1c2goeC5zbGljZSgpKVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhciBRID0gKGlzT3J0aG8pID8gNSA6IDRcbiAgICAgIGZvcih2YXIgaj1ROyBqPT09UTsgKytqKSB7IC8vIE5vdGU6IHVzaW5nIG9ubHkgbmVhciBwbGFuZSBoZXJlICgmIGZvciBvcnRob2dyYXBoaWMgcHJvamVjdGlvbiB3ZSB1c2UgdGhlIGZhcikuXG4gICAgICAgIGlmKHBvbHkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgY29udGludWUgaV9sb29wXG4gICAgICAgIH1cbiAgICAgICAgcG9seSA9IHNwbGl0UG9seS5wb3NpdGl2ZShwb2x5LCBmcnVzdHVtW2pdKVxuICAgICAgfVxuXG4gICAgICAvL0xvb3Agb3ZlciB2ZXJ0aWNlcyBvZiBwb2x5Z29uIHRvIGZpbmQgZXh0cmVtYWwgcG9pbnRzXG4gICAgICBmb3IodmFyIGo9MDsgajxwb2x5Lmxlbmd0aDsgKytqKSB7XG4gICAgICAgIHZhciB2ID0gcG9seVtqXVxuICAgICAgICB2YXIgZ3JhZCA9IGdyYWRpZW50KFNDUkFUQ0hfWCwgbXZwLCB2LCB3aWR0aCwgaGVpZ2h0KVxuICAgICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgICAgICByYW5nZXNba10ubG8gPSBNYXRoLm1pbihyYW5nZXNba10ubG8sIHZba10pXG4gICAgICAgICAgcmFuZ2VzW2tdLmhpID0gTWF0aC5tYXgocmFuZ2VzW2tdLmhpLCB2W2tdKVxuICAgICAgICAgIGlmKGsgIT09IGQpIHtcbiAgICAgICAgICAgIHJhbmdlc1trXS5waXhlbHNQZXJEYXRhVW5pdCA9IE1hdGgubWluKHJhbmdlc1trXS5waXhlbHNQZXJEYXRhVW5pdCwgTWF0aC5hYnMoZ3JhZFtrXSkpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJhbmdlc1xufVxuXG59LHtcIi4vbGliL2N1YmUuanNcIjoyMzUsXCJleHRyYWN0LWZydXN0dW0tcGxhbmVzXCI6MjI0LFwiZ2wtbWF0NC9tdWx0aXBseVwiOjI2NyxcImdsLW1hdDQvdHJhbnNwb3NlXCI6Mjc2LFwiZ2wtdmVjNC90cmFuc2Zvcm1NYXQ0XCI6Mzk4LFwic3BsaXQtcG9seWdvblwiOjUyN31dLDI0MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG52YXIgcG9vbCA9IF9kZXJlcV8oXCJ0eXBlZGFycmF5LXBvb2xcIilcbnZhciBvcHMgPSBfZGVyZXFfKFwibmRhcnJheS1vcHNcIilcbnZhciBuZGFycmF5ID0gX2RlcmVxXyhcIm5kYXJyYXlcIilcblxudmFyIFNVUFBPUlRFRF9UWVBFUyA9IFtcbiAgXCJ1aW50OFwiLFxuICBcInVpbnQ4X2NsYW1wZWRcIixcbiAgXCJ1aW50MTZcIixcbiAgXCJ1aW50MzJcIixcbiAgXCJpbnQ4XCIsXG4gIFwiaW50MTZcIixcbiAgXCJpbnQzMlwiLFxuICBcImZsb2F0MzJcIiBdXG5cbmZ1bmN0aW9uIEdMQnVmZmVyKGdsLCB0eXBlLCBoYW5kbGUsIGxlbmd0aCwgdXNhZ2UpIHtcbiAgdGhpcy5nbCA9IGdsXG4gIHRoaXMudHlwZSA9IHR5cGVcbiAgdGhpcy5oYW5kbGUgPSBoYW5kbGVcbiAgdGhpcy5sZW5ndGggPSBsZW5ndGhcbiAgdGhpcy51c2FnZSA9IHVzYWdlXG59XG5cbnZhciBwcm90byA9IEdMQnVmZmVyLnByb3RvdHlwZVxuXG5wcm90by5iaW5kID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZ2wuYmluZEJ1ZmZlcih0aGlzLnR5cGUsIHRoaXMuaGFuZGxlKVxufVxuXG5wcm90by51bmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5nbC5iaW5kQnVmZmVyKHRoaXMudHlwZSwgbnVsbClcbn1cblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmdsLmRlbGV0ZUJ1ZmZlcih0aGlzLmhhbmRsZSlcbn1cblxuZnVuY3Rpb24gdXBkYXRlVHlwZUFycmF5KGdsLCB0eXBlLCBsZW4sIHVzYWdlLCBkYXRhLCBvZmZzZXQpIHtcbiAgdmFyIGRhdGFMZW4gPSBkYXRhLmxlbmd0aCAqIGRhdGEuQllURVNfUEVSX0VMRU1FTlRcbiAgaWYob2Zmc2V0IDwgMCkge1xuICAgIGdsLmJ1ZmZlckRhdGEodHlwZSwgZGF0YSwgdXNhZ2UpXG4gICAgcmV0dXJuIGRhdGFMZW5cbiAgfVxuICBpZihkYXRhTGVuICsgb2Zmc2V0ID4gbGVuKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiZ2wtYnVmZmVyOiBJZiByZXNpemluZyBidWZmZXIsIG11c3Qgbm90IHNwZWNpZnkgb2Zmc2V0XCIpXG4gIH1cbiAgZ2wuYnVmZmVyU3ViRGF0YSh0eXBlLCBvZmZzZXQsIGRhdGEpXG4gIHJldHVybiBsZW5cbn1cblxuZnVuY3Rpb24gbWFrZVNjcmF0Y2hUeXBlQXJyYXkoYXJyYXksIGR0eXBlKSB7XG4gIHZhciByZXMgPSBwb29sLm1hbGxvYyhhcnJheS5sZW5ndGgsIGR0eXBlKVxuICB2YXIgbiA9IGFycmF5Lmxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICByZXNbaV0gPSBhcnJheVtpXVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuZnVuY3Rpb24gaXNQYWNrZWQoc2hhcGUsIHN0cmlkZSkge1xuICB2YXIgbiA9IDFcbiAgZm9yKHZhciBpPXN0cmlkZS5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgaWYoc3RyaWRlW2ldICE9PSBuKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgbiAqPSBzaGFwZVtpXVxuICB9XG4gIHJldHVybiB0cnVlXG59XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGFycmF5LCBvZmZzZXQpIHtcbiAgaWYodHlwZW9mIG9mZnNldCAhPT0gXCJudW1iZXJcIikge1xuICAgIG9mZnNldCA9IC0xXG4gIH1cbiAgdGhpcy5iaW5kKClcbiAgaWYodHlwZW9mIGFycmF5ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBhcnJheS5zaGFwZSAhPT0gXCJ1bmRlZmluZWRcIikgeyAvL25kYXJyYXlcbiAgICB2YXIgZHR5cGUgPSBhcnJheS5kdHlwZVxuICAgIGlmKFNVUFBPUlRFRF9UWVBFUy5pbmRleE9mKGR0eXBlKSA8IDApIHtcbiAgICAgIGR0eXBlID0gXCJmbG9hdDMyXCJcbiAgICB9XG4gICAgaWYodGhpcy50eXBlID09PSB0aGlzLmdsLkVMRU1FTlRfQVJSQVlfQlVGRkVSKSB7XG4gICAgICB2YXIgZXh0ID0gZ2wuZ2V0RXh0ZW5zaW9uKCdPRVNfZWxlbWVudF9pbmRleF91aW50JylcbiAgICAgIGlmKGV4dCAmJiBkdHlwZSAhPT0gXCJ1aW50MTZcIikge1xuICAgICAgICBkdHlwZSA9IFwidWludDMyXCJcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGR0eXBlID0gXCJ1aW50MTZcIlxuICAgICAgfVxuICAgIH1cbiAgICBpZihkdHlwZSA9PT0gYXJyYXkuZHR5cGUgJiYgaXNQYWNrZWQoYXJyYXkuc2hhcGUsIGFycmF5LnN0cmlkZSkpIHtcbiAgICAgIGlmKGFycmF5Lm9mZnNldCA9PT0gMCAmJiBhcnJheS5kYXRhLmxlbmd0aCA9PT0gYXJyYXkuc2hhcGVbMF0pIHtcbiAgICAgICAgdGhpcy5sZW5ndGggPSB1cGRhdGVUeXBlQXJyYXkodGhpcy5nbCwgdGhpcy50eXBlLCB0aGlzLmxlbmd0aCwgdGhpcy51c2FnZSwgYXJyYXkuZGF0YSwgb2Zmc2V0KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5sZW5ndGggPSB1cGRhdGVUeXBlQXJyYXkodGhpcy5nbCwgdGhpcy50eXBlLCB0aGlzLmxlbmd0aCwgdGhpcy51c2FnZSwgYXJyYXkuZGF0YS5zdWJhcnJheShhcnJheS5vZmZzZXQsIGFycmF5LnNoYXBlWzBdKSwgb2Zmc2V0KVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgdG1wID0gcG9vbC5tYWxsb2MoYXJyYXkuc2l6ZSwgZHR5cGUpXG4gICAgICB2YXIgbmR0ID0gbmRhcnJheSh0bXAsIGFycmF5LnNoYXBlKVxuICAgICAgb3BzLmFzc2lnbihuZHQsIGFycmF5KVxuICAgICAgaWYob2Zmc2V0IDwgMCkge1xuICAgICAgICB0aGlzLmxlbmd0aCA9IHVwZGF0ZVR5cGVBcnJheSh0aGlzLmdsLCB0aGlzLnR5cGUsIHRoaXMubGVuZ3RoLCB0aGlzLnVzYWdlLCB0bXAsIG9mZnNldClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMubGVuZ3RoID0gdXBkYXRlVHlwZUFycmF5KHRoaXMuZ2wsIHRoaXMudHlwZSwgdGhpcy5sZW5ndGgsIHRoaXMudXNhZ2UsIHRtcC5zdWJhcnJheSgwLCBhcnJheS5zaXplKSwgb2Zmc2V0KVxuICAgICAgfVxuICAgICAgcG9vbC5mcmVlKHRtcClcbiAgICB9XG4gIH0gZWxzZSBpZihBcnJheS5pc0FycmF5KGFycmF5KSkgeyAvL1ZhbmlsbGEgYXJyYXlcbiAgICB2YXIgdFxuICAgIGlmKHRoaXMudHlwZSA9PT0gdGhpcy5nbC5FTEVNRU5UX0FSUkFZX0JVRkZFUikge1xuICAgICAgdCA9IG1ha2VTY3JhdGNoVHlwZUFycmF5KGFycmF5LCBcInVpbnQxNlwiKVxuICAgIH0gZWxzZSB7XG4gICAgICB0ID0gbWFrZVNjcmF0Y2hUeXBlQXJyYXkoYXJyYXksIFwiZmxvYXQzMlwiKVxuICAgIH1cbiAgICBpZihvZmZzZXQgPCAwKSB7XG4gICAgICB0aGlzLmxlbmd0aCA9IHVwZGF0ZVR5cGVBcnJheSh0aGlzLmdsLCB0aGlzLnR5cGUsIHRoaXMubGVuZ3RoLCB0aGlzLnVzYWdlLCB0LCBvZmZzZXQpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGVuZ3RoID0gdXBkYXRlVHlwZUFycmF5KHRoaXMuZ2wsIHRoaXMudHlwZSwgdGhpcy5sZW5ndGgsIHRoaXMudXNhZ2UsIHQuc3ViYXJyYXkoMCwgYXJyYXkubGVuZ3RoKSwgb2Zmc2V0KVxuICAgIH1cbiAgICBwb29sLmZyZWUodClcbiAgfSBlbHNlIGlmKHR5cGVvZiBhcnJheSA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgYXJyYXkubGVuZ3RoID09PSBcIm51bWJlclwiKSB7IC8vVHlwZWQgYXJyYXlcbiAgICB0aGlzLmxlbmd0aCA9IHVwZGF0ZVR5cGVBcnJheSh0aGlzLmdsLCB0aGlzLnR5cGUsIHRoaXMubGVuZ3RoLCB0aGlzLnVzYWdlLCBhcnJheSwgb2Zmc2V0KVxuICB9IGVsc2UgaWYodHlwZW9mIGFycmF5ID09PSBcIm51bWJlclwiIHx8IGFycmF5ID09PSB1bmRlZmluZWQpIHsgLy9OdW1iZXIvZGVmYXVsdFxuICAgIGlmKG9mZnNldCA+PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJnbC1idWZmZXI6IENhbm5vdCBzcGVjaWZ5IG9mZnNldCB3aGVuIHJlc2l6aW5nIGJ1ZmZlclwiKVxuICAgIH1cbiAgICBhcnJheSA9IGFycmF5IHwgMFxuICAgIGlmKGFycmF5IDw9IDApIHtcbiAgICAgIGFycmF5ID0gMVxuICAgIH1cbiAgICB0aGlzLmdsLmJ1ZmZlckRhdGEodGhpcy50eXBlLCBhcnJheXwwLCB0aGlzLnVzYWdlKVxuICAgIHRoaXMubGVuZ3RoID0gYXJyYXlcbiAgfSBlbHNlIHsgLy9FcnJvciwgY2FzZSBzaG91bGQgbm90IGhhcHBlblxuICAgIHRocm93IG5ldyBFcnJvcihcImdsLWJ1ZmZlcjogSW52YWxpZCBkYXRhIHR5cGVcIilcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVCdWZmZXIoZ2wsIGRhdGEsIHR5cGUsIHVzYWdlKSB7XG4gIHR5cGUgPSB0eXBlIHx8IGdsLkFSUkFZX0JVRkZFUlxuICB1c2FnZSA9IHVzYWdlIHx8IGdsLkRZTkFNSUNfRFJBV1xuICBpZih0eXBlICE9PSBnbC5BUlJBWV9CVUZGRVIgJiYgdHlwZSAhPT0gZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJnbC1idWZmZXI6IEludmFsaWQgdHlwZSBmb3Igd2ViZ2wgYnVmZmVyLCBtdXN0IGJlIGVpdGhlciBnbC5BUlJBWV9CVUZGRVIgb3IgZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVJcIilcbiAgfVxuICBpZih1c2FnZSAhPT0gZ2wuRFlOQU1JQ19EUkFXICYmIHVzYWdlICE9PSBnbC5TVEFUSUNfRFJBVyAmJiB1c2FnZSAhPT0gZ2wuU1RSRUFNX0RSQVcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJnbC1idWZmZXI6IEludmFsaWQgdXNhZ2UgZm9yIGJ1ZmZlciwgbXVzdCBiZSBlaXRoZXIgZ2wuRFlOQU1JQ19EUkFXLCBnbC5TVEFUSUNfRFJBVyBvciBnbC5TVFJFQU1fRFJBV1wiKVxuICB9XG4gIHZhciBoYW5kbGUgPSBnbC5jcmVhdGVCdWZmZXIoKVxuICB2YXIgcmVzdWx0ID0gbmV3IEdMQnVmZmVyKGdsLCB0eXBlLCBoYW5kbGUsIDAsIHVzYWdlKVxuICByZXN1bHQudXBkYXRlKGRhdGEpXG4gIHJldHVybiByZXN1bHRcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCdWZmZXJcblxufSx7XCJuZGFycmF5XCI6NDUwLFwibmRhcnJheS1vcHNcIjo0NDQsXCJ0eXBlZGFycmF5LXBvb2xcIjo1NDV9XSwyNDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBWID0gX2RlcmVxXygnZ2wtdmVjMycpO1xuXG52YXIgdmVjMyA9IGZ1bmN0aW9uKHgsIHksIHopIHtcblx0dmFyIHYgPSBWLmNyZWF0ZSgpO1xuXHRpZiAoeCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0Vi5zZXQodiwgeCwgeSwgeik7XG5cdH1cblx0cmV0dXJuIHY7XG59XG5cbnZhciBjcmVhdGVQb3NpdGlvbnNGb3JNZXNoZ3JpZCA9IGZ1bmN0aW9uKG1lc2hncmlkKSB7XG5cdHZhciB4cyA9IG1lc2hncmlkWzBdLCB5cyA9IG1lc2hncmlkWzFdLCB6cyA9IG1lc2hncmlkWzJdO1xuXHR2YXIgcG9zaXRpb25zID0gW107XG5cdGZvciAodmFyIHo9MDsgejx6cy5sZW5ndGg7IHorKykge1xuXHRcdGZvciAodmFyIHk9MDsgeTx5cy5sZW5ndGg7IHkrKykge1xuXHRcdFx0Zm9yICh2YXIgeD0wOyB4PHhzLmxlbmd0aDsgeCsrKSB7XG5cdFx0XHRcdHBvc2l0aW9ucy5wdXNoKFt6c1t6XSwgeXNbeV0sIHhzW3hdXSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdHJldHVybiBwb3NpdGlvbnM7XG59O1xuXG52YXIgZmluZExhc3RTbWFsbGVySW5kZXggPSBmdW5jdGlvbihwb2ludHMsIHYpIHtcblx0Zm9yICh2YXIgaT0wOyBpPHBvaW50cy5sZW5ndGg7IGkrKykge1xuXHRcdGlmIChwb2ludHNbaV0gPj0gdikge1xuXHRcdFx0cmV0dXJuIGktMTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGk7XG59O1xuXG52YXIgdG1wID0gVi5jcmVhdGUoKTtcbnZhciB0bXAyID0gVi5jcmVhdGUoKTtcblxudmFyIGNsYW1wID0gZnVuY3Rpb24odiwgbWluLCBtYXgpIHtcblx0cmV0dXJuIHYgPCBtaW4gPyBtaW4gOiAodiA+IG1heCA/IG1heCA6IHYpO1xufTtcblxudmFyIHNhbXBsZU1lc2hncmlkID0gZnVuY3Rpb24ocG9pbnQsIGFycmF5LCBtZXNoZ3JpZCwgY2xhbXBPdmVyZmxvdykge1xuXHR2YXIgeCA9IHBvaW50WzBdO1xuXHR2YXIgeSA9IHBvaW50WzFdO1xuXHR2YXIgeiA9IHBvaW50WzJdO1xuXG5cdHZhciB3ID0gbWVzaGdyaWRbMF0ubGVuZ3RoO1xuXHR2YXIgaCA9IG1lc2hncmlkWzFdLmxlbmd0aDtcblx0dmFyIGQgPSBtZXNoZ3JpZFsyXS5sZW5ndGg7XG5cblx0Ly8gRmluZCB0aGUgaW5kZXggb2YgdGhlIG5lYXJlc3Qgc21hbGxlciB2YWx1ZSBpbiB0aGUgbWVzaGdyaWQgZm9yIGVhY2ggY29vcmRpbmF0ZSBvZiAoeCx5LHopLlxuXHQvLyBUaGUgbmVhcmVzdCBzbWFsbGVyIHZhbHVlIGluZGV4IGZvciB4IGlzIHRoZSBpbmRleCB4MCBzdWNoIHRoYXRcblx0Ly8gbWVzaGdyaWRbMF1beDBdIDwgeCBhbmQgZm9yIGFsbCB4MSA+IHgwLCBtZXNoZ3JpZFswXVt4MV0gPj0geC5cblx0dmFyIHgwID0gZmluZExhc3RTbWFsbGVySW5kZXgobWVzaGdyaWRbMF0sIHgpO1xuXHR2YXIgeTAgPSBmaW5kTGFzdFNtYWxsZXJJbmRleChtZXNoZ3JpZFsxXSwgeSk7XG5cdHZhciB6MCA9IGZpbmRMYXN0U21hbGxlckluZGV4KG1lc2hncmlkWzJdLCB6KTtcblxuXHQvLyBHZXQgdGhlIG5lYXJlc3QgbGFyZ2VyIG1lc2hncmlkIHZhbHVlIGluZGljZXMuXG5cdC8vIEZyb20gdGhlIGFib3ZlIFwibmVhcmVzdCBzbWFsbGVyIHZhbHVlXCIsIHdlIGtub3cgdGhhdFxuXHQvLyAgIG1lc2hncmlkWzBdW3gwXSA8IHhcblx0Ly8gICBtZXNoZ3JpZFswXVt4MCsxXSA+PSB4XG5cdHZhciB4MSA9IHgwICsgMTtcblx0dmFyIHkxID0geTAgKyAxO1xuXHR2YXIgejEgPSB6MCArIDE7XG5cblx0aWYgKGNsYW1wT3ZlcmZsb3cpIHtcblx0XHR4MCA9IGNsYW1wKHgwLCAwLCB3LTEpO1xuXHRcdHgxID0gY2xhbXAoeDEsIDAsIHctMSk7XG5cdFx0eTAgPSBjbGFtcCh5MCwgMCwgaC0xKTtcblx0XHR5MSA9IGNsYW1wKHkxLCAwLCBoLTEpO1xuXHRcdHowID0gY2xhbXAoejAsIDAsIGQtMSk7XG5cdFx0ejEgPSBjbGFtcCh6MSwgMCwgZC0xKTtcblx0fVxuXG5cdC8vIFJlamVjdCBwb2ludHMgb3V0c2lkZSB0aGUgbWVzaGdyaWQsIHJldHVybiBhIHplcm8gdmVjdG9yLlxuXHRpZiAoeDAgPCAwIHx8IHkwIDwgMCB8fCB6MCA8IDAgfHwgeDEgPj0gdyB8fCB5MSA+PSBoIHx8IHoxID49IGQpIHtcblx0XHRyZXR1cm4gVi5jcmVhdGUoKTtcblx0fVxuXG5cdC8vIE5vcm1hbGl6ZSBwb2ludCBjb29yZGluYXRlcyB0byAwLi4xIHNjYWxpbmcgZmFjdG9yIGJldHdlZW4geDAgYW5kIHgxLlxuXHR2YXIgeGYgPSAoeCAtIG1lc2hncmlkWzBdW3gwXSkgLyAobWVzaGdyaWRbMF1beDFdIC0gbWVzaGdyaWRbMF1beDBdKTtcblx0dmFyIHlmID0gKHkgLSBtZXNoZ3JpZFsxXVt5MF0pIC8gKG1lc2hncmlkWzFdW3kxXSAtIG1lc2hncmlkWzFdW3kwXSk7XG5cdHZhciB6ZiA9ICh6IC0gbWVzaGdyaWRbMl1bejBdKSAvIChtZXNoZ3JpZFsyXVt6MV0gLSBtZXNoZ3JpZFsyXVt6MF0pO1xuXG5cdGlmICh4ZiA8IDAgfHwgeGYgPiAxIHx8IGlzTmFOKHhmKSkgeGYgPSAwO1xuXHRpZiAoeWYgPCAwIHx8IHlmID4gMSB8fCBpc05hTih5ZikpIHlmID0gMDtcblx0aWYgKHpmIDwgMCB8fCB6ZiA+IDEgfHwgaXNOYU4oemYpKSB6ZiA9IDA7XG5cblx0dmFyIHowb2ZmID0gejAqdypoO1xuXHR2YXIgejFvZmYgPSB6MSp3Kmg7XG5cblx0dmFyIHkwb2ZmID0geTAqdztcblx0dmFyIHkxb2ZmID0geTEqdztcblxuXHR2YXIgeDBvZmYgPSB4MDtcblx0dmFyIHgxb2ZmID0geDE7XG5cblx0Ly8gU2FtcGxlIGRhdGEgYXJyYXkgYXJvdW5kIHRoZSAoeCx5LHopIHBvaW50LlxuXHQvLyAgdlpZWCA9IGFycmF5W3pab2ZmICsgeVlvZmYgKyB4WG9mZl1cblx0dmFyIHYwMDAgPSBhcnJheVt5MG9mZiArIHowb2ZmICsgeDBvZmZdO1xuXHR2YXIgdjAwMSA9IGFycmF5W3kwb2ZmICsgejBvZmYgKyB4MW9mZl07XG5cdHZhciB2MDEwID0gYXJyYXlbeTFvZmYgKyB6MG9mZiArIHgwb2ZmXTtcblx0dmFyIHYwMTEgPSBhcnJheVt5MW9mZiArIHowb2ZmICsgeDFvZmZdO1xuXHR2YXIgdjEwMCA9IGFycmF5W3kwb2ZmICsgejFvZmYgKyB4MG9mZl07XG5cdHZhciB2MTAxID0gYXJyYXlbeTBvZmYgKyB6MW9mZiArIHgxb2ZmXTtcblx0dmFyIHYxMTAgPSBhcnJheVt5MW9mZiArIHoxb2ZmICsgeDBvZmZdO1xuXHR2YXIgdjExMSA9IGFycmF5W3kxb2ZmICsgejFvZmYgKyB4MW9mZl07XG5cblx0dmFyIHJlc3VsdCA9IFYuY3JlYXRlKCk7XG5cblx0Ly8gQXZlcmFnZSBzYW1wbGVzIGFjY29yZGluZyB0byBkaXN0YW5jZSB0byBwb2ludC5cblx0Vi5sZXJwKHJlc3VsdCwgdjAwMCwgdjAwMSwgeGYpO1xuXHRWLmxlcnAodG1wLCB2MDEwLCB2MDExLCB4Zik7XG5cdFYubGVycChyZXN1bHQsIHJlc3VsdCwgdG1wLCB5Zik7XG5cdFYubGVycCh0bXAsIHYxMDAsIHYxMDEsIHhmKTtcblx0Vi5sZXJwKHRtcDIsIHYxMTAsIHYxMTEsIHhmKTtcblx0Vi5sZXJwKHRtcCwgdG1wLCB0bXAyLCB5Zik7XG5cdFYubGVycChyZXN1bHQsIHJlc3VsdCwgdG1wLCB6Zik7XG5cblx0cmV0dXJuIHJlc3VsdDtcbn07XG5cbnZhciBnZXRPcnRob2dvbmFsVmVjdG9yID0gZnVuY3Rpb24oZHN0LCB2KSB7XG5cdC8vIFJldHVybiB1cC12ZWN0b3IgZm9yIG9ubHkteiB2ZWN0b3IuXG5cdGlmICh2WzBdID09PSAwICYmIHZbMV0gPT09IDApIHtcblx0XHRWLnNldChkc3QsIDAsIDEsIDApO1xuXHR9IGVsc2Uge1xuXHRcdC8vIFJldHVybiBheCArIGJ5ICsgY3ogPSAwLCBhIHBvaW50IHRoYXQgbGllcyBvbiB0aGUgcGxhbmUgdGhhdCBoYXMgdiBhcyBhIG5vcm1hbCBhbmQgdGhhdCBpc24ndCAoMCwwLDApLlxuXHRcdC8vIEZyb20gdGhlIGFib3ZlIGlmLXN0YXRlbWVudCB3ZSBoYXZlIHx8YXx8ID4gMCAgVSAgfHxifHwgPiAwLlxuXHRcdC8vIEFzc2lnbiB6ID0gMCwgeCA9IC1iLCB5ID0gYTpcblx0XHQvLyBhKi1iICsgYiphICsgYyowID0gLWJhICsgYmEgKyAwID0gMFxuXHRcdFYuc2V0KGRzdCwgLXZbMV0sIHZbMF0sIDApO1xuXHR9XG5cdHJldHVybiBkc3Q7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHZlY3RvcmZpZWxkLCBib3VuZHMpIHtcblx0dmFyIHBvc2l0aW9ucztcblx0aWYgKHZlY3RvcmZpZWxkLnBvc2l0aW9ucykge1xuXHRcdHBvc2l0aW9ucyA9IHZlY3RvcmZpZWxkLnBvc2l0aW9ucztcblx0fSBlbHNlIHtcblx0XHRwb3NpdGlvbnMgPSBjcmVhdGVQb3NpdGlvbnNGb3JNZXNoZ3JpZCh2ZWN0b3JmaWVsZC5tZXNoZ3JpZCk7XG5cdH1cblx0dmFyIG1lc2hncmlkID0gdmVjdG9yZmllbGQubWVzaGdyaWQ7XG5cdHZhciB2ZWN0b3JzID0gdmVjdG9yZmllbGQudmVjdG9ycztcblx0dmFyIGdlbyA9IHtcblx0XHRwb3NpdGlvbnM6IFtdLFxuXHRcdHZlcnRleEludGVuc2l0eTogW10sXG5cdFx0dmVydGV4SW50ZW5zaXR5Qm91bmRzOiB2ZWN0b3JmaWVsZC52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHMsXG5cdFx0dmVydGV4Tm9ybWFsczogW10sXG5cdFx0dmVjdG9yczogW10sXG5cdFx0Y2VsbHM6IFtdLFxuXHRcdGNvbmVPZmZzZXQ6IHZlY3RvcmZpZWxkLmNvbmVPZmZzZXQsXG5cdFx0Y29sb3JtYXA6IHZlY3RvcmZpZWxkLmNvbG9ybWFwXG5cdH07XG5cblx0aWYgKHZlY3RvcmZpZWxkLnBvc2l0aW9ucy5sZW5ndGggPT09IDApIHtcblx0XHRpZiAoYm91bmRzKSB7XG5cdFx0XHRib3VuZHNbMF0gPSBbMCwwLDBdO1xuXHRcdFx0Ym91bmRzWzFdID0gWzAsMCwwXTtcblx0XHR9XG5cdFx0cmV0dXJuIGdlbztcblx0fVxuXG5cdC8vIENvbXB1dGUgYm91bmRpbmcgYm94IGZvciB0aGUgZGF0YXNldC5cblx0Ly8gQ29tcHV0ZSBtYXhpbXVtIHZlbG9jaXR5IGZvciB0aGUgZGF0YXNldCB0byB1c2UgZm9yIHNjYWxpbmcgdGhlIGNvbmVzLlxuXHR2YXIgbWF4Tm9ybSA9IDA7XG5cdHZhciBtaW5YID0gMS8wLCBtYXhYID0gLTEvMDtcblx0dmFyIG1pblkgPSAxLzAsIG1heFkgPSAtMS8wO1xuXHR2YXIgbWluWiA9IDEvMCwgbWF4WiA9IC0xLzA7XG5cdHZhciBwMiA9IG51bGw7XG5cdHZhciB1MiA9IG51bGw7XG5cdHZhciBwb3NpdGlvblZlY3RvcnMgPSBbXTtcblx0dmFyIHZlY3RvclNjYWxlID0gMS8wO1xuXHRmb3IgKHZhciBpID0gMDsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7IGkrKykge1xuXHRcdHZhciBwID0gcG9zaXRpb25zW2ldO1xuXHRcdG1pblggPSBNYXRoLm1pbihwWzBdLCBtaW5YKTtcblx0XHRtYXhYID0gTWF0aC5tYXgocFswXSwgbWF4WCk7XG5cdFx0bWluWSA9IE1hdGgubWluKHBbMV0sIG1pblkpO1xuXHRcdG1heFkgPSBNYXRoLm1heChwWzFdLCBtYXhZKTtcblx0XHRtaW5aID0gTWF0aC5taW4ocFsyXSwgbWluWik7XG5cdFx0bWF4WiA9IE1hdGgubWF4KHBbMl0sIG1heFopO1xuXHRcdHZhciB1O1xuXHRcdGlmIChtZXNoZ3JpZCkge1xuXHRcdFx0dSA9IHNhbXBsZU1lc2hncmlkKHAsIHZlY3RvcnMsIG1lc2hncmlkLCB0cnVlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dSA9IHZlY3RvcnNbaV07XG5cdFx0fVxuXHRcdGlmIChWLmxlbmd0aCh1KSA+IG1heE5vcm0pIHtcblx0XHRcdG1heE5vcm0gPSBWLmxlbmd0aCh1KTtcblx0XHR9XG5cdFx0aWYgKGkpIHtcblx0XHRcdC8vIEZpbmQgdmVjdG9yIHNjYWxlIFt3LyB1bml0cyBvZiB0aW1lXSB1c2luZyBcInN1Y2Nlc3NpdmVcIiBwb3NpdGlvbnNcblx0XHRcdC8vIChub3QgXCJhZGphY2VudFwiIHdpdGggd291bGQgYmUgTyhuXjIpKSxcblx0XHRcdC8vXG5cdFx0XHQvLyBUaGUgdmVjdG9yIHNjYWxlIGNvcnJlc3BvbmRzIHRvIHRoZSBtaW5pbXVtIFwidGltZVwiIHRvIHRyYXZlbCBhY3Jvc3MgdHdvXG5cdFx0XHQvLyB0d28gYWRqYWNlbnQgcG9zaXRpb25zIGF0IHRoZSBhdmVyYWdlIHZlbG9jaXR5IG9mIHRob3NlIHR3byBhZGphY2VudCBwb3NpdGlvbnNcblx0XHRcdHZlY3RvclNjYWxlID0gTWF0aC5taW4odmVjdG9yU2NhbGUsXG5cdFx0XHRcdDIgKiBWLmRpc3RhbmNlKHAyLCBwKSAvIChWLmxlbmd0aCh1MikgKyBWLmxlbmd0aCh1KSlcblx0XHRcdCk7XG5cdFx0fVxuXHRcdHAyID0gcDtcblx0XHR1MiA9IHU7XG5cdFx0cG9zaXRpb25WZWN0b3JzLnB1c2godSk7XG5cdH1cblx0dmFyIG1pblYgPSBbbWluWCwgbWluWSwgbWluWl07XG5cdHZhciBtYXhWID0gW21heFgsIG1heFksIG1heFpdO1xuXHRpZiAoYm91bmRzKSB7XG5cdFx0Ym91bmRzWzBdID0gbWluVjtcblx0XHRib3VuZHNbMV0gPSBtYXhWO1xuXHR9XG5cdGlmIChtYXhOb3JtID09PSAwKSB7XG5cdFx0bWF4Tm9ybSA9IDE7XG5cdH1cblxuXHQvLyBJbnZlcnRlZCBtYXggbm9ybSB3b3VsZCBtYXAgdmVjdG9yIHdpdGggbm9ybSBtYXhOb3JtIHRvIDEgY29vcmQgc3BhY2UgdW5pdHMgaW4gbGVuZ3RoXG5cdHZhciBpbnZlcnRlZE1heE5vcm0gPSAxIC8gbWF4Tm9ybTtcblxuXHRpZiAoIWlzRmluaXRlKHZlY3RvclNjYWxlKSB8fCBpc05hTih2ZWN0b3JTY2FsZSkpIHtcblx0XHR2ZWN0b3JTY2FsZSA9IDEuMDtcblx0fVxuXHRnZW8udmVjdG9yU2NhbGUgPSB2ZWN0b3JTY2FsZTtcblxuXHR2YXIgbm1sID0gdmVjMygwLDEsMCk7XG5cblx0dmFyIGNvbmVTY2FsZSA9IHZlY3RvcmZpZWxkLmNvbmVTaXplIHx8IDAuNTtcblxuXHRpZiAodmVjdG9yZmllbGQuYWJzb2x1dGVDb25lU2l6ZSkge1xuXHRcdGNvbmVTY2FsZSA9IHZlY3RvcmZpZWxkLmFic29sdXRlQ29uZVNpemUgKiBpbnZlcnRlZE1heE5vcm07XG5cdH1cblxuXHRnZW8uY29uZVNjYWxlID0gY29uZVNjYWxlO1xuXG5cdC8vIEJ1aWxkIHRoZSBjb25lIG1vZGVsLlxuXHRmb3IgKHZhciBpID0gMCwgaiA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoOyBpKyspIHtcblx0XHR2YXIgcCA9IHBvc2l0aW9uc1tpXTtcblx0XHR2YXIgeCA9IHBbMF0sIHkgPSBwWzFdLCB6ID0gcFsyXTtcblx0XHR2YXIgZCA9IHBvc2l0aW9uVmVjdG9yc1tpXTtcblx0XHR2YXIgaW50ZW5zaXR5ID0gVi5sZW5ndGgoZCkgKiBpbnZlcnRlZE1heE5vcm07XG5cdFx0Zm9yICh2YXIgayA9IDAsIGwgPSA4OyBrIDwgbDsgaysrKSB7XG5cdFx0XHRnZW8ucG9zaXRpb25zLnB1c2goW3gsIHksIHosIGorK10pO1xuXHRcdFx0Z2VvLnBvc2l0aW9ucy5wdXNoKFt4LCB5LCB6LCBqKytdKTtcblx0XHRcdGdlby5wb3NpdGlvbnMucHVzaChbeCwgeSwgeiwgaisrXSk7XG5cdFx0XHRnZW8ucG9zaXRpb25zLnB1c2goW3gsIHksIHosIGorK10pO1xuXHRcdFx0Z2VvLnBvc2l0aW9ucy5wdXNoKFt4LCB5LCB6LCBqKytdKTtcblx0XHRcdGdlby5wb3NpdGlvbnMucHVzaChbeCwgeSwgeiwgaisrXSk7XG5cblx0XHRcdGdlby52ZWN0b3JzLnB1c2goZCk7XG5cdFx0XHRnZW8udmVjdG9ycy5wdXNoKGQpO1xuXHRcdFx0Z2VvLnZlY3RvcnMucHVzaChkKTtcblx0XHRcdGdlby52ZWN0b3JzLnB1c2goZCk7XG5cdFx0XHRnZW8udmVjdG9ycy5wdXNoKGQpO1xuXHRcdFx0Z2VvLnZlY3RvcnMucHVzaChkKTtcblxuXHRcdFx0Z2VvLnZlcnRleEludGVuc2l0eS5wdXNoKGludGVuc2l0eSwgaW50ZW5zaXR5LCBpbnRlbnNpdHkpO1xuXHRcdFx0Z2VvLnZlcnRleEludGVuc2l0eS5wdXNoKGludGVuc2l0eSwgaW50ZW5zaXR5LCBpbnRlbnNpdHkpO1xuXG5cdFx0XHRnZW8udmVydGV4Tm9ybWFscy5wdXNoKG5tbCwgbm1sLCBubWwpO1xuXHRcdFx0Z2VvLnZlcnRleE5vcm1hbHMucHVzaChubWwsIG5tbCwgbm1sKTtcblxuXHRcdFx0dmFyIG0gPSBnZW8ucG9zaXRpb25zLmxlbmd0aDtcblx0XHRcdGdlby5jZWxscy5wdXNoKFttLTYsIG0tNSwgbS00XSwgW20tMywgbS0yLCBtLTFdKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZ2VvO1xufTtcblxubW9kdWxlLmV4cG9ydHMuY3JlYXRlQ29uZU1lc2ggPSBfZGVyZXFfKCcuL2xpYi9jb25lbWVzaCcpO1xuXG59LHtcIi4vbGliL2NvbmVtZXNoXCI6MjQzLFwiZ2wtdmVjM1wiOjM0Nn1dLDI0MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIERFRkFVTFRfVkVSVEVYX05PUk1BTFNfRVBTSUxPTiA9IDFlLTY7IC8vIG1heSBiZSB0b28gbGFyZ2UgaWYgdHJpYW5nbGVzIGFyZSB2ZXJ5IHNtYWxsXG52YXIgREVGQVVMVF9GQUNFX05PUk1BTFNfRVBTSUxPTiA9IDFlLTY7XG5cbnZhciBjcmVhdGVTaGFkZXIgID0gX2RlcmVxXygnZ2wtc2hhZGVyJylcbnZhciBjcmVhdGVCdWZmZXIgID0gX2RlcmVxXygnZ2wtYnVmZmVyJylcbnZhciBjcmVhdGVWQU8gICAgID0gX2RlcmVxXygnZ2wtdmFvJylcbnZhciBjcmVhdGVUZXh0dXJlID0gX2RlcmVxXygnZ2wtdGV4dHVyZTJkJylcbnZhciBub3JtYWxzICAgICAgID0gX2RlcmVxXygnbm9ybWFscycpXG52YXIgbXVsdGlwbHkgICAgICA9IF9kZXJlcV8oJ2dsLW1hdDQvbXVsdGlwbHknKVxudmFyIGludmVydCAgICAgICAgPSBfZGVyZXFfKCdnbC1tYXQ0L2ludmVydCcpXG52YXIgbmRhcnJheSAgICAgICA9IF9kZXJlcV8oJ25kYXJyYXknKVxudmFyIGNvbG9ybWFwICAgICAgPSBfZGVyZXFfKCdjb2xvcm1hcCcpXG52YXIgZ2V0Q29udG91ciAgICA9IF9kZXJlcV8oJ3NpbXBsaWNpYWwtY29tcGxleC1jb250b3VyJylcbnZhciBwb29sICAgICAgICAgID0gX2RlcmVxXygndHlwZWRhcnJheS1wb29sJylcbnZhciBzaGFkZXJzICAgICAgID0gX2RlcmVxXygnLi9zaGFkZXJzJylcblxudmFyIG1lc2hTaGFkZXIgICAgPSBzaGFkZXJzLm1lc2hTaGFkZXJcbnZhciBwaWNrU2hhZGVyICAgID0gc2hhZGVycy5waWNrU2hhZGVyXG5cbnZhciBJREVOVElUWSA9IFtcbiAgMSwwLDAsMCxcbiAgMCwxLDAsMCxcbiAgMCwwLDEsMCxcbiAgMCwwLDAsMV1cblxuZnVuY3Rpb24gU2ltcGxpY2lhbE1lc2goZ2xcbiAgLCB0ZXh0dXJlXG4gICwgdHJpU2hhZGVyXG4gICwgcGlja1NoYWRlclxuICAsIHRyaWFuZ2xlUG9zaXRpb25zXG4gICwgdHJpYW5nbGVWZWN0b3JzXG4gICwgdHJpYW5nbGVJZHNcbiAgLCB0cmlhbmdsZUNvbG9yc1xuICAsIHRyaWFuZ2xlVVZzXG4gICwgdHJpYW5nbGVOb3JtYWxzXG4gICwgdHJpYW5nbGVWQU9cbiAgLCBlZGdlUG9zaXRpb25zXG4gICwgZWRnZUlkc1xuICAsIGVkZ2VDb2xvcnNcbiAgLCBlZGdlVVZzXG4gICwgZWRnZVZBT1xuICAsIHBvaW50UG9zaXRpb25zXG4gICwgcG9pbnRJZHNcbiAgLCBwb2ludENvbG9yc1xuICAsIHBvaW50VVZzXG4gICwgcG9pbnRTaXplc1xuICAsIHBvaW50VkFPXG4gICwgY29udG91clBvc2l0aW9uc1xuICAsIGNvbnRvdXJWQU8pIHtcblxuICB0aGlzLmdsICAgICAgICAgICAgICAgID0gZ2xcbiAgdGhpcy5waXhlbFJhdGlvICAgICAgICAgPSAxXG4gIHRoaXMuY2VsbHMgICAgICAgICAgICAgPSBbXVxuICB0aGlzLnBvc2l0aW9ucyAgICAgICAgID0gW11cbiAgdGhpcy5pbnRlbnNpdHkgICAgICAgICA9IFtdXG4gIHRoaXMudGV4dHVyZSAgICAgICAgICAgPSB0ZXh0dXJlXG4gIHRoaXMuZGlydHkgICAgICAgICAgICAgPSB0cnVlXG5cbiAgdGhpcy50cmlTaGFkZXIgICAgICAgICA9IHRyaVNoYWRlclxuICB0aGlzLnBpY2tTaGFkZXIgICAgICAgID0gcGlja1NoYWRlclxuXG4gIHRoaXMudHJpYW5nbGVQb3NpdGlvbnMgPSB0cmlhbmdsZVBvc2l0aW9uc1xuICB0aGlzLnRyaWFuZ2xlVmVjdG9ycyAgID0gdHJpYW5nbGVWZWN0b3JzXG4gIHRoaXMudHJpYW5nbGVDb2xvcnMgICAgPSB0cmlhbmdsZUNvbG9yc1xuICB0aGlzLnRyaWFuZ2xlTm9ybWFscyAgID0gdHJpYW5nbGVOb3JtYWxzXG4gIHRoaXMudHJpYW5nbGVVVnMgICAgICAgPSB0cmlhbmdsZVVWc1xuICB0aGlzLnRyaWFuZ2xlSWRzICAgICAgID0gdHJpYW5nbGVJZHNcbiAgdGhpcy50cmlhbmdsZVZBTyAgICAgICA9IHRyaWFuZ2xlVkFPXG4gIHRoaXMudHJpYW5nbGVDb3VudCAgICAgPSAwXG5cbiAgdGhpcy5saW5lV2lkdGggICAgICAgICA9IDFcbiAgdGhpcy5lZGdlUG9zaXRpb25zICAgICA9IGVkZ2VQb3NpdGlvbnNcbiAgdGhpcy5lZGdlQ29sb3JzICAgICAgICA9IGVkZ2VDb2xvcnNcbiAgdGhpcy5lZGdlVVZzICAgICAgICAgICA9IGVkZ2VVVnNcbiAgdGhpcy5lZGdlSWRzICAgICAgICAgICA9IGVkZ2VJZHNcbiAgdGhpcy5lZGdlVkFPICAgICAgICAgICA9IGVkZ2VWQU9cbiAgdGhpcy5lZGdlQ291bnQgICAgICAgICA9IDBcblxuICB0aGlzLnBvaW50UG9zaXRpb25zICAgID0gcG9pbnRQb3NpdGlvbnNcbiAgdGhpcy5wb2ludENvbG9ycyAgICAgICA9IHBvaW50Q29sb3JzXG4gIHRoaXMucG9pbnRVVnMgICAgICAgICAgPSBwb2ludFVWc1xuICB0aGlzLnBvaW50U2l6ZXMgICAgICAgID0gcG9pbnRTaXplc1xuICB0aGlzLnBvaW50SWRzICAgICAgICAgID0gcG9pbnRJZHNcbiAgdGhpcy5wb2ludFZBTyAgICAgICAgICA9IHBvaW50VkFPXG4gIHRoaXMucG9pbnRDb3VudCAgICAgICAgPSAwXG5cbiAgdGhpcy5jb250b3VyTGluZVdpZHRoICA9IDFcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zICA9IGNvbnRvdXJQb3NpdGlvbnNcbiAgdGhpcy5jb250b3VyVkFPICAgICAgICA9IGNvbnRvdXJWQU9cbiAgdGhpcy5jb250b3VyQ291bnQgICAgICA9IDBcbiAgdGhpcy5jb250b3VyQ29sb3IgICAgICA9IFswLDAsMF1cbiAgdGhpcy5jb250b3VyRW5hYmxlICAgICA9IHRydWVcblxuICB0aGlzLnBpY2tJZCAgICAgICAgICAgID0gMVxuICB0aGlzLmJvdW5kcyAgICAgICAgICAgID0gW1xuICAgIFsgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV0sXG4gICAgWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XSBdXG4gIHRoaXMuY2xpcEJvdW5kcyAgICAgICAgPSBbXG4gICAgWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XSxcbiAgICBbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldIF1cblxuICB0aGlzLmxpZ2h0UG9zaXRpb24gPSBbMWU1LCAxZTUsIDBdXG4gIHRoaXMuYW1iaWVudExpZ2h0ICA9IDAuOFxuICB0aGlzLmRpZmZ1c2VMaWdodCAgPSAwLjhcbiAgdGhpcy5zcGVjdWxhckxpZ2h0ID0gMi4wXG4gIHRoaXMucm91Z2huZXNzICAgICA9IDAuNVxuICB0aGlzLmZyZXNuZWwgICAgICAgPSAxLjVcblxuICB0aGlzLm9wYWNpdHkgICAgICAgPSAxLjBcblxuICB0aGlzLmNvbmVTY2FsZSAgICAgPSAyLjBcbiAgdGhpcy52ZWN0b3JTY2FsZSAgID0gMS4wXG4gIHRoaXMuY29uZU9mZnNldCAgICA9IDEuMCAvIDQuMDtcblxuICB0aGlzLl9tb2RlbCAgICAgICA9IElERU5USVRZXG4gIHRoaXMuX3ZpZXcgICAgICAgID0gSURFTlRJVFlcbiAgdGhpcy5fcHJvamVjdGlvbiAgPSBJREVOVElUWVxuICB0aGlzLl9yZXNvbHV0aW9uICA9IFsxLDFdXG59XG5cbnZhciBwcm90byA9IFNpbXBsaWNpYWxNZXNoLnByb3RvdHlwZVxuXG5wcm90by5pc09wYXF1ZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5vcGFjaXR5ID49IDFcbn1cblxucHJvdG8uaXNUcmFuc3BhcmVudCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5vcGFjaXR5IDwgMVxufVxuXG5wcm90by5waWNrU2xvdHMgPSAxXG5cbnByb3RvLnNldFBpY2tCYXNlID0gZnVuY3Rpb24oaWQpIHtcbiAgdGhpcy5waWNrSWQgPSBpZFxufVxuXG5mdW5jdGlvbiBnZW5Db2xvcm1hcChwYXJhbSkge1xuICB2YXIgY29sb3JzID0gY29sb3JtYXAoe1xuICAgICAgY29sb3JtYXA6IHBhcmFtXG4gICAgLCBuc2hhZGVzOiAgMjU2XG4gICAgLCBmb3JtYXQ6ICAncmdiYSdcbiAgfSlcblxuICB2YXIgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoMjU2KjQpXG4gIGZvcih2YXIgaT0wOyBpPDI1NjsgKytpKSB7XG4gICAgdmFyIGMgPSBjb2xvcnNbaV1cbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIHJlc3VsdFs0Kmkral0gPSBjW2pdXG4gICAgfVxuICAgIHJlc3VsdFs0KmkrM10gPSBjWzNdKjI1NVxuICB9XG5cbiAgcmV0dXJuIG5kYXJyYXkocmVzdWx0LCBbMjU2LDI1Niw0XSwgWzQsMCwxXSlcbn1cblxuZnVuY3Rpb24gdW5wYWNrSW50ZW5zaXR5KGNlbGxzLCBudW1WZXJ0cywgY2VsbEludGVuc2l0eSkge1xuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG51bVZlcnRzKVxuICBmb3IodmFyIGk9MDsgaTxudW1WZXJ0czsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gMFxuICB9XG4gIHZhciBudW1DZWxscyA9IGNlbGxzLmxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxudW1DZWxsczsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPGMubGVuZ3RoOyArK2opIHtcbiAgICAgIHJlc3VsdFtjW2pdXSA9IGNlbGxJbnRlbnNpdHlbaV1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiB0YWtlWkNvbXBvbmVudChhcnJheSkge1xuICB2YXIgbiA9IGFycmF5Lmxlbmd0aFxuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG4pXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IGFycmF5W2ldWzJdXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5wcm90by5oaWdobGlnaHQgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcbiAgaWYoIXNlbGVjdGlvbiB8fCAhdGhpcy5jb250b3VyRW5hYmxlKSB7XG4gICAgdGhpcy5jb250b3VyQ291bnQgPSAwXG4gICAgcmV0dXJuXG4gIH1cbiAgdmFyIGxldmVsID0gZ2V0Q29udG91cih0aGlzLmNlbGxzLCB0aGlzLmludGVuc2l0eSwgc2VsZWN0aW9uLmludGVuc2l0eSlcbiAgdmFyIGNlbGxzICAgICAgICAgPSBsZXZlbC5jZWxsc1xuICB2YXIgdmVydGV4SWRzICAgICA9IGxldmVsLnZlcnRleElkc1xuICB2YXIgdmVydGV4V2VpZ2h0cyA9IGxldmVsLnZlcnRleFdlaWdodHNcbiAgdmFyIG51bUNlbGxzID0gY2VsbHMubGVuZ3RoXG4gIHZhciByZXN1bHQgPSBwb29sLm1hbGxvY0Zsb2F0MzIoMiAqIDMgKiBudW1DZWxscylcbiAgdmFyIHB0ciA9IDBcbiAgZm9yKHZhciBpPTA7IGk8bnVtQ2VsbHM7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcbiAgICAgIHZhciB2ID0gY1swXVxuICAgICAgaWYoYy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgdiA9IGNbal1cbiAgICAgIH1cbiAgICAgIHZhciBhID0gdmVydGV4SWRzW3ZdWzBdXG4gICAgICB2YXIgYiA9IHZlcnRleElkc1t2XVsxXVxuICAgICAgdmFyIHcgPSB2ZXJ0ZXhXZWlnaHRzW3ZdXG4gICAgICB2YXIgd2kgPSAxLjAgLSB3XG4gICAgICB2YXIgcGEgPSB0aGlzLnBvc2l0aW9uc1thXVxuICAgICAgdmFyIHBiID0gdGhpcy5wb3NpdGlvbnNbYl1cbiAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xuICAgICAgICByZXN1bHRbcHRyKytdID0gdyAqIHBhW2tdICsgd2kgKiBwYltrXVxuICAgICAgfVxuICAgIH1cbiAgfVxuICB0aGlzLmNvbnRvdXJDb3VudCA9IChwdHIgLyAzKXwwXG4gIHRoaXMuY29udG91clBvc2l0aW9ucy51cGRhdGUocmVzdWx0LnN1YmFycmF5KDAsIHB0cikpXG4gIHBvb2wuZnJlZShyZXN1bHQpXG59XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKHBhcmFtcykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge31cbiAgdmFyIGdsID0gdGhpcy5nbFxuXG4gIHRoaXMuZGlydHkgPSB0cnVlXG5cbiAgaWYoJ2NvbnRvdXJFbmFibGUnIGluIHBhcmFtcykge1xuICAgIHRoaXMuY29udG91ckVuYWJsZSA9IHBhcmFtcy5jb250b3VyRW5hYmxlXG4gIH1cbiAgaWYoJ2NvbnRvdXJDb2xvcicgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5jb250b3VyQ29sb3IgPSBwYXJhbXMuY29udG91ckNvbG9yXG4gIH1cbiAgaWYoJ2xpbmVXaWR0aCcgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5saW5lV2lkdGggPSBwYXJhbXMubGluZVdpZHRoXG4gIH1cbiAgaWYoJ2xpZ2h0UG9zaXRpb24nIGluIHBhcmFtcykge1xuICAgIHRoaXMubGlnaHRQb3NpdGlvbiA9IHBhcmFtcy5saWdodFBvc2l0aW9uXG4gIH1cbiAgaWYoJ29wYWNpdHknIGluIHBhcmFtcykge1xuICAgIHRoaXMub3BhY2l0eSA9IHBhcmFtcy5vcGFjaXR5XG4gIH1cbiAgaWYoJ2FtYmllbnQnIGluIHBhcmFtcykge1xuICAgIHRoaXMuYW1iaWVudExpZ2h0ICA9IHBhcmFtcy5hbWJpZW50XG4gIH1cbiAgaWYoJ2RpZmZ1c2UnIGluIHBhcmFtcykge1xuICAgIHRoaXMuZGlmZnVzZUxpZ2h0ID0gcGFyYW1zLmRpZmZ1c2VcbiAgfVxuICBpZignc3BlY3VsYXInIGluIHBhcmFtcykge1xuICAgIHRoaXMuc3BlY3VsYXJMaWdodCA9IHBhcmFtcy5zcGVjdWxhclxuICB9XG4gIGlmKCdyb3VnaG5lc3MnIGluIHBhcmFtcykge1xuICAgIHRoaXMucm91Z2huZXNzID0gcGFyYW1zLnJvdWdobmVzc1xuICB9XG4gIGlmKCdmcmVzbmVsJyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLmZyZXNuZWwgPSBwYXJhbXMuZnJlc25lbFxuICB9XG5cbiAgaWYgKHBhcmFtcy52ZWN0b3JTY2FsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdGhpcy52ZWN0b3JTY2FsZSA9IHBhcmFtcy52ZWN0b3JTY2FsZTtcbiAgfVxuICBpZiAocGFyYW1zLmNvbmVTY2FsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5jb25lU2NhbGUgPSBwYXJhbXMuY29uZVNjYWxlO1xuICB9XG4gIGlmIChwYXJhbXMuY29uZU9mZnNldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5jb25lT2Zmc2V0ID0gcGFyYW1zLmNvbmVPZmZzZXQ7XG4gIH1cblxuICBpZihwYXJhbXMudGV4dHVyZSkge1xuICAgIHRoaXMudGV4dHVyZS5kaXNwb3NlKClcbiAgICB0aGlzLnRleHR1cmUgPSBjcmVhdGVUZXh0dXJlKGdsLCBwYXJhbXMudGV4dHVyZSlcbiAgfSBlbHNlIGlmIChwYXJhbXMuY29sb3JtYXApIHtcbiAgICB0aGlzLnRleHR1cmUuc2hhcGUgPSBbMjU2LDI1Nl1cbiAgICB0aGlzLnRleHR1cmUubWluRmlsdGVyID0gZ2wuTElORUFSX01JUE1BUF9MSU5FQVJcbiAgICB0aGlzLnRleHR1cmUubWFnRmlsdGVyID0gZ2wuTElORUFSXG4gICAgdGhpcy50ZXh0dXJlLnNldFBpeGVscyhnZW5Db2xvcm1hcChwYXJhbXMuY29sb3JtYXApKVxuICAgIHRoaXMudGV4dHVyZS5nZW5lcmF0ZU1pcG1hcCgpXG4gIH1cblxuICB2YXIgY2VsbHMgPSBwYXJhbXMuY2VsbHNcbiAgdmFyIHBvc2l0aW9ucyA9IHBhcmFtcy5wb3NpdGlvbnNcbiAgdmFyIHZlY3RvcnMgPSBwYXJhbXMudmVjdG9yc1xuXG4gIGlmKCFwb3NpdGlvbnMgfHwgIWNlbGxzIHx8ICF2ZWN0b3JzKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICB2YXIgdFBvcyA9IFtdXG4gIHZhciB0VmVjID0gW11cbiAgdmFyIHRDb2wgPSBbXVxuICB2YXIgdE5vciA9IFtdXG4gIHZhciB0VVZzID0gW11cbiAgdmFyIHRJZHMgPSBbXVxuXG4gIHZhciBlUG9zID0gW11cbiAgdmFyIGVDb2wgPSBbXVxuICB2YXIgZVVWcyA9IFtdXG4gIHZhciBlSWRzID0gW11cblxuICB2YXIgcFBvcyA9IFtdXG4gIHZhciBwQ29sID0gW11cbiAgdmFyIHBVVnMgPSBbXVxuICB2YXIgcFNpeiA9IFtdXG4gIHZhciBwSWRzID0gW11cblxuICAvL1NhdmUgZ2VvbWV0cnkgZGF0YSBmb3IgcGlja2luZyBjYWxjdWxhdGlvbnNcbiAgdGhpcy5jZWxscyAgICAgPSBjZWxsc1xuICB0aGlzLnBvc2l0aW9ucyA9IHBvc2l0aW9uc1xuXG4gIC8vQ29tcHV0ZSBub3JtYWxzXG4gIHZhciB2ZXJ0ZXhOb3JtYWxzID0gcGFyYW1zLnZlcnRleE5vcm1hbHNcbiAgdmFyIGNlbGxOb3JtYWxzICAgPSBwYXJhbXMuY2VsbE5vcm1hbHNcbiAgdmFyIHZlcnRleE5vcm1hbHNFcHNpbG9uID0gcGFyYW1zLnZlcnRleE5vcm1hbHNFcHNpbG9uID09PSB2b2lkKDApID8gREVGQVVMVF9WRVJURVhfTk9STUFMU19FUFNJTE9OIDogcGFyYW1zLnZlcnRleE5vcm1hbHNFcHNpbG9uXG4gIHZhciBmYWNlTm9ybWFsc0Vwc2lsb24gPSBwYXJhbXMuZmFjZU5vcm1hbHNFcHNpbG9uID09PSB2b2lkKDApID8gREVGQVVMVF9GQUNFX05PUk1BTFNfRVBTSUxPTiA6IHBhcmFtcy5mYWNlTm9ybWFsc0Vwc2lsb25cbiAgaWYocGFyYW1zLnVzZUZhY2V0Tm9ybWFscyAmJiAhY2VsbE5vcm1hbHMpIHtcbiAgICBjZWxsTm9ybWFscyA9IG5vcm1hbHMuZmFjZU5vcm1hbHMoY2VsbHMsIHBvc2l0aW9ucywgZmFjZU5vcm1hbHNFcHNpbG9uKVxuICB9XG4gIGlmKCFjZWxsTm9ybWFscyAmJiAhdmVydGV4Tm9ybWFscykge1xuICAgIHZlcnRleE5vcm1hbHMgPSBub3JtYWxzLnZlcnRleE5vcm1hbHMoY2VsbHMsIHBvc2l0aW9ucywgdmVydGV4Tm9ybWFsc0Vwc2lsb24pXG4gIH1cblxuICAvL0NvbXB1dGUgY29sb3JzXG4gIHZhciB2ZXJ0ZXhDb2xvcnMgICAgPSBwYXJhbXMudmVydGV4Q29sb3JzXG4gIHZhciBjZWxsQ29sb3JzICAgICAgPSBwYXJhbXMuY2VsbENvbG9yc1xuICB2YXIgbWVzaENvbG9yICAgICAgID0gcGFyYW1zLm1lc2hDb2xvciB8fCBbMSwxLDEsMV1cblxuICAvL1VWc1xuICB2YXIgdmVydGV4VVZzICAgICAgID0gcGFyYW1zLnZlcnRleFVWc1xuICB2YXIgdmVydGV4SW50ZW5zaXR5ID0gcGFyYW1zLnZlcnRleEludGVuc2l0eVxuICB2YXIgY2VsbFVWcyAgICAgICAgID0gcGFyYW1zLmNlbGxVVnNcbiAgdmFyIGNlbGxJbnRlbnNpdHkgICA9IHBhcmFtcy5jZWxsSW50ZW5zaXR5XG5cbiAgdmFyIGludGVuc2l0eUxvICAgICA9IEluZmluaXR5XG4gIHZhciBpbnRlbnNpdHlIaSAgICAgPSAtSW5maW5pdHlcbiAgaWYoIXZlcnRleFVWcyAmJiAhY2VsbFVWcykge1xuICAgIGlmKHZlcnRleEludGVuc2l0eSkge1xuICAgICAgaWYocGFyYW1zLnZlcnRleEludGVuc2l0eUJvdW5kcykge1xuICAgICAgICBpbnRlbnNpdHlMbyA9ICtwYXJhbXMudmVydGV4SW50ZW5zaXR5Qm91bmRzWzBdXG4gICAgICAgIGludGVuc2l0eUhpID0gK3BhcmFtcy52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHNbMV1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvcih2YXIgaT0wOyBpPHZlcnRleEludGVuc2l0eS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIHZhciBmID0gdmVydGV4SW50ZW5zaXR5W2ldXG4gICAgICAgICAgaW50ZW5zaXR5TG8gPSBNYXRoLm1pbihpbnRlbnNpdHlMbywgZilcbiAgICAgICAgICBpbnRlbnNpdHlIaSA9IE1hdGgubWF4KGludGVuc2l0eUhpLCBmKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcbiAgICAgIGZvcih2YXIgaT0wOyBpPGNlbGxJbnRlbnNpdHkubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGYgPSBjZWxsSW50ZW5zaXR5W2ldXG4gICAgICAgIGludGVuc2l0eUxvID0gTWF0aC5taW4oaW50ZW5zaXR5TG8sIGYpXG4gICAgICAgIGludGVuc2l0eUhpID0gTWF0aC5tYXgoaW50ZW5zaXR5SGksIGYpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvcih2YXIgaT0wOyBpPHBvc2l0aW9ucy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgZiA9IHBvc2l0aW9uc1tpXVsyXVxuICAgICAgICBpbnRlbnNpdHlMbyA9IE1hdGgubWluKGludGVuc2l0eUxvLCBmKVxuICAgICAgICBpbnRlbnNpdHlIaSA9IE1hdGgubWF4KGludGVuc2l0eUhpLCBmKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmKHZlcnRleEludGVuc2l0eSkge1xuICAgIHRoaXMuaW50ZW5zaXR5ID0gdmVydGV4SW50ZW5zaXR5XG4gIH0gZWxzZSBpZihjZWxsSW50ZW5zaXR5KSB7XG4gICAgdGhpcy5pbnRlbnNpdHkgPSB1bnBhY2tJbnRlbnNpdHkoY2VsbHMsIHBvc2l0aW9ucy5sZW5ndGgsIGNlbGxJbnRlbnNpdHkpXG4gIH0gZWxzZSB7XG4gICAgdGhpcy5pbnRlbnNpdHkgPSB0YWtlWkNvbXBvbmVudChwb3NpdGlvbnMpXG4gIH1cblxuICAvL1BvaW50IHNpemVcbiAgdmFyIHBvaW50U2l6ZXMgICAgICA9IHBhcmFtcy5wb2ludFNpemVzXG4gIHZhciBtZXNoUG9pbnRTaXplICAgPSBwYXJhbXMucG9pbnRTaXplIHx8IDEuMFxuXG4gIC8vVXBkYXRlIGJvdW5kc1xuICB0aGlzLmJvdW5kcyAgICAgICA9IFtbSW5maW5pdHksSW5maW5pdHksSW5maW5pdHldLCBbLUluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldXVxuICBmb3IodmFyIGk9MDsgaTxwb3NpdGlvbnMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcCA9IHBvc2l0aW9uc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgaWYoaXNOYU4ocFtqXSkgfHwgIWlzRmluaXRlKHBbal0pKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICB0aGlzLmJvdW5kc1swXVtqXSA9IE1hdGgubWluKHRoaXMuYm91bmRzWzBdW2pdLCBwW2pdKVxuICAgICAgdGhpcy5ib3VuZHNbMV1bal0gPSBNYXRoLm1heCh0aGlzLmJvdW5kc1sxXVtqXSwgcFtqXSlcbiAgICB9XG4gIH1cblxuICAvL1BhY2sgY2VsbHMgaW50byBidWZmZXJzXG4gIHZhciB0cmlhbmdsZUNvdW50ID0gMFxuICB2YXIgZWRnZUNvdW50ID0gMFxuICB2YXIgcG9pbnRDb3VudCA9IDBcblxuZmlsbF9sb29wOlxuICBmb3IodmFyIGk9MDsgaTxjZWxscy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBjZWxsID0gY2VsbHNbaV1cbiAgICBzd2l0Y2goY2VsbC5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMTpcblxuICAgICAgICB2YXIgdiA9IGNlbGxbMF1cbiAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cblxuICAgICAgICAvL0NoZWNrIE5hTnNcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICAgICAgaWYoaXNOYU4ocFtqXSkgfHwgIWlzRmluaXRlKHBbal0pKSB7XG4gICAgICAgICAgICBjb250aW51ZSBmaWxsX2xvb3BcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwUG9zLnB1c2gocFswXSwgcFsxXSwgcFsyXSwgcFszXSlcblxuICAgICAgICB2YXIgY1xuICAgICAgICBpZih2ZXJ0ZXhDb2xvcnMpIHtcbiAgICAgICAgICBjID0gdmVydGV4Q29sb3JzW3ZdXG4gICAgICAgIH0gZWxzZSBpZihjZWxsQ29sb3JzKSB7XG4gICAgICAgICAgYyA9IGNlbGxDb2xvcnNbaV1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjID0gbWVzaENvbG9yXG4gICAgICAgIH1cbiAgICAgICAgaWYoYy5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICBwQ29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgMSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwQ29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgY1szXSlcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB1dlxuICAgICAgICBpZih2ZXJ0ZXhVVnMpIHtcbiAgICAgICAgICB1diA9IHZlcnRleFVWc1t2XVxuICAgICAgICB9IGVsc2UgaWYodmVydGV4SW50ZW5zaXR5KSB7XG4gICAgICAgICAgdXYgPSBbXG4gICAgICAgICAgICAodmVydGV4SW50ZW5zaXR5W3ZdIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgfSBlbHNlIGlmKGNlbGxVVnMpIHtcbiAgICAgICAgICB1diA9IGNlbGxVVnNbaV1cbiAgICAgICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcbiAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgIChjZWxsSW50ZW5zaXR5W2ldIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgIChwWzJdIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgfVxuICAgICAgICBwVVZzLnB1c2godXZbMF0sIHV2WzFdKVxuXG4gICAgICAgIGlmKHBvaW50U2l6ZXMpIHtcbiAgICAgICAgICBwU2l6LnB1c2gocG9pbnRTaXplc1t2XSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwU2l6LnB1c2gobWVzaFBvaW50U2l6ZSlcbiAgICAgICAgfVxuXG4gICAgICAgIHBJZHMucHVzaChpKVxuXG4gICAgICAgIHBvaW50Q291bnQgKz0gMVxuICAgICAgYnJlYWtcblxuICAgICAgY2FzZSAyOlxuXG4gICAgICAgIC8vQ2hlY2sgTmFOc1xuICAgICAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcbiAgICAgICAgICB2YXIgdiA9IGNlbGxbal1cbiAgICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxuICAgICAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xuICAgICAgICAgICAgaWYoaXNOYU4ocFtrXSkgfHwgIWlzRmluaXRlKHBba10pKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIGZpbGxfbG9vcFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xuICAgICAgICAgIHZhciB2ID0gY2VsbFtqXVxuICAgICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXG5cbiAgICAgICAgICBlUG9zLnB1c2gocFswXSwgcFsxXSwgcFsyXSlcblxuICAgICAgICAgIHZhciBjXG4gICAgICAgICAgaWYodmVydGV4Q29sb3JzKSB7XG4gICAgICAgICAgICBjID0gdmVydGV4Q29sb3JzW3ZdXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxDb2xvcnMpIHtcbiAgICAgICAgICAgIGMgPSBjZWxsQ29sb3JzW2ldXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGMgPSBtZXNoQ29sb3JcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYoYy5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICAgIGVDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCAxKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlQ29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgY1szXSlcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgdXZcbiAgICAgICAgICBpZih2ZXJ0ZXhVVnMpIHtcbiAgICAgICAgICAgIHV2ID0gdmVydGV4VVZzW3ZdXG4gICAgICAgICAgfSBlbHNlIGlmKHZlcnRleEludGVuc2l0eSkge1xuICAgICAgICAgICAgdXYgPSBbXG4gICAgICAgICAgICAgICh2ZXJ0ZXhJbnRlbnNpdHlbdl0gLSBpbnRlbnNpdHlMbykgL1xuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxVVnMpIHtcbiAgICAgICAgICAgIHV2ID0gY2VsbFVWc1tpXVxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsSW50ZW5zaXR5KSB7XG4gICAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgICAgKGNlbGxJbnRlbnNpdHlbaV0gLSBpbnRlbnNpdHlMbykgL1xuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHV2ID0gW1xuICAgICAgICAgICAgICAocFsyXSAtIGludGVuc2l0eUxvKSAvXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgICB9XG4gICAgICAgICAgZVVWcy5wdXNoKHV2WzBdLCB1dlsxXSlcblxuICAgICAgICAgIGVJZHMucHVzaChpKVxuICAgICAgICB9XG4gICAgICAgIGVkZ2VDb3VudCArPSAxXG4gICAgICBicmVha1xuXG4gICAgICBjYXNlIDM6XG4gICAgICAgIC8vQ2hlY2sgTmFOc1xuICAgICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgICB2YXIgdiA9IGNlbGxbal1cbiAgICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxuICAgICAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xuICAgICAgICAgICAgaWYoaXNOYU4ocFtrXSkgfHwgIWlzRmluaXRlKHBba10pKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIGZpbGxfbG9vcFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgICAgIHZhciB2ID0gY2VsbFsyIC0gal1cblxuICAgICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXG4gICAgICAgICAgdFBvcy5wdXNoKHBbMF0sIHBbMV0sIHBbMl0sIHBbM10pXG5cbiAgICAgICAgICB2YXIgdyA9IHZlY3RvcnNbdl1cbiAgICAgICAgICB0VmVjLnB1c2god1swXSwgd1sxXSwgd1syXSk7XG5cbiAgICAgICAgICB2YXIgY1xuICAgICAgICAgIGlmKHZlcnRleENvbG9ycykge1xuICAgICAgICAgICAgYyA9IHZlcnRleENvbG9yc1t2XVxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsQ29sb3JzKSB7XG4gICAgICAgICAgICBjID0gY2VsbENvbG9yc1tpXVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjID0gbWVzaENvbG9yXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKGMubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgICB0Q29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgMSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdENvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sIGNbM10pXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHV2XG4gICAgICAgICAgaWYodmVydGV4VVZzKSB7XG4gICAgICAgICAgICB1diA9IHZlcnRleFVWc1t2XVxuICAgICAgICAgIH0gZWxzZSBpZih2ZXJ0ZXhJbnRlbnNpdHkpIHtcbiAgICAgICAgICAgIHV2ID0gW1xuICAgICAgICAgICAgICAodmVydGV4SW50ZW5zaXR5W3ZdIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsVVZzKSB7XG4gICAgICAgICAgICB1diA9IGNlbGxVVnNbaV1cbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbEludGVuc2l0eSkge1xuICAgICAgICAgICAgdXYgPSBbXG4gICAgICAgICAgICAgIChjZWxsSW50ZW5zaXR5W2ldIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgICAgKHBbMl0gLSBpbnRlbnNpdHlMbykgL1xuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXG4gICAgICAgICAgfVxuICAgICAgICAgIHRVVnMucHVzaCh1dlswXSwgdXZbMV0pXG5cbiAgICAgICAgICB2YXIgcVxuICAgICAgICAgIGlmKHZlcnRleE5vcm1hbHMpIHtcbiAgICAgICAgICAgIHEgPSB2ZXJ0ZXhOb3JtYWxzW3ZdXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHEgPSBjZWxsTm9ybWFsc1tpXVxuICAgICAgICAgIH1cbiAgICAgICAgICB0Tm9yLnB1c2gocVswXSwgcVsxXSwgcVsyXSlcblxuICAgICAgICAgIHRJZHMucHVzaChpKVxuICAgICAgICB9XG4gICAgICAgIHRyaWFuZ2xlQ291bnQgKz0gMVxuICAgICAgYnJlYWtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgdGhpcy5wb2ludENvdW50ICAgICA9IHBvaW50Q291bnRcbiAgdGhpcy5lZGdlQ291bnQgICAgICA9IGVkZ2VDb3VudFxuICB0aGlzLnRyaWFuZ2xlQ291bnQgID0gdHJpYW5nbGVDb3VudFxuXG4gIHRoaXMucG9pbnRQb3NpdGlvbnMudXBkYXRlKHBQb3MpXG4gIHRoaXMucG9pbnRDb2xvcnMudXBkYXRlKHBDb2wpXG4gIHRoaXMucG9pbnRVVnMudXBkYXRlKHBVVnMpXG4gIHRoaXMucG9pbnRTaXplcy51cGRhdGUocFNpeilcbiAgdGhpcy5wb2ludElkcy51cGRhdGUobmV3IFVpbnQzMkFycmF5KHBJZHMpKVxuXG4gIHRoaXMuZWRnZVBvc2l0aW9ucy51cGRhdGUoZVBvcylcbiAgdGhpcy5lZGdlQ29sb3JzLnVwZGF0ZShlQ29sKVxuICB0aGlzLmVkZ2VVVnMudXBkYXRlKGVVVnMpXG4gIHRoaXMuZWRnZUlkcy51cGRhdGUobmV3IFVpbnQzMkFycmF5KGVJZHMpKVxuXG4gIHRoaXMudHJpYW5nbGVQb3NpdGlvbnMudXBkYXRlKHRQb3MpXG4gIHRoaXMudHJpYW5nbGVWZWN0b3JzLnVwZGF0ZSh0VmVjKVxuICB0aGlzLnRyaWFuZ2xlQ29sb3JzLnVwZGF0ZSh0Q29sKVxuICB0aGlzLnRyaWFuZ2xlVVZzLnVwZGF0ZSh0VVZzKVxuICB0aGlzLnRyaWFuZ2xlTm9ybWFscy51cGRhdGUodE5vcilcbiAgdGhpcy50cmlhbmdsZUlkcy51cGRhdGUobmV3IFVpbnQzMkFycmF5KHRJZHMpKVxufVxuXG5wcm90by5kcmF3VHJhbnNwYXJlbnQgPSBwcm90by5kcmF3ID0gZnVuY3Rpb24ocGFyYW1zKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fVxuICB2YXIgZ2wgICAgICAgICAgPSB0aGlzLmdsXG4gIHZhciBtb2RlbCAgICAgICA9IHBhcmFtcy5tb2RlbCAgICAgIHx8IElERU5USVRZXG4gIHZhciB2aWV3ICAgICAgICA9IHBhcmFtcy52aWV3ICAgICAgIHx8IElERU5USVRZXG4gIHZhciBwcm9qZWN0aW9uICA9IHBhcmFtcy5wcm9qZWN0aW9uIHx8IElERU5USVRZXG5cbiAgdmFyIGNsaXBCb3VuZHMgPSBbWy0xZTYsLTFlNiwtMWU2XSxbMWU2LDFlNiwxZTZdXVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICBjbGlwQm91bmRzWzBdW2ldID0gTWF0aC5tYXgoY2xpcEJvdW5kc1swXVtpXSwgdGhpcy5jbGlwQm91bmRzWzBdW2ldKVxuICAgIGNsaXBCb3VuZHNbMV1baV0gPSBNYXRoLm1pbihjbGlwQm91bmRzWzFdW2ldLCB0aGlzLmNsaXBCb3VuZHNbMV1baV0pXG4gIH1cblxuICB2YXIgdW5pZm9ybXMgPSB7XG4gICAgbW9kZWw6ICAgICAgbW9kZWwsXG4gICAgdmlldzogICAgICAgdmlldyxcbiAgICBwcm9qZWN0aW9uOiBwcm9qZWN0aW9uLFxuICAgIGludmVyc2VNb2RlbDogSURFTlRJVFkuc2xpY2UoKSxcblxuICAgIGNsaXBCb3VuZHM6IGNsaXBCb3VuZHMsXG5cbiAgICBrYW1iaWVudDogICB0aGlzLmFtYmllbnRMaWdodCxcbiAgICBrZGlmZnVzZTogICB0aGlzLmRpZmZ1c2VMaWdodCxcbiAgICBrc3BlY3VsYXI6ICB0aGlzLnNwZWN1bGFyTGlnaHQsXG4gICAgcm91Z2huZXNzOiAgdGhpcy5yb3VnaG5lc3MsXG4gICAgZnJlc25lbDogICAgdGhpcy5mcmVzbmVsLFxuXG4gICAgZXllUG9zaXRpb246ICAgWzAsMCwwXSxcbiAgICBsaWdodFBvc2l0aW9uOiBbMCwwLDBdLFxuXG4gICAgb3BhY2l0eTogIHRoaXMub3BhY2l0eSxcblxuICAgIHZlY3RvclNjYWxlOiB0aGlzLnZlY3RvclNjYWxlLFxuICAgIGNvbmVTY2FsZTogdGhpcy5jb25lU2NhbGUsXG4gICAgY29uZU9mZnNldDogdGhpcy5jb25lT2Zmc2V0LFxuXG4gICAgY29udG91ckNvbG9yOiB0aGlzLmNvbnRvdXJDb2xvcixcblxuICAgIHRleHR1cmU6ICAgIDBcbiAgfVxuXG4gIHVuaWZvcm1zLmludmVyc2VNb2RlbCA9IGludmVydCh1bmlmb3Jtcy5pbnZlcnNlTW9kZWwsIHVuaWZvcm1zLm1vZGVsKVxuXG4gIGdsLmRpc2FibGUoZ2wuQ1VMTF9GQUNFKVxuXG4gIHRoaXMudGV4dHVyZS5iaW5kKDApXG5cbiAgdmFyIGludkNhbWVyYU1hdHJpeCA9IG5ldyBBcnJheSgxNilcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy52aWV3LCB1bmlmb3Jtcy5tb2RlbClcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy5wcm9qZWN0aW9uLCBpbnZDYW1lcmFNYXRyaXgpXG4gIGludmVydChpbnZDYW1lcmFNYXRyaXgsIGludkNhbWVyYU1hdHJpeClcblxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICB1bmlmb3Jtcy5leWVQb3NpdGlvbltpXSA9IGludkNhbWVyYU1hdHJpeFsxMitpXSAvIGludkNhbWVyYU1hdHJpeFsxNV1cbiAgfVxuXG4gIHZhciB3ID0gaW52Q2FtZXJhTWF0cml4WzE1XVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICB3ICs9IHRoaXMubGlnaHRQb3NpdGlvbltpXSAqIGludkNhbWVyYU1hdHJpeFs0KmkrM11cbiAgfVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICB2YXIgcyA9IGludkNhbWVyYU1hdHJpeFsxMitpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgcyArPSBpbnZDYW1lcmFNYXRyaXhbNCpqK2ldICogdGhpcy5saWdodFBvc2l0aW9uW2pdXG4gICAgfVxuICAgIHVuaWZvcm1zLmxpZ2h0UG9zaXRpb25baV0gPSBzIC8gd1xuICB9XG5cbiAgaWYodGhpcy50cmlhbmdsZUNvdW50ID4gMCkge1xuICAgIHZhciBzaGFkZXIgPSB0aGlzLnRyaVNoYWRlclxuICAgIHNoYWRlci5iaW5kKClcbiAgICBzaGFkZXIudW5pZm9ybXMgPSB1bmlmb3Jtc1xuXG4gICAgdGhpcy50cmlhbmdsZVZBTy5iaW5kKClcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgdGhpcy50cmlhbmdsZUNvdW50KjMpXG4gICAgdGhpcy50cmlhbmdsZVZBTy51bmJpbmQoKVxuICB9XG59XG5wcm90by5kcmF3UGljayA9IGZ1bmN0aW9uKHBhcmFtcykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge31cblxuICB2YXIgZ2wgICAgICAgICA9IHRoaXMuZ2xcblxuICB2YXIgbW9kZWwgICAgICA9IHBhcmFtcy5tb2RlbCAgICAgIHx8IElERU5USVRZXG4gIHZhciB2aWV3ICAgICAgID0gcGFyYW1zLnZpZXcgICAgICAgfHwgSURFTlRJVFlcbiAgdmFyIHByb2plY3Rpb24gPSBwYXJhbXMucHJvamVjdGlvbiB8fCBJREVOVElUWVxuXG4gIHZhciBjbGlwQm91bmRzID0gW1stMWU2LC0xZTYsLTFlNl0sWzFlNiwxZTYsMWU2XV1cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgY2xpcEJvdW5kc1swXVtpXSA9IE1hdGgubWF4KGNsaXBCb3VuZHNbMF1baV0sIHRoaXMuY2xpcEJvdW5kc1swXVtpXSlcbiAgICBjbGlwQm91bmRzWzFdW2ldID0gTWF0aC5taW4oY2xpcEJvdW5kc1sxXVtpXSwgdGhpcy5jbGlwQm91bmRzWzFdW2ldKVxuICB9XG5cbiAgLy9TYXZlIGNhbWVyYSBwYXJhbWV0ZXJzXG4gIHRoaXMuX21vZGVsICAgICAgPSBbXS5zbGljZS5jYWxsKG1vZGVsKVxuICB0aGlzLl92aWV3ICAgICAgID0gW10uc2xpY2UuY2FsbCh2aWV3KVxuICB0aGlzLl9wcm9qZWN0aW9uID0gW10uc2xpY2UuY2FsbChwcm9qZWN0aW9uKVxuICB0aGlzLl9yZXNvbHV0aW9uID0gW2dsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF1cblxuICB2YXIgdW5pZm9ybXMgPSB7XG4gICAgbW9kZWw6ICAgICAgbW9kZWwsXG4gICAgdmlldzogICAgICAgdmlldyxcbiAgICBwcm9qZWN0aW9uOiBwcm9qZWN0aW9uLFxuICAgIGNsaXBCb3VuZHM6IGNsaXBCb3VuZHMsXG5cbiAgICB2ZWN0b3JTY2FsZTogdGhpcy52ZWN0b3JTY2FsZSxcbiAgICBjb25lU2NhbGU6IHRoaXMuY29uZVNjYWxlLFxuICAgIGNvbmVPZmZzZXQ6IHRoaXMuY29uZU9mZnNldCxcblxuICAgIHBpY2tJZDogICAgIHRoaXMucGlja0lkIC8gMjU1LjAsXG4gIH1cblxuICB2YXIgc2hhZGVyID0gdGhpcy5waWNrU2hhZGVyXG4gIHNoYWRlci5iaW5kKClcbiAgc2hhZGVyLnVuaWZvcm1zID0gdW5pZm9ybXNcblxuICBpZih0aGlzLnRyaWFuZ2xlQ291bnQgPiAwKSB7XG4gICAgdGhpcy50cmlhbmdsZVZBTy5iaW5kKClcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgdGhpcy50cmlhbmdsZUNvdW50KjMpXG4gICAgdGhpcy50cmlhbmdsZVZBTy51bmJpbmQoKVxuICB9XG5cbiAgaWYodGhpcy5lZGdlQ291bnQgPiAwKSB7XG4gICAgdGhpcy5lZGdlVkFPLmJpbmQoKVxuICAgIGdsLmxpbmVXaWR0aCh0aGlzLmxpbmVXaWR0aCAqIHRoaXMucGl4ZWxSYXRpbylcbiAgICBnbC5kcmF3QXJyYXlzKGdsLkxJTkVTLCAwLCB0aGlzLmVkZ2VDb3VudCoyKVxuICAgIHRoaXMuZWRnZVZBTy51bmJpbmQoKVxuICB9XG5cbn1cblxuXG5wcm90by5waWNrID0gZnVuY3Rpb24ocGlja0RhdGEpIHtcbiAgaWYoIXBpY2tEYXRhKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICBpZihwaWNrRGF0YS5pZCAhPT0gdGhpcy5waWNrSWQpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgdmFyIGNlbGxJZCAgICA9IHBpY2tEYXRhLnZhbHVlWzBdICsgMjU2KnBpY2tEYXRhLnZhbHVlWzFdICsgNjU1MzYqcGlja0RhdGEudmFsdWVbMl1cbiAgdmFyIGNlbGwgICAgICA9IHRoaXMuY2VsbHNbY2VsbElkXVxuICB2YXIgcG9zID0gICAgIHRoaXMucG9zaXRpb25zW2NlbGxbMV1dLnNsaWNlKDAsIDMpXG5cbiAgcmV0dXJuIHtcbiAgICAvLyBjb3JyZXNwb25kaW5nIHRvIGlucHV0IGluZGljZXNcbiAgICBpbmRleDogTWF0aC5mbG9vcihjZWxsWzFdIC8gNDgpLFxuICAgIHBvc2l0aW9uOiBwb3MsXG4gICAgZGF0YUNvb3JkaW5hdGU6IHBvc1xuICB9XG59XG5cblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnRleHR1cmUuZGlzcG9zZSgpXG5cbiAgdGhpcy50cmlTaGFkZXIuZGlzcG9zZSgpXG4gIHRoaXMucGlja1NoYWRlci5kaXNwb3NlKClcblxuICB0aGlzLnRyaWFuZ2xlVkFPLmRpc3Bvc2UoKVxuICB0aGlzLnRyaWFuZ2xlUG9zaXRpb25zLmRpc3Bvc2UoKVxuICB0aGlzLnRyaWFuZ2xlVmVjdG9ycy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZUNvbG9ycy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZVVWcy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZU5vcm1hbHMuZGlzcG9zZSgpXG4gIHRoaXMudHJpYW5nbGVJZHMuZGlzcG9zZSgpXG5cbiAgdGhpcy5lZGdlVkFPLmRpc3Bvc2UoKVxuICB0aGlzLmVkZ2VQb3NpdGlvbnMuZGlzcG9zZSgpXG4gIHRoaXMuZWRnZUNvbG9ycy5kaXNwb3NlKClcbiAgdGhpcy5lZGdlVVZzLmRpc3Bvc2UoKVxuICB0aGlzLmVkZ2VJZHMuZGlzcG9zZSgpXG5cbiAgdGhpcy5wb2ludFZBTy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFBvc2l0aW9ucy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludENvbG9ycy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFVWcy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFNpemVzLmRpc3Bvc2UoKVxuICB0aGlzLnBvaW50SWRzLmRpc3Bvc2UoKVxuXG4gIHRoaXMuY29udG91clZBTy5kaXNwb3NlKClcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zLmRpc3Bvc2UoKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVNZXNoU2hhZGVyKGdsKSB7XG4gIC8vIG5lZWQgdG8gcGFzcyBtZXNoU2hhZGVyIGF0dHJpYnV0ZXMgbWFudWFsbHksXG4gIC8vIHRvIG1ha2UgdGhpcyB3b3JrIG9uIGV0cGluYXJkJ3MgVWJ1bnR1IFRoaW5rcGFkXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIG1lc2hTaGFkZXIudmVydGV4LCBtZXNoU2hhZGVyLmZyYWdtZW50LCBudWxsLCBtZXNoU2hhZGVyLmF0dHJpYnV0ZXMpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiAgICA9IDJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMudXYubG9jYXRpb24gICAgICAgPSAzXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnZlY3Rvci5sb2NhdGlvbiAgID0gNVxuICByZXR1cm4gc2hhZGVyXG59XG5cblxuZnVuY3Rpb24gY3JlYXRlUGlja1NoYWRlcihnbCkge1xuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBwaWNrU2hhZGVyLnZlcnRleCwgcGlja1NoYWRlci5mcmFnbWVudCwgbnVsbCwgcGlja1NoYWRlci5hdHRyaWJ1dGVzKVxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuaWQubG9jYXRpb24gICAgICAgPSAxXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnZlY3Rvci5sb2NhdGlvbiAgID0gNVxuICByZXR1cm4gc2hhZGVyXG59XG5cblxuXG5mdW5jdGlvbiBjcmVhdGVTaW1wbGljaWFsTWVzaChnbCwgcGFyYW1zKSB7XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgcGFyYW1zID0gZ2w7XG4gICAgZ2wgPSBwYXJhbXMuZ2w7XG4gIH1cblxuXG4gIHZhciB0cmlTaGFkZXIgICAgICAgPSBwYXJhbXMudHJpU2hhZGVyIHx8IGNyZWF0ZU1lc2hTaGFkZXIoZ2wpXG4gIHZhciBwaWNrU2hhZGVyICAgICAgPSBjcmVhdGVQaWNrU2hhZGVyKGdsKVxuICB2YXIgbWVzaFRleHR1cmUgICAgICAgPSBjcmVhdGVUZXh0dXJlKGdsLFxuICAgIG5kYXJyYXkobmV3IFVpbnQ4QXJyYXkoWzI1NSwyNTUsMjU1LDI1NV0pLCBbMSwxLDRdKSlcbiAgbWVzaFRleHR1cmUuZ2VuZXJhdGVNaXBtYXAoKVxuICBtZXNoVGV4dHVyZS5taW5GaWx0ZXIgPSBnbC5MSU5FQVJfTUlQTUFQX0xJTkVBUlxuICBtZXNoVGV4dHVyZS5tYWdGaWx0ZXIgPSBnbC5MSU5FQVJcblxuICB2YXIgdHJpYW5nbGVQb3NpdGlvbnMgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciB0cmlhbmdsZVZlY3RvcnMgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHRyaWFuZ2xlQ29sb3JzICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgdHJpYW5nbGVVVnMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciB0cmlhbmdsZU5vcm1hbHMgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHRyaWFuZ2xlSWRzICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgdHJpYW5nbGVWQU8gICAgICAgPSBjcmVhdGVWQU8oZ2wsIFtcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVQb3NpdGlvbnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDRcbiAgICB9LFxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZUlkcyxcbiAgICAgIHR5cGU6IGdsLlVOU0lHTkVEX0JZVEUsXG4gICAgICBzaXplOiA0LFxuICAgICAgbm9ybWFsaXplZDogdHJ1ZVxuICAgIH0sXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlQ29sb3JzLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiA0XG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVVVnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDJcbiAgICB9LFxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZU5vcm1hbHMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDNcbiAgICB9LFxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZVZlY3RvcnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDNcbiAgICB9XG4gIF0pXG5cbiAgdmFyIGVkZ2VQb3NpdGlvbnMgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBlZGdlQ29sb3JzICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgZWRnZVVWcyAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIGVkZ2VJZHMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBlZGdlVkFPICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXG4gICAgeyBidWZmZXI6IGVkZ2VQb3NpdGlvbnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDNcbiAgICB9LFxuICAgIHsgYnVmZmVyOiBlZGdlSWRzLFxuICAgICAgdHlwZTogZ2wuVU5TSUdORURfQllURSxcbiAgICAgIHNpemU6IDQsXG4gICAgICBub3JtYWxpemVkOiB0cnVlXG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogZWRnZUNvbG9ycyxcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxuICAgICAgc2l6ZTogNFxuICAgIH0sXG4gICAgeyBidWZmZXI6IGVkZ2VVVnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDJcbiAgICB9XG4gIF0pXG5cbiAgdmFyIHBvaW50UG9zaXRpb25zICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50Q29sb3JzICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50VVZzICAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50U2l6ZXMgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50SWRzICAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50VkFPICAgICAgICA9IGNyZWF0ZVZBTyhnbCwgW1xuICAgIHsgYnVmZmVyOiBwb2ludFBvc2l0aW9ucyxcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxuICAgICAgc2l6ZTogM1xuICAgIH0sXG4gICAgeyBidWZmZXI6IHBvaW50SWRzLFxuICAgICAgdHlwZTogZ2wuVU5TSUdORURfQllURSxcbiAgICAgIHNpemU6IDQsXG4gICAgICBub3JtYWxpemVkOiB0cnVlXG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogcG9pbnRDb2xvcnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDRcbiAgICB9LFxuICAgIHsgYnVmZmVyOiBwb2ludFVWcyxcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxuICAgICAgc2l6ZTogMlxuICAgIH0sXG4gICAgeyBidWZmZXI6IHBvaW50U2l6ZXMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDFcbiAgICB9XG4gIF0pXG5cbiAgdmFyIGNvbnRvdXJQb3NpdGlvbnMgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBjb250b3VyVkFPICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXG4gICAgeyBidWZmZXI6IGNvbnRvdXJQb3NpdGlvbnMsXG4gICAgICB0eXBlOiAgIGdsLkZMT0FULFxuICAgICAgc2l6ZTogICAzXG4gICAgfV0pXG5cbiAgdmFyIG1lc2ggPSBuZXcgU2ltcGxpY2lhbE1lc2goZ2xcbiAgICAsIG1lc2hUZXh0dXJlXG4gICAgLCB0cmlTaGFkZXJcbiAgICAsIHBpY2tTaGFkZXJcbiAgICAsIHRyaWFuZ2xlUG9zaXRpb25zXG4gICAgLCB0cmlhbmdsZVZlY3RvcnNcbiAgICAsIHRyaWFuZ2xlSWRzXG4gICAgLCB0cmlhbmdsZUNvbG9yc1xuICAgICwgdHJpYW5nbGVVVnNcbiAgICAsIHRyaWFuZ2xlTm9ybWFsc1xuICAgICwgdHJpYW5nbGVWQU9cbiAgICAsIGVkZ2VQb3NpdGlvbnNcbiAgICAsIGVkZ2VJZHNcbiAgICAsIGVkZ2VDb2xvcnNcbiAgICAsIGVkZ2VVVnNcbiAgICAsIGVkZ2VWQU9cbiAgICAsIHBvaW50UG9zaXRpb25zXG4gICAgLCBwb2ludElkc1xuICAgICwgcG9pbnRDb2xvcnNcbiAgICAsIHBvaW50VVZzXG4gICAgLCBwb2ludFNpemVzXG4gICAgLCBwb2ludFZBT1xuICAgICwgY29udG91clBvc2l0aW9uc1xuICAgICwgY29udG91clZBTylcblxuICBtZXNoLnVwZGF0ZShwYXJhbXMpXG5cbiAgcmV0dXJuIG1lc2hcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTaW1wbGljaWFsTWVzaFxuXG59LHtcIi4vc2hhZGVyc1wiOjI0NCxcImNvbG9ybWFwXCI6MTI2LFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtbWF0NC9pbnZlcnRcIjoyNjUsXCJnbC1tYXQ0L211bHRpcGx5XCI6MjY3LFwiZ2wtc2hhZGVyXCI6MzAxLFwiZ2wtdGV4dHVyZTJkXCI6MzIyLFwiZ2wtdmFvXCI6MzI3LFwibmRhcnJheVwiOjQ1MCxcIm5vcm1hbHNcIjo0NTMsXCJzaW1wbGljaWFsLWNvbXBsZXgtY29udG91clwiOjUxOCxcInR5cGVkYXJyYXktcG9vbFwiOjU0NX1dLDI0NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG52YXIgZ2xzbGlmeSAgICAgICA9IF9kZXJlcV8oJ2dsc2xpZnknKVxuXG52YXIgdHJpVmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcblxcbnByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnZlYzMgZ2V0T3J0aG9nb25hbFZlY3Rvcih2ZWMzIHYpIHtcXG4gIC8vIFJldHVybiB1cC12ZWN0b3IgZm9yIG9ubHkteiB2ZWN0b3IuXFxuICAvLyBSZXR1cm4gYXggKyBieSArIGN6ID0gMCwgYSBwb2ludCB0aGF0IGxpZXMgb24gdGhlIHBsYW5lIHRoYXQgaGFzIHYgYXMgYSBub3JtYWwgYW5kIHRoYXQgaXNuJ3QgKDAsMCwwKS5cXG4gIC8vIEZyb20gdGhlIGFib3ZlIGlmLXN0YXRlbWVudCB3ZSBoYXZlIHx8YXx8ID4gMCAgVSAgfHxifHwgPiAwLlxcbiAgLy8gQXNzaWduIHogPSAwLCB4ID0gLWIsIHkgPSBhOlxcbiAgLy8gYSotYiArIGIqYSArIGMqMCA9IC1iYSArIGJhICsgMCA9IDBcXG4gIGlmICh2Lngqdi54ID4gdi56KnYueiB8fCB2Lnkqdi55ID4gdi56KnYueikge1xcbiAgICByZXR1cm4gbm9ybWFsaXplKHZlYzMoLXYueSwgdi54LCAwLjApKTtcXG4gIH0gZWxzZSB7XFxuICAgIHJldHVybiBub3JtYWxpemUodmVjMygwLjAsIHYueiwgLXYueSkpO1xcbiAgfVxcbn1cXG5cXG4vLyBDYWxjdWxhdGUgdGhlIGNvbmUgdmVydGV4IGFuZCBub3JtYWwgYXQgdGhlIGdpdmVuIGluZGV4Llxcbi8vXFxuLy8gVGhlIHJldHVybmVkIHZlcnRleCBpcyBmb3IgYSBjb25lIHdpdGggaXRzIHRvcCBhdCBvcmlnaW4gYW5kIGhlaWdodCBvZiAxLjAsXFxuLy8gcG9pbnRpbmcgaW4gdGhlIGRpcmVjdGlvbiBvZiB0aGUgdmVjdG9yIGF0dHJpYnV0ZS5cXG4vL1xcbi8vIEVhY2ggY29uZSBpcyBtYWRlIHVwIG9mIGEgdG9wIHZlcnRleCwgYSBjZW50ZXIgYmFzZSB2ZXJ0ZXggYW5kIGJhc2UgcGVyaW1ldGVyIHZlcnRpY2VzLlxcbi8vIFRoZXNlIHZlcnRpY2VzIGFyZSB1c2VkIHRvIG1ha2UgdXAgdGhlIHRyaWFuZ2xlcyBvZiB0aGUgY29uZSBieSB0aGUgZm9sbG93aW5nOlxcbi8vICAgc2VnbWVudCArIDAgdG9wIHZlcnRleFxcbi8vICAgc2VnbWVudCArIDEgcGVyaW1ldGVyIHZlcnRleCBhKzFcXG4vLyAgIHNlZ21lbnQgKyAyIHBlcmltZXRlciB2ZXJ0ZXggYVxcbi8vICAgc2VnbWVudCArIDMgY2VudGVyIGJhc2UgdmVydGV4XFxuLy8gICBzZWdtZW50ICsgNCBwZXJpbWV0ZXIgdmVydGV4IGFcXG4vLyAgIHNlZ21lbnQgKyA1IHBlcmltZXRlciB2ZXJ0ZXggYSsxXFxuLy8gV2hlcmUgc2VnbWVudCBpcyB0aGUgbnVtYmVyIG9mIHRoZSByYWRpYWwgc2VnbWVudCAqIDYgYW5kIGEgaXMgdGhlIGFuZ2xlIGF0IHRoYXQgcmFkaWFsIHNlZ21lbnQuXFxuLy8gVG8gZ28gZnJvbSBpbmRleCB0byBzZWdtZW50LCBmbG9vcihpbmRleCAvIDYpXFxuLy8gVG8gZ28gZnJvbSBzZWdtZW50IHRvIGFuZ2xlLCAyKnBpICogKHNlZ21lbnQvc2VnbWVudENvdW50KVxcbi8vIFRvIGdvIGZyb20gaW5kZXggdG8gc2VnbWVudCBpbmRleCwgaW5kZXggLSAoc2VnbWVudCo2KVxcbi8vXFxudmVjMyBnZXRDb25lUG9zaXRpb24odmVjMyBkLCBmbG9hdCByYXdJbmRleCwgZmxvYXQgY29uZU9mZnNldCwgb3V0IHZlYzMgbm9ybWFsKSB7XFxuXFxuICBjb25zdCBmbG9hdCBzZWdtZW50Q291bnQgPSA4LjA7XFxuXFxuICBmbG9hdCBpbmRleCA9IHJhd0luZGV4IC0gZmxvb3IocmF3SW5kZXggL1xcbiAgICAoc2VnbWVudENvdW50ICogNi4wKSkgKlxcbiAgICAoc2VnbWVudENvdW50ICogNi4wKTtcXG5cXG4gIGZsb2F0IHNlZ21lbnQgPSBmbG9vcigwLjAwMSArIGluZGV4LzYuMCk7XFxuICBmbG9hdCBzZWdtZW50SW5kZXggPSBpbmRleCAtIChzZWdtZW50KjYuMCk7XFxuXFxuICBub3JtYWwgPSAtbm9ybWFsaXplKGQpO1xcblxcbiAgaWYgKHNlZ21lbnRJbmRleCA+IDIuOTkgJiYgc2VnbWVudEluZGV4IDwgMy4wMSkge1xcbiAgICByZXR1cm4gbWl4KHZlYzMoMC4wKSwgLWQsIGNvbmVPZmZzZXQpO1xcbiAgfVxcblxcbiAgZmxvYXQgbmV4dEFuZ2xlID0gKFxcbiAgICAoc2VnbWVudEluZGV4ID4gMC45OSAmJiAgc2VnbWVudEluZGV4IDwgMS4wMSkgfHxcXG4gICAgKHNlZ21lbnRJbmRleCA+IDQuOTkgJiYgIHNlZ21lbnRJbmRleCA8IDUuMDEpXFxuICApID8gMS4wIDogMC4wO1xcbiAgZmxvYXQgYW5nbGUgPSAyLjAgKiAzLjE0MTU5ICogKChzZWdtZW50ICsgbmV4dEFuZ2xlKSAvIHNlZ21lbnRDb3VudCk7XFxuXFxuICB2ZWMzIHYxID0gbWl4KGQsIHZlYzMoMC4wKSwgY29uZU9mZnNldCk7XFxuICB2ZWMzIHYyID0gdjEgLSBkO1xcblxcbiAgdmVjMyB1ID0gZ2V0T3J0aG9nb25hbFZlY3RvcihkKTtcXG4gIHZlYzMgdiA9IG5vcm1hbGl6ZShjcm9zcyh1LCBkKSk7XFxuXFxuICB2ZWMzIHggPSB1ICogY29zKGFuZ2xlKSAqIGxlbmd0aChkKSowLjI1O1xcbiAgdmVjMyB5ID0gdiAqIHNpbihhbmdsZSkgKiBsZW5ndGgoZCkqMC4yNTtcXG4gIHZlYzMgdjMgPSB2MiArIHggKyB5O1xcbiAgaWYgKHNlZ21lbnRJbmRleCA8IDMuMCkge1xcbiAgICB2ZWMzIHR4ID0gdSAqIHNpbihhbmdsZSk7XFxuICAgIHZlYzMgdHkgPSB2ICogLWNvcyhhbmdsZSk7XFxuICAgIHZlYzMgdGFuZ2VudCA9IHR4ICsgdHk7XFxuICAgIG5vcm1hbCA9IG5vcm1hbGl6ZShjcm9zcyh2MyAtIHYxLCB0YW5nZW50KSk7XFxuICB9XFxuXFxuICBpZiAoc2VnbWVudEluZGV4ID09IDAuMCkge1xcbiAgICByZXR1cm4gbWl4KGQsIHZlYzMoMC4wKSwgY29uZU9mZnNldCk7XFxuICB9XFxuICByZXR1cm4gdjM7XFxufVxcblxcbmF0dHJpYnV0ZSB2ZWMzIHZlY3RvcjtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvciwgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzIgdXY7XFxudW5pZm9ybSBmbG9hdCB2ZWN0b3JTY2FsZTtcXG51bmlmb3JtIGZsb2F0IGNvbmVTY2FsZTtcXG5cXG51bmlmb3JtIGZsb2F0IGNvbmVPZmZzZXQ7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsXFxuICAgICAgICAgICAsIHZpZXdcXG4gICAgICAgICAgICwgcHJvamVjdGlvblxcbiAgICAgICAgICAgLCBpbnZlcnNlTW9kZWw7XFxudW5pZm9ybSB2ZWMzIGV5ZVBvc2l0aW9uXFxuICAgICAgICAgICAsIGxpZ2h0UG9zaXRpb247XFxuXFxudmFyeWluZyB2ZWMzIGZfbm9ybWFsXFxuICAgICAgICAgICAsIGZfbGlnaHREaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9leWVEaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9kYXRhXFxuICAgICAgICAgICAsIGZfcG9zaXRpb247XFxudmFyeWluZyB2ZWM0IGZfY29sb3I7XFxudmFyeWluZyB2ZWMyIGZfdXY7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgLy8gU2NhbGUgdGhlIHZlY3RvciBtYWduaXR1ZGUgdG8gc3RheSBjb25zdGFudCB3aXRoXFxuICAvLyBtb2RlbCAmIHZpZXcgY2hhbmdlcy5cXG4gIHZlYzMgbm9ybWFsO1xcbiAgdmVjMyBYWVogPSBnZXRDb25lUG9zaXRpb24obWF0Myhtb2RlbCkgKiAoKHZlY3RvclNjYWxlICogY29uZVNjYWxlKSAqIHZlY3RvciksIHBvc2l0aW9uLncsIGNvbmVPZmZzZXQsIG5vcm1hbCk7XFxuICB2ZWM0IGNvbmVQb3NpdGlvbiA9IG1vZGVsICogdmVjNChwb3NpdGlvbi54eXosIDEuMCkgKyB2ZWM0KFhZWiwgMC4wKTtcXG5cXG4gIC8vTGlnaHRpbmcgZ2VvbWV0cnkgcGFyYW1ldGVyc1xcbiAgdmVjNCBjYW1lcmFDb29yZGluYXRlID0gdmlldyAqIGNvbmVQb3NpdGlvbjtcXG4gIGNhbWVyYUNvb3JkaW5hdGUueHl6IC89IGNhbWVyYUNvb3JkaW5hdGUudztcXG4gIGZfbGlnaHREaXJlY3Rpb24gPSBsaWdodFBvc2l0aW9uIC0gY2FtZXJhQ29vcmRpbmF0ZS54eXo7XFxuICBmX2V5ZURpcmVjdGlvbiAgID0gZXllUG9zaXRpb24gLSBjYW1lcmFDb29yZGluYXRlLnh5ejtcXG4gIGZfbm9ybWFsID0gbm9ybWFsaXplKCh2ZWM0KG5vcm1hbCwwLjApICogaW52ZXJzZU1vZGVsKS54eXopO1xcblxcbiAgLy8gdmVjNCBtX3Bvc2l0aW9uICA9IG1vZGVsICogdmVjNChjb25lUG9zaXRpb24sIDEuMCk7XFxuICB2ZWM0IHRfcG9zaXRpb24gID0gdmlldyAqIGNvbmVQb3NpdGlvbjtcXG4gIGdsX1Bvc2l0aW9uICAgICAgPSBwcm9qZWN0aW9uICogdF9wb3NpdGlvbjtcXG5cXG4gIGZfY29sb3IgICAgICAgICAgPSBjb2xvcjtcXG4gIGZfZGF0YSAgICAgICAgICAgPSBjb25lUG9zaXRpb24ueHl6O1xcbiAgZl9wb3NpdGlvbiAgICAgICA9IHBvc2l0aW9uLnh5ejtcXG4gIGZfdXYgICAgICAgICAgICAgPSB1djtcXG59XFxuXCJdKVxudmFyIHRyaUZyYWdTcmMgPSBnbHNsaWZ5KFtcIiNleHRlbnNpb24gR0xfT0VTX3N0YW5kYXJkX2Rlcml2YXRpdmVzIDogZW5hYmxlXFxuXFxucHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuZmxvYXQgYmVja21hbm5EaXN0cmlidXRpb24oZmxvYXQgeCwgZmxvYXQgcm91Z2huZXNzKSB7XFxuICBmbG9hdCBOZG90SCA9IG1heCh4LCAwLjAwMDEpO1xcbiAgZmxvYXQgY29zMkFscGhhID0gTmRvdEggKiBOZG90SDtcXG4gIGZsb2F0IHRhbjJBbHBoYSA9IChjb3MyQWxwaGEgLSAxLjApIC8gY29zMkFscGhhO1xcbiAgZmxvYXQgcm91Z2huZXNzMiA9IHJvdWdobmVzcyAqIHJvdWdobmVzcztcXG4gIGZsb2F0IGRlbm9tID0gMy4xNDE1OTI2NTM1ODk3OTMgKiByb3VnaG5lc3MyICogY29zMkFscGhhICogY29zMkFscGhhO1xcbiAgcmV0dXJuIGV4cCh0YW4yQWxwaGEgLyByb3VnaG5lc3MyKSAvIGRlbm9tO1xcbn1cXG5cXG5mbG9hdCBjb29rVG9ycmFuY2VTcGVjdWxhcihcXG4gIHZlYzMgbGlnaHREaXJlY3Rpb24sXFxuICB2ZWMzIHZpZXdEaXJlY3Rpb24sXFxuICB2ZWMzIHN1cmZhY2VOb3JtYWwsXFxuICBmbG9hdCByb3VnaG5lc3MsXFxuICBmbG9hdCBmcmVzbmVsKSB7XFxuXFxuICBmbG9hdCBWZG90TiA9IG1heChkb3Qodmlld0RpcmVjdGlvbiwgc3VyZmFjZU5vcm1hbCksIDAuMCk7XFxuICBmbG9hdCBMZG90TiA9IG1heChkb3QobGlnaHREaXJlY3Rpb24sIHN1cmZhY2VOb3JtYWwpLCAwLjApO1xcblxcbiAgLy9IYWxmIGFuZ2xlIHZlY3RvclxcbiAgdmVjMyBIID0gbm9ybWFsaXplKGxpZ2h0RGlyZWN0aW9uICsgdmlld0RpcmVjdGlvbik7XFxuXFxuICAvL0dlb21ldHJpYyB0ZXJtXFxuICBmbG9hdCBOZG90SCA9IG1heChkb3Qoc3VyZmFjZU5vcm1hbCwgSCksIDAuMCk7XFxuICBmbG9hdCBWZG90SCA9IG1heChkb3Qodmlld0RpcmVjdGlvbiwgSCksIDAuMDAwMDAxKTtcXG4gIGZsb2F0IExkb3RIID0gbWF4KGRvdChsaWdodERpcmVjdGlvbiwgSCksIDAuMDAwMDAxKTtcXG4gIGZsb2F0IEcxID0gKDIuMCAqIE5kb3RIICogVmRvdE4pIC8gVmRvdEg7XFxuICBmbG9hdCBHMiA9ICgyLjAgKiBOZG90SCAqIExkb3ROKSAvIExkb3RIO1xcbiAgZmxvYXQgRyA9IG1pbigxLjAsIG1pbihHMSwgRzIpKTtcXG4gIFxcbiAgLy9EaXN0cmlidXRpb24gdGVybVxcbiAgZmxvYXQgRCA9IGJlY2ttYW5uRGlzdHJpYnV0aW9uKE5kb3RILCByb3VnaG5lc3MpO1xcblxcbiAgLy9GcmVzbmVsIHRlcm1cXG4gIGZsb2F0IEYgPSBwb3coMS4wIC0gVmRvdE4sIGZyZXNuZWwpO1xcblxcbiAgLy9NdWx0aXBseSB0ZXJtcyBhbmQgZG9uZVxcbiAgcmV0dXJuICBHICogRiAqIEQgLyBtYXgoMy4xNDE1OTI2NSAqIFZkb3ROLCAwLjAwMDAwMSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgcm91Z2huZXNzXFxuICAgICAgICAgICAgLCBmcmVzbmVsXFxuICAgICAgICAgICAgLCBrYW1iaWVudFxcbiAgICAgICAgICAgICwga2RpZmZ1c2VcXG4gICAgICAgICAgICAsIGtzcGVjdWxhclxcbiAgICAgICAgICAgICwgb3BhY2l0eTtcXG51bmlmb3JtIHNhbXBsZXIyRCB0ZXh0dXJlO1xcblxcbnZhcnlpbmcgdmVjMyBmX25vcm1hbFxcbiAgICAgICAgICAgLCBmX2xpZ2h0RGlyZWN0aW9uXFxuICAgICAgICAgICAsIGZfZXllRGlyZWN0aW9uXFxuICAgICAgICAgICAsIGZfZGF0YVxcbiAgICAgICAgICAgLCBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2NvbG9yO1xcbnZhcnlpbmcgdmVjMiBmX3V2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIGZfcG9zaXRpb24pKSBkaXNjYXJkO1xcbiAgdmVjMyBOID0gbm9ybWFsaXplKGZfbm9ybWFsKTtcXG4gIHZlYzMgTCA9IG5vcm1hbGl6ZShmX2xpZ2h0RGlyZWN0aW9uKTtcXG4gIHZlYzMgViA9IG5vcm1hbGl6ZShmX2V5ZURpcmVjdGlvbik7XFxuXFxuICBpZihnbF9Gcm9udEZhY2luZykge1xcbiAgICBOID0gLU47XFxuICB9XFxuXFxuICBmbG9hdCBzcGVjdWxhciA9IG1pbigxLjAsIG1heCgwLjAsIGNvb2tUb3JyYW5jZVNwZWN1bGFyKEwsIFYsIE4sIHJvdWdobmVzcywgZnJlc25lbCkpKTtcXG4gIGZsb2F0IGRpZmZ1c2UgID0gbWluKGthbWJpZW50ICsga2RpZmZ1c2UgKiBtYXgoZG90KE4sIEwpLCAwLjApLCAxLjApO1xcblxcbiAgdmVjNCBzdXJmYWNlQ29sb3IgPSBmX2NvbG9yICogdGV4dHVyZTJEKHRleHR1cmUsIGZfdXYpO1xcbiAgdmVjNCBsaXRDb2xvciA9IHN1cmZhY2VDb2xvci5hICogdmVjNChkaWZmdXNlICogc3VyZmFjZUNvbG9yLnJnYiArIGtzcGVjdWxhciAqIHZlYzMoMSwxLDEpICogc3BlY3VsYXIsICAxLjApO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gbGl0Q29sb3IgKiBvcGFjaXR5O1xcbn1cXG5cIl0pXG52YXIgcGlja1ZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG5cXG5wcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG52ZWMzIGdldE9ydGhvZ29uYWxWZWN0b3IodmVjMyB2KSB7XFxuICAvLyBSZXR1cm4gdXAtdmVjdG9yIGZvciBvbmx5LXogdmVjdG9yLlxcbiAgLy8gUmV0dXJuIGF4ICsgYnkgKyBjeiA9IDAsIGEgcG9pbnQgdGhhdCBsaWVzIG9uIHRoZSBwbGFuZSB0aGF0IGhhcyB2IGFzIGEgbm9ybWFsIGFuZCB0aGF0IGlzbid0ICgwLDAsMCkuXFxuICAvLyBGcm9tIHRoZSBhYm92ZSBpZi1zdGF0ZW1lbnQgd2UgaGF2ZSB8fGF8fCA+IDAgIFUgIHx8Ynx8ID4gMC5cXG4gIC8vIEFzc2lnbiB6ID0gMCwgeCA9IC1iLCB5ID0gYTpcXG4gIC8vIGEqLWIgKyBiKmEgKyBjKjAgPSAtYmEgKyBiYSArIDAgPSAwXFxuICBpZiAodi54KnYueCA+IHYueip2LnogfHwgdi55KnYueSA+IHYueip2LnopIHtcXG4gICAgcmV0dXJuIG5vcm1hbGl6ZSh2ZWMzKC12LnksIHYueCwgMC4wKSk7XFxuICB9IGVsc2Uge1xcbiAgICByZXR1cm4gbm9ybWFsaXplKHZlYzMoMC4wLCB2LnosIC12LnkpKTtcXG4gIH1cXG59XFxuXFxuLy8gQ2FsY3VsYXRlIHRoZSBjb25lIHZlcnRleCBhbmQgbm9ybWFsIGF0IHRoZSBnaXZlbiBpbmRleC5cXG4vL1xcbi8vIFRoZSByZXR1cm5lZCB2ZXJ0ZXggaXMgZm9yIGEgY29uZSB3aXRoIGl0cyB0b3AgYXQgb3JpZ2luIGFuZCBoZWlnaHQgb2YgMS4wLFxcbi8vIHBvaW50aW5nIGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIHZlY3RvciBhdHRyaWJ1dGUuXFxuLy9cXG4vLyBFYWNoIGNvbmUgaXMgbWFkZSB1cCBvZiBhIHRvcCB2ZXJ0ZXgsIGEgY2VudGVyIGJhc2UgdmVydGV4IGFuZCBiYXNlIHBlcmltZXRlciB2ZXJ0aWNlcy5cXG4vLyBUaGVzZSB2ZXJ0aWNlcyBhcmUgdXNlZCB0byBtYWtlIHVwIHRoZSB0cmlhbmdsZXMgb2YgdGhlIGNvbmUgYnkgdGhlIGZvbGxvd2luZzpcXG4vLyAgIHNlZ21lbnQgKyAwIHRvcCB2ZXJ0ZXhcXG4vLyAgIHNlZ21lbnQgKyAxIHBlcmltZXRlciB2ZXJ0ZXggYSsxXFxuLy8gICBzZWdtZW50ICsgMiBwZXJpbWV0ZXIgdmVydGV4IGFcXG4vLyAgIHNlZ21lbnQgKyAzIGNlbnRlciBiYXNlIHZlcnRleFxcbi8vICAgc2VnbWVudCArIDQgcGVyaW1ldGVyIHZlcnRleCBhXFxuLy8gICBzZWdtZW50ICsgNSBwZXJpbWV0ZXIgdmVydGV4IGErMVxcbi8vIFdoZXJlIHNlZ21lbnQgaXMgdGhlIG51bWJlciBvZiB0aGUgcmFkaWFsIHNlZ21lbnQgKiA2IGFuZCBhIGlzIHRoZSBhbmdsZSBhdCB0aGF0IHJhZGlhbCBzZWdtZW50Llxcbi8vIFRvIGdvIGZyb20gaW5kZXggdG8gc2VnbWVudCwgZmxvb3IoaW5kZXggLyA2KVxcbi8vIFRvIGdvIGZyb20gc2VnbWVudCB0byBhbmdsZSwgMipwaSAqIChzZWdtZW50L3NlZ21lbnRDb3VudClcXG4vLyBUbyBnbyBmcm9tIGluZGV4IHRvIHNlZ21lbnQgaW5kZXgsIGluZGV4IC0gKHNlZ21lbnQqNilcXG4vL1xcbnZlYzMgZ2V0Q29uZVBvc2l0aW9uKHZlYzMgZCwgZmxvYXQgcmF3SW5kZXgsIGZsb2F0IGNvbmVPZmZzZXQsIG91dCB2ZWMzIG5vcm1hbCkge1xcblxcbiAgY29uc3QgZmxvYXQgc2VnbWVudENvdW50ID0gOC4wO1xcblxcbiAgZmxvYXQgaW5kZXggPSByYXdJbmRleCAtIGZsb29yKHJhd0luZGV4IC9cXG4gICAgKHNlZ21lbnRDb3VudCAqIDYuMCkpICpcXG4gICAgKHNlZ21lbnRDb3VudCAqIDYuMCk7XFxuXFxuICBmbG9hdCBzZWdtZW50ID0gZmxvb3IoMC4wMDEgKyBpbmRleC82LjApO1xcbiAgZmxvYXQgc2VnbWVudEluZGV4ID0gaW5kZXggLSAoc2VnbWVudCo2LjApO1xcblxcbiAgbm9ybWFsID0gLW5vcm1hbGl6ZShkKTtcXG5cXG4gIGlmIChzZWdtZW50SW5kZXggPiAyLjk5ICYmIHNlZ21lbnRJbmRleCA8IDMuMDEpIHtcXG4gICAgcmV0dXJuIG1peCh2ZWMzKDAuMCksIC1kLCBjb25lT2Zmc2V0KTtcXG4gIH1cXG5cXG4gIGZsb2F0IG5leHRBbmdsZSA9IChcXG4gICAgKHNlZ21lbnRJbmRleCA+IDAuOTkgJiYgIHNlZ21lbnRJbmRleCA8IDEuMDEpIHx8XFxuICAgIChzZWdtZW50SW5kZXggPiA0Ljk5ICYmICBzZWdtZW50SW5kZXggPCA1LjAxKVxcbiAgKSA/IDEuMCA6IDAuMDtcXG4gIGZsb2F0IGFuZ2xlID0gMi4wICogMy4xNDE1OSAqICgoc2VnbWVudCArIG5leHRBbmdsZSkgLyBzZWdtZW50Q291bnQpO1xcblxcbiAgdmVjMyB2MSA9IG1peChkLCB2ZWMzKDAuMCksIGNvbmVPZmZzZXQpO1xcbiAgdmVjMyB2MiA9IHYxIC0gZDtcXG5cXG4gIHZlYzMgdSA9IGdldE9ydGhvZ29uYWxWZWN0b3IoZCk7XFxuICB2ZWMzIHYgPSBub3JtYWxpemUoY3Jvc3ModSwgZCkpO1xcblxcbiAgdmVjMyB4ID0gdSAqIGNvcyhhbmdsZSkgKiBsZW5ndGgoZCkqMC4yNTtcXG4gIHZlYzMgeSA9IHYgKiBzaW4oYW5nbGUpICogbGVuZ3RoKGQpKjAuMjU7XFxuICB2ZWMzIHYzID0gdjIgKyB4ICsgeTtcXG4gIGlmIChzZWdtZW50SW5kZXggPCAzLjApIHtcXG4gICAgdmVjMyB0eCA9IHUgKiBzaW4oYW5nbGUpO1xcbiAgICB2ZWMzIHR5ID0gdiAqIC1jb3MoYW5nbGUpO1xcbiAgICB2ZWMzIHRhbmdlbnQgPSB0eCArIHR5O1xcbiAgICBub3JtYWwgPSBub3JtYWxpemUoY3Jvc3ModjMgLSB2MSwgdGFuZ2VudCkpO1xcbiAgfVxcblxcbiAgaWYgKHNlZ21lbnRJbmRleCA9PSAwLjApIHtcXG4gICAgcmV0dXJuIG1peChkLCB2ZWMzKDAuMCksIGNvbmVPZmZzZXQpO1xcbiAgfVxcbiAgcmV0dXJuIHYzO1xcbn1cXG5cXG5hdHRyaWJ1dGUgdmVjMyB2ZWN0b3I7XFxuYXR0cmlidXRlIHZlYzQgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzQgaWQ7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcblxcbnVuaWZvcm0gZmxvYXQgdmVjdG9yU2NhbGU7XFxudW5pZm9ybSBmbG9hdCBjb25lU2NhbGU7XFxudW5pZm9ybSBmbG9hdCBjb25lT2Zmc2V0O1xcblxcbnZhcnlpbmcgdmVjMyBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzMgbm9ybWFsO1xcbiAgdmVjMyBYWVogPSBnZXRDb25lUG9zaXRpb24obWF0Myhtb2RlbCkgKiAoKHZlY3RvclNjYWxlICogY29uZVNjYWxlKSAqIHZlY3RvciksIHBvc2l0aW9uLncsIGNvbmVPZmZzZXQsIG5vcm1hbCk7XFxuICB2ZWM0IGNvbmVQb3NpdGlvbiA9IG1vZGVsICogdmVjNChwb3NpdGlvbi54eXosIDEuMCkgKyB2ZWM0KFhZWiwgMC4wKTtcXG4gIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiBjb25lUG9zaXRpb247XFxuICBmX2lkICAgICAgICA9IGlkO1xcbiAgZl9wb3NpdGlvbiAgPSBwb3NpdGlvbi54eXo7XFxufVxcblwiXSlcbnZhciBwaWNrRnJhZ1NyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzICBjbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgcGlja0lkO1xcblxcbnZhcnlpbmcgdmVjMyBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIGZfcG9zaXRpb24pKSBkaXNjYXJkO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gdmVjNChwaWNrSWQsIGZfaWQueHl6KTtcXG59XCJdKVxuXG5leHBvcnRzLm1lc2hTaGFkZXIgPSB7XG4gIHZlcnRleDogICB0cmlWZXJ0U3JjLFxuICBmcmFnbWVudDogdHJpRnJhZ1NyYyxcbiAgYXR0cmlidXRlczogW1xuICAgIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjNCd9LFxuICAgIHtuYW1lOiAnbm9ybWFsJywgdHlwZTogJ3ZlYzMnfSxcbiAgICB7bmFtZTogJ2NvbG9yJywgdHlwZTogJ3ZlYzQnfSxcbiAgICB7bmFtZTogJ3V2JywgdHlwZTogJ3ZlYzInfSxcbiAgICB7bmFtZTogJ3ZlY3RvcicsIHR5cGU6ICd2ZWMzJ31cbiAgXVxufVxuZXhwb3J0cy5waWNrU2hhZGVyID0ge1xuICB2ZXJ0ZXg6ICAgcGlja1ZlcnRTcmMsXG4gIGZyYWdtZW50OiBwaWNrRnJhZ1NyYyxcbiAgYXR0cmlidXRlczogW1xuICAgIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjNCd9LFxuICAgIHtuYW1lOiAnaWQnLCB0eXBlOiAndmVjNCd9LFxuICAgIHtuYW1lOiAndmVjdG9yJywgdHlwZTogJ3ZlYzMnfVxuICBdXG59XG5cbn0se1wiZ2xzbGlmeVwiOjQwOX1dLDI0NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgMDogJ05PTkUnLFxuICAxOiAnT05FJyxcbiAgMjogJ0xJTkVfTE9PUCcsXG4gIDM6ICdMSU5FX1NUUklQJyxcbiAgNDogJ1RSSUFOR0xFUycsXG4gIDU6ICdUUklBTkdMRV9TVFJJUCcsXG4gIDY6ICdUUklBTkdMRV9GQU4nLFxuICAyNTY6ICdERVBUSF9CVUZGRVJfQklUJyxcbiAgNTEyOiAnTkVWRVInLFxuICA1MTM6ICdMRVNTJyxcbiAgNTE0OiAnRVFVQUwnLFxuICA1MTU6ICdMRVFVQUwnLFxuICA1MTY6ICdHUkVBVEVSJyxcbiAgNTE3OiAnTk9URVFVQUwnLFxuICA1MTg6ICdHRVFVQUwnLFxuICA1MTk6ICdBTFdBWVMnLFxuICA3Njg6ICdTUkNfQ09MT1InLFxuICA3Njk6ICdPTkVfTUlOVVNfU1JDX0NPTE9SJyxcbiAgNzcwOiAnU1JDX0FMUEhBJyxcbiAgNzcxOiAnT05FX01JTlVTX1NSQ19BTFBIQScsXG4gIDc3MjogJ0RTVF9BTFBIQScsXG4gIDc3MzogJ09ORV9NSU5VU19EU1RfQUxQSEEnLFxuICA3NzQ6ICdEU1RfQ09MT1InLFxuICA3NzU6ICdPTkVfTUlOVVNfRFNUX0NPTE9SJyxcbiAgNzc2OiAnU1JDX0FMUEhBX1NBVFVSQVRFJyxcbiAgMTAyNDogJ1NURU5DSUxfQlVGRkVSX0JJVCcsXG4gIDEwMjg6ICdGUk9OVCcsXG4gIDEwMjk6ICdCQUNLJyxcbiAgMTAzMjogJ0ZST05UX0FORF9CQUNLJyxcbiAgMTI4MDogJ0lOVkFMSURfRU5VTScsXG4gIDEyODE6ICdJTlZBTElEX1ZBTFVFJyxcbiAgMTI4MjogJ0lOVkFMSURfT1BFUkFUSU9OJyxcbiAgMTI4NTogJ09VVF9PRl9NRU1PUlknLFxuICAxMjg2OiAnSU5WQUxJRF9GUkFNRUJVRkZFUl9PUEVSQVRJT04nLFxuICAyMzA0OiAnQ1cnLFxuICAyMzA1OiAnQ0NXJyxcbiAgMjg0OTogJ0xJTkVfV0lEVEgnLFxuICAyODg0OiAnQ1VMTF9GQUNFJyxcbiAgMjg4NTogJ0NVTExfRkFDRV9NT0RFJyxcbiAgMjg4NjogJ0ZST05UX0ZBQ0UnLFxuICAyOTI4OiAnREVQVEhfUkFOR0UnLFxuICAyOTI5OiAnREVQVEhfVEVTVCcsXG4gIDI5MzA6ICdERVBUSF9XUklURU1BU0snLFxuICAyOTMxOiAnREVQVEhfQ0xFQVJfVkFMVUUnLFxuICAyOTMyOiAnREVQVEhfRlVOQycsXG4gIDI5NjA6ICdTVEVOQ0lMX1RFU1QnLFxuICAyOTYxOiAnU1RFTkNJTF9DTEVBUl9WQUxVRScsXG4gIDI5NjI6ICdTVEVOQ0lMX0ZVTkMnLFxuICAyOTYzOiAnU1RFTkNJTF9WQUxVRV9NQVNLJyxcbiAgMjk2NDogJ1NURU5DSUxfRkFJTCcsXG4gIDI5NjU6ICdTVEVOQ0lMX1BBU1NfREVQVEhfRkFJTCcsXG4gIDI5NjY6ICdTVEVOQ0lMX1BBU1NfREVQVEhfUEFTUycsXG4gIDI5Njc6ICdTVEVOQ0lMX1JFRicsXG4gIDI5Njg6ICdTVEVOQ0lMX1dSSVRFTUFTSycsXG4gIDI5Nzg6ICdWSUVXUE9SVCcsXG4gIDMwMjQ6ICdESVRIRVInLFxuICAzMDQyOiAnQkxFTkQnLFxuICAzMDg4OiAnU0NJU1NPUl9CT1gnLFxuICAzMDg5OiAnU0NJU1NPUl9URVNUJyxcbiAgMzEwNjogJ0NPTE9SX0NMRUFSX1ZBTFVFJyxcbiAgMzEwNzogJ0NPTE9SX1dSSVRFTUFTSycsXG4gIDMzMTc6ICdVTlBBQ0tfQUxJR05NRU5UJyxcbiAgMzMzMzogJ1BBQ0tfQUxJR05NRU5UJyxcbiAgMzM3OTogJ01BWF9URVhUVVJFX1NJWkUnLFxuICAzMzg2OiAnTUFYX1ZJRVdQT1JUX0RJTVMnLFxuICAzNDA4OiAnU1VCUElYRUxfQklUUycsXG4gIDM0MTA6ICdSRURfQklUUycsXG4gIDM0MTE6ICdHUkVFTl9CSVRTJyxcbiAgMzQxMjogJ0JMVUVfQklUUycsXG4gIDM0MTM6ICdBTFBIQV9CSVRTJyxcbiAgMzQxNDogJ0RFUFRIX0JJVFMnLFxuICAzNDE1OiAnU1RFTkNJTF9CSVRTJyxcbiAgMzU1MzogJ1RFWFRVUkVfMkQnLFxuICA0MzUyOiAnRE9OVF9DQVJFJyxcbiAgNDM1MzogJ0ZBU1RFU1QnLFxuICA0MzU0OiAnTklDRVNUJyxcbiAgNTEyMDogJ0JZVEUnLFxuICA1MTIxOiAnVU5TSUdORURfQllURScsXG4gIDUxMjI6ICdTSE9SVCcsXG4gIDUxMjM6ICdVTlNJR05FRF9TSE9SVCcsXG4gIDUxMjQ6ICdJTlQnLFxuICA1MTI1OiAnVU5TSUdORURfSU5UJyxcbiAgNTEyNjogJ0ZMT0FUJyxcbiAgNTM4NjogJ0lOVkVSVCcsXG4gIDU4OTA6ICdURVhUVVJFJyxcbiAgNjQwMTogJ1NURU5DSUxfSU5ERVgnLFxuICA2NDAyOiAnREVQVEhfQ09NUE9ORU5UJyxcbiAgNjQwNjogJ0FMUEhBJyxcbiAgNjQwNzogJ1JHQicsXG4gIDY0MDg6ICdSR0JBJyxcbiAgNjQwOTogJ0xVTUlOQU5DRScsXG4gIDY0MTA6ICdMVU1JTkFOQ0VfQUxQSEEnLFxuICA3NjgwOiAnS0VFUCcsXG4gIDc2ODE6ICdSRVBMQUNFJyxcbiAgNzY4MjogJ0lOQ1InLFxuICA3NjgzOiAnREVDUicsXG4gIDc5MzY6ICdWRU5ET1InLFxuICA3OTM3OiAnUkVOREVSRVInLFxuICA3OTM4OiAnVkVSU0lPTicsXG4gIDk3Mjg6ICdORUFSRVNUJyxcbiAgOTcyOTogJ0xJTkVBUicsXG4gIDk5ODQ6ICdORUFSRVNUX01JUE1BUF9ORUFSRVNUJyxcbiAgOTk4NTogJ0xJTkVBUl9NSVBNQVBfTkVBUkVTVCcsXG4gIDk5ODY6ICdORUFSRVNUX01JUE1BUF9MSU5FQVInLFxuICA5OTg3OiAnTElORUFSX01JUE1BUF9MSU5FQVInLFxuICAxMDI0MDogJ1RFWFRVUkVfTUFHX0ZJTFRFUicsXG4gIDEwMjQxOiAnVEVYVFVSRV9NSU5fRklMVEVSJyxcbiAgMTAyNDI6ICdURVhUVVJFX1dSQVBfUycsXG4gIDEwMjQzOiAnVEVYVFVSRV9XUkFQX1QnLFxuICAxMDQ5NzogJ1JFUEVBVCcsXG4gIDEwNzUyOiAnUE9MWUdPTl9PRkZTRVRfVU5JVFMnLFxuICAxNjM4NDogJ0NPTE9SX0JVRkZFUl9CSVQnLFxuICAzMjc2OTogJ0NPTlNUQU5UX0NPTE9SJyxcbiAgMzI3NzA6ICdPTkVfTUlOVVNfQ09OU1RBTlRfQ09MT1InLFxuICAzMjc3MTogJ0NPTlNUQU5UX0FMUEhBJyxcbiAgMzI3NzI6ICdPTkVfTUlOVVNfQ09OU1RBTlRfQUxQSEEnLFxuICAzMjc3MzogJ0JMRU5EX0NPTE9SJyxcbiAgMzI3NzQ6ICdGVU5DX0FERCcsXG4gIDMyNzc3OiAnQkxFTkRfRVFVQVRJT05fUkdCJyxcbiAgMzI3Nzg6ICdGVU5DX1NVQlRSQUNUJyxcbiAgMzI3Nzk6ICdGVU5DX1JFVkVSU0VfU1VCVFJBQ1QnLFxuICAzMjgxOTogJ1VOU0lHTkVEX1NIT1JUXzRfNF80XzQnLFxuICAzMjgyMDogJ1VOU0lHTkVEX1NIT1JUXzVfNV81XzEnLFxuICAzMjgyMzogJ1BPTFlHT05fT0ZGU0VUX0ZJTEwnLFxuICAzMjgyNDogJ1BPTFlHT05fT0ZGU0VUX0ZBQ1RPUicsXG4gIDMyODU0OiAnUkdCQTQnLFxuICAzMjg1NTogJ1JHQjVfQTEnLFxuICAzMjg3MzogJ1RFWFRVUkVfQklORElOR18yRCcsXG4gIDMyOTI2OiAnU0FNUExFX0FMUEhBX1RPX0NPVkVSQUdFJyxcbiAgMzI5Mjg6ICdTQU1QTEVfQ09WRVJBR0UnLFxuICAzMjkzNjogJ1NBTVBMRV9CVUZGRVJTJyxcbiAgMzI5Mzc6ICdTQU1QTEVTJyxcbiAgMzI5Mzg6ICdTQU1QTEVfQ09WRVJBR0VfVkFMVUUnLFxuICAzMjkzOTogJ1NBTVBMRV9DT1ZFUkFHRV9JTlZFUlQnLFxuICAzMjk2ODogJ0JMRU5EX0RTVF9SR0InLFxuICAzMjk2OTogJ0JMRU5EX1NSQ19SR0InLFxuICAzMjk3MDogJ0JMRU5EX0RTVF9BTFBIQScsXG4gIDMyOTcxOiAnQkxFTkRfU1JDX0FMUEhBJyxcbiAgMzMwNzE6ICdDTEFNUF9UT19FREdFJyxcbiAgMzMxNzA6ICdHRU5FUkFURV9NSVBNQVBfSElOVCcsXG4gIDMzMTg5OiAnREVQVEhfQ09NUE9ORU5UMTYnLFxuICAzMzMwNjogJ0RFUFRIX1NURU5DSUxfQVRUQUNITUVOVCcsXG4gIDMzNjM1OiAnVU5TSUdORURfU0hPUlRfNV82XzUnLFxuICAzMzY0ODogJ01JUlJPUkVEX1JFUEVBVCcsXG4gIDMzOTAxOiAnQUxJQVNFRF9QT0lOVF9TSVpFX1JBTkdFJyxcbiAgMzM5MDI6ICdBTElBU0VEX0xJTkVfV0lEVEhfUkFOR0UnLFxuICAzMzk4NDogJ1RFWFRVUkUwJyxcbiAgMzM5ODU6ICdURVhUVVJFMScsXG4gIDMzOTg2OiAnVEVYVFVSRTInLFxuICAzMzk4NzogJ1RFWFRVUkUzJyxcbiAgMzM5ODg6ICdURVhUVVJFNCcsXG4gIDMzOTg5OiAnVEVYVFVSRTUnLFxuICAzMzk5MDogJ1RFWFRVUkU2JyxcbiAgMzM5OTE6ICdURVhUVVJFNycsXG4gIDMzOTkyOiAnVEVYVFVSRTgnLFxuICAzMzk5MzogJ1RFWFRVUkU5JyxcbiAgMzM5OTQ6ICdURVhUVVJFMTAnLFxuICAzMzk5NTogJ1RFWFRVUkUxMScsXG4gIDMzOTk2OiAnVEVYVFVSRTEyJyxcbiAgMzM5OTc6ICdURVhUVVJFMTMnLFxuICAzMzk5ODogJ1RFWFRVUkUxNCcsXG4gIDMzOTk5OiAnVEVYVFVSRTE1JyxcbiAgMzQwMDA6ICdURVhUVVJFMTYnLFxuICAzNDAwMTogJ1RFWFRVUkUxNycsXG4gIDM0MDAyOiAnVEVYVFVSRTE4JyxcbiAgMzQwMDM6ICdURVhUVVJFMTknLFxuICAzNDAwNDogJ1RFWFRVUkUyMCcsXG4gIDM0MDA1OiAnVEVYVFVSRTIxJyxcbiAgMzQwMDY6ICdURVhUVVJFMjInLFxuICAzNDAwNzogJ1RFWFRVUkUyMycsXG4gIDM0MDA4OiAnVEVYVFVSRTI0JyxcbiAgMzQwMDk6ICdURVhUVVJFMjUnLFxuICAzNDAxMDogJ1RFWFRVUkUyNicsXG4gIDM0MDExOiAnVEVYVFVSRTI3JyxcbiAgMzQwMTI6ICdURVhUVVJFMjgnLFxuICAzNDAxMzogJ1RFWFRVUkUyOScsXG4gIDM0MDE0OiAnVEVYVFVSRTMwJyxcbiAgMzQwMTU6ICdURVhUVVJFMzEnLFxuICAzNDAxNjogJ0FDVElWRV9URVhUVVJFJyxcbiAgMzQwMjQ6ICdNQVhfUkVOREVSQlVGRkVSX1NJWkUnLFxuICAzNDA0MTogJ0RFUFRIX1NURU5DSUwnLFxuICAzNDA1NTogJ0lOQ1JfV1JBUCcsXG4gIDM0MDU2OiAnREVDUl9XUkFQJyxcbiAgMzQwNjc6ICdURVhUVVJFX0NVQkVfTUFQJyxcbiAgMzQwNjg6ICdURVhUVVJFX0JJTkRJTkdfQ1VCRV9NQVAnLFxuICAzNDA2OTogJ1RFWFRVUkVfQ1VCRV9NQVBfUE9TSVRJVkVfWCcsXG4gIDM0MDcwOiAnVEVYVFVSRV9DVUJFX01BUF9ORUdBVElWRV9YJyxcbiAgMzQwNzE6ICdURVhUVVJFX0NVQkVfTUFQX1BPU0lUSVZFX1knLFxuICAzNDA3MjogJ1RFWFRVUkVfQ1VCRV9NQVBfTkVHQVRJVkVfWScsXG4gIDM0MDczOiAnVEVYVFVSRV9DVUJFX01BUF9QT1NJVElWRV9aJyxcbiAgMzQwNzQ6ICdURVhUVVJFX0NVQkVfTUFQX05FR0FUSVZFX1onLFxuICAzNDA3NjogJ01BWF9DVUJFX01BUF9URVhUVVJFX1NJWkUnLFxuICAzNDMzODogJ1ZFUlRFWF9BVFRSSUJfQVJSQVlfRU5BQkxFRCcsXG4gIDM0MzM5OiAnVkVSVEVYX0FUVFJJQl9BUlJBWV9TSVpFJyxcbiAgMzQzNDA6ICdWRVJURVhfQVRUUklCX0FSUkFZX1NUUklERScsXG4gIDM0MzQxOiAnVkVSVEVYX0FUVFJJQl9BUlJBWV9UWVBFJyxcbiAgMzQzNDI6ICdDVVJSRU5UX1ZFUlRFWF9BVFRSSUInLFxuICAzNDM3MzogJ1ZFUlRFWF9BVFRSSUJfQVJSQVlfUE9JTlRFUicsXG4gIDM0NDY2OiAnTlVNX0NPTVBSRVNTRURfVEVYVFVSRV9GT1JNQVRTJyxcbiAgMzQ0Njc6ICdDT01QUkVTU0VEX1RFWFRVUkVfRk9STUFUUycsXG4gIDM0NjYwOiAnQlVGRkVSX1NJWkUnLFxuICAzNDY2MTogJ0JVRkZFUl9VU0FHRScsXG4gIDM0ODE2OiAnU1RFTkNJTF9CQUNLX0ZVTkMnLFxuICAzNDgxNzogJ1NURU5DSUxfQkFDS19GQUlMJyxcbiAgMzQ4MTg6ICdTVEVOQ0lMX0JBQ0tfUEFTU19ERVBUSF9GQUlMJyxcbiAgMzQ4MTk6ICdTVEVOQ0lMX0JBQ0tfUEFTU19ERVBUSF9QQVNTJyxcbiAgMzQ4Nzc6ICdCTEVORF9FUVVBVElPTl9BTFBIQScsXG4gIDM0OTIxOiAnTUFYX1ZFUlRFWF9BVFRSSUJTJyxcbiAgMzQ5MjI6ICdWRVJURVhfQVRUUklCX0FSUkFZX05PUk1BTElaRUQnLFxuICAzNDkzMDogJ01BWF9URVhUVVJFX0lNQUdFX1VOSVRTJyxcbiAgMzQ5NjI6ICdBUlJBWV9CVUZGRVInLFxuICAzNDk2MzogJ0VMRU1FTlRfQVJSQVlfQlVGRkVSJyxcbiAgMzQ5NjQ6ICdBUlJBWV9CVUZGRVJfQklORElORycsXG4gIDM0OTY1OiAnRUxFTUVOVF9BUlJBWV9CVUZGRVJfQklORElORycsXG4gIDM0OTc1OiAnVkVSVEVYX0FUVFJJQl9BUlJBWV9CVUZGRVJfQklORElORycsXG4gIDM1MDQwOiAnU1RSRUFNX0RSQVcnLFxuICAzNTA0NDogJ1NUQVRJQ19EUkFXJyxcbiAgMzUwNDg6ICdEWU5BTUlDX0RSQVcnLFxuICAzNTYzMjogJ0ZSQUdNRU5UX1NIQURFUicsXG4gIDM1NjMzOiAnVkVSVEVYX1NIQURFUicsXG4gIDM1NjYwOiAnTUFYX1ZFUlRFWF9URVhUVVJFX0lNQUdFX1VOSVRTJyxcbiAgMzU2NjE6ICdNQVhfQ09NQklORURfVEVYVFVSRV9JTUFHRV9VTklUUycsXG4gIDM1NjYzOiAnU0hBREVSX1RZUEUnLFxuICAzNTY2NDogJ0ZMT0FUX1ZFQzInLFxuICAzNTY2NTogJ0ZMT0FUX1ZFQzMnLFxuICAzNTY2NjogJ0ZMT0FUX1ZFQzQnLFxuICAzNTY2NzogJ0lOVF9WRUMyJyxcbiAgMzU2Njg6ICdJTlRfVkVDMycsXG4gIDM1NjY5OiAnSU5UX1ZFQzQnLFxuICAzNTY3MDogJ0JPT0wnLFxuICAzNTY3MTogJ0JPT0xfVkVDMicsXG4gIDM1NjcyOiAnQk9PTF9WRUMzJyxcbiAgMzU2NzM6ICdCT09MX1ZFQzQnLFxuICAzNTY3NDogJ0ZMT0FUX01BVDInLFxuICAzNTY3NTogJ0ZMT0FUX01BVDMnLFxuICAzNTY3NjogJ0ZMT0FUX01BVDQnLFxuICAzNTY3ODogJ1NBTVBMRVJfMkQnLFxuICAzNTY4MDogJ1NBTVBMRVJfQ1VCRScsXG4gIDM1NzEyOiAnREVMRVRFX1NUQVRVUycsXG4gIDM1NzEzOiAnQ09NUElMRV9TVEFUVVMnLFxuICAzNTcxNDogJ0xJTktfU1RBVFVTJyxcbiAgMzU3MTU6ICdWQUxJREFURV9TVEFUVVMnLFxuICAzNTcxNjogJ0lORk9fTE9HX0xFTkdUSCcsXG4gIDM1NzE3OiAnQVRUQUNIRURfU0hBREVSUycsXG4gIDM1NzE4OiAnQUNUSVZFX1VOSUZPUk1TJyxcbiAgMzU3MTk6ICdBQ1RJVkVfVU5JRk9STV9NQVhfTEVOR1RIJyxcbiAgMzU3MjA6ICdTSEFERVJfU09VUkNFX0xFTkdUSCcsXG4gIDM1NzIxOiAnQUNUSVZFX0FUVFJJQlVURVMnLFxuICAzNTcyMjogJ0FDVElWRV9BVFRSSUJVVEVfTUFYX0xFTkdUSCcsXG4gIDM1NzI0OiAnU0hBRElOR19MQU5HVUFHRV9WRVJTSU9OJyxcbiAgMzU3MjU6ICdDVVJSRU5UX1BST0dSQU0nLFxuICAzNjAwMzogJ1NURU5DSUxfQkFDS19SRUYnLFxuICAzNjAwNDogJ1NURU5DSUxfQkFDS19WQUxVRV9NQVNLJyxcbiAgMzYwMDU6ICdTVEVOQ0lMX0JBQ0tfV1JJVEVNQVNLJyxcbiAgMzYwMDY6ICdGUkFNRUJVRkZFUl9CSU5ESU5HJyxcbiAgMzYwMDc6ICdSRU5ERVJCVUZGRVJfQklORElORycsXG4gIDM2MDQ4OiAnRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9PQkpFQ1RfVFlQRScsXG4gIDM2MDQ5OiAnRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9PQkpFQ1RfTkFNRScsXG4gIDM2MDUwOiAnRlJBTUVCVUZGRVJfQVRUQUNITUVOVF9URVhUVVJFX0xFVkVMJyxcbiAgMzYwNTE6ICdGUkFNRUJVRkZFUl9BVFRBQ0hNRU5UX1RFWFRVUkVfQ1VCRV9NQVBfRkFDRScsXG4gIDM2MDUzOiAnRlJBTUVCVUZGRVJfQ09NUExFVEUnLFxuICAzNjA1NDogJ0ZSQU1FQlVGRkVSX0lOQ09NUExFVEVfQVRUQUNITUVOVCcsXG4gIDM2MDU1OiAnRlJBTUVCVUZGRVJfSU5DT01QTEVURV9NSVNTSU5HX0FUVEFDSE1FTlQnLFxuICAzNjA1NzogJ0ZSQU1FQlVGRkVSX0lOQ09NUExFVEVfRElNRU5TSU9OUycsXG4gIDM2MDYxOiAnRlJBTUVCVUZGRVJfVU5TVVBQT1JURUQnLFxuICAzNjA2NDogJ0NPTE9SX0FUVEFDSE1FTlQwJyxcbiAgMzYwOTY6ICdERVBUSF9BVFRBQ0hNRU5UJyxcbiAgMzYxMjg6ICdTVEVOQ0lMX0FUVEFDSE1FTlQnLFxuICAzNjE2MDogJ0ZSQU1FQlVGRkVSJyxcbiAgMzYxNjE6ICdSRU5ERVJCVUZGRVInLFxuICAzNjE2MjogJ1JFTkRFUkJVRkZFUl9XSURUSCcsXG4gIDM2MTYzOiAnUkVOREVSQlVGRkVSX0hFSUdIVCcsXG4gIDM2MTY0OiAnUkVOREVSQlVGRkVSX0lOVEVSTkFMX0ZPUk1BVCcsXG4gIDM2MTY4OiAnU1RFTkNJTF9JTkRFWDgnLFxuICAzNjE3NjogJ1JFTkRFUkJVRkZFUl9SRURfU0laRScsXG4gIDM2MTc3OiAnUkVOREVSQlVGRkVSX0dSRUVOX1NJWkUnLFxuICAzNjE3ODogJ1JFTkRFUkJVRkZFUl9CTFVFX1NJWkUnLFxuICAzNjE3OTogJ1JFTkRFUkJVRkZFUl9BTFBIQV9TSVpFJyxcbiAgMzYxODA6ICdSRU5ERVJCVUZGRVJfREVQVEhfU0laRScsXG4gIDM2MTgxOiAnUkVOREVSQlVGRkVSX1NURU5DSUxfU0laRScsXG4gIDM2MTk0OiAnUkdCNTY1JyxcbiAgMzYzMzY6ICdMT1dfRkxPQVQnLFxuICAzNjMzNzogJ01FRElVTV9GTE9BVCcsXG4gIDM2MzM4OiAnSElHSF9GTE9BVCcsXG4gIDM2MzM5OiAnTE9XX0lOVCcsXG4gIDM2MzQwOiAnTUVESVVNX0lOVCcsXG4gIDM2MzQxOiAnSElHSF9JTlQnLFxuICAzNjM0NjogJ1NIQURFUl9DT01QSUxFUicsXG4gIDM2MzQ3OiAnTUFYX1ZFUlRFWF9VTklGT1JNX1ZFQ1RPUlMnLFxuICAzNjM0ODogJ01BWF9WQVJZSU5HX1ZFQ1RPUlMnLFxuICAzNjM0OTogJ01BWF9GUkFHTUVOVF9VTklGT1JNX1ZFQ1RPUlMnLFxuICAzNzQ0MDogJ1VOUEFDS19GTElQX1lfV0VCR0wnLFxuICAzNzQ0MTogJ1VOUEFDS19QUkVNVUxUSVBMWV9BTFBIQV9XRUJHTCcsXG4gIDM3NDQyOiAnQ09OVEVYVF9MT1NUX1dFQkdMJyxcbiAgMzc0NDM6ICdVTlBBQ0tfQ09MT1JTUEFDRV9DT05WRVJTSU9OX1dFQkdMJyxcbiAgMzc0NDQ6ICdCUk9XU0VSX0RFRkFVTFRfV0VCR0wnXG59XG5cbn0se31dLDI0NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG52YXIgZ2wxMCA9IF9kZXJlcV8oJy4vMS4wL251bWJlcnMnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGxvb2t1cENvbnN0YW50IChudW1iZXIpIHtcbiAgcmV0dXJuIGdsMTBbbnVtYmVyXVxufVxuXG59LHtcIi4vMS4wL251bWJlcnNcIjoyNDV9XSwyNDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlRXJyb3JCYXJzXG5cbnZhciBjcmVhdGVCdWZmZXIgID0gX2RlcmVxXygnZ2wtYnVmZmVyJylcbnZhciBjcmVhdGVWQU8gICAgID0gX2RlcmVxXygnZ2wtdmFvJylcbnZhciBjcmVhdGVTaGFkZXIgID0gX2RlcmVxXygnLi9zaGFkZXJzL2luZGV4JylcblxudmFyIElERU5USVRZID0gWzEsMCwwLDAsXG4gICAgICAgICAgICAgICAgMCwxLDAsMCxcbiAgICAgICAgICAgICAgICAwLDAsMSwwLFxuICAgICAgICAgICAgICAgIDAsMCwwLDFdXG5cbmZ1bmN0aW9uIEVycm9yQmFycyhnbCwgYnVmZmVyLCB2YW8sIHNoYWRlcikge1xuICB0aGlzLmdsICAgICAgICAgICA9IGdsXG4gIHRoaXMuc2hhZGVyICAgICAgID0gc2hhZGVyXG4gIHRoaXMuYnVmZmVyICAgICAgID0gYnVmZmVyXG4gIHRoaXMudmFvICAgICAgICAgID0gdmFvXG4gIHRoaXMucGl4ZWxSYXRpbyAgID0gMVxuICB0aGlzLmJvdW5kcyAgICAgICA9IFtbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldLCBbLUluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldXVxuICB0aGlzLmNsaXBCb3VuZHMgICA9IFtbLUluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldLCBbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldXVxuICB0aGlzLmxpbmVXaWR0aCAgICA9IFsxLDEsMV1cbiAgdGhpcy5jYXBTaXplICAgICAgPSBbMTAsMTAsMTBdXG4gIHRoaXMubGluZUNvdW50ICAgID0gWzAsMCwwXVxuICB0aGlzLmxpbmVPZmZzZXQgICA9IFswLDAsMF1cbiAgdGhpcy5vcGFjaXR5ICAgICAgPSAxXG4gIHRoaXMuaGFzQWxwaGEgICAgID0gZmFsc2Vcbn1cblxudmFyIHByb3RvID0gRXJyb3JCYXJzLnByb3RvdHlwZVxuXG5wcm90by5pc09wYXF1ZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gIXRoaXMuaGFzQWxwaGFcbn1cblxucHJvdG8uaXNUcmFuc3BhcmVudCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5oYXNBbHBoYVxufVxuXG5wcm90by5kcmF3VHJhbnNwYXJlbnQgPSBwcm90by5kcmF3ID0gZnVuY3Rpb24oY2FtZXJhUGFyYW1zKSB7XG4gIHZhciBnbCA9IHRoaXMuZ2xcbiAgdmFyIHVuaWZvcm1zICAgICAgICA9IHRoaXMuc2hhZGVyLnVuaWZvcm1zXG5cbiAgdGhpcy5zaGFkZXIuYmluZCgpXG4gIHZhciB2aWV3ICAgICAgID0gdW5pZm9ybXMudmlldyAgICAgICA9IGNhbWVyYVBhcmFtcy52aWV3ICAgICAgIHx8IElERU5USVRZXG4gIHZhciBwcm9qZWN0aW9uID0gdW5pZm9ybXMucHJvamVjdGlvbiA9IGNhbWVyYVBhcmFtcy5wcm9qZWN0aW9uIHx8IElERU5USVRZXG4gIHVuaWZvcm1zLm1vZGVsICAgICAgPSBjYW1lcmFQYXJhbXMubW9kZWwgICAgICB8fCBJREVOVElUWVxuICB1bmlmb3Jtcy5jbGlwQm91bmRzID0gdGhpcy5jbGlwQm91bmRzXG4gIHVuaWZvcm1zLm9wYWNpdHkgICAgPSB0aGlzLm9wYWNpdHlcblxuXG4gIHZhciBjeCA9IHZpZXdbMTJdXG4gIHZhciBjeSA9IHZpZXdbMTNdXG4gIHZhciBjeiA9IHZpZXdbMTRdXG4gIHZhciBjdyA9IHZpZXdbMTVdXG5cbiAgdmFyIGlzT3J0aG8gPSBjYW1lcmFQYXJhbXMuX29ydGhvIHx8IGZhbHNlXG4gIHZhciBvcnRob0ZpeCA9IChpc09ydGhvKSA/IDIgOiAxIC8vIGRvdWJsZSB1cCBwYWRkaW5nIGZvciBvcnRob2dyYXBoaWMgdGlja3MgJiBsYWJlbHNcbiAgdmFyIHBpeGVsU2NhbGVGID0gb3J0aG9GaXggKiB0aGlzLnBpeGVsUmF0aW8gKiAocHJvamVjdGlvblszXSpjeCArIHByb2plY3Rpb25bN10qY3kgKyBwcm9qZWN0aW9uWzExXSpjeiArIHByb2plY3Rpb25bMTVdKmN3KSAvIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRcblxuICB0aGlzLnZhby5iaW5kKClcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgZ2wubGluZVdpZHRoKHRoaXMubGluZVdpZHRoW2ldICogdGhpcy5waXhlbFJhdGlvKVxuICAgIHVuaWZvcm1zLmNhcFNpemUgPSB0aGlzLmNhcFNpemVbaV0gKiBwaXhlbFNjYWxlRlxuICAgIGlmICh0aGlzLmxpbmVDb3VudFtpXSkge1xuICAgICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgdGhpcy5saW5lT2Zmc2V0W2ldLCB0aGlzLmxpbmVDb3VudFtpXSlcbiAgICB9XG4gIH1cbiAgdGhpcy52YW8udW5iaW5kKClcbn1cblxuZnVuY3Rpb24gdXBkYXRlQm91bmRzKGJvdW5kcywgcG9pbnQpIHtcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgYm91bmRzWzBdW2ldID0gTWF0aC5taW4oYm91bmRzWzBdW2ldLCBwb2ludFtpXSlcbiAgICBib3VuZHNbMV1baV0gPSBNYXRoLm1heChib3VuZHNbMV1baV0sIHBvaW50W2ldKVxuICB9XG59XG5cbnZhciBGQUNFX1RBQkxFID0gKGZ1bmN0aW9uKCl7XG4gIHZhciB0YWJsZSA9IG5ldyBBcnJheSgzKVxuICBmb3IodmFyIGQ9MDsgZDwzOyArK2QpIHtcbiAgICB2YXIgcm93ID0gW11cbiAgICBmb3IodmFyIGo9MTsgajw9MjsgKytqKSB7XG4gICAgICBmb3IodmFyIHM9LTE7IHM8PTE7IHMrPTIpIHtcbiAgICAgICAgdmFyIHUgPSAoaitkKSAlIDNcbiAgICAgICAgdmFyIHkgPSBbMCwwLDBdXG4gICAgICAgIHlbdV0gPSBzXG4gICAgICAgIHJvdy5wdXNoKHkpXG4gICAgICB9XG4gICAgfVxuICAgIHRhYmxlW2RdID0gcm93XG4gIH1cbiAgcmV0dXJuIHRhYmxlXG59KSgpXG5cblxuZnVuY3Rpb24gZW1pdEZhY2UodmVydHMsIHgsIGMsIGQpIHtcbiAgdmFyIG9mZnNldHMgPSBGQUNFX1RBQkxFW2RdXG4gIGZvcih2YXIgaT0wOyBpPG9mZnNldHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgbyA9IG9mZnNldHNbaV1cbiAgICB2ZXJ0cy5wdXNoKHhbMF0sIHhbMV0sIHhbMl0sXG4gICAgICAgICAgICAgICBjWzBdLCBjWzFdLCBjWzJdLCBjWzNdLFxuICAgICAgICAgICAgICAgb1swXSwgb1sxXSwgb1syXSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0cy5sZW5ndGhcbn1cblxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gIGlmKCdsaW5lV2lkdGgnIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLmxpbmVXaWR0aCA9IG9wdGlvbnMubGluZVdpZHRoXG4gICAgaWYoIUFycmF5LmlzQXJyYXkodGhpcy5saW5lV2lkdGgpKSB7XG4gICAgICB0aGlzLmxpbmVXaWR0aCA9IFt0aGlzLmxpbmVXaWR0aCwgdGhpcy5saW5lV2lkdGgsIHRoaXMubGluZVdpZHRoXVxuICAgIH1cbiAgfVxuICBpZignY2FwU2l6ZScgaW4gb3B0aW9ucykge1xuICAgIHRoaXMuY2FwU2l6ZSA9IG9wdGlvbnMuY2FwU2l6ZVxuICAgIGlmKCFBcnJheS5pc0FycmF5KHRoaXMuY2FwU2l6ZSkpIHtcbiAgICAgIHRoaXMuY2FwU2l6ZSA9IFt0aGlzLmNhcFNpemUsIHRoaXMuY2FwU2l6ZSwgdGhpcy5jYXBTaXplXVxuICAgIH1cbiAgfVxuXG4gIHRoaXMuaGFzQWxwaGEgPSBmYWxzZSAvLyBkZWZhdWx0IHRvIG5vIHRyYW5zcGFyZW50IGRyYXdcbiAgaWYoJ29wYWNpdHknIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wYWNpdHkgPSArb3B0aW9ucy5vcGFjaXR5XG4gICAgaWYodGhpcy5vcGFjaXR5IDwgMSkge1xuICAgICAgdGhpcy5oYXNBbHBoYSA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgdmFyIGNvbG9yICAgID0gb3B0aW9ucy5jb2xvciB8fCBbWzAsMCwwXSxbMCwwLDBdLFswLDAsMF1dXG4gIHZhciBwb3NpdGlvbiA9IG9wdGlvbnMucG9zaXRpb25cbiAgdmFyIGVycm9yICAgID0gb3B0aW9ucy5lcnJvclxuICBpZighQXJyYXkuaXNBcnJheShjb2xvclswXSkpIHtcbiAgICBjb2xvciA9IFtjb2xvcixjb2xvcixjb2xvcl1cbiAgfVxuXG4gIGlmKHBvc2l0aW9uICYmIGVycm9yKSB7XG5cbiAgICB2YXIgdmVydHMgICAgICAgPSBbXVxuICAgIHZhciBuICAgICAgICAgICA9IHBvc2l0aW9uLmxlbmd0aFxuICAgIHZhciB2ZXJ0ZXhDb3VudCA9IDBcbiAgICB0aGlzLmJvdW5kcyAgICAgPSBbWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XSxcbiAgICAgICAgICAgICAgICAgICAgICAgWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XV1cbiAgICB0aGlzLmxpbmVDb3VudCAgPSBbMCwwLDBdXG5cbiAgICAvL0J1aWxkIGdlb21ldHJ5IGZvciBsaW5lc1xuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgdGhpcy5saW5lT2Zmc2V0W2pdID0gdmVydGV4Q291bnRcblxuaV9sb29wOlxuICAgICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgICAgIHZhciBwID0gcG9zaXRpb25baV1cblxuICAgICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgICAgICBpZihpc05hTihwW2tdKSB8fCAhaXNGaW5pdGUocFtrXSkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlIGlfbG9vcFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBlID0gZXJyb3JbaV1cbiAgICAgICAgdmFyIGMgPSBjb2xvcltqXVxuICAgICAgICBpZihBcnJheS5pc0FycmF5KGNbMF0pKSB7XG4gICAgICAgICAgYyA9IGNvbG9yW2ldXG4gICAgICAgIH1cbiAgICAgICAgaWYoYy5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICBjID0gW2NbMF0sIGNbMV0sIGNbMl0sIDFdXG4gICAgICAgIH0gZWxzZSBpZihjLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgIGMgPSBbY1swXSwgY1sxXSwgY1syXSwgY1szXV1cbiAgICAgICAgICBpZighdGhpcy5oYXNBbHBoYSAmJiBjWzNdIDwgMSkgdGhpcy5oYXNBbHBoYSA9IHRydWVcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGlzTmFOKGVbMF1bal0pIHx8IGlzTmFOKGVbMV1bal0pKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgICBpZihlWzBdW2pdIDwgMCkge1xuICAgICAgICAgIHZhciB4ID0gcC5zbGljZSgpXG4gICAgICAgICAgeFtqXSArPSBlWzBdW2pdXG4gICAgICAgICAgdmVydHMucHVzaChwWzBdLCBwWzFdLCBwWzJdLFxuICAgICAgICAgICAgICAgICAgICAgY1swXSwgY1sxXSwgY1syXSwgY1szXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDAsICAgIDAsICAgIDAsXG4gICAgICAgICAgICAgICAgICAgICB4WzBdLCB4WzFdLCB4WzJdLFxuICAgICAgICAgICAgICAgICAgICAgY1swXSwgY1sxXSwgY1syXSwgY1szXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDAsICAgIDAsICAgIDApXG4gICAgICAgICAgdXBkYXRlQm91bmRzKHRoaXMuYm91bmRzLCB4KVxuICAgICAgICAgIHZlcnRleENvdW50ICs9IDIgKyBlbWl0RmFjZSh2ZXJ0cywgeCwgYywgailcbiAgICAgICAgfVxuICAgICAgICBpZihlWzFdW2pdID4gMCkge1xuICAgICAgICAgIHZhciB4ID0gcC5zbGljZSgpXG4gICAgICAgICAgeFtqXSArPSBlWzFdW2pdXG4gICAgICAgICAgdmVydHMucHVzaChwWzBdLCBwWzFdLCBwWzJdLFxuICAgICAgICAgICAgICAgICAgICAgY1swXSwgY1sxXSwgY1syXSwgY1szXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDAsICAgIDAsICAgIDAsXG4gICAgICAgICAgICAgICAgICAgICB4WzBdLCB4WzFdLCB4WzJdLFxuICAgICAgICAgICAgICAgICAgICAgY1swXSwgY1sxXSwgY1syXSwgY1szXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDAsICAgIDAsICAgIDApXG4gICAgICAgICAgdXBkYXRlQm91bmRzKHRoaXMuYm91bmRzLCB4KVxuICAgICAgICAgIHZlcnRleENvdW50ICs9IDIgKyBlbWl0RmFjZSh2ZXJ0cywgeCwgYywgailcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5saW5lQ291bnRbal0gPSB2ZXJ0ZXhDb3VudCAtIHRoaXMubGluZU9mZnNldFtqXVxuICAgIH1cbiAgICB0aGlzLmJ1ZmZlci51cGRhdGUodmVydHMpXG4gIH1cbn1cblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnNoYWRlci5kaXNwb3NlKClcbiAgdGhpcy5idWZmZXIuZGlzcG9zZSgpXG4gIHRoaXMudmFvLmRpc3Bvc2UoKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVFcnJvckJhcnMob3B0aW9ucykge1xuICB2YXIgZ2wgPSBvcHRpb25zLmdsXG4gIHZhciBidWZmZXIgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciB2YW8gPSBjcmVhdGVWQU8oZ2wsIFtcbiAgICAgIHtcbiAgICAgICAgYnVmZmVyOiBidWZmZXIsXG4gICAgICAgIHR5cGU6ICAgZ2wuRkxPQVQsXG4gICAgICAgIHNpemU6ICAgMyxcbiAgICAgICAgb2Zmc2V0OiAwLFxuICAgICAgICBzdHJpZGU6IDQwXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBidWZmZXI6IGJ1ZmZlcixcbiAgICAgICAgdHlwZTogICBnbC5GTE9BVCxcbiAgICAgICAgc2l6ZTogICA0LFxuICAgICAgICBvZmZzZXQ6IDEyLFxuICAgICAgICBzdHJpZGU6IDQwXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBidWZmZXI6IGJ1ZmZlcixcbiAgICAgICAgdHlwZTogICBnbC5GTE9BVCxcbiAgICAgICAgc2l6ZTogICAzLFxuICAgICAgICBvZmZzZXQ6IDI4LFxuICAgICAgICBzdHJpZGU6IDQwXG4gICAgICB9XG4gICAgXSlcblxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsKVxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuY29sb3IubG9jYXRpb24gICAgPSAxXG4gIHNoYWRlci5hdHRyaWJ1dGVzLm9mZnNldC5sb2NhdGlvbiAgID0gMlxuXG4gIHZhciByZXN1bHQgPSBuZXcgRXJyb3JCYXJzKGdsLCBidWZmZXIsIHZhbywgc2hhZGVyKVxuICByZXN1bHQudXBkYXRlKG9wdGlvbnMpXG4gIHJldHVybiByZXN1bHRcbn1cblxufSx7XCIuL3NoYWRlcnMvaW5kZXhcIjoyNDgsXCJnbC1idWZmZXJcIjoyNDEsXCJnbC12YW9cIjozMjd9XSwyNDg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBnbHNsaWZ5ID0gX2RlcmVxXygnZ2xzbGlmeScpXG52YXIgY3JlYXRlU2hhZGVyID0gX2RlcmVxXygnZ2wtc2hhZGVyJylcblxudmFyIHZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMzIHBvc2l0aW9uLCBvZmZzZXQ7XFxuYXR0cmlidXRlIHZlYzQgY29sb3I7XFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gZmxvYXQgY2FwU2l6ZTtcXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcbnZhcnlpbmcgdmVjMyBmcmFnUG9zaXRpb247XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjNCB3b3JsZFBvc2l0aW9uICA9IG1vZGVsICogdmVjNChwb3NpdGlvbiwgMS4wKTtcXG4gIHdvcmxkUG9zaXRpb24gICAgICAgPSAod29ybGRQb3NpdGlvbiAvIHdvcmxkUG9zaXRpb24udykgKyB2ZWM0KGNhcFNpemUgKiBvZmZzZXQsIDAuMCk7XFxuICBnbF9Qb3NpdGlvbiAgICAgICAgID0gcHJvamVjdGlvbiAqIHZpZXcgKiB3b3JsZFBvc2l0aW9uO1xcbiAgZnJhZ0NvbG9yICAgICAgICAgICA9IGNvbG9yO1xcbiAgZnJhZ1Bvc2l0aW9uICAgICAgICA9IHBvc2l0aW9uO1xcbn1cIl0pXG52YXIgZnJhZ1NyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxudW5pZm9ybSBmbG9hdCBvcGFjaXR5O1xcbnZhcnlpbmcgdmVjMyBmcmFnUG9zaXRpb247XFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAoXFxuICAgIG91dE9mUmFuZ2UoY2xpcEJvdW5kc1swXSwgY2xpcEJvdW5kc1sxXSwgZnJhZ1Bvc2l0aW9uKSB8fFxcbiAgICBmcmFnQ29sb3IuYSAqIG9wYWNpdHkgPT0gMC5cXG4gICkgZGlzY2FyZDtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IG9wYWNpdHkgKiBmcmFnQ29sb3I7XFxufVwiXSlcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihnbCkge1xuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCB2ZXJ0U3JjLCBmcmFnU3JjLCBudWxsLCBbXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXG4gICAge25hbWU6ICdjb2xvcicsIHR5cGU6ICd2ZWM0J30sXG4gICAge25hbWU6ICdvZmZzZXQnLCB0eXBlOiAndmVjMyd9XG4gIF0pXG59XG5cbn0se1wiZ2wtc2hhZGVyXCI6MzAxLFwiZ2xzbGlmeVwiOjQwOX1dLDI0OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGNyZWF0ZVRleHR1cmUgPSBfZGVyZXFfKCdnbC10ZXh0dXJlMmQnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUZCT1xuXG52YXIgY29sb3JBdHRhY2htZW50QXJyYXlzID0gbnVsbFxudmFyIEZSQU1FQlVGRkVSX1VOU1VQUE9SVEVEXG52YXIgRlJBTUVCVUZGRVJfSU5DT01QTEVURV9BVFRBQ0hNRU5UXG52YXIgRlJBTUVCVUZGRVJfSU5DT01QTEVURV9ESU1FTlNJT05TXG52YXIgRlJBTUVCVUZGRVJfSU5DT01QTEVURV9NSVNTSU5HX0FUVEFDSE1FTlRcblxuZnVuY3Rpb24gc2F2ZUZCT1N0YXRlKGdsKSB7XG4gIHZhciBmYm8gPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuRlJBTUVCVUZGRVJfQklORElORylcbiAgdmFyIHJibyA9IGdsLmdldFBhcmFtZXRlcihnbC5SRU5ERVJCVUZGRVJfQklORElORylcbiAgdmFyIHRleCA9IGdsLmdldFBhcmFtZXRlcihnbC5URVhUVVJFX0JJTkRJTkdfMkQpXG4gIHJldHVybiBbZmJvLCByYm8sIHRleF1cbn1cblxuZnVuY3Rpb24gcmVzdG9yZUZCT1N0YXRlKGdsLCBkYXRhKSB7XG4gIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgZGF0YVswXSlcbiAgZ2wuYmluZFJlbmRlcmJ1ZmZlcihnbC5SRU5ERVJCVUZGRVIsIGRhdGFbMV0pXG4gIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIGRhdGFbMl0pXG59XG5cbmZ1bmN0aW9uIGxhenlJbml0Q29sb3JBdHRhY2htZW50cyhnbCwgZXh0KSB7XG4gIHZhciBtYXhDb2xvckF0dGFjaG1lbnRzID0gZ2wuZ2V0UGFyYW1ldGVyKGV4dC5NQVhfQ09MT1JfQVRUQUNITUVOVFNfV0VCR0wpXG4gIGNvbG9yQXR0YWNobWVudEFycmF5cyA9IG5ldyBBcnJheShtYXhDb2xvckF0dGFjaG1lbnRzICsgMSlcbiAgZm9yKHZhciBpPTA7IGk8PW1heENvbG9yQXR0YWNobWVudHM7ICsraSkge1xuICAgIHZhciB4ID0gbmV3IEFycmF5KG1heENvbG9yQXR0YWNobWVudHMpXG4gICAgZm9yKHZhciBqPTA7IGo8aTsgKytqKSB7XG4gICAgICB4W2pdID0gZ2wuQ09MT1JfQVRUQUNITUVOVDAgKyBqXG4gICAgfVxuICAgIGZvcih2YXIgaj1pOyBqPG1heENvbG9yQXR0YWNobWVudHM7ICsraikge1xuICAgICAgeFtqXSA9IGdsLk5PTkVcbiAgICB9XG4gICAgY29sb3JBdHRhY2htZW50QXJyYXlzW2ldID0geFxuICB9XG59XG5cbi8vVGhyb3cgYW4gYXBwcm9wcmlhdGUgZXJyb3JcbmZ1bmN0aW9uIHRocm93RkJPRXJyb3Ioc3RhdHVzKSB7XG4gIHN3aXRjaChzdGF0dXMpe1xuICAgIGNhc2UgRlJBTUVCVUZGRVJfVU5TVVBQT1JURUQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLWZibzogRnJhbWVidWZmZXIgdW5zdXBwb3J0ZWQnKVxuICAgIGNhc2UgRlJBTUVCVUZGRVJfSU5DT01QTEVURV9BVFRBQ0hNRU5UOlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IEZyYW1lYnVmZmVyIGluY29tcGxldGUgYXR0YWNobWVudCcpXG4gICAgY2FzZSBGUkFNRUJVRkZFUl9JTkNPTVBMRVRFX0RJTUVOU0lPTlM6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLWZibzogRnJhbWVidWZmZXIgaW5jb21wbGV0ZSBkaW1lbnNpb25zJylcbiAgICBjYXNlIEZSQU1FQlVGRkVSX0lOQ09NUExFVEVfTUlTU0lOR19BVFRBQ0hNRU5UOlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IEZyYW1lYnVmZmVyIGluY29tcGxldGUgbWlzc2luZyBhdHRhY2htZW50JylcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IEZyYW1lYnVmZmVyIGZhaWxlZCBmb3IgdW5zcGVjaWZpZWQgcmVhc29uJylcbiAgfVxufVxuXG4vL0luaXRpYWxpemUgYSB0ZXh0dXJlIG9iamVjdFxuZnVuY3Rpb24gaW5pdFRleHR1cmUoZ2wsIHdpZHRoLCBoZWlnaHQsIHR5cGUsIGZvcm1hdCwgYXR0YWNobWVudCkge1xuICBpZighdHlwZSkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgdmFyIHJlc3VsdCA9IGNyZWF0ZVRleHR1cmUoZ2wsIHdpZHRoLCBoZWlnaHQsIGZvcm1hdCwgdHlwZSlcbiAgcmVzdWx0Lm1hZ0ZpbHRlciA9IGdsLk5FQVJFU1RcbiAgcmVzdWx0Lm1pbkZpbHRlciA9IGdsLk5FQVJFU1RcbiAgcmVzdWx0Lm1pcFNhbXBsZXMgPSAxXG4gIHJlc3VsdC5iaW5kKClcbiAgZ2wuZnJhbWVidWZmZXJUZXh0dXJlMkQoZ2wuRlJBTUVCVUZGRVIsIGF0dGFjaG1lbnQsIGdsLlRFWFRVUkVfMkQsIHJlc3VsdC5oYW5kbGUsIDApXG4gIHJldHVybiByZXN1bHRcbn1cblxuLy9Jbml0aWFsaXplIGEgcmVuZGVyIGJ1ZmZlciBvYmplY3RcbmZ1bmN0aW9uIGluaXRSZW5kZXJCdWZmZXIoZ2wsIHdpZHRoLCBoZWlnaHQsIGNvbXBvbmVudCwgYXR0YWNobWVudCkge1xuICB2YXIgcmVzdWx0ID0gZ2wuY3JlYXRlUmVuZGVyYnVmZmVyKClcbiAgZ2wuYmluZFJlbmRlcmJ1ZmZlcihnbC5SRU5ERVJCVUZGRVIsIHJlc3VsdClcbiAgZ2wucmVuZGVyYnVmZmVyU3RvcmFnZShnbC5SRU5ERVJCVUZGRVIsIGNvbXBvbmVudCwgd2lkdGgsIGhlaWdodClcbiAgZ2wuZnJhbWVidWZmZXJSZW5kZXJidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIGF0dGFjaG1lbnQsIGdsLlJFTkRFUkJVRkZFUiwgcmVzdWx0KVxuICByZXR1cm4gcmVzdWx0XG59XG5cbi8vUmVidWlsZCB0aGUgZnJhbWUgYnVmZmVyXG5mdW5jdGlvbiByZWJ1aWxkRkJPKGZibykge1xuXG4gIC8vU2F2ZSBGQk8gc3RhdGVcbiAgdmFyIHN0YXRlID0gc2F2ZUZCT1N0YXRlKGZiby5nbClcblxuICB2YXIgZ2wgPSBmYm8uZ2xcbiAgdmFyIGhhbmRsZSA9IGZiby5oYW5kbGUgPSBnbC5jcmVhdGVGcmFtZWJ1ZmZlcigpXG4gIHZhciB3aWR0aCA9IGZiby5fc2hhcGVbMF1cbiAgdmFyIGhlaWdodCA9IGZiby5fc2hhcGVbMV1cbiAgdmFyIG51bUNvbG9ycyA9IGZiby5jb2xvci5sZW5ndGhcbiAgdmFyIGV4dCA9IGZiby5fZXh0XG4gIHZhciB1c2VTdGVuY2lsID0gZmJvLl91c2VTdGVuY2lsXG4gIHZhciB1c2VEZXB0aCA9IGZiby5fdXNlRGVwdGhcbiAgdmFyIGNvbG9yVHlwZSA9IGZiby5fY29sb3JUeXBlXG5cbiAgLy9CaW5kIHRoZSBmYm9cbiAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBoYW5kbGUpXG5cbiAgLy9BbGxvY2F0ZSBjb2xvciBidWZmZXJzXG4gIGZvcih2YXIgaT0wOyBpPG51bUNvbG9yczsgKytpKSB7XG4gICAgZmJvLmNvbG9yW2ldID0gaW5pdFRleHR1cmUoZ2wsIHdpZHRoLCBoZWlnaHQsIGNvbG9yVHlwZSwgZ2wuUkdCQSwgZ2wuQ09MT1JfQVRUQUNITUVOVDAgKyBpKVxuICB9XG4gIGlmKG51bUNvbG9ycyA9PT0gMCkge1xuICAgIGZiby5fY29sb3JfcmIgPSBpbml0UmVuZGVyQnVmZmVyKGdsLCB3aWR0aCwgaGVpZ2h0LCBnbC5SR0JBNCwgZ2wuQ09MT1JfQVRUQUNITUVOVDApXG4gICAgaWYoZXh0KSB7XG4gICAgICBleHQuZHJhd0J1ZmZlcnNXRUJHTChjb2xvckF0dGFjaG1lbnRBcnJheXNbMF0pXG4gICAgfVxuICB9IGVsc2UgaWYobnVtQ29sb3JzID4gMSkge1xuICAgIGV4dC5kcmF3QnVmZmVyc1dFQkdMKGNvbG9yQXR0YWNobWVudEFycmF5c1tudW1Db2xvcnNdKVxuICB9XG5cbiAgLy9BbGxvY2F0ZSBkZXB0aC9zdGVuY2lsIGJ1ZmZlcnNcbiAgdmFyIFdFQkdMX2RlcHRoX3RleHR1cmUgPSBnbC5nZXRFeHRlbnNpb24oJ1dFQkdMX2RlcHRoX3RleHR1cmUnKVxuICBpZihXRUJHTF9kZXB0aF90ZXh0dXJlKSB7XG4gICAgaWYodXNlU3RlbmNpbCkge1xuICAgICAgZmJvLmRlcHRoID0gaW5pdFRleHR1cmUoZ2wsIHdpZHRoLCBoZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFdFQkdMX2RlcHRoX3RleHR1cmUuVU5TSUdORURfSU5UXzI0XzhfV0VCR0wsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGdsLkRFUFRIX1NURU5DSUwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGdsLkRFUFRIX1NURU5DSUxfQVRUQUNITUVOVClcbiAgICB9IGVsc2UgaWYodXNlRGVwdGgpIHtcbiAgICAgIGZiby5kZXB0aCA9IGluaXRUZXh0dXJlKGdsLCB3aWR0aCwgaGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICBnbC5VTlNJR05FRF9TSE9SVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZ2wuREVQVEhfQ09NUE9ORU5ULFxuICAgICAgICAgICAgICAgICAgICAgICAgICBnbC5ERVBUSF9BVFRBQ0hNRU5UKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZih1c2VEZXB0aCAmJiB1c2VTdGVuY2lsKSB7XG4gICAgICBmYm8uX2RlcHRoX3JiID0gaW5pdFJlbmRlckJ1ZmZlcihnbCwgd2lkdGgsIGhlaWdodCwgZ2wuREVQVEhfU1RFTkNJTCwgZ2wuREVQVEhfU1RFTkNJTF9BVFRBQ0hNRU5UKVxuICAgIH0gZWxzZSBpZih1c2VEZXB0aCkge1xuICAgICAgZmJvLl9kZXB0aF9yYiA9IGluaXRSZW5kZXJCdWZmZXIoZ2wsIHdpZHRoLCBoZWlnaHQsIGdsLkRFUFRIX0NPTVBPTkVOVDE2LCBnbC5ERVBUSF9BVFRBQ0hNRU5UKVxuICAgIH0gZWxzZSBpZih1c2VTdGVuY2lsKSB7XG4gICAgICBmYm8uX2RlcHRoX3JiID0gaW5pdFJlbmRlckJ1ZmZlcihnbCwgd2lkdGgsIGhlaWdodCwgZ2wuU1RFTkNJTF9JTkRFWCwgZ2wuU1RFTkNJTF9BVFRBQ0hNRU5UKVxuICAgIH1cbiAgfVxuXG4gIC8vQ2hlY2sgZnJhbWUgYnVmZmVyIHN0YXRlXG4gIHZhciBzdGF0dXMgPSBnbC5jaGVja0ZyYW1lYnVmZmVyU3RhdHVzKGdsLkZSQU1FQlVGRkVSKVxuICBpZihzdGF0dXMgIT09IGdsLkZSQU1FQlVGRkVSX0NPTVBMRVRFKSB7XG5cbiAgICAvL1JlbGVhc2UgYWxsIHBhcnRpYWxseSBhbGxvY2F0ZWQgcmVzb3VyY2VzXG4gICAgZmJvLl9kZXN0cm95ZWQgPSB0cnVlXG5cbiAgICAvL1JlbGVhc2UgYWxsIHJlc291cmNlc1xuICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgbnVsbClcbiAgICBnbC5kZWxldGVGcmFtZWJ1ZmZlcihmYm8uaGFuZGxlKVxuICAgIGZiby5oYW5kbGUgPSBudWxsXG4gICAgaWYoZmJvLmRlcHRoKSB7XG4gICAgICBmYm8uZGVwdGguZGlzcG9zZSgpXG4gICAgICBmYm8uZGVwdGggPSBudWxsXG4gICAgfVxuICAgIGlmKGZiby5fZGVwdGhfcmIpIHtcbiAgICAgIGdsLmRlbGV0ZVJlbmRlcmJ1ZmZlcihmYm8uX2RlcHRoX3JiKVxuICAgICAgZmJvLl9kZXB0aF9yYiA9IG51bGxcbiAgICB9XG4gICAgZm9yKHZhciBpPTA7IGk8ZmJvLmNvbG9yLmxlbmd0aDsgKytpKSB7XG4gICAgICBmYm8uY29sb3JbaV0uZGlzcG9zZSgpXG4gICAgICBmYm8uY29sb3JbaV0gPSBudWxsXG4gICAgfVxuICAgIGlmKGZiby5fY29sb3JfcmIpIHtcbiAgICAgIGdsLmRlbGV0ZVJlbmRlcmJ1ZmZlcihmYm8uX2NvbG9yX3JiKVxuICAgICAgZmJvLl9jb2xvcl9yYiA9IG51bGxcbiAgICB9XG5cbiAgICByZXN0b3JlRkJPU3RhdGUoZ2wsIHN0YXRlKVxuXG4gICAgLy9UaHJvdyB0aGUgZnJhbWUgYnVmZmVyIGVycm9yXG4gICAgdGhyb3dGQk9FcnJvcihzdGF0dXMpXG4gIH1cblxuICAvL0V2ZXJ5dGhpbmcgb2ssIGxldCdzIGdldCBvbiB3aXRoIGxpZmVcbiAgcmVzdG9yZUZCT1N0YXRlKGdsLCBzdGF0ZSlcbn1cblxuZnVuY3Rpb24gRnJhbWVidWZmZXIoZ2wsIHdpZHRoLCBoZWlnaHQsIGNvbG9yVHlwZSwgbnVtQ29sb3JzLCB1c2VEZXB0aCwgdXNlU3RlbmNpbCwgZXh0KSB7XG5cbiAgLy9IYW5kbGUgYW5kIHNldCBwcm9wZXJ0aWVzXG4gIHRoaXMuZ2wgPSBnbFxuICB0aGlzLl9zaGFwZSA9IFt3aWR0aHwwLCBoZWlnaHR8MF1cbiAgdGhpcy5fZGVzdHJveWVkID0gZmFsc2VcbiAgdGhpcy5fZXh0ID0gZXh0XG5cbiAgLy9BbGxvY2F0ZSBidWZmZXJzXG4gIHRoaXMuY29sb3IgPSBuZXcgQXJyYXkobnVtQ29sb3JzKVxuICBmb3IodmFyIGk9MDsgaTxudW1Db2xvcnM7ICsraSkge1xuICAgIHRoaXMuY29sb3JbaV0gPSBudWxsXG4gIH1cbiAgdGhpcy5fY29sb3JfcmIgPSBudWxsXG4gIHRoaXMuZGVwdGggPSBudWxsXG4gIHRoaXMuX2RlcHRoX3JiID0gbnVsbFxuXG4gIC8vU2F2ZSBkZXB0aCBhbmQgc3RlbmNpbCBmbGFnc1xuICB0aGlzLl9jb2xvclR5cGUgPSBjb2xvclR5cGVcbiAgdGhpcy5fdXNlRGVwdGggPSB1c2VEZXB0aFxuICB0aGlzLl91c2VTdGVuY2lsID0gdXNlU3RlbmNpbFxuXG4gIC8vU2hhcGUgdmVjdG9yIGZvciByZXNpemluZ1xuICB2YXIgcGFyZW50ID0gdGhpc1xuICB2YXIgc2hhcGVWZWN0b3IgPSBbd2lkdGh8MCwgaGVpZ2h0fDBdXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHNoYXBlVmVjdG9yLCB7XG4gICAgMDoge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHBhcmVudC5fc2hhcGVbMF1cbiAgICAgIH0sXG4gICAgICBzZXQ6IGZ1bmN0aW9uKHcpIHtcbiAgICAgICAgcmV0dXJuIHBhcmVudC53aWR0aCA9IHdcbiAgICAgIH1cbiAgICB9LFxuICAgIDE6IHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQuX3NoYXBlWzFdXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbihoKSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQuaGVpZ2h0ID0gaFxuICAgICAgfVxuICAgIH1cbiAgfSlcbiAgdGhpcy5fc2hhcGVWZWN0b3IgPSBzaGFwZVZlY3RvclxuXG4gIC8vSW5pdGlhbGl6ZSBhbGwgYXR0YWNobWVudHNcbiAgcmVidWlsZEZCTyh0aGlzKVxufVxuXG52YXIgcHJvdG8gPSBGcmFtZWJ1ZmZlci5wcm90b3R5cGVcblxuZnVuY3Rpb24gcmVzaGFwZUZCTyhmYm8sIHcsIGgpIHtcbiAgLy9JZiBmYm8gaXMgaW52YWxpZCwganVzdCBza2lwIHRoaXNcbiAgaWYoZmJvLl9kZXN0cm95ZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLWZibzogQ2FuXFwndCByZXNpemUgZGVzdHJveWVkIEZCTycpXG4gIH1cblxuICAvL0Rvbid0IHJlc2l6ZSBpZiBubyBjaGFuZ2UgaW4gc2hhcGVcbiAgaWYoIChmYm8uX3NoYXBlWzBdID09PSB3KSAmJlxuICAgICAgKGZiby5fc2hhcGVbMV0gPT09IGgpICkge1xuICAgIHJldHVyblxuICB9XG5cbiAgdmFyIGdsID0gZmJvLmdsXG5cbiAgLy9DaGVjayBwYXJhbWV0ZXIgcmFuZ2VzXG4gIHZhciBtYXhGQk9TaXplID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLk1BWF9SRU5ERVJCVUZGRVJfU0laRSlcbiAgaWYoIHcgPCAwIHx8IHcgPiBtYXhGQk9TaXplIHx8XG4gICAgICBoIDwgMCB8fCBoID4gbWF4RkJPU2l6ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBDYW5cXCd0IHJlc2l6ZSBGQk8sIGludmFsaWQgZGltZW5zaW9ucycpXG4gIH1cblxuICAvL1VwZGF0ZSBzaGFwZVxuICBmYm8uX3NoYXBlWzBdID0gd1xuICBmYm8uX3NoYXBlWzFdID0gaFxuXG4gIC8vU2F2ZSBmcmFtZWJ1ZmZlciBzdGF0ZVxuICB2YXIgc3RhdGUgPSBzYXZlRkJPU3RhdGUoZ2wpXG5cbiAgLy9SZXNpemUgZnJhbWVidWZmZXIgYXR0YWNobWVudHNcbiAgZm9yKHZhciBpPTA7IGk8ZmJvLmNvbG9yLmxlbmd0aDsgKytpKSB7XG4gICAgZmJvLmNvbG9yW2ldLnNoYXBlID0gZmJvLl9zaGFwZVxuICB9XG4gIGlmKGZiby5fY29sb3JfcmIpIHtcbiAgICBnbC5iaW5kUmVuZGVyYnVmZmVyKGdsLlJFTkRFUkJVRkZFUiwgZmJvLl9jb2xvcl9yYilcbiAgICBnbC5yZW5kZXJidWZmZXJTdG9yYWdlKGdsLlJFTkRFUkJVRkZFUiwgZ2wuUkdCQTQsIGZiby5fc2hhcGVbMF0sIGZiby5fc2hhcGVbMV0pXG4gIH1cbiAgaWYoZmJvLmRlcHRoKSB7XG4gICAgZmJvLmRlcHRoLnNoYXBlID0gZmJvLl9zaGFwZVxuICB9XG4gIGlmKGZiby5fZGVwdGhfcmIpIHtcbiAgICBnbC5iaW5kUmVuZGVyYnVmZmVyKGdsLlJFTkRFUkJVRkZFUiwgZmJvLl9kZXB0aF9yYilcbiAgICBpZihmYm8uX3VzZURlcHRoICYmIGZiby5fdXNlU3RlbmNpbCkge1xuICAgICAgZ2wucmVuZGVyYnVmZmVyU3RvcmFnZShnbC5SRU5ERVJCVUZGRVIsIGdsLkRFUFRIX1NURU5DSUwsIGZiby5fc2hhcGVbMF0sIGZiby5fc2hhcGVbMV0pXG4gICAgfSBlbHNlIGlmKGZiby5fdXNlRGVwdGgpIHtcbiAgICAgIGdsLnJlbmRlcmJ1ZmZlclN0b3JhZ2UoZ2wuUkVOREVSQlVGRkVSLCBnbC5ERVBUSF9DT01QT05FTlQxNiwgZmJvLl9zaGFwZVswXSwgZmJvLl9zaGFwZVsxXSlcbiAgICB9IGVsc2UgaWYoZmJvLl91c2VTdGVuY2lsKSB7XG4gICAgICBnbC5yZW5kZXJidWZmZXJTdG9yYWdlKGdsLlJFTkRFUkJVRkZFUiwgZ2wuU1RFTkNJTF9JTkRFWCwgZmJvLl9zaGFwZVswXSwgZmJvLl9zaGFwZVsxXSlcbiAgICB9XG4gIH1cblxuICAvL0NoZWNrIEZCTyBzdGF0dXMgYWZ0ZXIgcmVzaXplLCBpZiBzb21ldGhpbmcgYnJva2UgdGhlbiBkaWUgaW4gYSBmaXJlXG4gIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgZmJvLmhhbmRsZSlcbiAgdmFyIHN0YXR1cyA9IGdsLmNoZWNrRnJhbWVidWZmZXJTdGF0dXMoZ2wuRlJBTUVCVUZGRVIpXG4gIGlmKHN0YXR1cyAhPT0gZ2wuRlJBTUVCVUZGRVJfQ09NUExFVEUpIHtcbiAgICBmYm8uZGlzcG9zZSgpXG4gICAgcmVzdG9yZUZCT1N0YXRlKGdsLCBzdGF0ZSlcbiAgICB0aHJvd0ZCT0Vycm9yKHN0YXR1cylcbiAgfVxuXG4gIC8vUmVzdG9yZSBmcmFtZWJ1ZmZlciBzdGF0ZVxuICByZXN0b3JlRkJPU3RhdGUoZ2wsIHN0YXRlKVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydGllcyhwcm90bywge1xuICAnc2hhcGUnOiB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmKHRoaXMuX2Rlc3Ryb3llZCkge1xuICAgICAgICByZXR1cm4gWzAsMF1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLl9zaGFwZVZlY3RvclxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbih4KSB7XG4gICAgICBpZighQXJyYXkuaXNBcnJheSh4KSkge1xuICAgICAgICB4ID0gW3h8MCwgeHwwXVxuICAgICAgfVxuICAgICAgaWYoeC5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IFNoYXBlIHZlY3RvciBtdXN0IGJlIGxlbmd0aCAyJylcbiAgICAgIH1cblxuICAgICAgdmFyIHcgPSB4WzBdfDBcbiAgICAgIHZhciBoID0geFsxXXwwXG4gICAgICByZXNoYXBlRkJPKHRoaXMsIHcsIGgpXG5cbiAgICAgIHJldHVybiBbdywgaF1cbiAgICB9LFxuICAgIGVudW1lcmFibGU6IGZhbHNlXG4gIH0sXG4gICd3aWR0aCc6IHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYodGhpcy5fZGVzdHJveWVkKSB7XG4gICAgICAgIHJldHVybiAwXG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fc2hhcGVbMF1cbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24odykge1xuICAgICAgdyA9IHd8MFxuICAgICAgcmVzaGFwZUZCTyh0aGlzLCB3LCB0aGlzLl9zaGFwZVsxXSlcbiAgICAgIHJldHVybiB3XG4gICAgfSxcbiAgICBlbnVtZXJhYmxlOiBmYWxzZVxuICB9LFxuICAnaGVpZ2h0Jzoge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICBpZih0aGlzLl9kZXN0cm95ZWQpIHtcbiAgICAgICAgcmV0dXJuIDBcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLl9zaGFwZVsxXVxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihoKSB7XG4gICAgICBoID0gaHwwXG4gICAgICByZXNoYXBlRkJPKHRoaXMsIHRoaXMuX3NoYXBlWzBdLCBoKVxuICAgICAgcmV0dXJuIGhcbiAgICB9LFxuICAgIGVudW1lcmFibGU6IGZhbHNlXG4gIH1cbn0pXG5cbnByb3RvLmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgaWYodGhpcy5fZGVzdHJveWVkKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdmFyIGdsID0gdGhpcy5nbFxuICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIHRoaXMuaGFuZGxlKVxuICBnbC52aWV3cG9ydCgwLCAwLCB0aGlzLl9zaGFwZVswXSwgdGhpcy5fc2hhcGVbMV0pXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgaWYodGhpcy5fZGVzdHJveWVkKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdGhpcy5fZGVzdHJveWVkID0gdHJ1ZVxuICB2YXIgZ2wgPSB0aGlzLmdsXG4gIGdsLmRlbGV0ZUZyYW1lYnVmZmVyKHRoaXMuaGFuZGxlKVxuICB0aGlzLmhhbmRsZSA9IG51bGxcbiAgaWYodGhpcy5kZXB0aCkge1xuICAgIHRoaXMuZGVwdGguZGlzcG9zZSgpXG4gICAgdGhpcy5kZXB0aCA9IG51bGxcbiAgfVxuICBpZih0aGlzLl9kZXB0aF9yYikge1xuICAgIGdsLmRlbGV0ZVJlbmRlcmJ1ZmZlcih0aGlzLl9kZXB0aF9yYilcbiAgICB0aGlzLl9kZXB0aF9yYiA9IG51bGxcbiAgfVxuICBmb3IodmFyIGk9MDsgaTx0aGlzLmNvbG9yLmxlbmd0aDsgKytpKSB7XG4gICAgdGhpcy5jb2xvcltpXS5kaXNwb3NlKClcbiAgICB0aGlzLmNvbG9yW2ldID0gbnVsbFxuICB9XG4gIGlmKHRoaXMuX2NvbG9yX3JiKSB7XG4gICAgZ2wuZGVsZXRlUmVuZGVyYnVmZmVyKHRoaXMuX2NvbG9yX3JiKVxuICAgIHRoaXMuX2NvbG9yX3JiID0gbnVsbFxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUZCTyhnbCwgd2lkdGgsIGhlaWdodCwgb3B0aW9ucykge1xuXG4gIC8vVXBkYXRlIGZyYW1lIGJ1ZmZlciBlcnJvciBjb2RlIHZhbHVlc1xuICBpZighRlJBTUVCVUZGRVJfVU5TVVBQT1JURUQpIHtcbiAgICBGUkFNRUJVRkZFUl9VTlNVUFBPUlRFRCA9IGdsLkZSQU1FQlVGRkVSX1VOU1VQUE9SVEVEXG4gICAgRlJBTUVCVUZGRVJfSU5DT01QTEVURV9BVFRBQ0hNRU5UID0gZ2wuRlJBTUVCVUZGRVJfSU5DT01QTEVURV9BVFRBQ0hNRU5UXG4gICAgRlJBTUVCVUZGRVJfSU5DT01QTEVURV9ESU1FTlNJT05TID0gZ2wuRlJBTUVCVUZGRVJfSU5DT01QTEVURV9ESU1FTlNJT05TXG4gICAgRlJBTUVCVUZGRVJfSU5DT01QTEVURV9NSVNTSU5HX0FUVEFDSE1FTlQgPSBnbC5GUkFNRUJVRkZFUl9JTkNPTVBMRVRFX01JU1NJTkdfQVRUQUNITUVOVFxuICB9XG5cbiAgLy9MYXppbHkgaW5pdGlhbGl6ZSBjb2xvciBhdHRhY2htZW50IGFycmF5c1xuICB2YXIgV0VCR0xfZHJhd19idWZmZXJzID0gZ2wuZ2V0RXh0ZW5zaW9uKCdXRUJHTF9kcmF3X2J1ZmZlcnMnKVxuICBpZighY29sb3JBdHRhY2htZW50QXJyYXlzICYmIFdFQkdMX2RyYXdfYnVmZmVycykge1xuICAgIGxhenlJbml0Q29sb3JBdHRhY2htZW50cyhnbCwgV0VCR0xfZHJhd19idWZmZXJzKVxuICB9XG5cbiAgLy9TcGVjaWFsIGNhc2U6IENhbiBhY2NlcHQgYW4gYXJyYXkgYXMgYXJndW1lbnRcbiAgaWYoQXJyYXkuaXNBcnJheSh3aWR0aCkpIHtcbiAgICBvcHRpb25zID0gaGVpZ2h0XG4gICAgaGVpZ2h0ID0gd2lkdGhbMV18MFxuICAgIHdpZHRoID0gd2lkdGhbMF18MFxuICB9XG5cbiAgaWYodHlwZW9mIHdpZHRoICE9PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBNaXNzaW5nIHNoYXBlIHBhcmFtZXRlcicpXG4gIH1cblxuICAvL1ZhbGlkYXRlIHdpZHRoL2hlaWdodCBwcm9wZXJ0aWVzXG4gIHZhciBtYXhGQk9TaXplID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLk1BWF9SRU5ERVJCVUZGRVJfU0laRSlcbiAgaWYod2lkdGggPCAwIHx8IHdpZHRoID4gbWF4RkJPU2l6ZSB8fCBoZWlnaHQgPCAwIHx8IGhlaWdodCA+IG1heEZCT1NpemUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLWZibzogUGFyYW1ldGVycyBhcmUgdG9vIGxhcmdlIGZvciBGQk8nKVxuICB9XG5cbiAgLy9IYW5kbGUgZWFjaCBvcHRpb24gdHlwZVxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gIC8vRmlndXJlIG91dCBudW1iZXIgb2YgY29sb3IgYnVmZmVycyB0byB1c2VcbiAgdmFyIG51bUNvbG9ycyA9IDFcbiAgaWYoJ2NvbG9yJyBpbiBvcHRpb25zKSB7XG4gICAgbnVtQ29sb3JzID0gTWF0aC5tYXgob3B0aW9ucy5jb2xvcnwwLCAwKVxuICAgIGlmKG51bUNvbG9ycyA8IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBNdXN0IHNwZWNpZnkgYSBub25uZWdhdGl2ZSBudW1iZXIgb2YgY29sb3JzJylcbiAgICB9XG4gICAgaWYobnVtQ29sb3JzID4gMSkge1xuICAgICAgLy9DaGVjayBpZiBtdWx0aXBsZSByZW5kZXIgdGFyZ2V0cyBzdXBwb3J0ZWRcbiAgICAgIGlmKCFXRUJHTF9kcmF3X2J1ZmZlcnMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IE11bHRpcGxlIGRyYXcgYnVmZmVyIGV4dGVuc2lvbiBub3Qgc3VwcG9ydGVkJylcbiAgICAgIH0gZWxzZSBpZihudW1Db2xvcnMgPiBnbC5nZXRQYXJhbWV0ZXIoV0VCR0xfZHJhd19idWZmZXJzLk1BWF9DT0xPUl9BVFRBQ0hNRU5UU19XRUJHTCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1mYm86IENvbnRleHQgZG9lcyBub3Qgc3VwcG9ydCAnICsgbnVtQ29sb3JzICsgJyBkcmF3IGJ1ZmZlcnMnKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vRGV0ZXJtaW5lIHdoZXRoZXIgdG8gdXNlIGZsb2F0aW5nIHBvaW50IHRleHR1cmVzXG4gIHZhciBjb2xvclR5cGUgPSBnbC5VTlNJR05FRF9CWVRFXG4gIHZhciBPRVNfdGV4dHVyZV9mbG9hdCA9IGdsLmdldEV4dGVuc2lvbignT0VTX3RleHR1cmVfZmxvYXQnKVxuICBpZihvcHRpb25zLmZsb2F0ICYmIG51bUNvbG9ycyA+IDApIHtcbiAgICBpZighT0VTX3RleHR1cmVfZmxvYXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtZmJvOiBDb250ZXh0IGRvZXMgbm90IHN1cHBvcnQgZmxvYXRpbmcgcG9pbnQgdGV4dHVyZXMnKVxuICAgIH1cbiAgICBjb2xvclR5cGUgPSBnbC5GTE9BVFxuICB9IGVsc2UgaWYob3B0aW9ucy5wcmVmZXJGbG9hdCAmJiBudW1Db2xvcnMgPiAwKSB7XG4gICAgaWYoT0VTX3RleHR1cmVfZmxvYXQpIHtcbiAgICAgIGNvbG9yVHlwZSA9IGdsLkZMT0FUXG4gICAgfVxuICB9XG5cbiAgLy9DaGVjayBpZiB3ZSBzaG91bGQgdXNlIGRlcHRoIGJ1ZmZlclxuICB2YXIgdXNlRGVwdGggPSB0cnVlXG4gIGlmKCdkZXB0aCcgaW4gb3B0aW9ucykge1xuICAgIHVzZURlcHRoID0gISFvcHRpb25zLmRlcHRoXG4gIH1cblxuICAvL0NoZWNrIGlmIHdlIHNob3VsZCB1c2UgYSBzdGVuY2lsIGJ1ZmZlclxuICB2YXIgdXNlU3RlbmNpbCA9IGZhbHNlXG4gIGlmKCdzdGVuY2lsJyBpbiBvcHRpb25zKSB7XG4gICAgdXNlU3RlbmNpbCA9ICEhb3B0aW9ucy5zdGVuY2lsXG4gIH1cblxuICByZXR1cm4gbmV3IEZyYW1lYnVmZmVyKFxuICAgIGdsLFxuICAgIHdpZHRoLFxuICAgIGhlaWdodCxcbiAgICBjb2xvclR5cGUsXG4gICAgbnVtQ29sb3JzLFxuICAgIHVzZURlcHRoLFxuICAgIHVzZVN0ZW5jaWwsXG4gICAgV0VCR0xfZHJhd19idWZmZXJzKVxufVxuXG59LHtcImdsLXRleHR1cmUyZFwiOjMyMn1dLDI1MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cbnZhciBzcHJpbnRmID0gX2RlcmVxXygnc3ByaW50Zi1qcycpLnNwcmludGY7XG52YXIgZ2xDb25zdGFudHMgPSBfZGVyZXFfKCdnbC1jb25zdGFudHMvbG9va3VwJyk7XG52YXIgc2hhZGVyTmFtZSA9IF9kZXJlcV8oJ2dsc2wtc2hhZGVyLW5hbWUnKTtcbnZhciBhZGRMaW5lTnVtYmVycyA9IF9kZXJlcV8oJ2FkZC1saW5lLW51bWJlcnMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmb3JtYXRDb21waWxlckVycm9yO1xuXG5mdW5jdGlvbiBmb3JtYXRDb21waWxlckVycm9yKGVyckxvZywgc3JjLCB0eXBlKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICB2YXIgbmFtZSA9IHNoYWRlck5hbWUoc3JjKSB8fCAnb2YgdW5rbm93biBuYW1lIChzZWUgbnBtIGdsc2wtc2hhZGVyLW5hbWUpJztcblxuICAgIHZhciB0eXBlTmFtZSA9ICd1bmtub3duIHR5cGUnO1xuICAgIGlmICh0eXBlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdHlwZU5hbWUgPSB0eXBlID09PSBnbENvbnN0YW50cy5GUkFHTUVOVF9TSEFERVIgPyAnZnJhZ21lbnQnIDogJ3ZlcnRleCdcbiAgICB9XG5cbiAgICB2YXIgbG9uZ0Zvcm0gPSBzcHJpbnRmKCdFcnJvciBjb21waWxpbmcgJXMgc2hhZGVyICVzOlxcbicsIHR5cGVOYW1lLCBuYW1lKTtcbiAgICB2YXIgc2hvcnRGb3JtID0gc3ByaW50ZihcIiVzJXNcIiwgbG9uZ0Zvcm0sIGVyckxvZyk7XG5cbiAgICB2YXIgZXJyb3JTdHJpbmdzID0gZXJyTG9nLnNwbGl0KCdcXG4nKTtcbiAgICB2YXIgZXJyb3JzID0ge307XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVycm9yU3RyaW5ncy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZXJyb3JTdHJpbmcgPSBlcnJvclN0cmluZ3NbaV07XG4gICAgICAgIGlmIChlcnJvclN0cmluZyA9PT0gJycgfHwgZXJyb3JTdHJpbmcgPT09IFwiXFwwXCIpIGNvbnRpbnVlO1xuICAgICAgICB2YXIgbGluZU5vID0gcGFyc2VJbnQoZXJyb3JTdHJpbmcuc3BsaXQoJzonKVsyXSk7XG4gICAgICAgIGlmIChpc05hTihsaW5lTm8pKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3Ioc3ByaW50ZignQ291bGQgbm90IHBhcnNlIGVycm9yOiAlcycsIGVycm9yU3RyaW5nKSk7XG4gICAgICAgIH1cbiAgICAgICAgZXJyb3JzW2xpbmVOb10gPSBlcnJvclN0cmluZztcbiAgICB9XG5cbiAgICB2YXIgbGluZXMgPSBhZGRMaW5lTnVtYmVycyhzcmMpLnNwbGl0KCdcXG4nKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKCFlcnJvcnNbaSszXSAmJiAhZXJyb3JzW2krMl0gJiYgIWVycm9yc1tpKzFdKSBjb250aW51ZTtcbiAgICAgICAgdmFyIGxpbmUgPSBsaW5lc1tpXTtcbiAgICAgICAgbG9uZ0Zvcm0gKz0gbGluZSArICdcXG4nO1xuICAgICAgICBpZiAoZXJyb3JzW2krMV0pIHtcbiAgICAgICAgICAgIHZhciBlID0gZXJyb3JzW2krMV07XG4gICAgICAgICAgICBlID0gZS5zdWJzdHIoZS5zcGxpdCgnOicsIDMpLmpvaW4oJzonKS5sZW5ndGggKyAxKS50cmltKCk7XG4gICAgICAgICAgICBsb25nRm9ybSArPSBzcHJpbnRmKCdeXl4gJXNcXG5cXG4nLCBlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGxvbmc6IGxvbmdGb3JtLnRyaW0oKSxcbiAgICAgICAgc2hvcnQ6IHNob3J0Rm9ybS50cmltKClcbiAgICB9O1xufVxuXG5cbn0se1wiYWRkLWxpbmUtbnVtYmVyc1wiOjYxLFwiZ2wtY29uc3RhbnRzL2xvb2t1cFwiOjI0NixcImdsc2wtc2hhZGVyLW5hbWVcIjo0MDEsXCJzcHJpbnRmLWpzXCI6NTI4fV0sMjUxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUhlYXRtYXAyRFxuXG52YXIgYnNlYXJjaCA9IF9kZXJlcV8oJ2JpbmFyeS1zZWFyY2gtYm91bmRzJylcbnZhciBpb3RhID0gX2RlcmVxXygnaW90YS1hcnJheScpXG52YXIgcG9vbCA9IF9kZXJlcV8oJ3R5cGVkYXJyYXktcG9vbCcpXG52YXIgY3JlYXRlU2hhZGVyID0gX2RlcmVxXygnZ2wtc2hhZGVyJylcbnZhciBjcmVhdGVCdWZmZXIgPSBfZGVyZXFfKCdnbC1idWZmZXInKVxuXG52YXIgc2hhZGVycyA9IF9kZXJlcV8oJy4vbGliL3NoYWRlcnMnKVxuXG5mdW5jdGlvbiBHTEhlYXRtYXAyRCAoXG4gIHBsb3QsXG4gIHNoYWRlcixcbiAgcGlja1NoYWRlcixcbiAgcG9zaXRpb25CdWZmZXIsXG4gIHdlaWdodEJ1ZmZlcixcbiAgY29sb3JCdWZmZXIsXG4gIGlkQnVmZmVyKSB7XG4gIHRoaXMucGxvdCA9IHBsb3RcbiAgdGhpcy5zaGFkZXIgPSBzaGFkZXJcbiAgdGhpcy5waWNrU2hhZGVyID0gcGlja1NoYWRlclxuICB0aGlzLnBvc2l0aW9uQnVmZmVyID0gcG9zaXRpb25CdWZmZXJcbiAgdGhpcy53ZWlnaHRCdWZmZXIgPSB3ZWlnaHRCdWZmZXJcbiAgdGhpcy5jb2xvckJ1ZmZlciA9IGNvbG9yQnVmZmVyXG4gIHRoaXMuaWRCdWZmZXIgPSBpZEJ1ZmZlclxuICB0aGlzLnhEYXRhID0gW11cbiAgdGhpcy55RGF0YSA9IFtdXG4gIHRoaXMuc2hhcGUgPSBbMCwgMF1cbiAgdGhpcy5ib3VuZHMgPSBbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV1cbiAgdGhpcy5waWNrT2Zmc2V0ID0gMFxufVxuXG52YXIgcHJvdG8gPSBHTEhlYXRtYXAyRC5wcm90b3R5cGVcblxudmFyIFdFSUdIVFMgPSBbXG4gIDAsIDAsXG4gIDEsIDAsXG4gIDAsIDEsXG4gIDEsIDAsXG4gIDEsIDEsXG4gIDAsIDFcbl1cblxucHJvdG8uZHJhdyA9IChmdW5jdGlvbiAoKSB7XG4gIHZhciBNQVRSSVggPSBbXG4gICAgMSwgMCwgMCxcbiAgICAwLCAxLCAwLFxuICAgIDAsIDAsIDFcbiAgXVxuXG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHBsb3QgPSB0aGlzLnBsb3RcbiAgICB2YXIgc2hhZGVyID0gdGhpcy5zaGFkZXJcbiAgICB2YXIgYm91bmRzID0gdGhpcy5ib3VuZHNcbiAgICB2YXIgbnVtVmVydGljZXMgPSB0aGlzLm51bVZlcnRpY2VzXG5cbiAgICBpZiAobnVtVmVydGljZXMgPD0gMCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdmFyIGdsID0gcGxvdC5nbFxuICAgIHZhciBkYXRhQm94ID0gcGxvdC5kYXRhQm94XG5cbiAgICB2YXIgYm91bmRYID0gYm91bmRzWzJdIC0gYm91bmRzWzBdXG4gICAgdmFyIGJvdW5kWSA9IGJvdW5kc1szXSAtIGJvdW5kc1sxXVxuICAgIHZhciBkYXRhWCA9IGRhdGFCb3hbMl0gLSBkYXRhQm94WzBdXG4gICAgdmFyIGRhdGFZID0gZGF0YUJveFszXSAtIGRhdGFCb3hbMV1cblxuICAgIE1BVFJJWFswXSA9IDIuMCAqIGJvdW5kWCAvIGRhdGFYXG4gICAgTUFUUklYWzRdID0gMi4wICogYm91bmRZIC8gZGF0YVlcbiAgICBNQVRSSVhbNl0gPSAyLjAgKiAoYm91bmRzWzBdIC0gZGF0YUJveFswXSkgLyBkYXRhWCAtIDEuMFxuICAgIE1BVFJJWFs3XSA9IDIuMCAqIChib3VuZHNbMV0gLSBkYXRhQm94WzFdKSAvIGRhdGFZIC0gMS4wXG5cbiAgICBzaGFkZXIuYmluZCgpXG5cbiAgICB2YXIgdW5pZm9ybXMgPSBzaGFkZXIudW5pZm9ybXNcbiAgICB1bmlmb3Jtcy52aWV3VHJhbnNmb3JtID0gTUFUUklYXG5cbiAgICB1bmlmb3Jtcy5zaGFwZSA9IHRoaXMuc2hhcGVcblxuICAgIHZhciBhdHRyaWJ1dGVzID0gc2hhZGVyLmF0dHJpYnV0ZXNcbiAgICB0aGlzLnBvc2l0aW9uQnVmZmVyLmJpbmQoKVxuICAgIGF0dHJpYnV0ZXMucG9zaXRpb24ucG9pbnRlcigpXG5cbiAgICB0aGlzLndlaWdodEJ1ZmZlci5iaW5kKClcbiAgICBhdHRyaWJ1dGVzLndlaWdodC5wb2ludGVyKGdsLlVOU0lHTkVEX0JZVEUsIGZhbHNlKVxuXG4gICAgdGhpcy5jb2xvckJ1ZmZlci5iaW5kKClcbiAgICBhdHRyaWJ1dGVzLmNvbG9yLnBvaW50ZXIoZ2wuVU5TSUdORURfQllURSwgdHJ1ZSlcblxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCAwLCBudW1WZXJ0aWNlcylcbiAgfVxufSkoKVxuXG5wcm90by5kcmF3UGljayA9IChmdW5jdGlvbiAoKSB7XG4gIHZhciBNQVRSSVggPSBbXG4gICAgMSwgMCwgMCxcbiAgICAwLCAxLCAwLFxuICAgIDAsIDAsIDFcbiAgXVxuXG4gIHZhciBQSUNLX1ZFQ1RPUiA9IFswLCAwLCAwLCAwXVxuXG4gIHJldHVybiBmdW5jdGlvbiAocGlja09mZnNldCkge1xuICAgIHZhciBwbG90ID0gdGhpcy5wbG90XG4gICAgdmFyIHNoYWRlciA9IHRoaXMucGlja1NoYWRlclxuICAgIHZhciBib3VuZHMgPSB0aGlzLmJvdW5kc1xuICAgIHZhciBudW1WZXJ0aWNlcyA9IHRoaXMubnVtVmVydGljZXNcblxuICAgIGlmIChudW1WZXJ0aWNlcyA8PSAwKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB2YXIgZ2wgPSBwbG90LmdsXG4gICAgdmFyIGRhdGFCb3ggPSBwbG90LmRhdGFCb3hcblxuICAgIHZhciBib3VuZFggPSBib3VuZHNbMl0gLSBib3VuZHNbMF1cbiAgICB2YXIgYm91bmRZID0gYm91bmRzWzNdIC0gYm91bmRzWzFdXG4gICAgdmFyIGRhdGFYID0gZGF0YUJveFsyXSAtIGRhdGFCb3hbMF1cbiAgICB2YXIgZGF0YVkgPSBkYXRhQm94WzNdIC0gZGF0YUJveFsxXVxuXG4gICAgTUFUUklYWzBdID0gMi4wICogYm91bmRYIC8gZGF0YVhcbiAgICBNQVRSSVhbNF0gPSAyLjAgKiBib3VuZFkgLyBkYXRhWVxuICAgIE1BVFJJWFs2XSA9IDIuMCAqIChib3VuZHNbMF0gLSBkYXRhQm94WzBdKSAvIGRhdGFYIC0gMS4wXG4gICAgTUFUUklYWzddID0gMi4wICogKGJvdW5kc1sxXSAtIGRhdGFCb3hbMV0pIC8gZGF0YVkgLSAxLjBcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNDsgKytpKSB7XG4gICAgICBQSUNLX1ZFQ1RPUltpXSA9IChwaWNrT2Zmc2V0ID4+IChpICogOCkpICYgMHhmZlxuICAgIH1cblxuICAgIHRoaXMucGlja09mZnNldCA9IHBpY2tPZmZzZXRcblxuICAgIHNoYWRlci5iaW5kKClcblxuICAgIHZhciB1bmlmb3JtcyA9IHNoYWRlci51bmlmb3Jtc1xuICAgIHVuaWZvcm1zLnZpZXdUcmFuc2Zvcm0gPSBNQVRSSVhcbiAgICB1bmlmb3Jtcy5waWNrT2Zmc2V0ID0gUElDS19WRUNUT1JcbiAgICB1bmlmb3Jtcy5zaGFwZSA9IHRoaXMuc2hhcGVcblxuICAgIHZhciBhdHRyaWJ1dGVzID0gc2hhZGVyLmF0dHJpYnV0ZXNcbiAgICB0aGlzLnBvc2l0aW9uQnVmZmVyLmJpbmQoKVxuICAgIGF0dHJpYnV0ZXMucG9zaXRpb24ucG9pbnRlcigpXG5cbiAgICB0aGlzLndlaWdodEJ1ZmZlci5iaW5kKClcbiAgICBhdHRyaWJ1dGVzLndlaWdodC5wb2ludGVyKGdsLlVOU0lHTkVEX0JZVEUsIGZhbHNlKVxuXG4gICAgdGhpcy5pZEJ1ZmZlci5iaW5kKClcbiAgICBhdHRyaWJ1dGVzLnBpY2tJZC5wb2ludGVyKGdsLlVOU0lHTkVEX0JZVEUsIGZhbHNlKVxuXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIDAsIG51bVZlcnRpY2VzKVxuXG4gICAgcmV0dXJuIHBpY2tPZmZzZXQgKyB0aGlzLnNoYXBlWzBdICogdGhpcy5zaGFwZVsxXVxuICB9XG59KSgpXG5cbnByb3RvLnBpY2sgPSBmdW5jdGlvbiAoeCwgeSwgdmFsdWUpIHtcbiAgdmFyIHBpY2tPZmZzZXQgPSB0aGlzLnBpY2tPZmZzZXRcbiAgdmFyIHBvaW50Q291bnQgPSB0aGlzLnNoYXBlWzBdICogdGhpcy5zaGFwZVsxXVxuICBpZiAodmFsdWUgPCBwaWNrT2Zmc2V0IHx8IHZhbHVlID49IHBpY2tPZmZzZXQgKyBwb2ludENvdW50KSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICB2YXIgcG9pbnRJZCA9IHZhbHVlIC0gcGlja09mZnNldFxuICB2YXIgeERhdGEgPSB0aGlzLnhEYXRhXG4gIHZhciB5RGF0YSA9IHRoaXMueURhdGFcbiAgcmV0dXJuIHtcbiAgICBvYmplY3Q6IHRoaXMsXG4gICAgcG9pbnRJZDogcG9pbnRJZCxcbiAgICBkYXRhQ29vcmQ6IFtcbiAgICAgIHhEYXRhW3BvaW50SWQgJSB0aGlzLnNoYXBlWzBdXSxcbiAgICAgIHlEYXRhWyhwb2ludElkIC8gdGhpcy5zaGFwZVswXSkgfCAwXV1cbiAgfVxufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gIHZhciBzaGFwZSA9IG9wdGlvbnMuc2hhcGUgfHwgWzAsIDBdXG5cbiAgdmFyIHggPSBvcHRpb25zLnggfHwgaW90YShzaGFwZVswXSlcbiAgdmFyIHkgPSBvcHRpb25zLnkgfHwgaW90YShzaGFwZVsxXSlcbiAgdmFyIHogPSBvcHRpb25zLnogfHwgbmV3IEZsb2F0MzJBcnJheShzaGFwZVswXSAqIHNoYXBlWzFdKVxuXG4gIHRoaXMueERhdGEgPSB4XG4gIHRoaXMueURhdGEgPSB5XG5cbiAgdmFyIGNvbG9yTGV2ZWxzID0gb3B0aW9ucy5jb2xvckxldmVscyB8fCBbMF1cbiAgdmFyIGNvbG9yVmFsdWVzID0gb3B0aW9ucy5jb2xvclZhbHVlcyB8fCBbMCwgMCwgMCwgMV1cbiAgdmFyIGNvbG9yQ291bnQgPSBjb2xvckxldmVscy5sZW5ndGhcblxuICB2YXIgYm91bmRzID0gdGhpcy5ib3VuZHNcbiAgdmFyIGxveCA9IGJvdW5kc1swXSA9IHhbMF1cbiAgdmFyIGxveSA9IGJvdW5kc1sxXSA9IHlbMF1cbiAgdmFyIGhpeCA9IGJvdW5kc1syXSA9IHhbeC5sZW5ndGggLSAxXVxuICB2YXIgaGl5ID0gYm91bmRzWzNdID0geVt5Lmxlbmd0aCAtIDFdXG5cbiAgdmFyIHhzID0gMS4wIC8gKGhpeCAtIGxveClcbiAgdmFyIHlzID0gMS4wIC8gKGhpeSAtIGxveSlcblxuICB2YXIgbnVtWCA9IHNoYXBlWzBdXG4gIHZhciBudW1ZID0gc2hhcGVbMV1cblxuICB0aGlzLnNoYXBlID0gW251bVgsIG51bVldXG5cbiAgdmFyIG51bVZlcnRzID0gKG51bVggLSAxKSAqIChudW1ZIC0gMSkgKiAoV0VJR0hUUy5sZW5ndGggPj4+IDEpXG5cbiAgdGhpcy5udW1WZXJ0aWNlcyA9IG51bVZlcnRzXG5cbiAgdmFyIGNvbG9ycyA9IHBvb2wubWFsbG9jVWludDgobnVtVmVydHMgKiA0KVxuICB2YXIgcG9zaXRpb25zID0gcG9vbC5tYWxsb2NGbG9hdDMyKG51bVZlcnRzICogMilcbiAgdmFyIHdlaWdodHMgICA9IHBvb2wubWFsbG9jVWludDggKG51bVZlcnRzICogMilcbiAgdmFyIGlkcyA9IHBvb2wubWFsbG9jVWludDMyKG51bVZlcnRzKVxuXG4gIHZhciBwdHIgPSAwXG5cbiAgZm9yICh2YXIgaiA9IDA7IGogPCBudW1ZIC0gMTsgKytqKSB7XG4gICAgdmFyIHljMCA9IHlzICogKHlbal0gLSBsb3kpXG4gICAgdmFyIHljMSA9IHlzICogKHlbaiArIDFdIC0gbG95KVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtWCAtIDE7ICsraSkge1xuICAgICAgdmFyIHhjMCA9IHhzICogKHhbaV0gLSBsb3gpXG4gICAgICB2YXIgeGMxID0geHMgKiAoeFtpICsgMV0gLSBsb3gpXG5cbiAgICAgIGZvciAodmFyIGRkID0gMDsgZGQgPCBXRUlHSFRTLmxlbmd0aDsgZGQgKz0gMikge1xuICAgICAgICB2YXIgZHggPSBXRUlHSFRTW2RkXVxuICAgICAgICB2YXIgZHkgPSBXRUlHSFRTW2RkICsgMV1cbiAgICAgICAgdmFyIG9mZnNldCA9IChqICsgZHkpICogbnVtWCArIChpICsgZHgpXG4gICAgICAgIHZhciB6YyA9IHpbb2Zmc2V0XVxuICAgICAgICB2YXIgY29sb3JJZHggPSBic2VhcmNoLmxlKGNvbG9yTGV2ZWxzLCB6YylcbiAgICAgICAgdmFyIHIsIGcsIGIsIGFcbiAgICAgICAgaWYgKGNvbG9ySWR4IDwgMCkge1xuICAgICAgICAgIHIgPSBjb2xvclZhbHVlc1swXVxuICAgICAgICAgIGcgPSBjb2xvclZhbHVlc1sxXVxuICAgICAgICAgIGIgPSBjb2xvclZhbHVlc1syXVxuICAgICAgICAgIGEgPSBjb2xvclZhbHVlc1szXVxuICAgICAgICB9IGVsc2UgaWYgKGNvbG9ySWR4ID09PSBjb2xvckNvdW50IC0gMSkge1xuICAgICAgICAgIHIgPSBjb2xvclZhbHVlc1s0ICogY29sb3JDb3VudCAtIDRdXG4gICAgICAgICAgZyA9IGNvbG9yVmFsdWVzWzQgKiBjb2xvckNvdW50IC0gM11cbiAgICAgICAgICBiID0gY29sb3JWYWx1ZXNbNCAqIGNvbG9yQ291bnQgLSAyXVxuICAgICAgICAgIGEgPSBjb2xvclZhbHVlc1s0ICogY29sb3JDb3VudCAtIDFdXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHQgPSAoemMgLSBjb2xvckxldmVsc1tjb2xvcklkeF0pIC9cbiAgICAgICAgICAgIChjb2xvckxldmVsc1tjb2xvcklkeCArIDFdIC0gY29sb3JMZXZlbHNbY29sb3JJZHhdKVxuICAgICAgICAgIHZhciB0aSA9IDEuMCAtIHRcbiAgICAgICAgICB2YXIgaTAgPSA0ICogY29sb3JJZHhcbiAgICAgICAgICB2YXIgaTEgPSA0ICogKGNvbG9ySWR4ICsgMSlcbiAgICAgICAgICByID0gdGkgKiBjb2xvclZhbHVlc1tpMF0gKyB0ICogY29sb3JWYWx1ZXNbaTFdXG4gICAgICAgICAgZyA9IHRpICogY29sb3JWYWx1ZXNbaTAgKyAxXSArIHQgKiBjb2xvclZhbHVlc1tpMSArIDFdXG4gICAgICAgICAgYiA9IHRpICogY29sb3JWYWx1ZXNbaTAgKyAyXSArIHQgKiBjb2xvclZhbHVlc1tpMSArIDJdXG4gICAgICAgICAgYSA9IHRpICogY29sb3JWYWx1ZXNbaTAgKyAzXSArIHQgKiBjb2xvclZhbHVlc1tpMSArIDNdXG4gICAgICAgIH1cblxuICAgICAgICBjb2xvcnNbNCAqIHB0cl0gPSAyNTUgKiByXG4gICAgICAgIGNvbG9yc1s0ICogcHRyICsgMV0gPSAyNTUgKiBnXG4gICAgICAgIGNvbG9yc1s0ICogcHRyICsgMl0gPSAyNTUgKiBiXG4gICAgICAgIGNvbG9yc1s0ICogcHRyICsgM10gPSAyNTUgKiBhXG5cbiAgICAgICAgcG9zaXRpb25zWzIqcHRyXSA9IHhjMCouNSArIHhjMSouNTtcbiAgICAgICAgcG9zaXRpb25zWzIqcHRyKzFdID0geWMwKi41ICsgeWMxKi41O1xuXG4gICAgICAgIHdlaWdodHNbMipwdHJdID0gZHg7XG4gICAgICAgIHdlaWdodHNbMipwdHIrMV0gPSBkeTtcblxuICAgICAgICBpZHNbcHRyXSA9IGogKiBudW1YICsgaVxuXG4gICAgICAgIHB0ciArPSAxXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdGhpcy5wb3NpdGlvbkJ1ZmZlci51cGRhdGUocG9zaXRpb25zKVxuICB0aGlzLndlaWdodEJ1ZmZlci51cGRhdGUod2VpZ2h0cylcbiAgdGhpcy5jb2xvckJ1ZmZlci51cGRhdGUoY29sb3JzKVxuICB0aGlzLmlkQnVmZmVyLnVwZGF0ZShpZHMpXG5cbiAgcG9vbC5mcmVlKHBvc2l0aW9ucylcbiAgcG9vbC5mcmVlKGNvbG9ycylcbiAgcG9vbC5mcmVlKHdlaWdodHMpXG4gIHBvb2wuZnJlZShpZHMpXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiAoKSB7XG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxuICB0aGlzLnBpY2tTaGFkZXIuZGlzcG9zZSgpXG4gIHRoaXMucG9zaXRpb25CdWZmZXIuZGlzcG9zZSgpXG4gIHRoaXMud2VpZ2h0QnVmZmVyLmRpc3Bvc2UoKVxuICB0aGlzLmNvbG9yQnVmZmVyLmRpc3Bvc2UoKVxuICB0aGlzLmlkQnVmZmVyLmRpc3Bvc2UoKVxuICB0aGlzLnBsb3QucmVtb3ZlT2JqZWN0KHRoaXMpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUhlYXRtYXAyRCAocGxvdCwgb3B0aW9ucykge1xuICB2YXIgZ2wgPSBwbG90LmdsXG5cbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgc2hhZGVycy52ZXJ0ZXgsIHNoYWRlcnMuZnJhZ21lbnQpXG4gIHZhciBwaWNrU2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBzaGFkZXJzLnBpY2tWZXJ0ZXgsIHNoYWRlcnMucGlja0ZyYWdtZW50KVxuXG4gIHZhciBwb3NpdGlvbkJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHdlaWdodEJ1ZmZlciAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgY29sb3JCdWZmZXIgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBpZEJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcblxuICB2YXIgaGVhdG1hcCA9IG5ldyBHTEhlYXRtYXAyRChcbiAgICBwbG90LFxuICAgIHNoYWRlcixcbiAgICBwaWNrU2hhZGVyLFxuICAgIHBvc2l0aW9uQnVmZmVyLFxuICAgIHdlaWdodEJ1ZmZlcixcbiAgICBjb2xvckJ1ZmZlcixcbiAgICBpZEJ1ZmZlcilcblxuICBoZWF0bWFwLnVwZGF0ZShvcHRpb25zKVxuICBwbG90LmFkZE9iamVjdChoZWF0bWFwKVxuXG4gIHJldHVybiBoZWF0bWFwXG59XG5cbn0se1wiLi9saWIvc2hhZGVyc1wiOjI1MixcImJpbmFyeS1zZWFyY2gtYm91bmRzXCI6MjUzLFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtc2hhZGVyXCI6MzAxLFwiaW90YS1hcnJheVwiOjQxNixcInR5cGVkYXJyYXktcG9vbFwiOjU0NX1dLDI1MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGdsc2xpZnkgPSBfZGVyZXFfKCdnbHNsaWZ5JylcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGZyYWdtZW50OiAgICAgZ2xzbGlmeShbXCJwcmVjaXNpb24gbG93cCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxudm9pZCBtYWluKCkge1xcbiAgZ2xfRnJhZ0NvbG9yID0gdmVjNChmcmFnQ29sb3IucmdiICogZnJhZ0NvbG9yLmEsIGZyYWdDb2xvci5hKTtcXG59XFxuXCJdKSxcbiAgdmVydGV4OiAgICAgICBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzIgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzQgY29sb3I7XFxuYXR0cmlidXRlIHZlYzIgd2VpZ2h0O1xcblxcbnVuaWZvcm0gdmVjMiBzaGFwZTtcXG51bmlmb3JtIG1hdDMgdmlld1RyYW5zZm9ybTtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzMgdlBvc2l0aW9uID0gdmlld1RyYW5zZm9ybSAqIHZlYzMoIHBvc2l0aW9uICsgKHdlaWdodC0uNSkvKHNoYXBlLTEuKSAsIDEuMCk7XFxuICBmcmFnQ29sb3IgPSBjb2xvcjtcXG4gIGdsX1Bvc2l0aW9uID0gdmVjNCh2UG9zaXRpb24ueHksIDAsIHZQb3NpdGlvbi56KTtcXG59XFxuXCJdKSxcbiAgcGlja0ZyYWdtZW50OiBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudmFyeWluZyB2ZWM0IGZyYWdJZDtcXG52YXJ5aW5nIHZlYzIgdldlaWdodDtcXG5cXG51bmlmb3JtIHZlYzIgc2hhcGU7XFxudW5pZm9ybSB2ZWM0IHBpY2tPZmZzZXQ7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMiBkID0gc3RlcCguNSwgdldlaWdodCk7XFxuICB2ZWM0IGlkID0gZnJhZ0lkICsgcGlja09mZnNldDtcXG4gIGlkLnggKz0gZC54ICsgZC55KnNoYXBlLng7XFxuXFxuICBpZC55ICs9IGZsb29yKGlkLnggLyAyNTYuMCk7XFxuICBpZC54IC09IGZsb29yKGlkLnggLyAyNTYuMCkgKiAyNTYuMDtcXG5cXG4gIGlkLnogKz0gZmxvb3IoaWQueSAvIDI1Ni4wKTtcXG4gIGlkLnkgLT0gZmxvb3IoaWQueSAvIDI1Ni4wKSAqIDI1Ni4wO1xcblxcbiAgaWQudyArPSBmbG9vcihpZC56IC8gMjU2LjApO1xcbiAgaWQueiAtPSBmbG9vcihpZC56IC8gMjU2LjApICogMjU2LjA7XFxuXFxuICBnbF9GcmFnQ29sb3IgPSBpZC8yNTUuO1xcbn1cXG5cIl0pLFxuICBwaWNrVmVydGV4OiAgIGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMiBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjNCBwaWNrSWQ7XFxuYXR0cmlidXRlIHZlYzIgd2VpZ2h0O1xcblxcbnVuaWZvcm0gdmVjMiBzaGFwZTtcXG51bmlmb3JtIG1hdDMgdmlld1RyYW5zZm9ybTtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0lkO1xcbnZhcnlpbmcgdmVjMiB2V2VpZ2h0O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZXZWlnaHQgPSB3ZWlnaHQ7XFxuXFxuICBmcmFnSWQgPSBwaWNrSWQ7XFxuXFxuICB2ZWMzIHZQb3NpdGlvbiA9IHZpZXdUcmFuc2Zvcm0gKiB2ZWMzKCBwb3NpdGlvbiArICh3ZWlnaHQtLjUpLyhzaGFwZS0xLikgLCAxLjApO1xcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHZQb3NpdGlvbi54eSwgMCwgdlBvc2l0aW9uLnopO1xcbn1cXG5cIl0pXG59XG5cbn0se1wiZ2xzbGlmeVwiOjQwOX1dLDI1MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5hcmd1bWVudHNbNF1bMTExXVswXS5hcHBseShleHBvcnRzLGFyZ3VtZW50cylcbn0se1wiZHVwXCI6MTExfV0sMjU0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciBnbHNsaWZ5ICAgICAgID0gX2RlcmVxXygnZ2xzbGlmeScpXG52YXIgY3JlYXRlU2hhZGVyICA9IF9kZXJlcV8oJ2dsLXNoYWRlcicpXG5cbnZhciB2ZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbiwgbmV4dFBvc2l0aW9uO1xcbmF0dHJpYnV0ZSBmbG9hdCBhcmNMZW5ndGgsIGxpbmVXaWR0aDtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvcjtcXG5cXG51bmlmb3JtIHZlYzIgc2NyZWVuU2hhcGU7XFxudW5pZm9ybSBmbG9hdCBwaXhlbFJhdGlvO1xcbnVuaWZvcm0gbWF0NCBtb2RlbCwgdmlldywgcHJvamVjdGlvbjtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcbnZhcnlpbmcgdmVjMyB3b3JsZFBvc2l0aW9uO1xcbnZhcnlpbmcgZmxvYXQgcGl4ZWxBcmNMZW5ndGg7XFxuXFxudmVjNCBwcm9qZWN0KHZlYzMgcCkge1xcbiAgcmV0dXJuIHByb2plY3Rpb24gKiB2aWV3ICogbW9kZWwgKiB2ZWM0KHAsIDEuMCk7XFxufVxcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzQgc3RhcnRQb2ludCA9IHByb2plY3QocG9zaXRpb24pO1xcbiAgdmVjNCBlbmRQb2ludCAgID0gcHJvamVjdChuZXh0UG9zaXRpb24pO1xcblxcbiAgdmVjMiBBID0gc3RhcnRQb2ludC54eSAvIHN0YXJ0UG9pbnQudztcXG4gIHZlYzIgQiA9ICAgZW5kUG9pbnQueHkgLyAgIGVuZFBvaW50Lnc7XFxuXFxuICBmbG9hdCBjbGlwQW5nbGUgPSBhdGFuKFxcbiAgICAoQi55IC0gQS55KSAqIHNjcmVlblNoYXBlLnksXFxuICAgIChCLnggLSBBLngpICogc2NyZWVuU2hhcGUueFxcbiAgKTtcXG5cXG4gIHZlYzIgb2Zmc2V0ID0gMC41ICogcGl4ZWxSYXRpbyAqIGxpbmVXaWR0aCAqIHZlYzIoXFxuICAgIHNpbihjbGlwQW5nbGUpLFxcbiAgICAtY29zKGNsaXBBbmdsZSlcXG4gICkgLyBzY3JlZW5TaGFwZTtcXG5cXG4gIGdsX1Bvc2l0aW9uID0gdmVjNChzdGFydFBvaW50Lnh5ICsgc3RhcnRQb2ludC53ICogb2Zmc2V0LCBzdGFydFBvaW50Lnp3KTtcXG5cXG4gIHdvcmxkUG9zaXRpb24gPSBwb3NpdGlvbjtcXG4gIHBpeGVsQXJjTGVuZ3RoID0gYXJjTGVuZ3RoO1xcbiAgZnJhZ0NvbG9yID0gY29sb3I7XFxufVxcblwiXSlcbnZhciBmb3J3YXJkRnJhZyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzICAgICAgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIHNhbXBsZXIyRCBkYXNoVGV4dHVyZTtcXG51bmlmb3JtIGZsb2F0ICAgICBkYXNoU2NhbGU7XFxudW5pZm9ybSBmbG9hdCAgICAgb3BhY2l0eTtcXG5cXG52YXJ5aW5nIHZlYzMgICAgd29ybGRQb3NpdGlvbjtcXG52YXJ5aW5nIGZsb2F0ICAgcGl4ZWxBcmNMZW5ndGg7XFxudmFyeWluZyB2ZWM0ICAgIGZyYWdDb2xvcjtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAoXFxuICAgIG91dE9mUmFuZ2UoY2xpcEJvdW5kc1swXSwgY2xpcEJvdW5kc1sxXSwgd29ybGRQb3NpdGlvbikgfHxcXG4gICAgZnJhZ0NvbG9yLmEgKiBvcGFjaXR5ID09IDAuXFxuICApIGRpc2NhcmQ7XFxuXFxuICBmbG9hdCBkYXNoV2VpZ2h0ID0gdGV4dHVyZTJEKGRhc2hUZXh0dXJlLCB2ZWMyKGRhc2hTY2FsZSAqIHBpeGVsQXJjTGVuZ3RoLCAwKSkucjtcXG4gIGlmKGRhc2hXZWlnaHQgPCAwLjUpIHtcXG4gICAgZGlzY2FyZDtcXG4gIH1cXG4gIGdsX0ZyYWdDb2xvciA9IGZyYWdDb2xvciAqIG9wYWNpdHk7XFxufVxcblwiXSlcbnZhciBwaWNrRnJhZyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuI2RlZmluZSBGTE9BVF9NQVggIDEuNzAxNDExODRlMzhcXG4jZGVmaW5lIEZMT0FUX01JTiAgMS4xNzU0OTQzNWUtMzhcXG5cXG5sb3dwIHZlYzQgZW5jb2RlX2Zsb2F0XzE1NDAyNTkxMzAoaGlnaHAgZmxvYXQgdikge1xcbiAgaGlnaHAgZmxvYXQgYXYgPSBhYnModik7XFxuXFxuICAvL0hhbmRsZSBzcGVjaWFsIGNhc2VzXFxuICBpZihhdiA8IEZMT0FUX01JTikge1xcbiAgICByZXR1cm4gdmVjNCgwLjAsIDAuMCwgMC4wLCAwLjApO1xcbiAgfSBlbHNlIGlmKHYgPiBGTE9BVF9NQVgpIHtcXG4gICAgcmV0dXJuIHZlYzQoMTI3LjAsIDEyOC4wLCAwLjAsIDAuMCkgLyAyNTUuMDtcXG4gIH0gZWxzZSBpZih2IDwgLUZMT0FUX01BWCkge1xcbiAgICByZXR1cm4gdmVjNCgyNTUuMCwgMTI4LjAsIDAuMCwgMC4wKSAvIDI1NS4wO1xcbiAgfVxcblxcbiAgaGlnaHAgdmVjNCBjID0gdmVjNCgwLDAsMCwwKTtcXG5cXG4gIC8vQ29tcHV0ZSBleHBvbmVudCBhbmQgbWFudGlzc2FcXG4gIGhpZ2hwIGZsb2F0IGUgPSBmbG9vcihsb2cyKGF2KSk7XFxuICBoaWdocCBmbG9hdCBtID0gYXYgKiBwb3coMi4wLCAtZSkgLSAxLjA7XFxuICBcXG4gIC8vVW5wYWNrIG1hbnRpc3NhXFxuICBjWzFdID0gZmxvb3IoMTI4LjAgKiBtKTtcXG4gIG0gLT0gY1sxXSAvIDEyOC4wO1xcbiAgY1syXSA9IGZsb29yKDMyNzY4LjAgKiBtKTtcXG4gIG0gLT0gY1syXSAvIDMyNzY4LjA7XFxuICBjWzNdID0gZmxvb3IoODM4ODYwOC4wICogbSk7XFxuICBcXG4gIC8vVW5wYWNrIGV4cG9uZW50XFxuICBoaWdocCBmbG9hdCBlYmlhcyA9IGUgKyAxMjcuMDtcXG4gIGNbMF0gPSBmbG9vcihlYmlhcyAvIDIuMCk7XFxuICBlYmlhcyAtPSBjWzBdICogMi4wO1xcbiAgY1sxXSArPSBmbG9vcihlYmlhcykgKiAxMjguMDsgXFxuXFxuICAvL1VucGFjayBzaWduIGJpdFxcbiAgY1swXSArPSAxMjguMCAqIHN0ZXAoMC4wLCAtdik7XFxuXFxuICAvL1NjYWxlIGJhY2sgdG8gcmFuZ2VcXG4gIHJldHVybiBjIC8gMjU1LjA7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbnVuaWZvcm0gZmxvYXQgcGlja0lkO1xcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcblxcbnZhcnlpbmcgdmVjMyB3b3JsZFBvc2l0aW9uO1xcbnZhcnlpbmcgZmxvYXQgcGl4ZWxBcmNMZW5ndGg7XFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCB3b3JsZFBvc2l0aW9uKSkgZGlzY2FyZDtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IHZlYzQocGlja0lkLzI1NS4wLCBlbmNvZGVfZmxvYXRfMTU0MDI1OTEzMChwaXhlbEFyY0xlbmd0aCkueHl6KTtcXG59XCJdKVxuXG52YXIgQVRUUklCVVRFUyA9IFtcbiAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXG4gIHtuYW1lOiAnbmV4dFBvc2l0aW9uJywgdHlwZTogJ3ZlYzMnfSxcbiAge25hbWU6ICdhcmNMZW5ndGgnLCB0eXBlOiAnZmxvYXQnfSxcbiAge25hbWU6ICdsaW5lV2lkdGgnLCB0eXBlOiAnZmxvYXQnfSxcbiAge25hbWU6ICdjb2xvcicsIHR5cGU6ICd2ZWM0J31cbl1cblxuZXhwb3J0cy5jcmVhdGVTaGFkZXIgPSBmdW5jdGlvbihnbCkge1xuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCB2ZXJ0U3JjLCBmb3J3YXJkRnJhZywgbnVsbCwgQVRUUklCVVRFUylcbn1cblxuZXhwb3J0cy5jcmVhdGVQaWNrU2hhZGVyID0gZnVuY3Rpb24oZ2wpIHtcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgdmVydFNyYywgcGlja0ZyYWcsIG51bGwsIEFUVFJJQlVURVMpXG59XG5cbn0se1wiZ2wtc2hhZGVyXCI6MzAxLFwiZ2xzbGlmeVwiOjQwOX1dLDI1NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVMaW5lUGxvdFxuXG52YXIgY3JlYXRlQnVmZmVyID0gX2RlcmVxXygnZ2wtYnVmZmVyJylcbnZhciBjcmVhdGVWQU8gPSBfZGVyZXFfKCdnbC12YW8nKVxudmFyIGNyZWF0ZVRleHR1cmUgPSBfZGVyZXFfKCdnbC10ZXh0dXJlMmQnKVxudmFyIHVucGFja0Zsb2F0ID0gX2RlcmVxXygnZ2xzbC1yZWFkLWZsb2F0JylcbnZhciBic2VhcmNoID0gX2RlcmVxXygnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxudmFyIG5kYXJyYXkgPSBfZGVyZXFfKCduZGFycmF5JylcbnZhciBzaGFkZXJzID0gX2RlcmVxXygnLi9saWIvc2hhZGVycycpXG5cbnZhciBjcmVhdGVTaGFkZXIgPSBzaGFkZXJzLmNyZWF0ZVNoYWRlclxudmFyIGNyZWF0ZVBpY2tTaGFkZXIgPSBzaGFkZXJzLmNyZWF0ZVBpY2tTaGFkZXJcblxudmFyIGlkZW50aXR5ID0gWzEsIDAsIDAsIDAsXG4gIDAsIDEsIDAsIDAsXG4gIDAsIDAsIDEsIDAsXG4gIDAsIDAsIDAsIDFdXG5cbmZ1bmN0aW9uIGRpc3RhbmNlIChhLCBiKSB7XG4gIHZhciBzID0gMC4wXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgdmFyIGQgPSBhW2ldIC0gYltpXVxuICAgIHMgKz0gZCAqIGRcbiAgfVxuICByZXR1cm4gTWF0aC5zcXJ0KHMpXG59XG5cbmZ1bmN0aW9uIGZpbHRlckNsaXBCb3VuZHMgKGJvdW5kcykge1xuICB2YXIgcmVzdWx0ID0gW1stMWU2LCAtMWU2LCAtMWU2XSwgWzFlNiwgMWU2LCAxZTZdXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgIHJlc3VsdFswXVtpXSA9IE1hdGgubWF4KGJvdW5kc1swXVtpXSwgcmVzdWx0WzBdW2ldKVxuICAgIHJlc3VsdFsxXVtpXSA9IE1hdGgubWluKGJvdW5kc1sxXVtpXSwgcmVzdWx0WzFdW2ldKVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gUGlja1Jlc3VsdCAodGF1LCBwb3NpdGlvbiwgaW5kZXgsIGRhdGFDb29yZGluYXRlKSB7XG4gIHRoaXMuYXJjTGVuZ3RoID0gdGF1XG4gIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvblxuICB0aGlzLmluZGV4ID0gaW5kZXhcbiAgdGhpcy5kYXRhQ29vcmRpbmF0ZSA9IGRhdGFDb29yZGluYXRlXG59XG5cbmZ1bmN0aW9uIExpbmVQbG90IChnbCwgc2hhZGVyLCBwaWNrU2hhZGVyLCBidWZmZXIsIHZhbywgdGV4dHVyZSkge1xuICB0aGlzLmdsID0gZ2xcbiAgdGhpcy5zaGFkZXIgPSBzaGFkZXJcbiAgdGhpcy5waWNrU2hhZGVyID0gcGlja1NoYWRlclxuICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlclxuICB0aGlzLnZhbyA9IHZhb1xuICB0aGlzLmNsaXBCb3VuZHMgPSBbXG4gICAgWyAtSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5IF0sXG4gICAgWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5IF1dXG4gIHRoaXMucG9pbnRzID0gW11cbiAgdGhpcy5hcmNMZW5ndGggPSBbXVxuICB0aGlzLnZlcnRleENvdW50ID0gMFxuICB0aGlzLmJvdW5kcyA9IFtbMCwgMCwgMF0sIFswLCAwLCAwXV1cbiAgdGhpcy5waWNrSWQgPSAwXG4gIHRoaXMubGluZVdpZHRoID0gMVxuICB0aGlzLnRleHR1cmUgPSB0ZXh0dXJlXG4gIHRoaXMuZGFzaFNjYWxlID0gMVxuICB0aGlzLm9wYWNpdHkgPSAxXG4gIHRoaXMuaGFzQWxwaGEgPSBmYWxzZVxuICB0aGlzLmRpcnR5ID0gdHJ1ZVxuICB0aGlzLnBpeGVsUmF0aW8gPSAxXG59XG5cbnZhciBwcm90byA9IExpbmVQbG90LnByb3RvdHlwZVxuXG5wcm90by5pc1RyYW5zcGFyZW50ID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5oYXNBbHBoYVxufVxuXG5wcm90by5pc09wYXF1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuICF0aGlzLmhhc0FscGhhXG59XG5cbnByb3RvLnBpY2tTbG90cyA9IDFcblxucHJvdG8uc2V0UGlja0Jhc2UgPSBmdW5jdGlvbiAoaWQpIHtcbiAgdGhpcy5waWNrSWQgPSBpZFxufVxuXG5wcm90by5kcmF3VHJhbnNwYXJlbnQgPSBwcm90by5kcmF3ID0gZnVuY3Rpb24gKGNhbWVyYSkge1xuICBpZiAoIXRoaXMudmVydGV4Q291bnQpIHJldHVyblxuICB2YXIgZ2wgPSB0aGlzLmdsXG4gIHZhciBzaGFkZXIgPSB0aGlzLnNoYWRlclxuICB2YXIgdmFvID0gdGhpcy52YW9cbiAgc2hhZGVyLmJpbmQoKVxuICBzaGFkZXIudW5pZm9ybXMgPSB7XG4gICAgbW9kZWw6IGNhbWVyYS5tb2RlbCB8fCBpZGVudGl0eSxcbiAgICB2aWV3OiBjYW1lcmEudmlldyB8fCBpZGVudGl0eSxcbiAgICBwcm9qZWN0aW9uOiBjYW1lcmEucHJvamVjdGlvbiB8fCBpZGVudGl0eSxcbiAgICBjbGlwQm91bmRzOiBmaWx0ZXJDbGlwQm91bmRzKHRoaXMuY2xpcEJvdW5kcyksXG4gICAgZGFzaFRleHR1cmU6IHRoaXMudGV4dHVyZS5iaW5kKCksXG4gICAgZGFzaFNjYWxlOiB0aGlzLmRhc2hTY2FsZSAvIHRoaXMuYXJjTGVuZ3RoW3RoaXMuYXJjTGVuZ3RoLmxlbmd0aCAtIDFdLFxuICAgIG9wYWNpdHk6IHRoaXMub3BhY2l0eSxcbiAgICBzY3JlZW5TaGFwZTogW2dsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF0sXG4gICAgcGl4ZWxSYXRpbzogdGhpcy5waXhlbFJhdGlvXG4gIH1cbiAgdmFvLmJpbmQoKVxuICB2YW8uZHJhdyhnbC5UUklBTkdMRV9TVFJJUCwgdGhpcy52ZXJ0ZXhDb3VudClcbiAgdmFvLnVuYmluZCgpXG59XG5cbnByb3RvLmRyYXdQaWNrID0gZnVuY3Rpb24gKGNhbWVyYSkge1xuICBpZiAoIXRoaXMudmVydGV4Q291bnQpIHJldHVyblxuICB2YXIgZ2wgPSB0aGlzLmdsXG4gIHZhciBzaGFkZXIgPSB0aGlzLnBpY2tTaGFkZXJcbiAgdmFyIHZhbyA9IHRoaXMudmFvXG4gIHNoYWRlci5iaW5kKClcbiAgc2hhZGVyLnVuaWZvcm1zID0ge1xuICAgIG1vZGVsOiBjYW1lcmEubW9kZWwgfHwgaWRlbnRpdHksXG4gICAgdmlldzogY2FtZXJhLnZpZXcgfHwgaWRlbnRpdHksXG4gICAgcHJvamVjdGlvbjogY2FtZXJhLnByb2plY3Rpb24gfHwgaWRlbnRpdHksXG4gICAgcGlja0lkOiB0aGlzLnBpY2tJZCxcbiAgICBjbGlwQm91bmRzOiBmaWx0ZXJDbGlwQm91bmRzKHRoaXMuY2xpcEJvdW5kcyksXG4gICAgc2NyZWVuU2hhcGU6IFtnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRdLFxuICAgIHBpeGVsUmF0aW86IHRoaXMucGl4ZWxSYXRpb1xuICB9XG4gIHZhby5iaW5kKClcbiAgdmFvLmRyYXcoZ2wuVFJJQU5HTEVfU1RSSVAsIHRoaXMudmVydGV4Q291bnQpXG4gIHZhby51bmJpbmQoKVxufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICB2YXIgaSwgalxuXG4gIHRoaXMuZGlydHkgPSB0cnVlXG5cbiAgdmFyIGNvbm5lY3RHYXBzID0gISFvcHRpb25zLmNvbm5lY3RHYXBzXG5cbiAgaWYgKCdkYXNoU2NhbGUnIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLmRhc2hTY2FsZSA9IG9wdGlvbnMuZGFzaFNjYWxlXG4gIH1cblxuICB0aGlzLmhhc0FscGhhID0gZmFsc2UgLy8gZGVmYXVsdCB0byBubyB0cmFuc3BhcmVudCBkcmF3XG4gIGlmICgnb3BhY2l0eScgaW4gb3B0aW9ucykge1xuICAgIHRoaXMub3BhY2l0eSA9ICtvcHRpb25zLm9wYWNpdHlcbiAgICBpZih0aGlzLm9wYWNpdHkgPCAxKSB7XG4gICAgICB0aGlzLmhhc0FscGhhID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICAvLyBSZWNhbGN1bGF0ZSBidWZmZXIgZGF0YVxuICB2YXIgYnVmZmVyID0gW11cbiAgdmFyIGFyY0xlbmd0aEFycmF5ID0gW11cbiAgdmFyIHBvaW50QXJyYXkgPSBbXVxuICB2YXIgYXJjTGVuZ3RoID0gMC4wXG4gIHZhciB2ZXJ0ZXhDb3VudCA9IDBcbiAgdmFyIGJvdW5kcyA9IFtcbiAgICBbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHkgXSxcbiAgICBbIC1JbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHkgXV1cblxuICB2YXIgcG9zaXRpb25zID0gb3B0aW9ucy5wb3NpdGlvbiB8fCBvcHRpb25zLnBvc2l0aW9uc1xuICBpZiAocG9zaXRpb25zKSB7XG5cbiAgICAvLyBEZWZhdWx0IGNvbG9yXG4gICAgdmFyIGNvbG9ycyA9IG9wdGlvbnMuY29sb3IgfHwgb3B0aW9ucy5jb2xvcnMgfHwgWzAsIDAsIDAsIDFdXG5cbiAgICB2YXIgbGluZVdpZHRoID0gb3B0aW9ucy5saW5lV2lkdGggfHwgMVxuXG4gICAgdmFyIGhhZEdhcCA9IGZhbHNlXG5cbiAgICBmaWxsX2xvb3A6XG4gICAgZm9yIChpID0gMTsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGEgPSBwb3NpdGlvbnNbaSAtIDFdXG4gICAgICB2YXIgYiA9IHBvc2l0aW9uc1tpXVxuXG4gICAgICBhcmNMZW5ndGhBcnJheS5wdXNoKGFyY0xlbmd0aClcbiAgICAgIHBvaW50QXJyYXkucHVzaChhLnNsaWNlKCkpXG5cbiAgICAgIGZvciAoaiA9IDA7IGogPCAzOyArK2opIHtcbiAgICAgICAgaWYgKGlzTmFOKGFbal0pIHx8IGlzTmFOKGJbal0pIHx8XG4gICAgICAgICAgIWlzRmluaXRlKGFbal0pIHx8ICFpc0Zpbml0ZShiW2pdKSkge1xuXG4gICAgICAgICAgaWYgKCFjb25uZWN0R2FwcyAmJiBidWZmZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCAyNDsgKytrKSB7XG4gICAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGJ1ZmZlcltidWZmZXIubGVuZ3RoIC0gMTJdKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmVydGV4Q291bnQgKz0gMlxuICAgICAgICAgICAgaGFkR2FwID0gdHJ1ZVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnRpbnVlIGZpbGxfbG9vcFxuICAgICAgICB9XG4gICAgICAgIGJvdW5kc1swXVtqXSA9IE1hdGgubWluKGJvdW5kc1swXVtqXSwgYVtqXSwgYltqXSlcbiAgICAgICAgYm91bmRzWzFdW2pdID0gTWF0aC5tYXgoYm91bmRzWzFdW2pdLCBhW2pdLCBiW2pdKVxuICAgICAgfVxuXG4gICAgICB2YXIgYWNvbG9yLCBiY29sb3JcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbG9yc1swXSkpIHtcbiAgICAgICAgYWNvbG9yID0gKGNvbG9ycy5sZW5ndGggPiBpIC0gMSkgPyBjb2xvcnNbaSAtIDFdIDogICAgICAgICAgICAgLy8gdXNpbmcgaW5kZXggdmFsdWVcbiAgICAgICAgICAgICAgICAgKGNvbG9ycy5sZW5ndGggPiAwKSAgICAgPyBjb2xvcnNbY29sb3JzLmxlbmd0aCAtIDFdIDogLy8gdXNpbmcgbGFzdCBpdGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsIDAsIDAsIDFdOyAgICAgICAgICAgICAgIC8vIHVzaW5nIGJsYWNrXG5cbiAgICAgICAgYmNvbG9yID0gKGNvbG9ycy5sZW5ndGggPiBpKSA/IGNvbG9yc1tpXSA6ICAgICAgICAgICAgICAgICAvLyB1c2luZyBpbmRleCB2YWx1ZVxuICAgICAgICAgICAgICAgICAoY29sb3JzLmxlbmd0aCA+IDApID8gY29sb3JzW2NvbG9ycy5sZW5ndGggLSAxXSA6IC8vIHVzaW5nIGxhc3QgaXRlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsIDAsIDAsIDFdOyAgICAgICAgICAgICAgIC8vIHVzaW5nIGJsYWNrXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhY29sb3IgPSBiY29sb3IgPSBjb2xvcnNcbiAgICAgIH1cblxuICAgICAgaWYgKGFjb2xvci5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgYWNvbG9yID0gW2Fjb2xvclswXSwgYWNvbG9yWzFdLCBhY29sb3JbMl0sIDFdXG4gICAgICB9XG4gICAgICBpZiAoYmNvbG9yLmxlbmd0aCA9PT0gMykge1xuICAgICAgICBiY29sb3IgPSBbYmNvbG9yWzBdLCBiY29sb3JbMV0sIGJjb2xvclsyXSwgMV1cbiAgICAgIH1cblxuICAgICAgaWYoIXRoaXMuaGFzQWxwaGEgJiYgYWNvbG9yWzNdIDwgMSkgdGhpcy5oYXNBbHBoYSA9IHRydWVcblxuICAgICAgdmFyIHcwXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShsaW5lV2lkdGgpKSB7XG4gICAgICAgIHcwID0gKGxpbmVXaWR0aC5sZW5ndGggPiBpIC0gMSkgPyBsaW5lV2lkdGhbaSAtIDFdIDogICAgICAgICAgICAgICAgLy8gdXNpbmcgaW5kZXggdmFsdWVcbiAgICAgICAgICAgICAobGluZVdpZHRoLmxlbmd0aCA+IDApICAgICA/IGxpbmVXaWR0aFtsaW5lV2lkdGgubGVuZ3RoIC0gMV0gOiAvLyB1c2luZyBsYXN0IGl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLCAwLCAwLCAxXTsgICAgICAgICAgICAgICAgICAgICAvLyB1c2luZyBibGFja1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdzAgPSBsaW5lV2lkdGhcbiAgICAgIH1cblxuICAgICAgdmFyIHQwID0gYXJjTGVuZ3RoXG4gICAgICBhcmNMZW5ndGggKz0gZGlzdGFuY2UoYSwgYilcblxuICAgICAgaWYgKGhhZEdhcCkge1xuICAgICAgICBmb3IgKGogPSAwOyBqIDwgMjsgKytqKSB7XG4gICAgICAgICAgYnVmZmVyLnB1c2goXG4gICAgICAgICAgICBhWzBdLCBhWzFdLCBhWzJdLCBiWzBdLCBiWzFdLCBiWzJdLCB0MCwgdzAsIGFjb2xvclswXSwgYWNvbG9yWzFdLCBhY29sb3JbMl0sIGFjb2xvclszXSlcbiAgICAgICAgfVxuICAgICAgICB2ZXJ0ZXhDb3VudCArPSAyXG4gICAgICAgIGhhZEdhcCA9IGZhbHNlXG4gICAgICB9XG5cbiAgICAgIGJ1ZmZlci5wdXNoKFxuICAgICAgICBhWzBdLCBhWzFdLCBhWzJdLCBiWzBdLCBiWzFdLCBiWzJdLCB0MCwgdzAsIGFjb2xvclswXSwgYWNvbG9yWzFdLCBhY29sb3JbMl0sIGFjb2xvclszXSxcbiAgICAgICAgYVswXSwgYVsxXSwgYVsyXSwgYlswXSwgYlsxXSwgYlsyXSwgdDAsIC13MCwgYWNvbG9yWzBdLCBhY29sb3JbMV0sIGFjb2xvclsyXSwgYWNvbG9yWzNdLFxuICAgICAgICBiWzBdLCBiWzFdLCBiWzJdLCBhWzBdLCBhWzFdLCBhWzJdLCBhcmNMZW5ndGgsIC13MCwgYmNvbG9yWzBdLCBiY29sb3JbMV0sIGJjb2xvclsyXSwgYmNvbG9yWzNdLFxuICAgICAgICBiWzBdLCBiWzFdLCBiWzJdLCBhWzBdLCBhWzFdLCBhWzJdLCBhcmNMZW5ndGgsIHcwLCBiY29sb3JbMF0sIGJjb2xvclsxXSwgYmNvbG9yWzJdLCBiY29sb3JbM10pXG5cbiAgICAgIHZlcnRleENvdW50ICs9IDRcbiAgICB9XG4gIH1cbiAgdGhpcy5idWZmZXIudXBkYXRlKGJ1ZmZlcilcblxuICBhcmNMZW5ndGhBcnJheS5wdXNoKGFyY0xlbmd0aClcbiAgcG9pbnRBcnJheS5wdXNoKHBvc2l0aW9uc1twb3NpdGlvbnMubGVuZ3RoIC0gMV0uc2xpY2UoKSlcblxuICB0aGlzLmJvdW5kcyA9IGJvdW5kc1xuXG4gIHRoaXMudmVydGV4Q291bnQgPSB2ZXJ0ZXhDb3VudFxuXG4gIHRoaXMucG9pbnRzID0gcG9pbnRBcnJheVxuICB0aGlzLmFyY0xlbmd0aCA9IGFyY0xlbmd0aEFycmF5XG5cbiAgaWYgKCdkYXNoZXMnIGluIG9wdGlvbnMpIHtcbiAgICB2YXIgZGFzaEFycmF5ID0gb3B0aW9ucy5kYXNoZXNcblxuICAgIC8vIENhbGN1bGF0ZSBwcmVmaXggc3VtXG4gICAgdmFyIHByZWZpeFN1bSA9IGRhc2hBcnJheS5zbGljZSgpXG4gICAgcHJlZml4U3VtLnVuc2hpZnQoMClcbiAgICBmb3IgKGkgPSAxOyBpIDwgcHJlZml4U3VtLmxlbmd0aDsgKytpKSB7XG4gICAgICBwcmVmaXhTdW1baV0gPSBwcmVmaXhTdW1baSAtIDFdICsgcHJlZml4U3VtW2ldXG4gICAgfVxuXG4gICAgdmFyIGRhc2hUZXh0dXJlID0gbmRhcnJheShuZXcgQXJyYXkoMjU2ICogNCksIFsyNTYsIDEsIDRdKVxuICAgIGZvciAoaSA9IDA7IGkgPCAyNTY7ICsraSkge1xuICAgICAgZm9yIChqID0gMDsgaiA8IDQ7ICsraikge1xuICAgICAgICBkYXNoVGV4dHVyZS5zZXQoaSwgMCwgaiwgMClcbiAgICAgIH1cbiAgICAgIGlmIChic2VhcmNoLmxlKHByZWZpeFN1bSwgcHJlZml4U3VtW3ByZWZpeFN1bS5sZW5ndGggLSAxXSAqIGkgLyAyNTUuMCkgJiAxKSB7XG4gICAgICAgIGRhc2hUZXh0dXJlLnNldChpLCAwLCAwLCAwKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGFzaFRleHR1cmUuc2V0KGksIDAsIDAsIDI1NSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnRleHR1cmUuc2V0UGl4ZWxzKGRhc2hUZXh0dXJlKVxuICB9XG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiAoKSB7XG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxuICB0aGlzLnZhby5kaXNwb3NlKClcbiAgdGhpcy5idWZmZXIuZGlzcG9zZSgpXG59XG5cbnByb3RvLnBpY2sgPSBmdW5jdGlvbiAoc2VsZWN0aW9uKSB7XG4gIGlmICghc2VsZWN0aW9uKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICBpZiAoc2VsZWN0aW9uLmlkICE9PSB0aGlzLnBpY2tJZCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgdmFyIHRhdSA9IHVucGFja0Zsb2F0KFxuICAgIHNlbGVjdGlvbi52YWx1ZVswXSxcbiAgICBzZWxlY3Rpb24udmFsdWVbMV0sXG4gICAgc2VsZWN0aW9uLnZhbHVlWzJdLFxuICAgIDApXG4gIHZhciBpbmRleCA9IGJzZWFyY2gubGUodGhpcy5hcmNMZW5ndGgsIHRhdSlcbiAgaWYgKGluZGV4IDwgMCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgaWYgKGluZGV4ID09PSB0aGlzLmFyY0xlbmd0aC5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG5ldyBQaWNrUmVzdWx0KFxuICAgICAgdGhpcy5hcmNMZW5ndGhbdGhpcy5hcmNMZW5ndGgubGVuZ3RoIC0gMV0sXG4gICAgICB0aGlzLnBvaW50c1t0aGlzLnBvaW50cy5sZW5ndGggLSAxXS5zbGljZSgpLFxuICAgICAgaW5kZXgpXG4gIH1cbiAgdmFyIGEgPSB0aGlzLnBvaW50c1tpbmRleF1cbiAgdmFyIGIgPSB0aGlzLnBvaW50c1tNYXRoLm1pbihpbmRleCArIDEsIHRoaXMucG9pbnRzLmxlbmd0aCAtIDEpXVxuICB2YXIgdCA9ICh0YXUgLSB0aGlzLmFyY0xlbmd0aFtpbmRleF0pIC8gKHRoaXMuYXJjTGVuZ3RoW2luZGV4ICsgMV0gLSB0aGlzLmFyY0xlbmd0aFtpbmRleF0pXG4gIHZhciB0aSA9IDEuMCAtIHRcbiAgdmFyIHggPSBbMCwgMCwgMF1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICB4W2ldID0gdGkgKiBhW2ldICsgdCAqIGJbaV1cbiAgfVxuICB2YXIgZGF0YUluZGV4ID0gTWF0aC5taW4oKHQgPCAwLjUpID8gaW5kZXggOiAoaW5kZXggKyAxKSwgdGhpcy5wb2ludHMubGVuZ3RoIC0gMSlcbiAgcmV0dXJuIG5ldyBQaWNrUmVzdWx0KFxuICAgIHRhdSxcbiAgICB4LFxuICAgIGRhdGFJbmRleCxcbiAgICB0aGlzLnBvaW50c1tkYXRhSW5kZXhdKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVMaW5lUGxvdCAob3B0aW9ucykge1xuICB2YXIgZ2wgPSBvcHRpb25zLmdsIHx8IChvcHRpb25zLnNjZW5lICYmIG9wdGlvbnMuc2NlbmUuZ2wpXG5cbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbClcbiAgc2hhZGVyLmF0dHJpYnV0ZXMucG9zaXRpb24ubG9jYXRpb24gPSAwXG4gIHNoYWRlci5hdHRyaWJ1dGVzLm5leHRQb3NpdGlvbi5sb2NhdGlvbiA9IDFcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuYXJjTGVuZ3RoLmxvY2F0aW9uID0gMlxuICBzaGFkZXIuYXR0cmlidXRlcy5saW5lV2lkdGgubG9jYXRpb24gPSAzXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmNvbG9yLmxvY2F0aW9uID0gNFxuXG4gIHZhciBwaWNrU2hhZGVyID0gY3JlYXRlUGlja1NoYWRlcihnbClcbiAgcGlja1NoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICBwaWNrU2hhZGVyLmF0dHJpYnV0ZXMubmV4dFBvc2l0aW9uLmxvY2F0aW9uID0gMVxuICBwaWNrU2hhZGVyLmF0dHJpYnV0ZXMuYXJjTGVuZ3RoLmxvY2F0aW9uID0gMlxuICBwaWNrU2hhZGVyLmF0dHJpYnV0ZXMubGluZVdpZHRoLmxvY2F0aW9uID0gM1xuICBwaWNrU2hhZGVyLmF0dHJpYnV0ZXMuY29sb3IubG9jYXRpb24gPSA0XG5cbiAgdmFyIGJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHZhbyA9IGNyZWF0ZVZBTyhnbCwgW1xuICAgIHtcbiAgICAgICdidWZmZXInOiBidWZmZXIsXG4gICAgICAnc2l6ZSc6IDMsXG4gICAgICAnb2Zmc2V0JzogMCxcbiAgICAgICdzdHJpZGUnOiA0OFxuICAgIH0sXG4gICAge1xuICAgICAgJ2J1ZmZlcic6IGJ1ZmZlcixcbiAgICAgICdzaXplJzogMyxcbiAgICAgICdvZmZzZXQnOiAxMixcbiAgICAgICdzdHJpZGUnOiA0OFxuICAgIH0sXG4gICAge1xuICAgICAgJ2J1ZmZlcic6IGJ1ZmZlcixcbiAgICAgICdzaXplJzogMSxcbiAgICAgICdvZmZzZXQnOiAyNCxcbiAgICAgICdzdHJpZGUnOiA0OFxuICAgIH0sXG4gICAge1xuICAgICAgJ2J1ZmZlcic6IGJ1ZmZlcixcbiAgICAgICdzaXplJzogMSxcbiAgICAgICdvZmZzZXQnOiAyOCxcbiAgICAgICdzdHJpZGUnOiA0OFxuICAgIH0sXG4gICAge1xuICAgICAgJ2J1ZmZlcic6IGJ1ZmZlcixcbiAgICAgICdzaXplJzogNCxcbiAgICAgICdvZmZzZXQnOiAzMixcbiAgICAgICdzdHJpZGUnOiA0OFxuICAgIH1cbiAgXSlcblxuICAvLyBDcmVhdGUgdGV4dHVyZSBmb3IgZGFzaCBwYXR0ZXJuXG4gIHZhciBkZWZhdWx0VGV4dHVyZSA9IG5kYXJyYXkobmV3IEFycmF5KDI1NiAqIDQpLCBbMjU2LCAxLCA0XSlcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAyNTYgKiA0OyArK2kpIHtcbiAgICBkZWZhdWx0VGV4dHVyZS5kYXRhW2ldID0gMjU1XG4gIH1cbiAgdmFyIHRleHR1cmUgPSBjcmVhdGVUZXh0dXJlKGdsLCBkZWZhdWx0VGV4dHVyZSlcbiAgdGV4dHVyZS53cmFwID0gZ2wuUkVQRUFUXG5cbiAgdmFyIGxpbmVQbG90ID0gbmV3IExpbmVQbG90KGdsLCBzaGFkZXIsIHBpY2tTaGFkZXIsIGJ1ZmZlciwgdmFvLCB0ZXh0dXJlKVxuICBsaW5lUGxvdC51cGRhdGUob3B0aW9ucylcbiAgcmV0dXJuIGxpbmVQbG90XG59XG5cbn0se1wiLi9saWIvc2hhZGVyc1wiOjI1NCxcImJpbmFyeS1zZWFyY2gtYm91bmRzXCI6MjU2LFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtdGV4dHVyZTJkXCI6MzIyLFwiZ2wtdmFvXCI6MzI3LFwiZ2xzbC1yZWFkLWZsb2F0XCI6NDAwLFwibmRhcnJheVwiOjQ1MH1dLDI1NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5hcmd1bWVudHNbNF1bMTExXVswXS5hcHBseShleHBvcnRzLGFyZ3VtZW50cylcbn0se1wiZHVwXCI6MTExfV0sMjU3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gaW52ZXJ0XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDJcbiAqXG4gKiBAYWxpYXMgbWF0Mi5pbnZlcnRcbiAqIEBwYXJhbSB7bWF0Mn0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDJ9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQyfSBvdXRcbiAqL1xuZnVuY3Rpb24gaW52ZXJ0KG91dCwgYSkge1xuICB2YXIgYTAgPSBhWzBdXG4gIHZhciBhMSA9IGFbMV1cbiAgdmFyIGEyID0gYVsyXVxuICB2YXIgYTMgPSBhWzNdXG4gIHZhciBkZXQgPSBhMCAqIGEzIC0gYTIgKiBhMVxuXG4gIGlmICghZGV0KSByZXR1cm4gbnVsbFxuICBkZXQgPSAxLjAgLyBkZXRcblxuICBvdXRbMF0gPSAgYTMgKiBkZXRcbiAgb3V0WzFdID0gLWExICogZGV0XG4gIG91dFsyXSA9IC1hMiAqIGRldFxuICBvdXRbM10gPSAgYTAgKiBkZXRcblxuICByZXR1cm4gb3V0XG59XG5cbn0se31dLDI1ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGludmVydFxuXG4vKipcbiAqIEludmVydHMgYSBtYXQzXG4gKlxuICogQGFsaWFzIG1hdDMuaW52ZXJ0XG4gKiBAcGFyYW0ge21hdDN9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQzfSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0M30gb3V0XG4gKi9cbmZ1bmN0aW9uIGludmVydChvdXQsIGEpIHtcbiAgdmFyIGEwMCA9IGFbMF0sIGEwMSA9IGFbMV0sIGEwMiA9IGFbMl1cbiAgdmFyIGExMCA9IGFbM10sIGExMSA9IGFbNF0sIGExMiA9IGFbNV1cbiAgdmFyIGEyMCA9IGFbNl0sIGEyMSA9IGFbN10sIGEyMiA9IGFbOF1cblxuICB2YXIgYjAxID0gYTIyICogYTExIC0gYTEyICogYTIxXG4gIHZhciBiMTEgPSAtYTIyICogYTEwICsgYTEyICogYTIwXG4gIHZhciBiMjEgPSBhMjEgKiBhMTAgLSBhMTEgKiBhMjBcblxuICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gIHZhciBkZXQgPSBhMDAgKiBiMDEgKyBhMDEgKiBiMTEgKyBhMDIgKiBiMjFcblxuICBpZiAoIWRldCkgcmV0dXJuIG51bGxcbiAgZGV0ID0gMS4wIC8gZGV0XG5cbiAgb3V0WzBdID0gYjAxICogZGV0XG4gIG91dFsxXSA9ICgtYTIyICogYTAxICsgYTAyICogYTIxKSAqIGRldFxuICBvdXRbMl0gPSAoYTEyICogYTAxIC0gYTAyICogYTExKSAqIGRldFxuICBvdXRbM10gPSBiMTEgKiBkZXRcbiAgb3V0WzRdID0gKGEyMiAqIGEwMCAtIGEwMiAqIGEyMCkgKiBkZXRcbiAgb3V0WzVdID0gKC1hMTIgKiBhMDAgKyBhMDIgKiBhMTApICogZGV0XG4gIG91dFs2XSA9IGIyMSAqIGRldFxuICBvdXRbN10gPSAoLWEyMSAqIGEwMCArIGEwMSAqIGEyMCkgKiBkZXRcbiAgb3V0WzhdID0gKGExMSAqIGEwMCAtIGEwMSAqIGExMCkgKiBkZXRcblxuICByZXR1cm4gb3V0XG59XG5cbn0se31dLDI1OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGNsb25lO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgbWF0NCBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIG1hdHJpeFxuICpcbiAqIEBwYXJhbSB7bWF0NH0gYSBtYXRyaXggdG8gY2xvbmVcbiAqIEByZXR1cm5zIHttYXQ0fSBhIG5ldyA0eDQgbWF0cml4XG4gKi9cbmZ1bmN0aW9uIGNsb25lKGEpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEZsb2F0MzJBcnJheSgxNik7XG4gICAgb3V0WzBdID0gYVswXTtcbiAgICBvdXRbMV0gPSBhWzFdO1xuICAgIG91dFsyXSA9IGFbMl07XG4gICAgb3V0WzNdID0gYVszXTtcbiAgICBvdXRbNF0gPSBhWzRdO1xuICAgIG91dFs1XSA9IGFbNV07XG4gICAgb3V0WzZdID0gYVs2XTtcbiAgICBvdXRbN10gPSBhWzddO1xuICAgIG91dFs4XSA9IGFbOF07XG4gICAgb3V0WzldID0gYVs5XTtcbiAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgb3V0WzExXSA9IGFbMTFdO1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcbn0se31dLDI2MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGlkZW50aXR5IG1hdDRcbiAqXG4gKiBAcmV0dXJucyB7bWF0NH0gYSBuZXcgNHg0IG1hdHJpeFxuICovXG5mdW5jdGlvbiBjcmVhdGUoKSB7XG4gICAgdmFyIG91dCA9IG5ldyBGbG9hdDMyQXJyYXkoMTYpO1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAxO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IDE7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IDA7XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG59LHt9XSwyNjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBkZXRlcm1pbmFudDtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkZXRlcm1pbmFudCBvZiBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRldGVybWluYW50IG9mIGFcbiAqL1xuZnVuY3Rpb24gZGV0ZXJtaW5hbnQoYSkge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdLFxuXG4gICAgICAgIGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMCxcbiAgICAgICAgYjAxID0gYTAwICogYTEyIC0gYTAyICogYTEwLFxuICAgICAgICBiMDIgPSBhMDAgKiBhMTMgLSBhMDMgKiBhMTAsXG4gICAgICAgIGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMSxcbiAgICAgICAgYjA0ID0gYTAxICogYTEzIC0gYTAzICogYTExLFxuICAgICAgICBiMDUgPSBhMDIgKiBhMTMgLSBhMDMgKiBhMTIsXG4gICAgICAgIGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMCxcbiAgICAgICAgYjA3ID0gYTIwICogYTMyIC0gYTIyICogYTMwLFxuICAgICAgICBiMDggPSBhMjAgKiBhMzMgLSBhMjMgKiBhMzAsXG4gICAgICAgIGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMSxcbiAgICAgICAgYjEwID0gYTIxICogYTMzIC0gYTIzICogYTMxLFxuICAgICAgICBiMTEgPSBhMjIgKiBhMzMgLSBhMjMgKiBhMzI7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50XG4gICAgcmV0dXJuIGIwMCAqIGIxMSAtIGIwMSAqIGIxMCArIGIwMiAqIGIwOSArIGIwMyAqIGIwOCAtIGIwNCAqIGIwNyArIGIwNSAqIGIwNjtcbn07XG59LHt9XSwyNjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBmcm9tUXVhdDtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbWF0cml4IGZyb20gYSBxdWF0ZXJuaW9uIHJvdGF0aW9uLlxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IG1hdDQgcmVjZWl2aW5nIG9wZXJhdGlvbiByZXN1bHRcbiAqIEBwYXJhbSB7cXVhdDR9IHEgUm90YXRpb24gcXVhdGVybmlvblxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5mdW5jdGlvbiBmcm9tUXVhdChvdXQsIHEpIHtcbiAgICB2YXIgeCA9IHFbMF0sIHkgPSBxWzFdLCB6ID0gcVsyXSwgdyA9IHFbM10sXG4gICAgICAgIHgyID0geCArIHgsXG4gICAgICAgIHkyID0geSArIHksXG4gICAgICAgIHoyID0geiArIHosXG5cbiAgICAgICAgeHggPSB4ICogeDIsXG4gICAgICAgIHl4ID0geSAqIHgyLFxuICAgICAgICB5eSA9IHkgKiB5MixcbiAgICAgICAgenggPSB6ICogeDIsXG4gICAgICAgIHp5ID0geiAqIHkyLFxuICAgICAgICB6eiA9IHogKiB6MixcbiAgICAgICAgd3ggPSB3ICogeDIsXG4gICAgICAgIHd5ID0gdyAqIHkyLFxuICAgICAgICB3eiA9IHcgKiB6MjtcblxuICAgIG91dFswXSA9IDEgLSB5eSAtIHp6O1xuICAgIG91dFsxXSA9IHl4ICsgd3o7XG4gICAgb3V0WzJdID0genggLSB3eTtcbiAgICBvdXRbM10gPSAwO1xuXG4gICAgb3V0WzRdID0geXggLSB3ejtcbiAgICBvdXRbNV0gPSAxIC0geHggLSB6ejtcbiAgICBvdXRbNl0gPSB6eSArIHd4O1xuICAgIG91dFs3XSA9IDA7XG5cbiAgICBvdXRbOF0gPSB6eCArIHd5O1xuICAgIG91dFs5XSA9IHp5IC0gd3g7XG4gICAgb3V0WzEwXSA9IDEgLSB4eCAtIHl5O1xuICAgIG91dFsxMV0gPSAwO1xuXG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IDA7XG4gICAgb3V0WzE1XSA9IDE7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcbn0se31dLDI2MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGZyb21Sb3RhdGlvblRyYW5zbGF0aW9uO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBtYXRyaXggZnJvbSBhIHF1YXRlcm5pb24gcm90YXRpb24gYW5kIHZlY3RvciB0cmFuc2xhdGlvblxuICogVGhpcyBpcyBlcXVpdmFsZW50IHRvIChidXQgbXVjaCBmYXN0ZXIgdGhhbik6XG4gKlxuICogICAgIG1hdDQuaWRlbnRpdHkoZGVzdCk7XG4gKiAgICAgbWF0NC50cmFuc2xhdGUoZGVzdCwgdmVjKTtcbiAqICAgICB2YXIgcXVhdE1hdCA9IG1hdDQuY3JlYXRlKCk7XG4gKiAgICAgcXVhdDQudG9NYXQ0KHF1YXQsIHF1YXRNYXQpO1xuICogICAgIG1hdDQubXVsdGlwbHkoZGVzdCwgcXVhdE1hdCk7XG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCByZWNlaXZpbmcgb3BlcmF0aW9uIHJlc3VsdFxuICogQHBhcmFtIHtxdWF0NH0gcSBSb3RhdGlvbiBxdWF0ZXJuaW9uXG4gKiBAcGFyYW0ge3ZlYzN9IHYgVHJhbnNsYXRpb24gdmVjdG9yXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbmZ1bmN0aW9uIGZyb21Sb3RhdGlvblRyYW5zbGF0aW9uKG91dCwgcSwgdikge1xuICAgIC8vIFF1YXRlcm5pb24gbWF0aFxuICAgIHZhciB4ID0gcVswXSwgeSA9IHFbMV0sIHogPSBxWzJdLCB3ID0gcVszXSxcbiAgICAgICAgeDIgPSB4ICsgeCxcbiAgICAgICAgeTIgPSB5ICsgeSxcbiAgICAgICAgejIgPSB6ICsgeixcblxuICAgICAgICB4eCA9IHggKiB4MixcbiAgICAgICAgeHkgPSB4ICogeTIsXG4gICAgICAgIHh6ID0geCAqIHoyLFxuICAgICAgICB5eSA9IHkgKiB5MixcbiAgICAgICAgeXogPSB5ICogejIsXG4gICAgICAgIHp6ID0geiAqIHoyLFxuICAgICAgICB3eCA9IHcgKiB4MixcbiAgICAgICAgd3kgPSB3ICogeTIsXG4gICAgICAgIHd6ID0gdyAqIHoyO1xuXG4gICAgb3V0WzBdID0gMSAtICh5eSArIHp6KTtcbiAgICBvdXRbMV0gPSB4eSArIHd6O1xuICAgIG91dFsyXSA9IHh6IC0gd3k7XG4gICAgb3V0WzNdID0gMDtcbiAgICBvdXRbNF0gPSB4eSAtIHd6O1xuICAgIG91dFs1XSA9IDEgLSAoeHggKyB6eik7XG4gICAgb3V0WzZdID0geXogKyB3eDtcbiAgICBvdXRbN10gPSAwO1xuICAgIG91dFs4XSA9IHh6ICsgd3k7XG4gICAgb3V0WzldID0geXogLSB3eDtcbiAgICBvdXRbMTBdID0gMSAtICh4eCArIHl5KTtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gdlswXTtcbiAgICBvdXRbMTNdID0gdlsxXTtcbiAgICBvdXRbMTRdID0gdlsyXTtcbiAgICBvdXRbMTVdID0gMTtcbiAgICBcbiAgICByZXR1cm4gb3V0O1xufTtcbn0se31dLDI2NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGlkZW50aXR5O1xuXG4vKipcbiAqIFNldCBhIG1hdDQgdG8gdGhlIGlkZW50aXR5IG1hdHJpeFxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbmZ1bmN0aW9uIGlkZW50aXR5KG91dCkge1xuICAgIG91dFswXSA9IDE7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAxO1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IDE7XG4gICAgb3V0WzExXSA9IDA7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9IDA7XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG59LHt9XSwyNjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBpbnZlcnQ7XG5cbi8qKlxuICogSW52ZXJ0cyBhIG1hdDRcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBzb3VyY2UgbWF0cml4XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbmZ1bmN0aW9uIGludmVydChvdXQsIGEpIHtcbiAgICB2YXIgYTAwID0gYVswXSwgYTAxID0gYVsxXSwgYTAyID0gYVsyXSwgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSwgYTExID0gYVs1XSwgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgYTIwID0gYVs4XSwgYTIxID0gYVs5XSwgYTIyID0gYVsxMF0sIGEyMyA9IGFbMTFdLFxuICAgICAgICBhMzAgPSBhWzEyXSwgYTMxID0gYVsxM10sIGEzMiA9IGFbMTRdLCBhMzMgPSBhWzE1XSxcblxuICAgICAgICBiMDAgPSBhMDAgKiBhMTEgLSBhMDEgKiBhMTAsXG4gICAgICAgIGIwMSA9IGEwMCAqIGExMiAtIGEwMiAqIGExMCxcbiAgICAgICAgYjAyID0gYTAwICogYTEzIC0gYTAzICogYTEwLFxuICAgICAgICBiMDMgPSBhMDEgKiBhMTIgLSBhMDIgKiBhMTEsXG4gICAgICAgIGIwNCA9IGEwMSAqIGExMyAtIGEwMyAqIGExMSxcbiAgICAgICAgYjA1ID0gYTAyICogYTEzIC0gYTAzICogYTEyLFxuICAgICAgICBiMDYgPSBhMjAgKiBhMzEgLSBhMjEgKiBhMzAsXG4gICAgICAgIGIwNyA9IGEyMCAqIGEzMiAtIGEyMiAqIGEzMCxcbiAgICAgICAgYjA4ID0gYTIwICogYTMzIC0gYTIzICogYTMwLFxuICAgICAgICBiMDkgPSBhMjEgKiBhMzIgLSBhMjIgKiBhMzEsXG4gICAgICAgIGIxMCA9IGEyMSAqIGEzMyAtIGEyMyAqIGEzMSxcbiAgICAgICAgYjExID0gYTIyICogYTMzIC0gYTIzICogYTMyLFxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgZGV0ZXJtaW5hbnRcbiAgICAgICAgZGV0ID0gYjAwICogYjExIC0gYjAxICogYjEwICsgYjAyICogYjA5ICsgYjAzICogYjA4IC0gYjA0ICogYjA3ICsgYjA1ICogYjA2O1xuXG4gICAgaWYgKCFkZXQpIHsgXG4gICAgICAgIHJldHVybiBudWxsOyBcbiAgICB9XG4gICAgZGV0ID0gMS4wIC8gZGV0O1xuXG4gICAgb3V0WzBdID0gKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQ7XG4gICAgb3V0WzFdID0gKGEwMiAqIGIxMCAtIGEwMSAqIGIxMSAtIGEwMyAqIGIwOSkgKiBkZXQ7XG4gICAgb3V0WzJdID0gKGEzMSAqIGIwNSAtIGEzMiAqIGIwNCArIGEzMyAqIGIwMykgKiBkZXQ7XG4gICAgb3V0WzNdID0gKGEyMiAqIGIwNCAtIGEyMSAqIGIwNSAtIGEyMyAqIGIwMykgKiBkZXQ7XG4gICAgb3V0WzRdID0gKGExMiAqIGIwOCAtIGExMCAqIGIxMSAtIGExMyAqIGIwNykgKiBkZXQ7XG4gICAgb3V0WzVdID0gKGEwMCAqIGIxMSAtIGEwMiAqIGIwOCArIGEwMyAqIGIwNykgKiBkZXQ7XG4gICAgb3V0WzZdID0gKGEzMiAqIGIwMiAtIGEzMCAqIGIwNSAtIGEzMyAqIGIwMSkgKiBkZXQ7XG4gICAgb3V0WzddID0gKGEyMCAqIGIwNSAtIGEyMiAqIGIwMiArIGEyMyAqIGIwMSkgKiBkZXQ7XG4gICAgb3V0WzhdID0gKGExMCAqIGIxMCAtIGExMSAqIGIwOCArIGExMyAqIGIwNikgKiBkZXQ7XG4gICAgb3V0WzldID0gKGEwMSAqIGIwOCAtIGEwMCAqIGIxMCAtIGEwMyAqIGIwNikgKiBkZXQ7XG4gICAgb3V0WzEwXSA9IChhMzAgKiBiMDQgLSBhMzEgKiBiMDIgKyBhMzMgKiBiMDApICogZGV0O1xuICAgIG91dFsxMV0gPSAoYTIxICogYjAyIC0gYTIwICogYjA0IC0gYTIzICogYjAwKSAqIGRldDtcbiAgICBvdXRbMTJdID0gKGExMSAqIGIwNyAtIGExMCAqIGIwOSAtIGExMiAqIGIwNikgKiBkZXQ7XG4gICAgb3V0WzEzXSA9IChhMDAgKiBiMDkgLSBhMDEgKiBiMDcgKyBhMDIgKiBiMDYpICogZGV0O1xuICAgIG91dFsxNF0gPSAoYTMxICogYjAxIC0gYTMwICogYjAzIC0gYTMyICogYjAwKSAqIGRldDtcbiAgICBvdXRbMTVdID0gKGEyMCAqIGIwMyAtIGEyMSAqIGIwMSArIGEyMiAqIGIwMCkgKiBkZXQ7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcbn0se31dLDI2NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG52YXIgaWRlbnRpdHkgPSBfZGVyZXFfKCcuL2lkZW50aXR5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gbG9va0F0O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIGxvb2stYXQgbWF0cml4IHdpdGggdGhlIGdpdmVuIGV5ZSBwb3NpdGlvbiwgZm9jYWwgcG9pbnQsIGFuZCB1cCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgbWF0NCBmcnVzdHVtIG1hdHJpeCB3aWxsIGJlIHdyaXR0ZW4gaW50b1xuICogQHBhcmFtIHt2ZWMzfSBleWUgUG9zaXRpb24gb2YgdGhlIHZpZXdlclxuICogQHBhcmFtIHt2ZWMzfSBjZW50ZXIgUG9pbnQgdGhlIHZpZXdlciBpcyBsb29raW5nIGF0XG4gKiBAcGFyYW0ge3ZlYzN9IHVwIHZlYzMgcG9pbnRpbmcgdXBcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuZnVuY3Rpb24gbG9va0F0KG91dCwgZXllLCBjZW50ZXIsIHVwKSB7XG4gICAgdmFyIHgwLCB4MSwgeDIsIHkwLCB5MSwgeTIsIHowLCB6MSwgejIsIGxlbixcbiAgICAgICAgZXlleCA9IGV5ZVswXSxcbiAgICAgICAgZXlleSA9IGV5ZVsxXSxcbiAgICAgICAgZXlleiA9IGV5ZVsyXSxcbiAgICAgICAgdXB4ID0gdXBbMF0sXG4gICAgICAgIHVweSA9IHVwWzFdLFxuICAgICAgICB1cHogPSB1cFsyXSxcbiAgICAgICAgY2VudGVyeCA9IGNlbnRlclswXSxcbiAgICAgICAgY2VudGVyeSA9IGNlbnRlclsxXSxcbiAgICAgICAgY2VudGVyeiA9IGNlbnRlclsyXTtcblxuICAgIGlmIChNYXRoLmFicyhleWV4IC0gY2VudGVyeCkgPCAwLjAwMDAwMSAmJlxuICAgICAgICBNYXRoLmFicyhleWV5IC0gY2VudGVyeSkgPCAwLjAwMDAwMSAmJlxuICAgICAgICBNYXRoLmFicyhleWV6IC0gY2VudGVyeikgPCAwLjAwMDAwMSkge1xuICAgICAgICByZXR1cm4gaWRlbnRpdHkob3V0KTtcbiAgICB9XG5cbiAgICB6MCA9IGV5ZXggLSBjZW50ZXJ4O1xuICAgIHoxID0gZXlleSAtIGNlbnRlcnk7XG4gICAgejIgPSBleWV6IC0gY2VudGVyejtcblxuICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQoejAgKiB6MCArIHoxICogejEgKyB6MiAqIHoyKTtcbiAgICB6MCAqPSBsZW47XG4gICAgejEgKj0gbGVuO1xuICAgIHoyICo9IGxlbjtcblxuICAgIHgwID0gdXB5ICogejIgLSB1cHogKiB6MTtcbiAgICB4MSA9IHVweiAqIHowIC0gdXB4ICogejI7XG4gICAgeDIgPSB1cHggKiB6MSAtIHVweSAqIHowO1xuICAgIGxlbiA9IE1hdGguc3FydCh4MCAqIHgwICsgeDEgKiB4MSArIHgyICogeDIpO1xuICAgIGlmICghbGVuKSB7XG4gICAgICAgIHgwID0gMDtcbiAgICAgICAgeDEgPSAwO1xuICAgICAgICB4MiA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbGVuID0gMSAvIGxlbjtcbiAgICAgICAgeDAgKj0gbGVuO1xuICAgICAgICB4MSAqPSBsZW47XG4gICAgICAgIHgyICo9IGxlbjtcbiAgICB9XG5cbiAgICB5MCA9IHoxICogeDIgLSB6MiAqIHgxO1xuICAgIHkxID0gejIgKiB4MCAtIHowICogeDI7XG4gICAgeTIgPSB6MCAqIHgxIC0gejEgKiB4MDtcblxuICAgIGxlbiA9IE1hdGguc3FydCh5MCAqIHkwICsgeTEgKiB5MSArIHkyICogeTIpO1xuICAgIGlmICghbGVuKSB7XG4gICAgICAgIHkwID0gMDtcbiAgICAgICAgeTEgPSAwO1xuICAgICAgICB5MiA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbGVuID0gMSAvIGxlbjtcbiAgICAgICAgeTAgKj0gbGVuO1xuICAgICAgICB5MSAqPSBsZW47XG4gICAgICAgIHkyICo9IGxlbjtcbiAgICB9XG5cbiAgICBvdXRbMF0gPSB4MDtcbiAgICBvdXRbMV0gPSB5MDtcbiAgICBvdXRbMl0gPSB6MDtcbiAgICBvdXRbM10gPSAwO1xuICAgIG91dFs0XSA9IHgxO1xuICAgIG91dFs1XSA9IHkxO1xuICAgIG91dFs2XSA9IHoxO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0geDI7XG4gICAgb3V0WzldID0geTI7XG4gICAgb3V0WzEwXSA9IHoyO1xuICAgIG91dFsxMV0gPSAwO1xuICAgIG91dFsxMl0gPSAtKHgwICogZXlleCArIHgxICogZXlleSArIHgyICogZXlleik7XG4gICAgb3V0WzEzXSA9IC0oeTAgKiBleWV4ICsgeTEgKiBleWV5ICsgeTIgKiBleWV6KTtcbiAgICBvdXRbMTRdID0gLSh6MCAqIGV5ZXggKyB6MSAqIGV5ZXkgKyB6MiAqIGV5ZXopO1xuICAgIG91dFsxNV0gPSAxO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG59LHtcIi4vaWRlbnRpdHlcIjoyNjR9XSwyNjc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBtdWx0aXBseTtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byBtYXQ0J3NcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge21hdDR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbmZ1bmN0aW9uIG11bHRpcGx5KG91dCwgYSwgYikge1xuICAgIHZhciBhMDAgPSBhWzBdLCBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICBhMTAgPSBhWzRdLCBhMTEgPSBhWzVdLCBhMTIgPSBhWzZdLCBhMTMgPSBhWzddLFxuICAgICAgICBhMjAgPSBhWzhdLCBhMjEgPSBhWzldLCBhMjIgPSBhWzEwXSwgYTIzID0gYVsxMV0sXG4gICAgICAgIGEzMCA9IGFbMTJdLCBhMzEgPSBhWzEzXSwgYTMyID0gYVsxNF0sIGEzMyA9IGFbMTVdO1xuXG4gICAgLy8gQ2FjaGUgb25seSB0aGUgY3VycmVudCBsaW5lIG9mIHRoZSBzZWNvbmQgbWF0cml4XG4gICAgdmFyIGIwICA9IGJbMF0sIGIxID0gYlsxXSwgYjIgPSBiWzJdLCBiMyA9IGJbM107ICBcbiAgICBvdXRbMF0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzFdID0gYjAqYTAxICsgYjEqYTExICsgYjIqYTIxICsgYjMqYTMxO1xuICAgIG91dFsyXSA9IGIwKmEwMiArIGIxKmExMiArIGIyKmEyMiArIGIzKmEzMjtcbiAgICBvdXRbM10gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbNF07IGIxID0gYls1XTsgYjIgPSBiWzZdOyBiMyA9IGJbN107XG4gICAgb3V0WzRdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs1XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbNl0gPSBiMCphMDIgKyBiMSphMTIgKyBiMiphMjIgKyBiMyphMzI7XG4gICAgb3V0WzddID0gYjAqYTAzICsgYjEqYTEzICsgYjIqYTIzICsgYjMqYTMzO1xuXG4gICAgYjAgPSBiWzhdOyBiMSA9IGJbOV07IGIyID0gYlsxMF07IGIzID0gYlsxMV07XG4gICAgb3V0WzhdID0gYjAqYTAwICsgYjEqYTEwICsgYjIqYTIwICsgYjMqYTMwO1xuICAgIG91dFs5XSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTBdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxMV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG5cbiAgICBiMCA9IGJbMTJdOyBiMSA9IGJbMTNdOyBiMiA9IGJbMTRdOyBiMyA9IGJbMTVdO1xuICAgIG91dFsxMl0gPSBiMCphMDAgKyBiMSphMTAgKyBiMiphMjAgKyBiMyphMzA7XG4gICAgb3V0WzEzXSA9IGIwKmEwMSArIGIxKmExMSArIGIyKmEyMSArIGIzKmEzMTtcbiAgICBvdXRbMTRdID0gYjAqYTAyICsgYjEqYTEyICsgYjIqYTIyICsgYjMqYTMyO1xuICAgIG91dFsxNV0gPSBiMCphMDMgKyBiMSphMTMgKyBiMiphMjMgKyBiMyphMzM7XG4gICAgcmV0dXJuIG91dDtcbn07XG59LHt9XSwyNjg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBvcnRobztcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBvcnRob2dvbmFsIHByb2plY3Rpb24gbWF0cml4IHdpdGggdGhlIGdpdmVuIGJvdW5kc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IG1hdDQgZnJ1c3R1bSBtYXRyaXggd2lsbCBiZSB3cml0dGVuIGludG9cbiAqIEBwYXJhbSB7bnVtYmVyfSBsZWZ0IExlZnQgYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSByaWdodCBSaWdodCBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHBhcmFtIHtudW1iZXJ9IGJvdHRvbSBCb3R0b20gYm91bmQgb2YgdGhlIGZydXN0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSB0b3AgVG9wIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gbmVhciBOZWFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gZmFyIEZhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5mdW5jdGlvbiBvcnRobyhvdXQsIGxlZnQsIHJpZ2h0LCBib3R0b20sIHRvcCwgbmVhciwgZmFyKSB7XG4gICAgdmFyIGxyID0gMSAvIChsZWZ0IC0gcmlnaHQpLFxuICAgICAgICBidCA9IDEgLyAoYm90dG9tIC0gdG9wKSxcbiAgICAgICAgbmYgPSAxIC8gKG5lYXIgLSBmYXIpO1xuICAgIG91dFswXSA9IC0yICogbHI7XG4gICAgb3V0WzFdID0gMDtcbiAgICBvdXRbMl0gPSAwO1xuICAgIG91dFszXSA9IDA7XG4gICAgb3V0WzRdID0gMDtcbiAgICBvdXRbNV0gPSAtMiAqIGJ0O1xuICAgIG91dFs2XSA9IDA7XG4gICAgb3V0WzddID0gMDtcbiAgICBvdXRbOF0gPSAwO1xuICAgIG91dFs5XSA9IDA7XG4gICAgb3V0WzEwXSA9IDIgKiBuZjtcbiAgICBvdXRbMTFdID0gMDtcbiAgICBvdXRbMTJdID0gKGxlZnQgKyByaWdodCkgKiBscjtcbiAgICBvdXRbMTNdID0gKHRvcCArIGJvdHRvbSkgKiBidDtcbiAgICBvdXRbMTRdID0gKGZhciArIG5lYXIpICogbmY7XG4gICAgb3V0WzE1XSA9IDE7XG4gICAgcmV0dXJuIG91dDtcbn07XG59LHt9XSwyNjk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBwZXJzcGVjdGl2ZTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBwZXJzcGVjdGl2ZSBwcm9qZWN0aW9uIG1hdHJpeCB3aXRoIHRoZSBnaXZlbiBib3VuZHNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCBtYXQ0IGZydXN0dW0gbWF0cml4IHdpbGwgYmUgd3JpdHRlbiBpbnRvXG4gKiBAcGFyYW0ge251bWJlcn0gZm92eSBWZXJ0aWNhbCBmaWVsZCBvZiB2aWV3IGluIHJhZGlhbnNcbiAqIEBwYXJhbSB7bnVtYmVyfSBhc3BlY3QgQXNwZWN0IHJhdGlvLiB0eXBpY2FsbHkgdmlld3BvcnQgd2lkdGgvaGVpZ2h0XG4gKiBAcGFyYW0ge251bWJlcn0gbmVhciBOZWFyIGJvdW5kIG9mIHRoZSBmcnVzdHVtXG4gKiBAcGFyYW0ge251bWJlcn0gZmFyIEZhciBib3VuZCBvZiB0aGUgZnJ1c3R1bVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5mdW5jdGlvbiBwZXJzcGVjdGl2ZShvdXQsIGZvdnksIGFzcGVjdCwgbmVhciwgZmFyKSB7XG4gICAgdmFyIGYgPSAxLjAgLyBNYXRoLnRhbihmb3Z5IC8gMiksXG4gICAgICAgIG5mID0gMSAvIChuZWFyIC0gZmFyKTtcbiAgICBvdXRbMF0gPSBmIC8gYXNwZWN0O1xuICAgIG91dFsxXSA9IDA7XG4gICAgb3V0WzJdID0gMDtcbiAgICBvdXRbM10gPSAwO1xuICAgIG91dFs0XSA9IDA7XG4gICAgb3V0WzVdID0gZjtcbiAgICBvdXRbNl0gPSAwO1xuICAgIG91dFs3XSA9IDA7XG4gICAgb3V0WzhdID0gMDtcbiAgICBvdXRbOV0gPSAwO1xuICAgIG91dFsxMF0gPSAoZmFyICsgbmVhcikgKiBuZjtcbiAgICBvdXRbMTFdID0gLTE7XG4gICAgb3V0WzEyXSA9IDA7XG4gICAgb3V0WzEzXSA9IDA7XG4gICAgb3V0WzE0XSA9ICgyICogZmFyICogbmVhcikgKiBuZjtcbiAgICBvdXRbMTVdID0gMDtcbiAgICByZXR1cm4gb3V0O1xufTtcbn0se31dLDI3MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHJvdGF0ZTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0NCBieSB0aGUgZ2l2ZW4gYW5nbGVcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHBhcmFtIHt2ZWMzfSBheGlzIHRoZSBheGlzIHRvIHJvdGF0ZSBhcm91bmRcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuZnVuY3Rpb24gcm90YXRlKG91dCwgYSwgcmFkLCBheGlzKSB7XG4gICAgdmFyIHggPSBheGlzWzBdLCB5ID0gYXhpc1sxXSwgeiA9IGF4aXNbMl0sXG4gICAgICAgIGxlbiA9IE1hdGguc3FydCh4ICogeCArIHkgKiB5ICsgeiAqIHopLFxuICAgICAgICBzLCBjLCB0LFxuICAgICAgICBhMDAsIGEwMSwgYTAyLCBhMDMsXG4gICAgICAgIGExMCwgYTExLCBhMTIsIGExMyxcbiAgICAgICAgYTIwLCBhMjEsIGEyMiwgYTIzLFxuICAgICAgICBiMDAsIGIwMSwgYjAyLFxuICAgICAgICBiMTAsIGIxMSwgYjEyLFxuICAgICAgICBiMjAsIGIyMSwgYjIyO1xuXG4gICAgaWYgKE1hdGguYWJzKGxlbikgPCAwLjAwMDAwMSkgeyByZXR1cm4gbnVsbDsgfVxuICAgIFxuICAgIGxlbiA9IDEgLyBsZW47XG4gICAgeCAqPSBsZW47XG4gICAgeSAqPSBsZW47XG4gICAgeiAqPSBsZW47XG5cbiAgICBzID0gTWF0aC5zaW4ocmFkKTtcbiAgICBjID0gTWF0aC5jb3MocmFkKTtcbiAgICB0ID0gMSAtIGM7XG5cbiAgICBhMDAgPSBhWzBdOyBhMDEgPSBhWzFdOyBhMDIgPSBhWzJdOyBhMDMgPSBhWzNdO1xuICAgIGExMCA9IGFbNF07IGExMSA9IGFbNV07IGExMiA9IGFbNl07IGExMyA9IGFbN107XG4gICAgYTIwID0gYVs4XTsgYTIxID0gYVs5XTsgYTIyID0gYVsxMF07IGEyMyA9IGFbMTFdO1xuXG4gICAgLy8gQ29uc3RydWN0IHRoZSBlbGVtZW50cyBvZiB0aGUgcm90YXRpb24gbWF0cml4XG4gICAgYjAwID0geCAqIHggKiB0ICsgYzsgYjAxID0geSAqIHggKiB0ICsgeiAqIHM7IGIwMiA9IHogKiB4ICogdCAtIHkgKiBzO1xuICAgIGIxMCA9IHggKiB5ICogdCAtIHogKiBzOyBiMTEgPSB5ICogeSAqIHQgKyBjOyBiMTIgPSB6ICogeSAqIHQgKyB4ICogcztcbiAgICBiMjAgPSB4ICogeiAqIHQgKyB5ICogczsgYjIxID0geSAqIHogKiB0IC0geCAqIHM7IGIyMiA9IHogKiB6ICogdCArIGM7XG5cbiAgICAvLyBQZXJmb3JtIHJvdGF0aW9uLXNwZWNpZmljIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuICAgIG91dFswXSA9IGEwMCAqIGIwMCArIGExMCAqIGIwMSArIGEyMCAqIGIwMjtcbiAgICBvdXRbMV0gPSBhMDEgKiBiMDAgKyBhMTEgKiBiMDEgKyBhMjEgKiBiMDI7XG4gICAgb3V0WzJdID0gYTAyICogYjAwICsgYTEyICogYjAxICsgYTIyICogYjAyO1xuICAgIG91dFszXSA9IGEwMyAqIGIwMCArIGExMyAqIGIwMSArIGEyMyAqIGIwMjtcbiAgICBvdXRbNF0gPSBhMDAgKiBiMTAgKyBhMTAgKiBiMTEgKyBhMjAgKiBiMTI7XG4gICAgb3V0WzVdID0gYTAxICogYjEwICsgYTExICogYjExICsgYTIxICogYjEyO1xuICAgIG91dFs2XSA9IGEwMiAqIGIxMCArIGExMiAqIGIxMSArIGEyMiAqIGIxMjtcbiAgICBvdXRbN10gPSBhMDMgKiBiMTAgKyBhMTMgKiBiMTEgKyBhMjMgKiBiMTI7XG4gICAgb3V0WzhdID0gYTAwICogYjIwICsgYTEwICogYjIxICsgYTIwICogYjIyO1xuICAgIG91dFs5XSA9IGEwMSAqIGIyMCArIGExMSAqIGIyMSArIGEyMSAqIGIyMjtcbiAgICBvdXRbMTBdID0gYTAyICogYjIwICsgYTEyICogYjIxICsgYTIyICogYjIyO1xuICAgIG91dFsxMV0gPSBhMDMgKiBiMjAgKyBhMTMgKiBiMjEgKyBhMjMgKiBiMjI7XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIGxhc3Qgcm93XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG59LHt9XSwyNzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSByb3RhdGVYO1xuXG4vKipcbiAqIFJvdGF0ZXMgYSBtYXRyaXggYnkgdGhlIGdpdmVuIGFuZ2xlIGFyb3VuZCB0aGUgWCBheGlzXG4gKlxuICogQHBhcmFtIHttYXQ0fSBvdXQgdGhlIHJlY2VpdmluZyBtYXRyaXhcbiAqIEBwYXJhbSB7bWF0NH0gYSB0aGUgbWF0cml4IHRvIHJvdGF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHJhZCB0aGUgYW5nbGUgdG8gcm90YXRlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuZnVuY3Rpb24gcm90YXRlWChvdXQsIGEsIHJhZCkge1xuICAgIHZhciBzID0gTWF0aC5zaW4ocmFkKSxcbiAgICAgICAgYyA9IE1hdGguY29zKHJhZCksXG4gICAgICAgIGExMCA9IGFbNF0sXG4gICAgICAgIGExMSA9IGFbNV0sXG4gICAgICAgIGExMiA9IGFbNl0sXG4gICAgICAgIGExMyA9IGFbN10sXG4gICAgICAgIGEyMCA9IGFbOF0sXG4gICAgICAgIGEyMSA9IGFbOV0sXG4gICAgICAgIGEyMiA9IGFbMTBdLFxuICAgICAgICBhMjMgPSBhWzExXTtcblxuICAgIGlmIChhICE9PSBvdXQpIHsgLy8gSWYgdGhlIHNvdXJjZSBhbmQgZGVzdGluYXRpb24gZGlmZmVyLCBjb3B5IHRoZSB1bmNoYW5nZWQgcm93c1xuICAgICAgICBvdXRbMF0gID0gYVswXTtcbiAgICAgICAgb3V0WzFdICA9IGFbMV07XG4gICAgICAgIG91dFsyXSAgPSBhWzJdO1xuICAgICAgICBvdXRbM10gID0gYVszXTtcbiAgICAgICAgb3V0WzEyXSA9IGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhWzE0XTtcbiAgICAgICAgb3V0WzE1XSA9IGFbMTVdO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm0gYXhpcy1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cbiAgICBvdXRbNF0gPSBhMTAgKiBjICsgYTIwICogcztcbiAgICBvdXRbNV0gPSBhMTEgKiBjICsgYTIxICogcztcbiAgICBvdXRbNl0gPSBhMTIgKiBjICsgYTIyICogcztcbiAgICBvdXRbN10gPSBhMTMgKiBjICsgYTIzICogcztcbiAgICBvdXRbOF0gPSBhMjAgKiBjIC0gYTEwICogcztcbiAgICBvdXRbOV0gPSBhMjEgKiBjIC0gYTExICogcztcbiAgICBvdXRbMTBdID0gYTIyICogYyAtIGExMiAqIHM7XG4gICAgb3V0WzExXSA9IGEyMyAqIGMgLSBhMTMgKiBzO1xuICAgIHJldHVybiBvdXQ7XG59O1xufSx7fV0sMjcyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gcm90YXRlWTtcblxuLyoqXG4gKiBSb3RhdGVzIGEgbWF0cml4IGJ5IHRoZSBnaXZlbiBhbmdsZSBhcm91bmQgdGhlIFkgYXhpc1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIG1hdHJpeCB0byByb3RhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSByYWQgdGhlIGFuZ2xlIHRvIHJvdGF0ZSB0aGUgbWF0cml4IGJ5XG4gKiBAcmV0dXJucyB7bWF0NH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHJvdGF0ZVkob3V0LCBhLCByYWQpIHtcbiAgICB2YXIgcyA9IE1hdGguc2luKHJhZCksXG4gICAgICAgIGMgPSBNYXRoLmNvcyhyYWQpLFxuICAgICAgICBhMDAgPSBhWzBdLFxuICAgICAgICBhMDEgPSBhWzFdLFxuICAgICAgICBhMDIgPSBhWzJdLFxuICAgICAgICBhMDMgPSBhWzNdLFxuICAgICAgICBhMjAgPSBhWzhdLFxuICAgICAgICBhMjEgPSBhWzldLFxuICAgICAgICBhMjIgPSBhWzEwXSxcbiAgICAgICAgYTIzID0gYVsxMV07XG5cbiAgICBpZiAoYSAhPT0gb3V0KSB7IC8vIElmIHRoZSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGRpZmZlciwgY29weSB0aGUgdW5jaGFuZ2VkIHJvd3NcbiAgICAgICAgb3V0WzRdICA9IGFbNF07XG4gICAgICAgIG91dFs1XSAgPSBhWzVdO1xuICAgICAgICBvdXRbNl0gID0gYVs2XTtcbiAgICAgICAgb3V0WzddICA9IGFbN107XG4gICAgICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsxNF07XG4gICAgICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGF4aXMtc3BlY2lmaWMgbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAgb3V0WzBdID0gYTAwICogYyAtIGEyMCAqIHM7XG4gICAgb3V0WzFdID0gYTAxICogYyAtIGEyMSAqIHM7XG4gICAgb3V0WzJdID0gYTAyICogYyAtIGEyMiAqIHM7XG4gICAgb3V0WzNdID0gYTAzICogYyAtIGEyMyAqIHM7XG4gICAgb3V0WzhdID0gYTAwICogcyArIGEyMCAqIGM7XG4gICAgb3V0WzldID0gYTAxICogcyArIGEyMSAqIGM7XG4gICAgb3V0WzEwXSA9IGEwMiAqIHMgKyBhMjIgKiBjO1xuICAgIG91dFsxMV0gPSBhMDMgKiBzICsgYTIzICogYztcbiAgICByZXR1cm4gb3V0O1xufTtcbn0se31dLDI3MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHJvdGF0ZVo7XG5cbi8qKlxuICogUm90YXRlcyBhIG1hdHJpeCBieSB0aGUgZ2l2ZW4gYW5nbGUgYXJvdW5kIHRoZSBaIGF4aXNcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gcm90YXRlXG4gKiBAcGFyYW0ge051bWJlcn0gcmFkIHRoZSBhbmdsZSB0byByb3RhdGUgdGhlIG1hdHJpeCBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5mdW5jdGlvbiByb3RhdGVaKG91dCwgYSwgcmFkKSB7XG4gICAgdmFyIHMgPSBNYXRoLnNpbihyYWQpLFxuICAgICAgICBjID0gTWF0aC5jb3MocmFkKSxcbiAgICAgICAgYTAwID0gYVswXSxcbiAgICAgICAgYTAxID0gYVsxXSxcbiAgICAgICAgYTAyID0gYVsyXSxcbiAgICAgICAgYTAzID0gYVszXSxcbiAgICAgICAgYTEwID0gYVs0XSxcbiAgICAgICAgYTExID0gYVs1XSxcbiAgICAgICAgYTEyID0gYVs2XSxcbiAgICAgICAgYTEzID0gYVs3XTtcblxuICAgIGlmIChhICE9PSBvdXQpIHsgLy8gSWYgdGhlIHNvdXJjZSBhbmQgZGVzdGluYXRpb24gZGlmZmVyLCBjb3B5IHRoZSB1bmNoYW5nZWQgbGFzdCByb3dcbiAgICAgICAgb3V0WzhdICA9IGFbOF07XG4gICAgICAgIG91dFs5XSAgPSBhWzldO1xuICAgICAgICBvdXRbMTBdID0gYVsxMF07XG4gICAgICAgIG91dFsxMV0gPSBhWzExXTtcbiAgICAgICAgb3V0WzEyXSA9IGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhWzE0XTtcbiAgICAgICAgb3V0WzE1XSA9IGFbMTVdO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm0gYXhpcy1zcGVjaWZpYyBtYXRyaXggbXVsdGlwbGljYXRpb25cbiAgICBvdXRbMF0gPSBhMDAgKiBjICsgYTEwICogcztcbiAgICBvdXRbMV0gPSBhMDEgKiBjICsgYTExICogcztcbiAgICBvdXRbMl0gPSBhMDIgKiBjICsgYTEyICogcztcbiAgICBvdXRbM10gPSBhMDMgKiBjICsgYTEzICogcztcbiAgICBvdXRbNF0gPSBhMTAgKiBjIC0gYTAwICogcztcbiAgICBvdXRbNV0gPSBhMTEgKiBjIC0gYTAxICogcztcbiAgICBvdXRbNl0gPSBhMTIgKiBjIC0gYTAyICogcztcbiAgICBvdXRbN10gPSBhMTMgKiBjIC0gYTAzICogcztcbiAgICByZXR1cm4gb3V0O1xufTtcbn0se31dLDI3NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHNjYWxlO1xuXG4vKipcbiAqIFNjYWxlcyB0aGUgbWF0NCBieSB0aGUgZGltZW5zaW9ucyBpbiB0aGUgZ2l2ZW4gdmVjM1xuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIG1hdHJpeCB0byBzY2FsZVxuICogQHBhcmFtIHt2ZWMzfSB2IHRoZSB2ZWMzIHRvIHNjYWxlIHRoZSBtYXRyaXggYnlcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqKi9cbmZ1bmN0aW9uIHNjYWxlKG91dCwgYSwgdikge1xuICAgIHZhciB4ID0gdlswXSwgeSA9IHZbMV0sIHogPSB2WzJdO1xuXG4gICAgb3V0WzBdID0gYVswXSAqIHg7XG4gICAgb3V0WzFdID0gYVsxXSAqIHg7XG4gICAgb3V0WzJdID0gYVsyXSAqIHg7XG4gICAgb3V0WzNdID0gYVszXSAqIHg7XG4gICAgb3V0WzRdID0gYVs0XSAqIHk7XG4gICAgb3V0WzVdID0gYVs1XSAqIHk7XG4gICAgb3V0WzZdID0gYVs2XSAqIHk7XG4gICAgb3V0WzddID0gYVs3XSAqIHk7XG4gICAgb3V0WzhdID0gYVs4XSAqIHo7XG4gICAgb3V0WzldID0gYVs5XSAqIHo7XG4gICAgb3V0WzEwXSA9IGFbMTBdICogejtcbiAgICBvdXRbMTFdID0gYVsxMV0gKiB6O1xuICAgIG91dFsxMl0gPSBhWzEyXTtcbiAgICBvdXRbMTNdID0gYVsxM107XG4gICAgb3V0WzE0XSA9IGFbMTRdO1xuICAgIG91dFsxNV0gPSBhWzE1XTtcbiAgICByZXR1cm4gb3V0O1xufTtcbn0se31dLDI3NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHRyYW5zbGF0ZTtcblxuLyoqXG4gKiBUcmFuc2xhdGUgYSBtYXQ0IGJ5IHRoZSBnaXZlbiB2ZWN0b3JcbiAqXG4gKiBAcGFyYW0ge21hdDR9IG91dCB0aGUgcmVjZWl2aW5nIG1hdHJpeFxuICogQHBhcmFtIHttYXQ0fSBhIHRoZSBtYXRyaXggdG8gdHJhbnNsYXRlXG4gKiBAcGFyYW0ge3ZlYzN9IHYgdmVjdG9yIHRvIHRyYW5zbGF0ZSBieVxuICogQHJldHVybnMge21hdDR9IG91dFxuICovXG5mdW5jdGlvbiB0cmFuc2xhdGUob3V0LCBhLCB2KSB7XG4gICAgdmFyIHggPSB2WzBdLCB5ID0gdlsxXSwgeiA9IHZbMl0sXG4gICAgICAgIGEwMCwgYTAxLCBhMDIsIGEwMyxcbiAgICAgICAgYTEwLCBhMTEsIGExMiwgYTEzLFxuICAgICAgICBhMjAsIGEyMSwgYTIyLCBhMjM7XG5cbiAgICBpZiAoYSA9PT0gb3V0KSB7XG4gICAgICAgIG91dFsxMl0gPSBhWzBdICogeCArIGFbNF0gKiB5ICsgYVs4XSAqIHogKyBhWzEyXTtcbiAgICAgICAgb3V0WzEzXSA9IGFbMV0gKiB4ICsgYVs1XSAqIHkgKyBhWzldICogeiArIGFbMTNdO1xuICAgICAgICBvdXRbMTRdID0gYVsyXSAqIHggKyBhWzZdICogeSArIGFbMTBdICogeiArIGFbMTRdO1xuICAgICAgICBvdXRbMTVdID0gYVszXSAqIHggKyBhWzddICogeSArIGFbMTFdICogeiArIGFbMTVdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGEwMCA9IGFbMF07IGEwMSA9IGFbMV07IGEwMiA9IGFbMl07IGEwMyA9IGFbM107XG4gICAgICAgIGExMCA9IGFbNF07IGExMSA9IGFbNV07IGExMiA9IGFbNl07IGExMyA9IGFbN107XG4gICAgICAgIGEyMCA9IGFbOF07IGEyMSA9IGFbOV07IGEyMiA9IGFbMTBdOyBhMjMgPSBhWzExXTtcblxuICAgICAgICBvdXRbMF0gPSBhMDA7IG91dFsxXSA9IGEwMTsgb3V0WzJdID0gYTAyOyBvdXRbM10gPSBhMDM7XG4gICAgICAgIG91dFs0XSA9IGExMDsgb3V0WzVdID0gYTExOyBvdXRbNl0gPSBhMTI7IG91dFs3XSA9IGExMztcbiAgICAgICAgb3V0WzhdID0gYTIwOyBvdXRbOV0gPSBhMjE7IG91dFsxMF0gPSBhMjI7IG91dFsxMV0gPSBhMjM7XG5cbiAgICAgICAgb3V0WzEyXSA9IGEwMCAqIHggKyBhMTAgKiB5ICsgYTIwICogeiArIGFbMTJdO1xuICAgICAgICBvdXRbMTNdID0gYTAxICogeCArIGExMSAqIHkgKyBhMjEgKiB6ICsgYVsxM107XG4gICAgICAgIG91dFsxNF0gPSBhMDIgKiB4ICsgYTEyICogeSArIGEyMiAqIHogKyBhWzE0XTtcbiAgICAgICAgb3V0WzE1XSA9IGEwMyAqIHggKyBhMTMgKiB5ICsgYTIzICogeiArIGFbMTVdO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59O1xufSx7fV0sMjc2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gdHJhbnNwb3NlO1xuXG4vKipcbiAqIFRyYW5zcG9zZSB0aGUgdmFsdWVzIG9mIGEgbWF0NFxuICpcbiAqIEBwYXJhbSB7bWF0NH0gb3V0IHRoZSByZWNlaXZpbmcgbWF0cml4XG4gKiBAcGFyYW0ge21hdDR9IGEgdGhlIHNvdXJjZSBtYXRyaXhcbiAqIEByZXR1cm5zIHttYXQ0fSBvdXRcbiAqL1xuZnVuY3Rpb24gdHJhbnNwb3NlKG91dCwgYSkge1xuICAgIC8vIElmIHdlIGFyZSB0cmFuc3Bvc2luZyBvdXJzZWx2ZXMgd2UgY2FuIHNraXAgYSBmZXcgc3RlcHMgYnV0IGhhdmUgdG8gY2FjaGUgc29tZSB2YWx1ZXNcbiAgICBpZiAob3V0ID09PSBhKSB7XG4gICAgICAgIHZhciBhMDEgPSBhWzFdLCBhMDIgPSBhWzJdLCBhMDMgPSBhWzNdLFxuICAgICAgICAgICAgYTEyID0gYVs2XSwgYTEzID0gYVs3XSxcbiAgICAgICAgICAgIGEyMyA9IGFbMTFdO1xuXG4gICAgICAgIG91dFsxXSA9IGFbNF07XG4gICAgICAgIG91dFsyXSA9IGFbOF07XG4gICAgICAgIG91dFszXSA9IGFbMTJdO1xuICAgICAgICBvdXRbNF0gPSBhMDE7XG4gICAgICAgIG91dFs2XSA9IGFbOV07XG4gICAgICAgIG91dFs3XSA9IGFbMTNdO1xuICAgICAgICBvdXRbOF0gPSBhMDI7XG4gICAgICAgIG91dFs5XSA9IGExMjtcbiAgICAgICAgb3V0WzExXSA9IGFbMTRdO1xuICAgICAgICBvdXRbMTJdID0gYTAzO1xuICAgICAgICBvdXRbMTNdID0gYTEzO1xuICAgICAgICBvdXRbMTRdID0gYTIzO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG91dFswXSA9IGFbMF07XG4gICAgICAgIG91dFsxXSA9IGFbNF07XG4gICAgICAgIG91dFsyXSA9IGFbOF07XG4gICAgICAgIG91dFszXSA9IGFbMTJdO1xuICAgICAgICBvdXRbNF0gPSBhWzFdO1xuICAgICAgICBvdXRbNV0gPSBhWzVdO1xuICAgICAgICBvdXRbNl0gPSBhWzldO1xuICAgICAgICBvdXRbN10gPSBhWzEzXTtcbiAgICAgICAgb3V0WzhdID0gYVsyXTtcbiAgICAgICAgb3V0WzldID0gYVs2XTtcbiAgICAgICAgb3V0WzEwXSA9IGFbMTBdO1xuICAgICAgICBvdXRbMTFdID0gYVsxNF07XG4gICAgICAgIG91dFsxMl0gPSBhWzNdO1xuICAgICAgICBvdXRbMTNdID0gYVs3XTtcbiAgICAgICAgb3V0WzE0XSA9IGFbMTFdO1xuICAgICAgICBvdXRbMTVdID0gYVsxNV07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBvdXQ7XG59O1xufSx7fV0sMjc3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGludmVydFxuXG52YXIgaW52ZXJ0MiA9IF9kZXJlcV8oJ2dsLW1hdDIvaW52ZXJ0JylcbnZhciBpbnZlcnQzID0gX2RlcmVxXygnZ2wtbWF0My9pbnZlcnQnKVxudmFyIGludmVydDQgPSBfZGVyZXFfKCdnbC1tYXQ0L2ludmVydCcpXG5cbmZ1bmN0aW9uIGludmVydChvdXQsIE0pIHtcbiAgc3dpdGNoKE0ubGVuZ3RoKSB7XG4gICAgY2FzZSAwOlxuICAgIGJyZWFrXG4gICAgY2FzZSAxOlxuICAgICAgb3V0WzBdID0gMS4wIC8gTVswXVxuICAgIGJyZWFrXG4gICAgY2FzZSA0OlxuICAgICAgaW52ZXJ0MihvdXQsIE0pXG4gICAgYnJlYWtcbiAgICBjYXNlIDk6XG4gICAgICBpbnZlcnQzKG91dCwgTSlcbiAgICBicmVha1xuICAgIGNhc2UgMTY6XG4gICAgICBpbnZlcnQ0KG91dCwgTSlcbiAgICBicmVha1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnRseSBzdXBwb3J0cyBtYXRyaWNlcyB1cCB0byA0eDQnKVxuICAgIGJyZWFrXG4gIH1cbiAgcmV0dXJuIG91dFxufVxufSx7XCJnbC1tYXQyL2ludmVydFwiOjI1NyxcImdsLW1hdDMvaW52ZXJ0XCI6MjU4LFwiZ2wtbWF0NC9pbnZlcnRcIjoyNjV9XSwyNzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBiYXJ5Y2VudHJpYyAgICAgICAgICAgID0gX2RlcmVxXygnYmFyeWNlbnRyaWMnKVxudmFyIGNsb3Nlc3RQb2ludFRvVHJpYW5nbGUgPSBfZGVyZXFfKCdwb2x5dG9wZS1jbG9zZXN0LXBvaW50L2xpYi9jbG9zZXN0X3BvaW50XzJkLmpzJylcblxubW9kdWxlLmV4cG9ydHMgPSBjbG9zZXN0UG9pbnRUb1BpY2tMb2NhdGlvblxuXG5mdW5jdGlvbiB4Zm9ybU1hdHJpeChtLCB2KSB7XG4gIHZhciBvdXQgPSBbMCwwLDAsMF1cbiAgZm9yKHZhciBpPTA7IGk8NDsgKytpKSB7XG4gICAgZm9yKHZhciBqPTA7IGo8NDsgKytqKSB7XG4gICAgICBvdXRbal0gKz0gbVs0KmkgKyBqXSAqIHZbaV1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG5mdW5jdGlvbiBwcm9qZWN0VmVydGV4KHYsIG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uLCByZXNvbHV0aW9uKSB7XG4gIHZhciBwID0geGZvcm1NYXRyaXgocHJvamVjdGlvbixcbiAgICAgICAgICAgIHhmb3JtTWF0cml4KHZpZXcsXG4gICAgICAgICAgICAgIHhmb3JtTWF0cml4KG1vZGVsLCBbdlswXSwgdlsxXSwgdlsyXSwgMV0pKSlcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgcFtpXSAvPSBwWzNdXG4gIH1cbiAgcmV0dXJuIFsgMC41ICogcmVzb2x1dGlvblswXSAqICgxLjArcFswXSksIDAuNSAqIHJlc29sdXRpb25bMV0gKiAoMS4wLXBbMV0pIF1cbn1cblxuZnVuY3Rpb24gYmFyeWNlbnRyaWNDb29yZChzaW1wbGV4LCBwb2ludCkge1xuICBpZihzaW1wbGV4Lmxlbmd0aCA9PT0gMikge1xuICAgIHZhciBkMCA9IDAuMFxuICAgIHZhciBkMSA9IDAuMFxuICAgIGZvcih2YXIgaT0wOyBpPDI7ICsraSkge1xuICAgICAgZDAgKz0gTWF0aC5wb3cocG9pbnRbaV0gLSBzaW1wbGV4WzBdW2ldLCAyKVxuICAgICAgZDEgKz0gTWF0aC5wb3cocG9pbnRbaV0gLSBzaW1wbGV4WzFdW2ldLCAyKVxuICAgIH1cbiAgICBkMCA9IE1hdGguc3FydChkMClcbiAgICBkMSA9IE1hdGguc3FydChkMSlcbiAgICBpZihkMCtkMSA8IDFlLTYpIHtcbiAgICAgIHJldHVybiBbMSwwXVxuICAgIH1cbiAgICByZXR1cm4gW2QxLyhkMCtkMSksZDAvKGQxK2QwKV1cbiAgfSBlbHNlIGlmKHNpbXBsZXgubGVuZ3RoID09PSAzKSB7XG4gICAgdmFyIGNsb3Nlc3RQb2ludCA9IFswLDBdXG4gICAgY2xvc2VzdFBvaW50VG9UcmlhbmdsZShzaW1wbGV4WzBdLCBzaW1wbGV4WzFdLCBzaW1wbGV4WzJdLCBwb2ludCwgY2xvc2VzdFBvaW50KVxuICAgIHJldHVybiBiYXJ5Y2VudHJpYyhzaW1wbGV4LCBjbG9zZXN0UG9pbnQpXG4gIH1cbiAgcmV0dXJuIFtdXG59XG5cbmZ1bmN0aW9uIGludGVycG9sYXRlKHNpbXBsZXgsIHdlaWdodHMpIHtcbiAgdmFyIHJlc3VsdCA9IFswLDAsMF1cbiAgZm9yKHZhciBpPTA7IGk8c2ltcGxleC5sZW5ndGg7ICsraSkge1xuICAgIHZhciBwID0gc2ltcGxleFtpXVxuICAgIHZhciB3ID0gd2VpZ2h0c1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgcmVzdWx0W2pdICs9IHcgKiBwW2pdXG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gY2xvc2VzdFBvaW50VG9QaWNrTG9jYXRpb24oc2ltcGxleCwgcGl4ZWxDb29yZCwgbW9kZWwsIHZpZXcsIHByb2plY3Rpb24sIHJlc29sdXRpb24pIHtcbiAgaWYoc2ltcGxleC5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gWzAsIHNpbXBsZXhbMF0uc2xpY2UoKV1cbiAgfVxuICB2YXIgc2ltcGxleDJEID0gbmV3IEFycmF5KHNpbXBsZXgubGVuZ3RoKVxuICBmb3IodmFyIGk9MDsgaTxzaW1wbGV4Lmxlbmd0aDsgKytpKSB7XG4gICAgc2ltcGxleDJEW2ldID0gcHJvamVjdFZlcnRleChzaW1wbGV4W2ldLCBtb2RlbCwgdmlldywgcHJvamVjdGlvbiwgcmVzb2x1dGlvbik7XG4gIH1cblxuICB2YXIgY2xvc2VzdEluZGV4ID0gMFxuICB2YXIgY2xvc2VzdERpc3QgID0gSW5maW5pdHlcbiAgZm9yKHZhciBpPTA7IGk8c2ltcGxleDJELmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGQyID0gMC4wXG4gICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XG4gICAgICBkMiArPSBNYXRoLnBvdyhzaW1wbGV4MkRbaV1bal0gLSBwaXhlbENvb3JkW2pdLCAyKVxuICAgIH1cbiAgICBpZihkMiA8IGNsb3Nlc3REaXN0KSB7XG4gICAgICBjbG9zZXN0RGlzdCAgPSBkMlxuICAgICAgY2xvc2VzdEluZGV4ID0gaVxuICAgIH1cbiAgfVxuXG4gIHZhciB3ZWlnaHRzID0gYmFyeWNlbnRyaWNDb29yZChzaW1wbGV4MkQsIHBpeGVsQ29vcmQpXG4gIHZhciBzID0gMC4wXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIGlmKHdlaWdodHNbaV0gPCAtMC4wMDEgfHxcbiAgICAgICB3ZWlnaHRzW2ldID4gMS4wMDAxKSB7XG4gICAgICByZXR1cm4gbnVsbFxuICAgIH1cbiAgICBzICs9IHdlaWdodHNbaV1cbiAgfVxuICBpZihNYXRoLmFicyhzIC0gMS4wKSA+IDAuMDAxKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICByZXR1cm4gW2Nsb3Nlc3RJbmRleCwgaW50ZXJwb2xhdGUoc2ltcGxleCwgd2VpZ2h0cyksIHdlaWdodHNdXG59XG59LHtcImJhcnljZW50cmljXCI6NzMsXCJwb2x5dG9wZS1jbG9zZXN0LXBvaW50L2xpYi9jbG9zZXN0X3BvaW50XzJkLmpzXCI6NDgxfV0sMjc5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciBnbHNsaWZ5ICAgICAgID0gX2RlcmVxXygnZ2xzbGlmeScpXG5cbnZhciB0cmlWZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbiwgbm9ybWFsO1xcbmF0dHJpYnV0ZSB2ZWM0IGNvbG9yO1xcbmF0dHJpYnV0ZSB2ZWMyIHV2O1xcblxcbnVuaWZvcm0gbWF0NCBtb2RlbFxcbiAgICAgICAgICAgLCB2aWV3XFxuICAgICAgICAgICAsIHByb2plY3Rpb25cXG4gICAgICAgICAgICwgaW52ZXJzZU1vZGVsO1xcbnVuaWZvcm0gdmVjMyBleWVQb3NpdGlvblxcbiAgICAgICAgICAgLCBsaWdodFBvc2l0aW9uO1xcblxcbnZhcnlpbmcgdmVjMyBmX25vcm1hbFxcbiAgICAgICAgICAgLCBmX2xpZ2h0RGlyZWN0aW9uXFxuICAgICAgICAgICAsIGZfZXllRGlyZWN0aW9uXFxuICAgICAgICAgICAsIGZfZGF0YTtcXG52YXJ5aW5nIHZlYzQgZl9jb2xvcjtcXG52YXJ5aW5nIHZlYzIgZl91djtcXG5cXG52ZWM0IHByb2plY3QodmVjMyBwKSB7XFxuICByZXR1cm4gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQocCwgMS4wKTtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZ2xfUG9zaXRpb24gICAgICA9IHByb2plY3QocG9zaXRpb24pO1xcblxcbiAgLy9MaWdodGluZyBnZW9tZXRyeSBwYXJhbWV0ZXJzXFxuICB2ZWM0IGNhbWVyYUNvb3JkaW5hdGUgPSB2aWV3ICogdmVjNChwb3NpdGlvbiAsIDEuMCk7XFxuICBjYW1lcmFDb29yZGluYXRlLnh5eiAvPSBjYW1lcmFDb29yZGluYXRlLnc7XFxuICBmX2xpZ2h0RGlyZWN0aW9uID0gbGlnaHRQb3NpdGlvbiAtIGNhbWVyYUNvb3JkaW5hdGUueHl6O1xcbiAgZl9leWVEaXJlY3Rpb24gICA9IGV5ZVBvc2l0aW9uIC0gY2FtZXJhQ29vcmRpbmF0ZS54eXo7XFxuICBmX25vcm1hbCAgPSBub3JtYWxpemUoKHZlYzQobm9ybWFsLCAwLjApICogaW52ZXJzZU1vZGVsKS54eXopO1xcblxcbiAgZl9jb2xvciAgICAgICAgICA9IGNvbG9yO1xcbiAgZl9kYXRhICAgICAgICAgICA9IHBvc2l0aW9uO1xcbiAgZl91diAgICAgICAgICAgICA9IHV2O1xcbn1cXG5cIl0pXG52YXIgdHJpRnJhZ1NyYyA9IGdsc2xpZnkoW1wiI2V4dGVuc2lvbiBHTF9PRVNfc3RhbmRhcmRfZGVyaXZhdGl2ZXMgOiBlbmFibGVcXG5cXG5wcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5mbG9hdCBiZWNrbWFubkRpc3RyaWJ1dGlvbihmbG9hdCB4LCBmbG9hdCByb3VnaG5lc3MpIHtcXG4gIGZsb2F0IE5kb3RIID0gbWF4KHgsIDAuMDAwMSk7XFxuICBmbG9hdCBjb3MyQWxwaGEgPSBOZG90SCAqIE5kb3RIO1xcbiAgZmxvYXQgdGFuMkFscGhhID0gKGNvczJBbHBoYSAtIDEuMCkgLyBjb3MyQWxwaGE7XFxuICBmbG9hdCByb3VnaG5lc3MyID0gcm91Z2huZXNzICogcm91Z2huZXNzO1xcbiAgZmxvYXQgZGVub20gPSAzLjE0MTU5MjY1MzU4OTc5MyAqIHJvdWdobmVzczIgKiBjb3MyQWxwaGEgKiBjb3MyQWxwaGE7XFxuICByZXR1cm4gZXhwKHRhbjJBbHBoYSAvIHJvdWdobmVzczIpIC8gZGVub207XFxufVxcblxcbmZsb2F0IGNvb2tUb3JyYW5jZVNwZWN1bGFyKFxcbiAgdmVjMyBsaWdodERpcmVjdGlvbixcXG4gIHZlYzMgdmlld0RpcmVjdGlvbixcXG4gIHZlYzMgc3VyZmFjZU5vcm1hbCxcXG4gIGZsb2F0IHJvdWdobmVzcyxcXG4gIGZsb2F0IGZyZXNuZWwpIHtcXG5cXG4gIGZsb2F0IFZkb3ROID0gbWF4KGRvdCh2aWV3RGlyZWN0aW9uLCBzdXJmYWNlTm9ybWFsKSwgMC4wKTtcXG4gIGZsb2F0IExkb3ROID0gbWF4KGRvdChsaWdodERpcmVjdGlvbiwgc3VyZmFjZU5vcm1hbCksIDAuMCk7XFxuXFxuICAvL0hhbGYgYW5nbGUgdmVjdG9yXFxuICB2ZWMzIEggPSBub3JtYWxpemUobGlnaHREaXJlY3Rpb24gKyB2aWV3RGlyZWN0aW9uKTtcXG5cXG4gIC8vR2VvbWV0cmljIHRlcm1cXG4gIGZsb2F0IE5kb3RIID0gbWF4KGRvdChzdXJmYWNlTm9ybWFsLCBIKSwgMC4wKTtcXG4gIGZsb2F0IFZkb3RIID0gbWF4KGRvdCh2aWV3RGlyZWN0aW9uLCBIKSwgMC4wMDAwMDEpO1xcbiAgZmxvYXQgTGRvdEggPSBtYXgoZG90KGxpZ2h0RGlyZWN0aW9uLCBIKSwgMC4wMDAwMDEpO1xcbiAgZmxvYXQgRzEgPSAoMi4wICogTmRvdEggKiBWZG90TikgLyBWZG90SDtcXG4gIGZsb2F0IEcyID0gKDIuMCAqIE5kb3RIICogTGRvdE4pIC8gTGRvdEg7XFxuICBmbG9hdCBHID0gbWluKDEuMCwgbWluKEcxLCBHMikpO1xcbiAgXFxuICAvL0Rpc3RyaWJ1dGlvbiB0ZXJtXFxuICBmbG9hdCBEID0gYmVja21hbm5EaXN0cmlidXRpb24oTmRvdEgsIHJvdWdobmVzcyk7XFxuXFxuICAvL0ZyZXNuZWwgdGVybVxcbiAgZmxvYXQgRiA9IHBvdygxLjAgLSBWZG90TiwgZnJlc25lbCk7XFxuXFxuICAvL011bHRpcGx5IHRlcm1zIGFuZCBkb25lXFxuICByZXR1cm4gIEcgKiBGICogRCAvIG1heCgzLjE0MTU5MjY1ICogVmRvdE4sIDAuMDAwMDAxKTtcXG59XFxuXFxuLy8jcHJhZ21hIGdsc2xpZnk6IGJlY2ttYW5uID0gcmVxdWlyZShnbHNsLXNwZWN1bGFyLWJlY2ttYW5uKSAvLyB1c2VkIGluIGdsLXN1cmZhY2UzZFxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgcm91Z2huZXNzXFxuICAgICAgICAgICAgLCBmcmVzbmVsXFxuICAgICAgICAgICAgLCBrYW1iaWVudFxcbiAgICAgICAgICAgICwga2RpZmZ1c2VcXG4gICAgICAgICAgICAsIGtzcGVjdWxhcjtcXG51bmlmb3JtIHNhbXBsZXIyRCB0ZXh0dXJlO1xcblxcbnZhcnlpbmcgdmVjMyBmX25vcm1hbFxcbiAgICAgICAgICAgLCBmX2xpZ2h0RGlyZWN0aW9uXFxuICAgICAgICAgICAsIGZfZXllRGlyZWN0aW9uXFxuICAgICAgICAgICAsIGZfZGF0YTtcXG52YXJ5aW5nIHZlYzQgZl9jb2xvcjtcXG52YXJ5aW5nIHZlYzIgZl91djtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAoZl9jb2xvci5hID09IDAuMCB8fFxcbiAgICBvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIGZfZGF0YSlcXG4gICkgZGlzY2FyZDtcXG5cXG4gIHZlYzMgTiA9IG5vcm1hbGl6ZShmX25vcm1hbCk7XFxuICB2ZWMzIEwgPSBub3JtYWxpemUoZl9saWdodERpcmVjdGlvbik7XFxuICB2ZWMzIFYgPSBub3JtYWxpemUoZl9leWVEaXJlY3Rpb24pO1xcblxcbiAgaWYoZ2xfRnJvbnRGYWNpbmcpIHtcXG4gICAgTiA9IC1OO1xcbiAgfVxcblxcbiAgZmxvYXQgc3BlY3VsYXIgPSBtaW4oMS4wLCBtYXgoMC4wLCBjb29rVG9ycmFuY2VTcGVjdWxhcihMLCBWLCBOLCByb3VnaG5lc3MsIGZyZXNuZWwpKSk7XFxuICAvL2Zsb2F0IHNwZWN1bGFyID0gbWF4KDAuMCwgYmVja21hbm4oTCwgViwgTiwgcm91Z2huZXNzKSk7IC8vIHVzZWQgaW4gZ2wtc3VyZmFjZTNkXFxuXFxuICBmbG9hdCBkaWZmdXNlICA9IG1pbihrYW1iaWVudCArIGtkaWZmdXNlICogbWF4KGRvdChOLCBMKSwgMC4wKSwgMS4wKTtcXG5cXG4gIHZlYzQgc3VyZmFjZUNvbG9yID0gdmVjNChmX2NvbG9yLnJnYiwgMS4wKSAqIHRleHR1cmUyRCh0ZXh0dXJlLCBmX3V2KTtcXG4gIHZlYzQgbGl0Q29sb3IgPSBzdXJmYWNlQ29sb3IuYSAqIHZlYzQoZGlmZnVzZSAqIHN1cmZhY2VDb2xvci5yZ2IgKyBrc3BlY3VsYXIgKiB2ZWMzKDEsMSwxKSAqIHNwZWN1bGFyLCAgMS4wKTtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IGxpdENvbG9yICogZl9jb2xvci5hO1xcbn1cXG5cIl0pXG52YXIgZWRnZVZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMzIHBvc2l0aW9uO1xcbmF0dHJpYnV0ZSB2ZWM0IGNvbG9yO1xcbmF0dHJpYnV0ZSB2ZWMyIHV2O1xcblxcbnVuaWZvcm0gbWF0NCBtb2RlbCwgdmlldywgcHJvamVjdGlvbjtcXG5cXG52YXJ5aW5nIHZlYzQgZl9jb2xvcjtcXG52YXJ5aW5nIHZlYzMgZl9kYXRhO1xcbnZhcnlpbmcgdmVjMiBmX3V2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQocG9zaXRpb24sIDEuMCk7XFxuICBmX2NvbG9yID0gY29sb3I7XFxuICBmX2RhdGEgID0gcG9zaXRpb247XFxuICBmX3V2ICAgID0gdXY7XFxufVwiXSlcbnZhciBlZGdlRnJhZ1NyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxudW5pZm9ybSBzYW1wbGVyMkQgdGV4dHVyZTtcXG51bmlmb3JtIGZsb2F0IG9wYWNpdHk7XFxuXFxudmFyeWluZyB2ZWM0IGZfY29sb3I7XFxudmFyeWluZyB2ZWMzIGZfZGF0YTtcXG52YXJ5aW5nIHZlYzIgZl91djtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBmX2RhdGEpKSBkaXNjYXJkO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gZl9jb2xvciAqIHRleHR1cmUyRCh0ZXh0dXJlLCBmX3V2KSAqIG9wYWNpdHk7XFxufVwiXSlcbnZhciBwb2ludFZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbmF0dHJpYnV0ZSB2ZWMzIHBvc2l0aW9uO1xcbmF0dHJpYnV0ZSB2ZWM0IGNvbG9yO1xcbmF0dHJpYnV0ZSB2ZWMyIHV2O1xcbmF0dHJpYnV0ZSBmbG9hdCBwb2ludFNpemU7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcblxcbnZhcnlpbmcgdmVjNCBmX2NvbG9yO1xcbnZhcnlpbmcgdmVjMiBmX3V2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIHBvc2l0aW9uKSkge1xcblxcbiAgICBnbF9Qb3NpdGlvbiA9IHZlYzQoMC4wLCAwLjAgLDAuMCAsMC4wKTtcXG4gIH0gZWxzZSB7XFxuICAgIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQocG9zaXRpb24sIDEuMCk7XFxuICB9XFxuICBnbF9Qb2ludFNpemUgPSBwb2ludFNpemU7XFxuICBmX2NvbG9yID0gY29sb3I7XFxuICBmX3V2ID0gdXY7XFxufVwiXSlcbnZhciBwb2ludEZyYWdTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnVuaWZvcm0gc2FtcGxlcjJEIHRleHR1cmU7XFxudW5pZm9ybSBmbG9hdCBvcGFjaXR5O1xcblxcbnZhcnlpbmcgdmVjNCBmX2NvbG9yO1xcbnZhcnlpbmcgdmVjMiBmX3V2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzIgcG9pbnRSID0gZ2xfUG9pbnRDb29yZC54eSAtIHZlYzIoMC41LCAwLjUpO1xcbiAgaWYoZG90KHBvaW50UiwgcG9pbnRSKSA+IDAuMjUpIHtcXG4gICAgZGlzY2FyZDtcXG4gIH1cXG4gIGdsX0ZyYWdDb2xvciA9IGZfY29sb3IgKiB0ZXh0dXJlMkQodGV4dHVyZSwgZl91dikgKiBvcGFjaXR5O1xcbn1cIl0pXG52YXIgcGlja1ZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMzIHBvc2l0aW9uO1xcbmF0dHJpYnV0ZSB2ZWM0IGlkO1xcblxcbnVuaWZvcm0gbWF0NCBtb2RlbCwgdmlldywgcHJvamVjdGlvbjtcXG5cXG52YXJ5aW5nIHZlYzMgZl9wb3NpdGlvbjtcXG52YXJ5aW5nIHZlYzQgZl9pZDtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBnbF9Qb3NpdGlvbiA9IHByb2plY3Rpb24gKiB2aWV3ICogbW9kZWwgKiB2ZWM0KHBvc2l0aW9uLCAxLjApO1xcbiAgZl9pZCAgICAgICAgPSBpZDtcXG4gIGZfcG9zaXRpb24gID0gcG9zaXRpb247XFxufVwiXSlcbnZhciBwaWNrRnJhZ1NyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzICBjbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgcGlja0lkO1xcblxcbnZhcnlpbmcgdmVjMyBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIGZfcG9zaXRpb24pKSBkaXNjYXJkO1xcblxcbiAgZ2xfRnJhZ0NvbG9yID0gdmVjNChwaWNrSWQsIGZfaWQueHl6KTtcXG59XCJdKVxudmFyIHBpY2tQb2ludFZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbmF0dHJpYnV0ZSB2ZWMzICBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgZmxvYXQgcG9pbnRTaXplO1xcbmF0dHJpYnV0ZSB2ZWM0ICBpZDtcXG5cXG51bmlmb3JtIG1hdDQgbW9kZWwsIHZpZXcsIHByb2plY3Rpb247XFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxuXFxudmFyeWluZyB2ZWMzIGZfcG9zaXRpb247XFxudmFyeWluZyB2ZWM0IGZfaWQ7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgaWYgKG91dE9mUmFuZ2UoY2xpcEJvdW5kc1swXSwgY2xpcEJvdW5kc1sxXSwgcG9zaXRpb24pKSB7XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gdmVjNCgwLjAsIDAuMCwgMC4wLCAwLjApO1xcbiAgfSBlbHNlIHtcXG4gICAgZ2xfUG9zaXRpb24gID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQocG9zaXRpb24sIDEuMCk7XFxuICAgIGdsX1BvaW50U2l6ZSA9IHBvaW50U2l6ZTtcXG4gIH1cXG4gIGZfaWQgICAgICAgICA9IGlkO1xcbiAgZl9wb3NpdGlvbiAgID0gcG9zaXRpb247XFxufVwiXSlcbnZhciBjb250b3VyVmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiBtb2RlbCAqIHZlYzQocG9zaXRpb24sIDEuMCk7XFxufVwiXSlcbnZhciBjb250b3VyRnJhZ1NyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudW5pZm9ybSB2ZWMzIGNvbnRvdXJDb2xvcjtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBnbF9GcmFnQ29sb3IgPSB2ZWM0KGNvbnRvdXJDb2xvciwgMS4wKTtcXG59XFxuXCJdKVxuXG5leHBvcnRzLm1lc2hTaGFkZXIgPSB7XG4gIHZlcnRleDogICB0cmlWZXJ0U3JjLFxuICBmcmFnbWVudDogdHJpRnJhZ1NyYyxcbiAgYXR0cmlidXRlczogW1xuICAgIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjMyd9LFxuICAgIHtuYW1lOiAnbm9ybWFsJywgdHlwZTogJ3ZlYzMnfSxcbiAgICB7bmFtZTogJ2NvbG9yJywgdHlwZTogJ3ZlYzQnfSxcbiAgICB7bmFtZTogJ3V2JywgdHlwZTogJ3ZlYzInfVxuICBdXG59XG5leHBvcnRzLndpcmVTaGFkZXIgPSB7XG4gIHZlcnRleDogICBlZGdlVmVydFNyYyxcbiAgZnJhZ21lbnQ6IGVkZ2VGcmFnU3JjLFxuICBhdHRyaWJ1dGVzOiBbXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXG4gICAge25hbWU6ICdjb2xvcicsIHR5cGU6ICd2ZWM0J30sXG4gICAge25hbWU6ICd1dicsIHR5cGU6ICd2ZWMyJ31cbiAgXVxufVxuZXhwb3J0cy5wb2ludFNoYWRlciA9IHtcbiAgdmVydGV4OiAgIHBvaW50VmVydFNyYyxcbiAgZnJhZ21lbnQ6IHBvaW50RnJhZ1NyYyxcbiAgYXR0cmlidXRlczogW1xuICAgIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjMyd9LFxuICAgIHtuYW1lOiAnY29sb3InLCB0eXBlOiAndmVjNCd9LFxuICAgIHtuYW1lOiAndXYnLCB0eXBlOiAndmVjMid9LFxuICAgIHtuYW1lOiAncG9pbnRTaXplJywgdHlwZTogJ2Zsb2F0J31cbiAgXVxufVxuZXhwb3J0cy5waWNrU2hhZGVyID0ge1xuICB2ZXJ0ZXg6ICAgcGlja1ZlcnRTcmMsXG4gIGZyYWdtZW50OiBwaWNrRnJhZ1NyYyxcbiAgYXR0cmlidXRlczogW1xuICAgIHtuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjMyd9LFxuICAgIHtuYW1lOiAnaWQnLCB0eXBlOiAndmVjNCd9XG4gIF1cbn1cbmV4cG9ydHMucG9pbnRQaWNrU2hhZGVyID0ge1xuICB2ZXJ0ZXg6ICAgcGlja1BvaW50VmVydFNyYyxcbiAgZnJhZ21lbnQ6IHBpY2tGcmFnU3JjLFxuICBhdHRyaWJ1dGVzOiBbXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXG4gICAge25hbWU6ICdwb2ludFNpemUnLCB0eXBlOiAnZmxvYXQnfSxcbiAgICB7bmFtZTogJ2lkJywgdHlwZTogJ3ZlYzQnfVxuICBdXG59XG5leHBvcnRzLmNvbnRvdXJTaGFkZXIgPSB7XG4gIHZlcnRleDogICBjb250b3VyVmVydFNyYyxcbiAgZnJhZ21lbnQ6IGNvbnRvdXJGcmFnU3JjLFxuICBhdHRyaWJ1dGVzOiBbXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ31cbiAgXVxufVxuXG59LHtcImdsc2xpZnlcIjo0MDl9XSwyODA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBERUZBVUxUX1ZFUlRFWF9OT1JNQUxTX0VQU0lMT04gPSAxZS02OyAvLyBtYXkgYmUgdG9vIGxhcmdlIGlmIHRyaWFuZ2xlcyBhcmUgdmVyeSBzbWFsbFxudmFyIERFRkFVTFRfRkFDRV9OT1JNQUxTX0VQU0lMT04gPSAxZS02O1xuXG52YXIgY3JlYXRlU2hhZGVyICA9IF9kZXJlcV8oJ2dsLXNoYWRlcicpXG52YXIgY3JlYXRlQnVmZmVyICA9IF9kZXJlcV8oJ2dsLWJ1ZmZlcicpXG52YXIgY3JlYXRlVkFPICAgICA9IF9kZXJlcV8oJ2dsLXZhbycpXG52YXIgY3JlYXRlVGV4dHVyZSA9IF9kZXJlcV8oJ2dsLXRleHR1cmUyZCcpXG52YXIgbm9ybWFscyAgICAgICA9IF9kZXJlcV8oJ25vcm1hbHMnKVxudmFyIG11bHRpcGx5ICAgICAgPSBfZGVyZXFfKCdnbC1tYXQ0L211bHRpcGx5JylcbnZhciBpbnZlcnQgICAgICAgID0gX2RlcmVxXygnZ2wtbWF0NC9pbnZlcnQnKVxudmFyIG5kYXJyYXkgICAgICAgPSBfZGVyZXFfKCduZGFycmF5JylcbnZhciBjb2xvcm1hcCAgICAgID0gX2RlcmVxXygnY29sb3JtYXAnKVxudmFyIGdldENvbnRvdXIgICAgPSBfZGVyZXFfKCdzaW1wbGljaWFsLWNvbXBsZXgtY29udG91cicpXG52YXIgcG9vbCAgICAgICAgICA9IF9kZXJlcV8oJ3R5cGVkYXJyYXktcG9vbCcpXG52YXIgc2hhZGVycyAgICAgICA9IF9kZXJlcV8oJy4vbGliL3NoYWRlcnMnKVxudmFyIGNsb3Nlc3RQb2ludCAgPSBfZGVyZXFfKCcuL2xpYi9jbG9zZXN0LXBvaW50JylcblxudmFyIG1lc2hTaGFkZXIgICAgPSBzaGFkZXJzLm1lc2hTaGFkZXJcbnZhciB3aXJlU2hhZGVyICAgID0gc2hhZGVycy53aXJlU2hhZGVyXG52YXIgcG9pbnRTaGFkZXIgICA9IHNoYWRlcnMucG9pbnRTaGFkZXJcbnZhciBwaWNrU2hhZGVyICAgID0gc2hhZGVycy5waWNrU2hhZGVyXG52YXIgcG9pbnRQaWNrU2hhZGVyID0gc2hhZGVycy5wb2ludFBpY2tTaGFkZXJcbnZhciBjb250b3VyU2hhZGVyID0gc2hhZGVycy5jb250b3VyU2hhZGVyXG5cbnZhciBJREVOVElUWSA9IFtcbiAgMSwwLDAsMCxcbiAgMCwxLDAsMCxcbiAgMCwwLDEsMCxcbiAgMCwwLDAsMV1cblxuXG5mdW5jdGlvbiBTaW1wbGljaWFsTWVzaChnbFxuICAsIHRleHR1cmVcbiAgLCB0cmlTaGFkZXJcbiAgLCBsaW5lU2hhZGVyXG4gICwgcG9pbnRTaGFkZXJcbiAgLCBwaWNrU2hhZGVyXG4gICwgcG9pbnRQaWNrU2hhZGVyXG4gICwgY29udG91clNoYWRlclxuICAsIHRyaWFuZ2xlUG9zaXRpb25zXG4gICwgdHJpYW5nbGVJZHNcbiAgLCB0cmlhbmdsZUNvbG9yc1xuICAsIHRyaWFuZ2xlVVZzXG4gICwgdHJpYW5nbGVOb3JtYWxzXG4gICwgdHJpYW5nbGVWQU9cbiAgLCBlZGdlUG9zaXRpb25zXG4gICwgZWRnZUlkc1xuICAsIGVkZ2VDb2xvcnNcbiAgLCBlZGdlVVZzXG4gICwgZWRnZVZBT1xuICAsIHBvaW50UG9zaXRpb25zXG4gICwgcG9pbnRJZHNcbiAgLCBwb2ludENvbG9yc1xuICAsIHBvaW50VVZzXG4gICwgcG9pbnRTaXplc1xuICAsIHBvaW50VkFPXG4gICwgY29udG91clBvc2l0aW9uc1xuICAsIGNvbnRvdXJWQU8pIHtcblxuICB0aGlzLmdsICAgICAgICAgICAgICAgID0gZ2xcbiAgdGhpcy5waXhlbFJhdGlvICAgICAgICAgPSAxXG4gIHRoaXMuY2VsbHMgICAgICAgICAgICAgPSBbXVxuICB0aGlzLnBvc2l0aW9ucyAgICAgICAgID0gW11cbiAgdGhpcy5pbnRlbnNpdHkgICAgICAgICA9IFtdXG4gIHRoaXMudGV4dHVyZSAgICAgICAgICAgPSB0ZXh0dXJlXG4gIHRoaXMuZGlydHkgICAgICAgICAgICAgPSB0cnVlXG5cbiAgdGhpcy50cmlTaGFkZXIgICAgICAgICA9IHRyaVNoYWRlclxuICB0aGlzLmxpbmVTaGFkZXIgICAgICAgID0gbGluZVNoYWRlclxuICB0aGlzLnBvaW50U2hhZGVyICAgICAgID0gcG9pbnRTaGFkZXJcbiAgdGhpcy5waWNrU2hhZGVyICAgICAgICA9IHBpY2tTaGFkZXJcbiAgdGhpcy5wb2ludFBpY2tTaGFkZXIgICA9IHBvaW50UGlja1NoYWRlclxuICB0aGlzLmNvbnRvdXJTaGFkZXIgICAgID0gY29udG91clNoYWRlclxuXG4gIHRoaXMudHJpYW5nbGVQb3NpdGlvbnMgPSB0cmlhbmdsZVBvc2l0aW9uc1xuICB0aGlzLnRyaWFuZ2xlQ29sb3JzICAgID0gdHJpYW5nbGVDb2xvcnNcbiAgdGhpcy50cmlhbmdsZU5vcm1hbHMgICA9IHRyaWFuZ2xlTm9ybWFsc1xuICB0aGlzLnRyaWFuZ2xlVVZzICAgICAgID0gdHJpYW5nbGVVVnNcbiAgdGhpcy50cmlhbmdsZUlkcyAgICAgICA9IHRyaWFuZ2xlSWRzXG4gIHRoaXMudHJpYW5nbGVWQU8gICAgICAgPSB0cmlhbmdsZVZBT1xuICB0aGlzLnRyaWFuZ2xlQ291bnQgICAgID0gMFxuXG4gIHRoaXMubGluZVdpZHRoICAgICAgICAgPSAxXG4gIHRoaXMuZWRnZVBvc2l0aW9ucyAgICAgPSBlZGdlUG9zaXRpb25zXG4gIHRoaXMuZWRnZUNvbG9ycyAgICAgICAgPSBlZGdlQ29sb3JzXG4gIHRoaXMuZWRnZVVWcyAgICAgICAgICAgPSBlZGdlVVZzXG4gIHRoaXMuZWRnZUlkcyAgICAgICAgICAgPSBlZGdlSWRzXG4gIHRoaXMuZWRnZVZBTyAgICAgICAgICAgPSBlZGdlVkFPXG4gIHRoaXMuZWRnZUNvdW50ICAgICAgICAgPSAwXG5cbiAgdGhpcy5wb2ludFBvc2l0aW9ucyAgICA9IHBvaW50UG9zaXRpb25zXG4gIHRoaXMucG9pbnRDb2xvcnMgICAgICAgPSBwb2ludENvbG9yc1xuICB0aGlzLnBvaW50VVZzICAgICAgICAgID0gcG9pbnRVVnNcbiAgdGhpcy5wb2ludFNpemVzICAgICAgICA9IHBvaW50U2l6ZXNcbiAgdGhpcy5wb2ludElkcyAgICAgICAgICA9IHBvaW50SWRzXG4gIHRoaXMucG9pbnRWQU8gICAgICAgICAgPSBwb2ludFZBT1xuICB0aGlzLnBvaW50Q291bnQgICAgICAgID0gMFxuXG4gIHRoaXMuY29udG91ckxpbmVXaWR0aCAgPSAxXG4gIHRoaXMuY29udG91clBvc2l0aW9ucyAgPSBjb250b3VyUG9zaXRpb25zXG4gIHRoaXMuY29udG91clZBTyAgICAgICAgPSBjb250b3VyVkFPXG4gIHRoaXMuY29udG91ckNvdW50ICAgICAgPSAwXG4gIHRoaXMuY29udG91ckNvbG9yICAgICAgPSBbMCwwLDBdXG4gIHRoaXMuY29udG91ckVuYWJsZSAgICAgPSB0cnVlXG5cbiAgdGhpcy5waWNrSWQgICAgICAgICAgICA9IDFcbiAgdGhpcy5ib3VuZHMgICAgICAgICAgICA9IFtcbiAgICBbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldLFxuICAgIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV0gXVxuICB0aGlzLmNsaXBCb3VuZHMgICAgICAgID0gW1xuICAgIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV0sXG4gICAgWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XSBdXG5cbiAgdGhpcy5saWdodFBvc2l0aW9uID0gWzFlNSwgMWU1LCAwXVxuICB0aGlzLmFtYmllbnRMaWdodCAgPSAwLjhcbiAgdGhpcy5kaWZmdXNlTGlnaHQgID0gMC44XG4gIHRoaXMuc3BlY3VsYXJMaWdodCA9IDIuMFxuICB0aGlzLnJvdWdobmVzcyAgICAgPSAwLjVcbiAgdGhpcy5mcmVzbmVsICAgICAgID0gMS41XG5cbiAgdGhpcy5vcGFjaXR5ICAgICAgID0gMS4wXG4gIHRoaXMuaGFzQWxwaGEgICAgICA9IGZhbHNlXG4gIHRoaXMub3BhY2l0eXNjYWxlICA9IGZhbHNlXG5cbiAgdGhpcy5fbW9kZWwgICAgICAgPSBJREVOVElUWVxuICB0aGlzLl92aWV3ICAgICAgICA9IElERU5USVRZXG4gIHRoaXMuX3Byb2plY3Rpb24gID0gSURFTlRJVFlcbiAgdGhpcy5fcmVzb2x1dGlvbiAgPSBbMSwxXVxufVxuXG52YXIgcHJvdG8gPSBTaW1wbGljaWFsTWVzaC5wcm90b3R5cGVcblxucHJvdG8uaXNPcGFxdWUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuICF0aGlzLmhhc0FscGhhXG59XG5cbnByb3RvLmlzVHJhbnNwYXJlbnQgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuaGFzQWxwaGFcbn1cblxucHJvdG8ucGlja1Nsb3RzID0gMVxuXG5wcm90by5zZXRQaWNrQmFzZSA9IGZ1bmN0aW9uKGlkKSB7XG4gIHRoaXMucGlja0lkID0gaWRcbn1cblxuZnVuY3Rpb24gZ2V0T3BhY2l0eUZyb21TY2FsZShyYXRpbywgb3BhY2l0eXNjYWxlKSB7XG5cbiAgaWYoIW9wYWNpdHlzY2FsZSkgcmV0dXJuIDFcbiAgaWYoIW9wYWNpdHlzY2FsZS5sZW5ndGgpIHJldHVybiAxXG5cbiAgZm9yKHZhciBpID0gMDsgaSA8IG9wYWNpdHlzY2FsZS5sZW5ndGg7ICsraSkge1xuICAgIGlmKG9wYWNpdHlzY2FsZS5sZW5ndGggPCAyKSByZXR1cm4gMVxuICAgIGlmKG9wYWNpdHlzY2FsZVtpXVswXSA9PT0gcmF0aW8pIHJldHVybiBvcGFjaXR5c2NhbGVbaV1bMV1cbiAgICBpZihvcGFjaXR5c2NhbGVbaV1bMF0gPiByYXRpbyAmJiBpID4gMCkge1xuICAgICAgdmFyIGQgPSAob3BhY2l0eXNjYWxlW2ldWzBdIC0gcmF0aW8pIC8gKG9wYWNpdHlzY2FsZVtpXVswXSAtIG9wYWNpdHlzY2FsZVtpIC0gMV1bMF0pXG4gICAgICByZXR1cm4gb3BhY2l0eXNjYWxlW2ldWzFdICogKDEgLSBkKSArIGQgKiBvcGFjaXR5c2NhbGVbaSAtIDFdWzFdXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIDFcbn1cblxuZnVuY3Rpb24gZ2VuQ29sb3JtYXAocGFyYW0sIG9wYWNpdHlzY2FsZSkge1xuICB2YXIgY29sb3JzID0gY29sb3JtYXAoe1xuICAgICAgY29sb3JtYXA6IHBhcmFtXG4gICAgLCBuc2hhZGVzOiAgMjU2XG4gICAgLCBmb3JtYXQ6ICAncmdiYSdcbiAgfSlcblxuICB2YXIgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoMjU2KjQpXG4gIGZvcih2YXIgaT0wOyBpPDI1NjsgKytpKSB7XG4gICAgdmFyIGMgPSBjb2xvcnNbaV1cbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIHJlc3VsdFs0Kmkral0gPSBjW2pdXG4gICAgfVxuICAgIGlmKCFvcGFjaXR5c2NhbGUpIHtcbiAgICAgIHJlc3VsdFs0KmkrM10gPSAyNTUgKiBjWzNdXG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdFs0KmkrM10gPSAyNTUgKiBnZXRPcGFjaXR5RnJvbVNjYWxlKGkgLyAyNTUuMCwgb3BhY2l0eXNjYWxlKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZGFycmF5KHJlc3VsdCwgWzI1NiwyNTYsNF0sIFs0LDAsMV0pXG59XG5cbmZ1bmN0aW9uIHVucGFja0ludGVuc2l0eShjZWxscywgbnVtVmVydHMsIGNlbGxJbnRlbnNpdHkpIHtcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShudW1WZXJ0cylcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydHM7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IDBcbiAgfVxuICB2YXIgbnVtQ2VsbHMgPSBjZWxscy5sZW5ndGhcbiAgZm9yKHZhciBpPTA7IGk8bnVtQ2VsbHM7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICBmb3IodmFyIGo9MDsgajxjLmxlbmd0aDsgKytqKSB7XG4gICAgICByZXN1bHRbY1tqXV0gPSBjZWxsSW50ZW5zaXR5W2ldXG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gdGFrZVpDb21wb25lbnQoYXJyYXkpIHtcbiAgdmFyIG4gPSBhcnJheS5sZW5ndGhcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShuKVxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSBhcnJheVtpXVsyXVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxucHJvdG8uaGlnaGxpZ2h0ID0gZnVuY3Rpb24oc2VsZWN0aW9uKSB7XG4gIGlmKCFzZWxlY3Rpb24gfHwgIXRoaXMuY29udG91ckVuYWJsZSkge1xuICAgIHRoaXMuY29udG91ckNvdW50ID0gMFxuICAgIHJldHVyblxuICB9XG4gIHZhciBsZXZlbCA9IGdldENvbnRvdXIodGhpcy5jZWxscywgdGhpcy5pbnRlbnNpdHksIHNlbGVjdGlvbi5pbnRlbnNpdHkpXG4gIHZhciBjZWxscyAgICAgICAgID0gbGV2ZWwuY2VsbHNcbiAgdmFyIHZlcnRleElkcyAgICAgPSBsZXZlbC52ZXJ0ZXhJZHNcbiAgdmFyIHZlcnRleFdlaWdodHMgPSBsZXZlbC52ZXJ0ZXhXZWlnaHRzXG4gIHZhciBudW1DZWxscyA9IGNlbGxzLmxlbmd0aFxuICB2YXIgcmVzdWx0ID0gcG9vbC5tYWxsb2NGbG9hdDMyKDIgKiAzICogbnVtQ2VsbHMpXG4gIHZhciBwdHIgPSAwXG4gIGZvcih2YXIgaT0wOyBpPG51bUNlbGxzOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XG4gICAgICB2YXIgdiA9IGNbMF1cbiAgICAgIGlmKGMubGVuZ3RoID09PSAyKSB7XG4gICAgICAgIHYgPSBjW2pdXG4gICAgICB9XG4gICAgICB2YXIgYSA9IHZlcnRleElkc1t2XVswXVxuICAgICAgdmFyIGIgPSB2ZXJ0ZXhJZHNbdl1bMV1cbiAgICAgIHZhciB3ID0gdmVydGV4V2VpZ2h0c1t2XVxuICAgICAgdmFyIHdpID0gMS4wIC0gd1xuICAgICAgdmFyIHBhID0gdGhpcy5wb3NpdGlvbnNbYV1cbiAgICAgIHZhciBwYiA9IHRoaXMucG9zaXRpb25zW2JdXG4gICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgICAgcmVzdWx0W3B0cisrXSA9IHcgKiBwYVtrXSArIHdpICogcGJba11cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdGhpcy5jb250b3VyQ291bnQgPSAocHRyIC8gMyl8MFxuICB0aGlzLmNvbnRvdXJQb3NpdGlvbnMudXBkYXRlKHJlc3VsdC5zdWJhcnJheSgwLCBwdHIpKVxuICBwb29sLmZyZWUocmVzdWx0KVxufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihwYXJhbXMpIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9XG4gIHZhciBnbCA9IHRoaXMuZ2xcblxuICB0aGlzLmRpcnR5ID0gdHJ1ZVxuXG4gIGlmKCdjb250b3VyRW5hYmxlJyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLmNvbnRvdXJFbmFibGUgPSBwYXJhbXMuY29udG91ckVuYWJsZVxuICB9XG4gIGlmKCdjb250b3VyQ29sb3InIGluIHBhcmFtcykge1xuICAgIHRoaXMuY29udG91ckNvbG9yID0gcGFyYW1zLmNvbnRvdXJDb2xvclxuICB9XG4gIGlmKCdsaW5lV2lkdGgnIGluIHBhcmFtcykge1xuICAgIHRoaXMubGluZVdpZHRoID0gcGFyYW1zLmxpbmVXaWR0aFxuICB9XG4gIGlmKCdsaWdodFBvc2l0aW9uJyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLmxpZ2h0UG9zaXRpb24gPSBwYXJhbXMubGlnaHRQb3NpdGlvblxuICB9XG5cbiAgdGhpcy5oYXNBbHBoYSA9IGZhbHNlIC8vIGRlZmF1bHQgdG8gbm8gdHJhbnNwYXJlbnQgZHJhd1xuICBpZignb3BhY2l0eScgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5vcGFjaXR5ID0gcGFyYW1zLm9wYWNpdHlcbiAgICBpZih0aGlzLm9wYWNpdHkgPCAxKSB7XG4gICAgICB0aGlzLmhhc0FscGhhID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgaWYoJ29wYWNpdHlzY2FsZScgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5vcGFjaXR5c2NhbGUgPSBwYXJhbXMub3BhY2l0eXNjYWxlXG4gICAgdGhpcy5oYXNBbHBoYSA9IHRydWU7XG4gIH1cblxuICBpZignYW1iaWVudCcgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5hbWJpZW50TGlnaHQgID0gcGFyYW1zLmFtYmllbnRcbiAgfVxuICBpZignZGlmZnVzZScgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5kaWZmdXNlTGlnaHQgPSBwYXJhbXMuZGlmZnVzZVxuICB9XG4gIGlmKCdzcGVjdWxhcicgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5zcGVjdWxhckxpZ2h0ID0gcGFyYW1zLnNwZWN1bGFyXG4gIH1cbiAgaWYoJ3JvdWdobmVzcycgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5yb3VnaG5lc3MgPSBwYXJhbXMucm91Z2huZXNzXG4gIH1cbiAgaWYoJ2ZyZXNuZWwnIGluIHBhcmFtcykge1xuICAgIHRoaXMuZnJlc25lbCA9IHBhcmFtcy5mcmVzbmVsXG4gIH1cblxuICBpZihwYXJhbXMudGV4dHVyZSkge1xuICAgIHRoaXMudGV4dHVyZS5kaXNwb3NlKClcbiAgICB0aGlzLnRleHR1cmUgPSBjcmVhdGVUZXh0dXJlKGdsLCBwYXJhbXMudGV4dHVyZSlcbiAgfSBlbHNlIGlmIChwYXJhbXMuY29sb3JtYXApIHtcbiAgICB0aGlzLnRleHR1cmUuc2hhcGUgPSBbMjU2LDI1Nl1cbiAgICB0aGlzLnRleHR1cmUubWluRmlsdGVyID0gZ2wuTElORUFSX01JUE1BUF9MSU5FQVJcbiAgICB0aGlzLnRleHR1cmUubWFnRmlsdGVyID0gZ2wuTElORUFSXG4gICAgdGhpcy50ZXh0dXJlLnNldFBpeGVscyhnZW5Db2xvcm1hcChwYXJhbXMuY29sb3JtYXAsIHRoaXMub3BhY2l0eXNjYWxlKSlcbiAgICB0aGlzLnRleHR1cmUuZ2VuZXJhdGVNaXBtYXAoKVxuICB9XG5cbiAgdmFyIGNlbGxzID0gcGFyYW1zLmNlbGxzXG4gIHZhciBwb3NpdGlvbnMgPSBwYXJhbXMucG9zaXRpb25zXG5cbiAgaWYoIXBvc2l0aW9ucyB8fCAhY2VsbHMpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHZhciB0UG9zID0gW11cbiAgdmFyIHRDb2wgPSBbXVxuICB2YXIgdE5vciA9IFtdXG4gIHZhciB0VVZzID0gW11cbiAgdmFyIHRJZHMgPSBbXVxuXG4gIHZhciBlUG9zID0gW11cbiAgdmFyIGVDb2wgPSBbXVxuICB2YXIgZVVWcyA9IFtdXG4gIHZhciBlSWRzID0gW11cblxuICB2YXIgcFBvcyA9IFtdXG4gIHZhciBwQ29sID0gW11cbiAgdmFyIHBVVnMgPSBbXVxuICB2YXIgcFNpeiA9IFtdXG4gIHZhciBwSWRzID0gW11cblxuICAvL1NhdmUgZ2VvbWV0cnkgZGF0YSBmb3IgcGlja2luZyBjYWxjdWxhdGlvbnNcbiAgdGhpcy5jZWxscyAgICAgPSBjZWxsc1xuICB0aGlzLnBvc2l0aW9ucyA9IHBvc2l0aW9uc1xuXG4gIC8vQ29tcHV0ZSBub3JtYWxzXG4gIHZhciB2ZXJ0ZXhOb3JtYWxzID0gcGFyYW1zLnZlcnRleE5vcm1hbHNcbiAgdmFyIGNlbGxOb3JtYWxzICAgPSBwYXJhbXMuY2VsbE5vcm1hbHNcbiAgdmFyIHZlcnRleE5vcm1hbHNFcHNpbG9uID0gcGFyYW1zLnZlcnRleE5vcm1hbHNFcHNpbG9uID09PSB2b2lkKDApID8gREVGQVVMVF9WRVJURVhfTk9STUFMU19FUFNJTE9OIDogcGFyYW1zLnZlcnRleE5vcm1hbHNFcHNpbG9uXG4gIHZhciBmYWNlTm9ybWFsc0Vwc2lsb24gPSBwYXJhbXMuZmFjZU5vcm1hbHNFcHNpbG9uID09PSB2b2lkKDApID8gREVGQVVMVF9GQUNFX05PUk1BTFNfRVBTSUxPTiA6IHBhcmFtcy5mYWNlTm9ybWFsc0Vwc2lsb25cbiAgaWYocGFyYW1zLnVzZUZhY2V0Tm9ybWFscyAmJiAhY2VsbE5vcm1hbHMpIHtcbiAgICBjZWxsTm9ybWFscyA9IG5vcm1hbHMuZmFjZU5vcm1hbHMoY2VsbHMsIHBvc2l0aW9ucywgZmFjZU5vcm1hbHNFcHNpbG9uKVxuICB9XG4gIGlmKCFjZWxsTm9ybWFscyAmJiAhdmVydGV4Tm9ybWFscykge1xuICAgIHZlcnRleE5vcm1hbHMgPSBub3JtYWxzLnZlcnRleE5vcm1hbHMoY2VsbHMsIHBvc2l0aW9ucywgdmVydGV4Tm9ybWFsc0Vwc2lsb24pXG4gIH1cblxuICAvL0NvbXB1dGUgY29sb3JzXG4gIHZhciB2ZXJ0ZXhDb2xvcnMgICAgPSBwYXJhbXMudmVydGV4Q29sb3JzXG4gIHZhciBjZWxsQ29sb3JzICAgICAgPSBwYXJhbXMuY2VsbENvbG9yc1xuICB2YXIgbWVzaENvbG9yICAgICAgID0gcGFyYW1zLm1lc2hDb2xvciB8fCBbMSwxLDEsMV1cblxuICAvL1VWc1xuICB2YXIgdmVydGV4VVZzICAgICAgID0gcGFyYW1zLnZlcnRleFVWc1xuICB2YXIgdmVydGV4SW50ZW5zaXR5ID0gcGFyYW1zLnZlcnRleEludGVuc2l0eVxuICB2YXIgY2VsbFVWcyAgICAgICAgID0gcGFyYW1zLmNlbGxVVnNcbiAgdmFyIGNlbGxJbnRlbnNpdHkgICA9IHBhcmFtcy5jZWxsSW50ZW5zaXR5XG5cbiAgdmFyIGludGVuc2l0eUxvICAgICA9IEluZmluaXR5XG4gIHZhciBpbnRlbnNpdHlIaSAgICAgPSAtSW5maW5pdHlcbiAgaWYoIXZlcnRleFVWcyAmJiAhY2VsbFVWcykge1xuICAgIGlmKHZlcnRleEludGVuc2l0eSkge1xuICAgICAgaWYocGFyYW1zLnZlcnRleEludGVuc2l0eUJvdW5kcykge1xuICAgICAgICBpbnRlbnNpdHlMbyA9ICtwYXJhbXMudmVydGV4SW50ZW5zaXR5Qm91bmRzWzBdXG4gICAgICAgIGludGVuc2l0eUhpID0gK3BhcmFtcy52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHNbMV1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvcih2YXIgaT0wOyBpPHZlcnRleEludGVuc2l0eS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIHZhciBmID0gdmVydGV4SW50ZW5zaXR5W2ldXG4gICAgICAgICAgaW50ZW5zaXR5TG8gPSBNYXRoLm1pbihpbnRlbnNpdHlMbywgZilcbiAgICAgICAgICBpbnRlbnNpdHlIaSA9IE1hdGgubWF4KGludGVuc2l0eUhpLCBmKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcbiAgICAgIGZvcih2YXIgaT0wOyBpPGNlbGxJbnRlbnNpdHkubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGYgPSBjZWxsSW50ZW5zaXR5W2ldXG4gICAgICAgIGludGVuc2l0eUxvID0gTWF0aC5taW4oaW50ZW5zaXR5TG8sIGYpXG4gICAgICAgIGludGVuc2l0eUhpID0gTWF0aC5tYXgoaW50ZW5zaXR5SGksIGYpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvcih2YXIgaT0wOyBpPHBvc2l0aW9ucy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgZiA9IHBvc2l0aW9uc1tpXVsyXVxuICAgICAgICBpbnRlbnNpdHlMbyA9IE1hdGgubWluKGludGVuc2l0eUxvLCBmKVxuICAgICAgICBpbnRlbnNpdHlIaSA9IE1hdGgubWF4KGludGVuc2l0eUhpLCBmKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmKHZlcnRleEludGVuc2l0eSkge1xuICAgIHRoaXMuaW50ZW5zaXR5ID0gdmVydGV4SW50ZW5zaXR5XG4gIH0gZWxzZSBpZihjZWxsSW50ZW5zaXR5KSB7XG4gICAgdGhpcy5pbnRlbnNpdHkgPSB1bnBhY2tJbnRlbnNpdHkoY2VsbHMsIHBvc2l0aW9ucy5sZW5ndGgsIGNlbGxJbnRlbnNpdHkpXG4gIH0gZWxzZSB7XG4gICAgdGhpcy5pbnRlbnNpdHkgPSB0YWtlWkNvbXBvbmVudChwb3NpdGlvbnMpXG4gIH1cblxuICAvL1BvaW50IHNpemVcbiAgdmFyIHBvaW50U2l6ZXMgICAgICA9IHBhcmFtcy5wb2ludFNpemVzXG4gIHZhciBtZXNoUG9pbnRTaXplICAgPSBwYXJhbXMucG9pbnRTaXplIHx8IDEuMFxuXG4gIC8vVXBkYXRlIGJvdW5kc1xuICB0aGlzLmJvdW5kcyAgICAgICA9IFtbSW5maW5pdHksSW5maW5pdHksSW5maW5pdHldLCBbLUluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldXVxuICBmb3IodmFyIGk9MDsgaTxwb3NpdGlvbnMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcCA9IHBvc2l0aW9uc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgaWYoaXNOYU4ocFtqXSkgfHwgIWlzRmluaXRlKHBbal0pKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICB0aGlzLmJvdW5kc1swXVtqXSA9IE1hdGgubWluKHRoaXMuYm91bmRzWzBdW2pdLCBwW2pdKVxuICAgICAgdGhpcy5ib3VuZHNbMV1bal0gPSBNYXRoLm1heCh0aGlzLmJvdW5kc1sxXVtqXSwgcFtqXSlcbiAgICB9XG4gIH1cblxuICAvL1BhY2sgY2VsbHMgaW50byBidWZmZXJzXG4gIHZhciB0cmlhbmdsZUNvdW50ID0gMFxuICB2YXIgZWRnZUNvdW50ID0gMFxuICB2YXIgcG9pbnRDb3VudCA9IDBcblxuZmlsbF9sb29wOlxuICBmb3IodmFyIGk9MDsgaTxjZWxscy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBjZWxsID0gY2VsbHNbaV1cbiAgICBzd2l0Y2goY2VsbC5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMTpcblxuICAgICAgICB2YXIgdiA9IGNlbGxbMF1cbiAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cblxuICAgICAgICAvL0NoZWNrIE5hTnNcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICAgICAgaWYoaXNOYU4ocFtqXSkgfHwgIWlzRmluaXRlKHBbal0pKSB7XG4gICAgICAgICAgICBjb250aW51ZSBmaWxsX2xvb3BcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBwUG9zLnB1c2gocFswXSwgcFsxXSwgcFsyXSlcblxuICAgICAgICB2YXIgY1xuICAgICAgICBpZih2ZXJ0ZXhDb2xvcnMpIHtcbiAgICAgICAgICBjID0gdmVydGV4Q29sb3JzW3ZdXG4gICAgICAgIH0gZWxzZSBpZihjZWxsQ29sb3JzKSB7XG4gICAgICAgICAgYyA9IGNlbGxDb2xvcnNbaV1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjID0gbWVzaENvbG9yXG4gICAgICAgIH1cbiAgICAgICAgaWYodGhpcy5vcGFjaXR5c2NhbGUgJiYgdmVydGV4SW50ZW5zaXR5KSB7XG4gICAgICAgICAgdENvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sXG4gICAgICAgICAgICB0aGlzLm9wYWNpdHkgKiBnZXRPcGFjaXR5RnJvbVNjYWxlKFxuICAgICAgICAgICAgICAodmVydGV4SW50ZW5zaXR5W3ZdIC0gaW50ZW5zaXR5TG8pIC8gKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLFxuICAgICAgICAgICAgICB0aGlzLm9wYWNpdHlzY2FsZVxuICAgICAgICAgICAgKVxuICAgICAgICAgIClcbiAgICAgICAgfSBlbHNlIGlmKGMubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgcENvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sIHRoaXMub3BhY2l0eSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwQ29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgY1szXSAqIHRoaXMub3BhY2l0eSlcbiAgICAgICAgICBpZighdGhpcy5oYXNBbHBoYSAmJiBjWzNdIDwgMSkgdGhpcy5oYXNBbHBoYSA9IHRydWVcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB1dlxuICAgICAgICBpZih2ZXJ0ZXhVVnMpIHtcbiAgICAgICAgICB1diA9IHZlcnRleFVWc1t2XVxuICAgICAgICB9IGVsc2UgaWYodmVydGV4SW50ZW5zaXR5KSB7XG4gICAgICAgICAgdXYgPSBbXG4gICAgICAgICAgICAodmVydGV4SW50ZW5zaXR5W3ZdIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgfSBlbHNlIGlmKGNlbGxVVnMpIHtcbiAgICAgICAgICB1diA9IGNlbGxVVnNbaV1cbiAgICAgICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcbiAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgIChjZWxsSW50ZW5zaXR5W2ldIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgIChwWzJdIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgfVxuICAgICAgICBwVVZzLnB1c2godXZbMF0sIHV2WzFdKVxuXG4gICAgICAgIGlmKHBvaW50U2l6ZXMpIHtcbiAgICAgICAgICBwU2l6LnB1c2gocG9pbnRTaXplc1t2XSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwU2l6LnB1c2gobWVzaFBvaW50U2l6ZSlcbiAgICAgICAgfVxuXG4gICAgICAgIHBJZHMucHVzaChpKVxuXG4gICAgICAgIHBvaW50Q291bnQgKz0gMVxuICAgICAgYnJlYWtcblxuICAgICAgY2FzZSAyOlxuXG4gICAgICAgIC8vQ2hlY2sgTmFOc1xuICAgICAgICBmb3IodmFyIGo9MDsgajwyOyArK2opIHtcbiAgICAgICAgICB2YXIgdiA9IGNlbGxbal1cbiAgICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxuICAgICAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xuICAgICAgICAgICAgaWYoaXNOYU4ocFtrXSkgfHwgIWlzRmluaXRlKHBba10pKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIGZpbGxfbG9vcFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xuICAgICAgICAgIHZhciB2ID0gY2VsbFtqXVxuICAgICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXG5cbiAgICAgICAgICBlUG9zLnB1c2gocFswXSwgcFsxXSwgcFsyXSlcblxuICAgICAgICAgIHZhciBjXG4gICAgICAgICAgaWYodmVydGV4Q29sb3JzKSB7XG4gICAgICAgICAgICBjID0gdmVydGV4Q29sb3JzW3ZdXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxDb2xvcnMpIHtcbiAgICAgICAgICAgIGMgPSBjZWxsQ29sb3JzW2ldXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGMgPSBtZXNoQ29sb3JcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYodGhpcy5vcGFjaXR5c2NhbGUgJiYgdmVydGV4SW50ZW5zaXR5KSB7XG4gICAgICAgICAgICB0Q29sLnB1c2goY1swXSwgY1sxXSwgY1syXSxcbiAgICAgICAgICAgICAgdGhpcy5vcGFjaXR5ICogZ2V0T3BhY2l0eUZyb21TY2FsZShcbiAgICAgICAgICAgICAgICAodmVydGV4SW50ZW5zaXR5W3ZdIC0gaW50ZW5zaXR5TG8pIC8gKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLFxuICAgICAgICAgICAgICAgIHRoaXMub3BhY2l0eXNjYWxlXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgICB9IGVsc2UgaWYoYy5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICAgIGVDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCB0aGlzLm9wYWNpdHkpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCBjWzNdICogdGhpcy5vcGFjaXR5KVxuICAgICAgICAgICAgaWYoIXRoaXMuaGFzQWxwaGEgJiYgY1szXSA8IDEpIHRoaXMuaGFzQWxwaGEgPSB0cnVlXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHV2XG4gICAgICAgICAgaWYodmVydGV4VVZzKSB7XG4gICAgICAgICAgICB1diA9IHZlcnRleFVWc1t2XVxuICAgICAgICAgIH0gZWxzZSBpZih2ZXJ0ZXhJbnRlbnNpdHkpIHtcbiAgICAgICAgICAgIHV2ID0gW1xuICAgICAgICAgICAgICAodmVydGV4SW50ZW5zaXR5W3ZdIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsVVZzKSB7XG4gICAgICAgICAgICB1diA9IGNlbGxVVnNbaV1cbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbEludGVuc2l0eSkge1xuICAgICAgICAgICAgdXYgPSBbXG4gICAgICAgICAgICAgIChjZWxsSW50ZW5zaXR5W2ldIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgICAgKHBbMl0gLSBpbnRlbnNpdHlMbykgL1xuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXG4gICAgICAgICAgfVxuICAgICAgICAgIGVVVnMucHVzaCh1dlswXSwgdXZbMV0pXG5cbiAgICAgICAgICBlSWRzLnB1c2goaSlcbiAgICAgICAgfVxuICAgICAgICBlZGdlQ291bnQgKz0gMVxuICAgICAgYnJlYWtcblxuICAgICAgY2FzZSAzOlxuICAgICAgICAvL0NoZWNrIE5hTnNcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICAgICAgdmFyIHYgPSBjZWxsW2pdXG4gICAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cbiAgICAgICAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgICAgICAgIGlmKGlzTmFOKHBba10pIHx8ICFpc0Zpbml0ZShwW2tdKSkge1xuICAgICAgICAgICAgICBjb250aW51ZSBmaWxsX2xvb3BcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgICB2YXIgdiA9IGNlbGxbMiAtIGpdXG5cbiAgICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxuICAgICAgICAgIHRQb3MucHVzaChwWzBdLCBwWzFdLCBwWzJdKVxuXG4gICAgICAgICAgdmFyIGNcbiAgICAgICAgICBpZih2ZXJ0ZXhDb2xvcnMpIHtcbiAgICAgICAgICAgIGMgPSB2ZXJ0ZXhDb2xvcnNbdl1cbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbENvbG9ycykge1xuICAgICAgICAgICAgYyA9IGNlbGxDb2xvcnNbaV1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYyA9IG1lc2hDb2xvclxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmKHRoaXMub3BhY2l0eXNjYWxlICYmIHZlcnRleEludGVuc2l0eSkge1xuICAgICAgICAgICAgdENvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sXG4gICAgICAgICAgICAgIHRoaXMub3BhY2l0eSAqIGdldE9wYWNpdHlGcm9tU2NhbGUoXG4gICAgICAgICAgICAgICAgKHZlcnRleEludGVuc2l0eVt2XSAtIGludGVuc2l0eUxvKSAvIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSxcbiAgICAgICAgICAgICAgICB0aGlzLm9wYWNpdHlzY2FsZVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICAgfSBlbHNlIGlmKGMubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgICB0Q29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgdGhpcy5vcGFjaXR5KVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0Q29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgY1szXSAqIHRoaXMub3BhY2l0eSlcbiAgICAgICAgICAgIGlmKCF0aGlzLmhhc0FscGhhICYmIGNbM10gPCAxKSB0aGlzLmhhc0FscGhhID0gdHJ1ZVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciB1dlxuICAgICAgICAgIGlmKHZlcnRleFVWcykge1xuICAgICAgICAgICAgdXYgPSB2ZXJ0ZXhVVnNbdl1cbiAgICAgICAgICB9IGVsc2UgaWYodmVydGV4SW50ZW5zaXR5KSB7XG4gICAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgICAgKHZlcnRleEludGVuc2l0eVt2XSAtIGludGVuc2l0eUxvKSAvXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbFVWcykge1xuICAgICAgICAgICAgdXYgPSBjZWxsVVZzW2ldXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcbiAgICAgICAgICAgIHV2ID0gW1xuICAgICAgICAgICAgICAoY2VsbEludGVuc2l0eVtpXSAtIGludGVuc2l0eUxvKSAvXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdXYgPSBbXG4gICAgICAgICAgICAgIChwWzJdIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxuICAgICAgICAgIH1cbiAgICAgICAgICB0VVZzLnB1c2godXZbMF0sIHV2WzFdKVxuXG4gICAgICAgICAgdmFyIHFcbiAgICAgICAgICBpZih2ZXJ0ZXhOb3JtYWxzKSB7XG4gICAgICAgICAgICBxID0gdmVydGV4Tm9ybWFsc1t2XVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBxID0gY2VsbE5vcm1hbHNbaV1cbiAgICAgICAgICB9XG4gICAgICAgICAgdE5vci5wdXNoKHFbMF0sIHFbMV0sIHFbMl0pXG5cbiAgICAgICAgICB0SWRzLnB1c2goaSlcbiAgICAgICAgfVxuICAgICAgICB0cmlhbmdsZUNvdW50ICs9IDFcbiAgICAgIGJyZWFrXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIHRoaXMucG9pbnRDb3VudCAgICAgPSBwb2ludENvdW50XG4gIHRoaXMuZWRnZUNvdW50ICAgICAgPSBlZGdlQ291bnRcbiAgdGhpcy50cmlhbmdsZUNvdW50ICA9IHRyaWFuZ2xlQ291bnRcblxuICB0aGlzLnBvaW50UG9zaXRpb25zLnVwZGF0ZShwUG9zKVxuICB0aGlzLnBvaW50Q29sb3JzLnVwZGF0ZShwQ29sKVxuICB0aGlzLnBvaW50VVZzLnVwZGF0ZShwVVZzKVxuICB0aGlzLnBvaW50U2l6ZXMudXBkYXRlKHBTaXopXG4gIHRoaXMucG9pbnRJZHMudXBkYXRlKG5ldyBVaW50MzJBcnJheShwSWRzKSlcblxuICB0aGlzLmVkZ2VQb3NpdGlvbnMudXBkYXRlKGVQb3MpXG4gIHRoaXMuZWRnZUNvbG9ycy51cGRhdGUoZUNvbClcbiAgdGhpcy5lZGdlVVZzLnVwZGF0ZShlVVZzKVxuICB0aGlzLmVkZ2VJZHMudXBkYXRlKG5ldyBVaW50MzJBcnJheShlSWRzKSlcblxuICB0aGlzLnRyaWFuZ2xlUG9zaXRpb25zLnVwZGF0ZSh0UG9zKVxuICB0aGlzLnRyaWFuZ2xlQ29sb3JzLnVwZGF0ZSh0Q29sKVxuICB0aGlzLnRyaWFuZ2xlVVZzLnVwZGF0ZSh0VVZzKVxuICB0aGlzLnRyaWFuZ2xlTm9ybWFscy51cGRhdGUodE5vcilcbiAgdGhpcy50cmlhbmdsZUlkcy51cGRhdGUobmV3IFVpbnQzMkFycmF5KHRJZHMpKVxufVxuXG5wcm90by5kcmF3VHJhbnNwYXJlbnQgPSBwcm90by5kcmF3ID0gZnVuY3Rpb24ocGFyYW1zKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fVxuICB2YXIgZ2wgICAgICAgICAgPSB0aGlzLmdsXG4gIHZhciBtb2RlbCAgICAgICA9IHBhcmFtcy5tb2RlbCAgICAgIHx8IElERU5USVRZXG4gIHZhciB2aWV3ICAgICAgICA9IHBhcmFtcy52aWV3ICAgICAgIHx8IElERU5USVRZXG4gIHZhciBwcm9qZWN0aW9uICA9IHBhcmFtcy5wcm9qZWN0aW9uIHx8IElERU5USVRZXG5cbiAgdmFyIGNsaXBCb3VuZHMgPSBbWy0xZTYsLTFlNiwtMWU2XSxbMWU2LDFlNiwxZTZdXVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICBjbGlwQm91bmRzWzBdW2ldID0gTWF0aC5tYXgoY2xpcEJvdW5kc1swXVtpXSwgdGhpcy5jbGlwQm91bmRzWzBdW2ldKVxuICAgIGNsaXBCb3VuZHNbMV1baV0gPSBNYXRoLm1pbihjbGlwQm91bmRzWzFdW2ldLCB0aGlzLmNsaXBCb3VuZHNbMV1baV0pXG4gIH1cblxuICB2YXIgdW5pZm9ybXMgPSB7XG4gICAgbW9kZWw6ICAgICAgbW9kZWwsXG4gICAgdmlldzogICAgICAgdmlldyxcbiAgICBwcm9qZWN0aW9uOiBwcm9qZWN0aW9uLFxuICAgIGludmVyc2VNb2RlbDogSURFTlRJVFkuc2xpY2UoKSxcblxuICAgIGNsaXBCb3VuZHM6IGNsaXBCb3VuZHMsXG5cbiAgICBrYW1iaWVudDogICB0aGlzLmFtYmllbnRMaWdodCxcbiAgICBrZGlmZnVzZTogICB0aGlzLmRpZmZ1c2VMaWdodCxcbiAgICBrc3BlY3VsYXI6ICB0aGlzLnNwZWN1bGFyTGlnaHQsXG4gICAgcm91Z2huZXNzOiAgdGhpcy5yb3VnaG5lc3MsXG4gICAgZnJlc25lbDogICAgdGhpcy5mcmVzbmVsLFxuXG4gICAgZXllUG9zaXRpb246ICAgWzAsMCwwXSxcbiAgICBsaWdodFBvc2l0aW9uOiBbMCwwLDBdLFxuXG4gICAgY29udG91ckNvbG9yOiB0aGlzLmNvbnRvdXJDb2xvcixcblxuICAgIHRleHR1cmU6ICAgIDBcbiAgfVxuXG4gIHVuaWZvcm1zLmludmVyc2VNb2RlbCA9IGludmVydCh1bmlmb3Jtcy5pbnZlcnNlTW9kZWwsIHVuaWZvcm1zLm1vZGVsKVxuXG4gIGdsLmRpc2FibGUoZ2wuQ1VMTF9GQUNFKVxuXG4gIHRoaXMudGV4dHVyZS5iaW5kKDApXG5cbiAgdmFyIGludkNhbWVyYU1hdHJpeCA9IG5ldyBBcnJheSgxNilcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy52aWV3LCB1bmlmb3Jtcy5tb2RlbClcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy5wcm9qZWN0aW9uLCBpbnZDYW1lcmFNYXRyaXgpXG4gIGludmVydChpbnZDYW1lcmFNYXRyaXgsIGludkNhbWVyYU1hdHJpeClcblxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICB1bmlmb3Jtcy5leWVQb3NpdGlvbltpXSA9IGludkNhbWVyYU1hdHJpeFsxMitpXSAvIGludkNhbWVyYU1hdHJpeFsxNV1cbiAgfVxuXG4gIHZhciB3ID0gaW52Q2FtZXJhTWF0cml4WzE1XVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICB3ICs9IHRoaXMubGlnaHRQb3NpdGlvbltpXSAqIGludkNhbWVyYU1hdHJpeFs0KmkrM11cbiAgfVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICB2YXIgcyA9IGludkNhbWVyYU1hdHJpeFsxMitpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgcyArPSBpbnZDYW1lcmFNYXRyaXhbNCpqK2ldICogdGhpcy5saWdodFBvc2l0aW9uW2pdXG4gICAgfVxuICAgIHVuaWZvcm1zLmxpZ2h0UG9zaXRpb25baV0gPSBzIC8gd1xuICB9XG5cbiAgaWYodGhpcy50cmlhbmdsZUNvdW50ID4gMCkge1xuICAgIHZhciBzaGFkZXIgPSB0aGlzLnRyaVNoYWRlclxuICAgIHNoYWRlci5iaW5kKClcbiAgICBzaGFkZXIudW5pZm9ybXMgPSB1bmlmb3Jtc1xuXG4gICAgdGhpcy50cmlhbmdsZVZBTy5iaW5kKClcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlRSSUFOR0xFUywgMCwgdGhpcy50cmlhbmdsZUNvdW50KjMpXG4gICAgdGhpcy50cmlhbmdsZVZBTy51bmJpbmQoKVxuICB9XG5cbiAgaWYodGhpcy5lZGdlQ291bnQgPiAwICYmIHRoaXMubGluZVdpZHRoID4gMCkge1xuICAgIHZhciBzaGFkZXIgPSB0aGlzLmxpbmVTaGFkZXJcbiAgICBzaGFkZXIuYmluZCgpXG4gICAgc2hhZGVyLnVuaWZvcm1zID0gdW5pZm9ybXNcblxuICAgIHRoaXMuZWRnZVZBTy5iaW5kKClcbiAgICBnbC5saW5lV2lkdGgodGhpcy5saW5lV2lkdGggKiB0aGlzLnBpeGVsUmF0aW8pXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5MSU5FUywgMCwgdGhpcy5lZGdlQ291bnQqMilcbiAgICB0aGlzLmVkZ2VWQU8udW5iaW5kKClcbiAgfVxuXG4gIGlmKHRoaXMucG9pbnRDb3VudCA+IDApIHtcbiAgICB2YXIgc2hhZGVyID0gdGhpcy5wb2ludFNoYWRlclxuICAgIHNoYWRlci5iaW5kKClcbiAgICBzaGFkZXIudW5pZm9ybXMgPSB1bmlmb3Jtc1xuXG4gICAgdGhpcy5wb2ludFZBTy5iaW5kKClcbiAgICBnbC5kcmF3QXJyYXlzKGdsLlBPSU5UUywgMCwgdGhpcy5wb2ludENvdW50KVxuICAgIHRoaXMucG9pbnRWQU8udW5iaW5kKClcbiAgfVxuXG4gIGlmKHRoaXMuY29udG91ckVuYWJsZSAmJiB0aGlzLmNvbnRvdXJDb3VudCA+IDAgJiYgdGhpcy5jb250b3VyTGluZVdpZHRoID4gMCkge1xuICAgIHZhciBzaGFkZXIgPSB0aGlzLmNvbnRvdXJTaGFkZXJcbiAgICBzaGFkZXIuYmluZCgpXG4gICAgc2hhZGVyLnVuaWZvcm1zID0gdW5pZm9ybXNcblxuICAgIHRoaXMuY29udG91clZBTy5iaW5kKClcbiAgICBnbC5kcmF3QXJyYXlzKGdsLkxJTkVTLCAwLCB0aGlzLmNvbnRvdXJDb3VudClcbiAgICB0aGlzLmNvbnRvdXJWQU8udW5iaW5kKClcbiAgfVxufVxuXG5wcm90by5kcmF3UGljayA9IGZ1bmN0aW9uKHBhcmFtcykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge31cblxuICB2YXIgZ2wgICAgICAgICA9IHRoaXMuZ2xcblxuICB2YXIgbW9kZWwgICAgICA9IHBhcmFtcy5tb2RlbCAgICAgIHx8IElERU5USVRZXG4gIHZhciB2aWV3ICAgICAgID0gcGFyYW1zLnZpZXcgICAgICAgfHwgSURFTlRJVFlcbiAgdmFyIHByb2plY3Rpb24gPSBwYXJhbXMucHJvamVjdGlvbiB8fCBJREVOVElUWVxuXG4gIHZhciBjbGlwQm91bmRzID0gW1stMWU2LC0xZTYsLTFlNl0sWzFlNiwxZTYsMWU2XV1cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgY2xpcEJvdW5kc1swXVtpXSA9IE1hdGgubWF4KGNsaXBCb3VuZHNbMF1baV0sIHRoaXMuY2xpcEJvdW5kc1swXVtpXSlcbiAgICBjbGlwQm91bmRzWzFdW2ldID0gTWF0aC5taW4oY2xpcEJvdW5kc1sxXVtpXSwgdGhpcy5jbGlwQm91bmRzWzFdW2ldKVxuICB9XG5cbiAgLy9TYXZlIGNhbWVyYSBwYXJhbWV0ZXJzXG4gIHRoaXMuX21vZGVsICAgICAgPSBbXS5zbGljZS5jYWxsKG1vZGVsKVxuICB0aGlzLl92aWV3ICAgICAgID0gW10uc2xpY2UuY2FsbCh2aWV3KVxuICB0aGlzLl9wcm9qZWN0aW9uID0gW10uc2xpY2UuY2FsbChwcm9qZWN0aW9uKVxuICB0aGlzLl9yZXNvbHV0aW9uID0gW2dsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF1cblxuICB2YXIgdW5pZm9ybXMgPSB7XG4gICAgbW9kZWw6ICAgICAgbW9kZWwsXG4gICAgdmlldzogICAgICAgdmlldyxcbiAgICBwcm9qZWN0aW9uOiBwcm9qZWN0aW9uLFxuICAgIGNsaXBCb3VuZHM6IGNsaXBCb3VuZHMsXG4gICAgcGlja0lkOiAgICAgdGhpcy5waWNrSWQgLyAyNTUuMCxcbiAgfVxuXG4gIHZhciBzaGFkZXIgPSB0aGlzLnBpY2tTaGFkZXJcbiAgc2hhZGVyLmJpbmQoKVxuICBzaGFkZXIudW5pZm9ybXMgPSB1bmlmb3Jtc1xuXG4gIGlmKHRoaXMudHJpYW5nbGVDb3VudCA+IDApIHtcbiAgICB0aGlzLnRyaWFuZ2xlVkFPLmJpbmQoKVxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCAwLCB0aGlzLnRyaWFuZ2xlQ291bnQqMylcbiAgICB0aGlzLnRyaWFuZ2xlVkFPLnVuYmluZCgpXG4gIH1cblxuICBpZih0aGlzLmVkZ2VDb3VudCA+IDApIHtcbiAgICB0aGlzLmVkZ2VWQU8uYmluZCgpXG4gICAgZ2wubGluZVdpZHRoKHRoaXMubGluZVdpZHRoICogdGhpcy5waXhlbFJhdGlvKVxuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIDAsIHRoaXMuZWRnZUNvdW50KjIpXG4gICAgdGhpcy5lZGdlVkFPLnVuYmluZCgpXG4gIH1cblxuICBpZih0aGlzLnBvaW50Q291bnQgPiAwKSB7XG4gICAgdmFyIHNoYWRlciA9IHRoaXMucG9pbnRQaWNrU2hhZGVyXG4gICAgc2hhZGVyLmJpbmQoKVxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXG5cbiAgICB0aGlzLnBvaW50VkFPLmJpbmQoKVxuICAgIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCAwLCB0aGlzLnBvaW50Q291bnQpXG4gICAgdGhpcy5wb2ludFZBTy51bmJpbmQoKVxuICB9XG59XG5cblxucHJvdG8ucGljayA9IGZ1bmN0aW9uKHBpY2tEYXRhKSB7XG4gIGlmKCFwaWNrRGF0YSkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgaWYocGlja0RhdGEuaWQgIT09IHRoaXMucGlja0lkKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHZhciBjZWxsSWQgICAgPSBwaWNrRGF0YS52YWx1ZVswXSArIDI1NipwaWNrRGF0YS52YWx1ZVsxXSArIDY1NTM2KnBpY2tEYXRhLnZhbHVlWzJdXG4gIHZhciBjZWxsICAgICAgPSB0aGlzLmNlbGxzW2NlbGxJZF1cbiAgdmFyIHBvc2l0aW9ucyA9IHRoaXMucG9zaXRpb25zXG5cbiAgdmFyIHNpbXBsZXggICA9IG5ldyBBcnJheShjZWxsLmxlbmd0aClcbiAgZm9yKHZhciBpPTA7IGk8Y2VsbC5sZW5ndGg7ICsraSkge1xuICAgIHNpbXBsZXhbaV0gPSBwb3NpdGlvbnNbY2VsbFtpXV1cbiAgfVxuXG4gIHZhciBkYXRhID0gY2xvc2VzdFBvaW50KFxuICAgIHNpbXBsZXgsXG4gICAgW3BpY2tEYXRhLmNvb3JkWzBdLCB0aGlzLl9yZXNvbHV0aW9uWzFdLXBpY2tEYXRhLmNvb3JkWzFdXSxcbiAgICB0aGlzLl9tb2RlbCxcbiAgICB0aGlzLl92aWV3LFxuICAgIHRoaXMuX3Byb2plY3Rpb24sXG4gICAgdGhpcy5fcmVzb2x1dGlvbilcblxuICBpZighZGF0YSkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICB2YXIgd2VpZ2h0cyA9IGRhdGFbMl1cbiAgdmFyIGludGVycEludGVuc2l0eSA9IDAuMFxuICBmb3IodmFyIGk9MDsgaTxjZWxsLmxlbmd0aDsgKytpKSB7XG4gICAgaW50ZXJwSW50ZW5zaXR5ICs9IHdlaWdodHNbaV0gKiB0aGlzLmludGVuc2l0eVtjZWxsW2ldXVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBwb3NpdGlvbjogZGF0YVsxXSxcbiAgICBpbmRleDogICAgY2VsbFtkYXRhWzBdXSxcbiAgICBjZWxsOiAgICAgY2VsbCxcbiAgICBjZWxsSWQ6ICAgY2VsbElkLFxuICAgIGludGVuc2l0eTogIGludGVycEludGVuc2l0eSxcbiAgICBkYXRhQ29vcmRpbmF0ZTogdGhpcy5wb3NpdGlvbnNbY2VsbFtkYXRhWzBdXV1cbiAgfVxufVxuXG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy50ZXh0dXJlLmRpc3Bvc2UoKVxuXG4gIHRoaXMudHJpU2hhZGVyLmRpc3Bvc2UoKVxuICB0aGlzLmxpbmVTaGFkZXIuZGlzcG9zZSgpXG4gIHRoaXMucG9pbnRTaGFkZXIuZGlzcG9zZSgpXG4gIHRoaXMucGlja1NoYWRlci5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFBpY2tTaGFkZXIuZGlzcG9zZSgpXG5cbiAgdGhpcy50cmlhbmdsZVZBTy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZVBvc2l0aW9ucy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZUNvbG9ycy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZVVWcy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZU5vcm1hbHMuZGlzcG9zZSgpXG4gIHRoaXMudHJpYW5nbGVJZHMuZGlzcG9zZSgpXG5cbiAgdGhpcy5lZGdlVkFPLmRpc3Bvc2UoKVxuICB0aGlzLmVkZ2VQb3NpdGlvbnMuZGlzcG9zZSgpXG4gIHRoaXMuZWRnZUNvbG9ycy5kaXNwb3NlKClcbiAgdGhpcy5lZGdlVVZzLmRpc3Bvc2UoKVxuICB0aGlzLmVkZ2VJZHMuZGlzcG9zZSgpXG5cbiAgdGhpcy5wb2ludFZBTy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFBvc2l0aW9ucy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludENvbG9ycy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFVWcy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFNpemVzLmRpc3Bvc2UoKVxuICB0aGlzLnBvaW50SWRzLmRpc3Bvc2UoKVxuXG4gIHRoaXMuY29udG91clZBTy5kaXNwb3NlKClcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zLmRpc3Bvc2UoKVxuICB0aGlzLmNvbnRvdXJTaGFkZXIuZGlzcG9zZSgpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZU1lc2hTaGFkZXIoZ2wpIHtcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgbWVzaFNoYWRlci52ZXJ0ZXgsIG1lc2hTaGFkZXIuZnJhZ21lbnQpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiAgICA9IDJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMudXYubG9jYXRpb24gICAgICAgPSAzXG4gIHNoYWRlci5hdHRyaWJ1dGVzLm5vcm1hbC5sb2NhdGlvbiAgID0gNFxuICByZXR1cm4gc2hhZGVyXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVdpcmVTaGFkZXIoZ2wpIHtcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgd2lyZVNoYWRlci52ZXJ0ZXgsIHdpcmVTaGFkZXIuZnJhZ21lbnQpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiAgICA9IDJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMudXYubG9jYXRpb24gICAgICAgPSAzXG4gIHJldHVybiBzaGFkZXJcbn1cblxuZnVuY3Rpb24gY3JlYXRlUG9pbnRTaGFkZXIoZ2wpIHtcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgcG9pbnRTaGFkZXIudmVydGV4LCBwb2ludFNoYWRlci5mcmFnbWVudClcbiAgc2hhZGVyLmF0dHJpYnV0ZXMucG9zaXRpb24ubG9jYXRpb24gID0gMFxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiAgICAgPSAyXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnV2LmxvY2F0aW9uICAgICAgICA9IDNcbiAgc2hhZGVyLmF0dHJpYnV0ZXMucG9pbnRTaXplLmxvY2F0aW9uID0gNFxuICByZXR1cm4gc2hhZGVyXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVBpY2tTaGFkZXIoZ2wpIHtcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgcGlja1NoYWRlci52ZXJ0ZXgsIHBpY2tTaGFkZXIuZnJhZ21lbnQpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICBzaGFkZXIuYXR0cmlidXRlcy5pZC5sb2NhdGlvbiAgICAgICA9IDFcbiAgcmV0dXJuIHNoYWRlclxufVxuXG5mdW5jdGlvbiBjcmVhdGVQb2ludFBpY2tTaGFkZXIoZ2wpIHtcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgcG9pbnRQaWNrU2hhZGVyLnZlcnRleCwgcG9pbnRQaWNrU2hhZGVyLmZyYWdtZW50KVxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiAgPSAwXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmlkLmxvY2F0aW9uICAgICAgICA9IDFcbiAgc2hhZGVyLmF0dHJpYnV0ZXMucG9pbnRTaXplLmxvY2F0aW9uID0gNFxuICByZXR1cm4gc2hhZGVyXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUNvbnRvdXJTaGFkZXIoZ2wpIHtcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgY29udG91clNoYWRlci52ZXJ0ZXgsIGNvbnRvdXJTaGFkZXIuZnJhZ21lbnQpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICByZXR1cm4gc2hhZGVyXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVNpbXBsaWNpYWxNZXNoKGdsLCBwYXJhbXMpIHtcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICBwYXJhbXMgPSBnbDtcbiAgICBnbCA9IHBhcmFtcy5nbDtcbiAgfVxuXG4gIC8vZW5hYmxlIGRlcml2YXRpdmVzIGZvciBmYWNlIG5vcm1hbHNcbiAgdmFyIGV4dCA9IGdsLmdldEV4dGVuc2lvbignT0VTX3N0YW5kYXJkX2Rlcml2YXRpdmVzJykgfHwgZ2wuZ2V0RXh0ZW5zaW9uKCdNT1pfT0VTX3N0YW5kYXJkX2Rlcml2YXRpdmVzJykgfHwgZ2wuZ2V0RXh0ZW5zaW9uKCdXRUJLSVRfT0VTX3N0YW5kYXJkX2Rlcml2YXRpdmVzJylcbiAgaWYgKCFleHQpXG4gICAgdGhyb3cgbmV3IEVycm9yKCdkZXJpdmF0aXZlcyBub3Qgc3VwcG9ydGVkJylcblxuICB2YXIgdHJpU2hhZGVyICAgICAgID0gY3JlYXRlTWVzaFNoYWRlcihnbClcbiAgdmFyIGxpbmVTaGFkZXIgICAgICA9IGNyZWF0ZVdpcmVTaGFkZXIoZ2wpXG4gIHZhciBwb2ludFNoYWRlciAgICAgPSBjcmVhdGVQb2ludFNoYWRlcihnbClcbiAgdmFyIHBpY2tTaGFkZXIgICAgICA9IGNyZWF0ZVBpY2tTaGFkZXIoZ2wpXG4gIHZhciBwb2ludFBpY2tTaGFkZXIgPSBjcmVhdGVQb2ludFBpY2tTaGFkZXIoZ2wpXG4gIHZhciBjb250b3VyU2hhZGVyICAgPSBjcmVhdGVDb250b3VyU2hhZGVyKGdsKVxuXG4gIHZhciBtZXNoVGV4dHVyZSAgICAgICA9IGNyZWF0ZVRleHR1cmUoZ2wsXG4gICAgbmRhcnJheShuZXcgVWludDhBcnJheShbMjU1LDI1NSwyNTUsMjU1XSksIFsxLDEsNF0pKVxuICBtZXNoVGV4dHVyZS5nZW5lcmF0ZU1pcG1hcCgpXG4gIG1lc2hUZXh0dXJlLm1pbkZpbHRlciA9IGdsLkxJTkVBUl9NSVBNQVBfTElORUFSXG4gIG1lc2hUZXh0dXJlLm1hZ0ZpbHRlciA9IGdsLkxJTkVBUlxuXG4gIHZhciB0cmlhbmdsZVBvc2l0aW9ucyA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHRyaWFuZ2xlQ29sb3JzICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgdHJpYW5nbGVVVnMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciB0cmlhbmdsZU5vcm1hbHMgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHRyaWFuZ2xlSWRzICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgdHJpYW5nbGVWQU8gICAgICAgPSBjcmVhdGVWQU8oZ2wsIFtcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVQb3NpdGlvbnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDNcbiAgICB9LFxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZUlkcyxcbiAgICAgIHR5cGU6IGdsLlVOU0lHTkVEX0JZVEUsXG4gICAgICBzaXplOiA0LFxuICAgICAgbm9ybWFsaXplZDogdHJ1ZVxuICAgIH0sXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlQ29sb3JzLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiA0XG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVVVnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDJcbiAgICB9LFxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZU5vcm1hbHMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDNcbiAgICB9XG4gIF0pXG5cbiAgdmFyIGVkZ2VQb3NpdGlvbnMgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBlZGdlQ29sb3JzICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgZWRnZVVWcyAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIGVkZ2VJZHMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBlZGdlVkFPICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXG4gICAgeyBidWZmZXI6IGVkZ2VQb3NpdGlvbnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDNcbiAgICB9LFxuICAgIHsgYnVmZmVyOiBlZGdlSWRzLFxuICAgICAgdHlwZTogZ2wuVU5TSUdORURfQllURSxcbiAgICAgIHNpemU6IDQsXG4gICAgICBub3JtYWxpemVkOiB0cnVlXG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogZWRnZUNvbG9ycyxcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxuICAgICAgc2l6ZTogNFxuICAgIH0sXG4gICAgeyBidWZmZXI6IGVkZ2VVVnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDJcbiAgICB9XG4gIF0pXG5cbiAgdmFyIHBvaW50UG9zaXRpb25zICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50Q29sb3JzICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50VVZzICAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50U2l6ZXMgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50SWRzICAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBvaW50VkFPICAgICAgICA9IGNyZWF0ZVZBTyhnbCwgW1xuICAgIHsgYnVmZmVyOiBwb2ludFBvc2l0aW9ucyxcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxuICAgICAgc2l6ZTogM1xuICAgIH0sXG4gICAgeyBidWZmZXI6IHBvaW50SWRzLFxuICAgICAgdHlwZTogZ2wuVU5TSUdORURfQllURSxcbiAgICAgIHNpemU6IDQsXG4gICAgICBub3JtYWxpemVkOiB0cnVlXG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogcG9pbnRDb2xvcnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDRcbiAgICB9LFxuICAgIHsgYnVmZmVyOiBwb2ludFVWcyxcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxuICAgICAgc2l6ZTogMlxuICAgIH0sXG4gICAgeyBidWZmZXI6IHBvaW50U2l6ZXMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDFcbiAgICB9XG4gIF0pXG5cbiAgdmFyIGNvbnRvdXJQb3NpdGlvbnMgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBjb250b3VyVkFPICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXG4gICAgeyBidWZmZXI6IGNvbnRvdXJQb3NpdGlvbnMsXG4gICAgICB0eXBlOiAgIGdsLkZMT0FULFxuICAgICAgc2l6ZTogICAzXG4gICAgfV0pXG5cbiAgdmFyIG1lc2ggPSBuZXcgU2ltcGxpY2lhbE1lc2goZ2xcbiAgICAsIG1lc2hUZXh0dXJlXG4gICAgLCB0cmlTaGFkZXJcbiAgICAsIGxpbmVTaGFkZXJcbiAgICAsIHBvaW50U2hhZGVyXG4gICAgLCBwaWNrU2hhZGVyXG4gICAgLCBwb2ludFBpY2tTaGFkZXJcbiAgICAsIGNvbnRvdXJTaGFkZXJcbiAgICAsIHRyaWFuZ2xlUG9zaXRpb25zXG4gICAgLCB0cmlhbmdsZUlkc1xuICAgICwgdHJpYW5nbGVDb2xvcnNcbiAgICAsIHRyaWFuZ2xlVVZzXG4gICAgLCB0cmlhbmdsZU5vcm1hbHNcbiAgICAsIHRyaWFuZ2xlVkFPXG4gICAgLCBlZGdlUG9zaXRpb25zXG4gICAgLCBlZGdlSWRzXG4gICAgLCBlZGdlQ29sb3JzXG4gICAgLCBlZGdlVVZzXG4gICAgLCBlZGdlVkFPXG4gICAgLCBwb2ludFBvc2l0aW9uc1xuICAgICwgcG9pbnRJZHNcbiAgICAsIHBvaW50Q29sb3JzXG4gICAgLCBwb2ludFVWc1xuICAgICwgcG9pbnRTaXplc1xuICAgICwgcG9pbnRWQU9cbiAgICAsIGNvbnRvdXJQb3NpdGlvbnNcbiAgICAsIGNvbnRvdXJWQU8pXG5cbiAgbWVzaC51cGRhdGUocGFyYW1zKVxuXG4gIHJldHVybiBtZXNoXG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU2ltcGxpY2lhbE1lc2hcblxufSx7XCIuL2xpYi9jbG9zZXN0LXBvaW50XCI6Mjc4LFwiLi9saWIvc2hhZGVyc1wiOjI3OSxcImNvbG9ybWFwXCI6MTI2LFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtbWF0NC9pbnZlcnRcIjoyNjUsXCJnbC1tYXQ0L211bHRpcGx5XCI6MjY3LFwiZ2wtc2hhZGVyXCI6MzAxLFwiZ2wtdGV4dHVyZTJkXCI6MzIyLFwiZ2wtdmFvXCI6MzI3LFwibmRhcnJheVwiOjQ1MCxcIm5vcm1hbHNcIjo0NTMsXCJzaW1wbGljaWFsLWNvbXBsZXgtY29udG91clwiOjUxOCxcInR5cGVkYXJyYXktcG9vbFwiOjU0NX1dLDI4MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCb3hlc1xuXG52YXIgY3JlYXRlQnVmZmVyID0gX2RlcmVxXygnZ2wtYnVmZmVyJylcbnZhciBjcmVhdGVTaGFkZXIgPSBfZGVyZXFfKCdnbC1zaGFkZXInKVxuXG52YXIgc2hhZGVycyA9IF9kZXJlcV8oJy4vc2hhZGVycycpXG5cbmZ1bmN0aW9uIEJveGVzKHBsb3QsIHZibywgc2hhZGVyKSB7XG4gIHRoaXMucGxvdCAgID0gcGxvdFxuICB0aGlzLnZibyAgICA9IHZib1xuICB0aGlzLnNoYWRlciA9IHNoYWRlclxufVxuXG52YXIgcHJvdG8gPSBCb3hlcy5wcm90b3R5cGVcblxucHJvdG8uYmluZCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc2hhZGVyID0gdGhpcy5zaGFkZXJcbiAgdGhpcy52Ym8uYmluZCgpXG4gIHRoaXMuc2hhZGVyLmJpbmQoKVxuICBzaGFkZXIuYXR0cmlidXRlcy5jb29yZC5wb2ludGVyKClcbiAgc2hhZGVyLnVuaWZvcm1zLnNjcmVlbkJveCA9IHRoaXMucGxvdC5zY3JlZW5Cb3hcbn1cblxucHJvdG8uZHJhd0JveCA9IChmdW5jdGlvbigpIHtcbiAgdmFyIGxvID0gWzAsMF1cbiAgdmFyIGhpID0gWzAsMF1cbiAgcmV0dXJuIGZ1bmN0aW9uKGxvWCwgbG9ZLCBoaVgsIGhpWSwgY29sb3IpIHtcbiAgICB2YXIgcGxvdCAgICAgICA9IHRoaXMucGxvdFxuICAgIHZhciBzaGFkZXIgICAgID0gdGhpcy5zaGFkZXJcbiAgICB2YXIgZ2wgICAgICAgICA9IHBsb3QuZ2xcblxuICAgIGxvWzBdID0gbG9YXG4gICAgbG9bMV0gPSBsb1lcbiAgICBoaVswXSA9IGhpWFxuICAgIGhpWzFdID0gaGlZXG5cbiAgICBzaGFkZXIudW5pZm9ybXMubG8gICAgID0gbG9cbiAgICBzaGFkZXIudW5pZm9ybXMuaGkgICAgID0gaGlcbiAgICBzaGFkZXIudW5pZm9ybXMuY29sb3IgID0gY29sb3JcblxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIDQpXG4gIH1cbn0oKSlcblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnZiby5kaXNwb3NlKClcbiAgdGhpcy5zaGFkZXIuZGlzcG9zZSgpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUJveGVzKHBsb3QpIHtcbiAgdmFyIGdsICA9IHBsb3QuZ2xcbiAgdmFyIHZibyA9IGNyZWF0ZUJ1ZmZlcihnbCwgW1xuICAgIDAsMCxcbiAgICAwLDEsXG4gICAgMSwwLFxuICAgIDEsMV0pXG4gIHZhciBzaGFkZXIgID0gY3JlYXRlU2hhZGVyKGdsLCBzaGFkZXJzLmJveFZlcnQsIHNoYWRlcnMubGluZUZyYWcpXG4gIHJldHVybiBuZXcgQm94ZXMocGxvdCwgdmJvLCBzaGFkZXIpXG59XG5cbn0se1wiLi9zaGFkZXJzXCI6Mjg0LFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtc2hhZGVyXCI6MzAxfV0sMjgyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUdyaWRcblxudmFyIGNyZWF0ZUJ1ZmZlciAgPSBfZGVyZXFfKCdnbC1idWZmZXInKVxudmFyIGNyZWF0ZVNoYWRlciAgPSBfZGVyZXFfKCdnbC1zaGFkZXInKVxudmFyIGJzZWFyY2ggICAgICAgPSBfZGVyZXFfKCdiaW5hcnktc2VhcmNoLWJvdW5kcycpXG52YXIgc2hhZGVycyAgICAgICA9IF9kZXJlcV8oJy4vc2hhZGVycycpXG5cbmZ1bmN0aW9uIEdyaWQocGxvdCwgdmJvLCBzaGFkZXIsIHRpY2tTaGFkZXIpIHtcbiAgdGhpcy5wbG90ICAgPSBwbG90XG4gIHRoaXMudmJvICAgID0gdmJvXG4gIHRoaXMuc2hhZGVyID0gc2hhZGVyXG4gIHRoaXMudGlja1NoYWRlciA9IHRpY2tTaGFkZXJcbiAgdGhpcy50aWNrcyAgPSBbW10sIFtdXVxufVxuXG5mdW5jdGlvbiBjb21wYXJlVGlja051bShhLCBiKSB7XG4gIHJldHVybiBhIC0gYlxufVxuXG52YXIgcHJvdG8gPSBHcmlkLnByb3RvdHlwZVxuXG5wcm90by5kcmF3ID0gKGZ1bmN0aW9uKCkge1xuXG4gIHZhciBEQVRBX1NISUZUID0gWzAsMF1cbiAgdmFyIERBVEFfU0NBTEUgPSBbMCwwXVxuICB2YXIgREFUQV9BWElTICA9IFswLDBdXG5cbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciBwbG90ICAgICAgID0gdGhpcy5wbG90XG4gICAgdmFyIHZibyAgICAgICAgPSB0aGlzLnZib1xuICAgIHZhciBzaGFkZXIgICAgID0gdGhpcy5zaGFkZXJcbiAgICB2YXIgdGlja3MgICAgICA9IHRoaXMudGlja3NcbiAgICB2YXIgZ2wgICAgICAgICA9IHBsb3QuZ2xcbiAgICB2YXIgYm91bmRzICAgICA9IHBsb3QuX3RpY2tCb3VuZHNcbiAgICB2YXIgZGF0YUJveCAgICA9IHBsb3QuZGF0YUJveFxuICAgIHZhciB2aWV3UGl4ZWxzID0gcGxvdC52aWV3Qm94XG4gICAgdmFyIGxpbmVXaWR0aCAgPSBwbG90LmdyaWRMaW5lV2lkdGhcbiAgICB2YXIgZ3JpZENvbG9yICA9IHBsb3QuZ3JpZExpbmVDb2xvclxuICAgIHZhciBncmlkRW5hYmxlID0gcGxvdC5ncmlkTGluZUVuYWJsZVxuICAgIHZhciBwaXhlbFJhdGlvID0gcGxvdC5waXhlbFJhdGlvXG5cbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcbiAgICAgIHZhciBsbyA9IGJvdW5kc1tpXVxuICAgICAgdmFyIGhpID0gYm91bmRzW2krMl1cbiAgICAgIHZhciBib3VuZFNjYWxlID0gaGkgLSBsb1xuICAgICAgdmFyIGRhdGFDZW50ZXIgID0gMC41ICogKGRhdGFCb3hbaSsyXSArIGRhdGFCb3hbaV0pXG4gICAgICB2YXIgZGF0YVdpZHRoICAgPSBkYXRhQm94W2krMl0gLSBkYXRhQm94W2ldXG4gICAgICBEQVRBX1NDQUxFW2ldID0gMi4wICogYm91bmRTY2FsZSAvIGRhdGFXaWR0aFxuICAgICAgREFUQV9TSElGVFtpXSA9IDIuMCAqIChsbyAtIGRhdGFDZW50ZXIpIC8gZGF0YVdpZHRoXG4gICAgfVxuXG4gICAgc2hhZGVyLmJpbmQoKVxuICAgIHZiby5iaW5kKClcbiAgICBzaGFkZXIuYXR0cmlidXRlcy5kYXRhQ29vcmQucG9pbnRlcigpXG4gICAgc2hhZGVyLnVuaWZvcm1zLmRhdGFTaGlmdCA9IERBVEFfU0hJRlRcbiAgICBzaGFkZXIudW5pZm9ybXMuZGF0YVNjYWxlID0gREFUQV9TQ0FMRVxuXG4gICAgdmFyIG9mZnNldCA9IDBcbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcbiAgICAgIERBVEFfQVhJU1swXSA9IERBVEFfQVhJU1sxXSA9IDBcbiAgICAgIERBVEFfQVhJU1tpXSA9IDFcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5kYXRhQXhpcyAgPSBEQVRBX0FYSVNcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5saW5lV2lkdGggPSBsaW5lV2lkdGhbaV0gLyAodmlld1BpeGVsc1tpKzJdIC0gdmlld1BpeGVsc1tpXSkgKiBwaXhlbFJhdGlvXG4gICAgICBzaGFkZXIudW5pZm9ybXMuY29sb3IgICAgID0gZ3JpZENvbG9yW2ldXG5cbiAgICAgIHZhciBzaXplID0gdGlja3NbaV0ubGVuZ3RoICogNlxuICAgICAgaWYoZ3JpZEVuYWJsZVtpXSAmJiBzaXplKSB7XG4gICAgICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCBvZmZzZXQsIHNpemUpXG4gICAgICB9XG4gICAgICBvZmZzZXQgKz0gc2l6ZVxuICAgIH1cbiAgfVxufSkoKVxuXG5wcm90by5kcmF3VGlja01hcmtzID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgREFUQV9TSElGVCA9IFswLDBdXG4gIHZhciBEQVRBX1NDQUxFID0gWzAsMF1cbiAgdmFyIFhfQVhJUyAgICAgPSBbMSwwXVxuICB2YXIgWV9BWElTICAgICA9IFswLDFdXG4gIHZhciBTQ1JfT0ZGU0VUID0gWzAsMF1cbiAgdmFyIFRJQ0tfU0NBTEUgPSBbMCwwXVxuXG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB2YXIgcGxvdCAgICAgICA9IHRoaXMucGxvdFxuICAgIHZhciB2Ym8gICAgICAgID0gdGhpcy52Ym9cbiAgICB2YXIgc2hhZGVyICAgICA9IHRoaXMudGlja1NoYWRlclxuICAgIHZhciB0aWNrcyAgICAgID0gdGhpcy50aWNrc1xuICAgIHZhciBnbCAgICAgICAgID0gcGxvdC5nbFxuICAgIHZhciBib3VuZHMgICAgID0gcGxvdC5fdGlja0JvdW5kc1xuICAgIHZhciBkYXRhQm94ICAgID0gcGxvdC5kYXRhQm94XG4gICAgdmFyIHZpZXdCb3ggICAgPSBwbG90LnZpZXdCb3hcbiAgICB2YXIgcGl4ZWxSYXRpbyA9IHBsb3QucGl4ZWxSYXRpb1xuICAgIHZhciBzY3JlZW5Cb3ggID0gcGxvdC5zY3JlZW5Cb3hcblxuICAgIHZhciBzY3JlZW5XaWR0aCAgPSBzY3JlZW5Cb3hbMl0gLSBzY3JlZW5Cb3hbMF1cbiAgICB2YXIgc2NyZWVuSGVpZ2h0ID0gc2NyZWVuQm94WzNdIC0gc2NyZWVuQm94WzFdXG4gICAgdmFyIHZpZXdXaWR0aCAgICA9IHZpZXdCb3hbMl0gICAtIHZpZXdCb3hbMF1cbiAgICB2YXIgdmlld0hlaWdodCAgID0gdmlld0JveFszXSAgIC0gdmlld0JveFsxXVxuXG4gICAgZm9yKHZhciBpPTA7IGk8MjsgKytpKSB7XG4gICAgICB2YXIgbG8gPSBib3VuZHNbaV1cbiAgICAgIHZhciBoaSA9IGJvdW5kc1tpKzJdXG4gICAgICB2YXIgYm91bmRTY2FsZSA9IGhpIC0gbG9cbiAgICAgIHZhciBkYXRhQ2VudGVyICA9IDAuNSAqIChkYXRhQm94W2krMl0gKyBkYXRhQm94W2ldKVxuICAgICAgdmFyIGRhdGFXaWR0aCAgID0gKGRhdGFCb3hbaSsyXSAtIGRhdGFCb3hbaV0pXG4gICAgICBEQVRBX1NDQUxFW2ldID0gMi4wICogYm91bmRTY2FsZSAvIGRhdGFXaWR0aFxuICAgICAgREFUQV9TSElGVFtpXSA9IDIuMCAqIChsbyAtIGRhdGFDZW50ZXIpIC8gZGF0YVdpZHRoXG4gICAgfVxuXG4gICAgREFUQV9TQ0FMRVswXSAqPSB2aWV3V2lkdGggLyBzY3JlZW5XaWR0aFxuICAgIERBVEFfU0hJRlRbMF0gKj0gdmlld1dpZHRoIC8gc2NyZWVuV2lkdGhcblxuICAgIERBVEFfU0NBTEVbMV0gKj0gdmlld0hlaWdodCAvIHNjcmVlbkhlaWdodFxuICAgIERBVEFfU0hJRlRbMV0gKj0gdmlld0hlaWdodCAvIHNjcmVlbkhlaWdodFxuXG4gICAgc2hhZGVyLmJpbmQoKVxuICAgIHZiby5iaW5kKClcblxuICAgIHNoYWRlci5hdHRyaWJ1dGVzLmRhdGFDb29yZC5wb2ludGVyKClcblxuICAgIHZhciB1bmlmb3JtcyA9IHNoYWRlci51bmlmb3Jtc1xuICAgIHVuaWZvcm1zLmRhdGFTaGlmdCA9IERBVEFfU0hJRlRcbiAgICB1bmlmb3Jtcy5kYXRhU2NhbGUgPSBEQVRBX1NDQUxFXG5cbiAgICB2YXIgdGlja01hcmtMZW5ndGggPSBwbG90LnRpY2tNYXJrTGVuZ3RoXG4gICAgdmFyIHRpY2tNYXJrV2lkdGggID0gcGxvdC50aWNrTWFya1dpZHRoXG4gICAgdmFyIHRpY2tNYXJrQ29sb3IgID0gcGxvdC50aWNrTWFya0NvbG9yXG5cbiAgICB2YXIgeFRpY2tzT2Zmc2V0ID0gMFxuICAgIHZhciB5VGlja3NPZmZzZXQgPSB0aWNrc1swXS5sZW5ndGggKiA2XG5cbiAgICB2YXIgeFN0YXJ0ID0gTWF0aC5taW4oYnNlYXJjaC5nZSh0aWNrc1swXSwgKGRhdGFCb3hbMF0gLSBib3VuZHNbMF0pIC8gKGJvdW5kc1syXSAtIGJvdW5kc1swXSksIGNvbXBhcmVUaWNrTnVtKSwgdGlja3NbMF0ubGVuZ3RoKVxuICAgIHZhciB4RW5kICAgPSBNYXRoLm1pbihic2VhcmNoLmd0KHRpY2tzWzBdLCAoZGF0YUJveFsyXSAtIGJvdW5kc1swXSkgLyAoYm91bmRzWzJdIC0gYm91bmRzWzBdKSwgY29tcGFyZVRpY2tOdW0pLCB0aWNrc1swXS5sZW5ndGgpXG4gICAgdmFyIHhPZmZzZXQgPSB4VGlja3NPZmZzZXQgKyA2ICogeFN0YXJ0XG4gICAgdmFyIHhDb3VudCAgPSA2ICogTWF0aC5tYXgoMCwgeEVuZCAtIHhTdGFydClcblxuICAgIHZhciB5U3RhcnQgPSBNYXRoLm1pbihic2VhcmNoLmdlKHRpY2tzWzFdLCAoZGF0YUJveFsxXSAtIGJvdW5kc1sxXSkgLyAoYm91bmRzWzNdIC0gYm91bmRzWzFdKSwgY29tcGFyZVRpY2tOdW0pLCB0aWNrc1sxXS5sZW5ndGgpXG4gICAgdmFyIHlFbmQgICA9IE1hdGgubWluKGJzZWFyY2guZ3QodGlja3NbMV0sIChkYXRhQm94WzNdIC0gYm91bmRzWzFdKSAvIChib3VuZHNbM10gLSBib3VuZHNbMV0pLCBjb21wYXJlVGlja051bSksIHRpY2tzWzFdLmxlbmd0aClcbiAgICB2YXIgeU9mZnNldCA9IHlUaWNrc09mZnNldCArIDYgKiB5U3RhcnRcbiAgICB2YXIgeUNvdW50ICA9IDYgKiBNYXRoLm1heCgwLCB5RW5kIC0geVN0YXJ0KVxuXG4gICAgU0NSX09GRlNFVFswXSAgICAgICAgID0gMi4wICogKHZpZXdCb3hbMF0gLSB0aWNrTWFya0xlbmd0aFsxXSkgLyBzY3JlZW5XaWR0aCAtIDEuMFxuICAgIFNDUl9PRkZTRVRbMV0gICAgICAgICA9ICh2aWV3Qm94WzNdICsgdmlld0JveFsxXSkgLyBzY3JlZW5IZWlnaHQgLSAxLjBcbiAgICBUSUNLX1NDQUxFWzBdICAgICAgICAgPSB0aWNrTWFya0xlbmd0aFsxXSAqIHBpeGVsUmF0aW8gLyBzY3JlZW5XaWR0aFxuICAgIFRJQ0tfU0NBTEVbMV0gICAgICAgICA9IHRpY2tNYXJrV2lkdGhbMV0gICogcGl4ZWxSYXRpbyAvIHNjcmVlbkhlaWdodFxuXG4gICAgaWYoeUNvdW50KSB7XG4gICAgICB1bmlmb3Jtcy5jb2xvciAgICAgICAgPSB0aWNrTWFya0NvbG9yWzFdXG4gICAgICB1bmlmb3Jtcy50aWNrU2NhbGUgICAgPSBUSUNLX1NDQUxFXG4gICAgICB1bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBZX0FYSVNcbiAgICAgIHVuaWZvcm1zLnNjcmVlbk9mZnNldCA9IFNDUl9PRkZTRVRcbiAgICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCB5T2Zmc2V0LCB5Q291bnQpXG4gICAgfVxuXG4gICAgU0NSX09GRlNFVFswXSAgICAgICAgID0gKHZpZXdCb3hbMl0gKyB2aWV3Qm94WzBdKSAvIHNjcmVlbldpZHRoIC0gMS4wXG4gICAgU0NSX09GRlNFVFsxXSAgICAgICAgID0gMi4wICogKHZpZXdCb3hbMV0gLSB0aWNrTWFya0xlbmd0aFswXSkgLyBzY3JlZW5IZWlnaHQgLSAxLjBcbiAgICBUSUNLX1NDQUxFWzBdICAgICAgICAgPSB0aWNrTWFya1dpZHRoWzBdICAqIHBpeGVsUmF0aW8gLyBzY3JlZW5XaWR0aFxuICAgIFRJQ0tfU0NBTEVbMV0gICAgICAgICA9IHRpY2tNYXJrTGVuZ3RoWzBdICogcGl4ZWxSYXRpbyAvIHNjcmVlbkhlaWdodFxuXG4gICAgaWYoeENvdW50KSB7XG4gICAgICB1bmlmb3Jtcy5jb2xvciAgICAgICAgPSB0aWNrTWFya0NvbG9yWzBdXG4gICAgICB1bmlmb3Jtcy50aWNrU2NhbGUgICAgPSBUSUNLX1NDQUxFXG4gICAgICB1bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBYX0FYSVNcbiAgICAgIHVuaWZvcm1zLnNjcmVlbk9mZnNldCA9IFNDUl9PRkZTRVRcbiAgICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCB4T2Zmc2V0LCB4Q291bnQpXG4gICAgfVxuXG4gICAgU0NSX09GRlNFVFswXSAgICAgICAgID0gMi4wICogKHZpZXdCb3hbMl0gKyB0aWNrTWFya0xlbmd0aFszXSkgLyBzY3JlZW5XaWR0aCAtIDEuMFxuICAgIFNDUl9PRkZTRVRbMV0gICAgICAgICA9ICh2aWV3Qm94WzNdICsgdmlld0JveFsxXSkgLyBzY3JlZW5IZWlnaHQgLSAxLjBcbiAgICBUSUNLX1NDQUxFWzBdICAgICAgICAgPSB0aWNrTWFya0xlbmd0aFszXSAqIHBpeGVsUmF0aW8gLyBzY3JlZW5XaWR0aFxuICAgIFRJQ0tfU0NBTEVbMV0gICAgICAgICA9IHRpY2tNYXJrV2lkdGhbM10gICogcGl4ZWxSYXRpbyAvIHNjcmVlbkhlaWdodFxuXG4gICAgaWYoeUNvdW50KSB7XG4gICAgICB1bmlmb3Jtcy5jb2xvciAgICAgICAgPSB0aWNrTWFya0NvbG9yWzNdXG4gICAgICB1bmlmb3Jtcy50aWNrU2NhbGUgICAgPSBUSUNLX1NDQUxFXG4gICAgICB1bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBZX0FYSVNcbiAgICAgIHVuaWZvcm1zLnNjcmVlbk9mZnNldCA9IFNDUl9PRkZTRVRcbiAgICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCB5T2Zmc2V0LCB5Q291bnQpXG4gICAgfVxuXG4gICAgU0NSX09GRlNFVFswXSAgICAgICAgID0gKHZpZXdCb3hbMl0gKyB2aWV3Qm94WzBdKSAvIHNjcmVlbldpZHRoIC0gMS4wXG4gICAgU0NSX09GRlNFVFsxXSAgICAgICAgID0gMi4wICogKHZpZXdCb3hbM10gKyB0aWNrTWFya0xlbmd0aFsyXSkgLyBzY3JlZW5IZWlnaHQgLSAxLjBcbiAgICBUSUNLX1NDQUxFWzBdICAgICAgICAgPSB0aWNrTWFya1dpZHRoWzJdICAqIHBpeGVsUmF0aW8gLyBzY3JlZW5XaWR0aFxuICAgIFRJQ0tfU0NBTEVbMV0gICAgICAgICA9IHRpY2tNYXJrTGVuZ3RoWzJdICogcGl4ZWxSYXRpbyAvIHNjcmVlbkhlaWdodFxuXG4gICAgaWYoeENvdW50KSB7XG4gICAgICB1bmlmb3Jtcy5jb2xvciAgICAgICAgPSB0aWNrTWFya0NvbG9yWzJdXG4gICAgICB1bmlmb3Jtcy50aWNrU2NhbGUgICAgPSBUSUNLX1NDQUxFXG4gICAgICB1bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBYX0FYSVNcbiAgICAgIHVuaWZvcm1zLnNjcmVlbk9mZnNldCA9IFNDUl9PRkZTRVRcbiAgICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCB4T2Zmc2V0LCB4Q291bnQpXG4gICAgfVxuICB9XG59KSgpXG5cbnByb3RvLnVwZGF0ZSA9IChmdW5jdGlvbigpIHtcbiAgdmFyIE9GRlNFVF9YID0gWzEsICAxLCAtMSwgLTEsICAxLCAtMV1cbiAgdmFyIE9GRlNFVF9ZID0gWzEsIC0xLCAgMSwgIDEsIC0xLCAtMV1cblxuICByZXR1cm4gZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIHZhciB0aWNrcyAgPSBvcHRpb25zLnRpY2tzXG4gICAgdmFyIGJvdW5kcyA9IG9wdGlvbnMuYm91bmRzXG4gICAgdmFyIGRhdGEgICA9IG5ldyBGbG9hdDMyQXJyYXkoNiAqIDMgKiAodGlja3NbMF0ubGVuZ3RoICsgdGlja3NbMV0ubGVuZ3RoKSlcblxuICAgIHZhciB6ZXJvTGluZUVuYWJsZSA9IHRoaXMucGxvdC56ZXJvTGluZUVuYWJsZVxuXG4gICAgdmFyIHB0ciAgICA9IDBcbiAgICB2YXIgZ3JpZFRpY2tzID0gW1tdLCBbXV1cbiAgICBmb3IodmFyIGRpbT0wOyBkaW08MjsgKytkaW0pIHtcbiAgICAgIHZhciBsb2NhbFRpY2tzID0gZ3JpZFRpY2tzW2RpbV1cbiAgICAgIHZhciBheGlzVGlja3MgPSB0aWNrc1tkaW1dXG4gICAgICB2YXIgbG8gPSBib3VuZHNbZGltXVxuICAgICAgdmFyIGhpID0gYm91bmRzW2RpbSsyXVxuICAgICAgZm9yKHZhciBpPTA7IGk8YXhpc1RpY2tzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciB4ID0gKGF4aXNUaWNrc1tpXS54IC0gbG8pIC8gKGhpIC0gbG8pXG4gICAgICAgIGxvY2FsVGlja3MucHVzaCh4KVxuICAgICAgICBmb3IodmFyIGo9MDsgajw2OyArK2opIHtcbiAgICAgICAgICBkYXRhW3B0cisrXSA9IHhcbiAgICAgICAgICBkYXRhW3B0cisrXSA9IE9GRlNFVF9YW2pdXG4gICAgICAgICAgZGF0YVtwdHIrK10gPSBPRkZTRVRfWVtqXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy50aWNrcyA9IGdyaWRUaWNrc1xuICAgIHRoaXMudmJvLnVwZGF0ZShkYXRhKVxuICB9XG59KSgpXG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy52Ym8uZGlzcG9zZSgpXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxuICB0aGlzLnRpY2tTaGFkZXIuZGlzcG9zZSgpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUdyaWQocGxvdCkge1xuICB2YXIgZ2wgICAgID0gcGxvdC5nbFxuICB2YXIgdmJvICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBzaGFkZXJzLmdyaWRWZXJ0LCBzaGFkZXJzLmdyaWRGcmFnKVxuICB2YXIgdGlja1NoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgc2hhZGVycy50aWNrVmVydCwgc2hhZGVycy5ncmlkRnJhZylcbiAgdmFyIGdyaWQgICA9IG5ldyBHcmlkKHBsb3QsIHZibywgc2hhZGVyLCB0aWNrU2hhZGVyKVxuICByZXR1cm4gZ3JpZFxufVxuXG59LHtcIi4vc2hhZGVyc1wiOjI4NCxcImJpbmFyeS1zZWFyY2gtYm91bmRzXCI6Mjg2LFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtc2hhZGVyXCI6MzAxfV0sMjgzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUxpbmVzXG5cbnZhciBjcmVhdGVCdWZmZXIgPSBfZGVyZXFfKCdnbC1idWZmZXInKVxudmFyIGNyZWF0ZVNoYWRlciA9IF9kZXJlcV8oJ2dsLXNoYWRlcicpXG5cbnZhciBzaGFkZXJzID0gX2RlcmVxXygnLi9zaGFkZXJzJylcblxuZnVuY3Rpb24gTGluZXMocGxvdCwgdmJvLCBzaGFkZXIpIHtcbiAgdGhpcy5wbG90ICAgPSBwbG90XG4gIHRoaXMudmJvICAgID0gdmJvXG4gIHRoaXMuc2hhZGVyID0gc2hhZGVyXG59XG5cbnZhciBwcm90byA9IExpbmVzLnByb3RvdHlwZVxuXG5wcm90by5iaW5kID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzaGFkZXIgPSB0aGlzLnNoYWRlclxuICB0aGlzLnZiby5iaW5kKClcbiAgdGhpcy5zaGFkZXIuYmluZCgpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmNvb3JkLnBvaW50ZXIoKVxuICBzaGFkZXIudW5pZm9ybXMuc2NyZWVuQm94ID0gdGhpcy5wbG90LnNjcmVlbkJveFxufVxuXG5wcm90by5kcmF3TGluZSA9IChmdW5jdGlvbigpIHtcbiAgdmFyIHN0YXJ0ID0gWzAsMF1cbiAgdmFyIGVuZCAgID0gWzAsMF1cbiAgcmV0dXJuIGZ1bmN0aW9uKHN0YXJ0WCwgc3RhcnRZLCBlbmRYLCBlbmRZLCB3aWR0aCwgY29sb3IpIHtcbiAgICB2YXIgcGxvdCAgICAgICA9IHRoaXMucGxvdFxuICAgIHZhciBzaGFkZXIgICAgID0gdGhpcy5zaGFkZXJcbiAgICB2YXIgZ2wgICAgICAgICA9IHBsb3QuZ2xcblxuICAgIHN0YXJ0WzBdID0gc3RhcnRYXG4gICAgc3RhcnRbMV0gPSBzdGFydFlcbiAgICBlbmRbMF0gICA9IGVuZFhcbiAgICBlbmRbMV0gICA9IGVuZFlcblxuICAgIHNoYWRlci51bmlmb3Jtcy5zdGFydCAgPSBzdGFydFxuICAgIHNoYWRlci51bmlmb3Jtcy5lbmQgICAgPSBlbmRcbiAgICBzaGFkZXIudW5pZm9ybXMud2lkdGggID0gd2lkdGggKiBwbG90LnBpeGVsUmF0aW9cbiAgICBzaGFkZXIudW5pZm9ybXMuY29sb3IgID0gY29sb3JcblxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVfU1RSSVAsIDAsIDQpXG4gIH1cbn0oKSlcblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnZiby5kaXNwb3NlKClcbiAgdGhpcy5zaGFkZXIuZGlzcG9zZSgpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUxpbmVzKHBsb3QpIHtcbiAgdmFyIGdsICA9IHBsb3QuZ2xcbiAgdmFyIHZibyA9IGNyZWF0ZUJ1ZmZlcihnbCwgW1xuICAgIC0xLC0xLFxuICAgIC0xLDEsXG4gICAgMSwtMSxcbiAgICAxLDFdKVxuICB2YXIgc2hhZGVyICA9IGNyZWF0ZVNoYWRlcihnbCwgc2hhZGVycy5saW5lVmVydCwgc2hhZGVycy5saW5lRnJhZylcbiAgdmFyIGxpbmVzICAgPSBuZXcgTGluZXMocGxvdCwgdmJvLCBzaGFkZXIpXG4gIHJldHVybiBsaW5lc1xufVxuXG59LHtcIi4vc2hhZGVyc1wiOjI4NCxcImdsLWJ1ZmZlclwiOjI0MSxcImdsLXNoYWRlclwiOjMwMX1dLDI4NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGdsc2xpZnkgPSBfZGVyZXFfKCdnbHNsaWZ5JylcblxudmFyIEZSQUdNRU5UID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbG93cCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcbnVuaWZvcm0gdmVjNCBjb2xvcjtcXG52b2lkIG1haW4oKSB7XFxuICBnbF9GcmFnQ29sb3IgPSB2ZWM0KGNvbG9yLnh5eiAqIGNvbG9yLncsIGNvbG9yLncpO1xcbn1cXG5cIl0pXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBsaW5lVmVydDogZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMyIGNvb3JkO1xcblxcbnVuaWZvcm0gdmVjNCBzY3JlZW5Cb3g7XFxudW5pZm9ybSB2ZWMyIHN0YXJ0LCBlbmQ7XFxudW5pZm9ybSBmbG9hdCB3aWR0aDtcXG5cXG52ZWMyIHBlcnAodmVjMiB2KSB7XFxuICByZXR1cm4gdmVjMih2LnksIC12LngpO1xcbn1cXG5cXG52ZWMyIHNjcmVlbih2ZWMyIHYpIHtcXG4gIHJldHVybiAyLjAgKiAodiAtIHNjcmVlbkJveC54eSkgLyAoc2NyZWVuQm94Lnp3IC0gc2NyZWVuQm94Lnh5KSAtIDEuMDtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMiBkZWx0YSA9IG5vcm1hbGl6ZShwZXJwKHN0YXJ0IC0gZW5kKSk7XFxuICB2ZWMyIG9mZnNldCA9IG1peChzdGFydCwgZW5kLCAwLjUgKiAoY29vcmQueSsxLjApKTtcXG4gIGdsX1Bvc2l0aW9uID0gdmVjNChzY3JlZW4ob2Zmc2V0ICsgMC41ICogd2lkdGggKiBkZWx0YSAqIGNvb3JkLngpLCAwLCAxKTtcXG59XFxuXCJdKSxcbiAgbGluZUZyYWc6IEZSQUdNRU5ULFxuICB0ZXh0VmVydDogZ2xzbGlmeShbXCIjZGVmaW5lIEdMU0xJRlkgMVxcbmF0dHJpYnV0ZSB2ZWMzIHRleHRDb29yZGluYXRlO1xcblxcbnVuaWZvcm0gdmVjMiBkYXRhU2NhbGUsIGRhdGFTaGlmdCwgZGF0YUF4aXMsIHNjcmVlbk9mZnNldCwgdGV4dFNjYWxlO1xcbnVuaWZvcm0gZmxvYXQgYW5nbGU7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZmxvYXQgZGF0YU9mZnNldCAgPSB0ZXh0Q29vcmRpbmF0ZS56O1xcbiAgdmVjMiBnbHlwaE9mZnNldCAgPSB0ZXh0Q29vcmRpbmF0ZS54eTtcXG4gIG1hdDIgZ2x5cGhNYXRyaXggPSBtYXQyKGNvcyhhbmdsZSksIHNpbihhbmdsZSksIC1zaW4oYW5nbGUpLCBjb3MoYW5nbGUpKTtcXG4gIHZlYzIgc2NyZWVuQ29vcmRpbmF0ZSA9IGRhdGFBeGlzICogKGRhdGFTY2FsZSAqIGRhdGFPZmZzZXQgKyBkYXRhU2hpZnQpICtcXG4gICAgZ2x5cGhNYXRyaXggKiBnbHlwaE9mZnNldCAqIHRleHRTY2FsZSArIHNjcmVlbk9mZnNldDtcXG4gIGdsX1Bvc2l0aW9uID0gdmVjNChzY3JlZW5Db29yZGluYXRlLCAwLCAxKTtcXG59XFxuXCJdKSxcbiAgdGV4dEZyYWc6IEZSQUdNRU5ULFxuICBncmlkVmVydDogZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMzIGRhdGFDb29yZDtcXG5cXG51bmlmb3JtIHZlYzIgZGF0YUF4aXMsIGRhdGFTaGlmdCwgZGF0YVNjYWxlO1xcbnVuaWZvcm0gZmxvYXQgbGluZVdpZHRoO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzIgcG9zID0gZGF0YUF4aXMgKiAoZGF0YVNjYWxlICogZGF0YUNvb3JkLnggKyBkYXRhU2hpZnQpO1xcbiAgcG9zICs9IDEwLjAgKiBkYXRhQ29vcmQueSAqIHZlYzIoZGF0YUF4aXMueSwgLWRhdGFBeGlzLngpICsgZGF0YUNvb3JkLnogKiBsaW5lV2lkdGg7XFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQocG9zLCAwLCAxKTtcXG59XFxuXCJdKSxcbiAgZ3JpZEZyYWc6IEZSQUdNRU5ULFxuICBib3hWZXJ0OiAgZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMyIGNvb3JkO1xcblxcbnVuaWZvcm0gdmVjNCBzY3JlZW5Cb3g7XFxudW5pZm9ybSB2ZWMyIGxvLCBoaTtcXG5cXG52ZWMyIHNjcmVlbih2ZWMyIHYpIHtcXG4gIHJldHVybiAyLjAgKiAodiAtIHNjcmVlbkJveC54eSkgLyAoc2NyZWVuQm94Lnp3IC0gc2NyZWVuQm94Lnh5KSAtIDEuMDtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHNjcmVlbihtaXgobG8sIGhpLCBjb29yZCkpLCAwLCAxKTtcXG59XFxuXCJdKSxcbiAgdGlja1ZlcnQ6IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMyBkYXRhQ29vcmQ7XFxuXFxudW5pZm9ybSB2ZWMyIGRhdGFBeGlzLCBkYXRhU2hpZnQsIGRhdGFTY2FsZSwgc2NyZWVuT2Zmc2V0LCB0aWNrU2NhbGU7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMiBwb3MgPSBkYXRhQXhpcyAqIChkYXRhU2NhbGUgKiBkYXRhQ29vcmQueCArIGRhdGFTaGlmdCk7XFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQocG9zICsgdGlja1NjYWxlKmRhdGFDb29yZC55eiArIHNjcmVlbk9mZnNldCwgMCwgMSk7XFxufVxcblwiXSlcbn1cblxufSx7XCJnbHNsaWZ5XCI6NDA5fV0sMjg1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVRleHRFbGVtZW50c1xuXG52YXIgY3JlYXRlQnVmZmVyID0gX2RlcmVxXygnZ2wtYnVmZmVyJylcbnZhciBjcmVhdGVTaGFkZXIgPSBfZGVyZXFfKCdnbC1zaGFkZXInKVxudmFyIGdldFRleHQgICAgICA9IF9kZXJlcV8oJ3RleHQtY2FjaGUnKVxudmFyIGJzZWFyY2ggICAgICA9IF9kZXJlcV8oJ2JpbmFyeS1zZWFyY2gtYm91bmRzJylcbnZhciBzaGFkZXJzICAgICAgPSBfZGVyZXFfKCcuL3NoYWRlcnMnKVxuXG5mdW5jdGlvbiBUZXh0RWxlbWVudHMocGxvdCwgdmJvLCBzaGFkZXIpIHtcbiAgdGhpcy5wbG90ICAgICAgICAgPSBwbG90XG4gIHRoaXMudmJvICAgICAgICAgID0gdmJvXG4gIHRoaXMuc2hhZGVyICAgICAgID0gc2hhZGVyXG4gIHRoaXMudGlja09mZnNldCAgID0gW1tdLFtdXVxuICB0aGlzLnRpY2tYICAgICAgICA9IFtbXSxbXV1cbiAgdGhpcy5sYWJlbE9mZnNldCAgPSBbMCwwXVxuICB0aGlzLmxhYmVsQ291bnQgICA9IFswLDBdXG59XG5cbnZhciBwcm90byA9IFRleHRFbGVtZW50cy5wcm90b3R5cGVcblxucHJvdG8uZHJhd1RpY2tzID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgREFUQV9BWElTID0gWzAsMF1cbiAgdmFyIFNDUkVFTl9PRkZTRVQgPSBbMCwwXVxuICB2YXIgWkVST18yID0gWzAsMF1cblxuICByZXR1cm4gZnVuY3Rpb24oYXhpcykge1xuICAgIHZhciBwbG90ICAgICAgICA9IHRoaXMucGxvdFxuICAgIHZhciBzaGFkZXIgICAgICA9IHRoaXMuc2hhZGVyXG4gICAgdmFyIHRpY2tYICAgICAgID0gdGhpcy50aWNrWFtheGlzXVxuICAgIHZhciB0aWNrT2Zmc2V0ICA9IHRoaXMudGlja09mZnNldFtheGlzXVxuICAgIHZhciBnbCAgICAgICAgICA9IHBsb3QuZ2xcbiAgICB2YXIgdmlld0JveCAgICAgPSBwbG90LnZpZXdCb3hcbiAgICB2YXIgZGF0YUJveCAgICAgPSBwbG90LmRhdGFCb3hcbiAgICB2YXIgc2NyZWVuQm94ICAgPSBwbG90LnNjcmVlbkJveFxuICAgIHZhciBwaXhlbFJhdGlvICA9IHBsb3QucGl4ZWxSYXRpb1xuICAgIHZhciB0aWNrRW5hYmxlICA9IHBsb3QudGlja0VuYWJsZVxuICAgIHZhciB0aWNrUGFkICAgICA9IHBsb3QudGlja1BhZFxuICAgIHZhciB0ZXh0Q29sb3IgICA9IHBsb3QudGlja0NvbG9yXG4gICAgdmFyIHRleHRBbmdsZSAgID0gcGxvdC50aWNrQW5nbGVcbiAgICAvLyB0b2RvIGNoZWNrIGlmIHRoaXMgc2hvdWxkIGJlIHVzZWQgKG5vdyB1bnVzZWQpXG4gICAgLy8gdmFyIHRpY2tMZW5ndGggID0gcGxvdC50aWNrTWFya0xlbmd0aFxuXG4gICAgdmFyIGxhYmVsRW5hYmxlID0gcGxvdC5sYWJlbEVuYWJsZVxuICAgIHZhciBsYWJlbFBhZCAgICA9IHBsb3QubGFiZWxQYWRcbiAgICB2YXIgbGFiZWxDb2xvciAgPSBwbG90LmxhYmVsQ29sb3JcbiAgICB2YXIgbGFiZWxBbmdsZSAgPSBwbG90LmxhYmVsQW5nbGVcbiAgICB2YXIgbGFiZWxPZmZzZXQgPSB0aGlzLmxhYmVsT2Zmc2V0W2F4aXNdXG4gICAgdmFyIGxhYmVsQ291bnQgID0gdGhpcy5sYWJlbENvdW50W2F4aXNdXG5cbiAgICB2YXIgc3RhcnQgPSBic2VhcmNoLmx0KHRpY2tYLCBkYXRhQm94W2F4aXNdKVxuICAgIHZhciBlbmQgICA9IGJzZWFyY2gubGUodGlja1gsIGRhdGFCb3hbYXhpcysyXSlcblxuICAgIERBVEFfQVhJU1swXSAgICA9IERBVEFfQVhJU1sxXSA9IDBcbiAgICBEQVRBX0FYSVNbYXhpc10gPSAxXG5cbiAgICBTQ1JFRU5fT0ZGU0VUW2F4aXNdID0gKHZpZXdCb3hbMitheGlzXSArIHZpZXdCb3hbYXhpc10pIC8gKHNjcmVlbkJveFsyK2F4aXNdIC0gc2NyZWVuQm94W2F4aXNdKSAtIDEuMFxuXG4gICAgdmFyIHNjcmVlblNjYWxlID0gMi4wIC8gc2NyZWVuQm94WzIrKGF4aXNeMSldIC0gc2NyZWVuQm94W2F4aXNeMV1cblxuICAgIFNDUkVFTl9PRkZTRVRbYXhpc14xXSA9IHNjcmVlblNjYWxlICogdmlld0JveFtheGlzXjFdIC0gMS4wXG4gICAgaWYodGlja0VuYWJsZVtheGlzXSkge1xuICAgICAgU0NSRUVOX09GRlNFVFtheGlzXjFdIC09IHNjcmVlblNjYWxlICogcGl4ZWxSYXRpbyAqIHRpY2tQYWRbYXhpc11cbiAgICAgIGlmKHN0YXJ0IDwgZW5kICYmIHRpY2tPZmZzZXRbZW5kXSA+IHRpY2tPZmZzZXRbc3RhcnRdKSB7XG4gICAgICAgIHNoYWRlci51bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBEQVRBX0FYSVNcbiAgICAgICAgc2hhZGVyLnVuaWZvcm1zLnNjcmVlbk9mZnNldCA9IFNDUkVFTl9PRkZTRVRcbiAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmNvbG9yICAgICAgICA9IHRleHRDb2xvcltheGlzXVxuICAgICAgICBzaGFkZXIudW5pZm9ybXMuYW5nbGUgICAgICAgID0gdGV4dEFuZ2xlW2F4aXNdXG4gICAgICAgIGdsLmRyYXdBcnJheXMoXG4gICAgICAgICAgZ2wuVFJJQU5HTEVTLFxuICAgICAgICAgIHRpY2tPZmZzZXRbc3RhcnRdLFxuICAgICAgICAgIHRpY2tPZmZzZXRbZW5kXSAtIHRpY2tPZmZzZXRbc3RhcnRdKVxuICAgICAgfVxuICAgIH1cbiAgICBpZihsYWJlbEVuYWJsZVtheGlzXSAmJiBsYWJlbENvdW50KSB7XG4gICAgICBTQ1JFRU5fT0ZGU0VUW2F4aXNeMV0gLT0gc2NyZWVuU2NhbGUgKiBwaXhlbFJhdGlvICogbGFiZWxQYWRbYXhpc11cbiAgICAgIHNoYWRlci51bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBaRVJPXzJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5zY3JlZW5PZmZzZXQgPSBTQ1JFRU5fT0ZGU0VUXG4gICAgICBzaGFkZXIudW5pZm9ybXMuY29sb3IgICAgICAgID0gbGFiZWxDb2xvcltheGlzXVxuICAgICAgc2hhZGVyLnVuaWZvcm1zLmFuZ2xlICAgICAgICA9IGxhYmVsQW5nbGVbYXhpc11cbiAgICAgIGdsLmRyYXdBcnJheXMoXG4gICAgICAgIGdsLlRSSUFOR0xFUyxcbiAgICAgICAgbGFiZWxPZmZzZXQsXG4gICAgICAgIGxhYmVsQ291bnQpXG4gICAgfVxuXG4gICAgU0NSRUVOX09GRlNFVFtheGlzXjFdID0gc2NyZWVuU2NhbGUgKiB2aWV3Qm94WzIrKGF4aXNeMSldIC0gMS4wXG4gICAgaWYodGlja0VuYWJsZVtheGlzKzJdKSB7XG4gICAgICBTQ1JFRU5fT0ZGU0VUW2F4aXNeMV0gKz0gc2NyZWVuU2NhbGUgKiBwaXhlbFJhdGlvICogdGlja1BhZFtheGlzKzJdXG4gICAgICBpZihzdGFydCA8IGVuZCAmJiB0aWNrT2Zmc2V0W2VuZF0gPiB0aWNrT2Zmc2V0W3N0YXJ0XSkge1xuICAgICAgICBzaGFkZXIudW5pZm9ybXMuZGF0YUF4aXMgICAgID0gREFUQV9BWElTXG4gICAgICAgIHNoYWRlci51bmlmb3Jtcy5zY3JlZW5PZmZzZXQgPSBTQ1JFRU5fT0ZGU0VUXG4gICAgICAgIHNoYWRlci51bmlmb3Jtcy5jb2xvciAgICAgICAgPSB0ZXh0Q29sb3JbYXhpcysyXVxuICAgICAgICBzaGFkZXIudW5pZm9ybXMuYW5nbGUgICAgICAgID0gdGV4dEFuZ2xlW2F4aXMrMl1cbiAgICAgICAgZ2wuZHJhd0FycmF5cyhcbiAgICAgICAgICBnbC5UUklBTkdMRVMsXG4gICAgICAgICAgdGlja09mZnNldFtzdGFydF0sXG4gICAgICAgICAgdGlja09mZnNldFtlbmRdIC0gdGlja09mZnNldFtzdGFydF0pXG4gICAgICB9XG4gICAgfVxuICAgIGlmKGxhYmVsRW5hYmxlW2F4aXMrMl0gJiYgbGFiZWxDb3VudCkge1xuICAgICAgU0NSRUVOX09GRlNFVFtheGlzXjFdICs9IHNjcmVlblNjYWxlICogcGl4ZWxSYXRpbyAqIGxhYmVsUGFkW2F4aXMrMl1cbiAgICAgIHNoYWRlci51bmlmb3Jtcy5kYXRhQXhpcyAgICAgPSBaRVJPXzJcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5zY3JlZW5PZmZzZXQgPSBTQ1JFRU5fT0ZGU0VUXG4gICAgICBzaGFkZXIudW5pZm9ybXMuY29sb3IgICAgICAgID0gbGFiZWxDb2xvcltheGlzKzJdXG4gICAgICBzaGFkZXIudW5pZm9ybXMuYW5nbGUgICAgICAgID0gbGFiZWxBbmdsZVtheGlzKzJdXG4gICAgICBnbC5kcmF3QXJyYXlzKFxuICAgICAgICBnbC5UUklBTkdMRVMsXG4gICAgICAgIGxhYmVsT2Zmc2V0LFxuICAgICAgICBsYWJlbENvdW50KVxuICAgIH1cblxuICB9XG59KSgpXG5cbnByb3RvLmRyYXdUaXRsZSA9IChmdW5jdGlvbigpIHtcbiAgdmFyIERBVEFfQVhJUyA9IFswLDBdXG4gIHZhciBTQ1JFRU5fT0ZGU0VUID0gWzAsMF1cblxuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHBsb3QgICAgICAgID0gdGhpcy5wbG90XG4gICAgdmFyIHNoYWRlciAgICAgID0gdGhpcy5zaGFkZXJcbiAgICB2YXIgZ2wgICAgICAgICAgPSBwbG90LmdsXG4gICAgdmFyIHNjcmVlbkJveCAgID0gcGxvdC5zY3JlZW5Cb3hcbiAgICB2YXIgdGl0bGVDZW50ZXIgPSBwbG90LnRpdGxlQ2VudGVyXG4gICAgdmFyIHRpdGxlQW5nbGUgID0gcGxvdC50aXRsZUFuZ2xlXG4gICAgdmFyIHRpdGxlQ29sb3IgID0gcGxvdC50aXRsZUNvbG9yXG4gICAgdmFyIHBpeGVsUmF0aW8gID0gcGxvdC5waXhlbFJhdGlvXG5cbiAgICBpZighdGhpcy50aXRsZUNvdW50KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcbiAgICAgIFNDUkVFTl9PRkZTRVRbaV0gPSAyLjAgKiAodGl0bGVDZW50ZXJbaV0qcGl4ZWxSYXRpbyAtIHNjcmVlbkJveFtpXSkgL1xuICAgICAgICAoc2NyZWVuQm94WzIraV0gLSBzY3JlZW5Cb3hbaV0pIC0gMVxuICAgIH1cblxuICAgIHNoYWRlci5iaW5kKClcbiAgICBzaGFkZXIudW5pZm9ybXMuZGF0YUF4aXMgICAgICA9IERBVEFfQVhJU1xuICAgIHNoYWRlci51bmlmb3Jtcy5zY3JlZW5PZmZzZXQgID0gU0NSRUVOX09GRlNFVFxuICAgIHNoYWRlci51bmlmb3Jtcy5hbmdsZSAgICAgICAgID0gdGl0bGVBbmdsZVxuICAgIHNoYWRlci51bmlmb3Jtcy5jb2xvciAgICAgICAgID0gdGl0bGVDb2xvclxuXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIHRoaXMudGl0bGVPZmZzZXQsIHRoaXMudGl0bGVDb3VudClcbiAgfVxufSkoKVxuXG5wcm90by5iaW5kID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgREFUQV9TSElGVCA9IFswLDBdXG4gIHZhciBEQVRBX1NDQUxFID0gWzAsMF1cbiAgdmFyIFRFWFRfU0NBTEUgPSBbMCwwXVxuXG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB2YXIgcGxvdCAgICAgID0gdGhpcy5wbG90XG4gICAgdmFyIHNoYWRlciAgICA9IHRoaXMuc2hhZGVyXG4gICAgdmFyIGJvdW5kcyAgICA9IHBsb3QuX3RpY2tCb3VuZHNcbiAgICB2YXIgZGF0YUJveCAgID0gcGxvdC5kYXRhQm94XG4gICAgdmFyIHNjcmVlbkJveCA9IHBsb3Quc2NyZWVuQm94XG4gICAgdmFyIHZpZXdCb3ggICA9IHBsb3Qudmlld0JveFxuXG4gICAgc2hhZGVyLmJpbmQoKVxuXG4gICAgLy9TZXQgdXAgY29vcmRpbmF0ZSBzY2FsaW5nIHVuaWZvcm1zXG4gICAgZm9yKHZhciBpPTA7IGk8MjsgKytpKSB7XG5cbiAgICAgIHZhciBsbyA9IGJvdW5kc1tpXVxuICAgICAgdmFyIGhpID0gYm91bmRzW2krMl1cbiAgICAgIHZhciBib3VuZFNjYWxlID0gaGkgLSBsb1xuICAgICAgdmFyIGRhdGFDZW50ZXIgID0gMC41ICogKGRhdGFCb3hbaSsyXSArIGRhdGFCb3hbaV0pXG4gICAgICB2YXIgZGF0YVdpZHRoICAgPSAoZGF0YUJveFtpKzJdIC0gZGF0YUJveFtpXSlcblxuICAgICAgdmFyIHZpZXdMbyA9IHZpZXdCb3hbaV1cbiAgICAgIHZhciB2aWV3SGkgPSB2aWV3Qm94W2krMl1cbiAgICAgIHZhciB2aWV3U2NhbGUgPSB2aWV3SGkgLSB2aWV3TG9cbiAgICAgIHZhciBzY3JlZW5MbyA9IHNjcmVlbkJveFtpXVxuICAgICAgdmFyIHNjcmVlbkhpID0gc2NyZWVuQm94W2krMl1cbiAgICAgIHZhciBzY3JlZW5TY2FsZSA9IHNjcmVlbkhpIC0gc2NyZWVuTG9cblxuICAgICAgREFUQV9TQ0FMRVtpXSA9IDIuMCAqIGJvdW5kU2NhbGUgLyBkYXRhV2lkdGggKiB2aWV3U2NhbGUgLyBzY3JlZW5TY2FsZVxuICAgICAgREFUQV9TSElGVFtpXSA9IDIuMCAqIChsbyAtIGRhdGFDZW50ZXIpIC8gZGF0YVdpZHRoICogdmlld1NjYWxlIC8gc2NyZWVuU2NhbGVcbiAgICB9XG5cbiAgICBURVhUX1NDQUxFWzFdID0gMi4wICogcGxvdC5waXhlbFJhdGlvIC8gKHNjcmVlbkJveFszXSAtIHNjcmVlbkJveFsxXSlcbiAgICBURVhUX1NDQUxFWzBdID0gVEVYVF9TQ0FMRVsxXSAqIChzY3JlZW5Cb3hbM10gLSBzY3JlZW5Cb3hbMV0pIC8gKHNjcmVlbkJveFsyXSAtIHNjcmVlbkJveFswXSlcblxuICAgIHNoYWRlci51bmlmb3Jtcy5kYXRhU2NhbGUgPSBEQVRBX1NDQUxFXG4gICAgc2hhZGVyLnVuaWZvcm1zLmRhdGFTaGlmdCA9IERBVEFfU0hJRlRcbiAgICBzaGFkZXIudW5pZm9ybXMudGV4dFNjYWxlID0gVEVYVF9TQ0FMRVxuXG4gICAgLy9TZXQgYXR0cmlidXRlc1xuICAgIHRoaXMudmJvLmJpbmQoKVxuICAgIHNoYWRlci5hdHRyaWJ1dGVzLnRleHRDb29yZGluYXRlLnBvaW50ZXIoKVxuICB9XG59KSgpXG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgdmFyIHZlcnRpY2VzICA9IFtdXG4gIHZhciBheGVzVGlja3MgPSBvcHRpb25zLnRpY2tzXG4gIHZhciBib3VuZHMgICAgPSBvcHRpb25zLmJvdW5kc1xuICB2YXIgaSwgaiwgaywgZGF0YSwgc2NhbGUsIGRpbWVuc2lvblxuXG4gIGZvcihkaW1lbnNpb249MDsgZGltZW5zaW9uPDI7ICsrZGltZW5zaW9uKSB7XG4gICAgdmFyIG9mZnNldHMgPSBbTWF0aC5mbG9vcih2ZXJ0aWNlcy5sZW5ndGgvMyldLCB0aWNrWCA9IFstSW5maW5pdHldXG5cbiAgICAvL0NvcHkgdmVydGljZXMgb3ZlciB0byBidWZmZXJcbiAgICB2YXIgdGlja3MgPSBheGVzVGlja3NbZGltZW5zaW9uXVxuICAgIGZvcihpPTA7IGk8dGlja3MubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciB0aWNrICA9IHRpY2tzW2ldXG4gICAgICB2YXIgeCAgICAgPSB0aWNrLnhcbiAgICAgIHZhciB0ZXh0ICA9IHRpY2sudGV4dFxuICAgICAgdmFyIGZvbnQgID0gdGljay5mb250IHx8ICdzYW5zLXNlcmlmJ1xuICAgICAgc2NhbGUgPSAodGljay5mb250U2l6ZSB8fCAxMilcblxuICAgICAgdmFyIGNvb3JkU2NhbGUgPSAxLjAgLyAoYm91bmRzW2RpbWVuc2lvbisyXSAtIGJvdW5kc1tkaW1lbnNpb25dKVxuICAgICAgdmFyIGNvb3JkU2hpZnQgPSBib3VuZHNbZGltZW5zaW9uXVxuXG4gICAgICB2YXIgcm93cyA9IHRleHQuc3BsaXQoJ1xcbicpXG4gICAgICBmb3IodmFyIHIgPSAwOyByIDwgcm93cy5sZW5ndGg7IHIrKykge1xuICAgICAgICBkYXRhID0gZ2V0VGV4dChmb250LCByb3dzW3JdKS5kYXRhXG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBkYXRhLmxlbmd0aDsgaiArPSAyKSB7XG4gICAgICAgICAgdmVydGljZXMucHVzaChcbiAgICAgICAgICAgICAgZGF0YVtqXSAqIHNjYWxlLFxuICAgICAgICAgICAgICAtZGF0YVtqICsgMV0gKiBzY2FsZSAtIHIgKiBzY2FsZSAqIDEuMixcbiAgICAgICAgICAgICAgKHggLSBjb29yZFNoaWZ0KSAqIGNvb3JkU2NhbGUpXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgb2Zmc2V0cy5wdXNoKE1hdGguZmxvb3IodmVydGljZXMubGVuZ3RoLzMpKVxuICAgICAgdGlja1gucHVzaCh4KVxuICAgIH1cblxuICAgIHRoaXMudGlja09mZnNldFtkaW1lbnNpb25dID0gb2Zmc2V0c1xuICAgIHRoaXMudGlja1hbZGltZW5zaW9uXSA9IHRpY2tYXG4gIH1cblxuICAvL0FkZCBsYWJlbHNcbiAgZm9yKGRpbWVuc2lvbj0wOyBkaW1lbnNpb248MjsgKytkaW1lbnNpb24pIHtcbiAgICB0aGlzLmxhYmVsT2Zmc2V0W2RpbWVuc2lvbl0gPSBNYXRoLmZsb29yKHZlcnRpY2VzLmxlbmd0aC8zKVxuXG4gICAgZGF0YSAgPSBnZXRUZXh0KG9wdGlvbnMubGFiZWxGb250W2RpbWVuc2lvbl0sIG9wdGlvbnMubGFiZWxzW2RpbWVuc2lvbl0sIHsgdGV4dEFsaWduOiAnY2VudGVyJyB9KS5kYXRhXG4gICAgc2NhbGUgPSBvcHRpb25zLmxhYmVsU2l6ZVtkaW1lbnNpb25dXG4gICAgZm9yKGk9MDsgaTxkYXRhLmxlbmd0aDsgaSs9Mikge1xuICAgICAgdmVydGljZXMucHVzaChkYXRhW2ldKnNjYWxlLCAtZGF0YVtpKzFdKnNjYWxlLCAwKVxuICAgIH1cblxuICAgIHRoaXMubGFiZWxDb3VudFtkaW1lbnNpb25dID1cbiAgICAgIE1hdGguZmxvb3IodmVydGljZXMubGVuZ3RoLzMpIC0gdGhpcy5sYWJlbE9mZnNldFtkaW1lbnNpb25dXG4gIH1cblxuICAvL0FkZCB0aXRsZVxuICB0aGlzLnRpdGxlT2Zmc2V0ID0gTWF0aC5mbG9vcih2ZXJ0aWNlcy5sZW5ndGgvMylcbiAgZGF0YSA9IGdldFRleHQob3B0aW9ucy50aXRsZUZvbnQsIG9wdGlvbnMudGl0bGUpLmRhdGFcbiAgc2NhbGUgPSBvcHRpb25zLnRpdGxlU2l6ZVxuICBmb3IoaT0wOyBpPGRhdGEubGVuZ3RoOyBpKz0yKSB7XG4gICAgdmVydGljZXMucHVzaChkYXRhW2ldKnNjYWxlLCAtZGF0YVtpKzFdKnNjYWxlLCAwKVxuICB9XG4gIHRoaXMudGl0bGVDb3VudCA9IE1hdGguZmxvb3IodmVydGljZXMubGVuZ3RoLzMpIC0gdGhpcy50aXRsZU9mZnNldFxuXG4gIC8vVXBsb2FkIG5ldyB2ZXJ0aWNlc1xuICB0aGlzLnZiby51cGRhdGUodmVydGljZXMpXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy52Ym8uZGlzcG9zZSgpXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVUZXh0RWxlbWVudHMocGxvdCkge1xuICB2YXIgZ2wgPSBwbG90LmdsXG4gIHZhciB2Ym8gPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHNoYWRlcnMudGV4dFZlcnQsIHNoYWRlcnMudGV4dEZyYWcpXG4gIHZhciB0ZXh0ID0gbmV3IFRleHRFbGVtZW50cyhwbG90LCB2Ym8sIHNoYWRlcilcbiAgcmV0dXJuIHRleHRcbn1cblxufSx7XCIuL3NoYWRlcnNcIjoyODQsXCJiaW5hcnktc2VhcmNoLWJvdW5kc1wiOjI4NixcImdsLWJ1ZmZlclwiOjI0MSxcImdsLXNoYWRlclwiOjMwMSxcInRleHQtY2FjaGVcIjo1MzZ9XSwyODY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuYXJndW1lbnRzWzRdWzExMV1bMF0uYXBwbHkoZXhwb3J0cyxhcmd1bWVudHMpXG59LHtcImR1cFwiOjExMX1dLDI4NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVHTFBsb3QyRFxuXG52YXIgY3JlYXRlUGljayA9IF9kZXJlcV8oJ2dsLXNlbGVjdC1zdGF0aWMnKVxuXG52YXIgY3JlYXRlR3JpZCA9IF9kZXJlcV8oJy4vbGliL2dyaWQnKVxudmFyIGNyZWF0ZVRleHQgPSBfZGVyZXFfKCcuL2xpYi90ZXh0JylcbnZhciBjcmVhdGVMaW5lID0gX2RlcmVxXygnLi9saWIvbGluZScpXG52YXIgY3JlYXRlQm94ICA9IF9kZXJlcV8oJy4vbGliL2JveCcpXG5cbmZ1bmN0aW9uIEdMUGxvdDJEKGdsLCBwaWNrQnVmZmVyKSB7XG4gIHRoaXMuZ2wgICAgICAgICAgICAgICA9IGdsXG4gIHRoaXMucGlja0J1ZmZlciAgICAgICA9IHBpY2tCdWZmZXJcblxuICB0aGlzLnNjcmVlbkJveCAgICAgICAgPSBbMCwgMCwgZ2wuZHJhd2luZ0J1ZmZlcldpZHRoLCBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0XVxuICB0aGlzLnZpZXdCb3ggICAgICAgICAgPSBbMCwgMCwgMCwgMF1cbiAgdGhpcy5kYXRhQm94ICAgICAgICAgID0gWy0xMCwgLTEwLCAxMCwgMTBdXG5cbiAgdGhpcy5ncmlkTGluZUVuYWJsZSAgID0gW3RydWUsdHJ1ZV1cbiAgdGhpcy5ncmlkTGluZVdpZHRoICAgID0gWzEsMV1cbiAgdGhpcy5ncmlkTGluZUNvbG9yICAgID0gW1swLDAsMCwxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXV1cblxuICB0aGlzLnBpeGVsUmF0aW8gICAgICAgPSAxXG5cbiAgdGhpcy50aWNrTWFya0xlbmd0aCAgID0gWzAsMCwwLDBdXG4gIHRoaXMudGlja01hcmtXaWR0aCAgICA9IFswLDAsMCwwXVxuICB0aGlzLnRpY2tNYXJrQ29sb3IgICAgPSBbWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdXVxuXG4gIHRoaXMudGlja1BhZCAgICAgICAgICA9IFsxNSwxNSwxNSwxNV1cbiAgdGhpcy50aWNrQW5nbGUgICAgICAgID0gWzAsMCwwLDBdXG4gIHRoaXMudGlja0VuYWJsZSAgICAgICA9IFt0cnVlLHRydWUsdHJ1ZSx0cnVlXVxuICB0aGlzLnRpY2tDb2xvciAgICAgICAgPSBbWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdXVxuXG4gIHRoaXMubGFiZWxQYWQgICAgICAgICA9IFsxNSwxNSwxNSwxNV1cbiAgdGhpcy5sYWJlbEFuZ2xlICAgICAgID0gWzAsTWF0aC5QSS8yLDAsMy4wKk1hdGguUEkvMl1cbiAgdGhpcy5sYWJlbEVuYWJsZSAgICAgID0gW3RydWUsdHJ1ZSx0cnVlLHRydWVdXG4gIHRoaXMubGFiZWxDb2xvciAgICAgICA9IFtbMCwwLDAsMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV1dXG5cbiAgdGhpcy50aXRsZUNlbnRlciAgICAgID0gWzAsMF1cbiAgdGhpcy50aXRsZUVuYWJsZSAgICAgID0gdHJ1ZVxuICB0aGlzLnRpdGxlQW5nbGUgICAgICAgPSAwXG4gIHRoaXMudGl0bGVDb2xvciAgICAgICA9IFswLDAsMCwxXVxuXG4gIHRoaXMuYm9yZGVyQ29sb3IgICAgICA9IFswLDAsMCwwXVxuICB0aGlzLmJhY2tncm91bmRDb2xvciAgPSBbMCwwLDAsMF1cblxuICB0aGlzLnplcm9MaW5lRW5hYmxlICAgPSBbdHJ1ZSwgdHJ1ZV1cbiAgdGhpcy56ZXJvTGluZVdpZHRoICAgID0gWzQsIDRdXG4gIHRoaXMuemVyb0xpbmVDb2xvciAgICA9IFtbMCwgMCwgMCwgMV0sWzAsIDAsIDAsIDFdXVxuXG4gIHRoaXMuYm9yZGVyTGluZUVuYWJsZSA9IFt0cnVlLHRydWUsdHJ1ZSx0cnVlXVxuICB0aGlzLmJvcmRlckxpbmVXaWR0aCAgPSBbMiwyLDIsMl1cbiAgdGhpcy5ib3JkZXJMaW5lQ29sb3IgID0gW1swLDAsMCwxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLDAsMCwxXV1cblxuICAvL0RyYXdpbmcgcGFyYW1ldGVyc1xuICB0aGlzLmdyaWQgICAgICAgICAgICAgPSBudWxsXG4gIHRoaXMudGV4dCAgICAgICAgICAgICA9IG51bGxcbiAgdGhpcy5saW5lICAgICAgICAgICAgID0gbnVsbFxuICB0aGlzLmJveCAgICAgICAgICAgICAgPSBudWxsXG4gIHRoaXMub2JqZWN0cyAgICAgICAgICA9IFtdXG4gIHRoaXMub3ZlcmxheXMgICAgICAgICA9IFtdXG5cbiAgdGhpcy5fdGlja0JvdW5kcyAgICAgID0gW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldXG5cbiAgdGhpcy5zdGF0aWMgPSBmYWxzZVxuXG4gIHRoaXMuZGlydHkgICAgICAgID0gZmFsc2VcbiAgdGhpcy5waWNrRGlydHkgICAgPSBmYWxzZVxuICB0aGlzLnBpY2tEZWxheSAgICA9IDEyMFxuICB0aGlzLnBpY2tSYWRpdXMgICA9IDEwXG4gIHRoaXMuX3BpY2tUaW1lb3V0ID0gbnVsbFxuICB0aGlzLl9kcmF3UGljayAgICA9IHRoaXMuZHJhd1BpY2suYmluZCh0aGlzKVxuXG4gIHRoaXMuX2RlcHRoQ291bnRlciA9IDBcbn1cblxudmFyIHByb3RvID0gR0xQbG90MkQucHJvdG90eXBlXG5cbnByb3RvLnNldERpcnR5ID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZGlydHkgPSB0aGlzLnBpY2tEaXJ0eSA9IHRydWVcbn1cblxucHJvdG8uc2V0T3ZlcmxheURpcnR5ID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZGlydHkgPSB0cnVlXG59XG5cbnByb3RvLm5leHREZXB0aFZhbHVlID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiAodGhpcy5fZGVwdGhDb3VudGVyKyspIC8gNjU1MzYuMFxufVxuXG5mdW5jdGlvbiBsZXJwKGEsIGIsIHQpIHtcbiAgdmFyIHMgPSAwLjUgKiAodCArIDEuMClcbiAgcmV0dXJuIE1hdGguZmxvb3IoKDEuMC1zKSphICsgcypiKXwwXG59XG5cbnByb3RvLmRyYXcgPSAoZnVuY3Rpb24oKSB7XG52YXIgVElDS19NQVJLX0JPWCA9IFswLDAsMCwwXVxucmV0dXJuIGZ1bmN0aW9uKCkge1xuICB2YXIgZ2wgICAgICAgICA9IHRoaXMuZ2xcbiAgdmFyIHNjcmVlbkJveCAgPSB0aGlzLnNjcmVlbkJveFxuICB2YXIgdmlld1BpeGVscyA9IHRoaXMudmlld0JveFxuICB2YXIgZGF0YUJveCAgICA9IHRoaXMuZGF0YUJveFxuICB2YXIgcGl4ZWxSYXRpbyA9IHRoaXMucGl4ZWxSYXRpb1xuICB2YXIgZ3JpZCAgICAgICA9IHRoaXMuZ3JpZFxuICB2YXIgbGluZSAgICAgICA9IHRoaXMubGluZVxuICB2YXIgdGV4dCAgICAgICA9IHRoaXMudGV4dFxuICB2YXIgb2JqZWN0cyAgICA9IHRoaXMub2JqZWN0c1xuXG4gIHRoaXMuX2RlcHRoQ291bnRlciA9IDBcblxuICBpZih0aGlzLnBpY2tEaXJ0eSkge1xuICAgIGlmKHRoaXMuX3BpY2tUaW1lb3V0KSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5fcGlja1RpbWVvdXQpXG4gICAgfVxuICAgIHRoaXMucGlja0RpcnR5ID0gZmFsc2VcbiAgICB0aGlzLl9waWNrVGltZW91dCA9IHNldFRpbWVvdXQodGhpcy5fZHJhd1BpY2ssIHRoaXMucGlja0RlbGF5KVxuICB9XG5cbiAgaWYoIXRoaXMuZGlydHkpIHtcbiAgICByZXR1cm5cbiAgfVxuICB0aGlzLmRpcnR5ID0gZmFsc2VcblxuICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpXG5cbiAgLy9UdXJuIG9uIHNjaXNzb3JcbiAgZ2wuZW5hYmxlKGdsLlNDSVNTT1JfVEVTVClcblxuICAvL1R1cm4gb2ZmIGRlcHRoIGJ1ZmZlclxuICBnbC5kaXNhYmxlKGdsLkRFUFRIX1RFU1QpXG4gIGdsLmRlcHRoRnVuYyhnbC5MRVNTKVxuICBnbC5kZXB0aE1hc2soZmFsc2UpXG5cbiAgLy9Db25maWd1cmUgcHJlbXVsdGlwbGllZCBhbHBoYSBibGVuZGluZ1xuICBnbC5lbmFibGUoZ2wuQkxFTkQpXG4gIGdsLmJsZW5kRXF1YXRpb24oZ2wuRlVOQ19BREQsIGdsLkZVTkNfQUREKTtcbiAgZ2wuYmxlbmRGdW5jKGdsLk9ORSwgZ2wuT05FX01JTlVTX1NSQ19BTFBIQSk7XG5cbiAgLy9EcmF3IGJvcmRlclxuICBpZiAodGhpcy5ib3JkZXJDb2xvcikge1xuICAgIGdsLnNjaXNzb3IoXG4gICAgICBzY3JlZW5Cb3hbMF0sXG4gICAgICBzY3JlZW5Cb3hbMV0sXG4gICAgICBzY3JlZW5Cb3hbMl0tc2NyZWVuQm94WzBdLFxuICAgICAgc2NyZWVuQm94WzNdLXNjcmVlbkJveFsxXSlcbiAgICB2YXIgYm9yZGVyQ29sb3IgPSB0aGlzLmJvcmRlckNvbG9yXG4gICAgZ2wuY2xlYXJDb2xvcihcbiAgICAgIGJvcmRlckNvbG9yWzBdKmJvcmRlckNvbG9yWzNdLFxuICAgICAgYm9yZGVyQ29sb3JbMV0qYm9yZGVyQ29sb3JbM10sXG4gICAgICBib3JkZXJDb2xvclsyXSpib3JkZXJDb2xvclszXSxcbiAgICAgIGJvcmRlckNvbG9yWzNdKVxuICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQgfCBnbC5ERVBUSF9CVUZGRVJfQklUKVxuICB9XG5cbiAgLy9EcmF3IGNlbnRlciBwYW5lXG4gIGdsLnNjaXNzb3IoXG4gICAgdmlld1BpeGVsc1swXSxcbiAgICB2aWV3UGl4ZWxzWzFdLFxuICAgIHZpZXdQaXhlbHNbMl0tdmlld1BpeGVsc1swXSxcbiAgICB2aWV3UGl4ZWxzWzNdLXZpZXdQaXhlbHNbMV0pXG4gIGdsLnZpZXdwb3J0KFxuICAgIHZpZXdQaXhlbHNbMF0sXG4gICAgdmlld1BpeGVsc1sxXSxcbiAgICB2aWV3UGl4ZWxzWzJdLXZpZXdQaXhlbHNbMF0sXG4gICAgdmlld1BpeGVsc1szXS12aWV3UGl4ZWxzWzFdKVxuICB2YXIgYmFja2dyb3VuZENvbG9yID0gdGhpcy5iYWNrZ3JvdW5kQ29sb3JcbiAgZ2wuY2xlYXJDb2xvcihcbiAgICBiYWNrZ3JvdW5kQ29sb3JbMF0qYmFja2dyb3VuZENvbG9yWzNdLFxuICAgIGJhY2tncm91bmRDb2xvclsxXSpiYWNrZ3JvdW5kQ29sb3JbM10sXG4gICAgYmFja2dyb3VuZENvbG9yWzJdKmJhY2tncm91bmRDb2xvclszXSxcbiAgICBiYWNrZ3JvdW5kQ29sb3JbM10pXG4gIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQpXG5cbiAgLy9EcmF3IGdyaWRcbiAgZ3JpZC5kcmF3KClcblxuICAvL0RyYXcgemVybyBsaW5lcyBzZXBhcmF0ZWx5XG4gIHZhciB6ZXJvTGluZUVuYWJsZSA9IHRoaXMuemVyb0xpbmVFbmFibGVcbiAgdmFyIHplcm9MaW5lQ29sb3IgID0gdGhpcy56ZXJvTGluZUNvbG9yXG4gIHZhciB6ZXJvTGluZVdpZHRoICA9IHRoaXMuemVyb0xpbmVXaWR0aFxuICBpZih6ZXJvTGluZUVuYWJsZVswXSB8fCB6ZXJvTGluZUVuYWJsZVsxXSkge1xuICAgIGxpbmUuYmluZCgpXG4gICAgZm9yKHZhciBpPTA7IGk8MjsgKytpKSB7XG4gICAgICBpZighemVyb0xpbmVFbmFibGVbaV0gfHxcbiAgICAgICAgIShkYXRhQm94W2ldIDw9IDAgJiYgZGF0YUJveFtpKzJdID49IDApKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIHZhciB6ZXJvSW50ZXJjZXB0ID0gc2NyZWVuQm94W2ldIC1cbiAgICAgICAgZGF0YUJveFtpXSAqIChzY3JlZW5Cb3hbaSsyXSAtIHNjcmVlbkJveFtpXSkgLyAoZGF0YUJveFtpKzJdIC0gZGF0YUJveFtpXSlcblxuICAgICAgaWYoaSA9PT0gMCkge1xuICAgICAgICBsaW5lLmRyYXdMaW5lKFxuICAgICAgICAgIHplcm9JbnRlcmNlcHQsIHNjcmVlbkJveFsxXSwgemVyb0ludGVyY2VwdCwgc2NyZWVuQm94WzNdLFxuICAgICAgICAgIHplcm9MaW5lV2lkdGhbaV0sXG4gICAgICAgICAgemVyb0xpbmVDb2xvcltpXSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxpbmUuZHJhd0xpbmUoXG4gICAgICAgICAgc2NyZWVuQm94WzBdLCB6ZXJvSW50ZXJjZXB0LCBzY3JlZW5Cb3hbMl0sIHplcm9JbnRlcmNlcHQsXG4gICAgICAgICAgemVyb0xpbmVXaWR0aFtpXSxcbiAgICAgICAgICB6ZXJvTGluZUNvbG9yW2ldKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vRHJhdyB0cmFjZXNcbiAgZm9yKHZhciBpPTA7IGk8b2JqZWN0cy5sZW5ndGg7ICsraSkge1xuICAgIG9iamVjdHNbaV0uZHJhdygpXG4gIH1cblxuICAvL1JldHVybiB2aWV3cG9ydCB0byBkZWZhdWx0XG4gIGdsLnZpZXdwb3J0KFxuICAgIHNjcmVlbkJveFswXSxcbiAgICBzY3JlZW5Cb3hbMV0sXG4gICAgc2NyZWVuQm94WzJdLXNjcmVlbkJveFswXSxcbiAgICBzY3JlZW5Cb3hbM10tc2NyZWVuQm94WzFdKVxuICBnbC5zY2lzc29yKFxuICAgIHNjcmVlbkJveFswXSxcbiAgICBzY3JlZW5Cb3hbMV0sXG4gICAgc2NyZWVuQm94WzJdLXNjcmVlbkJveFswXSxcbiAgICBzY3JlZW5Cb3hbM10tc2NyZWVuQm94WzFdKVxuXG4gIC8vRHJhdyB0aWNrIG1hcmtzXG4gIHRoaXMuZ3JpZC5kcmF3VGlja01hcmtzKClcblxuICAvL0RyYXcgbGluZSBlbGVtZW50c1xuICBsaW5lLmJpbmQoKVxuXG4gIC8vRHJhdyBib3JkZXIgbGluZXNcbiAgdmFyIGJvcmRlckxpbmVFbmFibGUgPSB0aGlzLmJvcmRlckxpbmVFbmFibGVcbiAgdmFyIGJvcmRlckxpbmVXaWR0aCAgPSB0aGlzLmJvcmRlckxpbmVXaWR0aFxuICB2YXIgYm9yZGVyTGluZUNvbG9yICA9IHRoaXMuYm9yZGVyTGluZUNvbG9yXG4gIGlmKGJvcmRlckxpbmVFbmFibGVbMV0pIHtcbiAgICBsaW5lLmRyYXdMaW5lKFxuICAgICAgdmlld1BpeGVsc1swXSwgdmlld1BpeGVsc1sxXSAtIDAuNSpib3JkZXJMaW5lV2lkdGhbMV0qcGl4ZWxSYXRpbyxcbiAgICAgIHZpZXdQaXhlbHNbMF0sIHZpZXdQaXhlbHNbM10gKyAwLjUqYm9yZGVyTGluZVdpZHRoWzNdKnBpeGVsUmF0aW8sXG4gICAgICBib3JkZXJMaW5lV2lkdGhbMV0sIGJvcmRlckxpbmVDb2xvclsxXSlcbiAgfVxuICBpZihib3JkZXJMaW5lRW5hYmxlWzBdKSB7XG4gICAgbGluZS5kcmF3TGluZShcbiAgICAgIHZpZXdQaXhlbHNbMF0gLSAwLjUqYm9yZGVyTGluZVdpZHRoWzBdKnBpeGVsUmF0aW8sIHZpZXdQaXhlbHNbMV0sXG4gICAgICB2aWV3UGl4ZWxzWzJdICsgMC41KmJvcmRlckxpbmVXaWR0aFsyXSpwaXhlbFJhdGlvLCB2aWV3UGl4ZWxzWzFdLFxuICAgICAgYm9yZGVyTGluZVdpZHRoWzBdLCBib3JkZXJMaW5lQ29sb3JbMF0pXG4gIH1cbiAgaWYoYm9yZGVyTGluZUVuYWJsZVszXSkge1xuICAgIGxpbmUuZHJhd0xpbmUoXG4gICAgICB2aWV3UGl4ZWxzWzJdLCB2aWV3UGl4ZWxzWzFdIC0gMC41KmJvcmRlckxpbmVXaWR0aFsxXSpwaXhlbFJhdGlvLFxuICAgICAgdmlld1BpeGVsc1syXSwgdmlld1BpeGVsc1szXSArIDAuNSpib3JkZXJMaW5lV2lkdGhbM10qcGl4ZWxSYXRpbyxcbiAgICAgIGJvcmRlckxpbmVXaWR0aFszXSwgYm9yZGVyTGluZUNvbG9yWzNdKVxuICB9XG4gIGlmKGJvcmRlckxpbmVFbmFibGVbMl0pIHtcbiAgICBsaW5lLmRyYXdMaW5lKFxuICAgICAgdmlld1BpeGVsc1swXSAtIDAuNSpib3JkZXJMaW5lV2lkdGhbMF0qcGl4ZWxSYXRpbywgdmlld1BpeGVsc1szXSxcbiAgICAgIHZpZXdQaXhlbHNbMl0gKyAwLjUqYm9yZGVyTGluZVdpZHRoWzJdKnBpeGVsUmF0aW8sIHZpZXdQaXhlbHNbM10sXG4gICAgICBib3JkZXJMaW5lV2lkdGhbMl0sIGJvcmRlckxpbmVDb2xvclsyXSlcbiAgfVxuXG4gIC8vRHJhdyB0ZXh0IGVsZW1lbnRzXG4gIHRleHQuYmluZCgpXG4gIGZvcih2YXIgaT0wOyBpPDI7ICsraSkge1xuICAgIHRleHQuZHJhd1RpY2tzKGkpXG4gIH1cbiAgaWYodGhpcy50aXRsZUVuYWJsZSkge1xuICAgIHRleHQuZHJhd1RpdGxlKClcbiAgfVxuXG4gIC8vRHJhdyBvdGhlciBvdmVybGF5IGVsZW1lbnRzIChzZWxlY3QgYm94ZXMsIGV0Yy4pXG4gIHZhciBvdmVybGF5cyA9IHRoaXMub3ZlcmxheXNcbiAgZm9yKHZhciBpPTA7IGk8b3ZlcmxheXMubGVuZ3RoOyArK2kpIHtcbiAgICBvdmVybGF5c1tpXS5kcmF3KClcbiAgfVxuXG4gIC8vVHVybiBvZmYgc2Npc3NvciB0ZXN0XG4gIGdsLmRpc2FibGUoZ2wuU0NJU1NPUl9URVNUKVxuICBnbC5kaXNhYmxlKGdsLkJMRU5EKVxuICBnbC5kZXB0aE1hc2sodHJ1ZSlcbn1cbn0pKClcblxucHJvdG8uZHJhd1BpY2sgPSAoZnVuY3Rpb24oKSB7XG5cbnJldHVybiBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuc3RhdGljKSByZXR1cm47XG5cbiAgdmFyIHBpY2tCdWZmZXIgPSB0aGlzLnBpY2tCdWZmZXJcbiAgdmFyIGdsID0gdGhpcy5nbFxuXG4gIHRoaXMuX3BpY2tUaW1lb3V0ID0gbnVsbFxuICBwaWNrQnVmZmVyLmJlZ2luKClcblxuICB2YXIgcGlja09mZnNldCA9IDFcbiAgdmFyIG9iamVjdHMgPSB0aGlzLm9iamVjdHNcbiAgZm9yKHZhciBpPTA7IGk8b2JqZWN0cy5sZW5ndGg7ICsraSkge1xuICAgIHBpY2tPZmZzZXQgPSBvYmplY3RzW2ldLmRyYXdQaWNrKHBpY2tPZmZzZXQpXG4gIH1cblxuICBwaWNrQnVmZmVyLmVuZCgpXG59XG59KSgpXG5cbnByb3RvLnBpY2sgPSAoZnVuY3Rpb24oKSB7XG5yZXR1cm4gZnVuY3Rpb24oeCwgeSkge1xuICBpZiAodGhpcy5zdGF0aWMpIHJldHVybjtcblxuICB2YXIgcGl4ZWxSYXRpbyAgICAgPSB0aGlzLnBpeGVsUmF0aW9cbiAgdmFyIHBpY2tQaXhlbFJhdGlvID0gdGhpcy5waWNrUGl4ZWxSYXRpb1xuICB2YXIgdmlld0JveCAgICAgICAgPSB0aGlzLnZpZXdCb3hcblxuICB2YXIgc2NyWCA9IE1hdGgucm91bmQoKHggLSB2aWV3Qm94WzBdIC8gcGl4ZWxSYXRpbykgKiBwaWNrUGl4ZWxSYXRpbyl8MFxuICB2YXIgc2NyWSA9IE1hdGgucm91bmQoKHkgLSB2aWV3Qm94WzFdIC8gcGl4ZWxSYXRpbykgKiBwaWNrUGl4ZWxSYXRpbyl8MFxuXG4gIHZhciBwaWNrUmVzdWx0ID0gdGhpcy5waWNrQnVmZmVyLnF1ZXJ5KHNjclgsIHNjclksIHRoaXMucGlja1JhZGl1cylcbiAgaWYoIXBpY2tSZXN1bHQpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgdmFyIHBpY2tWYWx1ZSA9IHBpY2tSZXN1bHQuaWQgK1xuICAgIChwaWNrUmVzdWx0LnZhbHVlWzBdPDw4KSAgK1xuICAgIChwaWNrUmVzdWx0LnZhbHVlWzFdPDwxNikgK1xuICAgIChwaWNrUmVzdWx0LnZhbHVlWzJdPDwyNClcblxuICB2YXIgb2JqZWN0cyA9IHRoaXMub2JqZWN0c1xuICBmb3IodmFyIGk9MDsgaTxvYmplY3RzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHJlc3VsdCA9IG9iamVjdHNbaV0ucGljayhzY3JYLCBzY3JZLCBwaWNrVmFsdWUpXG4gICAgaWYocmVzdWx0KSB7XG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGxcbn1cbn0pKClcblxuZnVuY3Rpb24gZGVlcENsb25lKGFycmF5KSB7XG4gIHZhciByZXN1bHQgPSBhcnJheS5zbGljZSgpXG4gIGZvcih2YXIgaT0wOyBpPHJlc3VsdC5sZW5ndGg7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IHJlc3VsdFtpXS5zbGljZSgpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBjb21wYXJlVGlja3MoYSwgYikge1xuICByZXR1cm4gYS54IC0gYi54XG59XG5cbnByb3RvLnNldFNjcmVlbkJveCA9IGZ1bmN0aW9uKG5ib3gpIHtcbiAgdmFyIHNjcmVlbkJveCA9IHRoaXMuc2NyZWVuQm94XG4gIHZhciBwaXhlbFJhdGlvID0gdGhpcy5waXhlbFJhdGlvXG5cbiAgc2NyZWVuQm94WzBdID0gTWF0aC5yb3VuZChuYm94WzBdICogcGl4ZWxSYXRpbykgfCAwXG4gIHNjcmVlbkJveFsxXSA9IE1hdGgucm91bmQobmJveFsxXSAqIHBpeGVsUmF0aW8pIHwgMFxuICBzY3JlZW5Cb3hbMl0gPSBNYXRoLnJvdW5kKG5ib3hbMl0gKiBwaXhlbFJhdGlvKSB8IDBcbiAgc2NyZWVuQm94WzNdID0gTWF0aC5yb3VuZChuYm94WzNdICogcGl4ZWxSYXRpbykgfCAwXG5cbiAgdGhpcy5zZXREaXJ0eSgpXG59XG5cbnByb3RvLnNldERhdGFCb3ggPSBmdW5jdGlvbihuYm94KSB7XG4gIHZhciBkYXRhQm94ID0gdGhpcy5kYXRhQm94XG5cbiAgdmFyIGRpZmZlcmVudCA9XG4gICAgZGF0YUJveFswXSAhPT0gbmJveFswXSB8fFxuICAgIGRhdGFCb3hbMV0gIT09IG5ib3hbMV0gfHxcbiAgICBkYXRhQm94WzJdICE9PSBuYm94WzJdIHx8XG4gICAgZGF0YUJveFszXSAhPT0gbmJveFszXVxuXG4gIGlmKGRpZmZlcmVudCkge1xuICAgIGRhdGFCb3hbMF0gPSBuYm94WzBdXG4gICAgZGF0YUJveFsxXSA9IG5ib3hbMV1cbiAgICBkYXRhQm94WzJdID0gbmJveFsyXVxuICAgIGRhdGFCb3hbM10gPSBuYm94WzNdXG5cbiAgICB0aGlzLnNldERpcnR5KClcbiAgfVxufVxuXG5wcm90by5zZXRWaWV3Qm94ID0gZnVuY3Rpb24obmJveCkge1xuICB2YXIgcGl4ZWxSYXRpbyA9IHRoaXMucGl4ZWxSYXRpb1xuICB2YXIgdmlld0JveCA9IHRoaXMudmlld0JveFxuXG4gIHZpZXdCb3hbMF0gPSBNYXRoLnJvdW5kKG5ib3hbMF0gKiBwaXhlbFJhdGlvKXwwXG4gIHZpZXdCb3hbMV0gPSBNYXRoLnJvdW5kKG5ib3hbMV0gKiBwaXhlbFJhdGlvKXwwXG4gIHZpZXdCb3hbMl0gPSBNYXRoLnJvdW5kKG5ib3hbMl0gKiBwaXhlbFJhdGlvKXwwXG4gIHZpZXdCb3hbM10gPSBNYXRoLnJvdW5kKG5ib3hbM10gKiBwaXhlbFJhdGlvKXwwXG5cbiAgdmFyIHBpY2tQaXhlbFJhdGlvID0gdGhpcy5waWNrUGl4ZWxSYXRpb1xuICB0aGlzLnBpY2tCdWZmZXIuc2hhcGUgPSBbXG4gICAgTWF0aC5yb3VuZCgobmJveFsyXSAtIG5ib3hbMF0pICogcGlja1BpeGVsUmF0aW8pfDAsXG4gICAgTWF0aC5yb3VuZCgobmJveFszXSAtIG5ib3hbMV0pICogcGlja1BpeGVsUmF0aW8pfDAgXVxuXG4gIHRoaXMuc2V0RGlydHkoKVxufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgdmFyIGdsID0gdGhpcy5nbFxuXG4gIHRoaXMucGl4ZWxSYXRpbyAgICAgID0gb3B0aW9ucy5waXhlbFJhdGlvIHx8IDFcblxuICB2YXIgcGl4ZWxSYXRpbyAgICAgICA9IHRoaXMucGl4ZWxSYXRpb1xuICB0aGlzLnBpY2tQaXhlbFJhdGlvICA9IE1hdGgubWF4KHBpeGVsUmF0aW8sIDEpXG5cbiAgdGhpcy5zZXRTY3JlZW5Cb3gob3B0aW9ucy5zY3JlZW5Cb3ggfHxcbiAgICBbMCwgMCwgZ2wuZHJhd2luZ0J1ZmZlcldpZHRoL3BpeGVsUmF0aW8sIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQvcGl4ZWxSYXRpb10pXG5cbiAgdmFyIHNjcmVlbkJveCA9IHRoaXMuc2NyZWVuQm94XG4gIHRoaXMuc2V0Vmlld0JveChvcHRpb25zLnZpZXdCb3ggfHxcbiAgICBbMC4xMjUqKHRoaXMuc2NyZWVuQm94WzJdLXRoaXMuc2NyZWVuQm94WzBdKS9waXhlbFJhdGlvLFxuICAgICAwLjEyNSoodGhpcy5zY3JlZW5Cb3hbM10tdGhpcy5zY3JlZW5Cb3hbMV0pL3BpeGVsUmF0aW8sXG4gICAgIDAuODc1Kih0aGlzLnNjcmVlbkJveFsyXS10aGlzLnNjcmVlbkJveFswXSkvcGl4ZWxSYXRpbyxcbiAgICAgMC44NzUqKHRoaXMuc2NyZWVuQm94WzNdLXRoaXMuc2NyZWVuQm94WzFdKS9waXhlbFJhdGlvXSlcblxuICB2YXIgdmlld0JveCA9IHRoaXMudmlld0JveFxuICB2YXIgYXNwZWN0UmF0aW8gPSAodmlld0JveFsyXSAtIHZpZXdCb3hbMF0pIC8gKHZpZXdCb3hbM10gLSB2aWV3Qm94WzFdKVxuICB0aGlzLnNldERhdGFCb3gob3B0aW9ucy5kYXRhQm94IHx8IFstMTAsIC0xMC9hc3BlY3RSYXRpbywgMTAsIDEwL2FzcGVjdFJhdGlvXSlcblxuICB0aGlzLmJvcmRlckNvbG9yICAgICA9IG9wdGlvbnMuYm9yZGVyQ29sb3IgIT09IGZhbHNlID8gKG9wdGlvbnMuYm9yZGVyQ29sb3IgfHwgWzAsMCwwLDBdKS5zbGljZSgpIDogZmFsc2VcbiAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSAob3B0aW9ucy5iYWNrZ3JvdW5kQ29sb3IgfHwgWzAsMCwwLDBdKS5zbGljZSgpXG5cbiAgdGhpcy5ncmlkTGluZUVuYWJsZSAgPSAob3B0aW9ucy5ncmlkTGluZUVuYWJsZSB8fCBbdHJ1ZSx0cnVlXSkuc2xpY2UoKVxuICB0aGlzLmdyaWRMaW5lV2lkdGggICA9IChvcHRpb25zLmdyaWRMaW5lV2lkdGggfHwgWzEsMV0pLnNsaWNlKClcbiAgdGhpcy5ncmlkTGluZUNvbG9yICAgPSBkZWVwQ2xvbmUob3B0aW9ucy5ncmlkTGluZUNvbG9yIHx8XG4gICAgW1swLjUsMC41LDAuNSwxXSxbMC41LDAuNSwwLjUsMV1dKVxuXG4gIHRoaXMuemVyb0xpbmVFbmFibGUgICA9IChvcHRpb25zLnplcm9MaW5lRW5hYmxlIHx8IFt0cnVlLCB0cnVlXSkuc2xpY2UoKVxuICB0aGlzLnplcm9MaW5lV2lkdGggICAgPSAob3B0aW9ucy56ZXJvTGluZVdpZHRoIHx8IFs0LCA0XSkuc2xpY2UoKVxuICB0aGlzLnplcm9MaW5lQ29sb3IgICAgPSBkZWVwQ2xvbmUob3B0aW9ucy56ZXJvTGluZUNvbG9yIHx8XG4gICAgW1swLCAwLCAwLCAxXSxbMCwgMCwgMCwgMV1dKVxuXG4gIHRoaXMudGlja01hcmtMZW5ndGggICA9IChvcHRpb25zLnRpY2tNYXJrTGVuZ3RoIHx8IFswLDAsMCwwXSkuc2xpY2UoKVxuICB0aGlzLnRpY2tNYXJrV2lkdGggICAgPSAob3B0aW9ucy50aWNrTWFya1dpZHRoIHx8IFswLDAsMCwwXSkuc2xpY2UoKVxuICB0aGlzLnRpY2tNYXJrQ29sb3IgICAgPSBkZWVwQ2xvbmUob3B0aW9ucy50aWNrTWFya0NvbG9yIHx8XG4gICAgW1swLDAsMCwxXSxbMCwwLDAsMV0sWzAsMCwwLDFdLFswLDAsMCwxXV0pXG5cbiAgdGhpcy50aXRsZUNlbnRlciAgICAgID0gKG9wdGlvbnMudGl0bGVDZW50ZXIgfHwgW1xuICAgIDAuNSoodmlld0JveFswXSt2aWV3Qm94WzJdKS9waXhlbFJhdGlvLCh2aWV3Qm94WzNdKzEyMCkvcGl4ZWxSYXRpb10pLnNsaWNlKClcbiAgdGhpcy50aXRsZUVuYWJsZSAgICAgID0gISgndGl0bGVFbmFibGUnIGluIG9wdGlvbnMpIHx8ICEhb3B0aW9ucy50aXRsZUVuYWJsZVxuICB0aGlzLnRpdGxlQW5nbGUgICAgICAgPSBvcHRpb25zLnRpdGxlQW5nbGUgfHwgMFxuICB0aGlzLnRpdGxlQ29sb3IgICAgICAgPSAob3B0aW9ucy50aXRsZUNvbG9yIHx8IFswLDAsMCwxXSkuc2xpY2UoKVxuXG4gIHRoaXMubGFiZWxQYWQgICAgICAgICA9IChvcHRpb25zLmxhYmVsUGFkIHx8IFsxNSwxNSwxNSwxNV0pLnNsaWNlKClcbiAgdGhpcy5sYWJlbEFuZ2xlICAgICAgID0gKG9wdGlvbnMubGFiZWxBbmdsZSB8fFxuICAgIFswLE1hdGguUEkvMiwwLDMuMCpNYXRoLlBJLzJdKS5zbGljZSgpXG4gIHRoaXMubGFiZWxFbmFibGUgICAgICA9IChvcHRpb25zLmxhYmVsRW5hYmxlIHx8IFt0cnVlLHRydWUsdHJ1ZSx0cnVlXSkuc2xpY2UoKVxuICB0aGlzLmxhYmVsQ29sb3IgICAgICAgPSBkZWVwQ2xvbmUob3B0aW9ucy5sYWJlbENvbG9yIHx8XG4gICAgW1swLDAsMCwxXSxbMCwwLDAsMV0sWzAsMCwwLDFdLFswLDAsMCwxXV0pXG5cbiAgdGhpcy50aWNrUGFkICAgICAgICAgPSAob3B0aW9ucy50aWNrUGFkIHx8IFsxNSwxNSwxNSwxNV0pLnNsaWNlKClcbiAgdGhpcy50aWNrQW5nbGUgICAgICAgPSAob3B0aW9ucy50aWNrQW5nbGUgfHwgWzAsMCwwLDBdKS5zbGljZSgpXG4gIHRoaXMudGlja0VuYWJsZSAgICAgID0gKG9wdGlvbnMudGlja0VuYWJsZSB8fCBbdHJ1ZSx0cnVlLHRydWUsdHJ1ZV0pLnNsaWNlKClcbiAgdGhpcy50aWNrQ29sb3IgICAgICAgPSBkZWVwQ2xvbmUob3B0aW9ucy50aWNrQ29sb3IgfHxcbiAgICBbWzAsMCwwLDFdLFswLDAsMCwxXSxbMCwwLDAsMV0sWzAsMCwwLDFdXSlcblxuICB0aGlzLmJvcmRlckxpbmVFbmFibGUgPSAob3B0aW9ucy5ib3JkZXJMaW5lRW5hYmxlIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3RydWUsdHJ1ZSx0cnVlLHRydWVdKS5zbGljZSgpXG4gIHRoaXMuYm9yZGVyTGluZVdpZHRoICA9IChvcHRpb25zLmJvcmRlckxpbmVXaWR0aCB8fCBbMiwyLDIsMl0pLnNsaWNlKClcbiAgdGhpcy5ib3JkZXJMaW5lQ29sb3IgID0gZGVlcENsb25lKG9wdGlvbnMuYm9yZGVyTGluZUNvbG9yIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtbMCwwLDAsMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwwLDAsMV1dKVxuXG4gIHZhciB0aWNrcyA9IG9wdGlvbnMudGlja3MgfHwgWyBbXSwgW10gXVxuXG4gIC8vQ29tcHV0ZSBib3VuZHMgb24gdGlja3NcbiAgdmFyIGJvdW5kcyA9IHRoaXMuX3RpY2tCb3VuZHNcbiAgYm91bmRzWzBdID0gYm91bmRzWzFdID0gIEluZmluaXR5XG4gIGJvdW5kc1syXSA9IGJvdW5kc1szXSA9IC1JbmZpbml0eVxuICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcbiAgICB2YXIgYXhpc1RpY2tzID0gdGlja3NbaV0uc2xpY2UoMClcbiAgICBpZihheGlzVGlja3MubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBheGlzVGlja3Muc29ydChjb21wYXJlVGlja3MpXG4gICAgYm91bmRzW2ldICAgPSBNYXRoLm1pbihib3VuZHNbaV0sIGF4aXNUaWNrc1swXS54KVxuICAgIGJvdW5kc1tpKzJdID0gTWF0aC5tYXgoYm91bmRzW2krMl0sIGF4aXNUaWNrc1theGlzVGlja3MubGVuZ3RoLTFdLngpXG4gIH1cblxuICAvL1VwZGF0ZSBncmlkXG4gIHRoaXMuZ3JpZC51cGRhdGUoe1xuICAgIGJvdW5kczogYm91bmRzLFxuICAgIHRpY2tzOiAgdGlja3NcbiAgfSlcblxuICAvL1VwZGF0ZSB0ZXh0XG4gIHRoaXMudGV4dC51cGRhdGUoe1xuICAgIGJvdW5kczogICAgIGJvdW5kcyxcbiAgICB0aWNrczogICAgICB0aWNrcyxcbiAgICBsYWJlbHM6ICAgICBvcHRpb25zLmxhYmVscyAgICB8fCBbJ3gnLCAneSddLFxuICAgIGxhYmVsU2l6ZTogIG9wdGlvbnMubGFiZWxTaXplIHx8IFsxMiwxMl0sXG4gICAgbGFiZWxGb250OiAgb3B0aW9ucy5sYWJlbEZvbnQgfHwgWydzYW5zLXNlcmlmJywgJ3NhbnMtc2VyaWYnXSxcbiAgICB0aXRsZTogICAgICBvcHRpb25zLnRpdGxlICAgICB8fCAnJyxcbiAgICB0aXRsZVNpemU6ICBvcHRpb25zLnRpdGxlU2l6ZSB8fCAxOCxcbiAgICB0aXRsZUZvbnQ6ICBvcHRpb25zLnRpdGxlRm9udCB8fCAnc2Fucy1zZXJpZidcbiAgfSlcblxuICB0aGlzLnN0YXRpYyA9ICEhb3B0aW9ucy5zdGF0aWM7XG5cbiAgdGhpcy5zZXREaXJ0eSgpXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5ib3guZGlzcG9zZSgpXG4gIHRoaXMuZ3JpZC5kaXNwb3NlKClcbiAgdGhpcy50ZXh0LmRpc3Bvc2UoKVxuICB0aGlzLmxpbmUuZGlzcG9zZSgpXG4gIGZvcih2YXIgaT10aGlzLm9iamVjdHMubGVuZ3RoLTE7IGk+PTA7IC0taSkge1xuICAgIHRoaXMub2JqZWN0c1tpXS5kaXNwb3NlKClcbiAgfVxuICB0aGlzLm9iamVjdHMubGVuZ3RoID0gMFxuICBmb3IodmFyIGk9dGhpcy5vdmVybGF5cy5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgdGhpcy5vdmVybGF5c1tpXS5kaXNwb3NlKClcbiAgfVxuICB0aGlzLm92ZXJsYXlzLmxlbmd0aCA9IDBcblxuICB0aGlzLmdsID0gbnVsbFxufVxuXG5wcm90by5hZGRPYmplY3QgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgaWYodGhpcy5vYmplY3RzLmluZGV4T2Yob2JqZWN0KSA8IDApIHtcbiAgICB0aGlzLm9iamVjdHMucHVzaChvYmplY3QpXG4gICAgdGhpcy5zZXREaXJ0eSgpXG4gIH1cbn1cblxucHJvdG8ucmVtb3ZlT2JqZWN0ID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gIHZhciBvYmplY3RzID0gdGhpcy5vYmplY3RzXG4gIGZvcih2YXIgaT0wOyBpPG9iamVjdHMubGVuZ3RoOyArK2kpIHtcbiAgICBpZihvYmplY3RzW2ldID09PSBvYmplY3QpIHtcbiAgICAgIG9iamVjdHMuc3BsaWNlKGksMSlcbiAgICAgIHRoaXMuc2V0RGlydHkoKVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cbn1cblxucHJvdG8uYWRkT3ZlcmxheSA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICBpZih0aGlzLm92ZXJsYXlzLmluZGV4T2Yob2JqZWN0KSA8IDApIHtcbiAgICB0aGlzLm92ZXJsYXlzLnB1c2gob2JqZWN0KVxuICAgIHRoaXMuc2V0T3ZlcmxheURpcnR5KClcbiAgfVxufVxuXG5wcm90by5yZW1vdmVPdmVybGF5ID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gIHZhciBvYmplY3RzID0gdGhpcy5vdmVybGF5c1xuICBmb3IodmFyIGk9MDsgaTxvYmplY3RzLmxlbmd0aDsgKytpKSB7XG4gICAgaWYob2JqZWN0c1tpXSA9PT0gb2JqZWN0KSB7XG4gICAgICBvYmplY3RzLnNwbGljZShpLDEpXG4gICAgICB0aGlzLnNldE92ZXJsYXlEaXJ0eSgpXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVHTFBsb3QyRChvcHRpb25zKSB7XG4gIHZhciBnbCA9IG9wdGlvbnMuZ2xcbiAgdmFyIHBpY2tCdWZmZXIgPSBjcmVhdGVQaWNrKGdsLCBbXG4gICAgZ2wuZHJhd2luZ0J1ZmZlcldpZHRoLCBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0XSlcbiAgdmFyIHBsb3QgPSBuZXcgR0xQbG90MkQoZ2wsIHBpY2tCdWZmZXIpXG4gIHBsb3QuZ3JpZCA9IGNyZWF0ZUdyaWQocGxvdClcbiAgcGxvdC50ZXh0ID0gY3JlYXRlVGV4dChwbG90KVxuICBwbG90LmxpbmUgPSBjcmVhdGVMaW5lKHBsb3QpXG4gIHBsb3QuYm94ICA9IGNyZWF0ZUJveChwbG90KVxuICBwbG90LnVwZGF0ZShvcHRpb25zKVxuICByZXR1cm4gcGxvdFxufVxuXG59LHtcIi4vbGliL2JveFwiOjI4MSxcIi4vbGliL2dyaWRcIjoyODIsXCIuL2xpYi9saW5lXCI6MjgzLFwiLi9saWIvdGV4dFwiOjI4NSxcImdsLXNlbGVjdC1zdGF0aWNcIjozMDB9XSwyODg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlQ2FtZXJhXG5cbnZhciBub3cgICAgICAgICA9IF9kZXJlcV8oJ3JpZ2h0LW5vdycpXG52YXIgY3JlYXRlVmlldyAgPSBfZGVyZXFfKCczZC12aWV3JylcbnZhciBtb3VzZUNoYW5nZSA9IF9kZXJlcV8oJ21vdXNlLWNoYW5nZScpXG52YXIgbW91c2VXaGVlbCAgPSBfZGVyZXFfKCdtb3VzZS13aGVlbCcpXG52YXIgbW91c2VPZmZzZXQgPSBfZGVyZXFfKCdtb3VzZS1ldmVudC1vZmZzZXQnKVxudmFyIGhhc1Bhc3NpdmUgID0gX2RlcmVxXygnaGFzLXBhc3NpdmUtZXZlbnRzJylcblxuZnVuY3Rpb24gY3JlYXRlQ2FtZXJhKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgZWxlbWVudCA9IGVsZW1lbnQgfHwgZG9jdW1lbnQuYm9keVxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gIHZhciBsaW1pdHMgID0gWyAwLjAxLCBJbmZpbml0eSBdXG4gIGlmKCdkaXN0YW5jZUxpbWl0cycgaW4gb3B0aW9ucykge1xuICAgIGxpbWl0c1swXSA9IG9wdGlvbnMuZGlzdGFuY2VMaW1pdHNbMF1cbiAgICBsaW1pdHNbMV0gPSBvcHRpb25zLmRpc3RhbmNlTGltaXRzWzFdXG4gIH1cbiAgaWYoJ3pvb21NaW4nIGluIG9wdGlvbnMpIHtcbiAgICBsaW1pdHNbMF0gPSBvcHRpb25zLnpvb21NaW5cbiAgfVxuICBpZignem9vbU1heCcgaW4gb3B0aW9ucykge1xuICAgIGxpbWl0c1sxXSA9IG9wdGlvbnMuem9vbU1heFxuICB9XG5cbiAgdmFyIHZpZXcgPSBjcmVhdGVWaWV3KHtcbiAgICBjZW50ZXI6IG9wdGlvbnMuY2VudGVyIHx8IFswLDAsMF0sXG4gICAgdXA6ICAgICBvcHRpb25zLnVwICAgICB8fCBbMCwxLDBdLFxuICAgIGV5ZTogICAgb3B0aW9ucy5leWUgICAgfHwgWzAsMCwxMF0sXG4gICAgbW9kZTogICBvcHRpb25zLm1vZGUgICB8fCAnb3JiaXQnLFxuICAgIGRpc3RhbmNlTGltaXRzOiBsaW1pdHNcbiAgfSlcblxuICB2YXIgcG1hdHJpeCA9IFswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXVxuICB2YXIgZGlzdGFuY2UgPSAwLjBcbiAgdmFyIHdpZHRoICAgPSBlbGVtZW50LmNsaWVudFdpZHRoXG4gIHZhciBoZWlnaHQgID0gZWxlbWVudC5jbGllbnRIZWlnaHRcblxuICB2YXIgY2FtZXJhID0ge1xuICAgIGtleUJpbmRpbmdNb2RlOiAncm90YXRlJyxcbiAgICBlbmFibGVXaGVlbDogdHJ1ZSxcbiAgICB2aWV3OiAgICAgICAgICAgICAgIHZpZXcsXG4gICAgZWxlbWVudDogICAgICAgICAgICBlbGVtZW50LFxuICAgIGRlbGF5OiAgICAgICAgICAgICAgb3B0aW9ucy5kZWxheSAgICAgICAgICB8fCAxNixcbiAgICByb3RhdGVTcGVlZDogICAgICAgIG9wdGlvbnMucm90YXRlU3BlZWQgICAgfHwgMSxcbiAgICB6b29tU3BlZWQ6ICAgICAgICAgIG9wdGlvbnMuem9vbVNwZWVkICAgICAgfHwgMSxcbiAgICB0cmFuc2xhdGVTcGVlZDogICAgIG9wdGlvbnMudHJhbnNsYXRlU3BlZWQgfHwgMSxcbiAgICBmbGlwWDogICAgICAgICAgICAgICEhb3B0aW9ucy5mbGlwWCxcbiAgICBmbGlwWTogICAgICAgICAgICAgICEhb3B0aW9ucy5mbGlwWSxcbiAgICBtb2RlczogICAgICAgICAgICAgIHZpZXcubW9kZXMsXG4gICAgX29ydGhvOiBvcHRpb25zLl9vcnRobyB8fCAob3B0aW9ucy5wcm9qZWN0aW9uICYmIG9wdGlvbnMucHJvamVjdGlvbi50eXBlID09PSAnb3J0aG9ncmFwaGljJykgfHwgZmFsc2UsXG4gICAgdGljazogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdCA9IG5vdygpXG4gICAgICB2YXIgZGVsYXkgPSB0aGlzLmRlbGF5XG4gICAgICB2YXIgY3RpbWUgPSB0IC0gMiAqIGRlbGF5XG4gICAgICB2aWV3LmlkbGUodC1kZWxheSlcbiAgICAgIHZpZXcucmVjYWxjTWF0cml4KGN0aW1lKVxuICAgICAgdmlldy5mbHVzaCh0LSgxMDArZGVsYXkqMikpXG4gICAgICB2YXIgYWxsRXF1YWwgPSB0cnVlXG4gICAgICB2YXIgbWF0cml4ID0gdmlldy5jb21wdXRlZE1hdHJpeFxuICAgICAgZm9yKHZhciBpPTA7IGk8MTY7ICsraSkge1xuICAgICAgICBhbGxFcXVhbCA9IGFsbEVxdWFsICYmIChwbWF0cml4W2ldID09PSBtYXRyaXhbaV0pXG4gICAgICAgIHBtYXRyaXhbaV0gPSBtYXRyaXhbaV1cbiAgICAgIH1cbiAgICAgIHZhciBzaXplQ2hhbmdlZCA9XG4gICAgICAgICAgZWxlbWVudC5jbGllbnRXaWR0aCA9PT0gd2lkdGggJiZcbiAgICAgICAgICBlbGVtZW50LmNsaWVudEhlaWdodCA9PT0gaGVpZ2h0XG4gICAgICB3aWR0aCAgPSBlbGVtZW50LmNsaWVudFdpZHRoXG4gICAgICBoZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgaWYoYWxsRXF1YWwpIHtcbiAgICAgICAgcmV0dXJuICFzaXplQ2hhbmdlZFxuICAgICAgfVxuICAgICAgZGlzdGFuY2UgPSBNYXRoLmV4cCh2aWV3LmNvbXB1dGVkUmFkaXVzWzBdKVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9LFxuICAgIGxvb2tBdDogZnVuY3Rpb24oZXllLCBjZW50ZXIsIHVwKSB7XG4gICAgICB2aWV3Lmxvb2tBdCh2aWV3Lmxhc3RUKCksIGV5ZSwgY2VudGVyLCB1cClcbiAgICB9LFxuICAgIHJvdGF0ZTogZnVuY3Rpb24ocGl0Y2gsIHlhdywgcm9sbCkge1xuICAgICAgdmlldy5yb3RhdGUodmlldy5sYXN0VCgpLCBwaXRjaCwgeWF3LCByb2xsKVxuICAgIH0sXG4gICAgcGFuOiBmdW5jdGlvbihkeCwgZHksIGR6KSB7XG4gICAgICB2aWV3LnBhbih2aWV3Lmxhc3RUKCksIGR4LCBkeSwgZHopXG4gICAgfSxcbiAgICB0cmFuc2xhdGU6IGZ1bmN0aW9uKGR4LCBkeSwgZHopIHtcbiAgICAgIHZpZXcudHJhbnNsYXRlKHZpZXcubGFzdFQoKSwgZHgsIGR5LCBkeilcbiAgICB9XG4gIH1cblxuICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhjYW1lcmEsIHtcbiAgICBtYXRyaXg6IHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB2aWV3LmNvbXB1dGVkTWF0cml4XG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbihtYXQpIHtcbiAgICAgICAgdmlldy5zZXRNYXRyaXgodmlldy5sYXN0VCgpLCBtYXQpXG4gICAgICAgIHJldHVybiB2aWV3LmNvbXB1dGVkTWF0cml4XG4gICAgICB9LFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgIH0sXG4gICAgbW9kZToge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZpZXcuZ2V0TW9kZSgpXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbihtb2RlKSB7XG4gICAgICAgIHZhciBjdXJVcCA9IHZpZXcuY29tcHV0ZWRVcC5zbGljZSgpXG4gICAgICAgIHZhciBjdXJFeWUgPSB2aWV3LmNvbXB1dGVkRXllLnNsaWNlKClcbiAgICAgICAgdmFyIGN1ckNlbnRlciA9IHZpZXcuY29tcHV0ZWRDZW50ZXIuc2xpY2UoKVxuICAgICAgICB2aWV3LnNldE1vZGUobW9kZSlcbiAgICAgICAgaWYobW9kZSA9PT0gJ3R1cm50YWJsZScpIHtcbiAgICAgICAgICAvLyBIYWNreSB0aW1lIHdhcnBpbmcgc3R1ZmYgdG8gZ2VuZXJhdGUgc21vb3RoIGFuaW1hdGlvblxuICAgICAgICAgIHZhciB0MCA9IG5vdygpXG4gICAgICAgICAgdmlldy5fYWN0aXZlLmxvb2tBdCh0MCwgY3VyRXllLCBjdXJDZW50ZXIsIGN1clVwKVxuICAgICAgICAgIHZpZXcuX2FjdGl2ZS5sb29rQXQodDAgKyA1MDAsIGN1ckV5ZSwgY3VyQ2VudGVyLCBbMCwgMCwgMV0pXG4gICAgICAgICAgdmlldy5fYWN0aXZlLmZsdXNoKHQwKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2aWV3LmdldE1vZGUoKVxuICAgICAgfSxcbiAgICAgIGVudW1lcmFibGU6IHRydWVcbiAgICB9LFxuICAgIGNlbnRlcjoge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRDZW50ZXJcbiAgICAgIH0sXG4gICAgICBzZXQ6IGZ1bmN0aW9uKG5jZW50ZXIpIHtcbiAgICAgICAgdmlldy5sb29rQXQodmlldy5sYXN0VCgpLCBudWxsLCBuY2VudGVyKVxuICAgICAgICByZXR1cm4gdmlldy5jb21wdXRlZENlbnRlclxuICAgICAgfSxcbiAgICAgIGVudW1lcmFibGU6IHRydWVcbiAgICB9LFxuICAgIGV5ZToge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZpZXcuY29tcHV0ZWRFeWVcbiAgICAgIH0sXG4gICAgICBzZXQ6IGZ1bmN0aW9uKG5leWUpIHtcbiAgICAgICAgdmlldy5sb29rQXQodmlldy5sYXN0VCgpLCBuZXllKVxuICAgICAgICByZXR1cm4gdmlldy5jb21wdXRlZEV5ZVxuICAgICAgfSxcbiAgICAgIGVudW1lcmFibGU6IHRydWVcbiAgICB9LFxuICAgIHVwOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdmlldy5jb21wdXRlZFVwXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbihudXApIHtcbiAgICAgICAgdmlldy5sb29rQXQodmlldy5sYXN0VCgpLCBudWxsLCBudWxsLCBudXApXG4gICAgICAgIHJldHVybiB2aWV3LmNvbXB1dGVkVXBcbiAgICAgIH0sXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgfSxcbiAgICBkaXN0YW5jZToge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGRpc3RhbmNlXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbihkKSB7XG4gICAgICAgIHZpZXcuc2V0RGlzdGFuY2Uodmlldy5sYXN0VCgpLCBkKVxuICAgICAgICByZXR1cm4gZFxuICAgICAgfSxcbiAgICAgIGVudW1lcmFibGU6IHRydWVcbiAgICB9LFxuICAgIGRpc3RhbmNlTGltaXRzOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdmlldy5nZXREaXN0YW5jZUxpbWl0cyhsaW1pdHMpXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgICAgIHZpZXcuc2V0RGlzdGFuY2VMaW1pdHModilcbiAgICAgICAgcmV0dXJuIHZcbiAgICAgIH0sXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgfVxuICB9KVxuXG4gIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY29udGV4dG1lbnUnLCBmdW5jdGlvbihldikge1xuICAgIGV2LnByZXZlbnREZWZhdWx0KClcbiAgICByZXR1cm4gZmFsc2VcbiAgfSlcblxuICBjYW1lcmEuX2xhc3RYID0gLTFcbiAgY2FtZXJhLl9sYXN0WSA9IC0xXG4gIGNhbWVyYS5fbGFzdE1vZHMgPSB7c2hpZnQ6IGZhbHNlLCBjb250cm9sOiBmYWxzZSwgYWx0OiBmYWxzZSwgbWV0YTogZmFsc2V9XG5cbiAgY2FtZXJhLmVuYWJsZU1vdXNlTGlzdGVuZXJzID0gZnVuY3Rpb24oKSB7XG5cbiAgICBjYW1lcmEubW91c2VMaXN0ZW5lciA9IG1vdXNlQ2hhbmdlKGVsZW1lbnQsIGhhbmRsZUludGVyYWN0aW9uKVxuXG4gICAgLy9lbmFibGUgc2ltcGxlIHRvdWNoIGludGVyYWN0aW9uc1xuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIGZ1bmN0aW9uIChldikge1xuICAgICAgdmFyIHh5ID0gbW91c2VPZmZzZXQoZXYuY2hhbmdlZFRvdWNoZXNbMF0sIGVsZW1lbnQpXG4gICAgICBoYW5kbGVJbnRlcmFjdGlvbigwLCB4eVswXSwgeHlbMV0sIGNhbWVyYS5fbGFzdE1vZHMpXG4gICAgICBoYW5kbGVJbnRlcmFjdGlvbigxLCB4eVswXSwgeHlbMV0sIGNhbWVyYS5fbGFzdE1vZHMpXG5cbiAgICAgIGV2LnByZXZlbnREZWZhdWx0KClcbiAgICB9LCBoYXNQYXNzaXZlID8ge3Bhc3NpdmU6IGZhbHNlfSA6IGZhbHNlKVxuXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgIHZhciB4eSA9IG1vdXNlT2Zmc2V0KGV2LmNoYW5nZWRUb3VjaGVzWzBdLCBlbGVtZW50KVxuICAgICAgaGFuZGxlSW50ZXJhY3Rpb24oMSwgeHlbMF0sIHh5WzFdLCBjYW1lcmEuX2xhc3RNb2RzKVxuXG4gICAgICBldi5wcmV2ZW50RGVmYXVsdCgpXG4gICAgfSwgaGFzUGFzc2l2ZSA/IHtwYXNzaXZlOiBmYWxzZX0gOiBmYWxzZSlcblxuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBmdW5jdGlvbiAoZXYpIHtcblxuICAgICAgaGFuZGxlSW50ZXJhY3Rpb24oMCwgY2FtZXJhLl9sYXN0WCwgY2FtZXJhLl9sYXN0WSwgY2FtZXJhLl9sYXN0TW9kcylcblxuICAgICAgZXYucHJldmVudERlZmF1bHQoKVxuICAgIH0sIGhhc1Bhc3NpdmUgPyB7cGFzc2l2ZTogZmFsc2V9IDogZmFsc2UpXG5cbiAgICBmdW5jdGlvbiBoYW5kbGVJbnRlcmFjdGlvbiAoYnV0dG9ucywgeCwgeSwgbW9kcykge1xuICAgICAgdmFyIGtleUJpbmRpbmdNb2RlID0gY2FtZXJhLmtleUJpbmRpbmdNb2RlXG5cbiAgICAgIGlmKGtleUJpbmRpbmdNb2RlID09PSBmYWxzZSkgcmV0dXJuXG5cbiAgICAgIHZhciByb3RhdGUgPSBrZXlCaW5kaW5nTW9kZSA9PT0gJ3JvdGF0ZSdcbiAgICAgIHZhciBwYW4gPSBrZXlCaW5kaW5nTW9kZSA9PT0gJ3BhbidcbiAgICAgIHZhciB6b29tID0ga2V5QmluZGluZ01vZGUgPT09ICd6b29tJ1xuXG4gICAgICB2YXIgY3RybCA9ICEhbW9kcy5jb250cm9sXG4gICAgICB2YXIgYWx0ID0gISFtb2RzLmFsdFxuICAgICAgdmFyIHNoaWZ0ID0gISFtb2RzLnNoaWZ0XG4gICAgICB2YXIgbGVmdCA9ICEhKGJ1dHRvbnMgJiAxKVxuICAgICAgdmFyIHJpZ2h0ID0gISEoYnV0dG9ucyAmIDIpXG4gICAgICB2YXIgbWlkZGxlID0gISEoYnV0dG9ucyAmIDQpXG5cbiAgICAgIHZhciBzY2FsZSA9IDEuMCAvIGVsZW1lbnQuY2xpZW50SGVpZ2h0XG4gICAgICB2YXIgZHggICAgPSBzY2FsZSAqICh4IC0gY2FtZXJhLl9sYXN0WClcbiAgICAgIHZhciBkeSAgICA9IHNjYWxlICogKHkgLSBjYW1lcmEuX2xhc3RZKVxuXG4gICAgICB2YXIgZmxpcFggPSBjYW1lcmEuZmxpcFggPyAxIDogLTFcbiAgICAgIHZhciBmbGlwWSA9IGNhbWVyYS5mbGlwWSA/IDEgOiAtMVxuXG4gICAgICB2YXIgZHJvdCAgPSBNYXRoLlBJICogY2FtZXJhLnJvdGF0ZVNwZWVkXG5cbiAgICAgIHZhciB0ID0gbm93KClcblxuICAgICAgaWYoY2FtZXJhLl9sYXN0WCAhPT0gLTEgJiYgY2FtZXJhLl9sYXN0WSAhPT0gLTEpIHtcbiAgICAgICAgaWYoKHJvdGF0ZSAmJiBsZWZ0ICYmICFjdHJsICYmICFhbHQgJiYgIXNoaWZ0KSB8fCAobGVmdCAmJiAhY3RybCAmJiAhYWx0ICYmIHNoaWZ0KSkge1xuICAgICAgICAgIC8vIFJvdGF0ZVxuICAgICAgICAgIHZpZXcucm90YXRlKHQsIGZsaXBYICogZHJvdCAqIGR4LCAtZmxpcFkgKiBkcm90ICogZHksIDApXG4gICAgICAgIH1cblxuICAgICAgICBpZigocGFuICYmIGxlZnQgJiYgIWN0cmwgJiYgIWFsdCAmJiAhc2hpZnQpIHx8IHJpZ2h0IHx8IChsZWZ0ICYmIGN0cmwgJiYgIWFsdCAmJiAhc2hpZnQpKSB7XG4gICAgICAgICAgLy8gUGFuXG4gICAgICAgICAgdmlldy5wYW4odCwgLWNhbWVyYS50cmFuc2xhdGVTcGVlZCAqIGR4ICogZGlzdGFuY2UsIGNhbWVyYS50cmFuc2xhdGVTcGVlZCAqIGR5ICogZGlzdGFuY2UsIDApXG4gICAgICAgIH1cblxuICAgICAgICBpZigoem9vbSAmJiBsZWZ0ICYmICFjdHJsICYmICFhbHQgJiYgIXNoaWZ0KSB8fCBtaWRkbGUgfHwgKGxlZnQgJiYgIWN0cmwgJiYgYWx0ICYmICFzaGlmdCkpIHtcbiAgICAgICAgICAvLyBab29tXG4gICAgICAgICAgdmFyIGt6b29tID0gLWNhbWVyYS56b29tU3BlZWQgKiBkeSAvIHdpbmRvdy5pbm5lckhlaWdodCAqICh0IC0gdmlldy5sYXN0VCgpKSAqIDEwMFxuICAgICAgICAgIHZpZXcucGFuKHQsIDAsIDAsIGRpc3RhbmNlICogKE1hdGguZXhwKGt6b29tKSAtIDEpKVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNhbWVyYS5fbGFzdFggPSB4XG4gICAgICBjYW1lcmEuX2xhc3RZID0geVxuICAgICAgY2FtZXJhLl9sYXN0TW9kcyA9IG1vZHNcblxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG5cbiAgICBjYW1lcmEud2hlZWxMaXN0ZW5lciA9IG1vdXNlV2hlZWwoZWxlbWVudCwgZnVuY3Rpb24oZHgsIGR5KSB7XG4gICAgICAvLyBUT0RPIHJlbW92ZSBub3cgdGhhdCB3ZSBjYW4gZGlzYWJsZSBzY3JvbGwgdmlhIHNjcm9sbFpvb20/XG4gICAgICBpZihjYW1lcmEua2V5QmluZGluZ01vZGUgPT09IGZhbHNlKSByZXR1cm5cbiAgICAgIGlmKCFjYW1lcmEuZW5hYmxlV2hlZWwpIHJldHVyblxuXG4gICAgICB2YXIgZmxpcFggPSBjYW1lcmEuZmxpcFggPyAxIDogLTFcbiAgICAgIHZhciBmbGlwWSA9IGNhbWVyYS5mbGlwWSA/IDEgOiAtMVxuICAgICAgdmFyIHQgPSBub3coKVxuICAgICAgaWYoTWF0aC5hYnMoZHgpID4gTWF0aC5hYnMoZHkpKSB7XG4gICAgICAgIHZpZXcucm90YXRlKHQsIDAsIDAsIC1keCAqIGZsaXBYICogTWF0aC5QSSAqIGNhbWVyYS5yb3RhdGVTcGVlZCAvIHdpbmRvdy5pbm5lcldpZHRoKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYoIWNhbWVyYS5fb3J0aG8pIHtcbiAgICAgICAgICB2YXIga3pvb20gPSAtY2FtZXJhLnpvb21TcGVlZCAqIGZsaXBZICogZHkgLyB3aW5kb3cuaW5uZXJIZWlnaHQgKiAodCAtIHZpZXcubGFzdFQoKSkgLyAyMC4wXG4gICAgICAgICAgdmlldy5wYW4odCwgMCwgMCwgZGlzdGFuY2UgKiAoTWF0aC5leHAoa3pvb20pIC0gMSkpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB0cnVlKVxuICB9XG5cbiAgY2FtZXJhLmVuYWJsZU1vdXNlTGlzdGVuZXJzKClcblxuICByZXR1cm4gY2FtZXJhXG59XG5cbn0se1wiM2Qtdmlld1wiOjUyLFwiaGFzLXBhc3NpdmUtZXZlbnRzXCI6NDExLFwibW91c2UtY2hhbmdlXCI6NDM1LFwibW91c2UtZXZlbnQtb2Zmc2V0XCI6NDM2LFwibW91c2Utd2hlZWxcIjo0MzgsXCJyaWdodC1ub3dcIjo1MDR9XSwyODk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xudmFyIGdsc2xpZnkgICAgICA9IF9kZXJlcV8oJ2dsc2xpZnknKVxudmFyIGNyZWF0ZVNoYWRlciA9IF9kZXJlcV8oJ2dsLXNoYWRlcicpXG5cbnZhciB2ZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcbmF0dHJpYnV0ZSB2ZWMyIHBvc2l0aW9uO1xcbnZhcnlpbmcgdmVjMiB1djtcXG52b2lkIG1haW4oKSB7XFxuICB1diA9IHBvc2l0aW9uO1xcbiAgZ2xfUG9zaXRpb24gPSB2ZWM0KHBvc2l0aW9uLCAwLCAxKTtcXG59XCJdKVxudmFyIGZyYWdTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudW5pZm9ybSBzYW1wbGVyMkQgYWNjdW1CdWZmZXI7XFxudmFyeWluZyB2ZWMyIHV2O1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzQgYWNjdW0gPSB0ZXh0dXJlMkQoYWNjdW1CdWZmZXIsIDAuNSAqICh1diArIDEuMCkpO1xcbiAgZ2xfRnJhZ0NvbG9yID0gbWluKHZlYzQoMSwxLDEsMSksIGFjY3VtKTtcXG59XCJdKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGdsKSB7XG4gIHJldHVybiBjcmVhdGVTaGFkZXIoZ2wsIHZlcnRTcmMsIGZyYWdTcmMsIG51bGwsIFsgeyBuYW1lOiAncG9zaXRpb24nLCB0eXBlOiAndmVjMid9XSlcbn1cblxufSx7XCJnbC1zaGFkZXJcIjozMDEsXCJnbHNsaWZ5XCI6NDA5fV0sMjkwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgY3JlYXRlQ2FtZXJhID0gX2RlcmVxXygnLi9jYW1lcmEuanMnKVxudmFyIGNyZWF0ZUF4ZXMgICA9IF9kZXJlcV8oJ2dsLWF4ZXMzZCcpXG52YXIgYXhlc1JhbmdlcyAgID0gX2RlcmVxXygnZ2wtYXhlczNkL3Byb3BlcnRpZXMnKVxudmFyIGNyZWF0ZVNwaWtlcyA9IF9kZXJlcV8oJ2dsLXNwaWtlczNkJylcbnZhciBjcmVhdGVTZWxlY3QgPSBfZGVyZXFfKCdnbC1zZWxlY3Qtc3RhdGljJylcbnZhciBjcmVhdGVGQk8gICAgPSBfZGVyZXFfKCdnbC1mYm8nKVxudmFyIGRyYXdUcmlhbmdsZSA9IF9kZXJlcV8oJ2EtYmlnLXRyaWFuZ2xlJylcbnZhciBtb3VzZUNoYW5nZSAgPSBfZGVyZXFfKCdtb3VzZS1jaGFuZ2UnKVxudmFyIG1vdXNlV2hlZWwgICA9IF9kZXJlcV8oJ21vdXNlLXdoZWVsJylcbnZhciBwZXJzcGVjdGl2ZSAgPSBfZGVyZXFfKCdnbC1tYXQ0L3BlcnNwZWN0aXZlJylcbnZhciBvcnRobyAgICAgICAgPSBfZGVyZXFfKCdnbC1tYXQ0L29ydGhvJylcbnZhciBjcmVhdGVTaGFkZXIgPSBfZGVyZXFfKCcuL2xpYi9zaGFkZXInKVxudmFyIGlzTW9iaWxlID0gX2RlcmVxXygnaXMtbW9iaWxlJykoeyB0YWJsZXQ6IHRydWUgfSlcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGNyZWF0ZVNjZW5lOiBjcmVhdGVTY2VuZSxcbiAgY3JlYXRlQ2FtZXJhOiBjcmVhdGVDYW1lcmFcbn1cblxuZnVuY3Rpb24gTW91c2VTZWxlY3QoKSB7XG4gIHRoaXMubW91c2UgICAgICAgICAgPSBbLTEsLTFdXG4gIHRoaXMuc2NyZWVuICAgICAgICAgPSBudWxsXG4gIHRoaXMuZGlzdGFuY2UgICAgICAgPSBJbmZpbml0eVxuICB0aGlzLmluZGV4ICAgICAgICAgID0gbnVsbFxuICB0aGlzLmRhdGFDb29yZGluYXRlID0gbnVsbFxuICB0aGlzLmRhdGFQb3NpdGlvbiAgID0gbnVsbFxuICB0aGlzLm9iamVjdCAgICAgICAgID0gbnVsbFxuICB0aGlzLmRhdGEgICAgICAgICAgID0gbnVsbFxufVxuXG5mdW5jdGlvbiBnZXRDb250ZXh0KGNhbnZhcywgb3B0aW9ucykge1xuICB2YXIgZ2wgPSBudWxsXG4gIHRyeSB7XG4gICAgZ2wgPSBjYW52YXMuZ2V0Q29udGV4dCgnd2ViZ2wnLCBvcHRpb25zKVxuICAgIGlmKCFnbCkge1xuICAgICAgZ2wgPSBjYW52YXMuZ2V0Q29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgb3B0aW9ucylcbiAgICB9XG4gIH0gY2F0Y2goZSkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgcmV0dXJuIGdsXG59XG5cbmZ1bmN0aW9uIHJvdW5kVXBQb3cxMCh4KSB7XG4gIHZhciB5ID0gTWF0aC5yb3VuZChNYXRoLmxvZyhNYXRoLmFicyh4KSkgLyBNYXRoLmxvZygxMCkpXG4gIGlmKHkgPCAwKSB7XG4gICAgdmFyIGJhc2UgPSBNYXRoLnJvdW5kKE1hdGgucG93KDEwLCAteSkpXG4gICAgcmV0dXJuIE1hdGguY2VpbCh4KmJhc2UpIC8gYmFzZVxuICB9IGVsc2UgaWYoeSA+IDApIHtcbiAgICB2YXIgYmFzZSA9IE1hdGgucm91bmQoTWF0aC5wb3coMTAsIHkpKVxuICAgIHJldHVybiBNYXRoLmNlaWwoeC9iYXNlKSAqIGJhc2VcbiAgfVxuICByZXR1cm4gTWF0aC5jZWlsKHgpXG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRCb29sKHgpIHtcbiAgaWYodHlwZW9mIHggPT09ICdib29sZWFuJykge1xuICAgIHJldHVybiB4XG4gIH1cbiAgcmV0dXJuIHRydWVcbn1cblxuZnVuY3Rpb24gY3JlYXRlU2NlbmUob3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICBvcHRpb25zLmNhbWVyYSA9IG9wdGlvbnMuY2FtZXJhIHx8IHt9XG5cbiAgdmFyIGNhbnZhcyA9IG9wdGlvbnMuY2FudmFzXG4gIGlmKCFjYW52YXMpIHtcbiAgICBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxuICAgIGlmKG9wdGlvbnMuY29udGFpbmVyKSB7XG4gICAgICB2YXIgY29udGFpbmVyID0gb3B0aW9ucy5jb250YWluZXJcbiAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChjYW52YXMpXG4gICAgfSBlbHNlIHtcbiAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoY2FudmFzKVxuICAgIH1cbiAgfVxuXG4gIHZhciBnbCA9IG9wdGlvbnMuZ2xcbiAgaWYoIWdsKSB7XG4gICAgZ2wgPSBnZXRDb250ZXh0KGNhbnZhcyxcbiAgICAgIG9wdGlvbnMuZ2xPcHRpb25zIHx8IHtcbiAgICAgICAgcHJlbXVsdGlwbGllZEFscGhhOiB0cnVlLFxuICAgICAgICBhbnRpYWxpYXM6IHRydWUsXG4gICAgICAgIHByZXNlcnZlRHJhd2luZ0J1ZmZlcjogaXNNb2JpbGVcbiAgICAgIH0pXG4gIH1cbiAgaWYoIWdsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd3ZWJnbCBub3Qgc3VwcG9ydGVkJylcbiAgfVxuXG4gIC8vSW5pdGlhbCBib3VuZHNcbiAgdmFyIGJvdW5kcyA9IG9wdGlvbnMuYm91bmRzIHx8IFtbLTEwLC0xMCwtMTBdLCBbMTAsMTAsMTBdXVxuXG4gIC8vQ3JlYXRlIHNlbGVjdGlvblxuICB2YXIgc2VsZWN0aW9uID0gbmV3IE1vdXNlU2VsZWN0KClcblxuICAvL0FjY3VtdWxhdGlvbiBidWZmZXJcbiAgdmFyIGFjY3VtQnVmZmVyID0gY3JlYXRlRkJPKGdsLFxuICAgIFtnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRdLCB7XG4gICAgICBwcmVmZXJGbG9hdDogIWlzTW9iaWxlXG4gICAgfSlcblxuICB2YXIgYWNjdW1TaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wpXG5cbiAgdmFyIGlzT3J0aG8gPVxuICAgIChvcHRpb25zLmNhbWVyYU9iamVjdCAmJiBvcHRpb25zLmNhbWVyYU9iamVjdC5fb3J0aG8gPT09IHRydWUpIHx8XG4gICAgKG9wdGlvbnMuY2FtZXJhLnByb2plY3Rpb24gJiYgb3B0aW9ucy5jYW1lcmEucHJvamVjdGlvbi50eXBlID09PSAnb3J0aG9ncmFwaGljJykgfHxcbiAgICBmYWxzZVxuXG4gIC8vQ3JlYXRlIGEgY2FtZXJhXG4gIHZhciBjYW1lcmFPcHRpb25zID0ge1xuICAgIGV5ZTogICAgIG9wdGlvbnMuY2FtZXJhLmV5ZSAgICAgfHwgWzIsMCwwXSxcbiAgICBjZW50ZXI6ICBvcHRpb25zLmNhbWVyYS5jZW50ZXIgIHx8IFswLDAsMF0sXG4gICAgdXA6ICAgICAgb3B0aW9ucy5jYW1lcmEudXAgICAgICB8fCBbMCwxLDBdLFxuICAgIHpvb21NaW46IG9wdGlvbnMuY2FtZXJhLnpvb21NYXggfHwgMC4xLFxuICAgIHpvb21NYXg6IG9wdGlvbnMuY2FtZXJhLnpvb21NaW4gfHwgMTAwLFxuICAgIG1vZGU6ICAgIG9wdGlvbnMuY2FtZXJhLm1vZGUgICAgfHwgJ3R1cm50YWJsZScsXG4gICAgX29ydGhvOiAgaXNPcnRob1xuICB9XG5cbiAgLy9DcmVhdGUgYXhlc1xuICB2YXIgYXhlc09wdGlvbnMgPSBvcHRpb25zLmF4ZXMgfHwge31cbiAgdmFyIGF4ZXMgPSBjcmVhdGVBeGVzKGdsLCBheGVzT3B0aW9ucylcbiAgYXhlcy5lbmFibGUgPSAhYXhlc09wdGlvbnMuZGlzYWJsZVxuXG4gIC8vQ3JlYXRlIHNwaWtlc1xuICB2YXIgc3Bpa2VPcHRpb25zID0gb3B0aW9ucy5zcGlrZXMgfHwge31cbiAgdmFyIHNwaWtlcyA9IGNyZWF0ZVNwaWtlcyhnbCwgc3Bpa2VPcHRpb25zKVxuXG4gIC8vT2JqZWN0IGxpc3QgaXMgZW1wdHkgaW5pdGlhbGx5XG4gIHZhciBvYmplY3RzICAgICAgICAgPSBbXVxuICB2YXIgcGlja0J1ZmZlcklkcyAgID0gW11cbiAgdmFyIHBpY2tCdWZmZXJDb3VudCA9IFtdXG4gIHZhciBwaWNrQnVmZmVycyAgICAgPSBbXVxuXG4gIC8vRGlydHkgZmxhZywgc2tpcCByZWRyYXcgaWYgc2NlbmUgc3RhdGljXG4gIHZhciBkaXJ0eSAgICAgICA9IHRydWVcbiAgdmFyIHBpY2tEaXJ0eSAgID0gdHJ1ZVxuXG4gIHZhciBwcm9qZWN0aW9uICAgICA9IG5ldyBBcnJheSgxNilcbiAgdmFyIG1vZGVsICAgICAgICAgID0gbmV3IEFycmF5KDE2KVxuXG4gIHZhciBjYW1lcmFQYXJhbXMgPSB7XG4gICAgdmlldzogICAgICAgICBudWxsLFxuICAgIHByb2plY3Rpb246ICAgcHJvamVjdGlvbixcbiAgICBtb2RlbDogICAgICAgIG1vZGVsLFxuICAgIF9vcnRobzogICAgICAgIGZhbHNlXG4gIH1cblxuICB2YXIgcGlja0RpcnR5ID0gdHJ1ZVxuXG4gIHZhciB2aWV3U2hhcGUgPSBbIGdsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodCBdXG5cbiAgdmFyIGNhbWVyYSA9IG9wdGlvbnMuY2FtZXJhT2JqZWN0IHx8IGNyZWF0ZUNhbWVyYShjYW52YXMsIGNhbWVyYU9wdGlvbnMpXG5cbiAgLy9DcmVhdGUgc2NlbmUgb2JqZWN0XG4gIHZhciBzY2VuZSA9IHtcbiAgICBnbDogICAgICAgICAgIGdsLFxuICAgIGNvbnRleHRMb3N0OiAgZmFsc2UsXG4gICAgcGl4ZWxSYXRpbzogICBvcHRpb25zLnBpeGVsUmF0aW8gfHwgMSxcbiAgICBjYW52YXM6ICAgICAgIGNhbnZhcyxcbiAgICBzZWxlY3Rpb246ICAgIHNlbGVjdGlvbixcbiAgICBjYW1lcmE6ICAgICAgIGNhbWVyYSxcbiAgICBheGVzOiAgICAgICAgIGF4ZXMsXG4gICAgYXhlc1BpeGVsczogICBudWxsLFxuICAgIHNwaWtlczogICAgICAgc3Bpa2VzLFxuICAgIGJvdW5kczogICAgICAgYm91bmRzLFxuICAgIG9iamVjdHM6ICAgICAgb2JqZWN0cyxcbiAgICBzaGFwZTogICAgICAgIHZpZXdTaGFwZSxcbiAgICBhc3BlY3Q6ICAgICAgIG9wdGlvbnMuYXNwZWN0UmF0aW8gfHwgWzEsMSwxXSxcbiAgICBwaWNrUmFkaXVzOiAgIG9wdGlvbnMucGlja1JhZGl1cyB8fCAxMCxcbiAgICB6TmVhcjogICAgICAgIG9wdGlvbnMuek5lYXIgfHwgMC4wMSxcbiAgICB6RmFyOiAgICAgICAgIG9wdGlvbnMuekZhciAgfHwgMTAwMCxcbiAgICBmb3Z5OiAgICAgICAgIG9wdGlvbnMuZm92eSAgfHwgTWF0aC5QSS80LFxuICAgIGNsZWFyQ29sb3I6ICAgb3B0aW9ucy5jbGVhckNvbG9yIHx8IFswLDAsMCwwXSxcbiAgICBhdXRvUmVzaXplOiAgIGRlZmF1bHRCb29sKG9wdGlvbnMuYXV0b1Jlc2l6ZSksXG4gICAgYXV0b0JvdW5kczogICBkZWZhdWx0Qm9vbChvcHRpb25zLmF1dG9Cb3VuZHMpLFxuICAgIGF1dG9TY2FsZTogICAgISFvcHRpb25zLmF1dG9TY2FsZSxcbiAgICBhdXRvQ2VudGVyOiAgIGRlZmF1bHRCb29sKG9wdGlvbnMuYXV0b0NlbnRlciksXG4gICAgY2xpcFRvQm91bmRzOiBkZWZhdWx0Qm9vbChvcHRpb25zLmNsaXBUb0JvdW5kcyksXG4gICAgc25hcFRvRGF0YTogICAhIW9wdGlvbnMuc25hcFRvRGF0YSxcbiAgICBvbnNlbGVjdDogICAgIG9wdGlvbnMub25zZWxlY3QgfHwgbnVsbCxcbiAgICBvbnJlbmRlcjogICAgIG9wdGlvbnMub25yZW5kZXIgfHwgbnVsbCxcbiAgICBvbmNsaWNrOiAgICAgIG9wdGlvbnMub25jbGljayAgfHwgbnVsbCxcbiAgICBjYW1lcmFQYXJhbXM6IGNhbWVyYVBhcmFtcyxcbiAgICBvbmNvbnRleHRsb3NzOiBudWxsLFxuICAgIG1vdXNlTGlzdGVuZXI6IG51bGwsXG4gICAgX3N0b3BwZWQ6IGZhbHNlXG4gIH1cblxuICB2YXIgcGlja1NoYXBlID0gWyAoZ2wuZHJhd2luZ0J1ZmZlcldpZHRoL3NjZW5lLnBpeGVsUmF0aW8pfDAsIChnbC5kcmF3aW5nQnVmZmVySGVpZ2h0L3NjZW5lLnBpeGVsUmF0aW8pfDAgXVxuXG4gIGZ1bmN0aW9uIHJlc2l6ZUxpc3RlbmVyKCkge1xuICAgIGlmKHNjZW5lLl9zdG9wcGVkKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgaWYoIXNjZW5lLmF1dG9SZXNpemUpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICB2YXIgcGFyZW50ID0gY2FudmFzLnBhcmVudE5vZGVcbiAgICB2YXIgd2lkdGggID0gMVxuICAgIHZhciBoZWlnaHQgPSAxXG4gICAgaWYocGFyZW50ICYmIHBhcmVudCAhPT0gZG9jdW1lbnQuYm9keSkge1xuICAgICAgd2lkdGggID0gcGFyZW50LmNsaWVudFdpZHRoXG4gICAgICBoZWlnaHQgPSBwYXJlbnQuY2xpZW50SGVpZ2h0XG4gICAgfSBlbHNlIHtcbiAgICAgIHdpZHRoICA9IHdpbmRvdy5pbm5lcldpZHRoXG4gICAgICBoZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHRcbiAgICB9XG4gICAgdmFyIG5leHRXaWR0aCAgPSBNYXRoLmNlaWwod2lkdGggICogc2NlbmUucGl4ZWxSYXRpbyl8MFxuICAgIHZhciBuZXh0SGVpZ2h0ID0gTWF0aC5jZWlsKGhlaWdodCAqIHNjZW5lLnBpeGVsUmF0aW8pfDBcbiAgICBpZihuZXh0V2lkdGggIT09IGNhbnZhcy53aWR0aCB8fCBuZXh0SGVpZ2h0ICE9PSBjYW52YXMuaGVpZ2h0KSB7XG4gICAgICBjYW52YXMud2lkdGggICA9IG5leHRXaWR0aFxuICAgICAgY2FudmFzLmhlaWdodCAgPSBuZXh0SGVpZ2h0XG4gICAgICB2YXIgc3R5bGUgPSBjYW52YXMuc3R5bGVcbiAgICAgIHN0eWxlLnBvc2l0aW9uID0gc3R5bGUucG9zaXRpb24gfHwgJ2Fic29sdXRlJ1xuICAgICAgc3R5bGUubGVmdCAgICAgPSAnMHB4J1xuICAgICAgc3R5bGUudG9wICAgICAgPSAnMHB4J1xuICAgICAgc3R5bGUud2lkdGggICAgPSB3aWR0aCAgKyAncHgnXG4gICAgICBzdHlsZS5oZWlnaHQgICA9IGhlaWdodCArICdweCdcbiAgICAgIGRpcnR5ID0gdHJ1ZVxuICAgIH1cbiAgfVxuICBpZihzY2VuZS5hdXRvUmVzaXplKSB7XG4gICAgcmVzaXplTGlzdGVuZXIoKVxuICB9XG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemVMaXN0ZW5lcilcblxuICBmdW5jdGlvbiByZWFsbG9jUGlja0lkcygpIHtcbiAgICB2YXIgbnVtT2JqcyA9IG9iamVjdHMubGVuZ3RoXG4gICAgdmFyIG51bVBpY2sgPSBwaWNrQnVmZmVycy5sZW5ndGhcbiAgICBmb3IodmFyIGk9MDsgaTxudW1QaWNrOyArK2kpIHtcbiAgICAgIHBpY2tCdWZmZXJDb3VudFtpXSA9IDBcbiAgICB9XG4gICAgb2JqX2xvb3A6XG4gICAgZm9yKHZhciBpPTA7IGk8bnVtT2JqczsgKytpKSB7XG4gICAgICB2YXIgb2JqID0gb2JqZWN0c1tpXVxuICAgICAgdmFyIHBpY2tDb3VudCA9IG9iai5waWNrU2xvdHNcbiAgICAgIGlmKCFwaWNrQ291bnQpIHtcbiAgICAgICAgcGlja0J1ZmZlcklkc1tpXSA9IC0xXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBmb3IodmFyIGo9MDsgajxudW1QaWNrOyArK2opIHtcbiAgICAgICAgaWYocGlja0J1ZmZlckNvdW50W2pdICsgcGlja0NvdW50IDwgMjU1KSB7XG4gICAgICAgICAgcGlja0J1ZmZlcklkc1tpXSA9IGpcbiAgICAgICAgICBvYmouc2V0UGlja0Jhc2UocGlja0J1ZmZlckNvdW50W2pdKzEpXG4gICAgICAgICAgcGlja0J1ZmZlckNvdW50W2pdICs9IHBpY2tDb3VudFxuICAgICAgICAgIGNvbnRpbnVlIG9ial9sb29wXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vQ3JlYXRlIG5ldyBwaWNrIGJ1ZmZlclxuICAgICAgdmFyIG5idWZmZXIgPSBjcmVhdGVTZWxlY3QoZ2wsIHZpZXdTaGFwZSlcbiAgICAgIHBpY2tCdWZmZXJJZHNbaV0gPSBudW1QaWNrXG4gICAgICBwaWNrQnVmZmVycy5wdXNoKG5idWZmZXIpXG4gICAgICBwaWNrQnVmZmVyQ291bnQucHVzaChwaWNrQ291bnQpXG4gICAgICBvYmouc2V0UGlja0Jhc2UoMSlcbiAgICAgIG51bVBpY2sgKz0gMVxuICAgIH1cbiAgICB3aGlsZShudW1QaWNrID4gMCAmJiBwaWNrQnVmZmVyQ291bnRbbnVtUGljay0xXSA9PT0gMCkge1xuICAgICAgcGlja0J1ZmZlckNvdW50LnBvcCgpXG4gICAgICBwaWNrQnVmZmVycy5wb3AoKS5kaXNwb3NlKClcbiAgICB9XG4gIH1cblxuICBzY2VuZS51cGRhdGUgPSBmdW5jdGlvbihvcHRpb25zKSB7XG5cbiAgICBpZihzY2VuZS5fc3RvcHBlZCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gICAgZGlydHkgPSB0cnVlXG4gICAgcGlja0RpcnR5ID0gdHJ1ZVxuICB9XG5cbiAgc2NlbmUuYWRkID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYoc2NlbmUuX3N0b3BwZWQpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBvYmouYXhlcyA9IGF4ZXNcbiAgICBvYmplY3RzLnB1c2gob2JqKVxuICAgIHBpY2tCdWZmZXJJZHMucHVzaCgtMSlcbiAgICBkaXJ0eSA9IHRydWVcbiAgICBwaWNrRGlydHkgPSB0cnVlXG4gICAgcmVhbGxvY1BpY2tJZHMoKVxuICB9XG5cbiAgc2NlbmUucmVtb3ZlID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYoc2NlbmUuX3N0b3BwZWQpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICB2YXIgaWR4ID0gb2JqZWN0cy5pbmRleE9mKG9iailcbiAgICBpZihpZHggPCAwKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgb2JqZWN0cy5zcGxpY2UoaWR4LCAxKVxuICAgIHBpY2tCdWZmZXJJZHMucG9wKClcbiAgICBkaXJ0eSA9IHRydWVcbiAgICBwaWNrRGlydHkgPSB0cnVlXG4gICAgcmVhbGxvY1BpY2tJZHMoKVxuICB9XG5cbiAgc2NlbmUuZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIGlmKHNjZW5lLl9zdG9wcGVkKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBzY2VuZS5fc3RvcHBlZCA9IHRydWVcblxuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCByZXNpemVMaXN0ZW5lcilcbiAgICBjYW52YXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0bG9zdCcsIGNoZWNrQ29udGV4dExvc3MpXG4gICAgc2NlbmUubW91c2VMaXN0ZW5lci5lbmFibGVkID0gZmFsc2VcblxuICAgIGlmKHNjZW5lLmNvbnRleHRMb3N0KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvL0Rlc3Ryb3kgb2JqZWN0c1xuICAgIGF4ZXMuZGlzcG9zZSgpXG4gICAgc3Bpa2VzLmRpc3Bvc2UoKVxuICAgIGZvcih2YXIgaT0wOyBpPG9iamVjdHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIG9iamVjdHNbaV0uZGlzcG9zZSgpXG4gICAgfVxuXG4gICAgLy9DbGVhbiB1cCBidWZmZXJzXG4gICAgYWNjdW1CdWZmZXIuZGlzcG9zZSgpXG4gICAgZm9yKHZhciBpPTA7IGk8cGlja0J1ZmZlcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHBpY2tCdWZmZXJzW2ldLmRpc3Bvc2UoKVxuICAgIH1cblxuICAgIC8vQ2xlYW4gdXAgc2hhZGVyc1xuICAgIGFjY3VtU2hhZGVyLmRpc3Bvc2UoKVxuXG4gICAgLy9SZWxlYXNlIGFsbCByZWZlcmVuY2VzXG4gICAgZ2wgPSBudWxsXG4gICAgYXhlcyA9IG51bGxcbiAgICBzcGlrZXMgPSBudWxsXG4gICAgb2JqZWN0cyA9IFtdXG4gIH1cblxuICBzY2VuZS53aGVlbExpc3RlbmVyID0gbW91c2VXaGVlbChjYW52YXMsIGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgIC8vIFRPRE8gcmVtb3ZlIG5vdyB0aGF0IHdlIGNhbiBkaXNhYmxlIHNjcm9sbCB2aWEgc2Nyb2xsWm9vbT9cbiAgICBpZihjYW1lcmEua2V5QmluZGluZ01vZGUgPT09IGZhbHNlKSByZXR1cm5cbiAgICBpZighY2FtZXJhLmVuYWJsZVdoZWVsKSByZXR1cm5cblxuICAgIGlmKGNhbWVyYS5fb3J0aG8pIHtcbiAgICAgIHZhciBzID0gKGR4ID4gZHkpID8gMS4xIDogMS4wIC8gMS4xXG5cbiAgICAgIHNjZW5lLmFzcGVjdFswXSAqPSBzXG4gICAgICBzY2VuZS5hc3BlY3RbMV0gKj0gc1xuICAgICAgc2NlbmUuYXNwZWN0WzJdICo9IHNcbiAgICAgIHNjZW5lLnJlZHJhdygpXG4gICAgfVxuICB9LCB0cnVlKVxuXG4gIC8vVXBkYXRlIG1vdXNlIHBvc2l0aW9uXG4gIHNjZW5lLl9tb3VzZVJvdGF0aW5nID0gZmFsc2VcbiAgc2NlbmUuX3ByZXZCdXR0b25zID0gMFxuXG4gIHNjZW5lLmVuYWJsZU1vdXNlTGlzdGVuZXJzID0gZnVuY3Rpb24oKSB7XG5cbiAgICBzY2VuZS5tb3VzZUxpc3RlbmVyID0gbW91c2VDaGFuZ2UoY2FudmFzLCBmdW5jdGlvbihidXR0b25zLCB4LCB5KSB7XG4gICAgICBpZihzY2VuZS5fc3RvcHBlZCkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgdmFyIG51bVBpY2sgPSBwaWNrQnVmZmVycy5sZW5ndGhcbiAgICAgIHZhciBudW1PYmpzID0gb2JqZWN0cy5sZW5ndGhcbiAgICAgIHZhciBwcmV2T2JqID0gc2VsZWN0aW9uLm9iamVjdFxuXG4gICAgICBzZWxlY3Rpb24uZGlzdGFuY2UgPSBJbmZpbml0eVxuICAgICAgc2VsZWN0aW9uLm1vdXNlWzBdID0geFxuICAgICAgc2VsZWN0aW9uLm1vdXNlWzFdID0geVxuICAgICAgc2VsZWN0aW9uLm9iamVjdCA9IG51bGxcbiAgICAgIHNlbGVjdGlvbi5zY3JlZW4gPSBudWxsXG4gICAgICBzZWxlY3Rpb24uZGF0YUNvb3JkaW5hdGUgPSBzZWxlY3Rpb24uZGF0YVBvc2l0aW9uID0gbnVsbFxuXG4gICAgICB2YXIgY2hhbmdlID0gZmFsc2VcblxuICAgICAgaWYoYnV0dG9ucyAmJiBzY2VuZS5fcHJldkJ1dHRvbnMpIHtcbiAgICAgICAgc2NlbmUuX21vdXNlUm90YXRpbmcgPSB0cnVlXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZihzY2VuZS5fbW91c2VSb3RhdGluZykge1xuICAgICAgICAgIHBpY2tEaXJ0eSA9IHRydWVcbiAgICAgICAgfVxuICAgICAgICBzY2VuZS5fbW91c2VSb3RhdGluZyA9IGZhbHNlXG5cbiAgICAgICAgZm9yKHZhciBpPTA7IGk8bnVtUGljazsgKytpKSB7XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IHBpY2tCdWZmZXJzW2ldLnF1ZXJ5KHgsIHBpY2tTaGFwZVsxXSAtIHkgLSAxLCBzY2VuZS5waWNrUmFkaXVzKVxuICAgICAgICAgIGlmKHJlc3VsdCkge1xuICAgICAgICAgICAgaWYocmVzdWx0LmRpc3RhbmNlID4gc2VsZWN0aW9uLmRpc3RhbmNlKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IodmFyIGo9MDsgajxudW1PYmpzOyArK2opIHtcbiAgICAgICAgICAgICAgdmFyIG9iaiA9IG9iamVjdHNbal1cbiAgICAgICAgICAgICAgaWYocGlja0J1ZmZlcklkc1tqXSAhPT0gaSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdmFyIG9ialBpY2sgPSBvYmoucGljayhyZXN1bHQpXG4gICAgICAgICAgICAgIGlmKG9ialBpY2spIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24uYnV0dG9ucyAgICAgICAgPSBidXR0b25zXG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLnNjcmVlbiAgICAgICAgID0gcmVzdWx0LmNvb3JkXG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLmRpc3RhbmNlICAgICAgID0gcmVzdWx0LmRpc3RhbmNlXG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLm9iamVjdCAgICAgICAgID0gb2JqXG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLmluZGV4ICAgICAgICAgID0gb2JqUGljay5kaXN0YW5jZVxuICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5kYXRhUG9zaXRpb24gICA9IG9ialBpY2sucG9zaXRpb25cbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24uZGF0YUNvb3JkaW5hdGUgPSBvYmpQaWNrLmRhdGFDb29yZGluYXRlXG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLmRhdGEgICAgICAgICAgID0gb2JqUGlja1xuICAgICAgICAgICAgICAgIGNoYW5nZSA9IHRydWVcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZihwcmV2T2JqICYmIHByZXZPYmogIT09IHNlbGVjdGlvbi5vYmplY3QpIHtcbiAgICAgICAgaWYocHJldk9iai5oaWdobGlnaHQpIHtcbiAgICAgICAgICBwcmV2T2JqLmhpZ2hsaWdodChudWxsKVxuICAgICAgICB9XG4gICAgICAgIGRpcnR5ID0gdHJ1ZVxuICAgICAgfVxuICAgICAgaWYoc2VsZWN0aW9uLm9iamVjdCkge1xuICAgICAgICBpZihzZWxlY3Rpb24ub2JqZWN0LmhpZ2hsaWdodCkge1xuICAgICAgICAgIHNlbGVjdGlvbi5vYmplY3QuaGlnaGxpZ2h0KHNlbGVjdGlvbi5kYXRhKVxuICAgICAgICB9XG4gICAgICAgIGRpcnR5ID0gdHJ1ZVxuICAgICAgfVxuXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2UgfHwgKHNlbGVjdGlvbi5vYmplY3QgIT09IHByZXZPYmopXG4gICAgICBpZihjaGFuZ2UgJiYgc2NlbmUub25zZWxlY3QpIHtcbiAgICAgICAgc2NlbmUub25zZWxlY3Qoc2VsZWN0aW9uKVxuICAgICAgfVxuXG4gICAgICBpZigoYnV0dG9ucyAmIDEpICYmICEoc2NlbmUuX3ByZXZCdXR0b25zICYgMSkgJiYgc2NlbmUub25jbGljaykge1xuICAgICAgICBzY2VuZS5vbmNsaWNrKHNlbGVjdGlvbilcbiAgICAgIH1cbiAgICAgIHNjZW5lLl9wcmV2QnV0dG9ucyA9IGJ1dHRvbnNcbiAgICB9KVxuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2tDb250ZXh0TG9zcygpIHtcbiAgICBpZihzY2VuZS5jb250ZXh0TG9zdCkge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gICAgaWYoZ2wuaXNDb250ZXh0TG9zdCgpKSB7XG4gICAgICBzY2VuZS5jb250ZXh0TG9zdCA9IHRydWVcbiAgICAgIHNjZW5lLm1vdXNlTGlzdGVuZXIuZW5hYmxlZCA9IGZhbHNlXG4gICAgICBzY2VuZS5zZWxlY3Rpb24ub2JqZWN0ID0gbnVsbFxuICAgICAgaWYoc2NlbmUub25jb250ZXh0bG9zcykge1xuICAgICAgICBzY2VuZS5vbmNvbnRleHRsb3NzKClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0bG9zdCcsIGNoZWNrQ29udGV4dExvc3MpXG5cbiAgLy9SZW5kZXIgdGhlIHNjZW5lIGZvciBtb3VzZSBwaWNraW5nXG4gIGZ1bmN0aW9uIHJlbmRlclBpY2soKSB7XG4gICAgaWYoY2hlY2tDb250ZXh0TG9zcygpKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBnbC5jb2xvck1hc2sodHJ1ZSwgdHJ1ZSwgdHJ1ZSwgdHJ1ZSlcbiAgICBnbC5kZXB0aE1hc2sodHJ1ZSlcbiAgICBnbC5kaXNhYmxlKGdsLkJMRU5EKVxuICAgIGdsLmVuYWJsZShnbC5ERVBUSF9URVNUKVxuXG4gICAgdmFyIG51bU9ianMgPSBvYmplY3RzLmxlbmd0aFxuICAgIHZhciBudW1QaWNrID0gcGlja0J1ZmZlcnMubGVuZ3RoXG4gICAgZm9yKHZhciBqPTA7IGo8bnVtUGljazsgKytqKSB7XG4gICAgICB2YXIgYnVmID0gcGlja0J1ZmZlcnNbal1cbiAgICAgIGJ1Zi5zaGFwZSA9IHBpY2tTaGFwZVxuICAgICAgYnVmLmJlZ2luKClcbiAgICAgIGZvcih2YXIgaT0wOyBpPG51bU9ianM7ICsraSkge1xuICAgICAgICBpZihwaWNrQnVmZmVySWRzW2ldICE9PSBqKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgICB2YXIgb2JqID0gb2JqZWN0c1tpXVxuICAgICAgICBpZihvYmouZHJhd1BpY2spIHtcbiAgICAgICAgICBvYmoucGl4ZWxSYXRpbyA9IDFcbiAgICAgICAgICBvYmouZHJhd1BpY2soY2FtZXJhUGFyYW1zKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBidWYuZW5kKClcbiAgICB9XG4gIH1cblxuICB2YXIgbkJvdW5kcyA9IFtcbiAgICBbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldLFxuICAgIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV1dXG5cbiAgdmFyIHByZXZCb3VuZHMgPSBbbkJvdW5kc1swXS5zbGljZSgpLCBuQm91bmRzWzFdLnNsaWNlKCldXG5cbiAgZnVuY3Rpb24gcmVkcmF3KCkge1xuICAgIGlmKGNoZWNrQ29udGV4dExvc3MoKSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgcmVzaXplTGlzdGVuZXIoKVxuXG4gICAgLy9UaWNrIGNhbWVyYVxuICAgIHZhciBjYW1lcmFNb3ZlZCA9IHNjZW5lLmNhbWVyYS50aWNrKClcbiAgICBjYW1lcmFQYXJhbXMudmlldyA9IHNjZW5lLmNhbWVyYS5tYXRyaXhcbiAgICBkaXJ0eSAgICAgPSBkaXJ0eSB8fCBjYW1lcmFNb3ZlZFxuICAgIHBpY2tEaXJ0eSA9IHBpY2tEaXJ0eSB8fCBjYW1lcmFNb3ZlZFxuXG4gICAgICAvL1NldCBwaXhlbCByYXRpb1xuICAgIGF4ZXMucGl4ZWxSYXRpbyAgID0gc2NlbmUucGl4ZWxSYXRpb1xuICAgIHNwaWtlcy5waXhlbFJhdGlvID0gc2NlbmUucGl4ZWxSYXRpb1xuXG4gICAgLy9DaGVjayBpZiBhbnkgb2JqZWN0cyBjaGFuZ2VkLCByZWNhbGN1bGF0ZSBib3VuZHNcbiAgICB2YXIgbnVtT2JqcyA9IG9iamVjdHMubGVuZ3RoXG4gICAgdmFyIGxvID0gbkJvdW5kc1swXVxuICAgIHZhciBoaSA9IG5Cb3VuZHNbMV1cbiAgICBsb1swXSA9IGxvWzFdID0gbG9bMl0gPSAgSW5maW5pdHlcbiAgICBoaVswXSA9IGhpWzFdID0gaGlbMl0gPSAtSW5maW5pdHlcbiAgICBmb3IodmFyIGk9MDsgaTxudW1PYmpzOyArK2kpIHtcbiAgICAgIHZhciBvYmogPSBvYmplY3RzW2ldXG5cbiAgICAgIC8vU2V0IHRoZSBheGVzIHByb3BlcnRpZXMgZm9yIGVhY2ggb2JqZWN0XG4gICAgICBvYmoucGl4ZWxSYXRpbyA9IHNjZW5lLnBpeGVsUmF0aW9cbiAgICAgIG9iai5heGVzID0gc2NlbmUuYXhlc1xuXG4gICAgICBkaXJ0eSA9IGRpcnR5IHx8ICEhb2JqLmRpcnR5XG4gICAgICBwaWNrRGlydHkgPSBwaWNrRGlydHkgfHwgISFvYmouZGlydHlcbiAgICAgIHZhciBvYmIgPSBvYmouYm91bmRzXG4gICAgICBpZihvYmIpIHtcbiAgICAgICAgdmFyIG9sbyA9IG9iYlswXVxuICAgICAgICB2YXIgb2hpID0gb2JiWzFdXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgICAgIGxvW2pdID0gTWF0aC5taW4obG9bal0sIG9sb1tqXSlcbiAgICAgICAgICBoaVtqXSA9IE1hdGgubWF4KGhpW2pdLCBvaGlbal0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvL1JlY2FsY3VsYXRlIGJvdW5kc1xuICAgIHZhciBib3VuZHMgPSBzY2VuZS5ib3VuZHNcbiAgICBpZihzY2VuZS5hdXRvQm91bmRzKSB7XG4gICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgaWYoaGlbal0gPCBsb1tqXSkge1xuICAgICAgICAgIGxvW2pdID0gLTFcbiAgICAgICAgICBoaVtqXSA9IDFcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZihsb1tqXSA9PT0gaGlbal0pIHtcbiAgICAgICAgICAgIGxvW2pdIC09IDFcbiAgICAgICAgICAgIGhpW2pdICs9IDFcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHBhZGRpbmcgPSAwLjA1ICogKGhpW2pdIC0gbG9bal0pXG4gICAgICAgICAgbG9bal0gPSBsb1tqXSAtIHBhZGRpbmdcbiAgICAgICAgICBoaVtqXSA9IGhpW2pdICsgcGFkZGluZ1xuICAgICAgICB9XG4gICAgICAgIGJvdW5kc1swXVtqXSA9IGxvW2pdXG4gICAgICAgIGJvdW5kc1sxXVtqXSA9IGhpW2pdXG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGJvdW5kc0NoYW5nZWQgPSBmYWxzZVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgICBib3VuZHNDaGFuZ2VkID0gYm91bmRzQ2hhbmdlZCB8fFxuICAgICAgICAgICAgKHByZXZCb3VuZHNbMF1bal0gIT09IGJvdW5kc1swXVtqXSkgIHx8XG4gICAgICAgICAgICAocHJldkJvdW5kc1sxXVtqXSAhPT0gYm91bmRzWzFdW2pdKVxuICAgICAgICBwcmV2Qm91bmRzWzBdW2pdID0gYm91bmRzWzBdW2pdXG4gICAgICAgIHByZXZCb3VuZHNbMV1bal0gPSBib3VuZHNbMV1bal1cbiAgICB9XG5cbiAgICAvL1JlY2FsY3VsYXRlIGJvdW5kc1xuICAgIHBpY2tEaXJ0eSA9IHBpY2tEaXJ0eSB8fCBib3VuZHNDaGFuZ2VkXG4gICAgZGlydHkgPSBkaXJ0eSB8fCBib3VuZHNDaGFuZ2VkXG5cbiAgICBpZighZGlydHkpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmKGJvdW5kc0NoYW5nZWQpIHtcbiAgICAgIHZhciB0aWNrU3BhY2luZyA9IFswLDAsMF1cbiAgICAgIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgICAgICB0aWNrU3BhY2luZ1tpXSA9IHJvdW5kVXBQb3cxMCgoYm91bmRzWzFdW2ldLWJvdW5kc1swXVtpXSkgLyAxMC4wKVxuICAgICAgfVxuICAgICAgaWYoYXhlcy5hdXRvVGlja3MpIHtcbiAgICAgICAgYXhlcy51cGRhdGUoe1xuICAgICAgICAgIGJvdW5kczogYm91bmRzLFxuICAgICAgICAgIHRpY2tTcGFjaW5nOiB0aWNrU3BhY2luZ1xuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXhlcy51cGRhdGUoe1xuICAgICAgICAgIGJvdW5kczogYm91bmRzXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy9HZXQgc2NlbmVcbiAgICB2YXIgd2lkdGggID0gZ2wuZHJhd2luZ0J1ZmZlcldpZHRoXG4gICAgdmFyIGhlaWdodCA9IGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRcbiAgICB2aWV3U2hhcGVbMF0gPSB3aWR0aFxuICAgIHZpZXdTaGFwZVsxXSA9IGhlaWdodFxuICAgIHBpY2tTaGFwZVswXSA9IE1hdGgubWF4KHdpZHRoL3NjZW5lLnBpeGVsUmF0aW8sIDEpfDBcbiAgICBwaWNrU2hhcGVbMV0gPSBNYXRoLm1heChoZWlnaHQvc2NlbmUucGl4ZWxSYXRpbywgMSl8MFxuXG4gICAgLy9Db21wdXRlIGNhbWVyYSBwYXJhbWV0ZXJzXG5cbiAgICBpZihpc09ydGhvKSB7XG4gICAgICBvcnRobyhwcm9qZWN0aW9uLFxuICAgICAgICAtd2lkdGgvaGVpZ2h0LFxuICAgICAgICB3aWR0aC9oZWlnaHQsXG4gICAgICAgIC0xLFxuICAgICAgICAxLFxuICAgICAgICBzY2VuZS56TmVhcixcbiAgICAgICAgc2NlbmUuekZhclxuICAgICAgKVxuICAgICAgY2FtZXJhUGFyYW1zLl9vcnRobyA9IHRydWVcbiAgICB9IGVsc2Uge1xuICAgICAgcGVyc3BlY3RpdmUocHJvamVjdGlvbixcbiAgICAgICAgc2NlbmUuZm92eSxcbiAgICAgICAgd2lkdGgvaGVpZ2h0LFxuICAgICAgICBzY2VuZS56TmVhcixcbiAgICAgICAgc2NlbmUuekZhclxuICAgICAgKVxuICAgICAgY2FtZXJhUGFyYW1zLl9vcnRobyA9IGZhbHNlXG4gICAgfVxuXG4gICAgLy9Db21wdXRlIG1vZGVsIG1hdHJpeFxuICAgIGZvcih2YXIgaT0wOyBpPDE2OyArK2kpIHtcbiAgICAgIG1vZGVsW2ldID0gMFxuICAgIH1cbiAgICBtb2RlbFsxNV0gPSAxXG5cbiAgICB2YXIgbWF4UyA9IDBcbiAgICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICAgIG1heFMgPSBNYXRoLm1heChtYXhTLCBib3VuZHNbMV1baV0gLSBib3VuZHNbMF1baV0pXG4gICAgfVxuXG4gICAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgICBpZihzY2VuZS5hdXRvU2NhbGUpIHtcbiAgICAgICAgbW9kZWxbNSppXSA9IHNjZW5lLmFzcGVjdFtpXSAvIChib3VuZHNbMV1baV0gLSBib3VuZHNbMF1baV0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtb2RlbFs1KmldID0gMSAgLyBtYXhTXG4gICAgICB9XG4gICAgICBpZihzY2VuZS5hdXRvQ2VudGVyKSB7XG4gICAgICAgIG1vZGVsWzEyK2ldID0gLW1vZGVsWzUqaV0gKiAwLjUgKiAoYm91bmRzWzBdW2ldICsgYm91bmRzWzFdW2ldKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vQXBwbHkgYXhlcy9jbGlwIGJvdW5kc1xuICAgIGZvcih2YXIgaT0wOyBpPG51bU9ianM7ICsraSkge1xuICAgICAgdmFyIG9iaiA9IG9iamVjdHNbaV1cblxuICAgICAgLy9TZXQgYXhlcyBib3VuZHNcbiAgICAgIG9iai5heGVzQm91bmRzID0gYm91bmRzXG5cbiAgICAgIC8vU2V0IGNsaXAgYm91bmRzXG4gICAgICBpZihzY2VuZS5jbGlwVG9Cb3VuZHMpIHtcbiAgICAgICAgb2JqLmNsaXBCb3VuZHMgPSBib3VuZHNcbiAgICAgIH1cbiAgICB9XG4gICAgLy9TZXQgc3Bpa2UgcGFyYW1ldGVyc1xuICAgIGlmKHNlbGVjdGlvbi5vYmplY3QpIHtcbiAgICAgIGlmKHNjZW5lLnNuYXBUb0RhdGEpIHtcbiAgICAgICAgc3Bpa2VzLnBvc2l0aW9uID0gc2VsZWN0aW9uLmRhdGFDb29yZGluYXRlXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzcGlrZXMucG9zaXRpb24gPSBzZWxlY3Rpb24uZGF0YVBvc2l0aW9uXG4gICAgICB9XG4gICAgICBzcGlrZXMuYm91bmRzID0gYm91bmRzXG4gICAgfVxuXG4gICAgLy9JZiBzdGF0ZSBjaGFuZ2VkLCB0aGVuIHJlZHJhdyBwaWNrIGJ1ZmZlcnNcbiAgICBpZihwaWNrRGlydHkpIHtcbiAgICAgIHBpY2tEaXJ0eSA9IGZhbHNlXG4gICAgICByZW5kZXJQaWNrKClcbiAgICB9XG5cbiAgICAvL1JlY2FsY3VsYXRlIHBpeGVsIGRhdGFcbiAgICBzY2VuZS5heGVzUGl4ZWxzID0gYXhlc1JhbmdlcyhzY2VuZS5heGVzLCBjYW1lcmFQYXJhbXMsIHdpZHRoLCBoZWlnaHQpXG5cbiAgICAvL0NhbGwgcmVuZGVyIGNhbGxiYWNrXG4gICAgaWYoc2NlbmUub25yZW5kZXIpIHtcbiAgICAgIHNjZW5lLm9ucmVuZGVyKClcbiAgICB9XG5cbiAgICAvL1JlYWQgdmFsdWVcbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpXG4gICAgZ2wudmlld3BvcnQoMCwgMCwgd2lkdGgsIGhlaWdodClcblxuICAgIC8vR2VuZXJhbCBzdHJhdGVneTogMyBzdGVwc1xuICAgIC8vICAxLiByZW5kZXIgbm9uLXRyYW5zcGFyZW50IG9iamVjdHNcbiAgICAvLyAgMi4gYWNjdW11bGF0ZSB0cmFuc3BhcmVudCBvYmplY3RzIGludG8gc2VwYXJhdGUgZmJvXG4gICAgLy8gIDMuIGNvbXBvc2l0ZSBmaW5hbCBzY2VuZVxuXG4gICAgLy9DbGVhciBGQk9cbiAgICB2YXIgY2xlYXJDb2xvciA9IHNjZW5lLmNsZWFyQ29sb3JcbiAgICBnbC5jbGVhckNvbG9yKGNsZWFyQ29sb3JbMF0sIGNsZWFyQ29sb3JbMV0sIGNsZWFyQ29sb3JbMl0sIGNsZWFyQ29sb3JbM10pXG4gICAgZ2wuY2xlYXIoZ2wuQ09MT1JfQlVGRkVSX0JJVCB8IGdsLkRFUFRIX0JVRkZFUl9CSVQpXG4gICAgZ2wuZGVwdGhNYXNrKHRydWUpXG4gICAgZ2wuY29sb3JNYXNrKHRydWUsIHRydWUsIHRydWUsIHRydWUpXG4gICAgZ2wuZW5hYmxlKGdsLkRFUFRIX1RFU1QpXG4gICAgZ2wuZGVwdGhGdW5jKGdsLkxFUVVBTClcbiAgICBnbC5kaXNhYmxlKGdsLkJMRU5EKVxuICAgIGdsLmRpc2FibGUoZ2wuQ1VMTF9GQUNFKSAgLy9tb3N0IHZpc3VhbGl6YXRpb24gc3VyZmFjZXMgYXJlIDIgc2lkZWRcblxuICAgIC8vUmVuZGVyIG9wYXF1ZSBwYXNzXG4gICAgdmFyIGhhc1RyYW5zcGFyZW50ID0gZmFsc2VcbiAgICBpZihheGVzLmVuYWJsZSkge1xuICAgICAgaGFzVHJhbnNwYXJlbnQgPSBoYXNUcmFuc3BhcmVudCB8fCBheGVzLmlzVHJhbnNwYXJlbnQoKVxuICAgICAgYXhlcy5kcmF3KGNhbWVyYVBhcmFtcylcbiAgICB9XG4gICAgc3Bpa2VzLmF4ZXMgPSBheGVzXG4gICAgaWYoc2VsZWN0aW9uLm9iamVjdCkge1xuICAgICAgc3Bpa2VzLmRyYXcoY2FtZXJhUGFyYW1zKVxuICAgIH1cblxuICAgIGdsLmRpc2FibGUoZ2wuQ1VMTF9GQUNFKSAgLy9tb3N0IHZpc3VhbGl6YXRpb24gc3VyZmFjZXMgYXJlIDIgc2lkZWRcblxuICAgIGZvcih2YXIgaT0wOyBpPG51bU9ianM7ICsraSkge1xuICAgICAgdmFyIG9iaiA9IG9iamVjdHNbaV1cbiAgICAgIG9iai5heGVzID0gYXhlc1xuICAgICAgb2JqLnBpeGVsUmF0aW8gPSBzY2VuZS5waXhlbFJhdGlvXG4gICAgICBpZihvYmouaXNPcGFxdWUgJiYgb2JqLmlzT3BhcXVlKCkpIHtcbiAgICAgICAgb2JqLmRyYXcoY2FtZXJhUGFyYW1zKVxuICAgICAgfVxuICAgICAgaWYob2JqLmlzVHJhbnNwYXJlbnQgJiYgb2JqLmlzVHJhbnNwYXJlbnQoKSkge1xuICAgICAgICBoYXNUcmFuc3BhcmVudCA9IHRydWVcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZihoYXNUcmFuc3BhcmVudCkge1xuICAgICAgLy9SZW5kZXIgdHJhbnNwYXJlbnQgcGFzc1xuICAgICAgYWNjdW1CdWZmZXIuc2hhcGUgPSB2aWV3U2hhcGVcbiAgICAgIGFjY3VtQnVmZmVyLmJpbmQoKVxuICAgICAgZ2wuY2xlYXIoZ2wuREVQVEhfQlVGRkVSX0JJVClcbiAgICAgIGdsLmNvbG9yTWFzayhmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSlcbiAgICAgIGdsLmRlcHRoTWFzayh0cnVlKVxuICAgICAgZ2wuZGVwdGhGdW5jKGdsLkxFU1MpXG5cbiAgICAgIC8vUmVuZGVyIGZvcndhcmQgZmFjaW5nIG9iamVjdHNcbiAgICAgIGlmKGF4ZXMuZW5hYmxlICYmIGF4ZXMuaXNUcmFuc3BhcmVudCgpKSB7XG4gICAgICAgIGF4ZXMuZHJhd1RyYW5zcGFyZW50KGNhbWVyYVBhcmFtcylcbiAgICAgIH1cbiAgICAgIGZvcih2YXIgaT0wOyBpPG51bU9ianM7ICsraSkge1xuICAgICAgICB2YXIgb2JqID0gb2JqZWN0c1tpXVxuICAgICAgICBpZihvYmouaXNPcGFxdWUgJiYgb2JqLmlzT3BhcXVlKCkpIHtcbiAgICAgICAgICBvYmouZHJhdyhjYW1lcmFQYXJhbXMpXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy9SZW5kZXIgdHJhbnNwYXJlbnQgcGFzc1xuICAgICAgZ2wuZW5hYmxlKGdsLkJMRU5EKVxuICAgICAgZ2wuYmxlbmRFcXVhdGlvbihnbC5GVU5DX0FERClcbiAgICAgIGdsLmJsZW5kRnVuYyhnbC5PTkUsIGdsLk9ORV9NSU5VU19TUkNfQUxQSEEpXG4gICAgICBnbC5jb2xvck1hc2sodHJ1ZSwgdHJ1ZSwgdHJ1ZSwgdHJ1ZSlcbiAgICAgIGdsLmRlcHRoTWFzayhmYWxzZSlcbiAgICAgIGdsLmNsZWFyQ29sb3IoMCwwLDAsMClcbiAgICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQpXG5cbiAgICAgIGlmKGF4ZXMuaXNUcmFuc3BhcmVudCgpKSB7XG4gICAgICAgIGF4ZXMuZHJhd1RyYW5zcGFyZW50KGNhbWVyYVBhcmFtcylcbiAgICAgIH1cblxuICAgICAgZm9yKHZhciBpPTA7IGk8bnVtT2JqczsgKytpKSB7XG4gICAgICAgIHZhciBvYmogPSBvYmplY3RzW2ldXG4gICAgICAgIGlmKG9iai5pc1RyYW5zcGFyZW50ICYmIG9iai5pc1RyYW5zcGFyZW50KCkpIHtcbiAgICAgICAgICBvYmouZHJhd1RyYW5zcGFyZW50KGNhbWVyYVBhcmFtcylcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvL1VuYmluZCBmcmFtZWJ1ZmZlclxuICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBudWxsKVxuXG4gICAgICAvL0RyYXcgY29tcG9zaXRlIHBhc3NcbiAgICAgIGdsLmJsZW5kRnVuYyhnbC5PTkUsIGdsLk9ORV9NSU5VU19TUkNfQUxQSEEpXG4gICAgICBnbC5kaXNhYmxlKGdsLkRFUFRIX1RFU1QpXG4gICAgICBhY2N1bVNoYWRlci5iaW5kKClcbiAgICAgIGFjY3VtQnVmZmVyLmNvbG9yWzBdLmJpbmQoMClcbiAgICAgIGFjY3VtU2hhZGVyLnVuaWZvcm1zLmFjY3VtQnVmZmVyID0gMFxuICAgICAgZHJhd1RyaWFuZ2xlKGdsKVxuXG4gICAgICAvL1R1cm4gb2ZmIGJsZW5kaW5nXG4gICAgICBnbC5kaXNhYmxlKGdsLkJMRU5EKVxuICAgIH1cblxuICAgIC8vQ2xlYXIgZGlydHkgZmxhZ3NcbiAgICBkaXJ0eSA9IGZhbHNlXG4gICAgZm9yKHZhciBpPTA7IGk8bnVtT2JqczsgKytpKSB7XG4gICAgICBvYmplY3RzW2ldLmRpcnR5ID0gZmFsc2VcbiAgICB9XG4gIH1cblxuICAvL0RyYXcgdGhlIHdob2xlIHNjZW5lXG4gIGZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgICBpZihzY2VuZS5fc3RvcHBlZCB8fCBzY2VuZS5jb250ZXh0TG9zdCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIC8vIHRoaXMgb3JkZXIgaXMgaW1wb3J0YW50OiBpb3Mgc2FmYXJpIHNvbWV0aW1lcyBoYXMgc3luYyByYWZcbiAgICByZWRyYXcoKVxuICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShyZW5kZXIpXG4gIH1cblxuICBzY2VuZS5lbmFibGVNb3VzZUxpc3RlbmVycygpXG4gIHJlbmRlcigpXG5cbiAgLy9Gb3JjZSByZWRyYXcgb2Ygd2hvbGUgc2NlbmVcbiAgc2NlbmUucmVkcmF3ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYoc2NlbmUuX3N0b3BwZWQpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBkaXJ0eSA9IHRydWVcbiAgICByZWRyYXcoKVxuICB9XG5cbiAgcmV0dXJuIHNjZW5lXG59XG5cbn0se1wiLi9jYW1lcmEuanNcIjoyODgsXCIuL2xpYi9zaGFkZXJcIjoyODksXCJhLWJpZy10cmlhbmdsZVwiOjU5LFwiZ2wtYXhlczNkXCI6MjMzLFwiZ2wtYXhlczNkL3Byb3BlcnRpZXNcIjoyNDAsXCJnbC1mYm9cIjoyNDksXCJnbC1tYXQ0L29ydGhvXCI6MjY4LFwiZ2wtbWF0NC9wZXJzcGVjdGl2ZVwiOjI2OSxcImdsLXNlbGVjdC1zdGF0aWNcIjozMDAsXCJnbC1zcGlrZXMzZFwiOjMxMCxcImlzLW1vYmlsZVwiOjQyMCxcIm1vdXNlLWNoYW5nZVwiOjQzNSxcIm1vdXNlLXdoZWVsXCI6NDM4fV0sMjkxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciBnbHNsaWZ5ID0gX2RlcmVxXygnZ2xzbGlmeScpXG5cbmV4cG9ydHMucG9pbnRWZXJ0ZXggICAgICAgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzIgcG9zaXRpb247XFxuXFxudW5pZm9ybSBtYXQzIG1hdHJpeDtcXG51bmlmb3JtIGZsb2F0IHBvaW50U2l6ZTtcXG51bmlmb3JtIGZsb2F0IHBvaW50Q2xvdWQ7XFxuXFxuaGlnaHAgZmxvYXQgcmFuZCh2ZWMyIGNvKSB7XFxuICBoaWdocCBmbG9hdCBhID0gMTIuOTg5ODtcXG4gIGhpZ2hwIGZsb2F0IGIgPSA3OC4yMzM7XFxuICBoaWdocCBmbG9hdCBjID0gNDM3NTguNTQ1MztcXG4gIGhpZ2hwIGZsb2F0IGQgPSBkb3QoY28ueHksIHZlYzIoYSwgYikpO1xcbiAgaGlnaHAgZmxvYXQgZSA9IG1vZChkLCAzLjE0KTtcXG4gIHJldHVybiBmcmFjdChzaW4oZSkgKiBjKTtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMyBoZ1Bvc2l0aW9uID0gbWF0cml4ICogdmVjMyhwb3NpdGlvbiwgMSk7XFxuICBnbF9Qb3NpdGlvbiAgPSB2ZWM0KGhnUG9zaXRpb24ueHksIDAsIGhnUG9zaXRpb24ueik7XFxuICAgIC8vIGlmIHdlIGRvbid0IGppdHRlciB0aGUgcG9pbnQgc2l6ZSBhIGJpdCwgb3ZlcmFsbCBwb2ludCBjbG91ZFxcbiAgICAvLyBzYXR1cmF0aW9uICdqdW1wcycgb24gem9vbWluZywgd2hpY2ggaXMgZGlzdHVyYmluZyBhbmQgY29uZnVzaW5nXFxuICBnbF9Qb2ludFNpemUgPSBwb2ludFNpemUgKiAoKDE5LjUgKyByYW5kKHBvc2l0aW9uKSkgLyAyMC4wKTtcXG4gIGlmKHBvaW50Q2xvdWQgIT0gMC4wKSB7IC8vIHBvaW50Q2xvdWQgaXMgdHJ1dGh5XFxuICAgIC8vIGdldCB0aGUgc2FtZSBzcXVhcmUgc3VyZmFjZSBhcyBjaXJjbGUgd291bGQgYmVcXG4gICAgZ2xfUG9pbnRTaXplICo9IDAuODg2O1xcbiAgfVxcbn1cIl0pXG5leHBvcnRzLnBvaW50RnJhZ21lbnQgICAgID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbnVuaWZvcm0gdmVjNCBjb2xvciwgYm9yZGVyQ29sb3I7XFxudW5pZm9ybSBmbG9hdCBjZW50ZXJGcmFjdGlvbjtcXG51bmlmb3JtIGZsb2F0IHBvaW50Q2xvdWQ7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgZmxvYXQgcmFkaXVzO1xcbiAgdmVjNCBiYXNlQ29sb3I7XFxuICBpZihwb2ludENsb3VkICE9IDAuMCkgeyAvLyBwb2ludENsb3VkIGlzIHRydXRoeVxcbiAgICBpZihjZW50ZXJGcmFjdGlvbiA9PSAxLjApIHtcXG4gICAgICBnbF9GcmFnQ29sb3IgPSBjb2xvcjtcXG4gICAgfSBlbHNlIHtcXG4gICAgICBnbF9GcmFnQ29sb3IgPSBtaXgoYm9yZGVyQ29sb3IsIGNvbG9yLCBjZW50ZXJGcmFjdGlvbik7XFxuICAgIH1cXG4gIH0gZWxzZSB7XFxuICAgIHJhZGl1cyA9IGxlbmd0aCgyLjAgKiBnbF9Qb2ludENvb3JkLnh5IC0gMS4wKTtcXG4gICAgaWYocmFkaXVzID4gMS4wKSB7XFxuICAgICAgZGlzY2FyZDtcXG4gICAgfVxcbiAgICBiYXNlQ29sb3IgPSBtaXgoYm9yZGVyQ29sb3IsIGNvbG9yLCBzdGVwKHJhZGl1cywgY2VudGVyRnJhY3Rpb24pKTtcXG4gICAgZ2xfRnJhZ0NvbG9yID0gdmVjNChiYXNlQ29sb3IucmdiICogYmFzZUNvbG9yLmEsIGJhc2VDb2xvci5hKTtcXG4gIH1cXG59XFxuXCJdKVxuZXhwb3J0cy5waWNrVmVydGV4ICAgICAgICA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMiBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjNCBwaWNrSWQ7XFxuXFxudW5pZm9ybSBtYXQzIG1hdHJpeDtcXG51bmlmb3JtIGZsb2F0IHBvaW50U2l6ZTtcXG51bmlmb3JtIHZlYzQgcGlja09mZnNldDtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzMgaGdQb3NpdGlvbiA9IG1hdHJpeCAqIHZlYzMocG9zaXRpb24sIDEpO1xcbiAgZ2xfUG9zaXRpb24gID0gdmVjNChoZ1Bvc2l0aW9uLnh5LCAwLCBoZ1Bvc2l0aW9uLnopO1xcbiAgZ2xfUG9pbnRTaXplID0gcG9pbnRTaXplO1xcblxcbiAgdmVjNCBpZCA9IHBpY2tJZCArIHBpY2tPZmZzZXQ7XFxuICBpZC55ICs9IGZsb29yKGlkLnggLyAyNTYuMCk7XFxuICBpZC54IC09IGZsb29yKGlkLnggLyAyNTYuMCkgKiAyNTYuMDtcXG5cXG4gIGlkLnogKz0gZmxvb3IoaWQueSAvIDI1Ni4wKTtcXG4gIGlkLnkgLT0gZmxvb3IoaWQueSAvIDI1Ni4wKSAqIDI1Ni4wO1xcblxcbiAgaWQudyArPSBmbG9vcihpZC56IC8gMjU2LjApO1xcbiAgaWQueiAtPSBmbG9vcihpZC56IC8gMjU2LjApICogMjU2LjA7XFxuXFxuICBmcmFnSWQgPSBpZDtcXG59XFxuXCJdKVxuZXhwb3J0cy5waWNrRnJhZ21lbnQgICAgICA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGZsb2F0IHJhZGl1cyA9IGxlbmd0aCgyLjAgKiBnbF9Qb2ludENvb3JkLnh5IC0gMS4wKTtcXG4gIGlmKHJhZGl1cyA+IDEuMCkge1xcbiAgICBkaXNjYXJkO1xcbiAgfVxcbiAgZ2xfRnJhZ0NvbG9yID0gZnJhZ0lkIC8gMjU1LjA7XFxufVxcblwiXSlcblxufSx7XCJnbHNsaWZ5XCI6NDA5fV0sMjkyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgY3JlYXRlU2hhZGVyID0gX2RlcmVxXygnZ2wtc2hhZGVyJylcbnZhciBjcmVhdGVCdWZmZXIgPSBfZGVyZXFfKCdnbC1idWZmZXInKVxuXG52YXIgcG9vbCA9IF9kZXJlcV8oJ3R5cGVkYXJyYXktcG9vbCcpXG5cbnZhciBTSEFERVJTID0gX2RlcmVxXygnLi9saWIvc2hhZGVyJylcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVQb2ludGNsb3VkMkRcblxuZnVuY3Rpb24gUG9pbnRjbG91ZDJEKHBsb3QsIG9mZnNldEJ1ZmZlciwgcGlja0J1ZmZlciwgc2hhZGVyLCBwaWNrU2hhZGVyKSB7XG4gIHRoaXMucGxvdCAgICAgICAgICAgPSBwbG90XG4gIHRoaXMub2Zmc2V0QnVmZmVyICAgPSBvZmZzZXRCdWZmZXJcbiAgdGhpcy5waWNrQnVmZmVyICAgICA9IHBpY2tCdWZmZXJcbiAgdGhpcy5zaGFkZXIgICAgICAgICA9IHNoYWRlclxuICB0aGlzLnBpY2tTaGFkZXIgICAgID0gcGlja1NoYWRlclxuICB0aGlzLnNpemVNaW4gICAgICAgID0gMC41XG4gIHRoaXMuc2l6ZU1pbkNhcCAgICAgPSAyXG4gIHRoaXMuc2l6ZU1heCAgICAgICAgPSAyMFxuICB0aGlzLmFyZWFSYXRpbyAgICAgID0gMS4wXG4gIHRoaXMucG9pbnRDb3VudCAgICAgPSAwXG4gIHRoaXMuY29sb3IgICAgICAgICAgPSBbMSwgMCwgMCwgMV1cbiAgdGhpcy5ib3JkZXJDb2xvciAgICA9IFswLCAwLCAwLCAxXVxuICB0aGlzLmJsZW5kICAgICAgICAgID0gZmFsc2VcbiAgdGhpcy5waWNrT2Zmc2V0ICAgICA9IDBcbiAgdGhpcy5wb2ludHMgICAgICAgICA9IG51bGxcbn1cblxudmFyIHByb3RvID0gUG9pbnRjbG91ZDJELnByb3RvdHlwZVxuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxuICB0aGlzLnBpY2tTaGFkZXIuZGlzcG9zZSgpXG4gIHRoaXMub2Zmc2V0QnVmZmVyLmRpc3Bvc2UoKVxuICB0aGlzLnBpY2tCdWZmZXIuZGlzcG9zZSgpXG4gIHRoaXMucGxvdC5yZW1vdmVPYmplY3QodGhpcylcbn1cblxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24ob3B0aW9ucykge1xuXG4gIHZhciBpXG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cblxuICBmdW5jdGlvbiBkZmx0KG9wdCwgdmFsdWUpIHtcbiAgICBpZihvcHQgaW4gb3B0aW9ucykge1xuICAgICAgcmV0dXJuIG9wdGlvbnNbb3B0XVxuICAgIH1cbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuXG4gIHRoaXMuc2l6ZU1pbiAgICAgID0gZGZsdCgnc2l6ZU1pbicsIDAuNSlcbiAgLy8gdGhpcy5zaXplTWluQ2FwICAgICAgPSBkZmx0KCdzaXplTWluQ2FwJywgMilcbiAgdGhpcy5zaXplTWF4ICAgICAgPSBkZmx0KCdzaXplTWF4JywgMjApXG4gIHRoaXMuY29sb3IgICAgICAgID0gZGZsdCgnY29sb3InLCBbMSwgMCwgMCwgMV0pLnNsaWNlKClcbiAgdGhpcy5hcmVhUmF0aW8gICAgPSBkZmx0KCdhcmVhUmF0aW8nLCAxKVxuICB0aGlzLmJvcmRlckNvbG9yICA9IGRmbHQoJ2JvcmRlckNvbG9yJywgWzAsIDAsIDAsIDFdKS5zbGljZSgpXG4gIHRoaXMuYmxlbmQgICAgICAgID0gZGZsdCgnYmxlbmQnLCBmYWxzZSlcblxuICAvL1VwZGF0ZSBwb2ludCBkYXRhXG5cbiAgLy8gQXR0ZW1wdCBzdHJhaWdodC10aHJvdWdoIHByb2Nlc3NpbmcgKFNUUCkgdG8gYXZvaWQgYWxsb2NhdGlvbiBhbmQgY29weVxuICAvLyBUT0RPIGV2ZW50dWFsbHkgYWJzdHJhY3Qgb3V0IFNUUCBsb2dpYywgbWF5YmUgaW50byBgcG9vbGAgb3IgYSBsYXllciBhYm92ZVxuICB2YXIgcG9pbnRDb3VudCA9IG9wdGlvbnMucG9zaXRpb25zLmxlbmd0aCA+Pj4gMVxuICB2YXIgZGF0YVN0cmFpZ2h0VGhyb3VnaCA9IG9wdGlvbnMucG9zaXRpb25zIGluc3RhbmNlb2YgRmxvYXQzMkFycmF5XG4gIHZhciBpZFN0cmFpZ2h0VGhyb3VnaCA9IG9wdGlvbnMuaWRUb0luZGV4IGluc3RhbmNlb2YgSW50MzJBcnJheSAmJiBvcHRpb25zLmlkVG9JbmRleC5sZW5ndGggPj0gcG9pbnRDb3VudCAvLyBwZXJtaXQgbGFyZ2VyIHRvIGhlbHAgcmV1c2VcblxuICB2YXIgZGF0YSAgICAgICAgICA9IG9wdGlvbnMucG9zaXRpb25zXG4gIHZhciBwYWNrZWQgICAgICAgID0gZGF0YVN0cmFpZ2h0VGhyb3VnaCA/IGRhdGEgOiBwb29sLm1hbGxvY0Zsb2F0MzIoZGF0YS5sZW5ndGgpXG4gIHZhciBwYWNrZWRJZCAgICAgID0gaWRTdHJhaWdodFRocm91Z2ggPyBvcHRpb25zLmlkVG9JbmRleCA6IHBvb2wubWFsbG9jSW50MzIocG9pbnRDb3VudClcblxuICBpZighZGF0YVN0cmFpZ2h0VGhyb3VnaCkge1xuICAgIHBhY2tlZC5zZXQoZGF0YSlcbiAgfVxuXG4gIGlmKCFpZFN0cmFpZ2h0VGhyb3VnaCkge1xuICAgIHBhY2tlZC5zZXQoZGF0YSlcbiAgICBmb3IoaSA9IDA7IGkgPCBwb2ludENvdW50OyBpKyspIHtcbiAgICAgIHBhY2tlZElkW2ldID0gaVxuICAgIH1cbiAgfVxuXG4gIHRoaXMucG9pbnRzICAgICAgID0gZGF0YVxuXG4gIHRoaXMub2Zmc2V0QnVmZmVyLnVwZGF0ZShwYWNrZWQpXG4gIHRoaXMucGlja0J1ZmZlci51cGRhdGUocGFja2VkSWQpXG5cbiAgaWYoIWRhdGFTdHJhaWdodFRocm91Z2gpIHtcbiAgICBwb29sLmZyZWUocGFja2VkKVxuICB9XG5cbiAgaWYoIWlkU3RyYWlnaHRUaHJvdWdoKSB7XG4gICAgcG9vbC5mcmVlKHBhY2tlZElkKVxuICB9XG5cbiAgdGhpcy5wb2ludENvdW50ID0gcG9pbnRDb3VudFxuICB0aGlzLnBpY2tPZmZzZXQgPSAwXG59XG5cbmZ1bmN0aW9uIGNvdW50KHBvaW50cywgZGF0YUJveCkge1xuICB2YXIgdmlzaWJsZVBvaW50Q291bnRFc3RpbWF0ZSA9IDBcbiAgdmFyIGxlbmd0aCA9IHBvaW50cy5sZW5ndGggPj4+IDFcbiAgdmFyIGlcbiAgZm9yKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgeCA9IHBvaW50c1tpICogMl1cbiAgICB2YXIgeSA9IHBvaW50c1tpICogMiArIDFdXG4gICAgaWYoeCA+PSBkYXRhQm94WzBdICYmIHggPD0gZGF0YUJveFsyXSAmJiB5ID49IGRhdGFCb3hbMV0gJiYgeSA8PSBkYXRhQm94WzNdKVxuICAgICAgdmlzaWJsZVBvaW50Q291bnRFc3RpbWF0ZSsrXG4gIH1cbiAgcmV0dXJuIHZpc2libGVQb2ludENvdW50RXN0aW1hdGVcbn1cblxucHJvdG8udW5pZmllZERyYXcgPSAoZnVuY3Rpb24oKSB7XG4gIHZhciBNQVRSSVggPSBbMSwgMCwgMCxcbiAgICAgICAgICAgICAgICAwLCAxLCAwLFxuICAgICAgICAgICAgICAgIDAsIDAsIDFdXG4gIHZhciBQSUNLX1ZFQzQgPSBbMCwgMCwgMCwgMF1cbnJldHVybiBmdW5jdGlvbihwaWNrT2Zmc2V0KSB7XG4gIHZhciBwaWNrID0gcGlja09mZnNldCAhPT0gdm9pZCgwKVxuXG4gIHZhciBzaGFkZXIgICAgICAgID0gcGljayA/IHRoaXMucGlja1NoYWRlciA6IHRoaXMuc2hhZGVyXG4gIHZhciBnbCAgICAgICAgICAgID0gdGhpcy5wbG90LmdsXG4gIHZhciBkYXRhQm94ICAgICAgID0gdGhpcy5wbG90LmRhdGFCb3hcblxuICBpZih0aGlzLnBvaW50Q291bnQgPT09IDApIHtcbiAgICByZXR1cm4gcGlja09mZnNldFxuICB9XG5cbiAgdmFyIGRhdGFYICAgPSBkYXRhQm94WzJdIC0gZGF0YUJveFswXVxuICB2YXIgZGF0YVkgICA9IGRhdGFCb3hbM10gLSBkYXRhQm94WzFdXG5cbiAgdmFyIHZpc2libGVQb2ludENvdW50RXN0aW1hdGUgPSBjb3VudCh0aGlzLnBvaW50cywgZGF0YUJveClcbiAgdmFyIGJhc2ljUG9pbnRTaXplID0gIHRoaXMucGxvdC5waWNrUGl4ZWxSYXRpbyAqIE1hdGgubWF4KE1hdGgubWluKHRoaXMuc2l6ZU1pbkNhcCwgdGhpcy5zaXplTWluKSwgTWF0aC5taW4odGhpcy5zaXplTWF4LCB0aGlzLnNpemVNYXggLyBNYXRoLnBvdyh2aXNpYmxlUG9pbnRDb3VudEVzdGltYXRlLCAwLjMzMzMzKSkpXG5cbiAgTUFUUklYWzBdID0gMi4wIC8gZGF0YVhcbiAgTUFUUklYWzRdID0gMi4wIC8gZGF0YVlcbiAgTUFUUklYWzZdID0gLTIuMCAqIGRhdGFCb3hbMF0gLyBkYXRhWCAtIDEuMFxuICBNQVRSSVhbN10gPSAtMi4wICogZGF0YUJveFsxXSAvIGRhdGFZIC0gMS4wXG5cbiAgdGhpcy5vZmZzZXRCdWZmZXIuYmluZCgpXG5cbiAgc2hhZGVyLmJpbmQoKVxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5wb2ludGVyKClcbiAgc2hhZGVyLnVuaWZvcm1zLm1hdHJpeCAgICAgID0gTUFUUklYXG4gIHNoYWRlci51bmlmb3Jtcy5jb2xvciAgICAgICA9IHRoaXMuY29sb3JcbiAgc2hhZGVyLnVuaWZvcm1zLmJvcmRlckNvbG9yID0gdGhpcy5ib3JkZXJDb2xvclxuICBzaGFkZXIudW5pZm9ybXMucG9pbnRDbG91ZCA9IGJhc2ljUG9pbnRTaXplIDwgNVxuICBzaGFkZXIudW5pZm9ybXMucG9pbnRTaXplID0gYmFzaWNQb2ludFNpemVcbiAgc2hhZGVyLnVuaWZvcm1zLmNlbnRlckZyYWN0aW9uID0gTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgTWF0aC5zcXJ0KDEgLSB0aGlzLmFyZWFSYXRpbykpKVxuXG4gIGlmKHBpY2spIHtcblxuICAgIFBJQ0tfVkVDNFswXSA9ICggcGlja09mZnNldCAgICAgICAgJiAweGZmKVxuICAgIFBJQ0tfVkVDNFsxXSA9ICgocGlja09mZnNldCA+PiA4KSAgJiAweGZmKVxuICAgIFBJQ0tfVkVDNFsyXSA9ICgocGlja09mZnNldCA+PiAxNikgJiAweGZmKVxuICAgIFBJQ0tfVkVDNFszXSA9ICgocGlja09mZnNldCA+PiAyNCkgJiAweGZmKVxuXG4gICAgdGhpcy5waWNrQnVmZmVyLmJpbmQoKVxuICAgIHNoYWRlci5hdHRyaWJ1dGVzLnBpY2tJZC5wb2ludGVyKGdsLlVOU0lHTkVEX0JZVEUpXG4gICAgc2hhZGVyLnVuaWZvcm1zLnBpY2tPZmZzZXQgPSBQSUNLX1ZFQzRcbiAgICB0aGlzLnBpY2tPZmZzZXQgPSBwaWNrT2Zmc2V0XG4gIH1cblxuICAvLyBXb3J0aCBzd2l0Y2hpbmcgdGhlc2Ugb2ZmLCBidXQgd2UgY2FuJ3QgbWFrZSBhc3N1bXB0aW9ucyBhYm91dCBvdGhlclxuICAvLyByZW5kZXJlcnMsIHNvIGxldCdzIHJlc3RvcmUgaXQgYWZ0ZXIgZWFjaCBkcmF3XG4gIHZhciBibGVuZCA9IGdsLmdldFBhcmFtZXRlcihnbC5CTEVORClcbiAgdmFyIGRpdGhlciA9IGdsLmdldFBhcmFtZXRlcihnbC5ESVRIRVIpXG5cbiAgaWYoYmxlbmQgJiYgIXRoaXMuYmxlbmQpXG4gICAgZ2wuZGlzYWJsZShnbC5CTEVORClcbiAgaWYoZGl0aGVyKVxuICAgIGdsLmRpc2FibGUoZ2wuRElUSEVSKVxuXG4gIGdsLmRyYXdBcnJheXMoZ2wuUE9JTlRTLCAwLCB0aGlzLnBvaW50Q291bnQpXG5cbiAgaWYoYmxlbmQgJiYgIXRoaXMuYmxlbmQpXG4gICAgZ2wuZW5hYmxlKGdsLkJMRU5EKVxuICBpZihkaXRoZXIpXG4gICAgZ2wuZW5hYmxlKGdsLkRJVEhFUilcblxuICByZXR1cm4gcGlja09mZnNldCArIHRoaXMucG9pbnRDb3VudFxufVxufSkoKVxuXG5wcm90by5kcmF3ID0gcHJvdG8udW5pZmllZERyYXdcbnByb3RvLmRyYXdQaWNrID0gcHJvdG8udW5pZmllZERyYXdcblxucHJvdG8ucGljayA9IGZ1bmN0aW9uKHgsIHksIHZhbHVlKSB7XG4gIHZhciBwaWNrT2Zmc2V0ID0gdGhpcy5waWNrT2Zmc2V0XG4gIHZhciBwb2ludENvdW50ID0gdGhpcy5wb2ludENvdW50XG4gIGlmKHZhbHVlIDwgcGlja09mZnNldCB8fCB2YWx1ZSA+PSBwaWNrT2Zmc2V0ICsgcG9pbnRDb3VudCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgdmFyIHBvaW50SWQgPSB2YWx1ZSAtIHBpY2tPZmZzZXRcbiAgdmFyIHBvaW50cyA9IHRoaXMucG9pbnRzXG4gIHJldHVybiB7XG4gICAgb2JqZWN0OiB0aGlzLFxuICAgIHBvaW50SWQ6IHBvaW50SWQsXG4gICAgZGF0YUNvb3JkOiBbcG9pbnRzWzIgKiBwb2ludElkXSwgcG9pbnRzWzIgKiBwb2ludElkICsgMV0gXVxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVBvaW50Y2xvdWQyRChwbG90LCBvcHRpb25zKSB7XG4gIHZhciBnbCA9IHBsb3QuZ2xcbiAgdmFyIGJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHBpY2tCdWZmZXIgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIFNIQURFUlMucG9pbnRWZXJ0ZXgsIFNIQURFUlMucG9pbnRGcmFnbWVudClcbiAgdmFyIHBpY2tTaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIFNIQURFUlMucGlja1ZlcnRleCwgU0hBREVSUy5waWNrRnJhZ21lbnQpXG5cbiAgdmFyIHJlc3VsdCA9IG5ldyBQb2ludGNsb3VkMkQocGxvdCwgYnVmZmVyLCBwaWNrQnVmZmVyLCBzaGFkZXIsIHBpY2tTaGFkZXIpXG4gIHJlc3VsdC51cGRhdGUob3B0aW9ucylcblxuICAvL1JlZ2lzdGVyIHdpdGggcGxvdFxuICBwbG90LmFkZE9iamVjdChyZXN1bHQpXG5cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG59LHtcIi4vbGliL3NoYWRlclwiOjI5MSxcImdsLWJ1ZmZlclwiOjI0MSxcImdsLXNoYWRlclwiOjMwMSxcInR5cGVkYXJyYXktcG9vbFwiOjU0NX1dLDI5MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHNsZXJwXG5cbi8qKlxuICogUGVyZm9ybXMgYSBzcGhlcmljYWwgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gcXVhdFxuICpcbiAqIEBwYXJhbSB7cXVhdH0gb3V0IHRoZSByZWNlaXZpbmcgcXVhdGVybmlvblxuICogQHBhcmFtIHtxdWF0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3F1YXR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7cXVhdH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHNsZXJwIChvdXQsIGEsIGIsIHQpIHtcbiAgLy8gYmVuY2htYXJrczpcbiAgLy8gICAgaHR0cDovL2pzcGVyZi5jb20vcXVhdGVybmlvbi1zbGVycC1pbXBsZW1lbnRhdGlvbnNcblxuICB2YXIgYXggPSBhWzBdLCBheSA9IGFbMV0sIGF6ID0gYVsyXSwgYXcgPSBhWzNdLFxuICAgIGJ4ID0gYlswXSwgYnkgPSBiWzFdLCBieiA9IGJbMl0sIGJ3ID0gYlszXVxuXG4gIHZhciBvbWVnYSwgY29zb20sIHNpbm9tLCBzY2FsZTAsIHNjYWxlMVxuXG4gIC8vIGNhbGMgY29zaW5lXG4gIGNvc29tID0gYXggKiBieCArIGF5ICogYnkgKyBheiAqIGJ6ICsgYXcgKiBid1xuICAvLyBhZGp1c3Qgc2lnbnMgKGlmIG5lY2Vzc2FyeSlcbiAgaWYgKGNvc29tIDwgMC4wKSB7XG4gICAgY29zb20gPSAtY29zb21cbiAgICBieCA9IC1ieFxuICAgIGJ5ID0gLWJ5XG4gICAgYnogPSAtYnpcbiAgICBidyA9IC1id1xuICB9XG4gIC8vIGNhbGN1bGF0ZSBjb2VmZmljaWVudHNcbiAgaWYgKCgxLjAgLSBjb3NvbSkgPiAwLjAwMDAwMSkge1xuICAgIC8vIHN0YW5kYXJkIGNhc2UgKHNsZXJwKVxuICAgIG9tZWdhID0gTWF0aC5hY29zKGNvc29tKVxuICAgIHNpbm9tID0gTWF0aC5zaW4ob21lZ2EpXG4gICAgc2NhbGUwID0gTWF0aC5zaW4oKDEuMCAtIHQpICogb21lZ2EpIC8gc2lub21cbiAgICBzY2FsZTEgPSBNYXRoLnNpbih0ICogb21lZ2EpIC8gc2lub21cbiAgfSBlbHNlIHtcbiAgICAvLyBcImZyb21cIiBhbmQgXCJ0b1wiIHF1YXRlcm5pb25zIGFyZSB2ZXJ5IGNsb3NlXG4gICAgLy8gIC4uLiBzbyB3ZSBjYW4gZG8gYSBsaW5lYXIgaW50ZXJwb2xhdGlvblxuICAgIHNjYWxlMCA9IDEuMCAtIHRcbiAgICBzY2FsZTEgPSB0XG4gIH1cbiAgLy8gY2FsY3VsYXRlIGZpbmFsIHZhbHVlc1xuICBvdXRbMF0gPSBzY2FsZTAgKiBheCArIHNjYWxlMSAqIGJ4XG4gIG91dFsxXSA9IHNjYWxlMCAqIGF5ICsgc2NhbGUxICogYnlcbiAgb3V0WzJdID0gc2NhbGUwICogYXogKyBzY2FsZTEgKiBielxuICBvdXRbM10gPSBzY2FsZTAgKiBhdyArIHNjYWxlMSAqIGJ3XG5cbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwyOTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGEpe1xuICByZXR1cm4gKCFhICYmIGEgIT09IDApID8gJycgOiBhLnRvU3RyaW5nKCk7XG59XG5cbn0se31dLDI5NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG52YXIgdmVjdG9yaXplVGV4dCA9IF9kZXJlcV8oXCJ2ZWN0b3JpemUtdGV4dFwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGdldEdseXBoXG5cbnZhciBHTFlQSF9DQUNIRSA9IHt9XG5cbmZ1bmN0aW9uIGdldEdseXBoKHN5bWJvbCwgZm9udCwgcGl4ZWxSYXRpbykge1xuICB2YXIgZm9udENhY2hlID0gR0xZUEhfQ0FDSEVbZm9udF1cbiAgaWYoIWZvbnRDYWNoZSkge1xuICAgIGZvbnRDYWNoZSA9IEdMWVBIX0NBQ0hFW2ZvbnRdID0ge31cbiAgfVxuICBpZihzeW1ib2wgaW4gZm9udENhY2hlKSB7XG4gICAgcmV0dXJuIGZvbnRDYWNoZVtzeW1ib2xdXG4gIH1cblxuICB2YXIgY29uZmlnID0ge1xuICAgIHRleHRBbGlnbjogXCJjZW50ZXJcIixcbiAgICB0ZXh0QmFzZWxpbmU6IFwibWlkZGxlXCIsXG4gICAgbGluZUhlaWdodDogMS4wLFxuICAgIGZvbnQ6IGZvbnQsXG4gICAgbGluZVNwYWNpbmc6IDEuMjUsXG4gICAgc3R5bGV0YWdzOiB7XG4gICAgICBicmVha2xpbmVzOnRydWUsXG4gICAgICBib2xkczogdHJ1ZSxcbiAgICAgIGl0YWxpY3M6IHRydWUsXG4gICAgICBzdWJzY3JpcHRzOnRydWUsXG4gICAgICBzdXBlcnNjcmlwdHM6dHJ1ZVxuICAgIH1cbiAgfVxuXG4gIC8vR2V0IGxpbmUgYW5kIHRyaWFuZ2xlIG1lc2hlcyBmb3IgZ2x5cGhcbiAgY29uZmlnLnRyaWFuZ2xlcyA9IHRydWVcbiAgdmFyIHRyaVN5bWJvbCA9IHZlY3Rvcml6ZVRleHQoc3ltYm9sLCBjb25maWcpXG4gIGNvbmZpZy50cmlhbmdsZXMgPSBmYWxzZVxuICB2YXIgbGluZVN5bWJvbCA9IHZlY3Rvcml6ZVRleHQoc3ltYm9sLCBjb25maWcpXG5cbiAgdmFyIGksIGpcblxuICBpZihwaXhlbFJhdGlvICYmIHBpeGVsUmF0aW8gIT09IDEpIHtcbiAgICBmb3IoaSA9IDA7IGkgPCB0cmlTeW1ib2wucG9zaXRpb25zLmxlbmd0aDsgKytpKXtcbiAgICAgIGZvcihqID0gMDsgaiA8IHRyaVN5bWJvbC5wb3NpdGlvbnNbaV0ubGVuZ3RoOyArK2ope1xuICAgICAgICB0cmlTeW1ib2wucG9zaXRpb25zW2ldW2pdIC89IHBpeGVsUmF0aW87XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgbGluZVN5bWJvbC5wb3NpdGlvbnMubGVuZ3RoOyArK2kpe1xuICAgICAgZm9yKGogPSAwOyBqIDwgbGluZVN5bWJvbC5wb3NpdGlvbnNbaV0ubGVuZ3RoOyArK2ope1xuICAgICAgICBsaW5lU3ltYm9sLnBvc2l0aW9uc1tpXVtqXSAvPSBwaXhlbFJhdGlvO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vQ2FsY3VsYXRlIGJvdW5kaW5nIGJveFxuICB2YXIgYm91bmRzID0gW1tJbmZpbml0eSxJbmZpbml0eV0sIFstSW5maW5pdHksLUluZmluaXR5XV1cbiAgdmFyIG4gPSBsaW5lU3ltYm9sLnBvc2l0aW9ucy5sZW5ndGhcbiAgZm9yKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgdmFyIHAgPSBsaW5lU3ltYm9sLnBvc2l0aW9uc1tpXVxuICAgIGZvcihqPTA7IGo8MjsgKytqKSB7XG4gICAgICBib3VuZHNbMF1bal0gPSBNYXRoLm1pbihib3VuZHNbMF1bal0sIHBbal0pXG4gICAgICBib3VuZHNbMV1bal0gPSBNYXRoLm1heChib3VuZHNbMV1bal0sIHBbal0pXG4gICAgfVxuICB9XG5cbiAgLy9TYXZlIGNhY2hlZCBzeW1ib2xcbiAgcmV0dXJuIGZvbnRDYWNoZVtzeW1ib2xdID0gW3RyaVN5bWJvbCwgbGluZVN5bWJvbCwgYm91bmRzXVxufVxufSx7XCJ2ZWN0b3JpemUtdGV4dFwiOjU1MH1dLDI5NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG52YXIgY3JlYXRlU2hhZGVyV3JhcHBlciA9IF9kZXJlcV8oJ2dsLXNoYWRlcicpXG52YXIgZ2xzbGlmeSA9IF9kZXJlcV8oJ2dsc2xpZnknKVxuXG52YXIgcGVyc3BlY3RpdmVWZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvcjtcXG5hdHRyaWJ1dGUgdmVjMiBnbHlwaDtcXG5hdHRyaWJ1dGUgdmVjNCBpZDtcXG5cXG51bmlmb3JtIHZlYzQgaGlnaGxpZ2h0SWQ7XFxudW5pZm9ybSBmbG9hdCBoaWdobGlnaHRTY2FsZTtcXG51bmlmb3JtIG1hdDQgbW9kZWwsIHZpZXcsIHByb2plY3Rpb247XFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxuXFxudmFyeWluZyB2ZWM0IGludGVycENvbG9yO1xcbnZhcnlpbmcgdmVjNCBwaWNrSWQ7XFxudmFyeWluZyB2ZWMzIGRhdGFDb29yZGluYXRlO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIHBvc2l0aW9uKSkge1xcblxcbiAgICBnbF9Qb3NpdGlvbiA9IHZlYzQoMCwwLDAsMCk7XFxuICB9IGVsc2Uge1xcbiAgICBmbG9hdCBzY2FsZSA9IDEuMDtcXG4gICAgaWYoZGlzdGFuY2UoaGlnaGxpZ2h0SWQsIGlkKSA8IDAuMDAwMSkge1xcbiAgICAgIHNjYWxlID0gaGlnaGxpZ2h0U2NhbGU7XFxuICAgIH1cXG5cXG4gICAgdmVjNCB3b3JsZFBvc2l0aW9uID0gbW9kZWwgKiB2ZWM0KHBvc2l0aW9uLCAxKTtcXG4gICAgdmVjNCB2aWV3UG9zaXRpb24gPSB2aWV3ICogd29ybGRQb3NpdGlvbjtcXG4gICAgdmlld1Bvc2l0aW9uID0gdmlld1Bvc2l0aW9uIC8gdmlld1Bvc2l0aW9uLnc7XFxuICAgIHZlYzQgY2xpcFBvc2l0aW9uID0gcHJvamVjdGlvbiAqICh2aWV3UG9zaXRpb24gKyBzY2FsZSAqIHZlYzQoZ2x5cGgueCwgLWdseXBoLnksIDAsIDApKTtcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSBjbGlwUG9zaXRpb247XFxuICAgIGludGVycENvbG9yID0gY29sb3I7XFxuICAgIHBpY2tJZCA9IGlkO1xcbiAgICBkYXRhQ29vcmRpbmF0ZSA9IHBvc2l0aW9uO1xcbiAgfVxcbn1cIl0pXG52YXIgb3J0aG9ncmFwaGljVmVydFNyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzQgY29sb3I7XFxuYXR0cmlidXRlIHZlYzIgZ2x5cGg7XFxuYXR0cmlidXRlIHZlYzQgaWQ7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMiBzY3JlZW5TaXplO1xcbnVuaWZvcm0gdmVjMyBjbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgaGlnaGxpZ2h0U2NhbGUsIHBpeGVsUmF0aW87XFxudW5pZm9ybSB2ZWM0IGhpZ2hsaWdodElkO1xcblxcbnZhcnlpbmcgdmVjNCBpbnRlcnBDb2xvcjtcXG52YXJ5aW5nIHZlYzQgcGlja0lkO1xcbnZhcnlpbmcgdmVjMyBkYXRhQ29vcmRpbmF0ZTtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBwb3NpdGlvbikpIHtcXG5cXG4gICAgZ2xfUG9zaXRpb24gPSB2ZWM0KDAsMCwwLDApO1xcbiAgfSBlbHNlIHtcXG4gICAgZmxvYXQgc2NhbGUgPSBwaXhlbFJhdGlvO1xcbiAgICBpZihkaXN0YW5jZShoaWdobGlnaHRJZC5iZ3IsIGlkLmJncikgPCAwLjAwMSkge1xcbiAgICAgIHNjYWxlICo9IGhpZ2hsaWdodFNjYWxlO1xcbiAgICB9XFxuXFxuICAgIHZlYzQgd29ybGRQb3NpdGlvbiA9IG1vZGVsICogdmVjNChwb3NpdGlvbiwgMS4wKTtcXG4gICAgdmVjNCB2aWV3UG9zaXRpb24gPSB2aWV3ICogd29ybGRQb3NpdGlvbjtcXG4gICAgdmVjNCBjbGlwUG9zaXRpb24gPSBwcm9qZWN0aW9uICogdmlld1Bvc2l0aW9uO1xcbiAgICBjbGlwUG9zaXRpb24gLz0gY2xpcFBvc2l0aW9uLnc7XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gY2xpcFBvc2l0aW9uICsgdmVjNChzY3JlZW5TaXplICogc2NhbGUgKiB2ZWMyKGdseXBoLngsIC1nbHlwaC55KSwgMC4wLCAwLjApO1xcbiAgICBpbnRlcnBDb2xvciA9IGNvbG9yO1xcbiAgICBwaWNrSWQgPSBpZDtcXG4gICAgZGF0YUNvb3JkaW5hdGUgPSBwb3NpdGlvbjtcXG4gIH1cXG59XCJdKVxudmFyIHByb2plY3Rpb25WZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG5hdHRyaWJ1dGUgdmVjMyBwb3NpdGlvbjtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvcjtcXG5hdHRyaWJ1dGUgdmVjMiBnbHlwaDtcXG5hdHRyaWJ1dGUgdmVjNCBpZDtcXG5cXG51bmlmb3JtIGZsb2F0IGhpZ2hsaWdodFNjYWxlO1xcbnVuaWZvcm0gdmVjNCBoaWdobGlnaHRJZDtcXG51bmlmb3JtIHZlYzMgYXhlc1syXTtcXG51bmlmb3JtIG1hdDQgbW9kZWwsIHZpZXcsIHByb2plY3Rpb247XFxudW5pZm9ybSB2ZWMyIHNjcmVlblNpemU7XFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxudW5pZm9ybSBmbG9hdCBzY2FsZSwgcGl4ZWxSYXRpbztcXG5cXG52YXJ5aW5nIHZlYzQgaW50ZXJwQ29sb3I7XFxudmFyeWluZyB2ZWM0IHBpY2tJZDtcXG52YXJ5aW5nIHZlYzMgZGF0YUNvb3JkaW5hdGU7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgaWYgKG91dE9mUmFuZ2UoY2xpcEJvdW5kc1swXSwgY2xpcEJvdW5kc1sxXSwgcG9zaXRpb24pKSB7XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gdmVjNCgwLDAsMCwwKTtcXG4gIH0gZWxzZSB7XFxuICAgIGZsb2F0IGxzY2FsZSA9IHBpeGVsUmF0aW8gKiBzY2FsZTtcXG4gICAgaWYoZGlzdGFuY2UoaGlnaGxpZ2h0SWQsIGlkKSA8IDAuMDAwMSkge1xcbiAgICAgIGxzY2FsZSAqPSBoaWdobGlnaHRTY2FsZTtcXG4gICAgfVxcblxcbiAgICB2ZWM0IGNsaXBDZW50ZXIgICA9IHByb2plY3Rpb24gKiB2aWV3ICogbW9kZWwgKiB2ZWM0KHBvc2l0aW9uLCAxKTtcXG4gICAgdmVjMyBkYXRhUG9zaXRpb24gPSBwb3NpdGlvbiArIDAuNSpsc2NhbGUqKGF4ZXNbMF0gKiBnbHlwaC54ICsgYXhlc1sxXSAqIGdseXBoLnkpICogY2xpcENlbnRlci53ICogc2NyZWVuU2l6ZS55O1xcbiAgICB2ZWM0IGNsaXBQb3NpdGlvbiA9IHByb2plY3Rpb24gKiB2aWV3ICogbW9kZWwgKiB2ZWM0KGRhdGFQb3NpdGlvbiwgMSk7XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gY2xpcFBvc2l0aW9uO1xcbiAgICBpbnRlcnBDb2xvciA9IGNvbG9yO1xcbiAgICBwaWNrSWQgPSBpZDtcXG4gICAgZGF0YUNvb3JkaW5hdGUgPSBkYXRhUG9zaXRpb247XFxuICB9XFxufVxcblwiXSlcbnZhciBkcmF3RnJhZ1NyYyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYm9vbCBvdXRPZlJhbmdlKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IHApIHtcXG4gIHJldHVybiAoKHAgPiBtYXgoYSwgYikpIHx8IFxcbiAgICAgICAgICAocCA8IG1pbihhLCBiKSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMiBhLCB2ZWMyIGIsIHZlYzIgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjMyBhLCB2ZWMzIGIsIHZlYzMgcCkge1xcbiAgcmV0dXJuIChvdXRPZlJhbmdlKGEueCwgYi54LCBwLngpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS55LCBiLnksIHAueSkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnosIGIueiwgcC56KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWM0IGEsIHZlYzQgYiwgdmVjNCBwKSB7XFxuICByZXR1cm4gb3V0T2ZSYW5nZShhLnh5eiwgYi54eXosIHAueHl6KTtcXG59XFxuXFxudW5pZm9ybSB2ZWMzIGZyYWdDbGlwQm91bmRzWzJdO1xcbnVuaWZvcm0gZmxvYXQgb3BhY2l0eTtcXG5cXG52YXJ5aW5nIHZlYzQgaW50ZXJwQ29sb3I7XFxudmFyeWluZyB2ZWMzIGRhdGFDb29yZGluYXRlO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGlmIChcXG4gICAgb3V0T2ZSYW5nZShmcmFnQ2xpcEJvdW5kc1swXSwgZnJhZ0NsaXBCb3VuZHNbMV0sIGRhdGFDb29yZGluYXRlKSB8fFxcbiAgICBpbnRlcnBDb2xvci5hICogb3BhY2l0eSA9PSAwLlxcbiAgKSBkaXNjYXJkO1xcbiAgZ2xfRnJhZ0NvbG9yID0gaW50ZXJwQ29sb3IgKiBvcGFjaXR5O1xcbn1cXG5cIl0pXG52YXIgcGlja0ZyYWdTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbnVuaWZvcm0gdmVjMyBmcmFnQ2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIGZsb2F0IHBpY2tHcm91cDtcXG5cXG52YXJ5aW5nIHZlYzQgcGlja0lkO1xcbnZhcnlpbmcgdmVjMyBkYXRhQ29vcmRpbmF0ZTtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShmcmFnQ2xpcEJvdW5kc1swXSwgZnJhZ0NsaXBCb3VuZHNbMV0sIGRhdGFDb29yZGluYXRlKSkgZGlzY2FyZDtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IHZlYzQocGlja0dyb3VwLCBwaWNrSWQuYmdyKTtcXG59XCJdKVxuXG52YXIgQVRUUklCVVRFUyA9IFtcbiAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXG4gIHtuYW1lOiAnY29sb3InLCB0eXBlOiAndmVjNCd9LFxuICB7bmFtZTogJ2dseXBoJywgdHlwZTogJ3ZlYzInfSxcbiAge25hbWU6ICdpZCcsIHR5cGU6ICd2ZWM0J31cbl1cblxudmFyIHBlcnNwZWN0aXZlID0ge1xuICAgIHZlcnRleDogcGVyc3BlY3RpdmVWZXJ0U3JjLFxuICAgIGZyYWdtZW50OiBkcmF3RnJhZ1NyYyxcbiAgICBhdHRyaWJ1dGVzOiBBVFRSSUJVVEVTXG4gIH0sXG4gIG9ydGhvID0ge1xuICAgIHZlcnRleDogb3J0aG9ncmFwaGljVmVydFNyYyxcbiAgICBmcmFnbWVudDogZHJhd0ZyYWdTcmMsXG4gICAgYXR0cmlidXRlczogQVRUUklCVVRFU1xuICB9LFxuICBwcm9qZWN0ID0ge1xuICAgIHZlcnRleDogcHJvamVjdGlvblZlcnRTcmMsXG4gICAgZnJhZ21lbnQ6IGRyYXdGcmFnU3JjLFxuICAgIGF0dHJpYnV0ZXM6IEFUVFJJQlVURVNcbiAgfSxcbiAgcGlja1BlcnNwZWN0aXZlID0ge1xuICAgIHZlcnRleDogcGVyc3BlY3RpdmVWZXJ0U3JjLFxuICAgIGZyYWdtZW50OiBwaWNrRnJhZ1NyYyxcbiAgICBhdHRyaWJ1dGVzOiBBVFRSSUJVVEVTXG4gIH0sXG4gIHBpY2tPcnRobyA9IHtcbiAgICB2ZXJ0ZXg6IG9ydGhvZ3JhcGhpY1ZlcnRTcmMsXG4gICAgZnJhZ21lbnQ6IHBpY2tGcmFnU3JjLFxuICAgIGF0dHJpYnV0ZXM6IEFUVFJJQlVURVNcbiAgfSxcbiAgcGlja1Byb2plY3QgPSB7XG4gICAgdmVydGV4OiBwcm9qZWN0aW9uVmVydFNyYyxcbiAgICBmcmFnbWVudDogcGlja0ZyYWdTcmMsXG4gICAgYXR0cmlidXRlczogQVRUUklCVVRFU1xuICB9XG5cbmZ1bmN0aW9uIGNyZWF0ZVNoYWRlcihnbCwgc3JjKSB7XG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXJXcmFwcGVyKGdsLCBzcmMpXG4gIHZhciBhdHRyID0gc2hhZGVyLmF0dHJpYnV0ZXNcbiAgYXR0ci5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcbiAgYXR0ci5jb2xvci5sb2NhdGlvbiA9IDFcbiAgYXR0ci5nbHlwaC5sb2NhdGlvbiA9IDJcbiAgYXR0ci5pZC5sb2NhdGlvbiA9IDNcbiAgcmV0dXJuIHNoYWRlclxufVxuXG5leHBvcnRzLmNyZWF0ZVBlcnNwZWN0aXZlID0gZnVuY3Rpb24oZ2wpIHtcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgcGVyc3BlY3RpdmUpXG59XG5leHBvcnRzLmNyZWF0ZU9ydGhvID0gZnVuY3Rpb24oZ2wpIHtcbiAgcmV0dXJuIGNyZWF0ZVNoYWRlcihnbCwgb3J0aG8pXG59XG5leHBvcnRzLmNyZWF0ZVByb2plY3QgPSBmdW5jdGlvbihnbCkge1xuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCBwcm9qZWN0KVxufVxuZXhwb3J0cy5jcmVhdGVQaWNrUGVyc3BlY3RpdmUgPSBmdW5jdGlvbihnbCkge1xuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCBwaWNrUGVyc3BlY3RpdmUpXG59XG5leHBvcnRzLmNyZWF0ZVBpY2tPcnRobyA9IGZ1bmN0aW9uKGdsKSB7XG4gIHJldHVybiBjcmVhdGVTaGFkZXIoZ2wsIHBpY2tPcnRobylcbn1cbmV4cG9ydHMuY3JlYXRlUGlja1Byb2plY3QgPSBmdW5jdGlvbihnbCkge1xuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCBwaWNrUHJvamVjdClcbn1cblxufSx7XCJnbC1zaGFkZXJcIjozMDEsXCJnbHNsaWZ5XCI6NDA5fV0sMjk3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgaXNBbGxCbGFuayAgICAgID0gX2RlcmVxXygnaXMtc3RyaW5nLWJsYW5rJylcbnZhciBjcmVhdGVCdWZmZXIgICAgPSBfZGVyZXFfKCdnbC1idWZmZXInKVxudmFyIGNyZWF0ZVZBTyAgICAgICA9IF9kZXJlcV8oJ2dsLXZhbycpXG52YXIgcG9vbCAgICAgICAgICAgID0gX2RlcmVxXygndHlwZWRhcnJheS1wb29sJylcbnZhciBtYXQ0bXVsdCAgICAgICAgPSBfZGVyZXFfKCdnbC1tYXQ0L211bHRpcGx5JylcbnZhciBzaGFkZXJzICAgICAgICAgPSBfZGVyZXFfKCcuL2xpYi9zaGFkZXJzJylcbnZhciBnZXRHbHlwaCAgICAgICAgPSBfZGVyZXFfKCcuL2xpYi9nbHlwaHMnKVxudmFyIGdldFNpbXBsZVN0cmluZyA9IF9kZXJlcV8oJy4vbGliL2dldC1zaW1wbGUtc3RyaW5nJylcblxudmFyIElERU5USVRZID0gWzEsMCwwLDAsXG4gICAgICAgICAgICAgICAgMCwxLDAsMCxcbiAgICAgICAgICAgICAgICAwLDAsMSwwLFxuICAgICAgICAgICAgICAgIDAsMCwwLDFdXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlUG9pbnRDbG91ZFxuXG5mdW5jdGlvbiB0cmFuc2Zvcm1NYXQ0KHgsIG0pIHtcbiAgdmFyIHgwID0geFswXVxuICB2YXIgeDEgPSB4WzFdXG4gIHZhciB4MiA9IHhbMl1cbiAgdmFyIHgzID0geFszXVxuICB4WzBdID0gbVswXSAqIHgwICsgbVs0XSAqIHgxICsgbVs4XSAgKiB4MiArIG1bMTJdICogeDNcbiAgeFsxXSA9IG1bMV0gKiB4MCArIG1bNV0gKiB4MSArIG1bOV0gICogeDIgKyBtWzEzXSAqIHgzXG4gIHhbMl0gPSBtWzJdICogeDAgKyBtWzZdICogeDEgKyBtWzEwXSAqIHgyICsgbVsxNF0gKiB4M1xuICB4WzNdID0gbVszXSAqIHgwICsgbVs3XSAqIHgxICsgbVsxMV0gKiB4MiArIG1bMTVdICogeDNcbiAgcmV0dXJuIHhcbn1cblxuZnVuY3Rpb24gcHJvamVjdChwLCB2LCBtLCB4KSB7XG4gIHRyYW5zZm9ybU1hdDQoeCwgeCwgbSlcbiAgdHJhbnNmb3JtTWF0NCh4LCB4LCB2KVxuICByZXR1cm4gdHJhbnNmb3JtTWF0NCh4LCB4LCBwKVxufVxuXG5mdW5jdGlvbiBTY2F0dGVyUGxvdFBpY2tSZXN1bHQoaW5kZXgsIHBvc2l0aW9uKSB7XG4gIHRoaXMuaW5kZXggPSBpbmRleFxuICB0aGlzLmRhdGFDb29yZGluYXRlID0gdGhpcy5wb3NpdGlvbiA9IHBvc2l0aW9uXG59XG5cbmZ1bmN0aW9uIGZpeE9wYWNpdHkoYSkge1xuICBpZihhID09PSB0cnVlKSByZXR1cm4gMVxuICBpZihhID4gMSkgcmV0dXJuIDFcbiAgcmV0dXJuIGFcbn1cblxuZnVuY3Rpb24gUG9pbnRDbG91ZChcbiAgZ2wsXG4gIHNoYWRlcixcbiAgb3J0aG9TaGFkZXIsXG4gIHByb2plY3RTaGFkZXIsXG4gIHBvaW50QnVmZmVyLFxuICBjb2xvckJ1ZmZlcixcbiAgZ2x5cGhCdWZmZXIsXG4gIGlkQnVmZmVyLFxuICB2YW8sXG4gIHBpY2tQZXJzcGVjdGl2ZVNoYWRlcixcbiAgcGlja09ydGhvU2hhZGVyLFxuICBwaWNrUHJvamVjdFNoYWRlcikge1xuXG4gIHRoaXMuZ2wgICAgICAgICAgICAgID0gZ2xcblxuICB0aGlzLnBpeGVsUmF0aW8gICAgICA9IDFcblxuICB0aGlzLnNoYWRlciAgICAgICAgICA9IHNoYWRlclxuICB0aGlzLm9ydGhvU2hhZGVyICAgICA9IG9ydGhvU2hhZGVyXG4gIHRoaXMucHJvamVjdFNoYWRlciAgID0gcHJvamVjdFNoYWRlclxuXG4gIHRoaXMucG9pbnRCdWZmZXIgICAgID0gcG9pbnRCdWZmZXJcbiAgdGhpcy5jb2xvckJ1ZmZlciAgICAgPSBjb2xvckJ1ZmZlclxuICB0aGlzLmdseXBoQnVmZmVyICAgICA9IGdseXBoQnVmZmVyXG4gIHRoaXMuaWRCdWZmZXIgICAgICAgID0gaWRCdWZmZXJcbiAgdGhpcy52YW8gICAgICAgICAgICAgPSB2YW9cbiAgdGhpcy52ZXJ0ZXhDb3VudCAgICAgPSAwXG4gIHRoaXMubGluZVZlcnRleENvdW50ID0gMFxuXG4gIHRoaXMub3BhY2l0eSAgICAgICAgID0gMVxuICB0aGlzLmhhc0FscGhhICAgICAgICA9IGZhbHNlXG5cbiAgdGhpcy5saW5lV2lkdGggICAgICAgPSAwXG4gIHRoaXMucHJvamVjdFNjYWxlICAgID0gWzIuMC8zLjAsIDIuMC8zLjAsIDIuMC8zLjBdXG4gIHRoaXMucHJvamVjdE9wYWNpdHkgID0gWzEsIDEsIDFdXG4gIHRoaXMucHJvamVjdEhhc0FscGhhICA9IGZhbHNlXG5cbiAgdGhpcy5waWNrSWQgICAgICAgICAgICAgICAgPSAwXG4gIHRoaXMucGlja1BlcnNwZWN0aXZlU2hhZGVyID0gcGlja1BlcnNwZWN0aXZlU2hhZGVyXG4gIHRoaXMucGlja09ydGhvU2hhZGVyICAgICAgID0gcGlja09ydGhvU2hhZGVyXG4gIHRoaXMucGlja1Byb2plY3RTaGFkZXIgICAgID0gcGlja1Byb2plY3RTaGFkZXJcbiAgdGhpcy5wb2ludHMgICAgICAgICAgICAgICAgPSBbXVxuXG4gIHRoaXMuX3NlbGVjdFJlc3VsdCA9IG5ldyBTY2F0dGVyUGxvdFBpY2tSZXN1bHQoMCwgWzAsMCwwXSlcblxuICB0aGlzLnVzZU9ydGhvID0gdHJ1ZVxuICB0aGlzLmJvdW5kcyAgID0gW1sgSW5maW5pdHksSW5maW5pdHksSW5maW5pdHldLFxuICAgICAgICAgICAgICAgICAgIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV1dXG5cbiAgLy9BeGVzIHByb2plY3Rpb25zXG4gIHRoaXMuYXhlc1Byb2plY3QgPSBbIHRydWUsIHRydWUsIHRydWUgXVxuICB0aGlzLmF4ZXNCb3VuZHMgPSBbWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XSxcbiAgICAgICAgICAgICAgICAgICAgIFsgSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV1dXG5cbiAgdGhpcy5oaWdobGlnaHRJZCAgICA9IFsxLDEsMSwxXVxuICB0aGlzLmhpZ2hsaWdodFNjYWxlID0gMlxuXG4gIHRoaXMuY2xpcEJvdW5kcyA9IFtbLUluZmluaXR5LC1JbmZpbml0eSwtSW5maW5pdHldLFxuICAgICAgICAgICAgICAgICAgICAgWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XV1cblxuICB0aGlzLmRpcnR5ID0gdHJ1ZVxufVxuXG52YXIgcHJvdG8gPSBQb2ludENsb3VkLnByb3RvdHlwZVxuXG5wcm90by5waWNrU2xvdHMgPSAxXG5cbnByb3RvLnNldFBpY2tCYXNlID0gZnVuY3Rpb24ocGlja0Jhc2UpIHtcbiAgdGhpcy5waWNrSWQgPSBwaWNrQmFzZVxufVxuXG5wcm90by5pc1RyYW5zcGFyZW50ID0gZnVuY3Rpb24oKSB7XG4gIGlmKHRoaXMuaGFzQWxwaGEpICB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICBpZih0aGlzLmF4ZXNQcm9qZWN0W2ldICYmIHRoaXMucHJvamVjdEhhc0FscGhhKSB7XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2Vcbn1cblxucHJvdG8uaXNPcGFxdWUgPSBmdW5jdGlvbigpIHtcbiAgaWYoIXRoaXMuaGFzQWxwaGEpICB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICBpZih0aGlzLmF4ZXNQcm9qZWN0W2ldICYmICF0aGlzLnByb2plY3RIYXNBbHBoYSkge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlXG59XG5cbnZhciBWSUVXX1NIQVBFID0gWzAsMF1cbnZhciBVX1ZFQyA9IFswLDAsMF1cbnZhciBWX1ZFQyA9IFswLDAsMF1cbnZhciBNVV9WRUMgPSBbMCwwLDAsMV1cbnZhciBNVl9WRUMgPSBbMCwwLDAsMV1cbnZhciBTQ1JBVENIX01BVFJJWCA9IElERU5USVRZLnNsaWNlKClcbnZhciBTQ1JBVENIX1ZFQyA9IFswLDAsMF1cbnZhciBDTElQX0JPVU5EUyA9IFtbMCwwLDBdLCBbMCwwLDBdXVxuXG5mdW5jdGlvbiB6ZXJvVmVjKGEpIHtcbiAgYVswXSA9IGFbMV0gPSBhWzJdID0gMFxuICByZXR1cm4gYVxufVxuXG5mdW5jdGlvbiBhdWdtZW50KGhnLCBhZikge1xuICBoZ1swXSA9IGFmWzBdXG4gIGhnWzFdID0gYWZbMV1cbiAgaGdbMl0gPSBhZlsyXVxuICBoZ1szXSA9IDFcbiAgcmV0dXJuIGhnXG59XG5cbmZ1bmN0aW9uIHNldENvbXBvbmVudChvdXQsIHYsIGksIHgpIHtcbiAgb3V0WzBdID0gdlswXVxuICBvdXRbMV0gPSB2WzFdXG4gIG91dFsyXSA9IHZbMl1cbiAgb3V0W2ldID0geFxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIGdldENsaXBCb3VuZHMoYm91bmRzKSB7XG4gIHZhciByZXN1bHQgPSBDTElQX0JPVU5EU1xuICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIHJlc3VsdFtpXVtqXSA9IE1hdGgubWF4KE1hdGgubWluKGJvdW5kc1tpXVtqXSwgMWU4KSwgLTFlOClcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBkcmF3UHJvamVjdChzaGFkZXIsIHBvaW50cywgY2FtZXJhLCBwaXhlbFJhdGlvKSB7XG4gIHZhciBheGVzUHJvamVjdCA9IHBvaW50cy5heGVzUHJvamVjdFxuXG4gIHZhciBnbCAgICAgICAgID0gcG9pbnRzLmdsXG4gIHZhciB1bmlmb3JtcyAgID0gc2hhZGVyLnVuaWZvcm1zXG4gIHZhciBtb2RlbCAgICAgID0gY2FtZXJhLm1vZGVsICAgICAgfHwgSURFTlRJVFlcbiAgdmFyIHZpZXcgICAgICAgPSBjYW1lcmEudmlldyAgICAgICB8fCBJREVOVElUWVxuICB2YXIgcHJvamVjdGlvbiA9IGNhbWVyYS5wcm9qZWN0aW9uIHx8IElERU5USVRZXG4gIHZhciBib3VuZHMgICAgID0gcG9pbnRzLmF4ZXNCb3VuZHNcbiAgdmFyIGNsaXBCb3VuZHMgPSBnZXRDbGlwQm91bmRzKHBvaW50cy5jbGlwQm91bmRzKVxuXG4gIHZhciBjdWJlQXhpc1xuICBpZihwb2ludHMuYXhlcyAmJiBwb2ludHMuYXhlcy5sYXN0Q3ViZVByb3BzKSB7XG4gICAgY3ViZUF4aXMgPSBwb2ludHMuYXhlcy5sYXN0Q3ViZVByb3BzLmF4aXNcbiAgfSBlbHNlIHtcbiAgICBjdWJlQXhpcyA9IFsxLDEsMV1cbiAgfVxuXG4gIFZJRVdfU0hBUEVbMF0gPSAyLjAvZ2wuZHJhd2luZ0J1ZmZlcldpZHRoXG4gIFZJRVdfU0hBUEVbMV0gPSAyLjAvZ2wuZHJhd2luZ0J1ZmZlckhlaWdodFxuXG4gIHNoYWRlci5iaW5kKClcbiAgdW5pZm9ybXMudmlldyAgICAgICAgICAgPSB2aWV3XG4gIHVuaWZvcm1zLnByb2plY3Rpb24gICAgID0gcHJvamVjdGlvblxuICB1bmlmb3Jtcy5zY3JlZW5TaXplICAgICA9IFZJRVdfU0hBUEVcbiAgdW5pZm9ybXMuaGlnaGxpZ2h0SWQgICAgPSBwb2ludHMuaGlnaGxpZ2h0SWRcbiAgdW5pZm9ybXMuaGlnaGxpZ2h0U2NhbGUgPSBwb2ludHMuaGlnaGxpZ2h0U2NhbGVcbiAgdW5pZm9ybXMuY2xpcEJvdW5kcyAgICAgPSBjbGlwQm91bmRzXG4gIHVuaWZvcm1zLnBpY2tHcm91cCAgICAgID0gcG9pbnRzLnBpY2tJZCAvIDI1NS4wXG4gIHVuaWZvcm1zLnBpeGVsUmF0aW8gICAgID0gcGl4ZWxSYXRpb1xuXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIGlmKCFheGVzUHJvamVjdFtpXSkge1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICB1bmlmb3Jtcy5zY2FsZSAgICAgICAgICA9IHBvaW50cy5wcm9qZWN0U2NhbGVbaV1cbiAgICB1bmlmb3Jtcy5vcGFjaXR5ICAgICAgICA9IHBvaW50cy5wcm9qZWN0T3BhY2l0eVtpXVxuXG4gICAgLy9Qcm9qZWN0IG1vZGVsIG1hdHJpeFxuICAgIHZhciBwbW9kZWwgPSBTQ1JBVENIX01BVFJJWFxuICAgIGZvcih2YXIgaj0wOyBqPDE2OyArK2opIHtcbiAgICAgIHBtb2RlbFtqXSA9IDBcbiAgICB9XG4gICAgZm9yKHZhciBqPTA7IGo8NDsgKytqKSB7XG4gICAgICBwbW9kZWxbNSpqXSA9IDFcbiAgICB9XG4gICAgcG1vZGVsWzUqaV0gPSAwXG4gICAgaWYoY3ViZUF4aXNbaV0gPCAwKSB7XG4gICAgICBwbW9kZWxbMTIraV0gPSBib3VuZHNbMF1baV1cbiAgICB9IGVsc2Uge1xuICAgICAgcG1vZGVsWzEyK2ldID0gYm91bmRzWzFdW2ldXG4gICAgfVxuICAgIG1hdDRtdWx0KHBtb2RlbCwgbW9kZWwsIHBtb2RlbClcbiAgICB1bmlmb3Jtcy5tb2RlbCA9IHBtb2RlbFxuXG4gICAgLy9Db21wdXRlIGluaXRpYWwgYXhlc1xuICAgIHZhciB1ID0gKGkrMSklM1xuICAgIHZhciB2ID0gKGkrMiklM1xuICAgIHZhciBkdSA9IHplcm9WZWMoVV9WRUMpXG4gICAgdmFyIGR2ID0gemVyb1ZlYyhWX1ZFQylcbiAgICBkdVt1XSA9IDFcbiAgICBkdlt2XSA9IDFcblxuICAgIC8vQWxpZ24gb3JpZW50YXRpb24gcmVsYXRpdmUgdG8gdmlld2VyXG4gICAgdmFyIG1kdSA9IHByb2plY3QocHJvamVjdGlvbiwgdmlldywgbW9kZWwsIGF1Z21lbnQoTVVfVkVDLCBkdSkpXG4gICAgdmFyIG1kdiA9IHByb2plY3QocHJvamVjdGlvbiwgdmlldywgbW9kZWwsIGF1Z21lbnQoTVZfVkVDLCBkdikpXG4gICAgaWYoTWF0aC5hYnMobWR1WzFdKSA+IE1hdGguYWJzKG1kdlsxXSkpIHtcbiAgICAgIHZhciB0bXAgPSBtZHVcbiAgICAgIG1kdSA9IG1kdlxuICAgICAgbWR2ID0gdG1wXG4gICAgICB0bXAgPSBkdVxuICAgICAgZHUgPSBkdlxuICAgICAgZHYgPSB0bXBcbiAgICAgIHZhciB0ID0gdVxuICAgICAgdSA9IHZcbiAgICAgIHYgPSB0XG4gICAgfVxuICAgIGlmKG1kdVswXSA8IDApIHtcbiAgICAgIGR1W3VdID0gLTFcbiAgICB9XG4gICAgaWYobWR2WzFdID4gMCkge1xuICAgICAgZHZbdl0gPSAtMVxuICAgIH1cbiAgICB2YXIgc3UgPSAwLjBcbiAgICB2YXIgc3YgPSAwLjBcbiAgICBmb3IodmFyIGo9MDsgajw0OyArK2opIHtcbiAgICAgIHN1ICs9IE1hdGgucG93KG1vZGVsWzQqdStqXSwgMilcbiAgICAgIHN2ICs9IE1hdGgucG93KG1vZGVsWzQqditqXSwgMilcbiAgICB9XG4gICAgZHVbdV0gLz0gTWF0aC5zcXJ0KHN1KVxuICAgIGR2W3ZdIC89IE1hdGguc3FydChzdilcbiAgICB1bmlmb3Jtcy5heGVzWzBdID0gZHVcbiAgICB1bmlmb3Jtcy5heGVzWzFdID0gZHZcblxuICAgIC8vVXBkYXRlIGZyYWdtZW50IGNsaXAgYm91bmRzXG4gICAgdW5pZm9ybXMuZnJhZ0NsaXBCb3VuZHNbMF0gPSBzZXRDb21wb25lbnQoU0NSQVRDSF9WRUMsIGNsaXBCb3VuZHNbMF0sIGksIC0xZTgpXG4gICAgdW5pZm9ybXMuZnJhZ0NsaXBCb3VuZHNbMV0gPSBzZXRDb21wb25lbnQoU0NSQVRDSF9WRUMsIGNsaXBCb3VuZHNbMV0sIGksIDFlOClcblxuICAgIHBvaW50cy52YW8uYmluZCgpXG5cbiAgICAvL0RyYXcgaW50ZXJpb3JcbiAgICBwb2ludHMudmFvLmRyYXcoZ2wuVFJJQU5HTEVTLCBwb2ludHMudmVydGV4Q291bnQpXG5cbiAgICAvL0RyYXcgZWRnZXNcbiAgICBpZihwb2ludHMubGluZVdpZHRoID4gMCkge1xuICAgICAgZ2wubGluZVdpZHRoKHBvaW50cy5saW5lV2lkdGggKiBwaXhlbFJhdGlvKVxuICAgICAgcG9pbnRzLnZhby5kcmF3KGdsLkxJTkVTLCBwb2ludHMubGluZVZlcnRleENvdW50LCBwb2ludHMudmVydGV4Q291bnQpXG4gICAgfVxuXG4gICAgcG9pbnRzLnZhby51bmJpbmQoKVxuICB9XG59XG5cblxudmFyIE5FR19JTkZJTklUWTMgPSBbLTFlOCwgLTFlOCwgLTFlOF1cbnZhciBQT1NfSU5GSU5JVFkzID0gWzFlOCwgMWU4LCAxZThdXG52YXIgQ0xJUF9HUk9VUCAgICA9IFtORUdfSU5GSU5JVFkzLCBQT1NfSU5GSU5JVFkzXVxuXG5mdW5jdGlvbiBkcmF3RnVsbChzaGFkZXIsIHBzaGFkZXIsIHBvaW50cywgY2FtZXJhLCBwaXhlbFJhdGlvLCB0cmFuc3BhcmVudCwgZm9yY2VEcmF3KSB7XG4gIHZhciBnbCA9IHBvaW50cy5nbFxuXG4gIGlmKHRyYW5zcGFyZW50ID09PSBwb2ludHMucHJvamVjdEhhc0FscGhhIHx8IGZvcmNlRHJhdykge1xuICAgIGRyYXdQcm9qZWN0KHBzaGFkZXIsIHBvaW50cywgY2FtZXJhLCBwaXhlbFJhdGlvKVxuICB9XG5cbiAgaWYodHJhbnNwYXJlbnQgPT09IHBvaW50cy5oYXNBbHBoYSB8fCBmb3JjZURyYXcpIHtcblxuICAgIHNoYWRlci5iaW5kKClcbiAgICB2YXIgdW5pZm9ybXMgPSBzaGFkZXIudW5pZm9ybXNcblxuICAgIHVuaWZvcm1zLm1vZGVsICAgICAgPSBjYW1lcmEubW9kZWwgICAgICB8fCBJREVOVElUWVxuICAgIHVuaWZvcm1zLnZpZXcgICAgICAgPSBjYW1lcmEudmlldyAgICAgICB8fCBJREVOVElUWVxuICAgIHVuaWZvcm1zLnByb2plY3Rpb24gPSBjYW1lcmEucHJvamVjdGlvbiB8fCBJREVOVElUWVxuXG4gICAgVklFV19TSEFQRVswXSAgICAgICA9IDIuMC9nbC5kcmF3aW5nQnVmZmVyV2lkdGhcbiAgICBWSUVXX1NIQVBFWzFdICAgICAgID0gMi4wL2dsLmRyYXdpbmdCdWZmZXJIZWlnaHRcbiAgICB1bmlmb3Jtcy5zY3JlZW5TaXplID0gVklFV19TSEFQRVxuXG4gICAgdW5pZm9ybXMuaGlnaGxpZ2h0SWQgICAgPSBwb2ludHMuaGlnaGxpZ2h0SWRcbiAgICB1bmlmb3Jtcy5oaWdobGlnaHRTY2FsZSA9IHBvaW50cy5oaWdobGlnaHRTY2FsZVxuXG4gICAgdW5pZm9ybXMuZnJhZ0NsaXBCb3VuZHMgPSBDTElQX0dST1VQXG4gICAgdW5pZm9ybXMuY2xpcEJvdW5kcyAgICAgPSBwb2ludHMuYXhlcy5ib3VuZHNcblxuICAgIHVuaWZvcm1zLm9wYWNpdHkgICAgPSBwb2ludHMub3BhY2l0eVxuICAgIHVuaWZvcm1zLnBpY2tHcm91cCAgPSBwb2ludHMucGlja0lkIC8gMjU1LjBcblxuICAgIHVuaWZvcm1zLnBpeGVsUmF0aW8gPSBwaXhlbFJhdGlvXG5cbiAgICBwb2ludHMudmFvLmJpbmQoKVxuXG4gICAgLy9EcmF3IGludGVyaW9yXG4gICAgcG9pbnRzLnZhby5kcmF3KGdsLlRSSUFOR0xFUywgcG9pbnRzLnZlcnRleENvdW50KVxuXG4gICAgLy9EcmF3IGVkZ2VzXG4gICAgaWYocG9pbnRzLmxpbmVXaWR0aCA+IDApIHtcbiAgICAgIGdsLmxpbmVXaWR0aChwb2ludHMubGluZVdpZHRoICogcGl4ZWxSYXRpbylcbiAgICAgIHBvaW50cy52YW8uZHJhdyhnbC5MSU5FUywgcG9pbnRzLmxpbmVWZXJ0ZXhDb3VudCwgcG9pbnRzLnZlcnRleENvdW50KVxuICAgIH1cblxuICAgIHBvaW50cy52YW8udW5iaW5kKClcbiAgfVxuXG5cbn1cblxucHJvdG8uZHJhdyA9IGZ1bmN0aW9uKGNhbWVyYSkge1xuICB2YXIgc2hhZGVyID0gdGhpcy51c2VPcnRobyA/IHRoaXMub3J0aG9TaGFkZXIgOiB0aGlzLnNoYWRlclxuICBkcmF3RnVsbChzaGFkZXIsIHRoaXMucHJvamVjdFNoYWRlciwgdGhpcywgY2FtZXJhLCB0aGlzLnBpeGVsUmF0aW8sIGZhbHNlLCBmYWxzZSlcbn1cblxucHJvdG8uZHJhd1RyYW5zcGFyZW50ID0gZnVuY3Rpb24oY2FtZXJhKSB7XG4gIHZhciBzaGFkZXIgPSB0aGlzLnVzZU9ydGhvID8gdGhpcy5vcnRob1NoYWRlciA6IHRoaXMuc2hhZGVyXG4gIGRyYXdGdWxsKHNoYWRlciwgdGhpcy5wcm9qZWN0U2hhZGVyLCB0aGlzLCBjYW1lcmEsIHRoaXMucGl4ZWxSYXRpbywgdHJ1ZSwgZmFsc2UpXG59XG5cbnByb3RvLmRyYXdQaWNrID0gZnVuY3Rpb24oY2FtZXJhKSB7XG4gIHZhciBzaGFkZXIgPSB0aGlzLnVzZU9ydGhvID8gdGhpcy5waWNrT3J0aG9TaGFkZXIgOiB0aGlzLnBpY2tQZXJzcGVjdGl2ZVNoYWRlclxuICBkcmF3RnVsbChzaGFkZXIsIHRoaXMucGlja1Byb2plY3RTaGFkZXIsIHRoaXMsIGNhbWVyYSwgMSwgdHJ1ZSwgdHJ1ZSlcbn1cblxucHJvdG8ucGljayA9IGZ1bmN0aW9uKHNlbGVjdGVkKSB7XG4gIGlmKCFzZWxlY3RlZCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cbiAgaWYoc2VsZWN0ZWQuaWQgIT09IHRoaXMucGlja0lkKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICB2YXIgeCA9IHNlbGVjdGVkLnZhbHVlWzJdICsgKHNlbGVjdGVkLnZhbHVlWzFdPDw4KSArIChzZWxlY3RlZC52YWx1ZVswXTw8MTYpXG4gIGlmKHggPj0gdGhpcy5wb2ludENvdW50IHx8IHggPCAwKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIC8vVW5wYWNrIHJlc3VsdFxuICB2YXIgY29vcmQgPSB0aGlzLnBvaW50c1t4XVxuICB2YXIgcmVzdWx0ID0gdGhpcy5fc2VsZWN0UmVzdWx0XG4gIHJlc3VsdC5pbmRleCA9IHhcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgcmVzdWx0LnBvc2l0aW9uW2ldID0gcmVzdWx0LmRhdGFDb29yZGluYXRlW2ldID0gY29vcmRbaV1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbnByb3RvLmhpZ2hsaWdodCA9IGZ1bmN0aW9uKHNlbGVjdGlvbikge1xuICBpZighc2VsZWN0aW9uKSB7XG4gICAgdGhpcy5oaWdobGlnaHRJZCA9IFsxLDEsMSwxXVxuICB9IGVsc2Uge1xuICAgIHZhciBwb2ludElkID0gc2VsZWN0aW9uLmluZGV4XG4gICAgdmFyIGEwID0gIHBvaW50SWQgICAgICYweGZmXG4gICAgdmFyIGExID0gKHBvaW50SWQ+PjgpICYweGZmXG4gICAgdmFyIGEyID0gKHBvaW50SWQ+PjE2KSYweGZmXG4gICAgdGhpcy5oaWdobGlnaHRJZCA9IFthMC8yNTUuMCwgYTEvMjU1LjAsIGEyLzI1NS4wLCAwXVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldF9nbHlwaERhdGEoZ2x5cGhzLCBpbmRleCwgZm9udCwgcGl4ZWxSYXRpbykge1xuICB2YXIgc3RyXG5cbiAgLy8gdXNlIHRoZSBkYXRhIGlmIHByZXNlbnRlZCBpbiBhbiBhcnJheVxuICBpZihBcnJheS5pc0FycmF5KGdseXBocykpIHtcbiAgICBpZihpbmRleCA8IGdseXBocy5sZW5ndGgpIHtcbiAgICAgIHN0ciA9IGdseXBoc1tpbmRleF1cbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gdW5kZWZpbmVkXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHN0ciA9IGdseXBoc1xuICB9XG5cbiAgc3RyID0gZ2V0U2ltcGxlU3RyaW5nKHN0cikgLy8gdGhpcyB3b3VsZCBoYW5kbGUgdW5kZWZpbmVkIGNhc2VzXG5cbiAgdmFyIHZpc2libGUgPSB0cnVlXG4gIGlmKGlzQWxsQmxhbmsoc3RyKSkge1xuICAgIHN0ciA9ICfilrwnIC8vIE5vdGU6IHRoaXMgc3BlY2lhbCBjaGFyYWN0ZXIgbWF5IGhhdmUgbWluaW11bSBudW1iZXIgb2Ygc3VyZmFjZXNcbiAgICB2aXNpYmxlID0gZmFsc2VcbiAgfVxuXG4gIHZhciBnbHlwaCA9IGdldEdseXBoKHN0ciwgZm9udCwgcGl4ZWxSYXRpbylcblxuICByZXR1cm4geyBtZXNoOmdseXBoWzBdLFxuICAgICAgICAgIGxpbmVzOmdseXBoWzFdLFxuICAgICAgICAgYm91bmRzOmdseXBoWzJdLFxuICAgICAgICB2aXNpYmxlOnZpc2libGUgfTtcbn1cblxuXG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuXG4gIGlmKCdwZXJzcGVjdGl2ZScgaW4gb3B0aW9ucykge1xuICAgIHRoaXMudXNlT3J0aG8gPSAhb3B0aW9ucy5wZXJzcGVjdGl2ZVxuICB9XG4gIGlmKCdvcnRob2dyYXBoaWMnIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLnVzZU9ydGhvID0gISFvcHRpb25zLm9ydGhvZ3JhcGhpY1xuICB9XG4gIGlmKCdsaW5lV2lkdGgnIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLmxpbmVXaWR0aCA9IG9wdGlvbnMubGluZVdpZHRoXG4gIH1cbiAgaWYoJ3Byb2plY3QnIGluIG9wdGlvbnMpIHtcbiAgICBpZihBcnJheS5pc0FycmF5KG9wdGlvbnMucHJvamVjdCkpIHtcbiAgICAgIHRoaXMuYXhlc1Byb2plY3QgPSBvcHRpb25zLnByb2plY3RcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHYgPSAhIW9wdGlvbnMucHJvamVjdFxuICAgICAgdGhpcy5heGVzUHJvamVjdCA9IFt2LHYsdl1cbiAgICB9XG4gIH1cbiAgaWYoJ3Byb2plY3RTY2FsZScgaW4gb3B0aW9ucykge1xuICAgIGlmKEFycmF5LmlzQXJyYXkob3B0aW9ucy5wcm9qZWN0U2NhbGUpKSB7XG4gICAgICB0aGlzLnByb2plY3RTY2FsZSA9IG9wdGlvbnMucHJvamVjdFNjYWxlLnNsaWNlKClcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHMgPSArb3B0aW9ucy5wcm9qZWN0U2NhbGVcbiAgICAgIHRoaXMucHJvamVjdFNjYWxlID0gW3MscyxzXVxuICAgIH1cbiAgfVxuXG4gIHRoaXMucHJvamVjdEhhc0FscGhhID0gZmFsc2UgLy8gZGVmYXVsdCB0byBubyB0cmFuc3BhcmVudCBkcmF3XG4gIGlmKCdwcm9qZWN0T3BhY2l0eScgaW4gb3B0aW9ucykge1xuICAgIGlmKEFycmF5LmlzQXJyYXkob3B0aW9ucy5wcm9qZWN0T3BhY2l0eSkpIHtcbiAgICAgIHRoaXMucHJvamVjdE9wYWNpdHkgPSBvcHRpb25zLnByb2plY3RPcGFjaXR5LnNsaWNlKClcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHMgPSArb3B0aW9ucy5wcm9qZWN0T3BhY2l0eVxuICAgICAgdGhpcy5wcm9qZWN0T3BhY2l0eSA9IFtzLHMsc11cbiAgICB9XG4gICAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgICB0aGlzLnByb2plY3RPcGFjaXR5W2ldID0gZml4T3BhY2l0eSh0aGlzLnByb2plY3RPcGFjaXR5W2ldKTtcbiAgICAgIGlmKHRoaXMucHJvamVjdE9wYWNpdHlbaV0gPCAxKSB7XG4gICAgICAgIHRoaXMucHJvamVjdEhhc0FscGhhID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB0aGlzLmhhc0FscGhhID0gZmFsc2UgLy8gZGVmYXVsdCB0byBubyB0cmFuc3BhcmVudCBkcmF3XG4gIGlmKCdvcGFjaXR5JyBpbiBvcHRpb25zKSB7XG4gICAgdGhpcy5vcGFjaXR5ID0gZml4T3BhY2l0eShvcHRpb25zLm9wYWNpdHkpXG4gICAgaWYodGhpcy5vcGFjaXR5IDwgMSkge1xuICAgICAgdGhpcy5oYXNBbHBoYSA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgLy9TZXQgZGlydHkgZmxhZ1xuICB0aGlzLmRpcnR5ID0gdHJ1ZVxuXG4gIC8vQ3JlYXRlIG5ldyBidWZmZXJzXG4gIHZhciBwb2ludHMgPSBvcHRpb25zLnBvc2l0aW9uXG5cbiAgLy9UZXh0IGZvbnRcbiAgdmFyIGZvbnQgICAgICA9IG9wdGlvbnMuZm9udCAgICAgIHx8ICdub3JtYWwnXG4gIHZhciBhbGlnbm1lbnQgPSBvcHRpb25zLmFsaWdubWVudCB8fCBbMCwwXVxuXG4gIHZhciBhbGlnbm1lbnRYO1xuICB2YXIgYWxpZ25tZW50WTtcbiAgaWYgKGFsaWdubWVudC5sZW5ndGggPT09IDIpIHtcbiAgICBhbGlnbm1lbnRYID0gYWxpZ25tZW50WzBdXG4gICAgYWxpZ25tZW50WSA9IGFsaWdubWVudFsxXVxuICB9IGVsc2Uge1xuICAgIGFsaWdubWVudFggPSBbXVxuICAgIGFsaWdubWVudFkgPSBbXVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYWxpZ25tZW50Lmxlbmd0aDsgKytpKSB7XG4gICAgICBhbGlnbm1lbnRYW2ldID0gYWxpZ25tZW50W2ldWzBdXG4gICAgICBhbGlnbm1lbnRZW2ldID0gYWxpZ25tZW50W2ldWzFdXG4gICAgfVxuICB9XG5cbiAgLy9Cb3VuZHNcbiAgdmFyIGxvd2VyQm91bmQgPSBbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldXG4gIHZhciB1cHBlckJvdW5kID0gWy1JbmZpbml0eSwtSW5maW5pdHksLUluZmluaXR5XVxuXG4gIC8vVW5wYWNrIG9wdGlvbnNcbiAgdmFyIGdseXBocyAgICAgPSBvcHRpb25zLmdseXBoXG4gIHZhciBjb2xvcnMgICAgID0gb3B0aW9ucy5jb2xvclxuICB2YXIgc2l6ZXMgICAgICA9IG9wdGlvbnMuc2l6ZVxuICB2YXIgYW5nbGVzICAgICA9IG9wdGlvbnMuYW5nbGVcbiAgdmFyIGxpbmVDb2xvcnMgPSBvcHRpb25zLmxpbmVDb2xvclxuXG4gIC8vUGlja2luZyBnZW9tZXRyeVxuICB2YXIgcGlja0NvdW50ZXIgPSAtMVxuXG4gIC8vRmlyc3QgZG8gcGFzcyB0byBjb21wdXRlIGJ1ZmZlciBzaXplc1xuICB2YXIgdHJpVmVydGV4Q291bnQgID0gMFxuICB2YXIgbGluZVZlcnRleENvdW50ID0gMFxuXG4gIHZhciBudW1Qb2ludHMgPSAwO1xuXG4gIGlmKHBvaW50cy5sZW5ndGgpIHtcblxuICAgIC8vQ291bnQgbnVtYmVyIG9mIHBvaW50cyBhbmQgYnVmZmVyIHNpemVcbiAgICBudW1Qb2ludHMgPSBwb2ludHMubGVuZ3RoXG5cbiAgY291bnRfbG9vcDpcbiAgICBmb3IodmFyIGk9MDsgaTxudW1Qb2ludHM7ICsraSkge1xuICAgICAgdmFyIHggPSBwb2ludHNbaV1cbiAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgICBpZihpc05hTih4W2pdKSB8fCAhaXNGaW5pdGUoeFtqXSkpIHtcbiAgICAgICAgICBjb250aW51ZSBjb3VudF9sb29wXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIGdseXBoRGF0YSA9IGdldF9nbHlwaERhdGEoZ2x5cGhzLCBpLCBmb250LCB0aGlzLnBpeGVsUmF0aW8pXG5cbiAgICAgIHZhciBnbHlwaE1lc2ggICA9IGdseXBoRGF0YS5tZXNoXG4gICAgICB2YXIgZ2x5cGhMaW5lcyAgPSBnbHlwaERhdGEubGluZXNcbiAgICAgIHZhciBnbHlwaEJvdW5kcyA9IGdseXBoRGF0YS5ib3VuZHNcblxuICAgICAgdHJpVmVydGV4Q291bnQgICs9IGdseXBoTWVzaC5jZWxscy5sZW5ndGggKiAzXG4gICAgICBsaW5lVmVydGV4Q291bnQgKz0gZ2x5cGhMaW5lcy5lZGdlcy5sZW5ndGggKiAyXG4gICAgfVxuICB9XG5cbiAgdmFyIHZlcnRleENvdW50ICAgPSB0cmlWZXJ0ZXhDb3VudCArIGxpbmVWZXJ0ZXhDb3VudFxuXG4gIC8vUHJlYWxsb2NhdGUgZGF0YVxuICB2YXIgcG9zaXRpb25BcnJheSA9IHBvb2wubWFsbG9jRmxvYXQoMyp2ZXJ0ZXhDb3VudClcbiAgdmFyIGNvbG9yQXJyYXkgICAgPSBwb29sLm1hbGxvY0Zsb2F0KDQqdmVydGV4Q291bnQpXG4gIHZhciBnbHlwaEFycmF5ICAgID0gcG9vbC5tYWxsb2NGbG9hdCgyKnZlcnRleENvdW50KVxuICB2YXIgaWRBcnJheSAgICAgICA9IHBvb2wubWFsbG9jVWludDMyKHZlcnRleENvdW50KVxuXG4gIGlmKHZlcnRleENvdW50ID4gMCkge1xuICAgIHZhciB0cmlPZmZzZXQgID0gMFxuICAgIHZhciBsaW5lT2Zmc2V0ID0gdHJpVmVydGV4Q291bnRcbiAgICB2YXIgY29sb3IgICAgICA9IFswLDAsMCwxXVxuICAgIHZhciBsaW5lQ29sb3IgID0gWzAsMCwwLDFdXG5cbiAgICB2YXIgaXNDb2xvckFycmF5ICAgICAgPSBBcnJheS5pc0FycmF5KGNvbG9ycykgICAgICYmIEFycmF5LmlzQXJyYXkoY29sb3JzWzBdKVxuICAgIHZhciBpc0xpbmVDb2xvckFycmF5ICA9IEFycmF5LmlzQXJyYXkobGluZUNvbG9ycykgJiYgQXJyYXkuaXNBcnJheShsaW5lQ29sb3JzWzBdKVxuXG4gIGZpbGxfbG9vcDpcbiAgICBmb3IodmFyIGk9MDsgaTxudW1Qb2ludHM7ICsraSkge1xuICAgICAgLy9JbmNyZW1lbnQgcGlja0NvdW50ZXJcbiAgICAgIHBpY2tDb3VudGVyICs9IDFcblxuICAgICAgdmFyIHggPSBwb2ludHNbaV1cbiAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgICBpZihpc05hTih4W2pdKSB8fCAhaXNGaW5pdGUoeFtqXSkpIHtcbiAgICAgICAgICBjb250aW51ZSBmaWxsX2xvb3BcbiAgICAgICAgfVxuXG4gICAgICAgIHVwcGVyQm91bmRbal0gPSBNYXRoLm1heCh1cHBlckJvdW5kW2pdLCB4W2pdKVxuICAgICAgICBsb3dlckJvdW5kW2pdID0gTWF0aC5taW4obG93ZXJCb3VuZFtqXSwgeFtqXSlcbiAgICAgIH1cblxuICAgICAgdmFyIGdseXBoRGF0YSA9IGdldF9nbHlwaERhdGEoZ2x5cGhzLCBpLCBmb250LCB0aGlzLnBpeGVsUmF0aW8pXG5cbiAgICAgIHZhciBnbHlwaE1lc2ggICA9IGdseXBoRGF0YS5tZXNoXG4gICAgICB2YXIgZ2x5cGhMaW5lcyAgPSBnbHlwaERhdGEubGluZXNcbiAgICAgIHZhciBnbHlwaEJvdW5kcyA9IGdseXBoRGF0YS5ib3VuZHNcbiAgICAgIHZhciBnbHlwaFZpc2libGUgPSBnbHlwaERhdGEudmlzaWJsZVxuXG4gICAgICAvL0dldCBjb2xvclxuICAgICAgaWYoIWdseXBoVmlzaWJsZSkgY29sb3IgPSBbMSwxLDEsMF1cbiAgICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheShjb2xvcnMpKSB7XG4gICAgICAgIHZhciBjXG4gICAgICAgIGlmKGlzQ29sb3JBcnJheSkge1xuICAgICAgICAgIGlmKGkgPCBjb2xvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjID0gY29sb3JzW2ldXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGMgPSBbMCwwLDAsMF1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYyA9IGNvbG9yc1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYy5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgICAgIGNvbG9yW2pdID0gY1tqXVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb2xvclszXSA9IDFcbiAgICAgICAgfSBlbHNlIGlmKGMubGVuZ3RoID09PSA0KSB7XG4gICAgICAgICAgZm9yKHZhciBqPTA7IGo8NDsgKytqKSB7XG4gICAgICAgICAgICBjb2xvcltqXSA9IGNbal1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYoIXRoaXMuaGFzQWxwaGEgJiYgY1szXSA8IDEpIHRoaXMuaGFzQWxwaGEgPSB0cnVlXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbG9yWzBdID0gY29sb3JbMV0gPSBjb2xvclsyXSA9IDBcbiAgICAgICAgY29sb3JbM10gPSAxXG4gICAgICB9XG5cblxuICAgICAgLy9HZXQgbGluZUNvbG9yXG4gICAgICBpZighZ2x5cGhWaXNpYmxlKSBsaW5lQ29sb3IgPSBbMSwxLDEsMF1cbiAgICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheShsaW5lQ29sb3JzKSkge1xuICAgICAgICB2YXIgY1xuICAgICAgICBpZihpc0xpbmVDb2xvckFycmF5KSB7XG4gICAgICAgICAgaWYoaSA8IGxpbmVDb2xvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjID0gbGluZUNvbG9yc1tpXVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjID0gWzAsMCwwLDBdXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGMgPSBsaW5lQ29sb3JzXG4gICAgICAgIH1cblxuICAgICAgICBpZihjLmxlbmd0aCA9PT0gMykge1xuICAgICAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgICAgICAgbGluZUNvbG9yW2pdID0gY1tqXVxuICAgICAgICAgIH1cbiAgICAgICAgICBsaW5lQ29sb3Jbal0gPSAxXG4gICAgICAgIH0gZWxzZSBpZihjLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgIGZvcih2YXIgaj0wOyBqPDQ7ICsraikge1xuICAgICAgICAgICAgbGluZUNvbG9yW2pdID0gY1tqXVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZighdGhpcy5oYXNBbHBoYSAmJiBjWzNdIDwgMSkgdGhpcy5oYXNBbHBoYSA9IHRydWVcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGluZUNvbG9yWzBdID0gbGluZUNvbG9yWzFdID0gbGluZUNvbG9yWzJdID0gMFxuICAgICAgICBsaW5lQ29sb3JbM10gPSAxXG4gICAgICB9XG5cblxuICAgICAgdmFyIHNpemUgPSAwLjVcbiAgICAgIGlmKCFnbHlwaFZpc2libGUpIHNpemUgPSAwLjBcbiAgICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheShzaXplcykpIHtcbiAgICAgICAgaWYoaSA8IHNpemVzLmxlbmd0aCkge1xuICAgICAgICAgIHNpemUgPSArc2l6ZXNbaV1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzaXplID0gMTJcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmKHNpemVzKSB7XG4gICAgICAgIHNpemUgPSArc2l6ZXNcbiAgICAgIH0gZWxzZSBpZih0aGlzLnVzZU9ydGhvKSB7XG4gICAgICAgIHNpemUgPSAxMlxuICAgICAgfVxuXG5cbiAgICAgIHZhciBhbmdsZSA9IDBcbiAgICAgIGlmKEFycmF5LmlzQXJyYXkoYW5nbGVzKSkge1xuICAgICAgICBpZihpIDwgYW5nbGVzLmxlbmd0aCkge1xuICAgICAgICAgIGFuZ2xlID0gK2FuZ2xlc1tpXVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFuZ2xlID0gMFxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYoYW5nbGVzKSB7XG4gICAgICAgIGFuZ2xlID0gK2FuZ2xlc1xuICAgICAgfVxuXG4gICAgICAvL0xvb3AgdGhyb3VnaCBtYXJrZXJzIGFuZCBhcHBlbmQgdG8gYnVmZmVyc1xuICAgICAgdmFyIGNvcyA9IE1hdGguY29zKGFuZ2xlKVxuICAgICAgdmFyIHNpbiA9IE1hdGguc2luKGFuZ2xlKVxuXG4gICAgICB2YXIgeCA9IHBvaW50c1tpXVxuICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICAgIHVwcGVyQm91bmRbal0gPSBNYXRoLm1heCh1cHBlckJvdW5kW2pdLCB4W2pdKVxuICAgICAgICBsb3dlckJvdW5kW2pdID0gTWF0aC5taW4obG93ZXJCb3VuZFtqXSwgeFtqXSlcbiAgICAgIH1cblxuICAgICAgLy9DYWxjdWxhdGUgdGV4dCBvZmZzZXRcbiAgICAgIHZhciB0ZXh0T2Zmc2V0WCA9IGFsaWdubWVudFhcbiAgICAgIHZhciB0ZXh0T2Zmc2V0WSA9IGFsaWdubWVudFlcblxuICAgICAgdmFyIHRleHRPZmZzZXRYID0gMFxuICAgICAgaWYoQXJyYXkuaXNBcnJheShhbGlnbm1lbnRYKSkge1xuICAgICAgICBpZihpIDwgYWxpZ25tZW50WC5sZW5ndGgpIHtcbiAgICAgICAgICB0ZXh0T2Zmc2V0WCA9IGFsaWdubWVudFhbaV1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0ZXh0T2Zmc2V0WCA9IDBcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmKGFsaWdubWVudFgpIHtcbiAgICAgICAgdGV4dE9mZnNldFggPSBhbGlnbm1lbnRYXG4gICAgICB9XG5cbiAgICAgIHZhciB0ZXh0T2Zmc2V0WSA9IDBcbiAgICAgIGlmKEFycmF5LmlzQXJyYXkoYWxpZ25tZW50WSkpIHtcbiAgICAgICAgaWYoaSA8IGFsaWdubWVudFkubGVuZ3RoKSB7XG4gICAgICAgICAgdGV4dE9mZnNldFkgPSBhbGlnbm1lbnRZW2ldXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGV4dE9mZnNldFkgPSAwXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZihhbGlnbm1lbnRZKSB7XG4gICAgICAgIHRleHRPZmZzZXRZID0gYWxpZ25tZW50WVxuICAgICAgfVxuXG4gICAgICB0ZXh0T2Zmc2V0WCAqPSAodGV4dE9mZnNldFggPiAwKSA/ICgxIC0gZ2x5cGhCb3VuZHNbMF1bMF0pIDpcbiAgICAgICAgICAgICAgICAgICAgICh0ZXh0T2Zmc2V0WCA8IDApID8gKDEgKyBnbHlwaEJvdW5kc1sxXVswXSkgOiAxO1xuXG4gICAgICB0ZXh0T2Zmc2V0WSAqPSAodGV4dE9mZnNldFkgPiAwKSA/ICgxIC0gZ2x5cGhCb3VuZHNbMF1bMV0pIDpcbiAgICAgICAgICAgICAgICAgICAgICh0ZXh0T2Zmc2V0WSA8IDApID8gKDEgKyBnbHlwaEJvdW5kc1sxXVsxXSkgOiAxO1xuXG4gICAgICB2YXIgdGV4dE9mZnNldCA9IFt0ZXh0T2Zmc2V0WCwgdGV4dE9mZnNldFldXG5cbiAgICAgIC8vV3JpdGUgb3V0IGlubmVyIG1hcmtlclxuICAgICAgdmFyIGNlbGxzID0gZ2x5cGhNZXNoLmNlbGxzIHx8IFtdXG4gICAgICB2YXIgdmVydHMgPSBnbHlwaE1lc2gucG9zaXRpb25zIHx8IFtdXG5cbiAgICAgIGZvcih2YXIgaj0wOyBqPGNlbGxzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgIHZhciBjZWxsID0gY2VsbHNbal1cbiAgICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XG4gICAgICAgICAgZm9yKHZhciBsPTA7IGw8MzsgKytsKSB7XG4gICAgICAgICAgICBwb3NpdGlvbkFycmF5WzMqdHJpT2Zmc2V0K2xdID0geFtsXVxuICAgICAgICAgIH1cbiAgICAgICAgICBmb3IodmFyIGw9MDsgbDw0OyArK2wpIHtcbiAgICAgICAgICAgIGNvbG9yQXJyYXlbNCp0cmlPZmZzZXQrbF0gPSBjb2xvcltsXVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZEFycmF5W3RyaU9mZnNldF0gPSBwaWNrQ291bnRlclxuICAgICAgICAgIHZhciBwID0gdmVydHNbY2VsbFtrXV1cbiAgICAgICAgICBnbHlwaEFycmF5WzIqdHJpT2Zmc2V0XSAgID0gc2l6ZSAqIChjb3MqcFswXSAtIHNpbipwWzFdICsgdGV4dE9mZnNldFswXSlcbiAgICAgICAgICBnbHlwaEFycmF5WzIqdHJpT2Zmc2V0KzFdID0gc2l6ZSAqIChzaW4qcFswXSArIGNvcypwWzFdICsgdGV4dE9mZnNldFsxXSlcbiAgICAgICAgICB0cmlPZmZzZXQgKz0gMVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhciBjZWxscyA9IGdseXBoTGluZXMuZWRnZXNcbiAgICAgIHZhciB2ZXJ0cyA9IGdseXBoTGluZXMucG9zaXRpb25zXG5cbiAgICAgIGZvcih2YXIgaj0wOyBqPGNlbGxzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgIHZhciBjZWxsID0gY2VsbHNbal1cbiAgICAgICAgZm9yKHZhciBrPTA7IGs8MjsgKytrKSB7XG4gICAgICAgICAgZm9yKHZhciBsPTA7IGw8MzsgKytsKSB7XG4gICAgICAgICAgICBwb3NpdGlvbkFycmF5WzMqbGluZU9mZnNldCtsXSA9IHhbbF1cbiAgICAgICAgICB9XG4gICAgICAgICAgZm9yKHZhciBsPTA7IGw8NDsgKytsKSB7XG4gICAgICAgICAgICBjb2xvckFycmF5WzQqbGluZU9mZnNldCtsXSA9IGxpbmVDb2xvcltsXVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZEFycmF5W2xpbmVPZmZzZXRdID0gcGlja0NvdW50ZXJcbiAgICAgICAgICB2YXIgcCA9IHZlcnRzW2NlbGxba11dXG4gICAgICAgICAgZ2x5cGhBcnJheVsyKmxpbmVPZmZzZXRdICAgPSBzaXplICogKGNvcypwWzBdIC0gc2luKnBbMV0gKyB0ZXh0T2Zmc2V0WzBdKVxuICAgICAgICAgIGdseXBoQXJyYXlbMipsaW5lT2Zmc2V0KzFdID0gc2l6ZSAqIChzaW4qcFswXSArIGNvcypwWzFdICsgdGV4dE9mZnNldFsxXSlcbiAgICAgICAgICBsaW5lT2Zmc2V0ICs9IDFcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgfVxuXG5cblxuICB9XG5cbiAgLy9VcGRhdGUgYm91bmRzXG4gIHRoaXMuYm91bmRzID0gW2xvd2VyQm91bmQsIHVwcGVyQm91bmRdXG5cbiAgLy9TYXZlIHBvaW50c1xuICB0aGlzLnBvaW50cyA9IHBvaW50c1xuXG4gIC8vU2F2ZSBudW1iZXIgb2YgcG9pbnRzXG4gIHRoaXMucG9pbnRDb3VudCA9IHBvaW50cy5sZW5ndGhcblxuICAvL1VwZGF0ZSB2ZXJ0ZXggY291bnRzXG4gIHRoaXMudmVydGV4Q291bnQgICAgICA9IHRyaVZlcnRleENvdW50XG4gIHRoaXMubGluZVZlcnRleENvdW50ICA9IGxpbmVWZXJ0ZXhDb3VudFxuXG4gIHRoaXMucG9pbnRCdWZmZXIudXBkYXRlKHBvc2l0aW9uQXJyYXkpXG4gIHRoaXMuY29sb3JCdWZmZXIudXBkYXRlKGNvbG9yQXJyYXkpXG4gIHRoaXMuZ2x5cGhCdWZmZXIudXBkYXRlKGdseXBoQXJyYXkpXG4gIC8vdGhpcy5pZEJ1ZmZlci51cGRhdGUobmV3IFVpbnQzMkFycmF5KGlkQXJyYXkpKVxuICB0aGlzLmlkQnVmZmVyLnVwZGF0ZShpZEFycmF5KVxuXG4gIHBvb2wuZnJlZShwb3NpdGlvbkFycmF5KVxuICBwb29sLmZyZWUoY29sb3JBcnJheSlcbiAgcG9vbC5mcmVlKGdseXBoQXJyYXkpXG4gIHBvb2wuZnJlZShpZEFycmF5KVxufVxuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIC8vU2hhZGVyc1xuICB0aGlzLnNoYWRlci5kaXNwb3NlKClcbiAgdGhpcy5vcnRob1NoYWRlci5kaXNwb3NlKClcbiAgdGhpcy5waWNrUGVyc3BlY3RpdmVTaGFkZXIuZGlzcG9zZSgpXG4gIHRoaXMucGlja09ydGhvU2hhZGVyLmRpc3Bvc2UoKVxuXG4gIC8vVmVydGV4IGFycmF5XG4gIHRoaXMudmFvLmRpc3Bvc2UoKVxuXG4gIC8vQnVmZmVyc1xuICB0aGlzLnBvaW50QnVmZmVyLmRpc3Bvc2UoKVxuICB0aGlzLmNvbG9yQnVmZmVyLmRpc3Bvc2UoKVxuICB0aGlzLmdseXBoQnVmZmVyLmRpc3Bvc2UoKVxuICB0aGlzLmlkQnVmZmVyLmRpc3Bvc2UoKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVQb2ludENsb3VkKG9wdGlvbnMpIHtcbiAgdmFyIGdsID0gb3B0aW9ucy5nbFxuXG4gIHZhciBzaGFkZXIgICAgICAgICAgICAgICAgPSBzaGFkZXJzLmNyZWF0ZVBlcnNwZWN0aXZlKGdsKVxuICB2YXIgb3J0aG9TaGFkZXIgICAgICAgICAgID0gc2hhZGVycy5jcmVhdGVPcnRobyhnbClcbiAgdmFyIHByb2plY3RTaGFkZXIgICAgICAgICA9IHNoYWRlcnMuY3JlYXRlUHJvamVjdChnbClcbiAgdmFyIHBpY2tQZXJzcGVjdGl2ZVNoYWRlciA9IHNoYWRlcnMuY3JlYXRlUGlja1BlcnNwZWN0aXZlKGdsKVxuICB2YXIgcGlja09ydGhvU2hhZGVyICAgICAgID0gc2hhZGVycy5jcmVhdGVQaWNrT3J0aG8oZ2wpXG4gIHZhciBwaWNrUHJvamVjdFNoYWRlciAgICAgPSBzaGFkZXJzLmNyZWF0ZVBpY2tQcm9qZWN0KGdsKVxuXG4gIHZhciBwb2ludEJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIGNvbG9yQnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgZ2x5cGhCdWZmZXIgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBpZEJ1ZmZlciAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHZhbyA9IGNyZWF0ZVZBTyhnbCwgW1xuICAgIHtcbiAgICAgIGJ1ZmZlcjogcG9pbnRCdWZmZXIsXG4gICAgICBzaXplOiAzLFxuICAgICAgdHlwZTogZ2wuRkxPQVRcbiAgICB9LFxuICAgIHtcbiAgICAgIGJ1ZmZlcjogY29sb3JCdWZmZXIsXG4gICAgICBzaXplOiA0LFxuICAgICAgdHlwZTogZ2wuRkxPQVRcbiAgICB9LFxuICAgIHtcbiAgICAgIGJ1ZmZlcjogZ2x5cGhCdWZmZXIsXG4gICAgICBzaXplOiAyLFxuICAgICAgdHlwZTogZ2wuRkxPQVRcbiAgICB9LFxuICAgIHtcbiAgICAgIGJ1ZmZlcjogaWRCdWZmZXIsXG4gICAgICBzaXplOiA0LFxuICAgICAgdHlwZTogZ2wuVU5TSUdORURfQllURSxcbiAgICAgIG5vcm1hbGl6ZWQ6IHRydWVcbiAgICB9XG4gIF0pXG5cbiAgdmFyIHBvaW50Q2xvdWQgPSBuZXcgUG9pbnRDbG91ZChcbiAgICBnbCxcbiAgICBzaGFkZXIsXG4gICAgb3J0aG9TaGFkZXIsXG4gICAgcHJvamVjdFNoYWRlcixcbiAgICBwb2ludEJ1ZmZlcixcbiAgICBjb2xvckJ1ZmZlcixcbiAgICBnbHlwaEJ1ZmZlcixcbiAgICBpZEJ1ZmZlcixcbiAgICB2YW8sXG4gICAgcGlja1BlcnNwZWN0aXZlU2hhZGVyLFxuICAgIHBpY2tPcnRob1NoYWRlcixcbiAgICBwaWNrUHJvamVjdFNoYWRlcilcblxuICBwb2ludENsb3VkLnVwZGF0ZShvcHRpb25zKVxuXG4gIHJldHVybiBwb2ludENsb3VkXG59XG5cbn0se1wiLi9saWIvZ2V0LXNpbXBsZS1zdHJpbmdcIjoyOTQsXCIuL2xpYi9nbHlwaHNcIjoyOTUsXCIuL2xpYi9zaGFkZXJzXCI6Mjk2LFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtbWF0NC9tdWx0aXBseVwiOjI2NyxcImdsLXZhb1wiOjMyNyxcImlzLXN0cmluZy1ibGFua1wiOjQyMyxcInR5cGVkYXJyYXktcG9vbFwiOjU0NX1dLDI5ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGdsc2xpZnkgPSBfZGVyZXFfKCdnbHNsaWZ5JylcblxuZXhwb3J0cy5ib3hWZXJ0ZXggPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzIgdmVydGV4O1xcblxcbnVuaWZvcm0gdmVjMiBjb3JuZXJBLCBjb3JuZXJCO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGdsX1Bvc2l0aW9uID0gdmVjNChtaXgoY29ybmVyQSwgY29ybmVyQiwgdmVydGV4KSwgMCwgMSk7XFxufVxcblwiXSlcbmV4cG9ydHMuYm94RnJhZ21lbnQgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudW5pZm9ybSB2ZWM0IGNvbG9yO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIGdsX0ZyYWdDb2xvciA9IGNvbG9yO1xcbn1cXG5cIl0pXG5cbn0se1wiZ2xzbGlmeVwiOjQwOX1dLDI5OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGNyZWF0ZVNoYWRlciA9IF9kZXJlcV8oJ2dsLXNoYWRlcicpXG52YXIgY3JlYXRlQnVmZmVyID0gX2RlcmVxXygnZ2wtYnVmZmVyJylcblxudmFyIFNIQURFUlMgPSBfZGVyZXFfKCcuL2xpYi9zaGFkZXJzJylcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTZWxlY3RCb3hcblxuZnVuY3Rpb24gU2VsZWN0Qm94KHBsb3QsIGJveEJ1ZmZlciwgYm94U2hhZGVyKSB7XG4gIHRoaXMucGxvdCA9IHBsb3RcbiAgdGhpcy5ib3hCdWZmZXIgPSBib3hCdWZmZXJcbiAgdGhpcy5ib3hTaGFkZXIgPSBib3hTaGFkZXJcblxuICB0aGlzLmVuYWJsZWQgPSB0cnVlXG5cbiAgdGhpcy5zZWxlY3RCb3ggPSBbSW5maW5pdHksSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV1cblxuICB0aGlzLmJvcmRlckNvbG9yID0gWzAsMCwwLDFdXG4gIHRoaXMuaW5uZXJGaWxsICAgPSBmYWxzZVxuICB0aGlzLmlubmVyQ29sb3IgID0gWzAsMCwwLDAuMjVdXG4gIHRoaXMub3V0ZXJGaWxsICAgPSB0cnVlXG4gIHRoaXMub3V0ZXJDb2xvciAgPSBbMCwwLDAsMC41XVxuICB0aGlzLmJvcmRlcldpZHRoID0gMTBcbn1cblxudmFyIHByb3RvID0gU2VsZWN0Qm94LnByb3RvdHlwZVxuXG5wcm90by5kcmF3ID0gZnVuY3Rpb24oKSB7XG4gIGlmKCF0aGlzLmVuYWJsZWQpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHZhciBwbG90ICAgICAgICAgPSB0aGlzLnBsb3RcbiAgdmFyIHNlbGVjdEJveCAgICA9IHRoaXMuc2VsZWN0Qm94XG4gIHZhciBsaW5lV2lkdGggICAgPSB0aGlzLmJvcmRlcldpZHRoXG5cbiAgdmFyIGlubmVyRmlsbCAgICA9IHRoaXMuaW5uZXJGaWxsXG4gIHZhciBpbm5lckNvbG9yICAgPSB0aGlzLmlubmVyQ29sb3JcbiAgdmFyIG91dGVyRmlsbCAgICA9IHRoaXMub3V0ZXJGaWxsXG4gIHZhciBvdXRlckNvbG9yICAgPSB0aGlzLm91dGVyQ29sb3JcbiAgdmFyIGJvcmRlckNvbG9yICA9IHRoaXMuYm9yZGVyQ29sb3JcblxuICB2YXIgYm94ZXMgICAgICAgID0gcGxvdC5ib3hcbiAgdmFyIHNjcmVlbkJveCAgICA9IHBsb3Quc2NyZWVuQm94XG4gIHZhciBkYXRhQm94ICAgICAgPSBwbG90LmRhdGFCb3hcbiAgdmFyIHZpZXdCb3ggICAgICA9IHBsb3Qudmlld0JveFxuICB2YXIgcGl4ZWxSYXRpbyAgID0gcGxvdC5waXhlbFJhdGlvXG5cbiAgLy9NYXAgc2VsZWN0IGJveCBpbnRvIHBpeGVsIGNvb3JkaW5hdGVzXG4gIHZhciBsb1ggPSAoc2VsZWN0Qm94WzBdLWRhdGFCb3hbMF0pKih2aWV3Qm94WzJdLXZpZXdCb3hbMF0pLyhkYXRhQm94WzJdLWRhdGFCb3hbMF0pK3ZpZXdCb3hbMF1cbiAgdmFyIGxvWSA9IChzZWxlY3RCb3hbMV0tZGF0YUJveFsxXSkqKHZpZXdCb3hbM10tdmlld0JveFsxXSkvKGRhdGFCb3hbM10tZGF0YUJveFsxXSkrdmlld0JveFsxXVxuICB2YXIgaGlYID0gKHNlbGVjdEJveFsyXS1kYXRhQm94WzBdKSoodmlld0JveFsyXS12aWV3Qm94WzBdKS8oZGF0YUJveFsyXS1kYXRhQm94WzBdKSt2aWV3Qm94WzBdXG4gIHZhciBoaVkgPSAoc2VsZWN0Qm94WzNdLWRhdGFCb3hbMV0pKih2aWV3Qm94WzNdLXZpZXdCb3hbMV0pLyhkYXRhQm94WzNdLWRhdGFCb3hbMV0pK3ZpZXdCb3hbMV1cblxuICBsb1ggPSBNYXRoLm1heChsb1gsIHZpZXdCb3hbMF0pXG4gIGxvWSA9IE1hdGgubWF4KGxvWSwgdmlld0JveFsxXSlcbiAgaGlYID0gTWF0aC5taW4oaGlYLCB2aWV3Qm94WzJdKVxuICBoaVkgPSBNYXRoLm1pbihoaVksIHZpZXdCb3hbM10pXG5cbiAgaWYoaGlYIDwgbG9YIHx8IGhpWSA8IGxvWSkge1xuICAgIHJldHVyblxuICB9XG5cbiAgYm94ZXMuYmluZCgpXG5cbiAgLy9EcmF3IGJveFxuICB2YXIgc2NyZWVuV2lkdGggID0gc2NyZWVuQm94WzJdIC0gc2NyZWVuQm94WzBdXG4gIHZhciBzY3JlZW5IZWlnaHQgPSBzY3JlZW5Cb3hbM10gLSBzY3JlZW5Cb3hbMV1cblxuICBpZih0aGlzLm91dGVyRmlsbCkge1xuICAgIGJveGVzLmRyYXdCb3goMCwgMCwgc2NyZWVuV2lkdGgsIGxvWSwgb3V0ZXJDb2xvcilcbiAgICBib3hlcy5kcmF3Qm94KDAsIGxvWSwgbG9YLCBoaVksIG91dGVyQ29sb3IpXG4gICAgYm94ZXMuZHJhd0JveCgwLCBoaVksIHNjcmVlbldpZHRoLCBzY3JlZW5IZWlnaHQsIG91dGVyQ29sb3IpXG4gICAgYm94ZXMuZHJhd0JveChoaVgsIGxvWSwgc2NyZWVuV2lkdGgsIGhpWSwgb3V0ZXJDb2xvcilcbiAgfVxuXG4gIGlmKHRoaXMuaW5uZXJGaWxsKSB7XG4gICAgYm94ZXMuZHJhd0JveChsb1gsIGxvWSwgaGlYLCBoaVksIGlubmVyQ29sb3IpXG4gIH1cblxuICAvL0RyYXcgYm9yZGVyXG4gIGlmKGxpbmVXaWR0aCA+IDApIHtcblxuICAgIC8vRHJhdyBib3JkZXJcbiAgICB2YXIgdyA9IGxpbmVXaWR0aCAqIHBpeGVsUmF0aW9cbiAgICBib3hlcy5kcmF3Qm94KGxvWC13LCBsb1ktdywgaGlYK3csIGxvWSt3LCBib3JkZXJDb2xvcilcbiAgICBib3hlcy5kcmF3Qm94KGxvWC13LCBoaVktdywgaGlYK3csIGhpWSt3LCBib3JkZXJDb2xvcilcbiAgICBib3hlcy5kcmF3Qm94KGxvWC13LCBsb1ktdywgbG9YK3csIGhpWSt3LCBib3JkZXJDb2xvcilcbiAgICBib3hlcy5kcmF3Qm94KGhpWC13LCBsb1ktdywgaGlYK3csIGhpWSt3LCBib3JkZXJDb2xvcilcbiAgfVxufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG5cbiAgdGhpcy5pbm5lckZpbGwgICAgPSAhIW9wdGlvbnMuaW5uZXJGaWxsXG4gIHRoaXMub3V0ZXJGaWxsICAgID0gISFvcHRpb25zLm91dGVyRmlsbFxuICB0aGlzLmlubmVyQ29sb3IgICA9IChvcHRpb25zLmlubmVyQ29sb3IgICB8fCBbMCwwLDAsMC41XSkuc2xpY2UoKVxuICB0aGlzLm91dGVyQ29sb3IgICA9IChvcHRpb25zLm91dGVyQ29sb3IgICB8fCBbMCwwLDAsMC41XSkuc2xpY2UoKVxuICB0aGlzLmJvcmRlckNvbG9yICA9IChvcHRpb25zLmJvcmRlckNvbG9yIHx8IFswLDAsMCwxXSkuc2xpY2UoKVxuICB0aGlzLmJvcmRlcldpZHRoICA9IG9wdGlvbnMuYm9yZGVyV2lkdGggfHwgMFxuICB0aGlzLnNlbGVjdEJveCAgICA9IChvcHRpb25zLnNlbGVjdEJveCB8fCB0aGlzLnNlbGVjdEJveCkuc2xpY2UoKVxufVxuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuYm94QnVmZmVyLmRpc3Bvc2UoKVxuICB0aGlzLmJveFNoYWRlci5kaXNwb3NlKClcbiAgdGhpcy5wbG90LnJlbW92ZU92ZXJsYXkodGhpcylcbn1cblxuZnVuY3Rpb24gY3JlYXRlU2VsZWN0Qm94KHBsb3QsIG9wdGlvbnMpIHtcbiAgdmFyIGdsID0gcGxvdC5nbFxuICB2YXIgYnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsLCBbXG4gICAgMCwgMCxcbiAgICAwLCAxLFxuICAgIDEsIDAsXG4gICAgMSwgMSBdKVxuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBTSEFERVJTLmJveFZlcnRleCwgU0hBREVSUy5ib3hGcmFnbWVudClcbiAgdmFyIHNlbGVjdEJveCA9IG5ldyBTZWxlY3RCb3gocGxvdCwgYnVmZmVyLCBzaGFkZXIpXG4gIHNlbGVjdEJveC51cGRhdGUob3B0aW9ucylcbiAgcGxvdC5hZGRPdmVybGF5KHNlbGVjdEJveClcbiAgcmV0dXJuIHNlbGVjdEJveFxufVxuXG59LHtcIi4vbGliL3NoYWRlcnNcIjoyOTgsXCJnbC1idWZmZXJcIjoyNDEsXCJnbC1zaGFkZXJcIjozMDF9XSwzMDA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU2VsZWN0QnVmZmVyXG5cbnZhciBjcmVhdGVGQk8gPSBfZGVyZXFfKCdnbC1mYm8nKVxudmFyIHBvb2wgICAgICA9IF9kZXJlcV8oJ3R5cGVkYXJyYXktcG9vbCcpXG52YXIgbmRhcnJheSAgID0gX2RlcmVxXygnbmRhcnJheScpXG5cbnZhciBuZXh0UG93MiAgPSBfZGVyZXFfKCdiaXQtdHdpZGRsZScpLm5leHRQb3cyXG5cbnZhciBzZWxlY3RSYW5nZSA9IF9kZXJlcV8oJ2N3aXNlL2xpYi93cmFwcGVyJykoe1wiYXJnc1wiOltcImFycmF5XCIse1wib2Zmc2V0XCI6WzAsMCwxXSxcImFycmF5XCI6MH0se1wib2Zmc2V0XCI6WzAsMCwyXSxcImFycmF5XCI6MH0se1wib2Zmc2V0XCI6WzAsMCwzXSxcImFycmF5XCI6MH0sXCJzY2FsYXJcIixcInNjYWxhclwiLFwiaW5kZXhcIl0sXCJwcmVcIjp7XCJib2R5XCI6XCJ7dGhpc19jbG9zZXN0RDI9MWU4LHRoaXNfY2xvc2VzdFg9LTEsdGhpc19jbG9zZXN0WT0tMX1cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W1widGhpc19jbG9zZXN0RDJcIixcInRoaXNfY2xvc2VzdFhcIixcInRoaXNfY2xvc2VzdFlcIl0sXCJsb2NhbFZhcnNcIjpbXX0sXCJib2R5XCI6e1wiYm9keVwiOlwie2lmKF9pbmxpbmVfMTZfYXJnMF88MjU1fHxfaW5saW5lXzE2X2FyZzFfPDI1NXx8X2lubGluZV8xNl9hcmcyXzwyNTV8fF9pbmxpbmVfMTZfYXJnM188MjU1KXt2YXIgX2lubGluZV8xNl9sPV9pbmxpbmVfMTZfYXJnNF8tX2lubGluZV8xNl9hcmc2X1swXSxfaW5saW5lXzE2X2E9X2lubGluZV8xNl9hcmc1Xy1faW5saW5lXzE2X2FyZzZfWzFdLF9pbmxpbmVfMTZfZj1faW5saW5lXzE2X2wqX2lubGluZV8xNl9sK19pbmxpbmVfMTZfYSpfaW5saW5lXzE2X2E7X2lubGluZV8xNl9mPHRoaXNfY2xvc2VzdEQyJiYodGhpc19jbG9zZXN0RDI9X2lubGluZV8xNl9mLHRoaXNfY2xvc2VzdFg9X2lubGluZV8xNl9hcmc2X1swXSx0aGlzX2Nsb3Nlc3RZPV9pbmxpbmVfMTZfYXJnNl9bMV0pfX1cIixcImFyZ3NcIjpbe1wibmFtZVwiOlwiX2lubGluZV8xNl9hcmcwX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzE2X2FyZzFfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTZfYXJnMl9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV8xNl9hcmczX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzE2X2FyZzRfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTZfYXJnNV9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV8xNl9hcmc2X1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjo0fV0sXCJ0aGlzVmFyc1wiOltcInRoaXNfY2xvc2VzdEQyXCIsXCJ0aGlzX2Nsb3Nlc3RYXCIsXCJ0aGlzX2Nsb3Nlc3RZXCJdLFwibG9jYWxWYXJzXCI6W1wiX2lubGluZV8xNl9hXCIsXCJfaW5saW5lXzE2X2ZcIixcIl9pbmxpbmVfMTZfbFwiXX0sXCJwb3N0XCI6e1wiYm9keVwiOlwie3JldHVyblt0aGlzX2Nsb3Nlc3RYLHRoaXNfY2xvc2VzdFksdGhpc19jbG9zZXN0RDJdfVwiLFwiYXJnc1wiOltdLFwidGhpc1ZhcnNcIjpbXCJ0aGlzX2Nsb3Nlc3REMlwiLFwidGhpc19jbG9zZXN0WFwiLFwidGhpc19jbG9zZXN0WVwiXSxcImxvY2FsVmFyc1wiOltdfSxcImRlYnVnXCI6ZmFsc2UsXCJmdW5jTmFtZVwiOlwiY3dpc2VcIixcImJsb2NrU2l6ZVwiOjY0fSlcblxuZnVuY3Rpb24gU2VsZWN0UmVzdWx0KHgsIHksIGlkLCB2YWx1ZSwgZGlzdGFuY2UpIHtcbiAgdGhpcy5jb29yZCA9IFt4LCB5XVxuICB0aGlzLmlkID0gaWRcbiAgdGhpcy52YWx1ZSA9IHZhbHVlXG4gIHRoaXMuZGlzdGFuY2UgPSBkaXN0YW5jZVxufVxuXG5mdW5jdGlvbiBTZWxlY3RCdWZmZXIoZ2wsIGZibywgYnVmZmVyKSB7XG4gIHRoaXMuZ2wgICAgID0gZ2xcbiAgdGhpcy5mYm8gICAgPSBmYm9cbiAgdGhpcy5idWZmZXIgPSBidWZmZXJcbiAgdGhpcy5fcmVhZFRpbWVvdXQgPSBudWxsXG4gIHZhciBzZWxmID0gdGhpc1xuXG4gIHRoaXMuX3JlYWRDYWxsYmFjayA9IGZ1bmN0aW9uKCkge1xuICAgIGlmKCFzZWxmLmdsKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgZmJvLmJpbmQoKVxuICAgIGdsLnJlYWRQaXhlbHMoMCwwLGZiby5zaGFwZVswXSxmYm8uc2hhcGVbMV0sZ2wuUkdCQSxnbC5VTlNJR05FRF9CWVRFLHNlbGYuYnVmZmVyKVxuICAgIHNlbGYuX3JlYWRUaW1lb3V0ID0gbnVsbFxuICB9XG59XG5cbnZhciBwcm90byA9IFNlbGVjdEJ1ZmZlci5wcm90b3R5cGVcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCAnc2hhcGUnLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgaWYoIXRoaXMuZ2wpIHtcbiAgICAgIHJldHVybiBbMCwwXVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5mYm8uc2hhcGUuc2xpY2UoKVxuICB9LFxuICBzZXQ6IGZ1bmN0aW9uKHYpIHtcbiAgICBpZighdGhpcy5nbCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIHRoaXMuZmJvLnNoYXBlID0gdlxuICAgIHZhciBjID0gdGhpcy5mYm8uc2hhcGVbMF1cbiAgICB2YXIgciA9IHRoaXMuZmJvLnNoYXBlWzFdXG4gICAgaWYocipjKjQgPiB0aGlzLmJ1ZmZlci5sZW5ndGgpIHtcbiAgICAgIHBvb2wuZnJlZSh0aGlzLmJ1ZmZlcilcbiAgICAgIHZhciBidWZmZXIgPSB0aGlzLmJ1ZmZlciA9IHBvb2wubWFsbG9jVWludDgobmV4dFBvdzIocipjKjQpKVxuICAgICAgZm9yKHZhciBpPTA7IGk8cipjKjQ7ICsraSkge1xuICAgICAgICBidWZmZXJbaV0gPSAweGZmXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB2XG4gIH1cbn0pXG5cbnByb3RvLmJlZ2luID0gZnVuY3Rpb24oKSB7XG4gIHZhciBnbCA9IHRoaXMuZ2xcbiAgdmFyIHNoYXBlID0gdGhpcy5zaGFwZVxuICBpZighZ2wpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHRoaXMuZmJvLmJpbmQoKVxuICBnbC5jbGVhckNvbG9yKDEsMSwxLDEpXG4gIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQgfCBnbC5ERVBUSF9CVUZGRVJfQklUKVxufVxuXG5wcm90by5lbmQgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGdsID0gdGhpcy5nbFxuICBpZighZ2wpIHtcbiAgICByZXR1cm5cbiAgfVxuICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpXG4gIGlmKCF0aGlzLl9yZWFkVGltZW91dCkge1xuICAgIGNsZWFyVGltZW91dCh0aGlzLl9yZWFkVGltZW91dClcbiAgfVxuICB0aGlzLl9yZWFkVGltZW91dCA9IHNldFRpbWVvdXQodGhpcy5fcmVhZENhbGxiYWNrLCAxKVxufVxuXG5wcm90by5xdWVyeSA9IGZ1bmN0aW9uKHgsIHksIHJhZGl1cykge1xuICBpZighdGhpcy5nbCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICB2YXIgc2hhcGUgPSB0aGlzLmZiby5zaGFwZS5zbGljZSgpXG5cbiAgeCA9IHh8MFxuICB5ID0geXwwXG4gIGlmKHR5cGVvZiByYWRpdXMgIT09ICdudW1iZXInKSB7XG4gICAgcmFkaXVzID0gMS4wXG4gIH1cblxuICB2YXIgeDAgPSBNYXRoLm1pbihNYXRoLm1heCh4IC0gcmFkaXVzLCAwKSwgc2hhcGVbMF0pfDBcbiAgdmFyIHgxID0gTWF0aC5taW4oTWF0aC5tYXgoeCArIHJhZGl1cywgMCksIHNoYXBlWzBdKXwwXG4gIHZhciB5MCA9IE1hdGgubWluKE1hdGgubWF4KHkgLSByYWRpdXMsIDApLCBzaGFwZVsxXSl8MFxuICB2YXIgeTEgPSBNYXRoLm1pbihNYXRoLm1heCh5ICsgcmFkaXVzLCAwKSwgc2hhcGVbMV0pfDBcblxuICBpZih4MSA8PSB4MCB8fCB5MSA8PSB5MCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICB2YXIgZGltcyAgID0gW3gxLXgwLHkxLXkwXVxuICB2YXIgcmVnaW9uID0gbmRhcnJheShcbiAgICB0aGlzLmJ1ZmZlcixcbiAgICBbZGltc1swXSwgZGltc1sxXSwgNF0sXG4gICAgWzQsIHNoYXBlWzBdKjQsIDFdLFxuICAgIDQqKHgwICsgc2hhcGVbMF0qeTApKTtcblxuICB2YXIgY2xvc2VzdCA9IHNlbGVjdFJhbmdlKHJlZ2lvbi5oaShkaW1zWzBdLGRpbXNbMV0sMSksIHJhZGl1cywgcmFkaXVzKVxuICB2YXIgZHggPSBjbG9zZXN0WzBdXG4gIHZhciBkeSA9IGNsb3Nlc3RbMV1cbiAgaWYoZHggPCAwIHx8IE1hdGgucG93KHRoaXMucmFkaXVzLCAyKSA8IGNsb3Nlc3RbMl0pIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgdmFyIGMwID0gcmVnaW9uLmdldChkeCwgZHksIDApXG4gIHZhciBjMSA9IHJlZ2lvbi5nZXQoZHgsIGR5LCAxKVxuICB2YXIgYzIgPSByZWdpb24uZ2V0KGR4LCBkeSwgMilcbiAgdmFyIGMzID0gcmVnaW9uLmdldChkeCwgZHksIDMpXG5cbiAgcmV0dXJuIG5ldyBTZWxlY3RSZXN1bHQoXG4gICAgIChkeCArIHgwKXwwLFxuICAgICAoZHkgKyB5MCl8MCxcbiAgICAgYzAsXG4gICAgIFtjMSwgYzIsIGMzXSxcbiAgICAgTWF0aC5zcXJ0KGNsb3Nlc3RbMl0pKVxufVxuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIGlmKCF0aGlzLmdsKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdGhpcy5mYm8uZGlzcG9zZSgpXG4gIHBvb2wuZnJlZSh0aGlzLmJ1ZmZlcilcbiAgdGhpcy5nbCA9IG51bGxcbiAgaWYodGhpcy5fcmVhZFRpbWVvdXQpIHtcbiAgICBjbGVhclRpbWVvdXQodGhpcy5fcmVhZFRpbWVvdXQpXG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlU2VsZWN0QnVmZmVyKGdsLCBzaGFwZSkge1xuICB2YXIgZmJvID0gY3JlYXRlRkJPKGdsLCBzaGFwZSlcbiAgdmFyIGJ1ZmZlciA9IHBvb2wubWFsbG9jVWludDgoc2hhcGVbMF0qc2hhcGVbMV0qNClcbiAgcmV0dXJuIG5ldyBTZWxlY3RCdWZmZXIoZ2wsIGZibywgYnVmZmVyKVxufVxuXG59LHtcImJpdC10d2lkZGxlXCI6OTIsXCJjd2lzZS9saWIvd3JhcHBlclwiOjE0OSxcImdsLWZib1wiOjI0OSxcIm5kYXJyYXlcIjo0NTAsXCJ0eXBlZGFycmF5LXBvb2xcIjo1NDV9XSwzMDE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBjcmVhdGVVbmlmb3JtV3JhcHBlciAgID0gX2RlcmVxXygnLi9saWIvY3JlYXRlLXVuaWZvcm1zJylcbnZhciBjcmVhdGVBdHRyaWJ1dGVXcmFwcGVyID0gX2RlcmVxXygnLi9saWIvY3JlYXRlLWF0dHJpYnV0ZXMnKVxudmFyIG1ha2VSZWZsZWN0ICAgICAgICAgICAgPSBfZGVyZXFfKCcuL2xpYi9yZWZsZWN0JylcbnZhciBzaGFkZXJDYWNoZSAgICAgICAgICAgID0gX2RlcmVxXygnLi9saWIvc2hhZGVyLWNhY2hlJylcbnZhciBydW50aW1lICAgICAgICAgICAgICAgID0gX2RlcmVxXygnLi9saWIvcnVudGltZS1yZWZsZWN0JylcbnZhciBHTEVycm9yICAgICAgICAgICAgICAgID0gX2RlcmVxXyhcIi4vbGliL0dMRXJyb3JcIilcblxuLy9TaGFkZXIgb2JqZWN0XG5mdW5jdGlvbiBTaGFkZXIoZ2wpIHtcbiAgdGhpcy5nbCAgICAgICAgID0gZ2xcbiAgdGhpcy5nbC5sYXN0QXR0cmliQ291bnQgPSAwICAvLyBmaXhtZSB3aGVyZSBlbHNlIHNob3VsZCB3ZSBzdG9yZSBpbmZvLCBzYWZlIGJ1dCBub3QgbmljZSBvbiB0aGUgZ2wgb2JqZWN0XG5cbiAgLy9EZWZhdWx0IGluaXRpYWxpemUgdGhlc2UgdG8gbnVsbFxuICB0aGlzLl92cmVmICAgICAgPVxuICB0aGlzLl9mcmVmICAgICAgPVxuICB0aGlzLl9yZWxpbmsgICAgPVxuICB0aGlzLnZlcnRTaGFkZXIgPVxuICB0aGlzLmZyYWdTaGFkZXIgPVxuICB0aGlzLnByb2dyYW0gICAgPVxuICB0aGlzLmF0dHJpYnV0ZXMgPVxuICB0aGlzLnVuaWZvcm1zICAgPVxuICB0aGlzLnR5cGVzICAgICAgPSBudWxsXG59XG5cbnZhciBwcm90byA9IFNoYWRlci5wcm90b3R5cGVcblxucHJvdG8uYmluZCA9IGZ1bmN0aW9uKCkge1xuICBpZighdGhpcy5wcm9ncmFtKSB7XG4gICAgdGhpcy5fcmVsaW5rKClcbiAgfVxuXG4gIC8vIGVuc3VyaW5nIHRoYXQgd2UgaGF2ZSB0aGUgcmlnaHQgbnVtYmVyIG9mIGVuYWJsZWQgdmVydGV4IGF0dHJpYnV0ZXNcbiAgdmFyIGlcbiAgdmFyIG5ld0F0dHJpYkNvdW50ID0gdGhpcy5nbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHRoaXMucHJvZ3JhbSwgdGhpcy5nbC5BQ1RJVkVfQVRUUklCVVRFUykgLy8gbW9yZSByb2J1c3QgYXBwcm9hY2hcbiAgLy92YXIgbmV3QXR0cmliQ291bnQgPSBPYmplY3Qua2V5cyh0aGlzLmF0dHJpYnV0ZXMpLmxlbmd0aCAvLyBhdm9pZHMgdGhlIHByb2JhYmx5IGltbWF0ZXJpYWwgaW50cm9zcGVjdGlvbiBzbG93ZG93blxuICB2YXIgb2xkQXR0cmliQ291bnQgPSB0aGlzLmdsLmxhc3RBdHRyaWJDb3VudFxuICBpZihuZXdBdHRyaWJDb3VudCA+IG9sZEF0dHJpYkNvdW50KSB7XG4gICAgZm9yKGkgPSBvbGRBdHRyaWJDb3VudDsgaSA8IG5ld0F0dHJpYkNvdW50OyBpKyspIHtcbiAgICAgIHRoaXMuZ2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoaSlcbiAgICB9XG4gIH0gZWxzZSBpZihvbGRBdHRyaWJDb3VudCA+IG5ld0F0dHJpYkNvdW50KSB7XG4gICAgZm9yKGkgPSBuZXdBdHRyaWJDb3VudDsgaSA8IG9sZEF0dHJpYkNvdW50OyBpKyspIHtcbiAgICAgIHRoaXMuZ2wuZGlzYWJsZVZlcnRleEF0dHJpYkFycmF5KGkpXG4gICAgfVxuICB9XG5cbiAgdGhpcy5nbC5sYXN0QXR0cmliQ291bnQgPSBuZXdBdHRyaWJDb3VudFxuXG4gIHRoaXMuZ2wudXNlUHJvZ3JhbSh0aGlzLnByb2dyYW0pXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcblxuICAvLyBkaXNhYmxpbmcgdmVydGV4IGF0dHJpYnV0ZXMgc28gbmV3IHNoYWRlciBzdGFydHMgd2l0aCB6ZXJvXG4gIC8vIGFuZCBpdCdzIGFsc28gdXNlZnVsIGlmIGFsbCBzaGFkZXJzIGFyZSBkaXNwb3NlZCBidXQgdGhlXG4gIC8vIGdsIGNvbnRleHQgaXMgcmV1c2VkIGZvciBzdWJzZXF1ZW50IHJlcGxvdHRpbmdcbiAgdmFyIG9sZEF0dHJpYkNvdW50ID0gdGhpcy5nbC5sYXN0QXR0cmliQ291bnRcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBvbGRBdHRyaWJDb3VudDsgaSsrKSB7XG4gICAgdGhpcy5nbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoaSlcbiAgfVxuICB0aGlzLmdsLmxhc3RBdHRyaWJDb3VudCA9IDBcblxuICBpZih0aGlzLl9mcmVmKSB7XG4gICAgdGhpcy5fZnJlZi5kaXNwb3NlKClcbiAgfVxuICBpZih0aGlzLl92cmVmKSB7XG4gICAgdGhpcy5fdnJlZi5kaXNwb3NlKClcbiAgfVxuICB0aGlzLmF0dHJpYnV0ZXMgPVxuICB0aGlzLnR5cGVzICAgICAgPVxuICB0aGlzLnZlcnRTaGFkZXIgPVxuICB0aGlzLmZyYWdTaGFkZXIgPVxuICB0aGlzLnByb2dyYW0gICAgPVxuICB0aGlzLl9yZWxpbmsgICAgPVxuICB0aGlzLl9mcmVmICAgICAgPVxuICB0aGlzLl92cmVmICAgICAgPSBudWxsXG59XG5cbmZ1bmN0aW9uIGNvbXBhcmVBdHRyaWJ1dGVzKGEsIGIpIHtcbiAgaWYoYS5uYW1lIDwgYi5uYW1lKSB7XG4gICAgcmV0dXJuIC0xXG4gIH1cbiAgcmV0dXJuIDFcbn1cblxuLy9VcGRhdGUgZXhwb3J0IGhvb2sgZm9yIGdsc2xpZnktbGl2ZVxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24oXG4gICAgdmVydFNvdXJjZVxuICAsIGZyYWdTb3VyY2VcbiAgLCB1bmlmb3Jtc1xuICAsIGF0dHJpYnV0ZXMpIHtcblxuICAvL0lmIG9ubHkgb25lIG9iamVjdCBwYXNzZWQsIGFzc3VtZSBnbHNsaWZ5IHN0eWxlIG91dHB1dFxuICBpZighZnJhZ1NvdXJjZSB8fCBhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgdmFyIG9iaiA9IHZlcnRTb3VyY2VcbiAgICB2ZXJ0U291cmNlID0gb2JqLnZlcnRleFxuICAgIGZyYWdTb3VyY2UgPSBvYmouZnJhZ21lbnRcbiAgICB1bmlmb3JtcyAgID0gb2JqLnVuaWZvcm1zXG4gICAgYXR0cmlidXRlcyA9IG9iai5hdHRyaWJ1dGVzXG4gIH1cblxuICB2YXIgd3JhcHBlciA9IHRoaXNcbiAgdmFyIGdsICAgICAgPSB3cmFwcGVyLmdsXG5cbiAgLy9Db21waWxlIHZlcnRleCBhbmQgZnJhZ21lbnQgc2hhZGVyc1xuICB2YXIgcHZyZWYgPSB3cmFwcGVyLl92cmVmXG4gIHdyYXBwZXIuX3ZyZWYgPSBzaGFkZXJDYWNoZS5zaGFkZXIoZ2wsIGdsLlZFUlRFWF9TSEFERVIsIHZlcnRTb3VyY2UpXG4gIGlmKHB2cmVmKSB7XG4gICAgcHZyZWYuZGlzcG9zZSgpXG4gIH1cbiAgd3JhcHBlci52ZXJ0U2hhZGVyID0gd3JhcHBlci5fdnJlZi5zaGFkZXJcbiAgdmFyIHBmcmVmID0gdGhpcy5fZnJlZlxuICB3cmFwcGVyLl9mcmVmID0gc2hhZGVyQ2FjaGUuc2hhZGVyKGdsLCBnbC5GUkFHTUVOVF9TSEFERVIsIGZyYWdTb3VyY2UpXG4gIGlmKHBmcmVmKSB7XG4gICAgcGZyZWYuZGlzcG9zZSgpXG4gIH1cbiAgd3JhcHBlci5mcmFnU2hhZGVyID0gd3JhcHBlci5fZnJlZi5zaGFkZXJcblxuICAvL0lmIHVuaWZvcm1zL2F0dHJpYnV0ZXMgaXMgbm90IHNwZWNpZmllZCwgdXNlIFJUIHJlZmxlY3Rpb25cbiAgaWYoIXVuaWZvcm1zIHx8ICFhdHRyaWJ1dGVzKSB7XG5cbiAgICAvL0NyZWF0ZSBpbml0aWFsIHRlc3QgcHJvZ3JhbVxuICAgIHZhciB0ZXN0UHJvZ3JhbSA9IGdsLmNyZWF0ZVByb2dyYW0oKVxuICAgIGdsLmF0dGFjaFNoYWRlcih0ZXN0UHJvZ3JhbSwgd3JhcHBlci5mcmFnU2hhZGVyKVxuICAgIGdsLmF0dGFjaFNoYWRlcih0ZXN0UHJvZ3JhbSwgd3JhcHBlci52ZXJ0U2hhZGVyKVxuICAgIGdsLmxpbmtQcm9ncmFtKHRlc3RQcm9ncmFtKVxuICAgIGlmKCFnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHRlc3RQcm9ncmFtLCBnbC5MSU5LX1NUQVRVUykpIHtcbiAgICAgIHZhciBlcnJMb2cgPSBnbC5nZXRQcm9ncmFtSW5mb0xvZyh0ZXN0UHJvZ3JhbSlcbiAgICAgIHRocm93IG5ldyBHTEVycm9yKGVyckxvZywgJ0Vycm9yIGxpbmtpbmcgcHJvZ3JhbTonICsgZXJyTG9nKVxuICAgIH1cblxuICAgIC8vTG9hZCBkYXRhIGZyb20gcnVudGltZVxuICAgIHVuaWZvcm1zICAgPSB1bmlmb3JtcyAgIHx8IHJ1bnRpbWUudW5pZm9ybXMoZ2wsIHRlc3RQcm9ncmFtKVxuICAgIGF0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzIHx8IHJ1bnRpbWUuYXR0cmlidXRlcyhnbCwgdGVzdFByb2dyYW0pXG5cbiAgICAvL1JlbGVhc2UgdGVzdCBwcm9ncmFtXG4gICAgZ2wuZGVsZXRlUHJvZ3JhbSh0ZXN0UHJvZ3JhbSlcbiAgfVxuXG4gIC8vU29ydCBhdHRyaWJ1dGVzIGxleGljb2dyYXBoaWNhbGx5XG4gIC8vIG92ZXJyaWRlcyB1bmRlZmluZWQgV2ViR0wgYmVoYXZpb3IgZm9yIGF0dHJpYnV0ZSBsb2NhdGlvbnNcbiAgYXR0cmlidXRlcyA9IGF0dHJpYnV0ZXMuc2xpY2UoKVxuICBhdHRyaWJ1dGVzLnNvcnQoY29tcGFyZUF0dHJpYnV0ZXMpXG5cbiAgLy9Db252ZXJ0IGF0dHJpYnV0ZSB0eXBlcywgcmVhZCBvdXQgbG9jYXRpb25zXG4gIHZhciBhdHRyaWJ1dGVVbnBhY2tlZCAgPSBbXVxuICB2YXIgYXR0cmlidXRlTmFtZXMgICAgID0gW11cbiAgdmFyIGF0dHJpYnV0ZUxvY2F0aW9ucyA9IFtdXG4gIHZhciBpXG4gIGZvcihpPTA7IGk8YXR0cmlidXRlcy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBhdHRyID0gYXR0cmlidXRlc1tpXVxuICAgIGlmKGF0dHIudHlwZS5pbmRleE9mKCdtYXQnKSA+PSAwKSB7XG4gICAgICB2YXIgc2l6ZSA9IGF0dHIudHlwZS5jaGFyQXQoYXR0ci50eXBlLmxlbmd0aC0xKXwwXG4gICAgICB2YXIgbG9jVmVjdG9yID0gbmV3IEFycmF5KHNpemUpXG4gICAgICBmb3IodmFyIGo9MDsgajxzaXplOyArK2opIHtcbiAgICAgICAgbG9jVmVjdG9yW2pdID0gYXR0cmlidXRlTG9jYXRpb25zLmxlbmd0aFxuICAgICAgICBhdHRyaWJ1dGVOYW1lcy5wdXNoKGF0dHIubmFtZSArICdbJyArIGogKyAnXScpXG4gICAgICAgIGlmKHR5cGVvZiBhdHRyLmxvY2F0aW9uID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGF0dHJpYnV0ZUxvY2F0aW9ucy5wdXNoKGF0dHIubG9jYXRpb24gKyBqKVxuICAgICAgICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheShhdHRyLmxvY2F0aW9uKSAmJlxuICAgICAgICAgICAgICAgICAgYXR0ci5sb2NhdGlvbi5sZW5ndGggPT09IHNpemUgJiZcbiAgICAgICAgICAgICAgICAgIHR5cGVvZiBhdHRyLmxvY2F0aW9uW2pdID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGF0dHJpYnV0ZUxvY2F0aW9ucy5wdXNoKGF0dHIubG9jYXRpb25bal18MClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhdHRyaWJ1dGVMb2NhdGlvbnMucHVzaCgtMSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYXR0cmlidXRlVW5wYWNrZWQucHVzaCh7XG4gICAgICAgIG5hbWU6IGF0dHIubmFtZSxcbiAgICAgICAgdHlwZTogYXR0ci50eXBlLFxuICAgICAgICBsb2NhdGlvbnM6IGxvY1ZlY3RvclxuICAgICAgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgYXR0cmlidXRlVW5wYWNrZWQucHVzaCh7XG4gICAgICAgIG5hbWU6IGF0dHIubmFtZSxcbiAgICAgICAgdHlwZTogYXR0ci50eXBlLFxuICAgICAgICBsb2NhdGlvbnM6IFsgYXR0cmlidXRlTG9jYXRpb25zLmxlbmd0aCBdXG4gICAgICB9KVxuICAgICAgYXR0cmlidXRlTmFtZXMucHVzaChhdHRyLm5hbWUpXG4gICAgICBpZih0eXBlb2YgYXR0ci5sb2NhdGlvbiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgYXR0cmlidXRlTG9jYXRpb25zLnB1c2goYXR0ci5sb2NhdGlvbnwwKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXR0cmlidXRlTG9jYXRpb25zLnB1c2goLTEpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9Gb3IgYWxsIHVuc3BlY2lmaWVkIGF0dHJpYnV0ZXMsIGFzc2lnbiB0aGVtIGxleGljb2dyYXBoaWNhbGx5IG1pbiBhdHRyaWJ1dGVcbiAgdmFyIGN1ckxvY2F0aW9uID0gMFxuICBmb3IoaT0wOyBpPGF0dHJpYnV0ZUxvY2F0aW9ucy5sZW5ndGg7ICsraSkge1xuICAgIGlmKGF0dHJpYnV0ZUxvY2F0aW9uc1tpXSA8IDApIHtcbiAgICAgIHdoaWxlKGF0dHJpYnV0ZUxvY2F0aW9ucy5pbmRleE9mKGN1ckxvY2F0aW9uKSA+PSAwKSB7XG4gICAgICAgIGN1ckxvY2F0aW9uICs9IDFcbiAgICAgIH1cbiAgICAgIGF0dHJpYnV0ZUxvY2F0aW9uc1tpXSA9IGN1ckxvY2F0aW9uXG4gICAgfVxuICB9XG5cbiAgLy9SZWJ1aWxkIHByb2dyYW0gYW5kIHJlY29tcHV0ZSBhbGwgdW5pZm9ybSBsb2NhdGlvbnNcbiAgdmFyIHVuaWZvcm1Mb2NhdGlvbnMgPSBuZXcgQXJyYXkodW5pZm9ybXMubGVuZ3RoKVxuICBmdW5jdGlvbiByZWxpbmsoKSB7XG4gICAgd3JhcHBlci5wcm9ncmFtID0gc2hhZGVyQ2FjaGUucHJvZ3JhbShcbiAgICAgICAgZ2xcbiAgICAgICwgd3JhcHBlci5fdnJlZlxuICAgICAgLCB3cmFwcGVyLl9mcmVmXG4gICAgICAsIGF0dHJpYnV0ZU5hbWVzXG4gICAgICAsIGF0dHJpYnV0ZUxvY2F0aW9ucylcblxuICAgIGZvcih2YXIgaT0wOyBpPHVuaWZvcm1zLmxlbmd0aDsgKytpKSB7XG4gICAgICB1bmlmb3JtTG9jYXRpb25zW2ldID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKFxuICAgICAgICAgIHdyYXBwZXIucHJvZ3JhbVxuICAgICAgICAsIHVuaWZvcm1zW2ldLm5hbWUpXG4gICAgfVxuICB9XG5cbiAgLy9QZXJmb3JtIGluaXRpYWwgbGlua2luZywgcmV1c2UgcHJvZ3JhbSB1c2VkIGZvciByZWZsZWN0aW9uXG4gIHJlbGluaygpXG5cbiAgLy9TYXZlIHJlbGlua2luZyBwcm9jZWR1cmUsIGRlZmVyIHVudGlsIHJ1bnRpbWVcbiAgd3JhcHBlci5fcmVsaW5rID0gcmVsaW5rXG5cbiAgLy9HZW5lcmF0ZSB0eXBlIGluZm9cbiAgd3JhcHBlci50eXBlcyA9IHtcbiAgICB1bmlmb3JtczogICBtYWtlUmVmbGVjdCh1bmlmb3JtcyksXG4gICAgYXR0cmlidXRlczogbWFrZVJlZmxlY3QoYXR0cmlidXRlcylcbiAgfVxuXG4gIC8vR2VuZXJhdGUgYXR0cmlidXRlIHdyYXBwZXJzXG4gIHdyYXBwZXIuYXR0cmlidXRlcyA9IGNyZWF0ZUF0dHJpYnV0ZVdyYXBwZXIoXG4gICAgICBnbFxuICAgICwgd3JhcHBlclxuICAgICwgYXR0cmlidXRlVW5wYWNrZWRcbiAgICAsIGF0dHJpYnV0ZUxvY2F0aW9ucylcblxuICAvL0dlbmVyYXRlIHVuaWZvcm0gd3JhcHBlcnNcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdyYXBwZXIsICd1bmlmb3JtcycsIGNyZWF0ZVVuaWZvcm1XcmFwcGVyKFxuICAgICAgZ2xcbiAgICAsIHdyYXBwZXJcbiAgICAsIHVuaWZvcm1zXG4gICAgLCB1bmlmb3JtTG9jYXRpb25zKSlcbn1cblxuLy9Db21waWxlcyBhbmQgbGlua3MgYSBzaGFkZXIgcHJvZ3JhbSB3aXRoIHRoZSBnaXZlbiBhdHRyaWJ1dGUgYW5kIHZlcnRleCBsaXN0XG5mdW5jdGlvbiBjcmVhdGVTaGFkZXIoXG4gICAgZ2xcbiAgLCB2ZXJ0U291cmNlXG4gICwgZnJhZ1NvdXJjZVxuICAsIHVuaWZvcm1zXG4gICwgYXR0cmlidXRlcykge1xuXG4gIHZhciBzaGFkZXIgPSBuZXcgU2hhZGVyKGdsKVxuXG4gIHNoYWRlci51cGRhdGUoXG4gICAgICB2ZXJ0U291cmNlXG4gICAgLCBmcmFnU291cmNlXG4gICAgLCB1bmlmb3Jtc1xuICAgICwgYXR0cmlidXRlcylcblxuICByZXR1cm4gc2hhZGVyXG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU2hhZGVyXG5cbn0se1wiLi9saWIvR0xFcnJvclwiOjMwMixcIi4vbGliL2NyZWF0ZS1hdHRyaWJ1dGVzXCI6MzAzLFwiLi9saWIvY3JlYXRlLXVuaWZvcm1zXCI6MzA0LFwiLi9saWIvcmVmbGVjdFwiOjMwNSxcIi4vbGliL3J1bnRpbWUtcmVmbGVjdFwiOjMwNixcIi4vbGliL3NoYWRlci1jYWNoZVwiOjMwN31dLDMwMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5mdW5jdGlvbiBHTEVycm9yIChyYXdFcnJvciwgc2hvcnRNZXNzYWdlLCBsb25nTWVzc2FnZSkge1xuICAgIHRoaXMuc2hvcnRNZXNzYWdlID0gc2hvcnRNZXNzYWdlIHx8ICcnXG4gICAgdGhpcy5sb25nTWVzc2FnZSA9IGxvbmdNZXNzYWdlIHx8ICcnXG4gICAgdGhpcy5yYXdFcnJvciA9IHJhd0Vycm9yIHx8ICcnXG4gICAgdGhpcy5tZXNzYWdlID1cbiAgICAgICdnbC1zaGFkZXI6ICcgKyAoc2hvcnRNZXNzYWdlIHx8IHJhd0Vycm9yIHx8ICcnKSArXG4gICAgICAobG9uZ01lc3NhZ2UgPyAnXFxuJytsb25nTWVzc2FnZSA6ICcnKVxuICAgIHRoaXMuc3RhY2sgPSAobmV3IEVycm9yKCkpLnN0YWNrXG59XG5HTEVycm9yLnByb3RvdHlwZSA9IG5ldyBFcnJvclxuR0xFcnJvci5wcm90b3R5cGUubmFtZSA9ICdHTEVycm9yJ1xuR0xFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBHTEVycm9yXG5tb2R1bGUuZXhwb3J0cyA9IEdMRXJyb3JcblxufSx7fV0sMzAzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUF0dHJpYnV0ZVdyYXBwZXJcblxudmFyIEdMRXJyb3IgPSBfZGVyZXFfKFwiLi9HTEVycm9yXCIpXG5cbmZ1bmN0aW9uIFNoYWRlckF0dHJpYnV0ZShcbiAgICBnbFxuICAsIHdyYXBwZXJcbiAgLCBpbmRleFxuICAsIGxvY2F0aW9uc1xuICAsIGRpbWVuc2lvblxuICAsIGNvbnN0RnVuYykge1xuICB0aGlzLl9nbCAgICAgICAgPSBnbFxuICB0aGlzLl93cmFwcGVyICAgPSB3cmFwcGVyXG4gIHRoaXMuX2luZGV4ICAgICA9IGluZGV4XG4gIHRoaXMuX2xvY2F0aW9ucyA9IGxvY2F0aW9uc1xuICB0aGlzLl9kaW1lbnNpb24gPSBkaW1lbnNpb25cbiAgdGhpcy5fY29uc3RGdW5jID0gY29uc3RGdW5jXG59XG5cbnZhciBwcm90byA9IFNoYWRlckF0dHJpYnV0ZS5wcm90b3R5cGVcblxucHJvdG8ucG9pbnRlciA9IGZ1bmN0aW9uIHNldEF0dHJpYlBvaW50ZXIoXG4gICAgdHlwZVxuICAsIG5vcm1hbGl6ZWRcbiAgLCBzdHJpZGVcbiAgLCBvZmZzZXQpIHtcblxuICB2YXIgc2VsZiAgICAgID0gdGhpc1xuICB2YXIgZ2wgICAgICAgID0gc2VsZi5fZ2xcbiAgdmFyIGxvY2F0aW9uICA9IHNlbGYuX2xvY2F0aW9uc1tzZWxmLl9pbmRleF1cblxuICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKFxuICAgICAgbG9jYXRpb25cbiAgICAsIHNlbGYuX2RpbWVuc2lvblxuICAgICwgdHlwZSB8fCBnbC5GTE9BVFxuICAgICwgISFub3JtYWxpemVkXG4gICAgLCBzdHJpZGUgfHwgMFxuICAgICwgb2Zmc2V0IHx8IDApXG4gIGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGxvY2F0aW9uKVxufVxuXG5wcm90by5zZXQgPSBmdW5jdGlvbih4MCwgeDEsIHgyLCB4Mykge1xuICByZXR1cm4gdGhpcy5fY29uc3RGdW5jKHRoaXMuX2xvY2F0aW9uc1t0aGlzLl9pbmRleF0sIHgwLCB4MSwgeDIsIHgzKVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sICdsb2NhdGlvbicsIHtcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fbG9jYXRpb25zW3RoaXMuX2luZGV4XVxuICB9XG4gICwgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgaWYodiAhPT0gdGhpcy5fbG9jYXRpb25zW3RoaXMuX2luZGV4XSkge1xuICAgICAgdGhpcy5fbG9jYXRpb25zW3RoaXMuX2luZGV4XSA9IHZ8MFxuICAgICAgdGhpcy5fd3JhcHBlci5wcm9ncmFtID0gbnVsbFxuICAgIH1cbiAgICByZXR1cm4gdnwwXG4gIH1cbn0pXG5cbi8vQWRkcyBhIHZlY3RvciBhdHRyaWJ1dGUgdG8gb2JqXG5mdW5jdGlvbiBhZGRWZWN0b3JBdHRyaWJ1dGUoXG4gICAgZ2xcbiAgLCB3cmFwcGVyXG4gICwgaW5kZXhcbiAgLCBsb2NhdGlvbnNcbiAgLCBkaW1lbnNpb25cbiAgLCBvYmpcbiAgLCBuYW1lKSB7XG5cbiAgLy9Db25zdHJ1Y3QgY29uc3RhbnQgZnVuY3Rpb25cbiAgdmFyIGNvbnN0RnVuY0FyZ3MgPSBbICdnbCcsICd2JyBdXG4gIHZhciB2YXJOYW1lcyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgY29uc3RGdW5jQXJncy5wdXNoKCd4JytpKVxuICAgIHZhck5hbWVzLnB1c2goJ3gnK2kpXG4gIH1cbiAgY29uc3RGdW5jQXJncy5wdXNoKFxuICAgICdpZih4MC5sZW5ndGg9PT12b2lkIDApe3JldHVybiBnbC52ZXJ0ZXhBdHRyaWInICtcbiAgICBkaW1lbnNpb24gKyAnZih2LCcgK1xuICAgIHZhck5hbWVzLmpvaW4oKSArXG4gICAgJyl9ZWxzZXtyZXR1cm4gZ2wudmVydGV4QXR0cmliJyArXG4gICAgZGltZW5zaW9uICtcbiAgICAnZnYodix4MCl9JylcbiAgdmFyIGNvbnN0RnVuYyA9IEZ1bmN0aW9uLmFwcGx5KG51bGwsIGNvbnN0RnVuY0FyZ3MpXG5cbiAgLy9DcmVhdGUgYXR0cmlidXRlIHdyYXBwZXJcbiAgdmFyIGF0dHIgPSBuZXcgU2hhZGVyQXR0cmlidXRlKFxuICAgICAgZ2xcbiAgICAsIHdyYXBwZXJcbiAgICAsIGluZGV4XG4gICAgLCBsb2NhdGlvbnNcbiAgICAsIGRpbWVuc2lvblxuICAgICwgY29uc3RGdW5jKVxuXG4gIC8vQ3JlYXRlIGFjY2Vzc29yXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIG5hbWUsIHtcbiAgICBzZXQ6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGdsLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShsb2NhdGlvbnNbaW5kZXhdKVxuICAgICAgY29uc3RGdW5jKGdsLCBsb2NhdGlvbnNbaW5kZXhdLCB4KVxuICAgICAgcmV0dXJuIHhcbiAgICB9XG4gICAgLCBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGF0dHJcbiAgICB9XG4gICAgLCBlbnVtZXJhYmxlOiB0cnVlXG4gIH0pXG59XG5cbmZ1bmN0aW9uIGFkZE1hdHJpeEF0dHJpYnV0ZShcbiAgICBnbFxuICAsIHdyYXBwZXJcbiAgLCBpbmRleFxuICAsIGxvY2F0aW9uc1xuICAsIGRpbWVuc2lvblxuICAsIG9ialxuICAsIG5hbWUpIHtcblxuICB2YXIgcGFydHMgPSBuZXcgQXJyYXkoZGltZW5zaW9uKVxuICB2YXIgYXR0cnMgPSBuZXcgQXJyYXkoZGltZW5zaW9uKVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGFkZFZlY3RvckF0dHJpYnV0ZShcbiAgICAgICAgZ2xcbiAgICAgICwgd3JhcHBlclxuICAgICAgLCBpbmRleFtpXVxuICAgICAgLCBsb2NhdGlvbnNcbiAgICAgICwgZGltZW5zaW9uXG4gICAgICAsIHBhcnRzXG4gICAgICAsIGkpXG4gICAgYXR0cnNbaV0gPSBwYXJ0c1tpXVxuICB9XG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHBhcnRzLCAnbG9jYXRpb24nLCB7XG4gICAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgICBpZihBcnJheS5pc0FycmF5KHYpKSB7XG4gICAgICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgICAgICAgYXR0cnNbaV0ubG9jYXRpb24gPSB2W2ldXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgICAgICAgYXR0cnNbaV0ubG9jYXRpb24gPSB2ICsgaVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdlxuICAgIH1cbiAgICAsIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgICAgIHJlc3VsdFtpXSA9IGxvY2F0aW9uc1tpbmRleFtpXV1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG4gICAgLCBlbnVtZXJhYmxlOiB0cnVlXG4gIH0pXG5cbiAgcGFydHMucG9pbnRlciA9IGZ1bmN0aW9uKHR5cGUsIG5vcm1hbGl6ZWQsIHN0cmlkZSwgb2Zmc2V0KSB7XG4gICAgdHlwZSAgICAgICA9IHR5cGUgfHwgZ2wuRkxPQVRcbiAgICBub3JtYWxpemVkID0gISFub3JtYWxpemVkXG4gICAgc3RyaWRlICAgICA9IHN0cmlkZSB8fCAoZGltZW5zaW9uICogZGltZW5zaW9uKVxuICAgIG9mZnNldCAgICAgPSBvZmZzZXQgfHwgMFxuICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgICB2YXIgbG9jYXRpb24gPSBsb2NhdGlvbnNbaW5kZXhbaV1dXG4gICAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKFxuICAgICAgICAgICAgbG9jYXRpb25cbiAgICAgICAgICAsIGRpbWVuc2lvblxuICAgICAgICAgICwgdHlwZVxuICAgICAgICAgICwgbm9ybWFsaXplZFxuICAgICAgICAgICwgc3RyaWRlXG4gICAgICAgICAgLCBvZmZzZXQgKyBpICogZGltZW5zaW9uKVxuICAgICAgZ2wuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkobG9jYXRpb24pXG4gICAgfVxuICB9XG5cbiAgdmFyIHNjcmF0Y2ggPSBuZXcgQXJyYXkoZGltZW5zaW9uKVxuICB2YXIgdmVydGV4QXR0cmliID0gZ2xbJ3ZlcnRleEF0dHJpYicgKyBkaW1lbnNpb24gKyAnZnYnXVxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIG5hbWUsIHtcbiAgICBzZXQ6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgICAgIHZhciBsb2MgPSBsb2NhdGlvbnNbaW5kZXhbaV1dXG4gICAgICAgIGdsLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShsb2MpXG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoeFswXSkpIHtcbiAgICAgICAgICB2ZXJ0ZXhBdHRyaWIuY2FsbChnbCwgbG9jLCB4W2ldKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGZvcih2YXIgaj0wOyBqPGRpbWVuc2lvbjsgKytqKSB7XG4gICAgICAgICAgICBzY3JhdGNoW2pdID0geFtkaW1lbnNpb24qaSArIGpdXG4gICAgICAgICAgfVxuICAgICAgICAgIHZlcnRleEF0dHJpYi5jYWxsKGdsLCBsb2MsIHNjcmF0Y2gpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB4XG4gICAgfVxuICAgICwgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwYXJ0c1xuICAgIH1cbiAgICAsIGVudW1lcmFibGU6IHRydWVcbiAgfSlcbn1cblxuLy9DcmVhdGUgc2hpbXMgZm9yIGF0dHJpYnV0ZXNcbmZ1bmN0aW9uIGNyZWF0ZUF0dHJpYnV0ZVdyYXBwZXIoXG4gICAgZ2xcbiAgLCB3cmFwcGVyXG4gICwgYXR0cmlidXRlc1xuICAsIGxvY2F0aW9ucykge1xuXG4gIHZhciBvYmogPSB7fVxuICBmb3IodmFyIGk9MCwgbj1hdHRyaWJ1dGVzLmxlbmd0aDsgaTxuOyArK2kpIHtcblxuICAgIHZhciBhID0gYXR0cmlidXRlc1tpXVxuICAgIHZhciBuYW1lID0gYS5uYW1lXG4gICAgdmFyIHR5cGUgPSBhLnR5cGVcbiAgICB2YXIgbG9jcyA9IGEubG9jYXRpb25zXG5cbiAgICBzd2l0Y2godHlwZSkge1xuICAgICAgY2FzZSAnYm9vbCc6XG4gICAgICBjYXNlICdpbnQnOlxuICAgICAgY2FzZSAnZmxvYXQnOlxuICAgICAgICBhZGRWZWN0b3JBdHRyaWJ1dGUoXG4gICAgICAgICAgICBnbFxuICAgICAgICAgICwgd3JhcHBlclxuICAgICAgICAgICwgbG9jc1swXVxuICAgICAgICAgICwgbG9jYXRpb25zXG4gICAgICAgICAgLCAxXG4gICAgICAgICAgLCBvYmpcbiAgICAgICAgICAsIG5hbWUpXG4gICAgICBicmVha1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZih0eXBlLmluZGV4T2YoJ3ZlYycpID49IDApIHtcbiAgICAgICAgICB2YXIgZCA9IHR5cGUuY2hhckNvZGVBdCh0eXBlLmxlbmd0aC0xKSAtIDQ4XG4gICAgICAgICAgaWYoZCA8IDIgfHwgZCA+IDQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBHTEVycm9yKCcnLCAnSW52YWxpZCBkYXRhIHR5cGUgZm9yIGF0dHJpYnV0ZSAnICsgbmFtZSArICc6ICcgKyB0eXBlKVxuICAgICAgICAgIH1cbiAgICAgICAgICBhZGRWZWN0b3JBdHRyaWJ1dGUoXG4gICAgICAgICAgICAgIGdsXG4gICAgICAgICAgICAsIHdyYXBwZXJcbiAgICAgICAgICAgICwgbG9jc1swXVxuICAgICAgICAgICAgLCBsb2NhdGlvbnNcbiAgICAgICAgICAgICwgZFxuICAgICAgICAgICAgLCBvYmpcbiAgICAgICAgICAgICwgbmFtZSlcbiAgICAgICAgfSBlbHNlIGlmKHR5cGUuaW5kZXhPZignbWF0JykgPj0gMCkge1xuICAgICAgICAgIHZhciBkID0gdHlwZS5jaGFyQ29kZUF0KHR5cGUubGVuZ3RoLTEpIC0gNDhcbiAgICAgICAgICBpZihkIDwgMiB8fCBkID4gNCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEdMRXJyb3IoJycsICdJbnZhbGlkIGRhdGEgdHlwZSBmb3IgYXR0cmlidXRlICcgKyBuYW1lICsgJzogJyArIHR5cGUpXG4gICAgICAgICAgfVxuICAgICAgICAgIGFkZE1hdHJpeEF0dHJpYnV0ZShcbiAgICAgICAgICAgICAgZ2xcbiAgICAgICAgICAgICwgd3JhcHBlclxuICAgICAgICAgICAgLCBsb2NzXG4gICAgICAgICAgICAsIGxvY2F0aW9uc1xuICAgICAgICAgICAgLCBkXG4gICAgICAgICAgICAsIG9ialxuICAgICAgICAgICAgLCBuYW1lKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBHTEVycm9yKCcnLCAnVW5rbm93biBkYXRhIHR5cGUgZm9yIGF0dHJpYnV0ZSAnICsgbmFtZSArICc6ICcgKyB0eXBlKVxuICAgICAgICB9XG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuICByZXR1cm4gb2JqXG59XG5cbn0se1wiLi9HTEVycm9yXCI6MzAyfV0sMzA0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgY29hbGxlc2NlVW5pZm9ybXMgPSBfZGVyZXFfKCcuL3JlZmxlY3QnKVxudmFyIEdMRXJyb3IgPSBfZGVyZXFfKFwiLi9HTEVycm9yXCIpXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVW5pZm9ybVdyYXBwZXJcblxuLy9CaW5kcyBhIGZ1bmN0aW9uIGFuZCByZXR1cm5zIGEgdmFsdWVcbmZ1bmN0aW9uIGlkZW50aXR5KHgpIHtcbiAgdmFyIGMgPSBuZXcgRnVuY3Rpb24oJ3knLCAncmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHl9JylcbiAgcmV0dXJuIGMoeClcbn1cblxuZnVuY3Rpb24gbWFrZVZlY3RvcihsZW5ndGgsIGZpbGwpIHtcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShsZW5ndGgpXG4gIGZvcih2YXIgaT0wOyBpPGxlbmd0aDsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gZmlsbFxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuLy9DcmVhdGUgc2hpbXMgZm9yIHVuaWZvcm1zXG5mdW5jdGlvbiBjcmVhdGVVbmlmb3JtV3JhcHBlcihnbCwgd3JhcHBlciwgdW5pZm9ybXMsIGxvY2F0aW9ucykge1xuXG4gIGZ1bmN0aW9uIG1ha2VHZXR0ZXIoaW5kZXgpIHtcbiAgICB2YXIgcHJvYyA9IG5ldyBGdW5jdGlvbihcbiAgICAgICAgJ2dsJ1xuICAgICAgLCAnd3JhcHBlcidcbiAgICAgICwgJ2xvY2F0aW9ucydcbiAgICAgICwgJ3JldHVybiBmdW5jdGlvbigpe3JldHVybiBnbC5nZXRVbmlmb3JtKHdyYXBwZXIucHJvZ3JhbSxsb2NhdGlvbnNbJyArIGluZGV4ICsgJ10pfScpXG4gICAgcmV0dXJuIHByb2MoZ2wsIHdyYXBwZXIsIGxvY2F0aW9ucylcbiAgfVxuXG4gIGZ1bmN0aW9uIG1ha2VQcm9wU2V0dGVyKHBhdGgsIGluZGV4LCB0eXBlKSB7XG4gICAgc3dpdGNoKHR5cGUpIHtcbiAgICAgIGNhc2UgJ2Jvb2wnOlxuICAgICAgY2FzZSAnaW50JzpcbiAgICAgIGNhc2UgJ3NhbXBsZXIyRCc6XG4gICAgICBjYXNlICdzYW1wbGVyQ3ViZSc6XG4gICAgICAgIHJldHVybiAnZ2wudW5pZm9ybTFpKGxvY2F0aW9uc1snICsgaW5kZXggKyAnXSxvYmonICsgcGF0aCArICcpJ1xuICAgICAgY2FzZSAnZmxvYXQnOlxuICAgICAgICByZXR1cm4gJ2dsLnVuaWZvcm0xZihsb2NhdGlvbnNbJyArIGluZGV4ICsgJ10sb2JqJyArIHBhdGggKyAnKSdcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHZhciB2aWR4ID0gdHlwZS5pbmRleE9mKCd2ZWMnKVxuICAgICAgICBpZigwIDw9IHZpZHggJiYgdmlkeCA8PSAxICYmIHR5cGUubGVuZ3RoID09PSA0ICsgdmlkeCkge1xuICAgICAgICAgIHZhciBkID0gdHlwZS5jaGFyQ29kZUF0KHR5cGUubGVuZ3RoLTEpIC0gNDhcbiAgICAgICAgICBpZihkIDwgMiB8fCBkID4gNCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEdMRXJyb3IoJycsICdJbnZhbGlkIGRhdGEgdHlwZScpXG4gICAgICAgICAgfVxuICAgICAgICAgIHN3aXRjaCh0eXBlLmNoYXJBdCgwKSkge1xuICAgICAgICAgICAgY2FzZSAnYic6XG4gICAgICAgICAgICBjYXNlICdpJzpcbiAgICAgICAgICAgICAgcmV0dXJuICdnbC51bmlmb3JtJyArIGQgKyAnaXYobG9jYXRpb25zWycgKyBpbmRleCArICddLG9iaicgKyBwYXRoICsgJyknXG4gICAgICAgICAgICBjYXNlICd2JzpcbiAgICAgICAgICAgICAgcmV0dXJuICdnbC51bmlmb3JtJyArIGQgKyAnZnYobG9jYXRpb25zWycgKyBpbmRleCArICddLG9iaicgKyBwYXRoICsgJyknXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICB0aHJvdyBuZXcgR0xFcnJvcignJywgJ1VucmVjb2duaXplZCBkYXRhIHR5cGUgZm9yIHZlY3RvciAnICsgbmFtZSArICc6ICcgKyB0eXBlKVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKHR5cGUuaW5kZXhPZignbWF0JykgPT09IDAgJiYgdHlwZS5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgICB2YXIgZCA9IHR5cGUuY2hhckNvZGVBdCh0eXBlLmxlbmd0aC0xKSAtIDQ4XG4gICAgICAgICAgaWYoZCA8IDIgfHwgZCA+IDQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBHTEVycm9yKCcnLCAnSW52YWxpZCB1bmlmb3JtIGRpbWVuc2lvbiB0eXBlIGZvciBtYXRyaXggJyArIG5hbWUgKyAnOiAnICsgdHlwZSlcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuICdnbC51bmlmb3JtTWF0cml4JyArIGQgKyAnZnYobG9jYXRpb25zWycgKyBpbmRleCArICddLGZhbHNlLG9iaicgKyBwYXRoICsgJyknXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEdMRXJyb3IoJycsICdVbmtub3duIHVuaWZvcm0gZGF0YSB0eXBlIGZvciAnICsgbmFtZSArICc6ICcgKyB0eXBlKVxuICAgICAgICB9XG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGVudW1lcmF0ZUluZGljZXMocHJlZml4LCB0eXBlKSB7XG4gICAgaWYodHlwZW9mIHR5cGUgIT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gWyBbcHJlZml4LCB0eXBlXSBdXG4gICAgfVxuICAgIHZhciBpbmRpY2VzID0gW11cbiAgICBmb3IodmFyIGlkIGluIHR5cGUpIHtcbiAgICAgIHZhciBwcm9wID0gdHlwZVtpZF1cbiAgICAgIHZhciB0cHJlZml4ID0gcHJlZml4XG4gICAgICBpZihwYXJzZUludChpZCkgKyAnJyA9PT0gaWQpIHtcbiAgICAgICAgdHByZWZpeCArPSAnWycgKyBpZCArICddJ1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHByZWZpeCArPSAnLicgKyBpZFxuICAgICAgfVxuICAgICAgaWYodHlwZW9mIHByb3AgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGluZGljZXMucHVzaC5hcHBseShpbmRpY2VzLCBlbnVtZXJhdGVJbmRpY2VzKHRwcmVmaXgsIHByb3ApKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5kaWNlcy5wdXNoKFt0cHJlZml4LCBwcm9wXSlcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGluZGljZXNcbiAgfVxuXG4gIGZ1bmN0aW9uIG1ha2VTZXR0ZXIodHlwZSkge1xuICAgIHZhciBjb2RlID0gWyAncmV0dXJuIGZ1bmN0aW9uIHVwZGF0ZVByb3BlcnR5KG9iail7JyBdXG4gICAgdmFyIGluZGljZXMgPSBlbnVtZXJhdGVJbmRpY2VzKCcnLCB0eXBlKVxuICAgIGZvcih2YXIgaT0wOyBpPGluZGljZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBpdGVtID0gaW5kaWNlc1tpXVxuICAgICAgdmFyIHBhdGggPSBpdGVtWzBdXG4gICAgICB2YXIgaWR4ICA9IGl0ZW1bMV1cbiAgICAgIGlmKGxvY2F0aW9uc1tpZHhdKSB7XG4gICAgICAgIGNvZGUucHVzaChtYWtlUHJvcFNldHRlcihwYXRoLCBpZHgsIHVuaWZvcm1zW2lkeF0udHlwZSkpXG4gICAgICB9XG4gICAgfVxuICAgIGNvZGUucHVzaCgncmV0dXJuIG9ian0nKVxuICAgIHZhciBwcm9jID0gbmV3IEZ1bmN0aW9uKCdnbCcsICdsb2NhdGlvbnMnLCBjb2RlLmpvaW4oJ1xcbicpKVxuICAgIHJldHVybiBwcm9jKGdsLCBsb2NhdGlvbnMpXG4gIH1cblxuICBmdW5jdGlvbiBkZWZhdWx0VmFsdWUodHlwZSkge1xuICAgIHN3aXRjaCh0eXBlKSB7XG4gICAgICBjYXNlICdib29sJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICBjYXNlICdpbnQnOlxuICAgICAgY2FzZSAnc2FtcGxlcjJEJzpcbiAgICAgIGNhc2UgJ3NhbXBsZXJDdWJlJzpcbiAgICAgICAgcmV0dXJuIDBcbiAgICAgIGNhc2UgJ2Zsb2F0JzpcbiAgICAgICAgcmV0dXJuIDAuMFxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdmFyIHZpZHggPSB0eXBlLmluZGV4T2YoJ3ZlYycpXG4gICAgICAgIGlmKDAgPD0gdmlkeCAmJiB2aWR4IDw9IDEgJiYgdHlwZS5sZW5ndGggPT09IDQgKyB2aWR4KSB7XG4gICAgICAgICAgdmFyIGQgPSB0eXBlLmNoYXJDb2RlQXQodHlwZS5sZW5ndGgtMSkgLSA0OFxuICAgICAgICAgIGlmKGQgPCAyIHx8IGQgPiA0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgR0xFcnJvcignJywgJ0ludmFsaWQgZGF0YSB0eXBlJylcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYodHlwZS5jaGFyQXQoMCkgPT09ICdiJykge1xuICAgICAgICAgICAgcmV0dXJuIG1ha2VWZWN0b3IoZCwgZmFsc2UpXG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBtYWtlVmVjdG9yKGQsIDApXG4gICAgICAgIH0gZWxzZSBpZih0eXBlLmluZGV4T2YoJ21hdCcpID09PSAwICYmIHR5cGUubGVuZ3RoID09PSA0KSB7XG4gICAgICAgICAgdmFyIGQgPSB0eXBlLmNoYXJDb2RlQXQodHlwZS5sZW5ndGgtMSkgLSA0OFxuICAgICAgICAgIGlmKGQgPCAyIHx8IGQgPiA0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgR0xFcnJvcignJywgJ0ludmFsaWQgdW5pZm9ybSBkaW1lbnNpb24gdHlwZSBmb3IgbWF0cml4ICcgKyBuYW1lICsgJzogJyArIHR5cGUpXG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBtYWtlVmVjdG9yKGQqZCwgMClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgR0xFcnJvcignJywgJ1Vua25vd24gdW5pZm9ybSBkYXRhIHR5cGUgZm9yICcgKyBuYW1lICsgJzogJyArIHR5cGUpXG4gICAgICAgIH1cbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc3RvcmVQcm9wZXJ0eShvYmosIHByb3AsIHR5cGUpIHtcbiAgICBpZih0eXBlb2YgdHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHZhciBjaGlsZCA9IHByb2Nlc3NPYmplY3QodHlwZSlcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIHByb3AsIHtcbiAgICAgICAgZ2V0OiBpZGVudGl0eShjaGlsZCksXG4gICAgICAgIHNldDogbWFrZVNldHRlcih0eXBlKSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZVxuICAgICAgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgaWYobG9jYXRpb25zW3R5cGVdKSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIHByb3AsIHtcbiAgICAgICAgICBnZXQ6IG1ha2VHZXR0ZXIodHlwZSksXG4gICAgICAgICAgc2V0OiBtYWtlU2V0dGVyKHR5cGUpLFxuICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZVxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb2JqW3Byb3BdID0gZGVmYXVsdFZhbHVlKHVuaWZvcm1zW3R5cGVdLnR5cGUpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcHJvY2Vzc09iamVjdChvYmopIHtcbiAgICB2YXIgcmVzdWx0XG4gICAgaWYoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgICByZXN1bHQgPSBuZXcgQXJyYXkob2JqLmxlbmd0aClcbiAgICAgIGZvcih2YXIgaT0wOyBpPG9iai5sZW5ndGg7ICsraSkge1xuICAgICAgICBzdG9yZVByb3BlcnR5KHJlc3VsdCwgaSwgb2JqW2ldKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQgPSB7fVxuICAgICAgZm9yKHZhciBpZCBpbiBvYmopIHtcbiAgICAgICAgc3RvcmVQcm9wZXJ0eShyZXN1bHQsIGlkLCBvYmpbaWRdKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICAvL1JldHVybiBkYXRhXG4gIHZhciBjb2FsbGVzY2VkID0gY29hbGxlc2NlVW5pZm9ybXModW5pZm9ybXMsIHRydWUpXG4gIHJldHVybiB7XG4gICAgZ2V0OiBpZGVudGl0eShwcm9jZXNzT2JqZWN0KGNvYWxsZXNjZWQpKSxcbiAgICBzZXQ6IG1ha2VTZXR0ZXIoY29hbGxlc2NlZCksXG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICBjb25maWd1cmFibGU6IHRydWVcbiAgfVxufVxuXG59LHtcIi4vR0xFcnJvclwiOjMwMixcIi4vcmVmbGVjdFwiOjMwNX1dLDMwNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBtYWtlUmVmbGVjdFR5cGVzXG5cbi8vQ29uc3RydWN0IHR5cGUgaW5mbyBmb3IgcmVmbGVjdGlvbi5cbi8vXG4vLyBUaGlzIGl0ZXJhdGVzIG92ZXIgdGhlIGZsYXR0ZW5lZCBsaXN0IG9mIHVuaWZvcm0gdHlwZSB2YWx1ZXMgYW5kIHNtYXNoZXMgdGhlbSBpbnRvIGEgSlNPTiBvYmplY3QuXG4vL1xuLy8gVGhlIGxlYXZlcyBvZiB0aGUgcmVzdWx0aW5nIG9iamVjdCBhcmUgZWl0aGVyIGluZGljZXMgb3IgdHlwZSBzdHJpbmdzIHJlcHJlc2VudGluZyBwcmltaXRpdmUgZ2xzbGlmeSB0eXBlc1xuZnVuY3Rpb24gbWFrZVJlZmxlY3RUeXBlcyh1bmlmb3JtcywgdXNlSW5kZXgpIHtcbiAgdmFyIG9iaiA9IHt9XG4gIGZvcih2YXIgaT0wOyBpPHVuaWZvcm1zLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIG4gPSB1bmlmb3Jtc1tpXS5uYW1lXG4gICAgdmFyIHBhcnRzID0gbi5zcGxpdChcIi5cIilcbiAgICB2YXIgbyA9IG9ialxuICAgIGZvcih2YXIgaj0wOyBqPHBhcnRzLmxlbmd0aDsgKytqKSB7XG4gICAgICB2YXIgeCA9IHBhcnRzW2pdLnNwbGl0KFwiW1wiKVxuICAgICAgaWYoeC5sZW5ndGggPiAxKSB7XG4gICAgICAgIGlmKCEoeFswXSBpbiBvKSkge1xuICAgICAgICAgIG9beFswXV0gPSBbXVxuICAgICAgICB9XG4gICAgICAgIG8gPSBvW3hbMF1dXG4gICAgICAgIGZvcih2YXIgaz0xOyBrPHgubGVuZ3RoOyArK2spIHtcbiAgICAgICAgICB2YXIgeSA9IHBhcnNlSW50KHhba10pXG4gICAgICAgICAgaWYoazx4Lmxlbmd0aC0xIHx8IGo8cGFydHMubGVuZ3RoLTEpIHtcbiAgICAgICAgICAgIGlmKCEoeSBpbiBvKSkge1xuICAgICAgICAgICAgICBpZihrIDwgeC5sZW5ndGgtMSkge1xuICAgICAgICAgICAgICAgIG9beV0gPSBbXVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9beV0gPSB7fVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvID0gb1t5XVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZih1c2VJbmRleCkge1xuICAgICAgICAgICAgICBvW3ldID0gaVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgb1t5XSA9IHVuaWZvcm1zW2ldLnR5cGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZihqIDwgcGFydHMubGVuZ3RoLTEpIHtcbiAgICAgICAgaWYoISh4WzBdIGluIG8pKSB7XG4gICAgICAgICAgb1t4WzBdXSA9IHt9XG4gICAgICAgIH1cbiAgICAgICAgbyA9IG9beFswXV1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKHVzZUluZGV4KSB7XG4gICAgICAgICAgb1t4WzBdXSA9IGlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvW3hbMF1dID0gdW5pZm9ybXNbaV0udHlwZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBvYmpcbn1cbn0se31dLDMwNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxuZXhwb3J0cy51bmlmb3JtcyAgICA9IHJ1bnRpbWVVbmlmb3Jtc1xuZXhwb3J0cy5hdHRyaWJ1dGVzICA9IHJ1bnRpbWVBdHRyaWJ1dGVzXG5cbnZhciBHTF9UT19HTFNMX1RZUEVTID0ge1xuICAnRkxPQVQnOiAgICAgICAnZmxvYXQnLFxuICAnRkxPQVRfVkVDMic6ICAndmVjMicsXG4gICdGTE9BVF9WRUMzJzogICd2ZWMzJyxcbiAgJ0ZMT0FUX1ZFQzQnOiAgJ3ZlYzQnLFxuICAnSU5UJzogICAgICAgICAnaW50JyxcbiAgJ0lOVF9WRUMyJzogICAgJ2l2ZWMyJyxcbiAgJ0lOVF9WRUMzJzogICAgJ2l2ZWMzJyxcbiAgJ0lOVF9WRUM0JzogICAgJ2l2ZWM0JyxcbiAgJ0JPT0wnOiAgICAgICAgJ2Jvb2wnLFxuICAnQk9PTF9WRUMyJzogICAnYnZlYzInLFxuICAnQk9PTF9WRUMzJzogICAnYnZlYzMnLFxuICAnQk9PTF9WRUM0JzogICAnYnZlYzQnLFxuICAnRkxPQVRfTUFUMic6ICAnbWF0MicsXG4gICdGTE9BVF9NQVQzJzogICdtYXQzJyxcbiAgJ0ZMT0FUX01BVDQnOiAgJ21hdDQnLFxuICAnU0FNUExFUl8yRCc6ICAnc2FtcGxlcjJEJyxcbiAgJ1NBTVBMRVJfQ1VCRSc6J3NhbXBsZXJDdWJlJ1xufVxuXG52YXIgR0xfVEFCTEUgPSBudWxsXG5cbmZ1bmN0aW9uIGdldFR5cGUoZ2wsIHR5cGUpIHtcbiAgaWYoIUdMX1RBQkxFKSB7XG4gICAgdmFyIHR5cGVOYW1lcyA9IE9iamVjdC5rZXlzKEdMX1RPX0dMU0xfVFlQRVMpXG4gICAgR0xfVEFCTEUgPSB7fVxuICAgIGZvcih2YXIgaT0wOyBpPHR5cGVOYW1lcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIHRuID0gdHlwZU5hbWVzW2ldXG4gICAgICBHTF9UQUJMRVtnbFt0bl1dID0gR0xfVE9fR0xTTF9UWVBFU1t0bl1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIEdMX1RBQkxFW3R5cGVdXG59XG5cbmZ1bmN0aW9uIHJ1bnRpbWVVbmlmb3JtcyhnbCwgcHJvZ3JhbSkge1xuICB2YXIgbnVtVW5pZm9ybXMgPSBnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIGdsLkFDVElWRV9VTklGT1JNUylcbiAgdmFyIHJlc3VsdCA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPG51bVVuaWZvcm1zOyArK2kpIHtcbiAgICB2YXIgaW5mbyA9IGdsLmdldEFjdGl2ZVVuaWZvcm0ocHJvZ3JhbSwgaSlcbiAgICBpZihpbmZvKSB7XG4gICAgICB2YXIgdHlwZSA9IGdldFR5cGUoZ2wsIGluZm8udHlwZSlcbiAgICAgIGlmKGluZm8uc2l6ZSA+IDEpIHtcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8aW5mby5zaXplOyArK2opIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgICAgICBuYW1lOiBpbmZvLm5hbWUucmVwbGFjZSgnWzBdJywgJ1snICsgaiArICddJyksXG4gICAgICAgICAgICB0eXBlOiB0eXBlXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0LnB1c2goe1xuICAgICAgICAgIG5hbWU6IGluZm8ubmFtZSxcbiAgICAgICAgICB0eXBlOiB0eXBlXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gcnVudGltZUF0dHJpYnV0ZXMoZ2wsIHByb2dyYW0pIHtcbiAgdmFyIG51bUF0dHJpYnV0ZXMgPSBnbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHByb2dyYW0sIGdsLkFDVElWRV9BVFRSSUJVVEVTKVxuICB2YXIgcmVzdWx0ID0gW11cbiAgZm9yKHZhciBpPTA7IGk8bnVtQXR0cmlidXRlczsgKytpKSB7XG4gICAgdmFyIGluZm8gPSBnbC5nZXRBY3RpdmVBdHRyaWIocHJvZ3JhbSwgaSlcbiAgICBpZihpbmZvKSB7XG4gICAgICByZXN1bHQucHVzaCh7XG4gICAgICAgIG5hbWU6IGluZm8ubmFtZSxcbiAgICAgICAgdHlwZTogZ2V0VHlwZShnbCwgaW5mby50eXBlKVxuICAgICAgfSlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG59LHt9XSwzMDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbmV4cG9ydHMuc2hhZGVyICAgPSBnZXRTaGFkZXJSZWZlcmVuY2VcbmV4cG9ydHMucHJvZ3JhbSAgPSBjcmVhdGVQcm9ncmFtXG5cbnZhciBHTEVycm9yID0gX2RlcmVxXyhcIi4vR0xFcnJvclwiKVxudmFyIGZvcm1hdENvbXBpbGVyRXJyb3IgPSBfZGVyZXFfKCdnbC1mb3JtYXQtY29tcGlsZXItZXJyb3InKTtcblxudmFyIHdlYWtNYXAgPSB0eXBlb2YgV2Vha01hcCA9PT0gJ3VuZGVmaW5lZCcgPyBfZGVyZXFfKCd3ZWFrbWFwLXNoaW0nKSA6IFdlYWtNYXBcbnZhciBDQUNIRSA9IG5ldyB3ZWFrTWFwKClcblxudmFyIFNIQURFUl9DT1VOVEVSID0gMFxuXG5mdW5jdGlvbiBTaGFkZXJSZWZlcmVuY2UoaWQsIHNyYywgdHlwZSwgc2hhZGVyLCBwcm9ncmFtcywgY291bnQsIGNhY2hlKSB7XG4gIHRoaXMuaWQgICAgICAgPSBpZFxuICB0aGlzLnNyYyAgICAgID0gc3JjXG4gIHRoaXMudHlwZSAgICAgPSB0eXBlXG4gIHRoaXMuc2hhZGVyICAgPSBzaGFkZXJcbiAgdGhpcy5jb3VudCAgICA9IGNvdW50XG4gIHRoaXMucHJvZ3JhbXMgPSBbXVxuICB0aGlzLmNhY2hlICAgID0gY2FjaGVcbn1cblxuU2hhZGVyUmVmZXJlbmNlLnByb3RvdHlwZS5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gIGlmKC0tdGhpcy5jb3VudCA9PT0gMCkge1xuICAgIHZhciBjYWNoZSAgICA9IHRoaXMuY2FjaGVcbiAgICB2YXIgZ2wgICAgICAgPSBjYWNoZS5nbFxuXG4gICAgLy9SZW1vdmUgcHJvZ3JhbSByZWZlcmVuY2VzXG4gICAgdmFyIHByb2dyYW1zID0gdGhpcy5wcm9ncmFtc1xuICAgIGZvcih2YXIgaT0wLCBuPXByb2dyYW1zLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICAgIHZhciBwID0gY2FjaGUucHJvZ3JhbXNbcHJvZ3JhbXNbaV1dXG4gICAgICBpZihwKSB7XG4gICAgICAgIGRlbGV0ZSBjYWNoZS5wcm9ncmFtc1tpXVxuICAgICAgICBnbC5kZWxldGVQcm9ncmFtKHApXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy9SZW1vdmUgc2hhZGVyIHJlZmVyZW5jZVxuICAgIGdsLmRlbGV0ZVNoYWRlcih0aGlzLnNoYWRlcilcbiAgICBkZWxldGUgY2FjaGUuc2hhZGVyc1sodGhpcy50eXBlID09PSBnbC5GUkFHTUVOVF9TSEFERVIpfDBdW3RoaXMuc3JjXVxuICB9XG59XG5cbmZ1bmN0aW9uIENvbnRleHRDYWNoZShnbCkge1xuICB0aGlzLmdsICAgICAgID0gZ2xcbiAgdGhpcy5zaGFkZXJzICA9IFt7fSwge31dXG4gIHRoaXMucHJvZ3JhbXMgPSB7fVxufVxuXG52YXIgcHJvdG8gPSBDb250ZXh0Q2FjaGUucHJvdG90eXBlXG5cbmZ1bmN0aW9uIGNvbXBpbGVTaGFkZXIoZ2wsIHR5cGUsIHNyYykge1xuICB2YXIgc2hhZGVyID0gZ2wuY3JlYXRlU2hhZGVyKHR5cGUpXG4gIGdsLnNoYWRlclNvdXJjZShzaGFkZXIsIHNyYylcbiAgZ2wuY29tcGlsZVNoYWRlcihzaGFkZXIpXG4gIGlmKCFnbC5nZXRTaGFkZXJQYXJhbWV0ZXIoc2hhZGVyLCBnbC5DT01QSUxFX1NUQVRVUykpIHtcbiAgICB2YXIgZXJyTG9nID0gZ2wuZ2V0U2hhZGVySW5mb0xvZyhzaGFkZXIpXG4gICAgdHJ5IHtcbiAgICAgICAgdmFyIGZtdCA9IGZvcm1hdENvbXBpbGVyRXJyb3IoZXJyTG9nLCBzcmMsIHR5cGUpO1xuICAgIH0gY2F0Y2ggKGUpe1xuICAgICAgICBjb25zb2xlLndhcm4oJ0ZhaWxlZCB0byBmb3JtYXQgY29tcGlsZXIgZXJyb3I6ICcgKyBlKTtcbiAgICAgICAgdGhyb3cgbmV3IEdMRXJyb3IoZXJyTG9nLCAnRXJyb3IgY29tcGlsaW5nIHNoYWRlcjpcXG4nICsgZXJyTG9nKVxuICAgIH1cbiAgICB0aHJvdyBuZXcgR0xFcnJvcihlcnJMb2csIGZtdC5zaG9ydCwgZm10LmxvbmcpXG4gIH1cbiAgcmV0dXJuIHNoYWRlclxufVxuXG5wcm90by5nZXRTaGFkZXJSZWZlcmVuY2UgPSBmdW5jdGlvbih0eXBlLCBzcmMpIHtcbiAgdmFyIGdsICAgICAgPSB0aGlzLmdsXG4gIHZhciBzaGFkZXJzID0gdGhpcy5zaGFkZXJzWyh0eXBlID09PSBnbC5GUkFHTUVOVF9TSEFERVIpfDBdXG4gIHZhciBzaGFkZXIgID0gc2hhZGVyc1tzcmNdXG4gIGlmKCFzaGFkZXIgfHwgIWdsLmlzU2hhZGVyKHNoYWRlci5zaGFkZXIpKSB7XG4gICAgdmFyIHNoYWRlck9iaiA9IGNvbXBpbGVTaGFkZXIoZ2wsIHR5cGUsIHNyYylcbiAgICBzaGFkZXIgPSBzaGFkZXJzW3NyY10gPSBuZXcgU2hhZGVyUmVmZXJlbmNlKFxuICAgICAgU0hBREVSX0NPVU5URVIrKyxcbiAgICAgIHNyYyxcbiAgICAgIHR5cGUsXG4gICAgICBzaGFkZXJPYmosXG4gICAgICBbXSxcbiAgICAgIDEsXG4gICAgICB0aGlzKVxuICB9IGVsc2Uge1xuICAgIHNoYWRlci5jb3VudCArPSAxXG4gIH1cbiAgcmV0dXJuIHNoYWRlclxufVxuXG5mdW5jdGlvbiBsaW5rUHJvZ3JhbShnbCwgdnNoYWRlciwgZnNoYWRlciwgYXR0cmlicywgbG9jYXRpb25zKSB7XG4gIHZhciBwcm9ncmFtID0gZ2wuY3JlYXRlUHJvZ3JhbSgpXG4gIGdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCB2c2hhZGVyKVxuICBnbC5hdHRhY2hTaGFkZXIocHJvZ3JhbSwgZnNoYWRlcilcbiAgZm9yKHZhciBpPTA7IGk8YXR0cmlicy5sZW5ndGg7ICsraSkge1xuICAgIGdsLmJpbmRBdHRyaWJMb2NhdGlvbihwcm9ncmFtLCBsb2NhdGlvbnNbaV0sIGF0dHJpYnNbaV0pXG4gIH1cbiAgZ2wubGlua1Byb2dyYW0ocHJvZ3JhbSlcbiAgaWYoIWdsLmdldFByb2dyYW1QYXJhbWV0ZXIocHJvZ3JhbSwgZ2wuTElOS19TVEFUVVMpKSB7XG4gICAgdmFyIGVyckxvZyA9IGdsLmdldFByb2dyYW1JbmZvTG9nKHByb2dyYW0pXG4gICAgdGhyb3cgbmV3IEdMRXJyb3IoZXJyTG9nLCAnRXJyb3IgbGlua2luZyBwcm9ncmFtOiAnICsgZXJyTG9nKVxuICB9XG4gIHJldHVybiBwcm9ncmFtXG59XG5cbnByb3RvLmdldFByb2dyYW0gPSBmdW5jdGlvbih2cmVmLCBmcmVmLCBhdHRyaWJzLCBsb2NhdGlvbnMpIHtcbiAgdmFyIHRva2VuID0gW3ZyZWYuaWQsIGZyZWYuaWQsIGF0dHJpYnMuam9pbignOicpLCBsb2NhdGlvbnMuam9pbignOicpXS5qb2luKCdAJylcbiAgdmFyIHByb2cgID0gdGhpcy5wcm9ncmFtc1t0b2tlbl1cbiAgaWYoIXByb2cgfHwgIXRoaXMuZ2wuaXNQcm9ncmFtKHByb2cpKSB7XG4gICAgdGhpcy5wcm9ncmFtc1t0b2tlbl0gPSBwcm9nID0gbGlua1Byb2dyYW0oXG4gICAgICB0aGlzLmdsLFxuICAgICAgdnJlZi5zaGFkZXIsXG4gICAgICBmcmVmLnNoYWRlcixcbiAgICAgIGF0dHJpYnMsXG4gICAgICBsb2NhdGlvbnMpXG4gICAgdnJlZi5wcm9ncmFtcy5wdXNoKHRva2VuKVxuICAgIGZyZWYucHJvZ3JhbXMucHVzaCh0b2tlbilcbiAgfVxuICByZXR1cm4gcHJvZ1xufVxuXG5mdW5jdGlvbiBnZXRDYWNoZShnbCkge1xuICB2YXIgY3R4Q2FjaGUgPSBDQUNIRS5nZXQoZ2wpXG4gIGlmKCFjdHhDYWNoZSkge1xuICAgIGN0eENhY2hlID0gbmV3IENvbnRleHRDYWNoZShnbClcbiAgICBDQUNIRS5zZXQoZ2wsIGN0eENhY2hlKVxuICB9XG4gIHJldHVybiBjdHhDYWNoZVxufVxuXG5mdW5jdGlvbiBnZXRTaGFkZXJSZWZlcmVuY2UoZ2wsIHR5cGUsIHNyYykge1xuICByZXR1cm4gZ2V0Q2FjaGUoZ2wpLmdldFNoYWRlclJlZmVyZW5jZSh0eXBlLCBzcmMpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVByb2dyYW0oZ2wsIHZyZWYsIGZyZWYsIGF0dHJpYnMsIGxvY2F0aW9ucykge1xuICByZXR1cm4gZ2V0Q2FjaGUoZ2wpLmdldFByb2dyYW0odnJlZiwgZnJlZiwgYXR0cmlicywgbG9jYXRpb25zKVxufVxuXG59LHtcIi4vR0xFcnJvclwiOjMwMixcImdsLWZvcm1hdC1jb21waWxlci1lcnJvclwiOjI1MCxcIndlYWttYXAtc2hpbVwiOjU1NX1dLDMwODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTcGlrZXMyRFxuXG5mdW5jdGlvbiBHTFNwaWtlczJEKHBsb3QpIHtcbiAgdGhpcy5wbG90ID0gcGxvdFxuICB0aGlzLmVuYWJsZSA9IFt0cnVlLCB0cnVlLCBmYWxzZSwgZmFsc2VdXG4gIHRoaXMud2lkdGggID0gWzEsIDEsIDEsIDFdXG4gIHRoaXMuY29sb3IgID0gW1swLDAsMCwxXSxcbiAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICBbMCwwLDAsMV0sXG4gICAgICAgICAgICAgICAgIFswLDAsMCwxXV1cbiAgdGhpcy5jZW50ZXIgPSBbSW5maW5pdHksIEluZmluaXR5XVxufVxuXG52YXIgcHJvdG8gPSBHTFNwaWtlczJELnByb3RvdHlwZVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9XG4gIHRoaXMuZW5hYmxlID0gKG9wdGlvbnMuZW5hYmxlIHx8IFt0cnVlLHRydWUsZmFsc2UsZmFsc2VdKS5zbGljZSgpXG4gIHRoaXMud2lkdGggID0gKG9wdGlvbnMud2lkdGggfHwgWzEsMSwxLDFdKS5zbGljZSgpXG4gIHRoaXMuY29sb3IgID0gKG9wdGlvbnMuY29sb3IgfHwgW1xuICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdLFxuICAgICAgICAgICAgICAgICAgWzAsMCwwLDFdXSkubWFwKGZ1bmN0aW9uKHgpIHsgcmV0dXJuIHguc2xpY2UoKSB9KVxuICB0aGlzLmNlbnRlciA9IChvcHRpb25zLmNlbnRlciB8fCBbSW5maW5pdHksSW5maW5pdHldKS5zbGljZSgpXG4gIHRoaXMucGxvdC5zZXRPdmVybGF5RGlydHkoKVxufVxuXG5wcm90by5kcmF3ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzcGlrZUVuYWJsZSA9IHRoaXMuZW5hYmxlXG4gIHZhciBzcGlrZVdpZHRoICA9IHRoaXMud2lkdGhcbiAgdmFyIHNwaWtlQ29sb3IgID0gdGhpcy5jb2xvclxuICB2YXIgc3Bpa2VDZW50ZXIgPSB0aGlzLmNlbnRlclxuICB2YXIgcGxvdCAgICAgICAgPSB0aGlzLnBsb3RcbiAgdmFyIGxpbmUgICAgICAgID0gcGxvdC5saW5lXG5cbiAgdmFyIGRhdGFCb3ggICAgID0gcGxvdC5kYXRhQm94XG4gIHZhciB2aWV3UGl4ZWxzICA9IHBsb3Qudmlld0JveFxuXG4gIGxpbmUuYmluZCgpXG5cbiAgaWYoZGF0YUJveFswXSA8PSBzcGlrZUNlbnRlclswXSAmJiBzcGlrZUNlbnRlclswXSA8PSBkYXRhQm94WzJdICYmXG4gICAgIGRhdGFCb3hbMV0gPD0gc3Bpa2VDZW50ZXJbMV0gJiYgc3Bpa2VDZW50ZXJbMV0gPD0gZGF0YUJveFszXSkge1xuXG4gICAgdmFyIGNlbnRlclggPSB2aWV3UGl4ZWxzWzBdICsgKHNwaWtlQ2VudGVyWzBdIC0gZGF0YUJveFswXSkgLyAoZGF0YUJveFsyXSAtIGRhdGFCb3hbMF0pICogKHZpZXdQaXhlbHNbMl0gLSB2aWV3UGl4ZWxzWzBdKVxuICAgIHZhciBjZW50ZXJZID0gdmlld1BpeGVsc1sxXSArIChzcGlrZUNlbnRlclsxXSAtIGRhdGFCb3hbMV0pIC8gKGRhdGFCb3hbM10gLSBkYXRhQm94WzFdKSAqICh2aWV3UGl4ZWxzWzNdIC0gdmlld1BpeGVsc1sxXSlcblxuICAgIGlmKHNwaWtlRW5hYmxlWzBdKSB7XG4gICAgIGxpbmUuZHJhd0xpbmUoXG4gICAgICAgY2VudGVyWCwgY2VudGVyWSxcbiAgICAgICB2aWV3UGl4ZWxzWzBdLCBjZW50ZXJZLFxuICAgICAgIHNwaWtlV2lkdGhbMF0sIHNwaWtlQ29sb3JbMF0pXG4gICAgfVxuICAgIGlmKHNwaWtlRW5hYmxlWzFdKSB7XG4gICAgIGxpbmUuZHJhd0xpbmUoXG4gICAgICAgY2VudGVyWCwgY2VudGVyWSxcbiAgICAgICBjZW50ZXJYLCB2aWV3UGl4ZWxzWzFdLFxuICAgICAgIHNwaWtlV2lkdGhbMV0sIHNwaWtlQ29sb3JbMV0pXG4gICAgfVxuICAgIGlmKHNwaWtlRW5hYmxlWzJdKSB7XG4gICAgICBsaW5lLmRyYXdMaW5lKFxuICAgICAgICBjZW50ZXJYLCBjZW50ZXJZLFxuICAgICAgICB2aWV3UGl4ZWxzWzJdLCBjZW50ZXJZLFxuICAgICAgICBzcGlrZVdpZHRoWzJdLCBzcGlrZUNvbG9yWzJdKVxuICAgIH1cbiAgICBpZihzcGlrZUVuYWJsZVszXSkge1xuICAgICAgbGluZS5kcmF3TGluZShcbiAgICAgICAgY2VudGVyWCwgY2VudGVyWSxcbiAgICAgICAgY2VudGVyWCwgdmlld1BpeGVsc1szXSxcbiAgICAgICAgc3Bpa2VXaWR0aFszXSwgc3Bpa2VDb2xvclszXSlcbiAgICB9XG4gIH1cbn1cblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnBsb3QucmVtb3ZlT3ZlcmxheSh0aGlzKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVTcGlrZXMyRChwbG90LCBvcHRpb25zKSB7XG4gIHZhciBzcGlrZXMgPSBuZXcgR0xTcGlrZXMyRChwbG90KVxuICBzcGlrZXMudXBkYXRlKG9wdGlvbnMpXG4gIHBsb3QuYWRkT3ZlcmxheShzcGlrZXMpXG4gIHJldHVybiBzcGlrZXNcbn1cblxufSx7fV0sMzA5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgZ2xzbGlmeSAgICAgID0gX2RlcmVxXygnZ2xzbGlmeScpXG52YXIgY3JlYXRlU2hhZGVyID0gX2RlcmVxXygnZ2wtc2hhZGVyJylcblxudmFyIHZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxuYXR0cmlidXRlIHZlYzMgcG9zaXRpb24sIGNvbG9yO1xcbmF0dHJpYnV0ZSBmbG9hdCB3ZWlnaHQ7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gdmVjMyBjb29yZGluYXRlc1szXTtcXG51bmlmb3JtIHZlYzQgY29sb3JzWzNdO1xcbnVuaWZvcm0gdmVjMiBzY3JlZW5TaGFwZTtcXG51bmlmb3JtIGZsb2F0IGxpbmVXaWR0aDtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzMgdmVydGV4UG9zaXRpb24gPSBtaXgoY29vcmRpbmF0ZXNbMF0sXFxuICAgIG1peChjb29yZGluYXRlc1syXSwgY29vcmRpbmF0ZXNbMV0sIDAuNSAqIChwb3NpdGlvbiArIDEuMCkpLCBhYnMocG9zaXRpb24pKTtcXG5cXG4gIHZlYzQgY2xpcFBvcyA9IHByb2plY3Rpb24gKiB2aWV3ICogbW9kZWwgKiB2ZWM0KHZlcnRleFBvc2l0aW9uLCAxLjApO1xcbiAgdmVjMiBjbGlwT2Zmc2V0ID0gKHByb2plY3Rpb24gKiB2aWV3ICogbW9kZWwgKiB2ZWM0KGNvbG9yLCAwLjApKS54eTtcXG4gIHZlYzIgZGVsdGEgPSB3ZWlnaHQgKiBjbGlwT2Zmc2V0ICogc2NyZWVuU2hhcGU7XFxuICB2ZWMyIGxpbmVPZmZzZXQgPSBub3JtYWxpemUodmVjMihkZWx0YS55LCAtZGVsdGEueCkpIC8gc2NyZWVuU2hhcGU7XFxuXFxuICBnbF9Qb3NpdGlvbiAgID0gdmVjNChjbGlwUG9zLnh5ICsgY2xpcFBvcy53ICogMC41ICogbGluZVdpZHRoICogbGluZU9mZnNldCwgY2xpcFBvcy56LCBjbGlwUG9zLncpO1xcbiAgZnJhZ0NvbG9yICAgICA9IGNvbG9yLnggKiBjb2xvcnNbMF0gKyBjb2xvci55ICogY29sb3JzWzFdICsgY29sb3IueiAqIGNvbG9yc1syXTtcXG59XFxuXCJdKVxudmFyIGZyYWdTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBnbF9GcmFnQ29sb3IgPSBmcmFnQ29sb3I7XFxufVwiXSlcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihnbCkge1xuICByZXR1cm4gY3JlYXRlU2hhZGVyKGdsLCB2ZXJ0U3JjLCBmcmFnU3JjLCBudWxsLCBbXG4gICAge25hbWU6ICdwb3NpdGlvbicsIHR5cGU6ICd2ZWMzJ30sXG4gICAge25hbWU6ICdjb2xvcicsIHR5cGU6ICd2ZWMzJ30sXG4gICAge25hbWU6ICd3ZWlnaHQnLCB0eXBlOiAnZmxvYXQnfVxuICBdKVxufVxuXG59LHtcImdsLXNoYWRlclwiOjMwMSxcImdsc2xpZnlcIjo0MDl9XSwzMTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBjcmVhdGVCdWZmZXIgPSBfZGVyZXFfKCdnbC1idWZmZXInKVxudmFyIGNyZWF0ZVZBTyA9IF9kZXJlcV8oJ2dsLXZhbycpXG52YXIgY3JlYXRlU2hhZGVyID0gX2RlcmVxXygnLi9zaGFkZXJzL2luZGV4JylcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTcGlrZXNcblxudmFyIGlkZW50aXR5ID0gWzEsMCwwLDAsXG4gICAgICAgICAgICAgICAgMCwxLDAsMCxcbiAgICAgICAgICAgICAgICAwLDAsMSwwLFxuICAgICAgICAgICAgICAgIDAsMCwwLDFdXG5cbmZ1bmN0aW9uIEF4aXNTcGlrZXMoZ2wsIGJ1ZmZlciwgdmFvLCBzaGFkZXIpIHtcbiAgdGhpcy5nbCAgICAgICAgID0gZ2xcbiAgdGhpcy5idWZmZXIgICAgID0gYnVmZmVyXG4gIHRoaXMudmFvICAgICAgICA9IHZhb1xuICB0aGlzLnNoYWRlciAgICAgPSBzaGFkZXJcbiAgdGhpcy5waXhlbFJhdGlvID0gMVxuICB0aGlzLmJvdW5kcyAgICAgPSBbWy0xMDAwLC0xMDAwLC0xMDAwXSwgWzEwMDAsMTAwMCwxMDAwXV1cbiAgdGhpcy5wb3NpdGlvbiAgID0gWzAsMCwwXVxuICB0aGlzLmxpbmVXaWR0aCAgPSBbMiwyLDJdXG4gIHRoaXMuY29sb3JzICAgICA9IFtbMCwwLDAsMV0sIFswLDAsMCwxXSwgWzAsMCwwLDFdXVxuICB0aGlzLmVuYWJsZWQgICAgPSBbdHJ1ZSx0cnVlLHRydWVdXG4gIHRoaXMuZHJhd1NpZGVzICA9IFt0cnVlLHRydWUsdHJ1ZV1cbiAgdGhpcy5heGVzICAgICAgID0gbnVsbFxufVxuXG52YXIgcHJvdG8gPSBBeGlzU3Bpa2VzLnByb3RvdHlwZVxuXG52YXIgT1VURVJfRkFDRSA9IFswLDAsMF1cbnZhciBJTk5FUl9GQUNFID0gWzAsMCwwXVxuXG52YXIgU0hBUEUgPSBbMCwwXVxuXG5wcm90by5pc1RyYW5zcGFyZW50ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBmYWxzZVxufVxuXG5wcm90by5kcmF3VHJhbnNwYXJlbnQgPSBmdW5jdGlvbihjYW1lcmEpIHt9XG5cbnByb3RvLmRyYXcgPSBmdW5jdGlvbihjYW1lcmEpIHtcbiAgdmFyIGdsID0gdGhpcy5nbFxuICB2YXIgdmFvID0gdGhpcy52YW9cbiAgdmFyIHNoYWRlciA9IHRoaXMuc2hhZGVyXG5cbiAgdmFvLmJpbmQoKVxuICBzaGFkZXIuYmluZCgpXG5cbiAgdmFyIG1vZGVsICAgICAgPSBjYW1lcmEubW9kZWwgfHwgaWRlbnRpdHlcbiAgdmFyIHZpZXcgICAgICAgPSBjYW1lcmEudmlldyB8fCBpZGVudGl0eVxuICB2YXIgcHJvamVjdGlvbiA9IGNhbWVyYS5wcm9qZWN0aW9uIHx8IGlkZW50aXR5XG5cbiAgdmFyIGF4aXNcbiAgaWYodGhpcy5heGVzKSB7XG4gICAgYXhpcyA9IHRoaXMuYXhlcy5sYXN0Q3ViZVByb3BzLmF4aXNcbiAgfVxuXG4gIHZhciBvdXRlckZhY2UgPSBPVVRFUl9GQUNFXG4gIHZhciBpbm5lckZhY2UgPSBJTk5FUl9GQUNFXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIGlmKGF4aXMgJiYgYXhpc1tpXSA8IDApIHtcbiAgICAgIG91dGVyRmFjZVtpXSA9IHRoaXMuYm91bmRzWzBdW2ldXG4gICAgICBpbm5lckZhY2VbaV0gPSB0aGlzLmJvdW5kc1sxXVtpXVxuICAgIH0gZWxzZSB7XG4gICAgICBvdXRlckZhY2VbaV0gPSB0aGlzLmJvdW5kc1sxXVtpXVxuICAgICAgaW5uZXJGYWNlW2ldID0gdGhpcy5ib3VuZHNbMF1baV1cbiAgICB9XG4gIH1cblxuICBTSEFQRVswXSA9IGdsLmRyYXdpbmdCdWZmZXJXaWR0aFxuICBTSEFQRVsxXSA9IGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRcblxuICBzaGFkZXIudW5pZm9ybXMubW9kZWwgICAgICAgPSBtb2RlbFxuICBzaGFkZXIudW5pZm9ybXMudmlldyAgICAgICAgPSB2aWV3XG4gIHNoYWRlci51bmlmb3Jtcy5wcm9qZWN0aW9uICA9IHByb2plY3Rpb25cbiAgc2hhZGVyLnVuaWZvcm1zLmNvb3JkaW5hdGVzID0gW3RoaXMucG9zaXRpb24sIG91dGVyRmFjZSwgaW5uZXJGYWNlXVxuICBzaGFkZXIudW5pZm9ybXMuY29sb3JzICAgICAgPSB0aGlzLmNvbG9yc1xuICBzaGFkZXIudW5pZm9ybXMuc2NyZWVuU2hhcGUgPSBTSEFQRVxuXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHNoYWRlci51bmlmb3Jtcy5saW5lV2lkdGggPSB0aGlzLmxpbmVXaWR0aFtpXSAqIHRoaXMucGl4ZWxSYXRpb1xuICAgIGlmKHRoaXMuZW5hYmxlZFtpXSkge1xuICAgICAgdmFvLmRyYXcoZ2wuVFJJQU5HTEVTLCA2LCA2KmkpXG4gICAgICBpZih0aGlzLmRyYXdTaWRlc1tpXSkge1xuICAgICAgICB2YW8uZHJhdyhnbC5UUklBTkdMRVMsIDEyLCAxOCsxMippKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZhby51bmJpbmQoKVxufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihvcHRpb25zKSB7XG4gIGlmKCFvcHRpb25zKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgaWYoXCJib3VuZHNcIiBpbiBvcHRpb25zKSB7XG4gICAgdGhpcy5ib3VuZHMgPSBvcHRpb25zLmJvdW5kc1xuICB9XG4gIGlmKFwicG9zaXRpb25cIiBpbiBvcHRpb25zKSB7XG4gICAgdGhpcy5wb3NpdGlvbiA9IG9wdGlvbnMucG9zaXRpb25cbiAgfVxuICBpZihcImxpbmVXaWR0aFwiIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLmxpbmVXaWR0aCA9IG9wdGlvbnMubGluZVdpZHRoXG4gIH1cbiAgaWYoXCJjb2xvcnNcIiBpbiBvcHRpb25zKSB7XG4gICAgdGhpcy5jb2xvcnMgPSBvcHRpb25zLmNvbG9yc1xuICB9XG4gIGlmKFwiZW5hYmxlZFwiIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLmVuYWJsZWQgPSBvcHRpb25zLmVuYWJsZWRcbiAgfVxuICBpZihcImRyYXdTaWRlc1wiIGluIG9wdGlvbnMpIHtcbiAgICB0aGlzLmRyYXdTaWRlcyA9IG9wdGlvbnMuZHJhd1NpZGVzXG4gIH1cbn1cblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnZhby5kaXNwb3NlKClcbiAgdGhpcy5idWZmZXIuZGlzcG9zZSgpXG4gIHRoaXMuc2hhZGVyLmRpc3Bvc2UoKVxufVxuXG5cblxuZnVuY3Rpb24gY3JlYXRlU3Bpa2VzKGdsLCBvcHRpb25zKSB7XG4gIC8vQ3JlYXRlIGJ1ZmZlcnNcbiAgdmFyIGRhdGEgPSBbIF1cblxuICBmdW5jdGlvbiBsaW5lKHgseSx6LGksbCxoKSB7XG4gICAgdmFyIHJvdyA9IFt4LHkseiwgIDAsMCwwLCAgMV1cbiAgICByb3dbaSszXSA9IDFcbiAgICByb3dbaV0gPSBsXG4gICAgZGF0YS5wdXNoLmFwcGx5KGRhdGEsIHJvdylcbiAgICByb3dbNl0gPSAtMVxuICAgIGRhdGEucHVzaC5hcHBseShkYXRhLCByb3cpXG4gICAgcm93W2ldID0gaFxuICAgIGRhdGEucHVzaC5hcHBseShkYXRhLCByb3cpXG4gICAgZGF0YS5wdXNoLmFwcGx5KGRhdGEsIHJvdylcbiAgICByb3dbNl0gPSAxXG4gICAgZGF0YS5wdXNoLmFwcGx5KGRhdGEsIHJvdylcbiAgICByb3dbaV0gPSBsXG4gICAgZGF0YS5wdXNoLmFwcGx5KGRhdGEsIHJvdylcbiAgfVxuXG4gIGxpbmUoMCwwLDAsIDAsIDAsIDEpXG4gIGxpbmUoMCwwLDAsIDEsIDAsIDEpXG4gIGxpbmUoMCwwLDAsIDIsIDAsIDEpXG5cbiAgbGluZSgxLDAsMCwgIDEsICAtMSwxKVxuICBsaW5lKDEsMCwwLCAgMiwgIC0xLDEpXG5cbiAgbGluZSgwLDEsMCwgIDAsICAtMSwxKVxuICBsaW5lKDAsMSwwLCAgMiwgIC0xLDEpXG5cbiAgbGluZSgwLDAsMSwgIDAsICAtMSwxKVxuICBsaW5lKDAsMCwxLCAgMSwgIC0xLDEpXG5cbiAgdmFyIGJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbCwgZGF0YSlcbiAgdmFyIHZhbyA9IGNyZWF0ZVZBTyhnbCwgW3tcbiAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICBidWZmZXI6IGJ1ZmZlcixcbiAgICBzaXplOiAzLFxuICAgIG9mZnNldDogMCxcbiAgICBzdHJpZGU6IDI4XG4gIH0sIHtcbiAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICBidWZmZXI6IGJ1ZmZlcixcbiAgICBzaXplOiAzLFxuICAgIG9mZnNldDogMTIsXG4gICAgc3RyaWRlOiAyOFxuICB9LCB7XG4gICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgYnVmZmVyOiBidWZmZXIsXG4gICAgc2l6ZTogMSxcbiAgICBvZmZzZXQ6IDI0LFxuICAgIHN0cmlkZTogMjhcbiAgfV0pXG5cbiAgLy9DcmVhdGUgc2hhZGVyXG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiA9IDFcbiAgc2hhZGVyLmF0dHJpYnV0ZXMud2VpZ2h0LmxvY2F0aW9uID0gMlxuXG4gIC8vQ3JlYXRlIHNwaWtlIG9iamVjdFxuICB2YXIgc3Bpa2VzID0gbmV3IEF4aXNTcGlrZXMoZ2wsIGJ1ZmZlciwgdmFvLCBzaGFkZXIpXG5cbiAgLy9TZXQgcGFyYW1ldGVyc1xuICBzcGlrZXMudXBkYXRlKG9wdGlvbnMpXG5cbiAgLy9SZXR1cm4gcmVzdWx0aW5nIG9iamVjdFxuICByZXR1cm4gc3Bpa2VzXG59XG5cbn0se1wiLi9zaGFkZXJzL2luZGV4XCI6MzA5LFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtdmFvXCI6MzI3fV0sMzExOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciBnbHNsaWZ5ICAgICAgID0gX2RlcmVxXygnZ2xzbGlmeScpXG5cbnZhciB0cmlWZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuXFxucHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudmVjMyBnZXRPcnRob2dvbmFsVmVjdG9yKHZlYzMgdikge1xcbiAgLy8gUmV0dXJuIHVwLXZlY3RvciBmb3Igb25seS16IHZlY3Rvci5cXG4gIC8vIFJldHVybiBheCArIGJ5ICsgY3ogPSAwLCBhIHBvaW50IHRoYXQgbGllcyBvbiB0aGUgcGxhbmUgdGhhdCBoYXMgdiBhcyBhIG5vcm1hbCBhbmQgdGhhdCBpc24ndCAoMCwwLDApLlxcbiAgLy8gRnJvbSB0aGUgYWJvdmUgaWYtc3RhdGVtZW50IHdlIGhhdmUgfHxhfHwgPiAwICBVICB8fGJ8fCA+IDAuXFxuICAvLyBBc3NpZ24geiA9IDAsIHggPSAtYiwgeSA9IGE6XFxuICAvLyBhKi1iICsgYiphICsgYyowID0gLWJhICsgYmEgKyAwID0gMFxcbiAgaWYgKHYueCp2LnggPiB2Lnoqdi56IHx8IHYueSp2LnkgPiB2Lnoqdi56KSB7XFxuICAgIHJldHVybiBub3JtYWxpemUodmVjMygtdi55LCB2LngsIDAuMCkpO1xcbiAgfSBlbHNlIHtcXG4gICAgcmV0dXJuIG5vcm1hbGl6ZSh2ZWMzKDAuMCwgdi56LCAtdi55KSk7XFxuICB9XFxufVxcblxcbi8vIENhbGN1bGF0ZSB0aGUgdHViZSB2ZXJ0ZXggYW5kIG5vcm1hbCBhdCB0aGUgZ2l2ZW4gaW5kZXguXFxuLy9cXG4vLyBUaGUgcmV0dXJuZWQgdmVydGV4IGlzIGZvciBhIHR1YmUgcmluZyB3aXRoIGl0cyBjZW50ZXIgYXQgb3JpZ2luLCByYWRpdXMgb2YgbGVuZ3RoKGQpLCBwb2ludGluZyBpbiB0aGUgZGlyZWN0aW9uIG9mIGQuXFxuLy9cXG4vLyBFYWNoIHR1YmUgc2VnbWVudCBpcyBtYWRlIHVwIG9mIGEgcmluZyBvZiB2ZXJ0aWNlcy5cXG4vLyBUaGVzZSB2ZXJ0aWNlcyBhcmUgdXNlZCB0byBtYWtlIHVwIHRoZSB0cmlhbmdsZXMgb2YgdGhlIHR1YmUgYnkgY29ubmVjdGluZyB0aGVtIHRvZ2V0aGVyIGluIHRoZSB2ZXJ0ZXggYXJyYXkuXFxuLy8gVGhlIGluZGV4ZXMgb2YgdHViZSBzZWdtZW50cyBydW4gZnJvbSAwIHRvIDguXFxuLy9cXG52ZWMzIGdldFR1YmVQb3NpdGlvbih2ZWMzIGQsIGZsb2F0IGluZGV4LCBvdXQgdmVjMyBub3JtYWwpIHtcXG4gIGZsb2F0IHNlZ21lbnRDb3VudCA9IDguMDtcXG5cXG4gIGZsb2F0IGFuZ2xlID0gMi4wICogMy4xNDE1OSAqIChpbmRleCAvIHNlZ21lbnRDb3VudCk7XFxuXFxuICB2ZWMzIHUgPSBnZXRPcnRob2dvbmFsVmVjdG9yKGQpO1xcbiAgdmVjMyB2ID0gbm9ybWFsaXplKGNyb3NzKHUsIGQpKTtcXG5cXG4gIHZlYzMgeCA9IHUgKiBjb3MoYW5nbGUpICogbGVuZ3RoKGQpO1xcbiAgdmVjMyB5ID0gdiAqIHNpbihhbmdsZSkgKiBsZW5ndGgoZCk7XFxuICB2ZWMzIHYzID0geCArIHk7XFxuXFxuICBub3JtYWwgPSBub3JtYWxpemUodjMpO1xcblxcbiAgcmV0dXJuIHYzO1xcbn1cXG5cXG5hdHRyaWJ1dGUgdmVjNCB2ZWN0b3I7XFxuYXR0cmlidXRlIHZlYzQgY29sb3IsIHBvc2l0aW9uO1xcbmF0dHJpYnV0ZSB2ZWMyIHV2O1xcbnVuaWZvcm0gZmxvYXQgdmVjdG9yU2NhbGU7XFxudW5pZm9ybSBmbG9hdCB0dWJlU2NhbGU7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsXFxuICAgICAgICAgICAsIHZpZXdcXG4gICAgICAgICAgICwgcHJvamVjdGlvblxcbiAgICAgICAgICAgLCBpbnZlcnNlTW9kZWw7XFxudW5pZm9ybSB2ZWMzIGV5ZVBvc2l0aW9uXFxuICAgICAgICAgICAsIGxpZ2h0UG9zaXRpb247XFxuXFxudmFyeWluZyB2ZWMzIGZfbm9ybWFsXFxuICAgICAgICAgICAsIGZfbGlnaHREaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9leWVEaXJlY3Rpb25cXG4gICAgICAgICAgICwgZl9kYXRhXFxuICAgICAgICAgICAsIGZfcG9zaXRpb247XFxudmFyeWluZyB2ZWM0IGZfY29sb3I7XFxudmFyeWluZyB2ZWMyIGZfdXY7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgLy8gU2NhbGUgdGhlIHZlY3RvciBtYWduaXR1ZGUgdG8gc3RheSBjb25zdGFudCB3aXRoXFxuICAvLyBtb2RlbCAmIHZpZXcgY2hhbmdlcy5cXG4gIHZlYzMgbm9ybWFsO1xcbiAgdmVjMyBYWVogPSBnZXRUdWJlUG9zaXRpb24obWF0Myhtb2RlbCkgKiAodHViZVNjYWxlICogdmVjdG9yLncgKiBub3JtYWxpemUodmVjdG9yLnh5eikpLCBwb3NpdGlvbi53LCBub3JtYWwpO1xcbiAgdmVjNCB0dWJlUG9zaXRpb24gPSBtb2RlbCAqIHZlYzQocG9zaXRpb24ueHl6LCAxLjApICsgdmVjNChYWVosIDAuMCk7XFxuXFxuICAvL0xpZ2h0aW5nIGdlb21ldHJ5IHBhcmFtZXRlcnNcXG4gIHZlYzQgY2FtZXJhQ29vcmRpbmF0ZSA9IHZpZXcgKiB0dWJlUG9zaXRpb247XFxuICBjYW1lcmFDb29yZGluYXRlLnh5eiAvPSBjYW1lcmFDb29yZGluYXRlLnc7XFxuICBmX2xpZ2h0RGlyZWN0aW9uID0gbGlnaHRQb3NpdGlvbiAtIGNhbWVyYUNvb3JkaW5hdGUueHl6O1xcbiAgZl9leWVEaXJlY3Rpb24gICA9IGV5ZVBvc2l0aW9uIC0gY2FtZXJhQ29vcmRpbmF0ZS54eXo7XFxuICBmX25vcm1hbCA9IG5vcm1hbGl6ZSgodmVjNChub3JtYWwsMC4wKSAqIGludmVyc2VNb2RlbCkueHl6KTtcXG5cXG4gIC8vIHZlYzQgbV9wb3NpdGlvbiAgPSBtb2RlbCAqIHZlYzQodHViZVBvc2l0aW9uLCAxLjApO1xcbiAgdmVjNCB0X3Bvc2l0aW9uICA9IHZpZXcgKiB0dWJlUG9zaXRpb247XFxuICBnbF9Qb3NpdGlvbiAgICAgID0gcHJvamVjdGlvbiAqIHRfcG9zaXRpb247XFxuXFxuICBmX2NvbG9yICAgICAgICAgID0gY29sb3I7XFxuICBmX2RhdGEgICAgICAgICAgID0gdHViZVBvc2l0aW9uLnh5ejtcXG4gIGZfcG9zaXRpb24gICAgICAgPSBwb3NpdGlvbi54eXo7XFxuICBmX3V2ICAgICAgICAgICAgID0gdXY7XFxufVxcblwiXSlcbnZhciB0cmlGcmFnU3JjID0gZ2xzbGlmeShbXCIjZXh0ZW5zaW9uIEdMX09FU19zdGFuZGFyZF9kZXJpdmF0aXZlcyA6IGVuYWJsZVxcblxcbnByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmZsb2F0IGJlY2ttYW5uRGlzdHJpYnV0aW9uKGZsb2F0IHgsIGZsb2F0IHJvdWdobmVzcykge1xcbiAgZmxvYXQgTmRvdEggPSBtYXgoeCwgMC4wMDAxKTtcXG4gIGZsb2F0IGNvczJBbHBoYSA9IE5kb3RIICogTmRvdEg7XFxuICBmbG9hdCB0YW4yQWxwaGEgPSAoY29zMkFscGhhIC0gMS4wKSAvIGNvczJBbHBoYTtcXG4gIGZsb2F0IHJvdWdobmVzczIgPSByb3VnaG5lc3MgKiByb3VnaG5lc3M7XFxuICBmbG9hdCBkZW5vbSA9IDMuMTQxNTkyNjUzNTg5NzkzICogcm91Z2huZXNzMiAqIGNvczJBbHBoYSAqIGNvczJBbHBoYTtcXG4gIHJldHVybiBleHAodGFuMkFscGhhIC8gcm91Z2huZXNzMikgLyBkZW5vbTtcXG59XFxuXFxuZmxvYXQgY29va1RvcnJhbmNlU3BlY3VsYXIoXFxuICB2ZWMzIGxpZ2h0RGlyZWN0aW9uLFxcbiAgdmVjMyB2aWV3RGlyZWN0aW9uLFxcbiAgdmVjMyBzdXJmYWNlTm9ybWFsLFxcbiAgZmxvYXQgcm91Z2huZXNzLFxcbiAgZmxvYXQgZnJlc25lbCkge1xcblxcbiAgZmxvYXQgVmRvdE4gPSBtYXgoZG90KHZpZXdEaXJlY3Rpb24sIHN1cmZhY2VOb3JtYWwpLCAwLjApO1xcbiAgZmxvYXQgTGRvdE4gPSBtYXgoZG90KGxpZ2h0RGlyZWN0aW9uLCBzdXJmYWNlTm9ybWFsKSwgMC4wKTtcXG5cXG4gIC8vSGFsZiBhbmdsZSB2ZWN0b3JcXG4gIHZlYzMgSCA9IG5vcm1hbGl6ZShsaWdodERpcmVjdGlvbiArIHZpZXdEaXJlY3Rpb24pO1xcblxcbiAgLy9HZW9tZXRyaWMgdGVybVxcbiAgZmxvYXQgTmRvdEggPSBtYXgoZG90KHN1cmZhY2VOb3JtYWwsIEgpLCAwLjApO1xcbiAgZmxvYXQgVmRvdEggPSBtYXgoZG90KHZpZXdEaXJlY3Rpb24sIEgpLCAwLjAwMDAwMSk7XFxuICBmbG9hdCBMZG90SCA9IG1heChkb3QobGlnaHREaXJlY3Rpb24sIEgpLCAwLjAwMDAwMSk7XFxuICBmbG9hdCBHMSA9ICgyLjAgKiBOZG90SCAqIFZkb3ROKSAvIFZkb3RIO1xcbiAgZmxvYXQgRzIgPSAoMi4wICogTmRvdEggKiBMZG90TikgLyBMZG90SDtcXG4gIGZsb2F0IEcgPSBtaW4oMS4wLCBtaW4oRzEsIEcyKSk7XFxuICBcXG4gIC8vRGlzdHJpYnV0aW9uIHRlcm1cXG4gIGZsb2F0IEQgPSBiZWNrbWFubkRpc3RyaWJ1dGlvbihOZG90SCwgcm91Z2huZXNzKTtcXG5cXG4gIC8vRnJlc25lbCB0ZXJtXFxuICBmbG9hdCBGID0gcG93KDEuMCAtIFZkb3ROLCBmcmVzbmVsKTtcXG5cXG4gIC8vTXVsdGlwbHkgdGVybXMgYW5kIGRvbmVcXG4gIHJldHVybiAgRyAqIEYgKiBEIC8gbWF4KDMuMTQxNTkyNjUgKiBWZG90TiwgMC4wMDAwMDEpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG51bmlmb3JtIHZlYzMgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIGZsb2F0IHJvdWdobmVzc1xcbiAgICAgICAgICAgICwgZnJlc25lbFxcbiAgICAgICAgICAgICwga2FtYmllbnRcXG4gICAgICAgICAgICAsIGtkaWZmdXNlXFxuICAgICAgICAgICAgLCBrc3BlY3VsYXJcXG4gICAgICAgICAgICAsIG9wYWNpdHk7XFxudW5pZm9ybSBzYW1wbGVyMkQgdGV4dHVyZTtcXG5cXG52YXJ5aW5nIHZlYzMgZl9ub3JtYWxcXG4gICAgICAgICAgICwgZl9saWdodERpcmVjdGlvblxcbiAgICAgICAgICAgLCBmX2V5ZURpcmVjdGlvblxcbiAgICAgICAgICAgLCBmX2RhdGFcXG4gICAgICAgICAgICwgZl9wb3NpdGlvbjtcXG52YXJ5aW5nIHZlYzQgZl9jb2xvcjtcXG52YXJ5aW5nIHZlYzIgZl91djtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBmX3Bvc2l0aW9uKSkgZGlzY2FyZDtcXG4gIHZlYzMgTiA9IG5vcm1hbGl6ZShmX25vcm1hbCk7XFxuICB2ZWMzIEwgPSBub3JtYWxpemUoZl9saWdodERpcmVjdGlvbik7XFxuICB2ZWMzIFYgPSBub3JtYWxpemUoZl9leWVEaXJlY3Rpb24pO1xcblxcbiAgaWYoZ2xfRnJvbnRGYWNpbmcpIHtcXG4gICAgTiA9IC1OO1xcbiAgfVxcblxcbiAgZmxvYXQgc3BlY3VsYXIgPSBtaW4oMS4wLCBtYXgoMC4wLCBjb29rVG9ycmFuY2VTcGVjdWxhcihMLCBWLCBOLCByb3VnaG5lc3MsIGZyZXNuZWwpKSk7XFxuICBmbG9hdCBkaWZmdXNlICA9IG1pbihrYW1iaWVudCArIGtkaWZmdXNlICogbWF4KGRvdChOLCBMKSwgMC4wKSwgMS4wKTtcXG5cXG4gIHZlYzQgc3VyZmFjZUNvbG9yID0gZl9jb2xvciAqIHRleHR1cmUyRCh0ZXh0dXJlLCBmX3V2KTtcXG4gIHZlYzQgbGl0Q29sb3IgPSBzdXJmYWNlQ29sb3IuYSAqIHZlYzQoZGlmZnVzZSAqIHN1cmZhY2VDb2xvci5yZ2IgKyBrc3BlY3VsYXIgKiB2ZWMzKDEsMSwxKSAqIHNwZWN1bGFyLCAgMS4wKTtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IGxpdENvbG9yICogb3BhY2l0eTtcXG59XFxuXCJdKVxudmFyIHBpY2tWZXJ0U3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuXFxucHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudmVjMyBnZXRPcnRob2dvbmFsVmVjdG9yKHZlYzMgdikge1xcbiAgLy8gUmV0dXJuIHVwLXZlY3RvciBmb3Igb25seS16IHZlY3Rvci5cXG4gIC8vIFJldHVybiBheCArIGJ5ICsgY3ogPSAwLCBhIHBvaW50IHRoYXQgbGllcyBvbiB0aGUgcGxhbmUgdGhhdCBoYXMgdiBhcyBhIG5vcm1hbCBhbmQgdGhhdCBpc24ndCAoMCwwLDApLlxcbiAgLy8gRnJvbSB0aGUgYWJvdmUgaWYtc3RhdGVtZW50IHdlIGhhdmUgfHxhfHwgPiAwICBVICB8fGJ8fCA+IDAuXFxuICAvLyBBc3NpZ24geiA9IDAsIHggPSAtYiwgeSA9IGE6XFxuICAvLyBhKi1iICsgYiphICsgYyowID0gLWJhICsgYmEgKyAwID0gMFxcbiAgaWYgKHYueCp2LnggPiB2Lnoqdi56IHx8IHYueSp2LnkgPiB2Lnoqdi56KSB7XFxuICAgIHJldHVybiBub3JtYWxpemUodmVjMygtdi55LCB2LngsIDAuMCkpO1xcbiAgfSBlbHNlIHtcXG4gICAgcmV0dXJuIG5vcm1hbGl6ZSh2ZWMzKDAuMCwgdi56LCAtdi55KSk7XFxuICB9XFxufVxcblxcbi8vIENhbGN1bGF0ZSB0aGUgdHViZSB2ZXJ0ZXggYW5kIG5vcm1hbCBhdCB0aGUgZ2l2ZW4gaW5kZXguXFxuLy9cXG4vLyBUaGUgcmV0dXJuZWQgdmVydGV4IGlzIGZvciBhIHR1YmUgcmluZyB3aXRoIGl0cyBjZW50ZXIgYXQgb3JpZ2luLCByYWRpdXMgb2YgbGVuZ3RoKGQpLCBwb2ludGluZyBpbiB0aGUgZGlyZWN0aW9uIG9mIGQuXFxuLy9cXG4vLyBFYWNoIHR1YmUgc2VnbWVudCBpcyBtYWRlIHVwIG9mIGEgcmluZyBvZiB2ZXJ0aWNlcy5cXG4vLyBUaGVzZSB2ZXJ0aWNlcyBhcmUgdXNlZCB0byBtYWtlIHVwIHRoZSB0cmlhbmdsZXMgb2YgdGhlIHR1YmUgYnkgY29ubmVjdGluZyB0aGVtIHRvZ2V0aGVyIGluIHRoZSB2ZXJ0ZXggYXJyYXkuXFxuLy8gVGhlIGluZGV4ZXMgb2YgdHViZSBzZWdtZW50cyBydW4gZnJvbSAwIHRvIDguXFxuLy9cXG52ZWMzIGdldFR1YmVQb3NpdGlvbih2ZWMzIGQsIGZsb2F0IGluZGV4LCBvdXQgdmVjMyBub3JtYWwpIHtcXG4gIGZsb2F0IHNlZ21lbnRDb3VudCA9IDguMDtcXG5cXG4gIGZsb2F0IGFuZ2xlID0gMi4wICogMy4xNDE1OSAqIChpbmRleCAvIHNlZ21lbnRDb3VudCk7XFxuXFxuICB2ZWMzIHUgPSBnZXRPcnRob2dvbmFsVmVjdG9yKGQpO1xcbiAgdmVjMyB2ID0gbm9ybWFsaXplKGNyb3NzKHUsIGQpKTtcXG5cXG4gIHZlYzMgeCA9IHUgKiBjb3MoYW5nbGUpICogbGVuZ3RoKGQpO1xcbiAgdmVjMyB5ID0gdiAqIHNpbihhbmdsZSkgKiBsZW5ndGgoZCk7XFxuICB2ZWMzIHYzID0geCArIHk7XFxuXFxuICBub3JtYWwgPSBub3JtYWxpemUodjMpO1xcblxcbiAgcmV0dXJuIHYzO1xcbn1cXG5cXG5hdHRyaWJ1dGUgdmVjNCB2ZWN0b3I7XFxuYXR0cmlidXRlIHZlYzQgcG9zaXRpb247XFxuYXR0cmlidXRlIHZlYzQgaWQ7XFxuXFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uO1xcbnVuaWZvcm0gZmxvYXQgdHViZVNjYWxlO1xcblxcbnZhcnlpbmcgdmVjMyBmX3Bvc2l0aW9uO1xcbnZhcnlpbmcgdmVjNCBmX2lkO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzMgbm9ybWFsO1xcbiAgdmVjMyBYWVogPSBnZXRUdWJlUG9zaXRpb24obWF0Myhtb2RlbCkgKiAodHViZVNjYWxlICogdmVjdG9yLncgKiBub3JtYWxpemUodmVjdG9yLnh5eikpLCBwb3NpdGlvbi53LCBub3JtYWwpO1xcbiAgdmVjNCB0dWJlUG9zaXRpb24gPSBtb2RlbCAqIHZlYzQocG9zaXRpb24ueHl6LCAxLjApICsgdmVjNChYWVosIDAuMCk7XFxuXFxuICBnbF9Qb3NpdGlvbiA9IHByb2plY3Rpb24gKiB2aWV3ICogdHViZVBvc2l0aW9uO1xcbiAgZl9pZCAgICAgICAgPSBpZDtcXG4gIGZfcG9zaXRpb24gID0gcG9zaXRpb24ueHl6O1xcbn1cXG5cIl0pXG52YXIgcGlja0ZyYWdTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmJvb2wgb3V0T2ZSYW5nZShmbG9hdCBhLCBmbG9hdCBiLCBmbG9hdCBwKSB7XFxuICByZXR1cm4gKChwID4gbWF4KGEsIGIpKSB8fCBcXG4gICAgICAgICAgKHAgPCBtaW4oYSwgYikpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzIgYSwgdmVjMiBiLCB2ZWMyIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzMgYSwgdmVjMyBiLCB2ZWMzIHApIHtcXG4gIHJldHVybiAob3V0T2ZSYW5nZShhLngsIGIueCwgcC54KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueSwgYi55LCBwLnkpIHx8XFxuICAgICAgICAgIG91dE9mUmFuZ2UoYS56LCBiLnosIHAueikpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UodmVjNCBhLCB2ZWM0IGIsIHZlYzQgcCkge1xcbiAgcmV0dXJuIG91dE9mUmFuZ2UoYS54eXosIGIueHl6LCBwLnh5eik7XFxufVxcblxcbnVuaWZvcm0gdmVjMyAgY2xpcEJvdW5kc1syXTtcXG51bmlmb3JtIGZsb2F0IHBpY2tJZDtcXG5cXG52YXJ5aW5nIHZlYzMgZl9wb3NpdGlvbjtcXG52YXJ5aW5nIHZlYzQgZl9pZDtcXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAob3V0T2ZSYW5nZShjbGlwQm91bmRzWzBdLCBjbGlwQm91bmRzWzFdLCBmX3Bvc2l0aW9uKSkgZGlzY2FyZDtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IHZlYzQocGlja0lkLCBmX2lkLnh5eik7XFxufVwiXSlcblxuZXhwb3J0cy5tZXNoU2hhZGVyID0ge1xuICB2ZXJ0ZXg6ICAgdHJpVmVydFNyYyxcbiAgZnJhZ21lbnQ6IHRyaUZyYWdTcmMsXG4gIGF0dHJpYnV0ZXM6IFtcbiAgICB7bmFtZTogJ3Bvc2l0aW9uJywgdHlwZTogJ3ZlYzQnfSxcbiAgICB7bmFtZTogJ25vcm1hbCcsIHR5cGU6ICd2ZWMzJ30sXG4gICAge25hbWU6ICdjb2xvcicsIHR5cGU6ICd2ZWM0J30sXG4gICAge25hbWU6ICd1dicsIHR5cGU6ICd2ZWMyJ30sXG4gICAge25hbWU6ICd2ZWN0b3InLCB0eXBlOiAndmVjNCd9XG4gIF1cbn1cbmV4cG9ydHMucGlja1NoYWRlciA9IHtcbiAgdmVydGV4OiAgIHBpY2tWZXJ0U3JjLFxuICBmcmFnbWVudDogcGlja0ZyYWdTcmMsXG4gIGF0dHJpYnV0ZXM6IFtcbiAgICB7bmFtZTogJ3Bvc2l0aW9uJywgdHlwZTogJ3ZlYzQnfSxcbiAgICB7bmFtZTogJ2lkJywgdHlwZTogJ3ZlYzQnfSxcbiAgICB7bmFtZTogJ3ZlY3RvcicsIHR5cGU6ICd2ZWM0J31cbiAgXVxufVxuXG59LHtcImdsc2xpZnlcIjo0MDl9XSwzMTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBERUZBVUxUX1ZFUlRFWF9OT1JNQUxTX0VQU0lMT04gPSAxZS02OyAvLyBtYXkgYmUgdG9vIGxhcmdlIGlmIHRyaWFuZ2xlcyBhcmUgdmVyeSBzbWFsbFxudmFyIERFRkFVTFRfRkFDRV9OT1JNQUxTX0VQU0lMT04gPSAxZS02O1xuXG52YXIgY3JlYXRlU2hhZGVyICA9IF9kZXJlcV8oJ2dsLXNoYWRlcicpXG52YXIgY3JlYXRlQnVmZmVyICA9IF9kZXJlcV8oJ2dsLWJ1ZmZlcicpXG52YXIgY3JlYXRlVkFPICAgICA9IF9kZXJlcV8oJ2dsLXZhbycpXG52YXIgY3JlYXRlVGV4dHVyZSA9IF9kZXJlcV8oJ2dsLXRleHR1cmUyZCcpXG52YXIgbm9ybWFscyAgICAgICA9IF9kZXJlcV8oJ25vcm1hbHMnKVxudmFyIG11bHRpcGx5ICAgICAgPSBfZGVyZXFfKCdnbC1tYXQ0L211bHRpcGx5JylcbnZhciBpbnZlcnQgICAgICAgID0gX2RlcmVxXygnZ2wtbWF0NC9pbnZlcnQnKVxudmFyIG5kYXJyYXkgICAgICAgPSBfZGVyZXFfKCduZGFycmF5JylcbnZhciBjb2xvcm1hcCAgICAgID0gX2RlcmVxXygnY29sb3JtYXAnKVxudmFyIGdldENvbnRvdXIgICAgPSBfZGVyZXFfKCdzaW1wbGljaWFsLWNvbXBsZXgtY29udG91cicpXG52YXIgcG9vbCAgICAgICAgICA9IF9kZXJlcV8oJ3R5cGVkYXJyYXktcG9vbCcpXG52YXIgc2hhZGVycyAgICAgICA9IF9kZXJlcV8oJy4vc2hhZGVycycpXG5cbnZhciBtZXNoU2hhZGVyICAgID0gc2hhZGVycy5tZXNoU2hhZGVyXG52YXIgcGlja1NoYWRlciAgICA9IHNoYWRlcnMucGlja1NoYWRlclxuXG52YXIgSURFTlRJVFkgPSBbXG4gIDEsMCwwLDAsXG4gIDAsMSwwLDAsXG4gIDAsMCwxLDAsXG4gIDAsMCwwLDFdXG5cbmZ1bmN0aW9uIFNpbXBsaWNpYWxNZXNoKGdsXG4gICwgdGV4dHVyZVxuICAsIHRyaVNoYWRlclxuICAsIHBpY2tTaGFkZXJcbiAgLCB0cmlhbmdsZVBvc2l0aW9uc1xuICAsIHRyaWFuZ2xlVmVjdG9yc1xuICAsIHRyaWFuZ2xlSWRzXG4gICwgdHJpYW5nbGVDb2xvcnNcbiAgLCB0cmlhbmdsZVVWc1xuICAsIHRyaWFuZ2xlTm9ybWFsc1xuICAsIHRyaWFuZ2xlVkFPXG4gICwgZWRnZVBvc2l0aW9uc1xuICAsIGVkZ2VJZHNcbiAgLCBlZGdlQ29sb3JzXG4gICwgZWRnZVVWc1xuICAsIGVkZ2VWQU9cbiAgLCBwb2ludFBvc2l0aW9uc1xuICAsIHBvaW50SWRzXG4gICwgcG9pbnRDb2xvcnNcbiAgLCBwb2ludFVWc1xuICAsIHBvaW50U2l6ZXNcbiAgLCBwb2ludFZBT1xuICAsIGNvbnRvdXJQb3NpdGlvbnNcbiAgLCBjb250b3VyVkFPKSB7XG5cbiAgdGhpcy5nbCAgICAgICAgICAgICAgICA9IGdsXG4gIHRoaXMuY2VsbHMgICAgICAgICAgICAgPSBbXVxuICB0aGlzLnBvc2l0aW9ucyAgICAgICAgID0gW11cbiAgdGhpcy5pbnRlbnNpdHkgICAgICAgICA9IFtdXG4gIHRoaXMudGV4dHVyZSAgICAgICAgICAgPSB0ZXh0dXJlXG4gIHRoaXMuZGlydHkgICAgICAgICAgICAgPSB0cnVlXG5cbiAgdGhpcy50cmlTaGFkZXIgICAgICAgICA9IHRyaVNoYWRlclxuICB0aGlzLnBpY2tTaGFkZXIgICAgICAgID0gcGlja1NoYWRlclxuXG4gIHRoaXMudHJpYW5nbGVQb3NpdGlvbnMgPSB0cmlhbmdsZVBvc2l0aW9uc1xuICB0aGlzLnRyaWFuZ2xlVmVjdG9ycyAgID0gdHJpYW5nbGVWZWN0b3JzXG4gIHRoaXMudHJpYW5nbGVDb2xvcnMgICAgPSB0cmlhbmdsZUNvbG9yc1xuICB0aGlzLnRyaWFuZ2xlTm9ybWFscyAgID0gdHJpYW5nbGVOb3JtYWxzXG4gIHRoaXMudHJpYW5nbGVVVnMgICAgICAgPSB0cmlhbmdsZVVWc1xuICB0aGlzLnRyaWFuZ2xlSWRzICAgICAgID0gdHJpYW5nbGVJZHNcbiAgdGhpcy50cmlhbmdsZVZBTyAgICAgICA9IHRyaWFuZ2xlVkFPXG4gIHRoaXMudHJpYW5nbGVDb3VudCAgICAgPSAwXG5cbiAgdGhpcy5saW5lV2lkdGggICAgICAgICA9IDFcbiAgdGhpcy5lZGdlUG9zaXRpb25zICAgICA9IGVkZ2VQb3NpdGlvbnNcbiAgdGhpcy5lZGdlQ29sb3JzICAgICAgICA9IGVkZ2VDb2xvcnNcbiAgdGhpcy5lZGdlVVZzICAgICAgICAgICA9IGVkZ2VVVnNcbiAgdGhpcy5lZGdlSWRzICAgICAgICAgICA9IGVkZ2VJZHNcbiAgdGhpcy5lZGdlVkFPICAgICAgICAgICA9IGVkZ2VWQU9cbiAgdGhpcy5lZGdlQ291bnQgICAgICAgICA9IDBcblxuICB0aGlzLnBvaW50UG9zaXRpb25zICAgID0gcG9pbnRQb3NpdGlvbnNcbiAgdGhpcy5wb2ludENvbG9ycyAgICAgICA9IHBvaW50Q29sb3JzXG4gIHRoaXMucG9pbnRVVnMgICAgICAgICAgPSBwb2ludFVWc1xuICB0aGlzLnBvaW50U2l6ZXMgICAgICAgID0gcG9pbnRTaXplc1xuICB0aGlzLnBvaW50SWRzICAgICAgICAgID0gcG9pbnRJZHNcbiAgdGhpcy5wb2ludFZBTyAgICAgICAgICA9IHBvaW50VkFPXG4gIHRoaXMucG9pbnRDb3VudCAgICAgICAgPSAwXG5cbiAgdGhpcy5jb250b3VyTGluZVdpZHRoICA9IDFcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zICA9IGNvbnRvdXJQb3NpdGlvbnNcbiAgdGhpcy5jb250b3VyVkFPICAgICAgICA9IGNvbnRvdXJWQU9cbiAgdGhpcy5jb250b3VyQ291bnQgICAgICA9IDBcbiAgdGhpcy5jb250b3VyQ29sb3IgICAgICA9IFswLDAsMF1cbiAgdGhpcy5jb250b3VyRW5hYmxlICAgICA9IGZhbHNlXG5cbiAgdGhpcy5waWNrSWQgICAgICAgICAgICA9IDFcbiAgdGhpcy5ib3VuZHMgICAgICAgICAgICA9IFtcbiAgICBbIEluZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldLFxuICAgIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV0gXVxuICB0aGlzLmNsaXBCb3VuZHMgICAgICAgID0gW1xuICAgIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV0sXG4gICAgWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XSBdXG5cbiAgdGhpcy5saWdodFBvc2l0aW9uID0gWzFlNSwgMWU1LCAwXVxuICB0aGlzLmFtYmllbnRMaWdodCAgPSAwLjhcbiAgdGhpcy5kaWZmdXNlTGlnaHQgID0gMC44XG4gIHRoaXMuc3BlY3VsYXJMaWdodCA9IDIuMFxuICB0aGlzLnJvdWdobmVzcyAgICAgPSAwLjVcbiAgdGhpcy5mcmVzbmVsICAgICAgID0gMS41XG5cbiAgdGhpcy5vcGFjaXR5ICAgICAgID0gMS4wXG5cbiAgdGhpcy50dWJlU2NhbGUgICAgID0gMS4wXG5cbiAgdGhpcy5fbW9kZWwgICAgICAgPSBJREVOVElUWVxuICB0aGlzLl92aWV3ICAgICAgICA9IElERU5USVRZXG4gIHRoaXMuX3Byb2plY3Rpb24gID0gSURFTlRJVFlcbiAgdGhpcy5fcmVzb2x1dGlvbiAgPSBbMSwxXVxuICB0aGlzLnBpeGVsUmF0aW8gICA9IDFcbn1cblxudmFyIHByb3RvID0gU2ltcGxpY2lhbE1lc2gucHJvdG90eXBlXG5cbnByb3RvLmlzT3BhcXVlID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLm9wYWNpdHkgPj0gMVxufVxuXG5wcm90by5pc1RyYW5zcGFyZW50ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLm9wYWNpdHkgPCAxXG59XG5cbnByb3RvLnBpY2tTbG90cyA9IDFcblxucHJvdG8uc2V0UGlja0Jhc2UgPSBmdW5jdGlvbihpZCkge1xuICB0aGlzLnBpY2tJZCA9IGlkXG59XG5cbmZ1bmN0aW9uIGdlbkNvbG9ybWFwKHBhcmFtKSB7XG4gIHZhciBjb2xvcnMgPSBjb2xvcm1hcCh7XG4gICAgICBjb2xvcm1hcDogcGFyYW1cbiAgICAsIG5zaGFkZXM6ICAyNTZcbiAgICAsIGZvcm1hdDogICdyZ2JhJ1xuICB9KVxuXG4gIHZhciByZXN1bHQgPSBuZXcgVWludDhBcnJheSgyNTYqNClcbiAgZm9yKHZhciBpPTA7IGk8MjU2OyArK2kpIHtcbiAgICB2YXIgYyA9IGNvbG9yc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgcmVzdWx0WzQqaStqXSA9IGNbal1cbiAgICB9XG4gICAgcmVzdWx0WzQqaSszXSA9IGNbM10qMjU1XG4gIH1cblxuICByZXR1cm4gbmRhcnJheShyZXN1bHQsIFsyNTYsMjU2LDRdLCBbNCwwLDFdKVxufVxuXG5mdW5jdGlvbiB1bnBhY2tJbnRlbnNpdHkoY2VsbHMsIG51bVZlcnRzLCBjZWxsSW50ZW5zaXR5KSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobnVtVmVydHMpXG4gIGZvcih2YXIgaT0wOyBpPG51bVZlcnRzOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSAwXG4gIH1cbiAgdmFyIG51bUNlbGxzID0gY2VsbHMubGVuZ3RoXG4gIGZvcih2YXIgaT0wOyBpPG51bUNlbGxzOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgZm9yKHZhciBqPTA7IGo8Yy5sZW5ndGg7ICsraikge1xuICAgICAgcmVzdWx0W2Nbal1dID0gY2VsbEludGVuc2l0eVtpXVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIHRha2VaQ29tcG9uZW50KGFycmF5KSB7XG4gIHZhciBuID0gYXJyYXkubGVuZ3RoXG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gYXJyYXlbaV1bMl1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbnByb3RvLmhpZ2hsaWdodCA9IGZ1bmN0aW9uKHNlbGVjdGlvbikge1xuICBpZighc2VsZWN0aW9uIHx8ICF0aGlzLmNvbnRvdXJFbmFibGUpIHtcbiAgICB0aGlzLmNvbnRvdXJDb3VudCA9IDBcbiAgICByZXR1cm5cbiAgfVxuICB2YXIgbGV2ZWwgPSBnZXRDb250b3VyKHRoaXMuY2VsbHMsIHRoaXMuaW50ZW5zaXR5LCBzZWxlY3Rpb24uaW50ZW5zaXR5KVxuICB2YXIgY2VsbHMgICAgICAgICA9IGxldmVsLmNlbGxzXG4gIHZhciB2ZXJ0ZXhJZHMgICAgID0gbGV2ZWwudmVydGV4SWRzXG4gIHZhciB2ZXJ0ZXhXZWlnaHRzID0gbGV2ZWwudmVydGV4V2VpZ2h0c1xuICB2YXIgbnVtQ2VsbHMgPSBjZWxscy5sZW5ndGhcbiAgdmFyIHJlc3VsdCA9IHBvb2wubWFsbG9jRmxvYXQzMigyICogMyAqIG51bUNlbGxzKVxuICB2YXIgcHRyID0gMFxuICBmb3IodmFyIGk9MDsgaTxudW1DZWxsczsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xuICAgICAgdmFyIHYgPSBjWzBdXG4gICAgICBpZihjLmxlbmd0aCA9PT0gMikge1xuICAgICAgICB2ID0gY1tqXVxuICAgICAgfVxuICAgICAgdmFyIGEgPSB2ZXJ0ZXhJZHNbdl1bMF1cbiAgICAgIHZhciBiID0gdmVydGV4SWRzW3ZdWzFdXG4gICAgICB2YXIgdyA9IHZlcnRleFdlaWdodHNbdl1cbiAgICAgIHZhciB3aSA9IDEuMCAtIHdcbiAgICAgIHZhciBwYSA9IHRoaXMucG9zaXRpb25zW2FdXG4gICAgICB2YXIgcGIgPSB0aGlzLnBvc2l0aW9uc1tiXVxuICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XG4gICAgICAgIHJlc3VsdFtwdHIrK10gPSB3ICogcGFba10gKyB3aSAqIHBiW2tdXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHRoaXMuY29udG91ckNvdW50ID0gKHB0ciAvIDMpfDBcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zLnVwZGF0ZShyZXN1bHQuc3ViYXJyYXkoMCwgcHRyKSlcbiAgcG9vbC5mcmVlKHJlc3VsdClcbn1cblxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24ocGFyYW1zKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fVxuICB2YXIgZ2wgPSB0aGlzLmdsXG5cbiAgdGhpcy5kaXJ0eSA9IHRydWVcblxuICBpZignY29udG91ckVuYWJsZScgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5jb250b3VyRW5hYmxlID0gcGFyYW1zLmNvbnRvdXJFbmFibGVcbiAgfVxuICBpZignY29udG91ckNvbG9yJyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLmNvbnRvdXJDb2xvciA9IHBhcmFtcy5jb250b3VyQ29sb3JcbiAgfVxuICBpZignbGluZVdpZHRoJyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLmxpbmVXaWR0aCA9IHBhcmFtcy5saW5lV2lkdGhcbiAgfVxuICBpZignbGlnaHRQb3NpdGlvbicgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5saWdodFBvc2l0aW9uID0gcGFyYW1zLmxpZ2h0UG9zaXRpb25cbiAgfVxuICBpZignb3BhY2l0eScgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5vcGFjaXR5ID0gcGFyYW1zLm9wYWNpdHlcbiAgfVxuICBpZignYW1iaWVudCcgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5hbWJpZW50TGlnaHQgID0gcGFyYW1zLmFtYmllbnRcbiAgfVxuICBpZignZGlmZnVzZScgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5kaWZmdXNlTGlnaHQgPSBwYXJhbXMuZGlmZnVzZVxuICB9XG4gIGlmKCdzcGVjdWxhcicgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5zcGVjdWxhckxpZ2h0ID0gcGFyYW1zLnNwZWN1bGFyXG4gIH1cbiAgaWYoJ3JvdWdobmVzcycgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5yb3VnaG5lc3MgPSBwYXJhbXMucm91Z2huZXNzXG4gIH1cbiAgaWYoJ2ZyZXNuZWwnIGluIHBhcmFtcykge1xuICAgIHRoaXMuZnJlc25lbCA9IHBhcmFtcy5mcmVzbmVsXG4gIH1cblxuICBpZihwYXJhbXMudGV4dHVyZSkge1xuICAgIHRoaXMudGV4dHVyZS5kaXNwb3NlKClcbiAgICB0aGlzLnRleHR1cmUgPSBjcmVhdGVUZXh0dXJlKGdsLCBwYXJhbXMudGV4dHVyZSlcbiAgfSBlbHNlIGlmIChwYXJhbXMuY29sb3JtYXApIHtcbiAgICB0aGlzLnRleHR1cmUuc2hhcGUgPSBbMjU2LDI1Nl1cbiAgICB0aGlzLnRleHR1cmUubWluRmlsdGVyID0gZ2wuTElORUFSX01JUE1BUF9MSU5FQVJcbiAgICB0aGlzLnRleHR1cmUubWFnRmlsdGVyID0gZ2wuTElORUFSXG4gICAgdGhpcy50ZXh0dXJlLnNldFBpeGVscyhnZW5Db2xvcm1hcChwYXJhbXMuY29sb3JtYXApKVxuICAgIHRoaXMudGV4dHVyZS5nZW5lcmF0ZU1pcG1hcCgpXG4gIH1cblxuICB2YXIgY2VsbHMgPSBwYXJhbXMuY2VsbHNcbiAgdmFyIHBvc2l0aW9ucyA9IHBhcmFtcy5wb3NpdGlvbnNcbiAgdmFyIHZlY3RvcnMgPSBwYXJhbXMudmVjdG9yc1xuXG4gIGlmKCFwb3NpdGlvbnMgfHwgIWNlbGxzIHx8ICF2ZWN0b3JzKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICBpZiAocGFyYW1zLnR1YmVTY2FsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdGhpcy50dWJlU2NhbGUgPSBwYXJhbXMudHViZVNjYWxlO1xuICB9XG5cbiAgdmFyIHRQb3MgPSBbXVxuICB2YXIgdFZlYyA9IFtdXG4gIHZhciB0Q29sID0gW11cbiAgdmFyIHROb3IgPSBbXVxuICB2YXIgdFVWcyA9IFtdXG4gIHZhciB0SWRzID0gW11cblxuICB2YXIgZVBvcyA9IFtdXG4gIHZhciBlQ29sID0gW11cbiAgdmFyIGVVVnMgPSBbXVxuICB2YXIgZUlkcyA9IFtdXG5cbiAgdmFyIHBQb3MgPSBbXVxuICB2YXIgcENvbCA9IFtdXG4gIHZhciBwVVZzID0gW11cbiAgdmFyIHBTaXogPSBbXVxuICB2YXIgcElkcyA9IFtdXG5cbiAgLy9TYXZlIGdlb21ldHJ5IGRhdGEgZm9yIHBpY2tpbmcgY2FsY3VsYXRpb25zXG4gIHRoaXMuY2VsbHMgICAgID0gY2VsbHNcbiAgdGhpcy5wb3NpdGlvbnMgPSBwb3NpdGlvbnNcbiAgdGhpcy52ZWN0b3JzICAgPSB2ZWN0b3JzXG5cbiAgLy9Db21wdXRlIG5vcm1hbHNcbiAgdmFyIHZlcnRleE5vcm1hbHMgPSBwYXJhbXMudmVydGV4Tm9ybWFsc1xuICB2YXIgY2VsbE5vcm1hbHMgICA9IHBhcmFtcy5jZWxsTm9ybWFsc1xuICB2YXIgdmVydGV4Tm9ybWFsc0Vwc2lsb24gPSBwYXJhbXMudmVydGV4Tm9ybWFsc0Vwc2lsb24gPT09IHZvaWQoMCkgPyBERUZBVUxUX1ZFUlRFWF9OT1JNQUxTX0VQU0lMT04gOiBwYXJhbXMudmVydGV4Tm9ybWFsc0Vwc2lsb25cbiAgdmFyIGZhY2VOb3JtYWxzRXBzaWxvbiA9IHBhcmFtcy5mYWNlTm9ybWFsc0Vwc2lsb24gPT09IHZvaWQoMCkgPyBERUZBVUxUX0ZBQ0VfTk9STUFMU19FUFNJTE9OIDogcGFyYW1zLmZhY2VOb3JtYWxzRXBzaWxvblxuICBpZihwYXJhbXMudXNlRmFjZXROb3JtYWxzICYmICFjZWxsTm9ybWFscykge1xuICAgIGNlbGxOb3JtYWxzID0gbm9ybWFscy5mYWNlTm9ybWFscyhjZWxscywgcG9zaXRpb25zLCBmYWNlTm9ybWFsc0Vwc2lsb24pXG4gIH1cbiAgaWYoIWNlbGxOb3JtYWxzICYmICF2ZXJ0ZXhOb3JtYWxzKSB7XG4gICAgdmVydGV4Tm9ybWFscyA9IG5vcm1hbHMudmVydGV4Tm9ybWFscyhjZWxscywgcG9zaXRpb25zLCB2ZXJ0ZXhOb3JtYWxzRXBzaWxvbilcbiAgfVxuXG4gIC8vQ29tcHV0ZSBjb2xvcnNcbiAgdmFyIHZlcnRleENvbG9ycyAgICA9IHBhcmFtcy52ZXJ0ZXhDb2xvcnNcbiAgdmFyIGNlbGxDb2xvcnMgICAgICA9IHBhcmFtcy5jZWxsQ29sb3JzXG4gIHZhciBtZXNoQ29sb3IgICAgICAgPSBwYXJhbXMubWVzaENvbG9yIHx8IFsxLDEsMSwxXVxuXG4gIC8vVVZzXG4gIHZhciB2ZXJ0ZXhVVnMgICAgICAgPSBwYXJhbXMudmVydGV4VVZzXG4gIHZhciB2ZXJ0ZXhJbnRlbnNpdHkgPSBwYXJhbXMudmVydGV4SW50ZW5zaXR5XG4gIHZhciBjZWxsVVZzICAgICAgICAgPSBwYXJhbXMuY2VsbFVWc1xuICB2YXIgY2VsbEludGVuc2l0eSAgID0gcGFyYW1zLmNlbGxJbnRlbnNpdHlcblxuICB2YXIgaW50ZW5zaXR5TG8gICAgID0gSW5maW5pdHlcbiAgdmFyIGludGVuc2l0eUhpICAgICA9IC1JbmZpbml0eVxuICBpZighdmVydGV4VVZzICYmICFjZWxsVVZzKSB7XG4gICAgaWYodmVydGV4SW50ZW5zaXR5KSB7XG4gICAgICBpZihwYXJhbXMudmVydGV4SW50ZW5zaXR5Qm91bmRzKSB7XG4gICAgICAgIGludGVuc2l0eUxvID0gK3BhcmFtcy52ZXJ0ZXhJbnRlbnNpdHlCb3VuZHNbMF1cbiAgICAgICAgaW50ZW5zaXR5SGkgPSArcGFyYW1zLnZlcnRleEludGVuc2l0eUJvdW5kc1sxXVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKHZhciBpPTA7IGk8dmVydGV4SW50ZW5zaXR5Lmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgdmFyIGYgPSB2ZXJ0ZXhJbnRlbnNpdHlbaV1cbiAgICAgICAgICBpbnRlbnNpdHlMbyA9IE1hdGgubWluKGludGVuc2l0eUxvLCBmKVxuICAgICAgICAgIGludGVuc2l0eUhpID0gTWF0aC5tYXgoaW50ZW5zaXR5SGksIGYpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYoY2VsbEludGVuc2l0eSkge1xuICAgICAgZm9yKHZhciBpPTA7IGk8Y2VsbEludGVuc2l0eS5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgZiA9IGNlbGxJbnRlbnNpdHlbaV1cbiAgICAgICAgaW50ZW5zaXR5TG8gPSBNYXRoLm1pbihpbnRlbnNpdHlMbywgZilcbiAgICAgICAgaW50ZW5zaXR5SGkgPSBNYXRoLm1heChpbnRlbnNpdHlIaSwgZilcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yKHZhciBpPTA7IGk8cG9zaXRpb25zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciBmID0gcG9zaXRpb25zW2ldWzJdXG4gICAgICAgIGludGVuc2l0eUxvID0gTWF0aC5taW4oaW50ZW5zaXR5TG8sIGYpXG4gICAgICAgIGludGVuc2l0eUhpID0gTWF0aC5tYXgoaW50ZW5zaXR5SGksIGYpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYodmVydGV4SW50ZW5zaXR5KSB7XG4gICAgdGhpcy5pbnRlbnNpdHkgPSB2ZXJ0ZXhJbnRlbnNpdHlcbiAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcbiAgICB0aGlzLmludGVuc2l0eSA9IHVucGFja0ludGVuc2l0eShjZWxscywgcG9zaXRpb25zLmxlbmd0aCwgY2VsbEludGVuc2l0eSlcbiAgfSBlbHNlIHtcbiAgICB0aGlzLmludGVuc2l0eSA9IHRha2VaQ29tcG9uZW50KHBvc2l0aW9ucylcbiAgfVxuXG4gIC8vUG9pbnQgc2l6ZVxuICB2YXIgcG9pbnRTaXplcyAgICAgID0gcGFyYW1zLnBvaW50U2l6ZXNcbiAgdmFyIG1lc2hQb2ludFNpemUgICA9IHBhcmFtcy5wb2ludFNpemUgfHwgMS4wXG5cbiAgLy9VcGRhdGUgYm91bmRzXG4gIHRoaXMuYm91bmRzICAgICAgID0gW1tJbmZpbml0eSxJbmZpbml0eSxJbmZpbml0eV0sIFstSW5maW5pdHksLUluZmluaXR5LC1JbmZpbml0eV1dXG4gIGZvcih2YXIgaT0wOyBpPHBvc2l0aW9ucy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBwID0gcG9zaXRpb25zW2ldXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICBpZihpc05hTihwW2pdKSB8fCAhaXNGaW5pdGUocFtqXSkpIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIHRoaXMuYm91bmRzWzBdW2pdID0gTWF0aC5taW4odGhpcy5ib3VuZHNbMF1bal0sIHBbal0pXG4gICAgICB0aGlzLmJvdW5kc1sxXVtqXSA9IE1hdGgubWF4KHRoaXMuYm91bmRzWzFdW2pdLCBwW2pdKVxuICAgIH1cbiAgfVxuXG4gIC8vUGFjayBjZWxscyBpbnRvIGJ1ZmZlcnNcbiAgdmFyIHRyaWFuZ2xlQ291bnQgPSAwXG4gIHZhciBlZGdlQ291bnQgPSAwXG4gIHZhciBwb2ludENvdW50ID0gMFxuXG5maWxsX2xvb3A6XG4gIGZvcih2YXIgaT0wOyBpPGNlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGNlbGwgPSBjZWxsc1tpXVxuICAgIHN3aXRjaChjZWxsLmxlbmd0aCkge1xuICAgICAgY2FzZSAxOlxuXG4gICAgICAgIHZhciB2ID0gY2VsbFswXVxuICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1t2XVxuXG4gICAgICAgIC8vQ2hlY2sgTmFOc1xuICAgICAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgICAgICBpZihpc05hTihwW2pdKSB8fCAhaXNGaW5pdGUocFtqXSkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlIGZpbGxfbG9vcFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHBQb3MucHVzaChwWzBdLCBwWzFdLCBwWzJdLCBwWzNdKVxuXG4gICAgICAgIHZhciBjXG4gICAgICAgIGlmKHZlcnRleENvbG9ycykge1xuICAgICAgICAgIGMgPSB2ZXJ0ZXhDb2xvcnNbdl1cbiAgICAgICAgfSBlbHNlIGlmKGNlbGxDb2xvcnMpIHtcbiAgICAgICAgICBjID0gY2VsbENvbG9yc1tpXVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGMgPSBtZXNoQ29sb3JcbiAgICAgICAgfVxuICAgICAgICBpZihjLmxlbmd0aCA9PT0gMykge1xuICAgICAgICAgIHBDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCAxKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCBjWzNdKVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHV2XG4gICAgICAgIGlmKHZlcnRleFVWcykge1xuICAgICAgICAgIHV2ID0gdmVydGV4VVZzW3ZdXG4gICAgICAgIH0gZWxzZSBpZih2ZXJ0ZXhJbnRlbnNpdHkpIHtcbiAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgICh2ZXJ0ZXhJbnRlbnNpdHlbdl0gLSBpbnRlbnNpdHlMbykgL1xuICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxuICAgICAgICB9IGVsc2UgaWYoY2VsbFVWcykge1xuICAgICAgICAgIHV2ID0gY2VsbFVWc1tpXVxuICAgICAgICB9IGVsc2UgaWYoY2VsbEludGVuc2l0eSkge1xuICAgICAgICAgIHV2ID0gW1xuICAgICAgICAgICAgKGNlbGxJbnRlbnNpdHlbaV0gLSBpbnRlbnNpdHlMbykgL1xuICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHV2ID0gW1xuICAgICAgICAgICAgKHBbMl0gLSBpbnRlbnNpdHlMbykgL1xuICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxuICAgICAgICB9XG4gICAgICAgIHBVVnMucHVzaCh1dlswXSwgdXZbMV0pXG5cbiAgICAgICAgaWYocG9pbnRTaXplcykge1xuICAgICAgICAgIHBTaXoucHVzaChwb2ludFNpemVzW3ZdKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBTaXoucHVzaChtZXNoUG9pbnRTaXplKVxuICAgICAgICB9XG5cbiAgICAgICAgcElkcy5wdXNoKGkpXG5cbiAgICAgICAgcG9pbnRDb3VudCArPSAxXG4gICAgICBicmVha1xuXG4gICAgICBjYXNlIDI6XG5cbiAgICAgICAgLy9DaGVjayBOYU5zXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xuICAgICAgICAgIHZhciB2ID0gY2VsbFtqXVxuICAgICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXG4gICAgICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XG4gICAgICAgICAgICBpZihpc05hTihwW2tdKSB8fCAhaXNGaW5pdGUocFtrXSkpIHtcbiAgICAgICAgICAgICAgY29udGludWUgZmlsbF9sb29wXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XG4gICAgICAgICAgdmFyIHYgPSBjZWxsW2pdXG4gICAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cblxuICAgICAgICAgIGVQb3MucHVzaChwWzBdLCBwWzFdLCBwWzJdKVxuXG4gICAgICAgICAgdmFyIGNcbiAgICAgICAgICBpZih2ZXJ0ZXhDb2xvcnMpIHtcbiAgICAgICAgICAgIGMgPSB2ZXJ0ZXhDb2xvcnNbdl1cbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbENvbG9ycykge1xuICAgICAgICAgICAgYyA9IGNlbGxDb2xvcnNbaV1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYyA9IG1lc2hDb2xvclxuICAgICAgICAgIH1cbiAgICAgICAgICBpZihjLmxlbmd0aCA9PT0gMykge1xuICAgICAgICAgICAgZUNvbC5wdXNoKGNbMF0sIGNbMV0sIGNbMl0sIDEpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCBjWzNdKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciB1dlxuICAgICAgICAgIGlmKHZlcnRleFVWcykge1xuICAgICAgICAgICAgdXYgPSB2ZXJ0ZXhVVnNbdl1cbiAgICAgICAgICB9IGVsc2UgaWYodmVydGV4SW50ZW5zaXR5KSB7XG4gICAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgICAgKHZlcnRleEludGVuc2l0eVt2XSAtIGludGVuc2l0eUxvKSAvXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgICB9IGVsc2UgaWYoY2VsbFVWcykge1xuICAgICAgICAgICAgdXYgPSBjZWxsVVZzW2ldXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxJbnRlbnNpdHkpIHtcbiAgICAgICAgICAgIHV2ID0gW1xuICAgICAgICAgICAgICAoY2VsbEludGVuc2l0eVtpXSAtIGludGVuc2l0eUxvKSAvXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdXYgPSBbXG4gICAgICAgICAgICAgIChwWzJdIC0gaW50ZW5zaXR5TG8pIC9cbiAgICAgICAgICAgICAgKGludGVuc2l0eUhpIC0gaW50ZW5zaXR5TG8pLCAwXVxuICAgICAgICAgIH1cbiAgICAgICAgICBlVVZzLnB1c2godXZbMF0sIHV2WzFdKVxuXG4gICAgICAgICAgZUlkcy5wdXNoKGkpXG4gICAgICAgIH1cbiAgICAgICAgZWRnZUNvdW50ICs9IDFcbiAgICAgIGJyZWFrXG5cbiAgICAgIGNhc2UgMzpcbiAgICAgICAgLy9DaGVjayBOYU5zXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgICAgIHZhciB2ID0gY2VsbFtqXVxuICAgICAgICAgIHZhciBwID0gcG9zaXRpb25zW3ZdXG4gICAgICAgICAgZm9yKHZhciBrPTA7IGs8MzsgKytrKSB7XG4gICAgICAgICAgICBpZihpc05hTihwW2tdKSB8fCAhaXNGaW5pdGUocFtrXSkpIHtcbiAgICAgICAgICAgICAgY29udGludWUgZmlsbF9sb29wXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICAgICAgdmFyIHYgPSBjZWxsWzIgLSBqXVxuXG4gICAgICAgICAgdmFyIHAgPSBwb3NpdGlvbnNbdl1cbiAgICAgICAgICB0UG9zLnB1c2gocFswXSwgcFsxXSwgcFsyXSwgcFszXSlcblxuICAgICAgICAgIHZhciB3ID0gdmVjdG9yc1t2XVxuICAgICAgICAgIHRWZWMucHVzaCh3WzBdLCB3WzFdLCB3WzJdLCB3WzNdKTtcblxuICAgICAgICAgIHZhciBjXG4gICAgICAgICAgaWYodmVydGV4Q29sb3JzKSB7XG4gICAgICAgICAgICBjID0gdmVydGV4Q29sb3JzW3ZdXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxDb2xvcnMpIHtcbiAgICAgICAgICAgIGMgPSBjZWxsQ29sb3JzW2ldXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGMgPSBtZXNoQ29sb3JcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYoYy5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICAgIHRDb2wucHVzaChjWzBdLCBjWzFdLCBjWzJdLCAxKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0Q29sLnB1c2goY1swXSwgY1sxXSwgY1syXSwgY1szXSlcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgdXZcbiAgICAgICAgICBpZih2ZXJ0ZXhVVnMpIHtcbiAgICAgICAgICAgIHV2ID0gdmVydGV4VVZzW3ZdXG4gICAgICAgICAgfSBlbHNlIGlmKHZlcnRleEludGVuc2l0eSkge1xuICAgICAgICAgICAgdXYgPSBbXG4gICAgICAgICAgICAgICh2ZXJ0ZXhJbnRlbnNpdHlbdl0gLSBpbnRlbnNpdHlMbykgL1xuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXG4gICAgICAgICAgfSBlbHNlIGlmKGNlbGxVVnMpIHtcbiAgICAgICAgICAgIHV2ID0gY2VsbFVWc1tpXVxuICAgICAgICAgIH0gZWxzZSBpZihjZWxsSW50ZW5zaXR5KSB7XG4gICAgICAgICAgICB1diA9IFtcbiAgICAgICAgICAgICAgKGNlbGxJbnRlbnNpdHlbaV0gLSBpbnRlbnNpdHlMbykgL1xuICAgICAgICAgICAgICAoaW50ZW5zaXR5SGkgLSBpbnRlbnNpdHlMbyksIDBdXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHV2ID0gW1xuICAgICAgICAgICAgICAocFsyXSAtIGludGVuc2l0eUxvKSAvXG4gICAgICAgICAgICAgIChpbnRlbnNpdHlIaSAtIGludGVuc2l0eUxvKSwgMF1cbiAgICAgICAgICB9XG4gICAgICAgICAgdFVWcy5wdXNoKHV2WzBdLCB1dlsxXSlcblxuICAgICAgICAgIHZhciBxXG4gICAgICAgICAgaWYodmVydGV4Tm9ybWFscykge1xuICAgICAgICAgICAgcSA9IHZlcnRleE5vcm1hbHNbdl1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcSA9IGNlbGxOb3JtYWxzW2ldXG4gICAgICAgICAgfVxuICAgICAgICAgIHROb3IucHVzaChxWzBdLCBxWzFdLCBxWzJdKVxuXG4gICAgICAgICAgdElkcy5wdXNoKGkpXG4gICAgICAgIH1cbiAgICAgICAgdHJpYW5nbGVDb3VudCArPSAxXG4gICAgICBicmVha1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICB0aGlzLnBvaW50Q291bnQgICAgID0gcG9pbnRDb3VudFxuICB0aGlzLmVkZ2VDb3VudCAgICAgID0gZWRnZUNvdW50XG4gIHRoaXMudHJpYW5nbGVDb3VudCAgPSB0cmlhbmdsZUNvdW50XG5cbiAgdGhpcy5wb2ludFBvc2l0aW9ucy51cGRhdGUocFBvcylcbiAgdGhpcy5wb2ludENvbG9ycy51cGRhdGUocENvbClcbiAgdGhpcy5wb2ludFVWcy51cGRhdGUocFVWcylcbiAgdGhpcy5wb2ludFNpemVzLnVwZGF0ZShwU2l6KVxuICB0aGlzLnBvaW50SWRzLnVwZGF0ZShuZXcgVWludDMyQXJyYXkocElkcykpXG5cbiAgdGhpcy5lZGdlUG9zaXRpb25zLnVwZGF0ZShlUG9zKVxuICB0aGlzLmVkZ2VDb2xvcnMudXBkYXRlKGVDb2wpXG4gIHRoaXMuZWRnZVVWcy51cGRhdGUoZVVWcylcbiAgdGhpcy5lZGdlSWRzLnVwZGF0ZShuZXcgVWludDMyQXJyYXkoZUlkcykpXG5cbiAgdGhpcy50cmlhbmdsZVBvc2l0aW9ucy51cGRhdGUodFBvcylcbiAgdGhpcy50cmlhbmdsZVZlY3RvcnMudXBkYXRlKHRWZWMpXG4gIHRoaXMudHJpYW5nbGVDb2xvcnMudXBkYXRlKHRDb2wpXG4gIHRoaXMudHJpYW5nbGVVVnMudXBkYXRlKHRVVnMpXG4gIHRoaXMudHJpYW5nbGVOb3JtYWxzLnVwZGF0ZSh0Tm9yKVxuICB0aGlzLnRyaWFuZ2xlSWRzLnVwZGF0ZShuZXcgVWludDMyQXJyYXkodElkcykpXG59XG5cbnByb3RvLmRyYXdUcmFuc3BhcmVudCA9IHByb3RvLmRyYXcgPSBmdW5jdGlvbihwYXJhbXMpIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9XG4gIHZhciBnbCAgICAgICAgICA9IHRoaXMuZ2xcbiAgdmFyIG1vZGVsICAgICAgID0gcGFyYW1zLm1vZGVsICAgICAgfHwgSURFTlRJVFlcbiAgdmFyIHZpZXcgICAgICAgID0gcGFyYW1zLnZpZXcgICAgICAgfHwgSURFTlRJVFlcbiAgdmFyIHByb2plY3Rpb24gID0gcGFyYW1zLnByb2plY3Rpb24gfHwgSURFTlRJVFlcblxuICB2YXIgY2xpcEJvdW5kcyA9IFtbLTFlNiwtMWU2LC0xZTZdLFsxZTYsMWU2LDFlNl1dXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIGNsaXBCb3VuZHNbMF1baV0gPSBNYXRoLm1heChjbGlwQm91bmRzWzBdW2ldLCB0aGlzLmNsaXBCb3VuZHNbMF1baV0pXG4gICAgY2xpcEJvdW5kc1sxXVtpXSA9IE1hdGgubWluKGNsaXBCb3VuZHNbMV1baV0sIHRoaXMuY2xpcEJvdW5kc1sxXVtpXSlcbiAgfVxuXG4gIHZhciB1bmlmb3JtcyA9IHtcbiAgICBtb2RlbDogICAgICBtb2RlbCxcbiAgICB2aWV3OiAgICAgICB2aWV3LFxuICAgIHByb2plY3Rpb246IHByb2plY3Rpb24sXG4gICAgaW52ZXJzZU1vZGVsOiBJREVOVElUWS5zbGljZSgpLFxuXG4gICAgY2xpcEJvdW5kczogY2xpcEJvdW5kcyxcblxuICAgIGthbWJpZW50OiAgIHRoaXMuYW1iaWVudExpZ2h0LFxuICAgIGtkaWZmdXNlOiAgIHRoaXMuZGlmZnVzZUxpZ2h0LFxuICAgIGtzcGVjdWxhcjogIHRoaXMuc3BlY3VsYXJMaWdodCxcbiAgICByb3VnaG5lc3M6ICB0aGlzLnJvdWdobmVzcyxcbiAgICBmcmVzbmVsOiAgICB0aGlzLmZyZXNuZWwsXG5cbiAgICBleWVQb3NpdGlvbjogICBbMCwwLDBdLFxuICAgIGxpZ2h0UG9zaXRpb246IFswLDAsMF0sXG5cbiAgICBvcGFjaXR5OiAgdGhpcy5vcGFjaXR5LFxuXG4gICAgdHViZVNjYWxlOiB0aGlzLnR1YmVTY2FsZSxcblxuICAgIGNvbnRvdXJDb2xvcjogdGhpcy5jb250b3VyQ29sb3IsXG5cbiAgICB0ZXh0dXJlOiAgICAwXG4gIH1cblxuICB1bmlmb3Jtcy5pbnZlcnNlTW9kZWwgPSBpbnZlcnQodW5pZm9ybXMuaW52ZXJzZU1vZGVsLCB1bmlmb3Jtcy5tb2RlbClcblxuICBnbC5kaXNhYmxlKGdsLkNVTExfRkFDRSlcblxuICB0aGlzLnRleHR1cmUuYmluZCgwKVxuXG4gIHZhciBpbnZDYW1lcmFNYXRyaXggPSBuZXcgQXJyYXkoMTYpXG4gIG11bHRpcGx5KGludkNhbWVyYU1hdHJpeCwgdW5pZm9ybXMudmlldywgdW5pZm9ybXMubW9kZWwpXG4gIG11bHRpcGx5KGludkNhbWVyYU1hdHJpeCwgdW5pZm9ybXMucHJvamVjdGlvbiwgaW52Q2FtZXJhTWF0cml4KVxuICBpbnZlcnQoaW52Q2FtZXJhTWF0cml4LCBpbnZDYW1lcmFNYXRyaXgpXG5cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgdW5pZm9ybXMuZXllUG9zaXRpb25baV0gPSBpbnZDYW1lcmFNYXRyaXhbMTIraV0gLyBpbnZDYW1lcmFNYXRyaXhbMTVdXG4gIH1cblxuICB2YXIgdyA9IGludkNhbWVyYU1hdHJpeFsxNV1cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgdyArPSB0aGlzLmxpZ2h0UG9zaXRpb25baV0gKiBpbnZDYW1lcmFNYXRyaXhbNCppKzNdXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgdmFyIHMgPSBpbnZDYW1lcmFNYXRyaXhbMTIraV1cbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIHMgKz0gaW52Q2FtZXJhTWF0cml4WzQqaitpXSAqIHRoaXMubGlnaHRQb3NpdGlvbltqXVxuICAgIH1cbiAgICB1bmlmb3Jtcy5saWdodFBvc2l0aW9uW2ldID0gcyAvIHdcbiAgfVxuXG4gIGlmKHRoaXMudHJpYW5nbGVDb3VudCA+IDApIHtcbiAgICB2YXIgc2hhZGVyID0gdGhpcy50cmlTaGFkZXJcbiAgICBzaGFkZXIuYmluZCgpXG4gICAgc2hhZGVyLnVuaWZvcm1zID0gdW5pZm9ybXNcblxuICAgIHRoaXMudHJpYW5nbGVWQU8uYmluZCgpXG4gICAgZ2wuZHJhd0FycmF5cyhnbC5UUklBTkdMRVMsIDAsIHRoaXMudHJpYW5nbGVDb3VudCozKVxuICAgIHRoaXMudHJpYW5nbGVWQU8udW5iaW5kKClcbiAgfVxufVxuXG5wcm90by5kcmF3UGljayA9IGZ1bmN0aW9uKHBhcmFtcykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge31cblxuICB2YXIgZ2wgICAgICAgICA9IHRoaXMuZ2xcblxuICB2YXIgbW9kZWwgICAgICA9IHBhcmFtcy5tb2RlbCAgICAgIHx8IElERU5USVRZXG4gIHZhciB2aWV3ICAgICAgID0gcGFyYW1zLnZpZXcgICAgICAgfHwgSURFTlRJVFlcbiAgdmFyIHByb2plY3Rpb24gPSBwYXJhbXMucHJvamVjdGlvbiB8fCBJREVOVElUWVxuXG4gIHZhciBjbGlwQm91bmRzID0gW1stMWU2LC0xZTYsLTFlNl0sWzFlNiwxZTYsMWU2XV1cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgY2xpcEJvdW5kc1swXVtpXSA9IE1hdGgubWF4KGNsaXBCb3VuZHNbMF1baV0sIHRoaXMuY2xpcEJvdW5kc1swXVtpXSlcbiAgICBjbGlwQm91bmRzWzFdW2ldID0gTWF0aC5taW4oY2xpcEJvdW5kc1sxXVtpXSwgdGhpcy5jbGlwQm91bmRzWzFdW2ldKVxuICB9XG5cbiAgLy9TYXZlIGNhbWVyYSBwYXJhbWV0ZXJzXG4gIHRoaXMuX21vZGVsICAgICAgPSBbXS5zbGljZS5jYWxsKG1vZGVsKVxuICB0aGlzLl92aWV3ICAgICAgID0gW10uc2xpY2UuY2FsbCh2aWV3KVxuICB0aGlzLl9wcm9qZWN0aW9uID0gW10uc2xpY2UuY2FsbChwcm9qZWN0aW9uKVxuICB0aGlzLl9yZXNvbHV0aW9uID0gW2dsLmRyYXdpbmdCdWZmZXJXaWR0aCwgZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF1cblxuICB2YXIgdW5pZm9ybXMgPSB7XG4gICAgbW9kZWw6ICAgICAgbW9kZWwsXG4gICAgdmlldzogICAgICAgdmlldyxcbiAgICBwcm9qZWN0aW9uOiBwcm9qZWN0aW9uLFxuICAgIGNsaXBCb3VuZHM6IGNsaXBCb3VuZHMsXG5cbiAgICB0dWJlU2NhbGU6IHRoaXMudHViZVNjYWxlLFxuXG4gICAgcGlja0lkOiAgICAgdGhpcy5waWNrSWQgLyAyNTUuMCxcbiAgfVxuXG4gIHZhciBzaGFkZXIgPSB0aGlzLnBpY2tTaGFkZXJcbiAgc2hhZGVyLmJpbmQoKVxuICBzaGFkZXIudW5pZm9ybXMgPSB1bmlmb3Jtc1xuXG4gIGlmKHRoaXMudHJpYW5nbGVDb3VudCA+IDApIHtcbiAgICB0aGlzLnRyaWFuZ2xlVkFPLmJpbmQoKVxuICAgIGdsLmRyYXdBcnJheXMoZ2wuVFJJQU5HTEVTLCAwLCB0aGlzLnRyaWFuZ2xlQ291bnQqMylcbiAgICB0aGlzLnRyaWFuZ2xlVkFPLnVuYmluZCgpXG4gIH1cblxuICBpZih0aGlzLmVkZ2VDb3VudCA+IDApIHtcbiAgICB0aGlzLmVkZ2VWQU8uYmluZCgpXG4gICAgZ2wubGluZVdpZHRoKHRoaXMubGluZVdpZHRoICogdGhpcy5waXhlbFJhdGlvKVxuICAgIGdsLmRyYXdBcnJheXMoZ2wuTElORVMsIDAsIHRoaXMuZWRnZUNvdW50KjIpXG4gICAgdGhpcy5lZGdlVkFPLnVuYmluZCgpXG4gIH1cblxufVxuXG5cbnByb3RvLnBpY2sgPSBmdW5jdGlvbihwaWNrRGF0YSkge1xuICBpZighcGlja0RhdGEpIHtcbiAgICByZXR1cm4gbnVsbFxuICB9XG4gIGlmKHBpY2tEYXRhLmlkICE9PSB0aGlzLnBpY2tJZCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICB2YXIgY2VsbElkID0gcGlja0RhdGEudmFsdWVbMF0gKyAyNTYqcGlja0RhdGEudmFsdWVbMV0gKyA2NTUzNipwaWNrRGF0YS52YWx1ZVsyXVxuICB2YXIgY2VsbCA9IHRoaXMuY2VsbHNbY2VsbElkXVxuXG4gIHZhciBwb3MgPSB0aGlzLnBvc2l0aW9uc1tjZWxsWzFdXS5zbGljZSgwLCAzKVxuICB2YXIgaW50ZW5zaXR5ID0gdGhpcy5pbnRlbnNpdHlbY2VsbFsxXV1cbiAgdmFyIHZlbG9jaXR5ID0gdGhpcy52ZWN0b3JzW2NlbGxbMV1dLnNsaWNlKDAsIDMpXG4gIHZhciBkaXZlcmdlbmNlID0gdGhpcy52ZWN0b3JzW2NlbGxbMV1dWzNdXG5cbiAgcmV0dXJuIHtcbiAgICBpbmRleDogY2VsbElkLFxuICAgIHBvc2l0aW9uOiBwb3MsXG4gICAgaW50ZW5zaXR5OiBpbnRlbnNpdHksXG4gICAgdmVsb2NpdHk6IHZlbG9jaXR5LFxuICAgIGRpdmVyZ2VuY2U6IGRpdmVyZ2VuY2UsXG4gICAgZGF0YUNvb3JkaW5hdGU6IHBvc1xuICB9XG59XG5cblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnRleHR1cmUuZGlzcG9zZSgpXG5cbiAgdGhpcy50cmlTaGFkZXIuZGlzcG9zZSgpXG4gIHRoaXMucGlja1NoYWRlci5kaXNwb3NlKClcblxuICB0aGlzLnRyaWFuZ2xlVkFPLmRpc3Bvc2UoKVxuICB0aGlzLnRyaWFuZ2xlUG9zaXRpb25zLmRpc3Bvc2UoKVxuICB0aGlzLnRyaWFuZ2xlVmVjdG9ycy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZUNvbG9ycy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZVVWcy5kaXNwb3NlKClcbiAgdGhpcy50cmlhbmdsZU5vcm1hbHMuZGlzcG9zZSgpXG4gIHRoaXMudHJpYW5nbGVJZHMuZGlzcG9zZSgpXG5cbiAgdGhpcy5lZGdlVkFPLmRpc3Bvc2UoKVxuICB0aGlzLmVkZ2VQb3NpdGlvbnMuZGlzcG9zZSgpXG4gIHRoaXMuZWRnZUNvbG9ycy5kaXNwb3NlKClcbiAgdGhpcy5lZGdlVVZzLmRpc3Bvc2UoKVxuICB0aGlzLmVkZ2VJZHMuZGlzcG9zZSgpXG5cbiAgdGhpcy5wb2ludFZBTy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFBvc2l0aW9ucy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludENvbG9ycy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFVWcy5kaXNwb3NlKClcbiAgdGhpcy5wb2ludFNpemVzLmRpc3Bvc2UoKVxuICB0aGlzLnBvaW50SWRzLmRpc3Bvc2UoKVxuXG4gIHRoaXMuY29udG91clZBTy5kaXNwb3NlKClcbiAgdGhpcy5jb250b3VyUG9zaXRpb25zLmRpc3Bvc2UoKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVNZXNoU2hhZGVyKGdsKSB7XG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIG1lc2hTaGFkZXIudmVydGV4LCBtZXNoU2hhZGVyLmZyYWdtZW50LCBudWxsLCBtZXNoU2hhZGVyLmF0dHJpYnV0ZXMpXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnBvc2l0aW9uLmxvY2F0aW9uID0gMFxuICBzaGFkZXIuYXR0cmlidXRlcy5jb2xvci5sb2NhdGlvbiAgICA9IDJcbiAgc2hhZGVyLmF0dHJpYnV0ZXMudXYubG9jYXRpb24gICAgICAgPSAzXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnZlY3Rvci5sb2NhdGlvbiAgID0gNVxuICByZXR1cm4gc2hhZGVyXG59XG5cblxuZnVuY3Rpb24gY3JlYXRlUGlja1NoYWRlcihnbCkge1xuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBwaWNrU2hhZGVyLnZlcnRleCwgcGlja1NoYWRlci5mcmFnbWVudCwgbnVsbCwgcGlja1NoYWRlci5hdHRyaWJ1dGVzKVxuICBzaGFkZXIuYXR0cmlidXRlcy5wb3NpdGlvbi5sb2NhdGlvbiA9IDBcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuaWQubG9jYXRpb24gICAgICAgPSAxXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnZlY3Rvci5sb2NhdGlvbiAgID0gNVxuICByZXR1cm4gc2hhZGVyXG59XG5cblxuZnVuY3Rpb24gY3JlYXRlU2ltcGxpY2lhbE1lc2goZ2wsIHBhcmFtcykge1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgIHBhcmFtcyA9IGdsO1xuICAgIGdsID0gcGFyYW1zLmdsO1xuICB9XG5cbiAgdmFyIHRyaVNoYWRlciAgICAgICA9IHBhcmFtcy50cmlTaGFkZXIgfHwgY3JlYXRlTWVzaFNoYWRlcihnbClcbiAgdmFyIHBpY2tTaGFkZXIgICAgICA9IGNyZWF0ZVBpY2tTaGFkZXIoZ2wpXG5cbiAgdmFyIG1lc2hUZXh0dXJlICAgICAgID0gY3JlYXRlVGV4dHVyZShnbCxcbiAgICBuZGFycmF5KG5ldyBVaW50OEFycmF5KFsyNTUsMjU1LDI1NSwyNTVdKSwgWzEsMSw0XSkpXG4gIG1lc2hUZXh0dXJlLmdlbmVyYXRlTWlwbWFwKClcbiAgbWVzaFRleHR1cmUubWluRmlsdGVyID0gZ2wuTElORUFSX01JUE1BUF9MSU5FQVJcbiAgbWVzaFRleHR1cmUubWFnRmlsdGVyID0gZ2wuTElORUFSXG5cbiAgdmFyIHRyaWFuZ2xlUG9zaXRpb25zID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgdHJpYW5nbGVWZWN0b3JzICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciB0cmlhbmdsZUNvbG9ycyAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHRyaWFuZ2xlVVZzICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgdHJpYW5nbGVOb3JtYWxzICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciB0cmlhbmdsZUlkcyAgICAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIHRyaWFuZ2xlVkFPICAgICAgID0gY3JlYXRlVkFPKGdsLCBbXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlUG9zaXRpb25zLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiA0XG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVJZHMsXG4gICAgICB0eXBlOiBnbC5VTlNJR05FRF9CWVRFLFxuICAgICAgc2l6ZTogNCxcbiAgICAgIG5vcm1hbGl6ZWQ6IHRydWVcbiAgICB9LFxuICAgIHsgYnVmZmVyOiB0cmlhbmdsZUNvbG9ycyxcbiAgICAgIHR5cGU6IGdsLkZMT0FULFxuICAgICAgc2l6ZTogNFxuICAgIH0sXG4gICAgeyBidWZmZXI6IHRyaWFuZ2xlVVZzLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiAyXG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVOb3JtYWxzLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiAzXG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogdHJpYW5nbGVWZWN0b3JzLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiA0XG4gICAgfVxuICBdKVxuXG4gIHZhciBlZGdlUG9zaXRpb25zID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgZWRnZUNvbG9ycyAgICA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIGVkZ2VVVnMgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBlZGdlSWRzICAgICAgID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgZWRnZVZBTyAgICAgICA9IGNyZWF0ZVZBTyhnbCwgW1xuICAgIHsgYnVmZmVyOiBlZGdlUG9zaXRpb25zLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiAzXG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogZWRnZUlkcyxcbiAgICAgIHR5cGU6IGdsLlVOU0lHTkVEX0JZVEUsXG4gICAgICBzaXplOiA0LFxuICAgICAgbm9ybWFsaXplZDogdHJ1ZVxuICAgIH0sXG4gICAgeyBidWZmZXI6IGVkZ2VDb2xvcnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDRcbiAgICB9LFxuICAgIHsgYnVmZmVyOiBlZGdlVVZzLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiAyXG4gICAgfVxuICBdKVxuXG4gIHZhciBwb2ludFBvc2l0aW9ucyAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBwb2ludENvbG9ycyAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBwb2ludFVWcyAgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBwb2ludFNpemVzICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBwb2ludElkcyAgICAgICAgPSBjcmVhdGVCdWZmZXIoZ2wpXG4gIHZhciBwb2ludFZBTyAgICAgICAgPSBjcmVhdGVWQU8oZ2wsIFtcbiAgICB7IGJ1ZmZlcjogcG9pbnRQb3NpdGlvbnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDNcbiAgICB9LFxuICAgIHsgYnVmZmVyOiBwb2ludElkcyxcbiAgICAgIHR5cGU6IGdsLlVOU0lHTkVEX0JZVEUsXG4gICAgICBzaXplOiA0LFxuICAgICAgbm9ybWFsaXplZDogdHJ1ZVxuICAgIH0sXG4gICAgeyBidWZmZXI6IHBvaW50Q29sb3JzLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiA0XG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogcG9pbnRVVnMsXG4gICAgICB0eXBlOiBnbC5GTE9BVCxcbiAgICAgIHNpemU6IDJcbiAgICB9LFxuICAgIHsgYnVmZmVyOiBwb2ludFNpemVzLFxuICAgICAgdHlwZTogZ2wuRkxPQVQsXG4gICAgICBzaXplOiAxXG4gICAgfVxuICBdKVxuXG4gIHZhciBjb250b3VyUG9zaXRpb25zID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgY29udG91clZBTyAgICAgICA9IGNyZWF0ZVZBTyhnbCwgW1xuICAgIHsgYnVmZmVyOiBjb250b3VyUG9zaXRpb25zLFxuICAgICAgdHlwZTogICBnbC5GTE9BVCxcbiAgICAgIHNpemU6ICAgM1xuICAgIH1dKVxuXG4gIHZhciBtZXNoID0gbmV3IFNpbXBsaWNpYWxNZXNoKGdsXG4gICAgLCBtZXNoVGV4dHVyZVxuICAgICwgdHJpU2hhZGVyXG4gICAgLCBwaWNrU2hhZGVyXG4gICAgLCB0cmlhbmdsZVBvc2l0aW9uc1xuICAgICwgdHJpYW5nbGVWZWN0b3JzXG4gICAgLCB0cmlhbmdsZUlkc1xuICAgICwgdHJpYW5nbGVDb2xvcnNcbiAgICAsIHRyaWFuZ2xlVVZzXG4gICAgLCB0cmlhbmdsZU5vcm1hbHNcbiAgICAsIHRyaWFuZ2xlVkFPXG4gICAgLCBlZGdlUG9zaXRpb25zXG4gICAgLCBlZGdlSWRzXG4gICAgLCBlZGdlQ29sb3JzXG4gICAgLCBlZGdlVVZzXG4gICAgLCBlZGdlVkFPXG4gICAgLCBwb2ludFBvc2l0aW9uc1xuICAgICwgcG9pbnRJZHNcbiAgICAsIHBvaW50Q29sb3JzXG4gICAgLCBwb2ludFVWc1xuICAgICwgcG9pbnRTaXplc1xuICAgICwgcG9pbnRWQU9cbiAgICAsIGNvbnRvdXJQb3NpdGlvbnNcbiAgICAsIGNvbnRvdXJWQU8pXG5cbiAgbWVzaC51cGRhdGUocGFyYW1zKVxuXG4gIHJldHVybiBtZXNoXG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU2ltcGxpY2lhbE1lc2hcblxufSx7XCIuL3NoYWRlcnNcIjozMTEsXCJjb2xvcm1hcFwiOjEyNixcImdsLWJ1ZmZlclwiOjI0MSxcImdsLW1hdDQvaW52ZXJ0XCI6MjY1LFwiZ2wtbWF0NC9tdWx0aXBseVwiOjI2NyxcImdsLXNoYWRlclwiOjMwMSxcImdsLXRleHR1cmUyZFwiOjMyMixcImdsLXZhb1wiOjMyNyxcIm5kYXJyYXlcIjo0NTAsXCJub3JtYWxzXCI6NDUzLFwic2ltcGxpY2lhbC1jb21wbGV4LWNvbnRvdXJcIjo1MTgsXCJ0eXBlZGFycmF5LXBvb2xcIjo1NDV9XSwzMTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB2ZWMzID0gX2RlcmVxXygnZ2wtdmVjMycpO1xudmFyIHZlYzQgPSBfZGVyZXFfKCdnbC12ZWM0Jyk7XG5cbnZhciBzdHJlYW1Ub1R1YmUgPSBmdW5jdGlvbihzdHJlYW0sIG1heERpdmVyZ2VuY2UsIG1pbkRpc3RhbmNlLCBtYXhOb3JtKSB7XG5cdHZhciBwb2ludHMgPSBzdHJlYW0ucG9pbnRzO1xuXHR2YXIgdmVsb2NpdGllcyA9IHN0cmVhbS52ZWxvY2l0aWVzO1xuXHR2YXIgZGl2ZXJnZW5jZXMgPSBzdHJlYW0uZGl2ZXJnZW5jZXM7XG5cblx0dmFyIHAsIGZ3ZCwgciwgdSwgdiwgdXA7XG5cdHVwID0gdmVjMy5zZXQodmVjMy5jcmVhdGUoKSwgMCwgMSwgMCk7XG5cdHUgPSB2ZWMzLmNyZWF0ZSgpO1xuXHR2ID0gdmVjMy5jcmVhdGUoKTtcblx0dmFyIHAyID0gdmVjMy5jcmVhdGUoKTtcblxuXHR2YXIgdmVydHMgPSBbXTtcblx0dmFyIGZhY2VzID0gW107XG5cdHZhciB2ZWN0b3JzID0gW107XG5cdHZhciBwcmV2aW91c1ZlcnRzID0gW107XG5cdHZhciBjdXJyZW50VmVydHMgPSBbXTtcblx0dmFyIGludGVuc2l0aWVzID0gW107XG5cdHZhciBwcmV2aW91c0ludGVuc2l0eSA9IDA7XG5cdHZhciBjdXJyZW50SW50ZW5zaXR5ID0gMDtcblx0dmFyIGN1cnJlbnRWZWN0b3IgPSB2ZWM0LmNyZWF0ZSgpO1xuXHR2YXIgcHJldmlvdXNWZWN0b3IgPSB2ZWM0LmNyZWF0ZSgpO1xuXG5cdHZhciBmYWNldHMgPSA4O1xuXG5cdGZvciAodmFyIGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0cCA9IHBvaW50c1tpXTtcblx0XHRmd2QgPSB2ZWxvY2l0aWVzW2ldO1xuXHRcdHIgPSBkaXZlcmdlbmNlc1tpXTtcblx0XHRpZiAobWF4RGl2ZXJnZW5jZSA9PT0gMCkge1xuXHRcdFx0ciA9IG1pbkRpc3RhbmNlICogMC4wNTtcblx0XHR9XG5cdFx0Y3VycmVudEludGVuc2l0eSA9IHZlYzMubGVuZ3RoKGZ3ZCkgLyBtYXhOb3JtO1xuXHRcdGN1cnJlbnRWZWN0b3IgPSB2ZWM0LmNyZWF0ZSgpO1xuXHRcdHZlYzMuY29weShjdXJyZW50VmVjdG9yLCBmd2QpO1xuXHRcdGN1cnJlbnRWZWN0b3JbM10gPSByO1xuXHRcdFxuXHRcdGZvciAodmFyIGEgPSAwOyBhIDwgZmFjZXRzOyBhKyspIHtcblx0XHRcdGN1cnJlbnRWZXJ0c1thXSA9IFtwWzBdLCBwWzFdLCBwWzJdLCBhXTtcblx0XHR9XG5cdFx0aWYgKHByZXZpb3VzVmVydHMubGVuZ3RoID4gMCkge1xuXHRcdFx0Zm9yICh2YXIgYSA9IDA7IGEgPCBmYWNldHM7IGErKykge1xuXHRcdFx0XHR2YXIgYTEgPSAoYSsxKSAlIGZhY2V0cztcblx0XHRcdFx0dmVydHMucHVzaChcblx0XHRcdFx0XHRwcmV2aW91c1ZlcnRzW2FdLFxuXHRcdFx0XHRcdGN1cnJlbnRWZXJ0c1thXSxcblx0XHRcdFx0XHRjdXJyZW50VmVydHNbYTFdLFxuXG5cdFx0XHRcdFx0Y3VycmVudFZlcnRzW2ExXSxcblx0XHRcdFx0XHRwcmV2aW91c1ZlcnRzW2ExXSxcblx0XHRcdFx0XHRwcmV2aW91c1ZlcnRzW2FdXG5cdFx0XHRcdCk7XG5cdFx0XHRcdHZlY3RvcnMucHVzaChcblx0XHRcdFx0XHRwcmV2aW91c1ZlY3Rvcixcblx0XHRcdFx0XHRjdXJyZW50VmVjdG9yLFxuXHRcdFx0XHRcdGN1cnJlbnRWZWN0b3IsXG5cblx0XHRcdFx0XHRjdXJyZW50VmVjdG9yLFxuXHRcdFx0XHRcdHByZXZpb3VzVmVjdG9yLFxuXHRcdFx0XHRcdHByZXZpb3VzVmVjdG9yXG5cdFx0XHRcdCk7XG5cdFx0XHRcdGludGVuc2l0aWVzLnB1c2goXG5cdFx0XHRcdFx0cHJldmlvdXNJbnRlbnNpdHksXG5cdFx0XHRcdFx0Y3VycmVudEludGVuc2l0eSxcblx0XHRcdFx0XHRjdXJyZW50SW50ZW5zaXR5LFxuXG5cdFx0XHRcdFx0Y3VycmVudEludGVuc2l0eSxcblx0XHRcdFx0XHRwcmV2aW91c0ludGVuc2l0eSxcblx0XHRcdFx0XHRwcmV2aW91c0ludGVuc2l0eVxuXHRcdFx0XHQpO1xuXHRcdFx0XHRmYWNlcy5wdXNoKFxuXHRcdFx0XHRcdFt2ZXJ0cy5sZW5ndGgtNiwgdmVydHMubGVuZ3RoLTUsIHZlcnRzLmxlbmd0aC00XSxcblx0XHRcdFx0XHRbdmVydHMubGVuZ3RoLTMsIHZlcnRzLmxlbmd0aC0yLCB2ZXJ0cy5sZW5ndGgtMV1cblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dmFyIHRtcCA9IHByZXZpb3VzVmVydHM7XG5cdFx0cHJldmlvdXNWZXJ0cyA9IGN1cnJlbnRWZXJ0cztcblx0XHRjdXJyZW50VmVydHMgPSB0bXA7XG5cdFx0dG1wID0gcHJldmlvdXNWZWN0b3I7XG5cdFx0cHJldmlvdXNWZWN0b3IgPSBjdXJyZW50VmVjdG9yO1xuXHRcdGN1cnJlbnRWZWN0b3IgPSB0bXA7XG5cdFx0dG1wID0gcHJldmlvdXNJbnRlbnNpdHk7XG5cdFx0cHJldmlvdXNJbnRlbnNpdHkgPSBjdXJyZW50SW50ZW5zaXR5O1xuXHRcdGN1cnJlbnRJbnRlbnNpdHkgPSB0bXA7XG5cdH1cblx0cmV0dXJuIHtcblx0XHRwb3NpdGlvbnM6IHZlcnRzLFxuXHRcdGNlbGxzOiBmYWNlcyxcblx0XHR2ZWN0b3JzOiB2ZWN0b3JzLFxuXHRcdHZlcnRleEludGVuc2l0eTogaW50ZW5zaXRpZXNcblx0fTtcblxufTtcblxudmFyIGNyZWF0ZVR1YmVzID0gZnVuY3Rpb24oc3RyZWFtcywgY29sb3JtYXAsIG1heERpdmVyZ2VuY2UsIG1pbkRpc3RhbmNlKSB7XG5cblx0dmFyIG1heE5vcm0gPSAwO1xuXHRmb3IgKHZhciBpPTA7IGk8c3RyZWFtcy5sZW5ndGg7IGkrKykge1xuXHRcdHZhciB2ZWxvY2l0aWVzID0gc3RyZWFtc1tpXS52ZWxvY2l0aWVzO1xuXHRcdGZvciAodmFyIGo9MDsgajx2ZWxvY2l0aWVzLmxlbmd0aDsgaisrKSB7XG5cdFx0XHR2YXIgbm9ybSA9IHZlYzMubGVuZ3RoKHZlbG9jaXRpZXNbal0pO1xuXHRcdFx0aWYgKG5vcm0gPiBtYXhOb3JtKSB7XG5cdFx0XHRcdG1heE5vcm0gPSBub3JtO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHZhciB0dWJlcyA9IHN0cmVhbXMubWFwKGZ1bmN0aW9uKHMpIHtcblx0XHRyZXR1cm4gc3RyZWFtVG9UdWJlKHMsIG1heERpdmVyZ2VuY2UsIG1pbkRpc3RhbmNlLCBtYXhOb3JtKTtcblx0fSk7XG5cblx0dmFyIHBvc2l0aW9ucyA9IFtdO1xuXHR2YXIgY2VsbHMgPSBbXTtcblx0dmFyIHZlY3RvcnMgPSBbXTtcblx0dmFyIHZlcnRleEludGVuc2l0eSA9IFtdO1xuXHRmb3IgKHZhciBpPTA7IGkgPCB0dWJlcy5sZW5ndGg7IGkrKykge1xuXHRcdHZhciB0dWJlID0gdHViZXNbaV07XG5cdFx0dmFyIG9mZnNldCA9IHBvc2l0aW9ucy5sZW5ndGg7XG5cdFx0cG9zaXRpb25zID0gcG9zaXRpb25zLmNvbmNhdCh0dWJlLnBvc2l0aW9ucyk7XG5cdFx0dmVjdG9ycyA9IHZlY3RvcnMuY29uY2F0KHR1YmUudmVjdG9ycyk7XG5cdFx0dmVydGV4SW50ZW5zaXR5ID0gdmVydGV4SW50ZW5zaXR5LmNvbmNhdCh0dWJlLnZlcnRleEludGVuc2l0eSk7XG5cdFx0Zm9yICh2YXIgaj0wOyBqPHR1YmUuY2VsbHMubGVuZ3RoOyBqKyspIHtcblx0XHRcdHZhciBjZWxsID0gdHViZS5jZWxsc1tqXTtcblx0XHRcdHZhciBuZXdDZWxsID0gW107XG5cdFx0XHRjZWxscy5wdXNoKG5ld0NlbGwpO1xuXHRcdFx0Zm9yICh2YXIgaz0wOyBrPGNlbGwubGVuZ3RoOyBrKyspIHtcblx0XHRcdFx0bmV3Q2VsbC5wdXNoKGNlbGxba10gKyBvZmZzZXQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXHRyZXR1cm4ge1xuXHRcdHBvc2l0aW9uczogcG9zaXRpb25zLFxuXHRcdGNlbGxzOiBjZWxscyxcblx0XHR2ZWN0b3JzOiB2ZWN0b3JzLFxuXHRcdHZlcnRleEludGVuc2l0eTogdmVydGV4SW50ZW5zaXR5LFxuXHRcdGNvbG9ybWFwOiBjb2xvcm1hcFxuXHR9O1xufTtcblxudmFyIGRlZmF1bHRHZXREaXZlcmdlbmNlID0gZnVuY3Rpb24ocCwgdjApIHtcblx0dmFyIGRwID0gdmVjMy5jcmVhdGUoKTtcblx0dmFyIGUgPSAxLzEwMDAwO1xuXG5cdHZlYzMuYWRkKGRwLCBwLCBbZSwgMCwgMF0pO1xuXHR2YXIgdnggPSB0aGlzLmdldFZlbG9jaXR5KGRwKTtcblx0dmVjMy5zdWJ0cmFjdCh2eCwgdngsIHYwKTtcblx0dmVjMy5zY2FsZSh2eCwgdngsIDEvZSk7XG5cblx0dmVjMy5hZGQoZHAsIHAsIFswLCBlLCAwXSk7XG5cdHZhciB2eSA9IHRoaXMuZ2V0VmVsb2NpdHkoZHApO1xuXHR2ZWMzLnN1YnRyYWN0KHZ5LCB2eSwgdjApO1xuXHR2ZWMzLnNjYWxlKHZ5LCB2eSwgMS9lKTtcblxuXHR2ZWMzLmFkZChkcCwgcCwgWzAsIDAsIGVdKTtcblx0dmFyIHZ6ID0gdGhpcy5nZXRWZWxvY2l0eShkcCk7XG5cdHZlYzMuc3VidHJhY3QodnosIHZ6LCB2MCk7XG5cdHZlYzMuc2NhbGUodnosIHZ6LCAxL2UpO1xuXG5cdHZlYzMuYWRkKGRwLCB2eCwgdnkpO1xuXHR2ZWMzLmFkZChkcCwgZHAsIHZ6KTtcblx0cmV0dXJuIGRwO1xufTtcblxudmFyIGRlZmF1bHRHZXRWZWxvY2l0eSA9IGZ1bmN0aW9uKHApIHtcbiAgICB2YXIgdSA9IHNhbXBsZU1lc2hncmlkKHAsIHRoaXMudmVjdG9ycywgdGhpcy5tZXNoZ3JpZCwgdGhpcy5jbGFtcEJvcmRlcnMpO1xuICAgIHJldHVybiB1O1xufTtcblxuXG52YXIgZmluZExhc3RTbWFsbGVySW5kZXggPSBmdW5jdGlvbihwb2ludHMsIHYpIHtcbiAgZm9yICh2YXIgaT0wOyBpPHBvaW50cy5sZW5ndGg7IGkrKykge1xuICBcdHZhciBwID0gcG9pbnRzW2ldO1xuICBcdGlmIChwID09PSB2KSByZXR1cm4gaTtcbiAgICBpZiAocCA+IHYpIHJldHVybiBpLTE7XG4gIH1cbiAgcmV0dXJuIGk7XG59O1xuXG52YXIgdG1wID0gdmVjMy5jcmVhdGUoKTtcbnZhciB0bXAyID0gdmVjMy5jcmVhdGUoKTtcblxudmFyIGNsYW1wID0gZnVuY3Rpb24odiwgbWluLCBtYXgpIHtcblx0cmV0dXJuIHYgPCBtaW4gPyBtaW4gOiAodiA+IG1heCA/IG1heCA6IHYpO1xufTtcblxudmFyIHNhbXBsZU1lc2hncmlkID0gZnVuY3Rpb24ocG9pbnQsIGFycmF5LCBtZXNoZ3JpZCwgY2xhbXBPdmVyZmxvdykge1xuXHR2YXIgeCA9IHBvaW50WzBdO1xuXHR2YXIgeSA9IHBvaW50WzFdO1xuXHR2YXIgeiA9IHBvaW50WzJdO1xuXG5cdHZhciB3ID0gbWVzaGdyaWRbMF0ubGVuZ3RoO1xuXHR2YXIgaCA9IG1lc2hncmlkWzFdLmxlbmd0aDtcblx0dmFyIGQgPSBtZXNoZ3JpZFsyXS5sZW5ndGg7XG5cblx0Ly8gRmluZCB0aGUgaW5kZXggb2YgdGhlIG5lYXJlc3Qgc21hbGxlciB2YWx1ZSBpbiB0aGUgbWVzaGdyaWQgZm9yIGVhY2ggY29vcmRpbmF0ZSBvZiAoeCx5LHopLlxuXHQvLyBUaGUgbmVhcmVzdCBzbWFsbGVyIHZhbHVlIGluZGV4IGZvciB4IGlzIHRoZSBpbmRleCB4MCBzdWNoIHRoYXRcblx0Ly8gbWVzaGdyaWRbMF1beDBdIDwgeCBhbmQgZm9yIGFsbCB4MSA+IHgwLCBtZXNoZ3JpZFswXVt4MV0gPj0geC5cblx0dmFyIHgwID0gZmluZExhc3RTbWFsbGVySW5kZXgobWVzaGdyaWRbMF0sIHgpO1xuXHR2YXIgeTAgPSBmaW5kTGFzdFNtYWxsZXJJbmRleChtZXNoZ3JpZFsxXSwgeSk7XG5cdHZhciB6MCA9IGZpbmRMYXN0U21hbGxlckluZGV4KG1lc2hncmlkWzJdLCB6KTtcblxuXHQvLyBHZXQgdGhlIG5lYXJlc3QgbGFyZ2VyIG1lc2hncmlkIHZhbHVlIGluZGljZXMuXG5cdC8vIEZyb20gdGhlIGFib3ZlIFwibmVhcmVzdCBzbWFsbGVyIHZhbHVlXCIsIHdlIGtub3cgdGhhdFxuXHQvLyAgIG1lc2hncmlkWzBdW3gwXSA8IHhcblx0Ly8gICBtZXNoZ3JpZFswXVt4MCsxXSA+PSB4XG5cdHZhciB4MSA9IHgwICsgMTtcblx0dmFyIHkxID0geTAgKyAxO1xuXHR2YXIgejEgPSB6MCArIDE7XG5cblx0aWYgKG1lc2hncmlkWzBdW3gwXSA9PT0geCkgeDEgPSB4MDtcblx0aWYgKG1lc2hncmlkWzFdW3kwXSA9PT0geSkgeTEgPSB5MDtcblx0aWYgKG1lc2hncmlkWzJdW3owXSA9PT0geikgejEgPSB6MDtcblxuXHRpZiAoY2xhbXBPdmVyZmxvdykge1xuXHRcdHgwID0gY2xhbXAoeDAsIDAsIHctMSk7XG5cdFx0eDEgPSBjbGFtcCh4MSwgMCwgdy0xKTtcblx0XHR5MCA9IGNsYW1wKHkwLCAwLCBoLTEpO1xuXHRcdHkxID0gY2xhbXAoeTEsIDAsIGgtMSk7XG5cdFx0ejAgPSBjbGFtcCh6MCwgMCwgZC0xKTtcblx0XHR6MSA9IGNsYW1wKHoxLCAwLCBkLTEpO1xuXHR9XG5cblx0Ly8gUmVqZWN0IHBvaW50cyBvdXRzaWRlIHRoZSBtZXNoZ3JpZCwgcmV0dXJuIGEgemVybyB2ZWN0b3IuXG5cdGlmICh4MCA8IDAgfHwgeTAgPCAwIHx8IHowIDwgMCB8fCB4MSA+PSB3IHx8IHkxID49IGggfHwgejEgPj0gZCkge1xuXHRcdHJldHVybiB2ZWMzLmNyZWF0ZSgpO1xuXHR9XG5cblx0Ly8gTm9ybWFsaXplIHBvaW50IGNvb3JkaW5hdGVzIHRvIDAuLjEgc2NhbGluZyBmYWN0b3IgYmV0d2VlbiB4MCBhbmQgeDEuXG5cdHZhciB4ZiA9ICh4IC0gbWVzaGdyaWRbMF1beDBdKSAvIChtZXNoZ3JpZFswXVt4MV0gLSBtZXNoZ3JpZFswXVt4MF0pO1xuXHR2YXIgeWYgPSAoeSAtIG1lc2hncmlkWzFdW3kwXSkgLyAobWVzaGdyaWRbMV1beTFdIC0gbWVzaGdyaWRbMV1beTBdKTtcblx0dmFyIHpmID0gKHogLSBtZXNoZ3JpZFsyXVt6MF0pIC8gKG1lc2hncmlkWzJdW3oxXSAtIG1lc2hncmlkWzJdW3owXSk7XG5cblx0aWYgKHhmIDwgMCB8fCB4ZiA+IDEgfHwgaXNOYU4oeGYpKSB4ZiA9IDA7XG5cdGlmICh5ZiA8IDAgfHwgeWYgPiAxIHx8IGlzTmFOKHlmKSkgeWYgPSAwO1xuXHRpZiAoemYgPCAwIHx8IHpmID4gMSB8fCBpc05hTih6ZikpIHpmID0gMDtcblxuXHR2YXIgejBvZmYgPSB6MCp3Kmg7XG5cdHZhciB6MW9mZiA9IHoxKncqaDtcblxuXHR2YXIgeTBvZmYgPSB5MCp3O1xuXHR2YXIgeTFvZmYgPSB5MSp3O1xuXG5cdHZhciB4MG9mZiA9IHgwO1xuXHR2YXIgeDFvZmYgPSB4MTtcblxuXHQvLyBTYW1wbGUgZGF0YSBhcnJheSBhcm91bmQgdGhlICh4LHkseikgcG9pbnQuXG5cdC8vICB2WllYID0gYXJyYXlbelpvZmYgKyB5WW9mZiArIHhYb2ZmXVxuXHR2YXIgdjAwMCA9IGFycmF5W3kwb2ZmICsgejBvZmYgKyB4MG9mZl07XG5cdHZhciB2MDAxID0gYXJyYXlbeTBvZmYgKyB6MG9mZiArIHgxb2ZmXTtcblx0dmFyIHYwMTAgPSBhcnJheVt5MW9mZiArIHowb2ZmICsgeDBvZmZdO1xuXHR2YXIgdjAxMSA9IGFycmF5W3kxb2ZmICsgejBvZmYgKyB4MW9mZl07XG5cdHZhciB2MTAwID0gYXJyYXlbeTBvZmYgKyB6MW9mZiArIHgwb2ZmXTtcblx0dmFyIHYxMDEgPSBhcnJheVt5MG9mZiArIHoxb2ZmICsgeDFvZmZdO1xuXHR2YXIgdjExMCA9IGFycmF5W3kxb2ZmICsgejFvZmYgKyB4MG9mZl07XG5cdHZhciB2MTExID0gYXJyYXlbeTFvZmYgKyB6MW9mZiArIHgxb2ZmXTtcblxuXHR2YXIgcmVzdWx0ID0gdmVjMy5jcmVhdGUoKTtcblxuXHQvLyBBdmVyYWdlIHNhbXBsZXMgYWNjb3JkaW5nIHRvIGRpc3RhbmNlIHRvIHBvaW50LlxuXHR2ZWMzLmxlcnAocmVzdWx0LCB2MDAwLCB2MDAxLCB4Zik7XG5cdHZlYzMubGVycCh0bXAsIHYwMTAsIHYwMTEsIHhmKTtcblx0dmVjMy5sZXJwKHJlc3VsdCwgcmVzdWx0LCB0bXAsIHlmKTtcblx0dmVjMy5sZXJwKHRtcCwgdjEwMCwgdjEwMSwgeGYpO1xuXHR2ZWMzLmxlcnAodG1wMiwgdjExMCwgdjExMSwgeGYpO1xuXHR2ZWMzLmxlcnAodG1wLCB0bXAsIHRtcDIsIHlmKTtcblx0dmVjMy5sZXJwKHJlc3VsdCwgcmVzdWx0LCB0bXAsIHpmKTtcblxuXHRyZXR1cm4gcmVzdWx0O1xufTtcblxuXG52YXIgdmFicyA9IGZ1bmN0aW9uKGRzdCwgdikge1xuXHR2YXIgeCA9IHZbMF07XG5cdHZhciB5ID0gdlsxXTtcblx0dmFyIHogPSB2WzJdO1xuXHRkc3RbMF0gPSB4ID49IDAgPyB4IDogLXg7XG5cdGRzdFsxXSA9IHkgPj0gMCA/IHkgOiAteTtcblx0ZHN0WzJdID0geiA+PSAwID8geiA6IC16O1xuXHRyZXR1cm4gZHN0O1xufTtcblxudmFyIGZpbmRNaW5TZXBhcmF0aW9uID0gZnVuY3Rpb24oeHMpIHtcblx0dmFyIG1pblNlcGFyYXRpb24gPSAxLzA7XG5cdHhzLnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYSAtIGI7IH0pO1xuXHRmb3IgKHZhciBpPTE7IGk8eHMubGVuZ3RoOyBpKyspIHtcblx0XHR2YXIgZCA9IE1hdGguYWJzKHhzW2ldIC0geHNbaS0xXSk7XG5cdFx0aWYgKGQgPCBtaW5TZXBhcmF0aW9uKSB7XG5cdFx0XHRtaW5TZXBhcmF0aW9uID0gZDtcblx0XHR9XG5cdH1cblx0cmV0dXJuIG1pblNlcGFyYXRpb247XG59O1xuXG4vLyBGaW5kcyB0aGUgbWluaW11bSBwZXItY29tcG9uZW50IGRpc3RhbmNlIGluIHBvc2l0aW9ucy5cbi8vIFxudmFyIGNhbGN1bGF0ZU1pblBvc2l0aW9uRGlzdGFuY2UgPSBmdW5jdGlvbihwb3NpdGlvbnMpIHtcblx0dmFyIHhzID0gW10sIHlzID0gW10sIHpzID0gW107XG5cdHZhciB4aSA9IHt9LCB5aSA9IHt9LCB6aSA9IHt9O1xuXHRmb3IgKHZhciBpPTA7IGk8cG9zaXRpb25zLmxlbmd0aDsgaSsrKSB7XG5cdFx0dmFyIHAgPSBwb3NpdGlvbnNbaV07XG5cdFx0dmFyIHggPSBwWzBdLCB5ID0gcFsxXSwgeiA9IHBbMl07XG5cblx0XHQvLyBTcGxpdCB0aGUgcG9zaXRpb25zIGFycmF5IGludG8gYXJyYXlzIG9mIHVuaXF1ZSBjb21wb25lbnQgdmFsdWVzLlxuXHRcdC8vXG5cdFx0Ly8gV2h5IGdvIHRocm91Z2ggdGhlIHRyb3VibGUgb2YgdXNpbmcgYSB1bmlxdWVuZXNzIGhhc2ggdGFibGUgdnNcblx0XHQvLyBzb3J0IGFuZCB1bmlxOiBcblx0XHQvL1xuXHRcdC8vIFN1cHBvc2UgeW91J3ZlIGdvdCBhIG1pbGxpb24gcG9zaXRpb25zIGluIGEgMTAweDEwMHgxMDAgZ3JpZC5cblx0XHQvL1xuXHRcdC8vIFVzaW5nIGEgdW5pcXVlbmVzcyBoYXNoIHRhYmxlLCB5b3UncmUgZG9pbmcgMU0gYXJyYXkgcmVhZHMsIFxuXHRcdC8vIDNNIGhhc2ggdGFibGUgbG9va3VwcyBmcm9tIDEwMC1lbGVtZW50IGhhc2hlcywgMzAwIGhhc2ggdGFibGUgaW5zZXJ0cywgdGhlblxuXHRcdC8vIHNvcnRpbmcgdGhyZWUgMTAwLWVsZW1lbnQgYXJyYXlzIGFuZCBpdGVyYXRpbmcgb3ZlciB0aGVtLlxuXHRcdC8vIFJvdWdobHksIDFNICsgM00gKiBsbigxMDApICsgMzAwICogbG4oMTAwLzIpICsgMyAqIDEwMCAqIGxuKDEwMCkgKyAzICogMTAwID0gXG5cdFx0Ly8gICAgICAgICAgMU0gKyAxMy44TSArIDAuMDAxMk0gKyAgMC4wMDE0TSArIDAuMDAwM00gXG5cdFx0Ly8gICAgICAgICAgPX4gMTVNXG5cdFx0Ly9cblx0XHQvLyBTb3J0IGFuZCB1bmlxIHNvbHV0aW9uIHdvdWxkIGRvIDFNIGFycmF5IHJlYWRzLCAzTSBhcnJheSBpbnNlcnRzLFxuXHRcdC8vIHNvcnQgdGhyZWUgMU0tZWxlbWVudCBhcnJheXMgYW5kIGl0ZXJhdGUgb3ZlciB0aGVtLlxuXHRcdC8vIFJvdWdobHksIDFNICsgM00gKyAzICogMU0gKiBsbigxTSkgKyAzICogMU0gPSBcblx0XHQvLyAgICAgICAgICAxTSArIDNNICsgNDEuNE0gKyAzTSBcblx0XHQvLyAgICAgICAgICA9fiA0OC40TVxuXHRcdC8vXG5cdFx0Ly8gR3Vlc3NpbmcgdGhhdCBhIGhhcmQtY29kZWQgc29ydCAmIHVuaXEgd291bGQgYmUgZmFzdGVyIGR1ZSB0byBub3QgaGF2aW5nXG5cdFx0Ly8gdG8gcnVuIGEgaGFzaGluZyBmdW5jdGlvbiBvbiBldmVyeXRoaW5nLiBNb3JlIG1lbW9yeSB1c2FnZSB0aG91Z2ggXG5cdFx0Ly8gKGJ1bmNoIG9mIHNtYWxsIGhhc2ggdGFibGVzIHZzLiBkdXBsaWNhdGluZyB0aGUgaW5wdXQgYXJyYXkuKVxuXHRcdC8vXG5cdFx0Ly8gSW4gSlMtbGFuZCwgd2hvIGtub3dzLiBNYXliZSB4aVt4XSBjYXN0cyB4IHRvIHN0cmluZyBhbmQgZGVzdHJveXMgcGVyZiwgXG5cdFx0Ly8gbWF5YmUgbnVtZXJpYyBrZXlzIGdldCBzcGVjaWFsLWNhc2VkLCBtYXliZSB0aGUgb2JqZWN0IGxvb2t1cHMgcnVuIGF0IG5lYXIgTygxKS1zcGVlZHMuXG5cdFx0Ly8gTWF5YmUgdGhlIHNvcnRpbmcgY29tcGFyaXNvbiBmdW5jdGlvbiBpcyBleHBlbnNpdmUgdG8gY2FsbCwgbWF5YmUgaXQgZ2V0cyBpbmxpbmVkIG9yIHNwZWNpYWwtY2FzZWQuXG5cdFx0Ly9cblx0XHQvLyAuLi4gWW91J3JlIHByb2JhYmx5IG5vdCBnb2luZyB0byBjYWxsIHRoaXMgd2l0aCBtb3JlIHRoYW4gMTBrIHBvc2l0aW9ucyBhbnlob3csIHNvIHRoaXMgaXMgdmVyeSBhY2FkZW1pYy5cblx0XHQvL1xuXHRcdGlmICgheGlbeF0pIHtcblx0XHRcdHhzLnB1c2goeCk7XG5cdFx0XHR4aVt4XSA9IHRydWU7XG5cdFx0fVxuXHRcdGlmICgheWlbeV0pIHtcblx0XHRcdHlzLnB1c2goeSk7XG5cdFx0XHR5aVt5XSA9IHRydWU7XG5cdFx0fVxuXHRcdGlmICghemlbel0pIHtcblx0XHRcdHpzLnB1c2goeik7XG5cdFx0XHR6aVt6XSA9IHRydWU7XG5cdFx0fVxuXHR9XG5cdHZhciB4U2VwID0gZmluZE1pblNlcGFyYXRpb24oeHMpO1xuXHR2YXIgeVNlcCA9IGZpbmRNaW5TZXBhcmF0aW9uKHlzKTtcblx0dmFyIHpTZXAgPSBmaW5kTWluU2VwYXJhdGlvbih6cyk7XG5cdHZhciBtaW5TZXBhcmF0aW9uID0gTWF0aC5taW4oeFNlcCwgeVNlcCwgelNlcCk7XG5cdGlmICghaXNGaW5pdGUobWluU2VwYXJhdGlvbikpIHtcblx0XHRyZXR1cm4gMTtcblx0fVxuXHRyZXR1cm4gbWluU2VwYXJhdGlvbjtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24odmVjdG9yRmllbGQsIGJvdW5kcykge1xuXHR2YXIgcG9zaXRpb25zID0gdmVjdG9yRmllbGQuc3RhcnRpbmdQb3NpdGlvbnM7XG5cdHZhciBtYXhMZW5ndGggPSB2ZWN0b3JGaWVsZC5tYXhMZW5ndGggfHwgMTAwMDtcblx0dmFyIHR1YmVTaXplID0gdmVjdG9yRmllbGQudHViZVNpemUgfHwgMTtcblx0dmFyIGFic29sdXRlVHViZVNpemUgPSB2ZWN0b3JGaWVsZC5hYnNvbHV0ZVR1YmVTaXplO1xuXG5cdGlmICghdmVjdG9yRmllbGQuZ2V0RGl2ZXJnZW5jZSkge1xuXHRcdHZlY3RvckZpZWxkLmdldERpdmVyZ2VuY2UgPSBkZWZhdWx0R2V0RGl2ZXJnZW5jZTtcblx0fVxuXG5cdGlmICghdmVjdG9yRmllbGQuZ2V0VmVsb2NpdHkpIHtcblx0XHR2ZWN0b3JGaWVsZC5nZXRWZWxvY2l0eSA9IGRlZmF1bHRHZXRWZWxvY2l0eTtcblx0fVxuXG5cdGlmICh2ZWN0b3JGaWVsZC5jbGFtcEJvcmRlcnMgPT09IHVuZGVmaW5lZCkge1xuXHRcdHZlY3RvckZpZWxkLmNsYW1wQm9yZGVycyA9IHRydWU7XG5cdH1cblxuXHR2YXIgc3RyZWFtcyA9IFtdO1xuXG5cdHZhciBtaW5YID0gYm91bmRzWzBdWzBdLCBtaW5ZID0gYm91bmRzWzBdWzFdLCBtaW5aID0gYm91bmRzWzBdWzJdO1xuXHR2YXIgbWF4WCA9IGJvdW5kc1sxXVswXSwgbWF4WSA9IGJvdW5kc1sxXVsxXSwgbWF4WiA9IGJvdW5kc1sxXVsyXTtcblxuXHR2YXIgaW5Cb3VuZHMgPSBmdW5jdGlvbihib3VuZHMsIHApIHtcblx0XHR2YXIgeCA9IHBbMF07XG5cdFx0dmFyIHkgPSBwWzFdO1xuXHRcdHZhciB6ID0gcFsyXTtcblx0XHRyZXR1cm4gKFxuXHRcdFx0eCA+PSBtaW5YICYmIHggPD0gbWF4WCAmJlxuXHRcdFx0eSA+PSBtaW5ZICYmIHkgPD0gbWF4WSAmJlxuXHRcdFx0eiA+PSBtaW5aICYmIHogPD0gbWF4WlxuXHRcdCk7XG5cdH07XG5cblx0dmFyIGJvdW5kc1NpemUgPSB2ZWMzLmRpc3RhbmNlKGJvdW5kc1swXSwgYm91bmRzWzFdKTtcblx0dmFyIG1heFN0ZXBTaXplID0gMTAgKiBib3VuZHNTaXplIC8gbWF4TGVuZ3RoO1xuXHR2YXIgbWF4U3RlcFNpemVTcSA9IG1heFN0ZXBTaXplICogbWF4U3RlcFNpemU7XG5cblx0dmFyIG1pbkRpc3RhbmNlID0gMTtcblx0dmFyIG1heERpdmVyZ2VuY2UgPSAwOyAvLyBGb3IgY29tcG9uZW50LXdpc2UgZGl2ZXJnZW5jZSB2ZWMzLmNyZWF0ZSgpO1xuXHR2YXIgdG1wID0gdmVjMy5jcmVhdGUoKTtcblxuXHRpZiAocG9zaXRpb25zLmxlbmd0aCA+PSAyKSB7XG5cdFx0bWluRGlzdGFuY2UgPSBjYWxjdWxhdGVNaW5Qb3NpdGlvbkRpc3RhbmNlKHBvc2l0aW9ucyk7XG5cdH1cblxuXHRmb3IgKHZhciBpID0gMDsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7IGkrKykge1xuXHRcdHZhciBwID0gdmVjMy5jcmVhdGUoKTtcblx0XHR2ZWMzLmNvcHkocCwgcG9zaXRpb25zW2ldKTtcblxuXHRcdHZhciBzdHJlYW0gPSBbcF07XG5cdFx0dmFyIHZlbG9jaXRpZXMgPSBbXTtcblx0XHR2YXIgdiA9IHZlY3RvckZpZWxkLmdldFZlbG9jaXR5KHApO1xuXHRcdHZhciBvcCA9IHA7XG5cdFx0dmVsb2NpdGllcy5wdXNoKHYpO1xuXG5cdFx0dmFyIGRpdmVyZ2VuY2VzID0gW107XG5cblx0XHR2YXIgZHYgPSB2ZWN0b3JGaWVsZC5nZXREaXZlcmdlbmNlKHAsIHYpO1xuXHRcdHZhciBkdkxlbmd0aCA9IHZlYzMubGVuZ3RoKGR2KTtcblx0XHRpZiAoZHZMZW5ndGggPiBtYXhEaXZlcmdlbmNlICYmICFpc05hTihkdkxlbmd0aCkgJiYgaXNGaW5pdGUoZHZMZW5ndGgpKSB7XG5cdFx0XHRtYXhEaXZlcmdlbmNlID0gZHZMZW5ndGg7XG5cdFx0fVxuXHRcdC8vIEluIGNhc2Ugd2UgbmVlZCB0byBkbyBjb21wb25lbnQtd2lzZSBkaXZlcmdlbmNlIHZpc3VhbGl6YXRpb25cblx0XHQvLyB2ZWMzLm1heChtYXhEaXZlcmdlbmNlLCBtYXhEaXZlcmdlbmNlLCB2YWJzKHRtcCwgZHYpKTtcblx0XHRkaXZlcmdlbmNlcy5wdXNoKGR2TGVuZ3RoKTtcblxuXHRcdHN0cmVhbXMucHVzaCh7cG9pbnRzOiBzdHJlYW0sIHZlbG9jaXRpZXM6IHZlbG9jaXRpZXMsIGRpdmVyZ2VuY2VzOiBkaXZlcmdlbmNlc30pO1xuXG5cdFx0dmFyIGogPSAwO1xuXG5cdFx0d2hpbGUgKGogPCBtYXhMZW5ndGggKiAxMDAgJiYgc3RyZWFtLmxlbmd0aCA8IG1heExlbmd0aCAmJiBpbkJvdW5kcyhib3VuZHMsIHApKSB7XG5cdFx0XHRqKys7XG5cdFx0XHR2YXIgbnAgPSB2ZWMzLmNsb25lKHYpO1xuXHRcdFx0dmFyIHNxTGVuID0gdmVjMy5zcXVhcmVkTGVuZ3RoKG5wKTtcblx0XHRcdGlmIChzcUxlbiA9PT0gMCkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH0gZWxzZSBpZiAoc3FMZW4gPiBtYXhTdGVwU2l6ZVNxKSB7XG5cdFx0XHRcdHZlYzMuc2NhbGUobnAsIG5wLCBtYXhTdGVwU2l6ZSAvIE1hdGguc3FydChzcUxlbikpO1xuXHRcdFx0fVxuXHRcdFx0dmVjMy5hZGQobnAsIG5wLCBwKTtcblxuXHRcdFx0diA9IHZlY3RvckZpZWxkLmdldFZlbG9jaXR5KG5wKTtcblxuXHRcdFx0aWYgKHZlYzMuc3F1YXJlZERpc3RhbmNlKG9wLCBucCkgLSBtYXhTdGVwU2l6ZVNxID4gLTAuMDAwMSAqIG1heFN0ZXBTaXplU3EpIHtcblx0XHRcdFx0c3RyZWFtLnB1c2gobnApO1xuXHRcdFx0XHRvcCA9IG5wO1xuXHRcdFx0XHR2ZWxvY2l0aWVzLnB1c2godik7XG5cdFx0XHRcdHZhciBkdiA9IHZlY3RvckZpZWxkLmdldERpdmVyZ2VuY2UobnAsIHYpO1xuXHRcdFx0XHR2YXIgZHZMZW5ndGggPSB2ZWMzLmxlbmd0aChkdik7XG5cdFx0XHRcdGlmIChkdkxlbmd0aCA+IG1heERpdmVyZ2VuY2UgJiYgIWlzTmFOKGR2TGVuZ3RoKSAmJiBpc0Zpbml0ZShkdkxlbmd0aCkpIHtcblx0XHRcdFx0XHRtYXhEaXZlcmdlbmNlID0gZHZMZW5ndGg7XG5cdFx0XHRcdH1cblx0XHRcdFx0Ly8gSW4gY2FzZSB3ZSBuZWVkIHRvIGRvIGNvbXBvbmVudC13aXNlIGRpdmVyZ2VuY2UgdmlzdWFsaXphdGlvblxuXHRcdFx0XHQvL3ZlYzMubWF4KG1heERpdmVyZ2VuY2UsIG1heERpdmVyZ2VuY2UsIHZhYnModG1wLCBkdikpO1xuXHRcdFx0XHRkaXZlcmdlbmNlcy5wdXNoKGR2TGVuZ3RoKTtcblx0XHRcdH1cblxuXHRcdFx0cCA9IG5wO1xuXHRcdH1cblx0fVxuXG5cdC8vIFJlcGxhY2UgTmFOcyBhbmQgSW5maW5pdGllcyB3aXRoIG5vbi1OYU4sIGZpbml0ZSBtYXhEaXZlcmdlbmNlXG5cdGZvciAodmFyIGk9MDsgaTxkaXZlcmdlbmNlcy5sZW5ndGg7IGkrKykge1xuXHRcdHZhciBkdkxlbmd0aCA9IGRpdmVyZ2VuY2VzW2ldO1xuXHRcdGlmIChpc05hTihkdkxlbmd0aCkgfHwgIWlzRmluaXRlKGR2TGVuZ3RoKSkge1xuXHRcdFx0ZGl2ZXJnZW5jZXNbaV0gPSBtYXhEaXZlcmdlbmNlO1xuXHRcdH1cblx0fVxuXG5cdHZhciB0dWJlcyA9IGNyZWF0ZVR1YmVzKHN0cmVhbXMsIHZlY3RvckZpZWxkLmNvbG9ybWFwLCBtYXhEaXZlcmdlbmNlLCBtaW5EaXN0YW5jZSk7XG5cblx0aWYgKGFic29sdXRlVHViZVNpemUpIHtcblx0XHR0dWJlcy50dWJlU2NhbGUgPSBhYnNvbHV0ZVR1YmVTaXplO1xuXHR9IGVsc2Uge1xuXHRcdC8vIEF2b2lkIGRpdmlzaW9uIGJ5IHplcm8uXG5cdFx0aWYgKG1heERpdmVyZ2VuY2UgPT09IDApIHtcblx0XHRcdG1heERpdmVyZ2VuY2UgPSAxO1xuXHRcdH1cblx0XHR0dWJlcy50dWJlU2NhbGUgPSB0dWJlU2l6ZSAqIDAuNSAqIG1pbkRpc3RhbmNlIC8gbWF4RGl2ZXJnZW5jZTtcblx0fVxuXG5cdHJldHVybiB0dWJlcztcbn07XG5cbm1vZHVsZS5leHBvcnRzLmNyZWF0ZVR1YmVNZXNoID0gX2RlcmVxXygnLi9saWIvdHViZW1lc2gnKTtcblxufSx7XCIuL2xpYi90dWJlbWVzaFwiOjMxMixcImdsLXZlYzNcIjozNDYsXCJnbC12ZWM0XCI6MzgyfV0sMzE0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciBjcmVhdGVTaGFkZXIgPSBfZGVyZXFfKCdnbC1zaGFkZXInKVxudmFyIGdsc2xpZnkgPSBfZGVyZXFfKCdnbHNsaWZ5JylcblxudmFyIHZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWM0IHV2O1xcbmF0dHJpYnV0ZSB2ZWMzIGY7XFxuYXR0cmlidXRlIHZlYzMgbm9ybWFsO1xcblxcbnVuaWZvcm0gdmVjMyBvYmplY3RPZmZzZXQ7XFxudW5pZm9ybSBtYXQ0IG1vZGVsLCB2aWV3LCBwcm9qZWN0aW9uLCBpbnZlcnNlTW9kZWw7XFxudW5pZm9ybSB2ZWMzIGxpZ2h0UG9zaXRpb24sIGV5ZVBvc2l0aW9uO1xcbnVuaWZvcm0gc2FtcGxlcjJEIGNvbG9ybWFwO1xcblxcbnZhcnlpbmcgZmxvYXQgdmFsdWUsIGtpbGw7XFxudmFyeWluZyB2ZWMzIHdvcmxkQ29vcmRpbmF0ZTtcXG52YXJ5aW5nIHZlYzIgcGxhbmVDb29yZGluYXRlO1xcbnZhcnlpbmcgdmVjMyBsaWdodERpcmVjdGlvbiwgZXllRGlyZWN0aW9uLCBzdXJmYWNlTm9ybWFsO1xcbnZhcnlpbmcgdmVjNCB2Q29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgdmVjMyBsb2NhbENvb3JkaW5hdGUgPSB2ZWMzKHV2Lnp3LCBmLngpO1xcbiAgd29ybGRDb29yZGluYXRlID0gb2JqZWN0T2Zmc2V0ICsgbG9jYWxDb29yZGluYXRlO1xcbiAgdmVjNCB3b3JsZFBvc2l0aW9uID0gbW9kZWwgKiB2ZWM0KHdvcmxkQ29vcmRpbmF0ZSwgMS4wKTtcXG4gIHZlYzQgY2xpcFBvc2l0aW9uID0gcHJvamVjdGlvbiAqIHZpZXcgKiB3b3JsZFBvc2l0aW9uO1xcbiAgZ2xfUG9zaXRpb24gPSBjbGlwUG9zaXRpb247XFxuICBraWxsID0gZi55O1xcbiAgdmFsdWUgPSBmLno7XFxuICBwbGFuZUNvb3JkaW5hdGUgPSB1di54eTtcXG5cXG4gIHZDb2xvciA9IHRleHR1cmUyRChjb2xvcm1hcCwgdmVjMih2YWx1ZSwgdmFsdWUpKTtcXG5cXG4gIC8vTGlnaHRpbmcgZ2VvbWV0cnkgcGFyYW1ldGVyc1xcbiAgdmVjNCBjYW1lcmFDb29yZGluYXRlID0gdmlldyAqIHdvcmxkUG9zaXRpb247XFxuICBjYW1lcmFDb29yZGluYXRlLnh5eiAvPSBjYW1lcmFDb29yZGluYXRlLnc7XFxuICBsaWdodERpcmVjdGlvbiA9IGxpZ2h0UG9zaXRpb24gLSBjYW1lcmFDb29yZGluYXRlLnh5ejtcXG4gIGV5ZURpcmVjdGlvbiAgID0gZXllUG9zaXRpb24gLSBjYW1lcmFDb29yZGluYXRlLnh5ejtcXG4gIHN1cmZhY2VOb3JtYWwgID0gbm9ybWFsaXplKCh2ZWM0KG5vcm1hbCwwKSAqIGludmVyc2VNb2RlbCkueHl6KTtcXG59XFxuXCJdKVxudmFyIGZyYWdTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmZsb2F0IGJlY2ttYW5uRGlzdHJpYnV0aW9uKGZsb2F0IHgsIGZsb2F0IHJvdWdobmVzcykge1xcbiAgZmxvYXQgTmRvdEggPSBtYXgoeCwgMC4wMDAxKTtcXG4gIGZsb2F0IGNvczJBbHBoYSA9IE5kb3RIICogTmRvdEg7XFxuICBmbG9hdCB0YW4yQWxwaGEgPSAoY29zMkFscGhhIC0gMS4wKSAvIGNvczJBbHBoYTtcXG4gIGZsb2F0IHJvdWdobmVzczIgPSByb3VnaG5lc3MgKiByb3VnaG5lc3M7XFxuICBmbG9hdCBkZW5vbSA9IDMuMTQxNTkyNjUzNTg5NzkzICogcm91Z2huZXNzMiAqIGNvczJBbHBoYSAqIGNvczJBbHBoYTtcXG4gIHJldHVybiBleHAodGFuMkFscGhhIC8gcm91Z2huZXNzMikgLyBkZW5vbTtcXG59XFxuXFxuZmxvYXQgYmVja21hbm5TcGVjdWxhcihcXG4gIHZlYzMgbGlnaHREaXJlY3Rpb24sXFxuICB2ZWMzIHZpZXdEaXJlY3Rpb24sXFxuICB2ZWMzIHN1cmZhY2VOb3JtYWwsXFxuICBmbG9hdCByb3VnaG5lc3MpIHtcXG4gIHJldHVybiBiZWNrbWFubkRpc3RyaWJ1dGlvbihkb3Qoc3VyZmFjZU5vcm1hbCwgbm9ybWFsaXplKGxpZ2h0RGlyZWN0aW9uICsgdmlld0RpcmVjdGlvbikpLCByb3VnaG5lc3MpO1xcbn1cXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG51bmlmb3JtIHZlYzMgbG93ZXJCb3VuZCwgdXBwZXJCb3VuZDtcXG51bmlmb3JtIGZsb2F0IGNvbnRvdXJUaW50O1xcbnVuaWZvcm0gdmVjNCBjb250b3VyQ29sb3I7XFxudW5pZm9ybSBzYW1wbGVyMkQgY29sb3JtYXA7XFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxudW5pZm9ybSBmbG9hdCByb3VnaG5lc3MsIGZyZXNuZWwsIGthbWJpZW50LCBrZGlmZnVzZSwga3NwZWN1bGFyLCBvcGFjaXR5O1xcbnVuaWZvcm0gZmxvYXQgdmVydGV4Q29sb3I7XFxuXFxudmFyeWluZyBmbG9hdCB2YWx1ZSwga2lsbDtcXG52YXJ5aW5nIHZlYzMgd29ybGRDb29yZGluYXRlO1xcbnZhcnlpbmcgdmVjMyBsaWdodERpcmVjdGlvbiwgZXllRGlyZWN0aW9uLCBzdXJmYWNlTm9ybWFsO1xcbnZhcnlpbmcgdmVjNCB2Q29sb3I7XFxuXFxudm9pZCBtYWluKCkge1xcbiAgaWYgKChraWxsID4gMC4wKSB8fFxcbiAgICAgIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIHdvcmxkQ29vcmRpbmF0ZSkpKSBkaXNjYXJkO1xcblxcbiAgdmVjMyBOID0gbm9ybWFsaXplKHN1cmZhY2VOb3JtYWwpO1xcbiAgdmVjMyBWID0gbm9ybWFsaXplKGV5ZURpcmVjdGlvbik7XFxuICB2ZWMzIEwgPSBub3JtYWxpemUobGlnaHREaXJlY3Rpb24pO1xcblxcbiAgaWYoZ2xfRnJvbnRGYWNpbmcpIHtcXG4gICAgTiA9IC1OO1xcbiAgfVxcblxcbiAgZmxvYXQgc3BlY3VsYXIgPSBtYXgoYmVja21hbm5TcGVjdWxhcihMLCBWLCBOLCByb3VnaG5lc3MpLCAwLik7XFxuICBmbG9hdCBkaWZmdXNlICA9IG1pbihrYW1iaWVudCArIGtkaWZmdXNlICogbWF4KGRvdChOLCBMKSwgMC4wKSwgMS4wKTtcXG5cXG4gIC8vZGVjaWRlIGhvdyB0byBpbnRlcnBvbGF0ZSBjb2xvciDigJQgaW4gdmVydGV4IG9yIGluIGZyYWdtZW50XFxuICB2ZWM0IHN1cmZhY2VDb2xvciA9XFxuICAgIHN0ZXAodmVydGV4Q29sb3IsIC41KSAqIHRleHR1cmUyRChjb2xvcm1hcCwgdmVjMih2YWx1ZSwgdmFsdWUpKSArXFxuICAgIHN0ZXAoLjUsIHZlcnRleENvbG9yKSAqIHZDb2xvcjtcXG5cXG4gIHZlYzQgbGl0Q29sb3IgPSBzdXJmYWNlQ29sb3IuYSAqIHZlYzQoZGlmZnVzZSAqIHN1cmZhY2VDb2xvci5yZ2IgKyBrc3BlY3VsYXIgKiB2ZWMzKDEsMSwxKSAqIHNwZWN1bGFyLCAgMS4wKTtcXG5cXG4gIGdsX0ZyYWdDb2xvciA9IG1peChsaXRDb2xvciwgY29udG91ckNvbG9yLCBjb250b3VyVGludCkgKiBvcGFjaXR5O1xcbn1cXG5cIl0pXG52YXIgY29udG91clZlcnRTcmMgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWM0IHV2O1xcbmF0dHJpYnV0ZSBmbG9hdCBmO1xcblxcbnVuaWZvcm0gdmVjMyBvYmplY3RPZmZzZXQ7XFxudW5pZm9ybSBtYXQzIHBlcm11dGF0aW9uO1xcbnVuaWZvcm0gbWF0NCBtb2RlbCwgdmlldywgcHJvamVjdGlvbjtcXG51bmlmb3JtIGZsb2F0IGhlaWdodCwgek9mZnNldDtcXG51bmlmb3JtIHNhbXBsZXIyRCBjb2xvcm1hcDtcXG5cXG52YXJ5aW5nIGZsb2F0IHZhbHVlLCBraWxsO1xcbnZhcnlpbmcgdmVjMyB3b3JsZENvb3JkaW5hdGU7XFxudmFyeWluZyB2ZWMyIHBsYW5lQ29vcmRpbmF0ZTtcXG52YXJ5aW5nIHZlYzMgbGlnaHREaXJlY3Rpb24sIGV5ZURpcmVjdGlvbiwgc3VyZmFjZU5vcm1hbDtcXG52YXJ5aW5nIHZlYzQgdkNvbG9yO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gIHZlYzMgZGF0YUNvb3JkaW5hdGUgPSBwZXJtdXRhdGlvbiAqIHZlYzModXYueHksIGhlaWdodCk7XFxuICB3b3JsZENvb3JkaW5hdGUgPSBvYmplY3RPZmZzZXQgKyBkYXRhQ29vcmRpbmF0ZTtcXG4gIHZlYzQgd29ybGRQb3NpdGlvbiA9IG1vZGVsICogdmVjNCh3b3JsZENvb3JkaW5hdGUsIDEuMCk7XFxuXFxuICB2ZWM0IGNsaXBQb3NpdGlvbiA9IHByb2plY3Rpb24gKiB2aWV3ICogd29ybGRQb3NpdGlvbjtcXG4gIGNsaXBQb3NpdGlvbi56ICs9IHpPZmZzZXQ7XFxuXFxuICBnbF9Qb3NpdGlvbiA9IGNsaXBQb3NpdGlvbjtcXG4gIHZhbHVlID0gZiArIG9iamVjdE9mZnNldC56O1xcbiAga2lsbCA9IC0xLjA7XFxuICBwbGFuZUNvb3JkaW5hdGUgPSB1di56dztcXG5cXG4gIHZDb2xvciA9IHRleHR1cmUyRChjb2xvcm1hcCwgdmVjMih2YWx1ZSwgdmFsdWUpKTtcXG5cXG4gIC8vRG9uJ3QgZG8gbGlnaHRpbmcgZm9yIGNvbnRvdXJzXFxuICBzdXJmYWNlTm9ybWFsICAgPSB2ZWMzKDEsMCwwKTtcXG4gIGV5ZURpcmVjdGlvbiAgICA9IHZlYzMoMCwxLDApO1xcbiAgbGlnaHREaXJlY3Rpb24gID0gdmVjMygwLDAsMSk7XFxufVxcblwiXSlcbnZhciBwaWNrU3JjID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5ib29sIG91dE9mUmFuZ2UoZmxvYXQgYSwgZmxvYXQgYiwgZmxvYXQgcCkge1xcbiAgcmV0dXJuICgocCA+IG1heChhLCBiKSkgfHwgXFxuICAgICAgICAgIChwIDwgbWluKGEsIGIpKSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMyIGEsIHZlYzIgYiwgdmVjMiBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSk7XFxufVxcblxcbmJvb2wgb3V0T2ZSYW5nZSh2ZWMzIGEsIHZlYzMgYiwgdmVjMyBwKSB7XFxuICByZXR1cm4gKG91dE9mUmFuZ2UoYS54LCBiLngsIHAueCkgfHxcXG4gICAgICAgICAgb3V0T2ZSYW5nZShhLnksIGIueSwgcC55KSB8fFxcbiAgICAgICAgICBvdXRPZlJhbmdlKGEueiwgYi56LCBwLnopKTtcXG59XFxuXFxuYm9vbCBvdXRPZlJhbmdlKHZlYzQgYSwgdmVjNCBiLCB2ZWM0IHApIHtcXG4gIHJldHVybiBvdXRPZlJhbmdlKGEueHl6LCBiLnh5eiwgcC54eXopO1xcbn1cXG5cXG51bmlmb3JtIHZlYzIgc2hhcGU7XFxudW5pZm9ybSB2ZWMzIGNsaXBCb3VuZHNbMl07XFxudW5pZm9ybSBmbG9hdCBwaWNrSWQ7XFxuXFxudmFyeWluZyBmbG9hdCB2YWx1ZSwga2lsbDtcXG52YXJ5aW5nIHZlYzMgd29ybGRDb29yZGluYXRlO1xcbnZhcnlpbmcgdmVjMiBwbGFuZUNvb3JkaW5hdGU7XFxudmFyeWluZyB2ZWMzIHN1cmZhY2VOb3JtYWw7XFxuXFxudmVjMiBzcGxpdEZsb2F0KGZsb2F0IHYpIHtcXG4gIGZsb2F0IHZoID0gMjU1LjAgKiB2O1xcbiAgZmxvYXQgdXBwZXIgPSBmbG9vcih2aCk7XFxuICBmbG9hdCBsb3dlciA9IGZyYWN0KHZoKTtcXG4gIHJldHVybiB2ZWMyKHVwcGVyIC8gMjU1LjAsIGZsb29yKGxvd2VyICogMTYuMCkgLyAxNi4wKTtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcbiAgaWYgKChraWxsID4gMC4wKSB8fFxcbiAgICAgIChvdXRPZlJhbmdlKGNsaXBCb3VuZHNbMF0sIGNsaXBCb3VuZHNbMV0sIHdvcmxkQ29vcmRpbmF0ZSkpKSBkaXNjYXJkO1xcblxcbiAgdmVjMiB1eCA9IHNwbGl0RmxvYXQocGxhbmVDb29yZGluYXRlLnggLyBzaGFwZS54KTtcXG4gIHZlYzIgdXkgPSBzcGxpdEZsb2F0KHBsYW5lQ29vcmRpbmF0ZS55IC8gc2hhcGUueSk7XFxuICBnbF9GcmFnQ29sb3IgPSB2ZWM0KHBpY2tJZCwgdXgueCwgdXkueCwgdXgueSArICh1eS55LzE2LjApKTtcXG59XFxuXCJdKVxuXG5leHBvcnRzLmNyZWF0ZVNoYWRlciA9IGZ1bmN0aW9uIChnbCkge1xuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCB2ZXJ0U3JjLCBmcmFnU3JjLCBudWxsLCBbXG4gICAge25hbWU6ICd1dicsIHR5cGU6ICd2ZWM0J30sXG4gICAge25hbWU6ICdmJywgdHlwZTogJ3ZlYzMnfSxcbiAgICB7bmFtZTogJ25vcm1hbCcsIHR5cGU6ICd2ZWMzJ31cbiAgXSlcbiAgc2hhZGVyLmF0dHJpYnV0ZXMudXYubG9jYXRpb24gPSAwXG4gIHNoYWRlci5hdHRyaWJ1dGVzLmYubG9jYXRpb24gPSAxXG4gIHNoYWRlci5hdHRyaWJ1dGVzLm5vcm1hbC5sb2NhdGlvbiA9IDJcbiAgcmV0dXJuIHNoYWRlclxufVxuZXhwb3J0cy5jcmVhdGVQaWNrU2hhZGVyID0gZnVuY3Rpb24gKGdsKSB7XG4gIHZhciBzaGFkZXIgPSBjcmVhdGVTaGFkZXIoZ2wsIHZlcnRTcmMsIHBpY2tTcmMsIG51bGwsIFtcbiAgICB7bmFtZTogJ3V2JywgdHlwZTogJ3ZlYzQnfSxcbiAgICB7bmFtZTogJ2YnLCB0eXBlOiAndmVjMyd9LFxuICAgIHtuYW1lOiAnbm9ybWFsJywgdHlwZTogJ3ZlYzMnfVxuICBdKVxuICBzaGFkZXIuYXR0cmlidXRlcy51di5sb2NhdGlvbiA9IDBcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuZi5sb2NhdGlvbiA9IDFcbiAgc2hhZGVyLmF0dHJpYnV0ZXMubm9ybWFsLmxvY2F0aW9uID0gMlxuICByZXR1cm4gc2hhZGVyXG59XG5leHBvcnRzLmNyZWF0ZUNvbnRvdXJTaGFkZXIgPSBmdW5jdGlvbiAoZ2wpIHtcbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbCwgY29udG91clZlcnRTcmMsIGZyYWdTcmMsIG51bGwsIFtcbiAgICB7bmFtZTogJ3V2JywgdHlwZTogJ3ZlYzQnfSxcbiAgICB7bmFtZTogJ2YnLCB0eXBlOiAnZmxvYXQnfVxuICBdKVxuICBzaGFkZXIuYXR0cmlidXRlcy51di5sb2NhdGlvbiA9IDBcbiAgc2hhZGVyLmF0dHJpYnV0ZXMuZi5sb2NhdGlvbiA9IDFcbiAgcmV0dXJuIHNoYWRlclxufVxuZXhwb3J0cy5jcmVhdGVQaWNrQ29udG91clNoYWRlciA9IGZ1bmN0aW9uIChnbCkge1xuICB2YXIgc2hhZGVyID0gY3JlYXRlU2hhZGVyKGdsLCBjb250b3VyVmVydFNyYywgcGlja1NyYywgbnVsbCwgW1xuICAgIHtuYW1lOiAndXYnLCB0eXBlOiAndmVjNCd9LFxuICAgIHtuYW1lOiAnZicsIHR5cGU6ICdmbG9hdCd9XG4gIF0pXG4gIHNoYWRlci5hdHRyaWJ1dGVzLnV2LmxvY2F0aW9uID0gMFxuICBzaGFkZXIuYXR0cmlidXRlcy5mLmxvY2F0aW9uID0gMVxuICByZXR1cm4gc2hhZGVyXG59XG5cbn0se1wiZ2wtc2hhZGVyXCI6MzAxLFwiZ2xzbGlmeVwiOjQwOX1dLDMxNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5hcmd1bWVudHNbNF1bMTExXVswXS5hcHBseShleHBvcnRzLGFyZ3VtZW50cylcbn0se1wiZHVwXCI6MTExfV0sMzE2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVN1cmZhY2VQbG90XG5cbnZhciBiaXRzID0gX2RlcmVxXygnYml0LXR3aWRkbGUnKVxudmFyIGNyZWF0ZUJ1ZmZlciA9IF9kZXJlcV8oJ2dsLWJ1ZmZlcicpXG52YXIgY3JlYXRlVkFPID0gX2RlcmVxXygnZ2wtdmFvJylcbnZhciBjcmVhdGVUZXh0dXJlID0gX2RlcmVxXygnZ2wtdGV4dHVyZTJkJylcbnZhciBwb29sID0gX2RlcmVxXygndHlwZWRhcnJheS1wb29sJylcbnZhciBjb2xvcm1hcCA9IF9kZXJlcV8oJ2NvbG9ybWFwJylcbnZhciBvcHMgPSBfZGVyZXFfKCduZGFycmF5LW9wcycpXG52YXIgcGFjayA9IF9kZXJlcV8oJ25kYXJyYXktcGFjaycpXG52YXIgbmRhcnJheSA9IF9kZXJlcV8oJ25kYXJyYXknKVxudmFyIHN1cmZhY2VOZXRzID0gX2RlcmVxXygnc3VyZmFjZS1uZXRzJylcbnZhciBtdWx0aXBseSA9IF9kZXJlcV8oJ2dsLW1hdDQvbXVsdGlwbHknKVxudmFyIGludmVydCA9IF9kZXJlcV8oJ2dsLW1hdDQvaW52ZXJ0JylcbnZhciBic2VhcmNoID0gX2RlcmVxXygnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxudmFyIGdyYWRpZW50ID0gX2RlcmVxXygnbmRhcnJheS1ncmFkaWVudCcpXG52YXIgc2hhZGVycyA9IF9kZXJlcV8oJy4vbGliL3NoYWRlcnMnKVxuXG52YXIgY3JlYXRlU2hhZGVyID0gc2hhZGVycy5jcmVhdGVTaGFkZXJcbnZhciBjcmVhdGVDb250b3VyU2hhZGVyID0gc2hhZGVycy5jcmVhdGVDb250b3VyU2hhZGVyXG52YXIgY3JlYXRlUGlja1NoYWRlciA9IHNoYWRlcnMuY3JlYXRlUGlja1NoYWRlclxudmFyIGNyZWF0ZVBpY2tDb250b3VyU2hhZGVyID0gc2hhZGVycy5jcmVhdGVQaWNrQ29udG91clNoYWRlclxuXG52YXIgU1VSRkFDRV9WRVJURVhfU0laRSA9IDQgKiAoNCArIDMgKyAzKVxuXG52YXIgSURFTlRJVFkgPSBbXG4gIDEsIDAsIDAsIDAsXG4gIDAsIDEsIDAsIDAsXG4gIDAsIDAsIDEsIDAsXG4gIDAsIDAsIDAsIDEgXVxuXG52YXIgUVVBRCA9IFtcbiAgWzAsIDBdLFxuICBbMCwgMV0sXG4gIFsxLCAwXSxcbiAgWzEsIDFdLFxuICBbMSwgMF0sXG4gIFswLCAxXVxuXVxuXG52YXIgUEVSTVVUQVRJT05TID0gW1xuICBbMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF0sXG4gIFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwXSxcbiAgWzAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDBdXG5dXG5cbjsoZnVuY3Rpb24gKCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgIHZhciBwID0gUEVSTVVUQVRJT05TW2ldXG4gICAgdmFyIHUgPSAoaSArIDEpICUgM1xuICAgIHZhciB2ID0gKGkgKyAyKSAlIDNcbiAgICBwW3UgKyAwXSA9IDFcbiAgICBwW3YgKyAzXSA9IDFcbiAgICBwW2kgKyA2XSA9IDFcbiAgfVxufSkoKVxuXG5mdW5jdGlvbiBTdXJmYWNlUGlja1Jlc3VsdCAocG9zaXRpb24sIGluZGV4LCB1diwgbGV2ZWwsIGRhdGFDb29yZGluYXRlKSB7XG4gIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvblxuICB0aGlzLmluZGV4ID0gaW5kZXhcbiAgdGhpcy51diA9IHV2XG4gIHRoaXMubGV2ZWwgPSBsZXZlbFxuICB0aGlzLmRhdGFDb29yZGluYXRlID0gZGF0YUNvb3JkaW5hdGVcbn1cblxudmFyIE5fQ09MT1JTID0gMjU2XG5cbmZ1bmN0aW9uIGdlbkNvbG9ybWFwIChuYW1lKSB7XG4gIHZhciB4ID0gcGFjayhbY29sb3JtYXAoe1xuICAgIGNvbG9ybWFwOiBuYW1lLFxuICAgIG5zaGFkZXM6IE5fQ09MT1JTLFxuICAgIGZvcm1hdDogJ3JnYmEnXG4gIH0pLm1hcChmdW5jdGlvbiAoYykge1xuICAgIHJldHVybiBbY1swXSwgY1sxXSwgY1syXSwgMjU1ICogY1szXV1cbiAgfSldKVxuICBvcHMuZGl2c2VxKHgsIDI1NS4wKVxuICByZXR1cm4geFxufVxuXG5mdW5jdGlvbiBTdXJmYWNlUGxvdCAoXG4gIGdsLFxuICBzaGFwZSxcbiAgYm91bmRzLFxuICBzaGFkZXIsXG4gIHBpY2tTaGFkZXIsXG4gIGNvb3JkaW5hdGVzLFxuICB2YW8sXG4gIGNvbG9yTWFwLFxuICBjb250b3VyU2hhZGVyLFxuICBjb250b3VyUGlja1NoYWRlcixcbiAgY29udG91ckJ1ZmZlcixcbiAgY29udG91clZBTyxcbiAgZHluYW1pY0J1ZmZlcixcbiAgZHluYW1pY1ZBTyxcbiAgb2JqZWN0T2Zmc2V0KSB7XG4gIHRoaXMuZ2wgPSBnbFxuICB0aGlzLnNoYXBlID0gc2hhcGVcbiAgdGhpcy5ib3VuZHMgPSBib3VuZHNcbiAgdGhpcy5vYmplY3RPZmZzZXQgPSBvYmplY3RPZmZzZXRcbiAgdGhpcy5pbnRlbnNpdHlCb3VuZHMgPSBbXVxuXG4gIHRoaXMuX3NoYWRlciA9IHNoYWRlclxuICB0aGlzLl9waWNrU2hhZGVyID0gcGlja1NoYWRlclxuICB0aGlzLl9jb29yZGluYXRlQnVmZmVyID0gY29vcmRpbmF0ZXNcbiAgdGhpcy5fdmFvID0gdmFvXG4gIHRoaXMuX2NvbG9yTWFwID0gY29sb3JNYXBcblxuICB0aGlzLl9jb250b3VyU2hhZGVyID0gY29udG91clNoYWRlclxuICB0aGlzLl9jb250b3VyUGlja1NoYWRlciA9IGNvbnRvdXJQaWNrU2hhZGVyXG4gIHRoaXMuX2NvbnRvdXJCdWZmZXIgPSBjb250b3VyQnVmZmVyXG4gIHRoaXMuX2NvbnRvdXJWQU8gPSBjb250b3VyVkFPXG4gIHRoaXMuX2NvbnRvdXJPZmZzZXRzID0gW1tdLCBbXSwgW11dXG4gIHRoaXMuX2NvbnRvdXJDb3VudHMgPSBbW10sIFtdLCBbXV1cbiAgdGhpcy5fdmVydGV4Q291bnQgPSAwXG5cbiAgdGhpcy5fcGlja1Jlc3VsdCA9IG5ldyBTdXJmYWNlUGlja1Jlc3VsdChbMCwgMCwgMF0sIFswLCAwXSwgWzAsIDBdLCBbMCwgMCwgMF0sIFswLCAwLCAwXSlcblxuICB0aGlzLl9keW5hbWljQnVmZmVyID0gZHluYW1pY0J1ZmZlclxuICB0aGlzLl9keW5hbWljVkFPID0gZHluYW1pY1ZBT1xuICB0aGlzLl9keW5hbWljT2Zmc2V0cyA9IFswLCAwLCAwXVxuICB0aGlzLl9keW5hbWljQ291bnRzID0gWzAsIDAsIDBdXG5cbiAgdGhpcy5jb250b3VyV2lkdGggPSBbIDEsIDEsIDEgXVxuICB0aGlzLmNvbnRvdXJMZXZlbHMgPSBbWzFdLCBbMV0sIFsxXV1cbiAgdGhpcy5jb250b3VyVGludCA9IFswLCAwLCAwXVxuICB0aGlzLmNvbnRvdXJDb2xvciA9IFtbMC41LCAwLjUsIDAuNSwgMV0sIFswLjUsIDAuNSwgMC41LCAxXSwgWzAuNSwgMC41LCAwLjUsIDFdXVxuXG4gIHRoaXMuc2hvd0NvbnRvdXIgPSB0cnVlXG4gIHRoaXMuc2hvd1N1cmZhY2UgPSB0cnVlXG5cbiAgdGhpcy5lbmFibGVIaWdobGlnaHQgPSBbdHJ1ZSwgdHJ1ZSwgdHJ1ZV1cbiAgdGhpcy5oaWdobGlnaHRDb2xvciA9IFtbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdXVxuICB0aGlzLmhpZ2hsaWdodFRpbnQgPSBbIDEsIDEsIDEgXVxuICB0aGlzLmhpZ2hsaWdodExldmVsID0gWy0xLCAtMSwgLTFdXG5cbiAgLy8gRHluYW1pYyBjb250b3VyIG9wdGlvbnNcbiAgdGhpcy5lbmFibGVEeW5hbWljID0gWyB0cnVlLCB0cnVlLCB0cnVlIF1cbiAgdGhpcy5keW5hbWljTGV2ZWwgPSBbIE5hTiwgTmFOLCBOYU4gXVxuICB0aGlzLmR5bmFtaWNDb2xvciA9IFsgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXSBdXG4gIHRoaXMuZHluYW1pY1RpbnQgPSBbIDEsIDEsIDEgXVxuICB0aGlzLmR5bmFtaWNXaWR0aCA9IFsgMSwgMSwgMSBdXG5cbiAgdGhpcy5heGVzQm91bmRzID0gW1tJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XSwgWy1JbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldXVxuICB0aGlzLnN1cmZhY2VQcm9qZWN0ID0gWyBmYWxzZSwgZmFsc2UsIGZhbHNlIF1cbiAgdGhpcy5jb250b3VyUHJvamVjdCA9IFtbIGZhbHNlLCBmYWxzZSwgZmFsc2UgXSxcbiAgICBbIGZhbHNlLCBmYWxzZSwgZmFsc2UgXSxcbiAgICBbIGZhbHNlLCBmYWxzZSwgZmFsc2UgXV1cblxuICB0aGlzLmNvbG9yQm91bmRzID0gWyBmYWxzZSwgZmFsc2UgXVxuXG4gIC8vIFN0b3JlIHh5eiBmaWVsZHMsIG5lZWQgdGhpcyBmb3IgcGlja2luZ1xuICB0aGlzLl9maWVsZCA9IFtcbiAgICBuZGFycmF5KHBvb2wubWFsbG9jRmxvYXQoMTAyNCksIFswLCAwXSksXG4gICAgbmRhcnJheShwb29sLm1hbGxvY0Zsb2F0KDEwMjQpLCBbMCwgMF0pLFxuICAgIG5kYXJyYXkocG9vbC5tYWxsb2NGbG9hdCgxMDI0KSwgWzAsIDBdKSBdXG5cbiAgdGhpcy5waWNrSWQgPSAxXG4gIHRoaXMuY2xpcEJvdW5kcyA9IFtbLUluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV0sIFtJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XV1cblxuICB0aGlzLnNuYXBUb0RhdGEgPSBmYWxzZVxuXG4gIHRoaXMucGl4ZWxSYXRpbyA9IDFcblxuICB0aGlzLm9wYWNpdHkgPSAxLjBcblxuICB0aGlzLmxpZ2h0UG9zaXRpb24gPSBbMTAsIDEwMDAwLCAwXVxuICB0aGlzLmFtYmllbnRMaWdodCA9IDAuOFxuICB0aGlzLmRpZmZ1c2VMaWdodCA9IDAuOFxuICB0aGlzLnNwZWN1bGFyTGlnaHQgPSAyLjBcbiAgdGhpcy5yb3VnaG5lc3MgPSAwLjVcbiAgdGhpcy5mcmVzbmVsID0gMS41XG4gIHRoaXMudmVydGV4Q29sb3IgPSAwXG5cbiAgdGhpcy5kaXJ0eSA9IHRydWVcbn1cblxudmFyIHByb3RvID0gU3VyZmFjZVBsb3QucHJvdG90eXBlXG5cbnByb3RvLmlzVHJhbnNwYXJlbnQgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLm9wYWNpdHkgPCAxXG59XG5cbnByb3RvLmlzT3BhcXVlID0gZnVuY3Rpb24gKCkge1xuICBpZiAodGhpcy5vcGFjaXR5ID49IDEpIHtcbiAgICByZXR1cm4gdHJ1ZVxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgaWYgKHRoaXMuX2NvbnRvdXJDb3VudHNbaV0ubGVuZ3RoID4gMCB8fCB0aGlzLl9keW5hbWljQ291bnRzW2ldID4gMCkge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlXG59XG5cbnByb3RvLnBpY2tTbG90cyA9IDFcblxucHJvdG8uc2V0UGlja0Jhc2UgPSBmdW5jdGlvbiAoaWQpIHtcbiAgdGhpcy5waWNrSWQgPSBpZFxufVxuXG52YXIgWkVST19WRUMgPSBbMCwgMCwgMF1cblxudmFyIFBST0pFQ1RfREFUQSA9IHtcbiAgc2hvd1N1cmZhY2U6IGZhbHNlLFxuICBzaG93Q29udG91cjogZmFsc2UsXG4gIHByb2plY3Rpb25zOiBbSURFTlRJVFkuc2xpY2UoKSwgSURFTlRJVFkuc2xpY2UoKSwgSURFTlRJVFkuc2xpY2UoKV0sXG4gIGNsaXBCb3VuZHM6IFtcbiAgICBbWzAsIDAsIDBdLCBbMCwgMCwgMF1dLFxuICAgIFtbMCwgMCwgMF0sIFswLCAwLCAwXV0sXG4gICAgW1swLCAwLCAwXSwgWzAsIDAsIDBdXV1cbn1cblxuZnVuY3Rpb24gY29tcHV0ZVByb2plY3Rpb25EYXRhIChjYW1lcmEsIG9iaikge1xuICB2YXIgaSwgaiwga1xuXG4gIC8vIENvbXB1dGUgY3ViZSBwcm9wZXJ0aWVzXG4gIHZhciBjdWJlQXhpcyA9IChvYmouYXhlcyAmJiBvYmouYXhlcy5sYXN0Q3ViZVByb3BzLmF4aXMpIHx8IFpFUk9fVkVDXG5cbiAgdmFyIHNob3dTdXJmYWNlID0gb2JqLnNob3dTdXJmYWNlXG4gIHZhciBzaG93Q29udG91ciA9IG9iai5zaG93Q29udG91clxuXG4gIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICBzaG93U3VyZmFjZSA9IHNob3dTdXJmYWNlIHx8IG9iai5zdXJmYWNlUHJvamVjdFtpXVxuICAgIGZvciAoaiA9IDA7IGogPCAzOyArK2opIHtcbiAgICAgIHNob3dDb250b3VyID0gc2hvd0NvbnRvdXIgfHwgb2JqLmNvbnRvdXJQcm9qZWN0W2ldW2pdXG4gICAgfVxuICB9XG5cbiAgZm9yIChpID0gMDsgaSA8IDM7ICsraSkge1xuICAgIC8vIENvbnN0cnVjdCBwcm9qZWN0aW9uIG9udG8gYXhpc1xuICAgIHZhciBheGlzU3F1aXNoID0gUFJPSkVDVF9EQVRBLnByb2plY3Rpb25zW2ldXG4gICAgZm9yIChqID0gMDsgaiA8IDE2OyArK2opIHtcbiAgICAgIGF4aXNTcXVpc2hbal0gPSAwXG4gICAgfVxuICAgIGZvciAoaiA9IDA7IGogPCA0OyArK2opIHtcbiAgICAgIGF4aXNTcXVpc2hbNSAqIGpdID0gMVxuICAgIH1cbiAgICBheGlzU3F1aXNoWzUgKiBpXSA9IDBcbiAgICBheGlzU3F1aXNoWzEyICsgaV0gPSBvYmouYXhlc0JvdW5kc1srKGN1YmVBeGlzW2ldID4gMCldW2ldXG4gICAgbXVsdGlwbHkoYXhpc1NxdWlzaCwgY2FtZXJhLm1vZGVsLCBheGlzU3F1aXNoKVxuXG4gICAgdmFyIG5jbGlwQm91bmRzID0gUFJPSkVDVF9EQVRBLmNsaXBCb3VuZHNbaV1cbiAgICBmb3IgKGsgPSAwOyBrIDwgMjsgKytrKSB7XG4gICAgICBmb3IgKGogPSAwOyBqIDwgMzsgKytqKSB7XG4gICAgICAgIG5jbGlwQm91bmRzW2tdW2pdID0gY2FtZXJhLmNsaXBCb3VuZHNba11bal1cbiAgICAgIH1cbiAgICB9XG4gICAgbmNsaXBCb3VuZHNbMF1baV0gPSAtMWU4XG4gICAgbmNsaXBCb3VuZHNbMV1baV0gPSAxZThcbiAgfVxuXG4gIFBST0pFQ1RfREFUQS5zaG93U3VyZmFjZSA9IHNob3dTdXJmYWNlXG4gIFBST0pFQ1RfREFUQS5zaG93Q29udG91ciA9IHNob3dDb250b3VyXG5cbiAgcmV0dXJuIFBST0pFQ1RfREFUQVxufVxuXG52YXIgVU5JRk9STVMgPSB7XG4gIG1vZGVsOiBJREVOVElUWSxcbiAgdmlldzogSURFTlRJVFksXG4gIHByb2plY3Rpb246IElERU5USVRZLFxuICBpbnZlcnNlTW9kZWw6IElERU5USVRZLnNsaWNlKCksXG4gIGxvd2VyQm91bmQ6IFswLCAwLCAwXSxcbiAgdXBwZXJCb3VuZDogWzAsIDAsIDBdLFxuICBjb2xvck1hcDogMCxcbiAgY2xpcEJvdW5kczogW1swLCAwLCAwXSwgWzAsIDAsIDBdXSxcbiAgaGVpZ2h0OiAwLjAsXG4gIGNvbnRvdXJUaW50OiAwLFxuICBjb250b3VyQ29sb3I6IFswLCAwLCAwLCAxXSxcbiAgcGVybXV0YXRpb246IFsxLCAwLCAwLCAwLCAxLCAwLCAwLCAwLCAxXSxcbiAgek9mZnNldDogLTFlLTQsXG4gIG9iamVjdE9mZnNldDogWzAsIDAsIDBdLFxuICBrYW1iaWVudDogMSxcbiAga2RpZmZ1c2U6IDEsXG4gIGtzcGVjdWxhcjogMSxcbiAgbGlnaHRQb3NpdGlvbjogWzEwMDAsIDEwMDAsIDEwMDBdLFxuICBleWVQb3NpdGlvbjogWzAsIDAsIDBdLFxuICByb3VnaG5lc3M6IDEsXG4gIGZyZXNuZWw6IDEsXG4gIG9wYWNpdHk6IDEsXG4gIHZlcnRleENvbG9yOiAwXG59XG5cbnZhciBNQVRSSVhfSU5WRVJTRSA9IElERU5USVRZLnNsaWNlKClcbnZhciBERUZBVUxUX1BFUk0gPSBbMSwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMV1cblxuZnVuY3Rpb24gZHJhd0NvcmUgKHBhcmFtcywgdHJhbnNwYXJlbnQpIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9XG4gIHZhciBnbCA9IHRoaXMuZ2xcblxuICBnbC5kaXNhYmxlKGdsLkNVTExfRkFDRSlcblxuICB0aGlzLl9jb2xvck1hcC5iaW5kKDApXG5cbiAgdmFyIHVuaWZvcm1zID0gVU5JRk9STVNcbiAgdW5pZm9ybXMubW9kZWwgPSBwYXJhbXMubW9kZWwgfHwgSURFTlRJVFlcbiAgdW5pZm9ybXMudmlldyA9IHBhcmFtcy52aWV3IHx8IElERU5USVRZXG4gIHVuaWZvcm1zLnByb2plY3Rpb24gPSBwYXJhbXMucHJvamVjdGlvbiB8fCBJREVOVElUWVxuICB1bmlmb3Jtcy5sb3dlckJvdW5kID0gW3RoaXMuYm91bmRzWzBdWzBdLCB0aGlzLmJvdW5kc1swXVsxXSwgdGhpcy5jb2xvckJvdW5kc1swXSB8fCB0aGlzLmJvdW5kc1swXVsyXV1cbiAgdW5pZm9ybXMudXBwZXJCb3VuZCA9IFt0aGlzLmJvdW5kc1sxXVswXSwgdGhpcy5ib3VuZHNbMV1bMV0sIHRoaXMuY29sb3JCb3VuZHNbMV0gfHwgdGhpcy5ib3VuZHNbMV1bMl1dXG4gIHVuaWZvcm1zLm9iamVjdE9mZnNldCA9IHRoaXMub2JqZWN0T2Zmc2V0XG4gIHVuaWZvcm1zLmNvbnRvdXJDb2xvciA9IHRoaXMuY29udG91ckNvbG9yWzBdXG5cbiAgdW5pZm9ybXMuaW52ZXJzZU1vZGVsID0gaW52ZXJ0KHVuaWZvcm1zLmludmVyc2VNb2RlbCwgdW5pZm9ybXMubW9kZWwpXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAyOyArK2kpIHtcbiAgICB2YXIgY2xpcENsYW1wZWQgPSB1bmlmb3Jtcy5jbGlwQm91bmRzW2ldXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCAzOyArK2opIHtcbiAgICAgIGNsaXBDbGFtcGVkW2pdID0gTWF0aC5taW4oTWF0aC5tYXgodGhpcy5jbGlwQm91bmRzW2ldW2pdLCAtMWU4KSwgMWU4KVxuICAgIH1cbiAgfVxuXG4gIHVuaWZvcm1zLmthbWJpZW50ID0gdGhpcy5hbWJpZW50TGlnaHRcbiAgdW5pZm9ybXMua2RpZmZ1c2UgPSB0aGlzLmRpZmZ1c2VMaWdodFxuICB1bmlmb3Jtcy5rc3BlY3VsYXIgPSB0aGlzLnNwZWN1bGFyTGlnaHRcblxuICB1bmlmb3Jtcy5yb3VnaG5lc3MgPSB0aGlzLnJvdWdobmVzc1xuICB1bmlmb3Jtcy5mcmVzbmVsID0gdGhpcy5mcmVzbmVsXG4gIHVuaWZvcm1zLm9wYWNpdHkgPSB0aGlzLm9wYWNpdHlcblxuICB1bmlmb3Jtcy5oZWlnaHQgPSAwLjBcbiAgdW5pZm9ybXMucGVybXV0YXRpb24gPSBERUZBVUxUX1BFUk1cblxuICB1bmlmb3Jtcy52ZXJ0ZXhDb2xvciA9IHRoaXMudmVydGV4Q29sb3JcblxuICAvLyBDb21wdXRlIGNhbWVyYSBtYXRyaXggaW52ZXJzZVxuICB2YXIgaW52Q2FtZXJhTWF0cml4ID0gTUFUUklYX0lOVkVSU0VcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy52aWV3LCB1bmlmb3Jtcy5tb2RlbClcbiAgbXVsdGlwbHkoaW52Q2FtZXJhTWF0cml4LCB1bmlmb3Jtcy5wcm9qZWN0aW9uLCBpbnZDYW1lcmFNYXRyaXgpXG4gIGludmVydChpbnZDYW1lcmFNYXRyaXgsIGludkNhbWVyYU1hdHJpeClcblxuICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgdW5pZm9ybXMuZXllUG9zaXRpb25baV0gPSBpbnZDYW1lcmFNYXRyaXhbMTIgKyBpXSAvIGludkNhbWVyYU1hdHJpeFsxNV1cbiAgfVxuXG4gIHZhciB3ID0gaW52Q2FtZXJhTWF0cml4WzE1XVxuICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgdyArPSB0aGlzLmxpZ2h0UG9zaXRpb25baV0gKiBpbnZDYW1lcmFNYXRyaXhbNCAqIGkgKyAzXVxuICB9XG4gIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICB2YXIgcyA9IGludkNhbWVyYU1hdHJpeFsxMiArIGldXG4gICAgZm9yIChqID0gMDsgaiA8IDM7ICsraikge1xuICAgICAgcyArPSBpbnZDYW1lcmFNYXRyaXhbNCAqIGogKyBpXSAqIHRoaXMubGlnaHRQb3NpdGlvbltqXVxuICAgIH1cbiAgICB1bmlmb3Jtcy5saWdodFBvc2l0aW9uW2ldID0gcyAvIHdcbiAgfVxuXG4gIHZhciBwcm9qZWN0RGF0YSA9IGNvbXB1dGVQcm9qZWN0aW9uRGF0YSh1bmlmb3JtcywgdGhpcylcblxuICBpZiAocHJvamVjdERhdGEuc2hvd1N1cmZhY2UgJiYgKHRyYW5zcGFyZW50ID09PSAodGhpcy5vcGFjaXR5IDwgMSkpKSB7XG4gICAgLy8gU2V0IHVwIHVuaWZvcm1zXG4gICAgdGhpcy5fc2hhZGVyLmJpbmQoKVxuICAgIHRoaXMuX3NoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXG5cbiAgICAvLyBEcmF3IGl0XG4gICAgdGhpcy5fdmFvLmJpbmQoKVxuXG4gICAgaWYgKHRoaXMuc2hvd1N1cmZhY2UgJiYgdGhpcy5fdmVydGV4Q291bnQpIHtcbiAgICAgIHRoaXMuX3Zhby5kcmF3KGdsLlRSSUFOR0xFUywgdGhpcy5fdmVydGV4Q291bnQpXG4gICAgfVxuXG4gICAgLy8gRHJhdyBwcm9qZWN0aW9ucyBvZiBzdXJmYWNlXG4gICAgZm9yIChpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgaWYgKCF0aGlzLnN1cmZhY2VQcm9qZWN0W2ldIHx8ICF0aGlzLnZlcnRleENvdW50KSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICB0aGlzLl9zaGFkZXIudW5pZm9ybXMubW9kZWwgPSBwcm9qZWN0RGF0YS5wcm9qZWN0aW9uc1tpXVxuICAgICAgdGhpcy5fc2hhZGVyLnVuaWZvcm1zLmNsaXBCb3VuZHMgPSBwcm9qZWN0RGF0YS5jbGlwQm91bmRzW2ldXG4gICAgICB0aGlzLl92YW8uZHJhdyhnbC5UUklBTkdMRVMsIHRoaXMuX3ZlcnRleENvdW50KVxuICAgIH1cblxuICAgIHRoaXMuX3Zhby51bmJpbmQoKVxuICB9XG5cbiAgaWYgKHByb2plY3REYXRhLnNob3dDb250b3VyICYmICF0cmFuc3BhcmVudCkge1xuICAgIHZhciBzaGFkZXIgPSB0aGlzLl9jb250b3VyU2hhZGVyXG5cbiAgICAvLyBEb24ndCBhcHBseSBsaWdodGluZyB0byBjb250b3Vyc1xuICAgIHVuaWZvcm1zLmthbWJpZW50ID0gMS4wXG4gICAgdW5pZm9ybXMua2RpZmZ1c2UgPSAwLjBcbiAgICB1bmlmb3Jtcy5rc3BlY3VsYXIgPSAwLjBcbiAgICB1bmlmb3Jtcy5vcGFjaXR5ID0gMS4wXG5cbiAgICBzaGFkZXIuYmluZCgpXG4gICAgc2hhZGVyLnVuaWZvcm1zID0gdW5pZm9ybXNcblxuICAgIC8vIERyYXcgY29udG91ciBsaW5lc1xuICAgIHZhciB2YW8gPSB0aGlzLl9jb250b3VyVkFPXG4gICAgdmFvLmJpbmQoKVxuXG4gICAgLy8gRHJhdyBjb250b3VyIGxldmVsc1xuICAgIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5wZXJtdXRhdGlvbiA9IFBFUk1VVEFUSU9OU1tpXVxuICAgICAgZ2wubGluZVdpZHRoKHRoaXMuY29udG91cldpZHRoW2ldICogdGhpcy5waXhlbFJhdGlvKVxuXG4gICAgICBmb3IgKGogPSAwOyBqIDwgdGhpcy5jb250b3VyTGV2ZWxzW2ldLmxlbmd0aDsgKytqKSB7XG4gICAgICAgIGlmIChqID09PSB0aGlzLmhpZ2hsaWdodExldmVsW2ldKSB7XG4gICAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmNvbnRvdXJDb2xvciA9IHRoaXMuaGlnaGxpZ2h0Q29sb3JbaV1cbiAgICAgICAgICBzaGFkZXIudW5pZm9ybXMuY29udG91clRpbnQgPSB0aGlzLmhpZ2hsaWdodFRpbnRbaV1cbiAgICAgICAgfSBlbHNlIGlmIChqID09PSAwIHx8IChqIC0gMSkgPT09IHRoaXMuaGlnaGxpZ2h0TGV2ZWxbaV0pIHtcbiAgICAgICAgICBzaGFkZXIudW5pZm9ybXMuY29udG91ckNvbG9yID0gdGhpcy5jb250b3VyQ29sb3JbaV1cbiAgICAgICAgICBzaGFkZXIudW5pZm9ybXMuY29udG91clRpbnQgPSB0aGlzLmNvbnRvdXJUaW50W2ldXG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLl9jb250b3VyQ291bnRzW2ldW2pdKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIHNoYWRlci51bmlmb3Jtcy5oZWlnaHQgPSB0aGlzLmNvbnRvdXJMZXZlbHNbaV1bal1cbiAgICAgICAgdmFvLmRyYXcoZ2wuTElORVMsIHRoaXMuX2NvbnRvdXJDb3VudHNbaV1bal0sIHRoaXMuX2NvbnRvdXJPZmZzZXRzW2ldW2pdKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIERyYXcgcHJvamVjdGlvbnMgb2Ygc3VyZmFjZVxuICAgIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5tb2RlbCA9IHByb2plY3REYXRhLnByb2plY3Rpb25zW2ldXG4gICAgICBzaGFkZXIudW5pZm9ybXMuY2xpcEJvdW5kcyA9IHByb2plY3REYXRhLmNsaXBCb3VuZHNbaV1cbiAgICAgIGZvciAoaiA9IDA7IGogPCAzOyArK2opIHtcbiAgICAgICAgaWYgKCF0aGlzLmNvbnRvdXJQcm9qZWN0W2ldW2pdKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgICBzaGFkZXIudW5pZm9ybXMucGVybXV0YXRpb24gPSBQRVJNVVRBVElPTlNbal1cbiAgICAgICAgZ2wubGluZVdpZHRoKHRoaXMuY29udG91cldpZHRoW2pdICogdGhpcy5waXhlbFJhdGlvKVxuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IHRoaXMuY29udG91ckxldmVsc1tqXS5sZW5ndGg7ICsraykge1xuICAgICAgICAgIGlmIChrID09PSB0aGlzLmhpZ2hsaWdodExldmVsW2pdKSB7XG4gICAgICAgICAgICBzaGFkZXIudW5pZm9ybXMuY29udG91ckNvbG9yID0gdGhpcy5oaWdobGlnaHRDb2xvcltqXVxuICAgICAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmNvbnRvdXJUaW50ID0gdGhpcy5oaWdobGlnaHRUaW50W2pdXG4gICAgICAgICAgfSBlbHNlIGlmIChrID09PSAwIHx8IChrIC0gMSkgPT09IHRoaXMuaGlnaGxpZ2h0TGV2ZWxbal0pIHtcbiAgICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5jb250b3VyQ29sb3IgPSB0aGlzLmNvbnRvdXJDb2xvcltqXVxuICAgICAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmNvbnRvdXJUaW50ID0gdGhpcy5jb250b3VyVGludFtqXVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIXRoaXMuX2NvbnRvdXJDb3VudHNbal1ba10pIHtcbiAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmhlaWdodCA9IHRoaXMuY29udG91ckxldmVsc1tqXVtrXVxuICAgICAgICAgIHZhby5kcmF3KGdsLkxJTkVTLCB0aGlzLl9jb250b3VyQ291bnRzW2pdW2tdLCB0aGlzLl9jb250b3VyT2Zmc2V0c1tqXVtrXSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHZhby51bmJpbmQoKVxuXG4gICAgLy8gRHJhdyBkeW5hbWljIGNvbnRvdXJzXG4gICAgdmFvID0gdGhpcy5fZHluYW1pY1ZBT1xuICAgIHZhby5iaW5kKClcblxuICAgIC8vIERyYXcgY29udG91ciBsZXZlbHNcbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICBpZiAodGhpcy5fZHluYW1pY0NvdW50c1tpXSA9PT0gMCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBzaGFkZXIudW5pZm9ybXMubW9kZWwgPSB1bmlmb3Jtcy5tb2RlbFxuICAgICAgc2hhZGVyLnVuaWZvcm1zLmNsaXBCb3VuZHMgPSB1bmlmb3Jtcy5jbGlwQm91bmRzXG4gICAgICBzaGFkZXIudW5pZm9ybXMucGVybXV0YXRpb24gPSBQRVJNVVRBVElPTlNbaV1cbiAgICAgIGdsLmxpbmVXaWR0aCh0aGlzLmR5bmFtaWNXaWR0aFtpXSAqIHRoaXMucGl4ZWxSYXRpbylcblxuICAgICAgc2hhZGVyLnVuaWZvcm1zLmNvbnRvdXJDb2xvciA9IHRoaXMuZHluYW1pY0NvbG9yW2ldXG4gICAgICBzaGFkZXIudW5pZm9ybXMuY29udG91clRpbnQgPSB0aGlzLmR5bmFtaWNUaW50W2ldXG4gICAgICBzaGFkZXIudW5pZm9ybXMuaGVpZ2h0ID0gdGhpcy5keW5hbWljTGV2ZWxbaV1cbiAgICAgIHZhby5kcmF3KGdsLkxJTkVTLCB0aGlzLl9keW5hbWljQ291bnRzW2ldLCB0aGlzLl9keW5hbWljT2Zmc2V0c1tpXSlcblxuICAgICAgZm9yIChqID0gMDsgaiA8IDM7ICsraikge1xuICAgICAgICBpZiAoIXRoaXMuY29udG91clByb2plY3Rbal1baV0pIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG5cbiAgICAgICAgc2hhZGVyLnVuaWZvcm1zLm1vZGVsID0gcHJvamVjdERhdGEucHJvamVjdGlvbnNbal1cbiAgICAgICAgc2hhZGVyLnVuaWZvcm1zLmNsaXBCb3VuZHMgPSBwcm9qZWN0RGF0YS5jbGlwQm91bmRzW2pdXG4gICAgICAgIHZhby5kcmF3KGdsLkxJTkVTLCB0aGlzLl9keW5hbWljQ291bnRzW2ldLCB0aGlzLl9keW5hbWljT2Zmc2V0c1tpXSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YW8udW5iaW5kKClcbiAgfVxufVxuXG5wcm90by5kcmF3ID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICByZXR1cm4gZHJhd0NvcmUuY2FsbCh0aGlzLCBwYXJhbXMsIGZhbHNlKVxufVxuXG5wcm90by5kcmF3VHJhbnNwYXJlbnQgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gIHJldHVybiBkcmF3Q29yZS5jYWxsKHRoaXMsIHBhcmFtcywgdHJ1ZSlcbn1cblxudmFyIFBJQ0tfVU5JRk9STVMgPSB7XG4gIG1vZGVsOiBJREVOVElUWSxcbiAgdmlldzogSURFTlRJVFksXG4gIHByb2plY3Rpb246IElERU5USVRZLFxuICBpbnZlcnNlTW9kZWw6IElERU5USVRZLFxuICBjbGlwQm91bmRzOiBbWzAsIDAsIDBdLCBbMCwgMCwgMF1dLFxuICBoZWlnaHQ6IDAuMCxcbiAgc2hhcGU6IFswLCAwXSxcbiAgcGlja0lkOiAwLFxuICBsb3dlckJvdW5kOiBbMCwgMCwgMF0sXG4gIHVwcGVyQm91bmQ6IFswLCAwLCAwXSxcbiAgek9mZnNldDogMC4wLFxuICBvYmplY3RPZmZzZXQ6IFswLCAwLCAwXSxcbiAgcGVybXV0YXRpb246IFsxLCAwLCAwLCAwLCAxLCAwLCAwLCAwLCAxXSxcbiAgbGlnaHRQb3NpdGlvbjogWzAsIDAsIDBdLFxuICBleWVQb3NpdGlvbjogWzAsIDAsIDBdXG59XG5cbnByb3RvLmRyYXdQaWNrID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge31cbiAgdmFyIGdsID0gdGhpcy5nbFxuICBnbC5kaXNhYmxlKGdsLkNVTExfRkFDRSlcblxuICB2YXIgdW5pZm9ybXMgPSBQSUNLX1VOSUZPUk1TXG4gIHVuaWZvcm1zLm1vZGVsID0gcGFyYW1zLm1vZGVsIHx8IElERU5USVRZXG4gIHVuaWZvcm1zLnZpZXcgPSBwYXJhbXMudmlldyB8fCBJREVOVElUWVxuICB1bmlmb3Jtcy5wcm9qZWN0aW9uID0gcGFyYW1zLnByb2plY3Rpb24gfHwgSURFTlRJVFlcbiAgdW5pZm9ybXMuc2hhcGUgPSB0aGlzLl9maWVsZFsyXS5zaGFwZVxuICB1bmlmb3Jtcy5waWNrSWQgPSB0aGlzLnBpY2tJZCAvIDI1NS4wXG4gIHVuaWZvcm1zLmxvd2VyQm91bmQgPSB0aGlzLmJvdW5kc1swXVxuICB1bmlmb3Jtcy51cHBlckJvdW5kID0gdGhpcy5ib3VuZHNbMV1cbiAgdW5pZm9ybXMub2JqZWN0T2Zmc2V0ID0gdGhpcy5vYmplY3RPZmZzZXRcbiAgdW5pZm9ybXMucGVybXV0YXRpb24gPSBERUZBVUxUX1BFUk1cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IDI7ICsraSkge1xuICAgIHZhciBjbGlwQ2xhbXBlZCA9IHVuaWZvcm1zLmNsaXBCb3VuZHNbaV1cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IDM7ICsraikge1xuICAgICAgY2xpcENsYW1wZWRbal0gPSBNYXRoLm1pbihNYXRoLm1heCh0aGlzLmNsaXBCb3VuZHNbaV1bal0sIC0xZTgpLCAxZTgpXG4gICAgfVxuICB9XG5cbiAgdmFyIHByb2plY3REYXRhID0gY29tcHV0ZVByb2plY3Rpb25EYXRhKHVuaWZvcm1zLCB0aGlzKVxuXG4gIGlmIChwcm9qZWN0RGF0YS5zaG93U3VyZmFjZSkge1xuICAgIC8vIFNldCB1cCB1bmlmb3Jtc1xuICAgIHRoaXMuX3BpY2tTaGFkZXIuYmluZCgpXG4gICAgdGhpcy5fcGlja1NoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXG5cbiAgICAvLyBEcmF3IGl0XG4gICAgdGhpcy5fdmFvLmJpbmQoKVxuICAgIHRoaXMuX3Zhby5kcmF3KGdsLlRSSUFOR0xFUywgdGhpcy5fdmVydGV4Q291bnQpXG5cbiAgICAvLyBEcmF3IHByb2plY3Rpb25zIG9mIHN1cmZhY2VcbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICBpZiAoIXRoaXMuc3VyZmFjZVByb2plY3RbaV0pIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIHRoaXMuX3BpY2tTaGFkZXIudW5pZm9ybXMubW9kZWwgPSBwcm9qZWN0RGF0YS5wcm9qZWN0aW9uc1tpXVxuICAgICAgdGhpcy5fcGlja1NoYWRlci51bmlmb3Jtcy5jbGlwQm91bmRzID0gcHJvamVjdERhdGEuY2xpcEJvdW5kc1tpXVxuICAgICAgdGhpcy5fdmFvLmRyYXcoZ2wuVFJJQU5HTEVTLCB0aGlzLl92ZXJ0ZXhDb3VudClcbiAgICB9XG5cbiAgICB0aGlzLl92YW8udW5iaW5kKClcbiAgfVxuXG4gIGlmIChwcm9qZWN0RGF0YS5zaG93Q29udG91cikge1xuICAgIHZhciBzaGFkZXIgPSB0aGlzLl9jb250b3VyUGlja1NoYWRlclxuXG4gICAgc2hhZGVyLmJpbmQoKVxuICAgIHNoYWRlci51bmlmb3JtcyA9IHVuaWZvcm1zXG5cbiAgICB2YXIgdmFvID0gdGhpcy5fY29udG91clZBT1xuICAgIHZhby5iaW5kKClcblxuICAgIGZvciAoaiA9IDA7IGogPCAzOyArK2opIHtcbiAgICAgIGdsLmxpbmVXaWR0aCh0aGlzLmNvbnRvdXJXaWR0aFtqXSAqIHRoaXMucGl4ZWxSYXRpbylcbiAgICAgIHNoYWRlci51bmlmb3Jtcy5wZXJtdXRhdGlvbiA9IFBFUk1VVEFUSU9OU1tqXVxuICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY29udG91ckxldmVsc1tqXS5sZW5ndGg7ICsraSkge1xuICAgICAgICBpZiAodGhpcy5fY29udG91ckNvdW50c1tqXVtpXSkge1xuICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5oZWlnaHQgPSB0aGlzLmNvbnRvdXJMZXZlbHNbal1baV1cbiAgICAgICAgICB2YW8uZHJhdyhnbC5MSU5FUywgdGhpcy5fY29udG91ckNvdW50c1tqXVtpXSwgdGhpcy5fY29udG91ck9mZnNldHNbal1baV0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEcmF3IHByb2plY3Rpb25zIG9mIHN1cmZhY2VcbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICBzaGFkZXIudW5pZm9ybXMubW9kZWwgPSBwcm9qZWN0RGF0YS5wcm9qZWN0aW9uc1tpXVxuICAgICAgc2hhZGVyLnVuaWZvcm1zLmNsaXBCb3VuZHMgPSBwcm9qZWN0RGF0YS5jbGlwQm91bmRzW2ldXG5cbiAgICAgIGZvciAoaiA9IDA7IGogPCAzOyArK2opIHtcbiAgICAgICAgaWYgKCF0aGlzLmNvbnRvdXJQcm9qZWN0W2ldW2pdKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIHNoYWRlci51bmlmb3Jtcy5wZXJtdXRhdGlvbiA9IFBFUk1VVEFUSU9OU1tqXVxuICAgICAgICBnbC5saW5lV2lkdGgodGhpcy5jb250b3VyV2lkdGhbal0gKiB0aGlzLnBpeGVsUmF0aW8pXG4gICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgdGhpcy5jb250b3VyTGV2ZWxzW2pdLmxlbmd0aDsgKytrKSB7XG4gICAgICAgICAgaWYgKHRoaXMuX2NvbnRvdXJDb3VudHNbal1ba10pIHtcbiAgICAgICAgICAgIHNoYWRlci51bmlmb3Jtcy5oZWlnaHQgPSB0aGlzLmNvbnRvdXJMZXZlbHNbal1ba11cbiAgICAgICAgICAgIHZhby5kcmF3KGdsLkxJTkVTLCB0aGlzLl9jb250b3VyQ291bnRzW2pdW2tdLCB0aGlzLl9jb250b3VyT2Zmc2V0c1tqXVtrXSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YW8udW5iaW5kKClcbiAgfVxufVxuXG5wcm90by5waWNrID0gZnVuY3Rpb24gKHNlbGVjdGlvbikge1xuICBpZiAoIXNlbGVjdGlvbikge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICBpZiAoc2VsZWN0aW9uLmlkICE9PSB0aGlzLnBpY2tJZCkge1xuICAgIHJldHVybiBudWxsXG4gIH1cblxuICB2YXIgc2hhcGUgPSB0aGlzLl9maWVsZFsyXS5zaGFwZVxuXG4gIHZhciByZXN1bHQgPSB0aGlzLl9waWNrUmVzdWx0XG5cbiAgLy8gQ29tcHV0ZSB1diBjb29yZGluYXRlXG4gIHZhciB4ID0gc2hhcGVbMF0gKiAoc2VsZWN0aW9uLnZhbHVlWzBdICsgKHNlbGVjdGlvbi52YWx1ZVsyXSA+PiA0KSAvIDE2LjApIC8gMjU1LjBcbiAgdmFyIGl4ID0gTWF0aC5mbG9vcih4KVxuICB2YXIgZnggPSB4IC0gaXhcblxuICB2YXIgeSA9IHNoYXBlWzFdICogKHNlbGVjdGlvbi52YWx1ZVsxXSArIChzZWxlY3Rpb24udmFsdWVbMl0gJiAxNSkgLyAxNi4wKSAvIDI1NS4wXG4gIHZhciBpeSA9IE1hdGguZmxvb3IoeSlcbiAgdmFyIGZ5ID0geSAtIGl5XG5cbiAgaXggKz0gMVxuICBpeSArPSAxXG5cbiAgLy8gQ29tcHV0ZSB4eXogY29vcmRpbmF0ZVxuICB2YXIgcG9zID0gcmVzdWx0LnBvc2l0aW9uXG4gIHBvc1swXSA9IHBvc1sxXSA9IHBvc1syXSA9IDBcbiAgZm9yICh2YXIgZHggPSAwOyBkeCA8IDI7ICsrZHgpIHtcbiAgICB2YXIgcyA9IGR4ID8gZnggOiAxLjAgLSBmeFxuICAgIGZvciAodmFyIGR5ID0gMDsgZHkgPCAyOyArK2R5KSB7XG4gICAgICB2YXIgdCA9IGR5ID8gZnkgOiAxLjAgLSBmeVxuXG4gICAgICB2YXIgciA9IGl4ICsgZHhcbiAgICAgIHZhciBjID0gaXkgKyBkeVxuICAgICAgdmFyIHcgPSBzICogdFxuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICBwb3NbaV0gKz0gdGhpcy5fZmllbGRbaV0uZ2V0KHIsIGMpICogd1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIEZpbmQgY2xvc2VzdCBsZXZlbFxuICB2YXIgbGV2ZWxJbmRleCA9IHRoaXMuX3BpY2tSZXN1bHQubGV2ZWxcbiAgZm9yICh2YXIgaiA9IDA7IGogPCAzOyArK2opIHtcbiAgICBsZXZlbEluZGV4W2pdID0gYnNlYXJjaC5sZSh0aGlzLmNvbnRvdXJMZXZlbHNbal0sIHBvc1tqXSlcbiAgICBpZiAobGV2ZWxJbmRleFtqXSA8IDApIHtcbiAgICAgIGlmICh0aGlzLmNvbnRvdXJMZXZlbHNbal0ubGVuZ3RoID4gMCkge1xuICAgICAgICBsZXZlbEluZGV4W2pdID0gMFxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobGV2ZWxJbmRleFtqXSA8IHRoaXMuY29udG91ckxldmVsc1tqXS5sZW5ndGggLSAxKSB7XG4gICAgICB2YXIgYSA9IHRoaXMuY29udG91ckxldmVsc1tqXVtsZXZlbEluZGV4W2pdXVxuICAgICAgdmFyIGIgPSB0aGlzLmNvbnRvdXJMZXZlbHNbal1bbGV2ZWxJbmRleFtqXSArIDFdXG4gICAgICBpZiAoTWF0aC5hYnMoYSAtIHBvc1tqXSkgPiBNYXRoLmFicyhiIC0gcG9zW2pdKSkge1xuICAgICAgICBsZXZlbEluZGV4W2pdICs9IDFcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXN1bHQuaW5kZXhbMF0gPSBmeCA8IDAuNSA/IGl4IDogKGl4ICsgMSlcbiAgcmVzdWx0LmluZGV4WzFdID0gZnkgPCAwLjUgPyBpeSA6IChpeSArIDEpXG5cbiAgcmVzdWx0LnV2WzBdID0geCAvIHNoYXBlWzBdXG4gIHJlc3VsdC51dlsxXSA9IHkgLyBzaGFwZVsxXVxuXG4gIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICByZXN1bHQuZGF0YUNvb3JkaW5hdGVbaV0gPSB0aGlzLl9maWVsZFtpXS5nZXQocmVzdWx0LmluZGV4WzBdLCByZXN1bHQuaW5kZXhbMV0pXG4gIH1cblxuICByZXR1cm4gcmVzdWx0XG59XG5cbnByb3RvLnBhZEZpZWxkID0gZnVuY3Rpb24oZHN0RmllbGQsIHNyY0ZpZWxkKSB7XG4gIHZhciBzcmNTaGFwZSA9IHNyY0ZpZWxkLnNoYXBlLnNsaWNlKClcbiAgdmFyIGRzdFNoYXBlID0gZHN0RmllbGQuc2hhcGUuc2xpY2UoKVxuXG4gIC8vIENlbnRlclxuICBvcHMuYXNzaWduKGRzdEZpZWxkLmxvKDEsIDEpLmhpKHNyY1NoYXBlWzBdLCBzcmNTaGFwZVsxXSksIHNyY0ZpZWxkKVxuXG4gIC8vIEVkZ2VzXG4gIG9wcy5hc3NpZ24oZHN0RmllbGQubG8oMSkuaGkoc3JjU2hhcGVbMF0sIDEpLFxuICAgIHNyY0ZpZWxkLmhpKHNyY1NoYXBlWzBdLCAxKSlcbiAgb3BzLmFzc2lnbihkc3RGaWVsZC5sbygxLCBkc3RTaGFwZVsxXSAtIDEpLmhpKHNyY1NoYXBlWzBdLCAxKSxcbiAgICBzcmNGaWVsZC5sbygwLCBzcmNTaGFwZVsxXSAtIDEpLmhpKHNyY1NoYXBlWzBdLCAxKSlcbiAgb3BzLmFzc2lnbihkc3RGaWVsZC5sbygwLCAxKS5oaSgxLCBzcmNTaGFwZVsxXSksXG4gICAgc3JjRmllbGQuaGkoMSkpXG4gIG9wcy5hc3NpZ24oZHN0RmllbGQubG8oZHN0U2hhcGVbMF0gLSAxLCAxKS5oaSgxLCBzcmNTaGFwZVsxXSksXG4gICAgc3JjRmllbGQubG8oc3JjU2hhcGVbMF0gLSAxKSlcbiAgLy8gQ29ybmVyc1xuICBkc3RGaWVsZC5zZXQoMCwgMCwgc3JjRmllbGQuZ2V0KDAsIDApKVxuICBkc3RGaWVsZC5zZXQoMCwgZHN0U2hhcGVbMV0gLSAxLCBzcmNGaWVsZC5nZXQoMCwgc3JjU2hhcGVbMV0gLSAxKSlcbiAgZHN0RmllbGQuc2V0KGRzdFNoYXBlWzBdIC0gMSwgMCwgc3JjRmllbGQuZ2V0KHNyY1NoYXBlWzBdIC0gMSwgMCkpXG4gIGRzdEZpZWxkLnNldChkc3RTaGFwZVswXSAtIDEsIGRzdFNoYXBlWzFdIC0gMSwgc3JjRmllbGQuZ2V0KHNyY1NoYXBlWzBdIC0gMSwgc3JjU2hhcGVbMV0gLSAxKSlcbn1cblxuZnVuY3Rpb24gaGFuZGxlQXJyYXkgKHBhcmFtLCBjdG9yKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHBhcmFtKSkge1xuICAgIHJldHVybiBbIGN0b3IocGFyYW1bMF0pLCBjdG9yKHBhcmFtWzFdKSwgY3RvcihwYXJhbVsyXSkgXVxuICB9XG4gIHJldHVybiBbIGN0b3IocGFyYW0pLCBjdG9yKHBhcmFtKSwgY3RvcihwYXJhbSkgXVxufVxuXG5mdW5jdGlvbiB0b0NvbG9yICh4KSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHgpKSB7XG4gICAgaWYgKHgubGVuZ3RoID09PSAzKSB7XG4gICAgICByZXR1cm4gW3hbMF0sIHhbMV0sIHhbMl0sIDFdXG4gICAgfVxuICAgIHJldHVybiBbeFswXSwgeFsxXSwgeFsyXSwgeFszXV1cbiAgfVxuICByZXR1cm4gWzAsIDAsIDAsIDFdXG59XG5cbmZ1bmN0aW9uIGhhbmRsZUNvbG9yIChwYXJhbSkge1xuICBpZiAoQXJyYXkuaXNBcnJheShwYXJhbSkpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShwYXJhbSkpIHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIHRvQ29sb3IocGFyYW1bMF0pLFxuICAgICAgICB0b0NvbG9yKHBhcmFtWzFdKSxcbiAgICAgICAgdG9Db2xvcihwYXJhbVsyXSkgXVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgYyA9IHRvQ29sb3IocGFyYW0pXG4gICAgICByZXR1cm4gW1xuICAgICAgICBjLnNsaWNlKCksXG4gICAgICAgIGMuc2xpY2UoKSxcbiAgICAgICAgYy5zbGljZSgpIF1cbiAgICB9XG4gIH1cbn1cblxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge31cblxuICB0aGlzLm9iamVjdE9mZnNldCA9IHBhcmFtcy5vYmplY3RPZmZzZXQgfHwgdGhpcy5vYmplY3RPZmZzZXRcblxuICB0aGlzLmRpcnR5ID0gdHJ1ZVxuXG4gIGlmICgnY29udG91cldpZHRoJyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLmNvbnRvdXJXaWR0aCA9IGhhbmRsZUFycmF5KHBhcmFtcy5jb250b3VyV2lkdGgsIE51bWJlcilcbiAgfVxuICBpZiAoJ3Nob3dDb250b3VyJyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLnNob3dDb250b3VyID0gaGFuZGxlQXJyYXkocGFyYW1zLnNob3dDb250b3VyLCBCb29sZWFuKVxuICB9XG4gIGlmICgnc2hvd1N1cmZhY2UnIGluIHBhcmFtcykge1xuICAgIHRoaXMuc2hvd1N1cmZhY2UgPSAhIXBhcmFtcy5zaG93U3VyZmFjZVxuICB9XG4gIGlmICgnY29udG91clRpbnQnIGluIHBhcmFtcykge1xuICAgIHRoaXMuY29udG91clRpbnQgPSBoYW5kbGVBcnJheShwYXJhbXMuY29udG91clRpbnQsIEJvb2xlYW4pXG4gIH1cbiAgaWYgKCdjb250b3VyQ29sb3InIGluIHBhcmFtcykge1xuICAgIHRoaXMuY29udG91ckNvbG9yID0gaGFuZGxlQ29sb3IocGFyYW1zLmNvbnRvdXJDb2xvcilcbiAgfVxuICBpZiAoJ2NvbnRvdXJQcm9qZWN0JyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLmNvbnRvdXJQcm9qZWN0ID0gaGFuZGxlQXJyYXkocGFyYW1zLmNvbnRvdXJQcm9qZWN0LCBmdW5jdGlvbiAoeCkge1xuICAgICAgcmV0dXJuIGhhbmRsZUFycmF5KHgsIEJvb2xlYW4pXG4gICAgfSlcbiAgfVxuICBpZiAoJ3N1cmZhY2VQcm9qZWN0JyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLnN1cmZhY2VQcm9qZWN0ID0gcGFyYW1zLnN1cmZhY2VQcm9qZWN0XG4gIH1cbiAgaWYgKCdkeW5hbWljQ29sb3InIGluIHBhcmFtcykge1xuICAgIHRoaXMuZHluYW1pY0NvbG9yID0gaGFuZGxlQ29sb3IocGFyYW1zLmR5bmFtaWNDb2xvcilcbiAgfVxuICBpZiAoJ2R5bmFtaWNUaW50JyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLmR5bmFtaWNUaW50ID0gaGFuZGxlQXJyYXkocGFyYW1zLmR5bmFtaWNUaW50LCBOdW1iZXIpXG4gIH1cbiAgaWYgKCdkeW5hbWljV2lkdGgnIGluIHBhcmFtcykge1xuICAgIHRoaXMuZHluYW1pY1dpZHRoID0gaGFuZGxlQXJyYXkocGFyYW1zLmR5bmFtaWNXaWR0aCwgTnVtYmVyKVxuICB9XG4gIGlmICgnb3BhY2l0eScgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy5vcGFjaXR5ID0gcGFyYW1zLm9wYWNpdHlcbiAgfVxuICBpZiAoJ2NvbG9yQm91bmRzJyBpbiBwYXJhbXMpIHtcbiAgICB0aGlzLmNvbG9yQm91bmRzID0gcGFyYW1zLmNvbG9yQm91bmRzXG4gIH1cbiAgaWYgKCd2ZXJ0ZXhDb2xvcicgaW4gcGFyYW1zKSB7XG4gICAgdGhpcy52ZXJ0ZXhDb2xvciA9IHBhcmFtcy52ZXJ0ZXhDb2xvciA/IDEgOiAwO1xuICB9XG5cbiAgdmFyIGZpZWxkID0gcGFyYW1zLmZpZWxkIHx8IChwYXJhbXMuY29vcmRzICYmIHBhcmFtcy5jb29yZHNbMl0pIHx8IG51bGxcbiAgdmFyIGxldmVsc0NoYW5nZWQgPSBmYWxzZVxuXG4gIGlmICghZmllbGQpIHtcbiAgICBpZiAodGhpcy5fZmllbGRbMl0uc2hhcGVbMF0gfHwgdGhpcy5fZmllbGRbMl0uc2hhcGVbMl0pIHtcbiAgICAgIGZpZWxkID0gdGhpcy5fZmllbGRbMl0ubG8oMSwgMSkuaGkodGhpcy5fZmllbGRbMl0uc2hhcGVbMF0gLSAyLCB0aGlzLl9maWVsZFsyXS5zaGFwZVsxXSAtIDIpXG4gICAgfSBlbHNlIHtcbiAgICAgIGZpZWxkID0gdGhpcy5fZmllbGRbMl0uaGkoMCwgMClcbiAgICB9XG4gIH1cblxuICAvLyBVcGRhdGUgZmllbGRcbiAgaWYgKCdmaWVsZCcgaW4gcGFyYW1zIHx8ICdjb29yZHMnIGluIHBhcmFtcykge1xuICAgIHZhciBmc2l6ZSA9IChmaWVsZC5zaGFwZVswXSArIDIpICogKGZpZWxkLnNoYXBlWzFdICsgMilcblxuICAgIC8vIFJlc2l6ZSBpZiBuZWNlc3NhcnlcbiAgICBpZiAoZnNpemUgPiB0aGlzLl9maWVsZFsyXS5kYXRhLmxlbmd0aCkge1xuICAgICAgcG9vbC5mcmVlRmxvYXQodGhpcy5fZmllbGRbMl0uZGF0YSlcbiAgICAgIHRoaXMuX2ZpZWxkWzJdLmRhdGEgPSBwb29sLm1hbGxvY0Zsb2F0KGJpdHMubmV4dFBvdzIoZnNpemUpKVxuICAgIH1cblxuICAgIC8vIFBhZCBmaWVsZFxuICAgIHRoaXMuX2ZpZWxkWzJdID0gbmRhcnJheSh0aGlzLl9maWVsZFsyXS5kYXRhLCBbZmllbGQuc2hhcGVbMF0gKyAyLCBmaWVsZC5zaGFwZVsxXSArIDJdKVxuICAgIHRoaXMucGFkRmllbGQodGhpcy5fZmllbGRbMl0sIGZpZWxkKVxuXG4gICAgLy8gU2F2ZSBzaGFwZSBvZiBmaWVsZFxuICAgIHRoaXMuc2hhcGUgPSBmaWVsZC5zaGFwZS5zbGljZSgpXG4gICAgdmFyIHNoYXBlID0gdGhpcy5zaGFwZVxuXG4gICAgLy8gUmVzaXplIGNvb3JkaW5hdGUgZmllbGRzIGlmIG5lY2Vzc2FyeVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMjsgKytpKSB7XG4gICAgICBpZiAodGhpcy5fZmllbGRbMl0uc2l6ZSA+IHRoaXMuX2ZpZWxkW2ldLmRhdGEubGVuZ3RoKSB7XG4gICAgICAgIHBvb2wuZnJlZUZsb2F0KHRoaXMuX2ZpZWxkW2ldLmRhdGEpXG4gICAgICAgIHRoaXMuX2ZpZWxkW2ldLmRhdGEgPSBwb29sLm1hbGxvY0Zsb2F0KHRoaXMuX2ZpZWxkWzJdLnNpemUpXG4gICAgICB9XG4gICAgICB0aGlzLl9maWVsZFtpXSA9IG5kYXJyYXkodGhpcy5fZmllbGRbaV0uZGF0YSwgW3NoYXBlWzBdICsgMiwgc2hhcGVbMV0gKyAyXSlcbiAgICB9XG5cbiAgICAvLyBHZW5lcmF0ZSB4L3kgY29vcmRpbmF0ZXNcbiAgICBpZiAocGFyYW1zLmNvb3Jkcykge1xuICAgICAgdmFyIGNvb3JkcyA9IHBhcmFtcy5jb29yZHNcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShjb29yZHMpIHx8IGNvb3Jkcy5sZW5ndGggIT09IDMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1zdXJmYWNlOiBpbnZhbGlkIGNvb3JkaW5hdGVzIGZvciB4L3knKVxuICAgICAgfVxuICAgICAgZm9yIChpID0gMDsgaSA8IDI7ICsraSkge1xuICAgICAgICB2YXIgY29vcmQgPSBjb29yZHNbaV1cbiAgICAgICAgZm9yIChqID0gMDsgaiA8IDI7ICsraikge1xuICAgICAgICAgIGlmIChjb29yZC5zaGFwZVtqXSAhPT0gc2hhcGVbal0pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtc3VyZmFjZTogY29vcmRzIGhhdmUgaW5jb3JyZWN0IHNoYXBlJylcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYWRGaWVsZCh0aGlzLl9maWVsZFtpXSwgY29vcmQpXG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChwYXJhbXMudGlja3MpIHtcbiAgICAgIHZhciB0aWNrcyA9IHBhcmFtcy50aWNrc1xuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHRpY2tzKSB8fCB0aWNrcy5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1zdXJmYWNlOiBpbnZhbGlkIHRpY2tzJylcbiAgICAgIH1cbiAgICAgIGZvciAoaSA9IDA7IGkgPCAyOyArK2kpIHtcbiAgICAgICAgdmFyIHRpY2sgPSB0aWNrc1tpXVxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh0aWNrKSB8fCB0aWNrLmxlbmd0aCkge1xuICAgICAgICAgIHRpY2sgPSBuZGFycmF5KHRpY2spXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRpY2suc2hhcGVbMF0gIT09IHNoYXBlW2ldKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC1zdXJmYWNlOiBpbnZhbGlkIHRpY2sgbGVuZ3RoJylcbiAgICAgICAgfVxuICAgICAgICAvLyBNYWtlIGEgY29weSB2aWV3IG9mIHRoZSB0aWNrIGFycmF5XG4gICAgICAgIHZhciB0aWNrMiA9IG5kYXJyYXkodGljay5kYXRhLCBzaGFwZSlcbiAgICAgICAgdGljazIuc3RyaWRlW2ldID0gdGljay5zdHJpZGVbMF1cbiAgICAgICAgdGljazIuc3RyaWRlW2kgXiAxXSA9IDBcblxuICAgICAgICAvLyBGaWxsIGluIGZpZWxkIGFycmF5XG4gICAgICAgIHRoaXMucGFkRmllbGQodGhpcy5fZmllbGRbaV0sIHRpY2syKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgMjsgKytpKSB7XG4gICAgICAgIHZhciBvZmZzZXQgPSBbMCwgMF1cbiAgICAgICAgb2Zmc2V0W2ldID0gMVxuICAgICAgICB0aGlzLl9maWVsZFtpXSA9IG5kYXJyYXkodGhpcy5fZmllbGRbaV0uZGF0YSwgW3NoYXBlWzBdICsgMiwgc2hhcGVbMV0gKyAyXSwgb2Zmc2V0LCAwKVxuICAgICAgfVxuICAgICAgdGhpcy5fZmllbGRbMF0uc2V0KDAsIDAsIDApXG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHNoYXBlWzBdOyArK2opIHtcbiAgICAgICAgdGhpcy5fZmllbGRbMF0uc2V0KGogKyAxLCAwLCBqKVxuICAgICAgfVxuICAgICAgdGhpcy5fZmllbGRbMF0uc2V0KHNoYXBlWzBdICsgMSwgMCwgc2hhcGVbMF0gLSAxKVxuICAgICAgdGhpcy5fZmllbGRbMV0uc2V0KDAsIDAsIDApXG4gICAgICBmb3IgKGogPSAwOyBqIDwgc2hhcGVbMV07ICsraikge1xuICAgICAgICB0aGlzLl9maWVsZFsxXS5zZXQoMCwgaiArIDEsIGopXG4gICAgICB9XG4gICAgICB0aGlzLl9maWVsZFsxXS5zZXQoMCwgc2hhcGVbMV0gKyAxLCBzaGFwZVsxXSAtIDEpXG4gICAgfVxuXG4gICAgLy8gU2F2ZSBzaGFwZVxuICAgIHZhciBmaWVsZHMgPSB0aGlzLl9maWVsZFxuXG4gICAgLy8gQ29tcHV0ZSBzdXJmYWNlIG5vcm1hbHNcbiAgICB2YXIgZGZpZWxkcyA9IG5kYXJyYXkocG9vbC5tYWxsb2NGbG9hdChmaWVsZHNbMl0uc2l6ZSAqIDMgKiAyKSwgWzMsIHNoYXBlWzBdICsgMiwgc2hhcGVbMV0gKyAyLCAyXSlcbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICBncmFkaWVudChkZmllbGRzLnBpY2soaSksIGZpZWxkc1tpXSwgJ21pcnJvcicpXG4gICAgfVxuICAgIHZhciBub3JtYWxzID0gbmRhcnJheShwb29sLm1hbGxvY0Zsb2F0KGZpZWxkc1syXS5zaXplICogMyksIFtzaGFwZVswXSArIDIsIHNoYXBlWzFdICsgMiwgM10pXG4gICAgZm9yIChpID0gMDsgaSA8IHNoYXBlWzBdICsgMjsgKytpKSB7XG4gICAgICBmb3IgKGogPSAwOyBqIDwgc2hhcGVbMV0gKyAyOyArK2opIHtcbiAgICAgICAgdmFyIGR4ZHUgPSBkZmllbGRzLmdldCgwLCBpLCBqLCAwKVxuICAgICAgICB2YXIgZHhkdiA9IGRmaWVsZHMuZ2V0KDAsIGksIGosIDEpXG4gICAgICAgIHZhciBkeWR1ID0gZGZpZWxkcy5nZXQoMSwgaSwgaiwgMClcbiAgICAgICAgdmFyIGR5ZHYgPSBkZmllbGRzLmdldCgxLCBpLCBqLCAxKVxuICAgICAgICB2YXIgZHpkdSA9IGRmaWVsZHMuZ2V0KDIsIGksIGosIDApXG4gICAgICAgIHZhciBkemR2ID0gZGZpZWxkcy5nZXQoMiwgaSwgaiwgMSlcblxuICAgICAgICB2YXIgbnggPSBkeWR1ICogZHpkdiAtIGR5ZHYgKiBkemR1XG4gICAgICAgIHZhciBueSA9IGR6ZHUgKiBkeGR2IC0gZHpkdiAqIGR4ZHVcbiAgICAgICAgdmFyIG56ID0gZHhkdSAqIGR5ZHYgLSBkeGR2ICogZHlkdVxuXG4gICAgICAgIHZhciBubCA9IE1hdGguc3FydChueCAqIG54ICsgbnkgKiBueSArIG56ICogbnopXG4gICAgICAgIGlmIChubCA8IDFlLTgpIHtcbiAgICAgICAgICBubCA9IE1hdGgubWF4KE1hdGguYWJzKG54KSwgTWF0aC5hYnMobnkpLCBNYXRoLmFicyhueikpXG4gICAgICAgICAgaWYgKG5sIDwgMWUtOCkge1xuICAgICAgICAgICAgbnogPSAxLjBcbiAgICAgICAgICAgIG55ID0gbnggPSAwLjBcbiAgICAgICAgICAgIG5sID0gMS4wXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5sID0gMS4wIC8gbmxcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbmwgPSAxLjAgLyBNYXRoLnNxcnQobmwpXG4gICAgICAgIH1cblxuICAgICAgICBub3JtYWxzLnNldChpLCBqLCAwLCBueCAqIG5sKVxuICAgICAgICBub3JtYWxzLnNldChpLCBqLCAxLCBueSAqIG5sKVxuICAgICAgICBub3JtYWxzLnNldChpLCBqLCAyLCBueiAqIG5sKVxuICAgICAgfVxuICAgIH1cbiAgICBwb29sLmZyZWUoZGZpZWxkcy5kYXRhKVxuXG4gICAgLy8gSW5pdGlhbGl6ZSBzdXJmYWNlXG4gICAgdmFyIGxvID0gWyBJbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5IF1cbiAgICB2YXIgaGkgPSBbIC1JbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHkgXVxuICAgIHZhciBsb19pbnRlbnNpdHkgPSBJbmZpbml0eVxuICAgIHZhciBoaV9pbnRlbnNpdHkgPSAtSW5maW5pdHlcbiAgICB2YXIgY291bnQgPSAoc2hhcGVbMF0gLSAxKSAqIChzaGFwZVsxXSAtIDEpICogNlxuICAgIHZhciB0dmVydHMgPSBwb29sLm1hbGxvY0Zsb2F0KGJpdHMubmV4dFBvdzIoMTAgKiBjb3VudCkpXG4gICAgdmFyIHRwdHIgPSAwXG4gICAgdmFyIHZlcnRleENvdW50ID0gMFxuICAgIGZvciAoaSA9IDA7IGkgPCBzaGFwZVswXSAtIDE7ICsraSkge1xuICAgICAgal9sb29wOlxuICAgICAgZm9yIChqID0gMDsgaiA8IHNoYXBlWzFdIC0gMTsgKytqKSB7XG4gICAgICAgIC8vIFRlc3QgZm9yIE5hTnNcbiAgICAgICAgZm9yICh2YXIgZHggPSAwOyBkeCA8IDI7ICsrZHgpIHtcbiAgICAgICAgICBmb3IgKHZhciBkeSA9IDA7IGR5IDwgMjsgKytkeSkge1xuICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCAzOyArK2spIHtcbiAgICAgICAgICAgICAgdmFyIGYgPSB0aGlzLl9maWVsZFtrXS5nZXQoMSArIGkgKyBkeCwgMSArIGogKyBkeSlcbiAgICAgICAgICAgICAgaWYgKGlzTmFOKGYpIHx8ICFpc0Zpbml0ZShmKSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlIGpfbG9vcFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAoayA9IDA7IGsgPCA2OyArK2spIHtcbiAgICAgICAgICB2YXIgciA9IGkgKyBRVUFEW2tdWzBdXG4gICAgICAgICAgdmFyIGMgPSBqICsgUVVBRFtrXVsxXVxuXG4gICAgICAgICAgdmFyIHR4ID0gdGhpcy5fZmllbGRbMF0uZ2V0KHIgKyAxLCBjICsgMSlcbiAgICAgICAgICB2YXIgdHkgPSB0aGlzLl9maWVsZFsxXS5nZXQociArIDEsIGMgKyAxKVxuICAgICAgICAgIGYgPSAgICAgIHRoaXMuX2ZpZWxkWzJdLmdldChyICsgMSwgYyArIDEpXG5cbiAgICAgICAgICBueCA9IG5vcm1hbHMuZ2V0KHIgKyAxLCBjICsgMSwgMClcbiAgICAgICAgICBueSA9IG5vcm1hbHMuZ2V0KHIgKyAxLCBjICsgMSwgMSlcbiAgICAgICAgICBueiA9IG5vcm1hbHMuZ2V0KHIgKyAxLCBjICsgMSwgMilcblxuICAgICAgICAgIGlmIChwYXJhbXMuaW50ZW5zaXR5KSB7XG4gICAgICAgICAgICB2ZiA9IHBhcmFtcy5pbnRlbnNpdHkuZ2V0KHIsIGMpXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIHZmID0gKHBhcmFtcy5pbnRlbnNpdHkpID9cbiAgICAgICAgICAgIHBhcmFtcy5pbnRlbnNpdHkuZ2V0KHIsIGMpIDpcbiAgICAgICAgICAgIGYgKyB0aGlzLm9iamVjdE9mZnNldFsyXTtcblxuICAgICAgICAgIHR2ZXJ0c1t0cHRyKytdID0gclxuICAgICAgICAgIHR2ZXJ0c1t0cHRyKytdID0gY1xuICAgICAgICAgIHR2ZXJ0c1t0cHRyKytdID0gdHhcbiAgICAgICAgICB0dmVydHNbdHB0cisrXSA9IHR5XG4gICAgICAgICAgdHZlcnRzW3RwdHIrK10gPSBmXG4gICAgICAgICAgdHZlcnRzW3RwdHIrK10gPSAwXG4gICAgICAgICAgdHZlcnRzW3RwdHIrK10gPSB2ZlxuICAgICAgICAgIHR2ZXJ0c1t0cHRyKytdID0gbnhcbiAgICAgICAgICB0dmVydHNbdHB0cisrXSA9IG55XG4gICAgICAgICAgdHZlcnRzW3RwdHIrK10gPSBuelxuXG4gICAgICAgICAgbG9bMF0gPSBNYXRoLm1pbihsb1swXSwgdHggKyB0aGlzLm9iamVjdE9mZnNldFswXSlcbiAgICAgICAgICBsb1sxXSA9IE1hdGgubWluKGxvWzFdLCB0eSArIHRoaXMub2JqZWN0T2Zmc2V0WzFdKVxuICAgICAgICAgIGxvWzJdID0gTWF0aC5taW4obG9bMl0sIGYgICsgdGhpcy5vYmplY3RPZmZzZXRbMl0pXG4gICAgICAgICAgbG9faW50ZW5zaXR5ID0gTWF0aC5taW4obG9faW50ZW5zaXR5LCB2ZilcblxuICAgICAgICAgIGhpWzBdID0gTWF0aC5tYXgoaGlbMF0sIHR4ICsgdGhpcy5vYmplY3RPZmZzZXRbMF0pXG4gICAgICAgICAgaGlbMV0gPSBNYXRoLm1heChoaVsxXSwgdHkgKyB0aGlzLm9iamVjdE9mZnNldFsxXSlcbiAgICAgICAgICBoaVsyXSA9IE1hdGgubWF4KGhpWzJdLCBmICArIHRoaXMub2JqZWN0T2Zmc2V0WzJdKVxuICAgICAgICAgIGhpX2ludGVuc2l0eSA9IE1hdGgubWF4KGhpX2ludGVuc2l0eSwgdmYpXG5cbiAgICAgICAgICB2ZXJ0ZXhDb3VudCArPSAxXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocGFyYW1zLmludGVuc2l0eUJvdW5kcykge1xuICAgICAgbG9faW50ZW5zaXR5ID0gK3BhcmFtcy5pbnRlbnNpdHlCb3VuZHNbMF1cbiAgICAgIGhpX2ludGVuc2l0eSA9ICtwYXJhbXMuaW50ZW5zaXR5Qm91bmRzWzFdXG4gICAgfVxuXG4gICAgLy8gU2NhbGUgYWxsIHZlcnRleCBpbnRlbnNpdGllc1xuICAgIGZvciAoaSA9IDY7IGkgPCB0cHRyOyBpICs9IDEwKSB7XG4gICAgICB0dmVydHNbaV0gPSAodHZlcnRzW2ldIC0gbG9faW50ZW5zaXR5KSAvIChoaV9pbnRlbnNpdHkgLSBsb19pbnRlbnNpdHkpXG4gICAgfVxuXG4gICAgdGhpcy5fdmVydGV4Q291bnQgPSB2ZXJ0ZXhDb3VudFxuICAgIHRoaXMuX2Nvb3JkaW5hdGVCdWZmZXIudXBkYXRlKHR2ZXJ0cy5zdWJhcnJheSgwLCB0cHRyKSlcbiAgICBwb29sLmZyZWVGbG9hdCh0dmVydHMpXG4gICAgcG9vbC5mcmVlKG5vcm1hbHMuZGF0YSlcblxuICAgIC8vIFVwZGF0ZSBib3VuZHNcbiAgICB0aGlzLmJvdW5kcyA9IFtsbywgaGldXG5cbiAgICAvLyBTYXZlIGludGVuc2l0eVxuICAgIHRoaXMuaW50ZW5zaXR5ID0gcGFyYW1zLmludGVuc2l0eSB8fCB0aGlzLl9maWVsZFsyXVxuXG4gICAgaWYodGhpcy5pbnRlbnNpdHlCb3VuZHNbMF0gIT09IGxvX2ludGVuc2l0eSB8fCB0aGlzLmludGVuc2l0eUJvdW5kc1sxXSAhPT0gaGlfaW50ZW5zaXR5KSB7XG4gICAgICAgIGxldmVsc0NoYW5nZWQgPSB0cnVlXG4gICAgfVxuXG4gICAgLy8gU2F2ZSBpbnRlbnNpdHkgYm91bmRcbiAgICB0aGlzLmludGVuc2l0eUJvdW5kcyA9IFtsb19pbnRlbnNpdHksIGhpX2ludGVuc2l0eV1cbiAgfVxuXG4gIC8vIFVwZGF0ZSBsZXZlbCBjcm9zc2luZ3NcbiAgaWYgKCdsZXZlbHMnIGluIHBhcmFtcykge1xuICAgIHZhciBsZXZlbHMgPSBwYXJhbXMubGV2ZWxzXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGxldmVsc1swXSkpIHtcbiAgICAgIGxldmVscyA9IFsgW10sIFtdLCBsZXZlbHMgXVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXZlbHMgPSBsZXZlbHMuc2xpY2UoKVxuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICBsZXZlbHNbaV0gPSBsZXZlbHNbaV0uc2xpY2UoKVxuICAgICAgbGV2ZWxzW2ldLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEgLSBiXG4gICAgICB9KVxuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICBmb3IgKGogPSAwOyBqIDwgbGV2ZWxzW2ldLmxlbmd0aDsgKytqKSB7XG4gICAgICAgIGxldmVsc1tpXVtqXSAtPSB0aGlzLm9iamVjdE9mZnNldFtpXVxuICAgICAgfVxuICAgIH1cbiAgICBjaGFuZ2VfdGVzdDpcbiAgICBmb3IgKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICBpZiAobGV2ZWxzW2ldLmxlbmd0aCAhPT0gdGhpcy5jb250b3VyTGV2ZWxzW2ldLmxlbmd0aCkge1xuICAgICAgICBsZXZlbHNDaGFuZ2VkID0gdHJ1ZVxuICAgICAgICBicmVha1xuICAgICAgfVxuICAgICAgZm9yIChqID0gMDsgaiA8IGxldmVsc1tpXS5sZW5ndGg7ICsraikge1xuICAgICAgICBpZiAobGV2ZWxzW2ldW2pdICE9PSB0aGlzLmNvbnRvdXJMZXZlbHNbaV1bal0pIHtcbiAgICAgICAgICBsZXZlbHNDaGFuZ2VkID0gdHJ1ZVxuICAgICAgICAgIGJyZWFrIGNoYW5nZV90ZXN0XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5jb250b3VyTGV2ZWxzID0gbGV2ZWxzXG4gIH1cblxuICBpZiAobGV2ZWxzQ2hhbmdlZCkge1xuICAgIGZpZWxkcyA9IHRoaXMuX2ZpZWxkXG4gICAgc2hhcGUgPSB0aGlzLnNoYXBlXG5cbiAgICAvLyBVcGRhdGUgY29udG91ciBsaW5lc1xuICAgIHZhciBjb250b3VyVmVydHMgPSBbXVxuXG4gICAgZm9yICh2YXIgZGltID0gMDsgZGltIDwgMzsgKytkaW0pIHtcbiAgICAgIHZhciBjb250b3VyTGV2ZWwgPSB0aGlzLmNvbnRvdXJMZXZlbHNbZGltXVxuXG4gICAgICB2YXIgbGV2ZWxPZmZzZXRzID0gW11cbiAgICAgIHZhciBsZXZlbENvdW50cyA9IFtdXG5cbiAgICAgIHZhciBwYXJ0cyA9IFswLCAwLCAwXVxuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgY29udG91ckxldmVsLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciBncmFwaCA9IHN1cmZhY2VOZXRzKHRoaXMuX2ZpZWxkW2RpbV0sIGNvbnRvdXJMZXZlbFtpXSlcblxuICAgICAgICBsZXZlbE9mZnNldHMucHVzaCgoY29udG91clZlcnRzLmxlbmd0aCAvIDUpIHwgMClcbiAgICAgICAgdmVydGV4Q291bnQgPSAwXG5cbiAgICAgICAgZWRnZV9sb29wOlxuICAgICAgICBmb3IgKGogPSAwOyBqIDwgZ3JhcGguY2VsbHMubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICB2YXIgZSA9IGdyYXBoLmNlbGxzW2pdXG4gICAgICAgICAgZm9yIChrID0gMDsgayA8IDI7ICsraykge1xuICAgICAgICAgICAgdmFyIHAgPSBncmFwaC5wb3NpdGlvbnNbZVtrXV1cblxuICAgICAgICAgICAgdmFyIHggPSBwWzBdXG4gICAgICAgICAgICB2YXIgaXggPSBNYXRoLmZsb29yKHgpIHwgMFxuICAgICAgICAgICAgdmFyIGZ4ID0geCAtIGl4XG5cbiAgICAgICAgICAgIHZhciB5ID0gcFsxXVxuICAgICAgICAgICAgdmFyIGl5ID0gTWF0aC5mbG9vcih5KSB8IDBcbiAgICAgICAgICAgIHZhciBmeSA9IHkgLSBpeVxuXG4gICAgICAgICAgICB2YXIgaG9sZSA9IGZhbHNlXG4gICAgICAgICAgICBheGlzX2xvb3A6XG4gICAgICAgICAgICBmb3IgKHZhciBheGlzID0gMDsgYXhpcyA8IDM7ICsrYXhpcykge1xuICAgICAgICAgICAgICBwYXJ0c1theGlzXSA9IDAuMFxuICAgICAgICAgICAgICB2YXIgaXUgPSAoZGltICsgYXhpcyArIDEpICUgM1xuICAgICAgICAgICAgICBmb3IgKGR4ID0gMDsgZHggPCAyOyArK2R4KSB7XG4gICAgICAgICAgICAgICAgdmFyIHMgPSBkeCA/IGZ4IDogMS4wIC0gZnhcbiAgICAgICAgICAgICAgICByID0gTWF0aC5taW4oTWF0aC5tYXgoaXggKyBkeCwgMCksIHNoYXBlWzBdKSB8IDBcbiAgICAgICAgICAgICAgICBmb3IgKGR5ID0gMDsgZHkgPCAyOyArK2R5KSB7XG4gICAgICAgICAgICAgICAgICB2YXIgdCA9IGR5ID8gZnkgOiAxLjAgLSBmeVxuICAgICAgICAgICAgICAgICAgYyA9IE1hdGgubWluKE1hdGgubWF4KGl5ICsgZHksIDApLCBzaGFwZVsxXSkgfCAwXG5cbiAgICAgICAgICAgICAgICAgIGlmIChheGlzIDwgMikge1xuICAgICAgICAgICAgICAgICAgICBmID0gdGhpcy5fZmllbGRbaXVdLmdldChyLCBjKVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZiA9ICh0aGlzLmludGVuc2l0eS5nZXQociwgYykgLSB0aGlzLmludGVuc2l0eUJvdW5kc1swXSkgLyAodGhpcy5pbnRlbnNpdHlCb3VuZHNbMV0gLSB0aGlzLmludGVuc2l0eUJvdW5kc1swXSlcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGlmICghaXNGaW5pdGUoZikgfHwgaXNOYU4oZikpIHtcbiAgICAgICAgICAgICAgICAgICAgaG9sZSA9IHRydWVcbiAgICAgICAgICAgICAgICAgICAgYnJlYWsgYXhpc19sb29wXG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIHZhciB3ID0gcyAqIHRcbiAgICAgICAgICAgICAgICAgIHBhcnRzW2F4aXNdICs9IHcgKiBmXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaG9sZSkge1xuICAgICAgICAgICAgICBjb250b3VyVmVydHMucHVzaChcbiAgICAgICAgICAgICAgICBwYXJ0c1swXSxcbiAgICAgICAgICAgICAgICBwYXJ0c1sxXSxcbiAgICAgICAgICAgICAgICBwWzBdLFxuICAgICAgICAgICAgICAgIHBbMV0sXG4gICAgICAgICAgICAgICAgcGFydHNbMl1cbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICB2ZXJ0ZXhDb3VudCArPSAxXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoayA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB3ZSBhbHJlYWR5IGFkZGVkIGZpcnN0IGVkZ2UsIHBvcCBvZmYgdmVydHNcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBsID0gMDsgbCA8IDU7ICsrbCkge1xuICAgICAgICAgICAgICAgICAgY29udG91clZlcnRzLnBvcCgpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZlcnRleENvdW50IC09IDFcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjb250aW51ZSBlZGdlX2xvb3BcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV2ZWxDb3VudHMucHVzaCh2ZXJ0ZXhDb3VudClcbiAgICAgIH1cblxuICAgICAgLy8gU3RvcmUgcmVzdWx0c1xuICAgICAgdGhpcy5fY29udG91ck9mZnNldHNbZGltXSA9IGxldmVsT2Zmc2V0c1xuICAgICAgdGhpcy5fY29udG91ckNvdW50c1tkaW1dID0gbGV2ZWxDb3VudHNcblxuICAgIH1cblxuICAgIHZhciBmbG9hdEJ1ZmZlciA9IHBvb2wubWFsbG9jRmxvYXQoY29udG91clZlcnRzLmxlbmd0aClcbiAgICBmb3IgKGkgPSAwOyBpIDwgY29udG91clZlcnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICBmbG9hdEJ1ZmZlcltpXSA9IGNvbnRvdXJWZXJ0c1tpXVxuICAgIH1cbiAgICB0aGlzLl9jb250b3VyQnVmZmVyLnVwZGF0ZShmbG9hdEJ1ZmZlcilcbiAgICBwb29sLmZyZWVGbG9hdChmbG9hdEJ1ZmZlcilcbiAgfVxuXG4gIGlmIChwYXJhbXMuY29sb3JtYXApIHtcbiAgICB0aGlzLl9jb2xvck1hcC5zZXRQaXhlbHMoZ2VuQ29sb3JtYXAocGFyYW1zLmNvbG9ybWFwKSlcbiAgfVxufVxuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLl9zaGFkZXIuZGlzcG9zZSgpXG4gIHRoaXMuX3Zhby5kaXNwb3NlKClcbiAgdGhpcy5fY29vcmRpbmF0ZUJ1ZmZlci5kaXNwb3NlKClcbiAgdGhpcy5fY29sb3JNYXAuZGlzcG9zZSgpXG4gIHRoaXMuX2NvbnRvdXJCdWZmZXIuZGlzcG9zZSgpXG4gIHRoaXMuX2NvbnRvdXJWQU8uZGlzcG9zZSgpXG4gIHRoaXMuX2NvbnRvdXJTaGFkZXIuZGlzcG9zZSgpXG4gIHRoaXMuX2NvbnRvdXJQaWNrU2hhZGVyLmRpc3Bvc2UoKVxuICB0aGlzLl9keW5hbWljQnVmZmVyLmRpc3Bvc2UoKVxuICB0aGlzLl9keW5hbWljVkFPLmRpc3Bvc2UoKVxuICBmb3IgKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgIHBvb2wuZnJlZUZsb2F0KHRoaXMuX2ZpZWxkW2ldLmRhdGEpXG4gIH1cbn1cblxucHJvdG8uaGlnaGxpZ2h0ID0gZnVuY3Rpb24gKHNlbGVjdGlvbikge1xuICB2YXIgaVxuXG4gIGlmICghc2VsZWN0aW9uKSB7XG4gICAgdGhpcy5fZHluYW1pY0NvdW50cyA9IFswLCAwLCAwXVxuICAgIHRoaXMuZHlhbmFtaWNMZXZlbCA9IFtOYU4sIE5hTiwgTmFOXVxuICAgIHRoaXMuaGlnaGxpZ2h0TGV2ZWwgPSBbLTEsIC0xLCAtMV1cbiAgICByZXR1cm5cbiAgfVxuXG4gIGZvciAoaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICBpZiAodGhpcy5lbmFibGVIaWdobGlnaHRbaV0pIHtcbiAgICAgIHRoaXMuaGlnaGxpZ2h0TGV2ZWxbaV0gPSBzZWxlY3Rpb24ubGV2ZWxbaV1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5oaWdobGlnaHRMZXZlbFtpXSA9IC0xXG4gICAgfVxuICB9XG5cbiAgdmFyIGxldmVsc1xuICBpZiAodGhpcy5zbmFwVG9EYXRhKSB7XG4gICAgbGV2ZWxzID0gc2VsZWN0aW9uLmRhdGFDb29yZGluYXRlXG4gIH0gZWxzZSB7XG4gICAgbGV2ZWxzID0gc2VsZWN0aW9uLnBvc2l0aW9uXG4gIH1cbiAgZm9yIChpID0gMDsgaSA8IDM7ICsraSkge1xuICAgIGxldmVsc1tpXSAtPSB0aGlzLm9iamVjdE9mZnNldFtpXVxuICB9XG4gIGlmICgoIXRoaXMuZW5hYmxlRHluYW1pY1swXSB8fCBsZXZlbHNbMF0gPT09IHRoaXMuZHluYW1pY0xldmVsWzBdKSAmJlxuICAgICghdGhpcy5lbmFibGVEeW5hbWljWzFdIHx8IGxldmVsc1sxXSA9PT0gdGhpcy5keW5hbWljTGV2ZWxbMV0pICYmXG4gICAgKCF0aGlzLmVuYWJsZUR5bmFtaWNbMl0gfHwgbGV2ZWxzWzJdID09PSB0aGlzLmR5bmFtaWNMZXZlbFsyXSkpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIHZhciB2ZXJ0ZXhDb3VudCA9IDBcbiAgdmFyIHNoYXBlID0gdGhpcy5zaGFwZVxuICB2YXIgc2NyYXRjaEJ1ZmZlciA9IHBvb2wubWFsbG9jRmxvYXQoMTIgKiBzaGFwZVswXSAqIHNoYXBlWzFdKVxuXG4gIGZvciAodmFyIGQgPSAwOyBkIDwgMzsgKytkKSB7XG4gICAgaWYgKCF0aGlzLmVuYWJsZUR5bmFtaWNbZF0pIHtcbiAgICAgIHRoaXMuZHluYW1pY0xldmVsW2RdID0gTmFOXG4gICAgICB0aGlzLl9keW5hbWljQ291bnRzW2RdID0gMFxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICB0aGlzLmR5bmFtaWNMZXZlbFtkXSA9IGxldmVsc1tkXVxuXG4gICAgdmFyIHUgPSAoZCArIDEpICUgM1xuICAgIHZhciB2ID0gKGQgKyAyKSAlIDNcblxuICAgIHZhciBmID0gdGhpcy5fZmllbGRbZF1cbiAgICB2YXIgZyA9IHRoaXMuX2ZpZWxkW3VdXG4gICAgdmFyIGggPSB0aGlzLl9maWVsZFt2XVxuXG4gICAgdmFyIGdyYXBoID0gc3VyZmFjZU5ldHMoZiwgbGV2ZWxzW2RdKVxuICAgIHZhciBlZGdlcyA9IGdyYXBoLmNlbGxzXG4gICAgdmFyIHBvc2l0aW9ucyA9IGdyYXBoLnBvc2l0aW9uc1xuXG4gICAgdGhpcy5fZHluYW1pY09mZnNldHNbZF0gPSB2ZXJ0ZXhDb3VudFxuXG4gICAgZm9yIChpID0gMDsgaSA8IGVkZ2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgZSA9IGVkZ2VzW2ldXG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IDI7ICsraikge1xuICAgICAgICB2YXIgcCA9IHBvc2l0aW9uc1tlW2pdXVxuXG4gICAgICAgIHZhciB4ID0gK3BbMF1cbiAgICAgICAgdmFyIGl4ID0geCB8IDBcbiAgICAgICAgdmFyIGp4ID0gTWF0aC5taW4oaXggKyAxLCBzaGFwZVswXSkgfCAwXG4gICAgICAgIHZhciBmeCA9IHggLSBpeFxuICAgICAgICB2YXIgaHggPSAxLjAgLSBmeFxuXG4gICAgICAgIHZhciB5ID0gK3BbMV1cbiAgICAgICAgdmFyIGl5ID0geSB8IDBcbiAgICAgICAgdmFyIGp5ID0gTWF0aC5taW4oaXkgKyAxLCBzaGFwZVsxXSkgfCAwXG4gICAgICAgIHZhciBmeSA9IHkgLSBpeVxuICAgICAgICB2YXIgaHkgPSAxLjAgLSBmeVxuXG4gICAgICAgIHZhciB3MDAgPSBoeCAqIGh5XG4gICAgICAgIHZhciB3MDEgPSBoeCAqIGZ5XG4gICAgICAgIHZhciB3MTAgPSBmeCAqIGh5XG4gICAgICAgIHZhciB3MTEgPSBmeCAqIGZ5XG5cbiAgICAgICAgdmFyIGN1ID0gdzAwICogZy5nZXQoaXgsIGl5KSArXG4gICAgICAgICAgdzAxICogZy5nZXQoaXgsIGp5KSArXG4gICAgICAgICAgdzEwICogZy5nZXQoangsIGl5KSArXG4gICAgICAgICAgdzExICogZy5nZXQoangsIGp5KVxuXG4gICAgICAgIHZhciBjdiA9IHcwMCAqIGguZ2V0KGl4LCBpeSkgK1xuICAgICAgICAgIHcwMSAqIGguZ2V0KGl4LCBqeSkgK1xuICAgICAgICAgIHcxMCAqIGguZ2V0KGp4LCBpeSkgK1xuICAgICAgICAgIHcxMSAqIGguZ2V0KGp4LCBqeSlcblxuICAgICAgICBpZiAoaXNOYU4oY3UpIHx8IGlzTmFOKGN2KSkge1xuICAgICAgICAgIGlmIChqKSB7XG4gICAgICAgICAgICB2ZXJ0ZXhDb3VudCAtPSAxXG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIH1cblxuICAgICAgICBzY3JhdGNoQnVmZmVyWzIgKiB2ZXJ0ZXhDb3VudCArIDBdID0gY3VcbiAgICAgICAgc2NyYXRjaEJ1ZmZlclsyICogdmVydGV4Q291bnQgKyAxXSA9IGN2XG5cbiAgICAgICAgdmVydGV4Q291bnQgKz0gMVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX2R5bmFtaWNDb3VudHNbZF0gPSB2ZXJ0ZXhDb3VudCAtIHRoaXMuX2R5bmFtaWNPZmZzZXRzW2RdXG4gIH1cblxuICB0aGlzLl9keW5hbWljQnVmZmVyLnVwZGF0ZShzY3JhdGNoQnVmZmVyLnN1YmFycmF5KDAsIDIgKiB2ZXJ0ZXhDb3VudCkpXG4gIHBvb2wuZnJlZUZsb2F0KHNjcmF0Y2hCdWZmZXIpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVN1cmZhY2VQbG90IChwYXJhbXMpIHtcbiAgdmFyIGdsID0gcGFyYW1zLmdsXG5cbiAgdmFyIHNoYWRlciA9IGNyZWF0ZVNoYWRlcihnbClcbiAgdmFyIHBpY2tTaGFkZXIgPSBjcmVhdGVQaWNrU2hhZGVyKGdsKVxuICB2YXIgY29udG91clNoYWRlciA9IGNyZWF0ZUNvbnRvdXJTaGFkZXIoZ2wpXG4gIHZhciBjb250b3VyUGlja1NoYWRlciA9IGNyZWF0ZVBpY2tDb250b3VyU2hhZGVyKGdsKVxuXG4gIHZhciBjb29yZGluYXRlQnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgdmFvID0gY3JlYXRlVkFPKGdsLCBbXG4gICAgeyBidWZmZXI6IGNvb3JkaW5hdGVCdWZmZXIsXG4gICAgICBzaXplOiA0LFxuICAgICAgc3RyaWRlOiBTVVJGQUNFX1ZFUlRFWF9TSVpFLFxuICAgICAgb2Zmc2V0OiAwXG4gICAgfSxcbiAgICB7IGJ1ZmZlcjogY29vcmRpbmF0ZUJ1ZmZlcixcbiAgICAgIHNpemU6IDMsXG4gICAgICBzdHJpZGU6IFNVUkZBQ0VfVkVSVEVYX1NJWkUsXG4gICAgICBvZmZzZXQ6IDE2XG4gICAgfSxcbiAgICB7XG4gICAgICBidWZmZXI6IGNvb3JkaW5hdGVCdWZmZXIsXG4gICAgICBzaXplOiAzLFxuICAgICAgc3RyaWRlOiBTVVJGQUNFX1ZFUlRFWF9TSVpFLFxuICAgICAgb2Zmc2V0OiAyOFxuICAgIH1cbiAgXSlcblxuICB2YXIgY29udG91ckJ1ZmZlciA9IGNyZWF0ZUJ1ZmZlcihnbClcbiAgdmFyIGNvbnRvdXJWQU8gPSBjcmVhdGVWQU8oZ2wsIFtcbiAgICB7XG4gICAgICBidWZmZXI6IGNvbnRvdXJCdWZmZXIsXG4gICAgICBzaXplOiA0LFxuICAgICAgc3RyaWRlOiAyMCxcbiAgICAgIG9mZnNldDogMFxuICAgIH0sXG4gICAge1xuICAgICAgYnVmZmVyOiBjb250b3VyQnVmZmVyLFxuICAgICAgc2l6ZTogMSxcbiAgICAgIHN0cmlkZTogMjAsXG4gICAgICBvZmZzZXQ6IDE2XG4gICAgfVxuICBdKVxuXG4gIHZhciBkeW5hbWljQnVmZmVyID0gY3JlYXRlQnVmZmVyKGdsKVxuICB2YXIgZHluYW1pY1ZBTyA9IGNyZWF0ZVZBTyhnbCwgW1xuICAgIHtcbiAgICAgIGJ1ZmZlcjogZHluYW1pY0J1ZmZlcixcbiAgICAgIHNpemU6IDIsXG4gICAgICB0eXBlOiBnbC5GTE9BVFxuICAgIH1dKVxuXG4gIHZhciBjbWFwID0gY3JlYXRlVGV4dHVyZShnbCwgMSwgTl9DT0xPUlMsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUpXG4gIGNtYXAubWluRmlsdGVyID0gZ2wuTElORUFSXG4gIGNtYXAubWFnRmlsdGVyID0gZ2wuTElORUFSXG5cbiAgdmFyIHN1cmZhY2UgPSBuZXcgU3VyZmFjZVBsb3QoXG4gICAgZ2wsXG4gICAgWzAsIDBdLCAvLyBzaGFwZVxuICAgIFtbMCwgMCwgMF0sIFswLCAwLCAwXV0sIC8vIGJvdW5kc1xuICAgIHNoYWRlcixcbiAgICBwaWNrU2hhZGVyLFxuICAgIGNvb3JkaW5hdGVCdWZmZXIsXG4gICAgdmFvLFxuICAgIGNtYXAsXG4gICAgY29udG91clNoYWRlcixcbiAgICBjb250b3VyUGlja1NoYWRlcixcbiAgICBjb250b3VyQnVmZmVyLFxuICAgIGNvbnRvdXJWQU8sXG4gICAgZHluYW1pY0J1ZmZlcixcbiAgICBkeW5hbWljVkFPLFxuICAgIFswLCAwLCAwXSAvLyBvYmplY3RPZmZzZXRcbiAgKVxuXG4gIHZhciBucGFyYW1zID0ge1xuICAgIGxldmVsczogW1tdLCBbXSwgW11dXG4gIH1cbiAgZm9yICh2YXIgaWQgaW4gcGFyYW1zKSB7XG4gICAgbnBhcmFtc1tpZF0gPSBwYXJhbXNbaWRdXG4gIH1cbiAgbnBhcmFtcy5jb2xvcm1hcCA9IG5wYXJhbXMuY29sb3JtYXAgfHwgJ2pldCdcblxuICBzdXJmYWNlLnVwZGF0ZShucGFyYW1zKVxuXG4gIHJldHVybiBzdXJmYWNlXG59XG5cbn0se1wiLi9saWIvc2hhZGVyc1wiOjMxNCxcImJpbmFyeS1zZWFyY2gtYm91bmRzXCI6MzE1LFwiYml0LXR3aWRkbGVcIjo5MixcImNvbG9ybWFwXCI6MTI2LFwiZ2wtYnVmZmVyXCI6MjQxLFwiZ2wtbWF0NC9pbnZlcnRcIjoyNjUsXCJnbC1tYXQ0L211bHRpcGx5XCI6MjY3LFwiZ2wtdGV4dHVyZTJkXCI6MzIyLFwiZ2wtdmFvXCI6MzI3LFwibmRhcnJheVwiOjQ1MCxcIm5kYXJyYXktZ3JhZGllbnRcIjo0NDEsXCJuZGFycmF5LW9wc1wiOjQ0NCxcIm5kYXJyYXktcGFja1wiOjQ0NSxcInN1cmZhY2UtbmV0c1wiOjUzMSxcInR5cGVkYXJyYXktcG9vbFwiOjU0NX1dLDMxNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIEZvbnQgPSBfZGVyZXFfKCdjc3MtZm9udCcpXG52YXIgcGljayA9IF9kZXJlcV8oJ3BpY2stYnktYWxpYXMnKVxudmFyIGNyZWF0ZVJlZ2wgPSBfZGVyZXFfKCdyZWdsJylcbnZhciBjcmVhdGVHbCA9IF9kZXJlcV8oJ2dsLXV0aWwvY29udGV4dCcpXG52YXIgV2Vha01hcCA9IF9kZXJlcV8oJ2VzNi13ZWFrLW1hcCcpXG52YXIgcmdiYSA9IF9kZXJlcV8oJ2NvbG9yLW5vcm1hbGl6ZScpXG52YXIgZm9udEF0bGFzID0gX2RlcmVxXygnZm9udC1hdGxhcycpXG52YXIgcG9vbCA9IF9kZXJlcV8oJ3R5cGVkYXJyYXktcG9vbCcpXG52YXIgcGFyc2VSZWN0ID0gX2RlcmVxXygncGFyc2UtcmVjdCcpXG52YXIgaXNPYmogPSBfZGVyZXFfKCdpcy1wbGFpbi1vYmonKVxudmFyIHBhcnNlVW5pdCA9IF9kZXJlcV8oJ3BhcnNlLXVuaXQnKVxudmFyIHB4ID0gX2RlcmVxXygndG8tcHgnKVxudmFyIGtlcm5pbmcgPSBfZGVyZXFfKCdkZXRlY3Qta2VybmluZycpXG52YXIgZXh0ZW5kID0gX2RlcmVxXygnb2JqZWN0LWFzc2lnbicpXG52YXIgbWV0cmljcyA9IF9kZXJlcV8oJ2ZvbnQtbWVhc3VyZScpXG52YXIgZmxhdHRlbiA9IF9kZXJlcV8oJ2ZsYXR0ZW4tdmVydGV4LWRhdGEnKVxudmFyIHJlZiA9IF9kZXJlcV8oJ2JpdC10d2lkZGxlJyk7XG52YXIgbmV4dFBvdzIgPSByZWYubmV4dFBvdzI7XG5cbnZhciBzaGFkZXJDYWNoZSA9IG5ldyBXZWFrTWFwXG5cblxuLy8gU2FmYXJpIGRvZXMgbm90IHN1cHBvcnQgZm9udC1zdHJldGNoXG52YXIgaXNTdHJldGNoU3VwcG9ydGVkID0gZmFsc2VcbmlmIChkb2N1bWVudC5ib2R5KSB7XG4gICAgdmFyIGVsID0gZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSlcbiAgICBlbC5zdHlsZS5mb250ID0gJ2l0YWxpYyBzbWFsbC1jYXBzIGJvbGQgY29uZGVuc2VkIDE2cHgvMiBjdXJzaXZlJ1xuICAgIGlmIChnZXRDb21wdXRlZFN0eWxlKGVsKS5mb250U3RyZXRjaCkge1xuICAgICAgICBpc1N0cmV0Y2hTdXBwb3J0ZWQgPSB0cnVlXG4gICAgfVxuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZWwpXG59XG5cbnZhciBHbFRleHQgPSBmdW5jdGlvbiBHbFRleHQgKG8pIHtcblx0aWYgKGlzUmVnbChvKSkge1xuXHRcdG8gPSB7cmVnbDogb31cblx0XHR0aGlzLmdsID0gby5yZWdsLl9nbFxuXHR9XG5cdGVsc2Uge1xuXHRcdHRoaXMuZ2wgPSBjcmVhdGVHbChvKVxuXHR9XG5cblx0dGhpcy5zaGFkZXIgPSBzaGFkZXJDYWNoZS5nZXQodGhpcy5nbClcblxuXHRpZiAoIXRoaXMuc2hhZGVyKSB7XG5cdFx0dGhpcy5yZWdsID0gby5yZWdsIHx8IGNyZWF0ZVJlZ2woeyBnbDogdGhpcy5nbCB9KVxuXHR9XG5cdGVsc2Uge1xuXHRcdHRoaXMucmVnbCA9IHRoaXMuc2hhZGVyLnJlZ2xcblx0fVxuXG5cdHRoaXMuY2hhckJ1ZmZlciA9IHRoaXMucmVnbC5idWZmZXIoeyB0eXBlOiAndWludDgnLCB1c2FnZTogJ3N0cmVhbScgfSlcblx0dGhpcy5zaXplQnVmZmVyID0gdGhpcy5yZWdsLmJ1ZmZlcih7IHR5cGU6ICdmbG9hdCcsIHVzYWdlOiAnc3RyZWFtJyB9KVxuXG5cdGlmICghdGhpcy5zaGFkZXIpIHtcblx0XHR0aGlzLnNoYWRlciA9IHRoaXMuY3JlYXRlU2hhZGVyKClcblx0XHRzaGFkZXJDYWNoZS5zZXQodGhpcy5nbCwgdGhpcy5zaGFkZXIpXG5cdH1cblxuXHR0aGlzLmJhdGNoID0gW11cblxuXHQvLyBtdWx0aXBsZSBvcHRpb25zIGluaXRpYWwgc3RhdGVcblx0dGhpcy5mb250U2l6ZSA9IFtdXG5cdHRoaXMuZm9udCA9IFtdXG5cdHRoaXMuZm9udEF0bGFzID0gW11cblxuXHR0aGlzLmRyYXcgPSB0aGlzLnNoYWRlci5kcmF3LmJpbmQodGhpcylcblx0dGhpcy5yZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gRklYTUU6IGFkZCBTYWZhcmkgcmVnbCByZXBvcnQgaGVyZTpcblx0XHQvLyBjaGFyQnVmZmVyIGFuZCB3aWR0aCBqdXN0IGRvIG5vdCB0cmlnZ2VyXG5cdFx0dGhpcy5yZWdsLl9yZWZyZXNoKClcblx0XHR0aGlzLmRyYXcodGhpcy5iYXRjaClcblx0fVxuXHR0aGlzLmNhbnZhcyA9IHRoaXMuZ2wuY2FudmFzXG5cblx0dGhpcy51cGRhdGUoaXNPYmoobykgPyBvIDoge30pXG59O1xuXG5HbFRleHQucHJvdG90eXBlLmNyZWF0ZVNoYWRlciA9IGZ1bmN0aW9uIGNyZWF0ZVNoYWRlciAoKSB7XG5cdHZhciByZWdsID0gdGhpcy5yZWdsXG5cblx0Ly8gRklYTUU6IHN0b3JlIDIgc2hhZGVyIHZlcnNpb25zOiB3aXRoIG5vcm1hbCB2aWV3cG9ydCBhbmQgd2l0aG91dFxuXHQvLyBkcmF3IHRleHR1cmUgbWV0aG9kXG5cdHZhciBkcmF3ID0gcmVnbCh7XG5cdFx0YmxlbmQ6IHtcblx0XHRcdGVuYWJsZTogdHJ1ZSxcblx0XHRcdGNvbG9yOiBbMCwwLDAsMV0sXG5cblx0XHRcdGZ1bmM6IHtcblx0XHRcdFx0c3JjUkdCOiAnc3JjIGFscGhhJyxcblx0XHRcdFx0ZHN0UkdCOiAnb25lIG1pbnVzIHNyYyBhbHBoYScsXG5cdFx0XHRcdHNyY0FscGhhOiAnb25lIG1pbnVzIGRzdCBhbHBoYScsXG5cdFx0XHRcdGRzdEFscGhhOiAnb25lJ1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0c3RlbmNpbDoge2VuYWJsZTogZmFsc2V9LFxuXHRcdGRlcHRoOiB7ZW5hYmxlOiBmYWxzZX0sXG5cblx0XHRjb3VudDogcmVnbC5wcm9wKCdjb3VudCcpLFxuXHRcdG9mZnNldDogcmVnbC5wcm9wKCdvZmZzZXQnKSxcblx0XHRhdHRyaWJ1dGVzOiB7XG5cdFx0XHRjaGFyT2Zmc2V0OiB7XG5cdFx0XHRcdG9mZnNldDogNCxcblx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRidWZmZXI6IHJlZ2wudGhpcygnc2l6ZUJ1ZmZlcicpXG5cdFx0XHR9LFxuXHRcdFx0d2lkdGg6IHtcblx0XHRcdFx0b2Zmc2V0OiAwLFxuXHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdGJ1ZmZlcjogcmVnbC50aGlzKCdzaXplQnVmZmVyJylcblx0XHRcdH0sXG5cdFx0XHRjaGFyOiByZWdsLnRoaXMoJ2NoYXJCdWZmZXInKSxcblx0XHRcdHBvc2l0aW9uOiByZWdsLnRoaXMoJ3Bvc2l0aW9uJylcblx0XHR9LFxuXHRcdHVuaWZvcm1zOiB7XG5cdFx0XHRhdGxhc1NpemU6IGZ1bmN0aW9uIChjLCBwKSB7IHJldHVybiBbcC5hdGxhcy53aWR0aCwgcC5hdGxhcy5oZWlnaHRdOyB9LFxuXHRcdFx0YXRsYXNEaW06IGZ1bmN0aW9uIChjLCBwKSB7IHJldHVybiBbcC5hdGxhcy5jb2xzLCBwLmF0bGFzLnJvd3NdOyB9LFxuXHRcdFx0YXRsYXM6IGZ1bmN0aW9uIChjLCBwKSB7IHJldHVybiBwLmF0bGFzLnRleHR1cmU7IH0sXG5cdFx0XHRjaGFyU3RlcDogZnVuY3Rpb24gKGMsIHApIHsgcmV0dXJuIHAuYXRsYXMuc3RlcDsgfSxcblx0XHRcdGVtOiBmdW5jdGlvbiAoYywgcCkgeyByZXR1cm4gcC5hdGxhcy5lbTsgfSxcblx0XHRcdGNvbG9yOiByZWdsLnByb3AoJ2NvbG9yJyksXG5cdFx0XHRvcGFjaXR5OiByZWdsLnByb3AoJ29wYWNpdHknKSxcblx0XHRcdHZpZXdwb3J0OiByZWdsLnRoaXMoJ3ZpZXdwb3J0QXJyYXknKSxcblx0XHRcdHNjYWxlOiByZWdsLnRoaXMoJ3NjYWxlJyksXG5cdFx0XHRhbGlnbjogcmVnbC5wcm9wKCdhbGlnbicpLFxuXHRcdFx0YmFzZWxpbmU6IHJlZ2wucHJvcCgnYmFzZWxpbmUnKSxcblx0XHRcdHRyYW5zbGF0ZTogcmVnbC50aGlzKCd0cmFuc2xhdGUnKSxcblx0XHRcdHBvc2l0aW9uT2Zmc2V0OiByZWdsLnByb3AoJ3Bvc2l0aW9uT2Zmc2V0Jylcblx0XHR9LFxuXHRcdHByaW1pdGl2ZTogJ3BvaW50cycsXG5cdFx0dmlld3BvcnQ6IHJlZ2wudGhpcygndmlld3BvcnQnKSxcblxuXHRcdHZlcnQ6IChcIlxcblxcdFxcdFxcdHByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG5cXHRcXHRcXHRhdHRyaWJ1dGUgZmxvYXQgd2lkdGgsIGNoYXJPZmZzZXQsIGNoYXI7XFxuXFx0XFx0XFx0YXR0cmlidXRlIHZlYzIgcG9zaXRpb247XFxuXFx0XFx0XFx0dW5pZm9ybSBmbG9hdCBmb250U2l6ZSwgY2hhclN0ZXAsIGVtLCBhbGlnbiwgYmFzZWxpbmU7XFxuXFx0XFx0XFx0dW5pZm9ybSB2ZWM0IHZpZXdwb3J0O1xcblxcdFxcdFxcdHVuaWZvcm0gdmVjNCBjb2xvcjtcXG5cXHRcXHRcXHR1bmlmb3JtIHZlYzIgYXRsYXNTaXplLCBhdGxhc0RpbSwgc2NhbGUsIHRyYW5zbGF0ZSwgcG9zaXRpb25PZmZzZXQ7XFxuXFx0XFx0XFx0dmFyeWluZyB2ZWMyIGNoYXJDb29yZCwgY2hhcklkO1xcblxcdFxcdFxcdHZhcnlpbmcgZmxvYXQgY2hhcldpZHRoO1xcblxcdFxcdFxcdHZhcnlpbmcgdmVjNCBmb250Q29sb3I7XFxuXFx0XFx0XFx0dm9pZCBtYWluICgpIHtcXG5cXHRcXHRcXHRcXHRcIiArICghR2xUZXh0Lm5vcm1hbFZpZXdwb3J0ID8gJ3ZlYzIgcG9zaXRpb25PZmZzZXQgPSB2ZWMyKHBvc2l0aW9uT2Zmc2V0LngsLSBwb3NpdGlvbk9mZnNldC55KTsnIDogJycpICsgXCJcXG5cXG5cXHRcXHRcXHRcXHR2ZWMyIG9mZnNldCA9IGZsb29yKGVtICogKHZlYzIoYWxpZ24gKyBjaGFyT2Zmc2V0LCBiYXNlbGluZSlcXG5cXHRcXHRcXHRcXHRcXHQrIHBvc2l0aW9uT2Zmc2V0KSlcXG5cXHRcXHRcXHRcXHRcXHQvICh2aWV3cG9ydC56dyAqIHNjYWxlLnh5KTtcXG5cXG5cXHRcXHRcXHRcXHR2ZWMyIHBvc2l0aW9uID0gKHBvc2l0aW9uICsgdHJhbnNsYXRlKSAqIHNjYWxlO1xcblxcdFxcdFxcdFxcdHBvc2l0aW9uICs9IG9mZnNldCAqIHNjYWxlO1xcblxcblxcdFxcdFxcdFxcdFwiICsgKEdsVGV4dC5ub3JtYWxWaWV3cG9ydCA/ICdwb3NpdGlvbi55ID0gMS4gLSBwb3NpdGlvbi55OycgOiAnJykgKyBcIlxcblxcblxcdFxcdFxcdFxcdGNoYXJDb29yZCA9IHBvc2l0aW9uICogdmlld3BvcnQuencgKyB2aWV3cG9ydC54eTtcXG5cXG5cXHRcXHRcXHRcXHRnbF9Qb3NpdGlvbiA9IHZlYzQocG9zaXRpb24gKiAyLiAtIDEuLCAwLCAxKTtcXG5cXG5cXHRcXHRcXHRcXHRnbF9Qb2ludFNpemUgPSBjaGFyU3RlcDtcXG5cXG5cXHRcXHRcXHRcXHRjaGFySWQueCA9IG1vZChjaGFyLCBhdGxhc0RpbS54KTtcXG5cXHRcXHRcXHRcXHRjaGFySWQueSA9IGZsb29yKGNoYXIgLyBhdGxhc0RpbS54KTtcXG5cXG5cXHRcXHRcXHRcXHRjaGFyV2lkdGggPSB3aWR0aCAqIGVtO1xcblxcblxcdFxcdFxcdFxcdGZvbnRDb2xvciA9IGNvbG9yIC8gMjU1LjtcXG5cXHRcXHRcXHR9XCIpLFxuXG5cdFx0ZnJhZzogXCJcXG5cXHRcXHRcXHRwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuXFx0XFx0XFx0dW5pZm9ybSBzYW1wbGVyMkQgYXRsYXM7XFxuXFx0XFx0XFx0dW5pZm9ybSBmbG9hdCBmb250U2l6ZSwgY2hhclN0ZXAsIG9wYWNpdHk7XFxuXFx0XFx0XFx0dW5pZm9ybSB2ZWMyIGF0bGFzU2l6ZTtcXG5cXHRcXHRcXHR1bmlmb3JtIHZlYzQgdmlld3BvcnQ7XFxuXFx0XFx0XFx0dmFyeWluZyB2ZWM0IGZvbnRDb2xvcjtcXG5cXHRcXHRcXHR2YXJ5aW5nIHZlYzIgY2hhckNvb3JkLCBjaGFySWQ7XFxuXFx0XFx0XFx0dmFyeWluZyBmbG9hdCBjaGFyV2lkdGg7XFxuXFxuXFx0XFx0XFx0ZmxvYXQgbGlnaHRuZXNzKHZlYzQgY29sb3IpIHtcXG5cXHRcXHRcXHRcXHRyZXR1cm4gY29sb3IuciAqIDAuMjk5ICsgY29sb3IuZyAqIDAuNTg3ICsgY29sb3IuYiAqIDAuMTE0O1xcblxcdFxcdFxcdH1cXG5cXG5cXHRcXHRcXHR2b2lkIG1haW4gKCkge1xcblxcdFxcdFxcdFxcdHZlYzIgdXYgPSBnbF9GcmFnQ29vcmQueHkgLSBjaGFyQ29vcmQgKyBjaGFyU3RlcCAqIC41O1xcblxcdFxcdFxcdFxcdGZsb2F0IGhhbGZDaGFyU3RlcCA9IGZsb29yKGNoYXJTdGVwICogLjUgKyAuNSk7XFxuXFxuXFx0XFx0XFx0XFx0Ly8gaW52ZXJ0IHkgYW5kIHNoaWZ0IGJ5IDFweCAoRkYgZXhwZWNpYWxseSBuZWVkcyB0aGF0KVxcblxcdFxcdFxcdFxcdHV2LnkgPSBjaGFyU3RlcCAtIHV2Lnk7XFxuXFxuXFx0XFx0XFx0XFx0Ly8gaWdub3JlIHBvaW50cyBvdXRzaWRlIG9mIGNoYXJhY3RlciBib3VuZGluZyBib3hcXG5cXHRcXHRcXHRcXHRmbG9hdCBoYWxmQ2hhcldpZHRoID0gY2VpbChjaGFyV2lkdGggKiAuNSk7XFxuXFx0XFx0XFx0XFx0aWYgKGZsb29yKHV2LngpID4gaGFsZkNoYXJTdGVwICsgaGFsZkNoYXJXaWR0aCB8fFxcblxcdFxcdFxcdFxcdFxcdGZsb29yKHV2LngpIDwgaGFsZkNoYXJTdGVwIC0gaGFsZkNoYXJXaWR0aCkgcmV0dXJuO1xcblxcblxcdFxcdFxcdFxcdHV2ICs9IGNoYXJJZCAqIGNoYXJTdGVwO1xcblxcdFxcdFxcdFxcdHV2ID0gdXYgLyBhdGxhc1NpemU7XFxuXFxuXFx0XFx0XFx0XFx0dmVjNCBjb2xvciA9IGZvbnRDb2xvcjtcXG5cXHRcXHRcXHRcXHR2ZWM0IG1hc2sgPSB0ZXh0dXJlMkQoYXRsYXMsIHV2KTtcXG5cXG5cXHRcXHRcXHRcXHRmbG9hdCBtYXNrWSA9IGxpZ2h0bmVzcyhtYXNrKTtcXG5cXHRcXHRcXHRcXHQvLyBmbG9hdCBjb2xvclkgPSBsaWdodG5lc3MoY29sb3IpO1xcblxcdFxcdFxcdFxcdGNvbG9yLmEgKj0gbWFza1k7XFxuXFx0XFx0XFx0XFx0Y29sb3IuYSAqPSBvcGFjaXR5O1xcblxcblxcdFxcdFxcdFxcdC8vIGNvbG9yLmEgKz0gLjE7XFxuXFxuXFx0XFx0XFx0XFx0Ly8gYW50aWFsaWFzaW5nLCBzZWUgeWlxIGNvbG9yIHNwYWNlIHktY2hhbm5lbCBmb3JtdWxhXFxuXFx0XFx0XFx0XFx0Ly8gY29sb3IucmdiICs9ICgxLiAtIGNvbG9yLnJnYikgKiAoMS4gLSBtYXNrLnJnYik7XFxuXFxuXFx0XFx0XFx0XFx0Z2xfRnJhZ0NvbG9yID0gY29sb3I7XFxuXFx0XFx0XFx0fVwiXG5cdH0pXG5cblx0Ly8gcGVyIGZvbnQtc2l6ZSBhdGxhc1xuXHR2YXIgYXRsYXMgPSB7fVxuXG5cdHJldHVybiB7IHJlZ2w6IHJlZ2wsIGRyYXc6IGRyYXcsIGF0bGFzOiBhdGxhcyB9XG59O1xuXG5HbFRleHQucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZSAobykge1xuXHRcdHZhciB0aGlzJDEgPSB0aGlzO1xuXG5cdGlmICh0eXBlb2YgbyA9PT0gJ3N0cmluZycpIHsgbyA9IHsgdGV4dDogbyB9IH1cblx0ZWxzZSBpZiAoIW8pIHsgcmV0dXJuIH1cblxuXHQvLyBGSVhNRTogbWFrZSB0aGlzIGEgc3RhdGljIHRyYW5zZm9ybSBvciBtb3JlIGdlbmVyYWwgYXBwcm9hY3Rcblx0byA9IHBpY2sobywge1xuXHRcdHBvc2l0aW9uOiAncG9zaXRpb24gcG9zaXRpb25zIGNvb3JkIGNvb3JkcyBjb29yZGluYXRlcycsXG5cdFx0Zm9udDogJ2ZvbnQgZm9udEZhY2UgZm9udGZhY2UgdHlwZWZhY2UgY3NzRm9udCBjc3MtZm9udCBmYW1pbHkgZm9udEZhbWlseScsXG5cdFx0Zm9udFNpemU6ICdmb250U2l6ZSBmb250c2l6ZSBzaXplIGZvbnQtc2l6ZScsXG5cdFx0dGV4dDogJ3RleHQgdGV4dHMgY2hhcnMgY2hhcmFjdGVycyB2YWx1ZSB2YWx1ZXMgc3ltYm9scycsXG5cdFx0YWxpZ246ICdhbGlnbiBhbGlnbm1lbnQgdGV4dEFsaWduIHRleHRiYXNlbGluZScsXG5cdFx0YmFzZWxpbmU6ICdiYXNlbGluZSB0ZXh0QmFzZWxpbmUgdGV4dGJhc2VsaW5lJyxcblx0XHRkaXJlY3Rpb246ICdkaXIgZGlyZWN0aW9uIHRleHREaXJlY3Rpb24nLFxuXHRcdGNvbG9yOiAnY29sb3IgY29sb3VyIGZpbGwgZmlsbC1jb2xvciBmaWxsQ29sb3IgdGV4dENvbG9yIHRleHRjb2xvcicsXG5cdFx0a2VybmluZzogJ2tlcm5pbmcga2VybicsXG5cdFx0cmFuZ2U6ICdyYW5nZSBkYXRhQm94Jyxcblx0XHR2aWV3cG9ydDogJ3ZwIHZpZXdwb3J0IHZpZXdCb3ggdmlld2JveCB2aWV3UG9ydCcsXG5cdFx0b3BhY2l0eTogJ29wYWNpdHkgYWxwaGEgdHJhbnNwYXJlbmN5IHZpc2libGUgdmlzaWJpbGl0eSBvcGFxdWUnLFxuXHRcdG9mZnNldDogJ29mZnNldCBwb3NpdGlvbk9mZnNldCBwYWRkaW5nIHNoaWZ0IGluZGVudCBpbmRlbnRhdGlvbidcblx0fSwgdHJ1ZSlcblxuXG5cdGlmIChvLm9wYWNpdHkgIT0gbnVsbCkge1xuXHRcdGlmIChBcnJheS5pc0FycmF5KG8ub3BhY2l0eSkpIHtcblx0XHRcdHRoaXMub3BhY2l0eSA9IG8ub3BhY2l0eS5tYXAoZnVuY3Rpb24gKG8pIHsgcmV0dXJuIHBhcnNlRmxvYXQobyk7IH0pXG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0dGhpcy5vcGFjaXR5ID0gcGFyc2VGbG9hdChvLm9wYWNpdHkpXG5cdFx0fVxuXHR9XG5cblx0aWYgKG8udmlld3BvcnQgIT0gbnVsbCkge1xuXHRcdHRoaXMudmlld3BvcnQgPSBwYXJzZVJlY3Qoby52aWV3cG9ydClcblxuXHRcdGlmIChHbFRleHQubm9ybWFsVmlld3BvcnQpIHtcblx0XHRcdHRoaXMudmlld3BvcnQueSA9IHRoaXMuY2FudmFzLmhlaWdodCAtIHRoaXMudmlld3BvcnQueSAtIHRoaXMudmlld3BvcnQuaGVpZ2h0XG5cdFx0fVxuXG5cdFx0dGhpcy52aWV3cG9ydEFycmF5ID0gW3RoaXMudmlld3BvcnQueCwgdGhpcy52aWV3cG9ydC55LCB0aGlzLnZpZXdwb3J0LndpZHRoLCB0aGlzLnZpZXdwb3J0LmhlaWdodF1cblxuXHR9XG5cdGlmICh0aGlzLnZpZXdwb3J0ID09IG51bGwpIHtcblx0XHR0aGlzLnZpZXdwb3J0ID0ge1xuXHRcdFx0eDogMCwgeTogMCxcblx0XHRcdHdpZHRoOiB0aGlzLmdsLmRyYXdpbmdCdWZmZXJXaWR0aCxcblx0XHRcdGhlaWdodDogdGhpcy5nbC5kcmF3aW5nQnVmZmVySGVpZ2h0XG5cdFx0fVxuXHRcdHRoaXMudmlld3BvcnRBcnJheSA9IFt0aGlzLnZpZXdwb3J0LngsIHRoaXMudmlld3BvcnQueSwgdGhpcy52aWV3cG9ydC53aWR0aCwgdGhpcy52aWV3cG9ydC5oZWlnaHRdXG5cdH1cblxuXHRpZiAoby5rZXJuaW5nICE9IG51bGwpIHsgdGhpcy5rZXJuaW5nID0gby5rZXJuaW5nIH1cblxuXHRpZiAoby5vZmZzZXQgIT0gbnVsbCkge1xuXHRcdGlmICh0eXBlb2Ygby5vZmZzZXQgPT09ICdudW1iZXInKSB7IG8ub2Zmc2V0ID0gW28ub2Zmc2V0LCAwXSB9XG5cblx0XHR0aGlzLnBvc2l0aW9uT2Zmc2V0ID0gZmxhdHRlbihvLm9mZnNldClcblx0fVxuXG5cdGlmIChvLmRpcmVjdGlvbikgeyB0aGlzLmRpcmVjdGlvbiA9IG8uZGlyZWN0aW9uIH1cblxuXHRpZiAoby5yYW5nZSkge1xuXHRcdHRoaXMucmFuZ2UgPSBvLnJhbmdlXG5cdFx0dGhpcy5zY2FsZSA9IFsxIC8gKG8ucmFuZ2VbMl0gLSBvLnJhbmdlWzBdKSwgMSAvIChvLnJhbmdlWzNdIC0gby5yYW5nZVsxXSldXG5cdFx0dGhpcy50cmFuc2xhdGUgPSBbLW8ucmFuZ2VbMF0sIC1vLnJhbmdlWzFdXVxuXHR9XG5cdGlmIChvLnNjYWxlKSB7IHRoaXMuc2NhbGUgPSBvLnNjYWxlIH1cblx0aWYgKG8udHJhbnNsYXRlKSB7IHRoaXMudHJhbnNsYXRlID0gby50cmFuc2xhdGUgfVxuXG5cdC8vIGRlZmF1bHQgc2NhbGUgY29ycmVzcG9uZHMgdG8gdmlld3BvcnRcblx0aWYgKCF0aGlzLnNjYWxlKSB7IHRoaXMuc2NhbGUgPSBbMSAvIHRoaXMudmlld3BvcnQud2lkdGgsIDEgLyB0aGlzLnZpZXdwb3J0LmhlaWdodF0gfVxuXG5cdGlmICghdGhpcy50cmFuc2xhdGUpIHsgdGhpcy50cmFuc2xhdGUgPSBbMCwgMF0gfVxuXG5cdGlmICghdGhpcy5mb250Lmxlbmd0aCAmJiAhby5mb250KSB7IG8uZm9udCA9IEdsVGV4dC5iYXNlRm9udFNpemUgKyAncHggc2Fucy1zZXJpZicgfVxuXG5cdC8vIG5vcm1hbGl6ZSBmb250IGNhY2hpbmcgc3RyaW5nXG5cdHZhciBuZXdGb250ID0gZmFsc2UsIG5ld0ZvbnRTaXplID0gZmFsc2VcblxuXHQvLyBvYnRhaW4gbmV3IGZvbnQgZGF0YVxuXHRpZiAoby5mb250KSB7XG5cdFx0KEFycmF5LmlzQXJyYXkoby5mb250KSA/IG8uZm9udCA6IFtvLmZvbnRdKS5mb3JFYWNoKGZ1bmN0aW9uIChmb250LCBpKSB7XG5cdFx0XHQvLyBub3JtYWxpemUgZm9udFxuXHRcdFx0aWYgKHR5cGVvZiBmb250ID09PSAnc3RyaW5nJykge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGZvbnQgPSBGb250LnBhcnNlKGZvbnQpXG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRmb250ID0gRm9udC5wYXJzZShHbFRleHQuYmFzZUZvbnRTaXplICsgJ3B4ICcgKyBmb250KVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHsgZm9udCA9IEZvbnQucGFyc2UoRm9udC5zdHJpbmdpZnkoZm9udCkpIH1cblxuXHRcdFx0dmFyIGJhc2VTdHJpbmcgPSBGb250LnN0cmluZ2lmeSh7XG5cdFx0XHRcdHNpemU6IEdsVGV4dC5iYXNlRm9udFNpemUsXG5cdFx0XHRcdGZhbWlseTogZm9udC5mYW1pbHksXG5cdFx0XHRcdHN0cmV0Y2g6IGlzU3RyZXRjaFN1cHBvcnRlZCA/IGZvbnQuc3RyZXRjaCA6IHVuZGVmaW5lZCxcblx0XHRcdFx0dmFyaWFudDogZm9udC52YXJpYW50LFxuXHRcdFx0XHR3ZWlnaHQ6IGZvbnQud2VpZ2h0LFxuXHRcdFx0XHRzdHlsZTogZm9udC5zdHlsZVxuXHRcdFx0fSlcblxuXHRcdFx0dmFyIHVuaXQgPSBwYXJzZVVuaXQoZm9udC5zaXplKVxuXHRcdFx0dmFyIGZzID0gTWF0aC5yb3VuZCh1bml0WzBdICogcHgodW5pdFsxXSkpXG5cdFx0XHRpZiAoZnMgIT09IHRoaXMkMS5mb250U2l6ZVtpXSkge1xuXHRcdFx0XHRuZXdGb250U2l6ZSA9IHRydWVcblx0XHRcdFx0dGhpcyQxLmZvbnRTaXplW2ldID0gZnNcblx0XHRcdH1cblxuXHRcdFx0Ly8gY2FsYyBuZXcgZm9udCBtZXRyaWNzL2F0bGFzXG5cdFx0XHRpZiAoIXRoaXMkMS5mb250W2ldIHx8IGJhc2VTdHJpbmcgIT0gdGhpcyQxLmZvbnRbaV0uYmFzZVN0cmluZykge1xuXHRcdFx0XHRuZXdGb250ID0gdHJ1ZVxuXG5cdFx0XHRcdC8vIG9idGFpbiBmb250IGNhY2hlIG9yIGNyZWF0ZSBvbmVcblx0XHRcdFx0dGhpcyQxLmZvbnRbaV0gPSBHbFRleHQuZm9udHNbYmFzZVN0cmluZ11cblx0XHRcdFx0aWYgKCF0aGlzJDEuZm9udFtpXSkge1xuXHRcdFx0XHRcdHZhciBmYW1pbHkgPSBmb250LmZhbWlseS5qb2luKCcsICcpXG5cdFx0XHRcdFx0dmFyIHN0eWxlID0gW2ZvbnQuc3R5bGVdXG5cdFx0XHRcdFx0aWYgKGZvbnQuc3R5bGUgIT0gZm9udC52YXJpYW50KSB7IHN0eWxlLnB1c2goZm9udC52YXJpYW50KSB9XG5cdFx0XHRcdFx0aWYgKGZvbnQudmFyaWFudCAhPSBmb250LndlaWdodCkgeyBzdHlsZS5wdXNoKGZvbnQud2VpZ2h0KSB9XG5cdFx0XHRcdFx0aWYgKGlzU3RyZXRjaFN1cHBvcnRlZCAmJiBmb250LndlaWdodCAhPSBmb250LnN0cmV0Y2gpIHsgc3R5bGUucHVzaChmb250LnN0cmV0Y2gpIH1cblxuXHRcdFx0XHRcdHRoaXMkMS5mb250W2ldID0ge1xuXHRcdFx0XHRcdFx0YmFzZVN0cmluZzogYmFzZVN0cmluZyxcblxuXHRcdFx0XHRcdFx0Ly8gdHlwZWZhY2Vcblx0XHRcdFx0XHRcdGZhbWlseTogZmFtaWx5LFxuXHRcdFx0XHRcdFx0d2VpZ2h0OiBmb250LndlaWdodCxcblx0XHRcdFx0XHRcdHN0cmV0Y2g6IGZvbnQuc3RyZXRjaCxcblx0XHRcdFx0XHRcdHN0eWxlOiBmb250LnN0eWxlLFxuXHRcdFx0XHRcdFx0dmFyaWFudDogZm9udC52YXJpYW50LFxuXG5cdFx0XHRcdFx0XHQvLyB3aWR0aHMgb2YgY2hhcmFjdGVyc1xuXHRcdFx0XHRcdFx0d2lkdGg6IHt9LFxuXG5cdFx0XHRcdFx0XHQvLyBrZXJuaW4gcGFpcnMgb2Zmc2V0c1xuXHRcdFx0XHRcdFx0a2VybmluZzoge30sXG5cblx0XHRcdFx0XHRcdG1ldHJpY3M6IG1ldHJpY3MoZmFtaWx5LCB7XG5cdFx0XHRcdFx0XHRcdG9yaWdpbjogJ3RvcCcsXG5cdFx0XHRcdFx0XHRcdGZvbnRTaXplOiBHbFRleHQuYmFzZUZvbnRTaXplLFxuXHRcdFx0XHRcdFx0XHRmb250U3R5bGU6IHN0eWxlLmpvaW4oJyAnKVxuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRHbFRleHQuZm9udHNbYmFzZVN0cmluZ10gPSB0aGlzJDEuZm9udFtpXVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSlcblx0fVxuXG5cdC8vIEZJWE1FOiBtYWtlIGluZGVwZW5kZW5kIGZvbnQtc2l6ZVxuXHQvLyBpZiAoby5mb250U2l6ZSkge1xuXHQvLyBsZXQgdW5pdCA9IHBhcnNlVW5pdChvLmZvbnRTaXplKVxuXHQvLyBsZXQgZnMgPSBNYXRoLnJvdW5kKHVuaXRbMF0gKiBweCh1bml0WzFdKSlcblxuXHQvLyBpZiAoZnMgIT0gdGhpcy5mb250U2l6ZSkge1xuXHQvLyBcdG5ld0ZvbnRTaXplID0gdHJ1ZVxuXHQvLyBcdHRoaXMuZm9udFNpemUgPSBmc1xuXHQvLyB9XG5cdC8vIH1cblxuXHRpZiAobmV3Rm9udCB8fCBuZXdGb250U2l6ZSkge1xuXHRcdHRoaXMuZm9udC5mb3JFYWNoKGZ1bmN0aW9uIChmb250LCBpKSB7XG5cdFx0XHR2YXIgZm9udFN0cmluZyA9IEZvbnQuc3RyaW5naWZ5KHtcblx0XHRcdFx0c2l6ZTogdGhpcyQxLmZvbnRTaXplW2ldLFxuXHRcdFx0XHRmYW1pbHk6IGZvbnQuZmFtaWx5LFxuXHRcdFx0XHRzdHJldGNoOiBpc1N0cmV0Y2hTdXBwb3J0ZWQgPyBmb250LnN0cmV0Y2ggOiB1bmRlZmluZWQsXG5cdFx0XHRcdHZhcmlhbnQ6IGZvbnQudmFyaWFudCxcblx0XHRcdFx0d2VpZ2h0OiBmb250LndlaWdodCxcblx0XHRcdFx0c3R5bGU6IGZvbnQuc3R5bGVcblx0XHRcdH0pXG5cblx0XHRcdC8vIGNhbGMgbmV3IGZvbnQgc2l6ZSBhdGxhc1xuXHRcdFx0dGhpcyQxLmZvbnRBdGxhc1tpXSA9IHRoaXMkMS5zaGFkZXIuYXRsYXNbZm9udFN0cmluZ11cblxuXHRcdFx0aWYgKCF0aGlzJDEuZm9udEF0bGFzW2ldKSB7XG5cdFx0XHRcdHZhciBtZXRyaWNzID0gZm9udC5tZXRyaWNzXG5cblx0XHRcdFx0dGhpcyQxLnNoYWRlci5hdGxhc1tmb250U3RyaW5nXSA9XG5cdFx0XHRcdHRoaXMkMS5mb250QXRsYXNbaV0gPSB7XG5cdFx0XHRcdFx0Zm9udFN0cmluZzogZm9udFN0cmluZyxcblx0XHRcdFx0XHQvLyBldmVuIHN0ZXAgaXMgYmV0dGVyIGZvciByZW5kZXJlZCBjaGFyYWN0ZXJzXG5cdFx0XHRcdFx0c3RlcDogTWF0aC5jZWlsKHRoaXMkMS5mb250U2l6ZVtpXSAqIG1ldHJpY3MuYm90dG9tICogLjUpICogMixcblx0XHRcdFx0XHRlbTogdGhpcyQxLmZvbnRTaXplW2ldLFxuXHRcdFx0XHRcdGNvbHM6IDAsXG5cdFx0XHRcdFx0cm93czogMCxcblx0XHRcdFx0XHRoZWlnaHQ6IDAsXG5cdFx0XHRcdFx0d2lkdGg6IDAsXG5cdFx0XHRcdFx0Y2hhcnM6IFtdLFxuXHRcdFx0XHRcdGlkczoge30sXG5cdFx0XHRcdFx0dGV4dHVyZTogdGhpcyQxLnJlZ2wudGV4dHVyZSgpXG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gYnVtcCBhdGxhcyBjaGFyYWN0ZXJzXG5cdFx0XHRpZiAoby50ZXh0ID09IG51bGwpIHsgby50ZXh0ID0gdGhpcyQxLnRleHQgfVxuXHRcdH0pXG5cdH1cblxuXHQvLyBpZiBtdWx0aXBsZSBwb3NpdGlvbnMgLSBkdXBsaWNhdGUgdGV4dCBhcmd1bWVudHNcblx0Ly8gRklYTUU6IHRoaXMgcG9zc2libHkgY2FuIGJlIGRvbmUgYmV0dGVyIHRvIGF2b2lkIGFycmF5IHNwYXduXG5cdGlmICh0eXBlb2Ygby50ZXh0ID09PSAnc3RyaW5nJyAmJiBvLnBvc2l0aW9uICYmIG8ucG9zaXRpb24ubGVuZ3RoID4gMikge1xuXHRcdHZhciB0ZXh0QXJyYXkgPSBBcnJheShvLnBvc2l0aW9uLmxlbmd0aCAqIC41KVxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgdGV4dEFycmF5Lmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR0ZXh0QXJyYXlbaV0gPSBvLnRleHRcblx0XHR9XG5cdFx0by50ZXh0ID0gdGV4dEFycmF5XG5cdH1cblxuXHQvLyBjYWxjdWxhdGUgb2Zmc2V0cyBmb3IgdGhlIG5ldyBmb250L3RleHRcblx0dmFyIG5ld0F0bGFzQ2hhcnNcblx0aWYgKG8udGV4dCAhPSBudWxsIHx8IG5ld0ZvbnQpIHtcblx0XHQvLyBGSVhNRTogaWdub3JlIHNwYWNlc1xuXHRcdC8vIHRleHQgb2Zmc2V0cyB3aXRoaW4gdGhlIHRleHQgYnVmZmVyXG5cdFx0dGhpcy50ZXh0T2Zmc2V0cyA9IFswXVxuXG5cdFx0aWYgKEFycmF5LmlzQXJyYXkoby50ZXh0KSkge1xuXHRcdFx0dGhpcy5jb3VudCA9IG8udGV4dFswXS5sZW5ndGhcblx0XHRcdHRoaXMuY291bnRzID0gW3RoaXMuY291bnRdXG5cdFx0XHRmb3IgKHZhciBpJDEgPSAxOyBpJDEgPCBvLnRleHQubGVuZ3RoOyBpJDErKykge1xuXHRcdFx0XHR0aGlzLnRleHRPZmZzZXRzW2kkMV0gPSB0aGlzLnRleHRPZmZzZXRzW2kkMSAtIDFdICsgby50ZXh0W2kkMSAtIDFdLmxlbmd0aFxuXHRcdFx0XHR0aGlzLmNvdW50ICs9IG8udGV4dFtpJDFdLmxlbmd0aFxuXHRcdFx0XHR0aGlzLmNvdW50cy5wdXNoKG8udGV4dFtpJDFdLmxlbmd0aClcblx0XHRcdH1cblx0XHRcdHRoaXMudGV4dCA9IG8udGV4dC5qb2luKCcnKVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHRoaXMudGV4dCA9IG8udGV4dFxuXHRcdFx0dGhpcy5jb3VudCA9IHRoaXMudGV4dC5sZW5ndGhcblx0XHRcdHRoaXMuY291bnRzID0gW3RoaXMuY291bnRdXG5cdFx0fVxuXG5cdFx0bmV3QXRsYXNDaGFycyA9IFtdXG5cblx0XHQvLyBkZXRlY3QgJiBtZWFzdXJlIG5ldyBjaGFyYWN0ZXJzXG5cdFx0dGhpcy5mb250LmZvckVhY2goZnVuY3Rpb24gKGZvbnQsIGlkeCkge1xuXHRcdFx0R2xUZXh0LmF0bGFzQ29udGV4dC5mb250ID0gZm9udC5iYXNlU3RyaW5nXG5cblx0XHRcdHZhciBhdGxhcyA9IHRoaXMkMS5mb250QXRsYXNbaWR4XVxuXG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMkMS50ZXh0Lmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHZhciBjaGFyID0gdGhpcyQxLnRleHQuY2hhckF0KGkpXG5cblx0XHRcdFx0aWYgKGF0bGFzLmlkc1tjaGFyXSA9PSBudWxsKSB7XG5cdFx0XHRcdFx0YXRsYXMuaWRzW2NoYXJdID0gYXRsYXMuY2hhcnMubGVuZ3RoXG5cdFx0XHRcdFx0YXRsYXMuY2hhcnMucHVzaChjaGFyKVxuXHRcdFx0XHRcdG5ld0F0bGFzQ2hhcnMucHVzaChjaGFyKVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGZvbnQud2lkdGhbY2hhcl0gPT0gbnVsbCkge1xuXHRcdFx0XHRcdGZvbnQud2lkdGhbY2hhcl0gPSBHbFRleHQuYXRsYXNDb250ZXh0Lm1lYXN1cmVUZXh0KGNoYXIpLndpZHRoIC8gR2xUZXh0LmJhc2VGb250U2l6ZVxuXG5cdFx0XHRcdFx0Ly8gbWVhc3VyZSBrZXJuaW5nIHBhaXJzIGZvciB0aGUgbmV3IGNoYXJhY3RlclxuXHRcdFx0XHRcdGlmICh0aGlzJDEua2VybmluZykge1xuXHRcdFx0XHRcdFx0dmFyIHBhaXJzID0gW11cblx0XHRcdFx0XHRcdGZvciAodmFyIGJhc2VDaGFyIGluIGZvbnQud2lkdGgpIHtcblx0XHRcdFx0XHRcdFx0cGFpcnMucHVzaChiYXNlQ2hhciArIGNoYXIsIGNoYXIgKyBiYXNlQ2hhcilcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGV4dGVuZChmb250Lmtlcm5pbmcsIGtlcm5pbmcoZm9udC5mYW1pbHksIHtcblx0XHRcdFx0XHRcdFx0cGFpcnM6IHBhaXJzXG5cdFx0XHRcdFx0XHR9KSlcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KVxuXHR9XG5cblx0Ly8gY3JlYXRlIHNpbmdsZSBwb3NpdGlvbiBidWZmZXIgKGZhc3RlciB0aGFuIGJhdGNoIG9yIG11bHRpcGxlIHNlcGFyYXRlIGluc3RhbmNlcylcblx0aWYgKG8ucG9zaXRpb24pIHtcblx0XHRpZiAoby5wb3NpdGlvbi5sZW5ndGggPiAyKSB7XG5cdFx0XHR2YXIgZmxhdCA9ICFvLnBvc2l0aW9uWzBdLmxlbmd0aFxuXHRcdFx0dmFyIHBvc2l0aW9uRGF0YSA9IHBvb2wubWFsbG9jRmxvYXQodGhpcy5jb3VudCAqIDIpXG5cdFx0XHRmb3IgKHZhciBpJDIgPSAwLCBwdHIgPSAwOyBpJDIgPCB0aGlzLmNvdW50cy5sZW5ndGg7IGkkMisrKSB7XG5cdFx0XHRcdHZhciBjb3VudCA9IHRoaXMuY291bnRzW2kkMl1cblx0XHRcdFx0aWYgKGZsYXQpIHtcblx0XHRcdFx0XHRmb3IgKHZhciBqID0gMDsgaiA8IGNvdW50OyBqKyspIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uRGF0YVtwdHIrK10gPSBvLnBvc2l0aW9uW2kkMiAqIDJdXG5cdFx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbcHRyKytdID0gby5wb3NpdGlvbltpJDIgKiAyICsgMV1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0Zm9yICh2YXIgaiQxID0gMDsgaiQxIDwgY291bnQ7IGokMSsrKSB7XG5cdFx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbcHRyKytdID0gby5wb3NpdGlvbltpJDJdWzBdXG5cdFx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbcHRyKytdID0gby5wb3NpdGlvbltpJDJdWzFdXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy5wb3NpdGlvbi5jYWxsKSB7XG5cdFx0XHRcdHRoaXMucG9zaXRpb24oe1xuXHRcdFx0XHRcdHR5cGU6ICdmbG9hdCcsXG5cdFx0XHRcdFx0ZGF0YTogcG9zaXRpb25EYXRhXG5cdFx0XHRcdH0pXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLnBvc2l0aW9uID0gdGhpcy5yZWdsLmJ1ZmZlcih7XG5cdFx0XHRcdFx0dHlwZTogJ2Zsb2F0Jyxcblx0XHRcdFx0XHRkYXRhOiBwb3NpdGlvbkRhdGFcblx0XHRcdFx0fSlcblx0XHRcdH1cblx0XHRcdHBvb2wuZnJlZUZsb2F0KHBvc2l0aW9uRGF0YSlcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHRpZiAodGhpcy5wb3NpdGlvbi5kZXN0cm95KSB7IHRoaXMucG9zaXRpb24uZGVzdHJveSgpIH1cblx0XHRcdHRoaXMucG9zaXRpb24gPSB7XG5cdFx0XHRcdGNvbnN0YW50OiBvLnBvc2l0aW9uXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gcG9wdWxhdGUgdGV4dC9vZmZzZXQgYnVmZmVycyBpZiBmb250L3RleHQgaGFzIGNoYW5nZWRcblx0Ly8gYXMgW2NoYXJXaWR0aCwgb2Zmc2V0LCBjaGFyV2lkdGgsIG9mZnNldC4uLl1cblx0Ly8gdGhhdCBpcyBpbiBlbSB1bml0cyBzaW5jZSBmb250LXNpemUgY2FuIGNoYW5nZSBvZnRlblxuXHRpZiAoby50ZXh0IHx8IG5ld0ZvbnQpIHtcblx0XHR2YXIgY2hhcklkcyA9IHBvb2wubWFsbG9jVWludDgodGhpcy5jb3VudClcblx0XHR2YXIgc2l6ZURhdGEgPSBwb29sLm1hbGxvY0Zsb2F0KHRoaXMuY291bnQgKiAyKVxuXHRcdHRoaXMudGV4dFdpZHRoID0gW11cblxuXHRcdGZvciAodmFyIGkkMyA9IDAsIHB0ciQxID0gMDsgaSQzIDwgdGhpcy5jb3VudHMubGVuZ3RoOyBpJDMrKykge1xuXHRcdFx0dmFyIGNvdW50JDEgPSB0aGlzLmNvdW50c1tpJDNdXG5cdFx0XHR2YXIgZm9udCA9IHRoaXMuZm9udFtpJDNdIHx8IHRoaXMuZm9udFswXVxuXHRcdFx0dmFyIGF0bGFzID0gdGhpcy5mb250QXRsYXNbaSQzXSB8fCB0aGlzLmZvbnRBdGxhc1swXVxuXG5cdFx0XHRmb3IgKHZhciBqJDIgPSAwOyBqJDIgPCBjb3VudCQxOyBqJDIrKykge1xuXHRcdFx0XHR2YXIgY2hhciA9IHRoaXMudGV4dC5jaGFyQXQocHRyJDEpXG5cdFx0XHRcdHZhciBwcmV2Q2hhciA9IHRoaXMudGV4dC5jaGFyQXQocHRyJDEgLSAxKVxuXG5cdFx0XHRcdGNoYXJJZHNbcHRyJDFdID0gYXRsYXMuaWRzW2NoYXJdXG5cdFx0XHRcdHNpemVEYXRhW3B0ciQxICogMl0gPSBmb250LndpZHRoW2NoYXJdXG5cblx0XHRcdFx0aWYgKGokMikge1xuXHRcdFx0XHRcdHZhciBwcmV2V2lkdGggPSBzaXplRGF0YVtwdHIkMSAqIDIgLSAyXVxuXHRcdFx0XHRcdHZhciBjdXJyV2lkdGggPSBzaXplRGF0YVtwdHIkMSAqIDJdXG5cdFx0XHRcdFx0dmFyIHByZXZPZmZzZXQgPSBzaXplRGF0YVtwdHIkMSAqIDIgLSAxXVxuXHRcdFx0XHRcdHZhciBvZmZzZXQgPSBwcmV2T2Zmc2V0ICsgcHJldldpZHRoICogLjUgKyBjdXJyV2lkdGggKiAuNTtcblxuXHRcdFx0XHRcdGlmICh0aGlzLmtlcm5pbmcpIHtcblx0XHRcdFx0XHRcdHZhciBrZXJuaW5nJDEgPSBmb250Lmtlcm5pbmdbcHJldkNoYXIgKyBjaGFyXVxuXHRcdFx0XHRcdFx0aWYgKGtlcm5pbmckMSkge1xuXHRcdFx0XHRcdFx0XHRvZmZzZXQgKz0ga2VybmluZyQxICogMWUtM1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHNpemVEYXRhW3B0ciQxICogMiArIDFdID0gb2Zmc2V0XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0c2l6ZURhdGFbcHRyJDEgKiAyICsgMV0gPSBzaXplRGF0YVtwdHIkMSAqIDJdICogLjVcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHB0ciQxKytcblx0XHRcdH1cblx0XHRcdHRoaXMudGV4dFdpZHRoLnB1c2goXG5cdFx0XHRcdCFzaXplRGF0YS5sZW5ndGggPyAwIDpcblx0XHRcdFx0Ly8gbGFzdCBvZmZzZXQgKyBoYWxmIGxhc3Qgd2lkdGhcblx0XHRcdFx0c2l6ZURhdGFbcHRyJDEgKiAyIC0gMl0gKiAuNSArIHNpemVEYXRhW3B0ciQxICogMiAtIDFdXG5cdFx0XHQpXG5cdFx0fVxuXG5cblx0XHQvLyBidW1wIHJlY2FsYyBhbGlnbiBvZmZzZXRcblx0XHRpZiAoIW8uYWxpZ24pIHsgby5hbGlnbiA9IHRoaXMuYWxpZ24gfVxuXHRcdHRoaXMuY2hhckJ1ZmZlcih7ZGF0YTogY2hhcklkcywgdHlwZTogJ3VpbnQ4JywgdXNhZ2U6ICdzdHJlYW0nfSlcblx0XHR0aGlzLnNpemVCdWZmZXIoe2RhdGE6IHNpemVEYXRhLCB0eXBlOiAnZmxvYXQnLCB1c2FnZTogJ3N0cmVhbSd9KVxuXHRcdHBvb2wuZnJlZVVpbnQ4KGNoYXJJZHMpXG5cdFx0cG9vbC5mcmVlRmxvYXQoc2l6ZURhdGEpXG5cblx0XHQvLyB1ZHBhdGUgZm9udCBhdGxhcyBhbmQgdGV4dHVyZVxuXHRcdGlmIChuZXdBdGxhc0NoYXJzLmxlbmd0aCkge1xuXHRcdFx0dGhpcy5mb250LmZvckVhY2goZnVuY3Rpb24gKGZvbnQsIGkpIHtcblx0XHRcdFx0dmFyIGF0bGFzID0gdGhpcyQxLmZvbnRBdGxhc1tpXVxuXG5cdFx0XHRcdC8vIEZJWE1FOiBpbnNlcnQgbWV0cmljcy1iYXNlZCByYXRpbyBoZXJlXG5cdFx0XHRcdHZhciBzdGVwID0gYXRsYXMuc3RlcFxuXG5cdFx0XHRcdHZhciBtYXhDb2xzID0gTWF0aC5mbG9vcihHbFRleHQubWF4QXRsYXNTaXplIC8gc3RlcClcblx0XHRcdFx0dmFyIGNvbHMgPSBNYXRoLm1pbihtYXhDb2xzLCBhdGxhcy5jaGFycy5sZW5ndGgpXG5cdFx0XHRcdHZhciByb3dzID0gTWF0aC5jZWlsKGF0bGFzLmNoYXJzLmxlbmd0aCAvIGNvbHMpXG5cblx0XHRcdFx0dmFyIGF0bGFzV2lkdGggPSBuZXh0UG93MiggY29scyAqIHN0ZXAgKVxuXHRcdFx0XHQvLyBsZXQgYXRsYXNIZWlnaHQgPSBNYXRoLm1pbihyb3dzICogc3RlcCArIHN0ZXAgKiAuNSwgR2xUZXh0Lm1heEF0bGFzU2l6ZSk7XG5cdFx0XHRcdHZhciBhdGxhc0hlaWdodCA9IG5leHRQb3cyKCByb3dzICogc3RlcCApO1xuXG5cdFx0XHRcdGF0bGFzLndpZHRoID0gYXRsYXNXaWR0aFxuXHRcdFx0XHRhdGxhcy5oZWlnaHQgPSBhdGxhc0hlaWdodDtcblx0XHRcdFx0YXRsYXMucm93cyA9IHJvd3Ncblx0XHRcdFx0YXRsYXMuY29scyA9IGNvbHNcblxuXHRcdFx0XHRpZiAoIWF0bGFzLmVtKSB7IHJldHVybiB9XG5cblx0XHRcdFx0YXRsYXMudGV4dHVyZSh7XG5cdFx0XHRcdFx0ZGF0YTogZm9udEF0bGFzKHtcblx0XHRcdFx0XHRcdGNhbnZhczogR2xUZXh0LmF0bGFzQ2FudmFzLFxuXHRcdFx0XHRcdFx0Zm9udDogYXRsYXMuZm9udFN0cmluZyxcblx0XHRcdFx0XHRcdGNoYXJzOiBhdGxhcy5jaGFycyxcblx0XHRcdFx0XHRcdHNoYXBlOiBbYXRsYXNXaWR0aCwgYXRsYXNIZWlnaHRdLFxuXHRcdFx0XHRcdFx0c3RlcDogW3N0ZXAsIHN0ZXBdXG5cdFx0XHRcdFx0fSlcblx0XHRcdFx0fSlcblxuXHRcdFx0fSlcblx0XHR9XG5cdH1cblxuXHRpZiAoby5hbGlnbikge1xuXHRcdHRoaXMuYWxpZ24gPSBvLmFsaWduXG5cdFx0dGhpcy5hbGlnbk9mZnNldCA9IHRoaXMudGV4dFdpZHRoLm1hcChmdW5jdGlvbiAodGV4dFdpZHRoLCBpKSB7XG5cdFx0XHR2YXIgYWxpZ24gPSAhQXJyYXkuaXNBcnJheSh0aGlzJDEuYWxpZ24pID8gdGhpcyQxLmFsaWduIDogdGhpcyQxLmFsaWduLmxlbmd0aCA+IDEgPyB0aGlzJDEuYWxpZ25baV0gOiB0aGlzJDEuYWxpZ25bMF1cblxuXHRcdFx0aWYgKHR5cGVvZiBhbGlnbiA9PT0gJ251bWJlcicpIHsgcmV0dXJuIGFsaWduIH1cblx0XHRcdHN3aXRjaCAoYWxpZ24pIHtcblx0XHRcdFx0Y2FzZSAncmlnaHQnOlxuXHRcdFx0XHRjYXNlICdlbmQnOlxuXHRcdFx0XHRcdHJldHVybiAtdGV4dFdpZHRoXG5cdFx0XHRcdGNhc2UgJ2NlbnRlcic6XG5cdFx0XHRcdGNhc2UgJ2NlbnRyZSc6XG5cdFx0XHRcdGNhc2UgJ21pZGRsZSc6XG5cdFx0XHRcdFx0cmV0dXJuIC10ZXh0V2lkdGggKiAuNVxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gMFxuXHRcdH0pXG5cdH1cblxuXHRpZiAodGhpcy5iYXNlbGluZSA9PSBudWxsICYmIG8uYmFzZWxpbmUgPT0gbnVsbCkge1xuXHRcdG8uYmFzZWxpbmUgPSAwXG5cdH1cblx0aWYgKG8uYmFzZWxpbmUgIT0gbnVsbCkge1xuXHRcdHRoaXMuYmFzZWxpbmUgPSBvLmJhc2VsaW5lXG5cdFx0aWYgKCFBcnJheS5pc0FycmF5KHRoaXMuYmFzZWxpbmUpKSB7IHRoaXMuYmFzZWxpbmUgPSBbdGhpcy5iYXNlbGluZV0gfVxuXHRcdHRoaXMuYmFzZWxpbmVPZmZzZXQgPSB0aGlzLmJhc2VsaW5lLm1hcChmdW5jdGlvbiAoYmFzZWxpbmUsIGkpIHtcblx0XHRcdHZhciBtID0gKHRoaXMkMS5mb250W2ldIHx8IHRoaXMkMS5mb250WzBdKS5tZXRyaWNzXG5cdFx0XHR2YXIgYmFzZSA9IDBcblxuXHRcdFx0YmFzZSArPSBtLmJvdHRvbSAqIC41XG5cblx0XHRcdGlmICh0eXBlb2YgYmFzZWxpbmUgPT09ICdudW1iZXInKSB7XG5cdFx0XHRcdGJhc2UgKz0gKGJhc2VsaW5lIC0gbS5iYXNlbGluZSlcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRiYXNlICs9IC1tW2Jhc2VsaW5lXVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIUdsVGV4dC5ub3JtYWxWaWV3cG9ydCkgeyBiYXNlICo9IC0xIH1cblx0XHRcdHJldHVybiBiYXNlXG5cdFx0fSlcblx0fVxuXG5cdC8vIGZsYXR0ZW4gY29sb3JzIHRvIGEgc2luZ2xlIHVpbnQ4IGFycmF5XG5cdGlmIChvLmNvbG9yICE9IG51bGwpIHtcblx0XHRpZiAoIW8uY29sb3IpIHsgby5jb2xvciA9ICd0cmFuc3BhcmVudCcgfVxuXG5cdFx0Ly8gc2luZ2xlIGNvbG9yXG5cdFx0aWYgKHR5cGVvZiBvLmNvbG9yID09PSAnc3RyaW5nJyB8fCAhaXNOYU4oby5jb2xvcikpIHtcblx0XHRcdHRoaXMuY29sb3IgPSByZ2JhKG8uY29sb3IsICd1aW50OCcpXG5cdFx0fVxuXHRcdC8vIGFycmF5XG5cdFx0ZWxzZSB7XG5cdFx0XHR2YXIgY29sb3JEYXRhXG5cblx0XHRcdC8vIGZsYXQgYXJyYXlcblx0XHRcdGlmICh0eXBlb2Ygby5jb2xvclswXSA9PT0gJ251bWJlcicgJiYgby5jb2xvci5sZW5ndGggPiB0aGlzLmNvdW50cy5sZW5ndGgpIHtcblx0XHRcdFx0dmFyIGwgPSBvLmNvbG9yLmxlbmd0aFxuXHRcdFx0XHRjb2xvckRhdGEgPSBwb29sLm1hbGxvY1VpbnQ4KGwpXG5cdFx0XHRcdHZhciBzdWIgPSAoby5jb2xvci5zdWJhcnJheSB8fCBvLmNvbG9yLnNsaWNlKS5iaW5kKG8uY29sb3IpXG5cdFx0XHRcdGZvciAodmFyIGkkNCA9IDA7IGkkNCA8IGw7IGkkNCArPSA0KSB7XG5cdFx0XHRcdFx0Y29sb3JEYXRhLnNldChyZ2JhKHN1YihpJDQsIGkkNCArIDQpLCAndWludDgnKSwgaSQ0KVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHQvLyBuZXN0ZWQgYXJyYXlcblx0XHRcdGVsc2Uge1xuXHRcdFx0XHR2YXIgbCQxID0gby5jb2xvci5sZW5ndGhcblx0XHRcdFx0Y29sb3JEYXRhID0gcG9vbC5tYWxsb2NVaW50OChsJDEgKiA0KVxuXHRcdFx0XHRmb3IgKHZhciBpJDUgPSAwOyBpJDUgPCBsJDE7IGkkNSsrKSB7XG5cdFx0XHRcdFx0Y29sb3JEYXRhLnNldChyZ2JhKG8uY29sb3JbaSQ1XSB8fCAwLCAndWludDgnKSwgaSQ1ICogNClcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmNvbG9yID0gY29sb3JEYXRhXG5cdFx0fVxuXHR9XG5cblx0Ly8gdXBkYXRlIHJlbmRlciBiYXRjaFxuXHRpZiAoby5wb3NpdGlvbiB8fCBvLnRleHQgfHwgby5jb2xvciB8fCBvLmJhc2VsaW5lIHx8IG8uYWxpZ24gfHwgby5mb250IHx8IG8ub2Zmc2V0IHx8IG8ub3BhY2l0eSkge1xuXHRcdHZhciBpc0JhdGNoID0gKHRoaXMuY29sb3IubGVuZ3RoID4gNClcblx0XHRcdHx8ICh0aGlzLmJhc2VsaW5lT2Zmc2V0Lmxlbmd0aCA+IDEpXG5cdFx0XHR8fCAodGhpcy5hbGlnbiAmJiB0aGlzLmFsaWduLmxlbmd0aCA+IDEpXG5cdFx0XHR8fCAodGhpcy5mb250QXRsYXMubGVuZ3RoID4gMSlcblx0XHRcdHx8ICh0aGlzLnBvc2l0aW9uT2Zmc2V0Lmxlbmd0aCA+IDIpXG5cdFx0aWYgKGlzQmF0Y2gpIHtcblx0XHRcdHZhciBsZW5ndGggPSBNYXRoLm1heChcblx0XHRcdFx0dGhpcy5wb3NpdGlvbi5sZW5ndGggKiAuNSB8fCAwLFxuXHRcdFx0XHR0aGlzLmNvbG9yLmxlbmd0aCAqIC4yNSB8fCAwLFxuXHRcdFx0XHR0aGlzLmJhc2VsaW5lT2Zmc2V0Lmxlbmd0aCB8fCAwLFxuXHRcdFx0XHR0aGlzLmFsaWduT2Zmc2V0Lmxlbmd0aCB8fCAwLFxuXHRcdFx0XHR0aGlzLmZvbnQubGVuZ3RoIHx8IDAsXG5cdFx0XHRcdHRoaXMub3BhY2l0eS5sZW5ndGggfHwgMCxcblx0XHRcdFx0dGhpcy5wb3NpdGlvbk9mZnNldC5sZW5ndGggKiAuNSB8fCAwXG5cdFx0XHQpXG5cdFx0XHR0aGlzLmJhdGNoID0gQXJyYXkobGVuZ3RoKVxuXHRcdFx0Zm9yICh2YXIgaSQ2ID0gMDsgaSQ2IDwgdGhpcy5iYXRjaC5sZW5ndGg7IGkkNisrKSB7XG5cdFx0XHRcdHRoaXMuYmF0Y2hbaSQ2XSA9IHtcblx0XHRcdFx0XHRjb3VudDogdGhpcy5jb3VudHMubGVuZ3RoID4gMSA/IHRoaXMuY291bnRzW2kkNl0gOiB0aGlzLmNvdW50c1swXSxcblx0XHRcdFx0XHRvZmZzZXQ6IHRoaXMudGV4dE9mZnNldHMubGVuZ3RoID4gMSA/IHRoaXMudGV4dE9mZnNldHNbaSQ2XSA6IHRoaXMudGV4dE9mZnNldHNbMF0sXG5cdFx0XHRcdFx0Y29sb3I6ICF0aGlzLmNvbG9yID8gWzAsMCwwLDI1NV0gOiB0aGlzLmNvbG9yLmxlbmd0aCA8PSA0ID8gdGhpcy5jb2xvciA6IHRoaXMuY29sb3Iuc3ViYXJyYXkoaSQ2ICogNCwgaSQ2ICogNCArIDQpLFxuXHRcdFx0XHRcdG9wYWNpdHk6IEFycmF5LmlzQXJyYXkodGhpcy5vcGFjaXR5KSA/IHRoaXMub3BhY2l0eVtpJDZdIDogdGhpcy5vcGFjaXR5LFxuXHRcdFx0XHRcdGJhc2VsaW5lOiB0aGlzLmJhc2VsaW5lT2Zmc2V0W2kkNl0gIT0gbnVsbCA/IHRoaXMuYmFzZWxpbmVPZmZzZXRbaSQ2XSA6IHRoaXMuYmFzZWxpbmVPZmZzZXRbMF0sXG5cdFx0XHRcdFx0YWxpZ246ICF0aGlzLmFsaWduID8gMCA6IHRoaXMuYWxpZ25PZmZzZXRbaSQ2XSAhPSBudWxsID8gdGhpcy5hbGlnbk9mZnNldFtpJDZdIDogdGhpcy5hbGlnbk9mZnNldFswXSxcblx0XHRcdFx0XHRhdGxhczogdGhpcy5mb250QXRsYXNbaSQ2XSB8fCB0aGlzLmZvbnRBdGxhc1swXSxcblx0XHRcdFx0XHRwb3NpdGlvbk9mZnNldDogdGhpcy5wb3NpdGlvbk9mZnNldC5sZW5ndGggPiAyID8gdGhpcy5wb3NpdGlvbk9mZnNldC5zdWJhcnJheShpJDYgKiAyLCBpJDYgKiAyICsgMikgOiB0aGlzLnBvc2l0aW9uT2Zmc2V0XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0Ly8gc2luZ2xlLWNvbG9yLCBzaW5nbGUtYmFzZWxpbmUsIHNpbmdsZS1hbGlnbiBiYXRjaCBpcyBmYXN0ZXIgdG8gcmVuZGVyXG5cdFx0ZWxzZSB7XG5cdFx0XHRpZiAodGhpcy5jb3VudCkge1xuXHRcdFx0XHR0aGlzLmJhdGNoID0gW3tcblx0XHRcdFx0XHRjb3VudDogdGhpcy5jb3VudCxcblx0XHRcdFx0XHRvZmZzZXQ6IDAsXG5cdFx0XHRcdFx0Y29sb3I6IHRoaXMuY29sb3IgfHwgWzAsMCwwLDI1NV0sXG5cdFx0XHRcdFx0b3BhY2l0eTogQXJyYXkuaXNBcnJheSh0aGlzLm9wYWNpdHkpID8gdGhpcy5vcGFjaXR5WzBdIDogdGhpcy5vcGFjaXR5LFxuXHRcdFx0XHRcdGJhc2VsaW5lOiB0aGlzLmJhc2VsaW5lT2Zmc2V0WzBdLFxuXHRcdFx0XHRcdGFsaWduOiB0aGlzLmFsaWduT2Zmc2V0ID8gdGhpcy5hbGlnbk9mZnNldFswXSA6IDAsXG5cdFx0XHRcdFx0YXRsYXM6IHRoaXMuZm9udEF0bGFzWzBdLFxuXHRcdFx0XHRcdHBvc2l0aW9uT2Zmc2V0OiB0aGlzLnBvc2l0aW9uT2Zmc2V0XG5cdFx0XHRcdH1dXG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0dGhpcy5iYXRjaCA9IFtdXG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59O1xuXG5HbFRleHQucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95ICgpIHtcblx0Ly8gVE9ETzogY291bnQgaW5zdGFuY2VzIG9mIGF0bGFzZXMgYW5kIGRlc3Ryb3kgYWxsIG9uIG51bGxcbn07XG5cblxuLy8gZGVmYXVsdHNcbkdsVGV4dC5wcm90b3R5cGUua2VybmluZyA9IHRydWVcbkdsVGV4dC5wcm90b3R5cGUucG9zaXRpb24gPSB7IGNvbnN0YW50OiBuZXcgRmxvYXQzMkFycmF5KDIpIH1cbkdsVGV4dC5wcm90b3R5cGUudHJhbnNsYXRlID0gbnVsbFxuR2xUZXh0LnByb3RvdHlwZS5zY2FsZSA9IG51bGxcbkdsVGV4dC5wcm90b3R5cGUuZm9udCA9IG51bGxcbkdsVGV4dC5wcm90b3R5cGUudGV4dCA9ICcnXG5HbFRleHQucHJvdG90eXBlLnBvc2l0aW9uT2Zmc2V0ID0gWzAsIDBdXG5HbFRleHQucHJvdG90eXBlLm9wYWNpdHkgPSAxXG5HbFRleHQucHJvdG90eXBlLmNvbG9yID0gbmV3IFVpbnQ4QXJyYXkoWzAsIDAsIDAsIDI1NV0pXG5HbFRleHQucHJvdG90eXBlLmFsaWduT2Zmc2V0ID0gWzAsIDBdXG5cblxuLy8gd2hldGhlciB2aWV3cG9ydCBzaG91bGQgYmUgdG9w4oaTYm90dG9tIDJkIG9uZSAodHJ1ZSkgb3Igd2ViZ2wgb25lIChmYWxzZSlcbkdsVGV4dC5ub3JtYWxWaWV3cG9ydCA9IGZhbHNlXG5cbi8vIHNpemUgb2YgYW4gYXRsYXNcbkdsVGV4dC5tYXhBdGxhc1NpemUgPSAxMDI0XG5cbi8vIGZvbnQgYXRsYXMgY2FudmFzIGlzIHNpbmdsZXRvblxuR2xUZXh0LmF0bGFzQ2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcbkdsVGV4dC5hdGxhc0NvbnRleHQgPSBHbFRleHQuYXRsYXNDYW52YXMuZ2V0Q29udGV4dCgnMmQnLCB7YWxwaGE6IGZhbHNlfSlcblxuLy8gZm9udC1zaXplIHVzZWQgZm9yIG1ldHJpY3MsIGF0bGFzIHN0ZXAgY2FsY3VsYXRpb25cbkdsVGV4dC5iYXNlRm9udFNpemUgPSA2NFxuXG4vLyBmb250cyBzdG9yYWdlXG5HbFRleHQuZm9udHMgPSB7fVxuXG4vLyBtYXggbnVtYmVyIG9mIGRpZmZlcmVudCBmb250IGF0bGFzZXMvdGV4dHVyZXMgY2FjaGVkXG4vLyBGSVhNRTogZW5hYmxlIGF0bGFzIHNpemUgbGltaXRhdGlvbiB2aWEgTFJVXG4vLyBHbFRleHQuYXRsYXNDYWNoZVNpemUgPSA2NFxuXG5mdW5jdGlvbiBpc1JlZ2wgKG8pIHtcblx0cmV0dXJuIHR5cGVvZiBvID09PSAnZnVuY3Rpb24nICYmXG5cdG8uX2dsICYmXG5cdG8ucHJvcCAmJlxuXHRvLnRleHR1cmUgJiZcblx0by5idWZmZXJcbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEdsVGV4dFxuXG5cbn0se1wiYml0LXR3aWRkbGVcIjo5MixcImNvbG9yLW5vcm1hbGl6ZVwiOjEyMCxcImNzcy1mb250XCI6MTM5LFwiZGV0ZWN0LWtlcm5pbmdcIjoxNjYsXCJlczYtd2Vhay1tYXBcIjozMTgsXCJmbGF0dGVuLXZlcnRleC1kYXRhXCI6MjI3LFwiZm9udC1hdGxhc1wiOjIyOCxcImZvbnQtbWVhc3VyZVwiOjIyOSxcImdsLXV0aWwvY29udGV4dFwiOjMyMyxcImlzLXBsYWluLW9ialwiOjQyMixcIm9iamVjdC1hc3NpZ25cIjo0NTQsXCJwYXJzZS1yZWN0XCI6NDU5LFwicGFyc2UtdW5pdFwiOjQ2MSxcInBpY2stYnktYWxpYXNcIjo0NjUsXCJyZWdsXCI6NTAyLFwidG8tcHhcIjo1MzksXCJ0eXBlZGFycmF5LXBvb2xcIjo1NDV9XSwzMTg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXyhcIi4vaXMtaW1wbGVtZW50ZWRcIikoKSA/IFdlYWtNYXAgOiBfZGVyZXFfKFwiLi9wb2x5ZmlsbFwiKTtcblxufSx7XCIuL2lzLWltcGxlbWVudGVkXCI6MzE5LFwiLi9wb2x5ZmlsbFwiOjMyMX1dLDMxOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciB3ZWFrTWFwLCBvYmo7XG5cblx0aWYgKHR5cGVvZiBXZWFrTWFwICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiBmYWxzZTtcblx0dHJ5IHtcblx0XHQvLyBXZWJLaXQgZG9lc24ndCBzdXBwb3J0IGFyZ3VtZW50cyBhbmQgY3Jhc2hlc1xuXHRcdHdlYWtNYXAgPSBuZXcgV2Vha01hcChbW29iaiA9IHt9LCBcIm9uZVwiXSwgW3t9LCBcInR3b1wiXSwgW3t9LCBcInRocmVlXCJdXSk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0aWYgKFN0cmluZyh3ZWFrTWFwKSAhPT0gXCJbb2JqZWN0IFdlYWtNYXBdXCIpIHJldHVybiBmYWxzZTtcblx0aWYgKHR5cGVvZiB3ZWFrTWFwLnNldCAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4gZmFsc2U7XG5cdGlmICh3ZWFrTWFwLnNldCh7fSwgMSkgIT09IHdlYWtNYXApIHJldHVybiBmYWxzZTtcblx0aWYgKHR5cGVvZiB3ZWFrTWFwLmRlbGV0ZSAhPT0gXCJmdW5jdGlvblwiKSByZXR1cm4gZmFsc2U7XG5cdGlmICh0eXBlb2Ygd2Vha01hcC5oYXMgIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIGZhbHNlO1xuXHRpZiAod2Vha01hcC5nZXQob2JqKSAhPT0gXCJvbmVcIikgcmV0dXJuIGZhbHNlO1xuXG5cdHJldHVybiB0cnVlO1xufTtcblxufSx7fV0sMzIwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vIEV4cG9ydHMgdHJ1ZSBpZiBlbnZpcm9ubWVudCBwcm92aWRlcyBuYXRpdmUgYFdlYWtNYXBgIGltcGxlbWVudGF0aW9uLCB3aGF0ZXZlciB0aGF0IGlzLlxuXG5cInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gKCkge1xuXHRpZiAodHlwZW9mIFdlYWtNYXAgIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIGZhbHNlO1xuXHRyZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG5ldyBXZWFrTWFwKCkpID09PSBcIltvYmplY3QgV2Vha01hcF1cIjtcbn0oKSk7XG5cbn0se31dLDMyMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGlzVmFsdWUgICAgICAgICAgID0gX2RlcmVxXyhcImVzNS1leHQvb2JqZWN0L2lzLXZhbHVlXCIpXG4gICwgc2V0UHJvdG90eXBlT2YgICAgPSBfZGVyZXFfKFwiZXM1LWV4dC9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZlwiKVxuICAsIG9iamVjdCAgICAgICAgICAgID0gX2RlcmVxXyhcImVzNS1leHQvb2JqZWN0L3ZhbGlkLW9iamVjdFwiKVxuICAsIGVuc3VyZVZhbHVlICAgICAgID0gX2RlcmVxXyhcImVzNS1leHQvb2JqZWN0L3ZhbGlkLXZhbHVlXCIpXG4gICwgcmFuZG9tVW5pcSAgICAgICAgPSBfZGVyZXFfKFwiZXM1LWV4dC9zdHJpbmcvcmFuZG9tLXVuaXFcIilcbiAgLCBkICAgICAgICAgICAgICAgICA9IF9kZXJlcV8oXCJkXCIpXG4gICwgZ2V0SXRlcmF0b3IgICAgICAgPSBfZGVyZXFfKFwiZXM2LWl0ZXJhdG9yL2dldFwiKVxuICAsIGZvck9mICAgICAgICAgICAgID0gX2RlcmVxXyhcImVzNi1pdGVyYXRvci9mb3Itb2ZcIilcbiAgLCB0b1N0cmluZ1RhZ1N5bWJvbCA9IF9kZXJlcV8oXCJlczYtc3ltYm9sXCIpLnRvU3RyaW5nVGFnXG4gICwgaXNOYXRpdmUgICAgICAgICAgPSBfZGVyZXFfKFwiLi9pcy1uYXRpdmUtaW1wbGVtZW50ZWRcIilcblxuICAsIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5LCBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eVxuICAsIG9iakhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eSwgZ2V0UHJvdG90eXBlT2YgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2ZcbiAgLCBXZWFrTWFwUG9seTtcblxubW9kdWxlLmV4cG9ydHMgPSBXZWFrTWFwUG9seSA9IGZ1bmN0aW9uICgvKiBJdGVyYWJsZSovKSB7XG5cdHZhciBpdGVyYWJsZSA9IGFyZ3VtZW50c1swXSwgc2VsZjtcblxuXHRpZiAoISh0aGlzIGluc3RhbmNlb2YgV2Vha01hcFBvbHkpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ29uc3RydWN0b3IgcmVxdWlyZXMgJ25ldydcIik7XG5cdHNlbGYgPSBpc05hdGl2ZSAmJiBzZXRQcm90b3R5cGVPZiAmJiAoV2Vha01hcCAhPT0gV2Vha01hcFBvbHkpXG5cdFx0PyBzZXRQcm90b3R5cGVPZihuZXcgV2Vha01hcCgpLCBnZXRQcm90b3R5cGVPZih0aGlzKSkgOiB0aGlzO1xuXG5cdGlmIChpc1ZhbHVlKGl0ZXJhYmxlKSkge1xuXHRcdGlmICghaXNBcnJheShpdGVyYWJsZSkpIGl0ZXJhYmxlID0gZ2V0SXRlcmF0b3IoaXRlcmFibGUpO1xuXHR9XG5cdGRlZmluZVByb3BlcnR5KHNlbGYsIFwiX193ZWFrTWFwRGF0YV9fXCIsIGQoXCJjXCIsIFwiJHdlYWtNYXAkXCIgKyByYW5kb21VbmlxKCkpKTtcblx0aWYgKCFpdGVyYWJsZSkgcmV0dXJuIHNlbGY7XG5cdGZvck9mKGl0ZXJhYmxlLCBmdW5jdGlvbiAodmFsKSB7XG5cdFx0ZW5zdXJlVmFsdWUodmFsKTtcblx0XHRzZWxmLnNldCh2YWxbMF0sIHZhbFsxXSk7XG5cdH0pO1xuXHRyZXR1cm4gc2VsZjtcbn07XG5cbmlmIChpc05hdGl2ZSkge1xuXHRpZiAoc2V0UHJvdG90eXBlT2YpIHNldFByb3RvdHlwZU9mKFdlYWtNYXBQb2x5LCBXZWFrTWFwKTtcblx0V2Vha01hcFBvbHkucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShXZWFrTWFwLnByb3RvdHlwZSwgeyBjb25zdHJ1Y3RvcjogZChXZWFrTWFwUG9seSkgfSk7XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKFdlYWtNYXBQb2x5LnByb3RvdHlwZSwge1xuXHRkZWxldGU6IGQoZnVuY3Rpb24gKGtleSkge1xuXHRcdGlmIChvYmpIYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdChrZXkpLCB0aGlzLl9fd2Vha01hcERhdGFfXykpIHtcblx0XHRcdGRlbGV0ZSBrZXlbdGhpcy5fX3dlYWtNYXBEYXRhX19dO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiBmYWxzZTtcblx0fSksXG5cdGdldDogZChmdW5jdGlvbiAoa2V5KSB7XG5cdFx0aWYgKCFvYmpIYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdChrZXkpLCB0aGlzLl9fd2Vha01hcERhdGFfXykpIHJldHVybiB1bmRlZmluZWQ7XG5cdFx0cmV0dXJuIGtleVt0aGlzLl9fd2Vha01hcERhdGFfX107XG5cdH0pLFxuXHRoYXM6IGQoZnVuY3Rpb24gKGtleSkge1xuXHRcdHJldHVybiBvYmpIYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdChrZXkpLCB0aGlzLl9fd2Vha01hcERhdGFfXyk7XG5cdH0pLFxuXHRzZXQ6IGQoZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcblx0XHRkZWZpbmVQcm9wZXJ0eShvYmplY3Qoa2V5KSwgdGhpcy5fX3dlYWtNYXBEYXRhX18sIGQoXCJjXCIsIHZhbHVlKSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0pLFxuXHR0b1N0cmluZzogZChmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIFwiW29iamVjdCBXZWFrTWFwXVwiO1xuXHR9KVxufSk7XG5kZWZpbmVQcm9wZXJ0eShXZWFrTWFwUG9seS5wcm90b3R5cGUsIHRvU3RyaW5nVGFnU3ltYm9sLCBkKFwiY1wiLCBcIldlYWtNYXBcIikpO1xuXG59LHtcIi4vaXMtbmF0aXZlLWltcGxlbWVudGVkXCI6MzIwLFwiZFwiOjE1MSxcImVzNS1leHQvb2JqZWN0L2lzLXZhbHVlXCI6MTk0LFwiZXM1LWV4dC9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZlwiOjIwMCxcImVzNS1leHQvb2JqZWN0L3ZhbGlkLW9iamVjdFwiOjIwNCxcImVzNS1leHQvb2JqZWN0L3ZhbGlkLXZhbHVlXCI6MjA1LFwiZXM1LWV4dC9zdHJpbmcvcmFuZG9tLXVuaXFcIjoyMTAsXCJlczYtaXRlcmF0b3IvZm9yLW9mXCI6MjEyLFwiZXM2LWl0ZXJhdG9yL2dldFwiOjIxMyxcImVzNi1zeW1ib2xcIjoyMTl9XSwzMjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBuZGFycmF5ID0gX2RlcmVxXygnbmRhcnJheScpXG52YXIgb3BzICAgICA9IF9kZXJlcV8oJ25kYXJyYXktb3BzJylcbnZhciBwb29sICAgID0gX2RlcmVxXygndHlwZWRhcnJheS1wb29sJylcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVUZXh0dXJlMkRcblxudmFyIGxpbmVhclR5cGVzID0gbnVsbFxudmFyIGZpbHRlclR5cGVzID0gbnVsbFxudmFyIHdyYXBUeXBlcyAgID0gbnVsbFxuXG5mdW5jdGlvbiBsYXp5SW5pdExpbmVhclR5cGVzKGdsKSB7XG4gIGxpbmVhclR5cGVzID0gW1xuICAgIGdsLkxJTkVBUixcbiAgICBnbC5ORUFSRVNUX01JUE1BUF9MSU5FQVIsXG4gICAgZ2wuTElORUFSX01JUE1BUF9ORUFSRVNULFxuICAgIGdsLkxJTkVBUl9NSVBNQVBfTkVBUkVTVFxuICBdXG4gIGZpbHRlclR5cGVzID0gW1xuICAgIGdsLk5FQVJFU1QsXG4gICAgZ2wuTElORUFSLFxuICAgIGdsLk5FQVJFU1RfTUlQTUFQX05FQVJFU1QsXG4gICAgZ2wuTkVBUkVTVF9NSVBNQVBfTElORUFSLFxuICAgIGdsLkxJTkVBUl9NSVBNQVBfTkVBUkVTVCxcbiAgICBnbC5MSU5FQVJfTUlQTUFQX0xJTkVBUlxuICBdXG4gIHdyYXBUeXBlcyA9IFtcbiAgICBnbC5SRVBFQVQsXG4gICAgZ2wuQ0xBTVBfVE9fRURHRSxcbiAgICBnbC5NSVJST1JFRF9SRVBFQVRcbiAgXVxufVxuXG5mdW5jdGlvbiBhY2NlcHRUZXh0dXJlRE9NIChvYmopIHtcbiAgcmV0dXJuIChcbiAgICAoJ3VuZGVmaW5lZCcgIT0gdHlwZW9mIEhUTUxDYW52YXNFbGVtZW50ICYmIG9iaiBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50KSB8fFxuICAgICgndW5kZWZpbmVkJyAhPSB0eXBlb2YgSFRNTEltYWdlRWxlbWVudCAmJiBvYmogaW5zdGFuY2VvZiBIVE1MSW1hZ2VFbGVtZW50KSB8fFxuICAgICgndW5kZWZpbmVkJyAhPSB0eXBlb2YgSFRNTFZpZGVvRWxlbWVudCAmJiBvYmogaW5zdGFuY2VvZiBIVE1MVmlkZW9FbGVtZW50KSB8fFxuICAgICgndW5kZWZpbmVkJyAhPSB0eXBlb2YgSW1hZ2VEYXRhICYmIG9iaiBpbnN0YW5jZW9mIEltYWdlRGF0YSkpXG59XG5cbnZhciBjb252ZXJ0RmxvYXRUb1VpbnQ4ID0gZnVuY3Rpb24ob3V0LCBpbnApIHtcbiAgb3BzLm11bHMob3V0LCBpbnAsIDI1NS4wKVxufVxuXG5mdW5jdGlvbiByZXNoYXBlVGV4dHVyZSh0ZXgsIHcsIGgpIHtcbiAgdmFyIGdsID0gdGV4LmdsXG4gIHZhciBtYXhTaXplID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLk1BWF9URVhUVVJFX1NJWkUpXG4gIGlmKHcgPCAwIHx8IHcgPiBtYXhTaXplIHx8IGggPCAwIHx8IGggPiBtYXhTaXplKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IEludmFsaWQgdGV4dHVyZSBzaXplJylcbiAgfVxuICB0ZXguX3NoYXBlID0gW3csIGhdXG4gIHRleC5iaW5kKClcbiAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCB0ZXguZm9ybWF0LCB3LCBoLCAwLCB0ZXguZm9ybWF0LCB0ZXgudHlwZSwgbnVsbClcbiAgdGV4Ll9taXBMZXZlbHMgPSBbMF1cbiAgcmV0dXJuIHRleFxufVxuXG5mdW5jdGlvbiBUZXh0dXJlMkQoZ2wsIGhhbmRsZSwgd2lkdGgsIGhlaWdodCwgZm9ybWF0LCB0eXBlKSB7XG4gIHRoaXMuZ2wgPSBnbFxuICB0aGlzLmhhbmRsZSA9IGhhbmRsZVxuICB0aGlzLmZvcm1hdCA9IGZvcm1hdFxuICB0aGlzLnR5cGUgPSB0eXBlXG4gIHRoaXMuX3NoYXBlID0gW3dpZHRoLCBoZWlnaHRdXG4gIHRoaXMuX21pcExldmVscyA9IFswXVxuICB0aGlzLl9tYWdGaWx0ZXIgPSBnbC5ORUFSRVNUXG4gIHRoaXMuX21pbkZpbHRlciA9IGdsLk5FQVJFU1RcbiAgdGhpcy5fd3JhcFMgPSBnbC5DTEFNUF9UT19FREdFXG4gIHRoaXMuX3dyYXBUID0gZ2wuQ0xBTVBfVE9fRURHRVxuICB0aGlzLl9hbmlzb1NhbXBsZXMgPSAxXG5cbiAgdmFyIHBhcmVudCA9IHRoaXNcbiAgdmFyIHdyYXBWZWN0b3IgPSBbdGhpcy5fd3JhcFMsIHRoaXMuX3dyYXBUXVxuICBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh3cmFwVmVjdG9yLCBbXG4gICAge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHBhcmVudC5fd3JhcFNcbiAgICAgIH0sXG4gICAgICBzZXQ6IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgcmV0dXJuIHBhcmVudC53cmFwUyA9IHZcbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQuX3dyYXBUXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQud3JhcFQgPSB2XG4gICAgICB9XG4gICAgfVxuICBdKVxuICB0aGlzLl93cmFwVmVjdG9yID0gd3JhcFZlY3RvclxuXG4gIHZhciBzaGFwZVZlY3RvciA9IFt0aGlzLl9zaGFwZVswXSwgdGhpcy5fc2hhcGVbMV1dXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHNoYXBlVmVjdG9yLCBbXG4gICAge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHBhcmVudC5fc2hhcGVbMF1cbiAgICAgIH0sXG4gICAgICBzZXQ6IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgcmV0dXJuIHBhcmVudC53aWR0aCA9IHZcbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQuX3NoYXBlWzFdXG4gICAgICB9LFxuICAgICAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgICAgIHJldHVybiBwYXJlbnQuaGVpZ2h0ID0gdlxuICAgICAgfVxuICAgIH1cbiAgXSlcbiAgdGhpcy5fc2hhcGVWZWN0b3IgPSBzaGFwZVZlY3RvclxufVxuXG52YXIgcHJvdG8gPSBUZXh0dXJlMkQucHJvdG90eXBlXG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHByb3RvLCB7XG4gIG1pbkZpbHRlcjoge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fbWluRmlsdGVyXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHYpIHtcbiAgICAgIHRoaXMuYmluZCgpXG4gICAgICB2YXIgZ2wgPSB0aGlzLmdsXG4gICAgICBpZih0aGlzLnR5cGUgPT09IGdsLkZMT0FUICYmIGxpbmVhclR5cGVzLmluZGV4T2YodikgPj0gMCkge1xuICAgICAgICBpZighZ2wuZ2V0RXh0ZW5zaW9uKCdPRVNfdGV4dHVyZV9mbG9hdF9saW5lYXInKSkge1xuICAgICAgICAgIHYgPSBnbC5ORUFSRVNUXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmKGZpbHRlclR5cGVzLmluZGV4T2YodikgPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBVbmtub3duIGZpbHRlciBtb2RlICcgKyB2KVxuICAgICAgfVxuICAgICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIHYpXG4gICAgICByZXR1cm4gdGhpcy5fbWluRmlsdGVyID0gdlxuICAgIH1cbiAgfSxcbiAgbWFnRmlsdGVyOiB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl9tYWdGaWx0ZXJcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgdGhpcy5iaW5kKClcbiAgICAgIHZhciBnbCA9IHRoaXMuZ2xcbiAgICAgIGlmKHRoaXMudHlwZSA9PT0gZ2wuRkxPQVQgJiYgbGluZWFyVHlwZXMuaW5kZXhPZih2KSA+PSAwKSB7XG4gICAgICAgIGlmKCFnbC5nZXRFeHRlbnNpb24oJ09FU190ZXh0dXJlX2Zsb2F0X2xpbmVhcicpKSB7XG4gICAgICAgICAgdiA9IGdsLk5FQVJFU1RcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYoZmlsdGVyVHlwZXMuaW5kZXhPZih2KSA8IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IFVua25vd24gZmlsdGVyIG1vZGUgJyArIHYpXG4gICAgICB9XG4gICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfTUFHX0ZJTFRFUiwgdilcbiAgICAgIHJldHVybiB0aGlzLl9tYWdGaWx0ZXIgPSB2XG4gICAgfVxuICB9LFxuICBtaXBTYW1wbGVzOiB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl9hbmlzb1NhbXBsZXNcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24oaSkge1xuICAgICAgdmFyIHBzYW1wbGVzID0gdGhpcy5fYW5pc29TYW1wbGVzXG4gICAgICB0aGlzLl9hbmlzb1NhbXBsZXMgPSBNYXRoLm1heChpLCAxKXwwXG4gICAgICBpZihwc2FtcGxlcyAhPT0gdGhpcy5fYW5pc29TYW1wbGVzKSB7XG4gICAgICAgIHZhciBleHQgPSB0aGlzLmdsLmdldEV4dGVuc2lvbignRVhUX3RleHR1cmVfZmlsdGVyX2FuaXNvdHJvcGljJylcbiAgICAgICAgaWYoZXh0KSB7XG4gICAgICAgICAgdGhpcy5nbC50ZXhQYXJhbWV0ZXJmKHRoaXMuZ2wuVEVYVFVSRV8yRCwgZXh0LlRFWFRVUkVfTUFYX0FOSVNPVFJPUFlfRVhULCB0aGlzLl9hbmlzb1NhbXBsZXMpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLl9hbmlzb1NhbXBsZXNcbiAgICB9XG4gIH0sXG4gIHdyYXBTOiB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl93cmFwU1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgICB0aGlzLmJpbmQoKVxuICAgICAgaWYod3JhcFR5cGVzLmluZGV4T2YodikgPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBVbmtub3duIHdyYXAgbW9kZSAnICsgdilcbiAgICAgIH1cbiAgICAgIHRoaXMuZ2wudGV4UGFyYW1ldGVyaSh0aGlzLmdsLlRFWFRVUkVfMkQsIHRoaXMuZ2wuVEVYVFVSRV9XUkFQX1MsIHYpXG4gICAgICByZXR1cm4gdGhpcy5fd3JhcFMgPSB2XG4gICAgfVxuICB9LFxuICB3cmFwVDoge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fd3JhcFRcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24odikge1xuICAgICAgdGhpcy5iaW5kKClcbiAgICAgIGlmKHdyYXBUeXBlcy5pbmRleE9mKHYpIDwgMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogVW5rbm93biB3cmFwIG1vZGUgJyArIHYpXG4gICAgICB9XG4gICAgICB0aGlzLmdsLnRleFBhcmFtZXRlcmkodGhpcy5nbC5URVhUVVJFXzJELCB0aGlzLmdsLlRFWFRVUkVfV1JBUF9ULCB2KVxuICAgICAgcmV0dXJuIHRoaXMuX3dyYXBUID0gdlxuICAgIH1cbiAgfSxcbiAgd3JhcDoge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fd3JhcFZlY3RvclxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbih2KSB7XG4gICAgICBpZighQXJyYXkuaXNBcnJheSh2KSkge1xuICAgICAgICB2ID0gW3Ysdl1cbiAgICAgIH1cbiAgICAgIGlmKHYubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBNdXN0IHNwZWNpZnkgd3JhcCBtb2RlIGZvciByb3dzIGFuZCBjb2x1bW5zJylcbiAgICAgIH1cbiAgICAgIGZvcih2YXIgaT0wOyBpPDI7ICsraSkge1xuICAgICAgICBpZih3cmFwVHlwZXMuaW5kZXhPZih2W2ldKSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogVW5rbm93biB3cmFwIG1vZGUgJyArIHYpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMuX3dyYXBTID0gdlswXVxuICAgICAgdGhpcy5fd3JhcFQgPSB2WzFdXG5cbiAgICAgIHZhciBnbCA9IHRoaXMuZ2xcbiAgICAgIHRoaXMuYmluZCgpXG4gICAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCB0aGlzLl93cmFwUylcbiAgICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9XUkFQX1QsIHRoaXMuX3dyYXBUKVxuXG4gICAgICByZXR1cm4gdlxuICAgIH1cbiAgfSxcbiAgc2hhcGU6IHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3NoYXBlVmVjdG9yXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHgpIHtcbiAgICAgIGlmKCFBcnJheS5pc0FycmF5KHgpKSB7XG4gICAgICAgIHggPSBbeHwwLHh8MF1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKHgubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IEludmFsaWQgdGV4dHVyZSBzaGFwZScpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJlc2hhcGVUZXh0dXJlKHRoaXMsIHhbMF18MCwgeFsxXXwwKVxuICAgICAgcmV0dXJuIFt4WzBdfDAsIHhbMV18MF1cbiAgICB9XG4gIH0sXG4gIHdpZHRoOiB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl9zaGFwZVswXVxuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbih3KSB7XG4gICAgICB3ID0gd3wwXG4gICAgICByZXNoYXBlVGV4dHVyZSh0aGlzLCB3LCB0aGlzLl9zaGFwZVsxXSlcbiAgICAgIHJldHVybiB3XG4gICAgfVxuICB9LFxuICBoZWlnaHQ6IHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3NoYXBlWzFdXG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKGgpIHtcbiAgICAgIGggPSBofDBcbiAgICAgIHJlc2hhcGVUZXh0dXJlKHRoaXMsIHRoaXMuX3NoYXBlWzBdLCBoKVxuICAgICAgcmV0dXJuIGhcbiAgICB9XG4gIH1cbn0pXG5cbnByb3RvLmJpbmQgPSBmdW5jdGlvbih1bml0KSB7XG4gIHZhciBnbCA9IHRoaXMuZ2xcbiAgaWYodW5pdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgZ2wuYWN0aXZlVGV4dHVyZShnbC5URVhUVVJFMCArICh1bml0fDApKVxuICB9XG4gIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRoaXMuaGFuZGxlKVxuICBpZih1bml0ICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gKHVuaXR8MClcbiAgfVxuICByZXR1cm4gZ2wuZ2V0UGFyYW1ldGVyKGdsLkFDVElWRV9URVhUVVJFKSAtIGdsLlRFWFRVUkUwXG59XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5nbC5kZWxldGVUZXh0dXJlKHRoaXMuaGFuZGxlKVxufVxuXG5wcm90by5nZW5lcmF0ZU1pcG1hcCA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmJpbmQoKVxuICB0aGlzLmdsLmdlbmVyYXRlTWlwbWFwKHRoaXMuZ2wuVEVYVFVSRV8yRClcblxuICAvL1VwZGF0ZSBtaXAgbGV2ZWxzXG4gIHZhciBsID0gTWF0aC5taW4odGhpcy5fc2hhcGVbMF0sIHRoaXMuX3NoYXBlWzFdKVxuICBmb3IodmFyIGk9MDsgbD4wOyArK2ksIGw+Pj49MSkge1xuICAgIGlmKHRoaXMuX21pcExldmVscy5pbmRleE9mKGkpIDwgMCkge1xuICAgICAgdGhpcy5fbWlwTGV2ZWxzLnB1c2goaSlcbiAgICB9XG4gIH1cbn1cblxucHJvdG8uc2V0UGl4ZWxzID0gZnVuY3Rpb24oZGF0YSwgeF9vZmYsIHlfb2ZmLCBtaXBfbGV2ZWwpIHtcbiAgdmFyIGdsID0gdGhpcy5nbFxuICB0aGlzLmJpbmQoKVxuICBpZihBcnJheS5pc0FycmF5KHhfb2ZmKSkge1xuICAgIG1pcF9sZXZlbCA9IHlfb2ZmXG4gICAgeV9vZmYgPSB4X29mZlsxXXwwXG4gICAgeF9vZmYgPSB4X29mZlswXXwwXG4gIH0gZWxzZSB7XG4gICAgeF9vZmYgPSB4X29mZiB8fCAwXG4gICAgeV9vZmYgPSB5X29mZiB8fCAwXG4gIH1cbiAgbWlwX2xldmVsID0gbWlwX2xldmVsIHx8IDBcbiAgdmFyIGRpcmVjdERhdGEgPSBhY2NlcHRUZXh0dXJlRE9NKGRhdGEpID8gZGF0YSA6IGRhdGEucmF3XG4gIGlmKGRpcmVjdERhdGEpIHtcbiAgICB2YXIgbmVlZHNNaXAgPSB0aGlzLl9taXBMZXZlbHMuaW5kZXhPZihtaXBfbGV2ZWwpIDwgMFxuICAgIGlmKG5lZWRzTWlwKSB7XG4gICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIHRoaXMuZm9ybWF0LCB0aGlzLmZvcm1hdCwgdGhpcy50eXBlLCBkaXJlY3REYXRhKVxuICAgICAgdGhpcy5fbWlwTGV2ZWxzLnB1c2gobWlwX2xldmVsKVxuICAgIH0gZWxzZSB7XG4gICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIG1pcF9sZXZlbCwgeF9vZmYsIHlfb2ZmLCB0aGlzLmZvcm1hdCwgdGhpcy50eXBlLCBkaXJlY3REYXRhKVxuICAgIH1cbiAgfSBlbHNlIGlmKGRhdGEuc2hhcGUgJiYgZGF0YS5zdHJpZGUgJiYgZGF0YS5kYXRhKSB7XG4gICAgaWYoZGF0YS5zaGFwZS5sZW5ndGggPCAyIHx8XG4gICAgICAgeF9vZmYgKyBkYXRhLnNoYXBlWzFdID4gdGhpcy5fc2hhcGVbMV0+Pj5taXBfbGV2ZWwgfHxcbiAgICAgICB5X29mZiArIGRhdGEuc2hhcGVbMF0gPiB0aGlzLl9zaGFwZVswXT4+Pm1pcF9sZXZlbCB8fFxuICAgICAgIHhfb2ZmIDwgMCB8fFxuICAgICAgIHlfb2ZmIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IFRleHR1cmUgZGltZW5zaW9ucyBhcmUgb3V0IG9mIGJvdW5kcycpXG4gICAgfVxuICAgIHRleFN1YkltYWdlQXJyYXkoZ2wsIHhfb2ZmLCB5X29mZiwgbWlwX2xldmVsLCB0aGlzLmZvcm1hdCwgdGhpcy50eXBlLCB0aGlzLl9taXBMZXZlbHMsIGRhdGEpXG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IFVuc3VwcG9ydGVkIGRhdGEgdHlwZScpXG4gIH1cbn1cblxuXG5mdW5jdGlvbiBpc1BhY2tlZChzaGFwZSwgc3RyaWRlKSB7XG4gIGlmKHNoYXBlLmxlbmd0aCA9PT0gMykge1xuICAgIHJldHVybiAgKHN0cmlkZVsyXSA9PT0gMSkgJiZcbiAgICAgICAgICAgIChzdHJpZGVbMV0gPT09IHNoYXBlWzBdKnNoYXBlWzJdKSAmJlxuICAgICAgICAgICAgKHN0cmlkZVswXSA9PT0gc2hhcGVbMl0pXG4gIH1cbiAgcmV0dXJuICAoc3RyaWRlWzBdID09PSAxKSAmJlxuICAgICAgICAgIChzdHJpZGVbMV0gPT09IHNoYXBlWzBdKVxufVxuXG5mdW5jdGlvbiB0ZXhTdWJJbWFnZUFycmF5KGdsLCB4X29mZiwgeV9vZmYsIG1pcF9sZXZlbCwgY2Zvcm1hdCwgY3R5cGUsIG1pcExldmVscywgYXJyYXkpIHtcbiAgdmFyIGR0eXBlID0gYXJyYXkuZHR5cGVcbiAgdmFyIHNoYXBlID0gYXJyYXkuc2hhcGUuc2xpY2UoKVxuICBpZihzaGFwZS5sZW5ndGggPCAyIHx8IHNoYXBlLmxlbmd0aCA+IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogSW52YWxpZCBuZGFycmF5LCBtdXN0IGJlIDJkIG9yIDNkJylcbiAgfVxuICB2YXIgdHlwZSA9IDAsIGZvcm1hdCA9IDBcbiAgdmFyIHBhY2tlZCA9IGlzUGFja2VkKHNoYXBlLCBhcnJheS5zdHJpZGUuc2xpY2UoKSlcbiAgaWYoZHR5cGUgPT09ICdmbG9hdDMyJykge1xuICAgIHR5cGUgPSBnbC5GTE9BVFxuICB9IGVsc2UgaWYoZHR5cGUgPT09ICdmbG9hdDY0Jykge1xuICAgIHR5cGUgPSBnbC5GTE9BVFxuICAgIHBhY2tlZCA9IGZhbHNlXG4gICAgZHR5cGUgPSAnZmxvYXQzMidcbiAgfSBlbHNlIGlmKGR0eXBlID09PSAndWludDgnKSB7XG4gICAgdHlwZSA9IGdsLlVOU0lHTkVEX0JZVEVcbiAgfSBlbHNlIHtcbiAgICB0eXBlID0gZ2wuVU5TSUdORURfQllURVxuICAgIHBhY2tlZCA9IGZhbHNlXG4gICAgZHR5cGUgPSAndWludDgnXG4gIH1cbiAgdmFyIGNoYW5uZWxzID0gMVxuICBpZihzaGFwZS5sZW5ndGggPT09IDIpIHtcbiAgICBmb3JtYXQgPSBnbC5MVU1JTkFOQ0VcbiAgICBzaGFwZSA9IFtzaGFwZVswXSwgc2hhcGVbMV0sIDFdXG4gICAgYXJyYXkgPSBuZGFycmF5KGFycmF5LmRhdGEsIHNoYXBlLCBbYXJyYXkuc3RyaWRlWzBdLCBhcnJheS5zdHJpZGVbMV0sIDFdLCBhcnJheS5vZmZzZXQpXG4gIH0gZWxzZSBpZihzaGFwZS5sZW5ndGggPT09IDMpIHtcbiAgICBpZihzaGFwZVsyXSA9PT0gMSkge1xuICAgICAgZm9ybWF0ID0gZ2wuQUxQSEFcbiAgICB9IGVsc2UgaWYoc2hhcGVbMl0gPT09IDIpIHtcbiAgICAgIGZvcm1hdCA9IGdsLkxVTUlOQU5DRV9BTFBIQVxuICAgIH0gZWxzZSBpZihzaGFwZVsyXSA9PT0gMykge1xuICAgICAgZm9ybWF0ID0gZ2wuUkdCXG4gICAgfSBlbHNlIGlmKHNoYXBlWzJdID09PSA0KSB7XG4gICAgICBmb3JtYXQgPSBnbC5SR0JBXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBJbnZhbGlkIHNoYXBlIGZvciBwaXhlbCBjb29yZHMnKVxuICAgIH1cbiAgICBjaGFubmVscyA9IHNoYXBlWzJdXG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IEludmFsaWQgc2hhcGUgZm9yIHRleHR1cmUnKVxuICB9XG4gIC8vRm9yIDEtY2hhbm5lbCB0ZXh0dXJlcyBhbGxvdyBjb252ZXJzaW9uIGJldHdlZW4gZm9ybWF0c1xuICBpZigoZm9ybWF0ICA9PT0gZ2wuTFVNSU5BTkNFIHx8IGZvcm1hdCAgPT09IGdsLkFMUEhBKSAmJlxuICAgICAoY2Zvcm1hdCA9PT0gZ2wuTFVNSU5BTkNFIHx8IGNmb3JtYXQgPT09IGdsLkFMUEhBKSkge1xuICAgIGZvcm1hdCA9IGNmb3JtYXRcbiAgfVxuICBpZihmb3JtYXQgIT09IGNmb3JtYXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogSW5jb21wYXRpYmxlIHRleHR1cmUgZm9ybWF0IGZvciBzZXRQaXhlbHMnKVxuICB9XG4gIHZhciBzaXplID0gYXJyYXkuc2l6ZVxuICB2YXIgbmVlZHNNaXAgPSBtaXBMZXZlbHMuaW5kZXhPZihtaXBfbGV2ZWwpIDwgMFxuICBpZihuZWVkc01pcCkge1xuICAgIG1pcExldmVscy5wdXNoKG1pcF9sZXZlbClcbiAgfVxuICBpZih0eXBlID09PSBjdHlwZSAmJiBwYWNrZWQpIHtcbiAgICAvL0FycmF5IGRhdGEgdHlwZXMgYXJlIGNvbXBhdGlibGUsIGNhbiBkaXJlY3RseSBjb3B5IGludG8gdGV4dHVyZVxuICAgIGlmKGFycmF5Lm9mZnNldCA9PT0gMCAmJiBhcnJheS5kYXRhLmxlbmd0aCA9PT0gc2l6ZSkge1xuICAgICAgaWYobmVlZHNNaXApIHtcbiAgICAgICAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCBtaXBfbGV2ZWwsIGNmb3JtYXQsIHNoYXBlWzBdLCBzaGFwZVsxXSwgMCwgY2Zvcm1hdCwgY3R5cGUsIGFycmF5LmRhdGEpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnbC50ZXhTdWJJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIG1pcF9sZXZlbCwgeF9vZmYsIHlfb2ZmLCBzaGFwZVswXSwgc2hhcGVbMV0sIGNmb3JtYXQsIGN0eXBlLCBhcnJheS5kYXRhKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZihuZWVkc01pcCkge1xuICAgICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIG1pcF9sZXZlbCwgY2Zvcm1hdCwgc2hhcGVbMF0sIHNoYXBlWzFdLCAwLCBjZm9ybWF0LCBjdHlwZSwgYXJyYXkuZGF0YS5zdWJhcnJheShhcnJheS5vZmZzZXQsIGFycmF5Lm9mZnNldCtzaXplKSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGdsLnRleFN1YkltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgbWlwX2xldmVsLCB4X29mZiwgeV9vZmYsIHNoYXBlWzBdLCBzaGFwZVsxXSwgY2Zvcm1hdCwgY3R5cGUsIGFycmF5LmRhdGEuc3ViYXJyYXkoYXJyYXkub2Zmc2V0LCBhcnJheS5vZmZzZXQrc2l6ZSkpXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vTmVlZCB0byBkbyB0eXBlIGNvbnZlcnNpb24gdG8gcGFjayBkYXRhIGludG8gYnVmZmVyXG4gICAgdmFyIHBhY2tfYnVmZmVyXG4gICAgaWYoY3R5cGUgPT09IGdsLkZMT0FUKSB7XG4gICAgICBwYWNrX2J1ZmZlciA9IHBvb2wubWFsbG9jRmxvYXQzMihzaXplKVxuICAgIH0gZWxzZSB7XG4gICAgICBwYWNrX2J1ZmZlciA9IHBvb2wubWFsbG9jVWludDgoc2l6ZSlcbiAgICB9XG4gICAgdmFyIHBhY2tfdmlldyA9IG5kYXJyYXkocGFja19idWZmZXIsIHNoYXBlLCBbc2hhcGVbMl0sIHNoYXBlWzJdKnNoYXBlWzBdLCAxXSlcbiAgICBpZih0eXBlID09PSBnbC5GTE9BVCAmJiBjdHlwZSA9PT0gZ2wuVU5TSUdORURfQllURSkge1xuICAgICAgY29udmVydEZsb2F0VG9VaW50OChwYWNrX3ZpZXcsIGFycmF5KVxuICAgIH0gZWxzZSB7XG4gICAgICBvcHMuYXNzaWduKHBhY2tfdmlldywgYXJyYXkpXG4gICAgfVxuICAgIGlmKG5lZWRzTWlwKSB7XG4gICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIG1pcF9sZXZlbCwgY2Zvcm1hdCwgc2hhcGVbMF0sIHNoYXBlWzFdLCAwLCBjZm9ybWF0LCBjdHlwZSwgcGFja19idWZmZXIuc3ViYXJyYXkoMCwgc2l6ZSkpXG4gICAgfSBlbHNlIHtcbiAgICAgIGdsLnRleFN1YkltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgbWlwX2xldmVsLCB4X29mZiwgeV9vZmYsIHNoYXBlWzBdLCBzaGFwZVsxXSwgY2Zvcm1hdCwgY3R5cGUsIHBhY2tfYnVmZmVyLnN1YmFycmF5KDAsIHNpemUpKVxuICAgIH1cbiAgICBpZihjdHlwZSA9PT0gZ2wuRkxPQVQpIHtcbiAgICAgIHBvb2wuZnJlZUZsb2F0MzIocGFja19idWZmZXIpXG4gICAgfSBlbHNlIHtcbiAgICAgIHBvb2wuZnJlZVVpbnQ4KHBhY2tfYnVmZmVyKVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBpbml0VGV4dHVyZShnbCkge1xuICB2YXIgdGV4ID0gZ2wuY3JlYXRlVGV4dHVyZSgpXG4gIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRleClcbiAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGdsLk5FQVJFU1QpXG4gIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5ORUFSRVNUKVxuICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKVxuICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKVxuICByZXR1cm4gdGV4XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVRleHR1cmVTaGFwZShnbCwgd2lkdGgsIGhlaWdodCwgZm9ybWF0LCB0eXBlKSB7XG4gIHZhciBtYXhUZXh0dXJlU2l6ZSA9IGdsLmdldFBhcmFtZXRlcihnbC5NQVhfVEVYVFVSRV9TSVpFKVxuICBpZih3aWR0aCA8IDAgfHwgd2lkdGggPiBtYXhUZXh0dXJlU2l6ZSB8fCBoZWlnaHQgPCAwIHx8IGhlaWdodCAgPiBtYXhUZXh0dXJlU2l6ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBJbnZhbGlkIHRleHR1cmUgc2hhcGUnKVxuICB9XG4gIGlmKHR5cGUgPT09IGdsLkZMT0FUICYmICFnbC5nZXRFeHRlbnNpb24oJ09FU190ZXh0dXJlX2Zsb2F0JykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogRmxvYXRpbmcgcG9pbnQgdGV4dHVyZXMgbm90IHN1cHBvcnRlZCBvbiB0aGlzIHBsYXRmb3JtJylcbiAgfVxuICB2YXIgdGV4ID0gaW5pdFRleHR1cmUoZ2wpXG4gIGdsLnRleEltYWdlMkQoZ2wuVEVYVFVSRV8yRCwgMCwgZm9ybWF0LCB3aWR0aCwgaGVpZ2h0LCAwLCBmb3JtYXQsIHR5cGUsIG51bGwpXG4gIHJldHVybiBuZXcgVGV4dHVyZTJEKGdsLCB0ZXgsIHdpZHRoLCBoZWlnaHQsIGZvcm1hdCwgdHlwZSlcbn1cblxuZnVuY3Rpb24gY3JlYXRlVGV4dHVyZURPTShnbCwgZGlyZWN0RGF0YSwgd2lkdGgsIGhlaWdodCwgZm9ybWF0LCB0eXBlKSB7XG4gIHZhciB0ZXggPSBpbml0VGV4dHVyZShnbClcbiAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBmb3JtYXQsIGZvcm1hdCwgdHlwZSwgZGlyZWN0RGF0YSlcbiAgcmV0dXJuIG5ldyBUZXh0dXJlMkQoZ2wsIHRleCwgd2lkdGgsIGhlaWdodCwgZm9ybWF0LCB0eXBlKVxufVxuXG4vL0NyZWF0ZXMgYSB0ZXh0dXJlIGZyb20gYW4gbmRhcnJheVxuZnVuY3Rpb24gY3JlYXRlVGV4dHVyZUFycmF5KGdsLCBhcnJheSkge1xuICB2YXIgZHR5cGUgPSBhcnJheS5kdHlwZVxuICB2YXIgc2hhcGUgPSBhcnJheS5zaGFwZS5zbGljZSgpXG4gIHZhciBtYXhTaXplID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLk1BWF9URVhUVVJFX1NJWkUpXG4gIGlmKHNoYXBlWzBdIDwgMCB8fCBzaGFwZVswXSA+IG1heFNpemUgfHwgc2hhcGVbMV0gPCAwIHx8IHNoYXBlWzFdID4gbWF4U2l6ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBJbnZhbGlkIHRleHR1cmUgc2l6ZScpXG4gIH1cbiAgdmFyIHBhY2tlZCA9IGlzUGFja2VkKHNoYXBlLCBhcnJheS5zdHJpZGUuc2xpY2UoKSlcbiAgdmFyIHR5cGUgPSAwXG4gIGlmKGR0eXBlID09PSAnZmxvYXQzMicpIHtcbiAgICB0eXBlID0gZ2wuRkxPQVRcbiAgfSBlbHNlIGlmKGR0eXBlID09PSAnZmxvYXQ2NCcpIHtcbiAgICB0eXBlID0gZ2wuRkxPQVRcbiAgICBwYWNrZWQgPSBmYWxzZVxuICAgIGR0eXBlID0gJ2Zsb2F0MzInXG4gIH0gZWxzZSBpZihkdHlwZSA9PT0gJ3VpbnQ4Jykge1xuICAgIHR5cGUgPSBnbC5VTlNJR05FRF9CWVRFXG4gIH0gZWxzZSB7XG4gICAgdHlwZSA9IGdsLlVOU0lHTkVEX0JZVEVcbiAgICBwYWNrZWQgPSBmYWxzZVxuICAgIGR0eXBlID0gJ3VpbnQ4J1xuICB9XG4gIHZhciBmb3JtYXQgPSAwXG4gIGlmKHNoYXBlLmxlbmd0aCA9PT0gMikge1xuICAgIGZvcm1hdCA9IGdsLkxVTUlOQU5DRVxuICAgIHNoYXBlID0gW3NoYXBlWzBdLCBzaGFwZVsxXSwgMV1cbiAgICBhcnJheSA9IG5kYXJyYXkoYXJyYXkuZGF0YSwgc2hhcGUsIFthcnJheS5zdHJpZGVbMF0sIGFycmF5LnN0cmlkZVsxXSwgMV0sIGFycmF5Lm9mZnNldClcbiAgfSBlbHNlIGlmKHNoYXBlLmxlbmd0aCA9PT0gMykge1xuICAgIGlmKHNoYXBlWzJdID09PSAxKSB7XG4gICAgICBmb3JtYXQgPSBnbC5BTFBIQVxuICAgIH0gZWxzZSBpZihzaGFwZVsyXSA9PT0gMikge1xuICAgICAgZm9ybWF0ID0gZ2wuTFVNSU5BTkNFX0FMUEhBXG4gICAgfSBlbHNlIGlmKHNoYXBlWzJdID09PSAzKSB7XG4gICAgICBmb3JtYXQgPSBnbC5SR0JcbiAgICB9IGVsc2UgaWYoc2hhcGVbMl0gPT09IDQpIHtcbiAgICAgIGZvcm1hdCA9IGdsLlJHQkFcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IEludmFsaWQgc2hhcGUgZm9yIHBpeGVsIGNvb3JkcycpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignZ2wtdGV4dHVyZTJkOiBJbnZhbGlkIHNoYXBlIGZvciB0ZXh0dXJlJylcbiAgfVxuICBpZih0eXBlID09PSBnbC5GTE9BVCAmJiAhZ2wuZ2V0RXh0ZW5zaW9uKCdPRVNfdGV4dHVyZV9mbG9hdCcpKSB7XG4gICAgdHlwZSA9IGdsLlVOU0lHTkVEX0JZVEVcbiAgICBwYWNrZWQgPSBmYWxzZVxuICB9XG4gIHZhciBidWZmZXIsIGJ1Zl9zdG9yZVxuICB2YXIgc2l6ZSA9IGFycmF5LnNpemVcbiAgaWYoIXBhY2tlZCkge1xuICAgIHZhciBzdHJpZGUgPSBbc2hhcGVbMl0sIHNoYXBlWzJdKnNoYXBlWzBdLCAxXVxuICAgIGJ1Zl9zdG9yZSA9IHBvb2wubWFsbG9jKHNpemUsIGR0eXBlKVxuICAgIHZhciBidWZfYXJyYXkgPSBuZGFycmF5KGJ1Zl9zdG9yZSwgc2hhcGUsIHN0cmlkZSwgMClcbiAgICBpZigoZHR5cGUgPT09ICdmbG9hdDMyJyB8fCBkdHlwZSA9PT0gJ2Zsb2F0NjQnKSAmJiB0eXBlID09PSBnbC5VTlNJR05FRF9CWVRFKSB7XG4gICAgICBjb252ZXJ0RmxvYXRUb1VpbnQ4KGJ1Zl9hcnJheSwgYXJyYXkpXG4gICAgfSBlbHNlIHtcbiAgICAgIG9wcy5hc3NpZ24oYnVmX2FycmF5LCBhcnJheSlcbiAgICB9XG4gICAgYnVmZmVyID0gYnVmX3N0b3JlLnN1YmFycmF5KDAsIHNpemUpXG4gIH0gZWxzZSBpZiAoYXJyYXkub2Zmc2V0ID09PSAwICYmIGFycmF5LmRhdGEubGVuZ3RoID09PSBzaXplKSB7XG4gICAgYnVmZmVyID0gYXJyYXkuZGF0YVxuICB9IGVsc2Uge1xuICAgIGJ1ZmZlciA9IGFycmF5LmRhdGEuc3ViYXJyYXkoYXJyYXkub2Zmc2V0LCBhcnJheS5vZmZzZXQgKyBzaXplKVxuICB9XG4gIHZhciB0ZXggPSBpbml0VGV4dHVyZShnbClcbiAgZ2wudGV4SW1hZ2UyRChnbC5URVhUVVJFXzJELCAwLCBmb3JtYXQsIHNoYXBlWzBdLCBzaGFwZVsxXSwgMCwgZm9ybWF0LCB0eXBlLCBidWZmZXIpXG4gIGlmKCFwYWNrZWQpIHtcbiAgICBwb29sLmZyZWUoYnVmX3N0b3JlKVxuICB9XG4gIHJldHVybiBuZXcgVGV4dHVyZTJEKGdsLCB0ZXgsIHNoYXBlWzBdLCBzaGFwZVsxXSwgZm9ybWF0LCB0eXBlKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVUZXh0dXJlMkQoZ2wpIHtcbiAgaWYoYXJndW1lbnRzLmxlbmd0aCA8PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdnbC10ZXh0dXJlMmQ6IE1pc3NpbmcgYXJndW1lbnRzIGZvciB0ZXh0dXJlMmQgY29uc3RydWN0b3InKVxuICB9XG4gIGlmKCFsaW5lYXJUeXBlcykge1xuICAgIGxhenlJbml0TGluZWFyVHlwZXMoZ2wpXG4gIH1cbiAgaWYodHlwZW9mIGFyZ3VtZW50c1sxXSA9PT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gY3JlYXRlVGV4dHVyZVNoYXBlKGdsLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSwgYXJndW1lbnRzWzNdfHxnbC5SR0JBLCBhcmd1bWVudHNbNF18fGdsLlVOU0lHTkVEX0JZVEUpXG4gIH1cbiAgaWYoQXJyYXkuaXNBcnJheShhcmd1bWVudHNbMV0pKSB7XG4gICAgcmV0dXJuIGNyZWF0ZVRleHR1cmVTaGFwZShnbCwgYXJndW1lbnRzWzFdWzBdfDAsIGFyZ3VtZW50c1sxXVsxXXwwLCBhcmd1bWVudHNbMl18fGdsLlJHQkEsIGFyZ3VtZW50c1szXXx8Z2wuVU5TSUdORURfQllURSlcbiAgfVxuICBpZih0eXBlb2YgYXJndW1lbnRzWzFdID09PSAnb2JqZWN0Jykge1xuICAgIHZhciBvYmogPSBhcmd1bWVudHNbMV1cbiAgICB2YXIgZGlyZWN0RGF0YSA9IGFjY2VwdFRleHR1cmVET00ob2JqKSA/IG9iaiA6IG9iai5yYXdcbiAgICBpZiAoZGlyZWN0RGF0YSkge1xuICAgICAgcmV0dXJuIGNyZWF0ZVRleHR1cmVET00oZ2wsIGRpcmVjdERhdGEsIG9iai53aWR0aHwwLCBvYmouaGVpZ2h0fDAsIGFyZ3VtZW50c1syXXx8Z2wuUkdCQSwgYXJndW1lbnRzWzNdfHxnbC5VTlNJR05FRF9CWVRFKVxuICAgIH0gZWxzZSBpZihvYmouc2hhcGUgJiYgb2JqLmRhdGEgJiYgb2JqLnN0cmlkZSkge1xuICAgICAgcmV0dXJuIGNyZWF0ZVRleHR1cmVBcnJheShnbCwgb2JqKVxuICAgIH1cbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoJ2dsLXRleHR1cmUyZDogSW52YWxpZCBhcmd1bWVudHMgZm9yIHRleHR1cmUyZCBjb25zdHJ1Y3RvcicpXG59XG5cbn0se1wibmRhcnJheVwiOjQ1MCxcIm5kYXJyYXktb3BzXCI6NDQ0LFwidHlwZWRhcnJheS1wb29sXCI6NTQ1fV0sMzIzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbihmdW5jdGlvbiAoZ2xvYmFsKXtcbi8qKiBAbW9kdWxlICBnbC11dGlsL2NvbnRleHQgKi9cclxuJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgcGljayA9IF9kZXJlcV8oJ3BpY2stYnktYWxpYXMnKVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzZXRDb250ZXh0IChvKSB7XHJcblx0aWYgKCFvKSBvID0ge31cclxuXHRlbHNlIGlmICh0eXBlb2YgbyA9PT0gJ3N0cmluZycpIG8gPSB7Y29udGFpbmVyOiBvfVxyXG5cclxuXHQvLyBIVE1MQ2FudmFzRWxlbWVudFxyXG5cdGlmIChpc0NhbnZhcyhvKSkge1xyXG5cdFx0byA9IHtjb250YWluZXI6IG99XHJcblx0fVxyXG5cdC8vIEhUTUxFbGVtZW50XHJcblx0ZWxzZSBpZiAoaXNFbGVtZW50KG8pKSB7XHJcblx0XHRvID0ge2NvbnRhaW5lcjogb31cclxuXHR9XHJcblx0Ly8gV2ViR0xDb250ZXh0XHJcblx0ZWxzZSBpZiAoaXNDb250ZXh0KG8pKSB7XHJcblx0XHRvID0ge2dsOiBvfVxyXG5cdH1cclxuXHQvLyBvcHRpb25zIG9iamVjdFxyXG5cdGVsc2Uge1xyXG5cdFx0byA9IHBpY2sobywge1xyXG5cdFx0XHRjb250YWluZXI6ICdjb250YWluZXIgdGFyZ2V0IGVsZW1lbnQgZWwgY2FudmFzIGhvbGRlciBwYXJlbnQgcGFyZW50Tm9kZSB3cmFwcGVyIHVzZSByZWYgcm9vdCBub2RlJyxcclxuXHRcdFx0Z2w6ICdnbCBjb250ZXh0IHdlYmdsIGdsQ29udGV4dCcsXHJcblx0XHRcdGF0dHJzOiAnYXR0cmlidXRlcyBhdHRycyBjb250ZXh0QXR0cmlidXRlcycsXHJcblx0XHRcdHBpeGVsUmF0aW86ICdwaXhlbFJhdGlvIHB4UmF0aW8gcHggcmF0aW8gcHhyYXRpbyBwaXhlbHJhdGlvJyxcclxuXHRcdFx0d2lkdGg6ICd3IHdpZHRoJyxcclxuXHRcdFx0aGVpZ2h0OiAnaCBoZWlnaHQnXHJcblx0XHR9LCB0cnVlKVxyXG5cdH1cclxuXHJcblx0aWYgKCFvLnBpeGVsUmF0aW8pIG8ucGl4ZWxSYXRpbyA9IGdsb2JhbC5waXhlbFJhdGlvIHx8IDFcclxuXHJcblx0Ly8gbWFrZSBzdXJlIHRoZXJlIGlzIGNvbnRhaW5lciBhbmQgY2FudmFzXHJcblx0aWYgKG8uZ2wpIHtcclxuXHRcdHJldHVybiBvLmdsXHJcblx0fVxyXG5cdGlmIChvLmNhbnZhcykge1xyXG5cdFx0by5jb250YWluZXIgPSBvLmNhbnZhcy5wYXJlbnROb2RlXHJcblx0fVxyXG5cdGlmIChvLmNvbnRhaW5lcikge1xyXG5cdFx0aWYgKHR5cGVvZiBvLmNvbnRhaW5lciA9PT0gJ3N0cmluZycpIHtcclxuXHRcdFx0dmFyIGMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKG8uY29udGFpbmVyKVxyXG5cdFx0XHRpZiAoIWMpIHRocm93IEVycm9yKCdFbGVtZW50ICcgKyBvLmNvbnRhaW5lciArICcgaXMgbm90IGZvdW5kJylcclxuXHRcdFx0by5jb250YWluZXIgPSBjXHJcblx0XHR9XHJcblx0XHRpZiAoaXNDYW52YXMoby5jb250YWluZXIpKSB7XHJcblx0XHRcdG8uY2FudmFzID0gby5jb250YWluZXJcclxuXHRcdFx0by5jb250YWluZXIgPSBvLmNhbnZhcy5wYXJlbnROb2RlXHJcblx0XHR9XHJcblx0XHRlbHNlIGlmICghby5jYW52YXMpIHtcclxuXHRcdFx0by5jYW52YXMgPSBjcmVhdGVDYW52YXMoKVxyXG5cdFx0XHRvLmNvbnRhaW5lci5hcHBlbmRDaGlsZChvLmNhbnZhcylcclxuXHRcdFx0cmVzaXplKG8pXHJcblx0XHR9XHJcblx0fVxyXG5cdC8vIGJsYW5rIG5ldyBjYW52YXNcclxuXHRlbHNlIGlmICghby5jYW52YXMpIHtcclxuXHRcdGlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XHJcblx0XHRcdG8uY29udGFpbmVyID0gZG9jdW1lbnQuYm9keSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnRcclxuXHRcdFx0by5jYW52YXMgPSBjcmVhdGVDYW52YXMoKVxyXG5cdFx0XHRvLmNvbnRhaW5lci5hcHBlbmRDaGlsZChvLmNhbnZhcylcclxuXHRcdFx0cmVzaXplKG8pXHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0dGhyb3cgRXJyb3IoJ05vdCBET00gZW52aXJvbm1lbnQuIFVzZSBoZWFkbGVzcy1nbC4nKVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0Ly8gbWFrZSBzdXJlIHRoZXJlIGlzIGNvbnRleHRcclxuXHRpZiAoIW8uZ2wpIHtcclxuXHRcdHRyeSB7XHJcblx0XHRcdG8uZ2wgPSBvLmNhbnZhcy5nZXRDb250ZXh0KCd3ZWJnbCcsIG8uYXR0cnMpXHJcblx0XHR9IGNhdGNoIChlKSB7XHJcblx0XHRcdHRyeSB7XHJcblx0XHRcdFx0by5nbCA9IG8uY2FudmFzLmdldENvbnRleHQoJ2V4cGVyaW1lbnRhbC13ZWJnbCcsIG8uYXR0cnMpXHJcblx0XHRcdH1cclxuXHRcdFx0Y2F0Y2ggKGUpIHtcclxuXHRcdFx0XHRvLmdsID0gby5jYW52YXMuZ2V0Q29udGV4dCgnd2ViZ2wtZXhwZXJpbWVudGFsJywgby5hdHRycylcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIG8uZ2xcclxufVxyXG5cclxuXHJcbmZ1bmN0aW9uIHJlc2l6ZSAobykge1xyXG5cdGlmIChvLmNvbnRhaW5lcikge1xyXG5cdFx0aWYgKG8uY29udGFpbmVyID09IGRvY3VtZW50LmJvZHkpIHtcclxuXHRcdFx0aWYgKCFkb2N1bWVudC5ib2R5LnN0eWxlLndpZHRoKSBvLmNhbnZhcy53aWR0aCA9IG8ud2lkdGggfHwgKG8ucGl4ZWxSYXRpbyAqIGdsb2JhbC5pbm5lcldpZHRoKVxyXG5cdFx0XHRpZiAoIWRvY3VtZW50LmJvZHkuc3R5bGUuaGVpZ2h0KSBvLmNhbnZhcy5oZWlnaHQgPSBvLmhlaWdodCB8fCAoby5waXhlbFJhdGlvICogZ2xvYmFsLmlubmVySGVpZ2h0KVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSB7XHJcblx0XHRcdHZhciBib3VuZHMgPSBvLmNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxyXG5cdFx0XHRvLmNhbnZhcy53aWR0aCA9IG8ud2lkdGggfHwgKGJvdW5kcy5yaWdodCAtIGJvdW5kcy5sZWZ0KVxyXG5cdFx0XHRvLmNhbnZhcy5oZWlnaHQgPSBvLmhlaWdodCB8fCAoYm91bmRzLmJvdHRvbSAtIGJvdW5kcy50b3ApXHJcblx0XHR9XHJcblx0fVxyXG59XHJcblxyXG5mdW5jdGlvbiBpc0NhbnZhcyAoZSkge1xyXG5cdHJldHVybiB0eXBlb2YgZS5nZXRDb250ZXh0ID09PSAnZnVuY3Rpb24nXHJcblx0XHQmJiAnd2lkdGgnIGluIGVcclxuXHRcdCYmICdoZWlnaHQnIGluIGVcclxufVxyXG5cclxuZnVuY3Rpb24gaXNFbGVtZW50IChlKSB7XHJcblx0cmV0dXJuIHR5cGVvZiBlLm5vZGVOYW1lID09PSAnc3RyaW5nJyAmJlxyXG5cdFx0dHlwZW9mIGUuYXBwZW5kQ2hpbGQgPT09ICdmdW5jdGlvbicgJiZcclxuXHRcdHR5cGVvZiBlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCA9PT0gJ2Z1bmN0aW9uJ1xyXG59XHJcblxyXG5mdW5jdGlvbiBpc0NvbnRleHQgKGUpIHtcclxuXHRyZXR1cm4gdHlwZW9mIGUuZHJhd0FycmF5cyA9PT0gJ2Z1bmN0aW9uJyB8fFxyXG5cdFx0dHlwZW9mIGUuZHJhd0VsZW1lbnRzID09PSAnZnVuY3Rpb24nXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZUNhbnZhcyAoKSB7XHJcblx0dmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXHJcblx0Y2FudmFzLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJ1xyXG5cdGNhbnZhcy5zdHlsZS50b3AgPSAwXHJcblx0Y2FudmFzLnN0eWxlLmxlZnQgPSAwXHJcblxyXG5cdHJldHVybiBjYW52YXNcclxufVxyXG5cbn0pLmNhbGwodGhpcyx0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KVxufSx7XCJwaWNrLWJ5LWFsaWFzXCI6NDY1fV0sMzI0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbmZ1bmN0aW9uIGRvQmluZChnbCwgZWxlbWVudHMsIGF0dHJpYnV0ZXMpIHtcbiAgaWYoZWxlbWVudHMpIHtcbiAgICBlbGVtZW50cy5iaW5kKClcbiAgfSBlbHNlIHtcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkVMRU1FTlRfQVJSQVlfQlVGRkVSLCBudWxsKVxuICB9XG4gIHZhciBuYXR0cmlicyA9IGdsLmdldFBhcmFtZXRlcihnbC5NQVhfVkVSVEVYX0FUVFJJQlMpfDBcbiAgaWYoYXR0cmlidXRlcykge1xuICAgIGlmKGF0dHJpYnV0ZXMubGVuZ3RoID4gbmF0dHJpYnMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImdsLXZhbzogVG9vIG1hbnkgdmVydGV4IGF0dHJpYnV0ZXNcIilcbiAgICB9XG4gICAgZm9yKHZhciBpPTA7IGk8YXR0cmlidXRlcy5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGF0dHJpYiA9IGF0dHJpYnV0ZXNbaV1cbiAgICAgIGlmKGF0dHJpYi5idWZmZXIpIHtcbiAgICAgICAgdmFyIGJ1ZmZlciA9IGF0dHJpYi5idWZmZXJcbiAgICAgICAgdmFyIHNpemUgPSBhdHRyaWIuc2l6ZSB8fCA0XG4gICAgICAgIHZhciB0eXBlID0gYXR0cmliLnR5cGUgfHwgZ2wuRkxPQVRcbiAgICAgICAgdmFyIG5vcm1hbGl6ZWQgPSAhIWF0dHJpYi5ub3JtYWxpemVkXG4gICAgICAgIHZhciBzdHJpZGUgPSBhdHRyaWIuc3RyaWRlIHx8IDBcbiAgICAgICAgdmFyIG9mZnNldCA9IGF0dHJpYi5vZmZzZXQgfHwgMFxuICAgICAgICBidWZmZXIuYmluZCgpXG4gICAgICAgIGdsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGkpXG4gICAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIoaSwgc2l6ZSwgdHlwZSwgbm9ybWFsaXplZCwgc3RyaWRlLCBvZmZzZXQpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZih0eXBlb2YgYXR0cmliID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgZ2wudmVydGV4QXR0cmliMWYoaSwgYXR0cmliKVxuICAgICAgICB9IGVsc2UgaWYoYXR0cmliLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIGdsLnZlcnRleEF0dHJpYjFmKGksIGF0dHJpYlswXSlcbiAgICAgICAgfSBlbHNlIGlmKGF0dHJpYi5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICBnbC52ZXJ0ZXhBdHRyaWIyZihpLCBhdHRyaWJbMF0sIGF0dHJpYlsxXSlcbiAgICAgICAgfSBlbHNlIGlmKGF0dHJpYi5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICBnbC52ZXJ0ZXhBdHRyaWIzZihpLCBhdHRyaWJbMF0sIGF0dHJpYlsxXSwgYXR0cmliWzJdKVxuICAgICAgICB9IGVsc2UgaWYoYXR0cmliLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgIGdsLnZlcnRleEF0dHJpYjRmKGksIGF0dHJpYlswXSwgYXR0cmliWzFdLCBhdHRyaWJbMl0sIGF0dHJpYlszXSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJnbC12YW86IEludmFsaWQgdmVydGV4IGF0dHJpYnV0ZVwiKVxuICAgICAgICB9XG4gICAgICAgIGdsLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShpKVxuICAgICAgfVxuICAgIH1cbiAgICBmb3IoOyBpPG5hdHRyaWJzOyArK2kpIHtcbiAgICAgIGdsLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShpKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBnbC5iaW5kQnVmZmVyKGdsLkFSUkFZX0JVRkZFUiwgbnVsbClcbiAgICBmb3IodmFyIGk9MDsgaTxuYXR0cmliczsgKytpKSB7XG4gICAgICBnbC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoaSlcbiAgICB9XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBkb0JpbmRcbn0se31dLDMyNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG52YXIgYmluZEF0dHJpYnMgPSBfZGVyZXFfKFwiLi9kby1iaW5kLmpzXCIpXG5cbmZ1bmN0aW9uIFZBT0VtdWxhdGVkKGdsKSB7XG4gIHRoaXMuZ2wgPSBnbFxuICB0aGlzLl9lbGVtZW50cyA9IG51bGxcbiAgdGhpcy5fYXR0cmlidXRlcyA9IG51bGxcbiAgdGhpcy5fZWxlbWVudHNUeXBlID0gZ2wuVU5TSUdORURfU0hPUlRcbn1cblxuVkFPRW11bGF0ZWQucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgYmluZEF0dHJpYnModGhpcy5nbCwgdGhpcy5fZWxlbWVudHMsIHRoaXMuX2F0dHJpYnV0ZXMpXG59XG5cblZBT0VtdWxhdGVkLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbihhdHRyaWJ1dGVzLCBlbGVtZW50cywgZWxlbWVudHNUeXBlKSB7XG4gIHRoaXMuX2VsZW1lbnRzID0gZWxlbWVudHNcbiAgdGhpcy5fYXR0cmlidXRlcyA9IGF0dHJpYnV0ZXNcbiAgdGhpcy5fZWxlbWVudHNUeXBlID0gZWxlbWVudHNUeXBlIHx8IHRoaXMuZ2wuVU5TSUdORURfU0hPUlRcbn1cblxuVkFPRW11bGF0ZWQucHJvdG90eXBlLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHsgfVxuVkFPRW11bGF0ZWQucHJvdG90eXBlLnVuYmluZCA9IGZ1bmN0aW9uKCkgeyB9XG5cblZBT0VtdWxhdGVkLnByb3RvdHlwZS5kcmF3ID0gZnVuY3Rpb24obW9kZSwgY291bnQsIG9mZnNldCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfHwgMFxuICB2YXIgZ2wgPSB0aGlzLmdsXG4gIGlmKHRoaXMuX2VsZW1lbnRzKSB7XG4gICAgZ2wuZHJhd0VsZW1lbnRzKG1vZGUsIGNvdW50LCB0aGlzLl9lbGVtZW50c1R5cGUsIG9mZnNldClcbiAgfSBlbHNlIHtcbiAgICBnbC5kcmF3QXJyYXlzKG1vZGUsIG9mZnNldCwgY291bnQpXG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlVkFPRW11bGF0ZWQoZ2wpIHtcbiAgcmV0dXJuIG5ldyBWQU9FbXVsYXRlZChnbClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVWQU9FbXVsYXRlZFxufSx7XCIuL2RvLWJpbmQuanNcIjozMjR9XSwzMjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxudmFyIGJpbmRBdHRyaWJzID0gX2RlcmVxXyhcIi4vZG8tYmluZC5qc1wiKVxuXG5mdW5jdGlvbiBWZXJ0ZXhBdHRyaWJ1dGUobG9jYXRpb24sIGRpbWVuc2lvbiwgYSwgYiwgYywgZCkge1xuICB0aGlzLmxvY2F0aW9uID0gbG9jYXRpb25cbiAgdGhpcy5kaW1lbnNpb24gPSBkaW1lbnNpb25cbiAgdGhpcy5hID0gYVxuICB0aGlzLmIgPSBiXG4gIHRoaXMuYyA9IGNcbiAgdGhpcy5kID0gZFxufVxuXG5WZXJ0ZXhBdHRyaWJ1dGUucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbihnbCkge1xuICBzd2l0Y2godGhpcy5kaW1lbnNpb24pIHtcbiAgICBjYXNlIDE6XG4gICAgICBnbC52ZXJ0ZXhBdHRyaWIxZih0aGlzLmxvY2F0aW9uLCB0aGlzLmEpXG4gICAgYnJlYWtcbiAgICBjYXNlIDI6XG4gICAgICBnbC52ZXJ0ZXhBdHRyaWIyZih0aGlzLmxvY2F0aW9uLCB0aGlzLmEsIHRoaXMuYilcbiAgICBicmVha1xuICAgIGNhc2UgMzpcbiAgICAgIGdsLnZlcnRleEF0dHJpYjNmKHRoaXMubG9jYXRpb24sIHRoaXMuYSwgdGhpcy5iLCB0aGlzLmMpXG4gICAgYnJlYWtcbiAgICBjYXNlIDQ6XG4gICAgICBnbC52ZXJ0ZXhBdHRyaWI0Zih0aGlzLmxvY2F0aW9uLCB0aGlzLmEsIHRoaXMuYiwgdGhpcy5jLCB0aGlzLmQpXG4gICAgYnJlYWtcbiAgfVxufVxuXG5mdW5jdGlvbiBWQU9OYXRpdmUoZ2wsIGV4dCwgaGFuZGxlKSB7XG4gIHRoaXMuZ2wgPSBnbFxuICB0aGlzLl9leHQgPSBleHRcbiAgdGhpcy5oYW5kbGUgPSBoYW5kbGVcbiAgdGhpcy5fYXR0cmlicyA9IFtdXG4gIHRoaXMuX3VzZUVsZW1lbnRzID0gZmFsc2VcbiAgdGhpcy5fZWxlbWVudHNUeXBlID0gZ2wuVU5TSUdORURfU0hPUlRcbn1cblxuVkFPTmF0aXZlLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuX2V4dC5iaW5kVmVydGV4QXJyYXlPRVModGhpcy5oYW5kbGUpXG4gIGZvcih2YXIgaT0wOyBpPHRoaXMuX2F0dHJpYnMubGVuZ3RoOyArK2kpIHtcbiAgICB0aGlzLl9hdHRyaWJzW2ldLmJpbmQodGhpcy5nbClcbiAgfVxufVxuXG5WQU9OYXRpdmUucHJvdG90eXBlLnVuYmluZCA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLl9leHQuYmluZFZlcnRleEFycmF5T0VTKG51bGwpXG59XG5cblZBT05hdGl2ZS5wcm90b3R5cGUuZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLl9leHQuZGVsZXRlVmVydGV4QXJyYXlPRVModGhpcy5oYW5kbGUpXG59XG5cblZBT05hdGl2ZS5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24oYXR0cmlidXRlcywgZWxlbWVudHMsIGVsZW1lbnRzVHlwZSkge1xuICB0aGlzLmJpbmQoKVxuICBiaW5kQXR0cmlicyh0aGlzLmdsLCBlbGVtZW50cywgYXR0cmlidXRlcylcbiAgdGhpcy51bmJpbmQoKVxuICB0aGlzLl9hdHRyaWJzLmxlbmd0aCA9IDBcbiAgaWYoYXR0cmlidXRlcylcbiAgZm9yKHZhciBpPTA7IGk8YXR0cmlidXRlcy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBhID0gYXR0cmlidXRlc1tpXVxuICAgIGlmKHR5cGVvZiBhID09PSBcIm51bWJlclwiKSB7XG4gICAgICB0aGlzLl9hdHRyaWJzLnB1c2gobmV3IFZlcnRleEF0dHJpYnV0ZShpLCAxLCBhKSlcbiAgICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheShhKSkge1xuICAgICAgdGhpcy5fYXR0cmlicy5wdXNoKG5ldyBWZXJ0ZXhBdHRyaWJ1dGUoaSwgYS5sZW5ndGgsIGFbMF0sIGFbMV0sIGFbMl0sIGFbM10pKVxuICAgIH1cbiAgfVxuICB0aGlzLl91c2VFbGVtZW50cyA9ICEhZWxlbWVudHNcbiAgdGhpcy5fZWxlbWVudHNUeXBlID0gZWxlbWVudHNUeXBlIHx8IHRoaXMuZ2wuVU5TSUdORURfU0hPUlRcbn1cblxuVkFPTmF0aXZlLnByb3RvdHlwZS5kcmF3ID0gZnVuY3Rpb24obW9kZSwgY291bnQsIG9mZnNldCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfHwgMFxuICB2YXIgZ2wgPSB0aGlzLmdsXG4gIGlmKHRoaXMuX3VzZUVsZW1lbnRzKSB7XG4gICAgZ2wuZHJhd0VsZW1lbnRzKG1vZGUsIGNvdW50LCB0aGlzLl9lbGVtZW50c1R5cGUsIG9mZnNldClcbiAgfSBlbHNlIHtcbiAgICBnbC5kcmF3QXJyYXlzKG1vZGUsIG9mZnNldCwgY291bnQpXG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlVkFPTmF0aXZlKGdsLCBleHQpIHtcbiAgcmV0dXJuIG5ldyBWQU9OYXRpdmUoZ2wsIGV4dCwgZXh0LmNyZWF0ZVZlcnRleEFycmF5T0VTKCkpXG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVkFPTmF0aXZlXG59LHtcIi4vZG8tYmluZC5qc1wiOjMyNH1dLDMyNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG52YXIgY3JlYXRlVkFPTmF0aXZlID0gX2RlcmVxXyhcIi4vbGliL3Zhby1uYXRpdmUuanNcIilcbnZhciBjcmVhdGVWQU9FbXVsYXRlZCA9IF9kZXJlcV8oXCIuL2xpYi92YW8tZW11bGF0ZWQuanNcIilcblxuZnVuY3Rpb24gRXh0ZW5zaW9uU2hpbSAoZ2wpIHtcbiAgdGhpcy5iaW5kVmVydGV4QXJyYXlPRVMgPSBnbC5iaW5kVmVydGV4QXJyYXkuYmluZChnbClcbiAgdGhpcy5jcmVhdGVWZXJ0ZXhBcnJheU9FUyA9IGdsLmNyZWF0ZVZlcnRleEFycmF5LmJpbmQoZ2wpXG4gIHRoaXMuZGVsZXRlVmVydGV4QXJyYXlPRVMgPSBnbC5kZWxldGVWZXJ0ZXhBcnJheS5iaW5kKGdsKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVWQU8oZ2wsIGF0dHJpYnV0ZXMsIGVsZW1lbnRzLCBlbGVtZW50c1R5cGUpIHtcbiAgdmFyIGV4dCA9IGdsLmNyZWF0ZVZlcnRleEFycmF5XG4gICAgPyBuZXcgRXh0ZW5zaW9uU2hpbShnbClcbiAgICA6IGdsLmdldEV4dGVuc2lvbignT0VTX3ZlcnRleF9hcnJheV9vYmplY3QnKVxuICB2YXIgdmFvXG5cbiAgaWYoZXh0KSB7XG4gICAgdmFvID0gY3JlYXRlVkFPTmF0aXZlKGdsLCBleHQpXG4gIH0gZWxzZSB7XG4gICAgdmFvID0gY3JlYXRlVkFPRW11bGF0ZWQoZ2wpXG4gIH1cbiAgdmFvLnVwZGF0ZShhdHRyaWJ1dGVzLCBlbGVtZW50cywgZWxlbWVudHNUeXBlKVxuICByZXR1cm4gdmFvXG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVkFPXG5cbn0se1wiLi9saWIvdmFvLWVtdWxhdGVkLmpzXCI6MzI1LFwiLi9saWIvdmFvLW5hdGl2ZS5qc1wiOjMyNn1dLDMyODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGFkZDtcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGFkZChvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdICsgYlswXVxuICAgIG91dFsxXSA9IGFbMV0gKyBiWzFdXG4gICAgb3V0WzJdID0gYVsyXSArIGJbMl1cbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzMjk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBhbmdsZVxuXG52YXIgZnJvbVZhbHVlcyA9IF9kZXJlcV8oJy4vZnJvbVZhbHVlcycpXG52YXIgbm9ybWFsaXplID0gX2RlcmVxXygnLi9ub3JtYWxpemUnKVxudmFyIGRvdCA9IF9kZXJlcV8oJy4vZG90JylcblxuLyoqXG4gKiBHZXQgdGhlIGFuZ2xlIGJldHdlZW4gdHdvIDNEIHZlY3RvcnNcbiAqIEBwYXJhbSB7dmVjM30gYSBUaGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIFRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gVGhlIGFuZ2xlIGluIHJhZGlhbnNcbiAqL1xuZnVuY3Rpb24gYW5nbGUoYSwgYikge1xuICAgIHZhciB0ZW1wQSA9IGZyb21WYWx1ZXMoYVswXSwgYVsxXSwgYVsyXSlcbiAgICB2YXIgdGVtcEIgPSBmcm9tVmFsdWVzKGJbMF0sIGJbMV0sIGJbMl0pXG4gXG4gICAgbm9ybWFsaXplKHRlbXBBLCB0ZW1wQSlcbiAgICBub3JtYWxpemUodGVtcEIsIHRlbXBCKVxuIFxuICAgIHZhciBjb3NpbmUgPSBkb3QodGVtcEEsIHRlbXBCKVxuXG4gICAgaWYoY29zaW5lID4gMS4wKXtcbiAgICAgICAgcmV0dXJuIDBcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gTWF0aC5hY29zKGNvc2luZSlcbiAgICB9ICAgICBcbn1cblxufSx7XCIuL2RvdFwiOjMzOSxcIi4vZnJvbVZhbHVlc1wiOjM0NSxcIi4vbm9ybWFsaXplXCI6MzU2fV0sMzMwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gY2VpbFxuXG4vKipcbiAqIE1hdGguY2VpbCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjZWlsXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGNlaWwob3V0LCBhKSB7XG4gIG91dFswXSA9IE1hdGguY2VpbChhWzBdKVxuICBvdXRbMV0gPSBNYXRoLmNlaWwoYVsxXSlcbiAgb3V0WzJdID0gTWF0aC5jZWlsKGFbMl0pXG4gIHJldHVybiBvdXRcbn1cblxufSx7fV0sMzMxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gY2xvbmU7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWMzIGluaXRpYWxpemVkIHdpdGggdmFsdWVzIGZyb20gYW4gZXhpc3RpbmcgdmVjdG9yXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBjbG9uZVxuICogQHJldHVybnMge3ZlYzN9IGEgbmV3IDNEIHZlY3RvclxuICovXG5mdW5jdGlvbiBjbG9uZShhKSB7XG4gICAgdmFyIG91dCA9IG5ldyBGbG9hdDMyQXJyYXkoMylcbiAgICBvdXRbMF0gPSBhWzBdXG4gICAgb3V0WzFdID0gYVsxXVxuICAgIG91dFsyXSA9IGFbMl1cbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzMzI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBjb3B5O1xuXG4vKipcbiAqIENvcHkgdGhlIHZhbHVlcyBmcm9tIG9uZSB2ZWMzIHRvIGFub3RoZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBzb3VyY2UgdmVjdG9yXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGNvcHkob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gYVswXVxuICAgIG91dFsxXSA9IGFbMV1cbiAgICBvdXRbMl0gPSBhWzJdXG4gICAgcmV0dXJuIG91dFxufVxufSx7fV0sMzMzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzNcbiAqXG4gKiBAcmV0dXJucyB7dmVjM30gYSBuZXcgM0QgdmVjdG9yXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEZsb2F0MzJBcnJheSgzKVxuICAgIG91dFswXSA9IDBcbiAgICBvdXRbMV0gPSAwXG4gICAgb3V0WzJdID0gMFxuICAgIHJldHVybiBvdXRcbn1cbn0se31dLDMzNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGNyb3NzO1xuXG4vKipcbiAqIENvbXB1dGVzIHRoZSBjcm9zcyBwcm9kdWN0IG9mIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGNyb3NzKG91dCwgYSwgYikge1xuICAgIHZhciBheCA9IGFbMF0sIGF5ID0gYVsxXSwgYXogPSBhWzJdLFxuICAgICAgICBieCA9IGJbMF0sIGJ5ID0gYlsxXSwgYnogPSBiWzJdXG5cbiAgICBvdXRbMF0gPSBheSAqIGJ6IC0gYXogKiBieVxuICAgIG91dFsxXSA9IGF6ICogYnggLSBheCAqIGJ6XG4gICAgb3V0WzJdID0gYXggKiBieSAtIGF5ICogYnhcbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzMzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuL2Rpc3RhbmNlJylcblxufSx7XCIuL2Rpc3RhbmNlXCI6MzM2fV0sMzM2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gZGlzdGFuY2U7XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgZXVjbGlkaWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge051bWJlcn0gZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbmZ1bmN0aW9uIGRpc3RhbmNlKGEsIGIpIHtcbiAgICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgICAgICB5ID0gYlsxXSAtIGFbMV0sXG4gICAgICAgIHogPSBiWzJdIC0gYVsyXVxuICAgIHJldHVybiBNYXRoLnNxcnQoeCp4ICsgeSp5ICsgeip6KVxufVxufSx7fV0sMzM3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi9kaXZpZGUnKVxuXG59LHtcIi4vZGl2aWRlXCI6MzM4fV0sMzM4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gZGl2aWRlO1xuXG4vKipcbiAqIERpdmlkZXMgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gZGl2aWRlKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gLyBiWzBdXG4gICAgb3V0WzFdID0gYVsxXSAvIGJbMV1cbiAgICBvdXRbMl0gPSBhWzJdIC8gYlsyXVxuICAgIHJldHVybiBvdXRcbn1cbn0se31dLDMzOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGRvdDtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkb3QgcHJvZHVjdCBvZiB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkb3QgcHJvZHVjdCBvZiBhIGFuZCBiXG4gKi9cbmZ1bmN0aW9uIGRvdChhLCBiKSB7XG4gICAgcmV0dXJuIGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV0gKyBhWzJdICogYlsyXVxufVxufSx7fV0sMzQwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gMC4wMDAwMDFcblxufSx7fV0sMzQxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gZXF1YWxzXG5cbnZhciBFUFNJTE9OID0gX2RlcmVxXygnLi9lcHNpbG9uJylcblxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSB2ZWN0b3JzIGhhdmUgYXBwcm94aW1hdGVseSB0aGUgc2FtZSBlbGVtZW50cyBpbiB0aGUgc2FtZSBwb3NpdGlvbi5cbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IGEgVGhlIGZpcnN0IHZlY3Rvci5cbiAqIEBwYXJhbSB7dmVjM30gYiBUaGUgc2Vjb25kIHZlY3Rvci5cbiAqIEByZXR1cm5zIHtCb29sZWFufSBUcnVlIGlmIHRoZSB2ZWN0b3JzIGFyZSBlcXVhbCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICovXG5mdW5jdGlvbiBlcXVhbHMoYSwgYikge1xuICB2YXIgYTAgPSBhWzBdXG4gIHZhciBhMSA9IGFbMV1cbiAgdmFyIGEyID0gYVsyXVxuICB2YXIgYjAgPSBiWzBdXG4gIHZhciBiMSA9IGJbMV1cbiAgdmFyIGIyID0gYlsyXVxuICByZXR1cm4gKE1hdGguYWJzKGEwIC0gYjApIDw9IEVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGEwKSwgTWF0aC5hYnMoYjApKSAmJlxuICAgICAgICAgIE1hdGguYWJzKGExIC0gYjEpIDw9IEVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGExKSwgTWF0aC5hYnMoYjEpKSAmJlxuICAgICAgICAgIE1hdGguYWJzKGEyIC0gYjIpIDw9IEVQU0lMT04gKiBNYXRoLm1heCgxLjAsIE1hdGguYWJzKGEyKSwgTWF0aC5hYnMoYjIpKSlcbn1cblxufSx7XCIuL2Vwc2lsb25cIjozNDB9XSwzNDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBleGFjdEVxdWFsc1xuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHZlY3RvcnMgZXhhY3RseSBoYXZlIHRoZSBzYW1lIGVsZW1lbnRzIGluIHRoZSBzYW1lIHBvc2l0aW9uICh3aGVuIGNvbXBhcmVkIHdpdGggPT09KVxuICpcbiAqIEBwYXJhbSB7dmVjM30gYSBUaGUgZmlyc3QgdmVjdG9yLlxuICogQHBhcmFtIHt2ZWMzfSBiIFRoZSBzZWNvbmQgdmVjdG9yLlxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWYgdGhlIHZlY3RvcnMgYXJlIGVxdWFsLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmZ1bmN0aW9uIGV4YWN0RXF1YWxzKGEsIGIpIHtcbiAgcmV0dXJuIGFbMF0gPT09IGJbMF0gJiYgYVsxXSA9PT0gYlsxXSAmJiBhWzJdID09PSBiWzJdXG59XG5cbn0se31dLDM0MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGZsb29yXG5cbi8qKlxuICogTWF0aC5mbG9vciB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBmbG9vclxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBmbG9vcihvdXQsIGEpIHtcbiAgb3V0WzBdID0gTWF0aC5mbG9vcihhWzBdKVxuICBvdXRbMV0gPSBNYXRoLmZsb29yKGFbMV0pXG4gIG91dFsyXSA9IE1hdGguZmxvb3IoYVsyXSlcbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzNDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBmb3JFYWNoO1xuXG52YXIgdmVjID0gX2RlcmVxXygnLi9jcmVhdGUnKSgpXG5cbi8qKlxuICogUGVyZm9ybSBzb21lIG9wZXJhdGlvbiBvdmVyIGFuIGFycmF5IG9mIHZlYzNzLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IGEgdGhlIGFycmF5IG9mIHZlY3RvcnMgdG8gaXRlcmF0ZSBvdmVyXG4gKiBAcGFyYW0ge051bWJlcn0gc3RyaWRlIE51bWJlciBvZiBlbGVtZW50cyBiZXR3ZWVuIHRoZSBzdGFydCBvZiBlYWNoIHZlYzMuIElmIDAgYXNzdW1lcyB0aWdodGx5IHBhY2tlZFxuICogQHBhcmFtIHtOdW1iZXJ9IG9mZnNldCBOdW1iZXIgb2YgZWxlbWVudHMgdG8gc2tpcCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhcnJheVxuICogQHBhcmFtIHtOdW1iZXJ9IGNvdW50IE51bWJlciBvZiB2ZWMzcyB0byBpdGVyYXRlIG92ZXIuIElmIDAgaXRlcmF0ZXMgb3ZlciBlbnRpcmUgYXJyYXlcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRvIGNhbGwgZm9yIGVhY2ggdmVjdG9yIGluIHRoZSBhcnJheVxuICogQHBhcmFtIHtPYmplY3R9IFthcmddIGFkZGl0aW9uYWwgYXJndW1lbnQgdG8gcGFzcyB0byBmblxuICogQHJldHVybnMge0FycmF5fSBhXG4gKiBAZnVuY3Rpb25cbiAqL1xuZnVuY3Rpb24gZm9yRWFjaChhLCBzdHJpZGUsIG9mZnNldCwgY291bnQsIGZuLCBhcmcpIHtcbiAgICAgICAgdmFyIGksIGxcbiAgICAgICAgaWYoIXN0cmlkZSkge1xuICAgICAgICAgICAgc3RyaWRlID0gM1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMFxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZihjb3VudCkge1xuICAgICAgICAgICAgbCA9IE1hdGgubWluKChjb3VudCAqIHN0cmlkZSkgKyBvZmZzZXQsIGEubGVuZ3RoKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbCA9IGEubGVuZ3RoXG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IG9mZnNldDsgaSA8IGw7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgICB2ZWNbMF0gPSBhW2ldIFxuICAgICAgICAgICAgdmVjWzFdID0gYVtpKzFdIFxuICAgICAgICAgICAgdmVjWzJdID0gYVtpKzJdXG4gICAgICAgICAgICBmbih2ZWMsIHZlYywgYXJnKVxuICAgICAgICAgICAgYVtpXSA9IHZlY1swXSBcbiAgICAgICAgICAgIGFbaSsxXSA9IHZlY1sxXSBcbiAgICAgICAgICAgIGFbaSsyXSA9IHZlY1syXVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gYVxufVxufSx7XCIuL2NyZWF0ZVwiOjMzM31dLDM0NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGZyb21WYWx1ZXM7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB2ZWMzIGluaXRpYWxpemVkIHdpdGggdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEByZXR1cm5zIHt2ZWMzfSBhIG5ldyAzRCB2ZWN0b3JcbiAqL1xuZnVuY3Rpb24gZnJvbVZhbHVlcyh4LCB5LCB6KSB7XG4gICAgdmFyIG91dCA9IG5ldyBGbG9hdDMyQXJyYXkoMylcbiAgICBvdXRbMF0gPSB4XG4gICAgb3V0WzFdID0geVxuICAgIG91dFsyXSA9IHpcbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzNDY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSB7XG4gIEVQU0lMT046IF9kZXJlcV8oJy4vZXBzaWxvbicpXG4gICwgY3JlYXRlOiBfZGVyZXFfKCcuL2NyZWF0ZScpXG4gICwgY2xvbmU6IF9kZXJlcV8oJy4vY2xvbmUnKVxuICAsIGFuZ2xlOiBfZGVyZXFfKCcuL2FuZ2xlJylcbiAgLCBmcm9tVmFsdWVzOiBfZGVyZXFfKCcuL2Zyb21WYWx1ZXMnKVxuICAsIGNvcHk6IF9kZXJlcV8oJy4vY29weScpXG4gICwgc2V0OiBfZGVyZXFfKCcuL3NldCcpXG4gICwgZXF1YWxzOiBfZGVyZXFfKCcuL2VxdWFscycpXG4gICwgZXhhY3RFcXVhbHM6IF9kZXJlcV8oJy4vZXhhY3RFcXVhbHMnKVxuICAsIGFkZDogX2RlcmVxXygnLi9hZGQnKVxuICAsIHN1YnRyYWN0OiBfZGVyZXFfKCcuL3N1YnRyYWN0JylcbiAgLCBzdWI6IF9kZXJlcV8oJy4vc3ViJylcbiAgLCBtdWx0aXBseTogX2RlcmVxXygnLi9tdWx0aXBseScpXG4gICwgbXVsOiBfZGVyZXFfKCcuL211bCcpXG4gICwgZGl2aWRlOiBfZGVyZXFfKCcuL2RpdmlkZScpXG4gICwgZGl2OiBfZGVyZXFfKCcuL2RpdicpXG4gICwgbWluOiBfZGVyZXFfKCcuL21pbicpXG4gICwgbWF4OiBfZGVyZXFfKCcuL21heCcpXG4gICwgZmxvb3I6IF9kZXJlcV8oJy4vZmxvb3InKVxuICAsIGNlaWw6IF9kZXJlcV8oJy4vY2VpbCcpXG4gICwgcm91bmQ6IF9kZXJlcV8oJy4vcm91bmQnKVxuICAsIHNjYWxlOiBfZGVyZXFfKCcuL3NjYWxlJylcbiAgLCBzY2FsZUFuZEFkZDogX2RlcmVxXygnLi9zY2FsZUFuZEFkZCcpXG4gICwgZGlzdGFuY2U6IF9kZXJlcV8oJy4vZGlzdGFuY2UnKVxuICAsIGRpc3Q6IF9kZXJlcV8oJy4vZGlzdCcpXG4gICwgc3F1YXJlZERpc3RhbmNlOiBfZGVyZXFfKCcuL3NxdWFyZWREaXN0YW5jZScpXG4gICwgc3FyRGlzdDogX2RlcmVxXygnLi9zcXJEaXN0JylcbiAgLCBsZW5ndGg6IF9kZXJlcV8oJy4vbGVuZ3RoJylcbiAgLCBsZW46IF9kZXJlcV8oJy4vbGVuJylcbiAgLCBzcXVhcmVkTGVuZ3RoOiBfZGVyZXFfKCcuL3NxdWFyZWRMZW5ndGgnKVxuICAsIHNxckxlbjogX2RlcmVxXygnLi9zcXJMZW4nKVxuICAsIG5lZ2F0ZTogX2RlcmVxXygnLi9uZWdhdGUnKVxuICAsIGludmVyc2U6IF9kZXJlcV8oJy4vaW52ZXJzZScpXG4gICwgbm9ybWFsaXplOiBfZGVyZXFfKCcuL25vcm1hbGl6ZScpXG4gICwgZG90OiBfZGVyZXFfKCcuL2RvdCcpXG4gICwgY3Jvc3M6IF9kZXJlcV8oJy4vY3Jvc3MnKVxuICAsIGxlcnA6IF9kZXJlcV8oJy4vbGVycCcpXG4gICwgcmFuZG9tOiBfZGVyZXFfKCcuL3JhbmRvbScpXG4gICwgdHJhbnNmb3JtTWF0NDogX2RlcmVxXygnLi90cmFuc2Zvcm1NYXQ0JylcbiAgLCB0cmFuc2Zvcm1NYXQzOiBfZGVyZXFfKCcuL3RyYW5zZm9ybU1hdDMnKVxuICAsIHRyYW5zZm9ybVF1YXQ6IF9kZXJlcV8oJy4vdHJhbnNmb3JtUXVhdCcpXG4gICwgcm90YXRlWDogX2RlcmVxXygnLi9yb3RhdGVYJylcbiAgLCByb3RhdGVZOiBfZGVyZXFfKCcuL3JvdGF0ZVknKVxuICAsIHJvdGF0ZVo6IF9kZXJlcV8oJy4vcm90YXRlWicpXG4gICwgZm9yRWFjaDogX2RlcmVxXygnLi9mb3JFYWNoJylcbn1cblxufSx7XCIuL2FkZFwiOjMyOCxcIi4vYW5nbGVcIjozMjksXCIuL2NlaWxcIjozMzAsXCIuL2Nsb25lXCI6MzMxLFwiLi9jb3B5XCI6MzMyLFwiLi9jcmVhdGVcIjozMzMsXCIuL2Nyb3NzXCI6MzM0LFwiLi9kaXN0XCI6MzM1LFwiLi9kaXN0YW5jZVwiOjMzNixcIi4vZGl2XCI6MzM3LFwiLi9kaXZpZGVcIjozMzgsXCIuL2RvdFwiOjMzOSxcIi4vZXBzaWxvblwiOjM0MCxcIi4vZXF1YWxzXCI6MzQxLFwiLi9leGFjdEVxdWFsc1wiOjM0MixcIi4vZmxvb3JcIjozNDMsXCIuL2ZvckVhY2hcIjozNDQsXCIuL2Zyb21WYWx1ZXNcIjozNDUsXCIuL2ludmVyc2VcIjozNDcsXCIuL2xlblwiOjM0OCxcIi4vbGVuZ3RoXCI6MzQ5LFwiLi9sZXJwXCI6MzUwLFwiLi9tYXhcIjozNTEsXCIuL21pblwiOjM1MixcIi4vbXVsXCI6MzUzLFwiLi9tdWx0aXBseVwiOjM1NCxcIi4vbmVnYXRlXCI6MzU1LFwiLi9ub3JtYWxpemVcIjozNTYsXCIuL3JhbmRvbVwiOjM1NyxcIi4vcm90YXRlWFwiOjM1OCxcIi4vcm90YXRlWVwiOjM1OSxcIi4vcm90YXRlWlwiOjM2MCxcIi4vcm91bmRcIjozNjEsXCIuL3NjYWxlXCI6MzYyLFwiLi9zY2FsZUFuZEFkZFwiOjM2MyxcIi4vc2V0XCI6MzY0LFwiLi9zcXJEaXN0XCI6MzY1LFwiLi9zcXJMZW5cIjozNjYsXCIuL3NxdWFyZWREaXN0YW5jZVwiOjM2NyxcIi4vc3F1YXJlZExlbmd0aFwiOjM2OCxcIi4vc3ViXCI6MzY5LFwiLi9zdWJ0cmFjdFwiOjM3MCxcIi4vdHJhbnNmb3JtTWF0M1wiOjM3MSxcIi4vdHJhbnNmb3JtTWF0NFwiOjM3MixcIi4vdHJhbnNmb3JtUXVhdFwiOjM3M31dLDM0NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGludmVyc2U7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgaW52ZXJzZSBvZiB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBpbnZlcnRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gaW52ZXJzZShvdXQsIGEpIHtcbiAgb3V0WzBdID0gMS4wIC8gYVswXVxuICBvdXRbMV0gPSAxLjAgLyBhWzFdXG4gIG91dFsyXSA9IDEuMCAvIGFbMl1cbiAgcmV0dXJuIG91dFxufVxufSx7fV0sMzQ4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi9sZW5ndGgnKVxuXG59LHtcIi4vbGVuZ3RoXCI6MzQ5fV0sMzQ5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gbGVuZ3RoO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdmVjdG9yIHRvIGNhbGN1bGF0ZSBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGxlbmd0aCBvZiBhXG4gKi9cbmZ1bmN0aW9uIGxlbmd0aChhKSB7XG4gICAgdmFyIHggPSBhWzBdLFxuICAgICAgICB5ID0gYVsxXSxcbiAgICAgICAgeiA9IGFbMl1cbiAgICByZXR1cm4gTWF0aC5zcXJ0KHgqeCArIHkqeSArIHoqeilcbn1cbn0se31dLDM1MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGxlcnA7XG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIGxlcnAob3V0LCBhLCBiLCB0KSB7XG4gICAgdmFyIGF4ID0gYVswXSxcbiAgICAgICAgYXkgPSBhWzFdLFxuICAgICAgICBheiA9IGFbMl1cbiAgICBvdXRbMF0gPSBheCArIHQgKiAoYlswXSAtIGF4KVxuICAgIG91dFsxXSA9IGF5ICsgdCAqIChiWzFdIC0gYXkpXG4gICAgb3V0WzJdID0gYXogKyB0ICogKGJbMl0gLSBheilcbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzNTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBtYXg7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbWF4aW11bSBvZiB0d28gdmVjMydzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBtYXgob3V0LCBhLCBiKSB7XG4gICAgb3V0WzBdID0gTWF0aC5tYXgoYVswXSwgYlswXSlcbiAgICBvdXRbMV0gPSBNYXRoLm1heChhWzFdLCBiWzFdKVxuICAgIG91dFsyXSA9IE1hdGgubWF4KGFbMl0sIGJbMl0pXG4gICAgcmV0dXJuIG91dFxufVxufSx7fV0sMzUyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gbWluO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzMnc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gbWluKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IE1hdGgubWluKGFbMF0sIGJbMF0pXG4gICAgb3V0WzFdID0gTWF0aC5taW4oYVsxXSwgYlsxXSlcbiAgICBvdXRbMl0gPSBNYXRoLm1pbihhWzJdLCBiWzJdKVxuICAgIHJldHVybiBvdXRcbn1cbn0se31dLDM1MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4vbXVsdGlwbHknKVxuXG59LHtcIi4vbXVsdGlwbHlcIjozNTR9XSwzNTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBtdWx0aXBseTtcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzN9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIG11bHRpcGx5KG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKiBiWzBdXG4gICAgb3V0WzFdID0gYVsxXSAqIGJbMV1cbiAgICBvdXRbMl0gPSBhWzJdICogYlsyXVxuICAgIHJldHVybiBvdXRcbn1cbn0se31dLDM1NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IG5lZ2F0ZTtcblxuLyoqXG4gKiBOZWdhdGVzIHRoZSBjb21wb25lbnRzIG9mIGEgdmVjM1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdmVjdG9yIHRvIG5lZ2F0ZVxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBuZWdhdGUob3V0LCBhKSB7XG4gICAgb3V0WzBdID0gLWFbMF1cbiAgICBvdXRbMV0gPSAtYVsxXVxuICAgIG91dFsyXSA9IC1hWzJdXG4gICAgcmV0dXJuIG91dFxufVxufSx7fV0sMzU2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gbm9ybWFsaXplO1xuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHZlYzNcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHZlY3RvciB0byBub3JtYWxpemVcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplKG91dCwgYSkge1xuICAgIHZhciB4ID0gYVswXSxcbiAgICAgICAgeSA9IGFbMV0sXG4gICAgICAgIHogPSBhWzJdXG4gICAgdmFyIGxlbiA9IHgqeCArIHkqeSArIHoqelxuICAgIGlmIChsZW4gPiAwKSB7XG4gICAgICAgIC8vVE9ETzogZXZhbHVhdGUgdXNlIG9mIGdsbV9pbnZzcXJ0IGhlcmU/XG4gICAgICAgIGxlbiA9IDEgLyBNYXRoLnNxcnQobGVuKVxuICAgICAgICBvdXRbMF0gPSBhWzBdICogbGVuXG4gICAgICAgIG91dFsxXSA9IGFbMV0gKiBsZW5cbiAgICAgICAgb3V0WzJdID0gYVsyXSAqIGxlblxuICAgIH1cbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzNTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSByYW5kb207XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcmFuZG9tIHZlY3RvciB3aXRoIHRoZSBnaXZlbiBzY2FsZVxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0gW3NjYWxlXSBMZW5ndGggb2YgdGhlIHJlc3VsdGluZyB2ZWN0b3IuIElmIG9tbWl0dGVkLCBhIHVuaXQgdmVjdG9yIHdpbGwgYmUgcmV0dXJuZWRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gcmFuZG9tKG91dCwgc2NhbGUpIHtcbiAgICBzY2FsZSA9IHNjYWxlIHx8IDEuMFxuXG4gICAgdmFyIHIgPSBNYXRoLnJhbmRvbSgpICogMi4wICogTWF0aC5QSVxuICAgIHZhciB6ID0gKE1hdGgucmFuZG9tKCkgKiAyLjApIC0gMS4wXG4gICAgdmFyIHpTY2FsZSA9IE1hdGguc3FydCgxLjAteip6KSAqIHNjYWxlXG5cbiAgICBvdXRbMF0gPSBNYXRoLmNvcyhyKSAqIHpTY2FsZVxuICAgIG91dFsxXSA9IE1hdGguc2luKHIpICogelNjYWxlXG4gICAgb3V0WzJdID0geiAqIHNjYWxlXG4gICAgcmV0dXJuIG91dFxufVxufSx7fV0sMzU4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gcm90YXRlWDtcblxuLyoqXG4gKiBSb3RhdGUgYSAzRCB2ZWN0b3IgYXJvdW5kIHRoZSB4LWF4aXNcbiAqIEBwYXJhbSB7dmVjM30gb3V0IFRoZSByZWNlaXZpbmcgdmVjM1xuICogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuICogQHBhcmFtIHt2ZWMzfSBiIFRoZSBvcmlnaW4gb2YgdGhlIHJvdGF0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYyBUaGUgYW5nbGUgb2Ygcm90YXRpb25cbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gcm90YXRlWChvdXQsIGEsIGIsIGMpe1xuICAgIHZhciBieSA9IGJbMV1cbiAgICB2YXIgYnogPSBiWzJdXG5cbiAgICAvLyBUcmFuc2xhdGUgcG9pbnQgdG8gdGhlIG9yaWdpblxuICAgIHZhciBweSA9IGFbMV0gLSBieVxuICAgIHZhciBweiA9IGFbMl0gLSBielxuXG4gICAgdmFyIHNjID0gTWF0aC5zaW4oYylcbiAgICB2YXIgY2MgPSBNYXRoLmNvcyhjKVxuXG4gICAgLy8gcGVyZm9ybSByb3RhdGlvbiBhbmQgdHJhbnNsYXRlIHRvIGNvcnJlY3QgcG9zaXRpb25cbiAgICBvdXRbMF0gPSBhWzBdXG4gICAgb3V0WzFdID0gYnkgKyBweSAqIGNjIC0gcHogKiBzY1xuICAgIG91dFsyXSA9IGJ6ICsgcHkgKiBzYyArIHB6ICogY2NcblxuICAgIHJldHVybiBvdXRcbn1cblxufSx7fV0sMzU5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gcm90YXRlWTtcblxuLyoqXG4gKiBSb3RhdGUgYSAzRCB2ZWN0b3IgYXJvdW5kIHRoZSB5LWF4aXNcbiAqIEBwYXJhbSB7dmVjM30gb3V0IFRoZSByZWNlaXZpbmcgdmVjM1xuICogQHBhcmFtIHt2ZWMzfSBhIFRoZSB2ZWMzIHBvaW50IHRvIHJvdGF0ZVxuICogQHBhcmFtIHt2ZWMzfSBiIFRoZSBvcmlnaW4gb2YgdGhlIHJvdGF0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYyBUaGUgYW5nbGUgb2Ygcm90YXRpb25cbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gcm90YXRlWShvdXQsIGEsIGIsIGMpe1xuICAgIHZhciBieCA9IGJbMF1cbiAgICB2YXIgYnogPSBiWzJdXG5cbiAgICAvLyB0cmFuc2xhdGUgcG9pbnQgdG8gdGhlIG9yaWdpblxuICAgIHZhciBweCA9IGFbMF0gLSBieFxuICAgIHZhciBweiA9IGFbMl0gLSBielxuICAgIFxuICAgIHZhciBzYyA9IE1hdGguc2luKGMpXG4gICAgdmFyIGNjID0gTWF0aC5jb3MoYylcbiAgXG4gICAgLy8gcGVyZm9ybSByb3RhdGlvbiBhbmQgdHJhbnNsYXRlIHRvIGNvcnJlY3QgcG9zaXRpb25cbiAgICBvdXRbMF0gPSBieCArIHB6ICogc2MgKyBweCAqIGNjXG4gICAgb3V0WzFdID0gYVsxXVxuICAgIG91dFsyXSA9IGJ6ICsgcHogKiBjYyAtIHB4ICogc2NcbiAgXG4gICAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzNjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSByb3RhdGVaO1xuXG4vKipcbiAqIFJvdGF0ZSBhIDNEIHZlY3RvciBhcm91bmQgdGhlIHotYXhpc1xuICogQHBhcmFtIHt2ZWMzfSBvdXQgVGhlIHJlY2VpdmluZyB2ZWMzXG4gKiBAcGFyYW0ge3ZlYzN9IGEgVGhlIHZlYzMgcG9pbnQgdG8gcm90YXRlXG4gKiBAcGFyYW0ge3ZlYzN9IGIgVGhlIG9yaWdpbiBvZiB0aGUgcm90YXRpb25cbiAqIEBwYXJhbSB7TnVtYmVyfSBjIFRoZSBhbmdsZSBvZiByb3RhdGlvblxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiByb3RhdGVaKG91dCwgYSwgYiwgYyl7XG4gICAgdmFyIGJ4ID0gYlswXVxuICAgIHZhciBieSA9IGJbMV1cblxuICAgIC8vVHJhbnNsYXRlIHBvaW50IHRvIHRoZSBvcmlnaW5cbiAgICB2YXIgcHggPSBhWzBdIC0gYnhcbiAgICB2YXIgcHkgPSBhWzFdIC0gYnlcbiAgXG4gICAgdmFyIHNjID0gTWF0aC5zaW4oYylcbiAgICB2YXIgY2MgPSBNYXRoLmNvcyhjKVxuXG4gICAgLy8gcGVyZm9ybSByb3RhdGlvbiBhbmQgdHJhbnNsYXRlIHRvIGNvcnJlY3QgcG9zaXRpb25cbiAgICBvdXRbMF0gPSBieCArIHB4ICogY2MgLSBweSAqIHNjXG4gICAgb3V0WzFdID0gYnkgKyBweCAqIHNjICsgcHkgKiBjY1xuICAgIG91dFsyXSA9IGFbMl1cbiAgXG4gICAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzNjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSByb3VuZFxuXG4vKipcbiAqIE1hdGgucm91bmQgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWMzXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB2ZWN0b3IgdG8gcm91bmRcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gcm91bmQob3V0LCBhKSB7XG4gIG91dFswXSA9IE1hdGgucm91bmQoYVswXSlcbiAgb3V0WzFdID0gTWF0aC5yb3VuZChhWzFdKVxuICBvdXRbMl0gPSBNYXRoLnJvdW5kKGFbMl0pXG4gIHJldHVybiBvdXRcbn1cblxufSx7fV0sMzYyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gc2NhbGU7XG5cbi8qKlxuICogU2NhbGVzIGEgdmVjMyBieSBhIHNjYWxhciBudW1iZXJcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gc2NhbGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBiIGFtb3VudCB0byBzY2FsZSB0aGUgdmVjdG9yIGJ5XG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIHNjYWxlKG91dCwgYSwgYikge1xuICAgIG91dFswXSA9IGFbMF0gKiBiXG4gICAgb3V0WzFdID0gYVsxXSAqIGJcbiAgICBvdXRbMl0gPSBhWzJdICogYlxuICAgIHJldHVybiBvdXRcbn1cbn0se31dLDM2MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHNjYWxlQW5kQWRkO1xuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzMncyBhZnRlciBzY2FsaW5nIHRoZSBzZWNvbmQgb3BlcmFuZCBieSBhIHNjYWxhciB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBzY2FsZSB0aGUgYW1vdW50IHRvIHNjYWxlIGIgYnkgYmVmb3JlIGFkZGluZ1xuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBzY2FsZUFuZEFkZChvdXQsIGEsIGIsIHNjYWxlKSB7XG4gICAgb3V0WzBdID0gYVswXSArIChiWzBdICogc2NhbGUpXG4gICAgb3V0WzFdID0gYVsxXSArIChiWzFdICogc2NhbGUpXG4gICAgb3V0WzJdID0gYVsyXSArIChiWzJdICogc2NhbGUpXG4gICAgcmV0dXJuIG91dFxufVxufSx7fV0sMzY0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gc2V0O1xuXG4vKipcbiAqIFNldCB0aGUgY29tcG9uZW50cyBvZiBhIHZlYzMgdG8gdGhlIGdpdmVuIHZhbHVlc1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIHNldChvdXQsIHgsIHksIHopIHtcbiAgICBvdXRbMF0gPSB4XG4gICAgb3V0WzFdID0geVxuICAgIG91dFsyXSA9IHpcbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzNjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuL3NxdWFyZWREaXN0YW5jZScpXG5cbn0se1wiLi9zcXVhcmVkRGlzdGFuY2VcIjozNjd9XSwzNjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCcuL3NxdWFyZWRMZW5ndGgnKVxuXG59LHtcIi4vc3F1YXJlZExlbmd0aFwiOjM2OH1dLDM2NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHNxdWFyZWREaXN0YW5jZTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGV1Y2xpZGlhbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byB2ZWMzJ3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjM30gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbmZ1bmN0aW9uIHNxdWFyZWREaXN0YW5jZShhLCBiKSB7XG4gICAgdmFyIHggPSBiWzBdIC0gYVswXSxcbiAgICAgICAgeSA9IGJbMV0gLSBhWzFdLFxuICAgICAgICB6ID0gYlsyXSAtIGFbMl1cbiAgICByZXR1cm4geCp4ICsgeSp5ICsgeip6XG59XG59LHt9XSwzNjg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBzcXVhcmVkTGVuZ3RoO1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHNxdWFyZWQgbGVuZ3RoIG9mIGEgdmVjM1xuICpcbiAqIEBwYXJhbSB7dmVjM30gYSB2ZWN0b3IgdG8gY2FsY3VsYXRlIHNxdWFyZWQgbGVuZ3RoIG9mXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBzcXVhcmVkIGxlbmd0aCBvZiBhXG4gKi9cbmZ1bmN0aW9uIHNxdWFyZWRMZW5ndGgoYSkge1xuICAgIHZhciB4ID0gYVswXSxcbiAgICAgICAgeSA9IGFbMV0sXG4gICAgICAgIHogPSBhWzJdXG4gICAgcmV0dXJuIHgqeCArIHkqeSArIHoqelxufVxufSx7fV0sMzY5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi9zdWJ0cmFjdCcpXG5cbn0se1wiLi9zdWJ0cmFjdFwiOjM3MH1dLDM3MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHN1YnRyYWN0O1xuXG4vKipcbiAqIFN1YnRyYWN0cyB2ZWN0b3IgYiBmcm9tIHZlY3RvciBhXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWMzfSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiBzdWJ0cmFjdChvdXQsIGEsIGIpIHtcbiAgICBvdXRbMF0gPSBhWzBdIC0gYlswXVxuICAgIG91dFsxXSA9IGFbMV0gLSBiWzFdXG4gICAgb3V0WzJdID0gYVsyXSAtIGJbMl1cbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzNzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSB0cmFuc2Zvcm1NYXQzO1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDMuXG4gKlxuICogQHBhcmFtIHt2ZWMzfSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjM30gYSB0aGUgdmVjdG9yIHRvIHRyYW5zZm9ybVxuICogQHBhcmFtIHttYXQ0fSBtIHRoZSAzeDMgbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjM30gb3V0XG4gKi9cbmZ1bmN0aW9uIHRyYW5zZm9ybU1hdDMob3V0LCBhLCBtKSB7XG4gICAgdmFyIHggPSBhWzBdLCB5ID0gYVsxXSwgeiA9IGFbMl1cbiAgICBvdXRbMF0gPSB4ICogbVswXSArIHkgKiBtWzNdICsgeiAqIG1bNl1cbiAgICBvdXRbMV0gPSB4ICogbVsxXSArIHkgKiBtWzRdICsgeiAqIG1bN11cbiAgICBvdXRbMl0gPSB4ICogbVsyXSArIHkgKiBtWzVdICsgeiAqIG1bOF1cbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzNzI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSB0cmFuc2Zvcm1NYXQ0O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIG1hdDQuXG4gKiA0dGggdmVjdG9yIGNvbXBvbmVudCBpcyBpbXBsaWNpdGx5ICcxJ1xuICpcbiAqIEBwYXJhbSB7dmVjM30gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzN9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7bWF0NH0gbSBtYXRyaXggdG8gdHJhbnNmb3JtIHdpdGhcbiAqIEByZXR1cm5zIHt2ZWMzfSBvdXRcbiAqL1xuZnVuY3Rpb24gdHJhbnNmb3JtTWF0NChvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSxcbiAgICAgICAgdyA9IG1bM10gKiB4ICsgbVs3XSAqIHkgKyBtWzExXSAqIHogKyBtWzE1XVxuICAgIHcgPSB3IHx8IDEuMFxuICAgIG91dFswXSA9IChtWzBdICogeCArIG1bNF0gKiB5ICsgbVs4XSAqIHogKyBtWzEyXSkgLyB3XG4gICAgb3V0WzFdID0gKG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzldICogeiArIG1bMTNdKSAvIHdcbiAgICBvdXRbMl0gPSAobVsyXSAqIHggKyBtWzZdICogeSArIG1bMTBdICogeiArIG1bMTRdKSAvIHdcbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSwzNzM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSB0cmFuc2Zvcm1RdWF0O1xuXG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIHZlYzMgd2l0aCBhIHF1YXRcbiAqXG4gKiBAcGFyYW0ge3ZlYzN9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWMzfSBhIHRoZSB2ZWN0b3IgdG8gdHJhbnNmb3JtXG4gKiBAcGFyYW0ge3F1YXR9IHEgcXVhdGVybmlvbiB0byB0cmFuc2Zvcm0gd2l0aFxuICogQHJldHVybnMge3ZlYzN9IG91dFxuICovXG5mdW5jdGlvbiB0cmFuc2Zvcm1RdWF0KG91dCwgYSwgcSkge1xuICAgIC8vIGJlbmNobWFya3M6IGh0dHA6Ly9qc3BlcmYuY29tL3F1YXRlcm5pb24tdHJhbnNmb3JtLXZlYzMtaW1wbGVtZW50YXRpb25zXG5cbiAgICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSxcbiAgICAgICAgcXggPSBxWzBdLCBxeSA9IHFbMV0sIHF6ID0gcVsyXSwgcXcgPSBxWzNdLFxuXG4gICAgICAgIC8vIGNhbGN1bGF0ZSBxdWF0ICogdmVjXG4gICAgICAgIGl4ID0gcXcgKiB4ICsgcXkgKiB6IC0gcXogKiB5LFxuICAgICAgICBpeSA9IHF3ICogeSArIHF6ICogeCAtIHF4ICogeixcbiAgICAgICAgaXogPSBxdyAqIHogKyBxeCAqIHkgLSBxeSAqIHgsXG4gICAgICAgIGl3ID0gLXF4ICogeCAtIHF5ICogeSAtIHF6ICogelxuXG4gICAgLy8gY2FsY3VsYXRlIHJlc3VsdCAqIGludmVyc2UgcXVhdFxuICAgIG91dFswXSA9IGl4ICogcXcgKyBpdyAqIC1xeCArIGl5ICogLXF6IC0gaXogKiAtcXlcbiAgICBvdXRbMV0gPSBpeSAqIHF3ICsgaXcgKiAtcXkgKyBpeiAqIC1xeCAtIGl4ICogLXF6XG4gICAgb3V0WzJdID0gaXogKiBxdyArIGl3ICogLXF6ICsgaXggKiAtcXkgLSBpeSAqIC1xeFxuICAgIHJldHVybiBvdXRcbn1cbn0se31dLDM3NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGFkZFxuXG4vKipcbiAqIEFkZHMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gYWRkIChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSArIGJbMF1cbiAgb3V0WzFdID0gYVsxXSArIGJbMV1cbiAgb3V0WzJdID0gYVsyXSArIGJbMl1cbiAgb3V0WzNdID0gYVszXSArIGJbM11cbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzNzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBjbG9uZVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjNCBpbml0aWFsaXplZCB3aXRoIHZhbHVlcyBmcm9tIGFuIGV4aXN0aW5nIHZlY3RvclxuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB2ZWN0b3IgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHt2ZWM0fSBhIG5ldyA0RCB2ZWN0b3JcbiAqL1xuZnVuY3Rpb24gY2xvbmUgKGEpIHtcbiAgdmFyIG91dCA9IG5ldyBGbG9hdDMyQXJyYXkoNClcbiAgb3V0WzBdID0gYVswXVxuICBvdXRbMV0gPSBhWzFdXG4gIG91dFsyXSA9IGFbMl1cbiAgb3V0WzNdID0gYVszXVxuICByZXR1cm4gb3V0XG59XG5cbn0se31dLDM3NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGNvcHlcblxuLyoqXG4gKiBDb3B5IHRoZSB2YWx1ZXMgZnJvbSBvbmUgdmVjNCB0byBhbm90aGVyXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgc291cmNlIHZlY3RvclxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiBjb3B5IChvdXQsIGEpIHtcbiAgb3V0WzBdID0gYVswXVxuICBvdXRbMV0gPSBhWzFdXG4gIG91dFsyXSA9IGFbMl1cbiAgb3V0WzNdID0gYVszXVxuICByZXR1cm4gb3V0XG59XG5cbn0se31dLDM3NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcsIGVtcHR5IHZlYzRcbiAqXG4gKiBAcmV0dXJucyB7dmVjNH0gYSBuZXcgNEQgdmVjdG9yXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZSAoKSB7XG4gIHZhciBvdXQgPSBuZXcgRmxvYXQzMkFycmF5KDQpXG4gIG91dFswXSA9IDBcbiAgb3V0WzFdID0gMFxuICBvdXRbMl0gPSAwXG4gIG91dFszXSA9IDBcbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzNzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBkaXN0YW5jZVxuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGV1Y2xpZGlhbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IGRpc3RhbmNlIGJldHdlZW4gYSBhbmQgYlxuICovXG5mdW5jdGlvbiBkaXN0YW5jZSAoYSwgYikge1xuICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgIHkgPSBiWzFdIC0gYVsxXSxcbiAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgdyA9IGJbM10gLSBhWzNdXG4gIHJldHVybiBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSArIHogKiB6ICsgdyAqIHcpXG59XG5cbn0se31dLDM3OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGRpdmlkZVxuXG4vKipcbiAqIERpdmlkZXMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gZGl2aWRlIChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSAvIGJbMF1cbiAgb3V0WzFdID0gYVsxXSAvIGJbMV1cbiAgb3V0WzJdID0gYVsyXSAvIGJbMl1cbiAgb3V0WzNdID0gYVszXSAvIGJbM11cbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzODA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBkb3RcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBkb3QgcHJvZHVjdCBvZiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBkb3QgcHJvZHVjdCBvZiBhIGFuZCBiXG4gKi9cbmZ1bmN0aW9uIGRvdCAoYSwgYikge1xuICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdICsgYVszXSAqIGJbM11cbn1cblxufSx7fV0sMzgxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gZnJvbVZhbHVlc1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgdmVjNCBpbml0aWFsaXplZCB3aXRoIHRoZSBnaXZlbiB2YWx1ZXNcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0geCBYIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHkgWSBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB6IFogY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0gdyBXIGNvbXBvbmVudFxuICogQHJldHVybnMge3ZlYzR9IGEgbmV3IDREIHZlY3RvclxuICovXG5mdW5jdGlvbiBmcm9tVmFsdWVzICh4LCB5LCB6LCB3KSB7XG4gIHZhciBvdXQgPSBuZXcgRmxvYXQzMkFycmF5KDQpXG4gIG91dFswXSA9IHhcbiAgb3V0WzFdID0geVxuICBvdXRbMl0gPSB6XG4gIG91dFszXSA9IHdcbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzODI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGNyZWF0ZTogX2RlcmVxXygnLi9jcmVhdGUnKSxcbiAgY2xvbmU6IF9kZXJlcV8oJy4vY2xvbmUnKSxcbiAgZnJvbVZhbHVlczogX2RlcmVxXygnLi9mcm9tVmFsdWVzJyksXG4gIGNvcHk6IF9kZXJlcV8oJy4vY29weScpLFxuICBzZXQ6IF9kZXJlcV8oJy4vc2V0JyksXG4gIGFkZDogX2RlcmVxXygnLi9hZGQnKSxcbiAgc3VidHJhY3Q6IF9kZXJlcV8oJy4vc3VidHJhY3QnKSxcbiAgbXVsdGlwbHk6IF9kZXJlcV8oJy4vbXVsdGlwbHknKSxcbiAgZGl2aWRlOiBfZGVyZXFfKCcuL2RpdmlkZScpLFxuICBtaW46IF9kZXJlcV8oJy4vbWluJyksXG4gIG1heDogX2RlcmVxXygnLi9tYXgnKSxcbiAgc2NhbGU6IF9kZXJlcV8oJy4vc2NhbGUnKSxcbiAgc2NhbGVBbmRBZGQ6IF9kZXJlcV8oJy4vc2NhbGVBbmRBZGQnKSxcbiAgZGlzdGFuY2U6IF9kZXJlcV8oJy4vZGlzdGFuY2UnKSxcbiAgc3F1YXJlZERpc3RhbmNlOiBfZGVyZXFfKCcuL3NxdWFyZWREaXN0YW5jZScpLFxuICBsZW5ndGg6IF9kZXJlcV8oJy4vbGVuZ3RoJyksXG4gIHNxdWFyZWRMZW5ndGg6IF9kZXJlcV8oJy4vc3F1YXJlZExlbmd0aCcpLFxuICBuZWdhdGU6IF9kZXJlcV8oJy4vbmVnYXRlJyksXG4gIGludmVyc2U6IF9kZXJlcV8oJy4vaW52ZXJzZScpLFxuICBub3JtYWxpemU6IF9kZXJlcV8oJy4vbm9ybWFsaXplJyksXG4gIGRvdDogX2RlcmVxXygnLi9kb3QnKSxcbiAgbGVycDogX2RlcmVxXygnLi9sZXJwJyksXG4gIHJhbmRvbTogX2RlcmVxXygnLi9yYW5kb20nKSxcbiAgdHJhbnNmb3JtTWF0NDogX2RlcmVxXygnLi90cmFuc2Zvcm1NYXQ0JyksXG4gIHRyYW5zZm9ybVF1YXQ6IF9kZXJlcV8oJy4vdHJhbnNmb3JtUXVhdCcpXG59XG5cbn0se1wiLi9hZGRcIjozNzQsXCIuL2Nsb25lXCI6Mzc1LFwiLi9jb3B5XCI6Mzc2LFwiLi9jcmVhdGVcIjozNzcsXCIuL2Rpc3RhbmNlXCI6Mzc4LFwiLi9kaXZpZGVcIjozNzksXCIuL2RvdFwiOjM4MCxcIi4vZnJvbVZhbHVlc1wiOjM4MSxcIi4vaW52ZXJzZVwiOjM4MyxcIi4vbGVuZ3RoXCI6Mzg0LFwiLi9sZXJwXCI6Mzg1LFwiLi9tYXhcIjozODYsXCIuL21pblwiOjM4NyxcIi4vbXVsdGlwbHlcIjozODgsXCIuL25lZ2F0ZVwiOjM4OSxcIi4vbm9ybWFsaXplXCI6MzkwLFwiLi9yYW5kb21cIjozOTEsXCIuL3NjYWxlXCI6MzkyLFwiLi9zY2FsZUFuZEFkZFwiOjM5MyxcIi4vc2V0XCI6Mzk0LFwiLi9zcXVhcmVkRGlzdGFuY2VcIjozOTUsXCIuL3NxdWFyZWRMZW5ndGhcIjozOTYsXCIuL3N1YnRyYWN0XCI6Mzk3LFwiLi90cmFuc2Zvcm1NYXQ0XCI6Mzk4LFwiLi90cmFuc2Zvcm1RdWF0XCI6Mzk5fV0sMzgzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gaW52ZXJzZVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGludmVyc2Ugb2YgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB2ZWN0b3IgdG8gaW52ZXJ0XG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIGludmVyc2UgKG91dCwgYSkge1xuICBvdXRbMF0gPSAxLjAgLyBhWzBdXG4gIG91dFsxXSA9IDEuMCAvIGFbMV1cbiAgb3V0WzJdID0gMS4wIC8gYVsyXVxuICBvdXRbM10gPSAxLjAgLyBhWzNdXG4gIHJldHVybiBvdXRcbn1cblxufSx7fV0sMzg0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gbGVuZ3RoXG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgbGVuZ3RoIG9mIGEgdmVjNFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gYSB2ZWN0b3IgdG8gY2FsY3VsYXRlIGxlbmd0aCBvZlxuICogQHJldHVybnMge051bWJlcn0gbGVuZ3RoIG9mIGFcbiAqL1xuZnVuY3Rpb24gbGVuZ3RoIChhKSB7XG4gIHZhciB4ID0gYVswXSxcbiAgICB5ID0gYVsxXSxcbiAgICB6ID0gYVsyXSxcbiAgICB3ID0gYVszXVxuICByZXR1cm4gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkgKyB6ICogeiArIHcgKiB3KVxufVxuXG59LHt9XSwzODU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBsZXJwXG5cbi8qKlxuICogUGVyZm9ybXMgYSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gdCBpbnRlcnBvbGF0aW9uIGFtb3VudCBiZXR3ZWVuIHRoZSB0d28gaW5wdXRzXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIGxlcnAgKG91dCwgYSwgYiwgdCkge1xuICB2YXIgYXggPSBhWzBdLFxuICAgIGF5ID0gYVsxXSxcbiAgICBheiA9IGFbMl0sXG4gICAgYXcgPSBhWzNdXG4gIG91dFswXSA9IGF4ICsgdCAqIChiWzBdIC0gYXgpXG4gIG91dFsxXSA9IGF5ICsgdCAqIChiWzFdIC0gYXkpXG4gIG91dFsyXSA9IGF6ICsgdCAqIChiWzJdIC0gYXopXG4gIG91dFszXSA9IGF3ICsgdCAqIChiWzNdIC0gYXcpXG4gIHJldHVybiBvdXRcbn1cblxufSx7fV0sMzg2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gbWF4XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbWF4aW11bSBvZiB0d28gdmVjNCdzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgZmlyc3Qgb3BlcmFuZFxuICogQHBhcmFtIHt2ZWM0fSBiIHRoZSBzZWNvbmQgb3BlcmFuZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiBtYXggKG91dCwgYSwgYikge1xuICBvdXRbMF0gPSBNYXRoLm1heChhWzBdLCBiWzBdKVxuICBvdXRbMV0gPSBNYXRoLm1heChhWzFdLCBiWzFdKVxuICBvdXRbMl0gPSBNYXRoLm1heChhWzJdLCBiWzJdKVxuICBvdXRbM10gPSBNYXRoLm1heChhWzNdLCBiWzNdKVxuICByZXR1cm4gb3V0XG59XG5cbn0se31dLDM4NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IG1pblxuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gb2YgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gbWluIChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gTWF0aC5taW4oYVswXSwgYlswXSlcbiAgb3V0WzFdID0gTWF0aC5taW4oYVsxXSwgYlsxXSlcbiAgb3V0WzJdID0gTWF0aC5taW4oYVsyXSwgYlsyXSlcbiAgb3V0WzNdID0gTWF0aC5taW4oYVszXSwgYlszXSlcbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzODg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBtdWx0aXBseVxuXG4vKipcbiAqIE11bHRpcGxpZXMgdHdvIHZlYzQnc1xuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gbXVsdGlwbHkgKG91dCwgYSwgYikge1xuICBvdXRbMF0gPSBhWzBdICogYlswXVxuICBvdXRbMV0gPSBhWzFdICogYlsxXVxuICBvdXRbMl0gPSBhWzJdICogYlsyXVxuICBvdXRbM10gPSBhWzNdICogYlszXVxuICByZXR1cm4gb3V0XG59XG5cbn0se31dLDM4OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IG5lZ2F0ZVxuXG4vKipcbiAqIE5lZ2F0ZXMgdGhlIGNvbXBvbmVudHMgb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB2ZWN0b3IgdG8gbmVnYXRlXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIG5lZ2F0ZSAob3V0LCBhKSB7XG4gIG91dFswXSA9IC1hWzBdXG4gIG91dFsxXSA9IC1hWzFdXG4gIG91dFsyXSA9IC1hWzJdXG4gIG91dFszXSA9IC1hWzNdXG4gIHJldHVybiBvdXRcbn1cblxufSx7fV0sMzkwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gbm9ybWFsaXplXG5cbi8qKlxuICogTm9ybWFsaXplIGEgdmVjNFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdmVjdG9yIHRvIG5vcm1hbGl6ZVxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiBub3JtYWxpemUgKG91dCwgYSkge1xuICB2YXIgeCA9IGFbMF0sXG4gICAgeSA9IGFbMV0sXG4gICAgeiA9IGFbMl0sXG4gICAgdyA9IGFbM11cbiAgdmFyIGxlbiA9IHggKiB4ICsgeSAqIHkgKyB6ICogeiArIHcgKiB3XG4gIGlmIChsZW4gPiAwKSB7XG4gICAgbGVuID0gMSAvIE1hdGguc3FydChsZW4pXG4gICAgb3V0WzBdID0geCAqIGxlblxuICAgIG91dFsxXSA9IHkgKiBsZW5cbiAgICBvdXRbMl0gPSB6ICogbGVuXG4gICAgb3V0WzNdID0gdyAqIGxlblxuICB9XG4gIHJldHVybiBvdXRcbn1cblxufSx7fV0sMzkxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciB2ZWNOb3JtYWxpemUgPSBfZGVyZXFfKCcuL25vcm1hbGl6ZScpXG52YXIgdmVjU2NhbGUgPSBfZGVyZXFfKCcuL3NjYWxlJylcblxubW9kdWxlLmV4cG9ydHMgPSByYW5kb21cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSByYW5kb20gdmVjdG9yIHdpdGggdGhlIGdpdmVuIHNjYWxlXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2NhbGVdIExlbmd0aCBvZiB0aGUgcmVzdWx0aW5nIHZlY3Rvci4gSWYgb21taXR0ZWQsIGEgdW5pdCB2ZWN0b3Igd2lsbCBiZSByZXR1cm5lZFxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiByYW5kb20gKG91dCwgc2NhbGUpIHtcbiAgc2NhbGUgPSBzY2FsZSB8fCAxLjBcblxuICAvLyBUT0RPOiBUaGlzIGlzIGEgcHJldHR5IGF3ZnVsIHdheSBvZiBkb2luZyB0aGlzLiBGaW5kIHNvbWV0aGluZyBiZXR0ZXIuXG4gIG91dFswXSA9IE1hdGgucmFuZG9tKClcbiAgb3V0WzFdID0gTWF0aC5yYW5kb20oKVxuICBvdXRbMl0gPSBNYXRoLnJhbmRvbSgpXG4gIG91dFszXSA9IE1hdGgucmFuZG9tKClcbiAgdmVjTm9ybWFsaXplKG91dCwgb3V0KVxuICB2ZWNTY2FsZShvdXQsIG91dCwgc2NhbGUpXG4gIHJldHVybiBvdXRcbn1cblxufSx7XCIuL25vcm1hbGl6ZVwiOjM5MCxcIi4vc2NhbGVcIjozOTJ9XSwzOTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBzY2FsZVxuXG4vKipcbiAqIFNjYWxlcyBhIHZlYzQgYnkgYSBzY2FsYXIgbnVtYmVyXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7dmVjNH0gYSB0aGUgdmVjdG9yIHRvIHNjYWxlXG4gKiBAcGFyYW0ge051bWJlcn0gYiBhbW91bnQgdG8gc2NhbGUgdGhlIHZlY3RvciBieVxuICogQHJldHVybnMge3ZlYzR9IG91dFxuICovXG5mdW5jdGlvbiBzY2FsZSAob3V0LCBhLCBiKSB7XG4gIG91dFswXSA9IGFbMF0gKiBiXG4gIG91dFsxXSA9IGFbMV0gKiBiXG4gIG91dFsyXSA9IGFbMl0gKiBiXG4gIG91dFszXSA9IGFbM10gKiBiXG4gIHJldHVybiBvdXRcbn1cblxufSx7fV0sMzkzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gc2NhbGVBbmRBZGRcblxuLyoqXG4gKiBBZGRzIHR3byB2ZWM0J3MgYWZ0ZXIgc2NhbGluZyB0aGUgc2Vjb25kIG9wZXJhbmQgYnkgYSBzY2FsYXIgdmFsdWVcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcGFyYW0ge051bWJlcn0gc2NhbGUgdGhlIGFtb3VudCB0byBzY2FsZSBiIGJ5IGJlZm9yZSBhZGRpbmdcbiAqIEByZXR1cm5zIHt2ZWM0fSBvdXRcbiAqL1xuZnVuY3Rpb24gc2NhbGVBbmRBZGQgKG91dCwgYSwgYiwgc2NhbGUpIHtcbiAgb3V0WzBdID0gYVswXSArIChiWzBdICogc2NhbGUpXG4gIG91dFsxXSA9IGFbMV0gKyAoYlsxXSAqIHNjYWxlKVxuICBvdXRbMl0gPSBhWzJdICsgKGJbMl0gKiBzY2FsZSlcbiAgb3V0WzNdID0gYVszXSArIChiWzNdICogc2NhbGUpXG4gIHJldHVybiBvdXRcbn1cblxufSx7fV0sMzk0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gc2V0XG5cbi8qKlxuICogU2V0IHRoZSBjb21wb25lbnRzIG9mIGEgdmVjNCB0byB0aGUgZ2l2ZW4gdmFsdWVzXG4gKlxuICogQHBhcmFtIHt2ZWM0fSBvdXQgdGhlIHJlY2VpdmluZyB2ZWN0b3JcbiAqIEBwYXJhbSB7TnVtYmVyfSB4IFggY29tcG9uZW50XG4gKiBAcGFyYW0ge051bWJlcn0geSBZIGNvbXBvbmVudFxuICogQHBhcmFtIHtOdW1iZXJ9IHogWiBjb21wb25lbnRcbiAqIEBwYXJhbSB7TnVtYmVyfSB3IFcgY29tcG9uZW50XG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHNldCAob3V0LCB4LCB5LCB6LCB3KSB7XG4gIG91dFswXSA9IHhcbiAgb3V0WzFdID0geVxuICBvdXRbMl0gPSB6XG4gIG91dFszXSA9IHdcbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzOTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBzcXVhcmVkRGlzdGFuY2VcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBzcXVhcmVkIGV1Y2xpZGlhbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byB2ZWM0J3NcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIGZpcnN0IG9wZXJhbmRcbiAqIEBwYXJhbSB7dmVjNH0gYiB0aGUgc2Vjb25kIG9wZXJhbmRcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgZGlzdGFuY2UgYmV0d2VlbiBhIGFuZCBiXG4gKi9cbmZ1bmN0aW9uIHNxdWFyZWREaXN0YW5jZSAoYSwgYikge1xuICB2YXIgeCA9IGJbMF0gLSBhWzBdLFxuICAgIHkgPSBiWzFdIC0gYVsxXSxcbiAgICB6ID0gYlsyXSAtIGFbMl0sXG4gICAgdyA9IGJbM10gLSBhWzNdXG4gIHJldHVybiB4ICogeCArIHkgKiB5ICsgeiAqIHogKyB3ICogd1xufVxuXG59LHt9XSwzOTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBzcXVhcmVkTGVuZ3RoXG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgc3F1YXJlZCBsZW5ndGggb2YgYSB2ZWM0XG4gKlxuICogQHBhcmFtIHt2ZWM0fSBhIHZlY3RvciB0byBjYWxjdWxhdGUgc3F1YXJlZCBsZW5ndGggb2ZcbiAqIEByZXR1cm5zIHtOdW1iZXJ9IHNxdWFyZWQgbGVuZ3RoIG9mIGFcbiAqL1xuZnVuY3Rpb24gc3F1YXJlZExlbmd0aCAoYSkge1xuICB2YXIgeCA9IGFbMF0sXG4gICAgeSA9IGFbMV0sXG4gICAgeiA9IGFbMl0sXG4gICAgdyA9IGFbM11cbiAgcmV0dXJuIHggKiB4ICsgeSAqIHkgKyB6ICogeiArIHcgKiB3XG59XG5cbn0se31dLDM5NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IHN1YnRyYWN0XG5cbi8qKlxuICogU3VidHJhY3RzIHZlY3RvciBiIGZyb20gdmVjdG9yIGFcbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSBmaXJzdCBvcGVyYW5kXG4gKiBAcGFyYW0ge3ZlYzR9IGIgdGhlIHNlY29uZCBvcGVyYW5kXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHN1YnRyYWN0IChvdXQsIGEsIGIpIHtcbiAgb3V0WzBdID0gYVswXSAtIGJbMF1cbiAgb3V0WzFdID0gYVsxXSAtIGJbMV1cbiAgb3V0WzJdID0gYVsyXSAtIGJbMl1cbiAgb3V0WzNdID0gYVszXSAtIGJbM11cbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzOTg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSB0cmFuc2Zvcm1NYXQ0XG5cbi8qKlxuICogVHJhbnNmb3JtcyB0aGUgdmVjNCB3aXRoIGEgbWF0NC5cbiAqXG4gKiBAcGFyYW0ge3ZlYzR9IG91dCB0aGUgcmVjZWl2aW5nIHZlY3RvclxuICogQHBhcmFtIHt2ZWM0fSBhIHRoZSB2ZWN0b3IgdG8gdHJhbnNmb3JtXG4gKiBAcGFyYW0ge21hdDR9IG0gbWF0cml4IHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHRyYW5zZm9ybU1hdDQgKG91dCwgYSwgbSkge1xuICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSwgdyA9IGFbM11cbiAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl0gKiB3XG4gIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzldICogeiArIG1bMTNdICogd1xuICBvdXRbMl0gPSBtWzJdICogeCArIG1bNl0gKiB5ICsgbVsxMF0gKiB6ICsgbVsxNF0gKiB3XG4gIG91dFszXSA9IG1bM10gKiB4ICsgbVs3XSAqIHkgKyBtWzExXSAqIHogKyBtWzE1XSAqIHdcbiAgcmV0dXJuIG91dFxufVxuXG59LHt9XSwzOTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSB0cmFuc2Zvcm1RdWF0XG5cbi8qKlxuICogVHJhbnNmb3JtcyB0aGUgdmVjNCB3aXRoIGEgcXVhdFxuICpcbiAqIEBwYXJhbSB7dmVjNH0gb3V0IHRoZSByZWNlaXZpbmcgdmVjdG9yXG4gKiBAcGFyYW0ge3ZlYzR9IGEgdGhlIHZlY3RvciB0byB0cmFuc2Zvcm1cbiAqIEBwYXJhbSB7cXVhdH0gcSBxdWF0ZXJuaW9uIHRvIHRyYW5zZm9ybSB3aXRoXG4gKiBAcmV0dXJucyB7dmVjNH0gb3V0XG4gKi9cbmZ1bmN0aW9uIHRyYW5zZm9ybVF1YXQgKG91dCwgYSwgcSkge1xuICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSxcbiAgICBxeCA9IHFbMF0sIHF5ID0gcVsxXSwgcXogPSBxWzJdLCBxdyA9IHFbM10sXG5cbiAgICAvLyBjYWxjdWxhdGUgcXVhdCAqIHZlY1xuICAgIGl4ID0gcXcgKiB4ICsgcXkgKiB6IC0gcXogKiB5LFxuICAgIGl5ID0gcXcgKiB5ICsgcXogKiB4IC0gcXggKiB6LFxuICAgIGl6ID0gcXcgKiB6ICsgcXggKiB5IC0gcXkgKiB4LFxuICAgIGl3ID0gLXF4ICogeCAtIHF5ICogeSAtIHF6ICogelxuXG4gIC8vIGNhbGN1bGF0ZSByZXN1bHQgKiBpbnZlcnNlIHF1YXRcbiAgb3V0WzBdID0gaXggKiBxdyArIGl3ICogLXF4ICsgaXkgKiAtcXogLSBpeiAqIC1xeVxuICBvdXRbMV0gPSBpeSAqIHF3ICsgaXcgKiAtcXkgKyBpeiAqIC1xeCAtIGl4ICogLXF6XG4gIG91dFsyXSA9IGl6ICogcXcgKyBpdyAqIC1xeiArIGl4ICogLXF5IC0gaXkgKiAtcXhcbiAgb3V0WzNdID0gYVszXVxuICByZXR1cm4gb3V0XG59XG5cbn0se31dLDQwMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGRlY29kZUZsb2F0XG5cbnZhciBVSU5UOF9WSUVXID0gbmV3IFVpbnQ4QXJyYXkoNClcbnZhciBGTE9BVF9WSUVXID0gbmV3IEZsb2F0MzJBcnJheShVSU5UOF9WSUVXLmJ1ZmZlcilcblxuZnVuY3Rpb24gZGVjb2RlRmxvYXQoeCwgeSwgeiwgdykge1xuICBVSU5UOF9WSUVXWzBdID0gd1xuICBVSU5UOF9WSUVXWzFdID0gelxuICBVSU5UOF9WSUVXWzJdID0geVxuICBVSU5UOF9WSUVXWzNdID0geFxuICByZXR1cm4gRkxPQVRfVklFV1swXVxufVxuXG59LHt9XSw0MDE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xudmFyIHRva2VuaXplID0gX2RlcmVxXygnZ2xzbC10b2tlbml6ZXInKVxudmFyIGF0b2IgICAgID0gX2RlcmVxXygnYXRvYi1saXRlJylcblxubW9kdWxlLmV4cG9ydHMgPSBnZXROYW1lXG5cbmZ1bmN0aW9uIGdldE5hbWUoc3JjKSB7XG4gIHZhciB0b2tlbnMgPSBBcnJheS5pc0FycmF5KHNyYylcbiAgICA/IHNyY1xuICAgIDogdG9rZW5pemUoc3JjKVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHRva2VuID0gdG9rZW5zW2ldXG4gICAgaWYgKHRva2VuLnR5cGUgIT09ICdwcmVwcm9jZXNzb3InKSBjb250aW51ZVxuICAgIHZhciBtYXRjaCA9IHRva2VuLmRhdGEubWF0Y2goL1xcI2RlZmluZVxccytTSEFERVJfTkFNRShfQjY0KT9cXHMrKC4rKSQvKVxuICAgIGlmICghbWF0Y2gpIGNvbnRpbnVlXG4gICAgaWYgKCFtYXRjaFsyXSkgY29udGludWVcblxuICAgIHZhciBiNjQgID0gbWF0Y2hbMV1cbiAgICB2YXIgbmFtZSA9IG1hdGNoWzJdXG5cbiAgICByZXR1cm4gKGI2NCA/IGF0b2IobmFtZSkgOiBuYW1lKS50cmltKClcbiAgfVxufVxuXG59LHtcImF0b2ItbGl0ZVwiOjcyLFwiZ2xzbC10b2tlbml6ZXJcIjo0MDh9XSw0MDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSB0b2tlbml6ZVxuXG52YXIgbGl0ZXJhbHMxMDAgPSBfZGVyZXFfKCcuL2xpYi9saXRlcmFscycpXG4gICwgb3BlcmF0b3JzID0gX2RlcmVxXygnLi9saWIvb3BlcmF0b3JzJylcbiAgLCBidWlsdGluczEwMCA9IF9kZXJlcV8oJy4vbGliL2J1aWx0aW5zJylcbiAgLCBsaXRlcmFsczMwMGVzID0gX2RlcmVxXygnLi9saWIvbGl0ZXJhbHMtMzAwZXMnKVxuICAsIGJ1aWx0aW5zMzAwZXMgPSBfZGVyZXFfKCcuL2xpYi9idWlsdGlucy0zMDBlcycpXG5cbnZhciBOT1JNQUwgPSA5OTkgICAgICAgICAgLy8gPC0tIG5ldmVyIGVtaXR0ZWRcbiAgLCBUT0tFTiA9IDk5OTkgICAgICAgICAgLy8gPC0tIG5ldmVyIGVtaXR0ZWRcbiAgLCBCTE9DS19DT01NRU5UID0gMFxuICAsIExJTkVfQ09NTUVOVCA9IDFcbiAgLCBQUkVQUk9DRVNTT1IgPSAyXG4gICwgT1BFUkFUT1IgPSAzXG4gICwgSU5URUdFUiA9IDRcbiAgLCBGTE9BVCA9IDVcbiAgLCBJREVOVCA9IDZcbiAgLCBCVUlMVElOID0gN1xuICAsIEtFWVdPUkQgPSA4XG4gICwgV0hJVEVTUEFDRSA9IDlcbiAgLCBFT0YgPSAxMFxuICAsIEhFWCA9IDExXG5cbnZhciBtYXAgPSBbXG4gICAgJ2Jsb2NrLWNvbW1lbnQnXG4gICwgJ2xpbmUtY29tbWVudCdcbiAgLCAncHJlcHJvY2Vzc29yJ1xuICAsICdvcGVyYXRvcidcbiAgLCAnaW50ZWdlcidcbiAgLCAnZmxvYXQnXG4gICwgJ2lkZW50J1xuICAsICdidWlsdGluJ1xuICAsICdrZXl3b3JkJ1xuICAsICd3aGl0ZXNwYWNlJ1xuICAsICdlb2YnXG4gICwgJ2ludGVnZXInXG5dXG5cbmZ1bmN0aW9uIHRva2VuaXplKG9wdCkge1xuICB2YXIgaSA9IDBcbiAgICAsIHRvdGFsID0gMFxuICAgICwgbW9kZSA9IE5PUk1BTFxuICAgICwgY1xuICAgICwgbGFzdFxuICAgICwgY29udGVudCA9IFtdXG4gICAgLCB0b2tlbnMgPSBbXVxuICAgICwgdG9rZW5faWR4ID0gMFxuICAgICwgdG9rZW5fb2ZmcyA9IDBcbiAgICAsIGxpbmUgPSAxXG4gICAgLCBjb2wgPSAwXG4gICAgLCBzdGFydCA9IDBcbiAgICAsIGlzbnVtID0gZmFsc2VcbiAgICAsIGlzb3BlcmF0b3IgPSBmYWxzZVxuICAgICwgaW5wdXQgPSAnJ1xuICAgICwgbGVuXG5cbiAgb3B0ID0gb3B0IHx8IHt9XG4gIHZhciBhbGxCdWlsdGlucyA9IGJ1aWx0aW5zMTAwXG4gIHZhciBhbGxMaXRlcmFscyA9IGxpdGVyYWxzMTAwXG4gIGlmIChvcHQudmVyc2lvbiA9PT0gJzMwMCBlcycpIHtcbiAgICBhbGxCdWlsdGlucyA9IGJ1aWx0aW5zMzAwZXNcbiAgICBhbGxMaXRlcmFscyA9IGxpdGVyYWxzMzAwZXNcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbihkYXRhKSB7XG4gICAgdG9rZW5zID0gW11cbiAgICBpZiAoZGF0YSAhPT0gbnVsbCkgcmV0dXJuIHdyaXRlKGRhdGEucmVwbGFjZSA/IGRhdGEucmVwbGFjZSgvXFxyXFxuL2csICdcXG4nKSA6IGRhdGEpXG4gICAgcmV0dXJuIGVuZCgpXG4gIH1cblxuICBmdW5jdGlvbiB0b2tlbihkYXRhKSB7XG4gICAgaWYgKGRhdGEubGVuZ3RoKSB7XG4gICAgICB0b2tlbnMucHVzaCh7XG4gICAgICAgIHR5cGU6IG1hcFttb2RlXVxuICAgICAgLCBkYXRhOiBkYXRhXG4gICAgICAsIHBvc2l0aW9uOiBzdGFydFxuICAgICAgLCBsaW5lOiBsaW5lXG4gICAgICAsIGNvbHVtbjogY29sXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHdyaXRlKGNodW5rKSB7XG4gICAgaSA9IDBcbiAgICBpbnB1dCArPSBjaHVua1xuICAgIGxlbiA9IGlucHV0Lmxlbmd0aFxuXG4gICAgdmFyIGxhc3RcblxuICAgIHdoaWxlKGMgPSBpbnB1dFtpXSwgaSA8IGxlbikge1xuICAgICAgbGFzdCA9IGlcblxuICAgICAgc3dpdGNoKG1vZGUpIHtcbiAgICAgICAgY2FzZSBCTE9DS19DT01NRU5UOiBpID0gYmxvY2tfY29tbWVudCgpOyBicmVha1xuICAgICAgICBjYXNlIExJTkVfQ09NTUVOVDogaSA9IGxpbmVfY29tbWVudCgpOyBicmVha1xuICAgICAgICBjYXNlIFBSRVBST0NFU1NPUjogaSA9IHByZXByb2Nlc3NvcigpOyBicmVha1xuICAgICAgICBjYXNlIE9QRVJBVE9SOiBpID0gb3BlcmF0b3IoKTsgYnJlYWtcbiAgICAgICAgY2FzZSBJTlRFR0VSOiBpID0gaW50ZWdlcigpOyBicmVha1xuICAgICAgICBjYXNlIEhFWDogaSA9IGhleCgpOyBicmVha1xuICAgICAgICBjYXNlIEZMT0FUOiBpID0gZGVjaW1hbCgpOyBicmVha1xuICAgICAgICBjYXNlIFRPS0VOOiBpID0gcmVhZHRva2VuKCk7IGJyZWFrXG4gICAgICAgIGNhc2UgV0hJVEVTUEFDRTogaSA9IHdoaXRlc3BhY2UoKTsgYnJlYWtcbiAgICAgICAgY2FzZSBOT1JNQUw6IGkgPSBub3JtYWwoKTsgYnJlYWtcbiAgICAgIH1cblxuICAgICAgaWYobGFzdCAhPT0gaSkge1xuICAgICAgICBzd2l0Y2goaW5wdXRbbGFzdF0pIHtcbiAgICAgICAgICBjYXNlICdcXG4nOiBjb2wgPSAwOyArK2xpbmU7IGJyZWFrXG4gICAgICAgICAgZGVmYXVsdDogKytjb2w7IGJyZWFrXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0b3RhbCArPSBpXG4gICAgaW5wdXQgPSBpbnB1dC5zbGljZShpKVxuICAgIHJldHVybiB0b2tlbnNcbiAgfVxuXG4gIGZ1bmN0aW9uIGVuZChjaHVuaykge1xuICAgIGlmKGNvbnRlbnQubGVuZ3RoKSB7XG4gICAgICB0b2tlbihjb250ZW50LmpvaW4oJycpKVxuICAgIH1cblxuICAgIG1vZGUgPSBFT0ZcbiAgICB0b2tlbignKGVvZiknKVxuICAgIHJldHVybiB0b2tlbnNcbiAgfVxuXG4gIGZ1bmN0aW9uIG5vcm1hbCgpIHtcbiAgICBjb250ZW50ID0gY29udGVudC5sZW5ndGggPyBbXSA6IGNvbnRlbnRcblxuICAgIGlmKGxhc3QgPT09ICcvJyAmJiBjID09PSAnKicpIHtcbiAgICAgIHN0YXJ0ID0gdG90YWwgKyBpIC0gMVxuICAgICAgbW9kZSA9IEJMT0NLX0NPTU1FTlRcbiAgICAgIGxhc3QgPSBjXG4gICAgICByZXR1cm4gaSArIDFcbiAgICB9XG5cbiAgICBpZihsYXN0ID09PSAnLycgJiYgYyA9PT0gJy8nKSB7XG4gICAgICBzdGFydCA9IHRvdGFsICsgaSAtIDFcbiAgICAgIG1vZGUgPSBMSU5FX0NPTU1FTlRcbiAgICAgIGxhc3QgPSBjXG4gICAgICByZXR1cm4gaSArIDFcbiAgICB9XG5cbiAgICBpZihjID09PSAnIycpIHtcbiAgICAgIG1vZGUgPSBQUkVQUk9DRVNTT1JcbiAgICAgIHN0YXJ0ID0gdG90YWwgKyBpXG4gICAgICByZXR1cm4gaVxuICAgIH1cblxuICAgIGlmKC9cXHMvLnRlc3QoYykpIHtcbiAgICAgIG1vZGUgPSBXSElURVNQQUNFXG4gICAgICBzdGFydCA9IHRvdGFsICsgaVxuICAgICAgcmV0dXJuIGlcbiAgICB9XG5cbiAgICBpc251bSA9IC9cXGQvLnRlc3QoYylcbiAgICBpc29wZXJhdG9yID0gL1teXFx3X10vLnRlc3QoYylcblxuICAgIHN0YXJ0ID0gdG90YWwgKyBpXG4gICAgbW9kZSA9IGlzbnVtID8gSU5URUdFUiA6IGlzb3BlcmF0b3IgPyBPUEVSQVRPUiA6IFRPS0VOXG4gICAgcmV0dXJuIGlcbiAgfVxuXG4gIGZ1bmN0aW9uIHdoaXRlc3BhY2UoKSB7XG4gICAgaWYoL1teXFxzXS9nLnRlc3QoYykpIHtcbiAgICAgIHRva2VuKGNvbnRlbnQuam9pbignJykpXG4gICAgICBtb2RlID0gTk9STUFMXG4gICAgICByZXR1cm4gaVxuICAgIH1cbiAgICBjb250ZW50LnB1c2goYylcbiAgICBsYXN0ID0gY1xuICAgIHJldHVybiBpICsgMVxuICB9XG5cbiAgZnVuY3Rpb24gcHJlcHJvY2Vzc29yKCkge1xuICAgIGlmKChjID09PSAnXFxyJyB8fCBjID09PSAnXFxuJykgJiYgbGFzdCAhPT0gJ1xcXFwnKSB7XG4gICAgICB0b2tlbihjb250ZW50LmpvaW4oJycpKVxuICAgICAgbW9kZSA9IE5PUk1BTFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG4gICAgY29udGVudC5wdXNoKGMpXG4gICAgbGFzdCA9IGNcbiAgICByZXR1cm4gaSArIDFcbiAgfVxuXG4gIGZ1bmN0aW9uIGxpbmVfY29tbWVudCgpIHtcbiAgICByZXR1cm4gcHJlcHJvY2Vzc29yKClcbiAgfVxuXG4gIGZ1bmN0aW9uIGJsb2NrX2NvbW1lbnQoKSB7XG4gICAgaWYoYyA9PT0gJy8nICYmIGxhc3QgPT09ICcqJykge1xuICAgICAgY29udGVudC5wdXNoKGMpXG4gICAgICB0b2tlbihjb250ZW50LmpvaW4oJycpKVxuICAgICAgbW9kZSA9IE5PUk1BTFxuICAgICAgcmV0dXJuIGkgKyAxXG4gICAgfVxuXG4gICAgY29udGVudC5wdXNoKGMpXG4gICAgbGFzdCA9IGNcbiAgICByZXR1cm4gaSArIDFcbiAgfVxuXG4gIGZ1bmN0aW9uIG9wZXJhdG9yKCkge1xuICAgIGlmKGxhc3QgPT09ICcuJyAmJiAvXFxkLy50ZXN0KGMpKSB7XG4gICAgICBtb2RlID0gRkxPQVRcbiAgICAgIHJldHVybiBpXG4gICAgfVxuXG4gICAgaWYobGFzdCA9PT0gJy8nICYmIGMgPT09ICcqJykge1xuICAgICAgbW9kZSA9IEJMT0NLX0NPTU1FTlRcbiAgICAgIHJldHVybiBpXG4gICAgfVxuXG4gICAgaWYobGFzdCA9PT0gJy8nICYmIGMgPT09ICcvJykge1xuICAgICAgbW9kZSA9IExJTkVfQ09NTUVOVFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG5cbiAgICBpZihjID09PSAnLicgJiYgY29udGVudC5sZW5ndGgpIHtcbiAgICAgIHdoaWxlKGRldGVybWluZV9vcGVyYXRvcihjb250ZW50KSk7XG5cbiAgICAgIG1vZGUgPSBGTE9BVFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG5cbiAgICBpZihjID09PSAnOycgfHwgYyA9PT0gJyknIHx8IGMgPT09ICcoJykge1xuICAgICAgaWYoY29udGVudC5sZW5ndGgpIHdoaWxlKGRldGVybWluZV9vcGVyYXRvcihjb250ZW50KSk7XG4gICAgICB0b2tlbihjKVxuICAgICAgbW9kZSA9IE5PUk1BTFxuICAgICAgcmV0dXJuIGkgKyAxXG4gICAgfVxuXG4gICAgdmFyIGlzX2NvbXBvc2l0ZV9vcGVyYXRvciA9IGNvbnRlbnQubGVuZ3RoID09PSAyICYmIGMgIT09ICc9J1xuICAgIGlmKC9bXFx3X1xcZFxcc10vLnRlc3QoYykgfHwgaXNfY29tcG9zaXRlX29wZXJhdG9yKSB7XG4gICAgICB3aGlsZShkZXRlcm1pbmVfb3BlcmF0b3IoY29udGVudCkpO1xuICAgICAgbW9kZSA9IE5PUk1BTFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG5cbiAgICBjb250ZW50LnB1c2goYylcbiAgICBsYXN0ID0gY1xuICAgIHJldHVybiBpICsgMVxuICB9XG5cbiAgZnVuY3Rpb24gZGV0ZXJtaW5lX29wZXJhdG9yKGJ1Zikge1xuICAgIHZhciBqID0gMFxuICAgICAgLCBpZHhcbiAgICAgICwgcmVzXG5cbiAgICBkbyB7XG4gICAgICBpZHggPSBvcGVyYXRvcnMuaW5kZXhPZihidWYuc2xpY2UoMCwgYnVmLmxlbmd0aCArIGopLmpvaW4oJycpKVxuICAgICAgcmVzID0gb3BlcmF0b3JzW2lkeF1cblxuICAgICAgaWYoaWR4ID09PSAtMSkge1xuICAgICAgICBpZihqLS0gKyBidWYubGVuZ3RoID4gMCkgY29udGludWVcbiAgICAgICAgcmVzID0gYnVmLnNsaWNlKDAsIDEpLmpvaW4oJycpXG4gICAgICB9XG5cbiAgICAgIHRva2VuKHJlcylcblxuICAgICAgc3RhcnQgKz0gcmVzLmxlbmd0aFxuICAgICAgY29udGVudCA9IGNvbnRlbnQuc2xpY2UocmVzLmxlbmd0aClcbiAgICAgIHJldHVybiBjb250ZW50Lmxlbmd0aFxuICAgIH0gd2hpbGUoMSlcbiAgfVxuXG4gIGZ1bmN0aW9uIGhleCgpIHtcbiAgICBpZigvW15hLWZBLUYwLTldLy50ZXN0KGMpKSB7XG4gICAgICB0b2tlbihjb250ZW50LmpvaW4oJycpKVxuICAgICAgbW9kZSA9IE5PUk1BTFxuICAgICAgcmV0dXJuIGlcbiAgICB9XG5cbiAgICBjb250ZW50LnB1c2goYylcbiAgICBsYXN0ID0gY1xuICAgIHJldHVybiBpICsgMVxuICB9XG5cbiAgZnVuY3Rpb24gaW50ZWdlcigpIHtcbiAgICBpZihjID09PSAnLicpIHtcbiAgICAgIGNvbnRlbnQucHVzaChjKVxuICAgICAgbW9kZSA9IEZMT0FUXG4gICAgICBsYXN0ID0gY1xuICAgICAgcmV0dXJuIGkgKyAxXG4gICAgfVxuXG4gICAgaWYoL1tlRV0vLnRlc3QoYykpIHtcbiAgICAgIGNvbnRlbnQucHVzaChjKVxuICAgICAgbW9kZSA9IEZMT0FUXG4gICAgICBsYXN0ID0gY1xuICAgICAgcmV0dXJuIGkgKyAxXG4gICAgfVxuXG4gICAgaWYoYyA9PT0gJ3gnICYmIGNvbnRlbnQubGVuZ3RoID09PSAxICYmIGNvbnRlbnRbMF0gPT09ICcwJykge1xuICAgICAgbW9kZSA9IEhFWFxuICAgICAgY29udGVudC5wdXNoKGMpXG4gICAgICBsYXN0ID0gY1xuICAgICAgcmV0dXJuIGkgKyAxXG4gICAgfVxuXG4gICAgaWYoL1teXFxkXS8udGVzdChjKSkge1xuICAgICAgdG9rZW4oY29udGVudC5qb2luKCcnKSlcbiAgICAgIG1vZGUgPSBOT1JNQUxcbiAgICAgIHJldHVybiBpXG4gICAgfVxuXG4gICAgY29udGVudC5wdXNoKGMpXG4gICAgbGFzdCA9IGNcbiAgICByZXR1cm4gaSArIDFcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlY2ltYWwoKSB7XG4gICAgaWYoYyA9PT0gJ2YnKSB7XG4gICAgICBjb250ZW50LnB1c2goYylcbiAgICAgIGxhc3QgPSBjXG4gICAgICBpICs9IDFcbiAgICB9XG5cbiAgICBpZigvW2VFXS8udGVzdChjKSkge1xuICAgICAgY29udGVudC5wdXNoKGMpXG4gICAgICBsYXN0ID0gY1xuICAgICAgcmV0dXJuIGkgKyAxXG4gICAgfVxuXG4gICAgaWYgKGMgPT09ICctJyAmJiAvW2VFXS8udGVzdChsYXN0KSkge1xuICAgICAgY29udGVudC5wdXNoKGMpXG4gICAgICBsYXN0ID0gY1xuICAgICAgcmV0dXJuIGkgKyAxXG4gICAgfVxuXG4gICAgaWYoL1teXFxkXS8udGVzdChjKSkge1xuICAgICAgdG9rZW4oY29udGVudC5qb2luKCcnKSlcbiAgICAgIG1vZGUgPSBOT1JNQUxcbiAgICAgIHJldHVybiBpXG4gICAgfVxuXG4gICAgY29udGVudC5wdXNoKGMpXG4gICAgbGFzdCA9IGNcbiAgICByZXR1cm4gaSArIDFcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlYWR0b2tlbigpIHtcbiAgICBpZigvW15cXGRcXHdfXS8udGVzdChjKSkge1xuICAgICAgdmFyIGNvbnRlbnRzdHIgPSBjb250ZW50LmpvaW4oJycpXG4gICAgICBpZihhbGxMaXRlcmFscy5pbmRleE9mKGNvbnRlbnRzdHIpID4gLTEpIHtcbiAgICAgICAgbW9kZSA9IEtFWVdPUkRcbiAgICAgIH0gZWxzZSBpZihhbGxCdWlsdGlucy5pbmRleE9mKGNvbnRlbnRzdHIpID4gLTEpIHtcbiAgICAgICAgbW9kZSA9IEJVSUxUSU5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1vZGUgPSBJREVOVFxuICAgICAgfVxuICAgICAgdG9rZW4oY29udGVudC5qb2luKCcnKSlcbiAgICAgIG1vZGUgPSBOT1JNQUxcbiAgICAgIHJldHVybiBpXG4gICAgfVxuICAgIGNvbnRlbnQucHVzaChjKVxuICAgIGxhc3QgPSBjXG4gICAgcmV0dXJuIGkgKyAxXG4gIH1cbn1cblxufSx7XCIuL2xpYi9idWlsdGluc1wiOjQwNCxcIi4vbGliL2J1aWx0aW5zLTMwMGVzXCI6NDAzLFwiLi9saWIvbGl0ZXJhbHNcIjo0MDYsXCIuL2xpYi9saXRlcmFscy0zMDBlc1wiOjQwNSxcIi4vbGliL29wZXJhdG9yc1wiOjQwN31dLDQwMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyAzMDBlcyBidWlsdGlucy9yZXNlcnZlZCB3b3JkcyB0aGF0IHdlcmUgcHJldmlvdXNseSB2YWxpZCBpbiB2MTAwXG52YXIgdjEwMCA9IF9kZXJlcV8oJy4vYnVpbHRpbnMnKVxuXG4vLyBUaGUgdGV4dHVyZTJEfEN1YmUgZnVuY3Rpb25zIGhhdmUgYmVlbiByZW1vdmVkXG4vLyBBbmQgdGhlIGdsXyBmZWF0dXJlcyBhcmUgdXBkYXRlZFxudjEwMCA9IHYxMDAuc2xpY2UoKS5maWx0ZXIoZnVuY3Rpb24gKGIpIHtcbiAgcmV0dXJuICEvXihnbFxcX3x0ZXh0dXJlKS8udGVzdChiKVxufSlcblxubW9kdWxlLmV4cG9ydHMgPSB2MTAwLmNvbmNhdChbXG4gIC8vIHRoZSB1cGRhdGVkIGdsXyBjb25zdGFudHNcbiAgICAnZ2xfVmVydGV4SUQnXG4gICwgJ2dsX0luc3RhbmNlSUQnXG4gICwgJ2dsX1Bvc2l0aW9uJ1xuICAsICdnbF9Qb2ludFNpemUnXG4gICwgJ2dsX0ZyYWdDb29yZCdcbiAgLCAnZ2xfRnJvbnRGYWNpbmcnXG4gICwgJ2dsX0ZyYWdEZXB0aCdcbiAgLCAnZ2xfUG9pbnRDb29yZCdcbiAgLCAnZ2xfTWF4VmVydGV4QXR0cmlicydcbiAgLCAnZ2xfTWF4VmVydGV4VW5pZm9ybVZlY3RvcnMnXG4gICwgJ2dsX01heFZlcnRleE91dHB1dFZlY3RvcnMnXG4gICwgJ2dsX01heEZyYWdtZW50SW5wdXRWZWN0b3JzJ1xuICAsICdnbF9NYXhWZXJ0ZXhUZXh0dXJlSW1hZ2VVbml0cydcbiAgLCAnZ2xfTWF4Q29tYmluZWRUZXh0dXJlSW1hZ2VVbml0cydcbiAgLCAnZ2xfTWF4VGV4dHVyZUltYWdlVW5pdHMnXG4gICwgJ2dsX01heEZyYWdtZW50VW5pZm9ybVZlY3RvcnMnXG4gICwgJ2dsX01heERyYXdCdWZmZXJzJ1xuICAsICdnbF9NaW5Qcm9ncmFtVGV4ZWxPZmZzZXQnXG4gICwgJ2dsX01heFByb2dyYW1UZXhlbE9mZnNldCdcbiAgLCAnZ2xfRGVwdGhSYW5nZVBhcmFtZXRlcnMnXG4gICwgJ2dsX0RlcHRoUmFuZ2UnXG5cbiAgLy8gb3RoZXIgYnVpbHRpbnNcbiAgLCAndHJ1bmMnXG4gICwgJ3JvdW5kJ1xuICAsICdyb3VuZEV2ZW4nXG4gICwgJ2lzbmFuJ1xuICAsICdpc2luZidcbiAgLCAnZmxvYXRCaXRzVG9JbnQnXG4gICwgJ2Zsb2F0Qml0c1RvVWludCdcbiAgLCAnaW50Qml0c1RvRmxvYXQnXG4gICwgJ3VpbnRCaXRzVG9GbG9hdCdcbiAgLCAncGFja1Nub3JtMngxNidcbiAgLCAndW5wYWNrU25vcm0yeDE2J1xuICAsICdwYWNrVW5vcm0yeDE2J1xuICAsICd1bnBhY2tVbm9ybTJ4MTYnXG4gICwgJ3BhY2tIYWxmMngxNidcbiAgLCAndW5wYWNrSGFsZjJ4MTYnXG4gICwgJ291dGVyUHJvZHVjdCdcbiAgLCAndHJhbnNwb3NlJ1xuICAsICdkZXRlcm1pbmFudCdcbiAgLCAnaW52ZXJzZSdcbiAgLCAndGV4dHVyZSdcbiAgLCAndGV4dHVyZVNpemUnXG4gICwgJ3RleHR1cmVQcm9qJ1xuICAsICd0ZXh0dXJlTG9kJ1xuICAsICd0ZXh0dXJlT2Zmc2V0J1xuICAsICd0ZXhlbEZldGNoJ1xuICAsICd0ZXhlbEZldGNoT2Zmc2V0J1xuICAsICd0ZXh0dXJlUHJvak9mZnNldCdcbiAgLCAndGV4dHVyZUxvZE9mZnNldCdcbiAgLCAndGV4dHVyZVByb2pMb2QnXG4gICwgJ3RleHR1cmVQcm9qTG9kT2Zmc2V0J1xuICAsICd0ZXh0dXJlR3JhZCdcbiAgLCAndGV4dHVyZUdyYWRPZmZzZXQnXG4gICwgJ3RleHR1cmVQcm9qR3JhZCdcbiAgLCAndGV4dHVyZVByb2pHcmFkT2Zmc2V0J1xuXSlcblxufSx7XCIuL2J1aWx0aW5zXCI6NDA0fV0sNDA0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gW1xuICAvLyBLZWVwIHRoaXMgbGlzdCBzb3J0ZWRcbiAgJ2FicydcbiAgLCAnYWNvcydcbiAgLCAnYWxsJ1xuICAsICdhbnknXG4gICwgJ2FzaW4nXG4gICwgJ2F0YW4nXG4gICwgJ2NlaWwnXG4gICwgJ2NsYW1wJ1xuICAsICdjb3MnXG4gICwgJ2Nyb3NzJ1xuICAsICdkRmR4J1xuICAsICdkRmR5J1xuICAsICdkZWdyZWVzJ1xuICAsICdkaXN0YW5jZSdcbiAgLCAnZG90J1xuICAsICdlcXVhbCdcbiAgLCAnZXhwJ1xuICAsICdleHAyJ1xuICAsICdmYWNlZm9yd2FyZCdcbiAgLCAnZmxvb3InXG4gICwgJ2ZyYWN0J1xuICAsICdnbF9CYWNrQ29sb3InXG4gICwgJ2dsX0JhY2tMaWdodE1vZGVsUHJvZHVjdCdcbiAgLCAnZ2xfQmFja0xpZ2h0UHJvZHVjdCdcbiAgLCAnZ2xfQmFja01hdGVyaWFsJ1xuICAsICdnbF9CYWNrU2Vjb25kYXJ5Q29sb3InXG4gICwgJ2dsX0NsaXBQbGFuZSdcbiAgLCAnZ2xfQ2xpcFZlcnRleCdcbiAgLCAnZ2xfQ29sb3InXG4gICwgJ2dsX0RlcHRoUmFuZ2UnXG4gICwgJ2dsX0RlcHRoUmFuZ2VQYXJhbWV0ZXJzJ1xuICAsICdnbF9FeWVQbGFuZVEnXG4gICwgJ2dsX0V5ZVBsYW5lUidcbiAgLCAnZ2xfRXllUGxhbmVTJ1xuICAsICdnbF9FeWVQbGFuZVQnXG4gICwgJ2dsX0ZvZydcbiAgLCAnZ2xfRm9nQ29vcmQnXG4gICwgJ2dsX0ZvZ0ZyYWdDb29yZCdcbiAgLCAnZ2xfRm9nUGFyYW1ldGVycydcbiAgLCAnZ2xfRnJhZ0NvbG9yJ1xuICAsICdnbF9GcmFnQ29vcmQnXG4gICwgJ2dsX0ZyYWdEYXRhJ1xuICAsICdnbF9GcmFnRGVwdGgnXG4gICwgJ2dsX0ZyYWdEZXB0aEVYVCdcbiAgLCAnZ2xfRnJvbnRDb2xvcidcbiAgLCAnZ2xfRnJvbnRGYWNpbmcnXG4gICwgJ2dsX0Zyb250TGlnaHRNb2RlbFByb2R1Y3QnXG4gICwgJ2dsX0Zyb250TGlnaHRQcm9kdWN0J1xuICAsICdnbF9Gcm9udE1hdGVyaWFsJ1xuICAsICdnbF9Gcm9udFNlY29uZGFyeUNvbG9yJ1xuICAsICdnbF9MaWdodE1vZGVsJ1xuICAsICdnbF9MaWdodE1vZGVsUGFyYW1ldGVycydcbiAgLCAnZ2xfTGlnaHRNb2RlbFByb2R1Y3RzJ1xuICAsICdnbF9MaWdodFByb2R1Y3RzJ1xuICAsICdnbF9MaWdodFNvdXJjZSdcbiAgLCAnZ2xfTGlnaHRTb3VyY2VQYXJhbWV0ZXJzJ1xuICAsICdnbF9NYXRlcmlhbFBhcmFtZXRlcnMnXG4gICwgJ2dsX01heENsaXBQbGFuZXMnXG4gICwgJ2dsX01heENvbWJpbmVkVGV4dHVyZUltYWdlVW5pdHMnXG4gICwgJ2dsX01heERyYXdCdWZmZXJzJ1xuICAsICdnbF9NYXhGcmFnbWVudFVuaWZvcm1Db21wb25lbnRzJ1xuICAsICdnbF9NYXhMaWdodHMnXG4gICwgJ2dsX01heFRleHR1cmVDb29yZHMnXG4gICwgJ2dsX01heFRleHR1cmVJbWFnZVVuaXRzJ1xuICAsICdnbF9NYXhUZXh0dXJlVW5pdHMnXG4gICwgJ2dsX01heFZhcnlpbmdGbG9hdHMnXG4gICwgJ2dsX01heFZlcnRleEF0dHJpYnMnXG4gICwgJ2dsX01heFZlcnRleFRleHR1cmVJbWFnZVVuaXRzJ1xuICAsICdnbF9NYXhWZXJ0ZXhVbmlmb3JtQ29tcG9uZW50cydcbiAgLCAnZ2xfTW9kZWxWaWV3TWF0cml4J1xuICAsICdnbF9Nb2RlbFZpZXdNYXRyaXhJbnZlcnNlJ1xuICAsICdnbF9Nb2RlbFZpZXdNYXRyaXhJbnZlcnNlVHJhbnNwb3NlJ1xuICAsICdnbF9Nb2RlbFZpZXdNYXRyaXhUcmFuc3Bvc2UnXG4gICwgJ2dsX01vZGVsVmlld1Byb2plY3Rpb25NYXRyaXgnXG4gICwgJ2dsX01vZGVsVmlld1Byb2plY3Rpb25NYXRyaXhJbnZlcnNlJ1xuICAsICdnbF9Nb2RlbFZpZXdQcm9qZWN0aW9uTWF0cml4SW52ZXJzZVRyYW5zcG9zZSdcbiAgLCAnZ2xfTW9kZWxWaWV3UHJvamVjdGlvbk1hdHJpeFRyYW5zcG9zZSdcbiAgLCAnZ2xfTXVsdGlUZXhDb29yZDAnXG4gICwgJ2dsX011bHRpVGV4Q29vcmQxJ1xuICAsICdnbF9NdWx0aVRleENvb3JkMidcbiAgLCAnZ2xfTXVsdGlUZXhDb29yZDMnXG4gICwgJ2dsX011bHRpVGV4Q29vcmQ0J1xuICAsICdnbF9NdWx0aVRleENvb3JkNSdcbiAgLCAnZ2xfTXVsdGlUZXhDb29yZDYnXG4gICwgJ2dsX011bHRpVGV4Q29vcmQ3J1xuICAsICdnbF9Ob3JtYWwnXG4gICwgJ2dsX05vcm1hbE1hdHJpeCdcbiAgLCAnZ2xfTm9ybWFsU2NhbGUnXG4gICwgJ2dsX09iamVjdFBsYW5lUSdcbiAgLCAnZ2xfT2JqZWN0UGxhbmVSJ1xuICAsICdnbF9PYmplY3RQbGFuZVMnXG4gICwgJ2dsX09iamVjdFBsYW5lVCdcbiAgLCAnZ2xfUG9pbnQnXG4gICwgJ2dsX1BvaW50Q29vcmQnXG4gICwgJ2dsX1BvaW50UGFyYW1ldGVycydcbiAgLCAnZ2xfUG9pbnRTaXplJ1xuICAsICdnbF9Qb3NpdGlvbidcbiAgLCAnZ2xfUHJvamVjdGlvbk1hdHJpeCdcbiAgLCAnZ2xfUHJvamVjdGlvbk1hdHJpeEludmVyc2UnXG4gICwgJ2dsX1Byb2plY3Rpb25NYXRyaXhJbnZlcnNlVHJhbnNwb3NlJ1xuICAsICdnbF9Qcm9qZWN0aW9uTWF0cml4VHJhbnNwb3NlJ1xuICAsICdnbF9TZWNvbmRhcnlDb2xvcidcbiAgLCAnZ2xfVGV4Q29vcmQnXG4gICwgJ2dsX1RleHR1cmVFbnZDb2xvcidcbiAgLCAnZ2xfVGV4dHVyZU1hdHJpeCdcbiAgLCAnZ2xfVGV4dHVyZU1hdHJpeEludmVyc2UnXG4gICwgJ2dsX1RleHR1cmVNYXRyaXhJbnZlcnNlVHJhbnNwb3NlJ1xuICAsICdnbF9UZXh0dXJlTWF0cml4VHJhbnNwb3NlJ1xuICAsICdnbF9WZXJ0ZXgnXG4gICwgJ2dyZWF0ZXJUaGFuJ1xuICAsICdncmVhdGVyVGhhbkVxdWFsJ1xuICAsICdpbnZlcnNlc3FydCdcbiAgLCAnbGVuZ3RoJ1xuICAsICdsZXNzVGhhbidcbiAgLCAnbGVzc1RoYW5FcXVhbCdcbiAgLCAnbG9nJ1xuICAsICdsb2cyJ1xuICAsICdtYXRyaXhDb21wTXVsdCdcbiAgLCAnbWF4J1xuICAsICdtaW4nXG4gICwgJ21peCdcbiAgLCAnbW9kJ1xuICAsICdub3JtYWxpemUnXG4gICwgJ25vdCdcbiAgLCAnbm90RXF1YWwnXG4gICwgJ3BvdydcbiAgLCAncmFkaWFucydcbiAgLCAncmVmbGVjdCdcbiAgLCAncmVmcmFjdCdcbiAgLCAnc2lnbidcbiAgLCAnc2luJ1xuICAsICdzbW9vdGhzdGVwJ1xuICAsICdzcXJ0J1xuICAsICdzdGVwJ1xuICAsICd0YW4nXG4gICwgJ3RleHR1cmUyRCdcbiAgLCAndGV4dHVyZTJETG9kJ1xuICAsICd0ZXh0dXJlMkRQcm9qJ1xuICAsICd0ZXh0dXJlMkRQcm9qTG9kJ1xuICAsICd0ZXh0dXJlQ3ViZSdcbiAgLCAndGV4dHVyZUN1YmVMb2QnXG4gICwgJ3RleHR1cmUyRExvZEVYVCdcbiAgLCAndGV4dHVyZTJEUHJvakxvZEVYVCdcbiAgLCAndGV4dHVyZUN1YmVMb2RFWFQnXG4gICwgJ3RleHR1cmUyREdyYWRFWFQnXG4gICwgJ3RleHR1cmUyRFByb2pHcmFkRVhUJ1xuICAsICd0ZXh0dXJlQ3ViZUdyYWRFWFQnXG5dXG5cbn0se31dLDQwNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG52YXIgdjEwMCA9IF9kZXJlcV8oJy4vbGl0ZXJhbHMnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHYxMDAuc2xpY2UoKS5jb25jYXQoW1xuICAgJ2xheW91dCdcbiAgLCAnY2VudHJvaWQnXG4gICwgJ3Ntb290aCdcbiAgLCAnY2FzZSdcbiAgLCAnbWF0MngyJ1xuICAsICdtYXQyeDMnXG4gICwgJ21hdDJ4NCdcbiAgLCAnbWF0M3gyJ1xuICAsICdtYXQzeDMnXG4gICwgJ21hdDN4NCdcbiAgLCAnbWF0NHgyJ1xuICAsICdtYXQ0eDMnXG4gICwgJ21hdDR4NCdcbiAgLCAndWludCdcbiAgLCAndXZlYzInXG4gICwgJ3V2ZWMzJ1xuICAsICd1dmVjNCdcbiAgLCAnc2FtcGxlckN1YmVTaGFkb3cnXG4gICwgJ3NhbXBsZXIyREFycmF5J1xuICAsICdzYW1wbGVyMkRBcnJheVNoYWRvdydcbiAgLCAnaXNhbXBsZXIyRCdcbiAgLCAnaXNhbXBsZXIzRCdcbiAgLCAnaXNhbXBsZXJDdWJlJ1xuICAsICdpc2FtcGxlcjJEQXJyYXknXG4gICwgJ3VzYW1wbGVyMkQnXG4gICwgJ3VzYW1wbGVyM0QnXG4gICwgJ3VzYW1wbGVyQ3ViZSdcbiAgLCAndXNhbXBsZXIyREFycmF5J1xuICAsICdjb2hlcmVudCdcbiAgLCAncmVzdHJpY3QnXG4gICwgJ3JlYWRvbmx5J1xuICAsICd3cml0ZW9ubHknXG4gICwgJ3Jlc291cmNlJ1xuICAsICdhdG9taWNfdWludCdcbiAgLCAnbm9wZXJzcGVjdGl2ZSdcbiAgLCAncGF0Y2gnXG4gICwgJ3NhbXBsZSdcbiAgLCAnc3Vicm91dGluZSdcbiAgLCAnY29tbW9uJ1xuICAsICdwYXJ0aXRpb24nXG4gICwgJ2FjdGl2ZSdcbiAgLCAnZmlsdGVyJ1xuICAsICdpbWFnZTFEJ1xuICAsICdpbWFnZTJEJ1xuICAsICdpbWFnZTNEJ1xuICAsICdpbWFnZUN1YmUnXG4gICwgJ2lpbWFnZTFEJ1xuICAsICdpaW1hZ2UyRCdcbiAgLCAnaWltYWdlM0QnXG4gICwgJ2lpbWFnZUN1YmUnXG4gICwgJ3VpbWFnZTFEJ1xuICAsICd1aW1hZ2UyRCdcbiAgLCAndWltYWdlM0QnXG4gICwgJ3VpbWFnZUN1YmUnXG4gICwgJ2ltYWdlMURBcnJheSdcbiAgLCAnaW1hZ2UyREFycmF5J1xuICAsICdpaW1hZ2UxREFycmF5J1xuICAsICdpaW1hZ2UyREFycmF5J1xuICAsICd1aW1hZ2UxREFycmF5J1xuICAsICd1aW1hZ2UyREFycmF5J1xuICAsICdpbWFnZTFEU2hhZG93J1xuICAsICdpbWFnZTJEU2hhZG93J1xuICAsICdpbWFnZTFEQXJyYXlTaGFkb3cnXG4gICwgJ2ltYWdlMkRBcnJheVNoYWRvdydcbiAgLCAnaW1hZ2VCdWZmZXInXG4gICwgJ2lpbWFnZUJ1ZmZlcidcbiAgLCAndWltYWdlQnVmZmVyJ1xuICAsICdzYW1wbGVyMURBcnJheSdcbiAgLCAnc2FtcGxlcjFEQXJyYXlTaGFkb3cnXG4gICwgJ2lzYW1wbGVyMUQnXG4gICwgJ2lzYW1wbGVyMURBcnJheSdcbiAgLCAndXNhbXBsZXIxRCdcbiAgLCAndXNhbXBsZXIxREFycmF5J1xuICAsICdpc2FtcGxlcjJEUmVjdCdcbiAgLCAndXNhbXBsZXIyRFJlY3QnXG4gICwgJ3NhbXBsZXJCdWZmZXInXG4gICwgJ2lzYW1wbGVyQnVmZmVyJ1xuICAsICd1c2FtcGxlckJ1ZmZlcidcbiAgLCAnc2FtcGxlcjJETVMnXG4gICwgJ2lzYW1wbGVyMkRNUydcbiAgLCAndXNhbXBsZXIyRE1TJ1xuICAsICdzYW1wbGVyMkRNU0FycmF5J1xuICAsICdpc2FtcGxlcjJETVNBcnJheSdcbiAgLCAndXNhbXBsZXIyRE1TQXJyYXknXG5dKVxuXG59LHtcIi4vbGl0ZXJhbHNcIjo0MDZ9XSw0MDY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBbXG4gIC8vIGN1cnJlbnRcbiAgICAncHJlY2lzaW9uJ1xuICAsICdoaWdocCdcbiAgLCAnbWVkaXVtcCdcbiAgLCAnbG93cCdcbiAgLCAnYXR0cmlidXRlJ1xuICAsICdjb25zdCdcbiAgLCAndW5pZm9ybSdcbiAgLCAndmFyeWluZydcbiAgLCAnYnJlYWsnXG4gICwgJ2NvbnRpbnVlJ1xuICAsICdkbydcbiAgLCAnZm9yJ1xuICAsICd3aGlsZSdcbiAgLCAnaWYnXG4gICwgJ2Vsc2UnXG4gICwgJ2luJ1xuICAsICdvdXQnXG4gICwgJ2lub3V0J1xuICAsICdmbG9hdCdcbiAgLCAnaW50J1xuICAsICd2b2lkJ1xuICAsICdib29sJ1xuICAsICd0cnVlJ1xuICAsICdmYWxzZSdcbiAgLCAnZGlzY2FyZCdcbiAgLCAncmV0dXJuJ1xuICAsICdtYXQyJ1xuICAsICdtYXQzJ1xuICAsICdtYXQ0J1xuICAsICd2ZWMyJ1xuICAsICd2ZWMzJ1xuICAsICd2ZWM0J1xuICAsICdpdmVjMidcbiAgLCAnaXZlYzMnXG4gICwgJ2l2ZWM0J1xuICAsICdidmVjMidcbiAgLCAnYnZlYzMnXG4gICwgJ2J2ZWM0J1xuICAsICdzYW1wbGVyMUQnXG4gICwgJ3NhbXBsZXIyRCdcbiAgLCAnc2FtcGxlcjNEJ1xuICAsICdzYW1wbGVyQ3ViZSdcbiAgLCAnc2FtcGxlcjFEU2hhZG93J1xuICAsICdzYW1wbGVyMkRTaGFkb3cnXG4gICwgJ3N0cnVjdCdcblxuICAvLyBmdXR1cmVcbiAgLCAnYXNtJ1xuICAsICdjbGFzcydcbiAgLCAndW5pb24nXG4gICwgJ2VudW0nXG4gICwgJ3R5cGVkZWYnXG4gICwgJ3RlbXBsYXRlJ1xuICAsICd0aGlzJ1xuICAsICdwYWNrZWQnXG4gICwgJ2dvdG8nXG4gICwgJ3N3aXRjaCdcbiAgLCAnZGVmYXVsdCdcbiAgLCAnaW5saW5lJ1xuICAsICdub2lubGluZSdcbiAgLCAndm9sYXRpbGUnXG4gICwgJ3B1YmxpYydcbiAgLCAnc3RhdGljJ1xuICAsICdleHRlcm4nXG4gICwgJ2V4dGVybmFsJ1xuICAsICdpbnRlcmZhY2UnXG4gICwgJ2xvbmcnXG4gICwgJ3Nob3J0J1xuICAsICdkb3VibGUnXG4gICwgJ2hhbGYnXG4gICwgJ2ZpeGVkJ1xuICAsICd1bnNpZ25lZCdcbiAgLCAnaW5wdXQnXG4gICwgJ291dHB1dCdcbiAgLCAnaHZlYzInXG4gICwgJ2h2ZWMzJ1xuICAsICdodmVjNCdcbiAgLCAnZHZlYzInXG4gICwgJ2R2ZWMzJ1xuICAsICdkdmVjNCdcbiAgLCAnZnZlYzInXG4gICwgJ2Z2ZWMzJ1xuICAsICdmdmVjNCdcbiAgLCAnc2FtcGxlcjJEUmVjdCdcbiAgLCAnc2FtcGxlcjNEUmVjdCdcbiAgLCAnc2FtcGxlcjJEUmVjdFNoYWRvdydcbiAgLCAnc2l6ZW9mJ1xuICAsICdjYXN0J1xuICAsICduYW1lc3BhY2UnXG4gICwgJ3VzaW5nJ1xuXVxuXG59LHt9XSw0MDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBbXG4gICAgJzw8PSdcbiAgLCAnPj49J1xuICAsICcrKydcbiAgLCAnLS0nXG4gICwgJzw8J1xuICAsICc+PidcbiAgLCAnPD0nXG4gICwgJz49J1xuICAsICc9PSdcbiAgLCAnIT0nXG4gICwgJyYmJ1xuICAsICd8fCdcbiAgLCAnKz0nXG4gICwgJy09J1xuICAsICcqPSdcbiAgLCAnLz0nXG4gICwgJyU9J1xuICAsICcmPSdcbiAgLCAnXl4nXG4gICwgJ149J1xuICAsICd8PSdcbiAgLCAnKCdcbiAgLCAnKSdcbiAgLCAnWydcbiAgLCAnXSdcbiAgLCAnLidcbiAgLCAnISdcbiAgLCAnfidcbiAgLCAnKidcbiAgLCAnLydcbiAgLCAnJSdcbiAgLCAnKydcbiAgLCAnLSdcbiAgLCAnPCdcbiAgLCAnPidcbiAgLCAnJidcbiAgLCAnXidcbiAgLCAnfCdcbiAgLCAnPydcbiAgLCAnOidcbiAgLCAnPSdcbiAgLCAnLCdcbiAgLCAnOydcbiAgLCAneydcbiAgLCAnfSdcbl1cblxufSx7fV0sNDA4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciB0b2tlbml6ZSA9IF9kZXJlcV8oJy4vaW5kZXgnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRva2VuaXplU3RyaW5nXG5cbmZ1bmN0aW9uIHRva2VuaXplU3RyaW5nKHN0ciwgb3B0KSB7XG4gIHZhciBnZW5lcmF0b3IgPSB0b2tlbml6ZShvcHQpXG4gIHZhciB0b2tlbnMgPSBbXVxuXG4gIHRva2VucyA9IHRva2Vucy5jb25jYXQoZ2VuZXJhdG9yKHN0cikpXG4gIHRva2VucyA9IHRva2Vucy5jb25jYXQoZ2VuZXJhdG9yKG51bGwpKVxuXG4gIHJldHVybiB0b2tlbnNcbn1cblxufSx7XCIuL2luZGV4XCI6NDAyfV0sNDA5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc3RyaW5ncykge1xyXG4gIGlmICh0eXBlb2Ygc3RyaW5ncyA9PT0gJ3N0cmluZycpIHN0cmluZ3MgPSBbc3RyaW5nc11cclxuICB2YXIgZXhwcnMgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywxKVxyXG4gIHZhciBwYXJ0cyA9IFtdXHJcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHJpbmdzLmxlbmd0aC0xOyBpKyspIHtcclxuICAgIHBhcnRzLnB1c2goc3RyaW5nc1tpXSwgZXhwcnNbaV0gfHwgJycpXHJcbiAgfVxyXG4gIHBhcnRzLnB1c2goc3RyaW5nc1tpXSlcclxuICByZXR1cm4gcGFydHMuam9pbignJylcclxufVxyXG5cbn0se31dLDQxMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4oZnVuY3Rpb24gKGdsb2JhbCl7XG4ndXNlIHN0cmljdCdcclxuXHJcbnZhciBpc0Jyb3dzZXIgPSBfZGVyZXFfKCdpcy1icm93c2VyJylcclxudmFyIGhhc0hvdmVyXHJcblxyXG5pZiAodHlwZW9mIGdsb2JhbC5tYXRjaE1lZGlhID09PSAnZnVuY3Rpb24nKSB7XHJcblx0aGFzSG92ZXIgPSAhZ2xvYmFsLm1hdGNoTWVkaWEoJyhob3Zlcjogbm9uZSknKS5tYXRjaGVzXHJcbn1cclxuZWxzZSB7XHJcblx0aGFzSG92ZXIgPSBpc0Jyb3dzZXJcclxufVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBoYXNIb3ZlclxyXG5cbn0pLmNhbGwodGhpcyx0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KVxufSx7XCJpcy1icm93c2VyXCI6NDE3fV0sNDExOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGlzQnJvd3NlciA9IF9kZXJlcV8oJ2lzLWJyb3dzZXInKVxyXG5cclxuZnVuY3Rpb24gZGV0ZWN0KCkge1xyXG5cdHZhciBzdXBwb3J0ZWQgPSBmYWxzZVxyXG5cclxuXHR0cnkge1xyXG5cdFx0dmFyIG9wdHMgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdwYXNzaXZlJywge1xyXG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCkge1xyXG5cdFx0XHRcdHN1cHBvcnRlZCA9IHRydWVcclxuXHRcdFx0fVxyXG5cdFx0fSlcclxuXHJcblx0XHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigndGVzdCcsIG51bGwsIG9wdHMpXHJcblx0XHR3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigndGVzdCcsIG51bGwsIG9wdHMpXHJcblx0fSBjYXRjaChlKSB7XHJcblx0XHRzdXBwb3J0ZWQgPSBmYWxzZVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIHN1cHBvcnRlZFxyXG59XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGlzQnJvd3NlciAmJiBkZXRlY3QoKVxyXG5cbn0se1wiaXMtYnJvd3NlclwiOjQxN31dLDQxMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5leHBvcnRzLnJlYWQgPSBmdW5jdGlvbiAoYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbVxuICB2YXIgZUxlbiA9IChuQnl0ZXMgKiA4KSAtIG1MZW4gLSAxXG4gIHZhciBlTWF4ID0gKDEgPDwgZUxlbikgLSAxXG4gIHZhciBlQmlhcyA9IGVNYXggPj4gMVxuICB2YXIgbkJpdHMgPSAtN1xuICB2YXIgaSA9IGlzTEUgPyAobkJ5dGVzIC0gMSkgOiAwXG4gIHZhciBkID0gaXNMRSA/IC0xIDogMVxuICB2YXIgcyA9IGJ1ZmZlcltvZmZzZXQgKyBpXVxuXG4gIGkgKz0gZFxuXG4gIGUgPSBzICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIHMgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IGVMZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgZSA9IChlICogMjU2KSArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIGUgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IG1MZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IChtICogMjU2KSArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIGlmIChlID09PSAwKSB7XG4gICAgZSA9IDEgLSBlQmlhc1xuICB9IGVsc2UgaWYgKGUgPT09IGVNYXgpIHtcbiAgICByZXR1cm4gbSA/IE5hTiA6ICgocyA/IC0xIDogMSkgKiBJbmZpbml0eSlcbiAgfSBlbHNlIHtcbiAgICBtID0gbSArIE1hdGgucG93KDIsIG1MZW4pXG4gICAgZSA9IGUgLSBlQmlhc1xuICB9XG4gIHJldHVybiAocyA/IC0xIDogMSkgKiBtICogTWF0aC5wb3coMiwgZSAtIG1MZW4pXG59XG5cbmV4cG9ydHMud3JpdGUgPSBmdW5jdGlvbiAoYnVmZmVyLCB2YWx1ZSwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG0sIGNcbiAgdmFyIGVMZW4gPSAobkJ5dGVzICogOCkgLSBtTGVuIC0gMVxuICB2YXIgZU1heCA9ICgxIDw8IGVMZW4pIC0gMVxuICB2YXIgZUJpYXMgPSBlTWF4ID4+IDFcbiAgdmFyIHJ0ID0gKG1MZW4gPT09IDIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwKVxuICB2YXIgaSA9IGlzTEUgPyAwIDogKG5CeXRlcyAtIDEpXG4gIHZhciBkID0gaXNMRSA/IDEgOiAtMVxuICB2YXIgcyA9IHZhbHVlIDwgMCB8fCAodmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCkgPyAxIDogMFxuXG4gIHZhbHVlID0gTWF0aC5hYnModmFsdWUpXG5cbiAgaWYgKGlzTmFOKHZhbHVlKSB8fCB2YWx1ZSA9PT0gSW5maW5pdHkpIHtcbiAgICBtID0gaXNOYU4odmFsdWUpID8gMSA6IDBcbiAgICBlID0gZU1heFxuICB9IGVsc2Uge1xuICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKVxuICAgIGlmICh2YWx1ZSAqIChjID0gTWF0aC5wb3coMiwgLWUpKSA8IDEpIHtcbiAgICAgIGUtLVxuICAgICAgYyAqPSAyXG4gICAgfVxuICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgdmFsdWUgKz0gcnQgLyBjXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlICs9IHJ0ICogTWF0aC5wb3coMiwgMSAtIGVCaWFzKVxuICAgIH1cbiAgICBpZiAodmFsdWUgKiBjID49IDIpIHtcbiAgICAgIGUrK1xuICAgICAgYyAvPSAyXG4gICAgfVxuXG4gICAgaWYgKGUgKyBlQmlhcyA+PSBlTWF4KSB7XG4gICAgICBtID0gMFxuICAgICAgZSA9IGVNYXhcbiAgICB9IGVsc2UgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICBtID0gKCh2YWx1ZSAqIGMpIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IGUgKyBlQmlhc1xuICAgIH0gZWxzZSB7XG4gICAgICBtID0gdmFsdWUgKiBNYXRoLnBvdygyLCBlQmlhcyAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSAwXG4gICAgfVxuICB9XG5cbiAgZm9yICg7IG1MZW4gPj0gODsgYnVmZmVyW29mZnNldCArIGldID0gbSAmIDB4ZmYsIGkgKz0gZCwgbSAvPSAyNTYsIG1MZW4gLT0gOCkge31cblxuICBlID0gKGUgPDwgbUxlbikgfCBtXG4gIGVMZW4gKz0gbUxlblxuICBmb3IgKDsgZUxlbiA+IDA7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IGUgJiAweGZmLCBpICs9IGQsIGUgLz0gMjU2LCBlTGVuIC09IDgpIHt9XG5cbiAgYnVmZmVyW29mZnNldCArIGkgLSBkXSB8PSBzICogMTI4XG59XG5cbn0se31dLDQxMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG4vL0hpZ2ggbGV2ZWwgaWRlYTpcbi8vIDEuIFVzZSBDbGFya3NvbidzIGluY3JlbWVudGFsIGNvbnN0cnVjdGlvbiB0byBmaW5kIGNvbnZleCBodWxsXG4vLyAyLiBQb2ludCBsb2NhdGlvbiBpbiB0cmlhbmd1bGF0aW9uIGJ5IGp1bXAgYW5kIHdhbGtcblxubW9kdWxlLmV4cG9ydHMgPSBpbmNyZW1lbnRhbENvbnZleEh1bGxcblxudmFyIG9yaWVudCA9IF9kZXJlcV8oXCJyb2J1c3Qtb3JpZW50YXRpb25cIilcbnZhciBjb21wYXJlQ2VsbCA9IF9kZXJlcV8oXCJzaW1wbGljaWFsLWNvbXBsZXhcIikuY29tcGFyZUNlbGxzXG5cbmZ1bmN0aW9uIGNvbXBhcmVJbnQoYSwgYikge1xuICByZXR1cm4gYSAtIGJcbn1cblxuZnVuY3Rpb24gU2ltcGxleCh2ZXJ0aWNlcywgYWRqYWNlbnQsIGJvdW5kYXJ5KSB7XG4gIHRoaXMudmVydGljZXMgPSB2ZXJ0aWNlc1xuICB0aGlzLmFkamFjZW50ID0gYWRqYWNlbnRcbiAgdGhpcy5ib3VuZGFyeSA9IGJvdW5kYXJ5XG4gIHRoaXMubGFzdFZpc2l0ZWQgPSAtMVxufVxuXG5TaW1wbGV4LnByb3RvdHlwZS5mbGlwID0gZnVuY3Rpb24oKSB7XG4gIHZhciB0ID0gdGhpcy52ZXJ0aWNlc1swXVxuICB0aGlzLnZlcnRpY2VzWzBdID0gdGhpcy52ZXJ0aWNlc1sxXVxuICB0aGlzLnZlcnRpY2VzWzFdID0gdFxuICB2YXIgdSA9IHRoaXMuYWRqYWNlbnRbMF1cbiAgdGhpcy5hZGphY2VudFswXSA9IHRoaXMuYWRqYWNlbnRbMV1cbiAgdGhpcy5hZGphY2VudFsxXSA9IHVcbn1cblxuZnVuY3Rpb24gR2x1ZUZhY2V0KHZlcnRpY2VzLCBjZWxsLCBpbmRleCkge1xuICB0aGlzLnZlcnRpY2VzID0gdmVydGljZXNcbiAgdGhpcy5jZWxsID0gY2VsbFxuICB0aGlzLmluZGV4ID0gaW5kZXhcbn1cblxuZnVuY3Rpb24gY29tcGFyZUdsdWUoYSwgYikge1xuICByZXR1cm4gY29tcGFyZUNlbGwoYS52ZXJ0aWNlcywgYi52ZXJ0aWNlcylcbn1cblxuZnVuY3Rpb24gYmFrZU9yaWVudChkKSB7XG4gIHZhciBjb2RlID0gW1wiZnVuY3Rpb24gb3JpZW50KCl7dmFyIHR1cGxlPXRoaXMudHVwbGU7cmV0dXJuIHRlc3QoXCJdXG4gIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICBpZihpID4gMCkge1xuICAgICAgY29kZS5wdXNoKFwiLFwiKVxuICAgIH1cbiAgICBjb2RlLnB1c2goXCJ0dXBsZVtcIiwgaSwgXCJdXCIpXG4gIH1cbiAgY29kZS5wdXNoKFwiKX1yZXR1cm4gb3JpZW50XCIpXG4gIHZhciBwcm9jID0gbmV3IEZ1bmN0aW9uKFwidGVzdFwiLCBjb2RlLmpvaW4oXCJcIikpXG4gIHZhciB0ZXN0ID0gb3JpZW50W2QrMV1cbiAgaWYoIXRlc3QpIHtcbiAgICB0ZXN0ID0gb3JpZW50XG4gIH1cbiAgcmV0dXJuIHByb2ModGVzdClcbn1cblxudmFyIEJBS0VEID0gW11cblxuZnVuY3Rpb24gVHJpYW5ndWxhdGlvbihkaW1lbnNpb24sIHZlcnRpY2VzLCBzaW1wbGljZXMpIHtcbiAgdGhpcy5kaW1lbnNpb24gPSBkaW1lbnNpb25cbiAgdGhpcy52ZXJ0aWNlcyA9IHZlcnRpY2VzXG4gIHRoaXMuc2ltcGxpY2VzID0gc2ltcGxpY2VzXG4gIHRoaXMuaW50ZXJpb3IgPSBzaW1wbGljZXMuZmlsdGVyKGZ1bmN0aW9uKGMpIHtcbiAgICByZXR1cm4gIWMuYm91bmRhcnlcbiAgfSlcblxuICB0aGlzLnR1cGxlID0gbmV3IEFycmF5KGRpbWVuc2lvbisxKVxuICBmb3IodmFyIGk9MDsgaTw9ZGltZW5zaW9uOyArK2kpIHtcbiAgICB0aGlzLnR1cGxlW2ldID0gdGhpcy52ZXJ0aWNlc1tpXVxuICB9XG5cbiAgdmFyIG8gPSBCQUtFRFtkaW1lbnNpb25dXG4gIGlmKCFvKSB7XG4gICAgbyA9IEJBS0VEW2RpbWVuc2lvbl0gPSBiYWtlT3JpZW50KGRpbWVuc2lvbilcbiAgfVxuICB0aGlzLm9yaWVudCA9IG9cbn1cblxudmFyIHByb3RvID0gVHJpYW5ndWxhdGlvbi5wcm90b3R5cGVcblxuLy9EZWdlbmVyYXRlIHNpdHVhdGlvbiB3aGVyZSB3ZSBhcmUgb24gYm91bmRhcnksIGJ1dCBjb3BsYW5hciB0byBmYWNlXG5wcm90by5oYW5kbGVCb3VuZGFyeURlZ2VuZXJhY3kgPSBmdW5jdGlvbihjZWxsLCBwb2ludCkge1xuICB2YXIgZCA9IHRoaXMuZGltZW5zaW9uXG4gIHZhciBuID0gdGhpcy52ZXJ0aWNlcy5sZW5ndGggLSAxXG4gIHZhciB0dXBsZSA9IHRoaXMudHVwbGVcbiAgdmFyIHZlcnRzID0gdGhpcy52ZXJ0aWNlc1xuXG4gIC8vRHVtYiBzb2x1dGlvbjogSnVzdCBkbyBkZnMgZnJvbSBib3VuZGFyeSBjZWxsIHVudGlsIHdlIGZpbmQgYW55IHBlYWssIG9yIHRlcm1pbmF0ZVxuICB2YXIgdG9WaXNpdCA9IFsgY2VsbCBdXG4gIGNlbGwubGFzdFZpc2l0ZWQgPSAtblxuICB3aGlsZSh0b1Zpc2l0Lmxlbmd0aCA+IDApIHtcbiAgICBjZWxsID0gdG9WaXNpdC5wb3AoKVxuICAgIHZhciBjZWxsVmVydHMgPSBjZWxsLnZlcnRpY2VzXG4gICAgdmFyIGNlbGxBZGogPSBjZWxsLmFkamFjZW50XG4gICAgZm9yKHZhciBpPTA7IGk8PWQ7ICsraSkge1xuICAgICAgdmFyIG5laWdoYm9yID0gY2VsbEFkaltpXVxuICAgICAgaWYoIW5laWdoYm9yLmJvdW5kYXJ5IHx8IG5laWdoYm9yLmxhc3RWaXNpdGVkIDw9IC1uKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICB2YXIgbnYgPSBuZWlnaGJvci52ZXJ0aWNlc1xuICAgICAgZm9yKHZhciBqPTA7IGo8PWQ7ICsraikge1xuICAgICAgICB2YXIgdnYgPSBudltqXVxuICAgICAgICBpZih2diA8IDApIHtcbiAgICAgICAgICB0dXBsZVtqXSA9IHBvaW50XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHVwbGVbal0gPSB2ZXJ0c1t2dl1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFyIG8gPSB0aGlzLm9yaWVudCgpXG4gICAgICBpZihvID4gMCkge1xuICAgICAgICByZXR1cm4gbmVpZ2hib3JcbiAgICAgIH1cbiAgICAgIG5laWdoYm9yLmxhc3RWaXNpdGVkID0gLW5cbiAgICAgIGlmKG8gPT09IDApIHtcbiAgICAgICAgdG9WaXNpdC5wdXNoKG5laWdoYm9yKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gbnVsbFxufVxuXG5wcm90by53YWxrID0gZnVuY3Rpb24ocG9pbnQsIHJhbmRvbSkge1xuICAvL0FsaWFzIGxvY2FsIHByb3BlcnRpZXNcbiAgdmFyIG4gPSB0aGlzLnZlcnRpY2VzLmxlbmd0aCAtIDFcbiAgdmFyIGQgPSB0aGlzLmRpbWVuc2lvblxuICB2YXIgdmVydHMgPSB0aGlzLnZlcnRpY2VzXG4gIHZhciB0dXBsZSA9IHRoaXMudHVwbGVcblxuICAvL0NvbXB1dGUgaW5pdGlhbCBqdW1wIGNlbGxcbiAgdmFyIGluaXRJbmRleCA9IHJhbmRvbSA/ICh0aGlzLmludGVyaW9yLmxlbmd0aCAqIE1hdGgucmFuZG9tKCkpfDAgOiAodGhpcy5pbnRlcmlvci5sZW5ndGgtMSlcbiAgdmFyIGNlbGwgPSB0aGlzLmludGVyaW9yWyBpbml0SW5kZXggXVxuXG4gIC8vU3RhcnQgd2Fsa2luZ1xub3V0ZXJMb29wOlxuICB3aGlsZSghY2VsbC5ib3VuZGFyeSkge1xuICAgIHZhciBjZWxsVmVydHMgPSBjZWxsLnZlcnRpY2VzXG4gICAgdmFyIGNlbGxBZGogPSBjZWxsLmFkamFjZW50XG5cbiAgICBmb3IodmFyIGk9MDsgaTw9ZDsgKytpKSB7XG4gICAgICB0dXBsZVtpXSA9IHZlcnRzW2NlbGxWZXJ0c1tpXV1cbiAgICB9XG4gICAgY2VsbC5sYXN0VmlzaXRlZCA9IG5cblxuICAgIC8vRmluZCBmYXJ0aGVzdCBhZGphY2VudCBjZWxsXG4gICAgZm9yKHZhciBpPTA7IGk8PWQ7ICsraSkge1xuICAgICAgdmFyIG5laWdoYm9yID0gY2VsbEFkaltpXVxuICAgICAgaWYobmVpZ2hib3IubGFzdFZpc2l0ZWQgPj0gbikge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgdmFyIHByZXYgPSB0dXBsZVtpXVxuICAgICAgdHVwbGVbaV0gPSBwb2ludFxuICAgICAgdmFyIG8gPSB0aGlzLm9yaWVudCgpXG4gICAgICB0dXBsZVtpXSA9IHByZXZcbiAgICAgIGlmKG8gPCAwKSB7XG4gICAgICAgIGNlbGwgPSBuZWlnaGJvclxuICAgICAgICBjb250aW51ZSBvdXRlckxvb3BcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKCFuZWlnaGJvci5ib3VuZGFyeSkge1xuICAgICAgICAgIG5laWdoYm9yLmxhc3RWaXNpdGVkID0gblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5laWdoYm9yLmxhc3RWaXNpdGVkID0gLW5cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm5cbiAgfVxuXG4gIHJldHVybiBjZWxsXG59XG5cbnByb3RvLmFkZFBlYWtzID0gZnVuY3Rpb24ocG9pbnQsIGNlbGwpIHtcbiAgdmFyIG4gPSB0aGlzLnZlcnRpY2VzLmxlbmd0aCAtIDFcbiAgdmFyIGQgPSB0aGlzLmRpbWVuc2lvblxuICB2YXIgdmVydHMgPSB0aGlzLnZlcnRpY2VzXG4gIHZhciB0dXBsZSA9IHRoaXMudHVwbGVcbiAgdmFyIGludGVyaW9yID0gdGhpcy5pbnRlcmlvclxuICB2YXIgc2ltcGxpY2VzID0gdGhpcy5zaW1wbGljZXNcblxuICAvL1dhbGtpbmcgZmluaXNoZWQgYXQgYm91bmRhcnksIHRpbWUgdG8gYWRkIHBlYWtzXG4gIHZhciB0b3Zpc2l0ID0gWyBjZWxsIF1cblxuICAvL1N0cmV0Y2ggaW5pdGlhbCBib3VuZGFyeSBjZWxsIGludG8gYSBwZWFrXG4gIGNlbGwubGFzdFZpc2l0ZWQgPSBuXG4gIGNlbGwudmVydGljZXNbY2VsbC52ZXJ0aWNlcy5pbmRleE9mKC0xKV0gPSBuXG4gIGNlbGwuYm91bmRhcnkgPSBmYWxzZVxuICBpbnRlcmlvci5wdXNoKGNlbGwpXG5cbiAgLy9SZWNvcmQgYSBsaXN0IG9mIGFsbCBuZXcgYm91bmRhcmllcyBjcmVhdGVkIGJ5IGFkZGVkIHBlYWtzIHNvIHdlIGNhbiBnbHVlIHRoZW0gdG9nZXRoZXIgd2hlbiB3ZSBhcmUgYWxsIGRvbmVcbiAgdmFyIGdsdWVGYWNldHMgPSBbXVxuXG4gIC8vRG8gYSB0cmF2ZXJzYWwgb2YgdGhlIGJvdW5kYXJ5IHdhbGtpbmcgb3V0d2FyZCBmcm9tIHN0YXJ0aW5nIHBlYWtcbiAgd2hpbGUodG92aXNpdC5sZW5ndGggPiAwKSB7XG4gICAgLy9Qb3Agb2ZmIHBlYWsgYW5kIHdhbGsgb3ZlciBhZGphY2VudCBjZWxsc1xuICAgIHZhciBjZWxsID0gdG92aXNpdC5wb3AoKVxuICAgIHZhciBjZWxsVmVydHMgPSBjZWxsLnZlcnRpY2VzXG4gICAgdmFyIGNlbGxBZGogPSBjZWxsLmFkamFjZW50XG4gICAgdmFyIGluZGV4T2ZOID0gY2VsbFZlcnRzLmluZGV4T2YobilcbiAgICBpZihpbmRleE9mTiA8IDApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgZm9yKHZhciBpPTA7IGk8PWQ7ICsraSkge1xuICAgICAgaWYoaSA9PT0gaW5kZXhPZk4pIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy9Gb3IgZWFjaCBib3VuZGFyeSBuZWlnaGJvciBvZiB0aGUgY2VsbFxuICAgICAgdmFyIG5laWdoYm9yID0gY2VsbEFkaltpXVxuICAgICAgaWYoIW5laWdoYm9yLmJvdW5kYXJ5IHx8IG5laWdoYm9yLmxhc3RWaXNpdGVkID49IG4pIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgdmFyIG52ID0gbmVpZ2hib3IudmVydGljZXNcblxuICAgICAgLy9UZXN0IGlmIG5laWdoYm9yIGlzIGEgcGVha1xuICAgICAgaWYobmVpZ2hib3IubGFzdFZpc2l0ZWQgIT09IC1uKSB7ICAgICAgXG4gICAgICAgIC8vQ29tcHV0ZSBvcmllbnRhdGlvbiBvZiBwIHJlbGF0aXZlIHRvIGVhY2ggYm91bmRhcnkgcGVha1xuICAgICAgICB2YXIgaW5kZXhPZk5lZzEgPSAwXG4gICAgICAgIGZvcih2YXIgaj0wOyBqPD1kOyArK2opIHtcbiAgICAgICAgICBpZihudltqXSA8IDApIHtcbiAgICAgICAgICAgIGluZGV4T2ZOZWcxID0galxuICAgICAgICAgICAgdHVwbGVbal0gPSBwb2ludFxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0dXBsZVtqXSA9IHZlcnRzW252W2pdXVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgbyA9IHRoaXMub3JpZW50KClcblxuICAgICAgICAvL1Rlc3QgaWYgbmVpZ2hib3IgY2VsbCBpcyBhbHNvIGEgcGVha1xuICAgICAgICBpZihvID4gMCkge1xuICAgICAgICAgIG52W2luZGV4T2ZOZWcxXSA9IG5cbiAgICAgICAgICBuZWlnaGJvci5ib3VuZGFyeSA9IGZhbHNlXG4gICAgICAgICAgaW50ZXJpb3IucHVzaChuZWlnaGJvcilcbiAgICAgICAgICB0b3Zpc2l0LnB1c2gobmVpZ2hib3IpXG4gICAgICAgICAgbmVpZ2hib3IubGFzdFZpc2l0ZWQgPSBuXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZWlnaGJvci5sYXN0VmlzaXRlZCA9IC1uXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIG5hID0gbmVpZ2hib3IuYWRqYWNlbnRcblxuICAgICAgLy9PdGhlcndpc2UsIHJlcGxhY2UgbmVpZ2hib3Igd2l0aCBuZXcgZmFjZVxuICAgICAgdmFyIHZ2ZXJ0cyA9IGNlbGxWZXJ0cy5zbGljZSgpXG4gICAgICB2YXIgdmFkaiA9IGNlbGxBZGouc2xpY2UoKVxuICAgICAgdmFyIG5jZWxsID0gbmV3IFNpbXBsZXgodnZlcnRzLCB2YWRqLCB0cnVlKVxuICAgICAgc2ltcGxpY2VzLnB1c2gobmNlbGwpXG5cbiAgICAgIC8vQ29ubmVjdCB0byBuZWlnaGJvclxuICAgICAgdmFyIG9wcG9zaXRlID0gbmEuaW5kZXhPZihjZWxsKVxuICAgICAgaWYob3Bwb3NpdGUgPCAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBuYVtvcHBvc2l0ZV0gPSBuY2VsbFxuICAgICAgdmFkaltpbmRleE9mTl0gPSBuZWlnaGJvclxuXG4gICAgICAvL0Nvbm5lY3QgdG8gY2VsbFxuICAgICAgdnZlcnRzW2ldID0gLTFcbiAgICAgIHZhZGpbaV0gPSBjZWxsXG4gICAgICBjZWxsQWRqW2ldID0gbmNlbGxcblxuICAgICAgLy9GbGlwIGZhY2V0XG4gICAgICBuY2VsbC5mbGlwKClcblxuICAgICAgLy9BZGQgdG8gZ2x1ZSBsaXN0XG4gICAgICBmb3IodmFyIGo9MDsgajw9ZDsgKytqKSB7XG4gICAgICAgIHZhciB1dSA9IHZ2ZXJ0c1tqXVxuICAgICAgICBpZih1dSA8IDAgfHwgdXUgPT09IG4pIHtcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICAgIHZhciBuZmFjZSA9IG5ldyBBcnJheShkLTEpXG4gICAgICAgIHZhciBucHRyID0gMFxuICAgICAgICBmb3IodmFyIGs9MDsgazw9ZDsgKytrKSB7XG4gICAgICAgICAgdmFyIHZ2ID0gdnZlcnRzW2tdXG4gICAgICAgICAgaWYodnYgPCAwIHx8IGsgPT09IGopIHtcbiAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgfVxuICAgICAgICAgIG5mYWNlW25wdHIrK10gPSB2dlxuICAgICAgICB9XG4gICAgICAgIGdsdWVGYWNldHMucHVzaChuZXcgR2x1ZUZhY2V0KG5mYWNlLCBuY2VsbCwgaikpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9HbHVlIGJvdW5kYXJ5IGZhY2V0cyB0b2dldGhlclxuICBnbHVlRmFjZXRzLnNvcnQoY29tcGFyZUdsdWUpXG5cbiAgZm9yKHZhciBpPTA7IGkrMTxnbHVlRmFjZXRzLmxlbmd0aDsgaSs9Mikge1xuICAgIHZhciBhID0gZ2x1ZUZhY2V0c1tpXVxuICAgIHZhciBiID0gZ2x1ZUZhY2V0c1tpKzFdXG4gICAgdmFyIGFpID0gYS5pbmRleFxuICAgIHZhciBiaSA9IGIuaW5kZXhcbiAgICBpZihhaSA8IDAgfHwgYmkgPCAwKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBhLmNlbGwuYWRqYWNlbnRbYS5pbmRleF0gPSBiLmNlbGxcbiAgICBiLmNlbGwuYWRqYWNlbnRbYi5pbmRleF0gPSBhLmNlbGxcbiAgfVxufVxuXG5wcm90by5pbnNlcnQgPSBmdW5jdGlvbihwb2ludCwgcmFuZG9tKSB7XG4gIC8vQWRkIHBvaW50XG4gIHZhciB2ZXJ0cyA9IHRoaXMudmVydGljZXNcbiAgdmVydHMucHVzaChwb2ludClcblxuICB2YXIgY2VsbCA9IHRoaXMud2Fsayhwb2ludCwgcmFuZG9tKVxuICBpZighY2VsbCkge1xuICAgIHJldHVyblxuICB9XG5cbiAgLy9BbGlhcyBsb2NhbCBwcm9wZXJ0aWVzXG4gIHZhciBkID0gdGhpcy5kaW1lbnNpb25cbiAgdmFyIHR1cGxlID0gdGhpcy50dXBsZVxuXG4gIC8vRGVnZW5lcmF0ZSBjYXNlOiBJZiBwb2ludCBpcyBjb3BsYW5hciB0byBjZWxsLCB0aGVuIHdhbGsgdW50aWwgd2UgZmluZCBhIG5vbi1kZWdlbmVyYXRlIGJvdW5kYXJ5XG4gIGZvcih2YXIgaT0wOyBpPD1kOyArK2kpIHtcbiAgICB2YXIgdnYgPSBjZWxsLnZlcnRpY2VzW2ldXG4gICAgaWYodnYgPCAwKSB7XG4gICAgICB0dXBsZVtpXSA9IHBvaW50XG4gICAgfSBlbHNlIHtcbiAgICAgIHR1cGxlW2ldID0gdmVydHNbdnZdXG4gICAgfVxuICB9XG4gIHZhciBvID0gdGhpcy5vcmllbnQodHVwbGUpXG4gIGlmKG8gPCAwKSB7XG4gICAgcmV0dXJuXG4gIH0gZWxzZSBpZihvID09PSAwKSB7XG4gICAgY2VsbCA9IHRoaXMuaGFuZGxlQm91bmRhcnlEZWdlbmVyYWN5KGNlbGwsIHBvaW50KVxuICAgIGlmKCFjZWxsKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gIH1cblxuICAvL0FkZCBwZWFrc1xuICB0aGlzLmFkZFBlYWtzKHBvaW50LCBjZWxsKVxufVxuXG4vL0V4dHJhY3QgYWxsIGJvdW5kYXJ5IGNlbGxzXG5wcm90by5ib3VuZGFyeSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgZCA9IHRoaXMuZGltZW5zaW9uXG4gIHZhciBib3VuZGFyeSA9IFtdXG4gIHZhciBjZWxscyA9IHRoaXMuc2ltcGxpY2VzXG4gIHZhciBuYyA9IGNlbGxzLmxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxuYzsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGlmKGMuYm91bmRhcnkpIHtcbiAgICAgIHZhciBiY2VsbCA9IG5ldyBBcnJheShkKVxuICAgICAgdmFyIGN2ID0gYy52ZXJ0aWNlc1xuICAgICAgdmFyIHB0ciA9IDBcbiAgICAgIHZhciBwYXJpdHkgPSAwXG4gICAgICBmb3IodmFyIGo9MDsgajw9ZDsgKytqKSB7XG4gICAgICAgIGlmKGN2W2pdID49IDApIHtcbiAgICAgICAgICBiY2VsbFtwdHIrK10gPSBjdltqXVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBhcml0eSA9IGomMVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZihwYXJpdHkgPT09IChkJjEpKSB7XG4gICAgICAgIHZhciB0ID0gYmNlbGxbMF1cbiAgICAgICAgYmNlbGxbMF0gPSBiY2VsbFsxXVxuICAgICAgICBiY2VsbFsxXSA9IHRcbiAgICAgIH1cbiAgICAgIGJvdW5kYXJ5LnB1c2goYmNlbGwpXG4gICAgfVxuICB9XG4gIHJldHVybiBib3VuZGFyeVxufVxuXG5mdW5jdGlvbiBpbmNyZW1lbnRhbENvbnZleEh1bGwocG9pbnRzLCByYW5kb21TZWFyY2gpIHtcbiAgdmFyIG4gPSBwb2ludHMubGVuZ3RoXG4gIGlmKG4gPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJNdXN0IGhhdmUgYXQgbGVhc3QgZCsxIHBvaW50c1wiKVxuICB9XG4gIHZhciBkID0gcG9pbnRzWzBdLmxlbmd0aFxuICBpZihuIDw9IGQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJNdXN0IGlucHV0IGF0IGxlYXN0IGQrMSBwb2ludHNcIilcbiAgfVxuXG4gIC8vRklYTUU6IFRoaXMgY291bGQgYmUgZGVnZW5lcmF0ZSwgYnV0IG5lZWQgdG8gc2VsZWN0IGQrMSBub24tY29wbGFuYXIgcG9pbnRzIHRvIGJvb3RzdHJhcCBwcm9jZXNzXG4gIHZhciBpbml0aWFsU2ltcGxleCA9IHBvaW50cy5zbGljZSgwLCBkKzEpXG5cbiAgLy9NYWtlIHN1cmUgaW5pdGlhbCBzaW1wbGV4IGlzIHBvc2l0aXZlbHkgb3JpZW50ZWRcbiAgdmFyIG8gPSBvcmllbnQuYXBwbHkodm9pZCAwLCBpbml0aWFsU2ltcGxleClcbiAgaWYobyA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIklucHV0IG5vdCBpbiBnZW5lcmFsIHBvc2l0aW9uXCIpXG4gIH1cbiAgdmFyIGluaXRpYWxDb29yZHMgPSBuZXcgQXJyYXkoZCsxKVxuICBmb3IodmFyIGk9MDsgaTw9ZDsgKytpKSB7XG4gICAgaW5pdGlhbENvb3Jkc1tpXSA9IGlcbiAgfVxuICBpZihvIDwgMCkge1xuICAgIGluaXRpYWxDb29yZHNbMF0gPSAxXG4gICAgaW5pdGlhbENvb3Jkc1sxXSA9IDBcbiAgfVxuXG4gIC8vQ3JlYXRlIGluaXRpYWwgdG9wb2xvZ2ljYWwgaW5kZXgsIGdsdWUgcG9pbnRlcnMgdG9nZXRoZXIgKGtpbmQgb2YgbWVzc3kpXG4gIHZhciBpbml0aWFsQ2VsbCA9IG5ldyBTaW1wbGV4KGluaXRpYWxDb29yZHMsIG5ldyBBcnJheShkKzEpLCBmYWxzZSlcbiAgdmFyIGJvdW5kYXJ5ID0gaW5pdGlhbENlbGwuYWRqYWNlbnRcbiAgdmFyIGxpc3QgPSBuZXcgQXJyYXkoZCsyKVxuICBmb3IodmFyIGk9MDsgaTw9ZDsgKytpKSB7XG4gICAgdmFyIHZlcnRzID0gaW5pdGlhbENvb3Jkcy5zbGljZSgpXG4gICAgZm9yKHZhciBqPTA7IGo8PWQ7ICsraikge1xuICAgICAgaWYoaiA9PT0gaSkge1xuICAgICAgICB2ZXJ0c1tqXSA9IC0xXG4gICAgICB9XG4gICAgfVxuICAgIHZhciB0ID0gdmVydHNbMF1cbiAgICB2ZXJ0c1swXSA9IHZlcnRzWzFdXG4gICAgdmVydHNbMV0gPSB0XG4gICAgdmFyIGNlbGwgPSBuZXcgU2ltcGxleCh2ZXJ0cywgbmV3IEFycmF5KGQrMSksIHRydWUpXG4gICAgYm91bmRhcnlbaV0gPSBjZWxsXG4gICAgbGlzdFtpXSA9IGNlbGxcbiAgfVxuICBsaXN0W2QrMV0gPSBpbml0aWFsQ2VsbFxuICBmb3IodmFyIGk9MDsgaTw9ZDsgKytpKSB7XG4gICAgdmFyIHZlcnRzID0gYm91bmRhcnlbaV0udmVydGljZXNcbiAgICB2YXIgYWRqID0gYm91bmRhcnlbaV0uYWRqYWNlbnRcbiAgICBmb3IodmFyIGo9MDsgajw9ZDsgKytqKSB7XG4gICAgICB2YXIgdiA9IHZlcnRzW2pdXG4gICAgICBpZih2IDwgMCkge1xuICAgICAgICBhZGpbal0gPSBpbml0aWFsQ2VsbFxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgZm9yKHZhciBrPTA7IGs8PWQ7ICsraykge1xuICAgICAgICBpZihib3VuZGFyeVtrXS52ZXJ0aWNlcy5pbmRleE9mKHYpIDwgMCkge1xuICAgICAgICAgIGFkaltqXSA9IGJvdW5kYXJ5W2tdXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvL0luaXRpYWxpemUgdHJpYW5nbGVzXG4gIHZhciB0cmlhbmdsZXMgPSBuZXcgVHJpYW5ndWxhdGlvbihkLCBpbml0aWFsU2ltcGxleCwgbGlzdClcblxuICAvL0luc2VydCByZW1haW5pbmcgcG9pbnRzXG4gIHZhciB1c2VSYW5kb20gPSAhIXJhbmRvbVNlYXJjaFxuICBmb3IodmFyIGk9ZCsxOyBpPG47ICsraSkge1xuICAgIHRyaWFuZ2xlcy5pbnNlcnQocG9pbnRzW2ldLCB1c2VSYW5kb20pXG4gIH1cbiAgXG4gIC8vRXh0cmFjdCBib3VuZGFyeSBjZWxsc1xuICByZXR1cm4gdHJpYW5nbGVzLmJvdW5kYXJ5KClcbn1cbn0se1wicm9idXN0LW9yaWVudGF0aW9uXCI6NTEwLFwic2ltcGxpY2lhbC1jb21wbGV4XCI6NTIwfV0sNDE0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciBib3VuZHMgPSBfZGVyZXFfKFwiYmluYXJ5LXNlYXJjaC1ib3VuZHNcIilcblxudmFyIE5PVF9GT1VORCA9IDBcbnZhciBTVUNDRVNTID0gMVxudmFyIEVNUFRZID0gMlxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVdyYXBwZXJcblxuZnVuY3Rpb24gSW50ZXJ2YWxUcmVlTm9kZShtaWQsIGxlZnQsIHJpZ2h0LCBsZWZ0UG9pbnRzLCByaWdodFBvaW50cykge1xuICB0aGlzLm1pZCA9IG1pZFxuICB0aGlzLmxlZnQgPSBsZWZ0XG4gIHRoaXMucmlnaHQgPSByaWdodFxuICB0aGlzLmxlZnRQb2ludHMgPSBsZWZ0UG9pbnRzXG4gIHRoaXMucmlnaHRQb2ludHMgPSByaWdodFBvaW50c1xuICB0aGlzLmNvdW50ID0gKGxlZnQgPyBsZWZ0LmNvdW50IDogMCkgKyAocmlnaHQgPyByaWdodC5jb3VudCA6IDApICsgbGVmdFBvaW50cy5sZW5ndGhcbn1cblxudmFyIHByb3RvID0gSW50ZXJ2YWxUcmVlTm9kZS5wcm90b3R5cGVcblxuZnVuY3Rpb24gY29weShhLCBiKSB7XG4gIGEubWlkID0gYi5taWRcbiAgYS5sZWZ0ID0gYi5sZWZ0XG4gIGEucmlnaHQgPSBiLnJpZ2h0XG4gIGEubGVmdFBvaW50cyA9IGIubGVmdFBvaW50c1xuICBhLnJpZ2h0UG9pbnRzID0gYi5yaWdodFBvaW50c1xuICBhLmNvdW50ID0gYi5jb3VudFxufVxuXG5mdW5jdGlvbiByZWJ1aWxkKG5vZGUsIGludGVydmFscykge1xuICB2YXIgbnRyZWUgPSBjcmVhdGVJbnRlcnZhbFRyZWUoaW50ZXJ2YWxzKVxuICBub2RlLm1pZCA9IG50cmVlLm1pZFxuICBub2RlLmxlZnQgPSBudHJlZS5sZWZ0XG4gIG5vZGUucmlnaHQgPSBudHJlZS5yaWdodFxuICBub2RlLmxlZnRQb2ludHMgPSBudHJlZS5sZWZ0UG9pbnRzXG4gIG5vZGUucmlnaHRQb2ludHMgPSBudHJlZS5yaWdodFBvaW50c1xuICBub2RlLmNvdW50ID0gbnRyZWUuY291bnRcbn1cblxuZnVuY3Rpb24gcmVidWlsZFdpdGhJbnRlcnZhbChub2RlLCBpbnRlcnZhbCkge1xuICB2YXIgaW50ZXJ2YWxzID0gbm9kZS5pbnRlcnZhbHMoW10pXG4gIGludGVydmFscy5wdXNoKGludGVydmFsKVxuICByZWJ1aWxkKG5vZGUsIGludGVydmFscykgICAgXG59XG5cbmZ1bmN0aW9uIHJlYnVpbGRXaXRob3V0SW50ZXJ2YWwobm9kZSwgaW50ZXJ2YWwpIHtcbiAgdmFyIGludGVydmFscyA9IG5vZGUuaW50ZXJ2YWxzKFtdKVxuICB2YXIgaWR4ID0gaW50ZXJ2YWxzLmluZGV4T2YoaW50ZXJ2YWwpXG4gIGlmKGlkeCA8IDApIHtcbiAgICByZXR1cm4gTk9UX0ZPVU5EXG4gIH1cbiAgaW50ZXJ2YWxzLnNwbGljZShpZHgsIDEpXG4gIHJlYnVpbGQobm9kZSwgaW50ZXJ2YWxzKVxuICByZXR1cm4gU1VDQ0VTU1xufVxuXG5wcm90by5pbnRlcnZhbHMgPSBmdW5jdGlvbihyZXN1bHQpIHtcbiAgcmVzdWx0LnB1c2guYXBwbHkocmVzdWx0LCB0aGlzLmxlZnRQb2ludHMpXG4gIGlmKHRoaXMubGVmdCkge1xuICAgIHRoaXMubGVmdC5pbnRlcnZhbHMocmVzdWx0KVxuICB9XG4gIGlmKHRoaXMucmlnaHQpIHtcbiAgICB0aGlzLnJpZ2h0LmludGVydmFscyhyZXN1bHQpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5wcm90by5pbnNlcnQgPSBmdW5jdGlvbihpbnRlcnZhbCkge1xuICB2YXIgd2VpZ2h0ID0gdGhpcy5jb3VudCAtIHRoaXMubGVmdFBvaW50cy5sZW5ndGhcbiAgdGhpcy5jb3VudCArPSAxXG4gIGlmKGludGVydmFsWzFdIDwgdGhpcy5taWQpIHtcbiAgICBpZih0aGlzLmxlZnQpIHtcbiAgICAgIGlmKDQqKHRoaXMubGVmdC5jb3VudCsxKSA+IDMqKHdlaWdodCsxKSkge1xuICAgICAgICByZWJ1aWxkV2l0aEludGVydmFsKHRoaXMsIGludGVydmFsKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5sZWZ0Lmluc2VydChpbnRlcnZhbClcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5sZWZ0ID0gY3JlYXRlSW50ZXJ2YWxUcmVlKFtpbnRlcnZhbF0pXG4gICAgfVxuICB9IGVsc2UgaWYoaW50ZXJ2YWxbMF0gPiB0aGlzLm1pZCkge1xuICAgIGlmKHRoaXMucmlnaHQpIHtcbiAgICAgIGlmKDQqKHRoaXMucmlnaHQuY291bnQrMSkgPiAzKih3ZWlnaHQrMSkpIHtcbiAgICAgICAgcmVidWlsZFdpdGhJbnRlcnZhbCh0aGlzLCBpbnRlcnZhbClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucmlnaHQuaW5zZXJ0KGludGVydmFsKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJpZ2h0ID0gY3JlYXRlSW50ZXJ2YWxUcmVlKFtpbnRlcnZhbF0pXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBsID0gYm91bmRzLmdlKHRoaXMubGVmdFBvaW50cywgaW50ZXJ2YWwsIGNvbXBhcmVCZWdpbilcbiAgICB2YXIgciA9IGJvdW5kcy5nZSh0aGlzLnJpZ2h0UG9pbnRzLCBpbnRlcnZhbCwgY29tcGFyZUVuZClcbiAgICB0aGlzLmxlZnRQb2ludHMuc3BsaWNlKGwsIDAsIGludGVydmFsKVxuICAgIHRoaXMucmlnaHRQb2ludHMuc3BsaWNlKHIsIDAsIGludGVydmFsKVxuICB9XG59XG5cbnByb3RvLnJlbW92ZSA9IGZ1bmN0aW9uKGludGVydmFsKSB7XG4gIHZhciB3ZWlnaHQgPSB0aGlzLmNvdW50IC0gdGhpcy5sZWZ0UG9pbnRzXG4gIGlmKGludGVydmFsWzFdIDwgdGhpcy5taWQpIHtcbiAgICBpZighdGhpcy5sZWZ0KSB7XG4gICAgICByZXR1cm4gTk9UX0ZPVU5EXG4gICAgfVxuICAgIHZhciBydyA9IHRoaXMucmlnaHQgPyB0aGlzLnJpZ2h0LmNvdW50IDogMFxuICAgIGlmKDQgKiBydyA+IDMgKiAod2VpZ2h0LTEpKSB7XG4gICAgICByZXR1cm4gcmVidWlsZFdpdGhvdXRJbnRlcnZhbCh0aGlzLCBpbnRlcnZhbClcbiAgICB9XG4gICAgdmFyIHIgPSB0aGlzLmxlZnQucmVtb3ZlKGludGVydmFsKVxuICAgIGlmKHIgPT09IEVNUFRZKSB7XG4gICAgICB0aGlzLmxlZnQgPSBudWxsXG4gICAgICB0aGlzLmNvdW50IC09IDFcbiAgICAgIHJldHVybiBTVUNDRVNTXG4gICAgfSBlbHNlIGlmKHIgPT09IFNVQ0NFU1MpIHtcbiAgICAgIHRoaXMuY291bnQgLT0gMVxuICAgIH1cbiAgICByZXR1cm4gclxuICB9IGVsc2UgaWYoaW50ZXJ2YWxbMF0gPiB0aGlzLm1pZCkge1xuICAgIGlmKCF0aGlzLnJpZ2h0KSB7XG4gICAgICByZXR1cm4gTk9UX0ZPVU5EXG4gICAgfVxuICAgIHZhciBsdyA9IHRoaXMubGVmdCA/IHRoaXMubGVmdC5jb3VudCA6IDBcbiAgICBpZig0ICogbHcgPiAzICogKHdlaWdodC0xKSkge1xuICAgICAgcmV0dXJuIHJlYnVpbGRXaXRob3V0SW50ZXJ2YWwodGhpcywgaW50ZXJ2YWwpXG4gICAgfVxuICAgIHZhciByID0gdGhpcy5yaWdodC5yZW1vdmUoaW50ZXJ2YWwpXG4gICAgaWYociA9PT0gRU1QVFkpIHtcbiAgICAgIHRoaXMucmlnaHQgPSBudWxsXG4gICAgICB0aGlzLmNvdW50IC09IDFcbiAgICAgIHJldHVybiBTVUNDRVNTXG4gICAgfSBlbHNlIGlmKHIgPT09IFNVQ0NFU1MpIHtcbiAgICAgIHRoaXMuY291bnQgLT0gMVxuICAgIH1cbiAgICByZXR1cm4gclxuICB9IGVsc2Uge1xuICAgIGlmKHRoaXMuY291bnQgPT09IDEpIHtcbiAgICAgIGlmKHRoaXMubGVmdFBvaW50c1swXSA9PT0gaW50ZXJ2YWwpIHtcbiAgICAgICAgcmV0dXJuIEVNUFRZXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gTk9UX0ZPVU5EXG4gICAgICB9XG4gICAgfVxuICAgIGlmKHRoaXMubGVmdFBvaW50cy5sZW5ndGggPT09IDEgJiYgdGhpcy5sZWZ0UG9pbnRzWzBdID09PSBpbnRlcnZhbCkge1xuICAgICAgaWYodGhpcy5sZWZ0ICYmIHRoaXMucmlnaHQpIHtcbiAgICAgICAgdmFyIHAgPSB0aGlzXG4gICAgICAgIHZhciBuID0gdGhpcy5sZWZ0XG4gICAgICAgIHdoaWxlKG4ucmlnaHQpIHtcbiAgICAgICAgICBwID0gblxuICAgICAgICAgIG4gPSBuLnJpZ2h0XG4gICAgICAgIH1cbiAgICAgICAgaWYocCA9PT0gdGhpcykge1xuICAgICAgICAgIG4ucmlnaHQgPSB0aGlzLnJpZ2h0XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIGwgPSB0aGlzLmxlZnRcbiAgICAgICAgICB2YXIgciA9IHRoaXMucmlnaHRcbiAgICAgICAgICBwLmNvdW50IC09IG4uY291bnRcbiAgICAgICAgICBwLnJpZ2h0ID0gbi5sZWZ0XG4gICAgICAgICAgbi5sZWZ0ID0gbFxuICAgICAgICAgIG4ucmlnaHQgPSByXG4gICAgICAgIH1cbiAgICAgICAgY29weSh0aGlzLCBuKVxuICAgICAgICB0aGlzLmNvdW50ID0gKHRoaXMubGVmdD90aGlzLmxlZnQuY291bnQ6MCkgKyAodGhpcy5yaWdodD90aGlzLnJpZ2h0LmNvdW50OjApICsgdGhpcy5sZWZ0UG9pbnRzLmxlbmd0aFxuICAgICAgfSBlbHNlIGlmKHRoaXMubGVmdCkge1xuICAgICAgICBjb3B5KHRoaXMsIHRoaXMubGVmdClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvcHkodGhpcywgdGhpcy5yaWdodClcbiAgICAgIH1cbiAgICAgIHJldHVybiBTVUNDRVNTXG4gICAgfVxuICAgIGZvcih2YXIgbCA9IGJvdW5kcy5nZSh0aGlzLmxlZnRQb2ludHMsIGludGVydmFsLCBjb21wYXJlQmVnaW4pOyBsPHRoaXMubGVmdFBvaW50cy5sZW5ndGg7ICsrbCkge1xuICAgICAgaWYodGhpcy5sZWZ0UG9pbnRzW2xdWzBdICE9PSBpbnRlcnZhbFswXSkge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgICAgaWYodGhpcy5sZWZ0UG9pbnRzW2xdID09PSBpbnRlcnZhbCkge1xuICAgICAgICB0aGlzLmNvdW50IC09IDFcbiAgICAgICAgdGhpcy5sZWZ0UG9pbnRzLnNwbGljZShsLCAxKVxuICAgICAgICBmb3IodmFyIHIgPSBib3VuZHMuZ2UodGhpcy5yaWdodFBvaW50cywgaW50ZXJ2YWwsIGNvbXBhcmVFbmQpOyByPHRoaXMucmlnaHRQb2ludHMubGVuZ3RoOyArK3IpIHtcbiAgICAgICAgICBpZih0aGlzLnJpZ2h0UG9pbnRzW3JdWzFdICE9PSBpbnRlcnZhbFsxXSkge1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9IGVsc2UgaWYodGhpcy5yaWdodFBvaW50c1tyXSA9PT0gaW50ZXJ2YWwpIHtcbiAgICAgICAgICAgIHRoaXMucmlnaHRQb2ludHMuc3BsaWNlKHIsIDEpXG4gICAgICAgICAgICByZXR1cm4gU1VDQ0VTU1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gTk9UX0ZPVU5EXG4gIH1cbn1cblxuZnVuY3Rpb24gcmVwb3J0TGVmdFJhbmdlKGFyciwgaGksIGNiKSB7XG4gIGZvcih2YXIgaT0wOyBpPGFyci5sZW5ndGggJiYgYXJyW2ldWzBdIDw9IGhpOyArK2kpIHtcbiAgICB2YXIgciA9IGNiKGFycltpXSlcbiAgICBpZihyKSB7IHJldHVybiByIH1cbiAgfVxufVxuXG5mdW5jdGlvbiByZXBvcnRSaWdodFJhbmdlKGFyciwgbG8sIGNiKSB7XG4gIGZvcih2YXIgaT1hcnIubGVuZ3RoLTE7IGk+PTAgJiYgYXJyW2ldWzFdID49IGxvOyAtLWkpIHtcbiAgICB2YXIgciA9IGNiKGFycltpXSlcbiAgICBpZihyKSB7IHJldHVybiByIH1cbiAgfVxufVxuXG5mdW5jdGlvbiByZXBvcnRSYW5nZShhcnIsIGNiKSB7XG4gIGZvcih2YXIgaT0wOyBpPGFyci5sZW5ndGg7ICsraSkge1xuICAgIHZhciByID0gY2IoYXJyW2ldKVxuICAgIGlmKHIpIHsgcmV0dXJuIHIgfVxuICB9XG59XG5cbnByb3RvLnF1ZXJ5UG9pbnQgPSBmdW5jdGlvbih4LCBjYikge1xuICBpZih4IDwgdGhpcy5taWQpIHtcbiAgICBpZih0aGlzLmxlZnQpIHtcbiAgICAgIHZhciByID0gdGhpcy5sZWZ0LnF1ZXJ5UG9pbnQoeCwgY2IpXG4gICAgICBpZihyKSB7IHJldHVybiByIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcG9ydExlZnRSYW5nZSh0aGlzLmxlZnRQb2ludHMsIHgsIGNiKVxuICB9IGVsc2UgaWYoeCA+IHRoaXMubWlkKSB7XG4gICAgaWYodGhpcy5yaWdodCkge1xuICAgICAgdmFyIHIgPSB0aGlzLnJpZ2h0LnF1ZXJ5UG9pbnQoeCwgY2IpXG4gICAgICBpZihyKSB7IHJldHVybiByIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcG9ydFJpZ2h0UmFuZ2UodGhpcy5yaWdodFBvaW50cywgeCwgY2IpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlcG9ydFJhbmdlKHRoaXMubGVmdFBvaW50cywgY2IpXG4gIH1cbn1cblxucHJvdG8ucXVlcnlJbnRlcnZhbCA9IGZ1bmN0aW9uKGxvLCBoaSwgY2IpIHtcbiAgaWYobG8gPCB0aGlzLm1pZCAmJiB0aGlzLmxlZnQpIHtcbiAgICB2YXIgciA9IHRoaXMubGVmdC5xdWVyeUludGVydmFsKGxvLCBoaSwgY2IpXG4gICAgaWYocikgeyByZXR1cm4gciB9XG4gIH1cbiAgaWYoaGkgPiB0aGlzLm1pZCAmJiB0aGlzLnJpZ2h0KSB7XG4gICAgdmFyIHIgPSB0aGlzLnJpZ2h0LnF1ZXJ5SW50ZXJ2YWwobG8sIGhpLCBjYilcbiAgICBpZihyKSB7IHJldHVybiByIH1cbiAgfVxuICBpZihoaSA8IHRoaXMubWlkKSB7XG4gICAgcmV0dXJuIHJlcG9ydExlZnRSYW5nZSh0aGlzLmxlZnRQb2ludHMsIGhpLCBjYilcbiAgfSBlbHNlIGlmKGxvID4gdGhpcy5taWQpIHtcbiAgICByZXR1cm4gcmVwb3J0UmlnaHRSYW5nZSh0aGlzLnJpZ2h0UG9pbnRzLCBsbywgY2IpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlcG9ydFJhbmdlKHRoaXMubGVmdFBvaW50cywgY2IpXG4gIH1cbn1cblxuZnVuY3Rpb24gY29tcGFyZU51bWJlcnMoYSwgYikge1xuICByZXR1cm4gYSAtIGJcbn1cblxuZnVuY3Rpb24gY29tcGFyZUJlZ2luKGEsIGIpIHtcbiAgdmFyIGQgPSBhWzBdIC0gYlswXVxuICBpZihkKSB7IHJldHVybiBkIH1cbiAgcmV0dXJuIGFbMV0gLSBiWzFdXG59XG5cbmZ1bmN0aW9uIGNvbXBhcmVFbmQoYSwgYikge1xuICB2YXIgZCA9IGFbMV0gLSBiWzFdXG4gIGlmKGQpIHsgcmV0dXJuIGQgfVxuICByZXR1cm4gYVswXSAtIGJbMF1cbn1cblxuZnVuY3Rpb24gY3JlYXRlSW50ZXJ2YWxUcmVlKGludGVydmFscykge1xuICBpZihpbnRlcnZhbHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICB2YXIgcHRzID0gW11cbiAgZm9yKHZhciBpPTA7IGk8aW50ZXJ2YWxzLmxlbmd0aDsgKytpKSB7XG4gICAgcHRzLnB1c2goaW50ZXJ2YWxzW2ldWzBdLCBpbnRlcnZhbHNbaV1bMV0pXG4gIH1cbiAgcHRzLnNvcnQoY29tcGFyZU51bWJlcnMpXG5cbiAgdmFyIG1pZCA9IHB0c1twdHMubGVuZ3RoPj4xXVxuXG4gIHZhciBsZWZ0SW50ZXJ2YWxzID0gW11cbiAgdmFyIHJpZ2h0SW50ZXJ2YWxzID0gW11cbiAgdmFyIGNlbnRlckludGVydmFscyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPGludGVydmFscy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBzID0gaW50ZXJ2YWxzW2ldXG4gICAgaWYoc1sxXSA8IG1pZCkge1xuICAgICAgbGVmdEludGVydmFscy5wdXNoKHMpXG4gICAgfSBlbHNlIGlmKG1pZCA8IHNbMF0pIHtcbiAgICAgIHJpZ2h0SW50ZXJ2YWxzLnB1c2gocylcbiAgICB9IGVsc2Uge1xuICAgICAgY2VudGVySW50ZXJ2YWxzLnB1c2gocylcbiAgICB9XG4gIH1cblxuICAvL1NwbGl0IGNlbnRlciBpbnRlcnZhbHNcbiAgdmFyIGxlZnRQb2ludHMgPSBjZW50ZXJJbnRlcnZhbHNcbiAgdmFyIHJpZ2h0UG9pbnRzID0gY2VudGVySW50ZXJ2YWxzLnNsaWNlKClcbiAgbGVmdFBvaW50cy5zb3J0KGNvbXBhcmVCZWdpbilcbiAgcmlnaHRQb2ludHMuc29ydChjb21wYXJlRW5kKVxuXG4gIHJldHVybiBuZXcgSW50ZXJ2YWxUcmVlTm9kZShtaWQsIFxuICAgIGNyZWF0ZUludGVydmFsVHJlZShsZWZ0SW50ZXJ2YWxzKSxcbiAgICBjcmVhdGVJbnRlcnZhbFRyZWUocmlnaHRJbnRlcnZhbHMpLFxuICAgIGxlZnRQb2ludHMsXG4gICAgcmlnaHRQb2ludHMpXG59XG5cbi8vVXNlciBmcmllbmRseSB3cmFwcGVyIHRoYXQgbWFrZXMgaXQgcG9zc2libGUgdG8gc3VwcG9ydCBlbXB0eSB0cmVlc1xuZnVuY3Rpb24gSW50ZXJ2YWxUcmVlKHJvb3QpIHtcbiAgdGhpcy5yb290ID0gcm9vdFxufVxuXG52YXIgdHByb3RvID0gSW50ZXJ2YWxUcmVlLnByb3RvdHlwZVxuXG50cHJvdG8uaW5zZXJ0ID0gZnVuY3Rpb24oaW50ZXJ2YWwpIHtcbiAgaWYodGhpcy5yb290KSB7XG4gICAgdGhpcy5yb290Lmluc2VydChpbnRlcnZhbClcbiAgfSBlbHNlIHtcbiAgICB0aGlzLnJvb3QgPSBuZXcgSW50ZXJ2YWxUcmVlTm9kZShpbnRlcnZhbFswXSwgbnVsbCwgbnVsbCwgW2ludGVydmFsXSwgW2ludGVydmFsXSlcbiAgfVxufVxuXG50cHJvdG8ucmVtb3ZlID0gZnVuY3Rpb24oaW50ZXJ2YWwpIHtcbiAgaWYodGhpcy5yb290KSB7XG4gICAgdmFyIHIgPSB0aGlzLnJvb3QucmVtb3ZlKGludGVydmFsKVxuICAgIGlmKHIgPT09IEVNUFRZKSB7XG4gICAgICB0aGlzLnJvb3QgPSBudWxsXG4gICAgfVxuICAgIHJldHVybiByICE9PSBOT1RfRk9VTkRcbiAgfVxuICByZXR1cm4gZmFsc2Vcbn1cblxudHByb3RvLnF1ZXJ5UG9pbnQgPSBmdW5jdGlvbihwLCBjYikge1xuICBpZih0aGlzLnJvb3QpIHtcbiAgICByZXR1cm4gdGhpcy5yb290LnF1ZXJ5UG9pbnQocCwgY2IpXG4gIH1cbn1cblxudHByb3RvLnF1ZXJ5SW50ZXJ2YWwgPSBmdW5jdGlvbihsbywgaGksIGNiKSB7XG4gIGlmKGxvIDw9IGhpICYmIHRoaXMucm9vdCkge1xuICAgIHJldHVybiB0aGlzLnJvb3QucXVlcnlJbnRlcnZhbChsbywgaGksIGNiKVxuICB9XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0cHJvdG8sIFwiY291bnRcIiwge1xuICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmKHRoaXMucm9vdCkge1xuICAgICAgcmV0dXJuIHRoaXMucm9vdC5jb3VudFxuICAgIH1cbiAgICByZXR1cm4gMFxuICB9XG59KVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkodHByb3RvLCBcImludGVydmFsc1wiLCB7XG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5yb290KSB7XG4gICAgICByZXR1cm4gdGhpcy5yb290LmludGVydmFscyhbXSlcbiAgICB9XG4gICAgcmV0dXJuIFtdXG4gIH1cbn0pXG5cbmZ1bmN0aW9uIGNyZWF0ZVdyYXBwZXIoaW50ZXJ2YWxzKSB7XG4gIGlmKCFpbnRlcnZhbHMgfHwgaW50ZXJ2YWxzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBuZXcgSW50ZXJ2YWxUcmVlKG51bGwpXG4gIH1cbiAgcmV0dXJuIG5ldyBJbnRlcnZhbFRyZWUoY3JlYXRlSW50ZXJ2YWxUcmVlKGludGVydmFscykpXG59XG5cbn0se1wiYmluYXJ5LXNlYXJjaC1ib3VuZHNcIjo5MX1dLDQxNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5mdW5jdGlvbiBpbnZlcnRQZXJtdXRhdGlvbihwaSwgcmVzdWx0KSB7XG4gIHJlc3VsdCA9IHJlc3VsdCB8fCBuZXcgQXJyYXkocGkubGVuZ3RoKVxuICBmb3IodmFyIGk9MDsgaTxwaS5sZW5ndGg7ICsraSkge1xuICAgIHJlc3VsdFtwaVtpXV0gPSBpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGludmVydFBlcm11dGF0aW9uXG59LHt9XSw0MTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxuZnVuY3Rpb24gaW90YShuKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gaVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpb3RhXG59LHt9XSw0MTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSB0cnVlO1xufSx7fV0sNDE4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qIVxuICogRGV0ZXJtaW5lIGlmIGFuIG9iamVjdCBpcyBhIEJ1ZmZlclxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cblxuLy8gVGhlIF9pc0J1ZmZlciBjaGVjayBpcyBmb3IgU2FmYXJpIDUtNyBzdXBwb3J0LCBiZWNhdXNlIGl0J3MgbWlzc2luZ1xuLy8gT2JqZWN0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvci4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHJldHVybiBvYmogIT0gbnVsbCAmJiAoaXNCdWZmZXIob2JqKSB8fCBpc1Nsb3dCdWZmZXIob2JqKSB8fCAhIW9iai5faXNCdWZmZXIpXG59XG5cbmZ1bmN0aW9uIGlzQnVmZmVyIChvYmopIHtcbiAgcmV0dXJuICEhb2JqLmNvbnN0cnVjdG9yICYmIHR5cGVvZiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIgPT09ICdmdW5jdGlvbicgJiYgb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyKG9iailcbn1cblxuLy8gRm9yIE5vZGUgdjAuMTAgc3VwcG9ydC4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseS5cbmZ1bmN0aW9uIGlzU2xvd0J1ZmZlciAob2JqKSB7XG4gIHJldHVybiB0eXBlb2Ygb2JqLnJlYWRGbG9hdExFID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBvYmouc2xpY2UgPT09ICdmdW5jdGlvbicgJiYgaXNCdWZmZXIob2JqLnNsaWNlKDAsIDApKVxufVxuXG59LHt9XSw0MTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xubW9kdWxlLmV4cG9ydHMgPSB0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJlxuXHQoL01TSUUvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgfHwgL1RyaWRlbnRcXC8vLnRlc3QobmF2aWdhdG9yLmFwcFZlcnNpb24pKTtcblxufSx7fV0sNDIwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGlzTW9iaWxlO1xubW9kdWxlLmV4cG9ydHMuaXNNb2JpbGUgPSBpc01vYmlsZTtcblxudmFyIG1vYmlsZVJFID0gLyhhbmRyb2lkfGJiXFxkK3xtZWVnbykuK21vYmlsZXxhdmFudGdvfGJhZGFcXC98YmxhY2tiZXJyeXxibGF6ZXJ8Y29tcGFsfGVsYWluZXxmZW5uZWN8aGlwdG9wfGllbW9iaWxlfGlwKGhvbmV8b2QpfGlyaXN8a2luZGxlfGxnZSB8bWFlbW98bWlkcHxtbXB8bW9iaWxlLitmaXJlZm94fG5ldGZyb250fG9wZXJhIG0ob2J8aW4paXxwYWxtKCBvcyk/fHBob25lfHAoaXhpfHJlKVxcL3xwbHVja2VyfHBvY2tldHxwc3B8c2VyaWVzKDR8NikwfHN5bWJpYW58dHJlb3x1cFxcLihicm93c2VyfGxpbmspfHZvZGFmb25lfHdhcHx3aW5kb3dzIChjZXxwaG9uZSl8eGRhfHhpaW5vL2k7XG5cbnZhciB0YWJsZXRSRSA9IC8oYW5kcm9pZHxiYlxcZCt8bWVlZ28pLittb2JpbGV8YXZhbnRnb3xiYWRhXFwvfGJsYWNrYmVycnl8YmxhemVyfGNvbXBhbHxlbGFpbmV8ZmVubmVjfGhpcHRvcHxpZW1vYmlsZXxpcChob25lfG9kKXxpcmlzfGtpbmRsZXxsZ2UgfG1hZW1vfG1pZHB8bW1wfG1vYmlsZS4rZmlyZWZveHxuZXRmcm9udHxvcGVyYSBtKG9ifGluKWl8cGFsbSggb3MpP3xwaG9uZXxwKGl4aXxyZSlcXC98cGx1Y2tlcnxwb2NrZXR8cHNwfHNlcmllcyg0fDYpMHxzeW1iaWFufHRyZW98dXBcXC4oYnJvd3NlcnxsaW5rKXx2b2RhZm9uZXx3YXB8d2luZG93cyAoY2V8cGhvbmUpfHhkYXx4aWlub3xhbmRyb2lkfGlwYWR8cGxheWJvb2t8c2lsay9pO1xuXG5mdW5jdGlvbiBpc01vYmlsZSAob3B0cykge1xuICBpZiAoIW9wdHMpIG9wdHMgPSB7fVxuICB2YXIgdWEgPSBvcHRzLnVhXG4gIGlmICghdWEgJiYgdHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcpIHVhID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcbiAgaWYgKHVhICYmIHVhLmhlYWRlcnMgJiYgdHlwZW9mIHVhLmhlYWRlcnNbJ3VzZXItYWdlbnQnXSA9PT0gJ3N0cmluZycpIHtcbiAgICB1YSA9IHVhLmhlYWRlcnNbJ3VzZXItYWdlbnQnXTtcbiAgfVxuICBpZiAodHlwZW9mIHVhICE9PSAnc3RyaW5nJykgcmV0dXJuIGZhbHNlO1xuXG4gIHJldHVybiBvcHRzLnRhYmxldFxuICAgID8gdGFibGV0UkUudGVzdCh1YSlcbiAgICA6IG1vYmlsZVJFLnRlc3QodWEpO1xufVxuXG59LHt9XSw0MjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoeCkge1xuXHR2YXIgdHlwZSA9IHR5cGVvZiB4O1xuXHRyZXR1cm4geCAhPT0gbnVsbCAmJiAodHlwZSA9PT0gJ29iamVjdCcgfHwgdHlwZSA9PT0gJ2Z1bmN0aW9uJyk7XG59O1xuXG59LHt9XSw0MjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xudmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoeCkge1xuXHR2YXIgcHJvdG90eXBlO1xuXHRyZXR1cm4gdG9TdHJpbmcuY2FsbCh4KSA9PT0gJ1tvYmplY3QgT2JqZWN0XScgJiYgKHByb3RvdHlwZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih4KSwgcHJvdG90eXBlID09PSBudWxsIHx8IHByb3RvdHlwZSA9PT0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHt9KSk7XG59O1xuXG59LHt9XSw0MjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xyXG5cclxuLyoqXHJcbiAqIElzIHRoaXMgc3RyaW5nIGFsbCB3aGl0ZXNwYWNlP1xyXG4gKiBUaGlzIHNvbHV0aW9uIGtpbmQgb2YgbWFrZXMgbXkgYnJhaW4gaHVydCwgYnV0IGl0J3Mgc2lnbmlmaWNhbnRseSBmYXN0ZXJcclxuICogdGhhbiAhc3RyLnRyaW0oKSBvciBhbnkgb3RoZXIgc29sdXRpb24gSSBjb3VsZCBmaW5kLlxyXG4gKlxyXG4gKiB3aGl0ZXNwYWNlIGNvZGVzIGZyb206IGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2hpdGVzcGFjZV9jaGFyYWN0ZXJcclxuICogYW5kIHZlcmlmaWVkIHdpdGg6XHJcbiAqXHJcbiAqICBmb3IodmFyIGkgPSAwOyBpIDwgNjU1MzY7IGkrKykge1xyXG4gKiAgICAgIHZhciBzID0gU3RyaW5nLmZyb21DaGFyQ29kZShpKTtcclxuICogICAgICBpZigrcz09PTAgJiYgIXMudHJpbSgpKSBjb25zb2xlLmxvZyhpLCBzKTtcclxuICogIH1cclxuICpcclxuICogd2hpY2ggY291bnRzIGEgY291cGxlIG9mIHRoZXNlIGFzICpub3QqIHdoaXRlc3BhY2UsIGJ1dCBmaW5kcyBub3RoaW5nIGVsc2VcclxuICogdGhhdCAqaXMqIHdoaXRlc3BhY2UuIE5vdGUgdGhhdCBjaGFyQ29kZUF0IHN0b3BzIGF0IDE2IGJpdHMsIGJ1dCBpdCBhcHBlYXJzXHJcbiAqIHRoYXQgdGhlcmUgYXJlIG5vIHdoaXRlc3BhY2UgY2hhcmFjdGVycyBhYm92ZSB0aGlzLCBhbmQgY29kZSBwb2ludHMgYWJvdmVcclxuICogdGhpcyBkbyBub3QgbWFwIG9udG8gd2hpdGUgc3BhY2UgY2hhcmFjdGVycy5cclxuICovXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHN0cil7XHJcbiAgICB2YXIgbCA9IHN0ci5sZW5ndGgsXHJcbiAgICAgICAgYTtcclxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICBhID0gc3RyLmNoYXJDb2RlQXQoaSk7XHJcbiAgICAgICAgaWYoKGEgPCA5IHx8IGEgPiAxMykgJiYgKGEgIT09IDMyKSAmJiAoYSAhPT0gMTMzKSAmJiAoYSAhPT0gMTYwKSAmJlxyXG4gICAgICAgICAgICAoYSAhPT0gNTc2MCkgJiYgKGEgIT09IDYxNTgpICYmIChhIDwgODE5MiB8fCBhID4gODIwNSkgJiZcclxuICAgICAgICAgICAgKGEgIT09IDgyMzIpICYmIChhICE9PSA4MjMzKSAmJiAoYSAhPT0gODIzOSkgJiYgKGEgIT09IDgyODcpICYmXHJcbiAgICAgICAgICAgIChhICE9PSA4Mjg4KSAmJiAoYSAhPT0gMTIyODgpICYmIChhICE9PSA2NTI3OSkpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxufVxyXG5cbn0se31dLDQyNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNQYXRoKHN0cikge1xyXG5cdGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykgcmV0dXJuIGZhbHNlXHJcblxyXG5cdHN0ciA9IHN0ci50cmltKClcclxuXHJcblx0Ly8gaHR0cHM6Ly93d3cudzMub3JnL1RSL1NWRy9wYXRocy5odG1sI1BhdGhEYXRhQk5GXHJcblx0aWYgKC9eW216bGh2Y3NxdGFdXFxzKlstKy4wLTldW15tbGh2emNzcXRhXSsvaS50ZXN0KHN0cikgJiYgL1tcXGR6XSQvaS50ZXN0KHN0cikgJiYgc3RyLmxlbmd0aCA+IDQpIHJldHVybiB0cnVlXHJcblxyXG5cdHJldHVybiBmYWxzZVxyXG59XHJcblxufSx7fV0sNDI1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbmZ1bmN0aW9uIGxlcnAodjAsIHYxLCB0KSB7XG4gICAgcmV0dXJuIHYwKigxLXQpK3YxKnRcbn1cbm1vZHVsZS5leHBvcnRzID0gbGVycFxufSx7fV0sNDI2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qIE1hcGJveCBHTCBKUyBpcyBsaWNlbnNlZCB1bmRlciB0aGUgMy1DbGF1c2UgQlNEIExpY2Vuc2UuIEZ1bGwgdGV4dCBvZiBsaWNlbnNlOiBodHRwczovL2dpdGh1Yi5jb20vbWFwYm94L21hcGJveC1nbC1qcy9ibG9iL3YxLjEuMS9MSUNFTlNFLnR4dCAqL1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbnR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpIDpcbnR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShmYWN0b3J5KSA6XG4oZ2xvYmFsID0gZ2xvYmFsIHx8IHNlbGYsIGdsb2JhbC5tYXBib3hnbCA9IGZhY3RvcnkoKSk7XG59KHRoaXMsIGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSAqL1xuXG52YXIgc2hhcmVkLCB3b3JrZXIsIG1hcGJveGdsO1xuLy8gZGVmaW5lIGdldHMgY2FsbGVkIHRocmVlIHRpbWVzOiBvbmUgZm9yIGVhY2ggY2h1bmsuIHdlIHJlbHkgb24gdGhlIG9yZGVyXG4vLyB0aGV5J3JlIGltcG9ydGVkIHRvIGtub3cgd2hpY2ggaXMgd2hpY2hcbmZ1bmN0aW9uIGRlZmluZShfLCBjaHVuaykge1xuaWYgKCFzaGFyZWQpIHtcbiAgICBzaGFyZWQgPSBjaHVuaztcbn0gZWxzZSBpZiAoIXdvcmtlcikge1xuICAgIHdvcmtlciA9IGNodW5rO1xufSBlbHNlIHtcbiAgICB2YXIgd29ya2VyQnVuZGxlU3RyaW5nID0gJ3ZhciBzaGFyZWRDaHVuayA9IHt9OyAoJyArIHNoYXJlZCArICcpKHNoYXJlZENodW5rKTsgKCcgKyB3b3JrZXIgKyAnKShzaGFyZWRDaHVuayk7J1xuXG4gICAgdmFyIHNoYXJlZENodW5rID0ge307XG4gICAgc2hhcmVkKHNoYXJlZENodW5rKTtcbiAgICBtYXBib3hnbCA9IGNodW5rKHNoYXJlZENodW5rKTtcbiAgICBtYXBib3hnbC53b3JrZXJVcmwgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChuZXcgQmxvYihbd29ya2VyQnVuZGxlU3RyaW5nXSwgeyB0eXBlOiAndGV4dC9qYXZhc2NyaXB0JyB9KSk7XG59XG59XG5cblxuZGVmaW5lKFtcImV4cG9ydHNcIl0sZnVuY3Rpb24odCl7XCJ1c2Ugc3RyaWN0XCI7ZnVuY3Rpb24gZSh0LGUpe3JldHVybiB0KGU9e2V4cG9ydHM6e319LGUuZXhwb3J0cyksZS5leHBvcnRzfXZhciByPW47ZnVuY3Rpb24gbih0LGUscixuKXt0aGlzLmN4PTMqdCx0aGlzLmJ4PTMqKHItdCktdGhpcy5jeCx0aGlzLmF4PTEtdGhpcy5jeC10aGlzLmJ4LHRoaXMuY3k9MyplLHRoaXMuYnk9Myoobi1lKS10aGlzLmN5LHRoaXMuYXk9MS10aGlzLmN5LXRoaXMuYnksdGhpcy5wMXg9dCx0aGlzLnAxeT1uLHRoaXMucDJ4PXIsdGhpcy5wMnk9bjt9bi5wcm90b3R5cGUuc2FtcGxlQ3VydmVYPWZ1bmN0aW9uKHQpe3JldHVybiAoKHRoaXMuYXgqdCt0aGlzLmJ4KSp0K3RoaXMuY3gpKnR9LG4ucHJvdG90eXBlLnNhbXBsZUN1cnZlWT1mdW5jdGlvbih0KXtyZXR1cm4gKCh0aGlzLmF5KnQrdGhpcy5ieSkqdCt0aGlzLmN5KSp0fSxuLnByb3RvdHlwZS5zYW1wbGVDdXJ2ZURlcml2YXRpdmVYPWZ1bmN0aW9uKHQpe3JldHVybiAoMyp0aGlzLmF4KnQrMip0aGlzLmJ4KSp0K3RoaXMuY3h9LG4ucHJvdG90eXBlLnNvbHZlQ3VydmVYPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixpLGEsbztmb3Iodm9pZCAwPT09ZSYmKGU9MWUtNiksaT10LG89MDtvPDg7bysrKXtpZihhPXRoaXMuc2FtcGxlQ3VydmVYKGkpLXQsTWF0aC5hYnMoYSk8ZSlyZXR1cm4gaTt2YXIgcz10aGlzLnNhbXBsZUN1cnZlRGVyaXZhdGl2ZVgoaSk7aWYoTWF0aC5hYnMocyk8MWUtNilicmVhaztpLT1hL3M7fWlmKChpPXQpPChyPTApKXJldHVybiByO2lmKGk+KG49MSkpcmV0dXJuIG47Zm9yKDtyPG47KXtpZihhPXRoaXMuc2FtcGxlQ3VydmVYKGkpLE1hdGguYWJzKGEtdCk8ZSlyZXR1cm4gaTt0PmE/cj1pOm49aSxpPS41KihuLXIpK3I7fXJldHVybiBpfSxuLnByb3RvdHlwZS5zb2x2ZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnNhbXBsZUN1cnZlWSh0aGlzLnNvbHZlQ3VydmVYKHQsZSkpfTt2YXIgaT1hO2Z1bmN0aW9uIGEodCxlKXt0aGlzLng9dCx0aGlzLnk9ZTt9ZnVuY3Rpb24gbyh0LGUpe2lmKEFycmF5LmlzQXJyYXkodCkpe2lmKCFBcnJheS5pc0FycmF5KGUpfHx0Lmxlbmd0aCE9PWUubGVuZ3RoKXJldHVybiAhMTtmb3IodmFyIHI9MDtyPHQubGVuZ3RoO3IrKylpZighbyh0W3JdLGVbcl0pKXJldHVybiAhMTtyZXR1cm4gITB9aWYoXCJvYmplY3RcIj09dHlwZW9mIHQmJm51bGwhPT10JiZudWxsIT09ZSl7aWYoXCJvYmplY3RcIiE9dHlwZW9mIGUpcmV0dXJuICExO2lmKE9iamVjdC5rZXlzKHQpLmxlbmd0aCE9PU9iamVjdC5rZXlzKGUpLmxlbmd0aClyZXR1cm4gITE7Zm9yKHZhciBuIGluIHQpaWYoIW8odFtuXSxlW25dKSlyZXR1cm4gITE7cmV0dXJuICEwfXJldHVybiB0PT09ZX1mdW5jdGlvbiBzKHQsZSxuLGkpe3ZhciBhPW5ldyByKHQsZSxuLGkpO3JldHVybiBmdW5jdGlvbih0KXtyZXR1cm4gYS5zb2x2ZSh0KX19YS5wcm90b3R5cGU9e2Nsb25lOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBhKHRoaXMueCx0aGlzLnkpfSxhZGQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuY2xvbmUoKS5fYWRkKHQpfSxzdWI6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuY2xvbmUoKS5fc3ViKHQpfSxtdWx0QnlQb2ludDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5jbG9uZSgpLl9tdWx0QnlQb2ludCh0KX0sZGl2QnlQb2ludDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5jbG9uZSgpLl9kaXZCeVBvaW50KHQpfSxtdWx0OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNsb25lKCkuX211bHQodCl9LGRpdjpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5jbG9uZSgpLl9kaXYodCl9LHJvdGF0ZTpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5jbG9uZSgpLl9yb3RhdGUodCl9LHJvdGF0ZUFyb3VuZDpmdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmNsb25lKCkuX3JvdGF0ZUFyb3VuZCh0LGUpfSxtYXRNdWx0OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNsb25lKCkuX21hdE11bHQodCl9LHVuaXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jbG9uZSgpLl91bml0KCl9LHBlcnA6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jbG9uZSgpLl9wZXJwKCl9LHJvdW5kOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY2xvbmUoKS5fcm91bmQoKX0sbWFnOmZ1bmN0aW9uKCl7cmV0dXJuIE1hdGguc3FydCh0aGlzLngqdGhpcy54K3RoaXMueSp0aGlzLnkpfSxlcXVhbHM6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMueD09PXQueCYmdGhpcy55PT09dC55fSxkaXN0OmZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLnNxcnQodGhpcy5kaXN0U3FyKHQpKX0sZGlzdFNxcjpmdW5jdGlvbih0KXt2YXIgZT10LngtdGhpcy54LHI9dC55LXRoaXMueTtyZXR1cm4gZSplK3Iqcn0sYW5nbGU6ZnVuY3Rpb24oKXtyZXR1cm4gTWF0aC5hdGFuMih0aGlzLnksdGhpcy54KX0sYW5nbGVUbzpmdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5hdGFuMih0aGlzLnktdC55LHRoaXMueC10LngpfSxhbmdsZVdpdGg6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuYW5nbGVXaXRoU2VwKHQueCx0LnkpfSxhbmdsZVdpdGhTZXA6ZnVuY3Rpb24odCxlKXtyZXR1cm4gTWF0aC5hdGFuMih0aGlzLngqZS10aGlzLnkqdCx0aGlzLngqdCt0aGlzLnkqZSl9LF9tYXRNdWx0OmZ1bmN0aW9uKHQpe3ZhciBlPXRbMF0qdGhpcy54K3RbMV0qdGhpcy55LHI9dFsyXSp0aGlzLngrdFszXSp0aGlzLnk7cmV0dXJuIHRoaXMueD1lLHRoaXMueT1yLHRoaXN9LF9hZGQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMueCs9dC54LHRoaXMueSs9dC55LHRoaXN9LF9zdWI6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMueC09dC54LHRoaXMueS09dC55LHRoaXN9LF9tdWx0OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLngqPXQsdGhpcy55Kj10LHRoaXN9LF9kaXY6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMueC89dCx0aGlzLnkvPXQsdGhpc30sX211bHRCeVBvaW50OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLngqPXQueCx0aGlzLnkqPXQueSx0aGlzfSxfZGl2QnlQb2ludDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy54Lz10LngsdGhpcy55Lz10LnksdGhpc30sX3VuaXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZGl2KHRoaXMubWFnKCkpLHRoaXN9LF9wZXJwOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy55O3JldHVybiB0aGlzLnk9dGhpcy54LHRoaXMueD0tdCx0aGlzfSxfcm90YXRlOmZ1bmN0aW9uKHQpe3ZhciBlPU1hdGguY29zKHQpLHI9TWF0aC5zaW4odCksbj1lKnRoaXMueC1yKnRoaXMueSxpPXIqdGhpcy54K2UqdGhpcy55O3JldHVybiB0aGlzLng9bix0aGlzLnk9aSx0aGlzfSxfcm90YXRlQXJvdW5kOmZ1bmN0aW9uKHQsZSl7dmFyIHI9TWF0aC5jb3ModCksbj1NYXRoLnNpbih0KSxpPWUueCtyKih0aGlzLngtZS54KS1uKih0aGlzLnktZS55KSxhPWUueStuKih0aGlzLngtZS54KStyKih0aGlzLnktZS55KTtyZXR1cm4gdGhpcy54PWksdGhpcy55PWEsdGhpc30sX3JvdW5kOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMueD1NYXRoLnJvdW5kKHRoaXMueCksdGhpcy55PU1hdGgucm91bmQodGhpcy55KSx0aGlzfX0sYS5jb252ZXJ0PWZ1bmN0aW9uKHQpe3JldHVybiB0IGluc3RhbmNlb2YgYT90OkFycmF5LmlzQXJyYXkodCk/bmV3IGEodFswXSx0WzFdKTp0fTt2YXIgdT1zKC4yNSwuMSwuMjUsMSk7ZnVuY3Rpb24gbCh0LGUscil7cmV0dXJuIE1hdGgubWluKHIsTWF0aC5tYXgoZSx0KSl9ZnVuY3Rpb24gcCh0LGUscil7dmFyIG49ci1lLGk9KCh0LWUpJW4rbiklbitlO3JldHVybiBpPT09ZT9yOml9ZnVuY3Rpb24gYyh0KXtmb3IodmFyIGU9W10scj1hcmd1bWVudHMubGVuZ3RoLTE7ci0tID4wOyllW3JdPWFyZ3VtZW50c1tyKzFdO2Zvcih2YXIgbj0wLGk9ZTtuPGkubGVuZ3RoO24rPTEpe3ZhciBhPWlbbl07Zm9yKHZhciBvIGluIGEpdFtvXT1hW29dO31yZXR1cm4gdH12YXIgaD0xO2Z1bmN0aW9uIGYoKXtyZXR1cm4gaCsrfWZ1bmN0aW9uIHkoKXtyZXR1cm4gZnVuY3Rpb24gdChlKXtyZXR1cm4gZT8oZV4xNipNYXRoLnJhbmRvbSgpPj5lLzQpLnRvU3RyaW5nKDE2KTooWzFlN10rLVsxZTNdKy00ZTMrLThlMystMWUxMSkucmVwbGFjZSgvWzAxOF0vZyx0KX0oKX1mdW5jdGlvbiBkKHQpe3JldHVybiAhIXQmJi9eWzAtOWEtZl17OH0tWzAtOWEtZl17NH0tWzRdWzAtOWEtZl17M30tWzg5YWJdWzAtOWEtZl17M30tWzAtOWEtZl17MTJ9JC9pLnRlc3QodCl9ZnVuY3Rpb24gbSh0LGUpe3QuZm9yRWFjaChmdW5jdGlvbih0KXtlW3RdJiYoZVt0XT1lW3RdLmJpbmQoZSkpO30pO31mdW5jdGlvbiB2KHQsZSl7cmV0dXJuIC0xIT09dC5pbmRleE9mKGUsdC5sZW5ndGgtZS5sZW5ndGgpfWZ1bmN0aW9uIGcodCxlLHIpe3ZhciBuPXt9O2Zvcih2YXIgaSBpbiB0KW5baV09ZS5jYWxsKHJ8fHRoaXMsdFtpXSxpLHQpO3JldHVybiBufWZ1bmN0aW9uIHgodCxlLHIpe3ZhciBuPXt9O2Zvcih2YXIgaSBpbiB0KWUuY2FsbChyfHx0aGlzLHRbaV0saSx0KSYmKG5baV09dFtpXSk7cmV0dXJuIG59ZnVuY3Rpb24gYih0KXtyZXR1cm4gQXJyYXkuaXNBcnJheSh0KT90Lm1hcChiKTpcIm9iamVjdFwiPT10eXBlb2YgdCYmdD9nKHQsYik6dH12YXIgXz17fTtmdW5jdGlvbiB3KHQpe19bdF18fChcInVuZGVmaW5lZFwiIT10eXBlb2YgY29uc29sZSYmY29uc29sZS53YXJuKHQpLF9bdF09ITApO31mdW5jdGlvbiBBKHQsZSxyKXtyZXR1cm4gKHIueS10LnkpKihlLngtdC54KT4oZS55LXQueSkqKHIueC10LngpfWZ1bmN0aW9uIFModCl7Zm9yKHZhciBlPTAscj0wLG49dC5sZW5ndGgsaT1uLTEsYT12b2lkIDAsbz12b2lkIDA7cjxuO2k9cisrKWE9dFtyXSxlKz0oKG89dFtpXSkueC1hLngpKihhLnkrby55KTtyZXR1cm4gZX1mdW5jdGlvbiBrKHQpe3ZhciBlPXt9O2lmKHQucmVwbGFjZSgvKD86XnwoPzpcXHMqXFwsXFxzKikpKFteXFx4MDAtXFx4MjBcXChcXCk8PkBcXCw7XFw6XFxcXFwiXFwvXFxbXFxdXFw/XFw9XFx7XFx9XFx4N0ZdKykoPzpcXD0oPzooW15cXHgwMC1cXHgyMFxcKFxcKTw+QFxcLDtcXDpcXFxcXCJcXC9cXFtcXF1cXD9cXD1cXHtcXH1cXHg3Rl0rKXwoPzpcXFwiKCg/OlteXCJcXFxcXXxcXFxcLikqKVxcXCIpKSk/L2csZnVuY3Rpb24odCxyLG4saSl7dmFyIGE9bnx8aTtyZXR1cm4gZVtyXT0hYXx8YS50b0xvd2VyQ2FzZSgpLFwiXCJ9KSxlW1wibWF4LWFnZVwiXSl7dmFyIHI9cGFyc2VJbnQoZVtcIm1heC1hZ2VcIl0sMTApO2lzTmFOKHIpP2RlbGV0ZSBlW1wibWF4LWFnZVwiXTplW1wibWF4LWFnZVwiXT1yO31yZXR1cm4gZX1mdW5jdGlvbiB6KHQpe3RyeXt2YXIgZT1zZWxmW3RdO3JldHVybiBlLnNldEl0ZW0oXCJfbWFwYm94X3Rlc3RfXCIsMSksZS5yZW1vdmVJdGVtKFwiX21hcGJveF90ZXN0X1wiKSwhMH1jYXRjaCh0KXtyZXR1cm4gITF9fXZhciBJLEIsQyxFPXNlbGYucGVyZm9ybWFuY2UmJnNlbGYucGVyZm9ybWFuY2Uubm93P3NlbGYucGVyZm9ybWFuY2Uubm93LmJpbmQoc2VsZi5wZXJmb3JtYW5jZSk6RGF0ZS5ub3cuYmluZChEYXRlKSxNPXNlbGYucmVxdWVzdEFuaW1hdGlvbkZyYW1lfHxzZWxmLm1velJlcXVlc3RBbmltYXRpb25GcmFtZXx8c2VsZi53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWV8fHNlbGYubXNSZXF1ZXN0QW5pbWF0aW9uRnJhbWUsVD1zZWxmLmNhbmNlbEFuaW1hdGlvbkZyYW1lfHxzZWxmLm1vekNhbmNlbEFuaW1hdGlvbkZyYW1lfHxzZWxmLndlYmtpdENhbmNlbEFuaW1hdGlvbkZyYW1lfHxzZWxmLm1zQ2FuY2VsQW5pbWF0aW9uRnJhbWUsUD17bm93OkUsZnJhbWU6ZnVuY3Rpb24odCl7dmFyIGU9TSh0KTtyZXR1cm4ge2NhbmNlbDpmdW5jdGlvbigpe3JldHVybiBUKGUpfX19LGdldEltYWdlRGF0YTpmdW5jdGlvbih0KXt2YXIgZT1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIikscj1lLmdldENvbnRleHQoXCIyZFwiKTtpZighcil0aHJvdyBuZXcgRXJyb3IoXCJmYWlsZWQgdG8gY3JlYXRlIGNhbnZhcyAyZCBjb250ZXh0XCIpO3JldHVybiBlLndpZHRoPXQud2lkdGgsZS5oZWlnaHQ9dC5oZWlnaHQsci5kcmF3SW1hZ2UodCwwLDAsdC53aWR0aCx0LmhlaWdodCksci5nZXRJbWFnZURhdGEoMCwwLHQud2lkdGgsdC5oZWlnaHQpfSxyZXNvbHZlVVJMOmZ1bmN0aW9uKHQpe3JldHVybiBJfHwoST1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpKSxJLmhyZWY9dCxJLmhyZWZ9LGhhcmR3YXJlQ29uY3VycmVuY3k6c2VsZi5uYXZpZ2F0b3IuaGFyZHdhcmVDb25jdXJyZW5jeXx8NCxnZXQgZGV2aWNlUGl4ZWxSYXRpbygpe3JldHVybiBzZWxmLmRldmljZVBpeGVsUmF0aW99fSxWPXtBUElfVVJMOlwiaHR0cHM6Ly9hcGkubWFwYm94LmNvbVwiLGdldCBFVkVOVFNfVVJMKCl7cmV0dXJuIHRoaXMuQVBJX1VSTD8wPT09dGhpcy5BUElfVVJMLmluZGV4T2YoXCJodHRwczovL2FwaS5tYXBib3guY25cIik/XCJodHRwczovL2V2ZW50cy5tYXBib3guY24vZXZlbnRzL3YyXCI6MD09PXRoaXMuQVBJX1VSTC5pbmRleE9mKFwiaHR0cHM6Ly9hcGkubWFwYm94LmNvbVwiKT9cImh0dHBzOi8vZXZlbnRzLm1hcGJveC5jb20vZXZlbnRzL3YyXCI6bnVsbDpudWxsfSxGRUVEQkFDS19VUkw6XCJodHRwczovL2FwcHMubWFwYm94LmNvbS9mZWVkYmFja1wiLFJFUVVJUkVfQUNDRVNTX1RPS0VOOiEwLEFDQ0VTU19UT0tFTjpudWxsLE1BWF9QQVJBTExFTF9JTUFHRV9SRVFVRVNUUzoxNn0sRj17c3VwcG9ydGVkOiExLHRlc3RTdXBwb3J0OmZ1bmN0aW9uKHQpe2lmKEx8fCFDKXJldHVybjtEP08odCk6Qj10O319LEw9ITEsRD0hMTtmdW5jdGlvbiBPKHQpe3ZhciBlPXQuY3JlYXRlVGV4dHVyZSgpO3QuYmluZFRleHR1cmUodC5URVhUVVJFXzJELGUpO3RyeXtpZih0LnRleEltYWdlMkQodC5URVhUVVJFXzJELDAsdC5SR0JBLHQuUkdCQSx0LlVOU0lHTkVEX0JZVEUsQyksdC5pc0NvbnRleHRMb3N0KCkpcmV0dXJuO0Yuc3VwcG9ydGVkPSEwO31jYXRjaCh0KXt9dC5kZWxldGVUZXh0dXJlKGUpLEw9ITA7fXNlbGYuZG9jdW1lbnQmJigoQz1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJpbWdcIikpLm9ubG9hZD1mdW5jdGlvbigpe0ImJk8oQiksQj1udWxsLEQ9ITA7fSxDLm9uZXJyb3I9ZnVuY3Rpb24oKXtMPSEwLEI9bnVsbDt9LEMuc3JjPVwiZGF0YTppbWFnZS93ZWJwO2Jhc2U2NCxVa2xHUmg0QUFBQlhSVUpRVmxBNFRCRUFBQUF2QVFBQUFBZlEvLzczdi8rQmlPaC9BQUE9XCIpO3ZhciBSPVwiMDFcIjt2YXIgVT1mdW5jdGlvbih0KXt0aGlzLl90cmFuc2Zvcm1SZXF1ZXN0Rm49dCx0aGlzLl9jcmVhdGVTa3VUb2tlbigpO307VS5wcm90b3R5cGUuX2NyZWF0ZVNrdVRva2VuPWZ1bmN0aW9uKCl7dmFyIHQ9ZnVuY3Rpb24oKXtmb3IodmFyIHQ9XCJcIixlPTA7ZTwxMDtlKyspdCs9XCIwMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWlwiW01hdGguZmxvb3IoNjIqTWF0aC5yYW5kb20oKSldO3JldHVybiB7dG9rZW46W1wiMVwiLFIsdF0uam9pbihcIlwiKSx0b2tlbkV4cGlyZXNBdDpEYXRlLm5vdygpKzQzMmU1fX0oKTt0aGlzLl9za3VUb2tlbj10LnRva2VuLHRoaXMuX3NrdVRva2VuRXhwaXJlc0F0PXQudG9rZW5FeHBpcmVzQXQ7fSxVLnByb3RvdHlwZS5faXNTa3VUb2tlbkV4cGlyZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gRGF0ZS5ub3coKT50aGlzLl9za3VUb2tlbkV4cGlyZXNBdH0sVS5wcm90b3R5cGUudHJhbnNmb3JtUmVxdWVzdD1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLl90cmFuc2Zvcm1SZXF1ZXN0Rm4mJnRoaXMuX3RyYW5zZm9ybVJlcXVlc3RGbih0LGUpfHx7dXJsOnR9fSxVLnByb3RvdHlwZS5ub3JtYWxpemVTdHlsZVVSTD1mdW5jdGlvbih0LGUpe3JldHVybiBHKHQsZSl9LFUucHJvdG90eXBlLm5vcm1hbGl6ZUdseXBoc1VSTD1mdW5jdGlvbih0LGUpe3JldHVybiBYKHQsZSl9LFUucHJvdG90eXBlLm5vcm1hbGl6ZVNvdXJjZVVSTD1mdW5jdGlvbih0LGUpe3JldHVybiBKKHQsZSl9LFUucHJvdG90eXBlLm5vcm1hbGl6ZVNwcml0ZVVSTD1mdW5jdGlvbih0LGUscixuKXtyZXR1cm4gSCh0LGUscixuKX0sVS5wcm90b3R5cGUubm9ybWFsaXplVGlsZVVSTD1mdW5jdGlvbih0LGUscil7cmV0dXJuIHRoaXMuX2lzU2t1VG9rZW5FeHBpcmVkKCkmJnRoaXMuX2NyZWF0ZVNrdVRva2VuKCksJCh0LGUscix0aGlzLl9za3VUb2tlbil9LFUucHJvdG90eXBlLmNhbm9uaWNhbGl6ZVRpbGVVUkw9ZnVuY3Rpb24odCl7cmV0dXJuIFEodCl9LFUucHJvdG90eXBlLmNhbm9uaWNhbGl6ZVRpbGVzZXQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdHQodCxlKX07dmFyIGo9XCJTZWUgaHR0cHM6Ly93d3cubWFwYm94LmNvbS9hcGktZG9jdW1lbnRhdGlvbi8jYWNjZXNzLXRva2Vucy1hbmQtdG9rZW4tc2NvcGVzXCI7ZnVuY3Rpb24gcSh0LGUpe3ZhciByPXJ0KFYuQVBJX1VSTCk7aWYodC5wcm90b2NvbD1yLnByb3RvY29sLHQuYXV0aG9yaXR5PXIuYXV0aG9yaXR5LFwiL1wiIT09ci5wYXRoJiYodC5wYXRoPVwiXCIrci5wYXRoK3QucGF0aCksIVYuUkVRVUlSRV9BQ0NFU1NfVE9LRU4pcmV0dXJuIG50KHQpO2lmKCEoZT1lfHxWLkFDQ0VTU19UT0tFTikpdGhyb3cgbmV3IEVycm9yKFwiQW4gQVBJIGFjY2VzcyB0b2tlbiBpcyByZXF1aXJlZCB0byB1c2UgTWFwYm94IEdMLiBcIitqKTtpZihcInNcIj09PWVbMF0pdGhyb3cgbmV3IEVycm9yKFwiVXNlIGEgcHVibGljIGFjY2VzcyB0b2tlbiAocGsuKikgd2l0aCBNYXBib3ggR0wsIG5vdCBhIHNlY3JldCBhY2Nlc3MgdG9rZW4gKHNrLiopLiBcIitqKTtyZXR1cm4gdC5wYXJhbXMucHVzaChcImFjY2Vzc190b2tlbj1cIitlKSxudCh0KX1mdW5jdGlvbiBOKHQpe3JldHVybiAwPT09dC5pbmRleE9mKFwibWFwYm94OlwiKX12YXIgWj0vXigoaHR0cHM/Oik/XFwvXFwvKT8oW15cXC9dK1xcLik/bWFwYm94XFwuYyhufG9tKShcXC98XFw/fCQpL2k7ZnVuY3Rpb24gSyh0KXtyZXR1cm4gWi50ZXN0KHQpfXZhciBHPWZ1bmN0aW9uKHQsZSl7aWYoIU4odCkpcmV0dXJuIHQ7dmFyIHI9cnQodCk7cmV0dXJuIHIucGF0aD1cIi9zdHlsZXMvdjFcIityLnBhdGgscShyLGUpfSxYPWZ1bmN0aW9uKHQsZSl7aWYoIU4odCkpcmV0dXJuIHQ7dmFyIHI9cnQodCk7cmV0dXJuIHIucGF0aD1cIi9mb250cy92MVwiK3IucGF0aCxxKHIsZSl9LEo9ZnVuY3Rpb24odCxlKXtpZighTih0KSlyZXR1cm4gdDt2YXIgcj1ydCh0KTtyZXR1cm4gci5wYXRoPVwiL3Y0L1wiK3IuYXV0aG9yaXR5K1wiLmpzb25cIixyLnBhcmFtcy5wdXNoKFwic2VjdXJlXCIpLHEocixlKX0sSD1mdW5jdGlvbih0LGUscixuKXt2YXIgaT1ydCh0KTtyZXR1cm4gTih0KT8oaS5wYXRoPVwiL3N0eWxlcy92MVwiK2kucGF0aCtcIi9zcHJpdGVcIitlK3IscShpLG4pKTooaS5wYXRoKz1cIlwiK2UrcixudChpKSl9LFk9LyhcXC4ocG5nfGpwZylcXGQqKSg/PSQpLywkPWZ1bmN0aW9uKHQsZSxyLG4pe2lmKCFlfHwhTihlKSlyZXR1cm4gdDt2YXIgaT1ydCh0KSxhPVAuZGV2aWNlUGl4ZWxSYXRpbz49Mnx8NTEyPT09cj9cIkAyeFwiOlwiXCIsbz1GLnN1cHBvcnRlZD9cIi53ZWJwXCI6XCIkMVwiO3JldHVybiBpLnBhdGg9aS5wYXRoLnJlcGxhY2UoWSxcIlwiK2ErbyksaS5wYXRoPVwiL3Y0XCIraS5wYXRoLFYuUkVRVUlSRV9BQ0NFU1NfVE9LRU4mJlYuQUNDRVNTX1RPS0VOJiZuJiZpLnBhcmFtcy5wdXNoKFwic2t1PVwiK24pLHEoaSl9LFc9L1xcLltcXHddKyQvLFE9ZnVuY3Rpb24odCl7dmFyIGU9cnQodCk7aWYoIWUucGF0aC5tYXRjaCgvKF5cXC92NFxcLykvKXx8IWUucGF0aC5tYXRjaChXKSlyZXR1cm4gdDt2YXIgcj1cIm1hcGJveDovL3RpbGVzL1wiO3IrPWUucGF0aC5yZXBsYWNlKFwiL3Y0L1wiLFwiXCIpO3ZhciBuPWUucGFyYW1zLmZpbHRlcihmdW5jdGlvbih0KXtyZXR1cm4gIXQubWF0Y2goL15hY2Nlc3NfdG9rZW49Lyl9KTtyZXR1cm4gbi5sZW5ndGgmJihyKz1cIj9cIituLmpvaW4oXCImXCIpKSxyfSx0dD1mdW5jdGlvbih0LGUpe2lmKCFOKGUpKXJldHVybiB0LnRpbGVzfHxbXTtmb3IodmFyIHI9W10sbj0wLGk9dC50aWxlcztuPGkubGVuZ3RoO24rPTEpe3ZhciBhPWlbbl0sbz1RKGEpO3IucHVzaChvKTt9cmV0dXJuIHJ9LGV0PS9eKFxcdyspOlxcL1xcLyhbXlxcLz9dKikoXFwvW14/XSspP1xcPz8oLispPy87ZnVuY3Rpb24gcnQodCl7dmFyIGU9dC5tYXRjaChldCk7aWYoIWUpdGhyb3cgbmV3IEVycm9yKFwiVW5hYmxlIHRvIHBhcnNlIFVSTCBvYmplY3RcIik7cmV0dXJuIHtwcm90b2NvbDplWzFdLGF1dGhvcml0eTplWzJdLHBhdGg6ZVszXXx8XCIvXCIscGFyYW1zOmVbNF0/ZVs0XS5zcGxpdChcIiZcIik6W119fWZ1bmN0aW9uIG50KHQpe3ZhciBlPXQucGFyYW1zLmxlbmd0aD9cIj9cIit0LnBhcmFtcy5qb2luKFwiJlwiKTpcIlwiO3JldHVybiB0LnByb3RvY29sK1wiOi8vXCIrdC5hdXRob3JpdHkrdC5wYXRoK2V9ZnVuY3Rpb24gaXQodCl7aWYoIXQpcmV0dXJuIG51bGw7dmFyIGUscj10LnNwbGl0KFwiLlwiKTtpZighcnx8MyE9PXIubGVuZ3RoKXJldHVybiBudWxsO3RyeXtyZXR1cm4gSlNPTi5wYXJzZSgoZT1yWzFdLGRlY29kZVVSSUNvbXBvbmVudChzZWxmLmF0b2IoZSkuc3BsaXQoXCJcIikubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBcIiVcIisoXCIwMFwiK3QuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNikpLnNsaWNlKC0yKX0pLmpvaW4oXCJcIikpKSl9Y2F0Y2godCl7cmV0dXJuIG51bGx9fXZhciBhdD1mdW5jdGlvbih0KXt0aGlzLnR5cGU9dCx0aGlzLmFub25JZD1udWxsLHRoaXMuZXZlbnREYXRhPXt9LHRoaXMucXVldWU9W10sdGhpcy5wZW5kaW5nUmVxdWVzdD1udWxsO307YXQucHJvdG90eXBlLmdldFN0b3JhZ2VLZXk9ZnVuY3Rpb24odCl7dmFyIGUscj1pdChWLkFDQ0VTU19UT0tFTiksbj1cIlwiO3JldHVybiByJiZyLnU/KGU9ci51LG49c2VsZi5idG9hKGVuY29kZVVSSUNvbXBvbmVudChlKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoTnVtYmVyKFwiMHhcIitlKSl9KSkpOm49Vi5BQ0NFU1NfVE9LRU58fFwiXCIsdD9cIm1hcGJveC5ldmVudERhdGEuXCIrdCtcIjpcIituOlwibWFwYm94LmV2ZW50RGF0YTpcIitufSxhdC5wcm90b3R5cGUuZmV0Y2hFdmVudERhdGE9ZnVuY3Rpb24oKXt2YXIgdD16KFwibG9jYWxTdG9yYWdlXCIpLGU9dGhpcy5nZXRTdG9yYWdlS2V5KCkscj10aGlzLmdldFN0b3JhZ2VLZXkoXCJ1dWlkXCIpO2lmKHQpdHJ5e3ZhciBuPXNlbGYubG9jYWxTdG9yYWdlLmdldEl0ZW0oZSk7biYmKHRoaXMuZXZlbnREYXRhPUpTT04ucGFyc2UobikpO3ZhciBpPXNlbGYubG9jYWxTdG9yYWdlLmdldEl0ZW0ocik7aSYmKHRoaXMuYW5vbklkPWkpO31jYXRjaCh0KXt3KFwiVW5hYmxlIHRvIHJlYWQgZnJvbSBMb2NhbFN0b3JhZ2VcIik7fX0sYXQucHJvdG90eXBlLnNhdmVFdmVudERhdGE9ZnVuY3Rpb24oKXt2YXIgdD16KFwibG9jYWxTdG9yYWdlXCIpLGU9dGhpcy5nZXRTdG9yYWdlS2V5KCkscj10aGlzLmdldFN0b3JhZ2VLZXkoXCJ1dWlkXCIpO2lmKHQpdHJ5e3NlbGYubG9jYWxTdG9yYWdlLnNldEl0ZW0ocix0aGlzLmFub25JZCksT2JqZWN0LmtleXModGhpcy5ldmVudERhdGEpLmxlbmd0aD49MSYmc2VsZi5sb2NhbFN0b3JhZ2Uuc2V0SXRlbShlLEpTT04uc3RyaW5naWZ5KHRoaXMuZXZlbnREYXRhKSk7fWNhdGNoKHQpe3coXCJVbmFibGUgdG8gd3JpdGUgdG8gTG9jYWxTdG9yYWdlXCIpO319LGF0LnByb3RvdHlwZS5wcm9jZXNzUmVxdWVzdHM9ZnVuY3Rpb24oKXt9LGF0LnByb3RvdHlwZS5wb3N0RXZlbnQ9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPXRoaXM7aWYoVi5FVkVOVFNfVVJMKXt2YXIgaT1ydChWLkVWRU5UU19VUkwpO2kucGFyYW1zLnB1c2goXCJhY2Nlc3NfdG9rZW49XCIrKFYuQUNDRVNTX1RPS0VOfHxcIlwiKSk7dmFyIGE9e2V2ZW50OnRoaXMudHlwZSxjcmVhdGVkOm5ldyBEYXRlKHQpLnRvSVNPU3RyaW5nKCksc2RrSWRlbnRpZmllcjpcIm1hcGJveC1nbC1qc1wiLHNka1ZlcnNpb246XCIxLjEuMVwiLHNrdUlkOlIsdXNlcklkOnRoaXMuYW5vbklkfSxvPWU/YyhhLGUpOmEscz17dXJsOm50KGkpLGhlYWRlcnM6e1wiQ29udGVudC1UeXBlXCI6XCJ0ZXh0L3BsYWluXCJ9LGJvZHk6SlNPTi5zdHJpbmdpZnkoW29dKX07dGhpcy5wZW5kaW5nUmVxdWVzdD1JdChzLGZ1bmN0aW9uKHQpe24ucGVuZGluZ1JlcXVlc3Q9bnVsbCxyKHQpLG4uc2F2ZUV2ZW50RGF0YSgpLG4ucHJvY2Vzc1JlcXVlc3RzKCk7fSk7fX0sYXQucHJvdG90eXBlLnF1ZXVlUmVxdWVzdD1mdW5jdGlvbih0KXt0aGlzLnF1ZXVlLnB1c2godCksdGhpcy5wcm9jZXNzUmVxdWVzdHMoKTt9O3ZhciBvdCxzdD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5jYWxsKHRoaXMsXCJtYXAubG9hZFwiKSx0aGlzLnN1Y2Nlc3M9e30sdGhpcy5za3VUb2tlbj1cIlwiO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUucG9zdE1hcExvYWRFdmVudD1mdW5jdGlvbih0LGUscil7dGhpcy5za3VUb2tlbj1yLFYuRVZFTlRTX1VSTCYmVi5BQ0NFU1NfVE9LRU4mJkFycmF5LmlzQXJyYXkodCkmJnQuc29tZShmdW5jdGlvbih0KXtyZXR1cm4gTih0KXx8Syh0KX0pJiZ0aGlzLnF1ZXVlUmVxdWVzdCh7aWQ6ZSx0aW1lc3RhbXA6RGF0ZS5ub3coKX0pO30sZS5wcm90b3R5cGUucHJvY2Vzc1JlcXVlc3RzPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcztpZighdGhpcy5wZW5kaW5nUmVxdWVzdCYmMCE9PXRoaXMucXVldWUubGVuZ3RoKXt2YXIgZT10aGlzLnF1ZXVlLnNoaWZ0KCkscj1lLmlkLG49ZS50aW1lc3RhbXA7ciYmdGhpcy5zdWNjZXNzW3JdfHwodGhpcy5hbm9uSWR8fHRoaXMuZmV0Y2hFdmVudERhdGEoKSxkKHRoaXMuYW5vbklkKXx8KHRoaXMuYW5vbklkPXkoKSksdGhpcy5wb3N0RXZlbnQobix7c2t1VG9rZW46dGhpcy5za3VUb2tlbn0sZnVuY3Rpb24oZSl7ZXx8ciYmKHQuc3VjY2Vzc1tyXT0hMCk7fSkpO319LGV9KGF0KSx1dD1uZXcoZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuY2FsbCh0aGlzLFwiYXBwVXNlclR1cm5zdGlsZVwiKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLnBvc3RUdXJuc3RpbGVFdmVudD1mdW5jdGlvbih0KXtWLkVWRU5UU19VUkwmJlYuQUNDRVNTX1RPS0VOJiZBcnJheS5pc0FycmF5KHQpJiZ0LnNvbWUoZnVuY3Rpb24odCl7cmV0dXJuIE4odCl8fEsodCl9KSYmdGhpcy5xdWV1ZVJlcXVlc3QoRGF0ZS5ub3coKSk7fSxlLnByb3RvdHlwZS5wcm9jZXNzUmVxdWVzdHM9ZnVuY3Rpb24oKXt2YXIgdD10aGlzO2lmKCF0aGlzLnBlbmRpbmdSZXF1ZXN0JiYwIT09dGhpcy5xdWV1ZS5sZW5ndGgpe3RoaXMuYW5vbklkJiZ0aGlzLmV2ZW50RGF0YS5sYXN0U3VjY2VzcyYmdGhpcy5ldmVudERhdGEudG9rZW5VfHx0aGlzLmZldGNoRXZlbnREYXRhKCk7dmFyIGU9aXQoVi5BQ0NFU1NfVE9LRU4pLHI9ZT9lLnU6Vi5BQ0NFU1NfVE9LRU4sbj1yIT09dGhpcy5ldmVudERhdGEudG9rZW5VO2QodGhpcy5hbm9uSWQpfHwodGhpcy5hbm9uSWQ9eSgpLG49ITApO3ZhciBpPXRoaXMucXVldWUuc2hpZnQoKTtpZih0aGlzLmV2ZW50RGF0YS5sYXN0U3VjY2Vzcyl7dmFyIGE9bmV3IERhdGUodGhpcy5ldmVudERhdGEubGFzdFN1Y2Nlc3MpLG89bmV3IERhdGUoaSkscz0oaS10aGlzLmV2ZW50RGF0YS5sYXN0U3VjY2VzcykvODY0ZTU7bj1ufHxzPj0xfHxzPC0xfHxhLmdldERhdGUoKSE9PW8uZ2V0RGF0ZSgpO31lbHNlIG49ITA7aWYoIW4pcmV0dXJuIHRoaXMucHJvY2Vzc1JlcXVlc3RzKCk7dGhpcy5wb3N0RXZlbnQoaSx7XCJlbmFibGVkLnRlbGVtZXRyeVwiOiExfSxmdW5jdGlvbihlKXtlfHwodC5ldmVudERhdGEubGFzdFN1Y2Nlc3M9aSx0LmV2ZW50RGF0YS50b2tlblU9cik7fSk7fX0sZX0oYXQpKSxsdD11dC5wb3N0VHVybnN0aWxlRXZlbnQuYmluZCh1dCkscHQ9bmV3IHN0LGN0PXB0LnBvc3RNYXBMb2FkRXZlbnQuYmluZChwdCksaHQ9XCJtYXBib3gtdGlsZXNcIixmdD01MDAseXQ9NTAsZHQ9NDJlNDtmdW5jdGlvbiBtdCh0LGUscil7aWYoc2VsZi5jYWNoZXMpe3ZhciBuPXtzdGF0dXM6ZS5zdGF0dXMsc3RhdHVzVGV4dDplLnN0YXR1c1RleHQsaGVhZGVyczpuZXcgc2VsZi5IZWFkZXJzfTtlLmhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbih0LGUpe3JldHVybiBuLmhlYWRlcnMuc2V0KGUsdCl9KTt2YXIgaT1rKGUuaGVhZGVycy5nZXQoXCJDYWNoZS1Db250cm9sXCIpfHxcIlwiKTtpZighaVtcIm5vLXN0b3JlXCJdKWlbXCJtYXgtYWdlXCJdJiZuLmhlYWRlcnMuc2V0KFwiRXhwaXJlc1wiLG5ldyBEYXRlKHIrMWUzKmlbXCJtYXgtYWdlXCJdKS50b1VUQ1N0cmluZygpKSxuZXcgRGF0ZShuLmhlYWRlcnMuZ2V0KFwiRXhwaXJlc1wiKSkuZ2V0VGltZSgpLXI8ZHR8fGZ1bmN0aW9uKHQsZSl7aWYodm9pZCAwPT09b3QpdHJ5e25ldyBSZXNwb25zZShuZXcgUmVhZGFibGVTdHJlYW0pLG90PSEwO31jYXRjaCh0KXtvdD0hMTt9b3Q/ZSh0LmJvZHkpOnQuYmxvYigpLnRoZW4oZSk7fShlLGZ1bmN0aW9uKGUpe3ZhciByPW5ldyBzZWxmLlJlc3BvbnNlKGUsbik7c2VsZi5jYWNoZXMub3BlbihodCkudGhlbihmdW5jdGlvbihlKXtyZXR1cm4gZS5wdXQodnQodC51cmwpLHIpfSk7fSk7fX1mdW5jdGlvbiB2dCh0KXt2YXIgZT10LmluZGV4T2YoXCI/XCIpO3JldHVybiBlPDA/dDp0LnNsaWNlKDAsZSl9ZnVuY3Rpb24gZ3QodCxlKXtpZighc2VsZi5jYWNoZXMpcmV0dXJuIGUobnVsbCk7dmFyIHI9dnQodC51cmwpO3NlbGYuY2FjaGVzLm9wZW4oaHQpLmNhdGNoKGUpLnRoZW4oZnVuY3Rpb24odCl7dC5tYXRjaChyKS5jYXRjaChlKS50aGVuKGZ1bmN0aW9uKG4pe3ZhciBpPWZ1bmN0aW9uKHQpe2lmKCF0KXJldHVybiAhMTt2YXIgZT1uZXcgRGF0ZSh0LmhlYWRlcnMuZ2V0KFwiRXhwaXJlc1wiKSkscj1rKHQuaGVhZGVycy5nZXQoXCJDYWNoZS1Db250cm9sXCIpfHxcIlwiKTtyZXR1cm4gZT5EYXRlLm5vdygpJiYhcltcIm5vLWNhY2hlXCJdfShuKTt0LmRlbGV0ZShyKSxpJiZ0LnB1dChyLG4uY2xvbmUoKSksZShudWxsLG4saSk7fSk7fSk7fXZhciB4dD0xLzA7dmFyIGJ0PXtVbmtub3duOlwiVW5rbm93blwiLFN0eWxlOlwiU3R5bGVcIixTb3VyY2U6XCJTb3VyY2VcIixUaWxlOlwiVGlsZVwiLEdseXBoczpcIkdseXBoc1wiLFNwcml0ZUltYWdlOlwiU3ByaXRlSW1hZ2VcIixTcHJpdGVKU09OOlwiU3ByaXRlSlNPTlwiLEltYWdlOlwiSW1hZ2VcIn07XCJmdW5jdGlvblwiPT10eXBlb2YgT2JqZWN0LmZyZWV6ZSYmT2JqZWN0LmZyZWV6ZShidCk7dmFyIF90PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSxyLG4pezQwMT09PXImJksobikmJihlKz1cIjogeW91IG1heSBoYXZlIHByb3ZpZGVkIGFuIGludmFsaWQgTWFwYm94IGFjY2VzcyB0b2tlbi4gU2VlIGh0dHBzOi8vd3d3Lm1hcGJveC5jb20vYXBpLWRvY3VtZW50YXRpb24vI2FjY2Vzcy10b2tlbnMtYW5kLXRva2VuLXNjb3Blc1wiKSx0LmNhbGwodGhpcyxlKSx0aGlzLnN0YXR1cz1yLHRoaXMudXJsPW4sdGhpcy5uYW1lPXRoaXMuY29uc3RydWN0b3IubmFtZSx0aGlzLm1lc3NhZ2U9ZTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubmFtZStcIjogXCIrdGhpcy5tZXNzYWdlK1wiIChcIit0aGlzLnN0YXR1cytcIik6IFwiK3RoaXMudXJsfSxlfShFcnJvcik7ZnVuY3Rpb24gd3QoKXtyZXR1cm4gXCJ1bmRlZmluZWRcIiE9dHlwZW9mIFdvcmtlckdsb2JhbFNjb3BlJiZcInVuZGVmaW5lZFwiIT10eXBlb2Ygc2VsZiYmc2VsZiBpbnN0YW5jZW9mIFdvcmtlckdsb2JhbFNjb3BlfXZhciBBdD13dCgpP2Z1bmN0aW9uKCl7cmV0dXJuIHNlbGYud29ya2VyJiZzZWxmLndvcmtlci5yZWZlcnJlcn06ZnVuY3Rpb24oKXt2YXIgdD1zZWxmLmxvY2F0aW9uLm9yaWdpbjtpZih0JiZcIm51bGxcIiE9PXQmJlwiZmlsZTovL1wiIT09dClyZXR1cm4gdCtzZWxmLmxvY2F0aW9uLnBhdGhuYW1lfTtmdW5jdGlvbiBTdCh0LGUpe3ZhciByLG49bmV3IHNlbGYuQWJvcnRDb250cm9sbGVyLGk9bmV3IHNlbGYuUmVxdWVzdCh0LnVybCx7bWV0aG9kOnQubWV0aG9kfHxcIkdFVFwiLGJvZHk6dC5ib2R5LGNyZWRlbnRpYWxzOnQuY3JlZGVudGlhbHMsaGVhZGVyczp0LmhlYWRlcnMscmVmZXJyZXI6QXQoKSxzaWduYWw6bi5zaWduYWx9KSxhPSExLG89ITEscz0ocj1pLnVybCkuaW5kZXhPZihcInNrdT1cIik+MCYmSyhyKTtcImpzb25cIj09PXQudHlwZSYmaS5oZWFkZXJzLnNldChcIkFjY2VwdFwiLFwiYXBwbGljYXRpb24vanNvblwiKTt2YXIgdT1mdW5jdGlvbihyLG4sYSl7aWYoIW8pe2lmKHImJlwiU2VjdXJpdHlFcnJvclwiIT09ci5tZXNzYWdlJiZ3KHIpLG4mJmEpcmV0dXJuIGwobik7dmFyIHU9RGF0ZS5ub3coKTtzZWxmLmZldGNoKGkpLnRoZW4oZnVuY3Rpb24ocil7aWYoci5vayl7dmFyIG49cz9yLmNsb25lKCk6bnVsbDtyZXR1cm4gbChyLG4sdSl9cmV0dXJuIGUobmV3IF90KHIuc3RhdHVzVGV4dCxyLnN0YXR1cyx0LnVybCkpfSkuY2F0Y2goZnVuY3Rpb24odCl7MjAhPT10LmNvZGUmJmUobmV3IEVycm9yKHQubWVzc2FnZSkpO30pO319LGw9ZnVuY3Rpb24ocixuLHMpeyhcImFycmF5QnVmZmVyXCI9PT10LnR5cGU/ci5hcnJheUJ1ZmZlcigpOlwianNvblwiPT09dC50eXBlP3IuanNvbigpOnIudGV4dCgpKS50aGVuKGZ1bmN0aW9uKHQpe298fChuJiZzJiZtdChpLG4scyksYT0hMCxlKG51bGwsdCxyLmhlYWRlcnMuZ2V0KFwiQ2FjaGUtQ29udHJvbFwiKSxyLmhlYWRlcnMuZ2V0KFwiRXhwaXJlc1wiKSkpO30pLmNhdGNoKGZ1bmN0aW9uKHQpe3JldHVybiBlKG5ldyBFcnJvcih0Lm1lc3NhZ2UpKX0pO307cmV0dXJuIHM/Z3QoaSx1KTp1KG51bGwsbnVsbCkse2NhbmNlbDpmdW5jdGlvbigpe289ITAsYXx8bi5hYm9ydCgpO319fXZhciBrdD1mdW5jdGlvbih0LGUpe2lmKCEvXmZpbGU6Ly50ZXN0KHQudXJsKSl7aWYoc2VsZi5mZXRjaCYmc2VsZi5SZXF1ZXN0JiZzZWxmLkFib3J0Q29udHJvbGxlciYmc2VsZi5SZXF1ZXN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eShcInNpZ25hbFwiKSlyZXR1cm4gU3QodCxlKTtpZih3dCgpJiZzZWxmLndvcmtlciYmc2VsZi53b3JrZXIuYWN0b3IpcmV0dXJuIHNlbGYud29ya2VyLmFjdG9yLnNlbmQoXCJnZXRSZXNvdXJjZVwiLHQsZSl9cmV0dXJuIGZ1bmN0aW9uKHQsZSl7dmFyIHI9bmV3IHNlbGYuWE1MSHR0cFJlcXVlc3Q7Zm9yKHZhciBuIGluIHIub3Blbih0Lm1ldGhvZHx8XCJHRVRcIix0LnVybCwhMCksXCJhcnJheUJ1ZmZlclwiPT09dC50eXBlJiYoci5yZXNwb25zZVR5cGU9XCJhcnJheWJ1ZmZlclwiKSx0LmhlYWRlcnMpci5zZXRSZXF1ZXN0SGVhZGVyKG4sdC5oZWFkZXJzW25dKTtyZXR1cm4gXCJqc29uXCI9PT10LnR5cGUmJnIuc2V0UmVxdWVzdEhlYWRlcihcIkFjY2VwdFwiLFwiYXBwbGljYXRpb24vanNvblwiKSxyLndpdGhDcmVkZW50aWFscz1cImluY2x1ZGVcIj09PXQuY3JlZGVudGlhbHMsci5vbmVycm9yPWZ1bmN0aW9uKCl7ZShuZXcgRXJyb3Ioci5zdGF0dXNUZXh0KSk7fSxyLm9ubG9hZD1mdW5jdGlvbigpe2lmKChyLnN0YXR1cz49MjAwJiZyLnN0YXR1czwzMDB8fDA9PT1yLnN0YXR1cykmJm51bGwhPT1yLnJlc3BvbnNlKXt2YXIgbj1yLnJlc3BvbnNlO2lmKFwianNvblwiPT09dC50eXBlKXRyeXtuPUpTT04ucGFyc2Uoci5yZXNwb25zZSk7fWNhdGNoKHQpe3JldHVybiBlKHQpfWUobnVsbCxuLHIuZ2V0UmVzcG9uc2VIZWFkZXIoXCJDYWNoZS1Db250cm9sXCIpLHIuZ2V0UmVzcG9uc2VIZWFkZXIoXCJFeHBpcmVzXCIpKTt9ZWxzZSBlKG5ldyBfdChyLnN0YXR1c1RleHQsci5zdGF0dXMsdC51cmwpKTt9LHIuc2VuZCh0LmJvZHkpLHtjYW5jZWw6ZnVuY3Rpb24oKXtyZXR1cm4gci5hYm9ydCgpfX19KHQsZSl9LHp0PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIGt0KGModCx7dHlwZTpcImFycmF5QnVmZmVyXCJ9KSxlKX0sSXQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4ga3QoYyh0LHttZXRob2Q6XCJQT1NUXCJ9KSxlKX07dmFyIEJ0LEN0O0J0PVtdLEN0PTA7dmFyIEV0PWZ1bmN0aW9uKHQsZSl7aWYoQ3Q+PVYuTUFYX1BBUkFMTEVMX0lNQUdFX1JFUVVFU1RTKXt2YXIgcj17cmVxdWVzdFBhcmFtZXRlcnM6dCxjYWxsYmFjazplLGNhbmNlbGxlZDohMSxjYW5jZWw6ZnVuY3Rpb24oKXt0aGlzLmNhbmNlbGxlZD0hMDt9fTtyZXR1cm4gQnQucHVzaChyKSxyfUN0Kys7dmFyIG49ITEsaT1mdW5jdGlvbigpe2lmKCFuKWZvcihuPSEwLEN0LS07QnQubGVuZ3RoJiZDdDxWLk1BWF9QQVJBTExFTF9JTUFHRV9SRVFVRVNUUzspe3ZhciB0PUJ0LnNoaWZ0KCksZT10LnJlcXVlc3RQYXJhbWV0ZXJzLHI9dC5jYWxsYmFjazt0LmNhbmNlbGxlZHx8KHQuY2FuY2VsPUV0KGUscikuY2FuY2VsKTt9fSxhPXp0KHQsZnVuY3Rpb24odCxyLG4sYSl7aWYoaSgpLHQpZSh0KTtlbHNlIGlmKHIpe3ZhciBvPW5ldyBzZWxmLkltYWdlLHM9c2VsZi5VUkx8fHNlbGYud2Via2l0VVJMO28ub25sb2FkPWZ1bmN0aW9uKCl7ZShudWxsLG8pLHMucmV2b2tlT2JqZWN0VVJMKG8uc3JjKTt9LG8ub25lcnJvcj1mdW5jdGlvbigpe3JldHVybiBlKG5ldyBFcnJvcihcIkNvdWxkIG5vdCBsb2FkIGltYWdlLiBQbGVhc2UgbWFrZSBzdXJlIHRvIHVzZSBhIHN1cHBvcnRlZCBpbWFnZSB0eXBlIHN1Y2ggYXMgUE5HIG9yIEpQRUcuIE5vdGUgdGhhdCBTVkdzIGFyZSBub3Qgc3VwcG9ydGVkLlwiKSl9O3ZhciB1PW5ldyBzZWxmLkJsb2IoW25ldyBVaW50OEFycmF5KHIpXSx7dHlwZTpcImltYWdlL3BuZ1wifSk7by5jYWNoZUNvbnRyb2w9bixvLmV4cGlyZXM9YSxvLnNyYz1yLmJ5dGVMZW5ndGg/cy5jcmVhdGVPYmplY3RVUkwodSk6XCJkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFFQUFBQUJDQVlBQUFBZkZjU0pBQUFBQzBsRVFWUVlWMk5nQUFJQUFBVUFBYXJWeUZFQUFBQUFTVVZPUks1Q1lJST1cIjt9fSk7cmV0dXJuIHtjYW5jZWw6ZnVuY3Rpb24oKXthLmNhbmNlbCgpLGkoKTt9fX07ZnVuY3Rpb24gTXQodCxlLHIpe3JbdF0mJi0xIT09clt0XS5pbmRleE9mKGUpfHwoclt0XT1yW3RdfHxbXSxyW3RdLnB1c2goZSkpO31mdW5jdGlvbiBUdCh0LGUscil7aWYociYmclt0XSl7dmFyIG49clt0XS5pbmRleE9mKGUpOy0xIT09biYmclt0XS5zcGxpY2UobiwxKTt9fXZhciBQdD1mdW5jdGlvbih0LGUpe3ZvaWQgMD09PWUmJihlPXt9KSxjKHRoaXMsZSksdGhpcy50eXBlPXQ7fSxWdD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUscil7dm9pZCAwPT09ciYmKHI9e30pLHQuY2FsbCh0aGlzLFwiZXJyb3JcIixjKHtlcnJvcjplfSxyKSk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlfShQdCksRnQ9ZnVuY3Rpb24oKXt9O0Z0LnByb3RvdHlwZS5vbj1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLl9saXN0ZW5lcnM9dGhpcy5fbGlzdGVuZXJzfHx7fSxNdCh0LGUsdGhpcy5fbGlzdGVuZXJzKSx0aGlzfSxGdC5wcm90b3R5cGUub2ZmPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIFR0KHQsZSx0aGlzLl9saXN0ZW5lcnMpLFR0KHQsZSx0aGlzLl9vbmVUaW1lTGlzdGVuZXJzKSx0aGlzfSxGdC5wcm90b3R5cGUub25jZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLl9vbmVUaW1lTGlzdGVuZXJzPXRoaXMuX29uZVRpbWVMaXN0ZW5lcnN8fHt9LE10KHQsZSx0aGlzLl9vbmVUaW1lTGlzdGVuZXJzKSx0aGlzfSxGdC5wcm90b3R5cGUuZmlyZT1mdW5jdGlvbih0LGUpe1wic3RyaW5nXCI9PXR5cGVvZiB0JiYodD1uZXcgUHQodCxlfHx7fSkpO3ZhciByPXQudHlwZTtpZih0aGlzLmxpc3RlbnMocikpe3QudGFyZ2V0PXRoaXM7Zm9yKHZhciBuPTAsaT10aGlzLl9saXN0ZW5lcnMmJnRoaXMuX2xpc3RlbmVyc1tyXT90aGlzLl9saXN0ZW5lcnNbcl0uc2xpY2UoKTpbXTtuPGkubGVuZ3RoO24rPTEpe2lbbl0uY2FsbCh0aGlzLHQpO31mb3IodmFyIGE9MCxvPXRoaXMuX29uZVRpbWVMaXN0ZW5lcnMmJnRoaXMuX29uZVRpbWVMaXN0ZW5lcnNbcl0/dGhpcy5fb25lVGltZUxpc3RlbmVyc1tyXS5zbGljZSgpOltdO2E8by5sZW5ndGg7YSs9MSl7dmFyIHM9b1thXTtUdChyLHMsdGhpcy5fb25lVGltZUxpc3RlbmVycykscy5jYWxsKHRoaXMsdCk7fXZhciB1PXRoaXMuX2V2ZW50ZWRQYXJlbnQ7dSYmKGModCxcImZ1bmN0aW9uXCI9PXR5cGVvZiB0aGlzLl9ldmVudGVkUGFyZW50RGF0YT90aGlzLl9ldmVudGVkUGFyZW50RGF0YSgpOnRoaXMuX2V2ZW50ZWRQYXJlbnREYXRhKSx1LmZpcmUodCkpO31lbHNlIHQgaW5zdGFuY2VvZiBWdCYmY29uc29sZS5lcnJvcih0LmVycm9yKTtyZXR1cm4gdGhpc30sRnQucHJvdG90eXBlLmxpc3RlbnM9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2xpc3RlbmVycyYmdGhpcy5fbGlzdGVuZXJzW3RdJiZ0aGlzLl9saXN0ZW5lcnNbdF0ubGVuZ3RoPjB8fHRoaXMuX29uZVRpbWVMaXN0ZW5lcnMmJnRoaXMuX29uZVRpbWVMaXN0ZW5lcnNbdF0mJnRoaXMuX29uZVRpbWVMaXN0ZW5lcnNbdF0ubGVuZ3RoPjB8fHRoaXMuX2V2ZW50ZWRQYXJlbnQmJnRoaXMuX2V2ZW50ZWRQYXJlbnQubGlzdGVucyh0KX0sRnQucHJvdG90eXBlLnNldEV2ZW50ZWRQYXJlbnQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5fZXZlbnRlZFBhcmVudD10LHRoaXMuX2V2ZW50ZWRQYXJlbnREYXRhPWUsdGhpc307dmFyIEx0PXskdmVyc2lvbjo4LCRyb290Ont2ZXJzaW9uOntyZXF1aXJlZDohMCx0eXBlOlwiZW51bVwiLHZhbHVlczpbOF19LG5hbWU6e3R5cGU6XCJzdHJpbmdcIn0sbWV0YWRhdGE6e3R5cGU6XCIqXCJ9LGNlbnRlcjp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJudW1iZXJcIn0sem9vbTp7dHlwZTpcIm51bWJlclwifSxiZWFyaW5nOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLHBlcmlvZDozNjAsdW5pdHM6XCJkZWdyZWVzXCJ9LHBpdGNoOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLHVuaXRzOlwiZGVncmVlc1wifSxsaWdodDp7dHlwZTpcImxpZ2h0XCJ9LHNvdXJjZXM6e3JlcXVpcmVkOiEwLHR5cGU6XCJzb3VyY2VzXCJ9LHNwcml0ZTp7dHlwZTpcInN0cmluZ1wifSxnbHlwaHM6e3R5cGU6XCJzdHJpbmdcIn0sdHJhbnNpdGlvbjp7dHlwZTpcInRyYW5zaXRpb25cIn0sbGF5ZXJzOntyZXF1aXJlZDohMCx0eXBlOlwiYXJyYXlcIix2YWx1ZTpcImxheWVyXCJ9fSxzb3VyY2VzOntcIipcIjp7dHlwZTpcInNvdXJjZVwifX0sc291cmNlOltcInNvdXJjZV92ZWN0b3JcIixcInNvdXJjZV9yYXN0ZXJcIixcInNvdXJjZV9yYXN0ZXJfZGVtXCIsXCJzb3VyY2VfZ2VvanNvblwiLFwic291cmNlX3ZpZGVvXCIsXCJzb3VyY2VfaW1hZ2VcIl0sc291cmNlX3ZlY3Rvcjp7dHlwZTp7cmVxdWlyZWQ6ITAsdHlwZTpcImVudW1cIix2YWx1ZXM6e3ZlY3Rvcjp7fX19LHVybDp7dHlwZTpcInN0cmluZ1wifSx0aWxlczp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJzdHJpbmdcIn0sYm91bmRzOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcIm51bWJlclwiLGxlbmd0aDo0LGRlZmF1bHQ6Wy0xODAsLTg1LjA1MTEyOSwxODAsODUuMDUxMTI5XX0sc2NoZW1lOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7eHl6Ont9LHRtczp7fX0sZGVmYXVsdDpcInh5elwifSxtaW56b29tOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowfSxtYXh6b29tOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoyMn0sYXR0cmlidXRpb246e3R5cGU6XCJzdHJpbmdcIn0sXCIqXCI6e3R5cGU6XCIqXCJ9fSxzb3VyY2VfcmFzdGVyOnt0eXBlOntyZXF1aXJlZDohMCx0eXBlOlwiZW51bVwiLHZhbHVlczp7cmFzdGVyOnt9fX0sdXJsOnt0eXBlOlwic3RyaW5nXCJ9LHRpbGVzOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcInN0cmluZ1wifSxib3VuZHM6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjQsZGVmYXVsdDpbLTE4MCwtODUuMDUxMTI5LDE4MCw4NS4wNTExMjldfSxtaW56b29tOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowfSxtYXh6b29tOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoyMn0sdGlsZVNpemU6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjUxMix1bml0czpcInBpeGVsc1wifSxzY2hlbWU6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnt4eXo6e30sdG1zOnt9fSxkZWZhdWx0OlwieHl6XCJ9LGF0dHJpYnV0aW9uOnt0eXBlOlwic3RyaW5nXCJ9LFwiKlwiOnt0eXBlOlwiKlwifX0sc291cmNlX3Jhc3Rlcl9kZW06e3R5cGU6e3JlcXVpcmVkOiEwLHR5cGU6XCJlbnVtXCIsdmFsdWVzOntcInJhc3Rlci1kZW1cIjp7fX19LHVybDp7dHlwZTpcInN0cmluZ1wifSx0aWxlczp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJzdHJpbmdcIn0sYm91bmRzOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcIm51bWJlclwiLGxlbmd0aDo0LGRlZmF1bHQ6Wy0xODAsLTg1LjA1MTEyOSwxODAsODUuMDUxMTI5XX0sbWluem9vbTp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MH0sbWF4em9vbTp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MjJ9LHRpbGVTaXplOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDo1MTIsdW5pdHM6XCJwaXhlbHNcIn0sYXR0cmlidXRpb246e3R5cGU6XCJzdHJpbmdcIn0sZW5jb2Rpbmc6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnt0ZXJyYXJpdW06e30sbWFwYm94Ont9fSxkZWZhdWx0OlwibWFwYm94XCJ9LFwiKlwiOnt0eXBlOlwiKlwifX0sc291cmNlX2dlb2pzb246e3R5cGU6e3JlcXVpcmVkOiEwLHR5cGU6XCJlbnVtXCIsdmFsdWVzOntnZW9qc29uOnt9fX0sZGF0YTp7dHlwZTpcIipcIn0sbWF4em9vbTp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MTh9LGF0dHJpYnV0aW9uOnt0eXBlOlwic3RyaW5nXCJ9LGJ1ZmZlcjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MTI4LG1heGltdW06NTEyLG1pbmltdW06MH0sdG9sZXJhbmNlOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDouMzc1fSxjbHVzdGVyOnt0eXBlOlwiYm9vbGVhblwiLGRlZmF1bHQ6ITF9LGNsdXN0ZXJSYWRpdXM6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjUwLG1pbmltdW06MH0sY2x1c3Rlck1heFpvb206e3R5cGU6XCJudW1iZXJcIn0sY2x1c3RlclByb3BlcnRpZXM6e3R5cGU6XCIqXCJ9LGxpbmVNZXRyaWNzOnt0eXBlOlwiYm9vbGVhblwiLGRlZmF1bHQ6ITF9LGdlbmVyYXRlSWQ6e3R5cGU6XCJib29sZWFuXCIsZGVmYXVsdDohMX19LHNvdXJjZV92aWRlbzp7dHlwZTp7cmVxdWlyZWQ6ITAsdHlwZTpcImVudW1cIix2YWx1ZXM6e3ZpZGVvOnt9fX0sdXJsczp7cmVxdWlyZWQ6ITAsdHlwZTpcImFycmF5XCIsdmFsdWU6XCJzdHJpbmdcIn0sY29vcmRpbmF0ZXM6e3JlcXVpcmVkOiEwLHR5cGU6XCJhcnJheVwiLGxlbmd0aDo0LHZhbHVlOnt0eXBlOlwiYXJyYXlcIixsZW5ndGg6Mix2YWx1ZTpcIm51bWJlclwifX19LHNvdXJjZV9pbWFnZTp7dHlwZTp7cmVxdWlyZWQ6ITAsdHlwZTpcImVudW1cIix2YWx1ZXM6e2ltYWdlOnt9fX0sdXJsOntyZXF1aXJlZDohMCx0eXBlOlwic3RyaW5nXCJ9LGNvb3JkaW5hdGVzOntyZXF1aXJlZDohMCx0eXBlOlwiYXJyYXlcIixsZW5ndGg6NCx2YWx1ZTp7dHlwZTpcImFycmF5XCIsbGVuZ3RoOjIsdmFsdWU6XCJudW1iZXJcIn19fSxsYXllcjp7aWQ6e3R5cGU6XCJzdHJpbmdcIixyZXF1aXJlZDohMH0sdHlwZTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e2ZpbGw6e30sbGluZTp7fSxzeW1ib2w6e30sY2lyY2xlOnt9LGhlYXRtYXA6e30sXCJmaWxsLWV4dHJ1c2lvblwiOnt9LHJhc3Rlcjp7fSxoaWxsc2hhZGU6e30sYmFja2dyb3VuZDp7fX0scmVxdWlyZWQ6ITB9LG1ldGFkYXRhOnt0eXBlOlwiKlwifSxzb3VyY2U6e3R5cGU6XCJzdHJpbmdcIn0sXCJzb3VyY2UtbGF5ZXJcIjp7dHlwZTpcInN0cmluZ1wifSxtaW56b29tOnt0eXBlOlwibnVtYmVyXCIsbWluaW11bTowLG1heGltdW06MjR9LG1heHpvb206e3R5cGU6XCJudW1iZXJcIixtaW5pbXVtOjAsbWF4aW11bToyNH0sZmlsdGVyOnt0eXBlOlwiZmlsdGVyXCJ9LGxheW91dDp7dHlwZTpcImxheW91dFwifSxwYWludDp7dHlwZTpcInBhaW50XCJ9fSxsYXlvdXQ6W1wibGF5b3V0X2ZpbGxcIixcImxheW91dF9saW5lXCIsXCJsYXlvdXRfY2lyY2xlXCIsXCJsYXlvdXRfaGVhdG1hcFwiLFwibGF5b3V0X2ZpbGwtZXh0cnVzaW9uXCIsXCJsYXlvdXRfc3ltYm9sXCIsXCJsYXlvdXRfcmFzdGVyXCIsXCJsYXlvdXRfaGlsbHNoYWRlXCIsXCJsYXlvdXRfYmFja2dyb3VuZFwiXSxsYXlvdXRfYmFja2dyb3VuZDp7dmlzaWJpbGl0eTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e3Zpc2libGU6e30sbm9uZTp7fX0sZGVmYXVsdDpcInZpc2libGVcIixcInByb3BlcnR5LXR5cGVcIjpcImNvbnN0YW50XCJ9fSxsYXlvdXRfZmlsbDp7dmlzaWJpbGl0eTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e3Zpc2libGU6e30sbm9uZTp7fX0sZGVmYXVsdDpcInZpc2libGVcIixcInByb3BlcnR5LXR5cGVcIjpcImNvbnN0YW50XCJ9fSxsYXlvdXRfY2lyY2xlOnt2aXNpYmlsaXR5Ont0eXBlOlwiZW51bVwiLHZhbHVlczp7dmlzaWJsZTp7fSxub25lOnt9fSxkZWZhdWx0OlwidmlzaWJsZVwiLFwicHJvcGVydHktdHlwZVwiOlwiY29uc3RhbnRcIn19LGxheW91dF9oZWF0bWFwOnt2aXNpYmlsaXR5Ont0eXBlOlwiZW51bVwiLHZhbHVlczp7dmlzaWJsZTp7fSxub25lOnt9fSxkZWZhdWx0OlwidmlzaWJsZVwiLFwicHJvcGVydHktdHlwZVwiOlwiY29uc3RhbnRcIn19LFwibGF5b3V0X2ZpbGwtZXh0cnVzaW9uXCI6e3Zpc2liaWxpdHk6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnt2aXNpYmxlOnt9LG5vbmU6e319LGRlZmF1bHQ6XCJ2aXNpYmxlXCIsXCJwcm9wZXJ0eS10eXBlXCI6XCJjb25zdGFudFwifX0sbGF5b3V0X2xpbmU6e1wibGluZS1jYXBcIjp7dHlwZTpcImVudW1cIix2YWx1ZXM6e2J1dHQ6e30scm91bmQ6e30sc3F1YXJlOnt9fSxkZWZhdWx0OlwiYnV0dFwiLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImxpbmUtam9pblwiOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7YmV2ZWw6e30scm91bmQ6e30sbWl0ZXI6e319LGRlZmF1bHQ6XCJtaXRlclwiLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJsaW5lLW1pdGVyLWxpbWl0XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjIscmVxdWlyZXM6W3tcImxpbmUtam9pblwiOlwibWl0ZXJcIn1dLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImxpbmUtcm91bmQtbGltaXRcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MS4wNSxyZXF1aXJlczpbe1wibGluZS1qb2luXCI6XCJyb3VuZFwifV0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LHZpc2liaWxpdHk6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnt2aXNpYmxlOnt9LG5vbmU6e319LGRlZmF1bHQ6XCJ2aXNpYmxlXCIsXCJwcm9wZXJ0eS10eXBlXCI6XCJjb25zdGFudFwifX0sbGF5b3V0X3N5bWJvbDp7XCJzeW1ib2wtcGxhY2VtZW50XCI6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOntwb2ludDp7fSxsaW5lOnt9LFwibGluZS1jZW50ZXJcIjp7fX0sZGVmYXVsdDpcInBvaW50XCIsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwic3ltYm9sLXNwYWNpbmdcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MjUwLG1pbmltdW06MSx1bml0czpcInBpeGVsc1wiLHJlcXVpcmVzOlt7XCJzeW1ib2wtcGxhY2VtZW50XCI6XCJsaW5lXCJ9XSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJzeW1ib2wtYXZvaWQtZWRnZXNcIjp7dHlwZTpcImJvb2xlYW5cIixkZWZhdWx0OiExLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcInN5bWJvbC1zb3J0LWtleVwiOnt0eXBlOlwibnVtYmVyXCIsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcInN5bWJvbC16LW9yZGVyXCI6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnthdXRvOnt9LFwidmlld3BvcnQteVwiOnt9LHNvdXJjZTp7fX0sZGVmYXVsdDpcImF1dG9cIixleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJpY29uLWFsbG93LW92ZXJsYXBcIjp7dHlwZTpcImJvb2xlYW5cIixkZWZhdWx0OiExLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiaWNvbi1pZ25vcmUtcGxhY2VtZW50XCI6e3R5cGU6XCJib29sZWFuXCIsZGVmYXVsdDohMSxyZXF1aXJlczpbXCJpY29uLWltYWdlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImljb24tb3B0aW9uYWxcIjp7dHlwZTpcImJvb2xlYW5cIixkZWZhdWx0OiExLHJlcXVpcmVzOltcImljb24taW1hZ2VcIixcInRleHQtZmllbGRcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjp7dHlwZTpcImVudW1cIix2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fSxhdXRvOnt9fSxkZWZhdWx0OlwiYXV0b1wiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiaWNvbi1zaXplXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLHVuaXRzOlwiZmFjdG9yIG9mIHRoZSBvcmlnaW5hbCBpY29uIHNpemVcIixyZXF1aXJlczpbXCJpY29uLWltYWdlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJpY29uLXRleHQtZml0XCI6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOntub25lOnt9LHdpZHRoOnt9LGhlaWdodDp7fSxib3RoOnt9fSxkZWZhdWx0Olwibm9uZVwiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIixcInRleHQtZmllbGRcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiaWNvbi10ZXh0LWZpdC1wYWRkaW5nXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjQsZGVmYXVsdDpbMCwwLDAsMF0sdW5pdHM6XCJwaXhlbHNcIixyZXF1aXJlczpbXCJpY29uLWltYWdlXCIsXCJ0ZXh0LWZpZWxkXCIse1wiaWNvbi10ZXh0LWZpdFwiOltcImJvdGhcIixcIndpZHRoXCIsXCJoZWlnaHRcIl19XSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJpY29uLWltYWdlXCI6e3R5cGU6XCJzdHJpbmdcIix0b2tlbnM6ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcImljb24tcm90YXRlXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjAscGVyaW9kOjM2MCx1bml0czpcImRlZ3JlZXNcIixyZXF1aXJlczpbXCJpY29uLWltYWdlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJpY29uLXBhZGRpbmdcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MixtaW5pbXVtOjAsdW5pdHM6XCJwaXhlbHNcIixyZXF1aXJlczpbXCJpY29uLWltYWdlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImljb24ta2VlcC11cHJpZ2h0XCI6e3R5cGU6XCJib29sZWFuXCIsZGVmYXVsdDohMSxyZXF1aXJlczpbXCJpY29uLWltYWdlXCIse1wiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIjpcIm1hcFwifSx7XCJzeW1ib2wtcGxhY2VtZW50XCI6W1wibGluZVwiLFwibGluZS1jZW50ZXJcIl19XSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJpY29uLW9mZnNldFwiOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcIm51bWJlclwiLGxlbmd0aDoyLGRlZmF1bHQ6WzAsMF0scmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwiaWNvbi1hbmNob3JcIjp7dHlwZTpcImVudW1cIix2YWx1ZXM6e2NlbnRlcjp7fSxsZWZ0Ont9LHJpZ2h0Ont9LHRvcDp7fSxib3R0b206e30sXCJ0b3AtbGVmdFwiOnt9LFwidG9wLXJpZ2h0XCI6e30sXCJib3R0b20tbGVmdFwiOnt9LFwiYm90dG9tLXJpZ2h0XCI6e319LGRlZmF1bHQ6XCJjZW50ZXJcIixyZXF1aXJlczpbXCJpY29uLWltYWdlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJpY29uLXBpdGNoLWFsaWdubWVudFwiOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7bWFwOnt9LHZpZXdwb3J0Ont9LGF1dG86e319LGRlZmF1bHQ6XCJhdXRvXCIscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJ0ZXh0LXBpdGNoLWFsaWdubWVudFwiOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7bWFwOnt9LHZpZXdwb3J0Ont9LGF1dG86e319LGRlZmF1bHQ6XCJhdXRvXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJ0ZXh0LXJvdGF0aW9uLWFsaWdubWVudFwiOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7bWFwOnt9LHZpZXdwb3J0Ont9LGF1dG86e319LGRlZmF1bHQ6XCJhdXRvXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJ0ZXh0LWZpZWxkXCI6e3R5cGU6XCJmb3JtYXR0ZWRcIixkZWZhdWx0OlwiXCIsdG9rZW5zOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJ0ZXh0LWZvbnRcIjp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJzdHJpbmdcIixkZWZhdWx0OltcIk9wZW4gU2FucyBSZWd1bGFyXCIsXCJBcmlhbCBVbmljb2RlIE1TIFJlZ3VsYXJcIl0scmVxdWlyZXM6W1widGV4dC1maWVsZFwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwidGV4dC1zaXplXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjE2LG1pbmltdW06MCx1bml0czpcInBpeGVsc1wiLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcInRleHQtbWF4LXdpZHRoXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEwLG1pbmltdW06MCx1bml0czpcImVtc1wiLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcInRleHQtbGluZS1oZWlnaHRcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MS4yLHVuaXRzOlwiZW1zXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJ0ZXh0LWxldHRlci1zcGFjaW5nXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjAsdW5pdHM6XCJlbXNcIixyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJ0ZXh0LWp1c3RpZnlcIjp7dHlwZTpcImVudW1cIix2YWx1ZXM6e2F1dG86e30sbGVmdDp7fSxjZW50ZXI6e30scmlnaHQ6e319LGRlZmF1bHQ6XCJjZW50ZXJcIixyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJ0ZXh0LXJhZGlhbC1vZmZzZXRcIjp7dHlwZTpcIm51bWJlclwiLHVuaXRzOlwiZW1zXCIsZGVmYXVsdDowLHJlcXVpcmVzOlt7XCIhXCI6XCJ0ZXh0LW9mZnNldFwifV0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwiLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19fSxcInRleHQtdmFyaWFibGUtYW5jaG9yXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwiZW51bVwiLHZhbHVlczp7Y2VudGVyOnt9LGxlZnQ6e30scmlnaHQ6e30sdG9wOnt9LGJvdHRvbTp7fSxcInRvcC1sZWZ0XCI6e30sXCJ0b3AtcmlnaHRcIjp7fSxcImJvdHRvbS1sZWZ0XCI6e30sXCJib3R0b20tcmlnaHRcIjp7fX0scmVxdWlyZXM6W3tcIiFcIjpcInRleHQtYW5jaG9yXCJ9LHtcIiFcIjpcInRleHQtb2Zmc2V0XCJ9LHtcInN5bWJvbC1wbGFjZW1lbnRcIjpbXCJwb2ludFwiXX1dLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcInRleHQtYW5jaG9yXCI6e3R5cGU6XCJlbnVtXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXSx2YWx1ZXM6e2NlbnRlcjp7fSxsZWZ0Ont9LHJpZ2h0Ont9LHRvcDp7fSxib3R0b206e30sXCJ0b3AtbGVmdFwiOnt9LFwidG9wLXJpZ2h0XCI6e30sXCJib3R0b20tbGVmdFwiOnt9LFwiYm90dG9tLXJpZ2h0XCI6e319LGRlZmF1bHQ6XCJjZW50ZXJcIixleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwidGV4dC1tYXgtYW5nbGVcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6NDUsdW5pdHM6XCJkZWdyZWVzXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiLHtcInN5bWJvbC1wbGFjZW1lbnRcIjpbXCJsaW5lXCIsXCJsaW5lLWNlbnRlclwiXX1dLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcInRleHQtcm90YXRlXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjAscGVyaW9kOjM2MCx1bml0czpcImRlZ3JlZXNcIixyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJ0ZXh0LXBhZGRpbmdcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MixtaW5pbXVtOjAsdW5pdHM6XCJwaXhlbHNcIixyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcInRleHQta2VlcC11cHJpZ2h0XCI6e3R5cGU6XCJib29sZWFuXCIsZGVmYXVsdDohMCxyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCIse1widGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjpcIm1hcFwifSx7XCJzeW1ib2wtcGxhY2VtZW50XCI6W1wibGluZVwiLFwibGluZS1jZW50ZXJcIl19XSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJ0ZXh0LXRyYW5zZm9ybVwiOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7bm9uZTp7fSx1cHBlcmNhc2U6e30sbG93ZXJjYXNlOnt9fSxkZWZhdWx0Olwibm9uZVwiLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcInRleHQtb2Zmc2V0XCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsdW5pdHM6XCJlbXNcIixsZW5ndGg6MixkZWZhdWx0OlswLDBdLHJlcXVpcmVzOltcInRleHQtZmllbGRcIix7XCIhXCI6XCJ0ZXh0LXJhZGlhbC1vZmZzZXRcIn1dLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJ0ZXh0LWFsbG93LW92ZXJsYXBcIjp7dHlwZTpcImJvb2xlYW5cIixkZWZhdWx0OiExLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwidGV4dC1pZ25vcmUtcGxhY2VtZW50XCI6e3R5cGU6XCJib29sZWFuXCIsZGVmYXVsdDohMSxyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcInRleHQtb3B0aW9uYWxcIjp7dHlwZTpcImJvb2xlYW5cIixkZWZhdWx0OiExLHJlcXVpcmVzOltcInRleHQtZmllbGRcIixcImljb24taW1hZ2VcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LHZpc2liaWxpdHk6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnt2aXNpYmxlOnt9LG5vbmU6e319LGRlZmF1bHQ6XCJ2aXNpYmxlXCIsXCJwcm9wZXJ0eS10eXBlXCI6XCJjb25zdGFudFwifX0sbGF5b3V0X3Jhc3Rlcjp7dmlzaWJpbGl0eTp7dHlwZTpcImVudW1cIix2YWx1ZXM6e3Zpc2libGU6e30sbm9uZTp7fX0sZGVmYXVsdDpcInZpc2libGVcIixcInByb3BlcnR5LXR5cGVcIjpcImNvbnN0YW50XCJ9fSxsYXlvdXRfaGlsbHNoYWRlOnt2aXNpYmlsaXR5Ont0eXBlOlwiZW51bVwiLHZhbHVlczp7dmlzaWJsZTp7fSxub25lOnt9fSxkZWZhdWx0OlwidmlzaWJsZVwiLFwicHJvcGVydHktdHlwZVwiOlwiY29uc3RhbnRcIn19LGZpbHRlcjp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCIqXCJ9LGZpbHRlcl9vcGVyYXRvcjp7dHlwZTpcImVudW1cIix2YWx1ZXM6e1wiPT1cIjp7fSxcIiE9XCI6e30sXCI+XCI6e30sXCI+PVwiOnt9LFwiPFwiOnt9LFwiPD1cIjp7fSxpbjp7fSxcIiFpblwiOnt9LGFsbDp7fSxhbnk6e30sbm9uZTp7fSxoYXM6e30sXCIhaGFzXCI6e319fSxnZW9tZXRyeV90eXBlOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7UG9pbnQ6e30sTGluZVN0cmluZzp7fSxQb2x5Z29uOnt9fX0sZnVuY3Rpb246e2V4cHJlc3Npb246e3R5cGU6XCJleHByZXNzaW9uXCJ9LHN0b3BzOnt0eXBlOlwiYXJyYXlcIix2YWx1ZTpcImZ1bmN0aW9uX3N0b3BcIn0sYmFzZTp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjB9LHByb3BlcnR5Ont0eXBlOlwic3RyaW5nXCIsZGVmYXVsdDpcIiR6b29tXCJ9LHR5cGU6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOntpZGVudGl0eTp7fSxleHBvbmVudGlhbDp7fSxpbnRlcnZhbDp7fSxjYXRlZ29yaWNhbDp7fX0sZGVmYXVsdDpcImV4cG9uZW50aWFsXCJ9LGNvbG9yU3BhY2U6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOntyZ2I6e30sbGFiOnt9LGhjbDp7fX0sZGVmYXVsdDpcInJnYlwifSxkZWZhdWx0Ont0eXBlOlwiKlwiLHJlcXVpcmVkOiExfX0sZnVuY3Rpb25fc3RvcDp7dHlwZTpcImFycmF5XCIsbWluaW11bTowLG1heGltdW06MjIsdmFsdWU6W1wibnVtYmVyXCIsXCJjb2xvclwiXSxsZW5ndGg6Mn0sZXhwcmVzc2lvbjp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCIqXCIsbWluaW11bToxfSxleHByZXNzaW9uX25hbWU6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOntsZXQ6e2dyb3VwOlwiVmFyaWFibGUgYmluZGluZ1wifSx2YXI6e2dyb3VwOlwiVmFyaWFibGUgYmluZGluZ1wifSxsaXRlcmFsOntncm91cDpcIlR5cGVzXCJ9LGFycmF5Ontncm91cDpcIlR5cGVzXCJ9LGF0Ontncm91cDpcIkxvb2t1cFwifSxjYXNlOntncm91cDpcIkRlY2lzaW9uXCJ9LG1hdGNoOntncm91cDpcIkRlY2lzaW9uXCJ9LGNvYWxlc2NlOntncm91cDpcIkRlY2lzaW9uXCJ9LHN0ZXA6e2dyb3VwOlwiUmFtcHMsIHNjYWxlcywgY3VydmVzXCJ9LGludGVycG9sYXRlOntncm91cDpcIlJhbXBzLCBzY2FsZXMsIGN1cnZlc1wifSxcImludGVycG9sYXRlLWhjbFwiOntncm91cDpcIlJhbXBzLCBzY2FsZXMsIGN1cnZlc1wifSxcImludGVycG9sYXRlLWxhYlwiOntncm91cDpcIlJhbXBzLCBzY2FsZXMsIGN1cnZlc1wifSxsbjI6e2dyb3VwOlwiTWF0aFwifSxwaTp7Z3JvdXA6XCJNYXRoXCJ9LGU6e2dyb3VwOlwiTWF0aFwifSx0eXBlb2Y6e2dyb3VwOlwiVHlwZXNcIn0sc3RyaW5nOntncm91cDpcIlR5cGVzXCJ9LG51bWJlcjp7Z3JvdXA6XCJUeXBlc1wifSxib29sZWFuOntncm91cDpcIlR5cGVzXCJ9LG9iamVjdDp7Z3JvdXA6XCJUeXBlc1wifSxjb2xsYXRvcjp7Z3JvdXA6XCJUeXBlc1wifSxmb3JtYXQ6e2dyb3VwOlwiVHlwZXNcIn0sXCJudW1iZXItZm9ybWF0XCI6e2dyb3VwOlwiVHlwZXNcIn0sXCJ0by1zdHJpbmdcIjp7Z3JvdXA6XCJUeXBlc1wifSxcInRvLW51bWJlclwiOntncm91cDpcIlR5cGVzXCJ9LFwidG8tYm9vbGVhblwiOntncm91cDpcIlR5cGVzXCJ9LFwidG8tcmdiYVwiOntncm91cDpcIkNvbG9yXCJ9LFwidG8tY29sb3JcIjp7Z3JvdXA6XCJUeXBlc1wifSxyZ2I6e2dyb3VwOlwiQ29sb3JcIn0scmdiYTp7Z3JvdXA6XCJDb2xvclwifSxnZXQ6e2dyb3VwOlwiTG9va3VwXCJ9LGhhczp7Z3JvdXA6XCJMb29rdXBcIn0sbGVuZ3RoOntncm91cDpcIkxvb2t1cFwifSxwcm9wZXJ0aWVzOntncm91cDpcIkZlYXR1cmUgZGF0YVwifSxcImZlYXR1cmUtc3RhdGVcIjp7Z3JvdXA6XCJGZWF0dXJlIGRhdGFcIn0sXCJnZW9tZXRyeS10eXBlXCI6e2dyb3VwOlwiRmVhdHVyZSBkYXRhXCJ9LGlkOntncm91cDpcIkZlYXR1cmUgZGF0YVwifSx6b29tOntncm91cDpcIlpvb21cIn0sXCJoZWF0bWFwLWRlbnNpdHlcIjp7Z3JvdXA6XCJIZWF0bWFwXCJ9LFwibGluZS1wcm9ncmVzc1wiOntncm91cDpcIkZlYXR1cmUgZGF0YVwifSxhY2N1bXVsYXRlZDp7Z3JvdXA6XCJGZWF0dXJlIGRhdGFcIn0sXCIrXCI6e2dyb3VwOlwiTWF0aFwifSxcIipcIjp7Z3JvdXA6XCJNYXRoXCJ9LFwiLVwiOntncm91cDpcIk1hdGhcIn0sXCIvXCI6e2dyb3VwOlwiTWF0aFwifSxcIiVcIjp7Z3JvdXA6XCJNYXRoXCJ9LFwiXlwiOntncm91cDpcIk1hdGhcIn0sc3FydDp7Z3JvdXA6XCJNYXRoXCJ9LGxvZzEwOntncm91cDpcIk1hdGhcIn0sbG46e2dyb3VwOlwiTWF0aFwifSxsb2cyOntncm91cDpcIk1hdGhcIn0sc2luOntncm91cDpcIk1hdGhcIn0sY29zOntncm91cDpcIk1hdGhcIn0sdGFuOntncm91cDpcIk1hdGhcIn0sYXNpbjp7Z3JvdXA6XCJNYXRoXCJ9LGFjb3M6e2dyb3VwOlwiTWF0aFwifSxhdGFuOntncm91cDpcIk1hdGhcIn0sbWluOntncm91cDpcIk1hdGhcIn0sbWF4Ontncm91cDpcIk1hdGhcIn0scm91bmQ6e2dyb3VwOlwiTWF0aFwifSxhYnM6e2dyb3VwOlwiTWF0aFwifSxjZWlsOntncm91cDpcIk1hdGhcIn0sZmxvb3I6e2dyb3VwOlwiTWF0aFwifSxcIj09XCI6e2dyb3VwOlwiRGVjaXNpb25cIn0sXCIhPVwiOntncm91cDpcIkRlY2lzaW9uXCJ9LFwiPlwiOntncm91cDpcIkRlY2lzaW9uXCJ9LFwiPFwiOntncm91cDpcIkRlY2lzaW9uXCJ9LFwiPj1cIjp7Z3JvdXA6XCJEZWNpc2lvblwifSxcIjw9XCI6e2dyb3VwOlwiRGVjaXNpb25cIn0sYWxsOntncm91cDpcIkRlY2lzaW9uXCJ9LGFueTp7Z3JvdXA6XCJEZWNpc2lvblwifSxcIiFcIjp7Z3JvdXA6XCJEZWNpc2lvblwifSxcImlzLXN1cHBvcnRlZC1zY3JpcHRcIjp7Z3JvdXA6XCJTdHJpbmdcIn0sdXBjYXNlOntncm91cDpcIlN0cmluZ1wifSxkb3duY2FzZTp7Z3JvdXA6XCJTdHJpbmdcIn0sY29uY2F0Ontncm91cDpcIlN0cmluZ1wifSxcInJlc29sdmVkLWxvY2FsZVwiOntncm91cDpcIlN0cmluZ1wifX19LGxpZ2h0OnthbmNob3I6e3R5cGU6XCJlbnVtXCIsZGVmYXVsdDpcInZpZXdwb3J0XCIsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e319LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwiLHRyYW5zaXRpb246ITEsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX19LHBvc2l0aW9uOnt0eXBlOlwiYXJyYXlcIixkZWZhdWx0OlsxLjE1LDIxMCwzMF0sbGVuZ3RoOjMsdmFsdWU6XCJudW1iZXJcIixcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIix0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19fSxjb2xvcjp7dHlwZTpcImNvbG9yXCIsXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCIsZGVmYXVsdDpcIiNmZmZmZmZcIixleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSx0cmFuc2l0aW9uOiEwfSxpbnRlbnNpdHk6e3R5cGU6XCJudW1iZXJcIixcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIixkZWZhdWx0Oi41LG1pbmltdW06MCxtYXhpbXVtOjEsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sdHJhbnNpdGlvbjohMH19LHBhaW50OltcInBhaW50X2ZpbGxcIixcInBhaW50X2xpbmVcIixcInBhaW50X2NpcmNsZVwiLFwicGFpbnRfaGVhdG1hcFwiLFwicGFpbnRfZmlsbC1leHRydXNpb25cIixcInBhaW50X3N5bWJvbFwiLFwicGFpbnRfcmFzdGVyXCIsXCJwYWludF9oaWxsc2hhZGVcIixcInBhaW50X2JhY2tncm91bmRcIl0scGFpbnRfZmlsbDp7XCJmaWxsLWFudGlhbGlhc1wiOnt0eXBlOlwiYm9vbGVhblwiLGRlZmF1bHQ6ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiZmlsbC1vcGFjaXR5XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLG1heGltdW06MSx0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJmaWxsLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCIjMDAwMDAwXCIsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbe1wiIVwiOlwiZmlsbC1wYXR0ZXJuXCJ9XSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwiZmlsbC1vdXRsaW5lLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLHRyYW5zaXRpb246ITAscmVxdWlyZXM6W3tcIiFcIjpcImZpbGwtcGF0dGVyblwifSx7XCJmaWxsLWFudGlhbGlhc1wiOiEwfV0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiLFwiZmVhdHVyZS1zdGF0ZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcImZpbGwtdHJhbnNsYXRlXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjIsZGVmYXVsdDpbMCwwXSx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiZmlsbC10cmFuc2xhdGUtYW5jaG9yXCI6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e319LGRlZmF1bHQ6XCJtYXBcIixyZXF1aXJlczpbXCJmaWxsLXRyYW5zbGF0ZVwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJmaWxsLXBhdHRlcm5cIjp7dHlwZTpcInN0cmluZ1wiLHRyYW5zaXRpb246ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJjcm9zcy1mYWRlZC1kYXRhLWRyaXZlblwifX0sXCJwYWludF9maWxsLWV4dHJ1c2lvblwiOntcImZpbGwtZXh0cnVzaW9uLW9wYWNpdHlcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjAsbWF4aW11bToxLHRyYW5zaXRpb246ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiZmlsbC1leHRydXNpb24tY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcIiMwMDAwMDBcIix0cmFuc2l0aW9uOiEwLHJlcXVpcmVzOlt7XCIhXCI6XCJmaWxsLWV4dHJ1c2lvbi1wYXR0ZXJuXCJ9XSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwiZmlsbC1leHRydXNpb24tdHJhbnNsYXRlXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjIsZGVmYXVsdDpbMCwwXSx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiZmlsbC1leHRydXNpb24tdHJhbnNsYXRlLWFuY2hvclwiOnt0eXBlOlwiZW51bVwiLHZhbHVlczp7bWFwOnt9LHZpZXdwb3J0Ont9fSxkZWZhdWx0OlwibWFwXCIscmVxdWlyZXM6W1wiZmlsbC1leHRydXNpb24tdHJhbnNsYXRlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImZpbGwtZXh0cnVzaW9uLXBhdHRlcm5cIjp7dHlwZTpcInN0cmluZ1wiLHRyYW5zaXRpb246ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJjcm9zcy1mYWRlZC1kYXRhLWRyaXZlblwifSxcImZpbGwtZXh0cnVzaW9uLWhlaWdodFwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCx1bml0czpcIm1ldGVyc1wiLHRyYW5zaXRpb246ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiLFwiZmVhdHVyZS1zdGF0ZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcImZpbGwtZXh0cnVzaW9uLWJhc2VcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MCxtaW5pbXVtOjAsdW5pdHM6XCJtZXRlcnNcIix0cmFuc2l0aW9uOiEwLHJlcXVpcmVzOltcImZpbGwtZXh0cnVzaW9uLWhlaWdodFwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwiZmlsbC1leHRydXNpb24tdmVydGljYWwtZ3JhZGllbnRcIjp7dHlwZTpcImJvb2xlYW5cIixkZWZhdWx0OiEwLHRyYW5zaXRpb246ITEsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9fSxwYWludF9saW5lOntcImxpbmUtb3BhY2l0eVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoxLG1pbmltdW06MCxtYXhpbXVtOjEsdHJhbnNpdGlvbjohMCxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwibGluZS1jb2xvclwiOnt0eXBlOlwiY29sb3JcIixkZWZhdWx0OlwiIzAwMDAwMFwiLHRyYW5zaXRpb246ITAscmVxdWlyZXM6W3tcIiFcIjpcImxpbmUtcGF0dGVyblwifV0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiLFwiZmVhdHVyZS1zdGF0ZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcImxpbmUtdHJhbnNsYXRlXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjIsZGVmYXVsdDpbMCwwXSx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwibGluZS10cmFuc2xhdGUtYW5jaG9yXCI6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e319LGRlZmF1bHQ6XCJtYXBcIixyZXF1aXJlczpbXCJsaW5lLXRyYW5zbGF0ZVwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJsaW5lLXdpZHRoXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLHRyYW5zaXRpb246ITAsdW5pdHM6XCJwaXhlbHNcIixleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwibGluZS1nYXAtd2lkdGhcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MCxtaW5pbXVtOjAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wiLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJsaW5lLW9mZnNldFwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLHRyYW5zaXRpb246ITAsdW5pdHM6XCJwaXhlbHNcIixleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwibGluZS1ibHVyXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjAsbWluaW11bTowLHRyYW5zaXRpb246ITAsdW5pdHM6XCJwaXhlbHNcIixleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwibGluZS1kYXNoYXJyYXlcIjp7dHlwZTpcImFycmF5XCIsdmFsdWU6XCJudW1iZXJcIixtaW5pbXVtOjAsdHJhbnNpdGlvbjohMCx1bml0czpcImxpbmUgd2lkdGhzXCIscmVxdWlyZXM6W3tcIiFcIjpcImxpbmUtcGF0dGVyblwifV0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJjcm9zcy1mYWRlZFwifSxcImxpbmUtcGF0dGVyblwiOnt0eXBlOlwic3RyaW5nXCIsdHJhbnNpdGlvbjohMCxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImNyb3NzLWZhZGVkLWRhdGEtZHJpdmVuXCJ9LFwibGluZS1ncmFkaWVudFwiOnt0eXBlOlwiY29sb3JcIix0cmFuc2l0aW9uOiExLHJlcXVpcmVzOlt7XCIhXCI6XCJsaW5lLWRhc2hhcnJheVwifSx7XCIhXCI6XCJsaW5lLXBhdHRlcm5cIn0se3NvdXJjZTpcImdlb2pzb25cIixoYXM6e2xpbmVNZXRyaWNzOiEwfX1dLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcImxpbmUtcHJvZ3Jlc3NcIl19LFwicHJvcGVydHktdHlwZVwiOlwiY29sb3ItcmFtcFwifX0scGFpbnRfY2lyY2xlOntcImNpcmNsZS1yYWRpdXNcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6NSxtaW5pbXVtOjAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wiLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJjaXJjbGUtY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcIiMwMDAwMDBcIix0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJjaXJjbGUtYmx1clwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLHRyYW5zaXRpb246ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiLFwiZmVhdHVyZS1zdGF0ZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcImNpcmNsZS1vcGFjaXR5XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLG1heGltdW06MSx0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJjaXJjbGUtdHJhbnNsYXRlXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjIsZGVmYXVsdDpbMCwwXSx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiY2lyY2xlLXRyYW5zbGF0ZS1hbmNob3JcIjp7dHlwZTpcImVudW1cIix2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fX0sZGVmYXVsdDpcIm1hcFwiLHJlcXVpcmVzOltcImNpcmNsZS10cmFuc2xhdGVcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwiY2lyY2xlLXBpdGNoLXNjYWxlXCI6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e319LGRlZmF1bHQ6XCJtYXBcIixleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITEscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJjaXJjbGUtcGl0Y2gtYWxpZ25tZW50XCI6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e319LGRlZmF1bHQ6XCJ2aWV3cG9ydFwiLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImNpcmNsZS1zdHJva2Utd2lkdGhcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MCxtaW5pbXVtOjAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wiLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJjaXJjbGUtc3Ryb2tlLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCIjMDAwMDAwXCIsdHJhbnNpdGlvbjohMCxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwiY2lyY2xlLXN0cm9rZS1vcGFjaXR5XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLG1heGltdW06MSx0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn19LHBhaW50X2hlYXRtYXA6e1wiaGVhdG1hcC1yYWRpdXNcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MzAsbWluaW11bToxLHRyYW5zaXRpb246ITAsdW5pdHM6XCJwaXhlbHNcIixleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwiaGVhdG1hcC13ZWlnaHRcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjAsdHJhbnNpdGlvbjohMSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwiaGVhdG1hcC1pbnRlbnNpdHlcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjAsdHJhbnNpdGlvbjohMCxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJoZWF0bWFwLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6W1wiaW50ZXJwb2xhdGVcIixbXCJsaW5lYXJcIl0sW1wiaGVhdG1hcC1kZW5zaXR5XCJdLDAsXCJyZ2JhKDAsIDAsIDI1NSwgMClcIiwuMSxcInJveWFsYmx1ZVwiLC4zLFwiY3lhblwiLC41LFwibGltZVwiLC43LFwieWVsbG93XCIsMSxcInJlZFwiXSx0cmFuc2l0aW9uOiExLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcImhlYXRtYXAtZGVuc2l0eVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJjb2xvci1yYW1wXCJ9LFwiaGVhdG1hcC1vcGFjaXR5XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLG1heGltdW06MSx0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifX0scGFpbnRfc3ltYm9sOntcImljb24tb3BhY2l0eVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoxLG1pbmltdW06MCxtYXhpbXVtOjEsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbXCJpY29uLWltYWdlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJpY29uLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCIjMDAwMDAwXCIsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbXCJpY29uLWltYWdlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJpY29uLWhhbG8tY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcInJnYmEoMCwgMCwgMCwgMClcIix0cmFuc2l0aW9uOiEwLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiLFwiZmVhdHVyZS1zdGF0ZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcImljb24taGFsby13aWR0aFwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwiaWNvbi1oYWxvLWJsdXJcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MCxtaW5pbXVtOjAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiLFwiZmVhdHVyZS1zdGF0ZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcImljb24tdHJhbnNsYXRlXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjIsZGVmYXVsdDpbMCwwXSx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIscmVxdWlyZXM6W1wiaWNvbi1pbWFnZVwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJpY29uLXRyYW5zbGF0ZS1hbmNob3JcIjp7dHlwZTpcImVudW1cIix2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fX0sZGVmYXVsdDpcIm1hcFwiLHJlcXVpcmVzOltcImljb24taW1hZ2VcIixcImljb24tdHJhbnNsYXRlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcInRleHQtb3BhY2l0eVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoxLG1pbmltdW06MCxtYXhpbXVtOjEsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJ0ZXh0LWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCIjMDAwMDAwXCIsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbXCJ0ZXh0LWZpZWxkXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIixcImZlYXR1cmVcIixcImZlYXR1cmUtc3RhdGVcIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1kcml2ZW5cIn0sXCJ0ZXh0LWhhbG8tY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcInJnYmEoMCwgMCwgMCwgMClcIix0cmFuc2l0aW9uOiEwLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiLFwiZmVhdHVyZS1zdGF0ZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcInRleHQtaGFsby13aWR0aFwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCIsXCJmZWF0dXJlXCIsXCJmZWF0dXJlLXN0YXRlXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCJ9LFwidGV4dC1oYWxvLWJsdXJcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MCxtaW5pbXVtOjAsdHJhbnNpdGlvbjohMCx1bml0czpcInBpeGVsc1wiLHJlcXVpcmVzOltcInRleHQtZmllbGRcIl0sZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiLFwiZmVhdHVyZS1zdGF0ZVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWRyaXZlblwifSxcInRleHQtdHJhbnNsYXRlXCI6e3R5cGU6XCJhcnJheVwiLHZhbHVlOlwibnVtYmVyXCIsbGVuZ3RoOjIsZGVmYXVsdDpbMCwwXSx0cmFuc2l0aW9uOiEwLHVuaXRzOlwicGl4ZWxzXCIscmVxdWlyZXM6W1widGV4dC1maWVsZFwiXSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJ0ZXh0LXRyYW5zbGF0ZS1hbmNob3JcIjp7dHlwZTpcImVudW1cIix2YWx1ZXM6e21hcDp7fSx2aWV3cG9ydDp7fX0sZGVmYXVsdDpcIm1hcFwiLHJlcXVpcmVzOltcInRleHQtZmllbGRcIixcInRleHQtdHJhbnNsYXRlXCJdLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifX0scGFpbnRfcmFzdGVyOntcInJhc3Rlci1vcGFjaXR5XCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjEsbWluaW11bTowLG1heGltdW06MSx0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcInJhc3Rlci1odWUtcm90YXRlXCI6e3R5cGU6XCJudW1iZXJcIixkZWZhdWx0OjAscGVyaW9kOjM2MCx0cmFuc2l0aW9uOiEwLHVuaXRzOlwiZGVncmVlc1wiLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcInJhc3Rlci1icmlnaHRuZXNzLW1pblwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCxtYXhpbXVtOjEsdHJhbnNpdGlvbjohMCxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJyYXN0ZXItYnJpZ2h0bmVzcy1tYXhcIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MSxtaW5pbXVtOjAsbWF4aW11bToxLHRyYW5zaXRpb246ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwicmFzdGVyLXNhdHVyYXRpb25cIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MCxtaW5pbXVtOi0xLG1heGltdW06MSx0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcInJhc3Rlci1jb250cmFzdFwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06LTEsbWF4aW11bToxLHRyYW5zaXRpb246ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwicmFzdGVyLXJlc2FtcGxpbmdcIjp7dHlwZTpcImVudW1cIix2YWx1ZXM6e2xpbmVhcjp7fSxuZWFyZXN0Ont9fSxkZWZhdWx0OlwibGluZWFyXCIsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9LFwicmFzdGVyLWZhZGUtZHVyYXRpb25cIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MzAwLG1pbmltdW06MCx0cmFuc2l0aW9uOiExLHVuaXRzOlwibWlsbGlzZWNvbmRzXCIsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiEwLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJkYXRhLWNvbnN0YW50XCJ9fSxwYWludF9oaWxsc2hhZGU6e1wiaGlsbHNoYWRlLWlsbHVtaW5hdGlvbi1kaXJlY3Rpb25cIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6MzM1LG1pbmltdW06MCxtYXhpbXVtOjM1OSx0cmFuc2l0aW9uOiExLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImhpbGxzaGFkZS1pbGx1bWluYXRpb24tYW5jaG9yXCI6e3R5cGU6XCJlbnVtXCIsdmFsdWVzOnttYXA6e30sdmlld3BvcnQ6e319LGRlZmF1bHQ6XCJ2aWV3cG9ydFwiLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMSxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImhpbGxzaGFkZS1leGFnZ2VyYXRpb25cIjp7dHlwZTpcIm51bWJlclwiLGRlZmF1bHQ6LjUsbWluaW11bTowLG1heGltdW06MSx0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImhpbGxzaGFkZS1zaGFkb3ctY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcIiMwMDAwMDBcIix0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImhpbGxzaGFkZS1oaWdobGlnaHQtY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcIiNGRkZGRkZcIix0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifSxcImhpbGxzaGFkZS1hY2NlbnQtY29sb3JcIjp7dHlwZTpcImNvbG9yXCIsZGVmYXVsdDpcIiMwMDAwMDBcIix0cmFuc2l0aW9uOiEwLGV4cHJlc3Npb246e2ludGVycG9sYXRlZDohMCxwYXJhbWV0ZXJzOltcInpvb21cIl19LFwicHJvcGVydHktdHlwZVwiOlwiZGF0YS1jb25zdGFudFwifX0scGFpbnRfYmFja2dyb3VuZDp7XCJiYWNrZ3JvdW5kLWNvbG9yXCI6e3R5cGU6XCJjb2xvclwiLGRlZmF1bHQ6XCIjMDAwMDAwXCIsdHJhbnNpdGlvbjohMCxyZXF1aXJlczpbe1wiIVwiOlwiYmFja2dyb3VuZC1wYXR0ZXJuXCJ9XSxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn0sXCJiYWNrZ3JvdW5kLXBhdHRlcm5cIjp7dHlwZTpcInN0cmluZ1wiLHRyYW5zaXRpb246ITAsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiXX0sXCJwcm9wZXJ0eS10eXBlXCI6XCJjcm9zcy1mYWRlZFwifSxcImJhY2tncm91bmQtb3BhY2l0eVwiOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDoxLG1pbmltdW06MCxtYXhpbXVtOjEsdHJhbnNpdGlvbjohMCxleHByZXNzaW9uOntpbnRlcnBvbGF0ZWQ6ITAscGFyYW1ldGVyczpbXCJ6b29tXCJdfSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtY29uc3RhbnRcIn19LHRyYW5zaXRpb246e2R1cmF0aW9uOnt0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDozMDAsbWluaW11bTowLHVuaXRzOlwibWlsbGlzZWNvbmRzXCJ9LGRlbGF5Ont0eXBlOlwibnVtYmVyXCIsZGVmYXVsdDowLG1pbmltdW06MCx1bml0czpcIm1pbGxpc2Vjb25kc1wifX0sXCJwcm9wZXJ0eS10eXBlXCI6e1wiZGF0YS1kcml2ZW5cIjp7dHlwZTpcInByb3BlcnR5LXR5cGVcIn0sXCJjcm9zcy1mYWRlZFwiOnt0eXBlOlwicHJvcGVydHktdHlwZVwifSxcImNyb3NzLWZhZGVkLWRhdGEtZHJpdmVuXCI6e3R5cGU6XCJwcm9wZXJ0eS10eXBlXCJ9LFwiY29sb3ItcmFtcFwiOnt0eXBlOlwicHJvcGVydHktdHlwZVwifSxcImRhdGEtY29uc3RhbnRcIjp7dHlwZTpcInByb3BlcnR5LXR5cGVcIn0sY29uc3RhbnQ6e3R5cGU6XCJwcm9wZXJ0eS10eXBlXCJ9fX0sRHQ9ZnVuY3Rpb24odCxlLHIsbil7dGhpcy5tZXNzYWdlPSh0P3QrXCI6IFwiOlwiXCIpK3IsbiYmKHRoaXMuaWRlbnRpZmllcj1uKSxudWxsIT1lJiZlLl9fbGluZV9fJiYodGhpcy5saW5lPWUuX19saW5lX18pO307ZnVuY3Rpb24gT3QodCl7dmFyIGU9dC5rZXkscj10LnZhbHVlO3JldHVybiByP1tuZXcgRHQoZSxyLFwiY29uc3RhbnRzIGhhdmUgYmVlbiBkZXByZWNhdGVkIGFzIG9mIHY4XCIpXTpbXX1mdW5jdGlvbiBSdCh0KXtmb3IodmFyIGU9W10scj1hcmd1bWVudHMubGVuZ3RoLTE7ci0tID4wOyllW3JdPWFyZ3VtZW50c1tyKzFdO2Zvcih2YXIgbj0wLGk9ZTtuPGkubGVuZ3RoO24rPTEpe3ZhciBhPWlbbl07Zm9yKHZhciBvIGluIGEpdFtvXT1hW29dO31yZXR1cm4gdH1mdW5jdGlvbiBVdCh0KXtyZXR1cm4gdCBpbnN0YW5jZW9mIE51bWJlcnx8dCBpbnN0YW5jZW9mIFN0cmluZ3x8dCBpbnN0YW5jZW9mIEJvb2xlYW59ZnVuY3Rpb24ganQodCl7cmV0dXJuIFV0KHQpP3QudmFsdWVPZigpOnR9ZnVuY3Rpb24gcXQodCl7aWYoQXJyYXkuaXNBcnJheSh0KSlyZXR1cm4gdC5tYXAocXQpO2lmKHQgaW5zdGFuY2VvZiBPYmplY3QmJiFVdCh0KSl7dmFyIGU9e307Zm9yKHZhciByIGluIHQpZVtyXT1xdCh0W3JdKTtyZXR1cm4gZX1yZXR1cm4ganQodCl9dmFyIE50PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSxyKXt0LmNhbGwodGhpcyxyKSx0aGlzLm1lc3NhZ2U9cix0aGlzLmtleT1lO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZX0oRXJyb3IpLFp0PWZ1bmN0aW9uKHQsZSl7dm9pZCAwPT09ZSYmKGU9W10pLHRoaXMucGFyZW50PXQsdGhpcy5iaW5kaW5ncz17fTtmb3IodmFyIHI9MCxuPWU7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdLGE9aVswXSxvPWlbMV07dGhpcy5iaW5kaW5nc1thXT1vO319O1p0LnByb3RvdHlwZS5jb25jYXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBadCh0aGlzLHQpfSxadC5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKHQpe2lmKHRoaXMuYmluZGluZ3NbdF0pcmV0dXJuIHRoaXMuYmluZGluZ3NbdF07aWYodGhpcy5wYXJlbnQpcmV0dXJuIHRoaXMucGFyZW50LmdldCh0KTt0aHJvdyBuZXcgRXJyb3IodCtcIiBub3QgZm91bmQgaW4gc2NvcGUuXCIpfSxadC5wcm90b3R5cGUuaGFzPWZ1bmN0aW9uKHQpe3JldHVybiAhIXRoaXMuYmluZGluZ3NbdF18fCEhdGhpcy5wYXJlbnQmJnRoaXMucGFyZW50Lmhhcyh0KX07dmFyIEt0PXtraW5kOlwibnVsbFwifSxHdD17a2luZDpcIm51bWJlclwifSxYdD17a2luZDpcInN0cmluZ1wifSxKdD17a2luZDpcImJvb2xlYW5cIn0sSHQ9e2tpbmQ6XCJjb2xvclwifSxZdD17a2luZDpcIm9iamVjdFwifSwkdD17a2luZDpcInZhbHVlXCJ9LFd0PXtraW5kOlwiY29sbGF0b3JcIn0sUXQ9e2tpbmQ6XCJmb3JtYXR0ZWRcIn07ZnVuY3Rpb24gdGUodCxlKXtyZXR1cm4ge2tpbmQ6XCJhcnJheVwiLGl0ZW1UeXBlOnQsTjplfX1mdW5jdGlvbiBlZSh0KXtpZihcImFycmF5XCI9PT10LmtpbmQpe3ZhciBlPWVlKHQuaXRlbVR5cGUpO3JldHVybiBcIm51bWJlclwiPT10eXBlb2YgdC5OP1wiYXJyYXk8XCIrZStcIiwgXCIrdC5OK1wiPlwiOlwidmFsdWVcIj09PXQuaXRlbVR5cGUua2luZD9cImFycmF5XCI6XCJhcnJheTxcIitlK1wiPlwifXJldHVybiB0LmtpbmR9dmFyIHJlPVtLdCxHdCxYdCxKdCxIdCxRdCxZdCx0ZSgkdCldO2Z1bmN0aW9uIG5lKHQsZSl7aWYoXCJlcnJvclwiPT09ZS5raW5kKXJldHVybiBudWxsO2lmKFwiYXJyYXlcIj09PXQua2luZCl7aWYoXCJhcnJheVwiPT09ZS5raW5kJiYoMD09PWUuTiYmXCJ2YWx1ZVwiPT09ZS5pdGVtVHlwZS5raW5kfHwhbmUodC5pdGVtVHlwZSxlLml0ZW1UeXBlKSkmJihcIm51bWJlclwiIT10eXBlb2YgdC5OfHx0Lk49PT1lLk4pKXJldHVybiBudWxsfWVsc2V7aWYodC5raW5kPT09ZS5raW5kKXJldHVybiBudWxsO2lmKFwidmFsdWVcIj09PXQua2luZClmb3IodmFyIHI9MCxuPXJlO3I8bi5sZW5ndGg7cis9MSl7aWYoIW5lKG5bcl0sZSkpcmV0dXJuIG51bGx9fXJldHVybiBcIkV4cGVjdGVkIFwiK2VlKHQpK1wiIGJ1dCBmb3VuZCBcIitlZShlKStcIiBpbnN0ZWFkLlwifXZhciBpZT1lKGZ1bmN0aW9uKHQsZSl7dmFyIHI9e3RyYW5zcGFyZW50OlswLDAsMCwwXSxhbGljZWJsdWU6WzI0MCwyNDgsMjU1LDFdLGFudGlxdWV3aGl0ZTpbMjUwLDIzNSwyMTUsMV0sYXF1YTpbMCwyNTUsMjU1LDFdLGFxdWFtYXJpbmU6WzEyNywyNTUsMjEyLDFdLGF6dXJlOlsyNDAsMjU1LDI1NSwxXSxiZWlnZTpbMjQ1LDI0NSwyMjAsMV0sYmlzcXVlOlsyNTUsMjI4LDE5NiwxXSxibGFjazpbMCwwLDAsMV0sYmxhbmNoZWRhbG1vbmQ6WzI1NSwyMzUsMjA1LDFdLGJsdWU6WzAsMCwyNTUsMV0sYmx1ZXZpb2xldDpbMTM4LDQzLDIyNiwxXSxicm93bjpbMTY1LDQyLDQyLDFdLGJ1cmx5d29vZDpbMjIyLDE4NCwxMzUsMV0sY2FkZXRibHVlOls5NSwxNTgsMTYwLDFdLGNoYXJ0cmV1c2U6WzEyNywyNTUsMCwxXSxjaG9jb2xhdGU6WzIxMCwxMDUsMzAsMV0sY29yYWw6WzI1NSwxMjcsODAsMV0sY29ybmZsb3dlcmJsdWU6WzEwMCwxNDksMjM3LDFdLGNvcm5zaWxrOlsyNTUsMjQ4LDIyMCwxXSxjcmltc29uOlsyMjAsMjAsNjAsMV0sY3lhbjpbMCwyNTUsMjU1LDFdLGRhcmtibHVlOlswLDAsMTM5LDFdLGRhcmtjeWFuOlswLDEzOSwxMzksMV0sZGFya2dvbGRlbnJvZDpbMTg0LDEzNCwxMSwxXSxkYXJrZ3JheTpbMTY5LDE2OSwxNjksMV0sZGFya2dyZWVuOlswLDEwMCwwLDFdLGRhcmtncmV5OlsxNjksMTY5LDE2OSwxXSxkYXJra2hha2k6WzE4OSwxODMsMTA3LDFdLGRhcmttYWdlbnRhOlsxMzksMCwxMzksMV0sZGFya29saXZlZ3JlZW46Wzg1LDEwNyw0NywxXSxkYXJrb3JhbmdlOlsyNTUsMTQwLDAsMV0sZGFya29yY2hpZDpbMTUzLDUwLDIwNCwxXSxkYXJrcmVkOlsxMzksMCwwLDFdLGRhcmtzYWxtb246WzIzMywxNTAsMTIyLDFdLGRhcmtzZWFncmVlbjpbMTQzLDE4OCwxNDMsMV0sZGFya3NsYXRlYmx1ZTpbNzIsNjEsMTM5LDFdLGRhcmtzbGF0ZWdyYXk6WzQ3LDc5LDc5LDFdLGRhcmtzbGF0ZWdyZXk6WzQ3LDc5LDc5LDFdLGRhcmt0dXJxdW9pc2U6WzAsMjA2LDIwOSwxXSxkYXJrdmlvbGV0OlsxNDgsMCwyMTEsMV0sZGVlcHBpbms6WzI1NSwyMCwxNDcsMV0sZGVlcHNreWJsdWU6WzAsMTkxLDI1NSwxXSxkaW1ncmF5OlsxMDUsMTA1LDEwNSwxXSxkaW1ncmV5OlsxMDUsMTA1LDEwNSwxXSxkb2RnZXJibHVlOlszMCwxNDQsMjU1LDFdLGZpcmVicmljazpbMTc4LDM0LDM0LDFdLGZsb3JhbHdoaXRlOlsyNTUsMjUwLDI0MCwxXSxmb3Jlc3RncmVlbjpbMzQsMTM5LDM0LDFdLGZ1Y2hzaWE6WzI1NSwwLDI1NSwxXSxnYWluc2Jvcm86WzIyMCwyMjAsMjIwLDFdLGdob3N0d2hpdGU6WzI0OCwyNDgsMjU1LDFdLGdvbGQ6WzI1NSwyMTUsMCwxXSxnb2xkZW5yb2Q6WzIxOCwxNjUsMzIsMV0sZ3JheTpbMTI4LDEyOCwxMjgsMV0sZ3JlZW46WzAsMTI4LDAsMV0sZ3JlZW55ZWxsb3c6WzE3MywyNTUsNDcsMV0sZ3JleTpbMTI4LDEyOCwxMjgsMV0saG9uZXlkZXc6WzI0MCwyNTUsMjQwLDFdLGhvdHBpbms6WzI1NSwxMDUsMTgwLDFdLGluZGlhbnJlZDpbMjA1LDkyLDkyLDFdLGluZGlnbzpbNzUsMCwxMzAsMV0saXZvcnk6WzI1NSwyNTUsMjQwLDFdLGtoYWtpOlsyNDAsMjMwLDE0MCwxXSxsYXZlbmRlcjpbMjMwLDIzMCwyNTAsMV0sbGF2ZW5kZXJibHVzaDpbMjU1LDI0MCwyNDUsMV0sbGF3bmdyZWVuOlsxMjQsMjUyLDAsMV0sbGVtb25jaGlmZm9uOlsyNTUsMjUwLDIwNSwxXSxsaWdodGJsdWU6WzE3MywyMTYsMjMwLDFdLGxpZ2h0Y29yYWw6WzI0MCwxMjgsMTI4LDFdLGxpZ2h0Y3lhbjpbMjI0LDI1NSwyNTUsMV0sbGlnaHRnb2xkZW5yb2R5ZWxsb3c6WzI1MCwyNTAsMjEwLDFdLGxpZ2h0Z3JheTpbMjExLDIxMSwyMTEsMV0sbGlnaHRncmVlbjpbMTQ0LDIzOCwxNDQsMV0sbGlnaHRncmV5OlsyMTEsMjExLDIxMSwxXSxsaWdodHBpbms6WzI1NSwxODIsMTkzLDFdLGxpZ2h0c2FsbW9uOlsyNTUsMTYwLDEyMiwxXSxsaWdodHNlYWdyZWVuOlszMiwxNzgsMTcwLDFdLGxpZ2h0c2t5Ymx1ZTpbMTM1LDIwNiwyNTAsMV0sbGlnaHRzbGF0ZWdyYXk6WzExOSwxMzYsMTUzLDFdLGxpZ2h0c2xhdGVncmV5OlsxMTksMTM2LDE1MywxXSxsaWdodHN0ZWVsYmx1ZTpbMTc2LDE5NiwyMjIsMV0sbGlnaHR5ZWxsb3c6WzI1NSwyNTUsMjI0LDFdLGxpbWU6WzAsMjU1LDAsMV0sbGltZWdyZWVuOls1MCwyMDUsNTAsMV0sbGluZW46WzI1MCwyNDAsMjMwLDFdLG1hZ2VudGE6WzI1NSwwLDI1NSwxXSxtYXJvb246WzEyOCwwLDAsMV0sbWVkaXVtYXF1YW1hcmluZTpbMTAyLDIwNSwxNzAsMV0sbWVkaXVtYmx1ZTpbMCwwLDIwNSwxXSxtZWRpdW1vcmNoaWQ6WzE4Niw4NSwyMTEsMV0sbWVkaXVtcHVycGxlOlsxNDcsMTEyLDIxOSwxXSxtZWRpdW1zZWFncmVlbjpbNjAsMTc5LDExMywxXSxtZWRpdW1zbGF0ZWJsdWU6WzEyMywxMDQsMjM4LDFdLG1lZGl1bXNwcmluZ2dyZWVuOlswLDI1MCwxNTQsMV0sbWVkaXVtdHVycXVvaXNlOls3MiwyMDksMjA0LDFdLG1lZGl1bXZpb2xldHJlZDpbMTk5LDIxLDEzMywxXSxtaWRuaWdodGJsdWU6WzI1LDI1LDExMiwxXSxtaW50Y3JlYW06WzI0NSwyNTUsMjUwLDFdLG1pc3R5cm9zZTpbMjU1LDIyOCwyMjUsMV0sbW9jY2FzaW46WzI1NSwyMjgsMTgxLDFdLG5hdmFqb3doaXRlOlsyNTUsMjIyLDE3MywxXSxuYXZ5OlswLDAsMTI4LDFdLG9sZGxhY2U6WzI1MywyNDUsMjMwLDFdLG9saXZlOlsxMjgsMTI4LDAsMV0sb2xpdmVkcmFiOlsxMDcsMTQyLDM1LDFdLG9yYW5nZTpbMjU1LDE2NSwwLDFdLG9yYW5nZXJlZDpbMjU1LDY5LDAsMV0sb3JjaGlkOlsyMTgsMTEyLDIxNCwxXSxwYWxlZ29sZGVucm9kOlsyMzgsMjMyLDE3MCwxXSxwYWxlZ3JlZW46WzE1MiwyNTEsMTUyLDFdLHBhbGV0dXJxdW9pc2U6WzE3NSwyMzgsMjM4LDFdLHBhbGV2aW9sZXRyZWQ6WzIxOSwxMTIsMTQ3LDFdLHBhcGF5YXdoaXA6WzI1NSwyMzksMjEzLDFdLHBlYWNocHVmZjpbMjU1LDIxOCwxODUsMV0scGVydTpbMjA1LDEzMyw2MywxXSxwaW5rOlsyNTUsMTkyLDIwMywxXSxwbHVtOlsyMjEsMTYwLDIyMSwxXSxwb3dkZXJibHVlOlsxNzYsMjI0LDIzMCwxXSxwdXJwbGU6WzEyOCwwLDEyOCwxXSxyZWJlY2NhcHVycGxlOlsxMDIsNTEsMTUzLDFdLHJlZDpbMjU1LDAsMCwxXSxyb3N5YnJvd246WzE4OCwxNDMsMTQzLDFdLHJveWFsYmx1ZTpbNjUsMTA1LDIyNSwxXSxzYWRkbGVicm93bjpbMTM5LDY5LDE5LDFdLHNhbG1vbjpbMjUwLDEyOCwxMTQsMV0sc2FuZHlicm93bjpbMjQ0LDE2NCw5NiwxXSxzZWFncmVlbjpbNDYsMTM5LDg3LDFdLHNlYXNoZWxsOlsyNTUsMjQ1LDIzOCwxXSxzaWVubmE6WzE2MCw4Miw0NSwxXSxzaWx2ZXI6WzE5MiwxOTIsMTkyLDFdLHNreWJsdWU6WzEzNSwyMDYsMjM1LDFdLHNsYXRlYmx1ZTpbMTA2LDkwLDIwNSwxXSxzbGF0ZWdyYXk6WzExMiwxMjgsMTQ0LDFdLHNsYXRlZ3JleTpbMTEyLDEyOCwxNDQsMV0sc25vdzpbMjU1LDI1MCwyNTAsMV0sc3ByaW5nZ3JlZW46WzAsMjU1LDEyNywxXSxzdGVlbGJsdWU6WzcwLDEzMCwxODAsMV0sdGFuOlsyMTAsMTgwLDE0MCwxXSx0ZWFsOlswLDEyOCwxMjgsMV0sdGhpc3RsZTpbMjE2LDE5MSwyMTYsMV0sdG9tYXRvOlsyNTUsOTksNzEsMV0sdHVycXVvaXNlOls2NCwyMjQsMjA4LDFdLHZpb2xldDpbMjM4LDEzMCwyMzgsMV0sd2hlYXQ6WzI0NSwyMjIsMTc5LDFdLHdoaXRlOlsyNTUsMjU1LDI1NSwxXSx3aGl0ZXNtb2tlOlsyNDUsMjQ1LDI0NSwxXSx5ZWxsb3c6WzI1NSwyNTUsMCwxXSx5ZWxsb3dncmVlbjpbMTU0LDIwNSw1MCwxXX07ZnVuY3Rpb24gbih0KXtyZXR1cm4gKHQ9TWF0aC5yb3VuZCh0KSk8MD8wOnQ+MjU1PzI1NTp0fWZ1bmN0aW9uIGkodCl7cmV0dXJuIHQ8MD8wOnQ+MT8xOnR9ZnVuY3Rpb24gYSh0KXtyZXR1cm4gXCIlXCI9PT10W3QubGVuZ3RoLTFdP24ocGFyc2VGbG9hdCh0KS8xMDAqMjU1KTpuKHBhcnNlSW50KHQpKX1mdW5jdGlvbiBvKHQpe3JldHVybiBcIiVcIj09PXRbdC5sZW5ndGgtMV0/aShwYXJzZUZsb2F0KHQpLzEwMCk6aShwYXJzZUZsb2F0KHQpKX1mdW5jdGlvbiBzKHQsZSxyKXtyZXR1cm4gcjwwP3IrPTE6cj4xJiYoci09MSksNipyPDE/dCsoZS10KSpyKjY6MipyPDE/ZTozKnI8Mj90KyhlLXQpKigyLzMtcikqNjp0fXRyeXtlLnBhcnNlQ1NTQ29sb3I9ZnVuY3Rpb24odCl7dmFyIGUsaT10LnJlcGxhY2UoLyAvZyxcIlwiKS50b0xvd2VyQ2FzZSgpO2lmKGkgaW4gcilyZXR1cm4gcltpXS5zbGljZSgpO2lmKFwiI1wiPT09aVswXSlyZXR1cm4gND09PWkubGVuZ3RoPyhlPXBhcnNlSW50KGkuc3Vic3RyKDEpLDE2KSk+PTAmJmU8PTQwOTU/WygzODQwJmUpPj40fCgzODQwJmUpPj44LDI0MCZlfCgyNDAmZSk+PjQsMTUmZXwoMTUmZSk8PDQsMV06bnVsbDo3PT09aS5sZW5ndGgmJihlPXBhcnNlSW50KGkuc3Vic3RyKDEpLDE2KSk+PTAmJmU8PTE2Nzc3MjE1P1soMTY3MTE2ODAmZSk+PjE2LCg2NTI4MCZlKT4+OCwyNTUmZSwxXTpudWxsO3ZhciB1PWkuaW5kZXhPZihcIihcIiksbD1pLmluZGV4T2YoXCIpXCIpO2lmKC0xIT09dSYmbCsxPT09aS5sZW5ndGgpe3ZhciBwPWkuc3Vic3RyKDAsdSksYz1pLnN1YnN0cih1KzEsbC0odSsxKSkuc3BsaXQoXCIsXCIpLGg9MTtzd2l0Y2gocCl7Y2FzZVwicmdiYVwiOmlmKDQhPT1jLmxlbmd0aClyZXR1cm4gbnVsbDtoPW8oYy5wb3AoKSk7Y2FzZVwicmdiXCI6cmV0dXJuIDMhPT1jLmxlbmd0aD9udWxsOlthKGNbMF0pLGEoY1sxXSksYShjWzJdKSxoXTtjYXNlXCJoc2xhXCI6aWYoNCE9PWMubGVuZ3RoKXJldHVybiBudWxsO2g9byhjLnBvcCgpKTtjYXNlXCJoc2xcIjppZigzIT09Yy5sZW5ndGgpcmV0dXJuIG51bGw7dmFyIGY9KHBhcnNlRmxvYXQoY1swXSklMzYwKzM2MCklMzYwLzM2MCx5PW8oY1sxXSksZD1vKGNbMl0pLG09ZDw9LjU/ZCooeSsxKTpkK3ktZCp5LHY9MipkLW07cmV0dXJuIFtuKDI1NSpzKHYsbSxmKzEvMykpLG4oMjU1KnModixtLGYpKSxuKDI1NSpzKHYsbSxmLTEvMykpLGhdO2RlZmF1bHQ6cmV0dXJuIG51bGx9fXJldHVybiBudWxsfTt9Y2F0Y2godCl7fX0pLnBhcnNlQ1NTQ29sb3IsYWU9ZnVuY3Rpb24odCxlLHIsbil7dm9pZCAwPT09biYmKG49MSksdGhpcy5yPXQsdGhpcy5nPWUsdGhpcy5iPXIsdGhpcy5hPW47fTthZS5wYXJzZT1mdW5jdGlvbih0KXtpZih0KXtpZih0IGluc3RhbmNlb2YgYWUpcmV0dXJuIHQ7aWYoXCJzdHJpbmdcIj09dHlwZW9mIHQpe3ZhciBlPWllKHQpO2lmKGUpcmV0dXJuIG5ldyBhZShlWzBdLzI1NSplWzNdLGVbMV0vMjU1KmVbM10sZVsyXS8yNTUqZVszXSxlWzNdKX19fSxhZS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLnRvQXJyYXkoKSxlPXRbMF0scj10WzFdLG49dFsyXSxpPXRbM107cmV0dXJuIFwicmdiYShcIitNYXRoLnJvdW5kKGUpK1wiLFwiK01hdGgucm91bmQocikrXCIsXCIrTWF0aC5yb3VuZChuKStcIixcIitpK1wiKVwifSxhZS5wcm90b3R5cGUudG9BcnJheT1mdW5jdGlvbigpe3ZhciB0PXRoaXMucixlPXRoaXMuZyxyPXRoaXMuYixuPXRoaXMuYTtyZXR1cm4gMD09PW4/WzAsMCwwLDBdOlsyNTUqdC9uLDI1NSplL24sMjU1KnIvbixuXX0sYWUuYmxhY2s9bmV3IGFlKDAsMCwwLDEpLGFlLndoaXRlPW5ldyBhZSgxLDEsMSwxKSxhZS50cmFuc3BhcmVudD1uZXcgYWUoMCwwLDAsMCksYWUucmVkPW5ldyBhZSgxLDAsMCwxKTt2YXIgb2U9ZnVuY3Rpb24odCxlLHIpe3RoaXMuc2Vuc2l0aXZpdHk9dD9lP1widmFyaWFudFwiOlwiY2FzZVwiOmU/XCJhY2NlbnRcIjpcImJhc2VcIix0aGlzLmxvY2FsZT1yLHRoaXMuY29sbGF0b3I9bmV3IEludGwuQ29sbGF0b3IodGhpcy5sb2NhbGU/dGhpcy5sb2NhbGU6W10se3NlbnNpdGl2aXR5OnRoaXMuc2Vuc2l0aXZpdHksdXNhZ2U6XCJzZWFyY2hcIn0pO307b2UucHJvdG90eXBlLmNvbXBhcmU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5jb2xsYXRvci5jb21wYXJlKHQsZSl9LG9lLnByb3RvdHlwZS5yZXNvbHZlZExvY2FsZT1mdW5jdGlvbigpe3JldHVybiBuZXcgSW50bC5Db2xsYXRvcih0aGlzLmxvY2FsZT90aGlzLmxvY2FsZTpbXSkucmVzb2x2ZWRPcHRpb25zKCkubG9jYWxlfTt2YXIgc2U9ZnVuY3Rpb24odCxlLHIpe3RoaXMudGV4dD10LHRoaXMuc2NhbGU9ZSx0aGlzLmZvbnRTdGFjaz1yO30sdWU9ZnVuY3Rpb24odCl7dGhpcy5zZWN0aW9ucz10O307ZnVuY3Rpb24gbGUodCxlLHIsbil7cmV0dXJuIFwibnVtYmVyXCI9PXR5cGVvZiB0JiZ0Pj0wJiZ0PD0yNTUmJlwibnVtYmVyXCI9PXR5cGVvZiBlJiZlPj0wJiZlPD0yNTUmJlwibnVtYmVyXCI9PXR5cGVvZiByJiZyPj0wJiZyPD0yNTU/dm9pZCAwPT09bnx8XCJudW1iZXJcIj09dHlwZW9mIG4mJm4+PTAmJm48PTE/bnVsbDpcIkludmFsaWQgcmdiYSB2YWx1ZSBbXCIrW3QsZSxyLG5dLmpvaW4oXCIsIFwiKStcIl06ICdhJyBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMS5cIjpcIkludmFsaWQgcmdiYSB2YWx1ZSBbXCIrKFwibnVtYmVyXCI9PXR5cGVvZiBuP1t0LGUscixuXTpbdCxlLHJdKS5qb2luKFwiLCBcIikrXCJdOiAncicsICdnJywgYW5kICdiJyBtdXN0IGJlIGJldHdlZW4gMCBhbmQgMjU1LlwifWZ1bmN0aW9uIHBlKHQpe2lmKG51bGw9PT10KXJldHVybiBLdDtpZihcInN0cmluZ1wiPT10eXBlb2YgdClyZXR1cm4gWHQ7aWYoXCJib29sZWFuXCI9PXR5cGVvZiB0KXJldHVybiBKdDtpZihcIm51bWJlclwiPT10eXBlb2YgdClyZXR1cm4gR3Q7aWYodCBpbnN0YW5jZW9mIGFlKXJldHVybiBIdDtpZih0IGluc3RhbmNlb2Ygb2UpcmV0dXJuIFd0O2lmKHQgaW5zdGFuY2VvZiB1ZSlyZXR1cm4gUXQ7aWYoQXJyYXkuaXNBcnJheSh0KSl7Zm9yKHZhciBlLHI9dC5sZW5ndGgsbj0wLGk9dDtuPGkubGVuZ3RoO24rPTEpe3ZhciBhPXBlKGlbbl0pO2lmKGUpe2lmKGU9PT1hKWNvbnRpbnVlO2U9JHQ7YnJlYWt9ZT1hO31yZXR1cm4gdGUoZXx8JHQscil9cmV0dXJuIFl0fWZ1bmN0aW9uIGNlKHQpe3ZhciBlPXR5cGVvZiB0O3JldHVybiBudWxsPT09dD9cIlwiOlwic3RyaW5nXCI9PT1lfHxcIm51bWJlclwiPT09ZXx8XCJib29sZWFuXCI9PT1lP1N0cmluZyh0KTp0IGluc3RhbmNlb2YgYWV8fHQgaW5zdGFuY2VvZiB1ZT90LnRvU3RyaW5nKCk6SlNPTi5zdHJpbmdpZnkodCl9dWUuZnJvbVN0cmluZz1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IHVlKFtuZXcgc2UodCxudWxsLG51bGwpXSl9LHVlLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNlY3Rpb25zLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC50ZXh0fSkuam9pbihcIlwiKX0sdWUucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe2Zvcih2YXIgdD1bXCJmb3JtYXRcIl0sZT0wLHI9dGhpcy5zZWN0aW9ucztlPHIubGVuZ3RoO2UrPTEpe3ZhciBuPXJbZV07dC5wdXNoKG4udGV4dCk7dmFyIGk9e307bi5mb250U3RhY2smJihpW1widGV4dC1mb250XCJdPVtcImxpdGVyYWxcIixuLmZvbnRTdGFjay5zcGxpdChcIixcIildKSxuLnNjYWxlJiYoaVtcImZvbnQtc2NhbGVcIl09bi5zY2FsZSksdC5wdXNoKGkpO31yZXR1cm4gdH07dmFyIGhlPWZ1bmN0aW9uKHQsZSl7dGhpcy50eXBlPXQsdGhpcy52YWx1ZT1lO307aGUucGFyc2U9ZnVuY3Rpb24odCxlKXtpZigyIT09dC5sZW5ndGgpcmV0dXJuIGUuZXJyb3IoXCInbGl0ZXJhbCcgZXhwcmVzc2lvbiByZXF1aXJlcyBleGFjdGx5IG9uZSBhcmd1bWVudCwgYnV0IGZvdW5kIFwiKyh0Lmxlbmd0aC0xKStcIiBpbnN0ZWFkLlwiKTtpZighZnVuY3Rpb24gdChlKXtpZihudWxsPT09ZSlyZXR1cm4gITA7aWYoXCJzdHJpbmdcIj09dHlwZW9mIGUpcmV0dXJuICEwO2lmKFwiYm9vbGVhblwiPT10eXBlb2YgZSlyZXR1cm4gITA7aWYoXCJudW1iZXJcIj09dHlwZW9mIGUpcmV0dXJuICEwO2lmKGUgaW5zdGFuY2VvZiBhZSlyZXR1cm4gITA7aWYoZSBpbnN0YW5jZW9mIG9lKXJldHVybiAhMDtpZihlIGluc3RhbmNlb2YgdWUpcmV0dXJuICEwO2lmKEFycmF5LmlzQXJyYXkoZSkpe2Zvcih2YXIgcj0wLG49ZTtyPG4ubGVuZ3RoO3IrPTEpaWYoIXQobltyXSkpcmV0dXJuICExO3JldHVybiAhMH1pZihcIm9iamVjdFwiPT10eXBlb2YgZSl7Zm9yKHZhciBpIGluIGUpaWYoIXQoZVtpXSkpcmV0dXJuICExO3JldHVybiAhMH1yZXR1cm4gITF9KHRbMV0pKXJldHVybiBlLmVycm9yKFwiaW52YWxpZCB2YWx1ZVwiKTt2YXIgcj10WzFdLG49cGUociksaT1lLmV4cGVjdGVkVHlwZTtyZXR1cm4gXCJhcnJheVwiIT09bi5raW5kfHwwIT09bi5OfHwhaXx8XCJhcnJheVwiIT09aS5raW5kfHxcIm51bWJlclwiPT10eXBlb2YgaS5OJiYwIT09aS5OfHwobj1pKSxuZXcgaGUobixyKX0saGUucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudmFsdWV9LGhlLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24oKXt9LGhlLnByb3RvdHlwZS5wb3NzaWJsZU91dHB1dHM9ZnVuY3Rpb24oKXtyZXR1cm4gW3RoaXMudmFsdWVdfSxoZS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuIFwiYXJyYXlcIj09PXRoaXMudHlwZS5raW5kfHxcIm9iamVjdFwiPT09dGhpcy50eXBlLmtpbmQ/W1wibGl0ZXJhbFwiLHRoaXMudmFsdWVdOnRoaXMudmFsdWUgaW5zdGFuY2VvZiBhZT9bXCJyZ2JhXCJdLmNvbmNhdCh0aGlzLnZhbHVlLnRvQXJyYXkoKSk6dGhpcy52YWx1ZSBpbnN0YW5jZW9mIHVlP3RoaXMudmFsdWUuc2VyaWFsaXplKCk6dGhpcy52YWx1ZX07dmFyIGZlPWZ1bmN0aW9uKHQpe3RoaXMubmFtZT1cIkV4cHJlc3Npb25FdmFsdWF0aW9uRXJyb3JcIix0aGlzLm1lc3NhZ2U9dDt9O2ZlLnByb3RvdHlwZS50b0pTT049ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tZXNzYWdlfTt2YXIgeWU9e3N0cmluZzpYdCxudW1iZXI6R3QsYm9vbGVhbjpKdCxvYmplY3Q6WXR9LGRlPWZ1bmN0aW9uKHQsZSl7dGhpcy50eXBlPXQsdGhpcy5hcmdzPWU7fTtkZS5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKHQubGVuZ3RoPDIpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhdCBsZWFzdCBvbmUgYXJndW1lbnQuXCIpO3ZhciByLG49MSxpPXRbMF07aWYoXCJhcnJheVwiPT09aSl7dmFyIGEsbztpZih0Lmxlbmd0aD4yKXt2YXIgcz10WzFdO2lmKFwic3RyaW5nXCIhPXR5cGVvZiBzfHwhKHMgaW4geWUpfHxcIm9iamVjdFwiPT09cylyZXR1cm4gZS5lcnJvcignVGhlIGl0ZW0gdHlwZSBhcmd1bWVudCBvZiBcImFycmF5XCIgbXVzdCBiZSBvbmUgb2Ygc3RyaW5nLCBudW1iZXIsIGJvb2xlYW4nLDEpO2E9eWVbc10sbisrO31lbHNlIGE9JHQ7aWYodC5sZW5ndGg+Myl7aWYobnVsbCE9PXRbMl0mJihcIm51bWJlclwiIT10eXBlb2YgdFsyXXx8dFsyXTwwfHx0WzJdIT09TWF0aC5mbG9vcih0WzJdKSkpcmV0dXJuIGUuZXJyb3IoJ1RoZSBsZW5ndGggYXJndW1lbnQgdG8gXCJhcnJheVwiIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyIGxpdGVyYWwnLDIpO289dFsyXSxuKys7fXI9dGUoYSxvKTt9ZWxzZSByPXllW2ldO2Zvcih2YXIgdT1bXTtuPHQubGVuZ3RoO24rKyl7dmFyIGw9ZS5wYXJzZSh0W25dLG4sJHQpO2lmKCFsKXJldHVybiBudWxsO3UucHVzaChsKTt9cmV0dXJuIG5ldyBkZShyLHUpfSxkZS5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTA7ZTx0aGlzLmFyZ3MubGVuZ3RoO2UrKyl7dmFyIHI9dGhpcy5hcmdzW2VdLmV2YWx1YXRlKHQpO2lmKCFuZSh0aGlzLnR5cGUscGUocikpKXJldHVybiByO2lmKGU9PT10aGlzLmFyZ3MubGVuZ3RoLTEpdGhyb3cgbmV3IGZlKFwiRXhwZWN0ZWQgdmFsdWUgdG8gYmUgb2YgdHlwZSBcIitlZSh0aGlzLnR5cGUpK1wiLCBidXQgZm91bmQgXCIrZWUocGUocikpK1wiIGluc3RlYWQuXCIpfXJldHVybiBudWxsfSxkZS5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKHQpe3RoaXMuYXJncy5mb3JFYWNoKHQpO30sZGUucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3ZhciB0O3JldHVybiAodD1bXSkuY29uY2F0LmFwcGx5KHQsdGhpcy5hcmdzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC5wb3NzaWJsZU91dHB1dHMoKX0pKX0sZGUucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3ZhciB0PXRoaXMudHlwZSxlPVt0LmtpbmRdO2lmKFwiYXJyYXlcIj09PXQua2luZCl7dmFyIHI9dC5pdGVtVHlwZTtpZihcInN0cmluZ1wiPT09ci5raW5kfHxcIm51bWJlclwiPT09ci5raW5kfHxcImJvb2xlYW5cIj09PXIua2luZCl7ZS5wdXNoKHIua2luZCk7dmFyIG49dC5OOyhcIm51bWJlclwiPT10eXBlb2Ygbnx8dGhpcy5hcmdzLmxlbmd0aD4xKSYmZS5wdXNoKG4pO319cmV0dXJuIGUuY29uY2F0KHRoaXMuYXJncy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuc2VyaWFsaXplKCl9KSl9O3ZhciBtZT1mdW5jdGlvbih0KXt0aGlzLnR5cGU9UXQsdGhpcy5zZWN0aW9ucz10O307bWUucGFyc2U9ZnVuY3Rpb24odCxlKXtpZih0Lmxlbmd0aDwzKXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgYXQgbGVhc3QgdHdvIGFyZ3VtZW50cy5cIik7aWYoKHQubGVuZ3RoLTEpJTIhPTApcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhbiBldmVuIG51bWJlciBvZiBhcmd1bWVudHMuXCIpO2Zvcih2YXIgcj1bXSxuPTE7bjx0Lmxlbmd0aC0xO24rPTIpe3ZhciBpPWUucGFyc2UodFtuXSwxLCR0KTtpZighaSlyZXR1cm4gbnVsbDt2YXIgYT1pLnR5cGUua2luZDtpZihcInN0cmluZ1wiIT09YSYmXCJ2YWx1ZVwiIT09YSYmXCJudWxsXCIhPT1hKXJldHVybiBlLmVycm9yKFwiRm9ybWF0dGVkIHRleHQgdHlwZSBtdXN0IGJlICdzdHJpbmcnLCAndmFsdWUnLCBvciAnbnVsbCcuXCIpO3ZhciBvPXRbbisxXTtpZihcIm9iamVjdFwiIT10eXBlb2Ygb3x8QXJyYXkuaXNBcnJheShvKSlyZXR1cm4gZS5lcnJvcihcIkZvcm1hdCBvcHRpb25zIGFyZ3VtZW50IG11c3QgYmUgYW4gb2JqZWN0LlwiKTt2YXIgcz1udWxsO2lmKG9bXCJmb250LXNjYWxlXCJdJiYhKHM9ZS5wYXJzZShvW1wiZm9udC1zY2FsZVwiXSwxLEd0KSkpcmV0dXJuIG51bGw7dmFyIHU9bnVsbDtpZihvW1widGV4dC1mb250XCJdJiYhKHU9ZS5wYXJzZShvW1widGV4dC1mb250XCJdLDEsdGUoWHQpKSkpcmV0dXJuIG51bGw7ci5wdXNoKHt0ZXh0Omksc2NhbGU6cyxmb250OnV9KTt9cmV0dXJuIG5ldyBtZShyKX0sbWUucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgdWUodGhpcy5zZWN0aW9ucy5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIG5ldyBzZShjZShlLnRleHQuZXZhbHVhdGUodCkpLGUuc2NhbGU/ZS5zY2FsZS5ldmFsdWF0ZSh0KTpudWxsLGUuZm9udD9lLmZvbnQuZXZhbHVhdGUodCkuam9pbihcIixcIik6bnVsbCl9KSl9LG1lLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTAscj10aGlzLnNlY3Rpb25zO2U8ci5sZW5ndGg7ZSs9MSl7dmFyIG49cltlXTt0KG4udGV4dCksbi5zY2FsZSYmdChuLnNjYWxlKSxuLmZvbnQmJnQobi5mb250KTt9fSxtZS5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7cmV0dXJuIFt2b2lkIDBdfSxtZS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PVtcImZvcm1hdFwiXSxlPTAscj10aGlzLnNlY3Rpb25zO2U8ci5sZW5ndGg7ZSs9MSl7dmFyIG49cltlXTt0LnB1c2gobi50ZXh0LnNlcmlhbGl6ZSgpKTt2YXIgaT17fTtuLnNjYWxlJiYoaVtcImZvbnQtc2NhbGVcIl09bi5zY2FsZS5zZXJpYWxpemUoKSksbi5mb250JiYoaVtcInRleHQtZm9udFwiXT1uLmZvbnQuc2VyaWFsaXplKCkpLHQucHVzaChpKTt9cmV0dXJuIHR9O3ZhciB2ZT17XCJ0by1ib29sZWFuXCI6SnQsXCJ0by1jb2xvclwiOkh0LFwidG8tbnVtYmVyXCI6R3QsXCJ0by1zdHJpbmdcIjpYdH0sZ2U9ZnVuY3Rpb24odCxlKXt0aGlzLnR5cGU9dCx0aGlzLmFyZ3M9ZTt9O2dlLnBhcnNlPWZ1bmN0aW9uKHQsZSl7aWYodC5sZW5ndGg8MilyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIGF0IGxlYXN0IG9uZSBhcmd1bWVudC5cIik7dmFyIHI9dFswXTtpZigoXCJ0by1ib29sZWFuXCI9PT1yfHxcInRvLXN0cmluZ1wiPT09cikmJjIhPT10Lmxlbmd0aClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIG9uZSBhcmd1bWVudC5cIik7Zm9yKHZhciBuPXZlW3JdLGk9W10sYT0xO2E8dC5sZW5ndGg7YSsrKXt2YXIgbz1lLnBhcnNlKHRbYV0sYSwkdCk7aWYoIW8pcmV0dXJuIG51bGw7aS5wdXNoKG8pO31yZXR1cm4gbmV3IGdlKG4saSl9LGdlLnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXtpZihcImJvb2xlYW5cIj09PXRoaXMudHlwZS5raW5kKXJldHVybiBCb29sZWFuKHRoaXMuYXJnc1swXS5ldmFsdWF0ZSh0KSk7aWYoXCJjb2xvclwiPT09dGhpcy50eXBlLmtpbmQpe2Zvcih2YXIgZSxyLG49MCxpPXRoaXMuYXJncztuPGkubGVuZ3RoO24rPTEpe2lmKHI9bnVsbCwoZT1pW25dLmV2YWx1YXRlKHQpKWluc3RhbmNlb2YgYWUpcmV0dXJuIGU7aWYoXCJzdHJpbmdcIj09dHlwZW9mIGUpe3ZhciBhPXQucGFyc2VDb2xvcihlKTtpZihhKXJldHVybiBhfWVsc2UgaWYoQXJyYXkuaXNBcnJheShlKSYmIShyPWUubGVuZ3RoPDN8fGUubGVuZ3RoPjQ/XCJJbnZhbGlkIHJiZ2EgdmFsdWUgXCIrSlNPTi5zdHJpbmdpZnkoZSkrXCI6IGV4cGVjdGVkIGFuIGFycmF5IGNvbnRhaW5pbmcgZWl0aGVyIHRocmVlIG9yIGZvdXIgbnVtZXJpYyB2YWx1ZXMuXCI6bGUoZVswXSxlWzFdLGVbMl0sZVszXSkpKXJldHVybiBuZXcgYWUoZVswXS8yNTUsZVsxXS8yNTUsZVsyXS8yNTUsZVszXSl9dGhyb3cgbmV3IGZlKHJ8fFwiQ291bGQgbm90IHBhcnNlIGNvbG9yIGZyb20gdmFsdWUgJ1wiKyhcInN0cmluZ1wiPT10eXBlb2YgZT9lOlN0cmluZyhKU09OLnN0cmluZ2lmeShlKSkpK1wiJ1wiKX1pZihcIm51bWJlclwiPT09dGhpcy50eXBlLmtpbmQpe2Zvcih2YXIgbz1udWxsLHM9MCx1PXRoaXMuYXJncztzPHUubGVuZ3RoO3MrPTEpe2lmKG51bGw9PT0obz11W3NdLmV2YWx1YXRlKHQpKSlyZXR1cm4gMDt2YXIgbD1OdW1iZXIobyk7aWYoIWlzTmFOKGwpKXJldHVybiBsfXRocm93IG5ldyBmZShcIkNvdWxkIG5vdCBjb252ZXJ0IFwiK0pTT04uc3RyaW5naWZ5KG8pK1wiIHRvIG51bWJlci5cIil9cmV0dXJuIFwiZm9ybWF0dGVkXCI9PT10aGlzLnR5cGUua2luZD91ZS5mcm9tU3RyaW5nKGNlKHRoaXMuYXJnc1swXS5ldmFsdWF0ZSh0KSkpOmNlKHRoaXMuYXJnc1swXS5ldmFsdWF0ZSh0KSl9LGdlLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dGhpcy5hcmdzLmZvckVhY2godCk7fSxnZS5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuICh0PVtdKS5jb25jYXQuYXBwbHkodCx0aGlzLmFyZ3MubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LnBvc3NpYmxlT3V0cHV0cygpfSkpfSxnZS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7aWYoXCJmb3JtYXR0ZWRcIj09PXRoaXMudHlwZS5raW5kKXJldHVybiBuZXcgbWUoW3t0ZXh0OnRoaXMuYXJnc1swXSxzY2FsZTpudWxsLGZvbnQ6bnVsbH1dKS5zZXJpYWxpemUoKTt2YXIgdD1bXCJ0by1cIit0aGlzLnR5cGUua2luZF07cmV0dXJuIHRoaXMuZWFjaENoaWxkKGZ1bmN0aW9uKGUpe3QucHVzaChlLnNlcmlhbGl6ZSgpKTt9KSx0fTt2YXIgeGU9W1wiVW5rbm93blwiLFwiUG9pbnRcIixcIkxpbmVTdHJpbmdcIixcIlBvbHlnb25cIl0sYmU9ZnVuY3Rpb24oKXt0aGlzLmdsb2JhbHM9bnVsbCx0aGlzLmZlYXR1cmU9bnVsbCx0aGlzLmZlYXR1cmVTdGF0ZT1udWxsLHRoaXMuX3BhcnNlQ29sb3JDYWNoZT17fTt9O2JlLnByb3RvdHlwZS5pZD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmZlYXR1cmUmJlwiaWRcImluIHRoaXMuZmVhdHVyZT90aGlzLmZlYXR1cmUuaWQ6bnVsbH0sYmUucHJvdG90eXBlLmdlb21ldHJ5VHlwZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmZlYXR1cmU/XCJudW1iZXJcIj09dHlwZW9mIHRoaXMuZmVhdHVyZS50eXBlP3hlW3RoaXMuZmVhdHVyZS50eXBlXTp0aGlzLmZlYXR1cmUudHlwZTpudWxsfSxiZS5wcm90b3R5cGUucHJvcGVydGllcz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmZlYXR1cmUmJnRoaXMuZmVhdHVyZS5wcm9wZXJ0aWVzfHx7fX0sYmUucHJvdG90eXBlLnBhcnNlQ29sb3I9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5fcGFyc2VDb2xvckNhY2hlW3RdO3JldHVybiBlfHwoZT10aGlzLl9wYXJzZUNvbG9yQ2FjaGVbdF09YWUucGFyc2UodCkpLGV9O3ZhciBfZT1mdW5jdGlvbih0LGUscixuKXt0aGlzLm5hbWU9dCx0aGlzLnR5cGU9ZSx0aGlzLl9ldmFsdWF0ZT1yLHRoaXMuYXJncz1uO307X2UucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9ldmFsdWF0ZSh0LHRoaXMuYXJncyl9LF9lLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dGhpcy5hcmdzLmZvckVhY2godCk7fSxfZS5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7cmV0dXJuIFt2b2lkIDBdfSxfZS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuIFt0aGlzLm5hbWVdLmNvbmNhdCh0aGlzLmFyZ3MubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LnNlcmlhbGl6ZSgpfSkpfSxfZS5wYXJzZT1mdW5jdGlvbih0LGUpe3ZhciByLG49dFswXSxpPV9lLmRlZmluaXRpb25zW25dO2lmKCFpKXJldHVybiBlLmVycm9yKCdVbmtub3duIGV4cHJlc3Npb24gXCInK24rJ1wiLiBJZiB5b3Ugd2FudGVkIGEgbGl0ZXJhbCBhcnJheSwgdXNlIFtcImxpdGVyYWxcIiwgWy4uLl1dLicsMCk7Zm9yKHZhciBhPUFycmF5LmlzQXJyYXkoaSk/aVswXTppLnR5cGUsbz1BcnJheS5pc0FycmF5KGkpP1tbaVsxXSxpWzJdXV06aS5vdmVybG9hZHMscz1vLmZpbHRlcihmdW5jdGlvbihlKXt2YXIgcj1lWzBdO3JldHVybiAhQXJyYXkuaXNBcnJheShyKXx8ci5sZW5ndGg9PT10Lmxlbmd0aC0xfSksdT1udWxsLGw9MCxwPXM7bDxwLmxlbmd0aDtsKz0xKXt2YXIgYz1wW2xdLGg9Y1swXSxmPWNbMV07dT1uZXcgSWUoZS5yZWdpc3RyeSxlLnBhdGgsbnVsbCxlLnNjb3BlKTtmb3IodmFyIHk9W10sZD0hMSxtPTE7bTx0Lmxlbmd0aDttKyspe3ZhciB2PXRbbV0sZz1BcnJheS5pc0FycmF5KGgpP2hbbS0xXTpoLnR5cGUseD11LnBhcnNlKHYsMSt5Lmxlbmd0aCxnKTtpZigheCl7ZD0hMDticmVha315LnB1c2goeCk7fWlmKCFkKWlmKEFycmF5LmlzQXJyYXkoaCkmJmgubGVuZ3RoIT09eS5sZW5ndGgpdS5lcnJvcihcIkV4cGVjdGVkIFwiK2gubGVuZ3RoK1wiIGFyZ3VtZW50cywgYnV0IGZvdW5kIFwiK3kubGVuZ3RoK1wiIGluc3RlYWQuXCIpO2Vsc2V7Zm9yKHZhciBiPTA7Yjx5Lmxlbmd0aDtiKyspe3ZhciBfPUFycmF5LmlzQXJyYXkoaCk/aFtiXTpoLnR5cGUsdz15W2JdO3UuY29uY2F0KGIrMSkuY2hlY2tTdWJ0eXBlKF8sdy50eXBlKTt9aWYoMD09PXUuZXJyb3JzLmxlbmd0aClyZXR1cm4gbmV3IF9lKG4sYSxmLHkpfX1pZigxPT09cy5sZW5ndGgpKHI9ZS5lcnJvcnMpLnB1c2guYXBwbHkocix1LmVycm9ycyk7ZWxzZXtmb3IodmFyIEE9KHMubGVuZ3RoP3M6bykubWFwKGZ1bmN0aW9uKHQpe3ZhciBlLHI9dFswXTtyZXR1cm4gZT1yLEFycmF5LmlzQXJyYXkoZSk/XCIoXCIrZS5tYXAoZWUpLmpvaW4oXCIsIFwiKStcIilcIjpcIihcIitlZShlLnR5cGUpK1wiLi4uKVwifSkuam9pbihcIiB8IFwiKSxTPVtdLGs9MTtrPHQubGVuZ3RoO2srKyl7dmFyIHo9ZS5wYXJzZSh0W2tdLDErUy5sZW5ndGgpO2lmKCF6KXJldHVybiBudWxsO1MucHVzaChlZSh6LnR5cGUpKTt9ZS5lcnJvcihcIkV4cGVjdGVkIGFyZ3VtZW50cyBvZiB0eXBlIFwiK0ErXCIsIGJ1dCBmb3VuZCAoXCIrUy5qb2luKFwiLCBcIikrXCIpIGluc3RlYWQuXCIpO31yZXR1cm4gbnVsbH0sX2UucmVnaXN0ZXI9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHIgaW4gX2UuZGVmaW5pdGlvbnM9ZSxlKXRbcl09X2U7fTt2YXIgd2U9ZnVuY3Rpb24odCxlLHIpe3RoaXMudHlwZT1XdCx0aGlzLmxvY2FsZT1yLHRoaXMuY2FzZVNlbnNpdGl2ZT10LHRoaXMuZGlhY3JpdGljU2Vuc2l0aXZlPWU7fTtmdW5jdGlvbiBBZSh0KXtpZih0IGluc3RhbmNlb2YgX2Upe2lmKFwiZ2V0XCI9PT10Lm5hbWUmJjE9PT10LmFyZ3MubGVuZ3RoKXJldHVybiAhMTtpZihcImZlYXR1cmUtc3RhdGVcIj09PXQubmFtZSlyZXR1cm4gITE7aWYoXCJoYXNcIj09PXQubmFtZSYmMT09PXQuYXJncy5sZW5ndGgpcmV0dXJuICExO2lmKFwicHJvcGVydGllc1wiPT09dC5uYW1lfHxcImdlb21ldHJ5LXR5cGVcIj09PXQubmFtZXx8XCJpZFwiPT09dC5uYW1lKXJldHVybiAhMTtpZigvXmZpbHRlci0vLnRlc3QodC5uYW1lKSlyZXR1cm4gITF9dmFyIGU9ITA7cmV0dXJuIHQuZWFjaENoaWxkKGZ1bmN0aW9uKHQpe2UmJiFBZSh0KSYmKGU9ITEpO30pLGV9ZnVuY3Rpb24gU2UodCl7aWYodCBpbnN0YW5jZW9mIF9lJiZcImZlYXR1cmUtc3RhdGVcIj09PXQubmFtZSlyZXR1cm4gITE7dmFyIGU9ITA7cmV0dXJuIHQuZWFjaENoaWxkKGZ1bmN0aW9uKHQpe2UmJiFTZSh0KSYmKGU9ITEpO30pLGV9ZnVuY3Rpb24ga2UodCxlKXtpZih0IGluc3RhbmNlb2YgX2UmJmUuaW5kZXhPZih0Lm5hbWUpPj0wKXJldHVybiAhMTt2YXIgcj0hMDtyZXR1cm4gdC5lYWNoQ2hpbGQoZnVuY3Rpb24odCl7ciYmIWtlKHQsZSkmJihyPSExKTt9KSxyfXdlLnBhcnNlPWZ1bmN0aW9uKHQsZSl7aWYoMiE9PXQubGVuZ3RoKXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgb25lIGFyZ3VtZW50LlwiKTt2YXIgcj10WzFdO2lmKFwib2JqZWN0XCIhPXR5cGVvZiByfHxBcnJheS5pc0FycmF5KHIpKXJldHVybiBlLmVycm9yKFwiQ29sbGF0b3Igb3B0aW9ucyBhcmd1bWVudCBtdXN0IGJlIGFuIG9iamVjdC5cIik7dmFyIG49ZS5wYXJzZSh2b2lkIDAhPT1yW1wiY2FzZS1zZW5zaXRpdmVcIl0mJnJbXCJjYXNlLXNlbnNpdGl2ZVwiXSwxLEp0KTtpZighbilyZXR1cm4gbnVsbDt2YXIgaT1lLnBhcnNlKHZvaWQgMCE9PXJbXCJkaWFjcml0aWMtc2Vuc2l0aXZlXCJdJiZyW1wiZGlhY3JpdGljLXNlbnNpdGl2ZVwiXSwxLEp0KTtpZighaSlyZXR1cm4gbnVsbDt2YXIgYT1udWxsO3JldHVybiByLmxvY2FsZSYmIShhPWUucGFyc2Uoci5sb2NhbGUsMSxYdCkpP251bGw6bmV3IHdlKG4saSxhKX0sd2UucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgb2UodGhpcy5jYXNlU2Vuc2l0aXZlLmV2YWx1YXRlKHQpLHRoaXMuZGlhY3JpdGljU2Vuc2l0aXZlLmV2YWx1YXRlKHQpLHRoaXMubG9jYWxlP3RoaXMubG9jYWxlLmV2YWx1YXRlKHQpOm51bGwpfSx3ZS5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKHQpe3QodGhpcy5jYXNlU2Vuc2l0aXZlKSx0KHRoaXMuZGlhY3JpdGljU2Vuc2l0aXZlKSx0aGlzLmxvY2FsZSYmdCh0aGlzLmxvY2FsZSk7fSx3ZS5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7cmV0dXJuIFt2b2lkIDBdfSx3ZS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7dmFyIHQ9e307cmV0dXJuIHRbXCJjYXNlLXNlbnNpdGl2ZVwiXT10aGlzLmNhc2VTZW5zaXRpdmUuc2VyaWFsaXplKCksdFtcImRpYWNyaXRpYy1zZW5zaXRpdmVcIl09dGhpcy5kaWFjcml0aWNTZW5zaXRpdmUuc2VyaWFsaXplKCksdGhpcy5sb2NhbGUmJih0LmxvY2FsZT10aGlzLmxvY2FsZS5zZXJpYWxpemUoKSksW1wiY29sbGF0b3JcIix0XX07dmFyIHplPWZ1bmN0aW9uKHQsZSl7dGhpcy50eXBlPWUudHlwZSx0aGlzLm5hbWU9dCx0aGlzLmJvdW5kRXhwcmVzc2lvbj1lO307emUucGFyc2U9ZnVuY3Rpb24odCxlKXtpZigyIT09dC5sZW5ndGh8fFwic3RyaW5nXCIhPXR5cGVvZiB0WzFdKXJldHVybiBlLmVycm9yKFwiJ3ZhcicgZXhwcmVzc2lvbiByZXF1aXJlcyBleGFjdGx5IG9uZSBzdHJpbmcgbGl0ZXJhbCBhcmd1bWVudC5cIik7dmFyIHI9dFsxXTtyZXR1cm4gZS5zY29wZS5oYXMocik/bmV3IHplKHIsZS5zY29wZS5nZXQocikpOmUuZXJyb3IoJ1Vua25vd24gdmFyaWFibGUgXCInK3IrJ1wiLiBNYWtlIHN1cmUgXCInK3IrJ1wiIGhhcyBiZWVuIGJvdW5kIGluIGFuIGVuY2xvc2luZyBcImxldFwiIGV4cHJlc3Npb24gYmVmb3JlIHVzaW5nIGl0LicsMSl9LHplLnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5ib3VuZEV4cHJlc3Npb24uZXZhbHVhdGUodCl9LHplLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24oKXt9LHplLnByb3RvdHlwZS5wb3NzaWJsZU91dHB1dHM9ZnVuY3Rpb24oKXtyZXR1cm4gW3ZvaWQgMF19LHplLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXtyZXR1cm4gW1widmFyXCIsdGhpcy5uYW1lXX07dmFyIEllPWZ1bmN0aW9uKHQsZSxyLG4saSl7dm9pZCAwPT09ZSYmKGU9W10pLHZvaWQgMD09PW4mJihuPW5ldyBadCksdm9pZCAwPT09aSYmKGk9W10pLHRoaXMucmVnaXN0cnk9dCx0aGlzLnBhdGg9ZSx0aGlzLmtleT1lLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gXCJbXCIrdCtcIl1cIn0pLmpvaW4oXCJcIiksdGhpcy5zY29wZT1uLHRoaXMuZXJyb3JzPWksdGhpcy5leHBlY3RlZFR5cGU9cjt9O2Z1bmN0aW9uIEJlKHQsZSl7Zm9yKHZhciByLG4saT10Lmxlbmd0aC0xLGE9MCxvPWkscz0wO2E8PW87KWlmKHI9dFtzPU1hdGguZmxvb3IoKGErbykvMildLG49dFtzKzFdLHI8PWUpe2lmKHM9PT1pfHxlPG4pcmV0dXJuIHM7YT1zKzE7fWVsc2V7aWYoIShyPmUpKXRocm93IG5ldyBmZShcIklucHV0IGlzIG5vdCBhIG51bWJlci5cIik7bz1zLTE7fXJldHVybiAwfUllLnByb3RvdHlwZS5wYXJzZT1mdW5jdGlvbih0LGUscixuLGkpe3JldHVybiB2b2lkIDA9PT1pJiYoaT17fSksZT90aGlzLmNvbmNhdChlLHIsbikuX3BhcnNlKHQsaSk6dGhpcy5fcGFyc2UodCxpKX0sSWUucHJvdG90eXBlLl9wYXJzZT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIodCxlLHIpe3JldHVybiBcImFzc2VydFwiPT09cj9uZXcgZGUoZSxbdF0pOlwiY29lcmNlXCI9PT1yP25ldyBnZShlLFt0XSk6dH1pZihudWxsIT09dCYmXCJzdHJpbmdcIiE9dHlwZW9mIHQmJlwiYm9vbGVhblwiIT10eXBlb2YgdCYmXCJudW1iZXJcIiE9dHlwZW9mIHR8fCh0PVtcImxpdGVyYWxcIix0XSksQXJyYXkuaXNBcnJheSh0KSl7aWYoMD09PXQubGVuZ3RoKXJldHVybiB0aGlzLmVycm9yKCdFeHBlY3RlZCBhbiBhcnJheSB3aXRoIGF0IGxlYXN0IG9uZSBlbGVtZW50LiBJZiB5b3Ugd2FudGVkIGEgbGl0ZXJhbCBhcnJheSwgdXNlIFtcImxpdGVyYWxcIiwgW11dLicpO3ZhciBuPXRbMF07aWYoXCJzdHJpbmdcIiE9dHlwZW9mIG4pcmV0dXJuIHRoaXMuZXJyb3IoXCJFeHByZXNzaW9uIG5hbWUgbXVzdCBiZSBhIHN0cmluZywgYnV0IGZvdW5kIFwiK3R5cGVvZiBuKycgaW5zdGVhZC4gSWYgeW91IHdhbnRlZCBhIGxpdGVyYWwgYXJyYXksIHVzZSBbXCJsaXRlcmFsXCIsIFsuLi5dXS4nLDApLG51bGw7dmFyIGk9dGhpcy5yZWdpc3RyeVtuXTtpZihpKXt2YXIgYT1pLnBhcnNlKHQsdGhpcyk7aWYoIWEpcmV0dXJuIG51bGw7aWYodGhpcy5leHBlY3RlZFR5cGUpe3ZhciBvPXRoaXMuZXhwZWN0ZWRUeXBlLHM9YS50eXBlO2lmKFwic3RyaW5nXCIhPT1vLmtpbmQmJlwibnVtYmVyXCIhPT1vLmtpbmQmJlwiYm9vbGVhblwiIT09by5raW5kJiZcIm9iamVjdFwiIT09by5raW5kJiZcImFycmF5XCIhPT1vLmtpbmR8fFwidmFsdWVcIiE9PXMua2luZClpZihcImNvbG9yXCIhPT1vLmtpbmQmJlwiZm9ybWF0dGVkXCIhPT1vLmtpbmR8fFwidmFsdWVcIiE9PXMua2luZCYmXCJzdHJpbmdcIiE9PXMua2luZCl7aWYodGhpcy5jaGVja1N1YnR5cGUobyxzKSlyZXR1cm4gbnVsbH1lbHNlIGE9cihhLG8sZS50eXBlQW5ub3RhdGlvbnx8XCJjb2VyY2VcIik7ZWxzZSBhPXIoYSxvLGUudHlwZUFubm90YXRpb258fFwiYXNzZXJ0XCIpO31pZighKGEgaW5zdGFuY2VvZiBoZSkmJmZ1bmN0aW9uIHQoZSl7aWYoZSBpbnN0YW5jZW9mIHplKXJldHVybiB0KGUuYm91bmRFeHByZXNzaW9uKTtpZihlIGluc3RhbmNlb2YgX2UmJlwiZXJyb3JcIj09PWUubmFtZSlyZXR1cm4gITE7aWYoZSBpbnN0YW5jZW9mIHdlKXJldHVybiAhMTt2YXIgcj1lIGluc3RhbmNlb2YgZ2V8fGUgaW5zdGFuY2VvZiBkZTt2YXIgbj0hMDtlLmVhY2hDaGlsZChmdW5jdGlvbihlKXtuPXI/biYmdChlKTpuJiZlIGluc3RhbmNlb2YgaGU7fSk7aWYoIW4pcmV0dXJuICExO3JldHVybiBBZShlKSYma2UoZSxbXCJ6b29tXCIsXCJoZWF0bWFwLWRlbnNpdHlcIixcImxpbmUtcHJvZ3Jlc3NcIixcImFjY3VtdWxhdGVkXCIsXCJpcy1zdXBwb3J0ZWQtc2NyaXB0XCJdKX0oYSkpe3ZhciB1PW5ldyBiZTt0cnl7YT1uZXcgaGUoYS50eXBlLGEuZXZhbHVhdGUodSkpO31jYXRjaCh0KXtyZXR1cm4gdGhpcy5lcnJvcih0Lm1lc3NhZ2UpLG51bGx9fXJldHVybiBhfXJldHVybiB0aGlzLmVycm9yKCdVbmtub3duIGV4cHJlc3Npb24gXCInK24rJ1wiLiBJZiB5b3Ugd2FudGVkIGEgbGl0ZXJhbCBhcnJheSwgdXNlIFtcImxpdGVyYWxcIiwgWy4uLl1dLicsMCl9cmV0dXJuIHZvaWQgMD09PXQ/dGhpcy5lcnJvcihcIid1bmRlZmluZWQnIHZhbHVlIGludmFsaWQuIFVzZSBudWxsIGluc3RlYWQuXCIpOlwib2JqZWN0XCI9PXR5cGVvZiB0P3RoaXMuZXJyb3IoJ0JhcmUgb2JqZWN0cyBpbnZhbGlkLiBVc2UgW1wibGl0ZXJhbFwiLCB7Li4ufV0gaW5zdGVhZC4nKTp0aGlzLmVycm9yKFwiRXhwZWN0ZWQgYW4gYXJyYXksIGJ1dCBmb3VuZCBcIit0eXBlb2YgdCtcIiBpbnN0ZWFkLlwiKX0sSWUucHJvdG90eXBlLmNvbmNhdD1mdW5jdGlvbih0LGUscil7dmFyIG49XCJudW1iZXJcIj09dHlwZW9mIHQ/dGhpcy5wYXRoLmNvbmNhdCh0KTp0aGlzLnBhdGgsaT1yP3RoaXMuc2NvcGUuY29uY2F0KHIpOnRoaXMuc2NvcGU7cmV0dXJuIG5ldyBJZSh0aGlzLnJlZ2lzdHJ5LG4sZXx8bnVsbCxpLHRoaXMuZXJyb3JzKX0sSWUucHJvdG90eXBlLmVycm9yPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT1bXSxyPWFyZ3VtZW50cy5sZW5ndGgtMTtyLS0gPjA7KWVbcl09YXJndW1lbnRzW3IrMV07dmFyIG49XCJcIit0aGlzLmtleStlLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gXCJbXCIrdCtcIl1cIn0pLmpvaW4oXCJcIik7dGhpcy5lcnJvcnMucHVzaChuZXcgTnQobix0KSk7fSxJZS5wcm90b3R5cGUuY2hlY2tTdWJ0eXBlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9bmUodCxlKTtyZXR1cm4gciYmdGhpcy5lcnJvcihyKSxyfTt2YXIgQ2U9ZnVuY3Rpb24odCxlLHIpe3RoaXMudHlwZT10LHRoaXMuaW5wdXQ9ZSx0aGlzLmxhYmVscz1bXSx0aGlzLm91dHB1dHM9W107Zm9yKHZhciBuPTAsaT1yO248aS5sZW5ndGg7bis9MSl7dmFyIGE9aVtuXSxvPWFbMF0scz1hWzFdO3RoaXMubGFiZWxzLnB1c2gobyksdGhpcy5vdXRwdXRzLnB1c2gocyk7fX07ZnVuY3Rpb24gRWUodCxlLHIpe3JldHVybiB0KigxLXIpK2Uqcn1DZS5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKHQubGVuZ3RoLTE8NClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIGF0IGxlYXN0IDQgYXJndW1lbnRzLCBidXQgZm91bmQgb25seSBcIisodC5sZW5ndGgtMSkrXCIuXCIpO2lmKCh0Lmxlbmd0aC0xKSUyIT0wKXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgYW4gZXZlbiBudW1iZXIgb2YgYXJndW1lbnRzLlwiKTt2YXIgcj1lLnBhcnNlKHRbMV0sMSxHdCk7aWYoIXIpcmV0dXJuIG51bGw7dmFyIG49W10saT1udWxsO2UuZXhwZWN0ZWRUeXBlJiZcInZhbHVlXCIhPT1lLmV4cGVjdGVkVHlwZS5raW5kJiYoaT1lLmV4cGVjdGVkVHlwZSk7Zm9yKHZhciBhPTE7YTx0Lmxlbmd0aDthKz0yKXt2YXIgbz0xPT09YT8tMS8wOnRbYV0scz10W2ErMV0sdT1hLGw9YSsxO2lmKFwibnVtYmVyXCIhPXR5cGVvZiBvKXJldHVybiBlLmVycm9yKCdJbnB1dC9vdXRwdXQgcGFpcnMgZm9yIFwic3RlcFwiIGV4cHJlc3Npb25zIG11c3QgYmUgZGVmaW5lZCB1c2luZyBsaXRlcmFsIG51bWVyaWMgdmFsdWVzIChub3QgY29tcHV0ZWQgZXhwcmVzc2lvbnMpIGZvciB0aGUgaW5wdXQgdmFsdWVzLicsdSk7aWYobi5sZW5ndGgmJm5bbi5sZW5ndGgtMV1bMF0+PW8pcmV0dXJuIGUuZXJyb3IoJ0lucHV0L291dHB1dCBwYWlycyBmb3IgXCJzdGVwXCIgZXhwcmVzc2lvbnMgbXVzdCBiZSBhcnJhbmdlZCB3aXRoIGlucHV0IHZhbHVlcyBpbiBzdHJpY3RseSBhc2NlbmRpbmcgb3JkZXIuJyx1KTt2YXIgcD1lLnBhcnNlKHMsbCxpKTtpZighcClyZXR1cm4gbnVsbDtpPWl8fHAudHlwZSxuLnB1c2goW28scF0pO31yZXR1cm4gbmV3IENlKGkscixuKX0sQ2UucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMubGFiZWxzLHI9dGhpcy5vdXRwdXRzO2lmKDE9PT1lLmxlbmd0aClyZXR1cm4gclswXS5ldmFsdWF0ZSh0KTt2YXIgbj10aGlzLmlucHV0LmV2YWx1YXRlKHQpO2lmKG48PWVbMF0pcmV0dXJuIHJbMF0uZXZhbHVhdGUodCk7dmFyIGk9ZS5sZW5ndGg7cmV0dXJuIG4+PWVbaS0xXT9yW2ktMV0uZXZhbHVhdGUodCk6cltCZShlLG4pXS5ldmFsdWF0ZSh0KX0sQ2UucHJvdG90eXBlLmVhY2hDaGlsZD1mdW5jdGlvbih0KXt0KHRoaXMuaW5wdXQpO2Zvcih2YXIgZT0wLHI9dGhpcy5vdXRwdXRzO2U8ci5sZW5ndGg7ZSs9MSl7dChyW2VdKTt9fSxDZS5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuICh0PVtdKS5jb25jYXQuYXBwbHkodCx0aGlzLm91dHB1dHMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LnBvc3NpYmxlT3V0cHV0cygpfSkpfSxDZS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PVtcInN0ZXBcIix0aGlzLmlucHV0LnNlcmlhbGl6ZSgpXSxlPTA7ZTx0aGlzLmxhYmVscy5sZW5ndGg7ZSsrKWU+MCYmdC5wdXNoKHRoaXMubGFiZWxzW2VdKSx0LnB1c2godGhpcy5vdXRwdXRzW2VdLnNlcmlhbGl6ZSgpKTtyZXR1cm4gdH07dmFyIE1lPU9iamVjdC5mcmVlemUoe251bWJlcjpFZSxjb2xvcjpmdW5jdGlvbih0LGUscil7cmV0dXJuIG5ldyBhZShFZSh0LnIsZS5yLHIpLEVlKHQuZyxlLmcsciksRWUodC5iLGUuYixyKSxFZSh0LmEsZS5hLHIpKX0sYXJyYXk6ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0Lm1hcChmdW5jdGlvbih0LG4pe3JldHVybiBFZSh0LGVbbl0scil9KX19KSxUZT0uOTUwNDcsUGU9MSxWZT0xLjA4ODgzLEZlPTQvMjksTGU9Ni8yOSxEZT0zKkxlKkxlLE9lPUxlKkxlKkxlLFJlPU1hdGguUEkvMTgwLFVlPTE4MC9NYXRoLlBJO2Z1bmN0aW9uIGplKHQpe3JldHVybiB0Pk9lP01hdGgucG93KHQsMS8zKTp0L0RlK0ZlfWZ1bmN0aW9uIHFlKHQpe3JldHVybiB0PkxlP3QqdCp0OkRlKih0LUZlKX1mdW5jdGlvbiBOZSh0KXtyZXR1cm4gMjU1Kih0PD0uMDAzMTMwOD8xMi45Mip0OjEuMDU1Kk1hdGgucG93KHQsMS8yLjQpLS4wNTUpfWZ1bmN0aW9uIFplKHQpe3JldHVybiAodC89MjU1KTw9LjA0MDQ1P3QvMTIuOTI6TWF0aC5wb3coKHQrLjA1NSkvMS4wNTUsMi40KX1mdW5jdGlvbiBLZSh0KXt2YXIgZT1aZSh0LnIpLHI9WmUodC5nKSxuPVplKHQuYiksaT1qZSgoLjQxMjQ1NjQqZSsuMzU3NTc2MSpyKy4xODA0Mzc1Km4pL1RlKSxhPWplKCguMjEyNjcyOSplKy43MTUxNTIyKnIrLjA3MjE3NSpuKS9QZSk7cmV0dXJuIHtsOjExNiphLTE2LGE6NTAwKihpLWEpLGI6MjAwKihhLWplKCguMDE5MzMzOSplKy4xMTkxOTIqcisuOTUwMzA0MSpuKS9WZSkpLGFscGhhOnQuYX19ZnVuY3Rpb24gR2UodCl7dmFyIGU9KHQubCsxNikvMTE2LHI9aXNOYU4odC5hKT9lOmUrdC5hLzUwMCxuPWlzTmFOKHQuYik/ZTplLXQuYi8yMDA7cmV0dXJuIGU9UGUqcWUoZSkscj1UZSpxZShyKSxuPVZlKnFlKG4pLG5ldyBhZShOZSgzLjI0MDQ1NDIqci0xLjUzNzEzODUqZS0uNDk4NTMxNCpuKSxOZSgtLjk2OTI2NipyKzEuODc2MDEwOCplKy4wNDE1NTYqbiksTmUoLjA1NTY0MzQqci0uMjA0MDI1OSplKzEuMDU3MjI1MipuKSx0LmFscGhhKX1mdW5jdGlvbiBYZSh0LGUscil7dmFyIG49ZS10O3JldHVybiB0K3IqKG4+MTgwfHxuPC0xODA/bi0zNjAqTWF0aC5yb3VuZChuLzM2MCk6bil9dmFyIEplPXtmb3J3YXJkOktlLHJldmVyc2U6R2UsaW50ZXJwb2xhdGU6ZnVuY3Rpb24odCxlLHIpe3JldHVybiB7bDpFZSh0LmwsZS5sLHIpLGE6RWUodC5hLGUuYSxyKSxiOkVlKHQuYixlLmIsciksYWxwaGE6RWUodC5hbHBoYSxlLmFscGhhLHIpfX19LEhlPXtmb3J3YXJkOmZ1bmN0aW9uKHQpe3ZhciBlPUtlKHQpLHI9ZS5sLG49ZS5hLGk9ZS5iLGE9TWF0aC5hdGFuMihpLG4pKlVlO3JldHVybiB7aDphPDA/YSszNjA6YSxjOk1hdGguc3FydChuKm4raSppKSxsOnIsYWxwaGE6dC5hfX0scmV2ZXJzZTpmdW5jdGlvbih0KXt2YXIgZT10LmgqUmUscj10LmM7cmV0dXJuIEdlKHtsOnQubCxhOk1hdGguY29zKGUpKnIsYjpNYXRoLnNpbihlKSpyLGFscGhhOnQuYWxwaGF9KX0saW50ZXJwb2xhdGU6ZnVuY3Rpb24odCxlLHIpe3JldHVybiB7aDpYZSh0LmgsZS5oLHIpLGM6RWUodC5jLGUuYyxyKSxsOkVlKHQubCxlLmwsciksYWxwaGE6RWUodC5hbHBoYSxlLmFscGhhLHIpfX19LFllPU9iamVjdC5mcmVlemUoe2xhYjpKZSxoY2w6SGV9KSwkZT1mdW5jdGlvbih0LGUscixuLGkpe3RoaXMudHlwZT10LHRoaXMub3BlcmF0b3I9ZSx0aGlzLmludGVycG9sYXRpb249cix0aGlzLmlucHV0PW4sdGhpcy5sYWJlbHM9W10sdGhpcy5vdXRwdXRzPVtdO2Zvcih2YXIgYT0wLG89aTthPG8ubGVuZ3RoO2ErPTEpe3ZhciBzPW9bYV0sdT1zWzBdLGw9c1sxXTt0aGlzLmxhYmVscy5wdXNoKHUpLHRoaXMub3V0cHV0cy5wdXNoKGwpO319O2Z1bmN0aW9uIFdlKHQsZSxyLG4pe3ZhciBpPW4tcixhPXQtcjtyZXR1cm4gMD09PWk/MDoxPT09ZT9hL2k6KE1hdGgucG93KGUsYSktMSkvKE1hdGgucG93KGUsaSktMSl9JGUuaW50ZXJwb2xhdGlvbkZhY3Rvcj1mdW5jdGlvbih0LGUsbixpKXt2YXIgYT0wO2lmKFwiZXhwb25lbnRpYWxcIj09PXQubmFtZSlhPVdlKGUsdC5iYXNlLG4saSk7ZWxzZSBpZihcImxpbmVhclwiPT09dC5uYW1lKWE9V2UoZSwxLG4saSk7ZWxzZSBpZihcImN1YmljLWJlemllclwiPT09dC5uYW1lKXt2YXIgbz10LmNvbnRyb2xQb2ludHM7YT1uZXcgcihvWzBdLG9bMV0sb1syXSxvWzNdKS5zb2x2ZShXZShlLDEsbixpKSk7fXJldHVybiBhfSwkZS5wYXJzZT1mdW5jdGlvbih0LGUpe3ZhciByPXRbMF0sbj10WzFdLGk9dFsyXSxhPXQuc2xpY2UoMyk7aWYoIUFycmF5LmlzQXJyYXkobil8fDA9PT1uLmxlbmd0aClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIGFuIGludGVycG9sYXRpb24gdHlwZSBleHByZXNzaW9uLlwiLDEpO2lmKFwibGluZWFyXCI9PT1uWzBdKW49e25hbWU6XCJsaW5lYXJcIn07ZWxzZSBpZihcImV4cG9uZW50aWFsXCI9PT1uWzBdKXt2YXIgbz1uWzFdO2lmKFwibnVtYmVyXCIhPXR5cGVvZiBvKXJldHVybiBlLmVycm9yKFwiRXhwb25lbnRpYWwgaW50ZXJwb2xhdGlvbiByZXF1aXJlcyBhIG51bWVyaWMgYmFzZS5cIiwxLDEpO249e25hbWU6XCJleHBvbmVudGlhbFwiLGJhc2U6b307fWVsc2V7aWYoXCJjdWJpYy1iZXppZXJcIiE9PW5bMF0pcmV0dXJuIGUuZXJyb3IoXCJVbmtub3duIGludGVycG9sYXRpb24gdHlwZSBcIitTdHJpbmcoblswXSksMSwwKTt2YXIgcz1uLnNsaWNlKDEpO2lmKDQhPT1zLmxlbmd0aHx8cy5zb21lKGZ1bmN0aW9uKHQpe3JldHVybiBcIm51bWJlclwiIT10eXBlb2YgdHx8dDwwfHx0PjF9KSlyZXR1cm4gZS5lcnJvcihcIkN1YmljIGJlemllciBpbnRlcnBvbGF0aW9uIHJlcXVpcmVzIGZvdXIgbnVtZXJpYyBhcmd1bWVudHMgd2l0aCB2YWx1ZXMgYmV0d2VlbiAwIGFuZCAxLlwiLDEpO249e25hbWU6XCJjdWJpYy1iZXppZXJcIixjb250cm9sUG9pbnRzOnN9O31pZih0Lmxlbmd0aC0xPDQpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhdCBsZWFzdCA0IGFyZ3VtZW50cywgYnV0IGZvdW5kIG9ubHkgXCIrKHQubGVuZ3RoLTEpK1wiLlwiKTtpZigodC5sZW5ndGgtMSklMiE9MClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIGFuIGV2ZW4gbnVtYmVyIG9mIGFyZ3VtZW50cy5cIik7aWYoIShpPWUucGFyc2UoaSwyLEd0KSkpcmV0dXJuIG51bGw7dmFyIHU9W10sbD1udWxsO1wiaW50ZXJwb2xhdGUtaGNsXCI9PT1yfHxcImludGVycG9sYXRlLWxhYlwiPT09cj9sPUh0OmUuZXhwZWN0ZWRUeXBlJiZcInZhbHVlXCIhPT1lLmV4cGVjdGVkVHlwZS5raW5kJiYobD1lLmV4cGVjdGVkVHlwZSk7Zm9yKHZhciBwPTA7cDxhLmxlbmd0aDtwKz0yKXt2YXIgYz1hW3BdLGg9YVtwKzFdLGY9cCszLHk9cCs0O2lmKFwibnVtYmVyXCIhPXR5cGVvZiBjKXJldHVybiBlLmVycm9yKCdJbnB1dC9vdXRwdXQgcGFpcnMgZm9yIFwiaW50ZXJwb2xhdGVcIiBleHByZXNzaW9ucyBtdXN0IGJlIGRlZmluZWQgdXNpbmcgbGl0ZXJhbCBudW1lcmljIHZhbHVlcyAobm90IGNvbXB1dGVkIGV4cHJlc3Npb25zKSBmb3IgdGhlIGlucHV0IHZhbHVlcy4nLGYpO2lmKHUubGVuZ3RoJiZ1W3UubGVuZ3RoLTFdWzBdPj1jKXJldHVybiBlLmVycm9yKCdJbnB1dC9vdXRwdXQgcGFpcnMgZm9yIFwiaW50ZXJwb2xhdGVcIiBleHByZXNzaW9ucyBtdXN0IGJlIGFycmFuZ2VkIHdpdGggaW5wdXQgdmFsdWVzIGluIHN0cmljdGx5IGFzY2VuZGluZyBvcmRlci4nLGYpO3ZhciBkPWUucGFyc2UoaCx5LGwpO2lmKCFkKXJldHVybiBudWxsO2w9bHx8ZC50eXBlLHUucHVzaChbYyxkXSk7fXJldHVybiBcIm51bWJlclwiPT09bC5raW5kfHxcImNvbG9yXCI9PT1sLmtpbmR8fFwiYXJyYXlcIj09PWwua2luZCYmXCJudW1iZXJcIj09PWwuaXRlbVR5cGUua2luZCYmXCJudW1iZXJcIj09dHlwZW9mIGwuTj9uZXcgJGUobCxyLG4saSx1KTplLmVycm9yKFwiVHlwZSBcIitlZShsKStcIiBpcyBub3QgaW50ZXJwb2xhdGFibGUuXCIpfSwkZS5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5sYWJlbHMscj10aGlzLm91dHB1dHM7aWYoMT09PWUubGVuZ3RoKXJldHVybiByWzBdLmV2YWx1YXRlKHQpO3ZhciBuPXRoaXMuaW5wdXQuZXZhbHVhdGUodCk7aWYobjw9ZVswXSlyZXR1cm4gclswXS5ldmFsdWF0ZSh0KTt2YXIgaT1lLmxlbmd0aDtpZihuPj1lW2ktMV0pcmV0dXJuIHJbaS0xXS5ldmFsdWF0ZSh0KTt2YXIgYT1CZShlLG4pLG89ZVthXSxzPWVbYSsxXSx1PSRlLmludGVycG9sYXRpb25GYWN0b3IodGhpcy5pbnRlcnBvbGF0aW9uLG4sbyxzKSxsPXJbYV0uZXZhbHVhdGUodCkscD1yW2ErMV0uZXZhbHVhdGUodCk7cmV0dXJuIFwiaW50ZXJwb2xhdGVcIj09PXRoaXMub3BlcmF0b3I/TWVbdGhpcy50eXBlLmtpbmQudG9Mb3dlckNhc2UoKV0obCxwLHUpOlwiaW50ZXJwb2xhdGUtaGNsXCI9PT10aGlzLm9wZXJhdG9yP0hlLnJldmVyc2UoSGUuaW50ZXJwb2xhdGUoSGUuZm9yd2FyZChsKSxIZS5mb3J3YXJkKHApLHUpKTpKZS5yZXZlcnNlKEplLmludGVycG9sYXRlKEplLmZvcndhcmQobCksSmUuZm9yd2FyZChwKSx1KSl9LCRlLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dCh0aGlzLmlucHV0KTtmb3IodmFyIGU9MCxyPXRoaXMub3V0cHV0cztlPHIubGVuZ3RoO2UrPTEpe3QocltlXSk7fX0sJGUucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3ZhciB0O3JldHVybiAodD1bXSkuY29uY2F0LmFwcGx5KHQsdGhpcy5vdXRwdXRzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC5wb3NzaWJsZU91dHB1dHMoKX0pKX0sJGUucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3ZhciB0O3Q9XCJsaW5lYXJcIj09PXRoaXMuaW50ZXJwb2xhdGlvbi5uYW1lP1tcImxpbmVhclwiXTpcImV4cG9uZW50aWFsXCI9PT10aGlzLmludGVycG9sYXRpb24ubmFtZT8xPT09dGhpcy5pbnRlcnBvbGF0aW9uLmJhc2U/W1wibGluZWFyXCJdOltcImV4cG9uZW50aWFsXCIsdGhpcy5pbnRlcnBvbGF0aW9uLmJhc2VdOltcImN1YmljLWJlemllclwiXS5jb25jYXQodGhpcy5pbnRlcnBvbGF0aW9uLmNvbnRyb2xQb2ludHMpO2Zvcih2YXIgZT1bdGhpcy5vcGVyYXRvcix0LHRoaXMuaW5wdXQuc2VyaWFsaXplKCldLHI9MDtyPHRoaXMubGFiZWxzLmxlbmd0aDtyKyspZS5wdXNoKHRoaXMubGFiZWxzW3JdLHRoaXMub3V0cHV0c1tyXS5zZXJpYWxpemUoKSk7cmV0dXJuIGV9O3ZhciBRZT1mdW5jdGlvbih0LGUpe3RoaXMudHlwZT10LHRoaXMuYXJncz1lO307UWUucGFyc2U9ZnVuY3Rpb24odCxlKXtpZih0Lmxlbmd0aDwyKXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWN0ZWQgYXQgbGVhc3Qgb25lIGFyZ3VtZW50LlwiKTt2YXIgcj1udWxsLG49ZS5leHBlY3RlZFR5cGU7biYmXCJ2YWx1ZVwiIT09bi5raW5kJiYocj1uKTtmb3IodmFyIGk9W10sYT0wLG89dC5zbGljZSgxKTthPG8ubGVuZ3RoO2ErPTEpe3ZhciBzPW9bYV0sdT1lLnBhcnNlKHMsMStpLmxlbmd0aCxyLHZvaWQgMCx7dHlwZUFubm90YXRpb246XCJvbWl0XCJ9KTtpZighdSlyZXR1cm4gbnVsbDtyPXJ8fHUudHlwZSxpLnB1c2godSk7fXZhciBsPW4mJmkuc29tZShmdW5jdGlvbih0KXtyZXR1cm4gbmUobix0LnR5cGUpfSk7cmV0dXJuIG5ldyBRZShsPyR0OnIsaSl9LFFlLnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXtmb3IodmFyIGU9bnVsbCxyPTAsbj10aGlzLmFyZ3M7cjxuLmxlbmd0aDtyKz0xKXtpZihudWxsIT09KGU9bltyXS5ldmFsdWF0ZSh0KSkpYnJlYWt9cmV0dXJuIGV9LFFlLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dGhpcy5hcmdzLmZvckVhY2godCk7fSxRZS5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuICh0PVtdKS5jb25jYXQuYXBwbHkodCx0aGlzLmFyZ3MubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LnBvc3NpYmxlT3V0cHV0cygpfSkpfSxRZS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7dmFyIHQ9W1wiY29hbGVzY2VcIl07cmV0dXJuIHRoaXMuZWFjaENoaWxkKGZ1bmN0aW9uKGUpe3QucHVzaChlLnNlcmlhbGl6ZSgpKTt9KSx0fTt2YXIgdHI9ZnVuY3Rpb24odCxlKXt0aGlzLnR5cGU9ZS50eXBlLHRoaXMuYmluZGluZ3M9W10uY29uY2F0KHQpLHRoaXMucmVzdWx0PWU7fTt0ci5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMucmVzdWx0LmV2YWx1YXRlKHQpfSx0ci5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT0wLHI9dGhpcy5iaW5kaW5ncztlPHIubGVuZ3RoO2UrPTEpe3QocltlXVsxXSk7fXQodGhpcy5yZXN1bHQpO30sdHIucGFyc2U9ZnVuY3Rpb24odCxlKXtpZih0Lmxlbmd0aDw0KXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgYXQgbGVhc3QgMyBhcmd1bWVudHMsIGJ1dCBmb3VuZCBcIisodC5sZW5ndGgtMSkrXCIgaW5zdGVhZC5cIik7Zm9yKHZhciByPVtdLG49MTtuPHQubGVuZ3RoLTE7bis9Mil7dmFyIGk9dFtuXTtpZihcInN0cmluZ1wiIT10eXBlb2YgaSlyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIHN0cmluZywgYnV0IGZvdW5kIFwiK3R5cGVvZiBpK1wiIGluc3RlYWQuXCIsbik7aWYoL1teYS16QS1aMC05X10vLnRlc3QoaSkpcmV0dXJuIGUuZXJyb3IoXCJWYXJpYWJsZSBuYW1lcyBtdXN0IGNvbnRhaW4gb25seSBhbHBoYW51bWVyaWMgY2hhcmFjdGVycyBvciAnXycuXCIsbik7dmFyIGE9ZS5wYXJzZSh0W24rMV0sbisxKTtpZighYSlyZXR1cm4gbnVsbDtyLnB1c2goW2ksYV0pO312YXIgbz1lLnBhcnNlKHRbdC5sZW5ndGgtMV0sdC5sZW5ndGgtMSxlLmV4cGVjdGVkVHlwZSxyKTtyZXR1cm4gbz9uZXcgdHIocixvKTpudWxsfSx0ci5wcm90b3R5cGUucG9zc2libGVPdXRwdXRzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucmVzdWx0LnBvc3NpYmxlT3V0cHV0cygpfSx0ci5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PVtcImxldFwiXSxlPTAscj10aGlzLmJpbmRpbmdzO2U8ci5sZW5ndGg7ZSs9MSl7dmFyIG49cltlXSxpPW5bMF0sYT1uWzFdO3QucHVzaChpLGEuc2VyaWFsaXplKCkpO31yZXR1cm4gdC5wdXNoKHRoaXMucmVzdWx0LnNlcmlhbGl6ZSgpKSx0fTt2YXIgZXI9ZnVuY3Rpb24odCxlLHIpe3RoaXMudHlwZT10LHRoaXMuaW5kZXg9ZSx0aGlzLmlucHV0PXI7fTtlci5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKDMhPT10Lmxlbmd0aClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIDIgYXJndW1lbnRzLCBidXQgZm91bmQgXCIrKHQubGVuZ3RoLTEpK1wiIGluc3RlYWQuXCIpO3ZhciByPWUucGFyc2UodFsxXSwxLEd0KSxuPWUucGFyc2UodFsyXSwyLHRlKGUuZXhwZWN0ZWRUeXBlfHwkdCkpO2lmKCFyfHwhbilyZXR1cm4gbnVsbDt2YXIgaT1uLnR5cGU7cmV0dXJuIG5ldyBlcihpLml0ZW1UeXBlLHIsbil9LGVyLnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmluZGV4LmV2YWx1YXRlKHQpLHI9dGhpcy5pbnB1dC5ldmFsdWF0ZSh0KTtpZihlPDApdGhyb3cgbmV3IGZlKFwiQXJyYXkgaW5kZXggb3V0IG9mIGJvdW5kczogXCIrZStcIiA8IDAuXCIpO2lmKGU+PXIubGVuZ3RoKXRocm93IG5ldyBmZShcIkFycmF5IGluZGV4IG91dCBvZiBib3VuZHM6IFwiK2UrXCIgPiBcIisoci5sZW5ndGgtMSkrXCIuXCIpO2lmKGUhPT1NYXRoLmZsb29yKGUpKXRocm93IG5ldyBmZShcIkFycmF5IGluZGV4IG11c3QgYmUgYW4gaW50ZWdlciwgYnV0IGZvdW5kIFwiK2UrXCIgaW5zdGVhZC5cIik7cmV0dXJuIHJbZV19LGVyLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dCh0aGlzLmluZGV4KSx0KHRoaXMuaW5wdXQpO30sZXIucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3JldHVybiBbdm9pZCAwXX0sZXIucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3JldHVybiBbXCJhdFwiLHRoaXMuaW5kZXguc2VyaWFsaXplKCksdGhpcy5pbnB1dC5zZXJpYWxpemUoKV19O3ZhciBycj1mdW5jdGlvbih0LGUscixuLGksYSl7dGhpcy5pbnB1dFR5cGU9dCx0aGlzLnR5cGU9ZSx0aGlzLmlucHV0PXIsdGhpcy5jYXNlcz1uLHRoaXMub3V0cHV0cz1pLHRoaXMub3RoZXJ3aXNlPWE7fTtyci5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKHQubGVuZ3RoPDUpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhdCBsZWFzdCA0IGFyZ3VtZW50cywgYnV0IGZvdW5kIG9ubHkgXCIrKHQubGVuZ3RoLTEpK1wiLlwiKTtpZih0Lmxlbmd0aCUyIT0xKXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgYW4gZXZlbiBudW1iZXIgb2YgYXJndW1lbnRzLlwiKTt2YXIgcixuO2UuZXhwZWN0ZWRUeXBlJiZcInZhbHVlXCIhPT1lLmV4cGVjdGVkVHlwZS5raW5kJiYobj1lLmV4cGVjdGVkVHlwZSk7Zm9yKHZhciBpPXt9LGE9W10sbz0yO288dC5sZW5ndGgtMTtvKz0yKXt2YXIgcz10W29dLHU9dFtvKzFdO0FycmF5LmlzQXJyYXkocyl8fChzPVtzXSk7dmFyIGw9ZS5jb25jYXQobyk7aWYoMD09PXMubGVuZ3RoKXJldHVybiBsLmVycm9yKFwiRXhwZWN0ZWQgYXQgbGVhc3Qgb25lIGJyYW5jaCBsYWJlbC5cIik7Zm9yKHZhciBwPTAsYz1zO3A8Yy5sZW5ndGg7cCs9MSl7dmFyIGg9Y1twXTtpZihcIm51bWJlclwiIT10eXBlb2YgaCYmXCJzdHJpbmdcIiE9dHlwZW9mIGgpcmV0dXJuIGwuZXJyb3IoXCJCcmFuY2ggbGFiZWxzIG11c3QgYmUgbnVtYmVycyBvciBzdHJpbmdzLlwiKTtpZihcIm51bWJlclwiPT10eXBlb2YgaCYmTWF0aC5hYnMoaCk+TnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpcmV0dXJuIGwuZXJyb3IoXCJCcmFuY2ggbGFiZWxzIG11c3QgYmUgaW50ZWdlcnMgbm8gbGFyZ2VyIHRoYW4gXCIrTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIrXCIuXCIpO2lmKFwibnVtYmVyXCI9PXR5cGVvZiBoJiZNYXRoLmZsb29yKGgpIT09aClyZXR1cm4gbC5lcnJvcihcIk51bWVyaWMgYnJhbmNoIGxhYmVscyBtdXN0IGJlIGludGVnZXIgdmFsdWVzLlwiKTtpZihyKXtpZihsLmNoZWNrU3VidHlwZShyLHBlKGgpKSlyZXR1cm4gbnVsbH1lbHNlIHI9cGUoaCk7aWYodm9pZCAwIT09aVtTdHJpbmcoaCldKXJldHVybiBsLmVycm9yKFwiQnJhbmNoIGxhYmVscyBtdXN0IGJlIHVuaXF1ZS5cIik7aVtTdHJpbmcoaCldPWEubGVuZ3RoO312YXIgZj1lLnBhcnNlKHUsbyxuKTtpZighZilyZXR1cm4gbnVsbDtuPW58fGYudHlwZSxhLnB1c2goZik7fXZhciB5PWUucGFyc2UodFsxXSwxLCR0KTtpZigheSlyZXR1cm4gbnVsbDt2YXIgZD1lLnBhcnNlKHRbdC5sZW5ndGgtMV0sdC5sZW5ndGgtMSxuKTtyZXR1cm4gZD9cInZhbHVlXCIhPT15LnR5cGUua2luZCYmZS5jb25jYXQoMSkuY2hlY2tTdWJ0eXBlKHIseS50eXBlKT9udWxsOm5ldyBycihyLG4seSxpLGEsZCk6bnVsbH0scnIucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuaW5wdXQuZXZhbHVhdGUodCk7cmV0dXJuIChwZShlKT09PXRoaXMuaW5wdXRUeXBlJiZ0aGlzLm91dHB1dHNbdGhpcy5jYXNlc1tlXV18fHRoaXMub3RoZXJ3aXNlKS5ldmFsdWF0ZSh0KX0scnIucHJvdG90eXBlLmVhY2hDaGlsZD1mdW5jdGlvbih0KXt0KHRoaXMuaW5wdXQpLHRoaXMub3V0cHV0cy5mb3JFYWNoKHQpLHQodGhpcy5vdGhlcndpc2UpO30scnIucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3ZhciB0O3JldHVybiAodD1bXSkuY29uY2F0LmFwcGx5KHQsdGhpcy5vdXRwdXRzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC5wb3NzaWJsZU91dHB1dHMoKX0pKS5jb25jYXQodGhpcy5vdGhlcndpc2UucG9zc2libGVPdXRwdXRzKCkpfSxyci5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PXRoaXMsZT1bXCJtYXRjaFwiLHRoaXMuaW5wdXQuc2VyaWFsaXplKCldLHI9W10sbj17fSxpPTAsYT1PYmplY3Qua2V5cyh0aGlzLmNhc2VzKS5zb3J0KCk7aTxhLmxlbmd0aDtpKz0xKXt2YXIgbz1hW2ldO3ZvaWQgMD09PShjPW5bdGhpcy5jYXNlc1tvXV0pPyhuW3RoaXMuY2FzZXNbb11dPXIubGVuZ3RoLHIucHVzaChbdGhpcy5jYXNlc1tvXSxbb11dKSk6cltjXVsxXS5wdXNoKG8pO31mb3IodmFyIHM9ZnVuY3Rpb24oZSl7cmV0dXJuIFwibnVtYmVyXCI9PT10LmlucHV0VHlwZS5raW5kP051bWJlcihlKTplfSx1PTAsbD1yO3U8bC5sZW5ndGg7dSs9MSl7dmFyIHA9bFt1XSxjPXBbMF0saD1wWzFdOzE9PT1oLmxlbmd0aD9lLnB1c2gocyhoWzBdKSk6ZS5wdXNoKGgubWFwKHMpKSxlLnB1c2godGhpcy5vdXRwdXRzW291dHB1dEluZGV4JDFdLnNlcmlhbGl6ZSgpKTt9cmV0dXJuIGUucHVzaCh0aGlzLm90aGVyd2lzZS5zZXJpYWxpemUoKSksZX07dmFyIG5yPWZ1bmN0aW9uKHQsZSxyKXt0aGlzLnR5cGU9dCx0aGlzLmJyYW5jaGVzPWUsdGhpcy5vdGhlcndpc2U9cjt9O2Z1bmN0aW9uIGlyKHQsZSl7cmV0dXJuIFwiPT1cIj09PXR8fFwiIT1cIj09PXQ/XCJib29sZWFuXCI9PT1lLmtpbmR8fFwic3RyaW5nXCI9PT1lLmtpbmR8fFwibnVtYmVyXCI9PT1lLmtpbmR8fFwibnVsbFwiPT09ZS5raW5kfHxcInZhbHVlXCI9PT1lLmtpbmQ6XCJzdHJpbmdcIj09PWUua2luZHx8XCJudW1iZXJcIj09PWUua2luZHx8XCJ2YWx1ZVwiPT09ZS5raW5kfWZ1bmN0aW9uIGFyKHQsZSxyLG4pe3JldHVybiAwPT09bi5jb21wYXJlKGUscil9ZnVuY3Rpb24gb3IodCxlLHIpe3ZhciBuPVwiPT1cIiE9PXQmJlwiIT1cIiE9PXQ7cmV0dXJuIGZ1bmN0aW9uKCl7ZnVuY3Rpb24gaSh0LGUscil7dGhpcy50eXBlPUp0LHRoaXMubGhzPXQsdGhpcy5yaHM9ZSx0aGlzLmNvbGxhdG9yPXIsdGhpcy5oYXNVbnR5cGVkQXJndW1lbnQ9XCJ2YWx1ZVwiPT09dC50eXBlLmtpbmR8fFwidmFsdWVcIj09PWUudHlwZS5raW5kO31yZXR1cm4gaS5wYXJzZT1mdW5jdGlvbih0LGUpe2lmKDMhPT10Lmxlbmd0aCYmNCE9PXQubGVuZ3RoKXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgdHdvIG9yIHRocmVlIGFyZ3VtZW50cy5cIik7dmFyIHI9dFswXSxhPWUucGFyc2UodFsxXSwxLCR0KTtpZighYSlyZXR1cm4gbnVsbDtpZighaXIocixhLnR5cGUpKXJldHVybiBlLmNvbmNhdCgxKS5lcnJvcignXCInK3IrXCJcXFwiIGNvbXBhcmlzb25zIGFyZSBub3Qgc3VwcG9ydGVkIGZvciB0eXBlICdcIitlZShhLnR5cGUpK1wiJy5cIik7dmFyIG89ZS5wYXJzZSh0WzJdLDIsJHQpO2lmKCFvKXJldHVybiBudWxsO2lmKCFpcihyLG8udHlwZSkpcmV0dXJuIGUuY29uY2F0KDIpLmVycm9yKCdcIicrcitcIlxcXCIgY29tcGFyaXNvbnMgYXJlIG5vdCBzdXBwb3J0ZWQgZm9yIHR5cGUgJ1wiK2VlKG8udHlwZSkrXCInLlwiKTtpZihhLnR5cGUua2luZCE9PW8udHlwZS5raW5kJiZcInZhbHVlXCIhPT1hLnR5cGUua2luZCYmXCJ2YWx1ZVwiIT09by50eXBlLmtpbmQpcmV0dXJuIGUuZXJyb3IoXCJDYW5ub3QgY29tcGFyZSB0eXBlcyAnXCIrZWUoYS50eXBlKStcIicgYW5kICdcIitlZShvLnR5cGUpK1wiJy5cIik7biYmKFwidmFsdWVcIj09PWEudHlwZS5raW5kJiZcInZhbHVlXCIhPT1vLnR5cGUua2luZD9hPW5ldyBkZShvLnR5cGUsW2FdKTpcInZhbHVlXCIhPT1hLnR5cGUua2luZCYmXCJ2YWx1ZVwiPT09by50eXBlLmtpbmQmJihvPW5ldyBkZShhLnR5cGUsW29dKSkpO3ZhciBzPW51bGw7aWYoND09PXQubGVuZ3RoKXtpZihcInN0cmluZ1wiIT09YS50eXBlLmtpbmQmJlwic3RyaW5nXCIhPT1vLnR5cGUua2luZCYmXCJ2YWx1ZVwiIT09YS50eXBlLmtpbmQmJlwidmFsdWVcIiE9PW8udHlwZS5raW5kKXJldHVybiBlLmVycm9yKFwiQ2Fubm90IHVzZSBjb2xsYXRvciB0byBjb21wYXJlIG5vbi1zdHJpbmcgdHlwZXMuXCIpO2lmKCEocz1lLnBhcnNlKHRbM10sMyxXdCkpKXJldHVybiBudWxsfXJldHVybiBuZXcgaShhLG8scyl9LGkucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKGkpe3ZhciBhPXRoaXMubGhzLmV2YWx1YXRlKGkpLG89dGhpcy5yaHMuZXZhbHVhdGUoaSk7aWYobiYmdGhpcy5oYXNVbnR5cGVkQXJndW1lbnQpe3ZhciBzPXBlKGEpLHU9cGUobyk7aWYocy5raW5kIT09dS5raW5kfHxcInN0cmluZ1wiIT09cy5raW5kJiZcIm51bWJlclwiIT09cy5raW5kKXRocm93IG5ldyBmZSgnRXhwZWN0ZWQgYXJndW1lbnRzIGZvciBcIicrdCsnXCIgdG8gYmUgKHN0cmluZywgc3RyaW5nKSBvciAobnVtYmVyLCBudW1iZXIpLCBidXQgZm91bmQgKCcrcy5raW5kK1wiLCBcIit1LmtpbmQrXCIpIGluc3RlYWQuXCIpfWlmKHRoaXMuY29sbGF0b3ImJiFuJiZ0aGlzLmhhc1VudHlwZWRBcmd1bWVudCl7dmFyIGw9cGUoYSkscD1wZShvKTtpZihcInN0cmluZ1wiIT09bC5raW5kfHxcInN0cmluZ1wiIT09cC5raW5kKXJldHVybiBlKGksYSxvKX1yZXR1cm4gdGhpcy5jb2xsYXRvcj9yKGksYSxvLHRoaXMuY29sbGF0b3IuZXZhbHVhdGUoaSkpOmUoaSxhLG8pfSxpLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dCh0aGlzLmxocyksdCh0aGlzLnJocyksdGhpcy5jb2xsYXRvciYmdCh0aGlzLmNvbGxhdG9yKTt9LGkucHJvdG90eXBlLnBvc3NpYmxlT3V0cHV0cz1mdW5jdGlvbigpe3JldHVybiBbITAsITFdfSxpLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXt2YXIgZT1bdF07cmV0dXJuIHRoaXMuZWFjaENoaWxkKGZ1bmN0aW9uKHQpe2UucHVzaCh0LnNlcmlhbGl6ZSgpKTt9KSxlfSxpfSgpfW5yLnBhcnNlPWZ1bmN0aW9uKHQsZSl7aWYodC5sZW5ndGg8NClyZXR1cm4gZS5lcnJvcihcIkV4cGVjdGVkIGF0IGxlYXN0IDMgYXJndW1lbnRzLCBidXQgZm91bmQgb25seSBcIisodC5sZW5ndGgtMSkrXCIuXCIpO2lmKHQubGVuZ3RoJTIhPTApcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCBhbiBvZGQgbnVtYmVyIG9mIGFyZ3VtZW50cy5cIik7dmFyIHI7ZS5leHBlY3RlZFR5cGUmJlwidmFsdWVcIiE9PWUuZXhwZWN0ZWRUeXBlLmtpbmQmJihyPWUuZXhwZWN0ZWRUeXBlKTtmb3IodmFyIG49W10saT0xO2k8dC5sZW5ndGgtMTtpKz0yKXt2YXIgYT1lLnBhcnNlKHRbaV0saSxKdCk7aWYoIWEpcmV0dXJuIG51bGw7dmFyIG89ZS5wYXJzZSh0W2krMV0saSsxLHIpO2lmKCFvKXJldHVybiBudWxsO24ucHVzaChbYSxvXSkscj1yfHxvLnR5cGU7fXZhciBzPWUucGFyc2UodFt0Lmxlbmd0aC0xXSx0Lmxlbmd0aC0xLHIpO3JldHVybiBzP25ldyBucihyLG4scyk6bnVsbH0sbnIucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT0wLHI9dGhpcy5icmFuY2hlcztlPHIubGVuZ3RoO2UrPTEpe3ZhciBuPXJbZV0saT1uWzBdLGE9blsxXTtpZihpLmV2YWx1YXRlKHQpKXJldHVybiBhLmV2YWx1YXRlKHQpfXJldHVybiB0aGlzLm90aGVyd2lzZS5ldmFsdWF0ZSh0KX0sbnIucHJvdG90eXBlLmVhY2hDaGlsZD1mdW5jdGlvbih0KXtmb3IodmFyIGU9MCxyPXRoaXMuYnJhbmNoZXM7ZTxyLmxlbmd0aDtlKz0xKXt2YXIgbj1yW2VdLGk9blswXSxhPW5bMV07dChpKSx0KGEpO310KHRoaXMub3RoZXJ3aXNlKTt9LG5yLnByb3RvdHlwZS5wb3NzaWJsZU91dHB1dHM9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gKHQ9W10pLmNvbmNhdC5hcHBseSh0LHRoaXMuYnJhbmNoZXMubWFwKGZ1bmN0aW9uKHQpe3RbMF07cmV0dXJuIHRbMV0ucG9zc2libGVPdXRwdXRzKCl9KSkuY29uY2F0KHRoaXMub3RoZXJ3aXNlLnBvc3NpYmxlT3V0cHV0cygpKX0sbnIucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3ZhciB0PVtcImNhc2VcIl07cmV0dXJuIHRoaXMuZWFjaENoaWxkKGZ1bmN0aW9uKGUpe3QucHVzaChlLnNlcmlhbGl6ZSgpKTt9KSx0fTt2YXIgc3I9b3IoXCI9PVwiLGZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gZT09PXJ9LGFyKSx1cj1vcihcIiE9XCIsZnVuY3Rpb24odCxlLHIpe3JldHVybiBlIT09cn0sZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuICFhcigwLGUscixuKX0pLGxyPW9yKFwiPFwiLGZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gZTxyfSxmdW5jdGlvbih0LGUscixuKXtyZXR1cm4gbi5jb21wYXJlKGUscik8MH0pLHByPW9yKFwiPlwiLGZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gZT5yfSxmdW5jdGlvbih0LGUscixuKXtyZXR1cm4gbi5jb21wYXJlKGUscik+MH0pLGNyPW9yKFwiPD1cIixmdW5jdGlvbih0LGUscil7cmV0dXJuIGU8PXJ9LGZ1bmN0aW9uKHQsZSxyLG4pe3JldHVybiBuLmNvbXBhcmUoZSxyKTw9MH0pLGhyPW9yKFwiPj1cIixmdW5jdGlvbih0LGUscil7cmV0dXJuIGU+PXJ9LGZ1bmN0aW9uKHQsZSxyLG4pe3JldHVybiBuLmNvbXBhcmUoZSxyKT49MH0pLGZyPWZ1bmN0aW9uKHQsZSxyLG4saSl7dGhpcy50eXBlPVh0LHRoaXMubnVtYmVyPXQsdGhpcy5sb2NhbGU9ZSx0aGlzLmN1cnJlbmN5PXIsdGhpcy5taW5GcmFjdGlvbkRpZ2l0cz1uLHRoaXMubWF4RnJhY3Rpb25EaWdpdHM9aTt9O2ZyLnBhcnNlPWZ1bmN0aW9uKHQsZSl7aWYoMyE9PXQubGVuZ3RoKXJldHVybiBlLmVycm9yKFwiRXhwZWN0ZWQgdHdvIGFyZ3VtZW50cy5cIik7dmFyIHI9ZS5wYXJzZSh0WzFdLDEsR3QpO2lmKCFyKXJldHVybiBudWxsO3ZhciBuPXRbMl07aWYoXCJvYmplY3RcIiE9dHlwZW9mIG58fEFycmF5LmlzQXJyYXkobikpcmV0dXJuIGUuZXJyb3IoXCJOdW1iZXJGb3JtYXQgb3B0aW9ucyBhcmd1bWVudCBtdXN0IGJlIGFuIG9iamVjdC5cIik7dmFyIGk9bnVsbDtpZihuLmxvY2FsZSYmIShpPWUucGFyc2Uobi5sb2NhbGUsMSxYdCkpKXJldHVybiBudWxsO3ZhciBhPW51bGw7aWYobi5jdXJyZW5jeSYmIShhPWUucGFyc2Uobi5jdXJyZW5jeSwxLFh0KSkpcmV0dXJuIG51bGw7dmFyIG89bnVsbDtpZihuW1wibWluLWZyYWN0aW9uLWRpZ2l0c1wiXSYmIShvPWUucGFyc2UobltcIm1pbi1mcmFjdGlvbi1kaWdpdHNcIl0sMSxHdCkpKXJldHVybiBudWxsO3ZhciBzPW51bGw7cmV0dXJuIG5bXCJtYXgtZnJhY3Rpb24tZGlnaXRzXCJdJiYhKHM9ZS5wYXJzZShuW1wibWF4LWZyYWN0aW9uLWRpZ2l0c1wiXSwxLEd0KSk/bnVsbDpuZXcgZnIocixpLGEsbyxzKX0sZnIucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgSW50bC5OdW1iZXJGb3JtYXQodGhpcy5sb2NhbGU/dGhpcy5sb2NhbGUuZXZhbHVhdGUodCk6W10se3N0eWxlOnRoaXMuY3VycmVuY3k/XCJjdXJyZW5jeVwiOlwiZGVjaW1hbFwiLGN1cnJlbmN5OnRoaXMuY3VycmVuY3k/dGhpcy5jdXJyZW5jeS5ldmFsdWF0ZSh0KTp2b2lkIDAsbWluaW11bUZyYWN0aW9uRGlnaXRzOnRoaXMubWluRnJhY3Rpb25EaWdpdHM/dGhpcy5taW5GcmFjdGlvbkRpZ2l0cy5ldmFsdWF0ZSh0KTp2b2lkIDAsbWF4aW11bUZyYWN0aW9uRGlnaXRzOnRoaXMubWF4RnJhY3Rpb25EaWdpdHM/dGhpcy5tYXhGcmFjdGlvbkRpZ2l0cy5ldmFsdWF0ZSh0KTp2b2lkIDB9KS5mb3JtYXQodGhpcy5udW1iZXIuZXZhbHVhdGUodCkpfSxmci5wcm90b3R5cGUuZWFjaENoaWxkPWZ1bmN0aW9uKHQpe3QodGhpcy5udW1iZXIpLHRoaXMubG9jYWxlJiZ0KHRoaXMubG9jYWxlKSx0aGlzLmN1cnJlbmN5JiZ0KHRoaXMuY3VycmVuY3kpLHRoaXMubWluRnJhY3Rpb25EaWdpdHMmJnQodGhpcy5taW5GcmFjdGlvbkRpZ2l0cyksdGhpcy5tYXhGcmFjdGlvbkRpZ2l0cyYmdCh0aGlzLm1heEZyYWN0aW9uRGlnaXRzKTt9LGZyLnByb3RvdHlwZS5wb3NzaWJsZU91dHB1dHM9ZnVuY3Rpb24oKXtyZXR1cm4gW3ZvaWQgMF19LGZyLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXt2YXIgdD17fTtyZXR1cm4gdGhpcy5sb2NhbGUmJih0LmxvY2FsZT10aGlzLmxvY2FsZS5zZXJpYWxpemUoKSksdGhpcy5jdXJyZW5jeSYmKHQuY3VycmVuY3k9dGhpcy5jdXJyZW5jeS5zZXJpYWxpemUoKSksdGhpcy5taW5GcmFjdGlvbkRpZ2l0cyYmKHRbXCJtaW4tZnJhY3Rpb24tZGlnaXRzXCJdPXRoaXMubWluRnJhY3Rpb25EaWdpdHMuc2VyaWFsaXplKCkpLHRoaXMubWF4RnJhY3Rpb25EaWdpdHMmJih0W1wibWF4LWZyYWN0aW9uLWRpZ2l0c1wiXT10aGlzLm1heEZyYWN0aW9uRGlnaXRzLnNlcmlhbGl6ZSgpKSxbXCJudW1iZXItZm9ybWF0XCIsdGhpcy5udW1iZXIuc2VyaWFsaXplKCksdF19O3ZhciB5cj1mdW5jdGlvbih0KXt0aGlzLnR5cGU9R3QsdGhpcy5pbnB1dD10O307eXIucGFyc2U9ZnVuY3Rpb24odCxlKXtpZigyIT09dC5sZW5ndGgpcmV0dXJuIGUuZXJyb3IoXCJFeHBlY3RlZCAxIGFyZ3VtZW50LCBidXQgZm91bmQgXCIrKHQubGVuZ3RoLTEpK1wiIGluc3RlYWQuXCIpO3ZhciByPWUucGFyc2UodFsxXSwxKTtyZXR1cm4gcj9cImFycmF5XCIhPT1yLnR5cGUua2luZCYmXCJzdHJpbmdcIiE9PXIudHlwZS5raW5kJiZcInZhbHVlXCIhPT1yLnR5cGUua2luZD9lLmVycm9yKFwiRXhwZWN0ZWQgYXJndW1lbnQgb2YgdHlwZSBzdHJpbmcgb3IgYXJyYXksIGJ1dCBmb3VuZCBcIitlZShyLnR5cGUpK1wiIGluc3RlYWQuXCIpOm5ldyB5cihyKTpudWxsfSx5ci5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5pbnB1dC5ldmFsdWF0ZSh0KTtpZihcInN0cmluZ1wiPT10eXBlb2YgZSlyZXR1cm4gZS5sZW5ndGg7aWYoQXJyYXkuaXNBcnJheShlKSlyZXR1cm4gZS5sZW5ndGg7dGhyb3cgbmV3IGZlKFwiRXhwZWN0ZWQgdmFsdWUgdG8gYmUgb2YgdHlwZSBzdHJpbmcgb3IgYXJyYXksIGJ1dCBmb3VuZCBcIitlZShwZShlKSkrXCIgaW5zdGVhZC5cIil9LHlyLnByb3RvdHlwZS5lYWNoQ2hpbGQ9ZnVuY3Rpb24odCl7dCh0aGlzLmlucHV0KTt9LHlyLnByb3RvdHlwZS5wb3NzaWJsZU91dHB1dHM9ZnVuY3Rpb24oKXtyZXR1cm4gW3ZvaWQgMF19LHlyLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXt2YXIgdD1bXCJsZW5ndGhcIl07cmV0dXJuIHRoaXMuZWFjaENoaWxkKGZ1bmN0aW9uKGUpe3QucHVzaChlLnNlcmlhbGl6ZSgpKTt9KSx0fTt2YXIgZHI9e1wiPT1cIjpzcixcIiE9XCI6dXIsXCI+XCI6cHIsXCI8XCI6bHIsXCI+PVwiOmhyLFwiPD1cIjpjcixhcnJheTpkZSxhdDplcixib29sZWFuOmRlLGNhc2U6bnIsY29hbGVzY2U6UWUsY29sbGF0b3I6d2UsZm9ybWF0Om1lLGludGVycG9sYXRlOiRlLFwiaW50ZXJwb2xhdGUtaGNsXCI6JGUsXCJpbnRlcnBvbGF0ZS1sYWJcIjokZSxsZW5ndGg6eXIsbGV0OnRyLGxpdGVyYWw6aGUsbWF0Y2g6cnIsbnVtYmVyOmRlLFwibnVtYmVyLWZvcm1hdFwiOmZyLG9iamVjdDpkZSxzdGVwOkNlLHN0cmluZzpkZSxcInRvLWJvb2xlYW5cIjpnZSxcInRvLWNvbG9yXCI6Z2UsXCJ0by1udW1iZXJcIjpnZSxcInRvLXN0cmluZ1wiOmdlLHZhcjp6ZX07ZnVuY3Rpb24gbXIodCxlKXt2YXIgcj1lWzBdLG49ZVsxXSxpPWVbMl0sYT1lWzNdO3I9ci5ldmFsdWF0ZSh0KSxuPW4uZXZhbHVhdGUodCksaT1pLmV2YWx1YXRlKHQpO3ZhciBvPWE/YS5ldmFsdWF0ZSh0KToxLHM9bGUocixuLGksbyk7aWYocyl0aHJvdyBuZXcgZmUocyk7cmV0dXJuIG5ldyBhZShyLzI1NSpvLG4vMjU1Km8saS8yNTUqbyxvKX1mdW5jdGlvbiB2cih0LGUpe3JldHVybiB0IGluIGV9ZnVuY3Rpb24gZ3IodCxlKXt2YXIgcj1lW3RdO3JldHVybiB2b2lkIDA9PT1yP251bGw6cn1mdW5jdGlvbiB4cih0KXtyZXR1cm4ge3R5cGU6dH19ZnVuY3Rpb24gYnIodCl7cmV0dXJuIHtyZXN1bHQ6XCJzdWNjZXNzXCIsdmFsdWU6dH19ZnVuY3Rpb24gX3IodCl7cmV0dXJuIHtyZXN1bHQ6XCJlcnJvclwiLHZhbHVlOnR9fWZ1bmN0aW9uIHdyKHQpe3JldHVybiBcImRhdGEtZHJpdmVuXCI9PT10W1wicHJvcGVydHktdHlwZVwiXXx8XCJjcm9zcy1mYWRlZC1kYXRhLWRyaXZlblwiPT09dFtcInByb3BlcnR5LXR5cGVcIl19ZnVuY3Rpb24gQXIodCl7cmV0dXJuICEhdC5leHByZXNzaW9uJiZ0LmV4cHJlc3Npb24ucGFyYW1ldGVycy5pbmRleE9mKFwiem9vbVwiKT4tMX1mdW5jdGlvbiBTcih0KXtyZXR1cm4gISF0LmV4cHJlc3Npb24mJnQuZXhwcmVzc2lvbi5pbnRlcnBvbGF0ZWR9ZnVuY3Rpb24ga3IodCl7cmV0dXJuIHQgaW5zdGFuY2VvZiBOdW1iZXI/XCJudW1iZXJcIjp0IGluc3RhbmNlb2YgU3RyaW5nP1wic3RyaW5nXCI6dCBpbnN0YW5jZW9mIEJvb2xlYW4/XCJib29sZWFuXCI6QXJyYXkuaXNBcnJheSh0KT9cImFycmF5XCI6bnVsbD09PXQ/XCJudWxsXCI6dHlwZW9mIHR9ZnVuY3Rpb24genIodCl7cmV0dXJuIFwib2JqZWN0XCI9PXR5cGVvZiB0JiZudWxsIT09dCYmIUFycmF5LmlzQXJyYXkodCl9ZnVuY3Rpb24gSXIodCl7cmV0dXJuIHR9ZnVuY3Rpb24gQnIodCxlLHIpe3JldHVybiB2b2lkIDAhPT10P3Q6dm9pZCAwIT09ZT9lOnZvaWQgMCE9PXI/cjp2b2lkIDB9ZnVuY3Rpb24gQ3IodCxlLHIsbixpKXtyZXR1cm4gQnIodHlwZW9mIHI9PT1pP25bcl06dm9pZCAwLHQuZGVmYXVsdCxlLmRlZmF1bHQpfWZ1bmN0aW9uIEVyKHQsZSxyKXtpZihcIm51bWJlclwiIT09a3IocikpcmV0dXJuIEJyKHQuZGVmYXVsdCxlLmRlZmF1bHQpO3ZhciBuPXQuc3RvcHMubGVuZ3RoO2lmKDE9PT1uKXJldHVybiB0LnN0b3BzWzBdWzFdO2lmKHI8PXQuc3RvcHNbMF1bMF0pcmV0dXJuIHQuc3RvcHNbMF1bMV07aWYocj49dC5zdG9wc1tuLTFdWzBdKXJldHVybiB0LnN0b3BzW24tMV1bMV07dmFyIGk9QmUodC5zdG9wcy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHRbMF19KSxyKTtyZXR1cm4gdC5zdG9wc1tpXVsxXX1mdW5jdGlvbiBNcih0LGUscil7dmFyIG49dm9pZCAwIT09dC5iYXNlP3QuYmFzZToxO2lmKFwibnVtYmVyXCIhPT1rcihyKSlyZXR1cm4gQnIodC5kZWZhdWx0LGUuZGVmYXVsdCk7dmFyIGk9dC5zdG9wcy5sZW5ndGg7aWYoMT09PWkpcmV0dXJuIHQuc3RvcHNbMF1bMV07aWYocjw9dC5zdG9wc1swXVswXSlyZXR1cm4gdC5zdG9wc1swXVsxXTtpZihyPj10LnN0b3BzW2ktMV1bMF0pcmV0dXJuIHQuc3RvcHNbaS0xXVsxXTt2YXIgYT1CZSh0LnN0b3BzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdFswXX0pLHIpLG89ZnVuY3Rpb24odCxlLHIsbil7dmFyIGk9bi1yLGE9dC1yO3JldHVybiAwPT09aT8wOjE9PT1lP2EvaTooTWF0aC5wb3coZSxhKS0xKS8oTWF0aC5wb3coZSxpKS0xKX0ocixuLHQuc3RvcHNbYV1bMF0sdC5zdG9wc1thKzFdWzBdKSxzPXQuc3RvcHNbYV1bMV0sdT10LnN0b3BzW2ErMV1bMV0sbD1NZVtlLnR5cGVdfHxJcjtpZih0LmNvbG9yU3BhY2UmJlwicmdiXCIhPT10LmNvbG9yU3BhY2Upe3ZhciBwPVllW3QuY29sb3JTcGFjZV07bD1mdW5jdGlvbih0LGUpe3JldHVybiBwLnJldmVyc2UocC5pbnRlcnBvbGF0ZShwLmZvcndhcmQodCkscC5mb3J3YXJkKGUpLG8pKX07fXJldHVybiBcImZ1bmN0aW9uXCI9PXR5cGVvZiBzLmV2YWx1YXRlP3tldmFsdWF0ZTpmdW5jdGlvbigpe2Zvcih2YXIgdD1bXSxlPWFyZ3VtZW50cy5sZW5ndGg7ZS0tOyl0W2VdPWFyZ3VtZW50c1tlXTt2YXIgcj1zLmV2YWx1YXRlLmFwcGx5KHZvaWQgMCx0KSxuPXUuZXZhbHVhdGUuYXBwbHkodm9pZCAwLHQpO2lmKHZvaWQgMCE9PXImJnZvaWQgMCE9PW4pcmV0dXJuIGwocixuLG8pfX06bChzLHUsbyl9ZnVuY3Rpb24gVHIodCxlLHIpe3JldHVybiBcImNvbG9yXCI9PT1lLnR5cGU/cj1hZS5wYXJzZShyKTpcImZvcm1hdHRlZFwiPT09ZS50eXBlP3I9dWUuZnJvbVN0cmluZyhyLnRvU3RyaW5nKCkpOmtyKHIpPT09ZS50eXBlfHxcImVudW1cIj09PWUudHlwZSYmZS52YWx1ZXNbcl18fChyPXZvaWQgMCksQnIocix0LmRlZmF1bHQsZS5kZWZhdWx0KX1fZS5yZWdpc3Rlcihkcix7ZXJyb3I6W3traW5kOlwiZXJyb3JcIn0sW1h0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07dGhyb3cgbmV3IGZlKHIuZXZhbHVhdGUodCkpfV0sdHlwZW9mOltYdCxbJHRdLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIGVlKHBlKGVbMF0uZXZhbHVhdGUodCkpKX1dLFwidG8tcmdiYVwiOlt0ZShHdCw0KSxbSHRdLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIGVbMF0uZXZhbHVhdGUodCkudG9BcnJheSgpfV0scmdiOltIdCxbR3QsR3QsR3RdLG1yXSxyZ2JhOltIdCxbR3QsR3QsR3QsR3RdLG1yXSxoYXM6e3R5cGU6SnQsb3ZlcmxvYWRzOltbW1h0XSxmdW5jdGlvbih0LGUpe3JldHVybiB2cihlWzBdLmV2YWx1YXRlKHQpLHQucHJvcGVydGllcygpKX1dLFtbWHQsWXRdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIHZyKHIuZXZhbHVhdGUodCksbi5ldmFsdWF0ZSh0KSl9XV19LGdldDp7dHlwZTokdCxvdmVybG9hZHM6W1tbWHRdLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIGdyKGVbMF0uZXZhbHVhdGUodCksdC5wcm9wZXJ0aWVzKCkpfV0sW1tYdCxZdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXTtyZXR1cm4gZ3Ioci5ldmFsdWF0ZSh0KSxuLmV2YWx1YXRlKHQpKX1dXX0sXCJmZWF0dXJlLXN0YXRlXCI6WyR0LFtYdF0sZnVuY3Rpb24odCxlKXtyZXR1cm4gZ3IoZVswXS5ldmFsdWF0ZSh0KSx0LmZlYXR1cmVTdGF0ZXx8e30pfV0scHJvcGVydGllczpbWXQsW10sZnVuY3Rpb24odCl7cmV0dXJuIHQucHJvcGVydGllcygpfV0sXCJnZW9tZXRyeS10eXBlXCI6W1h0LFtdLGZ1bmN0aW9uKHQpe3JldHVybiB0Lmdlb21ldHJ5VHlwZSgpfV0saWQ6WyR0LFtdLGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkKCl9XSx6b29tOltHdCxbXSxmdW5jdGlvbih0KXtyZXR1cm4gdC5nbG9iYWxzLnpvb219XSxcImhlYXRtYXAtZGVuc2l0eVwiOltHdCxbXSxmdW5jdGlvbih0KXtyZXR1cm4gdC5nbG9iYWxzLmhlYXRtYXBEZW5zaXR5fHwwfV0sXCJsaW5lLXByb2dyZXNzXCI6W0d0LFtdLGZ1bmN0aW9uKHQpe3JldHVybiB0Lmdsb2JhbHMubGluZVByb2dyZXNzfHwwfV0sYWNjdW11bGF0ZWQ6WyR0LFtdLGZ1bmN0aW9uKHQpe3JldHVybiB2b2lkIDA9PT10Lmdsb2JhbHMuYWNjdW11bGF0ZWQ/bnVsbDp0Lmdsb2JhbHMuYWNjdW11bGF0ZWR9XSxcIitcIjpbR3QseHIoR3QpLGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTAsbj0wLGk9ZTtuPGkubGVuZ3RoO24rPTEpe3IrPWlbbl0uZXZhbHVhdGUodCk7fXJldHVybiByfV0sXCIqXCI6W0d0LHhyKEd0KSxmdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0xLG49MCxpPWU7bjxpLmxlbmd0aDtuKz0xKXtyKj1pW25dLmV2YWx1YXRlKHQpO31yZXR1cm4gcn1dLFwiLVwiOnt0eXBlOkd0LG92ZXJsb2FkczpbW1tHdCxHdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXTtyZXR1cm4gci5ldmFsdWF0ZSh0KS1uLmV2YWx1YXRlKHQpfV0sW1tHdF0sZnVuY3Rpb24odCxlKXtyZXR1cm4gLWVbMF0uZXZhbHVhdGUodCl9XV19LFwiL1wiOltHdCxbR3QsR3RdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIHIuZXZhbHVhdGUodCkvbi5ldmFsdWF0ZSh0KX1dLFwiJVwiOltHdCxbR3QsR3RdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIHIuZXZhbHVhdGUodCklbi5ldmFsdWF0ZSh0KX1dLGxuMjpbR3QsW10sZnVuY3Rpb24oKXtyZXR1cm4gTWF0aC5MTjJ9XSxwaTpbR3QsW10sZnVuY3Rpb24oKXtyZXR1cm4gTWF0aC5QSX1dLGU6W0d0LFtdLGZ1bmN0aW9uKCl7cmV0dXJuIE1hdGguRX1dLFwiXlwiOltHdCxbR3QsR3RdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIE1hdGgucG93KHIuZXZhbHVhdGUodCksbi5ldmFsdWF0ZSh0KSl9XSxzcXJ0OltHdCxbR3RdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXTtyZXR1cm4gTWF0aC5zcXJ0KHIuZXZhbHVhdGUodCkpfV0sbG9nMTA6W0d0LFtHdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiBNYXRoLmxvZyhyLmV2YWx1YXRlKHQpKS9NYXRoLkxOMTB9XSxsbjpbR3QsW0d0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGgubG9nKHIuZXZhbHVhdGUodCkpfV0sbG9nMjpbR3QsW0d0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGgubG9nKHIuZXZhbHVhdGUodCkpL01hdGguTE4yfV0sc2luOltHdCxbR3RdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXTtyZXR1cm4gTWF0aC5zaW4oci5ldmFsdWF0ZSh0KSl9XSxjb3M6W0d0LFtHdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiBNYXRoLmNvcyhyLmV2YWx1YXRlKHQpKX1dLHRhbjpbR3QsW0d0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGgudGFuKHIuZXZhbHVhdGUodCkpfV0sYXNpbjpbR3QsW0d0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGguYXNpbihyLmV2YWx1YXRlKHQpKX1dLGFjb3M6W0d0LFtHdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiBNYXRoLmFjb3Moci5ldmFsdWF0ZSh0KSl9XSxhdGFuOltHdCxbR3RdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXTtyZXR1cm4gTWF0aC5hdGFuKHIuZXZhbHVhdGUodCkpfV0sbWluOltHdCx4cihHdCksZnVuY3Rpb24odCxlKXtyZXR1cm4gTWF0aC5taW4uYXBwbHkoTWF0aCxlLm1hcChmdW5jdGlvbihlKXtyZXR1cm4gZS5ldmFsdWF0ZSh0KX0pKX1dLG1heDpbR3QseHIoR3QpLGZ1bmN0aW9uKHQsZSl7cmV0dXJuIE1hdGgubWF4LmFwcGx5KE1hdGgsZS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIGUuZXZhbHVhdGUodCl9KSl9XSxhYnM6W0d0LFtHdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiBNYXRoLmFicyhyLmV2YWx1YXRlKHQpKX1dLHJvdW5kOltHdCxbR3RdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXS5ldmFsdWF0ZSh0KTtyZXR1cm4gcjwwPy1NYXRoLnJvdW5kKC1yKTpNYXRoLnJvdW5kKHIpfV0sZmxvb3I6W0d0LFtHdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiBNYXRoLmZsb29yKHIuZXZhbHVhdGUodCkpfV0sY2VpbDpbR3QsW0d0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIE1hdGguY2VpbChyLmV2YWx1YXRlKHQpKX1dLFwiZmlsdGVyLT09XCI6W0p0LFtYdCwkdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXTtyZXR1cm4gdC5wcm9wZXJ0aWVzKClbci52YWx1ZV09PT1uLnZhbHVlfV0sXCJmaWx0ZXItaWQtPT1cIjpbSnQsWyR0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIHQuaWQoKT09PXIudmFsdWV9XSxcImZpbHRlci10eXBlLT09XCI6W0p0LFtYdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdO3JldHVybiB0Lmdlb21ldHJ5VHlwZSgpPT09ci52YWx1ZX1dLFwiZmlsdGVyLTxcIjpbSnQsW1h0LCR0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdLGk9dC5wcm9wZXJ0aWVzKClbci52YWx1ZV0sYT1uLnZhbHVlO3JldHVybiB0eXBlb2YgaT09dHlwZW9mIGEmJmk8YX1dLFwiZmlsdGVyLWlkLTxcIjpbSnQsWyR0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj10LmlkKCksaT1yLnZhbHVlO3JldHVybiB0eXBlb2Ygbj09dHlwZW9mIGkmJm48aX1dLFwiZmlsdGVyLT5cIjpbSnQsW1h0LCR0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdLGk9dC5wcm9wZXJ0aWVzKClbci52YWx1ZV0sYT1uLnZhbHVlO3JldHVybiB0eXBlb2YgaT09dHlwZW9mIGEmJmk+YX1dLFwiZmlsdGVyLWlkLT5cIjpbSnQsWyR0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj10LmlkKCksaT1yLnZhbHVlO3JldHVybiB0eXBlb2Ygbj09dHlwZW9mIGkmJm4+aX1dLFwiZmlsdGVyLTw9XCI6W0p0LFtYdCwkdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49ZVsxXSxpPXQucHJvcGVydGllcygpW3IudmFsdWVdLGE9bi52YWx1ZTtyZXR1cm4gdHlwZW9mIGk9PXR5cGVvZiBhJiZpPD1hfV0sXCJmaWx0ZXItaWQtPD1cIjpbSnQsWyR0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj10LmlkKCksaT1yLnZhbHVlO3JldHVybiB0eXBlb2Ygbj09dHlwZW9mIGkmJm48PWl9XSxcImZpbHRlci0+PVwiOltKdCxbWHQsJHRdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV0saT10LnByb3BlcnRpZXMoKVtyLnZhbHVlXSxhPW4udmFsdWU7cmV0dXJuIHR5cGVvZiBpPT10eXBlb2YgYSYmaT49YX1dLFwiZmlsdGVyLWlkLT49XCI6W0p0LFskdF0sZnVuY3Rpb24odCxlKXt2YXIgcj1lWzBdLG49dC5pZCgpLGk9ci52YWx1ZTtyZXR1cm4gdHlwZW9mIG49PXR5cGVvZiBpJiZuPj1pfV0sXCJmaWx0ZXItaGFzXCI6W0p0LFskdF0sZnVuY3Rpb24odCxlKXtyZXR1cm4gZVswXS52YWx1ZSBpbiB0LnByb3BlcnRpZXMoKX1dLFwiZmlsdGVyLWhhcy1pZFwiOltKdCxbXSxmdW5jdGlvbih0KXtyZXR1cm4gbnVsbCE9PXQuaWQoKX1dLFwiZmlsdGVyLXR5cGUtaW5cIjpbSnQsW3RlKFh0KV0sZnVuY3Rpb24odCxlKXtyZXR1cm4gZVswXS52YWx1ZS5pbmRleE9mKHQuZ2VvbWV0cnlUeXBlKCkpPj0wfV0sXCJmaWx0ZXItaWQtaW5cIjpbSnQsW3RlKCR0KV0sZnVuY3Rpb24odCxlKXtyZXR1cm4gZVswXS52YWx1ZS5pbmRleE9mKHQuaWQoKSk+PTB9XSxcImZpbHRlci1pbi1zbWFsbFwiOltKdCxbWHQsdGUoJHQpXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF07cmV0dXJuIGVbMV0udmFsdWUuaW5kZXhPZih0LnByb3BlcnRpZXMoKVtyLnZhbHVlXSk+PTB9XSxcImZpbHRlci1pbi1sYXJnZVwiOltKdCxbWHQsdGUoJHQpXSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdO3JldHVybiBmdW5jdGlvbih0LGUscixuKXtmb3IoO3I8PW47KXt2YXIgaT1yK24+PjE7aWYoZVtpXT09PXQpcmV0dXJuICEwO2VbaV0+dD9uPWktMTpyPWkrMTt9cmV0dXJuICExfSh0LnByb3BlcnRpZXMoKVtyLnZhbHVlXSxuLnZhbHVlLDAsbi52YWx1ZS5sZW5ndGgtMSl9XSxhbGw6e3R5cGU6SnQsb3ZlcmxvYWRzOltbW0p0LEp0XSxmdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdO3JldHVybiByLmV2YWx1YXRlKHQpJiZuLmV2YWx1YXRlKHQpfV0sW3hyKEp0KSxmdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0wLG49ZTtyPG4ubGVuZ3RoO3IrPTEpe2lmKCFuW3JdLmV2YWx1YXRlKHQpKXJldHVybiAhMX1yZXR1cm4gITB9XV19LGFueTp7dHlwZTpKdCxvdmVybG9hZHM6W1tbSnQsSnRdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV07cmV0dXJuIHIuZXZhbHVhdGUodCl8fG4uZXZhbHVhdGUodCl9XSxbeHIoSnQpLGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTAsbj1lO3I8bi5sZW5ndGg7cis9MSl7aWYobltyXS5ldmFsdWF0ZSh0KSlyZXR1cm4gITB9cmV0dXJuICExfV1dfSxcIiFcIjpbSnQsW0p0XSxmdW5jdGlvbih0LGUpe3JldHVybiAhZVswXS5ldmFsdWF0ZSh0KX1dLFwiaXMtc3VwcG9ydGVkLXNjcmlwdFwiOltKdCxbWHRdLGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPXQuZ2xvYmFscyYmdC5nbG9iYWxzLmlzU3VwcG9ydGVkU2NyaXB0O3JldHVybiAhbnx8bihyLmV2YWx1YXRlKHQpKX1dLHVwY2FzZTpbWHQsW1h0XSxmdW5jdGlvbih0LGUpe3JldHVybiBlWzBdLmV2YWx1YXRlKHQpLnRvVXBwZXJDYXNlKCl9XSxkb3duY2FzZTpbWHQsW1h0XSxmdW5jdGlvbih0LGUpe3JldHVybiBlWzBdLmV2YWx1YXRlKHQpLnRvTG93ZXJDYXNlKCl9XSxjb25jYXQ6W1h0LHhyKCR0KSxmdW5jdGlvbih0LGUpe3JldHVybiBlLm1hcChmdW5jdGlvbihlKXtyZXR1cm4gY2UoZS5ldmFsdWF0ZSh0KSl9KS5qb2luKFwiXCIpfV0sXCJyZXNvbHZlZC1sb2NhbGVcIjpbWHQsW1d0XSxmdW5jdGlvbih0LGUpe3JldHVybiBlWzBdLmV2YWx1YXRlKHQpLnJlc29sdmVkTG9jYWxlKCl9XX0pO3ZhciBQcj1mdW5jdGlvbih0LGUpe3ZhciByO3RoaXMuZXhwcmVzc2lvbj10LHRoaXMuX3dhcm5pbmdIaXN0b3J5PXt9LHRoaXMuX2V2YWx1YXRvcj1uZXcgYmUsdGhpcy5fZGVmYXVsdFZhbHVlPWU/XCJjb2xvclwiPT09KHI9ZSkudHlwZSYmenIoci5kZWZhdWx0KT9uZXcgYWUoMCwwLDAsMCk6XCJjb2xvclwiPT09ci50eXBlP2FlLnBhcnNlKHIuZGVmYXVsdCl8fG51bGw6dm9pZCAwPT09ci5kZWZhdWx0P251bGw6ci5kZWZhdWx0Om51bGwsdGhpcy5fZW51bVZhbHVlcz1lJiZcImVudW1cIj09PWUudHlwZT9lLnZhbHVlczpudWxsO307ZnVuY3Rpb24gVnIodCl7cmV0dXJuIEFycmF5LmlzQXJyYXkodCkmJnQubGVuZ3RoPjAmJlwic3RyaW5nXCI9PXR5cGVvZiB0WzBdJiZ0WzBdaW4gZHJ9ZnVuY3Rpb24gRnIodCxlKXt2YXIgcj1uZXcgSWUoZHIsW10sZT9mdW5jdGlvbih0KXt2YXIgZT17Y29sb3I6SHQsc3RyaW5nOlh0LG51bWJlcjpHdCxlbnVtOlh0LGJvb2xlYW46SnQsZm9ybWF0dGVkOlF0fTtpZihcImFycmF5XCI9PT10LnR5cGUpcmV0dXJuIHRlKGVbdC52YWx1ZV18fCR0LHQubGVuZ3RoKTtyZXR1cm4gZVt0LnR5cGVdfShlKTp2b2lkIDApLG49ci5wYXJzZSh0LHZvaWQgMCx2b2lkIDAsdm9pZCAwLGUmJlwic3RyaW5nXCI9PT1lLnR5cGU/e3R5cGVBbm5vdGF0aW9uOlwiY29lcmNlXCJ9OnZvaWQgMCk7cmV0dXJuIG4/YnIobmV3IFByKG4sZSkpOl9yKHIuZXJyb3JzKX1Qci5wcm90b3R5cGUuZXZhbHVhdGVXaXRob3V0RXJyb3JIYW5kbGluZz1mdW5jdGlvbih0LGUscil7cmV0dXJuIHRoaXMuX2V2YWx1YXRvci5nbG9iYWxzPXQsdGhpcy5fZXZhbHVhdG9yLmZlYXR1cmU9ZSx0aGlzLl9ldmFsdWF0b3IuZmVhdHVyZVN0YXRlPXIsdGhpcy5leHByZXNzaW9uLmV2YWx1YXRlKHRoaXMuX2V2YWx1YXRvcil9LFByLnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0LGUscil7dGhpcy5fZXZhbHVhdG9yLmdsb2JhbHM9dCx0aGlzLl9ldmFsdWF0b3IuZmVhdHVyZT1lfHxudWxsLHRoaXMuX2V2YWx1YXRvci5mZWF0dXJlU3RhdGU9cnx8bnVsbDt0cnl7dmFyIG49dGhpcy5leHByZXNzaW9uLmV2YWx1YXRlKHRoaXMuX2V2YWx1YXRvcik7aWYobnVsbD09bilyZXR1cm4gdGhpcy5fZGVmYXVsdFZhbHVlO2lmKHRoaXMuX2VudW1WYWx1ZXMmJiEobiBpbiB0aGlzLl9lbnVtVmFsdWVzKSl0aHJvdyBuZXcgZmUoXCJFeHBlY3RlZCB2YWx1ZSB0byBiZSBvbmUgb2YgXCIrT2JqZWN0LmtleXModGhpcy5fZW51bVZhbHVlcykubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBKU09OLnN0cmluZ2lmeSh0KX0pLmpvaW4oXCIsIFwiKStcIiwgYnV0IGZvdW5kIFwiK0pTT04uc3RyaW5naWZ5KG4pK1wiIGluc3RlYWQuXCIpO3JldHVybiBufWNhdGNoKHQpe3JldHVybiB0aGlzLl93YXJuaW5nSGlzdG9yeVt0Lm1lc3NhZ2VdfHwodGhpcy5fd2FybmluZ0hpc3RvcnlbdC5tZXNzYWdlXT0hMCxcInVuZGVmaW5lZFwiIT10eXBlb2YgY29uc29sZSYmY29uc29sZS53YXJuKHQubWVzc2FnZSkpLHRoaXMuX2RlZmF1bHRWYWx1ZX19O3ZhciBMcj1mdW5jdGlvbih0LGUpe3RoaXMua2luZD10LHRoaXMuX3N0eWxlRXhwcmVzc2lvbj1lLHRoaXMuaXNTdGF0ZURlcGVuZGVudD1cImNvbnN0YW50XCIhPT10JiYhU2UoZS5leHByZXNzaW9uKTt9O0xyLnByb3RvdHlwZS5ldmFsdWF0ZVdpdGhvdXRFcnJvckhhbmRsaW5nPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gdGhpcy5fc3R5bGVFeHByZXNzaW9uLmV2YWx1YXRlV2l0aG91dEVycm9ySGFuZGxpbmcodCxlLHIpfSxMci5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0aGlzLl9zdHlsZUV4cHJlc3Npb24uZXZhbHVhdGUodCxlLHIpfTt2YXIgRHI9ZnVuY3Rpb24odCxlLHIpe3RoaXMua2luZD10LHRoaXMuem9vbVN0b3BzPXIubGFiZWxzLHRoaXMuX3N0eWxlRXhwcmVzc2lvbj1lLHRoaXMuaXNTdGF0ZURlcGVuZGVudD1cImNhbWVyYVwiIT09dCYmIVNlKGUuZXhwcmVzc2lvbiksciBpbnN0YW5jZW9mICRlJiYodGhpcy5pbnRlcnBvbGF0aW9uVHlwZT1yLmludGVycG9sYXRpb24pO307ZnVuY3Rpb24gT3IodCxlKXtpZihcImVycm9yXCI9PT0odD1Gcih0LGUpKS5yZXN1bHQpcmV0dXJuIHQ7dmFyIHI9dC52YWx1ZS5leHByZXNzaW9uLG49QWUocik7aWYoIW4mJiF3cihlKSlyZXR1cm4gX3IoW25ldyBOdChcIlwiLFwiZGF0YSBleHByZXNzaW9ucyBub3Qgc3VwcG9ydGVkXCIpXSk7dmFyIGk9a2UocixbXCJ6b29tXCJdKTtpZighaSYmIUFyKGUpKXJldHVybiBfcihbbmV3IE50KFwiXCIsXCJ6b29tIGV4cHJlc3Npb25zIG5vdCBzdXBwb3J0ZWRcIildKTt2YXIgYT1mdW5jdGlvbiB0KGUpe3ZhciByPW51bGw7aWYoZSBpbnN0YW5jZW9mIHRyKXI9dChlLnJlc3VsdCk7ZWxzZSBpZihlIGluc3RhbmNlb2YgUWUpZm9yKHZhciBuPTAsaT1lLmFyZ3M7bjxpLmxlbmd0aDtuKz0xKXt2YXIgYT1pW25dO2lmKHI9dChhKSlicmVha31lbHNlKGUgaW5zdGFuY2VvZiBDZXx8ZSBpbnN0YW5jZW9mICRlKSYmZS5pbnB1dCBpbnN0YW5jZW9mIF9lJiZcInpvb21cIj09PWUuaW5wdXQubmFtZSYmKHI9ZSk7aWYociBpbnN0YW5jZW9mIE50KXJldHVybiByO2UuZWFjaENoaWxkKGZ1bmN0aW9uKGUpe3ZhciBuPXQoZSk7biBpbnN0YW5jZW9mIE50P3I9bjohciYmbj9yPW5ldyBOdChcIlwiLCdcInpvb21cIiBleHByZXNzaW9uIG1heSBvbmx5IGJlIHVzZWQgYXMgaW5wdXQgdG8gYSB0b3AtbGV2ZWwgXCJzdGVwXCIgb3IgXCJpbnRlcnBvbGF0ZVwiIGV4cHJlc3Npb24uJyk6ciYmbiYmciE9PW4mJihyPW5ldyBOdChcIlwiLCdPbmx5IG9uZSB6b29tLWJhc2VkIFwic3RlcFwiIG9yIFwiaW50ZXJwb2xhdGVcIiBzdWJleHByZXNzaW9uIG1heSBiZSB1c2VkIGluIGFuIGV4cHJlc3Npb24uJykpO30pO3JldHVybiByfShyKTtyZXR1cm4gYXx8aT9hIGluc3RhbmNlb2YgTnQ/X3IoW2FdKTphIGluc3RhbmNlb2YgJGUmJiFTcihlKT9fcihbbmV3IE50KFwiXCIsJ1wiaW50ZXJwb2xhdGVcIiBleHByZXNzaW9ucyBjYW5ub3QgYmUgdXNlZCB3aXRoIHRoaXMgcHJvcGVydHknKV0pOmJyKGE/bmV3IERyKG4/XCJjYW1lcmFcIjpcImNvbXBvc2l0ZVwiLHQudmFsdWUsYSk6bmV3IExyKG4/XCJjb25zdGFudFwiOlwic291cmNlXCIsdC52YWx1ZSkpOl9yKFtuZXcgTnQoXCJcIiwnXCJ6b29tXCIgZXhwcmVzc2lvbiBtYXkgb25seSBiZSB1c2VkIGFzIGlucHV0IHRvIGEgdG9wLWxldmVsIFwic3RlcFwiIG9yIFwiaW50ZXJwb2xhdGVcIiBleHByZXNzaW9uLicpXSl9RHIucHJvdG90eXBlLmV2YWx1YXRlV2l0aG91dEVycm9ySGFuZGxpbmc9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0aGlzLl9zdHlsZUV4cHJlc3Npb24uZXZhbHVhdGVXaXRob3V0RXJyb3JIYW5kbGluZyh0LGUscil9LERyLnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0LGUscil7cmV0dXJuIHRoaXMuX3N0eWxlRXhwcmVzc2lvbi5ldmFsdWF0ZSh0LGUscil9LERyLnByb3RvdHlwZS5pbnRlcnBvbGF0aW9uRmFjdG9yPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gdGhpcy5pbnRlcnBvbGF0aW9uVHlwZT8kZS5pbnRlcnBvbGF0aW9uRmFjdG9yKHRoaXMuaW50ZXJwb2xhdGlvblR5cGUsdCxlLHIpOjB9O3ZhciBScj1mdW5jdGlvbih0LGUpe3RoaXMuX3BhcmFtZXRlcnM9dCx0aGlzLl9zcGVjaWZpY2F0aW9uPWUsUnQodGhpcyxmdW5jdGlvbiB0KGUscil7dmFyIG4saSxhLG89XCJjb2xvclwiPT09ci50eXBlLHM9ZS5zdG9wcyYmXCJvYmplY3RcIj09dHlwZW9mIGUuc3RvcHNbMF1bMF0sdT1zfHx2b2lkIDAhPT1lLnByb3BlcnR5LGw9c3x8IXUscD1lLnR5cGV8fChTcihyKT9cImV4cG9uZW50aWFsXCI6XCJpbnRlcnZhbFwiKTtpZihvJiYoKGU9UnQoe30sZSkpLnN0b3BzJiYoZS5zdG9wcz1lLnN0b3BzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gW3RbMF0sYWUucGFyc2UodFsxXSldfSkpLGUuZGVmYXVsdD9lLmRlZmF1bHQ9YWUucGFyc2UoZS5kZWZhdWx0KTplLmRlZmF1bHQ9YWUucGFyc2Uoci5kZWZhdWx0KSksZS5jb2xvclNwYWNlJiZcInJnYlwiIT09ZS5jb2xvclNwYWNlJiYhWWVbZS5jb2xvclNwYWNlXSl0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIGNvbG9yIHNwYWNlOiBcIitlLmNvbG9yU3BhY2UpO2lmKFwiZXhwb25lbnRpYWxcIj09PXApbj1NcjtlbHNlIGlmKFwiaW50ZXJ2YWxcIj09PXApbj1FcjtlbHNlIGlmKFwiY2F0ZWdvcmljYWxcIj09PXApe249Q3IsaT1PYmplY3QuY3JlYXRlKG51bGwpO2Zvcih2YXIgYz0wLGg9ZS5zdG9wcztjPGgubGVuZ3RoO2MrPTEpe3ZhciBmPWhbY107aVtmWzBdXT1mWzFdO31hPXR5cGVvZiBlLnN0b3BzWzBdWzBdO31lbHNle2lmKFwiaWRlbnRpdHlcIiE9PXApdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGZ1bmN0aW9uIHR5cGUgXCInK3ArJ1wiJyk7bj1Ucjt9aWYocyl7Zm9yKHZhciB5PXt9LGQ9W10sbT0wO208ZS5zdG9wcy5sZW5ndGg7bSsrKXt2YXIgdj1lLnN0b3BzW21dLGc9dlswXS56b29tO3ZvaWQgMD09PXlbZ10mJih5W2ddPXt6b29tOmcsdHlwZTplLnR5cGUscHJvcGVydHk6ZS5wcm9wZXJ0eSxkZWZhdWx0OmUuZGVmYXVsdCxzdG9wczpbXX0sZC5wdXNoKGcpKSx5W2ddLnN0b3BzLnB1c2goW3ZbMF0udmFsdWUsdlsxXV0pO31mb3IodmFyIHg9W10sYj0wLF89ZDtiPF8ubGVuZ3RoO2IrPTEpe3ZhciB3PV9bYl07eC5wdXNoKFt5W3ddLnpvb20sdCh5W3ddLHIpXSk7fXZhciBBPXtuYW1lOlwibGluZWFyXCJ9O3JldHVybiB7a2luZDpcImNvbXBvc2l0ZVwiLGludGVycG9sYXRpb25UeXBlOkEsaW50ZXJwb2xhdGlvbkZhY3RvcjokZS5pbnRlcnBvbGF0aW9uRmFjdG9yLmJpbmQodm9pZCAwLEEpLHpvb21TdG9wczp4Lm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdFswXX0pLGV2YWx1YXRlOmZ1bmN0aW9uKHQsbil7dmFyIGk9dC56b29tO3JldHVybiBNcih7c3RvcHM6eCxiYXNlOmUuYmFzZX0scixpKS5ldmFsdWF0ZShpLG4pfX19aWYobCl7dmFyIFM9XCJleHBvbmVudGlhbFwiPT09cD97bmFtZTpcImV4cG9uZW50aWFsXCIsYmFzZTp2b2lkIDAhPT1lLmJhc2U/ZS5iYXNlOjF9Om51bGw7cmV0dXJuIHtraW5kOlwiY2FtZXJhXCIsaW50ZXJwb2xhdGlvblR5cGU6UyxpbnRlcnBvbGF0aW9uRmFjdG9yOiRlLmludGVycG9sYXRpb25GYWN0b3IuYmluZCh2b2lkIDAsUyksem9vbVN0b3BzOmUuc3RvcHMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0WzBdfSksZXZhbHVhdGU6ZnVuY3Rpb24odCl7dmFyIG89dC56b29tO3JldHVybiBuKGUscixvLGksYSl9fX1yZXR1cm4ge2tpbmQ6XCJzb3VyY2VcIixldmFsdWF0ZTpmdW5jdGlvbih0LG8pe3ZhciBzPW8mJm8ucHJvcGVydGllcz9vLnByb3BlcnRpZXNbZS5wcm9wZXJ0eV06dm9pZCAwO3JldHVybiB2b2lkIDA9PT1zP0JyKGUuZGVmYXVsdCxyLmRlZmF1bHQpOm4oZSxyLHMsaSxhKX19fSh0aGlzLl9wYXJhbWV0ZXJzLHRoaXMuX3NwZWNpZmljYXRpb24pKTt9O2Z1bmN0aW9uIFVyKHQpe3ZhciBlPXQua2V5LHI9dC52YWx1ZSxuPXQudmFsdWVTcGVjfHx7fSxpPXQub2JqZWN0RWxlbWVudFZhbGlkYXRvcnN8fHt9LGE9dC5zdHlsZSxvPXQuc3R5bGVTcGVjLHM9W10sdT1rcihyKTtpZihcIm9iamVjdFwiIT09dSlyZXR1cm4gW25ldyBEdChlLHIsXCJvYmplY3QgZXhwZWN0ZWQsIFwiK3UrXCIgZm91bmRcIildO2Zvcih2YXIgbCBpbiByKXt2YXIgcD1sLnNwbGl0KFwiLlwiKVswXSxjPW5bcF18fG5bXCIqXCJdLGg9dm9pZCAwO2lmKGlbcF0paD1pW3BdO2Vsc2UgaWYobltwXSloPWNuO2Vsc2UgaWYoaVtcIipcIl0paD1pW1wiKlwiXTtlbHNle2lmKCFuW1wiKlwiXSl7cy5wdXNoKG5ldyBEdChlLHJbbF0sJ3Vua25vd24gcHJvcGVydHkgXCInK2wrJ1wiJykpO2NvbnRpbnVlfWg9Y247fXM9cy5jb25jYXQoaCh7a2V5OihlP2UrXCIuXCI6ZSkrbCx2YWx1ZTpyW2xdLHZhbHVlU3BlYzpjLHN0eWxlOmEsc3R5bGVTcGVjOm8sb2JqZWN0OnIsb2JqZWN0S2V5Omx9LHIpKTt9Zm9yKHZhciBmIGluIG4paVtmXXx8bltmXS5yZXF1aXJlZCYmdm9pZCAwPT09bltmXS5kZWZhdWx0JiZ2b2lkIDA9PT1yW2ZdJiZzLnB1c2gobmV3IER0KGUsciwnbWlzc2luZyByZXF1aXJlZCBwcm9wZXJ0eSBcIicrZisnXCInKSk7cmV0dXJuIHN9ZnVuY3Rpb24ganIodCl7dmFyIGU9dC52YWx1ZSxyPXQudmFsdWVTcGVjLG49dC5zdHlsZSxpPXQuc3R5bGVTcGVjLGE9dC5rZXksbz10LmFycmF5RWxlbWVudFZhbGlkYXRvcnx8Y247aWYoXCJhcnJheVwiIT09a3IoZSkpcmV0dXJuIFtuZXcgRHQoYSxlLFwiYXJyYXkgZXhwZWN0ZWQsIFwiK2tyKGUpK1wiIGZvdW5kXCIpXTtpZihyLmxlbmd0aCYmZS5sZW5ndGghPT1yLmxlbmd0aClyZXR1cm4gW25ldyBEdChhLGUsXCJhcnJheSBsZW5ndGggXCIrci5sZW5ndGgrXCIgZXhwZWN0ZWQsIGxlbmd0aCBcIitlLmxlbmd0aCtcIiBmb3VuZFwiKV07aWYocltcIm1pbi1sZW5ndGhcIl0mJmUubGVuZ3RoPHJbXCJtaW4tbGVuZ3RoXCJdKXJldHVybiBbbmV3IER0KGEsZSxcImFycmF5IGxlbmd0aCBhdCBsZWFzdCBcIityW1wibWluLWxlbmd0aFwiXStcIiBleHBlY3RlZCwgbGVuZ3RoIFwiK2UubGVuZ3RoK1wiIGZvdW5kXCIpXTt2YXIgcz17dHlwZTpyLnZhbHVlLHZhbHVlczpyLnZhbHVlc307aS4kdmVyc2lvbjw3JiYocy5mdW5jdGlvbj1yLmZ1bmN0aW9uKSxcIm9iamVjdFwiPT09a3Ioci52YWx1ZSkmJihzPXIudmFsdWUpO2Zvcih2YXIgdT1bXSxsPTA7bDxlLmxlbmd0aDtsKyspdT11LmNvbmNhdChvKHthcnJheTplLGFycmF5SW5kZXg6bCx2YWx1ZTplW2xdLHZhbHVlU3BlYzpzLHN0eWxlOm4sc3R5bGVTcGVjOmksa2V5OmErXCJbXCIrbCtcIl1cIn0pKTtyZXR1cm4gdX1mdW5jdGlvbiBxcih0KXt2YXIgZT10LmtleSxyPXQudmFsdWUsbj10LnZhbHVlU3BlYyxpPWtyKHIpO3JldHVybiBcIm51bWJlclwiIT09aT9bbmV3IER0KGUscixcIm51bWJlciBleHBlY3RlZCwgXCIraStcIiBmb3VuZFwiKV06XCJtaW5pbXVtXCJpbiBuJiZyPG4ubWluaW11bT9bbmV3IER0KGUscixyK1wiIGlzIGxlc3MgdGhhbiB0aGUgbWluaW11bSB2YWx1ZSBcIituLm1pbmltdW0pXTpcIm1heGltdW1cImluIG4mJnI+bi5tYXhpbXVtP1tuZXcgRHQoZSxyLHIrXCIgaXMgZ3JlYXRlciB0aGFuIHRoZSBtYXhpbXVtIHZhbHVlIFwiK24ubWF4aW11bSldOltdfWZ1bmN0aW9uIE5yKHQpe3ZhciBlLHIsbixpPXQudmFsdWVTcGVjLGE9anQodC52YWx1ZS50eXBlKSxvPXt9LHM9XCJjYXRlZ29yaWNhbFwiIT09YSYmdm9pZCAwPT09dC52YWx1ZS5wcm9wZXJ0eSx1PSFzLGw9XCJhcnJheVwiPT09a3IodC52YWx1ZS5zdG9wcykmJlwiYXJyYXlcIj09PWtyKHQudmFsdWUuc3RvcHNbMF0pJiZcIm9iamVjdFwiPT09a3IodC52YWx1ZS5zdG9wc1swXVswXSkscD1Vcih7a2V5OnQua2V5LHZhbHVlOnQudmFsdWUsdmFsdWVTcGVjOnQuc3R5bGVTcGVjLmZ1bmN0aW9uLHN0eWxlOnQuc3R5bGUsc3R5bGVTcGVjOnQuc3R5bGVTcGVjLG9iamVjdEVsZW1lbnRWYWxpZGF0b3JzOntzdG9wczpmdW5jdGlvbih0KXtpZihcImlkZW50aXR5XCI9PT1hKXJldHVybiBbbmV3IER0KHQua2V5LHQudmFsdWUsJ2lkZW50aXR5IGZ1bmN0aW9uIG1heSBub3QgaGF2ZSBhIFwic3RvcHNcIiBwcm9wZXJ0eScpXTt2YXIgZT1bXSxyPXQudmFsdWU7ZT1lLmNvbmNhdChqcih7a2V5OnQua2V5LHZhbHVlOnIsdmFsdWVTcGVjOnQudmFsdWVTcGVjLHN0eWxlOnQuc3R5bGUsc3R5bGVTcGVjOnQuc3R5bGVTcGVjLGFycmF5RWxlbWVudFZhbGlkYXRvcjpjfSkpLFwiYXJyYXlcIj09PWtyKHIpJiYwPT09ci5sZW5ndGgmJmUucHVzaChuZXcgRHQodC5rZXkscixcImFycmF5IG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgc3RvcFwiKSk7cmV0dXJuIGV9LGRlZmF1bHQ6ZnVuY3Rpb24odCl7cmV0dXJuIGNuKHtrZXk6dC5rZXksdmFsdWU6dC52YWx1ZSx2YWx1ZVNwZWM6aSxzdHlsZTp0LnN0eWxlLHN0eWxlU3BlYzp0LnN0eWxlU3BlY30pfX19KTtyZXR1cm4gXCJpZGVudGl0eVwiPT09YSYmcyYmcC5wdXNoKG5ldyBEdCh0LmtleSx0LnZhbHVlLCdtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IFwicHJvcGVydHlcIicpKSxcImlkZW50aXR5XCI9PT1hfHx0LnZhbHVlLnN0b3BzfHxwLnB1c2gobmV3IER0KHQua2V5LHQudmFsdWUsJ21pc3NpbmcgcmVxdWlyZWQgcHJvcGVydHkgXCJzdG9wc1wiJykpLFwiZXhwb25lbnRpYWxcIj09PWEmJnQudmFsdWVTcGVjLmV4cHJlc3Npb24mJiFTcih0LnZhbHVlU3BlYykmJnAucHVzaChuZXcgRHQodC5rZXksdC52YWx1ZSxcImV4cG9uZW50aWFsIGZ1bmN0aW9ucyBub3Qgc3VwcG9ydGVkXCIpKSx0LnN0eWxlU3BlYy4kdmVyc2lvbj49OCYmKHUmJiF3cih0LnZhbHVlU3BlYyk/cC5wdXNoKG5ldyBEdCh0LmtleSx0LnZhbHVlLFwicHJvcGVydHkgZnVuY3Rpb25zIG5vdCBzdXBwb3J0ZWRcIikpOnMmJiFBcih0LnZhbHVlU3BlYykmJnAucHVzaChuZXcgRHQodC5rZXksdC52YWx1ZSxcInpvb20gZnVuY3Rpb25zIG5vdCBzdXBwb3J0ZWRcIikpKSxcImNhdGVnb3JpY2FsXCIhPT1hJiYhbHx8dm9pZCAwIT09dC52YWx1ZS5wcm9wZXJ0eXx8cC5wdXNoKG5ldyBEdCh0LmtleSx0LnZhbHVlLCdcInByb3BlcnR5XCIgcHJvcGVydHkgaXMgcmVxdWlyZWQnKSkscDtmdW5jdGlvbiBjKHQpe3ZhciBlPVtdLGE9dC52YWx1ZSxzPXQua2V5O2lmKFwiYXJyYXlcIiE9PWtyKGEpKXJldHVybiBbbmV3IER0KHMsYSxcImFycmF5IGV4cGVjdGVkLCBcIitrcihhKStcIiBmb3VuZFwiKV07aWYoMiE9PWEubGVuZ3RoKXJldHVybiBbbmV3IER0KHMsYSxcImFycmF5IGxlbmd0aCAyIGV4cGVjdGVkLCBsZW5ndGggXCIrYS5sZW5ndGgrXCIgZm91bmRcIildO2lmKGwpe2lmKFwib2JqZWN0XCIhPT1rcihhWzBdKSlyZXR1cm4gW25ldyBEdChzLGEsXCJvYmplY3QgZXhwZWN0ZWQsIFwiK2tyKGFbMF0pK1wiIGZvdW5kXCIpXTtpZih2b2lkIDA9PT1hWzBdLnpvb20pcmV0dXJuIFtuZXcgRHQocyxhLFwib2JqZWN0IHN0b3Aga2V5IG11c3QgaGF2ZSB6b29tXCIpXTtpZih2b2lkIDA9PT1hWzBdLnZhbHVlKXJldHVybiBbbmV3IER0KHMsYSxcIm9iamVjdCBzdG9wIGtleSBtdXN0IGhhdmUgdmFsdWVcIildO2lmKG4mJm4+anQoYVswXS56b29tKSlyZXR1cm4gW25ldyBEdChzLGFbMF0uem9vbSxcInN0b3Agem9vbSB2YWx1ZXMgbXVzdCBhcHBlYXIgaW4gYXNjZW5kaW5nIG9yZGVyXCIpXTtqdChhWzBdLnpvb20pIT09biYmKG49anQoYVswXS56b29tKSxyPXZvaWQgMCxvPXt9KSxlPWUuY29uY2F0KFVyKHtrZXk6cytcIlswXVwiLHZhbHVlOmFbMF0sdmFsdWVTcGVjOnt6b29tOnt9fSxzdHlsZTp0LnN0eWxlLHN0eWxlU3BlYzp0LnN0eWxlU3BlYyxvYmplY3RFbGVtZW50VmFsaWRhdG9yczp7em9vbTpxcix2YWx1ZTpofX0pKTt9ZWxzZSBlPWUuY29uY2F0KGgoe2tleTpzK1wiWzBdXCIsdmFsdWU6YVswXSx2YWx1ZVNwZWM6e30sc3R5bGU6dC5zdHlsZSxzdHlsZVNwZWM6dC5zdHlsZVNwZWN9LGEpKTtyZXR1cm4gVnIocXQoYVsxXSkpP2UuY29uY2F0KFtuZXcgRHQocytcIlsxXVwiLGFbMV0sXCJleHByZXNzaW9ucyBhcmUgbm90IGFsbG93ZWQgaW4gZnVuY3Rpb24gc3RvcHMuXCIpXSk6ZS5jb25jYXQoY24oe2tleTpzK1wiWzFdXCIsdmFsdWU6YVsxXSx2YWx1ZVNwZWM6aSxzdHlsZTp0LnN0eWxlLHN0eWxlU3BlYzp0LnN0eWxlU3BlY30pKX1mdW5jdGlvbiBoKHQsbil7dmFyIHM9a3IodC52YWx1ZSksdT1qdCh0LnZhbHVlKSxsPW51bGwhPT10LnZhbHVlP3QudmFsdWU6bjtpZihlKXtpZihzIT09ZSlyZXR1cm4gW25ldyBEdCh0LmtleSxsLHMrXCIgc3RvcCBkb21haW4gdHlwZSBtdXN0IG1hdGNoIHByZXZpb3VzIHN0b3AgZG9tYWluIHR5cGUgXCIrZSldfWVsc2UgZT1zO2lmKFwibnVtYmVyXCIhPT1zJiZcInN0cmluZ1wiIT09cyYmXCJib29sZWFuXCIhPT1zKXJldHVybiBbbmV3IER0KHQua2V5LGwsXCJzdG9wIGRvbWFpbiB2YWx1ZSBtdXN0IGJlIGEgbnVtYmVyLCBzdHJpbmcsIG9yIGJvb2xlYW5cIildO2lmKFwibnVtYmVyXCIhPT1zJiZcImNhdGVnb3JpY2FsXCIhPT1hKXt2YXIgcD1cIm51bWJlciBleHBlY3RlZCwgXCIrcytcIiBmb3VuZFwiO3JldHVybiB3cihpKSYmdm9pZCAwPT09YSYmKHArPSdcXG5JZiB5b3UgaW50ZW5kZWQgdG8gdXNlIGEgY2F0ZWdvcmljYWwgZnVuY3Rpb24sIHNwZWNpZnkgYFwidHlwZVwiOiBcImNhdGVnb3JpY2FsXCJgLicpLFtuZXcgRHQodC5rZXksbCxwKV19cmV0dXJuIFwiY2F0ZWdvcmljYWxcIiE9PWF8fFwibnVtYmVyXCIhPT1zfHxpc0Zpbml0ZSh1KSYmTWF0aC5mbG9vcih1KT09PXU/XCJjYXRlZ29yaWNhbFwiIT09YSYmXCJudW1iZXJcIj09PXMmJnZvaWQgMCE9PXImJnU8cj9bbmV3IER0KHQua2V5LGwsXCJzdG9wIGRvbWFpbiB2YWx1ZXMgbXVzdCBhcHBlYXIgaW4gYXNjZW5kaW5nIG9yZGVyXCIpXToocj11LFwiY2F0ZWdvcmljYWxcIj09PWEmJnUgaW4gbz9bbmV3IER0KHQua2V5LGwsXCJzdG9wIGRvbWFpbiB2YWx1ZXMgbXVzdCBiZSB1bmlxdWVcIildOihvW3VdPSEwLFtdKSk6W25ldyBEdCh0LmtleSxsLFwiaW50ZWdlciBleHBlY3RlZCwgZm91bmQgXCIrdSldfX1mdW5jdGlvbiBacih0KXt2YXIgZT0oXCJwcm9wZXJ0eVwiPT09dC5leHByZXNzaW9uQ29udGV4dD9PcjpGcikocXQodC52YWx1ZSksdC52YWx1ZVNwZWMpO2lmKFwiZXJyb3JcIj09PWUucmVzdWx0KXJldHVybiBlLnZhbHVlLm1hcChmdW5jdGlvbihlKXtyZXR1cm4gbmV3IER0KFwiXCIrdC5rZXkrZS5rZXksdC52YWx1ZSxlLm1lc3NhZ2UpfSk7dmFyIHI9ZS52YWx1ZS5leHByZXNzaW9ufHxlLnZhbHVlLl9zdHlsZUV4cHJlc3Npb24uZXhwcmVzc2lvbjtpZihcInByb3BlcnR5XCI9PT10LmV4cHJlc3Npb25Db250ZXh0JiZcInRleHQtZm9udFwiPT09dC5wcm9wZXJ0eUtleSYmLTEhPT1yLnBvc3NpYmxlT3V0cHV0cygpLmluZGV4T2Yodm9pZCAwKSlyZXR1cm4gW25ldyBEdCh0LmtleSx0LnZhbHVlLCdJbnZhbGlkIGRhdGEgZXhwcmVzc2lvbiBmb3IgXCInK3QucHJvcGVydHlLZXkrJ1wiLiBPdXRwdXQgdmFsdWVzIG11c3QgYmUgY29udGFpbmVkIGFzIGxpdGVyYWxzIHdpdGhpbiB0aGUgZXhwcmVzc2lvbi4nKV07aWYoXCJwcm9wZXJ0eVwiPT09dC5leHByZXNzaW9uQ29udGV4dCYmXCJsYXlvdXRcIj09PXQucHJvcGVydHlUeXBlJiYhU2UocikpcmV0dXJuIFtuZXcgRHQodC5rZXksdC52YWx1ZSwnXCJmZWF0dXJlLXN0YXRlXCIgZGF0YSBleHByZXNzaW9ucyBhcmUgbm90IHN1cHBvcnRlZCB3aXRoIGxheW91dCBwcm9wZXJ0aWVzLicpXTtpZihcImZpbHRlclwiPT09dC5leHByZXNzaW9uQ29udGV4dCYmIVNlKHIpKXJldHVybiBbbmV3IER0KHQua2V5LHQudmFsdWUsJ1wiZmVhdHVyZS1zdGF0ZVwiIGRhdGEgZXhwcmVzc2lvbnMgYXJlIG5vdCBzdXBwb3J0ZWQgd2l0aCBmaWx0ZXJzLicpXTtpZih0LmV4cHJlc3Npb25Db250ZXh0JiYwPT09dC5leHByZXNzaW9uQ29udGV4dC5pbmRleE9mKFwiY2x1c3RlclwiKSl7aWYoIWtlKHIsW1wiem9vbVwiLFwiZmVhdHVyZS1zdGF0ZVwiXSkpcmV0dXJuIFtuZXcgRHQodC5rZXksdC52YWx1ZSwnXCJ6b29tXCIgYW5kIFwiZmVhdHVyZS1zdGF0ZVwiIGV4cHJlc3Npb25zIGFyZSBub3Qgc3VwcG9ydGVkIHdpdGggY2x1c3RlciBwcm9wZXJ0aWVzLicpXTtpZihcImNsdXN0ZXItaW5pdGlhbFwiPT09dC5leHByZXNzaW9uQ29udGV4dCYmIUFlKHIpKXJldHVybiBbbmV3IER0KHQua2V5LHQudmFsdWUsXCJGZWF0dXJlIGRhdGEgZXhwcmVzc2lvbnMgYXJlIG5vdCBzdXBwb3J0ZWQgd2l0aCBpbml0aWFsIGV4cHJlc3Npb24gcGFydCBvZiBjbHVzdGVyIHByb3BlcnRpZXMuXCIpXX1yZXR1cm4gW119ZnVuY3Rpb24gS3IodCl7dmFyIGU9dC5rZXkscj10LnZhbHVlLG49dC52YWx1ZVNwZWMsaT1bXTtyZXR1cm4gQXJyYXkuaXNBcnJheShuLnZhbHVlcyk/LTE9PT1uLnZhbHVlcy5pbmRleE9mKGp0KHIpKSYmaS5wdXNoKG5ldyBEdChlLHIsXCJleHBlY3RlZCBvbmUgb2YgW1wiK24udmFsdWVzLmpvaW4oXCIsIFwiKStcIl0sIFwiK0pTT04uc3RyaW5naWZ5KHIpK1wiIGZvdW5kXCIpKTotMT09PU9iamVjdC5rZXlzKG4udmFsdWVzKS5pbmRleE9mKGp0KHIpKSYmaS5wdXNoKG5ldyBEdChlLHIsXCJleHBlY3RlZCBvbmUgb2YgW1wiK09iamVjdC5rZXlzKG4udmFsdWVzKS5qb2luKFwiLCBcIikrXCJdLCBcIitKU09OLnN0cmluZ2lmeShyKStcIiBmb3VuZFwiKSksaX1mdW5jdGlvbiBHcih0KXtpZighMD09PXR8fCExPT09dClyZXR1cm4gITA7aWYoIUFycmF5LmlzQXJyYXkodCl8fDA9PT10Lmxlbmd0aClyZXR1cm4gITE7c3dpdGNoKHRbMF0pe2Nhc2VcImhhc1wiOnJldHVybiB0Lmxlbmd0aD49MiYmXCIkaWRcIiE9PXRbMV0mJlwiJHR5cGVcIiE9PXRbMV07Y2FzZVwiaW5cIjpjYXNlXCIhaW5cIjpjYXNlXCIhaGFzXCI6Y2FzZVwibm9uZVwiOnJldHVybiAhMTtjYXNlXCI9PVwiOmNhc2VcIiE9XCI6Y2FzZVwiPlwiOmNhc2VcIj49XCI6Y2FzZVwiPFwiOmNhc2VcIjw9XCI6cmV0dXJuIDMhPT10Lmxlbmd0aHx8QXJyYXkuaXNBcnJheSh0WzFdKXx8QXJyYXkuaXNBcnJheSh0WzJdKTtjYXNlXCJhbnlcIjpjYXNlXCJhbGxcIjpmb3IodmFyIGU9MCxyPXQuc2xpY2UoMSk7ZTxyLmxlbmd0aDtlKz0xKXt2YXIgbj1yW2VdO2lmKCFHcihuKSYmXCJib29sZWFuXCIhPXR5cGVvZiBuKXJldHVybiAhMX1yZXR1cm4gITA7ZGVmYXVsdDpyZXR1cm4gITB9fVJyLmRlc2VyaWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgUnIodC5fcGFyYW1ldGVycyx0Ll9zcGVjaWZpY2F0aW9uKX0sUnIuc2VyaWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiB7X3BhcmFtZXRlcnM6dC5fcGFyYW1ldGVycyxfc3BlY2lmaWNhdGlvbjp0Ll9zcGVjaWZpY2F0aW9ufX07dmFyIFhyPXt0eXBlOlwiYm9vbGVhblwiLGRlZmF1bHQ6ITEsdHJhbnNpdGlvbjohMSxcInByb3BlcnR5LXR5cGVcIjpcImRhdGEtZHJpdmVuXCIsZXhwcmVzc2lvbjp7aW50ZXJwb2xhdGVkOiExLHBhcmFtZXRlcnM6W1wiem9vbVwiLFwiZmVhdHVyZVwiXX19O2Z1bmN0aW9uIEpyKHQpe2lmKG51bGw9PXQpcmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuICEwfTtHcih0KXx8KHQ9WXIodCkpO3ZhciBlPUZyKHQsWHIpO2lmKFwiZXJyb3JcIj09PWUucmVzdWx0KXRocm93IG5ldyBFcnJvcihlLnZhbHVlLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC5rZXkrXCI6IFwiK3QubWVzc2FnZX0pLmpvaW4oXCIsIFwiKSk7cmV0dXJuIGZ1bmN0aW9uKHQscil7cmV0dXJuIGUudmFsdWUuZXZhbHVhdGUodCxyKX19ZnVuY3Rpb24gSHIodCxlKXtyZXR1cm4gdDxlPy0xOnQ+ZT8xOjB9ZnVuY3Rpb24gWXIodCl7aWYoIXQpcmV0dXJuICEwO3ZhciBlLHI9dFswXTtyZXR1cm4gdC5sZW5ndGg8PTE/XCJhbnlcIiE9PXI6XCI9PVwiPT09cj8kcih0WzFdLHRbMl0sXCI9PVwiKTpcIiE9XCI9PT1yP3RuKCRyKHRbMV0sdFsyXSxcIj09XCIpKTpcIjxcIj09PXJ8fFwiPlwiPT09cnx8XCI8PVwiPT09cnx8XCI+PVwiPT09cj8kcih0WzFdLHRbMl0scik6XCJhbnlcIj09PXI/KGU9dC5zbGljZSgxKSxbXCJhbnlcIl0uY29uY2F0KGUubWFwKFlyKSkpOlwiYWxsXCI9PT1yP1tcImFsbFwiXS5jb25jYXQodC5zbGljZSgxKS5tYXAoWXIpKTpcIm5vbmVcIj09PXI/W1wiYWxsXCJdLmNvbmNhdCh0LnNsaWNlKDEpLm1hcChZcikubWFwKHRuKSk6XCJpblwiPT09cj9Xcih0WzFdLHQuc2xpY2UoMikpOlwiIWluXCI9PT1yP3RuKFdyKHRbMV0sdC5zbGljZSgyKSkpOlwiaGFzXCI9PT1yP1FyKHRbMV0pOlwiIWhhc1wiIT09cnx8dG4oUXIodFsxXSkpfWZ1bmN0aW9uICRyKHQsZSxyKXtzd2l0Y2godCl7Y2FzZVwiJHR5cGVcIjpyZXR1cm4gW1wiZmlsdGVyLXR5cGUtXCIrcixlXTtjYXNlXCIkaWRcIjpyZXR1cm4gW1wiZmlsdGVyLWlkLVwiK3IsZV07ZGVmYXVsdDpyZXR1cm4gW1wiZmlsdGVyLVwiK3IsdCxlXX19ZnVuY3Rpb24gV3IodCxlKXtpZigwPT09ZS5sZW5ndGgpcmV0dXJuICExO3N3aXRjaCh0KXtjYXNlXCIkdHlwZVwiOnJldHVybiBbXCJmaWx0ZXItdHlwZS1pblwiLFtcImxpdGVyYWxcIixlXV07Y2FzZVwiJGlkXCI6cmV0dXJuIFtcImZpbHRlci1pZC1pblwiLFtcImxpdGVyYWxcIixlXV07ZGVmYXVsdDpyZXR1cm4gZS5sZW5ndGg+MjAwJiYhZS5zb21lKGZ1bmN0aW9uKHQpe3JldHVybiB0eXBlb2YgdCE9dHlwZW9mIGVbMF19KT9bXCJmaWx0ZXItaW4tbGFyZ2VcIix0LFtcImxpdGVyYWxcIixlLnNvcnQoSHIpXV06W1wiZmlsdGVyLWluLXNtYWxsXCIsdCxbXCJsaXRlcmFsXCIsZV1dfX1mdW5jdGlvbiBRcih0KXtzd2l0Y2godCl7Y2FzZVwiJHR5cGVcIjpyZXR1cm4gITA7Y2FzZVwiJGlkXCI6cmV0dXJuIFtcImZpbHRlci1oYXMtaWRcIl07ZGVmYXVsdDpyZXR1cm4gW1wiZmlsdGVyLWhhc1wiLHRdfX1mdW5jdGlvbiB0bih0KXtyZXR1cm4gW1wiIVwiLHRdfWZ1bmN0aW9uIGVuKHQpe3JldHVybiBHcihxdCh0LnZhbHVlKSk/WnIoUnQoe30sdCx7ZXhwcmVzc2lvbkNvbnRleHQ6XCJmaWx0ZXJcIix2YWx1ZVNwZWM6e3ZhbHVlOlwiYm9vbGVhblwifX0pKTpmdW5jdGlvbiB0KGUpe3ZhciByPWUudmFsdWU7dmFyIG49ZS5rZXk7aWYoXCJhcnJheVwiIT09a3IocikpcmV0dXJuIFtuZXcgRHQobixyLFwiYXJyYXkgZXhwZWN0ZWQsIFwiK2tyKHIpK1wiIGZvdW5kXCIpXTt2YXIgaT1lLnN0eWxlU3BlYzt2YXIgYTt2YXIgbz1bXTtpZihyLmxlbmd0aDwxKXJldHVybiBbbmV3IER0KG4scixcImZpbHRlciBhcnJheSBtdXN0IGhhdmUgYXQgbGVhc3QgMSBlbGVtZW50XCIpXTtvPW8uY29uY2F0KEtyKHtrZXk6bitcIlswXVwiLHZhbHVlOnJbMF0sdmFsdWVTcGVjOmkuZmlsdGVyX29wZXJhdG9yLHN0eWxlOmUuc3R5bGUsc3R5bGVTcGVjOmUuc3R5bGVTcGVjfSkpO3N3aXRjaChqdChyWzBdKSl7Y2FzZVwiPFwiOmNhc2VcIjw9XCI6Y2FzZVwiPlwiOmNhc2VcIj49XCI6ci5sZW5ndGg+PTImJlwiJHR5cGVcIj09PWp0KHJbMV0pJiZvLnB1c2gobmV3IER0KG4sciwnXCIkdHlwZVwiIGNhbm5vdCBiZSB1c2Ugd2l0aCBvcGVyYXRvciBcIicrclswXSsnXCInKSk7Y2FzZVwiPT1cIjpjYXNlXCIhPVwiOjMhPT1yLmxlbmd0aCYmby5wdXNoKG5ldyBEdChuLHIsJ2ZpbHRlciBhcnJheSBmb3Igb3BlcmF0b3IgXCInK3JbMF0rJ1wiIG11c3QgaGF2ZSAzIGVsZW1lbnRzJykpO2Nhc2VcImluXCI6Y2FzZVwiIWluXCI6ci5sZW5ndGg+PTImJlwic3RyaW5nXCIhPT0oYT1rcihyWzFdKSkmJm8ucHVzaChuZXcgRHQobitcIlsxXVwiLHJbMV0sXCJzdHJpbmcgZXhwZWN0ZWQsIFwiK2ErXCIgZm91bmRcIikpO2Zvcih2YXIgcz0yO3M8ci5sZW5ndGg7cysrKWE9a3IocltzXSksXCIkdHlwZVwiPT09anQoclsxXSk/bz1vLmNvbmNhdChLcih7a2V5Om4rXCJbXCIrcytcIl1cIix2YWx1ZTpyW3NdLHZhbHVlU3BlYzppLmdlb21ldHJ5X3R5cGUsc3R5bGU6ZS5zdHlsZSxzdHlsZVNwZWM6ZS5zdHlsZVNwZWN9KSk6XCJzdHJpbmdcIiE9PWEmJlwibnVtYmVyXCIhPT1hJiZcImJvb2xlYW5cIiE9PWEmJm8ucHVzaChuZXcgRHQobitcIltcIitzK1wiXVwiLHJbc10sXCJzdHJpbmcsIG51bWJlciwgb3IgYm9vbGVhbiBleHBlY3RlZCwgXCIrYStcIiBmb3VuZFwiKSk7YnJlYWs7Y2FzZVwiYW55XCI6Y2FzZVwiYWxsXCI6Y2FzZVwibm9uZVwiOmZvcih2YXIgdT0xO3U8ci5sZW5ndGg7dSsrKW89by5jb25jYXQodCh7a2V5Om4rXCJbXCIrdStcIl1cIix2YWx1ZTpyW3VdLHN0eWxlOmUuc3R5bGUsc3R5bGVTcGVjOmUuc3R5bGVTcGVjfSkpO2JyZWFrO2Nhc2VcImhhc1wiOmNhc2VcIiFoYXNcIjphPWtyKHJbMV0pLDIhPT1yLmxlbmd0aD9vLnB1c2gobmV3IER0KG4sciwnZmlsdGVyIGFycmF5IGZvciBcIicrclswXSsnXCIgb3BlcmF0b3IgbXVzdCBoYXZlIDIgZWxlbWVudHMnKSk6XCJzdHJpbmdcIiE9PWEmJm8ucHVzaChuZXcgRHQobitcIlsxXVwiLHJbMV0sXCJzdHJpbmcgZXhwZWN0ZWQsIFwiK2ErXCIgZm91bmRcIikpO31yZXR1cm4gb30odCl9ZnVuY3Rpb24gcm4odCxlKXt2YXIgcj10LmtleSxuPXQuc3R5bGUsaT10LnN0eWxlU3BlYyxhPXQudmFsdWUsbz10Lm9iamVjdEtleSxzPWlbZStcIl9cIit0LmxheWVyVHlwZV07aWYoIXMpcmV0dXJuIFtdO3ZhciB1PW8ubWF0Y2goL14oLiopLXRyYW5zaXRpb24kLyk7aWYoXCJwYWludFwiPT09ZSYmdSYmc1t1WzFdXSYmc1t1WzFdXS50cmFuc2l0aW9uKXJldHVybiBjbih7a2V5OnIsdmFsdWU6YSx2YWx1ZVNwZWM6aS50cmFuc2l0aW9uLHN0eWxlOm4sc3R5bGVTcGVjOml9KTt2YXIgbCxwPXQudmFsdWVTcGVjfHxzW29dO2lmKCFwKXJldHVybiBbbmV3IER0KHIsYSwndW5rbm93biBwcm9wZXJ0eSBcIicrbysnXCInKV07aWYoXCJzdHJpbmdcIj09PWtyKGEpJiZ3cihwKSYmIXAudG9rZW5zJiYobD0vXnsoW159XSspfSQvLmV4ZWMoYSkpKXJldHVybiBbbmV3IER0KHIsYSwnXCInK28rJ1wiIGRvZXMgbm90IHN1cHBvcnQgaW50ZXJwb2xhdGlvbiBzeW50YXhcXG5Vc2UgYW4gaWRlbnRpdHkgcHJvcGVydHkgZnVuY3Rpb24gaW5zdGVhZDogYHsgXCJ0eXBlXCI6IFwiaWRlbnRpdHlcIiwgXCJwcm9wZXJ0eVwiOiAnK0pTT04uc3RyaW5naWZ5KGxbMV0pK1wiIH1gLlwiKV07dmFyIGM9W107cmV0dXJuIFwic3ltYm9sXCI9PT10LmxheWVyVHlwZSYmKFwidGV4dC1maWVsZFwiPT09byYmbiYmIW4uZ2x5cGhzJiZjLnB1c2gobmV3IER0KHIsYSwndXNlIG9mIFwidGV4dC1maWVsZFwiIHJlcXVpcmVzIGEgc3R5bGUgXCJnbHlwaHNcIiBwcm9wZXJ0eScpKSxcInRleHQtZm9udFwiPT09byYmenIocXQoYSkpJiZcImlkZW50aXR5XCI9PT1qdChhLnR5cGUpJiZjLnB1c2gobmV3IER0KHIsYSwnXCJ0ZXh0LWZvbnRcIiBkb2VzIG5vdCBzdXBwb3J0IGlkZW50aXR5IGZ1bmN0aW9ucycpKSksYy5jb25jYXQoY24oe2tleTp0LmtleSx2YWx1ZTphLHZhbHVlU3BlYzpwLHN0eWxlOm4sc3R5bGVTcGVjOmksZXhwcmVzc2lvbkNvbnRleHQ6XCJwcm9wZXJ0eVwiLHByb3BlcnR5VHlwZTplLHByb3BlcnR5S2V5Om99KSl9ZnVuY3Rpb24gbm4odCl7cmV0dXJuIHJuKHQsXCJwYWludFwiKX1mdW5jdGlvbiBhbih0KXtyZXR1cm4gcm4odCxcImxheW91dFwiKX1mdW5jdGlvbiBvbih0KXt2YXIgZT1bXSxyPXQudmFsdWUsbj10LmtleSxpPXQuc3R5bGUsYT10LnN0eWxlU3BlYztyLnR5cGV8fHIucmVmfHxlLnB1c2gobmV3IER0KG4sciwnZWl0aGVyIFwidHlwZVwiIG9yIFwicmVmXCIgaXMgcmVxdWlyZWQnKSk7dmFyIG8scz1qdChyLnR5cGUpLHU9anQoci5yZWYpO2lmKHIuaWQpZm9yKHZhciBsPWp0KHIuaWQpLHA9MDtwPHQuYXJyYXlJbmRleDtwKyspe3ZhciBjPWkubGF5ZXJzW3BdO2p0KGMuaWQpPT09bCYmZS5wdXNoKG5ldyBEdChuLHIuaWQsJ2R1cGxpY2F0ZSBsYXllciBpZCBcIicrci5pZCsnXCIsIHByZXZpb3VzbHkgdXNlZCBhdCBsaW5lICcrYy5pZC5fX2xpbmVfXykpO31pZihcInJlZlwiaW4gcilbXCJ0eXBlXCIsXCJzb3VyY2VcIixcInNvdXJjZS1sYXllclwiLFwiZmlsdGVyXCIsXCJsYXlvdXRcIl0uZm9yRWFjaChmdW5jdGlvbih0KXt0IGluIHImJmUucHVzaChuZXcgRHQobixyW3RdLCdcIicrdCsnXCIgaXMgcHJvaGliaXRlZCBmb3IgcmVmIGxheWVycycpKTt9KSxpLmxheWVycy5mb3JFYWNoKGZ1bmN0aW9uKHQpe2p0KHQuaWQpPT09dSYmKG89dCk7fSksbz9vLnJlZj9lLnB1c2gobmV3IER0KG4sci5yZWYsXCJyZWYgY2Fubm90IHJlZmVyZW5jZSBhbm90aGVyIHJlZiBsYXllclwiKSk6cz1qdChvLnR5cGUpOmUucHVzaChuZXcgRHQobixyLnJlZiwncmVmIGxheWVyIFwiJyt1KydcIiBub3QgZm91bmQnKSk7ZWxzZSBpZihcImJhY2tncm91bmRcIiE9PXMpaWYoci5zb3VyY2Upe3ZhciBoPWkuc291cmNlcyYmaS5zb3VyY2VzW3Iuc291cmNlXSxmPWgmJmp0KGgudHlwZSk7aD9cInZlY3RvclwiPT09ZiYmXCJyYXN0ZXJcIj09PXM/ZS5wdXNoKG5ldyBEdChuLHIuc291cmNlLCdsYXllciBcIicrci5pZCsnXCIgcmVxdWlyZXMgYSByYXN0ZXIgc291cmNlJykpOlwicmFzdGVyXCI9PT1mJiZcInJhc3RlclwiIT09cz9lLnB1c2gobmV3IER0KG4sci5zb3VyY2UsJ2xheWVyIFwiJytyLmlkKydcIiByZXF1aXJlcyBhIHZlY3RvciBzb3VyY2UnKSk6XCJ2ZWN0b3JcIiE9PWZ8fHJbXCJzb3VyY2UtbGF5ZXJcIl0/XCJyYXN0ZXItZGVtXCI9PT1mJiZcImhpbGxzaGFkZVwiIT09cz9lLnB1c2gobmV3IER0KG4sci5zb3VyY2UsXCJyYXN0ZXItZGVtIHNvdXJjZSBjYW4gb25seSBiZSB1c2VkIHdpdGggbGF5ZXIgdHlwZSAnaGlsbHNoYWRlJy5cIikpOlwibGluZVwiIT09c3x8IXIucGFpbnR8fCFyLnBhaW50W1wibGluZS1ncmFkaWVudFwiXXx8XCJnZW9qc29uXCI9PT1mJiZoLmxpbmVNZXRyaWNzfHxlLnB1c2gobmV3IER0KG4sciwnbGF5ZXIgXCInK3IuaWQrJ1wiIHNwZWNpZmllcyBhIGxpbmUtZ3JhZGllbnQsIHdoaWNoIHJlcXVpcmVzIGEgR2VvSlNPTiBzb3VyY2Ugd2l0aCBgbGluZU1ldHJpY3NgIGVuYWJsZWQuJykpOmUucHVzaChuZXcgRHQobixyLCdsYXllciBcIicrci5pZCsnXCIgbXVzdCBzcGVjaWZ5IGEgXCJzb3VyY2UtbGF5ZXJcIicpKTplLnB1c2gobmV3IER0KG4sci5zb3VyY2UsJ3NvdXJjZSBcIicrci5zb3VyY2UrJ1wiIG5vdCBmb3VuZCcpKTt9ZWxzZSBlLnB1c2gobmV3IER0KG4sciwnbWlzc2luZyByZXF1aXJlZCBwcm9wZXJ0eSBcInNvdXJjZVwiJykpO3JldHVybiBlPWUuY29uY2F0KFVyKHtrZXk6bix2YWx1ZTpyLHZhbHVlU3BlYzphLmxheWVyLHN0eWxlOnQuc3R5bGUsc3R5bGVTcGVjOnQuc3R5bGVTcGVjLG9iamVjdEVsZW1lbnRWYWxpZGF0b3JzOntcIipcIjpmdW5jdGlvbigpe3JldHVybiBbXX0sdHlwZTpmdW5jdGlvbigpe3JldHVybiBjbih7a2V5Om4rXCIudHlwZVwiLHZhbHVlOnIudHlwZSx2YWx1ZVNwZWM6YS5sYXllci50eXBlLHN0eWxlOnQuc3R5bGUsc3R5bGVTcGVjOnQuc3R5bGVTcGVjLG9iamVjdDpyLG9iamVjdEtleTpcInR5cGVcIn0pfSxmaWx0ZXI6ZW4sbGF5b3V0OmZ1bmN0aW9uKHQpe3JldHVybiBVcih7bGF5ZXI6cixrZXk6dC5rZXksdmFsdWU6dC52YWx1ZSxzdHlsZTp0LnN0eWxlLHN0eWxlU3BlYzp0LnN0eWxlU3BlYyxvYmplY3RFbGVtZW50VmFsaWRhdG9yczp7XCIqXCI6ZnVuY3Rpb24odCl7cmV0dXJuIGFuKFJ0KHtsYXllclR5cGU6c30sdCkpfX19KX0scGFpbnQ6ZnVuY3Rpb24odCl7cmV0dXJuIFVyKHtsYXllcjpyLGtleTp0LmtleSx2YWx1ZTp0LnZhbHVlLHN0eWxlOnQuc3R5bGUsc3R5bGVTcGVjOnQuc3R5bGVTcGVjLG9iamVjdEVsZW1lbnRWYWxpZGF0b3JzOntcIipcIjpmdW5jdGlvbih0KXtyZXR1cm4gbm4oUnQoe2xheWVyVHlwZTpzfSx0KSl9fX0pfX19KSl9ZnVuY3Rpb24gc24odCl7dmFyIGU9dC52YWx1ZSxyPXQua2V5LG49dC5zdHlsZVNwZWMsaT10LnN0eWxlO2lmKCFlLnR5cGUpcmV0dXJuIFtuZXcgRHQocixlLCdcInR5cGVcIiBpcyByZXF1aXJlZCcpXTt2YXIgYSxvPWp0KGUudHlwZSk7c3dpdGNoKG8pe2Nhc2VcInZlY3RvclwiOmNhc2VcInJhc3RlclwiOmNhc2VcInJhc3Rlci1kZW1cIjppZihhPVVyKHtrZXk6cix2YWx1ZTplLHZhbHVlU3BlYzpuW1wic291cmNlX1wiK28ucmVwbGFjZShcIi1cIixcIl9cIildLHN0eWxlOnQuc3R5bGUsc3R5bGVTcGVjOm59KSxcInVybFwiaW4gZSlmb3IodmFyIHMgaW4gZSlbXCJ0eXBlXCIsXCJ1cmxcIixcInRpbGVTaXplXCJdLmluZGV4T2Yocyk8MCYmYS5wdXNoKG5ldyBEdChyK1wiLlwiK3MsZVtzXSwnYSBzb3VyY2Ugd2l0aCBhIFwidXJsXCIgcHJvcGVydHkgbWF5IG5vdCBpbmNsdWRlIGEgXCInK3MrJ1wiIHByb3BlcnR5JykpO3JldHVybiBhO2Nhc2VcImdlb2pzb25cIjppZihhPVVyKHtrZXk6cix2YWx1ZTplLHZhbHVlU3BlYzpuLnNvdXJjZV9nZW9qc29uLHN0eWxlOmksc3R5bGVTcGVjOm59KSxlLmNsdXN0ZXIpZm9yKHZhciB1IGluIGUuY2x1c3RlclByb3BlcnRpZXMpe3ZhciBsPWUuY2x1c3RlclByb3BlcnRpZXNbdV0scD1sWzBdLGM9bFsxXSxoPVwic3RyaW5nXCI9PXR5cGVvZiBwP1twLFtcImFjY3VtdWxhdGVkXCJdLFtcImdldFwiLHVdXTpwO2EucHVzaC5hcHBseShhLFpyKHtrZXk6citcIi5cIit1K1wiLm1hcFwiLHZhbHVlOmMsZXhwcmVzc2lvbkNvbnRleHQ6XCJjbHVzdGVyLW1hcFwifSkpLGEucHVzaC5hcHBseShhLFpyKHtrZXk6citcIi5cIit1K1wiLnJlZHVjZVwiLHZhbHVlOmgsZXhwcmVzc2lvbkNvbnRleHQ6XCJjbHVzdGVyLXJlZHVjZVwifSkpO31yZXR1cm4gYTtjYXNlXCJ2aWRlb1wiOnJldHVybiBVcih7a2V5OnIsdmFsdWU6ZSx2YWx1ZVNwZWM6bi5zb3VyY2VfdmlkZW8sc3R5bGU6aSxzdHlsZVNwZWM6bn0pO2Nhc2VcImltYWdlXCI6cmV0dXJuIFVyKHtrZXk6cix2YWx1ZTplLHZhbHVlU3BlYzpuLnNvdXJjZV9pbWFnZSxzdHlsZTppLHN0eWxlU3BlYzpufSk7Y2FzZVwiY2FudmFzXCI6cmV0dXJuIFtuZXcgRHQocixudWxsLFwiUGxlYXNlIHVzZSBydW50aW1lIEFQSXMgdG8gYWRkIGNhbnZhcyBzb3VyY2VzLCByYXRoZXIgdGhhbiBpbmNsdWRpbmcgdGhlbSBpbiBzdHlsZXNoZWV0cy5cIixcInNvdXJjZS5jYW52YXNcIildO2RlZmF1bHQ6cmV0dXJuIEtyKHtrZXk6citcIi50eXBlXCIsdmFsdWU6ZS50eXBlLHZhbHVlU3BlYzp7dmFsdWVzOltcInZlY3RvclwiLFwicmFzdGVyXCIsXCJyYXN0ZXItZGVtXCIsXCJnZW9qc29uXCIsXCJ2aWRlb1wiLFwiaW1hZ2VcIl19LHN0eWxlOmksc3R5bGVTcGVjOm59KX19ZnVuY3Rpb24gdW4odCl7dmFyIGU9dC52YWx1ZSxyPXQuc3R5bGVTcGVjLG49ci5saWdodCxpPXQuc3R5bGUsYT1bXSxvPWtyKGUpO2lmKHZvaWQgMD09PWUpcmV0dXJuIGE7aWYoXCJvYmplY3RcIiE9PW8pcmV0dXJuIGE9YS5jb25jYXQoW25ldyBEdChcImxpZ2h0XCIsZSxcIm9iamVjdCBleHBlY3RlZCwgXCIrbytcIiBmb3VuZFwiKV0pO2Zvcih2YXIgcyBpbiBlKXt2YXIgdT1zLm1hdGNoKC9eKC4qKS10cmFuc2l0aW9uJC8pO2E9dSYmblt1WzFdXSYmblt1WzFdXS50cmFuc2l0aW9uP2EuY29uY2F0KGNuKHtrZXk6cyx2YWx1ZTplW3NdLHZhbHVlU3BlYzpyLnRyYW5zaXRpb24sc3R5bGU6aSxzdHlsZVNwZWM6cn0pKTpuW3NdP2EuY29uY2F0KGNuKHtrZXk6cyx2YWx1ZTplW3NdLHZhbHVlU3BlYzpuW3NdLHN0eWxlOmksc3R5bGVTcGVjOnJ9KSk6YS5jb25jYXQoW25ldyBEdChzLGVbc10sJ3Vua25vd24gcHJvcGVydHkgXCInK3MrJ1wiJyldKTt9cmV0dXJuIGF9ZnVuY3Rpb24gbG4odCl7dmFyIGU9dC52YWx1ZSxyPXQua2V5LG49a3IoZSk7cmV0dXJuIFwic3RyaW5nXCIhPT1uP1tuZXcgRHQocixlLFwic3RyaW5nIGV4cGVjdGVkLCBcIituK1wiIGZvdW5kXCIpXTpbXX12YXIgcG49e1wiKlwiOmZ1bmN0aW9uKCl7cmV0dXJuIFtdfSxhcnJheTpqcixib29sZWFuOmZ1bmN0aW9uKHQpe3ZhciBlPXQudmFsdWUscj10LmtleSxuPWtyKGUpO3JldHVybiBcImJvb2xlYW5cIiE9PW4/W25ldyBEdChyLGUsXCJib29sZWFuIGV4cGVjdGVkLCBcIituK1wiIGZvdW5kXCIpXTpbXX0sbnVtYmVyOnFyLGNvbG9yOmZ1bmN0aW9uKHQpe3ZhciBlPXQua2V5LHI9dC52YWx1ZSxuPWtyKHIpO3JldHVybiBcInN0cmluZ1wiIT09bj9bbmV3IER0KGUscixcImNvbG9yIGV4cGVjdGVkLCBcIituK1wiIGZvdW5kXCIpXTpudWxsPT09aWUocik/W25ldyBEdChlLHIsJ2NvbG9yIGV4cGVjdGVkLCBcIicrcisnXCIgZm91bmQnKV06W119LGNvbnN0YW50czpPdCxlbnVtOktyLGZpbHRlcjplbixmdW5jdGlvbjpOcixsYXllcjpvbixvYmplY3Q6VXIsc291cmNlOnNuLGxpZ2h0OnVuLHN0cmluZzpsbixmb3JtYXR0ZWQ6ZnVuY3Rpb24odCl7cmV0dXJuIDA9PT1sbih0KS5sZW5ndGg/W106WnIodCl9fTtmdW5jdGlvbiBjbih0KXt2YXIgZT10LnZhbHVlLHI9dC52YWx1ZVNwZWMsbj10LnN0eWxlU3BlYztyZXR1cm4gci5leHByZXNzaW9uJiZ6cihqdChlKSk/TnIodCk6ci5leHByZXNzaW9uJiZWcihxdChlKSk/WnIodCk6ci50eXBlJiZwbltyLnR5cGVdP3BuW3IudHlwZV0odCk6VXIoUnQoe30sdCx7dmFsdWVTcGVjOnIudHlwZT9uW3IudHlwZV06cn0pKX1mdW5jdGlvbiBobih0KXt2YXIgZT10LnZhbHVlLHI9dC5rZXksbj1sbih0KTtyZXR1cm4gbi5sZW5ndGg/bjooLTE9PT1lLmluZGV4T2YoXCJ7Zm9udHN0YWNrfVwiKSYmbi5wdXNoKG5ldyBEdChyLGUsJ1wiZ2x5cGhzXCIgdXJsIG11c3QgaW5jbHVkZSBhIFwie2ZvbnRzdGFja31cIiB0b2tlbicpKSwtMT09PWUuaW5kZXhPZihcIntyYW5nZX1cIikmJm4ucHVzaChuZXcgRHQocixlLCdcImdseXBoc1wiIHVybCBtdXN0IGluY2x1ZGUgYSBcIntyYW5nZX1cIiB0b2tlbicpKSxuKX1mdW5jdGlvbiBmbih0LGUpe2U9ZXx8THQ7dmFyIHI9W107cmV0dXJuIHI9ci5jb25jYXQoY24oe2tleTpcIlwiLHZhbHVlOnQsdmFsdWVTcGVjOmUuJHJvb3Qsc3R5bGVTcGVjOmUsc3R5bGU6dCxvYmplY3RFbGVtZW50VmFsaWRhdG9yczp7Z2x5cGhzOmhuLFwiKlwiOmZ1bmN0aW9uKCl7cmV0dXJuIFtdfX19KSksdC5jb25zdGFudHMmJihyPXIuY29uY2F0KE90KHtrZXk6XCJjb25zdGFudHNcIix2YWx1ZTp0LmNvbnN0YW50cyxzdHlsZTp0LHN0eWxlU3BlYzplfSkpKSx5bihyKX1mdW5jdGlvbiB5bih0KXtyZXR1cm4gW10uY29uY2F0KHQpLnNvcnQoZnVuY3Rpb24odCxlKXtyZXR1cm4gdC5saW5lLWUubGluZX0pfWZ1bmN0aW9uIGRuKHQpe3JldHVybiBmdW5jdGlvbigpe2Zvcih2YXIgZT1bXSxyPWFyZ3VtZW50cy5sZW5ndGg7ci0tOyllW3JdPWFyZ3VtZW50c1tyXTtyZXR1cm4geW4odC5hcHBseSh0aGlzLGUpKX19Zm4uc291cmNlPWRuKHNuKSxmbi5saWdodD1kbih1biksZm4ubGF5ZXI9ZG4ob24pLGZuLmZpbHRlcj1kbihlbiksZm4ucGFpbnRQcm9wZXJ0eT1kbihubiksZm4ubGF5b3V0UHJvcGVydHk9ZG4oYW4pO3ZhciBtbj1mbix2bj1tbi5saWdodCxnbj1tbi5wYWludFByb3BlcnR5LHhuPW1uLmxheW91dFByb3BlcnR5O2Z1bmN0aW9uIGJuKHQsZSl7dmFyIHI9ITE7aWYoZSYmZS5sZW5ndGgpZm9yKHZhciBuPTAsaT1lO248aS5sZW5ndGg7bis9MSl7dmFyIGE9aVtuXTt0LmZpcmUobmV3IFZ0KG5ldyBFcnJvcihhLm1lc3NhZ2UpKSkscj0hMDt9cmV0dXJuIHJ9dmFyIF9uPUFuLHduPTM7ZnVuY3Rpb24gQW4odCxlLHIpe3ZhciBuPXRoaXMuY2VsbHM9W107aWYodCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKXt0aGlzLmFycmF5QnVmZmVyPXQ7dmFyIGk9bmV3IEludDMyQXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7dD1pWzBdLGU9aVsxXSxyPWlbMl0sdGhpcy5kPWUrMipyO2Zvcih2YXIgYT0wO2E8dGhpcy5kKnRoaXMuZDthKyspe3ZhciBvPWlbd24rYV0scz1pW3duK2ErMV07bi5wdXNoKG89PT1zP251bGw6aS5zdWJhcnJheShvLHMpKTt9dmFyIHU9aVt3bituLmxlbmd0aF0sbD1pW3duK24ubGVuZ3RoKzFdO3RoaXMua2V5cz1pLnN1YmFycmF5KHUsbCksdGhpcy5iYm94ZXM9aS5zdWJhcnJheShsKSx0aGlzLmluc2VydD10aGlzLl9pbnNlcnRSZWFkb25seTt9ZWxzZXt0aGlzLmQ9ZSsyKnI7Zm9yKHZhciBwPTA7cDx0aGlzLmQqdGhpcy5kO3ArKyluLnB1c2goW10pO3RoaXMua2V5cz1bXSx0aGlzLmJib3hlcz1bXTt9dGhpcy5uPWUsdGhpcy5leHRlbnQ9dCx0aGlzLnBhZGRpbmc9cix0aGlzLnNjYWxlPWUvdCx0aGlzLnVpZD0wO3ZhciBjPXIvZSp0O3RoaXMubWluPS1jLHRoaXMubWF4PXQrYzt9QW4ucHJvdG90eXBlLmluc2VydD1mdW5jdGlvbih0LGUscixuLGkpe3RoaXMuX2ZvckVhY2hDZWxsKGUscixuLGksdGhpcy5faW5zZXJ0Q2VsbCx0aGlzLnVpZCsrKSx0aGlzLmtleXMucHVzaCh0KSx0aGlzLmJib3hlcy5wdXNoKGUpLHRoaXMuYmJveGVzLnB1c2gociksdGhpcy5iYm94ZXMucHVzaChuKSx0aGlzLmJib3hlcy5wdXNoKGkpO30sQW4ucHJvdG90eXBlLl9pbnNlcnRSZWFkb25seT1mdW5jdGlvbigpe3Rocm93XCJDYW5ub3QgaW5zZXJ0IGludG8gYSBHcmlkSW5kZXggY3JlYXRlZCBmcm9tIGFuIEFycmF5QnVmZmVyLlwifSxBbi5wcm90b3R5cGUuX2luc2VydENlbGw9ZnVuY3Rpb24odCxlLHIsbixpLGEpe3RoaXMuY2VsbHNbaV0ucHVzaChhKTt9LEFuLnByb3RvdHlwZS5xdWVyeT1mdW5jdGlvbih0LGUscixuLGkpe3ZhciBhPXRoaXMubWluLG89dGhpcy5tYXg7aWYodDw9YSYmZTw9YSYmbzw9ciYmbzw9biYmIWkpcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMua2V5cyk7dmFyIHM9W107cmV0dXJuIHRoaXMuX2ZvckVhY2hDZWxsKHQsZSxyLG4sdGhpcy5fcXVlcnlDZWxsLHMse30saSksc30sQW4ucHJvdG90eXBlLl9xdWVyeUNlbGw9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyxzKXt2YXIgdT10aGlzLmNlbGxzW2ldO2lmKG51bGwhPT11KWZvcih2YXIgbD10aGlzLmtleXMscD10aGlzLmJib3hlcyxjPTA7Yzx1Lmxlbmd0aDtjKyspe3ZhciBoPXVbY107aWYodm9pZCAwPT09b1toXSl7dmFyIGY9NCpoOyhzP3MocFtmKzBdLHBbZisxXSxwW2YrMl0scFtmKzNdKTp0PD1wW2YrMl0mJmU8PXBbZiszXSYmcj49cFtmKzBdJiZuPj1wW2YrMV0pPyhvW2hdPSEwLGEucHVzaChsW2hdKSk6b1toXT0hMTt9fX0sQW4ucHJvdG90eXBlLl9mb3JFYWNoQ2VsbD1mdW5jdGlvbih0LGUscixuLGksYSxvLHMpe2Zvcih2YXIgdT10aGlzLl9jb252ZXJ0VG9DZWxsQ29vcmQodCksbD10aGlzLl9jb252ZXJ0VG9DZWxsQ29vcmQoZSkscD10aGlzLl9jb252ZXJ0VG9DZWxsQ29vcmQociksYz10aGlzLl9jb252ZXJ0VG9DZWxsQ29vcmQobiksaD11O2g8PXA7aCsrKWZvcih2YXIgZj1sO2Y8PWM7ZisrKXt2YXIgeT10aGlzLmQqZitoO2lmKCghc3x8cyh0aGlzLl9jb252ZXJ0RnJvbUNlbGxDb29yZChoKSx0aGlzLl9jb252ZXJ0RnJvbUNlbGxDb29yZChmKSx0aGlzLl9jb252ZXJ0RnJvbUNlbGxDb29yZChoKzEpLHRoaXMuX2NvbnZlcnRGcm9tQ2VsbENvb3JkKGYrMSkpKSYmaS5jYWxsKHRoaXMsdCxlLHIsbix5LGEsbyxzKSlyZXR1cm59fSxBbi5wcm90b3R5cGUuX2NvbnZlcnRGcm9tQ2VsbENvb3JkPWZ1bmN0aW9uKHQpe3JldHVybiAodC10aGlzLnBhZGRpbmcpL3RoaXMuc2NhbGV9LEFuLnByb3RvdHlwZS5fY29udmVydFRvQ2VsbENvb3JkPWZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLm1heCgwLE1hdGgubWluKHRoaXMuZC0xLE1hdGguZmxvb3IodCp0aGlzLnNjYWxlKSt0aGlzLnBhZGRpbmcpKX0sQW4ucHJvdG90eXBlLnRvQXJyYXlCdWZmZXI9ZnVuY3Rpb24oKXtpZih0aGlzLmFycmF5QnVmZmVyKXJldHVybiB0aGlzLmFycmF5QnVmZmVyO2Zvcih2YXIgdD10aGlzLmNlbGxzLGU9d24rdGhpcy5jZWxscy5sZW5ndGgrMSsxLHI9MCxuPTA7bjx0aGlzLmNlbGxzLmxlbmd0aDtuKyspcis9dGhpcy5jZWxsc1tuXS5sZW5ndGg7dmFyIGk9bmV3IEludDMyQXJyYXkoZStyK3RoaXMua2V5cy5sZW5ndGgrdGhpcy5iYm94ZXMubGVuZ3RoKTtpWzBdPXRoaXMuZXh0ZW50LGlbMV09dGhpcy5uLGlbMl09dGhpcy5wYWRkaW5nO2Zvcih2YXIgYT1lLG89MDtvPHQubGVuZ3RoO28rKyl7dmFyIHM9dFtvXTtpW3duK29dPWEsaS5zZXQocyxhKSxhKz1zLmxlbmd0aDt9cmV0dXJuIGlbd24rdC5sZW5ndGhdPWEsaS5zZXQodGhpcy5rZXlzLGEpLGErPXRoaXMua2V5cy5sZW5ndGgsaVt3bit0Lmxlbmd0aCsxXT1hLGkuc2V0KHRoaXMuYmJveGVzLGEpLGErPXRoaXMuYmJveGVzLmxlbmd0aCxpLmJ1ZmZlcn07dmFyIFNuPXNlbGYuSW1hZ2VEYXRhLGtuPXt9O2Z1bmN0aW9uIHpuKHQsZSxyKXt2b2lkIDA9PT1yJiYocj17fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsXCJfY2xhc3NSZWdpc3RyeUtleVwiLHt2YWx1ZTp0LHdyaXRlYWJsZTohMX0pLGtuW3RdPXtrbGFzczplLG9taXQ6ci5vbWl0fHxbXSxzaGFsbG93OnIuc2hhbGxvd3x8W119O31mb3IodmFyIEluIGluIHpuKFwiT2JqZWN0XCIsT2JqZWN0KSxfbi5zZXJpYWxpemU9ZnVuY3Rpb24odCxlKXt2YXIgcj10LnRvQXJyYXlCdWZmZXIoKTtyZXR1cm4gZSYmZS5wdXNoKHIpLHtidWZmZXI6cn19LF9uLmRlc2VyaWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgX24odC5idWZmZXIpfSx6bihcIkdyaWRcIixfbiksem4oXCJDb2xvclwiLGFlKSx6bihcIkVycm9yXCIsRXJyb3IpLHpuKFwiU3R5bGVQcm9wZXJ0eUZ1bmN0aW9uXCIsUnIpLHpuKFwiU3R5bGVFeHByZXNzaW9uXCIsUHIse29taXQ6W1wiX2V2YWx1YXRvclwiXX0pLHpuKFwiWm9vbURlcGVuZGVudEV4cHJlc3Npb25cIixEciksem4oXCJab29tQ29uc3RhbnRFeHByZXNzaW9uXCIsTHIpLHpuKFwiQ29tcG91bmRFeHByZXNzaW9uXCIsX2Use29taXQ6W1wiX2V2YWx1YXRlXCJdfSksZHIpZHJbSW5dLl9jbGFzc1JlZ2lzdHJ5S2V5fHx6bihcIkV4cHJlc3Npb25fXCIrSW4sZHJbSW5dKTtmdW5jdGlvbiBCbih0LGUpe2lmKG51bGw9PXR8fFwiYm9vbGVhblwiPT10eXBlb2YgdHx8XCJudW1iZXJcIj09dHlwZW9mIHR8fFwic3RyaW5nXCI9PXR5cGVvZiB0fHx0IGluc3RhbmNlb2YgQm9vbGVhbnx8dCBpbnN0YW5jZW9mIE51bWJlcnx8dCBpbnN0YW5jZW9mIFN0cmluZ3x8dCBpbnN0YW5jZW9mIERhdGV8fHQgaW5zdGFuY2VvZiBSZWdFeHApcmV0dXJuIHQ7aWYodCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKXJldHVybiBlJiZlLnB1c2godCksdDtpZihBcnJheUJ1ZmZlci5pc1ZpZXcodCkpe3ZhciByPXQ7cmV0dXJuIGUmJmUucHVzaChyLmJ1ZmZlcikscn1pZih0IGluc3RhbmNlb2YgU24pcmV0dXJuIGUmJmUucHVzaCh0LmRhdGEuYnVmZmVyKSx0O2lmKEFycmF5LmlzQXJyYXkodCkpe2Zvcih2YXIgbj1bXSxpPTAsYT10O2k8YS5sZW5ndGg7aSs9MSl7dmFyIG89YVtpXTtuLnB1c2goQm4obyxlKSk7fXJldHVybiBufWlmKFwib2JqZWN0XCI9PXR5cGVvZiB0KXt2YXIgcz10LmNvbnN0cnVjdG9yLHU9cy5fY2xhc3NSZWdpc3RyeUtleTtpZighdSl0aHJvdyBuZXcgRXJyb3IoXCJjYW4ndCBzZXJpYWxpemUgb2JqZWN0IG9mIHVucmVnaXN0ZXJlZCBjbGFzc1wiKTt2YXIgbD1zLnNlcmlhbGl6ZT9zLnNlcmlhbGl6ZSh0LGUpOnt9O2lmKCFzLnNlcmlhbGl6ZSl7Zm9yKHZhciBwIGluIHQpaWYodC5oYXNPd25Qcm9wZXJ0eShwKSYmIShrblt1XS5vbWl0LmluZGV4T2YocCk+PTApKXt2YXIgYz10W3BdO2xbcF09a25bdV0uc2hhbGxvdy5pbmRleE9mKHApPj0wP2M6Qm4oYyxlKTt9dCBpbnN0YW5jZW9mIEVycm9yJiYobC5tZXNzYWdlPXQubWVzc2FnZSk7fWlmKGwuJG5hbWUpdGhyb3cgbmV3IEVycm9yKFwiJG5hbWUgcHJvcGVydHkgaXMgcmVzZXJ2ZWQgZm9yIHdvcmtlciBzZXJpYWxpemF0aW9uIGxvZ2ljLlwiKTtyZXR1cm4gXCJPYmplY3RcIiE9PXUmJihsLiRuYW1lPXUpLGx9dGhyb3cgbmV3IEVycm9yKFwiY2FuJ3Qgc2VyaWFsaXplIG9iamVjdCBvZiB0eXBlIFwiK3R5cGVvZiB0KX1mdW5jdGlvbiBDbih0KXtpZihudWxsPT10fHxcImJvb2xlYW5cIj09dHlwZW9mIHR8fFwibnVtYmVyXCI9PXR5cGVvZiB0fHxcInN0cmluZ1wiPT10eXBlb2YgdHx8dCBpbnN0YW5jZW9mIEJvb2xlYW58fHQgaW5zdGFuY2VvZiBOdW1iZXJ8fHQgaW5zdGFuY2VvZiBTdHJpbmd8fHQgaW5zdGFuY2VvZiBEYXRlfHx0IGluc3RhbmNlb2YgUmVnRXhwfHx0IGluc3RhbmNlb2YgQXJyYXlCdWZmZXJ8fEFycmF5QnVmZmVyLmlzVmlldyh0KXx8dCBpbnN0YW5jZW9mIFNuKXJldHVybiB0O2lmKEFycmF5LmlzQXJyYXkodCkpcmV0dXJuIHQubWFwKENuKTtpZihcIm9iamVjdFwiPT10eXBlb2YgdCl7dmFyIGU9dC4kbmFtZXx8XCJPYmplY3RcIixyPWtuW2VdLmtsYXNzO2lmKCFyKXRocm93IG5ldyBFcnJvcihcImNhbid0IGRlc2VyaWFsaXplIHVucmVnaXN0ZXJlZCBjbGFzcyBcIitlKTtpZihyLmRlc2VyaWFsaXplKXJldHVybiByLmRlc2VyaWFsaXplKHQpO2Zvcih2YXIgbj1PYmplY3QuY3JlYXRlKHIucHJvdG90eXBlKSxpPTAsYT1PYmplY3Qua2V5cyh0KTtpPGEubGVuZ3RoO2krPTEpe3ZhciBvPWFbaV07aWYoXCIkbmFtZVwiIT09byl7dmFyIHM9dFtvXTtuW29dPWtuW2VdLnNoYWxsb3cuaW5kZXhPZihvKT49MD9zOkNuKHMpO319cmV0dXJuIG59dGhyb3cgbmV3IEVycm9yKFwiY2FuJ3QgZGVzZXJpYWxpemUgb2JqZWN0IG9mIHR5cGUgXCIrdHlwZW9mIHQpfXZhciBFbj1mdW5jdGlvbigpe3RoaXMuZmlyc3Q9ITA7fTtFbi5wcm90b3R5cGUudXBkYXRlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9TWF0aC5mbG9vcih0KTtyZXR1cm4gdGhpcy5maXJzdD8odGhpcy5maXJzdD0hMSx0aGlzLmxhc3RJbnRlZ2VyWm9vbT1yLHRoaXMubGFzdEludGVnZXJab29tVGltZT0wLHRoaXMubGFzdFpvb209dCx0aGlzLmxhc3RGbG9vclpvb209ciwhMCk6KHRoaXMubGFzdEZsb29yWm9vbT5yPyh0aGlzLmxhc3RJbnRlZ2VyWm9vbT1yKzEsdGhpcy5sYXN0SW50ZWdlclpvb21UaW1lPWUpOnRoaXMubGFzdEZsb29yWm9vbTxyJiYodGhpcy5sYXN0SW50ZWdlclpvb209cix0aGlzLmxhc3RJbnRlZ2VyWm9vbVRpbWU9ZSksdCE9PXRoaXMubGFzdFpvb20mJih0aGlzLmxhc3Rab29tPXQsdGhpcy5sYXN0Rmxvb3Jab29tPXIsITApKX07dmFyIE1uPXtcIkxhdGluLTEgU3VwcGxlbWVudFwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjgmJnQ8PTI1NX0sQXJhYmljOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xNTM2JiZ0PD0xNzkxfSxcIkFyYWJpYyBTdXBwbGVtZW50XCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTE4NzImJnQ8PTE5MTl9LFwiQXJhYmljIEV4dGVuZGVkLUFcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MjIwOCYmdDw9MjMwM30sXCJIYW5ndWwgSmFtb1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj00MzUyJiZ0PD00NjA3fSxcIlVuaWZpZWQgQ2FuYWRpYW4gQWJvcmlnaW5hbCBTeWxsYWJpY3NcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49NTEyMCYmdDw9NTc1OX0sS2htZXI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTYwMTYmJnQ8PTYxNDN9LFwiVW5pZmllZCBDYW5hZGlhbiBBYm9yaWdpbmFsIFN5bGxhYmljcyBFeHRlbmRlZFwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj02MzIwJiZ0PD02Mzk5fSxcIkdlbmVyYWwgUHVuY3R1YXRpb25cIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49ODE5MiYmdDw9ODMwM30sXCJMZXR0ZXJsaWtlIFN5bWJvbHNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49ODQ0OCYmdDw9ODUyN30sXCJOdW1iZXIgRm9ybXNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49ODUyOCYmdDw9ODU5MX0sXCJNaXNjZWxsYW5lb3VzIFRlY2huaWNhbFwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj04OTYwJiZ0PD05MjE1fSxcIkNvbnRyb2wgUGljdHVyZXNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49OTIxNiYmdDw9OTI3OX0sXCJPcHRpY2FsIENoYXJhY3RlciBSZWNvZ25pdGlvblwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj05MjgwJiZ0PD05MzExfSxcIkVuY2xvc2VkIEFscGhhbnVtZXJpY3NcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49OTMxMiYmdDw9OTQ3MX0sXCJHZW9tZXRyaWMgU2hhcGVzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTk2MzImJnQ8PTk3Mjd9LFwiTWlzY2VsbGFuZW91cyBTeW1ib2xzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTk3MjgmJnQ8PTk5ODN9LFwiTWlzY2VsbGFuZW91cyBTeW1ib2xzIGFuZCBBcnJvd3NcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTEwMDgmJnQ8PTExMjYzfSxcIkNKSyBSYWRpY2FscyBTdXBwbGVtZW50XCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTExOTA0JiZ0PD0xMjAzMX0sXCJLYW5neGkgUmFkaWNhbHNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTIwMzImJnQ8PTEyMjU1fSxcIklkZW9ncmFwaGljIERlc2NyaXB0aW9uIENoYXJhY3RlcnNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTIyNzImJnQ8PTEyMjg3fSxcIkNKSyBTeW1ib2xzIGFuZCBQdW5jdHVhdGlvblwiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjI4OCYmdDw9MTIzNTF9LEhpcmFnYW5hOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjM1MiYmdDw9MTI0NDd9LEthdGFrYW5hOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjQ0OCYmdDw9MTI1NDN9LEJvcG9tb2ZvOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjU0NCYmdDw9MTI1OTF9LFwiSGFuZ3VsIENvbXBhdGliaWxpdHkgSmFtb1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjU5MiYmdDw9MTI2ODd9LEthbmJ1bjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTI2ODgmJnQ8PTEyNzAzfSxcIkJvcG9tb2ZvIEV4dGVuZGVkXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTEyNzA0JiZ0PD0xMjczNX0sXCJDSksgU3Ryb2tlc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjczNiYmdDw9MTI3ODN9LFwiS2F0YWthbmEgUGhvbmV0aWMgRXh0ZW5zaW9uc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjc4NCYmdDw9MTI3OTl9LFwiRW5jbG9zZWQgQ0pLIExldHRlcnMgYW5kIE1vbnRoc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj0xMjgwMCYmdDw9MTMwNTV9LFwiQ0pLIENvbXBhdGliaWxpdHlcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTMwNTYmJnQ8PTEzMzExfSxcIkNKSyBVbmlmaWVkIElkZW9ncmFwaHMgRXh0ZW5zaW9uIEFcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49MTMzMTImJnQ8PTE5OTAzfSxcIllpamluZyBIZXhhZ3JhbSBTeW1ib2xzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTE5OTA0JiZ0PD0xOTk2N30sXCJDSksgVW5pZmllZCBJZGVvZ3JhcGhzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTE5OTY4JiZ0PD00MDk1OX0sXCJZaSBTeWxsYWJsZXNcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49NDA5NjAmJnQ8PTQyMTI3fSxcIllpIFJhZGljYWxzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTQyMTI4JiZ0PD00MjE5MX0sXCJIYW5ndWwgSmFtbyBFeHRlbmRlZC1BXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTQzMzYwJiZ0PD00MzM5MX0sXCJIYW5ndWwgU3lsbGFibGVzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTQ0MDMyJiZ0PD01NTIxNX0sXCJIYW5ndWwgSmFtbyBFeHRlbmRlZC1CXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTU1MjE2JiZ0PD01NTI5NX0sXCJQcml2YXRlIFVzZSBBcmVhXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTU3MzQ0JiZ0PD02Mzc0M30sXCJDSksgQ29tcGF0aWJpbGl0eSBJZGVvZ3JhcGhzXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTYzNzQ0JiZ0PD02NDI1NX0sXCJBcmFiaWMgUHJlc2VudGF0aW9uIEZvcm1zLUFcIjpmdW5jdGlvbih0KXtyZXR1cm4gdD49NjQzMzYmJnQ8PTY1MDIzfSxcIlZlcnRpY2FsIEZvcm1zXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTY1MDQwJiZ0PD02NTA1NX0sXCJDSksgQ29tcGF0aWJpbGl0eSBGb3Jtc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj02NTA3MiYmdDw9NjUxMDN9LFwiU21hbGwgRm9ybSBWYXJpYW50c1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj02NTEwNCYmdDw9NjUxMzV9LFwiQXJhYmljIFByZXNlbnRhdGlvbiBGb3Jtcy1CXCI6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTY1MTM2JiZ0PD02NTI3OX0sXCJIYWxmd2lkdGggYW5kIEZ1bGx3aWR0aCBGb3Jtc1wiOmZ1bmN0aW9uKHQpe3JldHVybiB0Pj02NTI4MCYmdDw9NjU1MTl9fTtmdW5jdGlvbiBUbih0KXtmb3IodmFyIGU9MCxyPXQ7ZTxyLmxlbmd0aDtlKz0xKXtpZihGbihyW2VdLmNoYXJDb2RlQXQoMCkpKXJldHVybiAhMH1yZXR1cm4gITF9ZnVuY3Rpb24gUG4odCl7Zm9yKHZhciBlPTAscj10O2U8ci5sZW5ndGg7ZSs9MSl7aWYoIVZuKHJbZV0uY2hhckNvZGVBdCgwKSkpcmV0dXJuICExfXJldHVybiAhMH1mdW5jdGlvbiBWbih0KXtyZXR1cm4gIU1uLkFyYWJpYyh0KSYmKCFNbltcIkFyYWJpYyBTdXBwbGVtZW50XCJdKHQpJiYoIU1uW1wiQXJhYmljIEV4dGVuZGVkLUFcIl0odCkmJighTW5bXCJBcmFiaWMgUHJlc2VudGF0aW9uIEZvcm1zLUFcIl0odCkmJiFNbltcIkFyYWJpYyBQcmVzZW50YXRpb24gRm9ybXMtQlwiXSh0KSkpKX1mdW5jdGlvbiBGbih0KXtyZXR1cm4gNzQ2PT09dHx8NzQ3PT09dHx8ISh0PDQzNTIpJiYoISFNbltcIkJvcG9tb2ZvIEV4dGVuZGVkXCJdKHQpfHwoISFNbi5Cb3BvbW9mbyh0KXx8KCEoIU1uW1wiQ0pLIENvbXBhdGliaWxpdHkgRm9ybXNcIl0odCl8fHQ+PTY1MDk3JiZ0PD02NTEwMyl8fCghIU1uW1wiQ0pLIENvbXBhdGliaWxpdHkgSWRlb2dyYXBoc1wiXSh0KXx8KCEhTW5bXCJDSksgQ29tcGF0aWJpbGl0eVwiXSh0KXx8KCEhTW5bXCJDSksgUmFkaWNhbHMgU3VwcGxlbWVudFwiXSh0KXx8KCEhTW5bXCJDSksgU3Ryb2tlc1wiXSh0KXx8KCEoIU1uW1wiQ0pLIFN5bWJvbHMgYW5kIFB1bmN0dWF0aW9uXCJdKHQpfHx0Pj0xMjI5NiYmdDw9MTIzMDV8fHQ+PTEyMzA4JiZ0PD0xMjMxOXx8MTIzMzY9PT10KXx8KCEhTW5bXCJDSksgVW5pZmllZCBJZGVvZ3JhcGhzIEV4dGVuc2lvbiBBXCJdKHQpfHwoISFNbltcIkNKSyBVbmlmaWVkIElkZW9ncmFwaHNcIl0odCl8fCghIU1uW1wiRW5jbG9zZWQgQ0pLIExldHRlcnMgYW5kIE1vbnRoc1wiXSh0KXx8KCEhTW5bXCJIYW5ndWwgQ29tcGF0aWJpbGl0eSBKYW1vXCJdKHQpfHwoISFNbltcIkhhbmd1bCBKYW1vIEV4dGVuZGVkLUFcIl0odCl8fCghIU1uW1wiSGFuZ3VsIEphbW8gRXh0ZW5kZWQtQlwiXSh0KXx8KCEhTW5bXCJIYW5ndWwgSmFtb1wiXSh0KXx8KCEhTW5bXCJIYW5ndWwgU3lsbGFibGVzXCJdKHQpfHwoISFNbi5IaXJhZ2FuYSh0KXx8KCEhTW5bXCJJZGVvZ3JhcGhpYyBEZXNjcmlwdGlvbiBDaGFyYWN0ZXJzXCJdKHQpfHwoISFNbi5LYW5idW4odCl8fCghIU1uW1wiS2FuZ3hpIFJhZGljYWxzXCJdKHQpfHwoISFNbltcIkthdGFrYW5hIFBob25ldGljIEV4dGVuc2lvbnNcIl0odCl8fCghKCFNbi5LYXRha2FuYSh0KXx8MTI1NDA9PT10KXx8KCEoIU1uW1wiSGFsZndpZHRoIGFuZCBGdWxsd2lkdGggRm9ybXNcIl0odCl8fDY1Mjg4PT09dHx8NjUyODk9PT10fHw2NTI5Mz09PXR8fHQ+PTY1MzA2JiZ0PD02NTMxMHx8NjUzMzk9PT10fHw2NTM0MT09PXR8fDY1MzQzPT09dHx8dD49NjUzNzEmJnQ8PTY1NTAzfHw2NTUwNz09PXR8fHQ+PTY1NTEyJiZ0PD02NTUxOSl8fCghKCFNbltcIlNtYWxsIEZvcm0gVmFyaWFudHNcIl0odCl8fHQ+PTY1MTEyJiZ0PD02NTExOHx8dD49NjUxMjMmJnQ8PTY1MTI2KXx8KCEhTW5bXCJVbmlmaWVkIENhbmFkaWFuIEFib3JpZ2luYWwgU3lsbGFiaWNzXCJdKHQpfHwoISFNbltcIlVuaWZpZWQgQ2FuYWRpYW4gQWJvcmlnaW5hbCBTeWxsYWJpY3MgRXh0ZW5kZWRcIl0odCl8fCghIU1uW1wiVmVydGljYWwgRm9ybXNcIl0odCl8fCghIU1uW1wiWWlqaW5nIEhleGFncmFtIFN5bWJvbHNcIl0odCl8fCghIU1uW1wiWWkgU3lsbGFibGVzXCJdKHQpfHwhIU1uW1wiWWkgUmFkaWNhbHNcIl0odCkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKX1mdW5jdGlvbiBMbih0KXtyZXR1cm4gIShGbih0KXx8ZnVuY3Rpb24odCl7cmV0dXJuICEhKE1uW1wiTGF0aW4tMSBTdXBwbGVtZW50XCJdKHQpJiYoMTY3PT09dHx8MTY5PT09dHx8MTc0PT09dHx8MTc3PT09dHx8MTg4PT09dHx8MTg5PT09dHx8MTkwPT09dHx8MjE1PT09dHx8MjQ3PT09dCl8fE1uW1wiR2VuZXJhbCBQdW5jdHVhdGlvblwiXSh0KSYmKDgyMTQ9PT10fHw4MjI0PT09dHx8ODIyNT09PXR8fDgyNDA9PT10fHw4MjQxPT09dHx8ODI1MT09PXR8fDgyNTI9PT10fHw4MjU4PT09dHx8ODI2Mz09PXR8fDgyNjQ9PT10fHw4MjY1PT09dHx8ODI3Mz09PXQpfHxNbltcIkxldHRlcmxpa2UgU3ltYm9sc1wiXSh0KXx8TW5bXCJOdW1iZXIgRm9ybXNcIl0odCl8fE1uW1wiTWlzY2VsbGFuZW91cyBUZWNobmljYWxcIl0odCkmJih0Pj04OTYwJiZ0PD04OTY3fHx0Pj04OTcyJiZ0PD04OTkxfHx0Pj04OTk2JiZ0PD05ZTN8fDkwMDM9PT10fHx0Pj05MDg1JiZ0PD05MTE0fHx0Pj05MTUwJiZ0PD05MTY1fHw5MTY3PT09dHx8dD49OTE2OSYmdDw9OTE3OXx8dD49OTE4NiYmdDw9OTIxNSl8fE1uW1wiQ29udHJvbCBQaWN0dXJlc1wiXSh0KSYmOTI1MSE9PXR8fE1uW1wiT3B0aWNhbCBDaGFyYWN0ZXIgUmVjb2duaXRpb25cIl0odCl8fE1uW1wiRW5jbG9zZWQgQWxwaGFudW1lcmljc1wiXSh0KXx8TW5bXCJHZW9tZXRyaWMgU2hhcGVzXCJdKHQpfHxNbltcIk1pc2NlbGxhbmVvdXMgU3ltYm9sc1wiXSh0KSYmISh0Pj05NzU0JiZ0PD05NzU5KXx8TW5bXCJNaXNjZWxsYW5lb3VzIFN5bWJvbHMgYW5kIEFycm93c1wiXSh0KSYmKHQ+PTExMDI2JiZ0PD0xMTA1NXx8dD49MTEwODgmJnQ8PTExMDk3fHx0Pj0xMTE5MiYmdDw9MTEyNDMpfHxNbltcIkNKSyBTeW1ib2xzIGFuZCBQdW5jdHVhdGlvblwiXSh0KXx8TW4uS2F0YWthbmEodCl8fE1uW1wiUHJpdmF0ZSBVc2UgQXJlYVwiXSh0KXx8TW5bXCJDSksgQ29tcGF0aWJpbGl0eSBGb3Jtc1wiXSh0KXx8TW5bXCJTbWFsbCBGb3JtIFZhcmlhbnRzXCJdKHQpfHxNbltcIkhhbGZ3aWR0aCBhbmQgRnVsbHdpZHRoIEZvcm1zXCJdKHQpfHw4NzM0PT09dHx8ODc1Nj09PXR8fDg3NTc9PT10fHx0Pj05OTg0JiZ0PD0xMDA4N3x8dD49MTAxMDImJnQ8PTEwMTMxfHw2NTUzMj09PXR8fDY1NTMzPT09dCl9KHQpKX1mdW5jdGlvbiBEbih0LGUpe3JldHVybiAhKCFlJiYodD49MTQyNCYmdDw9MjMwM3x8TW5bXCJBcmFiaWMgUHJlc2VudGF0aW9uIEZvcm1zLUFcIl0odCl8fE1uW1wiQXJhYmljIFByZXNlbnRhdGlvbiBGb3Jtcy1CXCJdKHQpKSkmJiEodD49MjMwNCYmdDw9MzU4M3x8dD49Mzg0MCYmdDw9NDI1NXx8TW4uS2htZXIodCkpfXZhciBPbixSbj0hMSxVbj1udWxsLGpuPSExLHFuPW5ldyBGdCxObj17YXBwbHlBcmFiaWNTaGFwaW5nOm51bGwscHJvY2Vzc0JpZGlyZWN0aW9uYWxUZXh0Om51bGwscHJvY2Vzc1N0eWxlZEJpZGlyZWN0aW9uYWxUZXh0Om51bGwsaXNMb2FkZWQ6ZnVuY3Rpb24oKXtyZXR1cm4gam58fG51bGwhPU5uLmFwcGx5QXJhYmljU2hhcGluZ319LFpuPWZ1bmN0aW9uKHQsZSl7dGhpcy56b29tPXQsZT8odGhpcy5ub3c9ZS5ub3csdGhpcy5mYWRlRHVyYXRpb249ZS5mYWRlRHVyYXRpb24sdGhpcy56b29tSGlzdG9yeT1lLnpvb21IaXN0b3J5LHRoaXMudHJhbnNpdGlvbj1lLnRyYW5zaXRpb24pOih0aGlzLm5vdz0wLHRoaXMuZmFkZUR1cmF0aW9uPTAsdGhpcy56b29tSGlzdG9yeT1uZXcgRW4sdGhpcy50cmFuc2l0aW9uPXt9KTt9O1puLnByb3RvdHlwZS5pc1N1cHBvcnRlZFNjcmlwdD1mdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9MCxuPXQ7cjxuLmxlbmd0aDtyKz0xKWlmKCFEbihuW3JdLmNoYXJDb2RlQXQoMCksZSkpcmV0dXJuICExO3JldHVybiAhMH0odCxObi5pc0xvYWRlZCgpKX0sWm4ucHJvdG90eXBlLmNyb3NzRmFkaW5nRmFjdG9yPWZ1bmN0aW9uKCl7cmV0dXJuIDA9PT10aGlzLmZhZGVEdXJhdGlvbj8xOk1hdGgubWluKCh0aGlzLm5vdy10aGlzLnpvb21IaXN0b3J5Lmxhc3RJbnRlZ2VyWm9vbVRpbWUpL3RoaXMuZmFkZUR1cmF0aW9uLDEpfSxabi5wcm90b3R5cGUuZ2V0Q3Jvc3NmYWRlUGFyYW1ldGVycz1mdW5jdGlvbigpe3ZhciB0PXRoaXMuem9vbSxlPXQtTWF0aC5mbG9vcih0KSxyPXRoaXMuY3Jvc3NGYWRpbmdGYWN0b3IoKTtyZXR1cm4gdD50aGlzLnpvb21IaXN0b3J5Lmxhc3RJbnRlZ2VyWm9vbT97ZnJvbVNjYWxlOjIsdG9TY2FsZToxLHQ6ZSsoMS1lKSpyfTp7ZnJvbVNjYWxlOi41LHRvU2NhbGU6MSx0OjEtKDEtcikqZX19O3ZhciBLbj1mdW5jdGlvbih0LGUpe3RoaXMucHJvcGVydHk9dCx0aGlzLnZhbHVlPWUsdGhpcy5leHByZXNzaW9uPWZ1bmN0aW9uKHQsZSl7aWYoenIodCkpcmV0dXJuIG5ldyBScih0LGUpO2lmKFZyKHQpKXt2YXIgcj1Pcih0LGUpO2lmKFwiZXJyb3JcIj09PXIucmVzdWx0KXRocm93IG5ldyBFcnJvcihyLnZhbHVlLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC5rZXkrXCI6IFwiK3QubWVzc2FnZX0pLmpvaW4oXCIsIFwiKSk7cmV0dXJuIHIudmFsdWV9dmFyIG49dDtyZXR1cm4gXCJzdHJpbmdcIj09dHlwZW9mIHQmJlwiY29sb3JcIj09PWUudHlwZSYmKG49YWUucGFyc2UodCkpLHtraW5kOlwiY29uc3RhbnRcIixldmFsdWF0ZTpmdW5jdGlvbigpe3JldHVybiBufX19KHZvaWQgMD09PWU/dC5zcGVjaWZpY2F0aW9uLmRlZmF1bHQ6ZSx0LnNwZWNpZmljYXRpb24pO307S24ucHJvdG90eXBlLmlzRGF0YURyaXZlbj1mdW5jdGlvbigpe3JldHVybiBcInNvdXJjZVwiPT09dGhpcy5leHByZXNzaW9uLmtpbmR8fFwiY29tcG9zaXRlXCI9PT10aGlzLmV4cHJlc3Npb24ua2luZH0sS24ucHJvdG90eXBlLnBvc3NpYmx5RXZhbHVhdGU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMucHJvcGVydHkucG9zc2libHlFdmFsdWF0ZSh0aGlzLHQpfTt2YXIgR249ZnVuY3Rpb24odCl7dGhpcy5wcm9wZXJ0eT10LHRoaXMudmFsdWU9bmV3IEtuKHQsdm9pZCAwKTt9O0duLnByb3RvdHlwZS50cmFuc2l0aW9uZWQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gbmV3IEpuKHRoaXMucHJvcGVydHksdGhpcy52YWx1ZSxlLGMoe30sdC50cmFuc2l0aW9uLHRoaXMudHJhbnNpdGlvbiksdC5ub3cpfSxHbi5wcm90b3R5cGUudW50cmFuc2l0aW9uZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEpuKHRoaXMucHJvcGVydHksdGhpcy52YWx1ZSxudWxsLHt9LDApfTt2YXIgWG49ZnVuY3Rpb24odCl7dGhpcy5fcHJvcGVydGllcz10LHRoaXMuX3ZhbHVlcz1PYmplY3QuY3JlYXRlKHQuZGVmYXVsdFRyYW5zaXRpb25hYmxlUHJvcGVydHlWYWx1ZXMpO307WG4ucHJvdG90eXBlLmdldFZhbHVlPWZ1bmN0aW9uKHQpe3JldHVybiBiKHRoaXMuX3ZhbHVlc1t0XS52YWx1ZS52YWx1ZSl9LFhuLnByb3RvdHlwZS5zZXRWYWx1ZT1mdW5jdGlvbih0LGUpe3RoaXMuX3ZhbHVlcy5oYXNPd25Qcm9wZXJ0eSh0KXx8KHRoaXMuX3ZhbHVlc1t0XT1uZXcgR24odGhpcy5fdmFsdWVzW3RdLnByb3BlcnR5KSksdGhpcy5fdmFsdWVzW3RdLnZhbHVlPW5ldyBLbih0aGlzLl92YWx1ZXNbdF0ucHJvcGVydHksbnVsbD09PWU/dm9pZCAwOmIoZSkpO30sWG4ucHJvdG90eXBlLmdldFRyYW5zaXRpb249ZnVuY3Rpb24odCl7cmV0dXJuIGIodGhpcy5fdmFsdWVzW3RdLnRyYW5zaXRpb24pfSxYbi5wcm90b3R5cGUuc2V0VHJhbnNpdGlvbj1mdW5jdGlvbih0LGUpe3RoaXMuX3ZhbHVlcy5oYXNPd25Qcm9wZXJ0eSh0KXx8KHRoaXMuX3ZhbHVlc1t0XT1uZXcgR24odGhpcy5fdmFsdWVzW3RdLnByb3BlcnR5KSksdGhpcy5fdmFsdWVzW3RdLnRyYW5zaXRpb249YihlKXx8dm9pZCAwO30sWG4ucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe2Zvcih2YXIgdD17fSxlPTAscj1PYmplY3Qua2V5cyh0aGlzLl92YWx1ZXMpO2U8ci5sZW5ndGg7ZSs9MSl7dmFyIG49cltlXSxpPXRoaXMuZ2V0VmFsdWUobik7dm9pZCAwIT09aSYmKHRbbl09aSk7dmFyIGE9dGhpcy5nZXRUcmFuc2l0aW9uKG4pO3ZvaWQgMCE9PWEmJih0W24rXCItdHJhbnNpdGlvblwiXT1hKTt9cmV0dXJuIHR9LFhuLnByb3RvdHlwZS50cmFuc2l0aW9uZWQ9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9bmV3IEhuKHRoaXMuX3Byb3BlcnRpZXMpLG49MCxpPU9iamVjdC5rZXlzKHRoaXMuX3ZhbHVlcyk7bjxpLmxlbmd0aDtuKz0xKXt2YXIgYT1pW25dO3IuX3ZhbHVlc1thXT10aGlzLl92YWx1ZXNbYV0udHJhbnNpdGlvbmVkKHQsZS5fdmFsdWVzW2FdKTt9cmV0dXJuIHJ9LFhuLnByb3RvdHlwZS51bnRyYW5zaXRpb25lZD1mdW5jdGlvbigpe2Zvcih2YXIgdD1uZXcgSG4odGhpcy5fcHJvcGVydGllcyksZT0wLHI9T2JqZWN0LmtleXModGhpcy5fdmFsdWVzKTtlPHIubGVuZ3RoO2UrPTEpe3ZhciBuPXJbZV07dC5fdmFsdWVzW25dPXRoaXMuX3ZhbHVlc1tuXS51bnRyYW5zaXRpb25lZCgpO31yZXR1cm4gdH07dmFyIEpuPWZ1bmN0aW9uKHQsZSxyLG4saSl7dGhpcy5wcm9wZXJ0eT10LHRoaXMudmFsdWU9ZSx0aGlzLmJlZ2luPWkrbi5kZWxheXx8MCx0aGlzLmVuZD10aGlzLmJlZ2luK24uZHVyYXRpb258fDAsdC5zcGVjaWZpY2F0aW9uLnRyYW5zaXRpb24mJihuLmRlbGF5fHxuLmR1cmF0aW9uKSYmKHRoaXMucHJpb3I9cik7fTtKbi5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbih0KXt2YXIgZT10Lm5vd3x8MCxyPXRoaXMudmFsdWUucG9zc2libHlFdmFsdWF0ZSh0KSxuPXRoaXMucHJpb3I7aWYobil7aWYoZT50aGlzLmVuZClyZXR1cm4gdGhpcy5wcmlvcj1udWxsLHI7aWYodGhpcy52YWx1ZS5pc0RhdGFEcml2ZW4oKSlyZXR1cm4gdGhpcy5wcmlvcj1udWxsLHI7aWYoZTx0aGlzLmJlZ2luKXJldHVybiBuLnBvc3NpYmx5RXZhbHVhdGUodCk7dmFyIGk9KGUtdGhpcy5iZWdpbikvKHRoaXMuZW5kLXRoaXMuYmVnaW4pO3JldHVybiB0aGlzLnByb3BlcnR5LmludGVycG9sYXRlKG4ucG9zc2libHlFdmFsdWF0ZSh0KSxyLGZ1bmN0aW9uKHQpe2lmKHQ8PTApcmV0dXJuIDA7aWYodD49MSlyZXR1cm4gMTt2YXIgZT10KnQscj1lKnQ7cmV0dXJuIDQqKHQ8LjU/cjozKih0LWUpK3ItLjc1KX0oaSkpfXJldHVybiByfTt2YXIgSG49ZnVuY3Rpb24odCl7dGhpcy5fcHJvcGVydGllcz10LHRoaXMuX3ZhbHVlcz1PYmplY3QuY3JlYXRlKHQuZGVmYXVsdFRyYW5zaXRpb25pbmdQcm9wZXJ0eVZhbHVlcyk7fTtIbi5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbih0KXtmb3IodmFyIGU9bmV3IFduKHRoaXMuX3Byb3BlcnRpZXMpLHI9MCxuPU9iamVjdC5rZXlzKHRoaXMuX3ZhbHVlcyk7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdO2UuX3ZhbHVlc1tpXT10aGlzLl92YWx1ZXNbaV0ucG9zc2libHlFdmFsdWF0ZSh0KTt9cmV0dXJuIGV9LEhuLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9uPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PTAsZT1PYmplY3Qua2V5cyh0aGlzLl92YWx1ZXMpO3Q8ZS5sZW5ndGg7dCs9MSl7dmFyIHI9ZVt0XTtpZih0aGlzLl92YWx1ZXNbcl0ucHJpb3IpcmV0dXJuICEwfXJldHVybiAhMX07dmFyIFluPWZ1bmN0aW9uKHQpe3RoaXMuX3Byb3BlcnRpZXM9dCx0aGlzLl92YWx1ZXM9T2JqZWN0LmNyZWF0ZSh0LmRlZmF1bHRQcm9wZXJ0eVZhbHVlcyk7fTtZbi5wcm90b3R5cGUuZ2V0VmFsdWU9ZnVuY3Rpb24odCl7cmV0dXJuIGIodGhpcy5fdmFsdWVzW3RdLnZhbHVlKX0sWW4ucHJvdG90eXBlLnNldFZhbHVlPWZ1bmN0aW9uKHQsZSl7dGhpcy5fdmFsdWVzW3RdPW5ldyBLbih0aGlzLl92YWx1ZXNbdF0ucHJvcGVydHksbnVsbD09PWU/dm9pZCAwOmIoZSkpO30sWW4ucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe2Zvcih2YXIgdD17fSxlPTAscj1PYmplY3Qua2V5cyh0aGlzLl92YWx1ZXMpO2U8ci5sZW5ndGg7ZSs9MSl7dmFyIG49cltlXSxpPXRoaXMuZ2V0VmFsdWUobik7dm9pZCAwIT09aSYmKHRbbl09aSk7fXJldHVybiB0fSxZbi5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbih0KXtmb3IodmFyIGU9bmV3IFduKHRoaXMuX3Byb3BlcnRpZXMpLHI9MCxuPU9iamVjdC5rZXlzKHRoaXMuX3ZhbHVlcyk7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdO2UuX3ZhbHVlc1tpXT10aGlzLl92YWx1ZXNbaV0ucG9zc2libHlFdmFsdWF0ZSh0KTt9cmV0dXJuIGV9O3ZhciAkbj1mdW5jdGlvbih0LGUscil7dGhpcy5wcm9wZXJ0eT10LHRoaXMudmFsdWU9ZSx0aGlzLnBhcmFtZXRlcnM9cjt9OyRuLnByb3RvdHlwZS5pc0NvbnN0YW50PWZ1bmN0aW9uKCl7cmV0dXJuIFwiY29uc3RhbnRcIj09PXRoaXMudmFsdWUua2luZH0sJG4ucHJvdG90eXBlLmNvbnN0YW50T3I9ZnVuY3Rpb24odCl7cmV0dXJuIFwiY29uc3RhbnRcIj09PXRoaXMudmFsdWUua2luZD90aGlzLnZhbHVlLnZhbHVlOnR9LCRuLnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnByb3BlcnR5LmV2YWx1YXRlKHRoaXMudmFsdWUsdGhpcy5wYXJhbWV0ZXJzLHQsZSl9O3ZhciBXbj1mdW5jdGlvbih0KXt0aGlzLl9wcm9wZXJ0aWVzPXQsdGhpcy5fdmFsdWVzPU9iamVjdC5jcmVhdGUodC5kZWZhdWx0UG9zc2libHlFdmFsdWF0ZWRWYWx1ZXMpO307V24ucHJvdG90eXBlLmdldD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fdmFsdWVzW3RdfTt2YXIgUW49ZnVuY3Rpb24odCl7dGhpcy5zcGVjaWZpY2F0aW9uPXQ7fTtRbi5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbih0LGUpe3JldHVybiB0LmV4cHJlc3Npb24uZXZhbHVhdGUoZSl9LFFuLnByb3RvdHlwZS5pbnRlcnBvbGF0ZT1mdW5jdGlvbih0LGUscil7dmFyIG49TWVbdGhpcy5zcGVjaWZpY2F0aW9uLnR5cGVdO3JldHVybiBuP24odCxlLHIpOnR9O3ZhciB0aT1mdW5jdGlvbih0KXt0aGlzLnNwZWNpZmljYXRpb249dDt9O3RpLnByb3RvdHlwZS5wb3NzaWJseUV2YWx1YXRlPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIFwiY29uc3RhbnRcIj09PXQuZXhwcmVzc2lvbi5raW5kfHxcImNhbWVyYVwiPT09dC5leHByZXNzaW9uLmtpbmQ/bmV3ICRuKHRoaXMse2tpbmQ6XCJjb25zdGFudFwiLHZhbHVlOnQuZXhwcmVzc2lvbi5ldmFsdWF0ZShlKX0sZSk6bmV3ICRuKHRoaXMsdC5leHByZXNzaW9uLGUpfSx0aS5wcm90b3R5cGUuaW50ZXJwb2xhdGU9ZnVuY3Rpb24odCxlLHIpe2lmKFwiY29uc3RhbnRcIiE9PXQudmFsdWUua2luZHx8XCJjb25zdGFudFwiIT09ZS52YWx1ZS5raW5kKXJldHVybiB0O2lmKHZvaWQgMD09PXQudmFsdWUudmFsdWV8fHZvaWQgMD09PWUudmFsdWUudmFsdWUpcmV0dXJuIG5ldyAkbih0aGlzLHtraW5kOlwiY29uc3RhbnRcIix2YWx1ZTp2b2lkIDB9LHQucGFyYW1ldGVycyk7dmFyIG49TWVbdGhpcy5zcGVjaWZpY2F0aW9uLnR5cGVdO3JldHVybiBuP25ldyAkbih0aGlzLHtraW5kOlwiY29uc3RhbnRcIix2YWx1ZTpuKHQudmFsdWUudmFsdWUsZS52YWx1ZS52YWx1ZSxyKX0sdC5wYXJhbWV0ZXJzKTp0fSx0aS5wcm90b3R5cGUuZXZhbHVhdGU9ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuIFwiY29uc3RhbnRcIj09PXQua2luZD90LnZhbHVlOnQuZXZhbHVhdGUoZSxyLG4pfTt2YXIgZWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbih0LGUpe2lmKHZvaWQgMD09PXQudmFsdWUpcmV0dXJuIG5ldyAkbih0aGlzLHtraW5kOlwiY29uc3RhbnRcIix2YWx1ZTp2b2lkIDB9LGUpO2lmKFwiY29uc3RhbnRcIj09PXQuZXhwcmVzc2lvbi5raW5kKXt2YXIgcj10LmV4cHJlc3Npb24uZXZhbHVhdGUoZSksbj10aGlzLl9jYWxjdWxhdGUocixyLHIsZSk7cmV0dXJuIG5ldyAkbih0aGlzLHtraW5kOlwiY29uc3RhbnRcIix2YWx1ZTpufSxlKX1pZihcImNhbWVyYVwiPT09dC5leHByZXNzaW9uLmtpbmQpe3ZhciBpPXRoaXMuX2NhbGN1bGF0ZSh0LmV4cHJlc3Npb24uZXZhbHVhdGUoe3pvb206ZS56b29tLTF9KSx0LmV4cHJlc3Npb24uZXZhbHVhdGUoe3pvb206ZS56b29tfSksdC5leHByZXNzaW9uLmV2YWx1YXRlKHt6b29tOmUuem9vbSsxfSksZSk7cmV0dXJuIG5ldyAkbih0aGlzLHtraW5kOlwiY29uc3RhbnRcIix2YWx1ZTppfSxlKX1yZXR1cm4gbmV3ICRuKHRoaXMsdC5leHByZXNzaW9uLGUpfSxlLnByb3RvdHlwZS5ldmFsdWF0ZT1mdW5jdGlvbih0LGUscixuKXtpZihcInNvdXJjZVwiPT09dC5raW5kKXt2YXIgaT10LmV2YWx1YXRlKGUscixuKTtyZXR1cm4gdGhpcy5fY2FsY3VsYXRlKGksaSxpLGUpfXJldHVybiBcImNvbXBvc2l0ZVwiPT09dC5raW5kP3RoaXMuX2NhbGN1bGF0ZSh0LmV2YWx1YXRlKHt6b29tOk1hdGguZmxvb3IoZS56b29tKS0xfSxyLG4pLHQuZXZhbHVhdGUoe3pvb206TWF0aC5mbG9vcihlLnpvb20pfSxyLG4pLHQuZXZhbHVhdGUoe3pvb206TWF0aC5mbG9vcihlLnpvb20pKzF9LHIsbiksZSk6dC52YWx1ZX0sZS5wcm90b3R5cGUuX2NhbGN1bGF0ZT1mdW5jdGlvbih0LGUscixuKXtyZXR1cm4gbi56b29tPm4uem9vbUhpc3RvcnkubGFzdEludGVnZXJab29tP3tmcm9tOnQsdG86ZX06e2Zyb206cix0bzplfX0sZS5wcm90b3R5cGUuaW50ZXJwb2xhdGU9ZnVuY3Rpb24odCl7cmV0dXJuIHR9LGV9KHRpKSxyaT1mdW5jdGlvbih0KXt0aGlzLnNwZWNpZmljYXRpb249dDt9O3JpLnByb3RvdHlwZS5wb3NzaWJseUV2YWx1YXRlPWZ1bmN0aW9uKHQsZSl7aWYodm9pZCAwIT09dC52YWx1ZSl7aWYoXCJjb25zdGFudFwiPT09dC5leHByZXNzaW9uLmtpbmQpe3ZhciByPXQuZXhwcmVzc2lvbi5ldmFsdWF0ZShlKTtyZXR1cm4gdGhpcy5fY2FsY3VsYXRlKHIscixyLGUpfXJldHVybiB0aGlzLl9jYWxjdWxhdGUodC5leHByZXNzaW9uLmV2YWx1YXRlKG5ldyBabihNYXRoLmZsb29yKGUuem9vbS0xKSxlKSksdC5leHByZXNzaW9uLmV2YWx1YXRlKG5ldyBabihNYXRoLmZsb29yKGUuem9vbSksZSkpLHQuZXhwcmVzc2lvbi5ldmFsdWF0ZShuZXcgWm4oTWF0aC5mbG9vcihlLnpvb20rMSksZSkpLGUpfX0scmkucHJvdG90eXBlLl9jYWxjdWxhdGU9ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuIG4uem9vbT5uLnpvb21IaXN0b3J5Lmxhc3RJbnRlZ2VyWm9vbT97ZnJvbTp0LHRvOmV9Ontmcm9tOnIsdG86ZX19LHJpLnByb3RvdHlwZS5pbnRlcnBvbGF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gdH07dmFyIG5pPWZ1bmN0aW9uKHQpe3RoaXMuc3BlY2lmaWNhdGlvbj10O307bmkucHJvdG90eXBlLnBvc3NpYmx5RXZhbHVhdGU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gISF0LmV4cHJlc3Npb24uZXZhbHVhdGUoZSl9LG5pLnByb3RvdHlwZS5pbnRlcnBvbGF0ZT1mdW5jdGlvbigpe3JldHVybiAhMX07dmFyIGlpPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZSBpbiB0aGlzLnByb3BlcnRpZXM9dCx0aGlzLmRlZmF1bHRQcm9wZXJ0eVZhbHVlcz17fSx0aGlzLmRlZmF1bHRUcmFuc2l0aW9uYWJsZVByb3BlcnR5VmFsdWVzPXt9LHRoaXMuZGVmYXVsdFRyYW5zaXRpb25pbmdQcm9wZXJ0eVZhbHVlcz17fSx0aGlzLmRlZmF1bHRQb3NzaWJseUV2YWx1YXRlZFZhbHVlcz17fSx0KXt2YXIgcj10W2VdLG49dGhpcy5kZWZhdWx0UHJvcGVydHlWYWx1ZXNbZV09bmV3IEtuKHIsdm9pZCAwKSxpPXRoaXMuZGVmYXVsdFRyYW5zaXRpb25hYmxlUHJvcGVydHlWYWx1ZXNbZV09bmV3IEduKHIpO3RoaXMuZGVmYXVsdFRyYW5zaXRpb25pbmdQcm9wZXJ0eVZhbHVlc1tlXT1pLnVudHJhbnNpdGlvbmVkKCksdGhpcy5kZWZhdWx0UG9zc2libHlFdmFsdWF0ZWRWYWx1ZXNbZV09bi5wb3NzaWJseUV2YWx1YXRlKHt9KTt9fTt6bihcIkRhdGFEcml2ZW5Qcm9wZXJ0eVwiLHRpKSx6bihcIkRhdGFDb25zdGFudFByb3BlcnR5XCIsUW4pLHpuKFwiQ3Jvc3NGYWRlZERhdGFEcml2ZW5Qcm9wZXJ0eVwiLGVpKSx6bihcIkNyb3NzRmFkZWRQcm9wZXJ0eVwiLHJpKSx6bihcIkNvbG9yUmFtcFByb3BlcnR5XCIsbmkpO3ZhciBhaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUscil7aWYodC5jYWxsKHRoaXMpLHRoaXMuaWQ9ZS5pZCx0aGlzLnR5cGU9ZS50eXBlLHRoaXMuX2ZlYXR1cmVGaWx0ZXI9ZnVuY3Rpb24oKXtyZXR1cm4gITB9LFwiY3VzdG9tXCIhPT1lLnR5cGUmJihlPWUsdGhpcy5tZXRhZGF0YT1lLm1ldGFkYXRhLHRoaXMubWluem9vbT1lLm1pbnpvb20sdGhpcy5tYXh6b29tPWUubWF4em9vbSxcImJhY2tncm91bmRcIiE9PWUudHlwZSYmKHRoaXMuc291cmNlPWUuc291cmNlLHRoaXMuc291cmNlTGF5ZXI9ZVtcInNvdXJjZS1sYXllclwiXSx0aGlzLmZpbHRlcj1lLmZpbHRlciksci5sYXlvdXQmJih0aGlzLl91bmV2YWx1YXRlZExheW91dD1uZXcgWW4oci5sYXlvdXQpKSxyLnBhaW50KSl7Zm9yKHZhciBuIGluIHRoaXMuX3RyYW5zaXRpb25hYmxlUGFpbnQ9bmV3IFhuKHIucGFpbnQpLGUucGFpbnQpdGhpcy5zZXRQYWludFByb3BlcnR5KG4sZS5wYWludFtuXSx7dmFsaWRhdGU6ITF9KTtmb3IodmFyIGkgaW4gZS5sYXlvdXQpdGhpcy5zZXRMYXlvdXRQcm9wZXJ0eShpLGUubGF5b3V0W2ldLHt2YWxpZGF0ZTohMX0pO3RoaXMuX3RyYW5zaXRpb25pbmdQYWludD10aGlzLl90cmFuc2l0aW9uYWJsZVBhaW50LnVudHJhbnNpdGlvbmVkKCk7fX1yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0Q3Jvc3NmYWRlUGFyYW1ldGVycz1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9jcm9zc2ZhZGVQYXJhbWV0ZXJzfSxlLnByb3RvdHlwZS5nZXRMYXlvdXRQcm9wZXJ0eT1mdW5jdGlvbih0KXtyZXR1cm4gXCJ2aXNpYmlsaXR5XCI9PT10P3RoaXMudmlzaWJpbGl0eTp0aGlzLl91bmV2YWx1YXRlZExheW91dC5nZXRWYWx1ZSh0KX0sZS5wcm90b3R5cGUuc2V0TGF5b3V0UHJvcGVydHk9ZnVuY3Rpb24odCxlLHIpe2lmKHZvaWQgMD09PXImJihyPXt9KSxudWxsIT1lKXt2YXIgbj1cImxheWVycy5cIit0aGlzLmlkK1wiLmxheW91dC5cIit0O2lmKHRoaXMuX3ZhbGlkYXRlKHhuLG4sdCxlLHIpKXJldHVybn1cInZpc2liaWxpdHlcIiE9PXQ/dGhpcy5fdW5ldmFsdWF0ZWRMYXlvdXQuc2V0VmFsdWUodCxlKTp0aGlzLnZpc2liaWxpdHk9ZTt9LGUucHJvdG90eXBlLmdldFBhaW50UHJvcGVydHk9ZnVuY3Rpb24odCl7cmV0dXJuIHYodCxcIi10cmFuc2l0aW9uXCIpP3RoaXMuX3RyYW5zaXRpb25hYmxlUGFpbnQuZ2V0VHJhbnNpdGlvbih0LnNsaWNlKDAsLVwiLXRyYW5zaXRpb25cIi5sZW5ndGgpKTp0aGlzLl90cmFuc2l0aW9uYWJsZVBhaW50LmdldFZhbHVlKHQpfSxlLnByb3RvdHlwZS5zZXRQYWludFByb3BlcnR5PWZ1bmN0aW9uKHQsZSxyKXtpZih2b2lkIDA9PT1yJiYocj17fSksbnVsbCE9ZSl7dmFyIG49XCJsYXllcnMuXCIrdGhpcy5pZCtcIi5wYWludC5cIit0O2lmKHRoaXMuX3ZhbGlkYXRlKGduLG4sdCxlLHIpKXJldHVybiAhMX1pZih2KHQsXCItdHJhbnNpdGlvblwiKSlyZXR1cm4gdGhpcy5fdHJhbnNpdGlvbmFibGVQYWludC5zZXRUcmFuc2l0aW9uKHQuc2xpY2UoMCwtXCItdHJhbnNpdGlvblwiLmxlbmd0aCksZXx8dm9pZCAwKSwhMTt2YXIgaT10aGlzLl90cmFuc2l0aW9uYWJsZVBhaW50Ll92YWx1ZXNbdF0sYT1cImNyb3NzLWZhZGVkLWRhdGEtZHJpdmVuXCI9PT1pLnByb3BlcnR5LnNwZWNpZmljYXRpb25bXCJwcm9wZXJ0eS10eXBlXCJdLG89aS52YWx1ZS5pc0RhdGFEcml2ZW4oKTtyZXR1cm4gdGhpcy5fdHJhbnNpdGlvbmFibGVQYWludC5zZXRWYWx1ZSh0LGUpLHRoaXMuX2hhbmRsZVNwZWNpYWxQYWludFByb3BlcnR5VXBkYXRlKHQpLHRoaXMuX3RyYW5zaXRpb25hYmxlUGFpbnQuX3ZhbHVlc1t0XS52YWx1ZS5pc0RhdGFEcml2ZW4oKXx8b3x8YX0sZS5wcm90b3R5cGUuX2hhbmRsZVNwZWNpYWxQYWludFByb3BlcnR5VXBkYXRlPWZ1bmN0aW9uKHQpe30sZS5wcm90b3R5cGUuaXNIaWRkZW49ZnVuY3Rpb24odCl7cmV0dXJuICEhKHRoaXMubWluem9vbSYmdDx0aGlzLm1pbnpvb20pfHwoISEodGhpcy5tYXh6b29tJiZ0Pj10aGlzLm1heHpvb20pfHxcIm5vbmVcIj09PXRoaXMudmlzaWJpbGl0eSl9LGUucHJvdG90eXBlLnVwZGF0ZVRyYW5zaXRpb25zPWZ1bmN0aW9uKHQpe3RoaXMuX3RyYW5zaXRpb25pbmdQYWludD10aGlzLl90cmFuc2l0aW9uYWJsZVBhaW50LnRyYW5zaXRpb25lZCh0LHRoaXMuX3RyYW5zaXRpb25pbmdQYWludCk7fSxlLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9uPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3RyYW5zaXRpb25pbmdQYWludC5oYXNUcmFuc2l0aW9uKCl9LGUucHJvdG90eXBlLnJlY2FsY3VsYXRlPWZ1bmN0aW9uKHQpe3QuZ2V0Q3Jvc3NmYWRlUGFyYW1ldGVycyYmKHRoaXMuX2Nyb3NzZmFkZVBhcmFtZXRlcnM9dC5nZXRDcm9zc2ZhZGVQYXJhbWV0ZXJzKCkpLHRoaXMuX3VuZXZhbHVhdGVkTGF5b3V0JiYodGhpcy5sYXlvdXQ9dGhpcy5fdW5ldmFsdWF0ZWRMYXlvdXQucG9zc2libHlFdmFsdWF0ZSh0KSksdGhpcy5wYWludD10aGlzLl90cmFuc2l0aW9uaW5nUGFpbnQucG9zc2libHlFdmFsdWF0ZSh0KTt9LGUucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3ZhciB0PXtpZDp0aGlzLmlkLHR5cGU6dGhpcy50eXBlLHNvdXJjZTp0aGlzLnNvdXJjZSxcInNvdXJjZS1sYXllclwiOnRoaXMuc291cmNlTGF5ZXIsbWV0YWRhdGE6dGhpcy5tZXRhZGF0YSxtaW56b29tOnRoaXMubWluem9vbSxtYXh6b29tOnRoaXMubWF4em9vbSxmaWx0ZXI6dGhpcy5maWx0ZXIsbGF5b3V0OnRoaXMuX3VuZXZhbHVhdGVkTGF5b3V0JiZ0aGlzLl91bmV2YWx1YXRlZExheW91dC5zZXJpYWxpemUoKSxwYWludDp0aGlzLl90cmFuc2l0aW9uYWJsZVBhaW50JiZ0aGlzLl90cmFuc2l0aW9uYWJsZVBhaW50LnNlcmlhbGl6ZSgpfTtyZXR1cm4gdGhpcy52aXNpYmlsaXR5JiYodC5sYXlvdXQ9dC5sYXlvdXR8fHt9LHQubGF5b3V0LnZpc2liaWxpdHk9dGhpcy52aXNpYmlsaXR5KSx4KHQsZnVuY3Rpb24odCxlKXtyZXR1cm4gISh2b2lkIDA9PT10fHxcImxheW91dFwiPT09ZSYmIU9iamVjdC5rZXlzKHQpLmxlbmd0aHx8XCJwYWludFwiPT09ZSYmIU9iamVjdC5rZXlzKHQpLmxlbmd0aCl9KX0sZS5wcm90b3R5cGUuX3ZhbGlkYXRlPWZ1bmN0aW9uKHQsZSxyLG4saSl7cmV0dXJuIHZvaWQgMD09PWkmJihpPXt9KSwoIWl8fCExIT09aS52YWxpZGF0ZSkmJmJuKHRoaXMsdC5jYWxsKG1uLHtrZXk6ZSxsYXllclR5cGU6dGhpcy50eXBlLG9iamVjdEtleTpyLHZhbHVlOm4sc3R5bGVTcGVjOkx0LHN0eWxlOntnbHlwaHM6ITAsc3ByaXRlOiEwfX0pKX0sZS5wcm90b3R5cGUuaXMzRD1mdW5jdGlvbigpe3JldHVybiAhMX0sZS5wcm90b3R5cGUuaXNUaWxlQ2xpcHBlZD1mdW5jdGlvbigpe3JldHVybiAhMX0sZS5wcm90b3R5cGUuaGFzT2Zmc2NyZWVuUGFzcz1mdW5jdGlvbigpe3JldHVybiAhMX0sZS5wcm90b3R5cGUucmVzaXplPWZ1bmN0aW9uKCl7fSxlLnByb3RvdHlwZS5pc1N0YXRlRGVwZW5kZW50PWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMucGFpbnQuX3ZhbHVlcyl7dmFyIGU9dGhpcy5wYWludC5nZXQodCk7aWYoZSBpbnN0YW5jZW9mICRuJiZ3cihlLnByb3BlcnR5LnNwZWNpZmljYXRpb24pJiYoKFwic291cmNlXCI9PT1lLnZhbHVlLmtpbmR8fFwiY29tcG9zaXRlXCI9PT1lLnZhbHVlLmtpbmQpJiZlLnZhbHVlLmlzU3RhdGVEZXBlbmRlbnQpKXJldHVybiAhMH1yZXR1cm4gITF9LGV9KEZ0KSxvaT17SW50ODpJbnQ4QXJyYXksVWludDg6VWludDhBcnJheSxJbnQxNjpJbnQxNkFycmF5LFVpbnQxNjpVaW50MTZBcnJheSxJbnQzMjpJbnQzMkFycmF5LFVpbnQzMjpVaW50MzJBcnJheSxGbG9hdDMyOkZsb2F0MzJBcnJheX0sc2k9ZnVuY3Rpb24odCxlKXt0aGlzLl9zdHJ1Y3RBcnJheT10LHRoaXMuX3BvczE9ZSp0aGlzLnNpemUsdGhpcy5fcG9zMj10aGlzLl9wb3MxLzIsdGhpcy5fcG9zND10aGlzLl9wb3MxLzQsdGhpcy5fcG9zOD10aGlzLl9wb3MxLzg7fSx1aT1mdW5jdGlvbigpe3RoaXMuaXNUcmFuc2ZlcnJlZD0hMSx0aGlzLmNhcGFjaXR5PS0xLHRoaXMucmVzaXplKDApO307ZnVuY3Rpb24gbGkodCxlKXt2b2lkIDA9PT1lJiYoZT0xKTt2YXIgcj0wLG49MDtyZXR1cm4ge21lbWJlcnM6dC5tYXAoZnVuY3Rpb24odCl7dmFyIGksYT0oaT10LnR5cGUsb2lbaV0uQllURVNfUEVSX0VMRU1FTlQpLG89cj1waShyLE1hdGgubWF4KGUsYSkpLHM9dC5jb21wb25lbnRzfHwxO3JldHVybiBuPU1hdGgubWF4KG4sYSkscis9YSpzLHtuYW1lOnQubmFtZSx0eXBlOnQudHlwZSxjb21wb25lbnRzOnMsb2Zmc2V0Om99fSksc2l6ZTpwaShyLE1hdGgubWF4KG4sZSkpLGFsaWdubWVudDplfX1mdW5jdGlvbiBwaSh0LGUpe3JldHVybiBNYXRoLmNlaWwodC9lKSplfXVpLnNlcmlhbGl6ZT1mdW5jdGlvbih0LGUpe3JldHVybiB0Ll90cmltKCksZSYmKHQuaXNUcmFuc2ZlcnJlZD0hMCxlLnB1c2godC5hcnJheUJ1ZmZlcikpLHtsZW5ndGg6dC5sZW5ndGgsYXJyYXlCdWZmZXI6dC5hcnJheUJ1ZmZlcn19LHVpLmRlc2VyaWFsaXplPWZ1bmN0aW9uKHQpe3ZhciBlPU9iamVjdC5jcmVhdGUodGhpcy5wcm90b3R5cGUpO3JldHVybiBlLmFycmF5QnVmZmVyPXQuYXJyYXlCdWZmZXIsZS5sZW5ndGg9dC5sZW5ndGgsZS5jYXBhY2l0eT10LmFycmF5QnVmZmVyLmJ5dGVMZW5ndGgvZS5ieXRlc1BlckVsZW1lbnQsZS5fcmVmcmVzaFZpZXdzKCksZX0sdWkucHJvdG90eXBlLl90cmltPWZ1bmN0aW9uKCl7dGhpcy5sZW5ndGghPT10aGlzLmNhcGFjaXR5JiYodGhpcy5jYXBhY2l0eT10aGlzLmxlbmd0aCx0aGlzLmFycmF5QnVmZmVyPXRoaXMuYXJyYXlCdWZmZXIuc2xpY2UoMCx0aGlzLmxlbmd0aCp0aGlzLmJ5dGVzUGVyRWxlbWVudCksdGhpcy5fcmVmcmVzaFZpZXdzKCkpO30sdWkucHJvdG90eXBlLmNsZWFyPWZ1bmN0aW9uKCl7dGhpcy5sZW5ndGg9MDt9LHVpLnByb3RvdHlwZS5yZXNpemU9ZnVuY3Rpb24odCl7dGhpcy5yZXNlcnZlKHQpLHRoaXMubGVuZ3RoPXQ7fSx1aS5wcm90b3R5cGUucmVzZXJ2ZT1mdW5jdGlvbih0KXtpZih0PnRoaXMuY2FwYWNpdHkpe3RoaXMuY2FwYWNpdHk9TWF0aC5tYXgodCxNYXRoLmZsb29yKDUqdGhpcy5jYXBhY2l0eSksMTI4KSx0aGlzLmFycmF5QnVmZmVyPW5ldyBBcnJheUJ1ZmZlcih0aGlzLmNhcGFjaXR5KnRoaXMuYnl0ZXNQZXJFbGVtZW50KTt2YXIgZT10aGlzLnVpbnQ4O3RoaXMuX3JlZnJlc2hWaWV3cygpLGUmJnRoaXMudWludDguc2V0KGUpO319LHVpLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhyb3cgbmV3IEVycm9yKFwiX3JlZnJlc2hWaWV3cygpIG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgZWFjaCBjb25jcmV0ZSBTdHJ1Y3RBcnJheSBsYXlvdXRcIil9O3ZhciBjaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLmludDE2PW5ldyBJbnQxNkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCxlKXt2YXIgcj10aGlzLmxlbmd0aDtyZXR1cm4gdGhpcy5yZXNpemUocisxKSx0aGlzLmVtcGxhY2Uocix0LGUpfSxlLnByb3RvdHlwZS5lbXBsYWNlPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj0yKnQ7cmV0dXJuIHRoaXMuaW50MTZbbiswXT1lLHRoaXMuaW50MTZbbisxXT1yLHR9LGV9KHVpKTtjaS5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTQsem4oXCJTdHJ1Y3RBcnJheUxheW91dDJpNFwiLGNpKTt2YXIgaGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPXRoaXMubGVuZ3RoO3JldHVybiB0aGlzLnJlc2l6ZShpKzEpLHRoaXMuZW1wbGFjZShpLHQsZSxyLG4pfSxlLnByb3RvdHlwZS5lbXBsYWNlPWZ1bmN0aW9uKHQsZSxyLG4saSl7dmFyIGE9NCp0O3JldHVybiB0aGlzLmludDE2W2ErMF09ZSx0aGlzLmludDE2W2ErMV09cix0aGlzLmludDE2W2ErMl09bix0aGlzLmludDE2W2ErM109aSx0fSxlfSh1aSk7aGkucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD04LHpuKFwiU3RydWN0QXJyYXlMYXlvdXQ0aThcIixoaSk7dmFyIGZpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMuaW50MTY9bmV3IEludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscixuLGksYSl7dmFyIG89dGhpcy5sZW5ndGg7cmV0dXJuIHRoaXMucmVzaXplKG8rMSksdGhpcy5lbXBsYWNlKG8sdCxlLHIsbixpLGEpfSxlLnByb3RvdHlwZS5lbXBsYWNlPWZ1bmN0aW9uKHQsZSxyLG4saSxhLG8pe3ZhciBzPTYqdDtyZXR1cm4gdGhpcy5pbnQxNltzKzBdPWUsdGhpcy5pbnQxNltzKzFdPXIsdGhpcy5pbnQxNltzKzJdPW4sdGhpcy5pbnQxNltzKzNdPWksdGhpcy5pbnQxNltzKzRdPWEsdGhpcy5pbnQxNltzKzVdPW8sdH0sZX0odWkpO2ZpLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9MTIsem4oXCJTdHJ1Y3RBcnJheUxheW91dDJpNGkxMlwiLGZpKTt2YXIgeWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyLG4saSxhKXt2YXIgbz10aGlzLmxlbmd0aDtyZXR1cm4gdGhpcy5yZXNpemUobysxKSx0aGlzLmVtcGxhY2Uobyx0LGUscixuLGksYSl9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyl7dmFyIHM9NCp0LHU9OCp0O3JldHVybiB0aGlzLmludDE2W3MrMF09ZSx0aGlzLmludDE2W3MrMV09cix0aGlzLnVpbnQ4W3UrNF09bix0aGlzLnVpbnQ4W3UrNV09aSx0aGlzLnVpbnQ4W3UrNl09YSx0aGlzLnVpbnQ4W3UrN109byx0fSxlfSh1aSk7eWkucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD04LHpuKFwiU3RydWN0QXJyYXlMYXlvdXQyaTR1YjhcIix5aSk7dmFyIGRpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMudWludDE2PW5ldyBVaW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyLG4saSxhLG8scyl7dmFyIHU9dGhpcy5sZW5ndGg7cmV0dXJuIHRoaXMucmVzaXplKHUrMSksdGhpcy5lbXBsYWNlKHUsdCxlLHIsbixpLGEsbyxzKX0sZS5wcm90b3R5cGUuZW1wbGFjZT1mdW5jdGlvbih0LGUscixuLGksYSxvLHMsdSl7dmFyIGw9OCp0O3JldHVybiB0aGlzLnVpbnQxNltsKzBdPWUsdGhpcy51aW50MTZbbCsxXT1yLHRoaXMudWludDE2W2wrMl09bix0aGlzLnVpbnQxNltsKzNdPWksdGhpcy51aW50MTZbbCs0XT1hLHRoaXMudWludDE2W2wrNV09byx0aGlzLnVpbnQxNltsKzZdPXMsdGhpcy51aW50MTZbbCs3XT11LHR9LGV9KHVpKTtkaS5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTE2LHpuKFwiU3RydWN0QXJyYXlMYXlvdXQ4dWkxNlwiLGRpKTt2YXIgbWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLnVpbnQxNj1uZXcgVWludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscixuLGksYSxvLHMpe3ZhciB1PXRoaXMubGVuZ3RoO3JldHVybiB0aGlzLnJlc2l6ZSh1KzEpLHRoaXMuZW1wbGFjZSh1LHQsZSxyLG4saSxhLG8scyl9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyxzLHUpe3ZhciBsPTgqdDtyZXR1cm4gdGhpcy5pbnQxNltsKzBdPWUsdGhpcy5pbnQxNltsKzFdPXIsdGhpcy5pbnQxNltsKzJdPW4sdGhpcy5pbnQxNltsKzNdPWksdGhpcy51aW50MTZbbCs0XT1hLHRoaXMudWludDE2W2wrNV09byx0aGlzLnVpbnQxNltsKzZdPXMsdGhpcy51aW50MTZbbCs3XT11LHR9LGV9KHVpKTttaS5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTE2LHpuKFwiU3RydWN0QXJyYXlMYXlvdXQ0aTR1aTE2XCIsbWkpO3ZhciB2aT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLmZsb2F0MzI9bmV3IEZsb2F0MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj10aGlzLmxlbmd0aDtyZXR1cm4gdGhpcy5yZXNpemUobisxKSx0aGlzLmVtcGxhY2Uobix0LGUscil9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlLHIsbil7dmFyIGk9Myp0O3JldHVybiB0aGlzLmZsb2F0MzJbaSswXT1lLHRoaXMuZmxvYXQzMltpKzFdPXIsdGhpcy5mbG9hdDMyW2krMl09bix0fSxlfSh1aSk7dmkucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD0xMix6bihcIlN0cnVjdEFycmF5TGF5b3V0M2YxMlwiLHZpKTt2YXIgZ2k9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy51aW50MzI9bmV3IFVpbnQzMkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5sZW5ndGg7cmV0dXJuIHRoaXMucmVzaXplKGUrMSksdGhpcy5lbXBsYWNlKGUsdCl9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlKXt2YXIgcj0xKnQ7cmV0dXJuIHRoaXMudWludDMyW3IrMF09ZSx0fSxlfSh1aSk7Z2kucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD00LHpuKFwiU3RydWN0QXJyYXlMYXlvdXQxdWw0XCIsZ2kpO3ZhciB4aT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLmludDE2PW5ldyBJbnQxNkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMudWludDMyPW5ldyBVaW50MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLnVpbnQxNj1uZXcgVWludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscixuLGksYSxvLHMsdSxsLHApe3ZhciBjPXRoaXMubGVuZ3RoO3JldHVybiB0aGlzLnJlc2l6ZShjKzEpLHRoaXMuZW1wbGFjZShjLHQsZSxyLG4saSxhLG8scyx1LGwscCl9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyxzLHUsbCxwLGMpe3ZhciBoPTEyKnQsZj02KnQ7cmV0dXJuIHRoaXMuaW50MTZbaCswXT1lLHRoaXMuaW50MTZbaCsxXT1yLHRoaXMuaW50MTZbaCsyXT1uLHRoaXMuaW50MTZbaCszXT1pLHRoaXMuaW50MTZbaCs0XT1hLHRoaXMuaW50MTZbaCs1XT1vLHRoaXMudWludDMyW2YrM109cyx0aGlzLnVpbnQxNltoKzhdPXUsdGhpcy51aW50MTZbaCs5XT1sLHRoaXMuaW50MTZbaCsxMF09cCx0aGlzLmludDE2W2grMTFdPWMsdH0sZX0odWkpO3hpLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9MjQsem4oXCJTdHJ1Y3RBcnJheUxheW91dDZpMXVsMnVpMmkyNFwiLHhpKTt2YXIgYmk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyLG4saSxhKXt2YXIgbz10aGlzLmxlbmd0aDtyZXR1cm4gdGhpcy5yZXNpemUobysxKSx0aGlzLmVtcGxhY2Uobyx0LGUscixuLGksYSl9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyl7dmFyIHM9Nip0O3JldHVybiB0aGlzLmludDE2W3MrMF09ZSx0aGlzLmludDE2W3MrMV09cix0aGlzLmludDE2W3MrMl09bix0aGlzLmludDE2W3MrM109aSx0aGlzLmludDE2W3MrNF09YSx0aGlzLmludDE2W3MrNV09byx0fSxlfSh1aSk7YmkucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD0xMix6bihcIlN0cnVjdEFycmF5TGF5b3V0MmkyaTJpMTJcIixiaSk7dmFyIF9pPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMuZmxvYXQzMj1uZXcgRmxvYXQzMkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCxlLHIsbil7dmFyIGk9dGhpcy5sZW5ndGg7cmV0dXJuIHRoaXMucmVzaXplKGkrMSksdGhpcy5lbXBsYWNlKGksdCxlLHIsbil9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlLHIsbixpKXt2YXIgYT0xMip0LG89Myp0O3JldHVybiB0aGlzLnVpbnQ4W2ErMF09ZSx0aGlzLnVpbnQ4W2ErMV09cix0aGlzLmZsb2F0MzJbbysxXT1uLHRoaXMuZmxvYXQzMltvKzJdPWksdH0sZX0odWkpO19pLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9MTIsem4oXCJTdHJ1Y3RBcnJheUxheW91dDJ1YjJmMTJcIixfaSk7dmFyIHdpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMuaW50MTY9bmV3IEludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy51aW50MTY9bmV3IFVpbnQxNkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMudWludDMyPW5ldyBVaW50MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLmZsb2F0MzI9bmV3IEZsb2F0MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyLG4saSxhLG8scyx1LGwscCxjLGgsZix5KXt2YXIgZD10aGlzLmxlbmd0aDtyZXR1cm4gdGhpcy5yZXNpemUoZCsxKSx0aGlzLmVtcGxhY2UoZCx0LGUscixuLGksYSxvLHMsdSxsLHAsYyxoLGYseSl9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyxzLHUsbCxwLGMsaCxmLHksZCl7dmFyIG09MjIqdCx2PTExKnQsZz00NCp0O3JldHVybiB0aGlzLmludDE2W20rMF09ZSx0aGlzLmludDE2W20rMV09cix0aGlzLnVpbnQxNlttKzJdPW4sdGhpcy51aW50MTZbbSszXT1pLHRoaXMudWludDMyW3YrMl09YSx0aGlzLnVpbnQzMlt2KzNdPW8sdGhpcy51aW50MzJbdis0XT1zLHRoaXMudWludDE2W20rMTBdPXUsdGhpcy51aW50MTZbbSsxMV09bCx0aGlzLnVpbnQxNlttKzEyXT1wLHRoaXMuZmxvYXQzMlt2KzddPWMsdGhpcy5mbG9hdDMyW3YrOF09aCx0aGlzLnVpbnQ4W2crMzZdPWYsdGhpcy51aW50OFtnKzM3XT15LHRoaXMudWludDMyW3YrMTBdPWQsdH0sZX0odWkpO3dpLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9NDQsem4oXCJTdHJ1Y3RBcnJheUxheW91dDJpMnVpM3VsM3VpMmYydWIxdWw0NFwiLHdpKTt2YXIgQWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLnVpbnQxNj1uZXcgVWludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy51aW50MzI9bmV3IFVpbnQzMkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMuZmxvYXQzMj1uZXcgRmxvYXQzMkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyxzLHUsbCxwLGMsaCxmLHksZCxtLHYpe3ZhciBnPXRoaXMubGVuZ3RoO3JldHVybiB0aGlzLnJlc2l6ZShnKzEpLHRoaXMuZW1wbGFjZShnLHQsZSxyLG4saSxhLG8scyx1LGwscCxjLGgsZix5LGQsbSx2KX0sZS5wcm90b3R5cGUuZW1wbGFjZT1mdW5jdGlvbih0LGUscixuLGksYSxvLHMsdSxsLHAsYyxoLGYseSxkLG0sdixnKXt2YXIgeD0yMip0LGI9MTEqdDtyZXR1cm4gdGhpcy5pbnQxNlt4KzBdPWUsdGhpcy5pbnQxNlt4KzFdPXIsdGhpcy5pbnQxNlt4KzJdPW4sdGhpcy5pbnQxNlt4KzNdPWksdGhpcy5pbnQxNlt4KzRdPWEsdGhpcy5pbnQxNlt4KzVdPW8sdGhpcy51aW50MTZbeCs2XT1zLHRoaXMudWludDE2W3grN109dSx0aGlzLnVpbnQxNlt4KzhdPWwsdGhpcy51aW50MTZbeCs5XT1wLHRoaXMudWludDE2W3grMTBdPWMsdGhpcy51aW50MTZbeCsxMV09aCx0aGlzLnVpbnQxNlt4KzEyXT1mLHRoaXMudWludDE2W3grMTNdPXksdGhpcy51aW50MTZbeCsxNF09ZCx0aGlzLnVpbnQzMltiKzhdPW0sdGhpcy5mbG9hdDMyW2IrOV09dix0aGlzLmZsb2F0MzJbYisxMF09Zyx0fSxlfSh1aSk7QWkucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD00NCx6bihcIlN0cnVjdEFycmF5TGF5b3V0Nmk5dWkxdWwyZjQ0XCIsQWkpO3ZhciBTaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5fcmVmcmVzaFZpZXdzPWZ1bmN0aW9uKCl7dGhpcy51aW50OD1uZXcgVWludDhBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLmZsb2F0MzI9bmV3IEZsb2F0MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMubGVuZ3RoO3JldHVybiB0aGlzLnJlc2l6ZShlKzEpLHRoaXMuZW1wbGFjZShlLHQpfSxlLnByb3RvdHlwZS5lbXBsYWNlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9MSp0O3JldHVybiB0aGlzLmZsb2F0MzJbciswXT1lLHR9LGV9KHVpKTtTaS5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTQsem4oXCJTdHJ1Y3RBcnJheUxheW91dDFmNFwiLFNpKTt2YXIga2k9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5pbnQxNj1uZXcgSW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj10aGlzLmxlbmd0aDtyZXR1cm4gdGhpcy5yZXNpemUobisxKSx0aGlzLmVtcGxhY2Uobix0LGUscil9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlLHIsbil7dmFyIGk9Myp0O3JldHVybiB0aGlzLmludDE2W2krMF09ZSx0aGlzLmludDE2W2krMV09cix0aGlzLmludDE2W2krMl09bix0fSxlfSh1aSk7a2kucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD02LHpuKFwiU3RydWN0QXJyYXlMYXlvdXQzaTZcIixraSk7dmFyIHppPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMudWludDMyPW5ldyBVaW50MzJBcnJheSh0aGlzLmFycmF5QnVmZmVyKSx0aGlzLnVpbnQxNj1uZXcgVWludDE2QXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscil7dmFyIG49dGhpcy5sZW5ndGg7cmV0dXJuIHRoaXMucmVzaXplKG4rMSksdGhpcy5lbXBsYWNlKG4sdCxlLHIpfSxlLnByb3RvdHlwZS5lbXBsYWNlPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPTIqdCxhPTQqdDtyZXR1cm4gdGhpcy51aW50MzJbaSswXT1lLHRoaXMudWludDE2W2ErMl09cix0aGlzLnVpbnQxNlthKzNdPW4sdH0sZX0odWkpO3ppLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9OCx6bihcIlN0cnVjdEFycmF5TGF5b3V0MXVsMnVpOFwiLHppKTt2YXIgSWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy51aW50MTY9bmV3IFVpbnQxNkFycmF5KHRoaXMuYXJyYXlCdWZmZXIpO30sZS5wcm90b3R5cGUuZW1wbGFjZUJhY2s9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPXRoaXMubGVuZ3RoO3JldHVybiB0aGlzLnJlc2l6ZShuKzEpLHRoaXMuZW1wbGFjZShuLHQsZSxyKX0sZS5wcm90b3R5cGUuZW1wbGFjZT1mdW5jdGlvbih0LGUscixuKXt2YXIgaT0zKnQ7cmV0dXJuIHRoaXMudWludDE2W2krMF09ZSx0aGlzLnVpbnQxNltpKzFdPXIsdGhpcy51aW50MTZbaSsyXT1uLHR9LGV9KHVpKTtJaS5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTYsem4oXCJTdHJ1Y3RBcnJheUxheW91dDN1aTZcIixJaSk7dmFyIEJpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMudWludDE2PW5ldyBVaW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQsZSl7dmFyIHI9dGhpcy5sZW5ndGg7cmV0dXJuIHRoaXMucmVzaXplKHIrMSksdGhpcy5lbXBsYWNlKHIsdCxlKX0sZS5wcm90b3R5cGUuZW1wbGFjZT1mdW5jdGlvbih0LGUscil7dmFyIG49Mip0O3JldHVybiB0aGlzLnVpbnQxNltuKzBdPWUsdGhpcy51aW50MTZbbisxXT1yLHR9LGV9KHVpKTtCaS5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTQsem4oXCJTdHJ1Y3RBcnJheUxheW91dDJ1aTRcIixCaSk7dmFyIENpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLl9yZWZyZXNoVmlld3M9ZnVuY3Rpb24oKXt0aGlzLnVpbnQ4PW5ldyBVaW50OEFycmF5KHRoaXMuYXJyYXlCdWZmZXIpLHRoaXMudWludDE2PW5ldyBVaW50MTZBcnJheSh0aGlzLmFycmF5QnVmZmVyKTt9LGUucHJvdG90eXBlLmVtcGxhY2VCYWNrPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMubGVuZ3RoO3JldHVybiB0aGlzLnJlc2l6ZShlKzEpLHRoaXMuZW1wbGFjZShlLHQpfSxlLnByb3RvdHlwZS5lbXBsYWNlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9MSp0O3JldHVybiB0aGlzLnVpbnQxNltyKzBdPWUsdH0sZX0odWkpO0NpLnByb3RvdHlwZS5ieXRlc1BlckVsZW1lbnQ9Mix6bihcIlN0cnVjdEFycmF5TGF5b3V0MXVpMlwiLENpKTt2YXIgRWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5mbG9hdDMyPW5ldyBGbG9hdDMyQXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUpe3ZhciByPXRoaXMubGVuZ3RoO3JldHVybiB0aGlzLnJlc2l6ZShyKzEpLHRoaXMuZW1wbGFjZShyLHQsZSl9LGUucHJvdG90eXBlLmVtcGxhY2U9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPTIqdDtyZXR1cm4gdGhpcy5mbG9hdDMyW24rMF09ZSx0aGlzLmZsb2F0MzJbbisxXT1yLHR9LGV9KHVpKTtFaS5wcm90b3R5cGUuYnl0ZXNQZXJFbGVtZW50PTgsem4oXCJTdHJ1Y3RBcnJheUxheW91dDJmOFwiLEVpKTt2YXIgTWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuX3JlZnJlc2hWaWV3cz1mdW5jdGlvbigpe3RoaXMudWludDg9bmV3IFVpbnQ4QXJyYXkodGhpcy5hcnJheUJ1ZmZlciksdGhpcy5mbG9hdDMyPW5ldyBGbG9hdDMyQXJyYXkodGhpcy5hcnJheUJ1ZmZlcik7fSxlLnByb3RvdHlwZS5lbXBsYWNlQmFjaz1mdW5jdGlvbih0LGUscixuKXt2YXIgaT10aGlzLmxlbmd0aDtyZXR1cm4gdGhpcy5yZXNpemUoaSsxKSx0aGlzLmVtcGxhY2UoaSx0LGUscixuKX0sZS5wcm90b3R5cGUuZW1wbGFjZT1mdW5jdGlvbih0LGUscixuLGkpe3ZhciBhPTQqdDtyZXR1cm4gdGhpcy5mbG9hdDMyW2ErMF09ZSx0aGlzLmZsb2F0MzJbYSsxXT1yLHRoaXMuZmxvYXQzMlthKzJdPW4sdGhpcy5mbG9hdDMyW2ErM109aSx0fSxlfSh1aSk7TWkucHJvdG90eXBlLmJ5dGVzUGVyRWxlbWVudD0xNix6bihcIlN0cnVjdEFycmF5TGF5b3V0NGYxNlwiLE1pKTt2YXIgVGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO310JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZTt2YXIgcj17YW5jaG9yUG9pbnRYOntjb25maWd1cmFibGU6ITB9LGFuY2hvclBvaW50WTp7Y29uZmlndXJhYmxlOiEwfSx4MTp7Y29uZmlndXJhYmxlOiEwfSx5MTp7Y29uZmlndXJhYmxlOiEwfSx4Mjp7Y29uZmlndXJhYmxlOiEwfSx5Mjp7Y29uZmlndXJhYmxlOiEwfSxmZWF0dXJlSW5kZXg6e2NvbmZpZ3VyYWJsZTohMH0sc291cmNlTGF5ZXJJbmRleDp7Y29uZmlndXJhYmxlOiEwfSxidWNrZXRJbmRleDp7Y29uZmlndXJhYmxlOiEwfSxyYWRpdXM6e2NvbmZpZ3VyYWJsZTohMH0sc2lnbmVkRGlzdGFuY2VGcm9tQW5jaG9yOntjb25maWd1cmFibGU6ITB9LGFuY2hvclBvaW50Ontjb25maWd1cmFibGU6ITB9fTtyZXR1cm4gci5hbmNob3JQb2ludFguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMF19LHIuYW5jaG9yUG9pbnRYLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzBdPXQ7fSxyLmFuY2hvclBvaW50WS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisxXX0sci5hbmNob3JQb2ludFkuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMV09dDt9LHIueDEuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMl19LHIueDEuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMl09dDt9LHIueTEuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrM119LHIueTEuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrM109dDt9LHIueDIuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrNF19LHIueDIuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrNF09dDt9LHIueTIuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrNV19LHIueTIuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrNV09dDt9LHIuZmVhdHVyZUluZGV4LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MzJbdGhpcy5fcG9zNCszXX0sci5mZWF0dXJlSW5kZXguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQzMlt0aGlzLl9wb3M0KzNdPXQ7fSxyLnNvdXJjZUxheWVySW5kZXguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzhdfSxyLnNvdXJjZUxheWVySW5kZXguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzhdPXQ7fSxyLmJ1Y2tldEluZGV4LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMis5XX0sci5idWNrZXRJbmRleC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrOV09dDt9LHIucmFkaXVzLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzEwXX0sci5yYWRpdXMuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMTBdPXQ7fSxyLnNpZ25lZERpc3RhbmNlRnJvbUFuY2hvci5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisxMV19LHIuc2lnbmVkRGlzdGFuY2VGcm9tQW5jaG9yLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzExXT10O30sci5hbmNob3JQb2ludC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IGkodGhpcy5hbmNob3JQb2ludFgsdGhpcy5hbmNob3JQb2ludFkpfSxPYmplY3QuZGVmaW5lUHJvcGVydGllcyhlLnByb3RvdHlwZSxyKSxlfShzaSk7VGkucHJvdG90eXBlLnNpemU9MjQ7dmFyIFBpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IFRpKHRoaXMsdCl9LGV9KHhpKTt6bihcIkNvbGxpc2lvbkJveEFycmF5XCIsUGkpO3ZhciBWaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lO3ZhciByPXthbmNob3JYOntjb25maWd1cmFibGU6ITB9LGFuY2hvclk6e2NvbmZpZ3VyYWJsZTohMH0sZ2x5cGhTdGFydEluZGV4Ontjb25maWd1cmFibGU6ITB9LG51bUdseXBoczp7Y29uZmlndXJhYmxlOiEwfSx2ZXJ0ZXhTdGFydEluZGV4Ontjb25maWd1cmFibGU6ITB9LGxpbmVTdGFydEluZGV4Ontjb25maWd1cmFibGU6ITB9LGxpbmVMZW5ndGg6e2NvbmZpZ3VyYWJsZTohMH0sc2VnbWVudDp7Y29uZmlndXJhYmxlOiEwfSxsb3dlclNpemU6e2NvbmZpZ3VyYWJsZTohMH0sdXBwZXJTaXplOntjb25maWd1cmFibGU6ITB9LGxpbmVPZmZzZXRYOntjb25maWd1cmFibGU6ITB9LGxpbmVPZmZzZXRZOntjb25maWd1cmFibGU6ITB9LHdyaXRpbmdNb2RlOntjb25maWd1cmFibGU6ITB9LGhpZGRlbjp7Y29uZmlndXJhYmxlOiEwfSxjcm9zc1RpbGVJRDp7Y29uZmlndXJhYmxlOiEwfX07cmV0dXJuIHIuYW5jaG9yWC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMiswXX0sci5hbmNob3JYLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzBdPXQ7fSxyLmFuY2hvclkuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMV19LHIuYW5jaG9yWS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisxXT10O30sci5nbHlwaFN0YXJ0SW5kZXguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzJdfSxyLmdseXBoU3RhcnRJbmRleC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMl09dDt9LHIubnVtR2x5cGhzLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMiszXX0sci5udW1HbHlwaHMuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzNdPXQ7fSxyLnZlcnRleFN0YXJ0SW5kZXguZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQzMlt0aGlzLl9wb3M0KzJdfSxyLnZlcnRleFN0YXJ0SW5kZXguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQzMlt0aGlzLl9wb3M0KzJdPXQ7fSxyLmxpbmVTdGFydEluZGV4LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MzJbdGhpcy5fcG9zNCszXX0sci5saW5lU3RhcnRJbmRleC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDMyW3RoaXMuX3BvczQrM109dDt9LHIubGluZUxlbmd0aC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDMyW3RoaXMuX3BvczQrNF19LHIubGluZUxlbmd0aC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDMyW3RoaXMuX3BvczQrNF09dDt9LHIuc2VnbWVudC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTBdfSxyLnNlZ21lbnQuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzEwXT10O30sci5sb3dlclNpemUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzExXX0sci5sb3dlclNpemUuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzExXT10O30sci51cHBlclNpemUuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzEyXX0sci51cHBlclNpemUuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzEyXT10O30sci5saW5lT2Zmc2V0WC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuZmxvYXQzMlt0aGlzLl9wb3M0KzddfSxyLmxpbmVPZmZzZXRYLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5mbG9hdDMyW3RoaXMuX3BvczQrN109dDt9LHIubGluZU9mZnNldFkuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmZsb2F0MzJbdGhpcy5fcG9zNCs4XX0sci5saW5lT2Zmc2V0WS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuZmxvYXQzMlt0aGlzLl9wb3M0KzhdPXQ7fSxyLndyaXRpbmdNb2RlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50OFt0aGlzLl9wb3MxKzM2XX0sci53cml0aW5nTW9kZS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDhbdGhpcy5fcG9zMSszNl09dDt9LHIuaGlkZGVuLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50OFt0aGlzLl9wb3MxKzM3XX0sci5oaWRkZW4uc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQ4W3RoaXMuX3BvczErMzddPXQ7fSxyLmNyb3NzVGlsZUlELmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MzJbdGhpcy5fcG9zNCsxMF19LHIuY3Jvc3NUaWxlSUQuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQzMlt0aGlzLl9wb3M0KzEwXT10O30sT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoZS5wcm90b3R5cGUsciksZX0oc2kpO1ZpLnByb3RvdHlwZS5zaXplPTQ0O3ZhciBGaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBWaSh0aGlzLHQpfSxlfSh3aSk7em4oXCJQbGFjZWRTeW1ib2xBcnJheVwiLEZpKTt2YXIgTGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO310JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZTt2YXIgcj17YW5jaG9yWDp7Y29uZmlndXJhYmxlOiEwfSxhbmNob3JZOntjb25maWd1cmFibGU6ITB9LHJpZ2h0SnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4Ontjb25maWd1cmFibGU6ITB9LGNlbnRlckp1c3RpZmllZFRleHRTeW1ib2xJbmRleDp7Y29uZmlndXJhYmxlOiEwfSxsZWZ0SnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4Ontjb25maWd1cmFibGU6ITB9LHZlcnRpY2FsUGxhY2VkVGV4dFN5bWJvbEluZGV4Ontjb25maWd1cmFibGU6ITB9LGtleTp7Y29uZmlndXJhYmxlOiEwfSx0ZXh0Qm94U3RhcnRJbmRleDp7Y29uZmlndXJhYmxlOiEwfSx0ZXh0Qm94RW5kSW5kZXg6e2NvbmZpZ3VyYWJsZTohMH0saWNvbkJveFN0YXJ0SW5kZXg6e2NvbmZpZ3VyYWJsZTohMH0saWNvbkJveEVuZEluZGV4Ontjb25maWd1cmFibGU6ITB9LGZlYXR1cmVJbmRleDp7Y29uZmlndXJhYmxlOiEwfSxudW1Ib3Jpem9udGFsR2x5cGhWZXJ0aWNlczp7Y29uZmlndXJhYmxlOiEwfSxudW1WZXJ0aWNhbEdseXBoVmVydGljZXM6e2NvbmZpZ3VyYWJsZTohMH0sbnVtSWNvblZlcnRpY2VzOntjb25maWd1cmFibGU6ITB9LGNyb3NzVGlsZUlEOntjb25maWd1cmFibGU6ITB9LHRleHRCb3hTY2FsZTp7Y29uZmlndXJhYmxlOiEwfSxyYWRpYWxUZXh0T2Zmc2V0Ontjb25maWd1cmFibGU6ITB9fTtyZXR1cm4gci5hbmNob3JYLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzBdfSxyLmFuY2hvclguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMF09dDt9LHIuYW5jaG9yWS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisxXX0sci5hbmNob3JZLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzFdPXQ7fSxyLnJpZ2h0SnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzJdfSxyLnJpZ2h0SnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzJdPXQ7fSxyLmNlbnRlckp1c3RpZmllZFRleHRTeW1ib2xJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMiszXX0sci5jZW50ZXJKdXN0aWZpZWRUZXh0U3ltYm9sSW5kZXguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrM109dDt9LHIubGVmdEp1c3RpZmllZFRleHRTeW1ib2xJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMis0XX0sci5sZWZ0SnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzRdPXQ7fSxyLnZlcnRpY2FsUGxhY2VkVGV4dFN5bWJvbEluZGV4LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzVdfSxyLnZlcnRpY2FsUGxhY2VkVGV4dFN5bWJvbEluZGV4LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzVdPXQ7fSxyLmtleS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrNl19LHIua2V5LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMis2XT10O30sci50ZXh0Qm94U3RhcnRJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrN119LHIudGV4dEJveFN0YXJ0SW5kZXguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzddPXQ7fSxyLnRleHRCb3hFbmRJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrOF19LHIudGV4dEJveEVuZEluZGV4LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMis4XT10O30sci5pY29uQm94U3RhcnRJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrOV19LHIuaWNvbkJveFN0YXJ0SW5kZXguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzldPXQ7fSxyLmljb25Cb3hFbmRJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTBdfSxyLmljb25Cb3hFbmRJbmRleC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTBdPXQ7fSxyLmZlYXR1cmVJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTFdfSxyLmZlYXR1cmVJbmRleC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrMTFdPXQ7fSxyLm51bUhvcml6b250YWxHbHlwaFZlcnRpY2VzLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMisxMl19LHIubnVtSG9yaXpvbnRhbEdseXBoVmVydGljZXMuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzEyXT10O30sci5udW1WZXJ0aWNhbEdseXBoVmVydGljZXMuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzEzXX0sci5udW1WZXJ0aWNhbEdseXBoVmVydGljZXMuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzEzXT10O30sci5udW1JY29uVmVydGljZXMuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzE0XX0sci5udW1JY29uVmVydGljZXMuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzE0XT10O30sci5jcm9zc1RpbGVJRC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDMyW3RoaXMuX3BvczQrOF19LHIuY3Jvc3NUaWxlSUQuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQzMlt0aGlzLl9wb3M0KzhdPXQ7fSxyLnRleHRCb3hTY2FsZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuZmxvYXQzMlt0aGlzLl9wb3M0KzldfSxyLnRleHRCb3hTY2FsZS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuZmxvYXQzMlt0aGlzLl9wb3M0KzldPXQ7fSxyLnJhZGlhbFRleHRPZmZzZXQuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N0cnVjdEFycmF5LmZsb2F0MzJbdGhpcy5fcG9zNCsxMF19LHIucmFkaWFsVGV4dE9mZnNldC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuZmxvYXQzMlt0aGlzLl9wb3M0KzEwXT10O30sT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoZS5wcm90b3R5cGUsciksZX0oc2kpO0xpLnByb3RvdHlwZS5zaXplPTQ0O3ZhciBEaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBMaSh0aGlzLHQpfSxlfShBaSk7em4oXCJTeW1ib2xJbnN0YW5jZUFycmF5XCIsRGkpO3ZhciBPaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lO3ZhciByPXtvZmZzZXRYOntjb25maWd1cmFibGU6ITB9fTtyZXR1cm4gci5vZmZzZXRYLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5mbG9hdDMyW3RoaXMuX3BvczQrMF19LHIub2Zmc2V0WC5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc3RydWN0QXJyYXkuZmxvYXQzMlt0aGlzLl9wb3M0KzBdPXQ7fSxPYmplY3QuZGVmaW5lUHJvcGVydGllcyhlLnByb3RvdHlwZSxyKSxlfShzaSk7T2kucHJvdG90eXBlLnNpemU9NDt2YXIgUmk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0b2Zmc2V0WD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5mbG9hdDMyWzEqdCswXX0sZS5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgT2kodGhpcyx0KX0sZX0oU2kpO3puKFwiR2x5cGhPZmZzZXRBcnJheVwiLFJpKTt2YXIgVWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO310JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZTt2YXIgcj17eDp7Y29uZmlndXJhYmxlOiEwfSx5Ontjb25maWd1cmFibGU6ITB9LHRpbGVVbml0RGlzdGFuY2VGcm9tQW5jaG9yOntjb25maWd1cmFibGU6ITB9fTtyZXR1cm4gci54LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzBdfSxyLnguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LmludDE2W3RoaXMuX3BvczIrMF09dDt9LHIueS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkuaW50MTZbdGhpcy5fcG9zMisxXX0sci55LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzFdPXQ7fSxyLnRpbGVVbml0RGlzdGFuY2VGcm9tQW5jaG9yLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzJdfSxyLnRpbGVVbml0RGlzdGFuY2VGcm9tQW5jaG9yLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS5pbnQxNlt0aGlzLl9wb3MyKzJdPXQ7fSxPYmplY3QuZGVmaW5lUHJvcGVydGllcyhlLnByb3RvdHlwZSxyKSxlfShzaSk7VWkucHJvdG90eXBlLnNpemU9Njt2YXIgamk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0eD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5pbnQxNlszKnQrMF19LGUucHJvdG90eXBlLmdldHk9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuaW50MTZbMyp0KzFdfSxlLnByb3RvdHlwZS5nZXR0aWxlVW5pdERpc3RhbmNlRnJvbUFuY2hvcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5pbnQxNlszKnQrMl19LGUucHJvdG90eXBlLmdldD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IFVpKHRoaXMsdCl9LGV9KGtpKTt6bihcIlN5bWJvbExpbmVWZXJ0ZXhBcnJheVwiLGppKTt2YXIgcWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO310JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZTt2YXIgcj17ZmVhdHVyZUluZGV4Ontjb25maWd1cmFibGU6ITB9LHNvdXJjZUxheWVySW5kZXg6e2NvbmZpZ3VyYWJsZTohMH0sYnVja2V0SW5kZXg6e2NvbmZpZ3VyYWJsZTohMH19O3JldHVybiByLmZlYXR1cmVJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDMyW3RoaXMuX3BvczQrMF19LHIuZmVhdHVyZUluZGV4LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS51aW50MzJbdGhpcy5fcG9zNCswXT10O30sci5zb3VyY2VMYXllckluZGV4LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMisyXX0sci5zb3VyY2VMYXllckluZGV4LnNldD1mdW5jdGlvbih0KXt0aGlzLl9zdHJ1Y3RBcnJheS51aW50MTZbdGhpcy5fcG9zMisyXT10O30sci5idWNrZXRJbmRleC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RydWN0QXJyYXkudWludDE2W3RoaXMuX3BvczIrM119LHIuYnVja2V0SW5kZXguc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3N0cnVjdEFycmF5LnVpbnQxNlt0aGlzLl9wb3MyKzNdPXQ7fSxPYmplY3QuZGVmaW5lUHJvcGVydGllcyhlLnByb3RvdHlwZSxyKSxlfShzaSk7cWkucHJvdG90eXBlLnNpemU9ODt2YXIgTmk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgcWkodGhpcyx0KX0sZX0oemkpO3puKFwiRmVhdHVyZUluZGV4QXJyYXlcIixOaSk7dmFyIFppPWxpKFt7bmFtZTpcImFfcG9zXCIsY29tcG9uZW50czoyLHR5cGU6XCJJbnQxNlwifV0sNCkubWVtYmVycyxLaT1mdW5jdGlvbih0KXt2b2lkIDA9PT10JiYodD1bXSksdGhpcy5zZWdtZW50cz10O307ZnVuY3Rpb24gR2kodCxlKXtyZXR1cm4gMjU2Kih0PWwoTWF0aC5mbG9vcih0KSwwLDI1NSkpKyhlPWwoTWF0aC5mbG9vcihlKSwwLDI1NSkpfUtpLnByb3RvdHlwZS5wcmVwYXJlU2VnbWVudD1mdW5jdGlvbih0LGUscixuKXt2YXIgaT10aGlzLnNlZ21lbnRzW3RoaXMuc2VnbWVudHMubGVuZ3RoLTFdO3JldHVybiB0PktpLk1BWF9WRVJURVhfQVJSQVlfTEVOR1RIJiZ3KFwiTWF4IHZlcnRpY2VzIHBlciBzZWdtZW50IGlzIFwiK0tpLk1BWF9WRVJURVhfQVJSQVlfTEVOR1RIK1wiOiBidWNrZXQgcmVxdWVzdGVkIFwiK3QpLCghaXx8aS52ZXJ0ZXhMZW5ndGgrdD5LaS5NQVhfVkVSVEVYX0FSUkFZX0xFTkdUSHx8aS5zb3J0S2V5IT09bikmJihpPXt2ZXJ0ZXhPZmZzZXQ6ZS5sZW5ndGgscHJpbWl0aXZlT2Zmc2V0OnIubGVuZ3RoLHZlcnRleExlbmd0aDowLHByaW1pdGl2ZUxlbmd0aDowfSx2b2lkIDAhPT1uJiYoaS5zb3J0S2V5PW4pLHRoaXMuc2VnbWVudHMucHVzaChpKSksaX0sS2kucHJvdG90eXBlLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNlZ21lbnRzfSxLaS5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe2Zvcih2YXIgdD0wLGU9dGhpcy5zZWdtZW50czt0PGUubGVuZ3RoO3QrPTEpe3ZhciByPWVbdF07Zm9yKHZhciBuIGluIHIudmFvcylyLnZhb3Nbbl0uZGVzdHJveSgpO319LEtpLnNpbXBsZVNlZ21lbnQ9ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuIG5ldyBLaShbe3ZlcnRleE9mZnNldDp0LHByaW1pdGl2ZU9mZnNldDplLHZlcnRleExlbmd0aDpyLHByaW1pdGl2ZUxlbmd0aDpuLHZhb3M6e30sc29ydEtleTowfV0pfSxLaS5NQVhfVkVSVEVYX0FSUkFZX0xFTkdUSD1NYXRoLnBvdygyLDE2KS0xLHpuKFwiU2VnbWVudFZlY3RvclwiLEtpKTt2YXIgWGk9ZnVuY3Rpb24oKXt0aGlzLmlkcz1bXSx0aGlzLnBvc2l0aW9ucz1bXSx0aGlzLmluZGV4ZWQ9ITE7fTtmdW5jdGlvbiBKaSh0LGUscil7dmFyIG49dFtlXTt0W2VdPXRbcl0sdFtyXT1uO31YaS5wcm90b3R5cGUuYWRkPWZ1bmN0aW9uKHQsZSxyLG4pe3RoaXMuaWRzLnB1c2godCksdGhpcy5wb3NpdGlvbnMucHVzaChlLHIsbik7fSxYaS5wcm90b3R5cGUuZ2V0UG9zaXRpb25zPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT0wLHI9dGhpcy5pZHMubGVuZ3RoLTE7ZTxyOyl7dmFyIG49ZStyPj4xO3RoaXMuaWRzW25dPj10P3I9bjplPW4rMTt9Zm9yKHZhciBpPVtdO3RoaXMuaWRzW2VdPT09dDspe3ZhciBhPXRoaXMucG9zaXRpb25zWzMqZV0sbz10aGlzLnBvc2l0aW9uc1szKmUrMV0scz10aGlzLnBvc2l0aW9uc1szKmUrMl07aS5wdXNoKHtpbmRleDphLHN0YXJ0Om8sZW5kOnN9KSxlKys7fXJldHVybiBpfSxYaS5zZXJpYWxpemU9ZnVuY3Rpb24odCxlKXt2YXIgcj1uZXcgRmxvYXQ2NEFycmF5KHQuaWRzKSxuPW5ldyBVaW50MzJBcnJheSh0LnBvc2l0aW9ucyk7cmV0dXJuIGZ1bmN0aW9uIHQoZSxyLG4saSl7aWYobj49aSlyZXR1cm47dmFyIGE9ZVtuK2k+PjFdO3ZhciBvPW4tMTt2YXIgcz1pKzE7Zm9yKDs7KXtkb3tvKys7fXdoaWxlKGVbb108YSk7ZG97cy0tO313aGlsZShlW3NdPmEpO2lmKG8+PXMpYnJlYWs7SmkoZSxvLHMpLEppKHIsMypvLDMqcyksSmkociwzKm8rMSwzKnMrMSksSmkociwzKm8rMiwzKnMrMik7fXQoZSxyLG4scyk7dChlLHIscysxLGkpO30ocixuLDAsci5sZW5ndGgtMSksZS5wdXNoKHIuYnVmZmVyLG4uYnVmZmVyKSx7aWRzOnIscG9zaXRpb25zOm59fSxYaS5kZXNlcmlhbGl6ZT1mdW5jdGlvbih0KXt2YXIgZT1uZXcgWGk7cmV0dXJuIGUuaWRzPXQuaWRzLGUucG9zaXRpb25zPXQucG9zaXRpb25zLGUuaW5kZXhlZD0hMCxlfSx6bihcIkZlYXR1cmVQb3NpdGlvbk1hcFwiLFhpKTt2YXIgSGk9ZnVuY3Rpb24odCxlKXt0aGlzLmdsPXQuZ2wsdGhpcy5sb2NhdGlvbj1lO30sWWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlLHIpe3QuY2FsbCh0aGlzLGUsciksdGhpcy5jdXJyZW50PTA7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5jdXJyZW50IT09dCYmKHRoaXMuY3VycmVudD10LHRoaXMuZ2wudW5pZm9ybTFpKHRoaXMubG9jYXRpb24sdCkpO30sZX0oSGkpLCRpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSxyKXt0LmNhbGwodGhpcyxlLHIpLHRoaXMuY3VycmVudD0wO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuY3VycmVudCE9PXQmJih0aGlzLmN1cnJlbnQ9dCx0aGlzLmdsLnVuaWZvcm0xZih0aGlzLmxvY2F0aW9uLHQpKTt9LGV9KEhpKSxXaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUscil7dC5jYWxsKHRoaXMsZSxyKSx0aGlzLmN1cnJlbnQ9WzAsMF07fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dFswXT09PXRoaXMuY3VycmVudFswXSYmdFsxXT09PXRoaXMuY3VycmVudFsxXXx8KHRoaXMuY3VycmVudD10LHRoaXMuZ2wudW5pZm9ybTJmKHRoaXMubG9jYXRpb24sdFswXSx0WzFdKSk7fSxlfShIaSksUWk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlLHIpe3QuY2FsbCh0aGlzLGUsciksdGhpcy5jdXJyZW50PVswLDAsMF07fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dFswXT09PXRoaXMuY3VycmVudFswXSYmdFsxXT09PXRoaXMuY3VycmVudFsxXSYmdFsyXT09PXRoaXMuY3VycmVudFsyXXx8KHRoaXMuY3VycmVudD10LHRoaXMuZ2wudW5pZm9ybTNmKHRoaXMubG9jYXRpb24sdFswXSx0WzFdLHRbMl0pKTt9LGV9KEhpKSx0YT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUscil7dC5jYWxsKHRoaXMsZSxyKSx0aGlzLmN1cnJlbnQ9WzAsMCwwLDBdO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe3RbMF09PT10aGlzLmN1cnJlbnRbMF0mJnRbMV09PT10aGlzLmN1cnJlbnRbMV0mJnRbMl09PT10aGlzLmN1cnJlbnRbMl0mJnRbM109PT10aGlzLmN1cnJlbnRbM118fCh0aGlzLmN1cnJlbnQ9dCx0aGlzLmdsLnVuaWZvcm00Zih0aGlzLmxvY2F0aW9uLHRbMF0sdFsxXSx0WzJdLHRbM10pKTt9LGV9KEhpKSxlYT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUscil7dC5jYWxsKHRoaXMsZSxyKSx0aGlzLmN1cnJlbnQ9YWUudHJhbnNwYXJlbnQ7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dC5yPT09dGhpcy5jdXJyZW50LnImJnQuZz09PXRoaXMuY3VycmVudC5nJiZ0LmI9PT10aGlzLmN1cnJlbnQuYiYmdC5hPT09dGhpcy5jdXJyZW50LmF8fCh0aGlzLmN1cnJlbnQ9dCx0aGlzLmdsLnVuaWZvcm00Zih0aGlzLmxvY2F0aW9uLHQucix0LmcsdC5iLHQuYSkpO30sZX0oSGkpLHJhPW5ldyBGbG9hdDMyQXJyYXkoMTYpLG5hPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSxyKXt0LmNhbGwodGhpcyxlLHIpLHRoaXMuY3VycmVudD1yYTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0WzEyXSE9PXRoaXMuY3VycmVudFsxMl18fHRbMF0hPT10aGlzLmN1cnJlbnRbMF0pcmV0dXJuIHRoaXMuY3VycmVudD10LHZvaWQgdGhpcy5nbC51bmlmb3JtTWF0cml4NGZ2KHRoaXMubG9jYXRpb24sITEsdCk7Zm9yKHZhciBlPTE7ZTwxNjtlKyspaWYodFtlXSE9PXRoaXMuY3VycmVudFtlXSl7dGhpcy5jdXJyZW50PXQsdGhpcy5nbC51bmlmb3JtTWF0cml4NGZ2KHRoaXMubG9jYXRpb24sITEsdCk7YnJlYWt9fSxlfShIaSk7ZnVuY3Rpb24gaWEodCl7cmV0dXJuIFtHaSgyNTUqdC5yLDI1NSp0LmcpLEdpKDI1NSp0LmIsMjU1KnQuYSldfXZhciBhYT1mdW5jdGlvbih0LGUscil7dGhpcy52YWx1ZT10LHRoaXMubmFtZXM9ZSx0aGlzLnVuaWZvcm1OYW1lcz10aGlzLm5hbWVzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gXCJ1X1wiK3R9KSx0aGlzLnR5cGU9cix0aGlzLm1heFZhbHVlPS0xLzA7fTthYS5wcm90b3R5cGUuZGVmaW5lcz1mdW5jdGlvbigpe3JldHVybiB0aGlzLm5hbWVzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gXCIjZGVmaW5lIEhBU19VTklGT1JNX3VfXCIrdH0pfSxhYS5wcm90b3R5cGUuc2V0Q29uc3RhbnRQYXR0ZXJuUG9zaXRpb25zPWZ1bmN0aW9uKCl7fSxhYS5wcm90b3R5cGUucG9wdWxhdGVQYWludEFycmF5PWZ1bmN0aW9uKCl7fSxhYS5wcm90b3R5cGUudXBkYXRlUGFpbnRBcnJheT1mdW5jdGlvbigpe30sYWEucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbigpe30sYWEucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt9LGFhLnByb3RvdHlwZS5zZXRVbmlmb3Jtcz1mdW5jdGlvbih0LGUscixuKXtlLnNldChuLmNvbnN0YW50T3IodGhpcy52YWx1ZSkpO30sYWEucHJvdG90eXBlLmdldEJpbmRpbmc9ZnVuY3Rpb24odCxlKXtyZXR1cm4gXCJjb2xvclwiPT09dGhpcy50eXBlP25ldyBlYSh0LGUpOm5ldyAkaSh0LGUpfSxhYS5zZXJpYWxpemU9ZnVuY3Rpb24odCl7dmFyIGU9dC52YWx1ZSxyPXQubmFtZXMsbj10LnR5cGU7cmV0dXJuIHt2YWx1ZTpCbihlKSxuYW1lczpyLHR5cGU6bn19LGFhLmRlc2VyaWFsaXplPWZ1bmN0aW9uKHQpe3ZhciBlPXQudmFsdWUscj10Lm5hbWVzLG49dC50eXBlO3JldHVybiBuZXcgYWEoQ24oZSkscixuKX07dmFyIG9hPWZ1bmN0aW9uKHQsZSxyKXt0aGlzLnZhbHVlPXQsdGhpcy5uYW1lcz1lLHRoaXMudW5pZm9ybU5hbWVzPXRoaXMubmFtZXMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBcInVfXCIrdH0pLHRoaXMudHlwZT1yLHRoaXMubWF4VmFsdWU9LTEvMCx0aGlzLnBhdHRlcm5Qb3NpdGlvbnM9e3BhdHRlcm5UbzpudWxsLHBhdHRlcm5Gcm9tOm51bGx9O307b2EucHJvdG90eXBlLmRlZmluZXM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5uYW1lcy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIFwiI2RlZmluZSBIQVNfVU5JRk9STV91X1wiK3R9KX0sb2EucHJvdG90eXBlLnBvcHVsYXRlUGFpbnRBcnJheT1mdW5jdGlvbigpe30sb2EucHJvdG90eXBlLnVwZGF0ZVBhaW50QXJyYXk9ZnVuY3Rpb24oKXt9LG9hLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24oKXt9LG9hLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7fSxvYS5wcm90b3R5cGUuc2V0Q29uc3RhbnRQYXR0ZXJuUG9zaXRpb25zPWZ1bmN0aW9uKHQsZSl7dGhpcy5wYXR0ZXJuUG9zaXRpb25zLnBhdHRlcm5Ubz10LnRsYnIsdGhpcy5wYXR0ZXJuUG9zaXRpb25zLnBhdHRlcm5Gcm9tPWUudGxicjt9LG9hLnByb3RvdHlwZS5zZXRVbmlmb3Jtcz1mdW5jdGlvbih0LGUscixuLGkpe3ZhciBhPXRoaXMucGF0dGVyblBvc2l0aW9ucztcInVfcGF0dGVybl90b1wiPT09aSYmYS5wYXR0ZXJuVG8mJmUuc2V0KGEucGF0dGVyblRvKSxcInVfcGF0dGVybl9mcm9tXCI9PT1pJiZhLnBhdHRlcm5Gcm9tJiZlLnNldChhLnBhdHRlcm5Gcm9tKTt9LG9hLnByb3RvdHlwZS5nZXRCaW5kaW5nPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIG5ldyB0YSh0LGUpfTt2YXIgc2E9ZnVuY3Rpb24odCxlLHIsbil7dGhpcy5leHByZXNzaW9uPXQsdGhpcy5uYW1lcz1lLHRoaXMudHlwZT1yLHRoaXMudW5pZm9ybU5hbWVzPXRoaXMubmFtZXMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBcImFfXCIrdH0pLHRoaXMubWF4VmFsdWU9LTEvMCx0aGlzLnBhaW50VmVydGV4QXR0cmlidXRlcz1lLm1hcChmdW5jdGlvbih0KXtyZXR1cm4ge25hbWU6XCJhX1wiK3QsdHlwZTpcIkZsb2F0MzJcIixjb21wb25lbnRzOlwiY29sb3JcIj09PXI/MjoxLG9mZnNldDowfX0pLHRoaXMucGFpbnRWZXJ0ZXhBcnJheT1uZXcgbjt9O3NhLnByb3RvdHlwZS5kZWZpbmVzPWZ1bmN0aW9uKCl7cmV0dXJuIFtdfSxzYS5wcm90b3R5cGUuc2V0Q29uc3RhbnRQYXR0ZXJuUG9zaXRpb25zPWZ1bmN0aW9uKCl7fSxzYS5wcm90b3R5cGUucG9wdWxhdGVQYWludEFycmF5PWZ1bmN0aW9uKHQsZSl7dmFyIHI9dGhpcy5wYWludFZlcnRleEFycmF5LG49ci5sZW5ndGg7ci5yZXNlcnZlKHQpO3ZhciBpPXRoaXMuZXhwcmVzc2lvbi5ldmFsdWF0ZShuZXcgWm4oMCksZSx7fSk7aWYoXCJjb2xvclwiPT09dGhpcy50eXBlKWZvcih2YXIgYT1pYShpKSxvPW47bzx0O28rKylyLmVtcGxhY2VCYWNrKGFbMF0sYVsxXSk7ZWxzZXtmb3IodmFyIHM9bjtzPHQ7cysrKXIuZW1wbGFjZUJhY2soaSk7dGhpcy5tYXhWYWx1ZT1NYXRoLm1heCh0aGlzLm1heFZhbHVlLGkpO319LHNhLnByb3RvdHlwZS51cGRhdGVQYWludEFycmF5PWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPXRoaXMucGFpbnRWZXJ0ZXhBcnJheSxhPXRoaXMuZXhwcmVzc2lvbi5ldmFsdWF0ZSh7em9vbTowfSxyLG4pO2lmKFwiY29sb3JcIj09PXRoaXMudHlwZSlmb3IodmFyIG89aWEoYSkscz10O3M8ZTtzKyspaS5lbXBsYWNlKHMsb1swXSxvWzFdKTtlbHNle2Zvcih2YXIgdT10O3U8ZTt1KyspaS5lbXBsYWNlKHUsYSk7dGhpcy5tYXhWYWx1ZT1NYXRoLm1heCh0aGlzLm1heFZhbHVlLGEpO319LHNhLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCl7dGhpcy5wYWludFZlcnRleEFycmF5JiZ0aGlzLnBhaW50VmVydGV4QXJyYXkuYXJyYXlCdWZmZXImJih0aGlzLnBhaW50VmVydGV4QnVmZmVyJiZ0aGlzLnBhaW50VmVydGV4QnVmZmVyLmJ1ZmZlcj90aGlzLnBhaW50VmVydGV4QnVmZmVyLnVwZGF0ZURhdGEodGhpcy5wYWludFZlcnRleEFycmF5KTp0aGlzLnBhaW50VmVydGV4QnVmZmVyPXQuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMucGFpbnRWZXJ0ZXhBcnJheSx0aGlzLnBhaW50VmVydGV4QXR0cmlidXRlcyx0aGlzLmV4cHJlc3Npb24uaXNTdGF0ZURlcGVuZGVudCkpO30sc2EucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLnBhaW50VmVydGV4QnVmZmVyJiZ0aGlzLnBhaW50VmVydGV4QnVmZmVyLmRlc3Ryb3koKTt9LHNhLnByb3RvdHlwZS5zZXRVbmlmb3Jtcz1mdW5jdGlvbih0LGUpe2Uuc2V0KDApO30sc2EucHJvdG90eXBlLmdldEJpbmRpbmc9ZnVuY3Rpb24odCxlKXtyZXR1cm4gbmV3ICRpKHQsZSl9O3ZhciB1YT1mdW5jdGlvbih0LGUscixuLGksYSl7dGhpcy5leHByZXNzaW9uPXQsdGhpcy5uYW1lcz1lLHRoaXMudW5pZm9ybU5hbWVzPXRoaXMubmFtZXMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBcInVfXCIrdCtcIl90XCJ9KSx0aGlzLnR5cGU9cix0aGlzLnVzZUludGVnZXJab29tPW4sdGhpcy56b29tPWksdGhpcy5tYXhWYWx1ZT0tMS8wO3ZhciBvPWE7dGhpcy5wYWludFZlcnRleEF0dHJpYnV0ZXM9ZS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHtuYW1lOlwiYV9cIit0LHR5cGU6XCJGbG9hdDMyXCIsY29tcG9uZW50czpcImNvbG9yXCI9PT1yPzQ6MixvZmZzZXQ6MH19KSx0aGlzLnBhaW50VmVydGV4QXJyYXk9bmV3IG87fTt1YS5wcm90b3R5cGUuZGVmaW5lcz1mdW5jdGlvbigpe3JldHVybiBbXX0sdWEucHJvdG90eXBlLnNldENvbnN0YW50UGF0dGVyblBvc2l0aW9ucz1mdW5jdGlvbigpe30sdWEucHJvdG90eXBlLnBvcHVsYXRlUGFpbnRBcnJheT1mdW5jdGlvbih0LGUpe3ZhciByPXRoaXMucGFpbnRWZXJ0ZXhBcnJheSxuPXIubGVuZ3RoO3IucmVzZXJ2ZSh0KTt2YXIgaT10aGlzLmV4cHJlc3Npb24uZXZhbHVhdGUobmV3IFpuKHRoaXMuem9vbSksZSx7fSksYT10aGlzLmV4cHJlc3Npb24uZXZhbHVhdGUobmV3IFpuKHRoaXMuem9vbSsxKSxlLHt9KTtpZihcImNvbG9yXCI9PT10aGlzLnR5cGUpZm9yKHZhciBvPWlhKGkpLHM9aWEoYSksdT1uO3U8dDt1Kyspci5lbXBsYWNlQmFjayhvWzBdLG9bMV0sc1swXSxzWzFdKTtlbHNle2Zvcih2YXIgbD1uO2w8dDtsKyspci5lbXBsYWNlQmFjayhpLGEpO3RoaXMubWF4VmFsdWU9TWF0aC5tYXgodGhpcy5tYXhWYWx1ZSxpLGEpO319LHVhLnByb3RvdHlwZS51cGRhdGVQYWludEFycmF5PWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpPXRoaXMucGFpbnRWZXJ0ZXhBcnJheSxhPXRoaXMuZXhwcmVzc2lvbi5ldmFsdWF0ZSh7em9vbTp0aGlzLnpvb219LHIsbiksbz10aGlzLmV4cHJlc3Npb24uZXZhbHVhdGUoe3pvb206dGhpcy56b29tKzF9LHIsbik7aWYoXCJjb2xvclwiPT09dGhpcy50eXBlKWZvcih2YXIgcz1pYShhKSx1PWlhKG8pLGw9dDtsPGU7bCsrKWkuZW1wbGFjZShsLHNbMF0sc1sxXSx1WzBdLHVbMV0pO2Vsc2V7Zm9yKHZhciBwPXQ7cDxlO3ArKylpLmVtcGxhY2UocCxhLG8pO3RoaXMubWF4VmFsdWU9TWF0aC5tYXgodGhpcy5tYXhWYWx1ZSxhLG8pO319LHVhLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCl7dGhpcy5wYWludFZlcnRleEFycmF5JiZ0aGlzLnBhaW50VmVydGV4QXJyYXkuYXJyYXlCdWZmZXImJih0aGlzLnBhaW50VmVydGV4QnVmZmVyJiZ0aGlzLnBhaW50VmVydGV4QnVmZmVyLmJ1ZmZlcj90aGlzLnBhaW50VmVydGV4QnVmZmVyLnVwZGF0ZURhdGEodGhpcy5wYWludFZlcnRleEFycmF5KTp0aGlzLnBhaW50VmVydGV4QnVmZmVyPXQuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMucGFpbnRWZXJ0ZXhBcnJheSx0aGlzLnBhaW50VmVydGV4QXR0cmlidXRlcyx0aGlzLmV4cHJlc3Npb24uaXNTdGF0ZURlcGVuZGVudCkpO30sdWEucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLnBhaW50VmVydGV4QnVmZmVyJiZ0aGlzLnBhaW50VmVydGV4QnVmZmVyLmRlc3Ryb3koKTt9LHVhLnByb3RvdHlwZS5pbnRlcnBvbGF0aW9uRmFjdG9yPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnVzZUludGVnZXJab29tP3RoaXMuZXhwcmVzc2lvbi5pbnRlcnBvbGF0aW9uRmFjdG9yKE1hdGguZmxvb3IodCksdGhpcy56b29tLHRoaXMuem9vbSsxKTp0aGlzLmV4cHJlc3Npb24uaW50ZXJwb2xhdGlvbkZhY3Rvcih0LHRoaXMuem9vbSx0aGlzLnpvb20rMSl9LHVhLnByb3RvdHlwZS5zZXRVbmlmb3Jtcz1mdW5jdGlvbih0LGUscil7ZS5zZXQodGhpcy5pbnRlcnBvbGF0aW9uRmFjdG9yKHIuem9vbSkpO30sdWEucHJvdG90eXBlLmdldEJpbmRpbmc9ZnVuY3Rpb24odCxlKXtyZXR1cm4gbmV3ICRpKHQsZSl9O3ZhciBsYT1mdW5jdGlvbih0LGUscixuLGksYSxvKXt0aGlzLmV4cHJlc3Npb249dCx0aGlzLm5hbWVzPWUsdGhpcy50eXBlPXIsdGhpcy51bmlmb3JtTmFtZXM9dGhpcy5uYW1lcy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIFwidV9cIit0K1wiX3RcIn0pLHRoaXMudXNlSW50ZWdlclpvb209bix0aGlzLnpvb209aSx0aGlzLm1heFZhbHVlPS0xLzAsdGhpcy5sYXllcklkPW8sdGhpcy5wYWludFZlcnRleEF0dHJpYnV0ZXM9ZS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHtuYW1lOlwiYV9cIit0LHR5cGU6XCJVaW50MTZcIixjb21wb25lbnRzOjQsb2Zmc2V0OjB9fSksdGhpcy56b29tSW5QYWludFZlcnRleEFycmF5PW5ldyBhLHRoaXMuem9vbU91dFBhaW50VmVydGV4QXJyYXk9bmV3IGE7fTtsYS5wcm90b3R5cGUuZGVmaW5lcz1mdW5jdGlvbigpe3JldHVybiBbXX0sbGEucHJvdG90eXBlLnNldENvbnN0YW50UGF0dGVyblBvc2l0aW9ucz1mdW5jdGlvbigpe30sbGEucHJvdG90eXBlLnBvcHVsYXRlUGFpbnRBcnJheT1mdW5jdGlvbih0LGUscil7dmFyIG49dGhpcy56b29tSW5QYWludFZlcnRleEFycmF5LGk9dGhpcy56b29tT3V0UGFpbnRWZXJ0ZXhBcnJheSxhPXRoaXMubGF5ZXJJZCxvPW4ubGVuZ3RoO2lmKG4ucmVzZXJ2ZSh0KSxpLnJlc2VydmUodCksciYmZS5wYXR0ZXJucyYmZS5wYXR0ZXJuc1thXSl7dmFyIHM9ZS5wYXR0ZXJuc1thXSx1PXMubWluLGw9cy5taWQscD1zLm1heCxjPXJbdV0saD1yW2xdLGY9cltwXTtpZighY3x8IWh8fCFmKXJldHVybjtmb3IodmFyIHk9bzt5PHQ7eSsrKW4uZW1wbGFjZUJhY2soaC50bFswXSxoLnRsWzFdLGguYnJbMF0saC5iclsxXSxjLnRsWzBdLGMudGxbMV0sYy5iclswXSxjLmJyWzFdKSxpLmVtcGxhY2VCYWNrKGgudGxbMF0saC50bFsxXSxoLmJyWzBdLGguYnJbMV0sZi50bFswXSxmLnRsWzFdLGYuYnJbMF0sZi5iclsxXSk7fX0sbGEucHJvdG90eXBlLnVwZGF0ZVBhaW50QXJyYXk9ZnVuY3Rpb24odCxlLHIsbixpKXt2YXIgYT10aGlzLnpvb21JblBhaW50VmVydGV4QXJyYXksbz10aGlzLnpvb21PdXRQYWludFZlcnRleEFycmF5LHM9dGhpcy5sYXllcklkO2lmKGkmJnIucGF0dGVybnMmJnIucGF0dGVybnNbc10pe3ZhciB1PXIucGF0dGVybnNbc10sbD11Lm1pbixwPXUubWlkLGM9dS5tYXgsaD1pW2xdLGY9aVtwXSx5PWlbY107aWYoIWh8fCFmfHwheSlyZXR1cm47Zm9yKHZhciBkPXQ7ZDxlO2QrKylhLmVtcGxhY2UoZCxmLnRsWzBdLGYudGxbMV0sZi5iclswXSxmLmJyWzFdLGgudGxbMF0saC50bFsxXSxoLmJyWzBdLGguYnJbMV0pLG8uZW1wbGFjZShkLGYudGxbMF0sZi50bFsxXSxmLmJyWzBdLGYuYnJbMV0seS50bFswXSx5LnRsWzFdLHkuYnJbMF0seS5iclsxXSk7fX0sbGEucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbih0KXt0aGlzLnpvb21JblBhaW50VmVydGV4QXJyYXkmJnRoaXMuem9vbUluUGFpbnRWZXJ0ZXhBcnJheS5hcnJheUJ1ZmZlciYmdGhpcy56b29tT3V0UGFpbnRWZXJ0ZXhBcnJheSYmdGhpcy56b29tT3V0UGFpbnRWZXJ0ZXhBcnJheS5hcnJheUJ1ZmZlciYmKHRoaXMuem9vbUluUGFpbnRWZXJ0ZXhCdWZmZXI9dC5jcmVhdGVWZXJ0ZXhCdWZmZXIodGhpcy56b29tSW5QYWludFZlcnRleEFycmF5LHRoaXMucGFpbnRWZXJ0ZXhBdHRyaWJ1dGVzLHRoaXMuZXhwcmVzc2lvbi5pc1N0YXRlRGVwZW5kZW50KSx0aGlzLnpvb21PdXRQYWludFZlcnRleEJ1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLnpvb21PdXRQYWludFZlcnRleEFycmF5LHRoaXMucGFpbnRWZXJ0ZXhBdHRyaWJ1dGVzLHRoaXMuZXhwcmVzc2lvbi5pc1N0YXRlRGVwZW5kZW50KSk7fSxsYS5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMuem9vbU91dFBhaW50VmVydGV4QnVmZmVyJiZ0aGlzLnpvb21PdXRQYWludFZlcnRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy56b29tSW5QYWludFZlcnRleEJ1ZmZlciYmdGhpcy56b29tSW5QYWludFZlcnRleEJ1ZmZlci5kZXN0cm95KCk7fSxsYS5wcm90b3R5cGUuc2V0VW5pZm9ybXM9ZnVuY3Rpb24odCxlKXtlLnNldCgwKTt9LGxhLnByb3RvdHlwZS5nZXRCaW5kaW5nPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIG5ldyAkaSh0LGUpfTt2YXIgcGE9ZnVuY3Rpb24oKXt0aGlzLmJpbmRlcnM9e30sdGhpcy5jYWNoZUtleT1cIlwiLHRoaXMuX2J1ZmZlcnM9W10sdGhpcy5fZmVhdHVyZU1hcD1uZXcgWGksdGhpcy5fYnVmZmVyT2Zmc2V0PTA7fTtwYS5jcmVhdGVEeW5hbWljPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj1uZXcgcGEsaT1bXTtmb3IodmFyIGEgaW4gdC5wYWludC5fdmFsdWVzKWlmKHIoYSkpe3ZhciBvPXQucGFpbnQuZ2V0KGEpO2lmKG8gaW5zdGFuY2VvZiAkbiYmd3Ioby5wcm9wZXJ0eS5zcGVjaWZpY2F0aW9uKSl7dmFyIHM9aGEoYSx0LnR5cGUpLHU9by5wcm9wZXJ0eS5zcGVjaWZpY2F0aW9uLnR5cGUsbD1vLnByb3BlcnR5LnVzZUludGVnZXJab29tO2lmKFwiY3Jvc3MtZmFkZWRcIj09PW8ucHJvcGVydHkuc3BlY2lmaWNhdGlvbltcInByb3BlcnR5LXR5cGVcIl18fFwiY3Jvc3MtZmFkZWQtZGF0YS1kcml2ZW5cIj09PW8ucHJvcGVydHkuc3BlY2lmaWNhdGlvbltcInByb3BlcnR5LXR5cGVcIl0paWYoXCJjb25zdGFudFwiPT09by52YWx1ZS5raW5kKW4uYmluZGVyc1thXT1uZXcgb2Eoby52YWx1ZS52YWx1ZSxzLHUpLGkucHVzaChcIi91X1wiK2EpO2Vsc2V7dmFyIHA9ZmEoYSx1LFwic291cmNlXCIpO24uYmluZGVyc1thXT1uZXcgbGEoby52YWx1ZSxzLHUsbCxlLHAsdC5pZCksaS5wdXNoKFwiL2FfXCIrYSk7fWVsc2UgaWYoXCJjb25zdGFudFwiPT09by52YWx1ZS5raW5kKW4uYmluZGVyc1thXT1uZXcgYWEoby52YWx1ZS52YWx1ZSxzLHUpLGkucHVzaChcIi91X1wiK2EpO2Vsc2UgaWYoXCJzb3VyY2VcIj09PW8udmFsdWUua2luZCl7dmFyIGM9ZmEoYSx1LFwic291cmNlXCIpO24uYmluZGVyc1thXT1uZXcgc2Eoby52YWx1ZSxzLHUsYyksaS5wdXNoKFwiL2FfXCIrYSk7fWVsc2V7dmFyIGg9ZmEoYSx1LFwiY29tcG9zaXRlXCIpO24uYmluZGVyc1thXT1uZXcgdWEoby52YWx1ZSxzLHUsbCxlLGgpLGkucHVzaChcIi96X1wiK2EpO319fXJldHVybiBuLmNhY2hlS2V5PWkuc29ydCgpLmpvaW4oXCJcIiksbn0scGEucHJvdG90eXBlLnBvcHVsYXRlUGFpbnRBcnJheXM9ZnVuY3Rpb24odCxlLHIsbil7Zm9yKHZhciBpIGluIHRoaXMuYmluZGVycyl7dGhpcy5iaW5kZXJzW2ldLnBvcHVsYXRlUGFpbnRBcnJheSh0LGUsbik7fXZvaWQgMCE9PWUuaWQmJnRoaXMuX2ZlYXR1cmVNYXAuYWRkKCtlLmlkLHIsdGhpcy5fYnVmZmVyT2Zmc2V0LHQpLHRoaXMuX2J1ZmZlck9mZnNldD10O30scGEucHJvdG90eXBlLnNldENvbnN0YW50UGF0dGVyblBvc2l0aW9ucz1mdW5jdGlvbih0LGUpe2Zvcih2YXIgciBpbiB0aGlzLmJpbmRlcnMpe3RoaXMuYmluZGVyc1tyXS5zZXRDb25zdGFudFBhdHRlcm5Qb3NpdGlvbnModCxlKTt9fSxwYS5wcm90b3R5cGUudXBkYXRlUGFpbnRBcnJheXM9ZnVuY3Rpb24odCxlLHIsbil7dmFyIGk9ITE7Zm9yKHZhciBhIGluIHQpZm9yKHZhciBvPTAscz10aGlzLl9mZWF0dXJlTWFwLmdldFBvc2l0aW9ucygrYSk7bzxzLmxlbmd0aDtvKz0xKXt2YXIgdT1zW29dLGw9ZS5mZWF0dXJlKHUuaW5kZXgpO2Zvcih2YXIgcCBpbiB0aGlzLmJpbmRlcnMpe3ZhciBjPXRoaXMuYmluZGVyc1twXTtpZighKGMgaW5zdGFuY2VvZiBhYXx8YyBpbnN0YW5jZW9mIG9hKSYmITA9PT1jLmV4cHJlc3Npb24uaXNTdGF0ZURlcGVuZGVudCl7dmFyIGg9ci5wYWludC5nZXQocCk7Yy5leHByZXNzaW9uPWgudmFsdWUsYy51cGRhdGVQYWludEFycmF5KHUuc3RhcnQsdS5lbmQsbCx0W2FdLG4pLGk9ITA7fX19cmV0dXJuIGl9LHBhLnByb3RvdHlwZS5kZWZpbmVzPWZ1bmN0aW9uKCl7dmFyIHQ9W107Zm9yKHZhciBlIGluIHRoaXMuYmluZGVycyl0LnB1c2guYXBwbHkodCx0aGlzLmJpbmRlcnNbZV0uZGVmaW5lcygpKTtyZXR1cm4gdH0scGEucHJvdG90eXBlLmdldFBhaW50VmVydGV4QnVmZmVycz1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9idWZmZXJzfSxwYS5wcm90b3R5cGUuZ2V0VW5pZm9ybXM9ZnVuY3Rpb24odCxlKXt2YXIgcj1bXTtmb3IodmFyIG4gaW4gdGhpcy5iaW5kZXJzKWZvcih2YXIgaT10aGlzLmJpbmRlcnNbbl0sYT0wLG89aS51bmlmb3JtTmFtZXM7YTxvLmxlbmd0aDthKz0xKXt2YXIgcz1vW2FdO2lmKGVbc10pe3ZhciB1PWkuZ2V0QmluZGluZyh0LGVbc10pO3IucHVzaCh7bmFtZTpzLHByb3BlcnR5Om4sYmluZGluZzp1fSk7fX1yZXR1cm4gcn0scGEucHJvdG90eXBlLnNldFVuaWZvcm1zPWZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgaT0wLGE9ZTtpPGEubGVuZ3RoO2krPTEpe3ZhciBvPWFbaV0scz1vLm5hbWUsdT1vLnByb3BlcnR5LGw9by5iaW5kaW5nO3RoaXMuYmluZGVyc1t1XS5zZXRVbmlmb3Jtcyh0LGwsbixyLmdldCh1KSxzKTt9fSxwYS5wcm90b3R5cGUudXBkYXRlUGF0dGVyblBhaW50QnVmZmVycz1mdW5jdGlvbih0KXt2YXIgZT1bXTtmb3IodmFyIHIgaW4gdGhpcy5iaW5kZXJzKXt2YXIgbj10aGlzLmJpbmRlcnNbcl07aWYobiBpbnN0YW5jZW9mIGxhKXt2YXIgaT0yPT09dC5mcm9tU2NhbGU/bi56b29tSW5QYWludFZlcnRleEJ1ZmZlcjpuLnpvb21PdXRQYWludFZlcnRleEJ1ZmZlcjtpJiZlLnB1c2goaSk7fWVsc2UobiBpbnN0YW5jZW9mIHNhfHxuIGluc3RhbmNlb2YgdWEpJiZuLnBhaW50VmVydGV4QnVmZmVyJiZlLnB1c2gobi5wYWludFZlcnRleEJ1ZmZlcik7fXRoaXMuX2J1ZmZlcnM9ZTt9LHBhLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCl7Zm9yKHZhciBlIGluIHRoaXMuYmluZGVycyl0aGlzLmJpbmRlcnNbZV0udXBsb2FkKHQpO3ZhciByPVtdO2Zvcih2YXIgbiBpbiB0aGlzLmJpbmRlcnMpe3ZhciBpPXRoaXMuYmluZGVyc1tuXTsoaSBpbnN0YW5jZW9mIHNhfHxpIGluc3RhbmNlb2YgdWEpJiZpLnBhaW50VmVydGV4QnVmZmVyJiZyLnB1c2goaS5wYWludFZlcnRleEJ1ZmZlcik7fXRoaXMuX2J1ZmZlcnM9cjt9LHBhLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMuYmluZGVycyl0aGlzLmJpbmRlcnNbdF0uZGVzdHJveSgpO307dmFyIGNhPWZ1bmN0aW9uKHQsZSxyLG4pe3ZvaWQgMD09PW4mJihuPWZ1bmN0aW9uKCl7cmV0dXJuICEwfSksdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnM9e307Zm9yKHZhciBpPTAsYT1lO2k8YS5sZW5ndGg7aSs9MSl7dmFyIG89YVtpXTt0aGlzLnByb2dyYW1Db25maWd1cmF0aW9uc1tvLmlkXT1wYS5jcmVhdGVEeW5hbWljKG8scixuKSx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9uc1tvLmlkXS5sYXlvdXRBdHRyaWJ1dGVzPXQ7fXRoaXMubmVlZHNVcGxvYWQ9ITE7fTtmdW5jdGlvbiBoYSh0LGUpe3JldHVybiB7XCJ0ZXh0LW9wYWNpdHlcIjpbXCJvcGFjaXR5XCJdLFwiaWNvbi1vcGFjaXR5XCI6W1wib3BhY2l0eVwiXSxcInRleHQtY29sb3JcIjpbXCJmaWxsX2NvbG9yXCJdLFwiaWNvbi1jb2xvclwiOltcImZpbGxfY29sb3JcIl0sXCJ0ZXh0LWhhbG8tY29sb3JcIjpbXCJoYWxvX2NvbG9yXCJdLFwiaWNvbi1oYWxvLWNvbG9yXCI6W1wiaGFsb19jb2xvclwiXSxcInRleHQtaGFsby1ibHVyXCI6W1wiaGFsb19ibHVyXCJdLFwiaWNvbi1oYWxvLWJsdXJcIjpbXCJoYWxvX2JsdXJcIl0sXCJ0ZXh0LWhhbG8td2lkdGhcIjpbXCJoYWxvX3dpZHRoXCJdLFwiaWNvbi1oYWxvLXdpZHRoXCI6W1wiaGFsb193aWR0aFwiXSxcImxpbmUtZ2FwLXdpZHRoXCI6W1wiZ2Fwd2lkdGhcIl0sXCJsaW5lLXBhdHRlcm5cIjpbXCJwYXR0ZXJuX3RvXCIsXCJwYXR0ZXJuX2Zyb21cIl0sXCJmaWxsLXBhdHRlcm5cIjpbXCJwYXR0ZXJuX3RvXCIsXCJwYXR0ZXJuX2Zyb21cIl0sXCJmaWxsLWV4dHJ1c2lvbi1wYXR0ZXJuXCI6W1wicGF0dGVybl90b1wiLFwicGF0dGVybl9mcm9tXCJdfVt0XXx8W3QucmVwbGFjZShlK1wiLVwiLFwiXCIpLnJlcGxhY2UoLy0vZyxcIl9cIildfWZ1bmN0aW9uIGZhKHQsZSxyKXt2YXIgbj17Y29sb3I6e3NvdXJjZTpFaSxjb21wb3NpdGU6TWl9LG51bWJlcjp7c291cmNlOlNpLGNvbXBvc2l0ZTpFaX19LGk9ZnVuY3Rpb24odCl7cmV0dXJuIHtcImxpbmUtcGF0dGVyblwiOntzb3VyY2U6ZGksY29tcG9zaXRlOmRpfSxcImZpbGwtcGF0dGVyblwiOntzb3VyY2U6ZGksY29tcG9zaXRlOmRpfSxcImZpbGwtZXh0cnVzaW9uLXBhdHRlcm5cIjp7c291cmNlOmRpLGNvbXBvc2l0ZTpkaX19W3RdfSh0KTtyZXR1cm4gaSYmaVtyXXx8bltlXVtyXX1jYS5wcm90b3R5cGUucG9wdWxhdGVQYWludEFycmF5cz1mdW5jdGlvbih0LGUscixuKXtmb3IodmFyIGkgaW4gdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMpdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnNbaV0ucG9wdWxhdGVQYWludEFycmF5cyh0LGUscixuKTt0aGlzLm5lZWRzVXBsb2FkPSEwO30sY2EucHJvdG90eXBlLnVwZGF0ZVBhaW50QXJyYXlzPWZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgaT0wLGE9cjtpPGEubGVuZ3RoO2krPTEpe3ZhciBvPWFbaV07dGhpcy5uZWVkc1VwbG9hZD10aGlzLnByb2dyYW1Db25maWd1cmF0aW9uc1tvLmlkXS51cGRhdGVQYWludEFycmF5cyh0LGUsbyxuKXx8dGhpcy5uZWVkc1VwbG9hZDt9fSxjYS5wcm90b3R5cGUuZ2V0PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnByb2dyYW1Db25maWd1cmF0aW9uc1t0XX0sY2EucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbih0KXtpZih0aGlzLm5lZWRzVXBsb2FkKXtmb3IodmFyIGUgaW4gdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMpdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnNbZV0udXBsb2FkKHQpO3RoaXMubmVlZHNVcGxvYWQ9ITE7fX0sY2EucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXtmb3IodmFyIHQgaW4gdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMpdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnNbdF0uZGVzdHJveSgpO30sem4oXCJDb25zdGFudEJpbmRlclwiLGFhKSx6bihcIkNyb3NzRmFkZWRDb25zdGFudEJpbmRlclwiLG9hKSx6bihcIlNvdXJjZUV4cHJlc3Npb25CaW5kZXJcIixzYSksem4oXCJDcm9zc0ZhZGVkQ29tcG9zaXRlQmluZGVyXCIsbGEpLHpuKFwiQ29tcG9zaXRlRXhwcmVzc2lvbkJpbmRlclwiLHVhKSx6bihcIlByb2dyYW1Db25maWd1cmF0aW9uXCIscGEse29taXQ6W1wiX2J1ZmZlcnNcIl19KSx6bihcIlByb2dyYW1Db25maWd1cmF0aW9uU2V0XCIsY2EpO3ZhciB5YT04MTkyO3ZhciBkYSxtYT0oZGE9MTYse21pbjotMSpNYXRoLnBvdygyLGRhLTEpLG1heDpNYXRoLnBvdygyLGRhLTEpLTF9KTtmdW5jdGlvbiB2YSh0KXtmb3IodmFyIGU9eWEvdC5leHRlbnQscj10LmxvYWRHZW9tZXRyeSgpLG49MDtuPHIubGVuZ3RoO24rKylmb3IodmFyIGk9cltuXSxhPTA7YTxpLmxlbmd0aDthKyspe3ZhciBvPWlbYV07by54PU1hdGgucm91bmQoby54KmUpLG8ueT1NYXRoLnJvdW5kKG8ueSplKSwoby54PG1hLm1pbnx8by54Pm1hLm1heHx8by55PG1hLm1pbnx8by55Pm1hLm1heCkmJncoXCJHZW9tZXRyeSBleGNlZWRzIGFsbG93ZWQgZXh0ZW50LCByZWR1Y2UgeW91ciB2ZWN0b3IgdGlsZSBidWZmZXIgc2l6ZVwiKTt9cmV0dXJuIHJ9ZnVuY3Rpb24gZ2EodCxlLHIsbixpKXt0LmVtcGxhY2VCYWNrKDIqZSsobisxKS8yLDIqcisoaSsxKS8yKTt9dmFyIHhhPWZ1bmN0aW9uKHQpe3RoaXMuem9vbT10Lnpvb20sdGhpcy5vdmVyc2NhbGluZz10Lm92ZXJzY2FsaW5nLHRoaXMubGF5ZXJzPXQubGF5ZXJzLHRoaXMubGF5ZXJJZHM9dGhpcy5sYXllcnMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkfSksdGhpcy5pbmRleD10LmluZGV4LHRoaXMuaGFzUGF0dGVybj0hMSx0aGlzLmxheW91dFZlcnRleEFycmF5PW5ldyBjaSx0aGlzLmluZGV4QXJyYXk9bmV3IElpLHRoaXMuc2VnbWVudHM9bmV3IEtpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zPW5ldyBjYShaaSx0LmxheWVycyx0Lnpvb20pLHRoaXMuc3RhdGVEZXBlbmRlbnRMYXllcklkcz10aGlzLmxheWVycy5maWx0ZXIoZnVuY3Rpb24odCl7cmV0dXJuIHQuaXNTdGF0ZURlcGVuZGVudCgpfSkubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkfSk7fTtmdW5jdGlvbiBiYSh0LGUpe2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7cisrKWlmKENhKGUsdFtyXSkpcmV0dXJuICEwO2Zvcih2YXIgbj0wO248ZS5sZW5ndGg7bisrKWlmKENhKHQsZVtuXSkpcmV0dXJuICEwO3JldHVybiAhIVNhKHQsZSl9ZnVuY3Rpb24gX2EodCxlLHIpe3JldHVybiAhIUNhKHQsZSl8fCEhemEoZSx0LHIpfWZ1bmN0aW9uIHdhKHQsZSl7aWYoMT09PXQubGVuZ3RoKXJldHVybiBCYShlLHRbMF0pO2Zvcih2YXIgcj0wO3I8ZS5sZW5ndGg7cisrKWZvcih2YXIgbj1lW3JdLGk9MDtpPG4ubGVuZ3RoO2krKylpZihDYSh0LG5baV0pKXJldHVybiAhMDtmb3IodmFyIGE9MDthPHQubGVuZ3RoO2ErKylpZihCYShlLHRbYV0pKXJldHVybiAhMDtmb3IodmFyIG89MDtvPGUubGVuZ3RoO28rKylpZihTYSh0LGVbb10pKXJldHVybiAhMDtyZXR1cm4gITF9ZnVuY3Rpb24gQWEodCxlLHIpe2lmKHQubGVuZ3RoPjEpe2lmKFNhKHQsZSkpcmV0dXJuICEwO2Zvcih2YXIgbj0wO248ZS5sZW5ndGg7bisrKWlmKHphKGVbbl0sdCxyKSlyZXR1cm4gITB9Zm9yKHZhciBpPTA7aTx0Lmxlbmd0aDtpKyspaWYoemEodFtpXSxlLHIpKXJldHVybiAhMDtyZXR1cm4gITF9ZnVuY3Rpb24gU2EodCxlKXtpZigwPT09dC5sZW5ndGh8fDA9PT1lLmxlbmd0aClyZXR1cm4gITE7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aC0xO3IrKylmb3IodmFyIG49dFtyXSxpPXRbcisxXSxhPTA7YTxlLmxlbmd0aC0xO2ErKyl7aWYoa2EobixpLGVbYV0sZVthKzFdKSlyZXR1cm4gITB9cmV0dXJuICExfWZ1bmN0aW9uIGthKHQsZSxyLG4pe3JldHVybiBBKHQscixuKSE9PUEoZSxyLG4pJiZBKHQsZSxyKSE9PUEodCxlLG4pfWZ1bmN0aW9uIHphKHQsZSxyKXt2YXIgbj1yKnI7aWYoMT09PWUubGVuZ3RoKXJldHVybiB0LmRpc3RTcXIoZVswXSk8bjtmb3IodmFyIGk9MTtpPGUubGVuZ3RoO2krKyl7aWYoSWEodCxlW2ktMV0sZVtpXSk8bilyZXR1cm4gITB9cmV0dXJuICExfWZ1bmN0aW9uIElhKHQsZSxyKXt2YXIgbj1lLmRpc3RTcXIocik7aWYoMD09PW4pcmV0dXJuIHQuZGlzdFNxcihlKTt2YXIgaT0oKHQueC1lLngpKihyLngtZS54KSsodC55LWUueSkqKHIueS1lLnkpKS9uO3JldHVybiBpPDA/dC5kaXN0U3FyKGUpOmk+MT90LmRpc3RTcXIocik6dC5kaXN0U3FyKHIuc3ViKGUpLl9tdWx0KGkpLl9hZGQoZSkpfWZ1bmN0aW9uIEJhKHQsZSl7Zm9yKHZhciByLG4saSxhPSExLG89MDtvPHQubGVuZ3RoO28rKylmb3IodmFyIHM9MCx1PShyPXRbb10pLmxlbmd0aC0xO3M8ci5sZW5ndGg7dT1zKyspbj1yW3NdLGk9clt1XSxuLnk+ZS55IT1pLnk+ZS55JiZlLng8KGkueC1uLngpKihlLnktbi55KS8oaS55LW4ueSkrbi54JiYoYT0hYSk7cmV0dXJuIGF9ZnVuY3Rpb24gQ2EodCxlKXtmb3IodmFyIHI9ITEsbj0wLGk9dC5sZW5ndGgtMTtuPHQubGVuZ3RoO2k9bisrKXt2YXIgYT10W25dLG89dFtpXTthLnk+ZS55IT1vLnk+ZS55JiZlLng8KG8ueC1hLngpKihlLnktYS55KS8oby55LWEueSkrYS54JiYocj0hcik7fXJldHVybiByfWZ1bmN0aW9uIEVhKHQsZSxyKXt2YXIgbj1yWzBdLGk9clsyXTtpZih0Lng8bi54JiZlLng8bi54fHx0Lng+aS54JiZlLng+aS54fHx0Lnk8bi55JiZlLnk8bi55fHx0Lnk+aS55JiZlLnk+aS55KXJldHVybiAhMTt2YXIgYT1BKHQsZSxyWzBdKTtyZXR1cm4gYSE9PUEodCxlLHJbMV0pfHxhIT09QSh0LGUsclsyXSl8fGEhPT1BKHQsZSxyWzNdKX1mdW5jdGlvbiBNYSh0LGUscil7dmFyIG49ZS5wYWludC5nZXQodCkudmFsdWU7cmV0dXJuIFwiY29uc3RhbnRcIj09PW4ua2luZD9uLnZhbHVlOnIucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLmdldChlLmlkKS5iaW5kZXJzW3RdLm1heFZhbHVlfWZ1bmN0aW9uIFRhKHQpe3JldHVybiBNYXRoLnNxcnQodFswXSp0WzBdK3RbMV0qdFsxXSl9ZnVuY3Rpb24gUGEodCxlLHIsbixhKXtpZighZVswXSYmIWVbMV0pcmV0dXJuIHQ7dmFyIG89aS5jb252ZXJ0KGUpLl9tdWx0KGEpO1widmlld3BvcnRcIj09PXImJm8uX3JvdGF0ZSgtbik7Zm9yKHZhciBzPVtdLHU9MDt1PHQubGVuZ3RoO3UrKyl7dmFyIGw9dFt1XTtzLnB1c2gobC5zdWIobykpO31yZXR1cm4gc314YS5wcm90b3R5cGUucG9wdWxhdGU9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9MCxuPXQ7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdLGE9aS5mZWF0dXJlLG89aS5pbmRleCxzPWkuc291cmNlTGF5ZXJJbmRleDtpZih0aGlzLmxheWVyc1swXS5fZmVhdHVyZUZpbHRlcihuZXcgWm4odGhpcy56b29tKSxhKSl7dmFyIHU9dmEoYSk7dGhpcy5hZGRGZWF0dXJlKGEsdSxvKSxlLmZlYXR1cmVJbmRleC5pbnNlcnQoYSx1LG8scyx0aGlzLmluZGV4KTt9fX0seGEucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbih0LGUscil7dGhpcy5zdGF0ZURlcGVuZGVudExheWVycy5sZW5ndGgmJnRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLnVwZGF0ZVBhaW50QXJyYXlzKHQsZSx0aGlzLnN0YXRlRGVwZW5kZW50TGF5ZXJzLHIpO30seGEucHJvdG90eXBlLmlzRW1wdHk9ZnVuY3Rpb24oKXtyZXR1cm4gMD09PXRoaXMubGF5b3V0VmVydGV4QXJyYXkubGVuZ3RofSx4YS5wcm90b3R5cGUudXBsb2FkUGVuZGluZz1mdW5jdGlvbigpe3JldHVybiAhdGhpcy51cGxvYWRlZHx8dGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMubmVlZHNVcGxvYWR9LHhhLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCl7dGhpcy51cGxvYWRlZHx8KHRoaXMubGF5b3V0VmVydGV4QnVmZmVyPXQuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMubGF5b3V0VmVydGV4QXJyYXksWmkpLHRoaXMuaW5kZXhCdWZmZXI9dC5jcmVhdGVJbmRleEJ1ZmZlcih0aGlzLmluZGV4QXJyYXkpKSx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy51cGxvYWQodCksdGhpcy51cGxvYWRlZD0hMDt9LHhhLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXImJih0aGlzLmxheW91dFZlcnRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5pbmRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZGVzdHJveSgpLHRoaXMuc2VnbWVudHMuZGVzdHJveSgpKTt9LHhhLnByb3RvdHlwZS5hZGRGZWF0dXJlPWZ1bmN0aW9uKHQsZSxyKXtmb3IodmFyIG49MCxpPWU7bjxpLmxlbmd0aDtuKz0xKWZvcih2YXIgYT0wLG89aVtuXTthPG8ubGVuZ3RoO2ErPTEpe3ZhciBzPW9bYV0sdT1zLngsbD1zLnk7aWYoISh1PDB8fHU+PXlhfHxsPDB8fGw+PXlhKSl7dmFyIHA9dGhpcy5zZWdtZW50cy5wcmVwYXJlU2VnbWVudCg0LHRoaXMubGF5b3V0VmVydGV4QXJyYXksdGhpcy5pbmRleEFycmF5KSxjPXAudmVydGV4TGVuZ3RoO2dhKHRoaXMubGF5b3V0VmVydGV4QXJyYXksdSxsLC0xLC0xKSxnYSh0aGlzLmxheW91dFZlcnRleEFycmF5LHUsbCwxLC0xKSxnYSh0aGlzLmxheW91dFZlcnRleEFycmF5LHUsbCwxLDEpLGdhKHRoaXMubGF5b3V0VmVydGV4QXJyYXksdSxsLC0xLDEpLHRoaXMuaW5kZXhBcnJheS5lbXBsYWNlQmFjayhjLGMrMSxjKzIpLHRoaXMuaW5kZXhBcnJheS5lbXBsYWNlQmFjayhjLGMrMyxjKzIpLHAudmVydGV4TGVuZ3RoKz00LHAucHJpbWl0aXZlTGVuZ3RoKz0yO319dGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMucG9wdWxhdGVQYWludEFycmF5cyh0aGlzLmxheW91dFZlcnRleEFycmF5Lmxlbmd0aCx0LHIse30pO30sem4oXCJDaXJjbGVCdWNrZXRcIix4YSx7b21pdDpbXCJsYXllcnNcIl19KTt2YXIgVmE9e3BhaW50Om5ldyBpaSh7XCJjaXJjbGUtcmFkaXVzXCI6bmV3IHRpKEx0LnBhaW50X2NpcmNsZVtcImNpcmNsZS1yYWRpdXNcIl0pLFwiY2lyY2xlLWNvbG9yXCI6bmV3IHRpKEx0LnBhaW50X2NpcmNsZVtcImNpcmNsZS1jb2xvclwiXSksXCJjaXJjbGUtYmx1clwiOm5ldyB0aShMdC5wYWludF9jaXJjbGVbXCJjaXJjbGUtYmx1clwiXSksXCJjaXJjbGUtb3BhY2l0eVwiOm5ldyB0aShMdC5wYWludF9jaXJjbGVbXCJjaXJjbGUtb3BhY2l0eVwiXSksXCJjaXJjbGUtdHJhbnNsYXRlXCI6bmV3IFFuKEx0LnBhaW50X2NpcmNsZVtcImNpcmNsZS10cmFuc2xhdGVcIl0pLFwiY2lyY2xlLXRyYW5zbGF0ZS1hbmNob3JcIjpuZXcgUW4oTHQucGFpbnRfY2lyY2xlW1wiY2lyY2xlLXRyYW5zbGF0ZS1hbmNob3JcIl0pLFwiY2lyY2xlLXBpdGNoLXNjYWxlXCI6bmV3IFFuKEx0LnBhaW50X2NpcmNsZVtcImNpcmNsZS1waXRjaC1zY2FsZVwiXSksXCJjaXJjbGUtcGl0Y2gtYWxpZ25tZW50XCI6bmV3IFFuKEx0LnBhaW50X2NpcmNsZVtcImNpcmNsZS1waXRjaC1hbGlnbm1lbnRcIl0pLFwiY2lyY2xlLXN0cm9rZS13aWR0aFwiOm5ldyB0aShMdC5wYWludF9jaXJjbGVbXCJjaXJjbGUtc3Ryb2tlLXdpZHRoXCJdKSxcImNpcmNsZS1zdHJva2UtY29sb3JcIjpuZXcgdGkoTHQucGFpbnRfY2lyY2xlW1wiY2lyY2xlLXN0cm9rZS1jb2xvclwiXSksXCJjaXJjbGUtc3Ryb2tlLW9wYWNpdHlcIjpuZXcgdGkoTHQucGFpbnRfY2lyY2xlW1wiY2lyY2xlLXN0cm9rZS1vcGFjaXR5XCJdKX0pfSxGYT0xZS02LExhPVwidW5kZWZpbmVkXCIhPXR5cGVvZiBGbG9hdDMyQXJyYXk/RmxvYXQzMkFycmF5OkFycmF5O01hdGguUEk7ZnVuY3Rpb24gRGEoKXt2YXIgdD1uZXcgTGEoOSk7cmV0dXJuIExhIT1GbG9hdDMyQXJyYXkmJih0WzFdPTAsdFsyXT0wLHRbM109MCx0WzVdPTAsdFs2XT0wLHRbN109MCksdFswXT0xLHRbNF09MSx0WzhdPTEsdH1mdW5jdGlvbiBPYSgpe3ZhciB0PW5ldyBMYSgzKTtyZXR1cm4gTGEhPUZsb2F0MzJBcnJheSYmKHRbMF09MCx0WzFdPTAsdFsyXT0wKSx0fWZ1bmN0aW9uIFJhKHQsZSxyKXt2YXIgbj1uZXcgTGEoMyk7cmV0dXJuIG5bMF09dCxuWzFdPWUsblsyXT1yLG59ZnVuY3Rpb24gVWEodCxlLHIpe3ZhciBuPWVbMF0saT1lWzFdLGE9ZVsyXSxvPXJbMF0scz1yWzFdLHU9clsyXTtyZXR1cm4gdFswXT1pKnUtYSpzLHRbMV09YSpvLW4qdSx0WzJdPW4qcy1pKm8sdH12YXIgamEscWE9ZnVuY3Rpb24odCl7dmFyIGU9dFswXSxyPXRbMV0sbj10WzJdO3JldHVybiBNYXRoLnNxcnQoZSplK3IqcituKm4pfTtqYT1PYSgpO2Z1bmN0aW9uIE5hKHQsZSxyKXt2YXIgbj1lWzBdLGk9ZVsxXSxhPWVbMl0sbz1lWzNdO3JldHVybiB0WzBdPXJbMF0qbityWzRdKmkrcls4XSphK3JbMTJdKm8sdFsxXT1yWzFdKm4rcls1XSppK3JbOV0qYStyWzEzXSpvLHRbMl09clsyXSpuK3JbNl0qaStyWzEwXSphK3JbMTRdKm8sdFszXT1yWzNdKm4rcls3XSppK3JbMTFdKmErclsxNV0qbyx0fSFmdW5jdGlvbigpe3ZhciB0LGU9KHQ9bmV3IExhKDQpLExhIT1GbG9hdDMyQXJyYXkmJih0WzBdPTAsdFsxXT0wLHRbMl09MCx0WzNdPTApLHQpO30oKTtmdW5jdGlvbiBaYSgpe3ZhciB0PW5ldyBMYSg0KTtyZXR1cm4gTGEhPUZsb2F0MzJBcnJheSYmKHRbMF09MCx0WzFdPTAsdFsyXT0wKSx0WzNdPTEsdH1mdW5jdGlvbiBLYSh0LGUscixuKXt2YXIgaSxhLG8scyx1LGw9ZVswXSxwPWVbMV0sYz1lWzJdLGg9ZVszXSxmPXJbMF0seT1yWzFdLGQ9clsyXSxtPXJbM107cmV0dXJuIChhPWwqZitwKnkrYypkK2gqbSk8MCYmKGE9LWEsZj0tZix5PS15LGQ9LWQsbT0tbSksMS1hPkZhPyhpPU1hdGguYWNvcyhhKSxvPU1hdGguc2luKGkpLHM9TWF0aC5zaW4oKDEtbikqaSkvbyx1PU1hdGguc2luKG4qaSkvbyk6KHM9MS1uLHU9biksdFswXT1zKmwrdSpmLHRbMV09cypwK3UqeSx0WzJdPXMqYyt1KmQsdFszXT1zKmgrdSptLHR9dmFyIEdhLFhhLEphLEhhLFlhLCRhLFdhPWZ1bmN0aW9uKHQsZSl7dmFyIHI9ZVswXSxuPWVbMV0saT1lWzJdLGE9ZVszXSxvPXIqcituKm4raSppK2EqYTtyZXR1cm4gbz4wJiYobz0xL01hdGguc3FydChvKSksdFswXT1yKm8sdFsxXT1uKm8sdFsyXT1pKm8sdFszXT1hKm8sdH07R2E9T2EoKSxYYT1SYSgxLDAsMCksSmE9UmEoMCwxLDApLEhhPVphKCksWWE9WmEoKSwkYT1EYSgpOyFmdW5jdGlvbigpe3ZhciB0LGU9KHQ9bmV3IExhKDIpLExhIT1GbG9hdDMyQXJyYXkmJih0WzBdPTAsdFsxXT0wKSx0KTt9KCk7dmFyIFFhPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSxWYSk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5jcmVhdGVCdWNrZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyB4YSh0KX0sZS5wcm90b3R5cGUucXVlcnlSYWRpdXM9ZnVuY3Rpb24odCl7dmFyIGU9dDtyZXR1cm4gTWEoXCJjaXJjbGUtcmFkaXVzXCIsdGhpcyxlKStNYShcImNpcmNsZS1zdHJva2Utd2lkdGhcIix0aGlzLGUpK1RhKHRoaXMucGFpbnQuZ2V0KFwiY2lyY2xlLXRyYW5zbGF0ZVwiKSl9LGUucHJvdG90eXBlLnF1ZXJ5SW50ZXJzZWN0c0ZlYXR1cmU9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyxzKXtmb3IodmFyIHU9UGEodCx0aGlzLnBhaW50LmdldChcImNpcmNsZS10cmFuc2xhdGVcIiksdGhpcy5wYWludC5nZXQoXCJjaXJjbGUtdHJhbnNsYXRlLWFuY2hvclwiKSxhLmFuZ2xlLG8pLGw9dGhpcy5wYWludC5nZXQoXCJjaXJjbGUtcmFkaXVzXCIpLmV2YWx1YXRlKGUscikrdGhpcy5wYWludC5nZXQoXCJjaXJjbGUtc3Ryb2tlLXdpZHRoXCIpLmV2YWx1YXRlKGUscikscD1cIm1hcFwiPT09dGhpcy5wYWludC5nZXQoXCJjaXJjbGUtcGl0Y2gtYWxpZ25tZW50XCIpLGM9cD91OmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0byh0LGUpfSl9KHUscyksaD1wP2wqbzpsLGY9MCx5PW47Zjx5Lmxlbmd0aDtmKz0xKWZvcih2YXIgZD0wLG09eVtmXTtkPG0ubGVuZ3RoO2QrPTEpe3ZhciB2PW1bZF0sZz1wP3Y6dG8odixzKSx4PWgsYj1OYShbXSxbdi54LHYueSwwLDFdLHMpO2lmKFwidmlld3BvcnRcIj09PXRoaXMucGFpbnQuZ2V0KFwiY2lyY2xlLXBpdGNoLXNjYWxlXCIpJiZcIm1hcFwiPT09dGhpcy5wYWludC5nZXQoXCJjaXJjbGUtcGl0Y2gtYWxpZ25tZW50XCIpP3gqPWJbM10vYS5jYW1lcmFUb0NlbnRlckRpc3RhbmNlOlwibWFwXCI9PT10aGlzLnBhaW50LmdldChcImNpcmNsZS1waXRjaC1zY2FsZVwiKSYmXCJ2aWV3cG9ydFwiPT09dGhpcy5wYWludC5nZXQoXCJjaXJjbGUtcGl0Y2gtYWxpZ25tZW50XCIpJiYoeCo9YS5jYW1lcmFUb0NlbnRlckRpc3RhbmNlL2JbM10pLF9hKGMsZyx4KSlyZXR1cm4gITB9cmV0dXJuICExfSxlfShhaSk7ZnVuY3Rpb24gdG8odCxlKXt2YXIgcj1OYShbXSxbdC54LHQueSwwLDFdLGUpO3JldHVybiBuZXcgaShyWzBdL3JbM10sclsxXS9yWzNdKX12YXIgZW89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZX0oeGEpO2Z1bmN0aW9uIHJvKHQsZSxyLG4pe3ZhciBpPWUud2lkdGgsYT1lLmhlaWdodDtpZihuKXtpZihuIGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXkpbj1uZXcgVWludDhBcnJheShuLmJ1ZmZlcik7ZWxzZSBpZihuLmxlbmd0aCE9PWkqYSpyKXRocm93IG5ldyBSYW5nZUVycm9yKFwibWlzbWF0Y2hlZCBpbWFnZSBzaXplXCIpfWVsc2Ugbj1uZXcgVWludDhBcnJheShpKmEqcik7cmV0dXJuIHQud2lkdGg9aSx0LmhlaWdodD1hLHQuZGF0YT1uLHR9ZnVuY3Rpb24gbm8odCxlLHIpe3ZhciBuPWUud2lkdGgsaT1lLmhlaWdodDtpZihuIT09dC53aWR0aHx8aSE9PXQuaGVpZ2h0KXt2YXIgYT1ybyh7fSx7d2lkdGg6bixoZWlnaHQ6aX0scik7aW8odCxhLHt4OjAseTowfSx7eDowLHk6MH0se3dpZHRoOk1hdGgubWluKHQud2lkdGgsbiksaGVpZ2h0Ok1hdGgubWluKHQuaGVpZ2h0LGkpfSxyKSx0LndpZHRoPW4sdC5oZWlnaHQ9aSx0LmRhdGE9YS5kYXRhO319ZnVuY3Rpb24gaW8odCxlLHIsbixpLGEpe2lmKDA9PT1pLndpZHRofHwwPT09aS5oZWlnaHQpcmV0dXJuIGU7aWYoaS53aWR0aD50LndpZHRofHxpLmhlaWdodD50LmhlaWdodHx8ci54PnQud2lkdGgtaS53aWR0aHx8ci55PnQuaGVpZ2h0LWkuaGVpZ2h0KXRocm93IG5ldyBSYW5nZUVycm9yKFwib3V0IG9mIHJhbmdlIHNvdXJjZSBjb29yZGluYXRlcyBmb3IgaW1hZ2UgY29weVwiKTtpZihpLndpZHRoPmUud2lkdGh8fGkuaGVpZ2h0PmUuaGVpZ2h0fHxuLng+ZS53aWR0aC1pLndpZHRofHxuLnk+ZS5oZWlnaHQtaS5oZWlnaHQpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJvdXQgb2YgcmFuZ2UgZGVzdGluYXRpb24gY29vcmRpbmF0ZXMgZm9yIGltYWdlIGNvcHlcIik7Zm9yKHZhciBvPXQuZGF0YSxzPWUuZGF0YSx1PTA7dTxpLmhlaWdodDt1KyspZm9yKHZhciBsPSgoci55K3UpKnQud2lkdGgrci54KSphLHA9KChuLnkrdSkqZS53aWR0aCtuLngpKmEsYz0wO2M8aS53aWR0aCphO2MrKylzW3ArY109b1tsK2NdO3JldHVybiBlfXpuKFwiSGVhdG1hcEJ1Y2tldFwiLGVvLHtvbWl0OltcImxheWVyc1wiXX0pO3ZhciBhbz1mdW5jdGlvbih0LGUpe3JvKHRoaXMsdCwxLGUpO307YW8ucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbih0KXtubyh0aGlzLHQsMSk7fSxhby5wcm90b3R5cGUuY2xvbmU9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IGFvKHt3aWR0aDp0aGlzLndpZHRoLGhlaWdodDp0aGlzLmhlaWdodH0sbmV3IFVpbnQ4QXJyYXkodGhpcy5kYXRhKSl9LGFvLmNvcHk9ZnVuY3Rpb24odCxlLHIsbixpKXtpbyh0LGUscixuLGksMSk7fTt2YXIgb289ZnVuY3Rpb24odCxlKXtybyh0aGlzLHQsNCxlKTt9O29vLnByb3RvdHlwZS5yZXNpemU9ZnVuY3Rpb24odCl7bm8odGhpcyx0LDQpO30sb28ucHJvdG90eXBlLnJlcGxhY2U9ZnVuY3Rpb24odCxlKXtlP3RoaXMuZGF0YS5zZXQodCk6dCBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5P3RoaXMuZGF0YT1uZXcgVWludDhBcnJheSh0LmJ1ZmZlcik6dGhpcy5kYXRhPXQ7fSxvby5wcm90b3R5cGUuY2xvbmU9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IG9vKHt3aWR0aDp0aGlzLndpZHRoLGhlaWdodDp0aGlzLmhlaWdodH0sbmV3IFVpbnQ4QXJyYXkodGhpcy5kYXRhKSl9LG9vLmNvcHk9ZnVuY3Rpb24odCxlLHIsbixpKXtpbyh0LGUscixuLGksNCk7fSx6bihcIkFscGhhSW1hZ2VcIixhbyksem4oXCJSR0JBSW1hZ2VcIixvbyk7dmFyIHNvPXtwYWludDpuZXcgaWkoe1wiaGVhdG1hcC1yYWRpdXNcIjpuZXcgdGkoTHQucGFpbnRfaGVhdG1hcFtcImhlYXRtYXAtcmFkaXVzXCJdKSxcImhlYXRtYXAtd2VpZ2h0XCI6bmV3IHRpKEx0LnBhaW50X2hlYXRtYXBbXCJoZWF0bWFwLXdlaWdodFwiXSksXCJoZWF0bWFwLWludGVuc2l0eVwiOm5ldyBRbihMdC5wYWludF9oZWF0bWFwW1wiaGVhdG1hcC1pbnRlbnNpdHlcIl0pLFwiaGVhdG1hcC1jb2xvclwiOm5ldyBuaShMdC5wYWludF9oZWF0bWFwW1wiaGVhdG1hcC1jb2xvclwiXSksXCJoZWF0bWFwLW9wYWNpdHlcIjpuZXcgUW4oTHQucGFpbnRfaGVhdG1hcFtcImhlYXRtYXAtb3BhY2l0eVwiXSl9KX07ZnVuY3Rpb24gdW8odCxlKXtmb3IodmFyIHI9bmV3IFVpbnQ4QXJyYXkoMTAyNCksbj17fSxpPTAsYT0wO2k8MjU2O2krKyxhKz00KXtuW2VdPWkvMjU1O3ZhciBvPXQuZXZhbHVhdGUobik7clthKzBdPU1hdGguZmxvb3IoMjU1Km8uci9vLmEpLHJbYSsxXT1NYXRoLmZsb29yKDI1NSpvLmcvby5hKSxyW2ErMl09TWF0aC5mbG9vcigyNTUqby5iL28uYSksclthKzNdPU1hdGguZmxvb3IoMjU1Km8uYSk7fXJldHVybiBuZXcgb28oe3dpZHRoOjI1NixoZWlnaHQ6MX0scil9dmFyIGxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSxzbyksdGhpcy5fdXBkYXRlQ29sb3JSYW1wKCk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5jcmVhdGVCdWNrZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBlbyh0KX0sZS5wcm90b3R5cGUuX2hhbmRsZVNwZWNpYWxQYWludFByb3BlcnR5VXBkYXRlPWZ1bmN0aW9uKHQpe1wiaGVhdG1hcC1jb2xvclwiPT09dCYmdGhpcy5fdXBkYXRlQ29sb3JSYW1wKCk7fSxlLnByb3RvdHlwZS5fdXBkYXRlQ29sb3JSYW1wPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5fdHJhbnNpdGlvbmFibGVQYWludC5fdmFsdWVzW1wiaGVhdG1hcC1jb2xvclwiXS52YWx1ZS5leHByZXNzaW9uO3RoaXMuY29sb3JSYW1wPXVvKHQsXCJoZWF0bWFwRGVuc2l0eVwiKSx0aGlzLmNvbG9yUmFtcFRleHR1cmU9bnVsbDt9LGUucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbigpe3RoaXMuaGVhdG1hcEZibyYmKHRoaXMuaGVhdG1hcEZiby5kZXN0cm95KCksdGhpcy5oZWF0bWFwRmJvPW51bGwpO30sZS5wcm90b3R5cGUucXVlcnlSYWRpdXM9ZnVuY3Rpb24oKXtyZXR1cm4gMH0sZS5wcm90b3R5cGUucXVlcnlJbnRlcnNlY3RzRmVhdHVyZT1mdW5jdGlvbigpe3JldHVybiAhMX0sZS5wcm90b3R5cGUuaGFzT2Zmc2NyZWVuUGFzcz1mdW5jdGlvbigpe3JldHVybiAwIT09dGhpcy5wYWludC5nZXQoXCJoZWF0bWFwLW9wYWNpdHlcIikmJlwibm9uZVwiIT09dGhpcy52aXNpYmlsaXR5fSxlfShhaSkscG89e3BhaW50Om5ldyBpaSh7XCJoaWxsc2hhZGUtaWxsdW1pbmF0aW9uLWRpcmVjdGlvblwiOm5ldyBRbihMdC5wYWludF9oaWxsc2hhZGVbXCJoaWxsc2hhZGUtaWxsdW1pbmF0aW9uLWRpcmVjdGlvblwiXSksXCJoaWxsc2hhZGUtaWxsdW1pbmF0aW9uLWFuY2hvclwiOm5ldyBRbihMdC5wYWludF9oaWxsc2hhZGVbXCJoaWxsc2hhZGUtaWxsdW1pbmF0aW9uLWFuY2hvclwiXSksXCJoaWxsc2hhZGUtZXhhZ2dlcmF0aW9uXCI6bmV3IFFuKEx0LnBhaW50X2hpbGxzaGFkZVtcImhpbGxzaGFkZS1leGFnZ2VyYXRpb25cIl0pLFwiaGlsbHNoYWRlLXNoYWRvdy1jb2xvclwiOm5ldyBRbihMdC5wYWludF9oaWxsc2hhZGVbXCJoaWxsc2hhZGUtc2hhZG93LWNvbG9yXCJdKSxcImhpbGxzaGFkZS1oaWdobGlnaHQtY29sb3JcIjpuZXcgUW4oTHQucGFpbnRfaGlsbHNoYWRlW1wiaGlsbHNoYWRlLWhpZ2hsaWdodC1jb2xvclwiXSksXCJoaWxsc2hhZGUtYWNjZW50LWNvbG9yXCI6bmV3IFFuKEx0LnBhaW50X2hpbGxzaGFkZVtcImhpbGxzaGFkZS1hY2NlbnQtY29sb3JcIl0pfSl9LGNvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSxwbyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5oYXNPZmZzY3JlZW5QYXNzPWZ1bmN0aW9uKCl7cmV0dXJuIDAhPT10aGlzLnBhaW50LmdldChcImhpbGxzaGFkZS1leGFnZ2VyYXRpb25cIikmJlwibm9uZVwiIT09dGhpcy52aXNpYmlsaXR5fSxlfShhaSksaG89bGkoW3tuYW1lOlwiYV9wb3NcIixjb21wb25lbnRzOjIsdHlwZTpcIkludDE2XCJ9XSw0KS5tZW1iZXJzLGZvPW1vLHlvPW1vO2Z1bmN0aW9uIG1vKHQsZSxyKXtyPXJ8fDI7dmFyIG4saSxhLG8scyx1LGwscD1lJiZlLmxlbmd0aCxjPXA/ZVswXSpyOnQubGVuZ3RoLGg9dm8odCwwLGMsciwhMCksZj1bXTtpZighaHx8aC5uZXh0PT09aC5wcmV2KXJldHVybiBmO2lmKHAmJihoPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBpLGEsbyxzLHUsbD1bXTtmb3IoaT0wLGE9ZS5sZW5ndGg7aTxhO2krKylvPWVbaV0qbixzPWk8YS0xP2VbaSsxXSpuOnQubGVuZ3RoLCh1PXZvKHQsbyxzLG4sITEpKT09PXUubmV4dCYmKHUuc3RlaW5lcj0hMCksbC5wdXNoKElvKHUpKTtmb3IobC5zb3J0KFNvKSxpPTA7aTxsLmxlbmd0aDtpKyspa28obFtpXSxyKSxyPWdvKHIsci5uZXh0KTtyZXR1cm4gcn0odCxlLGgscikpLHQubGVuZ3RoPjgwKnIpe249YT10WzBdLGk9bz10WzFdO2Zvcih2YXIgeT1yO3k8Yzt5Kz1yKShzPXRbeV0pPG4mJihuPXMpLCh1PXRbeSsxXSk8aSYmKGk9dSkscz5hJiYoYT1zKSx1Pm8mJihvPXUpO2w9MCE9PShsPU1hdGgubWF4KGEtbixvLWkpKT8xL2w6MDt9cmV0dXJuIHhvKGgsZixyLG4saSxsKSxmfWZ1bmN0aW9uIHZvKHQsZSxyLG4saSl7dmFyIGEsbztpZihpPT09T28odCxlLHIsbik+MClmb3IoYT1lO2E8cjthKz1uKW89Rm8oYSx0W2FdLHRbYSsxXSxvKTtlbHNlIGZvcihhPXItbjthPj1lO2EtPW4pbz1GbyhhLHRbYV0sdFthKzFdLG8pO3JldHVybiBvJiZNbyhvLG8ubmV4dCkmJihMbyhvKSxvPW8ubmV4dCksb31mdW5jdGlvbiBnbyh0LGUpe2lmKCF0KXJldHVybiB0O2V8fChlPXQpO3ZhciByLG49dDtkb3tpZihyPSExLG4uc3RlaW5lcnx8IU1vKG4sbi5uZXh0KSYmMCE9PUVvKG4ucHJldixuLG4ubmV4dCkpbj1uLm5leHQ7ZWxzZXtpZihMbyhuKSwobj1lPW4ucHJldik9PT1uLm5leHQpYnJlYWs7cj0hMDt9fXdoaWxlKHJ8fG4hPT1lKTtyZXR1cm4gZX1mdW5jdGlvbiB4byh0LGUscixuLGksYSxvKXtpZih0KXshbyYmYSYmZnVuY3Rpb24odCxlLHIsbil7dmFyIGk9dDtkb3tudWxsPT09aS56JiYoaS56PXpvKGkueCxpLnksZSxyLG4pKSxpLnByZXZaPWkucHJldixpLm5leHRaPWkubmV4dCxpPWkubmV4dDt9d2hpbGUoaSE9PXQpO2kucHJldloubmV4dFo9bnVsbCxpLnByZXZaPW51bGwsZnVuY3Rpb24odCl7dmFyIGUscixuLGksYSxvLHMsdSxsPTE7ZG97Zm9yKHI9dCx0PW51bGwsYT1udWxsLG89MDtyOyl7Zm9yKG8rKyxuPXIscz0wLGU9MDtlPGwmJihzKyssbj1uLm5leHRaKTtlKyspO2Zvcih1PWw7cz4wfHx1PjAmJm47KTAhPT1zJiYoMD09PXV8fCFufHxyLno8PW4ueik/KGk9cixyPXIubmV4dFoscy0tKTooaT1uLG49bi5uZXh0Wix1LS0pLGE/YS5uZXh0Wj1pOnQ9aSxpLnByZXZaPWEsYT1pO3I9bjt9YS5uZXh0Wj1udWxsLGwqPTI7fXdoaWxlKG8+MSl9KGkpO30odCxuLGksYSk7Zm9yKHZhciBzLHUsbD10O3QucHJldiE9PXQubmV4dDspaWYocz10LnByZXYsdT10Lm5leHQsYT9fbyh0LG4saSxhKTpibyh0KSllLnB1c2gocy5pL3IpLGUucHVzaCh0LmkvciksZS5wdXNoKHUuaS9yKSxMbyh0KSx0PXUubmV4dCxsPXUubmV4dDtlbHNlIGlmKCh0PXUpPT09bCl7bz8xPT09bz94byh0PXdvKHQsZSxyKSxlLHIsbixpLGEsMik6Mj09PW8mJkFvKHQsZSxyLG4saSxhKTp4byhnbyh0KSxlLHIsbixpLGEsMSk7YnJlYWt9fX1mdW5jdGlvbiBibyh0KXt2YXIgZT10LnByZXYscj10LG49dC5uZXh0O2lmKEVvKGUscixuKT49MClyZXR1cm4gITE7Zm9yKHZhciBpPXQubmV4dC5uZXh0O2khPT10LnByZXY7KXtpZihCbyhlLngsZS55LHIueCxyLnksbi54LG4ueSxpLngsaS55KSYmRW8oaS5wcmV2LGksaS5uZXh0KT49MClyZXR1cm4gITE7aT1pLm5leHQ7fXJldHVybiAhMH1mdW5jdGlvbiBfbyh0LGUscixuKXt2YXIgaT10LnByZXYsYT10LG89dC5uZXh0O2lmKEVvKGksYSxvKT49MClyZXR1cm4gITE7Zm9yKHZhciBzPWkueDxhLng/aS54PG8ueD9pLng6by54OmEueDxvLng/YS54Om8ueCx1PWkueTxhLnk/aS55PG8ueT9pLnk6by55OmEueTxvLnk/YS55Om8ueSxsPWkueD5hLng/aS54Pm8ueD9pLng6by54OmEueD5vLng/YS54Om8ueCxwPWkueT5hLnk/aS55Pm8ueT9pLnk6by55OmEueT5vLnk/YS55Om8ueSxjPXpvKHMsdSxlLHIsbiksaD16byhsLHAsZSxyLG4pLGY9dC5wcmV2Wix5PXQubmV4dFo7ZiYmZi56Pj1jJiZ5JiZ5Lno8PWg7KXtpZihmIT09dC5wcmV2JiZmIT09dC5uZXh0JiZCbyhpLngsaS55LGEueCxhLnksby54LG8ueSxmLngsZi55KSYmRW8oZi5wcmV2LGYsZi5uZXh0KT49MClyZXR1cm4gITE7aWYoZj1mLnByZXZaLHkhPT10LnByZXYmJnkhPT10Lm5leHQmJkJvKGkueCxpLnksYS54LGEueSxvLngsby55LHkueCx5LnkpJiZFbyh5LnByZXYseSx5Lm5leHQpPj0wKXJldHVybiAhMTt5PXkubmV4dFo7fWZvcig7ZiYmZi56Pj1jOyl7aWYoZiE9PXQucHJldiYmZiE9PXQubmV4dCYmQm8oaS54LGkueSxhLngsYS55LG8ueCxvLnksZi54LGYueSkmJkVvKGYucHJldixmLGYubmV4dCk+PTApcmV0dXJuICExO2Y9Zi5wcmV2Wjt9Zm9yKDt5JiZ5Lno8PWg7KXtpZih5IT09dC5wcmV2JiZ5IT09dC5uZXh0JiZCbyhpLngsaS55LGEueCxhLnksby54LG8ueSx5LngseS55KSYmRW8oeS5wcmV2LHkseS5uZXh0KT49MClyZXR1cm4gITE7eT15Lm5leHRaO31yZXR1cm4gITB9ZnVuY3Rpb24gd28odCxlLHIpe3ZhciBuPXQ7ZG97dmFyIGk9bi5wcmV2LGE9bi5uZXh0Lm5leHQ7IU1vKGksYSkmJlRvKGksbixuLm5leHQsYSkmJlBvKGksYSkmJlBvKGEsaSkmJihlLnB1c2goaS5pL3IpLGUucHVzaChuLmkvciksZS5wdXNoKGEuaS9yKSxMbyhuKSxMbyhuLm5leHQpLG49dD1hKSxuPW4ubmV4dDt9d2hpbGUobiE9PXQpO3JldHVybiBufWZ1bmN0aW9uIEFvKHQsZSxyLG4saSxhKXt2YXIgbz10O2Rve2Zvcih2YXIgcz1vLm5leHQubmV4dDtzIT09by5wcmV2Oyl7aWYoby5pIT09cy5pJiZDbyhvLHMpKXt2YXIgdT1WbyhvLHMpO3JldHVybiBvPWdvKG8sby5uZXh0KSx1PWdvKHUsdS5uZXh0KSx4byhvLGUscixuLGksYSksdm9pZCB4byh1LGUscixuLGksYSl9cz1zLm5leHQ7fW89by5uZXh0O313aGlsZShvIT09dCl9ZnVuY3Rpb24gU28odCxlKXtyZXR1cm4gdC54LWUueH1mdW5jdGlvbiBrbyh0LGUpe2lmKGU9ZnVuY3Rpb24odCxlKXt2YXIgcixuPWUsaT10LngsYT10Lnksbz0tMS8wO2Rve2lmKGE8PW4ueSYmYT49bi5uZXh0LnkmJm4ubmV4dC55IT09bi55KXt2YXIgcz1uLngrKGEtbi55KSoobi5uZXh0Lngtbi54KS8obi5uZXh0Lnktbi55KTtpZihzPD1pJiZzPm8pe2lmKG89cyxzPT09aSl7aWYoYT09PW4ueSlyZXR1cm4gbjtpZihhPT09bi5uZXh0LnkpcmV0dXJuIG4ubmV4dH1yPW4ueDxuLm5leHQueD9uOm4ubmV4dDt9fW49bi5uZXh0O313aGlsZShuIT09ZSk7aWYoIXIpcmV0dXJuIG51bGw7aWYoaT09PW8pcmV0dXJuIHIucHJldjt2YXIgdSxsPXIscD1yLngsYz1yLnksaD0xLzA7bj1yLm5leHQ7Zm9yKDtuIT09bDspaT49bi54JiZuLng+PXAmJmkhPT1uLngmJkJvKGE8Yz9pOm8sYSxwLGMsYTxjP286aSxhLG4ueCxuLnkpJiYoKHU9TWF0aC5hYnMoYS1uLnkpLyhpLW4ueCkpPGh8fHU9PT1oJiZuLng+ci54KSYmUG8obix0KSYmKHI9bixoPXUpLG49bi5uZXh0O3JldHVybiByfSh0LGUpKXt2YXIgcj1WbyhlLHQpO2dvKHIsci5uZXh0KTt9fWZ1bmN0aW9uIHpvKHQsZSxyLG4saSl7cmV0dXJuICh0PTE0MzE2NTU3NjUmKCh0PTg1ODk5MzQ1OSYoKHQ9MjUyNjQ1MTM1JigodD0xNjcxMTkzNSYoKHQ9MzI3NjcqKHQtcikqaSl8dDw8OCkpfHQ8PDQpKXx0PDwyKSl8dDw8MSkpfChlPTE0MzE2NTU3NjUmKChlPTg1ODk5MzQ1OSYoKGU9MjUyNjQ1MTM1JigoZT0xNjcxMTkzNSYoKGU9MzI3NjcqKGUtbikqaSl8ZTw8OCkpfGU8PDQpKXxlPDwyKSl8ZTw8MSkpPDwxfWZ1bmN0aW9uIElvKHQpe3ZhciBlPXQscj10O2RveyhlLng8ci54fHxlLng9PT1yLngmJmUueTxyLnkpJiYocj1lKSxlPWUubmV4dDt9d2hpbGUoZSE9PXQpO3JldHVybiByfWZ1bmN0aW9uIEJvKHQsZSxyLG4saSxhLG8scyl7cmV0dXJuIChpLW8pKihlLXMpLSh0LW8pKihhLXMpPj0wJiYodC1vKSoobi1zKS0oci1vKSooZS1zKT49MCYmKHItbykqKGEtcyktKGktbykqKG4tcyk+PTB9ZnVuY3Rpb24gQ28odCxlKXtyZXR1cm4gdC5uZXh0LmkhPT1lLmkmJnQucHJldi5pIT09ZS5pJiYhZnVuY3Rpb24odCxlKXt2YXIgcj10O2Rve2lmKHIuaSE9PXQuaSYmci5uZXh0LmkhPT10LmkmJnIuaSE9PWUuaSYmci5uZXh0LmkhPT1lLmkmJlRvKHIsci5uZXh0LHQsZSkpcmV0dXJuICEwO3I9ci5uZXh0O313aGlsZShyIT09dCk7cmV0dXJuICExfSh0LGUpJiZQbyh0LGUpJiZQbyhlLHQpJiZmdW5jdGlvbih0LGUpe3ZhciByPXQsbj0hMSxpPSh0LngrZS54KS8yLGE9KHQueStlLnkpLzI7ZG97ci55PmEhPXIubmV4dC55PmEmJnIubmV4dC55IT09ci55JiZpPChyLm5leHQueC1yLngpKihhLXIueSkvKHIubmV4dC55LXIueSkrci54JiYobj0hbikscj1yLm5leHQ7fXdoaWxlKHIhPT10KTtyZXR1cm4gbn0odCxlKX1mdW5jdGlvbiBFbyh0LGUscil7cmV0dXJuIChlLnktdC55KSooci54LWUueCktKGUueC10LngpKihyLnktZS55KX1mdW5jdGlvbiBNbyh0LGUpe3JldHVybiB0Lng9PT1lLngmJnQueT09PWUueX1mdW5jdGlvbiBUbyh0LGUscixuKXtyZXR1cm4gISEoTW8odCxlKSYmTW8ocixuKXx8TW8odCxuKSYmTW8ocixlKSl8fEVvKHQsZSxyKT4wIT1Fbyh0LGUsbik+MCYmRW8ocixuLHQpPjAhPUVvKHIsbixlKT4wfWZ1bmN0aW9uIFBvKHQsZSl7cmV0dXJuIEVvKHQucHJldix0LHQubmV4dCk8MD9Fbyh0LGUsdC5uZXh0KT49MCYmRW8odCx0LnByZXYsZSk+PTA6RW8odCxlLHQucHJldik8MHx8RW8odCx0Lm5leHQsZSk8MH1mdW5jdGlvbiBWbyh0LGUpe3ZhciByPW5ldyBEbyh0LmksdC54LHQueSksbj1uZXcgRG8oZS5pLGUueCxlLnkpLGk9dC5uZXh0LGE9ZS5wcmV2O3JldHVybiB0Lm5leHQ9ZSxlLnByZXY9dCxyLm5leHQ9aSxpLnByZXY9cixuLm5leHQ9cixyLnByZXY9bixhLm5leHQ9bixuLnByZXY9YSxufWZ1bmN0aW9uIEZvKHQsZSxyLG4pe3ZhciBpPW5ldyBEbyh0LGUscik7cmV0dXJuIG4/KGkubmV4dD1uLm5leHQsaS5wcmV2PW4sbi5uZXh0LnByZXY9aSxuLm5leHQ9aSk6KGkucHJldj1pLGkubmV4dD1pKSxpfWZ1bmN0aW9uIExvKHQpe3QubmV4dC5wcmV2PXQucHJldix0LnByZXYubmV4dD10Lm5leHQsdC5wcmV2WiYmKHQucHJldloubmV4dFo9dC5uZXh0WiksdC5uZXh0WiYmKHQubmV4dFoucHJldlo9dC5wcmV2Wik7fWZ1bmN0aW9uIERvKHQsZSxyKXt0aGlzLmk9dCx0aGlzLng9ZSx0aGlzLnk9cix0aGlzLnByZXY9bnVsbCx0aGlzLm5leHQ9bnVsbCx0aGlzLno9bnVsbCx0aGlzLnByZXZaPW51bGwsdGhpcy5uZXh0Wj1udWxsLHRoaXMuc3RlaW5lcj0hMTt9ZnVuY3Rpb24gT28odCxlLHIsbil7Zm9yKHZhciBpPTAsYT1lLG89ci1uO2E8cjthKz1uKWkrPSh0W29dLXRbYV0pKih0W2ErMV0rdFtvKzFdKSxvPWE7cmV0dXJuIGl9ZnVuY3Rpb24gUm8odCxlLHIsbixpKXshZnVuY3Rpb24gdChlLHIsbixpLGEpe2Zvcig7aT5uOyl7aWYoaS1uPjYwMCl7dmFyIG89aS1uKzEscz1yLW4rMSx1PU1hdGgubG9nKG8pLGw9LjUqTWF0aC5leHAoMip1LzMpLHA9LjUqTWF0aC5zcXJ0KHUqbCooby1sKS9vKSoocy1vLzI8MD8tMToxKSxjPU1hdGgubWF4KG4sTWF0aC5mbG9vcihyLXMqbC9vK3ApKSxoPU1hdGgubWluKGksTWF0aC5mbG9vcihyKyhvLXMpKmwvbytwKSk7dChlLHIsYyxoLGEpO312YXIgZj1lW3JdLHk9bixkPWk7Zm9yKFVvKGUsbixyKSxhKGVbaV0sZik+MCYmVW8oZSxuLGkpO3k8ZDspe2ZvcihVbyhlLHksZCkseSsrLGQtLTthKGVbeV0sZik8MDspeSsrO2Zvcig7YShlW2RdLGYpPjA7KWQtLTt9MD09PWEoZVtuXSxmKT9VbyhlLG4sZCk6VW8oZSwrK2QsaSksZDw9ciYmKG49ZCsxKSxyPD1kJiYoaT1kLTEpO319KHQsZSxyfHwwLG58fHQubGVuZ3RoLTEsaXx8am8pO31mdW5jdGlvbiBVbyh0LGUscil7dmFyIG49dFtlXTt0W2VdPXRbcl0sdFtyXT1uO31mdW5jdGlvbiBqbyh0LGUpe3JldHVybiB0PGU/LTE6dD5lPzE6MH1mdW5jdGlvbiBxbyh0LGUpe3ZhciByPXQubGVuZ3RoO2lmKHI8PTEpcmV0dXJuIFt0XTtmb3IodmFyIG4saSxhPVtdLG89MDtvPHI7bysrKXt2YXIgcz1TKHRbb10pOzAhPT1zJiYodFtvXS5hcmVhPU1hdGguYWJzKHMpLHZvaWQgMD09PWkmJihpPXM8MCksaT09PXM8MD8obiYmYS5wdXNoKG4pLG49W3Rbb11dKTpuLnB1c2godFtvXSkpO31pZihuJiZhLnB1c2gobiksZT4xKWZvcih2YXIgdT0wO3U8YS5sZW5ndGg7dSsrKWFbdV0ubGVuZ3RoPD1lfHwoUm8oYVt1XSxlLDEsYVt1XS5sZW5ndGgtMSxObyksYVt1XT1hW3VdLnNsaWNlKDAsZSkpO3JldHVybiBhfWZ1bmN0aW9uIE5vKHQsZSl7cmV0dXJuIGUuYXJlYS10LmFyZWF9ZnVuY3Rpb24gWm8odCxlLHIpe2Zvcih2YXIgbj1yLnBhdHRlcm5EZXBlbmRlbmNpZXMsaT0hMSxhPTAsbz1lO2E8by5sZW5ndGg7YSs9MSl7dmFyIHM9b1thXS5wYWludC5nZXQodCtcIi1wYXR0ZXJuXCIpO3MuaXNDb25zdGFudCgpfHwoaT0hMCk7dmFyIHU9cy5jb25zdGFudE9yKG51bGwpO3UmJihpPSEwLG5bdS50b109ITAsblt1LmZyb21dPSEwKTt9cmV0dXJuIGl9ZnVuY3Rpb24gS28odCxlLHIsbixpKXtmb3IodmFyIGE9aS5wYXR0ZXJuRGVwZW5kZW5jaWVzLG89MCxzPWU7bzxzLmxlbmd0aDtvKz0xKXt2YXIgdT1zW29dLGw9dS5wYWludC5nZXQodCtcIi1wYXR0ZXJuXCIpLnZhbHVlO2lmKFwiY29uc3RhbnRcIiE9PWwua2luZCl7dmFyIHA9bC5ldmFsdWF0ZSh7em9vbTpuLTF9LHIse30pLGM9bC5ldmFsdWF0ZSh7em9vbTpufSxyLHt9KSxoPWwuZXZhbHVhdGUoe3pvb206bisxfSxyLHt9KTthW3BdPSEwLGFbY109ITAsYVtoXT0hMCxyLnBhdHRlcm5zW3UuaWRdPXttaW46cCxtaWQ6YyxtYXg6aH07fX1yZXR1cm4gcn1tby5kZXZpYXRpb249ZnVuY3Rpb24odCxlLHIsbil7dmFyIGk9ZSYmZS5sZW5ndGgsYT1pP2VbMF0qcjp0Lmxlbmd0aCxvPU1hdGguYWJzKE9vKHQsMCxhLHIpKTtpZihpKWZvcih2YXIgcz0wLHU9ZS5sZW5ndGg7czx1O3MrKyl7dmFyIGw9ZVtzXSpyLHA9czx1LTE/ZVtzKzFdKnI6dC5sZW5ndGg7by09TWF0aC5hYnMoT28odCxsLHAscikpO312YXIgYz0wO2ZvcihzPTA7czxuLmxlbmd0aDtzKz0zKXt2YXIgaD1uW3NdKnIsZj1uW3MrMV0qcix5PW5bcysyXSpyO2MrPU1hdGguYWJzKCh0W2hdLXRbeV0pKih0W2YrMV0tdFtoKzFdKS0odFtoXS10W2ZdKSoodFt5KzFdLXRbaCsxXSkpO31yZXR1cm4gMD09PW8mJjA9PT1jPzA6TWF0aC5hYnMoKGMtbykvbyl9LG1vLmZsYXR0ZW49ZnVuY3Rpb24odCl7Zm9yKHZhciBlPXRbMF1bMF0ubGVuZ3RoLHI9e3ZlcnRpY2VzOltdLGhvbGVzOltdLGRpbWVuc2lvbnM6ZX0sbj0wLGk9MDtpPHQubGVuZ3RoO2krKyl7Zm9yKHZhciBhPTA7YTx0W2ldLmxlbmd0aDthKyspZm9yKHZhciBvPTA7bzxlO28rKylyLnZlcnRpY2VzLnB1c2godFtpXVthXVtvXSk7aT4wJiYobis9dFtpLTFdLmxlbmd0aCxyLmhvbGVzLnB1c2gobikpO31yZXR1cm4gcn0sZm8uZGVmYXVsdD15bzt2YXIgR289ZnVuY3Rpb24odCl7dGhpcy56b29tPXQuem9vbSx0aGlzLm92ZXJzY2FsaW5nPXQub3ZlcnNjYWxpbmcsdGhpcy5sYXllcnM9dC5sYXllcnMsdGhpcy5sYXllcklkcz10aGlzLmxheWVycy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuaWR9KSx0aGlzLmluZGV4PXQuaW5kZXgsdGhpcy5oYXNQYXR0ZXJuPSExLHRoaXMubGF5b3V0VmVydGV4QXJyYXk9bmV3IGNpLHRoaXMuaW5kZXhBcnJheT1uZXcgSWksdGhpcy5pbmRleEFycmF5Mj1uZXcgQmksdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnM9bmV3IGNhKGhvLHQubGF5ZXJzLHQuem9vbSksdGhpcy5zZWdtZW50cz1uZXcgS2ksdGhpcy5zZWdtZW50czI9bmV3IEtpLHRoaXMuc3RhdGVEZXBlbmRlbnRMYXllcklkcz10aGlzLmxheWVycy5maWx0ZXIoZnVuY3Rpb24odCl7cmV0dXJuIHQuaXNTdGF0ZURlcGVuZGVudCgpfSkubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkfSk7fTtHby5wcm90b3R5cGUucG9wdWxhdGU9ZnVuY3Rpb24odCxlKXt0aGlzLmZlYXR1cmVzPVtdLHRoaXMuaGFzUGF0dGVybj1abyhcImZpbGxcIix0aGlzLmxheWVycyxlKTtmb3IodmFyIHI9MCxuPXQ7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdLGE9aS5mZWF0dXJlLG89aS5pbmRleCxzPWkuc291cmNlTGF5ZXJJbmRleDtpZih0aGlzLmxheWVyc1swXS5fZmVhdHVyZUZpbHRlcihuZXcgWm4odGhpcy56b29tKSxhKSl7dmFyIHU9dmEoYSksbD17c291cmNlTGF5ZXJJbmRleDpzLGluZGV4Om8sZ2VvbWV0cnk6dSxwcm9wZXJ0aWVzOmEucHJvcGVydGllcyx0eXBlOmEudHlwZSxwYXR0ZXJuczp7fX07dm9pZCAwIT09YS5pZCYmKGwuaWQ9YS5pZCksdGhpcy5oYXNQYXR0ZXJuP3RoaXMuZmVhdHVyZXMucHVzaChLbyhcImZpbGxcIix0aGlzLmxheWVycyxsLHRoaXMuem9vbSxlKSk6dGhpcy5hZGRGZWF0dXJlKGwsdSxvLHt9KSxlLmZlYXR1cmVJbmRleC5pbnNlcnQoYSx1LG8scyx0aGlzLmluZGV4KTt9fX0sR28ucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbih0LGUscil7dGhpcy5zdGF0ZURlcGVuZGVudExheWVycy5sZW5ndGgmJnRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLnVwZGF0ZVBhaW50QXJyYXlzKHQsZSx0aGlzLnN0YXRlRGVwZW5kZW50TGF5ZXJzLHIpO30sR28ucHJvdG90eXBlLmFkZEZlYXR1cmVzPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTAsbj10aGlzLmZlYXR1cmVzO3I8bi5sZW5ndGg7cis9MSl7dmFyIGk9bltyXSxhPWkuZ2VvbWV0cnk7dGhpcy5hZGRGZWF0dXJlKGksYSxpLmluZGV4LGUpO319LEdvLnByb3RvdHlwZS5pc0VtcHR5PWZ1bmN0aW9uKCl7cmV0dXJuIDA9PT10aGlzLmxheW91dFZlcnRleEFycmF5Lmxlbmd0aH0sR28ucHJvdG90eXBlLnVwbG9hZFBlbmRpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gIXRoaXMudXBsb2FkZWR8fHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLm5lZWRzVXBsb2FkfSxHby5wcm90b3R5cGUudXBsb2FkPWZ1bmN0aW9uKHQpe3RoaXMudXBsb2FkZWR8fCh0aGlzLmxheW91dFZlcnRleEJ1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLmxheW91dFZlcnRleEFycmF5LGhvKSx0aGlzLmluZGV4QnVmZmVyPXQuY3JlYXRlSW5kZXhCdWZmZXIodGhpcy5pbmRleEFycmF5KSx0aGlzLmluZGV4QnVmZmVyMj10LmNyZWF0ZUluZGV4QnVmZmVyKHRoaXMuaW5kZXhBcnJheTIpKSx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy51cGxvYWQodCksdGhpcy51cGxvYWRlZD0hMDt9LEdvLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXImJih0aGlzLmxheW91dFZlcnRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5pbmRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5pbmRleEJ1ZmZlcjIuZGVzdHJveSgpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLmRlc3Ryb3koKSx0aGlzLnNlZ21lbnRzLmRlc3Ryb3koKSx0aGlzLnNlZ21lbnRzMi5kZXN0cm95KCkpO30sR28ucHJvdG90eXBlLmFkZEZlYXR1cmU9ZnVuY3Rpb24odCxlLHIsbil7Zm9yKHZhciBpPTAsYT1xbyhlLDUwMCk7aTxhLmxlbmd0aDtpKz0xKXtmb3IodmFyIG89YVtpXSxzPTAsdT0wLGw9bzt1PGwubGVuZ3RoO3UrPTEpe3MrPWxbdV0ubGVuZ3RoO31mb3IodmFyIHA9dGhpcy5zZWdtZW50cy5wcmVwYXJlU2VnbWVudChzLHRoaXMubGF5b3V0VmVydGV4QXJyYXksdGhpcy5pbmRleEFycmF5KSxjPXAudmVydGV4TGVuZ3RoLGg9W10sZj1bXSx5PTAsZD1vO3k8ZC5sZW5ndGg7eSs9MSl7dmFyIG09ZFt5XTtpZigwIT09bS5sZW5ndGgpe20hPT1vWzBdJiZmLnB1c2goaC5sZW5ndGgvMik7dmFyIHY9dGhpcy5zZWdtZW50czIucHJlcGFyZVNlZ21lbnQobS5sZW5ndGgsdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSx0aGlzLmluZGV4QXJyYXkyKSxnPXYudmVydGV4TGVuZ3RoO3RoaXMubGF5b3V0VmVydGV4QXJyYXkuZW1wbGFjZUJhY2sobVswXS54LG1bMF0ueSksdGhpcy5pbmRleEFycmF5Mi5lbXBsYWNlQmFjayhnK20ubGVuZ3RoLTEsZyksaC5wdXNoKG1bMF0ueCksaC5wdXNoKG1bMF0ueSk7Zm9yKHZhciB4PTE7eDxtLmxlbmd0aDt4KyspdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheS5lbXBsYWNlQmFjayhtW3hdLngsbVt4XS55KSx0aGlzLmluZGV4QXJyYXkyLmVtcGxhY2VCYWNrKGcreC0xLGcreCksaC5wdXNoKG1beF0ueCksaC5wdXNoKG1beF0ueSk7di52ZXJ0ZXhMZW5ndGgrPW0ubGVuZ3RoLHYucHJpbWl0aXZlTGVuZ3RoKz1tLmxlbmd0aDt9fWZvcih2YXIgYj1mbyhoLGYpLF89MDtfPGIubGVuZ3RoO18rPTMpdGhpcy5pbmRleEFycmF5LmVtcGxhY2VCYWNrKGMrYltfXSxjK2JbXysxXSxjK2JbXysyXSk7cC52ZXJ0ZXhMZW5ndGgrPXMscC5wcmltaXRpdmVMZW5ndGgrPWIubGVuZ3RoLzM7fXRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLnBvcHVsYXRlUGFpbnRBcnJheXModGhpcy5sYXlvdXRWZXJ0ZXhBcnJheS5sZW5ndGgsdCxyLG4pO30sem4oXCJGaWxsQnVja2V0XCIsR28se29taXQ6W1wibGF5ZXJzXCIsXCJmZWF0dXJlc1wiXX0pO3ZhciBYbz17cGFpbnQ6bmV3IGlpKHtcImZpbGwtYW50aWFsaWFzXCI6bmV3IFFuKEx0LnBhaW50X2ZpbGxbXCJmaWxsLWFudGlhbGlhc1wiXSksXCJmaWxsLW9wYWNpdHlcIjpuZXcgdGkoTHQucGFpbnRfZmlsbFtcImZpbGwtb3BhY2l0eVwiXSksXCJmaWxsLWNvbG9yXCI6bmV3IHRpKEx0LnBhaW50X2ZpbGxbXCJmaWxsLWNvbG9yXCJdKSxcImZpbGwtb3V0bGluZS1jb2xvclwiOm5ldyB0aShMdC5wYWludF9maWxsW1wiZmlsbC1vdXRsaW5lLWNvbG9yXCJdKSxcImZpbGwtdHJhbnNsYXRlXCI6bmV3IFFuKEx0LnBhaW50X2ZpbGxbXCJmaWxsLXRyYW5zbGF0ZVwiXSksXCJmaWxsLXRyYW5zbGF0ZS1hbmNob3JcIjpuZXcgUW4oTHQucGFpbnRfZmlsbFtcImZpbGwtdHJhbnNsYXRlLWFuY2hvclwiXSksXCJmaWxsLXBhdHRlcm5cIjpuZXcgZWkoTHQucGFpbnRfZmlsbFtcImZpbGwtcGF0dGVyblwiXSl9KX0sSm89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlKXt0LmNhbGwodGhpcyxlLFhvKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLnJlY2FsY3VsYXRlPWZ1bmN0aW9uKGUpe3QucHJvdG90eXBlLnJlY2FsY3VsYXRlLmNhbGwodGhpcyxlKTt2YXIgcj10aGlzLnBhaW50Ll92YWx1ZXNbXCJmaWxsLW91dGxpbmUtY29sb3JcIl07XCJjb25zdGFudFwiPT09ci52YWx1ZS5raW5kJiZ2b2lkIDA9PT1yLnZhbHVlLnZhbHVlJiYodGhpcy5wYWludC5fdmFsdWVzW1wiZmlsbC1vdXRsaW5lLWNvbG9yXCJdPXRoaXMucGFpbnQuX3ZhbHVlc1tcImZpbGwtY29sb3JcIl0pO30sZS5wcm90b3R5cGUuY3JlYXRlQnVja2V0PWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgR28odCl9LGUucHJvdG90eXBlLnF1ZXJ5UmFkaXVzPWZ1bmN0aW9uKCl7cmV0dXJuIFRhKHRoaXMucGFpbnQuZ2V0KFwiZmlsbC10cmFuc2xhdGVcIikpfSxlLnByb3RvdHlwZS5xdWVyeUludGVyc2VjdHNGZWF0dXJlPWZ1bmN0aW9uKHQsZSxyLG4saSxhLG8pe3JldHVybiB3YShQYSh0LHRoaXMucGFpbnQuZ2V0KFwiZmlsbC10cmFuc2xhdGVcIiksdGhpcy5wYWludC5nZXQoXCJmaWxsLXRyYW5zbGF0ZS1hbmNob3JcIiksYS5hbmdsZSxvKSxuKX0sZS5wcm90b3R5cGUuaXNUaWxlQ2xpcHBlZD1mdW5jdGlvbigpe3JldHVybiAhMH0sZX0oYWkpLEhvPWxpKFt7bmFtZTpcImFfcG9zXCIsY29tcG9uZW50czoyLHR5cGU6XCJJbnQxNlwifSx7bmFtZTpcImFfbm9ybWFsX2VkXCIsY29tcG9uZW50czo0LHR5cGU6XCJJbnQxNlwifV0sNCkubWVtYmVycyxZbz0kbztmdW5jdGlvbiAkbyh0LGUscixuLGkpe3RoaXMucHJvcGVydGllcz17fSx0aGlzLmV4dGVudD1yLHRoaXMudHlwZT0wLHRoaXMuX3BiZj10LHRoaXMuX2dlb21ldHJ5PS0xLHRoaXMuX2tleXM9bix0aGlzLl92YWx1ZXM9aSx0LnJlYWRGaWVsZHMoV28sdGhpcyxlKTt9ZnVuY3Rpb24gV28odCxlLHIpezE9PXQ/ZS5pZD1yLnJlYWRWYXJpbnQoKToyPT10P2Z1bmN0aW9uKHQsZSl7dmFyIHI9dC5yZWFkVmFyaW50KCkrdC5wb3M7Zm9yKDt0LnBvczxyOyl7dmFyIG49ZS5fa2V5c1t0LnJlYWRWYXJpbnQoKV0saT1lLl92YWx1ZXNbdC5yZWFkVmFyaW50KCldO2UucHJvcGVydGllc1tuXT1pO319KHIsZSk6Mz09dD9lLnR5cGU9ci5yZWFkVmFyaW50KCk6ND09dCYmKGUuX2dlb21ldHJ5PXIucG9zKTt9ZnVuY3Rpb24gUW8odCl7Zm9yKHZhciBlLHIsbj0wLGk9MCxhPXQubGVuZ3RoLG89YS0xO2k8YTtvPWkrKyllPXRbaV0sbis9KChyPXRbb10pLngtZS54KSooZS55K3IueSk7cmV0dXJuIG59JG8udHlwZXM9W1wiVW5rbm93blwiLFwiUG9pbnRcIixcIkxpbmVTdHJpbmdcIixcIlBvbHlnb25cIl0sJG8ucHJvdG90eXBlLmxvYWRHZW9tZXRyeT1mdW5jdGlvbigpe3ZhciB0PXRoaXMuX3BiZjt0LnBvcz10aGlzLl9nZW9tZXRyeTtmb3IodmFyIGUscj10LnJlYWRWYXJpbnQoKSt0LnBvcyxuPTEsYT0wLG89MCxzPTAsdT1bXTt0LnBvczxyOyl7aWYoYTw9MCl7dmFyIGw9dC5yZWFkVmFyaW50KCk7bj03JmwsYT1sPj4zO31pZihhLS0sMT09PW58fDI9PT1uKW8rPXQucmVhZFNWYXJpbnQoKSxzKz10LnJlYWRTVmFyaW50KCksMT09PW4mJihlJiZ1LnB1c2goZSksZT1bXSksZS5wdXNoKG5ldyBpKG8scykpO2Vsc2V7aWYoNyE9PW4pdGhyb3cgbmV3IEVycm9yKFwidW5rbm93biBjb21tYW5kIFwiK24pO2UmJmUucHVzaChlWzBdLmNsb25lKCkpO319cmV0dXJuIGUmJnUucHVzaChlKSx1fSwkby5wcm90b3R5cGUuYmJveD1mdW5jdGlvbigpe3ZhciB0PXRoaXMuX3BiZjt0LnBvcz10aGlzLl9nZW9tZXRyeTtmb3IodmFyIGU9dC5yZWFkVmFyaW50KCkrdC5wb3Mscj0xLG49MCxpPTAsYT0wLG89MS8wLHM9LTEvMCx1PTEvMCxsPS0xLzA7dC5wb3M8ZTspe2lmKG48PTApe3ZhciBwPXQucmVhZFZhcmludCgpO3I9NyZwLG49cD4+Mzt9aWYobi0tLDE9PT1yfHwyPT09cikoaSs9dC5yZWFkU1ZhcmludCgpKTxvJiYobz1pKSxpPnMmJihzPWkpLChhKz10LnJlYWRTVmFyaW50KCkpPHUmJih1PWEpLGE+bCYmKGw9YSk7ZWxzZSBpZig3IT09cil0aHJvdyBuZXcgRXJyb3IoXCJ1bmtub3duIGNvbW1hbmQgXCIrcil9cmV0dXJuIFtvLHUscyxsXX0sJG8ucHJvdG90eXBlLnRvR2VvSlNPTj1mdW5jdGlvbih0LGUscil7dmFyIG4saSxhPXRoaXMuZXh0ZW50Kk1hdGgucG93KDIsciksbz10aGlzLmV4dGVudCp0LHM9dGhpcy5leHRlbnQqZSx1PXRoaXMubG9hZEdlb21ldHJ5KCksbD0kby50eXBlc1t0aGlzLnR5cGVdO2Z1bmN0aW9uIHAodCl7Zm9yKHZhciBlPTA7ZTx0Lmxlbmd0aDtlKyspe3ZhciByPXRbZV0sbj0xODAtMzYwKihyLnkrcykvYTt0W2VdPVszNjAqKHIueCtvKS9hLTE4MCwzNjAvTWF0aC5QSSpNYXRoLmF0YW4oTWF0aC5leHAobipNYXRoLlBJLzE4MCkpLTkwXTt9fXN3aXRjaCh0aGlzLnR5cGUpe2Nhc2UgMTp2YXIgYz1bXTtmb3Iobj0wO248dS5sZW5ndGg7bisrKWNbbl09dVtuXVswXTtwKHU9Yyk7YnJlYWs7Y2FzZSAyOmZvcihuPTA7bjx1Lmxlbmd0aDtuKyspcCh1W25dKTticmVhaztjYXNlIDM6Zm9yKHU9ZnVuY3Rpb24odCl7dmFyIGU9dC5sZW5ndGg7aWYoZTw9MSlyZXR1cm4gW3RdO2Zvcih2YXIgcixuLGk9W10sYT0wO2E8ZTthKyspe3ZhciBvPVFvKHRbYV0pOzAhPT1vJiYodm9pZCAwPT09biYmKG49bzwwKSxuPT09bzwwPyhyJiZpLnB1c2gocikscj1bdFthXV0pOnIucHVzaCh0W2FdKSk7fXImJmkucHVzaChyKTtyZXR1cm4gaX0odSksbj0wO248dS5sZW5ndGg7bisrKWZvcihpPTA7aTx1W25dLmxlbmd0aDtpKyspcCh1W25dW2ldKTt9MT09PXUubGVuZ3RoP3U9dVswXTpsPVwiTXVsdGlcIitsO3ZhciBoPXt0eXBlOlwiRmVhdHVyZVwiLGdlb21ldHJ5Ont0eXBlOmwsY29vcmRpbmF0ZXM6dX0scHJvcGVydGllczp0aGlzLnByb3BlcnRpZXN9O3JldHVybiBcImlkXCJpbiB0aGlzJiYoaC5pZD10aGlzLmlkKSxofTt2YXIgdHM9ZXM7ZnVuY3Rpb24gZXModCxlKXt0aGlzLnZlcnNpb249MSx0aGlzLm5hbWU9bnVsbCx0aGlzLmV4dGVudD00MDk2LHRoaXMubGVuZ3RoPTAsdGhpcy5fcGJmPXQsdGhpcy5fa2V5cz1bXSx0aGlzLl92YWx1ZXM9W10sdGhpcy5fZmVhdHVyZXM9W10sdC5yZWFkRmllbGRzKHJzLHRoaXMsZSksdGhpcy5sZW5ndGg9dGhpcy5fZmVhdHVyZXMubGVuZ3RoO31mdW5jdGlvbiBycyh0LGUscil7MTU9PT10P2UudmVyc2lvbj1yLnJlYWRWYXJpbnQoKToxPT09dD9lLm5hbWU9ci5yZWFkU3RyaW5nKCk6NT09PXQ/ZS5leHRlbnQ9ci5yZWFkVmFyaW50KCk6Mj09PXQ/ZS5fZmVhdHVyZXMucHVzaChyLnBvcyk6Mz09PXQ/ZS5fa2V5cy5wdXNoKHIucmVhZFN0cmluZygpKTo0PT09dCYmZS5fdmFsdWVzLnB1c2goZnVuY3Rpb24odCl7dmFyIGU9bnVsbCxyPXQucmVhZFZhcmludCgpK3QucG9zO2Zvcig7dC5wb3M8cjspe3ZhciBuPXQucmVhZFZhcmludCgpPj4zO2U9MT09PW4/dC5yZWFkU3RyaW5nKCk6Mj09PW4/dC5yZWFkRmxvYXQoKTozPT09bj90LnJlYWREb3VibGUoKTo0PT09bj90LnJlYWRWYXJpbnQ2NCgpOjU9PT1uP3QucmVhZFZhcmludCgpOjY9PT1uP3QucmVhZFNWYXJpbnQoKTo3PT09bj90LnJlYWRCb29sZWFuKCk6bnVsbDt9cmV0dXJuIGV9KHIpKTt9ZnVuY3Rpb24gbnModCxlLHIpe2lmKDM9PT10KXt2YXIgbj1uZXcgdHMocixyLnJlYWRWYXJpbnQoKStyLnBvcyk7bi5sZW5ndGgmJihlW24ubmFtZV09bik7fX1lcy5wcm90b3R5cGUuZmVhdHVyZT1mdW5jdGlvbih0KXtpZih0PDB8fHQ+PXRoaXMuX2ZlYXR1cmVzLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoXCJmZWF0dXJlIGluZGV4IG91dCBvZiBib3VuZHNcIik7dGhpcy5fcGJmLnBvcz10aGlzLl9mZWF0dXJlc1t0XTt2YXIgZT10aGlzLl9wYmYucmVhZFZhcmludCgpK3RoaXMuX3BiZi5wb3M7cmV0dXJuIG5ldyBZbyh0aGlzLl9wYmYsZSx0aGlzLmV4dGVudCx0aGlzLl9rZXlzLHRoaXMuX3ZhbHVlcyl9O3ZhciBpcz17VmVjdG9yVGlsZTpmdW5jdGlvbih0LGUpe3RoaXMubGF5ZXJzPXQucmVhZEZpZWxkcyhucyx7fSxlKTt9LFZlY3RvclRpbGVGZWF0dXJlOllvLFZlY3RvclRpbGVMYXllcjp0c30sYXM9aXMuVmVjdG9yVGlsZUZlYXR1cmUudHlwZXMsb3M9TWF0aC5wb3coMiwxMyk7ZnVuY3Rpb24gc3ModCxlLHIsbixpLGEsbyxzKXt0LmVtcGxhY2VCYWNrKGUsciwyKk1hdGguZmxvb3IobipvcykrbyxpKm9zKjIsYSpvcyoyLE1hdGgucm91bmQocykpO312YXIgdXM9ZnVuY3Rpb24odCl7dGhpcy56b29tPXQuem9vbSx0aGlzLm92ZXJzY2FsaW5nPXQub3ZlcnNjYWxpbmcsdGhpcy5sYXllcnM9dC5sYXllcnMsdGhpcy5sYXllcklkcz10aGlzLmxheWVycy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuaWR9KSx0aGlzLmluZGV4PXQuaW5kZXgsdGhpcy5oYXNQYXR0ZXJuPSExLHRoaXMubGF5b3V0VmVydGV4QXJyYXk9bmV3IGZpLHRoaXMuaW5kZXhBcnJheT1uZXcgSWksdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnM9bmV3IGNhKEhvLHQubGF5ZXJzLHQuem9vbSksdGhpcy5zZWdtZW50cz1uZXcgS2ksdGhpcy5zdGF0ZURlcGVuZGVudExheWVySWRzPXRoaXMubGF5ZXJzLmZpbHRlcihmdW5jdGlvbih0KXtyZXR1cm4gdC5pc1N0YXRlRGVwZW5kZW50KCl9KS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuaWR9KTt9O2Z1bmN0aW9uIGxzKHQsZSl7cmV0dXJuIHQueD09PWUueCYmKHQueDwwfHx0Lng+eWEpfHx0Lnk9PT1lLnkmJih0Lnk8MHx8dC55PnlhKX1mdW5jdGlvbiBwcyh0KXtyZXR1cm4gdC5ldmVyeShmdW5jdGlvbih0KXtyZXR1cm4gdC54PDB9KXx8dC5ldmVyeShmdW5jdGlvbih0KXtyZXR1cm4gdC54PnlhfSl8fHQuZXZlcnkoZnVuY3Rpb24odCl7cmV0dXJuIHQueTwwfSl8fHQuZXZlcnkoZnVuY3Rpb24odCl7cmV0dXJuIHQueT55YX0pfXVzLnByb3RvdHlwZS5wb3B1bGF0ZT1mdW5jdGlvbih0LGUpe3RoaXMuZmVhdHVyZXM9W10sdGhpcy5oYXNQYXR0ZXJuPVpvKFwiZmlsbC1leHRydXNpb25cIix0aGlzLmxheWVycyxlKTtmb3IodmFyIHI9MCxuPXQ7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdLGE9aS5mZWF0dXJlLG89aS5pbmRleCxzPWkuc291cmNlTGF5ZXJJbmRleDtpZih0aGlzLmxheWVyc1swXS5fZmVhdHVyZUZpbHRlcihuZXcgWm4odGhpcy56b29tKSxhKSl7dmFyIHU9dmEoYSksbD17c291cmNlTGF5ZXJJbmRleDpzLGluZGV4Om8sZ2VvbWV0cnk6dSxwcm9wZXJ0aWVzOmEucHJvcGVydGllcyx0eXBlOmEudHlwZSxwYXR0ZXJuczp7fX07dm9pZCAwIT09YS5pZCYmKGwuaWQ9YS5pZCksdGhpcy5oYXNQYXR0ZXJuP3RoaXMuZmVhdHVyZXMucHVzaChLbyhcImZpbGwtZXh0cnVzaW9uXCIsdGhpcy5sYXllcnMsbCx0aGlzLnpvb20sZSkpOnRoaXMuYWRkRmVhdHVyZShsLHUsbyx7fSksZS5mZWF0dXJlSW5kZXguaW5zZXJ0KGEsdSxvLHMsdGhpcy5pbmRleCwhMCk7fX19LHVzLnByb3RvdHlwZS5hZGRGZWF0dXJlcz1mdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0wLG49dGhpcy5mZWF0dXJlcztyPG4ubGVuZ3RoO3IrPTEpe3ZhciBpPW5bcl0sYT1pLmdlb21ldHJ5O3RoaXMuYWRkRmVhdHVyZShpLGEsaS5pbmRleCxlKTt9fSx1cy5wcm90b3R5cGUudXBkYXRlPWZ1bmN0aW9uKHQsZSxyKXt0aGlzLnN0YXRlRGVwZW5kZW50TGF5ZXJzLmxlbmd0aCYmdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMudXBkYXRlUGFpbnRBcnJheXModCxlLHRoaXMuc3RhdGVEZXBlbmRlbnRMYXllcnMscik7fSx1cy5wcm90b3R5cGUuaXNFbXB0eT1mdW5jdGlvbigpe3JldHVybiAwPT09dGhpcy5sYXlvdXRWZXJ0ZXhBcnJheS5sZW5ndGh9LHVzLnByb3RvdHlwZS51cGxvYWRQZW5kaW5nPWZ1bmN0aW9uKCl7cmV0dXJuICF0aGlzLnVwbG9hZGVkfHx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy5uZWVkc1VwbG9hZH0sdXMucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbih0KXt0aGlzLnVwbG9hZGVkfHwodGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXI9dC5jcmVhdGVWZXJ0ZXhCdWZmZXIodGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSxIbyksdGhpcy5pbmRleEJ1ZmZlcj10LmNyZWF0ZUluZGV4QnVmZmVyKHRoaXMuaW5kZXhBcnJheSkpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLnVwbG9hZCh0KSx0aGlzLnVwbG9hZGVkPSEwO30sdXMucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLmxheW91dFZlcnRleEJ1ZmZlciYmKHRoaXMubGF5b3V0VmVydGV4QnVmZmVyLmRlc3Ryb3koKSx0aGlzLmluZGV4QnVmZmVyLmRlc3Ryb3koKSx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy5kZXN0cm95KCksdGhpcy5zZWdtZW50cy5kZXN0cm95KCkpO30sdXMucHJvdG90eXBlLmFkZEZlYXR1cmU9ZnVuY3Rpb24odCxlLHIsbil7Zm9yKHZhciBpPTAsYT1xbyhlLDUwMCk7aTxhLmxlbmd0aDtpKz0xKXtmb3IodmFyIG89YVtpXSxzPTAsdT0wLGw9bzt1PGwubGVuZ3RoO3UrPTEpe3MrPWxbdV0ubGVuZ3RoO31mb3IodmFyIHA9dGhpcy5zZWdtZW50cy5wcmVwYXJlU2VnbWVudCg0LHRoaXMubGF5b3V0VmVydGV4QXJyYXksdGhpcy5pbmRleEFycmF5KSxjPTAsaD1vO2M8aC5sZW5ndGg7Yys9MSl7dmFyIGY9aFtjXTtpZigwIT09Zi5sZW5ndGgmJiFwcyhmKSlmb3IodmFyIHk9MCxkPTA7ZDxmLmxlbmd0aDtkKyspe3ZhciBtPWZbZF07aWYoZD49MSl7dmFyIHY9ZltkLTFdO2lmKCFscyhtLHYpKXtwLnZlcnRleExlbmd0aCs0PktpLk1BWF9WRVJURVhfQVJSQVlfTEVOR1RIJiYocD10aGlzLnNlZ21lbnRzLnByZXBhcmVTZWdtZW50KDQsdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSx0aGlzLmluZGV4QXJyYXkpKTt2YXIgZz1tLnN1Yih2KS5fcGVycCgpLl91bml0KCkseD12LmRpc3QobSk7eSt4PjMyNzY4JiYoeT0wKSxzcyh0aGlzLmxheW91dFZlcnRleEFycmF5LG0ueCxtLnksZy54LGcueSwwLDAseSksc3ModGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSxtLngsbS55LGcueCxnLnksMCwxLHkpLHkrPXgsc3ModGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSx2Lngsdi55LGcueCxnLnksMCwwLHkpLHNzKHRoaXMubGF5b3V0VmVydGV4QXJyYXksdi54LHYueSxnLngsZy55LDAsMSx5KTt2YXIgYj1wLnZlcnRleExlbmd0aDt0aGlzLmluZGV4QXJyYXkuZW1wbGFjZUJhY2soYixiKzIsYisxKSx0aGlzLmluZGV4QXJyYXkuZW1wbGFjZUJhY2soYisxLGIrMixiKzMpLHAudmVydGV4TGVuZ3RoKz00LHAucHJpbWl0aXZlTGVuZ3RoKz0yO319fX1pZihwLnZlcnRleExlbmd0aCtzPktpLk1BWF9WRVJURVhfQVJSQVlfTEVOR1RIJiYocD10aGlzLnNlZ21lbnRzLnByZXBhcmVTZWdtZW50KHMsdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSx0aGlzLmluZGV4QXJyYXkpKSxcIlBvbHlnb25cIj09PWFzW3QudHlwZV0pe2Zvcih2YXIgXz1bXSx3PVtdLEE9cC52ZXJ0ZXhMZW5ndGgsUz0wLGs9bztTPGsubGVuZ3RoO1MrPTEpe3ZhciB6PWtbU107aWYoMCE9PXoubGVuZ3RoKXt6IT09b1swXSYmdy5wdXNoKF8ubGVuZ3RoLzIpO2Zvcih2YXIgST0wO0k8ei5sZW5ndGg7SSsrKXt2YXIgQj16W0ldO3NzKHRoaXMubGF5b3V0VmVydGV4QXJyYXksQi54LEIueSwwLDAsMSwxLDApLF8ucHVzaChCLngpLF8ucHVzaChCLnkpO319fWZvcih2YXIgQz1mbyhfLHcpLEU9MDtFPEMubGVuZ3RoO0UrPTMpdGhpcy5pbmRleEFycmF5LmVtcGxhY2VCYWNrKEErQ1tFXSxBK0NbRSsyXSxBK0NbRSsxXSk7cC5wcmltaXRpdmVMZW5ndGgrPUMubGVuZ3RoLzMscC52ZXJ0ZXhMZW5ndGgrPXM7fX10aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy5wb3B1bGF0ZVBhaW50QXJyYXlzKHRoaXMubGF5b3V0VmVydGV4QXJyYXkubGVuZ3RoLHQscixuKTt9LHpuKFwiRmlsbEV4dHJ1c2lvbkJ1Y2tldFwiLHVzLHtvbWl0OltcImxheWVyc1wiLFwiZmVhdHVyZXNcIl19KTt2YXIgY3M9e3BhaW50Om5ldyBpaSh7XCJmaWxsLWV4dHJ1c2lvbi1vcGFjaXR5XCI6bmV3IFFuKEx0W1wicGFpbnRfZmlsbC1leHRydXNpb25cIl1bXCJmaWxsLWV4dHJ1c2lvbi1vcGFjaXR5XCJdKSxcImZpbGwtZXh0cnVzaW9uLWNvbG9yXCI6bmV3IHRpKEx0W1wicGFpbnRfZmlsbC1leHRydXNpb25cIl1bXCJmaWxsLWV4dHJ1c2lvbi1jb2xvclwiXSksXCJmaWxsLWV4dHJ1c2lvbi10cmFuc2xhdGVcIjpuZXcgUW4oTHRbXCJwYWludF9maWxsLWV4dHJ1c2lvblwiXVtcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZVwiXSksXCJmaWxsLWV4dHJ1c2lvbi10cmFuc2xhdGUtYW5jaG9yXCI6bmV3IFFuKEx0W1wicGFpbnRfZmlsbC1leHRydXNpb25cIl1bXCJmaWxsLWV4dHJ1c2lvbi10cmFuc2xhdGUtYW5jaG9yXCJdKSxcImZpbGwtZXh0cnVzaW9uLXBhdHRlcm5cIjpuZXcgZWkoTHRbXCJwYWludF9maWxsLWV4dHJ1c2lvblwiXVtcImZpbGwtZXh0cnVzaW9uLXBhdHRlcm5cIl0pLFwiZmlsbC1leHRydXNpb24taGVpZ2h0XCI6bmV3IHRpKEx0W1wicGFpbnRfZmlsbC1leHRydXNpb25cIl1bXCJmaWxsLWV4dHJ1c2lvbi1oZWlnaHRcIl0pLFwiZmlsbC1leHRydXNpb24tYmFzZVwiOm5ldyB0aShMdFtcInBhaW50X2ZpbGwtZXh0cnVzaW9uXCJdW1wiZmlsbC1leHRydXNpb24tYmFzZVwiXSksXCJmaWxsLWV4dHJ1c2lvbi12ZXJ0aWNhbC1ncmFkaWVudFwiOm5ldyBRbihMdFtcInBhaW50X2ZpbGwtZXh0cnVzaW9uXCJdW1wiZmlsbC1leHRydXNpb24tdmVydGljYWwtZ3JhZGllbnRcIl0pfSl9LGhzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSxjcyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5jcmVhdGVCdWNrZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyB1cyh0KX0sZS5wcm90b3R5cGUucXVlcnlSYWRpdXM9ZnVuY3Rpb24oKXtyZXR1cm4gVGEodGhpcy5wYWludC5nZXQoXCJmaWxsLWV4dHJ1c2lvbi10cmFuc2xhdGVcIikpfSxlLnByb3RvdHlwZS5pczNEPWZ1bmN0aW9uKCl7cmV0dXJuICEwfSxlLnByb3RvdHlwZS5xdWVyeUludGVyc2VjdHNGZWF0dXJlPWZ1bmN0aW9uKHQsZSxyLG4sYSxvLHMsdSl7dmFyIGw9UGEodCx0aGlzLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZVwiKSx0aGlzLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZS1hbmNob3JcIiksby5hbmdsZSxzKSxwPXRoaXMucGFpbnQuZ2V0KFwiZmlsbC1leHRydXNpb24taGVpZ2h0XCIpLmV2YWx1YXRlKGUsciksYz10aGlzLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLWJhc2VcIikuZXZhbHVhdGUoZSxyKSxoPWZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgYT1bXSxvPTAscz10O288cy5sZW5ndGg7bys9MSl7dmFyIHU9c1tvXSxsPVt1LngsdS55LG4sMV07TmEobCxsLGUpLGEucHVzaChuZXcgaShsWzBdL2xbM10sbFsxXS9sWzNdKSk7fXJldHVybiBhfShsLHUsMCwwKSxmPWZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgYT1bXSxvPVtdLHM9bls4XSplLHU9bls5XSplLGw9blsxMF0qZSxwPW5bMTFdKmUsYz1uWzhdKnIsaD1uWzldKnIsZj1uWzEwXSpyLHk9blsxMV0qcixkPTAsbT10O2Q8bS5sZW5ndGg7ZCs9MSl7Zm9yKHZhciB2PW1bZF0sZz1bXSx4PVtdLGI9MCxfPXY7YjxfLmxlbmd0aDtiKz0xKXt2YXIgdz1fW2JdLEE9dy54LFM9dy55LGs9blswXSpBK25bNF0qUytuWzEyXSx6PW5bMV0qQStuWzVdKlMrblsxM10sST1uWzJdKkErbls2XSpTK25bMTRdLEI9blszXSpBK25bN10qUytuWzE1XSxDPWsrcyxFPXordSxNPUkrbCxUPUIrcCxQPWsrYyxWPXoraCxGPUkrZixMPUIreSxEPW5ldyBpKEMvVCxFL1QpO0Quej1NL1QsZy5wdXNoKEQpO3ZhciBPPW5ldyBpKFAvTCxWL0wpO08uej1GL0wseC5wdXNoKE8pO31hLnB1c2goZyksby5wdXNoKHgpO31yZXR1cm4gW2Esb119KG4sYyxwLHUpO3JldHVybiBmdW5jdGlvbih0LGUscil7dmFyIG49MS8wO3dhKHIsZSkmJihuPXlzKHIsZVswXSkpO2Zvcih2YXIgaT0wO2k8ZS5sZW5ndGg7aSsrKWZvcih2YXIgYT1lW2ldLG89dFtpXSxzPTA7czxhLmxlbmd0aC0xO3MrKyl7dmFyIHU9YVtzXSxsPWFbcysxXSxwPW9bc10sYz1vW3MrMV0saD1bdSxsLGMscCx1XTtiYShyLGgpJiYobj1NYXRoLm1pbihuLHlzKHIsaCkpKTt9cmV0dXJuIG4hPT0xLzAmJm59KGZbMF0sZlsxXSxoKX0sZX0oYWkpO2Z1bmN0aW9uIGZzKHQsZSl7cmV0dXJuIHQueCplLngrdC55KmUueX1mdW5jdGlvbiB5cyh0LGUpe2lmKDE9PT10Lmxlbmd0aCl7dmFyIHI9ZVswXSxuPWVbMV0saT1lWzNdLGE9dFswXSxvPW4uc3ViKHIpLHM9aS5zdWIociksdT1hLnN1YihyKSxsPWZzKG8sbykscD1mcyhvLHMpLGM9ZnMocyxzKSxoPWZzKHUsbyksZj1mcyh1LHMpLHk9bCpjLXAqcCxkPShjKmgtcCpmKS95LG09KGwqZi1wKmgpL3ksdj0xLWQtbTtyZXR1cm4gci56KnYrbi56KmQraS56Km19Zm9yKHZhciBnPTEvMCx4PTAsYj1lO3g8Yi5sZW5ndGg7eCs9MSl7dmFyIF89Ylt4XTtnPU1hdGgubWluKGcsXy56KTt9cmV0dXJuIGd9dmFyIGRzPWxpKFt7bmFtZTpcImFfcG9zX25vcm1hbFwiLGNvbXBvbmVudHM6Mix0eXBlOlwiSW50MTZcIn0se25hbWU6XCJhX2RhdGFcIixjb21wb25lbnRzOjQsdHlwZTpcIlVpbnQ4XCJ9XSw0KS5tZW1iZXJzLG1zPWlzLlZlY3RvclRpbGVGZWF0dXJlLnR5cGVzLHZzPTYzLGdzPU1hdGguY29zKE1hdGguUEkvMTgwKjM3LjUpLHhzPS41LGJzPU1hdGgucG93KDIsMTQpL3hzO2Z1bmN0aW9uIF9zKHQsZSxyLG4saSxhLG8pe3QuZW1wbGFjZUJhY2soKGUueDw8MSkrKG4/MTowKSwoZS55PDwxKSsoaT8xOjApLE1hdGgucm91bmQodnMqci54KSsxMjgsTWF0aC5yb3VuZCh2cypyLnkpKzEyOCwxKygwPT09YT8wOmE8MD8tMToxKXwobyp4cyY2Myk8PDIsbyp4cz4+Nik7fXZhciB3cz1mdW5jdGlvbih0KXt0aGlzLnpvb209dC56b29tLHRoaXMub3ZlcnNjYWxpbmc9dC5vdmVyc2NhbGluZyx0aGlzLmxheWVycz10LmxheWVycyx0aGlzLmxheWVySWRzPXRoaXMubGF5ZXJzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdC5pZH0pLHRoaXMuaW5kZXg9dC5pbmRleCx0aGlzLmZlYXR1cmVzPVtdLHRoaXMuaGFzUGF0dGVybj0hMSx0aGlzLmxheW91dFZlcnRleEFycmF5PW5ldyB5aSx0aGlzLmluZGV4QXJyYXk9bmV3IElpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zPW5ldyBjYShkcyx0LmxheWVycyx0Lnpvb20pLHRoaXMuc2VnbWVudHM9bmV3IEtpLHRoaXMuc3RhdGVEZXBlbmRlbnRMYXllcklkcz10aGlzLmxheWVycy5maWx0ZXIoZnVuY3Rpb24odCl7cmV0dXJuIHQuaXNTdGF0ZURlcGVuZGVudCgpfSkubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkfSk7fTtmdW5jdGlvbiBBcyh0LGUpe3JldHVybiAodC9lLnRpbGVUb3RhbCooZS5lbmQtZS5zdGFydCkrZS5zdGFydCkqKGJzLTEpfXdzLnByb3RvdHlwZS5wb3B1bGF0ZT1mdW5jdGlvbih0LGUpe3RoaXMuZmVhdHVyZXM9W10sdGhpcy5oYXNQYXR0ZXJuPVpvKFwibGluZVwiLHRoaXMubGF5ZXJzLGUpO2Zvcih2YXIgcj0wLG49dDtyPG4ubGVuZ3RoO3IrPTEpe3ZhciBpPW5bcl0sYT1pLmZlYXR1cmUsbz1pLmluZGV4LHM9aS5zb3VyY2VMYXllckluZGV4O2lmKHRoaXMubGF5ZXJzWzBdLl9mZWF0dXJlRmlsdGVyKG5ldyBabih0aGlzLnpvb20pLGEpKXt2YXIgdT12YShhKSxsPXtzb3VyY2VMYXllckluZGV4OnMsaW5kZXg6byxnZW9tZXRyeTp1LHByb3BlcnRpZXM6YS5wcm9wZXJ0aWVzLHR5cGU6YS50eXBlLHBhdHRlcm5zOnt9fTt2b2lkIDAhPT1hLmlkJiYobC5pZD1hLmlkKSx0aGlzLmhhc1BhdHRlcm4/dGhpcy5mZWF0dXJlcy5wdXNoKEtvKFwibGluZVwiLHRoaXMubGF5ZXJzLGwsdGhpcy56b29tLGUpKTp0aGlzLmFkZEZlYXR1cmUobCx1LG8se30pLGUuZmVhdHVyZUluZGV4Lmluc2VydChhLHUsbyxzLHRoaXMuaW5kZXgpO319fSx3cy5wcm90b3R5cGUudXBkYXRlPWZ1bmN0aW9uKHQsZSxyKXt0aGlzLnN0YXRlRGVwZW5kZW50TGF5ZXJzLmxlbmd0aCYmdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMudXBkYXRlUGFpbnRBcnJheXModCxlLHRoaXMuc3RhdGVEZXBlbmRlbnRMYXllcnMscik7fSx3cy5wcm90b3R5cGUuYWRkRmVhdHVyZXM9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9MCxuPXRoaXMuZmVhdHVyZXM7cjxuLmxlbmd0aDtyKz0xKXt2YXIgaT1uW3JdLGE9aS5nZW9tZXRyeTt0aGlzLmFkZEZlYXR1cmUoaSxhLGkuaW5kZXgsZSk7fX0sd3MucHJvdG90eXBlLmlzRW1wdHk9ZnVuY3Rpb24oKXtyZXR1cm4gMD09PXRoaXMubGF5b3V0VmVydGV4QXJyYXkubGVuZ3RofSx3cy5wcm90b3R5cGUudXBsb2FkUGVuZGluZz1mdW5jdGlvbigpe3JldHVybiAhdGhpcy51cGxvYWRlZHx8dGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMubmVlZHNVcGxvYWR9LHdzLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCl7dGhpcy51cGxvYWRlZHx8KHRoaXMubGF5b3V0VmVydGV4QnVmZmVyPXQuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMubGF5b3V0VmVydGV4QXJyYXksZHMpLHRoaXMuaW5kZXhCdWZmZXI9dC5jcmVhdGVJbmRleEJ1ZmZlcih0aGlzLmluZGV4QXJyYXkpKSx0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy51cGxvYWQodCksdGhpcy51cGxvYWRlZD0hMDt9LHdzLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXImJih0aGlzLmxheW91dFZlcnRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5pbmRleEJ1ZmZlci5kZXN0cm95KCksdGhpcy5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZGVzdHJveSgpLHRoaXMuc2VnbWVudHMuZGVzdHJveSgpKTt9LHdzLnByb3RvdHlwZS5hZGRGZWF0dXJlPWZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgaT10aGlzLmxheWVyc1swXS5sYXlvdXQsYT1pLmdldChcImxpbmUtam9pblwiKS5ldmFsdWF0ZSh0LHt9KSxvPWkuZ2V0KFwibGluZS1jYXBcIikscz1pLmdldChcImxpbmUtbWl0ZXItbGltaXRcIiksdT1pLmdldChcImxpbmUtcm91bmQtbGltaXRcIiksbD0wLHA9ZTtsPHAubGVuZ3RoO2wrPTEpe3ZhciBjPXBbbF07dGhpcy5hZGRMaW5lKGMsdCxhLG8scyx1LHIsbik7fX0sd3MucHJvdG90eXBlLmFkZExpbmU9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyxzKXt2YXIgdT1udWxsO2UucHJvcGVydGllcyYmZS5wcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KFwibWFwYm94X2NsaXBfc3RhcnRcIikmJmUucHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShcIm1hcGJveF9jbGlwX2VuZFwiKSYmKHU9e3N0YXJ0OmUucHJvcGVydGllcy5tYXBib3hfY2xpcF9zdGFydCxlbmQ6ZS5wcm9wZXJ0aWVzLm1hcGJveF9jbGlwX2VuZCx0aWxlVG90YWw6dm9pZCAwfSk7Zm9yKHZhciBsPVwiUG9seWdvblwiPT09bXNbZS50eXBlXSxwPXQubGVuZ3RoO3A+PTImJnRbcC0xXS5lcXVhbHModFtwLTJdKTspcC0tO2Zvcih2YXIgYz0wO2M8cC0xJiZ0W2NdLmVxdWFscyh0W2MrMV0pOyljKys7aWYoIShwPChsPzM6MikpKXt1JiYodS50aWxlVG90YWw9ZnVuY3Rpb24odCxlLHIpe2Zvcih2YXIgbixpLGE9MCxvPWU7bzxyLTE7bysrKW49dFtvXSxpPXRbbysxXSxhKz1uLmRpc3QoaSk7cmV0dXJuIGF9KHQsYyxwKSksXCJiZXZlbFwiPT09ciYmKGk9MS4wNSk7dmFyIGg9eWEvKDUxMip0aGlzLm92ZXJzY2FsaW5nKSoxNSxmPXRbY10seT10aGlzLnNlZ21lbnRzLnByZXBhcmVTZWdtZW50KDEwKnAsdGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSx0aGlzLmluZGV4QXJyYXkpO3RoaXMuZGlzdGFuY2U9MDt2YXIgZCxtLHYsZz1uLHg9bD9cImJ1dHRcIjpuLGI9ITAsXz12b2lkIDAsdz12b2lkIDAsQT12b2lkIDAsUz12b2lkIDA7dGhpcy5lMT10aGlzLmUyPXRoaXMuZTM9LTEsbCYmKGQ9dFtwLTJdLFM9Zi5zdWIoZCkuX3VuaXQoKS5fcGVycCgpKTtmb3IodmFyIGs9YztrPHA7aysrKWlmKCEodz1sJiZrPT09cC0xP3RbYysxXTp0W2srMV0pfHwhdFtrXS5lcXVhbHModykpe1MmJihBPVMpLGQmJihfPWQpLGQ9dFtrXSxTPXc/dy5zdWIoZCkuX3VuaXQoKS5fcGVycCgpOkE7dmFyIHo9KEE9QXx8UykuYWRkKFMpOzA9PT16LngmJjA9PT16Lnl8fHouX3VuaXQoKTt2YXIgST16LngqUy54K3oueSpTLnksQj0wIT09ST8xL0k6MS8wLEM9STxncyYmXyYmdztpZihDJiZrPmMpe3ZhciBFPWQuZGlzdChfKTtpZihFPjIqaCl7dmFyIE09ZC5zdWIoZC5zdWIoXykuX211bHQoaC9FKS5fcm91bmQoKSk7dGhpcy5kaXN0YW5jZSs9TS5kaXN0KF8pLHRoaXMuYWRkQ3VycmVudFZlcnRleChNLHRoaXMuZGlzdGFuY2UsQS5tdWx0KDEpLDAsMCwhMSx5LHUpLF89TTt9fXZhciBUPV8mJncsUD1UP3I6dz9nOng7aWYoVCYmXCJyb3VuZFwiPT09UCYmKEI8YT9QPVwibWl0ZXJcIjpCPD0yJiYoUD1cImZha2Vyb3VuZFwiKSksXCJtaXRlclwiPT09UCYmQj5pJiYoUD1cImJldmVsXCIpLFwiYmV2ZWxcIj09PVAmJihCPjImJihQPVwiZmxpcGJldmVsXCIpLEI8aSYmKFA9XCJtaXRlclwiKSksXyYmKHRoaXMuZGlzdGFuY2UrPWQuZGlzdChfKSksXCJtaXRlclwiPT09UCl6Ll9tdWx0KEIpLHRoaXMuYWRkQ3VycmVudFZlcnRleChkLHRoaXMuZGlzdGFuY2UseiwwLDAsITEseSx1KTtlbHNlIGlmKFwiZmxpcGJldmVsXCI9PT1QKXtpZihCPjEwMCl6PVMuY2xvbmUoKS5tdWx0KC0xKTtlbHNle3ZhciBWPUEueCpTLnktQS55KlMueD4wPy0xOjEsRj1CKkEuYWRkKFMpLm1hZygpL0Euc3ViKFMpLm1hZygpO3ouX3BlcnAoKS5fbXVsdChGKlYpO310aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZCx0aGlzLmRpc3RhbmNlLHosMCwwLCExLHksdSksdGhpcy5hZGRDdXJyZW50VmVydGV4KGQsdGhpcy5kaXN0YW5jZSx6Lm11bHQoLTEpLDAsMCwhMSx5LHUpO31lbHNlIGlmKFwiYmV2ZWxcIj09PVB8fFwiZmFrZXJvdW5kXCI9PT1QKXt2YXIgTD1BLngqUy55LUEueSpTLng+MCxEPS1NYXRoLnNxcnQoQipCLTEpO2lmKEw/KHY9MCxtPUQpOihtPTAsdj1EKSxifHx0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZCx0aGlzLmRpc3RhbmNlLEEsbSx2LCExLHksdSksXCJmYWtlcm91bmRcIj09PVApe2Zvcih2YXIgTz1NYXRoLmZsb29yKDgqKC41LShJLS41KSkpLFI9dm9pZCAwLFU9MDtVPE87VSsrKVI9Uy5tdWx0KChVKzEpLyhPKzEpKS5fYWRkKEEpLl91bml0KCksdGhpcy5hZGRQaWVTbGljZVZlcnRleChkLHRoaXMuZGlzdGFuY2UsUixMLHksdSk7dGhpcy5hZGRQaWVTbGljZVZlcnRleChkLHRoaXMuZGlzdGFuY2UseixMLHksdSk7Zm9yKHZhciBqPU8tMTtqPj0wO2otLSlSPUEubXVsdCgoaisxKS8oTysxKSkuX2FkZChTKS5fdW5pdCgpLHRoaXMuYWRkUGllU2xpY2VWZXJ0ZXgoZCx0aGlzLmRpc3RhbmNlLFIsTCx5LHUpO313JiZ0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZCx0aGlzLmRpc3RhbmNlLFMsLW0sLXYsITEseSx1KTt9ZWxzZVwiYnV0dFwiPT09UD8oYnx8dGhpcy5hZGRDdXJyZW50VmVydGV4KGQsdGhpcy5kaXN0YW5jZSxBLDAsMCwhMSx5LHUpLHcmJnRoaXMuYWRkQ3VycmVudFZlcnRleChkLHRoaXMuZGlzdGFuY2UsUywwLDAsITEseSx1KSk6XCJzcXVhcmVcIj09PVA/KGJ8fCh0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZCx0aGlzLmRpc3RhbmNlLEEsMSwxLCExLHksdSksdGhpcy5lMT10aGlzLmUyPS0xKSx3JiZ0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZCx0aGlzLmRpc3RhbmNlLFMsLTEsLTEsITEseSx1KSk6XCJyb3VuZFwiPT09UCYmKGJ8fCh0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoZCx0aGlzLmRpc3RhbmNlLEEsMCwwLCExLHksdSksdGhpcy5hZGRDdXJyZW50VmVydGV4KGQsdGhpcy5kaXN0YW5jZSxBLDEsMSwhMCx5LHUpLHRoaXMuZTE9dGhpcy5lMj0tMSksdyYmKHRoaXMuYWRkQ3VycmVudFZlcnRleChkLHRoaXMuZGlzdGFuY2UsUywtMSwtMSwhMCx5LHUpLHRoaXMuYWRkQ3VycmVudFZlcnRleChkLHRoaXMuZGlzdGFuY2UsUywwLDAsITEseSx1KSkpO2lmKEMmJms8cC0xKXt2YXIgcT1kLmRpc3Qodyk7aWYocT4yKmgpe3ZhciBOPWQuYWRkKHcuc3ViKGQpLl9tdWx0KGgvcSkuX3JvdW5kKCkpO3RoaXMuZGlzdGFuY2UrPU4uZGlzdChkKSx0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgoTix0aGlzLmRpc3RhbmNlLFMubXVsdCgxKSwwLDAsITEseSx1KSxkPU47fX1iPSExO310aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy5wb3B1bGF0ZVBhaW50QXJyYXlzKHRoaXMubGF5b3V0VmVydGV4QXJyYXkubGVuZ3RoLGUsbyxzKTt9fSx3cy5wcm90b3R5cGUuYWRkQ3VycmVudFZlcnRleD1mdW5jdGlvbih0LGUscixuLGksYSxvLHMpe3ZhciB1LGw9dGhpcy5sYXlvdXRWZXJ0ZXhBcnJheSxwPXRoaXMuaW5kZXhBcnJheTtzJiYoZT1BcyhlLHMpKSx1PXIuY2xvbmUoKSxuJiZ1Ll9zdWIoci5wZXJwKCkuX211bHQobikpLF9zKGwsdCx1LGEsITEsbixlKSx0aGlzLmUzPW8udmVydGV4TGVuZ3RoKyssdGhpcy5lMT49MCYmdGhpcy5lMj49MCYmKHAuZW1wbGFjZUJhY2sodGhpcy5lMSx0aGlzLmUyLHRoaXMuZTMpLG8ucHJpbWl0aXZlTGVuZ3RoKyspLHRoaXMuZTE9dGhpcy5lMix0aGlzLmUyPXRoaXMuZTMsdT1yLm11bHQoLTEpLGkmJnUuX3N1YihyLnBlcnAoKS5fbXVsdChpKSksX3MobCx0LHUsYSwhMCwtaSxlKSx0aGlzLmUzPW8udmVydGV4TGVuZ3RoKyssdGhpcy5lMT49MCYmdGhpcy5lMj49MCYmKHAuZW1wbGFjZUJhY2sodGhpcy5lMSx0aGlzLmUyLHRoaXMuZTMpLG8ucHJpbWl0aXZlTGVuZ3RoKyspLHRoaXMuZTE9dGhpcy5lMix0aGlzLmUyPXRoaXMuZTMsZT5icy8yJiYhcyYmKHRoaXMuZGlzdGFuY2U9MCx0aGlzLmFkZEN1cnJlbnRWZXJ0ZXgodCx0aGlzLmRpc3RhbmNlLHIsbixpLGEsbykpO30sd3MucHJvdG90eXBlLmFkZFBpZVNsaWNlVmVydGV4PWZ1bmN0aW9uKHQsZSxyLG4saSxhKXtyPXIubXVsdChuPy0xOjEpO3ZhciBvPXRoaXMubGF5b3V0VmVydGV4QXJyYXkscz10aGlzLmluZGV4QXJyYXk7YSYmKGU9QXMoZSxhKSksX3Mobyx0LHIsITEsbiwwLGUpLHRoaXMuZTM9aS52ZXJ0ZXhMZW5ndGgrKyx0aGlzLmUxPj0wJiZ0aGlzLmUyPj0wJiYocy5lbXBsYWNlQmFjayh0aGlzLmUxLHRoaXMuZTIsdGhpcy5lMyksaS5wcmltaXRpdmVMZW5ndGgrKyksbj90aGlzLmUyPXRoaXMuZTM6dGhpcy5lMT10aGlzLmUzO30sem4oXCJMaW5lQnVja2V0XCIsd3Mse29taXQ6W1wibGF5ZXJzXCIsXCJmZWF0dXJlc1wiXX0pO3ZhciBTcz1uZXcgaWkoe1wibGluZS1jYXBcIjpuZXcgUW4oTHQubGF5b3V0X2xpbmVbXCJsaW5lLWNhcFwiXSksXCJsaW5lLWpvaW5cIjpuZXcgdGkoTHQubGF5b3V0X2xpbmVbXCJsaW5lLWpvaW5cIl0pLFwibGluZS1taXRlci1saW1pdFwiOm5ldyBRbihMdC5sYXlvdXRfbGluZVtcImxpbmUtbWl0ZXItbGltaXRcIl0pLFwibGluZS1yb3VuZC1saW1pdFwiOm5ldyBRbihMdC5sYXlvdXRfbGluZVtcImxpbmUtcm91bmQtbGltaXRcIl0pfSksa3M9e3BhaW50Om5ldyBpaSh7XCJsaW5lLW9wYWNpdHlcIjpuZXcgdGkoTHQucGFpbnRfbGluZVtcImxpbmUtb3BhY2l0eVwiXSksXCJsaW5lLWNvbG9yXCI6bmV3IHRpKEx0LnBhaW50X2xpbmVbXCJsaW5lLWNvbG9yXCJdKSxcImxpbmUtdHJhbnNsYXRlXCI6bmV3IFFuKEx0LnBhaW50X2xpbmVbXCJsaW5lLXRyYW5zbGF0ZVwiXSksXCJsaW5lLXRyYW5zbGF0ZS1hbmNob3JcIjpuZXcgUW4oTHQucGFpbnRfbGluZVtcImxpbmUtdHJhbnNsYXRlLWFuY2hvclwiXSksXCJsaW5lLXdpZHRoXCI6bmV3IHRpKEx0LnBhaW50X2xpbmVbXCJsaW5lLXdpZHRoXCJdKSxcImxpbmUtZ2FwLXdpZHRoXCI6bmV3IHRpKEx0LnBhaW50X2xpbmVbXCJsaW5lLWdhcC13aWR0aFwiXSksXCJsaW5lLW9mZnNldFwiOm5ldyB0aShMdC5wYWludF9saW5lW1wibGluZS1vZmZzZXRcIl0pLFwibGluZS1ibHVyXCI6bmV3IHRpKEx0LnBhaW50X2xpbmVbXCJsaW5lLWJsdXJcIl0pLFwibGluZS1kYXNoYXJyYXlcIjpuZXcgcmkoTHQucGFpbnRfbGluZVtcImxpbmUtZGFzaGFycmF5XCJdKSxcImxpbmUtcGF0dGVyblwiOm5ldyBlaShMdC5wYWludF9saW5lW1wibGluZS1wYXR0ZXJuXCJdKSxcImxpbmUtZ3JhZGllbnRcIjpuZXcgbmkoTHQucGFpbnRfbGluZVtcImxpbmUtZ3JhZGllbnRcIl0pfSksbGF5b3V0OlNzfSx6cz1uZXcoZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUucG9zc2libHlFdmFsdWF0ZT1mdW5jdGlvbihlLHIpe3JldHVybiByPW5ldyBabihNYXRoLmZsb29yKHIuem9vbSkse25vdzpyLm5vdyxmYWRlRHVyYXRpb246ci5mYWRlRHVyYXRpb24sem9vbUhpc3Rvcnk6ci56b29tSGlzdG9yeSx0cmFuc2l0aW9uOnIudHJhbnNpdGlvbn0pLHQucHJvdG90eXBlLnBvc3NpYmx5RXZhbHVhdGUuY2FsbCh0aGlzLGUscil9LGUucHJvdG90eXBlLmV2YWx1YXRlPWZ1bmN0aW9uKGUscixuLGkpe3JldHVybiByPWMoe30scix7em9vbTpNYXRoLmZsb29yKHIuem9vbSl9KSx0LnByb3RvdHlwZS5ldmFsdWF0ZS5jYWxsKHRoaXMsZSxyLG4saSl9LGV9KHRpKSkoa3MucGFpbnQucHJvcGVydGllc1tcImxpbmUtd2lkdGhcIl0uc3BlY2lmaWNhdGlvbik7enMudXNlSW50ZWdlclpvb209ITA7dmFyIElzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSxrcyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5faGFuZGxlU3BlY2lhbFBhaW50UHJvcGVydHlVcGRhdGU9ZnVuY3Rpb24odCl7XCJsaW5lLWdyYWRpZW50XCI9PT10JiZ0aGlzLl91cGRhdGVHcmFkaWVudCgpO30sZS5wcm90b3R5cGUuX3VwZGF0ZUdyYWRpZW50PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5fdHJhbnNpdGlvbmFibGVQYWludC5fdmFsdWVzW1wibGluZS1ncmFkaWVudFwiXS52YWx1ZS5leHByZXNzaW9uO3RoaXMuZ3JhZGllbnQ9dW8odCxcImxpbmVQcm9ncmVzc1wiKSx0aGlzLmdyYWRpZW50VGV4dHVyZT1udWxsO30sZS5wcm90b3R5cGUucmVjYWxjdWxhdGU9ZnVuY3Rpb24oZSl7dC5wcm90b3R5cGUucmVjYWxjdWxhdGUuY2FsbCh0aGlzLGUpLHRoaXMucGFpbnQuX3ZhbHVlc1tcImxpbmUtZmxvb3J3aWR0aFwiXT16cy5wb3NzaWJseUV2YWx1YXRlKHRoaXMuX3RyYW5zaXRpb25pbmdQYWludC5fdmFsdWVzW1wibGluZS13aWR0aFwiXS52YWx1ZSxlKTt9LGUucHJvdG90eXBlLmNyZWF0ZUJ1Y2tldD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IHdzKHQpfSxlLnByb3RvdHlwZS5xdWVyeVJhZGl1cz1mdW5jdGlvbih0KXt2YXIgZT10LHI9QnMoTWEoXCJsaW5lLXdpZHRoXCIsdGhpcyxlKSxNYShcImxpbmUtZ2FwLXdpZHRoXCIsdGhpcyxlKSksbj1NYShcImxpbmUtb2Zmc2V0XCIsdGhpcyxlKTtyZXR1cm4gci8yK01hdGguYWJzKG4pK1RhKHRoaXMucGFpbnQuZ2V0KFwibGluZS10cmFuc2xhdGVcIikpfSxlLnByb3RvdHlwZS5xdWVyeUludGVyc2VjdHNGZWF0dXJlPWZ1bmN0aW9uKHQsZSxyLG4sYSxvLHMpe3ZhciB1PVBhKHQsdGhpcy5wYWludC5nZXQoXCJsaW5lLXRyYW5zbGF0ZVwiKSx0aGlzLnBhaW50LmdldChcImxpbmUtdHJhbnNsYXRlLWFuY2hvclwiKSxvLmFuZ2xlLHMpLGw9cy8yKkJzKHRoaXMucGFpbnQuZ2V0KFwibGluZS13aWR0aFwiKS5ldmFsdWF0ZShlLHIpLHRoaXMucGFpbnQuZ2V0KFwibGluZS1nYXAtd2lkdGhcIikuZXZhbHVhdGUoZSxyKSkscD10aGlzLnBhaW50LmdldChcImxpbmUtb2Zmc2V0XCIpLmV2YWx1YXRlKGUscik7cmV0dXJuIHAmJihuPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPVtdLG49bmV3IGkoMCwwKSxhPTA7YTx0Lmxlbmd0aDthKyspe2Zvcih2YXIgbz10W2FdLHM9W10sdT0wO3U8by5sZW5ndGg7dSsrKXt2YXIgbD1vW3UtMV0scD1vW3VdLGM9b1t1KzFdLGg9MD09PXU/bjpwLnN1YihsKS5fdW5pdCgpLl9wZXJwKCksZj11PT09by5sZW5ndGgtMT9uOmMuc3ViKHApLl91bml0KCkuX3BlcnAoKSx5PWguX2FkZChmKS5fdW5pdCgpLGQ9eS54KmYueCt5LnkqZi55O3kuX211bHQoMS9kKSxzLnB1c2goeS5fbXVsdChlKS5fYWRkKHApKTt9ci5wdXNoKHMpO31yZXR1cm4gcn0obixwKnMpKSxmdW5jdGlvbih0LGUscil7Zm9yKHZhciBuPTA7bjxlLmxlbmd0aDtuKyspe3ZhciBpPWVbbl07aWYodC5sZW5ndGg+PTMpZm9yKHZhciBhPTA7YTxpLmxlbmd0aDthKyspaWYoQ2EodCxpW2FdKSlyZXR1cm4gITA7aWYoQWEodCxpLHIpKXJldHVybiAhMH1yZXR1cm4gITF9KHUsbixsKX0sZS5wcm90b3R5cGUuaXNUaWxlQ2xpcHBlZD1mdW5jdGlvbigpe3JldHVybiAhMH0sZX0oYWkpO2Z1bmN0aW9uIEJzKHQsZSl7cmV0dXJuIGU+MD9lKzIqdDp0fXZhciBDcz1saShbe25hbWU6XCJhX3Bvc19vZmZzZXRcIixjb21wb25lbnRzOjQsdHlwZTpcIkludDE2XCJ9LHtuYW1lOlwiYV9kYXRhXCIsY29tcG9uZW50czo0LHR5cGU6XCJVaW50MTZcIn1dKSxFcz1saShbe25hbWU6XCJhX3Byb2plY3RlZF9wb3NcIixjb21wb25lbnRzOjMsdHlwZTpcIkZsb2F0MzJcIn1dLDQpLE1zPShsaShbe25hbWU6XCJhX2ZhZGVfb3BhY2l0eVwiLGNvbXBvbmVudHM6MSx0eXBlOlwiVWludDMyXCJ9XSw0KSxsaShbe25hbWU6XCJhX3BsYWNlZFwiLGNvbXBvbmVudHM6Mix0eXBlOlwiVWludDhcIn0se25hbWU6XCJhX3NoaWZ0XCIsY29tcG9uZW50czoyLHR5cGU6XCJGbG9hdDMyXCJ9XSkpLFRzPShsaShbe3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJhbmNob3JQb2ludFhcIn0se3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJhbmNob3JQb2ludFlcIn0se3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJ4MVwifSx7dHlwZTpcIkludDE2XCIsbmFtZTpcInkxXCJ9LHt0eXBlOlwiSW50MTZcIixuYW1lOlwieDJcIn0se3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJ5MlwifSx7dHlwZTpcIlVpbnQzMlwiLG5hbWU6XCJmZWF0dXJlSW5kZXhcIn0se3R5cGU6XCJVaW50MTZcIixuYW1lOlwic291cmNlTGF5ZXJJbmRleFwifSx7dHlwZTpcIlVpbnQxNlwiLG5hbWU6XCJidWNrZXRJbmRleFwifSx7dHlwZTpcIkludDE2XCIsbmFtZTpcInJhZGl1c1wifSx7dHlwZTpcIkludDE2XCIsbmFtZTpcInNpZ25lZERpc3RhbmNlRnJvbUFuY2hvclwifV0pLGxpKFt7bmFtZTpcImFfcG9zXCIsY29tcG9uZW50czoyLHR5cGU6XCJJbnQxNlwifSx7bmFtZTpcImFfYW5jaG9yX3Bvc1wiLGNvbXBvbmVudHM6Mix0eXBlOlwiSW50MTZcIn0se25hbWU6XCJhX2V4dHJ1ZGVcIixjb21wb25lbnRzOjIsdHlwZTpcIkludDE2XCJ9XSw0KSksUHM9bGkoW3tuYW1lOlwiYV9wb3NcIixjb21wb25lbnRzOjIsdHlwZTpcIkludDE2XCJ9LHtuYW1lOlwiYV9hbmNob3JfcG9zXCIsY29tcG9uZW50czoyLHR5cGU6XCJJbnQxNlwifSx7bmFtZTpcImFfZXh0cnVkZVwiLGNvbXBvbmVudHM6Mix0eXBlOlwiSW50MTZcIn1dLDQpO2xpKFt7dHlwZTpcIkludDE2XCIsbmFtZTpcImFuY2hvclhcIn0se3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJhbmNob3JZXCJ9LHt0eXBlOlwiVWludDE2XCIsbmFtZTpcImdseXBoU3RhcnRJbmRleFwifSx7dHlwZTpcIlVpbnQxNlwiLG5hbWU6XCJudW1HbHlwaHNcIn0se3R5cGU6XCJVaW50MzJcIixuYW1lOlwidmVydGV4U3RhcnRJbmRleFwifSx7dHlwZTpcIlVpbnQzMlwiLG5hbWU6XCJsaW5lU3RhcnRJbmRleFwifSx7dHlwZTpcIlVpbnQzMlwiLG5hbWU6XCJsaW5lTGVuZ3RoXCJ9LHt0eXBlOlwiVWludDE2XCIsbmFtZTpcInNlZ21lbnRcIn0se3R5cGU6XCJVaW50MTZcIixuYW1lOlwibG93ZXJTaXplXCJ9LHt0eXBlOlwiVWludDE2XCIsbmFtZTpcInVwcGVyU2l6ZVwifSx7dHlwZTpcIkZsb2F0MzJcIixuYW1lOlwibGluZU9mZnNldFhcIn0se3R5cGU6XCJGbG9hdDMyXCIsbmFtZTpcImxpbmVPZmZzZXRZXCJ9LHt0eXBlOlwiVWludDhcIixuYW1lOlwid3JpdGluZ01vZGVcIn0se3R5cGU6XCJVaW50OFwiLG5hbWU6XCJoaWRkZW5cIn0se3R5cGU6XCJVaW50MzJcIixuYW1lOlwiY3Jvc3NUaWxlSURcIn1dKSxsaShbe3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJhbmNob3JYXCJ9LHt0eXBlOlwiSW50MTZcIixuYW1lOlwiYW5jaG9yWVwifSx7dHlwZTpcIkludDE2XCIsbmFtZTpcInJpZ2h0SnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4XCJ9LHt0eXBlOlwiSW50MTZcIixuYW1lOlwiY2VudGVySnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4XCJ9LHt0eXBlOlwiSW50MTZcIixuYW1lOlwibGVmdEp1c3RpZmllZFRleHRTeW1ib2xJbmRleFwifSx7dHlwZTpcIkludDE2XCIsbmFtZTpcInZlcnRpY2FsUGxhY2VkVGV4dFN5bWJvbEluZGV4XCJ9LHt0eXBlOlwiVWludDE2XCIsbmFtZTpcImtleVwifSx7dHlwZTpcIlVpbnQxNlwiLG5hbWU6XCJ0ZXh0Qm94U3RhcnRJbmRleFwifSx7dHlwZTpcIlVpbnQxNlwiLG5hbWU6XCJ0ZXh0Qm94RW5kSW5kZXhcIn0se3R5cGU6XCJVaW50MTZcIixuYW1lOlwiaWNvbkJveFN0YXJ0SW5kZXhcIn0se3R5cGU6XCJVaW50MTZcIixuYW1lOlwiaWNvbkJveEVuZEluZGV4XCJ9LHt0eXBlOlwiVWludDE2XCIsbmFtZTpcImZlYXR1cmVJbmRleFwifSx7dHlwZTpcIlVpbnQxNlwiLG5hbWU6XCJudW1Ib3Jpem9udGFsR2x5cGhWZXJ0aWNlc1wifSx7dHlwZTpcIlVpbnQxNlwiLG5hbWU6XCJudW1WZXJ0aWNhbEdseXBoVmVydGljZXNcIn0se3R5cGU6XCJVaW50MTZcIixuYW1lOlwibnVtSWNvblZlcnRpY2VzXCJ9LHt0eXBlOlwiVWludDMyXCIsbmFtZTpcImNyb3NzVGlsZUlEXCJ9LHt0eXBlOlwiRmxvYXQzMlwiLG5hbWU6XCJ0ZXh0Qm94U2NhbGVcIn0se3R5cGU6XCJGbG9hdDMyXCIsbmFtZTpcInJhZGlhbFRleHRPZmZzZXRcIn1dKSxsaShbe3R5cGU6XCJGbG9hdDMyXCIsbmFtZTpcIm9mZnNldFhcIn1dKSxsaShbe3R5cGU6XCJJbnQxNlwiLG5hbWU6XCJ4XCJ9LHt0eXBlOlwiSW50MTZcIixuYW1lOlwieVwifSx7dHlwZTpcIkludDE2XCIsbmFtZTpcInRpbGVVbml0RGlzdGFuY2VGcm9tQW5jaG9yXCJ9XSk7ZnVuY3Rpb24gVnModCxlLHIpe3JldHVybiB0LnNlY3Rpb25zLmZvckVhY2goZnVuY3Rpb24odCl7dC50ZXh0PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj1lLmxheW91dC5nZXQoXCJ0ZXh0LXRyYW5zZm9ybVwiKS5ldmFsdWF0ZShyLHt9KTtyZXR1cm4gXCJ1cHBlcmNhc2VcIj09PW4/dD10LnRvTG9jYWxlVXBwZXJDYXNlKCk6XCJsb3dlcmNhc2VcIj09PW4mJih0PXQudG9Mb2NhbGVMb3dlckNhc2UoKSksTm4uYXBwbHlBcmFiaWNTaGFwaW5nJiYodD1Obi5hcHBseUFyYWJpY1NoYXBpbmcodCkpLHR9KHQudGV4dCxlLHIpO30pLHR9dmFyIEZzPXtcIiFcIjpcIu+4lVwiLFwiI1wiOlwi77yDXCIsJDpcIu+8hFwiLFwiJVwiOlwi77yFXCIsXCImXCI6XCLvvIZcIixcIihcIjpcIu+4tVwiLFwiKVwiOlwi77i2XCIsXCIqXCI6XCLvvIpcIixcIitcIjpcIu+8i1wiLFwiLFwiOlwi77iQXCIsXCItXCI6XCLvuLJcIixcIi5cIjpcIuODu1wiLFwiL1wiOlwi77yPXCIsXCI6XCI6XCLvuJNcIixcIjtcIjpcIu+4lFwiLFwiPFwiOlwi77i/XCIsXCI9XCI6XCLvvJ1cIixcIj5cIjpcIu+5gFwiLFwiP1wiOlwi77iWXCIsXCJAXCI6XCLvvKBcIixcIltcIjpcIu+5h1wiLFwiXFxcXFwiOlwi77y8XCIsXCJdXCI6XCLvuYhcIixcIl5cIjpcIu+8vlwiLF86XCLvuLNcIixcImBcIjpcIu+9gFwiLFwie1wiOlwi77i3XCIsXCJ8XCI6XCLigJVcIixcIn1cIjpcIu+4uFwiLFwiflwiOlwi772eXCIsXCLColwiOlwi77+gXCIsXCLCo1wiOlwi77+hXCIsXCLCpVwiOlwi77+lXCIsXCLCplwiOlwi77+kXCIsXCLCrFwiOlwi77+iXCIsXCLCr1wiOlwi77+jXCIsXCLigJNcIjpcIu+4slwiLFwi4oCUXCI6XCLvuLFcIixcIuKAmFwiOlwi77mDXCIsXCLigJlcIjpcIu+5hFwiLFwi4oCcXCI6XCLvuYFcIixcIuKAnVwiOlwi77mCXCIsXCLigKZcIjpcIu+4mVwiLFwi4oCnXCI6XCLjg7tcIixcIuKCqVwiOlwi77+mXCIsXCLjgIFcIjpcIu+4kVwiLFwi44CCXCI6XCLvuJJcIixcIuOAiFwiOlwi77i/XCIsXCLjgIlcIjpcIu+5gFwiLFwi44CKXCI6XCLvuL1cIixcIuOAi1wiOlwi77i+XCIsXCLjgIxcIjpcIu+5gVwiLFwi44CNXCI6XCLvuYJcIixcIuOAjlwiOlwi77mDXCIsXCLjgI9cIjpcIu+5hFwiLFwi44CQXCI6XCLvuLtcIixcIuOAkVwiOlwi77i8XCIsXCLjgJRcIjpcIu+4uVwiLFwi44CVXCI6XCLvuLpcIixcIuOAllwiOlwi77iXXCIsXCLjgJdcIjpcIu+4mFwiLFwi77yBXCI6XCLvuJVcIixcIu+8iFwiOlwi77i1XCIsXCLvvIlcIjpcIu+4tlwiLFwi77yMXCI6XCLvuJBcIixcIu+8jVwiOlwi77iyXCIsXCLvvI5cIjpcIuODu1wiLFwi77yaXCI6XCLvuJNcIixcIu+8m1wiOlwi77iUXCIsXCLvvJxcIjpcIu+4v1wiLFwi77yeXCI6XCLvuYBcIixcIu+8n1wiOlwi77iWXCIsXCLvvLtcIjpcIu+5h1wiLFwi77y9XCI6XCLvuYhcIixcIu+8v1wiOlwi77izXCIsXCLvvZtcIjpcIu+4t1wiLFwi772cXCI6XCLigJVcIixcIu+9nVwiOlwi77i4XCIsXCLvvZ9cIjpcIu+4tVwiLFwi772gXCI6XCLvuLZcIixcIu+9oVwiOlwi77iSXCIsXCLvvaJcIjpcIu+5gVwiLFwi772jXCI6XCLvuYJcIn07dmFyIExzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSxyLG4saSl7dC5jYWxsKHRoaXMsZSxyKSx0aGlzLmFuZ2xlPW4sdm9pZCAwIT09aSYmKHRoaXMuc2VnbWVudD1pKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmNsb25lPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBlKHRoaXMueCx0aGlzLnksdGhpcy5hbmdsZSx0aGlzLnNlZ21lbnQpfSxlfShpKTt6bihcIkFuY2hvclwiLExzKTt2YXIgRHM9MjU2O2Z1bmN0aW9uIE9zKHQsZSl7dmFyIHI9ZS5leHByZXNzaW9uO2lmKFwiY29uc3RhbnRcIj09PXIua2luZClyZXR1cm4ge2tpbmQ6XCJjb25zdGFudFwiLGxheW91dFNpemU6ci5ldmFsdWF0ZShuZXcgWm4odCsxKSl9O2lmKFwic291cmNlXCI9PT1yLmtpbmQpcmV0dXJuIHtraW5kOlwic291cmNlXCJ9O2Zvcih2YXIgbj1yLnpvb21TdG9wcyxpPXIuaW50ZXJwb2xhdGlvblR5cGUsYT0wO2E8bi5sZW5ndGgmJm5bYV08PXQ7KWErKztmb3IodmFyIG89YT1NYXRoLm1heCgwLGEtMSk7bzxuLmxlbmd0aCYmbltvXTx0KzE7KW8rKztvPU1hdGgubWluKG4ubGVuZ3RoLTEsbyk7dmFyIHM9blthXSx1PW5bb107cmV0dXJuIFwiY29tcG9zaXRlXCI9PT1yLmtpbmQ/e2tpbmQ6XCJjb21wb3NpdGVcIixtaW5ab29tOnMsbWF4Wm9vbTp1LGludGVycG9sYXRpb25UeXBlOml9OntraW5kOlwiY2FtZXJhXCIsbWluWm9vbTpzLG1heFpvb206dSxtaW5TaXplOnIuZXZhbHVhdGUobmV3IFpuKHMpKSxtYXhTaXplOnIuZXZhbHVhdGUobmV3IFpuKHUpKSxpbnRlcnBvbGF0aW9uVHlwZTppfX1mdW5jdGlvbiBScyh0LGUscil7dmFyIG49ZS51U2l6ZSxpPWUudVNpemVULGE9ci5sb3dlclNpemUsbz1yLnVwcGVyU2l6ZTtyZXR1cm4gXCJzb3VyY2VcIj09PXQua2luZD9hL0RzOlwiY29tcG9zaXRlXCI9PT10LmtpbmQ/RWUoYS9EcyxvL0RzLGkpOm59ZnVuY3Rpb24gVXModCxlKXt2YXIgcj0wLG49MDtpZihcImNvbnN0YW50XCI9PT10LmtpbmQpbj10LmxheW91dFNpemU7ZWxzZSBpZihcInNvdXJjZVwiIT09dC5raW5kKXt2YXIgaT10LmludGVycG9sYXRpb25UeXBlLGE9dC5taW5ab29tLG89dC5tYXhab29tLHM9aT9sKCRlLmludGVycG9sYXRpb25GYWN0b3IoaSxlLGEsbyksMCwxKTowO1wiY2FtZXJhXCI9PT10LmtpbmQ/bj1FZSh0Lm1pblNpemUsdC5tYXhTaXplLHMpOnI9czt9cmV0dXJuIHt1U2l6ZVQ6cix1U2l6ZTpufX12YXIganM9T2JqZWN0LmZyZWV6ZSh7Z2V0U2l6ZURhdGE6T3MsZXZhbHVhdGVTaXplRm9yRmVhdHVyZTpScyxldmFsdWF0ZVNpemVGb3Jab29tOlVzLFNJWkVfUEFDS19GQUNUT1I6RHN9KSxxcz1pcy5WZWN0b3JUaWxlRmVhdHVyZS50eXBlcyxOcz1be25hbWU6XCJhX2ZhZGVfb3BhY2l0eVwiLGNvbXBvbmVudHM6MSx0eXBlOlwiVWludDhcIixvZmZzZXQ6MH1dO2Z1bmN0aW9uIFpzKHQsZSxyLG4saSxhLG8scyl7dC5lbXBsYWNlQmFjayhlLHIsTWF0aC5yb3VuZCgzMipuKSxNYXRoLnJvdW5kKDMyKmkpLGEsbyxzP3NbMF06MCxzP3NbMV06MCk7fWZ1bmN0aW9uIEtzKHQsZSxyKXt0LmVtcGxhY2VCYWNrKGUueCxlLnksciksdC5lbXBsYWNlQmFjayhlLngsZS55LHIpLHQuZW1wbGFjZUJhY2soZS54LGUueSxyKSx0LmVtcGxhY2VCYWNrKGUueCxlLnkscik7fXZhciBHcz1mdW5jdGlvbih0KXt0aGlzLmxheW91dFZlcnRleEFycmF5PW5ldyBtaSx0aGlzLmluZGV4QXJyYXk9bmV3IElpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zPXQsdGhpcy5zZWdtZW50cz1uZXcgS2ksdGhpcy5keW5hbWljTGF5b3V0VmVydGV4QXJyYXk9bmV3IHZpLHRoaXMub3BhY2l0eVZlcnRleEFycmF5PW5ldyBnaSx0aGlzLnBsYWNlZFN5bWJvbEFycmF5PW5ldyBGaTt9O0dzLnByb3RvdHlwZS51cGxvYWQ9ZnVuY3Rpb24odCxlLHIsbil7ciYmKHRoaXMubGF5b3V0VmVydGV4QnVmZmVyPXQuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMubGF5b3V0VmVydGV4QXJyYXksQ3MubWVtYmVycyksdGhpcy5pbmRleEJ1ZmZlcj10LmNyZWF0ZUluZGV4QnVmZmVyKHRoaXMuaW5kZXhBcnJheSxlKSx0aGlzLmR5bmFtaWNMYXlvdXRWZXJ0ZXhCdWZmZXI9dC5jcmVhdGVWZXJ0ZXhCdWZmZXIodGhpcy5keW5hbWljTGF5b3V0VmVydGV4QXJyYXksRXMubWVtYmVycywhMCksdGhpcy5vcGFjaXR5VmVydGV4QnVmZmVyPXQuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMub3BhY2l0eVZlcnRleEFycmF5LE5zLCEwKSx0aGlzLm9wYWNpdHlWZXJ0ZXhCdWZmZXIuaXRlbVNpemU9MSksKHJ8fG4pJiZ0aGlzLnByb2dyYW1Db25maWd1cmF0aW9ucy51cGxvYWQodCk7fSxHcy5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMubGF5b3V0VmVydGV4QnVmZmVyJiYodGhpcy5sYXlvdXRWZXJ0ZXhCdWZmZXIuZGVzdHJveSgpLHRoaXMuaW5kZXhCdWZmZXIuZGVzdHJveSgpLHRoaXMucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLmRlc3Ryb3koKSx0aGlzLnNlZ21lbnRzLmRlc3Ryb3koKSx0aGlzLmR5bmFtaWNMYXlvdXRWZXJ0ZXhCdWZmZXIuZGVzdHJveSgpLHRoaXMub3BhY2l0eVZlcnRleEJ1ZmZlci5kZXN0cm95KCkpO30sem4oXCJTeW1ib2xCdWZmZXJzXCIsR3MpO3ZhciBYcz1mdW5jdGlvbih0LGUscil7dGhpcy5sYXlvdXRWZXJ0ZXhBcnJheT1uZXcgdCx0aGlzLmxheW91dEF0dHJpYnV0ZXM9ZSx0aGlzLmluZGV4QXJyYXk9bmV3IHIsdGhpcy5zZWdtZW50cz1uZXcgS2ksdGhpcy5jb2xsaXNpb25WZXJ0ZXhBcnJheT1uZXcgX2k7fTtYcy5wcm90b3R5cGUudXBsb2FkPWZ1bmN0aW9uKHQpe3RoaXMubGF5b3V0VmVydGV4QnVmZmVyPXQuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMubGF5b3V0VmVydGV4QXJyYXksdGhpcy5sYXlvdXRBdHRyaWJ1dGVzKSx0aGlzLmluZGV4QnVmZmVyPXQuY3JlYXRlSW5kZXhCdWZmZXIodGhpcy5pbmRleEFycmF5KSx0aGlzLmNvbGxpc2lvblZlcnRleEJ1ZmZlcj10LmNyZWF0ZVZlcnRleEJ1ZmZlcih0aGlzLmNvbGxpc2lvblZlcnRleEFycmF5LE1zLm1lbWJlcnMsITApO30sWHMucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLmxheW91dFZlcnRleEJ1ZmZlciYmKHRoaXMubGF5b3V0VmVydGV4QnVmZmVyLmRlc3Ryb3koKSx0aGlzLmluZGV4QnVmZmVyLmRlc3Ryb3koKSx0aGlzLnNlZ21lbnRzLmRlc3Ryb3koKSx0aGlzLmNvbGxpc2lvblZlcnRleEJ1ZmZlci5kZXN0cm95KCkpO30sem4oXCJDb2xsaXNpb25CdWZmZXJzXCIsWHMpO3ZhciBKcz1mdW5jdGlvbih0KXt0aGlzLmNvbGxpc2lvbkJveEFycmF5PXQuY29sbGlzaW9uQm94QXJyYXksdGhpcy56b29tPXQuem9vbSx0aGlzLm92ZXJzY2FsaW5nPXQub3ZlcnNjYWxpbmcsdGhpcy5sYXllcnM9dC5sYXllcnMsdGhpcy5sYXllcklkcz10aGlzLmxheWVycy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuaWR9KSx0aGlzLmluZGV4PXQuaW5kZXgsdGhpcy5waXhlbFJhdGlvPXQucGl4ZWxSYXRpbyx0aGlzLnNvdXJjZUxheWVySW5kZXg9dC5zb3VyY2VMYXllckluZGV4LHRoaXMuaGFzUGF0dGVybj0hMTt2YXIgZT10aGlzLmxheWVyc1swXS5fdW5ldmFsdWF0ZWRMYXlvdXQuX3ZhbHVlczt0aGlzLnRleHRTaXplRGF0YT1Pcyh0aGlzLnpvb20sZVtcInRleHQtc2l6ZVwiXSksdGhpcy5pY29uU2l6ZURhdGE9T3ModGhpcy56b29tLGVbXCJpY29uLXNpemVcIl0pO3ZhciByPXRoaXMubGF5ZXJzWzBdLmxheW91dCxuPXIuZ2V0KFwic3ltYm9sLXNvcnQta2V5XCIpLGk9ci5nZXQoXCJzeW1ib2wtei1vcmRlclwiKTt0aGlzLnNvcnRGZWF0dXJlc0J5S2V5PVwidmlld3BvcnQteVwiIT09aSYmdm9pZCAwIT09bi5jb25zdGFudE9yKDEpO3ZhciBhPVwidmlld3BvcnQteVwiPT09aXx8XCJhdXRvXCI9PT1pJiYhdGhpcy5zb3J0RmVhdHVyZXNCeUtleTt0aGlzLnNvcnRGZWF0dXJlc0J5WT1hJiYoci5nZXQoXCJ0ZXh0LWFsbG93LW92ZXJsYXBcIil8fHIuZ2V0KFwiaWNvbi1hbGxvdy1vdmVybGFwXCIpfHxyLmdldChcInRleHQtaWdub3JlLXBsYWNlbWVudFwiKXx8ci5nZXQoXCJpY29uLWlnbm9yZS1wbGFjZW1lbnRcIikpLHRoaXMuc3RhdGVEZXBlbmRlbnRMYXllcklkcz10aGlzLmxheWVycy5maWx0ZXIoZnVuY3Rpb24odCl7cmV0dXJuIHQuaXNTdGF0ZURlcGVuZGVudCgpfSkubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkfSksdGhpcy5zb3VyY2VJRD10LnNvdXJjZUlEO307SnMucHJvdG90eXBlLmNyZWF0ZUFycmF5cz1mdW5jdGlvbigpe3RoaXMudGV4dD1uZXcgR3MobmV3IGNhKENzLm1lbWJlcnMsdGhpcy5sYXllcnMsdGhpcy56b29tLGZ1bmN0aW9uKHQpe3JldHVybiAvXnRleHQvLnRlc3QodCl9KSksdGhpcy5pY29uPW5ldyBHcyhuZXcgY2EoQ3MubWVtYmVycyx0aGlzLmxheWVycyx0aGlzLnpvb20sZnVuY3Rpb24odCl7cmV0dXJuIC9eaWNvbi8udGVzdCh0KX0pKSx0aGlzLmNvbGxpc2lvbkJveD1uZXcgWHMoYmksVHMubWVtYmVycyxCaSksdGhpcy5jb2xsaXNpb25DaXJjbGU9bmV3IFhzKGJpLFBzLm1lbWJlcnMsSWkpLHRoaXMuZ2x5cGhPZmZzZXRBcnJheT1uZXcgUmksdGhpcy5saW5lVmVydGV4QXJyYXk9bmV3IGppLHRoaXMuc3ltYm9sSW5zdGFuY2VzPW5ldyBEaTt9LEpzLnByb3RvdHlwZS5jYWxjdWxhdGVHbHlwaERlcGVuZGVuY2llcz1mdW5jdGlvbih0LGUscixuKXtmb3IodmFyIGk9MDtpPHQubGVuZ3RoO2krKylpZihlW3QuY2hhckNvZGVBdChpKV09ITAsciYmbil7dmFyIGE9RnNbdC5jaGFyQXQoaSldO2EmJihlW2EuY2hhckNvZGVBdCgwKV09ITApO319LEpzLnByb3RvdHlwZS5wb3B1bGF0ZT1mdW5jdGlvbih0LGUpe3ZhciByPXRoaXMubGF5ZXJzWzBdLG49ci5sYXlvdXQsaT1uLmdldChcInRleHQtZm9udFwiKSxhPW4uZ2V0KFwidGV4dC1maWVsZFwiKSxvPW4uZ2V0KFwiaWNvbi1pbWFnZVwiKSxzPShcImNvbnN0YW50XCIhPT1hLnZhbHVlLmtpbmR8fGEudmFsdWUudmFsdWUudG9TdHJpbmcoKS5sZW5ndGg+MCkmJihcImNvbnN0YW50XCIhPT1pLnZhbHVlLmtpbmR8fGkudmFsdWUudmFsdWUubGVuZ3RoPjApLHU9XCJjb25zdGFudFwiIT09by52YWx1ZS5raW5kfHxvLnZhbHVlLnZhbHVlJiZvLnZhbHVlLnZhbHVlLmxlbmd0aD4wLGw9bi5nZXQoXCJzeW1ib2wtc29ydC1rZXlcIik7aWYodGhpcy5mZWF0dXJlcz1bXSxzfHx1KXtmb3IodmFyIHA9ZS5pY29uRGVwZW5kZW5jaWVzLGM9ZS5nbHlwaERlcGVuZGVuY2llcyxoPW5ldyBabih0aGlzLnpvb20pLGY9MCx5PXQ7Zjx5Lmxlbmd0aDtmKz0xKXt2YXIgZD15W2ZdLG09ZC5mZWF0dXJlLHY9ZC5pbmRleCxnPWQuc291cmNlTGF5ZXJJbmRleDtpZihyLl9mZWF0dXJlRmlsdGVyKGgsbSkpe3ZhciB4PXZvaWQgMDtpZihzKXt2YXIgYj1yLmdldFZhbHVlQW5kUmVzb2x2ZVRva2VucyhcInRleHQtZmllbGRcIixtKTt4PVZzKGIgaW5zdGFuY2VvZiB1ZT9iOnVlLmZyb21TdHJpbmcoYikscixtKTt9dmFyIF89dm9pZCAwO2lmKHUmJihfPXIuZ2V0VmFsdWVBbmRSZXNvbHZlVG9rZW5zKFwiaWNvbi1pbWFnZVwiLG0pKSx4fHxfKXt2YXIgdz10aGlzLnNvcnRGZWF0dXJlc0J5S2V5P2wuZXZhbHVhdGUobSx7fSk6dm9pZCAwLEE9e3RleHQ6eCxpY29uOl8saW5kZXg6dixzb3VyY2VMYXllckluZGV4OmcsZ2VvbWV0cnk6dmEobSkscHJvcGVydGllczptLnByb3BlcnRpZXMsdHlwZTpxc1ttLnR5cGVdLHNvcnRLZXk6d307aWYodm9pZCAwIT09bS5pZCYmKEEuaWQ9bS5pZCksdGhpcy5mZWF0dXJlcy5wdXNoKEEpLF8mJihwW19dPSEwKSx4KWZvcih2YXIgUz1pLmV2YWx1YXRlKG0se30pLmpvaW4oXCIsXCIpLGs9XCJtYXBcIj09PW4uZ2V0KFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIikmJlwicG9pbnRcIiE9PW4uZ2V0KFwic3ltYm9sLXBsYWNlbWVudFwiKSx6PTAsST14LnNlY3Rpb25zO3o8SS5sZW5ndGg7eis9MSl7dmFyIEI9SVt6XSxDPVRuKHgudG9TdHJpbmcoKSksRT1CLmZvbnRTdGFja3x8UyxNPWNbRV09Y1tFXXx8e307dGhpcy5jYWxjdWxhdGVHbHlwaERlcGVuZGVuY2llcyhCLnRleHQsTSxrLEMpO319fX1cImxpbmVcIj09PW4uZ2V0KFwic3ltYm9sLXBsYWNlbWVudFwiKSYmKHRoaXMuZmVhdHVyZXM9ZnVuY3Rpb24odCl7dmFyIGU9e30scj17fSxuPVtdLGk9MDtmdW5jdGlvbiBhKGUpe24ucHVzaCh0W2VdKSxpKys7fWZ1bmN0aW9uIG8odCxlLGkpe3ZhciBhPXJbdF07cmV0dXJuIGRlbGV0ZSByW3RdLHJbZV09YSxuW2FdLmdlb21ldHJ5WzBdLnBvcCgpLG5bYV0uZ2VvbWV0cnlbMF09blthXS5nZW9tZXRyeVswXS5jb25jYXQoaVswXSksYX1mdW5jdGlvbiBzKHQscixpKXt2YXIgYT1lW3JdO3JldHVybiBkZWxldGUgZVtyXSxlW3RdPWEsblthXS5nZW9tZXRyeVswXS5zaGlmdCgpLG5bYV0uZ2VvbWV0cnlbMF09aVswXS5jb25jYXQoblthXS5nZW9tZXRyeVswXSksYX1mdW5jdGlvbiB1KHQsZSxyKXt2YXIgbj1yP2VbMF1bZVswXS5sZW5ndGgtMV06ZVswXVswXTtyZXR1cm4gdCtcIjpcIituLngrXCI6XCIrbi55fWZvcih2YXIgbD0wO2w8dC5sZW5ndGg7bCsrKXt2YXIgcD10W2xdLGM9cC5nZW9tZXRyeSxoPXAudGV4dD9wLnRleHQudG9TdHJpbmcoKTpudWxsO2lmKGgpe3ZhciBmPXUoaCxjKSx5PXUoaCxjLCEwKTtpZihmIGluIHImJnkgaW4gZSYmcltmXSE9PWVbeV0pe3ZhciBkPXMoZix5LGMpLG09byhmLHksbltkXS5nZW9tZXRyeSk7ZGVsZXRlIGVbZl0sZGVsZXRlIHJbeV0sclt1KGgsblttXS5nZW9tZXRyeSwhMCldPW0sbltkXS5nZW9tZXRyeT1udWxsO31lbHNlIGYgaW4gcj9vKGYseSxjKTp5IGluIGU/cyhmLHksYyk6KGEobCksZVtmXT1pLTEsclt5XT1pLTEpO31lbHNlIGEobCk7fXJldHVybiBuLmZpbHRlcihmdW5jdGlvbih0KXtyZXR1cm4gdC5nZW9tZXRyeX0pfSh0aGlzLmZlYXR1cmVzKSksdGhpcy5zb3J0RmVhdHVyZXNCeUtleSYmdGhpcy5mZWF0dXJlcy5zb3J0KGZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQuc29ydEtleS1lLnNvcnRLZXl9KTt9fSxKcy5wcm90b3R5cGUudXBkYXRlPWZ1bmN0aW9uKHQsZSxyKXt0aGlzLnN0YXRlRGVwZW5kZW50TGF5ZXJzLmxlbmd0aCYmKHRoaXMudGV4dC5wcm9ncmFtQ29uZmlndXJhdGlvbnMudXBkYXRlUGFpbnRBcnJheXModCxlLHRoaXMubGF5ZXJzLHIpLHRoaXMuaWNvbi5wcm9ncmFtQ29uZmlndXJhdGlvbnMudXBkYXRlUGFpbnRBcnJheXModCxlLHRoaXMubGF5ZXJzLHIpKTt9LEpzLnByb3RvdHlwZS5pc0VtcHR5PWZ1bmN0aW9uKCl7cmV0dXJuIDA9PT10aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGh9LEpzLnByb3RvdHlwZS51cGxvYWRQZW5kaW5nPWZ1bmN0aW9uKCl7cmV0dXJuICF0aGlzLnVwbG9hZGVkfHx0aGlzLnRleHQucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLm5lZWRzVXBsb2FkfHx0aGlzLmljb24ucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLm5lZWRzVXBsb2FkfSxKcy5wcm90b3R5cGUudXBsb2FkPWZ1bmN0aW9uKHQpe3RoaXMudXBsb2FkZWR8fCh0aGlzLmNvbGxpc2lvbkJveC51cGxvYWQodCksdGhpcy5jb2xsaXNpb25DaXJjbGUudXBsb2FkKHQpKSx0aGlzLnRleHQudXBsb2FkKHQsdGhpcy5zb3J0RmVhdHVyZXNCeVksIXRoaXMudXBsb2FkZWQsdGhpcy50ZXh0LnByb2dyYW1Db25maWd1cmF0aW9ucy5uZWVkc1VwbG9hZCksdGhpcy5pY29uLnVwbG9hZCh0LHRoaXMuc29ydEZlYXR1cmVzQnlZLCF0aGlzLnVwbG9hZGVkLHRoaXMuaWNvbi5wcm9ncmFtQ29uZmlndXJhdGlvbnMubmVlZHNVcGxvYWQpLHRoaXMudXBsb2FkZWQ9ITA7fSxKcy5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMudGV4dC5kZXN0cm95KCksdGhpcy5pY29uLmRlc3Ryb3koKSx0aGlzLmNvbGxpc2lvbkJveC5kZXN0cm95KCksdGhpcy5jb2xsaXNpb25DaXJjbGUuZGVzdHJveSgpO30sSnMucHJvdG90eXBlLmFkZFRvTGluZVZlcnRleEFycmF5PWZ1bmN0aW9uKHQsZSl7dmFyIHI9dGhpcy5saW5lVmVydGV4QXJyYXkubGVuZ3RoO2lmKHZvaWQgMCE9PXQuc2VnbWVudCl7Zm9yKHZhciBuPXQuZGlzdChlW3Quc2VnbWVudCsxXSksaT10LmRpc3QoZVt0LnNlZ21lbnRdKSxhPXt9LG89dC5zZWdtZW50KzE7bzxlLmxlbmd0aDtvKyspYVtvXT17eDplW29dLngseTplW29dLnksdGlsZVVuaXREaXN0YW5jZUZyb21BbmNob3I6bn0sbzxlLmxlbmd0aC0xJiYobis9ZVtvKzFdLmRpc3QoZVtvXSkpO2Zvcih2YXIgcz10LnNlZ21lbnR8fDA7cz49MDtzLS0pYVtzXT17eDplW3NdLngseTplW3NdLnksdGlsZVVuaXREaXN0YW5jZUZyb21BbmNob3I6aX0scz4wJiYoaSs9ZVtzLTFdLmRpc3QoZVtzXSkpO2Zvcih2YXIgdT0wO3U8ZS5sZW5ndGg7dSsrKXt2YXIgbD1hW3VdO3RoaXMubGluZVZlcnRleEFycmF5LmVtcGxhY2VCYWNrKGwueCxsLnksbC50aWxlVW5pdERpc3RhbmNlRnJvbUFuY2hvcik7fX1yZXR1cm4ge2xpbmVTdGFydEluZGV4OnIsbGluZUxlbmd0aDp0aGlzLmxpbmVWZXJ0ZXhBcnJheS5sZW5ndGgtcn19LEpzLnByb3RvdHlwZS5hZGRTeW1ib2xzPWZ1bmN0aW9uKHQsZSxyLG4saSxhLG8scyx1LGwpe2Zvcih2YXIgcD10LmluZGV4QXJyYXksYz10LmxheW91dFZlcnRleEFycmF5LGg9dC5keW5hbWljTGF5b3V0VmVydGV4QXJyYXksZj10LnNlZ21lbnRzLnByZXBhcmVTZWdtZW50KDQqZS5sZW5ndGgsdC5sYXlvdXRWZXJ0ZXhBcnJheSx0LmluZGV4QXJyYXksYS5zb3J0S2V5KSx5PXRoaXMuZ2x5cGhPZmZzZXRBcnJheS5sZW5ndGgsZD1mLnZlcnRleExlbmd0aCxtPTAsdj1lO208di5sZW5ndGg7bSs9MSl7dmFyIGc9dlttXSx4PWcudGwsYj1nLnRyLF89Zy5ibCx3PWcuYnIsQT1nLnRleCxTPWYudmVydGV4TGVuZ3RoLGs9Zy5nbHlwaE9mZnNldFsxXTtacyhjLHMueCxzLnkseC54LGsreC55LEEueCxBLnksciksWnMoYyxzLngscy55LGIueCxrK2IueSxBLngrQS53LEEueSxyKSxacyhjLHMueCxzLnksXy54LGsrXy55LEEueCxBLnkrQS5oLHIpLFpzKGMscy54LHMueSx3Lngsayt3LnksQS54K0EudyxBLnkrQS5oLHIpLEtzKGgscywwKSxwLmVtcGxhY2VCYWNrKFMsUysxLFMrMikscC5lbXBsYWNlQmFjayhTKzEsUysyLFMrMyksZi52ZXJ0ZXhMZW5ndGgrPTQsZi5wcmltaXRpdmVMZW5ndGgrPTIsdGhpcy5nbHlwaE9mZnNldEFycmF5LmVtcGxhY2VCYWNrKGcuZ2x5cGhPZmZzZXRbMF0pO310LnBsYWNlZFN5bWJvbEFycmF5LmVtcGxhY2VCYWNrKHMueCxzLnkseSx0aGlzLmdseXBoT2Zmc2V0QXJyYXkubGVuZ3RoLXksZCx1LGwscy5zZWdtZW50LHI/clswXTowLHI/clsxXTowLG5bMF0sblsxXSxvLCExLDApLHQucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLnBvcHVsYXRlUGFpbnRBcnJheXModC5sYXlvdXRWZXJ0ZXhBcnJheS5sZW5ndGgsYSxhLmluZGV4LHt9KTt9LEpzLnByb3RvdHlwZS5fYWRkQ29sbGlzaW9uRGVidWdWZXJ0ZXg9ZnVuY3Rpb24odCxlLHIsbixpLGEpe3JldHVybiBlLmVtcGxhY2VCYWNrKDAsMCksdC5lbXBsYWNlQmFjayhyLngsci55LG4saSxNYXRoLnJvdW5kKGEueCksTWF0aC5yb3VuZChhLnkpKX0sSnMucHJvdG90eXBlLmFkZENvbGxpc2lvbkRlYnVnVmVydGljZXM9ZnVuY3Rpb24odCxlLHIsbixhLG8scyx1KXt2YXIgbD1hLnNlZ21lbnRzLnByZXBhcmVTZWdtZW50KDQsYS5sYXlvdXRWZXJ0ZXhBcnJheSxhLmluZGV4QXJyYXkpLHA9bC52ZXJ0ZXhMZW5ndGgsYz1hLmxheW91dFZlcnRleEFycmF5LGg9YS5jb2xsaXNpb25WZXJ0ZXhBcnJheSxmPXMuYW5jaG9yWCx5PXMuYW5jaG9yWTtpZih0aGlzLl9hZGRDb2xsaXNpb25EZWJ1Z1ZlcnRleChjLGgsbyxmLHksbmV3IGkodCxlKSksdGhpcy5fYWRkQ29sbGlzaW9uRGVidWdWZXJ0ZXgoYyxoLG8sZix5LG5ldyBpKHIsZSkpLHRoaXMuX2FkZENvbGxpc2lvbkRlYnVnVmVydGV4KGMsaCxvLGYseSxuZXcgaShyLG4pKSx0aGlzLl9hZGRDb2xsaXNpb25EZWJ1Z1ZlcnRleChjLGgsbyxmLHksbmV3IGkodCxuKSksbC52ZXJ0ZXhMZW5ndGgrPTQsdSl7dmFyIGQ9YS5pbmRleEFycmF5O2QuZW1wbGFjZUJhY2socCxwKzEscCsyKSxkLmVtcGxhY2VCYWNrKHAscCsyLHArMyksbC5wcmltaXRpdmVMZW5ndGgrPTI7fWVsc2V7dmFyIG09YS5pbmRleEFycmF5O20uZW1wbGFjZUJhY2socCxwKzEpLG0uZW1wbGFjZUJhY2socCsxLHArMiksbS5lbXBsYWNlQmFjayhwKzIscCszKSxtLmVtcGxhY2VCYWNrKHArMyxwKSxsLnByaW1pdGl2ZUxlbmd0aCs9NDt9fSxKcy5wcm90b3R5cGUuYWRkRGVidWdDb2xsaXNpb25Cb3hlcz1mdW5jdGlvbih0LGUscil7Zm9yKHZhciBuPXQ7bjxlO24rKyl7dmFyIGk9dGhpcy5jb2xsaXNpb25Cb3hBcnJheS5nZXQobiksYT1pLngxLG89aS55MSxzPWkueDIsdT1pLnkyLGw9aS5yYWRpdXM+MDt0aGlzLmFkZENvbGxpc2lvbkRlYnVnVmVydGljZXMoYSxvLHMsdSxsP3RoaXMuY29sbGlzaW9uQ2lyY2xlOnRoaXMuY29sbGlzaW9uQm94LGkuYW5jaG9yUG9pbnQscixsKTt9fSxKcy5wcm90b3R5cGUuZ2VuZXJhdGVDb2xsaXNpb25EZWJ1Z0J1ZmZlcnM9ZnVuY3Rpb24oKXtmb3IodmFyIHQ9MDt0PHRoaXMuc3ltYm9sSW5zdGFuY2VzLmxlbmd0aDt0Kyspe3ZhciBlPXRoaXMuc3ltYm9sSW5zdGFuY2VzLmdldCh0KTt0aGlzLmFkZERlYnVnQ29sbGlzaW9uQm94ZXMoZS50ZXh0Qm94U3RhcnRJbmRleCxlLnRleHRCb3hFbmRJbmRleCxlKSx0aGlzLmFkZERlYnVnQ29sbGlzaW9uQm94ZXMoZS5pY29uQm94U3RhcnRJbmRleCxlLmljb25Cb3hFbmRJbmRleCxlKTt9fSxKcy5wcm90b3R5cGUuX2Rlc2VyaWFsaXplQ29sbGlzaW9uQm94ZXNGb3JTeW1ib2w9ZnVuY3Rpb24odCxlLHIsbixpKXtmb3IodmFyIGE9e30sbz1lO288cjtvKyspe3ZhciBzPXQuZ2V0KG8pO2lmKDA9PT1zLnJhZGl1cyl7YS50ZXh0Qm94PXt4MTpzLngxLHkxOnMueTEseDI6cy54Mix5MjpzLnkyLGFuY2hvclBvaW50WDpzLmFuY2hvclBvaW50WCxhbmNob3JQb2ludFk6cy5hbmNob3JQb2ludFl9LGEudGV4dEZlYXR1cmVJbmRleD1zLmZlYXR1cmVJbmRleDticmVha31hLnRleHRDaXJjbGVzfHwoYS50ZXh0Q2lyY2xlcz1bXSxhLnRleHRGZWF0dXJlSW5kZXg9cy5mZWF0dXJlSW5kZXgpO2EudGV4dENpcmNsZXMucHVzaChzLmFuY2hvclBvaW50WCxzLmFuY2hvclBvaW50WSxzLnJhZGl1cyxzLnNpZ25lZERpc3RhbmNlRnJvbUFuY2hvciwxKTt9Zm9yKHZhciB1PW47dTxpO3UrKyl7dmFyIGw9dC5nZXQodSk7aWYoMD09PWwucmFkaXVzKXthLmljb25Cb3g9e3gxOmwueDEseTE6bC55MSx4MjpsLngyLHkyOmwueTIsYW5jaG9yUG9pbnRYOmwuYW5jaG9yUG9pbnRYLGFuY2hvclBvaW50WTpsLmFuY2hvclBvaW50WX0sYS5pY29uRmVhdHVyZUluZGV4PWwuZmVhdHVyZUluZGV4O2JyZWFrfX1yZXR1cm4gYX0sSnMucHJvdG90eXBlLmRlc2VyaWFsaXplQ29sbGlzaW9uQm94ZXM9ZnVuY3Rpb24odCl7dGhpcy5jb2xsaXNpb25BcnJheXM9W107Zm9yKHZhciBlPTA7ZTx0aGlzLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7ZSsrKXt2YXIgcj10aGlzLnN5bWJvbEluc3RhbmNlcy5nZXQoZSk7dGhpcy5jb2xsaXNpb25BcnJheXMucHVzaCh0aGlzLl9kZXNlcmlhbGl6ZUNvbGxpc2lvbkJveGVzRm9yU3ltYm9sKHQsci50ZXh0Qm94U3RhcnRJbmRleCxyLnRleHRCb3hFbmRJbmRleCxyLmljb25Cb3hTdGFydEluZGV4LHIuaWNvbkJveEVuZEluZGV4KSk7fX0sSnMucHJvdG90eXBlLmhhc1RleHREYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudGV4dC5zZWdtZW50cy5nZXQoKS5sZW5ndGg+MH0sSnMucHJvdG90eXBlLmhhc0ljb25EYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuaWNvbi5zZWdtZW50cy5nZXQoKS5sZW5ndGg+MH0sSnMucHJvdG90eXBlLmhhc0NvbGxpc2lvbkJveERhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jb2xsaXNpb25Cb3guc2VnbWVudHMuZ2V0KCkubGVuZ3RoPjB9LEpzLnByb3RvdHlwZS5oYXNDb2xsaXNpb25DaXJjbGVEYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY29sbGlzaW9uQ2lyY2xlLnNlZ21lbnRzLmdldCgpLmxlbmd0aD4wfSxKcy5wcm90b3R5cGUuYWRkSW5kaWNlc0ZvclBsYWNlZFRleHRTeW1ib2w9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPXRoaXMudGV4dC5wbGFjZWRTeW1ib2xBcnJheS5nZXQodCkscj1lLnZlcnRleFN0YXJ0SW5kZXgrNCplLm51bUdseXBocyxuPWUudmVydGV4U3RhcnRJbmRleDtuPHI7bis9NCl0aGlzLnRleHQuaW5kZXhBcnJheS5lbXBsYWNlQmFjayhuLG4rMSxuKzIpLHRoaXMudGV4dC5pbmRleEFycmF5LmVtcGxhY2VCYWNrKG4rMSxuKzIsbiszKTt9LEpzLnByb3RvdHlwZS5nZXRTb3J0ZWRTeW1ib2xJbmRleGVzPWZ1bmN0aW9uKHQpe2lmKHRoaXMuc29ydGVkQW5nbGU9PT10JiZ2b2lkIDAhPT10aGlzLnN5bWJvbEluc3RhbmNlSW5kZXhlcylyZXR1cm4gdGhpcy5zeW1ib2xJbnN0YW5jZUluZGV4ZXM7Zm9yKHZhciBlPU1hdGguc2luKHQpLHI9TWF0aC5jb3ModCksbj1bXSxpPVtdLGE9W10sbz0wO288dGhpcy5zeW1ib2xJbnN0YW5jZXMubGVuZ3RoOysrbyl7YS5wdXNoKG8pO3ZhciBzPXRoaXMuc3ltYm9sSW5zdGFuY2VzLmdldChvKTtuLnB1c2goMHxNYXRoLnJvdW5kKGUqcy5hbmNob3JYK3Iqcy5hbmNob3JZKSksaS5wdXNoKHMuZmVhdHVyZUluZGV4KTt9cmV0dXJuIGEuc29ydChmdW5jdGlvbih0LGUpe3JldHVybiBuW3RdLW5bZV18fGlbZV0taVt0XX0pLGF9LEpzLnByb3RvdHlwZS5zb3J0RmVhdHVyZXM9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcztpZih0aGlzLnNvcnRGZWF0dXJlc0J5WSYmdGhpcy5zb3J0ZWRBbmdsZSE9PXQmJiEodGhpcy50ZXh0LnNlZ21lbnRzLmdldCgpLmxlbmd0aD4xfHx0aGlzLmljb24uc2VnbWVudHMuZ2V0KCkubGVuZ3RoPjEpKXt0aGlzLnN5bWJvbEluc3RhbmNlSW5kZXhlcz10aGlzLmdldFNvcnRlZFN5bWJvbEluZGV4ZXModCksdGhpcy5zb3J0ZWRBbmdsZT10LHRoaXMudGV4dC5pbmRleEFycmF5LmNsZWFyKCksdGhpcy5pY29uLmluZGV4QXJyYXkuY2xlYXIoKSx0aGlzLmZlYXR1cmVTb3J0T3JkZXI9W107Zm9yKHZhciByPTAsbj10aGlzLnN5bWJvbEluc3RhbmNlSW5kZXhlcztyPG4ubGVuZ3RoO3IrPTEpe3ZhciBpPW5bcl0sYT10aGlzLnN5bWJvbEluc3RhbmNlcy5nZXQoaSk7dGhpcy5mZWF0dXJlU29ydE9yZGVyLnB1c2goYS5mZWF0dXJlSW5kZXgpLFthLnJpZ2h0SnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4LGEuY2VudGVySnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4LGEubGVmdEp1c3RpZmllZFRleHRTeW1ib2xJbmRleF0uZm9yRWFjaChmdW5jdGlvbih0LHIsbil7dD49MCYmbi5pbmRleE9mKHQpPT09ciYmZS5hZGRJbmRpY2VzRm9yUGxhY2VkVGV4dFN5bWJvbCh0KTt9KSxhLnZlcnRpY2FsUGxhY2VkVGV4dFN5bWJvbEluZGV4Pj0wJiZ0aGlzLmFkZEluZGljZXNGb3JQbGFjZWRUZXh0U3ltYm9sKGEudmVydGljYWxQbGFjZWRUZXh0U3ltYm9sSW5kZXgpO3ZhciBvPXRoaXMuaWNvbi5wbGFjZWRTeW1ib2xBcnJheS5nZXQoaSk7aWYoby5udW1HbHlwaHMpe3ZhciBzPW8udmVydGV4U3RhcnRJbmRleDt0aGlzLmljb24uaW5kZXhBcnJheS5lbXBsYWNlQmFjayhzLHMrMSxzKzIpLHRoaXMuaWNvbi5pbmRleEFycmF5LmVtcGxhY2VCYWNrKHMrMSxzKzIscyszKTt9fXRoaXMudGV4dC5pbmRleEJ1ZmZlciYmdGhpcy50ZXh0LmluZGV4QnVmZmVyLnVwZGF0ZURhdGEodGhpcy50ZXh0LmluZGV4QXJyYXkpLHRoaXMuaWNvbi5pbmRleEJ1ZmZlciYmdGhpcy5pY29uLmluZGV4QnVmZmVyLnVwZGF0ZURhdGEodGhpcy5pY29uLmluZGV4QXJyYXkpO319LHpuKFwiU3ltYm9sQnVja2V0XCIsSnMse29taXQ6W1wibGF5ZXJzXCIsXCJjb2xsaXNpb25Cb3hBcnJheVwiLFwiZmVhdHVyZXNcIixcImNvbXBhcmVUZXh0XCJdfSksSnMuTUFYX0dMWVBIUz02NTUzNSxKcy5hZGREeW5hbWljQXR0cmlidXRlcz1Lczt2YXIgSHM9bmV3IGlpKHtcInN5bWJvbC1wbGFjZW1lbnRcIjpuZXcgUW4oTHQubGF5b3V0X3N5bWJvbFtcInN5bWJvbC1wbGFjZW1lbnRcIl0pLFwic3ltYm9sLXNwYWNpbmdcIjpuZXcgUW4oTHQubGF5b3V0X3N5bWJvbFtcInN5bWJvbC1zcGFjaW5nXCJdKSxcInN5bWJvbC1hdm9pZC1lZGdlc1wiOm5ldyBRbihMdC5sYXlvdXRfc3ltYm9sW1wic3ltYm9sLWF2b2lkLWVkZ2VzXCJdKSxcInN5bWJvbC1zb3J0LWtleVwiOm5ldyB0aShMdC5sYXlvdXRfc3ltYm9sW1wic3ltYm9sLXNvcnQta2V5XCJdKSxcInN5bWJvbC16LW9yZGVyXCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJzeW1ib2wtei1vcmRlclwiXSksXCJpY29uLWFsbG93LW92ZXJsYXBcIjpuZXcgUW4oTHQubGF5b3V0X3N5bWJvbFtcImljb24tYWxsb3ctb3ZlcmxhcFwiXSksXCJpY29uLWlnbm9yZS1wbGFjZW1lbnRcIjpuZXcgUW4oTHQubGF5b3V0X3N5bWJvbFtcImljb24taWdub3JlLXBsYWNlbWVudFwiXSksXCJpY29uLW9wdGlvbmFsXCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJpY29uLW9wdGlvbmFsXCJdKSxcImljb24tcm90YXRpb24tYWxpZ25tZW50XCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJpY29uLXJvdGF0aW9uLWFsaWdubWVudFwiXSksXCJpY29uLXNpemVcIjpuZXcgdGkoTHQubGF5b3V0X3N5bWJvbFtcImljb24tc2l6ZVwiXSksXCJpY29uLXRleHQtZml0XCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJpY29uLXRleHQtZml0XCJdKSxcImljb24tdGV4dC1maXQtcGFkZGluZ1wiOm5ldyBRbihMdC5sYXlvdXRfc3ltYm9sW1wiaWNvbi10ZXh0LWZpdC1wYWRkaW5nXCJdKSxcImljb24taW1hZ2VcIjpuZXcgdGkoTHQubGF5b3V0X3N5bWJvbFtcImljb24taW1hZ2VcIl0pLFwiaWNvbi1yb3RhdGVcIjpuZXcgdGkoTHQubGF5b3V0X3N5bWJvbFtcImljb24tcm90YXRlXCJdKSxcImljb24tcGFkZGluZ1wiOm5ldyBRbihMdC5sYXlvdXRfc3ltYm9sW1wiaWNvbi1wYWRkaW5nXCJdKSxcImljb24ta2VlcC11cHJpZ2h0XCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJpY29uLWtlZXAtdXByaWdodFwiXSksXCJpY29uLW9mZnNldFwiOm5ldyB0aShMdC5sYXlvdXRfc3ltYm9sW1wiaWNvbi1vZmZzZXRcIl0pLFwiaWNvbi1hbmNob3JcIjpuZXcgdGkoTHQubGF5b3V0X3N5bWJvbFtcImljb24tYW5jaG9yXCJdKSxcImljb24tcGl0Y2gtYWxpZ25tZW50XCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJpY29uLXBpdGNoLWFsaWdubWVudFwiXSksXCJ0ZXh0LXBpdGNoLWFsaWdubWVudFwiOm5ldyBRbihMdC5sYXlvdXRfc3ltYm9sW1widGV4dC1waXRjaC1hbGlnbm1lbnRcIl0pLFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIjpuZXcgUW4oTHQubGF5b3V0X3N5bWJvbFtcInRleHQtcm90YXRpb24tYWxpZ25tZW50XCJdKSxcInRleHQtZmllbGRcIjpuZXcgdGkoTHQubGF5b3V0X3N5bWJvbFtcInRleHQtZmllbGRcIl0pLFwidGV4dC1mb250XCI6bmV3IHRpKEx0LmxheW91dF9zeW1ib2xbXCJ0ZXh0LWZvbnRcIl0pLFwidGV4dC1zaXplXCI6bmV3IHRpKEx0LmxheW91dF9zeW1ib2xbXCJ0ZXh0LXNpemVcIl0pLFwidGV4dC1tYXgtd2lkdGhcIjpuZXcgdGkoTHQubGF5b3V0X3N5bWJvbFtcInRleHQtbWF4LXdpZHRoXCJdKSxcInRleHQtbGluZS1oZWlnaHRcIjpuZXcgUW4oTHQubGF5b3V0X3N5bWJvbFtcInRleHQtbGluZS1oZWlnaHRcIl0pLFwidGV4dC1sZXR0ZXItc3BhY2luZ1wiOm5ldyB0aShMdC5sYXlvdXRfc3ltYm9sW1widGV4dC1sZXR0ZXItc3BhY2luZ1wiXSksXCJ0ZXh0LWp1c3RpZnlcIjpuZXcgdGkoTHQubGF5b3V0X3N5bWJvbFtcInRleHQtanVzdGlmeVwiXSksXCJ0ZXh0LXJhZGlhbC1vZmZzZXRcIjpuZXcgdGkoTHQubGF5b3V0X3N5bWJvbFtcInRleHQtcmFkaWFsLW9mZnNldFwiXSksXCJ0ZXh0LXZhcmlhYmxlLWFuY2hvclwiOm5ldyBRbihMdC5sYXlvdXRfc3ltYm9sW1widGV4dC12YXJpYWJsZS1hbmNob3JcIl0pLFwidGV4dC1hbmNob3JcIjpuZXcgdGkoTHQubGF5b3V0X3N5bWJvbFtcInRleHQtYW5jaG9yXCJdKSxcInRleHQtbWF4LWFuZ2xlXCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJ0ZXh0LW1heC1hbmdsZVwiXSksXCJ0ZXh0LXJvdGF0ZVwiOm5ldyB0aShMdC5sYXlvdXRfc3ltYm9sW1widGV4dC1yb3RhdGVcIl0pLFwidGV4dC1wYWRkaW5nXCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJ0ZXh0LXBhZGRpbmdcIl0pLFwidGV4dC1rZWVwLXVwcmlnaHRcIjpuZXcgUW4oTHQubGF5b3V0X3N5bWJvbFtcInRleHQta2VlcC11cHJpZ2h0XCJdKSxcInRleHQtdHJhbnNmb3JtXCI6bmV3IHRpKEx0LmxheW91dF9zeW1ib2xbXCJ0ZXh0LXRyYW5zZm9ybVwiXSksXCJ0ZXh0LW9mZnNldFwiOm5ldyB0aShMdC5sYXlvdXRfc3ltYm9sW1widGV4dC1vZmZzZXRcIl0pLFwidGV4dC1hbGxvdy1vdmVybGFwXCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJ0ZXh0LWFsbG93LW92ZXJsYXBcIl0pLFwidGV4dC1pZ25vcmUtcGxhY2VtZW50XCI6bmV3IFFuKEx0LmxheW91dF9zeW1ib2xbXCJ0ZXh0LWlnbm9yZS1wbGFjZW1lbnRcIl0pLFwidGV4dC1vcHRpb25hbFwiOm5ldyBRbihMdC5sYXlvdXRfc3ltYm9sW1widGV4dC1vcHRpb25hbFwiXSl9KSxZcz17cGFpbnQ6bmV3IGlpKHtcImljb24tb3BhY2l0eVwiOm5ldyB0aShMdC5wYWludF9zeW1ib2xbXCJpY29uLW9wYWNpdHlcIl0pLFwiaWNvbi1jb2xvclwiOm5ldyB0aShMdC5wYWludF9zeW1ib2xbXCJpY29uLWNvbG9yXCJdKSxcImljb24taGFsby1jb2xvclwiOm5ldyB0aShMdC5wYWludF9zeW1ib2xbXCJpY29uLWhhbG8tY29sb3JcIl0pLFwiaWNvbi1oYWxvLXdpZHRoXCI6bmV3IHRpKEx0LnBhaW50X3N5bWJvbFtcImljb24taGFsby13aWR0aFwiXSksXCJpY29uLWhhbG8tYmx1clwiOm5ldyB0aShMdC5wYWludF9zeW1ib2xbXCJpY29uLWhhbG8tYmx1clwiXSksXCJpY29uLXRyYW5zbGF0ZVwiOm5ldyBRbihMdC5wYWludF9zeW1ib2xbXCJpY29uLXRyYW5zbGF0ZVwiXSksXCJpY29uLXRyYW5zbGF0ZS1hbmNob3JcIjpuZXcgUW4oTHQucGFpbnRfc3ltYm9sW1wiaWNvbi10cmFuc2xhdGUtYW5jaG9yXCJdKSxcInRleHQtb3BhY2l0eVwiOm5ldyB0aShMdC5wYWludF9zeW1ib2xbXCJ0ZXh0LW9wYWNpdHlcIl0pLFwidGV4dC1jb2xvclwiOm5ldyB0aShMdC5wYWludF9zeW1ib2xbXCJ0ZXh0LWNvbG9yXCJdKSxcInRleHQtaGFsby1jb2xvclwiOm5ldyB0aShMdC5wYWludF9zeW1ib2xbXCJ0ZXh0LWhhbG8tY29sb3JcIl0pLFwidGV4dC1oYWxvLXdpZHRoXCI6bmV3IHRpKEx0LnBhaW50X3N5bWJvbFtcInRleHQtaGFsby13aWR0aFwiXSksXCJ0ZXh0LWhhbG8tYmx1clwiOm5ldyB0aShMdC5wYWludF9zeW1ib2xbXCJ0ZXh0LWhhbG8tYmx1clwiXSksXCJ0ZXh0LXRyYW5zbGF0ZVwiOm5ldyBRbihMdC5wYWludF9zeW1ib2xbXCJ0ZXh0LXRyYW5zbGF0ZVwiXSksXCJ0ZXh0LXRyYW5zbGF0ZS1hbmNob3JcIjpuZXcgUW4oTHQucGFpbnRfc3ltYm9sW1widGV4dC10cmFuc2xhdGUtYW5jaG9yXCJdKX0pLGxheW91dDpIc30sJHM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlKXt0LmNhbGwodGhpcyxlLFlzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLnJlY2FsY3VsYXRlPWZ1bmN0aW9uKGUpe3QucHJvdG90eXBlLnJlY2FsY3VsYXRlLmNhbGwodGhpcyxlKSxcImF1dG9cIj09PXRoaXMubGF5b3V0LmdldChcImljb24tcm90YXRpb24tYWxpZ25tZW50XCIpJiYoXCJwb2ludFwiIT09dGhpcy5sYXlvdXQuZ2V0KFwic3ltYm9sLXBsYWNlbWVudFwiKT90aGlzLmxheW91dC5fdmFsdWVzW1wiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIl09XCJtYXBcIjp0aGlzLmxheW91dC5fdmFsdWVzW1wiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIl09XCJ2aWV3cG9ydFwiKSxcImF1dG9cIj09PXRoaXMubGF5b3V0LmdldChcInRleHQtcm90YXRpb24tYWxpZ25tZW50XCIpJiYoXCJwb2ludFwiIT09dGhpcy5sYXlvdXQuZ2V0KFwic3ltYm9sLXBsYWNlbWVudFwiKT90aGlzLmxheW91dC5fdmFsdWVzW1widGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIl09XCJtYXBcIjp0aGlzLmxheW91dC5fdmFsdWVzW1widGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIl09XCJ2aWV3cG9ydFwiKSxcImF1dG9cIj09PXRoaXMubGF5b3V0LmdldChcInRleHQtcGl0Y2gtYWxpZ25tZW50XCIpJiYodGhpcy5sYXlvdXQuX3ZhbHVlc1tcInRleHQtcGl0Y2gtYWxpZ25tZW50XCJdPXRoaXMubGF5b3V0LmdldChcInRleHQtcm90YXRpb24tYWxpZ25tZW50XCIpKSxcImF1dG9cIj09PXRoaXMubGF5b3V0LmdldChcImljb24tcGl0Y2gtYWxpZ25tZW50XCIpJiYodGhpcy5sYXlvdXQuX3ZhbHVlc1tcImljb24tcGl0Y2gtYWxpZ25tZW50XCJdPXRoaXMubGF5b3V0LmdldChcImljb24tcm90YXRpb24tYWxpZ25tZW50XCIpKTt9LGUucHJvdG90eXBlLmdldFZhbHVlQW5kUmVzb2x2ZVRva2Vucz1mdW5jdGlvbih0LGUpe3ZhciByLG49dGhpcy5sYXlvdXQuZ2V0KHQpLmV2YWx1YXRlKGUse30pLGk9dGhpcy5fdW5ldmFsdWF0ZWRMYXlvdXQuX3ZhbHVlc1t0XTtyZXR1cm4gaS5pc0RhdGFEcml2ZW4oKXx8VnIoaS52YWx1ZSk/bjoocj1lLnByb3BlcnRpZXMsbi5yZXBsYWNlKC97KFtee31dKyl9L2csZnVuY3Rpb24odCxlKXtyZXR1cm4gZSBpbiByP1N0cmluZyhyW2VdKTpcIlwifSkpfSxlLnByb3RvdHlwZS5jcmVhdGVCdWNrZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBKcyh0KX0sZS5wcm90b3R5cGUucXVlcnlSYWRpdXM9ZnVuY3Rpb24oKXtyZXR1cm4gMH0sZS5wcm90b3R5cGUucXVlcnlJbnRlcnNlY3RzRmVhdHVyZT1mdW5jdGlvbigpe3JldHVybiAhMX0sZX0oYWkpLFdzPXtwYWludDpuZXcgaWkoe1wiYmFja2dyb3VuZC1jb2xvclwiOm5ldyBRbihMdC5wYWludF9iYWNrZ3JvdW5kW1wiYmFja2dyb3VuZC1jb2xvclwiXSksXCJiYWNrZ3JvdW5kLXBhdHRlcm5cIjpuZXcgcmkoTHQucGFpbnRfYmFja2dyb3VuZFtcImJhY2tncm91bmQtcGF0dGVyblwiXSksXCJiYWNrZ3JvdW5kLW9wYWNpdHlcIjpuZXcgUW4oTHQucGFpbnRfYmFja2dyb3VuZFtcImJhY2tncm91bmQtb3BhY2l0eVwiXSl9KX0sUXM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlKXt0LmNhbGwodGhpcyxlLFdzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGV9KGFpKSx0dT17cGFpbnQ6bmV3IGlpKHtcInJhc3Rlci1vcGFjaXR5XCI6bmV3IFFuKEx0LnBhaW50X3Jhc3RlcltcInJhc3Rlci1vcGFjaXR5XCJdKSxcInJhc3Rlci1odWUtcm90YXRlXCI6bmV3IFFuKEx0LnBhaW50X3Jhc3RlcltcInJhc3Rlci1odWUtcm90YXRlXCJdKSxcInJhc3Rlci1icmlnaHRuZXNzLW1pblwiOm5ldyBRbihMdC5wYWludF9yYXN0ZXJbXCJyYXN0ZXItYnJpZ2h0bmVzcy1taW5cIl0pLFwicmFzdGVyLWJyaWdodG5lc3MtbWF4XCI6bmV3IFFuKEx0LnBhaW50X3Jhc3RlcltcInJhc3Rlci1icmlnaHRuZXNzLW1heFwiXSksXCJyYXN0ZXItc2F0dXJhdGlvblwiOm5ldyBRbihMdC5wYWludF9yYXN0ZXJbXCJyYXN0ZXItc2F0dXJhdGlvblwiXSksXCJyYXN0ZXItY29udHJhc3RcIjpuZXcgUW4oTHQucGFpbnRfcmFzdGVyW1wicmFzdGVyLWNvbnRyYXN0XCJdKSxcInJhc3Rlci1yZXNhbXBsaW5nXCI6bmV3IFFuKEx0LnBhaW50X3Jhc3RlcltcInJhc3Rlci1yZXNhbXBsaW5nXCJdKSxcInJhc3Rlci1mYWRlLWR1cmF0aW9uXCI6bmV3IFFuKEx0LnBhaW50X3Jhc3RlcltcInJhc3Rlci1mYWRlLWR1cmF0aW9uXCJdKX0pfSxldT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUpe3QuY2FsbCh0aGlzLGUsdHUpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZX0oYWkpO3ZhciBydT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUpe3QuY2FsbCh0aGlzLGUse30pLHRoaXMuaW1wbGVtZW50YXRpb249ZTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmlzM0Q9ZnVuY3Rpb24oKXtyZXR1cm4gXCIzZFwiPT09dGhpcy5pbXBsZW1lbnRhdGlvbi5yZW5kZXJpbmdNb2RlfSxlLnByb3RvdHlwZS5oYXNPZmZzY3JlZW5QYXNzPWZ1bmN0aW9uKCl7cmV0dXJuIHZvaWQgMCE9PXRoaXMuaW1wbGVtZW50YXRpb24ucHJlcmVuZGVyfSxlLnByb3RvdHlwZS5yZWNhbGN1bGF0ZT1mdW5jdGlvbigpe30sZS5wcm90b3R5cGUudXBkYXRlVHJhbnNpdGlvbnM9ZnVuY3Rpb24oKXt9LGUucHJvdG90eXBlLmhhc1RyYW5zaXRpb249ZnVuY3Rpb24oKXt9LGUucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe30sZS5wcm90b3R5cGUub25BZGQ9ZnVuY3Rpb24odCl7dGhpcy5pbXBsZW1lbnRhdGlvbi5vbkFkZCYmdGhpcy5pbXBsZW1lbnRhdGlvbi5vbkFkZCh0LHQucGFpbnRlci5jb250ZXh0LmdsKTt9LGUucHJvdG90eXBlLm9uUmVtb3ZlPWZ1bmN0aW9uKHQpe3RoaXMuaW1wbGVtZW50YXRpb24ub25SZW1vdmUmJnRoaXMuaW1wbGVtZW50YXRpb24ub25SZW1vdmUodCx0LnBhaW50ZXIuY29udGV4dC5nbCk7fSxlfShhaSksbnU9e2NpcmNsZTpRYSxoZWF0bWFwOmxvLGhpbGxzaGFkZTpjbyxmaWxsOkpvLFwiZmlsbC1leHRydXNpb25cIjpocyxsaW5lOklzLHN5bWJvbDokcyxiYWNrZ3JvdW5kOlFzLHJhc3RlcjpldX07ZnVuY3Rpb24gaXUodCl7Zm9yKHZhciBlPTAscj0wLG49MCxpPXQ7bjxpLmxlbmd0aDtuKz0xKXt2YXIgYT1pW25dO2UrPWEudyphLmgscj1NYXRoLm1heChyLGEudyk7fXQuc29ydChmdW5jdGlvbih0LGUpe3JldHVybiBlLmgtdC5ofSk7Zm9yKHZhciBvPVt7eDowLHk6MCx3Ok1hdGgubWF4KE1hdGguY2VpbChNYXRoLnNxcnQoZS8uOTUpKSxyKSxoOjEvMH1dLHM9MCx1PTAsbD0wLHA9dDtsPHAubGVuZ3RoO2wrPTEpZm9yKHZhciBjPXBbbF0saD1vLmxlbmd0aC0xO2g+PTA7aC0tKXt2YXIgZj1vW2hdO2lmKCEoYy53PmYud3x8Yy5oPmYuaCkpe2lmKGMueD1mLngsYy55PWYueSx1PU1hdGgubWF4KHUsYy55K2MuaCkscz1NYXRoLm1heChzLGMueCtjLncpLGMudz09PWYudyYmYy5oPT09Zi5oKXt2YXIgeT1vLnBvcCgpO2g8by5sZW5ndGgmJihvW2hdPXkpO31lbHNlIGMuaD09PWYuaD8oZi54Kz1jLncsZi53LT1jLncpOmMudz09PWYudz8oZi55Kz1jLmgsZi5oLT1jLmgpOihvLnB1c2goe3g6Zi54K2Mudyx5OmYueSx3OmYudy1jLncsaDpjLmh9KSxmLnkrPWMuaCxmLmgtPWMuaCk7YnJlYWt9fXJldHVybiB7dzpzLGg6dSxmaWxsOmUvKHMqdSl8fDB9fXZhciBhdT1mdW5jdGlvbih0LGUpe3ZhciByPWUucGl4ZWxSYXRpbyxuPWUudmVyc2lvbjt0aGlzLnBhZGRlZFJlY3Q9dCx0aGlzLnBpeGVsUmF0aW89cix0aGlzLnZlcnNpb249bjt9LG91PXt0bDp7Y29uZmlndXJhYmxlOiEwfSxicjp7Y29uZmlndXJhYmxlOiEwfSx0bGJyOntjb25maWd1cmFibGU6ITB9LGRpc3BsYXlTaXplOntjb25maWd1cmFibGU6ITB9fTtvdS50bC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gW3RoaXMucGFkZGVkUmVjdC54KzEsdGhpcy5wYWRkZWRSZWN0LnkrMV19LG91LmJyLmdldD1mdW5jdGlvbigpe3JldHVybiBbdGhpcy5wYWRkZWRSZWN0LngrdGhpcy5wYWRkZWRSZWN0LnctMSx0aGlzLnBhZGRlZFJlY3QueSt0aGlzLnBhZGRlZFJlY3QuaC0xXX0sb3UudGxici5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50bC5jb25jYXQodGhpcy5icil9LG91LmRpc3BsYXlTaXplLmdldD1mdW5jdGlvbigpe3JldHVybiBbKHRoaXMucGFkZGVkUmVjdC53LTIpL3RoaXMucGl4ZWxSYXRpbywodGhpcy5wYWRkZWRSZWN0LmgtMikvdGhpcy5waXhlbFJhdGlvXX0sT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoYXUucHJvdG90eXBlLG91KTt2YXIgc3U9ZnVuY3Rpb24odCxlKXt2YXIgcj17fSxuPXt9O3RoaXMuaGF2ZVJlbmRlckNhbGxiYWNrcz1bXTt2YXIgaT1bXTt0aGlzLmFkZEltYWdlcyh0LHIsaSksdGhpcy5hZGRJbWFnZXMoZSxuLGkpO3ZhciBhPWl1KGkpLG89YS53LHM9YS5oLHU9bmV3IG9vKHt3aWR0aDpvfHwxLGhlaWdodDpzfHwxfSk7Zm9yKHZhciBsIGluIHQpe3ZhciBwPXRbbF0sYz1yW2xdLnBhZGRlZFJlY3Q7b28uY29weShwLmRhdGEsdSx7eDowLHk6MH0se3g6Yy54KzEseTpjLnkrMX0scC5kYXRhKTt9Zm9yKHZhciBoIGluIGUpe3ZhciBmPWVbaF0seT1uW2hdLnBhZGRlZFJlY3QsZD15LngrMSxtPXkueSsxLHY9Zi5kYXRhLndpZHRoLGc9Zi5kYXRhLmhlaWdodDtvby5jb3B5KGYuZGF0YSx1LHt4OjAseTowfSx7eDpkLHk6bX0sZi5kYXRhKSxvby5jb3B5KGYuZGF0YSx1LHt4OjAseTpnLTF9LHt4OmQseTptLTF9LHt3aWR0aDp2LGhlaWdodDoxfSksb28uY29weShmLmRhdGEsdSx7eDowLHk6MH0se3g6ZCx5Om0rZ30se3dpZHRoOnYsaGVpZ2h0OjF9KSxvby5jb3B5KGYuZGF0YSx1LHt4OnYtMSx5OjB9LHt4OmQtMSx5Om19LHt3aWR0aDoxLGhlaWdodDpnfSksb28uY29weShmLmRhdGEsdSx7eDowLHk6MH0se3g6ZCt2LHk6bX0se3dpZHRoOjEsaGVpZ2h0Omd9KTt9dGhpcy5pbWFnZT11LHRoaXMuaWNvblBvc2l0aW9ucz1yLHRoaXMucGF0dGVyblBvc2l0aW9ucz1uO307c3UucHJvdG90eXBlLmFkZEltYWdlcz1mdW5jdGlvbih0LGUscil7Zm9yKHZhciBuIGluIHQpe3ZhciBpPXRbbl0sYT17eDowLHk6MCx3OmkuZGF0YS53aWR0aCsyLGg6aS5kYXRhLmhlaWdodCsyfTtyLnB1c2goYSksZVtuXT1uZXcgYXUoYSxpKSxpLmhhc1JlbmRlckNhbGxiYWNrJiZ0aGlzLmhhdmVSZW5kZXJDYWxsYmFja3MucHVzaChuKTt9fSxzdS5wcm90b3R5cGUucGF0Y2hVcGRhdGVkSW1hZ2VzPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByIGluIHQuZGlzcGF0Y2hSZW5kZXJDYWxsYmFja3ModGhpcy5oYXZlUmVuZGVyQ2FsbGJhY2tzKSx0LnVwZGF0ZWRJbWFnZXMpdGhpcy5wYXRjaFVwZGF0ZWRJbWFnZSh0aGlzLmljb25Qb3NpdGlvbnNbcl0sdC5nZXRJbWFnZShyKSxlKSx0aGlzLnBhdGNoVXBkYXRlZEltYWdlKHRoaXMucGF0dGVyblBvc2l0aW9uc1tyXSx0LmdldEltYWdlKHIpLGUpO30sc3UucHJvdG90eXBlLnBhdGNoVXBkYXRlZEltYWdlPWZ1bmN0aW9uKHQsZSxyKXtpZih0JiZlJiZ0LnZlcnNpb24hPT1lLnZlcnNpb24pe3QudmVyc2lvbj1lLnZlcnNpb247dmFyIG49dC50bCxpPW5bMF0sYT1uWzFdO3IudXBkYXRlKGUuZGF0YSx2b2lkIDAse3g6aSx5OmF9KTt9fSx6bihcIkltYWdlUG9zaXRpb25cIixhdSksem4oXCJJbWFnZUF0bGFzXCIsc3UpO3ZhciB1dT1zZWxmLkhUTUxJbWFnZUVsZW1lbnQsbHU9c2VsZi5IVE1MQ2FudmFzRWxlbWVudCxwdT1zZWxmLkhUTUxWaWRlb0VsZW1lbnQsY3U9c2VsZi5JbWFnZURhdGEsaHU9ZnVuY3Rpb24odCxlLHIsbil7dGhpcy5jb250ZXh0PXQsdGhpcy5mb3JtYXQ9cix0aGlzLnRleHR1cmU9dC5nbC5jcmVhdGVUZXh0dXJlKCksdGhpcy51cGRhdGUoZSxuKTt9O2h1LnByb3RvdHlwZS51cGRhdGU9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQud2lkdGgsaT10LmhlaWdodCxhPSEodGhpcy5zaXplJiZ0aGlzLnNpemVbMF09PT1uJiZ0aGlzLnNpemVbMV09PT1pfHxyKSxvPXRoaXMuY29udGV4dCxzPW8uZ2w7aWYodGhpcy51c2VNaXBtYXA9Qm9vbGVhbihlJiZlLnVzZU1pcG1hcCkscy5iaW5kVGV4dHVyZShzLlRFWFRVUkVfMkQsdGhpcy50ZXh0dXJlKSxvLnBpeGVsU3RvcmVVbnBhY2tGbGlwWS5zZXQoITEpLG8ucGl4ZWxTdG9yZVVucGFjay5zZXQoMSksby5waXhlbFN0b3JlVW5wYWNrUHJlbXVsdGlwbHlBbHBoYS5zZXQodGhpcy5mb3JtYXQ9PT1zLlJHQkEmJighZXx8ITEhPT1lLnByZW11bHRpcGx5KSksYSl0aGlzLnNpemU9W24saV0sdCBpbnN0YW5jZW9mIHV1fHx0IGluc3RhbmNlb2YgbHV8fHQgaW5zdGFuY2VvZiBwdXx8dCBpbnN0YW5jZW9mIGN1P3MudGV4SW1hZ2UyRChzLlRFWFRVUkVfMkQsMCx0aGlzLmZvcm1hdCx0aGlzLmZvcm1hdCxzLlVOU0lHTkVEX0JZVEUsdCk6cy50ZXhJbWFnZTJEKHMuVEVYVFVSRV8yRCwwLHRoaXMuZm9ybWF0LG4saSwwLHRoaXMuZm9ybWF0LHMuVU5TSUdORURfQllURSx0LmRhdGEpO2Vsc2V7dmFyIHU9cnx8e3g6MCx5OjB9LGw9dS54LHA9dS55O3QgaW5zdGFuY2VvZiB1dXx8dCBpbnN0YW5jZW9mIGx1fHx0IGluc3RhbmNlb2YgcHV8fHQgaW5zdGFuY2VvZiBjdT9zLnRleFN1YkltYWdlMkQocy5URVhUVVJFXzJELDAsbCxwLHMuUkdCQSxzLlVOU0lHTkVEX0JZVEUsdCk6cy50ZXhTdWJJbWFnZTJEKHMuVEVYVFVSRV8yRCwwLGwscCxuLGkscy5SR0JBLHMuVU5TSUdORURfQllURSx0LmRhdGEpO310aGlzLnVzZU1pcG1hcCYmdGhpcy5pc1NpemVQb3dlck9mVHdvKCkmJnMuZ2VuZXJhdGVNaXBtYXAocy5URVhUVVJFXzJEKTt9LGh1LnByb3RvdHlwZS5iaW5kPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj10aGlzLmNvbnRleHQuZ2w7bi5iaW5kVGV4dHVyZShuLlRFWFRVUkVfMkQsdGhpcy50ZXh0dXJlKSxyIT09bi5MSU5FQVJfTUlQTUFQX05FQVJFU1R8fHRoaXMuaXNTaXplUG93ZXJPZlR3bygpfHwocj1uLkxJTkVBUiksdCE9PXRoaXMuZmlsdGVyJiYobi50ZXhQYXJhbWV0ZXJpKG4uVEVYVFVSRV8yRCxuLlRFWFRVUkVfTUFHX0ZJTFRFUix0KSxuLnRleFBhcmFtZXRlcmkobi5URVhUVVJFXzJELG4uVEVYVFVSRV9NSU5fRklMVEVSLHJ8fHQpLHRoaXMuZmlsdGVyPXQpLGUhPT10aGlzLndyYXAmJihuLnRleFBhcmFtZXRlcmkobi5URVhUVVJFXzJELG4uVEVYVFVSRV9XUkFQX1MsZSksbi50ZXhQYXJhbWV0ZXJpKG4uVEVYVFVSRV8yRCxuLlRFWFRVUkVfV1JBUF9ULGUpLHRoaXMud3JhcD1lKTt9LGh1LnByb3RvdHlwZS5pc1NpemVQb3dlck9mVHdvPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuc2l6ZVswXT09PXRoaXMuc2l6ZVsxXSYmTWF0aC5sb2codGhpcy5zaXplWzBdKS9NYXRoLkxOMiUxPT0wfSxodS5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMuY29udGV4dC5nbC5kZWxldGVUZXh0dXJlKHRoaXMudGV4dHVyZSksdGhpcy50ZXh0dXJlPW51bGw7fTt2YXIgZnU9ZnVuY3Rpb24odCxlLHIsbixpKXt2YXIgYSxvLHM9OCppLW4tMSx1PSgxPDxzKS0xLGw9dT4+MSxwPS03LGM9cj9pLTE6MCxoPXI/LTE6MSxmPXRbZStjXTtmb3IoYys9aCxhPWYmKDE8PC1wKS0xLGY+Pj0tcCxwKz1zO3A+MDthPTI1NiphK3RbZStjXSxjKz1oLHAtPTgpO2ZvcihvPWEmKDE8PC1wKS0xLGE+Pj0tcCxwKz1uO3A+MDtvPTI1NipvK3RbZStjXSxjKz1oLHAtPTgpO2lmKDA9PT1hKWE9MS1sO2Vsc2V7aWYoYT09PXUpcmV0dXJuIG8/TmFOOjEvMCooZj8tMToxKTtvKz1NYXRoLnBvdygyLG4pLGEtPWw7fXJldHVybiAoZj8tMToxKSpvKk1hdGgucG93KDIsYS1uKX0seXU9ZnVuY3Rpb24odCxlLHIsbixpLGEpe3ZhciBvLHMsdSxsPTgqYS1pLTEscD0oMTw8bCktMSxjPXA+PjEsaD0yMz09PWk/TWF0aC5wb3coMiwtMjQpLU1hdGgucG93KDIsLTc3KTowLGY9bj8wOmEtMSx5PW4/MTotMSxkPWU8MHx8MD09PWUmJjEvZTwwPzE6MDtmb3IoZT1NYXRoLmFicyhlKSxpc05hTihlKXx8ZT09PTEvMD8ocz1pc05hTihlKT8xOjAsbz1wKToobz1NYXRoLmZsb29yKE1hdGgubG9nKGUpL01hdGguTE4yKSxlKih1PU1hdGgucG93KDIsLW8pKTwxJiYoby0tLHUqPTIpLChlKz1vK2M+PTE/aC91OmgqTWF0aC5wb3coMiwxLWMpKSp1Pj0yJiYobysrLHUvPTIpLG8rYz49cD8ocz0wLG89cCk6bytjPj0xPyhzPShlKnUtMSkqTWF0aC5wb3coMixpKSxvKz1jKToocz1lKk1hdGgucG93KDIsYy0xKSpNYXRoLnBvdygyLGkpLG89MCkpO2k+PTg7dFtyK2ZdPTI1NSZzLGYrPXkscy89MjU2LGktPTgpO2ZvcihvPW88PGl8cyxsKz1pO2w+MDt0W3IrZl09MjU1Jm8sZis9eSxvLz0yNTYsbC09OCk7dFtyK2YteV18PTEyOCpkO30sZHU9bXU7ZnVuY3Rpb24gbXUodCl7dGhpcy5idWY9QXJyYXlCdWZmZXIuaXNWaWV3JiZBcnJheUJ1ZmZlci5pc1ZpZXcodCk/dDpuZXcgVWludDhBcnJheSh0fHwwKSx0aGlzLnBvcz0wLHRoaXMudHlwZT0wLHRoaXMubGVuZ3RoPXRoaXMuYnVmLmxlbmd0aDt9bXUuVmFyaW50PTAsbXUuRml4ZWQ2ND0xLG11LkJ5dGVzPTIsbXUuRml4ZWQzMj01O2Z1bmN0aW9uIHZ1KHQpe3JldHVybiB0LnR5cGU9PT1tdS5CeXRlcz90LnJlYWRWYXJpbnQoKSt0LnBvczp0LnBvcysxfWZ1bmN0aW9uIGd1KHQsZSxyKXtyZXR1cm4gcj80Mjk0OTY3Mjk2KmUrKHQ+Pj4wKTo0Mjk0OTY3Mjk2KihlPj4+MCkrKHQ+Pj4wKX1mdW5jdGlvbiB4dSh0LGUscil7dmFyIG49ZTw9MTYzODM/MTplPD0yMDk3MTUxPzI6ZTw9MjY4NDM1NDU1PzM6TWF0aC5mbG9vcihNYXRoLmxvZyhlKS8oNypNYXRoLkxOMikpO3IucmVhbGxvYyhuKTtmb3IodmFyIGk9ci5wb3MtMTtpPj10O2ktLSlyLmJ1ZltpK25dPXIuYnVmW2ldO31mdW5jdGlvbiBidSh0LGUpe2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7cisrKWUud3JpdGVWYXJpbnQodFtyXSk7fWZ1bmN0aW9uIF91KHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspZS53cml0ZVNWYXJpbnQodFtyXSk7fWZ1bmN0aW9uIHd1KHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspZS53cml0ZUZsb2F0KHRbcl0pO31mdW5jdGlvbiBBdSh0LGUpe2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7cisrKWUud3JpdGVEb3VibGUodFtyXSk7fWZ1bmN0aW9uIFN1KHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspZS53cml0ZUJvb2xlYW4odFtyXSk7fWZ1bmN0aW9uIGt1KHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspZS53cml0ZUZpeGVkMzIodFtyXSk7fWZ1bmN0aW9uIHp1KHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspZS53cml0ZVNGaXhlZDMyKHRbcl0pO31mdW5jdGlvbiBJdSh0LGUpe2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7cisrKWUud3JpdGVGaXhlZDY0KHRbcl0pO31mdW5jdGlvbiBCdSh0LGUpe2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7cisrKWUud3JpdGVTRml4ZWQ2NCh0W3JdKTt9ZnVuY3Rpb24gQ3UodCxlKXtyZXR1cm4gKHRbZV18dFtlKzFdPDw4fHRbZSsyXTw8MTYpKzE2Nzc3MjE2KnRbZSszXX1mdW5jdGlvbiBFdSh0LGUscil7dFtyXT1lLHRbcisxXT1lPj4+OCx0W3IrMl09ZT4+PjE2LHRbciszXT1lPj4+MjQ7fWZ1bmN0aW9uIE11KHQsZSl7cmV0dXJuICh0W2VdfHRbZSsxXTw8OHx0W2UrMl08PDE2KSsodFtlKzNdPDwyNCl9bXUucHJvdG90eXBlPXtkZXN0cm95OmZ1bmN0aW9uKCl7dGhpcy5idWY9bnVsbDt9LHJlYWRGaWVsZHM6ZnVuY3Rpb24odCxlLHIpe2ZvcihyPXJ8fHRoaXMubGVuZ3RoO3RoaXMucG9zPHI7KXt2YXIgbj10aGlzLnJlYWRWYXJpbnQoKSxpPW4+PjMsYT10aGlzLnBvczt0aGlzLnR5cGU9NyZuLHQoaSxlLHRoaXMpLHRoaXMucG9zPT09YSYmdGhpcy5za2lwKG4pO31yZXR1cm4gZX0scmVhZE1lc3NhZ2U6ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5yZWFkRmllbGRzKHQsZSx0aGlzLnJlYWRWYXJpbnQoKSt0aGlzLnBvcyl9LHJlYWRGaXhlZDMyOmZ1bmN0aW9uKCl7dmFyIHQ9Q3UodGhpcy5idWYsdGhpcy5wb3MpO3JldHVybiB0aGlzLnBvcys9NCx0fSxyZWFkU0ZpeGVkMzI6ZnVuY3Rpb24oKXt2YXIgdD1NdSh0aGlzLmJ1Zix0aGlzLnBvcyk7cmV0dXJuIHRoaXMucG9zKz00LHR9LHJlYWRGaXhlZDY0OmZ1bmN0aW9uKCl7dmFyIHQ9Q3UodGhpcy5idWYsdGhpcy5wb3MpKzQyOTQ5NjcyOTYqQ3UodGhpcy5idWYsdGhpcy5wb3MrNCk7cmV0dXJuIHRoaXMucG9zKz04LHR9LHJlYWRTRml4ZWQ2NDpmdW5jdGlvbigpe3ZhciB0PUN1KHRoaXMuYnVmLHRoaXMucG9zKSs0Mjk0OTY3Mjk2Kk11KHRoaXMuYnVmLHRoaXMucG9zKzQpO3JldHVybiB0aGlzLnBvcys9OCx0fSxyZWFkRmxvYXQ6ZnVuY3Rpb24oKXt2YXIgdD1mdSh0aGlzLmJ1Zix0aGlzLnBvcywhMCwyMyw0KTtyZXR1cm4gdGhpcy5wb3MrPTQsdH0scmVhZERvdWJsZTpmdW5jdGlvbigpe3ZhciB0PWZ1KHRoaXMuYnVmLHRoaXMucG9zLCEwLDUyLDgpO3JldHVybiB0aGlzLnBvcys9OCx0fSxyZWFkVmFyaW50OmZ1bmN0aW9uKHQpe3ZhciBlLHIsbj10aGlzLmJ1ZjtyZXR1cm4gZT0xMjcmKHI9blt0aGlzLnBvcysrXSkscjwxMjg/ZTooZXw9KDEyNyYocj1uW3RoaXMucG9zKytdKSk8PDcscjwxMjg/ZTooZXw9KDEyNyYocj1uW3RoaXMucG9zKytdKSk8PDE0LHI8MTI4P2U6KGV8PSgxMjcmKHI9blt0aGlzLnBvcysrXSkpPDwyMSxyPDEyOD9lOmZ1bmN0aW9uKHQsZSxyKXt2YXIgbixpLGE9ci5idWY7aWYoaT1hW3IucG9zKytdLG49KDExMiZpKT4+NCxpPDEyOClyZXR1cm4gZ3UodCxuLGUpO2lmKGk9YVtyLnBvcysrXSxufD0oMTI3JmkpPDwzLGk8MTI4KXJldHVybiBndSh0LG4sZSk7aWYoaT1hW3IucG9zKytdLG58PSgxMjcmaSk8PDEwLGk8MTI4KXJldHVybiBndSh0LG4sZSk7aWYoaT1hW3IucG9zKytdLG58PSgxMjcmaSk8PDE3LGk8MTI4KXJldHVybiBndSh0LG4sZSk7aWYoaT1hW3IucG9zKytdLG58PSgxMjcmaSk8PDI0LGk8MTI4KXJldHVybiBndSh0LG4sZSk7aWYoaT1hW3IucG9zKytdLG58PSgxJmkpPDwzMSxpPDEyOClyZXR1cm4gZ3UodCxuLGUpO3Rocm93IG5ldyBFcnJvcihcIkV4cGVjdGVkIHZhcmludCBub3QgbW9yZSB0aGFuIDEwIGJ5dGVzXCIpfShlfD0oMTUmKHI9blt0aGlzLnBvc10pKTw8MjgsdCx0aGlzKSkpKX0scmVhZFZhcmludDY0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucmVhZFZhcmludCghMCl9LHJlYWRTVmFyaW50OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yZWFkVmFyaW50KCk7cmV0dXJuIHQlMj09MT8odCsxKS8tMjp0LzJ9LHJlYWRCb29sZWFuOmZ1bmN0aW9uKCl7cmV0dXJuIEJvb2xlYW4odGhpcy5yZWFkVmFyaW50KCkpfSxyZWFkU3RyaW5nOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yZWFkVmFyaW50KCkrdGhpcy5wb3MsZT1mdW5jdGlvbih0LGUscil7dmFyIG49XCJcIixpPWU7Zm9yKDtpPHI7KXt2YXIgYSxvLHMsdT10W2ldLGw9bnVsbCxwPXU+MjM5PzQ6dT4yMjM/Mzp1PjE5MT8yOjE7aWYoaStwPnIpYnJlYWs7MT09PXA/dTwxMjgmJihsPXUpOjI9PT1wPzEyOD09KDE5MiYoYT10W2krMV0pKSYmKGw9KDMxJnUpPDw2fDYzJmEpPD0xMjcmJihsPW51bGwpOjM9PT1wPyhhPXRbaSsxXSxvPXRbaSsyXSwxMjg9PSgxOTImYSkmJjEyOD09KDE5MiZvKSYmKChsPSgxNSZ1KTw8MTJ8KDYzJmEpPDw2fDYzJm8pPD0yMDQ3fHxsPj01NTI5NiYmbDw9NTczNDMpJiYobD1udWxsKSk6ND09PXAmJihhPXRbaSsxXSxvPXRbaSsyXSxzPXRbaSszXSwxMjg9PSgxOTImYSkmJjEyOD09KDE5MiZvKSYmMTI4PT0oMTkyJnMpJiYoKGw9KDE1JnUpPDwxOHwoNjMmYSk8PDEyfCg2MyZvKTw8Nnw2MyZzKTw9NjU1MzV8fGw+PTExMTQxMTIpJiYobD1udWxsKSksbnVsbD09PWw/KGw9NjU1MzMscD0xKTpsPjY1NTM1JiYobC09NjU1MzYsbis9U3RyaW5nLmZyb21DaGFyQ29kZShsPj4+MTAmMTAyM3w1NTI5NiksbD01NjMyMHwxMDIzJmwpLG4rPVN0cmluZy5mcm9tQ2hhckNvZGUobCksaSs9cDt9cmV0dXJuIG59KHRoaXMuYnVmLHRoaXMucG9zLHQpO3JldHVybiB0aGlzLnBvcz10LGV9LHJlYWRCeXRlczpmdW5jdGlvbigpe3ZhciB0PXRoaXMucmVhZFZhcmludCgpK3RoaXMucG9zLGU9dGhpcy5idWYuc3ViYXJyYXkodGhpcy5wb3MsdCk7cmV0dXJuIHRoaXMucG9zPXQsZX0scmVhZFBhY2tlZFZhcmludDpmdW5jdGlvbih0LGUpe2lmKHRoaXMudHlwZSE9PW11LkJ5dGVzKXJldHVybiB0LnB1c2godGhpcy5yZWFkVmFyaW50KGUpKTt2YXIgcj12dSh0aGlzKTtmb3IodD10fHxbXTt0aGlzLnBvczxyOyl0LnB1c2godGhpcy5yZWFkVmFyaW50KGUpKTtyZXR1cm4gdH0scmVhZFBhY2tlZFNWYXJpbnQ6ZnVuY3Rpb24odCl7aWYodGhpcy50eXBlIT09bXUuQnl0ZXMpcmV0dXJuIHQucHVzaCh0aGlzLnJlYWRTVmFyaW50KCkpO3ZhciBlPXZ1KHRoaXMpO2Zvcih0PXR8fFtdO3RoaXMucG9zPGU7KXQucHVzaCh0aGlzLnJlYWRTVmFyaW50KCkpO3JldHVybiB0fSxyZWFkUGFja2VkQm9vbGVhbjpmdW5jdGlvbih0KXtpZih0aGlzLnR5cGUhPT1tdS5CeXRlcylyZXR1cm4gdC5wdXNoKHRoaXMucmVhZEJvb2xlYW4oKSk7dmFyIGU9dnUodGhpcyk7Zm9yKHQ9dHx8W107dGhpcy5wb3M8ZTspdC5wdXNoKHRoaXMucmVhZEJvb2xlYW4oKSk7cmV0dXJuIHR9LHJlYWRQYWNrZWRGbG9hdDpmdW5jdGlvbih0KXtpZih0aGlzLnR5cGUhPT1tdS5CeXRlcylyZXR1cm4gdC5wdXNoKHRoaXMucmVhZEZsb2F0KCkpO3ZhciBlPXZ1KHRoaXMpO2Zvcih0PXR8fFtdO3RoaXMucG9zPGU7KXQucHVzaCh0aGlzLnJlYWRGbG9hdCgpKTtyZXR1cm4gdH0scmVhZFBhY2tlZERvdWJsZTpmdW5jdGlvbih0KXtpZih0aGlzLnR5cGUhPT1tdS5CeXRlcylyZXR1cm4gdC5wdXNoKHRoaXMucmVhZERvdWJsZSgpKTt2YXIgZT12dSh0aGlzKTtmb3IodD10fHxbXTt0aGlzLnBvczxlOyl0LnB1c2godGhpcy5yZWFkRG91YmxlKCkpO3JldHVybiB0fSxyZWFkUGFja2VkRml4ZWQzMjpmdW5jdGlvbih0KXtpZih0aGlzLnR5cGUhPT1tdS5CeXRlcylyZXR1cm4gdC5wdXNoKHRoaXMucmVhZEZpeGVkMzIoKSk7dmFyIGU9dnUodGhpcyk7Zm9yKHQ9dHx8W107dGhpcy5wb3M8ZTspdC5wdXNoKHRoaXMucmVhZEZpeGVkMzIoKSk7cmV0dXJuIHR9LHJlYWRQYWNrZWRTRml4ZWQzMjpmdW5jdGlvbih0KXtpZih0aGlzLnR5cGUhPT1tdS5CeXRlcylyZXR1cm4gdC5wdXNoKHRoaXMucmVhZFNGaXhlZDMyKCkpO3ZhciBlPXZ1KHRoaXMpO2Zvcih0PXR8fFtdO3RoaXMucG9zPGU7KXQucHVzaCh0aGlzLnJlYWRTRml4ZWQzMigpKTtyZXR1cm4gdH0scmVhZFBhY2tlZEZpeGVkNjQ6ZnVuY3Rpb24odCl7aWYodGhpcy50eXBlIT09bXUuQnl0ZXMpcmV0dXJuIHQucHVzaCh0aGlzLnJlYWRGaXhlZDY0KCkpO3ZhciBlPXZ1KHRoaXMpO2Zvcih0PXR8fFtdO3RoaXMucG9zPGU7KXQucHVzaCh0aGlzLnJlYWRGaXhlZDY0KCkpO3JldHVybiB0fSxyZWFkUGFja2VkU0ZpeGVkNjQ6ZnVuY3Rpb24odCl7aWYodGhpcy50eXBlIT09bXUuQnl0ZXMpcmV0dXJuIHQucHVzaCh0aGlzLnJlYWRTRml4ZWQ2NCgpKTt2YXIgZT12dSh0aGlzKTtmb3IodD10fHxbXTt0aGlzLnBvczxlOyl0LnB1c2godGhpcy5yZWFkU0ZpeGVkNjQoKSk7cmV0dXJuIHR9LHNraXA6ZnVuY3Rpb24odCl7dmFyIGU9NyZ0O2lmKGU9PT1tdS5WYXJpbnQpZm9yKDt0aGlzLmJ1Zlt0aGlzLnBvcysrXT4xMjc7KTtlbHNlIGlmKGU9PT1tdS5CeXRlcyl0aGlzLnBvcz10aGlzLnJlYWRWYXJpbnQoKSt0aGlzLnBvcztlbHNlIGlmKGU9PT1tdS5GaXhlZDMyKXRoaXMucG9zKz00O2Vsc2V7aWYoZSE9PW11LkZpeGVkNjQpdGhyb3cgbmV3IEVycm9yKFwiVW5pbXBsZW1lbnRlZCB0eXBlOiBcIitlKTt0aGlzLnBvcys9ODt9fSx3cml0ZVRhZzpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVWYXJpbnQodDw8M3xlKTt9LHJlYWxsb2M6ZnVuY3Rpb24odCl7Zm9yKHZhciBlPXRoaXMubGVuZ3RofHwxNjtlPHRoaXMucG9zK3Q7KWUqPTI7aWYoZSE9PXRoaXMubGVuZ3RoKXt2YXIgcj1uZXcgVWludDhBcnJheShlKTtyLnNldCh0aGlzLmJ1ZiksdGhpcy5idWY9cix0aGlzLmxlbmd0aD1lO319LGZpbmlzaDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmxlbmd0aD10aGlzLnBvcyx0aGlzLnBvcz0wLHRoaXMuYnVmLnN1YmFycmF5KDAsdGhpcy5sZW5ndGgpfSx3cml0ZUZpeGVkMzI6ZnVuY3Rpb24odCl7dGhpcy5yZWFsbG9jKDQpLEV1KHRoaXMuYnVmLHQsdGhpcy5wb3MpLHRoaXMucG9zKz00O30sd3JpdGVTRml4ZWQzMjpmdW5jdGlvbih0KXt0aGlzLnJlYWxsb2MoNCksRXUodGhpcy5idWYsdCx0aGlzLnBvcyksdGhpcy5wb3MrPTQ7fSx3cml0ZUZpeGVkNjQ6ZnVuY3Rpb24odCl7dGhpcy5yZWFsbG9jKDgpLEV1KHRoaXMuYnVmLC0xJnQsdGhpcy5wb3MpLEV1KHRoaXMuYnVmLE1hdGguZmxvb3IodCooMS80Mjk0OTY3Mjk2KSksdGhpcy5wb3MrNCksdGhpcy5wb3MrPTg7fSx3cml0ZVNGaXhlZDY0OmZ1bmN0aW9uKHQpe3RoaXMucmVhbGxvYyg4KSxFdSh0aGlzLmJ1ZiwtMSZ0LHRoaXMucG9zKSxFdSh0aGlzLmJ1ZixNYXRoLmZsb29yKHQqKDEvNDI5NDk2NzI5NikpLHRoaXMucG9zKzQpLHRoaXMucG9zKz04O30sd3JpdGVWYXJpbnQ6ZnVuY3Rpb24odCl7KHQ9K3R8fDApPjI2ODQzNTQ1NXx8dDwwP2Z1bmN0aW9uKHQsZSl7dmFyIHIsbjt0Pj0wPyhyPXQlNDI5NDk2NzI5NnwwLG49dC80Mjk0OTY3Mjk2fDApOihuPX4oLXQvNDI5NDk2NzI5NiksNDI5NDk2NzI5NV4ocj1+KC10JTQyOTQ5NjcyOTYpKT9yPXIrMXwwOihyPTAsbj1uKzF8MCkpO2lmKHQ+PTB4MTAwMDAwMDAwMDAwMDAwMDB8fHQ8LTB4MTAwMDAwMDAwMDAwMDAwMDApdGhyb3cgbmV3IEVycm9yKFwiR2l2ZW4gdmFyaW50IGRvZXNuJ3QgZml0IGludG8gMTAgYnl0ZXNcIik7ZS5yZWFsbG9jKDEwKSxmdW5jdGlvbih0LGUscil7ci5idWZbci5wb3MrK109MTI3JnR8MTI4LHQ+Pj49NyxyLmJ1ZltyLnBvcysrXT0xMjcmdHwxMjgsdD4+Pj03LHIuYnVmW3IucG9zKytdPTEyNyZ0fDEyOCx0Pj4+PTcsci5idWZbci5wb3MrK109MTI3JnR8MTI4LHQ+Pj49NyxyLmJ1ZltyLnBvc109MTI3JnQ7fShyLDAsZSksZnVuY3Rpb24odCxlKXt2YXIgcj0oNyZ0KTw8NDtpZihlLmJ1ZltlLnBvcysrXXw9cnwoKHQ+Pj49Myk/MTI4OjApLCF0KXJldHVybjtpZihlLmJ1ZltlLnBvcysrXT0xMjcmdHwoKHQ+Pj49Nyk/MTI4OjApLCF0KXJldHVybjtpZihlLmJ1ZltlLnBvcysrXT0xMjcmdHwoKHQ+Pj49Nyk/MTI4OjApLCF0KXJldHVybjtpZihlLmJ1ZltlLnBvcysrXT0xMjcmdHwoKHQ+Pj49Nyk/MTI4OjApLCF0KXJldHVybjtpZihlLmJ1ZltlLnBvcysrXT0xMjcmdHwoKHQ+Pj49Nyk/MTI4OjApLCF0KXJldHVybjtlLmJ1ZltlLnBvcysrXT0xMjcmdDt9KG4sZSk7fSh0LHRoaXMpOih0aGlzLnJlYWxsb2MoNCksdGhpcy5idWZbdGhpcy5wb3MrK109MTI3JnR8KHQ+MTI3PzEyODowKSx0PD0xMjd8fCh0aGlzLmJ1Zlt0aGlzLnBvcysrXT0xMjcmKHQ+Pj49Nyl8KHQ+MTI3PzEyODowKSx0PD0xMjd8fCh0aGlzLmJ1Zlt0aGlzLnBvcysrXT0xMjcmKHQ+Pj49Nyl8KHQ+MTI3PzEyODowKSx0PD0xMjd8fCh0aGlzLmJ1Zlt0aGlzLnBvcysrXT10Pj4+NyYxMjcpKSkpO30sd3JpdGVTVmFyaW50OmZ1bmN0aW9uKHQpe3RoaXMud3JpdGVWYXJpbnQodDwwPzIqLXQtMToyKnQpO30sd3JpdGVCb29sZWFuOmZ1bmN0aW9uKHQpe3RoaXMud3JpdGVWYXJpbnQoQm9vbGVhbih0KSk7fSx3cml0ZVN0cmluZzpmdW5jdGlvbih0KXt0PVN0cmluZyh0KSx0aGlzLnJlYWxsb2MoNCp0Lmxlbmd0aCksdGhpcy5wb3MrKzt2YXIgZT10aGlzLnBvczt0aGlzLnBvcz1mdW5jdGlvbih0LGUscil7Zm9yKHZhciBuLGksYT0wO2E8ZS5sZW5ndGg7YSsrKXtpZigobj1lLmNoYXJDb2RlQXQoYSkpPjU1Mjk1JiZuPDU3MzQ0KXtpZighaSl7bj41NjMxOXx8YSsxPT09ZS5sZW5ndGg/KHRbcisrXT0yMzksdFtyKytdPTE5MSx0W3IrK109MTg5KTppPW47Y29udGludWV9aWYobjw1NjMyMCl7dFtyKytdPTIzOSx0W3IrK109MTkxLHRbcisrXT0xODksaT1uO2NvbnRpbnVlfW49aS01NTI5Njw8MTB8bi01NjMyMHw2NTUzNixpPW51bGw7fWVsc2UgaSYmKHRbcisrXT0yMzksdFtyKytdPTE5MSx0W3IrK109MTg5LGk9bnVsbCk7bjwxMjg/dFtyKytdPW46KG48MjA0OD90W3IrK109bj4+NnwxOTI6KG48NjU1MzY/dFtyKytdPW4+PjEyfDIyNDoodFtyKytdPW4+PjE4fDI0MCx0W3IrK109bj4+MTImNjN8MTI4KSx0W3IrK109bj4+NiY2M3wxMjgpLHRbcisrXT02MyZufDEyOCk7fXJldHVybiByfSh0aGlzLmJ1Zix0LHRoaXMucG9zKTt2YXIgcj10aGlzLnBvcy1lO3I+PTEyOCYmeHUoZSxyLHRoaXMpLHRoaXMucG9zPWUtMSx0aGlzLndyaXRlVmFyaW50KHIpLHRoaXMucG9zKz1yO30sd3JpdGVGbG9hdDpmdW5jdGlvbih0KXt0aGlzLnJlYWxsb2MoNCkseXUodGhpcy5idWYsdCx0aGlzLnBvcywhMCwyMyw0KSx0aGlzLnBvcys9NDt9LHdyaXRlRG91YmxlOmZ1bmN0aW9uKHQpe3RoaXMucmVhbGxvYyg4KSx5dSh0aGlzLmJ1Zix0LHRoaXMucG9zLCEwLDUyLDgpLHRoaXMucG9zKz04O30sd3JpdGVCeXRlczpmdW5jdGlvbih0KXt2YXIgZT10Lmxlbmd0aDt0aGlzLndyaXRlVmFyaW50KGUpLHRoaXMucmVhbGxvYyhlKTtmb3IodmFyIHI9MDtyPGU7cisrKXRoaXMuYnVmW3RoaXMucG9zKytdPXRbcl07fSx3cml0ZVJhd01lc3NhZ2U6ZnVuY3Rpb24odCxlKXt0aGlzLnBvcysrO3ZhciByPXRoaXMucG9zO3QoZSx0aGlzKTt2YXIgbj10aGlzLnBvcy1yO24+PTEyOCYmeHUocixuLHRoaXMpLHRoaXMucG9zPXItMSx0aGlzLndyaXRlVmFyaW50KG4pLHRoaXMucG9zKz1uO30sd3JpdGVNZXNzYWdlOmZ1bmN0aW9uKHQsZSxyKXt0aGlzLndyaXRlVGFnKHQsbXUuQnl0ZXMpLHRoaXMud3JpdGVSYXdNZXNzYWdlKGUscik7fSx3cml0ZVBhY2tlZFZhcmludDpmdW5jdGlvbih0LGUpe2UubGVuZ3RoJiZ0aGlzLndyaXRlTWVzc2FnZSh0LGJ1LGUpO30sd3JpdGVQYWNrZWRTVmFyaW50OmZ1bmN0aW9uKHQsZSl7ZS5sZW5ndGgmJnRoaXMud3JpdGVNZXNzYWdlKHQsX3UsZSk7fSx3cml0ZVBhY2tlZEJvb2xlYW46ZnVuY3Rpb24odCxlKXtlLmxlbmd0aCYmdGhpcy53cml0ZU1lc3NhZ2UodCxTdSxlKTt9LHdyaXRlUGFja2VkRmxvYXQ6ZnVuY3Rpb24odCxlKXtlLmxlbmd0aCYmdGhpcy53cml0ZU1lc3NhZ2UodCx3dSxlKTt9LHdyaXRlUGFja2VkRG91YmxlOmZ1bmN0aW9uKHQsZSl7ZS5sZW5ndGgmJnRoaXMud3JpdGVNZXNzYWdlKHQsQXUsZSk7fSx3cml0ZVBhY2tlZEZpeGVkMzI6ZnVuY3Rpb24odCxlKXtlLmxlbmd0aCYmdGhpcy53cml0ZU1lc3NhZ2UodCxrdSxlKTt9LHdyaXRlUGFja2VkU0ZpeGVkMzI6ZnVuY3Rpb24odCxlKXtlLmxlbmd0aCYmdGhpcy53cml0ZU1lc3NhZ2UodCx6dSxlKTt9LHdyaXRlUGFja2VkRml4ZWQ2NDpmdW5jdGlvbih0LGUpe2UubGVuZ3RoJiZ0aGlzLndyaXRlTWVzc2FnZSh0LEl1LGUpO30sd3JpdGVQYWNrZWRTRml4ZWQ2NDpmdW5jdGlvbih0LGUpe2UubGVuZ3RoJiZ0aGlzLndyaXRlTWVzc2FnZSh0LEJ1LGUpO30sd3JpdGVCeXRlc0ZpZWxkOmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZVRhZyh0LG11LkJ5dGVzKSx0aGlzLndyaXRlQnl0ZXMoZSk7fSx3cml0ZUZpeGVkMzJGaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVUYWcodCxtdS5GaXhlZDMyKSx0aGlzLndyaXRlRml4ZWQzMihlKTt9LHdyaXRlU0ZpeGVkMzJGaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVUYWcodCxtdS5GaXhlZDMyKSx0aGlzLndyaXRlU0ZpeGVkMzIoZSk7fSx3cml0ZUZpeGVkNjRGaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVUYWcodCxtdS5GaXhlZDY0KSx0aGlzLndyaXRlRml4ZWQ2NChlKTt9LHdyaXRlU0ZpeGVkNjRGaWVsZDpmdW5jdGlvbih0LGUpe3RoaXMud3JpdGVUYWcodCxtdS5GaXhlZDY0KSx0aGlzLndyaXRlU0ZpeGVkNjQoZSk7fSx3cml0ZVZhcmludEZpZWxkOmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZVRhZyh0LG11LlZhcmludCksdGhpcy53cml0ZVZhcmludChlKTt9LHdyaXRlU1ZhcmludEZpZWxkOmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZVRhZyh0LG11LlZhcmludCksdGhpcy53cml0ZVNWYXJpbnQoZSk7fSx3cml0ZVN0cmluZ0ZpZWxkOmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZVRhZyh0LG11LkJ5dGVzKSx0aGlzLndyaXRlU3RyaW5nKGUpO30sd3JpdGVGbG9hdEZpZWxkOmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZVRhZyh0LG11LkZpeGVkMzIpLHRoaXMud3JpdGVGbG9hdChlKTt9LHdyaXRlRG91YmxlRmllbGQ6ZnVuY3Rpb24odCxlKXt0aGlzLndyaXRlVGFnKHQsbXUuRml4ZWQ2NCksdGhpcy53cml0ZURvdWJsZShlKTt9LHdyaXRlQm9vbGVhbkZpZWxkOmZ1bmN0aW9uKHQsZSl7dGhpcy53cml0ZVZhcmludEZpZWxkKHQsQm9vbGVhbihlKSk7fX07dmFyIFR1PTM7ZnVuY3Rpb24gUHUodCxlLHIpezE9PT10JiZyLnJlYWRNZXNzYWdlKFZ1LGUpO31mdW5jdGlvbiBWdSh0LGUscil7aWYoMz09PXQpe3ZhciBuPXIucmVhZE1lc3NhZ2UoRnUse30pLGk9bi5pZCxhPW4uYml0bWFwLG89bi53aWR0aCxzPW4uaGVpZ2h0LHU9bi5sZWZ0LGw9bi50b3AscD1uLmFkdmFuY2U7ZS5wdXNoKHtpZDppLGJpdG1hcDpuZXcgYW8oe3dpZHRoOm8rMipUdSxoZWlnaHQ6cysyKlR1fSxhKSxtZXRyaWNzOnt3aWR0aDpvLGhlaWdodDpzLGxlZnQ6dSx0b3A6bCxhZHZhbmNlOnB9fSk7fX1mdW5jdGlvbiBGdSh0LGUscil7MT09PXQ/ZS5pZD1yLnJlYWRWYXJpbnQoKToyPT09dD9lLmJpdG1hcD1yLnJlYWRCeXRlcygpOjM9PT10P2Uud2lkdGg9ci5yZWFkVmFyaW50KCk6ND09PXQ/ZS5oZWlnaHQ9ci5yZWFkVmFyaW50KCk6NT09PXQ/ZS5sZWZ0PXIucmVhZFNWYXJpbnQoKTo2PT09dD9lLnRvcD1yLnJlYWRTVmFyaW50KCk6Nz09PXQmJihlLmFkdmFuY2U9ci5yZWFkVmFyaW50KCkpO312YXIgTHU9VHUsRHU9ZnVuY3Rpb24odCxlLHIpe3RoaXMudGFyZ2V0PXQsdGhpcy5wYXJlbnQ9ZSx0aGlzLm1hcElkPXIsdGhpcy5jYWxsYmFja3M9e30sdGhpcy5jYWxsYmFja0lEPTAsbShbXCJyZWNlaXZlXCJdLHRoaXMpLHRoaXMudGFyZ2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsdGhpcy5yZWNlaXZlLCExKTt9O2Z1bmN0aW9uIE91KHQsZSxyKXt2YXIgbj0yKk1hdGguUEkqNjM3ODEzNy8yNTYvTWF0aC5wb3coMixyKTtyZXR1cm4gW3Qqbi0yKk1hdGguUEkqNjM3ODEzNy8yLGUqbi0yKk1hdGguUEkqNjM3ODEzNy8yXX1EdS5wcm90b3R5cGUuc2VuZD1mdW5jdGlvbih0LGUscixuKXt2YXIgaT10aGlzLGE9cj90aGlzLm1hcElkK1wiOlwiK3RoaXMuY2FsbGJhY2tJRCsrOm51bGw7ciYmKHRoaXMuY2FsbGJhY2tzW2FdPXIpO3ZhciBvPVtdO2lmKHRoaXMudGFyZ2V0LnBvc3RNZXNzYWdlKHt0YXJnZXRNYXBJZDpuLHNvdXJjZU1hcElkOnRoaXMubWFwSWQsdHlwZTp0LGlkOlN0cmluZyhhKSxkYXRhOkJuKGUsbyl9LG8pLHIpcmV0dXJuIHtjYW5jZWw6ZnVuY3Rpb24oKXtpLmNhbGxiYWNrc1thXT1udWxsLGkudGFyZ2V0LnBvc3RNZXNzYWdlKHt0YXJnZXRNYXBJZDpuLHNvdXJjZU1hcElkOmkubWFwSWQsdHlwZTpcIjxjYW5jZWw+XCIsaWQ6U3RyaW5nKGEpfSk7fX19LER1LnByb3RvdHlwZS5yZWNlaXZlPWZ1bmN0aW9uKHQpe3ZhciBlLHI9dGhpcyxuPXQuZGF0YSxpPW4uaWQ7aWYoIW4udGFyZ2V0TWFwSWR8fHRoaXMubWFwSWQ9PT1uLnRhcmdldE1hcElkKXt2YXIgYT1mdW5jdGlvbih0LGUpe2RlbGV0ZSByLmNhbGxiYWNrc1tpXTt2YXIgbj1bXTtyLnRhcmdldC5wb3N0TWVzc2FnZSh7c291cmNlTWFwSWQ6ci5tYXBJZCx0eXBlOlwiPHJlc3BvbnNlPlwiLGlkOlN0cmluZyhpKSxlcnJvcjp0P0JuKHQpOm51bGwsZGF0YTpCbihlLG4pfSxuKTt9O2lmKFwiPHJlc3BvbnNlPlwiPT09bi50eXBlfHxcIjxjYW5jZWw+XCI9PT1uLnR5cGUpZT10aGlzLmNhbGxiYWNrc1tuLmlkXSxkZWxldGUgdGhpcy5jYWxsYmFja3Nbbi5pZF0sZSYmbi5lcnJvcj9lKENuKG4uZXJyb3IpKTplJiZlKG51bGwsQ24obi5kYXRhKSk7ZWxzZSBpZih2b2lkIDAhPT1uLmlkJiZ0aGlzLnBhcmVudFtuLnR5cGVdKXt0aGlzLmNhbGxiYWNrc1tuLmlkXT1udWxsO3ZhciBvPXRoaXMucGFyZW50W24udHlwZV0obi5zb3VyY2VNYXBJZCxDbihuLmRhdGEpLGEpO28mJm51bGw9PT10aGlzLmNhbGxiYWNrc1tuLmlkXSYmKHRoaXMuY2FsbGJhY2tzW24uaWRdPW8uY2FuY2VsKTt9ZWxzZSBpZih2b2lkIDAhPT1uLmlkJiZ0aGlzLnBhcmVudC5nZXRXb3JrZXJTb3VyY2Upe3ZhciBzPW4udHlwZS5zcGxpdChcIi5cIiksdT1DbihuLmRhdGEpO3RoaXMucGFyZW50LmdldFdvcmtlclNvdXJjZShuLnNvdXJjZU1hcElkLHNbMF0sdS5zb3VyY2UpW3NbMV1dKHUsYSk7fWVsc2UgdGhpcy5wYXJlbnRbbi50eXBlXShDbihuLmRhdGEpKTt9fSxEdS5wcm90b3R5cGUucmVtb3ZlPWZ1bmN0aW9uKCl7dGhpcy50YXJnZXQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIix0aGlzLnJlY2VpdmUsITEpO307dmFyIFJ1PWZ1bmN0aW9uKHQsZSl7dCYmKGU/dGhpcy5zZXRTb3V0aFdlc3QodCkuc2V0Tm9ydGhFYXN0KGUpOjQ9PT10Lmxlbmd0aD90aGlzLnNldFNvdXRoV2VzdChbdFswXSx0WzFdXSkuc2V0Tm9ydGhFYXN0KFt0WzJdLHRbM11dKTp0aGlzLnNldFNvdXRoV2VzdCh0WzBdKS5zZXROb3J0aEVhc3QodFsxXSkpO307UnUucHJvdG90eXBlLnNldE5vcnRoRWFzdD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbmU9dCBpbnN0YW5jZW9mIFV1P25ldyBVdSh0LmxuZyx0LmxhdCk6VXUuY29udmVydCh0KSx0aGlzfSxSdS5wcm90b3R5cGUuc2V0U291dGhXZXN0PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9zdz10IGluc3RhbmNlb2YgVXU/bmV3IFV1KHQubG5nLHQubGF0KTpVdS5jb252ZXJ0KHQpLHRoaXN9LFJ1LnByb3RvdHlwZS5leHRlbmQ9ZnVuY3Rpb24odCl7dmFyIGUscixuPXRoaXMuX3N3LGk9dGhpcy5fbmU7aWYodCBpbnN0YW5jZW9mIFV1KWU9dCxyPXQ7ZWxzZXtpZighKHQgaW5zdGFuY2VvZiBSdSkpcmV0dXJuIEFycmF5LmlzQXJyYXkodCk/dC5ldmVyeShBcnJheS5pc0FycmF5KT90aGlzLmV4dGVuZChSdS5jb252ZXJ0KHQpKTp0aGlzLmV4dGVuZChVdS5jb252ZXJ0KHQpKTp0aGlzO2lmKGU9dC5fc3cscj10Ll9uZSwhZXx8IXIpcmV0dXJuIHRoaXN9cmV0dXJuIG58fGk/KG4ubG5nPU1hdGgubWluKGUubG5nLG4ubG5nKSxuLmxhdD1NYXRoLm1pbihlLmxhdCxuLmxhdCksaS5sbmc9TWF0aC5tYXgoci5sbmcsaS5sbmcpLGkubGF0PU1hdGgubWF4KHIubGF0LGkubGF0KSk6KHRoaXMuX3N3PW5ldyBVdShlLmxuZyxlLmxhdCksdGhpcy5fbmU9bmV3IFV1KHIubG5nLHIubGF0KSksdGhpc30sUnUucHJvdG90eXBlLmdldENlbnRlcj1mdW5jdGlvbigpe3JldHVybiBuZXcgVXUoKHRoaXMuX3N3LmxuZyt0aGlzLl9uZS5sbmcpLzIsKHRoaXMuX3N3LmxhdCt0aGlzLl9uZS5sYXQpLzIpfSxSdS5wcm90b3R5cGUuZ2V0U291dGhXZXN0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3N3fSxSdS5wcm90b3R5cGUuZ2V0Tm9ydGhFYXN0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX25lfSxSdS5wcm90b3R5cGUuZ2V0Tm9ydGhXZXN0PWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBVdSh0aGlzLmdldFdlc3QoKSx0aGlzLmdldE5vcnRoKCkpfSxSdS5wcm90b3R5cGUuZ2V0U291dGhFYXN0PWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBVdSh0aGlzLmdldEVhc3QoKSx0aGlzLmdldFNvdXRoKCkpfSxSdS5wcm90b3R5cGUuZ2V0V2VzdD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdy5sbmd9LFJ1LnByb3RvdHlwZS5nZXRTb3V0aD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zdy5sYXR9LFJ1LnByb3RvdHlwZS5nZXRFYXN0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX25lLmxuZ30sUnUucHJvdG90eXBlLmdldE5vcnRoPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX25lLmxhdH0sUnUucHJvdG90eXBlLnRvQXJyYXk9ZnVuY3Rpb24oKXtyZXR1cm4gW3RoaXMuX3N3LnRvQXJyYXkoKSx0aGlzLl9uZS50b0FycmF5KCldfSxSdS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gXCJMbmdMYXRCb3VuZHMoXCIrdGhpcy5fc3cudG9TdHJpbmcoKStcIiwgXCIrdGhpcy5fbmUudG9TdHJpbmcoKStcIilcIn0sUnUucHJvdG90eXBlLmlzRW1wdHk9ZnVuY3Rpb24oKXtyZXR1cm4gISh0aGlzLl9zdyYmdGhpcy5fbmUpfSxSdS5jb252ZXJ0PWZ1bmN0aW9uKHQpe3JldHVybiAhdHx8dCBpbnN0YW5jZW9mIFJ1P3Q6bmV3IFJ1KHQpfTt2YXIgVXU9ZnVuY3Rpb24odCxlKXtpZihpc05hTih0KXx8aXNOYU4oZSkpdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBMbmdMYXQgb2JqZWN0OiAoXCIrdCtcIiwgXCIrZStcIilcIik7aWYodGhpcy5sbmc9K3QsdGhpcy5sYXQ9K2UsdGhpcy5sYXQ+OTB8fHRoaXMubGF0PC05MCl0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIExuZ0xhdCBsYXRpdHVkZSB2YWx1ZTogbXVzdCBiZSBiZXR3ZWVuIC05MCBhbmQgOTBcIil9O2Z1bmN0aW9uIGp1KHQpe3JldHVybiAyKk1hdGguUEkqNjM3ODEzNypNYXRoLmNvcyh0Kk1hdGguUEkvMTgwKX1mdW5jdGlvbiBxdSh0KXtyZXR1cm4gKDE4MCt0KS8zNjB9ZnVuY3Rpb24gTnUodCl7cmV0dXJuICgxODAtMTgwL01hdGguUEkqTWF0aC5sb2coTWF0aC50YW4oTWF0aC5QSS80K3QqTWF0aC5QSS8zNjApKSkvMzYwfWZ1bmN0aW9uIFp1KHQsZSl7cmV0dXJuIHQvanUoZSl9ZnVuY3Rpb24gS3UodCl7dmFyIGU9MTgwLTM2MCp0O3JldHVybiAzNjAvTWF0aC5QSSpNYXRoLmF0YW4oTWF0aC5leHAoZSpNYXRoLlBJLzE4MCkpLTkwfVV1LnByb3RvdHlwZS53cmFwPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBVdShwKHRoaXMubG5nLC0xODAsMTgwKSx0aGlzLmxhdCl9LFV1LnByb3RvdHlwZS50b0FycmF5PWZ1bmN0aW9uKCl7cmV0dXJuIFt0aGlzLmxuZyx0aGlzLmxhdF19LFV1LnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiBcIkxuZ0xhdChcIit0aGlzLmxuZytcIiwgXCIrdGhpcy5sYXQrXCIpXCJ9LFV1LnByb3RvdHlwZS50b0JvdW5kcz1mdW5jdGlvbih0KXt2b2lkIDA9PT10JiYodD0wKTt2YXIgZT0zNjAqdC80MDA3NTAxNyxyPWUvTWF0aC5jb3MoTWF0aC5QSS8xODAqdGhpcy5sYXQpO3JldHVybiBuZXcgUnUobmV3IFV1KHRoaXMubG5nLXIsdGhpcy5sYXQtZSksbmV3IFV1KHRoaXMubG5nK3IsdGhpcy5sYXQrZSkpfSxVdS5jb252ZXJ0PWZ1bmN0aW9uKHQpe2lmKHQgaW5zdGFuY2VvZiBVdSlyZXR1cm4gdDtpZihBcnJheS5pc0FycmF5KHQpJiYoMj09PXQubGVuZ3RofHwzPT09dC5sZW5ndGgpKXJldHVybiBuZXcgVXUoTnVtYmVyKHRbMF0pLE51bWJlcih0WzFdKSk7aWYoIUFycmF5LmlzQXJyYXkodCkmJlwib2JqZWN0XCI9PXR5cGVvZiB0JiZudWxsIT09dClyZXR1cm4gbmV3IFV1KE51bWJlcihcImxuZ1wiaW4gdD90LmxuZzp0LmxvbiksTnVtYmVyKHQubGF0KSk7dGhyb3cgbmV3IEVycm9yKFwiYExuZ0xhdExpa2VgIGFyZ3VtZW50IG11c3QgYmUgc3BlY2lmaWVkIGFzIGEgTG5nTGF0IGluc3RhbmNlLCBhbiBvYmplY3Qge2xuZzogPGxuZz4sIGxhdDogPGxhdD59LCBhbiBvYmplY3Qge2xvbjogPGxuZz4sIGxhdDogPGxhdD59LCBvciBhbiBhcnJheSBvZiBbPGxuZz4sIDxsYXQ+XVwiKX07dmFyIEd1PWZ1bmN0aW9uKHQsZSxyKXt2b2lkIDA9PT1yJiYocj0wKSx0aGlzLng9K3QsdGhpcy55PStlLHRoaXMuej0rcjt9O0d1LmZyb21MbmdMYXQ9ZnVuY3Rpb24odCxlKXt2b2lkIDA9PT1lJiYoZT0wKTt2YXIgcj1VdS5jb252ZXJ0KHQpO3JldHVybiBuZXcgR3UocXUoci5sbmcpLE51KHIubGF0KSxadShlLHIubGF0KSl9LEd1LnByb3RvdHlwZS50b0xuZ0xhdD1mdW5jdGlvbigpe3JldHVybiBuZXcgVXUoMzYwKnRoaXMueC0xODAsS3UodGhpcy55KSl9LEd1LnByb3RvdHlwZS50b0FsdGl0dWRlPWZ1bmN0aW9uKCl7cmV0dXJuIHQ9dGhpcy56LGU9dGhpcy55LHQqanUoS3UoZSkpO3ZhciB0LGU7fTt2YXIgWHU9ZnVuY3Rpb24odCxlLHIpe3RoaXMuej10LHRoaXMueD1lLHRoaXMueT1yLHRoaXMua2V5PVl1KDAsdCxlLHIpO307WHUucHJvdG90eXBlLmVxdWFscz1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy56PT09dC56JiZ0aGlzLng9PT10LngmJnRoaXMueT09PXQueX0sWHUucHJvdG90eXBlLnVybD1mdW5jdGlvbih0LGUpe3ZhciByLG4saSxhLG8scz0ocj10aGlzLngsbj10aGlzLnksaT10aGlzLnosYT1PdSgyNTYqciwyNTYqKG49TWF0aC5wb3coMixpKS1uLTEpLGkpLG89T3UoMjU2KihyKzEpLDI1NioobisxKSxpKSxhWzBdK1wiLFwiK2FbMV0rXCIsXCIrb1swXStcIixcIitvWzFdKSx1PWZ1bmN0aW9uKHQsZSxyKXtmb3IodmFyIG4saT1cIlwiLGE9dDthPjA7YS0tKWkrPShlJihuPTE8PGEtMSk/MTowKSsociZuPzI6MCk7cmV0dXJuIGl9KHRoaXMueix0aGlzLngsdGhpcy55KTtyZXR1cm4gdFsodGhpcy54K3RoaXMueSkldC5sZW5ndGhdLnJlcGxhY2UoXCJ7cHJlZml4fVwiLCh0aGlzLnglMTYpLnRvU3RyaW5nKDE2KSsodGhpcy55JTE2KS50b1N0cmluZygxNikpLnJlcGxhY2UoXCJ7en1cIixTdHJpbmcodGhpcy56KSkucmVwbGFjZShcInt4fVwiLFN0cmluZyh0aGlzLngpKS5yZXBsYWNlKFwie3l9XCIsU3RyaW5nKFwidG1zXCI9PT1lP01hdGgucG93KDIsdGhpcy56KS10aGlzLnktMTp0aGlzLnkpKS5yZXBsYWNlKFwie3F1YWRrZXl9XCIsdSkucmVwbGFjZShcIntiYm94LWVwc2ctMzg1N31cIixzKX0sWHUucHJvdG90eXBlLmdldFRpbGVQb2ludD1mdW5jdGlvbih0KXt2YXIgZT1NYXRoLnBvdygyLHRoaXMueik7cmV0dXJuIG5ldyBpKCh0LngqZS10aGlzLngpKnlhLCh0LnkqZS10aGlzLnkpKnlhKX07dmFyIEp1PWZ1bmN0aW9uKHQsZSl7dGhpcy53cmFwPXQsdGhpcy5jYW5vbmljYWw9ZSx0aGlzLmtleT1ZdSh0LGUueixlLngsZS55KTt9LEh1PWZ1bmN0aW9uKHQsZSxyLG4saSl7dGhpcy5vdmVyc2NhbGVkWj10LHRoaXMud3JhcD1lLHRoaXMuY2Fub25pY2FsPW5ldyBYdShyLCtuLCtpKSx0aGlzLmtleT1ZdShlLHQsbixpKTt9O2Z1bmN0aW9uIFl1KHQsZSxyLG4peyh0Kj0yKTwwJiYodD0tMSp0LTEpO3ZhciBpPTE8PGU7cmV0dXJuIDMyKihpKmkqdCtpKm4rcikrZX1IdS5wcm90b3R5cGUuZXF1YWxzPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLm92ZXJzY2FsZWRaPT09dC5vdmVyc2NhbGVkWiYmdGhpcy53cmFwPT09dC53cmFwJiZ0aGlzLmNhbm9uaWNhbC5lcXVhbHModC5jYW5vbmljYWwpfSxIdS5wcm90b3R5cGUuc2NhbGVkVG89ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jYW5vbmljYWwuei10O3JldHVybiB0PnRoaXMuY2Fub25pY2FsLno/bmV3IEh1KHQsdGhpcy53cmFwLHRoaXMuY2Fub25pY2FsLnosdGhpcy5jYW5vbmljYWwueCx0aGlzLmNhbm9uaWNhbC55KTpuZXcgSHUodCx0aGlzLndyYXAsdCx0aGlzLmNhbm9uaWNhbC54Pj5lLHRoaXMuY2Fub25pY2FsLnk+PmUpfSxIdS5wcm90b3R5cGUuaXNDaGlsZE9mPWZ1bmN0aW9uKHQpe2lmKHQud3JhcCE9PXRoaXMud3JhcClyZXR1cm4gITE7dmFyIGU9dGhpcy5jYW5vbmljYWwuei10LmNhbm9uaWNhbC56O3JldHVybiAwPT09dC5vdmVyc2NhbGVkWnx8dC5vdmVyc2NhbGVkWjx0aGlzLm92ZXJzY2FsZWRaJiZ0LmNhbm9uaWNhbC54PT09dGhpcy5jYW5vbmljYWwueD4+ZSYmdC5jYW5vbmljYWwueT09PXRoaXMuY2Fub25pY2FsLnk+PmV9LEh1LnByb3RvdHlwZS5jaGlsZHJlbj1mdW5jdGlvbih0KXtpZih0aGlzLm92ZXJzY2FsZWRaPj10KXJldHVybiBbbmV3IEh1KHRoaXMub3ZlcnNjYWxlZForMSx0aGlzLndyYXAsdGhpcy5jYW5vbmljYWwueix0aGlzLmNhbm9uaWNhbC54LHRoaXMuY2Fub25pY2FsLnkpXTt2YXIgZT10aGlzLmNhbm9uaWNhbC56KzEscj0yKnRoaXMuY2Fub25pY2FsLngsbj0yKnRoaXMuY2Fub25pY2FsLnk7cmV0dXJuIFtuZXcgSHUoZSx0aGlzLndyYXAsZSxyLG4pLG5ldyBIdShlLHRoaXMud3JhcCxlLHIrMSxuKSxuZXcgSHUoZSx0aGlzLndyYXAsZSxyLG4rMSksbmV3IEh1KGUsdGhpcy53cmFwLGUscisxLG4rMSldfSxIdS5wcm90b3R5cGUuaXNMZXNzVGhhbj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy53cmFwPHQud3JhcHx8ISh0aGlzLndyYXA+dC53cmFwKSYmKHRoaXMub3ZlcnNjYWxlZFo8dC5vdmVyc2NhbGVkWnx8ISh0aGlzLm92ZXJzY2FsZWRaPnQub3ZlcnNjYWxlZFopJiYodGhpcy5jYW5vbmljYWwueDx0LmNhbm9uaWNhbC54fHwhKHRoaXMuY2Fub25pY2FsLng+dC5jYW5vbmljYWwueCkmJnRoaXMuY2Fub25pY2FsLnk8dC5jYW5vbmljYWwueSkpfSxIdS5wcm90b3R5cGUud3JhcHBlZD1mdW5jdGlvbigpe3JldHVybiBuZXcgSHUodGhpcy5vdmVyc2NhbGVkWiwwLHRoaXMuY2Fub25pY2FsLnosdGhpcy5jYW5vbmljYWwueCx0aGlzLmNhbm9uaWNhbC55KX0sSHUucHJvdG90eXBlLnVud3JhcFRvPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgSHUodGhpcy5vdmVyc2NhbGVkWix0LHRoaXMuY2Fub25pY2FsLnosdGhpcy5jYW5vbmljYWwueCx0aGlzLmNhbm9uaWNhbC55KX0sSHUucHJvdG90eXBlLm92ZXJzY2FsZUZhY3Rvcj1mdW5jdGlvbigpe3JldHVybiBNYXRoLnBvdygyLHRoaXMub3ZlcnNjYWxlZFotdGhpcy5jYW5vbmljYWwueil9LEh1LnByb3RvdHlwZS50b1Vud3JhcHBlZD1mdW5jdGlvbigpe3JldHVybiBuZXcgSnUodGhpcy53cmFwLHRoaXMuY2Fub25pY2FsKX0sSHUucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMub3ZlcnNjYWxlZForXCIvXCIrdGhpcy5jYW5vbmljYWwueCtcIi9cIit0aGlzLmNhbm9uaWNhbC55fSxIdS5wcm90b3R5cGUuZ2V0VGlsZVBvaW50PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNhbm9uaWNhbC5nZXRUaWxlUG9pbnQobmV3IEd1KHQueC10aGlzLndyYXAsdC55KSl9LHpuKFwiQ2Fub25pY2FsVGlsZUlEXCIsWHUpLHpuKFwiT3ZlcnNjYWxlZFRpbGVJRFwiLEh1LHtvbWl0OltcInBvc01hdHJpeFwiXX0pO3ZhciAkdT1mdW5jdGlvbih0LGUscil7aWYodGhpcy51aWQ9dCxlLmhlaWdodCE9PWUud2lkdGgpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJERU0gdGlsZXMgbXVzdCBiZSBzcXVhcmVcIik7aWYociYmXCJtYXBib3hcIiE9PXImJlwidGVycmFyaXVtXCIhPT1yKXJldHVybiB3KCdcIicrcisnXCIgaXMgbm90IGEgdmFsaWQgZW5jb2RpbmcgdHlwZS4gVmFsaWQgdHlwZXMgaW5jbHVkZSBcIm1hcGJveFwiIGFuZCBcInRlcnJhcml1bVwiLicpO3ZhciBuPXRoaXMuZGltPWUuaGVpZ2h0O3RoaXMuc3RyaWRlPXRoaXMuZGltKzIsdGhpcy5kYXRhPW5ldyBJbnQzMkFycmF5KHRoaXMuc3RyaWRlKnRoaXMuc3RyaWRlKTtmb3IodmFyIGk9ZS5kYXRhLGE9XCJ0ZXJyYXJpdW1cIj09PXI/dGhpcy5fdW5wYWNrVGVycmFyaXVtOnRoaXMuX3VucGFja01hcGJveCxvPTA7bzxuO28rKylmb3IodmFyIHM9MDtzPG47cysrKXt2YXIgdT00KihvKm4rcyk7dGhpcy5zZXQocyxvLGEoaVt1XSxpW3UrMV0saVt1KzJdKSk7fWZvcih2YXIgbD0wO2w8bjtsKyspdGhpcy5zZXQoLTEsbCx0aGlzLmdldCgwLGwpKSx0aGlzLnNldChuLGwsdGhpcy5nZXQobi0xLGwpKSx0aGlzLnNldChsLC0xLHRoaXMuZ2V0KGwsMCkpLHRoaXMuc2V0KGwsbix0aGlzLmdldChsLG4tMSkpO3RoaXMuc2V0KC0xLC0xLHRoaXMuZ2V0KDAsMCkpLHRoaXMuc2V0KG4sLTEsdGhpcy5nZXQobi0xLDApKSx0aGlzLnNldCgtMSxuLHRoaXMuZ2V0KDAsbi0xKSksdGhpcy5zZXQobixuLHRoaXMuZ2V0KG4tMSxuLTEpKTt9OyR1LnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCxlLHIpe3RoaXMuZGF0YVt0aGlzLl9pZHgodCxlKV09cis2NTUzNjt9LCR1LnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5kYXRhW3RoaXMuX2lkeCh0LGUpXS02NTUzNn0sJHUucHJvdG90eXBlLl9pZHg9ZnVuY3Rpb24odCxlKXtpZih0PC0xfHx0Pj10aGlzLmRpbSsxfHxlPC0xfHxlPj10aGlzLmRpbSsxKXRocm93IG5ldyBSYW5nZUVycm9yKFwib3V0IG9mIHJhbmdlIHNvdXJjZSBjb29yZGluYXRlcyBmb3IgREVNIGRhdGFcIik7cmV0dXJuIChlKzEpKnRoaXMuc3RyaWRlKyh0KzEpfSwkdS5wcm90b3R5cGUuX3VucGFja01hcGJveD1mdW5jdGlvbih0LGUscil7cmV0dXJuICgyNTYqdCoyNTYrMjU2KmUrcikvMTAtMWU0fSwkdS5wcm90b3R5cGUuX3VucGFja1RlcnJhcml1bT1mdW5jdGlvbih0LGUscil7cmV0dXJuIDI1Nip0K2Urci8yNTYtMzI3Njh9LCR1LnByb3RvdHlwZS5nZXRQaXhlbHM9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IG9vKHt3aWR0aDp0aGlzLnN0cmlkZSxoZWlnaHQ6dGhpcy5zdHJpZGV9LG5ldyBVaW50OEFycmF5KHRoaXMuZGF0YS5idWZmZXIpKX0sJHUucHJvdG90eXBlLmJhY2tmaWxsQm9yZGVyPWZ1bmN0aW9uKHQsZSxyKXtpZih0aGlzLmRpbSE9PXQuZGltKXRocm93IG5ldyBFcnJvcihcImRlbSBkaW1lbnNpb24gbWlzbWF0Y2hcIik7dmFyIG49ZSp0aGlzLmRpbSxpPWUqdGhpcy5kaW0rdGhpcy5kaW0sYT1yKnRoaXMuZGltLG89cip0aGlzLmRpbSt0aGlzLmRpbTtzd2l0Y2goZSl7Y2FzZS0xOm49aS0xO2JyZWFrO2Nhc2UgMTppPW4rMTt9c3dpdGNoKHIpe2Nhc2UtMTphPW8tMTticmVhaztjYXNlIDE6bz1hKzE7fWZvcih2YXIgcz0tZSp0aGlzLmRpbSx1PS1yKnRoaXMuZGltLGw9YTtsPG87bCsrKWZvcih2YXIgcD1uO3A8aTtwKyspdGhpcy5zZXQocCxsLHQuZ2V0KHArcyxsK3UpKTt9LHpuKFwiREVNRGF0YVwiLCR1KTt2YXIgV3U9bGkoW3tuYW1lOlwiYV9wb3NcIix0eXBlOlwiSW50MTZcIixjb21wb25lbnRzOjJ9LHtuYW1lOlwiYV90ZXh0dXJlX3Bvc1wiLHR5cGU6XCJJbnQxNlwiLGNvbXBvbmVudHM6Mn1dKTt2YXIgUXU9ZnVuY3Rpb24odCl7dGhpcy5fc3RyaW5nVG9OdW1iZXI9e30sdGhpcy5fbnVtYmVyVG9TdHJpbmc9W107Zm9yKHZhciBlPTA7ZTx0Lmxlbmd0aDtlKyspe3ZhciByPXRbZV07dGhpcy5fc3RyaW5nVG9OdW1iZXJbcl09ZSx0aGlzLl9udW1iZXJUb1N0cmluZ1tlXT1yO319O1F1LnByb3RvdHlwZS5lbmNvZGU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX3N0cmluZ1RvTnVtYmVyW3RdfSxRdS5wcm90b3R5cGUuZGVjb2RlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9udW1iZXJUb1N0cmluZ1t0XX07dmFyIHRsPWZ1bmN0aW9uKHQsZSxyLG4pe3RoaXMudHlwZT1cIkZlYXR1cmVcIix0aGlzLl92ZWN0b3JUaWxlRmVhdHVyZT10LHQuX3o9ZSx0Ll94PXIsdC5feT1uLHRoaXMucHJvcGVydGllcz10LnByb3BlcnRpZXMsbnVsbCE9dC5pZCYmKHRoaXMuaWQ9dC5pZCk7fSxlbD17Z2VvbWV0cnk6e2NvbmZpZ3VyYWJsZTohMH19O2VsLmdlb21ldHJ5LmdldD1mdW5jdGlvbigpe3JldHVybiB2b2lkIDA9PT10aGlzLl9nZW9tZXRyeSYmKHRoaXMuX2dlb21ldHJ5PXRoaXMuX3ZlY3RvclRpbGVGZWF0dXJlLnRvR2VvSlNPTih0aGlzLl92ZWN0b3JUaWxlRmVhdHVyZS5feCx0aGlzLl92ZWN0b3JUaWxlRmVhdHVyZS5feSx0aGlzLl92ZWN0b3JUaWxlRmVhdHVyZS5feikuZ2VvbWV0cnkpLHRoaXMuX2dlb21ldHJ5fSxlbC5nZW9tZXRyeS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fZ2VvbWV0cnk9dDt9LHRsLnByb3RvdHlwZS50b0pTT049ZnVuY3Rpb24oKXt2YXIgdD17Z2VvbWV0cnk6dGhpcy5nZW9tZXRyeX07Zm9yKHZhciBlIGluIHRoaXMpXCJfZ2VvbWV0cnlcIiE9PWUmJlwiX3ZlY3RvclRpbGVGZWF0dXJlXCIhPT1lJiYodFtlXT10aGlzW2VdKTtyZXR1cm4gdH0sT2JqZWN0LmRlZmluZVByb3BlcnRpZXModGwucHJvdG90eXBlLGVsKTt2YXIgcmw9ZnVuY3Rpb24oKXt0aGlzLnN0YXRlPXt9LHRoaXMuc3RhdGVDaGFuZ2VzPXt9LHRoaXMuZGVsZXRlZFN0YXRlcz17fTt9O3JsLnByb3RvdHlwZS51cGRhdGVTdGF0ZT1mdW5jdGlvbih0LGUscil7dmFyIG49U3RyaW5nKGUpO2lmKHRoaXMuc3RhdGVDaGFuZ2VzW3RdPXRoaXMuc3RhdGVDaGFuZ2VzW3RdfHx7fSx0aGlzLnN0YXRlQ2hhbmdlc1t0XVtuXT10aGlzLnN0YXRlQ2hhbmdlc1t0XVtuXXx8e30sYyh0aGlzLnN0YXRlQ2hhbmdlc1t0XVtuXSxyKSxudWxsPT09dGhpcy5kZWxldGVkU3RhdGVzW3RdKWZvcih2YXIgaSBpbiB0aGlzLmRlbGV0ZWRTdGF0ZXNbdF09e30sdGhpcy5zdGF0ZVt0XSlpIT09biYmKHRoaXMuZGVsZXRlZFN0YXRlc1t0XVtpXT1udWxsKTtlbHNlIGlmKHRoaXMuZGVsZXRlZFN0YXRlc1t0XSYmbnVsbD09PXRoaXMuZGVsZXRlZFN0YXRlc1t0XVtuXSlmb3IodmFyIGEgaW4gdGhpcy5kZWxldGVkU3RhdGVzW3RdW25dPXt9LHRoaXMuc3RhdGVbdF1bbl0pclthXXx8KHRoaXMuZGVsZXRlZFN0YXRlc1t0XVtuXVthXT1udWxsKTtlbHNlIGZvcih2YXIgbyBpbiByKXt0aGlzLmRlbGV0ZWRTdGF0ZXNbdF0mJnRoaXMuZGVsZXRlZFN0YXRlc1t0XVtuXSYmbnVsbD09PXRoaXMuZGVsZXRlZFN0YXRlc1t0XVtuXVtvXSYmZGVsZXRlIHRoaXMuZGVsZXRlZFN0YXRlc1t0XVtuXVtvXTt9fSxybC5wcm90b3R5cGUucmVtb3ZlRmVhdHVyZVN0YXRlPWZ1bmN0aW9uKHQsZSxyKXtpZighKG51bGw9PT10aGlzLmRlbGV0ZWRTdGF0ZXNbdF0pKXt2YXIgbj1TdHJpbmcoZSk7aWYodGhpcy5kZWxldGVkU3RhdGVzW3RdPXRoaXMuZGVsZXRlZFN0YXRlc1t0XXx8e30sciYmdm9pZCAwIT09ZSYmZT49MCludWxsIT09dGhpcy5kZWxldGVkU3RhdGVzW3RdW25dJiYodGhpcy5kZWxldGVkU3RhdGVzW3RdW25dPXRoaXMuZGVsZXRlZFN0YXRlc1t0XVtuXXx8e30sdGhpcy5kZWxldGVkU3RhdGVzW3RdW25dW3JdPW51bGwpO2Vsc2UgaWYodm9pZCAwIT09ZSYmZT49MCl7aWYodGhpcy5zdGF0ZUNoYW5nZXNbdF0mJnRoaXMuc3RhdGVDaGFuZ2VzW3RdW25dKWZvcihyIGluIHRoaXMuZGVsZXRlZFN0YXRlc1t0XVtuXT17fSx0aGlzLnN0YXRlQ2hhbmdlc1t0XVtuXSl0aGlzLmRlbGV0ZWRTdGF0ZXNbdF1bbl1bcl09bnVsbDtlbHNlIHRoaXMuZGVsZXRlZFN0YXRlc1t0XVtuXT1udWxsO31lbHNlIHRoaXMuZGVsZXRlZFN0YXRlc1t0XT1udWxsO319LHJsLnByb3RvdHlwZS5nZXRTdGF0ZT1mdW5jdGlvbih0LGUpe3ZhciByPVN0cmluZyhlKSxuPXRoaXMuc3RhdGVbdF18fHt9LGk9dGhpcy5zdGF0ZUNoYW5nZXNbdF18fHt9LGE9Yyh7fSxuW3JdLGlbcl0pO2lmKG51bGw9PT10aGlzLmRlbGV0ZWRTdGF0ZXNbdF0pcmV0dXJuIHt9O2lmKHRoaXMuZGVsZXRlZFN0YXRlc1t0XSl7dmFyIG89dGhpcy5kZWxldGVkU3RhdGVzW3RdW2VdO2lmKG51bGw9PT1vKXJldHVybiB7fTtmb3IodmFyIHMgaW4gbylkZWxldGUgYVtzXTt9cmV0dXJuIGF9LHJsLnByb3RvdHlwZS5pbml0aWFsaXplVGlsZVN0YXRlPWZ1bmN0aW9uKHQsZSl7dC5zZXRGZWF0dXJlU3RhdGUodGhpcy5zdGF0ZSxlKTt9LHJsLnByb3RvdHlwZS5jb2FsZXNjZUNoYW5nZXM9ZnVuY3Rpb24odCxlKXt2YXIgcj17fTtmb3IodmFyIG4gaW4gdGhpcy5zdGF0ZUNoYW5nZXMpe3RoaXMuc3RhdGVbbl09dGhpcy5zdGF0ZVtuXXx8e307dmFyIGk9e307Zm9yKHZhciBhIGluIHRoaXMuc3RhdGVDaGFuZ2VzW25dKXRoaXMuc3RhdGVbbl1bYV18fCh0aGlzLnN0YXRlW25dW2FdPXt9KSxjKHRoaXMuc3RhdGVbbl1bYV0sdGhpcy5zdGF0ZUNoYW5nZXNbbl1bYV0pLGlbYV09dGhpcy5zdGF0ZVtuXVthXTtyW25dPWk7fWZvcih2YXIgbyBpbiB0aGlzLmRlbGV0ZWRTdGF0ZXMpe3RoaXMuc3RhdGVbb109dGhpcy5zdGF0ZVtvXXx8e307dmFyIHM9e307aWYobnVsbD09PXRoaXMuZGVsZXRlZFN0YXRlc1tvXSlmb3IodmFyIHUgaW4gdGhpcy5zdGF0ZVtvXSlzW3VdPXt9LHRoaXMuc3RhdGVbb11bdV09e307ZWxzZSBmb3IodmFyIGwgaW4gdGhpcy5kZWxldGVkU3RhdGVzW29dKXtpZihudWxsPT09dGhpcy5kZWxldGVkU3RhdGVzW29dW2xdKXRoaXMuc3RhdGVbb11bbF09e307ZWxzZSBmb3IodmFyIHA9MCxoPU9iamVjdC5rZXlzKHRoaXMuZGVsZXRlZFN0YXRlc1tvXVtsXSk7cDxoLmxlbmd0aDtwKz0xKXt2YXIgZj1oW3BdO2RlbGV0ZSB0aGlzLnN0YXRlW29dW2xdW2ZdO31zW2xdPXRoaXMuc3RhdGVbb11bbF07fXJbb109cltvXXx8e30sYyhyW29dLHMpO31pZih0aGlzLnN0YXRlQ2hhbmdlcz17fSx0aGlzLmRlbGV0ZWRTdGF0ZXM9e30sMCE9PU9iamVjdC5rZXlzKHIpLmxlbmd0aClmb3IodmFyIHkgaW4gdCl7dFt5XS5zZXRGZWF0dXJlU3RhdGUocixlKTt9fTt2YXIgbmw9ZnVuY3Rpb24odCxlLHIpe3RoaXMudGlsZUlEPXQsdGhpcy54PXQuY2Fub25pY2FsLngsdGhpcy55PXQuY2Fub25pY2FsLnksdGhpcy56PXQuY2Fub25pY2FsLnosdGhpcy5ncmlkPWV8fG5ldyBfbih5YSwxNiwwKSx0aGlzLmdyaWQzRD1uZXcgX24oeWEsMTYsMCksdGhpcy5mZWF0dXJlSW5kZXhBcnJheT1yfHxuZXcgTmk7fTtmdW5jdGlvbiBpbCh0KXtmb3IodmFyIGU9MS8wLHI9MS8wLG49LTEvMCxpPS0xLzAsYT0wLG89dDthPG8ubGVuZ3RoO2ErPTEpe3ZhciBzPW9bYV07ZT1NYXRoLm1pbihlLHMueCkscj1NYXRoLm1pbihyLHMueSksbj1NYXRoLm1heChuLHMueCksaT1NYXRoLm1heChpLHMueSk7fXJldHVybiB7bWluWDplLG1pblk6cixtYXhYOm4sbWF4WTppfX1mdW5jdGlvbiBhbCh0LGUpe3JldHVybiBlLXR9bmwucHJvdG90eXBlLmluc2VydD1mdW5jdGlvbih0LGUscixuLGksYSl7dmFyIG89dGhpcy5mZWF0dXJlSW5kZXhBcnJheS5sZW5ndGg7dGhpcy5mZWF0dXJlSW5kZXhBcnJheS5lbXBsYWNlQmFjayhyLG4saSk7Zm9yKHZhciBzPWE/dGhpcy5ncmlkM0Q6dGhpcy5ncmlkLHU9MDt1PGUubGVuZ3RoO3UrKyl7Zm9yKHZhciBsPWVbdV0scD1bMS8wLDEvMCwtMS8wLC0xLzBdLGM9MDtjPGwubGVuZ3RoO2MrKyl7dmFyIGg9bFtjXTtwWzBdPU1hdGgubWluKHBbMF0saC54KSxwWzFdPU1hdGgubWluKHBbMV0saC55KSxwWzJdPU1hdGgubWF4KHBbMl0saC54KSxwWzNdPU1hdGgubWF4KHBbM10saC55KTt9cFswXTx5YSYmcFsxXTx5YSYmcFsyXT49MCYmcFszXT49MCYmcy5pbnNlcnQobyxwWzBdLHBbMV0scFsyXSxwWzNdKTt9fSxubC5wcm90b3R5cGUubG9hZFZUTGF5ZXJzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudnRMYXllcnN8fCh0aGlzLnZ0TGF5ZXJzPW5ldyBpcy5WZWN0b3JUaWxlKG5ldyBkdSh0aGlzLnJhd1RpbGVEYXRhKSkubGF5ZXJzLHRoaXMuc291cmNlTGF5ZXJDb2Rlcj1uZXcgUXUodGhpcy52dExheWVycz9PYmplY3Qua2V5cyh0aGlzLnZ0TGF5ZXJzKS5zb3J0KCk6W1wiX2dlb2pzb25UaWxlTGF5ZXJcIl0pKSx0aGlzLnZ0TGF5ZXJzfSxubC5wcm90b3R5cGUucXVlcnk9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPXRoaXM7dGhpcy5sb2FkVlRMYXllcnMoKTtmb3IodmFyIGE9dC5wYXJhbXN8fHt9LG89eWEvdC50aWxlU2l6ZS90LnNjYWxlLHM9SnIoYS5maWx0ZXIpLHU9dC5xdWVyeUdlb21ldHJ5LGw9dC5xdWVyeVBhZGRpbmcqbyxwPWlsKHUpLGM9dGhpcy5ncmlkLnF1ZXJ5KHAubWluWC1sLHAubWluWS1sLHAubWF4WCtsLHAubWF4WStsKSxoPWlsKHQuY2FtZXJhUXVlcnlHZW9tZXRyeSksZj10aGlzLmdyaWQzRC5xdWVyeShoLm1pblgtbCxoLm1pblktbCxoLm1heFgrbCxoLm1heFkrbCxmdW5jdGlvbihlLHIsbixhKXtyZXR1cm4gZnVuY3Rpb24odCxlLHIsbixhKXtmb3IodmFyIG89MCxzPXQ7bzxzLmxlbmd0aDtvKz0xKXt2YXIgdT1zW29dO2lmKGU8PXUueCYmcjw9dS55JiZuPj11LngmJmE+PXUueSlyZXR1cm4gITB9dmFyIGw9W25ldyBpKGUsciksbmV3IGkoZSxhKSxuZXcgaShuLGEpLG5ldyBpKG4scildO2lmKHQubGVuZ3RoPjIpZm9yKHZhciBwPTAsYz1sO3A8Yy5sZW5ndGg7cCs9MSlpZihDYSh0LGNbcF0pKXJldHVybiAhMDtmb3IodmFyIGg9MDtoPHQubGVuZ3RoLTE7aCsrKWlmKEVhKHRbaF0sdFtoKzFdLGwpKXJldHVybiAhMDtyZXR1cm4gITF9KHQuY2FtZXJhUXVlcnlHZW9tZXRyeSxlLWwsci1sLG4rbCxhK2wpfSkseT0wLGQ9Zjt5PGQubGVuZ3RoO3krPTEpe3ZhciBtPWRbeV07Yy5wdXNoKG0pO31jLnNvcnQoYWwpO2Zvcih2YXIgdixnPXt9LHg9ZnVuY3Rpb24oaSl7dmFyIGw9Y1tpXTtpZihsIT09dil7dj1sO3ZhciBwPW4uZmVhdHVyZUluZGV4QXJyYXkuZ2V0KGwpLGg9bnVsbDtuLmxvYWRNYXRjaGluZ0ZlYXR1cmUoZyxwLmJ1Y2tldEluZGV4LHAuc291cmNlTGF5ZXJJbmRleCxwLmZlYXR1cmVJbmRleCxzLGEubGF5ZXJzLGUsZnVuY3Rpb24oZSxpKXtofHwoaD12YShlKSk7dmFyIGE9e307cmV0dXJuIGUuaWQmJihhPXIuZ2V0U3RhdGUoaS5zb3VyY2VMYXllcnx8XCJfZ2VvanNvblRpbGVMYXllclwiLGUuaWQpKSxpLnF1ZXJ5SW50ZXJzZWN0c0ZlYXR1cmUodSxlLGEsaCxuLnosdC50cmFuc2Zvcm0sbyx0LnBpeGVsUG9zTWF0cml4KX0pO319LGI9MDtiPGMubGVuZ3RoO2IrKyl4KGIpO3JldHVybiBnfSxubC5wcm90b3R5cGUubG9hZE1hdGNoaW5nRmVhdHVyZT1mdW5jdGlvbih0LGUscixuLGksYSxvLHMpe3ZhciB1PXRoaXMuYnVja2V0TGF5ZXJJRHNbZV07aWYoIWF8fGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDtyKyspaWYoZS5pbmRleE9mKHRbcl0pPj0wKXJldHVybiAhMDtyZXR1cm4gITF9KGEsdSkpe3ZhciBsPXRoaXMuc291cmNlTGF5ZXJDb2Rlci5kZWNvZGUocikscD10aGlzLnZ0TGF5ZXJzW2xdLmZlYXR1cmUobik7aWYoaShuZXcgWm4odGhpcy50aWxlSUQub3ZlcnNjYWxlZFopLHApKWZvcih2YXIgYz0wO2M8dS5sZW5ndGg7YysrKXt2YXIgaD11W2NdO2lmKCEoYSYmYS5pbmRleE9mKGgpPDApKXt2YXIgZj1vW2hdO2lmKGYpe3ZhciB5PSFzfHxzKHAsZik7aWYoeSl7dmFyIGQ9bmV3IHRsKHAsdGhpcy56LHRoaXMueCx0aGlzLnkpO2QubGF5ZXI9Zi5zZXJpYWxpemUoKTt2YXIgbT10W2hdO3ZvaWQgMD09PW0mJihtPXRbaF09W10pLG0ucHVzaCh7ZmVhdHVyZUluZGV4Om4sZmVhdHVyZTpkLGludGVyc2VjdGlvblo6eX0pO319fX19fSxubC5wcm90b3R5cGUubG9va3VwU3ltYm9sRmVhdHVyZXM9ZnVuY3Rpb24odCxlLHIsbixpLGEpe3ZhciBvPXt9O3RoaXMubG9hZFZUTGF5ZXJzKCk7Zm9yKHZhciBzPUpyKG4pLHU9MCxsPXQ7dTxsLmxlbmd0aDt1Kz0xKXt2YXIgcD1sW3VdO3RoaXMubG9hZE1hdGNoaW5nRmVhdHVyZShvLGUscixwLHMsaSxhKTt9cmV0dXJuIG99LG5sLnByb3RvdHlwZS5oYXNMYXllcj1mdW5jdGlvbih0KXtmb3IodmFyIGU9MCxyPXRoaXMuYnVja2V0TGF5ZXJJRHM7ZTxyLmxlbmd0aDtlKz0xKWZvcih2YXIgbj0wLGk9cltlXTtuPGkubGVuZ3RoO24rPTEpe2lmKHQ9PT1pW25dKXJldHVybiAhMH1yZXR1cm4gITF9LHpuKFwiRmVhdHVyZUluZGV4XCIsbmwse29taXQ6W1wicmF3VGlsZURhdGFcIixcInNvdXJjZUxheWVyQ29kZXJcIl19KTt2YXIgb2w9ZnVuY3Rpb24odCxlKXt0aGlzLnRpbGVJRD10LHRoaXMudWlkPWYoKSx0aGlzLnVzZXM9MCx0aGlzLnRpbGVTaXplPWUsdGhpcy5idWNrZXRzPXt9LHRoaXMuZXhwaXJhdGlvblRpbWU9bnVsbCx0aGlzLnF1ZXJ5UGFkZGluZz0wLHRoaXMuaGFzU3ltYm9sQnVja2V0cz0hMSx0aGlzLmV4cGlyZWRSZXF1ZXN0Q291bnQ9MCx0aGlzLnN0YXRlPVwibG9hZGluZ1wiO307b2wucHJvdG90eXBlLnJlZ2lzdGVyRmFkZUR1cmF0aW9uPWZ1bmN0aW9uKHQpe3ZhciBlPXQrdGhpcy50aW1lQWRkZWQ7ZTxQLm5vdygpfHx0aGlzLmZhZGVFbmRUaW1lJiZlPHRoaXMuZmFkZUVuZFRpbWV8fCh0aGlzLmZhZGVFbmRUaW1lPWUpO30sb2wucHJvdG90eXBlLndhc1JlcXVlc3RlZD1mdW5jdGlvbigpe3JldHVybiBcImVycm9yZWRcIj09PXRoaXMuc3RhdGV8fFwibG9hZGVkXCI9PT10aGlzLnN0YXRlfHxcInJlbG9hZGluZ1wiPT09dGhpcy5zdGF0ZX0sb2wucHJvdG90eXBlLmxvYWRWZWN0b3JEYXRhPWZ1bmN0aW9uKHQsZSxyKXtpZih0aGlzLmhhc0RhdGEoKSYmdGhpcy51bmxvYWRWZWN0b3JEYXRhKCksdGhpcy5zdGF0ZT1cImxvYWRlZFwiLHQpe2Zvcih2YXIgbiBpbiB0LmZlYXR1cmVJbmRleCYmKHRoaXMubGF0ZXN0RmVhdHVyZUluZGV4PXQuZmVhdHVyZUluZGV4LHQucmF3VGlsZURhdGE/KHRoaXMubGF0ZXN0UmF3VGlsZURhdGE9dC5yYXdUaWxlRGF0YSx0aGlzLmxhdGVzdEZlYXR1cmVJbmRleC5yYXdUaWxlRGF0YT10LnJhd1RpbGVEYXRhKTp0aGlzLmxhdGVzdFJhd1RpbGVEYXRhJiYodGhpcy5sYXRlc3RGZWF0dXJlSW5kZXgucmF3VGlsZURhdGE9dGhpcy5sYXRlc3RSYXdUaWxlRGF0YSkpLHRoaXMuY29sbGlzaW9uQm94QXJyYXk9dC5jb2xsaXNpb25Cb3hBcnJheSx0aGlzLmJ1Y2tldHM9ZnVuY3Rpb24odCxlKXt2YXIgcj17fTtpZighZSlyZXR1cm4gcjtmb3IodmFyIG49ZnVuY3Rpb24oKXt2YXIgdD1hW2ldLG49dC5sYXllcklkcy5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIGUuZ2V0TGF5ZXIodCl9KS5maWx0ZXIoQm9vbGVhbik7aWYoMCE9PW4ubGVuZ3RoKXt0LmxheWVycz1uLHQuc3RhdGVEZXBlbmRlbnRMYXllcklkcyYmKHQuc3RhdGVEZXBlbmRlbnRMYXllcnM9dC5zdGF0ZURlcGVuZGVudExheWVySWRzLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gbi5maWx0ZXIoZnVuY3Rpb24oZSl7cmV0dXJuIGUuaWQ9PT10fSlbMF19KSk7Zm9yKHZhciBvPTAscz1uO288cy5sZW5ndGg7bys9MSl7dmFyIHU9c1tvXTtyW3UuaWRdPXQ7fX19LGk9MCxhPXQ7aTxhLmxlbmd0aDtpKz0xKW4oKTtyZXR1cm4gcn0odC5idWNrZXRzLGUuc3R5bGUpLHRoaXMuaGFzU3ltYm9sQnVja2V0cz0hMSx0aGlzLmJ1Y2tldHMpe3ZhciBpPXRoaXMuYnVja2V0c1tuXTtpZihpIGluc3RhbmNlb2YgSnMpe2lmKHRoaXMuaGFzU3ltYm9sQnVja2V0cz0hMCwhcilicmVhaztpLmp1c3RSZWxvYWRlZD0hMDt9fWZvcih2YXIgYSBpbiB0aGlzLnF1ZXJ5UGFkZGluZz0wLHRoaXMuYnVja2V0cyl7dmFyIG89dGhpcy5idWNrZXRzW2FdO3RoaXMucXVlcnlQYWRkaW5nPU1hdGgubWF4KHRoaXMucXVlcnlQYWRkaW5nLGUuc3R5bGUuZ2V0TGF5ZXIoYSkucXVlcnlSYWRpdXMobykpO310LmltYWdlQXRsYXMmJih0aGlzLmltYWdlQXRsYXM9dC5pbWFnZUF0bGFzKSx0LmdseXBoQXRsYXNJbWFnZSYmKHRoaXMuZ2x5cGhBdGxhc0ltYWdlPXQuZ2x5cGhBdGxhc0ltYWdlKTt9ZWxzZSB0aGlzLmNvbGxpc2lvbkJveEFycmF5PW5ldyBQaTt9LG9sLnByb3RvdHlwZS51bmxvYWRWZWN0b3JEYXRhPWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMuYnVja2V0cyl0aGlzLmJ1Y2tldHNbdF0uZGVzdHJveSgpO3RoaXMuYnVja2V0cz17fSx0aGlzLmltYWdlQXRsYXNUZXh0dXJlJiZ0aGlzLmltYWdlQXRsYXNUZXh0dXJlLmRlc3Ryb3koKSx0aGlzLmltYWdlQXRsYXMmJih0aGlzLmltYWdlQXRsYXM9bnVsbCksdGhpcy5nbHlwaEF0bGFzVGV4dHVyZSYmdGhpcy5nbHlwaEF0bGFzVGV4dHVyZS5kZXN0cm95KCksdGhpcy5sYXRlc3RGZWF0dXJlSW5kZXg9bnVsbCx0aGlzLnN0YXRlPVwidW5sb2FkZWRcIjt9LG9sLnByb3RvdHlwZS51bmxvYWRERU1EYXRhPWZ1bmN0aW9uKCl7dGhpcy5kZW09bnVsbCx0aGlzLm5laWdoYm9yaW5nVGlsZXM9bnVsbCx0aGlzLnN0YXRlPVwidW5sb2FkZWRcIjt9LG9sLnByb3RvdHlwZS5nZXRCdWNrZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuYnVja2V0c1t0LmlkXX0sb2wucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbih0KXtmb3IodmFyIGUgaW4gdGhpcy5idWNrZXRzKXt2YXIgcj10aGlzLmJ1Y2tldHNbZV07ci51cGxvYWRQZW5kaW5nKCkmJnIudXBsb2FkKHQpO312YXIgbj10LmdsO3RoaXMuaW1hZ2VBdGxhcyYmIXRoaXMuaW1hZ2VBdGxhcy51cGxvYWRlZCYmKHRoaXMuaW1hZ2VBdGxhc1RleHR1cmU9bmV3IGh1KHQsdGhpcy5pbWFnZUF0bGFzLmltYWdlLG4uUkdCQSksdGhpcy5pbWFnZUF0bGFzLnVwbG9hZGVkPSEwKSx0aGlzLmdseXBoQXRsYXNJbWFnZSYmKHRoaXMuZ2x5cGhBdGxhc1RleHR1cmU9bmV3IGh1KHQsdGhpcy5nbHlwaEF0bGFzSW1hZ2Usbi5BTFBIQSksdGhpcy5nbHlwaEF0bGFzSW1hZ2U9bnVsbCk7fSxvbC5wcm90b3R5cGUucHJlcGFyZT1mdW5jdGlvbih0KXt0aGlzLmltYWdlQXRsYXMmJnRoaXMuaW1hZ2VBdGxhcy5wYXRjaFVwZGF0ZWRJbWFnZXModCx0aGlzLmltYWdlQXRsYXNUZXh0dXJlKTt9LG9sLnByb3RvdHlwZS5xdWVyeVJlbmRlcmVkRmVhdHVyZXM9ZnVuY3Rpb24odCxlLHIsbixpLGEsbyxzLHUpe3JldHVybiB0aGlzLmxhdGVzdEZlYXR1cmVJbmRleCYmdGhpcy5sYXRlc3RGZWF0dXJlSW5kZXgucmF3VGlsZURhdGE/dGhpcy5sYXRlc3RGZWF0dXJlSW5kZXgucXVlcnkoe3F1ZXJ5R2VvbWV0cnk6cixjYW1lcmFRdWVyeUdlb21ldHJ5Om4sc2NhbGU6aSx0aWxlU2l6ZTp0aGlzLnRpbGVTaXplLHBpeGVsUG9zTWF0cml4OnUsdHJhbnNmb3JtOm8scGFyYW1zOmEscXVlcnlQYWRkaW5nOnRoaXMucXVlcnlQYWRkaW5nKnN9LHQsZSk6e319LG9sLnByb3RvdHlwZS5xdWVyeVNvdXJjZUZlYXR1cmVzPWZ1bmN0aW9uKHQsZSl7aWYodGhpcy5sYXRlc3RGZWF0dXJlSW5kZXgmJnRoaXMubGF0ZXN0RmVhdHVyZUluZGV4LnJhd1RpbGVEYXRhKXt2YXIgcj10aGlzLmxhdGVzdEZlYXR1cmVJbmRleC5sb2FkVlRMYXllcnMoKSxuPWU/ZS5zb3VyY2VMYXllcjpcIlwiLGk9ci5fZ2VvanNvblRpbGVMYXllcnx8cltuXTtpZihpKWZvcih2YXIgYT1KcihlJiZlLmZpbHRlciksbz10aGlzLnRpbGVJRC5jYW5vbmljYWwscz1vLnosdT1vLngsbD1vLnkscD17ejpzLHg6dSx5Omx9LGM9MDtjPGkubGVuZ3RoO2MrKyl7dmFyIGg9aS5mZWF0dXJlKGMpO2lmKGEobmV3IFpuKHRoaXMudGlsZUlELm92ZXJzY2FsZWRaKSxoKSl7dmFyIGY9bmV3IHRsKGgscyx1LGwpO2YudGlsZT1wLHQucHVzaChmKTt9fX19LG9sLnByb3RvdHlwZS5jbGVhck1hc2s9ZnVuY3Rpb24oKXt0aGlzLnNlZ21lbnRzJiYodGhpcy5zZWdtZW50cy5kZXN0cm95KCksZGVsZXRlIHRoaXMuc2VnbWVudHMpLHRoaXMubWFza2VkQm91bmRzQnVmZmVyJiYodGhpcy5tYXNrZWRCb3VuZHNCdWZmZXIuZGVzdHJveSgpLGRlbGV0ZSB0aGlzLm1hc2tlZEJvdW5kc0J1ZmZlciksdGhpcy5tYXNrZWRJbmRleEJ1ZmZlciYmKHRoaXMubWFza2VkSW5kZXhCdWZmZXIuZGVzdHJveSgpLGRlbGV0ZSB0aGlzLm1hc2tlZEluZGV4QnVmZmVyKTt9LG9sLnByb3RvdHlwZS5zZXRNYXNrPWZ1bmN0aW9uKHQsZSl7aWYoIW8odGhpcy5tYXNrLHQpJiYodGhpcy5tYXNrPXQsdGhpcy5jbGVhck1hc2soKSwhbyh0LHswOiEwfSkpKXt2YXIgcj1uZXcgaGksbj1uZXcgSWk7dGhpcy5zZWdtZW50cz1uZXcgS2ksdGhpcy5zZWdtZW50cy5wcmVwYXJlU2VnbWVudCgwLHIsbik7Zm9yKHZhciBhPU9iamVjdC5rZXlzKHQpLHM9MDtzPGEubGVuZ3RoO3MrKyl7dmFyIHU9dFsrYVtzXV0sbD15YT4+dS56LHA9bmV3IGkodS54KmwsdS55KmwpLGM9bmV3IGkocC54K2wscC55K2wpLGg9dGhpcy5zZWdtZW50cy5wcmVwYXJlU2VnbWVudCg0LHIsbik7ci5lbXBsYWNlQmFjayhwLngscC55LHAueCxwLnkpLHIuZW1wbGFjZUJhY2soYy54LHAueSxjLngscC55KSxyLmVtcGxhY2VCYWNrKHAueCxjLnkscC54LGMueSksci5lbXBsYWNlQmFjayhjLngsYy55LGMueCxjLnkpO3ZhciBmPWgudmVydGV4TGVuZ3RoO24uZW1wbGFjZUJhY2soZixmKzEsZisyKSxuLmVtcGxhY2VCYWNrKGYrMSxmKzIsZiszKSxoLnZlcnRleExlbmd0aCs9NCxoLnByaW1pdGl2ZUxlbmd0aCs9Mjt9dGhpcy5tYXNrZWRCb3VuZHNCdWZmZXI9ZS5jcmVhdGVWZXJ0ZXhCdWZmZXIocixXdS5tZW1iZXJzKSx0aGlzLm1hc2tlZEluZGV4QnVmZmVyPWUuY3JlYXRlSW5kZXhCdWZmZXIobik7fX0sb2wucHJvdG90eXBlLmhhc0RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gXCJsb2FkZWRcIj09PXRoaXMuc3RhdGV8fFwicmVsb2FkaW5nXCI9PT10aGlzLnN0YXRlfHxcImV4cGlyZWRcIj09PXRoaXMuc3RhdGV9LG9sLnByb3RvdHlwZS5wYXR0ZXJuc0xvYWRlZD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmltYWdlQXRsYXMmJiEhT2JqZWN0LmtleXModGhpcy5pbWFnZUF0bGFzLnBhdHRlcm5Qb3NpdGlvbnMpLmxlbmd0aH0sb2wucHJvdG90eXBlLnNldEV4cGlyeURhdGE9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5leHBpcmF0aW9uVGltZTtpZih0LmNhY2hlQ29udHJvbCl7dmFyIHI9ayh0LmNhY2hlQ29udHJvbCk7cltcIm1heC1hZ2VcIl0mJih0aGlzLmV4cGlyYXRpb25UaW1lPURhdGUubm93KCkrMWUzKnJbXCJtYXgtYWdlXCJdKTt9ZWxzZSB0LmV4cGlyZXMmJih0aGlzLmV4cGlyYXRpb25UaW1lPW5ldyBEYXRlKHQuZXhwaXJlcykuZ2V0VGltZSgpKTtpZih0aGlzLmV4cGlyYXRpb25UaW1lKXt2YXIgbj1EYXRlLm5vdygpLGk9ITE7aWYodGhpcy5leHBpcmF0aW9uVGltZT5uKWk9ITE7ZWxzZSBpZihlKWlmKHRoaXMuZXhwaXJhdGlvblRpbWU8ZSlpPSEwO2Vsc2V7dmFyIGE9dGhpcy5leHBpcmF0aW9uVGltZS1lO2E/dGhpcy5leHBpcmF0aW9uVGltZT1uK01hdGgubWF4KGEsM2U0KTppPSEwO31lbHNlIGk9ITA7aT8odGhpcy5leHBpcmVkUmVxdWVzdENvdW50KyssdGhpcy5zdGF0ZT1cImV4cGlyZWRcIik6dGhpcy5leHBpcmVkUmVxdWVzdENvdW50PTA7fX0sb2wucHJvdG90eXBlLmdldEV4cGlyeVRpbWVvdXQ9ZnVuY3Rpb24oKXtpZih0aGlzLmV4cGlyYXRpb25UaW1lKXJldHVybiB0aGlzLmV4cGlyZWRSZXF1ZXN0Q291bnQ/MWUzKigxPDxNYXRoLm1pbih0aGlzLmV4cGlyZWRSZXF1ZXN0Q291bnQtMSwzMSkpOk1hdGgubWluKHRoaXMuZXhwaXJhdGlvblRpbWUtKG5ldyBEYXRlKS5nZXRUaW1lKCksTWF0aC5wb3coMiwzMSktMSl9LG9sLnByb3RvdHlwZS5zZXRGZWF0dXJlU3RhdGU9ZnVuY3Rpb24odCxlKXtpZih0aGlzLmxhdGVzdEZlYXR1cmVJbmRleCYmdGhpcy5sYXRlc3RGZWF0dXJlSW5kZXgucmF3VGlsZURhdGEmJjAhPT1PYmplY3Qua2V5cyh0KS5sZW5ndGgpe3ZhciByPXRoaXMubGF0ZXN0RmVhdHVyZUluZGV4LmxvYWRWVExheWVycygpO2Zvcih2YXIgbiBpbiB0aGlzLmJ1Y2tldHMpe3ZhciBpPXRoaXMuYnVja2V0c1tuXSxhPWkubGF5ZXJzWzBdLnNvdXJjZUxheWVyfHxcIl9nZW9qc29uVGlsZUxheWVyXCIsbz1yW2FdLHM9dFthXTtvJiZzJiYwIT09T2JqZWN0LmtleXMocykubGVuZ3RoJiYoaS51cGRhdGUocyxvLHRoaXMuaW1hZ2VBdGxhcyYmdGhpcy5pbWFnZUF0bGFzLnBhdHRlcm5Qb3NpdGlvbnN8fHt9KSxlJiZlLnN0eWxlJiYodGhpcy5xdWVyeVBhZGRpbmc9TWF0aC5tYXgodGhpcy5xdWVyeVBhZGRpbmcsZS5zdHlsZS5nZXRMYXllcihuKS5xdWVyeVJhZGl1cyhpKSkpKTt9fX0sb2wucHJvdG90eXBlLmhvbGRpbmdGb3JGYWRlPWZ1bmN0aW9uKCl7cmV0dXJuIHZvaWQgMCE9PXRoaXMuc3ltYm9sRmFkZUhvbGRVbnRpbH0sb2wucHJvdG90eXBlLnN5bWJvbEZhZGVGaW5pc2hlZD1mdW5jdGlvbigpe3JldHVybiAhdGhpcy5zeW1ib2xGYWRlSG9sZFVudGlsfHx0aGlzLnN5bWJvbEZhZGVIb2xkVW50aWw8UC5ub3coKX0sb2wucHJvdG90eXBlLmNsZWFyRmFkZUhvbGQ9ZnVuY3Rpb24oKXt0aGlzLnN5bWJvbEZhZGVIb2xkVW50aWw9dm9pZCAwO30sb2wucHJvdG90eXBlLnNldEhvbGREdXJhdGlvbj1mdW5jdGlvbih0KXt0aGlzLnN5bWJvbEZhZGVIb2xkVW50aWw9UC5ub3coKSt0O307dmFyIHNsPTI0LHVsPXtob3Jpem9udGFsOjEsdmVydGljYWw6Mixob3Jpem9udGFsT25seTozfSxsbD1mdW5jdGlvbigpe3RoaXMudGV4dD1cIlwiLHRoaXMuc2VjdGlvbkluZGV4PVtdLHRoaXMuc2VjdGlvbnM9W107fTtmdW5jdGlvbiBwbCh0LGUscixuLGksYSxvLHMsdSxsKXt2YXIgcCxjPWxsLmZyb21GZWF0dXJlKHQscik7bD09PXVsLnZlcnRpY2FsJiZjLnZlcnRpY2FsaXplUHVuY3R1YXRpb24oKTt2YXIgaD1Obi5wcm9jZXNzQmlkaXJlY3Rpb25hbFRleHQsZj1Obi5wcm9jZXNzU3R5bGVkQmlkaXJlY3Rpb25hbFRleHQ7aWYoaCYmMT09PWMuc2VjdGlvbnMubGVuZ3RoKXtwPVtdO2Zvcih2YXIgeT0wLGQ9aChjLnRvU3RyaW5nKCksbWwoYyxzLG4sZSkpO3k8ZC5sZW5ndGg7eSs9MSl7dmFyIG09ZFt5XSx2PW5ldyBsbDt2LnRleHQ9bSx2LnNlY3Rpb25zPWMuc2VjdGlvbnM7Zm9yKHZhciBnPTA7ZzxtLmxlbmd0aDtnKyspdi5zZWN0aW9uSW5kZXgucHVzaCgwKTtwLnB1c2godik7fX1lbHNlIGlmKGYpe3A9W107Zm9yKHZhciB4PTAsYj1mKGMudGV4dCxjLnNlY3Rpb25JbmRleCxtbChjLHMsbixlKSk7eDxiLmxlbmd0aDt4Kz0xKXt2YXIgXz1iW3hdLHc9bmV3IGxsO3cudGV4dD1fWzBdLHcuc2VjdGlvbkluZGV4PV9bMV0sdy5zZWN0aW9ucz1jLnNlY3Rpb25zLHAucHVzaCh3KTt9fWVsc2UgcD1mdW5jdGlvbih0LGUpe2Zvcih2YXIgcj1bXSxuPXQudGV4dCxpPTAsYT0wLG89ZTthPG8ubGVuZ3RoO2ErPTEpe3ZhciBzPW9bYV07ci5wdXNoKHQuc3Vic3RyaW5nKGkscykpLGk9czt9cmV0dXJuIGk8bi5sZW5ndGgmJnIucHVzaCh0LnN1YnN0cmluZyhpLG4ubGVuZ3RoKSkscn0oYyxtbChjLHMsbixlKSk7dmFyIEE9W10sUz17cG9zaXRpb25lZEdseXBoczpBLHRleHQ6Yy50b1N0cmluZygpLHRvcDp1WzFdLGJvdHRvbTp1WzFdLGxlZnQ6dVswXSxyaWdodDp1WzBdLHdyaXRpbmdNb2RlOmwsbGluZUNvdW50OnAubGVuZ3RofTtyZXR1cm4gZnVuY3Rpb24odCxlLHIsbixpLGEsbyxzKXtmb3IodmFyIHU9MCxsPS0xNyxwPTAsYz10LnBvc2l0aW9uZWRHbHlwaHMsaD1cInJpZ2h0XCI9PT1hPzE6XCJsZWZ0XCI9PT1hPzA6LjUsZj0wLHk9cjtmPHkubGVuZ3RoO2YrPTEpe3ZhciBkPXlbZl07ZC50cmltKCk7dmFyIG09ZC5nZXRNYXhTY2FsZSgpO2lmKGQubGVuZ3RoKCkpe2Zvcih2YXIgdj1jLmxlbmd0aCxnPTA7ZzxkLmxlbmd0aCgpO2crKyl7dmFyIHg9ZC5nZXRTZWN0aW9uKGcpLGI9ZC5nZXRDaGFyQ29kZShnKSxfPTI0KihtLXguc2NhbGUpLHc9ZVt4LmZvbnRTdGFja10sQT13JiZ3W2JdO0EmJihGbihiKSYmbyE9PXVsLmhvcml6b250YWw/KGMucHVzaCh7Z2x5cGg6Yix4OnUseTpfLHZlcnRpY2FsOiEwLHNjYWxlOnguc2NhbGUsZm9udFN0YWNrOnguZm9udFN0YWNrfSksdSs9c2wqeC5zY2FsZStzKTooYy5wdXNoKHtnbHlwaDpiLHg6dSx5OmwrXyx2ZXJ0aWNhbDohMSxzY2FsZTp4LnNjYWxlLGZvbnRTdGFjazp4LmZvbnRTdGFja30pLHUrPUEubWV0cmljcy5hZHZhbmNlKnguc2NhbGUrcykpO31pZihjLmxlbmd0aCE9PXYpe3ZhciBTPXUtcztwPU1hdGgubWF4KFMscCksZ2woYyxlLHYsYy5sZW5ndGgtMSxoKTt9dT0wLGwrPW4qbTt9ZWxzZSBsKz1uO312YXIgaz12bChpKSx6PWsuaG9yaXpvbnRhbEFsaWduLEk9ay52ZXJ0aWNhbEFsaWduOyFmdW5jdGlvbih0LGUscixuLGksYSxvKXtmb3IodmFyIHM9KGUtcikqaSx1PSgtbipvKy41KSphLGw9MDtsPHQubGVuZ3RoO2wrKyl0W2xdLngrPXMsdFtsXS55Kz11O30oYyxoLHosSSxwLG4sci5sZW5ndGgpO3ZhciBCPWwtIC0xNzt0LnRvcCs9LUkqQix0LmJvdHRvbT10LnRvcCtCLHQubGVmdCs9LXoqcCx0LnJpZ2h0PXQubGVmdCtwO30oUyxlLHAsaSxhLG8sbCxzKSwhIUEubGVuZ3RoJiZTfWxsLmZyb21GZWF0dXJlPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPW5ldyBsbCxuPTA7bjx0LnNlY3Rpb25zLmxlbmd0aDtuKyspe3ZhciBpPXQuc2VjdGlvbnNbbl07ci5zZWN0aW9ucy5wdXNoKHtzY2FsZTppLnNjYWxlfHwxLGZvbnRTdGFjazppLmZvbnRTdGFja3x8ZX0pLHIudGV4dCs9aS50ZXh0O2Zvcih2YXIgYT0wO2E8aS50ZXh0Lmxlbmd0aDthKyspci5zZWN0aW9uSW5kZXgucHVzaChuKTt9cmV0dXJuIHJ9LGxsLnByb3RvdHlwZS5sZW5ndGg9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50ZXh0Lmxlbmd0aH0sbGwucHJvdG90eXBlLmdldFNlY3Rpb249ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuc2VjdGlvbnNbdGhpcy5zZWN0aW9uSW5kZXhbdF1dfSxsbC5wcm90b3R5cGUuZ2V0Q2hhckNvZGU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMudGV4dC5jaGFyQ29kZUF0KHQpfSxsbC5wcm90b3R5cGUudmVydGljYWxpemVQdW5jdHVhdGlvbj1mdW5jdGlvbigpe3RoaXMudGV4dD1mdW5jdGlvbih0KXtmb3IodmFyIGU9XCJcIixyPTA7cjx0Lmxlbmd0aDtyKyspe3ZhciBuPXQuY2hhckNvZGVBdChyKzEpfHxudWxsLGk9dC5jaGFyQ29kZUF0KHItMSl8fG51bGw7biYmTG4obikmJiFGc1t0W3IrMV1dfHxpJiZMbihpKSYmIUZzW3Rbci0xXV18fCFGc1t0W3JdXT9lKz10W3JdOmUrPUZzW3Rbcl1dO31yZXR1cm4gZX0odGhpcy50ZXh0KTt9LGxsLnByb3RvdHlwZS50cmltPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PTAsZT0wO2U8dGhpcy50ZXh0Lmxlbmd0aCYmY2xbdGhpcy50ZXh0LmNoYXJDb2RlQXQoZSldO2UrKyl0Kys7Zm9yKHZhciByPXRoaXMudGV4dC5sZW5ndGgsbj10aGlzLnRleHQubGVuZ3RoLTE7bj49MCYmbj49dCYmY2xbdGhpcy50ZXh0LmNoYXJDb2RlQXQobildO24tLSlyLS07dGhpcy50ZXh0PXRoaXMudGV4dC5zdWJzdHJpbmcodCxyKSx0aGlzLnNlY3Rpb25JbmRleD10aGlzLnNlY3Rpb25JbmRleC5zbGljZSh0LHIpO30sbGwucHJvdG90eXBlLnN1YnN0cmluZz1mdW5jdGlvbih0LGUpe3ZhciByPW5ldyBsbDtyZXR1cm4gci50ZXh0PXRoaXMudGV4dC5zdWJzdHJpbmcodCxlKSxyLnNlY3Rpb25JbmRleD10aGlzLnNlY3Rpb25JbmRleC5zbGljZSh0LGUpLHIuc2VjdGlvbnM9dGhpcy5zZWN0aW9ucyxyfSxsbC5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50ZXh0fSxsbC5wcm90b3R5cGUuZ2V0TWF4U2NhbGU9ZnVuY3Rpb24oKXt2YXIgdD10aGlzO3JldHVybiB0aGlzLnNlY3Rpb25JbmRleC5yZWR1Y2UoZnVuY3Rpb24oZSxyKXtyZXR1cm4gTWF0aC5tYXgoZSx0LnNlY3Rpb25zW3JdLnNjYWxlKX0sMCl9O3ZhciBjbD17OTohMCwxMDohMCwxMTohMCwxMjohMCwxMzohMCwzMjohMH0saGw9e307ZnVuY3Rpb24gZmwodCxlLHIsbil7dmFyIGk9TWF0aC5wb3codC1lLDIpO3JldHVybiBuP3Q8ZT9pLzI6MippOmkrTWF0aC5hYnMocikqcn1mdW5jdGlvbiB5bCh0LGUscil7dmFyIG49MDtyZXR1cm4gMTA9PT10JiYobi09MWU0KSxyJiYobis9MTUwKSw0MCE9PXQmJjY1Mjg4IT09dHx8KG4rPTUwKSw0MSE9PWUmJjY1Mjg5IT09ZXx8KG4rPTUwKSxufWZ1bmN0aW9uIGRsKHQsZSxyLG4saSxhKXtmb3IodmFyIG89bnVsbCxzPWZsKGUscixpLGEpLHU9MCxsPW47dTxsLmxlbmd0aDt1Kz0xKXt2YXIgcD1sW3VdLGM9ZmwoZS1wLngscixpLGEpK3AuYmFkbmVzcztjPD1zJiYobz1wLHM9Yyk7fXJldHVybiB7aW5kZXg6dCx4OmUscHJpb3JCcmVhazpvLGJhZG5lc3M6c319ZnVuY3Rpb24gbWwodCxlLHIsbil7aWYoIXIpcmV0dXJuIFtdO2lmKCF0KXJldHVybiBbXTtmb3IodmFyIGksYT1bXSxvPWZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgaT0wLGE9MDthPHQubGVuZ3RoKCk7YSsrKXt2YXIgbz10LmdldFNlY3Rpb24oYSkscz1uW28uZm9udFN0YWNrXSx1PXMmJnNbdC5nZXRDaGFyQ29kZShhKV07dSYmKGkrPXUubWV0cmljcy5hZHZhbmNlKm8uc2NhbGUrZSk7fXJldHVybiBpL01hdGgubWF4KDEsTWF0aC5jZWlsKGkvcikpfSh0LGUscixuKSxzPXQudGV4dC5pbmRleE9mKFwi4oCLXCIpPj0wLHU9MCxsPTA7bDx0Lmxlbmd0aCgpO2wrKyl7dmFyIHA9dC5nZXRTZWN0aW9uKGwpLGM9dC5nZXRDaGFyQ29kZShsKSxoPW5bcC5mb250U3RhY2tdLGY9aCYmaFtjXTtpZihmJiYhY2xbY10mJih1Kz1mLm1ldHJpY3MuYWR2YW5jZSpwLnNjYWxlK2UpLGw8dC5sZW5ndGgoKS0xKXt2YXIgeT0hISghKChpPWMpPDExOTA0KSYmKE1uW1wiQm9wb21vZm8gRXh0ZW5kZWRcIl0oaSl8fE1uLkJvcG9tb2ZvKGkpfHxNbltcIkNKSyBDb21wYXRpYmlsaXR5IEZvcm1zXCJdKGkpfHxNbltcIkNKSyBDb21wYXRpYmlsaXR5IElkZW9ncmFwaHNcIl0oaSl8fE1uW1wiQ0pLIENvbXBhdGliaWxpdHlcIl0oaSl8fE1uW1wiQ0pLIFJhZGljYWxzIFN1cHBsZW1lbnRcIl0oaSl8fE1uW1wiQ0pLIFN0cm9rZXNcIl0oaSl8fE1uW1wiQ0pLIFN5bWJvbHMgYW5kIFB1bmN0dWF0aW9uXCJdKGkpfHxNbltcIkNKSyBVbmlmaWVkIElkZW9ncmFwaHMgRXh0ZW5zaW9uIEFcIl0oaSl8fE1uW1wiQ0pLIFVuaWZpZWQgSWRlb2dyYXBoc1wiXShpKXx8TW5bXCJFbmNsb3NlZCBDSksgTGV0dGVycyBhbmQgTW9udGhzXCJdKGkpfHxNbltcIkhhbGZ3aWR0aCBhbmQgRnVsbHdpZHRoIEZvcm1zXCJdKGkpfHxNbi5IaXJhZ2FuYShpKXx8TW5bXCJJZGVvZ3JhcGhpYyBEZXNjcmlwdGlvbiBDaGFyYWN0ZXJzXCJdKGkpfHxNbltcIkthbmd4aSBSYWRpY2Fsc1wiXShpKXx8TW5bXCJLYXRha2FuYSBQaG9uZXRpYyBFeHRlbnNpb25zXCJdKGkpfHxNbi5LYXRha2FuYShpKXx8TW5bXCJWZXJ0aWNhbCBGb3Jtc1wiXShpKXx8TW5bXCJZaSBSYWRpY2Fsc1wiXShpKXx8TW5bXCJZaSBTeWxsYWJsZXNcIl0oaSkpKTsoaGxbY118fHkpJiZhLnB1c2goZGwobCsxLHUsbyxhLHlsKGMsdC5nZXRDaGFyQ29kZShsKzEpLHkmJnMpLCExKSk7fX1yZXR1cm4gZnVuY3Rpb24gdChlKXtyZXR1cm4gZT90KGUucHJpb3JCcmVhaykuY29uY2F0KGUuaW5kZXgpOltdfShkbCh0Lmxlbmd0aCgpLHUsbyxhLDAsITApKX1mdW5jdGlvbiB2bCh0KXt2YXIgZT0uNSxyPS41O3N3aXRjaCh0KXtjYXNlXCJyaWdodFwiOmNhc2VcInRvcC1yaWdodFwiOmNhc2VcImJvdHRvbS1yaWdodFwiOmU9MTticmVhaztjYXNlXCJsZWZ0XCI6Y2FzZVwidG9wLWxlZnRcIjpjYXNlXCJib3R0b20tbGVmdFwiOmU9MDt9c3dpdGNoKHQpe2Nhc2VcImJvdHRvbVwiOmNhc2VcImJvdHRvbS1yaWdodFwiOmNhc2VcImJvdHRvbS1sZWZ0XCI6cj0xO2JyZWFrO2Nhc2VcInRvcFwiOmNhc2VcInRvcC1yaWdodFwiOmNhc2VcInRvcC1sZWZ0XCI6cj0wO31yZXR1cm4ge2hvcml6b250YWxBbGlnbjplLHZlcnRpY2FsQWxpZ246cn19ZnVuY3Rpb24gZ2wodCxlLHIsbixpKXtpZihpKXt2YXIgYT10W25dLG89ZVthLmZvbnRTdGFja10scz1vJiZvW2EuZ2x5cGhdO2lmKHMpZm9yKHZhciB1PXMubWV0cmljcy5hZHZhbmNlKmEuc2NhbGUsbD0odFtuXS54K3UpKmkscD1yO3A8PW47cCsrKXRbcF0ueC09bDt9fWZ1bmN0aW9uIHhsKHQsZSxyKXt2YXIgbj12bChyKSxpPW4uaG9yaXpvbnRhbEFsaWduLGE9bi52ZXJ0aWNhbEFsaWduLG89ZVswXSxzPWVbMV0sdT1vLXQuZGlzcGxheVNpemVbMF0qaSxsPXUrdC5kaXNwbGF5U2l6ZVswXSxwPXMtdC5kaXNwbGF5U2l6ZVsxXSphO3JldHVybiB7aW1hZ2U6dCx0b3A6cCxib3R0b206cCt0LmRpc3BsYXlTaXplWzFdLGxlZnQ6dSxyaWdodDpsfX1mdW5jdGlvbiBibCh0LGUscixuLGkpe2lmKHZvaWQgMD09PWUuc2VnbWVudClyZXR1cm4gITA7Zm9yKHZhciBhPWUsbz1lLnNlZ21lbnQrMSxzPTA7cz4tci8yOyl7aWYoLS1vPDApcmV0dXJuICExO3MtPXRbb10uZGlzdChhKSxhPXRbb107fXMrPXRbb10uZGlzdCh0W28rMV0pLG8rKztmb3IodmFyIHU9W10sbD0wO3M8ci8yOyl7dmFyIHA9dFtvLTFdLGM9dFtvXSxoPXRbbysxXTtpZighaClyZXR1cm4gITE7dmFyIGY9cC5hbmdsZVRvKGMpLWMuYW5nbGVUbyhoKTtmb3IoZj1NYXRoLmFicygoZiszKk1hdGguUEkpJSgyKk1hdGguUEkpLU1hdGguUEkpLHUucHVzaCh7ZGlzdGFuY2U6cyxhbmdsZURlbHRhOmZ9KSxsKz1mO3MtdVswXS5kaXN0YW5jZT5uOylsLT11LnNoaWZ0KCkuYW5nbGVEZWx0YTtpZihsPmkpcmV0dXJuICExO28rKyxzKz1jLmRpc3QoaCk7fXJldHVybiAhMH1mdW5jdGlvbiBfbCh0KXtmb3IodmFyIGU9MCxyPTA7cjx0Lmxlbmd0aC0xO3IrKyllKz10W3JdLmRpc3QodFtyKzFdKTtyZXR1cm4gZX1mdW5jdGlvbiB3bCh0LGUscil7cmV0dXJuIHQ/LjYqZSpyOjB9ZnVuY3Rpb24gQWwodCxlKXtyZXR1cm4gTWF0aC5tYXgodD90LnJpZ2h0LXQubGVmdDowLGU/ZS5yaWdodC1lLmxlZnQ6MCl9ZnVuY3Rpb24gU2wodCxlLHIsbixpLGEpe2Zvcih2YXIgbz13bChyLGksYSkscz1BbChyLG4pKmEsdT0wLGw9X2wodCkvMixwPTA7cDx0Lmxlbmd0aC0xO3ArKyl7dmFyIGM9dFtwXSxoPXRbcCsxXSxmPWMuZGlzdChoKTtpZih1K2Y+bCl7dmFyIHk9KGwtdSkvZixkPUVlKGMueCxoLngseSksbT1FZShjLnksaC55LHkpLHY9bmV3IExzKGQsbSxoLmFuZ2xlVG8oYykscCk7cmV0dXJuIHYuX3JvdW5kKCksIW98fGJsKHQsdixzLG8sZSk/djp2b2lkIDB9dSs9Zjt9fWZ1bmN0aW9uIGtsKHQsZSxyLG4saSxhLG8scyx1KXt2YXIgbD13bChuLGEsbykscD1BbChuLGkpLGM9cCpvLGg9MD09PXRbMF0ueHx8dFswXS54PT09dXx8MD09PXRbMF0ueXx8dFswXS55PT09dTtyZXR1cm4gZS1jPGUvNCYmKGU9YytlLzQpLGZ1bmN0aW9uIHQoZSxyLG4saSxhLG8scyx1LGwpe3ZhciBwPW8vMjt2YXIgYz1fbChlKTt2YXIgaD0wLGY9ci1uO3ZhciB5PVtdO2Zvcih2YXIgZD0wO2Q8ZS5sZW5ndGgtMTtkKyspe2Zvcih2YXIgbT1lW2RdLHY9ZVtkKzFdLGc9bS5kaXN0KHYpLHg9di5hbmdsZVRvKG0pO2YrbjxoK2c7KXt2YXIgYj0oKGYrPW4pLWgpL2csXz1FZShtLngsdi54LGIpLHc9RWUobS55LHYueSxiKTtpZihfPj0wJiZfPGwmJnc+PTAmJnc8bCYmZi1wPj0wJiZmK3A8PWMpe3ZhciBBPW5ldyBMcyhfLHcseCxkKTtBLl9yb3VuZCgpLGkmJiFibChlLEEsbyxpLGEpfHx5LnB1c2goQSk7fX1oKz1nO311fHx5Lmxlbmd0aHx8c3x8KHk9dChlLGgvMixuLGksYSxvLHMsITAsbCkpO3JldHVybiB5fSh0LGg/ZS8yKnMlZToocC8yKzIqYSkqbypzJWUsZSxsLHIsYyxoLCExLHUpfWhsWzEwXT0hMCxobFszMl09ITAsaGxbMzhdPSEwLGhsWzQwXT0hMCxobFs0MV09ITAsaGxbNDNdPSEwLGhsWzQ1XT0hMCxobFs0N109ITAsaGxbMTczXT0hMCxobFsxODNdPSEwLGhsWzgyMDNdPSEwLGhsWzgyMDhdPSEwLGhsWzgyMTFdPSEwLGhsWzgyMzFdPSEwO3ZhciB6bD1mdW5jdGlvbih0LGUscixuLGEsbyxzLHUsbCxwLGMsaCl7dmFyIGY9cy50b3AqdS1sLHk9cy5ib3R0b20qdStsLGQ9cy5sZWZ0KnUtbCxtPXMucmlnaHQqdStsO2lmKHRoaXMuYm94U3RhcnRJbmRleD10Lmxlbmd0aCxwKXt2YXIgdj15LWYsZz1tLWQ7dj4wJiYodj1NYXRoLm1heCgxMCp1LHYpLHRoaXMuX2FkZExpbmVDb2xsaXNpb25DaXJjbGVzKHQsZSxyLHIuc2VnbWVudCxnLHYsbixhLG8sYykpO31lbHNle2lmKGgpe3ZhciB4PW5ldyBpKGQsZiksYj1uZXcgaShtLGYpLF89bmV3IGkoZCx5KSx3PW5ldyBpKG0seSksQT1oKk1hdGguUEkvMTgwO3guX3JvdGF0ZShBKSxiLl9yb3RhdGUoQSksXy5fcm90YXRlKEEpLHcuX3JvdGF0ZShBKSxkPU1hdGgubWluKHgueCxiLngsXy54LHcueCksbT1NYXRoLm1heCh4LngsYi54LF8ueCx3LngpLGY9TWF0aC5taW4oeC55LGIueSxfLnksdy55KSx5PU1hdGgubWF4KHgueSxiLnksXy55LHcueSk7fXQuZW1wbGFjZUJhY2soci54LHIueSxkLGYsbSx5LG4sYSxvLDAsMCk7fXRoaXMuYm94RW5kSW5kZXg9dC5sZW5ndGg7fTt6bC5wcm90b3R5cGUuX2FkZExpbmVDb2xsaXNpb25DaXJjbGVzPWZ1bmN0aW9uKHQsZSxyLG4saSxhLG8scyx1LGwpe3ZhciBwPWEvMixjPU1hdGguZmxvb3IoaS9wKXx8MSxoPTErLjQqTWF0aC5sb2cobCkvTWF0aC5MTjIsZj1NYXRoLmZsb29yKGMqaC8yKSx5PS1hLzIsZD1yLG09bisxLHY9eSxnPS1pLzIseD1nLWkvNDtkb3tpZigtLW08MCl7aWYodj5nKXJldHVybjttPTA7YnJlYWt9di09ZVttXS5kaXN0KGQpLGQ9ZVttXTt9d2hpbGUodj54KTtmb3IodmFyIGI9ZVttXS5kaXN0KGVbbSsxXSksXz0tZjtfPGMrZjtfKyspe3ZhciB3PV8qcCxBPWcrdztpZih3PDAmJihBKz13KSx3PmkmJihBKz13LWkpLCEoQTx2KSl7Zm9yKDt2K2I8QTspe2lmKHYrPWIsKyttKzE+PWUubGVuZ3RoKXJldHVybjtiPWVbbV0uZGlzdChlW20rMV0pO312YXIgUz1BLXYsaz1lW21dLHo9ZVttKzFdLnN1YihrKS5fdW5pdCgpLl9tdWx0KFMpLl9hZGQoaykuX3JvdW5kKCksST1NYXRoLmFicyhBLXkpPHA/MDouOCooQS15KTt0LmVtcGxhY2VCYWNrKHoueCx6LnksLWEvMiwtYS8yLGEvMixhLzIsbyxzLHUsYS8yLEkpO319fTt2YXIgSWw9ZnVuY3Rpb24odCxlKXtpZih2b2lkIDA9PT10JiYodD1bXSksdm9pZCAwPT09ZSYmKGU9QmwpLHRoaXMuZGF0YT10LHRoaXMubGVuZ3RoPXRoaXMuZGF0YS5sZW5ndGgsdGhpcy5jb21wYXJlPWUsdGhpcy5sZW5ndGg+MClmb3IodmFyIHI9KHRoaXMubGVuZ3RoPj4xKS0xO3I+PTA7ci0tKXRoaXMuX2Rvd24ocik7fTtmdW5jdGlvbiBCbCh0LGUpe3JldHVybiB0PGU/LTE6dD5lPzE6MH1mdW5jdGlvbiBDbCh0LGUscil7dm9pZCAwPT09ZSYmKGU9MSksdm9pZCAwPT09ciYmKHI9ITEpO2Zvcih2YXIgbj0xLzAsYT0xLzAsbz0tMS8wLHM9LTEvMCx1PXRbMF0sbD0wO2w8dS5sZW5ndGg7bCsrKXt2YXIgcD11W2xdOyghbHx8cC54PG4pJiYobj1wLngpLCghbHx8cC55PGEpJiYoYT1wLnkpLCghbHx8cC54Pm8pJiYobz1wLngpLCghbHx8cC55PnMpJiYocz1wLnkpO312YXIgYz1vLW4saD1zLWEsZj1NYXRoLm1pbihjLGgpLHk9Zi8yLGQ9bmV3IElsKFtdLEVsKTtpZigwPT09ZilyZXR1cm4gbmV3IGkobixhKTtmb3IodmFyIG09bjttPG87bSs9Zilmb3IodmFyIHY9YTt2PHM7dis9ZilkLnB1c2gobmV3IE1sKG0reSx2K3kseSx0KSk7Zm9yKHZhciBnPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT0wLHI9MCxuPTAsaT10WzBdLGE9MCxvPWkubGVuZ3RoLHM9by0xO2E8bztzPWErKyl7dmFyIHU9aVthXSxsPWlbc10scD11LngqbC55LWwueCp1Lnk7cis9KHUueCtsLngpKnAsbis9KHUueStsLnkpKnAsZSs9MypwO31yZXR1cm4gbmV3IE1sKHIvZSxuL2UsMCx0KX0odCkseD1kLmxlbmd0aDtkLmxlbmd0aDspe3ZhciBiPWQucG9wKCk7KGIuZD5nLmR8fCFnLmQpJiYoZz1iLHImJmNvbnNvbGUubG9nKFwiZm91bmQgYmVzdCAlZCBhZnRlciAlZCBwcm9iZXNcIixNYXRoLnJvdW5kKDFlNCpiLmQpLzFlNCx4KSksYi5tYXgtZy5kPD1lfHwoeT1iLmgvMixkLnB1c2gobmV3IE1sKGIucC54LXksYi5wLnkteSx5LHQpKSxkLnB1c2gobmV3IE1sKGIucC54K3ksYi5wLnkteSx5LHQpKSxkLnB1c2gobmV3IE1sKGIucC54LXksYi5wLnkreSx5LHQpKSxkLnB1c2gobmV3IE1sKGIucC54K3ksYi5wLnkreSx5LHQpKSx4Kz00KTt9cmV0dXJuIHImJihjb25zb2xlLmxvZyhcIm51bSBwcm9iZXM6IFwiK3gpLGNvbnNvbGUubG9nKFwiYmVzdCBkaXN0YW5jZTogXCIrZy5kKSksZy5wfWZ1bmN0aW9uIEVsKHQsZSl7cmV0dXJuIGUubWF4LXQubWF4fWZ1bmN0aW9uIE1sKHQsZSxyLG4pe3RoaXMucD1uZXcgaSh0LGUpLHRoaXMuaD1yLHRoaXMuZD1mdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0hMSxuPTEvMCxpPTA7aTxlLmxlbmd0aDtpKyspZm9yKHZhciBhPWVbaV0sbz0wLHM9YS5sZW5ndGgsdT1zLTE7bzxzO3U9bysrKXt2YXIgbD1hW29dLHA9YVt1XTtsLnk+dC55IT1wLnk+dC55JiZ0Lng8KHAueC1sLngpKih0LnktbC55KS8ocC55LWwueSkrbC54JiYocj0hciksbj1NYXRoLm1pbihuLElhKHQsbCxwKSk7fXJldHVybiAocj8xOi0xKSpNYXRoLnNxcnQobil9KHRoaXMucCxuKSx0aGlzLm1heD10aGlzLmQrdGhpcy5oKk1hdGguU1FSVDI7fUlsLnByb3RvdHlwZS5wdXNoPWZ1bmN0aW9uKHQpe3RoaXMuZGF0YS5wdXNoKHQpLHRoaXMubGVuZ3RoKyssdGhpcy5fdXAodGhpcy5sZW5ndGgtMSk7fSxJbC5wcm90b3R5cGUucG9wPWZ1bmN0aW9uKCl7aWYoMCE9PXRoaXMubGVuZ3RoKXt2YXIgdD10aGlzLmRhdGFbMF07cmV0dXJuIHRoaXMubGVuZ3RoLS0sdGhpcy5sZW5ndGg+MCYmKHRoaXMuZGF0YVswXT10aGlzLmRhdGFbdGhpcy5sZW5ndGhdLHRoaXMuX2Rvd24oMCkpLHRoaXMuZGF0YS5wb3AoKSx0fX0sSWwucHJvdG90eXBlLnBlZWs9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kYXRhWzBdfSxJbC5wcm90b3R5cGUuX3VwPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT10aGlzLmRhdGEscj10aGlzLmNvbXBhcmUsbj1lW3RdO3Q+MDspe3ZhciBpPXQtMT4+MSxhPWVbaV07aWYocihuLGEpPj0wKWJyZWFrO2VbdF09YSx0PWk7fWVbdF09bjt9LElsLnByb3RvdHlwZS5fZG93bj1mdW5jdGlvbih0KXtmb3IodmFyIGU9dGhpcy5kYXRhLHI9dGhpcy5jb21wYXJlLG49dGhpcy5sZW5ndGg+PjEsaT1lW3RdO3Q8bjspe3ZhciBhPTErKHQ8PDEpLG89ZVthXSxzPWErMTtpZihzPHRoaXMubGVuZ3RoJiZyKGVbc10sbyk8MCYmKGE9cyxvPWVbc10pLHIobyxpKT49MClicmVhaztlW3RdPW8sdD1hO31lW3RdPWk7fTt2YXIgVGw9ZShmdW5jdGlvbih0KXt0LmV4cG9ydHM9ZnVuY3Rpb24odCxlKXt2YXIgcixuLGksYSxvLHMsdSxsO2ZvcihyPTMmdC5sZW5ndGgsbj10Lmxlbmd0aC1yLGk9ZSxvPTM0MzI5MTgzNTMscz00NjE4NDU5MDcsbD0wO2w8bjspdT0yNTUmdC5jaGFyQ29kZUF0KGwpfCgyNTUmdC5jaGFyQ29kZUF0KCsrbCkpPDw4fCgyNTUmdC5jaGFyQ29kZUF0KCsrbCkpPDwxNnwoMjU1JnQuY2hhckNvZGVBdCgrK2wpKTw8MjQsKytsLGk9Mjc0OTIrKDY1NTM1JihhPTUqKDY1NTM1JihpPShpXj11PSg2NTUzNSYodT0odT0oNjU1MzUmdSkqbysoKCh1Pj4+MTYpKm8mNjU1MzUpPDwxNikmNDI5NDk2NzI5NSk8PDE1fHU+Pj4xNykpKnMrKCgodT4+PjE2KSpzJjY1NTM1KTw8MTYpJjQyOTQ5NjcyOTUpPDwxM3xpPj4+MTkpKSsoKDUqKGk+Pj4xNikmNjU1MzUpPDwxNikmNDI5NDk2NzI5NSkpKygoNTg5NjQrKGE+Pj4xNikmNjU1MzUpPDwxNik7c3dpdGNoKHU9MCxyKXtjYXNlIDM6dV49KDI1NSZ0LmNoYXJDb2RlQXQobCsyKSk8PDE2O2Nhc2UgMjp1Xj0oMjU1JnQuY2hhckNvZGVBdChsKzEpKTw8ODtjYXNlIDE6aV49dT0oNjU1MzUmKHU9KHU9KDY1NTM1Jih1Xj0yNTUmdC5jaGFyQ29kZUF0KGwpKSkqbysoKCh1Pj4+MTYpKm8mNjU1MzUpPDwxNikmNDI5NDk2NzI5NSk8PDE1fHU+Pj4xNykpKnMrKCgodT4+PjE2KSpzJjY1NTM1KTw8MTYpJjQyOTQ5NjcyOTU7fXJldHVybiBpXj10Lmxlbmd0aCxpPTIyNDY4MjI1MDcqKDY1NTM1JihpXj1pPj4+MTYpKSsoKDIyNDY4MjI1MDcqKGk+Pj4xNikmNjU1MzUpPDwxNikmNDI5NDk2NzI5NSxpPTMyNjY0ODk5MDkqKDY1NTM1JihpXj1pPj4+MTMpKSsoKDMyNjY0ODk5MDkqKGk+Pj4xNikmNjU1MzUpPDwxNikmNDI5NDk2NzI5NSwoaV49aT4+PjE2KT4+PjB9O30pLFBsPWUoZnVuY3Rpb24odCl7dC5leHBvcnRzPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByLG49dC5sZW5ndGgsaT1lXm4sYT0wO24+PTQ7KXI9MTU0MDQ4MzQ3NyooNjU1MzUmKHI9MjU1JnQuY2hhckNvZGVBdChhKXwoMjU1JnQuY2hhckNvZGVBdCgrK2EpKTw8OHwoMjU1JnQuY2hhckNvZGVBdCgrK2EpKTw8MTZ8KDI1NSZ0LmNoYXJDb2RlQXQoKythKSk8PDI0KSkrKCgxNTQwNDgzNDc3KihyPj4+MTYpJjY1NTM1KTw8MTYpLGk9MTU0MDQ4MzQ3NyooNjU1MzUmaSkrKCgxNTQwNDgzNDc3KihpPj4+MTYpJjY1NTM1KTw8MTYpXihyPTE1NDA0ODM0NzcqKDY1NTM1JihyXj1yPj4+MjQpKSsoKDE1NDA0ODM0NzcqKHI+Pj4xNikmNjU1MzUpPDwxNikpLG4tPTQsKythO3N3aXRjaChuKXtjYXNlIDM6aV49KDI1NSZ0LmNoYXJDb2RlQXQoYSsyKSk8PDE2O2Nhc2UgMjppXj0oMjU1JnQuY2hhckNvZGVBdChhKzEpKTw8ODtjYXNlIDE6aT0xNTQwNDgzNDc3Kig2NTUzNSYoaV49MjU1JnQuY2hhckNvZGVBdChhKSkpKygoMTU0MDQ4MzQ3NyooaT4+PjE2KSY2NTUzNSk8PDE2KTt9cmV0dXJuIGk9MTU0MDQ4MzQ3NyooNjU1MzUmKGlePWk+Pj4xMykpKygoMTU0MDQ4MzQ3NyooaT4+PjE2KSY2NTUzNSk8PDE2KSwoaV49aT4+PjE1KT4+PjB9O30pLFZsPVRsLEZsPVRsLExsPVBsO1ZsLm11cm11cjM9RmwsVmwubXVybXVyMj1MbDt2YXIgRGw9NztmdW5jdGlvbiBPbCh0LGUpe3ZhciByPTAsbj0wLGk9ZS9NYXRoLnNxcnQoMik7c3dpdGNoKHQpe2Nhc2VcInRvcC1yaWdodFwiOmNhc2VcInRvcC1sZWZ0XCI6bj1pLURsO2JyZWFrO2Nhc2VcImJvdHRvbS1yaWdodFwiOmNhc2VcImJvdHRvbS1sZWZ0XCI6bj0taStEbDticmVhaztjYXNlXCJib3R0b21cIjpuPS1lK0RsO2JyZWFrO2Nhc2VcInRvcFwiOm49ZS1EbDt9c3dpdGNoKHQpe2Nhc2VcInRvcC1yaWdodFwiOmNhc2VcImJvdHRvbS1yaWdodFwiOnI9LWk7YnJlYWs7Y2FzZVwidG9wLWxlZnRcIjpjYXNlXCJib3R0b20tbGVmdFwiOnI9aTticmVhaztjYXNlXCJsZWZ0XCI6cj1lO2JyZWFrO2Nhc2VcInJpZ2h0XCI6cj0tZTt9cmV0dXJuIFtyLG5dfWZ1bmN0aW9uIFJsKHQpe3N3aXRjaCh0KXtjYXNlXCJyaWdodFwiOmNhc2VcInRvcC1yaWdodFwiOmNhc2VcImJvdHRvbS1yaWdodFwiOnJldHVybiBcInJpZ2h0XCI7Y2FzZVwibGVmdFwiOmNhc2VcInRvcC1sZWZ0XCI6Y2FzZVwiYm90dG9tLWxlZnRcIjpyZXR1cm4gXCJsZWZ0XCJ9cmV0dXJuIFwiY2VudGVyXCJ9ZnVuY3Rpb24gVWwodCxlLHIsbixhLG8scyl7dmFyIHU9by5sYXlvdXRUZXh0U2l6ZS5ldmFsdWF0ZShlLHt9KSxsPW8ubGF5b3V0SWNvblNpemUuZXZhbHVhdGUoZSx7fSkscD1vLnRleHRNYXhTaXplLmV2YWx1YXRlKGUse30pO3ZvaWQgMD09PXAmJihwPXUpO3ZhciBjPXQubGF5ZXJzWzBdLmxheW91dCxoPWMuZ2V0KFwiaWNvbi1vZmZzZXRcIikuZXZhbHVhdGUoZSx7fSksZj1ObChyLmhvcml6b250YWwpLHk9dS8yNCxkPXQudGlsZVBpeGVsUmF0aW8qeSxtPXQudGlsZVBpeGVsUmF0aW8qcC8yNCx2PXQudGlsZVBpeGVsUmF0aW8qbCxnPXQudGlsZVBpeGVsUmF0aW8qYy5nZXQoXCJzeW1ib2wtc3BhY2luZ1wiKSx4PWMuZ2V0KFwidGV4dC1wYWRkaW5nXCIpKnQudGlsZVBpeGVsUmF0aW8sYj1jLmdldChcImljb24tcGFkZGluZ1wiKSp0LnRpbGVQaXhlbFJhdGlvLF89Yy5nZXQoXCJ0ZXh0LW1heC1hbmdsZVwiKS8xODAqTWF0aC5QSSxBPVwibWFwXCI9PT1jLmdldChcInRleHQtcm90YXRpb24tYWxpZ25tZW50XCIpJiZcInBvaW50XCIhPT1jLmdldChcInN5bWJvbC1wbGFjZW1lbnRcIiksUz1cIm1hcFwiPT09Yy5nZXQoXCJpY29uLXJvdGF0aW9uLWFsaWdubWVudFwiKSYmXCJwb2ludFwiIT09Yy5nZXQoXCJzeW1ib2wtcGxhY2VtZW50XCIpLGs9Yy5nZXQoXCJzeW1ib2wtcGxhY2VtZW50XCIpLHo9Zy8yLEk9ZnVuY3Rpb24odSxsKXtsLng8MHx8bC54Pj15YXx8bC55PDB8fGwueT49eWF8fGZ1bmN0aW9uKHQsZSxyLG4sYSxvLHMsdSxsLHAsYyxoLGYseSxkLG0sdixnLHgsYixfKXt2YXIgQSxTLGs9dC5hZGRUb0xpbmVWZXJ0ZXhBcnJheShlLHIpLHo9MCxJPTAsQj0wLEM9e30sRT1WbChcIlwiKSxNPShvLmxheW91dC5nZXQoXCJ0ZXh0LXJhZGlhbC1vZmZzZXRcIikuZXZhbHVhdGUoeCx7fSl8fDApKnNsO2Zvcih2YXIgVCBpbiBuLmhvcml6b250YWwpe3ZhciBQPW4uaG9yaXpvbnRhbFtUXTtpZighQSl7RT1WbChQLnRleHQpO3ZhciBWPW8ubGF5b3V0LmdldChcInRleHQtcm90YXRlXCIpLmV2YWx1YXRlKHgse30pO0E9bmV3IHpsKHMscixlLHUsbCxwLFAsYyxoLGYsdC5vdmVyc2NhbGluZyxWKTt9dmFyIEY9MT09PVAubGluZUNvdW50O2lmKEkrPXFsKHQsZSxQLG8sZix4LHksayxuLnZlcnRpY2FsP3VsLmhvcml6b250YWw6dWwuaG9yaXpvbnRhbE9ubHksRj9PYmplY3Qua2V5cyhuLmhvcml6b250YWwpOltUXSxDLGIsXyksRilicmVha31uLnZlcnRpY2FsJiYoQis9cWwodCxlLG4udmVydGljYWwsbyxmLHgseSxrLHVsLnZlcnRpY2FsLFtcInZlcnRpY2FsXCJdLEMsYixfKSk7dmFyIEw9QT9BLmJveFN0YXJ0SW5kZXg6dC5jb2xsaXNpb25Cb3hBcnJheS5sZW5ndGgsRD1BP0EuYm94RW5kSW5kZXg6dC5jb2xsaXNpb25Cb3hBcnJheS5sZW5ndGg7aWYoYSl7dmFyIE89ZnVuY3Rpb24odCxlLHIsbixhLG8pe3ZhciBzLHUsbCxwLGM9ZS5pbWFnZSxoPXIubGF5b3V0LGY9ZS50b3AtMS9jLnBpeGVsUmF0aW8seT1lLmxlZnQtMS9jLnBpeGVsUmF0aW8sZD1lLmJvdHRvbSsxL2MucGl4ZWxSYXRpbyxtPWUucmlnaHQrMS9jLnBpeGVsUmF0aW87aWYoXCJub25lXCIhPT1oLmdldChcImljb24tdGV4dC1maXRcIikmJmEpe3ZhciB2PW0teSxnPWQtZix4PWguZ2V0KFwidGV4dC1zaXplXCIpLmV2YWx1YXRlKG8se30pLzI0LGI9YS5sZWZ0KngsXz1hLnJpZ2h0Kngsdz1hLnRvcCp4LEE9Xy1iLFM9YS5ib3R0b20qeC13LGs9aC5nZXQoXCJpY29uLXRleHQtZml0LXBhZGRpbmdcIilbMF0sej1oLmdldChcImljb24tdGV4dC1maXQtcGFkZGluZ1wiKVsxXSxJPWguZ2V0KFwiaWNvbi10ZXh0LWZpdC1wYWRkaW5nXCIpWzJdLEI9aC5nZXQoXCJpY29uLXRleHQtZml0LXBhZGRpbmdcIilbM10sQz1cIndpZHRoXCI9PT1oLmdldChcImljb24tdGV4dC1maXRcIik/LjUqKFMtZyk6MCxFPVwiaGVpZ2h0XCI9PT1oLmdldChcImljb24tdGV4dC1maXRcIik/LjUqKEEtdik6MCxNPVwid2lkdGhcIj09PWguZ2V0KFwiaWNvbi10ZXh0LWZpdFwiKXx8XCJib3RoXCI9PT1oLmdldChcImljb24tdGV4dC1maXRcIik/QTp2LFQ9XCJoZWlnaHRcIj09PWguZ2V0KFwiaWNvbi10ZXh0LWZpdFwiKXx8XCJib3RoXCI9PT1oLmdldChcImljb24tdGV4dC1maXRcIik/UzpnO3M9bmV3IGkoYitFLUIsdytDLWspLHU9bmV3IGkoYitFK3orTSx3K0MtayksbD1uZXcgaShiK0UreitNLHcrQytJK1QpLHA9bmV3IGkoYitFLUIsdytDK0krVCk7fWVsc2Ugcz1uZXcgaSh5LGYpLHU9bmV3IGkobSxmKSxsPW5ldyBpKG0sZCkscD1uZXcgaSh5LGQpO3ZhciBQPXIubGF5b3V0LmdldChcImljb24tcm90YXRlXCIpLmV2YWx1YXRlKG8se30pKk1hdGguUEkvMTgwO2lmKFApe3ZhciBWPU1hdGguc2luKFApLEY9TWF0aC5jb3MoUCksTD1bRiwtVixWLEZdO3MuX21hdE11bHQoTCksdS5fbWF0TXVsdChMKSxwLl9tYXRNdWx0KEwpLGwuX21hdE11bHQoTCk7fXJldHVybiBbe3RsOnMsdHI6dSxibDpwLGJyOmwsdGV4OmMucGFkZGVkUmVjdCx3cml0aW5nTW9kZTp2b2lkIDAsZ2x5cGhPZmZzZXQ6WzAsMF19XX0oMCxhLG8sMCxObChuLmhvcml6b250YWwpLHgpLFI9by5sYXlvdXQuZ2V0KFwiaWNvbi1yb3RhdGVcIikuZXZhbHVhdGUoeCx7fSk7Uz1uZXcgemwocyxyLGUsdSxsLHAsYSxkLG0sITEsdC5vdmVyc2NhbGluZyxSKSx6PTQqTy5sZW5ndGg7dmFyIFU9dC5pY29uU2l6ZURhdGEsaj1udWxsO1wic291cmNlXCI9PT1VLmtpbmQ/KGo9W0RzKm8ubGF5b3V0LmdldChcImljb24tc2l6ZVwiKS5ldmFsdWF0ZSh4LHt9KV0pWzBdPmpsJiZ3KHQubGF5ZXJJZHNbMF0rJzogVmFsdWUgZm9yIFwiaWNvbi1zaXplXCIgaXMgPj0gMjU2LiBSZWR1Y2UgeW91ciBcImljb24tc2l6ZVwiLicpOlwiY29tcG9zaXRlXCI9PT1VLmtpbmQmJigoaj1bRHMqXy5jb21wb3NpdGVJY29uU2l6ZXNbMF0uZXZhbHVhdGUoeCx7fSksRHMqXy5jb21wb3NpdGVJY29uU2l6ZXNbMV0uZXZhbHVhdGUoeCx7fSldKVswXT5qbHx8alsxXT5qbCkmJncodC5sYXllcklkc1swXSsnOiBWYWx1ZSBmb3IgXCJpY29uLXNpemVcIiBpcyA+PSAyNTYuIFJlZHVjZSB5b3VyIFwiaWNvbi1zaXplXCIuJyksdC5hZGRTeW1ib2xzKHQuaWNvbixPLGosZyx2LHgsITEsZSxrLmxpbmVTdGFydEluZGV4LGsubGluZUxlbmd0aCk7fXZhciBxPVM/Uy5ib3hTdGFydEluZGV4OnQuY29sbGlzaW9uQm94QXJyYXkubGVuZ3RoLE49Uz9TLmJveEVuZEluZGV4OnQuY29sbGlzaW9uQm94QXJyYXkubGVuZ3RoO3QuZ2x5cGhPZmZzZXRBcnJheS5sZW5ndGg+PUpzLk1BWF9HTFlQSFMmJncoXCJUb28gbWFueSBnbHlwaHMgYmVpbmcgcmVuZGVyZWQgaW4gYSB0aWxlLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL21hcGJveC9tYXBib3gtZ2wtanMvaXNzdWVzLzI5MDdcIik7dC5zeW1ib2xJbnN0YW5jZXMuZW1wbGFjZUJhY2soZS54LGUueSxDLnJpZ2h0Pj0wP0MucmlnaHQ6LTEsQy5jZW50ZXI+PTA/Qy5jZW50ZXI6LTEsQy5sZWZ0Pj0wP0MubGVmdDotMSxDLnZlcnRpY2FsfHwtMSxFLEwsRCxxLE4sdSxJLEIseiwwLGMsTSk7fSh0LGwsdSxyLG4sdC5sYXllcnNbMF0sdC5jb2xsaXNpb25Cb3hBcnJheSxlLmluZGV4LGUuc291cmNlTGF5ZXJJbmRleCx0LmluZGV4LGQseCxBLHMsdixiLFMsaCxlLGEsbyk7fTtpZihcImxpbmVcIj09PWspZm9yKHZhciBCPTAsQz1mdW5jdGlvbih0LGUscixuLGEpe2Zvcih2YXIgbz1bXSxzPTA7czx0Lmxlbmd0aDtzKyspZm9yKHZhciB1PXRbc10sbD12b2lkIDAscD0wO3A8dS5sZW5ndGgtMTtwKyspe3ZhciBjPXVbcF0saD11W3ArMV07Yy54PGUmJmgueDxlfHwoYy54PGU/Yz1uZXcgaShlLGMueSsoaC55LWMueSkqKChlLWMueCkvKGgueC1jLngpKSkuX3JvdW5kKCk6aC54PGUmJihoPW5ldyBpKGUsYy55KyhoLnktYy55KSooKGUtYy54KS8oaC54LWMueCkpKS5fcm91bmQoKSksYy55PHImJmgueTxyfHwoYy55PHI/Yz1uZXcgaShjLngrKGgueC1jLngpKigoci1jLnkpLyhoLnktYy55KSkscikuX3JvdW5kKCk6aC55PHImJihoPW5ldyBpKGMueCsoaC54LWMueCkqKChyLWMueSkvKGgueS1jLnkpKSxyKS5fcm91bmQoKSksYy54Pj1uJiZoLng+PW58fChjLng+PW4/Yz1uZXcgaShuLGMueSsoaC55LWMueSkqKChuLWMueCkvKGgueC1jLngpKSkuX3JvdW5kKCk6aC54Pj1uJiYoaD1uZXcgaShuLGMueSsoaC55LWMueSkqKChuLWMueCkvKGgueC1jLngpKSkuX3JvdW5kKCkpLGMueT49YSYmaC55Pj1hfHwoYy55Pj1hP2M9bmV3IGkoYy54KyhoLngtYy54KSooKGEtYy55KS8oaC55LWMueSkpLGEpLl9yb3VuZCgpOmgueT49YSYmKGg9bmV3IGkoYy54KyhoLngtYy54KSooKGEtYy55KS8oaC55LWMueSkpLGEpLl9yb3VuZCgpKSxsJiZjLmVxdWFscyhsW2wubGVuZ3RoLTFdKXx8KGw9W2NdLG8ucHVzaChsKSksbC5wdXNoKGgpKSkpKTt9cmV0dXJuIG99KGUuZ2VvbWV0cnksMCwwLHlhLHlhKTtCPEMubGVuZ3RoO0IrPTEpZm9yKHZhciBFPUNbQl0sTT0wLFQ9a2woRSxnLF8sci52ZXJ0aWNhbHx8ZixuLDI0LG0sdC5vdmVyc2NhbGluZyx5YSk7TTxULmxlbmd0aDtNKz0xKXt2YXIgUD1UW01dO2YmJlpsKHQsZi50ZXh0LHosUCl8fEkoRSxQKTt9ZWxzZSBpZihcImxpbmUtY2VudGVyXCI9PT1rKWZvcih2YXIgVj0wLEY9ZS5nZW9tZXRyeTtWPEYubGVuZ3RoO1YrPTEpe3ZhciBMPUZbVl07aWYoTC5sZW5ndGg+MSl7dmFyIEQ9U2woTCxfLHIudmVydGljYWx8fGYsbiwyNCxtKTtEJiZJKEwsRCk7fX1lbHNlIGlmKFwiUG9seWdvblwiPT09ZS50eXBlKWZvcih2YXIgTz0wLFI9cW8oZS5nZW9tZXRyeSwwKTtPPFIubGVuZ3RoO08rPTEpe3ZhciBVPVJbT10saj1DbChVLDE2KTtJKFVbMF0sbmV3IExzKGoueCxqLnksMCkpO31lbHNlIGlmKFwiTGluZVN0cmluZ1wiPT09ZS50eXBlKWZvcih2YXIgcT0wLE49ZS5nZW9tZXRyeTtxPE4ubGVuZ3RoO3ErPTEpe3ZhciBaPU5bcV07SShaLG5ldyBMcyhaWzBdLngsWlswXS55LDApKTt9ZWxzZSBpZihcIlBvaW50XCI9PT1lLnR5cGUpZm9yKHZhciBLPTAsRz1lLmdlb21ldHJ5O0s8Ry5sZW5ndGg7Sys9MSlmb3IodmFyIFg9MCxKPUdbS107WDxKLmxlbmd0aDtYKz0xKXt2YXIgSD1KW1hdO0koW0hdLG5ldyBMcyhILngsSC55LDApKTt9fXZhciBqbD02NTUzNTtmdW5jdGlvbiBxbCh0LGUscixuLGEsbyxzLHUsbCxwLGMsaCxmKXt2YXIgeT1mdW5jdGlvbih0LGUscixuLGEsbyxzKXtmb3IodmFyIHU9bi5sYXlvdXQuZ2V0KFwidGV4dC1yb3RhdGVcIikuZXZhbHVhdGUobyx7fSkqTWF0aC5QSS8xODAsbD1lLnBvc2l0aW9uZWRHbHlwaHMscD1bXSxjPTA7YzxsLmxlbmd0aDtjKyspe3ZhciBoPWxbY10sZj1zW2guZm9udFN0YWNrXSx5PWYmJmZbaC5nbHlwaF07aWYoeSl7dmFyIGQ9eS5yZWN0O2lmKGQpe3ZhciBtPUx1KzEsdj15Lm1ldHJpY3MuYWR2YW5jZSpoLnNjYWxlLzIsZz1hP1toLngrdixoLnldOlswLDBdLHg9YT9bMCwwXTpbaC54K3YrclswXSxoLnkrclsxXV0sYj0oeS5tZXRyaWNzLmxlZnQtbSkqaC5zY2FsZS12K3hbMF0sXz0oLXkubWV0cmljcy50b3AtbSkqaC5zY2FsZSt4WzFdLHc9YitkLncqaC5zY2FsZSxBPV8rZC5oKmguc2NhbGUsUz1uZXcgaShiLF8pLGs9bmV3IGkodyxfKSx6PW5ldyBpKGIsQSksST1uZXcgaSh3LEEpO2lmKGEmJmgudmVydGljYWwpe3ZhciBCPW5ldyBpKC12LHYpLEM9LU1hdGguUEkvMixFPW5ldyBpKDUsMCk7Uy5fcm90YXRlQXJvdW5kKEMsQikuX2FkZChFKSxrLl9yb3RhdGVBcm91bmQoQyxCKS5fYWRkKEUpLHouX3JvdGF0ZUFyb3VuZChDLEIpLl9hZGQoRSksSS5fcm90YXRlQXJvdW5kKEMsQikuX2FkZChFKTt9aWYodSl7dmFyIE09TWF0aC5zaW4odSksVD1NYXRoLmNvcyh1KSxQPVtULC1NLE0sVF07Uy5fbWF0TXVsdChQKSxrLl9tYXRNdWx0KFApLHouX21hdE11bHQoUCksSS5fbWF0TXVsdChQKTt9cC5wdXNoKHt0bDpTLHRyOmssYmw6eixicjpJLHRleDpkLHdyaXRpbmdNb2RlOmUud3JpdGluZ01vZGUsZ2x5cGhPZmZzZXQ6Z30pO319fXJldHVybiBwfSgwLHIscyxuLGEsbyxoKSxkPXQudGV4dFNpemVEYXRhLG09bnVsbDtcInNvdXJjZVwiPT09ZC5raW5kPyhtPVtEcypuLmxheW91dC5nZXQoXCJ0ZXh0LXNpemVcIikuZXZhbHVhdGUobyx7fSldKVswXT5qbCYmdyh0LmxheWVySWRzWzBdKyc6IFZhbHVlIGZvciBcInRleHQtc2l6ZVwiIGlzID49IDI1Ni4gUmVkdWNlIHlvdXIgXCJ0ZXh0LXNpemVcIi4nKTpcImNvbXBvc2l0ZVwiPT09ZC5raW5kJiYoKG09W0RzKmYuY29tcG9zaXRlVGV4dFNpemVzWzBdLmV2YWx1YXRlKG8se30pLERzKmYuY29tcG9zaXRlVGV4dFNpemVzWzFdLmV2YWx1YXRlKG8se30pXSlbMF0+amx8fG1bMV0+amwpJiZ3KHQubGF5ZXJJZHNbMF0rJzogVmFsdWUgZm9yIFwidGV4dC1zaXplXCIgaXMgPj0gMjU2LiBSZWR1Y2UgeW91ciBcInRleHQtc2l6ZVwiLicpLHQuYWRkU3ltYm9scyh0LnRleHQseSxtLHMsYSxvLGwsZSx1LmxpbmVTdGFydEluZGV4LHUubGluZUxlbmd0aCk7Zm9yKHZhciB2PTAsZz1wO3Y8Zy5sZW5ndGg7dis9MSl7Y1tnW3ZdXT10LnRleHQucGxhY2VkU3ltYm9sQXJyYXkubGVuZ3RoLTE7fXJldHVybiA0KnkubGVuZ3RofWZ1bmN0aW9uIE5sKHQpe2Zvcih2YXIgZSBpbiB0KXJldHVybiB0W2VdO3JldHVybiBudWxsfWZ1bmN0aW9uIFpsKHQsZSxyLG4pe3ZhciBpPXQuY29tcGFyZVRleHQ7aWYoZSBpbiBpKXtmb3IodmFyIGE9aVtlXSxvPWEubGVuZ3RoLTE7bz49MDtvLS0paWYobi5kaXN0KGFbb10pPHIpcmV0dXJuICEwfWVsc2UgaVtlXT1bXTtyZXR1cm4gaVtlXS5wdXNoKG4pLCExfXQuQWN0b3I9RHUsdC5BbHBoYUltYWdlPWFvLHQuQ2Fub25pY2FsVGlsZUlEPVh1LHQuQ29sbGlzaW9uQm94QXJyYXk9UGksdC5Db2xvcj1hZSx0LkRFTURhdGE9JHUsdC5EYXRhQ29uc3RhbnRQcm9wZXJ0eT1Rbix0LkRpY3Rpb25hcnlDb2Rlcj1RdSx0LkVYVEVOVD15YSx0LkVycm9yRXZlbnQ9VnQsdC5FdmFsdWF0aW9uUGFyYW1ldGVycz1abix0LkV2ZW50PVB0LHQuRXZlbnRlZD1GdCx0LkZlYXR1cmVJbmRleD1ubCx0LkZpbGxCdWNrZXQ9R28sdC5GaWxsRXh0cnVzaW9uQnVja2V0PXVzLHQuSW1hZ2VBdGxhcz1zdSx0LkltYWdlUG9zaXRpb249YXUsdC5MaW5lQnVja2V0PXdzLHQuTG5nTGF0PVV1LHQuTG5nTGF0Qm91bmRzPVJ1LHQuTWVyY2F0b3JDb29yZGluYXRlPUd1LHQuT05FX0VNPXNsLHQuT3ZlcnNjYWxlZFRpbGVJRD1IdSx0LlBvaW50PWksdC5Qb2ludCQxPWksdC5Qcm9ncmFtQ29uZmlndXJhdGlvbj1wYSx0LlByb3BlcnRpZXM9aWksdC5Qcm90b2J1Zj1kdSx0LlJHQkFJbWFnZT1vbyx0LlJlcXVlc3RNYW5hZ2VyPVUsdC5SZXNvdXJjZVR5cGU9YnQsdC5TZWdtZW50VmVjdG9yPUtpLHQuU291cmNlRmVhdHVyZVN0YXRlPXJsLHQuU3RydWN0QXJyYXlMYXlvdXQxdWkyPUNpLHQuU3RydWN0QXJyYXlMYXlvdXQyaTQ9Y2ksdC5TdHJ1Y3RBcnJheUxheW91dDJ1aTQ9QmksdC5TdHJ1Y3RBcnJheUxheW91dDN1aTY9SWksdC5TdHJ1Y3RBcnJheUxheW91dDRpOD1oaSx0LlN5bWJvbEJ1Y2tldD1Kcyx0LlRleHR1cmU9aHUsdC5UaWxlPW9sLHQuVHJhbnNpdGlvbmFibGU9WG4sdC5Vbmlmb3JtMWY9JGksdC5Vbmlmb3JtMWk9WWksdC5Vbmlmb3JtMmY9V2ksdC5Vbmlmb3JtM2Y9UWksdC5Vbmlmb3JtNGY9dGEsdC5Vbmlmb3JtQ29sb3I9ZWEsdC5Vbmlmb3JtTWF0cml4NGY9bmEsdC5VbndyYXBwZWRUaWxlSUQ9SnUsdC5WYWxpZGF0aW9uRXJyb3I9RHQsdC5Xcml0aW5nTW9kZT11bCx0Llpvb21IaXN0b3J5PUVuLHQuYWRkRHluYW1pY0F0dHJpYnV0ZXM9S3MsdC5hc3luY0FsbD1mdW5jdGlvbih0LGUscil7aWYoIXQubGVuZ3RoKXJldHVybiByKG51bGwsW10pO3ZhciBuPXQubGVuZ3RoLGk9bmV3IEFycmF5KHQubGVuZ3RoKSxhPW51bGw7dC5mb3JFYWNoKGZ1bmN0aW9uKHQsbyl7ZSh0LGZ1bmN0aW9uKHQsZSl7dCYmKGE9dCksaVtvXT1lLDA9PS0tbiYmcihhLGkpO30pO30pO30sdC5iZXppZXI9cyx0LmJpbmRBbGw9bSx0LmJyb3dzZXI9UCx0LmNhY2hlRW50cnlQb3NzaWJseUFkZGVkPWZ1bmN0aW9uKHQpeysreHQ+eXQmJih0LnNlbmQoXCJlbmZvcmNlQ2FjaGVTaXplTGltaXRcIixmdCkseHQ9MCk7fSx0LmNsYW1wPWwsdC5jbGVhclRpbGVDYWNoZT1mdW5jdGlvbih0KXt2YXIgZT1zZWxmLmNhY2hlcy5kZWxldGUoaHQpO3QmJmUuY2F0Y2godCkudGhlbihmdW5jdGlvbigpe3JldHVybiB0KCl9KTt9LHQuY2xvbmU9ZnVuY3Rpb24odCl7dmFyIGU9bmV3IExhKDE2KTtyZXR1cm4gZVswXT10WzBdLGVbMV09dFsxXSxlWzJdPXRbMl0sZVszXT10WzNdLGVbNF09dFs0XSxlWzVdPXRbNV0sZVs2XT10WzZdLGVbN109dFs3XSxlWzhdPXRbOF0sZVs5XT10WzldLGVbMTBdPXRbMTBdLGVbMTFdPXRbMTFdLGVbMTJdPXRbMTJdLGVbMTNdPXRbMTNdLGVbMTRdPXRbMTRdLGVbMTVdPXRbMTVdLGV9LHQuY2xvbmUkMT1iLHQuY29uZmlnPVYsdC5jcmVhdGU9ZnVuY3Rpb24oKXt2YXIgdD1uZXcgTGEoMTYpO3JldHVybiBMYSE9RmxvYXQzMkFycmF5JiYodFsxXT0wLHRbMl09MCx0WzNdPTAsdFs0XT0wLHRbNl09MCx0WzddPTAsdFs4XT0wLHRbOV09MCx0WzExXT0wLHRbMTJdPTAsdFsxM109MCx0WzE0XT0wKSx0WzBdPTEsdFs1XT0xLHRbMTBdPTEsdFsxNV09MSx0fSx0LmNyZWF0ZSQxPURhLHQuY3JlYXRlJDI9ZnVuY3Rpb24oKXt2YXIgdD1uZXcgTGEoNCk7cmV0dXJuIExhIT1GbG9hdDMyQXJyYXkmJih0WzFdPTAsdFsyXT0wKSx0WzBdPTEsdFszXT0xLHR9LHQuY3JlYXRlQ29tbW9uanNNb2R1bGU9ZSx0LmNyZWF0ZUV4cHJlc3Npb249RnIsdC5jcmVhdGVMYXlvdXQ9bGksdC5jcmVhdGVTdHlsZUxheWVyPWZ1bmN0aW9uKHQpe3JldHVybiBcImN1c3RvbVwiPT09dC50eXBlP25ldyBydSh0KTpuZXcgbnVbdC50eXBlXSh0KX0sdC5kZWVwRXF1YWw9byx0LmVhc2U9dSx0LmVtaXRWYWxpZGF0aW9uRXJyb3JzPWJuLHQuZW5kc1dpdGg9dix0LmVuZm9yY2VDYWNoZVNpemVMaW1pdD1mdW5jdGlvbih0KXtzZWxmLmNhY2hlcyYmc2VsZi5jYWNoZXMub3BlbihodCkudGhlbihmdW5jdGlvbihlKXtlLmtleXMoKS50aGVuKGZ1bmN0aW9uKHIpe2Zvcih2YXIgbj0wO248ci5sZW5ndGgtdDtuKyspZS5kZWxldGUocltuXSk7fSk7fSk7fSx0LmV2YWx1YXRlUmFkaWFsT2Zmc2V0PU9sLHQuZXZhbHVhdGVTaXplRm9yRmVhdHVyZT1Scyx0LmV2YWx1YXRlU2l6ZUZvclpvb209VXMsdC5ldmVudGVkPXFuLHQuZXh0ZW5kPWMsdC5mZWF0dXJlRmlsdGVyPUpyLHQuZmlsdGVyT2JqZWN0PXgsdC5mcm9tUm90YXRpb249ZnVuY3Rpb24odCxlKXt2YXIgcj1NYXRoLnNpbihlKSxuPU1hdGguY29zKGUpO3JldHVybiB0WzBdPW4sdFsxXT1yLHRbMl09MCx0WzNdPS1yLHRbNF09bix0WzVdPTAsdFs2XT0wLHRbN109MCx0WzhdPTEsdH0sdC5nZXRBbmNob3JBbGlnbm1lbnQ9dmwsdC5nZXRBbmNob3JKdXN0aWZpY2F0aW9uPVJsLHQuZ2V0QXJyYXlCdWZmZXI9enQsdC5nZXRJbWFnZT1FdCx0LmdldEpTT049ZnVuY3Rpb24odCxlKXtyZXR1cm4ga3QoYyh0LHt0eXBlOlwianNvblwifSksZSl9LHQuZ2V0UmVmZXJyZXI9QXQsdC5nZXRWaWRlbz1mdW5jdGlvbih0LGUpe3ZhciByLG4saT1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJ2aWRlb1wiKTtpLm11dGVkPSEwLGkub25sb2Fkc3RhcnQ9ZnVuY3Rpb24oKXtlKG51bGwsaSk7fTtmb3IodmFyIGE9MDthPHQubGVuZ3RoO2ErKyl7dmFyIG89c2VsZi5kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic291cmNlXCIpO3I9dFthXSxuPXZvaWQgMCwobj1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpKS5ocmVmPXIsKG4ucHJvdG9jb2whPT1zZWxmLmRvY3VtZW50LmxvY2F0aW9uLnByb3RvY29sfHxuLmhvc3QhPT1zZWxmLmRvY3VtZW50LmxvY2F0aW9uLmhvc3QpJiYoaS5jcm9zc09yaWdpbj1cIkFub255bW91c1wiKSxvLnNyYz10W2FdLGkuYXBwZW5kQ2hpbGQobyk7fXJldHVybiB7Y2FuY2VsOmZ1bmN0aW9uKCl7fX19LHQuaWRlbnRpdHk9ZnVuY3Rpb24odCl7cmV0dXJuIHRbMF09MSx0WzFdPTAsdFsyXT0wLHRbM109MCx0WzRdPTAsdFs1XT0xLHRbNl09MCx0WzddPTAsdFs4XT0wLHRbOV09MCx0WzEwXT0xLHRbMTFdPTAsdFsxMl09MCx0WzEzXT0wLHRbMTRdPTAsdFsxNV09MSx0fSx0LmludmVydD1mdW5jdGlvbih0LGUpe3ZhciByPWVbMF0sbj1lWzFdLGk9ZVsyXSxhPWVbM10sbz1lWzRdLHM9ZVs1XSx1PWVbNl0sbD1lWzddLHA9ZVs4XSxjPWVbOV0saD1lWzEwXSxmPWVbMTFdLHk9ZVsxMl0sZD1lWzEzXSxtPWVbMTRdLHY9ZVsxNV0sZz1yKnMtbipvLHg9cip1LWkqbyxiPXIqbC1hKm8sXz1uKnUtaSpzLHc9bipsLWEqcyxBPWkqbC1hKnUsUz1wKmQtYyp5LGs9cCptLWgqeSx6PXAqdi1mKnksST1jKm0taCpkLEI9Yyp2LWYqZCxDPWgqdi1mKm0sRT1nKkMteCpCK2IqSStfKnotdyprK0EqUztyZXR1cm4gRT8oRT0xL0UsdFswXT0ocypDLXUqQitsKkkpKkUsdFsxXT0oaSpCLW4qQy1hKkkpKkUsdFsyXT0oZCpBLW0qdyt2Kl8pKkUsdFszXT0oaCp3LWMqQS1mKl8pKkUsdFs0XT0odSp6LW8qQy1sKmspKkUsdFs1XT0ocipDLWkqeithKmspKkUsdFs2XT0obSpiLXkqQS12KngpKkUsdFs3XT0ocCpBLWgqYitmKngpKkUsdFs4XT0obypCLXMqeitsKlMpKkUsdFs5XT0obip6LXIqQi1hKlMpKkUsdFsxMF09KHkqdy1kKmIrdipnKSpFLHRbMTFdPShjKmItcCp3LWYqZykqRSx0WzEyXT0ocyprLW8qSS11KlMpKkUsdFsxM109KHIqSS1uKmsraSpTKSpFLHRbMTRdPShkKngteSpfLW0qZykqRSx0WzE1XT0ocCpfLWMqeCtoKmcpKkUsdCk6bnVsbH0sdC5pc0NoYXI9TW4sdC5pc01hcGJveFVSTD1OLHQua2V5c0RpZmZlcmVuY2U9ZnVuY3Rpb24odCxlKXt2YXIgcj1bXTtmb3IodmFyIG4gaW4gdCluIGluIGV8fHIucHVzaChuKTtyZXR1cm4gcn0sdC5tYWtlUmVxdWVzdD1rdCx0Lm1hcE9iamVjdD1nLHQubWVyY2F0b3JYZnJvbUxuZz1xdSx0Lm1lcmNhdG9yWWZyb21MYXQ9TnUsdC5tZXJjYXRvclpmcm9tQWx0aXR1ZGU9WnUsdC5tdWx0aXBseT1mdW5jdGlvbih0LGUscil7dmFyIG49ZVswXSxpPWVbMV0sYT1lWzJdLG89ZVszXSxzPWVbNF0sdT1lWzVdLGw9ZVs2XSxwPWVbN10sYz1lWzhdLGg9ZVs5XSxmPWVbMTBdLHk9ZVsxMV0sZD1lWzEyXSxtPWVbMTNdLHY9ZVsxNF0sZz1lWzE1XSx4PXJbMF0sYj1yWzFdLF89clsyXSx3PXJbM107cmV0dXJuIHRbMF09eCpuK2IqcytfKmMrdypkLHRbMV09eCppK2IqdStfKmgrdyptLHRbMl09eCphK2IqbCtfKmYrdyp2LHRbM109eCpvK2IqcCtfKnkrdypnLHg9cls0XSxiPXJbNV0sXz1yWzZdLHc9cls3XSx0WzRdPXgqbitiKnMrXypjK3cqZCx0WzVdPXgqaStiKnUrXypoK3cqbSx0WzZdPXgqYStiKmwrXypmK3cqdix0WzddPXgqbytiKnArXyp5K3cqZyx4PXJbOF0sYj1yWzldLF89clsxMF0sdz1yWzExXSx0WzhdPXgqbitiKnMrXypjK3cqZCx0WzldPXgqaStiKnUrXypoK3cqbSx0WzEwXT14KmErYipsK18qZit3KnYsdFsxMV09eCpvK2IqcCtfKnkrdypnLHg9clsxMl0sYj1yWzEzXSxfPXJbMTRdLHc9clsxNV0sdFsxMl09eCpuK2IqcytfKmMrdypkLHRbMTNdPXgqaStiKnUrXypoK3cqbSx0WzE0XT14KmErYipsK18qZit3KnYsdFsxNV09eCpvK2IqcCtfKnkrdypnLHR9LHQubXZ0PWlzLHQubnVtYmVyPUVlLHQub3J0aG89ZnVuY3Rpb24odCxlLHIsbixpLGEsbyl7dmFyIHM9MS8oZS1yKSx1PTEvKG4taSksbD0xLyhhLW8pO3JldHVybiB0WzBdPS0yKnMsdFsxXT0wLHRbMl09MCx0WzNdPTAsdFs0XT0wLHRbNV09LTIqdSx0WzZdPTAsdFs3XT0wLHRbOF09MCx0WzldPTAsdFsxMF09MipsLHRbMTFdPTAsdFsxMl09KGUrcikqcyx0WzEzXT0oaStuKSp1LHRbMTRdPShvK2EpKmwsdFsxNV09MSx0fSx0LnBhcnNlR2x5cGhQQkY9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBkdSh0KS5yZWFkRmllbGRzKFB1LFtdKX0sdC5wYmY9ZHUsdC5wZXJmb3JtU3ltYm9sTGF5b3V0PWZ1bmN0aW9uKHQsZSxyLG4saSxhKXt0LmNyZWF0ZUFycmF5cygpO3ZhciBvPTUxMip0Lm92ZXJzY2FsaW5nO3QudGlsZVBpeGVsUmF0aW89eWEvbyx0LmNvbXBhcmVUZXh0PXt9LHQuaWNvbnNOZWVkTGluZWFyPSExO3ZhciBzPXQubGF5ZXJzWzBdLmxheW91dCx1PXQubGF5ZXJzWzBdLl91bmV2YWx1YXRlZExheW91dC5fdmFsdWVzLGw9e307aWYoXCJjb21wb3NpdGVcIj09PXQudGV4dFNpemVEYXRhLmtpbmQpe3ZhciBwPXQudGV4dFNpemVEYXRhLGM9cC5taW5ab29tLGg9cC5tYXhab29tO2wuY29tcG9zaXRlVGV4dFNpemVzPVt1W1widGV4dC1zaXplXCJdLnBvc3NpYmx5RXZhbHVhdGUobmV3IFpuKGMpKSx1W1widGV4dC1zaXplXCJdLnBvc3NpYmx5RXZhbHVhdGUobmV3IFpuKGgpKV07fWlmKFwiY29tcG9zaXRlXCI9PT10Lmljb25TaXplRGF0YS5raW5kKXt2YXIgZj10Lmljb25TaXplRGF0YSx5PWYubWluWm9vbSxkPWYubWF4Wm9vbTtsLmNvbXBvc2l0ZUljb25TaXplcz1bdVtcImljb24tc2l6ZVwiXS5wb3NzaWJseUV2YWx1YXRlKG5ldyBabih5KSksdVtcImljb24tc2l6ZVwiXS5wb3NzaWJseUV2YWx1YXRlKG5ldyBabihkKSldO31sLmxheW91dFRleHRTaXplPXVbXCJ0ZXh0LXNpemVcIl0ucG9zc2libHlFdmFsdWF0ZShuZXcgWm4odC56b29tKzEpKSxsLmxheW91dEljb25TaXplPXVbXCJpY29uLXNpemVcIl0ucG9zc2libHlFdmFsdWF0ZShuZXcgWm4odC56b29tKzEpKSxsLnRleHRNYXhTaXplPXVbXCJ0ZXh0LXNpemVcIl0ucG9zc2libHlFdmFsdWF0ZShuZXcgWm4oMTgpKTtmb3IodmFyIG09cy5nZXQoXCJ0ZXh0LWxpbmUtaGVpZ2h0XCIpKnNsLHY9XCJtYXBcIj09PXMuZ2V0KFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIikmJlwicG9pbnRcIiE9PXMuZ2V0KFwic3ltYm9sLXBsYWNlbWVudFwiKSxnPXMuZ2V0KFwidGV4dC1rZWVwLXVwcmlnaHRcIikseD0wLGI9dC5mZWF0dXJlczt4PGIubGVuZ3RoO3grPTEpe3ZhciBfPWJbeF0sQT1zLmdldChcInRleHQtZm9udFwiKS5ldmFsdWF0ZShfLHt9KS5qb2luKFwiLFwiKSxTPXIsaz17aG9yaXpvbnRhbDp7fSx2ZXJ0aWNhbDp2b2lkIDB9LHo9Xy50ZXh0LEk9WzAsMF07aWYoeil7dmFyIEI9ei50b1N0cmluZygpLEM9cy5nZXQoXCJ0ZXh0LWxldHRlci1zcGFjaW5nXCIpLmV2YWx1YXRlKF8se30pKnNsLEU9UG4oQik/QzowLE09cy5nZXQoXCJ0ZXh0LWFuY2hvclwiKS5ldmFsdWF0ZShfLHt9KSxUPXMuZ2V0KFwidGV4dC12YXJpYWJsZS1hbmNob3JcIiksUD1zLmdldChcInRleHQtcmFkaWFsLW9mZnNldFwiKS5ldmFsdWF0ZShfLHt9KTtUfHwoST1QP09sKE0sUCpzbCk6cy5nZXQoXCJ0ZXh0LW9mZnNldFwiKS5ldmFsdWF0ZShfLHt9KS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQqc2x9KSk7dmFyIFY9dj9cImNlbnRlclwiOnMuZ2V0KFwidGV4dC1qdXN0aWZ5XCIpLmV2YWx1YXRlKF8se30pLEY9XCJwb2ludFwiPT09cy5nZXQoXCJzeW1ib2wtcGxhY2VtZW50XCIpP3MuZ2V0KFwidGV4dC1tYXgtd2lkdGhcIikuZXZhbHVhdGUoXyx7fSkqc2w6MDtpZighdiYmVClmb3IodmFyIEw9XCJhdXRvXCI9PT1WP1QubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBSbCh0KX0pOltWXSxEPSExLE89MDtPPEwubGVuZ3RoO08rKyl7dmFyIFI9TFtPXTtpZighay5ob3Jpem9udGFsW1JdKWlmKEQpay5ob3Jpem9udGFsW1JdPWsuaG9yaXpvbnRhbFswXTtlbHNle3ZhciBVPXBsKHosZSxBLEYsbSxcImNlbnRlclwiLFIsRSxJLHVsLmhvcml6b250YWwpO1UmJihrLmhvcml6b250YWxbUl09VSxEPTE9PT1VLmxpbmVDb3VudCk7fX1lbHNle1wiYXV0b1wiPT09ViYmKFY9UmwoTSkpO3ZhciBqPXBsKHosZSxBLEYsbSxNLFYsRSxJLHVsLmhvcml6b250YWwpO2omJihrLmhvcml6b250YWxbVl09aiksVG4oQikmJnYmJmcmJihrLnZlcnRpY2FsPXBsKHosZSxBLEYsbSxNLFYsRSxJLHVsLnZlcnRpY2FsKSk7fX12YXIgcT12b2lkIDA7aWYoXy5pY29uKXt2YXIgTj1uW18uaWNvbl07TiYmKHE9eGwoaVtfLmljb25dLHMuZ2V0KFwiaWNvbi1vZmZzZXRcIikuZXZhbHVhdGUoXyx7fSkscy5nZXQoXCJpY29uLWFuY2hvclwiKS5ldmFsdWF0ZShfLHt9KSksdm9pZCAwPT09dC5zZGZJY29ucz90LnNkZkljb25zPU4uc2RmOnQuc2RmSWNvbnMhPT1OLnNkZiYmdyhcIlN0eWxlIHNoZWV0IHdhcm5pbmc6IENhbm5vdCBtaXggU0RGIGFuZCBub24tU0RGIGljb25zIGluIG9uZSBidWZmZXJcIiksTi5waXhlbFJhdGlvIT09dC5waXhlbFJhdGlvP3QuaWNvbnNOZWVkTGluZWFyPSEwOjAhPT1zLmdldChcImljb24tcm90YXRlXCIpLmNvbnN0YW50T3IoMSkmJih0Lmljb25zTmVlZExpbmVhcj0hMCkpO30oT2JqZWN0LmtleXMoay5ob3Jpem9udGFsKS5sZW5ndGh8fHEpJiZVbCh0LF8sayxxLFMsbCxJKTt9YSYmdC5nZW5lcmF0ZUNvbGxpc2lvbkRlYnVnQnVmZmVycygpO30sdC5wZXJzcGVjdGl2ZT1mdW5jdGlvbih0LGUscixuLGkpe3ZhciBhLG89MS9NYXRoLnRhbihlLzIpO3JldHVybiB0WzBdPW8vcix0WzFdPTAsdFsyXT0wLHRbM109MCx0WzRdPTAsdFs1XT1vLHRbNl09MCx0WzddPTAsdFs4XT0wLHRbOV09MCx0WzExXT0tMSx0WzEyXT0wLHRbMTNdPTAsdFsxNV09MCxudWxsIT1pJiZpIT09MS8wPyhhPTEvKG4taSksdFsxMF09KGkrbikqYSx0WzE0XT0yKmkqbiphKToodFsxMF09LTEsdFsxNF09LTIqbiksdH0sdC5waWNrPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPXt9LG49MDtuPGUubGVuZ3RoO24rKyl7dmFyIGk9ZVtuXTtpIGluIHQmJihyW2ldPXRbaV0pO31yZXR1cm4gcn0sdC5wbHVnaW49Tm4sdC5wb2x5Z29uSW50ZXJzZWN0c1BvbHlnb249YmEsdC5wb3N0TWFwTG9hZEV2ZW50PWN0LHQucG9zdFR1cm5zdGlsZUV2ZW50PWx0LHQucG90cGFjaz1pdSx0LnJhc3RlckJvdW5kc0F0dHJpYnV0ZXM9V3UsdC5yZWZQcm9wZXJ0aWVzPVtcInR5cGVcIixcInNvdXJjZVwiLFwic291cmNlLWxheWVyXCIsXCJtaW56b29tXCIsXCJtYXh6b29tXCIsXCJmaWx0ZXJcIixcImxheW91dFwiXSx0LnJlZ2lzdGVyPXpuLHQucmVnaXN0ZXJGb3JQbHVnaW5BdmFpbGFiaWxpdHk9ZnVuY3Rpb24odCl7cmV0dXJuIFVuP3Qoe3BsdWdpblVSTDpVbixjb21wbGV0aW9uQ2FsbGJhY2s6T259KTpxbi5vbmNlKFwicGx1Z2luQXZhaWxhYmxlXCIsdCksdH0sdC5yb3RhdGU9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPWVbMF0saT1lWzFdLGE9ZVsyXSxvPWVbM10scz1NYXRoLnNpbihyKSx1PU1hdGguY29zKHIpO3JldHVybiB0WzBdPW4qdSthKnMsdFsxXT1pKnUrbypzLHRbMl09biotcythKnUsdFszXT1pKi1zK28qdSx0fSx0LnJvdGF0ZVg9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPU1hdGguc2luKHIpLGk9TWF0aC5jb3MociksYT1lWzRdLG89ZVs1XSxzPWVbNl0sdT1lWzddLGw9ZVs4XSxwPWVbOV0sYz1lWzEwXSxoPWVbMTFdO3JldHVybiBlIT09dCYmKHRbMF09ZVswXSx0WzFdPWVbMV0sdFsyXT1lWzJdLHRbM109ZVszXSx0WzEyXT1lWzEyXSx0WzEzXT1lWzEzXSx0WzE0XT1lWzE0XSx0WzE1XT1lWzE1XSksdFs0XT1hKmkrbCpuLHRbNV09byppK3Aqbix0WzZdPXMqaStjKm4sdFs3XT11KmkraCpuLHRbOF09bCppLWEqbix0WzldPXAqaS1vKm4sdFsxMF09YyppLXMqbix0WzExXT1oKmktdSpuLHR9LHQucm90YXRlWj1mdW5jdGlvbih0LGUscil7dmFyIG49TWF0aC5zaW4ociksaT1NYXRoLmNvcyhyKSxhPWVbMF0sbz1lWzFdLHM9ZVsyXSx1PWVbM10sbD1lWzRdLHA9ZVs1XSxjPWVbNl0saD1lWzddO3JldHVybiBlIT09dCYmKHRbOF09ZVs4XSx0WzldPWVbOV0sdFsxMF09ZVsxMF0sdFsxMV09ZVsxMV0sdFsxMl09ZVsxMl0sdFsxM109ZVsxM10sdFsxNF09ZVsxNF0sdFsxNV09ZVsxNV0pLHRbMF09YSppK2wqbix0WzFdPW8qaStwKm4sdFsyXT1zKmkrYypuLHRbM109dSppK2gqbix0WzRdPWwqaS1hKm4sdFs1XT1wKmktbypuLHRbNl09YyppLXMqbix0WzddPWgqaS11Km4sdH0sdC5zY2FsZT1mdW5jdGlvbih0LGUscil7dmFyIG49clswXSxpPXJbMV0sYT1yWzJdO3JldHVybiB0WzBdPWVbMF0qbix0WzFdPWVbMV0qbix0WzJdPWVbMl0qbix0WzNdPWVbM10qbix0WzRdPWVbNF0qaSx0WzVdPWVbNV0qaSx0WzZdPWVbNl0qaSx0WzddPWVbN10qaSx0WzhdPWVbOF0qYSx0WzldPWVbOV0qYSx0WzEwXT1lWzEwXSphLHRbMTFdPWVbMTFdKmEsdFsxMl09ZVsxMl0sdFsxM109ZVsxM10sdFsxNF09ZVsxNF0sdFsxNV09ZVsxNV0sdH0sdC5zZXRDYWNoZUxpbWl0cz1mdW5jdGlvbih0LGUpe2Z0PXQseXQ9ZTt9LHQuc2V0UlRMVGV4dFBsdWdpbj1mdW5jdGlvbih0LGUpe2lmKFJuKXRocm93IG5ldyBFcnJvcihcInNldFJUTFRleHRQbHVnaW4gY2Fubm90IGJlIGNhbGxlZCBtdWx0aXBsZSB0aW1lcy5cIik7Um49ITAsVW49UC5yZXNvbHZlVVJMKHQpLE9uPWZ1bmN0aW9uKHQpe3Q/KFJuPSExLFVuPW51bGwsZSYmZSh0KSk6am49ITA7fSxxbi5maXJlKG5ldyBQdChcInBsdWdpbkF2YWlsYWJsZVwiLHtwbHVnaW5VUkw6VW4sY29tcGxldGlvbkNhbGxiYWNrOk9ufSkpO30sdC5zcGhlcmljYWxUb0NhcnRlc2lhbj1mdW5jdGlvbih0KXt2YXIgZT10WzBdLHI9dFsxXSxuPXRbMl07cmV0dXJuIHIrPTkwLHIqPU1hdGguUEkvMTgwLG4qPU1hdGguUEkvMTgwLHt4OmUqTWF0aC5jb3MocikqTWF0aC5zaW4obikseTplKk1hdGguc2luKHIpKk1hdGguc2luKG4pLHo6ZSpNYXRoLmNvcyhuKX19LHQuc3R5bGVTcGVjPUx0LHQuc3ltYm9sU2l6ZT1qcyx0LnRyYW5zZm9ybU1hdDM9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPWVbMF0saT1lWzFdLGE9ZVsyXTtyZXR1cm4gdFswXT1uKnJbMF0raSpyWzNdK2Eqcls2XSx0WzFdPW4qclsxXStpKnJbNF0rYSpyWzddLHRbMl09bipyWzJdK2kqcls1XSthKnJbOF0sdH0sdC50cmFuc2Zvcm1NYXQ0PU5hLHQudHJhbnNsYXRlPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixpLGEsbyxzLHUsbCxwLGMsaCxmLHksZD1yWzBdLG09clsxXSx2PXJbMl07cmV0dXJuIGU9PT10Pyh0WzEyXT1lWzBdKmQrZVs0XSptK2VbOF0qditlWzEyXSx0WzEzXT1lWzFdKmQrZVs1XSptK2VbOV0qditlWzEzXSx0WzE0XT1lWzJdKmQrZVs2XSptK2VbMTBdKnYrZVsxNF0sdFsxNV09ZVszXSpkK2VbN10qbStlWzExXSp2K2VbMTVdKToobj1lWzBdLGk9ZVsxXSxhPWVbMl0sbz1lWzNdLHM9ZVs0XSx1PWVbNV0sbD1lWzZdLHA9ZVs3XSxjPWVbOF0saD1lWzldLGY9ZVsxMF0seT1lWzExXSx0WzBdPW4sdFsxXT1pLHRbMl09YSx0WzNdPW8sdFs0XT1zLHRbNV09dSx0WzZdPWwsdFs3XT1wLHRbOF09Yyx0WzldPWgsdFsxMF09Zix0WzExXT15LHRbMTJdPW4qZCtzKm0rYyp2K2VbMTJdLHRbMTNdPWkqZCt1Km0raCp2K2VbMTNdLHRbMTRdPWEqZCtsKm0rZip2K2VbMTRdLHRbMTVdPW8qZCtwKm0reSp2K2VbMTVdKSx0fSx0LnVuaXF1ZUlkPWYsdC52YWxpZGF0ZUN1c3RvbVN0eWxlTGF5ZXI9ZnVuY3Rpb24odCl7dmFyIGU9W10scj10LmlkO3JldHVybiB2b2lkIDA9PT1yJiZlLnB1c2goe21lc3NhZ2U6XCJsYXllcnMuXCIrcisnOiBtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IFwiaWRcIid9KSx2b2lkIDA9PT10LnJlbmRlciYmZS5wdXNoKHttZXNzYWdlOlwibGF5ZXJzLlwiK3IrJzogbWlzc2luZyByZXF1aXJlZCBtZXRob2QgXCJyZW5kZXJcIid9KSx0LnJlbmRlcmluZ01vZGUmJlwiMmRcIiE9PXQucmVuZGVyaW5nTW9kZSYmXCIzZFwiIT09dC5yZW5kZXJpbmdNb2RlJiZlLnB1c2goe21lc3NhZ2U6XCJsYXllcnMuXCIrcisnOiBwcm9wZXJ0eSBcInJlbmRlcmluZ01vZGVcIiBtdXN0IGJlIGVpdGhlciBcIjJkXCIgb3IgXCIzZFwiJ30pLGV9LHQudmFsaWRhdGVMaWdodD12bix0LnZhbGlkYXRlU3R5bGU9bW4sdC52YWx1ZXM9ZnVuY3Rpb24odCl7dmFyIGU9W107Zm9yKHZhciByIGluIHQpZS5wdXNoKHRbcl0pO3JldHVybiBlfSx0LnZlY3RvclRpbGU9aXMsdC52ZXJzaW9uPVwiMS4xLjFcIix0Lndhcm5PbmNlPXcsdC53ZWJwU3VwcG9ydGVkPUYsdC53aW5kb3c9c2VsZix0LndyYXA9cDt9KTtcblxuZGVmaW5lKFtcIi4vc2hhcmVkLmpzXCJdLGZ1bmN0aW9uKGUpe1widXNlIHN0cmljdFwiO2Z1bmN0aW9uIHQoZSl7dmFyIHI9dHlwZW9mIGU7aWYoXCJudW1iZXJcIj09PXJ8fFwiYm9vbGVhblwiPT09cnx8XCJzdHJpbmdcIj09PXJ8fG51bGw9PWUpcmV0dXJuIEpTT04uc3RyaW5naWZ5KGUpO2lmKEFycmF5LmlzQXJyYXkoZSkpe2Zvcih2YXIgbz1cIltcIixpPTAsbj1lO2k8bi5sZW5ndGg7aSs9MSl7bys9dChuW2ldKStcIixcIjt9cmV0dXJuIG8rXCJdXCJ9Zm9yKHZhciBhPU9iamVjdC5rZXlzKGUpLnNvcnQoKSxzPVwie1wiLHU9MDt1PGEubGVuZ3RoO3UrKylzKz1KU09OLnN0cmluZ2lmeShhW3VdKStcIjpcIit0KGVbYVt1XV0pK1wiLFwiO3JldHVybiBzK1wifVwifWZ1bmN0aW9uIHIocil7Zm9yKHZhciBvPVwiXCIsaT0wLG49ZS5yZWZQcm9wZXJ0aWVzO2k8bi5sZW5ndGg7aSs9MSl7bys9XCIvXCIrdChyW25baV1dKTt9cmV0dXJuIG99dmFyIG89ZnVuY3Rpb24oZSl7dGhpcy5rZXlDYWNoZT17fSxlJiZ0aGlzLnJlcGxhY2UoZSk7fTtvLnByb3RvdHlwZS5yZXBsYWNlPWZ1bmN0aW9uKGUpe3RoaXMuX2xheWVyQ29uZmlncz17fSx0aGlzLl9sYXllcnM9e30sdGhpcy51cGRhdGUoZSxbXSk7fSxvLnByb3RvdHlwZS51cGRhdGU9ZnVuY3Rpb24odCxvKXtmb3IodmFyIGk9dGhpcyxuPTAsYT10O248YS5sZW5ndGg7bis9MSl7dmFyIHM9YVtuXTt0aGlzLl9sYXllckNvbmZpZ3Nbcy5pZF09czt2YXIgdT10aGlzLl9sYXllcnNbcy5pZF09ZS5jcmVhdGVTdHlsZUxheWVyKHMpO3UuX2ZlYXR1cmVGaWx0ZXI9ZS5mZWF0dXJlRmlsdGVyKHUuZmlsdGVyKSx0aGlzLmtleUNhY2hlW3MuaWRdJiZkZWxldGUgdGhpcy5rZXlDYWNoZVtzLmlkXTt9Zm9yKHZhciBsPTAsaD1vO2w8aC5sZW5ndGg7bCs9MSl7dmFyIGM9aFtsXTtkZWxldGUgdGhpcy5rZXlDYWNoZVtjXSxkZWxldGUgdGhpcy5fbGF5ZXJDb25maWdzW2NdLGRlbGV0ZSB0aGlzLl9sYXllcnNbY107fXRoaXMuZmFtaWxpZXNCeVNvdXJjZT17fTtmb3IodmFyIHA9MCxmPWZ1bmN0aW9uKGUsdCl7Zm9yKHZhciBvPXt9LGk9MDtpPGUubGVuZ3RoO2krKyl7dmFyIG49dCYmdFtlW2ldLmlkXXx8cihlW2ldKTt0JiYodFtlW2ldLmlkXT1uKTt2YXIgYT1vW25dO2F8fChhPW9bbl09W10pLGEucHVzaChlW2ldKTt9dmFyIHM9W107Zm9yKHZhciB1IGluIG8pcy5wdXNoKG9bdV0pO3JldHVybiBzfShlLnZhbHVlcyh0aGlzLl9sYXllckNvbmZpZ3MpLHRoaXMua2V5Q2FjaGUpO3A8Zi5sZW5ndGg7cCs9MSl7dmFyIGQ9ZltwXS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIGkuX2xheWVyc1tlLmlkXX0pLGc9ZFswXTtpZihcIm5vbmVcIiE9PWcudmlzaWJpbGl0eSl7dmFyIG09Zy5zb3VyY2V8fFwiXCIsdj10aGlzLmZhbWlsaWVzQnlTb3VyY2VbbV07dnx8KHY9dGhpcy5mYW1pbGllc0J5U291cmNlW21dPXt9KTt2YXIgeT1nLnNvdXJjZUxheWVyfHxcIl9nZW9qc29uVGlsZUxheWVyXCIseD12W3ldO3h8fCh4PXZbeV09W10pLHgucHVzaChkKTt9fX07dmFyIGk9ZnVuY3Rpb24odCl7dmFyIHI9e30sbz1bXTtmb3IodmFyIGkgaW4gdCl7dmFyIG49dFtpXSxhPXJbaV09e307Zm9yKHZhciBzIGluIG4pe3ZhciB1PW5bK3NdO2lmKHUmJjAhPT11LmJpdG1hcC53aWR0aCYmMCE9PXUuYml0bWFwLmhlaWdodCl7dmFyIGw9e3g6MCx5OjAsdzp1LmJpdG1hcC53aWR0aCsyLGg6dS5iaXRtYXAuaGVpZ2h0KzJ9O28ucHVzaChsKSxhW3NdPXtyZWN0OmwsbWV0cmljczp1Lm1ldHJpY3N9O319fXZhciBoPWUucG90cGFjayhvKSxjPWgudyxwPWguaCxmPW5ldyBlLkFscGhhSW1hZ2Uoe3dpZHRoOmN8fDEsaGVpZ2h0OnB8fDF9KTtmb3IodmFyIGQgaW4gdCl7dmFyIGc9dFtkXTtmb3IodmFyIG0gaW4gZyl7dmFyIHY9Z1srbV07aWYodiYmMCE9PXYuYml0bWFwLndpZHRoJiYwIT09di5iaXRtYXAuaGVpZ2h0KXt2YXIgeT1yW2RdW21dLnJlY3Q7ZS5BbHBoYUltYWdlLmNvcHkodi5iaXRtYXAsZix7eDowLHk6MH0se3g6eS54KzEseTp5LnkrMX0sdi5iaXRtYXApO319fXRoaXMuaW1hZ2U9Zix0aGlzLnBvc2l0aW9ucz1yO307ZS5yZWdpc3RlcihcIkdseXBoQXRsYXNcIixpKTt2YXIgbj1mdW5jdGlvbih0KXt0aGlzLnRpbGVJRD1uZXcgZS5PdmVyc2NhbGVkVGlsZUlEKHQudGlsZUlELm92ZXJzY2FsZWRaLHQudGlsZUlELndyYXAsdC50aWxlSUQuY2Fub25pY2FsLnosdC50aWxlSUQuY2Fub25pY2FsLngsdC50aWxlSUQuY2Fub25pY2FsLnkpLHRoaXMudWlkPXQudWlkLHRoaXMuem9vbT10Lnpvb20sdGhpcy5waXhlbFJhdGlvPXQucGl4ZWxSYXRpbyx0aGlzLnRpbGVTaXplPXQudGlsZVNpemUsdGhpcy5zb3VyY2U9dC5zb3VyY2UsdGhpcy5vdmVyc2NhbGluZz10aGlzLnRpbGVJRC5vdmVyc2NhbGVGYWN0b3IoKSx0aGlzLnNob3dDb2xsaXNpb25Cb3hlcz10LnNob3dDb2xsaXNpb25Cb3hlcyx0aGlzLmNvbGxlY3RSZXNvdXJjZVRpbWluZz0hIXQuY29sbGVjdFJlc291cmNlVGltaW5nLHRoaXMucmV0dXJuRGVwZW5kZW5jaWVzPSEhdC5yZXR1cm5EZXBlbmRlbmNpZXM7fTtmdW5jdGlvbiBhKHQscil7Zm9yKHZhciBvPW5ldyBlLkV2YWx1YXRpb25QYXJhbWV0ZXJzKHIpLGk9MCxuPXQ7aTxuLmxlbmd0aDtpKz0xKXtuW2ldLnJlY2FsY3VsYXRlKG8pO319bi5wcm90b3R5cGUucGFyc2U9ZnVuY3Rpb24odCxyLG8sbil7dmFyIHM9dGhpczt0aGlzLnN0YXR1cz1cInBhcnNpbmdcIix0aGlzLmRhdGE9dCx0aGlzLmNvbGxpc2lvbkJveEFycmF5PW5ldyBlLkNvbGxpc2lvbkJveEFycmF5O3ZhciB1PW5ldyBlLkRpY3Rpb25hcnlDb2RlcihPYmplY3Qua2V5cyh0LmxheWVycykuc29ydCgpKSxsPW5ldyBlLkZlYXR1cmVJbmRleCh0aGlzLnRpbGVJRCk7bC5idWNrZXRMYXllcklEcz1bXTt2YXIgaCxjLHAsZixkPXt9LGc9e2ZlYXR1cmVJbmRleDpsLGljb25EZXBlbmRlbmNpZXM6e30scGF0dGVybkRlcGVuZGVuY2llczp7fSxnbHlwaERlcGVuZGVuY2llczp7fX0sbT1yLmZhbWlsaWVzQnlTb3VyY2VbdGhpcy5zb3VyY2VdO2Zvcih2YXIgdiBpbiBtKXt2YXIgeT10LmxheWVyc1t2XTtpZih5KXsxPT09eS52ZXJzaW9uJiZlLndhcm5PbmNlKCdWZWN0b3IgdGlsZSBzb3VyY2UgXCInK3RoaXMuc291cmNlKydcIiBsYXllciBcIicrdisnXCIgZG9lcyBub3QgdXNlIHZlY3RvciB0aWxlIHNwZWMgdjIgYW5kIHRoZXJlZm9yZSBtYXkgaGF2ZSBzb21lIHJlbmRlcmluZyBlcnJvcnMuJyk7Zm9yKHZhciB4PXUuZW5jb2RlKHYpLHc9W10sUz0wO1M8eS5sZW5ndGg7UysrKXt2YXIgTT15LmZlYXR1cmUoUyk7dy5wdXNoKHtmZWF0dXJlOk0saW5kZXg6Uyxzb3VyY2VMYXllckluZGV4Onh9KTt9Zm9yKHZhciBrPTAsYj1tW3ZdO2s8Yi5sZW5ndGg7ays9MSl7dmFyIF89YltrXSxQPV9bMF07aWYoIShQLm1pbnpvb20mJnRoaXMuem9vbTxNYXRoLmZsb29yKFAubWluem9vbSkpKWlmKCEoUC5tYXh6b29tJiZ0aGlzLnpvb20+PVAubWF4em9vbSkpaWYoXCJub25lXCIhPT1QLnZpc2liaWxpdHkpYShfLHRoaXMuem9vbSksKGRbUC5pZF09UC5jcmVhdGVCdWNrZXQoe2luZGV4OmwuYnVja2V0TGF5ZXJJRHMubGVuZ3RoLGxheWVyczpfLHpvb206dGhpcy56b29tLHBpeGVsUmF0aW86dGhpcy5waXhlbFJhdGlvLG92ZXJzY2FsaW5nOnRoaXMub3ZlcnNjYWxpbmcsY29sbGlzaW9uQm94QXJyYXk6dGhpcy5jb2xsaXNpb25Cb3hBcnJheSxzb3VyY2VMYXllckluZGV4Ongsc291cmNlSUQ6dGhpcy5zb3VyY2V9KSkucG9wdWxhdGUodyxnKSxsLmJ1Y2tldExheWVySURzLnB1c2goXy5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIGUuaWR9KSk7fX19dmFyIEk9ZS5tYXBPYmplY3QoZy5nbHlwaERlcGVuZGVuY2llcyxmdW5jdGlvbihlKXtyZXR1cm4gT2JqZWN0LmtleXMoZSkubWFwKE51bWJlcil9KTtPYmplY3Qua2V5cyhJKS5sZW5ndGg/by5zZW5kKFwiZ2V0R2x5cGhzXCIse3VpZDp0aGlzLnVpZCxzdGFja3M6SX0sZnVuY3Rpb24oZSx0KXtofHwoaD1lLGM9dCxELmNhbGwocykpO30pOmM9e307dmFyIFQ9T2JqZWN0LmtleXMoZy5pY29uRGVwZW5kZW5jaWVzKTtULmxlbmd0aD9vLnNlbmQoXCJnZXRJbWFnZXNcIix7aWNvbnM6VH0sZnVuY3Rpb24oZSx0KXtofHwoaD1lLHA9dCxELmNhbGwocykpO30pOnA9e307dmFyIEw9T2JqZWN0LmtleXMoZy5wYXR0ZXJuRGVwZW5kZW5jaWVzKTtmdW5jdGlvbiBEKCl7aWYoaClyZXR1cm4gbihoKTtpZihjJiZwJiZmKXt2YXIgdD1uZXcgaShjKSxyPW5ldyBlLkltYWdlQXRsYXMocCxmKTtmb3IodmFyIG8gaW4gZCl7dmFyIHM9ZFtvXTtzIGluc3RhbmNlb2YgZS5TeW1ib2xCdWNrZXQ/KGEocy5sYXllcnMsdGhpcy56b29tKSxlLnBlcmZvcm1TeW1ib2xMYXlvdXQocyxjLHQucG9zaXRpb25zLHAsci5pY29uUG9zaXRpb25zLHRoaXMuc2hvd0NvbGxpc2lvbkJveGVzKSk6cy5oYXNQYXR0ZXJuJiYocyBpbnN0YW5jZW9mIGUuTGluZUJ1Y2tldHx8cyBpbnN0YW5jZW9mIGUuRmlsbEJ1Y2tldHx8cyBpbnN0YW5jZW9mIGUuRmlsbEV4dHJ1c2lvbkJ1Y2tldCkmJihhKHMubGF5ZXJzLHRoaXMuem9vbSkscy5hZGRGZWF0dXJlcyhnLHIucGF0dGVyblBvc2l0aW9ucykpO310aGlzLnN0YXR1cz1cImRvbmVcIixuKG51bGwse2J1Y2tldHM6ZS52YWx1ZXMoZCkuZmlsdGVyKGZ1bmN0aW9uKGUpe3JldHVybiAhZS5pc0VtcHR5KCl9KSxmZWF0dXJlSW5kZXg6bCxjb2xsaXNpb25Cb3hBcnJheTp0aGlzLmNvbGxpc2lvbkJveEFycmF5LGdseXBoQXRsYXNJbWFnZTp0LmltYWdlLGltYWdlQXRsYXM6cixnbHlwaE1hcDp0aGlzLnJldHVybkRlcGVuZGVuY2llcz9jOm51bGwsaWNvbk1hcDp0aGlzLnJldHVybkRlcGVuZGVuY2llcz9wOm51bGwsZ2x5cGhQb3NpdGlvbnM6dGhpcy5yZXR1cm5EZXBlbmRlbmNpZXM/dC5wb3NpdGlvbnM6bnVsbH0pO319TC5sZW5ndGg/by5zZW5kKFwiZ2V0SW1hZ2VzXCIse2ljb25zOkx9LGZ1bmN0aW9uKGUsdCl7aHx8KGg9ZSxmPXQsRC5jYWxsKHMpKTt9KTpmPXt9LEQuY2FsbCh0aGlzKTt9O3ZhciBzPVwidW5kZWZpbmVkXCIhPXR5cGVvZiBwZXJmb3JtYW5jZSx1PXtnZXRFbnRyaWVzQnlOYW1lOmZ1bmN0aW9uKGUpe3JldHVybiAhIShzJiZwZXJmb3JtYW5jZSYmcGVyZm9ybWFuY2UuZ2V0RW50cmllc0J5TmFtZSkmJnBlcmZvcm1hbmNlLmdldEVudHJpZXNCeU5hbWUoZSl9LG1hcms6ZnVuY3Rpb24oZSl7cmV0dXJuICEhKHMmJnBlcmZvcm1hbmNlJiZwZXJmb3JtYW5jZS5tYXJrKSYmcGVyZm9ybWFuY2UubWFyayhlKX0sbWVhc3VyZTpmdW5jdGlvbihlLHQscil7cmV0dXJuICEhKHMmJnBlcmZvcm1hbmNlJiZwZXJmb3JtYW5jZS5tZWFzdXJlKSYmcGVyZm9ybWFuY2UubWVhc3VyZShlLHQscil9LGNsZWFyTWFya3M6ZnVuY3Rpb24oZSl7cmV0dXJuICEhKHMmJnBlcmZvcm1hbmNlJiZwZXJmb3JtYW5jZS5jbGVhck1hcmtzKSYmcGVyZm9ybWFuY2UuY2xlYXJNYXJrcyhlKX0sY2xlYXJNZWFzdXJlczpmdW5jdGlvbihlKXtyZXR1cm4gISEocyYmcGVyZm9ybWFuY2UmJnBlcmZvcm1hbmNlLmNsZWFyTWVhc3VyZXMpJiZwZXJmb3JtYW5jZS5jbGVhck1lYXN1cmVzKGUpfX0sbD1mdW5jdGlvbihlKXt0aGlzLl9tYXJrcz17c3RhcnQ6W2UudXJsLFwic3RhcnRcIl0uam9pbihcIiNcIiksZW5kOltlLnVybCxcImVuZFwiXS5qb2luKFwiI1wiKSxtZWFzdXJlOmUudXJsLnRvU3RyaW5nKCl9LHUubWFyayh0aGlzLl9tYXJrcy5zdGFydCk7fTtmdW5jdGlvbiBoKHQscil7dmFyIG89ZS5nZXRBcnJheUJ1ZmZlcih0LnJlcXVlc3QsZnVuY3Rpb24odCxvLGksbil7dD9yKHQpOm8mJnIobnVsbCx7dmVjdG9yVGlsZTpuZXcgZS52ZWN0b3JUaWxlLlZlY3RvclRpbGUobmV3IGUucGJmKG8pKSxyYXdEYXRhOm8sY2FjaGVDb250cm9sOmksZXhwaXJlczpufSk7fSk7cmV0dXJuIGZ1bmN0aW9uKCl7by5jYW5jZWwoKSxyKCk7fX1sLnByb3RvdHlwZS5maW5pc2g9ZnVuY3Rpb24oKXt1Lm1hcmsodGhpcy5fbWFya3MuZW5kKTt2YXIgZT11LmdldEVudHJpZXNCeU5hbWUodGhpcy5fbWFya3MubWVhc3VyZSk7cmV0dXJuIDA9PT1lLmxlbmd0aCYmKHUubWVhc3VyZSh0aGlzLl9tYXJrcy5tZWFzdXJlLHRoaXMuX21hcmtzLnN0YXJ0LHRoaXMuX21hcmtzLmVuZCksZT11LmdldEVudHJpZXNCeU5hbWUodGhpcy5fbWFya3MubWVhc3VyZSksdS5jbGVhck1hcmtzKHRoaXMuX21hcmtzLnN0YXJ0KSx1LmNsZWFyTWFya3ModGhpcy5fbWFya3MuZW5kKSx1LmNsZWFyTWVhc3VyZXModGhpcy5fbWFya3MubWVhc3VyZSkpLGV9LHUuUGVyZm9ybWFuY2U9bDt2YXIgYz1mdW5jdGlvbihlLHQscil7dGhpcy5hY3Rvcj1lLHRoaXMubGF5ZXJJbmRleD10LHRoaXMubG9hZFZlY3RvckRhdGE9cnx8aCx0aGlzLmxvYWRpbmc9e30sdGhpcy5sb2FkZWQ9e307fTtjLnByb3RvdHlwZS5sb2FkVGlsZT1mdW5jdGlvbih0LHIpe3ZhciBvPXRoaXMsaT10LnVpZDt0aGlzLmxvYWRpbmd8fCh0aGlzLmxvYWRpbmc9e30pO3ZhciBhPSEhKHQmJnQucmVxdWVzdCYmdC5yZXF1ZXN0LmNvbGxlY3RSZXNvdXJjZVRpbWluZykmJm5ldyB1LlBlcmZvcm1hbmNlKHQucmVxdWVzdCkscz10aGlzLmxvYWRpbmdbaV09bmV3IG4odCk7cy5hYm9ydD10aGlzLmxvYWRWZWN0b3JEYXRhKHQsZnVuY3Rpb24odCxuKXtpZihkZWxldGUgby5sb2FkaW5nW2ldLHR8fCFuKXJldHVybiBzLnN0YXR1cz1cImRvbmVcIixvLmxvYWRlZFtpXT1zLHIodCk7dmFyIHU9bi5yYXdEYXRhLGw9e307bi5leHBpcmVzJiYobC5leHBpcmVzPW4uZXhwaXJlcyksbi5jYWNoZUNvbnRyb2wmJihsLmNhY2hlQ29udHJvbD1uLmNhY2hlQ29udHJvbCk7dmFyIGg9e307aWYoYSl7dmFyIGM9YS5maW5pc2goKTtjJiYoaC5yZXNvdXJjZVRpbWluZz1KU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGMpKSk7fXMudmVjdG9yVGlsZT1uLnZlY3RvclRpbGUscy5wYXJzZShuLnZlY3RvclRpbGUsby5sYXllckluZGV4LG8uYWN0b3IsZnVuY3Rpb24odCxvKXtpZih0fHwhbylyZXR1cm4gcih0KTtyKG51bGwsZS5leHRlbmQoe3Jhd1RpbGVEYXRhOnUuc2xpY2UoMCl9LG8sbCxoKSk7fSksby5sb2FkZWQ9by5sb2FkZWR8fHt9LG8ubG9hZGVkW2ldPXM7fSk7fSxjLnByb3RvdHlwZS5yZWxvYWRUaWxlPWZ1bmN0aW9uKGUsdCl7dmFyIHI9dGhpcy5sb2FkZWQsbz1lLnVpZCxpPXRoaXM7aWYociYmcltvXSl7dmFyIG49cltvXTtuLnNob3dDb2xsaXNpb25Cb3hlcz1lLnNob3dDb2xsaXNpb25Cb3hlczt2YXIgYT1mdW5jdGlvbihlLHIpe3ZhciBvPW4ucmVsb2FkQ2FsbGJhY2s7byYmKGRlbGV0ZSBuLnJlbG9hZENhbGxiYWNrLG4ucGFyc2Uobi52ZWN0b3JUaWxlLGkubGF5ZXJJbmRleCxpLmFjdG9yLG8pKSx0KGUscik7fTtcInBhcnNpbmdcIj09PW4uc3RhdHVzP24ucmVsb2FkQ2FsbGJhY2s9YTpcImRvbmVcIj09PW4uc3RhdHVzJiYobi52ZWN0b3JUaWxlP24ucGFyc2Uobi52ZWN0b3JUaWxlLHRoaXMubGF5ZXJJbmRleCx0aGlzLmFjdG9yLGEpOmEoKSk7fX0sYy5wcm90b3R5cGUuYWJvcnRUaWxlPWZ1bmN0aW9uKGUsdCl7dmFyIHI9dGhpcy5sb2FkaW5nLG89ZS51aWQ7ciYmcltvXSYmcltvXS5hYm9ydCYmKHJbb10uYWJvcnQoKSxkZWxldGUgcltvXSksdCgpO30sYy5wcm90b3R5cGUucmVtb3ZlVGlsZT1mdW5jdGlvbihlLHQpe3ZhciByPXRoaXMubG9hZGVkLG89ZS51aWQ7ciYmcltvXSYmZGVsZXRlIHJbb10sdCgpO307dmFyIHA9ZnVuY3Rpb24oKXt0aGlzLmxvYWRlZD17fTt9O3AucHJvdG90eXBlLmxvYWRUaWxlPWZ1bmN0aW9uKHQscil7dmFyIG89dC51aWQsaT10LmVuY29kaW5nLG49dC5yYXdJbWFnZURhdGEsYT1uZXcgZS5ERU1EYXRhKG8sbixpKTt0aGlzLmxvYWRlZD10aGlzLmxvYWRlZHx8e30sdGhpcy5sb2FkZWRbb109YSxyKG51bGwsYSk7fSxwLnByb3RvdHlwZS5yZW1vdmVUaWxlPWZ1bmN0aW9uKGUpe3ZhciB0PXRoaXMubG9hZGVkLHI9ZS51aWQ7dCYmdFtyXSYmZGVsZXRlIHRbcl07fTt2YXIgZj17UkFESVVTOjYzNzgxMzcsRkxBVFRFTklORzoxLzI5OC4yNTcyMjM1NjMsUE9MQVJfUkFESVVTOjYzNTY3NTIuMzE0Mn07ZnVuY3Rpb24gZChlKXt2YXIgdD0wO2lmKGUmJmUubGVuZ3RoPjApe3QrPU1hdGguYWJzKGcoZVswXSkpO2Zvcih2YXIgcj0xO3I8ZS5sZW5ndGg7cisrKXQtPU1hdGguYWJzKGcoZVtyXSkpO31yZXR1cm4gdH1mdW5jdGlvbiBnKGUpe3ZhciB0LHIsbyxpLG4sYSxzPTAsdT1lLmxlbmd0aDtpZih1PjIpe2ZvcihhPTA7YTx1O2ErKylhPT09dS0yPyhvPXUtMixpPXUtMSxuPTApOmE9PT11LTE/KG89dS0xLGk9MCxuPTEpOihvPWEsaT1hKzEsbj1hKzIpLHQ9ZVtvXSxyPWVbaV0scys9KG0oZVtuXVswXSktbSh0WzBdKSkqTWF0aC5zaW4obShyWzFdKSk7cz1zKmYuUkFESVVTKmYuUkFESVVTLzI7fXJldHVybiBzfWZ1bmN0aW9uIG0oZSl7cmV0dXJuIGUqTWF0aC5QSS8xODB9dmFyIHY9e2dlb21ldHJ5OmZ1bmN0aW9uIGUodCl7dmFyIHIsbz0wO3N3aXRjaCh0LnR5cGUpe2Nhc2VcIlBvbHlnb25cIjpyZXR1cm4gZCh0LmNvb3JkaW5hdGVzKTtjYXNlXCJNdWx0aVBvbHlnb25cIjpmb3Iocj0wO3I8dC5jb29yZGluYXRlcy5sZW5ndGg7cisrKW8rPWQodC5jb29yZGluYXRlc1tyXSk7cmV0dXJuIG87Y2FzZVwiUG9pbnRcIjpjYXNlXCJNdWx0aVBvaW50XCI6Y2FzZVwiTGluZVN0cmluZ1wiOmNhc2VcIk11bHRpTGluZVN0cmluZ1wiOnJldHVybiAwO2Nhc2VcIkdlb21ldHJ5Q29sbGVjdGlvblwiOmZvcihyPTA7cjx0Lmdlb21ldHJpZXMubGVuZ3RoO3IrKylvKz1lKHQuZ2VvbWV0cmllc1tyXSk7cmV0dXJuIG99fSxyaW5nOmd9LHk9ZnVuY3Rpb24gZSh0LHIpe3N3aXRjaCh0JiZ0LnR5cGV8fG51bGwpe2Nhc2VcIkZlYXR1cmVDb2xsZWN0aW9uXCI6cmV0dXJuIHQuZmVhdHVyZXM9dC5mZWF0dXJlcy5tYXAoeChlLHIpKSx0O2Nhc2VcIkdlb21ldHJ5Q29sbGVjdGlvblwiOnJldHVybiB0Lmdlb21ldHJpZXM9dC5nZW9tZXRyaWVzLm1hcCh4KGUscikpLHQ7Y2FzZVwiRmVhdHVyZVwiOnJldHVybiB0Lmdlb21ldHJ5PWUodC5nZW9tZXRyeSxyKSx0O2Nhc2VcIlBvbHlnb25cIjpjYXNlXCJNdWx0aVBvbHlnb25cIjpyZXR1cm4gZnVuY3Rpb24oZSx0KXtcIlBvbHlnb25cIj09PWUudHlwZT9lLmNvb3JkaW5hdGVzPXcoZS5jb29yZGluYXRlcyx0KTpcIk11bHRpUG9seWdvblwiPT09ZS50eXBlJiYoZS5jb29yZGluYXRlcz1lLmNvb3JkaW5hdGVzLm1hcCh4KHcsdCkpKTtyZXR1cm4gZX0odCxyKTtkZWZhdWx0OnJldHVybiB0fX07ZnVuY3Rpb24geChlLHQpe3JldHVybiBmdW5jdGlvbihyKXtyZXR1cm4gZShyLHQpfX1mdW5jdGlvbiB3KGUsdCl7dD0hIXQsZVswXT1TKGVbMF0sdCk7Zm9yKHZhciByPTE7cjxlLmxlbmd0aDtyKyspZVtyXT1TKGVbcl0sIXQpO3JldHVybiBlfWZ1bmN0aW9uIFMoZSx0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHYucmluZyhlKT49MH0oZSk9PT10P2U6ZS5yZXZlcnNlKCl9dmFyIE09ZS52ZWN0b3JUaWxlLlZlY3RvclRpbGVGZWF0dXJlLnByb3RvdHlwZS50b0dlb0pTT04saz1mdW5jdGlvbih0KXt0aGlzLl9mZWF0dXJlPXQsdGhpcy5leHRlbnQ9ZS5FWFRFTlQsdGhpcy50eXBlPXQudHlwZSx0aGlzLnByb3BlcnRpZXM9dC50YWdzLFwiaWRcImluIHQmJiFpc05hTih0LmlkKSYmKHRoaXMuaWQ9cGFyc2VJbnQodC5pZCwxMCkpO307ay5wcm90b3R5cGUubG9hZEdlb21ldHJ5PWZ1bmN0aW9uKCl7aWYoMT09PXRoaXMuX2ZlYXR1cmUudHlwZSl7Zm9yKHZhciB0PVtdLHI9MCxvPXRoaXMuX2ZlYXR1cmUuZ2VvbWV0cnk7cjxvLmxlbmd0aDtyKz0xKXt2YXIgaT1vW3JdO3QucHVzaChbbmV3IGUuUG9pbnQkMShpWzBdLGlbMV0pXSk7fXJldHVybiB0fWZvcih2YXIgbj1bXSxhPTAscz10aGlzLl9mZWF0dXJlLmdlb21ldHJ5O2E8cy5sZW5ndGg7YSs9MSl7Zm9yKHZhciB1PVtdLGw9MCxoPXNbYV07bDxoLmxlbmd0aDtsKz0xKXt2YXIgYz1oW2xdO3UucHVzaChuZXcgZS5Qb2ludCQxKGNbMF0sY1sxXSkpO31uLnB1c2godSk7fXJldHVybiBufSxrLnByb3RvdHlwZS50b0dlb0pTT049ZnVuY3Rpb24oZSx0LHIpe3JldHVybiBNLmNhbGwodGhpcyxlLHQscil9O3ZhciBiPWZ1bmN0aW9uKHQpe3RoaXMubGF5ZXJzPXtfZ2VvanNvblRpbGVMYXllcjp0aGlzfSx0aGlzLm5hbWU9XCJfZ2VvanNvblRpbGVMYXllclwiLHRoaXMuZXh0ZW50PWUuRVhURU5ULHRoaXMubGVuZ3RoPXQubGVuZ3RoLHRoaXMuX2ZlYXR1cmVzPXQ7fTtiLnByb3RvdHlwZS5mZWF0dXJlPWZ1bmN0aW9uKGUpe3JldHVybiBuZXcgayh0aGlzLl9mZWF0dXJlc1tlXSl9O3ZhciBfPWUudmVjdG9yVGlsZS5WZWN0b3JUaWxlRmVhdHVyZSxQPUk7ZnVuY3Rpb24gSShlLHQpe3RoaXMub3B0aW9ucz10fHx7fSx0aGlzLmZlYXR1cmVzPWUsdGhpcy5sZW5ndGg9ZS5sZW5ndGg7fWZ1bmN0aW9uIFQoZSx0KXt0aGlzLmlkPVwibnVtYmVyXCI9PXR5cGVvZiBlLmlkP2UuaWQ6dm9pZCAwLHRoaXMudHlwZT1lLnR5cGUsdGhpcy5yYXdHZW9tZXRyeT0xPT09ZS50eXBlP1tlLmdlb21ldHJ5XTplLmdlb21ldHJ5LHRoaXMucHJvcGVydGllcz1lLnRhZ3MsdGhpcy5leHRlbnQ9dHx8NDA5Njt9SS5wcm90b3R5cGUuZmVhdHVyZT1mdW5jdGlvbihlKXtyZXR1cm4gbmV3IFQodGhpcy5mZWF0dXJlc1tlXSx0aGlzLm9wdGlvbnMuZXh0ZW50KX0sVC5wcm90b3R5cGUubG9hZEdlb21ldHJ5PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yYXdHZW9tZXRyeTt0aGlzLmdlb21ldHJ5PVtdO2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7cisrKXtmb3IodmFyIG89dFtyXSxpPVtdLG49MDtuPG8ubGVuZ3RoO24rKylpLnB1c2gobmV3IGUuUG9pbnQkMShvW25dWzBdLG9bbl1bMV0pKTt0aGlzLmdlb21ldHJ5LnB1c2goaSk7fXJldHVybiB0aGlzLmdlb21ldHJ5fSxULnByb3RvdHlwZS5iYm94PWZ1bmN0aW9uKCl7dGhpcy5nZW9tZXRyeXx8dGhpcy5sb2FkR2VvbWV0cnkoKTtmb3IodmFyIGU9dGhpcy5nZW9tZXRyeSx0PTEvMCxyPS0xLzAsbz0xLzAsaT0tMS8wLG49MDtuPGUubGVuZ3RoO24rKylmb3IodmFyIGE9ZVtuXSxzPTA7czxhLmxlbmd0aDtzKyspe3ZhciB1PWFbc107dD1NYXRoLm1pbih0LHUueCkscj1NYXRoLm1heChyLHUueCksbz1NYXRoLm1pbihvLHUueSksaT1NYXRoLm1heChpLHUueSk7fXJldHVybiBbdCxvLHIsaV19LFQucHJvdG90eXBlLnRvR2VvSlNPTj1fLnByb3RvdHlwZS50b0dlb0pTT047dmFyIEw9TyxEPU8sQz1mdW5jdGlvbihlLHQpe3Q9dHx8e307dmFyIHI9e307Zm9yKHZhciBvIGluIGUpcltvXT1uZXcgUChlW29dLmZlYXR1cmVzLHQpLHJbb10ubmFtZT1vLHJbb10udmVyc2lvbj10LnZlcnNpb24scltvXS5leHRlbnQ9dC5leHRlbnQ7cmV0dXJuIE8oe2xheWVyczpyfSl9LHo9UDtmdW5jdGlvbiBPKHQpe3ZhciByPW5ldyBlLnBiZjtyZXR1cm4gZnVuY3Rpb24oZSx0KXtmb3IodmFyIHIgaW4gZS5sYXllcnMpdC53cml0ZU1lc3NhZ2UoMyxFLGUubGF5ZXJzW3JdKTt9KHQsciksci5maW5pc2goKX1mdW5jdGlvbiBFKGUsdCl7dmFyIHI7dC53cml0ZVZhcmludEZpZWxkKDE1LGUudmVyc2lvbnx8MSksdC53cml0ZVN0cmluZ0ZpZWxkKDEsZS5uYW1lfHxcIlwiKSx0LndyaXRlVmFyaW50RmllbGQoNSxlLmV4dGVudHx8NDA5Nik7dmFyIG89e2tleXM6W10sdmFsdWVzOltdLGtleWNhY2hlOnt9LHZhbHVlY2FjaGU6e319O2ZvcihyPTA7cjxlLmxlbmd0aDtyKyspby5mZWF0dXJlPWUuZmVhdHVyZShyKSx0LndyaXRlTWVzc2FnZSgyLE4sbyk7dmFyIGk9by5rZXlzO2ZvcihyPTA7cjxpLmxlbmd0aDtyKyspdC53cml0ZVN0cmluZ0ZpZWxkKDMsaVtyXSk7dmFyIG49by52YWx1ZXM7Zm9yKHI9MDtyPG4ubGVuZ3RoO3IrKyl0LndyaXRlTWVzc2FnZSg0LEcsbltyXSk7fWZ1bmN0aW9uIE4oZSx0KXt2YXIgcj1lLmZlYXR1cmU7dm9pZCAwIT09ci5pZCYmdC53cml0ZVZhcmludEZpZWxkKDEsci5pZCksdC53cml0ZU1lc3NhZ2UoMixGLGUpLHQud3JpdGVWYXJpbnRGaWVsZCgzLHIudHlwZSksdC53cml0ZU1lc3NhZ2UoNCxKLHIpO31mdW5jdGlvbiBGKGUsdCl7dmFyIHI9ZS5mZWF0dXJlLG89ZS5rZXlzLGk9ZS52YWx1ZXMsbj1lLmtleWNhY2hlLGE9ZS52YWx1ZWNhY2hlO2Zvcih2YXIgcyBpbiByLnByb3BlcnRpZXMpe3ZhciB1PW5bc107dm9pZCAwPT09dSYmKG8ucHVzaChzKSx1PW8ubGVuZ3RoLTEsbltzXT11KSx0LndyaXRlVmFyaW50KHUpO3ZhciBsPXIucHJvcGVydGllc1tzXSxoPXR5cGVvZiBsO1wic3RyaW5nXCIhPT1oJiZcImJvb2xlYW5cIiE9PWgmJlwibnVtYmVyXCIhPT1oJiYobD1KU09OLnN0cmluZ2lmeShsKSk7dmFyIGM9aCtcIjpcIitsLHA9YVtjXTt2b2lkIDA9PT1wJiYoaS5wdXNoKGwpLHA9aS5sZW5ndGgtMSxhW2NdPXApLHQud3JpdGVWYXJpbnQocCk7fX1mdW5jdGlvbiBBKGUsdCl7cmV0dXJuICh0PDwzKSsoNyZlKX1mdW5jdGlvbiBCKGUpe3JldHVybiBlPDwxXmU+PjMxfWZ1bmN0aW9uIEooZSx0KXtmb3IodmFyIHI9ZS5sb2FkR2VvbWV0cnkoKSxvPWUudHlwZSxpPTAsbj0wLGE9ci5sZW5ndGgscz0wO3M8YTtzKyspe3ZhciB1PXJbc10sbD0xOzE9PT1vJiYobD11Lmxlbmd0aCksdC53cml0ZVZhcmludChBKDEsbCkpO2Zvcih2YXIgaD0zPT09bz91Lmxlbmd0aC0xOnUubGVuZ3RoLGM9MDtjPGg7YysrKXsxPT09YyYmMSE9PW8mJnQud3JpdGVWYXJpbnQoQSgyLGgtMSkpO3ZhciBwPXVbY10ueC1pLGY9dVtjXS55LW47dC53cml0ZVZhcmludChCKHApKSx0LndyaXRlVmFyaW50KEIoZikpLGkrPXAsbis9Zjt9Mz09PW8mJnQud3JpdGVWYXJpbnQoQSg3LDEpKTt9fWZ1bmN0aW9uIEcoZSx0KXt2YXIgcj10eXBlb2YgZTtcInN0cmluZ1wiPT09cj90LndyaXRlU3RyaW5nRmllbGQoMSxlKTpcImJvb2xlYW5cIj09PXI/dC53cml0ZUJvb2xlYW5GaWVsZCg3LGUpOlwibnVtYmVyXCI9PT1yJiYoZSUxIT0wP3Qud3JpdGVEb3VibGVGaWVsZCgzLGUpOmU8MD90LndyaXRlU1ZhcmludEZpZWxkKDYsZSk6dC53cml0ZVZhcmludEZpZWxkKDUsZSkpO31mdW5jdGlvbiBaKGUsdCxyLG8saSxuKXtpZighKGktbzw9cikpe3ZhciBhPW8raT4+MTshZnVuY3Rpb24gZSh0LHIsbyxpLG4sYSl7Zm9yKDtuPmk7KXtpZihuLWk+NjAwKXt2YXIgcz1uLWkrMSx1PW8taSsxLGw9TWF0aC5sb2cocyksaD0uNSpNYXRoLmV4cCgyKmwvMyksYz0uNSpNYXRoLnNxcnQobCpoKihzLWgpL3MpKih1LXMvMjwwPy0xOjEpLHA9TWF0aC5tYXgoaSxNYXRoLmZsb29yKG8tdSpoL3MrYykpLGY9TWF0aC5taW4obixNYXRoLmZsb29yKG8rKHMtdSkqaC9zK2MpKTtlKHQscixvLHAsZixhKTt9dmFyIGQ9clsyKm8rYV0sZz1pLG09bjtmb3Ioaih0LHIsaSxvKSxyWzIqbithXT5kJiZqKHQscixpLG4pO2c8bTspe2ZvcihqKHQscixnLG0pLGcrKyxtLS07clsyKmcrYV08ZDspZysrO2Zvcig7clsyKm0rYV0+ZDspbS0tO31yWzIqaSthXT09PWQ/aih0LHIsaSxtKTpqKHQsciwrK20sbiksbTw9byYmKGk9bSsxKSxvPD1tJiYobj1tLTEpO319KGUsdCxhLG8saSxuJTIpLFooZSx0LHIsbyxhLTEsbisxKSxaKGUsdCxyLGErMSxpLG4rMSk7fX1mdW5jdGlvbiBqKGUsdCxyLG8pe1koZSxyLG8pLFkodCwyKnIsMipvKSxZKHQsMipyKzEsMipvKzEpO31mdW5jdGlvbiBZKGUsdCxyKXt2YXIgbz1lW3RdO2VbdF09ZVtyXSxlW3JdPW87fWZ1bmN0aW9uIFYoZSx0LHIsbyl7dmFyIGk9ZS1yLG49dC1vO3JldHVybiBpKmkrbipufUwuZnJvbVZlY3RvclRpbGVKcz1ELEwuZnJvbUdlb2pzb25WdD1DLEwuR2VvSlNPTldyYXBwZXI9ejt2YXIgWD1mdW5jdGlvbihlKXtyZXR1cm4gZVswXX0sVz1mdW5jdGlvbihlKXtyZXR1cm4gZVsxXX0sUj1mdW5jdGlvbihlLHQscixvLGkpe3ZvaWQgMD09PXQmJih0PVgpLHZvaWQgMD09PXImJihyPVcpLHZvaWQgMD09PW8mJihvPTY0KSx2b2lkIDA9PT1pJiYoaT1GbG9hdDY0QXJyYXkpLHRoaXMubm9kZVNpemU9byx0aGlzLnBvaW50cz1lO2Zvcih2YXIgbj1lLmxlbmd0aDw2NTUzNj9VaW50MTZBcnJheTpVaW50MzJBcnJheSxhPXRoaXMuaWRzPW5ldyBuKGUubGVuZ3RoKSxzPXRoaXMuY29vcmRzPW5ldyBpKDIqZS5sZW5ndGgpLHU9MDt1PGUubGVuZ3RoO3UrKylhW3VdPXUsc1syKnVdPXQoZVt1XSksc1syKnUrMV09cihlW3VdKTtaKGEscyxvLDAsYS5sZW5ndGgtMSwwKTt9O1IucHJvdG90eXBlLnJhbmdlPWZ1bmN0aW9uKGUsdCxyLG8pe3JldHVybiBmdW5jdGlvbihlLHQscixvLGksbixhKXtmb3IodmFyIHMsdSxsPVswLGUubGVuZ3RoLTEsMF0saD1bXTtsLmxlbmd0aDspe3ZhciBjPWwucG9wKCkscD1sLnBvcCgpLGY9bC5wb3AoKTtpZihwLWY8PWEpZm9yKHZhciBkPWY7ZDw9cDtkKyspcz10WzIqZF0sdT10WzIqZCsxXSxzPj1yJiZzPD1pJiZ1Pj1vJiZ1PD1uJiZoLnB1c2goZVtkXSk7ZWxzZXt2YXIgZz1NYXRoLmZsb29yKChmK3ApLzIpO3M9dFsyKmddLHU9dFsyKmcrMV0scz49ciYmczw9aSYmdT49byYmdTw9biYmaC5wdXNoKGVbZ10pO3ZhciBtPShjKzEpJTI7KDA9PT1jP3I8PXM6bzw9dSkmJihsLnB1c2goZiksbC5wdXNoKGctMSksbC5wdXNoKG0pKSwoMD09PWM/aT49czpuPj11KSYmKGwucHVzaChnKzEpLGwucHVzaChwKSxsLnB1c2gobSkpO319cmV0dXJuIGh9KHRoaXMuaWRzLHRoaXMuY29vcmRzLGUsdCxyLG8sdGhpcy5ub2RlU2l6ZSl9LFIucHJvdG90eXBlLndpdGhpbj1mdW5jdGlvbihlLHQscil7cmV0dXJuIGZ1bmN0aW9uKGUsdCxyLG8saSxuKXtmb3IodmFyIGE9WzAsZS5sZW5ndGgtMSwwXSxzPVtdLHU9aSppO2EubGVuZ3RoOyl7dmFyIGw9YS5wb3AoKSxoPWEucG9wKCksYz1hLnBvcCgpO2lmKGgtYzw9bilmb3IodmFyIHA9YztwPD1oO3ArKylWKHRbMipwXSx0WzIqcCsxXSxyLG8pPD11JiZzLnB1c2goZVtwXSk7ZWxzZXt2YXIgZj1NYXRoLmZsb29yKChjK2gpLzIpLGQ9dFsyKmZdLGc9dFsyKmYrMV07VihkLGcscixvKTw9dSYmcy5wdXNoKGVbZl0pO3ZhciBtPShsKzEpJTI7KDA9PT1sP3ItaTw9ZDpvLWk8PWcpJiYoYS5wdXNoKGMpLGEucHVzaChmLTEpLGEucHVzaChtKSksKDA9PT1sP3IraT49ZDpvK2k+PWcpJiYoYS5wdXNoKGYrMSksYS5wdXNoKGgpLGEucHVzaChtKSk7fX1yZXR1cm4gc30odGhpcy5pZHMsdGhpcy5jb29yZHMsZSx0LHIsdGhpcy5ub2RlU2l6ZSl9O3ZhciBxPXttaW5ab29tOjAsbWF4Wm9vbToxNixyYWRpdXM6NDAsZXh0ZW50OjUxMixub2RlU2l6ZTo2NCxsb2c6ITEscmVkdWNlOm51bGwsbWFwOmZ1bmN0aW9uKGUpe3JldHVybiBlfX0sVT1mdW5jdGlvbihlKXt0aGlzLm9wdGlvbnM9cmUoT2JqZWN0LmNyZWF0ZShxKSxlKSx0aGlzLnRyZWVzPW5ldyBBcnJheSh0aGlzLm9wdGlvbnMubWF4Wm9vbSsxKTt9O2Z1bmN0aW9uICQoZSx0LHIsbyxpKXtyZXR1cm4ge3g6ZSx5OnQsem9vbToxLzAsaWQ6cixwYXJlbnRJZDotMSxudW1Qb2ludHM6byxwcm9wZXJ0aWVzOml9fWZ1bmN0aW9uIEgoZSx0KXt2YXIgcj1lLmdlb21ldHJ5LmNvb3JkaW5hdGVzLG89clswXSxpPXJbMV07cmV0dXJuIHt4OmVlKG8pLHk6dGUoaSksem9vbToxLzAsaW5kZXg6dCxwYXJlbnRJZDotMX19ZnVuY3Rpb24gSyhlKXtyZXR1cm4ge3R5cGU6XCJGZWF0dXJlXCIsaWQ6ZS5pZCxwcm9wZXJ0aWVzOlEoZSksZ2VvbWV0cnk6e3R5cGU6XCJQb2ludFwiLGNvb3JkaW5hdGVzOlsobz1lLngsMzYwKihvLS41KSksKHQ9ZS55LHI9KDE4MC0zNjAqdCkqTWF0aC5QSS8xODAsMzYwKk1hdGguYXRhbihNYXRoLmV4cChyKSkvTWF0aC5QSS05MCldfX07dmFyIHQscixvO31mdW5jdGlvbiBRKGUpe3ZhciB0PWUubnVtUG9pbnRzLHI9dD49MWU0P01hdGgucm91bmQodC8xZTMpK1wia1wiOnQ+PTFlMz9NYXRoLnJvdW5kKHQvMTAwKS8xMCtcImtcIjp0O3JldHVybiByZShyZSh7fSxlLnByb3BlcnRpZXMpLHtjbHVzdGVyOiEwLGNsdXN0ZXJfaWQ6ZS5pZCxwb2ludF9jb3VudDp0LHBvaW50X2NvdW50X2FiYnJldmlhdGVkOnJ9KX1mdW5jdGlvbiBlZShlKXtyZXR1cm4gZS8zNjArLjV9ZnVuY3Rpb24gdGUoZSl7dmFyIHQ9TWF0aC5zaW4oZSpNYXRoLlBJLzE4MCkscj0uNS0uMjUqTWF0aC5sb2coKDErdCkvKDEtdCkpL01hdGguUEk7cmV0dXJuIHI8MD8wOnI+MT8xOnJ9ZnVuY3Rpb24gcmUoZSx0KXtmb3IodmFyIHIgaW4gdCllW3JdPXRbcl07cmV0dXJuIGV9ZnVuY3Rpb24gb2UoZSl7cmV0dXJuIGUueH1mdW5jdGlvbiBpZShlKXtyZXR1cm4gZS55fWZ1bmN0aW9uIG5lKGUsdCxyLG8saSxuKXt2YXIgYT1pLXIscz1uLW87aWYoMCE9PWF8fDAhPT1zKXt2YXIgdT0oKGUtcikqYSsodC1vKSpzKS8oYSphK3Mqcyk7dT4xPyhyPWksbz1uKTp1PjAmJihyKz1hKnUsbys9cyp1KTt9cmV0dXJuIChhPWUtcikqYSsocz10LW8pKnN9ZnVuY3Rpb24gYWUoZSx0LHIsbyl7dmFyIGk9e2lkOnZvaWQgMD09PWU/bnVsbDplLHR5cGU6dCxnZW9tZXRyeTpyLHRhZ3M6byxtaW5YOjEvMCxtaW5ZOjEvMCxtYXhYOi0xLzAsbWF4WTotMS8wfTtyZXR1cm4gZnVuY3Rpb24oZSl7dmFyIHQ9ZS5nZW9tZXRyeSxyPWUudHlwZTtpZihcIlBvaW50XCI9PT1yfHxcIk11bHRpUG9pbnRcIj09PXJ8fFwiTGluZVN0cmluZ1wiPT09cilzZShlLHQpO2Vsc2UgaWYoXCJQb2x5Z29uXCI9PT1yfHxcIk11bHRpTGluZVN0cmluZ1wiPT09cilmb3IodmFyIG89MDtvPHQubGVuZ3RoO28rKylzZShlLHRbb10pO2Vsc2UgaWYoXCJNdWx0aVBvbHlnb25cIj09PXIpZm9yKG89MDtvPHQubGVuZ3RoO28rKylmb3IodmFyIGk9MDtpPHRbb10ubGVuZ3RoO2krKylzZShlLHRbb11baV0pO30oaSksaX1mdW5jdGlvbiBzZShlLHQpe2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7cis9MyllLm1pblg9TWF0aC5taW4oZS5taW5YLHRbcl0pLGUubWluWT1NYXRoLm1pbihlLm1pblksdFtyKzFdKSxlLm1heFg9TWF0aC5tYXgoZS5tYXhYLHRbcl0pLGUubWF4WT1NYXRoLm1heChlLm1heFksdFtyKzFdKTt9ZnVuY3Rpb24gdWUoZSx0LHIsbyl7aWYodC5nZW9tZXRyeSl7dmFyIGk9dC5nZW9tZXRyeS5jb29yZGluYXRlcyxuPXQuZ2VvbWV0cnkudHlwZSxhPU1hdGgucG93KHIudG9sZXJhbmNlLygoMTw8ci5tYXhab29tKSpyLmV4dGVudCksMikscz1bXSx1PXQuaWQ7aWYoci5wcm9tb3RlSWQ/dT10LnByb3BlcnRpZXNbci5wcm9tb3RlSWRdOnIuZ2VuZXJhdGVJZCYmKHU9b3x8MCksXCJQb2ludFwiPT09bilsZShpLHMpO2Vsc2UgaWYoXCJNdWx0aVBvaW50XCI9PT1uKWZvcih2YXIgbD0wO2w8aS5sZW5ndGg7bCsrKWxlKGlbbF0scyk7ZWxzZSBpZihcIkxpbmVTdHJpbmdcIj09PW4paGUoaSxzLGEsITEpO2Vsc2UgaWYoXCJNdWx0aUxpbmVTdHJpbmdcIj09PW4pe2lmKHIubGluZU1ldHJpY3Mpe2ZvcihsPTA7bDxpLmxlbmd0aDtsKyspcz1bXSxoZShpW2xdLHMsYSwhMSksZS5wdXNoKGFlKHUsXCJMaW5lU3RyaW5nXCIscyx0LnByb3BlcnRpZXMpKTtyZXR1cm59Y2UoaSxzLGEsITEpO31lbHNlIGlmKFwiUG9seWdvblwiPT09biljZShpLHMsYSwhMCk7ZWxzZXtpZihcIk11bHRpUG9seWdvblwiIT09bil7aWYoXCJHZW9tZXRyeUNvbGxlY3Rpb25cIj09PW4pe2ZvcihsPTA7bDx0Lmdlb21ldHJ5Lmdlb21ldHJpZXMubGVuZ3RoO2wrKyl1ZShlLHtpZDp1LGdlb21ldHJ5OnQuZ2VvbWV0cnkuZ2VvbWV0cmllc1tsXSxwcm9wZXJ0aWVzOnQucHJvcGVydGllc30scixvKTtyZXR1cm59dGhyb3cgbmV3IEVycm9yKFwiSW5wdXQgZGF0YSBpcyBub3QgYSB2YWxpZCBHZW9KU09OIG9iamVjdC5cIil9Zm9yKGw9MDtsPGkubGVuZ3RoO2wrKyl7dmFyIGg9W107Y2UoaVtsXSxoLGEsITApLHMucHVzaChoKTt9fWUucHVzaChhZSh1LG4scyx0LnByb3BlcnRpZXMpKTt9fWZ1bmN0aW9uIGxlKGUsdCl7dC5wdXNoKHBlKGVbMF0pKSx0LnB1c2goZmUoZVsxXSkpLHQucHVzaCgwKTt9ZnVuY3Rpb24gaGUoZSx0LHIsbyl7Zm9yKHZhciBpLG4sYT0wLHM9MDtzPGUubGVuZ3RoO3MrKyl7dmFyIHU9cGUoZVtzXVswXSksbD1mZShlW3NdWzFdKTt0LnB1c2godSksdC5wdXNoKGwpLHQucHVzaCgwKSxzPjAmJihhKz1vPyhpKmwtdSpuKS8yOk1hdGguc3FydChNYXRoLnBvdyh1LWksMikrTWF0aC5wb3cobC1uLDIpKSksaT11LG49bDt9dmFyIGg9dC5sZW5ndGgtMzt0WzJdPTEsZnVuY3Rpb24gZSh0LHIsbyxpKXtmb3IodmFyIG4sYT1pLHM9by1yPj4xLHU9by1yLGw9dFtyXSxoPXRbcisxXSxjPXRbb10scD10W28rMV0sZj1yKzM7ZjxvO2YrPTMpe3ZhciBkPW5lKHRbZl0sdFtmKzFdLGwsaCxjLHApO2lmKGQ+YSluPWYsYT1kO2Vsc2UgaWYoZD09PWEpe3ZhciBnPU1hdGguYWJzKGYtcyk7Zzx1JiYobj1mLHU9Zyk7fX1hPmkmJihuLXI+MyYmZSh0LHIsbixpKSx0W24rMl09YSxvLW4+MyYmZSh0LG4sbyxpKSk7fSh0LDAsaCxyKSx0W2grMl09MSx0LnNpemU9TWF0aC5hYnMoYSksdC5zdGFydD0wLHQuZW5kPXQuc2l6ZTt9ZnVuY3Rpb24gY2UoZSx0LHIsbyl7Zm9yKHZhciBpPTA7aTxlLmxlbmd0aDtpKyspe3ZhciBuPVtdO2hlKGVbaV0sbixyLG8pLHQucHVzaChuKTt9fWZ1bmN0aW9uIHBlKGUpe3JldHVybiBlLzM2MCsuNX1mdW5jdGlvbiBmZShlKXt2YXIgdD1NYXRoLnNpbihlKk1hdGguUEkvMTgwKSxyPS41LS4yNSpNYXRoLmxvZygoMSt0KS8oMS10KSkvTWF0aC5QSTtyZXR1cm4gcjwwPzA6cj4xPzE6cn1mdW5jdGlvbiBkZShlLHQscixvLGksbixhLHMpe2lmKG8vPXQsbj49KHIvPXQpJiZhPG8pcmV0dXJuIGU7aWYoYTxyfHxuPj1vKXJldHVybiBudWxsO2Zvcih2YXIgdT1bXSxsPTA7bDxlLmxlbmd0aDtsKyspe3ZhciBoPWVbbF0sYz1oLmdlb21ldHJ5LHA9aC50eXBlLGY9MD09PWk/aC5taW5YOmgubWluWSxkPTA9PT1pP2gubWF4WDpoLm1heFk7aWYoZj49ciYmZDxvKXUucHVzaChoKTtlbHNlIGlmKCEoZDxyfHxmPj1vKSl7dmFyIGc9W107aWYoXCJQb2ludFwiPT09cHx8XCJNdWx0aVBvaW50XCI9PT1wKWdlKGMsZyxyLG8saSk7ZWxzZSBpZihcIkxpbmVTdHJpbmdcIj09PXApbWUoYyxnLHIsbyxpLCExLHMubGluZU1ldHJpY3MpO2Vsc2UgaWYoXCJNdWx0aUxpbmVTdHJpbmdcIj09PXApeWUoYyxnLHIsbyxpLCExKTtlbHNlIGlmKFwiUG9seWdvblwiPT09cCl5ZShjLGcscixvLGksITApO2Vsc2UgaWYoXCJNdWx0aVBvbHlnb25cIj09PXApZm9yKHZhciBtPTA7bTxjLmxlbmd0aDttKyspe3ZhciB2PVtdO3llKGNbbV0sdixyLG8saSwhMCksdi5sZW5ndGgmJmcucHVzaCh2KTt9aWYoZy5sZW5ndGgpe2lmKHMubGluZU1ldHJpY3MmJlwiTGluZVN0cmluZ1wiPT09cCl7Zm9yKG09MDttPGcubGVuZ3RoO20rKyl1LnB1c2goYWUoaC5pZCxwLGdbbV0saC50YWdzKSk7Y29udGludWV9XCJMaW5lU3RyaW5nXCIhPT1wJiZcIk11bHRpTGluZVN0cmluZ1wiIT09cHx8KDE9PT1nLmxlbmd0aD8ocD1cIkxpbmVTdHJpbmdcIixnPWdbMF0pOnA9XCJNdWx0aUxpbmVTdHJpbmdcIiksXCJQb2ludFwiIT09cCYmXCJNdWx0aVBvaW50XCIhPT1wfHwocD0zPT09Zy5sZW5ndGg/XCJQb2ludFwiOlwiTXVsdGlQb2ludFwiKSx1LnB1c2goYWUoaC5pZCxwLGcsaC50YWdzKSk7fX19cmV0dXJuIHUubGVuZ3RoP3U6bnVsbH1mdW5jdGlvbiBnZShlLHQscixvLGkpe2Zvcih2YXIgbj0wO248ZS5sZW5ndGg7bis9Myl7dmFyIGE9ZVtuK2ldO2E+PXImJmE8PW8mJih0LnB1c2goZVtuXSksdC5wdXNoKGVbbisxXSksdC5wdXNoKGVbbisyXSkpO319ZnVuY3Rpb24gbWUoZSx0LHIsbyxpLG4sYSl7Zm9yKHZhciBzLHUsbD12ZShlKSxoPTA9PT1pP3dlOlNlLGM9ZS5zdGFydCxwPTA7cDxlLmxlbmd0aC0zO3ArPTMpe3ZhciBmPWVbcF0sZD1lW3ArMV0sZz1lW3ArMl0sbT1lW3ArM10sdj1lW3ArNF0seT0wPT09aT9mOmQseD0wPT09aT9tOnYsdz0hMTthJiYocz1NYXRoLnNxcnQoTWF0aC5wb3coZi1tLDIpK01hdGgucG93KGQtdiwyKSkpLHk8cj94PnImJih1PWgobCxmLGQsbSx2LHIpLGEmJihsLnN0YXJ0PWMrcyp1KSk6eT5vP3g8byYmKHU9aChsLGYsZCxtLHYsbyksYSYmKGwuc3RhcnQ9YytzKnUpKTp4ZShsLGYsZCxnKSx4PHImJnk+PXImJih1PWgobCxmLGQsbSx2LHIpLHc9ITApLHg+byYmeTw9byYmKHU9aChsLGYsZCxtLHYsbyksdz0hMCksIW4mJncmJihhJiYobC5lbmQ9YytzKnUpLHQucHVzaChsKSxsPXZlKGUpKSxhJiYoYys9cyk7fXZhciBTPWUubGVuZ3RoLTM7Zj1lW1NdLGQ9ZVtTKzFdLGc9ZVtTKzJdLCh5PTA9PT1pP2Y6ZCk+PXImJnk8PW8mJnhlKGwsZixkLGcpLFM9bC5sZW5ndGgtMyxuJiZTPj0zJiYobFtTXSE9PWxbMF18fGxbUysxXSE9PWxbMV0pJiZ4ZShsLGxbMF0sbFsxXSxsWzJdKSxsLmxlbmd0aCYmdC5wdXNoKGwpO31mdW5jdGlvbiB2ZShlKXt2YXIgdD1bXTtyZXR1cm4gdC5zaXplPWUuc2l6ZSx0LnN0YXJ0PWUuc3RhcnQsdC5lbmQ9ZS5lbmQsdH1mdW5jdGlvbiB5ZShlLHQscixvLGksbil7Zm9yKHZhciBhPTA7YTxlLmxlbmd0aDthKyspbWUoZVthXSx0LHIsbyxpLG4sITEpO31mdW5jdGlvbiB4ZShlLHQscixvKXtlLnB1c2godCksZS5wdXNoKHIpLGUucHVzaChvKTt9ZnVuY3Rpb24gd2UoZSx0LHIsbyxpLG4pe3ZhciBhPShuLXQpLyhvLXQpO3JldHVybiBlLnB1c2gobiksZS5wdXNoKHIrKGktcikqYSksZS5wdXNoKDEpLGF9ZnVuY3Rpb24gU2UoZSx0LHIsbyxpLG4pe3ZhciBhPShuLXIpLyhpLXIpO3JldHVybiBlLnB1c2godCsoby10KSphKSxlLnB1c2gobiksZS5wdXNoKDEpLGF9ZnVuY3Rpb24gTWUoZSx0KXtmb3IodmFyIHI9W10sbz0wO288ZS5sZW5ndGg7bysrKXt2YXIgaSxuPWVbb10sYT1uLnR5cGU7aWYoXCJQb2ludFwiPT09YXx8XCJNdWx0aVBvaW50XCI9PT1hfHxcIkxpbmVTdHJpbmdcIj09PWEpaT1rZShuLmdlb21ldHJ5LHQpO2Vsc2UgaWYoXCJNdWx0aUxpbmVTdHJpbmdcIj09PWF8fFwiUG9seWdvblwiPT09YSl7aT1bXTtmb3IodmFyIHM9MDtzPG4uZ2VvbWV0cnkubGVuZ3RoO3MrKylpLnB1c2goa2Uobi5nZW9tZXRyeVtzXSx0KSk7fWVsc2UgaWYoXCJNdWx0aVBvbHlnb25cIj09PWEpZm9yKGk9W10scz0wO3M8bi5nZW9tZXRyeS5sZW5ndGg7cysrKXtmb3IodmFyIHU9W10sbD0wO2w8bi5nZW9tZXRyeVtzXS5sZW5ndGg7bCsrKXUucHVzaChrZShuLmdlb21ldHJ5W3NdW2xdLHQpKTtpLnB1c2godSk7fXIucHVzaChhZShuLmlkLGEsaSxuLnRhZ3MpKTt9cmV0dXJuIHJ9ZnVuY3Rpb24ga2UoZSx0KXt2YXIgcj1bXTtyLnNpemU9ZS5zaXplLHZvaWQgMCE9PWUuc3RhcnQmJihyLnN0YXJ0PWUuc3RhcnQsci5lbmQ9ZS5lbmQpO2Zvcih2YXIgbz0wO288ZS5sZW5ndGg7bys9MylyLnB1c2goZVtvXSt0LGVbbysxXSxlW28rMl0pO3JldHVybiByfWZ1bmN0aW9uIGJlKGUsdCl7aWYoZS50cmFuc2Zvcm1lZClyZXR1cm4gZTt2YXIgcixvLGksbj0xPDxlLnosYT1lLngscz1lLnk7Zm9yKHI9MDtyPGUuZmVhdHVyZXMubGVuZ3RoO3IrKyl7dmFyIHU9ZS5mZWF0dXJlc1tyXSxsPXUuZ2VvbWV0cnksaD11LnR5cGU7aWYodS5nZW9tZXRyeT1bXSwxPT09aClmb3Iobz0wO288bC5sZW5ndGg7bys9Mil1Lmdlb21ldHJ5LnB1c2goX2UobFtvXSxsW28rMV0sdCxuLGEscykpO2Vsc2UgZm9yKG89MDtvPGwubGVuZ3RoO28rKyl7dmFyIGM9W107Zm9yKGk9MDtpPGxbb10ubGVuZ3RoO2krPTIpYy5wdXNoKF9lKGxbb11baV0sbFtvXVtpKzFdLHQsbixhLHMpKTt1Lmdlb21ldHJ5LnB1c2goYyk7fX1yZXR1cm4gZS50cmFuc2Zvcm1lZD0hMCxlfWZ1bmN0aW9uIF9lKGUsdCxyLG8saSxuKXtyZXR1cm4gW01hdGgucm91bmQociooZSpvLWkpKSxNYXRoLnJvdW5kKHIqKHQqby1uKSldfWZ1bmN0aW9uIFBlKGUsdCxyLG8saSl7Zm9yKHZhciBuPXQ9PT1pLm1heFpvb20/MDppLnRvbGVyYW5jZS8oKDE8PHQpKmkuZXh0ZW50KSxhPXtmZWF0dXJlczpbXSxudW1Qb2ludHM6MCxudW1TaW1wbGlmaWVkOjAsbnVtRmVhdHVyZXM6MCxzb3VyY2U6bnVsbCx4OnIseTpvLHo6dCx0cmFuc2Zvcm1lZDohMSxtaW5YOjIsbWluWToxLG1heFg6LTEsbWF4WTowfSxzPTA7czxlLmxlbmd0aDtzKyspe2EubnVtRmVhdHVyZXMrKyxJZShhLGVbc10sbixpKTt2YXIgdT1lW3NdLm1pblgsbD1lW3NdLm1pblksaD1lW3NdLm1heFgsYz1lW3NdLm1heFk7dTxhLm1pblgmJihhLm1pblg9dSksbDxhLm1pblkmJihhLm1pblk9bCksaD5hLm1heFgmJihhLm1heFg9aCksYz5hLm1heFkmJihhLm1heFk9Yyk7fXJldHVybiBhfWZ1bmN0aW9uIEllKGUsdCxyLG8pe3ZhciBpPXQuZ2VvbWV0cnksbj10LnR5cGUsYT1bXTtpZihcIlBvaW50XCI9PT1ufHxcIk11bHRpUG9pbnRcIj09PW4pZm9yKHZhciBzPTA7czxpLmxlbmd0aDtzKz0zKWEucHVzaChpW3NdKSxhLnB1c2goaVtzKzFdKSxlLm51bVBvaW50cysrLGUubnVtU2ltcGxpZmllZCsrO2Vsc2UgaWYoXCJMaW5lU3RyaW5nXCI9PT1uKVRlKGEsaSxlLHIsITEsITEpO2Vsc2UgaWYoXCJNdWx0aUxpbmVTdHJpbmdcIj09PW58fFwiUG9seWdvblwiPT09bilmb3Iocz0wO3M8aS5sZW5ndGg7cysrKVRlKGEsaVtzXSxlLHIsXCJQb2x5Z29uXCI9PT1uLDA9PT1zKTtlbHNlIGlmKFwiTXVsdGlQb2x5Z29uXCI9PT1uKWZvcih2YXIgdT0wO3U8aS5sZW5ndGg7dSsrKXt2YXIgbD1pW3VdO2ZvcihzPTA7czxsLmxlbmd0aDtzKyspVGUoYSxsW3NdLGUsciwhMCwwPT09cyk7fWlmKGEubGVuZ3RoKXt2YXIgaD10LnRhZ3N8fG51bGw7aWYoXCJMaW5lU3RyaW5nXCI9PT1uJiZvLmxpbmVNZXRyaWNzKXtmb3IodmFyIGMgaW4gaD17fSx0LnRhZ3MpaFtjXT10LnRhZ3NbY107aC5tYXBib3hfY2xpcF9zdGFydD1pLnN0YXJ0L2kuc2l6ZSxoLm1hcGJveF9jbGlwX2VuZD1pLmVuZC9pLnNpemU7fXZhciBwPXtnZW9tZXRyeTphLHR5cGU6XCJQb2x5Z29uXCI9PT1ufHxcIk11bHRpUG9seWdvblwiPT09bj8zOlwiTGluZVN0cmluZ1wiPT09bnx8XCJNdWx0aUxpbmVTdHJpbmdcIj09PW4/MjoxLHRhZ3M6aH07bnVsbCE9PXQuaWQmJihwLmlkPXQuaWQpLGUuZmVhdHVyZXMucHVzaChwKTt9fWZ1bmN0aW9uIFRlKGUsdCxyLG8saSxuKXt2YXIgYT1vKm87aWYobz4wJiZ0LnNpemU8KGk/YTpvKSlyLm51bVBvaW50cys9dC5sZW5ndGgvMztlbHNle2Zvcih2YXIgcz1bXSx1PTA7dTx0Lmxlbmd0aDt1Kz0zKSgwPT09b3x8dFt1KzJdPmEpJiYoci5udW1TaW1wbGlmaWVkKysscy5wdXNoKHRbdV0pLHMucHVzaCh0W3UrMV0pKSxyLm51bVBvaW50cysrO2kmJmZ1bmN0aW9uKGUsdCl7Zm9yKHZhciByPTAsbz0wLGk9ZS5sZW5ndGgsbj1pLTI7bzxpO249byxvKz0yKXIrPShlW29dLWVbbl0pKihlW28rMV0rZVtuKzFdKTtpZihyPjA9PT10KWZvcihvPTAsaT1lLmxlbmd0aDtvPGkvMjtvKz0yKXt2YXIgYT1lW29dLHM9ZVtvKzFdO2Vbb109ZVtpLTItb10sZVtvKzFdPWVbaS0xLW9dLGVbaS0yLW9dPWEsZVtpLTEtb109czt9fShzLG4pLGUucHVzaChzKTt9fWZ1bmN0aW9uIExlKGUsdCl7dmFyIHI9KHQ9dGhpcy5vcHRpb25zPWZ1bmN0aW9uKGUsdCl7Zm9yKHZhciByIGluIHQpZVtyXT10W3JdO3JldHVybiBlfShPYmplY3QuY3JlYXRlKHRoaXMub3B0aW9ucyksdCkpLmRlYnVnO2lmKHImJmNvbnNvbGUudGltZShcInByZXByb2Nlc3MgZGF0YVwiKSx0Lm1heFpvb208MHx8dC5tYXhab29tPjI0KXRocm93IG5ldyBFcnJvcihcIm1heFpvb20gc2hvdWxkIGJlIGluIHRoZSAwLTI0IHJhbmdlXCIpO2lmKHQucHJvbW90ZUlkJiZ0LmdlbmVyYXRlSWQpdGhyb3cgbmV3IEVycm9yKFwicHJvbW90ZUlkIGFuZCBnZW5lcmF0ZUlkIGNhbm5vdCBiZSB1c2VkIHRvZ2V0aGVyLlwiKTt2YXIgbz1mdW5jdGlvbihlLHQpe3ZhciByPVtdO2lmKFwiRmVhdHVyZUNvbGxlY3Rpb25cIj09PWUudHlwZSlmb3IodmFyIG89MDtvPGUuZmVhdHVyZXMubGVuZ3RoO28rKyl1ZShyLGUuZmVhdHVyZXNbb10sdCxvKTtlbHNlXCJGZWF0dXJlXCI9PT1lLnR5cGU/dWUocixlLHQpOnVlKHIse2dlb21ldHJ5OmV9LHQpO3JldHVybiByfShlLHQpO3RoaXMudGlsZXM9e30sdGhpcy50aWxlQ29vcmRzPVtdLHImJihjb25zb2xlLnRpbWVFbmQoXCJwcmVwcm9jZXNzIGRhdGFcIiksY29uc29sZS5sb2coXCJpbmRleDogbWF4Wm9vbTogJWQsIG1heFBvaW50czogJWRcIix0LmluZGV4TWF4Wm9vbSx0LmluZGV4TWF4UG9pbnRzKSxjb25zb2xlLnRpbWUoXCJnZW5lcmF0ZSB0aWxlc1wiKSx0aGlzLnN0YXRzPXt9LHRoaXMudG90YWw9MCksKG89ZnVuY3Rpb24oZSx0KXt2YXIgcj10LmJ1ZmZlci90LmV4dGVudCxvPWUsaT1kZShlLDEsLTEtcixyLDAsLTEsMix0KSxuPWRlKGUsMSwxLXIsMityLDAsLTEsMix0KTtyZXR1cm4gKGl8fG4pJiYobz1kZShlLDEsLXIsMStyLDAsLTEsMix0KXx8W10saSYmKG89TWUoaSwxKS5jb25jYXQobykpLG4mJihvPW8uY29uY2F0KE1lKG4sLTEpKSkpLG99KG8sdCkpLmxlbmd0aCYmdGhpcy5zcGxpdFRpbGUobywwLDAsMCksciYmKG8ubGVuZ3RoJiZjb25zb2xlLmxvZyhcImZlYXR1cmVzOiAlZCwgcG9pbnRzOiAlZFwiLHRoaXMudGlsZXNbMF0ubnVtRmVhdHVyZXMsdGhpcy50aWxlc1swXS5udW1Qb2ludHMpLGNvbnNvbGUudGltZUVuZChcImdlbmVyYXRlIHRpbGVzXCIpLGNvbnNvbGUubG9nKFwidGlsZXMgZ2VuZXJhdGVkOlwiLHRoaXMudG90YWwsSlNPTi5zdHJpbmdpZnkodGhpcy5zdGF0cykpKTt9ZnVuY3Rpb24gRGUoZSx0LHIpe3JldHVybiAzMiooKDE8PGUpKnIrdCkrZX1mdW5jdGlvbiBDZShlLHQpe3ZhciByPWUudGlsZUlELmNhbm9uaWNhbDtpZighdGhpcy5fZ2VvSlNPTkluZGV4KXJldHVybiB0KG51bGwsbnVsbCk7dmFyIG89dGhpcy5fZ2VvSlNPTkluZGV4LmdldFRpbGUoci56LHIueCxyLnkpO2lmKCFvKXJldHVybiB0KG51bGwsbnVsbCk7dmFyIGk9bmV3IGIoby5mZWF0dXJlcyksbj1MKGkpOzA9PT1uLmJ5dGVPZmZzZXQmJm4uYnl0ZUxlbmd0aD09PW4uYnVmZmVyLmJ5dGVMZW5ndGh8fChuPW5ldyBVaW50OEFycmF5KG4pKSx0KG51bGwse3ZlY3RvclRpbGU6aSxyYXdEYXRhOm4uYnVmZmVyfSk7fVUucHJvdG90eXBlLmxvYWQ9ZnVuY3Rpb24oZSl7dmFyIHQ9dGhpcy5vcHRpb25zLHI9dC5sb2csbz10Lm1pblpvb20saT10Lm1heFpvb20sbj10Lm5vZGVTaXplO3ImJmNvbnNvbGUudGltZShcInRvdGFsIHRpbWVcIik7dmFyIGE9XCJwcmVwYXJlIFwiK2UubGVuZ3RoK1wiIHBvaW50c1wiO3ImJmNvbnNvbGUudGltZShhKSx0aGlzLnBvaW50cz1lO2Zvcih2YXIgcz1bXSx1PTA7dTxlLmxlbmd0aDt1KyspZVt1XS5nZW9tZXRyeSYmcy5wdXNoKEgoZVt1XSx1KSk7dGhpcy50cmVlc1tpKzFdPW5ldyBSKHMsb2UsaWUsbixGbG9hdDMyQXJyYXkpLHImJmNvbnNvbGUudGltZUVuZChhKTtmb3IodmFyIGw9aTtsPj1vO2wtLSl7dmFyIGg9K0RhdGUubm93KCk7cz10aGlzLl9jbHVzdGVyKHMsbCksdGhpcy50cmVlc1tsXT1uZXcgUihzLG9lLGllLG4sRmxvYXQzMkFycmF5KSxyJiZjb25zb2xlLmxvZyhcInolZDogJWQgY2x1c3RlcnMgaW4gJWRtc1wiLGwscy5sZW5ndGgsK0RhdGUubm93KCktaCk7fXJldHVybiByJiZjb25zb2xlLnRpbWVFbmQoXCJ0b3RhbCB0aW1lXCIpLHRoaXN9LFUucHJvdG90eXBlLmdldENsdXN0ZXJzPWZ1bmN0aW9uKGUsdCl7dmFyIHI9KChlWzBdKzE4MCklMzYwKzM2MCklMzYwLTE4MCxvPU1hdGgubWF4KC05MCxNYXRoLm1pbig5MCxlWzFdKSksaT0xODA9PT1lWzJdPzE4MDooKGVbMl0rMTgwKSUzNjArMzYwKSUzNjAtMTgwLG49TWF0aC5tYXgoLTkwLE1hdGgubWluKDkwLGVbM10pKTtpZihlWzJdLWVbMF0+PTM2MClyPS0xODAsaT0xODA7ZWxzZSBpZihyPmkpe3ZhciBhPXRoaXMuZ2V0Q2x1c3RlcnMoW3IsbywxODAsbl0sdCkscz10aGlzLmdldENsdXN0ZXJzKFstMTgwLG8saSxuXSx0KTtyZXR1cm4gYS5jb25jYXQocyl9Zm9yKHZhciB1PXRoaXMudHJlZXNbdGhpcy5fbGltaXRab29tKHQpXSxsPVtdLGg9MCxjPXUucmFuZ2UoZWUociksdGUobiksZWUoaSksdGUobykpO2g8Yy5sZW5ndGg7aCs9MSl7dmFyIHA9Y1toXSxmPXUucG9pbnRzW3BdO2wucHVzaChmLm51bVBvaW50cz9LKGYpOnRoaXMucG9pbnRzW2YuaW5kZXhdKTt9cmV0dXJuIGx9LFUucHJvdG90eXBlLmdldENoaWxkcmVuPWZ1bmN0aW9uKGUpe3ZhciB0PWU+PjUscj1lJTMyLG89XCJObyBjbHVzdGVyIHdpdGggdGhlIHNwZWNpZmllZCBpZC5cIixpPXRoaXMudHJlZXNbcl07aWYoIWkpdGhyb3cgbmV3IEVycm9yKG8pO3ZhciBuPWkucG9pbnRzW3RdO2lmKCFuKXRocm93IG5ldyBFcnJvcihvKTtmb3IodmFyIGE9dGhpcy5vcHRpb25zLnJhZGl1cy8odGhpcy5vcHRpb25zLmV4dGVudCpNYXRoLnBvdygyLHItMSkpLHM9W10sdT0wLGw9aS53aXRoaW4obi54LG4ueSxhKTt1PGwubGVuZ3RoO3UrPTEpe3ZhciBoPWxbdV0sYz1pLnBvaW50c1toXTtjLnBhcmVudElkPT09ZSYmcy5wdXNoKGMubnVtUG9pbnRzP0soYyk6dGhpcy5wb2ludHNbYy5pbmRleF0pO31pZigwPT09cy5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKG8pO3JldHVybiBzfSxVLnByb3RvdHlwZS5nZXRMZWF2ZXM9ZnVuY3Rpb24oZSx0LHIpe3Q9dHx8MTAscj1yfHwwO3ZhciBvPVtdO3JldHVybiB0aGlzLl9hcHBlbmRMZWF2ZXMobyxlLHQsciwwKSxvfSxVLnByb3RvdHlwZS5nZXRUaWxlPWZ1bmN0aW9uKGUsdCxyKXt2YXIgbz10aGlzLnRyZWVzW3RoaXMuX2xpbWl0Wm9vbShlKV0saT1NYXRoLnBvdygyLGUpLG49dGhpcy5vcHRpb25zLGE9bi5leHRlbnQscz1uLnJhZGl1cy9hLHU9KHItcykvaSxsPShyKzErcykvaSxoPXtmZWF0dXJlczpbXX07cmV0dXJuIHRoaXMuX2FkZFRpbGVGZWF0dXJlcyhvLnJhbmdlKCh0LXMpL2ksdSwodCsxK3MpL2ksbCksby5wb2ludHMsdCxyLGksaCksMD09PXQmJnRoaXMuX2FkZFRpbGVGZWF0dXJlcyhvLnJhbmdlKDEtcy9pLHUsMSxsKSxvLnBvaW50cyxpLHIsaSxoKSx0PT09aS0xJiZ0aGlzLl9hZGRUaWxlRmVhdHVyZXMoby5yYW5nZSgwLHUscy9pLGwpLG8ucG9pbnRzLC0xLHIsaSxoKSxoLmZlYXR1cmVzLmxlbmd0aD9oOm51bGx9LFUucHJvdG90eXBlLmdldENsdXN0ZXJFeHBhbnNpb25ab29tPWZ1bmN0aW9uKGUpe2Zvcih2YXIgdD1lJTMyLTE7dDw9dGhpcy5vcHRpb25zLm1heFpvb207KXt2YXIgcj10aGlzLmdldENoaWxkcmVuKGUpO2lmKHQrKywxIT09ci5sZW5ndGgpYnJlYWs7ZT1yWzBdLnByb3BlcnRpZXMuY2x1c3Rlcl9pZDt9cmV0dXJuIHR9LFUucHJvdG90eXBlLl9hcHBlbmRMZWF2ZXM9ZnVuY3Rpb24oZSx0LHIsbyxpKXtmb3IodmFyIG49MCxhPXRoaXMuZ2V0Q2hpbGRyZW4odCk7bjxhLmxlbmd0aDtuKz0xKXt2YXIgcz1hW25dLHU9cy5wcm9wZXJ0aWVzO2lmKHUmJnUuY2x1c3Rlcj9pK3UucG9pbnRfY291bnQ8PW8/aSs9dS5wb2ludF9jb3VudDppPXRoaXMuX2FwcGVuZExlYXZlcyhlLHUuY2x1c3Rlcl9pZCxyLG8saSk6aTxvP2krKzplLnB1c2gocyksZS5sZW5ndGg9PT1yKWJyZWFrfXJldHVybiBpfSxVLnByb3RvdHlwZS5fYWRkVGlsZUZlYXR1cmVzPWZ1bmN0aW9uKGUsdCxyLG8saSxuKXtmb3IodmFyIGE9MCxzPWU7YTxzLmxlbmd0aDthKz0xKXt2YXIgdT10W3NbYV1dLGw9e3R5cGU6MSxnZW9tZXRyeTpbW01hdGgucm91bmQodGhpcy5vcHRpb25zLmV4dGVudCoodS54KmktcikpLE1hdGgucm91bmQodGhpcy5vcHRpb25zLmV4dGVudCoodS55KmktbykpXV0sdGFnczp1Lm51bVBvaW50cz9RKHUpOnRoaXMucG9pbnRzW3UuaW5kZXhdLnByb3BlcnRpZXN9LGg9dS5udW1Qb2ludHM/dS5pZDp0aGlzLnBvaW50c1t1LmluZGV4XS5pZDt2b2lkIDAhPT1oJiYobC5pZD1oKSxuLmZlYXR1cmVzLnB1c2gobCk7fX0sVS5wcm90b3R5cGUuX2xpbWl0Wm9vbT1mdW5jdGlvbihlKXtyZXR1cm4gTWF0aC5tYXgodGhpcy5vcHRpb25zLm1pblpvb20sTWF0aC5taW4oZSx0aGlzLm9wdGlvbnMubWF4Wm9vbSsxKSl9LFUucHJvdG90eXBlLl9jbHVzdGVyPWZ1bmN0aW9uKGUsdCl7Zm9yKHZhciByPVtdLG89dGhpcy5vcHRpb25zLGk9by5yYWRpdXMsbj1vLmV4dGVudCxhPW8ucmVkdWNlLHM9aS8obipNYXRoLnBvdygyLHQpKSx1PTA7dTxlLmxlbmd0aDt1Kyspe3ZhciBsPWVbdV07aWYoIShsLnpvb208PXQpKXtsLnpvb209dDtmb3IodmFyIGg9dGhpcy50cmVlc1t0KzFdLGM9aC53aXRoaW4obC54LGwueSxzKSxwPWwubnVtUG9pbnRzfHwxLGY9bC54KnAsZD1sLnkqcCxnPWE/dGhpcy5fbWFwKGwsITApOm51bGwsbT0odTw8NSkrKHQrMSksdj0wLHk9Yzt2PHkubGVuZ3RoO3YrPTEpe3ZhciB4PXlbdl0sdz1oLnBvaW50c1t4XTtpZighKHcuem9vbTw9dCkpe3cuem9vbT10O3ZhciBTPXcubnVtUG9pbnRzfHwxO2YrPXcueCpTLGQrPXcueSpTLHArPVMsdy5wYXJlbnRJZD1tLGEmJmEoZyx0aGlzLl9tYXAodykpO319MT09PXA/ci5wdXNoKGwpOihsLnBhcmVudElkPW0sci5wdXNoKCQoZi9wLGQvcCxtLHAsZykpKTt9fXJldHVybiByfSxVLnByb3RvdHlwZS5fbWFwPWZ1bmN0aW9uKGUsdCl7aWYoZS5udW1Qb2ludHMpcmV0dXJuIHQ/cmUoe30sZS5wcm9wZXJ0aWVzKTplLnByb3BlcnRpZXM7dmFyIHI9dGhpcy5wb2ludHNbZS5pbmRleF0ucHJvcGVydGllcyxvPXRoaXMub3B0aW9ucy5tYXAocik7cmV0dXJuIHQmJm89PT1yP3JlKHt9LG8pOm99LExlLnByb3RvdHlwZS5vcHRpb25zPXttYXhab29tOjE0LGluZGV4TWF4Wm9vbTo1LGluZGV4TWF4UG9pbnRzOjFlNSx0b2xlcmFuY2U6MyxleHRlbnQ6NDA5NixidWZmZXI6NjQsbGluZU1ldHJpY3M6ITEscHJvbW90ZUlkOm51bGwsZ2VuZXJhdGVJZDohMSxkZWJ1ZzowfSxMZS5wcm90b3R5cGUuc3BsaXRUaWxlPWZ1bmN0aW9uKGUsdCxyLG8saSxuLGEpe2Zvcih2YXIgcz1bZSx0LHIsb10sdT10aGlzLm9wdGlvbnMsbD11LmRlYnVnO3MubGVuZ3RoOyl7bz1zLnBvcCgpLHI9cy5wb3AoKSx0PXMucG9wKCksZT1zLnBvcCgpO3ZhciBoPTE8PHQsYz1EZSh0LHIsbykscD10aGlzLnRpbGVzW2NdO2lmKCFwJiYobD4xJiZjb25zb2xlLnRpbWUoXCJjcmVhdGlvblwiKSxwPXRoaXMudGlsZXNbY109UGUoZSx0LHIsbyx1KSx0aGlzLnRpbGVDb29yZHMucHVzaCh7ejp0LHg6cix5Om99KSxsKSl7bD4xJiYoY29uc29sZS5sb2coXCJ0aWxlIHolZC0lZC0lZCAoZmVhdHVyZXM6ICVkLCBwb2ludHM6ICVkLCBzaW1wbGlmaWVkOiAlZClcIix0LHIsbyxwLm51bUZlYXR1cmVzLHAubnVtUG9pbnRzLHAubnVtU2ltcGxpZmllZCksY29uc29sZS50aW1lRW5kKFwiY3JlYXRpb25cIikpO3ZhciBmPVwielwiK3Q7dGhpcy5zdGF0c1tmXT0odGhpcy5zdGF0c1tmXXx8MCkrMSx0aGlzLnRvdGFsKys7fWlmKHAuc291cmNlPWUsaSl7aWYodD09PXUubWF4Wm9vbXx8dD09PWkpY29udGludWU7dmFyIGQ9MTw8aS10O2lmKHIhPT1NYXRoLmZsb29yKG4vZCl8fG8hPT1NYXRoLmZsb29yKGEvZCkpY29udGludWV9ZWxzZSBpZih0PT09dS5pbmRleE1heFpvb218fHAubnVtUG9pbnRzPD11LmluZGV4TWF4UG9pbnRzKWNvbnRpbnVlO2lmKHAuc291cmNlPW51bGwsMCE9PWUubGVuZ3RoKXtsPjEmJmNvbnNvbGUudGltZShcImNsaXBwaW5nXCIpO3ZhciBnLG0sdix5LHgsdyxTPS41KnUuYnVmZmVyL3UuZXh0ZW50LE09LjUtUyxrPS41K1MsYj0xK1M7Zz1tPXY9eT1udWxsLHg9ZGUoZSxoLHItUyxyK2ssMCxwLm1pblgscC5tYXhYLHUpLHc9ZGUoZSxoLHIrTSxyK2IsMCxwLm1pblgscC5tYXhYLHUpLGU9bnVsbCx4JiYoZz1kZSh4LGgsby1TLG8raywxLHAubWluWSxwLm1heFksdSksbT1kZSh4LGgsbytNLG8rYiwxLHAubWluWSxwLm1heFksdSkseD1udWxsKSx3JiYodj1kZSh3LGgsby1TLG8raywxLHAubWluWSxwLm1heFksdSkseT1kZSh3LGgsbytNLG8rYiwxLHAubWluWSxwLm1heFksdSksdz1udWxsKSxsPjEmJmNvbnNvbGUudGltZUVuZChcImNsaXBwaW5nXCIpLHMucHVzaChnfHxbXSx0KzEsMipyLDIqbykscy5wdXNoKG18fFtdLHQrMSwyKnIsMipvKzEpLHMucHVzaCh2fHxbXSx0KzEsMipyKzEsMipvKSxzLnB1c2goeXx8W10sdCsxLDIqcisxLDIqbysxKTt9fX0sTGUucHJvdG90eXBlLmdldFRpbGU9ZnVuY3Rpb24oZSx0LHIpe3ZhciBvPXRoaXMub3B0aW9ucyxpPW8uZXh0ZW50LG49by5kZWJ1ZztpZihlPDB8fGU+MjQpcmV0dXJuIG51bGw7dmFyIGE9MTw8ZSxzPURlKGUsdD0odCVhK2EpJWEscik7aWYodGhpcy50aWxlc1tzXSlyZXR1cm4gYmUodGhpcy50aWxlc1tzXSxpKTtuPjEmJmNvbnNvbGUubG9nKFwiZHJpbGxpbmcgZG93biB0byB6JWQtJWQtJWRcIixlLHQscik7Zm9yKHZhciB1LGw9ZSxoPXQsYz1yOyF1JiZsPjA7KWwtLSxoPU1hdGguZmxvb3IoaC8yKSxjPU1hdGguZmxvb3IoYy8yKSx1PXRoaXMudGlsZXNbRGUobCxoLGMpXTtyZXR1cm4gdSYmdS5zb3VyY2U/KG4+MSYmY29uc29sZS5sb2coXCJmb3VuZCBwYXJlbnQgdGlsZSB6JWQtJWQtJWRcIixsLGgsYyksbj4xJiZjb25zb2xlLnRpbWUoXCJkcmlsbGluZyBkb3duXCIpLHRoaXMuc3BsaXRUaWxlKHUuc291cmNlLGwsaCxjLGUsdCxyKSxuPjEmJmNvbnNvbGUudGltZUVuZChcImRyaWxsaW5nIGRvd25cIiksdGhpcy50aWxlc1tzXT9iZSh0aGlzLnRpbGVzW3NdLGkpOm51bGwpOm51bGx9O3ZhciB6ZT1mdW5jdGlvbih0KXtmdW5jdGlvbiByKGUscixvKXt0LmNhbGwodGhpcyxlLHIsQ2UpLG8mJih0aGlzLmxvYWRHZW9KU09OPW8pO31yZXR1cm4gdCYmKHIuX19wcm90b19fPXQpLHIucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLHIucHJvdG90eXBlLmNvbnN0cnVjdG9yPXIsci5wcm90b3R5cGUubG9hZERhdGE9ZnVuY3Rpb24oZSx0KXt0aGlzLl9wZW5kaW5nQ2FsbGJhY2smJnRoaXMuX3BlbmRpbmdDYWxsYmFjayhudWxsLHthYmFuZG9uZWQ6ITB9KSx0aGlzLl9wZW5kaW5nQ2FsbGJhY2s9dCx0aGlzLl9wZW5kaW5nTG9hZERhdGFQYXJhbXM9ZSx0aGlzLl9zdGF0ZSYmXCJJZGxlXCIhPT10aGlzLl9zdGF0ZT90aGlzLl9zdGF0ZT1cIk5lZWRzTG9hZERhdGFcIjoodGhpcy5fc3RhdGU9XCJDb2FsZXNjaW5nXCIsdGhpcy5fbG9hZERhdGEoKSk7fSxyLnByb3RvdHlwZS5fbG9hZERhdGE9ZnVuY3Rpb24oKXt2YXIgdD10aGlzO2lmKHRoaXMuX3BlbmRpbmdDYWxsYmFjayYmdGhpcy5fcGVuZGluZ0xvYWREYXRhUGFyYW1zKXt2YXIgcj10aGlzLl9wZW5kaW5nQ2FsbGJhY2ssbz10aGlzLl9wZW5kaW5nTG9hZERhdGFQYXJhbXM7ZGVsZXRlIHRoaXMuX3BlbmRpbmdDYWxsYmFjayxkZWxldGUgdGhpcy5fcGVuZGluZ0xvYWREYXRhUGFyYW1zO3ZhciBpPSEhKG8mJm8ucmVxdWVzdCYmby5yZXF1ZXN0LmNvbGxlY3RSZXNvdXJjZVRpbWluZykmJm5ldyB1LlBlcmZvcm1hbmNlKG8ucmVxdWVzdCk7dGhpcy5sb2FkR2VvSlNPTihvLGZ1bmN0aW9uKG4sYSl7aWYobnx8IWEpcmV0dXJuIHIobik7aWYoXCJvYmplY3RcIiE9dHlwZW9mIGEpcmV0dXJuIHIobmV3IEVycm9yKFwiSW5wdXQgZGF0YSBnaXZlbiB0byAnXCIrby5zb3VyY2UrXCInIGlzIG5vdCBhIHZhbGlkIEdlb0pTT04gb2JqZWN0LlwiKSk7eShhLCEwKTt0cnl7dC5fZ2VvSlNPTkluZGV4PW8uY2x1c3Rlcj9uZXcgVShmdW5jdGlvbih0KXt2YXIgcj10LnN1cGVyY2x1c3Rlck9wdGlvbnMsbz10LmNsdXN0ZXJQcm9wZXJ0aWVzO2lmKCFvfHwhcilyZXR1cm4gcjtmb3IodmFyIGk9e30sbj17fSxhPXthY2N1bXVsYXRlZDpudWxsLHpvb206MH0scz17cHJvcGVydGllczpudWxsfSx1PU9iamVjdC5rZXlzKG8pLGw9MCxoPXU7bDxoLmxlbmd0aDtsKz0xKXt2YXIgYz1oW2xdLHA9b1tjXSxmPXBbMF0sZD1wWzFdLGc9ZS5jcmVhdGVFeHByZXNzaW9uKGQpLG09ZS5jcmVhdGVFeHByZXNzaW9uKFwic3RyaW5nXCI9PXR5cGVvZiBmP1tmLFtcImFjY3VtdWxhdGVkXCJdLFtcImdldFwiLGNdXTpmKTtpW2NdPWcudmFsdWUsbltjXT1tLnZhbHVlO31yZXR1cm4gci5tYXA9ZnVuY3Rpb24oZSl7cy5wcm9wZXJ0aWVzPWU7Zm9yKHZhciB0PXt9LHI9MCxvPXU7cjxvLmxlbmd0aDtyKz0xKXt2YXIgbj1vW3JdO3Rbbl09aVtuXS5ldmFsdWF0ZShhLHMpO31yZXR1cm4gdH0sci5yZWR1Y2U9ZnVuY3Rpb24oZSx0KXtzLnByb3BlcnRpZXM9dDtmb3IodmFyIHI9MCxvPXU7cjxvLmxlbmd0aDtyKz0xKXt2YXIgaT1vW3JdO2EuYWNjdW11bGF0ZWQ9ZVtpXSxlW2ldPW5baV0uZXZhbHVhdGUoYSxzKTt9fSxyfShvKSkubG9hZChhLmZlYXR1cmVzKTpmdW5jdGlvbihlLHQpe3JldHVybiBuZXcgTGUoZSx0KX0oYSxvLmdlb2pzb25WdE9wdGlvbnMpO31jYXRjaChuKXtyZXR1cm4gcihuKX10LmxvYWRlZD17fTt2YXIgcz17fTtpZihpKXt2YXIgdT1pLmZpbmlzaCgpO3UmJihzLnJlc291cmNlVGltaW5nPXt9LHMucmVzb3VyY2VUaW1pbmdbby5zb3VyY2VdPUpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodSkpKTt9cihudWxsLHMpO30pO319LHIucHJvdG90eXBlLmNvYWxlc2NlPWZ1bmN0aW9uKCl7XCJDb2FsZXNjaW5nXCI9PT10aGlzLl9zdGF0ZT90aGlzLl9zdGF0ZT1cIklkbGVcIjpcIk5lZWRzTG9hZERhdGFcIj09PXRoaXMuX3N0YXRlJiYodGhpcy5fc3RhdGU9XCJDb2FsZXNjaW5nXCIsdGhpcy5fbG9hZERhdGEoKSk7fSxyLnByb3RvdHlwZS5yZWxvYWRUaWxlPWZ1bmN0aW9uKGUscil7dmFyIG89dGhpcy5sb2FkZWQsaT1lLnVpZDtyZXR1cm4gbyYmb1tpXT90LnByb3RvdHlwZS5yZWxvYWRUaWxlLmNhbGwodGhpcyxlLHIpOnRoaXMubG9hZFRpbGUoZSxyKX0sci5wcm90b3R5cGUubG9hZEdlb0pTT049ZnVuY3Rpb24odCxyKXtpZih0LnJlcXVlc3QpZS5nZXRKU09OKHQucmVxdWVzdCxyKTtlbHNle2lmKFwic3RyaW5nXCIhPXR5cGVvZiB0LmRhdGEpcmV0dXJuIHIobmV3IEVycm9yKFwiSW5wdXQgZGF0YSBnaXZlbiB0byAnXCIrdC5zb3VyY2UrXCInIGlzIG5vdCBhIHZhbGlkIEdlb0pTT04gb2JqZWN0LlwiKSk7dHJ5e3JldHVybiByKG51bGwsSlNPTi5wYXJzZSh0LmRhdGEpKX1jYXRjaChlKXtyZXR1cm4gcihuZXcgRXJyb3IoXCJJbnB1dCBkYXRhIGdpdmVuIHRvICdcIit0LnNvdXJjZStcIicgaXMgbm90IGEgdmFsaWQgR2VvSlNPTiBvYmplY3QuXCIpKX19fSxyLnByb3RvdHlwZS5yZW1vdmVTb3VyY2U9ZnVuY3Rpb24oZSx0KXt0aGlzLl9wZW5kaW5nQ2FsbGJhY2smJnRoaXMuX3BlbmRpbmdDYWxsYmFjayhudWxsLHthYmFuZG9uZWQ6ITB9KSx0KCk7fSxyLnByb3RvdHlwZS5nZXRDbHVzdGVyRXhwYW5zaW9uWm9vbT1mdW5jdGlvbihlLHQpe3QobnVsbCx0aGlzLl9nZW9KU09OSW5kZXguZ2V0Q2x1c3RlckV4cGFuc2lvblpvb20oZS5jbHVzdGVySWQpKTt9LHIucHJvdG90eXBlLmdldENsdXN0ZXJDaGlsZHJlbj1mdW5jdGlvbihlLHQpe3QobnVsbCx0aGlzLl9nZW9KU09OSW5kZXguZ2V0Q2hpbGRyZW4oZS5jbHVzdGVySWQpKTt9LHIucHJvdG90eXBlLmdldENsdXN0ZXJMZWF2ZXM9ZnVuY3Rpb24oZSx0KXt0KG51bGwsdGhpcy5fZ2VvSlNPTkluZGV4LmdldExlYXZlcyhlLmNsdXN0ZXJJZCxlLmxpbWl0LGUub2Zmc2V0KSk7fSxyfShjKTt2YXIgT2U9ZnVuY3Rpb24odCl7dmFyIHI9dGhpczt0aGlzLnNlbGY9dCx0aGlzLmFjdG9yPW5ldyBlLkFjdG9yKHQsdGhpcyksdGhpcy5sYXllckluZGV4ZXM9e30sdGhpcy53b3JrZXJTb3VyY2VUeXBlcz17dmVjdG9yOmMsZ2VvanNvbjp6ZX0sdGhpcy53b3JrZXJTb3VyY2VzPXt9LHRoaXMuZGVtV29ya2VyU291cmNlcz17fSx0aGlzLnNlbGYucmVnaXN0ZXJXb3JrZXJTb3VyY2U9ZnVuY3Rpb24oZSx0KXtpZihyLndvcmtlclNvdXJjZVR5cGVzW2VdKXRocm93IG5ldyBFcnJvcignV29ya2VyIHNvdXJjZSB3aXRoIG5hbWUgXCInK2UrJ1wiIGFscmVhZHkgcmVnaXN0ZXJlZC4nKTtyLndvcmtlclNvdXJjZVR5cGVzW2VdPXQ7fSx0aGlzLnNlbGYucmVnaXN0ZXJSVExUZXh0UGx1Z2luPWZ1bmN0aW9uKHQpe2lmKGUucGx1Z2luLmlzTG9hZGVkKCkpdGhyb3cgbmV3IEVycm9yKFwiUlRMIHRleHQgcGx1Z2luIGFscmVhZHkgcmVnaXN0ZXJlZC5cIik7ZS5wbHVnaW4uYXBwbHlBcmFiaWNTaGFwaW5nPXQuYXBwbHlBcmFiaWNTaGFwaW5nLGUucGx1Z2luLnByb2Nlc3NCaWRpcmVjdGlvbmFsVGV4dD10LnByb2Nlc3NCaWRpcmVjdGlvbmFsVGV4dCxlLnBsdWdpbi5wcm9jZXNzU3R5bGVkQmlkaXJlY3Rpb25hbFRleHQ9dC5wcm9jZXNzU3R5bGVkQmlkaXJlY3Rpb25hbFRleHQ7fTt9O3JldHVybiBPZS5wcm90b3R5cGUuc2V0UmVmZXJyZXI9ZnVuY3Rpb24oZSx0KXt0aGlzLnJlZmVycmVyPXQ7fSxPZS5wcm90b3R5cGUuc2V0TGF5ZXJzPWZ1bmN0aW9uKGUsdCxyKXt0aGlzLmdldExheWVySW5kZXgoZSkucmVwbGFjZSh0KSxyKCk7fSxPZS5wcm90b3R5cGUudXBkYXRlTGF5ZXJzPWZ1bmN0aW9uKGUsdCxyKXt0aGlzLmdldExheWVySW5kZXgoZSkudXBkYXRlKHQubGF5ZXJzLHQucmVtb3ZlZElkcykscigpO30sT2UucHJvdG90eXBlLmxvYWRUaWxlPWZ1bmN0aW9uKGUsdCxyKXt0aGlzLmdldFdvcmtlclNvdXJjZShlLHQudHlwZSx0LnNvdXJjZSkubG9hZFRpbGUodCxyKTt9LE9lLnByb3RvdHlwZS5sb2FkREVNVGlsZT1mdW5jdGlvbihlLHQscil7dGhpcy5nZXRERU1Xb3JrZXJTb3VyY2UoZSx0LnNvdXJjZSkubG9hZFRpbGUodCxyKTt9LE9lLnByb3RvdHlwZS5yZWxvYWRUaWxlPWZ1bmN0aW9uKGUsdCxyKXt0aGlzLmdldFdvcmtlclNvdXJjZShlLHQudHlwZSx0LnNvdXJjZSkucmVsb2FkVGlsZSh0LHIpO30sT2UucHJvdG90eXBlLmFib3J0VGlsZT1mdW5jdGlvbihlLHQscil7dGhpcy5nZXRXb3JrZXJTb3VyY2UoZSx0LnR5cGUsdC5zb3VyY2UpLmFib3J0VGlsZSh0LHIpO30sT2UucHJvdG90eXBlLnJlbW92ZVRpbGU9ZnVuY3Rpb24oZSx0LHIpe3RoaXMuZ2V0V29ya2VyU291cmNlKGUsdC50eXBlLHQuc291cmNlKS5yZW1vdmVUaWxlKHQscik7fSxPZS5wcm90b3R5cGUucmVtb3ZlREVNVGlsZT1mdW5jdGlvbihlLHQpe3RoaXMuZ2V0REVNV29ya2VyU291cmNlKGUsdC5zb3VyY2UpLnJlbW92ZVRpbGUodCk7fSxPZS5wcm90b3R5cGUucmVtb3ZlU291cmNlPWZ1bmN0aW9uKGUsdCxyKXtpZih0aGlzLndvcmtlclNvdXJjZXNbZV0mJnRoaXMud29ya2VyU291cmNlc1tlXVt0LnR5cGVdJiZ0aGlzLndvcmtlclNvdXJjZXNbZV1bdC50eXBlXVt0LnNvdXJjZV0pe3ZhciBvPXRoaXMud29ya2VyU291cmNlc1tlXVt0LnR5cGVdW3Quc291cmNlXTtkZWxldGUgdGhpcy53b3JrZXJTb3VyY2VzW2VdW3QudHlwZV1bdC5zb3VyY2VdLHZvaWQgMCE9PW8ucmVtb3ZlU291cmNlP28ucmVtb3ZlU291cmNlKHQscik6cigpO319LE9lLnByb3RvdHlwZS5sb2FkV29ya2VyU291cmNlPWZ1bmN0aW9uKGUsdCxyKXt0cnl7dGhpcy5zZWxmLmltcG9ydFNjcmlwdHModC51cmwpLHIoKTt9Y2F0Y2goZSl7cihlLnRvU3RyaW5nKCkpO319LE9lLnByb3RvdHlwZS5sb2FkUlRMVGV4dFBsdWdpbj1mdW5jdGlvbih0LHIsbyl7dHJ5e2UucGx1Z2luLmlzTG9hZGVkKCl8fCh0aGlzLnNlbGYuaW1wb3J0U2NyaXB0cyhyKSxvKGUucGx1Z2luLmlzTG9hZGVkKCk/bnVsbDpuZXcgRXJyb3IoXCJSVEwgVGV4dCBQbHVnaW4gZmFpbGVkIHRvIGltcG9ydCBzY3JpcHRzIGZyb20gXCIrcikpKTt9Y2F0Y2goZSl7byhlLnRvU3RyaW5nKCkpO319LE9lLnByb3RvdHlwZS5nZXRMYXllckluZGV4PWZ1bmN0aW9uKGUpe3ZhciB0PXRoaXMubGF5ZXJJbmRleGVzW2VdO3JldHVybiB0fHwodD10aGlzLmxheWVySW5kZXhlc1tlXT1uZXcgbyksdH0sT2UucHJvdG90eXBlLmdldFdvcmtlclNvdXJjZT1mdW5jdGlvbihlLHQscil7dmFyIG89dGhpcztpZih0aGlzLndvcmtlclNvdXJjZXNbZV18fCh0aGlzLndvcmtlclNvdXJjZXNbZV09e30pLHRoaXMud29ya2VyU291cmNlc1tlXVt0XXx8KHRoaXMud29ya2VyU291cmNlc1tlXVt0XT17fSksIXRoaXMud29ya2VyU291cmNlc1tlXVt0XVtyXSl7dmFyIGk9e3NlbmQ6ZnVuY3Rpb24odCxyLGkpe28uYWN0b3Iuc2VuZCh0LHIsaSxlKTt9fTt0aGlzLndvcmtlclNvdXJjZXNbZV1bdF1bcl09bmV3IHRoaXMud29ya2VyU291cmNlVHlwZXNbdF0oaSx0aGlzLmdldExheWVySW5kZXgoZSkpO31yZXR1cm4gdGhpcy53b3JrZXJTb3VyY2VzW2VdW3RdW3JdfSxPZS5wcm90b3R5cGUuZ2V0REVNV29ya2VyU291cmNlPWZ1bmN0aW9uKGUsdCl7cmV0dXJuIHRoaXMuZGVtV29ya2VyU291cmNlc1tlXXx8KHRoaXMuZGVtV29ya2VyU291cmNlc1tlXT17fSksdGhpcy5kZW1Xb3JrZXJTb3VyY2VzW2VdW3RdfHwodGhpcy5kZW1Xb3JrZXJTb3VyY2VzW2VdW3RdPW5ldyBwKSx0aGlzLmRlbVdvcmtlclNvdXJjZXNbZV1bdF19LE9lLnByb3RvdHlwZS5lbmZvcmNlQ2FjaGVTaXplTGltaXQ9ZnVuY3Rpb24odCxyKXtlLmVuZm9yY2VDYWNoZVNpemVMaW1pdChyKTt9LFwidW5kZWZpbmVkXCIhPXR5cGVvZiBXb3JrZXJHbG9iYWxTY29wZSYmdm9pZCAwIT09ZS53aW5kb3cmJmUud2luZG93IGluc3RhbmNlb2YgV29ya2VyR2xvYmFsU2NvcGUmJihlLndpbmRvdy53b3JrZXI9bmV3IE9lKGUud2luZG93KSksT2V9KTtcblxuZGVmaW5lKFtcIi4vc2hhcmVkLmpzXCJdLGZ1bmN0aW9uKHQpe1widXNlIHN0cmljdFwiO3ZhciBlPXQuY3JlYXRlQ29tbW9uanNNb2R1bGUoZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSh0KXtyZXR1cm4gISEoXCJ1bmRlZmluZWRcIiE9dHlwZW9mIHdpbmRvdyYmXCJ1bmRlZmluZWRcIiE9dHlwZW9mIGRvY3VtZW50JiZBcnJheS5wcm90b3R5cGUmJkFycmF5LnByb3RvdHlwZS5ldmVyeSYmQXJyYXkucHJvdG90eXBlLmZpbHRlciYmQXJyYXkucHJvdG90eXBlLmZvckVhY2gmJkFycmF5LnByb3RvdHlwZS5pbmRleE9mJiZBcnJheS5wcm90b3R5cGUubGFzdEluZGV4T2YmJkFycmF5LnByb3RvdHlwZS5tYXAmJkFycmF5LnByb3RvdHlwZS5zb21lJiZBcnJheS5wcm90b3R5cGUucmVkdWNlJiZBcnJheS5wcm90b3R5cGUucmVkdWNlUmlnaHQmJkFycmF5LmlzQXJyYXkmJkZ1bmN0aW9uLnByb3RvdHlwZSYmRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQmJk9iamVjdC5rZXlzJiZPYmplY3QuY3JlYXRlJiZPYmplY3QuZ2V0UHJvdG90eXBlT2YmJk9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzJiZPYmplY3QuaXNTZWFsZWQmJk9iamVjdC5pc0Zyb3plbiYmT2JqZWN0LmlzRXh0ZW5zaWJsZSYmT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvciYmT2JqZWN0LmRlZmluZVByb3BlcnR5JiZPYmplY3QuZGVmaW5lUHJvcGVydGllcyYmT2JqZWN0LnNlYWwmJk9iamVjdC5mcmVlemUmJk9iamVjdC5wcmV2ZW50RXh0ZW5zaW9ucyYmXCJKU09OXCJpbiB3aW5kb3cmJlwicGFyc2VcImluIEpTT04mJlwic3RyaW5naWZ5XCJpbiBKU09OJiZmdW5jdGlvbigpe2lmKCEoXCJXb3JrZXJcImluIHdpbmRvdyYmXCJCbG9iXCJpbiB3aW5kb3cmJlwiVVJMXCJpbiB3aW5kb3cpKXJldHVybiAhMTt2YXIgdCxlLGk9bmV3IEJsb2IoW1wiXCJdLHt0eXBlOlwidGV4dC9qYXZhc2NyaXB0XCJ9KSxvPVVSTC5jcmVhdGVPYmplY3RVUkwoaSk7dHJ5e2U9bmV3IFdvcmtlcihvKSx0PSEwO31jYXRjaChlKXt0PSExO31lJiZlLnRlcm1pbmF0ZSgpO3JldHVybiBVUkwucmV2b2tlT2JqZWN0VVJMKG8pLHR9KCkmJlwiVWludDhDbGFtcGVkQXJyYXlcImluIHdpbmRvdyYmQXJyYXlCdWZmZXIuaXNWaWV3JiZmdW5jdGlvbih0KXt2b2lkIDA9PT1pW3RdJiYoaVt0XT1mdW5jdGlvbih0KXt2YXIgaT1kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpLG89T2JqZWN0LmNyZWF0ZShlLndlYkdMQ29udGV4dEF0dHJpYnV0ZXMpO3JldHVybiBvLmZhaWxJZk1ham9yUGVyZm9ybWFuY2VDYXZlYXQ9dCxpLnByb2JhYmx5U3VwcG9ydHNDb250ZXh0P2kucHJvYmFibHlTdXBwb3J0c0NvbnRleHQoXCJ3ZWJnbFwiLG8pfHxpLnByb2JhYmx5U3VwcG9ydHNDb250ZXh0KFwiZXhwZXJpbWVudGFsLXdlYmdsXCIsbyk6aS5zdXBwb3J0c0NvbnRleHQ/aS5zdXBwb3J0c0NvbnRleHQoXCJ3ZWJnbFwiLG8pfHxpLnN1cHBvcnRzQ29udGV4dChcImV4cGVyaW1lbnRhbC13ZWJnbFwiLG8pOmkuZ2V0Q29udGV4dChcIndlYmdsXCIsbyl8fGkuZ2V0Q29udGV4dChcImV4cGVyaW1lbnRhbC13ZWJnbFwiLG8pfSh0KSk7cmV0dXJuIGlbdF19KHQmJnQuZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdCkpfXQuZXhwb3J0cz90LmV4cG9ydHM9ZTp3aW5kb3cmJih3aW5kb3cubWFwYm94Z2w9d2luZG93Lm1hcGJveGdsfHx7fSx3aW5kb3cubWFwYm94Z2wuc3VwcG9ydGVkPWUpO3ZhciBpPXt9O2Uud2ViR0xDb250ZXh0QXR0cmlidXRlcz17YW50aWFsaWFzOiExLGFscGhhOiEwLHN0ZW5jaWw6ITAsZGVwdGg6ITB9O30pLGk9e2NyZWF0ZTpmdW5jdGlvbihlLGksbyl7dmFyIHI9dC53aW5kb3cuZG9jdW1lbnQuY3JlYXRlRWxlbWVudChlKTtyZXR1cm4gdm9pZCAwIT09aSYmKHIuY2xhc3NOYW1lPWkpLG8mJm8uYXBwZW5kQ2hpbGQocikscn0sY3JlYXRlTlM6ZnVuY3Rpb24oZSxpKXtyZXR1cm4gdC53aW5kb3cuZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKGUsaSl9fSxvPXQud2luZG93LmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZTtmdW5jdGlvbiByKHQpe2lmKCFvKXJldHVybiB0WzBdO2Zvcih2YXIgZT0wO2U8dC5sZW5ndGg7ZSsrKWlmKHRbZV1pbiBvKXJldHVybiB0W2VdO3JldHVybiB0WzBdfXZhciBhLG49cihbXCJ1c2VyU2VsZWN0XCIsXCJNb3pVc2VyU2VsZWN0XCIsXCJXZWJraXRVc2VyU2VsZWN0XCIsXCJtc1VzZXJTZWxlY3RcIl0pO2kuZGlzYWJsZURyYWc9ZnVuY3Rpb24oKXtvJiZuJiYoYT1vW25dLG9bbl09XCJub25lXCIpO30saS5lbmFibGVEcmFnPWZ1bmN0aW9uKCl7byYmbiYmKG9bbl09YSk7fTt2YXIgcz1yKFtcInRyYW5zZm9ybVwiLFwiV2Via2l0VHJhbnNmb3JtXCJdKTtpLnNldFRyYW5zZm9ybT1mdW5jdGlvbih0LGUpe3Quc3R5bGVbc109ZTt9O3ZhciBsPSExO3RyeXt2YXIgYz1PYmplY3QuZGVmaW5lUHJvcGVydHkoe30sXCJwYXNzaXZlXCIse2dldDpmdW5jdGlvbigpe2w9ITA7fX0pO3Qud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJ0ZXN0XCIsYyxjKSx0LndpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwidGVzdFwiLGMsYyk7fWNhdGNoKHQpe2w9ITE7fWkuYWRkRXZlbnRMaXN0ZW5lcj1mdW5jdGlvbih0LGUsaSxvKXt2b2lkIDA9PT1vJiYobz17fSksXCJwYXNzaXZlXCJpbiBvJiZsP3QuYWRkRXZlbnRMaXN0ZW5lcihlLGksbyk6dC5hZGRFdmVudExpc3RlbmVyKGUsaSxvLmNhcHR1cmUpO30saS5yZW1vdmVFdmVudExpc3RlbmVyPWZ1bmN0aW9uKHQsZSxpLG8pe3ZvaWQgMD09PW8mJihvPXt9KSxcInBhc3NpdmVcImluIG8mJmw/dC5yZW1vdmVFdmVudExpc3RlbmVyKGUsaSxvKTp0LnJlbW92ZUV2ZW50TGlzdGVuZXIoZSxpLG8uY2FwdHVyZSk7fTt2YXIgdT1mdW5jdGlvbihlKXtlLnByZXZlbnREZWZhdWx0KCksZS5zdG9wUHJvcGFnYXRpb24oKSx0LndpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2xpY2tcIix1LCEwKTt9O2Z1bmN0aW9uIGgodCl7dmFyIGU9dC51c2VySW1hZ2U7aWYoZSYmZS5yZW5kZXImJmUucmVuZGVyKCkpcmV0dXJuIHQuZGF0YS5yZXBsYWNlKG5ldyBVaW50OEFycmF5KGUuZGF0YS5idWZmZXIpKSwhMDtyZXR1cm4gITF9aS5zdXBwcmVzc0NsaWNrPWZ1bmN0aW9uKCl7dC53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsdSwhMCksdC53aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpe3Qud2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLHUsITApO30sMCk7fSxpLm1vdXNlUG9zPWZ1bmN0aW9uKGUsaSl7dmFyIG89ZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxyPXQud2luZG93LlRvdWNoRXZlbnQmJmkgaW5zdGFuY2VvZiB0LndpbmRvdy5Ub3VjaEV2ZW50P2kudG91Y2hlc1swXTppO3JldHVybiBuZXcgdC5Qb2ludChyLmNsaWVudFgtby5sZWZ0LWUuY2xpZW50TGVmdCxyLmNsaWVudFktby50b3AtZS5jbGllbnRUb3ApfSxpLnRvdWNoUG9zPWZ1bmN0aW9uKGUsaSl7Zm9yKHZhciBvPWUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkscj1bXSxhPVwidG91Y2hlbmRcIj09PWkudHlwZT9pLmNoYW5nZWRUb3VjaGVzOmkudG91Y2hlcyxuPTA7bjxhLmxlbmd0aDtuKyspci5wdXNoKG5ldyB0LlBvaW50KGFbbl0uY2xpZW50WC1vLmxlZnQtZS5jbGllbnRMZWZ0LGFbbl0uY2xpZW50WS1vLnRvcC1lLmNsaWVudFRvcCkpO3JldHVybiByfSxpLm1vdXNlQnV0dG9uPWZ1bmN0aW9uKGUpe3JldHVybiB2b2lkIDAhPT10LndpbmRvdy5JbnN0YWxsVHJpZ2dlciYmMj09PWUuYnV0dG9uJiZlLmN0cmxLZXkmJnQud2luZG93Lm5hdmlnYXRvci5wbGF0Zm9ybS50b1VwcGVyQ2FzZSgpLmluZGV4T2YoXCJNQUNcIik+PTA/MDplLmJ1dHRvbn0saS5yZW1vdmU9ZnVuY3Rpb24odCl7dC5wYXJlbnROb2RlJiZ0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodCk7fTt2YXIgcD1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKCl7ZS5jYWxsKHRoaXMpLHRoaXMuaW1hZ2VzPXt9LHRoaXMudXBkYXRlZEltYWdlcz17fSx0aGlzLmNhbGxiYWNrRGlzcGF0Y2hlZFRoaXNGcmFtZT17fSx0aGlzLmxvYWRlZD0hMSx0aGlzLnJlcXVlc3RvcnM9W10sdGhpcy5wYXR0ZXJucz17fSx0aGlzLmF0bGFzSW1hZ2U9bmV3IHQuUkdCQUltYWdlKHt3aWR0aDoxLGhlaWdodDoxfSksdGhpcy5kaXJ0eT0hMDt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmlzTG9hZGVkPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubG9hZGVkfSxpLnByb3RvdHlwZS5zZXRMb2FkZWQ9ZnVuY3Rpb24odCl7aWYodGhpcy5sb2FkZWQhPT10JiYodGhpcy5sb2FkZWQ9dCx0KSl7Zm9yKHZhciBlPTAsaT10aGlzLnJlcXVlc3RvcnM7ZTxpLmxlbmd0aDtlKz0xKXt2YXIgbz1pW2VdLHI9by5pZHMsYT1vLmNhbGxiYWNrO3RoaXMuX25vdGlmeShyLGEpO310aGlzLnJlcXVlc3RvcnM9W107fX0saS5wcm90b3R5cGUuZ2V0SW1hZ2U9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuaW1hZ2VzW3RdfSxpLnByb3RvdHlwZS5hZGRJbWFnZT1mdW5jdGlvbih0LGUpe3RoaXMuaW1hZ2VzW3RdPWU7fSxpLnByb3RvdHlwZS51cGRhdGVJbWFnZT1mdW5jdGlvbih0LGUpe3ZhciBpPXRoaXMuaW1hZ2VzW3RdO2UudmVyc2lvbj1pLnZlcnNpb24rMSx0aGlzLmltYWdlc1t0XT1lLHRoaXMudXBkYXRlZEltYWdlc1t0XT0hMDt9LGkucHJvdG90eXBlLnJlbW92ZUltYWdlPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuaW1hZ2VzW3RdO2RlbGV0ZSB0aGlzLmltYWdlc1t0XSxkZWxldGUgdGhpcy5wYXR0ZXJuc1t0XSxlLnVzZXJJbWFnZSYmZS51c2VySW1hZ2Uub25SZW1vdmUmJmUudXNlckltYWdlLm9uUmVtb3ZlKCk7fSxpLnByb3RvdHlwZS5saXN0SW1hZ2VzPWZ1bmN0aW9uKCl7cmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuaW1hZ2VzKX0saS5wcm90b3R5cGUuZ2V0SW1hZ2VzPWZ1bmN0aW9uKHQsZSl7dmFyIGk9ITA7aWYoIXRoaXMuaXNMb2FkZWQoKSlmb3IodmFyIG89MCxyPXQ7bzxyLmxlbmd0aDtvKz0xKXt2YXIgYT1yW29dO3RoaXMuaW1hZ2VzW2FdfHwoaT0hMSk7fXRoaXMuaXNMb2FkZWQoKXx8aT90aGlzLl9ub3RpZnkodCxlKTp0aGlzLnJlcXVlc3RvcnMucHVzaCh7aWRzOnQsY2FsbGJhY2s6ZX0pO30saS5wcm90b3R5cGUuX25vdGlmeT1mdW5jdGlvbihlLGkpe2Zvcih2YXIgbz17fSxyPTAsYT1lO3I8YS5sZW5ndGg7cis9MSl7dmFyIG49YVtyXTt0aGlzLmltYWdlc1tuXXx8dGhpcy5maXJlKG5ldyB0LkV2ZW50KFwic3R5bGVpbWFnZW1pc3NpbmdcIix7aWQ6bn0pKTt2YXIgcz10aGlzLmltYWdlc1tuXTtzP29bbl09e2RhdGE6cy5kYXRhLmNsb25lKCkscGl4ZWxSYXRpbzpzLnBpeGVsUmF0aW8sc2RmOnMuc2RmLHZlcnNpb246cy52ZXJzaW9uLGhhc1JlbmRlckNhbGxiYWNrOkJvb2xlYW4ocy51c2VySW1hZ2UmJnMudXNlckltYWdlLnJlbmRlcil9OnQud2Fybk9uY2UoJ0ltYWdlIFwiJytuKydcIiBjb3VsZCBub3QgYmUgbG9hZGVkLiBQbGVhc2UgbWFrZSBzdXJlIHlvdSBoYXZlIGFkZGVkIHRoZSBpbWFnZSB3aXRoIG1hcC5hZGRJbWFnZSgpIG9yIGEgXCJzcHJpdGVcIiBwcm9wZXJ0eSBpbiB5b3VyIHN0eWxlLiBZb3UgY2FuIHByb3ZpZGUgbWlzc2luZyBpbWFnZXMgYnkgbGlzdGVuaW5nIGZvciB0aGUgXCJzdHlsZWltYWdlbWlzc2luZ1wiIG1hcCBldmVudC4nKTt9aShudWxsLG8pO30saS5wcm90b3R5cGUuZ2V0UGl4ZWxTaXplPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5hdGxhc0ltYWdlO3JldHVybiB7d2lkdGg6dC53aWR0aCxoZWlnaHQ6dC5oZWlnaHR9fSxpLnByb3RvdHlwZS5nZXRQYXR0ZXJuPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXMucGF0dGVybnNbZV0sbz10aGlzLmdldEltYWdlKGUpO2lmKCFvKXJldHVybiBudWxsO2lmKGkmJmkucG9zaXRpb24udmVyc2lvbj09PW8udmVyc2lvbilyZXR1cm4gaS5wb3NpdGlvbjtpZihpKWkucG9zaXRpb24udmVyc2lvbj1vLnZlcnNpb247ZWxzZXt2YXIgcj17dzpvLmRhdGEud2lkdGgrMixoOm8uZGF0YS5oZWlnaHQrMix4OjAseTowfSxhPW5ldyB0LkltYWdlUG9zaXRpb24ocixvKTt0aGlzLnBhdHRlcm5zW2VdPXtiaW46cixwb3NpdGlvbjphfTt9cmV0dXJuIHRoaXMuX3VwZGF0ZVBhdHRlcm5BdGxhcygpLHRoaXMucGF0dGVybnNbZV0ucG9zaXRpb259LGkucHJvdG90eXBlLmJpbmQ9ZnVuY3Rpb24oZSl7dmFyIGk9ZS5nbDt0aGlzLmF0bGFzVGV4dHVyZT90aGlzLmRpcnR5JiYodGhpcy5hdGxhc1RleHR1cmUudXBkYXRlKHRoaXMuYXRsYXNJbWFnZSksdGhpcy5kaXJ0eT0hMSk6dGhpcy5hdGxhc1RleHR1cmU9bmV3IHQuVGV4dHVyZShlLHRoaXMuYXRsYXNJbWFnZSxpLlJHQkEpLHRoaXMuYXRsYXNUZXh0dXJlLmJpbmQoaS5MSU5FQVIsaS5DTEFNUF9UT19FREdFKTt9LGkucHJvdG90eXBlLl91cGRhdGVQYXR0ZXJuQXRsYXM9ZnVuY3Rpb24oKXt2YXIgZT1bXTtmb3IodmFyIGkgaW4gdGhpcy5wYXR0ZXJucyllLnB1c2godGhpcy5wYXR0ZXJuc1tpXS5iaW4pO3ZhciBvPXQucG90cGFjayhlKSxyPW8udyxhPW8uaCxuPXRoaXMuYXRsYXNJbWFnZTtmb3IodmFyIHMgaW4gbi5yZXNpemUoe3dpZHRoOnJ8fDEsaGVpZ2h0OmF8fDF9KSx0aGlzLnBhdHRlcm5zKXt2YXIgbD10aGlzLnBhdHRlcm5zW3NdLmJpbixjPWwueCsxLHU9bC55KzEsaD10aGlzLmltYWdlc1tzXS5kYXRhLHA9aC53aWR0aCxkPWguaGVpZ2h0O3QuUkdCQUltYWdlLmNvcHkoaCxuLHt4OjAseTowfSx7eDpjLHk6dX0se3dpZHRoOnAsaGVpZ2h0OmR9KSx0LlJHQkFJbWFnZS5jb3B5KGgsbix7eDowLHk6ZC0xfSx7eDpjLHk6dS0xfSx7d2lkdGg6cCxoZWlnaHQ6MX0pLHQuUkdCQUltYWdlLmNvcHkoaCxuLHt4OjAseTowfSx7eDpjLHk6dStkfSx7d2lkdGg6cCxoZWlnaHQ6MX0pLHQuUkdCQUltYWdlLmNvcHkoaCxuLHt4OnAtMSx5OjB9LHt4OmMtMSx5OnV9LHt3aWR0aDoxLGhlaWdodDpkfSksdC5SR0JBSW1hZ2UuY29weShoLG4se3g6MCx5OjB9LHt4OmMrcCx5OnV9LHt3aWR0aDoxLGhlaWdodDpkfSk7fXRoaXMuZGlydHk9ITA7fSxpLnByb3RvdHlwZS5iZWdpbkZyYW1lPWZ1bmN0aW9uKCl7dGhpcy5jYWxsYmFja0Rpc3BhdGNoZWRUaGlzRnJhbWU9e307fSxpLnByb3RvdHlwZS5kaXNwYXRjaFJlbmRlckNhbGxiYWNrcz1mdW5jdGlvbih0KXtmb3IodmFyIGU9MCxpPXQ7ZTxpLmxlbmd0aDtlKz0xKXt2YXIgbz1pW2VdO2lmKCF0aGlzLmNhbGxiYWNrRGlzcGF0Y2hlZFRoaXNGcmFtZVtvXSl7dGhpcy5jYWxsYmFja0Rpc3BhdGNoZWRUaGlzRnJhbWVbb109ITA7dmFyIHI9dGhpcy5pbWFnZXNbb107aChyKSYmdGhpcy51cGRhdGVJbWFnZShvLHIpO319fSxpfSh0LkV2ZW50ZWQpO3ZhciBkPWYsXz0xZTIwO2Z1bmN0aW9uIGYodCxlLGksbyxyLGEpe3RoaXMuZm9udFNpemU9dHx8MjQsdGhpcy5idWZmZXI9dm9pZCAwPT09ZT8zOmUsdGhpcy5jdXRvZmY9b3x8LjI1LHRoaXMuZm9udEZhbWlseT1yfHxcInNhbnMtc2VyaWZcIix0aGlzLmZvbnRXZWlnaHQ9YXx8XCJub3JtYWxcIix0aGlzLnJhZGl1cz1pfHw4O3ZhciBuPXRoaXMuc2l6ZT10aGlzLmZvbnRTaXplKzIqdGhpcy5idWZmZXI7dGhpcy5jYW52YXM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKSx0aGlzLmNhbnZhcy53aWR0aD10aGlzLmNhbnZhcy5oZWlnaHQ9bix0aGlzLmN0eD10aGlzLmNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIiksdGhpcy5jdHguZm9udD10aGlzLmZvbnRXZWlnaHQrXCIgXCIrdGhpcy5mb250U2l6ZStcInB4IFwiK3RoaXMuZm9udEZhbWlseSx0aGlzLmN0eC50ZXh0QmFzZWxpbmU9XCJtaWRkbGVcIix0aGlzLmN0eC5maWxsU3R5bGU9XCJibGFja1wiLHRoaXMuZ3JpZE91dGVyPW5ldyBGbG9hdDY0QXJyYXkobipuKSx0aGlzLmdyaWRJbm5lcj1uZXcgRmxvYXQ2NEFycmF5KG4qbiksdGhpcy5mPW5ldyBGbG9hdDY0QXJyYXkobiksdGhpcy5kPW5ldyBGbG9hdDY0QXJyYXkobiksdGhpcy56PW5ldyBGbG9hdDY0QXJyYXkobisxKSx0aGlzLnY9bmV3IEludDE2QXJyYXkobiksdGhpcy5taWRkbGU9TWF0aC5yb3VuZChuLzIqKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZihcIkdlY2tvL1wiKT49MD8xLjI6MSkpO31mdW5jdGlvbiBtKHQsZSxpLG8scixhLG4pe2Zvcih2YXIgcz0wO3M8ZTtzKyspe2Zvcih2YXIgbD0wO2w8aTtsKyspb1tsXT10W2wqZStzXTtmb3IoZyhvLHIsYSxuLGkpLGw9MDtsPGk7bCsrKXRbbCplK3NdPXJbbF07fWZvcihsPTA7bDxpO2wrKyl7Zm9yKHM9MDtzPGU7cysrKW9bc109dFtsKmUrc107Zm9yKGcobyxyLGEsbixlKSxzPTA7czxlO3MrKyl0W2wqZStzXT1NYXRoLnNxcnQocltzXSk7fX1mdW5jdGlvbiBnKHQsZSxpLG8scil7aVswXT0wLG9bMF09LV8sb1sxXT0rXztmb3IodmFyIGE9MSxuPTA7YTxyO2ErKyl7Zm9yKHZhciBzPSh0W2FdK2EqYS0odFtpW25dXStpW25dKmlbbl0pKS8oMiphLTIqaVtuXSk7czw9b1tuXTspbi0tLHM9KHRbYV0rYSphLSh0W2lbbl1dK2lbbl0qaVtuXSkpLygyKmEtMippW25dKTtpWysrbl09YSxvW25dPXMsb1tuKzFdPStfO31mb3IoYT0wLG49MDthPHI7YSsrKXtmb3IoO29bbisxXTxhOyluKys7ZVthXT0oYS1pW25dKSooYS1pW25dKSt0W2lbbl1dO319Zi5wcm90b3R5cGUuZHJhdz1mdW5jdGlvbih0KXt0aGlzLmN0eC5jbGVhclJlY3QoMCwwLHRoaXMuc2l6ZSx0aGlzLnNpemUpLHRoaXMuY3R4LmZpbGxUZXh0KHQsdGhpcy5idWZmZXIsdGhpcy5taWRkbGUpO2Zvcih2YXIgZT10aGlzLmN0eC5nZXRJbWFnZURhdGEoMCwwLHRoaXMuc2l6ZSx0aGlzLnNpemUpLGk9bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHRoaXMuc2l6ZSp0aGlzLnNpemUpLG89MDtvPHRoaXMuc2l6ZSp0aGlzLnNpemU7bysrKXt2YXIgcj1lLmRhdGFbNCpvKzNdLzI1NTt0aGlzLmdyaWRPdXRlcltvXT0xPT09cj8wOjA9PT1yP186TWF0aC5wb3coTWF0aC5tYXgoMCwuNS1yKSwyKSx0aGlzLmdyaWRJbm5lcltvXT0xPT09cj9fOjA9PT1yPzA6TWF0aC5wb3coTWF0aC5tYXgoMCxyLS41KSwyKTt9Zm9yKG0odGhpcy5ncmlkT3V0ZXIsdGhpcy5zaXplLHRoaXMuc2l6ZSx0aGlzLmYsdGhpcy5kLHRoaXMudix0aGlzLnopLG0odGhpcy5ncmlkSW5uZXIsdGhpcy5zaXplLHRoaXMuc2l6ZSx0aGlzLmYsdGhpcy5kLHRoaXMudix0aGlzLnopLG89MDtvPHRoaXMuc2l6ZSp0aGlzLnNpemU7bysrKXt2YXIgYT10aGlzLmdyaWRPdXRlcltvXS10aGlzLmdyaWRJbm5lcltvXTtpW29dPU1hdGgubWF4KDAsTWF0aC5taW4oMjU1LE1hdGgucm91bmQoMjU1LTI1NSooYS90aGlzLnJhZGl1cyt0aGlzLmN1dG9mZikpKSk7fXJldHVybiBpfTt2YXIgdj1mdW5jdGlvbih0LGUpe3RoaXMucmVxdWVzdE1hbmFnZXI9dCx0aGlzLmxvY2FsSWRlb2dyYXBoRm9udEZhbWlseT1lLHRoaXMuZW50cmllcz17fTt9O3YucHJvdG90eXBlLnNldFVSTD1mdW5jdGlvbih0KXt0aGlzLnVybD10O30sdi5wcm90b3R5cGUuZ2V0R2x5cGhzPWZ1bmN0aW9uKGUsaSl7dmFyIG89dGhpcyxyPVtdO2Zvcih2YXIgYSBpbiBlKWZvcih2YXIgbj0wLHM9ZVthXTtuPHMubGVuZ3RoO24rPTEpe3ZhciBsPXNbbl07ci5wdXNoKHtzdGFjazphLGlkOmx9KTt9dC5hc3luY0FsbChyLGZ1bmN0aW9uKHQsZSl7dmFyIGk9dC5zdGFjayxyPXQuaWQsYT1vLmVudHJpZXNbaV07YXx8KGE9by5lbnRyaWVzW2ldPXtnbHlwaHM6e30scmVxdWVzdHM6e319KTt2YXIgbj1hLmdseXBoc1tyXTtpZih2b2lkIDA9PT1uKWlmKG49by5fdGlueVNERihhLGkscikpZShudWxsLHtzdGFjazppLGlkOnIsZ2x5cGg6bn0pO2Vsc2V7dmFyIHM9TWF0aC5mbG9vcihyLzI1Nik7aWYoMjU2KnM+NjU1MzUpZShuZXcgRXJyb3IoXCJnbHlwaHMgPiA2NTUzNSBub3Qgc3VwcG9ydGVkXCIpKTtlbHNle3ZhciBsPWEucmVxdWVzdHNbc107bHx8KGw9YS5yZXF1ZXN0c1tzXT1bXSx2LmxvYWRHbHlwaFJhbmdlKGkscyxvLnVybCxvLnJlcXVlc3RNYW5hZ2VyLGZ1bmN0aW9uKHQsZSl7aWYoZSlmb3IodmFyIGkgaW4gZSlhLmdseXBoc1sraV09ZVsraV07Zm9yKHZhciBvPTAscj1sO288ci5sZW5ndGg7bys9MSl7KDAscltvXSkodCxlKTt9ZGVsZXRlIGEucmVxdWVzdHNbc107fSkpLGwucHVzaChmdW5jdGlvbih0LG8pe3Q/ZSh0KTpvJiZlKG51bGwse3N0YWNrOmksaWQ6cixnbHlwaDpvW3JdfHxudWxsfSk7fSk7fX1lbHNlIGUobnVsbCx7c3RhY2s6aSxpZDpyLGdseXBoOm59KTt9LGZ1bmN0aW9uKHQsZSl7aWYodClpKHQpO2Vsc2UgaWYoZSl7Zm9yKHZhciBvPXt9LHI9MCxhPWU7cjxhLmxlbmd0aDtyKz0xKXt2YXIgbj1hW3JdLHM9bi5zdGFjayxsPW4uaWQsYz1uLmdseXBoOyhvW3NdfHwob1tzXT17fSkpW2xdPWMmJntpZDpjLmlkLGJpdG1hcDpjLmJpdG1hcC5jbG9uZSgpLG1ldHJpY3M6Yy5tZXRyaWNzfTt9aShudWxsLG8pO319KTt9LHYucHJvdG90eXBlLl90aW55U0RGPWZ1bmN0aW9uKGUsaSxvKXt2YXIgcj10aGlzLmxvY2FsSWRlb2dyYXBoRm9udEZhbWlseTtpZihyJiYodC5pc0NoYXJbXCJDSksgVW5pZmllZCBJZGVvZ3JhcGhzXCJdKG8pfHx0LmlzQ2hhcltcIkhhbmd1bCBTeWxsYWJsZXNcIl0obyl8fHQuaXNDaGFyLkhpcmFnYW5hKG8pfHx0LmlzQ2hhci5LYXRha2FuYShvKSkpe3ZhciBhPWUudGlueVNERjtpZighYSl7dmFyIG49XCI0MDBcIjsvYm9sZC9pLnRlc3QoaSk/bj1cIjkwMFwiOi9tZWRpdW0vaS50ZXN0KGkpP249XCI1MDBcIjovbGlnaHQvaS50ZXN0KGkpJiYobj1cIjIwMFwiKSxhPWUudGlueVNERj1uZXcgdi5UaW55U0RGKDI0LDMsOCwuMjUscixuKTt9cmV0dXJuIHtpZDpvLGJpdG1hcDpuZXcgdC5BbHBoYUltYWdlKHt3aWR0aDozMCxoZWlnaHQ6MzB9LGEuZHJhdyhTdHJpbmcuZnJvbUNoYXJDb2RlKG8pKSksbWV0cmljczp7d2lkdGg6MjQsaGVpZ2h0OjI0LGxlZnQ6MCx0b3A6LTgsYWR2YW5jZToyNH19fX0sdi5sb2FkR2x5cGhSYW5nZT1mdW5jdGlvbihlLGksbyxyLGEpe3ZhciBuPTI1NippLHM9bisyNTUsbD1yLnRyYW5zZm9ybVJlcXVlc3Qoci5ub3JtYWxpemVHbHlwaHNVUkwobykucmVwbGFjZShcIntmb250c3RhY2t9XCIsZSkucmVwbGFjZShcIntyYW5nZX1cIixuK1wiLVwiK3MpLHQuUmVzb3VyY2VUeXBlLkdseXBocyk7dC5nZXRBcnJheUJ1ZmZlcihsLGZ1bmN0aW9uKGUsaSl7aWYoZSlhKGUpO2Vsc2UgaWYoaSl7Zm9yKHZhciBvPXt9LHI9MCxuPXQucGFyc2VHbHlwaFBCRihpKTtyPG4ubGVuZ3RoO3IrPTEpe3ZhciBzPW5bcl07b1tzLmlkXT1zO31hKG51bGwsbyk7fX0pO30sdi5UaW55U0RGPWQ7dmFyIHk9ZnVuY3Rpb24oKXt0aGlzLnNwZWNpZmljYXRpb249dC5zdHlsZVNwZWMubGlnaHQucG9zaXRpb247fTt5LnByb3RvdHlwZS5wb3NzaWJseUV2YWx1YXRlPWZ1bmN0aW9uKGUsaSl7cmV0dXJuIHQuc3BoZXJpY2FsVG9DYXJ0ZXNpYW4oZS5leHByZXNzaW9uLmV2YWx1YXRlKGkpKX0seS5wcm90b3R5cGUuaW50ZXJwb2xhdGU9ZnVuY3Rpb24oZSxpLG8pe3JldHVybiB7eDp0Lm51bWJlcihlLngsaS54LG8pLHk6dC5udW1iZXIoZS55LGkueSxvKSx6OnQubnVtYmVyKGUueixpLnosbyl9fTt2YXIgeD1uZXcgdC5Qcm9wZXJ0aWVzKHthbmNob3I6bmV3IHQuRGF0YUNvbnN0YW50UHJvcGVydHkodC5zdHlsZVNwZWMubGlnaHQuYW5jaG9yKSxwb3NpdGlvbjpuZXcgeSxjb2xvcjpuZXcgdC5EYXRhQ29uc3RhbnRQcm9wZXJ0eSh0LnN0eWxlU3BlYy5saWdodC5jb2xvciksaW50ZW5zaXR5Om5ldyB0LkRhdGFDb25zdGFudFByb3BlcnR5KHQuc3R5bGVTcGVjLmxpZ2h0LmludGVuc2l0eSl9KSxiPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIGkoaSl7ZS5jYWxsKHRoaXMpLHRoaXMuX3RyYW5zaXRpb25hYmxlPW5ldyB0LlRyYW5zaXRpb25hYmxlKHgpLHRoaXMuc2V0TGlnaHQoaSksdGhpcy5fdHJhbnNpdGlvbmluZz10aGlzLl90cmFuc2l0aW9uYWJsZS51bnRyYW5zaXRpb25lZCgpO31yZXR1cm4gZSYmKGkuX19wcm90b19fPWUpLGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLGkucHJvdG90eXBlLmNvbnN0cnVjdG9yPWksaS5wcm90b3R5cGUuZ2V0TGlnaHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fdHJhbnNpdGlvbmFibGUuc2VyaWFsaXplKCl9LGkucHJvdG90eXBlLnNldExpZ2h0PWZ1bmN0aW9uKGUsaSl7aWYodm9pZCAwPT09aSYmKGk9e30pLCF0aGlzLl92YWxpZGF0ZSh0LnZhbGlkYXRlTGlnaHQsZSxpKSlmb3IodmFyIG8gaW4gZSl7dmFyIHI9ZVtvXTt0LmVuZHNXaXRoKG8sXCItdHJhbnNpdGlvblwiKT90aGlzLl90cmFuc2l0aW9uYWJsZS5zZXRUcmFuc2l0aW9uKG8uc2xpY2UoMCwtXCItdHJhbnNpdGlvblwiLmxlbmd0aCkscik6dGhpcy5fdHJhbnNpdGlvbmFibGUuc2V0VmFsdWUobyxyKTt9fSxpLnByb3RvdHlwZS51cGRhdGVUcmFuc2l0aW9ucz1mdW5jdGlvbih0KXt0aGlzLl90cmFuc2l0aW9uaW5nPXRoaXMuX3RyYW5zaXRpb25hYmxlLnRyYW5zaXRpb25lZCh0LHRoaXMuX3RyYW5zaXRpb25pbmcpO30saS5wcm90b3R5cGUuaGFzVHJhbnNpdGlvbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLl90cmFuc2l0aW9uaW5nLmhhc1RyYW5zaXRpb24oKX0saS5wcm90b3R5cGUucmVjYWxjdWxhdGU9ZnVuY3Rpb24odCl7dGhpcy5wcm9wZXJ0aWVzPXRoaXMuX3RyYW5zaXRpb25pbmcucG9zc2libHlFdmFsdWF0ZSh0KTt9LGkucHJvdG90eXBlLl92YWxpZGF0ZT1mdW5jdGlvbihlLGksbyl7cmV0dXJuICghb3x8ITEhPT1vLnZhbGlkYXRlKSYmdC5lbWl0VmFsaWRhdGlvbkVycm9ycyh0aGlzLGUuY2FsbCh0LnZhbGlkYXRlU3R5bGUsdC5leHRlbmQoe3ZhbHVlOmksc3R5bGU6e2dseXBoczohMCxzcHJpdGU6ITB9LHN0eWxlU3BlYzp0LnN0eWxlU3BlY30pKSl9LGl9KHQuRXZlbnRlZCksdz1mdW5jdGlvbih0LGUpe3RoaXMud2lkdGg9dCx0aGlzLmhlaWdodD1lLHRoaXMubmV4dFJvdz0wLHRoaXMuYnl0ZXM9NCx0aGlzLmRhdGE9bmV3IFVpbnQ4QXJyYXkodGhpcy53aWR0aCp0aGlzLmhlaWdodCp0aGlzLmJ5dGVzKSx0aGlzLnBvc2l0aW9ucz17fTt9O3cucHJvdG90eXBlLmdldERhc2g9ZnVuY3Rpb24odCxlKXt2YXIgaT10LmpvaW4oXCIsXCIpK1N0cmluZyhlKTtyZXR1cm4gdGhpcy5wb3NpdGlvbnNbaV18fCh0aGlzLnBvc2l0aW9uc1tpXT10aGlzLmFkZERhc2godCxlKSksdGhpcy5wb3NpdGlvbnNbaV19LHcucHJvdG90eXBlLmFkZERhc2g9ZnVuY3Rpb24oZSxpKXt2YXIgbz1pPzc6MCxyPTIqbysxO2lmKHRoaXMubmV4dFJvdytyPnRoaXMuaGVpZ2h0KXJldHVybiB0Lndhcm5PbmNlKFwiTGluZUF0bGFzIG91dCBvZiBzcGFjZVwiKSxudWxsO2Zvcih2YXIgYT0wLG49MDtuPGUubGVuZ3RoO24rKylhKz1lW25dO2Zvcih2YXIgcz10aGlzLndpZHRoL2EsbD1zLzIsYz1lLmxlbmd0aCUyPT0xLHU9LW87dTw9bzt1KyspZm9yKHZhciBoPXRoaXMubmV4dFJvdytvK3UscD10aGlzLndpZHRoKmgsZD1jPy1lW2UubGVuZ3RoLTFdOjAsXz1lWzBdLGY9MSxtPTA7bTx0aGlzLndpZHRoO20rKyl7Zm9yKDtfPG0vczspZD1fLF8rPWVbZl0sYyYmZj09PWUubGVuZ3RoLTEmJihfKz1lWzBdKSxmKys7dmFyIGc9TWF0aC5hYnMobS1kKnMpLHY9TWF0aC5hYnMobS1fKnMpLHk9TWF0aC5taW4oZyx2KSx4PWYlMj09MSxiPXZvaWQgMDtpZihpKXt2YXIgdz1vP3UvbyoobCsxKTowO2lmKHgpe3ZhciBFPWwtTWF0aC5hYnModyk7Yj1NYXRoLnNxcnQoeSp5K0UqRSk7fWVsc2UgYj1sLU1hdGguc3FydCh5Knkrdyp3KTt9ZWxzZSBiPSh4PzE6LTEpKnk7dGhpcy5kYXRhWzMrNCoocCttKV09TWF0aC5tYXgoMCxNYXRoLm1pbigyNTUsYisxMjgpKTt9dmFyIFQ9e3k6KHRoaXMubmV4dFJvdytvKy41KS90aGlzLmhlaWdodCxoZWlnaHQ6MipvL3RoaXMuaGVpZ2h0LHdpZHRoOmF9O3JldHVybiB0aGlzLm5leHRSb3crPXIsdGhpcy5kaXJ0eT0hMCxUfSx3LnByb3RvdHlwZS5iaW5kPWZ1bmN0aW9uKHQpe3ZhciBlPXQuZ2w7dGhpcy50ZXh0dXJlPyhlLmJpbmRUZXh0dXJlKGUuVEVYVFVSRV8yRCx0aGlzLnRleHR1cmUpLHRoaXMuZGlydHkmJih0aGlzLmRpcnR5PSExLGUudGV4U3ViSW1hZ2UyRChlLlRFWFRVUkVfMkQsMCwwLDAsdGhpcy53aWR0aCx0aGlzLmhlaWdodCxlLlJHQkEsZS5VTlNJR05FRF9CWVRFLHRoaXMuZGF0YSkpKToodGhpcy50ZXh0dXJlPWUuY3JlYXRlVGV4dHVyZSgpLGUuYmluZFRleHR1cmUoZS5URVhUVVJFXzJELHRoaXMudGV4dHVyZSksZS50ZXhQYXJhbWV0ZXJpKGUuVEVYVFVSRV8yRCxlLlRFWFRVUkVfV1JBUF9TLGUuUkVQRUFUKSxlLnRleFBhcmFtZXRlcmkoZS5URVhUVVJFXzJELGUuVEVYVFVSRV9XUkFQX1QsZS5SRVBFQVQpLGUudGV4UGFyYW1ldGVyaShlLlRFWFRVUkVfMkQsZS5URVhUVVJFX01JTl9GSUxURVIsZS5MSU5FQVIpLGUudGV4UGFyYW1ldGVyaShlLlRFWFRVUkVfMkQsZS5URVhUVVJFX01BR19GSUxURVIsZS5MSU5FQVIpLGUudGV4SW1hZ2UyRChlLlRFWFRVUkVfMkQsMCxlLlJHQkEsdGhpcy53aWR0aCx0aGlzLmhlaWdodCwwLGUuUkdCQSxlLlVOU0lHTkVEX0JZVEUsdGhpcy5kYXRhKSk7fTt2YXIgRT1mdW5jdGlvbiBlKGksbyl7dGhpcy53b3JrZXJQb29sPWksdGhpcy5hY3RvcnM9W10sdGhpcy5jdXJyZW50QWN0b3I9MCx0aGlzLmlkPXQudW5pcXVlSWQoKTtmb3IodmFyIHI9dGhpcy53b3JrZXJQb29sLmFjcXVpcmUodGhpcy5pZCksYT0wO2E8ci5sZW5ndGg7YSsrKXt2YXIgbj1yW2FdLHM9bmV3IGUuQWN0b3IobixvLHRoaXMuaWQpO3MubmFtZT1cIldvcmtlciBcIithLHRoaXMuYWN0b3JzLnB1c2gocyk7fX07ZnVuY3Rpb24gVChlLGksbyl7dmFyIHI9ZnVuY3Rpb24ocixhKXtpZihyKXJldHVybiBvKHIpO2lmKGEpe3ZhciBuPXQucGljayhhLFtcInRpbGVzXCIsXCJtaW56b29tXCIsXCJtYXh6b29tXCIsXCJhdHRyaWJ1dGlvblwiLFwibWFwYm94X2xvZ29cIixcImJvdW5kc1wiXSk7YS52ZWN0b3JfbGF5ZXJzJiYobi52ZWN0b3JMYXllcnM9YS52ZWN0b3JfbGF5ZXJzLG4udmVjdG9yTGF5ZXJJZHM9bi52ZWN0b3JMYXllcnMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkfSkpLGUudXJsJiYobi50aWxlcz1pLmNhbm9uaWNhbGl6ZVRpbGVzZXQobixlLnVybCkpLG8obnVsbCxuKTt9fTtyZXR1cm4gZS51cmw/dC5nZXRKU09OKGkudHJhbnNmb3JtUmVxdWVzdChpLm5vcm1hbGl6ZVNvdXJjZVVSTChlLnVybCksdC5SZXNvdXJjZVR5cGUuU291cmNlKSxyKTp0LmJyb3dzZXIuZnJhbWUoZnVuY3Rpb24oKXtyZXR1cm4gcihudWxsLGUpfSl9RS5wcm90b3R5cGUuYnJvYWRjYXN0PWZ1bmN0aW9uKGUsaSxvKXtvPW98fGZ1bmN0aW9uKCl7fSx0LmFzeW5jQWxsKHRoaXMuYWN0b3JzLGZ1bmN0aW9uKHQsbyl7dC5zZW5kKGUsaSxvKTt9LG8pO30sRS5wcm90b3R5cGUuc2VuZD1mdW5jdGlvbih0LGUsaSxvKXtyZXR1cm4gKFwibnVtYmVyXCIhPXR5cGVvZiBvfHxpc05hTihvKSkmJihvPXRoaXMuY3VycmVudEFjdG9yPSh0aGlzLmN1cnJlbnRBY3RvcisxKSV0aGlzLmFjdG9ycy5sZW5ndGgpLHRoaXMuYWN0b3JzW29dLnNlbmQodCxlLGkpLG99LEUucHJvdG90eXBlLnJlbW92ZT1mdW5jdGlvbigpe3RoaXMuYWN0b3JzLmZvckVhY2goZnVuY3Rpb24odCl7dC5yZW1vdmUoKTt9KSx0aGlzLmFjdG9ycz1bXSx0aGlzLndvcmtlclBvb2wucmVsZWFzZSh0aGlzLmlkKTt9LEUuQWN0b3I9dC5BY3Rvcjt2YXIgST1mdW5jdGlvbihlLGksbyl7dGhpcy5ib3VuZHM9dC5MbmdMYXRCb3VuZHMuY29udmVydCh0aGlzLnZhbGlkYXRlQm91bmRzKGUpKSx0aGlzLm1pbnpvb209aXx8MCx0aGlzLm1heHpvb209b3x8MjQ7fTtJLnByb3RvdHlwZS52YWxpZGF0ZUJvdW5kcz1mdW5jdGlvbih0KXtyZXR1cm4gQXJyYXkuaXNBcnJheSh0KSYmND09PXQubGVuZ3RoP1tNYXRoLm1heCgtMTgwLHRbMF0pLE1hdGgubWF4KC05MCx0WzFdKSxNYXRoLm1pbigxODAsdFsyXSksTWF0aC5taW4oOTAsdFszXSldOlstMTgwLC05MCwxODAsOTBdfSxJLnByb3RvdHlwZS5jb250YWlucz1mdW5jdGlvbihlKXt2YXIgaT1NYXRoLnBvdygyLGUueiksbz1NYXRoLmZsb29yKHQubWVyY2F0b3JYZnJvbUxuZyh0aGlzLmJvdW5kcy5nZXRXZXN0KCkpKmkpLHI9TWF0aC5mbG9vcih0Lm1lcmNhdG9yWWZyb21MYXQodGhpcy5ib3VuZHMuZ2V0Tm9ydGgoKSkqaSksYT1NYXRoLmNlaWwodC5tZXJjYXRvclhmcm9tTG5nKHRoaXMuYm91bmRzLmdldEVhc3QoKSkqaSksbj1NYXRoLmNlaWwodC5tZXJjYXRvcllmcm9tTGF0KHRoaXMuYm91bmRzLmdldFNvdXRoKCkpKmkpO3JldHVybiBlLng+PW8mJmUueDxhJiZlLnk+PXImJmUueTxufTt2YXIgQz1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKGksbyxyLGEpe2lmKGUuY2FsbCh0aGlzKSx0aGlzLmlkPWksdGhpcy5kaXNwYXRjaGVyPXIsdGhpcy50eXBlPVwidmVjdG9yXCIsdGhpcy5taW56b29tPTAsdGhpcy5tYXh6b29tPTIyLHRoaXMuc2NoZW1lPVwieHl6XCIsdGhpcy50aWxlU2l6ZT01MTIsdGhpcy5yZXBhcnNlT3ZlcnNjYWxlZD0hMCx0aGlzLmlzVGlsZUNsaXBwZWQ9ITAsdC5leHRlbmQodGhpcyx0LnBpY2sobyxbXCJ1cmxcIixcInNjaGVtZVwiLFwidGlsZVNpemVcIl0pKSx0aGlzLl9vcHRpb25zPXQuZXh0ZW5kKHt0eXBlOlwidmVjdG9yXCJ9LG8pLHRoaXMuX2NvbGxlY3RSZXNvdXJjZVRpbWluZz1vLmNvbGxlY3RSZXNvdXJjZVRpbWluZyw1MTIhPT10aGlzLnRpbGVTaXplKXRocm93IG5ldyBFcnJvcihcInZlY3RvciB0aWxlIHNvdXJjZXMgbXVzdCBoYXZlIGEgdGlsZVNpemUgb2YgNTEyXCIpO3RoaXMuc2V0RXZlbnRlZFBhcmVudChhKTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmxvYWQ9ZnVuY3Rpb24oKXt2YXIgZT10aGlzO3RoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFsb2FkaW5nXCIse2RhdGFUeXBlOlwic291cmNlXCJ9KSksdGhpcy5fdGlsZUpTT05SZXF1ZXN0PVQodGhpcy5fb3B0aW9ucyx0aGlzLm1hcC5fcmVxdWVzdE1hbmFnZXIsZnVuY3Rpb24oaSxvKXtlLl90aWxlSlNPTlJlcXVlc3Q9bnVsbCxpP2UuZmlyZShuZXcgdC5FcnJvckV2ZW50KGkpKTpvJiYodC5leHRlbmQoZSxvKSxvLmJvdW5kcyYmKGUudGlsZUJvdW5kcz1uZXcgSShvLmJvdW5kcyxlLm1pbnpvb20sZS5tYXh6b29tKSksdC5wb3N0VHVybnN0aWxlRXZlbnQoby50aWxlcyksdC5wb3N0TWFwTG9hZEV2ZW50KG8udGlsZXMsZS5tYXAuX2dldE1hcElkKCksZS5tYXAuX3JlcXVlc3RNYW5hZ2VyLl9za3VUb2tlbiksZS5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInNvdXJjZVwiLHNvdXJjZURhdGFUeXBlOlwibWV0YWRhdGFcIn0pKSxlLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhXCIse2RhdGFUeXBlOlwic291cmNlXCIsc291cmNlRGF0YVR5cGU6XCJjb250ZW50XCJ9KSkpO30pO30saS5wcm90b3R5cGUuaGFzVGlsZT1mdW5jdGlvbih0KXtyZXR1cm4gIXRoaXMudGlsZUJvdW5kc3x8dGhpcy50aWxlQm91bmRzLmNvbnRhaW5zKHQuY2Fub25pY2FsKX0saS5wcm90b3R5cGUub25BZGQ9ZnVuY3Rpb24odCl7dGhpcy5tYXA9dCx0aGlzLmxvYWQoKTt9LGkucHJvdG90eXBlLm9uUmVtb3ZlPWZ1bmN0aW9uKCl7dGhpcy5fdGlsZUpTT05SZXF1ZXN0JiYodGhpcy5fdGlsZUpTT05SZXF1ZXN0LmNhbmNlbCgpLHRoaXMuX3RpbGVKU09OUmVxdWVzdD1udWxsKTt9LGkucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3JldHVybiB0LmV4dGVuZCh7fSx0aGlzLl9vcHRpb25zKX0saS5wcm90b3R5cGUubG9hZFRpbGU9ZnVuY3Rpb24oZSxpKXt2YXIgbz10aGlzLm1hcC5fcmVxdWVzdE1hbmFnZXIubm9ybWFsaXplVGlsZVVSTChlLnRpbGVJRC5jYW5vbmljYWwudXJsKHRoaXMudGlsZXMsdGhpcy5zY2hlbWUpLHRoaXMudXJsLG51bGwpLHI9e3JlcXVlc3Q6dGhpcy5tYXAuX3JlcXVlc3RNYW5hZ2VyLnRyYW5zZm9ybVJlcXVlc3Qobyx0LlJlc291cmNlVHlwZS5UaWxlKSx1aWQ6ZS51aWQsdGlsZUlEOmUudGlsZUlELHpvb206ZS50aWxlSUQub3ZlcnNjYWxlZFosdGlsZVNpemU6dGhpcy50aWxlU2l6ZSplLnRpbGVJRC5vdmVyc2NhbGVGYWN0b3IoKSx0eXBlOnRoaXMudHlwZSxzb3VyY2U6dGhpcy5pZCxwaXhlbFJhdGlvOnQuYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvLHNob3dDb2xsaXNpb25Cb3hlczp0aGlzLm1hcC5zaG93Q29sbGlzaW9uQm94ZXN9O2Z1bmN0aW9uIGEobyxyKXtyZXR1cm4gZS5hYm9ydGVkP2kobnVsbCk6byYmNDA0IT09by5zdGF0dXM/aShvKToociYmci5yZXNvdXJjZVRpbWluZyYmKGUucmVzb3VyY2VUaW1pbmc9ci5yZXNvdXJjZVRpbWluZyksdGhpcy5tYXAuX3JlZnJlc2hFeHBpcmVkVGlsZXMmJnImJmUuc2V0RXhwaXJ5RGF0YShyKSxlLmxvYWRWZWN0b3JEYXRhKHIsdGhpcy5tYXAucGFpbnRlciksdC5jYWNoZUVudHJ5UG9zc2libHlBZGRlZCh0aGlzLmRpc3BhdGNoZXIpLGkobnVsbCksdm9pZChlLnJlbG9hZENhbGxiYWNrJiYodGhpcy5sb2FkVGlsZShlLGUucmVsb2FkQ2FsbGJhY2spLGUucmVsb2FkQ2FsbGJhY2s9bnVsbCkpKX1yLnJlcXVlc3QuY29sbGVjdFJlc291cmNlVGltaW5nPXRoaXMuX2NvbGxlY3RSZXNvdXJjZVRpbWluZyx2b2lkIDA9PT1lLndvcmtlcklEfHxcImV4cGlyZWRcIj09PWUuc3RhdGU/ZS53b3JrZXJJRD10aGlzLmRpc3BhdGNoZXIuc2VuZChcImxvYWRUaWxlXCIscixhLmJpbmQodGhpcykpOlwibG9hZGluZ1wiPT09ZS5zdGF0ZT9lLnJlbG9hZENhbGxiYWNrPWk6dGhpcy5kaXNwYXRjaGVyLnNlbmQoXCJyZWxvYWRUaWxlXCIscixhLmJpbmQodGhpcyksZS53b3JrZXJJRCk7fSxpLnByb3RvdHlwZS5hYm9ydFRpbGU9ZnVuY3Rpb24odCl7dGhpcy5kaXNwYXRjaGVyLnNlbmQoXCJhYm9ydFRpbGVcIix7dWlkOnQudWlkLHR5cGU6dGhpcy50eXBlLHNvdXJjZTp0aGlzLmlkfSx2b2lkIDAsdC53b3JrZXJJRCk7fSxpLnByb3RvdHlwZS51bmxvYWRUaWxlPWZ1bmN0aW9uKHQpe3QudW5sb2FkVmVjdG9yRGF0YSgpLHRoaXMuZGlzcGF0Y2hlci5zZW5kKFwicmVtb3ZlVGlsZVwiLHt1aWQ6dC51aWQsdHlwZTp0aGlzLnR5cGUsc291cmNlOnRoaXMuaWR9LHZvaWQgMCx0LndvcmtlcklEKTt9LGkucHJvdG90eXBlLmhhc1RyYW5zaXRpb249ZnVuY3Rpb24oKXtyZXR1cm4gITF9LGl9KHQuRXZlbnRlZCksUz1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKGksbyxyLGEpe2UuY2FsbCh0aGlzKSx0aGlzLmlkPWksdGhpcy5kaXNwYXRjaGVyPXIsdGhpcy5zZXRFdmVudGVkUGFyZW50KGEpLHRoaXMudHlwZT1cInJhc3RlclwiLHRoaXMubWluem9vbT0wLHRoaXMubWF4em9vbT0yMix0aGlzLnJvdW5kWm9vbT0hMCx0aGlzLnNjaGVtZT1cInh5elwiLHRoaXMudGlsZVNpemU9NTEyLHRoaXMuX2xvYWRlZD0hMSx0aGlzLl9vcHRpb25zPXQuZXh0ZW5kKHt9LG8pLHQuZXh0ZW5kKHRoaXMsdC5waWNrKG8sW1widXJsXCIsXCJzY2hlbWVcIixcInRpbGVTaXplXCJdKSk7fXJldHVybiBlJiYoaS5fX3Byb3RvX189ZSksaS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShlJiZlLnByb3RvdHlwZSksaS5wcm90b3R5cGUuY29uc3RydWN0b3I9aSxpLnByb3RvdHlwZS5sb2FkPWZ1bmN0aW9uKCl7dmFyIGU9dGhpczt0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhbG9hZGluZ1wiLHtkYXRhVHlwZTpcInNvdXJjZVwifSkpLHRoaXMuX3RpbGVKU09OUmVxdWVzdD1UKHRoaXMuX29wdGlvbnMsdGhpcy5tYXAuX3JlcXVlc3RNYW5hZ2VyLGZ1bmN0aW9uKGksbyl7ZS5fdGlsZUpTT05SZXF1ZXN0PW51bGwsaT9lLmZpcmUobmV3IHQuRXJyb3JFdmVudChpKSk6byYmKHQuZXh0ZW5kKGUsbyksby5ib3VuZHMmJihlLnRpbGVCb3VuZHM9bmV3IEkoby5ib3VuZHMsZS5taW56b29tLGUubWF4em9vbSkpLHQucG9zdFR1cm5zdGlsZUV2ZW50KG8udGlsZXMpLHQucG9zdE1hcExvYWRFdmVudChvLnRpbGVzLGUubWFwLl9nZXRNYXBJZCgpLGUubWFwLl9yZXF1ZXN0TWFuYWdlci5fc2t1VG9rZW4pLGUuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIix7ZGF0YVR5cGU6XCJzb3VyY2VcIixzb3VyY2VEYXRhVHlwZTpcIm1ldGFkYXRhXCJ9KSksZS5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInNvdXJjZVwiLHNvdXJjZURhdGFUeXBlOlwiY29udGVudFwifSkpKTt9KTt9LGkucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKHQpe3RoaXMubWFwPXQsdGhpcy5sb2FkKCk7fSxpLnByb3RvdHlwZS5vblJlbW92ZT1mdW5jdGlvbigpe3RoaXMuX3RpbGVKU09OUmVxdWVzdCYmKHRoaXMuX3RpbGVKU09OUmVxdWVzdC5jYW5jZWwoKSx0aGlzLl90aWxlSlNPTlJlcXVlc3Q9bnVsbCk7fSxpLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXtyZXR1cm4gdC5leHRlbmQoe30sdGhpcy5fb3B0aW9ucyl9LGkucHJvdG90eXBlLmhhc1RpbGU9ZnVuY3Rpb24odCl7cmV0dXJuICF0aGlzLnRpbGVCb3VuZHN8fHRoaXMudGlsZUJvdW5kcy5jb250YWlucyh0LmNhbm9uaWNhbCl9LGkucHJvdG90eXBlLmxvYWRUaWxlPWZ1bmN0aW9uKGUsaSl7dmFyIG89dGhpcyxyPXRoaXMubWFwLl9yZXF1ZXN0TWFuYWdlci5ub3JtYWxpemVUaWxlVVJMKGUudGlsZUlELmNhbm9uaWNhbC51cmwodGhpcy50aWxlcyx0aGlzLnNjaGVtZSksdGhpcy51cmwsdGhpcy50aWxlU2l6ZSk7ZS5yZXF1ZXN0PXQuZ2V0SW1hZ2UodGhpcy5tYXAuX3JlcXVlc3RNYW5hZ2VyLnRyYW5zZm9ybVJlcXVlc3Qocix0LlJlc291cmNlVHlwZS5UaWxlKSxmdW5jdGlvbihyLGEpe2lmKGRlbGV0ZSBlLnJlcXVlc3QsZS5hYm9ydGVkKWUuc3RhdGU9XCJ1bmxvYWRlZFwiLGkobnVsbCk7ZWxzZSBpZihyKWUuc3RhdGU9XCJlcnJvcmVkXCIsaShyKTtlbHNlIGlmKGEpe28ubWFwLl9yZWZyZXNoRXhwaXJlZFRpbGVzJiZlLnNldEV4cGlyeURhdGEoYSksZGVsZXRlIGEuY2FjaGVDb250cm9sLGRlbGV0ZSBhLmV4cGlyZXM7dmFyIG49by5tYXAucGFpbnRlci5jb250ZXh0LHM9bi5nbDtlLnRleHR1cmU9by5tYXAucGFpbnRlci5nZXRUaWxlVGV4dHVyZShhLndpZHRoKSxlLnRleHR1cmU/ZS50ZXh0dXJlLnVwZGF0ZShhLHt1c2VNaXBtYXA6ITB9KTooZS50ZXh0dXJlPW5ldyB0LlRleHR1cmUobixhLHMuUkdCQSx7dXNlTWlwbWFwOiEwfSksZS50ZXh0dXJlLmJpbmQocy5MSU5FQVIscy5DTEFNUF9UT19FREdFLHMuTElORUFSX01JUE1BUF9ORUFSRVNUKSxuLmV4dFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpYyYmcy50ZXhQYXJhbWV0ZXJmKHMuVEVYVFVSRV8yRCxuLmV4dFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpYy5URVhUVVJFX01BWF9BTklTT1RST1BZX0VYVCxuLmV4dFRleHR1cmVGaWx0ZXJBbmlzb3Ryb3BpY01heCkpLGUuc3RhdGU9XCJsb2FkZWRcIix0LmNhY2hlRW50cnlQb3NzaWJseUFkZGVkKG8uZGlzcGF0Y2hlciksaShudWxsKTt9fSk7fSxpLnByb3RvdHlwZS5hYm9ydFRpbGU9ZnVuY3Rpb24odCxlKXt0LnJlcXVlc3QmJih0LnJlcXVlc3QuY2FuY2VsKCksZGVsZXRlIHQucmVxdWVzdCksZSgpO30saS5wcm90b3R5cGUudW5sb2FkVGlsZT1mdW5jdGlvbih0LGUpe3QudGV4dHVyZSYmdGhpcy5tYXAucGFpbnRlci5zYXZlVGlsZVRleHR1cmUodC50ZXh0dXJlKSxlKCk7fSxpLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9uPWZ1bmN0aW9uKCl7cmV0dXJuICExfSxpfSh0LkV2ZW50ZWQpLFA9ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gaShpLG8scixhKXtlLmNhbGwodGhpcyxpLG8scixhKSx0aGlzLnR5cGU9XCJyYXN0ZXItZGVtXCIsdGhpcy5tYXh6b29tPTIyLHRoaXMuX29wdGlvbnM9dC5leHRlbmQoe30sbyksdGhpcy5lbmNvZGluZz1vLmVuY29kaW5nfHxcIm1hcGJveFwiO31yZXR1cm4gZSYmKGkuX19wcm90b19fPWUpLGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLGkucHJvdG90eXBlLmNvbnN0cnVjdG9yPWksaS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuIHt0eXBlOlwicmFzdGVyLWRlbVwiLHVybDp0aGlzLnVybCx0aWxlU2l6ZTp0aGlzLnRpbGVTaXplLHRpbGVzOnRoaXMudGlsZXMsYm91bmRzOnRoaXMuYm91bmRzLGVuY29kaW5nOnRoaXMuZW5jb2Rpbmd9fSxpLnByb3RvdHlwZS5sb2FkVGlsZT1mdW5jdGlvbihlLGkpe3ZhciBvPXRoaXMubWFwLl9yZXF1ZXN0TWFuYWdlci5ub3JtYWxpemVUaWxlVVJMKGUudGlsZUlELmNhbm9uaWNhbC51cmwodGhpcy50aWxlcyx0aGlzLnNjaGVtZSksdGhpcy51cmwsdGhpcy50aWxlU2l6ZSk7ZS5yZXF1ZXN0PXQuZ2V0SW1hZ2UodGhpcy5tYXAuX3JlcXVlc3RNYW5hZ2VyLnRyYW5zZm9ybVJlcXVlc3Qobyx0LlJlc291cmNlVHlwZS5UaWxlKSxmdW5jdGlvbihvLHIpe2lmKGRlbGV0ZSBlLnJlcXVlc3QsZS5hYm9ydGVkKWUuc3RhdGU9XCJ1bmxvYWRlZFwiLGkobnVsbCk7ZWxzZSBpZihvKWUuc3RhdGU9XCJlcnJvcmVkXCIsaShvKTtlbHNlIGlmKHIpe3RoaXMubWFwLl9yZWZyZXNoRXhwaXJlZFRpbGVzJiZlLnNldEV4cGlyeURhdGEociksZGVsZXRlIHIuY2FjaGVDb250cm9sLGRlbGV0ZSByLmV4cGlyZXM7dmFyIGE9dC5icm93c2VyLmdldEltYWdlRGF0YShyKSxuPXt1aWQ6ZS51aWQsY29vcmQ6ZS50aWxlSUQsc291cmNlOnRoaXMuaWQscmF3SW1hZ2VEYXRhOmEsZW5jb2Rpbmc6dGhpcy5lbmNvZGluZ307ZS53b3JrZXJJRCYmXCJleHBpcmVkXCIhPT1lLnN0YXRlfHwoZS53b3JrZXJJRD10aGlzLmRpc3BhdGNoZXIuc2VuZChcImxvYWRERU1UaWxlXCIsbixmdW5jdGlvbih0LG8pe3QmJihlLnN0YXRlPVwiZXJyb3JlZFwiLGkodCkpO28mJihlLmRlbT1vLGUubmVlZHNIaWxsc2hhZGVQcmVwYXJlPSEwLGUuc3RhdGU9XCJsb2FkZWRcIixpKG51bGwpKTt9LmJpbmQodGhpcykpKTt9fS5iaW5kKHRoaXMpKSxlLm5laWdoYm9yaW5nVGlsZXM9dGhpcy5fZ2V0TmVpZ2hib3JpbmdUaWxlcyhlLnRpbGVJRCk7fSxpLnByb3RvdHlwZS5fZ2V0TmVpZ2hib3JpbmdUaWxlcz1mdW5jdGlvbihlKXt2YXIgaT1lLmNhbm9uaWNhbCxvPU1hdGgucG93KDIsaS56KSxyPShpLngtMStvKSVvLGE9MD09PWkueD9lLndyYXAtMTplLndyYXAsbj0oaS54KzErbyklbyxzPWkueCsxPT09bz9lLndyYXArMTplLndyYXAsbD17fTtyZXR1cm4gbFtuZXcgdC5PdmVyc2NhbGVkVGlsZUlEKGUub3ZlcnNjYWxlZFosYSxpLnoscixpLnkpLmtleV09e2JhY2tmaWxsZWQ6ITF9LGxbbmV3IHQuT3ZlcnNjYWxlZFRpbGVJRChlLm92ZXJzY2FsZWRaLHMsaS56LG4saS55KS5rZXldPXtiYWNrZmlsbGVkOiExfSxpLnk+MCYmKGxbbmV3IHQuT3ZlcnNjYWxlZFRpbGVJRChlLm92ZXJzY2FsZWRaLGEsaS56LHIsaS55LTEpLmtleV09e2JhY2tmaWxsZWQ6ITF9LGxbbmV3IHQuT3ZlcnNjYWxlZFRpbGVJRChlLm92ZXJzY2FsZWRaLGUud3JhcCxpLnosaS54LGkueS0xKS5rZXldPXtiYWNrZmlsbGVkOiExfSxsW25ldyB0Lk92ZXJzY2FsZWRUaWxlSUQoZS5vdmVyc2NhbGVkWixzLGkueixuLGkueS0xKS5rZXldPXtiYWNrZmlsbGVkOiExfSksaS55KzE8byYmKGxbbmV3IHQuT3ZlcnNjYWxlZFRpbGVJRChlLm92ZXJzY2FsZWRaLGEsaS56LHIsaS55KzEpLmtleV09e2JhY2tmaWxsZWQ6ITF9LGxbbmV3IHQuT3ZlcnNjYWxlZFRpbGVJRChlLm92ZXJzY2FsZWRaLGUud3JhcCxpLnosaS54LGkueSsxKS5rZXldPXtiYWNrZmlsbGVkOiExfSxsW25ldyB0Lk92ZXJzY2FsZWRUaWxlSUQoZS5vdmVyc2NhbGVkWixzLGkueixuLGkueSsxKS5rZXldPXtiYWNrZmlsbGVkOiExfSksbH0saS5wcm90b3R5cGUudW5sb2FkVGlsZT1mdW5jdGlvbih0KXt0LmRlbVRleHR1cmUmJnRoaXMubWFwLnBhaW50ZXIuc2F2ZVRpbGVUZXh0dXJlKHQuZGVtVGV4dHVyZSksdC5mYm8mJih0LmZiby5kZXN0cm95KCksZGVsZXRlIHQuZmJvKSx0LmRlbSYmZGVsZXRlIHQuZGVtLGRlbGV0ZSB0Lm5laWdoYm9yaW5nVGlsZXMsdC5zdGF0ZT1cInVubG9hZGVkXCIsdGhpcy5kaXNwYXRjaGVyLnNlbmQoXCJyZW1vdmVERU1UaWxlXCIse3VpZDp0LnVpZCxzb3VyY2U6dGhpcy5pZH0sdm9pZCAwLHQud29ya2VySUQpO30saX0oUyksej1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKGksbyxyLGEpe2UuY2FsbCh0aGlzKSx0aGlzLmlkPWksdGhpcy50eXBlPVwiZ2VvanNvblwiLHRoaXMubWluem9vbT0wLHRoaXMubWF4em9vbT0xOCx0aGlzLnRpbGVTaXplPTUxMix0aGlzLmlzVGlsZUNsaXBwZWQ9ITAsdGhpcy5yZXBhcnNlT3ZlcnNjYWxlZD0hMCx0aGlzLl9yZW1vdmVkPSExLHRoaXMuZGlzcGF0Y2hlcj1yLHRoaXMuc2V0RXZlbnRlZFBhcmVudChhKSx0aGlzLl9kYXRhPW8uZGF0YSx0aGlzLl9vcHRpb25zPXQuZXh0ZW5kKHt9LG8pLHRoaXMuX2NvbGxlY3RSZXNvdXJjZVRpbWluZz1vLmNvbGxlY3RSZXNvdXJjZVRpbWluZyx0aGlzLl9yZXNvdXJjZVRpbWluZz1bXSx2b2lkIDAhPT1vLm1heHpvb20mJih0aGlzLm1heHpvb209by5tYXh6b29tKSxvLnR5cGUmJih0aGlzLnR5cGU9by50eXBlKSxvLmF0dHJpYnV0aW9uJiYodGhpcy5hdHRyaWJ1dGlvbj1vLmF0dHJpYnV0aW9uKTt2YXIgbj10LkVYVEVOVC90aGlzLnRpbGVTaXplO3RoaXMud29ya2VyT3B0aW9ucz10LmV4dGVuZCh7c291cmNlOnRoaXMuaWQsY2x1c3RlcjpvLmNsdXN0ZXJ8fCExLGdlb2pzb25WdE9wdGlvbnM6e2J1ZmZlcjoodm9pZCAwIT09by5idWZmZXI/by5idWZmZXI6MTI4KSpuLHRvbGVyYW5jZToodm9pZCAwIT09by50b2xlcmFuY2U/by50b2xlcmFuY2U6LjM3NSkqbixleHRlbnQ6dC5FWFRFTlQsbWF4Wm9vbTp0aGlzLm1heHpvb20sbGluZU1ldHJpY3M6by5saW5lTWV0cmljc3x8ITEsZ2VuZXJhdGVJZDpvLmdlbmVyYXRlSWR8fCExfSxzdXBlcmNsdXN0ZXJPcHRpb25zOnttYXhab29tOnZvaWQgMCE9PW8uY2x1c3Rlck1heFpvb20/TWF0aC5taW4oby5jbHVzdGVyTWF4Wm9vbSx0aGlzLm1heHpvb20tMSk6dGhpcy5tYXh6b29tLTEsZXh0ZW50OnQuRVhURU5ULHJhZGl1czooby5jbHVzdGVyUmFkaXVzfHw1MCkqbixsb2c6ITF9LGNsdXN0ZXJQcm9wZXJ0aWVzOm8uY2x1c3RlclByb3BlcnRpZXN9LG8ud29ya2VyT3B0aW9ucyk7fXJldHVybiBlJiYoaS5fX3Byb3RvX189ZSksaS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShlJiZlLnByb3RvdHlwZSksaS5wcm90b3R5cGUuY29uc3RydWN0b3I9aSxpLnByb3RvdHlwZS5sb2FkPWZ1bmN0aW9uKCl7dmFyIGU9dGhpczt0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhbG9hZGluZ1wiLHtkYXRhVHlwZTpcInNvdXJjZVwifSkpLHRoaXMuX3VwZGF0ZVdvcmtlckRhdGEoZnVuY3Rpb24oaSl7aWYoaSllLmZpcmUobmV3IHQuRXJyb3JFdmVudChpKSk7ZWxzZXt2YXIgbz17ZGF0YVR5cGU6XCJzb3VyY2VcIixzb3VyY2VEYXRhVHlwZTpcIm1ldGFkYXRhXCJ9O2UuX2NvbGxlY3RSZXNvdXJjZVRpbWluZyYmZS5fcmVzb3VyY2VUaW1pbmcmJmUuX3Jlc291cmNlVGltaW5nLmxlbmd0aD4wJiYoby5yZXNvdXJjZVRpbWluZz1lLl9yZXNvdXJjZVRpbWluZyxlLl9yZXNvdXJjZVRpbWluZz1bXSksZS5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLG8pKTt9fSk7fSxpLnByb3RvdHlwZS5vbkFkZD1mdW5jdGlvbih0KXt0aGlzLm1hcD10LHRoaXMubG9hZCgpO30saS5wcm90b3R5cGUuc2V0RGF0YT1mdW5jdGlvbihlKXt2YXIgaT10aGlzO3JldHVybiB0aGlzLl9kYXRhPWUsdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YWxvYWRpbmdcIix7ZGF0YVR5cGU6XCJzb3VyY2VcIn0pKSx0aGlzLl91cGRhdGVXb3JrZXJEYXRhKGZ1bmN0aW9uKGUpe2lmKGUpaS5maXJlKG5ldyB0LkVycm9yRXZlbnQoZSkpO2Vsc2V7dmFyIG89e2RhdGFUeXBlOlwic291cmNlXCIsc291cmNlRGF0YVR5cGU6XCJjb250ZW50XCJ9O2kuX2NvbGxlY3RSZXNvdXJjZVRpbWluZyYmaS5fcmVzb3VyY2VUaW1pbmcmJmkuX3Jlc291cmNlVGltaW5nLmxlbmd0aD4wJiYoby5yZXNvdXJjZVRpbWluZz1pLl9yZXNvdXJjZVRpbWluZyxpLl9yZXNvdXJjZVRpbWluZz1bXSksaS5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLG8pKTt9fSksdGhpc30saS5wcm90b3R5cGUuZ2V0Q2x1c3RlckV4cGFuc2lvblpvb209ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5kaXNwYXRjaGVyLnNlbmQoXCJnZW9qc29uLmdldENsdXN0ZXJFeHBhbnNpb25ab29tXCIse2NsdXN0ZXJJZDp0LHNvdXJjZTp0aGlzLmlkfSxlLHRoaXMud29ya2VySUQpLHRoaXN9LGkucHJvdG90eXBlLmdldENsdXN0ZXJDaGlsZHJlbj1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmRpc3BhdGNoZXIuc2VuZChcImdlb2pzb24uZ2V0Q2x1c3RlckNoaWxkcmVuXCIse2NsdXN0ZXJJZDp0LHNvdXJjZTp0aGlzLmlkfSxlLHRoaXMud29ya2VySUQpLHRoaXN9LGkucHJvdG90eXBlLmdldENsdXN0ZXJMZWF2ZXM9ZnVuY3Rpb24odCxlLGksbyl7cmV0dXJuIHRoaXMuZGlzcGF0Y2hlci5zZW5kKFwiZ2VvanNvbi5nZXRDbHVzdGVyTGVhdmVzXCIse3NvdXJjZTp0aGlzLmlkLGNsdXN0ZXJJZDp0LGxpbWl0OmUsb2Zmc2V0Oml9LG8sdGhpcy53b3JrZXJJRCksdGhpc30saS5wcm90b3R5cGUuX3VwZGF0ZVdvcmtlckRhdGE9ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcyxvPXQuZXh0ZW5kKHt9LHRoaXMud29ya2VyT3B0aW9ucykscj10aGlzLl9kYXRhO1wic3RyaW5nXCI9PXR5cGVvZiByPyhvLnJlcXVlc3Q9dGhpcy5tYXAuX3JlcXVlc3RNYW5hZ2VyLnRyYW5zZm9ybVJlcXVlc3QodC5icm93c2VyLnJlc29sdmVVUkwociksdC5SZXNvdXJjZVR5cGUuU291cmNlKSxvLnJlcXVlc3QuY29sbGVjdFJlc291cmNlVGltaW5nPXRoaXMuX2NvbGxlY3RSZXNvdXJjZVRpbWluZyk6by5kYXRhPUpTT04uc3RyaW5naWZ5KHIpLHRoaXMud29ya2VySUQ9dGhpcy5kaXNwYXRjaGVyLnNlbmQodGhpcy50eXBlK1wiLmxvYWREYXRhXCIsbyxmdW5jdGlvbih0LHIpe2kuX3JlbW92ZWR8fHImJnIuYWJhbmRvbmVkfHwoaS5fbG9hZGVkPSEwLHImJnIucmVzb3VyY2VUaW1pbmcmJnIucmVzb3VyY2VUaW1pbmdbaS5pZF0mJihpLl9yZXNvdXJjZVRpbWluZz1yLnJlc291cmNlVGltaW5nW2kuaWRdLnNsaWNlKDApKSxpLmRpc3BhdGNoZXIuc2VuZChpLnR5cGUrXCIuY29hbGVzY2VcIix7c291cmNlOm8uc291cmNlfSxudWxsLGkud29ya2VySUQpLGUodCkpO30sdGhpcy53b3JrZXJJRCk7fSxpLnByb3RvdHlwZS5sb2FkVGlsZT1mdW5jdGlvbihlLGkpe3ZhciBvPXRoaXMscj12b2lkIDA9PT1lLndvcmtlcklEP1wibG9hZFRpbGVcIjpcInJlbG9hZFRpbGVcIixhPXt0eXBlOnRoaXMudHlwZSx1aWQ6ZS51aWQsdGlsZUlEOmUudGlsZUlELHpvb206ZS50aWxlSUQub3ZlcnNjYWxlZFosbWF4Wm9vbTp0aGlzLm1heHpvb20sdGlsZVNpemU6dGhpcy50aWxlU2l6ZSxzb3VyY2U6dGhpcy5pZCxwaXhlbFJhdGlvOnQuYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvLHNob3dDb2xsaXNpb25Cb3hlczp0aGlzLm1hcC5zaG93Q29sbGlzaW9uQm94ZXN9O2Uud29ya2VySUQ9dGhpcy5kaXNwYXRjaGVyLnNlbmQocixhLGZ1bmN0aW9uKHQsYSl7cmV0dXJuIGUudW5sb2FkVmVjdG9yRGF0YSgpLGUuYWJvcnRlZD9pKG51bGwpOnQ/aSh0KTooZS5sb2FkVmVjdG9yRGF0YShhLG8ubWFwLnBhaW50ZXIsXCJyZWxvYWRUaWxlXCI9PT1yKSxpKG51bGwpKX0sdGhpcy53b3JrZXJJRCk7fSxpLnByb3RvdHlwZS5hYm9ydFRpbGU9ZnVuY3Rpb24odCl7dC5hYm9ydGVkPSEwO30saS5wcm90b3R5cGUudW5sb2FkVGlsZT1mdW5jdGlvbih0KXt0LnVubG9hZFZlY3RvckRhdGEoKSx0aGlzLmRpc3BhdGNoZXIuc2VuZChcInJlbW92ZVRpbGVcIix7dWlkOnQudWlkLHR5cGU6dGhpcy50eXBlLHNvdXJjZTp0aGlzLmlkfSxudWxsLHQud29ya2VySUQpO30saS5wcm90b3R5cGUub25SZW1vdmU9ZnVuY3Rpb24oKXt0aGlzLl9yZW1vdmVkPSEwLHRoaXMuZGlzcGF0Y2hlci5zZW5kKFwicmVtb3ZlU291cmNlXCIse3R5cGU6dGhpcy50eXBlLHNvdXJjZTp0aGlzLmlkfSxudWxsLHRoaXMud29ya2VySUQpO30saS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuIHQuZXh0ZW5kKHt9LHRoaXMuX29wdGlvbnMse3R5cGU6dGhpcy50eXBlLGRhdGE6dGhpcy5fZGF0YX0pfSxpLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9uPWZ1bmN0aW9uKCl7cmV0dXJuICExfSxpfSh0LkV2ZW50ZWQpLEw9ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gaSh0LGksbyxyKXtlLmNhbGwodGhpcyksdGhpcy5pZD10LHRoaXMuZGlzcGF0Y2hlcj1vLHRoaXMuY29vcmRpbmF0ZXM9aS5jb29yZGluYXRlcyx0aGlzLnR5cGU9XCJpbWFnZVwiLHRoaXMubWluem9vbT0wLHRoaXMubWF4em9vbT0yMix0aGlzLnRpbGVTaXplPTUxMix0aGlzLnRpbGVzPXt9LHRoaXMuc2V0RXZlbnRlZFBhcmVudChyKSx0aGlzLm9wdGlvbnM9aTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmxvYWQ9ZnVuY3Rpb24oZSxpKXt2YXIgbz10aGlzO3RoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFsb2FkaW5nXCIse2RhdGFUeXBlOlwic291cmNlXCJ9KSksdGhpcy51cmw9dGhpcy5vcHRpb25zLnVybCx0LmdldEltYWdlKHRoaXMubWFwLl9yZXF1ZXN0TWFuYWdlci50cmFuc2Zvcm1SZXF1ZXN0KHRoaXMudXJsLHQuUmVzb3VyY2VUeXBlLkltYWdlKSxmdW5jdGlvbihyLGEpe3I/by5maXJlKG5ldyB0LkVycm9yRXZlbnQocikpOmEmJihvLmltYWdlPWEsZSYmKG8uY29vcmRpbmF0ZXM9ZSksaSYmaSgpLG8uX2ZpbmlzaExvYWRpbmcoKSk7fSk7fSxpLnByb3RvdHlwZS51cGRhdGVJbWFnZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzO3JldHVybiB0aGlzLmltYWdlJiZ0LnVybD8odGhpcy5vcHRpb25zLnVybD10LnVybCx0aGlzLmxvYWQodC5jb29yZGluYXRlcyxmdW5jdGlvbigpe2UudGV4dHVyZT1udWxsO30pLHRoaXMpOnRoaXN9LGkucHJvdG90eXBlLl9maW5pc2hMb2FkaW5nPWZ1bmN0aW9uKCl7dGhpcy5tYXAmJih0aGlzLnNldENvb3JkaW5hdGVzKHRoaXMuY29vcmRpbmF0ZXMpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIix7ZGF0YVR5cGU6XCJzb3VyY2VcIixzb3VyY2VEYXRhVHlwZTpcIm1ldGFkYXRhXCJ9KSkpO30saS5wcm90b3R5cGUub25BZGQ9ZnVuY3Rpb24odCl7dGhpcy5tYXA9dCx0aGlzLmxvYWQoKTt9LGkucHJvdG90eXBlLnNldENvb3JkaW5hdGVzPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXM7dGhpcy5jb29yZGluYXRlcz1lO3ZhciBvPWUubWFwKHQuTWVyY2F0b3JDb29yZGluYXRlLmZyb21MbmdMYXQpO3RoaXMudGlsZUlEPWZ1bmN0aW9uKGUpe2Zvcih2YXIgaT0xLzAsbz0xLzAscj0tMS8wLGE9LTEvMCxuPTAscz1lO248cy5sZW5ndGg7bis9MSl7dmFyIGw9c1tuXTtpPU1hdGgubWluKGksbC54KSxvPU1hdGgubWluKG8sbC55KSxyPU1hdGgubWF4KHIsbC54KSxhPU1hdGgubWF4KGEsbC55KTt9dmFyIGM9ci1pLHU9YS1vLGg9TWF0aC5tYXgoYyx1KSxwPU1hdGgubWF4KDAsTWF0aC5mbG9vcigtTWF0aC5sb2coaCkvTWF0aC5MTjIpKSxkPU1hdGgucG93KDIscCk7cmV0dXJuIG5ldyB0LkNhbm9uaWNhbFRpbGVJRChwLE1hdGguZmxvb3IoKGkrcikvMipkKSxNYXRoLmZsb29yKChvK2EpLzIqZCkpfShvKSx0aGlzLm1pbnpvb209dGhpcy5tYXh6b29tPXRoaXMudGlsZUlELno7dmFyIHI9by5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIGkudGlsZUlELmdldFRpbGVQb2ludCh0KS5fcm91bmQoKX0pO3JldHVybiB0aGlzLl9ib3VuZHNBcnJheT1uZXcgdC5TdHJ1Y3RBcnJheUxheW91dDRpOCx0aGlzLl9ib3VuZHNBcnJheS5lbXBsYWNlQmFjayhyWzBdLngsclswXS55LDAsMCksdGhpcy5fYm91bmRzQXJyYXkuZW1wbGFjZUJhY2soclsxXS54LHJbMV0ueSx0LkVYVEVOVCwwKSx0aGlzLl9ib3VuZHNBcnJheS5lbXBsYWNlQmFjayhyWzNdLngsclszXS55LDAsdC5FWFRFTlQpLHRoaXMuX2JvdW5kc0FycmF5LmVtcGxhY2VCYWNrKHJbMl0ueCxyWzJdLnksdC5FWFRFTlQsdC5FWFRFTlQpLHRoaXMuYm91bmRzQnVmZmVyJiYodGhpcy5ib3VuZHNCdWZmZXIuZGVzdHJveSgpLGRlbGV0ZSB0aGlzLmJvdW5kc0J1ZmZlciksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInNvdXJjZVwiLHNvdXJjZURhdGFUeXBlOlwiY29udGVudFwifSkpLHRoaXN9LGkucHJvdG90eXBlLnByZXBhcmU9ZnVuY3Rpb24oKXtpZigwIT09T2JqZWN0LmtleXModGhpcy50aWxlcykubGVuZ3RoJiZ0aGlzLmltYWdlKXt2YXIgZT10aGlzLm1hcC5wYWludGVyLmNvbnRleHQsaT1lLmdsO2Zvcih2YXIgbyBpbiB0aGlzLmJvdW5kc0J1ZmZlcnx8KHRoaXMuYm91bmRzQnVmZmVyPWUuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMuX2JvdW5kc0FycmF5LHQucmFzdGVyQm91bmRzQXR0cmlidXRlcy5tZW1iZXJzKSksdGhpcy5ib3VuZHNTZWdtZW50c3x8KHRoaXMuYm91bmRzU2VnbWVudHM9dC5TZWdtZW50VmVjdG9yLnNpbXBsZVNlZ21lbnQoMCwwLDQsMikpLHRoaXMudGV4dHVyZXx8KHRoaXMudGV4dHVyZT1uZXcgdC5UZXh0dXJlKGUsdGhpcy5pbWFnZSxpLlJHQkEpLHRoaXMudGV4dHVyZS5iaW5kKGkuTElORUFSLGkuQ0xBTVBfVE9fRURHRSkpLHRoaXMudGlsZXMpe3ZhciByPXRoaXMudGlsZXNbb107XCJsb2FkZWRcIiE9PXIuc3RhdGUmJihyLnN0YXRlPVwibG9hZGVkXCIsci50ZXh0dXJlPXRoaXMudGV4dHVyZSk7fX19LGkucHJvdG90eXBlLmxvYWRUaWxlPWZ1bmN0aW9uKHQsZSl7dGhpcy50aWxlSUQmJnRoaXMudGlsZUlELmVxdWFscyh0LnRpbGVJRC5jYW5vbmljYWwpPyh0aGlzLnRpbGVzW1N0cmluZyh0LnRpbGVJRC53cmFwKV09dCx0LmJ1Y2tldHM9e30sZShudWxsKSk6KHQuc3RhdGU9XCJlcnJvcmVkXCIsZShudWxsKSk7fSxpLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXtyZXR1cm4ge3R5cGU6XCJpbWFnZVwiLHVybDp0aGlzLm9wdGlvbnMudXJsLGNvb3JkaW5hdGVzOnRoaXMuY29vcmRpbmF0ZXN9fSxpLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9uPWZ1bmN0aW9uKCl7cmV0dXJuICExfSxpfSh0LkV2ZW50ZWQpO3ZhciBEPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIGkodCxpLG8scil7ZS5jYWxsKHRoaXMsdCxpLG8sciksdGhpcy5yb3VuZFpvb209ITAsdGhpcy50eXBlPVwidmlkZW9cIix0aGlzLm9wdGlvbnM9aTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmxvYWQ9ZnVuY3Rpb24oKXt2YXIgZT10aGlzLGk9dGhpcy5vcHRpb25zO3RoaXMudXJscz1bXTtmb3IodmFyIG89MCxyPWkudXJscztvPHIubGVuZ3RoO28rPTEpe3ZhciBhPXJbb107dGhpcy51cmxzLnB1c2godGhpcy5tYXAuX3JlcXVlc3RNYW5hZ2VyLnRyYW5zZm9ybVJlcXVlc3QoYSx0LlJlc291cmNlVHlwZS5Tb3VyY2UpLnVybCk7fXQuZ2V0VmlkZW8odGhpcy51cmxzLGZ1bmN0aW9uKGksbyl7aT9lLmZpcmUobmV3IHQuRXJyb3JFdmVudChpKSk6byYmKGUudmlkZW89byxlLnZpZGVvLmxvb3A9ITAsZS52aWRlby5hZGRFdmVudExpc3RlbmVyKFwicGxheWluZ1wiLGZ1bmN0aW9uKCl7ZS5tYXAudHJpZ2dlclJlcGFpbnQoKTt9KSxlLm1hcCYmZS52aWRlby5wbGF5KCksZS5fZmluaXNoTG9hZGluZygpKTt9KTt9LGkucHJvdG90eXBlLmdldFZpZGVvPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudmlkZW99LGkucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKHQpe3RoaXMubWFwfHwodGhpcy5tYXA9dCx0aGlzLmxvYWQoKSx0aGlzLnZpZGVvJiYodGhpcy52aWRlby5wbGF5KCksdGhpcy5zZXRDb29yZGluYXRlcyh0aGlzLmNvb3JkaW5hdGVzKSkpO30saS5wcm90b3R5cGUucHJlcGFyZT1mdW5jdGlvbigpe2lmKCEoMD09PU9iamVjdC5rZXlzKHRoaXMudGlsZXMpLmxlbmd0aHx8dGhpcy52aWRlby5yZWFkeVN0YXRlPDIpKXt2YXIgZT10aGlzLm1hcC5wYWludGVyLmNvbnRleHQsaT1lLmdsO2Zvcih2YXIgbyBpbiB0aGlzLmJvdW5kc0J1ZmZlcnx8KHRoaXMuYm91bmRzQnVmZmVyPWUuY3JlYXRlVmVydGV4QnVmZmVyKHRoaXMuX2JvdW5kc0FycmF5LHQucmFzdGVyQm91bmRzQXR0cmlidXRlcy5tZW1iZXJzKSksdGhpcy5ib3VuZHNTZWdtZW50c3x8KHRoaXMuYm91bmRzU2VnbWVudHM9dC5TZWdtZW50VmVjdG9yLnNpbXBsZVNlZ21lbnQoMCwwLDQsMikpLHRoaXMudGV4dHVyZT90aGlzLnZpZGVvLnBhdXNlZHx8KHRoaXMudGV4dHVyZS5iaW5kKGkuTElORUFSLGkuQ0xBTVBfVE9fRURHRSksaS50ZXhTdWJJbWFnZTJEKGkuVEVYVFVSRV8yRCwwLDAsMCxpLlJHQkEsaS5VTlNJR05FRF9CWVRFLHRoaXMudmlkZW8pKToodGhpcy50ZXh0dXJlPW5ldyB0LlRleHR1cmUoZSx0aGlzLnZpZGVvLGkuUkdCQSksdGhpcy50ZXh0dXJlLmJpbmQoaS5MSU5FQVIsaS5DTEFNUF9UT19FREdFKSksdGhpcy50aWxlcyl7dmFyIHI9dGhpcy50aWxlc1tvXTtcImxvYWRlZFwiIT09ci5zdGF0ZSYmKHIuc3RhdGU9XCJsb2FkZWRcIixyLnRleHR1cmU9dGhpcy50ZXh0dXJlKTt9fX0saS5wcm90b3R5cGUuc2VyaWFsaXplPWZ1bmN0aW9uKCl7cmV0dXJuIHt0eXBlOlwidmlkZW9cIix1cmxzOnRoaXMudXJscyxjb29yZGluYXRlczp0aGlzLmNvb3JkaW5hdGVzfX0saS5wcm90b3R5cGUuaGFzVHJhbnNpdGlvbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLnZpZGVvJiYhdGhpcy52aWRlby5wYXVzZWR9LGl9KEwpLE09ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gaShpLG8scixhKXtlLmNhbGwodGhpcyxpLG8scixhKSxvLmNvb3JkaW5hdGVzP0FycmF5LmlzQXJyYXkoby5jb29yZGluYXRlcykmJjQ9PT1vLmNvb3JkaW5hdGVzLmxlbmd0aCYmIW8uY29vcmRpbmF0ZXMuc29tZShmdW5jdGlvbih0KXtyZXR1cm4gIUFycmF5LmlzQXJyYXkodCl8fDIhPT10Lmxlbmd0aHx8dC5zb21lKGZ1bmN0aW9uKHQpe3JldHVybiBcIm51bWJlclwiIT10eXBlb2YgdH0pfSl8fHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyB0LlZhbGlkYXRpb25FcnJvcihcInNvdXJjZXMuXCIraSxudWxsLCdcImNvb3JkaW5hdGVzXCIgcHJvcGVydHkgbXVzdCBiZSBhbiBhcnJheSBvZiA0IGxvbmdpdHVkZS9sYXRpdHVkZSBhcnJheSBwYWlycycpKSk6dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IHQuVmFsaWRhdGlvbkVycm9yKFwic291cmNlcy5cIitpLG51bGwsJ21pc3NpbmcgcmVxdWlyZWQgcHJvcGVydHkgXCJjb29yZGluYXRlc1wiJykpKSxvLmFuaW1hdGUmJlwiYm9vbGVhblwiIT10eXBlb2Ygby5hbmltYXRlJiZ0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgdC5WYWxpZGF0aW9uRXJyb3IoXCJzb3VyY2VzLlwiK2ksbnVsbCwnb3B0aW9uYWwgXCJhbmltYXRlXCIgcHJvcGVydHkgbXVzdCBiZSBhIGJvb2xlYW4gdmFsdWUnKSkpLG8uY2FudmFzP1wic3RyaW5nXCI9PXR5cGVvZiBvLmNhbnZhc3x8by5jYW52YXMgaW5zdGFuY2VvZiB0LndpbmRvdy5IVE1MQ2FudmFzRWxlbWVudHx8dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IHQuVmFsaWRhdGlvbkVycm9yKFwic291cmNlcy5cIitpLG51bGwsJ1wiY2FudmFzXCIgbXVzdCBiZSBlaXRoZXIgYSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBJRCBvZiB0aGUgY2FudmFzIGVsZW1lbnQgZnJvbSB3aGljaCB0byByZWFkLCBvciBhbiBIVE1MQ2FudmFzRWxlbWVudCBpbnN0YW5jZScpKSk6dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IHQuVmFsaWRhdGlvbkVycm9yKFwic291cmNlcy5cIitpLG51bGwsJ21pc3NpbmcgcmVxdWlyZWQgcHJvcGVydHkgXCJjYW52YXNcIicpKSksdGhpcy5vcHRpb25zPW8sdGhpcy5hbmltYXRlPXZvaWQgMD09PW8uYW5pbWF0ZXx8by5hbmltYXRlO31yZXR1cm4gZSYmKGkuX19wcm90b19fPWUpLGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLGkucHJvdG90eXBlLmNvbnN0cnVjdG9yPWksaS5wcm90b3R5cGUubG9hZD1mdW5jdGlvbigpe3RoaXMuY2FudmFzfHwodGhpcy5jYW52YXM9dGhpcy5vcHRpb25zLmNhbnZhcyBpbnN0YW5jZW9mIHQud2luZG93LkhUTUxDYW52YXNFbGVtZW50P3RoaXMub3B0aW9ucy5jYW52YXM6dC53aW5kb3cuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5vcHRpb25zLmNhbnZhcykpLHRoaXMud2lkdGg9dGhpcy5jYW52YXMud2lkdGgsdGhpcy5oZWlnaHQ9dGhpcy5jYW52YXMuaGVpZ2h0LHRoaXMuX2hhc0ludmFsaWREaW1lbnNpb25zKCk/dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiQ2FudmFzIGRpbWVuc2lvbnMgY2Fubm90IGJlIGxlc3MgdGhhbiBvciBlcXVhbCB0byB6ZXJvLlwiKSkpOih0aGlzLnBsYXk9ZnVuY3Rpb24oKXt0aGlzLl9wbGF5aW5nPSEwLHRoaXMubWFwLnRyaWdnZXJSZXBhaW50KCk7fSx0aGlzLnBhdXNlPWZ1bmN0aW9uKCl7dGhpcy5fcGxheWluZyYmKHRoaXMucHJlcGFyZSgpLHRoaXMuX3BsYXlpbmc9ITEpO30sdGhpcy5fZmluaXNoTG9hZGluZygpKTt9LGkucHJvdG90eXBlLmdldENhbnZhcz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmNhbnZhc30saS5wcm90b3R5cGUub25BZGQ9ZnVuY3Rpb24odCl7dGhpcy5tYXA9dCx0aGlzLmxvYWQoKSx0aGlzLmNhbnZhcyYmdGhpcy5hbmltYXRlJiZ0aGlzLnBsYXkoKTt9LGkucHJvdG90eXBlLm9uUmVtb3ZlPWZ1bmN0aW9uKCl7dGhpcy5wYXVzZSgpO30saS5wcm90b3R5cGUucHJlcGFyZT1mdW5jdGlvbigpe3ZhciBlPSExO2lmKHRoaXMuY2FudmFzLndpZHRoIT09dGhpcy53aWR0aCYmKHRoaXMud2lkdGg9dGhpcy5jYW52YXMud2lkdGgsZT0hMCksdGhpcy5jYW52YXMuaGVpZ2h0IT09dGhpcy5oZWlnaHQmJih0aGlzLmhlaWdodD10aGlzLmNhbnZhcy5oZWlnaHQsZT0hMCksIXRoaXMuX2hhc0ludmFsaWREaW1lbnNpb25zKCkmJjAhPT1PYmplY3Qua2V5cyh0aGlzLnRpbGVzKS5sZW5ndGgpe3ZhciBpPXRoaXMubWFwLnBhaW50ZXIuY29udGV4dCxvPWkuZ2w7Zm9yKHZhciByIGluIHRoaXMuYm91bmRzQnVmZmVyfHwodGhpcy5ib3VuZHNCdWZmZXI9aS5jcmVhdGVWZXJ0ZXhCdWZmZXIodGhpcy5fYm91bmRzQXJyYXksdC5yYXN0ZXJCb3VuZHNBdHRyaWJ1dGVzLm1lbWJlcnMpKSx0aGlzLmJvdW5kc1NlZ21lbnRzfHwodGhpcy5ib3VuZHNTZWdtZW50cz10LlNlZ21lbnRWZWN0b3Iuc2ltcGxlU2VnbWVudCgwLDAsNCwyKSksdGhpcy50ZXh0dXJlPyhlfHx0aGlzLl9wbGF5aW5nKSYmdGhpcy50ZXh0dXJlLnVwZGF0ZSh0aGlzLmNhbnZhcyx7cHJlbXVsdGlwbHk6ITB9KTp0aGlzLnRleHR1cmU9bmV3IHQuVGV4dHVyZShpLHRoaXMuY2FudmFzLG8uUkdCQSx7cHJlbXVsdGlwbHk6ITB9KSx0aGlzLnRpbGVzKXt2YXIgYT10aGlzLnRpbGVzW3JdO1wibG9hZGVkXCIhPT1hLnN0YXRlJiYoYS5zdGF0ZT1cImxvYWRlZFwiLGEudGV4dHVyZT10aGlzLnRleHR1cmUpO319fSxpLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXtyZXR1cm4ge3R5cGU6XCJjYW52YXNcIixjb29yZGluYXRlczp0aGlzLmNvb3JkaW5hdGVzfX0saS5wcm90b3R5cGUuaGFzVHJhbnNpdGlvbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9wbGF5aW5nfSxpLnByb3RvdHlwZS5faGFzSW52YWxpZERpbWVuc2lvbnM9ZnVuY3Rpb24oKXtmb3IodmFyIHQ9MCxlPVt0aGlzLmNhbnZhcy53aWR0aCx0aGlzLmNhbnZhcy5oZWlnaHRdO3Q8ZS5sZW5ndGg7dCs9MSl7dmFyIGk9ZVt0XTtpZihpc05hTihpKXx8aTw9MClyZXR1cm4gITB9cmV0dXJuICExfSxpfShMKSxSPXt2ZWN0b3I6QyxyYXN0ZXI6UyxcInJhc3Rlci1kZW1cIjpQLGdlb2pzb246eix2aWRlbzpELGltYWdlOkwsY2FudmFzOk19LEE9ZnVuY3Rpb24oZSxpLG8scil7dmFyIGE9bmV3IFJbaS50eXBlXShlLGksbyxyKTtpZihhLmlkIT09ZSl0aHJvdyBuZXcgRXJyb3IoXCJFeHBlY3RlZCBTb3VyY2UgaWQgdG8gYmUgXCIrZStcIiBpbnN0ZWFkIG9mIFwiK2EuaWQpO3JldHVybiB0LmJpbmRBbGwoW1wibG9hZFwiLFwiYWJvcnRcIixcInVubG9hZFwiLFwic2VyaWFsaXplXCIsXCJwcmVwYXJlXCJdLGEpLGF9O2Z1bmN0aW9uIGsoZSxpKXt2YXIgbz10LmlkZW50aXR5KFtdKTtyZXR1cm4gdC50cmFuc2xhdGUobyxvLFsxLDEsMF0pLHQuc2NhbGUobyxvLFsuNSplLndpZHRoLC41KmUuaGVpZ2h0LDFdKSx0Lm11bHRpcGx5KG8sbyxlLmNhbGN1bGF0ZVBvc01hdHJpeChpLnRvVW53cmFwcGVkKCkpKX1mdW5jdGlvbiBCKHQsZSxpLG8scil7dmFyIGE9ZnVuY3Rpb24odCxlLGkpe2lmKHQpZm9yKHZhciBvPTAscj10O288ci5sZW5ndGg7bys9MSl7dmFyIGE9ZVtyW29dXTtpZihhJiZhLnNvdXJjZT09PWkmJlwiZmlsbC1leHRydXNpb25cIj09PWEudHlwZSlyZXR1cm4gITB9ZWxzZSBmb3IodmFyIG4gaW4gZSl7dmFyIHM9ZVtuXTtpZihzLnNvdXJjZT09PWkmJlwiZmlsbC1leHRydXNpb25cIj09PXMudHlwZSlyZXR1cm4gITB9cmV0dXJuICExfShvJiZvLmxheWVycyxlLHQuaWQpLG49ci5tYXhQaXRjaFNjYWxlRmFjdG9yKCkscz10LnRpbGVzSW4oaSxuLGEpO3Muc29ydChPKTtmb3IodmFyIGw9W10sYz0wLHU9cztjPHUubGVuZ3RoO2MrPTEpe3ZhciBoPXVbY107bC5wdXNoKHt3cmFwcGVkVGlsZUlEOmgudGlsZUlELndyYXBwZWQoKS5rZXkscXVlcnlSZXN1bHRzOmgudGlsZS5xdWVyeVJlbmRlcmVkRmVhdHVyZXMoZSx0Ll9zdGF0ZSxoLnF1ZXJ5R2VvbWV0cnksaC5jYW1lcmFRdWVyeUdlb21ldHJ5LGguc2NhbGUsbyxyLG4sayh0LnRyYW5zZm9ybSxoLnRpbGVJRCkpfSk7fXZhciBwPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT17fSxpPXt9LG89MCxyPXQ7bzxyLmxlbmd0aDtvKz0xKXt2YXIgYT1yW29dLG49YS5xdWVyeVJlc3VsdHMscz1hLndyYXBwZWRUaWxlSUQsbD1pW3NdPWlbc118fHt9O2Zvcih2YXIgYyBpbiBuKWZvcih2YXIgdT1uW2NdLGg9bFtjXT1sW2NdfHx7fSxwPWVbY109ZVtjXXx8W10sZD0wLF89dTtkPF8ubGVuZ3RoO2QrPTEpe3ZhciBmPV9bZF07aFtmLmZlYXR1cmVJbmRleF18fChoW2YuZmVhdHVyZUluZGV4XT0hMCxwLnB1c2goZikpO319cmV0dXJuIGV9KGwpO2Zvcih2YXIgZCBpbiBwKXBbZF0uZm9yRWFjaChmdW5jdGlvbihlKXt2YXIgaT1lLmZlYXR1cmUsbz10LmdldEZlYXR1cmVTdGF0ZShpLmxheWVyW1wic291cmNlLWxheWVyXCJdLGkuaWQpO2kuc291cmNlPWkubGF5ZXIuc291cmNlLGkubGF5ZXJbXCJzb3VyY2UtbGF5ZXJcIl0mJihpLnNvdXJjZUxheWVyPWkubGF5ZXJbXCJzb3VyY2UtbGF5ZXJcIl0pLGkuc3RhdGU9bzt9KTtyZXR1cm4gcH1mdW5jdGlvbiBPKHQsZSl7dmFyIGk9dC50aWxlSUQsbz1lLnRpbGVJRDtyZXR1cm4gaS5vdmVyc2NhbGVkWi1vLm92ZXJzY2FsZWRafHxpLmNhbm9uaWNhbC55LW8uY2Fub25pY2FsLnl8fGkud3JhcC1vLndyYXB8fGkuY2Fub25pY2FsLngtby5jYW5vbmljYWwueH12YXIgRj1mdW5jdGlvbih0LGUpe3RoaXMubWF4PXQsdGhpcy5vblJlbW92ZT1lLHRoaXMucmVzZXQoKTt9O0YucHJvdG90eXBlLnJlc2V0PWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMuZGF0YSlmb3IodmFyIGU9MCxpPXRoaXMuZGF0YVt0XTtlPGkubGVuZ3RoO2UrPTEpe3ZhciBvPWlbZV07by50aW1lb3V0JiZjbGVhclRpbWVvdXQoby50aW1lb3V0KSx0aGlzLm9uUmVtb3ZlKG8udmFsdWUpO31yZXR1cm4gdGhpcy5kYXRhPXt9LHRoaXMub3JkZXI9W10sdGhpc30sRi5wcm90b3R5cGUuYWRkPWZ1bmN0aW9uKHQsZSxpKXt2YXIgbz10aGlzLHI9dC53cmFwcGVkKCkua2V5O3ZvaWQgMD09PXRoaXMuZGF0YVtyXSYmKHRoaXMuZGF0YVtyXT1bXSk7dmFyIGE9e3ZhbHVlOmUsdGltZW91dDp2b2lkIDB9O2lmKHZvaWQgMCE9PWkmJihhLnRpbWVvdXQ9c2V0VGltZW91dChmdW5jdGlvbigpe28ucmVtb3ZlKHQsYSk7fSxpKSksdGhpcy5kYXRhW3JdLnB1c2goYSksdGhpcy5vcmRlci5wdXNoKHIpLHRoaXMub3JkZXIubGVuZ3RoPnRoaXMubWF4KXt2YXIgbj10aGlzLl9nZXRBbmRSZW1vdmVCeUtleSh0aGlzLm9yZGVyWzBdKTtuJiZ0aGlzLm9uUmVtb3ZlKG4pO31yZXR1cm4gdGhpc30sRi5wcm90b3R5cGUuaGFzPWZ1bmN0aW9uKHQpe3JldHVybiB0LndyYXBwZWQoKS5rZXkgaW4gdGhpcy5kYXRhfSxGLnByb3RvdHlwZS5nZXRBbmRSZW1vdmU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuaGFzKHQpP3RoaXMuX2dldEFuZFJlbW92ZUJ5S2V5KHQud3JhcHBlZCgpLmtleSk6bnVsbH0sRi5wcm90b3R5cGUuX2dldEFuZFJlbW92ZUJ5S2V5PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuZGF0YVt0XS5zaGlmdCgpO3JldHVybiBlLnRpbWVvdXQmJmNsZWFyVGltZW91dChlLnRpbWVvdXQpLDA9PT10aGlzLmRhdGFbdF0ubGVuZ3RoJiZkZWxldGUgdGhpcy5kYXRhW3RdLHRoaXMub3JkZXIuc3BsaWNlKHRoaXMub3JkZXIuaW5kZXhPZih0KSwxKSxlLnZhbHVlfSxGLnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuaGFzKHQpP3RoaXMuZGF0YVt0LndyYXBwZWQoKS5rZXldWzBdLnZhbHVlOm51bGx9LEYucHJvdG90eXBlLnJlbW92ZT1mdW5jdGlvbih0LGUpe2lmKCF0aGlzLmhhcyh0KSlyZXR1cm4gdGhpczt2YXIgaT10LndyYXBwZWQoKS5rZXksbz12b2lkIDA9PT1lPzA6dGhpcy5kYXRhW2ldLmluZGV4T2YoZSkscj10aGlzLmRhdGFbaV1bb107cmV0dXJuIHRoaXMuZGF0YVtpXS5zcGxpY2UobywxKSxyLnRpbWVvdXQmJmNsZWFyVGltZW91dChyLnRpbWVvdXQpLDA9PT10aGlzLmRhdGFbaV0ubGVuZ3RoJiZkZWxldGUgdGhpcy5kYXRhW2ldLHRoaXMub25SZW1vdmUoci52YWx1ZSksdGhpcy5vcmRlci5zcGxpY2UodGhpcy5vcmRlci5pbmRleE9mKGkpLDEpLHRoaXN9LEYucHJvdG90eXBlLnNldE1heFNpemU9ZnVuY3Rpb24odCl7Zm9yKHRoaXMubWF4PXQ7dGhpcy5vcmRlci5sZW5ndGg+dGhpcy5tYXg7KXt2YXIgZT10aGlzLl9nZXRBbmRSZW1vdmVCeUtleSh0aGlzLm9yZGVyWzBdKTtlJiZ0aGlzLm9uUmVtb3ZlKGUpO31yZXR1cm4gdGhpc307dmFyIFU9ZnVuY3Rpb24odCxlLGkpe3RoaXMuY29udGV4dD10O3ZhciBvPXQuZ2w7dGhpcy5idWZmZXI9by5jcmVhdGVCdWZmZXIoKSx0aGlzLmR5bmFtaWNEcmF3PUJvb2xlYW4oaSksdGhpcy5jb250ZXh0LnVuYmluZFZBTygpLHQuYmluZEVsZW1lbnRCdWZmZXIuc2V0KHRoaXMuYnVmZmVyKSxvLmJ1ZmZlckRhdGEoby5FTEVNRU5UX0FSUkFZX0JVRkZFUixlLmFycmF5QnVmZmVyLHRoaXMuZHluYW1pY0RyYXc/by5EWU5BTUlDX0RSQVc6by5TVEFUSUNfRFJBVyksdGhpcy5keW5hbWljRHJhd3x8ZGVsZXRlIGUuYXJyYXlCdWZmZXI7fTtVLnByb3RvdHlwZS5iaW5kPWZ1bmN0aW9uKCl7dGhpcy5jb250ZXh0LmJpbmRFbGVtZW50QnVmZmVyLnNldCh0aGlzLmJ1ZmZlcik7fSxVLnByb3RvdHlwZS51cGRhdGVEYXRhPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuY29udGV4dC5nbDt0aGlzLmNvbnRleHQudW5iaW5kVkFPKCksdGhpcy5iaW5kKCksZS5idWZmZXJTdWJEYXRhKGUuRUxFTUVOVF9BUlJBWV9CVUZGRVIsMCx0LmFycmF5QnVmZmVyKTt9LFUucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmNvbnRleHQuZ2w7dGhpcy5idWZmZXImJih0LmRlbGV0ZUJ1ZmZlcih0aGlzLmJ1ZmZlciksZGVsZXRlIHRoaXMuYnVmZmVyKTt9O3ZhciBOPXtJbnQ4OlwiQllURVwiLFVpbnQ4OlwiVU5TSUdORURfQllURVwiLEludDE2OlwiU0hPUlRcIixVaW50MTY6XCJVTlNJR05FRF9TSE9SVFwiLEludDMyOlwiSU5UXCIsVWludDMyOlwiVU5TSUdORURfSU5UXCIsRmxvYXQzMjpcIkZMT0FUXCJ9LFo9ZnVuY3Rpb24odCxlLGksbyl7dGhpcy5sZW5ndGg9ZS5sZW5ndGgsdGhpcy5hdHRyaWJ1dGVzPWksdGhpcy5pdGVtU2l6ZT1lLmJ5dGVzUGVyRWxlbWVudCx0aGlzLmR5bmFtaWNEcmF3PW8sdGhpcy5jb250ZXh0PXQ7dmFyIHI9dC5nbDt0aGlzLmJ1ZmZlcj1yLmNyZWF0ZUJ1ZmZlcigpLHQuYmluZFZlcnRleEJ1ZmZlci5zZXQodGhpcy5idWZmZXIpLHIuYnVmZmVyRGF0YShyLkFSUkFZX0JVRkZFUixlLmFycmF5QnVmZmVyLHRoaXMuZHluYW1pY0RyYXc/ci5EWU5BTUlDX0RSQVc6ci5TVEFUSUNfRFJBVyksdGhpcy5keW5hbWljRHJhd3x8ZGVsZXRlIGUuYXJyYXlCdWZmZXI7fTtaLnByb3RvdHlwZS5iaW5kPWZ1bmN0aW9uKCl7dGhpcy5jb250ZXh0LmJpbmRWZXJ0ZXhCdWZmZXIuc2V0KHRoaXMuYnVmZmVyKTt9LFoucHJvdG90eXBlLnVwZGF0ZURhdGE9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jb250ZXh0LmdsO3RoaXMuYmluZCgpLGUuYnVmZmVyU3ViRGF0YShlLkFSUkFZX0JVRkZFUiwwLHQuYXJyYXlCdWZmZXIpO30sWi5wcm90b3R5cGUuZW5hYmxlQXR0cmlidXRlcz1mdW5jdGlvbih0LGUpe2Zvcih2YXIgaT0wO2k8dGhpcy5hdHRyaWJ1dGVzLmxlbmd0aDtpKyspe3ZhciBvPXRoaXMuYXR0cmlidXRlc1tpXSxyPWUuYXR0cmlidXRlc1tvLm5hbWVdO3ZvaWQgMCE9PXImJnQuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkocik7fX0sWi5wcm90b3R5cGUuc2V0VmVydGV4QXR0cmliUG9pbnRlcnM9ZnVuY3Rpb24odCxlLGkpe2Zvcih2YXIgbz0wO288dGhpcy5hdHRyaWJ1dGVzLmxlbmd0aDtvKyspe3ZhciByPXRoaXMuYXR0cmlidXRlc1tvXSxhPWUuYXR0cmlidXRlc1tyLm5hbWVdO3ZvaWQgMCE9PWEmJnQudmVydGV4QXR0cmliUG9pbnRlcihhLHIuY29tcG9uZW50cyx0W05bci50eXBlXV0sITEsdGhpcy5pdGVtU2l6ZSxyLm9mZnNldCt0aGlzLml0ZW1TaXplKihpfHwwKSk7fX0sWi5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3ZhciB0PXRoaXMuY29udGV4dC5nbDt0aGlzLmJ1ZmZlciYmKHQuZGVsZXRlQnVmZmVyKHRoaXMuYnVmZmVyKSxkZWxldGUgdGhpcy5idWZmZXIpO307dmFyIGo9ZnVuY3Rpb24odCl7dGhpcy5nbD10LmdsLHRoaXMuZGVmYXVsdD10aGlzLmdldERlZmF1bHQoKSx0aGlzLmN1cnJlbnQ9dGhpcy5kZWZhdWx0LHRoaXMuZGlydHk9ITE7fTtqLnByb3RvdHlwZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jdXJyZW50fSxqLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7fSxqLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZGVmYXVsdH0sai5wcm90b3R5cGUuc2V0RGVmYXVsdD1mdW5jdGlvbigpe3RoaXMuc2V0KHRoaXMuZGVmYXVsdCk7fTt2YXIgcT1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKCl7ZS5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiBlJiYoaS5fX3Byb3RvX189ZSksaS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShlJiZlLnByb3RvdHlwZSksaS5wcm90b3R5cGUuY29uc3RydWN0b3I9aSxpLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7cmV0dXJuIHQuQ29sb3IudHJhbnNwYXJlbnR9LGkucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmN1cnJlbnQ7KHQuciE9PWUucnx8dC5nIT09ZS5nfHx0LmIhPT1lLmJ8fHQuYSE9PWUuYXx8dGhpcy5kaXJ0eSkmJih0aGlzLmdsLmNsZWFyQ29sb3IodC5yLHQuZyx0LmIsdC5hKSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGl9KGopLFY9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0RGVmYXVsdD1mdW5jdGlvbigpe3JldHVybiAxfSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7KHQhPT10aGlzLmN1cnJlbnR8fHRoaXMuZGlydHkpJiYodGhpcy5nbC5jbGVhckRlcHRoKHQpLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITEpO30sZX0oaiksRz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7cmV0dXJuIDB9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXsodCE9PXRoaXMuY3VycmVudHx8dGhpcy5kaXJ0eSkmJih0aGlzLmdsLmNsZWFyU3RlbmNpbCh0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGV9KGopLFc9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0RGVmYXVsdD1mdW5jdGlvbigpe3JldHVybiBbITAsITAsITAsITBdfSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jdXJyZW50Oyh0WzBdIT09ZVswXXx8dFsxXSE9PWVbMV18fHRbMl0hPT1lWzJdfHx0WzNdIT09ZVszXXx8dGhpcy5kaXJ0eSkmJih0aGlzLmdsLmNvbG9yTWFzayh0WzBdLHRbMV0sdFsyXSx0WzNdKSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGV9KGopLFg9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0RGVmYXVsdD1mdW5jdGlvbigpe3JldHVybiAhMH0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpeyh0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KSYmKHRoaXMuZ2wuZGVwdGhNYXNrKHQpLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITEpO30sZX0oaiksSD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7cmV0dXJuIDI1NX0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpeyh0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KSYmKHRoaXMuZ2wuc3RlbmNpbE1hc2sodCksdGhpcy5jdXJyZW50PXQsdGhpcy5kaXJ0eT0hMSk7fSxlfShqKSxLPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4ge2Z1bmM6dGhpcy5nbC5BTFdBWVMscmVmOjAsbWFzazoyNTV9fSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jdXJyZW50Oyh0LmZ1bmMhPT1lLmZ1bmN8fHQucmVmIT09ZS5yZWZ8fHQubWFzayE9PWUubWFza3x8dGhpcy5kaXJ0eSkmJih0aGlzLmdsLnN0ZW5jaWxGdW5jKHQuZnVuYyx0LnJlZix0Lm1hc2spLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITEpO30sZX0oaiksWT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5nbDtyZXR1cm4gW3QuS0VFUCx0LktFRVAsdC5LRUVQXX0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuY3VycmVudDsodFswXSE9PWVbMF18fHRbMV0hPT1lWzFdfHx0WzJdIT09ZVsyXXx8dGhpcy5kaXJ0eSkmJih0aGlzLmdsLnN0ZW5jaWxPcCh0WzBdLHRbMV0sdFsyXSksdGhpcy5jdXJyZW50PXQsdGhpcy5kaXJ0eT0hMSk7fSxlfShqKSxKPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gITF9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KXt2YXIgZT10aGlzLmdsO3Q/ZS5lbmFibGUoZS5TVEVOQ0lMX1RFU1QpOmUuZGlzYWJsZShlLlNURU5DSUxfVEVTVCksdGhpcy5jdXJyZW50PXQsdGhpcy5kaXJ0eT0hMTt9fSxlfShqKSxRPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gWzAsMV19LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmN1cnJlbnQ7KHRbMF0hPT1lWzBdfHx0WzFdIT09ZVsxXXx8dGhpcy5kaXJ0eSkmJih0aGlzLmdsLmRlcHRoUmFuZ2UodFswXSx0WzFdKSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGV9KGopLCQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0RGVmYXVsdD1mdW5jdGlvbigpe3JldHVybiAhMX0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe2lmKHQhPT10aGlzLmN1cnJlbnR8fHRoaXMuZGlydHkpe3ZhciBlPXRoaXMuZ2w7dD9lLmVuYWJsZShlLkRFUFRIX1RFU1QpOmUuZGlzYWJsZShlLkRFUFRIX1RFU1QpLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITE7fX0sZX0oaiksdHQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0RGVmYXVsdD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmdsLkxFU1N9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXsodCE9PXRoaXMuY3VycmVudHx8dGhpcy5kaXJ0eSkmJih0aGlzLmdsLmRlcHRoRnVuYyh0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGV9KGopLGV0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gITF9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KXt2YXIgZT10aGlzLmdsO3Q/ZS5lbmFibGUoZS5CTEVORCk6ZS5kaXNhYmxlKGUuQkxFTkQpLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITE7fX0sZX0oaiksaXQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0RGVmYXVsdD1mdW5jdGlvbigpe3ZhciB0PXRoaXMuZ2w7cmV0dXJuIFt0Lk9ORSx0LlpFUk9dfSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jdXJyZW50Oyh0WzBdIT09ZVswXXx8dFsxXSE9PWVbMV18fHRoaXMuZGlydHkpJiYodGhpcy5nbC5ibGVuZEZ1bmModFswXSx0WzFdKSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGV9KGopLG90PWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIGkoKXtlLmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdC5Db2xvci50cmFuc3BhcmVudH0saS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuY3VycmVudDsodC5yIT09ZS5yfHx0LmchPT1lLmd8fHQuYiE9PWUuYnx8dC5hIT09ZS5hfHx0aGlzLmRpcnR5KSYmKHRoaXMuZ2wuYmxlbmRDb2xvcih0LnIsdC5nLHQuYix0LmEpLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITEpO30saX0oaikscnQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0RGVmYXVsdD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmdsLkZVTkNfQUREfSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7KHQhPT10aGlzLmN1cnJlbnR8fHRoaXMuZGlydHkpJiYodGhpcy5nbC5ibGVuZEVxdWF0aW9uKHQpLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITEpO30sZX0oaiksYXQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0RGVmYXVsdD1mdW5jdGlvbigpe3JldHVybiAhMX0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe2lmKHQhPT10aGlzLmN1cnJlbnR8fHRoaXMuZGlydHkpe3ZhciBlPXRoaXMuZ2w7dD9lLmVuYWJsZShlLkNVTExfRkFDRSk6ZS5kaXNhYmxlKGUuQ1VMTF9GQUNFKSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExO319LGV9KGopLG50PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5nbC5CQUNLfSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7KHQhPT10aGlzLmN1cnJlbnR8fHRoaXMuZGlydHkpJiYodGhpcy5nbC5jdWxsRmFjZSh0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGV9KGopLHN0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5nbC5DQ1d9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXsodCE9PXRoaXMuY3VycmVudHx8dGhpcy5kaXJ0eSkmJih0aGlzLmdsLmZyb250RmFjZSh0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGV9KGopLGx0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpeyh0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KSYmKHRoaXMuZ2wudXNlUHJvZ3JhbSh0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGV9KGopLGN0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5nbC5URVhUVVJFMH0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpeyh0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KSYmKHRoaXMuZ2wuYWN0aXZlVGV4dHVyZSh0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExKTt9LGV9KGopLHV0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmdsO3JldHVybiBbMCwwLHQuZHJhd2luZ0J1ZmZlcldpZHRoLHQuZHJhd2luZ0J1ZmZlckhlaWdodF19LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXt2YXIgZT10aGlzLmN1cnJlbnQ7KHRbMF0hPT1lWzBdfHx0WzFdIT09ZVsxXXx8dFsyXSE9PWVbMl18fHRbM10hPT1lWzNdfHx0aGlzLmRpcnR5KSYmKHRoaXMuZ2wudmlld3BvcnQodFswXSx0WzFdLHRbMl0sdFszXSksdGhpcy5jdXJyZW50PXQsdGhpcy5kaXJ0eT0hMSk7fSxlfShqKSxodD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7cmV0dXJuIG51bGx9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KXt2YXIgZT10aGlzLmdsO2UuYmluZEZyYW1lYnVmZmVyKGUuRlJBTUVCVUZGRVIsdCksdGhpcy5jdXJyZW50PXQsdGhpcy5kaXJ0eT0hMTt9fSxlfShqKSxwdD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7cmV0dXJuIG51bGx9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KXt2YXIgZT10aGlzLmdsO2UuYmluZFJlbmRlcmJ1ZmZlcihlLlJFTkRFUkJVRkZFUix0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExO319LGV9KGopLGR0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe2lmKHQhPT10aGlzLmN1cnJlbnR8fHRoaXMuZGlydHkpe3ZhciBlPXRoaXMuZ2w7ZS5iaW5kVGV4dHVyZShlLlRFWFRVUkVfMkQsdCksdGhpcy5jdXJyZW50PXQsdGhpcy5kaXJ0eT0hMTt9fSxlfShqKSxfdD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7cmV0dXJuIG51bGx9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KXt2YXIgZT10aGlzLmdsO2UuYmluZEJ1ZmZlcihlLkFSUkFZX0JVRkZFUix0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExO319LGV9KGopLGZ0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuZ2w7ZS5iaW5kQnVmZmVyKGUuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdCksdGhpcy5jdXJyZW50PXQsdGhpcy5kaXJ0eT0hMTt9LGV9KGopLG10PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7dC5jYWxsKHRoaXMsZSksdGhpcy52YW89ZS5leHRWZXJ0ZXhBcnJheU9iamVjdDt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe3RoaXMudmFvJiYodCE9PXRoaXMuY3VycmVudHx8dGhpcy5kaXJ0eSkmJih0aGlzLnZhby5iaW5kVmVydGV4QXJyYXlPRVModCksdGhpcy5jdXJyZW50PXQsdGhpcy5kaXJ0eT0hMSk7fSxlfShqKSxndD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7cmV0dXJuIDR9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KXt2YXIgZT10aGlzLmdsO2UucGl4ZWxTdG9yZWkoZS5VTlBBQ0tfQUxJR05NRU5ULHQpLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITE7fX0sZX0oaiksdnQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3QuYXBwbHkodGhpcyxhcmd1bWVudHMpO31yZXR1cm4gdCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWUsZS5wcm90b3R5cGUuZ2V0RGVmYXVsdD1mdW5jdGlvbigpe3JldHVybiAhMX0sZS5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKHQpe2lmKHQhPT10aGlzLmN1cnJlbnR8fHRoaXMuZGlydHkpe3ZhciBlPXRoaXMuZ2w7ZS5waXhlbFN0b3JlaShlLlVOUEFDS19QUkVNVUxUSVBMWV9BTFBIQV9XRUJHTCx0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExO319LGV9KGopLHl0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLmdldERlZmF1bHQ9ZnVuY3Rpb24oKXtyZXR1cm4gITF9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KXt2YXIgZT10aGlzLmdsO2UucGl4ZWxTdG9yZWkoZS5VTlBBQ0tfRkxJUF9ZX1dFQkdMLHQpLHRoaXMuY3VycmVudD10LHRoaXMuZGlydHk9ITE7fX0sZX0oaikseHQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlLGkpe3QuY2FsbCh0aGlzLGUpLHRoaXMuY29udGV4dD1lLHRoaXMucGFyZW50PWk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5nZXREZWZhdWx0PWZ1bmN0aW9uKCl7cmV0dXJuIG51bGx9LGV9KGopLGJ0PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXt0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTt9cmV0dXJuIHQmJihlLl9fcHJvdG9fXz10KSxlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQmJnQucHJvdG90eXBlKSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lLGUucHJvdG90eXBlLnNldERpcnR5PWZ1bmN0aW9uKCl7dGhpcy5kaXJ0eT0hMDt9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0KXtpZih0IT09dGhpcy5jdXJyZW50fHx0aGlzLmRpcnR5KXt0aGlzLmNvbnRleHQuYmluZEZyYW1lYnVmZmVyLnNldCh0aGlzLnBhcmVudCk7dmFyIGU9dGhpcy5nbDtlLmZyYW1lYnVmZmVyVGV4dHVyZTJEKGUuRlJBTUVCVUZGRVIsZS5DT0xPUl9BVFRBQ0hNRU5UMCxlLlRFWFRVUkVfMkQsdCwwKSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExO319LGV9KHh0KSx3dD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7dC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7fXJldHVybiB0JiYoZS5fX3Byb3RvX189dCksZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0JiZ0LnByb3RvdHlwZSksZS5wcm90b3R5cGUuY29uc3RydWN0b3I9ZSxlLnByb3RvdHlwZS5zZXQ9ZnVuY3Rpb24odCl7aWYodCE9PXRoaXMuY3VycmVudHx8dGhpcy5kaXJ0eSl7dGhpcy5jb250ZXh0LmJpbmRGcmFtZWJ1ZmZlci5zZXQodGhpcy5wYXJlbnQpO3ZhciBlPXRoaXMuZ2w7ZS5mcmFtZWJ1ZmZlclJlbmRlcmJ1ZmZlcihlLkZSQU1FQlVGRkVSLGUuREVQVEhfQVRUQUNITUVOVCxlLlJFTkRFUkJVRkZFUix0KSx0aGlzLmN1cnJlbnQ9dCx0aGlzLmRpcnR5PSExO319LGV9KHh0KSxFdD1mdW5jdGlvbih0LGUsaSl7dGhpcy5jb250ZXh0PXQsdGhpcy53aWR0aD1lLHRoaXMuaGVpZ2h0PWk7dmFyIG89dC5nbCxyPXRoaXMuZnJhbWVidWZmZXI9by5jcmVhdGVGcmFtZWJ1ZmZlcigpO3RoaXMuY29sb3JBdHRhY2htZW50PW5ldyBidCh0LHIpLHRoaXMuZGVwdGhBdHRhY2htZW50PW5ldyB3dCh0LHIpO307RXQucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmNvbnRleHQuZ2wsZT10aGlzLmNvbG9yQXR0YWNobWVudC5nZXQoKTtlJiZ0LmRlbGV0ZVRleHR1cmUoZSk7dmFyIGk9dGhpcy5kZXB0aEF0dGFjaG1lbnQuZ2V0KCk7aSYmdC5kZWxldGVSZW5kZXJidWZmZXIoaSksdC5kZWxldGVGcmFtZWJ1ZmZlcih0aGlzLmZyYW1lYnVmZmVyKTt9O3ZhciBUdD1mdW5jdGlvbih0LGUsaSl7dGhpcy5mdW5jPXQsdGhpcy5tYXNrPWUsdGhpcy5yYW5nZT1pO307VHQuUmVhZE9ubHk9ITEsVHQuUmVhZFdyaXRlPSEwLFR0LmRpc2FibGVkPW5ldyBUdCg1MTksVHQuUmVhZE9ubHksWzAsMV0pO3ZhciBJdD1mdW5jdGlvbih0LGUsaSxvLHIsYSl7dGhpcy50ZXN0PXQsdGhpcy5yZWY9ZSx0aGlzLm1hc2s9aSx0aGlzLmZhaWw9byx0aGlzLmRlcHRoRmFpbD1yLHRoaXMucGFzcz1hO307SXQuZGlzYWJsZWQ9bmV3IEl0KHtmdW5jOjUxOSxtYXNrOjB9LDAsMCw3NjgwLDc2ODAsNzY4MCk7dmFyIEN0PWZ1bmN0aW9uKHQsZSxpKXt0aGlzLmJsZW5kRnVuY3Rpb249dCx0aGlzLmJsZW5kQ29sb3I9ZSx0aGlzLm1hc2s9aTt9O0N0LlJlcGxhY2U9WzEsMF0sQ3QuZGlzYWJsZWQ9bmV3IEN0KEN0LlJlcGxhY2UsdC5Db2xvci50cmFuc3BhcmVudCxbITEsITEsITEsITFdKSxDdC51bmJsZW5kZWQ9bmV3IEN0KEN0LlJlcGxhY2UsdC5Db2xvci50cmFuc3BhcmVudCxbITAsITAsITAsITBdKSxDdC5hbHBoYUJsZW5kZWQ9bmV3IEN0KFsxLDc3MV0sdC5Db2xvci50cmFuc3BhcmVudCxbITAsITAsITAsITBdKTt2YXIgU3Q9ZnVuY3Rpb24odCxlLGkpe3RoaXMuZW5hYmxlPXQsdGhpcy5tb2RlPWUsdGhpcy5mcm9udEZhY2U9aTt9O1N0LmRpc2FibGVkPW5ldyBTdCghMSwxMDI5LDIzMDUpLFN0LmJhY2tDQ1c9bmV3IFN0KCEwLDEwMjksMjMwNSk7dmFyIFB0PWZ1bmN0aW9uKHQpe3RoaXMuZ2w9dCx0aGlzLmV4dFZlcnRleEFycmF5T2JqZWN0PXRoaXMuZ2wuZ2V0RXh0ZW5zaW9uKFwiT0VTX3ZlcnRleF9hcnJheV9vYmplY3RcIiksdGhpcy5jbGVhckNvbG9yPW5ldyBxKHRoaXMpLHRoaXMuY2xlYXJEZXB0aD1uZXcgVih0aGlzKSx0aGlzLmNsZWFyU3RlbmNpbD1uZXcgRyh0aGlzKSx0aGlzLmNvbG9yTWFzaz1uZXcgVyh0aGlzKSx0aGlzLmRlcHRoTWFzaz1uZXcgWCh0aGlzKSx0aGlzLnN0ZW5jaWxNYXNrPW5ldyBIKHRoaXMpLHRoaXMuc3RlbmNpbEZ1bmM9bmV3IEsodGhpcyksdGhpcy5zdGVuY2lsT3A9bmV3IFkodGhpcyksdGhpcy5zdGVuY2lsVGVzdD1uZXcgSih0aGlzKSx0aGlzLmRlcHRoUmFuZ2U9bmV3IFEodGhpcyksdGhpcy5kZXB0aFRlc3Q9bmV3ICQodGhpcyksdGhpcy5kZXB0aEZ1bmM9bmV3IHR0KHRoaXMpLHRoaXMuYmxlbmQ9bmV3IGV0KHRoaXMpLHRoaXMuYmxlbmRGdW5jPW5ldyBpdCh0aGlzKSx0aGlzLmJsZW5kQ29sb3I9bmV3IG90KHRoaXMpLHRoaXMuYmxlbmRFcXVhdGlvbj1uZXcgcnQodGhpcyksdGhpcy5jdWxsRmFjZT1uZXcgYXQodGhpcyksdGhpcy5jdWxsRmFjZVNpZGU9bmV3IG50KHRoaXMpLHRoaXMuZnJvbnRGYWNlPW5ldyBzdCh0aGlzKSx0aGlzLnByb2dyYW09bmV3IGx0KHRoaXMpLHRoaXMuYWN0aXZlVGV4dHVyZT1uZXcgY3QodGhpcyksdGhpcy52aWV3cG9ydD1uZXcgdXQodGhpcyksdGhpcy5iaW5kRnJhbWVidWZmZXI9bmV3IGh0KHRoaXMpLHRoaXMuYmluZFJlbmRlcmJ1ZmZlcj1uZXcgcHQodGhpcyksdGhpcy5iaW5kVGV4dHVyZT1uZXcgZHQodGhpcyksdGhpcy5iaW5kVmVydGV4QnVmZmVyPW5ldyBfdCh0aGlzKSx0aGlzLmJpbmRFbGVtZW50QnVmZmVyPW5ldyBmdCh0aGlzKSx0aGlzLmJpbmRWZXJ0ZXhBcnJheU9FUz10aGlzLmV4dFZlcnRleEFycmF5T2JqZWN0JiZuZXcgbXQodGhpcyksdGhpcy5waXhlbFN0b3JlVW5wYWNrPW5ldyBndCh0aGlzKSx0aGlzLnBpeGVsU3RvcmVVbnBhY2tQcmVtdWx0aXBseUFscGhhPW5ldyB2dCh0aGlzKSx0aGlzLnBpeGVsU3RvcmVVbnBhY2tGbGlwWT1uZXcgeXQodGhpcyksdGhpcy5leHRUZXh0dXJlRmlsdGVyQW5pc290cm9waWM9dC5nZXRFeHRlbnNpb24oXCJFWFRfdGV4dHVyZV9maWx0ZXJfYW5pc290cm9waWNcIil8fHQuZ2V0RXh0ZW5zaW9uKFwiTU9aX0VYVF90ZXh0dXJlX2ZpbHRlcl9hbmlzb3Ryb3BpY1wiKXx8dC5nZXRFeHRlbnNpb24oXCJXRUJLSVRfRVhUX3RleHR1cmVfZmlsdGVyX2FuaXNvdHJvcGljXCIpLHRoaXMuZXh0VGV4dHVyZUZpbHRlckFuaXNvdHJvcGljJiYodGhpcy5leHRUZXh0dXJlRmlsdGVyQW5pc290cm9waWNNYXg9dC5nZXRQYXJhbWV0ZXIodGhpcy5leHRUZXh0dXJlRmlsdGVyQW5pc290cm9waWMuTUFYX1RFWFRVUkVfTUFYX0FOSVNPVFJPUFlfRVhUKSksdGhpcy5leHRUZXh0dXJlSGFsZkZsb2F0PXQuZ2V0RXh0ZW5zaW9uKFwiT0VTX3RleHR1cmVfaGFsZl9mbG9hdFwiKSx0aGlzLmV4dFRleHR1cmVIYWxmRmxvYXQmJnQuZ2V0RXh0ZW5zaW9uKFwiT0VTX3RleHR1cmVfaGFsZl9mbG9hdF9saW5lYXJcIik7fTtQdC5wcm90b3R5cGUuc2V0RGVmYXVsdD1mdW5jdGlvbigpe3RoaXMudW5iaW5kVkFPKCksdGhpcy5jbGVhckNvbG9yLnNldERlZmF1bHQoKSx0aGlzLmNsZWFyRGVwdGguc2V0RGVmYXVsdCgpLHRoaXMuY2xlYXJTdGVuY2lsLnNldERlZmF1bHQoKSx0aGlzLmNvbG9yTWFzay5zZXREZWZhdWx0KCksdGhpcy5kZXB0aE1hc2suc2V0RGVmYXVsdCgpLHRoaXMuc3RlbmNpbE1hc2suc2V0RGVmYXVsdCgpLHRoaXMuc3RlbmNpbEZ1bmMuc2V0RGVmYXVsdCgpLHRoaXMuc3RlbmNpbE9wLnNldERlZmF1bHQoKSx0aGlzLnN0ZW5jaWxUZXN0LnNldERlZmF1bHQoKSx0aGlzLmRlcHRoUmFuZ2Uuc2V0RGVmYXVsdCgpLHRoaXMuZGVwdGhUZXN0LnNldERlZmF1bHQoKSx0aGlzLmRlcHRoRnVuYy5zZXREZWZhdWx0KCksdGhpcy5ibGVuZC5zZXREZWZhdWx0KCksdGhpcy5ibGVuZEZ1bmMuc2V0RGVmYXVsdCgpLHRoaXMuYmxlbmRDb2xvci5zZXREZWZhdWx0KCksdGhpcy5ibGVuZEVxdWF0aW9uLnNldERlZmF1bHQoKSx0aGlzLmN1bGxGYWNlLnNldERlZmF1bHQoKSx0aGlzLmN1bGxGYWNlU2lkZS5zZXREZWZhdWx0KCksdGhpcy5mcm9udEZhY2Uuc2V0RGVmYXVsdCgpLHRoaXMucHJvZ3JhbS5zZXREZWZhdWx0KCksdGhpcy5hY3RpdmVUZXh0dXJlLnNldERlZmF1bHQoKSx0aGlzLmJpbmRGcmFtZWJ1ZmZlci5zZXREZWZhdWx0KCksdGhpcy5waXhlbFN0b3JlVW5wYWNrLnNldERlZmF1bHQoKSx0aGlzLnBpeGVsU3RvcmVVbnBhY2tQcmVtdWx0aXBseUFscGhhLnNldERlZmF1bHQoKSx0aGlzLnBpeGVsU3RvcmVVbnBhY2tGbGlwWS5zZXREZWZhdWx0KCk7fSxQdC5wcm90b3R5cGUuc2V0RGlydHk9ZnVuY3Rpb24oKXt0aGlzLmNsZWFyQ29sb3IuZGlydHk9ITAsdGhpcy5jbGVhckRlcHRoLmRpcnR5PSEwLHRoaXMuY2xlYXJTdGVuY2lsLmRpcnR5PSEwLHRoaXMuY29sb3JNYXNrLmRpcnR5PSEwLHRoaXMuZGVwdGhNYXNrLmRpcnR5PSEwLHRoaXMuc3RlbmNpbE1hc2suZGlydHk9ITAsdGhpcy5zdGVuY2lsRnVuYy5kaXJ0eT0hMCx0aGlzLnN0ZW5jaWxPcC5kaXJ0eT0hMCx0aGlzLnN0ZW5jaWxUZXN0LmRpcnR5PSEwLHRoaXMuZGVwdGhSYW5nZS5kaXJ0eT0hMCx0aGlzLmRlcHRoVGVzdC5kaXJ0eT0hMCx0aGlzLmRlcHRoRnVuYy5kaXJ0eT0hMCx0aGlzLmJsZW5kLmRpcnR5PSEwLHRoaXMuYmxlbmRGdW5jLmRpcnR5PSEwLHRoaXMuYmxlbmRDb2xvci5kaXJ0eT0hMCx0aGlzLmJsZW5kRXF1YXRpb24uZGlydHk9ITAsdGhpcy5jdWxsRmFjZS5kaXJ0eT0hMCx0aGlzLmN1bGxGYWNlU2lkZS5kaXJ0eT0hMCx0aGlzLmZyb250RmFjZS5kaXJ0eT0hMCx0aGlzLnByb2dyYW0uZGlydHk9ITAsdGhpcy5hY3RpdmVUZXh0dXJlLmRpcnR5PSEwLHRoaXMudmlld3BvcnQuZGlydHk9ITAsdGhpcy5iaW5kRnJhbWVidWZmZXIuZGlydHk9ITAsdGhpcy5iaW5kUmVuZGVyYnVmZmVyLmRpcnR5PSEwLHRoaXMuYmluZFRleHR1cmUuZGlydHk9ITAsdGhpcy5iaW5kVmVydGV4QnVmZmVyLmRpcnR5PSEwLHRoaXMuYmluZEVsZW1lbnRCdWZmZXIuZGlydHk9ITAsdGhpcy5leHRWZXJ0ZXhBcnJheU9iamVjdCYmKHRoaXMuYmluZFZlcnRleEFycmF5T0VTLmRpcnR5PSEwKSx0aGlzLnBpeGVsU3RvcmVVbnBhY2suZGlydHk9ITAsdGhpcy5waXhlbFN0b3JlVW5wYWNrUHJlbXVsdGlwbHlBbHBoYS5kaXJ0eT0hMCx0aGlzLnBpeGVsU3RvcmVVbnBhY2tGbGlwWS5kaXJ0eT0hMDt9LFB0LnByb3RvdHlwZS5jcmVhdGVJbmRleEJ1ZmZlcj1mdW5jdGlvbih0LGUpe3JldHVybiBuZXcgVSh0aGlzLHQsZSl9LFB0LnByb3RvdHlwZS5jcmVhdGVWZXJ0ZXhCdWZmZXI9ZnVuY3Rpb24odCxlLGkpe3JldHVybiBuZXcgWih0aGlzLHQsZSxpKX0sUHQucHJvdG90eXBlLmNyZWF0ZVJlbmRlcmJ1ZmZlcj1mdW5jdGlvbih0LGUsaSl7dmFyIG89dGhpcy5nbCxyPW8uY3JlYXRlUmVuZGVyYnVmZmVyKCk7cmV0dXJuIHRoaXMuYmluZFJlbmRlcmJ1ZmZlci5zZXQociksby5yZW5kZXJidWZmZXJTdG9yYWdlKG8uUkVOREVSQlVGRkVSLHQsZSxpKSx0aGlzLmJpbmRSZW5kZXJidWZmZXIuc2V0KG51bGwpLHJ9LFB0LnByb3RvdHlwZS5jcmVhdGVGcmFtZWJ1ZmZlcj1mdW5jdGlvbih0LGUpe3JldHVybiBuZXcgRXQodGhpcyx0LGUpfSxQdC5wcm90b3R5cGUuY2xlYXI9ZnVuY3Rpb24odCl7dmFyIGU9dC5jb2xvcixpPXQuZGVwdGgsbz10aGlzLmdsLHI9MDtlJiYocnw9by5DT0xPUl9CVUZGRVJfQklULHRoaXMuY2xlYXJDb2xvci5zZXQoZSksdGhpcy5jb2xvck1hc2suc2V0KFshMCwhMCwhMCwhMF0pKSx2b2lkIDAhPT1pJiYocnw9by5ERVBUSF9CVUZGRVJfQklULHRoaXMuZGVwdGhSYW5nZS5zZXQoWzAsMV0pLHRoaXMuY2xlYXJEZXB0aC5zZXQoaSksdGhpcy5kZXB0aE1hc2suc2V0KCEwKSksby5jbGVhcihyKTt9LFB0LnByb3RvdHlwZS5zZXRDdWxsRmFjZT1mdW5jdGlvbih0KXshMT09PXQuZW5hYmxlP3RoaXMuY3VsbEZhY2Uuc2V0KCExKToodGhpcy5jdWxsRmFjZS5zZXQoITApLHRoaXMuY3VsbEZhY2VTaWRlLnNldCh0Lm1vZGUpLHRoaXMuZnJvbnRGYWNlLnNldCh0LmZyb250RmFjZSkpO30sUHQucHJvdG90eXBlLnNldERlcHRoTW9kZT1mdW5jdGlvbih0KXt0LmZ1bmMhPT10aGlzLmdsLkFMV0FZU3x8dC5tYXNrPyh0aGlzLmRlcHRoVGVzdC5zZXQoITApLHRoaXMuZGVwdGhGdW5jLnNldCh0LmZ1bmMpLHRoaXMuZGVwdGhNYXNrLnNldCh0Lm1hc2spLHRoaXMuZGVwdGhSYW5nZS5zZXQodC5yYW5nZSkpOnRoaXMuZGVwdGhUZXN0LnNldCghMSk7fSxQdC5wcm90b3R5cGUuc2V0U3RlbmNpbE1vZGU9ZnVuY3Rpb24odCl7dC50ZXN0LmZ1bmMhPT10aGlzLmdsLkFMV0FZU3x8dC5tYXNrPyh0aGlzLnN0ZW5jaWxUZXN0LnNldCghMCksdGhpcy5zdGVuY2lsTWFzay5zZXQodC5tYXNrKSx0aGlzLnN0ZW5jaWxPcC5zZXQoW3QuZmFpbCx0LmRlcHRoRmFpbCx0LnBhc3NdKSx0aGlzLnN0ZW5jaWxGdW5jLnNldCh7ZnVuYzp0LnRlc3QuZnVuYyxyZWY6dC5yZWYsbWFzazp0LnRlc3QubWFza30pKTp0aGlzLnN0ZW5jaWxUZXN0LnNldCghMSk7fSxQdC5wcm90b3R5cGUuc2V0Q29sb3JNb2RlPWZ1bmN0aW9uKGUpe3QuZGVlcEVxdWFsKGUuYmxlbmRGdW5jdGlvbixDdC5SZXBsYWNlKT90aGlzLmJsZW5kLnNldCghMSk6KHRoaXMuYmxlbmQuc2V0KCEwKSx0aGlzLmJsZW5kRnVuYy5zZXQoZS5ibGVuZEZ1bmN0aW9uKSx0aGlzLmJsZW5kQ29sb3Iuc2V0KGUuYmxlbmRDb2xvcikpLHRoaXMuY29sb3JNYXNrLnNldChlLm1hc2spO30sUHQucHJvdG90eXBlLnVuYmluZFZBTz1mdW5jdGlvbigpe3RoaXMuZXh0VmVydGV4QXJyYXlPYmplY3QmJnRoaXMuYmluZFZlcnRleEFycmF5T0VTLnNldChudWxsKTt9O3ZhciB6dD1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKGksbyxyKXt2YXIgYT10aGlzO2UuY2FsbCh0aGlzKSx0aGlzLmlkPWksdGhpcy5kaXNwYXRjaGVyPXIsdGhpcy5vbihcImRhdGFcIixmdW5jdGlvbih0KXtcInNvdXJjZVwiPT09dC5kYXRhVHlwZSYmXCJtZXRhZGF0YVwiPT09dC5zb3VyY2VEYXRhVHlwZSYmKGEuX3NvdXJjZUxvYWRlZD0hMCksYS5fc291cmNlTG9hZGVkJiYhYS5fcGF1c2VkJiZcInNvdXJjZVwiPT09dC5kYXRhVHlwZSYmXCJjb250ZW50XCI9PT10LnNvdXJjZURhdGFUeXBlJiYoYS5yZWxvYWQoKSxhLnRyYW5zZm9ybSYmYS51cGRhdGUoYS50cmFuc2Zvcm0pKTt9KSx0aGlzLm9uKFwiZXJyb3JcIixmdW5jdGlvbigpe2EuX3NvdXJjZUVycm9yZWQ9ITA7fSksdGhpcy5fc291cmNlPUEoaSxvLHIsdGhpcyksdGhpcy5fdGlsZXM9e30sdGhpcy5fY2FjaGU9bmV3IEYoMCx0aGlzLl91bmxvYWRUaWxlLmJpbmQodGhpcykpLHRoaXMuX3RpbWVycz17fSx0aGlzLl9jYWNoZVRpbWVycz17fSx0aGlzLl9tYXhUaWxlQ2FjaGVTaXplPW51bGwsdGhpcy5fY292ZXJlZFRpbGVzPXt9LHRoaXMuX3N0YXRlPW5ldyB0LlNvdXJjZUZlYXR1cmVTdGF0ZTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKHQpe3RoaXMubWFwPXQsdGhpcy5fbWF4VGlsZUNhY2hlU2l6ZT10P3QuX21heFRpbGVDYWNoZVNpemU6bnVsbCx0aGlzLl9zb3VyY2UmJnRoaXMuX3NvdXJjZS5vbkFkZCYmdGhpcy5fc291cmNlLm9uQWRkKHQpO30saS5wcm90b3R5cGUub25SZW1vdmU9ZnVuY3Rpb24odCl7dGhpcy5fc291cmNlJiZ0aGlzLl9zb3VyY2Uub25SZW1vdmUmJnRoaXMuX3NvdXJjZS5vblJlbW92ZSh0KTt9LGkucHJvdG90eXBlLmxvYWRlZD1mdW5jdGlvbigpe2lmKHRoaXMuX3NvdXJjZUVycm9yZWQpcmV0dXJuICEwO2lmKCF0aGlzLl9zb3VyY2VMb2FkZWQpcmV0dXJuICExO2Zvcih2YXIgdCBpbiB0aGlzLl90aWxlcyl7dmFyIGU9dGhpcy5fdGlsZXNbdF07aWYoXCJsb2FkZWRcIiE9PWUuc3RhdGUmJlwiZXJyb3JlZFwiIT09ZS5zdGF0ZSlyZXR1cm4gITF9cmV0dXJuICEwfSxpLnByb3RvdHlwZS5nZXRTb3VyY2U9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc291cmNlfSxpLnByb3RvdHlwZS5wYXVzZT1mdW5jdGlvbigpe3RoaXMuX3BhdXNlZD0hMDt9LGkucHJvdG90eXBlLnJlc3VtZT1mdW5jdGlvbigpe2lmKHRoaXMuX3BhdXNlZCl7dmFyIHQ9dGhpcy5fc2hvdWxkUmVsb2FkT25SZXN1bWU7dGhpcy5fcGF1c2VkPSExLHRoaXMuX3Nob3VsZFJlbG9hZE9uUmVzdW1lPSExLHQmJnRoaXMucmVsb2FkKCksdGhpcy50cmFuc2Zvcm0mJnRoaXMudXBkYXRlKHRoaXMudHJhbnNmb3JtKTt9fSxpLnByb3RvdHlwZS5fbG9hZFRpbGU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5fc291cmNlLmxvYWRUaWxlKHQsZSl9LGkucHJvdG90eXBlLl91bmxvYWRUaWxlPWZ1bmN0aW9uKHQpe2lmKHRoaXMuX3NvdXJjZS51bmxvYWRUaWxlKXJldHVybiB0aGlzLl9zb3VyY2UudW5sb2FkVGlsZSh0LGZ1bmN0aW9uKCl7fSl9LGkucHJvdG90eXBlLl9hYm9ydFRpbGU9ZnVuY3Rpb24odCl7aWYodGhpcy5fc291cmNlLmFib3J0VGlsZSlyZXR1cm4gdGhpcy5fc291cmNlLmFib3J0VGlsZSh0LGZ1bmN0aW9uKCl7fSl9LGkucHJvdG90eXBlLnNlcmlhbGl6ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zb3VyY2Uuc2VyaWFsaXplKCl9LGkucHJvdG90eXBlLnByZXBhcmU9ZnVuY3Rpb24odCl7Zm9yKHZhciBlIGluIHRoaXMuX3NvdXJjZS5wcmVwYXJlJiZ0aGlzLl9zb3VyY2UucHJlcGFyZSgpLHRoaXMuX3N0YXRlLmNvYWxlc2NlQ2hhbmdlcyh0aGlzLl90aWxlcyx0aGlzLm1hcD90aGlzLm1hcC5wYWludGVyOm51bGwpLHRoaXMuX3RpbGVzKXt2YXIgaT10aGlzLl90aWxlc1tlXTtpLnVwbG9hZCh0KSxpLnByZXBhcmUodGhpcy5tYXAuc3R5bGUuaW1hZ2VNYW5hZ2VyKTt9fSxpLnByb3RvdHlwZS5nZXRJZHM9ZnVuY3Rpb24oKXtyZXR1cm4gT2JqZWN0LmtleXModGhpcy5fdGlsZXMpLm1hcChOdW1iZXIpLnNvcnQoTHQpfSxpLnByb3RvdHlwZS5nZXRSZW5kZXJhYmxlSWRzPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXMsbz1bXTtmb3IodmFyIHIgaW4gdGhpcy5fdGlsZXMpdGhpcy5faXNJZFJlbmRlcmFibGUoK3IsZSkmJm8ucHVzaCgrcik7cmV0dXJuIGU/by5zb3J0KGZ1bmN0aW9uKGUsbyl7dmFyIHI9aS5fdGlsZXNbZV0udGlsZUlELGE9aS5fdGlsZXNbb10udGlsZUlELG49bmV3IHQuUG9pbnQoci5jYW5vbmljYWwueCxyLmNhbm9uaWNhbC55KS5fcm90YXRlKGkudHJhbnNmb3JtLmFuZ2xlKSxzPW5ldyB0LlBvaW50KGEuY2Fub25pY2FsLngsYS5jYW5vbmljYWwueSkuX3JvdGF0ZShpLnRyYW5zZm9ybS5hbmdsZSk7cmV0dXJuIHIub3ZlcnNjYWxlZFotYS5vdmVyc2NhbGVkWnx8cy55LW4ueXx8cy54LW4ueH0pOm8uc29ydChMdCl9LGkucHJvdG90eXBlLmhhc1JlbmRlcmFibGVQYXJlbnQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5maW5kTG9hZGVkUGFyZW50KHQsMCk7cmV0dXJuICEhZSYmdGhpcy5faXNJZFJlbmRlcmFibGUoZS50aWxlSUQua2V5KX0saS5wcm90b3R5cGUuX2lzSWRSZW5kZXJhYmxlPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuX3RpbGVzW3RdJiZ0aGlzLl90aWxlc1t0XS5oYXNEYXRhKCkmJiF0aGlzLl9jb3ZlcmVkVGlsZXNbdF0mJihlfHwhdGhpcy5fdGlsZXNbdF0uaG9sZGluZ0ZvckZhZGUoKSl9LGkucHJvdG90eXBlLnJlbG9hZD1mdW5jdGlvbigpe2lmKHRoaXMuX3BhdXNlZCl0aGlzLl9zaG91bGRSZWxvYWRPblJlc3VtZT0hMDtlbHNlIGZvcih2YXIgdCBpbiB0aGlzLl9jYWNoZS5yZXNldCgpLHRoaXMuX3RpbGVzKVwiZXJyb3JlZFwiIT09dGhpcy5fdGlsZXNbdF0uc3RhdGUmJnRoaXMuX3JlbG9hZFRpbGUodCxcInJlbG9hZGluZ1wiKTt9LGkucHJvdG90eXBlLl9yZWxvYWRUaWxlPWZ1bmN0aW9uKHQsZSl7dmFyIGk9dGhpcy5fdGlsZXNbdF07aSYmKFwibG9hZGluZ1wiIT09aS5zdGF0ZSYmKGkuc3RhdGU9ZSksdGhpcy5fbG9hZFRpbGUoaSx0aGlzLl90aWxlTG9hZGVkLmJpbmQodGhpcyxpLHQsZSkpKTt9LGkucHJvdG90eXBlLl90aWxlTG9hZGVkPWZ1bmN0aW9uKGUsaSxvLHIpe2lmKHIpcmV0dXJuIGUuc3RhdGU9XCJlcnJvcmVkXCIsdm9pZCg0MDQhPT1yLnN0YXR1cz90aGlzLl9zb3VyY2UuZmlyZShuZXcgdC5FcnJvckV2ZW50KHIse3RpbGU6ZX0pKTp0aGlzLnVwZGF0ZSh0aGlzLnRyYW5zZm9ybSkpO2UudGltZUFkZGVkPXQuYnJvd3Nlci5ub3coKSxcImV4cGlyZWRcIj09PW8mJihlLnJlZnJlc2hlZFVwb25FeHBpcmF0aW9uPSEwKSx0aGlzLl9zZXRUaWxlUmVsb2FkVGltZXIoaSxlKSxcInJhc3Rlci1kZW1cIj09PXRoaXMuZ2V0U291cmNlKCkudHlwZSYmZS5kZW0mJnRoaXMuX2JhY2tmaWxsREVNKGUpLHRoaXMuX3N0YXRlLmluaXRpYWxpemVUaWxlU3RhdGUoZSx0aGlzLm1hcD90aGlzLm1hcC5wYWludGVyOm51bGwpLHRoaXMuX3NvdXJjZS5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInNvdXJjZVwiLHRpbGU6ZSxjb29yZDplLnRpbGVJRH0pKTt9LGkucHJvdG90eXBlLl9iYWNrZmlsbERFTT1mdW5jdGlvbih0KXtmb3IodmFyIGU9dGhpcy5nZXRSZW5kZXJhYmxlSWRzKCksaT0wO2k8ZS5sZW5ndGg7aSsrKXt2YXIgbz1lW2ldO2lmKHQubmVpZ2hib3JpbmdUaWxlcyYmdC5uZWlnaGJvcmluZ1RpbGVzW29dKXt2YXIgcj10aGlzLmdldFRpbGVCeUlEKG8pO2EodCxyKSxhKHIsdCk7fX1mdW5jdGlvbiBhKHQsZSl7dC5uZWVkc0hpbGxzaGFkZVByZXBhcmU9ITA7dmFyIGk9ZS50aWxlSUQuY2Fub25pY2FsLngtdC50aWxlSUQuY2Fub25pY2FsLngsbz1lLnRpbGVJRC5jYW5vbmljYWwueS10LnRpbGVJRC5jYW5vbmljYWwueSxyPU1hdGgucG93KDIsdC50aWxlSUQuY2Fub25pY2FsLnopLGE9ZS50aWxlSUQua2V5OzA9PT1pJiYwPT09b3x8TWF0aC5hYnMobyk+MXx8KE1hdGguYWJzKGkpPjEmJigxPT09TWF0aC5hYnMoaStyKT9pKz1yOjE9PT1NYXRoLmFicyhpLXIpJiYoaS09cikpLGUuZGVtJiZ0LmRlbSYmKHQuZGVtLmJhY2tmaWxsQm9yZGVyKGUuZGVtLGksbyksdC5uZWlnaGJvcmluZ1RpbGVzJiZ0Lm5laWdoYm9yaW5nVGlsZXNbYV0mJih0Lm5laWdoYm9yaW5nVGlsZXNbYV0uYmFja2ZpbGxlZD0hMCkpKTt9fSxpLnByb3RvdHlwZS5nZXRUaWxlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmdldFRpbGVCeUlEKHQua2V5KX0saS5wcm90b3R5cGUuZ2V0VGlsZUJ5SUQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX3RpbGVzW3RdfSxpLnByb3RvdHlwZS5nZXRab29tPWZ1bmN0aW9uKHQpe3JldHVybiB0Lnpvb20rdC5zY2FsZVpvb20odC50aWxlU2l6ZS90aGlzLl9zb3VyY2UudGlsZVNpemUpfSxpLnByb3RvdHlwZS5fcmV0YWluTG9hZGVkQ2hpbGRyZW49ZnVuY3Rpb24odCxlLGksbyl7Zm9yKHZhciByIGluIHRoaXMuX3RpbGVzKXt2YXIgYT10aGlzLl90aWxlc1tyXTtpZighKG9bcl18fCFhLmhhc0RhdGEoKXx8YS50aWxlSUQub3ZlcnNjYWxlZFo8PWV8fGEudGlsZUlELm92ZXJzY2FsZWRaPmkpKXtmb3IodmFyIG49YS50aWxlSUQ7YSYmYS50aWxlSUQub3ZlcnNjYWxlZFo+ZSsxOyl7dmFyIHM9YS50aWxlSUQuc2NhbGVkVG8oYS50aWxlSUQub3ZlcnNjYWxlZFotMSk7KGE9dGhpcy5fdGlsZXNbcy5rZXldKSYmYS5oYXNEYXRhKCkmJihuPXMpO31mb3IodmFyIGw9bjtsLm92ZXJzY2FsZWRaPmU7KWlmKHRbKGw9bC5zY2FsZWRUbyhsLm92ZXJzY2FsZWRaLTEpKS5rZXldKXtvW24ua2V5XT1uO2JyZWFrfX19fSxpLnByb3RvdHlwZS5maW5kTG9hZGVkUGFyZW50PWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciBpPXQub3ZlcnNjYWxlZFotMTtpPj1lO2ktLSl7dmFyIG89dC5zY2FsZWRUbyhpKTtpZighbylyZXR1cm47dmFyIHI9U3RyaW5nKG8ua2V5KSxhPXRoaXMuX3RpbGVzW3JdO2lmKGEmJmEuaGFzRGF0YSgpKXJldHVybiBhO2lmKHRoaXMuX2NhY2hlLmhhcyhvKSlyZXR1cm4gdGhpcy5fY2FjaGUuZ2V0KG8pfX0saS5wcm90b3R5cGUudXBkYXRlQ2FjaGVTaXplPWZ1bmN0aW9uKHQpe3ZhciBlPShNYXRoLmNlaWwodC53aWR0aC90aGlzLl9zb3VyY2UudGlsZVNpemUpKzEpKihNYXRoLmNlaWwodC5oZWlnaHQvdGhpcy5fc291cmNlLnRpbGVTaXplKSsxKSxpPU1hdGguZmxvb3IoNSplKSxvPVwibnVtYmVyXCI9PXR5cGVvZiB0aGlzLl9tYXhUaWxlQ2FjaGVTaXplP01hdGgubWluKHRoaXMuX21heFRpbGVDYWNoZVNpemUsaSk6aTt0aGlzLl9jYWNoZS5zZXRNYXhTaXplKG8pO30saS5wcm90b3R5cGUuaGFuZGxlV3JhcEp1bXA9ZnVuY3Rpb24odCl7dmFyIGU9KHQtKHZvaWQgMD09PXRoaXMuX3ByZXZMbmc/dDp0aGlzLl9wcmV2TG5nKSkvMzYwLGk9TWF0aC5yb3VuZChlKTtpZih0aGlzLl9wcmV2TG5nPXQsaSl7dmFyIG89e307Zm9yKHZhciByIGluIHRoaXMuX3RpbGVzKXt2YXIgYT10aGlzLl90aWxlc1tyXTthLnRpbGVJRD1hLnRpbGVJRC51bndyYXBUbyhhLnRpbGVJRC53cmFwK2kpLG9bYS50aWxlSUQua2V5XT1hO31mb3IodmFyIG4gaW4gdGhpcy5fdGlsZXM9byx0aGlzLl90aW1lcnMpY2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVyc1tuXSksZGVsZXRlIHRoaXMuX3RpbWVyc1tuXTtmb3IodmFyIHMgaW4gdGhpcy5fdGlsZXMpe3ZhciBsPXRoaXMuX3RpbGVzW3NdO3RoaXMuX3NldFRpbGVSZWxvYWRUaW1lcihzLGwpO319fSxpLnByb3RvdHlwZS51cGRhdGU9ZnVuY3Rpb24oZSl7dmFyIG89dGhpcztpZih0aGlzLnRyYW5zZm9ybT1lLHRoaXMuX3NvdXJjZUxvYWRlZCYmIXRoaXMuX3BhdXNlZCl7dmFyIHI7dGhpcy51cGRhdGVDYWNoZVNpemUoZSksdGhpcy5oYW5kbGVXcmFwSnVtcCh0aGlzLnRyYW5zZm9ybS5jZW50ZXIubG5nKSx0aGlzLl9jb3ZlcmVkVGlsZXM9e30sdGhpcy51c2VkP3RoaXMuX3NvdXJjZS50aWxlSUQ/cj1lLmdldFZpc2libGVVbndyYXBwZWRDb29yZGluYXRlcyh0aGlzLl9zb3VyY2UudGlsZUlEKS5tYXAoZnVuY3Rpb24oZSl7cmV0dXJuIG5ldyB0Lk92ZXJzY2FsZWRUaWxlSUQoZS5jYW5vbmljYWwueixlLndyYXAsZS5jYW5vbmljYWwueixlLmNhbm9uaWNhbC54LGUuY2Fub25pY2FsLnkpfSk6KHI9ZS5jb3ZlcmluZ1RpbGVzKHt0aWxlU2l6ZTp0aGlzLl9zb3VyY2UudGlsZVNpemUsbWluem9vbTp0aGlzLl9zb3VyY2UubWluem9vbSxtYXh6b29tOnRoaXMuX3NvdXJjZS5tYXh6b29tLHJvdW5kWm9vbTp0aGlzLl9zb3VyY2Uucm91bmRab29tLHJlcGFyc2VPdmVyc2NhbGVkOnRoaXMuX3NvdXJjZS5yZXBhcnNlT3ZlcnNjYWxlZH0pLHRoaXMuX3NvdXJjZS5oYXNUaWxlJiYocj1yLmZpbHRlcihmdW5jdGlvbih0KXtyZXR1cm4gby5fc291cmNlLmhhc1RpbGUodCl9KSkpOnI9W107dmFyIGE9KHRoaXMuX3NvdXJjZS5yb3VuZFpvb20/TWF0aC5yb3VuZDpNYXRoLmZsb29yKSh0aGlzLmdldFpvb20oZSkpLG49TWF0aC5tYXgoYS1pLm1heE92ZXJ6b29taW5nLHRoaXMuX3NvdXJjZS5taW56b29tKSxzPU1hdGgubWF4KGEraS5tYXhVbmRlcnpvb21pbmcsdGhpcy5fc291cmNlLm1pbnpvb20pLGw9dGhpcy5fdXBkYXRlUmV0YWluZWRUaWxlcyhyLGEpO2lmKER0KHRoaXMuX3NvdXJjZS50eXBlKSl7Zm9yKHZhciBjPXt9LHU9e30saD0wLHA9T2JqZWN0LmtleXMobCk7aDxwLmxlbmd0aDtoKz0xKXt2YXIgZD1wW2hdLF89bFtkXSxmPXRoaXMuX3RpbGVzW2RdO2lmKGYmJiEoZi5mYWRlRW5kVGltZSYmZi5mYWRlRW5kVGltZTw9dC5icm93c2VyLm5vdygpKSl7dmFyIG09dGhpcy5maW5kTG9hZGVkUGFyZW50KF8sbik7bSYmKHRoaXMuX2FkZFRpbGUobS50aWxlSUQpLGNbbS50aWxlSUQua2V5XT1tLnRpbGVJRCksdVtkXT1fO319Zm9yKHZhciBnIGluIHRoaXMuX3JldGFpbkxvYWRlZENoaWxkcmVuKHUsYSxzLGwpLGMpbFtnXXx8KHRoaXMuX2NvdmVyZWRUaWxlc1tnXT0hMCxsW2ddPWNbZ10pO31mb3IodmFyIHYgaW4gbCl0aGlzLl90aWxlc1t2XS5jbGVhckZhZGVIb2xkKCk7Zm9yKHZhciB5PTAseD10LmtleXNEaWZmZXJlbmNlKHRoaXMuX3RpbGVzLGwpO3k8eC5sZW5ndGg7eSs9MSl7dmFyIGI9eFt5XSx3PXRoaXMuX3RpbGVzW2JdO3cuaGFzU3ltYm9sQnVja2V0cyYmIXcuaG9sZGluZ0ZvckZhZGUoKT93LnNldEhvbGREdXJhdGlvbih0aGlzLm1hcC5fZmFkZUR1cmF0aW9uKTp3Lmhhc1N5bWJvbEJ1Y2tldHMmJiF3LnN5bWJvbEZhZGVGaW5pc2hlZCgpfHx0aGlzLl9yZW1vdmVUaWxlKGIpO319fSxpLnByb3RvdHlwZS5yZWxlYXNlU3ltYm9sRmFkZVRpbGVzPWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMuX3RpbGVzKXRoaXMuX3RpbGVzW3RdLmhvbGRpbmdGb3JGYWRlKCkmJnRoaXMuX3JlbW92ZVRpbGUodCk7fSxpLnByb3RvdHlwZS5fdXBkYXRlUmV0YWluZWRUaWxlcz1mdW5jdGlvbih0LGUpe2Zvcih2YXIgbz17fSxyPXt9LGE9TWF0aC5tYXgoZS1pLm1heE92ZXJ6b29taW5nLHRoaXMuX3NvdXJjZS5taW56b29tKSxuPU1hdGgubWF4KGUraS5tYXhVbmRlcnpvb21pbmcsdGhpcy5fc291cmNlLm1pbnpvb20pLHM9e30sbD0wLGM9dDtsPGMubGVuZ3RoO2wrPTEpe3ZhciB1PWNbbF0saD10aGlzLl9hZGRUaWxlKHUpO29bdS5rZXldPXUsaC5oYXNEYXRhKCl8fGU8dGhpcy5fc291cmNlLm1heHpvb20mJihzW3Uua2V5XT11KTt9dGhpcy5fcmV0YWluTG9hZGVkQ2hpbGRyZW4ocyxlLG4sbyk7Zm9yKHZhciBwPTAsZD10O3A8ZC5sZW5ndGg7cCs9MSl7dmFyIF89ZFtwXSxmPXRoaXMuX3RpbGVzW18ua2V5XTtpZighZi5oYXNEYXRhKCkpe2lmKGUrMT50aGlzLl9zb3VyY2UubWF4em9vbSl7dmFyIG09Xy5jaGlsZHJlbih0aGlzLl9zb3VyY2UubWF4em9vbSlbMF0sZz10aGlzLmdldFRpbGUobSk7aWYoZyYmZy5oYXNEYXRhKCkpe29bbS5rZXldPW07Y29udGludWV9fWVsc2V7dmFyIHY9Xy5jaGlsZHJlbih0aGlzLl9zb3VyY2UubWF4em9vbSk7aWYob1t2WzBdLmtleV0mJm9bdlsxXS5rZXldJiZvW3ZbMl0ua2V5XSYmb1t2WzNdLmtleV0pY29udGludWV9Zm9yKHZhciB5PWYud2FzUmVxdWVzdGVkKCkseD1fLm92ZXJzY2FsZWRaLTE7eD49YTstLXgpe3ZhciBiPV8uc2NhbGVkVG8oeCk7aWYocltiLmtleV0pYnJlYWs7aWYocltiLmtleV09ITAsIShmPXRoaXMuZ2V0VGlsZShiKSkmJnkmJihmPXRoaXMuX2FkZFRpbGUoYikpLGYmJihvW2Iua2V5XT1iLHk9Zi53YXNSZXF1ZXN0ZWQoKSxmLmhhc0RhdGEoKSkpYnJlYWt9fX1yZXR1cm4gb30saS5wcm90b3R5cGUuX2FkZFRpbGU9ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcy5fdGlsZXNbZS5rZXldO2lmKGkpcmV0dXJuIGk7KGk9dGhpcy5fY2FjaGUuZ2V0QW5kUmVtb3ZlKGUpKSYmKHRoaXMuX3NldFRpbGVSZWxvYWRUaW1lcihlLmtleSxpKSxpLnRpbGVJRD1lLHRoaXMuX3N0YXRlLmluaXRpYWxpemVUaWxlU3RhdGUoaSx0aGlzLm1hcD90aGlzLm1hcC5wYWludGVyOm51bGwpLHRoaXMuX2NhY2hlVGltZXJzW2Uua2V5XSYmKGNsZWFyVGltZW91dCh0aGlzLl9jYWNoZVRpbWVyc1tlLmtleV0pLGRlbGV0ZSB0aGlzLl9jYWNoZVRpbWVyc1tlLmtleV0sdGhpcy5fc2V0VGlsZVJlbG9hZFRpbWVyKGUua2V5LGkpKSk7dmFyIG89Qm9vbGVhbihpKTtyZXR1cm4gb3x8KGk9bmV3IHQuVGlsZShlLHRoaXMuX3NvdXJjZS50aWxlU2l6ZSplLm92ZXJzY2FsZUZhY3RvcigpKSx0aGlzLl9sb2FkVGlsZShpLHRoaXMuX3RpbGVMb2FkZWQuYmluZCh0aGlzLGksZS5rZXksaS5zdGF0ZSkpKSxpPyhpLnVzZXMrKyx0aGlzLl90aWxlc1tlLmtleV09aSxvfHx0aGlzLl9zb3VyY2UuZmlyZShuZXcgdC5FdmVudChcImRhdGFsb2FkaW5nXCIse3RpbGU6aSxjb29yZDppLnRpbGVJRCxkYXRhVHlwZTpcInNvdXJjZVwifSkpLGkpOm51bGx9LGkucHJvdG90eXBlLl9zZXRUaWxlUmVsb2FkVGltZXI9ZnVuY3Rpb24odCxlKXt2YXIgaT10aGlzO3QgaW4gdGhpcy5fdGltZXJzJiYoY2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVyc1t0XSksZGVsZXRlIHRoaXMuX3RpbWVyc1t0XSk7dmFyIG89ZS5nZXRFeHBpcnlUaW1lb3V0KCk7byYmKHRoaXMuX3RpbWVyc1t0XT1zZXRUaW1lb3V0KGZ1bmN0aW9uKCl7aS5fcmVsb2FkVGlsZSh0LFwiZXhwaXJlZFwiKSxkZWxldGUgaS5fdGltZXJzW3RdO30sbykpO30saS5wcm90b3R5cGUuX3JlbW92ZVRpbGU9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5fdGlsZXNbdF07ZSYmKGUudXNlcy0tLGRlbGV0ZSB0aGlzLl90aWxlc1t0XSx0aGlzLl90aW1lcnNbdF0mJihjbGVhclRpbWVvdXQodGhpcy5fdGltZXJzW3RdKSxkZWxldGUgdGhpcy5fdGltZXJzW3RdKSxlLnVzZXM+MHx8KGUuaGFzRGF0YSgpP3RoaXMuX2NhY2hlLmFkZChlLnRpbGVJRCxlLGUuZ2V0RXhwaXJ5VGltZW91dCgpKTooZS5hYm9ydGVkPSEwLHRoaXMuX2Fib3J0VGlsZShlKSx0aGlzLl91bmxvYWRUaWxlKGUpKSkpO30saS5wcm90b3R5cGUuY2xlYXJUaWxlcz1mdW5jdGlvbigpe2Zvcih2YXIgdCBpbiB0aGlzLl9zaG91bGRSZWxvYWRPblJlc3VtZT0hMSx0aGlzLl9wYXVzZWQ9ITEsdGhpcy5fdGlsZXMpdGhpcy5fcmVtb3ZlVGlsZSh0KTt0aGlzLl9jYWNoZS5yZXNldCgpO30saS5wcm90b3R5cGUudGlsZXNJbj1mdW5jdGlvbihlLGksbyl7dmFyIHI9dGhpcyxhPVtdLG49dGhpcy50cmFuc2Zvcm07aWYoIW4pcmV0dXJuIGE7Zm9yKHZhciBzPW8/bi5nZXRDYW1lcmFRdWVyeUdlb21ldHJ5KGUpOmUsbD1lLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gbi5wb2ludENvb3JkaW5hdGUodCl9KSxjPXMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBuLnBvaW50Q29vcmRpbmF0ZSh0KX0pLHU9dGhpcy5nZXRJZHMoKSxoPTEvMCxwPTEvMCxkPS0xLzAsXz0tMS8wLGY9MCxtPWM7ZjxtLmxlbmd0aDtmKz0xKXt2YXIgZz1tW2ZdO2g9TWF0aC5taW4oaCxnLngpLHA9TWF0aC5taW4ocCxnLnkpLGQ9TWF0aC5tYXgoZCxnLngpLF89TWF0aC5tYXgoXyxnLnkpO31mb3IodmFyIHY9ZnVuY3Rpb24oZSl7dmFyIG89ci5fdGlsZXNbdVtlXV07aWYoIW8uaG9sZGluZ0ZvckZhZGUoKSl7dmFyIHM9by50aWxlSUQsZj1NYXRoLnBvdygyLG4uem9vbS1vLnRpbGVJRC5vdmVyc2NhbGVkWiksbT1pKm8ucXVlcnlQYWRkaW5nKnQuRVhURU5UL28udGlsZVNpemUvZixnPVtzLmdldFRpbGVQb2ludChuZXcgdC5NZXJjYXRvckNvb3JkaW5hdGUoaCxwKSkscy5nZXRUaWxlUG9pbnQobmV3IHQuTWVyY2F0b3JDb29yZGluYXRlKGQsXykpXTtpZihnWzBdLngtbTx0LkVYVEVOVCYmZ1swXS55LW08dC5FWFRFTlQmJmdbMV0ueCttPj0wJiZnWzFdLnkrbT49MCl7dmFyIHY9bC5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHMuZ2V0VGlsZVBvaW50KHQpfSkseT1jLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gcy5nZXRUaWxlUG9pbnQodCl9KTthLnB1c2goe3RpbGU6byx0aWxlSUQ6cyxxdWVyeUdlb21ldHJ5OnYsY2FtZXJhUXVlcnlHZW9tZXRyeTp5LHNjYWxlOmZ9KTt9fX0seT0wO3k8dS5sZW5ndGg7eSsrKXYoeSk7cmV0dXJuIGF9LGkucHJvdG90eXBlLmdldFZpc2libGVDb29yZGluYXRlcz1mdW5jdGlvbih0KXtmb3IodmFyIGU9dGhpcyxpPXRoaXMuZ2V0UmVuZGVyYWJsZUlkcyh0KS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIGUuX3RpbGVzW3RdLnRpbGVJRH0pLG89MCxyPWk7bzxyLmxlbmd0aDtvKz0xKXt2YXIgYT1yW29dO2EucG9zTWF0cml4PXRoaXMudHJhbnNmb3JtLmNhbGN1bGF0ZVBvc01hdHJpeChhLnRvVW53cmFwcGVkKCkpO31yZXR1cm4gaX0saS5wcm90b3R5cGUuaGFzVHJhbnNpdGlvbj1mdW5jdGlvbigpe2lmKHRoaXMuX3NvdXJjZS5oYXNUcmFuc2l0aW9uKCkpcmV0dXJuICEwO2lmKER0KHRoaXMuX3NvdXJjZS50eXBlKSlmb3IodmFyIGUgaW4gdGhpcy5fdGlsZXMpe3ZhciBpPXRoaXMuX3RpbGVzW2VdO2lmKHZvaWQgMCE9PWkuZmFkZUVuZFRpbWUmJmkuZmFkZUVuZFRpbWU+PXQuYnJvd3Nlci5ub3coKSlyZXR1cm4gITB9cmV0dXJuICExfSxpLnByb3RvdHlwZS5zZXRGZWF0dXJlU3RhdGU9ZnVuY3Rpb24odCxlLGkpe3Q9dHx8XCJfZ2VvanNvblRpbGVMYXllclwiLHRoaXMuX3N0YXRlLnVwZGF0ZVN0YXRlKHQsZSxpKTt9LGkucHJvdG90eXBlLnJlbW92ZUZlYXR1cmVTdGF0ZT1mdW5jdGlvbih0LGUsaSl7dD10fHxcIl9nZW9qc29uVGlsZUxheWVyXCIsdGhpcy5fc3RhdGUucmVtb3ZlRmVhdHVyZVN0YXRlKHQsZSxpKTt9LGkucHJvdG90eXBlLmdldEZlYXR1cmVTdGF0ZT1mdW5jdGlvbih0LGUpe3JldHVybiB0PXR8fFwiX2dlb2pzb25UaWxlTGF5ZXJcIix0aGlzLl9zdGF0ZS5nZXRTdGF0ZSh0LGUpfSxpfSh0LkV2ZW50ZWQpO2Z1bmN0aW9uIEx0KHQsZSl7cmV0dXJuIHQlMzItZSUzMnx8ZS10fWZ1bmN0aW9uIER0KHQpe3JldHVybiBcInJhc3RlclwiPT09dHx8XCJpbWFnZVwiPT09dHx8XCJ2aWRlb1wiPT09dH1mdW5jdGlvbiBNdCgpe3JldHVybiBuZXcgdC53aW5kb3cuV29ya2VyKCRvLndvcmtlclVybCl9enQubWF4T3Zlcnpvb21pbmc9MTAsenQubWF4VW5kZXJ6b29taW5nPTM7dmFyIFJ0PWZ1bmN0aW9uKCl7dGhpcy5hY3RpdmU9e307fTtSdC5wcm90b3R5cGUuYWNxdWlyZT1mdW5jdGlvbih0KXtpZighdGhpcy53b3JrZXJzKWZvcih0aGlzLndvcmtlcnM9W107dGhpcy53b3JrZXJzLmxlbmd0aDxSdC53b3JrZXJDb3VudDspdGhpcy53b3JrZXJzLnB1c2gobmV3IE10KTtyZXR1cm4gdGhpcy5hY3RpdmVbdF09ITAsdGhpcy53b3JrZXJzLnNsaWNlKCl9LFJ0LnByb3RvdHlwZS5yZWxlYXNlPWZ1bmN0aW9uKHQpe2RlbGV0ZSB0aGlzLmFjdGl2ZVt0XSwwPT09T2JqZWN0LmtleXModGhpcy5hY3RpdmUpLmxlbmd0aCYmKHRoaXMud29ya2Vycy5mb3JFYWNoKGZ1bmN0aW9uKHQpe3QudGVybWluYXRlKCk7fSksdGhpcy53b3JrZXJzPW51bGwpO307dmFyIEF0LGt0PU1hdGguZmxvb3IodC5icm93c2VyLmhhcmR3YXJlQ29uY3VycmVuY3kvMik7ZnVuY3Rpb24gQnQoZSxpKXt2YXIgbz17fTtmb3IodmFyIHIgaW4gZSlcInJlZlwiIT09ciYmKG9bcl09ZVtyXSk7cmV0dXJuIHQucmVmUHJvcGVydGllcy5mb3JFYWNoKGZ1bmN0aW9uKHQpe3QgaW4gaSYmKG9bdF09aVt0XSk7fSksb31mdW5jdGlvbiBPdCh0KXt0PXQuc2xpY2UoKTtmb3IodmFyIGU9T2JqZWN0LmNyZWF0ZShudWxsKSxpPTA7aTx0Lmxlbmd0aDtpKyspZVt0W2ldLmlkXT10W2ldO2Zvcih2YXIgbz0wO288dC5sZW5ndGg7bysrKVwicmVmXCJpbiB0W29dJiYodFtvXT1CdCh0W29dLGVbdFtvXS5yZWZdKSk7cmV0dXJuIHR9UnQud29ya2VyQ291bnQ9TWF0aC5tYXgoTWF0aC5taW4oa3QsNiksMSk7dmFyIEZ0PXtzZXRTdHlsZTpcInNldFN0eWxlXCIsYWRkTGF5ZXI6XCJhZGRMYXllclwiLHJlbW92ZUxheWVyOlwicmVtb3ZlTGF5ZXJcIixzZXRQYWludFByb3BlcnR5Olwic2V0UGFpbnRQcm9wZXJ0eVwiLHNldExheW91dFByb3BlcnR5Olwic2V0TGF5b3V0UHJvcGVydHlcIixzZXRGaWx0ZXI6XCJzZXRGaWx0ZXJcIixhZGRTb3VyY2U6XCJhZGRTb3VyY2VcIixyZW1vdmVTb3VyY2U6XCJyZW1vdmVTb3VyY2VcIixzZXRHZW9KU09OU291cmNlRGF0YTpcInNldEdlb0pTT05Tb3VyY2VEYXRhXCIsc2V0TGF5ZXJab29tUmFuZ2U6XCJzZXRMYXllclpvb21SYW5nZVwiLHNldExheWVyUHJvcGVydHk6XCJzZXRMYXllclByb3BlcnR5XCIsc2V0Q2VudGVyOlwic2V0Q2VudGVyXCIsc2V0Wm9vbTpcInNldFpvb21cIixzZXRCZWFyaW5nOlwic2V0QmVhcmluZ1wiLHNldFBpdGNoOlwic2V0UGl0Y2hcIixzZXRTcHJpdGU6XCJzZXRTcHJpdGVcIixzZXRHbHlwaHM6XCJzZXRHbHlwaHNcIixzZXRUcmFuc2l0aW9uOlwic2V0VHJhbnNpdGlvblwiLHNldExpZ2h0Olwic2V0TGlnaHRcIn07ZnVuY3Rpb24gVXQodCxlLGkpe2kucHVzaCh7Y29tbWFuZDpGdC5hZGRTb3VyY2UsYXJnczpbdCxlW3RdXX0pO31mdW5jdGlvbiBOdCh0LGUsaSl7ZS5wdXNoKHtjb21tYW5kOkZ0LnJlbW92ZVNvdXJjZSxhcmdzOlt0XX0pLGlbdF09ITA7fWZ1bmN0aW9uIFp0KHQsZSxpLG8pe050KHQsaSxvKSxVdCh0LGUsaSk7fWZ1bmN0aW9uIGp0KGUsaSxvKXt2YXIgcjtmb3IociBpbiBlW29dKWlmKGVbb10uaGFzT3duUHJvcGVydHkocikmJlwiZGF0YVwiIT09ciYmIXQuZGVlcEVxdWFsKGVbb11bcl0saVtvXVtyXSkpcmV0dXJuICExO2ZvcihyIGluIGlbb10paWYoaVtvXS5oYXNPd25Qcm9wZXJ0eShyKSYmXCJkYXRhXCIhPT1yJiYhdC5kZWVwRXF1YWwoZVtvXVtyXSxpW29dW3JdKSlyZXR1cm4gITE7cmV0dXJuICEwfWZ1bmN0aW9uIHF0KGUsaSxvLHIsYSxuKXt2YXIgcztmb3IocyBpbiBpPWl8fHt9LGU9ZXx8e30pZS5oYXNPd25Qcm9wZXJ0eShzKSYmKHQuZGVlcEVxdWFsKGVbc10saVtzXSl8fG8ucHVzaCh7Y29tbWFuZDpuLGFyZ3M6W3IscyxpW3NdLGFdfSkpO2ZvcihzIGluIGkpaS5oYXNPd25Qcm9wZXJ0eShzKSYmIWUuaGFzT3duUHJvcGVydHkocykmJih0LmRlZXBFcXVhbChlW3NdLGlbc10pfHxvLnB1c2goe2NvbW1hbmQ6bixhcmdzOltyLHMsaVtzXSxhXX0pKTt9ZnVuY3Rpb24gVnQodCl7cmV0dXJuIHQuaWR9ZnVuY3Rpb24gR3QodCxlKXtyZXR1cm4gdFtlLmlkXT1lLHR9ZnVuY3Rpb24gV3QoZSxpKXtpZighZSlyZXR1cm4gW3tjb21tYW5kOkZ0LnNldFN0eWxlLGFyZ3M6W2ldfV07dmFyIG89W107dHJ5e2lmKCF0LmRlZXBFcXVhbChlLnZlcnNpb24saS52ZXJzaW9uKSlyZXR1cm4gW3tjb21tYW5kOkZ0LnNldFN0eWxlLGFyZ3M6W2ldfV07dC5kZWVwRXF1YWwoZS5jZW50ZXIsaS5jZW50ZXIpfHxvLnB1c2goe2NvbW1hbmQ6RnQuc2V0Q2VudGVyLGFyZ3M6W2kuY2VudGVyXX0pLHQuZGVlcEVxdWFsKGUuem9vbSxpLnpvb20pfHxvLnB1c2goe2NvbW1hbmQ6RnQuc2V0Wm9vbSxhcmdzOltpLnpvb21dfSksdC5kZWVwRXF1YWwoZS5iZWFyaW5nLGkuYmVhcmluZyl8fG8ucHVzaCh7Y29tbWFuZDpGdC5zZXRCZWFyaW5nLGFyZ3M6W2kuYmVhcmluZ119KSx0LmRlZXBFcXVhbChlLnBpdGNoLGkucGl0Y2gpfHxvLnB1c2goe2NvbW1hbmQ6RnQuc2V0UGl0Y2gsYXJnczpbaS5waXRjaF19KSx0LmRlZXBFcXVhbChlLnNwcml0ZSxpLnNwcml0ZSl8fG8ucHVzaCh7Y29tbWFuZDpGdC5zZXRTcHJpdGUsYXJnczpbaS5zcHJpdGVdfSksdC5kZWVwRXF1YWwoZS5nbHlwaHMsaS5nbHlwaHMpfHxvLnB1c2goe2NvbW1hbmQ6RnQuc2V0R2x5cGhzLGFyZ3M6W2kuZ2x5cGhzXX0pLHQuZGVlcEVxdWFsKGUudHJhbnNpdGlvbixpLnRyYW5zaXRpb24pfHxvLnB1c2goe2NvbW1hbmQ6RnQuc2V0VHJhbnNpdGlvbixhcmdzOltpLnRyYW5zaXRpb25dfSksdC5kZWVwRXF1YWwoZS5saWdodCxpLmxpZ2h0KXx8by5wdXNoKHtjb21tYW5kOkZ0LnNldExpZ2h0LGFyZ3M6W2kubGlnaHRdfSk7dmFyIHI9e30sYT1bXTshZnVuY3Rpb24oZSxpLG8scil7dmFyIGE7Zm9yKGEgaW4gaT1pfHx7fSxlPWV8fHt9KWUuaGFzT3duUHJvcGVydHkoYSkmJihpLmhhc093blByb3BlcnR5KGEpfHxOdChhLG8scikpO2ZvcihhIGluIGkpaS5oYXNPd25Qcm9wZXJ0eShhKSYmKGUuaGFzT3duUHJvcGVydHkoYSk/dC5kZWVwRXF1YWwoZVthXSxpW2FdKXx8KFwiZ2VvanNvblwiPT09ZVthXS50eXBlJiZcImdlb2pzb25cIj09PWlbYV0udHlwZSYmanQoZSxpLGEpP28ucHVzaCh7Y29tbWFuZDpGdC5zZXRHZW9KU09OU291cmNlRGF0YSxhcmdzOlthLGlbYV0uZGF0YV19KTpadChhLGksbyxyKSk6VXQoYSxpLG8pKTt9KGUuc291cmNlcyxpLnNvdXJjZXMsYSxyKTt2YXIgbj1bXTtlLmxheWVycyYmZS5sYXllcnMuZm9yRWFjaChmdW5jdGlvbih0KXtyW3Quc291cmNlXT9vLnB1c2goe2NvbW1hbmQ6RnQucmVtb3ZlTGF5ZXIsYXJnczpbdC5pZF19KTpuLnB1c2godCk7fSksbz1vLmNvbmNhdChhKSxmdW5jdGlvbihlLGksbyl7aT1pfHxbXTt2YXIgcixhLG4scyxsLGMsdSxoPShlPWV8fFtdKS5tYXAoVnQpLHA9aS5tYXAoVnQpLGQ9ZS5yZWR1Y2UoR3Qse30pLF89aS5yZWR1Y2UoR3Qse30pLGY9aC5zbGljZSgpLG09T2JqZWN0LmNyZWF0ZShudWxsKTtmb3Iocj0wLGE9MDtyPGgubGVuZ3RoO3IrKyluPWhbcl0sXy5oYXNPd25Qcm9wZXJ0eShuKT9hKys6KG8ucHVzaCh7Y29tbWFuZDpGdC5yZW1vdmVMYXllcixhcmdzOltuXX0pLGYuc3BsaWNlKGYuaW5kZXhPZihuLGEpLDEpKTtmb3Iocj0wLGE9MDtyPHAubGVuZ3RoO3IrKyluPXBbcC5sZW5ndGgtMS1yXSxmW2YubGVuZ3RoLTEtcl0hPT1uJiYoZC5oYXNPd25Qcm9wZXJ0eShuKT8oby5wdXNoKHtjb21tYW5kOkZ0LnJlbW92ZUxheWVyLGFyZ3M6W25dfSksZi5zcGxpY2UoZi5sYXN0SW5kZXhPZihuLGYubGVuZ3RoLWEpLDEpKTphKyssYz1mW2YubGVuZ3RoLXJdLG8ucHVzaCh7Y29tbWFuZDpGdC5hZGRMYXllcixhcmdzOltfW25dLGNdfSksZi5zcGxpY2UoZi5sZW5ndGgtciwwLG4pLG1bbl09ITApO2ZvcihyPTA7cjxwLmxlbmd0aDtyKyspaWYocz1kW249cFtyXV0sbD1fW25dLCFtW25dJiYhdC5kZWVwRXF1YWwocyxsKSlpZih0LmRlZXBFcXVhbChzLnNvdXJjZSxsLnNvdXJjZSkmJnQuZGVlcEVxdWFsKHNbXCJzb3VyY2UtbGF5ZXJcIl0sbFtcInNvdXJjZS1sYXllclwiXSkmJnQuZGVlcEVxdWFsKHMudHlwZSxsLnR5cGUpKXtmb3IodSBpbiBxdChzLmxheW91dCxsLmxheW91dCxvLG4sbnVsbCxGdC5zZXRMYXlvdXRQcm9wZXJ0eSkscXQocy5wYWludCxsLnBhaW50LG8sbixudWxsLEZ0LnNldFBhaW50UHJvcGVydHkpLHQuZGVlcEVxdWFsKHMuZmlsdGVyLGwuZmlsdGVyKXx8by5wdXNoKHtjb21tYW5kOkZ0LnNldEZpbHRlcixhcmdzOltuLGwuZmlsdGVyXX0pLHQuZGVlcEVxdWFsKHMubWluem9vbSxsLm1pbnpvb20pJiZ0LmRlZXBFcXVhbChzLm1heHpvb20sbC5tYXh6b29tKXx8by5wdXNoKHtjb21tYW5kOkZ0LnNldExheWVyWm9vbVJhbmdlLGFyZ3M6W24sbC5taW56b29tLGwubWF4em9vbV19KSxzKXMuaGFzT3duUHJvcGVydHkodSkmJlwibGF5b3V0XCIhPT11JiZcInBhaW50XCIhPT11JiZcImZpbHRlclwiIT09dSYmXCJtZXRhZGF0YVwiIT09dSYmXCJtaW56b29tXCIhPT11JiZcIm1heHpvb21cIiE9PXUmJigwPT09dS5pbmRleE9mKFwicGFpbnQuXCIpP3F0KHNbdV0sbFt1XSxvLG4sdS5zbGljZSg2KSxGdC5zZXRQYWludFByb3BlcnR5KTp0LmRlZXBFcXVhbChzW3VdLGxbdV0pfHxvLnB1c2goe2NvbW1hbmQ6RnQuc2V0TGF5ZXJQcm9wZXJ0eSxhcmdzOltuLHUsbFt1XV19KSk7Zm9yKHUgaW4gbClsLmhhc093blByb3BlcnR5KHUpJiYhcy5oYXNPd25Qcm9wZXJ0eSh1KSYmXCJsYXlvdXRcIiE9PXUmJlwicGFpbnRcIiE9PXUmJlwiZmlsdGVyXCIhPT11JiZcIm1ldGFkYXRhXCIhPT11JiZcIm1pbnpvb21cIiE9PXUmJlwibWF4em9vbVwiIT09dSYmKDA9PT11LmluZGV4T2YoXCJwYWludC5cIik/cXQoc1t1XSxsW3VdLG8sbix1LnNsaWNlKDYpLEZ0LnNldFBhaW50UHJvcGVydHkpOnQuZGVlcEVxdWFsKHNbdV0sbFt1XSl8fG8ucHVzaCh7Y29tbWFuZDpGdC5zZXRMYXllclByb3BlcnR5LGFyZ3M6W24sdSxsW3VdXX0pKTt9ZWxzZSBvLnB1c2goe2NvbW1hbmQ6RnQucmVtb3ZlTGF5ZXIsYXJnczpbbl19KSxjPWZbZi5sYXN0SW5kZXhPZihuKSsxXSxvLnB1c2goe2NvbW1hbmQ6RnQuYWRkTGF5ZXIsYXJnczpbbCxjXX0pO30obixpLmxheWVycyxvKTt9Y2F0Y2godCl7Y29uc29sZS53YXJuKFwiVW5hYmxlIHRvIGNvbXB1dGUgc3R5bGUgZGlmZjpcIix0KSxvPVt7Y29tbWFuZDpGdC5zZXRTdHlsZSxhcmdzOltpXX1dO31yZXR1cm4gb312YXIgWHQ9ZnVuY3Rpb24odCxlLGkpe3ZhciBvPXRoaXMuYm94Q2VsbHM9W10scj10aGlzLmNpcmNsZUNlbGxzPVtdO3RoaXMueENlbGxDb3VudD1NYXRoLmNlaWwodC9pKSx0aGlzLnlDZWxsQ291bnQ9TWF0aC5jZWlsKGUvaSk7Zm9yKHZhciBhPTA7YTx0aGlzLnhDZWxsQ291bnQqdGhpcy55Q2VsbENvdW50O2ErKylvLnB1c2goW10pLHIucHVzaChbXSk7dGhpcy5jaXJjbGVLZXlzPVtdLHRoaXMuYm94S2V5cz1bXSx0aGlzLmJib3hlcz1bXSx0aGlzLmNpcmNsZXM9W10sdGhpcy53aWR0aD10LHRoaXMuaGVpZ2h0PWUsdGhpcy54U2NhbGU9dGhpcy54Q2VsbENvdW50L3QsdGhpcy55U2NhbGU9dGhpcy55Q2VsbENvdW50L2UsdGhpcy5ib3hVaWQ9MCx0aGlzLmNpcmNsZVVpZD0wO307ZnVuY3Rpb24gSHQoZSxpLG8scixhKXt2YXIgbj10LmNyZWF0ZSgpO3JldHVybiBpPyh0LnNjYWxlKG4sbixbMS9hLDEvYSwxXSksb3x8dC5yb3RhdGVaKG4sbixyLmFuZ2xlKSk6dC5tdWx0aXBseShuLHIubGFiZWxQbGFuZU1hdHJpeCxlKSxufWZ1bmN0aW9uIEt0KGUsaSxvLHIsYSl7aWYoaSl7dmFyIG49dC5jbG9uZShlKTtyZXR1cm4gdC5zY2FsZShuLG4sW2EsYSwxXSksb3x8dC5yb3RhdGVaKG4sbiwtci5hbmdsZSksbn1yZXR1cm4gci5nbENvb3JkTWF0cml4fWZ1bmN0aW9uIFl0KGUsaSl7dmFyIG89W2UueCxlLnksMCwxXTtuZShvLG8saSk7dmFyIHI9b1szXTtyZXR1cm4ge3BvaW50Om5ldyB0LlBvaW50KG9bMF0vcixvWzFdL3IpLHNpZ25lZERpc3RhbmNlRnJvbUNhbWVyYTpyfX1mdW5jdGlvbiBKdCh0LGUpe3ZhciBpPXRbMF0vdFszXSxvPXRbMV0vdFszXTtyZXR1cm4gaT49LWVbMF0mJmk8PWVbMF0mJm8+PS1lWzFdJiZvPD1lWzFdfWZ1bmN0aW9uIFF0KGUsaSxvLHIsYSxuLHMsbCl7dmFyIGM9cj9lLnRleHRTaXplRGF0YTplLmljb25TaXplRGF0YSx1PXQuZXZhbHVhdGVTaXplRm9yWm9vbShjLG8udHJhbnNmb3JtLnpvb20pLGg9WzI1Ni9vLndpZHRoKjIrMSwyNTYvby5oZWlnaHQqMisxXSxwPXI/ZS50ZXh0LmR5bmFtaWNMYXlvdXRWZXJ0ZXhBcnJheTplLmljb24uZHluYW1pY0xheW91dFZlcnRleEFycmF5O3AuY2xlYXIoKTtmb3IodmFyIGQ9ZS5saW5lVmVydGV4QXJyYXksXz1yP2UudGV4dC5wbGFjZWRTeW1ib2xBcnJheTplLmljb24ucGxhY2VkU3ltYm9sQXJyYXksZj1vLnRyYW5zZm9ybS53aWR0aC9vLnRyYW5zZm9ybS5oZWlnaHQsbT0hMSxnPTA7ZzxfLmxlbmd0aDtnKyspe3ZhciB2PV8uZ2V0KGcpO2lmKHYuaGlkZGVufHx2LndyaXRpbmdNb2RlPT09dC5Xcml0aW5nTW9kZS52ZXJ0aWNhbCYmIW0pYWUodi5udW1HbHlwaHMscCk7ZWxzZXttPSExO3ZhciB5PVt2LmFuY2hvclgsdi5hbmNob3JZLDAsMV07aWYodC50cmFuc2Zvcm1NYXQ0KHkseSxpKSxKdCh5LGgpKXt2YXIgeD0uNSt5WzNdL28udHJhbnNmb3JtLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2UqLjUsYj10LmV2YWx1YXRlU2l6ZUZvckZlYXR1cmUoYyx1LHYpLHc9cz9iKng6Yi94LEU9bmV3IHQuUG9pbnQodi5hbmNob3JYLHYuYW5jaG9yWSksVD1ZdChFLGEpLnBvaW50LEk9e30sQz1lZSh2LHcsITEsbCxpLGEsbixlLmdseXBoT2Zmc2V0QXJyYXksZCxwLFQsRSxJLGYpO209Qy51c2VWZXJ0aWNhbCwoQy5ub3RFbm91Z2hSb29tfHxtfHxDLm5lZWRzRmxpcHBpbmcmJmVlKHYsdywhMCxsLGksYSxuLGUuZ2x5cGhPZmZzZXRBcnJheSxkLHAsVCxFLEksZikubm90RW5vdWdoUm9vbSkmJmFlKHYubnVtR2x5cGhzLHApO31lbHNlIGFlKHYubnVtR2x5cGhzLHApO319cj9lLnRleHQuZHluYW1pY0xheW91dFZlcnRleEJ1ZmZlci51cGRhdGVEYXRhKHApOmUuaWNvbi5keW5hbWljTGF5b3V0VmVydGV4QnVmZmVyLnVwZGF0ZURhdGEocCk7fWZ1bmN0aW9uICR0KHQsZSxpLG8scixhLG4scyxsLGMsdSxoKXt2YXIgcD1zLmdseXBoU3RhcnRJbmRleCtzLm51bUdseXBocyxkPXMubGluZVN0YXJ0SW5kZXgsXz1zLmxpbmVTdGFydEluZGV4K3MubGluZUxlbmd0aCxmPWUuZ2V0b2Zmc2V0WChzLmdseXBoU3RhcnRJbmRleCksbT1lLmdldG9mZnNldFgocC0xKSxnPW9lKHQqZixpLG8scixhLG4scy5zZWdtZW50LGQsXyxsLGMsdSxoKTtpZighZylyZXR1cm4gbnVsbDt2YXIgdj1vZSh0Km0saSxvLHIsYSxuLHMuc2VnbWVudCxkLF8sbCxjLHUsaCk7cmV0dXJuIHY/e2ZpcnN0OmcsbGFzdDp2fTpudWxsfWZ1bmN0aW9uIHRlKGUsaSxvLHIpe2lmKGU9PT10LldyaXRpbmdNb2RlLmhvcml6b250YWwmJk1hdGguYWJzKG8ueS1pLnkpPk1hdGguYWJzKG8ueC1pLngpKnIpcmV0dXJuIHt1c2VWZXJ0aWNhbDohMH07cmV0dXJuIChlPT09dC5Xcml0aW5nTW9kZS52ZXJ0aWNhbD9pLnk8by55OmkueD5vLngpP3tuZWVkc0ZsaXBwaW5nOiEwfTpudWxsfWZ1bmN0aW9uIGVlKGUsaSxvLHIsYSxuLHMsbCxjLHUsaCxwLGQsXyl7dmFyIGYsbT1pLzI0LGc9ZS5saW5lT2Zmc2V0WCptLHY9ZS5saW5lT2Zmc2V0WSptO2lmKGUubnVtR2x5cGhzPjEpe3ZhciB5PWUuZ2x5cGhTdGFydEluZGV4K2UubnVtR2x5cGhzLHg9ZS5saW5lU3RhcnRJbmRleCxiPWUubGluZVN0YXJ0SW5kZXgrZS5saW5lTGVuZ3RoLHc9JHQobSxsLGcsdixvLGgscCxlLGMsbixkLCExKTtpZighdylyZXR1cm4ge25vdEVub3VnaFJvb206ITB9O3ZhciBFPVl0KHcuZmlyc3QucG9pbnQscykucG9pbnQsVD1ZdCh3Lmxhc3QucG9pbnQscykucG9pbnQ7aWYociYmIW8pe3ZhciBJPXRlKGUud3JpdGluZ01vZGUsRSxULF8pO2lmKEkpcmV0dXJuIEl9Zj1bdy5maXJzdF07Zm9yKHZhciBDPWUuZ2x5cGhTdGFydEluZGV4KzE7Qzx5LTE7QysrKWYucHVzaChvZShtKmwuZ2V0b2Zmc2V0WChDKSxnLHYsbyxoLHAsZS5zZWdtZW50LHgsYixjLG4sZCwhMSkpO2YucHVzaCh3Lmxhc3QpO31lbHNle2lmKHImJiFvKXt2YXIgUz1ZdChwLGEpLnBvaW50LFA9ZS5saW5lU3RhcnRJbmRleCtlLnNlZ21lbnQrMSx6PW5ldyB0LlBvaW50KGMuZ2V0eChQKSxjLmdldHkoUCkpLEw9WXQoeixhKSxEPUwuc2lnbmVkRGlzdGFuY2VGcm9tQ2FtZXJhPjA/TC5wb2ludDppZShwLHosUywxLGEpLE09dGUoZS53cml0aW5nTW9kZSxTLEQsXyk7aWYoTSlyZXR1cm4gTX12YXIgUj1vZShtKmwuZ2V0b2Zmc2V0WChlLmdseXBoU3RhcnRJbmRleCksZyx2LG8saCxwLGUuc2VnbWVudCxlLmxpbmVTdGFydEluZGV4LGUubGluZVN0YXJ0SW5kZXgrZS5saW5lTGVuZ3RoLGMsbixkLCExKTtpZighUilyZXR1cm4ge25vdEVub3VnaFJvb206ITB9O2Y9W1JdO31mb3IodmFyIEE9MCxrPWY7QTxrLmxlbmd0aDtBKz0xKXt2YXIgQj1rW0FdO3QuYWRkRHluYW1pY0F0dHJpYnV0ZXModSxCLnBvaW50LEIuYW5nbGUpO31yZXR1cm4ge319ZnVuY3Rpb24gaWUodCxlLGksbyxyKXt2YXIgYT1ZdCh0LmFkZCh0LnN1YihlKS5fdW5pdCgpKSxyKS5wb2ludCxuPWkuc3ViKGEpO3JldHVybiBpLmFkZChuLl9tdWx0KG8vbi5tYWcoKSkpfWZ1bmN0aW9uIG9lKGUsaSxvLHIsYSxuLHMsbCxjLHUsaCxwLGQpe3ZhciBfPXI/ZS1pOmUraSxmPV8+MD8xOi0xLG09MDtyJiYoZio9LTEsbT1NYXRoLlBJKSxmPDAmJihtKz1NYXRoLlBJKTtmb3IodmFyIGc9Zj4wP2wrczpsK3MrMSx2PWcseT1hLHg9YSxiPTAsdz0wLEU9TWF0aC5hYnMoXyk7Yit3PD1FOyl7aWYoKGcrPWYpPGx8fGc+PWMpcmV0dXJuIG51bGw7aWYoeD15LHZvaWQgMD09PSh5PXBbZ10pKXt2YXIgVD1uZXcgdC5Qb2ludCh1LmdldHgoZyksdS5nZXR5KGcpKSxJPVl0KFQsaCk7aWYoSS5zaWduZWREaXN0YW5jZUZyb21DYW1lcmE+MCl5PXBbZ109SS5wb2ludDtlbHNle3ZhciBDPWctZjt5PWllKDA9PT1iP246bmV3IHQuUG9pbnQodS5nZXR4KEMpLHUuZ2V0eShDKSksVCx4LEUtYisxLGgpO319Yis9dyx3PXguZGlzdCh5KTt9dmFyIFM9KEUtYikvdyxQPXkuc3ViKHgpLHo9UC5tdWx0KFMpLl9hZGQoeCk7cmV0dXJuIHouX2FkZChQLl91bml0KCkuX3BlcnAoKS5fbXVsdChvKmYpKSx7cG9pbnQ6eixhbmdsZTptK01hdGguYXRhbjIoeS55LXgueSx5LngteC54KSx0aWxlRGlzdGFuY2U6ZD97cHJldlRpbGVEaXN0YW5jZTpnLWY9PT12PzA6dS5nZXR0aWxlVW5pdERpc3RhbmNlRnJvbUFuY2hvcihnLWYpLGxhc3RTZWdtZW50Vmlld3BvcnREaXN0YW5jZTpFLWJ9Om51bGx9fVh0LnByb3RvdHlwZS5rZXlzTGVuZ3RoPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYm94S2V5cy5sZW5ndGgrdGhpcy5jaXJjbGVLZXlzLmxlbmd0aH0sWHQucHJvdG90eXBlLmluc2VydD1mdW5jdGlvbih0LGUsaSxvLHIpe3RoaXMuX2ZvckVhY2hDZWxsKGUsaSxvLHIsdGhpcy5faW5zZXJ0Qm94Q2VsbCx0aGlzLmJveFVpZCsrKSx0aGlzLmJveEtleXMucHVzaCh0KSx0aGlzLmJib3hlcy5wdXNoKGUpLHRoaXMuYmJveGVzLnB1c2goaSksdGhpcy5iYm94ZXMucHVzaChvKSx0aGlzLmJib3hlcy5wdXNoKHIpO30sWHQucHJvdG90eXBlLmluc2VydENpcmNsZT1mdW5jdGlvbih0LGUsaSxvKXt0aGlzLl9mb3JFYWNoQ2VsbChlLW8saS1vLGUrbyxpK28sdGhpcy5faW5zZXJ0Q2lyY2xlQ2VsbCx0aGlzLmNpcmNsZVVpZCsrKSx0aGlzLmNpcmNsZUtleXMucHVzaCh0KSx0aGlzLmNpcmNsZXMucHVzaChlKSx0aGlzLmNpcmNsZXMucHVzaChpKSx0aGlzLmNpcmNsZXMucHVzaChvKTt9LFh0LnByb3RvdHlwZS5faW5zZXJ0Qm94Q2VsbD1mdW5jdGlvbih0LGUsaSxvLHIsYSl7dGhpcy5ib3hDZWxsc1tyXS5wdXNoKGEpO30sWHQucHJvdG90eXBlLl9pbnNlcnRDaXJjbGVDZWxsPWZ1bmN0aW9uKHQsZSxpLG8scixhKXt0aGlzLmNpcmNsZUNlbGxzW3JdLnB1c2goYSk7fSxYdC5wcm90b3R5cGUuX3F1ZXJ5PWZ1bmN0aW9uKHQsZSxpLG8scixhKXtpZihpPDB8fHQ+dGhpcy53aWR0aHx8bzwwfHxlPnRoaXMuaGVpZ2h0KXJldHVybiAhciYmW107dmFyIG49W107aWYodDw9MCYmZTw9MCYmdGhpcy53aWR0aDw9aSYmdGhpcy5oZWlnaHQ8PW8pe2lmKHIpcmV0dXJuICEwO2Zvcih2YXIgcz0wO3M8dGhpcy5ib3hLZXlzLmxlbmd0aDtzKyspbi5wdXNoKHtrZXk6dGhpcy5ib3hLZXlzW3NdLHgxOnRoaXMuYmJveGVzWzQqc10seTE6dGhpcy5iYm94ZXNbNCpzKzFdLHgyOnRoaXMuYmJveGVzWzQqcysyXSx5Mjp0aGlzLmJib3hlc1s0KnMrM119KTtmb3IodmFyIGw9MDtsPHRoaXMuY2lyY2xlS2V5cy5sZW5ndGg7bCsrKXt2YXIgYz10aGlzLmNpcmNsZXNbMypsXSx1PXRoaXMuY2lyY2xlc1szKmwrMV0saD10aGlzLmNpcmNsZXNbMypsKzJdO24ucHVzaCh7a2V5OnRoaXMuY2lyY2xlS2V5c1tsXSx4MTpjLWgseTE6dS1oLHgyOmMraCx5Mjp1K2h9KTt9cmV0dXJuIGE/bi5maWx0ZXIoYSk6bn12YXIgcD17aGl0VGVzdDpyLHNlZW5VaWRzOntib3g6e30sY2lyY2xlOnt9fX07cmV0dXJuIHRoaXMuX2ZvckVhY2hDZWxsKHQsZSxpLG8sdGhpcy5fcXVlcnlDZWxsLG4scCxhKSxyP24ubGVuZ3RoPjA6bn0sWHQucHJvdG90eXBlLl9xdWVyeUNpcmNsZT1mdW5jdGlvbih0LGUsaSxvLHIpe3ZhciBhPXQtaSxuPXQraSxzPWUtaSxsPWUraTtpZihuPDB8fGE+dGhpcy53aWR0aHx8bDwwfHxzPnRoaXMuaGVpZ2h0KXJldHVybiAhbyYmW107dmFyIGM9W10sdT17aGl0VGVzdDpvLGNpcmNsZTp7eDp0LHk6ZSxyYWRpdXM6aX0sc2VlblVpZHM6e2JveDp7fSxjaXJjbGU6e319fTtyZXR1cm4gdGhpcy5fZm9yRWFjaENlbGwoYSxzLG4sbCx0aGlzLl9xdWVyeUNlbGxDaXJjbGUsYyx1LHIpLG8/Yy5sZW5ndGg+MDpjfSxYdC5wcm90b3R5cGUucXVlcnk9ZnVuY3Rpb24odCxlLGksbyxyKXtyZXR1cm4gdGhpcy5fcXVlcnkodCxlLGksbywhMSxyKX0sWHQucHJvdG90eXBlLmhpdFRlc3Q9ZnVuY3Rpb24odCxlLGksbyxyKXtyZXR1cm4gdGhpcy5fcXVlcnkodCxlLGksbywhMCxyKX0sWHQucHJvdG90eXBlLmhpdFRlc3RDaXJjbGU9ZnVuY3Rpb24odCxlLGksbyl7cmV0dXJuIHRoaXMuX3F1ZXJ5Q2lyY2xlKHQsZSxpLCEwLG8pfSxYdC5wcm90b3R5cGUuX3F1ZXJ5Q2VsbD1mdW5jdGlvbih0LGUsaSxvLHIsYSxuLHMpe3ZhciBsPW4uc2VlblVpZHMsYz10aGlzLmJveENlbGxzW3JdO2lmKG51bGwhPT1jKWZvcih2YXIgdT10aGlzLmJib3hlcyxoPTAscD1jO2g8cC5sZW5ndGg7aCs9MSl7dmFyIGQ9cFtoXTtpZighbC5ib3hbZF0pe2wuYm94W2RdPSEwO3ZhciBfPTQqZDtpZih0PD11W18rMl0mJmU8PXVbXyszXSYmaT49dVtfKzBdJiZvPj11W18rMV0mJighc3x8cyh0aGlzLmJveEtleXNbZF0pKSl7aWYobi5oaXRUZXN0KXJldHVybiBhLnB1c2goITApLCEwO2EucHVzaCh7a2V5OnRoaXMuYm94S2V5c1tkXSx4MTp1W19dLHkxOnVbXysxXSx4Mjp1W18rMl0seTI6dVtfKzNdfSk7fX19dmFyIGY9dGhpcy5jaXJjbGVDZWxsc1tyXTtpZihudWxsIT09Zilmb3IodmFyIG09dGhpcy5jaXJjbGVzLGc9MCx2PWY7Zzx2Lmxlbmd0aDtnKz0xKXt2YXIgeT12W2ddO2lmKCFsLmNpcmNsZVt5XSl7bC5jaXJjbGVbeV09ITA7dmFyIHg9Myp5O2lmKHRoaXMuX2NpcmNsZUFuZFJlY3RDb2xsaWRlKG1beF0sbVt4KzFdLG1beCsyXSx0LGUsaSxvKSYmKCFzfHxzKHRoaXMuY2lyY2xlS2V5c1t5XSkpKXtpZihuLmhpdFRlc3QpcmV0dXJuIGEucHVzaCghMCksITA7dmFyIGI9bVt4XSx3PW1beCsxXSxFPW1beCsyXTthLnB1c2goe2tleTp0aGlzLmNpcmNsZUtleXNbeV0seDE6Yi1FLHkxOnctRSx4MjpiK0UseTI6dytFfSk7fX19fSxYdC5wcm90b3R5cGUuX3F1ZXJ5Q2VsbENpcmNsZT1mdW5jdGlvbih0LGUsaSxvLHIsYSxuLHMpe3ZhciBsPW4uY2lyY2xlLGM9bi5zZWVuVWlkcyx1PXRoaXMuYm94Q2VsbHNbcl07aWYobnVsbCE9PXUpZm9yKHZhciBoPXRoaXMuYmJveGVzLHA9MCxkPXU7cDxkLmxlbmd0aDtwKz0xKXt2YXIgXz1kW3BdO2lmKCFjLmJveFtfXSl7Yy5ib3hbX109ITA7dmFyIGY9NCpfO2lmKHRoaXMuX2NpcmNsZUFuZFJlY3RDb2xsaWRlKGwueCxsLnksbC5yYWRpdXMsaFtmKzBdLGhbZisxXSxoW2YrMl0saFtmKzNdKSYmKCFzfHxzKHRoaXMuYm94S2V5c1tfXSkpKXJldHVybiBhLnB1c2goITApLCEwfX12YXIgbT10aGlzLmNpcmNsZUNlbGxzW3JdO2lmKG51bGwhPT1tKWZvcih2YXIgZz10aGlzLmNpcmNsZXMsdj0wLHk9bTt2PHkubGVuZ3RoO3YrPTEpe3ZhciB4PXlbdl07aWYoIWMuY2lyY2xlW3hdKXtjLmNpcmNsZVt4XT0hMDt2YXIgYj0zKng7aWYodGhpcy5fY2lyY2xlc0NvbGxpZGUoZ1tiXSxnW2IrMV0sZ1tiKzJdLGwueCxsLnksbC5yYWRpdXMpJiYoIXN8fHModGhpcy5jaXJjbGVLZXlzW3hdKSkpcmV0dXJuIGEucHVzaCghMCksITB9fX0sWHQucHJvdG90eXBlLl9mb3JFYWNoQ2VsbD1mdW5jdGlvbih0LGUsaSxvLHIsYSxuLHMpe2Zvcih2YXIgbD10aGlzLl9jb252ZXJ0VG9YQ2VsbENvb3JkKHQpLGM9dGhpcy5fY29udmVydFRvWUNlbGxDb29yZChlKSx1PXRoaXMuX2NvbnZlcnRUb1hDZWxsQ29vcmQoaSksaD10aGlzLl9jb252ZXJ0VG9ZQ2VsbENvb3JkKG8pLHA9bDtwPD11O3ArKylmb3IodmFyIGQ9YztkPD1oO2QrKyl7dmFyIF89dGhpcy54Q2VsbENvdW50KmQrcDtpZihyLmNhbGwodGhpcyx0LGUsaSxvLF8sYSxuLHMpKXJldHVybn19LFh0LnByb3RvdHlwZS5fY29udmVydFRvWENlbGxDb29yZD1mdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5tYXgoMCxNYXRoLm1pbih0aGlzLnhDZWxsQ291bnQtMSxNYXRoLmZsb29yKHQqdGhpcy54U2NhbGUpKSl9LFh0LnByb3RvdHlwZS5fY29udmVydFRvWUNlbGxDb29yZD1mdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5tYXgoMCxNYXRoLm1pbih0aGlzLnlDZWxsQ291bnQtMSxNYXRoLmZsb29yKHQqdGhpcy55U2NhbGUpKSl9LFh0LnByb3RvdHlwZS5fY2lyY2xlc0NvbGxpZGU9ZnVuY3Rpb24odCxlLGksbyxyLGEpe3ZhciBuPW8tdCxzPXItZSxsPWkrYTtyZXR1cm4gbCpsPm4qbitzKnN9LFh0LnByb3RvdHlwZS5fY2lyY2xlQW5kUmVjdENvbGxpZGU9ZnVuY3Rpb24odCxlLGksbyxyLGEsbil7dmFyIHM9KGEtbykvMixsPU1hdGguYWJzKHQtKG8rcykpO2lmKGw+cytpKXJldHVybiAhMTt2YXIgYz0obi1yKS8yLHU9TWF0aC5hYnMoZS0ocitjKSk7aWYodT5jK2kpcmV0dXJuICExO2lmKGw8PXN8fHU8PWMpcmV0dXJuICEwO3ZhciBoPWwtcyxwPXUtYztyZXR1cm4gaCpoK3AqcDw9aSppfTt2YXIgcmU9bmV3IEZsb2F0MzJBcnJheShbLTEvMCwtMS8wLDAsLTEvMCwtMS8wLDAsLTEvMCwtMS8wLDAsLTEvMCwtMS8wLDBdKTtmdW5jdGlvbiBhZSh0LGUpe2Zvcih2YXIgaT0wO2k8dDtpKyspe3ZhciBvPWUubGVuZ3RoO2UucmVzaXplKG8rNCksZS5mbG9hdDMyLnNldChyZSwzKm8pO319ZnVuY3Rpb24gbmUodCxlLGkpe3ZhciBvPWVbMF0scj1lWzFdO3JldHVybiB0WzBdPWlbMF0qbytpWzRdKnIraVsxMl0sdFsxXT1pWzFdKm8raVs1XSpyK2lbMTNdLHRbM109aVszXSpvK2lbN10qcitpWzE1XSx0fXZhciBzZT1mdW5jdGlvbih0LGUsaSl7dm9pZCAwPT09ZSYmKGU9bmV3IFh0KHQud2lkdGgrMjAwLHQuaGVpZ2h0KzIwMCwyNSkpLHZvaWQgMD09PWkmJihpPW5ldyBYdCh0LndpZHRoKzIwMCx0LmhlaWdodCsyMDAsMjUpKSx0aGlzLnRyYW5zZm9ybT10LHRoaXMuZ3JpZD1lLHRoaXMuaWdub3JlZEdyaWQ9aSx0aGlzLnBpdGNoZmFjdG9yPU1hdGguY29zKHQuX3BpdGNoKSp0LmNhbWVyYVRvQ2VudGVyRGlzdGFuY2UsdGhpcy5zY3JlZW5SaWdodEJvdW5kYXJ5PXQud2lkdGgrMTAwLHRoaXMuc2NyZWVuQm90dG9tQm91bmRhcnk9dC5oZWlnaHQrMTAwLHRoaXMuZ3JpZFJpZ2h0Qm91bmRhcnk9dC53aWR0aCsyMDAsdGhpcy5ncmlkQm90dG9tQm91bmRhcnk9dC5oZWlnaHQrMjAwO307ZnVuY3Rpb24gbGUodCxlLGkpe3RbZSs0XT1pPzE6MDt9ZnVuY3Rpb24gY2UoZSxpLG8pe3JldHVybiBpKih0LkVYVEVOVC8oZS50aWxlU2l6ZSpNYXRoLnBvdygyLG8tZS50aWxlSUQub3ZlcnNjYWxlZFopKSl9c2UucHJvdG90eXBlLnBsYWNlQ29sbGlzaW9uQm94PWZ1bmN0aW9uKHQsZSxpLG8scil7dmFyIGE9dGhpcy5wcm9qZWN0QW5kR2V0UGVyc3BlY3RpdmVSYXRpbyhvLHQuYW5jaG9yUG9pbnRYLHQuYW5jaG9yUG9pbnRZKSxuPWkqYS5wZXJzcGVjdGl2ZVJhdGlvLHM9dC54MSpuK2EucG9pbnQueCxsPXQueTEqbithLnBvaW50LnksYz10LngyKm4rYS5wb2ludC54LHU9dC55MipuK2EucG9pbnQueTtyZXR1cm4gIXRoaXMuaXNJbnNpZGVHcmlkKHMsbCxjLHUpfHwhZSYmdGhpcy5ncmlkLmhpdFRlc3QocyxsLGMsdSxyKT97Ym94OltdLG9mZnNjcmVlbjohMX06e2JveDpbcyxsLGMsdV0sb2Zmc2NyZWVuOnRoaXMuaXNPZmZzY3JlZW4ocyxsLGMsdSl9fSxzZS5wcm90b3R5cGUuYXBwcm94aW1hdGVUaWxlRGlzdGFuY2U9ZnVuY3Rpb24odCxlLGksbyxyKXt2YXIgYT1yPzE6by90aGlzLnBpdGNoZmFjdG9yLG49dC5sYXN0U2VnbWVudFZpZXdwb3J0RGlzdGFuY2UqaTtyZXR1cm4gdC5wcmV2VGlsZURpc3RhbmNlK24rKGEtMSkqbipNYXRoLmFicyhNYXRoLnNpbihlKSl9LHNlLnByb3RvdHlwZS5wbGFjZUNvbGxpc2lvbkNpcmNsZXM9ZnVuY3Rpb24oZSxpLG8scixhLG4scyxsLGMsdSxoLHAsZCl7dmFyIF89W10sZj10aGlzLnByb2plY3RBbmNob3IoYyxhLmFuY2hvclgsYS5hbmNob3JZKSxtPWwvMjQsZz1hLmxpbmVPZmZzZXRYKmwsdj1hLmxpbmVPZmZzZXRZKmwseT1uZXcgdC5Qb2ludChhLmFuY2hvclgsYS5hbmNob3JZKSx4PSR0KG0scyxnLHYsITEsWXQoeSx1KS5wb2ludCx5LGEsbix1LHt9LCEwKSxiPSExLHc9ITEsRT0hMCxUPWYucGVyc3BlY3RpdmVSYXRpbypyLEk9MS8ocipvKSxDPTAsUz0wO3gmJihDPXRoaXMuYXBwcm94aW1hdGVUaWxlRGlzdGFuY2UoeC5maXJzdC50aWxlRGlzdGFuY2UseC5maXJzdC5hbmdsZSxJLGYuY2FtZXJhRGlzdGFuY2UscCksUz10aGlzLmFwcHJveGltYXRlVGlsZURpc3RhbmNlKHgubGFzdC50aWxlRGlzdGFuY2UseC5sYXN0LmFuZ2xlLEksZi5jYW1lcmFEaXN0YW5jZSxwKSk7Zm9yKHZhciBQPTA7UDxlLmxlbmd0aDtQKz01KXt2YXIgej1lW1BdLEw9ZVtQKzFdLEQ9ZVtQKzJdLE09ZVtQKzNdO2lmKCF4fHxNPC1DfHxNPlMpbGUoZSxQLCExKTtlbHNle3ZhciBSPXRoaXMucHJvamVjdFBvaW50KGMseixMKSxBPUQqVDtpZihfLmxlbmd0aD4wKXt2YXIgaz1SLngtX1tfLmxlbmd0aC00XSxCPVIueS1fW18ubGVuZ3RoLTNdO2lmKEEqQSoyPmsqaytCKkIpaWYoUCs4PGUubGVuZ3RoKXt2YXIgTz1lW1ArOF07aWYoTz4tQyYmTzxTKXtsZShlLFAsITEpO2NvbnRpbnVlfX19dmFyIEY9UC81O18ucHVzaChSLngsUi55LEEsRiksbGUoZSxQLCEwKTt2YXIgVT1SLngtQSxOPVIueS1BLFo9Ui54K0Esaj1SLnkrQTtpZihFPUUmJnRoaXMuaXNPZmZzY3JlZW4oVSxOLFosaiksdz13fHx0aGlzLmlzSW5zaWRlR3JpZChVLE4sWixqKSwhaSYmdGhpcy5ncmlkLmhpdFRlc3RDaXJjbGUoUi54LFIueSxBLGQpKXtpZighaClyZXR1cm4ge2NpcmNsZXM6W10sb2Zmc2NyZWVuOiExfTtiPSEwO319fXJldHVybiB7Y2lyY2xlczpifHwhdz9bXTpfLG9mZnNjcmVlbjpFfX0sc2UucHJvdG90eXBlLnF1ZXJ5UmVuZGVyZWRTeW1ib2xzPWZ1bmN0aW9uKGUpe2lmKDA9PT1lLmxlbmd0aHx8MD09PXRoaXMuZ3JpZC5rZXlzTGVuZ3RoKCkmJjA9PT10aGlzLmlnbm9yZWRHcmlkLmtleXNMZW5ndGgoKSlyZXR1cm4ge307Zm9yKHZhciBpPVtdLG89MS8wLHI9MS8wLGE9LTEvMCxuPS0xLzAscz0wLGw9ZTtzPGwubGVuZ3RoO3MrPTEpe3ZhciBjPWxbc10sdT1uZXcgdC5Qb2ludChjLngrMTAwLGMueSsxMDApO289TWF0aC5taW4obyx1LngpLHI9TWF0aC5taW4ocix1LnkpLGE9TWF0aC5tYXgoYSx1LngpLG49TWF0aC5tYXgobix1LnkpLGkucHVzaCh1KTt9Zm9yKHZhciBoPXt9LHA9e30sZD0wLF89dGhpcy5ncmlkLnF1ZXJ5KG8scixhLG4pLmNvbmNhdCh0aGlzLmlnbm9yZWRHcmlkLnF1ZXJ5KG8scixhLG4pKTtkPF8ubGVuZ3RoO2QrPTEpe3ZhciBmPV9bZF0sbT1mLmtleTtpZih2b2lkIDA9PT1oW20uYnVja2V0SW5zdGFuY2VJZF0mJihoW20uYnVja2V0SW5zdGFuY2VJZF09e30pLCFoW20uYnVja2V0SW5zdGFuY2VJZF1bbS5mZWF0dXJlSW5kZXhdKXt2YXIgZz1bbmV3IHQuUG9pbnQoZi54MSxmLnkxKSxuZXcgdC5Qb2ludChmLngyLGYueTEpLG5ldyB0LlBvaW50KGYueDIsZi55MiksbmV3IHQuUG9pbnQoZi54MSxmLnkyKV07dC5wb2x5Z29uSW50ZXJzZWN0c1BvbHlnb24oaSxnKSYmKGhbbS5idWNrZXRJbnN0YW5jZUlkXVttLmZlYXR1cmVJbmRleF09ITAsdm9pZCAwPT09cFttLmJ1Y2tldEluc3RhbmNlSWRdJiYocFttLmJ1Y2tldEluc3RhbmNlSWRdPVtdKSxwW20uYnVja2V0SW5zdGFuY2VJZF0ucHVzaChtLmZlYXR1cmVJbmRleCkpO319cmV0dXJuIHB9LHNlLnByb3RvdHlwZS5pbnNlcnRDb2xsaXNpb25Cb3g9ZnVuY3Rpb24odCxlLGksbyxyKXt2YXIgYT17YnVja2V0SW5zdGFuY2VJZDppLGZlYXR1cmVJbmRleDpvLGNvbGxpc2lvbkdyb3VwSUQ6cn07KGU/dGhpcy5pZ25vcmVkR3JpZDp0aGlzLmdyaWQpLmluc2VydChhLHRbMF0sdFsxXSx0WzJdLHRbM10pO30sc2UucHJvdG90eXBlLmluc2VydENvbGxpc2lvbkNpcmNsZXM9ZnVuY3Rpb24odCxlLGksbyxyKXtmb3IodmFyIGE9ZT90aGlzLmlnbm9yZWRHcmlkOnRoaXMuZ3JpZCxuPXtidWNrZXRJbnN0YW5jZUlkOmksZmVhdHVyZUluZGV4Om8sY29sbGlzaW9uR3JvdXBJRDpyfSxzPTA7czx0Lmxlbmd0aDtzKz00KWEuaW5zZXJ0Q2lyY2xlKG4sdFtzXSx0W3MrMV0sdFtzKzJdKTt9LHNlLnByb3RvdHlwZS5wcm9qZWN0QW5jaG9yPWZ1bmN0aW9uKHQsZSxpKXt2YXIgbz1bZSxpLDAsMV07cmV0dXJuIG5lKG8sbyx0KSx7cGVyc3BlY3RpdmVSYXRpbzouNSt0aGlzLnRyYW5zZm9ybS5jYW1lcmFUb0NlbnRlckRpc3RhbmNlL29bM10qLjUsY2FtZXJhRGlzdGFuY2U6b1szXX19LHNlLnByb3RvdHlwZS5wcm9qZWN0UG9pbnQ9ZnVuY3Rpb24oZSxpLG8pe3ZhciByPVtpLG8sMCwxXTtyZXR1cm4gbmUocixyLGUpLG5ldyB0LlBvaW50KChyWzBdL3JbM10rMSkvMip0aGlzLnRyYW5zZm9ybS53aWR0aCsxMDAsKC1yWzFdL3JbM10rMSkvMip0aGlzLnRyYW5zZm9ybS5oZWlnaHQrMTAwKX0sc2UucHJvdG90eXBlLnByb2plY3RBbmRHZXRQZXJzcGVjdGl2ZVJhdGlvPWZ1bmN0aW9uKGUsaSxvKXt2YXIgcj1baSxvLDAsMV07cmV0dXJuIG5lKHIscixlKSx7cG9pbnQ6bmV3IHQuUG9pbnQoKHJbMF0vclszXSsxKS8yKnRoaXMudHJhbnNmb3JtLndpZHRoKzEwMCwoLXJbMV0vclszXSsxKS8yKnRoaXMudHJhbnNmb3JtLmhlaWdodCsxMDApLHBlcnNwZWN0aXZlUmF0aW86LjUrdGhpcy50cmFuc2Zvcm0uY2FtZXJhVG9DZW50ZXJEaXN0YW5jZS9yWzNdKi41fX0sc2UucHJvdG90eXBlLmlzT2Zmc2NyZWVuPWZ1bmN0aW9uKHQsZSxpLG8pe3JldHVybiBpPDEwMHx8dD49dGhpcy5zY3JlZW5SaWdodEJvdW5kYXJ5fHxvPDEwMHx8ZT50aGlzLnNjcmVlbkJvdHRvbUJvdW5kYXJ5fSxzZS5wcm90b3R5cGUuaXNJbnNpZGVHcmlkPWZ1bmN0aW9uKHQsZSxpLG8pe3JldHVybiBpPj0wJiZ0PHRoaXMuZ3JpZFJpZ2h0Qm91bmRhcnkmJm8+PTAmJmU8dGhpcy5ncmlkQm90dG9tQm91bmRhcnl9O3ZhciB1ZT1mdW5jdGlvbih0LGUsaSxvKXt0aGlzLm9wYWNpdHk9dD9NYXRoLm1heCgwLE1hdGgubWluKDEsdC5vcGFjaXR5Kyh0LnBsYWNlZD9lOi1lKSkpOm8mJmk/MTowLHRoaXMucGxhY2VkPWk7fTt1ZS5wcm90b3R5cGUuaXNIaWRkZW49ZnVuY3Rpb24oKXtyZXR1cm4gMD09PXRoaXMub3BhY2l0eSYmIXRoaXMucGxhY2VkfTt2YXIgaGU9ZnVuY3Rpb24odCxlLGksbyxyKXt0aGlzLnRleHQ9bmV3IHVlKHQ/dC50ZXh0Om51bGwsZSxpLHIpLHRoaXMuaWNvbj1uZXcgdWUodD90Lmljb246bnVsbCxlLG8scik7fTtoZS5wcm90b3R5cGUuaXNIaWRkZW49ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50ZXh0LmlzSGlkZGVuKCkmJnRoaXMuaWNvbi5pc0hpZGRlbigpfTt2YXIgcGU9ZnVuY3Rpb24odCxlLGkpe3RoaXMudGV4dD10LHRoaXMuaWNvbj1lLHRoaXMuc2tpcEZhZGU9aTt9LGRlPWZ1bmN0aW9uKHQsZSxpLG8scil7dGhpcy5idWNrZXRJbnN0YW5jZUlkPXQsdGhpcy5mZWF0dXJlSW5kZXg9ZSx0aGlzLnNvdXJjZUxheWVySW5kZXg9aSx0aGlzLmJ1Y2tldEluZGV4PW8sdGhpcy50aWxlSUQ9cjt9LF9lPWZ1bmN0aW9uKHQpe3RoaXMuY3Jvc3NTb3VyY2VDb2xsaXNpb25zPXQsdGhpcy5tYXhHcm91cElEPTAsdGhpcy5jb2xsaXNpb25Hcm91cHM9e307fTtmdW5jdGlvbiBmZShlLGksbyxyLGEpe3ZhciBuPXQuZ2V0QW5jaG9yQWxpZ25tZW50KGUpLHM9LShuLmhvcml6b250YWxBbGlnbi0uNSkqaSxsPS0obi52ZXJ0aWNhbEFsaWduLS41KSpvLGM9dC5ldmFsdWF0ZVJhZGlhbE9mZnNldChlLHIpO3JldHVybiBuZXcgdC5Qb2ludChzK2NbMF0qYSxsK2NbMV0qYSl9X2UucHJvdG90eXBlLmdldD1mdW5jdGlvbih0KXtpZih0aGlzLmNyb3NzU291cmNlQ29sbGlzaW9ucylyZXR1cm4ge0lEOjAscHJlZGljYXRlOm51bGx9O2lmKCF0aGlzLmNvbGxpc2lvbkdyb3Vwc1t0XSl7dmFyIGU9Kyt0aGlzLm1heEdyb3VwSUQ7dGhpcy5jb2xsaXNpb25Hcm91cHNbdF09e0lEOmUscHJlZGljYXRlOmZ1bmN0aW9uKHQpe3JldHVybiB0LmNvbGxpc2lvbkdyb3VwSUQ9PT1lfX07fXJldHVybiB0aGlzLmNvbGxpc2lvbkdyb3Vwc1t0XX07dmFyIG1lPWZ1bmN0aW9uKHQsZSxpLG8pe3RoaXMudHJhbnNmb3JtPXQuY2xvbmUoKSx0aGlzLmNvbGxpc2lvbkluZGV4PW5ldyBzZSh0aGlzLnRyYW5zZm9ybSksdGhpcy5wbGFjZW1lbnRzPXt9LHRoaXMub3BhY2l0aWVzPXt9LHRoaXMudmFyaWFibGVPZmZzZXRzPXt9LHRoaXMuc3RhbGU9ITEsdGhpcy5jb21taXRUaW1lPTAsdGhpcy5mYWRlRHVyYXRpb249ZSx0aGlzLnJldGFpbmVkUXVlcnlEYXRhPXt9LHRoaXMuY29sbGlzaW9uR3JvdXBzPW5ldyBfZShpKSx0aGlzLnByZXZQbGFjZW1lbnQ9byxvJiYoby5wcmV2UGxhY2VtZW50PXZvaWQgMCk7fTtmdW5jdGlvbiBnZSh0LGUsaSxvLHIpe3QuZW1wbGFjZUJhY2soZT8xOjAsaT8xOjAsb3x8MCxyfHwwKSx0LmVtcGxhY2VCYWNrKGU/MTowLGk/MTowLG98fDAscnx8MCksdC5lbXBsYWNlQmFjayhlPzE6MCxpPzE6MCxvfHwwLHJ8fDApLHQuZW1wbGFjZUJhY2soZT8xOjAsaT8xOjAsb3x8MCxyfHwwKTt9bWUucHJvdG90eXBlLnBsYWNlTGF5ZXJUaWxlPWZ1bmN0aW9uKGUsaSxvLHIpe3ZhciBhPWkuZ2V0QnVja2V0KGUpLG49aS5sYXRlc3RGZWF0dXJlSW5kZXg7aWYoYSYmbiYmZS5pZD09PWEubGF5ZXJJZHNbMF0pe3ZhciBzPWkuY29sbGlzaW9uQm94QXJyYXksbD1hLmxheWVyc1swXS5sYXlvdXQsYz1NYXRoLnBvdygyLHRoaXMudHJhbnNmb3JtLnpvb20taS50aWxlSUQub3ZlcnNjYWxlZFopLHU9aS50aWxlU2l6ZS90LkVYVEVOVCxoPXRoaXMudHJhbnNmb3JtLmNhbGN1bGF0ZVBvc01hdHJpeChpLnRpbGVJRC50b1Vud3JhcHBlZCgpKSxwPUh0KGgsXCJtYXBcIj09PWwuZ2V0KFwidGV4dC1waXRjaC1hbGlnbm1lbnRcIiksXCJtYXBcIj09PWwuZ2V0KFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIiksdGhpcy50cmFuc2Zvcm0sY2UoaSwxLHRoaXMudHJhbnNmb3JtLnpvb20pKSxkPUh0KGgsXCJtYXBcIj09PWwuZ2V0KFwiaWNvbi1waXRjaC1hbGlnbm1lbnRcIiksXCJtYXBcIj09PWwuZ2V0KFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIiksdGhpcy50cmFuc2Zvcm0sY2UoaSwxLHRoaXMudHJhbnNmb3JtLnpvb20pKTt0aGlzLnJldGFpbmVkUXVlcnlEYXRhW2EuYnVja2V0SW5zdGFuY2VJZF09bmV3IGRlKGEuYnVja2V0SW5zdGFuY2VJZCxuLGEuc291cmNlTGF5ZXJJbmRleCxhLmluZGV4LGkudGlsZUlEKSx0aGlzLnBsYWNlTGF5ZXJCdWNrZXQoYSxoLHAsZCxjLHUsbyxpLmhvbGRpbmdGb3JGYWRlKCkscixzKTt9fSxtZS5wcm90b3R5cGUuYXR0ZW1wdEFuY2hvclBsYWNlbWVudD1mdW5jdGlvbihlLGksbyxyLGEsbixzLGwsYyx1LGgscCxkLF8pe3ZhciBmLG09ZmUoZSxvLHIsYSxuKSxnPXRoaXMuY29sbGlzaW9uSW5kZXgucGxhY2VDb2xsaXNpb25Cb3goZnVuY3Rpb24oZSxpLG8scixhLG4pe3ZhciBzPWUueDEsbD1lLngyLGM9ZS55MSx1PWUueTIsaD1lLmFuY2hvclBvaW50WCxwPWUuYW5jaG9yUG9pbnRZLGQ9bmV3IHQuUG9pbnQoaSxvKTtyZXR1cm4gciYmZC5fcm90YXRlKGE/bjotbikse3gxOnMrZC54LHkxOmMrZC55LHgyOmwrZC54LHkyOnUrZC55LGFuY2hvclBvaW50WDpoLGFuY2hvclBvaW50WTpwfX0oaSxtLngsbS55LHMsbCx0aGlzLnRyYW5zZm9ybS5hbmdsZSkscCxjLHUsaC5wcmVkaWNhdGUpO2lmKGcuYm94Lmxlbmd0aD4wKXJldHVybiB0aGlzLnByZXZQbGFjZW1lbnQmJnRoaXMucHJldlBsYWNlbWVudC52YXJpYWJsZU9mZnNldHNbZC5jcm9zc1RpbGVJRF0mJnRoaXMucHJldlBsYWNlbWVudC5wbGFjZW1lbnRzW2QuY3Jvc3NUaWxlSURdJiZ0aGlzLnByZXZQbGFjZW1lbnQucGxhY2VtZW50c1tkLmNyb3NzVGlsZUlEXS50ZXh0JiYoZj10aGlzLnByZXZQbGFjZW1lbnQudmFyaWFibGVPZmZzZXRzW2QuY3Jvc3NUaWxlSURdLmFuY2hvciksdGhpcy52YXJpYWJsZU9mZnNldHNbZC5jcm9zc1RpbGVJRF09e3JhZGlhbE9mZnNldDphLHdpZHRoOm8saGVpZ2h0OnIsYW5jaG9yOmUsdGV4dEJveFNjYWxlOm4scHJldkFuY2hvcjpmfSx0aGlzLm1hcmtVc2VkSnVzdGlmaWNhdGlvbihfLGUsZCksZ30sbWUucHJvdG90eXBlLnBsYWNlTGF5ZXJCdWNrZXQ9ZnVuY3Rpb24oZSxpLG8scixhLG4scyxsLGMsdSl7dmFyIGg9dGhpcyxwPWUubGF5ZXJzWzBdLmxheW91dCxkPXQuZXZhbHVhdGVTaXplRm9yWm9vbShlLnRleHRTaXplRGF0YSx0aGlzLnRyYW5zZm9ybS56b29tKSxfPXAuZ2V0KFwidGV4dC1vcHRpb25hbFwiKSxmPXAuZ2V0KFwiaWNvbi1vcHRpb25hbFwiKSxtPXAuZ2V0KFwidGV4dC1hbGxvdy1vdmVybGFwXCIpLGc9cC5nZXQoXCJpY29uLWFsbG93LW92ZXJsYXBcIiksdj1tJiYoZ3x8IWUuaGFzSWNvbkRhdGEoKXx8ZikseT1nJiYobXx8IWUuaGFzVGV4dERhdGEoKXx8XykseD10aGlzLmNvbGxpc2lvbkdyb3Vwcy5nZXQoZS5zb3VyY2VJRCksYj1cIm1hcFwiPT09cC5nZXQoXCJ0ZXh0LXJvdGF0aW9uLWFsaWdubWVudFwiKSx3PVwibWFwXCI9PT1wLmdldChcInRleHQtcGl0Y2gtYWxpZ25tZW50XCIpLEU9XCJ2aWV3cG9ydC15XCI9PT1wLmdldChcInN5bWJvbC16LW9yZGVyXCIpOyFlLmNvbGxpc2lvbkFycmF5cyYmdSYmZS5kZXNlcmlhbGl6ZUNvbGxpc2lvbkJveGVzKHUpO3ZhciBUPWZ1bmN0aW9uKHIsdSl7aWYoIWNbci5jcm9zc1RpbGVJRF0paWYobCloLnBsYWNlbWVudHNbci5jcm9zc1RpbGVJRF09bmV3IHBlKCExLCExLCExKTtlbHNle3ZhciBnPSExLEU9ITEsVD0hMCxJPW51bGwsQz1udWxsLFM9bnVsbCxQPTAsej0wO3UudGV4dEZlYXR1cmVJbmRleCYmKFA9dS50ZXh0RmVhdHVyZUluZGV4KTt2YXIgTD11LnRleHRCb3g7aWYoTClpZihwLmdldChcInRleHQtdmFyaWFibGUtYW5jaG9yXCIpKXt2YXIgRD1MLngyLUwueDEsTT1MLnkyLUwueTEsUj1yLnRleHRCb3hTY2FsZSxBPXAuZ2V0KFwidGV4dC12YXJpYWJsZS1hbmNob3JcIik7aWYoaC5wcmV2UGxhY2VtZW50JiZoLnByZXZQbGFjZW1lbnQudmFyaWFibGVPZmZzZXRzW3IuY3Jvc3NUaWxlSURdKXt2YXIgaz1oLnByZXZQbGFjZW1lbnQudmFyaWFibGVPZmZzZXRzW3IuY3Jvc3NUaWxlSURdO0FbMF0hPT1rLmFuY2hvciYmKEE9QS5maWx0ZXIoZnVuY3Rpb24odCl7cmV0dXJuIHQhPT1rLmFuY2hvcn0pKS51bnNoaWZ0KGsuYW5jaG9yKTt9Zm9yKHZhciBCPTAsTz1BO0I8Ty5sZW5ndGg7Qis9MSl7dmFyIEY9T1tCXTtpZihJPWguYXR0ZW1wdEFuY2hvclBsYWNlbWVudChGLEwsRCxNLHIucmFkaWFsVGV4dE9mZnNldCxSLGIsdyxuLGkseCxtLHIsZSkpe2c9ITA7YnJlYWt9fWlmKCFoLnZhcmlhYmxlT2Zmc2V0c1tyLmNyb3NzVGlsZUlEXSYmaC5wcmV2UGxhY2VtZW50KXt2YXIgVT1oLnByZXZQbGFjZW1lbnQudmFyaWFibGVPZmZzZXRzW3IuY3Jvc3NUaWxlSURdO1UmJihoLnZhcmlhYmxlT2Zmc2V0c1tyLmNyb3NzVGlsZUlEXT1VLGgubWFya1VzZWRKdXN0aWZpY2F0aW9uKGUsVS5hbmNob3IscikpO319ZWxzZSBnPShJPWguY29sbGlzaW9uSW5kZXgucGxhY2VDb2xsaXNpb25Cb3goTCxwLmdldChcInRleHQtYWxsb3ctb3ZlcmxhcFwiKSxuLGkseC5wcmVkaWNhdGUpKS5ib3gubGVuZ3RoPjA7VD1JJiZJLm9mZnNjcmVlbjt2YXIgTj11LnRleHRDaXJjbGVzO2lmKE4pe3ZhciBaPWUudGV4dC5wbGFjZWRTeW1ib2xBcnJheS5nZXQoci5jZW50ZXJKdXN0aWZpZWRUZXh0U3ltYm9sSW5kZXgpLGo9dC5ldmFsdWF0ZVNpemVGb3JGZWF0dXJlKGUudGV4dFNpemVEYXRhLGQsWik7Qz1oLmNvbGxpc2lvbkluZGV4LnBsYWNlQ29sbGlzaW9uQ2lyY2xlcyhOLHAuZ2V0KFwidGV4dC1hbGxvdy1vdmVybGFwXCIpLGEsbixaLGUubGluZVZlcnRleEFycmF5LGUuZ2x5cGhPZmZzZXRBcnJheSxqLGksbyxzLHcseC5wcmVkaWNhdGUpLGc9cC5nZXQoXCJ0ZXh0LWFsbG93LW92ZXJsYXBcIil8fEMuY2lyY2xlcy5sZW5ndGg+MCxUPVQmJkMub2Zmc2NyZWVuO311Lmljb25GZWF0dXJlSW5kZXgmJih6PXUuaWNvbkZlYXR1cmVJbmRleCksdS5pY29uQm94JiYoRT0oUz1oLmNvbGxpc2lvbkluZGV4LnBsYWNlQ29sbGlzaW9uQm94KHUuaWNvbkJveCxwLmdldChcImljb24tYWxsb3ctb3ZlcmxhcFwiKSxuLGkseC5wcmVkaWNhdGUpKS5ib3gubGVuZ3RoPjAsVD1UJiZTLm9mZnNjcmVlbik7dmFyIHE9X3x8MD09PXIubnVtSG9yaXpvbnRhbEdseXBoVmVydGljZXMmJjA9PT1yLm51bVZlcnRpY2FsR2x5cGhWZXJ0aWNlcyxWPWZ8fDA9PT1yLm51bUljb25WZXJ0aWNlcztxfHxWP1Y/cXx8KEU9RSYmZyk6Zz1FJiZnOkU9Zz1FJiZnLGcmJkkmJmguY29sbGlzaW9uSW5kZXguaW5zZXJ0Q29sbGlzaW9uQm94KEkuYm94LHAuZ2V0KFwidGV4dC1pZ25vcmUtcGxhY2VtZW50XCIpLGUuYnVja2V0SW5zdGFuY2VJZCxQLHguSUQpLEUmJlMmJmguY29sbGlzaW9uSW5kZXguaW5zZXJ0Q29sbGlzaW9uQm94KFMuYm94LHAuZ2V0KFwiaWNvbi1pZ25vcmUtcGxhY2VtZW50XCIpLGUuYnVja2V0SW5zdGFuY2VJZCx6LHguSUQpLGcmJkMmJmguY29sbGlzaW9uSW5kZXguaW5zZXJ0Q29sbGlzaW9uQ2lyY2xlcyhDLmNpcmNsZXMscC5nZXQoXCJ0ZXh0LWlnbm9yZS1wbGFjZW1lbnRcIiksZS5idWNrZXRJbnN0YW5jZUlkLFAseC5JRCksaC5wbGFjZW1lbnRzW3IuY3Jvc3NUaWxlSURdPW5ldyBwZShnfHx2LEV8fHksVHx8ZS5qdXN0UmVsb2FkZWQpLGNbci5jcm9zc1RpbGVJRF09ITA7fX07aWYoRSlmb3IodmFyIEk9ZS5nZXRTb3J0ZWRTeW1ib2xJbmRleGVzKHRoaXMudHJhbnNmb3JtLmFuZ2xlKSxDPUkubGVuZ3RoLTE7Qz49MDstLUMpe3ZhciBTPUlbQ107VChlLnN5bWJvbEluc3RhbmNlcy5nZXQoUyksZS5jb2xsaXNpb25BcnJheXNbU10pO31lbHNlIGZvcih2YXIgUD0wO1A8ZS5zeW1ib2xJbnN0YW5jZXMubGVuZ3RoOysrUClUKGUuc3ltYm9sSW5zdGFuY2VzLmdldChQKSxlLmNvbGxpc2lvbkFycmF5c1tQXSk7ZS5qdXN0UmVsb2FkZWQ9ITE7fSxtZS5wcm90b3R5cGUubWFya1VzZWRKdXN0aWZpY2F0aW9uPWZ1bmN0aW9uKGUsaSxvKXt2YXIgcj17bGVmdDpvLmxlZnRKdXN0aWZpZWRUZXh0U3ltYm9sSW5kZXgsY2VudGVyOm8uY2VudGVySnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4LHJpZ2h0Om8ucmlnaHRKdXN0aWZpZWRUZXh0U3ltYm9sSW5kZXh9LGE9clt0LmdldEFuY2hvckp1c3RpZmljYXRpb24oaSldO2Zvcih2YXIgbiBpbiByKXt2YXIgcz1yW25dO3M+PTAmJihlLnRleHQucGxhY2VkU3ltYm9sQXJyYXkuZ2V0KHMpLmNyb3NzVGlsZUlEPWE+PTAmJnMhPT1hPzA6by5jcm9zc1RpbGVJRCk7fX0sbWUucHJvdG90eXBlLmNvbW1pdD1mdW5jdGlvbih0KXt0aGlzLmNvbW1pdFRpbWU9dDt2YXIgZT10aGlzLnByZXZQbGFjZW1lbnQsaT0hMSxvPWUmJjAhPT10aGlzLmZhZGVEdXJhdGlvbj8odGhpcy5jb21taXRUaW1lLWUuY29tbWl0VGltZSkvdGhpcy5mYWRlRHVyYXRpb246MSxyPWU/ZS5vcGFjaXRpZXM6e30sYT1lP2UudmFyaWFibGVPZmZzZXRzOnt9O2Zvcih2YXIgbiBpbiB0aGlzLnBsYWNlbWVudHMpe3ZhciBzPXRoaXMucGxhY2VtZW50c1tuXSxsPXJbbl07bD8odGhpcy5vcGFjaXRpZXNbbl09bmV3IGhlKGwsbyxzLnRleHQscy5pY29uKSxpPWl8fHMudGV4dCE9PWwudGV4dC5wbGFjZWR8fHMuaWNvbiE9PWwuaWNvbi5wbGFjZWQpOih0aGlzLm9wYWNpdGllc1tuXT1uZXcgaGUobnVsbCxvLHMudGV4dCxzLmljb24scy5za2lwRmFkZSksaT1pfHxzLnRleHR8fHMuaWNvbik7fWZvcih2YXIgYyBpbiByKXt2YXIgdT1yW2NdO2lmKCF0aGlzLm9wYWNpdGllc1tjXSl7dmFyIGg9bmV3IGhlKHUsbywhMSwhMSk7aC5pc0hpZGRlbigpfHwodGhpcy5vcGFjaXRpZXNbY109aCxpPWl8fHUudGV4dC5wbGFjZWR8fHUuaWNvbi5wbGFjZWQpO319Zm9yKHZhciBwIGluIGEpdGhpcy52YXJpYWJsZU9mZnNldHNbcF18fCF0aGlzLm9wYWNpdGllc1twXXx8dGhpcy5vcGFjaXRpZXNbcF0uaXNIaWRkZW4oKXx8KHRoaXMudmFyaWFibGVPZmZzZXRzW3BdPWFbcF0pO2k/dGhpcy5sYXN0UGxhY2VtZW50Q2hhbmdlVGltZT10OlwibnVtYmVyXCIhPXR5cGVvZiB0aGlzLmxhc3RQbGFjZW1lbnRDaGFuZ2VUaW1lJiYodGhpcy5sYXN0UGxhY2VtZW50Q2hhbmdlVGltZT1lP2UubGFzdFBsYWNlbWVudENoYW5nZVRpbWU6dCk7fSxtZS5wcm90b3R5cGUudXBkYXRlTGF5ZXJPcGFjaXRpZXM9ZnVuY3Rpb24odCxlKXtmb3IodmFyIGk9e30sbz0wLHI9ZTtvPHIubGVuZ3RoO28rPTEpe3ZhciBhPXJbb10sbj1hLmdldEJ1Y2tldCh0KTtuJiZhLmxhdGVzdEZlYXR1cmVJbmRleCYmdC5pZD09PW4ubGF5ZXJJZHNbMF0mJnRoaXMudXBkYXRlQnVja2V0T3BhY2l0aWVzKG4saSxhLmNvbGxpc2lvbkJveEFycmF5KTt9fSxtZS5wcm90b3R5cGUudXBkYXRlQnVja2V0T3BhY2l0aWVzPWZ1bmN0aW9uKGUsaSxvKXtlLmhhc1RleHREYXRhKCkmJmUudGV4dC5vcGFjaXR5VmVydGV4QXJyYXkuY2xlYXIoKSxlLmhhc0ljb25EYXRhKCkmJmUuaWNvbi5vcGFjaXR5VmVydGV4QXJyYXkuY2xlYXIoKSxlLmhhc0NvbGxpc2lvbkJveERhdGEoKSYmZS5jb2xsaXNpb25Cb3guY29sbGlzaW9uVmVydGV4QXJyYXkuY2xlYXIoKSxlLmhhc0NvbGxpc2lvbkNpcmNsZURhdGEoKSYmZS5jb2xsaXNpb25DaXJjbGUuY29sbGlzaW9uVmVydGV4QXJyYXkuY2xlYXIoKTt2YXIgcj1lLmxheWVyc1swXS5sYXlvdXQsYT1uZXcgaGUobnVsbCwwLCExLCExLCEwKSxuPXIuZ2V0KFwidGV4dC1hbGxvdy1vdmVybGFwXCIpLHM9ci5nZXQoXCJpY29uLWFsbG93LW92ZXJsYXBcIiksbD1yLmdldChcInRleHQtdmFyaWFibGUtYW5jaG9yXCIpLGM9XCJtYXBcIj09PXIuZ2V0KFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIiksdT1cIm1hcFwiPT09ci5nZXQoXCJ0ZXh0LXBpdGNoLWFsaWdubWVudFwiKSxoPW5ldyBoZShudWxsLDAsbiYmKHN8fCFlLmhhc0ljb25EYXRhKCl8fHIuZ2V0KFwiaWNvbi1vcHRpb25hbFwiKSkscyYmKG58fCFlLmhhc1RleHREYXRhKCl8fHIuZ2V0KFwidGV4dC1vcHRpb25hbFwiKSksITApOyFlLmNvbGxpc2lvbkFycmF5cyYmbyYmKGUuaGFzQ29sbGlzaW9uQm94RGF0YSgpfHxlLmhhc0NvbGxpc2lvbkNpcmNsZURhdGEoKSkmJmUuZGVzZXJpYWxpemVDb2xsaXNpb25Cb3hlcyhvKTtmb3IodmFyIHA9MDtwPGUuc3ltYm9sSW5zdGFuY2VzLmxlbmd0aDtwKyspe3ZhciBkPWUuc3ltYm9sSW5zdGFuY2VzLmdldChwKSxfPWQubnVtSG9yaXpvbnRhbEdseXBoVmVydGljZXMsZj1kLm51bVZlcnRpY2FsR2x5cGhWZXJ0aWNlcyxtPWQuY3Jvc3NUaWxlSUQsZz1pW21dLHY9dGhpcy5vcGFjaXRpZXNbbV07Zz92PWE6dnx8KHY9aCx0aGlzLm9wYWNpdGllc1ttXT12KSxpW21dPSEwO3ZhciB5PV8+MHx8Zj4wLHg9ZC5udW1JY29uVmVydGljZXM+MDtpZih5KXtmb3IodmFyIGI9SWUodi50ZXh0KSx3PShfK2YpLzQsRT0wO0U8dztFKyspZS50ZXh0Lm9wYWNpdHlWZXJ0ZXhBcnJheS5lbXBsYWNlQmFjayhiKTt2YXIgVD12LnRleHQuaXNIaWRkZW4oKT8xOjA7W2QucmlnaHRKdXN0aWZpZWRUZXh0U3ltYm9sSW5kZXgsZC5jZW50ZXJKdXN0aWZpZWRUZXh0U3ltYm9sSW5kZXgsZC5sZWZ0SnVzdGlmaWVkVGV4dFN5bWJvbEluZGV4LGQudmVydGljYWxQbGFjZWRUZXh0U3ltYm9sSW5kZXhdLmZvckVhY2goZnVuY3Rpb24odCl7dD49MCYmKGUudGV4dC5wbGFjZWRTeW1ib2xBcnJheS5nZXQodCkuaGlkZGVuPVQpO30pO3ZhciBJPXRoaXMudmFyaWFibGVPZmZzZXRzW2QuY3Jvc3NUaWxlSURdO0kmJnRoaXMubWFya1VzZWRKdXN0aWZpY2F0aW9uKGUsSS5hbmNob3IsZCk7fWlmKHgpe2Zvcih2YXIgQz1JZSh2Lmljb24pLFM9MDtTPGQubnVtSWNvblZlcnRpY2VzLzQ7UysrKWUuaWNvbi5vcGFjaXR5VmVydGV4QXJyYXkuZW1wbGFjZUJhY2soQyk7ZS5pY29uLnBsYWNlZFN5bWJvbEFycmF5LmdldChwKS5oaWRkZW49di5pY29uLmlzSGlkZGVuKCk7fWlmKGUuaGFzQ29sbGlzaW9uQm94RGF0YSgpfHxlLmhhc0NvbGxpc2lvbkNpcmNsZURhdGEoKSl7dmFyIFA9ZS5jb2xsaXNpb25BcnJheXNbcF07aWYoUCl7aWYoUC50ZXh0Qm94KXt2YXIgej1uZXcgdC5Qb2ludCgwLDApLEw9ITA7aWYobCl7dmFyIEQ9dGhpcy52YXJpYWJsZU9mZnNldHNbbV07RD8oej1mZShELmFuY2hvcixELndpZHRoLEQuaGVpZ2h0LEQucmFkaWFsT2Zmc2V0LEQudGV4dEJveFNjYWxlKSxjJiZ6Ll9yb3RhdGUodT90aGlzLnRyYW5zZm9ybS5hbmdsZTotdGhpcy50cmFuc2Zvcm0uYW5nbGUpKTpMPSExO31nZShlLmNvbGxpc2lvbkJveC5jb2xsaXNpb25WZXJ0ZXhBcnJheSx2LnRleHQucGxhY2VkLCFMLHoueCx6LnkpO31QLmljb25Cb3gmJmdlKGUuY29sbGlzaW9uQm94LmNvbGxpc2lvblZlcnRleEFycmF5LHYuaWNvbi5wbGFjZWQsITEpO3ZhciBNPVAudGV4dENpcmNsZXM7aWYoTSYmZS5oYXNDb2xsaXNpb25DaXJjbGVEYXRhKCkpZm9yKHZhciBSPTA7UjxNLmxlbmd0aDtSKz01KXt2YXIgQT1nfHwwPT09TVtSKzRdO2dlKGUuY29sbGlzaW9uQ2lyY2xlLmNvbGxpc2lvblZlcnRleEFycmF5LHYudGV4dC5wbGFjZWQsQSk7fX19fWUuc29ydEZlYXR1cmVzKHRoaXMudHJhbnNmb3JtLmFuZ2xlKSx0aGlzLnJldGFpbmVkUXVlcnlEYXRhW2UuYnVja2V0SW5zdGFuY2VJZF0mJih0aGlzLnJldGFpbmVkUXVlcnlEYXRhW2UuYnVja2V0SW5zdGFuY2VJZF0uZmVhdHVyZVNvcnRPcmRlcj1lLmZlYXR1cmVTb3J0T3JkZXIpLGUuaGFzVGV4dERhdGEoKSYmZS50ZXh0Lm9wYWNpdHlWZXJ0ZXhCdWZmZXImJmUudGV4dC5vcGFjaXR5VmVydGV4QnVmZmVyLnVwZGF0ZURhdGEoZS50ZXh0Lm9wYWNpdHlWZXJ0ZXhBcnJheSksZS5oYXNJY29uRGF0YSgpJiZlLmljb24ub3BhY2l0eVZlcnRleEJ1ZmZlciYmZS5pY29uLm9wYWNpdHlWZXJ0ZXhCdWZmZXIudXBkYXRlRGF0YShlLmljb24ub3BhY2l0eVZlcnRleEFycmF5KSxlLmhhc0NvbGxpc2lvbkJveERhdGEoKSYmZS5jb2xsaXNpb25Cb3guY29sbGlzaW9uVmVydGV4QnVmZmVyJiZlLmNvbGxpc2lvbkJveC5jb2xsaXNpb25WZXJ0ZXhCdWZmZXIudXBkYXRlRGF0YShlLmNvbGxpc2lvbkJveC5jb2xsaXNpb25WZXJ0ZXhBcnJheSksZS5oYXNDb2xsaXNpb25DaXJjbGVEYXRhKCkmJmUuY29sbGlzaW9uQ2lyY2xlLmNvbGxpc2lvblZlcnRleEJ1ZmZlciYmZS5jb2xsaXNpb25DaXJjbGUuY29sbGlzaW9uVmVydGV4QnVmZmVyLnVwZGF0ZURhdGEoZS5jb2xsaXNpb25DaXJjbGUuY29sbGlzaW9uVmVydGV4QXJyYXkpO30sbWUucHJvdG90eXBlLnN5bWJvbEZhZGVDaGFuZ2U9ZnVuY3Rpb24odCl7cmV0dXJuIDA9PT10aGlzLmZhZGVEdXJhdGlvbj8xOih0LXRoaXMuY29tbWl0VGltZSkvdGhpcy5mYWRlRHVyYXRpb259LG1lLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9ucz1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zdGFsZXx8dC10aGlzLmxhc3RQbGFjZW1lbnRDaGFuZ2VUaW1lPHRoaXMuZmFkZUR1cmF0aW9ufSxtZS5wcm90b3R5cGUuc3RpbGxSZWNlbnQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuY29tbWl0VGltZSt0aGlzLmZhZGVEdXJhdGlvbj50fSxtZS5wcm90b3R5cGUuc2V0U3RhbGU9ZnVuY3Rpb24oKXt0aGlzLnN0YWxlPSEwO307dmFyIHZlPU1hdGgucG93KDIsMjUpLHllPU1hdGgucG93KDIsMjQpLHhlPU1hdGgucG93KDIsMTcpLGJlPU1hdGgucG93KDIsMTYpLHdlPU1hdGgucG93KDIsOSksRWU9TWF0aC5wb3coMiw4KSxUZT1NYXRoLnBvdygyLDEpO2Z1bmN0aW9uIEllKHQpe2lmKDA9PT10Lm9wYWNpdHkmJiF0LnBsYWNlZClyZXR1cm4gMDtpZigxPT09dC5vcGFjaXR5JiZ0LnBsYWNlZClyZXR1cm4gNDI5NDk2NzI5NTt2YXIgZT10LnBsYWNlZD8xOjAsaT1NYXRoLmZsb29yKDEyNyp0Lm9wYWNpdHkpO3JldHVybiBpKnZlK2UqeWUraSp4ZStlKmJlK2kqd2UrZSpFZStpKlRlK2V9dmFyIENlPWZ1bmN0aW9uKCl7dGhpcy5fY3VycmVudFRpbGVJbmRleD0wLHRoaXMuX3NlZW5Dcm9zc1RpbGVJRHM9e307fTtDZS5wcm90b3R5cGUuY29udGludWVQbGFjZW1lbnQ9ZnVuY3Rpb24odCxlLGksbyxyKXtmb3IoO3RoaXMuX2N1cnJlbnRUaWxlSW5kZXg8dC5sZW5ndGg7KXt2YXIgYT10W3RoaXMuX2N1cnJlbnRUaWxlSW5kZXhdO2lmKGUucGxhY2VMYXllclRpbGUobyxhLGksdGhpcy5fc2VlbkNyb3NzVGlsZUlEcyksdGhpcy5fY3VycmVudFRpbGVJbmRleCsrLHIoKSlyZXR1cm4gITB9fTt2YXIgU2U9ZnVuY3Rpb24odCxlLGksbyxyLGEsbil7dGhpcy5wbGFjZW1lbnQ9bmV3IG1lKHQscixhLG4pLHRoaXMuX2N1cnJlbnRQbGFjZW1lbnRJbmRleD1lLmxlbmd0aC0xLHRoaXMuX2ZvcmNlRnVsbFBsYWNlbWVudD1pLHRoaXMuX3Nob3dDb2xsaXNpb25Cb3hlcz1vLHRoaXMuX2RvbmU9ITE7fTtTZS5wcm90b3R5cGUuaXNEb25lPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2RvbmV9LFNlLnByb3RvdHlwZS5jb250aW51ZVBsYWNlbWVudD1mdW5jdGlvbihlLGksbyl7Zm9yKHZhciByPXRoaXMsYT10LmJyb3dzZXIubm93KCksbj1mdW5jdGlvbigpe3ZhciBlPXQuYnJvd3Nlci5ub3coKS1hO3JldHVybiAhci5fZm9yY2VGdWxsUGxhY2VtZW50JiZlPjJ9O3RoaXMuX2N1cnJlbnRQbGFjZW1lbnRJbmRleD49MDspe3ZhciBzPWlbZVt0aGlzLl9jdXJyZW50UGxhY2VtZW50SW5kZXhdXSxsPXRoaXMucGxhY2VtZW50LmNvbGxpc2lvbkluZGV4LnRyYW5zZm9ybS56b29tO2lmKFwic3ltYm9sXCI9PT1zLnR5cGUmJighcy5taW56b29tfHxzLm1pbnpvb208PWwpJiYoIXMubWF4em9vbXx8cy5tYXh6b29tPmwpKXtpZih0aGlzLl9pblByb2dyZXNzTGF5ZXJ8fCh0aGlzLl9pblByb2dyZXNzTGF5ZXI9bmV3IENlKSx0aGlzLl9pblByb2dyZXNzTGF5ZXIuY29udGludWVQbGFjZW1lbnQob1tzLnNvdXJjZV0sdGhpcy5wbGFjZW1lbnQsdGhpcy5fc2hvd0NvbGxpc2lvbkJveGVzLHMsbikpcmV0dXJuO2RlbGV0ZSB0aGlzLl9pblByb2dyZXNzTGF5ZXI7fXRoaXMuX2N1cnJlbnRQbGFjZW1lbnRJbmRleC0tO310aGlzLl9kb25lPSEwO30sU2UucHJvdG90eXBlLmNvbW1pdD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5wbGFjZW1lbnQuY29tbWl0KHQpLHRoaXMucGxhY2VtZW50fTt2YXIgUGU9NTEyL3QuRVhURU5ULzIsemU9ZnVuY3Rpb24odCxlLGkpe3RoaXMudGlsZUlEPXQsdGhpcy5pbmRleGVkU3ltYm9sSW5zdGFuY2VzPXt9LHRoaXMuYnVja2V0SW5zdGFuY2VJZD1pO2Zvcih2YXIgbz0wO288ZS5sZW5ndGg7bysrKXt2YXIgcj1lLmdldChvKSxhPXIua2V5O3RoaXMuaW5kZXhlZFN5bWJvbEluc3RhbmNlc1thXXx8KHRoaXMuaW5kZXhlZFN5bWJvbEluc3RhbmNlc1thXT1bXSksdGhpcy5pbmRleGVkU3ltYm9sSW5zdGFuY2VzW2FdLnB1c2goe2Nyb3NzVGlsZUlEOnIuY3Jvc3NUaWxlSUQsY29vcmQ6dGhpcy5nZXRTY2FsZWRDb29yZGluYXRlcyhyLHQpfSk7fX07emUucHJvdG90eXBlLmdldFNjYWxlZENvb3JkaW5hdGVzPWZ1bmN0aW9uKGUsaSl7dmFyIG89aS5jYW5vbmljYWwuei10aGlzLnRpbGVJRC5jYW5vbmljYWwueixyPVBlL01hdGgucG93KDIsbyk7cmV0dXJuIHt4Ok1hdGguZmxvb3IoKGkuY2Fub25pY2FsLngqdC5FWFRFTlQrZS5hbmNob3JYKSpyKSx5Ok1hdGguZmxvb3IoKGkuY2Fub25pY2FsLnkqdC5FWFRFTlQrZS5hbmNob3JZKSpyKX19LHplLnByb3RvdHlwZS5maW5kTWF0Y2hlcz1mdW5jdGlvbih0LGUsaSl7Zm9yKHZhciBvPXRoaXMudGlsZUlELmNhbm9uaWNhbC56PGUuY2Fub25pY2FsLno/MTpNYXRoLnBvdygyLHRoaXMudGlsZUlELmNhbm9uaWNhbC56LWUuY2Fub25pY2FsLnopLHI9MDtyPHQubGVuZ3RoO3IrKyl7dmFyIGE9dC5nZXQocik7aWYoIWEuY3Jvc3NUaWxlSUQpe3ZhciBuPXRoaXMuaW5kZXhlZFN5bWJvbEluc3RhbmNlc1thLmtleV07aWYobilmb3IodmFyIHM9dGhpcy5nZXRTY2FsZWRDb29yZGluYXRlcyhhLGUpLGw9MCxjPW47bDxjLmxlbmd0aDtsKz0xKXt2YXIgdT1jW2xdO2lmKE1hdGguYWJzKHUuY29vcmQueC1zLngpPD1vJiZNYXRoLmFicyh1LmNvb3JkLnktcy55KTw9byYmIWlbdS5jcm9zc1RpbGVJRF0pe2lbdS5jcm9zc1RpbGVJRF09ITAsYS5jcm9zc1RpbGVJRD11LmNyb3NzVGlsZUlEO2JyZWFrfX19fX07dmFyIExlPWZ1bmN0aW9uKCl7dGhpcy5tYXhDcm9zc1RpbGVJRD0wO307TGUucHJvdG90eXBlLmdlbmVyYXRlPWZ1bmN0aW9uKCl7cmV0dXJuICsrdGhpcy5tYXhDcm9zc1RpbGVJRH07dmFyIERlPWZ1bmN0aW9uKCl7dGhpcy5pbmRleGVzPXt9LHRoaXMudXNlZENyb3NzVGlsZUlEcz17fSx0aGlzLmxuZz0wO307RGUucHJvdG90eXBlLmhhbmRsZVdyYXBKdW1wPWZ1bmN0aW9uKHQpe3ZhciBlPU1hdGgucm91bmQoKHQtdGhpcy5sbmcpLzM2MCk7aWYoMCE9PWUpZm9yKHZhciBpIGluIHRoaXMuaW5kZXhlcyl7dmFyIG89dGhpcy5pbmRleGVzW2ldLHI9e307Zm9yKHZhciBhIGluIG8pe3ZhciBuPW9bYV07bi50aWxlSUQ9bi50aWxlSUQudW53cmFwVG8obi50aWxlSUQud3JhcCtlKSxyW24udGlsZUlELmtleV09bjt9dGhpcy5pbmRleGVzW2ldPXI7fXRoaXMubG5nPXQ7fSxEZS5wcm90b3R5cGUuYWRkQnVja2V0PWZ1bmN0aW9uKHQsZSxpKXtpZih0aGlzLmluZGV4ZXNbdC5vdmVyc2NhbGVkWl0mJnRoaXMuaW5kZXhlc1t0Lm92ZXJzY2FsZWRaXVt0LmtleV0pe2lmKHRoaXMuaW5kZXhlc1t0Lm92ZXJzY2FsZWRaXVt0LmtleV0uYnVja2V0SW5zdGFuY2VJZD09PWUuYnVja2V0SW5zdGFuY2VJZClyZXR1cm4gITE7dGhpcy5yZW1vdmVCdWNrZXRDcm9zc1RpbGVJRHModC5vdmVyc2NhbGVkWix0aGlzLmluZGV4ZXNbdC5vdmVyc2NhbGVkWl1bdC5rZXldKTt9Zm9yKHZhciBvPTA7bzxlLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7bysrKXtlLnN5bWJvbEluc3RhbmNlcy5nZXQobykuY3Jvc3NUaWxlSUQ9MDt9dGhpcy51c2VkQ3Jvc3NUaWxlSURzW3Qub3ZlcnNjYWxlZFpdfHwodGhpcy51c2VkQ3Jvc3NUaWxlSURzW3Qub3ZlcnNjYWxlZFpdPXt9KTt2YXIgcj10aGlzLnVzZWRDcm9zc1RpbGVJRHNbdC5vdmVyc2NhbGVkWl07Zm9yKHZhciBhIGluIHRoaXMuaW5kZXhlcyl7dmFyIG49dGhpcy5pbmRleGVzW2FdO2lmKE51bWJlcihhKT50Lm92ZXJzY2FsZWRaKWZvcih2YXIgcyBpbiBuKXt2YXIgbD1uW3NdO2wudGlsZUlELmlzQ2hpbGRPZih0KSYmbC5maW5kTWF0Y2hlcyhlLnN5bWJvbEluc3RhbmNlcyx0LHIpO31lbHNle3ZhciBjPW5bdC5zY2FsZWRUbyhOdW1iZXIoYSkpLmtleV07YyYmYy5maW5kTWF0Y2hlcyhlLnN5bWJvbEluc3RhbmNlcyx0LHIpO319Zm9yKHZhciB1PTA7dTxlLnN5bWJvbEluc3RhbmNlcy5sZW5ndGg7dSsrKXt2YXIgaD1lLnN5bWJvbEluc3RhbmNlcy5nZXQodSk7aC5jcm9zc1RpbGVJRHx8KGguY3Jvc3NUaWxlSUQ9aS5nZW5lcmF0ZSgpLHJbaC5jcm9zc1RpbGVJRF09ITApO31yZXR1cm4gdm9pZCAwPT09dGhpcy5pbmRleGVzW3Qub3ZlcnNjYWxlZFpdJiYodGhpcy5pbmRleGVzW3Qub3ZlcnNjYWxlZFpdPXt9KSx0aGlzLmluZGV4ZXNbdC5vdmVyc2NhbGVkWl1bdC5rZXldPW5ldyB6ZSh0LGUuc3ltYm9sSW5zdGFuY2VzLGUuYnVja2V0SW5zdGFuY2VJZCksITB9LERlLnByb3RvdHlwZS5yZW1vdmVCdWNrZXRDcm9zc1RpbGVJRHM9ZnVuY3Rpb24odCxlKXtmb3IodmFyIGkgaW4gZS5pbmRleGVkU3ltYm9sSW5zdGFuY2VzKWZvcih2YXIgbz0wLHI9ZS5pbmRleGVkU3ltYm9sSW5zdGFuY2VzW2ldO288ci5sZW5ndGg7bys9MSl7dmFyIGE9cltvXTtkZWxldGUgdGhpcy51c2VkQ3Jvc3NUaWxlSURzW3RdW2EuY3Jvc3NUaWxlSURdO319LERlLnByb3RvdHlwZS5yZW1vdmVTdGFsZUJ1Y2tldHM9ZnVuY3Rpb24odCl7dmFyIGU9ITE7Zm9yKHZhciBpIGluIHRoaXMuaW5kZXhlcyl7dmFyIG89dGhpcy5pbmRleGVzW2ldO2Zvcih2YXIgciBpbiBvKXRbb1tyXS5idWNrZXRJbnN0YW5jZUlkXXx8KHRoaXMucmVtb3ZlQnVja2V0Q3Jvc3NUaWxlSURzKGksb1tyXSksZGVsZXRlIG9bcl0sZT0hMCk7fXJldHVybiBlfTt2YXIgTWU9ZnVuY3Rpb24oKXt0aGlzLmxheWVySW5kZXhlcz17fSx0aGlzLmNyb3NzVGlsZUlEcz1uZXcgTGUsdGhpcy5tYXhCdWNrZXRJbnN0YW5jZUlkPTAsdGhpcy5idWNrZXRzSW5DdXJyZW50UGxhY2VtZW50PXt9O307TWUucHJvdG90eXBlLmFkZExheWVyPWZ1bmN0aW9uKHQsZSxpKXt2YXIgbz10aGlzLmxheWVySW5kZXhlc1t0LmlkXTt2b2lkIDA9PT1vJiYobz10aGlzLmxheWVySW5kZXhlc1t0LmlkXT1uZXcgRGUpO3ZhciByPSExLGE9e307by5oYW5kbGVXcmFwSnVtcChpKTtmb3IodmFyIG49MCxzPWU7bjxzLmxlbmd0aDtuKz0xKXt2YXIgbD1zW25dLGM9bC5nZXRCdWNrZXQodCk7YyYmdC5pZD09PWMubGF5ZXJJZHNbMF0mJihjLmJ1Y2tldEluc3RhbmNlSWR8fChjLmJ1Y2tldEluc3RhbmNlSWQ9Kyt0aGlzLm1heEJ1Y2tldEluc3RhbmNlSWQpLG8uYWRkQnVja2V0KGwudGlsZUlELGMsdGhpcy5jcm9zc1RpbGVJRHMpJiYocj0hMCksYVtjLmJ1Y2tldEluc3RhbmNlSWRdPSEwKTt9cmV0dXJuIG8ucmVtb3ZlU3RhbGVCdWNrZXRzKGEpJiYocj0hMCkscn0sTWUucHJvdG90eXBlLnBydW5lVW51c2VkTGF5ZXJzPWZ1bmN0aW9uKHQpe3ZhciBlPXt9O2Zvcih2YXIgaSBpbiB0LmZvckVhY2goZnVuY3Rpb24odCl7ZVt0XT0hMDt9KSx0aGlzLmxheWVySW5kZXhlcyllW2ldfHxkZWxldGUgdGhpcy5sYXllckluZGV4ZXNbaV07fTt2YXIgUmU9ZnVuY3Rpb24oZSxpKXtyZXR1cm4gdC5lbWl0VmFsaWRhdGlvbkVycm9ycyhlLGkmJmkuZmlsdGVyKGZ1bmN0aW9uKHQpe3JldHVybiBcInNvdXJjZS5jYW52YXNcIiE9PXQuaWRlbnRpZmllcn0pKX0sQWU9dC5waWNrKEZ0LFtcImFkZExheWVyXCIsXCJyZW1vdmVMYXllclwiLFwic2V0UGFpbnRQcm9wZXJ0eVwiLFwic2V0TGF5b3V0UHJvcGVydHlcIixcInNldEZpbHRlclwiLFwiYWRkU291cmNlXCIsXCJyZW1vdmVTb3VyY2VcIixcInNldExheWVyWm9vbVJhbmdlXCIsXCJzZXRMaWdodFwiLFwic2V0VHJhbnNpdGlvblwiLFwic2V0R2VvSlNPTlNvdXJjZURhdGFcIl0pLGtlPXQucGljayhGdCxbXCJzZXRDZW50ZXJcIixcInNldFpvb21cIixcInNldEJlYXJpbmdcIixcInNldFBpdGNoXCJdKSxCZT1mdW5jdGlvbihlKXtmdW5jdGlvbiBpKG8scil7dmFyIGE9dGhpczt2b2lkIDA9PT1yJiYocj17fSksZS5jYWxsKHRoaXMpLHRoaXMubWFwPW8sdGhpcy5kaXNwYXRjaGVyPW5ldyBFKChBdHx8KEF0PW5ldyBSdCksQXQpLHRoaXMpLHRoaXMuaW1hZ2VNYW5hZ2VyPW5ldyBwLHRoaXMuaW1hZ2VNYW5hZ2VyLnNldEV2ZW50ZWRQYXJlbnQodGhpcyksdGhpcy5nbHlwaE1hbmFnZXI9bmV3IHYoby5fcmVxdWVzdE1hbmFnZXIsci5sb2NhbElkZW9ncmFwaEZvbnRGYW1pbHkpLHRoaXMubGluZUF0bGFzPW5ldyB3KDI1Niw1MTIpLHRoaXMuY3Jvc3NUaWxlU3ltYm9sSW5kZXg9bmV3IE1lLHRoaXMuX2xheWVycz17fSx0aGlzLl9vcmRlcj1bXSx0aGlzLnNvdXJjZUNhY2hlcz17fSx0aGlzLnpvb21IaXN0b3J5PW5ldyB0Llpvb21IaXN0b3J5LHRoaXMuX2xvYWRlZD0hMSx0aGlzLl9yZXNldFVwZGF0ZXMoKSx0aGlzLmRpc3BhdGNoZXIuYnJvYWRjYXN0KFwic2V0UmVmZXJyZXJcIix0LmdldFJlZmVycmVyKCkpO3ZhciBuPXRoaXM7dGhpcy5fcnRsVGV4dFBsdWdpbkNhbGxiYWNrPWkucmVnaXN0ZXJGb3JQbHVnaW5BdmFpbGFiaWxpdHkoZnVuY3Rpb24odCl7Zm9yKHZhciBlIGluIG4uZGlzcGF0Y2hlci5icm9hZGNhc3QoXCJsb2FkUlRMVGV4dFBsdWdpblwiLHQucGx1Z2luVVJMLHQuY29tcGxldGlvbkNhbGxiYWNrKSxuLnNvdXJjZUNhY2hlcyluLnNvdXJjZUNhY2hlc1tlXS5yZWxvYWQoKTt9KSx0aGlzLm9uKFwiZGF0YVwiLGZ1bmN0aW9uKHQpe2lmKFwic291cmNlXCI9PT10LmRhdGFUeXBlJiZcIm1ldGFkYXRhXCI9PT10LnNvdXJjZURhdGFUeXBlKXt2YXIgZT1hLnNvdXJjZUNhY2hlc1t0LnNvdXJjZUlkXTtpZihlKXt2YXIgaT1lLmdldFNvdXJjZSgpO2lmKGkmJmkudmVjdG9yTGF5ZXJJZHMpZm9yKHZhciBvIGluIGEuX2xheWVycyl7dmFyIHI9YS5fbGF5ZXJzW29dO3Iuc291cmNlPT09aS5pZCYmYS5fdmFsaWRhdGVMYXllcihyKTt9fX19KTt9cmV0dXJuIGUmJihpLl9fcHJvdG9fXz1lKSxpLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxpLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1pLGkucHJvdG90eXBlLmxvYWRVUkw9ZnVuY3Rpb24oZSxpKXt2YXIgbz10aGlzO3ZvaWQgMD09PWkmJihpPXt9KSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhbG9hZGluZ1wiLHtkYXRhVHlwZTpcInN0eWxlXCJ9KSk7dmFyIHI9XCJib29sZWFuXCI9PXR5cGVvZiBpLnZhbGlkYXRlP2kudmFsaWRhdGU6IXQuaXNNYXBib3hVUkwoZSk7ZT10aGlzLm1hcC5fcmVxdWVzdE1hbmFnZXIubm9ybWFsaXplU3R5bGVVUkwoZSxpLmFjY2Vzc1Rva2VuKTt2YXIgYT10aGlzLm1hcC5fcmVxdWVzdE1hbmFnZXIudHJhbnNmb3JtUmVxdWVzdChlLHQuUmVzb3VyY2VUeXBlLlN0eWxlKTt0aGlzLl9yZXF1ZXN0PXQuZ2V0SlNPTihhLGZ1bmN0aW9uKGUsaSl7by5fcmVxdWVzdD1udWxsLGU/by5maXJlKG5ldyB0LkVycm9yRXZlbnQoZSkpOmkmJm8uX2xvYWQoaSxyKTt9KTt9LGkucHJvdG90eXBlLmxvYWRKU09OPWZ1bmN0aW9uKGUsaSl7dmFyIG89dGhpczt2b2lkIDA9PT1pJiYoaT17fSksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YWxvYWRpbmdcIix7ZGF0YVR5cGU6XCJzdHlsZVwifSkpLHRoaXMuX3JlcXVlc3Q9dC5icm93c2VyLmZyYW1lKGZ1bmN0aW9uKCl7by5fcmVxdWVzdD1udWxsLG8uX2xvYWQoZSwhMSE9PWkudmFsaWRhdGUpO30pO30saS5wcm90b3R5cGUuX2xvYWQ9ZnVuY3Rpb24oZSxpKXt2YXIgbz10aGlzO2lmKCFpfHwhUmUodGhpcyx0LnZhbGlkYXRlU3R5bGUoZSkpKXtmb3IodmFyIHIgaW4gdGhpcy5fbG9hZGVkPSEwLHRoaXMuc3R5bGVzaGVldD1lLGUuc291cmNlcyl0aGlzLmFkZFNvdXJjZShyLGUuc291cmNlc1tyXSx7dmFsaWRhdGU6ITF9KTtlLnNwcml0ZT90aGlzLl9zcHJpdGVSZXF1ZXN0PWZ1bmN0aW9uKGUsaSxvKXt2YXIgcixhLG4scz10LmJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbz4xP1wiQDJ4XCI6XCJcIixsPXQuZ2V0SlNPTihpLnRyYW5zZm9ybVJlcXVlc3QoaS5ub3JtYWxpemVTcHJpdGVVUkwoZSxzLFwiLmpzb25cIiksdC5SZXNvdXJjZVR5cGUuU3ByaXRlSlNPTiksZnVuY3Rpb24odCxlKXtsPW51bGwsbnx8KG49dCxyPWUsdSgpKTt9KSxjPXQuZ2V0SW1hZ2UoaS50cmFuc2Zvcm1SZXF1ZXN0KGkubm9ybWFsaXplU3ByaXRlVVJMKGUscyxcIi5wbmdcIiksdC5SZXNvdXJjZVR5cGUuU3ByaXRlSW1hZ2UpLGZ1bmN0aW9uKHQsZSl7Yz1udWxsLG58fChuPXQsYT1lLHUoKSk7fSk7ZnVuY3Rpb24gdSgpe2lmKG4pbyhuKTtlbHNlIGlmKHImJmEpe3ZhciBlPXQuYnJvd3Nlci5nZXRJbWFnZURhdGEoYSksaT17fTtmb3IodmFyIHMgaW4gcil7dmFyIGw9cltzXSxjPWwud2lkdGgsdT1sLmhlaWdodCxoPWwueCxwPWwueSxkPWwuc2RmLF89bC5waXhlbFJhdGlvLGY9bmV3IHQuUkdCQUltYWdlKHt3aWR0aDpjLGhlaWdodDp1fSk7dC5SR0JBSW1hZ2UuY29weShlLGYse3g6aCx5OnB9LHt4OjAseTowfSx7d2lkdGg6YyxoZWlnaHQ6dX0pLGlbc109e2RhdGE6ZixwaXhlbFJhdGlvOl8sc2RmOmR9O31vKG51bGwsaSk7fX1yZXR1cm4ge2NhbmNlbDpmdW5jdGlvbigpe2wmJihsLmNhbmNlbCgpLGw9bnVsbCksYyYmKGMuY2FuY2VsKCksYz1udWxsKTt9fX0oZS5zcHJpdGUsdGhpcy5tYXAuX3JlcXVlc3RNYW5hZ2VyLGZ1bmN0aW9uKGUsaSl7aWYoby5fc3ByaXRlUmVxdWVzdD1udWxsLGUpby5maXJlKG5ldyB0LkVycm9yRXZlbnQoZSkpO2Vsc2UgaWYoaSlmb3IodmFyIHIgaW4gaSlvLmltYWdlTWFuYWdlci5hZGRJbWFnZShyLGlbcl0pO28uaW1hZ2VNYW5hZ2VyLnNldExvYWRlZCghMCksby5maXJlKG5ldyB0LkV2ZW50KFwiZGF0YVwiLHtkYXRhVHlwZTpcInN0eWxlXCJ9KSk7fSk6dGhpcy5pbWFnZU1hbmFnZXIuc2V0TG9hZGVkKCEwKSx0aGlzLmdseXBoTWFuYWdlci5zZXRVUkwoZS5nbHlwaHMpO3ZhciBhPU90KHRoaXMuc3R5bGVzaGVldC5sYXllcnMpO3RoaXMuX29yZGVyPWEubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkfSksdGhpcy5fbGF5ZXJzPXt9O2Zvcih2YXIgbj0wLHM9YTtuPHMubGVuZ3RoO24rPTEpe3ZhciBsPXNbbl07KGw9dC5jcmVhdGVTdHlsZUxheWVyKGwpKS5zZXRFdmVudGVkUGFyZW50KHRoaXMse2xheWVyOntpZDpsLmlkfX0pLHRoaXMuX2xheWVyc1tsLmlkXT1sO310aGlzLmRpc3BhdGNoZXIuYnJvYWRjYXN0KFwic2V0TGF5ZXJzXCIsdGhpcy5fc2VyaWFsaXplTGF5ZXJzKHRoaXMuX29yZGVyKSksdGhpcy5saWdodD1uZXcgYih0aGlzLnN0eWxlc2hlZXQubGlnaHQpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIix7ZGF0YVR5cGU6XCJzdHlsZVwifSkpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcInN0eWxlLmxvYWRcIikpO319LGkucHJvdG90eXBlLl92YWxpZGF0ZUxheWVyPWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXMuc291cmNlQ2FjaGVzW2Uuc291cmNlXTtpZihpKXt2YXIgbz1lLnNvdXJjZUxheWVyO2lmKG8pe3ZhciByPWkuZ2V0U291cmNlKCk7KFwiZ2VvanNvblwiPT09ci50eXBlfHxyLnZlY3RvckxheWVySWRzJiYtMT09PXIudmVjdG9yTGF5ZXJJZHMuaW5kZXhPZihvKSkmJnRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcignU291cmNlIGxheWVyIFwiJytvKydcIiBkb2VzIG5vdCBleGlzdCBvbiBzb3VyY2UgXCInK3IuaWQrJ1wiIGFzIHNwZWNpZmllZCBieSBzdHlsZSBsYXllciBcIicrZS5pZCsnXCInKSkpO319fSxpLnByb3RvdHlwZS5sb2FkZWQ9ZnVuY3Rpb24oKXtpZighdGhpcy5fbG9hZGVkKXJldHVybiAhMTtpZihPYmplY3Qua2V5cyh0aGlzLl91cGRhdGVkU291cmNlcykubGVuZ3RoKXJldHVybiAhMTtmb3IodmFyIHQgaW4gdGhpcy5zb3VyY2VDYWNoZXMpaWYoIXRoaXMuc291cmNlQ2FjaGVzW3RdLmxvYWRlZCgpKXJldHVybiAhMTtyZXR1cm4gISF0aGlzLmltYWdlTWFuYWdlci5pc0xvYWRlZCgpfSxpLnByb3RvdHlwZS5fc2VyaWFsaXplTGF5ZXJzPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT1bXSxpPTAsbz10O2k8by5sZW5ndGg7aSs9MSl7dmFyIHI9b1tpXSxhPXRoaXMuX2xheWVyc1tyXTtcImN1c3RvbVwiIT09YS50eXBlJiZlLnB1c2goYS5zZXJpYWxpemUoKSk7fXJldHVybiBlfSxpLnByb3RvdHlwZS5oYXNUcmFuc2l0aW9ucz1mdW5jdGlvbigpe2lmKHRoaXMubGlnaHQmJnRoaXMubGlnaHQuaGFzVHJhbnNpdGlvbigpKXJldHVybiAhMDtmb3IodmFyIHQgaW4gdGhpcy5zb3VyY2VDYWNoZXMpaWYodGhpcy5zb3VyY2VDYWNoZXNbdF0uaGFzVHJhbnNpdGlvbigpKXJldHVybiAhMDtmb3IodmFyIGUgaW4gdGhpcy5fbGF5ZXJzKWlmKHRoaXMuX2xheWVyc1tlXS5oYXNUcmFuc2l0aW9uKCkpcmV0dXJuICEwO3JldHVybiAhMX0saS5wcm90b3R5cGUuX2NoZWNrTG9hZGVkPWZ1bmN0aW9uKCl7aWYoIXRoaXMuX2xvYWRlZCl0aHJvdyBuZXcgRXJyb3IoXCJTdHlsZSBpcyBub3QgZG9uZSBsb2FkaW5nXCIpfSxpLnByb3RvdHlwZS51cGRhdGU9ZnVuY3Rpb24oZSl7aWYodGhpcy5fbG9hZGVkKXt2YXIgaT10aGlzLl9jaGFuZ2VkO2lmKHRoaXMuX2NoYW5nZWQpe3ZhciBvPU9iamVjdC5rZXlzKHRoaXMuX3VwZGF0ZWRMYXllcnMpLHI9T2JqZWN0LmtleXModGhpcy5fcmVtb3ZlZExheWVycyk7Zm9yKHZhciBhIGluKG8ubGVuZ3RofHxyLmxlbmd0aCkmJnRoaXMuX3VwZGF0ZVdvcmtlckxheWVycyhvLHIpLHRoaXMuX3VwZGF0ZWRTb3VyY2VzKXt2YXIgbj10aGlzLl91cGRhdGVkU291cmNlc1thXTtcInJlbG9hZFwiPT09bj90aGlzLl9yZWxvYWRTb3VyY2UoYSk6XCJjbGVhclwiPT09biYmdGhpcy5fY2xlYXJTb3VyY2UoYSk7fWZvcih2YXIgcyBpbiB0aGlzLl91cGRhdGVkUGFpbnRQcm9wcyl0aGlzLl9sYXllcnNbc10udXBkYXRlVHJhbnNpdGlvbnMoZSk7dGhpcy5saWdodC51cGRhdGVUcmFuc2l0aW9ucyhlKSx0aGlzLl9yZXNldFVwZGF0ZXMoKTt9Zm9yKHZhciBsIGluIHRoaXMuc291cmNlQ2FjaGVzKXRoaXMuc291cmNlQ2FjaGVzW2xdLnVzZWQ9ITE7Zm9yKHZhciBjPTAsdT10aGlzLl9vcmRlcjtjPHUubGVuZ3RoO2MrPTEpe3ZhciBoPXVbY10scD10aGlzLl9sYXllcnNbaF07cC5yZWNhbGN1bGF0ZShlKSwhcC5pc0hpZGRlbihlLnpvb20pJiZwLnNvdXJjZSYmKHRoaXMuc291cmNlQ2FjaGVzW3Auc291cmNlXS51c2VkPSEwKTt9dGhpcy5saWdodC5yZWNhbGN1bGF0ZShlKSx0aGlzLno9ZS56b29tLGkmJnRoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIix7ZGF0YVR5cGU6XCJzdHlsZVwifSkpO319LGkucHJvdG90eXBlLl91cGRhdGVXb3JrZXJMYXllcnM9ZnVuY3Rpb24odCxlKXt0aGlzLmRpc3BhdGNoZXIuYnJvYWRjYXN0KFwidXBkYXRlTGF5ZXJzXCIse2xheWVyczp0aGlzLl9zZXJpYWxpemVMYXllcnModCkscmVtb3ZlZElkczplfSk7fSxpLnByb3RvdHlwZS5fcmVzZXRVcGRhdGVzPWZ1bmN0aW9uKCl7dGhpcy5fY2hhbmdlZD0hMSx0aGlzLl91cGRhdGVkTGF5ZXJzPXt9LHRoaXMuX3JlbW92ZWRMYXllcnM9e30sdGhpcy5fdXBkYXRlZFNvdXJjZXM9e30sdGhpcy5fdXBkYXRlZFBhaW50UHJvcHM9e307fSxpLnByb3RvdHlwZS5zZXRTdGF0ZT1mdW5jdGlvbihlKXt2YXIgaT10aGlzO2lmKHRoaXMuX2NoZWNrTG9hZGVkKCksUmUodGhpcyx0LnZhbGlkYXRlU3R5bGUoZSkpKXJldHVybiAhMTsoZT10LmNsb25lJDEoZSkpLmxheWVycz1PdChlLmxheWVycyk7dmFyIG89V3QodGhpcy5zZXJpYWxpemUoKSxlKS5maWx0ZXIoZnVuY3Rpb24odCl7cmV0dXJuICEodC5jb21tYW5kIGluIGtlKX0pO2lmKDA9PT1vLmxlbmd0aClyZXR1cm4gITE7dmFyIHI9by5maWx0ZXIoZnVuY3Rpb24odCl7cmV0dXJuICEodC5jb21tYW5kIGluIEFlKX0pO2lmKHIubGVuZ3RoPjApdGhyb3cgbmV3IEVycm9yKFwiVW5pbXBsZW1lbnRlZDogXCIrci5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHQuY29tbWFuZH0pLmpvaW4oXCIsIFwiKStcIi5cIik7cmV0dXJuIG8uZm9yRWFjaChmdW5jdGlvbih0KXtcInNldFRyYW5zaXRpb25cIiE9PXQuY29tbWFuZCYmaVt0LmNvbW1hbmRdLmFwcGx5KGksdC5hcmdzKTt9KSx0aGlzLnN0eWxlc2hlZXQ9ZSwhMH0saS5wcm90b3R5cGUuYWRkSW1hZ2U9ZnVuY3Rpb24oZSxpKXtpZih0aGlzLmdldEltYWdlKGUpKXJldHVybiB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJBbiBpbWFnZSB3aXRoIHRoaXMgbmFtZSBhbHJlYWR5IGV4aXN0cy5cIikpKTt0aGlzLmltYWdlTWFuYWdlci5hZGRJbWFnZShlLGkpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIix7ZGF0YVR5cGU6XCJzdHlsZVwifSkpO30saS5wcm90b3R5cGUudXBkYXRlSW1hZ2U9ZnVuY3Rpb24odCxlKXt0aGlzLmltYWdlTWFuYWdlci51cGRhdGVJbWFnZSh0LGUpO30saS5wcm90b3R5cGUuZ2V0SW1hZ2U9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuaW1hZ2VNYW5hZ2VyLmdldEltYWdlKHQpfSxpLnByb3RvdHlwZS5yZW1vdmVJbWFnZT1mdW5jdGlvbihlKXtpZighdGhpcy5nZXRJbWFnZShlKSlyZXR1cm4gdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiTm8gaW1hZ2Ugd2l0aCB0aGlzIG5hbWUgZXhpc3RzLlwiKSkpO3RoaXMuaW1hZ2VNYW5hZ2VyLnJlbW92ZUltYWdlKGUpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImRhdGFcIix7ZGF0YVR5cGU6XCJzdHlsZVwifSkpO30saS5wcm90b3R5cGUubGlzdEltYWdlcz1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9jaGVja0xvYWRlZCgpLHRoaXMuaW1hZ2VNYW5hZ2VyLmxpc3RJbWFnZXMoKX0saS5wcm90b3R5cGUuYWRkU291cmNlPWZ1bmN0aW9uKGUsaSxvKXt2YXIgcj10aGlzO2lmKHZvaWQgMD09PW8mJihvPXt9KSx0aGlzLl9jaGVja0xvYWRlZCgpLHZvaWQgMCE9PXRoaXMuc291cmNlQ2FjaGVzW2VdKXRocm93IG5ldyBFcnJvcihcIlRoZXJlIGlzIGFscmVhZHkgYSBzb3VyY2Ugd2l0aCB0aGlzIElEXCIpO2lmKCFpLnR5cGUpdGhyb3cgbmV3IEVycm9yKFwiVGhlIHR5cGUgcHJvcGVydHkgbXVzdCBiZSBkZWZpbmVkLCBidXQgdGhlIG9ubHkgdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzIHdlcmUgZ2l2ZW46IFwiK09iamVjdC5rZXlzKGkpLmpvaW4oXCIsIFwiKStcIi5cIik7aWYoIShbXCJ2ZWN0b3JcIixcInJhc3RlclwiLFwiZ2VvanNvblwiLFwidmlkZW9cIixcImltYWdlXCJdLmluZGV4T2YoaS50eXBlKT49MCl8fCF0aGlzLl92YWxpZGF0ZSh0LnZhbGlkYXRlU3R5bGUuc291cmNlLFwic291cmNlcy5cIitlLGksbnVsbCxvKSl7dGhpcy5tYXAmJnRoaXMubWFwLl9jb2xsZWN0UmVzb3VyY2VUaW1pbmcmJihpLmNvbGxlY3RSZXNvdXJjZVRpbWluZz0hMCk7dmFyIGE9dGhpcy5zb3VyY2VDYWNoZXNbZV09bmV3IHp0KGUsaSx0aGlzLmRpc3BhdGNoZXIpO2Euc3R5bGU9dGhpcyxhLnNldEV2ZW50ZWRQYXJlbnQodGhpcyxmdW5jdGlvbigpe3JldHVybiB7aXNTb3VyY2VMb2FkZWQ6ci5sb2FkZWQoKSxzb3VyY2U6YS5zZXJpYWxpemUoKSxzb3VyY2VJZDplfX0pLGEub25BZGQodGhpcy5tYXApLHRoaXMuX2NoYW5nZWQ9ITA7fX0saS5wcm90b3R5cGUucmVtb3ZlU291cmNlPWZ1bmN0aW9uKGUpe2lmKHRoaXMuX2NoZWNrTG9hZGVkKCksdm9pZCAwPT09dGhpcy5zb3VyY2VDYWNoZXNbZV0pdGhyb3cgbmV3IEVycm9yKFwiVGhlcmUgaXMgbm8gc291cmNlIHdpdGggdGhpcyBJRFwiKTtmb3IodmFyIGkgaW4gdGhpcy5fbGF5ZXJzKWlmKHRoaXMuX2xheWVyc1tpXS5zb3VyY2U9PT1lKXJldHVybiB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoJ1NvdXJjZSBcIicrZSsnXCIgY2Fubm90IGJlIHJlbW92ZWQgd2hpbGUgbGF5ZXIgXCInK2krJ1wiIGlzIHVzaW5nIGl0LicpKSk7dmFyIG89dGhpcy5zb3VyY2VDYWNoZXNbZV07ZGVsZXRlIHRoaXMuc291cmNlQ2FjaGVzW2VdLGRlbGV0ZSB0aGlzLl91cGRhdGVkU291cmNlc1tlXSxvLmZpcmUobmV3IHQuRXZlbnQoXCJkYXRhXCIse3NvdXJjZURhdGFUeXBlOlwibWV0YWRhdGFcIixkYXRhVHlwZTpcInNvdXJjZVwiLHNvdXJjZUlkOmV9KSksby5zZXRFdmVudGVkUGFyZW50KG51bGwpLG8uY2xlYXJUaWxlcygpLG8ub25SZW1vdmUmJm8ub25SZW1vdmUodGhpcy5tYXApLHRoaXMuX2NoYW5nZWQ9ITA7fSxpLnByb3RvdHlwZS5zZXRHZW9KU09OU291cmNlRGF0YT1mdW5jdGlvbih0LGUpe3RoaXMuX2NoZWNrTG9hZGVkKCksdGhpcy5zb3VyY2VDYWNoZXNbdF0uZ2V0U291cmNlKCkuc2V0RGF0YShlKSx0aGlzLl9jaGFuZ2VkPSEwO30saS5wcm90b3R5cGUuZ2V0U291cmNlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnNvdXJjZUNhY2hlc1t0XSYmdGhpcy5zb3VyY2VDYWNoZXNbdF0uZ2V0U291cmNlKCl9LGkucHJvdG90eXBlLmFkZExheWVyPWZ1bmN0aW9uKGUsaSxvKXt2b2lkIDA9PT1vJiYobz17fSksdGhpcy5fY2hlY2tMb2FkZWQoKTt2YXIgcj1lLmlkO2lmKHRoaXMuZ2V0TGF5ZXIocikpdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKCdMYXllciB3aXRoIGlkIFwiJytyKydcIiBhbHJlYWR5IGV4aXN0cyBvbiB0aGlzIG1hcCcpKSk7ZWxzZXt2YXIgYTtpZihcImN1c3RvbVwiPT09ZS50eXBlKXtpZihSZSh0aGlzLHQudmFsaWRhdGVDdXN0b21TdHlsZUxheWVyKGUpKSlyZXR1cm47YT10LmNyZWF0ZVN0eWxlTGF5ZXIoZSk7fWVsc2V7aWYoXCJvYmplY3RcIj09dHlwZW9mIGUuc291cmNlJiYodGhpcy5hZGRTb3VyY2UocixlLnNvdXJjZSksZT10LmNsb25lJDEoZSksZT10LmV4dGVuZChlLHtzb3VyY2U6cn0pKSx0aGlzLl92YWxpZGF0ZSh0LnZhbGlkYXRlU3R5bGUubGF5ZXIsXCJsYXllcnMuXCIrcixlLHthcnJheUluZGV4Oi0xfSxvKSlyZXR1cm47YT10LmNyZWF0ZVN0eWxlTGF5ZXIoZSksdGhpcy5fdmFsaWRhdGVMYXllcihhKSxhLnNldEV2ZW50ZWRQYXJlbnQodGhpcyx7bGF5ZXI6e2lkOnJ9fSk7fXZhciBuPWk/dGhpcy5fb3JkZXIuaW5kZXhPZihpKTp0aGlzLl9vcmRlci5sZW5ndGg7aWYoaSYmLTE9PT1uKXRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcignTGF5ZXIgd2l0aCBpZCBcIicraSsnXCIgZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBtYXAuJykpKTtlbHNle2lmKHRoaXMuX29yZGVyLnNwbGljZShuLDAsciksdGhpcy5fbGF5ZXJPcmRlckNoYW5nZWQ9ITAsdGhpcy5fbGF5ZXJzW3JdPWEsdGhpcy5fcmVtb3ZlZExheWVyc1tyXSYmYS5zb3VyY2UmJlwiY3VzdG9tXCIhPT1hLnR5cGUpe3ZhciBzPXRoaXMuX3JlbW92ZWRMYXllcnNbcl07ZGVsZXRlIHRoaXMuX3JlbW92ZWRMYXllcnNbcl0scy50eXBlIT09YS50eXBlP3RoaXMuX3VwZGF0ZWRTb3VyY2VzW2Euc291cmNlXT1cImNsZWFyXCI6KHRoaXMuX3VwZGF0ZWRTb3VyY2VzW2Euc291cmNlXT1cInJlbG9hZFwiLHRoaXMuc291cmNlQ2FjaGVzW2Euc291cmNlXS5wYXVzZSgpKTt9dGhpcy5fdXBkYXRlTGF5ZXIoYSksYS5vbkFkZCYmYS5vbkFkZCh0aGlzLm1hcCk7fX19LGkucHJvdG90eXBlLm1vdmVMYXllcj1mdW5jdGlvbihlLGkpe2lmKHRoaXMuX2NoZWNrTG9hZGVkKCksdGhpcy5fY2hhbmdlZD0hMCx0aGlzLl9sYXllcnNbZV0pe2lmKGUhPT1pKXt2YXIgbz10aGlzLl9vcmRlci5pbmRleE9mKGUpO3RoaXMuX29yZGVyLnNwbGljZShvLDEpO3ZhciByPWk/dGhpcy5fb3JkZXIuaW5kZXhPZihpKTp0aGlzLl9vcmRlci5sZW5ndGg7aSYmLTE9PT1yP3RoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcignTGF5ZXIgd2l0aCBpZCBcIicraSsnXCIgZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBtYXAuJykpKToodGhpcy5fb3JkZXIuc3BsaWNlKHIsMCxlKSx0aGlzLl9sYXllck9yZGVyQ2hhbmdlZD0hMCk7fX1lbHNlIHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBsYXllciAnXCIrZStcIicgZG9lcyBub3QgZXhpc3QgaW4gdGhlIG1hcCdzIHN0eWxlIGFuZCBjYW5ub3QgYmUgbW92ZWQuXCIpKSk7fSxpLnByb3RvdHlwZS5yZW1vdmVMYXllcj1mdW5jdGlvbihlKXt0aGlzLl9jaGVja0xvYWRlZCgpO3ZhciBpPXRoaXMuX2xheWVyc1tlXTtpZihpKXtpLnNldEV2ZW50ZWRQYXJlbnQobnVsbCk7dmFyIG89dGhpcy5fb3JkZXIuaW5kZXhPZihlKTt0aGlzLl9vcmRlci5zcGxpY2UobywxKSx0aGlzLl9sYXllck9yZGVyQ2hhbmdlZD0hMCx0aGlzLl9jaGFuZ2VkPSEwLHRoaXMuX3JlbW92ZWRMYXllcnNbZV09aSxkZWxldGUgdGhpcy5fbGF5ZXJzW2VdLGRlbGV0ZSB0aGlzLl91cGRhdGVkTGF5ZXJzW2VdLGRlbGV0ZSB0aGlzLl91cGRhdGVkUGFpbnRQcm9wc1tlXSxpLm9uUmVtb3ZlJiZpLm9uUmVtb3ZlKHRoaXMubWFwKTt9ZWxzZSB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJUaGUgbGF5ZXIgJ1wiK2UrXCInIGRvZXMgbm90IGV4aXN0IGluIHRoZSBtYXAncyBzdHlsZSBhbmQgY2Fubm90IGJlIHJlbW92ZWQuXCIpKSk7fSxpLnByb3RvdHlwZS5nZXRMYXllcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbGF5ZXJzW3RdfSxpLnByb3RvdHlwZS5zZXRMYXllclpvb21SYW5nZT1mdW5jdGlvbihlLGksbyl7dGhpcy5fY2hlY2tMb2FkZWQoKTt2YXIgcj10aGlzLmdldExheWVyKGUpO3I/ci5taW56b29tPT09aSYmci5tYXh6b29tPT09b3x8KG51bGwhPWkmJihyLm1pbnpvb209aSksbnVsbCE9byYmKHIubWF4em9vbT1vKSx0aGlzLl91cGRhdGVMYXllcihyKSk6dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlIGxheWVyICdcIitlK1wiJyBkb2VzIG5vdCBleGlzdCBpbiB0aGUgbWFwJ3Mgc3R5bGUgYW5kIGNhbm5vdCBoYXZlIHpvb20gZXh0ZW50LlwiKSkpO30saS5wcm90b3R5cGUuc2V0RmlsdGVyPWZ1bmN0aW9uKGUsaSxvKXt2b2lkIDA9PT1vJiYobz17fSksdGhpcy5fY2hlY2tMb2FkZWQoKTt2YXIgcj10aGlzLmdldExheWVyKGUpO2lmKHIpe2lmKCF0LmRlZXBFcXVhbChyLmZpbHRlcixpKSlyZXR1cm4gbnVsbD09aT8oci5maWx0ZXI9dm9pZCAwLHZvaWQgdGhpcy5fdXBkYXRlTGF5ZXIocikpOnZvaWQodGhpcy5fdmFsaWRhdGUodC52YWxpZGF0ZVN0eWxlLmZpbHRlcixcImxheWVycy5cIityLmlkK1wiLmZpbHRlclwiLGksbnVsbCxvKXx8KHIuZmlsdGVyPXQuY2xvbmUkMShpKSx0aGlzLl91cGRhdGVMYXllcihyKSkpfWVsc2UgdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlIGxheWVyICdcIitlK1wiJyBkb2VzIG5vdCBleGlzdCBpbiB0aGUgbWFwJ3Mgc3R5bGUgYW5kIGNhbm5vdCBiZSBmaWx0ZXJlZC5cIikpKTt9LGkucHJvdG90eXBlLmdldEZpbHRlcj1mdW5jdGlvbihlKXtyZXR1cm4gdC5jbG9uZSQxKHRoaXMuZ2V0TGF5ZXIoZSkuZmlsdGVyKX0saS5wcm90b3R5cGUuc2V0TGF5b3V0UHJvcGVydHk9ZnVuY3Rpb24oZSxpLG8scil7dm9pZCAwPT09ciYmKHI9e30pLHRoaXMuX2NoZWNrTG9hZGVkKCk7dmFyIGE9dGhpcy5nZXRMYXllcihlKTthP3QuZGVlcEVxdWFsKGEuZ2V0TGF5b3V0UHJvcGVydHkoaSksbyl8fChhLnNldExheW91dFByb3BlcnR5KGksbyxyKSx0aGlzLl91cGRhdGVMYXllcihhKSk6dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlIGxheWVyICdcIitlK1wiJyBkb2VzIG5vdCBleGlzdCBpbiB0aGUgbWFwJ3Mgc3R5bGUgYW5kIGNhbm5vdCBiZSBzdHlsZWQuXCIpKSk7fSxpLnByb3RvdHlwZS5nZXRMYXlvdXRQcm9wZXJ0eT1mdW5jdGlvbihlLGkpe3ZhciBvPXRoaXMuZ2V0TGF5ZXIoZSk7aWYobylyZXR1cm4gby5nZXRMYXlvdXRQcm9wZXJ0eShpKTt0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJUaGUgbGF5ZXIgJ1wiK2UrXCInIGRvZXMgbm90IGV4aXN0IGluIHRoZSBtYXAncyBzdHlsZS5cIikpKTt9LGkucHJvdG90eXBlLnNldFBhaW50UHJvcGVydHk9ZnVuY3Rpb24oZSxpLG8scil7dm9pZCAwPT09ciYmKHI9e30pLHRoaXMuX2NoZWNrTG9hZGVkKCk7dmFyIGE9dGhpcy5nZXRMYXllcihlKTthP3QuZGVlcEVxdWFsKGEuZ2V0UGFpbnRQcm9wZXJ0eShpKSxvKXx8KGEuc2V0UGFpbnRQcm9wZXJ0eShpLG8scikmJnRoaXMuX3VwZGF0ZUxheWVyKGEpLHRoaXMuX2NoYW5nZWQ9ITAsdGhpcy5fdXBkYXRlZFBhaW50UHJvcHNbZV09ITApOnRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBsYXllciAnXCIrZStcIicgZG9lcyBub3QgZXhpc3QgaW4gdGhlIG1hcCdzIHN0eWxlIGFuZCBjYW5ub3QgYmUgc3R5bGVkLlwiKSkpO30saS5wcm90b3R5cGUuZ2V0UGFpbnRQcm9wZXJ0eT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmdldExheWVyKHQpLmdldFBhaW50UHJvcGVydHkoZSl9LGkucHJvdG90eXBlLnNldEZlYXR1cmVTdGF0ZT1mdW5jdGlvbihlLGkpe3RoaXMuX2NoZWNrTG9hZGVkKCk7dmFyIG89ZS5zb3VyY2Uscj1lLnNvdXJjZUxheWVyLGE9dGhpcy5zb3VyY2VDYWNoZXNbb10sbj1wYXJzZUludChlLmlkLDEwKTtpZih2b2lkIDAhPT1hKXt2YXIgcz1hLmdldFNvdXJjZSgpLnR5cGU7XCJnZW9qc29uXCI9PT1zJiZyP3RoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIkdlb0pTT04gc291cmNlcyBjYW5ub3QgaGF2ZSBhIHNvdXJjZUxheWVyIHBhcmFtZXRlci5cIikpKTpcInZlY3RvclwiIT09c3x8cj9pc05hTihuKXx8bjwwP3RoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBmZWF0dXJlIGlkIHBhcmFtZXRlciBtdXN0IGJlIHByb3ZpZGVkIGFuZCBub24tbmVnYXRpdmUuXCIpKSk6YS5zZXRGZWF0dXJlU3RhdGUocixuLGkpOnRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBzb3VyY2VMYXllciBwYXJhbWV0ZXIgbXVzdCBiZSBwcm92aWRlZCBmb3IgdmVjdG9yIHNvdXJjZSB0eXBlcy5cIikpKTt9ZWxzZSB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJUaGUgc291cmNlICdcIitvK1wiJyBkb2VzIG5vdCBleGlzdCBpbiB0aGUgbWFwJ3Mgc3R5bGUuXCIpKSk7fSxpLnByb3RvdHlwZS5yZW1vdmVGZWF0dXJlU3RhdGU9ZnVuY3Rpb24oZSxpKXt0aGlzLl9jaGVja0xvYWRlZCgpO3ZhciBvPWUuc291cmNlLHI9dGhpcy5zb3VyY2VDYWNoZXNbb107aWYodm9pZCAwIT09cil7dmFyIGE9ci5nZXRTb3VyY2UoKS50eXBlLG49XCJ2ZWN0b3JcIj09PWE/ZS5zb3VyY2VMYXllcjp2b2lkIDAscz1wYXJzZUludChlLmlkLDEwKTtcInZlY3RvclwiIT09YXx8bj92b2lkIDAhPT1lLmlkJiZpc05hTihzKXx8czwwP3RoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBmZWF0dXJlIGlkIHBhcmFtZXRlciBtdXN0IGJlIG5vbi1uZWdhdGl2ZS5cIikpKTppJiZcInN0cmluZ1wiIT10eXBlb2YgZS5pZCYmXCJudW1iZXJcIiE9dHlwZW9mIGUuaWQ/dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiQSBmZWF0dXJlIGlkIGlzIHJlcXVyZWQgdG8gcmVtb3ZlIGl0cyBzcGVjaWZpYyBzdGF0ZSBwcm9wZXJ0eS5cIikpKTpyLnJlbW92ZUZlYXR1cmVTdGF0ZShuLHMsaSk6dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlIHNvdXJjZUxheWVyIHBhcmFtZXRlciBtdXN0IGJlIHByb3ZpZGVkIGZvciB2ZWN0b3Igc291cmNlIHR5cGVzLlwiKSkpO31lbHNlIHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBzb3VyY2UgJ1wiK28rXCInIGRvZXMgbm90IGV4aXN0IGluIHRoZSBtYXAncyBzdHlsZS5cIikpKTt9LGkucHJvdG90eXBlLmdldEZlYXR1cmVTdGF0ZT1mdW5jdGlvbihlKXt0aGlzLl9jaGVja0xvYWRlZCgpO3ZhciBpPWUuc291cmNlLG89ZS5zb3VyY2VMYXllcixyPXRoaXMuc291cmNlQ2FjaGVzW2ldLGE9cGFyc2VJbnQoZS5pZCwxMCk7aWYodm9pZCAwIT09cilpZihcInZlY3RvclwiIT09ci5nZXRTb3VyY2UoKS50eXBlfHxvKXtpZighKGlzTmFOKGEpfHxhPDApKXJldHVybiByLmdldEZlYXR1cmVTdGF0ZShvLGEpO3RoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBmZWF0dXJlIGlkIHBhcmFtZXRlciBtdXN0IGJlIHByb3ZpZGVkIGFuZCBub24tbmVnYXRpdmUuXCIpKSk7fWVsc2UgdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlIHNvdXJjZUxheWVyIHBhcmFtZXRlciBtdXN0IGJlIHByb3ZpZGVkIGZvciB2ZWN0b3Igc291cmNlIHR5cGVzLlwiKSkpO2Vsc2UgdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlIHNvdXJjZSAnXCIraStcIicgZG9lcyBub3QgZXhpc3QgaW4gdGhlIG1hcCdzIHN0eWxlLlwiKSkpO30saS5wcm90b3R5cGUuZ2V0VHJhbnNpdGlvbj1mdW5jdGlvbigpe3JldHVybiB0LmV4dGVuZCh7ZHVyYXRpb246MzAwLGRlbGF5OjB9LHRoaXMuc3R5bGVzaGVldCYmdGhpcy5zdHlsZXNoZWV0LnRyYW5zaXRpb24pfSxpLnByb3RvdHlwZS5zZXJpYWxpemU9ZnVuY3Rpb24oKXtyZXR1cm4gdC5maWx0ZXJPYmplY3Qoe3ZlcnNpb246dGhpcy5zdHlsZXNoZWV0LnZlcnNpb24sbmFtZTp0aGlzLnN0eWxlc2hlZXQubmFtZSxtZXRhZGF0YTp0aGlzLnN0eWxlc2hlZXQubWV0YWRhdGEsbGlnaHQ6dGhpcy5zdHlsZXNoZWV0LmxpZ2h0LGNlbnRlcjp0aGlzLnN0eWxlc2hlZXQuY2VudGVyLHpvb206dGhpcy5zdHlsZXNoZWV0Lnpvb20sYmVhcmluZzp0aGlzLnN0eWxlc2hlZXQuYmVhcmluZyxwaXRjaDp0aGlzLnN0eWxlc2hlZXQucGl0Y2gsc3ByaXRlOnRoaXMuc3R5bGVzaGVldC5zcHJpdGUsZ2x5cGhzOnRoaXMuc3R5bGVzaGVldC5nbHlwaHMsdHJhbnNpdGlvbjp0aGlzLnN0eWxlc2hlZXQudHJhbnNpdGlvbixzb3VyY2VzOnQubWFwT2JqZWN0KHRoaXMuc291cmNlQ2FjaGVzLGZ1bmN0aW9uKHQpe3JldHVybiB0LnNlcmlhbGl6ZSgpfSksbGF5ZXJzOnRoaXMuX3NlcmlhbGl6ZUxheWVycyh0aGlzLl9vcmRlcil9LGZ1bmN0aW9uKHQpe3JldHVybiB2b2lkIDAhPT10fSl9LGkucHJvdG90eXBlLl91cGRhdGVMYXllcj1mdW5jdGlvbih0KXt0aGlzLl91cGRhdGVkTGF5ZXJzW3QuaWRdPSEwLHQuc291cmNlJiYhdGhpcy5fdXBkYXRlZFNvdXJjZXNbdC5zb3VyY2VdJiYodGhpcy5fdXBkYXRlZFNvdXJjZXNbdC5zb3VyY2VdPVwicmVsb2FkXCIsdGhpcy5zb3VyY2VDYWNoZXNbdC5zb3VyY2VdLnBhdXNlKCkpLHRoaXMuX2NoYW5nZWQ9ITA7fSxpLnByb3RvdHlwZS5fZmxhdHRlbkFuZFNvcnRSZW5kZXJlZEZlYXR1cmVzPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT10aGlzLGk9ZnVuY3Rpb24odCl7cmV0dXJuIFwiZmlsbC1leHRydXNpb25cIj09PWUuX2xheWVyc1t0XS50eXBlfSxvPXt9LHI9W10sYT10aGlzLl9vcmRlci5sZW5ndGgtMTthPj0wO2EtLSl7dmFyIG49dGhpcy5fb3JkZXJbYV07aWYoaShuKSl7b1tuXT1hO2Zvcih2YXIgcz0wLGw9dDtzPGwubGVuZ3RoO3MrPTEpe3ZhciBjPWxbc11bbl07aWYoYylmb3IodmFyIHU9MCxoPWM7dTxoLmxlbmd0aDt1Kz0xKXt2YXIgcD1oW3VdO3IucHVzaChwKTt9fX19ci5zb3J0KGZ1bmN0aW9uKHQsZSl7cmV0dXJuIGUuaW50ZXJzZWN0aW9uWi10LmludGVyc2VjdGlvblp9KTtmb3IodmFyIGQ9W10sXz10aGlzLl9vcmRlci5sZW5ndGgtMTtfPj0wO18tLSl7dmFyIGY9dGhpcy5fb3JkZXJbX107aWYoaShmKSlmb3IodmFyIG09ci5sZW5ndGgtMTttPj0wO20tLSl7dmFyIGc9clttXS5mZWF0dXJlO2lmKG9bZy5sYXllci5pZF08XylicmVhaztkLnB1c2goZyksci5wb3AoKTt9ZWxzZSBmb3IodmFyIHY9MCx5PXQ7djx5Lmxlbmd0aDt2Kz0xKXt2YXIgeD15W3ZdW2ZdO2lmKHgpZm9yKHZhciBiPTAsdz14O2I8dy5sZW5ndGg7Yis9MSl7dmFyIEU9d1tiXTtkLnB1c2goRS5mZWF0dXJlKTt9fX1yZXR1cm4gZH0saS5wcm90b3R5cGUucXVlcnlSZW5kZXJlZEZlYXR1cmVzPWZ1bmN0aW9uKGUsaSxvKXtpJiZpLmZpbHRlciYmdGhpcy5fdmFsaWRhdGUodC52YWxpZGF0ZVN0eWxlLmZpbHRlcixcInF1ZXJ5UmVuZGVyZWRGZWF0dXJlcy5maWx0ZXJcIixpLmZpbHRlcixudWxsLGkpO3ZhciByPXt9O2lmKGkmJmkubGF5ZXJzKXtpZighQXJyYXkuaXNBcnJheShpLmxheWVycykpcmV0dXJuIHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcInBhcmFtZXRlcnMubGF5ZXJzIG11c3QgYmUgYW4gQXJyYXkuXCIpKSksW107Zm9yKHZhciBhPTAsbj1pLmxheWVyczthPG4ubGVuZ3RoO2ErPTEpe3ZhciBzPW5bYV0sbD10aGlzLl9sYXllcnNbc107aWYoIWwpcmV0dXJuIHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSBsYXllciAnXCIrcytcIicgZG9lcyBub3QgZXhpc3QgaW4gdGhlIG1hcCdzIHN0eWxlIGFuZCBjYW5ub3QgYmUgcXVlcmllZCBmb3IgZmVhdHVyZXMuXCIpKSksW107cltsLnNvdXJjZV09ITA7fX12YXIgYz1bXTtmb3IodmFyIHUgaW4gdGhpcy5zb3VyY2VDYWNoZXMpaS5sYXllcnMmJiFyW3VdfHxjLnB1c2goQih0aGlzLnNvdXJjZUNhY2hlc1t1XSx0aGlzLl9sYXllcnMsZSxpLG8pKTtyZXR1cm4gdGhpcy5wbGFjZW1lbnQmJmMucHVzaChmdW5jdGlvbih0LGUsaSxvLHIsYSl7Zm9yKHZhciBuPXt9LHM9ci5xdWVyeVJlbmRlcmVkU3ltYm9scyhpKSxsPVtdLGM9MCx1PU9iamVjdC5rZXlzKHMpLm1hcChOdW1iZXIpO2M8dS5sZW5ndGg7Yys9MSl7dmFyIGg9dVtjXTtsLnB1c2goYVtoXSk7fWwuc29ydChPKTtmb3IodmFyIHA9ZnVuY3Rpb24oKXt2YXIgZT1fW2RdLGk9ZS5mZWF0dXJlSW5kZXgubG9va3VwU3ltYm9sRmVhdHVyZXMoc1tlLmJ1Y2tldEluc3RhbmNlSWRdLGUuYnVja2V0SW5kZXgsZS5zb3VyY2VMYXllckluZGV4LG8uZmlsdGVyLG8ubGF5ZXJzLHQpO2Zvcih2YXIgciBpbiBpKXt2YXIgYT1uW3JdPW5bcl18fFtdLGw9aVtyXTtsLnNvcnQoZnVuY3Rpb24odCxpKXt2YXIgbz1lLmZlYXR1cmVTb3J0T3JkZXI7aWYobyl7dmFyIHI9by5pbmRleE9mKHQuZmVhdHVyZUluZGV4KTtyZXR1cm4gby5pbmRleE9mKGkuZmVhdHVyZUluZGV4KS1yfXJldHVybiBpLmZlYXR1cmVJbmRleC10LmZlYXR1cmVJbmRleH0pO2Zvcih2YXIgYz0wLHU9bDtjPHUubGVuZ3RoO2MrPTEpe3ZhciBoPXVbY107YS5wdXNoKGgpO319fSxkPTAsXz1sO2Q8Xy5sZW5ndGg7ZCs9MSlwKCk7dmFyIGY9ZnVuY3Rpb24oaSl7bltpXS5mb3JFYWNoKGZ1bmN0aW9uKG8pe3ZhciByPW8uZmVhdHVyZSxhPXRbaV0sbj1lW2Euc291cmNlXS5nZXRGZWF0dXJlU3RhdGUoci5sYXllcltcInNvdXJjZS1sYXllclwiXSxyLmlkKTtyLnNvdXJjZT1yLmxheWVyLnNvdXJjZSxyLmxheWVyW1wic291cmNlLWxheWVyXCJdJiYoci5zb3VyY2VMYXllcj1yLmxheWVyW1wic291cmNlLWxheWVyXCJdKSxyLnN0YXRlPW47fSk7fTtmb3IodmFyIG0gaW4gbilmKG0pO3JldHVybiBufSh0aGlzLl9sYXllcnMsdGhpcy5zb3VyY2VDYWNoZXMsZSxpLHRoaXMucGxhY2VtZW50LmNvbGxpc2lvbkluZGV4LHRoaXMucGxhY2VtZW50LnJldGFpbmVkUXVlcnlEYXRhKSksdGhpcy5fZmxhdHRlbkFuZFNvcnRSZW5kZXJlZEZlYXR1cmVzKGMpfSxpLnByb3RvdHlwZS5xdWVyeVNvdXJjZUZlYXR1cmVzPWZ1bmN0aW9uKGUsaSl7aSYmaS5maWx0ZXImJnRoaXMuX3ZhbGlkYXRlKHQudmFsaWRhdGVTdHlsZS5maWx0ZXIsXCJxdWVyeVNvdXJjZUZlYXR1cmVzLmZpbHRlclwiLGkuZmlsdGVyLG51bGwsaSk7dmFyIG89dGhpcy5zb3VyY2VDYWNoZXNbZV07cmV0dXJuIG8/ZnVuY3Rpb24odCxlKXtmb3IodmFyIGk9dC5nZXRSZW5kZXJhYmxlSWRzKCkubWFwKGZ1bmN0aW9uKGUpe3JldHVybiB0LmdldFRpbGVCeUlEKGUpfSksbz1bXSxyPXt9LGE9MDthPGkubGVuZ3RoO2ErKyl7dmFyIG49aVthXSxzPW4udGlsZUlELmNhbm9uaWNhbC5rZXk7cltzXXx8KHJbc109ITAsbi5xdWVyeVNvdXJjZUZlYXR1cmVzKG8sZSkpO31yZXR1cm4gb30obyxpKTpbXX0saS5wcm90b3R5cGUuYWRkU291cmNlVHlwZT1mdW5jdGlvbih0LGUsbyl7cmV0dXJuIGkuZ2V0U291cmNlVHlwZSh0KT9vKG5ldyBFcnJvcignQSBzb3VyY2UgdHlwZSBjYWxsZWQgXCInK3QrJ1wiIGFscmVhZHkgZXhpc3RzLicpKTooaS5zZXRTb3VyY2VUeXBlKHQsZSksZS53b3JrZXJTb3VyY2VVUkw/dm9pZCB0aGlzLmRpc3BhdGNoZXIuYnJvYWRjYXN0KFwibG9hZFdvcmtlclNvdXJjZVwiLHtuYW1lOnQsdXJsOmUud29ya2VyU291cmNlVVJMfSxvKTpvKG51bGwsbnVsbCkpfSxpLnByb3RvdHlwZS5nZXRMaWdodD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmxpZ2h0LmdldExpZ2h0KCl9LGkucHJvdG90eXBlLnNldExpZ2h0PWZ1bmN0aW9uKGUsaSl7dm9pZCAwPT09aSYmKGk9e30pLHRoaXMuX2NoZWNrTG9hZGVkKCk7dmFyIG89dGhpcy5saWdodC5nZXRMaWdodCgpLHI9ITE7Zm9yKHZhciBhIGluIGUpaWYoIXQuZGVlcEVxdWFsKGVbYV0sb1thXSkpe3I9ITA7YnJlYWt9aWYocil7dmFyIG49e25vdzp0LmJyb3dzZXIubm93KCksdHJhbnNpdGlvbjp0LmV4dGVuZCh7ZHVyYXRpb246MzAwLGRlbGF5OjB9LHRoaXMuc3R5bGVzaGVldC50cmFuc2l0aW9uKX07dGhpcy5saWdodC5zZXRMaWdodChlLGkpLHRoaXMubGlnaHQudXBkYXRlVHJhbnNpdGlvbnMobik7fX0saS5wcm90b3R5cGUuX3ZhbGlkYXRlPWZ1bmN0aW9uKGUsaSxvLHIsYSl7cmV0dXJuIHZvaWQgMD09PWEmJihhPXt9KSwoIWF8fCExIT09YS52YWxpZGF0ZSkmJlJlKHRoaXMsZS5jYWxsKHQudmFsaWRhdGVTdHlsZSx0LmV4dGVuZCh7a2V5Omksc3R5bGU6dGhpcy5zZXJpYWxpemUoKSx2YWx1ZTpvLHN0eWxlU3BlYzp0LnN0eWxlU3BlY30scikpKX0saS5wcm90b3R5cGUuX3JlbW92ZT1mdW5jdGlvbigpe2Zvcih2YXIgZSBpbiB0aGlzLl9yZXF1ZXN0JiYodGhpcy5fcmVxdWVzdC5jYW5jZWwoKSx0aGlzLl9yZXF1ZXN0PW51bGwpLHRoaXMuX3Nwcml0ZVJlcXVlc3QmJih0aGlzLl9zcHJpdGVSZXF1ZXN0LmNhbmNlbCgpLHRoaXMuX3Nwcml0ZVJlcXVlc3Q9bnVsbCksdC5ldmVudGVkLm9mZihcInBsdWdpbkF2YWlsYWJsZVwiLHRoaXMuX3J0bFRleHRQbHVnaW5DYWxsYmFjayksdGhpcy5zb3VyY2VDYWNoZXMpdGhpcy5zb3VyY2VDYWNoZXNbZV0uY2xlYXJUaWxlcygpO3RoaXMuZGlzcGF0Y2hlci5yZW1vdmUoKTt9LGkucHJvdG90eXBlLl9jbGVhclNvdXJjZT1mdW5jdGlvbih0KXt0aGlzLnNvdXJjZUNhY2hlc1t0XS5jbGVhclRpbGVzKCk7fSxpLnByb3RvdHlwZS5fcmVsb2FkU291cmNlPWZ1bmN0aW9uKHQpe3RoaXMuc291cmNlQ2FjaGVzW3RdLnJlc3VtZSgpLHRoaXMuc291cmNlQ2FjaGVzW3RdLnJlbG9hZCgpO30saS5wcm90b3R5cGUuX3VwZGF0ZVNvdXJjZXM9ZnVuY3Rpb24odCl7Zm9yKHZhciBlIGluIHRoaXMuc291cmNlQ2FjaGVzKXRoaXMuc291cmNlQ2FjaGVzW2VdLnVwZGF0ZSh0KTt9LGkucHJvdG90eXBlLl9nZW5lcmF0ZUNvbGxpc2lvbkJveGVzPWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMuc291cmNlQ2FjaGVzKXRoaXMuX3JlbG9hZFNvdXJjZSh0KTt9LGkucHJvdG90eXBlLl91cGRhdGVQbGFjZW1lbnQ9ZnVuY3Rpb24oZSxpLG8scil7Zm9yKHZhciBhPSExLG49ITEscz17fSxsPTAsYz10aGlzLl9vcmRlcjtsPGMubGVuZ3RoO2wrPTEpe3ZhciB1PWNbbF0saD10aGlzLl9sYXllcnNbdV07aWYoXCJzeW1ib2xcIj09PWgudHlwZSl7aWYoIXNbaC5zb3VyY2VdKXt2YXIgcD10aGlzLnNvdXJjZUNhY2hlc1toLnNvdXJjZV07c1toLnNvdXJjZV09cC5nZXRSZW5kZXJhYmxlSWRzKCEwKS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHAuZ2V0VGlsZUJ5SUQodCl9KS5zb3J0KGZ1bmN0aW9uKHQsZSl7cmV0dXJuIGUudGlsZUlELm92ZXJzY2FsZWRaLXQudGlsZUlELm92ZXJzY2FsZWRafHwodC50aWxlSUQuaXNMZXNzVGhhbihlLnRpbGVJRCk/LTE6MSl9KTt9dmFyIGQ9dGhpcy5jcm9zc1RpbGVTeW1ib2xJbmRleC5hZGRMYXllcihoLHNbaC5zb3VyY2VdLGUuY2VudGVyLmxuZyk7YT1hfHxkO319dGhpcy5jcm9zc1RpbGVTeW1ib2xJbmRleC5wcnVuZVVudXNlZExheWVycyh0aGlzLl9vcmRlcik7dmFyIF89dGhpcy5fbGF5ZXJPcmRlckNoYW5nZWR8fDA9PT1vO2lmKChffHwhdGhpcy5wYXVzZWFibGVQbGFjZW1lbnR8fHRoaXMucGF1c2VhYmxlUGxhY2VtZW50LmlzRG9uZSgpJiYhdGhpcy5wbGFjZW1lbnQuc3RpbGxSZWNlbnQodC5icm93c2VyLm5vdygpKSkmJih0aGlzLnBhdXNlYWJsZVBsYWNlbWVudD1uZXcgU2UoZSx0aGlzLl9vcmRlcixfLGksbyxyLHRoaXMucGxhY2VtZW50KSx0aGlzLl9sYXllck9yZGVyQ2hhbmdlZD0hMSksdGhpcy5wYXVzZWFibGVQbGFjZW1lbnQuaXNEb25lKCk/dGhpcy5wbGFjZW1lbnQuc2V0U3RhbGUoKToodGhpcy5wYXVzZWFibGVQbGFjZW1lbnQuY29udGludWVQbGFjZW1lbnQodGhpcy5fb3JkZXIsdGhpcy5fbGF5ZXJzLHMpLHRoaXMucGF1c2VhYmxlUGxhY2VtZW50LmlzRG9uZSgpJiYodGhpcy5wbGFjZW1lbnQ9dGhpcy5wYXVzZWFibGVQbGFjZW1lbnQuY29tbWl0KHQuYnJvd3Nlci5ub3coKSksbj0hMCksYSYmdGhpcy5wYXVzZWFibGVQbGFjZW1lbnQucGxhY2VtZW50LnNldFN0YWxlKCkpLG58fGEpZm9yKHZhciBmPTAsbT10aGlzLl9vcmRlcjtmPG0ubGVuZ3RoO2YrPTEpe3ZhciBnPW1bZl0sdj10aGlzLl9sYXllcnNbZ107XCJzeW1ib2xcIj09PXYudHlwZSYmdGhpcy5wbGFjZW1lbnQudXBkYXRlTGF5ZXJPcGFjaXRpZXModixzW3Yuc291cmNlXSk7fXJldHVybiAhdGhpcy5wYXVzZWFibGVQbGFjZW1lbnQuaXNEb25lKCl8fHRoaXMucGxhY2VtZW50Lmhhc1RyYW5zaXRpb25zKHQuYnJvd3Nlci5ub3coKSl9LGkucHJvdG90eXBlLl9yZWxlYXNlU3ltYm9sRmFkZVRpbGVzPWZ1bmN0aW9uKCl7Zm9yKHZhciB0IGluIHRoaXMuc291cmNlQ2FjaGVzKXRoaXMuc291cmNlQ2FjaGVzW3RdLnJlbGVhc2VTeW1ib2xGYWRlVGlsZXMoKTt9LGkucHJvdG90eXBlLmdldEltYWdlcz1mdW5jdGlvbih0LGUsaSl7dGhpcy5pbWFnZU1hbmFnZXIuZ2V0SW1hZ2VzKGUuaWNvbnMsaSk7fSxpLnByb3RvdHlwZS5nZXRHbHlwaHM9ZnVuY3Rpb24odCxlLGkpe3RoaXMuZ2x5cGhNYW5hZ2VyLmdldEdseXBocyhlLnN0YWNrcyxpKTt9LGkucHJvdG90eXBlLmdldFJlc291cmNlPWZ1bmN0aW9uKGUsaSxvKXtyZXR1cm4gdC5tYWtlUmVxdWVzdChpLG8pfSxpfSh0LkV2ZW50ZWQpO0JlLmdldFNvdXJjZVR5cGU9ZnVuY3Rpb24odCl7cmV0dXJuIFJbdF19LEJlLnNldFNvdXJjZVR5cGU9ZnVuY3Rpb24odCxlKXtSW3RdPWU7fSxCZS5yZWdpc3RlckZvclBsdWdpbkF2YWlsYWJpbGl0eT10LnJlZ2lzdGVyRm9yUGx1Z2luQXZhaWxhYmlsaXR5O3ZhciBPZT10LmNyZWF0ZUxheW91dChbe25hbWU6XCJhX3Bvc1wiLHR5cGU6XCJJbnQxNlwiLGNvbXBvbmVudHM6Mn1dKSxGZT1jaShcIiNpZmRlZiBHTF9FU1xcbnByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xcbiNlbHNlXFxuI2lmICFkZWZpbmVkKGxvd3ApXFxuI2RlZmluZSBsb3dwXFxuI2VuZGlmXFxuI2lmICFkZWZpbmVkKG1lZGl1bXApXFxuI2RlZmluZSBtZWRpdW1wXFxuI2VuZGlmXFxuI2lmICFkZWZpbmVkKGhpZ2hwKVxcbiNkZWZpbmUgaGlnaHBcXG4jZW5kaWZcXG4jZW5kaWZcIixcIiNpZmRlZiBHTF9FU1xcbnByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZWxzZVxcbiNpZiAhZGVmaW5lZChsb3dwKVxcbiNkZWZpbmUgbG93cFxcbiNlbmRpZlxcbiNpZiAhZGVmaW5lZChtZWRpdW1wKVxcbiNkZWZpbmUgbWVkaXVtcFxcbiNlbmRpZlxcbiNpZiAhZGVmaW5lZChoaWdocClcXG4jZGVmaW5lIGhpZ2hwXFxuI2VuZGlmXFxuI2VuZGlmXFxudmVjMiB1bnBhY2tfZmxvYXQoY29uc3QgZmxvYXQgcGFja2VkVmFsdWUpIHtpbnQgcGFja2VkSW50VmFsdWU9aW50KHBhY2tlZFZhbHVlKTtpbnQgdjA9cGFja2VkSW50VmFsdWUvMjU2O3JldHVybiB2ZWMyKHYwLHBhY2tlZEludFZhbHVlLXYwKjI1Nik7fXZlYzIgdW5wYWNrX29wYWNpdHkoY29uc3QgZmxvYXQgcGFja2VkT3BhY2l0eSkge2ludCBpbnRPcGFjaXR5PWludChwYWNrZWRPcGFjaXR5KS8yO3JldHVybiB2ZWMyKGZsb2F0KGludE9wYWNpdHkpLzEyNy4wLG1vZChwYWNrZWRPcGFjaXR5LDIuMCkpO312ZWM0IGRlY29kZV9jb2xvcihjb25zdCB2ZWMyIGVuY29kZWRDb2xvcikge3JldHVybiB2ZWM0KHVucGFja19mbG9hdChlbmNvZGVkQ29sb3JbMF0pLzI1NS4wLHVucGFja19mbG9hdChlbmNvZGVkQ29sb3JbMV0pLzI1NS4wXFxuKTt9ZmxvYXQgdW5wYWNrX21peF92ZWMyKGNvbnN0IHZlYzIgcGFja2VkVmFsdWUsY29uc3QgZmxvYXQgdCkge3JldHVybiBtaXgocGFja2VkVmFsdWVbMF0scGFja2VkVmFsdWVbMV0sdCk7fXZlYzQgdW5wYWNrX21peF9jb2xvcihjb25zdCB2ZWM0IHBhY2tlZENvbG9ycyxjb25zdCBmbG9hdCB0KSB7dmVjNCBtaW5Db2xvcj1kZWNvZGVfY29sb3IodmVjMihwYWNrZWRDb2xvcnNbMF0scGFja2VkQ29sb3JzWzFdKSk7dmVjNCBtYXhDb2xvcj1kZWNvZGVfY29sb3IodmVjMihwYWNrZWRDb2xvcnNbMl0scGFja2VkQ29sb3JzWzNdKSk7cmV0dXJuIG1peChtaW5Db2xvcixtYXhDb2xvcix0KTt9dmVjMiBnZXRfcGF0dGVybl9wb3MoY29uc3QgdmVjMiBwaXhlbF9jb29yZF91cHBlcixjb25zdCB2ZWMyIHBpeGVsX2Nvb3JkX2xvd2VyLGNvbnN0IHZlYzIgcGF0dGVybl9zaXplLGNvbnN0IGZsb2F0IHRpbGVfdW5pdHNfdG9fcGl4ZWxzLGNvbnN0IHZlYzIgcG9zKSB7dmVjMiBvZmZzZXQ9bW9kKG1vZChtb2QocGl4ZWxfY29vcmRfdXBwZXIscGF0dGVybl9zaXplKSoyNTYuMCxwYXR0ZXJuX3NpemUpKjI1Ni4wK3BpeGVsX2Nvb3JkX2xvd2VyLHBhdHRlcm5fc2l6ZSk7cmV0dXJuICh0aWxlX3VuaXRzX3RvX3BpeGVscypwb3Mrb2Zmc2V0KS9wYXR0ZXJuX3NpemU7fVwiKSxVZT1jaShcInVuaWZvcm0gdmVjNCB1X2NvbG9yO3VuaWZvcm0gZmxvYXQgdV9vcGFjaXR5O3ZvaWQgbWFpbigpIHtnbF9GcmFnQ29sb3I9dV9jb2xvcip1X29wYWNpdHk7XFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbmdsX0ZyYWdDb2xvcj12ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVwiLFwiYXR0cmlidXRlIHZlYzIgYV9wb3M7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3ZvaWQgbWFpbigpIHtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7fVwiKSxOZT1jaShcInVuaWZvcm0gdmVjMiB1X3BhdHRlcm5fdGxfYTt1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX2JyX2E7dW5pZm9ybSB2ZWMyIHVfcGF0dGVybl90bF9iO3VuaWZvcm0gdmVjMiB1X3BhdHRlcm5fYnJfYjt1bmlmb3JtIHZlYzIgdV90ZXhzaXplO3VuaWZvcm0gZmxvYXQgdV9taXg7dW5pZm9ybSBmbG9hdCB1X29wYWNpdHk7dW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTt2YXJ5aW5nIHZlYzIgdl9wb3NfYTt2YXJ5aW5nIHZlYzIgdl9wb3NfYjt2b2lkIG1haW4oKSB7dmVjMiBpbWFnZWNvb3JkPW1vZCh2X3Bvc19hLDEuMCk7dmVjMiBwb3M9bWl4KHVfcGF0dGVybl90bF9hL3VfdGV4c2l6ZSx1X3BhdHRlcm5fYnJfYS91X3RleHNpemUsaW1hZ2Vjb29yZCk7dmVjNCBjb2xvcjE9dGV4dHVyZTJEKHVfaW1hZ2UscG9zKTt2ZWMyIGltYWdlY29vcmRfYj1tb2Qodl9wb3NfYiwxLjApO3ZlYzIgcG9zMj1taXgodV9wYXR0ZXJuX3RsX2IvdV90ZXhzaXplLHVfcGF0dGVybl9icl9iL3VfdGV4c2l6ZSxpbWFnZWNvb3JkX2IpO3ZlYzQgY29sb3IyPXRleHR1cmUyRCh1X2ltYWdlLHBvczIpO2dsX0ZyYWdDb2xvcj1taXgoY29sb3IxLGNvbG9yMix1X21peCkqdV9vcGFjaXR5O1xcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG5nbF9GcmFnQ29sb3I9dmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cIixcInVuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3NpemVfYTt1bmlmb3JtIHZlYzIgdV9wYXR0ZXJuX3NpemVfYjt1bmlmb3JtIHZlYzIgdV9waXhlbF9jb29yZF91cHBlcjt1bmlmb3JtIHZlYzIgdV9waXhlbF9jb29yZF9sb3dlcjt1bmlmb3JtIGZsb2F0IHVfc2NhbGVfYTt1bmlmb3JtIGZsb2F0IHVfc2NhbGVfYjt1bmlmb3JtIGZsb2F0IHVfdGlsZV91bml0c190b19waXhlbHM7YXR0cmlidXRlIHZlYzIgYV9wb3M7dmFyeWluZyB2ZWMyIHZfcG9zX2E7dmFyeWluZyB2ZWMyIHZfcG9zX2I7dm9pZCBtYWluKCkge2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3MsMCwxKTt2X3Bvc19hPWdldF9wYXR0ZXJuX3Bvcyh1X3BpeGVsX2Nvb3JkX3VwcGVyLHVfcGl4ZWxfY29vcmRfbG93ZXIsdV9zY2FsZV9hKnVfcGF0dGVybl9zaXplX2EsdV90aWxlX3VuaXRzX3RvX3BpeGVscyxhX3Bvcyk7dl9wb3NfYj1nZXRfcGF0dGVybl9wb3ModV9waXhlbF9jb29yZF91cHBlcix1X3BpeGVsX2Nvb3JkX2xvd2VyLHVfc2NhbGVfYip1X3BhdHRlcm5fc2l6ZV9iLHVfdGlsZV91bml0c190b19waXhlbHMsYV9wb3MpO31cIiksWmU9Y2koXCJ2YXJ5aW5nIHZlYzMgdl9kYXRhO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbWVkaXVtcCBmbG9hdCByYWRpdXNcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IHN0cm9rZV9jb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbWVkaXVtcCBmbG9hdCBzdHJva2Vfd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgc3Ryb2tlX29wYWNpdHlcXG52b2lkIG1haW4oKSB7XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgcmFkaXVzXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBibHVyXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBzdHJva2VfY29sb3JcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IHN0cm9rZV93aWR0aFxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgc3Ryb2tlX29wYWNpdHlcXG52ZWMyIGV4dHJ1ZGU9dl9kYXRhLnh5O2Zsb2F0IGV4dHJ1ZGVfbGVuZ3RoPWxlbmd0aChleHRydWRlKTtsb3dwIGZsb2F0IGFudGlhbGlhc2JsdXI9dl9kYXRhLno7ZmxvYXQgYW50aWFsaWFzZWRfYmx1cj0tbWF4KGJsdXIsYW50aWFsaWFzYmx1cik7ZmxvYXQgb3BhY2l0eV90PXNtb290aHN0ZXAoMC4wLGFudGlhbGlhc2VkX2JsdXIsZXh0cnVkZV9sZW5ndGgtMS4wKTtmbG9hdCBjb2xvcl90PXN0cm9rZV93aWR0aCA8IDAuMDEgPyAwLjAgOiBzbW9vdGhzdGVwKGFudGlhbGlhc2VkX2JsdXIsMC4wLGV4dHJ1ZGVfbGVuZ3RoLXJhZGl1cy8ocmFkaXVzK3N0cm9rZV93aWR0aCkpO2dsX0ZyYWdDb2xvcj1vcGFjaXR5X3QqbWl4KGNvbG9yKm9wYWNpdHksc3Ryb2tlX2NvbG9yKnN0cm9rZV9vcGFjaXR5LGNvbG9yX3QpO1xcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG5nbF9GcmFnQ29sb3I9dmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cIixcInVuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIGJvb2wgdV9zY2FsZV93aXRoX21hcDt1bmlmb3JtIGJvb2wgdV9waXRjaF93aXRoX21hcDt1bmlmb3JtIHZlYzIgdV9leHRydWRlX3NjYWxlO3VuaWZvcm0gbG93cCBmbG9hdCB1X2RldmljZV9waXhlbF9yYXRpbzt1bmlmb3JtIGhpZ2hwIGZsb2F0IHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZTthdHRyaWJ1dGUgdmVjMiBhX3Bvczt2YXJ5aW5nIHZlYzMgdl9kYXRhO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbWVkaXVtcCBmbG9hdCByYWRpdXNcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IHN0cm9rZV9jb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbWVkaXVtcCBmbG9hdCBzdHJva2Vfd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgc3Ryb2tlX29wYWNpdHlcXG52b2lkIG1haW4odm9pZCkge1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIHZlYzQgY29sb3JcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IHJhZGl1c1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIHZlYzQgc3Ryb2tlX2NvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCBmbG9hdCBzdHJva2Vfd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IHN0cm9rZV9vcGFjaXR5XFxudmVjMiBleHRydWRlPXZlYzIobW9kKGFfcG9zLDIuMCkqMi4wLTEuMCk7dmVjMiBjaXJjbGVfY2VudGVyPWZsb29yKGFfcG9zKjAuNSk7aWYgKHVfcGl0Y2hfd2l0aF9tYXApIHt2ZWMyIGNvcm5lcl9wb3NpdGlvbj1jaXJjbGVfY2VudGVyO2lmICh1X3NjYWxlX3dpdGhfbWFwKSB7Y29ybmVyX3Bvc2l0aW9uKz1leHRydWRlKihyYWRpdXMrc3Ryb2tlX3dpZHRoKSp1X2V4dHJ1ZGVfc2NhbGU7fSBlbHNlIHt2ZWM0IHByb2plY3RlZF9jZW50ZXI9dV9tYXRyaXgqdmVjNChjaXJjbGVfY2VudGVyLDAsMSk7Y29ybmVyX3Bvc2l0aW9uKz1leHRydWRlKihyYWRpdXMrc3Ryb2tlX3dpZHRoKSp1X2V4dHJ1ZGVfc2NhbGUqKHByb2plY3RlZF9jZW50ZXIudy91X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2UpO31nbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGNvcm5lcl9wb3NpdGlvbiwwLDEpO30gZWxzZSB7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChjaXJjbGVfY2VudGVyLDAsMSk7aWYgKHVfc2NhbGVfd2l0aF9tYXApIHtnbF9Qb3NpdGlvbi54eSs9ZXh0cnVkZSoocmFkaXVzK3N0cm9rZV93aWR0aCkqdV9leHRydWRlX3NjYWxlKnVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZTt9IGVsc2Uge2dsX1Bvc2l0aW9uLnh5Kz1leHRydWRlKihyYWRpdXMrc3Ryb2tlX3dpZHRoKSp1X2V4dHJ1ZGVfc2NhbGUqZ2xfUG9zaXRpb24udzt9fWxvd3AgZmxvYXQgYW50aWFsaWFzYmx1cj0xLjAvdV9kZXZpY2VfcGl4ZWxfcmF0aW8vKHJhZGl1cytzdHJva2Vfd2lkdGgpO3ZfZGF0YT12ZWMzKGV4dHJ1ZGUueCxleHRydWRlLnksYW50aWFsaWFzYmx1cik7fVwiKSxqZT1jaShcInZvaWQgbWFpbigpIHtnbF9GcmFnQ29sb3I9dmVjNCgxLjApO31cIixcImF0dHJpYnV0ZSB2ZWMyIGFfcG9zO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt2b2lkIG1haW4oKSB7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO31cIikscWU9Y2koXCJ1bmlmb3JtIGhpZ2hwIGZsb2F0IHVfaW50ZW5zaXR5O3ZhcnlpbmcgdmVjMiB2X2V4dHJ1ZGU7XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCBmbG9hdCB3ZWlnaHRcXG4jZGVmaW5lIEdBVVNTX0NPRUYgMC4zOTg5NDIyODA0MDE0MzI3XFxudm9pZCBtYWluKCkge1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIGZsb2F0IHdlaWdodFxcbmZsb2F0IGQ9LTAuNSozLjAqMy4wKmRvdCh2X2V4dHJ1ZGUsdl9leHRydWRlKTtmbG9hdCB2YWw9d2VpZ2h0KnVfaW50ZW5zaXR5KkdBVVNTX0NPRUYqZXhwKGQpO2dsX0ZyYWdDb2xvcj12ZWM0KHZhbCwxLjAsMS4wLDEuMCk7XFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbmdsX0ZyYWdDb2xvcj12ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVwiLFwidW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gZmxvYXQgdV9leHRydWRlX3NjYWxlO3VuaWZvcm0gZmxvYXQgdV9vcGFjaXR5O3VuaWZvcm0gZmxvYXQgdV9pbnRlbnNpdHk7YXR0cmlidXRlIHZlYzIgYV9wb3M7dmFyeWluZyB2ZWMyIHZfZXh0cnVkZTtcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIGZsb2F0IHdlaWdodFxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbWVkaXVtcCBmbG9hdCByYWRpdXNcXG5jb25zdCBoaWdocCBmbG9hdCBaRVJPPTEuMC8yNTUuMC8xNi4wO1xcbiNkZWZpbmUgR0FVU1NfQ09FRiAwLjM5ODk0MjI4MDQwMTQzMjdcXG52b2lkIG1haW4odm9pZCkge1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIGZsb2F0IHdlaWdodFxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgcmFkaXVzXFxudmVjMiB1bnNjYWxlZF9leHRydWRlPXZlYzIobW9kKGFfcG9zLDIuMCkqMi4wLTEuMCk7ZmxvYXQgUz1zcXJ0KC0yLjAqbG9nKFpFUk8vd2VpZ2h0L3VfaW50ZW5zaXR5L0dBVVNTX0NPRUYpKS8zLjA7dl9leHRydWRlPVMqdW5zY2FsZWRfZXh0cnVkZTt2ZWMyIGV4dHJ1ZGU9dl9leHRydWRlKnJhZGl1cyp1X2V4dHJ1ZGVfc2NhbGU7dmVjNCBwb3M9dmVjNChmbG9vcihhX3BvcyowLjUpK2V4dHJ1ZGUsMCwxKTtnbF9Qb3NpdGlvbj11X21hdHJpeCpwb3M7fVwiKSxWZT1jaShcInVuaWZvcm0gc2FtcGxlcjJEIHVfaW1hZ2U7dW5pZm9ybSBzYW1wbGVyMkQgdV9jb2xvcl9yYW1wO3VuaWZvcm0gZmxvYXQgdV9vcGFjaXR5O3ZhcnlpbmcgdmVjMiB2X3Bvczt2b2lkIG1haW4oKSB7ZmxvYXQgdD10ZXh0dXJlMkQodV9pbWFnZSx2X3Bvcykucjt2ZWM0IGNvbG9yPXRleHR1cmUyRCh1X2NvbG9yX3JhbXAsdmVjMih0LDAuNSkpO2dsX0ZyYWdDb2xvcj1jb2xvcip1X29wYWNpdHk7XFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbmdsX0ZyYWdDb2xvcj12ZWM0KDAuMCk7XFxuI2VuZGlmXFxufVwiLFwidW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X3dvcmxkO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO3ZhcnlpbmcgdmVjMiB2X3Bvczt2b2lkIG1haW4oKSB7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3Bvcyp1X3dvcmxkLDAsMSk7dl9wb3MueD1hX3Bvcy54O3ZfcG9zLnk9MS4wLWFfcG9zLnk7fVwiKSxHZT1jaShcInZhcnlpbmcgZmxvYXQgdl9wbGFjZWQ7dmFyeWluZyBmbG9hdCB2X25vdFVzZWQ7dm9pZCBtYWluKCkge2Zsb2F0IGFscGhhPTAuNTtnbF9GcmFnQ29sb3I9dmVjNCgxLjAsMC4wLDAuMCwxLjApKmFscGhhO2lmICh2X3BsYWNlZCA+IDAuNSkge2dsX0ZyYWdDb2xvcj12ZWM0KDAuMCwwLjAsMS4wLDAuNSkqYWxwaGE7fWlmICh2X25vdFVzZWQgPiAwLjUpIHtnbF9GcmFnQ29sb3IqPS4xO319XCIsXCJhdHRyaWJ1dGUgdmVjMiBhX3BvczthdHRyaWJ1dGUgdmVjMiBhX2FuY2hvcl9wb3M7YXR0cmlidXRlIHZlYzIgYV9leHRydWRlO2F0dHJpYnV0ZSB2ZWMyIGFfcGxhY2VkO2F0dHJpYnV0ZSB2ZWMyIGFfc2hpZnQ7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X2V4dHJ1ZGVfc2NhbGU7dW5pZm9ybSBmbG9hdCB1X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2U7dmFyeWluZyBmbG9hdCB2X3BsYWNlZDt2YXJ5aW5nIGZsb2F0IHZfbm90VXNlZDt2b2lkIG1haW4oKSB7dmVjNCBwcm9qZWN0ZWRQb2ludD11X21hdHJpeCp2ZWM0KGFfYW5jaG9yX3BvcywwLDEpO2hpZ2hwIGZsb2F0IGNhbWVyYV90b19hbmNob3JfZGlzdGFuY2U9cHJvamVjdGVkUG9pbnQudztoaWdocCBmbG9hdCBjb2xsaXNpb25fcGVyc3BlY3RpdmVfcmF0aW89Y2xhbXAoMC41KzAuNSoodV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlL2NhbWVyYV90b19hbmNob3JfZGlzdGFuY2UpLDAuMCw0LjApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3MsMC4wLDEuMCk7Z2xfUG9zaXRpb24ueHkrPShhX2V4dHJ1ZGUrYV9zaGlmdCkqdV9leHRydWRlX3NjYWxlKmdsX1Bvc2l0aW9uLncqY29sbGlzaW9uX3BlcnNwZWN0aXZlX3JhdGlvO3ZfcGxhY2VkPWFfcGxhY2VkLng7dl9ub3RVc2VkPWFfcGxhY2VkLnk7fVwiKSxXZT1jaShcInVuaWZvcm0gZmxvYXQgdV9vdmVyc2NhbGVfZmFjdG9yO3ZhcnlpbmcgZmxvYXQgdl9wbGFjZWQ7dmFyeWluZyBmbG9hdCB2X25vdFVzZWQ7dmFyeWluZyBmbG9hdCB2X3JhZGl1czt2YXJ5aW5nIHZlYzIgdl9leHRydWRlO3ZhcnlpbmcgdmVjMiB2X2V4dHJ1ZGVfc2NhbGU7dm9pZCBtYWluKCkge2Zsb2F0IGFscGhhPTAuNTt2ZWM0IGNvbG9yPXZlYzQoMS4wLDAuMCwwLjAsMS4wKSphbHBoYTtpZiAodl9wbGFjZWQgPiAwLjUpIHtjb2xvcj12ZWM0KDAuMCwwLjAsMS4wLDAuNSkqYWxwaGE7fWlmICh2X25vdFVzZWQgPiAwLjUpIHtjb2xvcio9LjI7fWZsb2F0IGV4dHJ1ZGVfc2NhbGVfbGVuZ3RoPWxlbmd0aCh2X2V4dHJ1ZGVfc2NhbGUpO2Zsb2F0IGV4dHJ1ZGVfbGVuZ3RoPWxlbmd0aCh2X2V4dHJ1ZGUpKmV4dHJ1ZGVfc2NhbGVfbGVuZ3RoO2Zsb2F0IHN0cm9rZV93aWR0aD0xNS4wKmV4dHJ1ZGVfc2NhbGVfbGVuZ3RoL3Vfb3ZlcnNjYWxlX2ZhY3RvcjtmbG9hdCByYWRpdXM9dl9yYWRpdXMqZXh0cnVkZV9zY2FsZV9sZW5ndGg7ZmxvYXQgZGlzdGFuY2VfdG9fZWRnZT1hYnMoZXh0cnVkZV9sZW5ndGgtcmFkaXVzKTtmbG9hdCBvcGFjaXR5X3Q9c21vb3Roc3RlcCgtc3Ryb2tlX3dpZHRoLDAuMCwtZGlzdGFuY2VfdG9fZWRnZSk7Z2xfRnJhZ0NvbG9yPW9wYWNpdHlfdCpjb2xvcjt9XCIsXCJhdHRyaWJ1dGUgdmVjMiBhX3BvczthdHRyaWJ1dGUgdmVjMiBhX2FuY2hvcl9wb3M7YXR0cmlidXRlIHZlYzIgYV9leHRydWRlO2F0dHJpYnV0ZSB2ZWMyIGFfcGxhY2VkO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIHZlYzIgdV9leHRydWRlX3NjYWxlO3VuaWZvcm0gZmxvYXQgdV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlO3ZhcnlpbmcgZmxvYXQgdl9wbGFjZWQ7dmFyeWluZyBmbG9hdCB2X25vdFVzZWQ7dmFyeWluZyBmbG9hdCB2X3JhZGl1czt2YXJ5aW5nIHZlYzIgdl9leHRydWRlO3ZhcnlpbmcgdmVjMiB2X2V4dHJ1ZGVfc2NhbGU7dm9pZCBtYWluKCkge3ZlYzQgcHJvamVjdGVkUG9pbnQ9dV9tYXRyaXgqdmVjNChhX2FuY2hvcl9wb3MsMCwxKTtoaWdocCBmbG9hdCBjYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlPXByb2plY3RlZFBvaW50Lnc7aGlnaHAgZmxvYXQgY29sbGlzaW9uX3BlcnNwZWN0aXZlX3JhdGlvPWNsYW1wKDAuNSswLjUqKHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZS9jYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlKSwwLjAsNC4wKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAuMCwxLjApO2hpZ2hwIGZsb2F0IHBhZGRpbmdfZmFjdG9yPTEuMjtnbF9Qb3NpdGlvbi54eSs9YV9leHRydWRlKnVfZXh0cnVkZV9zY2FsZSpwYWRkaW5nX2ZhY3RvcipnbF9Qb3NpdGlvbi53KmNvbGxpc2lvbl9wZXJzcGVjdGl2ZV9yYXRpbzt2X3BsYWNlZD1hX3BsYWNlZC54O3Zfbm90VXNlZD1hX3BsYWNlZC55O3ZfcmFkaXVzPWFicyhhX2V4dHJ1ZGUueSk7dl9leHRydWRlPWFfZXh0cnVkZSpwYWRkaW5nX2ZhY3Rvcjt2X2V4dHJ1ZGVfc2NhbGU9dV9leHRydWRlX3NjYWxlKnVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZSpjb2xsaXNpb25fcGVyc3BlY3RpdmVfcmF0aW87fVwiKSxYZT1jaShcInVuaWZvcm0gaGlnaHAgdmVjNCB1X2NvbG9yO3ZvaWQgbWFpbigpIHtnbF9GcmFnQ29sb3I9dV9jb2xvcjt9XCIsXCJhdHRyaWJ1dGUgdmVjMiBhX3Bvczt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dm9pZCBtYWluKCkge2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQoYV9wb3MsMCwxKTt9XCIpLEhlPWNpKFwiI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IGNvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG52b2lkIG1haW4oKSB7XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcbmdsX0ZyYWdDb2xvcj1jb2xvcipvcGFjaXR5O1xcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG5nbF9GcmFnQ29sb3I9dmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cIixcImF0dHJpYnV0ZSB2ZWMyIGFfcG9zO3VuaWZvcm0gbWF0NCB1X21hdHJpeDtcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IGNvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuZ2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO31cIiksS2U9Y2koXCJ2YXJ5aW5nIHZlYzIgdl9wb3M7XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IG91dGxpbmVfY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IG91dGxpbmVfY29sb3JcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5mbG9hdCBkaXN0PWxlbmd0aCh2X3Bvcy1nbF9GcmFnQ29vcmQueHkpO2Zsb2F0IGFscGhhPTEuMC1zbW9vdGhzdGVwKDAuMCwxLjAsZGlzdCk7Z2xfRnJhZ0NvbG9yPW91dGxpbmVfY29sb3IqKGFscGhhKm9wYWNpdHkpO1xcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG5nbF9GcmFnQ29sb3I9dmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cIixcImF0dHJpYnV0ZSB2ZWMyIGFfcG9zO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIHZlYzIgdV93b3JsZDt2YXJ5aW5nIHZlYzIgdl9wb3M7XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IG91dGxpbmVfY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IG91dGxpbmVfY29sb3JcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5nbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7dl9wb3M9KGdsX1Bvc2l0aW9uLnh5L2dsX1Bvc2l0aW9uLncrMS4wKS8yLjAqdV93b3JsZDt9XCIpLFllPWNpKFwidW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTt1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO3VuaWZvcm0gZmxvYXQgdV9mYWRlO3ZhcnlpbmcgdmVjMiB2X3Bvc19hO3ZhcnlpbmcgdmVjMiB2X3Bvc19iO3ZhcnlpbmcgdmVjMiB2X3BvcztcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCB2ZWM0IHBhdHRlcm5fZnJvbVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCB2ZWM0IHBhdHRlcm5fdG9cXG52b2lkIG1haW4oKSB7XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCB2ZWM0IHBhdHRlcm5fZnJvbVxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgdmVjNCBwYXR0ZXJuX3RvXFxudmVjMiBwYXR0ZXJuX3RsX2E9cGF0dGVybl9mcm9tLnh5O3ZlYzIgcGF0dGVybl9icl9hPXBhdHRlcm5fZnJvbS56dzt2ZWMyIHBhdHRlcm5fdGxfYj1wYXR0ZXJuX3RvLnh5O3ZlYzIgcGF0dGVybl9icl9iPXBhdHRlcm5fdG8uenc7dmVjMiBpbWFnZWNvb3JkPW1vZCh2X3Bvc19hLDEuMCk7dmVjMiBwb3M9bWl4KHBhdHRlcm5fdGxfYS91X3RleHNpemUscGF0dGVybl9icl9hL3VfdGV4c2l6ZSxpbWFnZWNvb3JkKTt2ZWM0IGNvbG9yMT10ZXh0dXJlMkQodV9pbWFnZSxwb3MpO3ZlYzIgaW1hZ2Vjb29yZF9iPW1vZCh2X3Bvc19iLDEuMCk7dmVjMiBwb3MyPW1peChwYXR0ZXJuX3RsX2IvdV90ZXhzaXplLHBhdHRlcm5fYnJfYi91X3RleHNpemUsaW1hZ2Vjb29yZF9iKTt2ZWM0IGNvbG9yMj10ZXh0dXJlMkQodV9pbWFnZSxwb3MyKTtmbG9hdCBkaXN0PWxlbmd0aCh2X3Bvcy1nbF9GcmFnQ29vcmQueHkpO2Zsb2F0IGFscGhhPTEuMC1zbW9vdGhzdGVwKDAuMCwxLjAsZGlzdCk7Z2xfRnJhZ0NvbG9yPW1peChjb2xvcjEsY29sb3IyLHVfZmFkZSkqYWxwaGEqb3BhY2l0eTtcXG4jaWZkZWYgT1ZFUkRSQVdfSU5TUEVDVE9SXFxuZ2xfRnJhZ0NvbG9yPXZlYzQoMS4wKTtcXG4jZW5kaWZcXG59XCIsXCJ1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSB2ZWMyIHVfd29ybGQ7dW5pZm9ybSB2ZWMyIHVfcGl4ZWxfY29vcmRfdXBwZXI7dW5pZm9ybSB2ZWMyIHVfcGl4ZWxfY29vcmRfbG93ZXI7dW5pZm9ybSB2ZWM0IHVfc2NhbGU7YXR0cmlidXRlIHZlYzIgYV9wb3M7dmFyeWluZyB2ZWMyIHZfcG9zX2E7dmFyeWluZyB2ZWMyIHZfcG9zX2I7dmFyeWluZyB2ZWMyIHZfcG9zO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIHZlYzQgcGF0dGVybl9mcm9tXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIHZlYzQgcGF0dGVybl90b1xcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIHZlYzQgcGF0dGVybl9mcm9tXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCB2ZWM0IHBhdHRlcm5fdG9cXG52ZWMyIHBhdHRlcm5fdGxfYT1wYXR0ZXJuX2Zyb20ueHk7dmVjMiBwYXR0ZXJuX2JyX2E9cGF0dGVybl9mcm9tLnp3O3ZlYzIgcGF0dGVybl90bF9iPXBhdHRlcm5fdG8ueHk7dmVjMiBwYXR0ZXJuX2JyX2I9cGF0dGVybl90by56dztmbG9hdCBwaXhlbFJhdGlvPXVfc2NhbGUueDtmbG9hdCB0aWxlUmF0aW89dV9zY2FsZS55O2Zsb2F0IGZyb21TY2FsZT11X3NjYWxlLno7ZmxvYXQgdG9TY2FsZT11X3NjYWxlLnc7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO3ZlYzIgZGlzcGxheV9zaXplX2E9dmVjMigocGF0dGVybl9icl9hLngtcGF0dGVybl90bF9hLngpL3BpeGVsUmF0aW8sKHBhdHRlcm5fYnJfYS55LXBhdHRlcm5fdGxfYS55KS9waXhlbFJhdGlvKTt2ZWMyIGRpc3BsYXlfc2l6ZV9iPXZlYzIoKHBhdHRlcm5fYnJfYi54LXBhdHRlcm5fdGxfYi54KS9waXhlbFJhdGlvLChwYXR0ZXJuX2JyX2IueS1wYXR0ZXJuX3RsX2IueSkvcGl4ZWxSYXRpbyk7dl9wb3NfYT1nZXRfcGF0dGVybl9wb3ModV9waXhlbF9jb29yZF91cHBlcix1X3BpeGVsX2Nvb3JkX2xvd2VyLGZyb21TY2FsZSpkaXNwbGF5X3NpemVfYSx0aWxlUmF0aW8sYV9wb3MpO3ZfcG9zX2I9Z2V0X3BhdHRlcm5fcG9zKHVfcGl4ZWxfY29vcmRfdXBwZXIsdV9waXhlbF9jb29yZF9sb3dlcix0b1NjYWxlKmRpc3BsYXlfc2l6ZV9iLHRpbGVSYXRpbyxhX3Bvcyk7dl9wb3M9KGdsX1Bvc2l0aW9uLnh5L2dsX1Bvc2l0aW9uLncrMS4wKS8yLjAqdV93b3JsZDt9XCIpLEplPWNpKFwidW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTt1bmlmb3JtIGZsb2F0IHVfZmFkZTt1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO3ZhcnlpbmcgdmVjMiB2X3Bvc19hO3ZhcnlpbmcgdmVjMiB2X3Bvc19iO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIHZlYzQgcGF0dGVybl9mcm9tXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIHZlYzQgcGF0dGVybl90b1xcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIHZlYzQgcGF0dGVybl9mcm9tXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCB2ZWM0IHBhdHRlcm5fdG9cXG52ZWMyIHBhdHRlcm5fdGxfYT1wYXR0ZXJuX2Zyb20ueHk7dmVjMiBwYXR0ZXJuX2JyX2E9cGF0dGVybl9mcm9tLnp3O3ZlYzIgcGF0dGVybl90bF9iPXBhdHRlcm5fdG8ueHk7dmVjMiBwYXR0ZXJuX2JyX2I9cGF0dGVybl90by56dzt2ZWMyIGltYWdlY29vcmQ9bW9kKHZfcG9zX2EsMS4wKTt2ZWMyIHBvcz1taXgocGF0dGVybl90bF9hL3VfdGV4c2l6ZSxwYXR0ZXJuX2JyX2EvdV90ZXhzaXplLGltYWdlY29vcmQpO3ZlYzQgY29sb3IxPXRleHR1cmUyRCh1X2ltYWdlLHBvcyk7dmVjMiBpbWFnZWNvb3JkX2I9bW9kKHZfcG9zX2IsMS4wKTt2ZWMyIHBvczI9bWl4KHBhdHRlcm5fdGxfYi91X3RleHNpemUscGF0dGVybl9icl9iL3VfdGV4c2l6ZSxpbWFnZWNvb3JkX2IpO3ZlYzQgY29sb3IyPXRleHR1cmUyRCh1X2ltYWdlLHBvczIpO2dsX0ZyYWdDb2xvcj1taXgoY29sb3IxLGNvbG9yMix1X2ZhZGUpKm9wYWNpdHk7XFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbmdsX0ZyYWdDb2xvcj12ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVwiLFwidW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X3BpeGVsX2Nvb3JkX3VwcGVyO3VuaWZvcm0gdmVjMiB1X3BpeGVsX2Nvb3JkX2xvd2VyO3VuaWZvcm0gdmVjNCB1X3NjYWxlO2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO3ZhcnlpbmcgdmVjMiB2X3Bvc19hO3ZhcnlpbmcgdmVjMiB2X3Bvc19iO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIHZlYzQgcGF0dGVybl9mcm9tXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIHZlYzQgcGF0dGVybl90b1xcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIHZlYzQgcGF0dGVybl9mcm9tXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCB2ZWM0IHBhdHRlcm5fdG9cXG52ZWMyIHBhdHRlcm5fdGxfYT1wYXR0ZXJuX2Zyb20ueHk7dmVjMiBwYXR0ZXJuX2JyX2E9cGF0dGVybl9mcm9tLnp3O3ZlYzIgcGF0dGVybl90bF9iPXBhdHRlcm5fdG8ueHk7dmVjMiBwYXR0ZXJuX2JyX2I9cGF0dGVybl90by56dztmbG9hdCBwaXhlbFJhdGlvPXVfc2NhbGUueDtmbG9hdCB0aWxlWm9vbVJhdGlvPXVfc2NhbGUueTtmbG9hdCBmcm9tU2NhbGU9dV9zY2FsZS56O2Zsb2F0IHRvU2NhbGU9dV9zY2FsZS53O3ZlYzIgZGlzcGxheV9zaXplX2E9dmVjMigocGF0dGVybl9icl9hLngtcGF0dGVybl90bF9hLngpL3BpeGVsUmF0aW8sKHBhdHRlcm5fYnJfYS55LXBhdHRlcm5fdGxfYS55KS9waXhlbFJhdGlvKTt2ZWMyIGRpc3BsYXlfc2l6ZV9iPXZlYzIoKHBhdHRlcm5fYnJfYi54LXBhdHRlcm5fdGxfYi54KS9waXhlbFJhdGlvLChwYXR0ZXJuX2JyX2IueS1wYXR0ZXJuX3RsX2IueSkvcGl4ZWxSYXRpbyk7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO3ZfcG9zX2E9Z2V0X3BhdHRlcm5fcG9zKHVfcGl4ZWxfY29vcmRfdXBwZXIsdV9waXhlbF9jb29yZF9sb3dlcixmcm9tU2NhbGUqZGlzcGxheV9zaXplX2EsdGlsZVpvb21SYXRpbyxhX3Bvcyk7dl9wb3NfYj1nZXRfcGF0dGVybl9wb3ModV9waXhlbF9jb29yZF91cHBlcix1X3BpeGVsX2Nvb3JkX2xvd2VyLHRvU2NhbGUqZGlzcGxheV9zaXplX2IsdGlsZVpvb21SYXRpbyxhX3Bvcyk7fVwiKSxRZT1jaShcInZhcnlpbmcgdmVjNCB2X2NvbG9yO3ZvaWQgbWFpbigpIHtnbF9GcmFnQ29sb3I9dl9jb2xvcjtcXG4jaWZkZWYgT1ZFUkRSQVdfSU5TUEVDVE9SXFxuZ2xfRnJhZ0NvbG9yPXZlYzQoMS4wKTtcXG4jZW5kaWZcXG59XCIsXCJ1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSB2ZWMzIHVfbGlnaHRjb2xvcjt1bmlmb3JtIGxvd3AgdmVjMyB1X2xpZ2h0cG9zO3VuaWZvcm0gbG93cCBmbG9hdCB1X2xpZ2h0aW50ZW5zaXR5O3VuaWZvcm0gZmxvYXQgdV92ZXJ0aWNhbF9ncmFkaWVudDt1bmlmb3JtIGxvd3AgZmxvYXQgdV9vcGFjaXR5O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO2F0dHJpYnV0ZSB2ZWM0IGFfbm9ybWFsX2VkO3ZhcnlpbmcgdmVjNCB2X2NvbG9yO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgZmxvYXQgYmFzZVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgZmxvYXQgaGVpZ2h0XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IGNvbG9yXFxudm9pZCBtYWluKCkge1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIGZsb2F0IGJhc2VcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCBmbG9hdCBoZWlnaHRcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IGNvbG9yXFxudmVjMyBub3JtYWw9YV9ub3JtYWxfZWQueHl6O2Jhc2U9bWF4KDAuMCxiYXNlKTtoZWlnaHQ9bWF4KDAuMCxoZWlnaHQpO2Zsb2F0IHQ9bW9kKG5vcm1hbC54LDIuMCk7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3Bvcyx0ID4gMC4wID8gaGVpZ2h0IDogYmFzZSwxKTtmbG9hdCBjb2xvcnZhbHVlPWNvbG9yLnIqMC4yMTI2K2NvbG9yLmcqMC43MTUyK2NvbG9yLmIqMC4wNzIyO3ZfY29sb3I9dmVjNCgwLjAsMC4wLDAuMCwxLjApO3ZlYzQgYW1iaWVudGxpZ2h0PXZlYzQoMC4wMywwLjAzLDAuMDMsMS4wKTtjb2xvcis9YW1iaWVudGxpZ2h0O2Zsb2F0IGRpcmVjdGlvbmFsPWNsYW1wKGRvdChub3JtYWwvMTYzODQuMCx1X2xpZ2h0cG9zKSwwLjAsMS4wKTtkaXJlY3Rpb25hbD1taXgoKDEuMC11X2xpZ2h0aW50ZW5zaXR5KSxtYXgoKDEuMC1jb2xvcnZhbHVlK3VfbGlnaHRpbnRlbnNpdHkpLDEuMCksZGlyZWN0aW9uYWwpO2lmIChub3JtYWwueSAhPTAuMCkge2RpcmVjdGlvbmFsKj0oKDEuMC11X3ZlcnRpY2FsX2dyYWRpZW50KSsodV92ZXJ0aWNhbF9ncmFkaWVudCpjbGFtcCgodCtiYXNlKSpwb3coaGVpZ2h0LzE1MC4wLDAuNSksbWl4KDAuNywwLjk4LDEuMC11X2xpZ2h0aW50ZW5zaXR5KSwxLjApKSk7fXZfY29sb3Iucis9Y2xhbXAoY29sb3IucipkaXJlY3Rpb25hbCp1X2xpZ2h0Y29sb3IucixtaXgoMC4wLDAuMywxLjAtdV9saWdodGNvbG9yLnIpLDEuMCk7dl9jb2xvci5nKz1jbGFtcChjb2xvci5nKmRpcmVjdGlvbmFsKnVfbGlnaHRjb2xvci5nLG1peCgwLjAsMC4zLDEuMC11X2xpZ2h0Y29sb3IuZyksMS4wKTt2X2NvbG9yLmIrPWNsYW1wKGNvbG9yLmIqZGlyZWN0aW9uYWwqdV9saWdodGNvbG9yLmIsbWl4KDAuMCwwLjMsMS4wLXVfbGlnaHRjb2xvci5iKSwxLjApO3ZfY29sb3IqPXVfb3BhY2l0eTt9XCIpLCRlPWNpKFwidW5pZm9ybSB2ZWMyIHVfdGV4c2l6ZTt1bmlmb3JtIGZsb2F0IHVfZmFkZTt1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO3ZhcnlpbmcgdmVjMiB2X3Bvc19hO3ZhcnlpbmcgdmVjMiB2X3Bvc19iO3ZhcnlpbmcgdmVjNCB2X2xpZ2h0aW5nO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBiYXNlXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGhlaWdodFxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCB2ZWM0IHBhdHRlcm5fZnJvbVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCB2ZWM0IHBhdHRlcm5fdG9cXG52b2lkIG1haW4oKSB7XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBiYXNlXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBoZWlnaHRcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIHZlYzQgcGF0dGVybl9mcm9tXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCB2ZWM0IHBhdHRlcm5fdG9cXG52ZWMyIHBhdHRlcm5fdGxfYT1wYXR0ZXJuX2Zyb20ueHk7dmVjMiBwYXR0ZXJuX2JyX2E9cGF0dGVybl9mcm9tLnp3O3ZlYzIgcGF0dGVybl90bF9iPXBhdHRlcm5fdG8ueHk7dmVjMiBwYXR0ZXJuX2JyX2I9cGF0dGVybl90by56dzt2ZWMyIGltYWdlY29vcmQ9bW9kKHZfcG9zX2EsMS4wKTt2ZWMyIHBvcz1taXgocGF0dGVybl90bF9hL3VfdGV4c2l6ZSxwYXR0ZXJuX2JyX2EvdV90ZXhzaXplLGltYWdlY29vcmQpO3ZlYzQgY29sb3IxPXRleHR1cmUyRCh1X2ltYWdlLHBvcyk7dmVjMiBpbWFnZWNvb3JkX2I9bW9kKHZfcG9zX2IsMS4wKTt2ZWMyIHBvczI9bWl4KHBhdHRlcm5fdGxfYi91X3RleHNpemUscGF0dGVybl9icl9iL3VfdGV4c2l6ZSxpbWFnZWNvb3JkX2IpO3ZlYzQgY29sb3IyPXRleHR1cmUyRCh1X2ltYWdlLHBvczIpO3ZlYzQgbWl4ZWRDb2xvcj1taXgoY29sb3IxLGNvbG9yMix1X2ZhZGUpO2dsX0ZyYWdDb2xvcj1taXhlZENvbG9yKnZfbGlnaHRpbmc7XFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbmdsX0ZyYWdDb2xvcj12ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVwiLFwidW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X3BpeGVsX2Nvb3JkX3VwcGVyO3VuaWZvcm0gdmVjMiB1X3BpeGVsX2Nvb3JkX2xvd2VyO3VuaWZvcm0gZmxvYXQgdV9oZWlnaHRfZmFjdG9yO3VuaWZvcm0gdmVjNCB1X3NjYWxlO3VuaWZvcm0gZmxvYXQgdV92ZXJ0aWNhbF9ncmFkaWVudDt1bmlmb3JtIGxvd3AgZmxvYXQgdV9vcGFjaXR5O3VuaWZvcm0gdmVjMyB1X2xpZ2h0Y29sb3I7dW5pZm9ybSBsb3dwIHZlYzMgdV9saWdodHBvczt1bmlmb3JtIGxvd3AgZmxvYXQgdV9saWdodGludGVuc2l0eTthdHRyaWJ1dGUgdmVjMiBhX3BvczthdHRyaWJ1dGUgdmVjNCBhX25vcm1hbF9lZDt2YXJ5aW5nIHZlYzIgdl9wb3NfYTt2YXJ5aW5nIHZlYzIgdl9wb3NfYjt2YXJ5aW5nIHZlYzQgdl9saWdodGluZztcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmFzZVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBoZWlnaHRcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgdmVjNCBwYXR0ZXJuX2Zyb21cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgdmVjNCBwYXR0ZXJuX3RvXFxudm9pZCBtYWluKCkge1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmFzZVxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgaGVpZ2h0XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCB2ZWM0IHBhdHRlcm5fZnJvbVxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgdmVjNCBwYXR0ZXJuX3RvXFxudmVjMiBwYXR0ZXJuX3RsX2E9cGF0dGVybl9mcm9tLnh5O3ZlYzIgcGF0dGVybl9icl9hPXBhdHRlcm5fZnJvbS56dzt2ZWMyIHBhdHRlcm5fdGxfYj1wYXR0ZXJuX3RvLnh5O3ZlYzIgcGF0dGVybl9icl9iPXBhdHRlcm5fdG8uenc7ZmxvYXQgcGl4ZWxSYXRpbz11X3NjYWxlLng7ZmxvYXQgdGlsZVJhdGlvPXVfc2NhbGUueTtmbG9hdCBmcm9tU2NhbGU9dV9zY2FsZS56O2Zsb2F0IHRvU2NhbGU9dV9zY2FsZS53O3ZlYzMgbm9ybWFsPWFfbm9ybWFsX2VkLnh5ejtmbG9hdCBlZGdlZGlzdGFuY2U9YV9ub3JtYWxfZWQudzt2ZWMyIGRpc3BsYXlfc2l6ZV9hPXZlYzIoKHBhdHRlcm5fYnJfYS54LXBhdHRlcm5fdGxfYS54KS9waXhlbFJhdGlvLChwYXR0ZXJuX2JyX2EueS1wYXR0ZXJuX3RsX2EueSkvcGl4ZWxSYXRpbyk7dmVjMiBkaXNwbGF5X3NpemVfYj12ZWMyKChwYXR0ZXJuX2JyX2IueC1wYXR0ZXJuX3RsX2IueCkvcGl4ZWxSYXRpbywocGF0dGVybl9icl9iLnktcGF0dGVybl90bF9iLnkpL3BpeGVsUmF0aW8pO2Jhc2U9bWF4KDAuMCxiYXNlKTtoZWlnaHQ9bWF4KDAuMCxoZWlnaHQpO2Zsb2F0IHQ9bW9kKG5vcm1hbC54LDIuMCk7ZmxvYXQgej10ID4gMC4wID8gaGVpZ2h0IDogYmFzZTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLHosMSk7dmVjMiBwb3M9bm9ybWFsLng9PTEuMCAmJiBub3JtYWwueT09MC4wICYmIG5vcm1hbC56PT0xNjM4NC4wXFxuPyBhX3Bvc1xcbjogdmVjMihlZGdlZGlzdGFuY2Useip1X2hlaWdodF9mYWN0b3IpO3ZfcG9zX2E9Z2V0X3BhdHRlcm5fcG9zKHVfcGl4ZWxfY29vcmRfdXBwZXIsdV9waXhlbF9jb29yZF9sb3dlcixmcm9tU2NhbGUqZGlzcGxheV9zaXplX2EsdGlsZVJhdGlvLHBvcyk7dl9wb3NfYj1nZXRfcGF0dGVybl9wb3ModV9waXhlbF9jb29yZF91cHBlcix1X3BpeGVsX2Nvb3JkX2xvd2VyLHRvU2NhbGUqZGlzcGxheV9zaXplX2IsdGlsZVJhdGlvLHBvcyk7dl9saWdodGluZz12ZWM0KDAuMCwwLjAsMC4wLDEuMCk7ZmxvYXQgZGlyZWN0aW9uYWw9Y2xhbXAoZG90KG5vcm1hbC8xNjM4My4wLHVfbGlnaHRwb3MpLDAuMCwxLjApO2RpcmVjdGlvbmFsPW1peCgoMS4wLXVfbGlnaHRpbnRlbnNpdHkpLG1heCgoMC41K3VfbGlnaHRpbnRlbnNpdHkpLDEuMCksZGlyZWN0aW9uYWwpO2lmIChub3JtYWwueSAhPTAuMCkge2RpcmVjdGlvbmFsKj0oKDEuMC11X3ZlcnRpY2FsX2dyYWRpZW50KSsodV92ZXJ0aWNhbF9ncmFkaWVudCpjbGFtcCgodCtiYXNlKSpwb3coaGVpZ2h0LzE1MC4wLDAuNSksbWl4KDAuNywwLjk4LDEuMC11X2xpZ2h0aW50ZW5zaXR5KSwxLjApKSk7fXZfbGlnaHRpbmcucmdiKz1jbGFtcChkaXJlY3Rpb25hbCp1X2xpZ2h0Y29sb3IsbWl4KHZlYzMoMC4wKSx2ZWMzKDAuMyksMS4wLXVfbGlnaHRjb2xvciksdmVjMygxLjApKTt2X2xpZ2h0aW5nKj11X29wYWNpdHk7fVwiKSx0aT1jaShcIiNpZmRlZiBHTF9FU1xcbnByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZW5kaWZcXG51bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO3ZhcnlpbmcgdmVjMiB2X3Bvczt1bmlmb3JtIHZlYzIgdV9kaW1lbnNpb247dW5pZm9ybSBmbG9hdCB1X3pvb207dW5pZm9ybSBmbG9hdCB1X21heHpvb207ZmxvYXQgZ2V0RWxldmF0aW9uKHZlYzIgY29vcmQsZmxvYXQgYmlhcykge3ZlYzQgZGF0YT10ZXh0dXJlMkQodV9pbWFnZSxjb29yZCkqMjU1LjA7cmV0dXJuIChkYXRhLnIrZGF0YS5nKjI1Ni4wK2RhdGEuYioyNTYuMCoyNTYuMCkvNC4wO312b2lkIG1haW4oKSB7dmVjMiBlcHNpbG9uPTEuMC91X2RpbWVuc2lvbjtmbG9hdCBhPWdldEVsZXZhdGlvbih2X3Bvcyt2ZWMyKC1lcHNpbG9uLngsLWVwc2lsb24ueSksMC4wKTtmbG9hdCBiPWdldEVsZXZhdGlvbih2X3Bvcyt2ZWMyKDAsLWVwc2lsb24ueSksMC4wKTtmbG9hdCBjPWdldEVsZXZhdGlvbih2X3Bvcyt2ZWMyKGVwc2lsb24ueCwtZXBzaWxvbi55KSwwLjApO2Zsb2F0IGQ9Z2V0RWxldmF0aW9uKHZfcG9zK3ZlYzIoLWVwc2lsb24ueCwwKSwwLjApO2Zsb2F0IGU9Z2V0RWxldmF0aW9uKHZfcG9zLDAuMCk7ZmxvYXQgZj1nZXRFbGV2YXRpb24odl9wb3MrdmVjMihlcHNpbG9uLngsMCksMC4wKTtmbG9hdCBnPWdldEVsZXZhdGlvbih2X3Bvcyt2ZWMyKC1lcHNpbG9uLngsZXBzaWxvbi55KSwwLjApO2Zsb2F0IGg9Z2V0RWxldmF0aW9uKHZfcG9zK3ZlYzIoMCxlcHNpbG9uLnkpLDAuMCk7ZmxvYXQgaT1nZXRFbGV2YXRpb24odl9wb3MrdmVjMihlcHNpbG9uLngsZXBzaWxvbi55KSwwLjApO2Zsb2F0IGV4YWdnZXJhdGlvbj11X3pvb20gPCAyLjAgPyAwLjQgOiB1X3pvb20gPCA0LjUgPyAwLjM1IDogMC4zO3ZlYzIgZGVyaXY9dmVjMigoYytmK2YraSktKGErZCtkK2cpLChnK2graCtpKS0oYStiK2IrYykpLyBwb3coMi4wLCh1X3pvb20tdV9tYXh6b29tKSpleGFnZ2VyYXRpb24rMTkuMjU2Mi11X3pvb20pO2dsX0ZyYWdDb2xvcj1jbGFtcCh2ZWM0KGRlcml2LngvMi4wKzAuNSxkZXJpdi55LzIuMCswLjUsMS4wLDEuMCksMC4wLDEuMCk7XFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbmdsX0ZyYWdDb2xvcj12ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVwiLFwidW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gdmVjMiB1X2RpbWVuc2lvbjthdHRyaWJ1dGUgdmVjMiBhX3BvczthdHRyaWJ1dGUgdmVjMiBhX3RleHR1cmVfcG9zO3ZhcnlpbmcgdmVjMiB2X3Bvczt2b2lkIG1haW4oKSB7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO2hpZ2hwIHZlYzIgZXBzaWxvbj0xLjAvdV9kaW1lbnNpb247ZmxvYXQgc2NhbGU9KHVfZGltZW5zaW9uLngtMi4wKS91X2RpbWVuc2lvbi54O3ZfcG9zPShhX3RleHR1cmVfcG9zLzgxOTIuMCkqc2NhbGUrZXBzaWxvbjt9XCIpLGVpPWNpKFwidW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTt2YXJ5aW5nIHZlYzIgdl9wb3M7dW5pZm9ybSB2ZWMyIHVfbGF0cmFuZ2U7dW5pZm9ybSB2ZWMyIHVfbGlnaHQ7dW5pZm9ybSB2ZWM0IHVfc2hhZG93O3VuaWZvcm0gdmVjNCB1X2hpZ2hsaWdodDt1bmlmb3JtIHZlYzQgdV9hY2NlbnQ7XFxuI2RlZmluZSBQSSAzLjE0MTU5MjY1MzU4OTc5M1xcbnZvaWQgbWFpbigpIHt2ZWM0IHBpeGVsPXRleHR1cmUyRCh1X2ltYWdlLHZfcG9zKTt2ZWMyIGRlcml2PSgocGl4ZWwucmcqMi4wKS0xLjApO2Zsb2F0IHNjYWxlRmFjdG9yPWNvcyhyYWRpYW5zKCh1X2xhdHJhbmdlWzBdLXVfbGF0cmFuZ2VbMV0pKigxLjAtdl9wb3MueSkrdV9sYXRyYW5nZVsxXSkpO2Zsb2F0IHNsb3BlPWF0YW4oMS4yNSpsZW5ndGgoZGVyaXYpL3NjYWxlRmFjdG9yKTtmbG9hdCBhc3BlY3Q9ZGVyaXYueCAhPTAuMCA/IGF0YW4oZGVyaXYueSwtZGVyaXYueCkgOiBQSS8yLjAqKGRlcml2LnkgPiAwLjAgPyAxLjAgOi0xLjApO2Zsb2F0IGludGVuc2l0eT11X2xpZ2h0Lng7ZmxvYXQgYXppbXV0aD11X2xpZ2h0LnkrUEk7ZmxvYXQgYmFzZT0xLjg3NS1pbnRlbnNpdHkqMS43NTtmbG9hdCBtYXhWYWx1ZT0wLjUqUEk7ZmxvYXQgc2NhbGVkU2xvcGU9aW50ZW5zaXR5ICE9MC41ID8gKChwb3coYmFzZSxzbG9wZSktMS4wKS8ocG93KGJhc2UsbWF4VmFsdWUpLTEuMCkpKm1heFZhbHVlIDogc2xvcGU7ZmxvYXQgYWNjZW50PWNvcyhzY2FsZWRTbG9wZSk7dmVjNCBhY2NlbnRfY29sb3I9KDEuMC1hY2NlbnQpKnVfYWNjZW50KmNsYW1wKGludGVuc2l0eSoyLjAsMC4wLDEuMCk7ZmxvYXQgc2hhZGU9YWJzKG1vZCgoYXNwZWN0K2F6aW11dGgpL1BJKzAuNSwyLjApLTEuMCk7dmVjNCBzaGFkZV9jb2xvcj1taXgodV9zaGFkb3csdV9oaWdobGlnaHQsc2hhZGUpKnNpbihzY2FsZWRTbG9wZSkqY2xhbXAoaW50ZW5zaXR5KjIuMCwwLjAsMS4wKTtnbF9GcmFnQ29sb3I9YWNjZW50X2NvbG9yKigxLjAtc2hhZGVfY29sb3IuYSkrc2hhZGVfY29sb3I7XFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbmdsX0ZyYWdDb2xvcj12ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVwiLFwidW5pZm9ybSBtYXQ0IHVfbWF0cml4O2F0dHJpYnV0ZSB2ZWMyIGFfcG9zO2F0dHJpYnV0ZSB2ZWMyIGFfdGV4dHVyZV9wb3M7dmFyeWluZyB2ZWMyIHZfcG9zO3ZvaWQgbWFpbigpIHtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KGFfcG9zLDAsMSk7dl9wb3M9YV90ZXh0dXJlX3Bvcy84MTkyLjA7fVwiKSxpaT1jaShcInVuaWZvcm0gbG93cCBmbG9hdCB1X2RldmljZV9waXhlbF9yYXRpbzt2YXJ5aW5nIHZlYzIgdl93aWR0aDI7dmFyeWluZyB2ZWMyIHZfbm9ybWFsO3ZhcnlpbmcgZmxvYXQgdl9nYW1tYV9zY2FsZTtcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxudm9pZCBtYWluKCkge1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIHZlYzQgY29sb3JcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJsdXJcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5mbG9hdCBkaXN0PWxlbmd0aCh2X25vcm1hbCkqdl93aWR0aDIucztmbG9hdCBibHVyMj0oYmx1cisxLjAvdV9kZXZpY2VfcGl4ZWxfcmF0aW8pKnZfZ2FtbWFfc2NhbGU7ZmxvYXQgYWxwaGE9Y2xhbXAobWluKGRpc3QtKHZfd2lkdGgyLnQtYmx1cjIpLHZfd2lkdGgyLnMtZGlzdCkvYmx1cjIsMC4wLDEuMCk7Z2xfRnJhZ0NvbG9yPWNvbG9yKihhbHBoYSpvcGFjaXR5KTtcXG4jaWZkZWYgT1ZFUkRSQVdfSU5TUEVDVE9SXFxuZ2xfRnJhZ0NvbG9yPXZlYzQoMS4wKTtcXG4jZW5kaWZcXG59XCIsXCJcXG4jZGVmaW5lIHNjYWxlIDAuMDE1ODczMDE2XFxuYXR0cmlidXRlIHZlYzIgYV9wb3Nfbm9ybWFsO2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSBtZWRpdW1wIGZsb2F0IHVfcmF0aW87dW5pZm9ybSB2ZWMyIHVfdW5pdHNfdG9fcGl4ZWxzO3VuaWZvcm0gbG93cCBmbG9hdCB1X2RldmljZV9waXhlbF9yYXRpbzt2YXJ5aW5nIHZlYzIgdl9ub3JtYWw7dmFyeWluZyB2ZWMyIHZfd2lkdGgyO3ZhcnlpbmcgZmxvYXQgdl9nYW1tYV9zY2FsZTt2YXJ5aW5nIGhpZ2hwIGZsb2F0IHZfbGluZXNvZmFyO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBibHVyXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIG1lZGl1bXAgZmxvYXQgZ2Fwd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb2Zmc2V0XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxudm9pZCBtYWluKCkge1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGhpZ2hwIHZlYzQgY29sb3JcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJsdXJcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IGdhcHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvZmZzZXRcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxuZmxvYXQgQU5USUFMSUFTSU5HPTEuMC91X2RldmljZV9waXhlbF9yYXRpby8yLjA7dmVjMiBhX2V4dHJ1ZGU9YV9kYXRhLnh5LTEyOC4wO2Zsb2F0IGFfZGlyZWN0aW9uPW1vZChhX2RhdGEueiw0LjApLTEuMDt2X2xpbmVzb2Zhcj0oZmxvb3IoYV9kYXRhLnovNC4wKSthX2RhdGEudyo2NC4wKSoyLjA7dmVjMiBwb3M9Zmxvb3IoYV9wb3Nfbm9ybWFsKjAuNSk7bWVkaXVtcCB2ZWMyIG5vcm1hbD1hX3Bvc19ub3JtYWwtMi4wKnBvcztub3JtYWwueT1ub3JtYWwueSoyLjAtMS4wO3Zfbm9ybWFsPW5vcm1hbDtnYXB3aWR0aD1nYXB3aWR0aC8yLjA7ZmxvYXQgaGFsZndpZHRoPXdpZHRoLzIuMDtvZmZzZXQ9LTEuMCpvZmZzZXQ7ZmxvYXQgaW5zZXQ9Z2Fwd2lkdGgrKGdhcHdpZHRoID4gMC4wID8gQU5USUFMSUFTSU5HIDogMC4wKTtmbG9hdCBvdXRzZXQ9Z2Fwd2lkdGgraGFsZndpZHRoKihnYXB3aWR0aCA+IDAuMCA/IDIuMCA6IDEuMCkrKGhhbGZ3aWR0aD09MC4wID8gMC4wIDogQU5USUFMSUFTSU5HKTttZWRpdW1wIHZlYzIgZGlzdD1vdXRzZXQqYV9leHRydWRlKnNjYWxlO21lZGl1bXAgZmxvYXQgdT0wLjUqYV9kaXJlY3Rpb247bWVkaXVtcCBmbG9hdCB0PTEuMC1hYnModSk7bWVkaXVtcCB2ZWMyIG9mZnNldDI9b2Zmc2V0KmFfZXh0cnVkZSpzY2FsZSpub3JtYWwueSptYXQyKHQsLXUsdSx0KTt2ZWM0IHByb2plY3RlZF9leHRydWRlPXVfbWF0cml4KnZlYzQoZGlzdC91X3JhdGlvLDAuMCwwLjApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQocG9zK29mZnNldDIvdV9yYXRpbywwLjAsMS4wKStwcm9qZWN0ZWRfZXh0cnVkZTtmbG9hdCBleHRydWRlX2xlbmd0aF93aXRob3V0X3BlcnNwZWN0aXZlPWxlbmd0aChkaXN0KTtmbG9hdCBleHRydWRlX2xlbmd0aF93aXRoX3BlcnNwZWN0aXZlPWxlbmd0aChwcm9qZWN0ZWRfZXh0cnVkZS54eS9nbF9Qb3NpdGlvbi53KnVfdW5pdHNfdG9fcGl4ZWxzKTt2X2dhbW1hX3NjYWxlPWV4dHJ1ZGVfbGVuZ3RoX3dpdGhvdXRfcGVyc3BlY3RpdmUvZXh0cnVkZV9sZW5ndGhfd2l0aF9wZXJzcGVjdGl2ZTt2X3dpZHRoMj12ZWMyKG91dHNldCxpbnNldCk7fVwiKSxvaT1jaShcInVuaWZvcm0gbG93cCBmbG9hdCB1X2RldmljZV9waXhlbF9yYXRpbzt1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlO3ZhcnlpbmcgdmVjMiB2X3dpZHRoMjt2YXJ5aW5nIHZlYzIgdl9ub3JtYWw7dmFyeWluZyBmbG9hdCB2X2dhbW1hX3NjYWxlO3ZhcnlpbmcgaGlnaHAgZmxvYXQgdl9saW5lcHJvZ3Jlc3M7XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGJsdXJcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJsdXJcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5mbG9hdCBkaXN0PWxlbmd0aCh2X25vcm1hbCkqdl93aWR0aDIucztmbG9hdCBibHVyMj0oYmx1cisxLjAvdV9kZXZpY2VfcGl4ZWxfcmF0aW8pKnZfZ2FtbWFfc2NhbGU7ZmxvYXQgYWxwaGE9Y2xhbXAobWluKGRpc3QtKHZfd2lkdGgyLnQtYmx1cjIpLHZfd2lkdGgyLnMtZGlzdCkvYmx1cjIsMC4wLDEuMCk7dmVjNCBjb2xvcj10ZXh0dXJlMkQodV9pbWFnZSx2ZWMyKHZfbGluZXByb2dyZXNzLDAuNSkpO2dsX0ZyYWdDb2xvcj1jb2xvciooYWxwaGEqb3BhY2l0eSk7XFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbmdsX0ZyYWdDb2xvcj12ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVwiLFwiXFxuI2RlZmluZSBNQVhfTElORV9ESVNUQU5DRSAzMjc2Ny4wXFxuI2RlZmluZSBzY2FsZSAwLjAxNTg3MzAxNlxcbmF0dHJpYnV0ZSB2ZWMyIGFfcG9zX25vcm1hbDthdHRyaWJ1dGUgdmVjNCBhX2RhdGE7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gbWVkaXVtcCBmbG9hdCB1X3JhdGlvO3VuaWZvcm0gbG93cCBmbG9hdCB1X2RldmljZV9waXhlbF9yYXRpbzt1bmlmb3JtIHZlYzIgdV91bml0c190b19waXhlbHM7dmFyeWluZyB2ZWMyIHZfbm9ybWFsO3ZhcnlpbmcgdmVjMiB2X3dpZHRoMjt2YXJ5aW5nIGZsb2F0IHZfZ2FtbWFfc2NhbGU7dmFyeWluZyBoaWdocCBmbG9hdCB2X2xpbmVwcm9ncmVzcztcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IGdhcHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9mZnNldFxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbWVkaXVtcCBmbG9hdCB3aWR0aFxcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJsdXJcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IGdhcHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvZmZzZXRcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxuZmxvYXQgQU5USUFMSUFTSU5HPTEuMC91X2RldmljZV9waXhlbF9yYXRpby8yLjA7dmVjMiBhX2V4dHJ1ZGU9YV9kYXRhLnh5LTEyOC4wO2Zsb2F0IGFfZGlyZWN0aW9uPW1vZChhX2RhdGEueiw0LjApLTEuMDt2X2xpbmVwcm9ncmVzcz0oZmxvb3IoYV9kYXRhLnovNC4wKSthX2RhdGEudyo2NC4wKSoyLjAvTUFYX0xJTkVfRElTVEFOQ0U7dmVjMiBwb3M9Zmxvb3IoYV9wb3Nfbm9ybWFsKjAuNSk7bWVkaXVtcCB2ZWMyIG5vcm1hbD1hX3Bvc19ub3JtYWwtMi4wKnBvcztub3JtYWwueT1ub3JtYWwueSoyLjAtMS4wO3Zfbm9ybWFsPW5vcm1hbDtnYXB3aWR0aD1nYXB3aWR0aC8yLjA7ZmxvYXQgaGFsZndpZHRoPXdpZHRoLzIuMDtvZmZzZXQ9LTEuMCpvZmZzZXQ7ZmxvYXQgaW5zZXQ9Z2Fwd2lkdGgrKGdhcHdpZHRoID4gMC4wID8gQU5USUFMSUFTSU5HIDogMC4wKTtmbG9hdCBvdXRzZXQ9Z2Fwd2lkdGgraGFsZndpZHRoKihnYXB3aWR0aCA+IDAuMCA/IDIuMCA6IDEuMCkrKGhhbGZ3aWR0aD09MC4wID8gMC4wIDogQU5USUFMSUFTSU5HKTttZWRpdW1wIHZlYzIgZGlzdD1vdXRzZXQqYV9leHRydWRlKnNjYWxlO21lZGl1bXAgZmxvYXQgdT0wLjUqYV9kaXJlY3Rpb247bWVkaXVtcCBmbG9hdCB0PTEuMC1hYnModSk7bWVkaXVtcCB2ZWMyIG9mZnNldDI9b2Zmc2V0KmFfZXh0cnVkZSpzY2FsZSpub3JtYWwueSptYXQyKHQsLXUsdSx0KTt2ZWM0IHByb2plY3RlZF9leHRydWRlPXVfbWF0cml4KnZlYzQoZGlzdC91X3JhdGlvLDAuMCwwLjApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQocG9zK29mZnNldDIvdV9yYXRpbywwLjAsMS4wKStwcm9qZWN0ZWRfZXh0cnVkZTtmbG9hdCBleHRydWRlX2xlbmd0aF93aXRob3V0X3BlcnNwZWN0aXZlPWxlbmd0aChkaXN0KTtmbG9hdCBleHRydWRlX2xlbmd0aF93aXRoX3BlcnNwZWN0aXZlPWxlbmd0aChwcm9qZWN0ZWRfZXh0cnVkZS54eS9nbF9Qb3NpdGlvbi53KnVfdW5pdHNfdG9fcGl4ZWxzKTt2X2dhbW1hX3NjYWxlPWV4dHJ1ZGVfbGVuZ3RoX3dpdGhvdXRfcGVyc3BlY3RpdmUvZXh0cnVkZV9sZW5ndGhfd2l0aF9wZXJzcGVjdGl2ZTt2X3dpZHRoMj12ZWMyKG91dHNldCxpbnNldCk7fVwiKSxyaT1jaShcInVuaWZvcm0gbG93cCBmbG9hdCB1X2RldmljZV9waXhlbF9yYXRpbzt1bmlmb3JtIHZlYzIgdV90ZXhzaXplO3VuaWZvcm0gZmxvYXQgdV9mYWRlO3VuaWZvcm0gbWVkaXVtcCB2ZWM0IHVfc2NhbGU7dW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTt2YXJ5aW5nIHZlYzIgdl9ub3JtYWw7dmFyeWluZyB2ZWMyIHZfd2lkdGgyO3ZhcnlpbmcgZmxvYXQgdl9saW5lc29mYXI7dmFyeWluZyBmbG9hdCB2X2dhbW1hX3NjYWxlO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCB2ZWM0IHBhdHRlcm5fZnJvbVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCB2ZWM0IHBhdHRlcm5fdG9cXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxudm9pZCBtYWluKCkge1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgdmVjNCBwYXR0ZXJuX2Zyb21cXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIHZlYzQgcGF0dGVybl90b1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcbnZlYzIgcGF0dGVybl90bF9hPXBhdHRlcm5fZnJvbS54eTt2ZWMyIHBhdHRlcm5fYnJfYT1wYXR0ZXJuX2Zyb20uenc7dmVjMiBwYXR0ZXJuX3RsX2I9cGF0dGVybl90by54eTt2ZWMyIHBhdHRlcm5fYnJfYj1wYXR0ZXJuX3RvLnp3O2Zsb2F0IHBpeGVsUmF0aW89dV9zY2FsZS54O2Zsb2F0IHRpbGVab29tUmF0aW89dV9zY2FsZS55O2Zsb2F0IGZyb21TY2FsZT11X3NjYWxlLno7ZmxvYXQgdG9TY2FsZT11X3NjYWxlLnc7dmVjMiBkaXNwbGF5X3NpemVfYT12ZWMyKChwYXR0ZXJuX2JyX2EueC1wYXR0ZXJuX3RsX2EueCkvcGl4ZWxSYXRpbywocGF0dGVybl9icl9hLnktcGF0dGVybl90bF9hLnkpL3BpeGVsUmF0aW8pO3ZlYzIgZGlzcGxheV9zaXplX2I9dmVjMigocGF0dGVybl9icl9iLngtcGF0dGVybl90bF9iLngpL3BpeGVsUmF0aW8sKHBhdHRlcm5fYnJfYi55LXBhdHRlcm5fdGxfYi55KS9waXhlbFJhdGlvKTt2ZWMyIHBhdHRlcm5fc2l6ZV9hPXZlYzIoZGlzcGxheV9zaXplX2EueCpmcm9tU2NhbGUvdGlsZVpvb21SYXRpbyxkaXNwbGF5X3NpemVfYS55KTt2ZWMyIHBhdHRlcm5fc2l6ZV9iPXZlYzIoZGlzcGxheV9zaXplX2IueCp0b1NjYWxlL3RpbGVab29tUmF0aW8sZGlzcGxheV9zaXplX2IueSk7ZmxvYXQgZGlzdD1sZW5ndGgodl9ub3JtYWwpKnZfd2lkdGgyLnM7ZmxvYXQgYmx1cjI9KGJsdXIrMS4wL3VfZGV2aWNlX3BpeGVsX3JhdGlvKSp2X2dhbW1hX3NjYWxlO2Zsb2F0IGFscGhhPWNsYW1wKG1pbihkaXN0LSh2X3dpZHRoMi50LWJsdXIyKSx2X3dpZHRoMi5zLWRpc3QpL2JsdXIyLDAuMCwxLjApO2Zsb2F0IHhfYT1tb2Qodl9saW5lc29mYXIvcGF0dGVybl9zaXplX2EueCwxLjApO2Zsb2F0IHhfYj1tb2Qodl9saW5lc29mYXIvcGF0dGVybl9zaXplX2IueCwxLjApO2Zsb2F0IHlfYT0wLjUrKHZfbm9ybWFsLnkqY2xhbXAodl93aWR0aDIucywwLjAsKHBhdHRlcm5fc2l6ZV9hLnkrMi4wKS8yLjApL3BhdHRlcm5fc2l6ZV9hLnkpO2Zsb2F0IHlfYj0wLjUrKHZfbm9ybWFsLnkqY2xhbXAodl93aWR0aDIucywwLjAsKHBhdHRlcm5fc2l6ZV9iLnkrMi4wKS8yLjApL3BhdHRlcm5fc2l6ZV9iLnkpO3ZlYzIgcG9zX2E9bWl4KHBhdHRlcm5fdGxfYS91X3RleHNpemUscGF0dGVybl9icl9hL3VfdGV4c2l6ZSx2ZWMyKHhfYSx5X2EpKTt2ZWMyIHBvc19iPW1peChwYXR0ZXJuX3RsX2IvdV90ZXhzaXplLHBhdHRlcm5fYnJfYi91X3RleHNpemUsdmVjMih4X2IseV9iKSk7dmVjNCBjb2xvcj1taXgodGV4dHVyZTJEKHVfaW1hZ2UscG9zX2EpLHRleHR1cmUyRCh1X2ltYWdlLHBvc19iKSx1X2ZhZGUpO2dsX0ZyYWdDb2xvcj1jb2xvciphbHBoYSpvcGFjaXR5O1xcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG5nbF9GcmFnQ29sb3I9dmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cIixcIlxcbiNkZWZpbmUgc2NhbGUgMC4wMTU4NzMwMTZcXG4jZGVmaW5lIExJTkVfRElTVEFOQ0VfU0NBTEUgMi4wXFxuYXR0cmlidXRlIHZlYzIgYV9wb3Nfbm9ybWFsO2F0dHJpYnV0ZSB2ZWM0IGFfZGF0YTt1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSB2ZWMyIHVfdW5pdHNfdG9fcGl4ZWxzO3VuaWZvcm0gbWVkaXVtcCBmbG9hdCB1X3JhdGlvO3VuaWZvcm0gbG93cCBmbG9hdCB1X2RldmljZV9waXhlbF9yYXRpbzt2YXJ5aW5nIHZlYzIgdl9ub3JtYWw7dmFyeWluZyB2ZWMyIHZfd2lkdGgyO3ZhcnlpbmcgZmxvYXQgdl9saW5lc29mYXI7dmFyeWluZyBmbG9hdCB2X2dhbW1hX3NjYWxlO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBibHVyXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb2Zmc2V0XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IGdhcHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIHZlYzQgcGF0dGVybl9mcm9tXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIHZlYzQgcGF0dGVybl90b1xcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGJsdXJcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9mZnNldFxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgZ2Fwd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbWVkaXVtcCB2ZWM0IHBhdHRlcm5fZnJvbVxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgdmVjNCBwYXR0ZXJuX3RvXFxuZmxvYXQgQU5USUFMSUFTSU5HPTEuMC91X2RldmljZV9waXhlbF9yYXRpby8yLjA7dmVjMiBhX2V4dHJ1ZGU9YV9kYXRhLnh5LTEyOC4wO2Zsb2F0IGFfZGlyZWN0aW9uPW1vZChhX2RhdGEueiw0LjApLTEuMDtmbG9hdCBhX2xpbmVzb2Zhcj0oZmxvb3IoYV9kYXRhLnovNC4wKSthX2RhdGEudyo2NC4wKSpMSU5FX0RJU1RBTkNFX1NDQUxFO3ZlYzIgcG9zPWZsb29yKGFfcG9zX25vcm1hbCowLjUpO21lZGl1bXAgdmVjMiBub3JtYWw9YV9wb3Nfbm9ybWFsLTIuMCpwb3M7bm9ybWFsLnk9bm9ybWFsLnkqMi4wLTEuMDt2X25vcm1hbD1ub3JtYWw7Z2Fwd2lkdGg9Z2Fwd2lkdGgvMi4wO2Zsb2F0IGhhbGZ3aWR0aD13aWR0aC8yLjA7b2Zmc2V0PS0xLjAqb2Zmc2V0O2Zsb2F0IGluc2V0PWdhcHdpZHRoKyhnYXB3aWR0aCA+IDAuMCA/IEFOVElBTElBU0lORyA6IDAuMCk7ZmxvYXQgb3V0c2V0PWdhcHdpZHRoK2hhbGZ3aWR0aCooZ2Fwd2lkdGggPiAwLjAgPyAyLjAgOiAxLjApKyhoYWxmd2lkdGg9PTAuMCA/IDAuMCA6IEFOVElBTElBU0lORyk7bWVkaXVtcCB2ZWMyIGRpc3Q9b3V0c2V0KmFfZXh0cnVkZSpzY2FsZTttZWRpdW1wIGZsb2F0IHU9MC41KmFfZGlyZWN0aW9uO21lZGl1bXAgZmxvYXQgdD0xLjAtYWJzKHUpO21lZGl1bXAgdmVjMiBvZmZzZXQyPW9mZnNldCphX2V4dHJ1ZGUqc2NhbGUqbm9ybWFsLnkqbWF0Mih0LC11LHUsdCk7dmVjNCBwcm9qZWN0ZWRfZXh0cnVkZT11X21hdHJpeCp2ZWM0KGRpc3QvdV9yYXRpbywwLjAsMC4wKTtnbF9Qb3NpdGlvbj11X21hdHJpeCp2ZWM0KHBvcytvZmZzZXQyL3VfcmF0aW8sMC4wLDEuMCkrcHJvamVjdGVkX2V4dHJ1ZGU7ZmxvYXQgZXh0cnVkZV9sZW5ndGhfd2l0aG91dF9wZXJzcGVjdGl2ZT1sZW5ndGgoZGlzdCk7ZmxvYXQgZXh0cnVkZV9sZW5ndGhfd2l0aF9wZXJzcGVjdGl2ZT1sZW5ndGgocHJvamVjdGVkX2V4dHJ1ZGUueHkvZ2xfUG9zaXRpb24udyp1X3VuaXRzX3RvX3BpeGVscyk7dl9nYW1tYV9zY2FsZT1leHRydWRlX2xlbmd0aF93aXRob3V0X3BlcnNwZWN0aXZlL2V4dHJ1ZGVfbGVuZ3RoX3dpdGhfcGVyc3BlY3RpdmU7dl9saW5lc29mYXI9YV9saW5lc29mYXI7dl93aWR0aDI9dmVjMihvdXRzZXQsaW5zZXQpO31cIiksYWk9Y2koXCJ1bmlmb3JtIGxvd3AgZmxvYXQgdV9kZXZpY2VfcGl4ZWxfcmF0aW87dW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTt1bmlmb3JtIGZsb2F0IHVfc2RmZ2FtbWE7dW5pZm9ybSBmbG9hdCB1X21peDt2YXJ5aW5nIHZlYzIgdl9ub3JtYWw7dmFyeWluZyB2ZWMyIHZfd2lkdGgyO3ZhcnlpbmcgdmVjMiB2X3RleF9hO3ZhcnlpbmcgdmVjMiB2X3RleF9iO3ZhcnlpbmcgZmxvYXQgdl9nYW1tYV9zY2FsZTtcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGZsb29yd2lkdGhcXG52b2lkIG1haW4oKSB7XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGZsb29yd2lkdGhcXG5mbG9hdCBkaXN0PWxlbmd0aCh2X25vcm1hbCkqdl93aWR0aDIucztmbG9hdCBibHVyMj0oYmx1cisxLjAvdV9kZXZpY2VfcGl4ZWxfcmF0aW8pKnZfZ2FtbWFfc2NhbGU7ZmxvYXQgYWxwaGE9Y2xhbXAobWluKGRpc3QtKHZfd2lkdGgyLnQtYmx1cjIpLHZfd2lkdGgyLnMtZGlzdCkvYmx1cjIsMC4wLDEuMCk7ZmxvYXQgc2RmZGlzdF9hPXRleHR1cmUyRCh1X2ltYWdlLHZfdGV4X2EpLmE7ZmxvYXQgc2RmZGlzdF9iPXRleHR1cmUyRCh1X2ltYWdlLHZfdGV4X2IpLmE7ZmxvYXQgc2RmZGlzdD1taXgoc2RmZGlzdF9hLHNkZmRpc3RfYix1X21peCk7YWxwaGEqPXNtb290aHN0ZXAoMC41LXVfc2RmZ2FtbWEvZmxvb3J3aWR0aCwwLjUrdV9zZGZnYW1tYS9mbG9vcndpZHRoLHNkZmRpc3QpO2dsX0ZyYWdDb2xvcj1jb2xvciooYWxwaGEqb3BhY2l0eSk7XFxuI2lmZGVmIE9WRVJEUkFXX0lOU1BFQ1RPUlxcbmdsX0ZyYWdDb2xvcj12ZWM0KDEuMCk7XFxuI2VuZGlmXFxufVwiLFwiXFxuI2RlZmluZSBzY2FsZSAwLjAxNTg3MzAxNlxcbiNkZWZpbmUgTElORV9ESVNUQU5DRV9TQ0FMRSAyLjBcXG5hdHRyaWJ1dGUgdmVjMiBhX3Bvc19ub3JtYWw7YXR0cmlidXRlIHZlYzQgYV9kYXRhO3VuaWZvcm0gbWF0NCB1X21hdHJpeDt1bmlmb3JtIG1lZGl1bXAgZmxvYXQgdV9yYXRpbzt1bmlmb3JtIGxvd3AgZmxvYXQgdV9kZXZpY2VfcGl4ZWxfcmF0aW87dW5pZm9ybSB2ZWMyIHVfcGF0dGVybnNjYWxlX2E7dW5pZm9ybSBmbG9hdCB1X3RleF95X2E7dW5pZm9ybSB2ZWMyIHVfcGF0dGVybnNjYWxlX2I7dW5pZm9ybSBmbG9hdCB1X3RleF95X2I7dW5pZm9ybSB2ZWMyIHVfdW5pdHNfdG9fcGl4ZWxzO3ZhcnlpbmcgdmVjMiB2X25vcm1hbDt2YXJ5aW5nIHZlYzIgdl93aWR0aDI7dmFyeWluZyB2ZWMyIHZfdGV4X2E7dmFyeWluZyB2ZWMyIHZfdGV4X2I7dmFyeWluZyBmbG9hdCB2X2dhbW1hX3NjYWxlO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBibHVyXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIG1lZGl1bXAgZmxvYXQgZ2Fwd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb2Zmc2V0XFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBtZWRpdW1wIGZsb2F0IHdpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGZsb29yd2lkdGhcXG52b2lkIG1haW4oKSB7XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBjb2xvclxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgYmx1clxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgZ2Fwd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9mZnNldFxcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIG1lZGl1bXAgZmxvYXQgd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGZsb29yd2lkdGhcXG5mbG9hdCBBTlRJQUxJQVNJTkc9MS4wL3VfZGV2aWNlX3BpeGVsX3JhdGlvLzIuMDt2ZWMyIGFfZXh0cnVkZT1hX2RhdGEueHktMTI4LjA7ZmxvYXQgYV9kaXJlY3Rpb249bW9kKGFfZGF0YS56LDQuMCktMS4wO2Zsb2F0IGFfbGluZXNvZmFyPShmbG9vcihhX2RhdGEuei80LjApK2FfZGF0YS53KjY0LjApKkxJTkVfRElTVEFOQ0VfU0NBTEU7dmVjMiBwb3M9Zmxvb3IoYV9wb3Nfbm9ybWFsKjAuNSk7bWVkaXVtcCB2ZWMyIG5vcm1hbD1hX3Bvc19ub3JtYWwtMi4wKnBvcztub3JtYWwueT1ub3JtYWwueSoyLjAtMS4wO3Zfbm9ybWFsPW5vcm1hbDtnYXB3aWR0aD1nYXB3aWR0aC8yLjA7ZmxvYXQgaGFsZndpZHRoPXdpZHRoLzIuMDtvZmZzZXQ9LTEuMCpvZmZzZXQ7ZmxvYXQgaW5zZXQ9Z2Fwd2lkdGgrKGdhcHdpZHRoID4gMC4wID8gQU5USUFMSUFTSU5HIDogMC4wKTtmbG9hdCBvdXRzZXQ9Z2Fwd2lkdGgraGFsZndpZHRoKihnYXB3aWR0aCA+IDAuMCA/IDIuMCA6IDEuMCkrKGhhbGZ3aWR0aD09MC4wID8gMC4wIDogQU5USUFMSUFTSU5HKTttZWRpdW1wIHZlYzIgZGlzdD1vdXRzZXQqYV9leHRydWRlKnNjYWxlO21lZGl1bXAgZmxvYXQgdT0wLjUqYV9kaXJlY3Rpb247bWVkaXVtcCBmbG9hdCB0PTEuMC1hYnModSk7bWVkaXVtcCB2ZWMyIG9mZnNldDI9b2Zmc2V0KmFfZXh0cnVkZSpzY2FsZSpub3JtYWwueSptYXQyKHQsLXUsdSx0KTt2ZWM0IHByb2plY3RlZF9leHRydWRlPXVfbWF0cml4KnZlYzQoZGlzdC91X3JhdGlvLDAuMCwwLjApO2dsX1Bvc2l0aW9uPXVfbWF0cml4KnZlYzQocG9zK29mZnNldDIvdV9yYXRpbywwLjAsMS4wKStwcm9qZWN0ZWRfZXh0cnVkZTtmbG9hdCBleHRydWRlX2xlbmd0aF93aXRob3V0X3BlcnNwZWN0aXZlPWxlbmd0aChkaXN0KTtmbG9hdCBleHRydWRlX2xlbmd0aF93aXRoX3BlcnNwZWN0aXZlPWxlbmd0aChwcm9qZWN0ZWRfZXh0cnVkZS54eS9nbF9Qb3NpdGlvbi53KnVfdW5pdHNfdG9fcGl4ZWxzKTt2X2dhbW1hX3NjYWxlPWV4dHJ1ZGVfbGVuZ3RoX3dpdGhvdXRfcGVyc3BlY3RpdmUvZXh0cnVkZV9sZW5ndGhfd2l0aF9wZXJzcGVjdGl2ZTt2X3RleF9hPXZlYzIoYV9saW5lc29mYXIqdV9wYXR0ZXJuc2NhbGVfYS54L2Zsb29yd2lkdGgsbm9ybWFsLnkqdV9wYXR0ZXJuc2NhbGVfYS55K3VfdGV4X3lfYSk7dl90ZXhfYj12ZWMyKGFfbGluZXNvZmFyKnVfcGF0dGVybnNjYWxlX2IueC9mbG9vcndpZHRoLG5vcm1hbC55KnVfcGF0dGVybnNjYWxlX2IueSt1X3RleF95X2IpO3Zfd2lkdGgyPXZlYzIob3V0c2V0LGluc2V0KTt9XCIpLG5pPWNpKFwidW5pZm9ybSBmbG9hdCB1X2ZhZGVfdDt1bmlmb3JtIGZsb2F0IHVfb3BhY2l0eTt1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlMDt1bmlmb3JtIHNhbXBsZXIyRCB1X2ltYWdlMTt2YXJ5aW5nIHZlYzIgdl9wb3MwO3ZhcnlpbmcgdmVjMiB2X3BvczE7dW5pZm9ybSBmbG9hdCB1X2JyaWdodG5lc3NfbG93O3VuaWZvcm0gZmxvYXQgdV9icmlnaHRuZXNzX2hpZ2g7dW5pZm9ybSBmbG9hdCB1X3NhdHVyYXRpb25fZmFjdG9yO3VuaWZvcm0gZmxvYXQgdV9jb250cmFzdF9mYWN0b3I7dW5pZm9ybSB2ZWMzIHVfc3Bpbl93ZWlnaHRzO3ZvaWQgbWFpbigpIHt2ZWM0IGNvbG9yMD10ZXh0dXJlMkQodV9pbWFnZTAsdl9wb3MwKTt2ZWM0IGNvbG9yMT10ZXh0dXJlMkQodV9pbWFnZTEsdl9wb3MxKTtpZiAoY29sb3IwLmEgPiAwLjApIHtjb2xvcjAucmdiPWNvbG9yMC5yZ2IvY29sb3IwLmE7fWlmIChjb2xvcjEuYSA+IDAuMCkge2NvbG9yMS5yZ2I9Y29sb3IxLnJnYi9jb2xvcjEuYTt9dmVjNCBjb2xvcj1taXgoY29sb3IwLGNvbG9yMSx1X2ZhZGVfdCk7Y29sb3IuYSo9dV9vcGFjaXR5O3ZlYzMgcmdiPWNvbG9yLnJnYjtyZ2I9dmVjMyhkb3QocmdiLHVfc3Bpbl93ZWlnaHRzLnh5eiksZG90KHJnYix1X3NwaW5fd2VpZ2h0cy56eHkpLGRvdChyZ2IsdV9zcGluX3dlaWdodHMueXp4KSk7ZmxvYXQgYXZlcmFnZT0oY29sb3Iucitjb2xvci5nK2NvbG9yLmIpLzMuMDtyZ2IrPShhdmVyYWdlLXJnYikqdV9zYXR1cmF0aW9uX2ZhY3RvcjtyZ2I9KHJnYi0wLjUpKnVfY29udHJhc3RfZmFjdG9yKzAuNTt2ZWMzIHVfaGlnaF92ZWM9dmVjMyh1X2JyaWdodG5lc3NfbG93LHVfYnJpZ2h0bmVzc19sb3csdV9icmlnaHRuZXNzX2xvdyk7dmVjMyB1X2xvd192ZWM9dmVjMyh1X2JyaWdodG5lc3NfaGlnaCx1X2JyaWdodG5lc3NfaGlnaCx1X2JyaWdodG5lc3NfaGlnaCk7Z2xfRnJhZ0NvbG9yPXZlYzQobWl4KHVfaGlnaF92ZWMsdV9sb3dfdmVjLHJnYikqY29sb3IuYSxjb2xvci5hKTtcXG4jaWZkZWYgT1ZFUkRSQVdfSU5TUEVDVE9SXFxuZ2xfRnJhZ0NvbG9yPXZlYzQoMS4wKTtcXG4jZW5kaWZcXG59XCIsXCJ1bmlmb3JtIG1hdDQgdV9tYXRyaXg7dW5pZm9ybSB2ZWMyIHVfdGxfcGFyZW50O3VuaWZvcm0gZmxvYXQgdV9zY2FsZV9wYXJlbnQ7dW5pZm9ybSBmbG9hdCB1X2J1ZmZlcl9zY2FsZTthdHRyaWJ1dGUgdmVjMiBhX3BvczthdHRyaWJ1dGUgdmVjMiBhX3RleHR1cmVfcG9zO3ZhcnlpbmcgdmVjMiB2X3BvczA7dmFyeWluZyB2ZWMyIHZfcG9zMTt2b2lkIG1haW4oKSB7Z2xfUG9zaXRpb249dV9tYXRyaXgqdmVjNChhX3BvcywwLDEpO3ZfcG9zMD0oKChhX3RleHR1cmVfcG9zLzgxOTIuMCktMC41KS91X2J1ZmZlcl9zY2FsZSApKzAuNTt2X3BvczE9KHZfcG9zMCp1X3NjYWxlX3BhcmVudCkrdV90bF9wYXJlbnQ7fVwiKSxzaT1jaShcInVuaWZvcm0gc2FtcGxlcjJEIHVfdGV4dHVyZTt2YXJ5aW5nIHZlYzIgdl90ZXg7dmFyeWluZyBmbG9hdCB2X2ZhZGVfb3BhY2l0eTtcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG5sb3dwIGZsb2F0IGFscGhhPW9wYWNpdHkqdl9mYWRlX29wYWNpdHk7Z2xfRnJhZ0NvbG9yPXRleHR1cmUyRCh1X3RleHR1cmUsdl90ZXgpKmFscGhhO1xcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG5nbF9GcmFnQ29sb3I9dmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cIixcImNvbnN0IGZsb2F0IFBJPTMuMTQxNTkyNjUzNTg5NzkzO2F0dHJpYnV0ZSB2ZWM0IGFfcG9zX29mZnNldDthdHRyaWJ1dGUgdmVjNCBhX2RhdGE7YXR0cmlidXRlIHZlYzMgYV9wcm9qZWN0ZWRfcG9zO2F0dHJpYnV0ZSBmbG9hdCBhX2ZhZGVfb3BhY2l0eTt1bmlmb3JtIGJvb2wgdV9pc19zaXplX3pvb21fY29uc3RhbnQ7dW5pZm9ybSBib29sIHVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50O3VuaWZvcm0gaGlnaHAgZmxvYXQgdV9zaXplX3Q7dW5pZm9ybSBoaWdocCBmbG9hdCB1X3NpemU7dW5pZm9ybSBoaWdocCBmbG9hdCB1X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2U7dW5pZm9ybSBoaWdocCBmbG9hdCB1X3BpdGNoO3VuaWZvcm0gYm9vbCB1X3JvdGF0ZV9zeW1ib2w7dW5pZm9ybSBoaWdocCBmbG9hdCB1X2FzcGVjdF9yYXRpbzt1bmlmb3JtIGZsb2F0IHVfZmFkZV9jaGFuZ2U7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gbWF0NCB1X2xhYmVsX3BsYW5lX21hdHJpeDt1bmlmb3JtIG1hdDQgdV9jb29yZF9tYXRyaXg7dW5pZm9ybSBib29sIHVfaXNfdGV4dDt1bmlmb3JtIGJvb2wgdV9waXRjaF93aXRoX21hcDt1bmlmb3JtIHZlYzIgdV90ZXhzaXplO3ZhcnlpbmcgdmVjMiB2X3RleDt2YXJ5aW5nIGZsb2F0IHZfZmFkZV9vcGFjaXR5O1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBvcGFjaXR5XFxudm9pZCBtYWluKCkge1xcbiNwcmFnbWEgbWFwYm94OiBpbml0aWFsaXplIGxvd3AgZmxvYXQgb3BhY2l0eVxcbnZlYzIgYV9wb3M9YV9wb3Nfb2Zmc2V0Lnh5O3ZlYzIgYV9vZmZzZXQ9YV9wb3Nfb2Zmc2V0Lnp3O3ZlYzIgYV90ZXg9YV9kYXRhLnh5O3ZlYzIgYV9zaXplPWFfZGF0YS56dztoaWdocCBmbG9hdCBzZWdtZW50X2FuZ2xlPS1hX3Byb2plY3RlZF9wb3NbMl07ZmxvYXQgc2l6ZTtpZiAoIXVfaXNfc2l6ZV96b29tX2NvbnN0YW50ICYmICF1X2lzX3NpemVfZmVhdHVyZV9jb25zdGFudCkge3NpemU9bWl4KGFfc2l6ZVswXSxhX3NpemVbMV0sdV9zaXplX3QpLzI1Ni4wO30gZWxzZSBpZiAodV9pc19zaXplX3pvb21fY29uc3RhbnQgJiYgIXVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50KSB7c2l6ZT1hX3NpemVbMF0vMjU2LjA7fSBlbHNlIGlmICghdV9pc19zaXplX3pvb21fY29uc3RhbnQgJiYgdV9pc19zaXplX2ZlYXR1cmVfY29uc3RhbnQpIHtzaXplPXVfc2l6ZTt9IGVsc2Uge3NpemU9dV9zaXplO312ZWM0IHByb2plY3RlZFBvaW50PXVfbWF0cml4KnZlYzQoYV9wb3MsMCwxKTtoaWdocCBmbG9hdCBjYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlPXByb2plY3RlZFBvaW50Lnc7aGlnaHAgZmxvYXQgZGlzdGFuY2VfcmF0aW89dV9waXRjaF93aXRoX21hcCA/XFxuY2FtZXJhX3RvX2FuY2hvcl9kaXN0YW5jZS91X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2UgOlxcbnVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZS9jYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlO2hpZ2hwIGZsb2F0IHBlcnNwZWN0aXZlX3JhdGlvPWNsYW1wKDAuNSswLjUqZGlzdGFuY2VfcmF0aW8sMC4wLDQuMCk7c2l6ZSo9cGVyc3BlY3RpdmVfcmF0aW87ZmxvYXQgZm9udFNjYWxlPXVfaXNfdGV4dCA/IHNpemUvMjQuMCA6IHNpemU7aGlnaHAgZmxvYXQgc3ltYm9sX3JvdGF0aW9uPTAuMDtpZiAodV9yb3RhdGVfc3ltYm9sKSB7dmVjNCBvZmZzZXRQcm9qZWN0ZWRQb2ludD11X21hdHJpeCp2ZWM0KGFfcG9zK3ZlYzIoMSwwKSwwLDEpO3ZlYzIgYT1wcm9qZWN0ZWRQb2ludC54eS9wcm9qZWN0ZWRQb2ludC53O3ZlYzIgYj1vZmZzZXRQcm9qZWN0ZWRQb2ludC54eS9vZmZzZXRQcm9qZWN0ZWRQb2ludC53O3N5bWJvbF9yb3RhdGlvbj1hdGFuKChiLnktYS55KS91X2FzcGVjdF9yYXRpbyxiLngtYS54KTt9aGlnaHAgZmxvYXQgYW5nbGVfc2luPXNpbihzZWdtZW50X2FuZ2xlK3N5bWJvbF9yb3RhdGlvbik7aGlnaHAgZmxvYXQgYW5nbGVfY29zPWNvcyhzZWdtZW50X2FuZ2xlK3N5bWJvbF9yb3RhdGlvbik7bWF0MiByb3RhdGlvbl9tYXRyaXg9bWF0MihhbmdsZV9jb3MsLTEuMCphbmdsZV9zaW4sYW5nbGVfc2luLGFuZ2xlX2Nvcyk7dmVjNCBwcm9qZWN0ZWRfcG9zPXVfbGFiZWxfcGxhbmVfbWF0cml4KnZlYzQoYV9wcm9qZWN0ZWRfcG9zLnh5LDAuMCwxLjApO2dsX1Bvc2l0aW9uPXVfY29vcmRfbWF0cml4KnZlYzQocHJvamVjdGVkX3Bvcy54eS9wcm9qZWN0ZWRfcG9zLncrcm90YXRpb25fbWF0cml4KihhX29mZnNldC8zMi4wKmZvbnRTY2FsZSksMC4wLDEuMCk7dl90ZXg9YV90ZXgvdV90ZXhzaXplO3ZlYzIgZmFkZV9vcGFjaXR5PXVucGFja19vcGFjaXR5KGFfZmFkZV9vcGFjaXR5KTtmbG9hdCBmYWRlX2NoYW5nZT1mYWRlX29wYWNpdHlbMV0gPiAwLjUgPyB1X2ZhZGVfY2hhbmdlIDotdV9mYWRlX2NoYW5nZTt2X2ZhZGVfb3BhY2l0eT1tYXgoMC4wLG1pbigxLjAsZmFkZV9vcGFjaXR5WzBdK2ZhZGVfY2hhbmdlKSk7fVwiKSxsaT1jaShcIiNkZWZpbmUgU0RGX1BYIDguMFxcbnVuaWZvcm0gYm9vbCB1X2lzX2hhbG87dW5pZm9ybSBzYW1wbGVyMkQgdV90ZXh0dXJlO3VuaWZvcm0gaGlnaHAgZmxvYXQgdV9nYW1tYV9zY2FsZTt1bmlmb3JtIGxvd3AgZmxvYXQgdV9kZXZpY2VfcGl4ZWxfcmF0aW87dW5pZm9ybSBib29sIHVfaXNfdGV4dDt2YXJ5aW5nIHZlYzIgdl9kYXRhMDt2YXJ5aW5nIHZlYzMgdl9kYXRhMTtcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGhpZ2hwIHZlYzQgZmlsbF9jb2xvclxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgdmVjNCBoYWxvX2NvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgaGFsb193aWR0aFxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBoYWxvX2JsdXJcXG52b2lkIG1haW4oKSB7XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBmaWxsX2NvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgaGlnaHAgdmVjNCBoYWxvX2NvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBvcGFjaXR5XFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBoYWxvX3dpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGluaXRpYWxpemUgbG93cCBmbG9hdCBoYWxvX2JsdXJcXG5mbG9hdCBFREdFX0dBTU1BPTAuMTA1L3VfZGV2aWNlX3BpeGVsX3JhdGlvO3ZlYzIgdGV4PXZfZGF0YTAueHk7ZmxvYXQgZ2FtbWFfc2NhbGU9dl9kYXRhMS54O2Zsb2F0IHNpemU9dl9kYXRhMS55O2Zsb2F0IGZhZGVfb3BhY2l0eT12X2RhdGExWzJdO2Zsb2F0IGZvbnRTY2FsZT11X2lzX3RleHQgPyBzaXplLzI0LjAgOiBzaXplO2xvd3AgdmVjNCBjb2xvcj1maWxsX2NvbG9yO2hpZ2hwIGZsb2F0IGdhbW1hPUVER0VfR0FNTUEvKGZvbnRTY2FsZSp1X2dhbW1hX3NjYWxlKTtsb3dwIGZsb2F0IGJ1ZmY9KDI1Ni4wLTY0LjApLzI1Ni4wO2lmICh1X2lzX2hhbG8pIHtjb2xvcj1oYWxvX2NvbG9yO2dhbW1hPShoYWxvX2JsdXIqMS4xOS9TREZfUFgrRURHRV9HQU1NQSkvKGZvbnRTY2FsZSp1X2dhbW1hX3NjYWxlKTtidWZmPSg2LjAtaGFsb193aWR0aC9mb250U2NhbGUpL1NERl9QWDt9bG93cCBmbG9hdCBkaXN0PXRleHR1cmUyRCh1X3RleHR1cmUsdGV4KS5hO2hpZ2hwIGZsb2F0IGdhbW1hX3NjYWxlZD1nYW1tYSpnYW1tYV9zY2FsZTtoaWdocCBmbG9hdCBhbHBoYT1zbW9vdGhzdGVwKGJ1ZmYtZ2FtbWFfc2NhbGVkLGJ1ZmYrZ2FtbWFfc2NhbGVkLGRpc3QpO2dsX0ZyYWdDb2xvcj1jb2xvciooYWxwaGEqb3BhY2l0eSpmYWRlX29wYWNpdHkpO1xcbiNpZmRlZiBPVkVSRFJBV19JTlNQRUNUT1JcXG5nbF9GcmFnQ29sb3I9dmVjNCgxLjApO1xcbiNlbmRpZlxcbn1cIixcImNvbnN0IGZsb2F0IFBJPTMuMTQxNTkyNjUzNTg5NzkzO2F0dHJpYnV0ZSB2ZWM0IGFfcG9zX29mZnNldDthdHRyaWJ1dGUgdmVjNCBhX2RhdGE7YXR0cmlidXRlIHZlYzMgYV9wcm9qZWN0ZWRfcG9zO2F0dHJpYnV0ZSBmbG9hdCBhX2ZhZGVfb3BhY2l0eTt1bmlmb3JtIGJvb2wgdV9pc19zaXplX3pvb21fY29uc3RhbnQ7dW5pZm9ybSBib29sIHVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50O3VuaWZvcm0gaGlnaHAgZmxvYXQgdV9zaXplX3Q7dW5pZm9ybSBoaWdocCBmbG9hdCB1X3NpemU7dW5pZm9ybSBtYXQ0IHVfbWF0cml4O3VuaWZvcm0gbWF0NCB1X2xhYmVsX3BsYW5lX21hdHJpeDt1bmlmb3JtIG1hdDQgdV9jb29yZF9tYXRyaXg7dW5pZm9ybSBib29sIHVfaXNfdGV4dDt1bmlmb3JtIGJvb2wgdV9waXRjaF93aXRoX21hcDt1bmlmb3JtIGhpZ2hwIGZsb2F0IHVfcGl0Y2g7dW5pZm9ybSBib29sIHVfcm90YXRlX3N5bWJvbDt1bmlmb3JtIGhpZ2hwIGZsb2F0IHVfYXNwZWN0X3JhdGlvO3VuaWZvcm0gaGlnaHAgZmxvYXQgdV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlO3VuaWZvcm0gZmxvYXQgdV9mYWRlX2NoYW5nZTt1bmlmb3JtIHZlYzIgdV90ZXhzaXplO3ZhcnlpbmcgdmVjMiB2X2RhdGEwO3ZhcnlpbmcgdmVjMyB2X2RhdGExO1xcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgaGlnaHAgdmVjNCBmaWxsX2NvbG9yXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBoaWdocCB2ZWM0IGhhbG9fY29sb3JcXG4jcHJhZ21hIG1hcGJveDogZGVmaW5lIGxvd3AgZmxvYXQgb3BhY2l0eVxcbiNwcmFnbWEgbWFwYm94OiBkZWZpbmUgbG93cCBmbG9hdCBoYWxvX3dpZHRoXFxuI3ByYWdtYSBtYXBib3g6IGRlZmluZSBsb3dwIGZsb2F0IGhhbG9fYmx1clxcbnZvaWQgbWFpbigpIHtcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IGZpbGxfY29sb3JcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBoaWdocCB2ZWM0IGhhbG9fY29sb3JcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IG9wYWNpdHlcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGhhbG9fd2lkdGhcXG4jcHJhZ21hIG1hcGJveDogaW5pdGlhbGl6ZSBsb3dwIGZsb2F0IGhhbG9fYmx1clxcbnZlYzIgYV9wb3M9YV9wb3Nfb2Zmc2V0Lnh5O3ZlYzIgYV9vZmZzZXQ9YV9wb3Nfb2Zmc2V0Lnp3O3ZlYzIgYV90ZXg9YV9kYXRhLnh5O3ZlYzIgYV9zaXplPWFfZGF0YS56dztoaWdocCBmbG9hdCBzZWdtZW50X2FuZ2xlPS1hX3Byb2plY3RlZF9wb3NbMl07ZmxvYXQgc2l6ZTtpZiAoIXVfaXNfc2l6ZV96b29tX2NvbnN0YW50ICYmICF1X2lzX3NpemVfZmVhdHVyZV9jb25zdGFudCkge3NpemU9bWl4KGFfc2l6ZVswXSxhX3NpemVbMV0sdV9zaXplX3QpLzI1Ni4wO30gZWxzZSBpZiAodV9pc19zaXplX3pvb21fY29uc3RhbnQgJiYgIXVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50KSB7c2l6ZT1hX3NpemVbMF0vMjU2LjA7fSBlbHNlIGlmICghdV9pc19zaXplX3pvb21fY29uc3RhbnQgJiYgdV9pc19zaXplX2ZlYXR1cmVfY29uc3RhbnQpIHtzaXplPXVfc2l6ZTt9IGVsc2Uge3NpemU9dV9zaXplO312ZWM0IHByb2plY3RlZFBvaW50PXVfbWF0cml4KnZlYzQoYV9wb3MsMCwxKTtoaWdocCBmbG9hdCBjYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlPXByb2plY3RlZFBvaW50Lnc7aGlnaHAgZmxvYXQgZGlzdGFuY2VfcmF0aW89dV9waXRjaF93aXRoX21hcCA/XFxuY2FtZXJhX3RvX2FuY2hvcl9kaXN0YW5jZS91X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2UgOlxcbnVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZS9jYW1lcmFfdG9fYW5jaG9yX2Rpc3RhbmNlO2hpZ2hwIGZsb2F0IHBlcnNwZWN0aXZlX3JhdGlvPWNsYW1wKDAuNSswLjUqZGlzdGFuY2VfcmF0aW8sMC4wLDQuMCk7c2l6ZSo9cGVyc3BlY3RpdmVfcmF0aW87ZmxvYXQgZm9udFNjYWxlPXVfaXNfdGV4dCA/IHNpemUvMjQuMCA6IHNpemU7aGlnaHAgZmxvYXQgc3ltYm9sX3JvdGF0aW9uPTAuMDtpZiAodV9yb3RhdGVfc3ltYm9sKSB7dmVjNCBvZmZzZXRQcm9qZWN0ZWRQb2ludD11X21hdHJpeCp2ZWM0KGFfcG9zK3ZlYzIoMSwwKSwwLDEpO3ZlYzIgYT1wcm9qZWN0ZWRQb2ludC54eS9wcm9qZWN0ZWRQb2ludC53O3ZlYzIgYj1vZmZzZXRQcm9qZWN0ZWRQb2ludC54eS9vZmZzZXRQcm9qZWN0ZWRQb2ludC53O3N5bWJvbF9yb3RhdGlvbj1hdGFuKChiLnktYS55KS91X2FzcGVjdF9yYXRpbyxiLngtYS54KTt9aGlnaHAgZmxvYXQgYW5nbGVfc2luPXNpbihzZWdtZW50X2FuZ2xlK3N5bWJvbF9yb3RhdGlvbik7aGlnaHAgZmxvYXQgYW5nbGVfY29zPWNvcyhzZWdtZW50X2FuZ2xlK3N5bWJvbF9yb3RhdGlvbik7bWF0MiByb3RhdGlvbl9tYXRyaXg9bWF0MihhbmdsZV9jb3MsLTEuMCphbmdsZV9zaW4sYW5nbGVfc2luLGFuZ2xlX2Nvcyk7dmVjNCBwcm9qZWN0ZWRfcG9zPXVfbGFiZWxfcGxhbmVfbWF0cml4KnZlYzQoYV9wcm9qZWN0ZWRfcG9zLnh5LDAuMCwxLjApO2dsX1Bvc2l0aW9uPXVfY29vcmRfbWF0cml4KnZlYzQocHJvamVjdGVkX3Bvcy54eS9wcm9qZWN0ZWRfcG9zLncrcm90YXRpb25fbWF0cml4KihhX29mZnNldC8zMi4wKmZvbnRTY2FsZSksMC4wLDEuMCk7ZmxvYXQgZ2FtbWFfc2NhbGU9Z2xfUG9zaXRpb24udzt2ZWMyIHRleD1hX3RleC91X3RleHNpemU7dmVjMiBmYWRlX29wYWNpdHk9dW5wYWNrX29wYWNpdHkoYV9mYWRlX29wYWNpdHkpO2Zsb2F0IGZhZGVfY2hhbmdlPWZhZGVfb3BhY2l0eVsxXSA+IDAuNSA/IHVfZmFkZV9jaGFuZ2UgOi11X2ZhZGVfY2hhbmdlO2Zsb2F0IGludGVycG9sYXRlZF9mYWRlX29wYWNpdHk9bWF4KDAuMCxtaW4oMS4wLGZhZGVfb3BhY2l0eVswXStmYWRlX2NoYW5nZSkpO3ZfZGF0YTA9dmVjMih0ZXgueCx0ZXgueSk7dl9kYXRhMT12ZWMzKGdhbW1hX3NjYWxlLHNpemUsaW50ZXJwb2xhdGVkX2ZhZGVfb3BhY2l0eSk7fVwiKTtmdW5jdGlvbiBjaSh0LGUpe3ZhciBpPS8jcHJhZ21hIG1hcGJveDogKFtcXHddKykgKFtcXHddKykgKFtcXHddKykgKFtcXHddKykvZyxvPXt9O3JldHVybiB7ZnJhZ21lbnRTb3VyY2U6dD10LnJlcGxhY2UoaSxmdW5jdGlvbih0LGUsaSxyLGEpe3JldHVybiBvW2FdPSEwLFwiZGVmaW5lXCI9PT1lP1wiXFxuI2lmbmRlZiBIQVNfVU5JRk9STV91X1wiK2ErXCJcXG52YXJ5aW5nIFwiK2krXCIgXCIrcitcIiBcIithK1wiO1xcbiNlbHNlXFxudW5pZm9ybSBcIitpK1wiIFwiK3IrXCIgdV9cIithK1wiO1xcbiNlbmRpZlxcblwiOlwiXFxuI2lmZGVmIEhBU19VTklGT1JNX3VfXCIrYStcIlxcbiAgICBcIitpK1wiIFwiK3IrXCIgXCIrYStcIiA9IHVfXCIrYStcIjtcXG4jZW5kaWZcXG5cIn0pLHZlcnRleFNvdXJjZTplPWUucmVwbGFjZShpLGZ1bmN0aW9uKHQsZSxpLHIsYSl7dmFyIG49XCJmbG9hdFwiPT09cj9cInZlYzJcIjpcInZlYzRcIixzPWEubWF0Y2goL2NvbG9yLyk/XCJjb2xvclwiOm47cmV0dXJuIG9bYV0/XCJkZWZpbmVcIj09PWU/XCJcXG4jaWZuZGVmIEhBU19VTklGT1JNX3VfXCIrYStcIlxcbnVuaWZvcm0gbG93cCBmbG9hdCB1X1wiK2ErXCJfdDtcXG5hdHRyaWJ1dGUgXCIraStcIiBcIituK1wiIGFfXCIrYStcIjtcXG52YXJ5aW5nIFwiK2krXCIgXCIrcitcIiBcIithK1wiO1xcbiNlbHNlXFxudW5pZm9ybSBcIitpK1wiIFwiK3IrXCIgdV9cIithK1wiO1xcbiNlbmRpZlxcblwiOlwidmVjNFwiPT09cz9cIlxcbiNpZm5kZWYgSEFTX1VOSUZPUk1fdV9cIithK1wiXFxuICAgIFwiK2ErXCIgPSBhX1wiK2ErXCI7XFxuI2Vsc2VcXG4gICAgXCIraStcIiBcIityK1wiIFwiK2ErXCIgPSB1X1wiK2ErXCI7XFxuI2VuZGlmXFxuXCI6XCJcXG4jaWZuZGVmIEhBU19VTklGT1JNX3VfXCIrYStcIlxcbiAgICBcIithK1wiID0gdW5wYWNrX21peF9cIitzK1wiKGFfXCIrYStcIiwgdV9cIithK1wiX3QpO1xcbiNlbHNlXFxuICAgIFwiK2krXCIgXCIrcitcIiBcIithK1wiID0gdV9cIithK1wiO1xcbiNlbmRpZlxcblwiOlwiZGVmaW5lXCI9PT1lP1wiXFxuI2lmbmRlZiBIQVNfVU5JRk9STV91X1wiK2ErXCJcXG51bmlmb3JtIGxvd3AgZmxvYXQgdV9cIithK1wiX3Q7XFxuYXR0cmlidXRlIFwiK2krXCIgXCIrbitcIiBhX1wiK2ErXCI7XFxuI2Vsc2VcXG51bmlmb3JtIFwiK2krXCIgXCIrcitcIiB1X1wiK2ErXCI7XFxuI2VuZGlmXFxuXCI6XCJ2ZWM0XCI9PT1zP1wiXFxuI2lmbmRlZiBIQVNfVU5JRk9STV91X1wiK2ErXCJcXG4gICAgXCIraStcIiBcIityK1wiIFwiK2ErXCIgPSBhX1wiK2ErXCI7XFxuI2Vsc2VcXG4gICAgXCIraStcIiBcIityK1wiIFwiK2ErXCIgPSB1X1wiK2ErXCI7XFxuI2VuZGlmXFxuXCI6XCJcXG4jaWZuZGVmIEhBU19VTklGT1JNX3VfXCIrYStcIlxcbiAgICBcIitpK1wiIFwiK3IrXCIgXCIrYStcIiA9IHVucGFja19taXhfXCIrcytcIihhX1wiK2ErXCIsIHVfXCIrYStcIl90KTtcXG4jZWxzZVxcbiAgICBcIitpK1wiIFwiK3IrXCIgXCIrYStcIiA9IHVfXCIrYStcIjtcXG4jZW5kaWZcXG5cIn0pfX12YXIgdWk9T2JqZWN0LmZyZWV6ZSh7cHJlbHVkZTpGZSxiYWNrZ3JvdW5kOlVlLGJhY2tncm91bmRQYXR0ZXJuOk5lLGNpcmNsZTpaZSxjbGlwcGluZ01hc2s6amUsaGVhdG1hcDpxZSxoZWF0bWFwVGV4dHVyZTpWZSxjb2xsaXNpb25Cb3g6R2UsY29sbGlzaW9uQ2lyY2xlOldlLGRlYnVnOlhlLGZpbGw6SGUsZmlsbE91dGxpbmU6S2UsZmlsbE91dGxpbmVQYXR0ZXJuOlllLGZpbGxQYXR0ZXJuOkplLGZpbGxFeHRydXNpb246UWUsZmlsbEV4dHJ1c2lvblBhdHRlcm46JGUsaGlsbHNoYWRlUHJlcGFyZTp0aSxoaWxsc2hhZGU6ZWksbGluZTppaSxsaW5lR3JhZGllbnQ6b2ksbGluZVBhdHRlcm46cmksbGluZVNERjphaSxyYXN0ZXI6bmksc3ltYm9sSWNvbjpzaSxzeW1ib2xTREY6bGl9KSxoaT1mdW5jdGlvbigpe3RoaXMuYm91bmRQcm9ncmFtPW51bGwsdGhpcy5ib3VuZExheW91dFZlcnRleEJ1ZmZlcj1udWxsLHRoaXMuYm91bmRQYWludFZlcnRleEJ1ZmZlcnM9W10sdGhpcy5ib3VuZEluZGV4QnVmZmVyPW51bGwsdGhpcy5ib3VuZFZlcnRleE9mZnNldD1udWxsLHRoaXMuYm91bmREeW5hbWljVmVydGV4QnVmZmVyPW51bGwsdGhpcy52YW89bnVsbDt9O2hpLnByb3RvdHlwZS5iaW5kPWZ1bmN0aW9uKHQsZSxpLG8scixhLG4scyl7dGhpcy5jb250ZXh0PXQ7Zm9yKHZhciBsPXRoaXMuYm91bmRQYWludFZlcnRleEJ1ZmZlcnMubGVuZ3RoIT09by5sZW5ndGgsYz0wOyFsJiZjPG8ubGVuZ3RoO2MrKyl0aGlzLmJvdW5kUGFpbnRWZXJ0ZXhCdWZmZXJzW2NdIT09b1tjXSYmKGw9ITApO3ZhciB1PSF0aGlzLnZhb3x8dGhpcy5ib3VuZFByb2dyYW0hPT1lfHx0aGlzLmJvdW5kTGF5b3V0VmVydGV4QnVmZmVyIT09aXx8bHx8dGhpcy5ib3VuZEluZGV4QnVmZmVyIT09cnx8dGhpcy5ib3VuZFZlcnRleE9mZnNldCE9PWF8fHRoaXMuYm91bmREeW5hbWljVmVydGV4QnVmZmVyIT09bnx8dGhpcy5ib3VuZER5bmFtaWNWZXJ0ZXhCdWZmZXIyIT09czshdC5leHRWZXJ0ZXhBcnJheU9iamVjdHx8dT90aGlzLmZyZXNoQmluZChlLGksbyxyLGEsbixzKToodC5iaW5kVmVydGV4QXJyYXlPRVMuc2V0KHRoaXMudmFvKSxuJiZuLmJpbmQoKSxyJiZyLmR5bmFtaWNEcmF3JiZyLmJpbmQoKSxzJiZzLmJpbmQoKSk7fSxoaS5wcm90b3R5cGUuZnJlc2hCaW5kPWZ1bmN0aW9uKHQsZSxpLG8scixhLG4pe3ZhciBzLGw9dC5udW1BdHRyaWJ1dGVzLGM9dGhpcy5jb250ZXh0LHU9Yy5nbDtpZihjLmV4dFZlcnRleEFycmF5T2JqZWN0KXRoaXMudmFvJiZ0aGlzLmRlc3Ryb3koKSx0aGlzLnZhbz1jLmV4dFZlcnRleEFycmF5T2JqZWN0LmNyZWF0ZVZlcnRleEFycmF5T0VTKCksYy5iaW5kVmVydGV4QXJyYXlPRVMuc2V0KHRoaXMudmFvKSxzPTAsdGhpcy5ib3VuZFByb2dyYW09dCx0aGlzLmJvdW5kTGF5b3V0VmVydGV4QnVmZmVyPWUsdGhpcy5ib3VuZFBhaW50VmVydGV4QnVmZmVycz1pLHRoaXMuYm91bmRJbmRleEJ1ZmZlcj1vLHRoaXMuYm91bmRWZXJ0ZXhPZmZzZXQ9cix0aGlzLmJvdW5kRHluYW1pY1ZlcnRleEJ1ZmZlcj1hLHRoaXMuYm91bmREeW5hbWljVmVydGV4QnVmZmVyMj1uO2Vsc2V7cz1jLmN1cnJlbnROdW1BdHRyaWJ1dGVzfHwwO2Zvcih2YXIgaD1sO2g8cztoKyspdS5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoaCk7fWUuZW5hYmxlQXR0cmlidXRlcyh1LHQpO2Zvcih2YXIgcD0wLGQ9aTtwPGQubGVuZ3RoO3ArPTEpe2RbcF0uZW5hYmxlQXR0cmlidXRlcyh1LHQpO31hJiZhLmVuYWJsZUF0dHJpYnV0ZXModSx0KSxuJiZuLmVuYWJsZUF0dHJpYnV0ZXModSx0KSxlLmJpbmQoKSxlLnNldFZlcnRleEF0dHJpYlBvaW50ZXJzKHUsdCxyKTtmb3IodmFyIF89MCxmPWk7XzxmLmxlbmd0aDtfKz0xKXt2YXIgbT1mW19dO20uYmluZCgpLG0uc2V0VmVydGV4QXR0cmliUG9pbnRlcnModSx0LHIpO31hJiYoYS5iaW5kKCksYS5zZXRWZXJ0ZXhBdHRyaWJQb2ludGVycyh1LHQscikpLG8mJm8uYmluZCgpLG4mJihuLmJpbmQoKSxuLnNldFZlcnRleEF0dHJpYlBvaW50ZXJzKHUsdCxyKSksYy5jdXJyZW50TnVtQXR0cmlidXRlcz1sO30saGkucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLnZhbyYmKHRoaXMuY29udGV4dC5leHRWZXJ0ZXhBcnJheU9iamVjdC5kZWxldGVWZXJ0ZXhBcnJheU9FUyh0aGlzLnZhbyksdGhpcy52YW89bnVsbCk7fTt2YXIgcGk9ZnVuY3Rpb24odCxlLGksbyxyKXt2YXIgYT10LmdsO3RoaXMucHJvZ3JhbT1hLmNyZWF0ZVByb2dyYW0oKTt2YXIgbj1pLmRlZmluZXMoKTtyJiZuLnB1c2goXCIjZGVmaW5lIE9WRVJEUkFXX0lOU1BFQ1RPUjtcIik7dmFyIHM9bi5jb25jYXQoRmUuZnJhZ21lbnRTb3VyY2UsZS5mcmFnbWVudFNvdXJjZSkuam9pbihcIlxcblwiKSxsPW4uY29uY2F0KEZlLnZlcnRleFNvdXJjZSxlLnZlcnRleFNvdXJjZSkuam9pbihcIlxcblwiKSxjPWEuY3JlYXRlU2hhZGVyKGEuRlJBR01FTlRfU0hBREVSKTthLnNoYWRlclNvdXJjZShjLHMpLGEuY29tcGlsZVNoYWRlcihjKSxhLmF0dGFjaFNoYWRlcih0aGlzLnByb2dyYW0sYyk7dmFyIHU9YS5jcmVhdGVTaGFkZXIoYS5WRVJURVhfU0hBREVSKTthLnNoYWRlclNvdXJjZSh1LGwpLGEuY29tcGlsZVNoYWRlcih1KSxhLmF0dGFjaFNoYWRlcih0aGlzLnByb2dyYW0sdSk7Zm9yKHZhciBoPWkubGF5b3V0QXR0cmlidXRlc3x8W10scD0wO3A8aC5sZW5ndGg7cCsrKWEuYmluZEF0dHJpYkxvY2F0aW9uKHRoaXMucHJvZ3JhbSxwLGhbcF0ubmFtZSk7YS5saW5rUHJvZ3JhbSh0aGlzLnByb2dyYW0pLHRoaXMubnVtQXR0cmlidXRlcz1hLmdldFByb2dyYW1QYXJhbWV0ZXIodGhpcy5wcm9ncmFtLGEuQUNUSVZFX0FUVFJJQlVURVMpLHRoaXMuYXR0cmlidXRlcz17fTtmb3IodmFyIGQ9e30sXz0wO188dGhpcy5udW1BdHRyaWJ1dGVzO18rKyl7dmFyIGY9YS5nZXRBY3RpdmVBdHRyaWIodGhpcy5wcm9ncmFtLF8pO2YmJih0aGlzLmF0dHJpYnV0ZXNbZi5uYW1lXT1hLmdldEF0dHJpYkxvY2F0aW9uKHRoaXMucHJvZ3JhbSxmLm5hbWUpKTt9Zm9yKHZhciBtPWEuZ2V0UHJvZ3JhbVBhcmFtZXRlcih0aGlzLnByb2dyYW0sYS5BQ1RJVkVfVU5JRk9STVMpLGc9MDtnPG07ZysrKXt2YXIgdj1hLmdldEFjdGl2ZVVuaWZvcm0odGhpcy5wcm9ncmFtLGcpO3YmJihkW3YubmFtZV09YS5nZXRVbmlmb3JtTG9jYXRpb24odGhpcy5wcm9ncmFtLHYubmFtZSkpO310aGlzLmZpeGVkVW5pZm9ybXM9byh0LGQpLHRoaXMuYmluZGVyVW5pZm9ybXM9aS5nZXRVbmlmb3Jtcyh0LGQpO307ZnVuY3Rpb24gZGkoZSxpLG8pe3ZhciByPTEvY2UobywxLGkudHJhbnNmb3JtLnRpbGVab29tKSxhPU1hdGgucG93KDIsby50aWxlSUQub3ZlcnNjYWxlZFopLG49by50aWxlU2l6ZSpNYXRoLnBvdygyLGkudHJhbnNmb3JtLnRpbGVab29tKS9hLHM9biooby50aWxlSUQuY2Fub25pY2FsLngrby50aWxlSUQud3JhcCphKSxsPW4qby50aWxlSUQuY2Fub25pY2FsLnk7cmV0dXJuIHt1X2ltYWdlOjAsdV90ZXhzaXplOm8uaW1hZ2VBdGxhc1RleHR1cmUuc2l6ZSx1X3NjYWxlOlt0LmJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyxyLGUuZnJvbVNjYWxlLGUudG9TY2FsZV0sdV9mYWRlOmUudCx1X3BpeGVsX2Nvb3JkX3VwcGVyOltzPj4xNixsPj4xNl0sdV9waXhlbF9jb29yZF9sb3dlcjpbNjU1MzUmcyw2NTUzNSZsXX19cGkucHJvdG90eXBlLmRyYXc9ZnVuY3Rpb24odCxlLGksbyxyLGEsbixzLGwsYyx1LGgscCxkLF8sZil7dmFyIG0sZz10LmdsO2Zvcih2YXIgdiBpbiB0LnByb2dyYW0uc2V0KHRoaXMucHJvZ3JhbSksdC5zZXREZXB0aE1vZGUoaSksdC5zZXRTdGVuY2lsTW9kZShvKSx0LnNldENvbG9yTW9kZShyKSx0LnNldEN1bGxGYWNlKGEpLHRoaXMuZml4ZWRVbmlmb3Jtcyl0aGlzLmZpeGVkVW5pZm9ybXNbdl0uc2V0KG5bdl0pO2QmJmQuc2V0VW5pZm9ybXModCx0aGlzLmJpbmRlclVuaWZvcm1zLGgse3pvb206cH0pO2Zvcih2YXIgeT0obT17fSxtW2cuTElORVNdPTIsbVtnLlRSSUFOR0xFU109MyxtW2cuTElORV9TVFJJUF09MSxtKVtlXSx4PTAsYj11LmdldCgpO3g8Yi5sZW5ndGg7eCs9MSl7dmFyIHc9Ylt4XSxFPXcudmFvc3x8KHcudmFvcz17fSk7KEVbc118fChFW3NdPW5ldyBoaSkpLmJpbmQodCx0aGlzLGwsZD9kLmdldFBhaW50VmVydGV4QnVmZmVycygpOltdLGMsdy52ZXJ0ZXhPZmZzZXQsXyxmKSxnLmRyYXdFbGVtZW50cyhlLHcucHJpbWl0aXZlTGVuZ3RoKnksZy5VTlNJR05FRF9TSE9SVCx3LnByaW1pdGl2ZU9mZnNldCp5KjIpO319O3ZhciBfaT1mdW5jdGlvbihlLGksbyxyKXt2YXIgYT1pLnN0eWxlLmxpZ2h0LG49YS5wcm9wZXJ0aWVzLmdldChcInBvc2l0aW9uXCIpLHM9W24ueCxuLnksbi56XSxsPXQuY3JlYXRlJDEoKTtcInZpZXdwb3J0XCI9PT1hLnByb3BlcnRpZXMuZ2V0KFwiYW5jaG9yXCIpJiZ0LmZyb21Sb3RhdGlvbihsLC1pLnRyYW5zZm9ybS5hbmdsZSksdC50cmFuc2Zvcm1NYXQzKHMscyxsKTt2YXIgYz1hLnByb3BlcnRpZXMuZ2V0KFwiY29sb3JcIik7cmV0dXJuIHt1X21hdHJpeDplLHVfbGlnaHRwb3M6cyx1X2xpZ2h0aW50ZW5zaXR5OmEucHJvcGVydGllcy5nZXQoXCJpbnRlbnNpdHlcIiksdV9saWdodGNvbG9yOltjLnIsYy5nLGMuYl0sdV92ZXJ0aWNhbF9ncmFkaWVudDorbyx1X29wYWNpdHk6cn19LGZpPWZ1bmN0aW9uKGUsaSxvLHIsYSxuLHMpe3JldHVybiB0LmV4dGVuZChfaShlLGksbyxyKSxkaShuLGkscykse3VfaGVpZ2h0X2ZhY3RvcjotTWF0aC5wb3coMixhLm92ZXJzY2FsZWRaKS9zLnRpbGVTaXplLzh9KX0sbWk9ZnVuY3Rpb24odCl7cmV0dXJuIHt1X21hdHJpeDp0fX0sZ2k9ZnVuY3Rpb24oZSxpLG8scil7cmV0dXJuIHQuZXh0ZW5kKG1pKGUpLGRpKG8saSxyKSl9LHZpPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHt1X21hdHJpeDp0LHVfd29ybGQ6ZX19LHlpPWZ1bmN0aW9uKGUsaSxvLHIsYSl7cmV0dXJuIHQuZXh0ZW5kKGdpKGUsaSxvLHIpLHt1X3dvcmxkOmF9KX0seGk9ZnVuY3Rpb24oZSxpLG8scil7dmFyIGEsbixzPWUudHJhbnNmb3JtO2lmKFwibWFwXCI9PT1yLnBhaW50LmdldChcImNpcmNsZS1waXRjaC1hbGlnbm1lbnRcIikpe3ZhciBsPWNlKG8sMSxzLnpvb20pO2E9ITAsbj1bbCxsXTt9ZWxzZSBhPSExLG49cy5waXhlbHNUb0dMVW5pdHM7cmV0dXJuIHt1X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2U6cy5jYW1lcmFUb0NlbnRlckRpc3RhbmNlLHVfc2NhbGVfd2l0aF9tYXA6KyhcIm1hcFwiPT09ci5wYWludC5nZXQoXCJjaXJjbGUtcGl0Y2gtc2NhbGVcIikpLHVfbWF0cml4OmUudHJhbnNsYXRlUG9zTWF0cml4KGkucG9zTWF0cml4LG8sci5wYWludC5nZXQoXCJjaXJjbGUtdHJhbnNsYXRlXCIpLHIucGFpbnQuZ2V0KFwiY2lyY2xlLXRyYW5zbGF0ZS1hbmNob3JcIikpLHVfcGl0Y2hfd2l0aF9tYXA6K2EsdV9kZXZpY2VfcGl4ZWxfcmF0aW86dC5icm93c2VyLmRldmljZVBpeGVsUmF0aW8sdV9leHRydWRlX3NjYWxlOm59fSxiaT1mdW5jdGlvbihlLGkpe3JldHVybiB7dV9tYXRyaXg6bmV3IHQuVW5pZm9ybU1hdHJpeDRmKGUsaS51X21hdHJpeCksdV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlOm5ldyB0LlVuaWZvcm0xZihlLGkudV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlKSx1X3BpeGVsc190b190aWxlX3VuaXRzOm5ldyB0LlVuaWZvcm0xZihlLGkudV9waXhlbHNfdG9fdGlsZV91bml0cyksdV9leHRydWRlX3NjYWxlOm5ldyB0LlVuaWZvcm0yZihlLGkudV9leHRydWRlX3NjYWxlKSx1X292ZXJzY2FsZV9mYWN0b3I6bmV3IHQuVW5pZm9ybTFmKGUsaS51X292ZXJzY2FsZV9mYWN0b3IpfX0sd2k9ZnVuY3Rpb24odCxlLGkpe3ZhciBvPWNlKGksMSxlLnpvb20pLHI9TWF0aC5wb3coMixlLnpvb20taS50aWxlSUQub3ZlcnNjYWxlZFopLGE9aS50aWxlSUQub3ZlcnNjYWxlRmFjdG9yKCk7cmV0dXJuIHt1X21hdHJpeDp0LHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZTplLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2UsdV9waXhlbHNfdG9fdGlsZV91bml0czpvLHVfZXh0cnVkZV9zY2FsZTpbZS5waXhlbHNUb0dMVW5pdHNbMF0vKG8qciksZS5waXhlbHNUb0dMVW5pdHNbMV0vKG8qcildLHVfb3ZlcnNjYWxlX2ZhY3RvcjphfX0sRWk9ZnVuY3Rpb24odCxlKXtyZXR1cm4ge3VfbWF0cml4OnQsdV9jb2xvcjplfX0sVGk9ZnVuY3Rpb24odCl7cmV0dXJuIHt1X21hdHJpeDp0fX0sSWk9ZnVuY3Rpb24odCxlLGksbyl7cmV0dXJuIHt1X21hdHJpeDp0LHVfZXh0cnVkZV9zY2FsZTpjZShlLDEsaSksdV9pbnRlbnNpdHk6b319LENpPWZ1bmN0aW9uKGUsaSxvLHIpe3ZhciBhPXQuY3JlYXRlKCk7dC5vcnRobyhhLDAsZS53aWR0aCxlLmhlaWdodCwwLDAsMSk7dmFyIG49ZS5jb250ZXh0LmdsO3JldHVybiB7dV9tYXRyaXg6YSx1X3dvcmxkOltuLmRyYXdpbmdCdWZmZXJXaWR0aCxuLmRyYXdpbmdCdWZmZXJIZWlnaHRdLHVfaW1hZ2U6byx1X2NvbG9yX3JhbXA6cix1X29wYWNpdHk6aS5wYWludC5nZXQoXCJoZWF0bWFwLW9wYWNpdHlcIil9fSxTaT1mdW5jdGlvbih0LGUsaSl7dmFyIG89aS5wYWludC5nZXQoXCJoaWxsc2hhZGUtc2hhZG93LWNvbG9yXCIpLHI9aS5wYWludC5nZXQoXCJoaWxsc2hhZGUtaGlnaGxpZ2h0LWNvbG9yXCIpLGE9aS5wYWludC5nZXQoXCJoaWxsc2hhZGUtYWNjZW50LWNvbG9yXCIpLG49aS5wYWludC5nZXQoXCJoaWxsc2hhZGUtaWxsdW1pbmF0aW9uLWRpcmVjdGlvblwiKSooTWF0aC5QSS8xODApO1widmlld3BvcnRcIj09PWkucGFpbnQuZ2V0KFwiaGlsbHNoYWRlLWlsbHVtaW5hdGlvbi1hbmNob3JcIikmJihuLT10LnRyYW5zZm9ybS5hbmdsZSk7dmFyIHM9IXQub3B0aW9ucy5tb3Zpbmc7cmV0dXJuIHt1X21hdHJpeDp0LnRyYW5zZm9ybS5jYWxjdWxhdGVQb3NNYXRyaXgoZS50aWxlSUQudG9VbndyYXBwZWQoKSxzKSx1X2ltYWdlOjAsdV9sYXRyYW5nZTp6aSh0LGUudGlsZUlEKSx1X2xpZ2h0OltpLnBhaW50LmdldChcImhpbGxzaGFkZS1leGFnZ2VyYXRpb25cIiksbl0sdV9zaGFkb3c6byx1X2hpZ2hsaWdodDpyLHVfYWNjZW50OmF9fSxQaT1mdW5jdGlvbihlLGkpe3ZhciBvPWUuZGVtLnN0cmlkZSxyPXQuY3JlYXRlKCk7cmV0dXJuIHQub3J0aG8ociwwLHQuRVhURU5ULC10LkVYVEVOVCwwLDAsMSksdC50cmFuc2xhdGUocixyLFswLC10LkVYVEVOVCwwXSkse3VfbWF0cml4OnIsdV9pbWFnZToxLHVfZGltZW5zaW9uOltvLG9dLHVfem9vbTplLnRpbGVJRC5vdmVyc2NhbGVkWix1X21heHpvb206aX19O2Z1bmN0aW9uIHppKGUsaSl7dmFyIG89TWF0aC5wb3coMixpLmNhbm9uaWNhbC56KSxyPWkuY2Fub25pY2FsLnk7cmV0dXJuIFtuZXcgdC5NZXJjYXRvckNvb3JkaW5hdGUoMCxyL28pLnRvTG5nTGF0KCkubGF0LG5ldyB0Lk1lcmNhdG9yQ29vcmRpbmF0ZSgwLChyKzEpL28pLnRvTG5nTGF0KCkubGF0XX12YXIgTGk9ZnVuY3Rpb24oZSxpLG8pe3ZhciByPWUudHJhbnNmb3JtO3JldHVybiB7dV9tYXRyaXg6a2koZSxpLG8pLHVfcmF0aW86MS9jZShpLDEsci56b29tKSx1X2RldmljZV9waXhlbF9yYXRpbzp0LmJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyx1X3VuaXRzX3RvX3BpeGVsczpbMS9yLnBpeGVsc1RvR0xVbml0c1swXSwxL3IucGl4ZWxzVG9HTFVuaXRzWzFdXX19LERpPWZ1bmN0aW9uKGUsaSxvKXtyZXR1cm4gdC5leHRlbmQoTGkoZSxpLG8pLHt1X2ltYWdlOjB9KX0sTWk9ZnVuY3Rpb24oZSxpLG8scil7dmFyIGE9ZS50cmFuc2Zvcm0sbj1BaShpLGEpO3JldHVybiB7dV9tYXRyaXg6a2koZSxpLG8pLHVfdGV4c2l6ZTppLmltYWdlQXRsYXNUZXh0dXJlLnNpemUsdV9yYXRpbzoxL2NlKGksMSxhLnpvb20pLHVfZGV2aWNlX3BpeGVsX3JhdGlvOnQuYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvLHVfaW1hZ2U6MCx1X3NjYWxlOlt0LmJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbyxuLHIuZnJvbVNjYWxlLHIudG9TY2FsZV0sdV9mYWRlOnIudCx1X3VuaXRzX3RvX3BpeGVsczpbMS9hLnBpeGVsc1RvR0xVbml0c1swXSwxL2EucGl4ZWxzVG9HTFVuaXRzWzFdXX19LFJpPWZ1bmN0aW9uKGUsaSxvLHIsYSl7dmFyIG49ZS50cmFuc2Zvcm0scz1lLmxpbmVBdGxhcyxsPUFpKGksbiksYz1cInJvdW5kXCI9PT1vLmxheW91dC5nZXQoXCJsaW5lLWNhcFwiKSx1PXMuZ2V0RGFzaChyLmZyb20sYyksaD1zLmdldERhc2goci50byxjKSxwPXUud2lkdGgqYS5mcm9tU2NhbGUsZD1oLndpZHRoKmEudG9TY2FsZTtyZXR1cm4gdC5leHRlbmQoTGkoZSxpLG8pLHt1X3BhdHRlcm5zY2FsZV9hOltsL3AsLXUuaGVpZ2h0LzJdLHVfcGF0dGVybnNjYWxlX2I6W2wvZCwtaC5oZWlnaHQvMl0sdV9zZGZnYW1tYTpzLndpZHRoLygyNTYqTWF0aC5taW4ocCxkKSp0LmJyb3dzZXIuZGV2aWNlUGl4ZWxSYXRpbykvMix1X2ltYWdlOjAsdV90ZXhfeV9hOnUueSx1X3RleF95X2I6aC55LHVfbWl4OmEudH0pfTtmdW5jdGlvbiBBaSh0LGUpe3JldHVybiAxL2NlKHQsMSxlLnRpbGVab29tKX1mdW5jdGlvbiBraSh0LGUsaSl7cmV0dXJuIHQudHJhbnNsYXRlUG9zTWF0cml4KGUudGlsZUlELnBvc01hdHJpeCxlLGkucGFpbnQuZ2V0KFwibGluZS10cmFuc2xhdGVcIiksaS5wYWludC5nZXQoXCJsaW5lLXRyYW5zbGF0ZS1hbmNob3JcIikpfXZhciBCaT1mdW5jdGlvbih0LGUsaSxvLHIpe3JldHVybiB7dV9tYXRyaXg6dCx1X3RsX3BhcmVudDplLHVfc2NhbGVfcGFyZW50OmksdV9idWZmZXJfc2NhbGU6MSx1X2ZhZGVfdDpvLm1peCx1X29wYWNpdHk6by5vcGFjaXR5KnIucGFpbnQuZ2V0KFwicmFzdGVyLW9wYWNpdHlcIiksdV9pbWFnZTA6MCx1X2ltYWdlMToxLHVfYnJpZ2h0bmVzc19sb3c6ci5wYWludC5nZXQoXCJyYXN0ZXItYnJpZ2h0bmVzcy1taW5cIiksdV9icmlnaHRuZXNzX2hpZ2g6ci5wYWludC5nZXQoXCJyYXN0ZXItYnJpZ2h0bmVzcy1tYXhcIiksdV9zYXR1cmF0aW9uX2ZhY3Rvcjoobj1yLnBhaW50LmdldChcInJhc3Rlci1zYXR1cmF0aW9uXCIpLG4+MD8xLTEvKDEuMDAxLW4pOi1uKSx1X2NvbnRyYXN0X2ZhY3RvcjooYT1yLnBhaW50LmdldChcInJhc3Rlci1jb250cmFzdFwiKSxhPjA/MS8oMS1hKToxK2EpLHVfc3Bpbl93ZWlnaHRzOk9pKHIucGFpbnQuZ2V0KFwicmFzdGVyLWh1ZS1yb3RhdGVcIikpfTt2YXIgYSxuO307ZnVuY3Rpb24gT2kodCl7dCo9TWF0aC5QSS8xODA7dmFyIGU9TWF0aC5zaW4odCksaT1NYXRoLmNvcyh0KTtyZXR1cm4gWygyKmkrMSkvMywoLU1hdGguc3FydCgzKSplLWkrMSkvMywoTWF0aC5zcXJ0KDMpKmUtaSsxKS8zXX12YXIgRmk9ZnVuY3Rpb24odCxlLGksbyxyLGEsbixzLGwsYyl7dmFyIHU9ci50cmFuc2Zvcm07cmV0dXJuIHt1X2lzX3NpemVfem9vbV9jb25zdGFudDorKFwiY29uc3RhbnRcIj09PXR8fFwic291cmNlXCI9PT10KSx1X2lzX3NpemVfZmVhdHVyZV9jb25zdGFudDorKFwiY29uc3RhbnRcIj09PXR8fFwiY2FtZXJhXCI9PT10KSx1X3NpemVfdDplP2UudVNpemVUOjAsdV9zaXplOmU/ZS51U2l6ZTowLHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZTp1LmNhbWVyYVRvQ2VudGVyRGlzdGFuY2UsdV9waXRjaDp1LnBpdGNoLzM2MCoyKk1hdGguUEksdV9yb3RhdGVfc3ltYm9sOitpLHVfYXNwZWN0X3JhdGlvOnUud2lkdGgvdS5oZWlnaHQsdV9mYWRlX2NoYW5nZTpyLm9wdGlvbnMuZmFkZUR1cmF0aW9uP3Iuc3ltYm9sRmFkZUNoYW5nZToxLHVfbWF0cml4OmEsdV9sYWJlbF9wbGFuZV9tYXRyaXg6bix1X2Nvb3JkX21hdHJpeDpzLHVfaXNfdGV4dDorbCx1X3BpdGNoX3dpdGhfbWFwOitvLHVfdGV4c2l6ZTpjLHVfdGV4dHVyZTowfX0sVWk9ZnVuY3Rpb24oZSxpLG8scixhLG4scyxsLGMsdSxoKXt2YXIgcD1hLnRyYW5zZm9ybTtyZXR1cm4gdC5leHRlbmQoRmkoZSxpLG8scixhLG4scyxsLGMsdSkse3VfZ2FtbWFfc2NhbGU6cj9NYXRoLmNvcyhwLl9waXRjaCkqcC5jYW1lcmFUb0NlbnRlckRpc3RhbmNlOjEsdV9kZXZpY2VfcGl4ZWxfcmF0aW86dC5icm93c2VyLmRldmljZVBpeGVsUmF0aW8sdV9pc19oYWxvOitofSl9LE5pPWZ1bmN0aW9uKHQsZSxpKXtyZXR1cm4ge3VfbWF0cml4OnQsdV9vcGFjaXR5OmUsdV9jb2xvcjppfX0sWmk9ZnVuY3Rpb24oZSxpLG8scixhLG4pe3JldHVybiB0LmV4dGVuZChmdW5jdGlvbih0LGUsaSxvKXt2YXIgcj1pLmltYWdlTWFuYWdlci5nZXRQYXR0ZXJuKHQuZnJvbSksYT1pLmltYWdlTWFuYWdlci5nZXRQYXR0ZXJuKHQudG8pLG49aS5pbWFnZU1hbmFnZXIuZ2V0UGl4ZWxTaXplKCkscz1uLndpZHRoLGw9bi5oZWlnaHQsYz1NYXRoLnBvdygyLG8udGlsZUlELm92ZXJzY2FsZWRaKSx1PW8udGlsZVNpemUqTWF0aC5wb3coMixpLnRyYW5zZm9ybS50aWxlWm9vbSkvYyxoPXUqKG8udGlsZUlELmNhbm9uaWNhbC54K28udGlsZUlELndyYXAqYykscD11Km8udGlsZUlELmNhbm9uaWNhbC55O3JldHVybiB7dV9pbWFnZTowLHVfcGF0dGVybl90bF9hOnIudGwsdV9wYXR0ZXJuX2JyX2E6ci5icix1X3BhdHRlcm5fdGxfYjphLnRsLHVfcGF0dGVybl9icl9iOmEuYnIsdV90ZXhzaXplOltzLGxdLHVfbWl4OmUudCx1X3BhdHRlcm5fc2l6ZV9hOnIuZGlzcGxheVNpemUsdV9wYXR0ZXJuX3NpemVfYjphLmRpc3BsYXlTaXplLHVfc2NhbGVfYTplLmZyb21TY2FsZSx1X3NjYWxlX2I6ZS50b1NjYWxlLHVfdGlsZV91bml0c190b19waXhlbHM6MS9jZShvLDEsaS50cmFuc2Zvcm0udGlsZVpvb20pLHVfcGl4ZWxfY29vcmRfdXBwZXI6W2g+PjE2LHA+PjE2XSx1X3BpeGVsX2Nvb3JkX2xvd2VyOls2NTUzNSZoLDY1NTM1JnBdfX0ocixuLG8sYSkse3VfbWF0cml4OmUsdV9vcGFjaXR5Oml9KX0samk9e2ZpbGxFeHRydXNpb246ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpLHVfbGlnaHRwb3M6bmV3IHQuVW5pZm9ybTNmKGUsaS51X2xpZ2h0cG9zKSx1X2xpZ2h0aW50ZW5zaXR5Om5ldyB0LlVuaWZvcm0xZihlLGkudV9saWdodGludGVuc2l0eSksdV9saWdodGNvbG9yOm5ldyB0LlVuaWZvcm0zZihlLGkudV9saWdodGNvbG9yKSx1X3ZlcnRpY2FsX2dyYWRpZW50Om5ldyB0LlVuaWZvcm0xZihlLGkudV92ZXJ0aWNhbF9ncmFkaWVudCksdV9vcGFjaXR5Om5ldyB0LlVuaWZvcm0xZihlLGkudV9vcGFjaXR5KX19LGZpbGxFeHRydXNpb25QYXR0ZXJuOmZ1bmN0aW9uKGUsaSl7cmV0dXJuIHt1X21hdHJpeDpuZXcgdC5Vbmlmb3JtTWF0cml4NGYoZSxpLnVfbWF0cml4KSx1X2xpZ2h0cG9zOm5ldyB0LlVuaWZvcm0zZihlLGkudV9saWdodHBvcyksdV9saWdodGludGVuc2l0eTpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfbGlnaHRpbnRlbnNpdHkpLHVfbGlnaHRjb2xvcjpuZXcgdC5Vbmlmb3JtM2YoZSxpLnVfbGlnaHRjb2xvciksdV92ZXJ0aWNhbF9ncmFkaWVudDpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfdmVydGljYWxfZ3JhZGllbnQpLHVfaGVpZ2h0X2ZhY3RvcjpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfaGVpZ2h0X2ZhY3RvciksdV9pbWFnZTpuZXcgdC5Vbmlmb3JtMWkoZSxpLnVfaW1hZ2UpLHVfdGV4c2l6ZTpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfdGV4c2l6ZSksdV9waXhlbF9jb29yZF91cHBlcjpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfcGl4ZWxfY29vcmRfdXBwZXIpLHVfcGl4ZWxfY29vcmRfbG93ZXI6bmV3IHQuVW5pZm9ybTJmKGUsaS51X3BpeGVsX2Nvb3JkX2xvd2VyKSx1X3NjYWxlOm5ldyB0LlVuaWZvcm00ZihlLGkudV9zY2FsZSksdV9mYWRlOm5ldyB0LlVuaWZvcm0xZihlLGkudV9mYWRlKSx1X29wYWNpdHk6bmV3IHQuVW5pZm9ybTFmKGUsaS51X29wYWNpdHkpfX0sZmlsbDpmdW5jdGlvbihlLGkpe3JldHVybiB7dV9tYXRyaXg6bmV3IHQuVW5pZm9ybU1hdHJpeDRmKGUsaS51X21hdHJpeCl9fSxmaWxsUGF0dGVybjpmdW5jdGlvbihlLGkpe3JldHVybiB7dV9tYXRyaXg6bmV3IHQuVW5pZm9ybU1hdHJpeDRmKGUsaS51X21hdHJpeCksdV9pbWFnZTpuZXcgdC5Vbmlmb3JtMWkoZSxpLnVfaW1hZ2UpLHVfdGV4c2l6ZTpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfdGV4c2l6ZSksdV9waXhlbF9jb29yZF91cHBlcjpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfcGl4ZWxfY29vcmRfdXBwZXIpLHVfcGl4ZWxfY29vcmRfbG93ZXI6bmV3IHQuVW5pZm9ybTJmKGUsaS51X3BpeGVsX2Nvb3JkX2xvd2VyKSx1X3NjYWxlOm5ldyB0LlVuaWZvcm00ZihlLGkudV9zY2FsZSksdV9mYWRlOm5ldyB0LlVuaWZvcm0xZihlLGkudV9mYWRlKX19LGZpbGxPdXRsaW5lOmZ1bmN0aW9uKGUsaSl7cmV0dXJuIHt1X21hdHJpeDpuZXcgdC5Vbmlmb3JtTWF0cml4NGYoZSxpLnVfbWF0cml4KSx1X3dvcmxkOm5ldyB0LlVuaWZvcm0yZihlLGkudV93b3JsZCl9fSxmaWxsT3V0bGluZVBhdHRlcm46ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpLHVfd29ybGQ6bmV3IHQuVW5pZm9ybTJmKGUsaS51X3dvcmxkKSx1X2ltYWdlOm5ldyB0LlVuaWZvcm0xaShlLGkudV9pbWFnZSksdV90ZXhzaXplOm5ldyB0LlVuaWZvcm0yZihlLGkudV90ZXhzaXplKSx1X3BpeGVsX2Nvb3JkX3VwcGVyOm5ldyB0LlVuaWZvcm0yZihlLGkudV9waXhlbF9jb29yZF91cHBlciksdV9waXhlbF9jb29yZF9sb3dlcjpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfcGl4ZWxfY29vcmRfbG93ZXIpLHVfc2NhbGU6bmV3IHQuVW5pZm9ybTRmKGUsaS51X3NjYWxlKSx1X2ZhZGU6bmV3IHQuVW5pZm9ybTFmKGUsaS51X2ZhZGUpfX0sY2lyY2xlOmZ1bmN0aW9uKGUsaSl7cmV0dXJuIHt1X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2U6bmV3IHQuVW5pZm9ybTFmKGUsaS51X2NhbWVyYV90b19jZW50ZXJfZGlzdGFuY2UpLHVfc2NhbGVfd2l0aF9tYXA6bmV3IHQuVW5pZm9ybTFpKGUsaS51X3NjYWxlX3dpdGhfbWFwKSx1X3BpdGNoX3dpdGhfbWFwOm5ldyB0LlVuaWZvcm0xaShlLGkudV9waXRjaF93aXRoX21hcCksdV9leHRydWRlX3NjYWxlOm5ldyB0LlVuaWZvcm0yZihlLGkudV9leHRydWRlX3NjYWxlKSx1X2RldmljZV9waXhlbF9yYXRpbzpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfZGV2aWNlX3BpeGVsX3JhdGlvKSx1X21hdHJpeDpuZXcgdC5Vbmlmb3JtTWF0cml4NGYoZSxpLnVfbWF0cml4KX19LGNvbGxpc2lvbkJveDpiaSxjb2xsaXNpb25DaXJjbGU6YmksZGVidWc6ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfY29sb3I6bmV3IHQuVW5pZm9ybUNvbG9yKGUsaS51X2NvbG9yKSx1X21hdHJpeDpuZXcgdC5Vbmlmb3JtTWF0cml4NGYoZSxpLnVfbWF0cml4KX19LGNsaXBwaW5nTWFzazpmdW5jdGlvbihlLGkpe3JldHVybiB7dV9tYXRyaXg6bmV3IHQuVW5pZm9ybU1hdHJpeDRmKGUsaS51X21hdHJpeCl9fSxoZWF0bWFwOmZ1bmN0aW9uKGUsaSl7cmV0dXJuIHt1X2V4dHJ1ZGVfc2NhbGU6bmV3IHQuVW5pZm9ybTFmKGUsaS51X2V4dHJ1ZGVfc2NhbGUpLHVfaW50ZW5zaXR5Om5ldyB0LlVuaWZvcm0xZihlLGkudV9pbnRlbnNpdHkpLHVfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpfX0saGVhdG1hcFRleHR1cmU6ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpLHVfd29ybGQ6bmV3IHQuVW5pZm9ybTJmKGUsaS51X3dvcmxkKSx1X2ltYWdlOm5ldyB0LlVuaWZvcm0xaShlLGkudV9pbWFnZSksdV9jb2xvcl9yYW1wOm5ldyB0LlVuaWZvcm0xaShlLGkudV9jb2xvcl9yYW1wKSx1X29wYWNpdHk6bmV3IHQuVW5pZm9ybTFmKGUsaS51X29wYWNpdHkpfX0saGlsbHNoYWRlOmZ1bmN0aW9uKGUsaSl7cmV0dXJuIHt1X21hdHJpeDpuZXcgdC5Vbmlmb3JtTWF0cml4NGYoZSxpLnVfbWF0cml4KSx1X2ltYWdlOm5ldyB0LlVuaWZvcm0xaShlLGkudV9pbWFnZSksdV9sYXRyYW5nZTpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfbGF0cmFuZ2UpLHVfbGlnaHQ6bmV3IHQuVW5pZm9ybTJmKGUsaS51X2xpZ2h0KSx1X3NoYWRvdzpuZXcgdC5Vbmlmb3JtQ29sb3IoZSxpLnVfc2hhZG93KSx1X2hpZ2hsaWdodDpuZXcgdC5Vbmlmb3JtQ29sb3IoZSxpLnVfaGlnaGxpZ2h0KSx1X2FjY2VudDpuZXcgdC5Vbmlmb3JtQ29sb3IoZSxpLnVfYWNjZW50KX19LGhpbGxzaGFkZVByZXBhcmU6ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpLHVfaW1hZ2U6bmV3IHQuVW5pZm9ybTFpKGUsaS51X2ltYWdlKSx1X2RpbWVuc2lvbjpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfZGltZW5zaW9uKSx1X3pvb206bmV3IHQuVW5pZm9ybTFmKGUsaS51X3pvb20pLHVfbWF4em9vbTpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfbWF4em9vbSl9fSxsaW5lOmZ1bmN0aW9uKGUsaSl7cmV0dXJuIHt1X21hdHJpeDpuZXcgdC5Vbmlmb3JtTWF0cml4NGYoZSxpLnVfbWF0cml4KSx1X3JhdGlvOm5ldyB0LlVuaWZvcm0xZihlLGkudV9yYXRpbyksdV9kZXZpY2VfcGl4ZWxfcmF0aW86bmV3IHQuVW5pZm9ybTFmKGUsaS51X2RldmljZV9waXhlbF9yYXRpbyksdV91bml0c190b19waXhlbHM6bmV3IHQuVW5pZm9ybTJmKGUsaS51X3VuaXRzX3RvX3BpeGVscyl9fSxsaW5lR3JhZGllbnQ6ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpLHVfcmF0aW86bmV3IHQuVW5pZm9ybTFmKGUsaS51X3JhdGlvKSx1X2RldmljZV9waXhlbF9yYXRpbzpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfZGV2aWNlX3BpeGVsX3JhdGlvKSx1X3VuaXRzX3RvX3BpeGVsczpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfdW5pdHNfdG9fcGl4ZWxzKSx1X2ltYWdlOm5ldyB0LlVuaWZvcm0xaShlLGkudV9pbWFnZSl9fSxsaW5lUGF0dGVybjpmdW5jdGlvbihlLGkpe3JldHVybiB7dV9tYXRyaXg6bmV3IHQuVW5pZm9ybU1hdHJpeDRmKGUsaS51X21hdHJpeCksdV90ZXhzaXplOm5ldyB0LlVuaWZvcm0yZihlLGkudV90ZXhzaXplKSx1X3JhdGlvOm5ldyB0LlVuaWZvcm0xZihlLGkudV9yYXRpbyksdV9kZXZpY2VfcGl4ZWxfcmF0aW86bmV3IHQuVW5pZm9ybTFmKGUsaS51X2RldmljZV9waXhlbF9yYXRpbyksdV9pbWFnZTpuZXcgdC5Vbmlmb3JtMWkoZSxpLnVfaW1hZ2UpLHVfdW5pdHNfdG9fcGl4ZWxzOm5ldyB0LlVuaWZvcm0yZihlLGkudV91bml0c190b19waXhlbHMpLHVfc2NhbGU6bmV3IHQuVW5pZm9ybTRmKGUsaS51X3NjYWxlKSx1X2ZhZGU6bmV3IHQuVW5pZm9ybTFmKGUsaS51X2ZhZGUpfX0sbGluZVNERjpmdW5jdGlvbihlLGkpe3JldHVybiB7dV9tYXRyaXg6bmV3IHQuVW5pZm9ybU1hdHJpeDRmKGUsaS51X21hdHJpeCksdV9yYXRpbzpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfcmF0aW8pLHVfZGV2aWNlX3BpeGVsX3JhdGlvOm5ldyB0LlVuaWZvcm0xZihlLGkudV9kZXZpY2VfcGl4ZWxfcmF0aW8pLHVfdW5pdHNfdG9fcGl4ZWxzOm5ldyB0LlVuaWZvcm0yZihlLGkudV91bml0c190b19waXhlbHMpLHVfcGF0dGVybnNjYWxlX2E6bmV3IHQuVW5pZm9ybTJmKGUsaS51X3BhdHRlcm5zY2FsZV9hKSx1X3BhdHRlcm5zY2FsZV9iOm5ldyB0LlVuaWZvcm0yZihlLGkudV9wYXR0ZXJuc2NhbGVfYiksdV9zZGZnYW1tYTpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfc2RmZ2FtbWEpLHVfaW1hZ2U6bmV3IHQuVW5pZm9ybTFpKGUsaS51X2ltYWdlKSx1X3RleF95X2E6bmV3IHQuVW5pZm9ybTFmKGUsaS51X3RleF95X2EpLHVfdGV4X3lfYjpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfdGV4X3lfYiksdV9taXg6bmV3IHQuVW5pZm9ybTFmKGUsaS51X21peCl9fSxyYXN0ZXI6ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpLHVfdGxfcGFyZW50Om5ldyB0LlVuaWZvcm0yZihlLGkudV90bF9wYXJlbnQpLHVfc2NhbGVfcGFyZW50Om5ldyB0LlVuaWZvcm0xZihlLGkudV9zY2FsZV9wYXJlbnQpLHVfYnVmZmVyX3NjYWxlOm5ldyB0LlVuaWZvcm0xZihlLGkudV9idWZmZXJfc2NhbGUpLHVfZmFkZV90Om5ldyB0LlVuaWZvcm0xZihlLGkudV9mYWRlX3QpLHVfb3BhY2l0eTpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfb3BhY2l0eSksdV9pbWFnZTA6bmV3IHQuVW5pZm9ybTFpKGUsaS51X2ltYWdlMCksdV9pbWFnZTE6bmV3IHQuVW5pZm9ybTFpKGUsaS51X2ltYWdlMSksdV9icmlnaHRuZXNzX2xvdzpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfYnJpZ2h0bmVzc19sb3cpLHVfYnJpZ2h0bmVzc19oaWdoOm5ldyB0LlVuaWZvcm0xZihlLGkudV9icmlnaHRuZXNzX2hpZ2gpLHVfc2F0dXJhdGlvbl9mYWN0b3I6bmV3IHQuVW5pZm9ybTFmKGUsaS51X3NhdHVyYXRpb25fZmFjdG9yKSx1X2NvbnRyYXN0X2ZhY3RvcjpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfY29udHJhc3RfZmFjdG9yKSx1X3NwaW5fd2VpZ2h0czpuZXcgdC5Vbmlmb3JtM2YoZSxpLnVfc3Bpbl93ZWlnaHRzKX19LHN5bWJvbEljb246ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfaXNfc2l6ZV96b29tX2NvbnN0YW50Om5ldyB0LlVuaWZvcm0xaShlLGkudV9pc19zaXplX3pvb21fY29uc3RhbnQpLHVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50Om5ldyB0LlVuaWZvcm0xaShlLGkudV9pc19zaXplX2ZlYXR1cmVfY29uc3RhbnQpLHVfc2l6ZV90Om5ldyB0LlVuaWZvcm0xZihlLGkudV9zaXplX3QpLHVfc2l6ZTpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfc2l6ZSksdV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlOm5ldyB0LlVuaWZvcm0xZihlLGkudV9jYW1lcmFfdG9fY2VudGVyX2Rpc3RhbmNlKSx1X3BpdGNoOm5ldyB0LlVuaWZvcm0xZihlLGkudV9waXRjaCksdV9yb3RhdGVfc3ltYm9sOm5ldyB0LlVuaWZvcm0xaShlLGkudV9yb3RhdGVfc3ltYm9sKSx1X2FzcGVjdF9yYXRpbzpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfYXNwZWN0X3JhdGlvKSx1X2ZhZGVfY2hhbmdlOm5ldyB0LlVuaWZvcm0xZihlLGkudV9mYWRlX2NoYW5nZSksdV9tYXRyaXg6bmV3IHQuVW5pZm9ybU1hdHJpeDRmKGUsaS51X21hdHJpeCksdV9sYWJlbF9wbGFuZV9tYXRyaXg6bmV3IHQuVW5pZm9ybU1hdHJpeDRmKGUsaS51X2xhYmVsX3BsYW5lX21hdHJpeCksdV9jb29yZF9tYXRyaXg6bmV3IHQuVW5pZm9ybU1hdHJpeDRmKGUsaS51X2Nvb3JkX21hdHJpeCksdV9pc190ZXh0Om5ldyB0LlVuaWZvcm0xZihlLGkudV9pc190ZXh0KSx1X3BpdGNoX3dpdGhfbWFwOm5ldyB0LlVuaWZvcm0xaShlLGkudV9waXRjaF93aXRoX21hcCksdV90ZXhzaXplOm5ldyB0LlVuaWZvcm0yZihlLGkudV90ZXhzaXplKSx1X3RleHR1cmU6bmV3IHQuVW5pZm9ybTFpKGUsaS51X3RleHR1cmUpfX0sc3ltYm9sU0RGOmZ1bmN0aW9uKGUsaSl7cmV0dXJuIHt1X2lzX3NpemVfem9vbV9jb25zdGFudDpuZXcgdC5Vbmlmb3JtMWkoZSxpLnVfaXNfc2l6ZV96b29tX2NvbnN0YW50KSx1X2lzX3NpemVfZmVhdHVyZV9jb25zdGFudDpuZXcgdC5Vbmlmb3JtMWkoZSxpLnVfaXNfc2l6ZV9mZWF0dXJlX2NvbnN0YW50KSx1X3NpemVfdDpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfc2l6ZV90KSx1X3NpemU6bmV3IHQuVW5pZm9ybTFmKGUsaS51X3NpemUpLHVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZTpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfY2FtZXJhX3RvX2NlbnRlcl9kaXN0YW5jZSksdV9waXRjaDpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfcGl0Y2gpLHVfcm90YXRlX3N5bWJvbDpuZXcgdC5Vbmlmb3JtMWkoZSxpLnVfcm90YXRlX3N5bWJvbCksdV9hc3BlY3RfcmF0aW86bmV3IHQuVW5pZm9ybTFmKGUsaS51X2FzcGVjdF9yYXRpbyksdV9mYWRlX2NoYW5nZTpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfZmFkZV9jaGFuZ2UpLHVfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpLHVfbGFiZWxfcGxhbmVfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9sYWJlbF9wbGFuZV9tYXRyaXgpLHVfY29vcmRfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9jb29yZF9tYXRyaXgpLHVfaXNfdGV4dDpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfaXNfdGV4dCksdV9waXRjaF93aXRoX21hcDpuZXcgdC5Vbmlmb3JtMWkoZSxpLnVfcGl0Y2hfd2l0aF9tYXApLHVfdGV4c2l6ZTpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfdGV4c2l6ZSksdV90ZXh0dXJlOm5ldyB0LlVuaWZvcm0xaShlLGkudV90ZXh0dXJlKSx1X2dhbW1hX3NjYWxlOm5ldyB0LlVuaWZvcm0xZihlLGkudV9nYW1tYV9zY2FsZSksdV9kZXZpY2VfcGl4ZWxfcmF0aW86bmV3IHQuVW5pZm9ybTFmKGUsaS51X2RldmljZV9waXhlbF9yYXRpbyksdV9pc19oYWxvOm5ldyB0LlVuaWZvcm0xZihlLGkudV9pc19oYWxvKX19LGJhY2tncm91bmQ6ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpLHVfb3BhY2l0eTpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfb3BhY2l0eSksdV9jb2xvcjpuZXcgdC5Vbmlmb3JtQ29sb3IoZSxpLnVfY29sb3IpfX0sYmFja2dyb3VuZFBhdHRlcm46ZnVuY3Rpb24oZSxpKXtyZXR1cm4ge3VfbWF0cml4Om5ldyB0LlVuaWZvcm1NYXRyaXg0ZihlLGkudV9tYXRyaXgpLHVfb3BhY2l0eTpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfb3BhY2l0eSksdV9pbWFnZTpuZXcgdC5Vbmlmb3JtMWkoZSxpLnVfaW1hZ2UpLHVfcGF0dGVybl90bF9hOm5ldyB0LlVuaWZvcm0yZihlLGkudV9wYXR0ZXJuX3RsX2EpLHVfcGF0dGVybl9icl9hOm5ldyB0LlVuaWZvcm0yZihlLGkudV9wYXR0ZXJuX2JyX2EpLHVfcGF0dGVybl90bF9iOm5ldyB0LlVuaWZvcm0yZihlLGkudV9wYXR0ZXJuX3RsX2IpLHVfcGF0dGVybl9icl9iOm5ldyB0LlVuaWZvcm0yZihlLGkudV9wYXR0ZXJuX2JyX2IpLHVfdGV4c2l6ZTpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfdGV4c2l6ZSksdV9taXg6bmV3IHQuVW5pZm9ybTFmKGUsaS51X21peCksdV9wYXR0ZXJuX3NpemVfYTpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfcGF0dGVybl9zaXplX2EpLHVfcGF0dGVybl9zaXplX2I6bmV3IHQuVW5pZm9ybTJmKGUsaS51X3BhdHRlcm5fc2l6ZV9iKSx1X3NjYWxlX2E6bmV3IHQuVW5pZm9ybTFmKGUsaS51X3NjYWxlX2EpLHVfc2NhbGVfYjpuZXcgdC5Vbmlmb3JtMWYoZSxpLnVfc2NhbGVfYiksdV9waXhlbF9jb29yZF91cHBlcjpuZXcgdC5Vbmlmb3JtMmYoZSxpLnVfcGl4ZWxfY29vcmRfdXBwZXIpLHVfcGl4ZWxfY29vcmRfbG93ZXI6bmV3IHQuVW5pZm9ybTJmKGUsaS51X3BpeGVsX2Nvb3JkX2xvd2VyKSx1X3RpbGVfdW5pdHNfdG9fcGl4ZWxzOm5ldyB0LlVuaWZvcm0xZihlLGkudV90aWxlX3VuaXRzX3RvX3BpeGVscyl9fX07ZnVuY3Rpb24gcWkoZSxpKXtmb3IodmFyIG89ZS5zb3J0KGZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQudGlsZUlELmlzTGVzc1RoYW4oZS50aWxlSUQpPy0xOmUudGlsZUlELmlzTGVzc1RoYW4odC50aWxlSUQpPzE6MH0pLHI9MDtyPG8ubGVuZ3RoO3IrKyl7dmFyIGE9e30sbj1vW3JdLHM9by5zbGljZShyKzEpO1ZpKG4udGlsZUlELndyYXBwZWQoKSxuLnRpbGVJRCxzLG5ldyB0Lk92ZXJzY2FsZWRUaWxlSUQoMCxuLnRpbGVJRC53cmFwKzEsMCwwLDApLGEpLG4uc2V0TWFzayhhLGkpO319ZnVuY3Rpb24gVmkoZSxpLG8scixhKXtmb3IodmFyIG49MDtuPG8ubGVuZ3RoO24rKyl7dmFyIHM9b1tuXTtpZihyLmlzTGVzc1RoYW4ocy50aWxlSUQpKWJyZWFrO2lmKGkua2V5PT09cy50aWxlSUQua2V5KXJldHVybjtpZihzLnRpbGVJRC5pc0NoaWxkT2YoaSkpe2Zvcih2YXIgbD1pLmNoaWxkcmVuKDEvMCksYz0wO2M8bC5sZW5ndGg7YysrKXtWaShlLGxbY10sby5zbGljZShuKSxyLGEpO31yZXR1cm59fXZhciB1PWkub3ZlcnNjYWxlZFotZS5vdmVyc2NhbGVkWixoPW5ldyB0LkNhbm9uaWNhbFRpbGVJRCh1LGkuY2Fub25pY2FsLngtKGUuY2Fub25pY2FsLng8PHUpLGkuY2Fub25pY2FsLnktKGUuY2Fub25pY2FsLnk8PHUpKTthW2gua2V5XT1hW2gua2V5XXx8aDt9ZnVuY3Rpb24gR2kodCxlLGksbyxyKXtmb3IodmFyIGE9dC5jb250ZXh0LG49YS5nbCxzPXI/dC51c2VQcm9ncmFtKFwiY29sbGlzaW9uQ2lyY2xlXCIpOnQudXNlUHJvZ3JhbShcImNvbGxpc2lvbkJveFwiKSxsPTA7bDxvLmxlbmd0aDtsKyspe3ZhciBjPW9bbF0sdT1lLmdldFRpbGUoYyksaD11LmdldEJ1Y2tldChpKTtpZihoKXt2YXIgcD1yP2guY29sbGlzaW9uQ2lyY2xlOmguY29sbGlzaW9uQm94O3AmJnMuZHJhdyhhLHI/bi5UUklBTkdMRVM6bi5MSU5FUyxUdC5kaXNhYmxlZCxJdC5kaXNhYmxlZCx0LmNvbG9yTW9kZUZvclJlbmRlclBhc3MoKSxTdC5kaXNhYmxlZCx3aShjLnBvc01hdHJpeCx0LnRyYW5zZm9ybSx1KSxpLmlkLHAubGF5b3V0VmVydGV4QnVmZmVyLHAuaW5kZXhCdWZmZXIscC5zZWdtZW50cyxudWxsLHQudHJhbnNmb3JtLnpvb20sbnVsbCxudWxsLHAuY29sbGlzaW9uVmVydGV4QnVmZmVyKTt9fX12YXIgV2k9dC5pZGVudGl0eShuZXcgRmxvYXQzMkFycmF5KDE2KSk7ZnVuY3Rpb24gWGkoZSxpLG8scixhLG4pe3ZhciBzPXQuZ2V0QW5jaG9yQWxpZ25tZW50KGUpLGw9LShzLmhvcml6b250YWxBbGlnbi0uNSkqaSxjPS0ocy52ZXJ0aWNhbEFsaWduLS41KSpvLHU9dC5ldmFsdWF0ZVJhZGlhbE9mZnNldChlLHIpO3JldHVybiBuZXcgdC5Qb2ludCgobC9hK3VbMF0pKm4sKGMvYSt1WzFdKSpuKX1mdW5jdGlvbiBIaShlLGksbyxyLGEsbixzLGwsYyx1KXt2YXIgaD1lLnRleHQucGxhY2VkU3ltYm9sQXJyYXkscD1lLnRleHQuZHluYW1pY0xheW91dFZlcnRleEFycmF5O3AuY2xlYXIoKTtmb3IodmFyIGQ9MDtkPGgubGVuZ3RoO2QrKyl7dmFyIF89aC5nZXQoZCksZj0hXy5oaWRkZW4mJl8uY3Jvc3NUaWxlSUQ/cltfLmNyb3NzVGlsZUlEXTpudWxsO2lmKGYpe3ZhciBtPW5ldyB0LlBvaW50KF8uYW5jaG9yWCxfLmFuY2hvclkpLGc9WXQobSxvP2w6cyksdj0uNStuLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2UvZy5zaWduZWREaXN0YW5jZUZyb21DYW1lcmEqLjUseT1hLmV2YWx1YXRlU2l6ZUZvckZlYXR1cmUoZS50ZXh0U2l6ZURhdGEsdSxfKSp2L3QuT05FX0VNO28mJih5Kj1lLnRpbGVQaXhlbFJhdGlvL2MpO2Zvcih2YXIgeD1mLndpZHRoLGI9Zi5oZWlnaHQsdz1mLnJhZGlhbE9mZnNldCxFPWYudGV4dEJveFNjYWxlLFQ9WGkoZi5hbmNob3IseCxiLHcsRSx5KSxJPW8/WXQobS5hZGQoVCkscykucG9pbnQ6Zy5wb2ludC5hZGQoaT9ULnJvdGF0ZSgtbi5hbmdsZSk6VCksQz0wO0M8Xy5udW1HbHlwaHM7QysrKXQuYWRkRHluYW1pY0F0dHJpYnV0ZXMocCxJLDApO31lbHNlIGFlKF8ubnVtR2x5cGhzLHApO31lLnRleHQuZHluYW1pY0xheW91dFZlcnRleEJ1ZmZlci51cGRhdGVEYXRhKHApO31mdW5jdGlvbiBLaShlLGksbyxyLGEsbixzLGwsYyx1LGgscCxkKXtmb3IodmFyIF8sZixtPWUuY29udGV4dCxnPW0uZ2wsdj1lLnRyYW5zZm9ybSx5PVwibWFwXCI9PT1sLHg9XCJtYXBcIj09PWMsYj15JiZcInBvaW50XCIhPT1vLmxheW91dC5nZXQoXCJzeW1ib2wtcGxhY2VtZW50XCIpLHc9eSYmIXgmJiFiLEU9dm9pZCAwIT09by5sYXlvdXQuZ2V0KFwic3ltYm9sLXNvcnQta2V5XCIpLmNvbnN0YW50T3IoMSksVD1lLmRlcHRoTW9kZUZvclN1YmxheWVyKDAsVHQuUmVhZE9ubHkpLEk9by5sYXlvdXQuZ2V0KFwidGV4dC12YXJpYWJsZS1hbmNob3JcIiksQz1bXSxTPTAsUD1yO1M8UC5sZW5ndGg7Uys9MSl7dmFyIHo9UFtTXSxMPWkuZ2V0VGlsZSh6KSxEPUwuZ2V0QnVja2V0KG8pO2lmKEQpe3ZhciBNPWE/RC50ZXh0OkQuaWNvbjtpZihNJiZNLnNlZ21lbnRzLmdldCgpLmxlbmd0aCl7dmFyIFI9TS5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KG8uaWQpLEE9YXx8RC5zZGZJY29ucyxrPWE/RC50ZXh0U2l6ZURhdGE6RC5pY29uU2l6ZURhdGE7X3x8KF89ZS51c2VQcm9ncmFtKEE/XCJzeW1ib2xTREZcIjpcInN5bWJvbEljb25cIixSKSxmPXQuZXZhbHVhdGVTaXplRm9yWm9vbShrLHYuem9vbSkpLG0uYWN0aXZlVGV4dHVyZS5zZXQoZy5URVhUVVJFMCk7dmFyIEI9dm9pZCAwLE89dm9pZCAwLEY9dm9pZCAwO2lmKGEpTz1MLmdseXBoQXRsYXNUZXh0dXJlLEY9Zy5MSU5FQVIsQj1MLmdseXBoQXRsYXNUZXh0dXJlLnNpemU7ZWxzZXt2YXIgVT0xIT09by5sYXlvdXQuZ2V0KFwiaWNvbi1zaXplXCIpLmNvbnN0YW50T3IoMCl8fEQuaWNvbnNOZWVkTGluZWFyLE49eHx8MCE9PXYucGl0Y2g7Tz1MLmltYWdlQXRsYXNUZXh0dXJlLEY9QXx8ZS5vcHRpb25zLnJvdGF0aW5nfHxlLm9wdGlvbnMuem9vbWluZ3x8VXx8Tj9nLkxJTkVBUjpnLk5FQVJFU1QsQj1MLmltYWdlQXRsYXNUZXh0dXJlLnNpemU7fXZhciBaPWNlKEwsMSxlLnRyYW5zZm9ybS56b29tKSxqPUh0KHoucG9zTWF0cml4LHgseSxlLnRyYW5zZm9ybSxaKSxxPUt0KHoucG9zTWF0cml4LHgseSxlLnRyYW5zZm9ybSxaKTtpZihiKVF0KEQsei5wb3NNYXRyaXgsZSxhLGoscSx4LHUpO2Vsc2UgaWYoYSYmZiYmSSl7dmFyIFY9TWF0aC5wb3coMix2Lnpvb20tTC50aWxlSUQub3ZlcnNjYWxlZFopO0hpKEQseSx4LGQsdC5zeW1ib2xTaXplLHYsaix6LnBvc01hdHJpeCxWLGYpO312YXIgRz1lLnRyYW5zbGF0ZVBvc01hdHJpeCh6LnBvc01hdHJpeCxMLG4scyksVz1ifHxhJiZJP1dpOmosWD1lLnRyYW5zbGF0ZVBvc01hdHJpeChxLEwsbixzLCEwKSxIPUEmJjAhPT1vLnBhaW50LmdldChhP1widGV4dC1oYWxvLXdpZHRoXCI6XCJpY29uLWhhbG8td2lkdGhcIikuY29uc3RhbnRPcigxKSxLPXtwcm9ncmFtOl8sYnVmZmVyczpNLHVuaWZvcm1WYWx1ZXM6QT9VaShrLmtpbmQsZix3LHgsZSxHLFcsWCxhLEIsITApOkZpKGsua2luZCxmLHcseCxlLEcsVyxYLGEsQiksYXRsYXNUZXh0dXJlOk8sYXRsYXNJbnRlcnBvbGF0aW9uOkYsaXNTREY6QSxoYXNIYWxvOkh9O2lmKEUpZm9yKHZhciBZPTAsSj1NLnNlZ21lbnRzLmdldCgpO1k8Si5sZW5ndGg7WSs9MSl7dmFyIFE9SltZXTtDLnB1c2goe3NlZ21lbnRzOm5ldyB0LlNlZ21lbnRWZWN0b3IoW1FdKSxzb3J0S2V5OlEuc29ydEtleSxzdGF0ZTpLfSk7fWVsc2UgQy5wdXNoKHtzZWdtZW50czpNLnNlZ21lbnRzLHNvcnRLZXk6MCxzdGF0ZTpLfSk7fX19RSYmQy5zb3J0KGZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQuc29ydEtleS1lLnNvcnRLZXl9KTtmb3IodmFyICQ9MCx0dD1DOyQ8dHQubGVuZ3RoOyQrPTEpe3ZhciBldD10dFskXSxpdD1ldC5zdGF0ZTtpZihpdC5hdGxhc1RleHR1cmUuYmluZChpdC5hdGxhc0ludGVycG9sYXRpb24sZy5DTEFNUF9UT19FREdFKSxpdC5pc1NERil7dmFyIG90PWl0LnVuaWZvcm1WYWx1ZXM7aXQuaGFzSGFsbyYmKG90LnVfaXNfaGFsbz0xLFlpKGl0LmJ1ZmZlcnMsZXQuc2VnbWVudHMsbyxlLGl0LnByb2dyYW0sVCxoLHAsb3QpKSxvdC51X2lzX2hhbG89MDt9WWkoaXQuYnVmZmVycyxldC5zZWdtZW50cyxvLGUsaXQucHJvZ3JhbSxULGgscCxpdC51bmlmb3JtVmFsdWVzKTt9fWZ1bmN0aW9uIFlpKHQsZSxpLG8scixhLG4scyxsKXt2YXIgYz1vLmNvbnRleHQsdT1jLmdsO3IuZHJhdyhjLHUuVFJJQU5HTEVTLGEsbixzLFN0LmRpc2FibGVkLGwsaS5pZCx0LmxheW91dFZlcnRleEJ1ZmZlcix0LmluZGV4QnVmZmVyLGUsaS5wYWludCxvLnRyYW5zZm9ybS56b29tLHQucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLmdldChpLmlkKSx0LmR5bmFtaWNMYXlvdXRWZXJ0ZXhCdWZmZXIsdC5vcGFjaXR5VmVydGV4QnVmZmVyKTt9ZnVuY3Rpb24gSmkodCxlLGksbyxyLGEsbil7dmFyIHMsbCxjLHUsaCxwPXQuY29udGV4dC5nbCxkPWkucGFpbnQuZ2V0KFwiZmlsbC1wYXR0ZXJuXCIpLF89ZCYmZC5jb25zdGFudE9yKDEpLGY9aS5nZXRDcm9zc2ZhZGVQYXJhbWV0ZXJzKCk7bj8obD1fJiYhaS5nZXRQYWludFByb3BlcnR5KFwiZmlsbC1vdXRsaW5lLWNvbG9yXCIpP1wiZmlsbE91dGxpbmVQYXR0ZXJuXCI6XCJmaWxsT3V0bGluZVwiLHM9cC5MSU5FUyk6KGw9Xz9cImZpbGxQYXR0ZXJuXCI6XCJmaWxsXCIscz1wLlRSSUFOR0xFUyk7Zm9yKHZhciBtPTAsZz1vO208Zy5sZW5ndGg7bSs9MSl7dmFyIHY9Z1ttXSx5PWUuZ2V0VGlsZSh2KTtpZighX3x8eS5wYXR0ZXJuc0xvYWRlZCgpKXt2YXIgeD15LmdldEJ1Y2tldChpKTtpZih4KXt2YXIgYj14LnByb2dyYW1Db25maWd1cmF0aW9ucy5nZXQoaS5pZCksdz10LnVzZVByb2dyYW0obCxiKTtfJiYodC5jb250ZXh0LmFjdGl2ZVRleHR1cmUuc2V0KHAuVEVYVFVSRTApLHkuaW1hZ2VBdGxhc1RleHR1cmUuYmluZChwLkxJTkVBUixwLkNMQU1QX1RPX0VER0UpLGIudXBkYXRlUGF0dGVyblBhaW50QnVmZmVycyhmKSk7dmFyIEU9ZC5jb25zdGFudE9yKG51bGwpO2lmKEUmJnkuaW1hZ2VBdGxhcyl7dmFyIFQ9eS5pbWFnZUF0bGFzLnBhdHRlcm5Qb3NpdGlvbnNbRS50b10sST15LmltYWdlQXRsYXMucGF0dGVyblBvc2l0aW9uc1tFLmZyb21dO1QmJkkmJmIuc2V0Q29uc3RhbnRQYXR0ZXJuUG9zaXRpb25zKFQsSSk7fXZhciBDPXQudHJhbnNsYXRlUG9zTWF0cml4KHYucG9zTWF0cml4LHksaS5wYWludC5nZXQoXCJmaWxsLXRyYW5zbGF0ZVwiKSxpLnBhaW50LmdldChcImZpbGwtdHJhbnNsYXRlLWFuY2hvclwiKSk7aWYobil7dT14LmluZGV4QnVmZmVyMixoPXguc2VnbWVudHMyO3ZhciBTPVtwLmRyYXdpbmdCdWZmZXJXaWR0aCxwLmRyYXdpbmdCdWZmZXJIZWlnaHRdO2M9XCJmaWxsT3V0bGluZVBhdHRlcm5cIj09PWwmJl8/eWkoQyx0LGYseSxTKTp2aShDLFMpO31lbHNlIHU9eC5pbmRleEJ1ZmZlcixoPXguc2VnbWVudHMsYz1fP2dpKEMsdCxmLHkpOm1pKEMpO3cuZHJhdyh0LmNvbnRleHQscyxyLHQuc3RlbmNpbE1vZGVGb3JDbGlwcGluZyh2KSxhLFN0LmRpc2FibGVkLGMsaS5pZCx4LmxheW91dFZlcnRleEJ1ZmZlcix1LGgsaS5wYWludCx0LnRyYW5zZm9ybS56b29tLGIpO319fX1mdW5jdGlvbiBRaSh0LGUsaSxvLHIsYSxuKXtmb3IodmFyIHM9dC5jb250ZXh0LGw9cy5nbCxjPWkucGFpbnQuZ2V0KFwiZmlsbC1leHRydXNpb24tcGF0dGVyblwiKSx1PWMuY29uc3RhbnRPcigxKSxoPWkuZ2V0Q3Jvc3NmYWRlUGFyYW1ldGVycygpLHA9aS5wYWludC5nZXQoXCJmaWxsLWV4dHJ1c2lvbi1vcGFjaXR5XCIpLGQ9MCxfPW87ZDxfLmxlbmd0aDtkKz0xKXt2YXIgZj1fW2RdLG09ZS5nZXRUaWxlKGYpLGc9bS5nZXRCdWNrZXQoaSk7aWYoZyl7dmFyIHY9Zy5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KGkuaWQpLHk9dC51c2VQcm9ncmFtKHU/XCJmaWxsRXh0cnVzaW9uUGF0dGVyblwiOlwiZmlsbEV4dHJ1c2lvblwiLHYpO3UmJih0LmNvbnRleHQuYWN0aXZlVGV4dHVyZS5zZXQobC5URVhUVVJFMCksbS5pbWFnZUF0bGFzVGV4dHVyZS5iaW5kKGwuTElORUFSLGwuQ0xBTVBfVE9fRURHRSksdi51cGRhdGVQYXR0ZXJuUGFpbnRCdWZmZXJzKGgpKTt2YXIgeD1jLmNvbnN0YW50T3IobnVsbCk7aWYoeCYmbS5pbWFnZUF0bGFzKXt2YXIgYj1tLmltYWdlQXRsYXMucGF0dGVyblBvc2l0aW9uc1t4LnRvXSx3PW0uaW1hZ2VBdGxhcy5wYXR0ZXJuUG9zaXRpb25zW3guZnJvbV07YiYmdyYmdi5zZXRDb25zdGFudFBhdHRlcm5Qb3NpdGlvbnMoYix3KTt9dmFyIEU9dC50cmFuc2xhdGVQb3NNYXRyaXgoZi5wb3NNYXRyaXgsbSxpLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZVwiKSxpLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLXRyYW5zbGF0ZS1hbmNob3JcIikpLFQ9aS5wYWludC5nZXQoXCJmaWxsLWV4dHJ1c2lvbi12ZXJ0aWNhbC1ncmFkaWVudFwiKSxJPXU/ZmkoRSx0LFQscCxmLGgsbSk6X2koRSx0LFQscCk7eS5kcmF3KHMscy5nbC5UUklBTkdMRVMscixhLG4sU3QuYmFja0NDVyxJLGkuaWQsZy5sYXlvdXRWZXJ0ZXhCdWZmZXIsZy5pbmRleEJ1ZmZlcixnLnNlZ21lbnRzLGkucGFpbnQsdC50cmFuc2Zvcm0uem9vbSx2KTt9fX1mdW5jdGlvbiAkaSh0LGUsaSxvLHIsYSl7dmFyIG49dC5jb250ZXh0LHM9bi5nbCxsPWUuZmJvO2lmKGwpe3ZhciBjPXQudXNlUHJvZ3JhbShcImhpbGxzaGFkZVwiKTtuLmFjdGl2ZVRleHR1cmUuc2V0KHMuVEVYVFVSRTApLHMuYmluZFRleHR1cmUocy5URVhUVVJFXzJELGwuY29sb3JBdHRhY2htZW50LmdldCgpKTt2YXIgdT1TaSh0LGUsaSk7ZS5tYXNrZWRCb3VuZHNCdWZmZXImJmUubWFza2VkSW5kZXhCdWZmZXImJmUuc2VnbWVudHM/Yy5kcmF3KG4scy5UUklBTkdMRVMsbyxyLGEsU3QuZGlzYWJsZWQsdSxpLmlkLGUubWFza2VkQm91bmRzQnVmZmVyLGUubWFza2VkSW5kZXhCdWZmZXIsZS5zZWdtZW50cyk6Yy5kcmF3KG4scy5UUklBTkdMRVMsbyxyLGEsU3QuZGlzYWJsZWQsdSxpLmlkLHQucmFzdGVyQm91bmRzQnVmZmVyLHQucXVhZFRyaWFuZ2xlSW5kZXhCdWZmZXIsdC5yYXN0ZXJCb3VuZHNTZWdtZW50cyk7fX1mdW5jdGlvbiB0byhlLGksbyxyLGEsbixzKXt2YXIgbD1lLmNvbnRleHQsYz1sLmdsO2lmKGkuZGVtJiZpLmRlbS5kYXRhKXt2YXIgdT1pLmRlbS5kaW0saD1pLmRlbS5zdHJpZGUscD1pLmRlbS5nZXRQaXhlbHMoKTtpZihsLmFjdGl2ZVRleHR1cmUuc2V0KGMuVEVYVFVSRTEpLGwucGl4ZWxTdG9yZVVucGFja1ByZW11bHRpcGx5QWxwaGEuc2V0KCExKSxpLmRlbVRleHR1cmU9aS5kZW1UZXh0dXJlfHxlLmdldFRpbGVUZXh0dXJlKGgpLGkuZGVtVGV4dHVyZSl7dmFyIGQ9aS5kZW1UZXh0dXJlO2QudXBkYXRlKHAse3ByZW11bHRpcGx5OiExfSksZC5iaW5kKGMuTkVBUkVTVCxjLkNMQU1QX1RPX0VER0UpO31lbHNlIGkuZGVtVGV4dHVyZT1uZXcgdC5UZXh0dXJlKGwscCxjLlJHQkEse3ByZW11bHRpcGx5OiExfSksaS5kZW1UZXh0dXJlLmJpbmQoYy5ORUFSRVNULGMuQ0xBTVBfVE9fRURHRSk7bC5hY3RpdmVUZXh0dXJlLnNldChjLlRFWFRVUkUwKTt2YXIgXz1pLmZibztpZighXyl7dmFyIGY9bmV3IHQuVGV4dHVyZShsLHt3aWR0aDp1LGhlaWdodDp1LGRhdGE6bnVsbH0sYy5SR0JBKTtmLmJpbmQoYy5MSU5FQVIsYy5DTEFNUF9UT19FREdFKSwoXz1pLmZibz1sLmNyZWF0ZUZyYW1lYnVmZmVyKHUsdSkpLmNvbG9yQXR0YWNobWVudC5zZXQoZi50ZXh0dXJlKTt9bC5iaW5kRnJhbWVidWZmZXIuc2V0KF8uZnJhbWVidWZmZXIpLGwudmlld3BvcnQuc2V0KFswLDAsdSx1XSksZS51c2VQcm9ncmFtKFwiaGlsbHNoYWRlUHJlcGFyZVwiKS5kcmF3KGwsYy5UUklBTkdMRVMsYSxuLHMsU3QuZGlzYWJsZWQsUGkoaSxyKSxvLmlkLGUucmFzdGVyQm91bmRzQnVmZmVyLGUucXVhZFRyaWFuZ2xlSW5kZXhCdWZmZXIsZS5yYXN0ZXJCb3VuZHNTZWdtZW50cyksaS5uZWVkc0hpbGxzaGFkZVByZXBhcmU9ITE7fX1mdW5jdGlvbiBlbyhlLGksbyxyLGEpe3ZhciBuPXIucGFpbnQuZ2V0KFwicmFzdGVyLWZhZGUtZHVyYXRpb25cIik7aWYobj4wKXt2YXIgcz10LmJyb3dzZXIubm93KCksbD0ocy1lLnRpbWVBZGRlZCkvbixjPWk/KHMtaS50aW1lQWRkZWQpL246LTEsdT1vLmdldFNvdXJjZSgpLGg9YS5jb3ZlcmluZ1pvb21MZXZlbCh7dGlsZVNpemU6dS50aWxlU2l6ZSxyb3VuZFpvb206dS5yb3VuZFpvb219KSxwPSFpfHxNYXRoLmFicyhpLnRpbGVJRC5vdmVyc2NhbGVkWi1oKT5NYXRoLmFicyhlLnRpbGVJRC5vdmVyc2NhbGVkWi1oKSxkPXAmJmUucmVmcmVzaGVkVXBvbkV4cGlyYXRpb24/MTp0LmNsYW1wKHA/bDoxLWMsMCwxKTtyZXR1cm4gZS5yZWZyZXNoZWRVcG9uRXhwaXJhdGlvbiYmbD49MSYmKGUucmVmcmVzaGVkVXBvbkV4cGlyYXRpb249ITEpLGk/e29wYWNpdHk6MSxtaXg6MS1kfTp7b3BhY2l0eTpkLG1peDowfX1yZXR1cm4ge29wYWNpdHk6MSxtaXg6MH19ZnVuY3Rpb24gaW8oZSxpLG8pe3ZhciByPWUuY29udGV4dCxhPXIuZ2wsbj1vLnBvc01hdHJpeCxzPWUudXNlUHJvZ3JhbShcImRlYnVnXCIpLGw9VHQuZGlzYWJsZWQsYz1JdC5kaXNhYmxlZCx1PWUuY29sb3JNb2RlRm9yUmVuZGVyUGFzcygpLGg9XCIkZGVidWdcIjtzLmRyYXcocixhLkxJTkVfU1RSSVAsbCxjLHUsU3QuZGlzYWJsZWQsRWkobix0LkNvbG9yLnJlZCksaCxlLmRlYnVnQnVmZmVyLGUudGlsZUJvcmRlckluZGV4QnVmZmVyLGUuZGVidWdTZWdtZW50cyk7Zm9yKHZhciBwPWkuZ2V0VGlsZUJ5SUQoby5rZXkpLmxhdGVzdFJhd1RpbGVEYXRhLGQ9cCYmcC5ieXRlTGVuZ3RofHwwLF89TWF0aC5mbG9vcihkLzEwMjQpLGY9ZnVuY3Rpb24odCxlLGksbyl7bz1vfHwxO3ZhciByLGEsbixzLGwsYyx1LGgscD1bXTtmb3Iocj0wLGE9dC5sZW5ndGg7cjxhO3IrKylpZihsPW9vW3Rbcl1dKXtmb3IoaD1udWxsLG49MCxzPWxbMV0ubGVuZ3RoO248cztuKz0yKS0xPT09bFsxXVtuXSYmLTE9PT1sWzFdW24rMV0/aD1udWxsOihjPWUrbFsxXVtuXSpvLHU9aS1sWzFdW24rMV0qbyxoJiZwLnB1c2goaC54LGgueSxjLHUpLGg9e3g6Yyx5OnV9KTtlKz1sWzBdKm87fXJldHVybiBwfShvLnRvU3RyaW5nKCkrXCIgXCIrXytcImtiXCIsNTAsMjAwLDUpLG09bmV3IHQuU3RydWN0QXJyYXlMYXlvdXQyaTQsZz1uZXcgdC5TdHJ1Y3RBcnJheUxheW91dDJ1aTQsdj0wO3Y8Zi5sZW5ndGg7dis9MiltLmVtcGxhY2VCYWNrKGZbdl0sZlt2KzFdKSxnLmVtcGxhY2VCYWNrKHYsdisxKTtmb3IodmFyIHk9ci5jcmVhdGVWZXJ0ZXhCdWZmZXIobSxPZS5tZW1iZXJzKSx4PXIuY3JlYXRlSW5kZXhCdWZmZXIoZyksYj10LlNlZ21lbnRWZWN0b3Iuc2ltcGxlU2VnbWVudCgwLDAsbS5sZW5ndGgvMixtLmxlbmd0aC8yKSx3PWkuZ2V0VGlsZShvKS50aWxlU2l6ZSxFPXQuRVhURU5ULyhNYXRoLnBvdygyLGUudHJhbnNmb3JtLnpvb20tby5vdmVyc2NhbGVkWikqdyksVD1bWy0xLC0xXSxbLTEsMV0sWzEsLTFdLFsxLDFdXSxJPTA7STxULmxlbmd0aDtJKyspe3ZhciBDPVRbSV07cy5kcmF3KHIsYS5MSU5FUyxsLGMsdSxTdC5kaXNhYmxlZCxFaSh0LnRyYW5zbGF0ZShbXSxuLFtFKkNbMF0sRSpDWzFdLDBdKSx0LkNvbG9yLndoaXRlKSxoLHkseCxiKTt9cy5kcmF3KHIsYS5MSU5FUyxsLGMsdSxTdC5kaXNhYmxlZCxFaShuLHQuQ29sb3IuYmxhY2spLGgseSx4LGIpO312YXIgb289e1wiIFwiOlsxNixbXV0sXCIhXCI6WzEwLFs1LDIxLDUsNywtMSwtMSw1LDIsNCwxLDUsMCw2LDEsNSwyXV0sJ1wiJzpbMTYsWzQsMjEsNCwxNCwtMSwtMSwxMiwyMSwxMiwxNF1dLFwiI1wiOlsyMSxbMTEsMjUsNCwtNywtMSwtMSwxNywyNSwxMCwtNywtMSwtMSw0LDEyLDE4LDEyLC0xLC0xLDMsNiwxNyw2XV0sJDpbMjAsWzgsMjUsOCwtNCwtMSwtMSwxMiwyNSwxMiwtNCwtMSwtMSwxNywxOCwxNSwyMCwxMiwyMSw4LDIxLDUsMjAsMywxOCwzLDE2LDQsMTQsNSwxMyw3LDEyLDEzLDEwLDE1LDksMTYsOCwxNyw2LDE3LDMsMTUsMSwxMiwwLDgsMCw1LDEsMywzXV0sXCIlXCI6WzI0LFsyMSwyMSwzLDAsLTEsLTEsOCwyMSwxMCwxOSwxMCwxNyw5LDE1LDcsMTQsNSwxNCwzLDE2LDMsMTgsNCwyMCw2LDIxLDgsMjEsMTAsMjAsMTMsMTksMTYsMTksMTksMjAsMjEsMjEsLTEsLTEsMTcsNywxNSw2LDE0LDQsMTQsMiwxNiwwLDE4LDAsMjAsMSwyMSwzLDIxLDUsMTksNywxNyw3XV0sXCImXCI6WzI2LFsyMywxMiwyMywxMywyMiwxNCwyMSwxNCwyMCwxMywxOSwxMSwxNyw2LDE1LDMsMTMsMSwxMSwwLDcsMCw1LDEsNCwyLDMsNCwzLDYsNCw4LDUsOSwxMiwxMywxMywxNCwxNCwxNiwxNCwxOCwxMywyMCwxMSwyMSw5LDIwLDgsMTgsOCwxNiw5LDEzLDExLDEwLDE2LDMsMTgsMSwyMCwwLDIyLDAsMjMsMSwyMywyXV0sXCInXCI6WzEwLFs1LDE5LDQsMjAsNSwyMSw2LDIwLDYsMTgsNSwxNiw0LDE1XV0sXCIoXCI6WzE0LFsxMSwyNSw5LDIzLDcsMjAsNSwxNiw0LDExLDQsNyw1LDIsNywtMiw5LC01LDExLC03XV0sXCIpXCI6WzE0LFszLDI1LDUsMjMsNywyMCw5LDE2LDEwLDExLDEwLDcsOSwyLDcsLTIsNSwtNSwzLC03XV0sXCIqXCI6WzE2LFs4LDIxLDgsOSwtMSwtMSwzLDE4LDEzLDEyLC0xLC0xLDEzLDE4LDMsMTJdXSxcIitcIjpbMjYsWzEzLDE4LDEzLDAsLTEsLTEsNCw5LDIyLDldXSxcIixcIjpbMTAsWzYsMSw1LDAsNCwxLDUsMiw2LDEsNiwtMSw1LC0zLDQsLTRdXSxcIi1cIjpbMjYsWzQsOSwyMiw5XV0sXCIuXCI6WzEwLFs1LDIsNCwxLDUsMCw2LDEsNSwyXV0sXCIvXCI6WzIyLFsyMCwyNSwyLC03XV0sMDpbMjAsWzksMjEsNiwyMCw0LDE3LDMsMTIsMyw5LDQsNCw2LDEsOSwwLDExLDAsMTQsMSwxNiw0LDE3LDksMTcsMTIsMTYsMTcsMTQsMjAsMTEsMjEsOSwyMV1dLDE6WzIwLFs2LDE3LDgsMTgsMTEsMjEsMTEsMF1dLDI6WzIwLFs0LDE2LDQsMTcsNSwxOSw2LDIwLDgsMjEsMTIsMjEsMTQsMjAsMTUsMTksMTYsMTcsMTYsMTUsMTUsMTMsMTMsMTAsMywwLDE3LDBdXSwzOlsyMCxbNSwyMSwxNiwyMSwxMCwxMywxMywxMywxNSwxMiwxNiwxMSwxNyw4LDE3LDYsMTYsMywxNCwxLDExLDAsOCwwLDUsMSw0LDIsMyw0XV0sNDpbMjAsWzEzLDIxLDMsNywxOCw3LC0xLC0xLDEzLDIxLDEzLDBdXSw1OlsyMCxbMTUsMjEsNSwyMSw0LDEyLDUsMTMsOCwxNCwxMSwxNCwxNCwxMywxNiwxMSwxNyw4LDE3LDYsMTYsMywxNCwxLDExLDAsOCwwLDUsMSw0LDIsMyw0XV0sNjpbMjAsWzE2LDE4LDE1LDIwLDEyLDIxLDEwLDIxLDcsMjAsNSwxNyw0LDEyLDQsNyw1LDMsNywxLDEwLDAsMTEsMCwxNCwxLDE2LDMsMTcsNiwxNyw3LDE2LDEwLDE0LDEyLDExLDEzLDEwLDEzLDcsMTIsNSwxMCw0LDddXSw3OlsyMCxbMTcsMjEsNywwLC0xLC0xLDMsMjEsMTcsMjFdXSw4OlsyMCxbOCwyMSw1LDIwLDQsMTgsNCwxNiw1LDE0LDcsMTMsMTEsMTIsMTQsMTEsMTYsOSwxNyw3LDE3LDQsMTYsMiwxNSwxLDEyLDAsOCwwLDUsMSw0LDIsMyw0LDMsNyw0LDksNiwxMSw5LDEyLDEzLDEzLDE1LDE0LDE2LDE2LDE2LDE4LDE1LDIwLDEyLDIxLDgsMjFdXSw5OlsyMCxbMTYsMTQsMTUsMTEsMTMsOSwxMCw4LDksOCw2LDksNCwxMSwzLDE0LDMsMTUsNCwxOCw2LDIwLDksMjEsMTAsMjEsMTMsMjAsMTUsMTgsMTYsMTQsMTYsOSwxNSw0LDEzLDEsMTAsMCw4LDAsNSwxLDQsM11dLFwiOlwiOlsxMCxbNSwxNCw0LDEzLDUsMTIsNiwxMyw1LDE0LC0xLC0xLDUsMiw0LDEsNSwwLDYsMSw1LDJdXSxcIjtcIjpbMTAsWzUsMTQsNCwxMyw1LDEyLDYsMTMsNSwxNCwtMSwtMSw2LDEsNSwwLDQsMSw1LDIsNiwxLDYsLTEsNSwtMyw0LC00XV0sXCI8XCI6WzI0LFsyMCwxOCw0LDksMjAsMF1dLFwiPVwiOlsyNixbNCwxMiwyMiwxMiwtMSwtMSw0LDYsMjIsNl1dLFwiPlwiOlsyNCxbNCwxOCwyMCw5LDQsMF1dLFwiP1wiOlsxOCxbMywxNiwzLDE3LDQsMTksNSwyMCw3LDIxLDExLDIxLDEzLDIwLDE0LDE5LDE1LDE3LDE1LDE1LDE0LDEzLDEzLDEyLDksMTAsOSw3LC0xLC0xLDksMiw4LDEsOSwwLDEwLDEsOSwyXV0sXCJAXCI6WzI3LFsxOCwxMywxNywxNSwxNSwxNiwxMiwxNiwxMCwxNSw5LDE0LDgsMTEsOCw4LDksNiwxMSw1LDE0LDUsMTYsNiwxNyw4LC0xLC0xLDEyLDE2LDEwLDE0LDksMTEsOSw4LDEwLDYsMTEsNSwtMSwtMSwxOCwxNiwxNyw4LDE3LDYsMTksNSwyMSw1LDIzLDcsMjQsMTAsMjQsMTIsMjMsMTUsMjIsMTcsMjAsMTksMTgsMjAsMTUsMjEsMTIsMjEsOSwyMCw3LDE5LDUsMTcsNCwxNSwzLDEyLDMsOSw0LDYsNSw0LDcsMiw5LDEsMTIsMCwxNSwwLDE4LDEsMjAsMiwyMSwzLC0xLC0xLDE5LDE2LDE4LDgsMTgsNiwxOSw1XV0sQTpbMTgsWzksMjEsMSwwLC0xLC0xLDksMjEsMTcsMCwtMSwtMSw0LDcsMTQsN11dLEI6WzIxLFs0LDIxLDQsMCwtMSwtMSw0LDIxLDEzLDIxLDE2LDIwLDE3LDE5LDE4LDE3LDE4LDE1LDE3LDEzLDE2LDEyLDEzLDExLC0xLC0xLDQsMTEsMTMsMTEsMTYsMTAsMTcsOSwxOCw3LDE4LDQsMTcsMiwxNiwxLDEzLDAsNCwwXV0sQzpbMjEsWzE4LDE2LDE3LDE4LDE1LDIwLDEzLDIxLDksMjEsNywyMCw1LDE4LDQsMTYsMywxMywzLDgsNCw1LDUsMyw3LDEsOSwwLDEzLDAsMTUsMSwxNywzLDE4LDVdXSxEOlsyMSxbNCwyMSw0LDAsLTEsLTEsNCwyMSwxMSwyMSwxNCwyMCwxNiwxOCwxNywxNiwxOCwxMywxOCw4LDE3LDUsMTYsMywxNCwxLDExLDAsNCwwXV0sRTpbMTksWzQsMjEsNCwwLC0xLC0xLDQsMjEsMTcsMjEsLTEsLTEsNCwxMSwxMiwxMSwtMSwtMSw0LDAsMTcsMF1dLEY6WzE4LFs0LDIxLDQsMCwtMSwtMSw0LDIxLDE3LDIxLC0xLC0xLDQsMTEsMTIsMTFdXSxHOlsyMSxbMTgsMTYsMTcsMTgsMTUsMjAsMTMsMjEsOSwyMSw3LDIwLDUsMTgsNCwxNiwzLDEzLDMsOCw0LDUsNSwzLDcsMSw5LDAsMTMsMCwxNSwxLDE3LDMsMTgsNSwxOCw4LC0xLC0xLDEzLDgsMTgsOF1dLEg6WzIyLFs0LDIxLDQsMCwtMSwtMSwxOCwyMSwxOCwwLC0xLC0xLDQsMTEsMTgsMTFdXSxJOls4LFs0LDIxLDQsMF1dLEo6WzE2LFsxMiwyMSwxMiw1LDExLDIsMTAsMSw4LDAsNiwwLDQsMSwzLDIsMiw1LDIsN11dLEs6WzIxLFs0LDIxLDQsMCwtMSwtMSwxOCwyMSw0LDcsLTEsLTEsOSwxMiwxOCwwXV0sTDpbMTcsWzQsMjEsNCwwLC0xLC0xLDQsMCwxNiwwXV0sTTpbMjQsWzQsMjEsNCwwLC0xLC0xLDQsMjEsMTIsMCwtMSwtMSwyMCwyMSwxMiwwLC0xLC0xLDIwLDIxLDIwLDBdXSxOOlsyMixbNCwyMSw0LDAsLTEsLTEsNCwyMSwxOCwwLC0xLC0xLDE4LDIxLDE4LDBdXSxPOlsyMixbOSwyMSw3LDIwLDUsMTgsNCwxNiwzLDEzLDMsOCw0LDUsNSwzLDcsMSw5LDAsMTMsMCwxNSwxLDE3LDMsMTgsNSwxOSw4LDE5LDEzLDE4LDE2LDE3LDE4LDE1LDIwLDEzLDIxLDksMjFdXSxQOlsyMSxbNCwyMSw0LDAsLTEsLTEsNCwyMSwxMywyMSwxNiwyMCwxNywxOSwxOCwxNywxOCwxNCwxNywxMiwxNiwxMSwxMywxMCw0LDEwXV0sUTpbMjIsWzksMjEsNywyMCw1LDE4LDQsMTYsMywxMywzLDgsNCw1LDUsMyw3LDEsOSwwLDEzLDAsMTUsMSwxNywzLDE4LDUsMTksOCwxOSwxMywxOCwxNiwxNywxOCwxNSwyMCwxMywyMSw5LDIxLC0xLC0xLDEyLDQsMTgsLTJdXSxSOlsyMSxbNCwyMSw0LDAsLTEsLTEsNCwyMSwxMywyMSwxNiwyMCwxNywxOSwxOCwxNywxOCwxNSwxNywxMywxNiwxMiwxMywxMSw0LDExLC0xLC0xLDExLDExLDE4LDBdXSxTOlsyMCxbMTcsMTgsMTUsMjAsMTIsMjEsOCwyMSw1LDIwLDMsMTgsMywxNiw0LDE0LDUsMTMsNywxMiwxMywxMCwxNSw5LDE2LDgsMTcsNiwxNywzLDE1LDEsMTIsMCw4LDAsNSwxLDMsM11dLFQ6WzE2LFs4LDIxLDgsMCwtMSwtMSwxLDIxLDE1LDIxXV0sVTpbMjIsWzQsMjEsNCw2LDUsMyw3LDEsMTAsMCwxMiwwLDE1LDEsMTcsMywxOCw2LDE4LDIxXV0sVjpbMTgsWzEsMjEsOSwwLC0xLC0xLDE3LDIxLDksMF1dLFc6WzI0LFsyLDIxLDcsMCwtMSwtMSwxMiwyMSw3LDAsLTEsLTEsMTIsMjEsMTcsMCwtMSwtMSwyMiwyMSwxNywwXV0sWDpbMjAsWzMsMjEsMTcsMCwtMSwtMSwxNywyMSwzLDBdXSxZOlsxOCxbMSwyMSw5LDExLDksMCwtMSwtMSwxNywyMSw5LDExXV0sWjpbMjAsWzE3LDIxLDMsMCwtMSwtMSwzLDIxLDE3LDIxLC0xLC0xLDMsMCwxNywwXV0sXCJbXCI6WzE0LFs0LDI1LDQsLTcsLTEsLTEsNSwyNSw1LC03LC0xLC0xLDQsMjUsMTEsMjUsLTEsLTEsNCwtNywxMSwtN11dLFwiXFxcXFwiOlsxNCxbMCwyMSwxNCwtM11dLFwiXVwiOlsxNCxbOSwyNSw5LC03LC0xLC0xLDEwLDI1LDEwLC03LC0xLC0xLDMsMjUsMTAsMjUsLTEsLTEsMywtNywxMCwtN11dLFwiXlwiOlsxNixbNiwxNSw4LDE4LDEwLDE1LC0xLC0xLDMsMTIsOCwxNywxMywxMiwtMSwtMSw4LDE3LDgsMF1dLF86WzE2LFswLC0yLDE2LC0yXV0sXCJgXCI6WzEwLFs2LDIxLDUsMjAsNCwxOCw0LDE2LDUsMTUsNiwxNiw1LDE3XV0sYTpbMTksWzE1LDE0LDE1LDAsLTEsLTEsMTUsMTEsMTMsMTMsMTEsMTQsOCwxNCw2LDEzLDQsMTEsMyw4LDMsNiw0LDMsNiwxLDgsMCwxMSwwLDEzLDEsMTUsM11dLGI6WzE5LFs0LDIxLDQsMCwtMSwtMSw0LDExLDYsMTMsOCwxNCwxMSwxNCwxMywxMywxNSwxMSwxNiw4LDE2LDYsMTUsMywxMywxLDExLDAsOCwwLDYsMSw0LDNdXSxjOlsxOCxbMTUsMTEsMTMsMTMsMTEsMTQsOCwxNCw2LDEzLDQsMTEsMyw4LDMsNiw0LDMsNiwxLDgsMCwxMSwwLDEzLDEsMTUsM11dLGQ6WzE5LFsxNSwyMSwxNSwwLC0xLC0xLDE1LDExLDEzLDEzLDExLDE0LDgsMTQsNiwxMyw0LDExLDMsOCwzLDYsNCwzLDYsMSw4LDAsMTEsMCwxMywxLDE1LDNdXSxlOlsxOCxbMyw4LDE1LDgsMTUsMTAsMTQsMTIsMTMsMTMsMTEsMTQsOCwxNCw2LDEzLDQsMTEsMyw4LDMsNiw0LDMsNiwxLDgsMCwxMSwwLDEzLDEsMTUsM11dLGY6WzEyLFsxMCwyMSw4LDIxLDYsMjAsNSwxNyw1LDAsLTEsLTEsMiwxNCw5LDE0XV0sZzpbMTksWzE1LDE0LDE1LC0yLDE0LC01LDEzLC02LDExLC03LDgsLTcsNiwtNiwtMSwtMSwxNSwxMSwxMywxMywxMSwxNCw4LDE0LDYsMTMsNCwxMSwzLDgsMyw2LDQsMyw2LDEsOCwwLDExLDAsMTMsMSwxNSwzXV0saDpbMTksWzQsMjEsNCwwLC0xLC0xLDQsMTAsNywxMyw5LDE0LDEyLDE0LDE0LDEzLDE1LDEwLDE1LDBdXSxpOls4LFszLDIxLDQsMjAsNSwyMSw0LDIyLDMsMjEsLTEsLTEsNCwxNCw0LDBdXSxqOlsxMCxbNSwyMSw2LDIwLDcsMjEsNiwyMiw1LDIxLC0xLC0xLDYsMTQsNiwtMyw1LC02LDMsLTcsMSwtN11dLGs6WzE3LFs0LDIxLDQsMCwtMSwtMSwxNCwxNCw0LDQsLTEsLTEsOCw4LDE1LDBdXSxsOls4LFs0LDIxLDQsMF1dLG06WzMwLFs0LDE0LDQsMCwtMSwtMSw0LDEwLDcsMTMsOSwxNCwxMiwxNCwxNCwxMywxNSwxMCwxNSwwLC0xLC0xLDE1LDEwLDE4LDEzLDIwLDE0LDIzLDE0LDI1LDEzLDI2LDEwLDI2LDBdXSxuOlsxOSxbNCwxNCw0LDAsLTEsLTEsNCwxMCw3LDEzLDksMTQsMTIsMTQsMTQsMTMsMTUsMTAsMTUsMF1dLG86WzE5LFs4LDE0LDYsMTMsNCwxMSwzLDgsMyw2LDQsMyw2LDEsOCwwLDExLDAsMTMsMSwxNSwzLDE2LDYsMTYsOCwxNSwxMSwxMywxMywxMSwxNCw4LDE0XV0scDpbMTksWzQsMTQsNCwtNywtMSwtMSw0LDExLDYsMTMsOCwxNCwxMSwxNCwxMywxMywxNSwxMSwxNiw4LDE2LDYsMTUsMywxMywxLDExLDAsOCwwLDYsMSw0LDNdXSxxOlsxOSxbMTUsMTQsMTUsLTcsLTEsLTEsMTUsMTEsMTMsMTMsMTEsMTQsOCwxNCw2LDEzLDQsMTEsMyw4LDMsNiw0LDMsNiwxLDgsMCwxMSwwLDEzLDEsMTUsM11dLHI6WzEzLFs0LDE0LDQsMCwtMSwtMSw0LDgsNSwxMSw3LDEzLDksMTQsMTIsMTRdXSxzOlsxNyxbMTQsMTEsMTMsMTMsMTAsMTQsNywxNCw0LDEzLDMsMTEsNCw5LDYsOCwxMSw3LDEzLDYsMTQsNCwxNCwzLDEzLDEsMTAsMCw3LDAsNCwxLDMsM11dLHQ6WzEyLFs1LDIxLDUsNCw2LDEsOCwwLDEwLDAsLTEsLTEsMiwxNCw5LDE0XV0sdTpbMTksWzQsMTQsNCw0LDUsMSw3LDAsMTAsMCwxMiwxLDE1LDQsLTEsLTEsMTUsMTQsMTUsMF1dLHY6WzE2LFsyLDE0LDgsMCwtMSwtMSwxNCwxNCw4LDBdXSx3OlsyMixbMywxNCw3LDAsLTEsLTEsMTEsMTQsNywwLC0xLC0xLDExLDE0LDE1LDAsLTEsLTEsMTksMTQsMTUsMF1dLHg6WzE3LFszLDE0LDE0LDAsLTEsLTEsMTQsMTQsMywwXV0seTpbMTYsWzIsMTQsOCwwLC0xLC0xLDE0LDE0LDgsMCw2LC00LDQsLTYsMiwtNywxLC03XV0sejpbMTcsWzE0LDE0LDMsMCwtMSwtMSwzLDE0LDE0LDE0LC0xLC0xLDMsMCwxNCwwXV0sXCJ7XCI6WzE0LFs5LDI1LDcsMjQsNiwyMyw1LDIxLDUsMTksNiwxNyw3LDE2LDgsMTQsOCwxMiw2LDEwLC0xLC0xLDcsMjQsNiwyMiw2LDIwLDcsMTgsOCwxNyw5LDE1LDksMTMsOCwxMSw0LDksOCw3LDksNSw5LDMsOCwxLDcsMCw2LC0yLDYsLTQsNywtNiwtMSwtMSw2LDgsOCw2LDgsNCw3LDIsNiwxLDUsLTEsNSwtMyw2LC01LDcsLTYsOSwtN11dLFwifFwiOls4LFs0LDI1LDQsLTddXSxcIn1cIjpbMTQsWzUsMjUsNywyNCw4LDIzLDksMjEsOSwxOSw4LDE3LDcsMTYsNiwxNCw2LDEyLDgsMTAsLTEsLTEsNywyNCw4LDIyLDgsMjAsNywxOCw2LDE3LDUsMTUsNSwxMyw2LDExLDEwLDksNiw3LDUsNSw1LDMsNiwxLDcsMCw4LC0yLDgsLTQsNywtNiwtMSwtMSw4LDgsNiw2LDYsNCw3LDIsOCwxLDksLTEsOSwtMyw4LC01LDcsLTYsNSwtN11dLFwiflwiOlsyNCxbMyw2LDMsOCw0LDExLDYsMTIsOCwxMiwxMCwxMSwxNCw4LDE2LDcsMTgsNywyMCw4LDIxLDEwLC0xLC0xLDMsOCw0LDEwLDYsMTEsOCwxMSwxMCwxMCwxNCw3LDE2LDYsMTgsNiwyMCw3LDIxLDEwLDIxLDEyXV19O3ZhciBybz17c3ltYm9sOmZ1bmN0aW9uKHQsZSxpLG8scil7aWYoXCJ0cmFuc2x1Y2VudFwiPT09dC5yZW5kZXJQYXNzKXt2YXIgYT1JdC5kaXNhYmxlZCxuPXQuY29sb3JNb2RlRm9yUmVuZGVyUGFzcygpOzAhPT1pLnBhaW50LmdldChcImljb24tb3BhY2l0eVwiKS5jb25zdGFudE9yKDEpJiZLaSh0LGUsaSxvLCExLGkucGFpbnQuZ2V0KFwiaWNvbi10cmFuc2xhdGVcIiksaS5wYWludC5nZXQoXCJpY29uLXRyYW5zbGF0ZS1hbmNob3JcIiksaS5sYXlvdXQuZ2V0KFwiaWNvbi1yb3RhdGlvbi1hbGlnbm1lbnRcIiksaS5sYXlvdXQuZ2V0KFwiaWNvbi1waXRjaC1hbGlnbm1lbnRcIiksaS5sYXlvdXQuZ2V0KFwiaWNvbi1rZWVwLXVwcmlnaHRcIiksYSxuLHIpLDAhPT1pLnBhaW50LmdldChcInRleHQtb3BhY2l0eVwiKS5jb25zdGFudE9yKDEpJiZLaSh0LGUsaSxvLCEwLGkucGFpbnQuZ2V0KFwidGV4dC10cmFuc2xhdGVcIiksaS5wYWludC5nZXQoXCJ0ZXh0LXRyYW5zbGF0ZS1hbmNob3JcIiksaS5sYXlvdXQuZ2V0KFwidGV4dC1yb3RhdGlvbi1hbGlnbm1lbnRcIiksaS5sYXlvdXQuZ2V0KFwidGV4dC1waXRjaC1hbGlnbm1lbnRcIiksaS5sYXlvdXQuZ2V0KFwidGV4dC1rZWVwLXVwcmlnaHRcIiksYSxuLHIpLGUubWFwLnNob3dDb2xsaXNpb25Cb3hlcyYmZnVuY3Rpb24odCxlLGksbyl7R2kodCxlLGksbywhMSksR2kodCxlLGksbywhMCk7fSh0LGUsaSxvKTt9fSxjaXJjbGU6ZnVuY3Rpb24odCxlLGksbyl7aWYoXCJ0cmFuc2x1Y2VudFwiPT09dC5yZW5kZXJQYXNzKXt2YXIgcj1pLnBhaW50LmdldChcImNpcmNsZS1vcGFjaXR5XCIpLGE9aS5wYWludC5nZXQoXCJjaXJjbGUtc3Ryb2tlLXdpZHRoXCIpLG49aS5wYWludC5nZXQoXCJjaXJjbGUtc3Ryb2tlLW9wYWNpdHlcIik7aWYoMCE9PXIuY29uc3RhbnRPcigxKXx8MCE9PWEuY29uc3RhbnRPcigxKSYmMCE9PW4uY29uc3RhbnRPcigxKSlmb3IodmFyIHM9dC5jb250ZXh0LGw9cy5nbCxjPXQuZGVwdGhNb2RlRm9yU3VibGF5ZXIoMCxUdC5SZWFkT25seSksdT1JdC5kaXNhYmxlZCxoPXQuY29sb3JNb2RlRm9yUmVuZGVyUGFzcygpLHA9MDtwPG8ubGVuZ3RoO3ArKyl7dmFyIGQ9b1twXSxfPWUuZ2V0VGlsZShkKSxmPV8uZ2V0QnVja2V0KGkpO2lmKGYpe3ZhciBtPWYucHJvZ3JhbUNvbmZpZ3VyYXRpb25zLmdldChpLmlkKTt0LnVzZVByb2dyYW0oXCJjaXJjbGVcIixtKS5kcmF3KHMsbC5UUklBTkdMRVMsYyx1LGgsU3QuZGlzYWJsZWQseGkodCxkLF8saSksaS5pZCxmLmxheW91dFZlcnRleEJ1ZmZlcixmLmluZGV4QnVmZmVyLGYuc2VnbWVudHMsaS5wYWludCx0LnRyYW5zZm9ybS56b29tLG0pO319fX0saGVhdG1hcDpmdW5jdGlvbihlLGksbyxyKXtpZigwIT09by5wYWludC5nZXQoXCJoZWF0bWFwLW9wYWNpdHlcIikpaWYoXCJvZmZzY3JlZW5cIj09PWUucmVuZGVyUGFzcyl7dmFyIGE9ZS5jb250ZXh0LG49YS5nbCxzPWUuZGVwdGhNb2RlRm9yU3VibGF5ZXIoMCxUdC5SZWFkT25seSksbD1JdC5kaXNhYmxlZCxjPW5ldyBDdChbbi5PTkUsbi5PTkVdLHQuQ29sb3IudHJhbnNwYXJlbnQsWyEwLCEwLCEwLCEwXSk7IWZ1bmN0aW9uKHQsZSxpKXt2YXIgbz10LmdsO3QuYWN0aXZlVGV4dHVyZS5zZXQoby5URVhUVVJFMSksdC52aWV3cG9ydC5zZXQoWzAsMCxlLndpZHRoLzQsZS5oZWlnaHQvNF0pO3ZhciByPWkuaGVhdG1hcEZibztpZihyKW8uYmluZFRleHR1cmUoby5URVhUVVJFXzJELHIuY29sb3JBdHRhY2htZW50LmdldCgpKSx0LmJpbmRGcmFtZWJ1ZmZlci5zZXQoci5mcmFtZWJ1ZmZlcik7ZWxzZXt2YXIgYT1vLmNyZWF0ZVRleHR1cmUoKTtvLmJpbmRUZXh0dXJlKG8uVEVYVFVSRV8yRCxhKSxvLnRleFBhcmFtZXRlcmkoby5URVhUVVJFXzJELG8uVEVYVFVSRV9XUkFQX1Msby5DTEFNUF9UT19FREdFKSxvLnRleFBhcmFtZXRlcmkoby5URVhUVVJFXzJELG8uVEVYVFVSRV9XUkFQX1Qsby5DTEFNUF9UT19FREdFKSxvLnRleFBhcmFtZXRlcmkoby5URVhUVVJFXzJELG8uVEVYVFVSRV9NSU5fRklMVEVSLG8uTElORUFSKSxvLnRleFBhcmFtZXRlcmkoby5URVhUVVJFXzJELG8uVEVYVFVSRV9NQUdfRklMVEVSLG8uTElORUFSKSxyPWkuaGVhdG1hcEZibz10LmNyZWF0ZUZyYW1lYnVmZmVyKGUud2lkdGgvNCxlLmhlaWdodC80KSxmdW5jdGlvbiB0KGUsaSxvLHIpe3ZhciBhPWUuZ2w7YS50ZXhJbWFnZTJEKGEuVEVYVFVSRV8yRCwwLGEuUkdCQSxpLndpZHRoLzQsaS5oZWlnaHQvNCwwLGEuUkdCQSxlLmV4dFRleHR1cmVIYWxmRmxvYXQ/ZS5leHRUZXh0dXJlSGFsZkZsb2F0LkhBTEZfRkxPQVRfT0VTOmEuVU5TSUdORURfQllURSxudWxsKSxyLmNvbG9yQXR0YWNobWVudC5zZXQobyksZS5leHRUZXh0dXJlSGFsZkZsb2F0JiZhLmNoZWNrRnJhbWVidWZmZXJTdGF0dXMoYS5GUkFNRUJVRkZFUikhPT1hLkZSQU1FQlVGRkVSX0NPTVBMRVRFJiYoZS5leHRUZXh0dXJlSGFsZkZsb2F0PW51bGwsci5jb2xvckF0dGFjaG1lbnQuc2V0RGlydHkoKSx0KGUsaSxvLHIpKTt9KHQsZSxhLHIpO319KGEsZSxvKSxhLmNsZWFyKHtjb2xvcjp0LkNvbG9yLnRyYW5zcGFyZW50fSk7Zm9yKHZhciB1PTA7dTxyLmxlbmd0aDt1Kyspe3ZhciBoPXJbdV07aWYoIWkuaGFzUmVuZGVyYWJsZVBhcmVudChoKSl7dmFyIHA9aS5nZXRUaWxlKGgpLGQ9cC5nZXRCdWNrZXQobyk7aWYoZCl7dmFyIF89ZC5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KG8uaWQpLGY9ZS51c2VQcm9ncmFtKFwiaGVhdG1hcFwiLF8pLG09ZS50cmFuc2Zvcm0uem9vbTtmLmRyYXcoYSxuLlRSSUFOR0xFUyxzLGwsYyxTdC5kaXNhYmxlZCxJaShoLnBvc01hdHJpeCxwLG0sby5wYWludC5nZXQoXCJoZWF0bWFwLWludGVuc2l0eVwiKSksby5pZCxkLmxheW91dFZlcnRleEJ1ZmZlcixkLmluZGV4QnVmZmVyLGQuc2VnbWVudHMsby5wYWludCxlLnRyYW5zZm9ybS56b29tLF8pO319fWEudmlld3BvcnQuc2V0KFswLDAsZS53aWR0aCxlLmhlaWdodF0pO31lbHNlXCJ0cmFuc2x1Y2VudFwiPT09ZS5yZW5kZXJQYXNzJiYoZS5jb250ZXh0LnNldENvbG9yTW9kZShlLmNvbG9yTW9kZUZvclJlbmRlclBhc3MoKSksZnVuY3Rpb24oZSxpKXt2YXIgbz1lLmNvbnRleHQscj1vLmdsLGE9aS5oZWF0bWFwRmJvO2lmKGEpe28uYWN0aXZlVGV4dHVyZS5zZXQoci5URVhUVVJFMCksci5iaW5kVGV4dHVyZShyLlRFWFRVUkVfMkQsYS5jb2xvckF0dGFjaG1lbnQuZ2V0KCkpLG8uYWN0aXZlVGV4dHVyZS5zZXQoci5URVhUVVJFMSk7dmFyIG49aS5jb2xvclJhbXBUZXh0dXJlO258fChuPWkuY29sb3JSYW1wVGV4dHVyZT1uZXcgdC5UZXh0dXJlKG8saS5jb2xvclJhbXAsci5SR0JBKSksbi5iaW5kKHIuTElORUFSLHIuQ0xBTVBfVE9fRURHRSksZS51c2VQcm9ncmFtKFwiaGVhdG1hcFRleHR1cmVcIikuZHJhdyhvLHIuVFJJQU5HTEVTLFR0LmRpc2FibGVkLEl0LmRpc2FibGVkLGUuY29sb3JNb2RlRm9yUmVuZGVyUGFzcygpLFN0LmRpc2FibGVkLENpKGUsaSwwLDEpLGkuaWQsZS52aWV3cG9ydEJ1ZmZlcixlLnF1YWRUcmlhbmdsZUluZGV4QnVmZmVyLGUudmlld3BvcnRTZWdtZW50cyxpLnBhaW50LGUudHJhbnNmb3JtLnpvb20pO319KGUsbykpO30sbGluZTpmdW5jdGlvbihlLGksbyxyKXtpZihcInRyYW5zbHVjZW50XCI9PT1lLnJlbmRlclBhc3Mpe3ZhciBhPW8ucGFpbnQuZ2V0KFwibGluZS1vcGFjaXR5XCIpLG49by5wYWludC5nZXQoXCJsaW5lLXdpZHRoXCIpO2lmKDAhPT1hLmNvbnN0YW50T3IoMSkmJjAhPT1uLmNvbnN0YW50T3IoMSkpe3ZhciBzPWUuZGVwdGhNb2RlRm9yU3VibGF5ZXIoMCxUdC5SZWFkT25seSksbD1lLmNvbG9yTW9kZUZvclJlbmRlclBhc3MoKSxjPW8ucGFpbnQuZ2V0KFwibGluZS1kYXNoYXJyYXlcIiksdT1vLnBhaW50LmdldChcImxpbmUtcGF0dGVyblwiKSxoPXUuY29uc3RhbnRPcigxKSxwPW8ucGFpbnQuZ2V0KFwibGluZS1ncmFkaWVudFwiKSxkPW8uZ2V0Q3Jvc3NmYWRlUGFyYW1ldGVycygpLF89Yz9cImxpbmVTREZcIjpoP1wibGluZVBhdHRlcm5cIjpwP1wibGluZUdyYWRpZW50XCI6XCJsaW5lXCIsZj1lLmNvbnRleHQsbT1mLmdsLGc9ITA7aWYocCl7Zi5hY3RpdmVUZXh0dXJlLnNldChtLlRFWFRVUkUwKTt2YXIgdj1vLmdyYWRpZW50VGV4dHVyZTtpZighby5ncmFkaWVudClyZXR1cm47dnx8KHY9by5ncmFkaWVudFRleHR1cmU9bmV3IHQuVGV4dHVyZShmLG8uZ3JhZGllbnQsbS5SR0JBKSksdi5iaW5kKG0uTElORUFSLG0uQ0xBTVBfVE9fRURHRSk7fWZvcih2YXIgeT0wLHg9cjt5PHgubGVuZ3RoO3krPTEpe3ZhciBiPXhbeV0sdz1pLmdldFRpbGUoYik7aWYoIWh8fHcucGF0dGVybnNMb2FkZWQoKSl7dmFyIEU9dy5nZXRCdWNrZXQobyk7aWYoRSl7dmFyIFQ9RS5wcm9ncmFtQ29uZmlndXJhdGlvbnMuZ2V0KG8uaWQpLEk9ZS5jb250ZXh0LnByb2dyYW0uZ2V0KCksQz1lLnVzZVByb2dyYW0oXyxUKSxTPWd8fEMucHJvZ3JhbSE9PUksUD11LmNvbnN0YW50T3IobnVsbCk7aWYoUCYmdy5pbWFnZUF0bGFzKXt2YXIgej13LmltYWdlQXRsYXMucGF0dGVyblBvc2l0aW9uc1tQLnRvXSxMPXcuaW1hZ2VBdGxhcy5wYXR0ZXJuUG9zaXRpb25zW1AuZnJvbV07eiYmTCYmVC5zZXRDb25zdGFudFBhdHRlcm5Qb3NpdGlvbnMoeixMKTt9dmFyIEQ9Yz9SaShlLHcsbyxjLGQpOmg/TWkoZSx3LG8sZCk6cD9EaShlLHcsbyk6TGkoZSx3LG8pO2MmJihTfHxlLmxpbmVBdGxhcy5kaXJ0eSk/KGYuYWN0aXZlVGV4dHVyZS5zZXQobS5URVhUVVJFMCksZS5saW5lQXRsYXMuYmluZChmKSk6aCYmKGYuYWN0aXZlVGV4dHVyZS5zZXQobS5URVhUVVJFMCksdy5pbWFnZUF0bGFzVGV4dHVyZS5iaW5kKG0uTElORUFSLG0uQ0xBTVBfVE9fRURHRSksVC51cGRhdGVQYXR0ZXJuUGFpbnRCdWZmZXJzKGQpKSxDLmRyYXcoZixtLlRSSUFOR0xFUyxzLGUuc3RlbmNpbE1vZGVGb3JDbGlwcGluZyhiKSxsLFN0LmRpc2FibGVkLEQsby5pZCxFLmxheW91dFZlcnRleEJ1ZmZlcixFLmluZGV4QnVmZmVyLEUuc2VnbWVudHMsby5wYWludCxlLnRyYW5zZm9ybS56b29tLFQpLGc9ITE7fX19fX19LGZpbGw6ZnVuY3Rpb24oZSxpLG8scil7dmFyIGE9by5wYWludC5nZXQoXCJmaWxsLWNvbG9yXCIpLG49by5wYWludC5nZXQoXCJmaWxsLW9wYWNpdHlcIik7aWYoMCE9PW4uY29uc3RhbnRPcigxKSl7dmFyIHM9ZS5jb2xvck1vZGVGb3JSZW5kZXJQYXNzKCksbD1vLnBhaW50LmdldChcImZpbGwtcGF0dGVyblwiKSxjPWUub3BhcXVlUGFzc0VuYWJsZWRGb3JMYXllcigpJiYhbC5jb25zdGFudE9yKDEpJiYxPT09YS5jb25zdGFudE9yKHQuQ29sb3IudHJhbnNwYXJlbnQpLmEmJjE9PT1uLmNvbnN0YW50T3IoMCk/XCJvcGFxdWVcIjpcInRyYW5zbHVjZW50XCI7aWYoZS5yZW5kZXJQYXNzPT09Yyl7dmFyIHU9ZS5kZXB0aE1vZGVGb3JTdWJsYXllcigxLFwib3BhcXVlXCI9PT1lLnJlbmRlclBhc3M/VHQuUmVhZFdyaXRlOlR0LlJlYWRPbmx5KTtKaShlLGksbyxyLHUscywhMSk7fWlmKFwidHJhbnNsdWNlbnRcIj09PWUucmVuZGVyUGFzcyYmby5wYWludC5nZXQoXCJmaWxsLWFudGlhbGlhc1wiKSl7dmFyIGg9ZS5kZXB0aE1vZGVGb3JTdWJsYXllcihvLmdldFBhaW50UHJvcGVydHkoXCJmaWxsLW91dGxpbmUtY29sb3JcIik/MjowLFR0LlJlYWRPbmx5KTtKaShlLGksbyxyLGgscywhMCk7fX19LFwiZmlsbC1leHRydXNpb25cIjpmdW5jdGlvbih0LGUsaSxvKXt2YXIgcj1pLnBhaW50LmdldChcImZpbGwtZXh0cnVzaW9uLW9wYWNpdHlcIik7aWYoMCE9PXImJlwidHJhbnNsdWNlbnRcIj09PXQucmVuZGVyUGFzcyl7dmFyIGE9bmV3IFR0KHQuY29udGV4dC5nbC5MRVFVQUwsVHQuUmVhZFdyaXRlLHQuZGVwdGhSYW5nZUZvcjNEKTtpZigxIT09cnx8aS5wYWludC5nZXQoXCJmaWxsLWV4dHJ1c2lvbi1wYXR0ZXJuXCIpLmNvbnN0YW50T3IoMSkpUWkodCxlLGksbyxhLEl0LmRpc2FibGVkLEN0LmRpc2FibGVkKSxRaSh0LGUsaSxvLGEsdC5zdGVuY2lsTW9kZUZvcjNEKCksdC5jb2xvck1vZGVGb3JSZW5kZXJQYXNzKCkpO2Vsc2V7dmFyIG49dC5jb2xvck1vZGVGb3JSZW5kZXJQYXNzKCk7UWkodCxlLGksbyxhLEl0LmRpc2FibGVkLG4pO319fSxoaWxsc2hhZGU6ZnVuY3Rpb24odCxlLGksbyl7aWYoXCJvZmZzY3JlZW5cIj09PXQucmVuZGVyUGFzc3x8XCJ0cmFuc2x1Y2VudFwiPT09dC5yZW5kZXJQYXNzKXtmb3IodmFyIHI9dC5jb250ZXh0LGE9ZS5nZXRTb3VyY2UoKS5tYXh6b29tLG49dC5kZXB0aE1vZGVGb3JTdWJsYXllcigwLFR0LlJlYWRPbmx5KSxzPUl0LmRpc2FibGVkLGw9dC5jb2xvck1vZGVGb3JSZW5kZXJQYXNzKCksYz0wLHU9bztjPHUubGVuZ3RoO2MrPTEpe3ZhciBoPXVbY10scD1lLmdldFRpbGUoaCk7cC5uZWVkc0hpbGxzaGFkZVByZXBhcmUmJlwib2Zmc2NyZWVuXCI9PT10LnJlbmRlclBhc3M/dG8odCxwLGksYSxuLHMsbCk6XCJ0cmFuc2x1Y2VudFwiPT09dC5yZW5kZXJQYXNzJiYkaSh0LHAsaSxuLHMsbCk7fXIudmlld3BvcnQuc2V0KFswLDAsdC53aWR0aCx0LmhlaWdodF0pO319LHJhc3RlcjpmdW5jdGlvbih0LGUsaSxvKXtpZihcInRyYW5zbHVjZW50XCI9PT10LnJlbmRlclBhc3MmJjAhPT1pLnBhaW50LmdldChcInJhc3Rlci1vcGFjaXR5XCIpKWZvcih2YXIgcj10LmNvbnRleHQsYT1yLmdsLG49ZS5nZXRTb3VyY2UoKSxzPXQudXNlUHJvZ3JhbShcInJhc3RlclwiKSxsPUl0LmRpc2FibGVkLGM9dC5jb2xvck1vZGVGb3JSZW5kZXJQYXNzKCksdT1vLmxlbmd0aCYmb1swXS5vdmVyc2NhbGVkWixoPSF0Lm9wdGlvbnMubW92aW5nLHA9MCxkPW87cDxkLmxlbmd0aDtwKz0xKXt2YXIgXz1kW3BdLGY9dC5kZXB0aE1vZGVGb3JTdWJsYXllcihfLm92ZXJzY2FsZWRaLXUsMT09PWkucGFpbnQuZ2V0KFwicmFzdGVyLW9wYWNpdHlcIik/VHQuUmVhZFdyaXRlOlR0LlJlYWRPbmx5LGEuTEVTUyksbT1lLmdldFRpbGUoXyksZz10LnRyYW5zZm9ybS5jYWxjdWxhdGVQb3NNYXRyaXgoXy50b1Vud3JhcHBlZCgpLGgpO20ucmVnaXN0ZXJGYWRlRHVyYXRpb24oaS5wYWludC5nZXQoXCJyYXN0ZXItZmFkZS1kdXJhdGlvblwiKSk7dmFyIHY9ZS5maW5kTG9hZGVkUGFyZW50KF8sMCkseT1lbyhtLHYsZSxpLHQudHJhbnNmb3JtKSx4PXZvaWQgMCxiPXZvaWQgMCx3PVwibmVhcmVzdFwiPT09aS5wYWludC5nZXQoXCJyYXN0ZXItcmVzYW1wbGluZ1wiKT9hLk5FQVJFU1Q6YS5MSU5FQVI7ci5hY3RpdmVUZXh0dXJlLnNldChhLlRFWFRVUkUwKSxtLnRleHR1cmUuYmluZCh3LGEuQ0xBTVBfVE9fRURHRSxhLkxJTkVBUl9NSVBNQVBfTkVBUkVTVCksci5hY3RpdmVUZXh0dXJlLnNldChhLlRFWFRVUkUxKSx2Pyh2LnRleHR1cmUuYmluZCh3LGEuQ0xBTVBfVE9fRURHRSxhLkxJTkVBUl9NSVBNQVBfTkVBUkVTVCkseD1NYXRoLnBvdygyLHYudGlsZUlELm92ZXJzY2FsZWRaLW0udGlsZUlELm92ZXJzY2FsZWRaKSxiPVttLnRpbGVJRC5jYW5vbmljYWwueCp4JTEsbS50aWxlSUQuY2Fub25pY2FsLnkqeCUxXSk6bS50ZXh0dXJlLmJpbmQodyxhLkNMQU1QX1RPX0VER0UsYS5MSU5FQVJfTUlQTUFQX05FQVJFU1QpO3ZhciBFPUJpKGcsYnx8WzAsMF0seHx8MSx5LGkpO24gaW5zdGFuY2VvZiBMP3MuZHJhdyhyLGEuVFJJQU5HTEVTLGYsbCxjLFN0LmRpc2FibGVkLEUsaS5pZCxuLmJvdW5kc0J1ZmZlcix0LnF1YWRUcmlhbmdsZUluZGV4QnVmZmVyLG4uYm91bmRzU2VnbWVudHMpOm0ubWFza2VkQm91bmRzQnVmZmVyJiZtLm1hc2tlZEluZGV4QnVmZmVyJiZtLnNlZ21lbnRzP3MuZHJhdyhyLGEuVFJJQU5HTEVTLGYsbCxjLFN0LmRpc2FibGVkLEUsaS5pZCxtLm1hc2tlZEJvdW5kc0J1ZmZlcixtLm1hc2tlZEluZGV4QnVmZmVyLG0uc2VnbWVudHMsaS5wYWludCx0LnRyYW5zZm9ybS56b29tKTpzLmRyYXcocixhLlRSSUFOR0xFUyxmLGwsYyxTdC5kaXNhYmxlZCxFLGkuaWQsdC5yYXN0ZXJCb3VuZHNCdWZmZXIsdC5xdWFkVHJpYW5nbGVJbmRleEJ1ZmZlcix0LnJhc3RlckJvdW5kc1NlZ21lbnRzKTt9fSxiYWNrZ3JvdW5kOmZ1bmN0aW9uKHQsZSxpKXt2YXIgbz1pLnBhaW50LmdldChcImJhY2tncm91bmQtY29sb3JcIikscj1pLnBhaW50LmdldChcImJhY2tncm91bmQtb3BhY2l0eVwiKTtpZigwIT09cil7dmFyIGE9dC5jb250ZXh0LG49YS5nbCxzPXQudHJhbnNmb3JtLGw9cy50aWxlU2l6ZSxjPWkucGFpbnQuZ2V0KFwiYmFja2dyb3VuZC1wYXR0ZXJuXCIpO2lmKCF0LmlzUGF0dGVybk1pc3NpbmcoYykpe3ZhciB1PWN8fDEhPT1vLmF8fDEhPT1yP1widHJhbnNsdWNlbnRcIjpcIm9wYXF1ZVwiO2lmKHQucmVuZGVyUGFzcz09PXUpe3ZhciBoPUl0LmRpc2FibGVkLHA9dC5kZXB0aE1vZGVGb3JTdWJsYXllcigwLFwib3BhcXVlXCI9PT11P1R0LlJlYWRXcml0ZTpUdC5SZWFkT25seSksZD10LmNvbG9yTW9kZUZvclJlbmRlclBhc3MoKSxfPXQudXNlUHJvZ3JhbShjP1wiYmFja2dyb3VuZFBhdHRlcm5cIjpcImJhY2tncm91bmRcIiksZj1zLmNvdmVyaW5nVGlsZXMoe3RpbGVTaXplOmx9KTtjJiYoYS5hY3RpdmVUZXh0dXJlLnNldChuLlRFWFRVUkUwKSx0LmltYWdlTWFuYWdlci5iaW5kKHQuY29udGV4dCkpO2Zvcih2YXIgbT1pLmdldENyb3NzZmFkZVBhcmFtZXRlcnMoKSxnPTAsdj1mO2c8di5sZW5ndGg7Zys9MSl7dmFyIHk9dltnXSx4PXQudHJhbnNmb3JtLmNhbGN1bGF0ZVBvc01hdHJpeCh5LnRvVW53cmFwcGVkKCkpLGI9Yz9aaSh4LHIsdCxjLHt0aWxlSUQ6eSx0aWxlU2l6ZTpsfSxtKTpOaSh4LHIsbyk7Xy5kcmF3KGEsbi5UUklBTkdMRVMscCxoLGQsU3QuZGlzYWJsZWQsYixpLmlkLHQudGlsZUV4dGVudEJ1ZmZlcix0LnF1YWRUcmlhbmdsZUluZGV4QnVmZmVyLHQudGlsZUV4dGVudFNlZ21lbnRzKTt9fX19fSxkZWJ1ZzpmdW5jdGlvbih0LGUsaSl7Zm9yKHZhciBvPTA7bzxpLmxlbmd0aDtvKyspaW8odCxlLGlbb10pO30sY3VzdG9tOmZ1bmN0aW9uKHQsZSxpKXt2YXIgbz10LmNvbnRleHQscj1pLmltcGxlbWVudGF0aW9uO2lmKFwib2Zmc2NyZWVuXCI9PT10LnJlbmRlclBhc3Mpe3ZhciBhPXIucHJlcmVuZGVyO2EmJih0LnNldEN1c3RvbUxheWVyRGVmYXVsdHMoKSxvLnNldENvbG9yTW9kZSh0LmNvbG9yTW9kZUZvclJlbmRlclBhc3MoKSksYS5jYWxsKHIsby5nbCx0LnRyYW5zZm9ybS5jdXN0b21MYXllck1hdHJpeCgpKSxvLnNldERpcnR5KCksdC5zZXRCYXNlU3RhdGUoKSk7fWVsc2UgaWYoXCJ0cmFuc2x1Y2VudFwiPT09dC5yZW5kZXJQYXNzKXt0LnNldEN1c3RvbUxheWVyRGVmYXVsdHMoKSxvLnNldENvbG9yTW9kZSh0LmNvbG9yTW9kZUZvclJlbmRlclBhc3MoKSksby5zZXRTdGVuY2lsTW9kZShJdC5kaXNhYmxlZCk7dmFyIG49XCIzZFwiPT09ci5yZW5kZXJpbmdNb2RlP25ldyBUdCh0LmNvbnRleHQuZ2wuTEVRVUFMLFR0LlJlYWRXcml0ZSx0LmRlcHRoUmFuZ2VGb3IzRCk6dC5kZXB0aE1vZGVGb3JTdWJsYXllcigwLFR0LlJlYWRPbmx5KTtvLnNldERlcHRoTW9kZShuKSxyLnJlbmRlcihvLmdsLHQudHJhbnNmb3JtLmN1c3RvbUxheWVyTWF0cml4KCkpLG8uc2V0RGlydHkoKSx0LnNldEJhc2VTdGF0ZSgpLG8uYmluZEZyYW1lYnVmZmVyLnNldChudWxsKTt9fX0sYW89ZnVuY3Rpb24oZSxpKXt0aGlzLmNvbnRleHQ9bmV3IFB0KGUpLHRoaXMudHJhbnNmb3JtPWksdGhpcy5fdGlsZVRleHR1cmVzPXt9LHRoaXMuc2V0dXAoKSx0aGlzLm51bVN1YmxheWVycz16dC5tYXhVbmRlcnpvb21pbmcrenQubWF4T3Zlcnpvb21pbmcrMSx0aGlzLmRlcHRoRXBzaWxvbj0xL01hdGgucG93KDIsMTYpLHRoaXMuZGVwdGhSYm9OZWVkc0NsZWFyPSEwLHRoaXMuZW1wdHlQcm9ncmFtQ29uZmlndXJhdGlvbj1uZXcgdC5Qcm9ncmFtQ29uZmlndXJhdGlvbix0aGlzLmNyb3NzVGlsZVN5bWJvbEluZGV4PW5ldyBNZTt9O2Z1bmN0aW9uIG5vKHQsZSl7aWYodC55PmUueSl7dmFyIGk9dDt0PWUsZT1pO31yZXR1cm4ge3gwOnQueCx5MDp0LnkseDE6ZS54LHkxOmUueSxkeDplLngtdC54LGR5OmUueS10Lnl9fWZ1bmN0aW9uIHNvKHQsZSxpLG8scil7dmFyIGE9TWF0aC5tYXgoaSxNYXRoLmZsb29yKGUueTApKSxuPU1hdGgubWluKG8sTWF0aC5jZWlsKGUueTEpKTtpZih0LngwPT09ZS54MCYmdC55MD09PWUueTA/dC54MCtlLmR5L3QuZHkqdC5keDxlLngxOnQueDEtZS5keS90LmR5KnQuZHg8ZS54MCl7dmFyIHM9dDt0PWUsZT1zO31mb3IodmFyIGw9dC5keC90LmR5LGM9ZS5keC9lLmR5LHU9dC5keD4wLGg9ZS5keDwwLHA9YTtwPG47cCsrKXt2YXIgZD1sKk1hdGgubWF4KDAsTWF0aC5taW4odC5keSxwK3UtdC55MCkpK3QueDAsXz1jKk1hdGgubWF4KDAsTWF0aC5taW4oZS5keSxwK2gtZS55MCkpK2UueDA7cihNYXRoLmZsb29yKF8pLE1hdGguY2VpbChkKSxwKTt9fWZ1bmN0aW9uIGxvKHQsZSxpLG8scixhKXt2YXIgbixzPW5vKHQsZSksbD1ubyhlLGkpLGM9bm8oaSx0KTtzLmR5PmwuZHkmJihuPXMscz1sLGw9bikscy5keT5jLmR5JiYobj1zLHM9YyxjPW4pLGwuZHk+Yy5keSYmKG49bCxsPWMsYz1uKSxzLmR5JiZzbyhjLHMsbyxyLGEpLGwuZHkmJnNvKGMsbCxvLHIsYSk7fWFvLnByb3RvdHlwZS5yZXNpemU9ZnVuY3Rpb24oZSxpKXt2YXIgbz10aGlzLmNvbnRleHQuZ2w7aWYodGhpcy53aWR0aD1lKnQuYnJvd3Nlci5kZXZpY2VQaXhlbFJhdGlvLHRoaXMuaGVpZ2h0PWkqdC5icm93c2VyLmRldmljZVBpeGVsUmF0aW8sdGhpcy5jb250ZXh0LnZpZXdwb3J0LnNldChbMCwwLHRoaXMud2lkdGgsdGhpcy5oZWlnaHRdKSx0aGlzLnN0eWxlKWZvcih2YXIgcj0wLGE9dGhpcy5zdHlsZS5fb3JkZXI7cjxhLmxlbmd0aDtyKz0xKXt2YXIgbj1hW3JdO3RoaXMuc3R5bGUuX2xheWVyc1tuXS5yZXNpemUoKTt9dGhpcy5kZXB0aFJibyYmKG8uZGVsZXRlUmVuZGVyYnVmZmVyKHRoaXMuZGVwdGhSYm8pLHRoaXMuZGVwdGhSYm89bnVsbCk7fSxhby5wcm90b3R5cGUuc2V0dXA9ZnVuY3Rpb24oKXt2YXIgZT10aGlzLmNvbnRleHQsaT1uZXcgdC5TdHJ1Y3RBcnJheUxheW91dDJpNDtpLmVtcGxhY2VCYWNrKDAsMCksaS5lbXBsYWNlQmFjayh0LkVYVEVOVCwwKSxpLmVtcGxhY2VCYWNrKDAsdC5FWFRFTlQpLGkuZW1wbGFjZUJhY2sodC5FWFRFTlQsdC5FWFRFTlQpLHRoaXMudGlsZUV4dGVudEJ1ZmZlcj1lLmNyZWF0ZVZlcnRleEJ1ZmZlcihpLE9lLm1lbWJlcnMpLHRoaXMudGlsZUV4dGVudFNlZ21lbnRzPXQuU2VnbWVudFZlY3Rvci5zaW1wbGVTZWdtZW50KDAsMCw0LDIpO3ZhciBvPW5ldyB0LlN0cnVjdEFycmF5TGF5b3V0Mmk0O28uZW1wbGFjZUJhY2soMCwwKSxvLmVtcGxhY2VCYWNrKHQuRVhURU5ULDApLG8uZW1wbGFjZUJhY2soMCx0LkVYVEVOVCksby5lbXBsYWNlQmFjayh0LkVYVEVOVCx0LkVYVEVOVCksdGhpcy5kZWJ1Z0J1ZmZlcj1lLmNyZWF0ZVZlcnRleEJ1ZmZlcihvLE9lLm1lbWJlcnMpLHRoaXMuZGVidWdTZWdtZW50cz10LlNlZ21lbnRWZWN0b3Iuc2ltcGxlU2VnbWVudCgwLDAsNCw1KTt2YXIgcj1uZXcgdC5TdHJ1Y3RBcnJheUxheW91dDRpODtyLmVtcGxhY2VCYWNrKDAsMCwwLDApLHIuZW1wbGFjZUJhY2sodC5FWFRFTlQsMCx0LkVYVEVOVCwwKSxyLmVtcGxhY2VCYWNrKDAsdC5FWFRFTlQsMCx0LkVYVEVOVCksci5lbXBsYWNlQmFjayh0LkVYVEVOVCx0LkVYVEVOVCx0LkVYVEVOVCx0LkVYVEVOVCksdGhpcy5yYXN0ZXJCb3VuZHNCdWZmZXI9ZS5jcmVhdGVWZXJ0ZXhCdWZmZXIocix0LnJhc3RlckJvdW5kc0F0dHJpYnV0ZXMubWVtYmVycyksdGhpcy5yYXN0ZXJCb3VuZHNTZWdtZW50cz10LlNlZ21lbnRWZWN0b3Iuc2ltcGxlU2VnbWVudCgwLDAsNCwyKTt2YXIgYT1uZXcgdC5TdHJ1Y3RBcnJheUxheW91dDJpNDthLmVtcGxhY2VCYWNrKDAsMCksYS5lbXBsYWNlQmFjaygxLDApLGEuZW1wbGFjZUJhY2soMCwxKSxhLmVtcGxhY2VCYWNrKDEsMSksdGhpcy52aWV3cG9ydEJ1ZmZlcj1lLmNyZWF0ZVZlcnRleEJ1ZmZlcihhLE9lLm1lbWJlcnMpLHRoaXMudmlld3BvcnRTZWdtZW50cz10LlNlZ21lbnRWZWN0b3Iuc2ltcGxlU2VnbWVudCgwLDAsNCwyKTt2YXIgbj1uZXcgdC5TdHJ1Y3RBcnJheUxheW91dDF1aTI7bi5lbXBsYWNlQmFjaygwKSxuLmVtcGxhY2VCYWNrKDEpLG4uZW1wbGFjZUJhY2soMyksbi5lbXBsYWNlQmFjaygyKSxuLmVtcGxhY2VCYWNrKDApLHRoaXMudGlsZUJvcmRlckluZGV4QnVmZmVyPWUuY3JlYXRlSW5kZXhCdWZmZXIobik7dmFyIHM9bmV3IHQuU3RydWN0QXJyYXlMYXlvdXQzdWk2O3MuZW1wbGFjZUJhY2soMCwxLDIpLHMuZW1wbGFjZUJhY2soMiwxLDMpLHRoaXMucXVhZFRyaWFuZ2xlSW5kZXhCdWZmZXI9ZS5jcmVhdGVJbmRleEJ1ZmZlcihzKTt2YXIgbD10aGlzLmNvbnRleHQuZ2w7dGhpcy5zdGVuY2lsQ2xlYXJNb2RlPW5ldyBJdCh7ZnVuYzpsLkFMV0FZUyxtYXNrOjB9LDAsMjU1LGwuWkVSTyxsLlpFUk8sbC5aRVJPKTt9LGFvLnByb3RvdHlwZS5jbGVhclN0ZW5jaWw9ZnVuY3Rpb24oKXt2YXIgZT10aGlzLmNvbnRleHQsaT1lLmdsO3RoaXMubmV4dFN0ZW5jaWxJRD0xLHRoaXMuY3VycmVudFN0ZW5jaWxTb3VyY2U9dm9pZCAwO3ZhciBvPXQuY3JlYXRlKCk7dC5vcnRobyhvLDAsdGhpcy53aWR0aCx0aGlzLmhlaWdodCwwLDAsMSksdC5zY2FsZShvLG8sW2kuZHJhd2luZ0J1ZmZlcldpZHRoLGkuZHJhd2luZ0J1ZmZlckhlaWdodCwwXSksdGhpcy51c2VQcm9ncmFtKFwiY2xpcHBpbmdNYXNrXCIpLmRyYXcoZSxpLlRSSUFOR0xFUyxUdC5kaXNhYmxlZCx0aGlzLnN0ZW5jaWxDbGVhck1vZGUsQ3QuZGlzYWJsZWQsU3QuZGlzYWJsZWQsVGkobyksXCIkY2xpcHBpbmdcIix0aGlzLnZpZXdwb3J0QnVmZmVyLHRoaXMucXVhZFRyaWFuZ2xlSW5kZXhCdWZmZXIsdGhpcy52aWV3cG9ydFNlZ21lbnRzKTt9LGFvLnByb3RvdHlwZS5fcmVuZGVyVGlsZUNsaXBwaW5nTWFza3M9ZnVuY3Rpb24odCxlKXtpZih0aGlzLmN1cnJlbnRTdGVuY2lsU291cmNlIT09dC5zb3VyY2UmJnQuaXNUaWxlQ2xpcHBlZCgpJiZlJiZlLmxlbmd0aCl7dGhpcy5jdXJyZW50U3RlbmNpbFNvdXJjZT10LnNvdXJjZTt2YXIgaT10aGlzLmNvbnRleHQsbz1pLmdsO3RoaXMubmV4dFN0ZW5jaWxJRCtlLmxlbmd0aD4yNTYmJnRoaXMuY2xlYXJTdGVuY2lsKCksaS5zZXRDb2xvck1vZGUoQ3QuZGlzYWJsZWQpLGkuc2V0RGVwdGhNb2RlKFR0LmRpc2FibGVkKTt2YXIgcj10aGlzLnVzZVByb2dyYW0oXCJjbGlwcGluZ01hc2tcIik7dGhpcy5fdGlsZUNsaXBwaW5nTWFza0lEcz17fTtmb3IodmFyIGE9MCxuPWU7YTxuLmxlbmd0aDthKz0xKXt2YXIgcz1uW2FdLGw9dGhpcy5fdGlsZUNsaXBwaW5nTWFza0lEc1tzLmtleV09dGhpcy5uZXh0U3RlbmNpbElEKys7ci5kcmF3KGksby5UUklBTkdMRVMsVHQuZGlzYWJsZWQsbmV3IEl0KHtmdW5jOm8uQUxXQVlTLG1hc2s6MH0sbCwyNTUsby5LRUVQLG8uS0VFUCxvLlJFUExBQ0UpLEN0LmRpc2FibGVkLFN0LmRpc2FibGVkLFRpKHMucG9zTWF0cml4KSxcIiRjbGlwcGluZ1wiLHRoaXMudGlsZUV4dGVudEJ1ZmZlcix0aGlzLnF1YWRUcmlhbmdsZUluZGV4QnVmZmVyLHRoaXMudGlsZUV4dGVudFNlZ21lbnRzKTt9fX0sYW8ucHJvdG90eXBlLnN0ZW5jaWxNb2RlRm9yM0Q9ZnVuY3Rpb24oKXt0aGlzLm5leHRTdGVuY2lsSUQrMT4yNTYmJnRoaXMuY2xlYXJTdGVuY2lsKCk7dmFyIHQ9dGhpcy5uZXh0U3RlbmNpbElEKyssZT10aGlzLmNvbnRleHQuZ2w7cmV0dXJuIG5ldyBJdCh7ZnVuYzplLk5PVEVRVUFMLG1hc2s6MjU1fSx0LDI1NSxlLktFRVAsZS5LRUVQLGUuUkVQTEFDRSl9LGFvLnByb3RvdHlwZS5zdGVuY2lsTW9kZUZvckNsaXBwaW5nPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuY29udGV4dC5nbDtyZXR1cm4gbmV3IEl0KHtmdW5jOmUuRVFVQUwsbWFzazoyNTV9LHRoaXMuX3RpbGVDbGlwcGluZ01hc2tJRHNbdC5rZXldLDAsZS5LRUVQLGUuS0VFUCxlLlJFUExBQ0UpfSxhby5wcm90b3R5cGUuY29sb3JNb2RlRm9yUmVuZGVyUGFzcz1mdW5jdGlvbigpe3ZhciBlPXRoaXMuY29udGV4dC5nbDtpZih0aGlzLl9zaG93T3ZlcmRyYXdJbnNwZWN0b3Ipe3JldHVybiBuZXcgQ3QoW2UuQ09OU1RBTlRfQ09MT1IsZS5PTkVdLG5ldyB0LkNvbG9yKDEvOCwxLzgsMS84LDApLFshMCwhMCwhMCwhMF0pfXJldHVybiBcIm9wYXF1ZVwiPT09dGhpcy5yZW5kZXJQYXNzP0N0LnVuYmxlbmRlZDpDdC5hbHBoYUJsZW5kZWR9LGFvLnByb3RvdHlwZS5kZXB0aE1vZGVGb3JTdWJsYXllcj1mdW5jdGlvbih0LGUsaSl7aWYoIXRoaXMub3BhcXVlUGFzc0VuYWJsZWRGb3JMYXllcigpKXJldHVybiBUdC5kaXNhYmxlZDt2YXIgbz0xLSgoMSt0aGlzLmN1cnJlbnRMYXllcikqdGhpcy5udW1TdWJsYXllcnMrdCkqdGhpcy5kZXB0aEVwc2lsb247cmV0dXJuIG5ldyBUdChpfHx0aGlzLmNvbnRleHQuZ2wuTEVRVUFMLGUsW28sb10pfSxhby5wcm90b3R5cGUub3BhcXVlUGFzc0VuYWJsZWRGb3JMYXllcj1mdW5jdGlvbigpe3JldHVybiB0aGlzLmN1cnJlbnRMYXllcjx0aGlzLm9wYXF1ZVBhc3NDdXRvZmZ9LGFvLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oZSxpKXt0aGlzLnN0eWxlPWUsdGhpcy5vcHRpb25zPWksdGhpcy5saW5lQXRsYXM9ZS5saW5lQXRsYXMsdGhpcy5pbWFnZU1hbmFnZXI9ZS5pbWFnZU1hbmFnZXIsdGhpcy5nbHlwaE1hbmFnZXI9ZS5nbHlwaE1hbmFnZXIsdGhpcy5zeW1ib2xGYWRlQ2hhbmdlPWUucGxhY2VtZW50LnN5bWJvbEZhZGVDaGFuZ2UodC5icm93c2VyLm5vdygpKSx0aGlzLmltYWdlTWFuYWdlci5iZWdpbkZyYW1lKCk7dmFyIG89dGhpcy5zdHlsZS5fb3JkZXIscj10aGlzLnN0eWxlLnNvdXJjZUNhY2hlcztmb3IodmFyIGEgaW4gcil7dmFyIG49clthXTtuLnVzZWQmJm4ucHJlcGFyZSh0aGlzLmNvbnRleHQpO312YXIgcz17fSxsPXt9LGM9e307Zm9yKHZhciB1IGluIHIpe3ZhciBoPXJbdV07c1t1XT1oLmdldFZpc2libGVDb29yZGluYXRlcygpLGxbdV09c1t1XS5zbGljZSgpLnJldmVyc2UoKSxjW3VdPWguZ2V0VmlzaWJsZUNvb3JkaW5hdGVzKCEwKS5yZXZlcnNlKCk7fWZvcih2YXIgcCBpbiByKXt2YXIgZD1yW3BdLF89ZC5nZXRTb3VyY2UoKTtpZihcInJhc3RlclwiPT09Xy50eXBlfHxcInJhc3Rlci1kZW1cIj09PV8udHlwZSl7Zm9yKHZhciBmPVtdLG09MCxnPXNbcF07bTxnLmxlbmd0aDttKz0xKXt2YXIgdj1nW21dO2YucHVzaChkLmdldFRpbGUodikpO31xaShmLHRoaXMuY29udGV4dCk7fX10aGlzLm9wYXF1ZVBhc3NDdXRvZmY9MS8wO2Zvcih2YXIgeT0wO3k8by5sZW5ndGg7eSsrKXt2YXIgeD1vW3ldO2lmKHRoaXMuc3R5bGUuX2xheWVyc1t4XS5pczNEKCkpe3RoaXMub3BhcXVlUGFzc0N1dG9mZj15O2JyZWFrfX10aGlzLnJlbmRlclBhc3M9XCJvZmZzY3JlZW5cIix0aGlzLmRlcHRoUmJvTmVlZHNDbGVhcj0hMDtmb3IodmFyIGI9MCx3PW87Yjx3Lmxlbmd0aDtiKz0xKXt2YXIgRT13W2JdLFQ9dGhpcy5zdHlsZS5fbGF5ZXJzW0VdO2lmKFQuaGFzT2Zmc2NyZWVuUGFzcygpJiYhVC5pc0hpZGRlbih0aGlzLnRyYW5zZm9ybS56b29tKSl7dmFyIEk9bFtULnNvdXJjZV07KFwiY3VzdG9tXCI9PT1ULnR5cGV8fEkubGVuZ3RoKSYmdGhpcy5yZW5kZXJMYXllcih0aGlzLHJbVC5zb3VyY2VdLFQsSSk7fX1mb3IodGhpcy5jb250ZXh0LmJpbmRGcmFtZWJ1ZmZlci5zZXQobnVsbCksdGhpcy5jb250ZXh0LmNsZWFyKHtjb2xvcjppLnNob3dPdmVyZHJhd0luc3BlY3Rvcj90LkNvbG9yLmJsYWNrOnQuQ29sb3IudHJhbnNwYXJlbnQsZGVwdGg6MX0pLHRoaXMuY2xlYXJTdGVuY2lsKCksdGhpcy5fc2hvd092ZXJkcmF3SW5zcGVjdG9yPWkuc2hvd092ZXJkcmF3SW5zcGVjdG9yLHRoaXMuZGVwdGhSYW5nZUZvcjNEPVswLDEtKGUuX29yZGVyLmxlbmd0aCsyKSp0aGlzLm51bVN1YmxheWVycyp0aGlzLmRlcHRoRXBzaWxvbl0sdGhpcy5yZW5kZXJQYXNzPVwib3BhcXVlXCIsdGhpcy5jdXJyZW50TGF5ZXI9by5sZW5ndGgtMTt0aGlzLmN1cnJlbnRMYXllcj49MDt0aGlzLmN1cnJlbnRMYXllci0tKXt2YXIgQz10aGlzLnN0eWxlLl9sYXllcnNbb1t0aGlzLmN1cnJlbnRMYXllcl1dLFM9cltDLnNvdXJjZV0sUD1zW0Muc291cmNlXTt0aGlzLl9yZW5kZXJUaWxlQ2xpcHBpbmdNYXNrcyhDLFApLHRoaXMucmVuZGVyTGF5ZXIodGhpcyxTLEMsUCk7fWZvcih0aGlzLnJlbmRlclBhc3M9XCJ0cmFuc2x1Y2VudFwiLHRoaXMuY3VycmVudExheWVyPTA7dGhpcy5jdXJyZW50TGF5ZXI8by5sZW5ndGg7dGhpcy5jdXJyZW50TGF5ZXIrKyl7dmFyIHo9dGhpcy5zdHlsZS5fbGF5ZXJzW29bdGhpcy5jdXJyZW50TGF5ZXJdXSxMPXJbei5zb3VyY2VdLEQ9KFwic3ltYm9sXCI9PT16LnR5cGU/YzpsKVt6LnNvdXJjZV07dGhpcy5fcmVuZGVyVGlsZUNsaXBwaW5nTWFza3MoeixzW3ouc291cmNlXSksdGhpcy5yZW5kZXJMYXllcih0aGlzLEwseixEKTt9aWYodGhpcy5vcHRpb25zLnNob3dUaWxlQm91bmRhcmllcylmb3IodmFyIE0gaW4gcil7cm8uZGVidWcodGhpcyxyW01dLHNbTV0pO2JyZWFrfXRoaXMuY29udGV4dC5zZXREZWZhdWx0KCk7fSxhby5wcm90b3R5cGUuc2V0dXBPZmZzY3JlZW5EZXB0aFJlbmRlcmJ1ZmZlcj1mdW5jdGlvbigpe3ZhciB0PXRoaXMuY29udGV4dDt0aGlzLmRlcHRoUmJvfHwodGhpcy5kZXB0aFJibz10LmNyZWF0ZVJlbmRlcmJ1ZmZlcih0LmdsLkRFUFRIX0NPTVBPTkVOVDE2LHRoaXMud2lkdGgsdGhpcy5oZWlnaHQpKTt9LGFvLnByb3RvdHlwZS5yZW5kZXJMYXllcj1mdW5jdGlvbih0LGUsaSxvKXtpLmlzSGlkZGVuKHRoaXMudHJhbnNmb3JtLnpvb20pfHwoXCJiYWNrZ3JvdW5kXCI9PT1pLnR5cGV8fFwiY3VzdG9tXCI9PT1pLnR5cGV8fG8ubGVuZ3RoKSYmKHRoaXMuaWQ9aS5pZCxyb1tpLnR5cGVdKHQsZSxpLG8sdGhpcy5zdHlsZS5wbGFjZW1lbnQudmFyaWFibGVPZmZzZXRzKSk7fSxhby5wcm90b3R5cGUudHJhbnNsYXRlUG9zTWF0cml4PWZ1bmN0aW9uKGUsaSxvLHIsYSl7aWYoIW9bMF0mJiFvWzFdKXJldHVybiBlO3ZhciBuPWE/XCJtYXBcIj09PXI/dGhpcy50cmFuc2Zvcm0uYW5nbGU6MDpcInZpZXdwb3J0XCI9PT1yPy10aGlzLnRyYW5zZm9ybS5hbmdsZTowO2lmKG4pe3ZhciBzPU1hdGguc2luKG4pLGw9TWF0aC5jb3Mobik7bz1bb1swXSpsLW9bMV0qcyxvWzBdKnMrb1sxXSpsXTt9dmFyIGM9W2E/b1swXTpjZShpLG9bMF0sdGhpcy50cmFuc2Zvcm0uem9vbSksYT9vWzFdOmNlKGksb1sxXSx0aGlzLnRyYW5zZm9ybS56b29tKSwwXSx1PW5ldyBGbG9hdDMyQXJyYXkoMTYpO3JldHVybiB0LnRyYW5zbGF0ZSh1LGUsYyksdX0sYW8ucHJvdG90eXBlLnNhdmVUaWxlVGV4dHVyZT1mdW5jdGlvbih0KXt2YXIgZT10aGlzLl90aWxlVGV4dHVyZXNbdC5zaXplWzBdXTtlP2UucHVzaCh0KTp0aGlzLl90aWxlVGV4dHVyZXNbdC5zaXplWzBdXT1bdF07fSxhby5wcm90b3R5cGUuZ2V0VGlsZVRleHR1cmU9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5fdGlsZVRleHR1cmVzW3RdO3JldHVybiBlJiZlLmxlbmd0aD4wP2UucG9wKCk6bnVsbH0sYW8ucHJvdG90eXBlLmlzUGF0dGVybk1pc3Npbmc9ZnVuY3Rpb24odCl7aWYoIXQpcmV0dXJuICExO3ZhciBlPXRoaXMuaW1hZ2VNYW5hZ2VyLmdldFBhdHRlcm4odC5mcm9tKSxpPXRoaXMuaW1hZ2VNYW5hZ2VyLmdldFBhdHRlcm4odC50byk7cmV0dXJuICFlfHwhaX0sYW8ucHJvdG90eXBlLnVzZVByb2dyYW09ZnVuY3Rpb24odCxlKXt2b2lkIDA9PT1lJiYoZT10aGlzLmVtcHR5UHJvZ3JhbUNvbmZpZ3VyYXRpb24pLHRoaXMuY2FjaGU9dGhpcy5jYWNoZXx8e307dmFyIGk9XCJcIit0KyhlLmNhY2hlS2V5fHxcIlwiKSsodGhpcy5fc2hvd092ZXJkcmF3SW5zcGVjdG9yP1wiL292ZXJkcmF3XCI6XCJcIik7cmV0dXJuIHRoaXMuY2FjaGVbaV18fCh0aGlzLmNhY2hlW2ldPW5ldyBwaSh0aGlzLmNvbnRleHQsdWlbdF0sZSxqaVt0XSx0aGlzLl9zaG93T3ZlcmRyYXdJbnNwZWN0b3IpKSx0aGlzLmNhY2hlW2ldfSxhby5wcm90b3R5cGUuc2V0Q3VzdG9tTGF5ZXJEZWZhdWx0cz1mdW5jdGlvbigpe3RoaXMuY29udGV4dC51bmJpbmRWQU8oKSx0aGlzLmNvbnRleHQuY3VsbEZhY2Uuc2V0RGVmYXVsdCgpLHRoaXMuY29udGV4dC5hY3RpdmVUZXh0dXJlLnNldERlZmF1bHQoKSx0aGlzLmNvbnRleHQucGl4ZWxTdG9yZVVucGFjay5zZXREZWZhdWx0KCksdGhpcy5jb250ZXh0LnBpeGVsU3RvcmVVbnBhY2tQcmVtdWx0aXBseUFscGhhLnNldERlZmF1bHQoKSx0aGlzLmNvbnRleHQucGl4ZWxTdG9yZVVucGFja0ZsaXBZLnNldERlZmF1bHQoKTt9LGFvLnByb3RvdHlwZS5zZXRCYXNlU3RhdGU9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmNvbnRleHQuZ2w7dGhpcy5jb250ZXh0LmN1bGxGYWNlLnNldCghMSksdGhpcy5jb250ZXh0LnZpZXdwb3J0LnNldChbMCwwLHRoaXMud2lkdGgsdGhpcy5oZWlnaHRdKSx0aGlzLmNvbnRleHQuYmxlbmRFcXVhdGlvbi5zZXQodC5GVU5DX0FERCk7fTt2YXIgY289ZnVuY3Rpb24oZSxpLG8pe3RoaXMudGlsZVNpemU9NTEyLHRoaXMubWF4VmFsaWRMYXRpdHVkZT04NS4wNTExMjksdGhpcy5fcmVuZGVyV29ybGRDb3BpZXM9dm9pZCAwPT09b3x8byx0aGlzLl9taW5ab29tPWV8fDAsdGhpcy5fbWF4Wm9vbT1pfHwyMix0aGlzLnNldE1heEJvdW5kcygpLHRoaXMud2lkdGg9MCx0aGlzLmhlaWdodD0wLHRoaXMuX2NlbnRlcj1uZXcgdC5MbmdMYXQoMCwwKSx0aGlzLnpvb209MCx0aGlzLmFuZ2xlPTAsdGhpcy5fZm92PS42NDM1MDExMDg3OTMyODQ0LHRoaXMuX3BpdGNoPTAsdGhpcy5fdW5tb2RpZmllZD0hMCx0aGlzLl9wb3NNYXRyaXhDYWNoZT17fSx0aGlzLl9hbGlnbmVkUG9zTWF0cml4Q2FjaGU9e307fSx1bz17bWluWm9vbTp7Y29uZmlndXJhYmxlOiEwfSxtYXhab29tOntjb25maWd1cmFibGU6ITB9LHJlbmRlcldvcmxkQ29waWVzOntjb25maWd1cmFibGU6ITB9LHdvcmxkU2l6ZTp7Y29uZmlndXJhYmxlOiEwfSxjZW50ZXJQb2ludDp7Y29uZmlndXJhYmxlOiEwfSxzaXplOntjb25maWd1cmFibGU6ITB9LGJlYXJpbmc6e2NvbmZpZ3VyYWJsZTohMH0scGl0Y2g6e2NvbmZpZ3VyYWJsZTohMH0sZm92Ontjb25maWd1cmFibGU6ITB9LHpvb206e2NvbmZpZ3VyYWJsZTohMH0sY2VudGVyOntjb25maWd1cmFibGU6ITB9LHVubW9kaWZpZWQ6e2NvbmZpZ3VyYWJsZTohMH0scG9pbnQ6e2NvbmZpZ3VyYWJsZTohMH19O2NvLnByb3RvdHlwZS5jbG9uZT1mdW5jdGlvbigpe3ZhciB0PW5ldyBjbyh0aGlzLl9taW5ab29tLHRoaXMuX21heFpvb20sdGhpcy5fcmVuZGVyV29ybGRDb3BpZXMpO3JldHVybiB0LnRpbGVTaXplPXRoaXMudGlsZVNpemUsdC5sYXRSYW5nZT10aGlzLmxhdFJhbmdlLHQud2lkdGg9dGhpcy53aWR0aCx0LmhlaWdodD10aGlzLmhlaWdodCx0Ll9jZW50ZXI9dGhpcy5fY2VudGVyLHQuem9vbT10aGlzLnpvb20sdC5hbmdsZT10aGlzLmFuZ2xlLHQuX2Zvdj10aGlzLl9mb3YsdC5fcGl0Y2g9dGhpcy5fcGl0Y2gsdC5fdW5tb2RpZmllZD10aGlzLl91bm1vZGlmaWVkLHQuX2NhbGNNYXRyaWNlcygpLHR9LHVvLm1pblpvb20uZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX21pblpvb219LHVvLm1pblpvb20uc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX21pblpvb20hPT10JiYodGhpcy5fbWluWm9vbT10LHRoaXMuem9vbT1NYXRoLm1heCh0aGlzLnpvb20sdCkpO30sdW8ubWF4Wm9vbS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fbWF4Wm9vbX0sdW8ubWF4Wm9vbS5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fbWF4Wm9vbSE9PXQmJih0aGlzLl9tYXhab29tPXQsdGhpcy56b29tPU1hdGgubWluKHRoaXMuem9vbSx0KSk7fSx1by5yZW5kZXJXb3JsZENvcGllcy5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fcmVuZGVyV29ybGRDb3BpZXN9LHVvLnJlbmRlcldvcmxkQ29waWVzLnNldD1mdW5jdGlvbih0KXt2b2lkIDA9PT10P3Q9ITA6bnVsbD09PXQmJih0PSExKSx0aGlzLl9yZW5kZXJXb3JsZENvcGllcz10O30sdW8ud29ybGRTaXplLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLnRpbGVTaXplKnRoaXMuc2NhbGV9LHVvLmNlbnRlclBvaW50LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNpemUuX2RpdigyKX0sdW8uc2l6ZS5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IHQuUG9pbnQodGhpcy53aWR0aCx0aGlzLmhlaWdodCl9LHVvLmJlYXJpbmcuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIC10aGlzLmFuZ2xlL01hdGguUEkqMTgwfSx1by5iZWFyaW5nLnNldD1mdW5jdGlvbihlKXt2YXIgaT0tdC53cmFwKGUsLTE4MCwxODApKk1hdGguUEkvMTgwO3RoaXMuYW5nbGUhPT1pJiYodGhpcy5fdW5tb2RpZmllZD0hMSx0aGlzLmFuZ2xlPWksdGhpcy5fY2FsY01hdHJpY2VzKCksdGhpcy5yb3RhdGlvbk1hdHJpeD10LmNyZWF0ZSQyKCksdC5yb3RhdGUodGhpcy5yb3RhdGlvbk1hdHJpeCx0aGlzLnJvdGF0aW9uTWF0cml4LHRoaXMuYW5nbGUpKTt9LHVvLnBpdGNoLmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9waXRjaC9NYXRoLlBJKjE4MH0sdW8ucGl0Y2guc2V0PWZ1bmN0aW9uKGUpe3ZhciBpPXQuY2xhbXAoZSwwLDYwKS8xODAqTWF0aC5QSTt0aGlzLl9waXRjaCE9PWkmJih0aGlzLl91bm1vZGlmaWVkPSExLHRoaXMuX3BpdGNoPWksdGhpcy5fY2FsY01hdHJpY2VzKCkpO30sdW8uZm92LmdldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9mb3YvTWF0aC5QSSoxODB9LHVvLmZvdi5zZXQ9ZnVuY3Rpb24odCl7dD1NYXRoLm1heCguMDEsTWF0aC5taW4oNjAsdCkpLHRoaXMuX2ZvdiE9PXQmJih0aGlzLl91bm1vZGlmaWVkPSExLHRoaXMuX2Zvdj10LzE4MCpNYXRoLlBJLHRoaXMuX2NhbGNNYXRyaWNlcygpKTt9LHVvLnpvb20uZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3pvb219LHVvLnpvb20uc2V0PWZ1bmN0aW9uKHQpe3ZhciBlPU1hdGgubWluKE1hdGgubWF4KHQsdGhpcy5taW5ab29tKSx0aGlzLm1heFpvb20pO3RoaXMuX3pvb20hPT1lJiYodGhpcy5fdW5tb2RpZmllZD0hMSx0aGlzLl96b29tPWUsdGhpcy5zY2FsZT10aGlzLnpvb21TY2FsZShlKSx0aGlzLnRpbGVab29tPU1hdGguZmxvb3IoZSksdGhpcy56b29tRnJhY3Rpb249ZS10aGlzLnRpbGVab29tLHRoaXMuX2NvbnN0cmFpbigpLHRoaXMuX2NhbGNNYXRyaWNlcygpKTt9LHVvLmNlbnRlci5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fY2VudGVyfSx1by5jZW50ZXIuc2V0PWZ1bmN0aW9uKHQpe3QubGF0PT09dGhpcy5fY2VudGVyLmxhdCYmdC5sbmc9PT10aGlzLl9jZW50ZXIubG5nfHwodGhpcy5fdW5tb2RpZmllZD0hMSx0aGlzLl9jZW50ZXI9dCx0aGlzLl9jb25zdHJhaW4oKSx0aGlzLl9jYWxjTWF0cmljZXMoKSk7fSxjby5wcm90b3R5cGUuY292ZXJpbmdab29tTGV2ZWw9ZnVuY3Rpb24odCl7cmV0dXJuICh0LnJvdW5kWm9vbT9NYXRoLnJvdW5kOk1hdGguZmxvb3IpKHRoaXMuem9vbSt0aGlzLnNjYWxlWm9vbSh0aGlzLnRpbGVTaXplL3QudGlsZVNpemUpKX0sY28ucHJvdG90eXBlLmdldFZpc2libGVVbndyYXBwZWRDb29yZGluYXRlcz1mdW5jdGlvbihlKXt2YXIgaT1bbmV3IHQuVW53cmFwcGVkVGlsZUlEKDAsZSldO2lmKHRoaXMuX3JlbmRlcldvcmxkQ29waWVzKWZvcih2YXIgbz10aGlzLnBvaW50Q29vcmRpbmF0ZShuZXcgdC5Qb2ludCgwLDApKSxyPXRoaXMucG9pbnRDb29yZGluYXRlKG5ldyB0LlBvaW50KHRoaXMud2lkdGgsMCkpLGE9dGhpcy5wb2ludENvb3JkaW5hdGUobmV3IHQuUG9pbnQodGhpcy53aWR0aCx0aGlzLmhlaWdodCkpLG49dGhpcy5wb2ludENvb3JkaW5hdGUobmV3IHQuUG9pbnQoMCx0aGlzLmhlaWdodCkpLHM9TWF0aC5mbG9vcihNYXRoLm1pbihvLngsci54LGEueCxuLngpKSxsPU1hdGguZmxvb3IoTWF0aC5tYXgoby54LHIueCxhLngsbi54KSksYz1zLTE7Yzw9bCsxO2MrKykwIT09YyYmaS5wdXNoKG5ldyB0LlVud3JhcHBlZFRpbGVJRChjLGUpKTtyZXR1cm4gaX0sY28ucHJvdG90eXBlLmNvdmVyaW5nVGlsZXM9ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcy5jb3ZlcmluZ1pvb21MZXZlbChlKSxvPWk7aWYodm9pZCAwIT09ZS5taW56b29tJiZpPGUubWluem9vbSlyZXR1cm4gW107dm9pZCAwIT09ZS5tYXh6b29tJiZpPmUubWF4em9vbSYmKGk9ZS5tYXh6b29tKTt2YXIgcj10Lk1lcmNhdG9yQ29vcmRpbmF0ZS5mcm9tTG5nTGF0KHRoaXMuY2VudGVyKSxhPU1hdGgucG93KDIsaSksbj1uZXcgdC5Qb2ludChhKnIueC0uNSxhKnIueS0uNSk7cmV0dXJuIGZ1bmN0aW9uKGUsaSxvLHIpe3ZvaWQgMD09PXImJihyPSEwKTt2YXIgYT0xPDxlLG49e307ZnVuY3Rpb24gcyhpLHMsbCl7dmFyIGMsdSxoLHA7aWYobD49MCYmbDw9YSlmb3IoYz1pO2M8cztjKyspdT1NYXRoLmZsb29yKGMvYSksaD0oYyVhK2EpJWEsMCE9PXUmJiEwIT09cnx8KHA9bmV3IHQuT3ZlcnNjYWxlZFRpbGVJRChvLHUsZSxoLGwpLG5bcC5rZXldPXApO312YXIgbD1pLm1hcChmdW5jdGlvbihlKXtyZXR1cm4gbmV3IHQuUG9pbnQoZS54LGUueSkuX211bHQoYSl9KTtyZXR1cm4gbG8obFswXSxsWzFdLGxbMl0sMCxhLHMpLGxvKGxbMl0sbFszXSxsWzBdLDAsYSxzKSxPYmplY3Qua2V5cyhuKS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIG5bdF19KX0oaSxbdGhpcy5wb2ludENvb3JkaW5hdGUobmV3IHQuUG9pbnQoMCwwKSksdGhpcy5wb2ludENvb3JkaW5hdGUobmV3IHQuUG9pbnQodGhpcy53aWR0aCwwKSksdGhpcy5wb2ludENvb3JkaW5hdGUobmV3IHQuUG9pbnQodGhpcy53aWR0aCx0aGlzLmhlaWdodCkpLHRoaXMucG9pbnRDb29yZGluYXRlKG5ldyB0LlBvaW50KDAsdGhpcy5oZWlnaHQpKV0sZS5yZXBhcnNlT3ZlcnNjYWxlZD9vOmksdGhpcy5fcmVuZGVyV29ybGRDb3BpZXMpLnNvcnQoZnVuY3Rpb24odCxlKXtyZXR1cm4gbi5kaXN0KHQuY2Fub25pY2FsKS1uLmRpc3QoZS5jYW5vbmljYWwpfSl9LGNvLnByb3RvdHlwZS5yZXNpemU9ZnVuY3Rpb24odCxlKXt0aGlzLndpZHRoPXQsdGhpcy5oZWlnaHQ9ZSx0aGlzLnBpeGVsc1RvR0xVbml0cz1bMi90LC0yL2VdLHRoaXMuX2NvbnN0cmFpbigpLHRoaXMuX2NhbGNNYXRyaWNlcygpO30sdW8udW5tb2RpZmllZC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fdW5tb2RpZmllZH0sY28ucHJvdG90eXBlLnpvb21TY2FsZT1mdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5wb3coMix0KX0sY28ucHJvdG90eXBlLnNjYWxlWm9vbT1mdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5sb2codCkvTWF0aC5MTjJ9LGNvLnByb3RvdHlwZS5wcm9qZWN0PWZ1bmN0aW9uKGUpe3ZhciBpPXQuY2xhbXAoZS5sYXQsLXRoaXMubWF4VmFsaWRMYXRpdHVkZSx0aGlzLm1heFZhbGlkTGF0aXR1ZGUpO3JldHVybiBuZXcgdC5Qb2ludCh0Lm1lcmNhdG9yWGZyb21MbmcoZS5sbmcpKnRoaXMud29ybGRTaXplLHQubWVyY2F0b3JZZnJvbUxhdChpKSp0aGlzLndvcmxkU2l6ZSl9LGNvLnByb3RvdHlwZS51bnByb2plY3Q9ZnVuY3Rpb24oZSl7cmV0dXJuIG5ldyB0Lk1lcmNhdG9yQ29vcmRpbmF0ZShlLngvdGhpcy53b3JsZFNpemUsZS55L3RoaXMud29ybGRTaXplKS50b0xuZ0xhdCgpfSx1by5wb2ludC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5wcm9qZWN0KHRoaXMuY2VudGVyKX0sY28ucHJvdG90eXBlLnNldExvY2F0aW9uQXRQb2ludD1mdW5jdGlvbihlLGkpe3ZhciBvPXRoaXMucG9pbnRDb29yZGluYXRlKGkpLHI9dGhpcy5wb2ludENvb3JkaW5hdGUodGhpcy5jZW50ZXJQb2ludCksYT10aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZShlKSxuPW5ldyB0Lk1lcmNhdG9yQ29vcmRpbmF0ZShhLngtKG8ueC1yLngpLGEueS0oby55LXIueSkpO3RoaXMuY2VudGVyPXRoaXMuY29vcmRpbmF0ZUxvY2F0aW9uKG4pLHRoaXMuX3JlbmRlcldvcmxkQ29waWVzJiYodGhpcy5jZW50ZXI9dGhpcy5jZW50ZXIud3JhcCgpKTt9LGNvLnByb3RvdHlwZS5sb2NhdGlvblBvaW50PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNvb3JkaW5hdGVQb2ludCh0aGlzLmxvY2F0aW9uQ29vcmRpbmF0ZSh0KSl9LGNvLnByb3RvdHlwZS5wb2ludExvY2F0aW9uPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNvb3JkaW5hdGVMb2NhdGlvbih0aGlzLnBvaW50Q29vcmRpbmF0ZSh0KSl9LGNvLnByb3RvdHlwZS5sb2NhdGlvbkNvb3JkaW5hdGU9ZnVuY3Rpb24oZSl7cmV0dXJuIHQuTWVyY2F0b3JDb29yZGluYXRlLmZyb21MbmdMYXQoZSl9LGNvLnByb3RvdHlwZS5jb29yZGluYXRlTG9jYXRpb249ZnVuY3Rpb24odCl7cmV0dXJuIHQudG9MbmdMYXQoKX0sY28ucHJvdG90eXBlLnBvaW50Q29vcmRpbmF0ZT1mdW5jdGlvbihlKXt2YXIgaT1bZS54LGUueSwwLDFdLG89W2UueCxlLnksMSwxXTt0LnRyYW5zZm9ybU1hdDQoaSxpLHRoaXMucGl4ZWxNYXRyaXhJbnZlcnNlKSx0LnRyYW5zZm9ybU1hdDQobyxvLHRoaXMucGl4ZWxNYXRyaXhJbnZlcnNlKTt2YXIgcj1pWzNdLGE9b1szXSxuPWlbMF0vcixzPW9bMF0vYSxsPWlbMV0vcixjPW9bMV0vYSx1PWlbMl0vcixoPW9bMl0vYSxwPXU9PT1oPzA6KDAtdSkvKGgtdSk7cmV0dXJuIG5ldyB0Lk1lcmNhdG9yQ29vcmRpbmF0ZSh0Lm51bWJlcihuLHMscCkvdGhpcy53b3JsZFNpemUsdC5udW1iZXIobCxjLHApL3RoaXMud29ybGRTaXplKX0sY28ucHJvdG90eXBlLmNvb3JkaW5hdGVQb2ludD1mdW5jdGlvbihlKXt2YXIgaT1bZS54KnRoaXMud29ybGRTaXplLGUueSp0aGlzLndvcmxkU2l6ZSwwLDFdO3JldHVybiB0LnRyYW5zZm9ybU1hdDQoaSxpLHRoaXMucGl4ZWxNYXRyaXgpLG5ldyB0LlBvaW50KGlbMF0vaVszXSxpWzFdL2lbM10pfSxjby5wcm90b3R5cGUuZ2V0Qm91bmRzPWZ1bmN0aW9uKCl7cmV0dXJuIChuZXcgdC5MbmdMYXRCb3VuZHMpLmV4dGVuZCh0aGlzLnBvaW50TG9jYXRpb24obmV3IHQuUG9pbnQoMCwwKSkpLmV4dGVuZCh0aGlzLnBvaW50TG9jYXRpb24obmV3IHQuUG9pbnQodGhpcy53aWR0aCwwKSkpLmV4dGVuZCh0aGlzLnBvaW50TG9jYXRpb24obmV3IHQuUG9pbnQodGhpcy53aWR0aCx0aGlzLmhlaWdodCkpKS5leHRlbmQodGhpcy5wb2ludExvY2F0aW9uKG5ldyB0LlBvaW50KDAsdGhpcy5oZWlnaHQpKSl9LGNvLnByb3RvdHlwZS5nZXRNYXhCb3VuZHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5sYXRSYW5nZSYmMj09PXRoaXMubGF0UmFuZ2UubGVuZ3RoJiZ0aGlzLmxuZ1JhbmdlJiYyPT09dGhpcy5sbmdSYW5nZS5sZW5ndGg/bmV3IHQuTG5nTGF0Qm91bmRzKFt0aGlzLmxuZ1JhbmdlWzBdLHRoaXMubGF0UmFuZ2VbMF1dLFt0aGlzLmxuZ1JhbmdlWzFdLHRoaXMubGF0UmFuZ2VbMV1dKTpudWxsfSxjby5wcm90b3R5cGUuc2V0TWF4Qm91bmRzPWZ1bmN0aW9uKHQpe3Q/KHRoaXMubG5nUmFuZ2U9W3QuZ2V0V2VzdCgpLHQuZ2V0RWFzdCgpXSx0aGlzLmxhdFJhbmdlPVt0LmdldFNvdXRoKCksdC5nZXROb3J0aCgpXSx0aGlzLl9jb25zdHJhaW4oKSk6KHRoaXMubG5nUmFuZ2U9bnVsbCx0aGlzLmxhdFJhbmdlPVstdGhpcy5tYXhWYWxpZExhdGl0dWRlLHRoaXMubWF4VmFsaWRMYXRpdHVkZV0pO30sY28ucHJvdG90eXBlLmNhbGN1bGF0ZVBvc01hdHJpeD1mdW5jdGlvbihlLGkpe3ZvaWQgMD09PWkmJihpPSExKTt2YXIgbz1lLmtleSxyPWk/dGhpcy5fYWxpZ25lZFBvc01hdHJpeENhY2hlOnRoaXMuX3Bvc01hdHJpeENhY2hlO2lmKHJbb10pcmV0dXJuIHJbb107dmFyIGE9ZS5jYW5vbmljYWwsbj10aGlzLndvcmxkU2l6ZS90aGlzLnpvb21TY2FsZShhLnopLHM9YS54K01hdGgucG93KDIsYS56KSplLndyYXAsbD10LmlkZW50aXR5KG5ldyBGbG9hdDY0QXJyYXkoMTYpKTtyZXR1cm4gdC50cmFuc2xhdGUobCxsLFtzKm4sYS55Km4sMF0pLHQuc2NhbGUobCxsLFtuL3QuRVhURU5ULG4vdC5FWFRFTlQsMV0pLHQubXVsdGlwbHkobCxpP3RoaXMuYWxpZ25lZFByb2pNYXRyaXg6dGhpcy5wcm9qTWF0cml4LGwpLHJbb109bmV3IEZsb2F0MzJBcnJheShsKSxyW29dfSxjby5wcm90b3R5cGUuY3VzdG9tTGF5ZXJNYXRyaXg9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tZXJjYXRvck1hdHJpeC5zbGljZSgpfSxjby5wcm90b3R5cGUuX2NvbnN0cmFpbj1mdW5jdGlvbigpe2lmKHRoaXMuY2VudGVyJiZ0aGlzLndpZHRoJiZ0aGlzLmhlaWdodCYmIXRoaXMuX2NvbnN0cmFpbmluZyl7dGhpcy5fY29uc3RyYWluaW5nPSEwO3ZhciBlLGksbyxyLGE9LTkwLG49OTAscz0tMTgwLGw9MTgwLGM9dGhpcy5zaXplLHU9dGhpcy5fdW5tb2RpZmllZDtpZih0aGlzLmxhdFJhbmdlKXt2YXIgaD10aGlzLmxhdFJhbmdlO2E9dC5tZXJjYXRvcllmcm9tTGF0KGhbMV0pKnRoaXMud29ybGRTaXplLGU9KG49dC5tZXJjYXRvcllmcm9tTGF0KGhbMF0pKnRoaXMud29ybGRTaXplKS1hPGMueT9jLnkvKG4tYSk6MDt9aWYodGhpcy5sbmdSYW5nZSl7dmFyIHA9dGhpcy5sbmdSYW5nZTtzPXQubWVyY2F0b3JYZnJvbUxuZyhwWzBdKSp0aGlzLndvcmxkU2l6ZSxpPShsPXQubWVyY2F0b3JYZnJvbUxuZyhwWzFdKSp0aGlzLndvcmxkU2l6ZSktczxjLng/Yy54LyhsLXMpOjA7fXZhciBkPXRoaXMucG9pbnQsXz1NYXRoLm1heChpfHwwLGV8fDApO2lmKF8pcmV0dXJuIHRoaXMuY2VudGVyPXRoaXMudW5wcm9qZWN0KG5ldyB0LlBvaW50KGk/KGwrcykvMjpkLngsZT8obithKS8yOmQueSkpLHRoaXMuem9vbSs9dGhpcy5zY2FsZVpvb20oXyksdGhpcy5fdW5tb2RpZmllZD11LHZvaWQodGhpcy5fY29uc3RyYWluaW5nPSExKTtpZih0aGlzLmxhdFJhbmdlKXt2YXIgZj1kLnksbT1jLnkvMjtmLW08YSYmKHI9YSttKSxmK20+biYmKHI9bi1tKTt9aWYodGhpcy5sbmdSYW5nZSl7dmFyIGc9ZC54LHY9Yy54LzI7Zy12PHMmJihvPXMrdiksZyt2PmwmJihvPWwtdik7fXZvaWQgMD09PW8mJnZvaWQgMD09PXJ8fCh0aGlzLmNlbnRlcj10aGlzLnVucHJvamVjdChuZXcgdC5Qb2ludCh2b2lkIDAhPT1vP286ZC54LHZvaWQgMCE9PXI/cjpkLnkpKSksdGhpcy5fdW5tb2RpZmllZD11LHRoaXMuX2NvbnN0cmFpbmluZz0hMTt9fSxjby5wcm90b3R5cGUuX2NhbGNNYXRyaWNlcz1mdW5jdGlvbigpe2lmKHRoaXMuaGVpZ2h0KXt0aGlzLmNhbWVyYVRvQ2VudGVyRGlzdGFuY2U9LjUvTWF0aC50YW4odGhpcy5fZm92LzIpKnRoaXMuaGVpZ2h0O3ZhciBlPXRoaXMuX2Zvdi8yLGk9TWF0aC5QSS8yK3RoaXMuX3BpdGNoLG89TWF0aC5zaW4oZSkqdGhpcy5jYW1lcmFUb0NlbnRlckRpc3RhbmNlL01hdGguc2luKE1hdGguUEktaS1lKSxyPXRoaXMucG9pbnQsYT1yLngsbj1yLnkscz0xLjAxKihNYXRoLmNvcyhNYXRoLlBJLzItdGhpcy5fcGl0Y2gpKm8rdGhpcy5jYW1lcmFUb0NlbnRlckRpc3RhbmNlKSxsPW5ldyBGbG9hdDY0QXJyYXkoMTYpO3QucGVyc3BlY3RpdmUobCx0aGlzLl9mb3YsdGhpcy53aWR0aC90aGlzLmhlaWdodCwxLHMpLHQuc2NhbGUobCxsLFsxLC0xLDFdKSx0LnRyYW5zbGF0ZShsLGwsWzAsMCwtdGhpcy5jYW1lcmFUb0NlbnRlckRpc3RhbmNlXSksdC5yb3RhdGVYKGwsbCx0aGlzLl9waXRjaCksdC5yb3RhdGVaKGwsbCx0aGlzLmFuZ2xlKSx0LnRyYW5zbGF0ZShsLGwsWy1hLC1uLDBdKSx0aGlzLm1lcmNhdG9yTWF0cml4PXQuc2NhbGUoW10sbCxbdGhpcy53b3JsZFNpemUsdGhpcy53b3JsZFNpemUsdGhpcy53b3JsZFNpemVdKSx0LnNjYWxlKGwsbCxbMSwxLHQubWVyY2F0b3JaZnJvbUFsdGl0dWRlKDEsdGhpcy5jZW50ZXIubGF0KSp0aGlzLndvcmxkU2l6ZSwxXSksdGhpcy5wcm9qTWF0cml4PWw7dmFyIGM9dGhpcy53aWR0aCUyLzIsdT10aGlzLmhlaWdodCUyLzIsaD1NYXRoLmNvcyh0aGlzLmFuZ2xlKSxwPU1hdGguc2luKHRoaXMuYW5nbGUpLGQ9YS1NYXRoLnJvdW5kKGEpK2gqYytwKnUsXz1uLU1hdGgucm91bmQobikraCp1K3AqYyxmPW5ldyBGbG9hdDY0QXJyYXkobCk7aWYodC50cmFuc2xhdGUoZixmLFtkPi41P2QtMTpkLF8+LjU/Xy0xOl8sMF0pLHRoaXMuYWxpZ25lZFByb2pNYXRyaXg9ZixsPXQuY3JlYXRlKCksdC5zY2FsZShsLGwsW3RoaXMud2lkdGgvMiwtdGhpcy5oZWlnaHQvMiwxXSksdC50cmFuc2xhdGUobCxsLFsxLC0xLDBdKSx0aGlzLmxhYmVsUGxhbmVNYXRyaXg9bCxsPXQuY3JlYXRlKCksdC5zY2FsZShsLGwsWzEsLTEsMV0pLHQudHJhbnNsYXRlKGwsbCxbLTEsLTEsMF0pLHQuc2NhbGUobCxsLFsyL3RoaXMud2lkdGgsMi90aGlzLmhlaWdodCwxXSksdGhpcy5nbENvb3JkTWF0cml4PWwsdGhpcy5waXhlbE1hdHJpeD10Lm11bHRpcGx5KG5ldyBGbG9hdDY0QXJyYXkoMTYpLHRoaXMubGFiZWxQbGFuZU1hdHJpeCx0aGlzLnByb2pNYXRyaXgpLCEobD10LmludmVydChuZXcgRmxvYXQ2NEFycmF5KDE2KSx0aGlzLnBpeGVsTWF0cml4KSkpdGhyb3cgbmV3IEVycm9yKFwiZmFpbGVkIHRvIGludmVydCBtYXRyaXhcIik7dGhpcy5waXhlbE1hdHJpeEludmVyc2U9bCx0aGlzLl9wb3NNYXRyaXhDYWNoZT17fSx0aGlzLl9hbGlnbmVkUG9zTWF0cml4Q2FjaGU9e307fX0sY28ucHJvdG90eXBlLm1heFBpdGNoU2NhbGVGYWN0b3I9ZnVuY3Rpb24oKXtpZighdGhpcy5waXhlbE1hdHJpeEludmVyc2UpcmV0dXJuIDE7dmFyIGU9dGhpcy5wb2ludENvb3JkaW5hdGUobmV3IHQuUG9pbnQoMCwwKSksaT1bZS54KnRoaXMud29ybGRTaXplLGUueSp0aGlzLndvcmxkU2l6ZSwwLDFdO3JldHVybiB0LnRyYW5zZm9ybU1hdDQoaSxpLHRoaXMucGl4ZWxNYXRyaXgpWzNdL3RoaXMuY2FtZXJhVG9DZW50ZXJEaXN0YW5jZX0sY28ucHJvdG90eXBlLmdldENhbWVyYVBvaW50PWZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5fcGl0Y2gsaT1NYXRoLnRhbihlKSoodGhpcy5jYW1lcmFUb0NlbnRlckRpc3RhbmNlfHwxKTtyZXR1cm4gdGhpcy5jZW50ZXJQb2ludC5hZGQobmV3IHQuUG9pbnQoMCxpKSl9LGNvLnByb3RvdHlwZS5nZXRDYW1lcmFRdWVyeUdlb21ldHJ5PWZ1bmN0aW9uKGUpe3ZhciBpPXRoaXMuZ2V0Q2FtZXJhUG9pbnQoKTtpZigxPT09ZS5sZW5ndGgpcmV0dXJuIFtlWzBdLGldO2Zvcih2YXIgbz1pLngscj1pLnksYT1pLngsbj1pLnkscz0wLGw9ZTtzPGwubGVuZ3RoO3MrPTEpe3ZhciBjPWxbc107bz1NYXRoLm1pbihvLGMueCkscj1NYXRoLm1pbihyLGMueSksYT1NYXRoLm1heChhLGMueCksbj1NYXRoLm1heChuLGMueSk7fXJldHVybiBbbmV3IHQuUG9pbnQobyxyKSxuZXcgdC5Qb2ludChhLHIpLG5ldyB0LlBvaW50KGEsbiksbmV3IHQuUG9pbnQobyxuKSxuZXcgdC5Qb2ludChvLHIpXX0sT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoY28ucHJvdG90eXBlLHVvKTt2YXIgaG89ZnVuY3Rpb24oKXt2YXIgZSxpLG8scixhO3QuYmluZEFsbChbXCJfb25IYXNoQ2hhbmdlXCIsXCJfdXBkYXRlSGFzaFwiXSx0aGlzKSx0aGlzLl91cGRhdGVIYXNoPShlPXRoaXMuX3VwZGF0ZUhhc2hVbnRocm90dGxlZC5iaW5kKHRoaXMpLGk9MzAwLG89ITEscj1udWxsLGE9ZnVuY3Rpb24oKXtyPW51bGwsbyYmKGUoKSxyPXNldFRpbWVvdXQoYSxpKSxvPSExKTt9LGZ1bmN0aW9uKCl7cmV0dXJuIG89ITAscnx8YSgpLHJ9KTt9O2hvLnByb3RvdHlwZS5hZGRUbz1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5fbWFwPWUsdC53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImhhc2hjaGFuZ2VcIix0aGlzLl9vbkhhc2hDaGFuZ2UsITEpLHRoaXMuX21hcC5vbihcIm1vdmVlbmRcIix0aGlzLl91cGRhdGVIYXNoKSx0aGlzfSxoby5wcm90b3R5cGUucmVtb3ZlPWZ1bmN0aW9uKCl7cmV0dXJuIHQud2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJoYXNoY2hhbmdlXCIsdGhpcy5fb25IYXNoQ2hhbmdlLCExKSx0aGlzLl9tYXAub2ZmKFwibW92ZWVuZFwiLHRoaXMuX3VwZGF0ZUhhc2gpLGNsZWFyVGltZW91dCh0aGlzLl91cGRhdGVIYXNoKCkpLGRlbGV0ZSB0aGlzLl9tYXAsdGhpc30saG8ucHJvdG90eXBlLmdldEhhc2hTdHJpbmc9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5fbWFwLmdldENlbnRlcigpLGk9TWF0aC5yb3VuZCgxMDAqdGhpcy5fbWFwLmdldFpvb20oKSkvMTAwLG89TWF0aC5jZWlsKChpKk1hdGguTE4yK01hdGgubG9nKDUxMi8zNjAvLjUpKS9NYXRoLkxOMTApLHI9TWF0aC5wb3coMTAsbyksYT1NYXRoLnJvdW5kKGUubG5nKnIpL3Isbj1NYXRoLnJvdW5kKGUubGF0KnIpL3Iscz10aGlzLl9tYXAuZ2V0QmVhcmluZygpLGw9dGhpcy5fbWFwLmdldFBpdGNoKCksYz1cIlwiO3JldHVybiBjKz10P1wiIy9cIithK1wiL1wiK24rXCIvXCIraTpcIiNcIitpK1wiL1wiK24rXCIvXCIrYSwoc3x8bCkmJihjKz1cIi9cIitNYXRoLnJvdW5kKDEwKnMpLzEwKSxsJiYoYys9XCIvXCIrTWF0aC5yb3VuZChsKSksY30saG8ucHJvdG90eXBlLl9vbkhhc2hDaGFuZ2U9ZnVuY3Rpb24oKXt2YXIgZT10LndpbmRvdy5sb2NhdGlvbi5oYXNoLnJlcGxhY2UoXCIjXCIsXCJcIikuc3BsaXQoXCIvXCIpO3JldHVybiBlLmxlbmd0aD49MyYmKHRoaXMuX21hcC5qdW1wVG8oe2NlbnRlcjpbK2VbMl0sK2VbMV1dLHpvb206K2VbMF0sYmVhcmluZzorKGVbM118fDApLHBpdGNoOisoZVs0XXx8MCl9KSwhMCl9LGhvLnByb3RvdHlwZS5fdXBkYXRlSGFzaFVudGhyb3R0bGVkPWZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5nZXRIYXNoU3RyaW5nKCk7dHJ5e3Qud2luZG93Lmhpc3RvcnkucmVwbGFjZVN0YXRlKHQud2luZG93Lmhpc3Rvcnkuc3RhdGUsXCJcIixlKTt9Y2F0Y2godCl7fX07dmFyIHBvPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIG8obyxyLGEsbil7dm9pZCAwPT09biYmKG49e30pO3ZhciBzPWkubW91c2VQb3Moci5nZXRDYW52YXNDb250YWluZXIoKSxhKSxsPXIudW5wcm9qZWN0KHMpO2UuY2FsbCh0aGlzLG8sdC5leHRlbmQoe3BvaW50OnMsbG5nTGF0Omwsb3JpZ2luYWxFdmVudDphfSxuKSksdGhpcy5fZGVmYXVsdFByZXZlbnRlZD0hMSx0aGlzLnRhcmdldD1yO31lJiYoby5fX3Byb3RvX189ZSksby5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShlJiZlLnByb3RvdHlwZSksby5wcm90b3R5cGUuY29uc3RydWN0b3I9bzt2YXIgcj17ZGVmYXVsdFByZXZlbnRlZDp7Y29uZmlndXJhYmxlOiEwfX07cmV0dXJuIG8ucHJvdG90eXBlLnByZXZlbnREZWZhdWx0PWZ1bmN0aW9uKCl7dGhpcy5fZGVmYXVsdFByZXZlbnRlZD0hMDt9LHIuZGVmYXVsdFByZXZlbnRlZC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZGVmYXVsdFByZXZlbnRlZH0sT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoby5wcm90b3R5cGUsciksb30odC5FdmVudCksX289ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gbyhvLHIsYSl7dmFyIG49aS50b3VjaFBvcyhyLmdldENhbnZhc0NvbnRhaW5lcigpLGEpLHM9bi5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHIudW5wcm9qZWN0KHQpfSksbD1uLnJlZHVjZShmdW5jdGlvbih0LGUsaSxvKXtyZXR1cm4gdC5hZGQoZS5kaXYoby5sZW5ndGgpKX0sbmV3IHQuUG9pbnQoMCwwKSksYz1yLnVucHJvamVjdChsKTtlLmNhbGwodGhpcyxvLHtwb2ludHM6bixwb2ludDpsLGxuZ0xhdHM6cyxsbmdMYXQ6YyxvcmlnaW5hbEV2ZW50OmF9KSx0aGlzLl9kZWZhdWx0UHJldmVudGVkPSExO31lJiYoby5fX3Byb3RvX189ZSksby5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShlJiZlLnByb3RvdHlwZSksby5wcm90b3R5cGUuY29uc3RydWN0b3I9bzt2YXIgcj17ZGVmYXVsdFByZXZlbnRlZDp7Y29uZmlndXJhYmxlOiEwfX07cmV0dXJuIG8ucHJvdG90eXBlLnByZXZlbnREZWZhdWx0PWZ1bmN0aW9uKCl7dGhpcy5fZGVmYXVsdFByZXZlbnRlZD0hMDt9LHIuZGVmYXVsdFByZXZlbnRlZC5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZGVmYXVsdFByZXZlbnRlZH0sT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoby5wcm90b3R5cGUsciksb30odC5FdmVudCksZm89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlLGksbyl7dC5jYWxsKHRoaXMsZSx7b3JpZ2luYWxFdmVudDpvfSksdGhpcy5fZGVmYXVsdFByZXZlbnRlZD0hMTt9dCYmKGUuX19wcm90b19fPXQpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUpLGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWU7dmFyIGk9e2RlZmF1bHRQcmV2ZW50ZWQ6e2NvbmZpZ3VyYWJsZTohMH19O3JldHVybiBlLnByb3RvdHlwZS5wcmV2ZW50RGVmYXVsdD1mdW5jdGlvbigpe3RoaXMuX2RlZmF1bHRQcmV2ZW50ZWQ9ITA7fSxpLmRlZmF1bHRQcmV2ZW50ZWQuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2RlZmF1bHRQcmV2ZW50ZWR9LE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGUucHJvdG90eXBlLGkpLGV9KHQuRXZlbnQpLG1vPWZ1bmN0aW9uKGUpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWUuZ2V0Q2FudmFzQ29udGFpbmVyKCksdGhpcy5fZGVsdGE9MCx0aGlzLl9kZWZhdWx0Wm9vbVJhdGU9LjAxLHRoaXMuX3doZWVsWm9vbVJhdGU9MS80NTAsdC5iaW5kQWxsKFtcIl9vbldoZWVsXCIsXCJfb25UaW1lb3V0XCIsXCJfb25TY3JvbGxGcmFtZVwiLFwiX29uU2Nyb2xsRmluaXNoZWRcIl0sdGhpcyk7fTttby5wcm90b3R5cGUuc2V0Wm9vbVJhdGU9ZnVuY3Rpb24odCl7dGhpcy5fZGVmYXVsdFpvb21SYXRlPXQ7fSxtby5wcm90b3R5cGUuc2V0V2hlZWxab29tUmF0ZT1mdW5jdGlvbih0KXt0aGlzLl93aGVlbFpvb21SYXRlPXQ7fSxtby5wcm90b3R5cGUuaXNFbmFibGVkPWZ1bmN0aW9uKCl7cmV0dXJuICEhdGhpcy5fZW5hYmxlZH0sbW8ucHJvdG90eXBlLmlzQWN0aXZlPWZ1bmN0aW9uKCl7cmV0dXJuICEhdGhpcy5fYWN0aXZlfSxtby5wcm90b3R5cGUuaXNab29taW5nPWZ1bmN0aW9uKCl7cmV0dXJuICEhdGhpcy5fem9vbWluZ30sbW8ucHJvdG90eXBlLmVuYWJsZT1mdW5jdGlvbih0KXt0aGlzLmlzRW5hYmxlZCgpfHwodGhpcy5fZW5hYmxlZD0hMCx0aGlzLl9hcm91bmRDZW50ZXI9dCYmXCJjZW50ZXJcIj09PXQuYXJvdW5kKTt9LG1vLnByb3RvdHlwZS5kaXNhYmxlPWZ1bmN0aW9uKCl7dGhpcy5pc0VuYWJsZWQoKSYmKHRoaXMuX2VuYWJsZWQ9ITEpO30sbW8ucHJvdG90eXBlLm9uV2hlZWw9ZnVuY3Rpb24oZSl7aWYodGhpcy5pc0VuYWJsZWQoKSl7dmFyIGk9ZS5kZWx0YU1vZGU9PT10LndpbmRvdy5XaGVlbEV2ZW50LkRPTV9ERUxUQV9MSU5FPzQwKmUuZGVsdGFZOmUuZGVsdGFZLG89dC5icm93c2VyLm5vdygpLHI9by0odGhpcy5fbGFzdFdoZWVsRXZlbnRUaW1lfHwwKTt0aGlzLl9sYXN0V2hlZWxFdmVudFRpbWU9bywwIT09aSYmaSU0LjAwMDI0NDE0MDYyNT09MD90aGlzLl90eXBlPVwid2hlZWxcIjowIT09aSYmTWF0aC5hYnMoaSk8ND90aGlzLl90eXBlPVwidHJhY2twYWRcIjpyPjQwMD8odGhpcy5fdHlwZT1udWxsLHRoaXMuX2xhc3RWYWx1ZT1pLHRoaXMuX3RpbWVvdXQ9c2V0VGltZW91dCh0aGlzLl9vblRpbWVvdXQsNDAsZSkpOnRoaXMuX3R5cGV8fCh0aGlzLl90eXBlPU1hdGguYWJzKHIqaSk8MjAwP1widHJhY2twYWRcIjpcIndoZWVsXCIsdGhpcy5fdGltZW91dCYmKGNsZWFyVGltZW91dCh0aGlzLl90aW1lb3V0KSx0aGlzLl90aW1lb3V0PW51bGwsaSs9dGhpcy5fbGFzdFZhbHVlKSksZS5zaGlmdEtleSYmaSYmKGkvPTQpLHRoaXMuX3R5cGUmJih0aGlzLl9sYXN0V2hlZWxFdmVudD1lLHRoaXMuX2RlbHRhLT1pLHRoaXMuaXNBY3RpdmUoKXx8dGhpcy5fc3RhcnQoZSkpLGUucHJldmVudERlZmF1bHQoKTt9fSxtby5wcm90b3R5cGUuX29uVGltZW91dD1mdW5jdGlvbih0KXt0aGlzLl90eXBlPVwid2hlZWxcIix0aGlzLl9kZWx0YS09dGhpcy5fbGFzdFZhbHVlLHRoaXMuaXNBY3RpdmUoKXx8dGhpcy5fc3RhcnQodCk7fSxtby5wcm90b3R5cGUuX3N0YXJ0PWZ1bmN0aW9uKGUpe2lmKHRoaXMuX2RlbHRhKXt0aGlzLl9mcmFtZUlkJiYodGhpcy5fbWFwLl9jYW5jZWxSZW5kZXJGcmFtZSh0aGlzLl9mcmFtZUlkKSx0aGlzLl9mcmFtZUlkPW51bGwpLHRoaXMuX2FjdGl2ZT0hMCx0aGlzLmlzWm9vbWluZygpfHwodGhpcy5fem9vbWluZz0hMCx0aGlzLl9tYXAuZmlyZShuZXcgdC5FdmVudChcIm1vdmVzdGFydFwiLHtvcmlnaW5hbEV2ZW50OmV9KSksdGhpcy5fbWFwLmZpcmUobmV3IHQuRXZlbnQoXCJ6b29tc3RhcnRcIix7b3JpZ2luYWxFdmVudDplfSkpKSx0aGlzLl9maW5pc2hUaW1lb3V0JiZjbGVhclRpbWVvdXQodGhpcy5fZmluaXNoVGltZW91dCk7dmFyIG89aS5tb3VzZVBvcyh0aGlzLl9lbCxlKTt0aGlzLl9hcm91bmQ9dC5MbmdMYXQuY29udmVydCh0aGlzLl9hcm91bmRDZW50ZXI/dGhpcy5fbWFwLmdldENlbnRlcigpOnRoaXMuX21hcC51bnByb2plY3QobykpLHRoaXMuX2Fyb3VuZFBvaW50PXRoaXMuX21hcC50cmFuc2Zvcm0ubG9jYXRpb25Qb2ludCh0aGlzLl9hcm91bmQpLHRoaXMuX2ZyYW1lSWR8fCh0aGlzLl9mcmFtZUlkPXRoaXMuX21hcC5fcmVxdWVzdFJlbmRlckZyYW1lKHRoaXMuX29uU2Nyb2xsRnJhbWUpKTt9fSxtby5wcm90b3R5cGUuX29uU2Nyb2xsRnJhbWU9ZnVuY3Rpb24oKXt2YXIgZT10aGlzO2lmKHRoaXMuX2ZyYW1lSWQ9bnVsbCx0aGlzLmlzQWN0aXZlKCkpe3ZhciBpPXRoaXMuX21hcC50cmFuc2Zvcm07aWYoMCE9PXRoaXMuX2RlbHRhKXt2YXIgbz1cIndoZWVsXCI9PT10aGlzLl90eXBlJiZNYXRoLmFicyh0aGlzLl9kZWx0YSk+NC4wMDAyNDQxNDA2MjU/dGhpcy5fd2hlZWxab29tUmF0ZTp0aGlzLl9kZWZhdWx0Wm9vbVJhdGUscj0yLygxK01hdGguZXhwKC1NYXRoLmFicyh0aGlzLl9kZWx0YSpvKSkpO3RoaXMuX2RlbHRhPDAmJjAhPT1yJiYocj0xL3IpO3ZhciBhPVwibnVtYmVyXCI9PXR5cGVvZiB0aGlzLl90YXJnZXRab29tP2kuem9vbVNjYWxlKHRoaXMuX3RhcmdldFpvb20pOmkuc2NhbGU7dGhpcy5fdGFyZ2V0Wm9vbT1NYXRoLm1pbihpLm1heFpvb20sTWF0aC5tYXgoaS5taW5ab29tLGkuc2NhbGVab29tKGEqcikpKSxcIndoZWVsXCI9PT10aGlzLl90eXBlJiYodGhpcy5fc3RhcnRab29tPWkuem9vbSx0aGlzLl9lYXNpbmc9dGhpcy5fc21vb3RoT3V0RWFzaW5nKDIwMCkpLHRoaXMuX2RlbHRhPTA7fXZhciBuPVwibnVtYmVyXCI9PXR5cGVvZiB0aGlzLl90YXJnZXRab29tP3RoaXMuX3RhcmdldFpvb206aS56b29tLHM9dGhpcy5fc3RhcnRab29tLGw9dGhpcy5fZWFzaW5nLGM9ITE7aWYoXCJ3aGVlbFwiPT09dGhpcy5fdHlwZSYmcyYmbCl7dmFyIHU9TWF0aC5taW4oKHQuYnJvd3Nlci5ub3coKS10aGlzLl9sYXN0V2hlZWxFdmVudFRpbWUpLzIwMCwxKSxoPWwodSk7aS56b29tPXQubnVtYmVyKHMsbixoKSx1PDE/dGhpcy5fZnJhbWVJZHx8KHRoaXMuX2ZyYW1lSWQ9dGhpcy5fbWFwLl9yZXF1ZXN0UmVuZGVyRnJhbWUodGhpcy5fb25TY3JvbGxGcmFtZSkpOmM9ITA7fWVsc2UgaS56b29tPW4sYz0hMDtpLnNldExvY2F0aW9uQXRQb2ludCh0aGlzLl9hcm91bmQsdGhpcy5fYXJvdW5kUG9pbnQpLHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KFwibW92ZVwiLHtvcmlnaW5hbEV2ZW50OnRoaXMuX2xhc3RXaGVlbEV2ZW50fSkpLHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KFwiem9vbVwiLHtvcmlnaW5hbEV2ZW50OnRoaXMuX2xhc3RXaGVlbEV2ZW50fSkpLGMmJih0aGlzLl9hY3RpdmU9ITEsdGhpcy5fZmluaXNoVGltZW91dD1zZXRUaW1lb3V0KGZ1bmN0aW9uKCl7ZS5fem9vbWluZz0hMSxlLl9tYXAuZmlyZShuZXcgdC5FdmVudChcInpvb21lbmRcIix7b3JpZ2luYWxFdmVudDplLl9sYXN0V2hlZWxFdmVudH0pKSxlLl9tYXAuZmlyZShuZXcgdC5FdmVudChcIm1vdmVlbmRcIix7b3JpZ2luYWxFdmVudDplLl9sYXN0V2hlZWxFdmVudH0pKSxkZWxldGUgZS5fdGFyZ2V0Wm9vbTt9LDIwMCkpO319LG1vLnByb3RvdHlwZS5fc21vb3RoT3V0RWFzaW5nPWZ1bmN0aW9uKGUpe3ZhciBpPXQuZWFzZTtpZih0aGlzLl9wcmV2RWFzZSl7dmFyIG89dGhpcy5fcHJldkVhc2Uscj0odC5icm93c2VyLm5vdygpLW8uc3RhcnQpL28uZHVyYXRpb24sYT1vLmVhc2luZyhyKy4wMSktby5lYXNpbmcociksbj0uMjcvTWF0aC5zcXJ0KGEqYSsxZS00KSouMDEscz1NYXRoLnNxcnQoLjA3MjktbipuKTtpPXQuYmV6aWVyKG4scywuMjUsMSk7fXJldHVybiB0aGlzLl9wcmV2RWFzZT17c3RhcnQ6dC5icm93c2VyLm5vdygpLGR1cmF0aW9uOmUsZWFzaW5nOml9LGl9O3ZhciBnbz1mdW5jdGlvbihlLGkpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWUuZ2V0Q2FudmFzQ29udGFpbmVyKCksdGhpcy5fY29udGFpbmVyPWUuZ2V0Q29udGFpbmVyKCksdGhpcy5fY2xpY2tUb2xlcmFuY2U9aS5jbGlja1RvbGVyYW5jZXx8MSx0LmJpbmRBbGwoW1wiX29uTW91c2VNb3ZlXCIsXCJfb25Nb3VzZVVwXCIsXCJfb25LZXlEb3duXCJdLHRoaXMpO307Z28ucHJvdG90eXBlLmlzRW5hYmxlZD1mdW5jdGlvbigpe3JldHVybiAhIXRoaXMuX2VuYWJsZWR9LGdvLnByb3RvdHlwZS5pc0FjdGl2ZT1mdW5jdGlvbigpe3JldHVybiAhIXRoaXMuX2FjdGl2ZX0sZ28ucHJvdG90eXBlLmVuYWJsZT1mdW5jdGlvbigpe3RoaXMuaXNFbmFibGVkKCl8fCh0aGlzLl9lbmFibGVkPSEwKTt9LGdvLnByb3RvdHlwZS5kaXNhYmxlPWZ1bmN0aW9uKCl7dGhpcy5pc0VuYWJsZWQoKSYmKHRoaXMuX2VuYWJsZWQ9ITEpO30sZ28ucHJvdG90eXBlLm9uTW91c2VEb3duPWZ1bmN0aW9uKGUpe3RoaXMuaXNFbmFibGVkKCkmJmUuc2hpZnRLZXkmJjA9PT1lLmJ1dHRvbiYmKHQud2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIix0aGlzLl9vbk1vdXNlTW92ZSwhMSksdC53aW5kb3cuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImtleWRvd25cIix0aGlzLl9vbktleURvd24sITEpLHQud2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZXVwXCIsdGhpcy5fb25Nb3VzZVVwLCExKSxpLmRpc2FibGVEcmFnKCksdGhpcy5fc3RhcnRQb3M9dGhpcy5fbGFzdFBvcz1pLm1vdXNlUG9zKHRoaXMuX2VsLGUpLHRoaXMuX2FjdGl2ZT0hMCk7fSxnby5wcm90b3R5cGUuX29uTW91c2VNb3ZlPWZ1bmN0aW9uKHQpe3ZhciBlPWkubW91c2VQb3ModGhpcy5fZWwsdCk7aWYoISh0aGlzLl9sYXN0UG9zLmVxdWFscyhlKXx8IXRoaXMuX2JveCYmZS5kaXN0KHRoaXMuX3N0YXJ0UG9zKTx0aGlzLl9jbGlja1RvbGVyYW5jZSkpe3ZhciBvPXRoaXMuX3N0YXJ0UG9zO3RoaXMuX2xhc3RQb3M9ZSx0aGlzLl9ib3h8fCh0aGlzLl9ib3g9aS5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLWJveHpvb21cIix0aGlzLl9jb250YWluZXIpLHRoaXMuX2NvbnRhaW5lci5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3Jvc3NoYWlyXCIpLHRoaXMuX2ZpcmVFdmVudChcImJveHpvb21zdGFydFwiLHQpKTt2YXIgcj1NYXRoLm1pbihvLngsZS54KSxhPU1hdGgubWF4KG8ueCxlLngpLG49TWF0aC5taW4oby55LGUueSkscz1NYXRoLm1heChvLnksZS55KTtpLnNldFRyYW5zZm9ybSh0aGlzLl9ib3gsXCJ0cmFuc2xhdGUoXCIrcitcInB4LFwiK24rXCJweClcIiksdGhpcy5fYm94LnN0eWxlLndpZHRoPWEtcitcInB4XCIsdGhpcy5fYm94LnN0eWxlLmhlaWdodD1zLW4rXCJweFwiO319LGdvLnByb3RvdHlwZS5fb25Nb3VzZVVwPWZ1bmN0aW9uKGUpe2lmKDA9PT1lLmJ1dHRvbil7dmFyIG89dGhpcy5fc3RhcnRQb3Mscj1pLm1vdXNlUG9zKHRoaXMuX2VsLGUpO3RoaXMuX2ZpbmlzaCgpLGkuc3VwcHJlc3NDbGljaygpLG8ueD09PXIueCYmby55PT09ci55P3RoaXMuX2ZpcmVFdmVudChcImJveHpvb21jYW5jZWxcIixlKTp0aGlzLl9tYXAuZml0U2NyZWVuQ29vcmRpbmF0ZXMobyxyLHRoaXMuX21hcC5nZXRCZWFyaW5nKCkse2xpbmVhcjohMH0pLmZpcmUobmV3IHQuRXZlbnQoXCJib3h6b29tZW5kXCIse29yaWdpbmFsRXZlbnQ6ZX0pKTt9fSxnby5wcm90b3R5cGUuX29uS2V5RG93bj1mdW5jdGlvbih0KXsyNz09PXQua2V5Q29kZSYmKHRoaXMuX2ZpbmlzaCgpLHRoaXMuX2ZpcmVFdmVudChcImJveHpvb21jYW5jZWxcIix0KSk7fSxnby5wcm90b3R5cGUuX2ZpbmlzaD1mdW5jdGlvbigpe3RoaXMuX2FjdGl2ZT0hMSx0LndpbmRvdy5kb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwibW91c2Vtb3ZlXCIsdGhpcy5fb25Nb3VzZU1vdmUsITEpLHQud2luZG93LmRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJrZXlkb3duXCIsdGhpcy5fb25LZXlEb3duLCExKSx0LndpbmRvdy5kb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwibW91c2V1cFwiLHRoaXMuX29uTW91c2VVcCwhMSksdGhpcy5fY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1jcm9zc2hhaXJcIiksdGhpcy5fYm94JiYoaS5yZW1vdmUodGhpcy5fYm94KSx0aGlzLl9ib3g9bnVsbCksaS5lbmFibGVEcmFnKCksZGVsZXRlIHRoaXMuX3N0YXJ0UG9zLGRlbGV0ZSB0aGlzLl9sYXN0UG9zO30sZ28ucHJvdG90eXBlLl9maXJlRXZlbnQ9ZnVuY3Rpb24oZSxpKXtyZXR1cm4gdGhpcy5fbWFwLmZpcmUobmV3IHQuRXZlbnQoZSx7b3JpZ2luYWxFdmVudDppfSkpfTt2YXIgdm89dC5iZXppZXIoMCwwLC4yNSwxKSx5bz1mdW5jdGlvbihlLGkpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWkuZWxlbWVudHx8ZS5nZXRDYW52YXNDb250YWluZXIoKSx0aGlzLl9zdGF0ZT1cImRpc2FibGVkXCIsdGhpcy5fYnV0dG9uPWkuYnV0dG9ufHxcInJpZ2h0XCIsdGhpcy5fYmVhcmluZ1NuYXA9aS5iZWFyaW5nU25hcHx8MCx0aGlzLl9waXRjaFdpdGhSb3RhdGU9ITEhPT1pLnBpdGNoV2l0aFJvdGF0ZSx0LmJpbmRBbGwoW1wib25Nb3VzZURvd25cIixcIl9vbk1vdXNlTW92ZVwiLFwiX29uTW91c2VVcFwiLFwiX29uQmx1clwiLFwiX29uRHJhZ0ZyYW1lXCJdLHRoaXMpO307eW8ucHJvdG90eXBlLmlzRW5hYmxlZD1mdW5jdGlvbigpe3JldHVybiBcImRpc2FibGVkXCIhPT10aGlzLl9zdGF0ZX0seW8ucHJvdG90eXBlLmlzQWN0aXZlPWZ1bmN0aW9uKCl7cmV0dXJuIFwiYWN0aXZlXCI9PT10aGlzLl9zdGF0ZX0seW8ucHJvdG90eXBlLmVuYWJsZT1mdW5jdGlvbigpe3RoaXMuaXNFbmFibGVkKCl8fCh0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIik7fSx5by5wcm90b3R5cGUuZGlzYWJsZT1mdW5jdGlvbigpe2lmKHRoaXMuaXNFbmFibGVkKCkpc3dpdGNoKHRoaXMuX3N0YXRlKXtjYXNlXCJhY3RpdmVcIjp0aGlzLl9zdGF0ZT1cImRpc2FibGVkXCIsdGhpcy5fdW5iaW5kKCksdGhpcy5fZGVhY3RpdmF0ZSgpLHRoaXMuX2ZpcmVFdmVudChcInJvdGF0ZWVuZFwiKSx0aGlzLl9waXRjaFdpdGhSb3RhdGUmJnRoaXMuX2ZpcmVFdmVudChcInBpdGNoZW5kXCIpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVlbmRcIik7YnJlYWs7Y2FzZVwicGVuZGluZ1wiOnRoaXMuX3N0YXRlPVwiZGlzYWJsZWRcIix0aGlzLl91bmJpbmQoKTticmVhaztkZWZhdWx0OnRoaXMuX3N0YXRlPVwiZGlzYWJsZWRcIjt9fSx5by5wcm90b3R5cGUub25Nb3VzZURvd249ZnVuY3Rpb24oZSl7aWYoXCJlbmFibGVkXCI9PT10aGlzLl9zdGF0ZSl7aWYoXCJyaWdodFwiPT09dGhpcy5fYnV0dG9uKXtpZih0aGlzLl9ldmVudEJ1dHRvbj1pLm1vdXNlQnV0dG9uKGUpLHRoaXMuX2V2ZW50QnV0dG9uIT09KGUuY3RybEtleT8wOjIpKXJldHVybn1lbHNle2lmKGUuY3RybEtleXx8MCE9PWkubW91c2VCdXR0b24oZSkpcmV0dXJuO3RoaXMuX2V2ZW50QnV0dG9uPTA7fWkuZGlzYWJsZURyYWcoKSx0LndpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwibW91c2Vtb3ZlXCIsdGhpcy5fb25Nb3VzZU1vdmUse2NhcHR1cmU6ITB9KSx0LndpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwibW91c2V1cFwiLHRoaXMuX29uTW91c2VVcCksdC53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImJsdXJcIix0aGlzLl9vbkJsdXIpLHRoaXMuX3N0YXRlPVwicGVuZGluZ1wiLHRoaXMuX2luZXJ0aWE9W1t0LmJyb3dzZXIubm93KCksdGhpcy5fbWFwLmdldEJlYXJpbmcoKV1dLHRoaXMuX3N0YXJ0UG9zPXRoaXMuX2xhc3RQb3M9aS5tb3VzZVBvcyh0aGlzLl9lbCxlKSx0aGlzLl9jZW50ZXI9dGhpcy5fbWFwLnRyYW5zZm9ybS5jZW50ZXJQb2ludCxlLnByZXZlbnREZWZhdWx0KCk7fX0seW8ucHJvdG90eXBlLl9vbk1vdXNlTW92ZT1mdW5jdGlvbih0KXt2YXIgZT1pLm1vdXNlUG9zKHRoaXMuX2VsLHQpO3RoaXMuX2xhc3RQb3MuZXF1YWxzKGUpfHwodGhpcy5fbGFzdE1vdmVFdmVudD10LHRoaXMuX2xhc3RQb3M9ZSxcInBlbmRpbmdcIj09PXRoaXMuX3N0YXRlJiYodGhpcy5fc3RhdGU9XCJhY3RpdmVcIix0aGlzLl9maXJlRXZlbnQoXCJyb3RhdGVzdGFydFwiLHQpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVzdGFydFwiLHQpLHRoaXMuX3BpdGNoV2l0aFJvdGF0ZSYmdGhpcy5fZmlyZUV2ZW50KFwicGl0Y2hzdGFydFwiLHQpKSx0aGlzLl9mcmFtZUlkfHwodGhpcy5fZnJhbWVJZD10aGlzLl9tYXAuX3JlcXVlc3RSZW5kZXJGcmFtZSh0aGlzLl9vbkRyYWdGcmFtZSkpKTt9LHlvLnByb3RvdHlwZS5fb25EcmFnRnJhbWU9ZnVuY3Rpb24oKXt0aGlzLl9mcmFtZUlkPW51bGw7dmFyIGU9dGhpcy5fbGFzdE1vdmVFdmVudDtpZihlKXt2YXIgaT10aGlzLl9tYXAudHJhbnNmb3JtLG89dGhpcy5fc3RhcnRQb3Mscj10aGlzLl9sYXN0UG9zLGE9LjgqKG8ueC1yLngpLG49LS41KihvLnktci55KSxzPWkuYmVhcmluZy1hLGw9aS5waXRjaC1uLGM9dGhpcy5faW5lcnRpYSx1PWNbYy5sZW5ndGgtMV07dGhpcy5fZHJhaW5JbmVydGlhQnVmZmVyKCksYy5wdXNoKFt0LmJyb3dzZXIubm93KCksdGhpcy5fbWFwLl9ub3JtYWxpemVCZWFyaW5nKHMsdVsxXSldKSxpLmJlYXJpbmc9cyx0aGlzLl9waXRjaFdpdGhSb3RhdGUmJih0aGlzLl9maXJlRXZlbnQoXCJwaXRjaFwiLGUpLGkucGl0Y2g9bCksdGhpcy5fZmlyZUV2ZW50KFwicm90YXRlXCIsZSksdGhpcy5fZmlyZUV2ZW50KFwibW92ZVwiLGUpLGRlbGV0ZSB0aGlzLl9sYXN0TW92ZUV2ZW50LHRoaXMuX3N0YXJ0UG9zPXRoaXMuX2xhc3RQb3M7fX0seW8ucHJvdG90eXBlLl9vbk1vdXNlVXA9ZnVuY3Rpb24odCl7aWYoaS5tb3VzZUJ1dHRvbih0KT09PXRoaXMuX2V2ZW50QnV0dG9uKXN3aXRjaCh0aGlzLl9zdGF0ZSl7Y2FzZVwiYWN0aXZlXCI6dGhpcy5fc3RhdGU9XCJlbmFibGVkXCIsaS5zdXBwcmVzc0NsaWNrKCksdGhpcy5fdW5iaW5kKCksdGhpcy5fZGVhY3RpdmF0ZSgpLHRoaXMuX2luZXJ0aWFsUm90YXRlKHQpO2JyZWFrO2Nhc2VcInBlbmRpbmdcIjp0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIix0aGlzLl91bmJpbmQoKTt9fSx5by5wcm90b3R5cGUuX29uQmx1cj1mdW5jdGlvbih0KXtzd2l0Y2godGhpcy5fc3RhdGUpe2Nhc2VcImFjdGl2ZVwiOnRoaXMuX3N0YXRlPVwiZW5hYmxlZFwiLHRoaXMuX3VuYmluZCgpLHRoaXMuX2RlYWN0aXZhdGUoKSx0aGlzLl9maXJlRXZlbnQoXCJyb3RhdGVlbmRcIix0KSx0aGlzLl9waXRjaFdpdGhSb3RhdGUmJnRoaXMuX2ZpcmVFdmVudChcInBpdGNoZW5kXCIsdCksdGhpcy5fZmlyZUV2ZW50KFwibW92ZWVuZFwiLHQpO2JyZWFrO2Nhc2VcInBlbmRpbmdcIjp0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIix0aGlzLl91bmJpbmQoKTt9fSx5by5wcm90b3R5cGUuX3VuYmluZD1mdW5jdGlvbigpe3Qud2luZG93LmRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIix0aGlzLl9vbk1vdXNlTW92ZSx7Y2FwdHVyZTohMH0pLHQud2luZG93LmRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZXVwXCIsdGhpcy5fb25Nb3VzZVVwKSx0LndpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwiYmx1clwiLHRoaXMuX29uQmx1ciksaS5lbmFibGVEcmFnKCk7fSx5by5wcm90b3R5cGUuX2RlYWN0aXZhdGU9ZnVuY3Rpb24oKXt0aGlzLl9mcmFtZUlkJiYodGhpcy5fbWFwLl9jYW5jZWxSZW5kZXJGcmFtZSh0aGlzLl9mcmFtZUlkKSx0aGlzLl9mcmFtZUlkPW51bGwpLGRlbGV0ZSB0aGlzLl9sYXN0TW92ZUV2ZW50LGRlbGV0ZSB0aGlzLl9zdGFydFBvcyxkZWxldGUgdGhpcy5fbGFzdFBvczt9LHlvLnByb3RvdHlwZS5faW5lcnRpYWxSb3RhdGU9ZnVuY3Rpb24odCl7dmFyIGU9dGhpczt0aGlzLl9maXJlRXZlbnQoXCJyb3RhdGVlbmRcIix0KSx0aGlzLl9kcmFpbkluZXJ0aWFCdWZmZXIoKTt2YXIgaT10aGlzLl9tYXAsbz1pLmdldEJlYXJpbmcoKSxyPXRoaXMuX2luZXJ0aWEsYT1mdW5jdGlvbigpe01hdGguYWJzKG8pPGUuX2JlYXJpbmdTbmFwP2kucmVzZXROb3J0aCh7bm9Nb3ZlU3RhcnQ6ITB9LHtvcmlnaW5hbEV2ZW50OnR9KTplLl9maXJlRXZlbnQoXCJtb3ZlZW5kXCIsdCksZS5fcGl0Y2hXaXRoUm90YXRlJiZlLl9maXJlRXZlbnQoXCJwaXRjaGVuZFwiLHQpO307aWYoci5sZW5ndGg8MilhKCk7ZWxzZXt2YXIgbj1yWzBdLHM9cltyLmxlbmd0aC0xXSxsPXJbci5sZW5ndGgtMl0sYz1pLl9ub3JtYWxpemVCZWFyaW5nKG8sbFsxXSksdT1zWzFdLW5bMV0saD11PDA/LTE6MSxwPShzWzBdLW5bMF0pLzFlMztpZigwIT09dSYmMCE9PXApe3ZhciBkPU1hdGguYWJzKHUqKC4yNS9wKSk7ZD4xODAmJihkPTE4MCk7dmFyIF89ZC8xODA7Yys9aCpkKihfLzIpLE1hdGguYWJzKGkuX25vcm1hbGl6ZUJlYXJpbmcoYywwKSk8dGhpcy5fYmVhcmluZ1NuYXAmJihjPWkuX25vcm1hbGl6ZUJlYXJpbmcoMCxjKSksaS5yb3RhdGVUbyhjLHtkdXJhdGlvbjoxZTMqXyxlYXNpbmc6dm8sbm9Nb3ZlU3RhcnQ6ITB9LHtvcmlnaW5hbEV2ZW50OnR9KTt9ZWxzZSBhKCk7fX0seW8ucHJvdG90eXBlLl9maXJlRXZlbnQ9ZnVuY3Rpb24oZSxpKXtyZXR1cm4gdGhpcy5fbWFwLmZpcmUobmV3IHQuRXZlbnQoZSxpP3tvcmlnaW5hbEV2ZW50Oml9Ont9KSl9LHlvLnByb3RvdHlwZS5fZHJhaW5JbmVydGlhQnVmZmVyPWZ1bmN0aW9uKCl7Zm9yKHZhciBlPXRoaXMuX2luZXJ0aWEsaT10LmJyb3dzZXIubm93KCk7ZS5sZW5ndGg+MCYmaS1lWzBdWzBdPjE2MDspZS5zaGlmdCgpO307dmFyIHhvPXQuYmV6aWVyKDAsMCwuMywxKSxibz1mdW5jdGlvbihlLGkpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWUuZ2V0Q2FudmFzQ29udGFpbmVyKCksdGhpcy5fc3RhdGU9XCJkaXNhYmxlZFwiLHRoaXMuX2NsaWNrVG9sZXJhbmNlPWkuY2xpY2tUb2xlcmFuY2V8fDEsdC5iaW5kQWxsKFtcIl9vbk1vdmVcIixcIl9vbk1vdXNlVXBcIixcIl9vblRvdWNoRW5kXCIsXCJfb25CbHVyXCIsXCJfb25EcmFnRnJhbWVcIl0sdGhpcyk7fTtiby5wcm90b3R5cGUuaXNFbmFibGVkPWZ1bmN0aW9uKCl7cmV0dXJuIFwiZGlzYWJsZWRcIiE9PXRoaXMuX3N0YXRlfSxiby5wcm90b3R5cGUuaXNBY3RpdmU9ZnVuY3Rpb24oKXtyZXR1cm4gXCJhY3RpdmVcIj09PXRoaXMuX3N0YXRlfSxiby5wcm90b3R5cGUuZW5hYmxlPWZ1bmN0aW9uKCl7dGhpcy5pc0VuYWJsZWQoKXx8KHRoaXMuX2VsLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC10b3VjaC1kcmFnLXBhblwiKSx0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIik7fSxiby5wcm90b3R5cGUuZGlzYWJsZT1mdW5jdGlvbigpe2lmKHRoaXMuaXNFbmFibGVkKCkpc3dpdGNoKHRoaXMuX2VsLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC10b3VjaC1kcmFnLXBhblwiKSx0aGlzLl9zdGF0ZSl7Y2FzZVwiYWN0aXZlXCI6dGhpcy5fc3RhdGU9XCJkaXNhYmxlZFwiLHRoaXMuX3VuYmluZCgpLHRoaXMuX2RlYWN0aXZhdGUoKSx0aGlzLl9maXJlRXZlbnQoXCJkcmFnZW5kXCIpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVlbmRcIik7YnJlYWs7Y2FzZVwicGVuZGluZ1wiOnRoaXMuX3N0YXRlPVwiZGlzYWJsZWRcIix0aGlzLl91bmJpbmQoKTticmVhaztkZWZhdWx0OnRoaXMuX3N0YXRlPVwiZGlzYWJsZWRcIjt9fSxiby5wcm90b3R5cGUub25Nb3VzZURvd249ZnVuY3Rpb24oZSl7XCJlbmFibGVkXCI9PT10aGlzLl9zdGF0ZSYmKGUuY3RybEtleXx8MCE9PWkubW91c2VCdXR0b24oZSl8fChpLmFkZEV2ZW50TGlzdGVuZXIodC53aW5kb3cuZG9jdW1lbnQsXCJtb3VzZW1vdmVcIix0aGlzLl9vbk1vdmUse2NhcHR1cmU6ITB9KSxpLmFkZEV2ZW50TGlzdGVuZXIodC53aW5kb3cuZG9jdW1lbnQsXCJtb3VzZXVwXCIsdGhpcy5fb25Nb3VzZVVwKSx0aGlzLl9zdGFydChlKSkpO30sYm8ucHJvdG90eXBlLm9uVG91Y2hTdGFydD1mdW5jdGlvbihlKXtcImVuYWJsZWRcIj09PXRoaXMuX3N0YXRlJiYoZS50b3VjaGVzLmxlbmd0aD4xfHwoaS5hZGRFdmVudExpc3RlbmVyKHQud2luZG93LmRvY3VtZW50LFwidG91Y2htb3ZlXCIsdGhpcy5fb25Nb3ZlLHtjYXB0dXJlOiEwLHBhc3NpdmU6ITF9KSxpLmFkZEV2ZW50TGlzdGVuZXIodC53aW5kb3cuZG9jdW1lbnQsXCJ0b3VjaGVuZFwiLHRoaXMuX29uVG91Y2hFbmQpLHRoaXMuX3N0YXJ0KGUpKSk7fSxiby5wcm90b3R5cGUuX3N0YXJ0PWZ1bmN0aW9uKGUpe3Qud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJibHVyXCIsdGhpcy5fb25CbHVyKSx0aGlzLl9zdGF0ZT1cInBlbmRpbmdcIix0aGlzLl9zdGFydFBvcz10aGlzLl9tb3VzZURvd25Qb3M9dGhpcy5fbGFzdFBvcz1pLm1vdXNlUG9zKHRoaXMuX2VsLGUpLHRoaXMuX2luZXJ0aWE9W1t0LmJyb3dzZXIubm93KCksdGhpcy5fc3RhcnRQb3NdXTt9LGJvLnByb3RvdHlwZS5fb25Nb3ZlPWZ1bmN0aW9uKGUpe2UucHJldmVudERlZmF1bHQoKTt2YXIgbz1pLm1vdXNlUG9zKHRoaXMuX2VsLGUpO3RoaXMuX2xhc3RQb3MuZXF1YWxzKG8pfHxcInBlbmRpbmdcIj09PXRoaXMuX3N0YXRlJiZvLmRpc3QodGhpcy5fbW91c2VEb3duUG9zKTx0aGlzLl9jbGlja1RvbGVyYW5jZXx8KHRoaXMuX2xhc3RNb3ZlRXZlbnQ9ZSx0aGlzLl9sYXN0UG9zPW8sdGhpcy5fZHJhaW5JbmVydGlhQnVmZmVyKCksdGhpcy5faW5lcnRpYS5wdXNoKFt0LmJyb3dzZXIubm93KCksdGhpcy5fbGFzdFBvc10pLFwicGVuZGluZ1wiPT09dGhpcy5fc3RhdGUmJih0aGlzLl9zdGF0ZT1cImFjdGl2ZVwiLHRoaXMuX2ZpcmVFdmVudChcImRyYWdzdGFydFwiLGUpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVzdGFydFwiLGUpKSx0aGlzLl9mcmFtZUlkfHwodGhpcy5fZnJhbWVJZD10aGlzLl9tYXAuX3JlcXVlc3RSZW5kZXJGcmFtZSh0aGlzLl9vbkRyYWdGcmFtZSkpKTt9LGJvLnByb3RvdHlwZS5fb25EcmFnRnJhbWU9ZnVuY3Rpb24oKXt0aGlzLl9mcmFtZUlkPW51bGw7dmFyIHQ9dGhpcy5fbGFzdE1vdmVFdmVudDtpZih0KXt2YXIgZT10aGlzLl9tYXAudHJhbnNmb3JtO2Uuc2V0TG9jYXRpb25BdFBvaW50KGUucG9pbnRMb2NhdGlvbih0aGlzLl9zdGFydFBvcyksdGhpcy5fbGFzdFBvcyksdGhpcy5fZmlyZUV2ZW50KFwiZHJhZ1wiLHQpLHRoaXMuX2ZpcmVFdmVudChcIm1vdmVcIix0KSx0aGlzLl9zdGFydFBvcz10aGlzLl9sYXN0UG9zLGRlbGV0ZSB0aGlzLl9sYXN0TW92ZUV2ZW50O319LGJvLnByb3RvdHlwZS5fb25Nb3VzZVVwPWZ1bmN0aW9uKHQpe2lmKDA9PT1pLm1vdXNlQnV0dG9uKHQpKXN3aXRjaCh0aGlzLl9zdGF0ZSl7Y2FzZVwiYWN0aXZlXCI6dGhpcy5fc3RhdGU9XCJlbmFibGVkXCIsaS5zdXBwcmVzc0NsaWNrKCksdGhpcy5fdW5iaW5kKCksdGhpcy5fZGVhY3RpdmF0ZSgpLHRoaXMuX2luZXJ0aWFsUGFuKHQpO2JyZWFrO2Nhc2VcInBlbmRpbmdcIjp0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIix0aGlzLl91bmJpbmQoKTt9fSxiby5wcm90b3R5cGUuX29uVG91Y2hFbmQ9ZnVuY3Rpb24odCl7c3dpdGNoKHRoaXMuX3N0YXRlKXtjYXNlXCJhY3RpdmVcIjp0aGlzLl9zdGF0ZT1cImVuYWJsZWRcIix0aGlzLl91bmJpbmQoKSx0aGlzLl9kZWFjdGl2YXRlKCksdGhpcy5faW5lcnRpYWxQYW4odCk7YnJlYWs7Y2FzZVwicGVuZGluZ1wiOnRoaXMuX3N0YXRlPVwiZW5hYmxlZFwiLHRoaXMuX3VuYmluZCgpO319LGJvLnByb3RvdHlwZS5fb25CbHVyPWZ1bmN0aW9uKHQpe3N3aXRjaCh0aGlzLl9zdGF0ZSl7Y2FzZVwiYWN0aXZlXCI6dGhpcy5fc3RhdGU9XCJlbmFibGVkXCIsdGhpcy5fdW5iaW5kKCksdGhpcy5fZGVhY3RpdmF0ZSgpLHRoaXMuX2ZpcmVFdmVudChcImRyYWdlbmRcIix0KSx0aGlzLl9maXJlRXZlbnQoXCJtb3ZlZW5kXCIsdCk7YnJlYWs7Y2FzZVwicGVuZGluZ1wiOnRoaXMuX3N0YXRlPVwiZW5hYmxlZFwiLHRoaXMuX3VuYmluZCgpO319LGJvLnByb3RvdHlwZS5fdW5iaW5kPWZ1bmN0aW9uKCl7aS5yZW1vdmVFdmVudExpc3RlbmVyKHQud2luZG93LmRvY3VtZW50LFwidG91Y2htb3ZlXCIsdGhpcy5fb25Nb3ZlLHtjYXB0dXJlOiEwLHBhc3NpdmU6ITF9KSxpLnJlbW92ZUV2ZW50TGlzdGVuZXIodC53aW5kb3cuZG9jdW1lbnQsXCJ0b3VjaGVuZFwiLHRoaXMuX29uVG91Y2hFbmQpLGkucmVtb3ZlRXZlbnRMaXN0ZW5lcih0LndpbmRvdy5kb2N1bWVudCxcIm1vdXNlbW92ZVwiLHRoaXMuX29uTW92ZSx7Y2FwdHVyZTohMH0pLGkucmVtb3ZlRXZlbnRMaXN0ZW5lcih0LndpbmRvdy5kb2N1bWVudCxcIm1vdXNldXBcIix0aGlzLl9vbk1vdXNlVXApLGkucmVtb3ZlRXZlbnRMaXN0ZW5lcih0LndpbmRvdyxcImJsdXJcIix0aGlzLl9vbkJsdXIpO30sYm8ucHJvdG90eXBlLl9kZWFjdGl2YXRlPWZ1bmN0aW9uKCl7dGhpcy5fZnJhbWVJZCYmKHRoaXMuX21hcC5fY2FuY2VsUmVuZGVyRnJhbWUodGhpcy5fZnJhbWVJZCksdGhpcy5fZnJhbWVJZD1udWxsKSxkZWxldGUgdGhpcy5fbGFzdE1vdmVFdmVudCxkZWxldGUgdGhpcy5fc3RhcnRQb3MsZGVsZXRlIHRoaXMuX21vdXNlRG93blBvcyxkZWxldGUgdGhpcy5fbGFzdFBvczt9LGJvLnByb3RvdHlwZS5faW5lcnRpYWxQYW49ZnVuY3Rpb24odCl7dGhpcy5fZmlyZUV2ZW50KFwiZHJhZ2VuZFwiLHQpLHRoaXMuX2RyYWluSW5lcnRpYUJ1ZmZlcigpO3ZhciBlPXRoaXMuX2luZXJ0aWE7aWYoZS5sZW5ndGg8Mil0aGlzLl9maXJlRXZlbnQoXCJtb3ZlZW5kXCIsdCk7ZWxzZXt2YXIgaT1lW2UubGVuZ3RoLTFdLG89ZVswXSxyPWlbMV0uc3ViKG9bMV0pLGE9KGlbMF0tb1swXSkvMWUzO2lmKDA9PT1hfHxpWzFdLmVxdWFscyhvWzFdKSl0aGlzLl9maXJlRXZlbnQoXCJtb3ZlZW5kXCIsdCk7ZWxzZXt2YXIgbj1yLm11bHQoLjMvYSkscz1uLm1hZygpO3M+MTQwMCYmKHM9MTQwMCxuLl91bml0KCkuX211bHQocykpO3ZhciBsPXMvNzUwLGM9bi5tdWx0KC1sLzIpO3RoaXMuX21hcC5wYW5CeShjLHtkdXJhdGlvbjoxZTMqbCxlYXNpbmc6eG8sbm9Nb3ZlU3RhcnQ6ITB9LHtvcmlnaW5hbEV2ZW50OnR9KTt9fX0sYm8ucHJvdG90eXBlLl9maXJlRXZlbnQ9ZnVuY3Rpb24oZSxpKXtyZXR1cm4gdGhpcy5fbWFwLmZpcmUobmV3IHQuRXZlbnQoZSxpP3tvcmlnaW5hbEV2ZW50Oml9Ont9KSl9LGJvLnByb3RvdHlwZS5fZHJhaW5JbmVydGlhQnVmZmVyPWZ1bmN0aW9uKCl7Zm9yKHZhciBlPXRoaXMuX2luZXJ0aWEsaT10LmJyb3dzZXIubm93KCk7ZS5sZW5ndGg+MCYmaS1lWzBdWzBdPjE2MDspZS5zaGlmdCgpO307dmFyIHdvPWZ1bmN0aW9uKGUpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWUuZ2V0Q2FudmFzQ29udGFpbmVyKCksdC5iaW5kQWxsKFtcIl9vbktleURvd25cIl0sdGhpcyk7fTtmdW5jdGlvbiBFbyh0KXtyZXR1cm4gdCooMi10KX13by5wcm90b3R5cGUuaXNFbmFibGVkPWZ1bmN0aW9uKCl7cmV0dXJuICEhdGhpcy5fZW5hYmxlZH0sd28ucHJvdG90eXBlLmVuYWJsZT1mdW5jdGlvbigpe3RoaXMuaXNFbmFibGVkKCl8fCh0aGlzLl9lbC5hZGRFdmVudExpc3RlbmVyKFwia2V5ZG93blwiLHRoaXMuX29uS2V5RG93biwhMSksdGhpcy5fZW5hYmxlZD0hMCk7fSx3by5wcm90b3R5cGUuZGlzYWJsZT1mdW5jdGlvbigpe3RoaXMuaXNFbmFibGVkKCkmJih0aGlzLl9lbC5yZW1vdmVFdmVudExpc3RlbmVyKFwia2V5ZG93blwiLHRoaXMuX29uS2V5RG93biksdGhpcy5fZW5hYmxlZD0hMSk7fSx3by5wcm90b3R5cGUuX29uS2V5RG93bj1mdW5jdGlvbih0KXtpZighKHQuYWx0S2V5fHx0LmN0cmxLZXl8fHQubWV0YUtleSkpe3ZhciBlPTAsaT0wLG89MCxyPTAsYT0wO3N3aXRjaCh0LmtleUNvZGUpe2Nhc2UgNjE6Y2FzZSAxMDc6Y2FzZSAxNzE6Y2FzZSAxODc6ZT0xO2JyZWFrO2Nhc2UgMTg5OmNhc2UgMTA5OmNhc2UgMTczOmU9LTE7YnJlYWs7Y2FzZSAzNzp0LnNoaWZ0S2V5P2k9LTE6KHQucHJldmVudERlZmF1bHQoKSxyPS0xKTticmVhaztjYXNlIDM5OnQuc2hpZnRLZXk/aT0xOih0LnByZXZlbnREZWZhdWx0KCkscj0xKTticmVhaztjYXNlIDM4OnQuc2hpZnRLZXk/bz0xOih0LnByZXZlbnREZWZhdWx0KCksYT0tMSk7YnJlYWs7Y2FzZSA0MDp0LnNoaWZ0S2V5P289LTE6KGE9MSx0LnByZXZlbnREZWZhdWx0KCkpO2JyZWFrO2RlZmF1bHQ6cmV0dXJufXZhciBuPXRoaXMuX21hcCxzPW4uZ2V0Wm9vbSgpLGw9e2R1cmF0aW9uOjMwMCxkZWxheUVuZEV2ZW50czo1MDAsZWFzaW5nOkVvLHpvb206ZT9NYXRoLnJvdW5kKHMpK2UqKHQuc2hpZnRLZXk/MjoxKTpzLGJlYXJpbmc6bi5nZXRCZWFyaW5nKCkrMTUqaSxwaXRjaDpuLmdldFBpdGNoKCkrMTAqbyxvZmZzZXQ6WzEwMCotciwxMDAqLWFdLGNlbnRlcjpuLmdldENlbnRlcigpfTtuLmVhc2VUbyhsLHtvcmlnaW5hbEV2ZW50OnR9KTt9fTt2YXIgVG89ZnVuY3Rpb24oZSl7dGhpcy5fbWFwPWUsdC5iaW5kQWxsKFtcIl9vbkRibENsaWNrXCIsXCJfb25ab29tRW5kXCJdLHRoaXMpO307VG8ucHJvdG90eXBlLmlzRW5hYmxlZD1mdW5jdGlvbigpe3JldHVybiAhIXRoaXMuX2VuYWJsZWR9LFRvLnByb3RvdHlwZS5pc0FjdGl2ZT1mdW5jdGlvbigpe3JldHVybiAhIXRoaXMuX2FjdGl2ZX0sVG8ucHJvdG90eXBlLmVuYWJsZT1mdW5jdGlvbigpe3RoaXMuaXNFbmFibGVkKCl8fCh0aGlzLl9lbmFibGVkPSEwKTt9LFRvLnByb3RvdHlwZS5kaXNhYmxlPWZ1bmN0aW9uKCl7dGhpcy5pc0VuYWJsZWQoKSYmKHRoaXMuX2VuYWJsZWQ9ITEpO30sVG8ucHJvdG90eXBlLm9uVG91Y2hTdGFydD1mdW5jdGlvbih0KXt2YXIgZT10aGlzO2lmKHRoaXMuaXNFbmFibGVkKCkmJiEodC5wb2ludHMubGVuZ3RoPjEpKWlmKHRoaXMuX3RhcHBlZCl7dmFyIGk9dC5wb2ludHNbMF0sbz10aGlzLl90YXBwZWRQb2ludDtpZihvJiZvLmRpc3QoaSk8PTMwKXt0Lm9yaWdpbmFsRXZlbnQucHJldmVudERlZmF1bHQoKTt2YXIgcj1mdW5jdGlvbigpe2UuX3RhcHBlZCYmZS5fem9vbSh0KSxlLl9tYXAub2ZmKFwidG91Y2hjYW5jZWxcIixhKSxlLl9yZXNldFRhcHBlZCgpO30sYT1mdW5jdGlvbigpe2UuX21hcC5vZmYoXCJ0b3VjaGVuZFwiLHIpLGUuX3Jlc2V0VGFwcGVkKCk7fTt0aGlzLl9tYXAub25jZShcInRvdWNoZW5kXCIsciksdGhpcy5fbWFwLm9uY2UoXCJ0b3VjaGNhbmNlbFwiLGEpO31lbHNlIHRoaXMuX3Jlc2V0VGFwcGVkKCk7fWVsc2UgdGhpcy5fdGFwcGVkUG9pbnQ9dC5wb2ludHNbMF0sdGhpcy5fdGFwcGVkPXNldFRpbWVvdXQoZnVuY3Rpb24oKXtlLl90YXBwZWQ9bnVsbCxlLl90YXBwZWRQb2ludD1udWxsO30sMzAwKTt9LFRvLnByb3RvdHlwZS5fcmVzZXRUYXBwZWQ9ZnVuY3Rpb24oKXtjbGVhclRpbWVvdXQodGhpcy5fdGFwcGVkKSx0aGlzLl90YXBwZWQ9bnVsbCx0aGlzLl90YXBwZWRQb2ludD1udWxsO30sVG8ucHJvdG90eXBlLm9uRGJsQ2xpY2s9ZnVuY3Rpb24odCl7dGhpcy5pc0VuYWJsZWQoKSYmKHQub3JpZ2luYWxFdmVudC5wcmV2ZW50RGVmYXVsdCgpLHRoaXMuX3pvb20odCkpO30sVG8ucHJvdG90eXBlLl96b29tPWZ1bmN0aW9uKHQpe3RoaXMuX2FjdGl2ZT0hMCx0aGlzLl9tYXAub24oXCJ6b29tZW5kXCIsdGhpcy5fb25ab29tRW5kKSx0aGlzLl9tYXAuem9vbVRvKHRoaXMuX21hcC5nZXRab29tKCkrKHQub3JpZ2luYWxFdmVudC5zaGlmdEtleT8tMToxKSx7YXJvdW5kOnQubG5nTGF0fSx0KTt9LFRvLnByb3RvdHlwZS5fb25ab29tRW5kPWZ1bmN0aW9uKCl7dGhpcy5fYWN0aXZlPSExLHRoaXMuX21hcC5vZmYoXCJ6b29tZW5kXCIsdGhpcy5fb25ab29tRW5kKTt9O3ZhciBJbz10LmJlemllcigwLDAsLjE1LDEpLENvPWZ1bmN0aW9uKGUpe3RoaXMuX21hcD1lLHRoaXMuX2VsPWUuZ2V0Q2FudmFzQ29udGFpbmVyKCksdC5iaW5kQWxsKFtcIl9vbk1vdmVcIixcIl9vbkVuZFwiLFwiX29uVG91Y2hGcmFtZVwiXSx0aGlzKTt9O0NvLnByb3RvdHlwZS5pc0VuYWJsZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gISF0aGlzLl9lbmFibGVkfSxDby5wcm90b3R5cGUuZW5hYmxlPWZ1bmN0aW9uKHQpe3RoaXMuaXNFbmFibGVkKCl8fCh0aGlzLl9lbC5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtdG91Y2gtem9vbS1yb3RhdGVcIiksdGhpcy5fZW5hYmxlZD0hMCx0aGlzLl9hcm91bmRDZW50ZXI9ISF0JiZcImNlbnRlclwiPT09dC5hcm91bmQpO30sQ28ucHJvdG90eXBlLmRpc2FibGU9ZnVuY3Rpb24oKXt0aGlzLmlzRW5hYmxlZCgpJiYodGhpcy5fZWwuY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLXRvdWNoLXpvb20tcm90YXRlXCIpLHRoaXMuX2VuYWJsZWQ9ITEpO30sQ28ucHJvdG90eXBlLmRpc2FibGVSb3RhdGlvbj1mdW5jdGlvbigpe3RoaXMuX3JvdGF0aW9uRGlzYWJsZWQ9ITA7fSxDby5wcm90b3R5cGUuZW5hYmxlUm90YXRpb249ZnVuY3Rpb24oKXt0aGlzLl9yb3RhdGlvbkRpc2FibGVkPSExO30sQ28ucHJvdG90eXBlLm9uU3RhcnQ9ZnVuY3Rpb24oZSl7aWYodGhpcy5pc0VuYWJsZWQoKSYmMj09PWUudG91Y2hlcy5sZW5ndGgpe3ZhciBvPWkubW91c2VQb3ModGhpcy5fZWwsZS50b3VjaGVzWzBdKSxyPWkubW91c2VQb3ModGhpcy5fZWwsZS50b3VjaGVzWzFdKSxhPW8uYWRkKHIpLmRpdigyKTt0aGlzLl9zdGFydFZlYz1vLnN1YihyKSx0aGlzLl9zdGFydEFyb3VuZD10aGlzLl9tYXAudHJhbnNmb3JtLnBvaW50TG9jYXRpb24oYSksdGhpcy5fZ2VzdHVyZUludGVudD12b2lkIDAsdGhpcy5faW5lcnRpYT1bXSxpLmFkZEV2ZW50TGlzdGVuZXIodC53aW5kb3cuZG9jdW1lbnQsXCJ0b3VjaG1vdmVcIix0aGlzLl9vbk1vdmUse3Bhc3NpdmU6ITF9KSxpLmFkZEV2ZW50TGlzdGVuZXIodC53aW5kb3cuZG9jdW1lbnQsXCJ0b3VjaGVuZFwiLHRoaXMuX29uRW5kKTt9fSxDby5wcm90b3R5cGUuX2dldFRvdWNoRXZlbnREYXRhPWZ1bmN0aW9uKHQpe3ZhciBlPWkubW91c2VQb3ModGhpcy5fZWwsdC50b3VjaGVzWzBdKSxvPWkubW91c2VQb3ModGhpcy5fZWwsdC50b3VjaGVzWzFdKSxyPWUuc3ViKG8pO3JldHVybiB7dmVjOnIsY2VudGVyOmUuYWRkKG8pLmRpdigyKSxzY2FsZTpyLm1hZygpL3RoaXMuX3N0YXJ0VmVjLm1hZygpLGJlYXJpbmc6dGhpcy5fcm90YXRpb25EaXNhYmxlZD8wOjE4MCpyLmFuZ2xlV2l0aCh0aGlzLl9zdGFydFZlYykvTWF0aC5QSX19LENvLnByb3RvdHlwZS5fb25Nb3ZlPWZ1bmN0aW9uKGUpe2lmKDI9PT1lLnRvdWNoZXMubGVuZ3RoKXt2YXIgaT10aGlzLl9nZXRUb3VjaEV2ZW50RGF0YShlKSxvPWkudmVjLHI9aS5zY2FsZSxhPWkuYmVhcmluZztpZighdGhpcy5fZ2VzdHVyZUludGVudCl7dmFyIG49dGhpcy5fcm90YXRpb25EaXNhYmxlZCYmMSE9PXJ8fE1hdGguYWJzKDEtcik+LjE1O01hdGguYWJzKGEpPjEwP3RoaXMuX2dlc3R1cmVJbnRlbnQ9XCJyb3RhdGVcIjpuJiYodGhpcy5fZ2VzdHVyZUludGVudD1cInpvb21cIiksdGhpcy5fZ2VzdHVyZUludGVudCYmKHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KHRoaXMuX2dlc3R1cmVJbnRlbnQrXCJzdGFydFwiLHtvcmlnaW5hbEV2ZW50OmV9KSksdGhpcy5fbWFwLmZpcmUobmV3IHQuRXZlbnQoXCJtb3Zlc3RhcnRcIix7b3JpZ2luYWxFdmVudDplfSkpLHRoaXMuX3N0YXJ0VmVjPW8pO310aGlzLl9sYXN0VG91Y2hFdmVudD1lLHRoaXMuX2ZyYW1lSWR8fCh0aGlzLl9mcmFtZUlkPXRoaXMuX21hcC5fcmVxdWVzdFJlbmRlckZyYW1lKHRoaXMuX29uVG91Y2hGcmFtZSkpLGUucHJldmVudERlZmF1bHQoKTt9fSxDby5wcm90b3R5cGUuX29uVG91Y2hGcmFtZT1mdW5jdGlvbigpe3RoaXMuX2ZyYW1lSWQ9bnVsbDt2YXIgZT10aGlzLl9nZXN0dXJlSW50ZW50O2lmKGUpe3ZhciBpPXRoaXMuX21hcC50cmFuc2Zvcm07dGhpcy5fc3RhcnRTY2FsZXx8KHRoaXMuX3N0YXJ0U2NhbGU9aS5zY2FsZSx0aGlzLl9zdGFydEJlYXJpbmc9aS5iZWFyaW5nKTt2YXIgbz10aGlzLl9nZXRUb3VjaEV2ZW50RGF0YSh0aGlzLl9sYXN0VG91Y2hFdmVudCkscj1vLmNlbnRlcixhPW8uYmVhcmluZyxuPW8uc2NhbGUscz1pLnBvaW50TG9jYXRpb24ociksbD1pLmxvY2F0aW9uUG9pbnQocyk7XCJyb3RhdGVcIj09PWUmJihpLmJlYXJpbmc9dGhpcy5fc3RhcnRCZWFyaW5nK2EpLGkuem9vbT1pLnNjYWxlWm9vbSh0aGlzLl9zdGFydFNjYWxlKm4pLGkuc2V0TG9jYXRpb25BdFBvaW50KHRoaXMuX3N0YXJ0QXJvdW5kLGwpLHRoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KGUse29yaWdpbmFsRXZlbnQ6dGhpcy5fbGFzdFRvdWNoRXZlbnR9KSksdGhpcy5fbWFwLmZpcmUobmV3IHQuRXZlbnQoXCJtb3ZlXCIse29yaWdpbmFsRXZlbnQ6dGhpcy5fbGFzdFRvdWNoRXZlbnR9KSksdGhpcy5fZHJhaW5JbmVydGlhQnVmZmVyKCksdGhpcy5faW5lcnRpYS5wdXNoKFt0LmJyb3dzZXIubm93KCksbixyXSk7fX0sQ28ucHJvdG90eXBlLl9vbkVuZD1mdW5jdGlvbihlKXtpLnJlbW92ZUV2ZW50TGlzdGVuZXIodC53aW5kb3cuZG9jdW1lbnQsXCJ0b3VjaG1vdmVcIix0aGlzLl9vbk1vdmUse3Bhc3NpdmU6ITF9KSxpLnJlbW92ZUV2ZW50TGlzdGVuZXIodC53aW5kb3cuZG9jdW1lbnQsXCJ0b3VjaGVuZFwiLHRoaXMuX29uRW5kKTt2YXIgbz10aGlzLl9nZXN0dXJlSW50ZW50LHI9dGhpcy5fc3RhcnRTY2FsZTtpZih0aGlzLl9mcmFtZUlkJiYodGhpcy5fbWFwLl9jYW5jZWxSZW5kZXJGcmFtZSh0aGlzLl9mcmFtZUlkKSx0aGlzLl9mcmFtZUlkPW51bGwpLGRlbGV0ZSB0aGlzLl9nZXN0dXJlSW50ZW50LGRlbGV0ZSB0aGlzLl9zdGFydFNjYWxlLGRlbGV0ZSB0aGlzLl9zdGFydEJlYXJpbmcsZGVsZXRlIHRoaXMuX2xhc3RUb3VjaEV2ZW50LG8pe3RoaXMuX21hcC5maXJlKG5ldyB0LkV2ZW50KG8rXCJlbmRcIix7b3JpZ2luYWxFdmVudDplfSkpLHRoaXMuX2RyYWluSW5lcnRpYUJ1ZmZlcigpO3ZhciBhPXRoaXMuX2luZXJ0aWEsbj10aGlzLl9tYXA7aWYoYS5sZW5ndGg8MiluLnNuYXBUb05vcnRoKHt9LHtvcmlnaW5hbEV2ZW50OmV9KTtlbHNle3ZhciBzPWFbYS5sZW5ndGgtMV0sbD1hWzBdLGM9bi50cmFuc2Zvcm0uc2NhbGVab29tKHIqc1sxXSksdT1uLnRyYW5zZm9ybS5zY2FsZVpvb20ocipsWzFdKSxoPWMtdSxwPShzWzBdLWxbMF0pLzFlMyxkPXNbMl07aWYoMCE9PXAmJmMhPT11KXt2YXIgXz0uMTUqaC9wO01hdGguYWJzKF8pPjIuNSYmKF89Xz4wPzIuNTotMi41KTt2YXIgZj0xZTMqTWF0aC5hYnMoXy8oMTIqLjE1KSksbT1jK18qZi8yZTM7bTwwJiYobT0wKSxuLmVhc2VUbyh7em9vbTptLGR1cmF0aW9uOmYsZWFzaW5nOklvLGFyb3VuZDp0aGlzLl9hcm91bmRDZW50ZXI/bi5nZXRDZW50ZXIoKTpuLnVucHJvamVjdChkKSxub01vdmVTdGFydDohMH0se29yaWdpbmFsRXZlbnQ6ZX0pO31lbHNlIG4uc25hcFRvTm9ydGgoe30se29yaWdpbmFsRXZlbnQ6ZX0pO319fSxDby5wcm90b3R5cGUuX2RyYWluSW5lcnRpYUJ1ZmZlcj1mdW5jdGlvbigpe2Zvcih2YXIgZT10aGlzLl9pbmVydGlhLGk9dC5icm93c2VyLm5vdygpO2UubGVuZ3RoPjImJmktZVswXVswXT4xNjA7KWUuc2hpZnQoKTt9O3ZhciBTbz17c2Nyb2xsWm9vbTptbyxib3hab29tOmdvLGRyYWdSb3RhdGU6eW8sZHJhZ1BhbjpibyxrZXlib2FyZDp3byxkb3VibGVDbGlja1pvb206VG8sdG91Y2hab29tUm90YXRlOkNvfTt2YXIgUG89ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gaShpLG8pe2UuY2FsbCh0aGlzKSx0aGlzLl9tb3Zpbmc9ITEsdGhpcy5fem9vbWluZz0hMSx0aGlzLnRyYW5zZm9ybT1pLHRoaXMuX2JlYXJpbmdTbmFwPW8uYmVhcmluZ1NuYXAsdC5iaW5kQWxsKFtcIl9yZW5kZXJGcmFtZUNhbGxiYWNrXCJdLHRoaXMpO31yZXR1cm4gZSYmKGkuX19wcm90b19fPWUpLGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLGkucHJvdG90eXBlLmNvbnN0cnVjdG9yPWksaS5wcm90b3R5cGUuZ2V0Q2VudGVyPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyB0LkxuZ0xhdCh0aGlzLnRyYW5zZm9ybS5jZW50ZXIubG5nLHRoaXMudHJhbnNmb3JtLmNlbnRlci5sYXQpfSxpLnByb3RvdHlwZS5zZXRDZW50ZXI9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5qdW1wVG8oe2NlbnRlcjp0fSxlKX0saS5wcm90b3R5cGUucGFuQnk9ZnVuY3Rpb24oZSxpLG8pe3JldHVybiBlPXQuUG9pbnQuY29udmVydChlKS5tdWx0KC0xKSx0aGlzLnBhblRvKHRoaXMudHJhbnNmb3JtLmNlbnRlcix0LmV4dGVuZCh7b2Zmc2V0OmV9LGkpLG8pfSxpLnByb3RvdHlwZS5wYW5Ubz1mdW5jdGlvbihlLGksbyl7cmV0dXJuIHRoaXMuZWFzZVRvKHQuZXh0ZW5kKHtjZW50ZXI6ZX0saSksbyl9LGkucHJvdG90eXBlLmdldFpvb209ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50cmFuc2Zvcm0uem9vbX0saS5wcm90b3R5cGUuc2V0Wm9vbT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmp1bXBUbyh7em9vbTp0fSxlKSx0aGlzfSxpLnByb3RvdHlwZS56b29tVG89ZnVuY3Rpb24oZSxpLG8pe3JldHVybiB0aGlzLmVhc2VUbyh0LmV4dGVuZCh7em9vbTplfSxpKSxvKX0saS5wcm90b3R5cGUuem9vbUluPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuem9vbVRvKHRoaXMuZ2V0Wm9vbSgpKzEsdCxlKSx0aGlzfSxpLnByb3RvdHlwZS56b29tT3V0PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuem9vbVRvKHRoaXMuZ2V0Wm9vbSgpLTEsdCxlKSx0aGlzfSxpLnByb3RvdHlwZS5nZXRCZWFyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLmJlYXJpbmd9LGkucHJvdG90eXBlLnNldEJlYXJpbmc9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5qdW1wVG8oe2JlYXJpbmc6dH0sZSksdGhpc30saS5wcm90b3R5cGUucm90YXRlVG89ZnVuY3Rpb24oZSxpLG8pe3JldHVybiB0aGlzLmVhc2VUbyh0LmV4dGVuZCh7YmVhcmluZzplfSxpKSxvKX0saS5wcm90b3R5cGUucmVzZXROb3J0aD1mdW5jdGlvbihlLGkpe3JldHVybiB0aGlzLnJvdGF0ZVRvKDAsdC5leHRlbmQoe2R1cmF0aW9uOjFlM30sZSksaSksdGhpc30saS5wcm90b3R5cGUuc25hcFRvTm9ydGg9ZnVuY3Rpb24odCxlKXtyZXR1cm4gTWF0aC5hYnModGhpcy5nZXRCZWFyaW5nKCkpPHRoaXMuX2JlYXJpbmdTbmFwP3RoaXMucmVzZXROb3J0aCh0LGUpOnRoaXN9LGkucHJvdG90eXBlLmdldFBpdGNoPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLnBpdGNofSxpLnByb3RvdHlwZS5zZXRQaXRjaD1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmp1bXBUbyh7cGl0Y2g6dH0sZSksdGhpc30saS5wcm90b3R5cGUuY2FtZXJhRm9yQm91bmRzPWZ1bmN0aW9uKGUsaSl7cmV0dXJuIGU9dC5MbmdMYXRCb3VuZHMuY29udmVydChlKSx0aGlzLl9jYW1lcmFGb3JCb3hBbmRCZWFyaW5nKGUuZ2V0Tm9ydGhXZXN0KCksZS5nZXRTb3V0aEVhc3QoKSwwLGkpfSxpLnByb3RvdHlwZS5fY2FtZXJhRm9yQm94QW5kQmVhcmluZz1mdW5jdGlvbihlLGksbyxyKXtpZihcIm51bWJlclwiPT10eXBlb2Yocj10LmV4dGVuZCh7cGFkZGluZzp7dG9wOjAsYm90dG9tOjAscmlnaHQ6MCxsZWZ0OjB9LG9mZnNldDpbMCwwXSxtYXhab29tOnRoaXMudHJhbnNmb3JtLm1heFpvb219LHIpKS5wYWRkaW5nKXt2YXIgYT1yLnBhZGRpbmc7ci5wYWRkaW5nPXt0b3A6YSxib3R0b206YSxyaWdodDphLGxlZnQ6YX07fWlmKHQuZGVlcEVxdWFsKE9iamVjdC5rZXlzKHIucGFkZGluZykuc29ydChmdW5jdGlvbih0LGUpe3JldHVybiB0PGU/LTE6dD5lPzE6MH0pLFtcImJvdHRvbVwiLFwibGVmdFwiLFwicmlnaHRcIixcInRvcFwiXSkpe3ZhciBuPXRoaXMudHJhbnNmb3JtLHM9bi5wcm9qZWN0KHQuTG5nTGF0LmNvbnZlcnQoZSkpLGw9bi5wcm9qZWN0KHQuTG5nTGF0LmNvbnZlcnQoaSkpLGM9cy5yb3RhdGUoLW8qTWF0aC5QSS8xODApLHU9bC5yb3RhdGUoLW8qTWF0aC5QSS8xODApLGg9bmV3IHQuUG9pbnQoTWF0aC5tYXgoYy54LHUueCksTWF0aC5tYXgoYy55LHUueSkpLHA9bmV3IHQuUG9pbnQoTWF0aC5taW4oYy54LHUueCksTWF0aC5taW4oYy55LHUueSkpLGQ9aC5zdWIocCksXz0obi53aWR0aC1yLnBhZGRpbmcubGVmdC1yLnBhZGRpbmcucmlnaHQpL2QueCxmPShuLmhlaWdodC1yLnBhZGRpbmcudG9wLXIucGFkZGluZy5ib3R0b20pL2QueTtpZighKGY8MHx8XzwwKSl7dmFyIG09TWF0aC5taW4obi5zY2FsZVpvb20obi5zY2FsZSpNYXRoLm1pbihfLGYpKSxyLm1heFpvb20pLGc9dC5Qb2ludC5jb252ZXJ0KHIub2Zmc2V0KSx2PShyLnBhZGRpbmcubGVmdC1yLnBhZGRpbmcucmlnaHQpLzIseT0oci5wYWRkaW5nLnRvcC1yLnBhZGRpbmcuYm90dG9tKS8yLHg9bmV3IHQuUG9pbnQoZy54K3YsZy55K3kpLm11bHQobi5zY2FsZS9uLnpvb21TY2FsZShtKSk7cmV0dXJuIHtjZW50ZXI6bi51bnByb2plY3Qocy5hZGQobCkuZGl2KDIpLnN1Yih4KSksem9vbTptLGJlYXJpbmc6b319dC53YXJuT25jZShcIk1hcCBjYW5ub3QgZml0IHdpdGhpbiBjYW52YXMgd2l0aCB0aGUgZ2l2ZW4gYm91bmRzLCBwYWRkaW5nLCBhbmQvb3Igb2Zmc2V0LlwiKTt9ZWxzZSB0Lndhcm5PbmNlKFwib3B0aW9ucy5wYWRkaW5nIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXIsIG9yIGFuIE9iamVjdCB3aXRoIGtleXMgJ2JvdHRvbScsICdsZWZ0JywgJ3JpZ2h0JywgJ3RvcCdcIik7fSxpLnByb3RvdHlwZS5maXRCb3VuZHM9ZnVuY3Rpb24odCxlLGkpe3JldHVybiB0aGlzLl9maXRJbnRlcm5hbCh0aGlzLmNhbWVyYUZvckJvdW5kcyh0LGUpLGUsaSl9LGkucHJvdG90eXBlLmZpdFNjcmVlbkNvb3JkaW5hdGVzPWZ1bmN0aW9uKGUsaSxvLHIsYSl7cmV0dXJuIHRoaXMuX2ZpdEludGVybmFsKHRoaXMuX2NhbWVyYUZvckJveEFuZEJlYXJpbmcodGhpcy50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbih0LlBvaW50LmNvbnZlcnQoZSkpLHRoaXMudHJhbnNmb3JtLnBvaW50TG9jYXRpb24odC5Qb2ludC5jb252ZXJ0KGkpKSxvLHIpLHIsYSl9LGkucHJvdG90eXBlLl9maXRJbnRlcm5hbD1mdW5jdGlvbihlLGksbyl7cmV0dXJuIGU/KGk9dC5leHRlbmQoZSxpKSkubGluZWFyP3RoaXMuZWFzZVRvKGksbyk6dGhpcy5mbHlUbyhpLG8pOnRoaXN9LGkucHJvdG90eXBlLmp1bXBUbz1mdW5jdGlvbihlLGkpe3RoaXMuc3RvcCgpO3ZhciBvPXRoaXMudHJhbnNmb3JtLHI9ITEsYT0hMSxuPSExO3JldHVybiBcInpvb21cImluIGUmJm8uem9vbSE9PStlLnpvb20mJihyPSEwLG8uem9vbT0rZS56b29tKSx2b2lkIDAhPT1lLmNlbnRlciYmKG8uY2VudGVyPXQuTG5nTGF0LmNvbnZlcnQoZS5jZW50ZXIpKSxcImJlYXJpbmdcImluIGUmJm8uYmVhcmluZyE9PStlLmJlYXJpbmcmJihhPSEwLG8uYmVhcmluZz0rZS5iZWFyaW5nKSxcInBpdGNoXCJpbiBlJiZvLnBpdGNoIT09K2UucGl0Y2gmJihuPSEwLG8ucGl0Y2g9K2UucGl0Y2gpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcIm1vdmVzdGFydFwiLGkpKS5maXJlKG5ldyB0LkV2ZW50KFwibW92ZVwiLGkpKSxyJiZ0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJ6b29tc3RhcnRcIixpKSkuZmlyZShuZXcgdC5FdmVudChcInpvb21cIixpKSkuZmlyZShuZXcgdC5FdmVudChcInpvb21lbmRcIixpKSksYSYmdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwicm90YXRlc3RhcnRcIixpKSkuZmlyZShuZXcgdC5FdmVudChcInJvdGF0ZVwiLGkpKS5maXJlKG5ldyB0LkV2ZW50KFwicm90YXRlZW5kXCIsaSkpLG4mJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInBpdGNoc3RhcnRcIixpKSkuZmlyZShuZXcgdC5FdmVudChcInBpdGNoXCIsaSkpLmZpcmUobmV3IHQuRXZlbnQoXCJwaXRjaGVuZFwiLGkpKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJtb3ZlZW5kXCIsaSkpfSxpLnByb3RvdHlwZS5lYXNlVG89ZnVuY3Rpb24oZSxpKXt2YXIgbz10aGlzO3RoaXMuc3RvcCgpLCExPT09KGU9dC5leHRlbmQoe29mZnNldDpbMCwwXSxkdXJhdGlvbjo1MDAsZWFzaW5nOnQuZWFzZX0sZSkpLmFuaW1hdGUmJihlLmR1cmF0aW9uPTApO3ZhciByPXRoaXMudHJhbnNmb3JtLGE9dGhpcy5nZXRab29tKCksbj10aGlzLmdldEJlYXJpbmcoKSxzPXRoaXMuZ2V0UGl0Y2goKSxsPVwiem9vbVwiaW4gZT8rZS56b29tOmEsYz1cImJlYXJpbmdcImluIGU/dGhpcy5fbm9ybWFsaXplQmVhcmluZyhlLmJlYXJpbmcsbik6bix1PVwicGl0Y2hcImluIGU/K2UucGl0Y2g6cyxoPXIuY2VudGVyUG9pbnQuYWRkKHQuUG9pbnQuY29udmVydChlLm9mZnNldCkpLHA9ci5wb2ludExvY2F0aW9uKGgpLGQ9dC5MbmdMYXQuY29udmVydChlLmNlbnRlcnx8cCk7dGhpcy5fbm9ybWFsaXplQ2VudGVyKGQpO3ZhciBfLGYsbT1yLnByb2plY3QocCksZz1yLnByb2plY3QoZCkuc3ViKG0pLHY9ci56b29tU2NhbGUobC1hKTtyZXR1cm4gZS5hcm91bmQmJihfPXQuTG5nTGF0LmNvbnZlcnQoZS5hcm91bmQpLGY9ci5sb2NhdGlvblBvaW50KF8pKSx0aGlzLl96b29taW5nPWwhPT1hLHRoaXMuX3JvdGF0aW5nPW4hPT1jLHRoaXMuX3BpdGNoaW5nPXUhPT1zLHRoaXMuX3ByZXBhcmVFYXNlKGksZS5ub01vdmVTdGFydCksY2xlYXJUaW1lb3V0KHRoaXMuX2Vhc2VFbmRUaW1lb3V0SUQpLHRoaXMuX2Vhc2UoZnVuY3Rpb24oZSl7aWYoby5fem9vbWluZyYmKHIuem9vbT10Lm51bWJlcihhLGwsZSkpLG8uX3JvdGF0aW5nJiYoci5iZWFyaW5nPXQubnVtYmVyKG4sYyxlKSksby5fcGl0Y2hpbmcmJihyLnBpdGNoPXQubnVtYmVyKHMsdSxlKSksXylyLnNldExvY2F0aW9uQXRQb2ludChfLGYpO2Vsc2V7dmFyIHA9ci56b29tU2NhbGUoci56b29tLWEpLGQ9bD5hP01hdGgubWluKDIsdik6TWF0aC5tYXgoLjUsdikseT1NYXRoLnBvdyhkLDEtZSkseD1yLnVucHJvamVjdChtLmFkZChnLm11bHQoZSp5KSkubXVsdChwKSk7ci5zZXRMb2NhdGlvbkF0UG9pbnQoci5yZW5kZXJXb3JsZENvcGllcz94LndyYXAoKTp4LGgpO31vLl9maXJlTW92ZUV2ZW50cyhpKTt9LGZ1bmN0aW9uKCl7ZS5kZWxheUVuZEV2ZW50cz9vLl9lYXNlRW5kVGltZW91dElEPXNldFRpbWVvdXQoZnVuY3Rpb24oKXtyZXR1cm4gby5fYWZ0ZXJFYXNlKGkpfSxlLmRlbGF5RW5kRXZlbnRzKTpvLl9hZnRlckVhc2UoaSk7fSxlKSx0aGlzfSxpLnByb3RvdHlwZS5fcHJlcGFyZUVhc2U9ZnVuY3Rpb24oZSxpKXt0aGlzLl9tb3Zpbmc9ITAsaXx8dGhpcy5maXJlKG5ldyB0LkV2ZW50KFwibW92ZXN0YXJ0XCIsZSkpLHRoaXMuX3pvb21pbmcmJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInpvb21zdGFydFwiLGUpKSx0aGlzLl9yb3RhdGluZyYmdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwicm90YXRlc3RhcnRcIixlKSksdGhpcy5fcGl0Y2hpbmcmJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInBpdGNoc3RhcnRcIixlKSk7fSxpLnByb3RvdHlwZS5fZmlyZU1vdmVFdmVudHM9ZnVuY3Rpb24oZSl7dGhpcy5maXJlKG5ldyB0LkV2ZW50KFwibW92ZVwiLGUpKSx0aGlzLl96b29taW5nJiZ0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJ6b29tXCIsZSkpLHRoaXMuX3JvdGF0aW5nJiZ0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJyb3RhdGVcIixlKSksdGhpcy5fcGl0Y2hpbmcmJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInBpdGNoXCIsZSkpO30saS5wcm90b3R5cGUuX2FmdGVyRWFzZT1mdW5jdGlvbihlKXt2YXIgaT10aGlzLl96b29taW5nLG89dGhpcy5fcm90YXRpbmcscj10aGlzLl9waXRjaGluZzt0aGlzLl9tb3Zpbmc9ITEsdGhpcy5fem9vbWluZz0hMSx0aGlzLl9yb3RhdGluZz0hMSx0aGlzLl9waXRjaGluZz0hMSxpJiZ0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJ6b29tZW5kXCIsZSkpLG8mJnRoaXMuZmlyZShuZXcgdC5FdmVudChcInJvdGF0ZWVuZFwiLGUpKSxyJiZ0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJwaXRjaGVuZFwiLGUpKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJtb3ZlZW5kXCIsZSkpO30saS5wcm90b3R5cGUuZmx5VG89ZnVuY3Rpb24oZSxpKXt2YXIgbz10aGlzO3RoaXMuc3RvcCgpLGU9dC5leHRlbmQoe29mZnNldDpbMCwwXSxzcGVlZDoxLjIsY3VydmU6MS40MixlYXNpbmc6dC5lYXNlfSxlKTt2YXIgcj10aGlzLnRyYW5zZm9ybSxhPXRoaXMuZ2V0Wm9vbSgpLG49dGhpcy5nZXRCZWFyaW5nKCkscz10aGlzLmdldFBpdGNoKCksbD1cInpvb21cImluIGU/dC5jbGFtcCgrZS56b29tLHIubWluWm9vbSxyLm1heFpvb20pOmEsYz1cImJlYXJpbmdcImluIGU/dGhpcy5fbm9ybWFsaXplQmVhcmluZyhlLmJlYXJpbmcsbik6bix1PVwicGl0Y2hcImluIGU/K2UucGl0Y2g6cyxoPXIuem9vbVNjYWxlKGwtYSkscD1yLmNlbnRlclBvaW50LmFkZCh0LlBvaW50LmNvbnZlcnQoZS5vZmZzZXQpKSxkPXIucG9pbnRMb2NhdGlvbihwKSxfPXQuTG5nTGF0LmNvbnZlcnQoZS5jZW50ZXJ8fGQpO3RoaXMuX25vcm1hbGl6ZUNlbnRlcihfKTt2YXIgZj1yLnByb2plY3QoZCksbT1yLnByb2plY3QoXykuc3ViKGYpLGc9ZS5jdXJ2ZSx2PU1hdGgubWF4KHIud2lkdGgsci5oZWlnaHQpLHk9di9oLHg9bS5tYWcoKTtpZihcIm1pblpvb21cImluIGUpe3ZhciBiPXQuY2xhbXAoTWF0aC5taW4oZS5taW5ab29tLGEsbCksci5taW5ab29tLHIubWF4Wm9vbSksdz12L3Iuem9vbVNjYWxlKGItYSk7Zz1NYXRoLnNxcnQody94KjIpO312YXIgRT1nKmc7ZnVuY3Rpb24gVCh0KXt2YXIgZT0oeSp5LXYqdisodD8tMToxKSpFKkUqeCp4KS8oMioodD95OnYpKkUqeCk7cmV0dXJuIE1hdGgubG9nKE1hdGguc3FydChlKmUrMSktZSl9ZnVuY3Rpb24gSSh0KXtyZXR1cm4gKE1hdGguZXhwKHQpLU1hdGguZXhwKC10KSkvMn1mdW5jdGlvbiBDKHQpe3JldHVybiAoTWF0aC5leHAodCkrTWF0aC5leHAoLXQpKS8yfXZhciBTPVQoMCksUD1mdW5jdGlvbih0KXtyZXR1cm4gQyhTKS9DKFMrZyp0KX0sej1mdW5jdGlvbih0KXtyZXR1cm4gdiooKEMoUykqKEkoZT1TK2cqdCkvQyhlKSktSShTKSkvRSkveDt2YXIgZTt9LEw9KFQoMSktUykvZztpZihNYXRoLmFicyh4KTwxZS02fHwhaXNGaW5pdGUoTCkpe2lmKE1hdGguYWJzKHYteSk8MWUtNilyZXR1cm4gdGhpcy5lYXNlVG8oZSxpKTt2YXIgRD15PHY/LTE6MTtMPU1hdGguYWJzKE1hdGgubG9nKHkvdikpL2csej1mdW5jdGlvbigpe3JldHVybiAwfSxQPWZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLmV4cChEKmcqdCl9O31pZihcImR1cmF0aW9uXCJpbiBlKWUuZHVyYXRpb249K2UuZHVyYXRpb247ZWxzZXt2YXIgTT1cInNjcmVlblNwZWVkXCJpbiBlPytlLnNjcmVlblNwZWVkL2c6K2Uuc3BlZWQ7ZS5kdXJhdGlvbj0xZTMqTC9NO31yZXR1cm4gZS5tYXhEdXJhdGlvbiYmZS5kdXJhdGlvbj5lLm1heER1cmF0aW9uJiYoZS5kdXJhdGlvbj0wKSx0aGlzLl96b29taW5nPSEwLHRoaXMuX3JvdGF0aW5nPW4hPT1jLHRoaXMuX3BpdGNoaW5nPXUhPT1zLHRoaXMuX3ByZXBhcmVFYXNlKGksITEpLHRoaXMuX2Vhc2UoZnVuY3Rpb24oZSl7dmFyIGg9ZSpMLGQ9MS9QKGgpO3Iuem9vbT0xPT09ZT9sOmErci5zY2FsZVpvb20oZCksby5fcm90YXRpbmcmJihyLmJlYXJpbmc9dC5udW1iZXIobixjLGUpKSxvLl9waXRjaGluZyYmKHIucGl0Y2g9dC5udW1iZXIocyx1LGUpKTt2YXIgZz0xPT09ZT9fOnIudW5wcm9qZWN0KGYuYWRkKG0ubXVsdCh6KGgpKSkubXVsdChkKSk7ci5zZXRMb2NhdGlvbkF0UG9pbnQoci5yZW5kZXJXb3JsZENvcGllcz9nLndyYXAoKTpnLHApLG8uX2ZpcmVNb3ZlRXZlbnRzKGkpO30sZnVuY3Rpb24oKXtyZXR1cm4gby5fYWZ0ZXJFYXNlKGkpfSxlKSx0aGlzfSxpLnByb3RvdHlwZS5pc0Vhc2luZz1mdW5jdGlvbigpe3JldHVybiAhIXRoaXMuX2Vhc2VGcmFtZUlkfSxpLnByb3RvdHlwZS5zdG9wPWZ1bmN0aW9uKCl7aWYodGhpcy5fZWFzZUZyYW1lSWQmJih0aGlzLl9jYW5jZWxSZW5kZXJGcmFtZSh0aGlzLl9lYXNlRnJhbWVJZCksZGVsZXRlIHRoaXMuX2Vhc2VGcmFtZUlkLGRlbGV0ZSB0aGlzLl9vbkVhc2VGcmFtZSksdGhpcy5fb25FYXNlRW5kKXt2YXIgdD10aGlzLl9vbkVhc2VFbmQ7ZGVsZXRlIHRoaXMuX29uRWFzZUVuZCx0LmNhbGwodGhpcyk7fXJldHVybiB0aGlzfSxpLnByb3RvdHlwZS5fZWFzZT1mdW5jdGlvbihlLGksbyl7ITE9PT1vLmFuaW1hdGV8fDA9PT1vLmR1cmF0aW9uPyhlKDEpLGkoKSk6KHRoaXMuX2Vhc2VTdGFydD10LmJyb3dzZXIubm93KCksdGhpcy5fZWFzZU9wdGlvbnM9byx0aGlzLl9vbkVhc2VGcmFtZT1lLHRoaXMuX29uRWFzZUVuZD1pLHRoaXMuX2Vhc2VGcmFtZUlkPXRoaXMuX3JlcXVlc3RSZW5kZXJGcmFtZSh0aGlzLl9yZW5kZXJGcmFtZUNhbGxiYWNrKSk7fSxpLnByb3RvdHlwZS5fcmVuZGVyRnJhbWVDYWxsYmFjaz1mdW5jdGlvbigpe3ZhciBlPU1hdGgubWluKCh0LmJyb3dzZXIubm93KCktdGhpcy5fZWFzZVN0YXJ0KS90aGlzLl9lYXNlT3B0aW9ucy5kdXJhdGlvbiwxKTt0aGlzLl9vbkVhc2VGcmFtZSh0aGlzLl9lYXNlT3B0aW9ucy5lYXNpbmcoZSkpLGU8MT90aGlzLl9lYXNlRnJhbWVJZD10aGlzLl9yZXF1ZXN0UmVuZGVyRnJhbWUodGhpcy5fcmVuZGVyRnJhbWVDYWxsYmFjayk6dGhpcy5zdG9wKCk7fSxpLnByb3RvdHlwZS5fbm9ybWFsaXplQmVhcmluZz1mdW5jdGlvbihlLGkpe2U9dC53cmFwKGUsLTE4MCwxODApO3ZhciBvPU1hdGguYWJzKGUtaSk7cmV0dXJuIE1hdGguYWJzKGUtMzYwLWkpPG8mJihlLT0zNjApLE1hdGguYWJzKGUrMzYwLWkpPG8mJihlKz0zNjApLGV9LGkucHJvdG90eXBlLl9ub3JtYWxpemVDZW50ZXI9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy50cmFuc2Zvcm07aWYoZS5yZW5kZXJXb3JsZENvcGllcyYmIWUubG5nUmFuZ2Upe3ZhciBpPXQubG5nLWUuY2VudGVyLmxuZzt0LmxuZys9aT4xODA/LTM2MDppPC0xODA/MzYwOjA7fX0saX0odC5FdmVudGVkKSx6bz1mdW5jdGlvbihlKXt2b2lkIDA9PT1lJiYoZT17fSksdGhpcy5vcHRpb25zPWUsdC5iaW5kQWxsKFtcIl91cGRhdGVFZGl0TGlua1wiLFwiX3VwZGF0ZURhdGFcIixcIl91cGRhdGVDb21wYWN0XCJdLHRoaXMpO307em8ucHJvdG90eXBlLmdldERlZmF1bHRQb3NpdGlvbj1mdW5jdGlvbigpe3JldHVybiBcImJvdHRvbS1yaWdodFwifSx6by5wcm90b3R5cGUub25BZGQ9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5vcHRpb25zJiZ0aGlzLm9wdGlvbnMuY29tcGFjdDtyZXR1cm4gdGhpcy5fbWFwPXQsdGhpcy5fY29udGFpbmVyPWkuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1jdHJsIG1hcGJveGdsLWN0cmwtYXR0cmliXCIpLHRoaXMuX2lubmVyQ29udGFpbmVyPWkuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1jdHJsLWF0dHJpYi1pbm5lclwiLHRoaXMuX2NvbnRhaW5lciksZSYmdGhpcy5fY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jb21wYWN0XCIpLHRoaXMuX3VwZGF0ZUF0dHJpYnV0aW9ucygpLHRoaXMuX3VwZGF0ZUVkaXRMaW5rKCksdGhpcy5fbWFwLm9uKFwic3R5bGVkYXRhXCIsdGhpcy5fdXBkYXRlRGF0YSksdGhpcy5fbWFwLm9uKFwic291cmNlZGF0YVwiLHRoaXMuX3VwZGF0ZURhdGEpLHRoaXMuX21hcC5vbihcIm1vdmVlbmRcIix0aGlzLl91cGRhdGVFZGl0TGluayksdm9pZCAwPT09ZSYmKHRoaXMuX21hcC5vbihcInJlc2l6ZVwiLHRoaXMuX3VwZGF0ZUNvbXBhY3QpLHRoaXMuX3VwZGF0ZUNvbXBhY3QoKSksdGhpcy5fY29udGFpbmVyfSx6by5wcm90b3R5cGUub25SZW1vdmU9ZnVuY3Rpb24oKXtpLnJlbW92ZSh0aGlzLl9jb250YWluZXIpLHRoaXMuX21hcC5vZmYoXCJzdHlsZWRhdGFcIix0aGlzLl91cGRhdGVEYXRhKSx0aGlzLl9tYXAub2ZmKFwic291cmNlZGF0YVwiLHRoaXMuX3VwZGF0ZURhdGEpLHRoaXMuX21hcC5vZmYoXCJtb3ZlZW5kXCIsdGhpcy5fdXBkYXRlRWRpdExpbmspLHRoaXMuX21hcC5vZmYoXCJyZXNpemVcIix0aGlzLl91cGRhdGVDb21wYWN0KSx0aGlzLl9tYXA9dm9pZCAwO30sem8ucHJvdG90eXBlLl91cGRhdGVFZGl0TGluaz1mdW5jdGlvbigpe3ZhciBlPXRoaXMuX2VkaXRMaW5rO2V8fChlPXRoaXMuX2VkaXRMaW5rPXRoaXMuX2NvbnRhaW5lci5xdWVyeVNlbGVjdG9yKFwiLm1hcGJveC1pbXByb3ZlLW1hcFwiKSk7dmFyIGk9W3trZXk6XCJvd25lclwiLHZhbHVlOnRoaXMuc3R5bGVPd25lcn0se2tleTpcImlkXCIsdmFsdWU6dGhpcy5zdHlsZUlkfSx7a2V5OlwiYWNjZXNzX3Rva2VuXCIsdmFsdWU6dC5jb25maWcuQUNDRVNTX1RPS0VOfV07aWYoZSl7dmFyIG89aS5yZWR1Y2UoZnVuY3Rpb24odCxlLG8pe3JldHVybiBlLnZhbHVlJiYodCs9ZS5rZXkrXCI9XCIrZS52YWx1ZSsobzxpLmxlbmd0aC0xP1wiJlwiOlwiXCIpKSx0fSxcIj9cIik7ZS5ocmVmPXQuY29uZmlnLkZFRURCQUNLX1VSTCtcIi9cIitvKyh0aGlzLl9tYXAuX2hhc2g/dGhpcy5fbWFwLl9oYXNoLmdldEhhc2hTdHJpbmcoITApOlwiXCIpLGUucmVsPVwibm9vcGVuZXIgbm9mb2xsb3dcIjt9fSx6by5wcm90b3R5cGUuX3VwZGF0ZURhdGE9ZnVuY3Rpb24odCl7IXR8fFwibWV0YWRhdGFcIiE9PXQuc291cmNlRGF0YVR5cGUmJlwic3R5bGVcIiE9PXQuZGF0YVR5cGV8fCh0aGlzLl91cGRhdGVBdHRyaWJ1dGlvbnMoKSx0aGlzLl91cGRhdGVFZGl0TGluaygpKTt9LHpvLnByb3RvdHlwZS5fdXBkYXRlQXR0cmlidXRpb25zPWZ1bmN0aW9uKCl7aWYodGhpcy5fbWFwLnN0eWxlKXt2YXIgdD1bXTtpZih0aGlzLm9wdGlvbnMuY3VzdG9tQXR0cmlidXRpb24mJihBcnJheS5pc0FycmF5KHRoaXMub3B0aW9ucy5jdXN0b21BdHRyaWJ1dGlvbik/dD10LmNvbmNhdCh0aGlzLm9wdGlvbnMuY3VzdG9tQXR0cmlidXRpb24ubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBcInN0cmluZ1wiIT10eXBlb2YgdD9cIlwiOnR9KSk6XCJzdHJpbmdcIj09dHlwZW9mIHRoaXMub3B0aW9ucy5jdXN0b21BdHRyaWJ1dGlvbiYmdC5wdXNoKHRoaXMub3B0aW9ucy5jdXN0b21BdHRyaWJ1dGlvbikpLHRoaXMuX21hcC5zdHlsZS5zdHlsZXNoZWV0KXt2YXIgZT10aGlzLl9tYXAuc3R5bGUuc3R5bGVzaGVldDt0aGlzLnN0eWxlT3duZXI9ZS5vd25lcix0aGlzLnN0eWxlSWQ9ZS5pZDt9dmFyIGk9dGhpcy5fbWFwLnN0eWxlLnNvdXJjZUNhY2hlcztmb3IodmFyIG8gaW4gaSl7dmFyIHI9aVtvXTtpZihyLnVzZWQpe3ZhciBhPXIuZ2V0U291cmNlKCk7YS5hdHRyaWJ1dGlvbiYmdC5pbmRleE9mKGEuYXR0cmlidXRpb24pPDAmJnQucHVzaChhLmF0dHJpYnV0aW9uKTt9fXQuc29ydChmdW5jdGlvbih0LGUpe3JldHVybiB0Lmxlbmd0aC1lLmxlbmd0aH0pO3ZhciBuPSh0PXQuZmlsdGVyKGZ1bmN0aW9uKGUsaSl7Zm9yKHZhciBvPWkrMTtvPHQubGVuZ3RoO28rKylpZih0W29dLmluZGV4T2YoZSk+PTApcmV0dXJuICExO3JldHVybiAhMH0pKS5qb2luKFwiIHwgXCIpO24hPT10aGlzLl9hdHRyaWJIVE1MJiYodGhpcy5fYXR0cmliSFRNTD1uLHQubGVuZ3RoPyh0aGlzLl9pbm5lckNvbnRhaW5lci5pbm5lckhUTUw9bix0aGlzLl9jb250YWluZXIuY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWF0dHJpYi1lbXB0eVwiKSk6dGhpcy5fY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1hdHRyaWItZW1wdHlcIiksdGhpcy5fZWRpdExpbms9bnVsbCk7fX0sem8ucHJvdG90eXBlLl91cGRhdGVDb21wYWN0PWZ1bmN0aW9uKCl7dGhpcy5fbWFwLmdldENhbnZhc0NvbnRhaW5lcigpLm9mZnNldFdpZHRoPD02NDA/dGhpcy5fY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jb21wYWN0XCIpOnRoaXMuX2NvbnRhaW5lci5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY29tcGFjdFwiKTt9O3ZhciBMbz1mdW5jdGlvbigpe3QuYmluZEFsbChbXCJfdXBkYXRlTG9nb1wiXSx0aGlzKSx0LmJpbmRBbGwoW1wiX3VwZGF0ZUNvbXBhY3RcIl0sdGhpcyk7fTtMby5wcm90b3R5cGUub25BZGQ9ZnVuY3Rpb24odCl7dGhpcy5fbWFwPXQsdGhpcy5fY29udGFpbmVyPWkuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1jdHJsXCIpO3ZhciBlPWkuY3JlYXRlKFwiYVwiLFwibWFwYm94Z2wtY3RybC1sb2dvXCIpO3JldHVybiBlLnRhcmdldD1cIl9ibGFua1wiLGUucmVsPVwibm9vcGVuZXIgbm9mb2xsb3dcIixlLmhyZWY9XCJodHRwczovL3d3dy5tYXBib3guY29tL1wiLGUuc2V0QXR0cmlidXRlKFwiYXJpYS1sYWJlbFwiLFwiTWFwYm94IGxvZ29cIiksZS5zZXRBdHRyaWJ1dGUoXCJyZWxcIixcIm5vb3BlbmVyIG5vZm9sbG93XCIpLHRoaXMuX2NvbnRhaW5lci5hcHBlbmRDaGlsZChlKSx0aGlzLl9jb250YWluZXIuc3R5bGUuZGlzcGxheT1cIm5vbmVcIix0aGlzLl9tYXAub24oXCJzb3VyY2VkYXRhXCIsdGhpcy5fdXBkYXRlTG9nbyksdGhpcy5fdXBkYXRlTG9nbygpLHRoaXMuX21hcC5vbihcInJlc2l6ZVwiLHRoaXMuX3VwZGF0ZUNvbXBhY3QpLHRoaXMuX3VwZGF0ZUNvbXBhY3QoKSx0aGlzLl9jb250YWluZXJ9LExvLnByb3RvdHlwZS5vblJlbW92ZT1mdW5jdGlvbigpe2kucmVtb3ZlKHRoaXMuX2NvbnRhaW5lciksdGhpcy5fbWFwLm9mZihcInNvdXJjZWRhdGFcIix0aGlzLl91cGRhdGVMb2dvKSx0aGlzLl9tYXAub2ZmKFwicmVzaXplXCIsdGhpcy5fdXBkYXRlQ29tcGFjdCk7fSxMby5wcm90b3R5cGUuZ2V0RGVmYXVsdFBvc2l0aW9uPWZ1bmN0aW9uKCl7cmV0dXJuIFwiYm90dG9tLWxlZnRcIn0sTG8ucHJvdG90eXBlLl91cGRhdGVMb2dvPWZ1bmN0aW9uKHQpe3QmJlwibWV0YWRhdGFcIiE9PXQuc291cmNlRGF0YVR5cGV8fCh0aGlzLl9jb250YWluZXIuc3R5bGUuZGlzcGxheT10aGlzLl9sb2dvUmVxdWlyZWQoKT9cImJsb2NrXCI6XCJub25lXCIpO30sTG8ucHJvdG90eXBlLl9sb2dvUmVxdWlyZWQ9ZnVuY3Rpb24oKXtpZih0aGlzLl9tYXAuc3R5bGUpe3ZhciB0PXRoaXMuX21hcC5zdHlsZS5zb3VyY2VDYWNoZXM7Zm9yKHZhciBlIGluIHQpe2lmKHRbZV0uZ2V0U291cmNlKCkubWFwYm94X2xvZ28pcmV0dXJuICEwfXJldHVybiAhMX19LExvLnByb3RvdHlwZS5fdXBkYXRlQ29tcGFjdD1mdW5jdGlvbigpe3ZhciB0PXRoaXMuX2NvbnRhaW5lci5jaGlsZHJlbjtpZih0Lmxlbmd0aCl7dmFyIGU9dFswXTt0aGlzLl9tYXAuZ2V0Q2FudmFzQ29udGFpbmVyKCkub2Zmc2V0V2lkdGg8MjUwP2UuY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWNvbXBhY3RcIik6ZS5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY29tcGFjdFwiKTt9fTt2YXIgRG89ZnVuY3Rpb24oKXt0aGlzLl9xdWV1ZT1bXSx0aGlzLl9pZD0wLHRoaXMuX2NsZWFyZWQ9ITEsdGhpcy5fY3VycmVudGx5UnVubmluZz0hMTt9O0RvLnByb3RvdHlwZS5hZGQ9ZnVuY3Rpb24odCl7dmFyIGU9Kyt0aGlzLl9pZDtyZXR1cm4gdGhpcy5fcXVldWUucHVzaCh7Y2FsbGJhY2s6dCxpZDplLGNhbmNlbGxlZDohMX0pLGV9LERvLnByb3RvdHlwZS5yZW1vdmU9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPXRoaXMuX2N1cnJlbnRseVJ1bm5pbmcsaT0wLG89ZT90aGlzLl9xdWV1ZS5jb25jYXQoZSk6dGhpcy5fcXVldWU7aTxvLmxlbmd0aDtpKz0xKXt2YXIgcj1vW2ldO2lmKHIuaWQ9PT10KXJldHVybiB2b2lkKHIuY2FuY2VsbGVkPSEwKX19LERvLnByb3RvdHlwZS5ydW49ZnVuY3Rpb24oKXt2YXIgdD10aGlzLl9jdXJyZW50bHlSdW5uaW5nPXRoaXMuX3F1ZXVlO3RoaXMuX3F1ZXVlPVtdO2Zvcih2YXIgZT0wLGk9dDtlPGkubGVuZ3RoO2UrPTEpe3ZhciBvPWlbZV07aWYoIW8uY2FuY2VsbGVkJiYoby5jYWxsYmFjaygpLHRoaXMuX2NsZWFyZWQpKWJyZWFrfXRoaXMuX2NsZWFyZWQ9ITEsdGhpcy5fY3VycmVudGx5UnVubmluZz0hMTt9LERvLnByb3RvdHlwZS5jbGVhcj1mdW5jdGlvbigpe3RoaXMuX2N1cnJlbnRseVJ1bm5pbmcmJih0aGlzLl9jbGVhcmVkPSEwKSx0aGlzLl9xdWV1ZT1bXTt9O3ZhciBNbz10LndpbmRvdy5IVE1MSW1hZ2VFbGVtZW50LFJvPXQud2luZG93LkhUTUxFbGVtZW50LEFvPXtjZW50ZXI6WzAsMF0sem9vbTowLGJlYXJpbmc6MCxwaXRjaDowLG1pblpvb206MCxtYXhab29tOjIyLGludGVyYWN0aXZlOiEwLHNjcm9sbFpvb206ITAsYm94Wm9vbTohMCxkcmFnUm90YXRlOiEwLGRyYWdQYW46ITAsa2V5Ym9hcmQ6ITAsZG91YmxlQ2xpY2tab29tOiEwLHRvdWNoWm9vbVJvdGF0ZTohMCxiZWFyaW5nU25hcDo3LGNsaWNrVG9sZXJhbmNlOjMsaGFzaDohMSxhdHRyaWJ1dGlvbkNvbnRyb2w6ITAsZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDohMSxwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6ITEsdHJhY2tSZXNpemU6ITAscmVuZGVyV29ybGRDb3BpZXM6ITAscmVmcmVzaEV4cGlyZWRUaWxlczohMCxtYXhUaWxlQ2FjaGVTaXplOm51bGwsbG9jYWxJZGVvZ3JhcGhGb250RmFtaWx5Olwic2Fucy1zZXJpZlwiLHRyYW5zZm9ybVJlcXVlc3Q6bnVsbCxmYWRlRHVyYXRpb246MzAwLGNyb3NzU291cmNlQ29sbGlzaW9uczohMH0sa289ZnVuY3Rpb24obyl7ZnVuY3Rpb24gcihlKXt2YXIgcj10aGlzO2lmKG51bGwhPShlPXQuZXh0ZW5kKHt9LEFvLGUpKS5taW5ab29tJiZudWxsIT1lLm1heFpvb20mJmUubWluWm9vbT5lLm1heFpvb20pdGhyb3cgbmV3IEVycm9yKFwibWF4Wm9vbSBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBtaW5ab29tXCIpO3ZhciBhPW5ldyBjbyhlLm1pblpvb20sZS5tYXhab29tLGUucmVuZGVyV29ybGRDb3BpZXMpO2lmKG8uY2FsbCh0aGlzLGEsZSksdGhpcy5faW50ZXJhY3RpdmU9ZS5pbnRlcmFjdGl2ZSx0aGlzLl9tYXhUaWxlQ2FjaGVTaXplPWUubWF4VGlsZUNhY2hlU2l6ZSx0aGlzLl9mYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0PWUuZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdCx0aGlzLl9wcmVzZXJ2ZURyYXdpbmdCdWZmZXI9ZS5wcmVzZXJ2ZURyYXdpbmdCdWZmZXIsdGhpcy5fYW50aWFsaWFzPWUuYW50aWFsaWFzLHRoaXMuX3RyYWNrUmVzaXplPWUudHJhY2tSZXNpemUsdGhpcy5fYmVhcmluZ1NuYXA9ZS5iZWFyaW5nU25hcCx0aGlzLl9yZWZyZXNoRXhwaXJlZFRpbGVzPWUucmVmcmVzaEV4cGlyZWRUaWxlcyx0aGlzLl9mYWRlRHVyYXRpb249ZS5mYWRlRHVyYXRpb24sdGhpcy5fY3Jvc3NTb3VyY2VDb2xsaXNpb25zPWUuY3Jvc3NTb3VyY2VDb2xsaXNpb25zLHRoaXMuX2Nyb3NzRmFkaW5nRmFjdG9yPTEsdGhpcy5fY29sbGVjdFJlc291cmNlVGltaW5nPWUuY29sbGVjdFJlc291cmNlVGltaW5nLHRoaXMuX3JlbmRlclRhc2tRdWV1ZT1uZXcgRG8sdGhpcy5fY29udHJvbHM9W10sdGhpcy5fbWFwSWQ9dC51bmlxdWVJZCgpLHRoaXMuX3JlcXVlc3RNYW5hZ2VyPW5ldyB0LlJlcXVlc3RNYW5hZ2VyKGUudHJhbnNmb3JtUmVxdWVzdCksXCJzdHJpbmdcIj09dHlwZW9mIGUuY29udGFpbmVyKXtpZih0aGlzLl9jb250YWluZXI9dC53aW5kb3cuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZS5jb250YWluZXIpLCF0aGlzLl9jb250YWluZXIpdGhyb3cgbmV3IEVycm9yKFwiQ29udGFpbmVyICdcIitlLmNvbnRhaW5lcitcIicgbm90IGZvdW5kLlwiKX1lbHNle2lmKCEoZS5jb250YWluZXIgaW5zdGFuY2VvZiBSbykpdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCB0eXBlOiAnY29udGFpbmVyJyBtdXN0IGJlIGEgU3RyaW5nIG9yIEhUTUxFbGVtZW50LlwiKTt0aGlzLl9jb250YWluZXI9ZS5jb250YWluZXI7fWlmKGUubWF4Qm91bmRzJiZ0aGlzLnNldE1heEJvdW5kcyhlLm1heEJvdW5kcyksdC5iaW5kQWxsKFtcIl9vbldpbmRvd09ubGluZVwiLFwiX29uV2luZG93UmVzaXplXCIsXCJfY29udGV4dExvc3RcIixcIl9jb250ZXh0UmVzdG9yZWRcIl0sdGhpcyksdGhpcy5fc2V0dXBDb250YWluZXIoKSx0aGlzLl9zZXR1cFBhaW50ZXIoKSx2b2lkIDA9PT10aGlzLnBhaW50ZXIpdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIGluaXRpYWxpemUgV2ViR0wuXCIpO3RoaXMub24oXCJtb3ZlXCIsZnVuY3Rpb24oKXtyZXR1cm4gci5fdXBkYXRlKCExKX0pLHRoaXMub24oXCJtb3ZlZW5kXCIsZnVuY3Rpb24oKXtyZXR1cm4gci5fdXBkYXRlKCExKX0pLHRoaXMub24oXCJ6b29tXCIsZnVuY3Rpb24oKXtyZXR1cm4gci5fdXBkYXRlKCEwKX0pLHZvaWQgMCE9PXQud2luZG93JiYodC53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm9ubGluZVwiLHRoaXMuX29uV2luZG93T25saW5lLCExKSx0LndpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwicmVzaXplXCIsdGhpcy5fb25XaW5kb3dSZXNpemUsITEpKSxmdW5jdGlvbih0LGUpe3ZhciBvPXQuZ2V0Q2FudmFzQ29udGFpbmVyKCkscj1udWxsLGE9ITEsbj1udWxsO2Zvcih2YXIgcyBpbiBTbyl0W3NdPW5ldyBTb1tzXSh0LGUpLGUuaW50ZXJhY3RpdmUmJmVbc10mJnRbc10uZW5hYmxlKGVbc10pO2kuYWRkRXZlbnRMaXN0ZW5lcihvLFwibW91c2VvdXRcIixmdW5jdGlvbihlKXt0LmZpcmUobmV3IHBvKFwibW91c2VvdXRcIix0LGUpKTt9KSxpLmFkZEV2ZW50TGlzdGVuZXIobyxcIm1vdXNlZG93blwiLGZ1bmN0aW9uKHIpe2E9ITAsbj1pLm1vdXNlUG9zKG8scik7dmFyIHM9bmV3IHBvKFwibW91c2Vkb3duXCIsdCxyKTt0LmZpcmUocykscy5kZWZhdWx0UHJldmVudGVkfHwoZS5pbnRlcmFjdGl2ZSYmIXQuZG91YmxlQ2xpY2tab29tLmlzQWN0aXZlKCkmJnQuc3RvcCgpLHQuYm94Wm9vbS5vbk1vdXNlRG93bihyKSx0LmJveFpvb20uaXNBY3RpdmUoKXx8dC5kcmFnUGFuLmlzQWN0aXZlKCl8fHQuZHJhZ1JvdGF0ZS5vbk1vdXNlRG93bihyKSx0LmJveFpvb20uaXNBY3RpdmUoKXx8dC5kcmFnUm90YXRlLmlzQWN0aXZlKCl8fHQuZHJhZ1Bhbi5vbk1vdXNlRG93bihyKSk7fSksaS5hZGRFdmVudExpc3RlbmVyKG8sXCJtb3VzZXVwXCIsZnVuY3Rpb24oZSl7dmFyIGk9dC5kcmFnUm90YXRlLmlzQWN0aXZlKCk7ciYmIWkmJnQuZmlyZShuZXcgcG8oXCJjb250ZXh0bWVudVwiLHQscikpLHI9bnVsbCxhPSExLHQuZmlyZShuZXcgcG8oXCJtb3VzZXVwXCIsdCxlKSk7fSksaS5hZGRFdmVudExpc3RlbmVyKG8sXCJtb3VzZW1vdmVcIixmdW5jdGlvbihlKXtpZighdC5kcmFnUGFuLmlzQWN0aXZlKCkmJiF0LmRyYWdSb3RhdGUuaXNBY3RpdmUoKSl7Zm9yKHZhciBpPWUudGFyZ2V0O2kmJmkhPT1vOylpPWkucGFyZW50Tm9kZTtpPT09byYmdC5maXJlKG5ldyBwbyhcIm1vdXNlbW92ZVwiLHQsZSkpO319KSxpLmFkZEV2ZW50TGlzdGVuZXIobyxcIm1vdXNlb3ZlclwiLGZ1bmN0aW9uKGUpe2Zvcih2YXIgaT1lLnRhcmdldDtpJiZpIT09bzspaT1pLnBhcmVudE5vZGU7aT09PW8mJnQuZmlyZShuZXcgcG8oXCJtb3VzZW92ZXJcIix0LGUpKTt9KSxpLmFkZEV2ZW50TGlzdGVuZXIobyxcInRvdWNoc3RhcnRcIixmdW5jdGlvbihpKXt2YXIgbz1uZXcgX28oXCJ0b3VjaHN0YXJ0XCIsdCxpKTt0LmZpcmUobyksby5kZWZhdWx0UHJldmVudGVkfHwoZS5pbnRlcmFjdGl2ZSYmdC5zdG9wKCksdC5ib3hab29tLmlzQWN0aXZlKCl8fHQuZHJhZ1JvdGF0ZS5pc0FjdGl2ZSgpfHx0LmRyYWdQYW4ub25Ub3VjaFN0YXJ0KGkpLHQudG91Y2hab29tUm90YXRlLm9uU3RhcnQoaSksdC5kb3VibGVDbGlja1pvb20ub25Ub3VjaFN0YXJ0KG8pKTt9LHtwYXNzaXZlOiExfSksaS5hZGRFdmVudExpc3RlbmVyKG8sXCJ0b3VjaG1vdmVcIixmdW5jdGlvbihlKXt0LmZpcmUobmV3IF9vKFwidG91Y2htb3ZlXCIsdCxlKSk7fSx7cGFzc2l2ZTohMX0pLGkuYWRkRXZlbnRMaXN0ZW5lcihvLFwidG91Y2hlbmRcIixmdW5jdGlvbihlKXt0LmZpcmUobmV3IF9vKFwidG91Y2hlbmRcIix0LGUpKTt9KSxpLmFkZEV2ZW50TGlzdGVuZXIobyxcInRvdWNoY2FuY2VsXCIsZnVuY3Rpb24oZSl7dC5maXJlKG5ldyBfbyhcInRvdWNoY2FuY2VsXCIsdCxlKSk7fSksaS5hZGRFdmVudExpc3RlbmVyKG8sXCJjbGlja1wiLGZ1bmN0aW9uKHIpe3ZhciBhPWkubW91c2VQb3MobyxyKTsoYS5lcXVhbHMobil8fGEuZGlzdChuKTxlLmNsaWNrVG9sZXJhbmNlKSYmdC5maXJlKG5ldyBwbyhcImNsaWNrXCIsdCxyKSk7fSksaS5hZGRFdmVudExpc3RlbmVyKG8sXCJkYmxjbGlja1wiLGZ1bmN0aW9uKGUpe3ZhciBpPW5ldyBwbyhcImRibGNsaWNrXCIsdCxlKTt0LmZpcmUoaSksaS5kZWZhdWx0UHJldmVudGVkfHx0LmRvdWJsZUNsaWNrWm9vbS5vbkRibENsaWNrKGkpO30pLGkuYWRkRXZlbnRMaXN0ZW5lcihvLFwiY29udGV4dG1lbnVcIixmdW5jdGlvbihlKXt2YXIgaT10LmRyYWdSb3RhdGUuaXNBY3RpdmUoKTthfHxpP2EmJihyPWUpOnQuZmlyZShuZXcgcG8oXCJjb250ZXh0bWVudVwiLHQsZSkpLCh0LmRyYWdSb3RhdGUuaXNFbmFibGVkKCl8fHQubGlzdGVucyhcImNvbnRleHRtZW51XCIpKSYmZS5wcmV2ZW50RGVmYXVsdCgpO30pLGkuYWRkRXZlbnRMaXN0ZW5lcihvLFwid2hlZWxcIixmdW5jdGlvbihpKXtlLmludGVyYWN0aXZlJiZ0LnN0b3AoKTt2YXIgbz1uZXcgZm8oXCJ3aGVlbFwiLHQsaSk7dC5maXJlKG8pLG8uZGVmYXVsdFByZXZlbnRlZHx8dC5zY3JvbGxab29tLm9uV2hlZWwoaSk7fSx7cGFzc2l2ZTohMX0pO30odGhpcyxlKSx0aGlzLl9oYXNoPWUuaGFzaCYmKG5ldyBobykuYWRkVG8odGhpcyksdGhpcy5faGFzaCYmdGhpcy5faGFzaC5fb25IYXNoQ2hhbmdlKCl8fCh0aGlzLmp1bXBUbyh7Y2VudGVyOmUuY2VudGVyLHpvb206ZS56b29tLGJlYXJpbmc6ZS5iZWFyaW5nLHBpdGNoOmUucGl0Y2h9KSxlLmJvdW5kcyYmKHRoaXMucmVzaXplKCksdGhpcy5maXRCb3VuZHMoZS5ib3VuZHMsdC5leHRlbmQoe30sZS5maXRCb3VuZHNPcHRpb25zLHtkdXJhdGlvbjowfSkpKSksdGhpcy5yZXNpemUoKSx0aGlzLl9sb2NhbElkZW9ncmFwaEZvbnRGYW1pbHk9ZS5sb2NhbElkZW9ncmFwaEZvbnRGYW1pbHksZS5zdHlsZSYmdGhpcy5zZXRTdHlsZShlLnN0eWxlLHtsb2NhbElkZW9ncmFwaEZvbnRGYW1pbHk6ZS5sb2NhbElkZW9ncmFwaEZvbnRGYW1pbHl9KSxlLmF0dHJpYnV0aW9uQ29udHJvbCYmdGhpcy5hZGRDb250cm9sKG5ldyB6byh7Y3VzdG9tQXR0cmlidXRpb246ZS5jdXN0b21BdHRyaWJ1dGlvbn0pKSx0aGlzLmFkZENvbnRyb2wobmV3IExvLGUubG9nb1Bvc2l0aW9uKSx0aGlzLm9uKFwic3R5bGUubG9hZFwiLGZ1bmN0aW9uKCl7ci50cmFuc2Zvcm0udW5tb2RpZmllZCYmci5qdW1wVG8oci5zdHlsZS5zdHlsZXNoZWV0KTt9KSx0aGlzLm9uKFwiZGF0YVwiLGZ1bmN0aW9uKGUpe3IuX3VwZGF0ZShcInN0eWxlXCI9PT1lLmRhdGFUeXBlKSxyLmZpcmUobmV3IHQuRXZlbnQoZS5kYXRhVHlwZStcImRhdGFcIixlKSk7fSksdGhpcy5vbihcImRhdGFsb2FkaW5nXCIsZnVuY3Rpb24oZSl7ci5maXJlKG5ldyB0LkV2ZW50KGUuZGF0YVR5cGUrXCJkYXRhbG9hZGluZ1wiLGUpKTt9KTt9byYmKHIuX19wcm90b19fPW8pLHIucHJvdG90eXBlPU9iamVjdC5jcmVhdGUobyYmby5wcm90b3R5cGUpLHIucHJvdG90eXBlLmNvbnN0cnVjdG9yPXI7dmFyIGE9e3Nob3dUaWxlQm91bmRhcmllczp7Y29uZmlndXJhYmxlOiEwfSxzaG93Q29sbGlzaW9uQm94ZXM6e2NvbmZpZ3VyYWJsZTohMH0sc2hvd092ZXJkcmF3SW5zcGVjdG9yOntjb25maWd1cmFibGU6ITB9LHJlcGFpbnQ6e2NvbmZpZ3VyYWJsZTohMH0sdmVydGljZXM6e2NvbmZpZ3VyYWJsZTohMH19O3JldHVybiByLnByb3RvdHlwZS5fZ2V0TWFwSWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fbWFwSWR9LHIucHJvdG90eXBlLmFkZENvbnRyb2w9ZnVuY3Rpb24oZSxpKXtpZih2b2lkIDA9PT1pJiZlLmdldERlZmF1bHRQb3NpdGlvbiYmKGk9ZS5nZXREZWZhdWx0UG9zaXRpb24oKSksdm9pZCAwPT09aSYmKGk9XCJ0b3AtcmlnaHRcIiksIWV8fCFlLm9uQWRkKXJldHVybiB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJJbnZhbGlkIGFyZ3VtZW50IHRvIG1hcC5hZGRDb250cm9sKCkuIEFyZ3VtZW50IG11c3QgYmUgYSBjb250cm9sIHdpdGggb25BZGQgYW5kIG9uUmVtb3ZlIG1ldGhvZHMuXCIpKSk7dmFyIG89ZS5vbkFkZCh0aGlzKTt0aGlzLl9jb250cm9scy5wdXNoKGUpO3ZhciByPXRoaXMuX2NvbnRyb2xQb3NpdGlvbnNbaV07cmV0dXJuIC0xIT09aS5pbmRleE9mKFwiYm90dG9tXCIpP3IuaW5zZXJ0QmVmb3JlKG8sci5maXJzdENoaWxkKTpyLmFwcGVuZENoaWxkKG8pLHRoaXN9LHIucHJvdG90eXBlLnJlbW92ZUNvbnRyb2w9ZnVuY3Rpb24oZSl7aWYoIWV8fCFlLm9uUmVtb3ZlKXJldHVybiB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJJbnZhbGlkIGFyZ3VtZW50IHRvIG1hcC5yZW1vdmVDb250cm9sKCkuIEFyZ3VtZW50IG11c3QgYmUgYSBjb250cm9sIHdpdGggb25BZGQgYW5kIG9uUmVtb3ZlIG1ldGhvZHMuXCIpKSk7dmFyIGk9dGhpcy5fY29udHJvbHMuaW5kZXhPZihlKTtyZXR1cm4gaT4tMSYmdGhpcy5fY29udHJvbHMuc3BsaWNlKGksMSksZS5vblJlbW92ZSh0aGlzKSx0aGlzfSxyLnByb3RvdHlwZS5yZXNpemU9ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcy5fY29udGFpbmVyRGltZW5zaW9ucygpLG89aVswXSxyPWlbMV07cmV0dXJuIHRoaXMuX3Jlc2l6ZUNhbnZhcyhvLHIpLHRoaXMudHJhbnNmb3JtLnJlc2l6ZShvLHIpLHRoaXMucGFpbnRlci5yZXNpemUobyxyKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJtb3Zlc3RhcnRcIixlKSkuZmlyZShuZXcgdC5FdmVudChcIm1vdmVcIixlKSkuZmlyZShuZXcgdC5FdmVudChcInJlc2l6ZVwiLGUpKS5maXJlKG5ldyB0LkV2ZW50KFwibW92ZWVuZFwiLGUpKSx0aGlzfSxyLnByb3RvdHlwZS5nZXRCb3VuZHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50cmFuc2Zvcm0uZ2V0Qm91bmRzKCl9LHIucHJvdG90eXBlLmdldE1heEJvdW5kcz1mdW5jdGlvbigpe3JldHVybiB0aGlzLnRyYW5zZm9ybS5nZXRNYXhCb3VuZHMoKX0sci5wcm90b3R5cGUuc2V0TWF4Qm91bmRzPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLnRyYW5zZm9ybS5zZXRNYXhCb3VuZHModC5MbmdMYXRCb3VuZHMuY29udmVydChlKSksdGhpcy5fdXBkYXRlKCl9LHIucHJvdG90eXBlLnNldE1pblpvb209ZnVuY3Rpb24odCl7aWYoKHQ9bnVsbD09dD8wOnQpPj0wJiZ0PD10aGlzLnRyYW5zZm9ybS5tYXhab29tKXJldHVybiB0aGlzLnRyYW5zZm9ybS5taW5ab29tPXQsdGhpcy5fdXBkYXRlKCksdGhpcy5nZXRab29tKCk8dCYmdGhpcy5zZXRab29tKHQpLHRoaXM7dGhyb3cgbmV3IEVycm9yKFwibWluWm9vbSBtdXN0IGJlIGJldHdlZW4gMCBhbmQgdGhlIGN1cnJlbnQgbWF4Wm9vbSwgaW5jbHVzaXZlXCIpfSxyLnByb3RvdHlwZS5nZXRNaW5ab29tPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLm1pblpvb219LHIucHJvdG90eXBlLnNldE1heFpvb209ZnVuY3Rpb24odCl7aWYoKHQ9bnVsbD09dD8yMjp0KT49dGhpcy50cmFuc2Zvcm0ubWluWm9vbSlyZXR1cm4gdGhpcy50cmFuc2Zvcm0ubWF4Wm9vbT10LHRoaXMuX3VwZGF0ZSgpLHRoaXMuZ2V0Wm9vbSgpPnQmJnRoaXMuc2V0Wm9vbSh0KSx0aGlzO3Rocm93IG5ldyBFcnJvcihcIm1heFpvb20gbXVzdCBiZSBncmVhdGVyIHRoYW4gdGhlIGN1cnJlbnQgbWluWm9vbVwiKX0sci5wcm90b3R5cGUuZ2V0UmVuZGVyV29ybGRDb3BpZXM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50cmFuc2Zvcm0ucmVuZGVyV29ybGRDb3BpZXN9LHIucHJvdG90eXBlLnNldFJlbmRlcldvcmxkQ29waWVzPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnRyYW5zZm9ybS5yZW5kZXJXb3JsZENvcGllcz10LHRoaXMuX3VwZGF0ZSgpfSxyLnByb3RvdHlwZS5nZXRNYXhab29tPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLm1heFpvb219LHIucHJvdG90eXBlLnByb2plY3Q9ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMudHJhbnNmb3JtLmxvY2F0aW9uUG9pbnQodC5MbmdMYXQuY29udmVydChlKSl9LHIucHJvdG90eXBlLnVucHJvamVjdD1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy50cmFuc2Zvcm0ucG9pbnRMb2NhdGlvbih0LlBvaW50LmNvbnZlcnQoZSkpfSxyLnByb3RvdHlwZS5pc01vdmluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9tb3Zpbmd8fHRoaXMuZHJhZ1Bhbi5pc0FjdGl2ZSgpfHx0aGlzLmRyYWdSb3RhdGUuaXNBY3RpdmUoKXx8dGhpcy5zY3JvbGxab29tLmlzQWN0aXZlKCl9LHIucHJvdG90eXBlLmlzWm9vbWluZz1mdW5jdGlvbigpe3JldHVybiB0aGlzLl96b29taW5nfHx0aGlzLnNjcm9sbFpvb20uaXNab29taW5nKCl9LHIucHJvdG90eXBlLmlzUm90YXRpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fcm90YXRpbmd8fHRoaXMuZHJhZ1JvdGF0ZS5pc0FjdGl2ZSgpfSxyLnByb3RvdHlwZS5vbj1mdW5jdGlvbih0LGUsaSl7dmFyIHI9dGhpcztpZih2b2lkIDA9PT1pKXJldHVybiBvLnByb3RvdHlwZS5vbi5jYWxsKHRoaXMsdCxlKTt2YXIgYT1mdW5jdGlvbigpe3ZhciBvO2lmKFwibW91c2VlbnRlclwiPT09dHx8XCJtb3VzZW92ZXJcIj09PXQpe3ZhciBhPSExO3JldHVybiB7bGF5ZXI6ZSxsaXN0ZW5lcjppLGRlbGVnYXRlczp7bW91c2Vtb3ZlOmZ1bmN0aW9uKG8pe3ZhciBuPXIuZ2V0TGF5ZXIoZSk/ci5xdWVyeVJlbmRlcmVkRmVhdHVyZXMoby5wb2ludCx7bGF5ZXJzOltlXX0pOltdO24ubGVuZ3RoP2F8fChhPSEwLGkuY2FsbChyLG5ldyBwbyh0LHIsby5vcmlnaW5hbEV2ZW50LHtmZWF0dXJlczpufSkpKTphPSExO30sbW91c2VvdXQ6ZnVuY3Rpb24oKXthPSExO319fX1pZihcIm1vdXNlbGVhdmVcIj09PXR8fFwibW91c2VvdXRcIj09PXQpe3ZhciBuPSExO3JldHVybiB7bGF5ZXI6ZSxsaXN0ZW5lcjppLGRlbGVnYXRlczp7bW91c2Vtb3ZlOmZ1bmN0aW9uKG8peyhyLmdldExheWVyKGUpP3IucXVlcnlSZW5kZXJlZEZlYXR1cmVzKG8ucG9pbnQse2xheWVyczpbZV19KTpbXSkubGVuZ3RoP249ITA6biYmKG49ITEsaS5jYWxsKHIsbmV3IHBvKHQscixvLm9yaWdpbmFsRXZlbnQpKSk7fSxtb3VzZW91dDpmdW5jdGlvbihlKXtuJiYobj0hMSxpLmNhbGwocixuZXcgcG8odCxyLGUub3JpZ2luYWxFdmVudCkpKTt9fX19cmV0dXJuIHtsYXllcjplLGxpc3RlbmVyOmksZGVsZWdhdGVzOihvPXt9LG9bdF09ZnVuY3Rpb24odCl7dmFyIG89ci5nZXRMYXllcihlKT9yLnF1ZXJ5UmVuZGVyZWRGZWF0dXJlcyh0LnBvaW50LHtsYXllcnM6W2VdfSk6W107by5sZW5ndGgmJih0LmZlYXR1cmVzPW8saS5jYWxsKHIsdCksZGVsZXRlIHQuZmVhdHVyZXMpO30sbyl9fSgpO2Zvcih2YXIgbiBpbiB0aGlzLl9kZWxlZ2F0ZWRMaXN0ZW5lcnM9dGhpcy5fZGVsZWdhdGVkTGlzdGVuZXJzfHx7fSx0aGlzLl9kZWxlZ2F0ZWRMaXN0ZW5lcnNbdF09dGhpcy5fZGVsZWdhdGVkTGlzdGVuZXJzW3RdfHxbXSx0aGlzLl9kZWxlZ2F0ZWRMaXN0ZW5lcnNbdF0ucHVzaChhKSxhLmRlbGVnYXRlcyl0aGlzLm9uKG4sYS5kZWxlZ2F0ZXNbbl0pO3JldHVybiB0aGlzfSxyLnByb3RvdHlwZS5vZmY9ZnVuY3Rpb24odCxlLGkpe2lmKHZvaWQgMD09PWkpcmV0dXJuIG8ucHJvdG90eXBlLm9mZi5jYWxsKHRoaXMsdCxlKTtpZih0aGlzLl9kZWxlZ2F0ZWRMaXN0ZW5lcnMmJnRoaXMuX2RlbGVnYXRlZExpc3RlbmVyc1t0XSlmb3IodmFyIHI9dGhpcy5fZGVsZWdhdGVkTGlzdGVuZXJzW3RdLGE9MDthPHIubGVuZ3RoO2ErKyl7dmFyIG49clthXTtpZihuLmxheWVyPT09ZSYmbi5saXN0ZW5lcj09PWkpe2Zvcih2YXIgcyBpbiBuLmRlbGVnYXRlcyl0aGlzLm9mZihzLG4uZGVsZWdhdGVzW3NdKTtyZXR1cm4gci5zcGxpY2UoYSwxKSx0aGlzfX1yZXR1cm4gdGhpc30sci5wcm90b3R5cGUucXVlcnlSZW5kZXJlZEZlYXR1cmVzPWZ1bmN0aW9uKGUsaSl7aWYoIXRoaXMuc3R5bGUpcmV0dXJuIFtdO3ZhciBvO2lmKHZvaWQgMCE9PWl8fHZvaWQgMD09PWV8fGUgaW5zdGFuY2VvZiB0LlBvaW50fHxBcnJheS5pc0FycmF5KGUpfHwoaT1lLGU9dm9pZCAwKSxpPWl8fHt9LChlPWV8fFtbMCwwXSxbdGhpcy50cmFuc2Zvcm0ud2lkdGgsdGhpcy50cmFuc2Zvcm0uaGVpZ2h0XV0paW5zdGFuY2VvZiB0LlBvaW50fHxcIm51bWJlclwiPT10eXBlb2YgZVswXSlvPVt0LlBvaW50LmNvbnZlcnQoZSldO2Vsc2V7dmFyIHI9dC5Qb2ludC5jb252ZXJ0KGVbMF0pLGE9dC5Qb2ludC5jb252ZXJ0KGVbMV0pO289W3IsbmV3IHQuUG9pbnQoYS54LHIueSksYSxuZXcgdC5Qb2ludChyLngsYS55KSxyXTt9cmV0dXJuIHRoaXMuc3R5bGUucXVlcnlSZW5kZXJlZEZlYXR1cmVzKG8saSx0aGlzLnRyYW5zZm9ybSl9LHIucHJvdG90eXBlLnF1ZXJ5U291cmNlRmVhdHVyZXM9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5zdHlsZS5xdWVyeVNvdXJjZUZlYXR1cmVzKHQsZSl9LHIucHJvdG90eXBlLnNldFN0eWxlPWZ1bmN0aW9uKGUsaSl7cmV0dXJuICExIT09KGk9dC5leHRlbmQoe30se2xvY2FsSWRlb2dyYXBoRm9udEZhbWlseTpBby5sb2NhbElkZW9ncmFwaEZvbnRGYW1pbHl9LGkpKS5kaWZmJiZpLmxvY2FsSWRlb2dyYXBoRm9udEZhbWlseT09PXRoaXMuX2xvY2FsSWRlb2dyYXBoRm9udEZhbWlseSYmdGhpcy5zdHlsZSYmZT8odGhpcy5fZGlmZlN0eWxlKGUsaSksdGhpcyk6KHRoaXMuX2xvY2FsSWRlb2dyYXBoRm9udEZhbWlseT1pLmxvY2FsSWRlb2dyYXBoRm9udEZhbWlseSx0aGlzLl91cGRhdGVTdHlsZShlLGkpKX0sci5wcm90b3R5cGUuX3VwZGF0ZVN0eWxlPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuc3R5bGUmJih0aGlzLnN0eWxlLnNldEV2ZW50ZWRQYXJlbnQobnVsbCksdGhpcy5zdHlsZS5fcmVtb3ZlKCkpLHQ/KHRoaXMuc3R5bGU9bmV3IEJlKHRoaXMsZXx8e30pLHRoaXMuc3R5bGUuc2V0RXZlbnRlZFBhcmVudCh0aGlzLHtzdHlsZTp0aGlzLnN0eWxlfSksXCJzdHJpbmdcIj09dHlwZW9mIHQ/dGhpcy5zdHlsZS5sb2FkVVJMKHQpOnRoaXMuc3R5bGUubG9hZEpTT04odCksdGhpcyk6KGRlbGV0ZSB0aGlzLnN0eWxlLHRoaXMpfSxyLnByb3RvdHlwZS5fZGlmZlN0eWxlPWZ1bmN0aW9uKGUsaSl7dmFyIG89dGhpcztpZihcInN0cmluZ1wiPT10eXBlb2YgZSl7dmFyIHI9dGhpcy5fcmVxdWVzdE1hbmFnZXIubm9ybWFsaXplU3R5bGVVUkwoZSksYT10aGlzLl9yZXF1ZXN0TWFuYWdlci50cmFuc2Zvcm1SZXF1ZXN0KHIsdC5SZXNvdXJjZVR5cGUuU3R5bGUpO3QuZ2V0SlNPTihhLGZ1bmN0aW9uKGUscil7ZT9vLmZpcmUobmV3IHQuRXJyb3JFdmVudChlKSk6ciYmby5fdXBkYXRlRGlmZihyLGkpO30pO31lbHNlXCJvYmplY3RcIj09dHlwZW9mIGUmJnRoaXMuX3VwZGF0ZURpZmYoZSxpKTt9LHIucHJvdG90eXBlLl91cGRhdGVEaWZmPWZ1bmN0aW9uKGUsaSl7dHJ5e3RoaXMuc3R5bGUuc2V0U3RhdGUoZSkmJnRoaXMuX3VwZGF0ZSghMCk7fWNhdGNoKG8pe3Qud2Fybk9uY2UoXCJVbmFibGUgdG8gcGVyZm9ybSBzdHlsZSBkaWZmOiBcIisoby5tZXNzYWdlfHxvLmVycm9yfHxvKStcIi4gIFJlYnVpbGRpbmcgdGhlIHN0eWxlIGZyb20gc2NyYXRjaC5cIiksdGhpcy5fdXBkYXRlU3R5bGUoZSxpKTt9fSxyLnByb3RvdHlwZS5nZXRTdHlsZT1mdW5jdGlvbigpe2lmKHRoaXMuc3R5bGUpcmV0dXJuIHRoaXMuc3R5bGUuc2VyaWFsaXplKCl9LHIucHJvdG90eXBlLmlzU3R5bGVMb2FkZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zdHlsZT90aGlzLnN0eWxlLmxvYWRlZCgpOnQud2Fybk9uY2UoXCJUaGVyZSBpcyBubyBzdHlsZSBhZGRlZCB0byB0aGUgbWFwLlwiKX0sci5wcm90b3R5cGUuYWRkU291cmNlPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuc3R5bGUuYWRkU291cmNlKHQsZSksdGhpcy5fdXBkYXRlKCEwKX0sci5wcm90b3R5cGUuaXNTb3VyY2VMb2FkZWQ9ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcy5zdHlsZSYmdGhpcy5zdHlsZS5zb3VyY2VDYWNoZXNbZV07aWYodm9pZCAwIT09aSlyZXR1cm4gaS5sb2FkZWQoKTt0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJUaGVyZSBpcyBubyBzb3VyY2Ugd2l0aCBJRCAnXCIrZStcIidcIikpKTt9LHIucHJvdG90eXBlLmFyZVRpbGVzTG9hZGVkPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5zdHlsZSYmdGhpcy5zdHlsZS5zb3VyY2VDYWNoZXM7Zm9yKHZhciBlIGluIHQpe3ZhciBpPXRbZV0uX3RpbGVzO2Zvcih2YXIgbyBpbiBpKXt2YXIgcj1pW29dO2lmKFwibG9hZGVkXCIhPT1yLnN0YXRlJiZcImVycm9yZWRcIiE9PXIuc3RhdGUpcmV0dXJuICExfX1yZXR1cm4gITB9LHIucHJvdG90eXBlLmFkZFNvdXJjZVR5cGU9ZnVuY3Rpb24odCxlLGkpe3JldHVybiB0aGlzLnN0eWxlLmFkZFNvdXJjZVR5cGUodCxlLGkpfSxyLnByb3RvdHlwZS5yZW1vdmVTb3VyY2U9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuc3R5bGUucmVtb3ZlU291cmNlKHQpLHRoaXMuX3VwZGF0ZSghMCl9LHIucHJvdG90eXBlLmdldFNvdXJjZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zdHlsZS5nZXRTb3VyY2UodCl9LHIucHJvdG90eXBlLmFkZEltYWdlPWZ1bmN0aW9uKGUsaSxvKXt2b2lkIDA9PT1vJiYobz17fSk7dmFyIHI9by5waXhlbFJhdGlvO3ZvaWQgMD09PXImJihyPTEpO3ZhciBhPW8uc2RmO3ZvaWQgMD09PWEmJihhPSExKTtpZihpIGluc3RhbmNlb2YgTW8pe3ZhciBuPXQuYnJvd3Nlci5nZXRJbWFnZURhdGEoaSkscz1uLndpZHRoLGw9bi5oZWlnaHQsYz1uLmRhdGE7dGhpcy5zdHlsZS5hZGRJbWFnZShlLHtkYXRhOm5ldyB0LlJHQkFJbWFnZSh7d2lkdGg6cyxoZWlnaHQ6bH0sYykscGl4ZWxSYXRpbzpyLHNkZjphLHZlcnNpb246MH0pO31lbHNle2lmKHZvaWQgMD09PWkud2lkdGh8fHZvaWQgMD09PWkuaGVpZ2h0KXJldHVybiB0aGlzLmZpcmUobmV3IHQuRXJyb3JFdmVudChuZXcgRXJyb3IoXCJJbnZhbGlkIGFyZ3VtZW50cyB0byBtYXAuYWRkSW1hZ2UoKS4gVGhlIHNlY29uZCBhcmd1bWVudCBtdXN0IGJlIGFuIGBIVE1MSW1hZ2VFbGVtZW50YCwgYEltYWdlRGF0YWAsIG9yIG9iamVjdCB3aXRoIGB3aWR0aGAsIGBoZWlnaHRgLCBhbmQgYGRhdGFgIHByb3BlcnRpZXMgd2l0aCB0aGUgc2FtZSBmb3JtYXQgYXMgYEltYWdlRGF0YWBcIikpKTt2YXIgdT1pLndpZHRoLGg9aS5oZWlnaHQscD1pLmRhdGEsZD1pO3RoaXMuc3R5bGUuYWRkSW1hZ2UoZSx7ZGF0YTpuZXcgdC5SR0JBSW1hZ2Uoe3dpZHRoOnUsaGVpZ2h0Omh9LG5ldyBVaW50OEFycmF5KHApKSxwaXhlbFJhdGlvOnIsc2RmOmEsdmVyc2lvbjowLHVzZXJJbWFnZTpkfSksZC5vbkFkZCYmZC5vbkFkZCh0aGlzLGUpO319LHIucHJvdG90eXBlLnVwZGF0ZUltYWdlPWZ1bmN0aW9uKGUsaSl7dmFyIG89dGhpcy5zdHlsZS5nZXRJbWFnZShlKTtpZighbylyZXR1cm4gdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiVGhlIG1hcCBoYXMgbm8gaW1hZ2Ugd2l0aCB0aGF0IGlkLiBJZiB5b3UgYXJlIGFkZGluZyBhIG5ldyBpbWFnZSB1c2UgYG1hcC5hZGRJbWFnZSguLi4pYCBpbnN0ZWFkLlwiKSkpO3ZhciByPWkgaW5zdGFuY2VvZiBNbz90LmJyb3dzZXIuZ2V0SW1hZ2VEYXRhKGkpOmksYT1yLndpZHRoLG49ci5oZWlnaHQscz1yLmRhdGE7aWYodm9pZCAwPT09YXx8dm9pZCAwPT09bilyZXR1cm4gdGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiSW52YWxpZCBhcmd1bWVudHMgdG8gbWFwLnVwZGF0ZUltYWdlKCkuIFRoZSBzZWNvbmQgYXJndW1lbnQgbXVzdCBiZSBhbiBgSFRNTEltYWdlRWxlbWVudGAsIGBJbWFnZURhdGFgLCBvciBvYmplY3Qgd2l0aCBgd2lkdGhgLCBgaGVpZ2h0YCwgYW5kIGBkYXRhYCBwcm9wZXJ0aWVzIHdpdGggdGhlIHNhbWUgZm9ybWF0IGFzIGBJbWFnZURhdGFgXCIpKSk7aWYoYSE9PW8uZGF0YS53aWR0aHx8biE9PW8uZGF0YS5oZWlnaHQpcmV0dXJuIHRoaXMuZmlyZShuZXcgdC5FcnJvckV2ZW50KG5ldyBFcnJvcihcIlRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSB1cGRhdGVkIGltYWdlIG11c3QgYmUgdGhhdCBzYW1lIGFzIHRoZSBwcmV2aW91cyB2ZXJzaW9uIG9mIHRoZSBpbWFnZVwiKSkpO3ZhciBsPSEoaSBpbnN0YW5jZW9mIE1vKTtvLmRhdGEucmVwbGFjZShzLGwpLHRoaXMuc3R5bGUudXBkYXRlSW1hZ2UoZSxvKTt9LHIucHJvdG90eXBlLmhhc0ltYWdlPWZ1bmN0aW9uKGUpe3JldHVybiBlPyEhdGhpcy5zdHlsZS5nZXRJbWFnZShlKToodGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiTWlzc2luZyByZXF1aXJlZCBpbWFnZSBpZFwiKSkpLCExKX0sci5wcm90b3R5cGUucmVtb3ZlSW1hZ2U9ZnVuY3Rpb24odCl7dGhpcy5zdHlsZS5yZW1vdmVJbWFnZSh0KTt9LHIucHJvdG90eXBlLmxvYWRJbWFnZT1mdW5jdGlvbihlLGkpe3QuZ2V0SW1hZ2UodGhpcy5fcmVxdWVzdE1hbmFnZXIudHJhbnNmb3JtUmVxdWVzdChlLHQuUmVzb3VyY2VUeXBlLkltYWdlKSxpKTt9LHIucHJvdG90eXBlLmxpc3RJbWFnZXM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zdHlsZS5saXN0SW1hZ2VzKCl9LHIucHJvdG90eXBlLmFkZExheWVyPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuc3R5bGUuYWRkTGF5ZXIodCxlKSx0aGlzLl91cGRhdGUoITApfSxyLnByb3RvdHlwZS5tb3ZlTGF5ZXI9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5zdHlsZS5tb3ZlTGF5ZXIodCxlKSx0aGlzLl91cGRhdGUoITApfSxyLnByb3RvdHlwZS5yZW1vdmVMYXllcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zdHlsZS5yZW1vdmVMYXllcih0KSx0aGlzLl91cGRhdGUoITApfSxyLnByb3RvdHlwZS5nZXRMYXllcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zdHlsZS5nZXRMYXllcih0KX0sci5wcm90b3R5cGUuc2V0RmlsdGVyPWZ1bmN0aW9uKHQsZSxpKXtyZXR1cm4gdm9pZCAwPT09aSYmKGk9e30pLHRoaXMuc3R5bGUuc2V0RmlsdGVyKHQsZSxpKSx0aGlzLl91cGRhdGUoITApfSxyLnByb3RvdHlwZS5zZXRMYXllclpvb21SYW5nZT1mdW5jdGlvbih0LGUsaSl7cmV0dXJuIHRoaXMuc3R5bGUuc2V0TGF5ZXJab29tUmFuZ2UodCxlLGkpLHRoaXMuX3VwZGF0ZSghMCl9LHIucHJvdG90eXBlLmdldEZpbHRlcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zdHlsZS5nZXRGaWx0ZXIodCl9LHIucHJvdG90eXBlLnNldFBhaW50UHJvcGVydHk9ZnVuY3Rpb24odCxlLGksbyl7cmV0dXJuIHZvaWQgMD09PW8mJihvPXt9KSx0aGlzLnN0eWxlLnNldFBhaW50UHJvcGVydHkodCxlLGksbyksdGhpcy5fdXBkYXRlKCEwKX0sci5wcm90b3R5cGUuZ2V0UGFpbnRQcm9wZXJ0eT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnN0eWxlLmdldFBhaW50UHJvcGVydHkodCxlKX0sci5wcm90b3R5cGUuc2V0TGF5b3V0UHJvcGVydHk9ZnVuY3Rpb24odCxlLGksbyl7cmV0dXJuIHZvaWQgMD09PW8mJihvPXt9KSx0aGlzLnN0eWxlLnNldExheW91dFByb3BlcnR5KHQsZSxpLG8pLHRoaXMuX3VwZGF0ZSghMCl9LHIucHJvdG90eXBlLmdldExheW91dFByb3BlcnR5PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuc3R5bGUuZ2V0TGF5b3V0UHJvcGVydHkodCxlKX0sci5wcm90b3R5cGUuc2V0TGlnaHQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdm9pZCAwPT09ZSYmKGU9e30pLHRoaXMuc3R5bGUuc2V0TGlnaHQodCxlKSx0aGlzLl91cGRhdGUoITApfSxyLnByb3RvdHlwZS5nZXRMaWdodD1mdW5jdGlvbigpe3JldHVybiB0aGlzLnN0eWxlLmdldExpZ2h0KCl9LHIucHJvdG90eXBlLnNldEZlYXR1cmVTdGF0ZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnN0eWxlLnNldEZlYXR1cmVTdGF0ZSh0LGUpLHRoaXMuX3VwZGF0ZSgpfSxyLnByb3RvdHlwZS5yZW1vdmVGZWF0dXJlU3RhdGU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5zdHlsZS5yZW1vdmVGZWF0dXJlU3RhdGUodCxlKSx0aGlzLl91cGRhdGUoKX0sci5wcm90b3R5cGUuZ2V0RmVhdHVyZVN0YXRlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnN0eWxlLmdldEZlYXR1cmVTdGF0ZSh0KX0sci5wcm90b3R5cGUuZ2V0Q29udGFpbmVyPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NvbnRhaW5lcn0sci5wcm90b3R5cGUuZ2V0Q2FudmFzQ29udGFpbmVyPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NhbnZhc0NvbnRhaW5lcn0sci5wcm90b3R5cGUuZ2V0Q2FudmFzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NhbnZhc30sci5wcm90b3R5cGUuX2NvbnRhaW5lckRpbWVuc2lvbnM9ZnVuY3Rpb24oKXt2YXIgdD0wLGU9MDtyZXR1cm4gdGhpcy5fY29udGFpbmVyJiYodD10aGlzLl9jb250YWluZXIuY2xpZW50V2lkdGh8fDQwMCxlPXRoaXMuX2NvbnRhaW5lci5jbGllbnRIZWlnaHR8fDMwMCksW3QsZV19LHIucHJvdG90eXBlLl9kZXRlY3RNaXNzaW5nQ1NTPWZ1bmN0aW9uKCl7XCJyZ2IoMjUwLCAxMjgsIDExNClcIiE9PXQud2luZG93LmdldENvbXB1dGVkU3R5bGUodGhpcy5fbWlzc2luZ0NTU0NhbmFyeSkuZ2V0UHJvcGVydHlWYWx1ZShcImJhY2tncm91bmQtY29sb3JcIikmJnQud2Fybk9uY2UoXCJUaGlzIHBhZ2UgYXBwZWFycyB0byBiZSBtaXNzaW5nIENTUyBkZWNsYXJhdGlvbnMgZm9yIE1hcGJveCBHTCBKUywgd2hpY2ggbWF5IGNhdXNlIHRoZSBtYXAgdG8gZGlzcGxheSBpbmNvcnJlY3RseS4gUGxlYXNlIGVuc3VyZSB5b3VyIHBhZ2UgaW5jbHVkZXMgbWFwYm94LWdsLmNzcywgYXMgZGVzY3JpYmVkIGluIGh0dHBzOi8vd3d3Lm1hcGJveC5jb20vbWFwYm94LWdsLWpzL2FwaS8uXCIpO30sci5wcm90b3R5cGUuX3NldHVwQ29udGFpbmVyPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5fY29udGFpbmVyO3QuY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLW1hcFwiKSwodGhpcy5fbWlzc2luZ0NTU0NhbmFyeT1pLmNyZWF0ZShcImRpdlwiLFwibWFwYm94Z2wtY2FuYXJ5XCIsdCkpLnN0eWxlLnZpc2liaWxpdHk9XCJoaWRkZW5cIix0aGlzLl9kZXRlY3RNaXNzaW5nQ1NTKCk7dmFyIGU9dGhpcy5fY2FudmFzQ29udGFpbmVyPWkuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1jYW52YXMtY29udGFpbmVyXCIsdCk7dGhpcy5faW50ZXJhY3RpdmUmJmUuY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWludGVyYWN0aXZlXCIpLHRoaXMuX2NhbnZhcz1pLmNyZWF0ZShcImNhbnZhc1wiLFwibWFwYm94Z2wtY2FudmFzXCIsZSksdGhpcy5fY2FudmFzLnN0eWxlLnBvc2l0aW9uPVwiYWJzb2x1dGVcIix0aGlzLl9jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcihcIndlYmdsY29udGV4dGxvc3RcIix0aGlzLl9jb250ZXh0TG9zdCwhMSksdGhpcy5fY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoXCJ3ZWJnbGNvbnRleHRyZXN0b3JlZFwiLHRoaXMuX2NvbnRleHRSZXN0b3JlZCwhMSksdGhpcy5fY2FudmFzLnNldEF0dHJpYnV0ZShcInRhYmluZGV4XCIsXCIwXCIpLHRoaXMuX2NhbnZhcy5zZXRBdHRyaWJ1dGUoXCJhcmlhLWxhYmVsXCIsXCJNYXBcIik7dmFyIG89dGhpcy5fY29udGFpbmVyRGltZW5zaW9ucygpO3RoaXMuX3Jlc2l6ZUNhbnZhcyhvWzBdLG9bMV0pO3ZhciByPXRoaXMuX2NvbnRyb2xDb250YWluZXI9aS5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLWNvbnRyb2wtY29udGFpbmVyXCIsdCksYT10aGlzLl9jb250cm9sUG9zaXRpb25zPXt9O1tcInRvcC1sZWZ0XCIsXCJ0b3AtcmlnaHRcIixcImJvdHRvbS1sZWZ0XCIsXCJib3R0b20tcmlnaHRcIl0uZm9yRWFjaChmdW5jdGlvbih0KXthW3RdPWkuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1jdHJsLVwiK3Qscik7fSk7fSxyLnByb3RvdHlwZS5fcmVzaXplQ2FudmFzPWZ1bmN0aW9uKGUsaSl7dmFyIG89dC53aW5kb3cuZGV2aWNlUGl4ZWxSYXRpb3x8MTt0aGlzLl9jYW52YXMud2lkdGg9byplLHRoaXMuX2NhbnZhcy5oZWlnaHQ9byppLHRoaXMuX2NhbnZhcy5zdHlsZS53aWR0aD1lK1wicHhcIix0aGlzLl9jYW52YXMuc3R5bGUuaGVpZ2h0PWkrXCJweFwiO30sci5wcm90b3R5cGUuX3NldHVwUGFpbnRlcj1mdW5jdGlvbigpe3ZhciBpPXQuZXh0ZW5kKHt9LGUud2ViR0xDb250ZXh0QXR0cmlidXRlcyx7ZmFpbElmTWFqb3JQZXJmb3JtYW5jZUNhdmVhdDp0aGlzLl9mYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0LHByZXNlcnZlRHJhd2luZ0J1ZmZlcjp0aGlzLl9wcmVzZXJ2ZURyYXdpbmdCdWZmZXIsYW50aWFsaWFzOnRoaXMuX2FudGlhbGlhc3x8ITF9KSxvPXRoaXMuX2NhbnZhcy5nZXRDb250ZXh0KFwid2ViZ2xcIixpKXx8dGhpcy5fY2FudmFzLmdldENvbnRleHQoXCJleHBlcmltZW50YWwtd2ViZ2xcIixpKTtvPyh0aGlzLnBhaW50ZXI9bmV3IGFvKG8sdGhpcy50cmFuc2Zvcm0pLHQud2VicFN1cHBvcnRlZC50ZXN0U3VwcG9ydChvKSk6dGhpcy5maXJlKG5ldyB0LkVycm9yRXZlbnQobmV3IEVycm9yKFwiRmFpbGVkIHRvIGluaXRpYWxpemUgV2ViR0xcIikpKTt9LHIucHJvdG90eXBlLl9jb250ZXh0TG9zdD1mdW5jdGlvbihlKXtlLnByZXZlbnREZWZhdWx0KCksdGhpcy5fZnJhbWUmJih0aGlzLl9mcmFtZS5jYW5jZWwoKSx0aGlzLl9mcmFtZT1udWxsKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJ3ZWJnbGNvbnRleHRsb3N0XCIse29yaWdpbmFsRXZlbnQ6ZX0pKTt9LHIucHJvdG90eXBlLl9jb250ZXh0UmVzdG9yZWQ9ZnVuY3Rpb24oZSl7dGhpcy5fc2V0dXBQYWludGVyKCksdGhpcy5yZXNpemUoKSx0aGlzLl91cGRhdGUoKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJ3ZWJnbGNvbnRleHRyZXN0b3JlZFwiLHtvcmlnaW5hbEV2ZW50OmV9KSk7fSxyLnByb3RvdHlwZS5sb2FkZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gIXRoaXMuX3N0eWxlRGlydHkmJiF0aGlzLl9zb3VyY2VzRGlydHkmJiEhdGhpcy5zdHlsZSYmdGhpcy5zdHlsZS5sb2FkZWQoKX0sci5wcm90b3R5cGUuX3VwZGF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zdHlsZT8odGhpcy5fc3R5bGVEaXJ0eT10aGlzLl9zdHlsZURpcnR5fHx0LHRoaXMuX3NvdXJjZXNEaXJ0eT0hMCx0aGlzLnRyaWdnZXJSZXBhaW50KCksdGhpcyk6dGhpc30sci5wcm90b3R5cGUuX3JlcXVlc3RSZW5kZXJGcmFtZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fdXBkYXRlKCksdGhpcy5fcmVuZGVyVGFza1F1ZXVlLmFkZCh0KX0sci5wcm90b3R5cGUuX2NhbmNlbFJlbmRlckZyYW1lPWZ1bmN0aW9uKHQpe3RoaXMuX3JlbmRlclRhc2tRdWV1ZS5yZW1vdmUodCk7fSxyLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKCl7dGhpcy5wYWludGVyLmNvbnRleHQuc2V0RGlydHkoKSx0aGlzLnBhaW50ZXIuc2V0QmFzZVN0YXRlKCksdGhpcy5fcmVuZGVyVGFza1F1ZXVlLnJ1bigpO3ZhciBlPSExO2lmKHRoaXMuc3R5bGUmJnRoaXMuX3N0eWxlRGlydHkpe3RoaXMuX3N0eWxlRGlydHk9ITE7dmFyIGk9dGhpcy50cmFuc2Zvcm0uem9vbSxvPXQuYnJvd3Nlci5ub3coKTt0aGlzLnN0eWxlLnpvb21IaXN0b3J5LnVwZGF0ZShpLG8pO3ZhciByPW5ldyB0LkV2YWx1YXRpb25QYXJhbWV0ZXJzKGkse25vdzpvLGZhZGVEdXJhdGlvbjp0aGlzLl9mYWRlRHVyYXRpb24sem9vbUhpc3Rvcnk6dGhpcy5zdHlsZS56b29tSGlzdG9yeSx0cmFuc2l0aW9uOnRoaXMuc3R5bGUuZ2V0VHJhbnNpdGlvbigpfSksYT1yLmNyb3NzRmFkaW5nRmFjdG9yKCk7MT09PWEmJmE9PT10aGlzLl9jcm9zc0ZhZGluZ0ZhY3Rvcnx8KGU9ITAsdGhpcy5fY3Jvc3NGYWRpbmdGYWN0b3I9YSksdGhpcy5zdHlsZS51cGRhdGUocik7fXJldHVybiB0aGlzLnN0eWxlJiZ0aGlzLl9zb3VyY2VzRGlydHkmJih0aGlzLl9zb3VyY2VzRGlydHk9ITEsdGhpcy5zdHlsZS5fdXBkYXRlU291cmNlcyh0aGlzLnRyYW5zZm9ybSkpLHRoaXMuX3BsYWNlbWVudERpcnR5PXRoaXMuc3R5bGUmJnRoaXMuc3R5bGUuX3VwZGF0ZVBsYWNlbWVudCh0aGlzLnBhaW50ZXIudHJhbnNmb3JtLHRoaXMuc2hvd0NvbGxpc2lvbkJveGVzLHRoaXMuX2ZhZGVEdXJhdGlvbix0aGlzLl9jcm9zc1NvdXJjZUNvbGxpc2lvbnMpLHRoaXMucGFpbnRlci5yZW5kZXIodGhpcy5zdHlsZSx7c2hvd1RpbGVCb3VuZGFyaWVzOnRoaXMuc2hvd1RpbGVCb3VuZGFyaWVzLHNob3dPdmVyZHJhd0luc3BlY3Rvcjp0aGlzLl9zaG93T3ZlcmRyYXdJbnNwZWN0b3Iscm90YXRpbmc6dGhpcy5pc1JvdGF0aW5nKCksem9vbWluZzp0aGlzLmlzWm9vbWluZygpLG1vdmluZzp0aGlzLmlzTW92aW5nKCksZmFkZUR1cmF0aW9uOnRoaXMuX2ZhZGVEdXJhdGlvbn0pLHRoaXMuZmlyZShuZXcgdC5FdmVudChcInJlbmRlclwiKSksdGhpcy5sb2FkZWQoKSYmIXRoaXMuX2xvYWRlZCYmKHRoaXMuX2xvYWRlZD0hMCx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJsb2FkXCIpKSksdGhpcy5zdHlsZSYmKHRoaXMuc3R5bGUuaGFzVHJhbnNpdGlvbnMoKXx8ZSkmJih0aGlzLl9zdHlsZURpcnR5PSEwKSx0aGlzLnN0eWxlJiYhdGhpcy5fcGxhY2VtZW50RGlydHkmJnRoaXMuc3R5bGUuX3JlbGVhc2VTeW1ib2xGYWRlVGlsZXMoKSx0aGlzLl9zb3VyY2VzRGlydHl8fHRoaXMuX3JlcGFpbnR8fHRoaXMuX3N0eWxlRGlydHl8fHRoaXMuX3BsYWNlbWVudERpcnR5P3RoaXMudHJpZ2dlclJlcGFpbnQoKTohdGhpcy5pc01vdmluZygpJiZ0aGlzLmxvYWRlZCgpJiZ0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJpZGxlXCIpKSx0aGlzfSxyLnByb3RvdHlwZS5yZW1vdmU9ZnVuY3Rpb24oKXt0aGlzLl9oYXNoJiZ0aGlzLl9oYXNoLnJlbW92ZSgpO2Zvcih2YXIgZT0wLGk9dGhpcy5fY29udHJvbHM7ZTxpLmxlbmd0aDtlKz0xKXtpW2VdLm9uUmVtb3ZlKHRoaXMpO310aGlzLl9jb250cm9scz1bXSx0aGlzLl9mcmFtZSYmKHRoaXMuX2ZyYW1lLmNhbmNlbCgpLHRoaXMuX2ZyYW1lPW51bGwpLHRoaXMuX3JlbmRlclRhc2tRdWV1ZS5jbGVhcigpLHRoaXMuc2V0U3R5bGUobnVsbCksdm9pZCAwIT09dC53aW5kb3cmJih0LndpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwicmVzaXplXCIsdGhpcy5fb25XaW5kb3dSZXNpemUsITEpLHQud2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJvbmxpbmVcIix0aGlzLl9vbldpbmRvd09ubGluZSwhMSkpO3ZhciBvPXRoaXMucGFpbnRlci5jb250ZXh0LmdsLmdldEV4dGVuc2lvbihcIldFQkdMX2xvc2VfY29udGV4dFwiKTtvJiZvLmxvc2VDb250ZXh0KCksQm8odGhpcy5fY2FudmFzQ29udGFpbmVyKSxCbyh0aGlzLl9jb250cm9sQ29udGFpbmVyKSxCbyh0aGlzLl9taXNzaW5nQ1NTQ2FuYXJ5KSx0aGlzLl9jb250YWluZXIuY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLW1hcFwiKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJyZW1vdmVcIikpO30sci5wcm90b3R5cGUudHJpZ2dlclJlcGFpbnQ9ZnVuY3Rpb24oKXt2YXIgZT10aGlzO3RoaXMuc3R5bGUmJiF0aGlzLl9mcmFtZSYmKHRoaXMuX2ZyYW1lPXQuYnJvd3Nlci5mcmFtZShmdW5jdGlvbigpe2UuX2ZyYW1lPW51bGwsZS5fcmVuZGVyKCk7fSkpO30sci5wcm90b3R5cGUuX29uV2luZG93T25saW5lPWZ1bmN0aW9uKCl7dGhpcy5fdXBkYXRlKCk7fSxyLnByb3RvdHlwZS5fb25XaW5kb3dSZXNpemU9ZnVuY3Rpb24oKXt0aGlzLl90cmFja1Jlc2l6ZSYmdGhpcy5yZXNpemUoKS5fdXBkYXRlKCk7fSxhLnNob3dUaWxlQm91bmRhcmllcy5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gISF0aGlzLl9zaG93VGlsZUJvdW5kYXJpZXN9LGEuc2hvd1RpbGVCb3VuZGFyaWVzLnNldD1mdW5jdGlvbih0KXt0aGlzLl9zaG93VGlsZUJvdW5kYXJpZXMhPT10JiYodGhpcy5fc2hvd1RpbGVCb3VuZGFyaWVzPXQsdGhpcy5fdXBkYXRlKCkpO30sYS5zaG93Q29sbGlzaW9uQm94ZXMuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuICEhdGhpcy5fc2hvd0NvbGxpc2lvbkJveGVzfSxhLnNob3dDb2xsaXNpb25Cb3hlcy5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fc2hvd0NvbGxpc2lvbkJveGVzIT09dCYmKHRoaXMuX3Nob3dDb2xsaXNpb25Cb3hlcz10LHQ/dGhpcy5zdHlsZS5fZ2VuZXJhdGVDb2xsaXNpb25Cb3hlcygpOnRoaXMuX3VwZGF0ZSgpKTt9LGEuc2hvd092ZXJkcmF3SW5zcGVjdG9yLmdldD1mdW5jdGlvbigpe3JldHVybiAhIXRoaXMuX3Nob3dPdmVyZHJhd0luc3BlY3Rvcn0sYS5zaG93T3ZlcmRyYXdJbnNwZWN0b3Iuc2V0PWZ1bmN0aW9uKHQpe3RoaXMuX3Nob3dPdmVyZHJhd0luc3BlY3RvciE9PXQmJih0aGlzLl9zaG93T3ZlcmRyYXdJbnNwZWN0b3I9dCx0aGlzLl91cGRhdGUoKSk7fSxhLnJlcGFpbnQuZ2V0PWZ1bmN0aW9uKCl7cmV0dXJuICEhdGhpcy5fcmVwYWludH0sYS5yZXBhaW50LnNldD1mdW5jdGlvbih0KXt0aGlzLl9yZXBhaW50IT09dCYmKHRoaXMuX3JlcGFpbnQ9dCx0aGlzLnRyaWdnZXJSZXBhaW50KCkpO30sYS52ZXJ0aWNlcy5nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gISF0aGlzLl92ZXJ0aWNlc30sYS52ZXJ0aWNlcy5zZXQ9ZnVuY3Rpb24odCl7dGhpcy5fdmVydGljZXM9dCx0aGlzLl91cGRhdGUoKTt9LHIucHJvdG90eXBlLl9zZXRDYWNoZUxpbWl0cz1mdW5jdGlvbihlLGkpe3Quc2V0Q2FjaGVMaW1pdHMoZSxpKTt9LE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHIucHJvdG90eXBlLGEpLHJ9KFBvKTtmdW5jdGlvbiBCbyh0KXt0LnBhcmVudE5vZGUmJnQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0KTt9dmFyIE9vPXtzaG93Q29tcGFzczohMCxzaG93Wm9vbTohMH0sRm89ZnVuY3Rpb24oZSl7dmFyIG89dGhpczt0aGlzLm9wdGlvbnM9dC5leHRlbmQoe30sT28sZSksdGhpcy5fY29udGFpbmVyPWkuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1jdHJsIG1hcGJveGdsLWN0cmwtZ3JvdXBcIiksdGhpcy5fY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoXCJjb250ZXh0bWVudVwiLGZ1bmN0aW9uKHQpe3JldHVybiB0LnByZXZlbnREZWZhdWx0KCl9KSx0aGlzLm9wdGlvbnMuc2hvd1pvb20mJih0LmJpbmRBbGwoW1wiX3VwZGF0ZVpvb21CdXR0b25zXCJdLHRoaXMpLHRoaXMuX3pvb21JbkJ1dHRvbj10aGlzLl9jcmVhdGVCdXR0b24oXCJtYXBib3hnbC1jdHJsLWljb24gbWFwYm94Z2wtY3RybC16b29tLWluXCIsXCJab29tIGluXCIsZnVuY3Rpb24oKXtyZXR1cm4gby5fbWFwLnpvb21JbigpfSksdGhpcy5fem9vbU91dEJ1dHRvbj10aGlzLl9jcmVhdGVCdXR0b24oXCJtYXBib3hnbC1jdHJsLWljb24gbWFwYm94Z2wtY3RybC16b29tLW91dFwiLFwiWm9vbSBvdXRcIixmdW5jdGlvbigpe3JldHVybiBvLl9tYXAuem9vbU91dCgpfSkpLHRoaXMub3B0aW9ucy5zaG93Q29tcGFzcyYmKHQuYmluZEFsbChbXCJfcm90YXRlQ29tcGFzc0Fycm93XCJdLHRoaXMpLHRoaXMuX2NvbXBhc3M9dGhpcy5fY3JlYXRlQnV0dG9uKFwibWFwYm94Z2wtY3RybC1pY29uIG1hcGJveGdsLWN0cmwtY29tcGFzc1wiLFwiUmVzZXQgYmVhcmluZyB0byBub3J0aFwiLGZ1bmN0aW9uKCl7cmV0dXJuIG8uX21hcC5yZXNldE5vcnRoKCl9KSx0aGlzLl9jb21wYXNzQXJyb3c9aS5jcmVhdGUoXCJzcGFuXCIsXCJtYXBib3hnbC1jdHJsLWNvbXBhc3MtYXJyb3dcIix0aGlzLl9jb21wYXNzKSk7fTtmdW5jdGlvbiBVbyhlLGksbyl7aWYoZT1uZXcgdC5MbmdMYXQoZS5sbmcsZS5sYXQpLGkpe3ZhciByPW5ldyB0LkxuZ0xhdChlLmxuZy0zNjAsZS5sYXQpLGE9bmV3IHQuTG5nTGF0KGUubG5nKzM2MCxlLmxhdCksbj1vLmxvY2F0aW9uUG9pbnQoZSkuZGlzdFNxcihpKTtvLmxvY2F0aW9uUG9pbnQocikuZGlzdFNxcihpKTxuP2U9cjpvLmxvY2F0aW9uUG9pbnQoYSkuZGlzdFNxcihpKTxuJiYoZT1hKTt9Zm9yKDtNYXRoLmFicyhlLmxuZy1vLmNlbnRlci5sbmcpPjE4MDspe3ZhciBzPW8ubG9jYXRpb25Qb2ludChlKTtpZihzLng+PTAmJnMueT49MCYmcy54PD1vLndpZHRoJiZzLnk8PW8uaGVpZ2h0KWJyZWFrO2UubG5nPm8uY2VudGVyLmxuZz9lLmxuZy09MzYwOmUubG5nKz0zNjA7fXJldHVybiBlfUZvLnByb3RvdHlwZS5fdXBkYXRlWm9vbUJ1dHRvbnM9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLl9tYXAuZ2V0Wm9vbSgpO3RoaXMuX3pvb21JbkJ1dHRvbi5jbGFzc0xpc3QudG9nZ2xlKFwibWFwYm94Z2wtY3RybC1pY29uLWRpc2FibGVkXCIsdD09PXRoaXMuX21hcC5nZXRNYXhab29tKCkpLHRoaXMuX3pvb21PdXRCdXR0b24uY2xhc3NMaXN0LnRvZ2dsZShcIm1hcGJveGdsLWN0cmwtaWNvbi1kaXNhYmxlZFwiLHQ9PT10aGlzLl9tYXAuZ2V0TWluWm9vbSgpKTt9LEZvLnByb3RvdHlwZS5fcm90YXRlQ29tcGFzc0Fycm93PWZ1bmN0aW9uKCl7dmFyIHQ9XCJyb3RhdGUoXCIrdGhpcy5fbWFwLnRyYW5zZm9ybS5hbmdsZSooMTgwL01hdGguUEkpK1wiZGVnKVwiO3RoaXMuX2NvbXBhc3NBcnJvdy5zdHlsZS50cmFuc2Zvcm09dDt9LEZvLnByb3RvdHlwZS5vbkFkZD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fbWFwPXQsdGhpcy5vcHRpb25zLnNob3dab29tJiYodGhpcy5fbWFwLm9uKFwiem9vbVwiLHRoaXMuX3VwZGF0ZVpvb21CdXR0b25zKSx0aGlzLl91cGRhdGVab29tQnV0dG9ucygpKSx0aGlzLm9wdGlvbnMuc2hvd0NvbXBhc3MmJih0aGlzLl9tYXAub24oXCJyb3RhdGVcIix0aGlzLl9yb3RhdGVDb21wYXNzQXJyb3cpLHRoaXMuX3JvdGF0ZUNvbXBhc3NBcnJvdygpLHRoaXMuX2hhbmRsZXI9bmV3IHlvKHQse2J1dHRvbjpcImxlZnRcIixlbGVtZW50OnRoaXMuX2NvbXBhc3N9KSxpLmFkZEV2ZW50TGlzdGVuZXIodGhpcy5fY29tcGFzcyxcIm1vdXNlZG93blwiLHRoaXMuX2hhbmRsZXIub25Nb3VzZURvd24pLHRoaXMuX2hhbmRsZXIuZW5hYmxlKCkpLHRoaXMuX2NvbnRhaW5lcn0sRm8ucHJvdG90eXBlLm9uUmVtb3ZlPWZ1bmN0aW9uKCl7aS5yZW1vdmUodGhpcy5fY29udGFpbmVyKSx0aGlzLm9wdGlvbnMuc2hvd1pvb20mJnRoaXMuX21hcC5vZmYoXCJ6b29tXCIsdGhpcy5fdXBkYXRlWm9vbUJ1dHRvbnMpLHRoaXMub3B0aW9ucy5zaG93Q29tcGFzcyYmKHRoaXMuX21hcC5vZmYoXCJyb3RhdGVcIix0aGlzLl9yb3RhdGVDb21wYXNzQXJyb3cpLGkucmVtb3ZlRXZlbnRMaXN0ZW5lcih0aGlzLl9jb21wYXNzLFwibW91c2Vkb3duXCIsdGhpcy5faGFuZGxlci5vbk1vdXNlRG93biksdGhpcy5faGFuZGxlci5kaXNhYmxlKCksZGVsZXRlIHRoaXMuX2hhbmRsZXIpLGRlbGV0ZSB0aGlzLl9tYXA7fSxGby5wcm90b3R5cGUuX2NyZWF0ZUJ1dHRvbj1mdW5jdGlvbih0LGUsbyl7dmFyIHI9aS5jcmVhdGUoXCJidXR0b25cIix0LHRoaXMuX2NvbnRhaW5lcik7cmV0dXJuIHIudHlwZT1cImJ1dHRvblwiLHIudGl0bGU9ZSxyLnNldEF0dHJpYnV0ZShcImFyaWEtbGFiZWxcIixlKSxyLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLG8pLHJ9O3ZhciBObz17Y2VudGVyOlwidHJhbnNsYXRlKC01MCUsLTUwJSlcIix0b3A6XCJ0cmFuc2xhdGUoLTUwJSwwKVwiLFwidG9wLWxlZnRcIjpcInRyYW5zbGF0ZSgwLDApXCIsXCJ0b3AtcmlnaHRcIjpcInRyYW5zbGF0ZSgtMTAwJSwwKVwiLGJvdHRvbTpcInRyYW5zbGF0ZSgtNTAlLC0xMDAlKVwiLFwiYm90dG9tLWxlZnRcIjpcInRyYW5zbGF0ZSgwLC0xMDAlKVwiLFwiYm90dG9tLXJpZ2h0XCI6XCJ0cmFuc2xhdGUoLTEwMCUsLTEwMCUpXCIsbGVmdDpcInRyYW5zbGF0ZSgwLC01MCUpXCIscmlnaHQ6XCJ0cmFuc2xhdGUoLTEwMCUsLTUwJSlcIn07ZnVuY3Rpb24gWm8odCxlLGkpe3ZhciBvPXQuY2xhc3NMaXN0O2Zvcih2YXIgciBpbiBObylvLnJlbW92ZShcIm1hcGJveGdsLVwiK2krXCItYW5jaG9yLVwiK3IpO28uYWRkKFwibWFwYm94Z2wtXCIraStcIi1hbmNob3ItXCIrZSk7fXZhciBqbyxxbz1mdW5jdGlvbihlKXtmdW5jdGlvbiBvKG8scil7aWYoZS5jYWxsKHRoaXMpLChvIGluc3RhbmNlb2YgdC53aW5kb3cuSFRNTEVsZW1lbnR8fHIpJiYobz10LmV4dGVuZCh7ZWxlbWVudDpvfSxyKSksdC5iaW5kQWxsKFtcIl91cGRhdGVcIixcIl9vbk1vdmVcIixcIl9vblVwXCIsXCJfYWRkRHJhZ0hhbmRsZXJcIixcIl9vbk1hcENsaWNrXCJdLHRoaXMpLHRoaXMuX2FuY2hvcj1vJiZvLmFuY2hvcnx8XCJjZW50ZXJcIix0aGlzLl9jb2xvcj1vJiZvLmNvbG9yfHxcIiMzRkIxQ0VcIix0aGlzLl9kcmFnZ2FibGU9byYmby5kcmFnZ2FibGV8fCExLHRoaXMuX3N0YXRlPVwiaW5hY3RpdmVcIixvJiZvLmVsZW1lbnQpdGhpcy5fZWxlbWVudD1vLmVsZW1lbnQsdGhpcy5fb2Zmc2V0PXQuUG9pbnQuY29udmVydChvJiZvLm9mZnNldHx8WzAsMF0pO2Vsc2V7dGhpcy5fZGVmYXVsdE1hcmtlcj0hMCx0aGlzLl9lbGVtZW50PWkuY3JlYXRlKFwiZGl2XCIpO3ZhciBhPWkuY3JlYXRlTlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFwic3ZnXCIpO2Euc2V0QXR0cmlidXRlTlMobnVsbCxcImRpc3BsYXlcIixcImJsb2NrXCIpLGEuc2V0QXR0cmlidXRlTlMobnVsbCxcImhlaWdodFwiLFwiNDFweFwiKSxhLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJ3aWR0aFwiLFwiMjdweFwiKSxhLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJ2aWV3Qm94XCIsXCIwIDAgMjcgNDFcIik7dmFyIG49aS5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJnXCIpO24uc2V0QXR0cmlidXRlTlMobnVsbCxcInN0cm9rZVwiLFwibm9uZVwiKSxuLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJzdHJva2Utd2lkdGhcIixcIjFcIiksbi5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiZmlsbFwiLFwibm9uZVwiKSxuLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJmaWxsLXJ1bGVcIixcImV2ZW5vZGRcIik7dmFyIHM9aS5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJnXCIpO3Muc2V0QXR0cmlidXRlTlMobnVsbCxcImZpbGwtcnVsZVwiLFwibm9uemVyb1wiKTt2YXIgbD1pLmNyZWF0ZU5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIixcImdcIik7bC5zZXRBdHRyaWJ1dGVOUyhudWxsLFwidHJhbnNmb3JtXCIsXCJ0cmFuc2xhdGUoMy4wLCAyOS4wKVwiKSxsLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJmaWxsXCIsXCIjMDAwMDAwXCIpO2Zvcih2YXIgYz0wLHU9W3tyeDpcIjEwLjVcIixyeTpcIjUuMjUwMDIyNzNcIn0se3J4OlwiMTAuNVwiLHJ5OlwiNS4yNTAwMjI3M1wifSx7cng6XCI5LjVcIixyeTpcIjQuNzcyNzUwMDdcIn0se3J4OlwiOC41XCIscnk6XCI0LjI5NTQ5OTM2XCJ9LHtyeDpcIjcuNVwiLHJ5OlwiMy44MTgyMjMwOFwifSx7cng6XCI2LjVcIixyeTpcIjMuMzQwOTQ2NzlcIn0se3J4OlwiNS41XCIscnk6XCIyLjg2MzY3MDUxXCJ9LHtyeDpcIjQuNVwiLHJ5OlwiMi4zODYzNjg2NFwifV07Yzx1Lmxlbmd0aDtjKz0xKXt2YXIgaD11W2NdLHA9aS5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJlbGxpcHNlXCIpO3Auc2V0QXR0cmlidXRlTlMobnVsbCxcIm9wYWNpdHlcIixcIjAuMDRcIikscC5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiY3hcIixcIjEwLjVcIikscC5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiY3lcIixcIjUuODAwMjkwMDhcIikscC5zZXRBdHRyaWJ1dGVOUyhudWxsLFwicnhcIixoLnJ4KSxwLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJyeVwiLGgucnkpLGwuYXBwZW5kQ2hpbGQocCk7fXZhciBkPWkuY3JlYXRlTlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFwiZ1wiKTtkLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJmaWxsXCIsdGhpcy5fY29sb3IpO3ZhciBfPWkuY3JlYXRlTlMoXCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiLFwicGF0aFwiKTtfLnNldEF0dHJpYnV0ZU5TKG51bGwsXCJkXCIsXCJNMjcsMTMuNSBDMjcsMTkuMDc0NjQ0IDIwLjI1MDAwMSwyNy4wMDAwMDIgMTQuNzUsMzQuNTAwMDAyIEMxNC4wMTY2NjUsMzUuNTAwMDA0IDEyLjk4MzMzNSwzNS41MDAwMDQgMTIuMjUsMzQuNTAwMDAyIEM2Ljc0OTk5OTMsMjcuMDAwMDAyIDAsMTkuMjIyNTYyIDAsMTMuNSBDMCw2LjA0NDE1NTkgNi4wNDQxNTU5LDAgMTMuNSwwIEMyMC45NTU4NDQsMCAyNyw2LjA0NDE1NTkgMjcsMTMuNSBaXCIpLGQuYXBwZW5kQ2hpbGQoXyk7dmFyIGY9aS5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJnXCIpO2Yuc2V0QXR0cmlidXRlTlMobnVsbCxcIm9wYWNpdHlcIixcIjAuMjVcIiksZi5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiZmlsbFwiLFwiIzAwMDAwMFwiKTt2YXIgbT1pLmNyZWF0ZU5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIixcInBhdGhcIik7bS5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiZFwiLFwiTTEzLjUsMCBDNi4wNDQxNTU5LDAgMCw2LjA0NDE1NTkgMCwxMy41IEMwLDE5LjIyMjU2MiA2Ljc0OTk5OTMsMjcgMTIuMjUsMzQuNSBDMTMsMzUuNTIyNzI3IDE0LjAxNjY2NCwzNS41MDAwMDQgMTQuNzUsMzQuNSBDMjAuMjUwMDAxLDI3IDI3LDE5LjA3NDY0NCAyNywxMy41IEMyNyw2LjA0NDE1NTkgMjAuOTU1ODQ0LDAgMTMuNSwwIFogTTEzLjUsMSBDMjAuNDE1NDA0LDEgMjYsNi41ODQ1OTYgMjYsMTMuNSBDMjYsMTUuODk4NjU3IDI0LjQ5NTU4NCwxOS4xODE0MzEgMjIuMjIwNzAzLDIyLjczODI4MSBDMTkuOTQ1ODIzLDI2LjI5NTEzMiAxNi43MDUxMTksMzAuMTQyMTY3IDEzLjk0MzM1OSwzMy45MDgyMDMgQzEzLjc0MzQ0NSwzNC4xODA4MTQgMTMuNjEyNzE1LDM0LjMyMjczOCAxMy41LDM0LjQ0MTQwNiBDMTMuMzg3Mjg1LDM0LjMyMjczOCAxMy4yNTY1NTUsMzQuMTgwODE0IDEzLjA1NjY0MSwzMy45MDgyMDMgQzEwLjI4NDQ4MSwzMC4xMjc5ODUgNy40MTQ4Njg0LDI2LjMxNDE1OSA1LjAxNTYyNSwyMi43NzM0MzggQzIuNjE2MzgxNiwxOS4yMzI3MTUgMSwxNS45NTM1MzggMSwxMy41IEMxLDYuNTg0NTk2IDYuNTg0NTk2LDEgMTMuNSwxIFpcIiksZi5hcHBlbmRDaGlsZChtKTt2YXIgZz1pLmNyZWF0ZU5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIixcImdcIik7Zy5zZXRBdHRyaWJ1dGVOUyhudWxsLFwidHJhbnNmb3JtXCIsXCJ0cmFuc2xhdGUoNi4wLCA3LjApXCIpLGcuc2V0QXR0cmlidXRlTlMobnVsbCxcImZpbGxcIixcIiNGRkZGRkZcIik7dmFyIHY9aS5jcmVhdGVOUyhcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXCJnXCIpO3Yuc2V0QXR0cmlidXRlTlMobnVsbCxcInRyYW5zZm9ybVwiLFwidHJhbnNsYXRlKDguMCwgOC4wKVwiKTt2YXIgeT1pLmNyZWF0ZU5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIixcImNpcmNsZVwiKTt5LnNldEF0dHJpYnV0ZU5TKG51bGwsXCJmaWxsXCIsXCIjMDAwMDAwXCIpLHkuc2V0QXR0cmlidXRlTlMobnVsbCxcIm9wYWNpdHlcIixcIjAuMjVcIikseS5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiY3hcIixcIjUuNVwiKSx5LnNldEF0dHJpYnV0ZU5TKG51bGwsXCJjeVwiLFwiNS41XCIpLHkuc2V0QXR0cmlidXRlTlMobnVsbCxcInJcIixcIjUuNDk5OTk2MlwiKTt2YXIgeD1pLmNyZWF0ZU5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIixcImNpcmNsZVwiKTt4LnNldEF0dHJpYnV0ZU5TKG51bGwsXCJmaWxsXCIsXCIjRkZGRkZGXCIpLHguc2V0QXR0cmlidXRlTlMobnVsbCxcImN4XCIsXCI1LjVcIikseC5zZXRBdHRyaWJ1dGVOUyhudWxsLFwiY3lcIixcIjUuNVwiKSx4LnNldEF0dHJpYnV0ZU5TKG51bGwsXCJyXCIsXCI1LjQ5OTk5NjJcIiksdi5hcHBlbmRDaGlsZCh5KSx2LmFwcGVuZENoaWxkKHgpLHMuYXBwZW5kQ2hpbGQobCkscy5hcHBlbmRDaGlsZChkKSxzLmFwcGVuZENoaWxkKGYpLHMuYXBwZW5kQ2hpbGQoZykscy5hcHBlbmRDaGlsZCh2KSxhLmFwcGVuZENoaWxkKHMpLHRoaXMuX2VsZW1lbnQuYXBwZW5kQ2hpbGQoYSksdGhpcy5fb2Zmc2V0PXQuUG9pbnQuY29udmVydChvJiZvLm9mZnNldHx8WzAsLTE0XSk7fXRoaXMuX2VsZW1lbnQuY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLW1hcmtlclwiKSx0aGlzLl9lbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJkcmFnc3RhcnRcIixmdW5jdGlvbih0KXt0LnByZXZlbnREZWZhdWx0KCk7fSksWm8odGhpcy5fZWxlbWVudCx0aGlzLl9hbmNob3IsXCJtYXJrZXJcIiksdGhpcy5fcG9wdXA9bnVsbDt9cmV0dXJuIGUmJihvLl9fcHJvdG9fXz1lKSxvLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUmJmUucHJvdG90eXBlKSxvLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1vLG8ucHJvdG90eXBlLmFkZFRvPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnJlbW92ZSgpLHRoaXMuX21hcD10LHQuZ2V0Q2FudmFzQ29udGFpbmVyKCkuYXBwZW5kQ2hpbGQodGhpcy5fZWxlbWVudCksdC5vbihcIm1vdmVcIix0aGlzLl91cGRhdGUpLHQub24oXCJtb3ZlZW5kXCIsdGhpcy5fdXBkYXRlKSx0aGlzLnNldERyYWdnYWJsZSh0aGlzLl9kcmFnZ2FibGUpLHRoaXMuX3VwZGF0ZSgpLHRoaXMuX21hcC5vbihcImNsaWNrXCIsdGhpcy5fb25NYXBDbGljayksdGhpc30sby5wcm90b3R5cGUucmVtb3ZlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX21hcCYmKHRoaXMuX21hcC5vZmYoXCJjbGlja1wiLHRoaXMuX29uTWFwQ2xpY2spLHRoaXMuX21hcC5vZmYoXCJtb3ZlXCIsdGhpcy5fdXBkYXRlKSx0aGlzLl9tYXAub2ZmKFwibW92ZWVuZFwiLHRoaXMuX3VwZGF0ZSksdGhpcy5fbWFwLm9mZihcIm1vdXNlZG93blwiLHRoaXMuX2FkZERyYWdIYW5kbGVyKSx0aGlzLl9tYXAub2ZmKFwidG91Y2hzdGFydFwiLHRoaXMuX2FkZERyYWdIYW5kbGVyKSx0aGlzLl9tYXAub2ZmKFwibW91c2V1cFwiLHRoaXMuX29uVXApLHRoaXMuX21hcC5vZmYoXCJ0b3VjaGVuZFwiLHRoaXMuX29uVXApLGRlbGV0ZSB0aGlzLl9tYXApLGkucmVtb3ZlKHRoaXMuX2VsZW1lbnQpLHRoaXMuX3BvcHVwJiZ0aGlzLl9wb3B1cC5yZW1vdmUoKSx0aGlzfSxvLnByb3RvdHlwZS5nZXRMbmdMYXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fbG5nTGF0fSxvLnByb3RvdHlwZS5zZXRMbmdMYXQ9ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuX2xuZ0xhdD10LkxuZ0xhdC5jb252ZXJ0KGUpLHRoaXMuX3Bvcz1udWxsLHRoaXMuX3BvcHVwJiZ0aGlzLl9wb3B1cC5zZXRMbmdMYXQodGhpcy5fbG5nTGF0KSx0aGlzLl91cGRhdGUoKSx0aGlzfSxvLnByb3RvdHlwZS5nZXRFbGVtZW50PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2VsZW1lbnR9LG8ucHJvdG90eXBlLnNldFBvcHVwPWZ1bmN0aW9uKHQpe2lmKHRoaXMuX3BvcHVwJiYodGhpcy5fcG9wdXAucmVtb3ZlKCksdGhpcy5fcG9wdXA9bnVsbCksdCl7aWYoIShcIm9mZnNldFwiaW4gdC5vcHRpb25zKSl7dmFyIGU9TWF0aC5zcXJ0KE1hdGgucG93KDEzLjUsMikvMik7dC5vcHRpb25zLm9mZnNldD10aGlzLl9kZWZhdWx0TWFya2VyP3t0b3A6WzAsMF0sXCJ0b3AtbGVmdFwiOlswLDBdLFwidG9wLXJpZ2h0XCI6WzAsMF0sYm90dG9tOlswLC0zOC4xXSxcImJvdHRvbS1sZWZ0XCI6W2UsLTEqKDI0LjYrZSldLFwiYm90dG9tLXJpZ2h0XCI6Wy1lLC0xKigyNC42K2UpXSxsZWZ0OlsxMy41LC0yNC42XSxyaWdodDpbLTEzLjUsLTI0LjZdfTp0aGlzLl9vZmZzZXQ7fXRoaXMuX3BvcHVwPXQsdGhpcy5fbG5nTGF0JiZ0aGlzLl9wb3B1cC5zZXRMbmdMYXQodGhpcy5fbG5nTGF0KTt9cmV0dXJuIHRoaXN9LG8ucHJvdG90eXBlLl9vbk1hcENsaWNrPWZ1bmN0aW9uKHQpe3ZhciBlPXQub3JpZ2luYWxFdmVudC50YXJnZXQsaT10aGlzLl9lbGVtZW50O3RoaXMuX3BvcHVwJiYoZT09PWl8fGkuY29udGFpbnMoZSkpJiZ0aGlzLnRvZ2dsZVBvcHVwKCk7fSxvLnByb3RvdHlwZS5nZXRQb3B1cD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9wb3B1cH0sby5wcm90b3R5cGUudG9nZ2xlUG9wdXA9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLl9wb3B1cDtyZXR1cm4gdD8odC5pc09wZW4oKT90LnJlbW92ZSgpOnQuYWRkVG8odGhpcy5fbWFwKSx0aGlzKTp0aGlzfSxvLnByb3RvdHlwZS5fdXBkYXRlPWZ1bmN0aW9uKHQpe3RoaXMuX21hcCYmKHRoaXMuX21hcC50cmFuc2Zvcm0ucmVuZGVyV29ybGRDb3BpZXMmJih0aGlzLl9sbmdMYXQ9VW8odGhpcy5fbG5nTGF0LHRoaXMuX3Bvcyx0aGlzLl9tYXAudHJhbnNmb3JtKSksdGhpcy5fcG9zPXRoaXMuX21hcC5wcm9qZWN0KHRoaXMuX2xuZ0xhdCkuX2FkZCh0aGlzLl9vZmZzZXQpLHQmJlwibW92ZWVuZFwiIT09dC50eXBlfHwodGhpcy5fcG9zPXRoaXMuX3Bvcy5yb3VuZCgpKSxpLnNldFRyYW5zZm9ybSh0aGlzLl9lbGVtZW50LE5vW3RoaXMuX2FuY2hvcl0rXCIgdHJhbnNsYXRlKFwiK3RoaXMuX3Bvcy54K1wicHgsIFwiK3RoaXMuX3Bvcy55K1wicHgpXCIpKTt9LG8ucHJvdG90eXBlLmdldE9mZnNldD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9vZmZzZXR9LG8ucHJvdG90eXBlLnNldE9mZnNldD1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5fb2Zmc2V0PXQuUG9pbnQuY29udmVydChlKSx0aGlzLl91cGRhdGUoKSx0aGlzfSxvLnByb3RvdHlwZS5fb25Nb3ZlPWZ1bmN0aW9uKGUpe3RoaXMuX3Bvcz1lLnBvaW50LnN1Yih0aGlzLl9wb3NpdGlvbkRlbHRhKSx0aGlzLl9sbmdMYXQ9dGhpcy5fbWFwLnVucHJvamVjdCh0aGlzLl9wb3MpLHRoaXMuc2V0TG5nTGF0KHRoaXMuX2xuZ0xhdCksdGhpcy5fZWxlbWVudC5zdHlsZS5wb2ludGVyRXZlbnRzPVwibm9uZVwiLFwicGVuZGluZ1wiPT09dGhpcy5fc3RhdGUmJih0aGlzLl9zdGF0ZT1cImFjdGl2ZVwiLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImRyYWdzdGFydFwiKSkpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImRyYWdcIikpO30sby5wcm90b3R5cGUuX29uVXA9ZnVuY3Rpb24oKXt0aGlzLl9lbGVtZW50LnN0eWxlLnBvaW50ZXJFdmVudHM9XCJhdXRvXCIsdGhpcy5fcG9zaXRpb25EZWx0YT1udWxsLHRoaXMuX21hcC5vZmYoXCJtb3VzZW1vdmVcIix0aGlzLl9vbk1vdmUpLHRoaXMuX21hcC5vZmYoXCJ0b3VjaG1vdmVcIix0aGlzLl9vbk1vdmUpLFwiYWN0aXZlXCI9PT10aGlzLl9zdGF0ZSYmdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiZHJhZ2VuZFwiKSksdGhpcy5fc3RhdGU9XCJpbmFjdGl2ZVwiO30sby5wcm90b3R5cGUuX2FkZERyYWdIYW5kbGVyPWZ1bmN0aW9uKHQpe3RoaXMuX2VsZW1lbnQuY29udGFpbnModC5vcmlnaW5hbEV2ZW50LnRhcmdldCkmJih0LnByZXZlbnREZWZhdWx0KCksdGhpcy5fcG9zaXRpb25EZWx0YT10LnBvaW50LnN1Yih0aGlzLl9wb3MpLmFkZCh0aGlzLl9vZmZzZXQpLHRoaXMuX3N0YXRlPVwicGVuZGluZ1wiLHRoaXMuX21hcC5vbihcIm1vdXNlbW92ZVwiLHRoaXMuX29uTW92ZSksdGhpcy5fbWFwLm9uKFwidG91Y2htb3ZlXCIsdGhpcy5fb25Nb3ZlKSx0aGlzLl9tYXAub25jZShcIm1vdXNldXBcIix0aGlzLl9vblVwKSx0aGlzLl9tYXAub25jZShcInRvdWNoZW5kXCIsdGhpcy5fb25VcCkpO30sby5wcm90b3R5cGUuc2V0RHJhZ2dhYmxlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9kcmFnZ2FibGU9ISF0LHRoaXMuX21hcCYmKHQ/KHRoaXMuX21hcC5vbihcIm1vdXNlZG93blwiLHRoaXMuX2FkZERyYWdIYW5kbGVyKSx0aGlzLl9tYXAub24oXCJ0b3VjaHN0YXJ0XCIsdGhpcy5fYWRkRHJhZ0hhbmRsZXIpKToodGhpcy5fbWFwLm9mZihcIm1vdXNlZG93blwiLHRoaXMuX2FkZERyYWdIYW5kbGVyKSx0aGlzLl9tYXAub2ZmKFwidG91Y2hzdGFydFwiLHRoaXMuX2FkZERyYWdIYW5kbGVyKSkpLHRoaXN9LG8ucHJvdG90eXBlLmlzRHJhZ2dhYmxlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2RyYWdnYWJsZX0sb30odC5FdmVudGVkKSxWbz17cG9zaXRpb25PcHRpb25zOntlbmFibGVIaWdoQWNjdXJhY3k6ITEsbWF4aW11bUFnZTowLHRpbWVvdXQ6NmUzfSxmaXRCb3VuZHNPcHRpb25zOnttYXhab29tOjE1fSx0cmFja1VzZXJMb2NhdGlvbjohMSxzaG93VXNlckxvY2F0aW9uOiEwfTt2YXIgR289ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gbyhpKXtlLmNhbGwodGhpcyksdGhpcy5vcHRpb25zPXQuZXh0ZW5kKHt9LFZvLGkpLHQuYmluZEFsbChbXCJfb25TdWNjZXNzXCIsXCJfb25FcnJvclwiLFwiX2ZpbmlzaFwiLFwiX3NldHVwVUlcIixcIl91cGRhdGVDYW1lcmFcIixcIl91cGRhdGVNYXJrZXJcIl0sdGhpcyk7fXJldHVybiBlJiYoby5fX3Byb3RvX189ZSksby5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShlJiZlLnByb3RvdHlwZSksby5wcm90b3R5cGUuY29uc3RydWN0b3I9byxvLnByb3RvdHlwZS5vbkFkZD1mdW5jdGlvbihlKXt2YXIgbztyZXR1cm4gdGhpcy5fbWFwPWUsdGhpcy5fY29udGFpbmVyPWkuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC1jdHJsIG1hcGJveGdsLWN0cmwtZ3JvdXBcIiksbz10aGlzLl9zZXR1cFVJLHZvaWQgMCE9PWpvP28oam8pOnZvaWQgMCE9PXQud2luZG93Lm5hdmlnYXRvci5wZXJtaXNzaW9ucz90LndpbmRvdy5uYXZpZ2F0b3IucGVybWlzc2lvbnMucXVlcnkoe25hbWU6XCJnZW9sb2NhdGlvblwifSkudGhlbihmdW5jdGlvbih0KXtqbz1cImRlbmllZFwiIT09dC5zdGF0ZSxvKGpvKTt9KTooam89ISF0LndpbmRvdy5uYXZpZ2F0b3IuZ2VvbG9jYXRpb24sbyhqbykpLHRoaXMuX2NvbnRhaW5lcn0sby5wcm90b3R5cGUub25SZW1vdmU9ZnVuY3Rpb24oKXt2b2lkIDAhPT10aGlzLl9nZW9sb2NhdGlvbldhdGNoSUQmJih0LndpbmRvdy5uYXZpZ2F0b3IuZ2VvbG9jYXRpb24uY2xlYXJXYXRjaCh0aGlzLl9nZW9sb2NhdGlvbldhdGNoSUQpLHRoaXMuX2dlb2xvY2F0aW9uV2F0Y2hJRD12b2lkIDApLHRoaXMub3B0aW9ucy5zaG93VXNlckxvY2F0aW9uJiZ0aGlzLl91c2VyTG9jYXRpb25Eb3RNYXJrZXImJnRoaXMuX3VzZXJMb2NhdGlvbkRvdE1hcmtlci5yZW1vdmUoKSxpLnJlbW92ZSh0aGlzLl9jb250YWluZXIpLHRoaXMuX21hcD12b2lkIDA7fSxvLnByb3RvdHlwZS5fb25TdWNjZXNzPWZ1bmN0aW9uKGUpe2lmKHRoaXMub3B0aW9ucy50cmFja1VzZXJMb2NhdGlvbilzd2l0Y2godGhpcy5fbGFzdEtub3duUG9zaXRpb249ZSx0aGlzLl93YXRjaFN0YXRlKXtjYXNlXCJXQUlUSU5HX0FDVElWRVwiOmNhc2VcIkFDVElWRV9MT0NLXCI6Y2FzZVwiQUNUSVZFX0VSUk9SXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIkFDVElWRV9MT0NLXCIsdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS13YWl0aW5nXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlLWVycm9yXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlXCIpO2JyZWFrO2Nhc2VcIkJBQ0tHUk9VTkRcIjpjYXNlXCJCQUNLR1JPVU5EX0VSUk9SXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIkJBQ0tHUk9VTkRcIix0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLXdhaXRpbmdcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kLWVycm9yXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYmFja2dyb3VuZFwiKTt9dGhpcy5vcHRpb25zLnNob3dVc2VyTG9jYXRpb24mJlwiT0ZGXCIhPT10aGlzLl93YXRjaFN0YXRlJiZ0aGlzLl91cGRhdGVNYXJrZXIoZSksdGhpcy5vcHRpb25zLnRyYWNrVXNlckxvY2F0aW9uJiZcIkFDVElWRV9MT0NLXCIhPT10aGlzLl93YXRjaFN0YXRlfHx0aGlzLl91cGRhdGVDYW1lcmEoZSksdGhpcy5vcHRpb25zLnNob3dVc2VyTG9jYXRpb24mJnRoaXMuX2RvdEVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLXVzZXItbG9jYXRpb24tZG90LXN0YWxlXCIpLHRoaXMuZmlyZShuZXcgdC5FdmVudChcImdlb2xvY2F0ZVwiLGUpKSx0aGlzLl9maW5pc2goKTt9LG8ucHJvdG90eXBlLl91cGRhdGVDYW1lcmE9ZnVuY3Rpb24oZSl7dmFyIGk9bmV3IHQuTG5nTGF0KGUuY29vcmRzLmxvbmdpdHVkZSxlLmNvb3Jkcy5sYXRpdHVkZSksbz1lLmNvb3Jkcy5hY2N1cmFjeSxyPXRoaXMuX21hcC5nZXRCZWFyaW5nKCksYT10LmV4dGVuZCh7YmVhcmluZzpyfSx0aGlzLm9wdGlvbnMuZml0Qm91bmRzT3B0aW9ucyk7dGhpcy5fbWFwLmZpdEJvdW5kcyhpLnRvQm91bmRzKG8pLGEse2dlb2xvY2F0ZVNvdXJjZTohMH0pO30sby5wcm90b3R5cGUuX3VwZGF0ZU1hcmtlcj1mdW5jdGlvbih0KXt0P3RoaXMuX3VzZXJMb2NhdGlvbkRvdE1hcmtlci5zZXRMbmdMYXQoW3QuY29vcmRzLmxvbmdpdHVkZSx0LmNvb3Jkcy5sYXRpdHVkZV0pLmFkZFRvKHRoaXMuX21hcCk6dGhpcy5fdXNlckxvY2F0aW9uRG90TWFya2VyLnJlbW92ZSgpO30sby5wcm90b3R5cGUuX29uRXJyb3I9ZnVuY3Rpb24oZSl7aWYodGhpcy5vcHRpb25zLnRyYWNrVXNlckxvY2F0aW9uKWlmKDE9PT1lLmNvZGUpdGhpcy5fd2F0Y2hTdGF0ZT1cIk9GRlwiLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZVwiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZS1lcnJvclwiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWJhY2tncm91bmRcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kLWVycm9yXCIpLHZvaWQgMCE9PXRoaXMuX2dlb2xvY2F0aW9uV2F0Y2hJRCYmdGhpcy5fY2xlYXJXYXRjaCgpO2Vsc2Ugc3dpdGNoKHRoaXMuX3dhdGNoU3RhdGUpe2Nhc2VcIldBSVRJTkdfQUNUSVZFXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIkFDVElWRV9FUlJPUlwiLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlLWVycm9yXCIpO2JyZWFrO2Nhc2VcIkFDVElWRV9MT0NLXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIkFDVElWRV9FUlJPUlwiLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlLWVycm9yXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKTticmVhaztjYXNlXCJCQUNLR1JPVU5EXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIkJBQ0tHUk9VTkRfRVJST1JcIix0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWJhY2tncm91bmRcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kLWVycm9yXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKTt9XCJPRkZcIiE9PXRoaXMuX3dhdGNoU3RhdGUmJnRoaXMub3B0aW9ucy5zaG93VXNlckxvY2F0aW9uJiZ0aGlzLl9kb3RFbGVtZW50LmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC11c2VyLWxvY2F0aW9uLWRvdC1zdGFsZVwiKSx0aGlzLmZpcmUobmV3IHQuRXZlbnQoXCJlcnJvclwiLGUpKSx0aGlzLl9maW5pc2goKTt9LG8ucHJvdG90eXBlLl9maW5pc2g9ZnVuY3Rpb24oKXt0aGlzLl90aW1lb3V0SWQmJmNsZWFyVGltZW91dCh0aGlzLl90aW1lb3V0SWQpLHRoaXMuX3RpbWVvdXRJZD12b2lkIDA7fSxvLnByb3RvdHlwZS5fc2V0dXBVST1mdW5jdGlvbihlKXt2YXIgbz10aGlzOyExIT09ZT8odGhpcy5fY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoXCJjb250ZXh0bWVudVwiLGZ1bmN0aW9uKHQpe3JldHVybiB0LnByZXZlbnREZWZhdWx0KCl9KSx0aGlzLl9nZW9sb2NhdGVCdXR0b249aS5jcmVhdGUoXCJidXR0b25cIixcIm1hcGJveGdsLWN0cmwtaWNvbiBtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZVwiLHRoaXMuX2NvbnRhaW5lciksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLnR5cGU9XCJidXR0b25cIix0aGlzLl9nZW9sb2NhdGVCdXR0b24uc2V0QXR0cmlidXRlKFwiYXJpYS1sYWJlbFwiLFwiR2VvbG9jYXRlXCIpLHRoaXMub3B0aW9ucy50cmFja1VzZXJMb2NhdGlvbiYmKHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5zZXRBdHRyaWJ1dGUoXCJhcmlhLXByZXNzZWRcIixcImZhbHNlXCIpLHRoaXMuX3dhdGNoU3RhdGU9XCJPRkZcIiksdGhpcy5vcHRpb25zLnNob3dVc2VyTG9jYXRpb24mJih0aGlzLl9kb3RFbGVtZW50PWkuY3JlYXRlKFwiZGl2XCIsXCJtYXBib3hnbC11c2VyLWxvY2F0aW9uLWRvdFwiKSx0aGlzLl91c2VyTG9jYXRpb25Eb3RNYXJrZXI9bmV3IHFvKHRoaXMuX2RvdEVsZW1lbnQpLHRoaXMub3B0aW9ucy50cmFja1VzZXJMb2NhdGlvbiYmKHRoaXMuX3dhdGNoU3RhdGU9XCJPRkZcIikpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIix0aGlzLnRyaWdnZXIuYmluZCh0aGlzKSksdGhpcy5fc2V0dXA9ITAsdGhpcy5vcHRpb25zLnRyYWNrVXNlckxvY2F0aW9uJiZ0aGlzLl9tYXAub24oXCJtb3Zlc3RhcnRcIixmdW5jdGlvbihlKXtlLmdlb2xvY2F0ZVNvdXJjZXx8XCJBQ1RJVkVfTE9DS1wiIT09by5fd2F0Y2hTdGF0ZXx8KG8uX3dhdGNoU3RhdGU9XCJCQUNLR1JPVU5EXCIsby5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kXCIpLG8uX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlXCIpLG8uZmlyZShuZXcgdC5FdmVudChcInRyYWNrdXNlcmxvY2F0aW9uZW5kXCIpKSk7fSkpOnQud2Fybk9uY2UoXCJHZW9sb2NhdGlvbiBzdXBwb3J0IGlzIG5vdCBhdmFpbGFibGUsIHRoZSBHZW9sb2NhdGVDb250cm9sIHdpbGwgbm90IGJlIHZpc2libGUuXCIpO30sby5wcm90b3R5cGUudHJpZ2dlcj1mdW5jdGlvbigpe2lmKCF0aGlzLl9zZXR1cClyZXR1cm4gdC53YXJuT25jZShcIkdlb2xvY2F0ZSBjb250cm9sIHRyaWdnZXJlZCBiZWZvcmUgYWRkZWQgdG8gYSBtYXBcIiksITE7aWYodGhpcy5vcHRpb25zLnRyYWNrVXNlckxvY2F0aW9uKXtzd2l0Y2godGhpcy5fd2F0Y2hTdGF0ZSl7Y2FzZVwiT0ZGXCI6dGhpcy5fd2F0Y2hTdGF0ZT1cIldBSVRJTkdfQUNUSVZFXCIsdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwidHJhY2t1c2VybG9jYXRpb25zdGFydFwiKSk7YnJlYWs7Y2FzZVwiV0FJVElOR19BQ1RJVkVcIjpjYXNlXCJBQ1RJVkVfTE9DS1wiOmNhc2VcIkFDVElWRV9FUlJPUlwiOmNhc2VcIkJBQ0tHUk9VTkRfRVJST1JcIjp0aGlzLl93YXRjaFN0YXRlPVwiT0ZGXCIsdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS13YWl0aW5nXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlLWVycm9yXCIpLHRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYmFja2dyb3VuZFwiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWJhY2tncm91bmQtZXJyb3JcIiksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwidHJhY2t1c2VybG9jYXRpb25lbmRcIikpO2JyZWFrO2Nhc2VcIkJBQ0tHUk9VTkRcIjp0aGlzLl93YXRjaFN0YXRlPVwiQUNUSVZFX0xPQ0tcIix0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWJhY2tncm91bmRcIiksdGhpcy5fbGFzdEtub3duUG9zaXRpb24mJnRoaXMuX3VwZGF0ZUNhbWVyYSh0aGlzLl9sYXN0S25vd25Qb3NpdGlvbiksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwidHJhY2t1c2VybG9jYXRpb25zdGFydFwiKSk7fXN3aXRjaCh0aGlzLl93YXRjaFN0YXRlKXtjYXNlXCJXQUlUSU5HX0FDVElWRVwiOnRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZVwiKTticmVhaztjYXNlXCJBQ1RJVkVfTE9DS1wiOnRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtYWN0aXZlXCIpO2JyZWFrO2Nhc2VcIkFDVElWRV9FUlJPUlwiOnRoaXMuX2dlb2xvY2F0ZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtY3RybC1nZW9sb2NhdGUtd2FpdGluZ1wiKSx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLWFjdGl2ZS1lcnJvclwiKTticmVhaztjYXNlXCJCQUNLR1JPVU5EXCI6dGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kXCIpO2JyZWFrO2Nhc2VcIkJBQ0tHUk9VTkRfRVJST1JcIjp0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLXdhaXRpbmdcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJtYXBib3hnbC1jdHJsLWdlb2xvY2F0ZS1iYWNrZ3JvdW5kLWVycm9yXCIpO31cIk9GRlwiPT09dGhpcy5fd2F0Y2hTdGF0ZSYmdm9pZCAwIT09dGhpcy5fZ2VvbG9jYXRpb25XYXRjaElEP3RoaXMuX2NsZWFyV2F0Y2goKTp2b2lkIDA9PT10aGlzLl9nZW9sb2NhdGlvbldhdGNoSUQmJih0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LmFkZChcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLXdhaXRpbmdcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLnNldEF0dHJpYnV0ZShcImFyaWEtcHJlc3NlZFwiLFwidHJ1ZVwiKSx0aGlzLl9nZW9sb2NhdGlvbldhdGNoSUQ9dC53aW5kb3cubmF2aWdhdG9yLmdlb2xvY2F0aW9uLndhdGNoUG9zaXRpb24odGhpcy5fb25TdWNjZXNzLHRoaXMuX29uRXJyb3IsdGhpcy5vcHRpb25zLnBvc2l0aW9uT3B0aW9ucykpO31lbHNlIHQud2luZG93Lm5hdmlnYXRvci5nZW9sb2NhdGlvbi5nZXRDdXJyZW50UG9zaXRpb24odGhpcy5fb25TdWNjZXNzLHRoaXMuX29uRXJyb3IsdGhpcy5vcHRpb25zLnBvc2l0aW9uT3B0aW9ucyksdGhpcy5fdGltZW91dElkPXNldFRpbWVvdXQodGhpcy5fZmluaXNoLDFlNCk7cmV0dXJuICEwfSxvLnByb3RvdHlwZS5fY2xlYXJXYXRjaD1mdW5jdGlvbigpe3Qud2luZG93Lm5hdmlnYXRvci5nZW9sb2NhdGlvbi5jbGVhcldhdGNoKHRoaXMuX2dlb2xvY2F0aW9uV2F0Y2hJRCksdGhpcy5fZ2VvbG9jYXRpb25XYXRjaElEPXZvaWQgMCx0aGlzLl9nZW9sb2NhdGVCdXR0b24uY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLWN0cmwtZ2VvbG9jYXRlLXdhaXRpbmdcIiksdGhpcy5fZ2VvbG9jYXRlQnV0dG9uLnNldEF0dHJpYnV0ZShcImFyaWEtcHJlc3NlZFwiLFwiZmFsc2VcIiksdGhpcy5vcHRpb25zLnNob3dVc2VyTG9jYXRpb24mJnRoaXMuX3VwZGF0ZU1hcmtlcihudWxsKTt9LG99KHQuRXZlbnRlZCksV289e21heFdpZHRoOjEwMCx1bml0OlwibWV0cmljXCJ9LFhvPWZ1bmN0aW9uKGUpe3RoaXMub3B0aW9ucz10LmV4dGVuZCh7fSxXbyxlKSx0LmJpbmRBbGwoW1wiX29uTW92ZVwiLFwic2V0VW5pdFwiXSx0aGlzKTt9O2Z1bmN0aW9uIEhvKHQsZSxpKXt2YXIgbyxyLGEsbixzLGwsYz1pJiZpLm1heFdpZHRofHwxMDAsdT10Ll9jb250YWluZXIuY2xpZW50SGVpZ2h0LzIsaD0obz10LnVucHJvamVjdChbMCx1XSkscj10LnVucHJvamVjdChbYyx1XSksYT1NYXRoLlBJLzE4MCxuPW8ubGF0KmEscz1yLmxhdCphLGw9TWF0aC5zaW4obikqTWF0aC5zaW4ocykrTWF0aC5jb3MobikqTWF0aC5jb3MocykqTWF0aC5jb3MoKHIubG5nLW8ubG5nKSphKSw2MzcxZTMqTWF0aC5hY29zKE1hdGgubWluKGwsMSkpKTtpZihpJiZcImltcGVyaWFsXCI9PT1pLnVuaXQpe3ZhciBwPTMuMjgwOCpoO2lmKHA+NTI4MClLbyhlLGMscC81MjgwLFwibWlcIik7ZWxzZSBLbyhlLGMscCxcImZ0XCIpO31lbHNlIGlmKGkmJlwibmF1dGljYWxcIj09PWkudW5pdCl7S28oZSxjLGgvMTg1MixcIm5tXCIpO31lbHNlIEtvKGUsYyxoLFwibVwiKTt9ZnVuY3Rpb24gS28odCxlLGksbyl7dmFyIHIsYSxuLHM9KHI9aSxhPU1hdGgucG93KDEwLChcIlwiK01hdGguZmxvb3IocikpLmxlbmd0aC0xKSxuPShuPXIvYSk+PTEwPzEwOm4+PTU/NTpuPj0zPzM6bj49Mj8yOm4+PTE/MTpmdW5jdGlvbih0KXt2YXIgZT1NYXRoLnBvdygxMCxNYXRoLmNlaWwoLU1hdGgubG9nKHQpL01hdGguTE4xMCkpO3JldHVybiBNYXRoLnJvdW5kKHQqZSkvZX0obiksYSpuKSxsPXMvaTtcIm1cIj09PW8mJnM+PTFlMyYmKHMvPTFlMyxvPVwia21cIiksdC5zdHlsZS53aWR0aD1lKmwrXCJweFwiLHQuaW5uZXJIVE1MPXMrbzt9WG8ucHJvdG90eXBlLmdldERlZmF1bHRQb3NpdGlvbj1mdW5jdGlvbigpe3JldHVybiBcImJvdHRvbS1sZWZ0XCJ9LFhvLnByb3RvdHlwZS5fb25Nb3ZlPWZ1bmN0aW9uKCl7SG8odGhpcy5fbWFwLHRoaXMuX2NvbnRhaW5lcix0aGlzLm9wdGlvbnMpO30sWG8ucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9tYXA9dCx0aGlzLl9jb250YWluZXI9aS5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLWN0cmwgbWFwYm94Z2wtY3RybC1zY2FsZVwiLHQuZ2V0Q29udGFpbmVyKCkpLHRoaXMuX21hcC5vbihcIm1vdmVcIix0aGlzLl9vbk1vdmUpLHRoaXMuX29uTW92ZSgpLHRoaXMuX2NvbnRhaW5lcn0sWG8ucHJvdG90eXBlLm9uUmVtb3ZlPWZ1bmN0aW9uKCl7aS5yZW1vdmUodGhpcy5fY29udGFpbmVyKSx0aGlzLl9tYXAub2ZmKFwibW92ZVwiLHRoaXMuX29uTW92ZSksdGhpcy5fbWFwPXZvaWQgMDt9LFhvLnByb3RvdHlwZS5zZXRVbml0PWZ1bmN0aW9uKHQpe3RoaXMub3B0aW9ucy51bml0PXQsSG8odGhpcy5fbWFwLHRoaXMuX2NvbnRhaW5lcix0aGlzLm9wdGlvbnMpO307dmFyIFlvPWZ1bmN0aW9uKGUpe3RoaXMuX2Z1bGxzY3JlZW49ITEsZSYmZS5jb250YWluZXImJihlLmNvbnRhaW5lciBpbnN0YW5jZW9mIHQud2luZG93LkhUTUxFbGVtZW50P3RoaXMuX2NvbnRhaW5lcj1lLmNvbnRhaW5lcjp0Lndhcm5PbmNlKFwiRnVsbCBzY3JlZW4gY29udHJvbCAnY29udGFpbmVyJyBtdXN0IGJlIGEgRE9NIGVsZW1lbnQuXCIpKSx0LmJpbmRBbGwoW1wiX29uQ2xpY2tGdWxsc2NyZWVuXCIsXCJfY2hhbmdlSWNvblwiXSx0aGlzKSxcIm9uZnVsbHNjcmVlbmNoYW5nZVwiaW4gdC53aW5kb3cuZG9jdW1lbnQ/dGhpcy5fZnVsbHNjcmVlbmNoYW5nZT1cImZ1bGxzY3JlZW5jaGFuZ2VcIjpcIm9ubW96ZnVsbHNjcmVlbmNoYW5nZVwiaW4gdC53aW5kb3cuZG9jdW1lbnQ/dGhpcy5fZnVsbHNjcmVlbmNoYW5nZT1cIm1vemZ1bGxzY3JlZW5jaGFuZ2VcIjpcIm9ud2Via2l0ZnVsbHNjcmVlbmNoYW5nZVwiaW4gdC53aW5kb3cuZG9jdW1lbnQ/dGhpcy5fZnVsbHNjcmVlbmNoYW5nZT1cIndlYmtpdGZ1bGxzY3JlZW5jaGFuZ2VcIjpcIm9ubXNmdWxsc2NyZWVuY2hhbmdlXCJpbiB0LndpbmRvdy5kb2N1bWVudCYmKHRoaXMuX2Z1bGxzY3JlZW5jaGFuZ2U9XCJNU0Z1bGxzY3JlZW5DaGFuZ2VcIiksdGhpcy5fY2xhc3NOYW1lPVwibWFwYm94Z2wtY3RybFwiO307WW8ucHJvdG90eXBlLm9uQWRkPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLl9tYXA9ZSx0aGlzLl9jb250YWluZXJ8fCh0aGlzLl9jb250YWluZXI9dGhpcy5fbWFwLmdldENvbnRhaW5lcigpKSx0aGlzLl9jb250cm9sQ29udGFpbmVyPWkuY3JlYXRlKFwiZGl2XCIsdGhpcy5fY2xhc3NOYW1lK1wiIG1hcGJveGdsLWN0cmwtZ3JvdXBcIiksdGhpcy5fY2hlY2tGdWxsc2NyZWVuU3VwcG9ydCgpP3RoaXMuX3NldHVwVUkoKToodGhpcy5fY29udHJvbENvbnRhaW5lci5zdHlsZS5kaXNwbGF5PVwibm9uZVwiLHQud2Fybk9uY2UoXCJUaGlzIGRldmljZSBkb2VzIG5vdCBzdXBwb3J0IGZ1bGxzY3JlZW4gbW9kZS5cIikpLHRoaXMuX2NvbnRyb2xDb250YWluZXJ9LFlvLnByb3RvdHlwZS5vblJlbW92ZT1mdW5jdGlvbigpe2kucmVtb3ZlKHRoaXMuX2NvbnRyb2xDb250YWluZXIpLHRoaXMuX21hcD1udWxsLHQud2luZG93LmRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodGhpcy5fZnVsbHNjcmVlbmNoYW5nZSx0aGlzLl9jaGFuZ2VJY29uKTt9LFlvLnByb3RvdHlwZS5fY2hlY2tGdWxsc2NyZWVuU3VwcG9ydD1mdW5jdGlvbigpe3JldHVybiAhISh0LndpbmRvdy5kb2N1bWVudC5mdWxsc2NyZWVuRW5hYmxlZHx8dC53aW5kb3cuZG9jdW1lbnQubW96RnVsbFNjcmVlbkVuYWJsZWR8fHQud2luZG93LmRvY3VtZW50Lm1zRnVsbHNjcmVlbkVuYWJsZWR8fHQud2luZG93LmRvY3VtZW50LndlYmtpdEZ1bGxzY3JlZW5FbmFibGVkKX0sWW8ucHJvdG90eXBlLl9zZXR1cFVJPWZ1bmN0aW9uKCl7KHRoaXMuX2Z1bGxzY3JlZW5CdXR0b249aS5jcmVhdGUoXCJidXR0b25cIix0aGlzLl9jbGFzc05hbWUrXCItaWNvbiBcIit0aGlzLl9jbGFzc05hbWUrXCItZnVsbHNjcmVlblwiLHRoaXMuX2NvbnRyb2xDb250YWluZXIpKS50eXBlPVwiYnV0dG9uXCIsdGhpcy5fdXBkYXRlVGl0bGUoKSx0aGlzLl9mdWxsc2NyZWVuQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLHRoaXMuX29uQ2xpY2tGdWxsc2NyZWVuKSx0LndpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKHRoaXMuX2Z1bGxzY3JlZW5jaGFuZ2UsdGhpcy5fY2hhbmdlSWNvbik7fSxZby5wcm90b3R5cGUuX3VwZGF0ZVRpdGxlPWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5faXNGdWxsc2NyZWVuKCk/XCJFeGl0IGZ1bGxzY3JlZW5cIjpcIkVudGVyIGZ1bGxzY3JlZW5cIjt0aGlzLl9mdWxsc2NyZWVuQnV0dG9uLnNldEF0dHJpYnV0ZShcImFyaWEtbGFiZWxcIix0KSx0aGlzLl9mdWxsc2NyZWVuQnV0dG9uLnRpdGxlPXQ7fSxZby5wcm90b3R5cGUuX2lzRnVsbHNjcmVlbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9mdWxsc2NyZWVufSxZby5wcm90b3R5cGUuX2NoYW5nZUljb249ZnVuY3Rpb24oKXsodC53aW5kb3cuZG9jdW1lbnQuZnVsbHNjcmVlbkVsZW1lbnR8fHQud2luZG93LmRvY3VtZW50Lm1vekZ1bGxTY3JlZW5FbGVtZW50fHx0LndpbmRvdy5kb2N1bWVudC53ZWJraXRGdWxsc2NyZWVuRWxlbWVudHx8dC53aW5kb3cuZG9jdW1lbnQubXNGdWxsc2NyZWVuRWxlbWVudCk9PT10aGlzLl9jb250YWluZXIhPT10aGlzLl9mdWxsc2NyZWVuJiYodGhpcy5fZnVsbHNjcmVlbj0hdGhpcy5fZnVsbHNjcmVlbix0aGlzLl9mdWxsc2NyZWVuQnV0dG9uLmNsYXNzTGlzdC50b2dnbGUodGhpcy5fY2xhc3NOYW1lK1wiLXNocmlua1wiKSx0aGlzLl9mdWxsc2NyZWVuQnV0dG9uLmNsYXNzTGlzdC50b2dnbGUodGhpcy5fY2xhc3NOYW1lK1wiLWZ1bGxzY3JlZW5cIiksdGhpcy5fdXBkYXRlVGl0bGUoKSk7fSxZby5wcm90b3R5cGUuX29uQ2xpY2tGdWxsc2NyZWVuPWZ1bmN0aW9uKCl7dGhpcy5faXNGdWxsc2NyZWVuKCk/dC53aW5kb3cuZG9jdW1lbnQuZXhpdEZ1bGxzY3JlZW4/dC53aW5kb3cuZG9jdW1lbnQuZXhpdEZ1bGxzY3JlZW4oKTp0LndpbmRvdy5kb2N1bWVudC5tb3pDYW5jZWxGdWxsU2NyZWVuP3Qud2luZG93LmRvY3VtZW50Lm1vekNhbmNlbEZ1bGxTY3JlZW4oKTp0LndpbmRvdy5kb2N1bWVudC5tc0V4aXRGdWxsc2NyZWVuP3Qud2luZG93LmRvY3VtZW50Lm1zRXhpdEZ1bGxzY3JlZW4oKTp0LndpbmRvdy5kb2N1bWVudC53ZWJraXRDYW5jZWxGdWxsU2NyZWVuJiZ0LndpbmRvdy5kb2N1bWVudC53ZWJraXRDYW5jZWxGdWxsU2NyZWVuKCk6dGhpcy5fY29udGFpbmVyLnJlcXVlc3RGdWxsc2NyZWVuP3RoaXMuX2NvbnRhaW5lci5yZXF1ZXN0RnVsbHNjcmVlbigpOnRoaXMuX2NvbnRhaW5lci5tb3pSZXF1ZXN0RnVsbFNjcmVlbj90aGlzLl9jb250YWluZXIubW96UmVxdWVzdEZ1bGxTY3JlZW4oKTp0aGlzLl9jb250YWluZXIubXNSZXF1ZXN0RnVsbHNjcmVlbj90aGlzLl9jb250YWluZXIubXNSZXF1ZXN0RnVsbHNjcmVlbigpOnRoaXMuX2NvbnRhaW5lci53ZWJraXRSZXF1ZXN0RnVsbHNjcmVlbiYmdGhpcy5fY29udGFpbmVyLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuKCk7fTt2YXIgSm89e2Nsb3NlQnV0dG9uOiEwLGNsb3NlT25DbGljazohMCxjbGFzc05hbWU6XCJcIixtYXhXaWR0aDpcIjI0MHB4XCJ9LFFvPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIG8oaSl7ZS5jYWxsKHRoaXMpLHRoaXMub3B0aW9ucz10LmV4dGVuZChPYmplY3QuY3JlYXRlKEpvKSxpKSx0LmJpbmRBbGwoW1wiX3VwZGF0ZVwiLFwiX29uQ2xpY2tDbG9zZVwiLFwicmVtb3ZlXCJdLHRoaXMpO31yZXR1cm4gZSYmKG8uX19wcm90b19fPWUpLG8ucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZSYmZS5wcm90b3R5cGUpLG8ucHJvdG90eXBlLmNvbnN0cnVjdG9yPW8sby5wcm90b3R5cGUuYWRkVG89ZnVuY3Rpb24oZSl7dmFyIGk9dGhpcztyZXR1cm4gdGhpcy5fbWFwPWUsdGhpcy5vcHRpb25zLmNsb3NlT25DbGljayYmdGhpcy5fbWFwLm9uKFwiY2xpY2tcIix0aGlzLl9vbkNsaWNrQ2xvc2UpLHRoaXMuX21hcC5vbihcInJlbW92ZVwiLHRoaXMucmVtb3ZlKSx0aGlzLl91cGRhdGUoKSx0aGlzLl90cmFja1BvaW50ZXI/KHRoaXMuX21hcC5vbihcIm1vdXNlbW92ZVwiLGZ1bmN0aW9uKHQpe2kuX3VwZGF0ZSh0LnBvaW50KTt9KSx0aGlzLl9tYXAub24oXCJtb3VzZXVwXCIsZnVuY3Rpb24odCl7aS5fdXBkYXRlKHQucG9pbnQpO30pLHRoaXMuX2NvbnRhaW5lci5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtcG9wdXAtdHJhY2stcG9pbnRlclwiKSx0aGlzLl9tYXAuX2NhbnZhc0NvbnRhaW5lci5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtdHJhY2stcG9pbnRlclwiKSk6dGhpcy5fbWFwLm9uKFwibW92ZVwiLHRoaXMuX3VwZGF0ZSksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwib3BlblwiKSksdGhpc30sby5wcm90b3R5cGUuaXNPcGVuPWZ1bmN0aW9uKCl7cmV0dXJuICEhdGhpcy5fbWFwfSxvLnByb3RvdHlwZS5yZW1vdmU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fY29udGVudCYmaS5yZW1vdmUodGhpcy5fY29udGVudCksdGhpcy5fY29udGFpbmVyJiYoaS5yZW1vdmUodGhpcy5fY29udGFpbmVyKSxkZWxldGUgdGhpcy5fY29udGFpbmVyKSx0aGlzLl9tYXAmJih0aGlzLl9tYXAub2ZmKFwibW92ZVwiLHRoaXMuX3VwZGF0ZSksdGhpcy5fbWFwLm9mZihcImNsaWNrXCIsdGhpcy5fb25DbGlja0Nsb3NlKSx0aGlzLl9tYXAub2ZmKFwicmVtb3ZlXCIsdGhpcy5yZW1vdmUpLHRoaXMuX21hcC5vZmYoXCJtb3VzZW1vdmVcIiksZGVsZXRlIHRoaXMuX21hcCksdGhpcy5maXJlKG5ldyB0LkV2ZW50KFwiY2xvc2VcIikpLHRoaXN9LG8ucHJvdG90eXBlLmdldExuZ0xhdD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9sbmdMYXR9LG8ucHJvdG90eXBlLnNldExuZ0xhdD1mdW5jdGlvbihlKXtyZXR1cm4gdGhpcy5fbG5nTGF0PXQuTG5nTGF0LmNvbnZlcnQoZSksdGhpcy5fcG9zPW51bGwsdGhpcy5fbWFwJiYodGhpcy5fbWFwLm9uKFwibW92ZVwiLHRoaXMuX3VwZGF0ZSksdGhpcy5fbWFwLm9mZihcIm1vdXNlbW92ZVwiKSx0aGlzLl9jb250YWluZXIuY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLXBvcHVwLXRyYWNrLXBvaW50ZXJcIiksdGhpcy5fbWFwLl9jYW52YXNDb250YWluZXIuY2xhc3NMaXN0LnJlbW92ZShcIm1hcGJveGdsLXRyYWNrLXBvaW50ZXJcIikpLHRoaXMuX3RyYWNrUG9pbnRlcj0hMSx0aGlzLl91cGRhdGUoKSx0aGlzfSxvLnByb3RvdHlwZS50cmFja1BvaW50ZXI9ZnVuY3Rpb24oKXt2YXIgdD10aGlzO3JldHVybiB0aGlzLl90cmFja1BvaW50ZXI9ITAsdGhpcy5fcG9zPW51bGwsdGhpcy5fbWFwJiYodGhpcy5fbWFwLm9mZihcIm1vdmVcIix0aGlzLl91cGRhdGUpLHRoaXMuX21hcC5vbihcIm1vdXNlbW92ZVwiLGZ1bmN0aW9uKGUpe3QuX3VwZGF0ZShlLnBvaW50KTt9KSx0aGlzLl9tYXAub24oXCJkcmFnXCIsZnVuY3Rpb24oZSl7dC5fdXBkYXRlKGUucG9pbnQpO30pLHRoaXMuX2NvbnRhaW5lci5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtcG9wdXAtdHJhY2stcG9pbnRlclwiKSx0aGlzLl9tYXAuX2NhbnZhc0NvbnRhaW5lci5jbGFzc0xpc3QuYWRkKFwibWFwYm94Z2wtdHJhY2stcG9pbnRlclwiKSksdGhpc30sby5wcm90b3R5cGUuZ2V0RWxlbWVudD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9jb250YWluZXJ9LG8ucHJvdG90eXBlLnNldFRleHQ9ZnVuY3Rpb24oZSl7cmV0dXJuIHRoaXMuc2V0RE9NQ29udGVudCh0LndpbmRvdy5kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShlKSl9LG8ucHJvdG90eXBlLnNldEhUTUw9ZnVuY3Rpb24oZSl7dmFyIGksbz10LndpbmRvdy5kb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkscj10LndpbmRvdy5kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYm9keVwiKTtmb3Ioci5pbm5lckhUTUw9ZTtpPXIuZmlyc3RDaGlsZDspby5hcHBlbmRDaGlsZChpKTtyZXR1cm4gdGhpcy5zZXRET01Db250ZW50KG8pfSxvLnByb3RvdHlwZS5nZXRNYXhXaWR0aD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9jb250YWluZXIuc3R5bGUubWF4V2lkdGh9LG8ucHJvdG90eXBlLnNldE1heFdpZHRoPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLm9wdGlvbnMubWF4V2lkdGg9dCx0aGlzLl91cGRhdGUoKSx0aGlzfSxvLnByb3RvdHlwZS5zZXRET01Db250ZW50PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9jcmVhdGVDb250ZW50KCksdGhpcy5fY29udGVudC5hcHBlbmRDaGlsZCh0KSx0aGlzLl91cGRhdGUoKSx0aGlzfSxvLnByb3RvdHlwZS5fY3JlYXRlQ29udGVudD1mdW5jdGlvbigpe3RoaXMuX2NvbnRlbnQmJmkucmVtb3ZlKHRoaXMuX2NvbnRlbnQpLHRoaXMuX2NvbnRlbnQ9aS5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLXBvcHVwLWNvbnRlbnRcIix0aGlzLl9jb250YWluZXIpLHRoaXMub3B0aW9ucy5jbG9zZUJ1dHRvbiYmKHRoaXMuX2Nsb3NlQnV0dG9uPWkuY3JlYXRlKFwiYnV0dG9uXCIsXCJtYXBib3hnbC1wb3B1cC1jbG9zZS1idXR0b25cIix0aGlzLl9jb250ZW50KSx0aGlzLl9jbG9zZUJ1dHRvbi50eXBlPVwiYnV0dG9uXCIsdGhpcy5fY2xvc2VCdXR0b24uc2V0QXR0cmlidXRlKFwiYXJpYS1sYWJlbFwiLFwiQ2xvc2UgcG9wdXBcIiksdGhpcy5fY2xvc2VCdXR0b24uaW5uZXJIVE1MPVwiJiMyMTU7XCIsdGhpcy5fY2xvc2VCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsdGhpcy5fb25DbGlja0Nsb3NlKSk7fSxvLnByb3RvdHlwZS5fdXBkYXRlPWZ1bmN0aW9uKGUpe3ZhciBvPXRoaXMscj10aGlzLl9sbmdMYXR8fHRoaXMuX3RyYWNrUG9pbnRlcjtpZih0aGlzLl9tYXAmJnImJnRoaXMuX2NvbnRlbnQmJih0aGlzLl9jb250YWluZXJ8fCh0aGlzLl9jb250YWluZXI9aS5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLXBvcHVwXCIsdGhpcy5fbWFwLmdldENvbnRhaW5lcigpKSx0aGlzLl90aXA9aS5jcmVhdGUoXCJkaXZcIixcIm1hcGJveGdsLXBvcHVwLXRpcFwiLHRoaXMuX2NvbnRhaW5lciksdGhpcy5fY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuX2NvbnRlbnQpLHRoaXMub3B0aW9ucy5jbGFzc05hbWUmJnRoaXMub3B0aW9ucy5jbGFzc05hbWUuc3BsaXQoXCIgXCIpLmZvckVhY2goZnVuY3Rpb24odCl7cmV0dXJuIG8uX2NvbnRhaW5lci5jbGFzc0xpc3QuYWRkKHQpfSkpLHRoaXMub3B0aW9ucy5tYXhXaWR0aCYmdGhpcy5fY29udGFpbmVyLnN0eWxlLm1heFdpZHRoIT09dGhpcy5vcHRpb25zLm1heFdpZHRoJiYodGhpcy5fY29udGFpbmVyLnN0eWxlLm1heFdpZHRoPXRoaXMub3B0aW9ucy5tYXhXaWR0aCksdGhpcy5fbWFwLnRyYW5zZm9ybS5yZW5kZXJXb3JsZENvcGllcyYmIXRoaXMuX3RyYWNrUG9pbnRlciYmKHRoaXMuX2xuZ0xhdD1Vbyh0aGlzLl9sbmdMYXQsdGhpcy5fcG9zLHRoaXMuX21hcC50cmFuc2Zvcm0pKSwhdGhpcy5fdHJhY2tQb2ludGVyfHxlKSl7dmFyIGE9dGhpcy5fcG9zPXRoaXMuX3RyYWNrUG9pbnRlciYmZT9lOnRoaXMuX21hcC5wcm9qZWN0KHRoaXMuX2xuZ0xhdCksbj10aGlzLm9wdGlvbnMuYW5jaG9yLHM9ZnVuY3Rpb24gZShpKXtpZihpKXtpZihcIm51bWJlclwiPT10eXBlb2YgaSl7dmFyIG89TWF0aC5yb3VuZChNYXRoLnNxcnQoLjUqTWF0aC5wb3coaSwyKSkpO3JldHVybiB7Y2VudGVyOm5ldyB0LlBvaW50KDAsMCksdG9wOm5ldyB0LlBvaW50KDAsaSksXCJ0b3AtbGVmdFwiOm5ldyB0LlBvaW50KG8sbyksXCJ0b3AtcmlnaHRcIjpuZXcgdC5Qb2ludCgtbyxvKSxib3R0b206bmV3IHQuUG9pbnQoMCwtaSksXCJib3R0b20tbGVmdFwiOm5ldyB0LlBvaW50KG8sLW8pLFwiYm90dG9tLXJpZ2h0XCI6bmV3IHQuUG9pbnQoLW8sLW8pLGxlZnQ6bmV3IHQuUG9pbnQoaSwwKSxyaWdodDpuZXcgdC5Qb2ludCgtaSwwKX19aWYoaSBpbnN0YW5jZW9mIHQuUG9pbnR8fEFycmF5LmlzQXJyYXkoaSkpe3ZhciByPXQuUG9pbnQuY29udmVydChpKTtyZXR1cm4ge2NlbnRlcjpyLHRvcDpyLFwidG9wLWxlZnRcIjpyLFwidG9wLXJpZ2h0XCI6cixib3R0b206cixcImJvdHRvbS1sZWZ0XCI6cixcImJvdHRvbS1yaWdodFwiOnIsbGVmdDpyLHJpZ2h0OnJ9fXJldHVybiB7Y2VudGVyOnQuUG9pbnQuY29udmVydChpLmNlbnRlcnx8WzAsMF0pLHRvcDp0LlBvaW50LmNvbnZlcnQoaS50b3B8fFswLDBdKSxcInRvcC1sZWZ0XCI6dC5Qb2ludC5jb252ZXJ0KGlbXCJ0b3AtbGVmdFwiXXx8WzAsMF0pLFwidG9wLXJpZ2h0XCI6dC5Qb2ludC5jb252ZXJ0KGlbXCJ0b3AtcmlnaHRcIl18fFswLDBdKSxib3R0b206dC5Qb2ludC5jb252ZXJ0KGkuYm90dG9tfHxbMCwwXSksXCJib3R0b20tbGVmdFwiOnQuUG9pbnQuY29udmVydChpW1wiYm90dG9tLWxlZnRcIl18fFswLDBdKSxcImJvdHRvbS1yaWdodFwiOnQuUG9pbnQuY29udmVydChpW1wiYm90dG9tLXJpZ2h0XCJdfHxbMCwwXSksbGVmdDp0LlBvaW50LmNvbnZlcnQoaS5sZWZ0fHxbMCwwXSkscmlnaHQ6dC5Qb2ludC5jb252ZXJ0KGkucmlnaHR8fFswLDBdKX19cmV0dXJuIGUobmV3IHQuUG9pbnQoMCwwKSl9KHRoaXMub3B0aW9ucy5vZmZzZXQpO2lmKCFuKXt2YXIgbCxjPXRoaXMuX2NvbnRhaW5lci5vZmZzZXRXaWR0aCx1PXRoaXMuX2NvbnRhaW5lci5vZmZzZXRIZWlnaHQ7bD1hLnkrcy5ib3R0b20ueTx1P1tcInRvcFwiXTphLnk+dGhpcy5fbWFwLnRyYW5zZm9ybS5oZWlnaHQtdT9bXCJib3R0b21cIl06W10sYS54PGMvMj9sLnB1c2goXCJsZWZ0XCIpOmEueD50aGlzLl9tYXAudHJhbnNmb3JtLndpZHRoLWMvMiYmbC5wdXNoKFwicmlnaHRcIiksbj0wPT09bC5sZW5ndGg/XCJib3R0b21cIjpsLmpvaW4oXCItXCIpO312YXIgaD1hLmFkZChzW25dKS5yb3VuZCgpO2kuc2V0VHJhbnNmb3JtKHRoaXMuX2NvbnRhaW5lcixOb1tuXStcIiB0cmFuc2xhdGUoXCIraC54K1wicHgsXCIraC55K1wicHgpXCIpLFpvKHRoaXMuX2NvbnRhaW5lcixuLFwicG9wdXBcIik7fX0sby5wcm90b3R5cGUuX29uQ2xpY2tDbG9zZT1mdW5jdGlvbigpe3RoaXMucmVtb3ZlKCk7fSxvfSh0LkV2ZW50ZWQpO3ZhciAkbz17dmVyc2lvbjp0LnZlcnNpb24sc3VwcG9ydGVkOmUsc2V0UlRMVGV4dFBsdWdpbjp0LnNldFJUTFRleHRQbHVnaW4sTWFwOmtvLE5hdmlnYXRpb25Db250cm9sOkZvLEdlb2xvY2F0ZUNvbnRyb2w6R28sQXR0cmlidXRpb25Db250cm9sOnpvLFNjYWxlQ29udHJvbDpYbyxGdWxsc2NyZWVuQ29udHJvbDpZbyxQb3B1cDpRbyxNYXJrZXI6cW8sU3R5bGU6QmUsTG5nTGF0OnQuTG5nTGF0LExuZ0xhdEJvdW5kczp0LkxuZ0xhdEJvdW5kcyxQb2ludDp0LlBvaW50LE1lcmNhdG9yQ29vcmRpbmF0ZTp0Lk1lcmNhdG9yQ29vcmRpbmF0ZSxFdmVudGVkOnQuRXZlbnRlZCxjb25maWc6dC5jb25maWcsZ2V0IGFjY2Vzc1Rva2VuKCl7cmV0dXJuIHQuY29uZmlnLkFDQ0VTU19UT0tFTn0sc2V0IGFjY2Vzc1Rva2VuKGUpe3QuY29uZmlnLkFDQ0VTU19UT0tFTj1lO30sZ2V0IGJhc2VBcGlVcmwoKXtyZXR1cm4gdC5jb25maWcuQVBJX1VSTH0sc2V0IGJhc2VBcGlVcmwoZSl7dC5jb25maWcuQVBJX1VSTD1lO30sZ2V0IHdvcmtlckNvdW50KCl7cmV0dXJuIFJ0LndvcmtlckNvdW50fSxzZXQgd29ya2VyQ291bnQodCl7UnQud29ya2VyQ291bnQ9dDt9LGdldCBtYXhQYXJhbGxlbEltYWdlUmVxdWVzdHMoKXtyZXR1cm4gdC5jb25maWcuTUFYX1BBUkFMTEVMX0lNQUdFX1JFUVVFU1RTfSxzZXQgbWF4UGFyYWxsZWxJbWFnZVJlcXVlc3RzKGUpe3QuY29uZmlnLk1BWF9QQVJBTExFTF9JTUFHRV9SRVFVRVNUUz1lO30sY2xlYXJTdG9yYWdlOmZ1bmN0aW9uKGUpe3QuY2xlYXJUaWxlQ2FjaGUoZSk7fSx3b3JrZXJVcmw6XCJcIn07cmV0dXJuICRvfSk7XG5cbi8vXG5cbnJldHVybiBtYXBib3hnbDtcblxufSkpO1xuXG5cbn0se31dLDQyNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVUYWJsZVxuXG52YXIgY2h1bGwgPSBfZGVyZXFfKCdjb252ZXgtaHVsbCcpXG5cbmZ1bmN0aW9uIGNvbnN0cnVjdFZlcnRleChkLCBhLCBiKSB7XG4gIHZhciB4ID0gbmV3IEFycmF5KGQpXG4gIGZvcih2YXIgaT0wOyBpPGQ7ICsraSkge1xuICAgIHhbaV0gPSAwLjBcbiAgICBpZihpID09PSBhKSB7XG4gICAgICB4W2ldICs9IDAuNVxuICAgIH1cbiAgICBpZihpID09PSBiKSB7XG4gICAgICB4W2ldICs9IDAuNVxuICAgIH1cbiAgfVxuICByZXR1cm4geFxufVxuXG5mdW5jdGlvbiBjb25zdHJ1Y3RDZWxsKGRpbWVuc2lvbiwgbWFzaykge1xuICBpZihtYXNrID09PSAwIHx8IG1hc2sgPT09ICgxPDwoZGltZW5zaW9uKzEpKS0xKSB7XG4gICAgcmV0dXJuIFtdXG4gIH1cbiAgdmFyIHBvaW50cyA9IFtdXG4gIHZhciBpbmRleCAgPSBbXVxuICBmb3IodmFyIGk9MDsgaTw9ZGltZW5zaW9uOyArK2kpIHtcbiAgICBpZihtYXNrICYgKDE8PGkpKSB7XG4gICAgICBwb2ludHMucHVzaChjb25zdHJ1Y3RWZXJ0ZXgoZGltZW5zaW9uLCBpLTEsIGktMSkpXG4gICAgICBpbmRleC5wdXNoKG51bGwpXG4gICAgICBmb3IodmFyIGo9MDsgajw9ZGltZW5zaW9uOyArK2opIHtcbiAgICAgICAgaWYofm1hc2sgJiAoMTw8aikpIHtcbiAgICAgICAgICBwb2ludHMucHVzaChjb25zdHJ1Y3RWZXJ0ZXgoZGltZW5zaW9uLCBpLTEsIGotMSkpXG4gICAgICAgICAgaW5kZXgucHVzaChbaSxqXSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuICBcbiAgLy9QcmVwcm9jZXNzIHBvaW50cyBzbyBmaXJzdCBkKzEgcG9pbnRzIGFyZSBsaW5lYXJseSBpbmRlcGVuZGVudFxuICB2YXIgaHVsbCA9IGNodWxsKHBvaW50cylcbiAgdmFyIGZhY2VzID0gW11cbmlfbG9vcDpcbiAgZm9yKHZhciBpPTA7IGk8aHVsbC5sZW5ndGg7ICsraSkge1xuICAgIHZhciBmYWNlID0gaHVsbFtpXVxuICAgIHZhciBuZmFjZSA9IFtdXG4gICAgZm9yKHZhciBqPTA7IGo8ZmFjZS5sZW5ndGg7ICsraikge1xuICAgICAgaWYoIWluZGV4W2ZhY2Vbal1dKSB7XG4gICAgICAgIGNvbnRpbnVlIGlfbG9vcFxuICAgICAgfVxuICAgICAgbmZhY2UucHVzaChpbmRleFtmYWNlW2pdXS5zbGljZSgpKVxuICAgIH1cbiAgICBmYWNlcy5wdXNoKG5mYWNlKVxuICB9XG4gIHJldHVybiBmYWNlc1xufVxuXG5mdW5jdGlvbiBjcmVhdGVUYWJsZShkaW1lbnNpb24pIHtcbiAgdmFyIG51bUNlbGxzID0gMTw8KGRpbWVuc2lvbisxKVxuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG51bUNlbGxzKVxuICBmb3IodmFyIGk9MDsgaTxudW1DZWxsczsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gY29uc3RydWN0Q2VsbChkaW1lbnNpb24sIGkpXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxufSx7XCJjb252ZXgtaHVsbFwiOjEzMH1dLDQyODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKmpzaGludCB1bnVzZWQ6dHJ1ZSovXG4vKlxuSW5wdXQ6ICBtYXRyaXggICAgICA7IGEgNHg0IG1hdHJpeFxuT3V0cHV0OiB0cmFuc2xhdGlvbiA7IGEgMyBjb21wb25lbnQgdmVjdG9yXG4gICAgICAgIHNjYWxlICAgICAgIDsgYSAzIGNvbXBvbmVudCB2ZWN0b3JcbiAgICAgICAgc2tldyAgICAgICAgOyBza2V3IGZhY3RvcnMgWFksWFosWVogcmVwcmVzZW50ZWQgYXMgYSAzIGNvbXBvbmVudCB2ZWN0b3JcbiAgICAgICAgcGVyc3BlY3RpdmUgOyBhIDQgY29tcG9uZW50IHZlY3RvclxuICAgICAgICBxdWF0ZXJuaW9uICA7IGEgNCBjb21wb25lbnQgdmVjdG9yXG5SZXR1cm5zIGZhbHNlIGlmIHRoZSBtYXRyaXggY2Fubm90IGJlIGRlY29tcG9zZWQsIHRydWUgaWYgaXQgY2FuXG5cblxuUmVmZXJlbmNlczpcbmh0dHBzOi8vZ2l0aHViLmNvbS9rYW1pY2FuZS9tYXRyaXgzZC9ibG9iL21hc3Rlci9saWIvTWF0cml4M2QuanNcbmh0dHBzOi8vZ2l0aHViLmNvbS9DaHJvbWl1bVdlYkFwcHMvY2hyb21pdW0vYmxvYi9tYXN0ZXIvdWkvZ2Z4L3RyYW5zZm9ybV91dGlsLmNjXG5odHRwOi8vd3d3LnczLm9yZy9UUi9jc3MzLXRyYW5zZm9ybXMvI2RlY29tcG9zaW5nLWEtM2QtbWF0cml4XG4qL1xuXG52YXIgbm9ybWFsaXplID0gX2RlcmVxXygnLi9ub3JtYWxpemUnKVxuXG52YXIgY3JlYXRlID0gX2RlcmVxXygnZ2wtbWF0NC9jcmVhdGUnKVxudmFyIGNsb25lID0gX2RlcmVxXygnZ2wtbWF0NC9jbG9uZScpXG52YXIgZGV0ZXJtaW5hbnQgPSBfZGVyZXFfKCdnbC1tYXQ0L2RldGVybWluYW50JylcbnZhciBpbnZlcnQgPSBfZGVyZXFfKCdnbC1tYXQ0L2ludmVydCcpXG52YXIgdHJhbnNwb3NlID0gX2RlcmVxXygnZ2wtbWF0NC90cmFuc3Bvc2UnKVxudmFyIHZlYzMgPSB7XG4gICAgbGVuZ3RoOiBfZGVyZXFfKCdnbC12ZWMzL2xlbmd0aCcpLFxuICAgIG5vcm1hbGl6ZTogX2RlcmVxXygnZ2wtdmVjMy9ub3JtYWxpemUnKSxcbiAgICBkb3Q6IF9kZXJlcV8oJ2dsLXZlYzMvZG90JyksXG4gICAgY3Jvc3M6IF9kZXJlcV8oJ2dsLXZlYzMvY3Jvc3MnKVxufVxuXG52YXIgdG1wID0gY3JlYXRlKClcbnZhciBwZXJzcGVjdGl2ZU1hdHJpeCA9IGNyZWF0ZSgpXG52YXIgdG1wVmVjNCA9IFswLCAwLCAwLCAwXVxudmFyIHJvdyA9IFsgWzAsMCwwXSwgWzAsMCwwXSwgWzAsMCwwXSBdXG52YXIgcGR1bTMgPSBbMCwwLDBdXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZGVjb21wb3NlTWF0NChtYXRyaXgsIHRyYW5zbGF0aW9uLCBzY2FsZSwgc2tldywgcGVyc3BlY3RpdmUsIHF1YXRlcm5pb24pIHtcbiAgICBpZiAoIXRyYW5zbGF0aW9uKSB0cmFuc2xhdGlvbiA9IFswLDAsMF1cbiAgICBpZiAoIXNjYWxlKSBzY2FsZSA9IFswLDAsMF1cbiAgICBpZiAoIXNrZXcpIHNrZXcgPSBbMCwwLDBdXG4gICAgaWYgKCFwZXJzcGVjdGl2ZSkgcGVyc3BlY3RpdmUgPSBbMCwwLDAsMV1cbiAgICBpZiAoIXF1YXRlcm5pb24pIHF1YXRlcm5pb24gPSBbMCwwLDAsMV1cblxuICAgIC8vbm9ybWFsaXplLCBpZiBub3QgcG9zc2libGUgdGhlbiBiYWlsIG91dCBlYXJseVxuICAgIGlmICghbm9ybWFsaXplKHRtcCwgbWF0cml4KSlcbiAgICAgICAgcmV0dXJuIGZhbHNlXG5cbiAgICAvLyBwZXJzcGVjdGl2ZU1hdHJpeCBpcyB1c2VkIHRvIHNvbHZlIGZvciBwZXJzcGVjdGl2ZSwgYnV0IGl0IGFsc28gcHJvdmlkZXNcbiAgICAvLyBhbiBlYXN5IHdheSB0byB0ZXN0IGZvciBzaW5ndWxhcml0eSBvZiB0aGUgdXBwZXIgM3gzIGNvbXBvbmVudC5cbiAgICBjbG9uZShwZXJzcGVjdGl2ZU1hdHJpeCwgdG1wKVxuXG4gICAgcGVyc3BlY3RpdmVNYXRyaXhbM10gPSAwXG4gICAgcGVyc3BlY3RpdmVNYXRyaXhbN10gPSAwXG4gICAgcGVyc3BlY3RpdmVNYXRyaXhbMTFdID0gMFxuICAgIHBlcnNwZWN0aXZlTWF0cml4WzE1XSA9IDFcblxuICAgIC8vIElmIHRoZSBwZXJzcGVjdGl2ZU1hdHJpeCBpcyBub3QgaW52ZXJ0aWJsZSwgd2UgYXJlIGFsc28gdW5hYmxlIHRvXG4gICAgLy8gZGVjb21wb3NlLCBzbyB3ZSdsbCBiYWlsIGVhcmx5LiBDb25zdGFudCB0YWtlbiBmcm9tIFNrTWF0cml4NDQ6OmludmVydC5cbiAgICBpZiAoTWF0aC5hYnMoZGV0ZXJtaW5hbnQocGVyc3BlY3RpdmVNYXRyaXgpIDwgMWUtOCkpXG4gICAgICAgIHJldHVybiBmYWxzZVxuXG4gICAgdmFyIGEwMyA9IHRtcFszXSwgYTEzID0gdG1wWzddLCBhMjMgPSB0bXBbMTFdLFxuICAgICAgICAgICAgYTMwID0gdG1wWzEyXSwgYTMxID0gdG1wWzEzXSwgYTMyID0gdG1wWzE0XSwgYTMzID0gdG1wWzE1XVxuXG4gICAgLy8gRmlyc3QsIGlzb2xhdGUgcGVyc3BlY3RpdmUuXG4gICAgaWYgKGEwMyAhPT0gMCB8fCBhMTMgIT09IDAgfHwgYTIzICE9PSAwKSB7XG4gICAgICAgIHRtcFZlYzRbMF0gPSBhMDNcbiAgICAgICAgdG1wVmVjNFsxXSA9IGExM1xuICAgICAgICB0bXBWZWM0WzJdID0gYTIzXG4gICAgICAgIHRtcFZlYzRbM10gPSBhMzNcblxuICAgICAgICAvLyBTb2x2ZSB0aGUgZXF1YXRpb24gYnkgaW52ZXJ0aW5nIHBlcnNwZWN0aXZlTWF0cml4IGFuZCBtdWx0aXBseWluZ1xuICAgICAgICAvLyByaWdodEhhbmRTaWRlIGJ5IHRoZSBpbnZlcnNlLlxuICAgICAgICAvLyByZXN1aW5nIHRoZSBwZXJzcGVjdGl2ZU1hdHJpeCBoZXJlIHNpbmNlIGl0J3Mgbm8gbG9uZ2VyIG5lZWRlZFxuICAgICAgICB2YXIgcmV0ID0gaW52ZXJ0KHBlcnNwZWN0aXZlTWF0cml4LCBwZXJzcGVjdGl2ZU1hdHJpeClcbiAgICAgICAgaWYgKCFyZXQpIHJldHVybiBmYWxzZVxuICAgICAgICB0cmFuc3Bvc2UocGVyc3BlY3RpdmVNYXRyaXgsIHBlcnNwZWN0aXZlTWF0cml4KVxuXG4gICAgICAgIC8vbXVsdGlwbHkgYnkgdHJhbnNwb3NlZCBpbnZlcnNlIHBlcnNwZWN0aXZlIG1hdHJpeCwgaW50byBwZXJzcGVjdGl2ZSB2ZWM0XG4gICAgICAgIHZlYzRtdWx0TWF0NChwZXJzcGVjdGl2ZSwgdG1wVmVjNCwgcGVyc3BlY3RpdmVNYXRyaXgpXG4gICAgfSBlbHNlIHsgXG4gICAgICAgIC8vbm8gcGVyc3BlY3RpdmVcbiAgICAgICAgcGVyc3BlY3RpdmVbMF0gPSBwZXJzcGVjdGl2ZVsxXSA9IHBlcnNwZWN0aXZlWzJdID0gMFxuICAgICAgICBwZXJzcGVjdGl2ZVszXSA9IDFcbiAgICB9XG5cbiAgICAvLyBOZXh0IHRha2UgY2FyZSBvZiB0cmFuc2xhdGlvblxuICAgIHRyYW5zbGF0aW9uWzBdID0gYTMwXG4gICAgdHJhbnNsYXRpb25bMV0gPSBhMzFcbiAgICB0cmFuc2xhdGlvblsyXSA9IGEzMlxuXG4gICAgLy8gTm93IGdldCBzY2FsZSBhbmQgc2hlYXIuICdyb3cnIGlzIGEgMyBlbGVtZW50IGFycmF5IG9mIDMgY29tcG9uZW50IHZlY3RvcnNcbiAgICBtYXQzZnJvbTQocm93LCB0bXApXG5cbiAgICAvLyBDb21wdXRlIFggc2NhbGUgZmFjdG9yIGFuZCBub3JtYWxpemUgZmlyc3Qgcm93LlxuICAgIHNjYWxlWzBdID0gdmVjMy5sZW5ndGgocm93WzBdKVxuICAgIHZlYzMubm9ybWFsaXplKHJvd1swXSwgcm93WzBdKVxuXG4gICAgLy8gQ29tcHV0ZSBYWSBzaGVhciBmYWN0b3IgYW5kIG1ha2UgMm5kIHJvdyBvcnRob2dvbmFsIHRvIDFzdC5cbiAgICBza2V3WzBdID0gdmVjMy5kb3Qocm93WzBdLCByb3dbMV0pXG4gICAgY29tYmluZShyb3dbMV0sIHJvd1sxXSwgcm93WzBdLCAxLjAsIC1za2V3WzBdKVxuXG4gICAgLy8gTm93LCBjb21wdXRlIFkgc2NhbGUgYW5kIG5vcm1hbGl6ZSAybmQgcm93LlxuICAgIHNjYWxlWzFdID0gdmVjMy5sZW5ndGgocm93WzFdKVxuICAgIHZlYzMubm9ybWFsaXplKHJvd1sxXSwgcm93WzFdKVxuICAgIHNrZXdbMF0gLz0gc2NhbGVbMV1cblxuICAgIC8vIENvbXB1dGUgWFogYW5kIFlaIHNoZWFycywgb3J0aG9nb25hbGl6ZSAzcmQgcm93XG4gICAgc2tld1sxXSA9IHZlYzMuZG90KHJvd1swXSwgcm93WzJdKVxuICAgIGNvbWJpbmUocm93WzJdLCByb3dbMl0sIHJvd1swXSwgMS4wLCAtc2tld1sxXSlcbiAgICBza2V3WzJdID0gdmVjMy5kb3Qocm93WzFdLCByb3dbMl0pXG4gICAgY29tYmluZShyb3dbMl0sIHJvd1syXSwgcm93WzFdLCAxLjAsIC1za2V3WzJdKVxuXG4gICAgLy8gTmV4dCwgZ2V0IFogc2NhbGUgYW5kIG5vcm1hbGl6ZSAzcmQgcm93LlxuICAgIHNjYWxlWzJdID0gdmVjMy5sZW5ndGgocm93WzJdKVxuICAgIHZlYzMubm9ybWFsaXplKHJvd1syXSwgcm93WzJdKVxuICAgIHNrZXdbMV0gLz0gc2NhbGVbMl1cbiAgICBza2V3WzJdIC89IHNjYWxlWzJdXG5cblxuICAgIC8vIEF0IHRoaXMgcG9pbnQsIHRoZSBtYXRyaXggKGluIHJvd3MpIGlzIG9ydGhvbm9ybWFsLlxuICAgIC8vIENoZWNrIGZvciBhIGNvb3JkaW5hdGUgc3lzdGVtIGZsaXAuICBJZiB0aGUgZGV0ZXJtaW5hbnRcbiAgICAvLyBpcyAtMSwgdGhlbiBuZWdhdGUgdGhlIG1hdHJpeCBhbmQgdGhlIHNjYWxpbmcgZmFjdG9ycy5cbiAgICB2ZWMzLmNyb3NzKHBkdW0zLCByb3dbMV0sIHJvd1syXSlcbiAgICBpZiAodmVjMy5kb3Qocm93WzBdLCBwZHVtMykgPCAwKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMzsgaSsrKSB7XG4gICAgICAgICAgICBzY2FsZVtpXSAqPSAtMTtcbiAgICAgICAgICAgIHJvd1tpXVswXSAqPSAtMVxuICAgICAgICAgICAgcm93W2ldWzFdICo9IC0xXG4gICAgICAgICAgICByb3dbaV1bMl0gKj0gLTFcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdywgZ2V0IHRoZSByb3RhdGlvbnMgb3V0XG4gICAgcXVhdGVybmlvblswXSA9IDAuNSAqIE1hdGguc3FydChNYXRoLm1heCgxICsgcm93WzBdWzBdIC0gcm93WzFdWzFdIC0gcm93WzJdWzJdLCAwKSlcbiAgICBxdWF0ZXJuaW9uWzFdID0gMC41ICogTWF0aC5zcXJ0KE1hdGgubWF4KDEgLSByb3dbMF1bMF0gKyByb3dbMV1bMV0gLSByb3dbMl1bMl0sIDApKVxuICAgIHF1YXRlcm5pb25bMl0gPSAwLjUgKiBNYXRoLnNxcnQoTWF0aC5tYXgoMSAtIHJvd1swXVswXSAtIHJvd1sxXVsxXSArIHJvd1syXVsyXSwgMCkpXG4gICAgcXVhdGVybmlvblszXSA9IDAuNSAqIE1hdGguc3FydChNYXRoLm1heCgxICsgcm93WzBdWzBdICsgcm93WzFdWzFdICsgcm93WzJdWzJdLCAwKSlcblxuICAgIGlmIChyb3dbMl1bMV0gPiByb3dbMV1bMl0pXG4gICAgICAgIHF1YXRlcm5pb25bMF0gPSAtcXVhdGVybmlvblswXVxuICAgIGlmIChyb3dbMF1bMl0gPiByb3dbMl1bMF0pXG4gICAgICAgIHF1YXRlcm5pb25bMV0gPSAtcXVhdGVybmlvblsxXVxuICAgIGlmIChyb3dbMV1bMF0gPiByb3dbMF1bMV0pXG4gICAgICAgIHF1YXRlcm5pb25bMl0gPSAtcXVhdGVybmlvblsyXVxuICAgIHJldHVybiB0cnVlXG59XG5cbi8vd2lsbCBiZSByZXBsYWNlZCBieSBnbC12ZWM0IGV2ZW50dWFsbHlcbmZ1bmN0aW9uIHZlYzRtdWx0TWF0NChvdXQsIGEsIG0pIHtcbiAgICB2YXIgeCA9IGFbMF0sIHkgPSBhWzFdLCB6ID0gYVsyXSwgdyA9IGFbM107XG4gICAgb3V0WzBdID0gbVswXSAqIHggKyBtWzRdICogeSArIG1bOF0gKiB6ICsgbVsxMl0gKiB3O1xuICAgIG91dFsxXSA9IG1bMV0gKiB4ICsgbVs1XSAqIHkgKyBtWzldICogeiArIG1bMTNdICogdztcbiAgICBvdXRbMl0gPSBtWzJdICogeCArIG1bNl0gKiB5ICsgbVsxMF0gKiB6ICsgbVsxNF0gKiB3O1xuICAgIG91dFszXSA9IG1bM10gKiB4ICsgbVs3XSAqIHkgKyBtWzExXSAqIHogKyBtWzE1XSAqIHc7XG4gICAgcmV0dXJuIG91dDtcbn1cblxuLy9nZXRzIHVwcGVyLWxlZnQgb2YgYSA0eDQgbWF0cml4IGludG8gYSAzeDMgb2YgdmVjdG9yc1xuZnVuY3Rpb24gbWF0M2Zyb200KG91dCwgbWF0NHg0KSB7XG4gICAgb3V0WzBdWzBdID0gbWF0NHg0WzBdXG4gICAgb3V0WzBdWzFdID0gbWF0NHg0WzFdXG4gICAgb3V0WzBdWzJdID0gbWF0NHg0WzJdXG4gICAgXG4gICAgb3V0WzFdWzBdID0gbWF0NHg0WzRdXG4gICAgb3V0WzFdWzFdID0gbWF0NHg0WzVdXG4gICAgb3V0WzFdWzJdID0gbWF0NHg0WzZdXG5cbiAgICBvdXRbMl1bMF0gPSBtYXQ0eDRbOF1cbiAgICBvdXRbMl1bMV0gPSBtYXQ0eDRbOV1cbiAgICBvdXRbMl1bMl0gPSBtYXQ0eDRbMTBdXG59XG5cbmZ1bmN0aW9uIGNvbWJpbmUob3V0LCBhLCBiLCBzY2FsZTEsIHNjYWxlMikge1xuICAgIG91dFswXSA9IGFbMF0gKiBzY2FsZTEgKyBiWzBdICogc2NhbGUyXG4gICAgb3V0WzFdID0gYVsxXSAqIHNjYWxlMSArIGJbMV0gKiBzY2FsZTJcbiAgICBvdXRbMl0gPSBhWzJdICogc2NhbGUxICsgYlsyXSAqIHNjYWxlMlxufVxufSx7XCIuL25vcm1hbGl6ZVwiOjQyOSxcImdsLW1hdDQvY2xvbmVcIjoyNTksXCJnbC1tYXQ0L2NyZWF0ZVwiOjI2MCxcImdsLW1hdDQvZGV0ZXJtaW5hbnRcIjoyNjEsXCJnbC1tYXQ0L2ludmVydFwiOjI2NSxcImdsLW1hdDQvdHJhbnNwb3NlXCI6Mjc2LFwiZ2wtdmVjMy9jcm9zc1wiOjMzNCxcImdsLXZlYzMvZG90XCI6MzM5LFwiZ2wtdmVjMy9sZW5ndGhcIjozNDksXCJnbC12ZWMzL25vcm1hbGl6ZVwiOjM1Nn1dLDQyOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG5vcm1hbGl6ZShvdXQsIG1hdCkge1xuICAgIHZhciBtNDQgPSBtYXRbMTVdXG4gICAgLy8gQ2Fubm90IG5vcm1hbGl6ZS5cbiAgICBpZiAobTQ0ID09PSAwKSBcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgdmFyIHNjYWxlID0gMSAvIG00NFxuICAgIGZvciAodmFyIGk9MDsgaTwxNjsgaSsrKVxuICAgICAgICBvdXRbaV0gPSBtYXRbaV0gKiBzY2FsZVxuICAgIHJldHVybiB0cnVlXG59XG59LHt9XSw0MzA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xudmFyIGxlcnAgPSBfZGVyZXFfKCdnbC12ZWMzL2xlcnAnKVxuXG52YXIgcmVjb21wb3NlID0gX2RlcmVxXygnbWF0NC1yZWNvbXBvc2UnKVxudmFyIGRlY29tcG9zZSA9IF9kZXJlcV8oJ21hdDQtZGVjb21wb3NlJylcbnZhciBkZXRlcm1pbmFudCA9IF9kZXJlcV8oJ2dsLW1hdDQvZGV0ZXJtaW5hbnQnKVxudmFyIHNsZXJwID0gX2RlcmVxXygncXVhdC1zbGVycCcpXG5cbnZhciBzdGF0ZTAgPSBzdGF0ZSgpXG52YXIgc3RhdGUxID0gc3RhdGUoKVxudmFyIHRtcCA9IHN0YXRlKClcblxubW9kdWxlLmV4cG9ydHMgPSBpbnRlcnBvbGF0ZVxuZnVuY3Rpb24gaW50ZXJwb2xhdGUob3V0LCBzdGFydCwgZW5kLCBhbHBoYSkge1xuICAgIGlmIChkZXRlcm1pbmFudChzdGFydCkgPT09IDAgfHwgZGV0ZXJtaW5hbnQoZW5kKSA9PT0gMClcbiAgICAgICAgcmV0dXJuIGZhbHNlXG5cbiAgICAvL2RlY29tcG9zZSB0aGUgc3RhcnQgYW5kIGVuZCBtYXRyaWNlcyBpbnRvIGluZGl2aWR1YWwgY29tcG9uZW50c1xuICAgIHZhciByMCA9IGRlY29tcG9zZShzdGFydCwgc3RhdGUwLnRyYW5zbGF0ZSwgc3RhdGUwLnNjYWxlLCBzdGF0ZTAuc2tldywgc3RhdGUwLnBlcnNwZWN0aXZlLCBzdGF0ZTAucXVhdGVybmlvbilcbiAgICB2YXIgcjEgPSBkZWNvbXBvc2UoZW5kLCBzdGF0ZTEudHJhbnNsYXRlLCBzdGF0ZTEuc2NhbGUsIHN0YXRlMS5za2V3LCBzdGF0ZTEucGVyc3BlY3RpdmUsIHN0YXRlMS5xdWF0ZXJuaW9uKVxuICAgIGlmICghcjAgfHwgIXIxKVxuICAgICAgICByZXR1cm4gZmFsc2UgICAgXG5cblxuICAgIC8vbm93IGxlcnAvc2xlcnAgdGhlIHN0YXJ0IGFuZCBlbmQgY29tcG9uZW50cyBpbnRvIGEgdGVtcG9yYXJ5ICAgICBsZXJwKHRtcHRyYW5zbGF0ZSwgc3RhdGUwLnRyYW5zbGF0ZSwgc3RhdGUxLnRyYW5zbGF0ZSwgYWxwaGEpXG4gICAgbGVycCh0bXAudHJhbnNsYXRlLCBzdGF0ZTAudHJhbnNsYXRlLCBzdGF0ZTEudHJhbnNsYXRlLCBhbHBoYSlcbiAgICBsZXJwKHRtcC5za2V3LCBzdGF0ZTAuc2tldywgc3RhdGUxLnNrZXcsIGFscGhhKVxuICAgIGxlcnAodG1wLnNjYWxlLCBzdGF0ZTAuc2NhbGUsIHN0YXRlMS5zY2FsZSwgYWxwaGEpXG4gICAgbGVycCh0bXAucGVyc3BlY3RpdmUsIHN0YXRlMC5wZXJzcGVjdGl2ZSwgc3RhdGUxLnBlcnNwZWN0aXZlLCBhbHBoYSlcbiAgICBzbGVycCh0bXAucXVhdGVybmlvbiwgc3RhdGUwLnF1YXRlcm5pb24sIHN0YXRlMS5xdWF0ZXJuaW9uLCBhbHBoYSlcblxuICAgIC8vYW5kIHJlY29tcG9zZSBpbnRvIG91ciAnb3V0JyBtYXRyaXhcbiAgICByZWNvbXBvc2Uob3V0LCB0bXAudHJhbnNsYXRlLCB0bXAuc2NhbGUsIHRtcC5za2V3LCB0bXAucGVyc3BlY3RpdmUsIHRtcC5xdWF0ZXJuaW9uKVxuICAgIHJldHVybiB0cnVlXG59XG5cbmZ1bmN0aW9uIHN0YXRlKCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHRyYW5zbGF0ZTogdmVjMygpLFxuICAgICAgICBzY2FsZTogdmVjMygxKSxcbiAgICAgICAgc2tldzogdmVjMygpLFxuICAgICAgICBwZXJzcGVjdGl2ZTogdmVjNCgpLFxuICAgICAgICBxdWF0ZXJuaW9uOiB2ZWM0KClcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHZlYzMobikge1xuICAgIHJldHVybiBbbnx8MCxufHwwLG58fDBdXG59XG5cbmZ1bmN0aW9uIHZlYzQoKSB7XG4gICAgcmV0dXJuIFswLDAsMCwxXVxufVxufSx7XCJnbC1tYXQ0L2RldGVybWluYW50XCI6MjYxLFwiZ2wtdmVjMy9sZXJwXCI6MzUwLFwibWF0NC1kZWNvbXBvc2VcIjo0MjgsXCJtYXQ0LXJlY29tcG9zZVwiOjQzMSxcInF1YXQtc2xlcnBcIjo0ODN9XSw0MzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLypcbklucHV0OiAgdHJhbnNsYXRpb24gOyBhIDMgY29tcG9uZW50IHZlY3RvclxuICAgICAgICBzY2FsZSAgICAgICA7IGEgMyBjb21wb25lbnQgdmVjdG9yXG4gICAgICAgIHNrZXcgICAgICAgIDsgc2tldyBmYWN0b3JzIFhZLFhaLFlaIHJlcHJlc2VudGVkIGFzIGEgMyBjb21wb25lbnQgdmVjdG9yXG4gICAgICAgIHBlcnNwZWN0aXZlIDsgYSA0IGNvbXBvbmVudCB2ZWN0b3JcbiAgICAgICAgcXVhdGVybmlvbiAgOyBhIDQgY29tcG9uZW50IHZlY3RvclxuT3V0cHV0OiBtYXRyaXggICAgICA7IGEgNHg0IG1hdHJpeFxuXG5Gcm9tOiBodHRwOi8vd3d3LnczLm9yZy9UUi9jc3MzLXRyYW5zZm9ybXMvI3JlY29tcG9zaW5nLXRvLWEtM2QtbWF0cml4XG4qL1xuXG52YXIgbWF0NCA9IHtcbiAgICBpZGVudGl0eTogX2RlcmVxXygnZ2wtbWF0NC9pZGVudGl0eScpLFxuICAgIHRyYW5zbGF0ZTogX2RlcmVxXygnZ2wtbWF0NC90cmFuc2xhdGUnKSxcbiAgICBtdWx0aXBseTogX2RlcmVxXygnZ2wtbWF0NC9tdWx0aXBseScpLFxuICAgIGNyZWF0ZTogX2RlcmVxXygnZ2wtbWF0NC9jcmVhdGUnKSxcbiAgICBzY2FsZTogX2RlcmVxXygnZ2wtbWF0NC9zY2FsZScpLFxuICAgIGZyb21Sb3RhdGlvblRyYW5zbGF0aW9uOiBfZGVyZXFfKCdnbC1tYXQ0L2Zyb21Sb3RhdGlvblRyYW5zbGF0aW9uJylcbn1cblxudmFyIHJvdGF0aW9uTWF0cml4ID0gbWF0NC5jcmVhdGUoKVxudmFyIHRlbXAgPSBtYXQ0LmNyZWF0ZSgpXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcmVjb21wb3NlTWF0NChtYXRyaXgsIHRyYW5zbGF0aW9uLCBzY2FsZSwgc2tldywgcGVyc3BlY3RpdmUsIHF1YXRlcm5pb24pIHtcbiAgICBtYXQ0LmlkZW50aXR5KG1hdHJpeClcblxuICAgIC8vYXBwbHkgdHJhbnNsYXRpb24gJiByb3RhdGlvblxuICAgIG1hdDQuZnJvbVJvdGF0aW9uVHJhbnNsYXRpb24obWF0cml4LCBxdWF0ZXJuaW9uLCB0cmFuc2xhdGlvbilcblxuICAgIC8vYXBwbHkgcGVyc3BlY3RpdmVcbiAgICBtYXRyaXhbM10gPSBwZXJzcGVjdGl2ZVswXVxuICAgIG1hdHJpeFs3XSA9IHBlcnNwZWN0aXZlWzFdXG4gICAgbWF0cml4WzExXSA9IHBlcnNwZWN0aXZlWzJdXG4gICAgbWF0cml4WzE1XSA9IHBlcnNwZWN0aXZlWzNdXG4gICAgICAgIFxuICAgIC8vIGFwcGx5IHNrZXdcbiAgICAvLyB0ZW1wIGlzIGEgaWRlbnRpdHkgNHg0IG1hdHJpeCBpbml0aWFsbHlcbiAgICBtYXQ0LmlkZW50aXR5KHRlbXApXG5cbiAgICBpZiAoc2tld1syXSAhPT0gMCkge1xuICAgICAgICB0ZW1wWzldID0gc2tld1syXVxuICAgICAgICBtYXQ0Lm11bHRpcGx5KG1hdHJpeCwgbWF0cml4LCB0ZW1wKVxuICAgIH1cblxuICAgIGlmIChza2V3WzFdICE9PSAwKSB7XG4gICAgICAgIHRlbXBbOV0gPSAwXG4gICAgICAgIHRlbXBbOF0gPSBza2V3WzFdXG4gICAgICAgIG1hdDQubXVsdGlwbHkobWF0cml4LCBtYXRyaXgsIHRlbXApXG4gICAgfVxuXG4gICAgaWYgKHNrZXdbMF0gIT09IDApIHtcbiAgICAgICAgdGVtcFs4XSA9IDBcbiAgICAgICAgdGVtcFs0XSA9IHNrZXdbMF1cbiAgICAgICAgbWF0NC5tdWx0aXBseShtYXRyaXgsIG1hdHJpeCwgdGVtcClcbiAgICB9XG5cbiAgICAvL2FwcGx5IHNjYWxlXG4gICAgbWF0NC5zY2FsZShtYXRyaXgsIG1hdHJpeCwgc2NhbGUpXG4gICAgcmV0dXJuIG1hdHJpeFxufVxufSx7XCJnbC1tYXQ0L2NyZWF0ZVwiOjI2MCxcImdsLW1hdDQvZnJvbVJvdGF0aW9uVHJhbnNsYXRpb25cIjoyNjMsXCJnbC1tYXQ0L2lkZW50aXR5XCI6MjY0LFwiZ2wtbWF0NC9tdWx0aXBseVwiOjI2NyxcImdsLW1hdDQvc2NhbGVcIjoyNzQsXCJnbC1tYXQ0L3RyYW5zbGF0ZVwiOjI3NX1dLDQzMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCc7XG5tb2R1bGUuZXhwb3J0cyA9IE1hdGgubG9nMiB8fCBmdW5jdGlvbiAoeCkge1xuXHRyZXR1cm4gTWF0aC5sb2coeCkgKiBNYXRoLkxPRzJFO1xufTtcblxufSx7fV0sNDMzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIGJzZWFyY2ggICA9IF9kZXJlcV8oJ2JpbmFyeS1zZWFyY2gtYm91bmRzJylcclxudmFyIG00aW50ZXJwICA9IF9kZXJlcV8oJ21hdDQtaW50ZXJwb2xhdGUnKVxyXG52YXIgaW52ZXJ0NDQgID0gX2RlcmVxXygnZ2wtbWF0NC9pbnZlcnQnKVxyXG52YXIgcm90YXRlWCAgID0gX2RlcmVxXygnZ2wtbWF0NC9yb3RhdGVYJylcclxudmFyIHJvdGF0ZVkgICA9IF9kZXJlcV8oJ2dsLW1hdDQvcm90YXRlWScpXHJcbnZhciByb3RhdGVaICAgPSBfZGVyZXFfKCdnbC1tYXQ0L3JvdGF0ZVonKVxyXG52YXIgbG9va0F0ICAgID0gX2RlcmVxXygnZ2wtbWF0NC9sb29rQXQnKVxyXG52YXIgdHJhbnNsYXRlID0gX2RlcmVxXygnZ2wtbWF0NC90cmFuc2xhdGUnKVxyXG52YXIgc2NhbGUgICAgID0gX2RlcmVxXygnZ2wtbWF0NC9zY2FsZScpXHJcbnZhciBub3JtYWxpemUgPSBfZGVyZXFfKCdnbC12ZWMzL25vcm1hbGl6ZScpXHJcblxyXG52YXIgREVGQVVMVF9DRU5URVIgPSBbMCwwLDBdXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZU1hdHJpeENhbWVyYUNvbnRyb2xsZXJcclxuXHJcbmZ1bmN0aW9uIE1hdHJpeENhbWVyYUNvbnRyb2xsZXIoaW5pdGlhbE1hdHJpeCkge1xyXG4gIHRoaXMuX2NvbXBvbmVudHMgICAgPSBpbml0aWFsTWF0cml4LnNsaWNlKClcclxuICB0aGlzLl90aW1lICAgICAgICAgID0gWzBdXHJcbiAgdGhpcy5wcmV2TWF0cml4ICAgICA9IGluaXRpYWxNYXRyaXguc2xpY2UoKVxyXG4gIHRoaXMubmV4dE1hdHJpeCAgICAgPSBpbml0aWFsTWF0cml4LnNsaWNlKClcclxuICB0aGlzLmNvbXB1dGVkTWF0cml4ID0gaW5pdGlhbE1hdHJpeC5zbGljZSgpXHJcbiAgdGhpcy5jb21wdXRlZEludmVyc2UgPSBpbml0aWFsTWF0cml4LnNsaWNlKClcclxuICB0aGlzLmNvbXB1dGVkRXllICAgID0gWzAsMCwwXVxyXG4gIHRoaXMuY29tcHV0ZWRVcCAgICAgPSBbMCwwLDBdXHJcbiAgdGhpcy5jb21wdXRlZENlbnRlciA9IFswLDAsMF1cclxuICB0aGlzLmNvbXB1dGVkUmFkaXVzID0gWzBdXHJcbiAgdGhpcy5fbGltaXRzICAgICAgICA9IFstSW5maW5pdHksIEluZmluaXR5XVxyXG59XHJcblxyXG52YXIgcHJvdG8gPSBNYXRyaXhDYW1lcmFDb250cm9sbGVyLnByb3RvdHlwZVxyXG5cclxucHJvdG8ucmVjYWxjTWF0cml4ID0gZnVuY3Rpb24odCkge1xyXG4gIHZhciB0aW1lID0gdGhpcy5fdGltZVxyXG4gIHZhciB0aWR4ID0gYnNlYXJjaC5sZSh0aW1lLCB0KVxyXG4gIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XHJcbiAgaWYodGlkeCA8IDApIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuICB2YXIgY29tcHMgPSB0aGlzLl9jb21wb25lbnRzXHJcbiAgaWYodGlkeCA9PT0gdGltZS5sZW5ndGgtMSkge1xyXG4gICAgdmFyIHB0ciA9IDE2KnRpZHhcclxuICAgIGZvcih2YXIgaT0wOyBpPDE2OyArK2kpIHtcclxuICAgICAgbWF0W2ldID0gY29tcHNbcHRyKytdXHJcbiAgICB9XHJcbiAgfSBlbHNlIHtcclxuICAgIHZhciBkdCA9ICh0aW1lW3RpZHgrMV0gLSB0aW1lW3RpZHhdKVxyXG4gICAgdmFyIHB0ciA9IDE2KnRpZHhcclxuICAgIHZhciBwcmV2ID0gdGhpcy5wcmV2TWF0cml4XHJcbiAgICB2YXIgYWxsRXF1YWwgPSB0cnVlXHJcbiAgICBmb3IodmFyIGk9MDsgaTwxNjsgKytpKSB7XHJcbiAgICAgIHByZXZbaV0gPSBjb21wc1twdHIrK11cclxuICAgIH1cclxuICAgIHZhciBuZXh0ID0gdGhpcy5uZXh0TWF0cml4XHJcbiAgICBmb3IodmFyIGk9MDsgaTwxNjsgKytpKSB7XHJcbiAgICAgIG5leHRbaV0gPSBjb21wc1twdHIrK11cclxuICAgICAgYWxsRXF1YWwgPSBhbGxFcXVhbCAmJiAocHJldltpXSA9PT0gbmV4dFtpXSlcclxuICAgIH1cclxuICAgIGlmKGR0IDwgMWUtNiB8fCBhbGxFcXVhbCkge1xyXG4gICAgICBmb3IodmFyIGk9MDsgaTwxNjsgKytpKSB7XHJcbiAgICAgICAgbWF0W2ldID0gcHJldltpXVxyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBtNGludGVycChtYXQsIHByZXYsIG5leHQsICh0IC0gdGltZVt0aWR4XSkvZHQpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB2YXIgdXAgPSB0aGlzLmNvbXB1dGVkVXBcclxuICB1cFswXSA9IG1hdFsxXVxyXG4gIHVwWzFdID0gbWF0WzVdXHJcbiAgdXBbMl0gPSBtYXRbOV1cclxuICBub3JtYWxpemUodXAsIHVwKVxyXG5cclxuICB2YXIgaW1hdCA9IHRoaXMuY29tcHV0ZWRJbnZlcnNlXHJcbiAgaW52ZXJ0NDQoaW1hdCwgbWF0KVxyXG4gIHZhciBleWUgPSB0aGlzLmNvbXB1dGVkRXllXHJcbiAgdmFyIHcgPSBpbWF0WzE1XVxyXG4gIGV5ZVswXSA9IGltYXRbMTJdL3dcclxuICBleWVbMV0gPSBpbWF0WzEzXS93XHJcbiAgZXllWzJdID0gaW1hdFsxNF0vd1xyXG5cclxuICB2YXIgY2VudGVyID0gdGhpcy5jb21wdXRlZENlbnRlclxyXG4gIHZhciByYWRpdXMgPSBNYXRoLmV4cCh0aGlzLmNvbXB1dGVkUmFkaXVzWzBdKVxyXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xyXG4gICAgY2VudGVyW2ldID0gZXllW2ldIC0gbWF0WzIrNCppXSAqIHJhZGl1c1xyXG4gIH1cclxufVxyXG5cclxucHJvdG8uaWRsZSA9IGZ1bmN0aW9uKHQpIHtcclxuICBpZih0IDwgdGhpcy5sYXN0VCgpKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcbiAgdmFyIG1jID0gdGhpcy5fY29tcG9uZW50c1xyXG4gIHZhciBwdHIgPSBtYy5sZW5ndGgtMTZcclxuICBmb3IodmFyIGk9MDsgaTwxNjsgKytpKSB7XHJcbiAgICBtYy5wdXNoKG1jW3B0cisrXSlcclxuICB9XHJcbiAgdGhpcy5fdGltZS5wdXNoKHQpXHJcbn1cclxuXHJcbnByb3RvLmZsdXNoID0gZnVuY3Rpb24odCkge1xyXG4gIHZhciBpZHggPSBic2VhcmNoLmd0KHRoaXMuX3RpbWUsIHQpIC0gMlxyXG4gIGlmKGlkeCA8IDApIHtcclxuICAgIHJldHVyblxyXG4gIH1cclxuICB0aGlzLl90aW1lLnNwbGljZSgwLCBpZHgpXHJcbiAgdGhpcy5fY29tcG9uZW50cy5zcGxpY2UoMCwgMTYqaWR4KVxyXG59XHJcblxyXG5wcm90by5sYXN0VCA9IGZ1bmN0aW9uKCkge1xyXG4gIHJldHVybiB0aGlzLl90aW1lW3RoaXMuX3RpbWUubGVuZ3RoLTFdXHJcbn1cclxuXHJcbnByb3RvLmxvb2tBdCA9IGZ1bmN0aW9uKHQsIGV5ZSwgY2VudGVyLCB1cCkge1xyXG4gIHRoaXMucmVjYWxjTWF0cml4KHQpXHJcbiAgZXllICAgID0gZXllIHx8IHRoaXMuY29tcHV0ZWRFeWVcclxuICBjZW50ZXIgPSBjZW50ZXIgfHwgREVGQVVMVF9DRU5URVJcclxuICB1cCAgICAgPSB1cCB8fCB0aGlzLmNvbXB1dGVkVXBcclxuICB0aGlzLnNldE1hdHJpeCh0LCBsb29rQXQodGhpcy5jb21wdXRlZE1hdHJpeCwgZXllLCBjZW50ZXIsIHVwKSlcclxuICB2YXIgZDIgPSAwLjBcclxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcclxuICAgIGQyICs9IE1hdGgucG93KGNlbnRlcltpXSAtIGV5ZVtpXSwgMilcclxuICB9XHJcbiAgZDIgPSBNYXRoLmxvZyhNYXRoLnNxcnQoZDIpKVxyXG4gIHRoaXMuY29tcHV0ZWRSYWRpdXNbMF0gPSBkMlxyXG59XHJcblxyXG5wcm90by5yb3RhdGUgPSBmdW5jdGlvbih0LCB5YXcsIHBpdGNoLCByb2xsKSB7XHJcbiAgdGhpcy5yZWNhbGNNYXRyaXgodClcclxuICB2YXIgbWF0ID0gdGhpcy5jb21wdXRlZEludmVyc2VcclxuICBpZih5YXcpICAgcm90YXRlWShtYXQsIG1hdCwgeWF3KVxyXG4gIGlmKHBpdGNoKSByb3RhdGVYKG1hdCwgbWF0LCBwaXRjaClcclxuICBpZihyb2xsKSAgcm90YXRlWihtYXQsIG1hdCwgcm9sbClcclxuICB0aGlzLnNldE1hdHJpeCh0LCBpbnZlcnQ0NCh0aGlzLmNvbXB1dGVkTWF0cml4LCBtYXQpKVxyXG59XHJcblxyXG52YXIgdHZlYyA9IFswLDAsMF1cclxuXHJcbnByb3RvLnBhbiA9IGZ1bmN0aW9uKHQsIGR4LCBkeSwgZHopIHtcclxuICB0dmVjWzBdID0gLShkeCB8fCAwLjApXHJcbiAgdHZlY1sxXSA9IC0oZHkgfHwgMC4wKVxyXG4gIHR2ZWNbMl0gPSAtKGR6IHx8IDAuMClcclxuICB0aGlzLnJlY2FsY01hdHJpeCh0KVxyXG4gIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkSW52ZXJzZVxyXG4gIHRyYW5zbGF0ZShtYXQsIG1hdCwgdHZlYylcclxuICB0aGlzLnNldE1hdHJpeCh0LCBpbnZlcnQ0NChtYXQsIG1hdCkpXHJcbn1cclxuXHJcbnByb3RvLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uKHQsIGR4LCBkeSwgZHopIHtcclxuICB0dmVjWzBdID0gZHggfHwgMC4wXHJcbiAgdHZlY1sxXSA9IGR5IHx8IDAuMFxyXG4gIHR2ZWNbMl0gPSBkeiB8fCAwLjBcclxuICB0aGlzLnJlY2FsY01hdHJpeCh0KVxyXG4gIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XHJcbiAgdHJhbnNsYXRlKG1hdCwgbWF0LCB0dmVjKVxyXG4gIHRoaXMuc2V0TWF0cml4KHQsIG1hdClcclxufVxyXG5cclxucHJvdG8uc2V0TWF0cml4ID0gZnVuY3Rpb24odCwgbWF0KSB7XHJcbiAgaWYodCA8IHRoaXMubGFzdFQoKSkge1xyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG4gIHRoaXMuX3RpbWUucHVzaCh0KVxyXG4gIGZvcih2YXIgaT0wOyBpPDE2OyArK2kpIHtcclxuICAgIHRoaXMuX2NvbXBvbmVudHMucHVzaChtYXRbaV0pXHJcbiAgfVxyXG59XHJcblxyXG5wcm90by5zZXREaXN0YW5jZSA9IGZ1bmN0aW9uKHQsIGQpIHtcclxuICB0aGlzLmNvbXB1dGVkUmFkaXVzWzBdID0gZFxyXG59XHJcblxyXG5wcm90by5zZXREaXN0YW5jZUxpbWl0cyA9IGZ1bmN0aW9uKGEsYikge1xyXG4gIHZhciBsaW0gPSB0aGlzLl9saW1pdHNcclxuICBsaW1bMF0gPSBhXHJcbiAgbGltWzFdID0gYlxyXG59XHJcblxyXG5wcm90by5nZXREaXN0YW5jZUxpbWl0cyA9IGZ1bmN0aW9uKG91dCkge1xyXG4gIHZhciBsaW0gPSB0aGlzLl9saW1pdHNcclxuICBpZihvdXQpIHtcclxuICAgIG91dFswXSA9IGxpbVswXVxyXG4gICAgb3V0WzFdID0gbGltWzFdXHJcbiAgICByZXR1cm4gb3V0XHJcbiAgfVxyXG4gIHJldHVybiBsaW1cclxufVxyXG5cclxuZnVuY3Rpb24gY3JlYXRlTWF0cml4Q2FtZXJhQ29udHJvbGxlcihvcHRpb25zKSB7XHJcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cclxuICB2YXIgbWF0cml4ID0gb3B0aW9ucy5tYXRyaXggfHwgXHJcbiAgICAgICAgICAgICAgWzEsMCwwLDAsXHJcbiAgICAgICAgICAgICAgIDAsMSwwLDAsXHJcbiAgICAgICAgICAgICAgIDAsMCwxLDAsXHJcbiAgICAgICAgICAgICAgIDAsMCwwLDFdXHJcbiAgcmV0dXJuIG5ldyBNYXRyaXhDYW1lcmFDb250cm9sbGVyKG1hdHJpeClcclxufVxyXG5cbn0se1wiYmluYXJ5LXNlYXJjaC1ib3VuZHNcIjo5MSxcImdsLW1hdDQvaW52ZXJ0XCI6MjY1LFwiZ2wtbWF0NC9sb29rQXRcIjoyNjYsXCJnbC1tYXQ0L3JvdGF0ZVhcIjoyNzEsXCJnbC1tYXQ0L3JvdGF0ZVlcIjoyNzIsXCJnbC1tYXQ0L3JvdGF0ZVpcIjoyNzMsXCJnbC1tYXQ0L3NjYWxlXCI6Mjc0LFwiZ2wtbWF0NC90cmFuc2xhdGVcIjoyNzUsXCJnbC12ZWMzL25vcm1hbGl6ZVwiOjM1NixcIm1hdDQtaW50ZXJwb2xhdGVcIjo0MzB9XSw0MzQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gbW9ub3RvbmVDb252ZXhIdWxsMkRcblxudmFyIG9yaWVudCA9IF9kZXJlcV8oJ3JvYnVzdC1vcmllbnRhdGlvbicpWzNdXG5cbmZ1bmN0aW9uIG1vbm90b25lQ29udmV4SHVsbDJEKHBvaW50cykge1xuICB2YXIgbiA9IHBvaW50cy5sZW5ndGhcblxuICBpZihuIDwgMykge1xuICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICAgIHJlc3VsdFtpXSA9IGlcbiAgICB9XG5cbiAgICBpZihuID09PSAyICYmXG4gICAgICAgcG9pbnRzWzBdWzBdID09PSBwb2ludHNbMV1bMF0gJiZcbiAgICAgICBwb2ludHNbMF1bMV0gPT09IHBvaW50c1sxXVsxXSkge1xuICAgICAgcmV0dXJuIFswXVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIC8vU29ydCBwb2ludCBpbmRpY2VzIGFsb25nIHgtYXhpc1xuICB2YXIgc29ydGVkID0gbmV3IEFycmF5KG4pXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHNvcnRlZFtpXSA9IGlcbiAgfVxuICBzb3J0ZWQuc29ydChmdW5jdGlvbihhLGIpIHtcbiAgICB2YXIgZCA9IHBvaW50c1thXVswXS1wb2ludHNbYl1bMF1cbiAgICBpZihkKSB7XG4gICAgICByZXR1cm4gZFxuICAgIH1cbiAgICByZXR1cm4gcG9pbnRzW2FdWzFdIC0gcG9pbnRzW2JdWzFdXG4gIH0pXG5cbiAgLy9Db25zdHJ1Y3QgdXBwZXIgYW5kIGxvd2VyIGh1bGxzXG4gIHZhciBsb3dlciA9IFtzb3J0ZWRbMF0sIHNvcnRlZFsxXV1cbiAgdmFyIHVwcGVyID0gW3NvcnRlZFswXSwgc29ydGVkWzFdXVxuXG4gIGZvcih2YXIgaT0yOyBpPG47ICsraSkge1xuICAgIHZhciBpZHggPSBzb3J0ZWRbaV1cbiAgICB2YXIgcCAgID0gcG9pbnRzW2lkeF1cblxuICAgIC8vSW5zZXJ0IGludG8gbG93ZXIgbGlzdFxuICAgIHZhciBtID0gbG93ZXIubGVuZ3RoXG4gICAgd2hpbGUobSA+IDEgJiYgb3JpZW50KFxuICAgICAgICBwb2ludHNbbG93ZXJbbS0yXV0sIFxuICAgICAgICBwb2ludHNbbG93ZXJbbS0xXV0sIFxuICAgICAgICBwKSA8PSAwKSB7XG4gICAgICBtIC09IDFcbiAgICAgIGxvd2VyLnBvcCgpXG4gICAgfVxuICAgIGxvd2VyLnB1c2goaWR4KVxuXG4gICAgLy9JbnNlcnQgaW50byB1cHBlciBsaXN0XG4gICAgbSA9IHVwcGVyLmxlbmd0aFxuICAgIHdoaWxlKG0gPiAxICYmIG9yaWVudChcbiAgICAgICAgcG9pbnRzW3VwcGVyW20tMl1dLCBcbiAgICAgICAgcG9pbnRzW3VwcGVyW20tMV1dLCBcbiAgICAgICAgcCkgPj0gMCkge1xuICAgICAgbSAtPSAxXG4gICAgICB1cHBlci5wb3AoKVxuICAgIH1cbiAgICB1cHBlci5wdXNoKGlkeClcbiAgfVxuXG4gIC8vTWVyZ2UgbGlzdHMgdG9nZXRoZXJcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSh1cHBlci5sZW5ndGggKyBsb3dlci5sZW5ndGggLSAyKVxuICB2YXIgcHRyICAgID0gMFxuICBmb3IodmFyIGk9MCwgbmw9bG93ZXIubGVuZ3RoOyBpPG5sOyArK2kpIHtcbiAgICByZXN1bHRbcHRyKytdID0gbG93ZXJbaV1cbiAgfVxuICBmb3IodmFyIGo9dXBwZXIubGVuZ3RoLTI7IGo+MDsgLS1qKSB7XG4gICAgcmVzdWx0W3B0cisrXSA9IHVwcGVyW2pdXG4gIH1cblxuICAvL1JldHVybiByZXN1bHRcbiAgcmV0dXJuIHJlc3VsdFxufVxufSx7XCJyb2J1c3Qtb3JpZW50YXRpb25cIjo1MTB9XSw0MzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gbW91c2VMaXN0ZW5cblxudmFyIG1vdXNlID0gX2RlcmVxXygnbW91c2UtZXZlbnQnKVxuXG5mdW5jdGlvbiBtb3VzZUxpc3RlbiAoZWxlbWVudCwgY2FsbGJhY2spIHtcbiAgaWYgKCFjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gZWxlbWVudFxuICAgIGVsZW1lbnQgPSB3aW5kb3dcbiAgfVxuXG4gIHZhciBidXR0b25TdGF0ZSA9IDBcbiAgdmFyIHggPSAwXG4gIHZhciB5ID0gMFxuICB2YXIgbW9kcyA9IHtcbiAgICBzaGlmdDogZmFsc2UsXG4gICAgYWx0OiBmYWxzZSxcbiAgICBjb250cm9sOiBmYWxzZSxcbiAgICBtZXRhOiBmYWxzZVxuICB9XG4gIHZhciBhdHRhY2hlZCA9IGZhbHNlXG5cbiAgZnVuY3Rpb24gdXBkYXRlTW9kcyAoZXYpIHtcbiAgICB2YXIgY2hhbmdlZCA9IGZhbHNlXG4gICAgaWYgKCdhbHRLZXknIGluIGV2KSB7XG4gICAgICBjaGFuZ2VkID0gY2hhbmdlZCB8fCBldi5hbHRLZXkgIT09IG1vZHMuYWx0XG4gICAgICBtb2RzLmFsdCA9ICEhZXYuYWx0S2V5XG4gICAgfVxuICAgIGlmICgnc2hpZnRLZXknIGluIGV2KSB7XG4gICAgICBjaGFuZ2VkID0gY2hhbmdlZCB8fCBldi5zaGlmdEtleSAhPT0gbW9kcy5zaGlmdFxuICAgICAgbW9kcy5zaGlmdCA9ICEhZXYuc2hpZnRLZXlcbiAgICB9XG4gICAgaWYgKCdjdHJsS2V5JyBpbiBldikge1xuICAgICAgY2hhbmdlZCA9IGNoYW5nZWQgfHwgZXYuY3RybEtleSAhPT0gbW9kcy5jb250cm9sXG4gICAgICBtb2RzLmNvbnRyb2wgPSAhIWV2LmN0cmxLZXlcbiAgICB9XG4gICAgaWYgKCdtZXRhS2V5JyBpbiBldikge1xuICAgICAgY2hhbmdlZCA9IGNoYW5nZWQgfHwgZXYubWV0YUtleSAhPT0gbW9kcy5tZXRhXG4gICAgICBtb2RzLm1ldGEgPSAhIWV2Lm1ldGFLZXlcbiAgICB9XG4gICAgcmV0dXJuIGNoYW5nZWRcbiAgfVxuXG4gIGZ1bmN0aW9uIGhhbmRsZUV2ZW50IChuZXh0QnV0dG9ucywgZXYpIHtcbiAgICB2YXIgbmV4dFggPSBtb3VzZS54KGV2KVxuICAgIHZhciBuZXh0WSA9IG1vdXNlLnkoZXYpXG4gICAgaWYgKCdidXR0b25zJyBpbiBldikge1xuICAgICAgbmV4dEJ1dHRvbnMgPSBldi5idXR0b25zIHwgMFxuICAgIH1cbiAgICBpZiAobmV4dEJ1dHRvbnMgIT09IGJ1dHRvblN0YXRlIHx8XG4gICAgICBuZXh0WCAhPT0geCB8fFxuICAgICAgbmV4dFkgIT09IHkgfHxcbiAgICAgIHVwZGF0ZU1vZHMoZXYpKSB7XG4gICAgICBidXR0b25TdGF0ZSA9IG5leHRCdXR0b25zIHwgMFxuICAgICAgeCA9IG5leHRYIHx8IDBcbiAgICAgIHkgPSBuZXh0WSB8fCAwXG4gICAgICBjYWxsYmFjayAmJiBjYWxsYmFjayhidXR0b25TdGF0ZSwgeCwgeSwgbW9kcylcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjbGVhclN0YXRlIChldikge1xuICAgIGhhbmRsZUV2ZW50KDAsIGV2KVxuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlQmx1ciAoKSB7XG4gICAgaWYgKGJ1dHRvblN0YXRlIHx8XG4gICAgICB4IHx8XG4gICAgICB5IHx8XG4gICAgICBtb2RzLnNoaWZ0IHx8XG4gICAgICBtb2RzLmFsdCB8fFxuICAgICAgbW9kcy5tZXRhIHx8XG4gICAgICBtb2RzLmNvbnRyb2wpIHtcbiAgICAgIHggPSB5ID0gMFxuICAgICAgYnV0dG9uU3RhdGUgPSAwXG4gICAgICBtb2RzLnNoaWZ0ID0gbW9kcy5hbHQgPSBtb2RzLmNvbnRyb2wgPSBtb2RzLm1ldGEgPSBmYWxzZVxuICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soMCwgMCwgMCwgbW9kcylcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBoYW5kbGVNb2RzIChldikge1xuICAgIGlmICh1cGRhdGVNb2RzKGV2KSkge1xuICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soYnV0dG9uU3RhdGUsIHgsIHksIG1vZHMpXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaGFuZGxlTW91c2VNb3ZlIChldikge1xuICAgIGlmIChtb3VzZS5idXR0b25zKGV2KSA9PT0gMCkge1xuICAgICAgaGFuZGxlRXZlbnQoMCwgZXYpXG4gICAgfSBlbHNlIHtcbiAgICAgIGhhbmRsZUV2ZW50KGJ1dHRvblN0YXRlLCBldilcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBoYW5kbGVNb3VzZURvd24gKGV2KSB7XG4gICAgaGFuZGxlRXZlbnQoYnV0dG9uU3RhdGUgfCBtb3VzZS5idXR0b25zKGV2KSwgZXYpXG4gIH1cblxuICBmdW5jdGlvbiBoYW5kbGVNb3VzZVVwIChldikge1xuICAgIGhhbmRsZUV2ZW50KGJ1dHRvblN0YXRlICYgfm1vdXNlLmJ1dHRvbnMoZXYpLCBldilcbiAgfVxuXG4gIGZ1bmN0aW9uIGF0dGFjaExpc3RlbmVycyAoKSB7XG4gICAgaWYgKGF0dGFjaGVkKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgYXR0YWNoZWQgPSB0cnVlXG5cbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIGhhbmRsZU1vdXNlTW92ZSlcblxuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgaGFuZGxlTW91c2VEb3duKVxuXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgaGFuZGxlTW91c2VVcClcblxuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VsZWF2ZScsIGNsZWFyU3RhdGUpXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgY2xlYXJTdGF0ZSlcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3V0JywgY2xlYXJTdGF0ZSlcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsIGNsZWFyU3RhdGUpXG5cbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCBoYW5kbGVCbHVyKVxuXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXl1cCcsIGhhbmRsZU1vZHMpXG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgaGFuZGxlTW9kcylcbiAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleXByZXNzJywgaGFuZGxlTW9kcylcblxuICAgIGlmIChlbGVtZW50ICE9PSB3aW5kb3cpIHtcbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdibHVyJywgaGFuZGxlQmx1cilcblxuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2tleXVwJywgaGFuZGxlTW9kcylcbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgaGFuZGxlTW9kcylcbiAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdrZXlwcmVzcycsIGhhbmRsZU1vZHMpXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZGV0YWNoTGlzdGVuZXJzICgpIHtcbiAgICBpZiAoIWF0dGFjaGVkKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgYXR0YWNoZWQgPSBmYWxzZVxuXG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBoYW5kbGVNb3VzZU1vdmUpXG5cbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIGhhbmRsZU1vdXNlRG93bilcblxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIGhhbmRsZU1vdXNlVXApXG5cbiAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCBjbGVhclN0YXRlKVxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VlbnRlcicsIGNsZWFyU3RhdGUpXG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW91dCcsIGNsZWFyU3RhdGUpXG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCBjbGVhclN0YXRlKVxuXG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdibHVyJywgaGFuZGxlQmx1cilcblxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5dXAnLCBoYW5kbGVNb2RzKVxuICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGhhbmRsZU1vZHMpXG4gICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlwcmVzcycsIGhhbmRsZU1vZHMpXG5cbiAgICBpZiAoZWxlbWVudCAhPT0gd2luZG93KSB7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignYmx1cicsIGhhbmRsZUJsdXIpXG5cbiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXl1cCcsIGhhbmRsZU1vZHMpXG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGhhbmRsZU1vZHMpXG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5cHJlc3MnLCBoYW5kbGVNb2RzKVxuICAgIH1cbiAgfVxuXG4gIC8vIEF0dGFjaCBsaXN0ZW5lcnNcbiAgYXR0YWNoTGlzdGVuZXJzKClcblxuICB2YXIgcmVzdWx0ID0ge1xuICAgIGVsZW1lbnQ6IGVsZW1lbnRcbiAgfVxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKHJlc3VsdCwge1xuICAgIGVuYWJsZWQ6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gYXR0YWNoZWQgfSxcbiAgICAgIHNldDogZnVuY3Rpb24gKGYpIHtcbiAgICAgICAgaWYgKGYpIHtcbiAgICAgICAgICBhdHRhY2hMaXN0ZW5lcnMoKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRldGFjaExpc3RlbmVycygpXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgfSxcbiAgICBidXR0b25zOiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGJ1dHRvblN0YXRlIH0sXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgfSxcbiAgICB4OiB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHggfSxcbiAgICAgIGVudW1lcmFibGU6IHRydWVcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4geSB9LFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZVxuICAgIH0sXG4gICAgbW9kczoge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBtb2RzIH0sXG4gICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgfVxuICB9KVxuXG4gIHJldHVybiByZXN1bHRcbn1cblxufSx7XCJtb3VzZS1ldmVudFwiOjQzN31dLDQzNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG52YXIgcm9vdFBvc2l0aW9uID0geyBsZWZ0OiAwLCB0b3A6IDAgfVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1vdXNlRXZlbnRPZmZzZXRcbmZ1bmN0aW9uIG1vdXNlRXZlbnRPZmZzZXQgKGV2LCB0YXJnZXQsIG91dCkge1xuICB0YXJnZXQgPSB0YXJnZXQgfHwgZXYuY3VycmVudFRhcmdldCB8fCBldi5zcmNFbGVtZW50XG4gIGlmICghQXJyYXkuaXNBcnJheShvdXQpKSB7XG4gICAgb3V0ID0gWyAwLCAwIF1cbiAgfVxuICB2YXIgY3ggPSBldi5jbGllbnRYIHx8IDBcbiAgdmFyIGN5ID0gZXYuY2xpZW50WSB8fCAwXG4gIHZhciByZWN0ID0gZ2V0Qm91bmRpbmdDbGllbnRPZmZzZXQodGFyZ2V0KVxuICBvdXRbMF0gPSBjeCAtIHJlY3QubGVmdFxuICBvdXRbMV0gPSBjeSAtIHJlY3QudG9wXG4gIHJldHVybiBvdXRcbn1cblxuZnVuY3Rpb24gZ2V0Qm91bmRpbmdDbGllbnRPZmZzZXQgKGVsZW1lbnQpIHtcbiAgaWYgKGVsZW1lbnQgPT09IHdpbmRvdyB8fFxuICAgICAgZWxlbWVudCA9PT0gZG9jdW1lbnQgfHxcbiAgICAgIGVsZW1lbnQgPT09IGRvY3VtZW50LmJvZHkpIHtcbiAgICByZXR1cm4gcm9vdFBvc2l0aW9uXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgfVxufVxuXG59LHt9XSw0Mzc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbmZ1bmN0aW9uIG1vdXNlQnV0dG9ucyhldikge1xuICBpZih0eXBlb2YgZXYgPT09ICdvYmplY3QnKSB7XG4gICAgaWYoJ2J1dHRvbnMnIGluIGV2KSB7XG4gICAgICByZXR1cm4gZXYuYnV0dG9uc1xuICAgIH0gZWxzZSBpZignd2hpY2gnIGluIGV2KSB7XG4gICAgICB2YXIgYiA9IGV2LndoaWNoXG4gICAgICBpZihiID09PSAyKSB7XG4gICAgICAgIHJldHVybiA0XG4gICAgICB9IGVsc2UgaWYoYiA9PT0gMykge1xuICAgICAgICByZXR1cm4gMlxuICAgICAgfSBlbHNlIGlmKGIgPiAwKSB7XG4gICAgICAgIHJldHVybiAxPDwoYi0xKVxuICAgICAgfVxuICAgIH0gZWxzZSBpZignYnV0dG9uJyBpbiBldikge1xuICAgICAgdmFyIGIgPSBldi5idXR0b25cbiAgICAgIGlmKGIgPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIDRcbiAgICAgIH0gZWxzZSBpZihiID09PSAyKSB7XG4gICAgICAgIHJldHVybiAyXG4gICAgICB9IGVsc2UgaWYoYiA+PSAwKSB7XG4gICAgICAgIHJldHVybiAxPDxiXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiAwXG59XG5leHBvcnRzLmJ1dHRvbnMgPSBtb3VzZUJ1dHRvbnNcblxuZnVuY3Rpb24gbW91c2VFbGVtZW50KGV2KSB7XG4gIHJldHVybiBldi50YXJnZXQgfHwgZXYuc3JjRWxlbWVudCB8fCB3aW5kb3dcbn1cbmV4cG9ydHMuZWxlbWVudCA9IG1vdXNlRWxlbWVudFxuXG5mdW5jdGlvbiBtb3VzZVJlbGF0aXZlWChldikge1xuICBpZih0eXBlb2YgZXYgPT09ICdvYmplY3QnKSB7XG4gICAgaWYoJ29mZnNldFgnIGluIGV2KSB7XG4gICAgICByZXR1cm4gZXYub2Zmc2V0WFxuICAgIH1cbiAgICB2YXIgdGFyZ2V0ID0gbW91c2VFbGVtZW50KGV2KVxuICAgIHZhciBib3VuZHMgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClcbiAgICByZXR1cm4gZXYuY2xpZW50WCAtIGJvdW5kcy5sZWZ0XG4gIH1cbiAgcmV0dXJuIDBcbn1cbmV4cG9ydHMueCA9IG1vdXNlUmVsYXRpdmVYXG5cbmZ1bmN0aW9uIG1vdXNlUmVsYXRpdmVZKGV2KSB7XG4gIGlmKHR5cGVvZiBldiA9PT0gJ29iamVjdCcpIHtcbiAgICBpZignb2Zmc2V0WScgaW4gZXYpIHtcbiAgICAgIHJldHVybiBldi5vZmZzZXRZXG4gICAgfVxuICAgIHZhciB0YXJnZXQgPSBtb3VzZUVsZW1lbnQoZXYpXG4gICAgdmFyIGJvdW5kcyA9IHRhcmdldC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICAgIHJldHVybiBldi5jbGllbnRZIC0gYm91bmRzLnRvcFxuICB9XG4gIHJldHVybiAwXG59XG5leHBvcnRzLnkgPSBtb3VzZVJlbGF0aXZlWVxuXG59LHt9XSw0Mzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciB0b1BYID0gX2RlcmVxXygndG8tcHgnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1vdXNlV2hlZWxMaXN0ZW5cblxuZnVuY3Rpb24gbW91c2VXaGVlbExpc3RlbihlbGVtZW50LCBjYWxsYmFjaywgbm9TY3JvbGwpIHtcbiAgaWYodHlwZW9mIGVsZW1lbnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICBub1Njcm9sbCA9ICEhY2FsbGJhY2tcbiAgICBjYWxsYmFjayA9IGVsZW1lbnRcbiAgICBlbGVtZW50ID0gd2luZG93XG4gIH1cbiAgdmFyIGxpbmVIZWlnaHQgPSB0b1BYKCdleCcsIGVsZW1lbnQpXG4gIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uKGV2KSB7XG4gICAgaWYobm9TY3JvbGwpIHtcbiAgICAgIGV2LnByZXZlbnREZWZhdWx0KClcbiAgICB9XG4gICAgdmFyIGR4ID0gZXYuZGVsdGFYIHx8IDBcbiAgICB2YXIgZHkgPSBldi5kZWx0YVkgfHwgMFxuICAgIHZhciBkeiA9IGV2LmRlbHRhWiB8fCAwXG4gICAgdmFyIG1vZGUgPSBldi5kZWx0YU1vZGVcbiAgICB2YXIgc2NhbGUgPSAxXG4gICAgc3dpdGNoKG1vZGUpIHtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgc2NhbGUgPSBsaW5lSGVpZ2h0XG4gICAgICBicmVha1xuICAgICAgY2FzZSAyOlxuICAgICAgICBzY2FsZSA9IHdpbmRvdy5pbm5lckhlaWdodFxuICAgICAgYnJlYWtcbiAgICB9XG4gICAgZHggKj0gc2NhbGVcbiAgICBkeSAqPSBzY2FsZVxuICAgIGR6ICo9IHNjYWxlXG4gICAgaWYoZHggfHwgZHkgfHwgZHopIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayhkeCwgZHksIGR6LCBldilcbiAgICB9XG4gIH1cbiAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd3aGVlbCcsIGxpc3RlbmVyKVxuICByZXR1cm4gbGlzdGVuZXJcbn1cblxufSx7XCJ0by1weFwiOjUzOX1dLDQzOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG52YXIgcG9vbCA9IF9kZXJlcV8oXCJ0eXBlZGFycmF5LXBvb2xcIilcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTdXJmYWNlRXh0cmFjdG9yXG5cbi8vSGVscGVyIG1hY3Jvc1xuZnVuY3Rpb24gYXJyYXkoaSkge1xuICByZXR1cm4gXCJhXCIgKyBpXG59XG5mdW5jdGlvbiBkYXRhKGkpIHtcbiAgcmV0dXJuIFwiZFwiICsgaVxufVxuZnVuY3Rpb24gY3ViZShpLGJpdG1hc2spIHtcbiAgcmV0dXJuIFwiY1wiICsgaSArIFwiX1wiICsgYml0bWFza1xufVxuZnVuY3Rpb24gc2hhcGUoaSkge1xuICByZXR1cm4gXCJzXCIgKyBpXG59XG5mdW5jdGlvbiBzdHJpZGUoaSxqKSB7XG4gIHJldHVybiBcInRcIiArIGkgKyBcIl9cIiArIGpcbn1cbmZ1bmN0aW9uIG9mZnNldChpKSB7XG4gIHJldHVybiBcIm9cIiArIGlcbn1cbmZ1bmN0aW9uIHNjYWxhcihpKSB7XG4gIHJldHVybiBcInhcIiArIGlcbn1cbmZ1bmN0aW9uIHBvaW50ZXIoaSkge1xuICByZXR1cm4gXCJwXCIgKyBpXG59XG5mdW5jdGlvbiBkZWx0YShpLGJpdG1hc2spIHtcbiAgcmV0dXJuIFwiZFwiICsgaSArIFwiX1wiICsgYml0bWFza1xufVxuZnVuY3Rpb24gaW5kZXgoaSkge1xuICByZXR1cm4gXCJpXCIgKyBpXG59XG5mdW5jdGlvbiBzdGVwKGksaikge1xuICByZXR1cm4gXCJ1XCIgKyBpICsgXCJfXCIgKyBqXG59XG5mdW5jdGlvbiBwY3ViZShiaXRtYXNrKSB7XG4gIHJldHVybiBcImJcIiArIGJpdG1hc2tcbn1cbmZ1bmN0aW9uIHFjdWJlKGJpdG1hc2spIHtcbiAgcmV0dXJuIFwieVwiICsgYml0bWFza1xufVxuZnVuY3Rpb24gcGRlbHRhKGJpdG1hc2spIHtcbiAgcmV0dXJuIFwiZVwiICsgYml0bWFza1xufVxuZnVuY3Rpb24gdmVydChpKSB7XG4gIHJldHVybiBcInZcIiArIGlcbn1cbnZhciBWRVJURVhfSURTID0gXCJWXCJcbnZhciBQSEFTRVMgPSBcIlBcIlxudmFyIFZFUlRFWF9DT1VOVCA9IFwiTlwiXG52YXIgUE9PTF9TSVpFID0gXCJRXCJcbnZhciBQT0lOVEVSID0gXCJYXCJcbnZhciBURU1QT1JBUlkgPSBcIlRcIlxuXG5mdW5jdGlvbiBwZXJtQml0bWFzayhkaW1lbnNpb24sIG1hc2ssIG9yZGVyKSB7XG4gIHZhciByID0gMFxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGlmKG1hc2sgJiAoMTw8aSkpIHtcbiAgICAgIHIgfD0gKDE8PG9yZGVyW2ldKVxuICAgIH1cbiAgfVxuICByZXR1cm4gclxufVxuXG4vL0dlbmVyYXRlcyB0aGUgc3VyZmFjZSBwcm9jZWR1cmVcbmZ1bmN0aW9uIGNvbXBpbGVTdXJmYWNlUHJvY2VkdXJlKHZlcnRleEZ1bmMsIGZhY2VGdW5jLCBwaGFzZUZ1bmMsIHNjYWxhckFyZ3MsIG9yZGVyLCB0eXBlc2lnKSB7XG4gIHZhciBhcnJheUFyZ3MgPSB0eXBlc2lnLmxlbmd0aFxuICB2YXIgZGltZW5zaW9uID0gb3JkZXIubGVuZ3RoXG5cbiAgaWYoZGltZW5zaW9uIDwgMikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIm5kYXJyYXktZXh0cmFjdC1jb250b3VyOiBEaW1lbnNpb24gbXVzdCBiZSBhdCBsZWFzdCAyXCIpXG4gIH1cblxuICB2YXIgZnVuY05hbWUgPSBcImV4dHJhY3RDb250b3VyXCIgKyBvcmRlci5qb2luKFwiX1wiKVxuICB2YXIgY29kZSA9IFtdXG4gIHZhciB2YXJzID0gW11cbiAgdmFyIGFyZ3MgPSBbXVxuXG4gIC8vQXNzZW1ibGUgYXJndW1lbnRzXG4gIGZvcih2YXIgaT0wOyBpPGFycmF5QXJnczsgKytpKSB7XG4gICAgYXJncy5wdXNoKGFycmF5KGkpKSAgXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8c2NhbGFyQXJnczsgKytpKSB7XG4gICAgYXJncy5wdXNoKHNjYWxhcihpKSlcbiAgfVxuXG4gIC8vU2hhcGVcbiAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICB2YXJzLnB1c2goc2hhcGUoaSkgKyBcIj1cIiArIGFycmF5KDApICsgXCIuc2hhcGVbXCIgKyBpICsgXCJdfDBcIilcbiAgfVxuICAvL0RhdGEsIHN0cmlkZSwgb2Zmc2V0IHBvaW50ZXJzXG4gIGZvcih2YXIgaT0wOyBpPGFycmF5QXJnczsgKytpKSB7XG4gICAgdmFycy5wdXNoKGRhdGEoaSkgKyBcIj1cIiArIGFycmF5KGkpICsgXCIuZGF0YVwiLFxuICAgICAgICAgICAgICBvZmZzZXQoaSkgKyBcIj1cIiArIGFycmF5KGkpICsgXCIub2Zmc2V0fDBcIilcbiAgICBmb3IodmFyIGo9MDsgajxkaW1lbnNpb247ICsraikge1xuICAgICAgdmFycy5wdXNoKHN0cmlkZShpLGopICsgXCI9XCIgKyBhcnJheShpKSArIFwiLnN0cmlkZVtcIiArIGogKyBcIl18MFwiKVxuICAgIH1cbiAgfVxuICAvL1BvaW50ZXIsIGRlbHRhIGFuZCBjdWJlIHZhcmlhYmxlc1xuICBmb3IodmFyIGk9MDsgaTxhcnJheUFyZ3M7ICsraSkge1xuICAgIHZhcnMucHVzaChwb2ludGVyKGkpICsgXCI9XCIgKyBvZmZzZXQoaSkpXG4gICAgdmFycy5wdXNoKGN1YmUoaSwwKSlcbiAgICBmb3IodmFyIGo9MTsgajwoMTw8ZGltZW5zaW9uKTsgKytqKSB7XG4gICAgICB2YXIgcHRyU3RyID0gW11cbiAgICAgIGZvcih2YXIgaz0wOyBrPGRpbWVuc2lvbjsgKytrKSB7XG4gICAgICAgIGlmKGogJiAoMTw8aykpIHtcbiAgICAgICAgICBwdHJTdHIucHVzaChcIi1cIiArIHN0cmlkZShpLGspKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB2YXJzLnB1c2goZGVsdGEoaSxqKSArIFwiPShcIiArIHB0clN0ci5qb2luKFwiXCIpICsgXCIpfDBcIilcbiAgICAgIHZhcnMucHVzaChjdWJlKGksaikgKyBcIj0wXCIpXG4gICAgfVxuICB9XG4gIC8vQ3JlYXRlIHN0ZXAgdmFyaWFibGVzXG4gIGZvcih2YXIgaT0wOyBpPGFycmF5QXJnczsgKytpKSB7XG4gICAgZm9yKHZhciBqPTA7IGo8ZGltZW5zaW9uOyArK2opIHtcbiAgICAgIHZhciBzdGVwVmFsID0gWyBzdHJpZGUoaSxvcmRlcltqXSkgXVxuICAgICAgaWYoaiA+IDApIHtcbiAgICAgICAgc3RlcFZhbC5wdXNoKHN0cmlkZShpLCBvcmRlcltqLTFdKSArIFwiKlwiICsgc2hhcGUob3JkZXJbai0xXSkgKVxuICAgICAgfVxuICAgICAgdmFycy5wdXNoKHN0ZXAoaSxvcmRlcltqXSkgKyBcIj0oXCIgKyBzdGVwVmFsLmpvaW4oXCItXCIpICsgXCIpfDBcIilcbiAgICB9XG4gIH1cbiAgLy9DcmVhdGUgaW5kZXggdmFyaWFibGVzXG4gIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgdmFycy5wdXNoKGluZGV4KGkpICsgXCI9MFwiKVxuICB9XG4gIC8vVmVydGV4IGNvdW50XG4gIHZhcnMucHVzaChWRVJURVhfQ09VTlQgKyBcIj0wXCIpXG4gIC8vQ29tcHV0ZSBwb29sIHNpemUsIGluaXRpYWxpemUgcG9vbCBzdGVwXG4gIHZhciBzaXplVmFyaWFibGUgPSBbXCIyXCJdXG4gIGZvcih2YXIgaT1kaW1lbnNpb24tMjsgaT49MDsgLS1pKSB7XG4gICAgc2l6ZVZhcmlhYmxlLnB1c2goc2hhcGUob3JkZXJbaV0pKVxuICB9XG4gIC8vUHJldmlvdXMgcGhhc2VzIGFuZCB2ZXJ0ZXhfaWRzXG4gIHZhcnMucHVzaChQT09MX1NJWkUgKyBcIj0oXCIgKyBzaXplVmFyaWFibGUuam9pbihcIipcIikgKyBcIil8MFwiLFxuICAgICAgICAgICAgUEhBU0VTICsgXCI9bWFsbG9jVWludDMyKFwiICsgUE9PTF9TSVpFICsgXCIpXCIsXG4gICAgICAgICAgICBWRVJURVhfSURTICsgXCI9bWFsbG9jVWludDMyKFwiICsgUE9PTF9TSVpFICsgXCIpXCIsXG4gICAgICAgICAgICBQT0lOVEVSICsgXCI9MFwiKVxuICAvL0NyZWF0ZSBjdWJlIHZhcmlhYmxlcyBmb3IgcGhhc2VzXG4gIHZhcnMucHVzaChwY3ViZSgwKSArIFwiPTBcIilcbiAgZm9yKHZhciBqPTE7IGo8KDE8PGRpbWVuc2lvbik7ICsraikge1xuICAgIHZhciBjdWJlRGVsdGEgPSBbXVxuICAgIHZhciBjdWJlU3RlcCA9IFsgXVxuICAgIGZvcih2YXIgaz0wOyBrPGRpbWVuc2lvbjsgKytrKSB7XG4gICAgICBpZihqICYgKDE8PGspKSB7XG4gICAgICAgIGlmKGN1YmVTdGVwLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGN1YmVEZWx0YS5wdXNoKFwiMVwiKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGN1YmVEZWx0YS51bnNoaWZ0KGN1YmVTdGVwLmpvaW4oXCIqXCIpKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjdWJlU3RlcC5wdXNoKHNoYXBlKG9yZGVyW2tdKSlcbiAgICB9XG4gICAgdmFyIHNpZ25GbGFnID0gXCJcIlxuICAgIGlmKGN1YmVEZWx0YVswXS5pbmRleE9mKHNoYXBlKG9yZGVyW2RpbWVuc2lvbi0yXSkpIDwgMCkge1xuICAgICAgc2lnbkZsYWcgPSBcIi1cIlxuICAgIH1cbiAgICB2YXIganBlcm0gPSBwZXJtQml0bWFzayhkaW1lbnNpb24sIGosIG9yZGVyKVxuICAgIHZhcnMucHVzaChwZGVsdGEoanBlcm0pICsgXCI9KC1cIiArIGN1YmVEZWx0YS5qb2luKFwiLVwiKSArIFwiKXwwXCIsXG4gICAgICAgICAgICAgIHFjdWJlKGpwZXJtKSArIFwiPShcIiArIHNpZ25GbGFnICsgY3ViZURlbHRhLmpvaW4oXCItXCIpICsgXCIpfDBcIixcbiAgICAgICAgICAgICAgcGN1YmUoanBlcm0pICsgXCI9MFwiKVxuICB9XG4gIHZhcnMucHVzaCh2ZXJ0KDApICsgXCI9MFwiLCBURU1QT1JBUlkgKyBcIj0wXCIpXG5cbiAgZnVuY3Rpb24gZm9yTG9vcEJlZ2luKGksIHN0YXJ0KSB7XG4gICAgY29kZS5wdXNoKFwiZm9yKFwiLCBpbmRleChvcmRlcltpXSksIFwiPVwiLCBzdGFydCwgXCI7XCIsXG4gICAgICBpbmRleChvcmRlcltpXSksIFwiPFwiLCBzaGFwZShvcmRlcltpXSksIFwiO1wiLFxuICAgICAgXCIrK1wiLCBpbmRleChvcmRlcltpXSksIFwiKXtcIilcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvckxvb3BFbmQoaSkge1xuICAgIGZvcih2YXIgaj0wOyBqPGFycmF5QXJnczsgKytqKSB7XG4gICAgICBjb2RlLnB1c2gocG9pbnRlcihqKSwgXCIrPVwiLCBzdGVwKGosb3JkZXJbaV0pLCBcIjtcIilcbiAgICB9XG4gICAgY29kZS5wdXNoKFwifVwiKVxuICB9XG5cbiAgZnVuY3Rpb24gZmlsbEVtcHR5U2xpY2Uoaykge1xuICAgIGZvcih2YXIgaT1rLTE7IGk+PTA7IC0taSkge1xuICAgICAgZm9yTG9vcEJlZ2luKGksIDApIFxuICAgIH1cbiAgICB2YXIgcGhhc2VGdW5jQXJncyA9IFtdXG4gICAgZm9yKHZhciBpPTA7IGk8YXJyYXlBcmdzOyArK2kpIHtcbiAgICAgIGlmKHR5cGVzaWdbaV0pIHtcbiAgICAgICAgcGhhc2VGdW5jQXJncy5wdXNoKGRhdGEoaSkgKyBcIi5nZXQoXCIgKyBwb2ludGVyKGkpICsgXCIpXCIpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwaGFzZUZ1bmNBcmdzLnB1c2goZGF0YShpKSArIFwiW1wiICsgcG9pbnRlcihpKSArIFwiXVwiKVxuICAgICAgfVxuICAgIH1cbiAgICBmb3IodmFyIGk9MDsgaTxzY2FsYXJBcmdzOyArK2kpIHtcbiAgICAgIHBoYXNlRnVuY0FyZ3MucHVzaChzY2FsYXIoaSkpXG4gICAgfVxuICAgIGNvZGUucHVzaChQSEFTRVMsIFwiW1wiLCBQT0lOVEVSLCBcIisrXT1waGFzZShcIiwgcGhhc2VGdW5jQXJncy5qb2luKCksIFwiKTtcIilcbiAgICBmb3IodmFyIGk9MDsgaTxrOyArK2kpIHtcbiAgICAgIGZvckxvb3BFbmQoaSlcbiAgICB9XG4gICAgZm9yKHZhciBqPTA7IGo8YXJyYXlBcmdzOyArK2opIHtcbiAgICAgIGNvZGUucHVzaChwb2ludGVyKGopLCBcIis9XCIsIHN0ZXAoaixvcmRlcltrXSksIFwiO1wiKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHByb2Nlc3NHcmlkQ2VsbChtYXNrKSB7XG4gICAgLy9SZWFkIGluIGxvY2FsIGRhdGFcbiAgICBmb3IodmFyIGk9MDsgaTxhcnJheUFyZ3M7ICsraSkge1xuICAgICAgaWYodHlwZXNpZ1tpXSkge1xuICAgICAgICBjb2RlLnB1c2goY3ViZShpLDApLCBcIj1cIiwgZGF0YShpKSwgXCIuZ2V0KFwiLCBwb2ludGVyKGkpLCBcIik7XCIpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2RlLnB1c2goY3ViZShpLDApLCBcIj1cIiwgZGF0YShpKSwgXCJbXCIsIHBvaW50ZXIoaSksIFwiXTtcIilcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvL1JlYWQgaW4gcGhhc2VcbiAgICB2YXIgcGhhc2VGdW5jQXJncyA9IFtdXG4gICAgZm9yKHZhciBpPTA7IGk8YXJyYXlBcmdzOyArK2kpIHtcbiAgICAgIHBoYXNlRnVuY0FyZ3MucHVzaChjdWJlKGksMCkpXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPHNjYWxhckFyZ3M7ICsraSkge1xuICAgICAgcGhhc2VGdW5jQXJncy5wdXNoKHNjYWxhcihpKSlcbiAgICB9XG4gICAgXG4gICAgY29kZS5wdXNoKHBjdWJlKDApLCBcIj1cIiwgUEhBU0VTLCBcIltcIiwgUE9JTlRFUiwgXCJdPXBoYXNlKFwiLCBwaGFzZUZ1bmNBcmdzLmpvaW4oKSwgXCIpO1wiKVxuICAgIFxuICAgIC8vUmVhZCBpbiBvdGhlciBjdWJlIGRhdGFcbiAgICBmb3IodmFyIGo9MTsgajwoMTw8ZGltZW5zaW9uKTsgKytqKSB7XG4gICAgICBjb2RlLnB1c2gocGN1YmUoaiksIFwiPVwiLCBQSEFTRVMsIFwiW1wiLCBQT0lOVEVSLCBcIitcIiwgcGRlbHRhKGopLCBcIl07XCIpXG4gICAgfVxuXG4gICAgLy9DaGVjayBmb3IgYm91bmRhcnkgY3Jvc3NpbmdcbiAgICB2YXIgdmVydGV4UHJlZGljYXRlID0gW11cbiAgICBmb3IodmFyIGo9MTsgajwoMTw8ZGltZW5zaW9uKTsgKytqKSB7XG4gICAgICB2ZXJ0ZXhQcmVkaWNhdGUucHVzaChcIihcIiArIHBjdWJlKDApICsgXCIhPT1cIiArIHBjdWJlKGopICsgXCIpXCIpXG4gICAgfVxuICAgIGNvZGUucHVzaChcImlmKFwiLCB2ZXJ0ZXhQcmVkaWNhdGUuam9pbihcInx8XCIpLCBcIil7XCIpXG5cbiAgICAvL1JlYWQgaW4gYm91bmRhcnkgZGF0YVxuICAgIHZhciB2ZXJ0ZXhBcmdzID0gW11cbiAgICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgICAgdmVydGV4QXJncy5wdXNoKGluZGV4KGkpKVxuICAgIH1cbiAgICBmb3IodmFyIGk9MDsgaTxhcnJheUFyZ3M7ICsraSkge1xuICAgICAgdmVydGV4QXJncy5wdXNoKGN1YmUoaSwwKSlcbiAgICAgIGZvcih2YXIgaj0xOyBqPCgxPDxkaW1lbnNpb24pOyArK2opIHtcbiAgICAgICAgaWYodHlwZXNpZ1tpXSkge1xuICAgICAgICAgIGNvZGUucHVzaChjdWJlKGksaiksIFwiPVwiLCBkYXRhKGkpLCBcIi5nZXQoXCIsIHBvaW50ZXIoaSksIFwiK1wiLCBkZWx0YShpLGopLCBcIik7XCIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29kZS5wdXNoKGN1YmUoaSxqKSwgXCI9XCIsIGRhdGEoaSksIFwiW1wiLCBwb2ludGVyKGkpLCBcIitcIiwgZGVsdGEoaSxqKSwgXCJdO1wiKVxuICAgICAgICB9XG4gICAgICAgIHZlcnRleEFyZ3MucHVzaChjdWJlKGksaikpXG4gICAgICB9XG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPCgxPDxkaW1lbnNpb24pOyArK2kpIHtcbiAgICAgIHZlcnRleEFyZ3MucHVzaChwY3ViZShpKSlcbiAgICB9XG4gICAgZm9yKHZhciBpPTA7IGk8c2NhbGFyQXJnczsgKytpKSB7XG4gICAgICB2ZXJ0ZXhBcmdzLnB1c2goc2NhbGFyKGkpKVxuICAgIH1cblxuICAgIC8vR2VuZXJhdGUgdmVydGV4XG4gICAgY29kZS5wdXNoKFwidmVydGV4KFwiLCB2ZXJ0ZXhBcmdzLmpvaW4oKSwgXCIpO1wiLFxuICAgICAgdmVydCgwKSwgXCI9XCIsIFZFUlRFWF9JRFMsIFwiW1wiLCBQT0lOVEVSLCBcIl09XCIsIFZFUlRFWF9DT1VOVCwgXCIrKztcIilcblxuICAgIC8vQ2hlY2sgZm9yIGZhY2UgY3Jvc3NpbmdzXG4gICAgdmFyIGJhc2UgPSAoMTw8ZGltZW5zaW9uKS0xXG4gICAgdmFyIGNvcm5lciA9IHBjdWJlKGJhc2UpXG4gICAgZm9yKHZhciBqPTA7IGo8ZGltZW5zaW9uOyArK2opIHtcbiAgICAgIGlmKChtYXNrICYgfigxPDxqKSk9PT0wKSB7XG4gICAgICAgIC8vQ2hlY2sgZmFjZVxuICAgICAgICB2YXIgc3Vic2V0ID0gYmFzZV4oMTw8ailcbiAgICAgICAgdmFyIGVkZ2UgPSBwY3ViZShzdWJzZXQpXG4gICAgICAgIHZhciBmYWNlQXJncyA9IFsgXVxuICAgICAgICBmb3IodmFyIGs9c3Vic2V0OyBrPjA7IGs9KGstMSkmc3Vic2V0KSB7XG4gICAgICAgICAgZmFjZUFyZ3MucHVzaChWRVJURVhfSURTICsgXCJbXCIgKyBQT0lOVEVSICsgXCIrXCIgKyBwZGVsdGEoaykgKyBcIl1cIilcbiAgICAgICAgfVxuICAgICAgICBmYWNlQXJncy5wdXNoKHZlcnQoMCkpXG4gICAgICAgIGZvcih2YXIgaz0wOyBrPGFycmF5QXJnczsgKytrKSB7XG4gICAgICAgICAgaWYoaiYxKSB7XG4gICAgICAgICAgICBmYWNlQXJncy5wdXNoKGN1YmUoayxiYXNlKSwgY3ViZShrLHN1YnNldCkpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZhY2VBcmdzLnB1c2goY3ViZShrLHN1YnNldCksIGN1YmUoayxiYXNlKSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYoaiYxKSB7XG4gICAgICAgICAgZmFjZUFyZ3MucHVzaChjb3JuZXIsIGVkZ2UpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmFjZUFyZ3MucHVzaChlZGdlLCBjb3JuZXIpXG4gICAgICAgIH1cbiAgICAgICAgZm9yKHZhciBrPTA7IGs8c2NhbGFyQXJnczsgKytrKSB7XG4gICAgICAgICAgZmFjZUFyZ3MucHVzaChzY2FsYXIoaykpXG4gICAgICAgIH1cbiAgICAgICAgY29kZS5wdXNoKFwiaWYoXCIsIGNvcm5lciwgXCIhPT1cIiwgZWRnZSwgXCIpe1wiLFxuICAgICAgICAgIFwiZmFjZShcIiwgZmFjZUFyZ3Muam9pbigpLCBcIil9XCIpXG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIC8vSW5jcmVtZW50IHBvaW50ZXIsIGNsb3NlIG9mZiBpZiBzdGF0ZW1lbnRcbiAgICBjb2RlLnB1c2goXCJ9XCIsXG4gICAgICBQT0lOVEVSLCBcIis9MTtcIilcbiAgfVxuXG4gIGZ1bmN0aW9uIGZsaXAoKSB7XG4gICAgZm9yKHZhciBqPTE7IGo8KDE8PGRpbWVuc2lvbik7ICsraikge1xuICAgICAgY29kZS5wdXNoKFRFTVBPUkFSWSwgXCI9XCIsIHBkZWx0YShqKSwgXCI7XCIsXG4gICAgICAgICAgICAgICAgcGRlbHRhKGopLCBcIj1cIiwgcWN1YmUoaiksIFwiO1wiLFxuICAgICAgICAgICAgICAgIHFjdWJlKGopLCBcIj1cIiwgVEVNUE9SQVJZLCBcIjtcIilcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjcmVhdGVMb29wKGksIG1hc2spIHtcbiAgICBpZihpIDwgMCkge1xuICAgICAgcHJvY2Vzc0dyaWRDZWxsKG1hc2spXG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgZmlsbEVtcHR5U2xpY2UoaSlcbiAgICBjb2RlLnB1c2goXCJpZihcIiwgc2hhcGUob3JkZXJbaV0pLCBcIj4wKXtcIixcbiAgICAgIGluZGV4KG9yZGVyW2ldKSwgXCI9MTtcIilcbiAgICBjcmVhdGVMb29wKGktMSwgbWFza3woMTw8b3JkZXJbaV0pKVxuXG4gICAgZm9yKHZhciBqPTA7IGo8YXJyYXlBcmdzOyArK2opIHtcbiAgICAgIGNvZGUucHVzaChwb2ludGVyKGopLCBcIis9XCIsIHN0ZXAoaixvcmRlcltpXSksIFwiO1wiKVxuICAgIH1cbiAgICBpZihpID09PSBkaW1lbnNpb24tMSkge1xuICAgICAgY29kZS5wdXNoKFBPSU5URVIsIFwiPTA7XCIpXG4gICAgICBmbGlwKClcbiAgICB9XG4gICAgZm9yTG9vcEJlZ2luKGksIDIpXG4gICAgY3JlYXRlTG9vcChpLTEsIG1hc2spXG4gICAgaWYoaSA9PT0gZGltZW5zaW9uLTEpIHtcbiAgICAgIGNvZGUucHVzaChcImlmKFwiLCBpbmRleChvcmRlcltkaW1lbnNpb24tMV0pLCBcIiYxKXtcIixcbiAgICAgICAgUE9JTlRFUiwgXCI9MDt9XCIpXG4gICAgICBmbGlwKClcbiAgICB9XG4gICAgZm9yTG9vcEVuZChpKVxuICAgIGNvZGUucHVzaChcIn1cIilcbiAgfVxuXG4gIGNyZWF0ZUxvb3AoZGltZW5zaW9uLTEsIDApXG5cbiAgLy9SZWxlYXNlIHNjcmF0Y2ggbWVtb3J5XG4gIGNvZGUucHVzaChcImZyZWVVaW50MzIoXCIsIFZFUlRFWF9JRFMsIFwiKTtmcmVlVWludDMyKFwiLCBQSEFTRVMsIFwiKTtcIilcblxuICAvL0NvbXBpbGUgYW5kIGxpbmsgcHJvY2VkdXJlXG4gIHZhciBwcm9jZWR1cmVDb2RlID0gW1xuICAgIFwiJ3VzZSBzdHJpY3QnO1wiLFxuICAgIFwiZnVuY3Rpb24gXCIsIGZ1bmNOYW1lLCBcIihcIiwgYXJncy5qb2luKCksIFwiKXtcIixcbiAgICAgIFwidmFyIFwiLCB2YXJzLmpvaW4oKSwgXCI7XCIsXG4gICAgICBjb2RlLmpvaW4oXCJcIiksXG4gICAgXCJ9XCIsXG4gICAgXCJyZXR1cm4gXCIsIGZ1bmNOYW1lIF0uam9pbihcIlwiKVxuXG4gIHZhciBwcm9jID0gbmV3IEZ1bmN0aW9uKFxuICAgIFwidmVydGV4XCIsIFxuICAgIFwiZmFjZVwiLCBcbiAgICBcInBoYXNlXCIsIFxuICAgIFwibWFsbG9jVWludDMyXCIsIFxuICAgIFwiZnJlZVVpbnQzMlwiLFxuICAgIHByb2NlZHVyZUNvZGUpXG4gIHJldHVybiBwcm9jKFxuICAgIHZlcnRleEZ1bmMsIFxuICAgIGZhY2VGdW5jLCBcbiAgICBwaGFzZUZ1bmMsIFxuICAgIHBvb2wubWFsbG9jVWludDMyLCBcbiAgICBwb29sLmZyZWVVaW50MzIpXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVN1cmZhY2VFeHRyYWN0b3IoYXJncykge1xuICBmdW5jdGlvbiBlcnJvcihtc2cpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJuZGFycmF5LWV4dHJhY3QtY29udG91cjogXCIgKyBtc2cpXG4gIH1cbiAgaWYodHlwZW9mIGFyZ3MgIT09IFwib2JqZWN0XCIpIHtcbiAgICBlcnJvcihcIk11c3Qgc3BlY2lmeSBhcmd1bWVudHNcIilcbiAgfVxuICB2YXIgb3JkZXIgPSBhcmdzLm9yZGVyXG4gIGlmKCFBcnJheS5pc0FycmF5KG9yZGVyKSkge1xuICAgIGVycm9yKFwiTXVzdCBzcGVjaWZ5IG9yZGVyXCIpXG4gIH1cbiAgdmFyIGFycmF5cyA9IGFyZ3MuYXJyYXlBcmd1bWVudHN8fDFcbiAgaWYoYXJyYXlzIDwgMSkge1xuICAgIGVycm9yKFwiTXVzdCBoYXZlIGF0IGxlYXN0IG9uZSBhcnJheSBhcmd1bWVudFwiKVxuICB9XG4gIHZhciBzY2FsYXJzID0gYXJncy5zY2FsYXJBcmd1bWVudHN8fDBcbiAgaWYoc2NhbGFycyA8IDApIHtcbiAgICBlcnJvcihcIlNjYWxhciBhcmcgY291bnQgbXVzdCBiZSA+IDBcIilcbiAgfVxuICBpZih0eXBlb2YgYXJncy52ZXJ0ZXggIT09IFwiZnVuY3Rpb25cIikge1xuICAgIGVycm9yKFwiTXVzdCBzcGVjaWZ5IHZlcnRleCBjcmVhdGlvbiBmdW5jdGlvblwiKVxuICB9XG4gIGlmKHR5cGVvZiBhcmdzLmNlbGwgIT09IFwiZnVuY3Rpb25cIikge1xuICAgIGVycm9yKFwiTXVzdCBzcGVjaWZ5IGNlbGwgY3JlYXRpb24gZnVuY3Rpb25cIilcbiAgfVxuICBpZih0eXBlb2YgYXJncy5waGFzZSAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgZXJyb3IoXCJNdXN0IHNwZWNpZnkgcGhhc2UgZnVuY3Rpb25cIilcbiAgfVxuICB2YXIgZ2V0dGVycyA9IGFyZ3MuZ2V0dGVycyB8fCBbXVxuICB2YXIgdHlwZXNpZyA9IG5ldyBBcnJheShhcnJheXMpXG4gIGZvcih2YXIgaT0wOyBpPGFycmF5czsgKytpKSB7XG4gICAgaWYoZ2V0dGVycy5pbmRleE9mKGkpID49IDApIHtcbiAgICAgIHR5cGVzaWdbaV0gPSB0cnVlXG4gICAgfSBlbHNlIHtcbiAgICAgIHR5cGVzaWdbaV0gPSBmYWxzZVxuICAgIH1cbiAgfVxuICByZXR1cm4gY29tcGlsZVN1cmZhY2VQcm9jZWR1cmUoXG4gICAgYXJncy52ZXJ0ZXgsXG4gICAgYXJncy5jZWxsLFxuICAgIGFyZ3MucGhhc2UsXG4gICAgc2NhbGFycyxcbiAgICBvcmRlcixcbiAgICB0eXBlc2lnKVxufVxufSx7XCJ0eXBlZGFycmF5LXBvb2xcIjo1NDV9XSw0NDA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxuXG5cbnZhciBmaWxsID0gX2RlcmVxXygnY3dpc2UvbGliL3dyYXBwZXInKSh7XCJhcmdzXCI6W1wiaW5kZXhcIixcImFycmF5XCIsXCJzY2FsYXJcIl0sXCJwcmVcIjp7XCJib2R5XCI6XCJ7fVwiLFwiYXJnc1wiOltdLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcImJvZHlcIjp7XCJib2R5XCI6XCJ7X2lubGluZV8xX2FyZzFfPV9pbmxpbmVfMV9hcmcyXy5hcHBseSh2b2lkIDAsX2lubGluZV8xX2FyZzBfKX1cIixcImFyZ3NcIjpbe1wibmFtZVwiOlwiX2lubGluZV8xX2FyZzBfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMV9hcmcxX1wiLFwibHZhbHVlXCI6dHJ1ZSxcInJ2YWx1ZVwiOmZhbHNlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzFfYXJnMl9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX1dLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcInBvc3RcIjp7XCJib2R5XCI6XCJ7fVwiLFwiYXJnc1wiOltdLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcImRlYnVnXCI6ZmFsc2UsXCJmdW5jTmFtZVwiOlwiY3dpc2VcIixcImJsb2NrU2l6ZVwiOjY0fSlcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihhcnJheSwgZikge1xuICBmaWxsKGFycmF5LCBmKVxuICByZXR1cm4gYXJyYXlcbn1cblxufSx7XCJjd2lzZS9saWIvd3JhcHBlclwiOjE0OX1dLDQ0MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgICAgICA9IGdyYWRpZW50XG5cbnZhciBkdXAgICAgICAgICAgICAgPSBfZGVyZXFfKCdkdXAnKVxudmFyIGN3aXNlQ29tcGlsZXIgICA9IF9kZXJlcV8oJ2N3aXNlLWNvbXBpbGVyJylcblxudmFyIFRFTVBMQVRFX0NBQ0hFICA9IHt9XG52YXIgR1JBRElFTlRfQ0FDSEUgID0ge31cblxudmFyIEVtcHR5UHJvYyA9IHtcbiAgYm9keTogXCJcIixcbiAgYXJnczogW10sXG4gIHRoaXNWYXJzOiBbXSxcbiAgbG9jYWxWYXJzOiBbXVxufVxuXG52YXIgY2VudHJhbERpZmYgPSBjd2lzZUNvbXBpbGVyKHtcbiAgYXJnczogWyAnYXJyYXknLCAnYXJyYXknLCAnYXJyYXknIF0sXG4gIHByZTogRW1wdHlQcm9jLFxuICBwb3N0OiBFbXB0eVByb2MsXG4gIGJvZHk6IHtcbiAgICBhcmdzOiBbIHtcbiAgICAgIG5hbWU6ICdvdXQnLCBcbiAgICAgIGx2YWx1ZTogdHJ1ZSxcbiAgICAgIHJ2YWx1ZTogZmFsc2UsXG4gICAgICBjb3VudDogMVxuICAgIH0sIHtcbiAgICAgIG5hbWU6ICdsZWZ0JywgXG4gICAgICBsdmFsdWU6IGZhbHNlLFxuICAgICAgcnZhbHVlOiB0cnVlLFxuICAgICAgY291bnQ6IDFcbiAgICB9LCB7XG4gICAgICBuYW1lOiAncmlnaHQnLCBcbiAgICAgIGx2YWx1ZTogZmFsc2UsXG4gICAgICBydmFsdWU6IHRydWUsXG4gICAgICBjb3VudDogMVxuICAgIH1dLFxuICAgIGJvZHk6IFwib3V0PTAuNSoobGVmdC1yaWdodClcIixcbiAgICB0aGlzVmFyczogW10sXG4gICAgbG9jYWxWYXJzOiBbXVxuICB9LFxuICBmdW5jTmFtZTogJ2NkaWZmJ1xufSlcblxudmFyIHplcm9PdXQgPSBjd2lzZUNvbXBpbGVyKHtcbiAgYXJnczogWyAnYXJyYXknIF0sXG4gIHByZTogRW1wdHlQcm9jLFxuICBwb3N0OiBFbXB0eVByb2MsXG4gIGJvZHk6IHtcbiAgICBhcmdzOiBbIHtcbiAgICAgIG5hbWU6ICdvdXQnLCBcbiAgICAgIGx2YWx1ZTogdHJ1ZSxcbiAgICAgIHJ2YWx1ZTogZmFsc2UsXG4gICAgICBjb3VudDogMVxuICAgIH1dLFxuICAgIGJvZHk6IFwib3V0PTBcIixcbiAgICB0aGlzVmFyczogW10sXG4gICAgbG9jYWxWYXJzOiBbXVxuICB9LFxuICBmdW5jTmFtZTogJ3plcm8nXG59KVxuXG5mdW5jdGlvbiBnZW5lcmF0ZVRlbXBsYXRlKGQpIHtcbiAgaWYoZCBpbiBURU1QTEFURV9DQUNIRSkge1xuICAgIHJldHVybiBURU1QTEFURV9DQUNIRVtkXVxuICB9XG4gIHZhciBjb2RlID0gW11cbiAgZm9yKHZhciBpPTA7IGk8ZDsgKytpKSB7XG4gICAgY29kZS5wdXNoKCdvdXQnLCBpLCAncz0wLjUqKGlucCcsIGksICdsLWlucCcsIGksICdyKTsnKVxuICB9XG4gIHZhciBhcmdzID0gWyAnYXJyYXknIF1cbiAgdmFyIG5hbWVzID0gWydqdW5rJ11cbiAgZm9yKHZhciBpPTA7IGk8ZDsgKytpKSB7XG4gICAgYXJncy5wdXNoKCdhcnJheScpXG4gICAgbmFtZXMucHVzaCgnb3V0JyArIGkgKyAncycpXG4gICAgdmFyIG8gPSBkdXAoZClcbiAgICBvW2ldID0gLTFcbiAgICBhcmdzLnB1c2goe1xuICAgICAgYXJyYXk6IDAsXG4gICAgICBvZmZzZXQ6IG8uc2xpY2UoKVxuICAgIH0pXG4gICAgb1tpXSA9IDFcbiAgICBhcmdzLnB1c2goe1xuICAgICAgYXJyYXk6IDAsXG4gICAgICBvZmZzZXQ6IG8uc2xpY2UoKVxuICAgIH0pXG4gICAgbmFtZXMucHVzaCgnaW5wJyArIGkgKyAnbCcsICdpbnAnICsgaSArICdyJylcbiAgfVxuICByZXR1cm4gVEVNUExBVEVfQ0FDSEVbZF0gPSBjd2lzZUNvbXBpbGVyKHtcbiAgICBhcmdzOiBhcmdzLFxuICAgIHByZTogIEVtcHR5UHJvYyxcbiAgICBwb3N0OiBFbXB0eVByb2MsXG4gICAgYm9keToge1xuICAgICAgYm9keTogY29kZS5qb2luKCcnKSxcbiAgICAgIGFyZ3M6IG5hbWVzLm1hcChmdW5jdGlvbihuKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbmFtZTogbixcbiAgICAgICAgICBsdmFsdWU6IG4uaW5kZXhPZignb3V0JykgPT09IDAsXG4gICAgICAgICAgcnZhbHVlOiBuLmluZGV4T2YoJ2lucCcpID09PSAwLFxuICAgICAgICAgIGNvdW50OiAobiE9PSdqdW5rJyl8MFxuICAgICAgICB9XG4gICAgICB9KSxcbiAgICAgIHRoaXNWYXJzOiBbXSxcbiAgICAgIGxvY2FsVmFyczogW11cbiAgICB9LFxuICAgIGZ1bmNOYW1lOiAnZmRUZW1wbGF0ZScgKyBkXG4gIH0pXG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlR3JhZGllbnQoYm91bmRhcnlDb25kaXRpb25zKSB7XG4gIHZhciB0b2tlbiA9IGJvdW5kYXJ5Q29uZGl0aW9ucy5qb2luKClcbiAgdmFyIHByb2MgPSBHUkFESUVOVF9DQUNIRVt0b2tlbl1cbiAgaWYocHJvYykge1xuICAgIHJldHVybiBwcm9jXG4gIH1cblxuICB2YXIgZCA9IGJvdW5kYXJ5Q29uZGl0aW9ucy5sZW5ndGhcbiAgdmFyIGNvZGUgPSBbJ2Z1bmN0aW9uIGdyYWRpZW50KGRzdCxzcmMpe3ZhciBzPXNyYy5zaGFwZS5zbGljZSgpOycgXVxuICBcbiAgZnVuY3Rpb24gaGFuZGxlQm91bmRhcnkoZmFjZXQpIHtcbiAgICB2YXIgY29kID0gZCAtIGZhY2V0Lmxlbmd0aFxuXG4gICAgdmFyIGxvU3RyID0gW11cbiAgICB2YXIgaGlTdHIgPSBbXVxuICAgIHZhciBwaWNrU3RyID0gW11cbiAgICBmb3IodmFyIGk9MDsgaTxkOyArK2kpIHtcbiAgICAgIGlmKGZhY2V0LmluZGV4T2YoaSsxKSA+PSAwKSB7XG4gICAgICAgIHBpY2tTdHIucHVzaCgnMCcpXG4gICAgICB9IGVsc2UgaWYoZmFjZXQuaW5kZXhPZigtKGkrMSkpID49IDApIHtcbiAgICAgICAgcGlja1N0ci5wdXNoKCdzWycraSsnXS0xJylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBpY2tTdHIucHVzaCgnLTEnKVxuICAgICAgICBsb1N0ci5wdXNoKCcxJylcbiAgICAgICAgaGlTdHIucHVzaCgnc1snK2krJ10tMicpXG4gICAgICB9XG4gICAgfVxuICAgIHZhciBib3VuZFN0ciA9ICcubG8oJyArIGxvU3RyLmpvaW4oKSArICcpLmhpKCcgKyBoaVN0ci5qb2luKCkgKyAnKSdcbiAgICBpZihsb1N0ci5sZW5ndGggPT09IDApIHtcbiAgICAgIGJvdW5kU3RyID0gJydcbiAgICB9XG4gICAgICAgIFxuICAgIGlmKGNvZCA+IDApIHtcbiAgICAgIGNvZGUucHVzaCgnaWYoMScpIFxuICAgICAgZm9yKHZhciBpPTA7IGk8ZDsgKytpKSB7XG4gICAgICAgIGlmKGZhY2V0LmluZGV4T2YoaSsxKSA+PSAwIHx8IGZhY2V0LmluZGV4T2YoLShpKzEpKSA+PSAwKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgICBjb2RlLnB1c2goJyYmc1snLCBpLCAnXT4yJylcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaCgnKXtncmFkJywgY29kLCAnKHNyYy5waWNrKCcsIHBpY2tTdHIuam9pbigpLCAnKScsIGJvdW5kU3RyKVxuICAgICAgZm9yKHZhciBpPTA7IGk8ZDsgKytpKSB7XG4gICAgICAgIGlmKGZhY2V0LmluZGV4T2YoaSsxKSA+PSAwIHx8IGZhY2V0LmluZGV4T2YoLShpKzEpKSA+PSAwKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgICBjb2RlLnB1c2goJyxkc3QucGljaygnLCBwaWNrU3RyLmpvaW4oKSwgJywnLCBpLCAnKScsIGJvdW5kU3RyKVxuICAgICAgfVxuICAgICAgY29kZS5wdXNoKCcpOycpXG4gICAgfVxuXG4gICAgZm9yKHZhciBpPTA7IGk8ZmFjZXQubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBibmQgPSBNYXRoLmFicyhmYWNldFtpXSktMVxuICAgICAgdmFyIG91dFN0ciA9ICdkc3QucGljaygnICsgcGlja1N0ci5qb2luKCkgKyAnLCcgKyBibmQgKyAnKScgKyBib3VuZFN0clxuICAgICAgc3dpdGNoKGJvdW5kYXJ5Q29uZGl0aW9uc1tibmRdKSB7XG5cbiAgICAgICAgY2FzZSAnY2xhbXAnOlxuICAgICAgICAgIHZhciBjUGlja1N0ciA9IHBpY2tTdHIuc2xpY2UoKVxuICAgICAgICAgIHZhciBkUGlja1N0ciA9IHBpY2tTdHIuc2xpY2UoKVxuICAgICAgICAgIGlmKGZhY2V0W2ldIDwgMCkge1xuICAgICAgICAgICAgY1BpY2tTdHJbYm5kXSA9ICdzWycgKyBibmQgKyAnXS0yJ1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkUGlja1N0cltibmRdID0gJzEnXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmKGNvZCA9PT0gMCkge1xuICAgICAgICAgICAgY29kZS5wdXNoKCdpZihzWycsIGJuZCwgJ10+MSl7ZHN0LnNldCgnLFxuICAgICAgICAgICAgICBwaWNrU3RyLmpvaW4oKSwgJywnLCBibmQsICcsMC41KihzcmMuZ2V0KCcsXG4gICAgICAgICAgICAgICAgY1BpY2tTdHIuam9pbigpLCAnKS1zcmMuZ2V0KCcsXG4gICAgICAgICAgICAgICAgZFBpY2tTdHIuam9pbigpLCAnKSkpfWVsc2V7ZHN0LnNldCgnLFxuICAgICAgICAgICAgICBwaWNrU3RyLmpvaW4oKSwgJywnLCBibmQsICcsMCl9OycpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvZGUucHVzaCgnaWYoc1snLCBibmQsICddPjEpe2RpZmYoJywgb3V0U3RyLCBcbiAgICAgICAgICAgICAgICAnLHNyYy5waWNrKCcsIGNQaWNrU3RyLmpvaW4oKSwgJyknLCBib3VuZFN0ciwgXG4gICAgICAgICAgICAgICAgJyxzcmMucGljaygnLCBkUGlja1N0ci5qb2luKCksICcpJywgYm91bmRTdHIsIFxuICAgICAgICAgICAgICAgICcpO31lbHNle3plcm8oJywgb3V0U3RyLCAnKTt9OycpXG4gICAgICAgICAgfVxuICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgJ21pcnJvcic6XG4gICAgICAgICAgaWYoY29kID09PSAwKSB7XG4gICAgICAgICAgICBjb2RlLnB1c2goJ2RzdC5zZXQoJywgcGlja1N0ci5qb2luKCksICcsJywgYm5kLCAnLDApOycpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvZGUucHVzaCgnemVybygnLCBvdXRTdHIsICcpOycpXG4gICAgICAgICAgfVxuICAgICAgICBicmVha1xuXG4gICAgICAgIGNhc2UgJ3dyYXAnOlxuICAgICAgICAgIHZhciBhUGlja1N0ciA9IHBpY2tTdHIuc2xpY2UoKVxuICAgICAgICAgIHZhciBiUGlja1N0ciA9IHBpY2tTdHIuc2xpY2UoKVxuICAgICAgICAgIGlmKGZhY2V0W2ldIDwgMCkge1xuICAgICAgICAgICAgYVBpY2tTdHJbYm5kXSA9ICdzWycgKyBibmQgKyAnXS0yJ1xuICAgICAgICAgICAgYlBpY2tTdHJbYm5kXSA9ICcwJ1xuICAgICAgICAgICAgXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFQaWNrU3RyW2JuZF0gPSAnc1snICsgYm5kICsgJ10tMSdcbiAgICAgICAgICAgIGJQaWNrU3RyW2JuZF0gPSAnMSdcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYoY29kID09PSAwKSB7XG4gICAgICAgICAgICBjb2RlLnB1c2goJ2lmKHNbJywgYm5kLCAnXT4yKXtkc3Quc2V0KCcsXG4gICAgICAgICAgICAgIHBpY2tTdHIuam9pbigpLCAnLCcsIGJuZCwgJywwLjUqKHNyYy5nZXQoJyxcbiAgICAgICAgICAgICAgICBhUGlja1N0ci5qb2luKCksICcpLXNyYy5nZXQoJyxcbiAgICAgICAgICAgICAgICBiUGlja1N0ci5qb2luKCksICcpKSl9ZWxzZXtkc3Quc2V0KCcsXG4gICAgICAgICAgICAgIHBpY2tTdHIuam9pbigpLCAnLCcsIGJuZCwgJywwKX07JylcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29kZS5wdXNoKCdpZihzWycsIGJuZCwgJ10+Mil7ZGlmZignLCBvdXRTdHIsIFxuICAgICAgICAgICAgICAgICcsc3JjLnBpY2soJywgYVBpY2tTdHIuam9pbigpLCAnKScsIGJvdW5kU3RyLCBcbiAgICAgICAgICAgICAgICAnLHNyYy5waWNrKCcsIGJQaWNrU3RyLmpvaW4oKSwgJyknLCBib3VuZFN0ciwgXG4gICAgICAgICAgICAgICAgJyk7fWVsc2V7emVybygnLCBvdXRTdHIsICcpO307JylcbiAgICAgICAgICB9XG4gICAgICAgIGJyZWFrXG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25kYXJyYXktZ3JhZGllbnQ6IEludmFsaWQgYm91bmRhcnkgY29uZGl0aW9uJylcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZihjb2QgPiAwKSB7XG4gICAgICBjb2RlLnB1c2goJ307JylcbiAgICB9XG4gIH1cblxuICAvL0VudW1lcmF0ZSByaWRnZXMsIGZhY2V0cywgZXRjLiBvZiBoeXBlcmN1YmVcbiAgZm9yKHZhciBpPTA7IGk8KDE8PGQpOyArK2kpIHtcbiAgICB2YXIgZmFjZXMgPSBbXVxuICAgIGZvcih2YXIgaj0wOyBqPGQ7ICsraikge1xuICAgICAgaWYoaSAmICgxPDxqKSkge1xuICAgICAgICBmYWNlcy5wdXNoKGorMSlcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yKHZhciBrPTA7IGs8KDE8PGZhY2VzLmxlbmd0aCk7ICsraykge1xuICAgICAgdmFyIHNmYWNlcyA9IGZhY2VzLnNsaWNlKClcbiAgICAgIGZvcih2YXIgaj0wOyBqPGZhY2VzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgIGlmKGsgJiAoMTw8aikpIHtcbiAgICAgICAgICBzZmFjZXNbal0gPSAtc2ZhY2VzW2pdXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGhhbmRsZUJvdW5kYXJ5KHNmYWNlcylcbiAgICB9XG4gIH1cblxuICBjb2RlLnB1c2goJ3JldHVybiBkc3Q7fTtyZXR1cm4gZ3JhZGllbnQnKVxuXG4gIC8vQ29tcGlsZSBhbmQgbGluayByb3V0aW5lLCBzYXZlIGNhY2hlZCBwcm9jZWR1cmVcbiAgdmFyIGxpbmtOYW1lcyA9IFsgJ2RpZmYnLCAnemVybycgXVxuICB2YXIgbGlua0FyZ3MgID0gWyBjZW50cmFsRGlmZiwgemVyb091dCBdXG4gIGZvcih2YXIgaT0xOyBpPD1kOyArK2kpIHtcbiAgICBsaW5rTmFtZXMucHVzaCgnZ3JhZCcgKyBpKVxuICAgIGxpbmtBcmdzLnB1c2goZ2VuZXJhdGVUZW1wbGF0ZShpKSlcbiAgfVxuICBsaW5rTmFtZXMucHVzaChjb2RlLmpvaW4oJycpKVxuXG4gIHZhciBsaW5rID0gRnVuY3Rpb24uYXBwbHkodm9pZCAwLCBsaW5rTmFtZXMpXG4gIHZhciBwcm9jID0gbGluay5hcHBseSh2b2lkIDAsIGxpbmtBcmdzKVxuICBURU1QTEFURV9DQUNIRVt0b2tlbl0gPSBwcm9jXG4gIHJldHVybiBwcm9jXG59XG5cbmZ1bmN0aW9uIGdyYWRpZW50KG91dCwgaW5wLCBiYykge1xuICBpZihBcnJheS5pc0FycmF5KGJjKSkge1xuICAgIGlmKGJjLmxlbmd0aCAhPT0gaW5wLmRpbWVuc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCduZGFycmF5LWdyYWRpZW50OiBpbnZhbGlkIGJvdW5kYXJ5IGNvbmRpdGlvbnMnKVxuICAgIH1cbiAgfSBlbHNlIGlmKHR5cGVvZiBiYyA9PT0gJ3N0cmluZycpIHtcbiAgICBiYyA9IGR1cChpbnAuZGltZW5zaW9uLCBiYylcbiAgfSBlbHNlIHtcbiAgICBiYyA9IGR1cChpbnAuZGltZW5zaW9uLCAnY2xhbXAnKVxuICB9XG4gIGlmKG91dC5kaW1lbnNpb24gIT09IGlucC5kaW1lbnNpb24gKyAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCduZGFycmF5LWdyYWRpZW50OiBvdXRwdXQgZGltZW5zaW9uIG11c3QgYmUgKzEgaW5wdXQgZGltZW5zaW9uJylcbiAgfVxuICBpZihvdXQuc2hhcGVbaW5wLmRpbWVuc2lvbl0gIT09IGlucC5kaW1lbnNpb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ25kYXJyYXktZ3JhZGllbnQ6IG91dHB1dCBzaGFwZSBtdXN0IG1hdGNoIGlucHV0IHNoYXBlJylcbiAgfVxuICBmb3IodmFyIGk9MDsgaTxpbnAuZGltZW5zaW9uOyArK2kpIHtcbiAgICBpZihvdXQuc2hhcGVbaV0gIT09IGlucC5zaGFwZVtpXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCduZGFycmF5LWdyYWRpZW50OiBzaGFwZSBtaXNtYXRjaCcpXG4gICAgfVxuICB9XG4gIGlmKGlucC5zaXplID09PSAwKSB7XG4gICAgcmV0dXJuIG91dFxuICB9XG4gIGlmKGlucC5kaW1lbnNpb24gPD0gMCkge1xuICAgIG91dC5zZXQoMClcbiAgICByZXR1cm4gb3V0XG4gIH1cbiAgdmFyIGNhY2hlZCA9IGdlbmVyYXRlR3JhZGllbnQoYmMpXG4gIHJldHVybiBjYWNoZWQob3V0LCBpbnApXG59XG59LHtcImN3aXNlLWNvbXBpbGVyXCI6MTQ2LFwiZHVwXCI6MTcwfV0sNDQyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgd2FycCA9IF9kZXJlcV8oJ25kYXJyYXktd2FycCcpXG52YXIgaW52ZXJ0ID0gX2RlcmVxXygnZ2wtbWF0cml4LWludmVydCcpXG5cbm1vZHVsZS5leHBvcnRzID0gYXBwbHlIb21vZ3JhcGh5XG5cbmZ1bmN0aW9uIGFwcGx5SG9tb2dyYXBoeShkZXN0LCBzcmMsIFhpKSB7XG4gIHZhciBuID0gc3JjLmRpbWVuc2lvblxuICB2YXIgWCA9IGludmVydChbXSwgWGkpXG4gIHdhcnAoZGVzdCwgc3JjLCBmdW5jdGlvbihvdXRfYywgaW5wX2MpIHtcbiAgICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICAgIG91dF9jW2ldID0gWFsobisxKSpuICsgaV1cbiAgICAgIGZvcih2YXIgaj0wOyBqPG47ICsraikge1xuICAgICAgICBvdXRfY1tpXSArPSBYWyhuKzEpKmoraV0gKiBpbnBfY1tqXVxuICAgICAgfVxuICAgIH1cbiAgICB2YXIgdyA9IFhbKG4rMSkqKG4rMSktMV1cbiAgICBmb3IodmFyIGo9MDsgajxuOyArK2opIHtcbiAgICAgIHcgKz0gWFsobisxKSpqK25dICogaW5wX2Nbal1cbiAgICB9XG4gICAgdmFyIHdyID0gMS4wIC8gd1xuICAgIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgICAgb3V0X2NbaV0gKj0gd3JcbiAgICB9XG4gICAgcmV0dXJuIG91dF9jXG4gIH0pXG4gIHJldHVybiBkZXN0XG59XG59LHtcImdsLW1hdHJpeC1pbnZlcnRcIjoyNzcsXCJuZGFycmF5LXdhcnBcIjo0NDl9XSw0NDM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxuZnVuY3Rpb24gaW50ZXJwMWQoYXJyLCB4KSB7XG4gIHZhciBpeCA9IE1hdGguZmxvb3IoeClcbiAgICAsIGZ4ID0geCAtIGl4XG4gICAgLCBzMCA9IDAgPD0gaXggICAmJiBpeCAgIDwgYXJyLnNoYXBlWzBdXG4gICAgLCBzMSA9IDAgPD0gaXgrMSAmJiBpeCsxIDwgYXJyLnNoYXBlWzBdXG4gICAgLCB3MCA9IHMwID8gK2Fyci5nZXQoaXgpICAgOiAwLjBcbiAgICAsIHcxID0gczEgPyArYXJyLmdldChpeCsxKSA6IDAuMFxuICByZXR1cm4gKDEuMC1meCkqdzAgKyBmeCp3MVxufVxuXG5mdW5jdGlvbiBpbnRlcnAyZChhcnIsIHgsIHkpIHtcbiAgdmFyIGl4ID0gTWF0aC5mbG9vcih4KVxuICAgICwgZnggPSB4IC0gaXhcbiAgICAsIHMwID0gMCA8PSBpeCAgICYmIGl4ICAgPCBhcnIuc2hhcGVbMF1cbiAgICAsIHMxID0gMCA8PSBpeCsxICYmIGl4KzEgPCBhcnIuc2hhcGVbMF1cbiAgICAsIGl5ID0gTWF0aC5mbG9vcih5KVxuICAgICwgZnkgPSB5IC0gaXlcbiAgICAsIHQwID0gMCA8PSBpeSAgICYmIGl5ICAgPCBhcnIuc2hhcGVbMV1cbiAgICAsIHQxID0gMCA8PSBpeSsxICYmIGl5KzEgPCBhcnIuc2hhcGVbMV1cbiAgICAsIHcwMCA9IHMwJiZ0MCA/IGFyci5nZXQoaXggICxpeSAgKSA6IDAuMFxuICAgICwgdzAxID0gczAmJnQxID8gYXJyLmdldChpeCAgLGl5KzEpIDogMC4wXG4gICAgLCB3MTAgPSBzMSYmdDAgPyBhcnIuZ2V0KGl4KzEsaXkgICkgOiAwLjBcbiAgICAsIHcxMSA9IHMxJiZ0MSA/IGFyci5nZXQoaXgrMSxpeSsxKSA6IDAuMFxuICByZXR1cm4gKDEuMC1meSkgKiAoKDEuMC1meCkqdzAwICsgZngqdzEwKSArIGZ5ICogKCgxLjAtZngpKncwMSArIGZ4KncxMSlcbn1cblxuZnVuY3Rpb24gaW50ZXJwM2QoYXJyLCB4LCB5LCB6KSB7XG4gIHZhciBpeCA9IE1hdGguZmxvb3IoeClcbiAgICAsIGZ4ID0geCAtIGl4XG4gICAgLCBzMCA9IDAgPD0gaXggICAmJiBpeCAgIDwgYXJyLnNoYXBlWzBdXG4gICAgLCBzMSA9IDAgPD0gaXgrMSAmJiBpeCsxIDwgYXJyLnNoYXBlWzBdXG4gICAgLCBpeSA9IE1hdGguZmxvb3IoeSlcbiAgICAsIGZ5ID0geSAtIGl5XG4gICAgLCB0MCA9IDAgPD0gaXkgICAmJiBpeSAgIDwgYXJyLnNoYXBlWzFdXG4gICAgLCB0MSA9IDAgPD0gaXkrMSAmJiBpeSsxIDwgYXJyLnNoYXBlWzFdXG4gICAgLCBpeiA9IE1hdGguZmxvb3IoeilcbiAgICAsIGZ6ID0geiAtIGl6XG4gICAgLCB1MCA9IDAgPD0gaXogICAmJiBpeiAgIDwgYXJyLnNoYXBlWzJdXG4gICAgLCB1MSA9IDAgPD0gaXorMSAmJiBpeisxIDwgYXJyLnNoYXBlWzJdXG4gICAgLCB3MDAwID0gczAmJnQwJiZ1MCA/IGFyci5nZXQoaXgsaXksaXopICAgICAgIDogMC4wXG4gICAgLCB3MDEwID0gczAmJnQxJiZ1MCA/IGFyci5nZXQoaXgsaXkrMSxpeikgICAgIDogMC4wXG4gICAgLCB3MTAwID0gczEmJnQwJiZ1MCA/IGFyci5nZXQoaXgrMSxpeSxpeikgICAgIDogMC4wXG4gICAgLCB3MTEwID0gczEmJnQxJiZ1MCA/IGFyci5nZXQoaXgrMSxpeSsxLGl6KSAgIDogMC4wXG4gICAgLCB3MDAxID0gczAmJnQwJiZ1MSA/IGFyci5nZXQoaXgsaXksaXorMSkgICAgIDogMC4wXG4gICAgLCB3MDExID0gczAmJnQxJiZ1MSA/IGFyci5nZXQoaXgsaXkrMSxpeisxKSAgIDogMC4wXG4gICAgLCB3MTAxID0gczEmJnQwJiZ1MSA/IGFyci5nZXQoaXgrMSxpeSxpeisxKSAgIDogMC4wXG4gICAgLCB3MTExID0gczEmJnQxJiZ1MSA/IGFyci5nZXQoaXgrMSxpeSsxLGl6KzEpIDogMC4wXG4gIHJldHVybiAoMS4wLWZ6KSAqICgoMS4wLWZ5KSAqICgoMS4wLWZ4KSp3MDAwICsgZngqdzEwMCkgKyBmeSAqICgoMS4wLWZ4KSp3MDEwICsgZngqdzExMCkpICsgZnogKiAoKDEuMC1meSkgKiAoKDEuMC1meCkqdzAwMSArIGZ4KncxMDEpICsgZnkgKiAoKDEuMC1meCkqdzAxMSArIGZ4KncxMTEpKVxufVxuXG5mdW5jdGlvbiBpbnRlcnBOZChhcnIpIHtcbiAgdmFyIGQgPSBhcnIuc2hhcGUubGVuZ3RofDBcbiAgICAsIGl4ID0gbmV3IEFycmF5KGQpXG4gICAgLCBmeCA9IG5ldyBBcnJheShkKVxuICAgICwgczAgPSBuZXcgQXJyYXkoZClcbiAgICAsIHMxID0gbmV3IEFycmF5KGQpXG4gICAgLCBpLCB0XG4gIGZvcihpPTA7IGk8ZDsgKytpKSB7XG4gICAgdCA9ICthcmd1bWVudHNbaSsxXVxuICAgIGl4W2ldID0gTWF0aC5mbG9vcih0KVxuICAgIGZ4W2ldID0gdCAtIGl4W2ldXG4gICAgczBbaV0gPSAoMCA8PSBpeFtpXSAgICYmIGl4W2ldICAgPCBhcnIuc2hhcGVbaV0pXG4gICAgczFbaV0gPSAoMCA8PSBpeFtpXSsxICYmIGl4W2ldKzEgPCBhcnIuc2hhcGVbaV0pXG4gIH1cbiAgdmFyIHIgPSAwLjAsIGosIHcsIGlkeFxuaV9sb29wOlxuICBmb3IoaT0wOyBpPCgxPDxkKTsgKytpKSB7XG4gICAgdyA9IDEuMFxuICAgIGlkeCA9IGFyci5vZmZzZXRcbiAgICBmb3Ioaj0wOyBqPGQ7ICsraikge1xuICAgICAgaWYoaSAmICgxPDxqKSkge1xuICAgICAgICBpZighczFbal0pIHtcbiAgICAgICAgICBjb250aW51ZSBpX2xvb3BcbiAgICAgICAgfVxuICAgICAgICB3ICo9IGZ4W2pdXG4gICAgICAgIGlkeCArPSBhcnIuc3RyaWRlW2pdICogKGl4W2pdICsgMSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKCFzMFtqXSkge1xuICAgICAgICAgIGNvbnRpbnVlIGlfbG9vcFxuICAgICAgICB9XG4gICAgICAgIHcgKj0gMS4wIC0gZnhbal1cbiAgICAgICAgaWR4ICs9IGFyci5zdHJpZGVbal0gKiBpeFtqXVxuICAgICAgfVxuICAgIH1cbiAgICByICs9IHcgKiBhcnIuZGF0YVtpZHhdXG4gIH1cbiAgcmV0dXJuIHJcbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGUoYXJyLCB4LCB5LCB6KSB7XG4gIHN3aXRjaChhcnIuc2hhcGUubGVuZ3RoKSB7XG4gICAgY2FzZSAwOlxuICAgICAgcmV0dXJuIDAuMFxuICAgIGNhc2UgMTpcbiAgICAgIHJldHVybiBpbnRlcnAxZChhcnIsIHgpXG4gICAgY2FzZSAyOlxuICAgICAgcmV0dXJuIGludGVycDJkKGFyciwgeCwgeSlcbiAgICBjYXNlIDM6XG4gICAgICByZXR1cm4gaW50ZXJwM2QoYXJyLCB4LCB5LCB6KVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gaW50ZXJwTmQuYXBwbHkodW5kZWZpbmVkLCBhcmd1bWVudHMpXG4gIH1cbn1cbm1vZHVsZS5leHBvcnRzID0gaW50ZXJwb2xhdGVcbm1vZHVsZS5leHBvcnRzLmQxID0gaW50ZXJwMWRcbm1vZHVsZS5leHBvcnRzLmQyID0gaW50ZXJwMmRcbm1vZHVsZS5leHBvcnRzLmQzID0gaW50ZXJwM2RcblxufSx7fV0sNDQ0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciBjb21waWxlID0gX2RlcmVxXyhcImN3aXNlLWNvbXBpbGVyXCIpXG5cbnZhciBFbXB0eVByb2MgPSB7XG4gIGJvZHk6IFwiXCIsXG4gIGFyZ3M6IFtdLFxuICB0aGlzVmFyczogW10sXG4gIGxvY2FsVmFyczogW11cbn1cblxuZnVuY3Rpb24gZml4dXAoeCkge1xuICBpZigheCkge1xuICAgIHJldHVybiBFbXB0eVByb2NcbiAgfVxuICBmb3IodmFyIGk9MDsgaTx4LmFyZ3MubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYSA9IHguYXJnc1tpXVxuICAgIGlmKGkgPT09IDApIHtcbiAgICAgIHguYXJnc1tpXSA9IHtuYW1lOiBhLCBsdmFsdWU6dHJ1ZSwgcnZhbHVlOiAhIXgucnZhbHVlLCBjb3VudDp4LmNvdW50fHwxIH1cbiAgICB9IGVsc2Uge1xuICAgICAgeC5hcmdzW2ldID0ge25hbWU6IGEsIGx2YWx1ZTpmYWxzZSwgcnZhbHVlOnRydWUsIGNvdW50OiAxfVxuICAgIH1cbiAgfVxuICBpZigheC50aGlzVmFycykge1xuICAgIHgudGhpc1ZhcnMgPSBbXVxuICB9XG4gIGlmKCF4LmxvY2FsVmFycykge1xuICAgIHgubG9jYWxWYXJzID0gW11cbiAgfVxuICByZXR1cm4geFxufVxuXG5mdW5jdGlvbiBwY29tcGlsZSh1c2VyX2FyZ3MpIHtcbiAgcmV0dXJuIGNvbXBpbGUoe1xuICAgIGFyZ3M6ICAgICB1c2VyX2FyZ3MuYXJncyxcbiAgICBwcmU6ICAgICAgZml4dXAodXNlcl9hcmdzLnByZSksXG4gICAgYm9keTogICAgIGZpeHVwKHVzZXJfYXJncy5ib2R5KSxcbiAgICBwb3N0OiAgICAgZml4dXAodXNlcl9hcmdzLnByb2MpLFxuICAgIGZ1bmNOYW1lOiB1c2VyX2FyZ3MuZnVuY05hbWVcbiAgfSlcbn1cblxuZnVuY3Rpb24gbWFrZU9wKHVzZXJfYXJncykge1xuICB2YXIgYXJncyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPHVzZXJfYXJncy5hcmdzLmxlbmd0aDsgKytpKSB7XG4gICAgYXJncy5wdXNoKFwiYVwiK2kpXG4gIH1cbiAgdmFyIHdyYXBwZXIgPSBuZXcgRnVuY3Rpb24oXCJQXCIsIFtcbiAgICBcInJldHVybiBmdW5jdGlvbiBcIiwgdXNlcl9hcmdzLmZ1bmNOYW1lLCBcIl9uZGFycmF5b3BzKFwiLCBhcmdzLmpvaW4oXCIsXCIpLCBcIikge1AoXCIsIGFyZ3Muam9pbihcIixcIiksIFwiKTtyZXR1cm4gYTB9XCJcbiAgXS5qb2luKFwiXCIpKVxuICByZXR1cm4gd3JhcHBlcihwY29tcGlsZSh1c2VyX2FyZ3MpKVxufVxuXG52YXIgYXNzaWduX29wcyA9IHtcbiAgYWRkOiAgXCIrXCIsXG4gIHN1YjogIFwiLVwiLFxuICBtdWw6ICBcIipcIixcbiAgZGl2OiAgXCIvXCIsXG4gIG1vZDogIFwiJVwiLFxuICBiYW5kOiBcIiZcIixcbiAgYm9yOiAgXCJ8XCIsXG4gIGJ4b3I6IFwiXlwiLFxuICBsc2hpZnQ6IFwiPDxcIixcbiAgcnNoaWZ0OiBcIj4+XCIsXG4gIHJyc2hpZnQ6IFwiPj4+XCJcbn1cbjsoZnVuY3Rpb24oKXtcbiAgZm9yKHZhciBpZCBpbiBhc3NpZ25fb3BzKSB7XG4gICAgdmFyIG9wID0gYXNzaWduX29wc1tpZF1cbiAgICBleHBvcnRzW2lkXSA9IG1ha2VPcCh7XG4gICAgICBhcmdzOiBbXCJhcnJheVwiLFwiYXJyYXlcIixcImFycmF5XCJdLFxuICAgICAgYm9keToge2FyZ3M6W1wiYVwiLFwiYlwiLFwiY1wiXSxcbiAgICAgICAgICAgICBib2R5OiBcImE9YlwiK29wK1wiY1wifSxcbiAgICAgIGZ1bmNOYW1lOiBpZFxuICAgIH0pXG4gICAgZXhwb3J0c1tpZCtcImVxXCJdID0gbWFrZU9wKHtcbiAgICAgIGFyZ3M6IFtcImFycmF5XCIsXCJhcnJheVwiXSxcbiAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIl0sXG4gICAgICAgICAgICAgYm9keTpcImFcIitvcCtcIj1iXCJ9LFxuICAgICAgcnZhbHVlOiB0cnVlLFxuICAgICAgZnVuY05hbWU6IGlkK1wiZXFcIlxuICAgIH0pXG4gICAgZXhwb3J0c1tpZCtcInNcIl0gPSBtYWtlT3Aoe1xuICAgICAgYXJnczogW1wiYXJyYXlcIiwgXCJhcnJheVwiLCBcInNjYWxhclwiXSxcbiAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIixcInNcIl0sXG4gICAgICAgICAgICAgYm9keTpcImE9YlwiK29wK1wic1wifSxcbiAgICAgIGZ1bmNOYW1lOiBpZCtcInNcIlxuICAgIH0pXG4gICAgZXhwb3J0c1tpZCtcInNlcVwiXSA9IG1ha2VPcCh7XG4gICAgICBhcmdzOiBbXCJhcnJheVwiLFwic2NhbGFyXCJdLFxuICAgICAgYm9keToge2FyZ3M6W1wiYVwiLFwic1wiXSxcbiAgICAgICAgICAgICBib2R5OlwiYVwiK29wK1wiPXNcIn0sXG4gICAgICBydmFsdWU6IHRydWUsXG4gICAgICBmdW5jTmFtZTogaWQrXCJzZXFcIlxuICAgIH0pXG4gIH1cbn0pKCk7XG5cbnZhciB1bmFyeV9vcHMgPSB7XG4gIG5vdDogXCIhXCIsXG4gIGJub3Q6IFwiflwiLFxuICBuZWc6IFwiLVwiLFxuICByZWNpcDogXCIxLjAvXCJcbn1cbjsoZnVuY3Rpb24oKXtcbiAgZm9yKHZhciBpZCBpbiB1bmFyeV9vcHMpIHtcbiAgICB2YXIgb3AgPSB1bmFyeV9vcHNbaWRdXG4gICAgZXhwb3J0c1tpZF0gPSBtYWtlT3Aoe1xuICAgICAgYXJnczogW1wiYXJyYXlcIiwgXCJhcnJheVwiXSxcbiAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIl0sXG4gICAgICAgICAgICAgYm9keTpcImE9XCIrb3ArXCJiXCJ9LFxuICAgICAgZnVuY05hbWU6IGlkXG4gICAgfSlcbiAgICBleHBvcnRzW2lkK1wiZXFcIl0gPSBtYWtlT3Aoe1xuICAgICAgYXJnczogW1wiYXJyYXlcIl0sXG4gICAgICBib2R5OiB7YXJnczpbXCJhXCJdLFxuICAgICAgICAgICAgIGJvZHk6XCJhPVwiK29wK1wiYVwifSxcbiAgICAgIHJ2YWx1ZTogdHJ1ZSxcbiAgICAgIGNvdW50OiAyLFxuICAgICAgZnVuY05hbWU6IGlkK1wiZXFcIlxuICAgIH0pXG4gIH1cbn0pKCk7XG5cbnZhciBiaW5hcnlfb3BzID0ge1xuICBhbmQ6IFwiJiZcIixcbiAgb3I6IFwifHxcIixcbiAgZXE6IFwiPT09XCIsXG4gIG5lcTogXCIhPT1cIixcbiAgbHQ6IFwiPFwiLFxuICBndDogXCI+XCIsXG4gIGxlcTogXCI8PVwiLFxuICBnZXE6IFwiPj1cIlxufVxuOyhmdW5jdGlvbigpIHtcbiAgZm9yKHZhciBpZCBpbiBiaW5hcnlfb3BzKSB7XG4gICAgdmFyIG9wID0gYmluYXJ5X29wc1tpZF1cbiAgICBleHBvcnRzW2lkXSA9IG1ha2VPcCh7XG4gICAgICBhcmdzOiBbXCJhcnJheVwiLFwiYXJyYXlcIixcImFycmF5XCJdLFxuICAgICAgYm9keToge2FyZ3M6W1wiYVwiLCBcImJcIiwgXCJjXCJdLFxuICAgICAgICAgICAgIGJvZHk6XCJhPWJcIitvcCtcImNcIn0sXG4gICAgICBmdW5jTmFtZTogaWRcbiAgICB9KVxuICAgIGV4cG9ydHNbaWQrXCJzXCJdID0gbWFrZU9wKHtcbiAgICAgIGFyZ3M6IFtcImFycmF5XCIsXCJhcnJheVwiLFwic2NhbGFyXCJdLFxuICAgICAgYm9keToge2FyZ3M6W1wiYVwiLCBcImJcIiwgXCJzXCJdLFxuICAgICAgICAgICAgIGJvZHk6XCJhPWJcIitvcCtcInNcIn0sXG4gICAgICBmdW5jTmFtZTogaWQrXCJzXCJcbiAgICB9KVxuICAgIGV4cG9ydHNbaWQrXCJlcVwiXSA9IG1ha2VPcCh7XG4gICAgICBhcmdzOiBbXCJhcnJheVwiLCBcImFycmF5XCJdLFxuICAgICAgYm9keToge2FyZ3M6W1wiYVwiLCBcImJcIl0sXG4gICAgICAgICAgICAgYm9keTpcImE9YVwiK29wK1wiYlwifSxcbiAgICAgIHJ2YWx1ZTp0cnVlLFxuICAgICAgY291bnQ6MixcbiAgICAgIGZ1bmNOYW1lOiBpZCtcImVxXCJcbiAgICB9KVxuICAgIGV4cG9ydHNbaWQrXCJzZXFcIl0gPSBtYWtlT3Aoe1xuICAgICAgYXJnczogW1wiYXJyYXlcIiwgXCJzY2FsYXJcIl0sXG4gICAgICBib2R5OiB7YXJnczpbXCJhXCIsXCJzXCJdLFxuICAgICAgICAgICAgIGJvZHk6XCJhPWFcIitvcCtcInNcIn0sXG4gICAgICBydmFsdWU6dHJ1ZSxcbiAgICAgIGNvdW50OjIsXG4gICAgICBmdW5jTmFtZTogaWQrXCJzZXFcIlxuICAgIH0pXG4gIH1cbn0pKCk7XG5cbnZhciBtYXRoX3VuYXJ5ID0gW1xuICBcImFic1wiLFxuICBcImFjb3NcIixcbiAgXCJhc2luXCIsXG4gIFwiYXRhblwiLFxuICBcImNlaWxcIixcbiAgXCJjb3NcIixcbiAgXCJleHBcIixcbiAgXCJmbG9vclwiLFxuICBcImxvZ1wiLFxuICBcInJvdW5kXCIsXG4gIFwic2luXCIsXG4gIFwic3FydFwiLFxuICBcInRhblwiXG5dXG47KGZ1bmN0aW9uKCkge1xuICBmb3IodmFyIGk9MDsgaTxtYXRoX3VuYXJ5Lmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGYgPSBtYXRoX3VuYXJ5W2ldXG4gICAgZXhwb3J0c1tmXSA9IG1ha2VPcCh7XG4gICAgICAgICAgICAgICAgICAgIGFyZ3M6IFtcImFycmF5XCIsIFwiYXJyYXlcIl0sXG4gICAgICAgICAgICAgICAgICAgIHByZToge2FyZ3M6W10sIGJvZHk6XCJ0aGlzX2Y9TWF0aC5cIitmLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgICBib2R5OiB7YXJnczpbXCJhXCIsXCJiXCJdLCBib2R5OlwiYT10aGlzX2YoYilcIiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgICAgZnVuY05hbWU6IGZcbiAgICAgICAgICAgICAgICAgIH0pXG4gICAgZXhwb3J0c1tmK1wiZXFcIl0gPSBtYWtlT3Aoe1xuICAgICAgICAgICAgICAgICAgICAgIGFyZ3M6IFtcImFycmF5XCJdLFxuICAgICAgICAgICAgICAgICAgICAgIHByZToge2FyZ3M6W10sIGJvZHk6XCJ0aGlzX2Y9TWF0aC5cIitmLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgICAgIGJvZHk6IHthcmdzOiBbXCJhXCJdLCBib2R5OlwiYT10aGlzX2YoYSlcIiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgICAgICBydmFsdWU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgY291bnQ6IDIsXG4gICAgICAgICAgICAgICAgICAgICAgZnVuY05hbWU6IGYrXCJlcVwiXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gIH1cbn0pKCk7XG5cbnZhciBtYXRoX2NvbW0gPSBbXG4gIFwibWF4XCIsXG4gIFwibWluXCIsXG4gIFwiYXRhbjJcIixcbiAgXCJwb3dcIlxuXVxuOyhmdW5jdGlvbigpe1xuICBmb3IodmFyIGk9MDsgaTxtYXRoX2NvbW0ubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgZj0gbWF0aF9jb21tW2ldXG4gICAgZXhwb3J0c1tmXSA9IG1ha2VPcCh7XG4gICAgICAgICAgICAgICAgICBhcmdzOltcImFycmF5XCIsIFwiYXJyYXlcIiwgXCJhcnJheVwiXSxcbiAgICAgICAgICAgICAgICAgIHByZToge2FyZ3M6W10sIGJvZHk6XCJ0aGlzX2Y9TWF0aC5cIitmLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgYm9keToge2FyZ3M6W1wiYVwiLFwiYlwiLFwiY1wiXSwgYm9keTpcImE9dGhpc19mKGIsYylcIiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIGZ1bmNOYW1lOiBmXG4gICAgICAgICAgICAgICAgfSlcbiAgICBleHBvcnRzW2YrXCJzXCJdID0gbWFrZU9wKHtcbiAgICAgICAgICAgICAgICAgIGFyZ3M6W1wiYXJyYXlcIiwgXCJhcnJheVwiLCBcInNjYWxhclwiXSxcbiAgICAgICAgICAgICAgICAgIHByZToge2FyZ3M6W10sIGJvZHk6XCJ0aGlzX2Y9TWF0aC5cIitmLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgYm9keToge2FyZ3M6W1wiYVwiLFwiYlwiLFwiY1wiXSwgYm9keTpcImE9dGhpc19mKGIsYylcIiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIGZ1bmNOYW1lOiBmK1wic1wiXG4gICAgICAgICAgICAgICAgICB9KVxuICAgIGV4cG9ydHNbZitcImVxXCJdID0gbWFrZU9wKHsgYXJnczpbXCJhcnJheVwiLCBcImFycmF5XCJdLFxuICAgICAgICAgICAgICAgICAgcHJlOiB7YXJnczpbXSwgYm9keTpcInRoaXNfZj1NYXRoLlwiK2YsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBib2R5OiB7YXJnczpbXCJhXCIsXCJiXCJdLCBib2R5OlwiYT10aGlzX2YoYSxiKVwiLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgcnZhbHVlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgY291bnQ6IDIsXG4gICAgICAgICAgICAgICAgICBmdW5jTmFtZTogZitcImVxXCJcbiAgICAgICAgICAgICAgICAgIH0pXG4gICAgZXhwb3J0c1tmK1wic2VxXCJdID0gbWFrZU9wKHsgYXJnczpbXCJhcnJheVwiLCBcInNjYWxhclwiXSxcbiAgICAgICAgICAgICAgICAgIHByZToge2FyZ3M6W10sIGJvZHk6XCJ0aGlzX2Y9TWF0aC5cIitmLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgYm9keToge2FyZ3M6W1wiYVwiLFwiYlwiXSwgYm9keTpcImE9dGhpc19mKGEsYilcIiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIHJ2YWx1ZTp0cnVlLFxuICAgICAgICAgICAgICAgICAgY291bnQ6MixcbiAgICAgICAgICAgICAgICAgIGZ1bmNOYW1lOiBmK1wic2VxXCJcbiAgICAgICAgICAgICAgICAgIH0pXG4gIH1cbn0pKCk7XG5cbnZhciBtYXRoX25vbmNvbW0gPSBbXG4gIFwiYXRhbjJcIixcbiAgXCJwb3dcIlxuXVxuOyhmdW5jdGlvbigpe1xuICBmb3IodmFyIGk9MDsgaTxtYXRoX25vbmNvbW0ubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgZj0gbWF0aF9ub25jb21tW2ldXG4gICAgZXhwb3J0c1tmK1wib3BcIl0gPSBtYWtlT3Aoe1xuICAgICAgICAgICAgICAgICAgYXJnczpbXCJhcnJheVwiLCBcImFycmF5XCIsIFwiYXJyYXlcIl0sXG4gICAgICAgICAgICAgICAgICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGguXCIrZiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIixcImNcIl0sIGJvZHk6XCJhPXRoaXNfZihjLGIpXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBmdW5jTmFtZTogZitcIm9wXCJcbiAgICAgICAgICAgICAgICB9KVxuICAgIGV4cG9ydHNbZitcIm9wc1wiXSA9IG1ha2VPcCh7XG4gICAgICAgICAgICAgICAgICBhcmdzOltcImFycmF5XCIsIFwiYXJyYXlcIiwgXCJzY2FsYXJcIl0sXG4gICAgICAgICAgICAgICAgICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGguXCIrZiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIixcImNcIl0sIGJvZHk6XCJhPXRoaXNfZihjLGIpXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBmdW5jTmFtZTogZitcIm9wc1wiXG4gICAgICAgICAgICAgICAgICB9KVxuICAgIGV4cG9ydHNbZitcIm9wZXFcIl0gPSBtYWtlT3AoeyBhcmdzOltcImFycmF5XCIsIFwiYXJyYXlcIl0sXG4gICAgICAgICAgICAgICAgICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGguXCIrZiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIGJvZHk6IHthcmdzOltcImFcIixcImJcIl0sIGJvZHk6XCJhPXRoaXNfZihiLGEpXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gICAgICAgICAgICAgICAgICBydmFsdWU6IHRydWUsXG4gICAgICAgICAgICAgICAgICBjb3VudDogMixcbiAgICAgICAgICAgICAgICAgIGZ1bmNOYW1lOiBmK1wib3BlcVwiXG4gICAgICAgICAgICAgICAgICB9KVxuICAgIGV4cG9ydHNbZitcIm9wc2VxXCJdID0gbWFrZU9wKHsgYXJnczpbXCJhcnJheVwiLCBcInNjYWxhclwiXSxcbiAgICAgICAgICAgICAgICAgIHByZToge2FyZ3M6W10sIGJvZHk6XCJ0aGlzX2Y9TWF0aC5cIitmLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICAgICAgICAgICAgICAgICAgYm9keToge2FyZ3M6W1wiYVwiLFwiYlwiXSwgYm9keTpcImE9dGhpc19mKGIsYSlcIiwgdGhpc1ZhcnM6W1widGhpc19mXCJdfSxcbiAgICAgICAgICAgICAgICAgIHJ2YWx1ZTp0cnVlLFxuICAgICAgICAgICAgICAgICAgY291bnQ6MixcbiAgICAgICAgICAgICAgICAgIGZ1bmNOYW1lOiBmK1wib3BzZXFcIlxuICAgICAgICAgICAgICAgICAgfSlcbiAgfVxufSkoKTtcblxuZXhwb3J0cy5hbnkgPSBjb21waWxlKHtcbiAgYXJnczpbXCJhcnJheVwiXSxcbiAgcHJlOiBFbXB0eVByb2MsXG4gIGJvZHk6IHthcmdzOlt7bmFtZTpcImFcIiwgbHZhbHVlOmZhbHNlLCBydmFsdWU6dHJ1ZSwgY291bnQ6MX1dLCBib2R5OiBcImlmKGEpe3JldHVybiB0cnVlfVwiLCBsb2NhbFZhcnM6IFtdLCB0aGlzVmFyczogW119LFxuICBwb3N0OiB7YXJnczpbXSwgbG9jYWxWYXJzOltdLCB0aGlzVmFyczpbXSwgYm9keTpcInJldHVybiBmYWxzZVwifSxcbiAgZnVuY05hbWU6IFwiYW55XCJcbn0pXG5cbmV4cG9ydHMuYWxsID0gY29tcGlsZSh7XG4gIGFyZ3M6W1wiYXJyYXlcIl0sXG4gIHByZTogRW1wdHlQcm9jLFxuICBib2R5OiB7YXJnczpbe25hbWU6XCJ4XCIsIGx2YWx1ZTpmYWxzZSwgcnZhbHVlOnRydWUsIGNvdW50OjF9XSwgYm9keTogXCJpZigheCl7cmV0dXJuIGZhbHNlfVwiLCBsb2NhbFZhcnM6IFtdLCB0aGlzVmFyczogW119LFxuICBwb3N0OiB7YXJnczpbXSwgbG9jYWxWYXJzOltdLCB0aGlzVmFyczpbXSwgYm9keTpcInJldHVybiB0cnVlXCJ9LFxuICBmdW5jTmFtZTogXCJhbGxcIlxufSlcblxuZXhwb3J0cy5zdW0gPSBjb21waWxlKHtcbiAgYXJnczpbXCJhcnJheVwiXSxcbiAgcHJlOiB7YXJnczpbXSwgbG9jYWxWYXJzOltdLCB0aGlzVmFyczpbXCJ0aGlzX3NcIl0sIGJvZHk6XCJ0aGlzX3M9MFwifSxcbiAgYm9keToge2FyZ3M6W3tuYW1lOlwiYVwiLCBsdmFsdWU6ZmFsc2UsIHJ2YWx1ZTp0cnVlLCBjb3VudDoxfV0sIGJvZHk6IFwidGhpc19zKz1hXCIsIGxvY2FsVmFyczogW10sIHRoaXNWYXJzOiBbXCJ0aGlzX3NcIl19LFxuICBwb3N0OiB7YXJnczpbXSwgbG9jYWxWYXJzOltdLCB0aGlzVmFyczpbXCJ0aGlzX3NcIl0sIGJvZHk6XCJyZXR1cm4gdGhpc19zXCJ9LFxuICBmdW5jTmFtZTogXCJzdW1cIlxufSlcblxuZXhwb3J0cy5wcm9kID0gY29tcGlsZSh7XG4gIGFyZ3M6W1wiYXJyYXlcIl0sXG4gIHByZToge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwidGhpc19zPTFcIn0sXG4gIGJvZHk6IHthcmdzOlt7bmFtZTpcImFcIiwgbHZhbHVlOmZhbHNlLCBydmFsdWU6dHJ1ZSwgY291bnQ6MX1dLCBib2R5OiBcInRoaXNfcyo9YVwiLCBsb2NhbFZhcnM6IFtdLCB0aGlzVmFyczogW1widGhpc19zXCJdfSxcbiAgcG9zdDoge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwicmV0dXJuIHRoaXNfc1wifSxcbiAgZnVuY05hbWU6IFwicHJvZFwiXG59KVxuXG5leHBvcnRzLm5vcm0yc3F1YXJlZCA9IGNvbXBpbGUoe1xuICBhcmdzOltcImFycmF5XCJdLFxuICBwcmU6IHthcmdzOltdLCBsb2NhbFZhcnM6W10sIHRoaXNWYXJzOltcInRoaXNfc1wiXSwgYm9keTpcInRoaXNfcz0wXCJ9LFxuICBib2R5OiB7YXJnczpbe25hbWU6XCJhXCIsIGx2YWx1ZTpmYWxzZSwgcnZhbHVlOnRydWUsIGNvdW50OjJ9XSwgYm9keTogXCJ0aGlzX3MrPWEqYVwiLCBsb2NhbFZhcnM6IFtdLCB0aGlzVmFyczogW1widGhpc19zXCJdfSxcbiAgcG9zdDoge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwicmV0dXJuIHRoaXNfc1wifSxcbiAgZnVuY05hbWU6IFwibm9ybTJzcXVhcmVkXCJcbn0pXG4gIFxuZXhwb3J0cy5ub3JtMiA9IGNvbXBpbGUoe1xuICBhcmdzOltcImFycmF5XCJdLFxuICBwcmU6IHthcmdzOltdLCBsb2NhbFZhcnM6W10sIHRoaXNWYXJzOltcInRoaXNfc1wiXSwgYm9keTpcInRoaXNfcz0wXCJ9LFxuICBib2R5OiB7YXJnczpbe25hbWU6XCJhXCIsIGx2YWx1ZTpmYWxzZSwgcnZhbHVlOnRydWUsIGNvdW50OjJ9XSwgYm9keTogXCJ0aGlzX3MrPWEqYVwiLCBsb2NhbFZhcnM6IFtdLCB0aGlzVmFyczogW1widGhpc19zXCJdfSxcbiAgcG9zdDoge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwicmV0dXJuIE1hdGguc3FydCh0aGlzX3MpXCJ9LFxuICBmdW5jTmFtZTogXCJub3JtMlwiXG59KVxuICBcblxuZXhwb3J0cy5ub3JtaW5mID0gY29tcGlsZSh7XG4gIGFyZ3M6W1wiYXJyYXlcIl0sXG4gIHByZToge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwidGhpc19zPTBcIn0sXG4gIGJvZHk6IHthcmdzOlt7bmFtZTpcImFcIiwgbHZhbHVlOmZhbHNlLCBydmFsdWU6dHJ1ZSwgY291bnQ6NH1dLCBib2R5OlwiaWYoLWE+dGhpc19zKXt0aGlzX3M9LWF9ZWxzZSBpZihhPnRoaXNfcyl7dGhpc19zPWF9XCIsIGxvY2FsVmFyczogW10sIHRoaXNWYXJzOiBbXCJ0aGlzX3NcIl19LFxuICBwb3N0OiB7YXJnczpbXSwgbG9jYWxWYXJzOltdLCB0aGlzVmFyczpbXCJ0aGlzX3NcIl0sIGJvZHk6XCJyZXR1cm4gdGhpc19zXCJ9LFxuICBmdW5jTmFtZTogXCJub3JtaW5mXCJcbn0pXG5cbmV4cG9ydHMubm9ybTEgPSBjb21waWxlKHtcbiAgYXJnczpbXCJhcnJheVwiXSxcbiAgcHJlOiB7YXJnczpbXSwgbG9jYWxWYXJzOltdLCB0aGlzVmFyczpbXCJ0aGlzX3NcIl0sIGJvZHk6XCJ0aGlzX3M9MFwifSxcbiAgYm9keToge2FyZ3M6W3tuYW1lOlwiYVwiLCBsdmFsdWU6ZmFsc2UsIHJ2YWx1ZTp0cnVlLCBjb3VudDozfV0sIGJvZHk6IFwidGhpc19zKz1hPDA/LWE6YVwiLCBsb2NhbFZhcnM6IFtdLCB0aGlzVmFyczogW1widGhpc19zXCJdfSxcbiAgcG9zdDoge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W1widGhpc19zXCJdLCBib2R5OlwicmV0dXJuIHRoaXNfc1wifSxcbiAgZnVuY05hbWU6IFwibm9ybTFcIlxufSlcblxuZXhwb3J0cy5zdXAgPSBjb21waWxlKHtcbiAgYXJnczogWyBcImFycmF5XCIgXSxcbiAgcHJlOlxuICAgeyBib2R5OiBcInRoaXNfaD0tSW5maW5pdHlcIixcbiAgICAgYXJnczogW10sXG4gICAgIHRoaXNWYXJzOiBbIFwidGhpc19oXCIgXSxcbiAgICAgbG9jYWxWYXJzOiBbXSB9LFxuICBib2R5OlxuICAgeyBib2R5OiBcImlmKF9pbmxpbmVfMV9hcmcwXz50aGlzX2gpdGhpc19oPV9pbmxpbmVfMV9hcmcwX1wiLFxuICAgICBhcmdzOiBbe1wibmFtZVwiOlwiX2lubGluZV8xX2FyZzBfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjJ9IF0sXG4gICAgIHRoaXNWYXJzOiBbIFwidGhpc19oXCIgXSxcbiAgICAgbG9jYWxWYXJzOiBbXSB9LFxuICBwb3N0OlxuICAgeyBib2R5OiBcInJldHVybiB0aGlzX2hcIixcbiAgICAgYXJnczogW10sXG4gICAgIHRoaXNWYXJzOiBbIFwidGhpc19oXCIgXSxcbiAgICAgbG9jYWxWYXJzOiBbXSB9XG4gfSlcblxuZXhwb3J0cy5pbmYgPSBjb21waWxlKHtcbiAgYXJnczogWyBcImFycmF5XCIgXSxcbiAgcHJlOlxuICAgeyBib2R5OiBcInRoaXNfaD1JbmZpbml0eVwiLFxuICAgICBhcmdzOiBbXSxcbiAgICAgdGhpc1ZhcnM6IFsgXCJ0aGlzX2hcIiBdLFxuICAgICBsb2NhbFZhcnM6IFtdIH0sXG4gIGJvZHk6XG4gICB7IGJvZHk6IFwiaWYoX2lubGluZV8xX2FyZzBfPHRoaXNfaCl0aGlzX2g9X2lubGluZV8xX2FyZzBfXCIsXG4gICAgIGFyZ3M6IFt7XCJuYW1lXCI6XCJfaW5saW5lXzFfYXJnMF9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6Mn0gXSxcbiAgICAgdGhpc1ZhcnM6IFsgXCJ0aGlzX2hcIiBdLFxuICAgICBsb2NhbFZhcnM6IFtdIH0sXG4gIHBvc3Q6XG4gICB7IGJvZHk6IFwicmV0dXJuIHRoaXNfaFwiLFxuICAgICBhcmdzOiBbXSxcbiAgICAgdGhpc1ZhcnM6IFsgXCJ0aGlzX2hcIiBdLFxuICAgICBsb2NhbFZhcnM6IFtdIH1cbiB9KVxuXG5leHBvcnRzLmFyZ21pbiA9IGNvbXBpbGUoe1xuICBhcmdzOltcImluZGV4XCIsXCJhcnJheVwiLFwic2hhcGVcIl0sXG4gIHByZTp7XG4gICAgYm9keTpcInt0aGlzX3Y9SW5maW5pdHk7dGhpc19pPV9pbmxpbmVfMF9hcmcyXy5zbGljZSgwKX1cIixcbiAgICBhcmdzOltcbiAgICAgIHtuYW1lOlwiX2lubGluZV8wX2FyZzBfXCIsbHZhbHVlOmZhbHNlLHJ2YWx1ZTpmYWxzZSxjb3VudDowfSxcbiAgICAgIHtuYW1lOlwiX2lubGluZV8wX2FyZzFfXCIsbHZhbHVlOmZhbHNlLHJ2YWx1ZTpmYWxzZSxjb3VudDowfSxcbiAgICAgIHtuYW1lOlwiX2lubGluZV8wX2FyZzJfXCIsbHZhbHVlOmZhbHNlLHJ2YWx1ZTp0cnVlLGNvdW50OjF9XG4gICAgICBdLFxuICAgIHRoaXNWYXJzOltcInRoaXNfaVwiLFwidGhpc192XCJdLFxuICAgIGxvY2FsVmFyczpbXX0sXG4gIGJvZHk6e1xuICAgIGJvZHk6XCJ7aWYoX2lubGluZV8xX2FyZzFfPHRoaXNfdil7dGhpc192PV9pbmxpbmVfMV9hcmcxXztmb3IodmFyIF9pbmxpbmVfMV9rPTA7X2lubGluZV8xX2s8X2lubGluZV8xX2FyZzBfLmxlbmd0aDsrK19pbmxpbmVfMV9rKXt0aGlzX2lbX2lubGluZV8xX2tdPV9pbmxpbmVfMV9hcmcwX1tfaW5saW5lXzFfa119fX1cIixcbiAgICBhcmdzOltcbiAgICAgIHtuYW1lOlwiX2lubGluZV8xX2FyZzBfXCIsbHZhbHVlOmZhbHNlLHJ2YWx1ZTp0cnVlLGNvdW50OjJ9LFxuICAgICAge25hbWU6XCJfaW5saW5lXzFfYXJnMV9cIixsdmFsdWU6ZmFsc2UscnZhbHVlOnRydWUsY291bnQ6Mn1dLFxuICAgIHRoaXNWYXJzOltcInRoaXNfaVwiLFwidGhpc192XCJdLFxuICAgIGxvY2FsVmFyczpbXCJfaW5saW5lXzFfa1wiXX0sXG4gIHBvc3Q6e1xuICAgIGJvZHk6XCJ7cmV0dXJuIHRoaXNfaX1cIixcbiAgICBhcmdzOltdLFxuICAgIHRoaXNWYXJzOltcInRoaXNfaVwiXSxcbiAgICBsb2NhbFZhcnM6W119XG59KVxuXG5leHBvcnRzLmFyZ21heCA9IGNvbXBpbGUoe1xuICBhcmdzOltcImluZGV4XCIsXCJhcnJheVwiLFwic2hhcGVcIl0sXG4gIHByZTp7XG4gICAgYm9keTpcInt0aGlzX3Y9LUluZmluaXR5O3RoaXNfaT1faW5saW5lXzBfYXJnMl8uc2xpY2UoMCl9XCIsXG4gICAgYXJnczpbXG4gICAgICB7bmFtZTpcIl9pbmxpbmVfMF9hcmcwX1wiLGx2YWx1ZTpmYWxzZSxydmFsdWU6ZmFsc2UsY291bnQ6MH0sXG4gICAgICB7bmFtZTpcIl9pbmxpbmVfMF9hcmcxX1wiLGx2YWx1ZTpmYWxzZSxydmFsdWU6ZmFsc2UsY291bnQ6MH0sXG4gICAgICB7bmFtZTpcIl9pbmxpbmVfMF9hcmcyX1wiLGx2YWx1ZTpmYWxzZSxydmFsdWU6dHJ1ZSxjb3VudDoxfVxuICAgICAgXSxcbiAgICB0aGlzVmFyczpbXCJ0aGlzX2lcIixcInRoaXNfdlwiXSxcbiAgICBsb2NhbFZhcnM6W119LFxuICBib2R5OntcbiAgICBib2R5Olwie2lmKF9pbmxpbmVfMV9hcmcxXz50aGlzX3Ype3RoaXNfdj1faW5saW5lXzFfYXJnMV87Zm9yKHZhciBfaW5saW5lXzFfaz0wO19pbmxpbmVfMV9rPF9pbmxpbmVfMV9hcmcwXy5sZW5ndGg7KytfaW5saW5lXzFfayl7dGhpc19pW19pbmxpbmVfMV9rXT1faW5saW5lXzFfYXJnMF9bX2lubGluZV8xX2tdfX19XCIsXG4gICAgYXJnczpbXG4gICAgICB7bmFtZTpcIl9pbmxpbmVfMV9hcmcwX1wiLGx2YWx1ZTpmYWxzZSxydmFsdWU6dHJ1ZSxjb3VudDoyfSxcbiAgICAgIHtuYW1lOlwiX2lubGluZV8xX2FyZzFfXCIsbHZhbHVlOmZhbHNlLHJ2YWx1ZTp0cnVlLGNvdW50OjJ9XSxcbiAgICB0aGlzVmFyczpbXCJ0aGlzX2lcIixcInRoaXNfdlwiXSxcbiAgICBsb2NhbFZhcnM6W1wiX2lubGluZV8xX2tcIl19LFxuICBwb3N0OntcbiAgICBib2R5Olwie3JldHVybiB0aGlzX2l9XCIsXG4gICAgYXJnczpbXSxcbiAgICB0aGlzVmFyczpbXCJ0aGlzX2lcIl0sXG4gICAgbG9jYWxWYXJzOltdfVxufSkgIFxuXG5leHBvcnRzLnJhbmRvbSA9IG1ha2VPcCh7XG4gIGFyZ3M6IFtcImFycmF5XCJdLFxuICBwcmU6IHthcmdzOltdLCBib2R5OlwidGhpc19mPU1hdGgucmFuZG9tXCIsIHRoaXNWYXJzOltcInRoaXNfZlwiXX0sXG4gIGJvZHk6IHthcmdzOiBbXCJhXCJdLCBib2R5OlwiYT10aGlzX2YoKVwiLCB0aGlzVmFyczpbXCJ0aGlzX2ZcIl19LFxuICBmdW5jTmFtZTogXCJyYW5kb21cIlxufSlcblxuZXhwb3J0cy5hc3NpZ24gPSBtYWtlT3Aoe1xuICBhcmdzOltcImFycmF5XCIsIFwiYXJyYXlcIl0sXG4gIGJvZHk6IHthcmdzOltcImFcIiwgXCJiXCJdLCBib2R5OlwiYT1iXCJ9LFxuICBmdW5jTmFtZTogXCJhc3NpZ25cIiB9KVxuXG5leHBvcnRzLmFzc2lnbnMgPSBtYWtlT3Aoe1xuICBhcmdzOltcImFycmF5XCIsIFwic2NhbGFyXCJdLFxuICBib2R5OiB7YXJnczpbXCJhXCIsIFwiYlwiXSwgYm9keTpcImE9YlwifSxcbiAgZnVuY05hbWU6IFwiYXNzaWduc1wiIH0pXG5cblxuZXhwb3J0cy5lcXVhbHMgPSBjb21waWxlKHtcbiAgYXJnczpbXCJhcnJheVwiLCBcImFycmF5XCJdLFxuICBwcmU6IEVtcHR5UHJvYyxcbiAgYm9keToge2FyZ3M6W3tuYW1lOlwieFwiLCBsdmFsdWU6ZmFsc2UsIHJ2YWx1ZTp0cnVlLCBjb3VudDoxfSxcbiAgICAgICAgICAgICAgIHtuYW1lOlwieVwiLCBsdmFsdWU6ZmFsc2UsIHJ2YWx1ZTp0cnVlLCBjb3VudDoxfV0sIFxuICAgICAgICBib2R5OiBcImlmKHghPT15KXtyZXR1cm4gZmFsc2V9XCIsIFxuICAgICAgICBsb2NhbFZhcnM6IFtdLCBcbiAgICAgICAgdGhpc1ZhcnM6IFtdfSxcbiAgcG9zdDoge2FyZ3M6W10sIGxvY2FsVmFyczpbXSwgdGhpc1ZhcnM6W10sIGJvZHk6XCJyZXR1cm4gdHJ1ZVwifSxcbiAgZnVuY05hbWU6IFwiZXF1YWxzXCJcbn0pXG5cblxuXG59LHtcImN3aXNlLWNvbXBpbGVyXCI6MTQ2fV0sNDQ1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciBuZGFycmF5ID0gX2RlcmVxXyhcIm5kYXJyYXlcIilcbnZhciBkb19jb252ZXJ0ID0gX2RlcmVxXyhcIi4vZG9Db252ZXJ0LmpzXCIpXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29udmVydChhcnIsIHJlc3VsdCkge1xuICB2YXIgc2hhcGUgPSBbXSwgYyA9IGFyciwgc3ogPSAxXG4gIHdoaWxlKEFycmF5LmlzQXJyYXkoYykpIHtcbiAgICBzaGFwZS5wdXNoKGMubGVuZ3RoKVxuICAgIHN6ICo9IGMubGVuZ3RoXG4gICAgYyA9IGNbMF1cbiAgfVxuICBpZihzaGFwZS5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbmRhcnJheSgpXG4gIH1cbiAgaWYoIXJlc3VsdCkge1xuICAgIHJlc3VsdCA9IG5kYXJyYXkobmV3IEZsb2F0NjRBcnJheShzeiksIHNoYXBlKVxuICB9XG4gIGRvX2NvbnZlcnQocmVzdWx0LCBhcnIpXG4gIHJldHVybiByZXN1bHRcbn1cblxufSx7XCIuL2RvQ29udmVydC5qc1wiOjQ0NixcIm5kYXJyYXlcIjo0NTB9XSw0NDY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHM9X2RlcmVxXygnY3dpc2UtY29tcGlsZXInKSh7XCJhcmdzXCI6W1wiYXJyYXlcIixcInNjYWxhclwiLFwiaW5kZXhcIl0sXCJwcmVcIjp7XCJib2R5XCI6XCJ7fVwiLFwiYXJnc1wiOltdLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcImJvZHlcIjp7XCJib2R5XCI6XCJ7XFxudmFyIF9pbmxpbmVfMV92PV9pbmxpbmVfMV9hcmcxXyxfaW5saW5lXzFfaVxcbmZvcihfaW5saW5lXzFfaT0wO19pbmxpbmVfMV9pPF9pbmxpbmVfMV9hcmcyXy5sZW5ndGgtMTsrK19pbmxpbmVfMV9pKSB7XFxuX2lubGluZV8xX3Y9X2lubGluZV8xX3ZbX2lubGluZV8xX2FyZzJfW19pbmxpbmVfMV9pXV1cXG59XFxuX2lubGluZV8xX2FyZzBfPV9pbmxpbmVfMV92W19pbmxpbmVfMV9hcmcyX1tfaW5saW5lXzFfYXJnMl8ubGVuZ3RoLTFdXVxcbn1cIixcImFyZ3NcIjpbe1wibmFtZVwiOlwiX2lubGluZV8xX2FyZzBfXCIsXCJsdmFsdWVcIjp0cnVlLFwicnZhbHVlXCI6ZmFsc2UsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMV9hcmcxX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzFfYXJnMl9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6NH1dLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltcIl9pbmxpbmVfMV9pXCIsXCJfaW5saW5lXzFfdlwiXX0sXCJwb3N0XCI6e1wiYm9keVwiOlwie31cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W10sXCJsb2NhbFZhcnNcIjpbXX0sXCJmdW5jTmFtZVwiOlwiY29udmVydFwiLFwiYmxvY2tTaXplXCI6NjR9KVxuXG59LHtcImN3aXNlLWNvbXBpbGVyXCI6MTQ2fV0sNDQ3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciBwb29sID0gX2RlcmVxXyhcInR5cGVkYXJyYXktcG9vbFwiKVxuXG52YXIgSU5TRVJUSU9OX1NPUlRfVEhSRVNIT0xEID0gMzJcblxuZnVuY3Rpb24gZ2V0TWFsbG9jRnJlZShkdHlwZSkge1xuICBzd2l0Y2goZHR5cGUpIHtcbiAgICBjYXNlIFwidWludDhcIjpcbiAgICAgIHJldHVybiBbcG9vbC5tYWxsb2NVaW50OCwgcG9vbC5mcmVlVWludDhdXG4gICAgY2FzZSBcInVpbnQxNlwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY1VpbnQxNiwgcG9vbC5mcmVlVWludDE2XVxuICAgIGNhc2UgXCJ1aW50MzJcIjpcbiAgICAgIHJldHVybiBbcG9vbC5tYWxsb2NVaW50MzIsIHBvb2wuZnJlZVVpbnQzMl1cbiAgICBjYXNlIFwiaW50OFwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY0ludDgsIHBvb2wuZnJlZUludDhdXG4gICAgY2FzZSBcImludDE2XCI6XG4gICAgICByZXR1cm4gW3Bvb2wubWFsbG9jSW50MTYsIHBvb2wuZnJlZUludDE2XVxuICAgIGNhc2UgXCJpbnQzMlwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY0ludDMyLCBwb29sLmZyZWVJbnQzMl1cbiAgICBjYXNlIFwiZmxvYXQzMlwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY0Zsb2F0LCBwb29sLmZyZWVGbG9hdF1cbiAgICBjYXNlIFwiZmxvYXQ2NFwiOlxuICAgICAgcmV0dXJuIFtwb29sLm1hbGxvY0RvdWJsZSwgcG9vbC5mcmVlRG91YmxlXVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbFxuICB9XG59XG5cbmZ1bmN0aW9uIHNoYXBlQXJncyhkaW1lbnNpb24pIHtcbiAgdmFyIGFyZ3MgPSBbXVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGFyZ3MucHVzaChcInNcIitpKVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgYXJncy5wdXNoKFwiblwiK2kpXG4gIH1cbiAgZm9yKHZhciBpPTE7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBhcmdzLnB1c2goXCJkXCIraSlcbiAgfVxuICBmb3IodmFyIGk9MTsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGFyZ3MucHVzaChcImVcIitpKVxuICB9XG4gIGZvcih2YXIgaT0xOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgYXJncy5wdXNoKFwiZlwiK2kpXG4gIH1cbiAgcmV0dXJuIGFyZ3Ncbn1cblxuZnVuY3Rpb24gY3JlYXRlSW5zZXJ0aW9uU29ydChvcmRlciwgZHR5cGUpIHtcblxuICB2YXIgY29kZSA9IFtcIid1c2Ugc3RyaWN0J1wiXVxuICB2YXIgZnVuY05hbWUgPSBbXCJuZGFycmF5SW5zZXJ0aW9uU29ydFwiLCBvcmRlci5qb2luKFwiZFwiKSwgZHR5cGVdLmpvaW4oXCJcIilcbiAgdmFyIGZ1bmNBcmdzID0gW1wibGVmdFwiLCBcInJpZ2h0XCIsIFwiZGF0YVwiLCBcIm9mZnNldFwiIF0uY29uY2F0KHNoYXBlQXJncyhvcmRlci5sZW5ndGgpKVxuICB2YXIgYWxsb2NhdG9yID0gZ2V0TWFsbG9jRnJlZShkdHlwZSlcbiAgXG4gIHZhciB2YXJzID0gWyBcImksaixjcHRyLHB0cj1sZWZ0KnMwK29mZnNldFwiIF1cbiAgXG4gIGlmKG9yZGVyLmxlbmd0aCA+IDEpIHtcbiAgICB2YXIgc2NyYXRjaF9zaGFwZSA9IFtdXG4gICAgZm9yKHZhciBpPTE7IGk8b3JkZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhcnMucHVzaChcImlcIitpKVxuICAgICAgc2NyYXRjaF9zaGFwZS5wdXNoKFwiblwiK2kpXG4gICAgfVxuICAgIGlmKGFsbG9jYXRvcikge1xuICAgICAgdmFycy5wdXNoKFwic2NyYXRjaD1tYWxsb2MoXCIgKyBzY3JhdGNoX3NoYXBlLmpvaW4oXCIqXCIpICsgXCIpXCIpXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhcnMucHVzaChcInNjcmF0Y2g9bmV3IEFycmF5KFwiK3NjcmF0Y2hfc2hhcGUuam9pbihcIipcIikgKyBcIilcIilcbiAgICB9XG4gICAgdmFycy5wdXNoKFwiZHB0clwiLFwic3B0clwiLFwiYVwiLFwiYlwiKVxuICB9IGVsc2Uge1xuICAgIHZhcnMucHVzaChcInNjcmF0Y2hcIilcbiAgfVxuICBcbiAgZnVuY3Rpb24gZGF0YVJlYWQocHRyKSB7XG4gICAgaWYoZHR5cGUgPT09IFwiZ2VuZXJpY1wiKSB7XG4gICAgICByZXR1cm4gW1wiZGF0YS5nZXQoXCIsIHB0ciwgXCIpXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gICAgcmV0dXJuIFtcImRhdGFbXCIscHRyLFwiXVwiXS5qb2luKFwiXCIpXG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGRhdGFXcml0ZShwdHIsIHYpIHtcbiAgICBpZihkdHlwZSA9PT0gXCJnZW5lcmljXCIpIHtcbiAgICAgIHJldHVybiBbXCJkYXRhLnNldChcIiwgcHRyLCBcIixcIiwgdiwgXCIpXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gICAgcmV0dXJuIFtcImRhdGFbXCIscHRyLFwiXT1cIix2XS5qb2luKFwiXCIpXG4gIH1cbiAgXG4gIC8vQ3JlYXRlIGZ1bmN0aW9uIGhlYWRlclxuICBjb2RlLnB1c2goXG4gICAgW1wiZnVuY3Rpb24gXCIsIGZ1bmNOYW1lLCBcIihcIiwgZnVuY0FyZ3Muam9pbihcIixcIiksIFwiKXt2YXIgXCIsIHZhcnMuam9pbihcIixcIildLmpvaW4oXCJcIiksXG4gICAgICBcImZvcihpPWxlZnQrMTtpPD1yaWdodDsrK2kpe1wiLFxuICAgICAgICBcImo9aTtwdHIrPXMwXCIsXG4gICAgICAgIFwiY3B0cj1wdHJcIilcbiAgXG4gIFxuICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gIFxuICAgIC8vQ29weSBkYXRhIGludG8gc2NyYXRjaFxuICAgIGNvZGUucHVzaChcImRwdHI9MDtzcHRyPXB0clwiKVxuICAgIGZvcih2YXIgaT1vcmRlci5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goW1wiZm9yKGlcIixqLFwiPTA7aVwiLGosXCI8blwiLGosXCI7KytpXCIsaixcIil7XCJdLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIGNvZGUucHVzaChcInNjcmF0Y2hbZHB0cisrXT1cIixkYXRhUmVhZChcInNwdHJcIikpXG4gICAgZm9yKHZhciBpPTA7IGk8b3JkZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgIHZhciBqID0gb3JkZXJbaV1cbiAgICAgIGlmKGogPT09IDApIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChcInNwdHIrPWRcIitqLFwifVwiKVxuICAgIH1cblxuICAgIFxuICAgIC8vQ29tcGFyZSBpdGVtcyBpbiBvdXRlciBsb29wXG4gICAgY29kZS5wdXNoKFwiX19nOndoaWxlKGotLT5sZWZ0KXtcIixcbiAgICAgICAgICAgICAgXCJkcHRyPTBcIixcbiAgICAgICAgICAgICAgXCJzcHRyPWNwdHItczBcIilcbiAgICBmb3IodmFyIGk9MTsgaTxvcmRlci5sZW5ndGg7ICsraSkge1xuICAgICAgaWYoaSA9PT0gMSkge1xuICAgICAgICBjb2RlLnB1c2goXCJfX2w6XCIpXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goW1wiZm9yKGlcIixpLFwiPTA7aVwiLGksXCI8blwiLGksXCI7KytpXCIsaSxcIil7XCJdLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIGNvZGUucHVzaChbXCJhPVwiLCBkYXRhUmVhZChcInNwdHJcIiksXCJcXG5iPXNjcmF0Y2hbZHB0cl1cXG5pZihhPGIpe2JyZWFrIF9fZ31cXG5pZihhPmIpe2JyZWFrIF9fbH1cIl0uam9pbihcIlwiKSlcbiAgICBmb3IodmFyIGk9b3JkZXIubGVuZ3RoLTE7IGk+PTE7IC0taSkge1xuICAgICAgY29kZS5wdXNoKFxuICAgICAgICBcInNwdHIrPWVcIitpLFxuICAgICAgICBcImRwdHIrPWZcIitpLFxuICAgICAgICBcIn1cIilcbiAgICB9XG4gICAgXG4gICAgLy9Db3B5IGRhdGEgYmFja1xuICAgIGNvZGUucHVzaChcImRwdHI9Y3B0cjtzcHRyPWNwdHItczBcIilcbiAgICBmb3IodmFyIGk9b3JkZXIubGVuZ3RoLTE7IGk+PTA7IC0taSkge1xuICAgICAgdmFyIGogPSBvcmRlcltpXVxuICAgICAgaWYoaiA9PT0gMCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgY29kZS5wdXNoKFtcImZvcihpXCIsaixcIj0wO2lcIixqLFwiPG5cIixqLFwiOysraVwiLGosXCIpe1wiXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgICBjb2RlLnB1c2goZGF0YVdyaXRlKFwiZHB0clwiLCBkYXRhUmVhZChcInNwdHJcIikpKVxuICAgIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goW1wiZHB0cis9ZFwiLGosXCI7c3B0cis9ZFwiLGpdLmpvaW4oXCJcIiksXCJ9XCIpXG4gICAgfVxuICAgIFxuICAgIC8vQ2xvc2Ugd2hpbGUgbG9vcFxuICAgIGNvZGUucHVzaChcImNwdHItPXMwXFxufVwiKVxuXG4gICAgLy9Db3B5IHNjcmF0Y2ggaW50byBjcHRyXG4gICAgY29kZS5wdXNoKFwiZHB0cj1jcHRyO3NwdHI9MFwiKVxuICAgIGZvcih2YXIgaT1vcmRlci5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goW1wiZm9yKGlcIixqLFwiPTA7aVwiLGosXCI8blwiLGosXCI7KytpXCIsaixcIil7XCJdLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIGNvZGUucHVzaChkYXRhV3JpdGUoXCJkcHRyXCIsIFwic2NyYXRjaFtzcHRyKytdXCIpKVxuICAgIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goXCJkcHRyKz1kXCIraixcIn1cIilcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY29kZS5wdXNoKFwic2NyYXRjaD1cIiArIGRhdGFSZWFkKFwicHRyXCIpLFxuICAgICAgICAgICAgICBcIndoaWxlKChqLS0+bGVmdCkmJihcIitkYXRhUmVhZChcImNwdHItczBcIikrXCI+c2NyYXRjaCkpe1wiLFxuICAgICAgICAgICAgICAgIGRhdGFXcml0ZShcImNwdHJcIiwgZGF0YVJlYWQoXCJjcHRyLXMwXCIpKSxcbiAgICAgICAgICAgICAgICBcImNwdHItPXMwXCIsXG4gICAgICAgICAgICAgIFwifVwiLFxuICAgICAgICAgICAgICBkYXRhV3JpdGUoXCJjcHRyXCIsIFwic2NyYXRjaFwiKSlcbiAgfVxuICBcbiAgLy9DbG9zZSBvdXRlciBsb29wIGJvZHlcbiAgY29kZS5wdXNoKFwifVwiKVxuICBpZihvcmRlci5sZW5ndGggPiAxICYmIGFsbG9jYXRvcikge1xuICAgIGNvZGUucHVzaChcImZyZWUoc2NyYXRjaClcIilcbiAgfVxuICBjb2RlLnB1c2goXCJ9IHJldHVybiBcIiArIGZ1bmNOYW1lKVxuICBcbiAgLy9Db21waWxlIGFuZCBsaW5rIGZ1bmN0aW9uXG4gIGlmKGFsbG9jYXRvcikge1xuICAgIHZhciByZXN1bHQgPSBuZXcgRnVuY3Rpb24oXCJtYWxsb2NcIiwgXCJmcmVlXCIsIGNvZGUuam9pbihcIlxcblwiKSlcbiAgICByZXR1cm4gcmVzdWx0KGFsbG9jYXRvclswXSwgYWxsb2NhdG9yWzFdKVxuICB9IGVsc2Uge1xuICAgIHZhciByZXN1bHQgPSBuZXcgRnVuY3Rpb24oY29kZS5qb2luKFwiXFxuXCIpKVxuICAgIHJldHVybiByZXN1bHQoKVxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVF1aWNrU29ydChvcmRlciwgZHR5cGUsIGluc2VydGlvblNvcnQpIHtcbiAgdmFyIGNvZGUgPSBbIFwiJ3VzZSBzdHJpY3QnXCIgXVxuICB2YXIgZnVuY05hbWUgPSBbXCJuZGFycmF5UXVpY2tTb3J0XCIsIG9yZGVyLmpvaW4oXCJkXCIpLCBkdHlwZV0uam9pbihcIlwiKVxuICB2YXIgZnVuY0FyZ3MgPSBbXCJsZWZ0XCIsIFwicmlnaHRcIiwgXCJkYXRhXCIsIFwib2Zmc2V0XCIgXS5jb25jYXQoc2hhcGVBcmdzKG9yZGVyLmxlbmd0aCkpXG4gIHZhciBhbGxvY2F0b3IgPSBnZXRNYWxsb2NGcmVlKGR0eXBlKVxuICB2YXIgbGFiZWxDb3VudGVyPTBcbiAgXG4gIGNvZGUucHVzaChbXCJmdW5jdGlvbiBcIiwgZnVuY05hbWUsIFwiKFwiLCBmdW5jQXJncy5qb2luKFwiLFwiKSwgXCIpe1wiXS5qb2luKFwiXCIpKVxuICBcbiAgdmFyIHZhcnMgPSBbXG4gICAgXCJzaXh0aD0oKHJpZ2h0LWxlZnQrMSkvNil8MFwiLFxuICAgIFwiaW5kZXgxPWxlZnQrc2l4dGhcIixcbiAgICBcImluZGV4NT1yaWdodC1zaXh0aFwiLFxuICAgIFwiaW5kZXgzPShsZWZ0K3JpZ2h0KT4+MVwiLFxuICAgIFwiaW5kZXgyPWluZGV4My1zaXh0aFwiLFxuICAgIFwiaW5kZXg0PWluZGV4MytzaXh0aFwiLFxuICAgIFwiZWwxPWluZGV4MVwiLFxuICAgIFwiZWwyPWluZGV4MlwiLFxuICAgIFwiZWwzPWluZGV4M1wiLFxuICAgIFwiZWw0PWluZGV4NFwiLFxuICAgIFwiZWw1PWluZGV4NVwiLFxuICAgIFwibGVzcz1sZWZ0KzFcIixcbiAgICBcImdyZWF0PXJpZ2h0LTFcIixcbiAgICBcInBpdm90c19hcmVfZXF1YWw9dHJ1ZVwiLFxuICAgIFwidG1wXCIsXG4gICAgXCJ0bXAwXCIsXG4gICAgXCJ4XCIsXG4gICAgXCJ5XCIsXG4gICAgXCJ6XCIsXG4gICAgXCJrXCIsXG4gICAgXCJwdHIwXCIsXG4gICAgXCJwdHIxXCIsXG4gICAgXCJwdHIyXCIsXG4gICAgXCJjb21wX3Bpdm90MT0wXCIsXG4gICAgXCJjb21wX3Bpdm90Mj0wXCIsXG4gICAgXCJjb21wPTBcIlxuICBdXG4gIFxuICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgdmFyIGVsZV9zaXplID0gW11cbiAgICBmb3IodmFyIGk9MTsgaTxvcmRlci5sZW5ndGg7ICsraSkge1xuICAgICAgZWxlX3NpemUucHVzaChcIm5cIitpKVxuICAgICAgdmFycy5wdXNoKFwiaVwiK2kpXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPDg7ICsraSkge1xuICAgICAgdmFycy5wdXNoKFwiYl9wdHJcIitpKVxuICAgIH1cbiAgICB2YXJzLnB1c2goXG4gICAgICBcInB0cjNcIixcbiAgICAgIFwicHRyNFwiLFxuICAgICAgXCJwdHI1XCIsXG4gICAgICBcInB0cjZcIixcbiAgICAgIFwicHRyN1wiLFxuICAgICAgXCJwaXZvdF9wdHJcIixcbiAgICAgIFwicHRyX3NoaWZ0XCIsXG4gICAgICBcImVsZW1lbnRTaXplPVwiK2VsZV9zaXplLmpvaW4oXCIqXCIpKVxuICAgIGlmKGFsbG9jYXRvcikge1xuICAgICAgdmFycy5wdXNoKFwicGl2b3QxPW1hbGxvYyhlbGVtZW50U2l6ZSlcIixcbiAgICAgICAgICAgICAgICBcInBpdm90Mj1tYWxsb2MoZWxlbWVudFNpemUpXCIpXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhcnMucHVzaChcInBpdm90MT1uZXcgQXJyYXkoZWxlbWVudFNpemUpLHBpdm90Mj1uZXcgQXJyYXkoZWxlbWVudFNpemUpXCIpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhcnMucHVzaChcInBpdm90MVwiLCBcInBpdm90MlwiKVxuICB9XG4gIFxuICAvL0luaXRpYWxpemUgbG9jYWwgdmFyaWFibGVzXG4gIGNvZGUucHVzaChcInZhciBcIiArIHZhcnMuam9pbihcIixcIikpXG4gIFxuICBmdW5jdGlvbiB0b1BvaW50ZXIodikge1xuICAgIHJldHVybiBbXCIob2Zmc2V0K1wiLHYsXCIqczApXCJdLmpvaW4oXCJcIilcbiAgfVxuICBcbiAgZnVuY3Rpb24gZGF0YVJlYWQocHRyKSB7XG4gICAgaWYoZHR5cGUgPT09IFwiZ2VuZXJpY1wiKSB7XG4gICAgICByZXR1cm4gW1wiZGF0YS5nZXQoXCIsIHB0ciwgXCIpXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gICAgcmV0dXJuIFtcImRhdGFbXCIscHRyLFwiXVwiXS5qb2luKFwiXCIpXG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGRhdGFXcml0ZShwdHIsIHYpIHtcbiAgICBpZihkdHlwZSA9PT0gXCJnZW5lcmljXCIpIHtcbiAgICAgIHJldHVybiBbXCJkYXRhLnNldChcIiwgcHRyLCBcIixcIiwgdiwgXCIpXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gICAgcmV0dXJuIFtcImRhdGFbXCIscHRyLFwiXT1cIix2XS5qb2luKFwiXCIpXG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGNhY2hlTG9vcChwdHJzLCB1c2VQaXZvdCwgYm9keSkge1xuICAgIGlmKHB0cnMubGVuZ3RoID09PSAxKSB7XG4gICAgICBjb2RlLnB1c2goXCJwdHIwPVwiK3RvUG9pbnRlcihwdHJzWzBdKSlcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yKHZhciBpPTA7IGk8cHRycy5sZW5ndGg7ICsraSkge1xuICAgICAgICBjb2RlLnB1c2goW1wiYl9wdHJcIixpLFwiPXMwKlwiLHB0cnNbaV1dLmpvaW4oXCJcIikpXG4gICAgICB9XG4gICAgfVxuICAgIGlmKHVzZVBpdm90KSB7XG4gICAgICBjb2RlLnB1c2goXCJwaXZvdF9wdHI9MFwiKVxuICAgIH1cbiAgICBjb2RlLnB1c2goXCJwdHJfc2hpZnQ9b2Zmc2V0XCIpXG4gICAgZm9yKHZhciBpPW9yZGVyLmxlbmd0aC0xOyBpPj0wOyAtLWkpIHtcbiAgICAgIHZhciBqID0gb3JkZXJbaV1cbiAgICAgIGlmKGogPT09IDApIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChbXCJmb3IoaVwiLGosXCI9MDtpXCIsaixcIjxuXCIsaixcIjsrK2lcIixqLFwiKXtcIl0uam9pbihcIlwiKSlcbiAgICB9XG4gICAgaWYocHRycy5sZW5ndGggPiAxKSB7XG4gICAgICBmb3IodmFyIGk9MDsgaTxwdHJzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGNvZGUucHVzaChbXCJwdHJcIixpLFwiPWJfcHRyXCIsaSxcIitwdHJfc2hpZnRcIl0uam9pbihcIlwiKSlcbiAgICAgIH1cbiAgICB9XG4gICAgY29kZS5wdXNoKGJvZHkpXG4gICAgaWYodXNlUGl2b3QpIHtcbiAgICAgIGNvZGUucHVzaChcIisrcGl2b3RfcHRyXCIpXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgaiA9IG9yZGVyW2ldXG4gICAgICBpZihqID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBpZihwdHJzLmxlbmd0aD4xKSB7XG4gICAgICAgIGNvZGUucHVzaChcInB0cl9zaGlmdCs9ZFwiK2opXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2RlLnB1c2goXCJwdHIwKz1kXCIrailcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChcIn1cIilcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGxleGljb0xvb3AobGFiZWwsIHB0cnMsIHVzZVBpdm90LCBib2R5KSB7XG4gICAgaWYocHRycy5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvZGUucHVzaChcInB0cjA9XCIrdG9Qb2ludGVyKHB0cnNbMF0pKVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IodmFyIGk9MDsgaTxwdHJzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGNvZGUucHVzaChbXCJiX3B0clwiLGksXCI9czAqXCIscHRyc1tpXV0uam9pbihcIlwiKSlcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChcInB0cl9zaGlmdD1vZmZzZXRcIilcbiAgICB9XG4gICAgaWYodXNlUGl2b3QpIHtcbiAgICAgIGNvZGUucHVzaChcInBpdm90X3B0cj0wXCIpXG4gICAgfVxuICAgIGlmKGxhYmVsKSB7XG4gICAgICBjb2RlLnB1c2gobGFiZWwrXCI6XCIpXG4gICAgfVxuICAgIGZvcih2YXIgaT0xOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgICBjb2RlLnB1c2goW1wiZm9yKGlcIixpLFwiPTA7aVwiLGksXCI8blwiLGksXCI7KytpXCIsaSxcIil7XCJdLmpvaW4oXCJcIikpXG4gICAgfVxuICAgIGlmKHB0cnMubGVuZ3RoID4gMSkge1xuICAgICAgZm9yKHZhciBpPTA7IGk8cHRycy5sZW5ndGg7ICsraSkge1xuICAgICAgICBjb2RlLnB1c2goW1wicHRyXCIsaSxcIj1iX3B0clwiLGksXCIrcHRyX3NoaWZ0XCJdLmpvaW4oXCJcIikpXG4gICAgICB9XG4gICAgfVxuICAgIGNvZGUucHVzaChib2R5KVxuICAgIGZvcih2YXIgaT1vcmRlci5sZW5ndGgtMTsgaT49MTsgLS1pKSB7XG4gICAgICBpZih1c2VQaXZvdCkge1xuICAgICAgICBjb2RlLnB1c2goXCJwaXZvdF9wdHIrPWZcIitpKVxuICAgICAgfVxuICAgICAgaWYocHRycy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGNvZGUucHVzaChcInB0cl9zaGlmdCs9ZVwiK2kpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2RlLnB1c2goXCJwdHIwKz1lXCIraSlcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaChcIn1cIilcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIGNsZWFuVXAoKSB7XG4gICAgaWYob3JkZXIubGVuZ3RoID4gMSAmJiBhbGxvY2F0b3IpIHtcbiAgICAgIGNvZGUucHVzaChcImZyZWUocGl2b3QxKVwiLCBcImZyZWUocGl2b3QyKVwiKVxuICAgIH1cbiAgfVxuICBcbiAgZnVuY3Rpb24gY29tcGFyZVN3YXAoYV9pZCwgYl9pZCkge1xuICAgIHZhciBhID0gXCJlbFwiK2FfaWRcbiAgICB2YXIgYiA9IFwiZWxcIitiX2lkXG4gICAgaWYob3JkZXIubGVuZ3RoID4gMSkge1xuICAgICAgdmFyIGxibCA9IFwiX19sXCIgKyAoKytsYWJlbENvdW50ZXIpXG4gICAgICBsZXhpY29Mb29wKGxibCwgW2EsIGJdLCBmYWxzZSwgW1xuICAgICAgICBcImNvbXA9XCIsZGF0YVJlYWQoXCJwdHIwXCIpLFwiLVwiLGRhdGFSZWFkKFwicHRyMVwiKSxcIlxcblwiLFxuICAgICAgICBcImlmKGNvbXA+MCl7dG1wMD1cIiwgYSwgXCI7XCIsYSxcIj1cIixiLFwiO1wiLCBiLFwiPXRtcDA7YnJlYWsgXCIsIGxibCxcIn1cXG5cIixcbiAgICAgICAgXCJpZihjb21wPDApe2JyZWFrIFwiLCBsYmwsIFwifVwiXG4gICAgICBdLmpvaW4oXCJcIikpXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGUucHVzaChbXCJpZihcIiwgZGF0YVJlYWQodG9Qb2ludGVyKGEpKSwgXCI+XCIsIGRhdGFSZWFkKHRvUG9pbnRlcihiKSksIFwiKXt0bXAwPVwiLCBhLCBcIjtcIixhLFwiPVwiLGIsXCI7XCIsIGIsXCI9dG1wMH1cIl0uam9pbihcIlwiKSlcbiAgICB9XG4gIH1cbiAgXG4gIGNvbXBhcmVTd2FwKDEsIDIpXG4gIGNvbXBhcmVTd2FwKDQsIDUpXG4gIGNvbXBhcmVTd2FwKDEsIDMpXG4gIGNvbXBhcmVTd2FwKDIsIDMpXG4gIGNvbXBhcmVTd2FwKDEsIDQpXG4gIGNvbXBhcmVTd2FwKDMsIDQpXG4gIGNvbXBhcmVTd2FwKDIsIDUpXG4gIGNvbXBhcmVTd2FwKDIsIDMpXG4gIGNvbXBhcmVTd2FwKDQsIDUpXG4gIFxuICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgY2FjaGVMb29wKFtcImVsMVwiLCBcImVsMlwiLCBcImVsM1wiLCBcImVsNFwiLCBcImVsNVwiLCBcImluZGV4MVwiLCBcImluZGV4M1wiLCBcImluZGV4NVwiXSwgdHJ1ZSwgW1xuICAgICAgXCJwaXZvdDFbcGl2b3RfcHRyXT1cIixkYXRhUmVhZChcInB0cjFcIiksXCJcXG5cIixcbiAgICAgIFwicGl2b3QyW3Bpdm90X3B0cl09XCIsZGF0YVJlYWQoXCJwdHIzXCIpLFwiXFxuXCIsXG4gICAgICBcInBpdm90c19hcmVfZXF1YWw9cGl2b3RzX2FyZV9lcXVhbCYmKHBpdm90MVtwaXZvdF9wdHJdPT09cGl2b3QyW3Bpdm90X3B0cl0pXFxuXCIsXG4gICAgICBcIng9XCIsZGF0YVJlYWQoXCJwdHIwXCIpLFwiXFxuXCIsXG4gICAgICBcInk9XCIsZGF0YVJlYWQoXCJwdHIyXCIpLFwiXFxuXCIsXG4gICAgICBcIno9XCIsZGF0YVJlYWQoXCJwdHI0XCIpLFwiXFxuXCIsXG4gICAgICBkYXRhV3JpdGUoXCJwdHI1XCIsIFwieFwiKSxcIlxcblwiLFxuICAgICAgZGF0YVdyaXRlKFwicHRyNlwiLCBcInlcIiksXCJcXG5cIixcbiAgICAgIGRhdGFXcml0ZShcInB0cjdcIiwgXCJ6XCIpXG4gICAgXS5qb2luKFwiXCIpKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChbXG4gICAgICBcInBpdm90MT1cIiwgZGF0YVJlYWQodG9Qb2ludGVyKFwiZWwyXCIpKSwgXCJcXG5cIixcbiAgICAgIFwicGl2b3QyPVwiLCBkYXRhUmVhZCh0b1BvaW50ZXIoXCJlbDRcIikpLCBcIlxcblwiLFxuICAgICAgXCJwaXZvdHNfYXJlX2VxdWFsPXBpdm90MT09PXBpdm90MlxcblwiLFxuICAgICAgXCJ4PVwiLCBkYXRhUmVhZCh0b1BvaW50ZXIoXCJlbDFcIikpLCBcIlxcblwiLFxuICAgICAgXCJ5PVwiLCBkYXRhUmVhZCh0b1BvaW50ZXIoXCJlbDNcIikpLCBcIlxcblwiLFxuICAgICAgXCJ6PVwiLCBkYXRhUmVhZCh0b1BvaW50ZXIoXCJlbDVcIikpLCBcIlxcblwiLFxuICAgICAgZGF0YVdyaXRlKHRvUG9pbnRlcihcImluZGV4MVwiKSwgXCJ4XCIpLCBcIlxcblwiLFxuICAgICAgZGF0YVdyaXRlKHRvUG9pbnRlcihcImluZGV4M1wiKSwgXCJ5XCIpLCBcIlxcblwiLFxuICAgICAgZGF0YVdyaXRlKHRvUG9pbnRlcihcImluZGV4NVwiKSwgXCJ6XCIpXG4gICAgXS5qb2luKFwiXCIpKVxuICB9XG4gIFxuXG4gIGZ1bmN0aW9uIG1vdmVFbGVtZW50KGRzdCwgc3JjKSB7XG4gICAgaWYob3JkZXIubGVuZ3RoID4gMSkge1xuICAgICAgY2FjaGVMb29wKFtkc3QsIHNyY10sIGZhbHNlLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIwXCIsIGRhdGFSZWFkKFwicHRyMVwiKSlcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZS5wdXNoKGRhdGFXcml0ZSh0b1BvaW50ZXIoZHN0KSwgZGF0YVJlYWQodG9Qb2ludGVyKHNyYykpKSlcbiAgICB9XG4gIH1cbiAgXG4gIG1vdmVFbGVtZW50KFwiaW5kZXgyXCIsIFwibGVmdFwiKVxuICBtb3ZlRWxlbWVudChcImluZGV4NFwiLCBcInJpZ2h0XCIpXG4gIFxuICBmdW5jdGlvbiBjb21wYXJlUGl2b3QocmVzdWx0LCBwdHIsIG4pIHtcbiAgICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgICB2YXIgbGJsID0gXCJfX2xcIiArICgrK2xhYmVsQ291bnRlcilcbiAgICAgIGxleGljb0xvb3AobGJsLCBbcHRyXSwgdHJ1ZSwgW1xuICAgICAgICByZXN1bHQsXCI9XCIsZGF0YVJlYWQoXCJwdHIwXCIpLFwiLXBpdm90XCIsbixcIltwaXZvdF9wdHJdXFxuXCIsXG4gICAgICAgIFwiaWYoXCIscmVzdWx0LFwiIT09MCl7YnJlYWsgXCIsIGxibCwgXCJ9XCJcbiAgICAgIF0uam9pbihcIlwiKSlcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZS5wdXNoKFtyZXN1bHQsXCI9XCIsIGRhdGFSZWFkKHRvUG9pbnRlcihwdHIpKSwgXCItcGl2b3RcIiwgbl0uam9pbihcIlwiKSlcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHN3YXBFbGVtZW50cyhhLCBiKSB7XG4gICAgaWYob3JkZXIubGVuZ3RoID4gMSkge1xuICAgICAgY2FjaGVMb29wKFthLGJdLGZhbHNlLFtcbiAgICAgICAgXCJ0bXA9XCIsZGF0YVJlYWQoXCJwdHIwXCIpLFwiXFxuXCIsXG4gICAgICAgIGRhdGFXcml0ZShcInB0cjBcIiwgZGF0YVJlYWQoXCJwdHIxXCIpKSxcIlxcblwiLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIxXCIsIFwidG1wXCIpXG4gICAgICBdLmpvaW4oXCJcIikpXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGUucHVzaChbXG4gICAgICAgIFwicHRyMD1cIix0b1BvaW50ZXIoYSksXCJcXG5cIixcbiAgICAgICAgXCJwdHIxPVwiLHRvUG9pbnRlcihiKSxcIlxcblwiLFxuICAgICAgICBcInRtcD1cIixkYXRhUmVhZChcInB0cjBcIiksXCJcXG5cIixcbiAgICAgICAgZGF0YVdyaXRlKFwicHRyMFwiLCBkYXRhUmVhZChcInB0cjFcIikpLFwiXFxuXCIsXG4gICAgICAgIGRhdGFXcml0ZShcInB0cjFcIiwgXCJ0bXBcIilcbiAgICAgIF0uam9pbihcIlwiKSlcbiAgICB9XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHRyaXBsZVN3YXAoaywgbGVzcywgZ3JlYXQpIHtcbiAgICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgICBjYWNoZUxvb3AoW2ssbGVzcyxncmVhdF0sIGZhbHNlLCBbXG4gICAgICAgIFwidG1wPVwiLGRhdGFSZWFkKFwicHRyMFwiKSxcIlxcblwiLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIwXCIsIGRhdGFSZWFkKFwicHRyMVwiKSksXCJcXG5cIixcbiAgICAgICAgZGF0YVdyaXRlKFwicHRyMVwiLCBkYXRhUmVhZChcInB0cjJcIikpLFwiXFxuXCIsXG4gICAgICAgIGRhdGFXcml0ZShcInB0cjJcIiwgXCJ0bXBcIilcbiAgICAgIF0uam9pbihcIlwiKSlcbiAgICAgIGNvZGUucHVzaChcIisrXCIrbGVzcywgXCItLVwiK2dyZWF0KVxuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlLnB1c2goW1xuICAgICAgICBcInB0cjA9XCIsdG9Qb2ludGVyKGspLFwiXFxuXCIsXG4gICAgICAgIFwicHRyMT1cIix0b1BvaW50ZXIobGVzcyksXCJcXG5cIixcbiAgICAgICAgXCJwdHIyPVwiLHRvUG9pbnRlcihncmVhdCksXCJcXG5cIixcbiAgICAgICAgXCIrK1wiLGxlc3MsXCJcXG5cIixcbiAgICAgICAgXCItLVwiLGdyZWF0LFwiXFxuXCIsXG4gICAgICAgIFwidG1wPVwiLCBkYXRhUmVhZChcInB0cjBcIiksIFwiXFxuXCIsXG4gICAgICAgIGRhdGFXcml0ZShcInB0cjBcIiwgZGF0YVJlYWQoXCJwdHIxXCIpKSwgXCJcXG5cIixcbiAgICAgICAgZGF0YVdyaXRlKFwicHRyMVwiLCBkYXRhUmVhZChcInB0cjJcIikpLCBcIlxcblwiLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIyXCIsIFwidG1wXCIpXG4gICAgICBdLmpvaW4oXCJcIikpXG4gICAgfVxuICB9XG4gIFxuICBmdW5jdGlvbiBzd2FwQW5kRGVjcmVtZW50KGssIGdyZWF0KSB7XG4gICAgc3dhcEVsZW1lbnRzKGssIGdyZWF0KVxuICAgIGNvZGUucHVzaChcIi0tXCIrZ3JlYXQpXG4gIH1cbiAgICBcbiAgY29kZS5wdXNoKFwiaWYocGl2b3RzX2FyZV9lcXVhbCl7XCIpXG4gICAgLy9QaXZvdHMgYXJlIGVxdWFsIGNhc2VcbiAgICBjb2RlLnB1c2goXCJmb3Ioaz1sZXNzO2s8PWdyZWF0Oysrayl7XCIpXG4gICAgICBjb21wYXJlUGl2b3QoXCJjb21wXCIsIFwia1wiLCAxKVxuICAgICAgY29kZS5wdXNoKFwiaWYoY29tcD09PTApe2NvbnRpbnVlfVwiKVxuICAgICAgY29kZS5wdXNoKFwiaWYoY29tcDwwKXtcIilcbiAgICAgICAgY29kZS5wdXNoKFwiaWYoayE9PWxlc3Mpe1wiKVxuICAgICAgICAgIHN3YXBFbGVtZW50cyhcImtcIiwgXCJsZXNzXCIpXG4gICAgICAgIGNvZGUucHVzaChcIn1cIilcbiAgICAgICAgY29kZS5wdXNoKFwiKytsZXNzXCIpXG4gICAgICBjb2RlLnB1c2goXCJ9ZWxzZXtcIilcbiAgICAgICAgY29kZS5wdXNoKFwid2hpbGUodHJ1ZSl7XCIpXG4gICAgICAgICAgY29tcGFyZVBpdm90KFwiY29tcFwiLCBcImdyZWF0XCIsIDEpXG4gICAgICAgICAgY29kZS5wdXNoKFwiaWYoY29tcD4wKXtcIilcbiAgICAgICAgICAgIGNvZGUucHVzaChcImdyZWF0LS1cIilcbiAgICAgICAgICBjb2RlLnB1c2goXCJ9ZWxzZSBpZihjb21wPDApe1wiKVxuICAgICAgICAgICAgdHJpcGxlU3dhcChcImtcIiwgXCJsZXNzXCIsIFwiZ3JlYXRcIilcbiAgICAgICAgICAgIGNvZGUucHVzaChcImJyZWFrXCIpXG4gICAgICAgICAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgICAgICAgICBzd2FwQW5kRGVjcmVtZW50KFwia1wiLCBcImdyZWF0XCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJicmVha1wiKVxuICAgICAgICAgIGNvZGUucHVzaChcIn1cIilcbiAgICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgIGNvZGUucHVzaChcIn1cIilcbiAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgLy9QaXZvdHMgbm90IGVxdWFsIGNhc2VcbiAgICBjb2RlLnB1c2goXCJmb3Ioaz1sZXNzO2s8PWdyZWF0Oysrayl7XCIpXG4gICAgICBjb21wYXJlUGl2b3QoXCJjb21wX3Bpdm90MVwiLCBcImtcIiwgMSlcbiAgICAgIGNvZGUucHVzaChcImlmKGNvbXBfcGl2b3QxPDApe1wiKVxuICAgICAgICBjb2RlLnB1c2goXCJpZihrIT09bGVzcyl7XCIpXG4gICAgICAgICAgc3dhcEVsZW1lbnRzKFwia1wiLCBcImxlc3NcIilcbiAgICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgICAgICBjb2RlLnB1c2goXCIrK2xlc3NcIilcbiAgICAgIGNvZGUucHVzaChcIn1lbHNle1wiKVxuICAgICAgICBjb21wYXJlUGl2b3QoXCJjb21wX3Bpdm90MlwiLCBcImtcIiwgMilcbiAgICAgICAgY29kZS5wdXNoKFwiaWYoY29tcF9waXZvdDI+MCl7XCIpXG4gICAgICAgICAgY29kZS5wdXNoKFwid2hpbGUodHJ1ZSl7XCIpXG4gICAgICAgICAgICBjb21wYXJlUGl2b3QoXCJjb21wXCIsIFwiZ3JlYXRcIiwgMilcbiAgICAgICAgICAgIGNvZGUucHVzaChcImlmKGNvbXA+MCl7XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImlmKC0tZ3JlYXQ8ayl7YnJlYWt9XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImNvbnRpbnVlXCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJ9ZWxzZXtcIilcbiAgICAgICAgICAgICAgY29tcGFyZVBpdm90KFwiY29tcFwiLCBcImdyZWF0XCIsIDEpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImlmKGNvbXA8MCl7XCIpXG4gICAgICAgICAgICAgICAgdHJpcGxlU3dhcChcImtcIiwgXCJsZXNzXCIsIFwiZ3JlYXRcIilcbiAgICAgICAgICAgICAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgICAgICAgICAgICAgc3dhcEFuZERlY3JlbWVudChcImtcIiwgXCJncmVhdFwiKVxuICAgICAgICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImJyZWFrXCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgY29kZS5wdXNoKFwifVwiKVxuICBjb2RlLnB1c2goXCJ9XCIpXG4gIFxuICAvL01vdmUgcGl2b3RzIHRvIGNvcnJlY3QgcGxhY2VcbiAgZnVuY3Rpb24gc3RvcmVQaXZvdChtZW1fZGVzdCwgcGl2b3RfZGVzdCwgcGl2b3QpIHtcbiAgICBpZihvcmRlci5sZW5ndGg+MSkge1xuICAgICAgY2FjaGVMb29wKFttZW1fZGVzdCwgcGl2b3RfZGVzdF0sIHRydWUsIFtcbiAgICAgICAgZGF0YVdyaXRlKFwicHRyMFwiLCBkYXRhUmVhZChcInB0cjFcIikpLCBcIlxcblwiLFxuICAgICAgICBkYXRhV3JpdGUoXCJwdHIxXCIsIFtcInBpdm90XCIscGl2b3QsXCJbcGl2b3RfcHRyXVwiXS5qb2luKFwiXCIpKVxuICAgICAgXS5qb2luKFwiXCIpKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlLnB1c2goXG4gICAgICAgICAgZGF0YVdyaXRlKHRvUG9pbnRlcihtZW1fZGVzdCksIGRhdGFSZWFkKHRvUG9pbnRlcihwaXZvdF9kZXN0KSkpLFxuICAgICAgICAgIGRhdGFXcml0ZSh0b1BvaW50ZXIocGl2b3RfZGVzdCksIFwicGl2b3RcIitwaXZvdCkpXG4gICAgfVxuICB9XG4gIFxuICBzdG9yZVBpdm90KFwibGVmdFwiLCBcIihsZXNzLTEpXCIsIDEpXG4gIHN0b3JlUGl2b3QoXCJyaWdodFwiLCBcIihncmVhdCsxKVwiLCAyKVxuXG4gIC8vUmVjdXJzaXZlIHNvcnQgY2FsbFxuICBmdW5jdGlvbiBkb1NvcnQobGVmdCwgcmlnaHQpIHtcbiAgICBjb2RlLnB1c2goW1xuICAgICAgXCJpZigoXCIscmlnaHQsXCItXCIsbGVmdCxcIik8PVwiLElOU0VSVElPTl9TT1JUX1RIUkVTSE9MRCxcIil7XFxuXCIsXG4gICAgICAgIFwiaW5zZXJ0aW9uU29ydChcIiwgbGVmdCwgXCIsXCIsIHJpZ2h0LCBcIixkYXRhLG9mZnNldCxcIiwgc2hhcGVBcmdzKG9yZGVyLmxlbmd0aCkuam9pbihcIixcIiksIFwiKVxcblwiLFxuICAgICAgXCJ9ZWxzZXtcXG5cIixcbiAgICAgICAgZnVuY05hbWUsIFwiKFwiLCBsZWZ0LCBcIixcIiwgcmlnaHQsIFwiLGRhdGEsb2Zmc2V0LFwiLCBzaGFwZUFyZ3Mob3JkZXIubGVuZ3RoKS5qb2luKFwiLFwiKSwgXCIpXFxuXCIsXG4gICAgICBcIn1cIlxuICAgIF0uam9pbihcIlwiKSlcbiAgfVxuICBkb1NvcnQoXCJsZWZ0XCIsIFwiKGxlc3MtMilcIilcbiAgZG9Tb3J0KFwiKGdyZWF0KzIpXCIsIFwicmlnaHRcIilcbiAgXG4gIC8vSWYgcGl2b3RzIGFyZSBlcXVhbCwgdGhlbiBlYXJseSBvdXRcbiAgY29kZS5wdXNoKFwiaWYocGl2b3RzX2FyZV9lcXVhbCl7XCIpXG4gICAgY2xlYW5VcCgpXG4gICAgY29kZS5wdXNoKFwicmV0dXJuXCIpXG4gIGNvZGUucHVzaChcIn1cIilcbiAgXG4gIGZ1bmN0aW9uIHdhbGtQb2ludGVyKHB0ciwgcGl2b3QsIGJvZHkpIHtcbiAgICBpZihvcmRlci5sZW5ndGggPiAxKSB7XG4gICAgICBjb2RlLnB1c2goW1wiX19sXCIsKytsYWJlbENvdW50ZXIsXCI6d2hpbGUodHJ1ZSl7XCJdLmpvaW4oXCJcIikpXG4gICAgICBjYWNoZUxvb3AoW3B0cl0sIHRydWUsIFtcbiAgICAgICAgXCJpZihcIiwgZGF0YVJlYWQoXCJwdHIwXCIpLCBcIiE9PXBpdm90XCIsIHBpdm90LCBcIltwaXZvdF9wdHJdKXticmVhayBfX2xcIiwgbGFiZWxDb3VudGVyLCBcIn1cIlxuICAgICAgXS5qb2luKFwiXCIpKVxuICAgICAgY29kZS5wdXNoKGJvZHksIFwifVwiKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlLnB1c2goW1wid2hpbGUoXCIsIGRhdGFSZWFkKHRvUG9pbnRlcihwdHIpKSwgXCI9PT1waXZvdFwiLCBwaXZvdCwgXCIpe1wiLCBib2R5LCBcIn1cIl0uam9pbihcIlwiKSlcbiAgICB9XG4gIH1cbiAgXG4gIC8vQ2hlY2sgYm91bmRzXG4gIGNvZGUucHVzaChcImlmKGxlc3M8aW5kZXgxJiZncmVhdD5pbmRleDUpe1wiKVxuICBcbiAgICB3YWxrUG9pbnRlcihcImxlc3NcIiwgMSwgXCIrK2xlc3NcIilcbiAgICB3YWxrUG9pbnRlcihcImdyZWF0XCIsIDIsIFwiLS1ncmVhdFwiKVxuICBcbiAgICBjb2RlLnB1c2goXCJmb3Ioaz1sZXNzO2s8PWdyZWF0Oysrayl7XCIpXG4gICAgICBjb21wYXJlUGl2b3QoXCJjb21wX3Bpdm90MVwiLCBcImtcIiwgMSlcbiAgICAgIGNvZGUucHVzaChcImlmKGNvbXBfcGl2b3QxPT09MCl7XCIpXG4gICAgICAgIGNvZGUucHVzaChcImlmKGshPT1sZXNzKXtcIilcbiAgICAgICAgICBzd2FwRWxlbWVudHMoXCJrXCIsIFwibGVzc1wiKVxuICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgIGNvZGUucHVzaChcIisrbGVzc1wiKVxuICAgICAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgICAgIGNvbXBhcmVQaXZvdChcImNvbXBfcGl2b3QyXCIsIFwia1wiLCAyKVxuICAgICAgICBjb2RlLnB1c2goXCJpZihjb21wX3Bpdm90Mj09PTApe1wiKVxuICAgICAgICAgIGNvZGUucHVzaChcIndoaWxlKHRydWUpe1wiKVxuICAgICAgICAgICAgY29tcGFyZVBpdm90KFwiY29tcFwiLCBcImdyZWF0XCIsIDIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJpZihjb21wPT09MCl7XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImlmKC0tZ3JlYXQ8ayl7YnJlYWt9XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImNvbnRpbnVlXCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJ9ZWxzZXtcIilcbiAgICAgICAgICAgICAgY29tcGFyZVBpdm90KFwiY29tcFwiLCBcImdyZWF0XCIsIDEpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImlmKGNvbXA8MCl7XCIpXG4gICAgICAgICAgICAgICAgdHJpcGxlU3dhcChcImtcIiwgXCJsZXNzXCIsIFwiZ3JlYXRcIilcbiAgICAgICAgICAgICAgY29kZS5wdXNoKFwifWVsc2V7XCIpXG4gICAgICAgICAgICAgICAgc3dhcEFuZERlY3JlbWVudChcImtcIiwgXCJncmVhdFwiKVxuICAgICAgICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgICAgICAgIGNvZGUucHVzaChcImJyZWFrXCIpXG4gICAgICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICAgICAgY29kZS5wdXNoKFwifVwiKVxuICAgICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgICBjb2RlLnB1c2goXCJ9XCIpXG4gICAgY29kZS5wdXNoKFwifVwiKVxuICBjb2RlLnB1c2goXCJ9XCIpXG4gIFxuICAvL0NsZWFuIHVwIGFuZCBkbyBhIGZpbmFsIHNvcnRpbmcgcGFzc1xuICBjbGVhblVwKClcbiAgZG9Tb3J0KFwibGVzc1wiLCBcImdyZWF0XCIpXG4gXG4gIC8vQ2xvc2Ugb2ZmIG1haW4gbG9vcFxuICBjb2RlLnB1c2goXCJ9cmV0dXJuIFwiICsgZnVuY05hbWUpXG4gIFxuICAvL0NvbXBpbGUgYW5kIGxpbmtcbiAgaWYob3JkZXIubGVuZ3RoID4gMSAmJiBhbGxvY2F0b3IpIHtcbiAgICB2YXIgY29tcGlsZWQgPSBuZXcgRnVuY3Rpb24oXCJpbnNlcnRpb25Tb3J0XCIsIFwibWFsbG9jXCIsIFwiZnJlZVwiLCBjb2RlLmpvaW4oXCJcXG5cIikpXG4gICAgcmV0dXJuIGNvbXBpbGVkKGluc2VydGlvblNvcnQsIGFsbG9jYXRvclswXSwgYWxsb2NhdG9yWzFdKVxuICB9XG4gIHZhciBjb21waWxlZCA9IG5ldyBGdW5jdGlvbihcImluc2VydGlvblNvcnRcIiwgY29kZS5qb2luKFwiXFxuXCIpKVxuICByZXR1cm4gY29tcGlsZWQoaW5zZXJ0aW9uU29ydClcbn1cblxuZnVuY3Rpb24gY29tcGlsZVNvcnQob3JkZXIsIGR0eXBlKSB7XG4gIHZhciBjb2RlID0gW1wiJ3VzZSBzdHJpY3QnXCJdXG4gIHZhciBmdW5jTmFtZSA9IFtcIm5kYXJyYXlTb3J0V3JhcHBlclwiLCBvcmRlci5qb2luKFwiZFwiKSwgZHR5cGVdLmpvaW4oXCJcIilcbiAgdmFyIGZ1bmNBcmdzID0gWyBcImFycmF5XCIgXVxuICBcbiAgY29kZS5wdXNoKFtcImZ1bmN0aW9uIFwiLCBmdW5jTmFtZSwgXCIoXCIsIGZ1bmNBcmdzLmpvaW4oXCIsXCIpLCBcIil7XCJdLmpvaW4oXCJcIikpXG4gIFxuICAvL1VucGFjayBsb2NhbCB2YXJpYWJsZXMgZnJvbSBhcnJheVxuICB2YXIgdmFycyA9IFtcImRhdGE9YXJyYXkuZGF0YSxvZmZzZXQ9YXJyYXkub2Zmc2V0fDAsc2hhcGU9YXJyYXkuc2hhcGUsc3RyaWRlPWFycmF5LnN0cmlkZVwiXVxuICBmb3IodmFyIGk9MDsgaTxvcmRlci5sZW5ndGg7ICsraSkge1xuICAgIHZhcnMucHVzaChbXCJzXCIsaSxcIj1zdHJpZGVbXCIsaSxcIl18MCxuXCIsaSxcIj1zaGFwZVtcIixpLFwiXXwwXCJdLmpvaW4oXCJcIikpXG4gIH1cbiAgXG4gIHZhciBzY3JhdGNoX3N0cmlkZSA9IG5ldyBBcnJheShvcmRlci5sZW5ndGgpXG4gIHZhciBucHJvZCA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGsgPSBvcmRlcltpXVxuICAgIGlmKGsgPT09IDApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGlmKG5wcm9kLmxlbmd0aCA9PT0gMCkge1xuICAgICAgc2NyYXRjaF9zdHJpZGVba10gPSBcIjFcIlxuICAgIH0gZWxzZSB7XG4gICAgICBzY3JhdGNoX3N0cmlkZVtrXSA9IG5wcm9kLmpvaW4oXCIqXCIpXG4gICAgfVxuICAgIG5wcm9kLnB1c2goXCJuXCIraylcbiAgfVxuICBcbiAgdmFyIHAgPSAtMSwgcSA9IC0xXG4gIGZvcih2YXIgaT0wOyBpPG9yZGVyLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGogPSBvcmRlcltpXVxuICAgIGlmKGogIT09IDApIHtcbiAgICAgIGlmKHAgPiAwKSB7XG4gICAgICAgIHZhcnMucHVzaChbXCJkXCIsaixcIj1zXCIsaixcIi1kXCIscCxcIipuXCIscF0uam9pbihcIlwiKSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhcnMucHVzaChbXCJkXCIsaixcIj1zXCIsal0uam9pbihcIlwiKSlcbiAgICAgIH1cbiAgICAgIHAgPSBqXG4gICAgfVxuICAgIHZhciBrID0gb3JkZXIubGVuZ3RoLTEtaVxuICAgIGlmKGsgIT09IDApIHtcbiAgICAgIGlmKHEgPiAwKSB7XG4gICAgICAgIHZhcnMucHVzaChbXCJlXCIsayxcIj1zXCIsayxcIi1lXCIscSxcIipuXCIscSxcbiAgICAgICAgICAgICAgICAgIFwiLGZcIixrLFwiPVwiLHNjcmF0Y2hfc3RyaWRlW2tdLFwiLWZcIixxLFwiKm5cIixxXS5qb2luKFwiXCIpKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFycy5wdXNoKFtcImVcIixrLFwiPXNcIixrLFwiLGZcIixrLFwiPVwiLHNjcmF0Y2hfc3RyaWRlW2tdXS5qb2luKFwiXCIpKVxuICAgICAgfVxuICAgICAgcSA9IGtcbiAgICB9XG4gIH1cbiAgXG4gIC8vRGVjbGFyZSBsb2NhbCB2YXJpYWJsZXNcbiAgY29kZS5wdXNoKFwidmFyIFwiICsgdmFycy5qb2luKFwiLFwiKSlcbiAgXG4gIC8vQ3JlYXRlIGFyZ3VtZW50cyBmb3Igc3Vicm91dGluZVxuICB2YXIgc29ydEFyZ3MgPSBbXCIwXCIsIFwibjAtMVwiLCBcImRhdGFcIiwgXCJvZmZzZXRcIl0uY29uY2F0KHNoYXBlQXJncyhvcmRlci5sZW5ndGgpKVxuICBcbiAgLy9DYWxsIG1haW4gc29ydGluZyByb3V0aW5lXG4gIGNvZGUucHVzaChbXG4gICAgXCJpZihuMDw9XCIsSU5TRVJUSU9OX1NPUlRfVEhSRVNIT0xELFwiKXtcIixcbiAgICAgIFwiaW5zZXJ0aW9uU29ydChcIiwgc29ydEFyZ3Muam9pbihcIixcIiksIFwiKX1lbHNle1wiLFxuICAgICAgXCJxdWlja1NvcnQoXCIsIHNvcnRBcmdzLmpvaW4oXCIsXCIpLFxuICAgIFwiKX1cIlxuICBdLmpvaW4oXCJcIikpXG4gIFxuICAvL1JldHVyblxuICBjb2RlLnB1c2goXCJ9cmV0dXJuIFwiICsgZnVuY05hbWUpXG4gIFxuICAvL0xpbmsgZXZlcnl0aGluZyB0b2dldGhlclxuICB2YXIgcmVzdWx0ID0gbmV3IEZ1bmN0aW9uKFwiaW5zZXJ0aW9uU29ydFwiLCBcInF1aWNrU29ydFwiLCBjb2RlLmpvaW4oXCJcXG5cIikpXG4gIHZhciBpbnNlcnRpb25Tb3J0ID0gY3JlYXRlSW5zZXJ0aW9uU29ydChvcmRlciwgZHR5cGUpXG4gIHZhciBxdWlja1NvcnQgPSBjcmVhdGVRdWlja1NvcnQob3JkZXIsIGR0eXBlLCBpbnNlcnRpb25Tb3J0KVxuICByZXR1cm4gcmVzdWx0KGluc2VydGlvblNvcnQsIHF1aWNrU29ydClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb21waWxlU29ydFxufSx7XCJ0eXBlZGFycmF5LXBvb2xcIjo1NDV9XSw0NDg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxudmFyIGNvbXBpbGUgPSBfZGVyZXFfKFwiLi9saWIvY29tcGlsZV9zb3J0LmpzXCIpXG52YXIgQ0FDSEUgPSB7fVxuXG5mdW5jdGlvbiBzb3J0KGFycmF5KSB7XG4gIHZhciBvcmRlciA9IGFycmF5Lm9yZGVyXG4gIHZhciBkdHlwZSA9IGFycmF5LmR0eXBlXG4gIHZhciB0eXBlU2lnID0gW29yZGVyLCBkdHlwZSBdXG4gIHZhciB0eXBlTmFtZSA9IHR5cGVTaWcuam9pbihcIjpcIilcbiAgdmFyIGNvbXBpbGVkID0gQ0FDSEVbdHlwZU5hbWVdXG4gIGlmKCFjb21waWxlZCkge1xuICAgIENBQ0hFW3R5cGVOYW1lXSA9IGNvbXBpbGVkID0gY29tcGlsZShvcmRlciwgZHR5cGUpXG4gIH1cbiAgY29tcGlsZWQoYXJyYXkpXG4gIHJldHVybiBhcnJheVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHNvcnRcbn0se1wiLi9saWIvY29tcGlsZV9zb3J0LmpzXCI6NDQ3fV0sNDQ5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgaW50ZXJwICA9IF9kZXJlcV8oJ25kYXJyYXktbGluZWFyLWludGVycG9sYXRlJylcblxuXG52YXIgZG9fd2FycCA9IF9kZXJlcV8oJ2N3aXNlL2xpYi93cmFwcGVyJykoe1wiYXJnc1wiOltcImluZGV4XCIsXCJhcnJheVwiLFwic2NhbGFyXCIsXCJzY2FsYXJcIixcInNjYWxhclwiXSxcInByZVwiOntcImJvZHlcIjpcInt0aGlzX3dhcnBlZD1uZXcgQXJyYXkoX2lubGluZV8zX2FyZzRfKX1cIixcImFyZ3NcIjpbe1wibmFtZVwiOlwiX2lubGluZV8zX2FyZzBfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOmZhbHNlLFwiY291bnRcIjowfSx7XCJuYW1lXCI6XCJfaW5saW5lXzNfYXJnMV9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6ZmFsc2UsXCJjb3VudFwiOjB9LHtcIm5hbWVcIjpcIl9pbmxpbmVfM19hcmcyX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjpmYWxzZSxcImNvdW50XCI6MH0se1wibmFtZVwiOlwiX2lubGluZV8zX2FyZzNfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOmZhbHNlLFwiY291bnRcIjowfSx7XCJuYW1lXCI6XCJfaW5saW5lXzNfYXJnNF9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX1dLFwidGhpc1ZhcnNcIjpbXCJ0aGlzX3dhcnBlZFwiXSxcImxvY2FsVmFyc1wiOltdfSxcImJvZHlcIjp7XCJib2R5XCI6XCJ7X2lubGluZV80X2FyZzJfKHRoaXNfd2FycGVkLF9pbmxpbmVfNF9hcmcwXyksX2lubGluZV80X2FyZzFfPV9pbmxpbmVfNF9hcmczXy5hcHBseSh2b2lkIDAsdGhpc193YXJwZWQpfVwiLFwiYXJnc1wiOlt7XCJuYW1lXCI6XCJfaW5saW5lXzRfYXJnMF9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV80X2FyZzFfXCIsXCJsdmFsdWVcIjp0cnVlLFwicnZhbHVlXCI6ZmFsc2UsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfNF9hcmcyX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzRfYXJnM19cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV80X2FyZzRfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOmZhbHNlLFwiY291bnRcIjowfV0sXCJ0aGlzVmFyc1wiOltcInRoaXNfd2FycGVkXCJdLFwibG9jYWxWYXJzXCI6W119LFwicG9zdFwiOntcImJvZHlcIjpcInt9XCIsXCJhcmdzXCI6W10sXCJ0aGlzVmFyc1wiOltdLFwibG9jYWxWYXJzXCI6W119LFwiZGVidWdcIjpmYWxzZSxcImZ1bmNOYW1lXCI6XCJ3YXJwTkRcIixcImJsb2NrU2l6ZVwiOjY0fSlcblxudmFyIGRvX3dhcnBfMSA9IF9kZXJlcV8oJ2N3aXNlL2xpYi93cmFwcGVyJykoe1wiYXJnc1wiOltcImluZGV4XCIsXCJhcnJheVwiLFwic2NhbGFyXCIsXCJzY2FsYXJcIixcInNjYWxhclwiXSxcInByZVwiOntcImJvZHlcIjpcInt0aGlzX3dhcnBlZD1bMF19XCIsXCJhcmdzXCI6W10sXCJ0aGlzVmFyc1wiOltcInRoaXNfd2FycGVkXCJdLFwibG9jYWxWYXJzXCI6W119LFwiYm9keVwiOntcImJvZHlcIjpcIntfaW5saW5lXzdfYXJnMl8odGhpc193YXJwZWQsX2lubGluZV83X2FyZzBfKSxfaW5saW5lXzdfYXJnMV89X2lubGluZV83X2FyZzNfKF9pbmxpbmVfN19hcmc0Xyx0aGlzX3dhcnBlZFswXSl9XCIsXCJhcmdzXCI6W3tcIm5hbWVcIjpcIl9pbmxpbmVfN19hcmcwX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzdfYXJnMV9cIixcImx2YWx1ZVwiOnRydWUsXCJydmFsdWVcIjpmYWxzZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV83X2FyZzJfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfN19hcmczX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzdfYXJnNF9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX1dLFwidGhpc1ZhcnNcIjpbXCJ0aGlzX3dhcnBlZFwiXSxcImxvY2FsVmFyc1wiOltdfSxcInBvc3RcIjp7XCJib2R5XCI6XCJ7fVwiLFwiYXJnc1wiOltdLFwidGhpc1ZhcnNcIjpbXSxcImxvY2FsVmFyc1wiOltdfSxcImRlYnVnXCI6ZmFsc2UsXCJmdW5jTmFtZVwiOlwid2FycDFEXCIsXCJibG9ja1NpemVcIjo2NH0pXG5cbnZhciBkb193YXJwXzIgPSBfZGVyZXFfKCdjd2lzZS9saWIvd3JhcHBlcicpKHtcImFyZ3NcIjpbXCJpbmRleFwiLFwiYXJyYXlcIixcInNjYWxhclwiLFwic2NhbGFyXCIsXCJzY2FsYXJcIl0sXCJwcmVcIjp7XCJib2R5XCI6XCJ7dGhpc193YXJwZWQ9WzAsMF19XCIsXCJhcmdzXCI6W10sXCJ0aGlzVmFyc1wiOltcInRoaXNfd2FycGVkXCJdLFwibG9jYWxWYXJzXCI6W119LFwiYm9keVwiOntcImJvZHlcIjpcIntfaW5saW5lXzEwX2FyZzJfKHRoaXNfd2FycGVkLF9pbmxpbmVfMTBfYXJnMF8pLF9pbmxpbmVfMTBfYXJnMV89X2lubGluZV8xMF9hcmczXyhfaW5saW5lXzEwX2FyZzRfLHRoaXNfd2FycGVkWzBdLHRoaXNfd2FycGVkWzFdKX1cIixcImFyZ3NcIjpbe1wibmFtZVwiOlwiX2lubGluZV8xMF9hcmcwX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzEwX2FyZzFfXCIsXCJsdmFsdWVcIjp0cnVlLFwicnZhbHVlXCI6ZmFsc2UsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTBfYXJnMl9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV8xMF9hcmczX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzEwX2FyZzRfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9XSxcInRoaXNWYXJzXCI6W1widGhpc193YXJwZWRcIl0sXCJsb2NhbFZhcnNcIjpbXX0sXCJwb3N0XCI6e1wiYm9keVwiOlwie31cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W10sXCJsb2NhbFZhcnNcIjpbXX0sXCJkZWJ1Z1wiOmZhbHNlLFwiZnVuY05hbWVcIjpcIndhcnAyRFwiLFwiYmxvY2tTaXplXCI6NjR9KVxuXG52YXIgZG9fd2FycF8zID0gX2RlcmVxXygnY3dpc2UvbGliL3dyYXBwZXInKSh7XCJhcmdzXCI6W1wiaW5kZXhcIixcImFycmF5XCIsXCJzY2FsYXJcIixcInNjYWxhclwiLFwic2NhbGFyXCJdLFwicHJlXCI6e1wiYm9keVwiOlwie3RoaXNfd2FycGVkPVswLDAsMF19XCIsXCJhcmdzXCI6W10sXCJ0aGlzVmFyc1wiOltcInRoaXNfd2FycGVkXCJdLFwibG9jYWxWYXJzXCI6W119LFwiYm9keVwiOntcImJvZHlcIjpcIntfaW5saW5lXzEzX2FyZzJfKHRoaXNfd2FycGVkLF9pbmxpbmVfMTNfYXJnMF8pLF9pbmxpbmVfMTNfYXJnMV89X2lubGluZV8xM19hcmczXyhfaW5saW5lXzEzX2FyZzRfLHRoaXNfd2FycGVkWzBdLHRoaXNfd2FycGVkWzFdLHRoaXNfd2FycGVkWzJdKX1cIixcImFyZ3NcIjpbe1wibmFtZVwiOlwiX2lubGluZV8xM19hcmcwX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzEzX2FyZzFfXCIsXCJsdmFsdWVcIjp0cnVlLFwicnZhbHVlXCI6ZmFsc2UsXCJjb3VudFwiOjF9LHtcIm5hbWVcIjpcIl9pbmxpbmVfMTNfYXJnMl9cIixcImx2YWx1ZVwiOmZhbHNlLFwicnZhbHVlXCI6dHJ1ZSxcImNvdW50XCI6MX0se1wibmFtZVwiOlwiX2lubGluZV8xM19hcmczX1wiLFwibHZhbHVlXCI6ZmFsc2UsXCJydmFsdWVcIjp0cnVlLFwiY291bnRcIjoxfSx7XCJuYW1lXCI6XCJfaW5saW5lXzEzX2FyZzRfXCIsXCJsdmFsdWVcIjpmYWxzZSxcInJ2YWx1ZVwiOnRydWUsXCJjb3VudFwiOjF9XSxcInRoaXNWYXJzXCI6W1widGhpc193YXJwZWRcIl0sXCJsb2NhbFZhcnNcIjpbXX0sXCJwb3N0XCI6e1wiYm9keVwiOlwie31cIixcImFyZ3NcIjpbXSxcInRoaXNWYXJzXCI6W10sXCJsb2NhbFZhcnNcIjpbXX0sXCJkZWJ1Z1wiOmZhbHNlLFwiZnVuY05hbWVcIjpcIndhcnAzRFwiLFwiYmxvY2tTaXplXCI6NjR9KVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHdhcnAoZGVzdCwgc3JjLCBmdW5jKSB7XG4gIHN3aXRjaChzcmMuc2hhcGUubGVuZ3RoKSB7XG4gICAgY2FzZSAxOlxuICAgICAgZG9fd2FycF8xKGRlc3QsIGZ1bmMsIGludGVycC5kMSwgc3JjKVxuICAgICAgYnJlYWtcbiAgICBjYXNlIDI6XG4gICAgICBkb193YXJwXzIoZGVzdCwgZnVuYywgaW50ZXJwLmQyLCBzcmMpXG4gICAgICBicmVha1xuICAgIGNhc2UgMzpcbiAgICAgIGRvX3dhcnBfMyhkZXN0LCBmdW5jLCBpbnRlcnAuZDMsIHNyYylcbiAgICAgIGJyZWFrXG4gICAgZGVmYXVsdDpcbiAgICAgIGRvX3dhcnAoZGVzdCwgZnVuYywgaW50ZXJwLmJpbmQodW5kZWZpbmVkLCBzcmMpLCBzcmMuc2hhcGUubGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgfVxuICByZXR1cm4gZGVzdFxufVxuXG59LHtcImN3aXNlL2xpYi93cmFwcGVyXCI6MTQ5LFwibmRhcnJheS1saW5lYXItaW50ZXJwb2xhdGVcIjo0NDN9XSw0NTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xudmFyIGlvdGEgPSBfZGVyZXFfKFwiaW90YS1hcnJheVwiKVxudmFyIGlzQnVmZmVyID0gX2RlcmVxXyhcImlzLWJ1ZmZlclwiKVxuXG52YXIgaGFzVHlwZWRBcnJheXMgID0gKCh0eXBlb2YgRmxvYXQ2NEFycmF5KSAhPT0gXCJ1bmRlZmluZWRcIilcblxuZnVuY3Rpb24gY29tcGFyZTFzdChhLCBiKSB7XG4gIHJldHVybiBhWzBdIC0gYlswXVxufVxuXG5mdW5jdGlvbiBvcmRlcigpIHtcbiAgdmFyIHN0cmlkZSA9IHRoaXMuc3RyaWRlXG4gIHZhciB0ZXJtcyA9IG5ldyBBcnJheShzdHJpZGUubGVuZ3RoKVxuICB2YXIgaVxuICBmb3IoaT0wOyBpPHRlcm1zLmxlbmd0aDsgKytpKSB7XG4gICAgdGVybXNbaV0gPSBbTWF0aC5hYnMoc3RyaWRlW2ldKSwgaV1cbiAgfVxuICB0ZXJtcy5zb3J0KGNvbXBhcmUxc3QpXG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkodGVybXMubGVuZ3RoKVxuICBmb3IoaT0wOyBpPHJlc3VsdC5sZW5ndGg7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IHRlcm1zW2ldWzFdXG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBjb21waWxlQ29uc3RydWN0b3IoZHR5cGUsIGRpbWVuc2lvbikge1xuICB2YXIgY2xhc3NOYW1lID0gW1wiVmlld1wiLCBkaW1lbnNpb24sIFwiZFwiLCBkdHlwZV0uam9pbihcIlwiKVxuICBpZihkaW1lbnNpb24gPCAwKSB7XG4gICAgY2xhc3NOYW1lID0gXCJWaWV3X05pbFwiICsgZHR5cGVcbiAgfVxuICB2YXIgdXNlR2V0dGVycyA9IChkdHlwZSA9PT0gXCJnZW5lcmljXCIpXG5cbiAgaWYoZGltZW5zaW9uID09PSAtMSkge1xuICAgIC8vU3BlY2lhbCBjYXNlIGZvciB0cml2aWFsIGFycmF5c1xuICAgIHZhciBjb2RlID1cbiAgICAgIFwiZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiKGEpe3RoaXMuZGF0YT1hO307XFxcbnZhciBwcm90bz1cIitjbGFzc05hbWUrXCIucHJvdG90eXBlO1xcXG5wcm90by5kdHlwZT0nXCIrZHR5cGUrXCInO1xcXG5wcm90by5pbmRleD1mdW5jdGlvbigpe3JldHVybiAtMX07XFxcbnByb3RvLnNpemU9MDtcXFxucHJvdG8uZGltZW5zaW9uPS0xO1xcXG5wcm90by5zaGFwZT1wcm90by5zdHJpZGU9cHJvdG8ub3JkZXI9W107XFxcbnByb3RvLmxvPXByb3RvLmhpPXByb3RvLnRyYW5zcG9zZT1wcm90by5zdGVwPVxcXG5mdW5jdGlvbigpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKHRoaXMuZGF0YSk7fTtcXFxucHJvdG8uZ2V0PXByb3RvLnNldD1mdW5jdGlvbigpe307XFxcbnByb3RvLnBpY2s9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH07XFxcbnJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RfXCIrY2xhc3NOYW1lK1wiKGEpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKGEpO31cIlxuICAgIHZhciBwcm9jZWR1cmUgPSBuZXcgRnVuY3Rpb24oY29kZSlcbiAgICByZXR1cm4gcHJvY2VkdXJlKClcbiAgfSBlbHNlIGlmKGRpbWVuc2lvbiA9PT0gMCkge1xuICAgIC8vU3BlY2lhbCBjYXNlIGZvciAwZCBhcnJheXNcbiAgICB2YXIgY29kZSA9XG4gICAgICBcImZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIihhLGQpIHtcXFxudGhpcy5kYXRhID0gYTtcXFxudGhpcy5vZmZzZXQgPSBkXFxcbn07XFxcbnZhciBwcm90bz1cIitjbGFzc05hbWUrXCIucHJvdG90eXBlO1xcXG5wcm90by5kdHlwZT0nXCIrZHR5cGUrXCInO1xcXG5wcm90by5pbmRleD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm9mZnNldH07XFxcbnByb3RvLmRpbWVuc2lvbj0wO1xcXG5wcm90by5zaXplPTE7XFxcbnByb3RvLnNoYXBlPVxcXG5wcm90by5zdHJpZGU9XFxcbnByb3RvLm9yZGVyPVtdO1xcXG5wcm90by5sbz1cXFxucHJvdG8uaGk9XFxcbnByb3RvLnRyYW5zcG9zZT1cXFxucHJvdG8uc3RlcD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfY29weSgpIHtcXFxucmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhLHRoaXMub2Zmc2V0KVxcXG59O1xcXG5wcm90by5waWNrPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9waWNrKCl7XFxcbnJldHVybiBUcml2aWFsQXJyYXkodGhpcy5kYXRhKTtcXFxufTtcXFxucHJvdG8udmFsdWVPZj1wcm90by5nZXQ9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2dldCgpe1xcXG5yZXR1cm4gXCIrKHVzZUdldHRlcnMgPyBcInRoaXMuZGF0YS5nZXQodGhpcy5vZmZzZXQpXCIgOiBcInRoaXMuZGF0YVt0aGlzLm9mZnNldF1cIikrXG5cIn07XFxcbnByb3RvLnNldD1mdW5jdGlvbiBcIitjbGFzc05hbWUrXCJfc2V0KHYpe1xcXG5yZXR1cm4gXCIrKHVzZUdldHRlcnMgPyBcInRoaXMuZGF0YS5zZXQodGhpcy5vZmZzZXQsdilcIiA6IFwidGhpcy5kYXRhW3RoaXMub2Zmc2V0XT12XCIpK1wiXFxcbn07XFxcbnJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RfXCIrY2xhc3NOYW1lK1wiKGEsYixjLGQpe3JldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKGEsZCl9XCJcbiAgICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKFwiVHJpdmlhbEFycmF5XCIsIGNvZGUpXG4gICAgcmV0dXJuIHByb2NlZHVyZShDQUNIRURfQ09OU1RSVUNUT1JTW2R0eXBlXVswXSlcbiAgfVxuXG4gIHZhciBjb2RlID0gW1wiJ3VzZSBzdHJpY3QnXCJdXG5cbiAgLy9DcmVhdGUgY29uc3RydWN0b3IgZm9yIHZpZXdcbiAgdmFyIGluZGljZXMgPSBpb3RhKGRpbWVuc2lvbilcbiAgdmFyIGFyZ3MgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiBcImlcIitpIH0pXG4gIHZhciBpbmRleF9zdHIgPSBcInRoaXMub2Zmc2V0K1wiICsgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgICByZXR1cm4gXCJ0aGlzLnN0cmlkZVtcIiArIGkgKyBcIl0qaVwiICsgaVxuICAgICAgfSkuam9pbihcIitcIilcbiAgdmFyIHNoYXBlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiYlwiK2lcbiAgICB9KS5qb2luKFwiLFwiKVxuICB2YXIgc3RyaWRlQXJnID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiY1wiK2lcbiAgICB9KS5qb2luKFwiLFwiKVxuICBjb2RlLnB1c2goXG4gICAgXCJmdW5jdGlvbiBcIitjbGFzc05hbWUrXCIoYSxcIiArIHNoYXBlQXJnICsgXCIsXCIgKyBzdHJpZGVBcmcgKyBcIixkKXt0aGlzLmRhdGE9YVwiLFxuICAgICAgXCJ0aGlzLnNoYXBlPVtcIiArIHNoYXBlQXJnICsgXCJdXCIsXG4gICAgICBcInRoaXMuc3RyaWRlPVtcIiArIHN0cmlkZUFyZyArIFwiXVwiLFxuICAgICAgXCJ0aGlzLm9mZnNldD1kfDB9XCIsXG4gICAgXCJ2YXIgcHJvdG89XCIrY2xhc3NOYW1lK1wiLnByb3RvdHlwZVwiLFxuICAgIFwicHJvdG8uZHR5cGU9J1wiK2R0eXBlK1wiJ1wiLFxuICAgIFwicHJvdG8uZGltZW5zaW9uPVwiK2RpbWVuc2lvbilcblxuICAvL3ZpZXcuc2l6ZTpcbiAgY29kZS5wdXNoKFwiT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCdzaXplJyx7Z2V0OmZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9zaXplKCl7XFxcbnJldHVybiBcIitpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiBcInRoaXMuc2hhcGVbXCIraStcIl1cIiB9KS5qb2luKFwiKlwiKSxcblwifX0pXCIpXG5cbiAgLy92aWV3Lm9yZGVyOlxuICBpZihkaW1lbnNpb24gPT09IDEpIHtcbiAgICBjb2RlLnB1c2goXCJwcm90by5vcmRlcj1bMF1cIilcbiAgfSBlbHNlIHtcbiAgICBjb2RlLnB1c2goXCJPYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG8sJ29yZGVyJyx7Z2V0OlwiKVxuICAgIGlmKGRpbWVuc2lvbiA8IDQpIHtcbiAgICAgIGNvZGUucHVzaChcImZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9vcmRlcigpe1wiKVxuICAgICAgaWYoZGltZW5zaW9uID09PSAyKSB7XG4gICAgICAgIGNvZGUucHVzaChcInJldHVybiAoTWF0aC5hYnModGhpcy5zdHJpZGVbMF0pPk1hdGguYWJzKHRoaXMuc3RyaWRlWzFdKSk/WzEsMF06WzAsMV19fSlcIilcbiAgICAgIH0gZWxzZSBpZihkaW1lbnNpb24gPT09IDMpIHtcbiAgICAgICAgY29kZS5wdXNoKFxuXCJ2YXIgczA9TWF0aC5hYnModGhpcy5zdHJpZGVbMF0pLHMxPU1hdGguYWJzKHRoaXMuc3RyaWRlWzFdKSxzMj1NYXRoLmFicyh0aGlzLnN0cmlkZVsyXSk7XFxcbmlmKHMwPnMxKXtcXFxuaWYoczE+czIpe1xcXG5yZXR1cm4gWzIsMSwwXTtcXFxufWVsc2UgaWYoczA+czIpe1xcXG5yZXR1cm4gWzEsMiwwXTtcXFxufWVsc2V7XFxcbnJldHVybiBbMSwwLDJdO1xcXG59XFxcbn1lbHNlIGlmKHMwPnMyKXtcXFxucmV0dXJuIFsyLDAsMV07XFxcbn1lbHNlIGlmKHMyPnMxKXtcXFxucmV0dXJuIFswLDEsMl07XFxcbn1lbHNle1xcXG5yZXR1cm4gWzAsMiwxXTtcXFxufX19KVwiKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlLnB1c2goXCJPUkRFUn0pXCIpXG4gICAgfVxuICB9XG5cbiAgLy92aWV3LnNldChpMCwgLi4uLCB2KTpcbiAgY29kZS5wdXNoKFxuXCJwcm90by5zZXQ9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX3NldChcIithcmdzLmpvaW4oXCIsXCIpK1wiLHYpe1wiKVxuICBpZih1c2VHZXR0ZXJzKSB7XG4gICAgY29kZS5wdXNoKFwicmV0dXJuIHRoaXMuZGF0YS5zZXQoXCIraW5kZXhfc3RyK1wiLHYpfVwiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcInJldHVybiB0aGlzLmRhdGFbXCIraW5kZXhfc3RyK1wiXT12fVwiKVxuICB9XG5cbiAgLy92aWV3LmdldChpMCwgLi4uKTpcbiAgY29kZS5wdXNoKFwicHJvdG8uZ2V0PWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9nZXQoXCIrYXJncy5qb2luKFwiLFwiKStcIil7XCIpXG4gIGlmKHVzZUdldHRlcnMpIHtcbiAgICBjb2RlLnB1c2goXCJyZXR1cm4gdGhpcy5kYXRhLmdldChcIitpbmRleF9zdHIrXCIpfVwiKVxuICB9IGVsc2Uge1xuICAgIGNvZGUucHVzaChcInJldHVybiB0aGlzLmRhdGFbXCIraW5kZXhfc3RyK1wiXX1cIilcbiAgfVxuXG4gIC8vdmlldy5pbmRleDpcbiAgY29kZS5wdXNoKFxuICAgIFwicHJvdG8uaW5kZXg9ZnVuY3Rpb24gXCIrY2xhc3NOYW1lK1wiX2luZGV4KFwiLCBhcmdzLmpvaW4oKSwgXCIpe3JldHVybiBcIitpbmRleF9zdHIrXCJ9XCIpXG5cbiAgLy92aWV3LmhpKCk6XG4gIGNvZGUucHVzaChcInByb3RvLmhpPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9oaShcIithcmdzLmpvaW4oXCIsXCIpK1wiKXtyZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIih0aGlzLmRhdGEsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFtcIih0eXBlb2YgaVwiLGksXCIhPT0nbnVtYmVyJ3x8aVwiLGksXCI8MCk/dGhpcy5zaGFwZVtcIiwgaSwgXCJdOmlcIiwgaSxcInwwXCJdLmpvaW4oXCJcIilcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJ0aGlzLnN0cmlkZVtcIitpICsgXCJdXCJcbiAgICB9KS5qb2luKFwiLFwiKStcIix0aGlzLm9mZnNldCl9XCIpXG5cbiAgLy92aWV3LmxvKCk6XG4gIHZhciBhX3ZhcnMgPSBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7IHJldHVybiBcImFcIitpK1wiPXRoaXMuc2hhcGVbXCIraStcIl1cIiB9KVxuICB2YXIgY192YXJzID0gaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkgeyByZXR1cm4gXCJjXCIraStcIj10aGlzLnN0cmlkZVtcIitpK1wiXVwiIH0pXG4gIGNvZGUucHVzaChcInByb3RvLmxvPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9sbyhcIithcmdzLmpvaW4oXCIsXCIpK1wiKXt2YXIgYj10aGlzLm9mZnNldCxkPTAsXCIrYV92YXJzLmpvaW4oXCIsXCIpK1wiLFwiK2NfdmFycy5qb2luKFwiLFwiKSlcbiAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBjb2RlLnB1c2goXG5cImlmKHR5cGVvZiBpXCIraStcIj09PSdudW1iZXInJiZpXCIraStcIj49MCl7XFxcbmQ9aVwiK2krXCJ8MDtcXFxuYis9Y1wiK2krXCIqZDtcXFxuYVwiK2krXCItPWR9XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwicmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcImFcIitpXG4gICAgfSkuam9pbihcIixcIikrXCIsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiY1wiK2lcbiAgICB9KS5qb2luKFwiLFwiKStcIixiKX1cIilcblxuICAvL3ZpZXcuc3RlcCgpOlxuICBjb2RlLnB1c2goXCJwcm90by5zdGVwPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9zdGVwKFwiK2FyZ3Muam9pbihcIixcIikrXCIpe3ZhciBcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJhXCIraStcIj10aGlzLnNoYXBlW1wiK2krXCJdXCJcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJiXCIraStcIj10aGlzLnN0cmlkZVtcIitpK1wiXVwiXG4gICAgfSkuam9pbihcIixcIikrXCIsYz10aGlzLm9mZnNldCxkPTAsY2VpbD1NYXRoLmNlaWxcIilcbiAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICBjb2RlLnB1c2goXG5cImlmKHR5cGVvZiBpXCIraStcIj09PSdudW1iZXInKXtcXFxuZD1pXCIraStcInwwO1xcXG5pZihkPDApe1xcXG5jKz1iXCIraStcIiooYVwiK2krXCItMSk7XFxcbmFcIitpK1wiPWNlaWwoLWFcIitpK1wiL2QpXFxcbn1lbHNle1xcXG5hXCIraStcIj1jZWlsKGFcIitpK1wiL2QpXFxcbn1cXFxuYlwiK2krXCIqPWRcXFxufVwiKVxuICB9XG4gIGNvZGUucHVzaChcInJldHVybiBuZXcgXCIrY2xhc3NOYW1lK1wiKHRoaXMuZGF0YSxcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJhXCIgKyBpXG4gICAgfSkuam9pbihcIixcIikrXCIsXCIrXG4gICAgaW5kaWNlcy5tYXAoZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIFwiYlwiICsgaVxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLGMpfVwiKVxuXG4gIC8vdmlldy50cmFuc3Bvc2UoKTpcbiAgdmFyIHRTaGFwZSA9IG5ldyBBcnJheShkaW1lbnNpb24pXG4gIHZhciB0U3RyaWRlID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgZm9yKHZhciBpPTA7IGk8ZGltZW5zaW9uOyArK2kpIHtcbiAgICB0U2hhcGVbaV0gPSBcImFbaVwiK2krXCJdXCJcbiAgICB0U3RyaWRlW2ldID0gXCJiW2lcIitpK1wiXVwiXG4gIH1cbiAgY29kZS5wdXNoKFwicHJvdG8udHJhbnNwb3NlPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl90cmFuc3Bvc2UoXCIrYXJncytcIil7XCIrXG4gICAgYXJncy5tYXAoZnVuY3Rpb24obixpZHgpIHsgcmV0dXJuIG4gKyBcIj0oXCIgKyBuICsgXCI9PT11bmRlZmluZWQ/XCIgKyBpZHggKyBcIjpcIiArIG4gKyBcInwwKVwifSkuam9pbihcIjtcIiksXG4gICAgXCJ2YXIgYT10aGlzLnNoYXBlLGI9dGhpcy5zdHJpZGU7cmV0dXJuIG5ldyBcIitjbGFzc05hbWUrXCIodGhpcy5kYXRhLFwiK3RTaGFwZS5qb2luKFwiLFwiKStcIixcIit0U3RyaWRlLmpvaW4oXCIsXCIpK1wiLHRoaXMub2Zmc2V0KX1cIilcblxuICAvL3ZpZXcucGljaygpOlxuICBjb2RlLnB1c2goXCJwcm90by5waWNrPWZ1bmN0aW9uIFwiK2NsYXNzTmFtZStcIl9waWNrKFwiK2FyZ3MrXCIpe3ZhciBhPVtdLGI9W10sYz10aGlzLm9mZnNldFwiKVxuICBmb3IodmFyIGk9MDsgaTxkaW1lbnNpb247ICsraSkge1xuICAgIGNvZGUucHVzaChcImlmKHR5cGVvZiBpXCIraStcIj09PSdudW1iZXInJiZpXCIraStcIj49MCl7Yz0oYyt0aGlzLnN0cmlkZVtcIitpK1wiXSppXCIraStcIil8MH1lbHNle2EucHVzaCh0aGlzLnNoYXBlW1wiK2krXCJdKTtiLnB1c2godGhpcy5zdHJpZGVbXCIraStcIl0pfVwiKVxuICB9XG4gIGNvZGUucHVzaChcInZhciBjdG9yPUNUT1JfTElTVFthLmxlbmd0aCsxXTtyZXR1cm4gY3Rvcih0aGlzLmRhdGEsYSxiLGMpfVwiKVxuXG4gIC8vQWRkIHJldHVybiBzdGF0ZW1lbnRcbiAgY29kZS5wdXNoKFwicmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdF9cIitjbGFzc05hbWUrXCIoZGF0YSxzaGFwZSxzdHJpZGUsb2Zmc2V0KXtyZXR1cm4gbmV3IFwiK2NsYXNzTmFtZStcIihkYXRhLFwiK1xuICAgIGluZGljZXMubWFwKGZ1bmN0aW9uKGkpIHtcbiAgICAgIHJldHVybiBcInNoYXBlW1wiK2krXCJdXCJcbiAgICB9KS5qb2luKFwiLFwiKStcIixcIitcbiAgICBpbmRpY2VzLm1hcChmdW5jdGlvbihpKSB7XG4gICAgICByZXR1cm4gXCJzdHJpZGVbXCIraStcIl1cIlxuICAgIH0pLmpvaW4oXCIsXCIpK1wiLG9mZnNldCl9XCIpXG5cbiAgLy9Db21waWxlIHByb2NlZHVyZVxuICB2YXIgcHJvY2VkdXJlID0gbmV3IEZ1bmN0aW9uKFwiQ1RPUl9MSVNUXCIsIFwiT1JERVJcIiwgY29kZS5qb2luKFwiXFxuXCIpKVxuICByZXR1cm4gcHJvY2VkdXJlKENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdLCBvcmRlcilcbn1cblxuZnVuY3Rpb24gYXJyYXlEVHlwZShkYXRhKSB7XG4gIGlmKGlzQnVmZmVyKGRhdGEpKSB7XG4gICAgcmV0dXJuIFwiYnVmZmVyXCJcbiAgfVxuICBpZihoYXNUeXBlZEFycmF5cykge1xuICAgIHN3aXRjaChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZGF0YSkpIHtcbiAgICAgIGNhc2UgXCJbb2JqZWN0IEZsb2F0NjRBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwiZmxvYXQ2NFwiXG4gICAgICBjYXNlIFwiW29iamVjdCBGbG9hdDMyQXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcImZsb2F0MzJcIlxuICAgICAgY2FzZSBcIltvYmplY3QgSW50OEFycmF5XVwiOlxuICAgICAgICByZXR1cm4gXCJpbnQ4XCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IEludDE2QXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcImludDE2XCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IEludDMyQXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcImludDMyXCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IFVpbnQ4QXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcInVpbnQ4XCJcbiAgICAgIGNhc2UgXCJbb2JqZWN0IFVpbnQxNkFycmF5XVwiOlxuICAgICAgICByZXR1cm4gXCJ1aW50MTZcIlxuICAgICAgY2FzZSBcIltvYmplY3QgVWludDMyQXJyYXldXCI6XG4gICAgICAgIHJldHVybiBcInVpbnQzMlwiXG4gICAgICBjYXNlIFwiW29iamVjdCBVaW50OENsYW1wZWRBcnJheV1cIjpcbiAgICAgICAgcmV0dXJuIFwidWludDhfY2xhbXBlZFwiXG4gICAgfVxuICB9XG4gIGlmKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICByZXR1cm4gXCJhcnJheVwiXG4gIH1cbiAgcmV0dXJuIFwiZ2VuZXJpY1wiXG59XG5cbnZhciBDQUNIRURfQ09OU1RSVUNUT1JTID0ge1xuICBcImZsb2F0MzJcIjpbXSxcbiAgXCJmbG9hdDY0XCI6W10sXG4gIFwiaW50OFwiOltdLFxuICBcImludDE2XCI6W10sXG4gIFwiaW50MzJcIjpbXSxcbiAgXCJ1aW50OFwiOltdLFxuICBcInVpbnQxNlwiOltdLFxuICBcInVpbnQzMlwiOltdLFxuICBcImFycmF5XCI6W10sXG4gIFwidWludDhfY2xhbXBlZFwiOltdLFxuICBcImJ1ZmZlclwiOltdLFxuICBcImdlbmVyaWNcIjpbXVxufVxuXG47KGZ1bmN0aW9uKCkge1xuICBmb3IodmFyIGlkIGluIENBQ0hFRF9DT05TVFJVQ1RPUlMpIHtcbiAgICBDQUNIRURfQ09OU1RSVUNUT1JTW2lkXS5wdXNoKGNvbXBpbGVDb25zdHJ1Y3RvcihpZCwgLTEpKVxuICB9XG59KTtcblxuZnVuY3Rpb24gd3JhcHBlZE5EQXJyYXlDdG9yKGRhdGEsIHNoYXBlLCBzdHJpZGUsIG9mZnNldCkge1xuICBpZihkYXRhID09PSB1bmRlZmluZWQpIHtcbiAgICB2YXIgY3RvciA9IENBQ0hFRF9DT05TVFJVQ1RPUlMuYXJyYXlbMF1cbiAgICByZXR1cm4gY3RvcihbXSlcbiAgfSBlbHNlIGlmKHR5cGVvZiBkYXRhID09PSBcIm51bWJlclwiKSB7XG4gICAgZGF0YSA9IFtkYXRhXVxuICB9XG4gIGlmKHNoYXBlID09PSB1bmRlZmluZWQpIHtcbiAgICBzaGFwZSA9IFsgZGF0YS5sZW5ndGggXVxuICB9XG4gIHZhciBkID0gc2hhcGUubGVuZ3RoXG4gIGlmKHN0cmlkZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgc3RyaWRlID0gbmV3IEFycmF5KGQpXG4gICAgZm9yKHZhciBpPWQtMSwgc3o9MTsgaT49MDsgLS1pKSB7XG4gICAgICBzdHJpZGVbaV0gPSBzelxuICAgICAgc3ogKj0gc2hhcGVbaV1cbiAgICB9XG4gIH1cbiAgaWYob2Zmc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICBvZmZzZXQgPSAwXG4gICAgZm9yKHZhciBpPTA7IGk8ZDsgKytpKSB7XG4gICAgICBpZihzdHJpZGVbaV0gPCAwKSB7XG4gICAgICAgIG9mZnNldCAtPSAoc2hhcGVbaV0tMSkqc3RyaWRlW2ldXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHZhciBkdHlwZSA9IGFycmF5RFR5cGUoZGF0YSlcbiAgdmFyIGN0b3JfbGlzdCA9IENBQ0hFRF9DT05TVFJVQ1RPUlNbZHR5cGVdXG4gIHdoaWxlKGN0b3JfbGlzdC5sZW5ndGggPD0gZCsxKSB7XG4gICAgY3Rvcl9saXN0LnB1c2goY29tcGlsZUNvbnN0cnVjdG9yKGR0eXBlLCBjdG9yX2xpc3QubGVuZ3RoLTEpKVxuICB9XG4gIHZhciBjdG9yID0gY3Rvcl9saXN0W2QrMV1cbiAgcmV0dXJuIGN0b3IoZGF0YSwgc2hhcGUsIHN0cmlkZSwgb2Zmc2V0KVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHdyYXBwZWROREFycmF5Q3RvclxuXG59LHtcImlvdGEtYXJyYXlcIjo0MTYsXCJpcy1idWZmZXJcIjo0MTh9XSw0NTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxudmFyIGRvdWJsZUJpdHMgPSBfZGVyZXFfKFwiZG91YmxlLWJpdHNcIilcblxudmFyIFNNQUxMRVNUX0RFTk9STSA9IE1hdGgucG93KDIsIC0xMDc0KVxudmFyIFVJTlRfTUFYID0gKC0xKT4+PjBcblxubW9kdWxlLmV4cG9ydHMgPSBuZXh0YWZ0ZXJcblxuZnVuY3Rpb24gbmV4dGFmdGVyKHgsIHkpIHtcbiAgaWYoaXNOYU4oeCkgfHwgaXNOYU4oeSkpIHtcbiAgICByZXR1cm4gTmFOXG4gIH1cbiAgaWYoeCA9PT0geSkge1xuICAgIHJldHVybiB4XG4gIH1cbiAgaWYoeCA9PT0gMCkge1xuICAgIGlmKHkgPCAwKSB7XG4gICAgICByZXR1cm4gLVNNQUxMRVNUX0RFTk9STVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gU01BTExFU1RfREVOT1JNXG4gICAgfVxuICB9XG4gIHZhciBoaSA9IGRvdWJsZUJpdHMuaGkoeClcbiAgdmFyIGxvID0gZG91YmxlQml0cy5sbyh4KVxuICBpZigoeSA+IHgpID09PSAoeCA+IDApKSB7XG4gICAgaWYobG8gPT09IFVJTlRfTUFYKSB7XG4gICAgICBoaSArPSAxXG4gICAgICBsbyA9IDBcbiAgICB9IGVsc2Uge1xuICAgICAgbG8gKz0gMVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZihsbyA9PT0gMCkge1xuICAgICAgbG8gPSBVSU5UX01BWFxuICAgICAgaGkgLT0gMVxuICAgIH0gZWxzZSB7XG4gICAgICBsbyAtPSAxXG4gICAgfVxuICB9XG4gIHJldHVybiBkb3VibGVCaXRzLnBhY2sobG8sIGhpKVxufVxufSx7XCJkb3VibGUtYml0c1wiOjE2N31dLDQ1MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cbnZhciDPgCA9IE1hdGguUElcbnZhciBfMTIwID0gcmFkaWFucygxMjApXG5cbm1vZHVsZS5leHBvcnRzID0gbm9ybWFsaXplXG5cbi8qKlxuICogZGVzY3JpYmUgYHBhdGhgIGluIHRlcm1zIG9mIGN1YmljIGLDqXppZXIgXG4gKiBjdXJ2ZXMgYW5kIG1vdmUgY29tbWFuZHNcbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBwYXRoXG4gKiBAcmV0dXJuIHtBcnJheX1cbiAqL1xuXG5mdW5jdGlvbiBub3JtYWxpemUocGF0aCl7XG5cdC8vIGluaXQgc3RhdGVcblx0dmFyIHByZXZcblx0dmFyIHJlc3VsdCA9IFtdXG5cdHZhciBiZXppZXJYID0gMFxuXHR2YXIgYmV6aWVyWSA9IDBcblx0dmFyIHN0YXJ0WCA9IDBcblx0dmFyIHN0YXJ0WSA9IDBcblx0dmFyIHF1YWRYID0gbnVsbFxuXHR2YXIgcXVhZFkgPSBudWxsXG5cdHZhciB4ID0gMFxuXHR2YXIgeSA9IDBcblxuXHRmb3IgKHZhciBpID0gMCwgbGVuID0gcGF0aC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdHZhciBzZWcgPSBwYXRoW2ldXG5cdFx0dmFyIGNvbW1hbmQgPSBzZWdbMF1cblx0XHRzd2l0Y2ggKGNvbW1hbmQpIHtcblx0XHRcdGNhc2UgJ00nOlxuXHRcdFx0XHRzdGFydFggPSBzZWdbMV1cblx0XHRcdFx0c3RhcnRZID0gc2VnWzJdXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRjYXNlICdBJzpcblx0XHRcdFx0c2VnID0gYXJjKHgsIHksc2VnWzFdLHNlZ1syXSxyYWRpYW5zKHNlZ1szXSksc2VnWzRdLHNlZ1s1XSxzZWdbNl0sc2VnWzddKVxuXHRcdFx0XHQvLyBzcGxpdCBtdWx0aSBwYXJ0XG5cdFx0XHRcdHNlZy51bnNoaWZ0KCdDJylcblx0XHRcdFx0aWYgKHNlZy5sZW5ndGggPiA3KSB7XG5cdFx0XHRcdFx0cmVzdWx0LnB1c2goc2VnLnNwbGljZSgwLCA3KSlcblx0XHRcdFx0XHRzZWcudW5zaGlmdCgnQycpXG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgJ1MnOlxuXHRcdFx0XHQvLyBkZWZhdWx0IGNvbnRyb2wgcG9pbnRcblx0XHRcdFx0dmFyIGN4ID0geFxuXHRcdFx0XHR2YXIgY3kgPSB5XG5cdFx0XHRcdGlmIChwcmV2ID09ICdDJyB8fCBwcmV2ID09ICdTJykge1xuXHRcdFx0XHRcdGN4ICs9IGN4IC0gYmV6aWVyWCAvLyByZWZsZWN0IHRoZSBwcmV2aW91cyBjb21tYW5kJ3MgY29udHJvbFxuXHRcdFx0XHRcdGN5ICs9IGN5IC0gYmV6aWVyWSAvLyBwb2ludCByZWxhdGl2ZSB0byB0aGUgY3VycmVudCBwb2ludFxuXHRcdFx0XHR9XG5cdFx0XHRcdHNlZyA9IFsnQycsIGN4LCBjeSwgc2VnWzFdLCBzZWdbMl0sIHNlZ1szXSwgc2VnWzRdXVxuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAnVCc6XG5cdFx0XHRcdGlmIChwcmV2ID09ICdRJyB8fCBwcmV2ID09ICdUJykge1xuXHRcdFx0XHRcdHF1YWRYID0geCAqIDIgLSBxdWFkWCAvLyBhcyB3aXRoICdTJyByZWZsZWN0IHByZXZpb3VzIGNvbnRyb2wgcG9pbnRcblx0XHRcdFx0XHRxdWFkWSA9IHkgKiAyIC0gcXVhZFlcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRxdWFkWCA9IHhcblx0XHRcdFx0XHRxdWFkWSA9IHlcblx0XHRcdFx0fVxuXHRcdFx0XHRzZWcgPSBxdWFkcmF0aWMoeCwgeSwgcXVhZFgsIHF1YWRZLCBzZWdbMV0sIHNlZ1syXSlcblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgJ1EnOlxuXHRcdFx0XHRxdWFkWCA9IHNlZ1sxXVxuXHRcdFx0XHRxdWFkWSA9IHNlZ1syXVxuXHRcdFx0XHRzZWcgPSBxdWFkcmF0aWMoeCwgeSwgc2VnWzFdLCBzZWdbMl0sIHNlZ1szXSwgc2VnWzRdKVxuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAnTCc6XG5cdFx0XHRcdHNlZyA9IGxpbmUoeCwgeSwgc2VnWzFdLCBzZWdbMl0pXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRjYXNlICdIJzpcblx0XHRcdFx0c2VnID0gbGluZSh4LCB5LCBzZWdbMV0sIHkpXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRjYXNlICdWJzpcblx0XHRcdFx0c2VnID0gbGluZSh4LCB5LCB4LCBzZWdbMV0pXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRjYXNlICdaJzpcblx0XHRcdFx0c2VnID0gbGluZSh4LCB5LCBzdGFydFgsIHN0YXJ0WSlcblx0XHRcdFx0YnJlYWtcblx0XHR9XG5cblx0XHQvLyB1cGRhdGUgc3RhdGVcblx0XHRwcmV2ID0gY29tbWFuZFxuXHRcdHggPSBzZWdbc2VnLmxlbmd0aCAtIDJdXG5cdFx0eSA9IHNlZ1tzZWcubGVuZ3RoIC0gMV1cblx0XHRpZiAoc2VnLmxlbmd0aCA+IDQpIHtcblx0XHRcdGJlemllclggPSBzZWdbc2VnLmxlbmd0aCAtIDRdXG5cdFx0XHRiZXppZXJZID0gc2VnW3NlZy5sZW5ndGggLSAzXVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRiZXppZXJYID0geFxuXHRcdFx0YmV6aWVyWSA9IHlcblx0XHR9XG5cdFx0cmVzdWx0LnB1c2goc2VnKVxuXHR9XG5cblx0cmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBsaW5lKHgxLCB5MSwgeDIsIHkyKXtcblx0cmV0dXJuIFsnQycsIHgxLCB5MSwgeDIsIHkyLCB4MiwgeTJdXG59XG5cbmZ1bmN0aW9uIHF1YWRyYXRpYyh4MSwgeTEsIGN4LCBjeSwgeDIsIHkyKXtcblx0cmV0dXJuIFtcblx0XHQnQycsXG5cdFx0eDEvMyArICgyLzMpICogY3gsXG5cdFx0eTEvMyArICgyLzMpICogY3ksXG5cdFx0eDIvMyArICgyLzMpICogY3gsXG5cdFx0eTIvMyArICgyLzMpICogY3ksXG5cdFx0eDIsXG5cdFx0eTJcblx0XVxufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIGlzIHJpcHBlZCBmcm9tIFxuLy8gZ2l0aHViLmNvbS9EbWl0cnlCYXJhbm92c2tpeS9yYXBoYWVsL2Jsb2IvNGQ5N2Q0L3JhcGhhZWwuanMjTDIyMTYtTDIzMDQgXG4vLyB3aGljaCByZWZlcmVuY2VzIHczLm9yZy9UUi9TVkcxMS9pbXBsbm90ZS5odG1sI0FyY0ltcGxlbWVudGF0aW9uTm90ZXNcbi8vIFRPRE86IG1ha2UgaXQgaHVtYW4gcmVhZGFibGVcblxuZnVuY3Rpb24gYXJjKHgxLCB5MSwgcngsIHJ5LCBhbmdsZSwgbGFyZ2VfYXJjX2ZsYWcsIHN3ZWVwX2ZsYWcsIHgyLCB5MiwgcmVjdXJzaXZlKSB7XG5cdGlmICghcmVjdXJzaXZlKSB7XG5cdFx0dmFyIHh5ID0gcm90YXRlKHgxLCB5MSwgLWFuZ2xlKVxuXHRcdHgxID0geHkueFxuXHRcdHkxID0geHkueVxuXHRcdHh5ID0gcm90YXRlKHgyLCB5MiwgLWFuZ2xlKVxuXHRcdHgyID0geHkueFxuXHRcdHkyID0geHkueVxuXHRcdHZhciB4ID0gKHgxIC0geDIpIC8gMlxuXHRcdHZhciB5ID0gKHkxIC0geTIpIC8gMlxuXHRcdHZhciBoID0gKHggKiB4KSAvIChyeCAqIHJ4KSArICh5ICogeSkgLyAocnkgKiByeSlcblx0XHRpZiAoaCA+IDEpIHtcblx0XHRcdGggPSBNYXRoLnNxcnQoaClcblx0XHRcdHJ4ID0gaCAqIHJ4XG5cdFx0XHRyeSA9IGggKiByeVxuXHRcdH1cblx0XHR2YXIgcngyID0gcnggKiByeFxuXHRcdHZhciByeTIgPSByeSAqIHJ5XG5cdFx0dmFyIGsgPSAobGFyZ2VfYXJjX2ZsYWcgPT0gc3dlZXBfZmxhZyA/IC0xIDogMSlcblx0XHRcdCogTWF0aC5zcXJ0KE1hdGguYWJzKChyeDIgKiByeTIgLSByeDIgKiB5ICogeSAtIHJ5MiAqIHggKiB4KSAvIChyeDIgKiB5ICogeSArIHJ5MiAqIHggKiB4KSkpXG5cdFx0aWYgKGsgPT0gSW5maW5pdHkpIGsgPSAxIC8vIG5ldXRyYWxpemVcblx0XHR2YXIgY3ggPSBrICogcnggKiB5IC8gcnkgKyAoeDEgKyB4MikgLyAyXG5cdFx0dmFyIGN5ID0gayAqIC1yeSAqIHggLyByeCArICh5MSArIHkyKSAvIDJcblx0XHR2YXIgZjEgPSBNYXRoLmFzaW4oKCh5MSAtIGN5KSAvIHJ5KS50b0ZpeGVkKDkpKVxuXHRcdHZhciBmMiA9IE1hdGguYXNpbigoKHkyIC0gY3kpIC8gcnkpLnRvRml4ZWQoOSkpXG5cblx0XHRmMSA9IHgxIDwgY3ggPyDPgCAtIGYxIDogZjFcblx0XHRmMiA9IHgyIDwgY3ggPyDPgCAtIGYyIDogZjJcblx0XHRpZiAoZjEgPCAwKSBmMSA9IM+AICogMiArIGYxXG5cdFx0aWYgKGYyIDwgMCkgZjIgPSDPgCAqIDIgKyBmMlxuXHRcdGlmIChzd2VlcF9mbGFnICYmIGYxID4gZjIpIGYxID0gZjEgLSDPgCAqIDJcblx0XHRpZiAoIXN3ZWVwX2ZsYWcgJiYgZjIgPiBmMSkgZjIgPSBmMiAtIM+AICogMlxuXHR9IGVsc2Uge1xuXHRcdGYxID0gcmVjdXJzaXZlWzBdXG5cdFx0ZjIgPSByZWN1cnNpdmVbMV1cblx0XHRjeCA9IHJlY3Vyc2l2ZVsyXVxuXHRcdGN5ID0gcmVjdXJzaXZlWzNdXG5cdH1cblx0Ly8gZ3JlYXRlciB0aGFuIDEyMCBkZWdyZWVzIHJlcXVpcmVzIG11bHRpcGxlIHNlZ21lbnRzXG5cdGlmIChNYXRoLmFicyhmMiAtIGYxKSA+IF8xMjApIHtcblx0XHR2YXIgZjJvbGQgPSBmMlxuXHRcdHZhciB4Mm9sZCA9IHgyXG5cdFx0dmFyIHkyb2xkID0geTJcblx0XHRmMiA9IGYxICsgXzEyMCAqIChzd2VlcF9mbGFnICYmIGYyID4gZjEgPyAxIDogLTEpXG5cdFx0eDIgPSBjeCArIHJ4ICogTWF0aC5jb3MoZjIpXG5cdFx0eTIgPSBjeSArIHJ5ICogTWF0aC5zaW4oZjIpXG5cdFx0dmFyIHJlcyA9IGFyYyh4MiwgeTIsIHJ4LCByeSwgYW5nbGUsIDAsIHN3ZWVwX2ZsYWcsIHgyb2xkLCB5Mm9sZCwgW2YyLCBmMm9sZCwgY3gsIGN5XSlcblx0fVxuXHR2YXIgdCA9IE1hdGgudGFuKChmMiAtIGYxKSAvIDQpXG5cdHZhciBoeCA9IDQgLyAzICogcnggKiB0XG5cdHZhciBoeSA9IDQgLyAzICogcnkgKiB0XG5cdHZhciBjdXJ2ZSA9IFtcblx0XHQyICogeDEgLSAoeDEgKyBoeCAqIE1hdGguc2luKGYxKSksXG5cdFx0MiAqIHkxIC0gKHkxIC0gaHkgKiBNYXRoLmNvcyhmMSkpLFxuXHRcdHgyICsgaHggKiBNYXRoLnNpbihmMiksXG5cdFx0eTIgLSBoeSAqIE1hdGguY29zKGYyKSxcblx0XHR4Mixcblx0XHR5MlxuXHRdXG5cdGlmIChyZWN1cnNpdmUpIHJldHVybiBjdXJ2ZVxuXHRpZiAocmVzKSBjdXJ2ZSA9IGN1cnZlLmNvbmNhdChyZXMpXG5cdGZvciAodmFyIGkgPSAwOyBpIDwgY3VydmUubGVuZ3RoOykge1xuXHRcdHZhciByb3QgPSByb3RhdGUoY3VydmVbaV0sIGN1cnZlW2krMV0sIGFuZ2xlKVxuXHRcdGN1cnZlW2krK10gPSByb3QueFxuXHRcdGN1cnZlW2krK10gPSByb3QueVxuXHR9XG5cdHJldHVybiBjdXJ2ZVxufVxuXG5mdW5jdGlvbiByb3RhdGUoeCwgeSwgcmFkKXtcblx0cmV0dXJuIHtcblx0XHR4OiB4ICogTWF0aC5jb3MocmFkKSAtIHkgKiBNYXRoLnNpbihyYWQpLFxuXHRcdHk6IHggKiBNYXRoLnNpbihyYWQpICsgeSAqIE1hdGguY29zKHJhZClcblx0fVxufVxuXG5mdW5jdGlvbiByYWRpYW5zKGRlZ3Jlc3Mpe1xuXHRyZXR1cm4gZGVncmVzcyAqICjPgCAvIDE4MClcbn1cblxufSx7fV0sNDUzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciBERUZBVUxUX05PUk1BTFNfRVBTSUxPTiA9IDFlLTY7XG52YXIgREVGQVVMVF9GQUNFX0VQU0lMT04gPSAxZS02O1xuXG4vL0VzdGltYXRlIHRoZSB2ZXJ0ZXggbm9ybWFscyBvZiBhIG1lc2hcbmV4cG9ydHMudmVydGV4Tm9ybWFscyA9IGZ1bmN0aW9uKGZhY2VzLCBwb3NpdGlvbnMsIHNwZWNpZmllZEVwc2lsb24pIHtcblxuICB2YXIgTiAgICAgICAgID0gcG9zaXRpb25zLmxlbmd0aDtcbiAgdmFyIG5vcm1hbHMgICA9IG5ldyBBcnJheShOKTtcbiAgdmFyIGVwc2lsb24gICA9IHNwZWNpZmllZEVwc2lsb24gPT09IHZvaWQoMCkgPyBERUZBVUxUX05PUk1BTFNfRVBTSUxPTiA6IHNwZWNpZmllZEVwc2lsb247XG5cbiAgLy9Jbml0aWFsaXplIG5vcm1hbCBhcnJheVxuICBmb3IodmFyIGk9MDsgaTxOOyArK2kpIHtcbiAgICBub3JtYWxzW2ldID0gWzAuMCwgMC4wLCAwLjBdO1xuICB9XG5cbiAgLy9XYWxrIG92ZXIgYWxsIHRoZSBmYWNlcyBhbmQgYWRkIHBlci12ZXJ0ZXggY29udHJpYnV0aW9uIHRvIG5vcm1hbCB3ZWlnaHRzXG4gIGZvcih2YXIgaT0wOyBpPGZhY2VzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGYgPSBmYWNlc1tpXTtcbiAgICB2YXIgcCA9IDA7XG4gICAgdmFyIGMgPSBmW2YubGVuZ3RoLTFdO1xuICAgIHZhciBuID0gZlswXTtcbiAgICBmb3IodmFyIGo9MDsgajxmLmxlbmd0aDsgKytqKSB7XG5cbiAgICAgIC8vU2hpZnQgaW5kaWNlcyBiYWNrXG4gICAgICBwID0gYztcbiAgICAgIGMgPSBuO1xuICAgICAgbiA9IGZbKGorMSkgJSBmLmxlbmd0aF07XG5cbiAgICAgIHZhciB2MCA9IHBvc2l0aW9uc1twXTtcbiAgICAgIHZhciB2MSA9IHBvc2l0aW9uc1tjXTtcbiAgICAgIHZhciB2MiA9IHBvc2l0aW9uc1tuXTtcblxuICAgICAgLy9Db21wdXRlIGluZmluZXRlaXNtYWwgYXJjc1xuICAgICAgdmFyIGQwMSA9IG5ldyBBcnJheSgzKTtcbiAgICAgIHZhciBtMDEgPSAwLjA7XG4gICAgICB2YXIgZDIxID0gbmV3IEFycmF5KDMpO1xuICAgICAgdmFyIG0yMSA9IDAuMDtcbiAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xuICAgICAgICBkMDFba10gPSB2MFtrXSAgLSB2MVtrXTtcbiAgICAgICAgbTAxICAgKz0gZDAxW2tdICogZDAxW2tdO1xuICAgICAgICBkMjFba10gPSB2MltrXSAgLSB2MVtrXTtcbiAgICAgICAgbTIxICAgKz0gZDIxW2tdICogZDIxW2tdO1xuICAgICAgfVxuXG4gICAgICAvL0FjY3VtdWxhdGUgdmFsdWVzIGluIG5vcm1hbFxuICAgICAgaWYobTAxICogbTIxID4gZXBzaWxvbikge1xuICAgICAgICB2YXIgbm9ybSA9IG5vcm1hbHNbY107XG4gICAgICAgIHZhciB3ID0gMS4wIC8gTWF0aC5zcXJ0KG0wMSAqIG0yMSk7XG4gICAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xuICAgICAgICAgIHZhciB1ID0gKGsrMSklMztcbiAgICAgICAgICB2YXIgdiA9IChrKzIpJTM7XG4gICAgICAgICAgbm9ybVtrXSArPSB3ICogKGQyMVt1XSAqIGQwMVt2XSAtIGQyMVt2XSAqIGQwMVt1XSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvL1NjYWxlIGFsbCBub3JtYWxzIHRvIHVuaXQgbGVuZ3RoXG4gIGZvcih2YXIgaT0wOyBpPE47ICsraSkge1xuICAgIHZhciBub3JtID0gbm9ybWFsc1tpXTtcbiAgICB2YXIgbSA9IDAuMDtcbiAgICBmb3IodmFyIGs9MDsgazwzOyArK2spIHtcbiAgICAgIG0gKz0gbm9ybVtrXSAqIG5vcm1ba107XG4gICAgfVxuICAgIGlmKG0gPiBlcHNpbG9uKSB7XG4gICAgICB2YXIgdyA9IDEuMCAvIE1hdGguc3FydChtKTtcbiAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xuICAgICAgICBub3JtW2tdICo9IHc7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvcih2YXIgaz0wOyBrPDM7ICsraykge1xuICAgICAgICBub3JtW2tdID0gMC4wO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vUmV0dXJuIHRoZSByZXN1bHRpbmcgc2V0IG9mIHBhdGNoZXNcbiAgcmV0dXJuIG5vcm1hbHM7XG59XG5cbi8vQ29tcHV0ZSBmYWNlIG5vcm1hbHMgb2YgYSBtZXNoXG5leHBvcnRzLmZhY2VOb3JtYWxzID0gZnVuY3Rpb24oZmFjZXMsIHBvc2l0aW9ucywgc3BlY2lmaWVkRXBzaWxvbikge1xuXG4gIHZhciBOICAgICAgICAgPSBmYWNlcy5sZW5ndGg7XG4gIHZhciBub3JtYWxzICAgPSBuZXcgQXJyYXkoTik7XG4gIHZhciBlcHNpbG9uICAgPSBzcGVjaWZpZWRFcHNpbG9uID09PSB2b2lkKDApID8gREVGQVVMVF9GQUNFX0VQU0lMT04gOiBzcGVjaWZpZWRFcHNpbG9uO1xuXG4gIGZvcih2YXIgaT0wOyBpPE47ICsraSkge1xuICAgIHZhciBmID0gZmFjZXNbaV07XG4gICAgdmFyIHBvcyA9IG5ldyBBcnJheSgzKTtcbiAgICBmb3IodmFyIGo9MDsgajwzOyArK2opIHtcbiAgICAgIHBvc1tqXSA9IHBvc2l0aW9uc1tmW2pdXTtcbiAgICB9XG5cbiAgICB2YXIgZDAxID0gbmV3IEFycmF5KDMpO1xuICAgIHZhciBkMjEgPSBuZXcgQXJyYXkoMyk7XG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICBkMDFbal0gPSBwb3NbMV1bal0gLSBwb3NbMF1bal07XG4gICAgICBkMjFbal0gPSBwb3NbMl1bal0gLSBwb3NbMF1bal07XG4gICAgfVxuXG4gICAgdmFyIG4gPSBuZXcgQXJyYXkoMyk7XG4gICAgdmFyIGwgPSAwLjA7XG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICB2YXIgdSA9IChqKzEpJTM7XG4gICAgICB2YXIgdiA9IChqKzIpJTM7XG4gICAgICBuW2pdID0gZDAxW3VdICogZDIxW3ZdIC0gZDAxW3ZdICogZDIxW3VdO1xuICAgICAgbCArPSBuW2pdICogbltqXTtcbiAgICB9XG4gICAgaWYobCA+IGVwc2lsb24pIHtcbiAgICAgIGwgPSAxLjAgLyBNYXRoLnNxcnQobCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGwgPSAwLjA7XG4gICAgfVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgbltqXSAqPSBsO1xuICAgIH1cbiAgICBub3JtYWxzW2ldID0gbjtcbiAgfVxuICByZXR1cm4gbm9ybWFscztcbn1cblxuXG5cbn0se31dLDQ1NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKlxub2JqZWN0LWFzc2lnblxuKGMpIFNpbmRyZSBTb3JodXNcbkBsaWNlbnNlIE1JVFxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cbnZhciBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzO1xudmFyIGhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcbnZhciBwcm9wSXNFbnVtZXJhYmxlID0gT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxuZnVuY3Rpb24gdG9PYmplY3QodmFsKSB7XG5cdGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHtcblx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCdPYmplY3QuYXNzaWduIGNhbm5vdCBiZSBjYWxsZWQgd2l0aCBudWxsIG9yIHVuZGVmaW5lZCcpO1xuXHR9XG5cblx0cmV0dXJuIE9iamVjdCh2YWwpO1xufVxuXG5mdW5jdGlvbiBzaG91bGRVc2VOYXRpdmUoKSB7XG5cdHRyeSB7XG5cdFx0aWYgKCFPYmplY3QuYXNzaWduKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly8gRGV0ZWN0IGJ1Z2d5IHByb3BlcnR5IGVudW1lcmF0aW9uIG9yZGVyIGluIG9sZGVyIFY4IHZlcnNpb25zLlxuXG5cdFx0Ly8gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9NDExOFxuXHRcdHZhciB0ZXN0MSA9IG5ldyBTdHJpbmcoJ2FiYycpOyAgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1uZXctd3JhcHBlcnNcblx0XHR0ZXN0MVs1XSA9ICdkZSc7XG5cdFx0aWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRlc3QxKVswXSA9PT0gJzUnKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly8gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MzA1NlxuXHRcdHZhciB0ZXN0MiA9IHt9O1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgMTA7IGkrKykge1xuXHRcdFx0dGVzdDJbJ18nICsgU3RyaW5nLmZyb21DaGFyQ29kZShpKV0gPSBpO1xuXHRcdH1cblx0XHR2YXIgb3JkZXIyID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGVzdDIpLm1hcChmdW5jdGlvbiAobikge1xuXHRcdFx0cmV0dXJuIHRlc3QyW25dO1xuXHRcdH0pO1xuXHRcdGlmIChvcmRlcjIuam9pbignJykgIT09ICcwMTIzNDU2Nzg5Jykge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMwNTZcblx0XHR2YXIgdGVzdDMgPSB7fTtcblx0XHQnYWJjZGVmZ2hpamtsbW5vcHFyc3QnLnNwbGl0KCcnKS5mb3JFYWNoKGZ1bmN0aW9uIChsZXR0ZXIpIHtcblx0XHRcdHRlc3QzW2xldHRlcl0gPSBsZXR0ZXI7XG5cdFx0fSk7XG5cdFx0aWYgKE9iamVjdC5rZXlzKE9iamVjdC5hc3NpZ24oe30sIHRlc3QzKSkuam9pbignJykgIT09XG5cdFx0XHRcdCdhYmNkZWZnaGlqa2xtbm9wcXJzdCcpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0Ly8gV2UgZG9uJ3QgZXhwZWN0IGFueSBvZiB0aGUgYWJvdmUgdG8gdGhyb3csIGJ1dCBiZXR0ZXIgdG8gYmUgc2FmZS5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzaG91bGRVc2VOYXRpdmUoKSA/IE9iamVjdC5hc3NpZ24gOiBmdW5jdGlvbiAodGFyZ2V0LCBzb3VyY2UpIHtcblx0dmFyIGZyb207XG5cdHZhciB0byA9IHRvT2JqZWN0KHRhcmdldCk7XG5cdHZhciBzeW1ib2xzO1xuXG5cdGZvciAodmFyIHMgPSAxOyBzIDwgYXJndW1lbnRzLmxlbmd0aDsgcysrKSB7XG5cdFx0ZnJvbSA9IE9iamVjdChhcmd1bWVudHNbc10pO1xuXG5cdFx0Zm9yICh2YXIga2V5IGluIGZyb20pIHtcblx0XHRcdGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKGZyb20sIGtleSkpIHtcblx0XHRcdFx0dG9ba2V5XSA9IGZyb21ba2V5XTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoZ2V0T3duUHJvcGVydHlTeW1ib2xzKSB7XG5cdFx0XHRzeW1ib2xzID0gZ2V0T3duUHJvcGVydHlTeW1ib2xzKGZyb20pO1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBzeW1ib2xzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGlmIChwcm9wSXNFbnVtZXJhYmxlLmNhbGwoZnJvbSwgc3ltYm9sc1tpXSkpIHtcblx0XHRcdFx0XHR0b1tzeW1ib2xzW2ldXSA9IGZyb21bc3ltYm9sc1tpXV07XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gdG87XG59O1xuXG59LHt9XSw0NTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gcXVhdEZyb21GcmFtZVxuXG5mdW5jdGlvbiBxdWF0RnJvbUZyYW1lKFxuICBvdXQsXG4gIHJ4LCByeSwgcnosXG4gIHV4LCB1eSwgdXosXG4gIGZ4LCBmeSwgZnopIHtcbiAgdmFyIHRyID0gcnggKyB1eSArIGZ6XG4gIGlmKGwgPiAwKSB7XG4gICAgdmFyIGwgPSBNYXRoLnNxcnQodHIgKyAxLjApXG4gICAgb3V0WzBdID0gMC41ICogKHV6IC0gZnkpIC8gbFxuICAgIG91dFsxXSA9IDAuNSAqIChmeCAtIHJ6KSAvIGxcbiAgICBvdXRbMl0gPSAwLjUgKiAocnkgLSB1eSkgLyBsXG4gICAgb3V0WzNdID0gMC41ICogbFxuICB9IGVsc2Uge1xuICAgIHZhciB0ZiA9IE1hdGgubWF4KHJ4LCB1eSwgZnopXG4gICAgdmFyIGwgPSBNYXRoLnNxcnQoMiAqIHRmIC0gdHIgKyAxLjApXG4gICAgaWYocnggPj0gdGYpIHtcbiAgICAgIC8veCB5IHogIG9yZGVyXG4gICAgICBvdXRbMF0gPSAwLjUgKiBsXG4gICAgICBvdXRbMV0gPSAwLjUgKiAodXggKyByeSkgLyBsXG4gICAgICBvdXRbMl0gPSAwLjUgKiAoZnggKyByeikgLyBsXG4gICAgICBvdXRbM10gPSAwLjUgKiAodXogLSBmeSkgLyBsXG4gICAgfSBlbHNlIGlmKHV5ID49IHRmKSB7XG4gICAgICAvL3kgeiB4ICBvcmRlclxuICAgICAgb3V0WzBdID0gMC41ICogKHJ5ICsgdXgpIC8gbFxuICAgICAgb3V0WzFdID0gMC41ICogbFxuICAgICAgb3V0WzJdID0gMC41ICogKGZ5ICsgdXopIC8gbFxuICAgICAgb3V0WzNdID0gMC41ICogKGZ4IC0gcnopIC8gbFxuICAgIH0gZWxzZSB7XG4gICAgICAvL3ogeCB5ICBvcmRlclxuICAgICAgb3V0WzBdID0gMC41ICogKHJ6ICsgZngpIC8gbFxuICAgICAgb3V0WzFdID0gMC41ICogKHV6ICsgZnkpIC8gbFxuICAgICAgb3V0WzJdID0gMC41ICogbFxuICAgICAgb3V0WzNdID0gMC41ICogKHJ5IC0gdXgpIC8gbFxuICAgIH1cbiAgfVxuICByZXR1cm4gb3V0XG59XG59LHt9XSw0NTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlT3JiaXRDb250cm9sbGVyXG5cbnZhciBmaWx0ZXJWZWN0b3IgID0gX2RlcmVxXygnZmlsdGVyZWQtdmVjdG9yJylcbnZhciBsb29rQXQgICAgICAgID0gX2RlcmVxXygnZ2wtbWF0NC9sb29rQXQnKVxudmFyIG1hdDRGcm9tUXVhdCAgPSBfZGVyZXFfKCdnbC1tYXQ0L2Zyb21RdWF0JylcbnZhciBpbnZlcnQ0NCAgICAgID0gX2RlcmVxXygnZ2wtbWF0NC9pbnZlcnQnKVxudmFyIHF1YXRGcm9tRnJhbWUgPSBfZGVyZXFfKCcuL2xpYi9xdWF0RnJvbUZyYW1lJylcblxuZnVuY3Rpb24gbGVuMyh4LHkseikge1xuICByZXR1cm4gTWF0aC5zcXJ0KE1hdGgucG93KHgsMikgKyBNYXRoLnBvdyh5LDIpICsgTWF0aC5wb3coeiwyKSlcbn1cblxuZnVuY3Rpb24gbGVuNCh3LHgseSx6KSB7XG4gIHJldHVybiBNYXRoLnNxcnQoTWF0aC5wb3codywyKSArIE1hdGgucG93KHgsMikgKyBNYXRoLnBvdyh5LDIpICsgTWF0aC5wb3coeiwyKSlcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplNChvdXQsIGEpIHtcbiAgdmFyIGF4ID0gYVswXVxuICB2YXIgYXkgPSBhWzFdXG4gIHZhciBheiA9IGFbMl1cbiAgdmFyIGF3ID0gYVszXVxuICB2YXIgYWwgPSBsZW40KGF4LCBheSwgYXosIGF3KVxuICBpZihhbCA+IDFlLTYpIHtcbiAgICBvdXRbMF0gPSBheC9hbFxuICAgIG91dFsxXSA9IGF5L2FsXG4gICAgb3V0WzJdID0gYXovYWxcbiAgICBvdXRbM10gPSBhdy9hbFxuICB9IGVsc2Uge1xuICAgIG91dFswXSA9IG91dFsxXSA9IG91dFsyXSA9IDAuMFxuICAgIG91dFszXSA9IDEuMFxuICB9XG59XG5cbmZ1bmN0aW9uIE9yYml0Q2FtZXJhQ29udHJvbGxlcihpbml0UXVhdCwgaW5pdENlbnRlciwgaW5pdFJhZGl1cykge1xuICB0aGlzLnJhZGl1cyAgICA9IGZpbHRlclZlY3RvcihbaW5pdFJhZGl1c10pXG4gIHRoaXMuY2VudGVyICAgID0gZmlsdGVyVmVjdG9yKGluaXRDZW50ZXIpXG4gIHRoaXMucm90YXRpb24gID0gZmlsdGVyVmVjdG9yKGluaXRRdWF0KVxuXG4gIHRoaXMuY29tcHV0ZWRSYWRpdXMgICA9IHRoaXMucmFkaXVzLmN1cnZlKDApXG4gIHRoaXMuY29tcHV0ZWRDZW50ZXIgICA9IHRoaXMuY2VudGVyLmN1cnZlKDApXG4gIHRoaXMuY29tcHV0ZWRSb3RhdGlvbiA9IHRoaXMucm90YXRpb24uY3VydmUoMClcbiAgdGhpcy5jb21wdXRlZFVwICAgICAgID0gWzAuMSwwLDBdXG4gIHRoaXMuY29tcHV0ZWRFeWUgICAgICA9IFswLjEsMCwwXVxuICB0aGlzLmNvbXB1dGVkTWF0cml4ICAgPSBbMC4xLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXVxuXG4gIHRoaXMucmVjYWxjTWF0cml4KDApXG59XG5cbnZhciBwcm90byA9IE9yYml0Q2FtZXJhQ29udHJvbGxlci5wcm90b3R5cGVcblxucHJvdG8ubGFzdFQgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIE1hdGgubWF4KFxuICAgIHRoaXMucmFkaXVzLmxhc3RUKCksXG4gICAgdGhpcy5jZW50ZXIubGFzdFQoKSxcbiAgICB0aGlzLnJvdGF0aW9uLmxhc3RUKCkpXG59XG5cbnByb3RvLnJlY2FsY01hdHJpeCA9IGZ1bmN0aW9uKHQpIHtcbiAgdGhpcy5yYWRpdXMuY3VydmUodClcbiAgdGhpcy5jZW50ZXIuY3VydmUodClcbiAgdGhpcy5yb3RhdGlvbi5jdXJ2ZSh0KVxuXG4gIHZhciBxdWF0ID0gdGhpcy5jb21wdXRlZFJvdGF0aW9uXG4gIG5vcm1hbGl6ZTQocXVhdCwgcXVhdClcblxuICB2YXIgbWF0ID0gdGhpcy5jb21wdXRlZE1hdHJpeFxuICBtYXQ0RnJvbVF1YXQobWF0LCBxdWF0KVxuXG4gIHZhciBjZW50ZXIgPSB0aGlzLmNvbXB1dGVkQ2VudGVyXG4gIHZhciBleWUgICAgPSB0aGlzLmNvbXB1dGVkRXllXG4gIHZhciB1cCAgICAgPSB0aGlzLmNvbXB1dGVkVXBcbiAgdmFyIHJhZGl1cyA9IE1hdGguZXhwKHRoaXMuY29tcHV0ZWRSYWRpdXNbMF0pXG5cbiAgZXllWzBdID0gY2VudGVyWzBdICsgcmFkaXVzICogbWF0WzJdXG4gIGV5ZVsxXSA9IGNlbnRlclsxXSArIHJhZGl1cyAqIG1hdFs2XVxuICBleWVbMl0gPSBjZW50ZXJbMl0gKyByYWRpdXMgKiBtYXRbMTBdXG4gIHVwWzBdID0gbWF0WzFdXG4gIHVwWzFdID0gbWF0WzVdXG4gIHVwWzJdID0gbWF0WzldXG5cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgdmFyIHJyID0gMC4wXG4gICAgZm9yKHZhciBqPTA7IGo8MzsgKytqKSB7XG4gICAgICByciArPSBtYXRbaSs0KmpdICogZXllW2pdXG4gICAgfVxuICAgIG1hdFsxMitpXSA9IC1yclxuICB9XG59XG5cbnByb3RvLmdldE1hdHJpeCA9IGZ1bmN0aW9uKHQsIHJlc3VsdCkge1xuICB0aGlzLnJlY2FsY01hdHJpeCh0KVxuICB2YXIgbSA9IHRoaXMuY29tcHV0ZWRNYXRyaXhcbiAgaWYocmVzdWx0KSB7XG4gICAgZm9yKHZhciBpPTA7IGk8MTY7ICsraSkge1xuICAgICAgcmVzdWx0W2ldID0gbVtpXVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cbiAgcmV0dXJuIG1cbn1cblxucHJvdG8uaWRsZSA9IGZ1bmN0aW9uKHQpIHtcbiAgdGhpcy5jZW50ZXIuaWRsZSh0KVxuICB0aGlzLnJhZGl1cy5pZGxlKHQpXG4gIHRoaXMucm90YXRpb24uaWRsZSh0KVxufVxuXG5wcm90by5mbHVzaCA9IGZ1bmN0aW9uKHQpIHtcbiAgdGhpcy5jZW50ZXIuZmx1c2godClcbiAgdGhpcy5yYWRpdXMuZmx1c2godClcbiAgdGhpcy5yb3RhdGlvbi5mbHVzaCh0KVxufVxuXG5wcm90by5wYW4gPSBmdW5jdGlvbih0LCBkeCwgZHksIGR6KSB7XG4gIGR4ID0gZHggfHwgMC4wXG4gIGR5ID0gZHkgfHwgMC4wXG4gIGR6ID0gZHogfHwgMC4wXG5cbiAgdGhpcy5yZWNhbGNNYXRyaXgodClcbiAgdmFyIG1hdCA9IHRoaXMuY29tcHV0ZWRNYXRyaXhcblxuICB2YXIgdXggPSBtYXRbMV1cbiAgdmFyIHV5ID0gbWF0WzVdXG4gIHZhciB1eiA9IG1hdFs5XVxuICB2YXIgdWwgPSBsZW4zKHV4LCB1eSwgdXopXG4gIHV4IC89IHVsXG4gIHV5IC89IHVsXG4gIHV6IC89IHVsXG5cbiAgdmFyIHJ4ID0gbWF0WzBdXG4gIHZhciByeSA9IG1hdFs0XVxuICB2YXIgcnogPSBtYXRbOF1cbiAgdmFyIHJ1ID0gcnggKiB1eCArIHJ5ICogdXkgKyByeiAqIHV6XG4gIHJ4IC09IHV4ICogcnVcbiAgcnkgLT0gdXkgKiBydVxuICByeiAtPSB1eiAqIHJ1XG4gIHZhciBybCA9IGxlbjMocngsIHJ5LCByeilcbiAgcnggLz0gcmxcbiAgcnkgLz0gcmxcbiAgcnogLz0gcmxcblxuICB2YXIgZnggPSBtYXRbMl1cbiAgdmFyIGZ5ID0gbWF0WzZdXG4gIHZhciBmeiA9IG1hdFsxMF1cbiAgdmFyIGZ1ID0gZnggKiB1eCArIGZ5ICogdXkgKyBmeiAqIHV6XG4gIHZhciBmciA9IGZ4ICogcnggKyBmeSAqIHJ5ICsgZnogKiByelxuICBmeCAtPSBmdSAqIHV4ICsgZnIgKiByeFxuICBmeSAtPSBmdSAqIHV5ICsgZnIgKiByeVxuICBmeiAtPSBmdSAqIHV6ICsgZnIgKiByelxuICB2YXIgZmwgPSBsZW4zKGZ4LCBmeSwgZnopXG4gIGZ4IC89IGZsXG4gIGZ5IC89IGZsXG4gIGZ6IC89IGZsXG5cbiAgdmFyIHZ4ID0gcnggKiBkeCArIHV4ICogZHlcbiAgdmFyIHZ5ID0gcnkgKiBkeCArIHV5ICogZHlcbiAgdmFyIHZ6ID0gcnogKiBkeCArIHV6ICogZHlcblxuICB0aGlzLmNlbnRlci5tb3ZlKHQsIHZ4LCB2eSwgdnopXG5cbiAgLy9VcGRhdGUgei1jb21wb25lbnQgb2YgcmFkaXVzXG4gIHZhciByYWRpdXMgPSBNYXRoLmV4cCh0aGlzLmNvbXB1dGVkUmFkaXVzWzBdKVxuICByYWRpdXMgPSBNYXRoLm1heCgxZS00LCByYWRpdXMgKyBkeilcbiAgdGhpcy5yYWRpdXMuc2V0KHQsIE1hdGgubG9nKHJhZGl1cykpXG59XG5cbnByb3RvLnJvdGF0ZSA9IGZ1bmN0aW9uKHQsIGR4LCBkeSwgZHopIHtcbiAgdGhpcy5yZWNhbGNNYXRyaXgodClcblxuICBkeCA9IGR4fHwwLjBcbiAgZHkgPSBkeXx8MC4wXG5cbiAgdmFyIG1hdCA9IHRoaXMuY29tcHV0ZWRNYXRyaXhcblxuICB2YXIgcnggPSBtYXRbMF1cbiAgdmFyIHJ5ID0gbWF0WzRdXG4gIHZhciByeiA9IG1hdFs4XVxuXG4gIHZhciB1eCA9IG1hdFsxXVxuICB2YXIgdXkgPSBtYXRbNV1cbiAgdmFyIHV6ID0gbWF0WzldXG5cbiAgdmFyIGZ4ID0gbWF0WzJdXG4gIHZhciBmeSA9IG1hdFs2XVxuICB2YXIgZnogPSBtYXRbMTBdXG5cbiAgdmFyIHF4ID0gZHggKiByeCArIGR5ICogdXhcbiAgdmFyIHF5ID0gZHggKiByeSArIGR5ICogdXlcbiAgdmFyIHF6ID0gZHggKiByeiArIGR5ICogdXpcblxuICB2YXIgYnggPSAtKGZ5ICogcXogLSBmeiAqIHF5KVxuICB2YXIgYnkgPSAtKGZ6ICogcXggLSBmeCAqIHF6KVxuICB2YXIgYnogPSAtKGZ4ICogcXkgLSBmeSAqIHF4KSAgXG4gIHZhciBidyA9IE1hdGguc3FydChNYXRoLm1heCgwLjAsIDEuMCAtIE1hdGgucG93KGJ4LDIpIC0gTWF0aC5wb3coYnksMikgLSBNYXRoLnBvdyhieiwyKSkpXG4gIHZhciBibCA9IGxlbjQoYngsIGJ5LCBieiwgYncpXG4gIGlmKGJsID4gMWUtNikge1xuICAgIGJ4IC89IGJsXG4gICAgYnkgLz0gYmxcbiAgICBieiAvPSBibFxuICAgIGJ3IC89IGJsXG4gIH0gZWxzZSB7XG4gICAgYnggPSBieSA9IGJ6ID0gMC4wXG4gICAgYncgPSAxLjBcbiAgfVxuXG4gIHZhciByb3RhdGlvbiA9IHRoaXMuY29tcHV0ZWRSb3RhdGlvblxuICB2YXIgYXggPSByb3RhdGlvblswXVxuICB2YXIgYXkgPSByb3RhdGlvblsxXVxuICB2YXIgYXogPSByb3RhdGlvblsyXVxuICB2YXIgYXcgPSByb3RhdGlvblszXVxuXG4gIHZhciBjeCA9IGF4KmJ3ICsgYXcqYnggKyBheSpieiAtIGF6KmJ5XG4gIHZhciBjeSA9IGF5KmJ3ICsgYXcqYnkgKyBheipieCAtIGF4KmJ6XG4gIHZhciBjeiA9IGF6KmJ3ICsgYXcqYnogKyBheCpieSAtIGF5KmJ4XG4gIHZhciBjdyA9IGF3KmJ3IC0gYXgqYnggLSBheSpieSAtIGF6KmJ6XG4gIFxuICAvL0FwcGx5IHJvbGxcbiAgaWYoZHopIHtcbiAgICBieCA9IGZ4XG4gICAgYnkgPSBmeVxuICAgIGJ6ID0gZnpcbiAgICB2YXIgcyA9IE1hdGguc2luKGR6KSAvIGxlbjMoYngsIGJ5LCBieilcbiAgICBieCAqPSBzXG4gICAgYnkgKj0gc1xuICAgIGJ6ICo9IHNcbiAgICBidyA9IE1hdGguY29zKGR4KVxuICAgIGN4ID0gY3gqYncgKyBjdypieCArIGN5KmJ6IC0gY3oqYnlcbiAgICBjeSA9IGN5KmJ3ICsgY3cqYnkgKyBjeipieCAtIGN4KmJ6XG4gICAgY3ogPSBjeipidyArIGN3KmJ6ICsgY3gqYnkgLSBjeSpieFxuICAgIGN3ID0gY3cqYncgLSBjeCpieCAtIGN5KmJ5IC0gY3oqYnpcbiAgfVxuXG4gIHZhciBjbCA9IGxlbjQoY3gsIGN5LCBjeiwgY3cpXG4gIGlmKGNsID4gMWUtNikge1xuICAgIGN4IC89IGNsXG4gICAgY3kgLz0gY2xcbiAgICBjeiAvPSBjbFxuICAgIGN3IC89IGNsXG4gIH0gZWxzZSB7XG4gICAgY3ggPSBjeSA9IGN6ID0gMC4wXG4gICAgY3cgPSAxLjBcbiAgfVxuXG4gIHRoaXMucm90YXRpb24uc2V0KHQsIGN4LCBjeSwgY3osIGN3KVxufVxuXG5wcm90by5sb29rQXQgPSBmdW5jdGlvbih0LCBleWUsIGNlbnRlciwgdXApIHtcbiAgdGhpcy5yZWNhbGNNYXRyaXgodClcblxuICBjZW50ZXIgPSBjZW50ZXIgfHwgdGhpcy5jb21wdXRlZENlbnRlclxuICBleWUgICAgPSBleWUgICAgfHwgdGhpcy5jb21wdXRlZEV5ZVxuICB1cCAgICAgPSB1cCAgICAgfHwgdGhpcy5jb21wdXRlZFVwXG5cbiAgdmFyIG1hdCA9IHRoaXMuY29tcHV0ZWRNYXRyaXhcbiAgbG9va0F0KG1hdCwgZXllLCBjZW50ZXIsIHVwKVxuXG4gIHZhciByb3RhdGlvbiA9IHRoaXMuY29tcHV0ZWRSb3RhdGlvblxuICBxdWF0RnJvbUZyYW1lKHJvdGF0aW9uLFxuICAgIG1hdFswXSwgbWF0WzFdLCBtYXRbMl0sXG4gICAgbWF0WzRdLCBtYXRbNV0sIG1hdFs2XSxcbiAgICBtYXRbOF0sIG1hdFs5XSwgbWF0WzEwXSlcbiAgbm9ybWFsaXplNChyb3RhdGlvbiwgcm90YXRpb24pXG4gIHRoaXMucm90YXRpb24uc2V0KHQsIHJvdGF0aW9uWzBdLCByb3RhdGlvblsxXSwgcm90YXRpb25bMl0sIHJvdGF0aW9uWzNdKVxuXG4gIHZhciBmbCA9IDAuMFxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICBmbCArPSBNYXRoLnBvdyhjZW50ZXJbaV0gLSBleWVbaV0sIDIpXG4gIH1cbiAgdGhpcy5yYWRpdXMuc2V0KHQsIDAuNSAqIE1hdGgubG9nKE1hdGgubWF4KGZsLCAxZS02KSkpXG5cbiAgdGhpcy5jZW50ZXIuc2V0KHQsIGNlbnRlclswXSwgY2VudGVyWzFdLCBjZW50ZXJbMl0pXG59XG5cbnByb3RvLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uKHQsIGR4LCBkeSwgZHopIHtcbiAgdGhpcy5jZW50ZXIubW92ZSh0LFxuICAgIGR4fHwwLjAsXG4gICAgZHl8fDAuMCxcbiAgICBkenx8MC4wKVxufVxuXG5wcm90by5zZXRNYXRyaXggPSBmdW5jdGlvbih0LCBtYXRyaXgpIHtcblxuICB2YXIgcm90YXRpb24gPSB0aGlzLmNvbXB1dGVkUm90YXRpb25cbiAgcXVhdEZyb21GcmFtZShyb3RhdGlvbixcbiAgICBtYXRyaXhbMF0sIG1hdHJpeFsxXSwgbWF0cml4WzJdLFxuICAgIG1hdHJpeFs0XSwgbWF0cml4WzVdLCBtYXRyaXhbNl0sXG4gICAgbWF0cml4WzhdLCBtYXRyaXhbOV0sIG1hdHJpeFsxMF0pXG4gIG5vcm1hbGl6ZTQocm90YXRpb24sIHJvdGF0aW9uKVxuICB0aGlzLnJvdGF0aW9uLnNldCh0LCByb3RhdGlvblswXSwgcm90YXRpb25bMV0sIHJvdGF0aW9uWzJdLCByb3RhdGlvblszXSlcblxuICB2YXIgbWF0ID0gdGhpcy5jb21wdXRlZE1hdHJpeFxuICBpbnZlcnQ0NChtYXQsIG1hdHJpeClcbiAgdmFyIHcgPSBtYXRbMTVdXG4gIGlmKE1hdGguYWJzKHcpID4gMWUtNikge1xuICAgIHZhciBjeCA9IG1hdFsxMl0vd1xuICAgIHZhciBjeSA9IG1hdFsxM10vd1xuICAgIHZhciBjeiA9IG1hdFsxNF0vd1xuXG4gICAgdGhpcy5yZWNhbGNNYXRyaXgodCkgIFxuICAgIHZhciByID0gTWF0aC5leHAodGhpcy5jb21wdXRlZFJhZGl1c1swXSlcbiAgICB0aGlzLmNlbnRlci5zZXQodCwgY3gtbWF0WzJdKnIsIGN5LW1hdFs2XSpyLCBjei1tYXRbMTBdKnIpXG4gICAgdGhpcy5yYWRpdXMuaWRsZSh0KVxuICB9IGVsc2Uge1xuICAgIHRoaXMuY2VudGVyLmlkbGUodClcbiAgICB0aGlzLnJhZGl1cy5pZGxlKHQpXG4gIH1cbn1cblxucHJvdG8uc2V0RGlzdGFuY2UgPSBmdW5jdGlvbih0LCBkKSB7XG4gIGlmKGQgPiAwKSB7XG4gICAgdGhpcy5yYWRpdXMuc2V0KHQsIE1hdGgubG9nKGQpKVxuICB9XG59XG5cbnByb3RvLnNldERpc3RhbmNlTGltaXRzID0gZnVuY3Rpb24obG8sIGhpKSB7XG4gIGlmKGxvID4gMCkge1xuICAgIGxvID0gTWF0aC5sb2cobG8pXG4gIH0gZWxzZSB7XG4gICAgbG8gPSAtSW5maW5pdHkgICAgXG4gIH1cbiAgaWYoaGkgPiAwKSB7XG4gICAgaGkgPSBNYXRoLmxvZyhoaSlcbiAgfSBlbHNlIHtcbiAgICBoaSA9IEluZmluaXR5XG4gIH1cbiAgaGkgPSBNYXRoLm1heChoaSwgbG8pXG4gIHRoaXMucmFkaXVzLmJvdW5kc1swXVswXSA9IGxvXG4gIHRoaXMucmFkaXVzLmJvdW5kc1sxXVswXSA9IGhpXG59XG5cbnByb3RvLmdldERpc3RhbmNlTGltaXRzID0gZnVuY3Rpb24ob3V0KSB7XG4gIHZhciBib3VuZHMgPSB0aGlzLnJhZGl1cy5ib3VuZHNcbiAgaWYob3V0KSB7XG4gICAgb3V0WzBdID0gTWF0aC5leHAoYm91bmRzWzBdWzBdKVxuICAgIG91dFsxXSA9IE1hdGguZXhwKGJvdW5kc1sxXVswXSlcbiAgICByZXR1cm4gb3V0XG4gIH1cbiAgcmV0dXJuIFsgTWF0aC5leHAoYm91bmRzWzBdWzBdKSwgTWF0aC5leHAoYm91bmRzWzFdWzBdKSBdXG59XG5cbnByb3RvLnRvSlNPTiA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnJlY2FsY01hdHJpeCh0aGlzLmxhc3RUKCkpXG4gIHJldHVybiB7XG4gICAgY2VudGVyOiAgIHRoaXMuY29tcHV0ZWRDZW50ZXIuc2xpY2UoKSxcbiAgICByb3RhdGlvbjogdGhpcy5jb21wdXRlZFJvdGF0aW9uLnNsaWNlKCksXG4gICAgZGlzdGFuY2U6IE1hdGgubG9nKHRoaXMuY29tcHV0ZWRSYWRpdXNbMF0pLFxuICAgIHpvb21NaW46ICB0aGlzLnJhZGl1cy5ib3VuZHNbMF1bMF0sXG4gICAgem9vbU1heDogIHRoaXMucmFkaXVzLmJvdW5kc1sxXVswXVxuICB9XG59XG5cbnByb3RvLmZyb21KU09OID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICB2YXIgdCA9IHRoaXMubGFzdFQoKVxuICB2YXIgYyA9IG9wdGlvbnMuY2VudGVyXG4gIGlmKGMpIHtcbiAgICB0aGlzLmNlbnRlci5zZXQodCwgY1swXSwgY1sxXSwgY1syXSlcbiAgfVxuICB2YXIgciA9IG9wdGlvbnMucm90YXRpb25cbiAgaWYocikge1xuICAgIHRoaXMucm90YXRpb24uc2V0KHQsIHJbMF0sIHJbMV0sIHJbMl0sIHJbM10pXG4gIH1cbiAgdmFyIGQgPSBvcHRpb25zLmRpc3RhbmNlXG4gIGlmKGQgJiYgZCA+IDApIHtcbiAgICB0aGlzLnJhZGl1cy5zZXQodCwgTWF0aC5sb2coZCkpXG4gIH1cbiAgdGhpcy5zZXREaXN0YW5jZUxpbWl0cyhvcHRpb25zLnpvb21NaW4sIG9wdGlvbnMuem9vbU1heClcbn1cblxuZnVuY3Rpb24gY3JlYXRlT3JiaXRDb250cm9sbGVyKG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgdmFyIGNlbnRlciAgID0gb3B0aW9ucy5jZW50ZXIgICB8fCBbMCwwLDBdXG4gIHZhciByb3RhdGlvbiA9IG9wdGlvbnMucm90YXRpb24gfHwgWzAsMCwwLDFdXG4gIHZhciByYWRpdXMgICA9IG9wdGlvbnMucmFkaXVzICAgfHwgMS4wXG5cbiAgY2VudGVyID0gW10uc2xpY2UuY2FsbChjZW50ZXIsIDAsIDMpXG4gIHJvdGF0aW9uID0gW10uc2xpY2UuY2FsbChyb3RhdGlvbiwgMCwgNClcbiAgbm9ybWFsaXplNChyb3RhdGlvbiwgcm90YXRpb24pXG5cbiAgdmFyIHJlc3VsdCA9IG5ldyBPcmJpdENhbWVyYUNvbnRyb2xsZXIoXG4gICAgcm90YXRpb24sXG4gICAgY2VudGVyLFxuICAgIE1hdGgubG9nKHJhZGl1cykpXG5cbiAgcmVzdWx0LnNldERpc3RhbmNlTGltaXRzKG9wdGlvbnMuem9vbU1pbiwgb3B0aW9ucy56b29tTWF4KVxuXG4gIGlmKCdleWUnIGluIG9wdGlvbnMgfHwgJ3VwJyBpbiBvcHRpb25zKSB7XG4gICAgcmVzdWx0Lmxvb2tBdCgwLCBvcHRpb25zLmV5ZSwgb3B0aW9ucy5jZW50ZXIsIG9wdGlvbnMudXApXG4gIH1cblxuICByZXR1cm4gcmVzdWx0XG59XG59LHtcIi4vbGliL3F1YXRGcm9tRnJhbWVcIjo0NTUsXCJmaWx0ZXJlZC12ZWN0b3JcIjoyMjYsXCJnbC1tYXQ0L2Zyb21RdWF0XCI6MjYyLFwiZ2wtbWF0NC9pbnZlcnRcIjoyNjUsXCJnbC1tYXQ0L2xvb2tBdFwiOjI2Nn1dLDQ1NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKiFcbiAqIHBhZC1sZWZ0IDxodHRwczovL2dpdGh1Yi5jb20vam9uc2NobGlua2VydC9wYWQtbGVmdD5cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxNSwgSm9uIFNjaGxpbmtlcnQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVwZWF0ID0gX2RlcmVxXygncmVwZWF0LXN0cmluZycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhZExlZnQoc3RyLCBudW0sIGNoKSB7XG4gIGNoID0gdHlwZW9mIGNoICE9PSAndW5kZWZpbmVkJyA/IChjaCArICcnKSA6ICcgJztcbiAgcmV0dXJuIHJlcGVhdChjaCwgbnVtKSArIHN0cjtcbn07XG59LHtcInJlcGVhdC1zdHJpbmdcIjo1MDN9XSw0NTg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXHJcblxyXG4vKipcclxuICogQG1vZHVsZSBwYXJlbnRoZXNpc1xyXG4gKi9cclxuXHJcbmZ1bmN0aW9uIHBhcnNlIChzdHIsIG9wdHMpIHtcclxuXHQvLyBwcmV0ZW5kIG5vbi1zdHJpbmcgcGFyc2VkIHBlci1zZVxyXG5cdGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykgcmV0dXJuIFtzdHJdXHJcblxyXG5cdHZhciByZXMgPSBbc3RyXVxyXG5cclxuXHRpZiAodHlwZW9mIG9wdHMgPT09ICdzdHJpbmcnIHx8IEFycmF5LmlzQXJyYXkob3B0cykpIHtcclxuXHRcdG9wdHMgPSB7YnJhY2tldHM6IG9wdHN9XHJcblx0fVxyXG5cdGVsc2UgaWYgKCFvcHRzKSBvcHRzID0ge31cclxuXHJcblx0dmFyIGJyYWNrZXRzID0gb3B0cy5icmFja2V0cyA/IChBcnJheS5pc0FycmF5KG9wdHMuYnJhY2tldHMpID8gb3B0cy5icmFja2V0cyA6IFtvcHRzLmJyYWNrZXRzXSkgOiBbJ3t9JywgJ1tdJywgJygpJ11cclxuXHJcblx0dmFyIGVzY2FwZSA9IG9wdHMuZXNjYXBlIHx8ICdfX18nXHJcblxyXG5cdHZhciBmbGF0ID0gISFvcHRzLmZsYXRcclxuXHJcblx0YnJhY2tldHMuZm9yRWFjaChmdW5jdGlvbiAoYnJhY2tldCkge1xyXG5cdFx0Ly8gY3JlYXRlIHBhcmVudGhlc2lzIHJlZ2V4XHJcblx0XHR2YXIgcFJFID0gbmV3IFJlZ0V4cChbJ1xcXFwnLCBicmFja2V0WzBdLCAnW15cXFxcJywgYnJhY2tldFswXSwgJ1xcXFwnLCBicmFja2V0WzFdLCAnXSpcXFxcJywgYnJhY2tldFsxXV0uam9pbignJykpXHJcblxyXG5cdFx0dmFyIGlkcyA9IFtdXHJcblxyXG5cdFx0ZnVuY3Rpb24gcmVwbGFjZVRva2VuKHRva2VuLCBpZHgsIHN0cil7XHJcblx0XHRcdC8vIHNhdmUgdG9rZW4gdG8gcmVzXHJcblx0XHRcdHZhciByZWZJZCA9IHJlcy5wdXNoKHRva2VuLnNsaWNlKGJyYWNrZXRbMF0ubGVuZ3RoLCAtYnJhY2tldFsxXS5sZW5ndGgpKSAtIDFcclxuXHJcblx0XHRcdGlkcy5wdXNoKHJlZklkKVxyXG5cclxuXHRcdFx0cmV0dXJuIGVzY2FwZSArIHJlZklkICsgZXNjYXBlXHJcblx0XHR9XHJcblxyXG5cdFx0cmVzLmZvckVhY2goZnVuY3Rpb24gKHN0ciwgaSkge1xyXG5cdFx0XHR2YXIgcHJldlN0clxyXG5cclxuXHRcdFx0Ly8gcmVwbGFjZSBwYXJlbiB0b2tlbnMgdGlsbCB0aGVyZeKAmXMgbm9uZVxyXG5cdFx0XHR2YXIgYSA9IDBcclxuXHRcdFx0d2hpbGUgKHN0ciAhPSBwcmV2U3RyKSB7XHJcblx0XHRcdFx0cHJldlN0ciA9IHN0clxyXG5cdFx0XHRcdHN0ciA9IHN0ci5yZXBsYWNlKHBSRSwgcmVwbGFjZVRva2VuKVxyXG5cdFx0XHRcdGlmIChhKysgPiAxMGUzKSB0aHJvdyBFcnJvcignUmVmZXJlbmNlcyBoYXZlIGNpcmN1bGFyIGRlcGVuZGVuY3kuIFBsZWFzZSwgY2hlY2sgdGhlbS4nKVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRyZXNbaV0gPSBzdHJcclxuXHRcdH0pXHJcblxyXG5cdFx0Ly8gd3JhcCBmb3VuZCByZWZzIHRvIGJyYWNrZXRzXHJcblx0XHRpZHMgPSBpZHMucmV2ZXJzZSgpXHJcblx0XHRyZXMgPSByZXMubWFwKGZ1bmN0aW9uIChzdHIpIHtcclxuXHRcdFx0aWRzLmZvckVhY2goZnVuY3Rpb24gKGlkKSB7XHJcblx0XHRcdFx0c3RyID0gc3RyLnJlcGxhY2UobmV3IFJlZ0V4cCgnKFxcXFwnICsgZXNjYXBlICsgaWQgKyAnXFxcXCcgKyBlc2NhcGUgKyAnKScsICdnJyksIGJyYWNrZXRbMF0gKyAnJDEnICsgYnJhY2tldFsxXSlcclxuXHRcdFx0fSlcclxuXHRcdFx0cmV0dXJuIHN0clxyXG5cdFx0fSlcclxuXHR9KVxyXG5cclxuXHR2YXIgcmUgPSBuZXcgUmVnRXhwKCdcXFxcJyArIGVzY2FwZSArICcoWzAtOV0rKScgKyAnXFxcXCcgKyBlc2NhcGUpXHJcblxyXG5cdC8vIHRyYW5zZm9ybSByZWZlcmVuY2VzIHRvIHRyZWVcclxuXHRmdW5jdGlvbiBuZXN0IChzdHIsIHJlZnMsIGVzY2FwZSkge1xyXG5cdFx0dmFyIHJlcyA9IFtdLCBtYXRjaFxyXG5cclxuXHRcdHZhciBhID0gMFxyXG5cdFx0d2hpbGUgKG1hdGNoID0gcmUuZXhlYyhzdHIpKSB7XHJcblx0XHRcdGlmIChhKysgPiAxMGUzKSB0aHJvdyBFcnJvcignQ2lyY3VsYXIgcmVmZXJlbmNlcyBpbiBwYXJlbnRoZXNpcycpXHJcblxyXG5cdFx0XHRyZXMucHVzaChzdHIuc2xpY2UoMCwgbWF0Y2guaW5kZXgpKVxyXG5cclxuXHRcdFx0cmVzLnB1c2gobmVzdChyZWZzW21hdGNoWzFdXSwgcmVmcykpXHJcblxyXG5cdFx0XHRzdHIgPSBzdHIuc2xpY2UobWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGgpXHJcblx0XHR9XHJcblxyXG5cdFx0cmVzLnB1c2goc3RyKVxyXG5cclxuXHRcdHJldHVybiByZXNcclxuXHR9XHJcblxyXG5cdHJldHVybiBmbGF0ID8gcmVzIDogbmVzdChyZXNbMF0sIHJlcylcclxufVxyXG5cclxuZnVuY3Rpb24gc3RyaW5naWZ5IChhcmcsIG9wdHMpIHtcclxuXHRpZiAob3B0cyAmJiBvcHRzLmZsYXQpIHtcclxuXHRcdHZhciBlc2NhcGUgPSBvcHRzICYmIG9wdHMuZXNjYXBlIHx8ICdfX18nXHJcblxyXG5cdFx0dmFyIHN0ciA9IGFyZ1swXSwgcHJldlN0clxyXG5cclxuXHRcdC8vIHByZXRlbmQgYmFkIHN0cmluZyBzdHJpbmdpZmllZCB3aXRoIG5vIHBhcmVudGhlc2VzXHJcblx0XHRpZiAoIXN0cikgcmV0dXJuICcnXHJcblxyXG5cclxuXHRcdHZhciByZSA9IG5ldyBSZWdFeHAoJ1xcXFwnICsgZXNjYXBlICsgJyhbMC05XSspJyArICdcXFxcJyArIGVzY2FwZSlcclxuXHJcblx0XHR2YXIgYSA9IDBcclxuXHRcdHdoaWxlIChzdHIgIT0gcHJldlN0cikge1xyXG5cdFx0XHRpZiAoYSsrID4gMTBlMykgdGhyb3cgRXJyb3IoJ0NpcmN1bGFyIHJlZmVyZW5jZXMgaW4gJyArIGFyZylcclxuXHRcdFx0cHJldlN0ciA9IHN0clxyXG5cdFx0XHRzdHIgPSBzdHIucmVwbGFjZShyZSwgcmVwbGFjZVJlZilcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gc3RyXHJcblx0fVxyXG5cclxuXHRyZXR1cm4gYXJnLnJlZHVjZShmdW5jdGlvbiBmIChwcmV2LCBjdXJyKSB7XHJcblx0XHRpZiAoQXJyYXkuaXNBcnJheShjdXJyKSkge1xyXG5cdFx0XHRjdXJyID0gY3Vyci5yZWR1Y2UoZiwgJycpXHJcblx0XHR9XHJcblx0XHRyZXR1cm4gcHJldiArIGN1cnJcclxuXHR9LCAnJylcclxuXHJcblx0ZnVuY3Rpb24gcmVwbGFjZVJlZihtYXRjaCwgaWR4KXtcclxuXHRcdGlmIChhcmdbaWR4XSA9PSBudWxsKSB0aHJvdyBFcnJvcignUmVmZXJlbmNlICcgKyBpZHggKyAnaXMgdW5kZWZpbmVkJylcclxuXHRcdHJldHVybiBhcmdbaWR4XVxyXG5cdH1cclxufVxyXG5cclxuZnVuY3Rpb24gcGFyZW50aGVzaXMgKGFyZywgb3B0cykge1xyXG5cdGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcclxuXHRcdHJldHVybiBzdHJpbmdpZnkoYXJnLCBvcHRzKVxyXG5cdH1cclxuXHRlbHNlIHtcclxuXHRcdHJldHVybiBwYXJzZShhcmcsIG9wdHMpXHJcblx0fVxyXG59XHJcblxyXG5wYXJlbnRoZXNpcy5wYXJzZSA9IHBhcnNlXHJcbnBhcmVudGhlc2lzLnN0cmluZ2lmeSA9IHN0cmluZ2lmeVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBwYXJlbnRoZXNpc1xyXG5cbn0se31dLDQ1OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcclxuXHJcbnZhciBwaWNrID0gX2RlcmVxXygncGljay1ieS1hbGlhcycpXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHBhcnNlUmVjdFxyXG5cclxuZnVuY3Rpb24gcGFyc2VSZWN0IChhcmcpIHtcclxuICB2YXIgcmVjdFxyXG5cclxuICAvLyBkaXJlY3QgYXJndW1lbnRzIHNlcXVlbmNlXHJcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XHJcbiAgICBhcmcgPSBhcmd1bWVudHNcclxuICB9XHJcblxyXG4gIC8vIHN2ZyB2aWV3Ym94XHJcbiAgaWYgKHR5cGVvZiBhcmcgPT09ICdzdHJpbmcnKSB7XHJcbiAgICBhcmcgPSBhcmcuc3BsaXQoL1xccy8pLm1hcChwYXJzZUZsb2F0KVxyXG4gIH1cclxuICBlbHNlIGlmICh0eXBlb2YgYXJnID09PSAnbnVtYmVyJykge1xyXG4gICAgYXJnID0gW2FyZ11cclxuICB9XHJcblxyXG4gIC8vIDAsIDAsIDEwMCwgMTAwIC0gYXJyYXktbGlrZVxyXG4gIGlmIChhcmcubGVuZ3RoICYmIHR5cGVvZiBhcmdbMF0gPT09ICdudW1iZXInKSB7XHJcbiAgICAvLyBbdywgd11cclxuICAgIGlmIChhcmcubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgIHJlY3QgPSB7XHJcbiAgICAgICAgd2lkdGg6IGFyZ1swXSxcclxuICAgICAgICBoZWlnaHQ6IGFyZ1swXSxcclxuICAgICAgICB4OiAwLCB5OiAwXHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vIFt3LCBoXVxyXG4gICAgZWxzZSBpZiAoYXJnLmxlbmd0aCA9PT0gMikge1xyXG4gICAgICByZWN0ID0ge1xyXG4gICAgICAgIHdpZHRoOiBhcmdbMF0sXHJcbiAgICAgICAgaGVpZ2h0OiBhcmdbMV0sXHJcbiAgICAgICAgeDogMCwgeTogMFxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvLyBbbCwgdCwgciwgYl1cclxuICAgIGVsc2Uge1xyXG4gICAgICByZWN0ID0ge1xyXG4gICAgICAgIHg6IGFyZ1swXSxcclxuICAgICAgICB5OiBhcmdbMV0sXHJcbiAgICAgICAgd2lkdGg6IChhcmdbMl0gLSBhcmdbMF0pIHx8IDAsXHJcbiAgICAgICAgaGVpZ2h0OiAoYXJnWzNdIC0gYXJnWzFdKSB8fCAwXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgLy8ge3gsIHksIHcsIGh9IG9yIHtsLCB0LCBiLCByfVxyXG4gIGVsc2UgaWYgKGFyZykge1xyXG4gICAgYXJnID0gcGljayhhcmcsIHtcclxuICAgICAgbGVmdDogJ3ggbCBsZWZ0IExlZnQnLFxyXG4gICAgICB0b3A6ICd5IHQgdG9wIFRvcCcsXHJcbiAgICAgIHdpZHRoOiAndyB3aWR0aCBXIFdpZHRoJyxcclxuICAgICAgaGVpZ2h0OiAnaCBoZWlnaHQgVyBXaWR0aCcsXHJcbiAgICAgIGJvdHRvbTogJ2IgYm90dG9tIEJvdHRvbScsXHJcbiAgICAgIHJpZ2h0OiAnciByaWdodCBSaWdodCdcclxuICAgIH0pXHJcblxyXG4gICAgcmVjdCA9IHtcclxuICAgICAgeDogYXJnLmxlZnQgfHwgMCxcclxuICAgICAgeTogYXJnLnRvcCB8fCAwXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGFyZy53aWR0aCA9PSBudWxsKSB7XHJcbiAgICAgIGlmIChhcmcucmlnaHQpIHJlY3Qud2lkdGggPSBhcmcucmlnaHQgLSByZWN0LnhcclxuICAgICAgZWxzZSByZWN0LndpZHRoID0gMFxyXG4gICAgfVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIHJlY3Qud2lkdGggPSBhcmcud2lkdGhcclxuICAgIH1cclxuXHJcbiAgICBpZiAoYXJnLmhlaWdodCA9PSBudWxsKSB7XHJcbiAgICAgIGlmIChhcmcuYm90dG9tKSByZWN0LmhlaWdodCA9IGFyZy5ib3R0b20gLSByZWN0LnlcclxuICAgICAgZWxzZSByZWN0LmhlaWdodCA9IDBcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICByZWN0LmhlaWdodCA9IGFyZy5oZWlnaHRcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiByZWN0XHJcbn1cclxuXG59LHtcInBpY2stYnktYWxpYXNcIjo0NjV9XSw0NjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXG5tb2R1bGUuZXhwb3J0cyA9IHBhcnNlXG5cbi8qKlxuICogZXhwZWN0ZWQgYXJndW1lbnQgbGVuZ3Roc1xuICogQHR5cGUge09iamVjdH1cbiAqL1xuXG52YXIgbGVuZ3RoID0ge2E6IDcsIGM6IDYsIGg6IDEsIGw6IDIsIG06IDIsIHE6IDQsIHM6IDQsIHQ6IDIsIHY6IDEsIHo6IDB9XG5cbi8qKlxuICogc2VnbWVudCBwYXR0ZXJuXG4gKiBAdHlwZSB7UmVnRXhwfVxuICovXG5cbnZhciBzZWdtZW50ID0gLyhbYXN0dnpxbWhsY10pKFteYXN0dnpxbWhsY10qKS9pZ1xuXG4vKipcbiAqIHBhcnNlIGFuIHN2ZyBwYXRoIGRhdGEgc3RyaW5nLiBHZW5lcmF0ZXMgYW4gQXJyYXlcbiAqIG9mIGNvbW1hbmRzIHdoZXJlIGVhY2ggY29tbWFuZCBpcyBhbiBBcnJheSBvZiB0aGVcbiAqIGZvcm0gYFtjb21tYW5kLCBhcmcxLCBhcmcyLCAuLi5dYFxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYXRoXG4gKiBAcmV0dXJuIHtBcnJheX1cbiAqL1xuXG5mdW5jdGlvbiBwYXJzZShwYXRoKSB7XG5cdHZhciBkYXRhID0gW11cblx0cGF0aC5yZXBsYWNlKHNlZ21lbnQsIGZ1bmN0aW9uKF8sIGNvbW1hbmQsIGFyZ3Mpe1xuXHRcdHZhciB0eXBlID0gY29tbWFuZC50b0xvd2VyQ2FzZSgpXG5cdFx0YXJncyA9IHBhcnNlVmFsdWVzKGFyZ3MpXG5cblx0XHQvLyBvdmVybG9hZGVkIG1vdmVUb1xuXHRcdGlmICh0eXBlID09ICdtJyAmJiBhcmdzLmxlbmd0aCA+IDIpIHtcblx0XHRcdGRhdGEucHVzaChbY29tbWFuZF0uY29uY2F0KGFyZ3Muc3BsaWNlKDAsIDIpKSlcblx0XHRcdHR5cGUgPSAnbCdcblx0XHRcdGNvbW1hbmQgPSBjb21tYW5kID09ICdtJyA/ICdsJyA6ICdMJ1xuXHRcdH1cblxuXHRcdHdoaWxlICh0cnVlKSB7XG5cdFx0XHRpZiAoYXJncy5sZW5ndGggPT0gbGVuZ3RoW3R5cGVdKSB7XG5cdFx0XHRcdGFyZ3MudW5zaGlmdChjb21tYW5kKVxuXHRcdFx0XHRyZXR1cm4gZGF0YS5wdXNoKGFyZ3MpXG5cdFx0XHR9XG5cdFx0XHRpZiAoYXJncy5sZW5ndGggPCBsZW5ndGhbdHlwZV0pIHRocm93IG5ldyBFcnJvcignbWFsZm9ybWVkIHBhdGggZGF0YScpXG5cdFx0XHRkYXRhLnB1c2goW2NvbW1hbmRdLmNvbmNhdChhcmdzLnNwbGljZSgwLCBsZW5ndGhbdHlwZV0pKSlcblx0XHR9XG5cdH0pXG5cdHJldHVybiBkYXRhXG59XG5cbnZhciBudW1iZXIgPSAvLT9bMC05XSpcXC4/WzAtOV0rKD86ZVstK10/XFxkKyk/L2lnXG5cbmZ1bmN0aW9uIHBhcnNlVmFsdWVzKGFyZ3MpIHtcblx0dmFyIG51bWJlcnMgPSBhcmdzLm1hdGNoKG51bWJlcilcblx0cmV0dXJuIG51bWJlcnMgPyBudW1iZXJzLm1hcChOdW1iZXIpIDogW11cbn1cblxufSx7fV0sNDYxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFyc2VVbml0KHN0ciwgb3V0KSB7XG4gICAgaWYgKCFvdXQpXG4gICAgICAgIG91dCA9IFsgMCwgJycgXVxuXG4gICAgc3RyID0gU3RyaW5nKHN0cilcbiAgICB2YXIgbnVtID0gcGFyc2VGbG9hdChzdHIsIDEwKVxuICAgIG91dFswXSA9IG51bVxuICAgIG91dFsxXSA9IHN0ci5tYXRjaCgvW1xcZC5cXC1cXCtdKlxccyooLiopLylbMV0gfHwgJydcbiAgICByZXR1cm4gb3V0XG59XG59LHt9XSw0NjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuKGZ1bmN0aW9uIChwcm9jZXNzKXtcbi8vIEdlbmVyYXRlZCBieSBDb2ZmZWVTY3JpcHQgMS4xMi4yXG4oZnVuY3Rpb24oKSB7XG4gIHZhciBnZXROYW5vU2Vjb25kcywgaHJ0aW1lLCBsb2FkVGltZSwgbW9kdWxlTG9hZFRpbWUsIG5vZGVMb2FkVGltZSwgdXBUaW1lO1xuXG4gIGlmICgodHlwZW9mIHBlcmZvcm1hbmNlICE9PSBcInVuZGVmaW5lZFwiICYmIHBlcmZvcm1hbmNlICE9PSBudWxsKSAmJiBwZXJmb3JtYW5jZS5ub3cpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHBlcmZvcm1hbmNlLm5vdygpO1xuICAgIH07XG4gIH0gZWxzZSBpZiAoKHR5cGVvZiBwcm9jZXNzICE9PSBcInVuZGVmaW5lZFwiICYmIHByb2Nlc3MgIT09IG51bGwpICYmIHByb2Nlc3MuaHJ0aW1lKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAoZ2V0TmFub1NlY29uZHMoKSAtIG5vZGVMb2FkVGltZSkgLyAxZTY7XG4gICAgfTtcbiAgICBocnRpbWUgPSBwcm9jZXNzLmhydGltZTtcbiAgICBnZXROYW5vU2Vjb25kcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGhyO1xuICAgICAgaHIgPSBocnRpbWUoKTtcbiAgICAgIHJldHVybiBoclswXSAqIDFlOSArIGhyWzFdO1xuICAgIH07XG4gICAgbW9kdWxlTG9hZFRpbWUgPSBnZXROYW5vU2Vjb25kcygpO1xuICAgIHVwVGltZSA9IHByb2Nlc3MudXB0aW1lKCkgKiAxZTk7XG4gICAgbm9kZUxvYWRUaW1lID0gbW9kdWxlTG9hZFRpbWUgLSB1cFRpbWU7XG4gIH0gZWxzZSBpZiAoRGF0ZS5ub3cpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIERhdGUubm93KCkgLSBsb2FkVGltZTtcbiAgICB9O1xuICAgIGxvYWRUaW1lID0gRGF0ZS5ub3coKTtcbiAgfSBlbHNlIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIG5ldyBEYXRlKCkuZ2V0VGltZSgpIC0gbG9hZFRpbWU7XG4gICAgfTtcbiAgICBsb2FkVGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICB9XG5cbn0pLmNhbGwodGhpcyk7XG5cblxuXG59KS5jYWxsKHRoaXMsX2RlcmVxXygnX3Byb2Nlc3MnKSlcbn0se1wiX3Byb2Nlc3NcIjo0ODJ9XSw0NjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBwZXJtdXRhdGlvblNpZ25cblxudmFyIEJSVVRFX0ZPUkNFX0NVVE9GRiA9IDMyXG5cbnZhciBwb29sID0gX2RlcmVxXyhcInR5cGVkYXJyYXktcG9vbFwiKVxuXG5mdW5jdGlvbiBwZXJtdXRhdGlvblNpZ24ocCkge1xuICB2YXIgbiA9IHAubGVuZ3RoXG4gIGlmKG4gPCBCUlVURV9GT1JDRV9DVVRPRkYpIHtcbiAgICAvL1VzZSBxdWFkcmF0aWMgYWxnb3JpdGhtIGZvciBzbWFsbCBuXG4gICAgdmFyIHNnbiA9IDFcbiAgICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICAgIGZvcih2YXIgaj0wOyBqPGk7ICsraikge1xuICAgICAgICBpZihwW2ldIDwgcFtqXSkge1xuICAgICAgICAgIHNnbiA9IC1zZ25cbiAgICAgICAgfSBlbHNlIGlmKHBbaV0gPT09IHBbal0pIHtcbiAgICAgICAgICByZXR1cm4gMFxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzZ25cbiAgfSBlbHNlIHtcbiAgICAvL090aGVyd2lzZSB1c2UgbGluZWFyIHRpbWUgYWxnb3JpdGhtXG4gICAgdmFyIHZpc2l0ZWQgPSBwb29sLm1hbGxvY1VpbnQ4KG4pXG4gICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgICB2aXNpdGVkW2ldID0gMFxuICAgIH1cbiAgICB2YXIgc2duID0gMVxuICAgIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgICAgaWYoIXZpc2l0ZWRbaV0pIHtcbiAgICAgICAgdmFyIGNvdW50ID0gMVxuICAgICAgICB2aXNpdGVkW2ldID0gMVxuICAgICAgICBmb3IodmFyIGo9cFtpXTsgaiE9PWk7IGo9cFtqXSkge1xuICAgICAgICAgIGlmKHZpc2l0ZWRbal0pIHtcbiAgICAgICAgICAgIHBvb2wuZnJlZVVpbnQ4KHZpc2l0ZWQpXG4gICAgICAgICAgICByZXR1cm4gMFxuICAgICAgICAgIH1cbiAgICAgICAgICBjb3VudCArPSAxXG4gICAgICAgICAgdmlzaXRlZFtqXSA9IDFcbiAgICAgICAgfVxuICAgICAgICBpZighKGNvdW50ICYgMSkpIHtcbiAgICAgICAgICBzZ24gPSAtc2duXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcG9vbC5mcmVlVWludDgodmlzaXRlZClcbiAgICByZXR1cm4gc2duXG4gIH1cbn1cbn0se1widHlwZWRhcnJheS1wb29sXCI6NTQ1fV0sNDY0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciBwb29sID0gX2RlcmVxXyhcInR5cGVkYXJyYXktcG9vbFwiKVxudmFyIGludmVyc2UgPSBfZGVyZXFfKFwiaW52ZXJ0LXBlcm11dGF0aW9uXCIpXG5cbmZ1bmN0aW9uIHJhbmsocGVybXV0YXRpb24pIHtcbiAgdmFyIG4gPSBwZXJtdXRhdGlvbi5sZW5ndGhcbiAgc3dpdGNoKG4pIHtcbiAgICBjYXNlIDA6XG4gICAgY2FzZSAxOlxuICAgICAgcmV0dXJuIDBcbiAgICBjYXNlIDI6XG4gICAgICByZXR1cm4gcGVybXV0YXRpb25bMV1cbiAgICBkZWZhdWx0OlxuICAgICAgYnJlYWtcbiAgfVxuICB2YXIgcCA9IHBvb2wubWFsbG9jVWludDMyKG4pXG4gIHZhciBwaW52ID0gcG9vbC5tYWxsb2NVaW50MzIobilcbiAgdmFyIHIgPSAwLCBzLCB0LCBpXG4gIGludmVyc2UocGVybXV0YXRpb24sIHBpbnYpXG4gIGZvcihpPTA7IGk8bjsgKytpKSB7XG4gICAgcFtpXSA9IHBlcm11dGF0aW9uW2ldXG4gIH1cbiAgZm9yKGk9bi0xOyBpPjA7IC0taSkge1xuICAgIHQgPSBwaW52W2ldXG4gICAgcyA9IHBbaV1cbiAgICBwW2ldID0gcFt0XVxuICAgIHBbdF0gPSBzXG4gICAgcGludltpXSA9IHBpbnZbc11cbiAgICBwaW52W3NdID0gdFxuICAgIHIgPSAociArIHMpICogaVxuICB9XG4gIHBvb2wuZnJlZVVpbnQzMihwaW52KVxuICBwb29sLmZyZWVVaW50MzIocClcbiAgcmV0dXJuIHJcbn1cblxuZnVuY3Rpb24gdW5yYW5rKG4sIHIsIHApIHtcbiAgc3dpdGNoKG4pIHtcbiAgICBjYXNlIDA6XG4gICAgICBpZihwKSB7IHJldHVybiBwIH1cbiAgICAgIHJldHVybiBbXVxuICAgIGNhc2UgMTpcbiAgICAgIGlmKHApIHtcbiAgICAgICAgcFswXSA9IDBcbiAgICAgICAgcmV0dXJuIHBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbMF1cbiAgICAgIH1cbiAgICBjYXNlIDI6XG4gICAgICBpZihwKSB7XG4gICAgICAgIGlmKHIpIHtcbiAgICAgICAgICBwWzBdID0gMFxuICAgICAgICAgIHBbMV0gPSAxXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcFswXSA9IDFcbiAgICAgICAgICBwWzFdID0gMFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gciA/IFswLDFdIDogWzEsMF1cbiAgICAgIH1cbiAgICBkZWZhdWx0OlxuICAgICAgYnJlYWtcbiAgfVxuICBwID0gcCB8fCBuZXcgQXJyYXkobilcbiAgdmFyIHMsIHQsIGksIG5mPTFcbiAgcFswXSA9IDBcbiAgZm9yKGk9MTsgaTxuOyArK2kpIHtcbiAgICBwW2ldID0gaVxuICAgIG5mID0gKG5mKmkpfDBcbiAgfVxuICBmb3IoaT1uLTE7IGk+MDsgLS1pKSB7XG4gICAgcyA9IChyIC8gbmYpfDBcbiAgICByID0gKHIgLSBzICogbmYpfDBcbiAgICBuZiA9IChuZiAvIGkpfDBcbiAgICB0ID0gcFtpXXwwXG4gICAgcFtpXSA9IHBbc118MFxuICAgIHBbc10gPSB0fDBcbiAgfVxuICByZXR1cm4gcFxufVxuXG5leHBvcnRzLnJhbmsgPSByYW5rXG5leHBvcnRzLnVucmFuayA9IHVucmFua1xuXG59LHtcImludmVydC1wZXJtdXRhdGlvblwiOjQxNSxcInR5cGVkYXJyYXktcG9vbFwiOjU0NX1dLDQ2NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcclxuXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBpY2sgKHNyYywgcHJvcHMsIGtlZXBSZXN0KSB7XHJcblx0dmFyIHJlc3VsdCA9IHt9LCBwcm9wLCBpXHJcblxyXG5cdGlmICh0eXBlb2YgcHJvcHMgPT09ICdzdHJpbmcnKSBwcm9wcyA9IHRvTGlzdChwcm9wcylcclxuXHRpZiAoQXJyYXkuaXNBcnJheShwcm9wcykpIHtcclxuXHRcdHZhciByZXMgPSB7fVxyXG5cdFx0Zm9yIChpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdHJlc1twcm9wc1tpXV0gPSB0cnVlXHJcblx0XHR9XHJcblx0XHRwcm9wcyA9IHJlc1xyXG5cdH1cclxuXHJcblx0Ly8gY29udmVydCBzdHJpbmdzIHRvIGxpc3RzXHJcblx0Zm9yIChwcm9wIGluIHByb3BzKSB7XHJcblx0XHRwcm9wc1twcm9wXSA9IHRvTGlzdChwcm9wc1twcm9wXSlcclxuXHR9XHJcblxyXG5cdC8vIGtlZXAtcmVzdCBzdHJhdGVneSByZXF1aXJlcyB1bm1hdGNoZWQgcHJvcHMgdG8gYmUgcHJlc2VydmVkXHJcblx0dmFyIG9jY3VwaWVkID0ge31cclxuXHJcblx0Zm9yIChwcm9wIGluIHByb3BzKSB7XHJcblx0XHR2YXIgYWxpYXNlcyA9IHByb3BzW3Byb3BdXHJcblxyXG5cdFx0aWYgKEFycmF5LmlzQXJyYXkoYWxpYXNlcykpIHtcclxuXHRcdFx0Zm9yIChpID0gMDsgaSA8IGFsaWFzZXMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0XHR2YXIgYWxpYXMgPSBhbGlhc2VzW2ldXHJcblxyXG5cdFx0XHRcdGlmIChrZWVwUmVzdCkge1xyXG5cdFx0XHRcdFx0b2NjdXBpZWRbYWxpYXNdID0gdHJ1ZVxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0aWYgKGFsaWFzIGluIHNyYykge1xyXG5cdFx0XHRcdFx0cmVzdWx0W3Byb3BdID0gc3JjW2FsaWFzXVxyXG5cclxuXHRcdFx0XHRcdGlmIChrZWVwUmVzdCkge1xyXG5cdFx0XHRcdFx0XHRmb3IgKHZhciBqID0gaTsgaiA8IGFsaWFzZXMubGVuZ3RoOyBqKyspIHtcclxuXHRcdFx0XHRcdFx0XHRvY2N1cGllZFthbGlhc2VzW2pdXSA9IHRydWVcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdGJyZWFrXHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRlbHNlIGlmIChwcm9wIGluIHNyYykge1xyXG5cdFx0XHRpZiAocHJvcHNbcHJvcF0pIHtcclxuXHRcdFx0XHRyZXN1bHRbcHJvcF0gPSBzcmNbcHJvcF1cclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKGtlZXBSZXN0KSB7XHJcblx0XHRcdFx0b2NjdXBpZWRbcHJvcF0gPSB0cnVlXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGlmIChrZWVwUmVzdCkge1xyXG5cdFx0Zm9yIChwcm9wIGluIHNyYykge1xyXG5cdFx0XHRpZiAob2NjdXBpZWRbcHJvcF0pIGNvbnRpbnVlXHJcblx0XHRcdHJlc3VsdFtwcm9wXSA9IHNyY1twcm9wXVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIHJlc3VsdFxyXG59XHJcblxyXG52YXIgQ0FDSEUgPSB7fVxyXG5cclxuZnVuY3Rpb24gdG9MaXN0KGFyZykge1xyXG5cdGlmIChDQUNIRVthcmddKSByZXR1cm4gQ0FDSEVbYXJnXVxyXG5cdGlmICh0eXBlb2YgYXJnID09PSAnc3RyaW5nJykge1xyXG5cdFx0YXJnID0gQ0FDSEVbYXJnXSA9IGFyZy5zcGxpdCgvXFxzKixcXHMqfFxccysvKVxyXG5cdH1cclxuXHRyZXR1cm4gYXJnXHJcbn1cclxuXG59LHt9XSw0NjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBwbGFuYXJEdWFsXG5cbnZhciBjb21wYXJlQW5nbGUgPSBfZGVyZXFfKFwiY29tcGFyZS1hbmdsZVwiKVxuXG5mdW5jdGlvbiBwbGFuYXJEdWFsKGNlbGxzLCBwb3NpdGlvbnMpIHtcblxuICB2YXIgbnVtVmVydGljZXMgPSBwb3NpdGlvbnMubGVuZ3RofDBcbiAgdmFyIG51bUVkZ2VzID0gY2VsbHMubGVuZ3RoXG4gIHZhciBhZGogPSBbbmV3IEFycmF5KG51bVZlcnRpY2VzKSwgbmV3IEFycmF5KG51bVZlcnRpY2VzKV1cbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydGljZXM7ICsraSkge1xuICAgIGFkalswXVtpXSA9IFtdXG4gICAgYWRqWzFdW2ldID0gW11cbiAgfVxuICBmb3IodmFyIGk9MDsgaTxudW1FZGdlczsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGFkalswXVtjWzBdXS5wdXNoKGMpXG4gICAgYWRqWzFdW2NbMV1dLnB1c2goYylcbiAgfVxuXG4gIHZhciBjeWNsZXMgPSBbXVxuXG4gIC8vQWRkIGlzb2xhdGVkIHZlcnRpY2VzIGFzIHRyaXZpYWwgY2FzZVxuICBmb3IodmFyIGk9MDsgaTxudW1WZXJ0aWNlczsgKytpKSB7XG4gICAgaWYoYWRqWzBdW2ldLmxlbmd0aCArIGFkalsxXVtpXS5sZW5ndGggPT09IDApIHtcbiAgICAgIGN5Y2xlcy5wdXNoKCBbaV0gKVxuICAgIH1cbiAgfVxuXG4gIC8vUmVtb3ZlIGEgaGFsZiBlZGdlXG4gIGZ1bmN0aW9uIGN1dChjLCBpKSB7XG4gICAgdmFyIGEgPSBhZGpbaV1bY1tpXV1cbiAgICBhLnNwbGljZShhLmluZGV4T2YoYyksIDEpXG4gIH1cblxuICAvL0ZpbmQgbmV4dCB2ZXJ0ZXggYW5kIGN1dCBlZGdlXG4gIGZ1bmN0aW9uIG5leHQoYSwgYiwgbm9DdXQpIHtcbiAgICB2YXIgbmV4dENlbGwsIG5leHRWZXJ0ZXgsIG5leHREaXJcbiAgICBmb3IodmFyIGk9MDsgaTwyOyArK2kpIHtcbiAgICAgIGlmKGFkaltpXVtiXS5sZW5ndGggPiAwKSB7XG4gICAgICAgIG5leHRDZWxsID0gYWRqW2ldW2JdWzBdXG4gICAgICAgIG5leHREaXIgPSBpXG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgfVxuICAgIG5leHRWZXJ0ZXggPSBuZXh0Q2VsbFtuZXh0RGlyXjFdXG5cbiAgICBmb3IodmFyIGRpcj0wOyBkaXI8MjsgKytkaXIpIHtcbiAgICAgIHZhciBuYmhkID0gYWRqW2Rpcl1bYl1cbiAgICAgIGZvcih2YXIgaz0wOyBrPG5iaGQubGVuZ3RoOyArK2spIHtcbiAgICAgICAgdmFyIGUgPSBuYmhkW2tdXG4gICAgICAgIHZhciBwID0gZVtkaXJeMV1cbiAgICAgICAgdmFyIGNtcCA9IGNvbXBhcmVBbmdsZShcbiAgICAgICAgICAgIHBvc2l0aW9uc1thXSwgXG4gICAgICAgICAgICBwb3NpdGlvbnNbYl0sIFxuICAgICAgICAgICAgcG9zaXRpb25zW25leHRWZXJ0ZXhdLFxuICAgICAgICAgICAgcG9zaXRpb25zW3BdKVxuICAgICAgICBpZihjbXAgPiAwKSB7XG4gICAgICAgICAgbmV4dENlbGwgPSBlXG4gICAgICAgICAgbmV4dFZlcnRleCA9IHBcbiAgICAgICAgICBuZXh0RGlyID0gZGlyXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYobm9DdXQpIHtcbiAgICAgIHJldHVybiBuZXh0VmVydGV4XG4gICAgfVxuICAgIGlmKG5leHRDZWxsKSB7XG4gICAgICBjdXQobmV4dENlbGwsIG5leHREaXIpXG4gICAgfVxuICAgIHJldHVybiBuZXh0VmVydGV4XG4gIH1cblxuICBmdW5jdGlvbiBleHRyYWN0Q3ljbGUodiwgZGlyKSB7XG4gICAgdmFyIGUwID0gYWRqW2Rpcl1bdl1bMF1cbiAgICB2YXIgY3ljbGUgPSBbdl1cbiAgICBjdXQoZTAsIGRpcilcbiAgICB2YXIgdSA9IGUwW2Rpcl4xXVxuICAgIHZhciBkMCA9IGRpclxuICAgIHdoaWxlKHRydWUpIHtcbiAgICAgIHdoaWxlKHUgIT09IHYpIHtcbiAgICAgICAgY3ljbGUucHVzaCh1KVxuICAgICAgICB1ID0gbmV4dChjeWNsZVtjeWNsZS5sZW5ndGgtMl0sIHUsIGZhbHNlKVxuICAgICAgfVxuICAgICAgaWYoYWRqWzBdW3ZdLmxlbmd0aCArIGFkalsxXVt2XS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIHZhciBhID0gY3ljbGVbY3ljbGUubGVuZ3RoLTFdXG4gICAgICB2YXIgYiA9IHZcbiAgICAgIHZhciBjID0gY3ljbGVbMV1cbiAgICAgIHZhciBkID0gbmV4dChhLCBiLCB0cnVlKVxuICAgICAgaWYoY29tcGFyZUFuZ2xlKHBvc2l0aW9uc1thXSwgcG9zaXRpb25zW2JdLCBwb3NpdGlvbnNbY10sIHBvc2l0aW9uc1tkXSkgPCAwKSB7XG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgICBjeWNsZS5wdXNoKHYpXG4gICAgICB1ID0gbmV4dChhLCBiKVxuICAgIH1cbiAgICByZXR1cm4gY3ljbGVcbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3VsZEdsdWUocGN5Y2xlLCBuY3ljbGUpIHtcbiAgICByZXR1cm4gKG5jeWNsZVsxXSA9PT0gbmN5Y2xlW25jeWNsZS5sZW5ndGgtMV0pXG4gIH1cblxuICBmb3IodmFyIGk9MDsgaTxudW1WZXJ0aWNlczsgKytpKSB7XG4gICAgZm9yKHZhciBqPTA7IGo8MjsgKytqKSB7XG4gICAgICB2YXIgcGN5Y2xlID0gW11cbiAgICAgIHdoaWxlKGFkaltqXVtpXS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHZhciBuaSA9IGFkalswXVtpXS5sZW5ndGhcbiAgICAgICAgdmFyIG5jeWNsZSA9IGV4dHJhY3RDeWNsZShpLGopXG4gICAgICAgIGlmKHNob3VsZEdsdWUocGN5Y2xlLCBuY3ljbGUpKSB7XG4gICAgICAgICAgLy9HbHVlIHRvZ2V0aGVyIHRyaXZpYWwgY3ljbGVzXG4gICAgICAgICAgcGN5Y2xlLnB1c2guYXBwbHkocGN5Y2xlLCBuY3ljbGUpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYocGN5Y2xlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGN5Y2xlcy5wdXNoKHBjeWNsZSlcbiAgICAgICAgICB9XG4gICAgICAgICAgcGN5Y2xlID0gbmN5Y2xlXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmKHBjeWNsZS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGN5Y2xlcy5wdXNoKHBjeWNsZSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvL0NvbWJpbmUgcGF0aHMgYW5kIGxvb3BzIHRvZ2V0aGVyXG4gIHJldHVybiBjeWNsZXNcbn1cbn0se1wiY29tcGFyZS1hbmdsZVwiOjEyN31dLDQ2NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSB0cmltTGVhdmVzXG5cbnZhciBlMmEgPSBfZGVyZXFfKCdlZGdlcy10by1hZGphY2VuY3ktbGlzdCcpXG5cbmZ1bmN0aW9uIHRyaW1MZWF2ZXMoZWRnZXMsIHBvc2l0aW9ucykge1xuICB2YXIgYWRqID0gZTJhKGVkZ2VzLCBwb3NpdGlvbnMubGVuZ3RoKVxuICB2YXIgbGl2ZSA9IG5ldyBBcnJheShwb3NpdGlvbnMubGVuZ3RoKVxuICB2YXIgbmJoZCA9IG5ldyBBcnJheShwb3NpdGlvbnMubGVuZ3RoKVxuXG4gIHZhciBkZWFkID0gW11cbiAgZm9yKHZhciBpPTA7IGk8cG9zaXRpb25zLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGNvdW50ID0gYWRqW2ldLmxlbmd0aFxuICAgIG5iaGRbaV0gPSBjb3VudFxuICAgIGxpdmVbaV0gPSB0cnVlXG4gICAgaWYoY291bnQgPD0gMSkge1xuICAgICAgZGVhZC5wdXNoKGkpXG4gICAgfVxuICB9XG5cbiAgd2hpbGUoZGVhZC5sZW5ndGggPiAwKSB7XG4gICAgdmFyIHYgPSBkZWFkLnBvcCgpXG4gICAgbGl2ZVt2XSA9IGZhbHNlXG4gICAgdmFyIG4gPSBhZGpbdl1cbiAgICBmb3IodmFyIGk9MDsgaTxuLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgdSA9IG5baV1cbiAgICAgIGlmKC0tbmJoZFt1XSA9PT0gMCkge1xuICAgICAgICBkZWFkLnB1c2godSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB2YXIgbmV3SW5kZXggPSBuZXcgQXJyYXkocG9zaXRpb25zLmxlbmd0aClcbiAgdmFyIG5wb3NpdGlvbnMgPSBbXVxuICBmb3IodmFyIGk9MDsgaTxwb3NpdGlvbnMubGVuZ3RoOyArK2kpIHtcbiAgICBpZihsaXZlW2ldKSB7XG4gICAgICB2YXIgdiA9IG5wb3NpdGlvbnMubGVuZ3RoXG4gICAgICBuZXdJbmRleFtpXSA9IHZcbiAgICAgIG5wb3NpdGlvbnMucHVzaChwb3NpdGlvbnNbaV0pXG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld0luZGV4W2ldID0gLTFcbiAgICB9XG4gIH1cblxuICB2YXIgbmVkZ2VzID0gW11cbiAgZm9yKHZhciBpPTA7IGk8ZWRnZXMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgZSA9IGVkZ2VzW2ldXG4gICAgaWYobGl2ZVtlWzBdXSAmJiBsaXZlW2VbMV1dKSB7XG4gICAgICBuZWRnZXMucHVzaChbIG5ld0luZGV4W2VbMF1dLCBuZXdJbmRleFtlWzFdXSBdKVxuICAgIH1cbiAgfVxuICBcbiAgcmV0dXJuIFsgbmVkZ2VzLCBucG9zaXRpb25zIF1cbn1cbn0se1wiZWRnZXMtdG8tYWRqYWNlbmN5LWxpc3RcIjoxNzF9XSw0Njg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbm1vZHVsZS5leHBvcnRzID0gcGxhbmFyR3JhcGhUb1BvbHlsaW5lXG5cbnZhciBlMmEgPSBfZGVyZXFfKCdlZGdlcy10by1hZGphY2VuY3ktbGlzdCcpXG52YXIgcGxhbmFyRHVhbCA9IF9kZXJlcV8oJ3BsYW5hci1kdWFsJylcbnZhciBwcmVwcm9jZXNzUG9seWdvbiA9IF9kZXJlcV8oJ3BvaW50LWluLWJpZy1wb2x5Z29uJylcbnZhciB0d29Qcm9kdWN0ID0gX2RlcmVxXygndHdvLXByb2R1Y3QnKVxudmFyIHJvYnVzdFN1bSA9IF9kZXJlcV8oJ3JvYnVzdC1zdW0nKVxudmFyIHVuaXEgPSBfZGVyZXFfKCd1bmlxJylcbnZhciB0cmltTGVhdmVzID0gX2RlcmVxXygnLi9saWIvdHJpbS1sZWF2ZXMnKVxuXG5mdW5jdGlvbiBtYWtlQXJyYXkobGVuZ3RoLCBmaWxsKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobGVuZ3RoKVxuICBmb3IodmFyIGk9MDsgaTxsZW5ndGg7ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IGZpbGxcbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIG1ha2VBcnJheU9mQXJyYXlzKGxlbmd0aCkge1xuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KGxlbmd0aClcbiAgZm9yKHZhciBpPTA7IGk8bGVuZ3RoOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSBbXVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuXG5mdW5jdGlvbiBwbGFuYXJHcmFwaFRvUG9seWxpbmUoZWRnZXMsIHBvc2l0aW9ucykge1xuXG4gIC8vVHJpbSBsZWF2ZXNcbiAgdmFyIHJlc3VsdCA9IHRyaW1MZWF2ZXMoZWRnZXMsIHBvc2l0aW9ucylcbiAgZWRnZXMgPSByZXN1bHRbMF1cbiAgcG9zaXRpb25zID0gcmVzdWx0WzFdXG5cbiAgdmFyIG51bVZlcnRpY2VzID0gcG9zaXRpb25zLmxlbmd0aFxuICB2YXIgbnVtRWRnZXMgPSBlZGdlcy5sZW5ndGhcblxuICAvL0NhbGN1bGF0ZSBhZGphY2VuY3kgbGlzdCwgY2hlY2sgbWFuaWZvbGRcbiAgdmFyIGFkaiA9IGUyYShlZGdlcywgcG9zaXRpb25zLmxlbmd0aClcbiAgZm9yKHZhciBpPTA7IGk8bnVtVmVydGljZXM7ICsraSkge1xuICAgIGlmKGFkaltpXS5sZW5ndGggJSAyID09PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BsYW5hci1ncmFwaC10by1wb2x5bGluZTogZ3JhcGggbXVzdCBiZSBtYW5pZm9sZCcpXG4gICAgfVxuICB9XG5cbiAgLy9HZXQgZmFjZXNcbiAgdmFyIGZhY2VzID0gcGxhbmFyRHVhbChlZGdlcywgcG9zaXRpb25zKVxuXG4gIC8vQ2hlY2sgb3JpZW50YXRpb24gb2YgYSBwb2x5Z29uIHVzaW5nIGV4YWN0IGFyaXRobWV0aWNcbiAgZnVuY3Rpb24gY2N3KGMpIHtcbiAgICB2YXIgbiA9IGMubGVuZ3RoXG4gICAgdmFyIGFyZWEgPSBbMF1cbiAgICBmb3IodmFyIGo9MDsgajxuOyArK2opIHtcbiAgICAgIHZhciBhID0gcG9zaXRpb25zW2Nbal1dXG4gICAgICB2YXIgYiA9IHBvc2l0aW9uc1tjWyhqKzEpJW5dXVxuICAgICAgdmFyIHQwMCA9IHR3b1Byb2R1Y3QoLWFbMF0sIGFbMV0pXG4gICAgICB2YXIgdDAxID0gdHdvUHJvZHVjdCgtYVswXSwgYlsxXSlcbiAgICAgIHZhciB0MTAgPSB0d29Qcm9kdWN0KCBiWzBdLCBhWzFdKVxuICAgICAgdmFyIHQxMSA9IHR3b1Byb2R1Y3QoIGJbMF0sIGJbMV0pXG4gICAgICBhcmVhID0gcm9idXN0U3VtKGFyZWEsIHJvYnVzdFN1bShyb2J1c3RTdW0odDAwLCB0MDEpLCByb2J1c3RTdW0odDEwLCB0MTEpKSlcbiAgICB9XG4gICAgcmV0dXJuIGFyZWFbYXJlYS5sZW5ndGgtMV0gPiAwXG4gIH1cblxuICAvL0V4dHJhY3QgYWxsIGNsb2Nrd2lzZSBmYWNlc1xuICBmYWNlcyA9IGZhY2VzLmZpbHRlcihjY3cpXG5cbiAgLy9EZXRlY3Qgd2hpY2ggbG9vcHMgYXJlIGNvbnRhaW5lZCBpbiBvbmUgYW5vdGhlciB0byBoYW5kbGUgcGFyZW50LW9mIHJlbGF0aW9uXG4gIHZhciBudW1GYWNlcyA9IGZhY2VzLmxlbmd0aFxuICB2YXIgcGFyZW50ID0gbmV3IEFycmF5KG51bUZhY2VzKVxuICB2YXIgY29udGFpbm1lbnQgPSBuZXcgQXJyYXkobnVtRmFjZXMpXG4gIGZvcih2YXIgaT0wOyBpPG51bUZhY2VzOyArK2kpIHtcbiAgICBwYXJlbnRbaV0gPSBpXG4gICAgdmFyIHJvdyA9IG5ldyBBcnJheShudW1GYWNlcylcbiAgICB2YXIgbG9vcFZlcnRpY2VzID0gZmFjZXNbaV0ubWFwKGZ1bmN0aW9uKHYpIHtcbiAgICAgIHJldHVybiBwb3NpdGlvbnNbdl1cbiAgICB9KVxuICAgIHZhciBwbWMgPSBwcmVwcm9jZXNzUG9seWdvbihbbG9vcFZlcnRpY2VzXSlcbiAgICB2YXIgY291bnQgPSAwXG4gICAgb3V0ZXI6XG4gICAgZm9yKHZhciBqPTA7IGo8bnVtRmFjZXM7ICsraikge1xuICAgICAgcm93W2pdID0gMFxuICAgICAgaWYoaSA9PT0gaikge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgdmFyIGMgPSBmYWNlc1tqXVxuICAgICAgdmFyIG4gPSBjLmxlbmd0aFxuICAgICAgZm9yKHZhciBrPTA7IGs8bjsgKytrKSB7XG4gICAgICAgIHZhciBkID0gcG1jKHBvc2l0aW9uc1tjW2tdXSlcbiAgICAgICAgaWYoZCAhPT0gMCkge1xuICAgICAgICAgIGlmKGQgPCAwKSB7XG4gICAgICAgICAgICByb3dbal0gPSAxXG4gICAgICAgICAgICBjb3VudCArPSAxXG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnRpbnVlIG91dGVyXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJvd1tqXSA9IDFcbiAgICAgIGNvdW50ICs9IDFcbiAgICB9XG4gICAgY29udGFpbm1lbnRbaV0gPSBbY291bnQsIGksIHJvd11cbiAgfVxuICBjb250YWlubWVudC5zb3J0KGZ1bmN0aW9uKGEsYikge1xuICAgIHJldHVybiBiWzBdIC0gYVswXVxuICB9KVxuICBmb3IodmFyIGk9MDsgaTxudW1GYWNlczsgKytpKSB7XG4gICAgdmFyIHJvdyA9IGNvbnRhaW5tZW50W2ldXG4gICAgdmFyIGlkeCA9IHJvd1sxXVxuICAgIHZhciBjaGlsZHJlbiA9IHJvd1syXVxuICAgIGZvcih2YXIgaj0wOyBqPG51bUZhY2VzOyArK2opIHtcbiAgICAgIGlmKGNoaWxkcmVuW2pdKSB7XG4gICAgICAgIHBhcmVudFtqXSA9IGlkeFxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vSW5pdGlhbGl6ZSBmYWNlIGFkamFjZW5jeSBsaXN0XG4gIHZhciBmYWRqID0gbWFrZUFycmF5T2ZBcnJheXMobnVtRmFjZXMpXG4gIGZvcih2YXIgaT0wOyBpPG51bUZhY2VzOyArK2kpIHtcbiAgICBmYWRqW2ldLnB1c2gocGFyZW50W2ldKVxuICAgIGZhZGpbcGFyZW50W2ldXS5wdXNoKGkpXG4gIH1cblxuICAvL0J1aWxkIGFkamFjZW5jeSBtYXRyaXggZm9yIGVkZ2VzXG4gIHZhciBlZGdlQWRqYWNlbmN5ID0ge31cbiAgdmFyIGludGVybmFsVmVydGljZXMgPSBtYWtlQXJyYXkobnVtVmVydGljZXMsIGZhbHNlKVxuICBmb3IodmFyIGk9MDsgaTxudW1GYWNlczsgKytpKSB7XG4gICAgdmFyIGMgPSBmYWNlc1tpXVxuICAgIHZhciBuID0gYy5sZW5ndGhcbiAgICBmb3IodmFyIGo9MDsgajxuOyArK2opIHtcbiAgICAgIHZhciBhID0gY1tqXVxuICAgICAgdmFyIGIgPSBjWyhqKzEpJW5dXG4gICAgICB2YXIga2V5ID0gTWF0aC5taW4oYSxiKSArIFwiOlwiICsgTWF0aC5tYXgoYSxiKVxuICAgICAgaWYoa2V5IGluIGVkZ2VBZGphY2VuY3kpIHtcbiAgICAgICAgdmFyIG5laWdoYm9yID0gZWRnZUFkamFjZW5jeVtrZXldXG4gICAgICAgIGZhZGpbbmVpZ2hib3JdLnB1c2goaSlcbiAgICAgICAgZmFkaltpXS5wdXNoKG5laWdoYm9yKVxuICAgICAgICBpbnRlcm5hbFZlcnRpY2VzW2FdID0gaW50ZXJuYWxWZXJ0aWNlc1tiXSA9IHRydWVcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVkZ2VBZGphY2VuY3lba2V5XSA9IGlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBzaGFyZWRCb3VuZGFyeShjKSB7XG4gICAgdmFyIG4gPSBjLmxlbmd0aFxuICAgIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgICAgaWYoIWludGVybmFsVmVydGljZXNbY1tpXV0pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICB2YXIgdG9WaXNpdCA9IFtdXG4gIHZhciBwYXJpdHkgPSBtYWtlQXJyYXkobnVtRmFjZXMsIC0xKVxuICBmb3IodmFyIGk9MDsgaTxudW1GYWNlczsgKytpKSB7XG4gICAgaWYocGFyZW50W2ldID09PSBpICYmICFzaGFyZWRCb3VuZGFyeShmYWNlc1tpXSkpIHtcbiAgICAgIHRvVmlzaXQucHVzaChpKVxuICAgICAgcGFyaXR5W2ldID0gMFxuICAgIH0gZWxzZSB7XG4gICAgICBwYXJpdHlbaV0gPSAtMVxuICAgIH1cbiAgfVxuXG4gIC8vVXNpbmcgZmFjZSBhZGphY2VuY3ksIGNsYXNzaWZ5IGZhY2VzIGFzIGluL291dFxuICB2YXIgcmVzdWx0ID0gW11cbiAgd2hpbGUodG9WaXNpdC5sZW5ndGggPiAwKSB7XG4gICAgdmFyIHRvcCA9IHRvVmlzaXQucG9wKClcbiAgICB2YXIgbmJoZCA9IGZhZGpbdG9wXVxuICAgIHVuaXEobmJoZCwgZnVuY3Rpb24oYSxiKSB7XG4gICAgICByZXR1cm4gYS1iXG4gICAgfSlcbiAgICB2YXIgbm5iaHIgPSBuYmhkLmxlbmd0aFxuICAgIHZhciBwID0gcGFyaXR5W3RvcF1cbiAgICB2YXIgcG9seWxpbmVcbiAgICBpZihwID09PSAwKSB7XG4gICAgICB2YXIgYyA9IGZhY2VzW3RvcF1cbiAgICAgIHBvbHlsaW5lID0gW2NdXG4gICAgfVxuICAgIGZvcih2YXIgaT0wOyBpPG5uYmhyOyArK2kpIHtcbiAgICAgIHZhciBmID0gbmJoZFtpXVxuICAgICAgaWYocGFyaXR5W2ZdID49IDApIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIHBhcml0eVtmXSA9IHBeMVxuICAgICAgdG9WaXNpdC5wdXNoKGYpXG4gICAgICBpZihwID09PSAwKSB7XG4gICAgICAgIHZhciBjID0gZmFjZXNbZl1cbiAgICAgICAgaWYoIXNoYXJlZEJvdW5kYXJ5KGMpKSB7XG4gICAgICAgICAgYy5yZXZlcnNlKClcbiAgICAgICAgICBwb2x5bGluZS5wdXNoKGMpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYocCA9PT0gMCkge1xuICAgICAgcmVzdWx0LnB1c2gocG9seWxpbmUpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdFxufVxufSx7XCIuL2xpYi90cmltLWxlYXZlc1wiOjQ2NyxcImVkZ2VzLXRvLWFkamFjZW5jeS1saXN0XCI6MTcxLFwicGxhbmFyLWR1YWxcIjo0NjYsXCJwb2ludC1pbi1iaWctcG9seWdvblwiOjQ3MixcInJvYnVzdC1zdW1cIjo1MTUsXCJ0d28tcHJvZHVjdFwiOjU0MyxcInVuaXFcIjo1NDd9XSw0Njk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4vcXVhZCcpXHJcbn0se1wiLi9xdWFkXCI6NDcxfV0sNDcwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbmFyZ3VtZW50c1s0XVsxMTFdWzBdLmFwcGx5KGV4cG9ydHMsYXJndW1lbnRzKVxufSx7XCJkdXBcIjoxMTF9XSw0NzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXHJcbiAqIEBtb2R1bGUgIHBvaW50LWNsdXN0ZXIvcXVhZFxyXG4gKlxyXG4gKiBCdWNrZXQgYmFzZWQgcXVhZCB0cmVlIGNsdXN0ZXJpbmdcclxuICovXHJcblxyXG4ndXNlIHN0cmljdCdcclxuXHJcbnZhciBzZWFyY2ggPSBfZGVyZXFfKCdiaW5hcnktc2VhcmNoLWJvdW5kcycpXHJcbnZhciBjbGFtcCA9IF9kZXJlcV8oJ2NsYW1wJylcclxudmFyIHJlY3QgPSBfZGVyZXFfKCdwYXJzZS1yZWN0JylcclxudmFyIGdldEJvdW5kcyA9IF9kZXJlcV8oJ2FycmF5LWJvdW5kcycpXHJcbnZhciBwaWNrID0gX2RlcmVxXygncGljay1ieS1hbGlhcycpXHJcbnZhciBkZWZpbmVkID0gX2RlcmVxXygnZGVmaW5lZCcpXHJcbnZhciBmbGF0dGVuID0gX2RlcmVxXygnZmxhdHRlbi12ZXJ0ZXgtZGF0YScpXHJcbnZhciBpc09iaiA9IF9kZXJlcV8oJ2lzLW9iaicpXHJcbnZhciBkdHlwZSA9IF9kZXJlcV8oJ2R0eXBlJylcclxudmFyIGxvZzIgPSBfZGVyZXFfKCdtYXRoLWxvZzInKVxyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2x1c3RlciAoc3JjUG9pbnRzLCBvcHRpb25zKSB7XHJcblx0aWYgKCFvcHRpb25zKSB7IG9wdGlvbnMgPSB7fSB9XHJcblxyXG5cdHNyY1BvaW50cyA9IGZsYXR0ZW4oc3JjUG9pbnRzLCAnZmxvYXQ2NCcpXHJcblxyXG5cdG9wdGlvbnMgPSBwaWNrKG9wdGlvbnMsIHtcclxuXHRcdGJvdW5kczogJ3JhbmdlIGJvdW5kcyBkYXRhQm94IGRhdGFib3gnLFxyXG5cdFx0bWF4RGVwdGg6ICdkZXB0aCBtYXhEZXB0aCBtYXhkZXB0aCBsZXZlbCBtYXhMZXZlbCBtYXhsZXZlbCBsZXZlbHMnLFxyXG5cdFx0ZHR5cGU6ICd0eXBlIGR0eXBlIGZvcm1hdCBvdXQgZHN0IG91dHB1dCBkZXN0aW5hdGlvbidcclxuXHRcdC8vIHNvcnQ6ICdzb3J0Qnkgc29ydGJ5IHNvcnQnLFxyXG5cdFx0Ly8gcGljazogJ3BpY2sgbGV2ZWxQb2ludCcsXHJcblx0XHQvLyBub2RlU2l6ZTogJ25vZGUgbm9kZVNpemUgbWluTm9kZVNpemUgbWluU2l6ZSBzaXplJ1xyXG5cdH0pXHJcblxyXG5cdC8vIGxldCBub2RlU2l6ZSA9IGRlZmluZWQob3B0aW9ucy5ub2RlU2l6ZSwgMSlcclxuXHR2YXIgbWF4RGVwdGggPSBkZWZpbmVkKG9wdGlvbnMubWF4RGVwdGgsIDI1NSlcclxuXHR2YXIgYm91bmRzID0gZGVmaW5lZChvcHRpb25zLmJvdW5kcywgZ2V0Qm91bmRzKHNyY1BvaW50cywgMikpXHJcblx0aWYgKGJvdW5kc1swXSA9PT0gYm91bmRzWzJdKSB7IGJvdW5kc1syXSsrIH1cclxuXHRpZiAoYm91bmRzWzFdID09PSBib3VuZHNbM10pIHsgYm91bmRzWzNdKysgfVxyXG5cclxuXHR2YXIgcG9pbnRzID0gbm9ybWFsaXplKHNyY1BvaW50cywgYm91bmRzKVxyXG5cclxuXHQvLyBpbml0IHZhcmlhYmxlc1xyXG5cdHZhciBuID0gc3JjUG9pbnRzLmxlbmd0aCA+Pj4gMVxyXG5cdHZhciBpZHNcclxuXHRpZiAoIW9wdGlvbnMuZHR5cGUpIHsgb3B0aW9ucy5kdHlwZSA9ICdhcnJheScgfVxyXG5cclxuXHRpZiAodHlwZW9mIG9wdGlvbnMuZHR5cGUgPT09ICdzdHJpbmcnKSB7XHJcblx0XHRpZHMgPSBuZXcgKGR0eXBlKG9wdGlvbnMuZHR5cGUpKShuKVxyXG5cdH1cclxuXHRlbHNlIGlmIChvcHRpb25zLmR0eXBlKSB7XHJcblx0XHRpZHMgPSBvcHRpb25zLmR0eXBlXHJcblx0XHRpZiAoQXJyYXkuaXNBcnJheShpZHMpKSB7IGlkcy5sZW5ndGggPSBuIH1cclxuXHR9XHJcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcclxuXHRcdGlkc1tpXSA9IGlcclxuXHR9XHJcblxyXG5cdC8vIHBvaW50IGluZGV4ZXMgZm9yIGxldmVscyBbMDogW2EsYixjLGRdLCAxOiBbYSxiLGMsZCxlLGYsLi4uXSwgLi4uXVxyXG5cdHZhciBsZXZlbHMgPSBbXVxyXG5cclxuXHQvLyBzdGFydGluZyBpbmRleGVzIG9mIHN1YnJhbmdlcyBpbiBzdWIgbGV2ZWxzLCBsZXZlbHMubGVuZ3RoICogNFxyXG5cdHZhciBzdWJsZXZlbHMgPSBbXVxyXG5cclxuXHQvLyB1bmlxdWUgZ3JvdXAgaWRzLCBzb3J0ZWQgaW4gei1jdXJ2ZSBmYXNoaW9uIHdpdGhpbiBsZXZlbHNcclxuXHR2YXIgZ3JvdXBzID0gW11cclxuXHJcblx0Ly8gbGV2ZWwgb2Zmc2V0cyBpbiBgaWRzYFxyXG5cdHZhciBvZmZzZXRzID0gW11cclxuXHJcblxyXG5cdC8vIHNvcnQgcG9pbnRzXHJcblx0c29ydCgwLCAwLCAxLCBpZHMsIDAsIDEpXHJcblxyXG5cclxuXHQvLyByZXR1cm4gcmVvcmRlcmVkIGlkcyB3aXRoIHByb3ZpZGVkIG1ldGhvZHNcclxuXHQvLyBzYXZlIGxldmVsIG9mZnNldHMgaW4gb3V0cHV0IGJ1ZmZlclxyXG5cdHZhciBvZmZzZXQgPSAwXHJcblx0Zm9yICh2YXIgbGV2ZWwgPSAwOyBsZXZlbCA8IGxldmVscy5sZW5ndGg7IGxldmVsKyspIHtcclxuXHRcdHZhciBsZXZlbEl0ZW1zID0gbGV2ZWxzW2xldmVsXVxyXG5cdFx0aWYgKGlkcy5zZXQpIHsgaWRzLnNldChsZXZlbEl0ZW1zLCBvZmZzZXQpIH1cclxuXHRcdGVsc2Uge1xyXG5cdFx0XHRmb3IgKHZhciBpJDEgPSAwLCBsID0gbGV2ZWxJdGVtcy5sZW5ndGg7IGkkMSA8IGw7IGkkMSsrKSB7XHJcblx0XHRcdFx0aWRzW2kkMSArIG9mZnNldF0gPSBsZXZlbEl0ZW1zW2kkMV1cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0dmFyIG5leHRPZmZzZXQgPSBvZmZzZXQgKyBsZXZlbHNbbGV2ZWxdLmxlbmd0aFxyXG5cdFx0b2Zmc2V0c1tsZXZlbF0gPSBbb2Zmc2V0LCBuZXh0T2Zmc2V0XVxyXG5cdFx0b2Zmc2V0ID0gbmV4dE9mZnNldFxyXG5cdH1cclxuXHJcblx0aWRzLnJhbmdlID0gcmFuZ2VcclxuXHJcblx0cmV0dXJuIGlkc1xyXG5cclxuXHJcblxyXG5cdC8vIEZJWE1FOiBpdCBpcyBwb3NzaWJsZSB0byBjcmVhdGUgb25lIHR5cGVkIGFycmF5IGhlYXAgYW5kIHJldXNlIHRoYXQgdG8gYXZvaWQgbWVtb3J5IGJsb3dcclxuXHRmdW5jdGlvbiBzb3J0ICh4LCB5LCBkaWFtLCBpZHMsIGxldmVsLCBncm91cCkge1xyXG5cdFx0aWYgKCFpZHMubGVuZ3RoKSB7IHJldHVybiBudWxsIH1cclxuXHJcblx0XHQvLyBzYXZlIGZpcnN0IHBvaW50IGFzIGxldmVsIHJlcHJlc2VudGF0aXZlXHJcblx0XHR2YXIgbGV2ZWxJdGVtcyA9IGxldmVsc1tsZXZlbF0gfHwgKGxldmVsc1tsZXZlbF0gPSBbXSlcclxuXHRcdHZhciBsZXZlbEdyb3VwcyA9IGdyb3Vwc1tsZXZlbF0gfHwgKGdyb3Vwc1tsZXZlbF0gPSBbXSlcclxuXHRcdHZhciBzdWJsZXZlbCA9IHN1YmxldmVsc1tsZXZlbF0gfHwgKHN1YmxldmVsc1tsZXZlbF0gPSBbXSlcclxuXHRcdHZhciBvZmZzZXQgPSBsZXZlbEl0ZW1zLmxlbmd0aFxyXG5cclxuXHRcdGxldmVsKytcclxuXHJcblx0XHQvLyBtYXggZGVwdGggcmVhY2hlZCAtIHB1dCBhbGwgaXRlbXMgaW50byBhIGZpcnN0IGdyb3VwXHJcblx0XHRpZiAobGV2ZWwgPiBtYXhEZXB0aCkge1xyXG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRcdGxldmVsSXRlbXMucHVzaChpZHNbaV0pXHJcblx0XHRcdFx0bGV2ZWxHcm91cHMucHVzaChncm91cClcclxuXHRcdFx0XHRzdWJsZXZlbC5wdXNoKG51bGwsIG51bGwsIG51bGwsIG51bGwpXHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHJldHVybiBvZmZzZXRcclxuXHRcdH1cclxuXHJcblx0XHRsZXZlbEl0ZW1zLnB1c2goaWRzWzBdKVxyXG5cdFx0bGV2ZWxHcm91cHMucHVzaChncm91cClcclxuXHJcblx0XHRpZiAoaWRzLmxlbmd0aCA8PSAxKSB7XHJcblx0XHRcdHN1YmxldmVsLnB1c2gobnVsbCwgbnVsbCwgbnVsbCwgbnVsbClcclxuXHRcdFx0cmV0dXJuIG9mZnNldFxyXG5cdFx0fVxyXG5cclxuXHJcblx0XHR2YXIgZDIgPSBkaWFtICogLjVcclxuXHRcdHZhciBjeCA9IHggKyBkMiwgY3kgPSB5ICsgZDJcclxuXHJcblx0XHQvLyBkaXN0cmlidXRlIHBvaW50cyBieSA0IGJ1Y2tldHNcclxuXHRcdHZhciBsb2xvID0gW10sIGxvaGkgPSBbXSwgaGlsbyA9IFtdLCBoaWhpID0gW11cclxuXHJcblx0XHRmb3IgKHZhciBpJDEgPSAxLCBsID0gaWRzLmxlbmd0aDsgaSQxIDwgbDsgaSQxKyspIHtcclxuXHRcdFx0dmFyIGlkeCA9IGlkc1tpJDFdLFxyXG5cdFx0XHRcdHgkMSA9IHBvaW50c1tpZHggKiAyXSxcclxuXHRcdFx0XHR5JDEgPSBwb2ludHNbaWR4ICogMiArIDFdXHJcblx0XHRcdHgkMSA8IGN4ID8gKHkkMSA8IGN5ID8gbG9sby5wdXNoKGlkeCkgOiBsb2hpLnB1c2goaWR4KSkgOiAoeSQxIDwgY3kgPyBoaWxvLnB1c2goaWR4KSA6IGhpaGkucHVzaChpZHgpKVxyXG5cdFx0fVxyXG5cclxuXHRcdGdyb3VwIDw8PSAyXHJcblx0XHRzdWJsZXZlbC5wdXNoKFxyXG5cdFx0XHRzb3J0KHgsIHksIGQyLCBsb2xvLCBsZXZlbCwgZ3JvdXApLFxyXG5cdFx0XHRzb3J0KHgsIGN5LCBkMiwgbG9oaSwgbGV2ZWwsIGdyb3VwICsgMSksXHJcblx0XHRcdHNvcnQoY3gsIHksIGQyLCBoaWxvLCBsZXZlbCwgZ3JvdXAgKyAyKSxcclxuXHRcdFx0c29ydChjeCwgY3ksIGQyLCBoaWhpLCBsZXZlbCwgZ3JvdXAgKyAzKVxyXG5cdFx0KVxyXG5cclxuXHRcdHJldHVybiBvZmZzZXRcclxuXHR9XHJcblxyXG5cdC8vIGdldCBhbGwgcG9pbnRzIHdpdGhpbiB0aGUgcGFzc2VkIHJhbmdlXHJcblx0ZnVuY3Rpb24gcmFuZ2UgKCkge1xuXHRcdHZhciBhcmdzID0gW10sIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG5cdFx0d2hpbGUgKCBsZW4tLSApIGFyZ3NbIGxlbiBdID0gYXJndW1lbnRzWyBsZW4gXTtcblxyXG5cdFx0dmFyIG9wdGlvbnNcclxuXHJcblx0XHRpZiAoaXNPYmooYXJnc1thcmdzLmxlbmd0aCAtIDFdKSkge1xyXG5cdFx0XHR2YXIgYXJnID0gYXJncy5wb3AoKVxyXG5cclxuXHRcdFx0Ly8gZGV0ZWN0IGlmIHRoYXQgd2FzIGEgcmVjdCBvYmplY3RcclxuXHRcdFx0aWYgKCFhcmdzLmxlbmd0aCAmJiAoYXJnLnggIT0gbnVsbCB8fCBhcmcubCAhPSBudWxsIHx8IGFyZy5sZWZ0ICE9IG51bGwpKSB7XHJcblx0XHRcdFx0YXJncyA9IFthcmddXHJcblx0XHRcdFx0b3B0aW9ucyA9IHt9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdG9wdGlvbnMgPSBwaWNrKGFyZywge1xyXG5cdFx0XHRcdGxldmVsOiAnbGV2ZWwgbWF4TGV2ZWwnLFxyXG5cdFx0XHRcdGQ6ICdkIGRpYW0gZGlhbWV0ZXIgciByYWRpdXMgcHggcHhTaXplIHBpeGVsIHBpeGVsU2l6ZSBtYXhEIHNpemUgbWluU2l6ZScsXHJcblx0XHRcdFx0bG9kOiAnbG9kIGRldGFpbHMgcmFuZ2VzIG9mZnNldHMnXHJcblx0XHRcdH0pXHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0b3B0aW9ucyA9IHt9XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCFhcmdzLmxlbmd0aCkgeyBhcmdzID0gYm91bmRzIH1cclxuXHJcblx0XHR2YXIgYm94ID0gcmVjdC5hcHBseSggdm9pZCAwLCBhcmdzIClcclxuXHJcblx0XHR2YXIgcmVmID0gW1xyXG5cdFx0XHRNYXRoLm1pbihib3gueCwgYm94LnggKyBib3gud2lkdGgpLFxyXG5cdFx0XHRNYXRoLm1pbihib3gueSwgYm94LnkgKyBib3guaGVpZ2h0KSxcclxuXHRcdFx0TWF0aC5tYXgoYm94LngsIGJveC54ICsgYm94LndpZHRoKSxcclxuXHRcdFx0TWF0aC5tYXgoYm94LnksIGJveC55ICsgYm94LmhlaWdodClcclxuXHRcdF07XG5cdFx0dmFyIG1pblggPSByZWZbMF07XG5cdFx0dmFyIG1pblkgPSByZWZbMV07XG5cdFx0dmFyIG1heFggPSByZWZbMl07XG5cdFx0dmFyIG1heFkgPSByZWZbM107XHJcblxyXG5cdFx0dmFyIHJlZiQxID0gbm9ybWFsaXplKFttaW5YLCBtaW5ZLCBtYXhYLCBtYXhZXSwgYm91bmRzICk7XG5cdFx0dmFyIG5taW5YID0gcmVmJDFbMF07XG5cdFx0dmFyIG5taW5ZID0gcmVmJDFbMV07XG5cdFx0dmFyIG5tYXhYID0gcmVmJDFbMl07XG5cdFx0dmFyIG5tYXhZID0gcmVmJDFbM107XHJcblxyXG5cdFx0dmFyIG1heExldmVsID0gZGVmaW5lZChvcHRpb25zLmxldmVsLCBsZXZlbHMubGVuZ3RoKVxyXG5cclxuXHRcdC8vIGxpbWl0IG1heExldmVsIGJ5IHB4IHNpemVcclxuXHRcdGlmIChvcHRpb25zLmQgIT0gbnVsbCkge1xyXG5cdFx0XHR2YXIgZFxyXG5cdFx0XHRpZiAodHlwZW9mIG9wdGlvbnMuZCA9PT0gJ251bWJlcicpIHsgZCA9IFtvcHRpb25zLmQsIG9wdGlvbnMuZF0gfVxyXG5cdFx0XHRlbHNlIGlmIChvcHRpb25zLmQubGVuZ3RoKSB7IGQgPSBvcHRpb25zLmQgfVxyXG5cclxuXHRcdFx0bWF4TGV2ZWwgPSBNYXRoLm1pbihcclxuXHRcdFx0XHRNYXRoLm1heChcclxuXHRcdFx0XHRcdE1hdGguY2VpbCgtbG9nMihNYXRoLmFicyhkWzBdKSAvIChib3VuZHNbMl0gLSBib3VuZHNbMF0pKSksXHJcblx0XHRcdFx0XHRNYXRoLmNlaWwoLWxvZzIoTWF0aC5hYnMoZFsxXSkgLyAoYm91bmRzWzNdIC0gYm91bmRzWzFdKSkpXHJcblx0XHRcdFx0KSxcclxuXHRcdFx0XHRtYXhMZXZlbFxyXG5cdFx0XHQpXHJcblx0XHR9XHJcblx0XHRtYXhMZXZlbCA9IE1hdGgubWluKG1heExldmVsLCBsZXZlbHMubGVuZ3RoKVxyXG5cclxuXHRcdC8vIHJldHVybiBsZXZlbHMgb2YgZGV0YWlsc1xyXG5cdFx0aWYgKG9wdGlvbnMubG9kKSB7XHJcblx0XHRcdHJldHVybiBsb2Qobm1pblgsIG5taW5ZLCBubWF4WCwgbm1heFksIG1heExldmVsKVxyXG5cdFx0fVxyXG5cclxuXHJcblxyXG5cdFx0Ly8gZG8gc2VsZWN0aW9uIGlkc1xyXG5cdFx0dmFyIHNlbGVjdGlvbiA9IFtdXHJcblxyXG5cdFx0Ly8gRklYTUU6IHByb2JhYmx5IHdlIGNhbiBkbyBMT0QgaGVyZSBiZWZvcmVoZWFkXHJcblx0XHRzZWxlY3QoIDAsIDAsIDEsIDAsIDAsIDEpXHJcblxyXG5cdFx0ZnVuY3Rpb24gc2VsZWN0ICggbG94LCBsb3ksIGQsIGxldmVsLCBmcm9tLCB0byApIHtcclxuXHRcdFx0aWYgKGZyb20gPT09IG51bGwgfHwgdG8gPT09IG51bGwpIHsgcmV0dXJuIH1cclxuXHJcblx0XHRcdHZhciBoaXggPSBsb3ggKyBkXHJcblx0XHRcdHZhciBoaXkgPSBsb3kgKyBkXHJcblxyXG5cdFx0XHQvLyBpZiBib3ggZG9lcyBub3QgaW50ZXJzZWN0IGxldmVsIC0gaWdub3JlXHJcblx0XHRcdGlmICggbm1pblggPiBoaXggfHwgbm1pblkgPiBoaXkgfHwgbm1heFggPCBsb3ggfHwgbm1heFkgPCBsb3kgKSB7IHJldHVybiB9XHJcblx0XHRcdGlmICggbGV2ZWwgPj0gbWF4TGV2ZWwgKSB7IHJldHVybiB9XHJcblx0XHRcdGlmICggZnJvbSA9PT0gdG8gKSB7IHJldHVybiB9XHJcblxyXG5cdFx0XHQvLyBpZiBwb2ludHMgZmFsbCBpbnRvIGJveCByYW5nZSAtIHRha2UgaXRcclxuXHRcdFx0dmFyIGxldmVsSXRlbXMgPSBsZXZlbHNbbGV2ZWxdXHJcblxyXG5cdFx0XHRpZiAodG8gPT09IHVuZGVmaW5lZCkgeyB0byA9IGxldmVsSXRlbXMubGVuZ3RoIH1cclxuXHJcblx0XHRcdGZvciAodmFyIGkgPSBmcm9tOyBpIDwgdG87IGkrKykge1xyXG5cdFx0XHRcdHZhciBpZCA9IGxldmVsSXRlbXNbaV1cclxuXHJcblx0XHRcdFx0dmFyIHB4ID0gc3JjUG9pbnRzWyBpZCAqIDIgXVxyXG5cdFx0XHRcdHZhciBweSA9IHNyY1BvaW50c1sgaWQgKiAyICsgMSBdXHJcblxyXG5cdFx0XHRcdGlmICggcHggPj0gbWluWCAmJiBweCA8PSBtYXhYICYmIHB5ID49IG1pblkgJiYgcHkgPD0gbWF4WSApIHtzZWxlY3Rpb24ucHVzaChpZClcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIGZvciBldmVyeSBzdWJzZWN0aW9uIGRvIHNlbGVjdFxyXG5cdFx0XHR2YXIgb2Zmc2V0cyA9IHN1YmxldmVsc1sgbGV2ZWwgXVxyXG5cdFx0XHR2YXIgb2ZmMCA9IG9mZnNldHNbIGZyb20gKiA0ICsgMCBdXHJcblx0XHRcdHZhciBvZmYxID0gb2Zmc2V0c1sgZnJvbSAqIDQgKyAxIF1cclxuXHRcdFx0dmFyIG9mZjIgPSBvZmZzZXRzWyBmcm9tICogNCArIDIgXVxyXG5cdFx0XHR2YXIgb2ZmMyA9IG9mZnNldHNbIGZyb20gKiA0ICsgMyBdXHJcblx0XHRcdHZhciBlbmQgPSBuZXh0T2Zmc2V0KG9mZnNldHMsIGZyb20gKyAxKVxyXG5cclxuXHRcdFx0dmFyIGQyID0gZCAqIC41XHJcblx0XHRcdHZhciBuZXh0TGV2ZWwgPSBsZXZlbCArIDFcclxuXHRcdFx0c2VsZWN0KCBsb3gsIGxveSwgZDIsIG5leHRMZXZlbCwgb2ZmMCwgb2ZmMSB8fCBvZmYyIHx8IG9mZjMgfHwgZW5kKVxyXG5cdFx0XHRzZWxlY3QoIGxveCwgbG95ICsgZDIsIGQyLCBuZXh0TGV2ZWwsIG9mZjEsIG9mZjIgfHwgb2ZmMyB8fCBlbmQpXHJcblx0XHRcdHNlbGVjdCggbG94ICsgZDIsIGxveSwgZDIsIG5leHRMZXZlbCwgb2ZmMiwgb2ZmMyB8fCBlbmQpXHJcblx0XHRcdHNlbGVjdCggbG94ICsgZDIsIGxveSArIGQyLCBkMiwgbmV4dExldmVsLCBvZmYzLCBlbmQpXHJcblx0XHR9XHJcblxyXG5cdFx0ZnVuY3Rpb24gbmV4dE9mZnNldChvZmZzZXRzLCBmcm9tKSB7XHJcblx0XHRcdHZhciBvZmZzZXQgPSBudWxsLCBpID0gMFxyXG5cdFx0XHR3aGlsZShvZmZzZXQgPT09IG51bGwpIHtcclxuXHRcdFx0XHRvZmZzZXQgPSBvZmZzZXRzWyBmcm9tICogNCArIGkgXVxyXG5cdFx0XHRcdGkrK1xyXG5cdFx0XHRcdGlmIChpID4gb2Zmc2V0cy5sZW5ndGgpIHsgcmV0dXJuIG51bGwgfVxyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBvZmZzZXRcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gc2VsZWN0aW9uXHJcblx0fVxyXG5cclxuXHQvLyBnZXQgcmFuZ2Ugb2Zmc2V0cyB3aXRoaW4gbGV2ZWxzIHRvIHJlbmRlciBsb2RzIGFwcHJvcHJpYXRlIGZvciB6b29tIGxldmVsXHJcblx0Ly8gVE9ETzogaXQgaXMgcG9zc2libGUgdG8gc3RvcmUgbWluU2l6ZSBvZiBhIHBvaW50IHRvIG9wdGltaXplIG5lZWRlIGxldmVsIGNhbGNcclxuXHRmdW5jdGlvbiBsb2QgKGxveCwgbG95LCBoaXgsIGhpeSwgbWF4TGV2ZWwpIHtcclxuXHRcdHZhciByYW5nZXMgPSBbXVxyXG5cclxuXHRcdGZvciAodmFyIGxldmVsID0gMDsgbGV2ZWwgPCBtYXhMZXZlbDsgbGV2ZWwrKykge1xyXG5cdFx0XHR2YXIgbGV2ZWxHcm91cHMgPSBncm91cHNbbGV2ZWxdXHJcblx0XHRcdHZhciBmcm9tID0gb2Zmc2V0c1tsZXZlbF1bMF1cclxuXHJcblx0XHRcdHZhciBsZXZlbEdyb3VwU3RhcnQgPSBncm91cChsb3gsIGxveSwgbGV2ZWwpXHJcblx0XHRcdHZhciBsZXZlbEdyb3VwRW5kID0gZ3JvdXAoaGl4LCBoaXksIGxldmVsKVxyXG5cclxuXHRcdFx0Ly8gRklYTUU6IHV0aWxpemUgc3VibGV2ZWxzIHRvIHNwZWVkIHVwIHNlYXJjaCByYW5nZSBoZXJlXHJcblx0XHRcdHZhciBzdGFydE9mZnNldCA9IHNlYXJjaC5nZShsZXZlbEdyb3VwcywgbGV2ZWxHcm91cFN0YXJ0KVxyXG5cdFx0XHR2YXIgZW5kT2Zmc2V0ID0gc2VhcmNoLmd0KGxldmVsR3JvdXBzLCBsZXZlbEdyb3VwRW5kLCBzdGFydE9mZnNldCwgbGV2ZWxHcm91cHMubGVuZ3RoIC0gMSlcclxuXHJcblx0XHRcdHJhbmdlc1tsZXZlbF0gPSBbc3RhcnRPZmZzZXQgKyBmcm9tLCBlbmRPZmZzZXQgKyBmcm9tXVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiByYW5nZXNcclxuXHR9XHJcblxyXG5cdC8vIGdldCBncm91cCBpZCBjbG9zZXN0IHRvIHRoZSB4LHkgY29vcmRpbmF0ZSwgY29ycmVzcG9uZGluZyB0byBhIGxldmVsXHJcblx0ZnVuY3Rpb24gZ3JvdXAgKHgsIHksIGxldmVsKSB7XHJcblx0XHR2YXIgZ3JvdXAgPSAxXHJcblxyXG5cdFx0dmFyIGN4ID0gLjUsIGN5ID0gLjVcclxuXHRcdHZhciBkaWFtID0gLjVcclxuXHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGxldmVsOyBpKyspIHtcclxuXHRcdFx0Z3JvdXAgPDw9IDJcclxuXHJcblx0XHRcdGdyb3VwICs9IHggPCBjeCA/ICh5IDwgY3kgPyAwIDogMSkgOiAoeSA8IGN5ID8gMiA6IDMpXHJcblxyXG5cdFx0XHRkaWFtICo9IC41XHJcblxyXG5cdFx0XHRjeCArPSB4IDwgY3ggPyAtZGlhbSA6IGRpYW1cclxuXHRcdFx0Y3kgKz0geSA8IGN5ID8gLWRpYW0gOiBkaWFtXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIGdyb3VwXHJcblx0fVxyXG59XHJcblxyXG5cclxuLy8gbm9ybWFsaXplIHBvaW50cyBieSBib3VuZHNcclxuZnVuY3Rpb24gbm9ybWFsaXplIChwdHMsIGJvdW5kcykge1xyXG5cdHZhciBsb3ggPSBib3VuZHNbMF07XG5cdHZhciBsb3kgPSBib3VuZHNbMV07XG5cdHZhciBoaXggPSBib3VuZHNbMl07XG5cdHZhciBoaXkgPSBib3VuZHNbM107XHJcblx0dmFyIHNjYWxlWCA9IDEuMCAvIChoaXggLSBsb3gpXHJcblx0dmFyIHNjYWxlWSA9IDEuMCAvIChoaXkgLSBsb3kpXHJcblx0dmFyIHJlc3VsdCA9IG5ldyBBcnJheShwdHMubGVuZ3RoKVxyXG5cclxuXHRmb3IgKHZhciBpID0gMCwgbiA9IHB0cy5sZW5ndGggLyAyOyBpIDwgbjsgaSsrKSB7XHJcblx0XHRyZXN1bHRbMippXSA9IGNsYW1wKChwdHNbMippXSAtIGxveCkgKiBzY2FsZVgsIDAsIDEpXHJcblx0XHRyZXN1bHRbMippKzFdID0gY2xhbXAoKHB0c1syKmkrMV0gLSBsb3kpICogc2NhbGVZLCAwLCAxKVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIHJlc3VsdFxyXG59XHJcbn0se1wiYXJyYXktYm91bmRzXCI6NjUsXCJiaW5hcnktc2VhcmNoLWJvdW5kc1wiOjQ3MCxcImNsYW1wXCI6MTE1LFwiZGVmaW5lZFwiOjE2NCxcImR0eXBlXCI6MTY5LFwiZmxhdHRlbi12ZXJ0ZXgtZGF0YVwiOjIyNyxcImlzLW9ialwiOjQyMSxcIm1hdGgtbG9nMlwiOjQzMixcInBhcnNlLXJlY3RcIjo0NTksXCJwaWNrLWJ5LWFsaWFzXCI6NDY1fV0sNDcyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gcHJlcHJvY2Vzc1BvbHlnb25cblxudmFyIG9yaWVudCA9IF9kZXJlcV8oJ3JvYnVzdC1vcmllbnRhdGlvbicpWzNdXG52YXIgbWFrZVNsYWJzID0gX2RlcmVxXygnc2xhYi1kZWNvbXBvc2l0aW9uJylcbnZhciBtYWtlSW50ZXJ2YWxUcmVlID0gX2RlcmVxXygnaW50ZXJ2YWwtdHJlZS0xZCcpXG52YXIgYnNlYXJjaCA9IF9kZXJlcV8oJ2JpbmFyeS1zZWFyY2gtYm91bmRzJylcblxuZnVuY3Rpb24gdmlzaXRJbnRlcnZhbCgpIHtcbiAgcmV0dXJuIHRydWVcbn1cblxuZnVuY3Rpb24gaW50ZXJ2YWxTZWFyY2godGFibGUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB2YXIgdHJlZSA9IHRhYmxlW3hdXG4gICAgaWYodHJlZSkge1xuICAgICAgcmV0dXJuICEhdHJlZS5xdWVyeVBvaW50KHksIHZpc2l0SW50ZXJ2YWwpXG4gICAgfVxuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbmZ1bmN0aW9uIGJ1aWxkVmVydGljYWxJbmRleChzZWdtZW50cykge1xuICB2YXIgdGFibGUgPSB7fVxuICBmb3IodmFyIGk9MDsgaTxzZWdtZW50cy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBzID0gc2VnbWVudHNbaV1cbiAgICB2YXIgeCA9IHNbMF1bMF1cbiAgICB2YXIgeTAgPSBzWzBdWzFdXG4gICAgdmFyIHkxID0gc1sxXVsxXVxuICAgIHZhciBwID0gWyBNYXRoLm1pbih5MCwgeTEpLCBNYXRoLm1heCh5MCwgeTEpIF1cbiAgICBpZih4IGluIHRhYmxlKSB7XG4gICAgICB0YWJsZVt4XS5wdXNoKHApXG4gICAgfSBlbHNlIHtcbiAgICAgIHRhYmxlW3hdID0gWyBwIF1cbiAgICB9XG4gIH1cbiAgdmFyIGludGVydmFsVGFibGUgPSB7fVxuICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHRhYmxlKVxuICBmb3IodmFyIGk9MDsgaTxrZXlzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHNlZ3MgPSB0YWJsZVtrZXlzW2ldXVxuICAgIGludGVydmFsVGFibGVba2V5c1tpXV0gPSBtYWtlSW50ZXJ2YWxUcmVlKHNlZ3MpXG4gIH1cbiAgcmV0dXJuIGludGVydmFsU2VhcmNoKGludGVydmFsVGFibGUpXG59XG5cbmZ1bmN0aW9uIGJ1aWxkU2xhYlNlYXJjaChzbGFicywgY29vcmRpbmF0ZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHApIHtcbiAgICB2YXIgYnVja2V0ID0gYnNlYXJjaC5sZShjb29yZGluYXRlcywgcFswXSlcbiAgICBpZihidWNrZXQgPCAwKSB7XG4gICAgICByZXR1cm4gMVxuICAgIH1cbiAgICB2YXIgcm9vdCA9IHNsYWJzW2J1Y2tldF1cbiAgICBpZighcm9vdCkge1xuICAgICAgaWYoYnVja2V0ID4gMCAmJiBjb29yZGluYXRlc1tidWNrZXRdID09PSBwWzBdKSB7XG4gICAgICAgIHJvb3QgPSBzbGFic1tidWNrZXQtMV1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAxXG4gICAgICB9XG4gICAgfVxuICAgIHZhciBsYXN0T3JpZW50YXRpb24gPSAxXG4gICAgd2hpbGUocm9vdCkge1xuICAgICAgdmFyIHMgPSByb290LmtleVxuICAgICAgdmFyIG8gPSBvcmllbnQocCwgc1swXSwgc1sxXSlcbiAgICAgIGlmKHNbMF1bMF0gPCBzWzFdWzBdKSB7XG4gICAgICAgIGlmKG8gPCAwKSB7XG4gICAgICAgICAgcm9vdCA9IHJvb3QubGVmdFxuICAgICAgICB9IGVsc2UgaWYobyA+IDApIHtcbiAgICAgICAgICBsYXN0T3JpZW50YXRpb24gPSAtMVxuICAgICAgICAgIHJvb3QgPSByb290LnJpZ2h0XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIDBcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYobyA+IDApIHtcbiAgICAgICAgICByb290ID0gcm9vdC5sZWZ0XG4gICAgICAgIH0gZWxzZSBpZihvIDwgMCkge1xuICAgICAgICAgIGxhc3RPcmllbnRhdGlvbiA9IDFcbiAgICAgICAgICByb290ID0gcm9vdC5yaWdodFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiAwXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGxhc3RPcmllbnRhdGlvblxuICB9XG59XG5cbmZ1bmN0aW9uIGNsYXNzaWZ5RW1wdHkocCkge1xuICByZXR1cm4gMVxufVxuXG5mdW5jdGlvbiBjcmVhdGVDbGFzc2lmeVZlcnRpY2FsKHRlc3RWZXJ0aWNhbCkge1xuICByZXR1cm4gZnVuY3Rpb24gY2xhc3NpZnkocCkge1xuICAgIGlmKHRlc3RWZXJ0aWNhbChwWzBdLCBwWzFdKSkge1xuICAgICAgcmV0dXJuIDBcbiAgICB9XG4gICAgcmV0dXJuIDFcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVDbGFzc2lmeVBvaW50RGVnZW4odGVzdFZlcnRpY2FsLCB0ZXN0Tm9ybWFsKSB7XG4gIHJldHVybiBmdW5jdGlvbiBjbGFzc2lmeShwKSB7XG4gICAgaWYodGVzdFZlcnRpY2FsKHBbMF0sIHBbMV0pKSB7XG4gICAgICByZXR1cm4gMFxuICAgIH1cbiAgICByZXR1cm4gdGVzdE5vcm1hbChwKVxuICB9XG59XG5cbmZ1bmN0aW9uIHByZXByb2Nlc3NQb2x5Z29uKGxvb3BzKSB7XG4gIC8vQ29tcHV0ZSBudW1iZXIgb2YgbG9vcHNcbiAgdmFyIG51bUxvb3BzID0gbG9vcHMubGVuZ3RoXG5cbiAgLy9VbnBhY2sgc2VnbWVudHNcbiAgdmFyIHNlZ21lbnRzID0gW11cbiAgdmFyIHZzZWdtZW50cyA9IFtdXG4gIHZhciBwdHIgPSAwXG4gIGZvcih2YXIgaT0wOyBpPG51bUxvb3BzOyArK2kpIHtcbiAgICB2YXIgbG9vcCA9IGxvb3BzW2ldXG4gICAgdmFyIG51bVZlcnRpY2VzID0gbG9vcC5sZW5ndGhcbiAgICBmb3IodmFyIHM9bnVtVmVydGljZXMtMSx0PTA7IHQ8bnVtVmVydGljZXM7IHM9KHQrKykpIHtcbiAgICAgIHZhciBhID0gbG9vcFtzXVxuICAgICAgdmFyIGIgPSBsb29wW3RdXG4gICAgICBpZihhWzBdID09PSBiWzBdKSB7XG4gICAgICAgIHZzZWdtZW50cy5wdXNoKFthLGJdKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2VnbWVudHMucHVzaChbYSxiXSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvL0RlZ2VuZXJhdGUgY2FzZTogQWxsIGxvb3BzIGFyZSBlbXB0eVxuICBpZihzZWdtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICBpZih2c2VnbWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gY2xhc3NpZnlFbXB0eVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY3JlYXRlQ2xhc3NpZnlWZXJ0aWNhbChidWlsZFZlcnRpY2FsSW5kZXgodnNlZ21lbnRzKSlcbiAgICB9XG4gIH1cblxuICAvL0J1aWxkIHNsYWIgZGVjb21wb3NpdGlvblxuICB2YXIgc2xhYnMgPSBtYWtlU2xhYnMoc2VnbWVudHMpXG4gIHZhciB0ZXN0U2xhYiA9IGJ1aWxkU2xhYlNlYXJjaChzbGFicy5zbGFicywgc2xhYnMuY29vcmRpbmF0ZXMpXG5cbiAgaWYodnNlZ21lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiB0ZXN0U2xhYlxuICB9IGVsc2Uge1xuICAgIHJldHVybiBjcmVhdGVDbGFzc2lmeVBvaW50RGVnZW4oXG4gICAgICBidWlsZFZlcnRpY2FsSW5kZXgodnNlZ21lbnRzKSxcbiAgICAgIHRlc3RTbGFiKVxuICB9XG59XG59LHtcImJpbmFyeS1zZWFyY2gtYm91bmRzXCI6OTEsXCJpbnRlcnZhbC10cmVlLTFkXCI6NDE0LFwicm9idXN0LW9yaWVudGF0aW9uXCI6NTEwLFwic2xhYi1kZWNvbXBvc2l0aW9uXCI6NTI2fV0sNDczOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiBAY29weXJpZ2h0IDIwMTYgU2VhbiBDb25uZWxseSAoQHZvaWRxayksIGh0dHA6Ly9zeW50aGV0aS5jY1xuICogQGxpY2Vuc2UgTUlUXG4gKiBAcHJlc2VydmUgUHJvamVjdCBIb21lOiBodHRwczovL2dpdGh1Yi5jb20vdm9pZHFrL3BvbHlib29sanNcbiAqL1xuXG52YXIgQnVpbGRMb2cgPSBfZGVyZXFfKCcuL2xpYi9idWlsZC1sb2cnKTtcbnZhciBFcHNpbG9uID0gX2RlcmVxXygnLi9saWIvZXBzaWxvbicpO1xudmFyIEludGVyc2VjdGVyID0gX2RlcmVxXygnLi9saWIvaW50ZXJzZWN0ZXInKTtcbnZhciBTZWdtZW50Q2hhaW5lciA9IF9kZXJlcV8oJy4vbGliL3NlZ21lbnQtY2hhaW5lcicpO1xudmFyIFNlZ21lbnRTZWxlY3RvciA9IF9kZXJlcV8oJy4vbGliL3NlZ21lbnQtc2VsZWN0b3InKTtcbnZhciBHZW9KU09OID0gX2RlcmVxXygnLi9saWIvZ2VvanNvbicpO1xuXG52YXIgYnVpbGRMb2cgPSBmYWxzZTtcbnZhciBlcHNpbG9uID0gRXBzaWxvbigpO1xuXG52YXIgUG9seUJvb2w7XG5Qb2x5Qm9vbCA9IHtcblx0Ly8gZ2V0dGVyL3NldHRlciBmb3IgYnVpbGRMb2dcblx0YnVpbGRMb2c6IGZ1bmN0aW9uKGJsKXtcblx0XHRpZiAoYmwgPT09IHRydWUpXG5cdFx0XHRidWlsZExvZyA9IEJ1aWxkTG9nKCk7XG5cdFx0ZWxzZSBpZiAoYmwgPT09IGZhbHNlKVxuXHRcdFx0YnVpbGRMb2cgPSBmYWxzZTtcblx0XHRyZXR1cm4gYnVpbGRMb2cgPT09IGZhbHNlID8gZmFsc2UgOiBidWlsZExvZy5saXN0O1xuXHR9LFxuXHQvLyBnZXR0ZXIvc2V0dGVyIGZvciBlcHNpbG9uXG5cdGVwc2lsb246IGZ1bmN0aW9uKHYpe1xuXHRcdHJldHVybiBlcHNpbG9uLmVwc2lsb24odik7XG5cdH0sXG5cblx0Ly8gY29yZSBBUElcblx0c2VnbWVudHM6IGZ1bmN0aW9uKHBvbHkpe1xuXHRcdHZhciBpID0gSW50ZXJzZWN0ZXIodHJ1ZSwgZXBzaWxvbiwgYnVpbGRMb2cpO1xuXHRcdHBvbHkucmVnaW9ucy5mb3JFYWNoKGkuYWRkUmVnaW9uKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0c2VnbWVudHM6IGkuY2FsY3VsYXRlKHBvbHkuaW52ZXJ0ZWQpLFxuXHRcdFx0aW52ZXJ0ZWQ6IHBvbHkuaW52ZXJ0ZWRcblx0XHR9O1xuXHR9LFxuXHRjb21iaW5lOiBmdW5jdGlvbihzZWdtZW50czEsIHNlZ21lbnRzMil7XG5cdFx0dmFyIGkzID0gSW50ZXJzZWN0ZXIoZmFsc2UsIGVwc2lsb24sIGJ1aWxkTG9nKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0Y29tYmluZWQ6IGkzLmNhbGN1bGF0ZShcblx0XHRcdFx0c2VnbWVudHMxLnNlZ21lbnRzLCBzZWdtZW50czEuaW52ZXJ0ZWQsXG5cdFx0XHRcdHNlZ21lbnRzMi5zZWdtZW50cywgc2VnbWVudHMyLmludmVydGVkXG5cdFx0XHQpLFxuXHRcdFx0aW52ZXJ0ZWQxOiBzZWdtZW50czEuaW52ZXJ0ZWQsXG5cdFx0XHRpbnZlcnRlZDI6IHNlZ21lbnRzMi5pbnZlcnRlZFxuXHRcdH07XG5cdH0sXG5cdHNlbGVjdFVuaW9uOiBmdW5jdGlvbihjb21iaW5lZCl7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlZ21lbnRzOiBTZWdtZW50U2VsZWN0b3IudW5pb24oY29tYmluZWQuY29tYmluZWQsIGJ1aWxkTG9nKSxcblx0XHRcdGludmVydGVkOiBjb21iaW5lZC5pbnZlcnRlZDEgfHwgY29tYmluZWQuaW52ZXJ0ZWQyXG5cdFx0fVxuXHR9LFxuXHRzZWxlY3RJbnRlcnNlY3Q6IGZ1bmN0aW9uKGNvbWJpbmVkKXtcblx0XHRyZXR1cm4ge1xuXHRcdFx0c2VnbWVudHM6IFNlZ21lbnRTZWxlY3Rvci5pbnRlcnNlY3QoY29tYmluZWQuY29tYmluZWQsIGJ1aWxkTG9nKSxcblx0XHRcdGludmVydGVkOiBjb21iaW5lZC5pbnZlcnRlZDEgJiYgY29tYmluZWQuaW52ZXJ0ZWQyXG5cdFx0fVxuXHR9LFxuXHRzZWxlY3REaWZmZXJlbmNlOiBmdW5jdGlvbihjb21iaW5lZCl7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlZ21lbnRzOiBTZWdtZW50U2VsZWN0b3IuZGlmZmVyZW5jZShjb21iaW5lZC5jb21iaW5lZCwgYnVpbGRMb2cpLFxuXHRcdFx0aW52ZXJ0ZWQ6IGNvbWJpbmVkLmludmVydGVkMSAmJiAhY29tYmluZWQuaW52ZXJ0ZWQyXG5cdFx0fVxuXHR9LFxuXHRzZWxlY3REaWZmZXJlbmNlUmV2OiBmdW5jdGlvbihjb21iaW5lZCl7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlZ21lbnRzOiBTZWdtZW50U2VsZWN0b3IuZGlmZmVyZW5jZVJldihjb21iaW5lZC5jb21iaW5lZCwgYnVpbGRMb2cpLFxuXHRcdFx0aW52ZXJ0ZWQ6ICFjb21iaW5lZC5pbnZlcnRlZDEgJiYgY29tYmluZWQuaW52ZXJ0ZWQyXG5cdFx0fVxuXHR9LFxuXHRzZWxlY3RYb3I6IGZ1bmN0aW9uKGNvbWJpbmVkKXtcblx0XHRyZXR1cm4ge1xuXHRcdFx0c2VnbWVudHM6IFNlZ21lbnRTZWxlY3Rvci54b3IoY29tYmluZWQuY29tYmluZWQsIGJ1aWxkTG9nKSxcblx0XHRcdGludmVydGVkOiBjb21iaW5lZC5pbnZlcnRlZDEgIT09IGNvbWJpbmVkLmludmVydGVkMlxuXHRcdH1cblx0fSxcblx0cG9seWdvbjogZnVuY3Rpb24oc2VnbWVudHMpe1xuXHRcdHJldHVybiB7XG5cdFx0XHRyZWdpb25zOiBTZWdtZW50Q2hhaW5lcihzZWdtZW50cy5zZWdtZW50cywgZXBzaWxvbiwgYnVpbGRMb2cpLFxuXHRcdFx0aW52ZXJ0ZWQ6IHNlZ21lbnRzLmludmVydGVkXG5cdFx0fTtcblx0fSxcblxuXHQvLyBHZW9KU09OIGNvbnZlcnRlcnNcblx0cG9seWdvbkZyb21HZW9KU09OOiBmdW5jdGlvbihnZW9qc29uKXtcblx0XHRyZXR1cm4gR2VvSlNPTi50b1BvbHlnb24oUG9seUJvb2wsIGdlb2pzb24pO1xuXHR9LFxuXHRwb2x5Z29uVG9HZW9KU09OOiBmdW5jdGlvbihwb2x5KXtcblx0XHRyZXR1cm4gR2VvSlNPTi5mcm9tUG9seWdvbihQb2x5Qm9vbCwgZXBzaWxvbiwgcG9seSk7XG5cdH0sXG5cblx0Ly8gaGVscGVyIGZ1bmN0aW9ucyBmb3IgY29tbW9uIG9wZXJhdGlvbnNcblx0dW5pb246IGZ1bmN0aW9uKHBvbHkxLCBwb2x5Mil7XG5cdFx0cmV0dXJuIG9wZXJhdGUocG9seTEsIHBvbHkyLCBQb2x5Qm9vbC5zZWxlY3RVbmlvbik7XG5cdH0sXG5cdGludGVyc2VjdDogZnVuY3Rpb24ocG9seTEsIHBvbHkyKXtcblx0XHRyZXR1cm4gb3BlcmF0ZShwb2x5MSwgcG9seTIsIFBvbHlCb29sLnNlbGVjdEludGVyc2VjdCk7XG5cdH0sXG5cdGRpZmZlcmVuY2U6IGZ1bmN0aW9uKHBvbHkxLCBwb2x5Mil7XG5cdFx0cmV0dXJuIG9wZXJhdGUocG9seTEsIHBvbHkyLCBQb2x5Qm9vbC5zZWxlY3REaWZmZXJlbmNlKTtcblx0fSxcblx0ZGlmZmVyZW5jZVJldjogZnVuY3Rpb24ocG9seTEsIHBvbHkyKXtcblx0XHRyZXR1cm4gb3BlcmF0ZShwb2x5MSwgcG9seTIsIFBvbHlCb29sLnNlbGVjdERpZmZlcmVuY2VSZXYpO1xuXHR9LFxuXHR4b3I6IGZ1bmN0aW9uKHBvbHkxLCBwb2x5Mil7XG5cdFx0cmV0dXJuIG9wZXJhdGUocG9seTEsIHBvbHkyLCBQb2x5Qm9vbC5zZWxlY3RYb3IpO1xuXHR9XG59O1xuXG5mdW5jdGlvbiBvcGVyYXRlKHBvbHkxLCBwb2x5Miwgc2VsZWN0b3Ipe1xuXHR2YXIgc2VnMSA9IFBvbHlCb29sLnNlZ21lbnRzKHBvbHkxKTtcblx0dmFyIHNlZzIgPSBQb2x5Qm9vbC5zZWdtZW50cyhwb2x5Mik7XG5cdHZhciBjb21iID0gUG9seUJvb2wuY29tYmluZShzZWcxLCBzZWcyKTtcblx0dmFyIHNlZzMgPSBzZWxlY3Rvcihjb21iKTtcblx0cmV0dXJuIFBvbHlCb29sLnBvbHlnb24oc2VnMyk7XG59XG5cbmlmICh0eXBlb2Ygd2luZG93ID09PSAnb2JqZWN0Jylcblx0d2luZG93LlBvbHlCb29sID0gUG9seUJvb2w7XG5cbm1vZHVsZS5leHBvcnRzID0gUG9seUJvb2w7XG5cbn0se1wiLi9saWIvYnVpbGQtbG9nXCI6NDc0LFwiLi9saWIvZXBzaWxvblwiOjQ3NSxcIi4vbGliL2dlb2pzb25cIjo0NzYsXCIuL2xpYi9pbnRlcnNlY3RlclwiOjQ3NyxcIi4vbGliL3NlZ21lbnQtY2hhaW5lclwiOjQ3OSxcIi4vbGliL3NlZ21lbnQtc2VsZWN0b3JcIjo0ODB9XSw0NzQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gKGMpIENvcHlyaWdodCAyMDE2LCBTZWFuIENvbm5lbGx5IChAdm9pZHFrKSwgaHR0cDovL3N5bnRoZXRpLmNjXG4vLyBNSVQgTGljZW5zZVxuLy8gUHJvamVjdCBIb21lOiBodHRwczovL2dpdGh1Yi5jb20vdm9pZHFrL3BvbHlib29sanNcblxuLy9cbi8vIHVzZWQgc3RyaWN0bHkgZm9yIGxvZ2dpbmcgdGhlIHByb2Nlc3Npbmcgb2YgdGhlIGFsZ29yaXRobS4uLiBvbmx5IHVzZWZ1bCBpZiB5b3UgaW50ZW5kIG9uXG4vLyBsb29raW5nIHVuZGVyIHRoZSBjb3ZlcnMgKGZvciBwcmV0dHkgVUkncyBvciBkZWJ1Z2dpbmcpXG4vL1xuXG5mdW5jdGlvbiBCdWlsZExvZygpe1xuXHR2YXIgbXk7XG5cdHZhciBuZXh0U2VnbWVudElkID0gMDtcblx0dmFyIGN1clZlcnQgPSBmYWxzZTtcblxuXHRmdW5jdGlvbiBwdXNoKHR5cGUsIGRhdGEpe1xuXHRcdG15Lmxpc3QucHVzaCh7XG5cdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0ZGF0YTogZGF0YSA/IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoZGF0YSkpIDogdm9pZCAwXG5cdFx0fSk7XG5cdFx0cmV0dXJuIG15O1xuXHR9XG5cblx0bXkgPSB7XG5cdFx0bGlzdDogW10sXG5cdFx0c2VnbWVudElkOiBmdW5jdGlvbigpe1xuXHRcdFx0cmV0dXJuIG5leHRTZWdtZW50SWQrKztcblx0XHR9LFxuXHRcdGNoZWNrSW50ZXJzZWN0aW9uOiBmdW5jdGlvbihzZWcxLCBzZWcyKXtcblx0XHRcdHJldHVybiBwdXNoKCdjaGVjaycsIHsgc2VnMTogc2VnMSwgc2VnMjogc2VnMiB9KTtcblx0XHR9LFxuXHRcdHNlZ21lbnRDaG9wOiBmdW5jdGlvbihzZWcsIGVuZCl7XG5cdFx0XHRwdXNoKCdkaXZfc2VnJywgeyBzZWc6IHNlZywgcHQ6IGVuZCB9KTtcblx0XHRcdHJldHVybiBwdXNoKCdjaG9wJywgeyBzZWc6IHNlZywgcHQ6IGVuZCB9KTtcblx0XHR9LFxuXHRcdHN0YXR1c1JlbW92ZTogZnVuY3Rpb24oc2VnKXtcblx0XHRcdHJldHVybiBwdXNoKCdwb3Bfc2VnJywgeyBzZWc6IHNlZyB9KTtcblx0XHR9LFxuXHRcdHNlZ21lbnRVcGRhdGU6IGZ1bmN0aW9uKHNlZyl7XG5cdFx0XHRyZXR1cm4gcHVzaCgnc2VnX3VwZGF0ZScsIHsgc2VnOiBzZWcgfSk7XG5cdFx0fSxcblx0XHRzZWdtZW50TmV3OiBmdW5jdGlvbihzZWcsIHByaW1hcnkpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ25ld19zZWcnLCB7IHNlZzogc2VnLCBwcmltYXJ5OiBwcmltYXJ5IH0pO1xuXHRcdH0sXG5cdFx0c2VnbWVudFJlbW92ZTogZnVuY3Rpb24oc2VnKXtcblx0XHRcdHJldHVybiBwdXNoKCdyZW1fc2VnJywgeyBzZWc6IHNlZyB9KTtcblx0XHR9LFxuXHRcdHRlbXBTdGF0dXM6IGZ1bmN0aW9uKHNlZywgYWJvdmUsIGJlbG93KXtcblx0XHRcdHJldHVybiBwdXNoKCd0ZW1wX3N0YXR1cycsIHsgc2VnOiBzZWcsIGFib3ZlOiBhYm92ZSwgYmVsb3c6IGJlbG93IH0pO1xuXHRcdH0sXG5cdFx0cmV3aW5kOiBmdW5jdGlvbihzZWcpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ3Jld2luZCcsIHsgc2VnOiBzZWcgfSk7XG5cdFx0fSxcblx0XHRzdGF0dXM6IGZ1bmN0aW9uKHNlZywgYWJvdmUsIGJlbG93KXtcblx0XHRcdHJldHVybiBwdXNoKCdzdGF0dXMnLCB7IHNlZzogc2VnLCBhYm92ZTogYWJvdmUsIGJlbG93OiBiZWxvdyB9KTtcblx0XHR9LFxuXHRcdHZlcnQ6IGZ1bmN0aW9uKHgpe1xuXHRcdFx0aWYgKHggPT09IGN1clZlcnQpXG5cdFx0XHRcdHJldHVybiBteTtcblx0XHRcdGN1clZlcnQgPSB4O1xuXHRcdFx0cmV0dXJuIHB1c2goJ3ZlcnQnLCB7IHg6IHggfSk7XG5cdFx0fSxcblx0XHRsb2c6IGZ1bmN0aW9uKGRhdGEpe1xuXHRcdFx0aWYgKHR5cGVvZiBkYXRhICE9PSAnc3RyaW5nJylcblx0XHRcdFx0ZGF0YSA9IEpTT04uc3RyaW5naWZ5KGRhdGEsIGZhbHNlLCAnICAnKTtcblx0XHRcdHJldHVybiBwdXNoKCdsb2cnLCB7IHR4dDogZGF0YSB9KTtcblx0XHR9LFxuXHRcdHJlc2V0OiBmdW5jdGlvbigpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ3Jlc2V0Jyk7XG5cdFx0fSxcblx0XHRzZWxlY3RlZDogZnVuY3Rpb24oc2Vncyl7XG5cdFx0XHRyZXR1cm4gcHVzaCgnc2VsZWN0ZWQnLCB7IHNlZ3M6IHNlZ3MgfSk7XG5cdFx0fSxcblx0XHRjaGFpblN0YXJ0OiBmdW5jdGlvbihzZWcpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2NoYWluX3N0YXJ0JywgeyBzZWc6IHNlZyB9KTtcblx0XHR9LFxuXHRcdGNoYWluUmVtb3ZlSGVhZDogZnVuY3Rpb24oaW5kZXgsIHB0KXtcblx0XHRcdHJldHVybiBwdXNoKCdjaGFpbl9yZW1faGVhZCcsIHsgaW5kZXg6IGluZGV4LCBwdDogcHQgfSk7XG5cdFx0fSxcblx0XHRjaGFpblJlbW92ZVRhaWw6IGZ1bmN0aW9uKGluZGV4LCBwdCl7XG5cdFx0XHRyZXR1cm4gcHVzaCgnY2hhaW5fcmVtX3RhaWwnLCB7IGluZGV4OiBpbmRleCwgcHQ6IHB0IH0pO1xuXHRcdH0sXG5cdFx0Y2hhaW5OZXc6IGZ1bmN0aW9uKHB0MSwgcHQyKXtcblx0XHRcdHJldHVybiBwdXNoKCdjaGFpbl9uZXcnLCB7IHB0MTogcHQxLCBwdDI6IHB0MiB9KTtcblx0XHR9LFxuXHRcdGNoYWluTWF0Y2g6IGZ1bmN0aW9uKGluZGV4KXtcblx0XHRcdHJldHVybiBwdXNoKCdjaGFpbl9tYXRjaCcsIHsgaW5kZXg6IGluZGV4IH0pO1xuXHRcdH0sXG5cdFx0Y2hhaW5DbG9zZTogZnVuY3Rpb24oaW5kZXgpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2NoYWluX2Nsb3NlJywgeyBpbmRleDogaW5kZXggfSk7XG5cdFx0fSxcblx0XHRjaGFpbkFkZEhlYWQ6IGZ1bmN0aW9uKGluZGV4LCBwdCl7XG5cdFx0XHRyZXR1cm4gcHVzaCgnY2hhaW5fYWRkX2hlYWQnLCB7IGluZGV4OiBpbmRleCwgcHQ6IHB0IH0pO1xuXHRcdH0sXG5cdFx0Y2hhaW5BZGRUYWlsOiBmdW5jdGlvbihpbmRleCwgcHQpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2NoYWluX2FkZF90YWlsJywgeyBpbmRleDogaW5kZXgsIHB0OiBwdCwgfSk7XG5cdFx0fSxcblx0XHRjaGFpbkNvbm5lY3Q6IGZ1bmN0aW9uKGluZGV4MSwgaW5kZXgyKXtcblx0XHRcdHJldHVybiBwdXNoKCdjaGFpbl9jb24nLCB7IGluZGV4MTogaW5kZXgxLCBpbmRleDI6IGluZGV4MiB9KTtcblx0XHR9LFxuXHRcdGNoYWluUmV2ZXJzZTogZnVuY3Rpb24oaW5kZXgpe1xuXHRcdFx0cmV0dXJuIHB1c2goJ2NoYWluX3JldicsIHsgaW5kZXg6IGluZGV4IH0pO1xuXHRcdH0sXG5cdFx0Y2hhaW5Kb2luOiBmdW5jdGlvbihpbmRleDEsIGluZGV4Mil7XG5cdFx0XHRyZXR1cm4gcHVzaCgnY2hhaW5fam9pbicsIHsgaW5kZXgxOiBpbmRleDEsIGluZGV4MjogaW5kZXgyIH0pO1xuXHRcdH0sXG5cdFx0ZG9uZTogZnVuY3Rpb24oKXtcblx0XHRcdHJldHVybiBwdXNoKCdkb25lJyk7XG5cdFx0fVxuXHR9O1xuXHRyZXR1cm4gbXk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gQnVpbGRMb2c7XG5cbn0se31dLDQ3NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyAoYykgQ29weXJpZ2h0IDIwMTYsIFNlYW4gQ29ubmVsbHkgKEB2b2lkcWspLCBodHRwOi8vc3ludGhldGkuY2Ncbi8vIE1JVCBMaWNlbnNlXG4vLyBQcm9qZWN0IEhvbWU6IGh0dHBzOi8vZ2l0aHViLmNvbS92b2lkcWsvcG9seWJvb2xqc1xuXG4vL1xuLy8gcHJvdmlkZXMgdGhlIHJhdyBjb21wdXRhdGlvbiBmdW5jdGlvbnMgdGhhdCB0YWtlcyBlcHNpbG9uIGludG8gYWNjb3VudFxuLy9cbi8vIHplcm8gaXMgZGVmaW5lZCB0byBiZSBiZXR3ZWVuICgtZXBzaWxvbiwgZXBzaWxvbikgZXhjbHVzaXZlXG4vL1xuXG5mdW5jdGlvbiBFcHNpbG9uKGVwcyl7XG5cdGlmICh0eXBlb2YgZXBzICE9PSAnbnVtYmVyJylcblx0XHRlcHMgPSAwLjAwMDAwMDAwMDE7IC8vIHNhbmUgZGVmYXVsdD8gc3VyZSB3aHkgbm90XG5cdHZhciBteSA9IHtcblx0XHRlcHNpbG9uOiBmdW5jdGlvbih2KXtcblx0XHRcdGlmICh0eXBlb2YgdiA9PT0gJ251bWJlcicpXG5cdFx0XHRcdGVwcyA9IHY7XG5cdFx0XHRyZXR1cm4gZXBzO1xuXHRcdH0sXG5cdFx0cG9pbnRBYm92ZU9yT25MaW5lOiBmdW5jdGlvbihwdCwgbGVmdCwgcmlnaHQpe1xuXHRcdFx0dmFyIEF4ID0gbGVmdFswXTtcblx0XHRcdHZhciBBeSA9IGxlZnRbMV07XG5cdFx0XHR2YXIgQnggPSByaWdodFswXTtcblx0XHRcdHZhciBCeSA9IHJpZ2h0WzFdO1xuXHRcdFx0dmFyIEN4ID0gcHRbMF07XG5cdFx0XHR2YXIgQ3kgPSBwdFsxXTtcblx0XHRcdHJldHVybiAoQnggLSBBeCkgKiAoQ3kgLSBBeSkgLSAoQnkgLSBBeSkgKiAoQ3ggLSBBeCkgPj0gLWVwcztcblx0XHR9LFxuXHRcdHBvaW50QmV0d2VlbjogZnVuY3Rpb24ocCwgbGVmdCwgcmlnaHQpe1xuXHRcdFx0Ly8gcCBtdXN0IGJlIGNvbGxpbmVhciB3aXRoIGxlZnQtPnJpZ2h0XG5cdFx0XHQvLyByZXR1cm5zIGZhbHNlIGlmIHAgPT0gbGVmdCwgcCA9PSByaWdodCwgb3IgbGVmdCA9PSByaWdodFxuXHRcdFx0dmFyIGRfcHlfbHkgPSBwWzFdIC0gbGVmdFsxXTtcblx0XHRcdHZhciBkX3J4X2x4ID0gcmlnaHRbMF0gLSBsZWZ0WzBdO1xuXHRcdFx0dmFyIGRfcHhfbHggPSBwWzBdIC0gbGVmdFswXTtcblx0XHRcdHZhciBkX3J5X2x5ID0gcmlnaHRbMV0gLSBsZWZ0WzFdO1xuXG5cdFx0XHR2YXIgZG90ID0gZF9weF9seCAqIGRfcnhfbHggKyBkX3B5X2x5ICogZF9yeV9seTtcblx0XHRcdC8vIGlmIGBkb3RgIGlzIDAsIHRoZW4gYHBgID09IGBsZWZ0YCBvciBgbGVmdGAgPT0gYHJpZ2h0YCAocmVqZWN0KVxuXHRcdFx0Ly8gaWYgYGRvdGAgaXMgbGVzcyB0aGFuIDAsIHRoZW4gYHBgIGlzIHRvIHRoZSBsZWZ0IG9mIGBsZWZ0YCAocmVqZWN0KVxuXHRcdFx0aWYgKGRvdCA8IGVwcylcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXG5cdFx0XHR2YXIgc3FsZW4gPSBkX3J4X2x4ICogZF9yeF9seCArIGRfcnlfbHkgKiBkX3J5X2x5O1xuXHRcdFx0Ly8gaWYgYGRvdGAgPiBgc3FsZW5gLCB0aGVuIGBwYCBpcyB0byB0aGUgcmlnaHQgb2YgYHJpZ2h0YCAocmVqZWN0KVxuXHRcdFx0Ly8gdGhlcmVmb3JlLCBpZiBgZG90IC0gc3FsZW5gIGlzIGdyZWF0ZXIgdGhhbiAwLCB0aGVuIGBwYCBpcyB0byB0aGUgcmlnaHQgb2YgYHJpZ2h0YCAocmVqZWN0KVxuXHRcdFx0aWYgKGRvdCAtIHNxbGVuID4gLWVwcylcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9LFxuXHRcdHBvaW50c1NhbWVYOiBmdW5jdGlvbihwMSwgcDIpe1xuXHRcdFx0cmV0dXJuIE1hdGguYWJzKHAxWzBdIC0gcDJbMF0pIDwgZXBzO1xuXHRcdH0sXG5cdFx0cG9pbnRzU2FtZVk6IGZ1bmN0aW9uKHAxLCBwMil7XG5cdFx0XHRyZXR1cm4gTWF0aC5hYnMocDFbMV0gLSBwMlsxXSkgPCBlcHM7XG5cdFx0fSxcblx0XHRwb2ludHNTYW1lOiBmdW5jdGlvbihwMSwgcDIpe1xuXHRcdFx0cmV0dXJuIG15LnBvaW50c1NhbWVYKHAxLCBwMikgJiYgbXkucG9pbnRzU2FtZVkocDEsIHAyKTtcblx0XHR9LFxuXHRcdHBvaW50c0NvbXBhcmU6IGZ1bmN0aW9uKHAxLCBwMil7XG5cdFx0XHQvLyByZXR1cm5zIC0xIGlmIHAxIGlzIHNtYWxsZXIsIDEgaWYgcDIgaXMgc21hbGxlciwgMCBpZiBlcXVhbFxuXHRcdFx0aWYgKG15LnBvaW50c1NhbWVYKHAxLCBwMikpXG5cdFx0XHRcdHJldHVybiBteS5wb2ludHNTYW1lWShwMSwgcDIpID8gMCA6IChwMVsxXSA8IHAyWzFdID8gLTEgOiAxKTtcblx0XHRcdHJldHVybiBwMVswXSA8IHAyWzBdID8gLTEgOiAxO1xuXHRcdH0sXG5cdFx0cG9pbnRzQ29sbGluZWFyOiBmdW5jdGlvbihwdDEsIHB0MiwgcHQzKXtcblx0XHRcdC8vIGRvZXMgcHQxLT5wdDItPnB0MyBtYWtlIGEgc3RyYWlnaHQgbGluZT9cblx0XHRcdC8vIGVzc2VudGlhbGx5IHRoaXMgaXMganVzdCBjaGVja2luZyB0byBzZWUgaWYgdGhlIHNsb3BlKHB0MS0+cHQyKSA9PT0gc2xvcGUocHQyLT5wdDMpXG5cdFx0XHQvLyBpZiBzbG9wZXMgYXJlIGVxdWFsLCB0aGVuIHRoZXkgbXVzdCBiZSBjb2xsaW5lYXIsIGJlY2F1c2UgdGhleSBzaGFyZSBwdDJcblx0XHRcdHZhciBkeDEgPSBwdDFbMF0gLSBwdDJbMF07XG5cdFx0XHR2YXIgZHkxID0gcHQxWzFdIC0gcHQyWzFdO1xuXHRcdFx0dmFyIGR4MiA9IHB0MlswXSAtIHB0M1swXTtcblx0XHRcdHZhciBkeTIgPSBwdDJbMV0gLSBwdDNbMV07XG5cdFx0XHRyZXR1cm4gTWF0aC5hYnMoZHgxICogZHkyIC0gZHgyICogZHkxKSA8IGVwcztcblx0XHR9LFxuXHRcdGxpbmVzSW50ZXJzZWN0OiBmdW5jdGlvbihhMCwgYTEsIGIwLCBiMSl7XG5cdFx0XHQvLyByZXR1cm5zIGZhbHNlIGlmIHRoZSBsaW5lcyBhcmUgY29pbmNpZGVudCAoZS5nLiwgcGFyYWxsZWwgb3Igb24gdG9wIG9mIGVhY2ggb3RoZXIpXG5cdFx0XHQvL1xuXHRcdFx0Ly8gcmV0dXJucyBhbiBvYmplY3QgaWYgdGhlIGxpbmVzIGludGVyc2VjdDpcblx0XHRcdC8vICAge1xuXHRcdFx0Ly8gICAgIHB0OiBbeCwgeV0sICAgIHdoZXJlIHRoZSBpbnRlcnNlY3Rpb24gcG9pbnQgaXMgYXRcblx0XHRcdC8vICAgICBhbG9uZ0E6IHdoZXJlIGludGVyc2VjdGlvbiBwb2ludCBpcyBhbG9uZyBBLFxuXHRcdFx0Ly8gICAgIGFsb25nQjogd2hlcmUgaW50ZXJzZWN0aW9uIHBvaW50IGlzIGFsb25nIEJcblx0XHRcdC8vICAgfVxuXHRcdFx0Ly9cblx0XHRcdC8vICBhbG9uZ0EgYW5kIGFsb25nQiB3aWxsIGVhY2ggYmUgb25lIG9mOiAtMiwgLTEsIDAsIDEsIDJcblx0XHRcdC8vXG5cdFx0XHQvLyAgd2l0aCB0aGUgZm9sbG93aW5nIG1lYW5pbmc6XG5cdFx0XHQvL1xuXHRcdFx0Ly8gICAgLTIgICBpbnRlcnNlY3Rpb24gcG9pbnQgaXMgYmVmb3JlIHNlZ21lbnQncyBmaXJzdCBwb2ludFxuXHRcdFx0Ly8gICAgLTEgICBpbnRlcnNlY3Rpb24gcG9pbnQgaXMgZGlyZWN0bHkgb24gc2VnbWVudCdzIGZpcnN0IHBvaW50XG5cdFx0XHQvLyAgICAgMCAgIGludGVyc2VjdGlvbiBwb2ludCBpcyBiZXR3ZWVuIHNlZ21lbnQncyBmaXJzdCBhbmQgc2Vjb25kIHBvaW50cyAoZXhjbHVzaXZlKVxuXHRcdFx0Ly8gICAgIDEgICBpbnRlcnNlY3Rpb24gcG9pbnQgaXMgZGlyZWN0bHkgb24gc2VnbWVudCdzIHNlY29uZCBwb2ludFxuXHRcdFx0Ly8gICAgIDIgICBpbnRlcnNlY3Rpb24gcG9pbnQgaXMgYWZ0ZXIgc2VnbWVudCdzIHNlY29uZCBwb2ludFxuXHRcdFx0dmFyIGFkeCA9IGExWzBdIC0gYTBbMF07XG5cdFx0XHR2YXIgYWR5ID0gYTFbMV0gLSBhMFsxXTtcblx0XHRcdHZhciBiZHggPSBiMVswXSAtIGIwWzBdO1xuXHRcdFx0dmFyIGJkeSA9IGIxWzFdIC0gYjBbMV07XG5cblx0XHRcdHZhciBheGIgPSBhZHggKiBiZHkgLSBhZHkgKiBiZHg7XG5cdFx0XHRpZiAoTWF0aC5hYnMoYXhiKSA8IGVwcylcblx0XHRcdFx0cmV0dXJuIGZhbHNlOyAvLyBsaW5lcyBhcmUgY29pbmNpZGVudFxuXG5cdFx0XHR2YXIgZHggPSBhMFswXSAtIGIwWzBdO1xuXHRcdFx0dmFyIGR5ID0gYTBbMV0gLSBiMFsxXTtcblxuXHRcdFx0dmFyIEEgPSAoYmR4ICogZHkgLSBiZHkgKiBkeCkgLyBheGI7XG5cdFx0XHR2YXIgQiA9IChhZHggKiBkeSAtIGFkeSAqIGR4KSAvIGF4YjtcblxuXHRcdFx0dmFyIHJldCA9IHtcblx0XHRcdFx0YWxvbmdBOiAwLFxuXHRcdFx0XHRhbG9uZ0I6IDAsXG5cdFx0XHRcdHB0OiBbXG5cdFx0XHRcdFx0YTBbMF0gKyBBICogYWR4LFxuXHRcdFx0XHRcdGEwWzFdICsgQSAqIGFkeVxuXHRcdFx0XHRdXG5cdFx0XHR9O1xuXG5cdFx0XHQvLyBjYXRlZ29yaXplIHdoZXJlIGludGVyc2VjdGlvbiBwb2ludCBpcyBhbG9uZyBBIGFuZCBCXG5cblx0XHRcdGlmIChBIDw9IC1lcHMpXG5cdFx0XHRcdHJldC5hbG9uZ0EgPSAtMjtcblx0XHRcdGVsc2UgaWYgKEEgPCBlcHMpXG5cdFx0XHRcdHJldC5hbG9uZ0EgPSAtMTtcblx0XHRcdGVsc2UgaWYgKEEgLSAxIDw9IC1lcHMpXG5cdFx0XHRcdHJldC5hbG9uZ0EgPSAwO1xuXHRcdFx0ZWxzZSBpZiAoQSAtIDEgPCBlcHMpXG5cdFx0XHRcdHJldC5hbG9uZ0EgPSAxO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHRyZXQuYWxvbmdBID0gMjtcblxuXHRcdFx0aWYgKEIgPD0gLWVwcylcblx0XHRcdFx0cmV0LmFsb25nQiA9IC0yO1xuXHRcdFx0ZWxzZSBpZiAoQiA8IGVwcylcblx0XHRcdFx0cmV0LmFsb25nQiA9IC0xO1xuXHRcdFx0ZWxzZSBpZiAoQiAtIDEgPD0gLWVwcylcblx0XHRcdFx0cmV0LmFsb25nQiA9IDA7XG5cdFx0XHRlbHNlIGlmIChCIC0gMSA8IGVwcylcblx0XHRcdFx0cmV0LmFsb25nQiA9IDE7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHJldC5hbG9uZ0IgPSAyO1xuXG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH0sXG5cdFx0cG9pbnRJbnNpZGVSZWdpb246IGZ1bmN0aW9uKHB0LCByZWdpb24pe1xuXHRcdFx0dmFyIHggPSBwdFswXTtcblx0XHRcdHZhciB5ID0gcHRbMV07XG5cdFx0XHR2YXIgbGFzdF94ID0gcmVnaW9uW3JlZ2lvbi5sZW5ndGggLSAxXVswXTtcblx0XHRcdHZhciBsYXN0X3kgPSByZWdpb25bcmVnaW9uLmxlbmd0aCAtIDFdWzFdO1xuXHRcdFx0dmFyIGluc2lkZSA9IGZhbHNlO1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCByZWdpb24ubGVuZ3RoOyBpKyspe1xuXHRcdFx0XHR2YXIgY3Vycl94ID0gcmVnaW9uW2ldWzBdO1xuXHRcdFx0XHR2YXIgY3Vycl95ID0gcmVnaW9uW2ldWzFdO1xuXG5cdFx0XHRcdC8vIGlmIHkgaXMgYmV0d2VlbiBjdXJyX3kgYW5kIGxhc3RfeSwgYW5kXG5cdFx0XHRcdC8vIHggaXMgdG8gdGhlIHJpZ2h0IG9mIHRoZSBib3VuZGFyeSBjcmVhdGVkIGJ5IHRoZSBsaW5lXG5cdFx0XHRcdGlmICgoY3Vycl95IC0geSA+IGVwcykgIT0gKGxhc3RfeSAtIHkgPiBlcHMpICYmXG5cdFx0XHRcdFx0KGxhc3RfeCAtIGN1cnJfeCkgKiAoeSAtIGN1cnJfeSkgLyAobGFzdF95IC0gY3Vycl95KSArIGN1cnJfeCAtIHggPiBlcHMpXG5cdFx0XHRcdFx0aW5zaWRlID0gIWluc2lkZVxuXG5cdFx0XHRcdGxhc3RfeCA9IGN1cnJfeDtcblx0XHRcdFx0bGFzdF95ID0gY3Vycl95O1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGluc2lkZTtcblx0XHR9XG5cdH07XG5cdHJldHVybiBteTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBFcHNpbG9uO1xuXG59LHt9XSw0NzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gKGMpIENvcHlyaWdodCAyMDE3LCBTZWFuIENvbm5lbGx5IChAdm9pZHFrKSwgaHR0cDovL3N5bnRoZXRpLmNjXG4vLyBNSVQgTGljZW5zZVxuLy8gUHJvamVjdCBIb21lOiBodHRwczovL2dpdGh1Yi5jb20vdm9pZHFrL3BvbHlib29sanNcblxuLy9cbi8vIGNvbnZlcnQgYmV0d2VlbiBQb2x5Qm9vbCBwb2x5Z29uIGZvcm1hdCBhbmQgR2VvSlNPTiBmb3JtYXRzIChQb2x5Z29uIGFuZCBNdWx0aVBvbHlnb24pXG4vL1xuXG52YXIgR2VvSlNPTiA9IHtcblx0Ly8gY29udmVydCBhIEdlb0pTT04gb2JqZWN0IHRvIGEgUG9seUJvb2wgcG9seWdvblxuXHR0b1BvbHlnb246IGZ1bmN0aW9uKFBvbHlCb29sLCBnZW9qc29uKXtcblxuXHRcdC8vIGNvbnZlcnRzIGxpc3Qgb2YgTGluZVN0cmluZydzIHRvIHNlZ21lbnRzXG5cdFx0ZnVuY3Rpb24gR2VvUG9seShjb29yZHMpe1xuXHRcdFx0Ly8gY2hlY2sgZm9yIGVtcHR5IGNvb3Jkc1xuXHRcdFx0aWYgKGNvb3Jkcy5sZW5ndGggPD0gMClcblx0XHRcdFx0cmV0dXJuIFBvbHlCb29sLnNlZ21lbnRzKHsgaW52ZXJ0ZWQ6IGZhbHNlLCByZWdpb25zOiBbXSB9KTtcblxuXHRcdFx0Ly8gY29udmVydCBMaW5lU3RyaW5nIHRvIHNlZ21lbnRzXG5cdFx0XHRmdW5jdGlvbiBMaW5lU3RyaW5nKGxzKXtcblx0XHRcdFx0Ly8gcmVtb3ZlIHRhaWwgd2hpY2ggc2hvdWxkIGJlIHRoZSBzYW1lIGFzIGhlYWRcblx0XHRcdFx0dmFyIHJlZyA9IGxzLnNsaWNlKDAsIGxzLmxlbmd0aCAtIDEpO1xuXHRcdFx0XHRyZXR1cm4gUG9seUJvb2wuc2VnbWVudHMoeyBpbnZlcnRlZDogZmFsc2UsIHJlZ2lvbnM6IFtyZWddIH0pO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyB0aGUgZmlyc3QgTGluZVN0cmluZyBpcyBjb25zaWRlcmVkIHRoZSBvdXRzaWRlXG5cdFx0XHR2YXIgb3V0ID0gTGluZVN0cmluZyhjb29yZHNbMF0pO1xuXG5cdFx0XHQvLyB0aGUgcmVzdCBvZiB0aGUgTGluZVN0cmluZ3MgYXJlIGNvbnNpZGVyZWQgaW50ZXJpb3IgaG9sZXMsIHNvIHN1YnRyYWN0IHRoZW0gZnJvbSB0aGVcblx0XHRcdC8vIGN1cnJlbnQgcmVzdWx0XG5cdFx0XHRmb3IgKHZhciBpID0gMTsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKylcblx0XHRcdFx0b3V0ID0gUG9seUJvb2wuc2VsZWN0RGlmZmVyZW5jZShQb2x5Qm9vbC5jb21iaW5lKG91dCwgTGluZVN0cmluZyhjb29yZHNbaV0pKSk7XG5cblx0XHRcdHJldHVybiBvdXQ7XG5cdFx0fVxuXG5cdFx0aWYgKGdlb2pzb24udHlwZSA9PT0gJ1BvbHlnb24nKXtcblx0XHRcdC8vIHNpbmdsZSBwb2x5Z29uLCBzbyBqdXN0IGNvbnZlcnQgaXQgYW5kIHdlJ3JlIGRvbmVcblx0XHRcdHJldHVybiBQb2x5Qm9vbC5wb2x5Z29uKEdlb1BvbHkoZ2VvanNvbi5jb29yZGluYXRlcykpO1xuXHRcdH1cblx0XHRlbHNlIGlmIChnZW9qc29uLnR5cGUgPT09ICdNdWx0aVBvbHlnb24nKXtcblx0XHRcdC8vIG11bHRpcGxlIHBvbHlnb25zLCBzbyB1bmlvbiBhbGwgdGhlIHBvbHlnb25zIHRvZ2V0aGVyXG5cdFx0XHR2YXIgb3V0ID0gUG9seUJvb2wuc2VnbWVudHMoeyBpbnZlcnRlZDogZmFsc2UsIHJlZ2lvbnM6IFtdIH0pO1xuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBnZW9qc29uLmNvb3JkaW5hdGVzLmxlbmd0aDsgaSsrKVxuXHRcdFx0XHRvdXQgPSBQb2x5Qm9vbC5zZWxlY3RVbmlvbihQb2x5Qm9vbC5jb21iaW5lKG91dCwgR2VvUG9seShnZW9qc29uLmNvb3JkaW5hdGVzW2ldKSkpO1xuXHRcdFx0cmV0dXJuIFBvbHlCb29sLnBvbHlnb24ob3V0KTtcblx0XHR9XG5cdFx0dGhyb3cgbmV3IEVycm9yKCdQb2x5Qm9vbDogQ2Fubm90IGNvbnZlcnQgR2VvSlNPTiBvYmplY3QgdG8gUG9seUJvb2wgcG9seWdvbicpO1xuXHR9LFxuXG5cdC8vIGNvbnZlcnQgYSBQb2x5Qm9vbCBwb2x5Z29uIHRvIGEgR2VvSlNPTiBvYmplY3Rcblx0ZnJvbVBvbHlnb246IGZ1bmN0aW9uKFBvbHlCb29sLCBlcHMsIHBvbHkpe1xuXHRcdC8vIG1ha2Ugc3VyZSBvdXQgcG9seWdvbiBpcyBjbGVhblxuXHRcdHBvbHkgPSBQb2x5Qm9vbC5wb2x5Z29uKFBvbHlCb29sLnNlZ21lbnRzKHBvbHkpKTtcblxuXHRcdC8vIHRlc3QgaWYgcjEgaXMgaW5zaWRlIHIyXG5cdFx0ZnVuY3Rpb24gcmVnaW9uSW5zaWRlUmVnaW9uKHIxLCByMil7XG5cdFx0XHQvLyB3ZSdyZSBndWFyYW50ZWVkIG5vIGxpbmVzIGludGVyc2VjdCAoYmVjYXVzZSB0aGUgcG9seWdvbiBpcyBjbGVhbiksIGJ1dCBhIHZlcnRleFxuXHRcdFx0Ly8gY291bGQgYmUgb24gdGhlIGVkZ2UgLS0gc28gd2UganVzdCBhdmVyYWdlIHB0WzBdIGFuZCBwdFsxXSB0byBwcm9kdWNlIGEgcG9pbnQgb24gdGhlXG5cdFx0XHQvLyBlZGdlIG9mIHRoZSBmaXJzdCBsaW5lLCB3aGljaCBjYW5ub3QgYmUgb24gYW4gZWRnZVxuXHRcdFx0cmV0dXJuIGVwcy5wb2ludEluc2lkZVJlZ2lvbihbXG5cdFx0XHRcdChyMVswXVswXSArIHIxWzFdWzBdKSAqIDAuNSxcblx0XHRcdFx0KHIxWzBdWzFdICsgcjFbMV1bMV0pICogMC41XG5cdFx0XHRdLCByMik7XG5cdFx0fVxuXG5cdFx0Ly8gY2FsY3VsYXRlIGluc2lkZSBoZWlyYXJjaHlcblx0XHQvL1xuXHRcdC8vICBfX19fX19fX19fX19fX19fX19fX18gICBfX19fX19fICAgIHJvb3RzIC0+IEEgICAgICAgLT4gRlxuXHRcdC8vIHwgICAgICAgICAgQSAgICAgICAgICB8IHwgICBGICAgfCAgICAgICAgICAgIHwgICAgICAgICAgfFxuXHRcdC8vIHwgIF9fX19fX18gICBfX19fX19fICB8IHwgIF9fXyAgfCAgICAgICAgICAgICstLSBCICAgICAgKy0tIEdcblx0XHQvLyB8IHwgICBCICAgfCB8ICAgQyAgIHwgfCB8IHwgICB8IHwgICAgICAgICAgICB8ICAgfFxuXHRcdC8vIHwgfCAgX19fICB8IHwgIF9fXyAgfCB8IHwgfCAgIHwgfCAgICAgICAgICAgIHwgICArLS0gRFxuXHRcdC8vIHwgfCB8IEQgfCB8IHwgfCBFIHwgfCB8IHwgfCBHIHwgfCAgICAgICAgICAgIHxcblx0XHQvLyB8IHwgfF9fX3wgfCB8IHxfX198IHwgfCB8IHwgICB8IHwgICAgICAgICAgICArLS0gQ1xuXHRcdC8vIHwgfF9fX19fX198IHxfX19fX19ffCB8IHwgfF9fX3wgfCAgICAgICAgICAgICAgICB8XG5cdFx0Ly8gfF9fX19fX19fX19fX19fX19fX19fX3wgfF9fX19fX198ICAgICAgICAgICAgICAgICstLSBFXG5cblx0XHRmdW5jdGlvbiBuZXdOb2RlKHJlZ2lvbil7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRyZWdpb246IHJlZ2lvbixcblx0XHRcdFx0Y2hpbGRyZW46IFtdXG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdHZhciByb290cyA9IG5ld05vZGUobnVsbCk7XG5cblx0XHRmdW5jdGlvbiBhZGRDaGlsZChyb290LCByZWdpb24pe1xuXHRcdFx0Ly8gZmlyc3QgY2hlY2sgaWYgd2UncmUgaW5zaWRlIGFueSBjaGlsZHJlblxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCByb290LmNoaWxkcmVuLmxlbmd0aDsgaSsrKXtcblx0XHRcdFx0dmFyIGNoaWxkID0gcm9vdC5jaGlsZHJlbltpXTtcblx0XHRcdFx0aWYgKHJlZ2lvbkluc2lkZVJlZ2lvbihyZWdpb24sIGNoaWxkLnJlZ2lvbikpe1xuXHRcdFx0XHRcdC8vIHdlIGFyZSwgc28gaW5zZXJ0IGluc2lkZSB0aGVtIGluc3RlYWRcblx0XHRcdFx0XHRhZGRDaGlsZChjaGlsZCwgcmVnaW9uKTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gbm90IGluc2lkZSBhbnkgY2hpbGRyZW4sIHNvIGNoZWNrIHRvIHNlZSBpZiBhbnkgY2hpbGRyZW4gYXJlIGluc2lkZSB1c1xuXHRcdFx0dmFyIG5vZGUgPSBuZXdOb2RlKHJlZ2lvbik7XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHJvb3QuY2hpbGRyZW4ubGVuZ3RoOyBpKyspe1xuXHRcdFx0XHR2YXIgY2hpbGQgPSByb290LmNoaWxkcmVuW2ldO1xuXHRcdFx0XHRpZiAocmVnaW9uSW5zaWRlUmVnaW9uKGNoaWxkLnJlZ2lvbiwgcmVnaW9uKSl7XG5cdFx0XHRcdFx0Ly8gb29wcy4uLiBtb3ZlIHRoZSBjaGlsZCBiZW5lYXRoIHVzLCBhbmQgcmVtb3ZlIHRoZW0gZnJvbSByb290XG5cdFx0XHRcdFx0bm9kZS5jaGlsZHJlbi5wdXNoKGNoaWxkKTtcblx0XHRcdFx0XHRyb290LmNoaWxkcmVuLnNwbGljZShpLCAxKTtcblx0XHRcdFx0XHRpLS07XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gbm93IHdlIGNhbiBhZGQgb3Vyc2VsdmVzXG5cdFx0XHRyb290LmNoaWxkcmVuLnB1c2gobm9kZSk7XG5cdFx0fVxuXG5cdFx0Ly8gYWRkIGFsbCByZWdpb25zIHRvIHRoZSByb290XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwb2x5LnJlZ2lvbnMubGVuZ3RoOyBpKyspe1xuXHRcdFx0dmFyIHJlZ2lvbiA9IHBvbHkucmVnaW9uc1tpXTtcblx0XHRcdGlmIChyZWdpb24ubGVuZ3RoIDwgMykgLy8gcmVnaW9ucyBtdXN0IGhhdmUgYXQgbGVhc3QgMyBwb2ludHMgKHNhbml0eSBjaGVjaylcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRhZGRDaGlsZChyb290cywgcmVnaW9uKTtcblx0XHR9XG5cblx0XHQvLyB3aXRoIG91ciBoZWlyYXJjaHksIHdlIGNhbiBkaXN0aW5ndWlzaCBiZXR3ZWVuIGV4dGVyaW9yIGJvcmRlcnMsIGFuZCBpbnRlcmlvciBob2xlc1xuXHRcdC8vIHRoZSByb290IG5vZGVzIGFyZSBleHRlcmlvciwgY2hpbGRyZW4gYXJlIGludGVyaW9yLCBjaGlsZHJlbidzIGNoaWxkcmVuIGFyZSBleHRlcmlvcixcblx0XHQvLyBjaGlsZHJlbidzIGNoaWxkcmVuJ3MgY2hpbGRyZW4gYXJlIGludGVyaW9yLCBldGNcblxuXHRcdC8vIHdoaWxlIHdlJ3JlIGF0IGl0LCBleHRlcmlvcnMgYXJlIGNvdW50ZXItY2xvY2t3aXNlLCBhbmQgaW50ZXJpb3JzIGFyZSBjbG9ja3dpc2VcblxuXHRcdGZ1bmN0aW9uIGZvcmNlV2luZGluZyhyZWdpb24sIGNsb2Nrd2lzZSl7XG5cdFx0XHQvLyBmaXJzdCwgc2VlIGlmIHdlJ3JlIGNsb2Nrd2lzZSBvciBjb3VudGVyLWNsb2Nrd2lzZVxuXHRcdFx0Ly8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2hvZWxhY2VfZm9ybXVsYVxuXHRcdFx0dmFyIHdpbmRpbmcgPSAwO1xuXHRcdFx0dmFyIGxhc3RfeCA9IHJlZ2lvbltyZWdpb24ubGVuZ3RoIC0gMV1bMF07XG5cdFx0XHR2YXIgbGFzdF95ID0gcmVnaW9uW3JlZ2lvbi5sZW5ndGggLSAxXVsxXTtcblx0XHRcdHZhciBjb3B5ID0gW107XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHJlZ2lvbi5sZW5ndGg7IGkrKyl7XG5cdFx0XHRcdHZhciBjdXJyX3ggPSByZWdpb25baV1bMF07XG5cdFx0XHRcdHZhciBjdXJyX3kgPSByZWdpb25baV1bMV07XG5cdFx0XHRcdGNvcHkucHVzaChbY3Vycl94LCBjdXJyX3ldKTsgLy8gY3JlYXRlIGEgY29weSB3aGlsZSB3ZSdyZSBhdCBpdFxuXHRcdFx0XHR3aW5kaW5nICs9IGN1cnJfeSAqIGxhc3RfeCAtIGN1cnJfeCAqIGxhc3RfeTtcblx0XHRcdFx0bGFzdF94ID0gY3Vycl94O1xuXHRcdFx0XHRsYXN0X3kgPSBjdXJyX3k7XG5cdFx0XHR9XG5cdFx0XHQvLyB0aGlzIGFzc3VtZXMgQ2FydGVzaWFuIGNvb3JkaW5hdGVzIChZIGlzIHBvc2l0aXZlIGdvaW5nIHVwKVxuXHRcdFx0dmFyIGlzY2xvY2t3aXNlID0gd2luZGluZyA8IDA7XG5cdFx0XHRpZiAoaXNjbG9ja3dpc2UgIT09IGNsb2Nrd2lzZSlcblx0XHRcdFx0Y29weS5yZXZlcnNlKCk7XG5cdFx0XHQvLyB3aGlsZSB3ZSdyZSBoZXJlLCB0aGUgbGFzdCBwb2ludCBtdXN0IGJlIHRoZSBmaXJzdCBwb2ludC4uLlxuXHRcdFx0Y29weS5wdXNoKFtjb3B5WzBdWzBdLCBjb3B5WzBdWzFdXSk7XG5cdFx0XHRyZXR1cm4gY29weTtcblx0XHR9XG5cblx0XHR2YXIgZ2VvcG9seXMgPSBbXTtcblxuXHRcdGZ1bmN0aW9uIGFkZEV4dGVyaW9yKG5vZGUpe1xuXHRcdFx0dmFyIHBvbHkgPSBbZm9yY2VXaW5kaW5nKG5vZGUucmVnaW9uLCBmYWxzZSldO1xuXHRcdFx0Z2VvcG9seXMucHVzaChwb2x5KTtcblx0XHRcdC8vIGNoaWxkcmVuIG9mIGV4dGVyaW9ycyBhcmUgaW50ZXJpb3Jcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkrKylcblx0XHRcdFx0cG9seS5wdXNoKGdldEludGVyaW9yKG5vZGUuY2hpbGRyZW5baV0pKTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBnZXRJbnRlcmlvcihub2RlKXtcblx0XHRcdC8vIGNoaWxkcmVuIG9mIGludGVyaW9ycyBhcmUgZXh0ZXJpb3Jcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkrKylcblx0XHRcdFx0YWRkRXh0ZXJpb3Iobm9kZS5jaGlsZHJlbltpXSk7XG5cdFx0XHQvLyByZXR1cm4gdGhlIGNsb2Nrd2lzZSBpbnRlcmlvclxuXHRcdFx0cmV0dXJuIGZvcmNlV2luZGluZyhub2RlLnJlZ2lvbiwgdHJ1ZSk7XG5cdFx0fVxuXG5cdFx0Ly8gcm9vdCBub2RlcyBhcmUgZXh0ZXJpb3Jcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHJvb3RzLmNoaWxkcmVuLmxlbmd0aDsgaSsrKVxuXHRcdFx0YWRkRXh0ZXJpb3Iocm9vdHMuY2hpbGRyZW5baV0pO1xuXG5cdFx0Ly8gbGFzdGx5LCBjb25zdHJ1Y3QgdGhlIGFwcHJvcnByaWF0ZSBHZW9KU09OIG9iamVjdFxuXG5cdFx0aWYgKGdlb3BvbHlzLmxlbmd0aCA8PSAwKSAvLyBlbXB0eSBHZW9KU09OIFBvbHlnb25cblx0XHRcdHJldHVybiB7IHR5cGU6ICdQb2x5Z29uJywgY29vcmRpbmF0ZXM6IFtdIH07XG5cdFx0aWYgKGdlb3BvbHlzLmxlbmd0aCA9PSAxKSAvLyB1c2UgYSBHZW9KU09OIFBvbHlnb25cblx0XHRcdHJldHVybiB7IHR5cGU6ICdQb2x5Z29uJywgY29vcmRpbmF0ZXM6IGdlb3BvbHlzWzBdIH07XG5cdFx0cmV0dXJuIHsgLy8gb3RoZXJ3aXNlLCB1c2UgYSBHZW9KU09OIE11bHRpUG9seWdvblxuXHRcdFx0dHlwZTogJ011bHRpUG9seWdvbicsXG5cdFx0XHRjb29yZGluYXRlczogZ2VvcG9seXNcblx0XHR9O1xuXHR9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdlb0pTT047XG5cbn0se31dLDQ3NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyAoYykgQ29weXJpZ2h0IDIwMTYsIFNlYW4gQ29ubmVsbHkgKEB2b2lkcWspLCBodHRwOi8vc3ludGhldGkuY2Ncbi8vIE1JVCBMaWNlbnNlXG4vLyBQcm9qZWN0IEhvbWU6IGh0dHBzOi8vZ2l0aHViLmNvbS92b2lkcWsvcG9seWJvb2xqc1xuXG4vL1xuLy8gdGhpcyBpcyB0aGUgY29yZSB3b3JrLWhvcnNlXG4vL1xuXG52YXIgTGlua2VkTGlzdCA9IF9kZXJlcV8oJy4vbGlua2VkLWxpc3QnKTtcblxuZnVuY3Rpb24gSW50ZXJzZWN0ZXIoc2VsZkludGVyc2VjdGlvbiwgZXBzLCBidWlsZExvZyl7XG5cdC8vIHNlbGZJbnRlcnNlY3Rpb24gaXMgdHJ1ZS9mYWxzZSBkZXBlbmRpbmcgb24gdGhlIHBoYXNlIG9mIHRoZSBvdmVyYWxsIGFsZ29yaXRobVxuXG5cdC8vXG5cdC8vIHNlZ21lbnQgY3JlYXRpb25cblx0Ly9cblxuXHRmdW5jdGlvbiBzZWdtZW50TmV3KHN0YXJ0LCBlbmQpe1xuXHRcdHJldHVybiB7XG5cdFx0XHRpZDogYnVpbGRMb2cgPyBidWlsZExvZy5zZWdtZW50SWQoKSA6IC0xLFxuXHRcdFx0c3RhcnQ6IHN0YXJ0LFxuXHRcdFx0ZW5kOiBlbmQsXG5cdFx0XHRteUZpbGw6IHtcblx0XHRcdFx0YWJvdmU6IG51bGwsIC8vIGlzIHRoZXJlIGZpbGwgYWJvdmUgdXM/XG5cdFx0XHRcdGJlbG93OiBudWxsICAvLyBpcyB0aGVyZSBmaWxsIGJlbG93IHVzP1xuXHRcdFx0fSxcblx0XHRcdG90aGVyRmlsbDogbnVsbFxuXHRcdH07XG5cdH1cblxuXHRmdW5jdGlvbiBzZWdtZW50Q29weShzdGFydCwgZW5kLCBzZWcpe1xuXHRcdHJldHVybiB7XG5cdFx0XHRpZDogYnVpbGRMb2cgPyBidWlsZExvZy5zZWdtZW50SWQoKSA6IC0xLFxuXHRcdFx0c3RhcnQ6IHN0YXJ0LFxuXHRcdFx0ZW5kOiBlbmQsXG5cdFx0XHRteUZpbGw6IHtcblx0XHRcdFx0YWJvdmU6IHNlZy5teUZpbGwuYWJvdmUsXG5cdFx0XHRcdGJlbG93OiBzZWcubXlGaWxsLmJlbG93XG5cdFx0XHR9LFxuXHRcdFx0b3RoZXJGaWxsOiBudWxsXG5cdFx0fTtcblx0fVxuXG5cdC8vXG5cdC8vIGV2ZW50IGxvZ2ljXG5cdC8vXG5cblx0dmFyIGV2ZW50X3Jvb3QgPSBMaW5rZWRMaXN0LmNyZWF0ZSgpO1xuXG5cdGZ1bmN0aW9uIGV2ZW50Q29tcGFyZShwMV9pc1N0YXJ0LCBwMV8xLCBwMV8yLCBwMl9pc1N0YXJ0LCBwMl8xLCBwMl8yKXtcblx0XHQvLyBjb21wYXJlIHRoZSBzZWxlY3RlZCBwb2ludHMgZmlyc3Rcblx0XHR2YXIgY29tcCA9IGVwcy5wb2ludHNDb21wYXJlKHAxXzEsIHAyXzEpO1xuXHRcdGlmIChjb21wICE9PSAwKVxuXHRcdFx0cmV0dXJuIGNvbXA7XG5cdFx0Ly8gdGhlIHNlbGVjdGVkIHBvaW50cyBhcmUgdGhlIHNhbWVcblxuXHRcdGlmIChlcHMucG9pbnRzU2FtZShwMV8yLCBwMl8yKSkgLy8gaWYgdGhlIG5vbi1zZWxlY3RlZCBwb2ludHMgYXJlIHRoZSBzYW1lIHRvby4uLlxuXHRcdFx0cmV0dXJuIDA7IC8vIHRoZW4gdGhlIHNlZ21lbnRzIGFyZSBlcXVhbFxuXG5cdFx0aWYgKHAxX2lzU3RhcnQgIT09IHAyX2lzU3RhcnQpIC8vIGlmIG9uZSBpcyBhIHN0YXJ0IGFuZCB0aGUgb3RoZXIgaXNuJ3QuLi5cblx0XHRcdHJldHVybiBwMV9pc1N0YXJ0ID8gMSA6IC0xOyAvLyBmYXZvciB0aGUgb25lIHRoYXQgaXNuJ3QgdGhlIHN0YXJ0XG5cblx0XHQvLyBvdGhlcndpc2UsIHdlJ2xsIGhhdmUgdG8gY2FsY3VsYXRlIHdoaWNoIG9uZSBpcyBiZWxvdyB0aGUgb3RoZXIgbWFudWFsbHlcblx0XHRyZXR1cm4gZXBzLnBvaW50QWJvdmVPck9uTGluZShwMV8yLFxuXHRcdFx0cDJfaXNTdGFydCA/IHAyXzEgOiBwMl8yLCAvLyBvcmRlciBtYXR0ZXJzXG5cdFx0XHRwMl9pc1N0YXJ0ID8gcDJfMiA6IHAyXzFcblx0XHQpID8gMSA6IC0xO1xuXHR9XG5cblx0ZnVuY3Rpb24gZXZlbnRBZGQoZXYsIG90aGVyX3B0KXtcblx0XHRldmVudF9yb290Lmluc2VydEJlZm9yZShldiwgZnVuY3Rpb24oaGVyZSl7XG5cdFx0XHQvLyBzaG91bGQgZXYgYmUgaW5zZXJ0ZWQgYmVmb3JlIGhlcmU/XG5cdFx0XHR2YXIgY29tcCA9IGV2ZW50Q29tcGFyZShcblx0XHRcdFx0ZXYgIC5pc1N0YXJ0LCBldiAgLnB0LCAgICAgIG90aGVyX3B0LFxuXHRcdFx0XHRoZXJlLmlzU3RhcnQsIGhlcmUucHQsIGhlcmUub3RoZXIucHRcblx0XHRcdCk7XG5cdFx0XHRyZXR1cm4gY29tcCA8IDA7XG5cdFx0fSk7XG5cdH1cblxuXHRmdW5jdGlvbiBldmVudEFkZFNlZ21lbnRTdGFydChzZWcsIHByaW1hcnkpe1xuXHRcdHZhciBldl9zdGFydCA9IExpbmtlZExpc3Qubm9kZSh7XG5cdFx0XHRpc1N0YXJ0OiB0cnVlLFxuXHRcdFx0cHQ6IHNlZy5zdGFydCxcblx0XHRcdHNlZzogc2VnLFxuXHRcdFx0cHJpbWFyeTogcHJpbWFyeSxcblx0XHRcdG90aGVyOiBudWxsLFxuXHRcdFx0c3RhdHVzOiBudWxsXG5cdFx0fSk7XG5cdFx0ZXZlbnRBZGQoZXZfc3RhcnQsIHNlZy5lbmQpO1xuXHRcdHJldHVybiBldl9zdGFydDtcblx0fVxuXG5cdGZ1bmN0aW9uIGV2ZW50QWRkU2VnbWVudEVuZChldl9zdGFydCwgc2VnLCBwcmltYXJ5KXtcblx0XHR2YXIgZXZfZW5kID0gTGlua2VkTGlzdC5ub2RlKHtcblx0XHRcdGlzU3RhcnQ6IGZhbHNlLFxuXHRcdFx0cHQ6IHNlZy5lbmQsXG5cdFx0XHRzZWc6IHNlZyxcblx0XHRcdHByaW1hcnk6IHByaW1hcnksXG5cdFx0XHRvdGhlcjogZXZfc3RhcnQsXG5cdFx0XHRzdGF0dXM6IG51bGxcblx0XHR9KTtcblx0XHRldl9zdGFydC5vdGhlciA9IGV2X2VuZDtcblx0XHRldmVudEFkZChldl9lbmQsIGV2X3N0YXJ0LnB0KTtcblx0fVxuXG5cdGZ1bmN0aW9uIGV2ZW50QWRkU2VnbWVudChzZWcsIHByaW1hcnkpe1xuXHRcdHZhciBldl9zdGFydCA9IGV2ZW50QWRkU2VnbWVudFN0YXJ0KHNlZywgcHJpbWFyeSk7XG5cdFx0ZXZlbnRBZGRTZWdtZW50RW5kKGV2X3N0YXJ0LCBzZWcsIHByaW1hcnkpO1xuXHRcdHJldHVybiBldl9zdGFydDtcblx0fVxuXG5cdGZ1bmN0aW9uIGV2ZW50VXBkYXRlRW5kKGV2LCBlbmQpe1xuXHRcdC8vIHNsaWRlcyBhbiBlbmQgYmFja3dhcmRzXG5cdFx0Ly8gICAoc3RhcnQpLS0tLS0tLS0tLS0tKGVuZCkgICAgdG86XG5cdFx0Ly8gICAoc3RhcnQpLS0tKGVuZClcblxuXHRcdGlmIChidWlsZExvZylcblx0XHRcdGJ1aWxkTG9nLnNlZ21lbnRDaG9wKGV2LnNlZywgZW5kKTtcblxuXHRcdGV2Lm90aGVyLnJlbW92ZSgpO1xuXHRcdGV2LnNlZy5lbmQgPSBlbmQ7XG5cdFx0ZXYub3RoZXIucHQgPSBlbmQ7XG5cdFx0ZXZlbnRBZGQoZXYub3RoZXIsIGV2LnB0KTtcblx0fVxuXG5cdGZ1bmN0aW9uIGV2ZW50RGl2aWRlKGV2LCBwdCl7XG5cdFx0dmFyIG5zID0gc2VnbWVudENvcHkocHQsIGV2LnNlZy5lbmQsIGV2LnNlZyk7XG5cdFx0ZXZlbnRVcGRhdGVFbmQoZXYsIHB0KTtcblx0XHRyZXR1cm4gZXZlbnRBZGRTZWdtZW50KG5zLCBldi5wcmltYXJ5KTtcblx0fVxuXG5cdGZ1bmN0aW9uIGNhbGN1bGF0ZShwcmltYXJ5UG9seUludmVydGVkLCBzZWNvbmRhcnlQb2x5SW52ZXJ0ZWQpe1xuXHRcdC8vIGlmIHNlbGZJbnRlcnNlY3Rpb24gaXMgdHJ1ZSB0aGVuIHRoZXJlIGlzIG5vIHNlY29uZGFyeSBwb2x5Z29uLCBzbyB0aGF0IGlzbid0IHVzZWRcblxuXHRcdC8vXG5cdFx0Ly8gc3RhdHVzIGxvZ2ljXG5cdFx0Ly9cblxuXHRcdHZhciBzdGF0dXNfcm9vdCA9IExpbmtlZExpc3QuY3JlYXRlKCk7XG5cblx0XHRmdW5jdGlvbiBzdGF0dXNDb21wYXJlKGV2MSwgZXYyKXtcblx0XHRcdHZhciBhMSA9IGV2MS5zZWcuc3RhcnQ7XG5cdFx0XHR2YXIgYTIgPSBldjEuc2VnLmVuZDtcblx0XHRcdHZhciBiMSA9IGV2Mi5zZWcuc3RhcnQ7XG5cdFx0XHR2YXIgYjIgPSBldjIuc2VnLmVuZDtcblxuXHRcdFx0aWYgKGVwcy5wb2ludHNDb2xsaW5lYXIoYTEsIGIxLCBiMikpe1xuXHRcdFx0XHRpZiAoZXBzLnBvaW50c0NvbGxpbmVhcihhMiwgYjEsIGIyKSlcblx0XHRcdFx0XHRyZXR1cm4gMTsvL2V2ZW50Q29tcGFyZSh0cnVlLCBhMSwgYTIsIHRydWUsIGIxLCBiMik7XG5cdFx0XHRcdHJldHVybiBlcHMucG9pbnRBYm92ZU9yT25MaW5lKGEyLCBiMSwgYjIpID8gMSA6IC0xO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGVwcy5wb2ludEFib3ZlT3JPbkxpbmUoYTEsIGIxLCBiMikgPyAxIDogLTE7XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gc3RhdHVzRmluZFN1cnJvdW5kaW5nKGV2KXtcblx0XHRcdHJldHVybiBzdGF0dXNfcm9vdC5maW5kVHJhbnNpdGlvbihmdW5jdGlvbihoZXJlKXtcblx0XHRcdFx0dmFyIGNvbXAgPSBzdGF0dXNDb21wYXJlKGV2LCBoZXJlLmV2KTtcblx0XHRcdFx0cmV0dXJuIGNvbXAgPiAwO1xuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gY2hlY2tJbnRlcnNlY3Rpb24oZXYxLCBldjIpe1xuXHRcdFx0Ly8gcmV0dXJucyB0aGUgc2VnbWVudCBlcXVhbCB0byBldjEsIG9yIGZhbHNlIGlmIG5vdGhpbmcgZXF1YWxcblxuXHRcdFx0dmFyIHNlZzEgPSBldjEuc2VnO1xuXHRcdFx0dmFyIHNlZzIgPSBldjIuc2VnO1xuXHRcdFx0dmFyIGExID0gc2VnMS5zdGFydDtcblx0XHRcdHZhciBhMiA9IHNlZzEuZW5kO1xuXHRcdFx0dmFyIGIxID0gc2VnMi5zdGFydDtcblx0XHRcdHZhciBiMiA9IHNlZzIuZW5kO1xuXG5cdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdGJ1aWxkTG9nLmNoZWNrSW50ZXJzZWN0aW9uKHNlZzEsIHNlZzIpO1xuXG5cdFx0XHR2YXIgaSA9IGVwcy5saW5lc0ludGVyc2VjdChhMSwgYTIsIGIxLCBiMik7XG5cblx0XHRcdGlmIChpID09PSBmYWxzZSl7XG5cdFx0XHRcdC8vIHNlZ21lbnRzIGFyZSBwYXJhbGxlbCBvciBjb2luY2lkZW50XG5cblx0XHRcdFx0Ly8gaWYgcG9pbnRzIGFyZW4ndCBjb2xsaW5lYXIsIHRoZW4gdGhlIHNlZ21lbnRzIGFyZSBwYXJhbGxlbCwgc28gbm8gaW50ZXJzZWN0aW9uc1xuXHRcdFx0XHRpZiAoIWVwcy5wb2ludHNDb2xsaW5lYXIoYTEsIGEyLCBiMSkpXG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHQvLyBvdGhlcndpc2UsIHNlZ21lbnRzIGFyZSBvbiB0b3Agb2YgZWFjaCBvdGhlciBzb21laG93IChha2EgY29pbmNpZGVudClcblxuXHRcdFx0XHRpZiAoZXBzLnBvaW50c1NhbWUoYTEsIGIyKSB8fCBlcHMucG9pbnRzU2FtZShhMiwgYjEpKVxuXHRcdFx0XHRcdHJldHVybiBmYWxzZTsgLy8gc2VnbWVudHMgdG91Y2ggYXQgZW5kcG9pbnRzLi4uIG5vIGludGVyc2VjdGlvblxuXG5cdFx0XHRcdHZhciBhMV9lcXVfYjEgPSBlcHMucG9pbnRzU2FtZShhMSwgYjEpO1xuXHRcdFx0XHR2YXIgYTJfZXF1X2IyID0gZXBzLnBvaW50c1NhbWUoYTIsIGIyKTtcblxuXHRcdFx0XHRpZiAoYTFfZXF1X2IxICYmIGEyX2VxdV9iMilcblx0XHRcdFx0XHRyZXR1cm4gZXYyOyAvLyBzZWdtZW50cyBhcmUgZXhhY3RseSBlcXVhbFxuXG5cdFx0XHRcdHZhciBhMV9iZXR3ZWVuID0gIWExX2VxdV9iMSAmJiBlcHMucG9pbnRCZXR3ZWVuKGExLCBiMSwgYjIpO1xuXHRcdFx0XHR2YXIgYTJfYmV0d2VlbiA9ICFhMl9lcXVfYjIgJiYgZXBzLnBvaW50QmV0d2VlbihhMiwgYjEsIGIyKTtcblxuXHRcdFx0XHQvLyBoYW5keSBmb3IgZGVidWdnaW5nOlxuXHRcdFx0XHQvLyBidWlsZExvZy5sb2coe1xuXHRcdFx0XHQvL1x0YTFfZXF1X2IxOiBhMV9lcXVfYjEsXG5cdFx0XHRcdC8vXHRhMl9lcXVfYjI6IGEyX2VxdV9iMixcblx0XHRcdFx0Ly9cdGExX2JldHdlZW46IGExX2JldHdlZW4sXG5cdFx0XHRcdC8vXHRhMl9iZXR3ZWVuOiBhMl9iZXR3ZWVuXG5cdFx0XHRcdC8vIH0pO1xuXG5cdFx0XHRcdGlmIChhMV9lcXVfYjEpe1xuXHRcdFx0XHRcdGlmIChhMl9iZXR3ZWVuKXtcblx0XHRcdFx0XHRcdC8vICAoYTEpLS0tKGEyKVxuXHRcdFx0XHRcdFx0Ly8gIChiMSktLS0tLS0tLS0tKGIyKVxuXHRcdFx0XHRcdFx0ZXZlbnREaXZpZGUoZXYyLCBhMik7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2V7XG5cdFx0XHRcdFx0XHQvLyAgKGExKS0tLS0tLS0tLS0oYTIpXG5cdFx0XHRcdFx0XHQvLyAgKGIxKS0tLShiMilcblx0XHRcdFx0XHRcdGV2ZW50RGl2aWRlKGV2MSwgYjIpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gZXYyO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKGExX2JldHdlZW4pe1xuXHRcdFx0XHRcdGlmICghYTJfZXF1X2IyKXtcblx0XHRcdFx0XHRcdC8vIG1ha2UgYTIgZXF1YWwgdG8gYjJcblx0XHRcdFx0XHRcdGlmIChhMl9iZXR3ZWVuKXtcblx0XHRcdFx0XHRcdFx0Ly8gICAgICAgICAoYTEpLS0tKGEyKVxuXHRcdFx0XHRcdFx0XHQvLyAgKGIxKS0tLS0tLS0tLS0tLS0tLS0tKGIyKVxuXHRcdFx0XHRcdFx0XHRldmVudERpdmlkZShldjIsIGEyKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGVsc2V7XG5cdFx0XHRcdFx0XHRcdC8vICAgICAgICAgKGExKS0tLS0tLS0tLS0oYTIpXG5cdFx0XHRcdFx0XHRcdC8vICAoYjEpLS0tLS0tLS0tLShiMilcblx0XHRcdFx0XHRcdFx0ZXZlbnREaXZpZGUoZXYxLCBiMik7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gICAgICAgICAoYTEpLS0tKGEyKVxuXHRcdFx0XHRcdC8vICAoYjEpLS0tLS0tLS0tLShiMilcblx0XHRcdFx0XHRldmVudERpdmlkZShldjIsIGExKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0ZWxzZXtcblx0XHRcdFx0Ly8gb3RoZXJ3aXNlLCBsaW5lcyBpbnRlcnNlY3QgYXQgaS5wdCwgd2hpY2ggbWF5IG9yIG1heSBub3QgYmUgYmV0d2VlbiB0aGUgZW5kcG9pbnRzXG5cblx0XHRcdFx0Ly8gaXMgQSBkaXZpZGVkIGJldHdlZW4gaXRzIGVuZHBvaW50cz8gKGV4Y2x1c2l2ZSlcblx0XHRcdFx0aWYgKGkuYWxvbmdBID09PSAwKXtcblx0XHRcdFx0XHRpZiAoaS5hbG9uZ0IgPT09IC0xKSAvLyB5ZXMsIGF0IGV4YWN0bHkgYjFcblx0XHRcdFx0XHRcdGV2ZW50RGl2aWRlKGV2MSwgYjEpO1xuXHRcdFx0XHRcdGVsc2UgaWYgKGkuYWxvbmdCID09PSAwKSAvLyB5ZXMsIHNvbWV3aGVyZSBiZXR3ZWVuIEIncyBlbmRwb2ludHNcblx0XHRcdFx0XHRcdGV2ZW50RGl2aWRlKGV2MSwgaS5wdCk7XG5cdFx0XHRcdFx0ZWxzZSBpZiAoaS5hbG9uZ0IgPT09IDEpIC8vIHllcywgYXQgZXhhY3RseSBiMlxuXHRcdFx0XHRcdFx0ZXZlbnREaXZpZGUoZXYxLCBiMik7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBpcyBCIGRpdmlkZWQgYmV0d2VlbiBpdHMgZW5kcG9pbnRzPyAoZXhjbHVzaXZlKVxuXHRcdFx0XHRpZiAoaS5hbG9uZ0IgPT09IDApe1xuXHRcdFx0XHRcdGlmIChpLmFsb25nQSA9PT0gLTEpIC8vIHllcywgYXQgZXhhY3RseSBhMVxuXHRcdFx0XHRcdFx0ZXZlbnREaXZpZGUoZXYyLCBhMSk7XG5cdFx0XHRcdFx0ZWxzZSBpZiAoaS5hbG9uZ0EgPT09IDApIC8vIHllcywgc29tZXdoZXJlIGJldHdlZW4gQSdzIGVuZHBvaW50cyAoZXhjbHVzaXZlKVxuXHRcdFx0XHRcdFx0ZXZlbnREaXZpZGUoZXYyLCBpLnB0KTtcblx0XHRcdFx0XHRlbHNlIGlmIChpLmFsb25nQSA9PT0gMSkgLy8geWVzLCBhdCBleGFjdGx5IGEyXG5cdFx0XHRcdFx0XHRldmVudERpdmlkZShldjIsIGEyKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdC8vXG5cdFx0Ly8gbWFpbiBldmVudCBsb29wXG5cdFx0Ly9cblx0XHR2YXIgc2VnbWVudHMgPSBbXTtcblx0XHR3aGlsZSAoIWV2ZW50X3Jvb3QuaXNFbXB0eSgpKXtcblx0XHRcdHZhciBldiA9IGV2ZW50X3Jvb3QuZ2V0SGVhZCgpO1xuXG5cdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdGJ1aWxkTG9nLnZlcnQoZXYucHRbMF0pO1xuXG5cdFx0XHRpZiAoZXYuaXNTdGFydCl7XG5cblx0XHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRcdGJ1aWxkTG9nLnNlZ21lbnROZXcoZXYuc2VnLCBldi5wcmltYXJ5KTtcblxuXHRcdFx0XHR2YXIgc3Vycm91bmRpbmcgPSBzdGF0dXNGaW5kU3Vycm91bmRpbmcoZXYpO1xuXHRcdFx0XHR2YXIgYWJvdmUgPSBzdXJyb3VuZGluZy5iZWZvcmUgPyBzdXJyb3VuZGluZy5iZWZvcmUuZXYgOiBudWxsO1xuXHRcdFx0XHR2YXIgYmVsb3cgPSBzdXJyb3VuZGluZy5hZnRlciA/IHN1cnJvdW5kaW5nLmFmdGVyLmV2IDogbnVsbDtcblxuXHRcdFx0XHRpZiAoYnVpbGRMb2cpe1xuXHRcdFx0XHRcdGJ1aWxkTG9nLnRlbXBTdGF0dXMoXG5cdFx0XHRcdFx0XHRldi5zZWcsXG5cdFx0XHRcdFx0XHRhYm92ZSA/IGFib3ZlLnNlZyA6IGZhbHNlLFxuXHRcdFx0XHRcdFx0YmVsb3cgPyBiZWxvdy5zZWcgOiBmYWxzZVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRmdW5jdGlvbiBjaGVja0JvdGhJbnRlcnNlY3Rpb25zKCl7XG5cdFx0XHRcdFx0aWYgKGFib3ZlKXtcblx0XHRcdFx0XHRcdHZhciBldmUgPSBjaGVja0ludGVyc2VjdGlvbihldiwgYWJvdmUpO1xuXHRcdFx0XHRcdFx0aWYgKGV2ZSlcblx0XHRcdFx0XHRcdFx0cmV0dXJuIGV2ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKGJlbG93KVxuXHRcdFx0XHRcdFx0cmV0dXJuIGNoZWNrSW50ZXJzZWN0aW9uKGV2LCBiZWxvdyk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIGV2ZSA9IGNoZWNrQm90aEludGVyc2VjdGlvbnMoKTtcblx0XHRcdFx0aWYgKGV2ZSl7XG5cdFx0XHRcdFx0Ly8gZXYgYW5kIGV2ZSBhcmUgZXF1YWxcblx0XHRcdFx0XHQvLyB3ZSdsbCBrZWVwIGV2ZSBhbmQgdGhyb3cgYXdheSBldlxuXG5cdFx0XHRcdFx0Ly8gbWVyZ2UgZXYuc2VnJ3MgZmlsbCBpbmZvcm1hdGlvbiBpbnRvIGV2ZS5zZWdcblxuXHRcdFx0XHRcdGlmIChzZWxmSW50ZXJzZWN0aW9uKXtcblx0XHRcdFx0XHRcdHZhciB0b2dnbGU7IC8vIGFyZSB3ZSBhIHRvZ2dsaW5nIGVkZ2U/XG5cdFx0XHRcdFx0XHRpZiAoZXYuc2VnLm15RmlsbC5iZWxvdyA9PT0gbnVsbClcblx0XHRcdFx0XHRcdFx0dG9nZ2xlID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdFx0dG9nZ2xlID0gZXYuc2VnLm15RmlsbC5hYm92ZSAhPT0gZXYuc2VnLm15RmlsbC5iZWxvdztcblxuXHRcdFx0XHRcdFx0Ly8gbWVyZ2UgdHdvIHNlZ21lbnRzIHRoYXQgYmVsb25nIHRvIHRoZSBzYW1lIHBvbHlnb25cblx0XHRcdFx0XHRcdC8vIHRoaW5rIG9mIHRoaXMgYXMgc2FuZHdpY2hpbmcgdHdvIHNlZ21lbnRzIHRvZ2V0aGVyLCB3aGVyZSBgZXZlLnNlZ2AgaXNcblx0XHRcdFx0XHRcdC8vIHRoZSBib3R0b20gLS0gdGhpcyB3aWxsIGNhdXNlIHRoZSBhYm92ZSBmaWxsIGZsYWcgdG8gdG9nZ2xlXG5cdFx0XHRcdFx0XHRpZiAodG9nZ2xlKVxuXHRcdFx0XHRcdFx0XHRldmUuc2VnLm15RmlsbC5hYm92ZSA9ICFldmUuc2VnLm15RmlsbC5hYm92ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZXtcblx0XHRcdFx0XHRcdC8vIG1lcmdlIHR3byBzZWdtZW50cyB0aGF0IGJlbG9uZyB0byBkaWZmZXJlbnQgcG9seWdvbnNcblx0XHRcdFx0XHRcdC8vIGVhY2ggc2VnbWVudCBoYXMgZGlzdGluY3Qga25vd2xlZGdlLCBzbyBubyBzcGVjaWFsIGxvZ2ljIGlzIG5lZWRlZFxuXHRcdFx0XHRcdFx0Ly8gbm90ZSB0aGF0IHRoaXMgY2FuIG9ubHkgaGFwcGVuIG9uY2UgcGVyIHNlZ21lbnQgaW4gdGhpcyBwaGFzZSwgYmVjYXVzZSB3ZVxuXHRcdFx0XHRcdFx0Ly8gYXJlIGd1YXJhbnRlZWQgdGhhdCBhbGwgc2VsZi1pbnRlcnNlY3Rpb25zIGFyZSBnb25lXG5cdFx0XHRcdFx0XHRldmUuc2VnLm90aGVyRmlsbCA9IGV2LnNlZy5teUZpbGw7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRcdFx0YnVpbGRMb2cuc2VnbWVudFVwZGF0ZShldmUuc2VnKTtcblxuXHRcdFx0XHRcdGV2Lm90aGVyLnJlbW92ZSgpO1xuXHRcdFx0XHRcdGV2LnJlbW92ZSgpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGV2ZW50X3Jvb3QuZ2V0SGVhZCgpICE9PSBldil7XG5cdFx0XHRcdFx0Ly8gc29tZXRoaW5nIHdhcyBpbnNlcnRlZCBiZWZvcmUgdXMgaW4gdGhlIGV2ZW50IHF1ZXVlLCBzbyBsb29wIGJhY2sgYXJvdW5kIGFuZFxuXHRcdFx0XHRcdC8vIHByb2Nlc3MgaXQgYmVmb3JlIGNvbnRpbnVpbmdcblx0XHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0XHRidWlsZExvZy5yZXdpbmQoZXYuc2VnKTtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vXG5cdFx0XHRcdC8vIGNhbGN1bGF0ZSBmaWxsIGZsYWdzXG5cdFx0XHRcdC8vXG5cdFx0XHRcdGlmIChzZWxmSW50ZXJzZWN0aW9uKXtcblx0XHRcdFx0XHR2YXIgdG9nZ2xlOyAvLyBhcmUgd2UgYSB0b2dnbGluZyBlZGdlP1xuXHRcdFx0XHRcdGlmIChldi5zZWcubXlGaWxsLmJlbG93ID09PSBudWxsKSAvLyBpZiB3ZSBhcmUgYSBuZXcgc2VnbWVudC4uLlxuXHRcdFx0XHRcdFx0dG9nZ2xlID0gdHJ1ZTsgLy8gdGhlbiB3ZSB0b2dnbGVcblx0XHRcdFx0XHRlbHNlIC8vIHdlIGFyZSBhIHNlZ21lbnQgdGhhdCBoYXMgcHJldmlvdXMga25vd2xlZGdlIGZyb20gYSBkaXZpc2lvblxuXHRcdFx0XHRcdFx0dG9nZ2xlID0gZXYuc2VnLm15RmlsbC5hYm92ZSAhPT0gZXYuc2VnLm15RmlsbC5iZWxvdzsgLy8gY2FsY3VsYXRlIHRvZ2dsZVxuXG5cdFx0XHRcdFx0Ly8gbmV4dCwgY2FsY3VsYXRlIHdoZXRoZXIgd2UgYXJlIGZpbGxlZCBiZWxvdyB1c1xuXHRcdFx0XHRcdGlmICghYmVsb3cpeyAvLyBpZiBub3RoaW5nIGlzIGJlbG93IHVzLi4uXG5cdFx0XHRcdFx0XHQvLyB3ZSBhcmUgZmlsbGVkIGJlbG93IHVzIGlmIHRoZSBwb2x5Z29uIGlzIGludmVydGVkXG5cdFx0XHRcdFx0XHRldi5zZWcubXlGaWxsLmJlbG93ID0gcHJpbWFyeVBvbHlJbnZlcnRlZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZXtcblx0XHRcdFx0XHRcdC8vIG90aGVyd2lzZSwgd2Uga25vdyB0aGUgYW5zd2VyIC0tIGl0J3MgdGhlIHNhbWUgaWYgd2hhdGV2ZXIgaXMgYmVsb3dcblx0XHRcdFx0XHRcdC8vIHVzIGlzIGZpbGxlZCBhYm92ZSBpdFxuXHRcdFx0XHRcdFx0ZXYuc2VnLm15RmlsbC5iZWxvdyA9IGJlbG93LnNlZy5teUZpbGwuYWJvdmU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gc2luY2Ugbm93IHdlIGtub3cgaWYgd2UncmUgZmlsbGVkIGJlbG93IHVzLCB3ZSBjYW4gY2FsY3VsYXRlIHdoZXRoZXJcblx0XHRcdFx0XHQvLyB3ZSdyZSBmaWxsZWQgYWJvdmUgdXMgYnkgYXBwbHlpbmcgdG9nZ2xlIHRvIHdoYXRldmVyIGlzIGJlbG93IHVzXG5cdFx0XHRcdFx0aWYgKHRvZ2dsZSlcblx0XHRcdFx0XHRcdGV2LnNlZy5teUZpbGwuYWJvdmUgPSAhZXYuc2VnLm15RmlsbC5iZWxvdztcblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHRldi5zZWcubXlGaWxsLmFib3ZlID0gZXYuc2VnLm15RmlsbC5iZWxvdztcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNle1xuXHRcdFx0XHRcdC8vIG5vdyB3ZSBmaWxsIGluIGFueSBtaXNzaW5nIHRyYW5zaXRpb24gaW5mb3JtYXRpb24sIHNpbmNlIHdlIGFyZSBhbGwta25vd2luZ1xuXHRcdFx0XHRcdC8vIGF0IHRoaXMgcG9pbnRcblxuXHRcdFx0XHRcdGlmIChldi5zZWcub3RoZXJGaWxsID09PSBudWxsKXtcblx0XHRcdFx0XHRcdC8vIGlmIHdlIGRvbid0IGhhdmUgb3RoZXIgaW5mb3JtYXRpb24sIHRoZW4gd2UgbmVlZCB0byBmaWd1cmUgb3V0IGlmIHdlJ3JlXG5cdFx0XHRcdFx0XHQvLyBpbnNpZGUgdGhlIG90aGVyIHBvbHlnb25cblx0XHRcdFx0XHRcdHZhciBpbnNpZGU7XG5cdFx0XHRcdFx0XHRpZiAoIWJlbG93KXtcblx0XHRcdFx0XHRcdFx0Ly8gaWYgbm90aGluZyBpcyBiZWxvdyB1cywgdGhlbiB3ZSdyZSBpbnNpZGUgaWYgdGhlIG90aGVyIHBvbHlnb24gaXNcblx0XHRcdFx0XHRcdFx0Ly8gaW52ZXJ0ZWRcblx0XHRcdFx0XHRcdFx0aW5zaWRlID1cblx0XHRcdFx0XHRcdFx0XHRldi5wcmltYXJ5ID8gc2Vjb25kYXJ5UG9seUludmVydGVkIDogcHJpbWFyeVBvbHlJbnZlcnRlZDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGVsc2V7IC8vIG90aGVyd2lzZSwgc29tZXRoaW5nIGlzIGJlbG93IHVzXG5cdFx0XHRcdFx0XHRcdC8vIHNvIGNvcHkgdGhlIGJlbG93IHNlZ21lbnQncyBvdGhlciBwb2x5Z29uJ3MgYWJvdmVcblx0XHRcdFx0XHRcdFx0aWYgKGV2LnByaW1hcnkgPT09IGJlbG93LnByaW1hcnkpXG5cdFx0XHRcdFx0XHRcdFx0aW5zaWRlID0gYmVsb3cuc2VnLm90aGVyRmlsbC5hYm92ZTtcblx0XHRcdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0XHRcdGluc2lkZSA9IGJlbG93LnNlZy5teUZpbGwuYWJvdmU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRldi5zZWcub3RoZXJGaWxsID0ge1xuXHRcdFx0XHRcdFx0XHRhYm92ZTogaW5zaWRlLFxuXHRcdFx0XHRcdFx0XHRiZWxvdzogaW5zaWRlXG5cdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChidWlsZExvZyl7XG5cdFx0XHRcdFx0YnVpbGRMb2cuc3RhdHVzKFxuXHRcdFx0XHRcdFx0ZXYuc2VnLFxuXHRcdFx0XHRcdFx0YWJvdmUgPyBhYm92ZS5zZWcgOiBmYWxzZSxcblx0XHRcdFx0XHRcdGJlbG93ID8gYmVsb3cuc2VnIDogZmFsc2Vcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gaW5zZXJ0IHRoZSBzdGF0dXMgYW5kIHJlbWVtYmVyIGl0IGZvciBsYXRlciByZW1vdmFsXG5cdFx0XHRcdGV2Lm90aGVyLnN0YXR1cyA9IHN1cnJvdW5kaW5nLmluc2VydChMaW5rZWRMaXN0Lm5vZGUoeyBldjogZXYgfSkpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZXtcblx0XHRcdFx0dmFyIHN0ID0gZXYuc3RhdHVzO1xuXG5cdFx0XHRcdGlmIChzdCA9PT0gbnVsbCl7XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCdQb2x5Qm9vbDogWmVyby1sZW5ndGggc2VnbWVudCBkZXRlY3RlZDsgeW91ciBlcHNpbG9uIGlzICcgK1xuXHRcdFx0XHRcdFx0J3Byb2JhYmx5IHRvbyBzbWFsbCBvciB0b28gbGFyZ2UnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIHJlbW92aW5nIHRoZSBzdGF0dXMgd2lsbCBjcmVhdGUgdHdvIG5ldyBhZGphY2VudCBlZGdlcywgc28gd2UnbGwgbmVlZCB0byBjaGVja1xuXHRcdFx0XHQvLyBmb3IgdGhvc2Vcblx0XHRcdFx0aWYgKHN0YXR1c19yb290LmV4aXN0cyhzdC5wcmV2KSAmJiBzdGF0dXNfcm9vdC5leGlzdHMoc3QubmV4dCkpXG5cdFx0XHRcdFx0Y2hlY2tJbnRlcnNlY3Rpb24oc3QucHJldi5ldiwgc3QubmV4dC5ldik7XG5cblx0XHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRcdGJ1aWxkTG9nLnN0YXR1c1JlbW92ZShzdC5ldi5zZWcpO1xuXG5cdFx0XHRcdC8vIHJlbW92ZSB0aGUgc3RhdHVzXG5cdFx0XHRcdHN0LnJlbW92ZSgpO1xuXG5cdFx0XHRcdC8vIGlmIHdlJ3ZlIHJlYWNoZWQgdGhpcyBwb2ludCwgd2UndmUgY2FsY3VsYXRlZCBldmVyeXRoaW5nIHRoZXJlIGlzIHRvIGtub3csIHNvXG5cdFx0XHRcdC8vIHNhdmUgdGhlIHNlZ21lbnQgZm9yIHJlcG9ydGluZ1xuXHRcdFx0XHRpZiAoIWV2LnByaW1hcnkpe1xuXHRcdFx0XHRcdC8vIG1ha2Ugc3VyZSBgc2VnLm15RmlsbGAgYWN0dWFsbHkgcG9pbnRzIHRvIHRoZSBwcmltYXJ5IHBvbHlnb24gdGhvdWdoXG5cdFx0XHRcdFx0dmFyIHMgPSBldi5zZWcubXlGaWxsO1xuXHRcdFx0XHRcdGV2LnNlZy5teUZpbGwgPSBldi5zZWcub3RoZXJGaWxsO1xuXHRcdFx0XHRcdGV2LnNlZy5vdGhlckZpbGwgPSBzO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHNlZ21lbnRzLnB1c2goZXYuc2VnKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gcmVtb3ZlIHRoZSBldmVudCBhbmQgY29udGludWVcblx0XHRcdGV2ZW50X3Jvb3QuZ2V0SGVhZCgpLnJlbW92ZSgpO1xuXHRcdH1cblxuXHRcdGlmIChidWlsZExvZylcblx0XHRcdGJ1aWxkTG9nLmRvbmUoKTtcblxuXHRcdHJldHVybiBzZWdtZW50cztcblx0fVxuXG5cdC8vIHJldHVybiB0aGUgYXBwcm9wcmlhdGUgQVBJIGRlcGVuZGluZyBvbiB3aGF0IHdlJ3JlIGRvaW5nXG5cdGlmICghc2VsZkludGVyc2VjdGlvbil7XG5cdFx0Ly8gcGVyZm9ybWluZyBjb21iaW5hdGlvbiBvZiBwb2x5Z29ucywgc28gb25seSBkZWFsIHdpdGggYWxyZWFkeS1wcm9jZXNzZWQgc2VnbWVudHNcblx0XHRyZXR1cm4ge1xuXHRcdFx0Y2FsY3VsYXRlOiBmdW5jdGlvbihzZWdtZW50czEsIGludmVydGVkMSwgc2VnbWVudHMyLCBpbnZlcnRlZDIpe1xuXHRcdFx0XHQvLyBzZWdtZW50c1ggY29tZSBmcm9tIHRoZSBzZWxmLWludGVyc2VjdGlvbiBBUEksIG9yIHRoaXMgQVBJXG5cdFx0XHRcdC8vIGludmVydGVkWCBpcyB3aGV0aGVyIHdlIHRyZWF0IHRoYXQgbGlzdCBvZiBzZWdtZW50cyBhcyBhbiBpbnZlcnRlZCBwb2x5Z29uIG9yIG5vdFxuXHRcdFx0XHQvLyByZXR1cm5zIHNlZ21lbnRzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGZ1cnRoZXIgb3BlcmF0aW9uc1xuXHRcdFx0XHRzZWdtZW50czEuZm9yRWFjaChmdW5jdGlvbihzZWcpe1xuXHRcdFx0XHRcdGV2ZW50QWRkU2VnbWVudChzZWdtZW50Q29weShzZWcuc3RhcnQsIHNlZy5lbmQsIHNlZyksIHRydWUpO1xuXHRcdFx0XHR9KTtcblx0XHRcdFx0c2VnbWVudHMyLmZvckVhY2goZnVuY3Rpb24oc2VnKXtcblx0XHRcdFx0XHRldmVudEFkZFNlZ21lbnQoc2VnbWVudENvcHkoc2VnLnN0YXJ0LCBzZWcuZW5kLCBzZWcpLCBmYWxzZSk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRyZXR1cm4gY2FsY3VsYXRlKGludmVydGVkMSwgaW52ZXJ0ZWQyKTtcblx0XHRcdH1cblx0XHR9O1xuXHR9XG5cblx0Ly8gb3RoZXJ3aXNlLCBwZXJmb3JtaW5nIHNlbGYtaW50ZXJzZWN0aW9uLCBzbyBkZWFsIHdpdGggcmVnaW9uc1xuXHRyZXR1cm4ge1xuXHRcdGFkZFJlZ2lvbjogZnVuY3Rpb24ocmVnaW9uKXtcblx0XHRcdC8vIHJlZ2lvbnMgYXJlIGEgbGlzdCBvZiBwb2ludHM6XG5cdFx0XHQvLyAgWyBbMCwgMF0sIFsxMDAsIDBdLCBbNTAsIDEwMF0gXVxuXHRcdFx0Ly8geW91IGNhbiBhZGQgbXVsdGlwbGUgcmVnaW9ucyBiZWZvcmUgcnVubmluZyBjYWxjdWxhdGVcblx0XHRcdHZhciBwdDE7XG5cdFx0XHR2YXIgcHQyID0gcmVnaW9uW3JlZ2lvbi5sZW5ndGggLSAxXTtcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcmVnaW9uLmxlbmd0aDsgaSsrKXtcblx0XHRcdFx0cHQxID0gcHQyO1xuXHRcdFx0XHRwdDIgPSByZWdpb25baV07XG5cblx0XHRcdFx0dmFyIGZvcndhcmQgPSBlcHMucG9pbnRzQ29tcGFyZShwdDEsIHB0Mik7XG5cdFx0XHRcdGlmIChmb3J3YXJkID09PSAwKSAvLyBwb2ludHMgYXJlIGVxdWFsLCBzbyB3ZSBoYXZlIGEgemVyby1sZW5ndGggc2VnbWVudFxuXHRcdFx0XHRcdGNvbnRpbnVlOyAvLyBqdXN0IHNraXAgaXRcblxuXHRcdFx0XHRldmVudEFkZFNlZ21lbnQoXG5cdFx0XHRcdFx0c2VnbWVudE5ldyhcblx0XHRcdFx0XHRcdGZvcndhcmQgPCAwID8gcHQxIDogcHQyLFxuXHRcdFx0XHRcdFx0Zm9yd2FyZCA8IDAgPyBwdDIgOiBwdDFcblx0XHRcdFx0XHQpLFxuXHRcdFx0XHRcdHRydWVcblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdGNhbGN1bGF0ZTogZnVuY3Rpb24oaW52ZXJ0ZWQpe1xuXHRcdFx0Ly8gaXMgdGhlIHBvbHlnb24gaW52ZXJ0ZWQ/XG5cdFx0XHQvLyByZXR1cm5zIHNlZ21lbnRzXG5cdFx0XHRyZXR1cm4gY2FsY3VsYXRlKGludmVydGVkLCBmYWxzZSk7XG5cdFx0fVxuXHR9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEludGVyc2VjdGVyO1xuXG59LHtcIi4vbGlua2VkLWxpc3RcIjo0Nzh9XSw0Nzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gKGMpIENvcHlyaWdodCAyMDE2LCBTZWFuIENvbm5lbGx5IChAdm9pZHFrKSwgaHR0cDovL3N5bnRoZXRpLmNjXG4vLyBNSVQgTGljZW5zZVxuLy8gUHJvamVjdCBIb21lOiBodHRwczovL2dpdGh1Yi5jb20vdm9pZHFrL3BvbHlib29sanNcblxuLy9cbi8vIHNpbXBsZSBsaW5rZWQgbGlzdCBpbXBsZW1lbnRhdGlvbiB0aGF0IGFsbG93cyB5b3UgdG8gdHJhdmVyc2UgZG93biBub2RlcyBhbmQgc2F2ZSBwb3NpdGlvbnNcbi8vXG5cbnZhciBMaW5rZWRMaXN0ID0ge1xuXHRjcmVhdGU6IGZ1bmN0aW9uKCl7XG5cdFx0dmFyIG15ID0ge1xuXHRcdFx0cm9vdDogeyByb290OiB0cnVlLCBuZXh0OiBudWxsIH0sXG5cdFx0XHRleGlzdHM6IGZ1bmN0aW9uKG5vZGUpe1xuXHRcdFx0XHRpZiAobm9kZSA9PT0gbnVsbCB8fCBub2RlID09PSBteS5yb290KVxuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9LFxuXHRcdFx0aXNFbXB0eTogZnVuY3Rpb24oKXtcblx0XHRcdFx0cmV0dXJuIG15LnJvb3QubmV4dCA9PT0gbnVsbDtcblx0XHRcdH0sXG5cdFx0XHRnZXRIZWFkOiBmdW5jdGlvbigpe1xuXHRcdFx0XHRyZXR1cm4gbXkucm9vdC5uZXh0O1xuXHRcdFx0fSxcblx0XHRcdGluc2VydEJlZm9yZTogZnVuY3Rpb24obm9kZSwgY2hlY2spe1xuXHRcdFx0XHR2YXIgbGFzdCA9IG15LnJvb3Q7XG5cdFx0XHRcdHZhciBoZXJlID0gbXkucm9vdC5uZXh0O1xuXHRcdFx0XHR3aGlsZSAoaGVyZSAhPT0gbnVsbCl7XG5cdFx0XHRcdFx0aWYgKGNoZWNrKGhlcmUpKXtcblx0XHRcdFx0XHRcdG5vZGUucHJldiA9IGhlcmUucHJldjtcblx0XHRcdFx0XHRcdG5vZGUubmV4dCA9IGhlcmU7XG5cdFx0XHRcdFx0XHRoZXJlLnByZXYubmV4dCA9IG5vZGU7XG5cdFx0XHRcdFx0XHRoZXJlLnByZXYgPSBub2RlO1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRsYXN0ID0gaGVyZTtcblx0XHRcdFx0XHRoZXJlID0gaGVyZS5uZXh0O1xuXHRcdFx0XHR9XG5cdFx0XHRcdGxhc3QubmV4dCA9IG5vZGU7XG5cdFx0XHRcdG5vZGUucHJldiA9IGxhc3Q7XG5cdFx0XHRcdG5vZGUubmV4dCA9IG51bGw7XG5cdFx0XHR9LFxuXHRcdFx0ZmluZFRyYW5zaXRpb246IGZ1bmN0aW9uKGNoZWNrKXtcblx0XHRcdFx0dmFyIHByZXYgPSBteS5yb290O1xuXHRcdFx0XHR2YXIgaGVyZSA9IG15LnJvb3QubmV4dDtcblx0XHRcdFx0d2hpbGUgKGhlcmUgIT09IG51bGwpe1xuXHRcdFx0XHRcdGlmIChjaGVjayhoZXJlKSlcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdHByZXYgPSBoZXJlO1xuXHRcdFx0XHRcdGhlcmUgPSBoZXJlLm5leHQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRiZWZvcmU6IHByZXYgPT09IG15LnJvb3QgPyBudWxsIDogcHJldixcblx0XHRcdFx0XHRhZnRlcjogaGVyZSxcblx0XHRcdFx0XHRpbnNlcnQ6IGZ1bmN0aW9uKG5vZGUpe1xuXHRcdFx0XHRcdFx0bm9kZS5wcmV2ID0gcHJldjtcblx0XHRcdFx0XHRcdG5vZGUubmV4dCA9IGhlcmU7XG5cdFx0XHRcdFx0XHRwcmV2Lm5leHQgPSBub2RlO1xuXHRcdFx0XHRcdFx0aWYgKGhlcmUgIT09IG51bGwpXG5cdFx0XHRcdFx0XHRcdGhlcmUucHJldiA9IG5vZGU7XG5cdFx0XHRcdFx0XHRyZXR1cm4gbm9kZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRyZXR1cm4gbXk7XG5cdH0sXG5cdG5vZGU6IGZ1bmN0aW9uKGRhdGEpe1xuXHRcdGRhdGEucHJldiA9IG51bGw7XG5cdFx0ZGF0YS5uZXh0ID0gbnVsbDtcblx0XHRkYXRhLnJlbW92ZSA9IGZ1bmN0aW9uKCl7XG5cdFx0XHRkYXRhLnByZXYubmV4dCA9IGRhdGEubmV4dDtcblx0XHRcdGlmIChkYXRhLm5leHQpXG5cdFx0XHRcdGRhdGEubmV4dC5wcmV2ID0gZGF0YS5wcmV2O1xuXHRcdFx0ZGF0YS5wcmV2ID0gbnVsbDtcblx0XHRcdGRhdGEubmV4dCA9IG51bGw7XG5cdFx0fTtcblx0XHRyZXR1cm4gZGF0YTtcblx0fVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBMaW5rZWRMaXN0O1xuXG59LHt9XSw0Nzk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gKGMpIENvcHlyaWdodCAyMDE2LCBTZWFuIENvbm5lbGx5IChAdm9pZHFrKSwgaHR0cDovL3N5bnRoZXRpLmNjXG4vLyBNSVQgTGljZW5zZVxuLy8gUHJvamVjdCBIb21lOiBodHRwczovL2dpdGh1Yi5jb20vdm9pZHFrL3BvbHlib29sanNcblxuLy9cbi8vIGNvbnZlcnRzIGEgbGlzdCBvZiBzZWdtZW50cyBpbnRvIGEgbGlzdCBvZiByZWdpb25zLCB3aGlsZSBhbHNvIHJlbW92aW5nIHVubmVjZXNzYXJ5IHZlcnRpY2llc1xuLy9cblxuZnVuY3Rpb24gU2VnbWVudENoYWluZXIoc2VnbWVudHMsIGVwcywgYnVpbGRMb2cpe1xuXHR2YXIgY2hhaW5zID0gW107XG5cdHZhciByZWdpb25zID0gW107XG5cblx0c2VnbWVudHMuZm9yRWFjaChmdW5jdGlvbihzZWcpe1xuXHRcdHZhciBwdDEgPSBzZWcuc3RhcnQ7XG5cdFx0dmFyIHB0MiA9IHNlZy5lbmQ7XG5cdFx0aWYgKGVwcy5wb2ludHNTYW1lKHB0MSwgcHQyKSl7XG5cdFx0XHRjb25zb2xlLndhcm4oJ1BvbHlCb29sOiBXYXJuaW5nOiBaZXJvLWxlbmd0aCBzZWdtZW50IGRldGVjdGVkOyB5b3VyIGVwc2lsb24gaXMgJyArXG5cdFx0XHRcdCdwcm9iYWJseSB0b28gc21hbGwgb3IgdG9vIGxhcmdlJyk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0YnVpbGRMb2cuY2hhaW5TdGFydChzZWcpO1xuXG5cdFx0Ly8gc2VhcmNoIGZvciB0d28gY2hhaW5zIHRoYXQgdGhpcyBzZWdtZW50IG1hdGNoZXNcblx0XHR2YXIgZmlyc3RfbWF0Y2ggPSB7XG5cdFx0XHRpbmRleDogMCxcblx0XHRcdG1hdGNoZXNfaGVhZDogZmFsc2UsXG5cdFx0XHRtYXRjaGVzX3B0MTogZmFsc2Vcblx0XHR9O1xuXHRcdHZhciBzZWNvbmRfbWF0Y2ggPSB7XG5cdFx0XHRpbmRleDogMCxcblx0XHRcdG1hdGNoZXNfaGVhZDogZmFsc2UsXG5cdFx0XHRtYXRjaGVzX3B0MTogZmFsc2Vcblx0XHR9O1xuXHRcdHZhciBuZXh0X21hdGNoID0gZmlyc3RfbWF0Y2g7XG5cdFx0ZnVuY3Rpb24gc2V0TWF0Y2goaW5kZXgsIG1hdGNoZXNfaGVhZCwgbWF0Y2hlc19wdDEpe1xuXHRcdFx0Ly8gcmV0dXJuIHRydWUgaWYgd2UndmUgbWF0Y2hlZCB0d2ljZVxuXHRcdFx0bmV4dF9tYXRjaC5pbmRleCA9IGluZGV4O1xuXHRcdFx0bmV4dF9tYXRjaC5tYXRjaGVzX2hlYWQgPSBtYXRjaGVzX2hlYWQ7XG5cdFx0XHRuZXh0X21hdGNoLm1hdGNoZXNfcHQxID0gbWF0Y2hlc19wdDE7XG5cdFx0XHRpZiAobmV4dF9tYXRjaCA9PT0gZmlyc3RfbWF0Y2gpe1xuXHRcdFx0XHRuZXh0X21hdGNoID0gc2Vjb25kX21hdGNoO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFx0XHRuZXh0X21hdGNoID0gbnVsbDtcblx0XHRcdHJldHVybiB0cnVlOyAvLyB3ZSd2ZSBtYXRjaGVkIHR3aWNlLCB3ZSdyZSBkb25lIGhlcmVcblx0XHR9XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBjaGFpbnMubGVuZ3RoOyBpKyspe1xuXHRcdFx0dmFyIGNoYWluID0gY2hhaW5zW2ldO1xuXHRcdFx0dmFyIGhlYWQgID0gY2hhaW5bMF07XG5cdFx0XHR2YXIgaGVhZDIgPSBjaGFpblsxXTtcblx0XHRcdHZhciB0YWlsICA9IGNoYWluW2NoYWluLmxlbmd0aCAtIDFdO1xuXHRcdFx0dmFyIHRhaWwyID0gY2hhaW5bY2hhaW4ubGVuZ3RoIC0gMl07XG5cdFx0XHRpZiAoZXBzLnBvaW50c1NhbWUoaGVhZCwgcHQxKSl7XG5cdFx0XHRcdGlmIChzZXRNYXRjaChpLCB0cnVlLCB0cnVlKSlcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKGVwcy5wb2ludHNTYW1lKGhlYWQsIHB0Mikpe1xuXHRcdFx0XHRpZiAoc2V0TWF0Y2goaSwgdHJ1ZSwgZmFsc2UpKVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoZXBzLnBvaW50c1NhbWUodGFpbCwgcHQxKSl7XG5cdFx0XHRcdGlmIChzZXRNYXRjaChpLCBmYWxzZSwgdHJ1ZSkpXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmIChlcHMucG9pbnRzU2FtZSh0YWlsLCBwdDIpKXtcblx0XHRcdFx0aWYgKHNldE1hdGNoKGksIGZhbHNlLCBmYWxzZSkpXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKG5leHRfbWF0Y2ggPT09IGZpcnN0X21hdGNoKXtcblx0XHRcdC8vIHdlIGRpZG4ndCBtYXRjaCBhbnl0aGluZywgc28gY3JlYXRlIGEgbmV3IGNoYWluXG5cdFx0XHRjaGFpbnMucHVzaChbIHB0MSwgcHQyIF0pO1xuXHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRidWlsZExvZy5jaGFpbk5ldyhwdDEsIHB0Mik7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKG5leHRfbWF0Y2ggPT09IHNlY29uZF9tYXRjaCl7XG5cdFx0XHQvLyB3ZSBtYXRjaGVkIGEgc2luZ2xlIGNoYWluXG5cblx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0YnVpbGRMb2cuY2hhaW5NYXRjaChmaXJzdF9tYXRjaC5pbmRleCk7XG5cblx0XHRcdC8vIGFkZCB0aGUgb3RoZXIgcG9pbnQgdG8gdGhlIGFwcG9ycHJpYXRlIGVuZCwgYW5kIGNoZWNrIHRvIHNlZSBpZiB3ZSd2ZSBjbG9zZWQgdGhlXG5cdFx0XHQvLyBjaGFpbiBpbnRvIGEgbG9vcFxuXG5cdFx0XHR2YXIgaW5kZXggPSBmaXJzdF9tYXRjaC5pbmRleDtcblx0XHRcdHZhciBwdCA9IGZpcnN0X21hdGNoLm1hdGNoZXNfcHQxID8gcHQyIDogcHQxOyAvLyBpZiB3ZSBtYXRjaGVkIHB0MSwgdGhlbiB3ZSBhZGQgcHQyLCBldGNcblx0XHRcdHZhciBhZGRUb0hlYWQgPSBmaXJzdF9tYXRjaC5tYXRjaGVzX2hlYWQ7IC8vIGlmIHdlIG1hdGNoZWQgYXQgaGVhZCwgdGhlbiBhZGQgdG8gdGhlIGhlYWRcblxuXHRcdFx0dmFyIGNoYWluID0gY2hhaW5zW2luZGV4XTtcblx0XHRcdHZhciBncm93ICA9IGFkZFRvSGVhZCA/IGNoYWluWzBdIDogY2hhaW5bY2hhaW4ubGVuZ3RoIC0gMV07XG5cdFx0XHR2YXIgZ3JvdzIgPSBhZGRUb0hlYWQgPyBjaGFpblsxXSA6IGNoYWluW2NoYWluLmxlbmd0aCAtIDJdO1xuXHRcdFx0dmFyIG9wcG8gID0gYWRkVG9IZWFkID8gY2hhaW5bY2hhaW4ubGVuZ3RoIC0gMV0gOiBjaGFpblswXTtcblx0XHRcdHZhciBvcHBvMiA9IGFkZFRvSGVhZCA/IGNoYWluW2NoYWluLmxlbmd0aCAtIDJdIDogY2hhaW5bMV07XG5cblx0XHRcdGlmIChlcHMucG9pbnRzQ29sbGluZWFyKGdyb3cyLCBncm93LCBwdCkpe1xuXHRcdFx0XHQvLyBncm93IGlzbid0IG5lZWRlZCBiZWNhdXNlIGl0J3MgZGlyZWN0bHkgYmV0d2VlbiBncm93MiBhbmQgcHQ6XG5cdFx0XHRcdC8vIGdyb3cyIC0tLWdyb3ctLS0+IHB0XG5cdFx0XHRcdGlmIChhZGRUb0hlYWQpe1xuXHRcdFx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0XHRcdGJ1aWxkTG9nLmNoYWluUmVtb3ZlSGVhZChmaXJzdF9tYXRjaC5pbmRleCwgcHQpO1xuXHRcdFx0XHRcdGNoYWluLnNoaWZ0KCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZXtcblx0XHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0XHRidWlsZExvZy5jaGFpblJlbW92ZVRhaWwoZmlyc3RfbWF0Y2guaW5kZXgsIHB0KTtcblx0XHRcdFx0XHRjaGFpbi5wb3AoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRncm93ID0gZ3JvdzI7IC8vIG9sZCBncm93IGlzIGdvbmUuLi4gbmV3IGdyb3cgaXMgd2hhdCBncm93MiB3YXNcblx0XHRcdH1cblxuXHRcdFx0aWYgKGVwcy5wb2ludHNTYW1lKG9wcG8sIHB0KSl7XG5cdFx0XHRcdC8vIHdlJ3JlIGNsb3NpbmcgdGhlIGxvb3AsIHNvIHJlbW92ZSBjaGFpbiBmcm9tIGNoYWluc1xuXHRcdFx0XHRjaGFpbnMuc3BsaWNlKGluZGV4LCAxKTtcblxuXHRcdFx0XHRpZiAoZXBzLnBvaW50c0NvbGxpbmVhcihvcHBvMiwgb3BwbywgZ3Jvdykpe1xuXHRcdFx0XHRcdC8vIG9wcG8gaXNuJ3QgbmVlZGVkIGJlY2F1c2UgaXQncyBkaXJlY3RseSBiZXR3ZWVuIG9wcG8yIGFuZCBncm93OlxuXHRcdFx0XHRcdC8vIG9wcG8yIC0tLW9wcG8tLS0+Z3Jvd1xuXHRcdFx0XHRcdGlmIChhZGRUb0hlYWQpe1xuXHRcdFx0XHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRcdFx0XHRidWlsZExvZy5jaGFpblJlbW92ZVRhaWwoZmlyc3RfbWF0Y2guaW5kZXgsIGdyb3cpO1xuXHRcdFx0XHRcdFx0Y2hhaW4ucG9wKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2V7XG5cdFx0XHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0XHRcdGJ1aWxkTG9nLmNoYWluUmVtb3ZlSGVhZChmaXJzdF9tYXRjaC5pbmRleCwgZ3Jvdyk7XG5cdFx0XHRcdFx0XHRjaGFpbi5zaGlmdCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0XHRidWlsZExvZy5jaGFpbkNsb3NlKGZpcnN0X21hdGNoLmluZGV4KTtcblxuXHRcdFx0XHQvLyB3ZSBoYXZlIGEgY2xvc2VkIGNoYWluIVxuXHRcdFx0XHRyZWdpb25zLnB1c2goY2hhaW4pO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdC8vIG5vdCBjbG9zaW5nIGEgbG9vcCwgc28ganVzdCBhZGQgaXQgdG8gdGhlIGFwcG9ycHJpYXRlIHNpZGVcblx0XHRcdGlmIChhZGRUb0hlYWQpe1xuXHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0YnVpbGRMb2cuY2hhaW5BZGRIZWFkKGZpcnN0X21hdGNoLmluZGV4LCBwdCk7XG5cdFx0XHRcdGNoYWluLnVuc2hpZnQocHQpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZXtcblx0XHRcdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0XHRcdGJ1aWxkTG9nLmNoYWluQWRkVGFpbChmaXJzdF9tYXRjaC5pbmRleCwgcHQpO1xuXHRcdFx0XHRjaGFpbi5wdXNoKHB0KTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBvdGhlcndpc2UsIHdlIG1hdGNoZWQgdHdvIGNoYWlucywgc28gd2UgbmVlZCB0byBjb21iaW5lIHRob3NlIGNoYWlucyB0b2dldGhlclxuXG5cdFx0ZnVuY3Rpb24gcmV2ZXJzZUNoYWluKGluZGV4KXtcblx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0YnVpbGRMb2cuY2hhaW5SZXZlcnNlKGluZGV4KTtcblx0XHRcdGNoYWluc1tpbmRleF0ucmV2ZXJzZSgpOyAvLyBnZWUsIHRoYXQncyBlYXN5XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gYXBwZW5kQ2hhaW4oaW5kZXgxLCBpbmRleDIpe1xuXHRcdFx0Ly8gaW5kZXgxIGdldHMgaW5kZXgyIGFwcGVuZGVkIHRvIGl0LCBhbmQgaW5kZXgyIGlzIHJlbW92ZWRcblx0XHRcdHZhciBjaGFpbjEgPSBjaGFpbnNbaW5kZXgxXTtcblx0XHRcdHZhciBjaGFpbjIgPSBjaGFpbnNbaW5kZXgyXTtcblx0XHRcdHZhciB0YWlsICA9IGNoYWluMVtjaGFpbjEubGVuZ3RoIC0gMV07XG5cdFx0XHR2YXIgdGFpbDIgPSBjaGFpbjFbY2hhaW4xLmxlbmd0aCAtIDJdO1xuXHRcdFx0dmFyIGhlYWQgID0gY2hhaW4yWzBdO1xuXHRcdFx0dmFyIGhlYWQyID0gY2hhaW4yWzFdO1xuXG5cdFx0XHRpZiAoZXBzLnBvaW50c0NvbGxpbmVhcih0YWlsMiwgdGFpbCwgaGVhZCkpe1xuXHRcdFx0XHQvLyB0YWlsIGlzbid0IG5lZWRlZCBiZWNhdXNlIGl0J3MgZGlyZWN0bHkgYmV0d2VlbiB0YWlsMiBhbmQgaGVhZFxuXHRcdFx0XHQvLyB0YWlsMiAtLS10YWlsLS0tPiBoZWFkXG5cdFx0XHRcdGlmIChidWlsZExvZylcblx0XHRcdFx0XHRidWlsZExvZy5jaGFpblJlbW92ZVRhaWwoaW5kZXgxLCB0YWlsKTtcblx0XHRcdFx0Y2hhaW4xLnBvcCgpO1xuXHRcdFx0XHR0YWlsID0gdGFpbDI7IC8vIG9sZCB0YWlsIGlzIGdvbmUuLi4gbmV3IHRhaWwgaXMgd2hhdCB0YWlsMiB3YXNcblx0XHRcdH1cblxuXHRcdFx0aWYgKGVwcy5wb2ludHNDb2xsaW5lYXIodGFpbCwgaGVhZCwgaGVhZDIpKXtcblx0XHRcdFx0Ly8gaGVhZCBpc24ndCBuZWVkZWQgYmVjYXVzZSBpdCdzIGRpcmVjdGx5IGJldHdlZW4gdGFpbCBhbmQgaGVhZDJcblx0XHRcdFx0Ly8gdGFpbCAtLS1oZWFkLS0tPiBoZWFkMlxuXHRcdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdFx0YnVpbGRMb2cuY2hhaW5SZW1vdmVIZWFkKGluZGV4MiwgaGVhZCk7XG5cdFx0XHRcdGNoYWluMi5zaGlmdCgpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoYnVpbGRMb2cpXG5cdFx0XHRcdGJ1aWxkTG9nLmNoYWluSm9pbihpbmRleDEsIGluZGV4Mik7XG5cdFx0XHRjaGFpbnNbaW5kZXgxXSA9IGNoYWluMS5jb25jYXQoY2hhaW4yKTtcblx0XHRcdGNoYWlucy5zcGxpY2UoaW5kZXgyLCAxKTtcblx0XHR9XG5cblx0XHR2YXIgRiA9IGZpcnN0X21hdGNoLmluZGV4O1xuXHRcdHZhciBTID0gc2Vjb25kX21hdGNoLmluZGV4O1xuXG5cdFx0aWYgKGJ1aWxkTG9nKVxuXHRcdFx0YnVpbGRMb2cuY2hhaW5Db25uZWN0KEYsIFMpO1xuXG5cdFx0dmFyIHJldmVyc2VGID0gY2hhaW5zW0ZdLmxlbmd0aCA8IGNoYWluc1tTXS5sZW5ndGg7IC8vIHJldmVyc2UgdGhlIHNob3J0ZXIgY2hhaW4sIGlmIG5lZWRlZFxuXHRcdGlmIChmaXJzdF9tYXRjaC5tYXRjaGVzX2hlYWQpe1xuXHRcdFx0aWYgKHNlY29uZF9tYXRjaC5tYXRjaGVzX2hlYWQpe1xuXHRcdFx0XHRpZiAocmV2ZXJzZUYpe1xuXHRcdFx0XHRcdC8vIDw8PDwgRiA8PDw8IC0tLSA+Pj4+IFMgPj4+PlxuXHRcdFx0XHRcdHJldmVyc2VDaGFpbihGKTtcblx0XHRcdFx0XHQvLyA+Pj4+IEYgPj4+PiAtLS0gPj4+PiBTID4+Pj5cblx0XHRcdFx0XHRhcHBlbmRDaGFpbihGLCBTKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNle1xuXHRcdFx0XHRcdC8vIDw8PDwgRiA8PDw8IC0tLSA+Pj4+IFMgPj4+PlxuXHRcdFx0XHRcdHJldmVyc2VDaGFpbihTKTtcblx0XHRcdFx0XHQvLyA8PDw8IEYgPDw8PCAtLS0gPDw8PCBTIDw8PDwgICBsb2dpY2FsbHkgc2FtZSBhczpcblx0XHRcdFx0XHQvLyA+Pj4+IFMgPj4+PiAtLS0gPj4+PiBGID4+Pj5cblx0XHRcdFx0XHRhcHBlbmRDaGFpbihTLCBGKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0ZWxzZXtcblx0XHRcdFx0Ly8gPDw8PCBGIDw8PDwgLS0tIDw8PDwgUyA8PDw8ICAgbG9naWNhbGx5IHNhbWUgYXM6XG5cdFx0XHRcdC8vID4+Pj4gUyA+Pj4+IC0tLSA+Pj4+IEYgPj4+PlxuXHRcdFx0XHRhcHBlbmRDaGFpbihTLCBGKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZXtcblx0XHRcdGlmIChzZWNvbmRfbWF0Y2gubWF0Y2hlc19oZWFkKXtcblx0XHRcdFx0Ly8gPj4+PiBGID4+Pj4gLS0tID4+Pj4gUyA+Pj4+XG5cdFx0XHRcdGFwcGVuZENoYWluKEYsIFMpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZXtcblx0XHRcdFx0aWYgKHJldmVyc2VGKXtcblx0XHRcdFx0XHQvLyA+Pj4+IEYgPj4+PiAtLS0gPDw8PCBTIDw8PDxcblx0XHRcdFx0XHRyZXZlcnNlQ2hhaW4oRik7XG5cdFx0XHRcdFx0Ly8gPDw8PCBGIDw8PDwgLS0tIDw8PDwgUyA8PDw8ICAgbG9naWNhbGx5IHNhbWUgYXM6XG5cdFx0XHRcdFx0Ly8gPj4+PiBTID4+Pj4gLS0tID4+Pj4gRiA+Pj4+XG5cdFx0XHRcdFx0YXBwZW5kQ2hhaW4oUywgRik7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZXtcblx0XHRcdFx0XHQvLyA+Pj4+IEYgPj4+PiAtLS0gPDw8PCBTIDw8PDxcblx0XHRcdFx0XHRyZXZlcnNlQ2hhaW4oUyk7XG5cdFx0XHRcdFx0Ly8gPj4+PiBGID4+Pj4gLS0tID4+Pj4gUyA+Pj4+XG5cdFx0XHRcdFx0YXBwZW5kQ2hhaW4oRiwgUyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuXG5cdHJldHVybiByZWdpb25zO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFNlZ21lbnRDaGFpbmVyO1xuXG59LHt9XSw0ODA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gKGMpIENvcHlyaWdodCAyMDE2LCBTZWFuIENvbm5lbGx5IChAdm9pZHFrKSwgaHR0cDovL3N5bnRoZXRpLmNjXG4vLyBNSVQgTGljZW5zZVxuLy8gUHJvamVjdCBIb21lOiBodHRwczovL2dpdGh1Yi5jb20vdm9pZHFrL3BvbHlib29sanNcblxuLy9cbi8vIGZpbHRlciBhIGxpc3Qgb2Ygc2VnbWVudHMgYmFzZWQgb24gYm9vbGVhbiBvcGVyYXRpb25zXG4vL1xuXG5mdW5jdGlvbiBzZWxlY3Qoc2VnbWVudHMsIHNlbGVjdGlvbiwgYnVpbGRMb2cpe1xuXHR2YXIgcmVzdWx0ID0gW107XG5cdHNlZ21lbnRzLmZvckVhY2goZnVuY3Rpb24oc2VnKXtcblx0XHR2YXIgaW5kZXggPVxuXHRcdFx0KHNlZy5teUZpbGwuYWJvdmUgPyA4IDogMCkgK1xuXHRcdFx0KHNlZy5teUZpbGwuYmVsb3cgPyA0IDogMCkgK1xuXHRcdFx0KChzZWcub3RoZXJGaWxsICYmIHNlZy5vdGhlckZpbGwuYWJvdmUpID8gMiA6IDApICtcblx0XHRcdCgoc2VnLm90aGVyRmlsbCAmJiBzZWcub3RoZXJGaWxsLmJlbG93KSA/IDEgOiAwKTtcblx0XHRpZiAoc2VsZWN0aW9uW2luZGV4XSAhPT0gMCl7XG5cdFx0XHQvLyBjb3B5IHRoZSBzZWdtZW50IHRvIHRoZSByZXN1bHRzLCB3aGlsZSBhbHNvIGNhbGN1bGF0aW5nIHRoZSBmaWxsIHN0YXR1c1xuXHRcdFx0cmVzdWx0LnB1c2goe1xuXHRcdFx0XHRpZDogYnVpbGRMb2cgPyBidWlsZExvZy5zZWdtZW50SWQoKSA6IC0xLFxuXHRcdFx0XHRzdGFydDogc2VnLnN0YXJ0LFxuXHRcdFx0XHRlbmQ6IHNlZy5lbmQsXG5cdFx0XHRcdG15RmlsbDoge1xuXHRcdFx0XHRcdGFib3ZlOiBzZWxlY3Rpb25baW5kZXhdID09PSAxLCAvLyAxIGlmIGZpbGxlZCBhYm92ZVxuXHRcdFx0XHRcdGJlbG93OiBzZWxlY3Rpb25baW5kZXhdID09PSAyICAvLyAyIGlmIGZpbGxlZCBiZWxvd1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRvdGhlckZpbGw6IG51bGxcblx0XHRcdH0pO1xuXHRcdH1cblx0fSk7XG5cblx0aWYgKGJ1aWxkTG9nKVxuXHRcdGJ1aWxkTG9nLnNlbGVjdGVkKHJlc3VsdCk7XG5cblx0cmV0dXJuIHJlc3VsdDtcbn1cblxudmFyIFNlZ21lbnRTZWxlY3RvciA9IHtcblx0dW5pb246IGZ1bmN0aW9uKHNlZ21lbnRzLCBidWlsZExvZyl7IC8vIHByaW1hcnkgfCBzZWNvbmRhcnlcblx0XHQvLyBhYm92ZTEgYmVsb3cxIGFib3ZlMiBiZWxvdzIgICAgS2VlcD8gICAgICAgICAgICAgICBWYWx1ZVxuXHRcdC8vICAgIDAgICAgICAwICAgICAgMCAgICAgIDAgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDAgICAgICAwICAgICAgMCAgICAgIDEgICA9PiAgIHllcyBmaWxsZWQgYmVsb3cgICAgMlxuXHRcdC8vICAgIDAgICAgICAwICAgICAgMSAgICAgIDAgICA9PiAgIHllcyBmaWxsZWQgYWJvdmUgICAgMVxuXHRcdC8vICAgIDAgICAgICAwICAgICAgMSAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDAgICAgICAxICAgICAgMCAgICAgIDAgICA9PiAgIHllcyBmaWxsZWQgYmVsb3cgICAgMlxuXHRcdC8vICAgIDAgICAgICAxICAgICAgMCAgICAgIDEgICA9PiAgIHllcyBmaWxsZWQgYmVsb3cgICAgMlxuXHRcdC8vICAgIDAgICAgICAxICAgICAgMSAgICAgIDAgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDAgICAgICAxICAgICAgMSAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDEgICAgICAwICAgICAgMCAgICAgIDAgICA9PiAgIHllcyBmaWxsZWQgYWJvdmUgICAgMVxuXHRcdC8vICAgIDEgICAgICAwICAgICAgMCAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDEgICAgICAwICAgICAgMSAgICAgIDAgICA9PiAgIHllcyBmaWxsZWQgYWJvdmUgICAgMVxuXHRcdC8vICAgIDEgICAgICAwICAgICAgMSAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDEgICAgICAxICAgICAgMCAgICAgIDAgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDEgICAgICAxICAgICAgMCAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDEgICAgICAxICAgICAgMSAgICAgIDAgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdC8vICAgIDEgICAgICAxICAgICAgMSAgICAgIDEgICA9PiAgIG5vICAgICAgICAgICAgICAgICAgMFxuXHRcdHJldHVybiBzZWxlY3Qoc2VnbWVudHMsIFtcblx0XHRcdDAsIDIsIDEsIDAsXG5cdFx0XHQyLCAyLCAwLCAwLFxuXHRcdFx0MSwgMCwgMSwgMCxcblx0XHRcdDAsIDAsIDAsIDBcblx0XHRdLCBidWlsZExvZyk7XG5cdH0sXG5cdGludGVyc2VjdDogZnVuY3Rpb24oc2VnbWVudHMsIGJ1aWxkTG9nKXsgLy8gcHJpbWFyeSAmIHNlY29uZGFyeVxuXHRcdC8vIGFib3ZlMSBiZWxvdzEgYWJvdmUyIGJlbG93MiAgICBLZWVwPyAgICAgICAgICAgICAgIFZhbHVlXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAwICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAxICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAwICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAxICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAxICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAwICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAxICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAxICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAwICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAxICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0cmV0dXJuIHNlbGVjdChzZWdtZW50cywgW1xuXHRcdFx0MCwgMCwgMCwgMCxcblx0XHRcdDAsIDIsIDAsIDIsXG5cdFx0XHQwLCAwLCAxLCAxLFxuXHRcdFx0MCwgMiwgMSwgMFxuXHRcdF0sIGJ1aWxkTG9nKTtcblx0fSxcblx0ZGlmZmVyZW5jZTogZnVuY3Rpb24oc2VnbWVudHMsIGJ1aWxkTG9nKXsgLy8gcHJpbWFyeSAtIHNlY29uZGFyeVxuXHRcdC8vIGFib3ZlMSBiZWxvdzEgYWJvdmUyIGJlbG93MiAgICBLZWVwPyAgICAgICAgICAgICAgIFZhbHVlXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAwICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAxICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAwICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAwICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAxICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAwICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAwICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAxICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAwICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAxICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0cmV0dXJuIHNlbGVjdChzZWdtZW50cywgW1xuXHRcdFx0MCwgMCwgMCwgMCxcblx0XHRcdDIsIDAsIDIsIDAsXG5cdFx0XHQxLCAxLCAwLCAwLFxuXHRcdFx0MCwgMSwgMiwgMFxuXHRcdF0sIGJ1aWxkTG9nKTtcblx0fSxcblx0ZGlmZmVyZW5jZVJldjogZnVuY3Rpb24oc2VnbWVudHMsIGJ1aWxkTG9nKXsgLy8gc2Vjb25kYXJ5IC0gcHJpbWFyeVxuXHRcdC8vIGFib3ZlMSBiZWxvdzEgYWJvdmUyIGJlbG93MiAgICBLZWVwPyAgICAgICAgICAgICAgIFZhbHVlXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAwICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAxICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMCAgICAgIDAgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAwICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAxICAgICAgMCAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMCAgICAgIDEgICAgICAxICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBhYm92ZSAgICAxXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAwICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAxICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDAgICAgICAxICAgICAgMSAgID0+ICAgeWVzIGZpbGxlZCBiZWxvdyAgICAyXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAwICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAwICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAxICAgICAgMCAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0Ly8gICAgMSAgICAgIDEgICAgICAxICAgICAgMSAgID0+ICAgbm8gICAgICAgICAgICAgICAgICAwXG5cdFx0cmV0dXJuIHNlbGVjdChzZWdtZW50cywgW1xuXHRcdFx0MCwgMiwgMSwgMCxcblx0XHRcdDAsIDAsIDEsIDEsXG5cdFx0XHQwLCAyLCAwLCAyLFxuXHRcdFx0MCwgMCwgMCwgMFxuXHRcdF0sIGJ1aWxkTG9nKTtcblx0fSxcblx0eG9yOiBmdW5jdGlvbihzZWdtZW50cywgYnVpbGRMb2cpeyAvLyBwcmltYXJ5IF4gc2Vjb25kYXJ5XG5cdFx0Ly8gYWJvdmUxIGJlbG93MSBhYm92ZTIgYmVsb3cyICAgIEtlZXA/ICAgICAgICAgICAgICAgVmFsdWVcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDAgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDEgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAwICAgICAgMCAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDAgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDAgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDEgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAwICAgICAgMSAgICAgIDEgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDAgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDAgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDEgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMCAgICAgIDEgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDAgICAgICAwICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDAgICAgICAxICAgPT4gICB5ZXMgZmlsbGVkIGFib3ZlICAgIDFcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDEgICAgICAwICAgPT4gICB5ZXMgZmlsbGVkIGJlbG93ICAgIDJcblx0XHQvLyAgICAxICAgICAgMSAgICAgIDEgICAgICAxICAgPT4gICBubyAgICAgICAgICAgICAgICAgIDBcblx0XHRyZXR1cm4gc2VsZWN0KHNlZ21lbnRzLCBbXG5cdFx0XHQwLCAyLCAxLCAwLFxuXHRcdFx0MiwgMCwgMCwgMSxcblx0XHRcdDEsIDAsIDAsIDIsXG5cdFx0XHQwLCAxLCAyLCAwXG5cdFx0XSwgYnVpbGRMb2cpO1xuXHR9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNlZ21lbnRTZWxlY3RvcjtcblxufSx7fV0sNDgxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vT3B0aW1pemVkIHZlcnNpb24gZm9yIHRyaWFuZ2xlIGNsb3Nlc3QgcG9pbnRcbi8vIEJhc2VkIG9uIEViZXJseSdzIFdpbGRNYWdpY2sgY29kZXNcbi8vIGh0dHA6Ly93d3cuZ2VvbWV0cmljdG9vbHMuY29tL0xpYk1hdGhlbWF0aWNzL0Rpc3RhbmNlL0Rpc3RhbmNlLmh0bWxcblwidXNlIHN0cmljdFwiO1xuXG52YXIgZGlmZiA9IG5ldyBGbG9hdDY0QXJyYXkoNCk7XG52YXIgZWRnZTAgPSBuZXcgRmxvYXQ2NEFycmF5KDQpO1xudmFyIGVkZ2UxID0gbmV3IEZsb2F0NjRBcnJheSg0KTtcblxuZnVuY3Rpb24gY2xvc2VzdFBvaW50MmQoVjAsIFYxLCBWMiwgcG9pbnQsIHJlc3VsdCkge1xuICAvL1JlYWxsb2NhdGUgYnVmZmVycyBpZiBuZWNlc3NhcnlcbiAgaWYoZGlmZi5sZW5ndGggPCBwb2ludC5sZW5ndGgpIHtcbiAgICBkaWZmID0gbmV3IEZsb2F0NjRBcnJheShwb2ludC5sZW5ndGgpO1xuICAgIGVkZ2UwID0gbmV3IEZsb2F0NjRBcnJheShwb2ludC5sZW5ndGgpO1xuICAgIGVkZ2UxID0gbmV3IEZsb2F0NjRBcnJheShwb2ludC5sZW5ndGgpO1xuICB9XG4gIC8vQ29tcHV0ZSBlZGdlc1xuICBmb3IodmFyIGk9MDsgaTxwb2ludC5sZW5ndGg7ICsraSkge1xuICAgIGRpZmZbaV0gID0gVjBbaV0gLSBwb2ludFtpXTtcbiAgICBlZGdlMFtpXSA9IFYxW2ldIC0gVjBbaV07XG4gICAgZWRnZTFbaV0gPSBWMltpXSAtIFYwW2ldO1xuICB9XG4gIC8vQ29tcHV0ZSBjb2VmZmljaWVudHMgZm9yIHF1YWRyYXRpYyBmdW5jXG4gIHZhciBhMDAgPSAwLjBcbiAgICAsIGEwMSA9IDAuMFxuICAgICwgYTExID0gMC4wXG4gICAgLCBiMCAgPSAwLjBcbiAgICAsIGIxICA9IDAuMFxuICAgICwgYyAgID0gMC4wO1xuICBmb3IodmFyIGk9MDsgaTxwb2ludC5sZW5ndGg7ICsraSkge1xuICAgIHZhciBlMCA9IGVkZ2UwW2ldXG4gICAgICAsIGUxID0gZWRnZTFbaV1cbiAgICAgICwgZCAgPSBkaWZmW2ldO1xuICAgIGEwMCArPSBlMCAqIGUwO1xuICAgIGEwMSArPSBlMCAqIGUxO1xuICAgIGExMSArPSBlMSAqIGUxO1xuICAgIGIwICArPSBkICogZTA7XG4gICAgYjEgICs9IGQgKiBlMTtcbiAgICBjICAgKz0gZCAqIGQ7XG4gIH1cbiAgLy9Db21wdXRlIGRldGVybWluYW50L2NvZWZmc1xuICB2YXIgZGV0ID0gTWF0aC5hYnMoYTAwKmExMSAtIGEwMSphMDEpO1xuICB2YXIgcyAgID0gYTAxKmIxIC0gYTExKmIwO1xuICB2YXIgdCAgID0gYTAxKmIwIC0gYTAwKmIxO1xuICB2YXIgc3FyRGlzdGFuY2U7XG4gIC8vSGFyZGNvZGVkIFZvcm9ub2kgZGlhZ3JhbSBjbGFzc2lmaWNhdGlvblxuICBpZiAocyArIHQgPD0gZGV0KSB7XG4gICAgaWYgKHMgPCAwKSB7XG4gICAgICBpZiAodCA8IDApIHsgLy8gcmVnaW9uIDRcbiAgICAgICAgaWYgKGIwIDwgMCkge1xuICAgICAgICAgIHQgPSAwO1xuICAgICAgICAgIGlmICgtYjAgPj0gYTAwKSB7XG4gICAgICAgICAgICBzID0gMS4wO1xuICAgICAgICAgICAgc3FyRGlzdGFuY2UgPSBhMDAgKyAyLjAqYjAgKyBjO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzID0gLWIwL2EwMDtcbiAgICAgICAgICAgIHNxckRpc3RhbmNlID0gYjAqcyArIGM7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMgPSAwO1xuICAgICAgICAgIGlmIChiMSA+PSAwKSB7XG4gICAgICAgICAgICB0ID0gMDtcbiAgICAgICAgICAgIHNxckRpc3RhbmNlID0gYztcbiAgICAgICAgICB9IGVsc2UgaWYgKC1iMSA+PSBhMTEpIHtcbiAgICAgICAgICAgIHQgPSAxO1xuICAgICAgICAgICAgc3FyRGlzdGFuY2UgPSBhMTEgKyAyLjAqYjEgKyBjO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0ID0gLWIxL2ExMTtcbiAgICAgICAgICAgIHNxckRpc3RhbmNlID0gYjEqdCArIGM7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgeyAgLy8gcmVnaW9uIDNcbiAgICAgICAgcyA9IDA7XG4gICAgICAgIGlmIChiMSA+PSAwKSB7XG4gICAgICAgICAgdCA9IDA7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBjO1xuICAgICAgICB9IGVsc2UgaWYgKC1iMSA+PSBhMTEpIHtcbiAgICAgICAgICB0ID0gMTtcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IGExMSArIDIuMCpiMSArIGM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdCA9IC1iMS9hMTE7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBiMSp0ICsgYztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodCA8IDApIHsgLy8gcmVnaW9uIDVcbiAgICAgIHQgPSAwO1xuICAgICAgaWYgKGIwID49IDApIHtcbiAgICAgICAgcyA9IDA7XG4gICAgICAgIHNxckRpc3RhbmNlID0gYztcbiAgICAgIH0gZWxzZSBpZiAoLWIwID49IGEwMCkge1xuICAgICAgICBzID0gMTtcbiAgICAgICAgc3FyRGlzdGFuY2UgPSBhMDAgKyAyLjAqYjAgKyBjO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcyA9IC1iMC9hMDA7XG4gICAgICAgIHNxckRpc3RhbmNlID0gYjAqcyArIGM7XG4gICAgICB9XG4gICAgfSBlbHNlIHsgIC8vIHJlZ2lvbiAwXG4gICAgICAvLyBtaW5pbXVtIGF0IGludGVyaW9yIHBvaW50XG4gICAgICB2YXIgaW52RGV0ID0gMS4wIC8gZGV0O1xuICAgICAgcyAqPSBpbnZEZXQ7XG4gICAgICB0ICo9IGludkRldDtcbiAgICAgIHNxckRpc3RhbmNlID0gcyooYTAwKnMgKyBhMDEqdCArIDIuMCpiMCkgKyB0KihhMDEqcyArIGExMSp0ICsgMi4wKmIxKSArIGM7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciB0bXAwLCB0bXAxLCBudW1lciwgZGVub207XG4gICAgXG4gICAgaWYgKHMgPCAwKSB7ICAvLyByZWdpb24gMlxuICAgICAgdG1wMCA9IGEwMSArIGIwO1xuICAgICAgdG1wMSA9IGExMSArIGIxO1xuICAgICAgaWYgKHRtcDEgPiB0bXAwKSB7XG4gICAgICAgIG51bWVyID0gdG1wMSAtIHRtcDA7XG4gICAgICAgIGRlbm9tID0gYTAwIC0gMi4wKmEwMSArIGExMTtcbiAgICAgICAgaWYgKG51bWVyID49IGRlbm9tKSB7XG4gICAgICAgICAgcyA9IDE7XG4gICAgICAgICAgdCA9IDA7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBhMDAgKyAyLjAqYjAgKyBjO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMgPSBudW1lci9kZW5vbTtcbiAgICAgICAgICB0ID0gMSAtIHM7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBzKihhMDAqcyArIGEwMSp0ICsgMi4wKmIwKSArXG4gICAgICAgICAgdCooYTAxKnMgKyBhMTEqdCArIDIuMCpiMSkgKyBjO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzID0gMDtcbiAgICAgICAgaWYgKHRtcDEgPD0gMCkge1xuICAgICAgICAgIHQgPSAxO1xuICAgICAgICAgIHNxckRpc3RhbmNlID0gYTExICsgMi4wKmIxICsgYztcbiAgICAgICAgfSBlbHNlIGlmIChiMSA+PSAwKSB7XG4gICAgICAgICAgdCA9IDA7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBjO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHQgPSAtYjEvYTExO1xuICAgICAgICAgIHNxckRpc3RhbmNlID0gYjEqdCArIGM7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHQgPCAwKSB7ICAvLyByZWdpb24gNlxuICAgICAgdG1wMCA9IGEwMSArIGIxO1xuICAgICAgdG1wMSA9IGEwMCArIGIwO1xuICAgICAgaWYgKHRtcDEgPiB0bXAwKSB7XG4gICAgICAgIG51bWVyID0gdG1wMSAtIHRtcDA7XG4gICAgICAgIGRlbm9tID0gYTAwIC0gMi4wKmEwMSArIGExMTtcbiAgICAgICAgaWYgKG51bWVyID49IGRlbm9tKSB7XG4gICAgICAgICAgdCA9IDE7XG4gICAgICAgICAgcyA9IDA7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBhMTEgKyAyLjAqYjEgKyBjO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHQgPSBudW1lci9kZW5vbTtcbiAgICAgICAgICBzID0gMSAtIHQ7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBzKihhMDAqcyArIGEwMSp0ICsgMi4wKmIwKSArXG4gICAgICAgICAgdCooYTAxKnMgKyBhMTEqdCArIDIuMCpiMSkgKyBjO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0ID0gMDtcbiAgICAgICAgaWYgKHRtcDEgPD0gMCkge1xuICAgICAgICAgIHMgPSAxO1xuICAgICAgICAgIHNxckRpc3RhbmNlID0gYTAwICsgMi4wKmIwICsgYztcbiAgICAgICAgfSBlbHNlIGlmIChiMCA+PSAwKSB7XG4gICAgICAgICAgcyA9IDA7XG4gICAgICAgICAgc3FyRGlzdGFuY2UgPSBjO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMgPSAtYjAvYTAwO1xuICAgICAgICAgIHNxckRpc3RhbmNlID0gYjAqcyArIGM7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgeyAgLy8gcmVnaW9uIDFcbiAgICAgIG51bWVyID0gYTExICsgYjEgLSBhMDEgLSBiMDtcbiAgICAgIGlmIChudW1lciA8PSAwKSB7XG4gICAgICAgIHMgPSAwO1xuICAgICAgICB0ID0gMTtcbiAgICAgICAgc3FyRGlzdGFuY2UgPSBhMTEgKyAyLjAqYjEgKyBjO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGVub20gPSBhMDAgLSAyLjAqYTAxICsgYTExO1xuICAgICAgICBpZiAobnVtZXIgPj0gZGVub20pIHtcbiAgICAgICAgICBzID0gMTtcbiAgICAgICAgICB0ID0gMDtcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IGEwMCArIDIuMCpiMCArIGM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcyA9IG51bWVyL2Rlbm9tO1xuICAgICAgICAgIHQgPSAxIC0gcztcbiAgICAgICAgICBzcXJEaXN0YW5jZSA9IHMqKGEwMCpzICsgYTAxKnQgKyAyLjAqYjApICtcbiAgICAgICAgICB0KihhMDEqcyArIGExMSp0ICsgMi4wKmIxKSArIGM7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdmFyIHUgPSAxLjAgLSBzIC0gdDtcbiAgZm9yKHZhciBpPTA7IGk8cG9pbnQubGVuZ3RoOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSB1ICogVjBbaV0gKyBzICogVjFbaV0gKyB0ICogVjJbaV07XG4gIH1cbiAgaWYoc3FyRGlzdGFuY2UgPCAwKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgcmV0dXJuIHNxckRpc3RhbmNlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNsb3Nlc3RQb2ludDJkO1xuXG59LHt9XSw0ODI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8vIGNhY2hlZCBmcm9tIHdoYXRldmVyIGdsb2JhbCBpcyBwcmVzZW50IHNvIHRoYXQgdGVzdCBydW5uZXJzIHRoYXQgc3R1YiBpdFxuLy8gZG9uJ3QgYnJlYWsgdGhpbmdzLiAgQnV0IHdlIG5lZWQgdG8gd3JhcCBpdCBpbiBhIHRyeSBjYXRjaCBpbiBjYXNlIGl0IGlzXG4vLyB3cmFwcGVkIGluIHN0cmljdCBtb2RlIGNvZGUgd2hpY2ggZG9lc24ndCBkZWZpbmUgYW55IGdsb2JhbHMuICBJdCdzIGluc2lkZSBhXG4vLyBmdW5jdGlvbiBiZWNhdXNlIHRyeS9jYXRjaGVzIGRlb3B0aW1pemUgaW4gY2VydGFpbiBlbmdpbmVzLlxuXG52YXIgY2FjaGVkU2V0VGltZW91dDtcbnZhciBjYWNoZWRDbGVhclRpbWVvdXQ7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXRUaW1vdXQoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG5mdW5jdGlvbiBkZWZhdWx0Q2xlYXJUaW1lb3V0ICgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCcpO1xufVxuKGZ1bmN0aW9uICgpIHtcbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIHNldFRpbWVvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBkZWZhdWx0U2V0VGltb3V0O1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIGNsZWFyVGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gY2xlYXJUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICB9XG59ICgpKVxuZnVuY3Rpb24gcnVuVGltZW91dChmdW4pIHtcbiAgICBpZiAoY2FjaGVkU2V0VGltZW91dCA9PT0gc2V0VGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgLy8gaWYgc2V0VGltZW91dCB3YXNuJ3QgYXZhaWxhYmxlIGJ1dCB3YXMgbGF0dGVyIGRlZmluZWRcbiAgICBpZiAoKGNhY2hlZFNldFRpbWVvdXQgPT09IGRlZmF1bHRTZXRUaW1vdXQgfHwgIWNhY2hlZFNldFRpbWVvdXQpICYmIHNldFRpbWVvdXQpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIC8vIHdoZW4gd2hlbiBzb21lYm9keSBoYXMgc2NyZXdlZCB3aXRoIHNldFRpbWVvdXQgYnV0IG5vIEkuRS4gbWFkZG5lc3NcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9IGNhdGNoKGUpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgaW4gSS5FLiBidXQgdGhlIHNjcmlwdCBoYXMgYmVlbiBldmFsZWQgc28gSS5FLiBkb2Vzbid0IHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKG51bGwsIGZ1biwgMCk7XG4gICAgICAgIH0gY2F0Y2goZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvclxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbCh0aGlzLCBmdW4sIDApO1xuICAgICAgICB9XG4gICAgfVxuXG5cbn1cbmZ1bmN0aW9uIHJ1bkNsZWFyVGltZW91dChtYXJrZXIpIHtcbiAgICBpZiAoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBjbGVhclRpbWVvdXQpIHtcbiAgICAgICAgLy9ub3JtYWwgZW52aXJvbWVudHMgaW4gc2FuZSBzaXR1YXRpb25zXG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgLy8gaWYgY2xlYXJUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBkZWZhdWx0Q2xlYXJUaW1lb3V0IHx8ICFjYWNoZWRDbGVhclRpbWVvdXQpICYmIGNsZWFyVGltZW91dCkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfSBjYXRjaCAoZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgIHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwobnVsbCwgbWFya2VyKTtcbiAgICAgICAgfSBjYXRjaCAoZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvci5cbiAgICAgICAgICAgIC8vIFNvbWUgdmVyc2lvbnMgb2YgSS5FLiBoYXZlIGRpZmZlcmVudCBydWxlcyBmb3IgY2xlYXJUaW1lb3V0IHZzIHNldFRpbWVvdXRcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbCh0aGlzLCBtYXJrZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cblxufVxudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgaWYgKCFkcmFpbmluZyB8fCAhY3VycmVudFF1ZXVlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gcnVuVGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgcnVuQ2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgcnVuVGltZW91dChkcmFpblF1ZXVlKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kT25jZUxpc3RlbmVyID0gbm9vcDtcblxucHJvY2Vzcy5saXN0ZW5lcnMgPSBmdW5jdGlvbiAobmFtZSkgeyByZXR1cm4gW10gfVxuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcblxufSx7fV0sNDgzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnZ2wtcXVhdC9zbGVycCcpXG59LHtcImdsLXF1YXQvc2xlcnBcIjoyOTN9XSw0ODQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuKGZ1bmN0aW9uIChnbG9iYWwpe1xudmFyIG5vdyA9IF9kZXJlcV8oJ3BlcmZvcm1hbmNlLW5vdycpXG4gICwgcm9vdCA9IHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogd2luZG93XG4gICwgdmVuZG9ycyA9IFsnbW96JywgJ3dlYmtpdCddXG4gICwgc3VmZml4ID0gJ0FuaW1hdGlvbkZyYW1lJ1xuICAsIHJhZiA9IHJvb3RbJ3JlcXVlc3QnICsgc3VmZml4XVxuICAsIGNhZiA9IHJvb3RbJ2NhbmNlbCcgKyBzdWZmaXhdIHx8IHJvb3RbJ2NhbmNlbFJlcXVlc3QnICsgc3VmZml4XVxuXG5mb3IodmFyIGkgPSAwOyAhcmFmICYmIGkgPCB2ZW5kb3JzLmxlbmd0aDsgaSsrKSB7XG4gIHJhZiA9IHJvb3RbdmVuZG9yc1tpXSArICdSZXF1ZXN0JyArIHN1ZmZpeF1cbiAgY2FmID0gcm9vdFt2ZW5kb3JzW2ldICsgJ0NhbmNlbCcgKyBzdWZmaXhdXG4gICAgICB8fCByb290W3ZlbmRvcnNbaV0gKyAnQ2FuY2VsUmVxdWVzdCcgKyBzdWZmaXhdXG59XG5cbi8vIFNvbWUgdmVyc2lvbnMgb2YgRkYgaGF2ZSByQUYgYnV0IG5vdCBjQUZcbmlmKCFyYWYgfHwgIWNhZikge1xuICB2YXIgbGFzdCA9IDBcbiAgICAsIGlkID0gMFxuICAgICwgcXVldWUgPSBbXVxuICAgICwgZnJhbWVEdXJhdGlvbiA9IDEwMDAgLyA2MFxuXG4gIHJhZiA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYocXVldWUubGVuZ3RoID09PSAwKSB7XG4gICAgICB2YXIgX25vdyA9IG5vdygpXG4gICAgICAgICwgbmV4dCA9IE1hdGgubWF4KDAsIGZyYW1lRHVyYXRpb24gLSAoX25vdyAtIGxhc3QpKVxuICAgICAgbGFzdCA9IG5leHQgKyBfbm93XG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgY3AgPSBxdWV1ZS5zbGljZSgwKVxuICAgICAgICAvLyBDbGVhciBxdWV1ZSBoZXJlIHRvIHByZXZlbnRcbiAgICAgICAgLy8gY2FsbGJhY2tzIGZyb20gYXBwZW5kaW5nIGxpc3RlbmVyc1xuICAgICAgICAvLyB0byB0aGUgY3VycmVudCBmcmFtZSdzIHF1ZXVlXG4gICAgICAgIHF1ZXVlLmxlbmd0aCA9IDBcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYoIWNwW2ldLmNhbmNlbGxlZCkge1xuICAgICAgICAgICAgdHJ5e1xuICAgICAgICAgICAgICBjcFtpXS5jYWxsYmFjayhsYXN0KVxuICAgICAgICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IHRocm93IGUgfSwgMClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sIE1hdGgucm91bmQobmV4dCkpXG4gICAgfVxuICAgIHF1ZXVlLnB1c2goe1xuICAgICAgaGFuZGxlOiArK2lkLFxuICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrLFxuICAgICAgY2FuY2VsbGVkOiBmYWxzZVxuICAgIH0pXG4gICAgcmV0dXJuIGlkXG4gIH1cblxuICBjYWYgPSBmdW5jdGlvbihoYW5kbGUpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcXVldWUubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmKHF1ZXVlW2ldLmhhbmRsZSA9PT0gaGFuZGxlKSB7XG4gICAgICAgIHF1ZXVlW2ldLmNhbmNlbGxlZCA9IHRydWVcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihmbikge1xuICAvLyBXcmFwIGluIGEgbmV3IGZ1bmN0aW9uIHRvIHByZXZlbnRcbiAgLy8gYGNhbmNlbGAgcG90ZW50aWFsbHkgYmVpbmcgYXNzaWduZWRcbiAgLy8gdG8gdGhlIG5hdGl2ZSByQUYgZnVuY3Rpb25cbiAgcmV0dXJuIHJhZi5jYWxsKHJvb3QsIGZuKVxufVxubW9kdWxlLmV4cG9ydHMuY2FuY2VsID0gZnVuY3Rpb24oKSB7XG4gIGNhZi5hcHBseShyb290LCBhcmd1bWVudHMpXG59XG5tb2R1bGUuZXhwb3J0cy5wb2x5ZmlsbCA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICBpZiAoIW9iamVjdCkge1xuICAgIG9iamVjdCA9IHJvb3Q7XG4gIH1cbiAgb2JqZWN0LnJlcXVlc3RBbmltYXRpb25GcmFtZSA9IHJhZlxuICBvYmplY3QuY2FuY2VsQW5pbWF0aW9uRnJhbWUgPSBjYWZcbn1cblxufSkuY2FsbCh0aGlzLHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pXG59LHtcInBlcmZvcm1hbmNlLW5vd1wiOjQ2Mn1dLDQ4NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGJuYWRkID0gX2RlcmVxXygnYmlnLXJhdC9hZGQnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFkZFxuXG5mdW5jdGlvbiBhZGQgKGEsIGIpIHtcbiAgdmFyIG4gPSBhLmxlbmd0aFxuICB2YXIgciA9IG5ldyBBcnJheShuKVxuICBmb3IgKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcltpXSA9IGJuYWRkKGFbaV0sIGJbaV0pXG4gIH1cbiAgcmV0dXJuIHJcbn1cblxufSx7XCJiaWctcmF0L2FkZFwiOjc1fV0sNDg2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZsb2F0MnJhdFxuXG52YXIgcmF0ID0gX2RlcmVxXygnYmlnLXJhdCcpXG5cbmZ1bmN0aW9uIGZsb2F0MnJhdCh2KSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkodi5sZW5ndGgpXG4gIGZvcih2YXIgaT0wOyBpPHYubGVuZ3RoOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSByYXQodltpXSlcbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbn0se1wiYmlnLXJhdFwiOjc4fV0sNDg3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgcmF0ID0gX2RlcmVxXygnYmlnLXJhdCcpXG52YXIgbXVsID0gX2RlcmVxXygnYmlnLXJhdC9tdWwnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IG11bHNcblxuZnVuY3Rpb24gbXVscyhhLCB4KSB7XG4gIHZhciBzID0gcmF0KHgpXG4gIHZhciBuID0gYS5sZW5ndGhcbiAgdmFyIHIgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcltpXSA9IG11bChhW2ldLCBzKVxuICB9XG4gIHJldHVybiByXG59XG5cbn0se1wiYmlnLXJhdFwiOjc4LFwiYmlnLXJhdC9tdWxcIjo4N31dLDQ4ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxudmFyIGJuc3ViID0gX2RlcmVxXygnYmlnLXJhdC9zdWInKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHN1YlxuXG5mdW5jdGlvbiBzdWIoYSwgYikge1xuICB2YXIgbiA9IGEubGVuZ3RoXG4gIHZhciByID0gbmV3IEFycmF5KG4pXG4gICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcltpXSA9IGJuc3ViKGFbaV0sIGJbaV0pXG4gIH1cbiAgcmV0dXJuIHJcbn1cblxufSx7XCJiaWctcmF0L3N1YlwiOjg5fV0sNDg5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgY29tcGFyZUNlbGwgPSBfZGVyZXFfKCdjb21wYXJlLWNlbGwnKVxudmFyIGNvbXBhcmVPcmllbnRlZENlbGwgPSBfZGVyZXFfKCdjb21wYXJlLW9yaWVudGVkLWNlbGwnKVxudmFyIG9yaWVudGF0aW9uID0gX2RlcmVxXygnY2VsbC1vcmllbnRhdGlvbicpXG5cbm1vZHVsZS5leHBvcnRzID0gcmVkdWNlQ2VsbENvbXBsZXhcblxuZnVuY3Rpb24gcmVkdWNlQ2VsbENvbXBsZXgoY2VsbHMpIHtcbiAgY2VsbHMuc29ydChjb21wYXJlT3JpZW50ZWRDZWxsKVxuICB2YXIgbiA9IGNlbGxzLmxlbmd0aFxuICB2YXIgcHRyID0gMFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgdmFyIG8gPSBvcmllbnRhdGlvbihjKVxuICAgIGlmKG8gPT09IDApIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGlmKHB0ciA+IDApIHtcbiAgICAgIHZhciBmID0gY2VsbHNbcHRyLTFdXG4gICAgICBpZihjb21wYXJlQ2VsbChjLCBmKSA9PT0gMCAmJlxuICAgICAgICAgb3JpZW50YXRpb24oZikgICAgIT09IG8pIHtcbiAgICAgICAgcHRyIC09IDFcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICB9XG4gICAgY2VsbHNbcHRyKytdID0gY1xuICB9XG4gIGNlbGxzLmxlbmd0aCA9IHB0clxuICByZXR1cm4gY2VsbHNcbn1cblxufSx7XCJjZWxsLW9yaWVudGF0aW9uXCI6MTEyLFwiY29tcGFyZS1jZWxsXCI6MTI4LFwiY29tcGFyZS1vcmllbnRlZC1jZWxsXCI6MTI5fV0sNDkwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgZ2V0Qm91bmRzID0gX2RlcmVxXygnYXJyYXktYm91bmRzJylcbnZhciByZ2JhID0gX2RlcmVxXygnY29sb3Itbm9ybWFsaXplJylcbnZhciB1cGRhdGVEaWZmID0gX2RlcmVxXygndXBkYXRlLWRpZmYnKVxudmFyIHBpY2sgPSBfZGVyZXFfKCdwaWNrLWJ5LWFsaWFzJylcbnZhciBleHRlbmQgPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJylcbnZhciBmbGF0dGVuID0gX2RlcmVxXygnZmxhdHRlbi12ZXJ0ZXgtZGF0YScpXG52YXIgcmVmID0gX2RlcmVxXygndG8tZmxvYXQzMicpO1xudmFyIGZsb2F0MzIgPSByZWYuZmxvYXQzMjtcbnZhciBmcmFjdDMyID0gcmVmLmZyYWN0MzI7XG5cbm1vZHVsZS5leHBvcnRzID0gRXJyb3IyRFxuXG52YXIgV0VJR0hUUyA9IFtcblx0Ly9kaXJlY3Rpb24sIGxpbmVXaWR0aCBzaGlmdCwgY2FwU2l6ZSBzaGlmdFxuXG5cdC8vIHgtZXJyb3IgYmFyXG5cdFsxLCAwLCAwLCAxLCAwLCAwXSxcblx0WzEsIDAsIDAsIC0xLCAwLCAwXSxcblx0Wy0xLCAwLCAwLCAtMSwgMCwgMF0sXG5cblx0Wy0xLCAwLCAwLCAtMSwgMCwgMF0sXG5cdFstMSwgMCwgMCwgMSwgMCwgMF0sXG5cdFsxLCAwLCAwLCAxLCAwLCAwXSxcblxuXHQvLyB4LWVycm9yIHJpZ2h0IGNhcFxuXHRbMSwgMCwgLTEsIDAsIDAsIDFdLFxuXHRbMSwgMCwgLTEsIDAsIDAsIC0xXSxcblx0WzEsIDAsIDEsIDAsIDAsIC0xXSxcblxuXHRbMSwgMCwgMSwgMCwgMCwgLTFdLFxuXHRbMSwgMCwgMSwgMCwgMCwgMV0sXG5cdFsxLCAwLCAtMSwgMCwgMCwgMV0sXG5cblx0Ly8geC1lcnJvciBsZWZ0IGNhcFxuXHRbLTEsIDAsIC0xLCAwLCAwLCAxXSxcblx0Wy0xLCAwLCAtMSwgMCwgMCwgLTFdLFxuXHRbLTEsIDAsIDEsIDAsIDAsIC0xXSxcblxuXHRbLTEsIDAsIDEsIDAsIDAsIC0xXSxcblx0Wy0xLCAwLCAxLCAwLCAwLCAxXSxcblx0Wy0xLCAwLCAtMSwgMCwgMCwgMV0sXG5cblx0Ly8geS1lcnJvciBiYXJcblx0WzAsIDEsIDEsIDAsIDAsIDBdLFxuXHRbMCwgMSwgLTEsIDAsIDAsIDBdLFxuXHRbMCwgLTEsIC0xLCAwLCAwLCAwXSxcblxuXHRbMCwgLTEsIC0xLCAwLCAwLCAwXSxcblx0WzAsIDEsIDEsIDAsIDAsIDBdLFxuXHRbMCwgLTEsIDEsIDAsIDAsIDBdLFxuXG5cdC8vIHktZXJyb3IgdG9wIGNhcFxuXHRbMCwgMSwgMCwgLTEsIDEsIDBdLFxuXHRbMCwgMSwgMCwgLTEsIC0xLCAwXSxcblx0WzAsIDEsIDAsIDEsIC0xLCAwXSxcblxuXHRbMCwgMSwgMCwgMSwgMSwgMF0sXG5cdFswLCAxLCAwLCAtMSwgMSwgMF0sXG5cdFswLCAxLCAwLCAxLCAtMSwgMF0sXG5cblx0Ly8geS1lcnJvciBib3R0b20gY2FwXG5cdFswLCAtMSwgMCwgLTEsIDEsIDBdLFxuXHRbMCwgLTEsIDAsIC0xLCAtMSwgMF0sXG5cdFswLCAtMSwgMCwgMSwgLTEsIDBdLFxuXG5cdFswLCAtMSwgMCwgMSwgMSwgMF0sXG5cdFswLCAtMSwgMCwgLTEsIDEsIDBdLFxuXHRbMCwgLTEsIDAsIDEsIC0xLCAwXVxuXVxuXG5cbmZ1bmN0aW9uIEVycm9yMkQgKHJlZ2wsIG9wdGlvbnMpIHtcblx0aWYgKHR5cGVvZiByZWdsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0aWYgKCFvcHRpb25zKSB7IG9wdGlvbnMgPSB7fSB9XG5cdFx0b3B0aW9ucy5yZWdsID0gcmVnbFxuXHR9XG5cdGVsc2Uge1xuXHRcdG9wdGlvbnMgPSByZWdsXG5cdH1cblx0aWYgKG9wdGlvbnMubGVuZ3RoKSB7IG9wdGlvbnMucG9zaXRpb25zID0gb3B0aW9ucyB9XG5cdHJlZ2wgPSBvcHRpb25zLnJlZ2xcblxuXHRpZiAoIXJlZ2wuaGFzRXh0ZW5zaW9uKCdBTkdMRV9pbnN0YW5jZWRfYXJyYXlzJykpIHtcblx0XHR0aHJvdyBFcnJvcigncmVnbC1lcnJvcjJkOiBgQU5HTEVfaW5zdGFuY2VkX2FycmF5c2AgZXh0ZW5zaW9uIHNob3VsZCBiZSBlbmFibGVkJyk7XG5cdH1cblxuXHQvLyBwZXJzaXN0ZW50IHZhcmlhYmxlc1xuXHR2YXIgZ2wgPSByZWdsLl9nbCwgZHJhd0Vycm9ycywgcG9zaXRpb25CdWZmZXIsIHBvc2l0aW9uRnJhY3RCdWZmZXIsIGNvbG9yQnVmZmVyLCBlcnJvckJ1ZmZlciwgbWVzaEJ1ZmZlcixcblx0XHRcdGRlZmF1bHRzID0ge1xuXHRcdFx0XHRjb2xvcjogJ2JsYWNrJyxcblx0XHRcdFx0Y2FwU2l6ZTogNSxcblx0XHRcdFx0bGluZVdpZHRoOiAxLFxuXHRcdFx0XHRvcGFjaXR5OiAxLFxuXHRcdFx0XHR2aWV3cG9ydDogbnVsbCxcblx0XHRcdFx0cmFuZ2U6IG51bGwsXG5cdFx0XHRcdG9mZnNldDogMCxcblx0XHRcdFx0Y291bnQ6IDAsXG5cdFx0XHRcdGJvdW5kczogbnVsbCxcblx0XHRcdFx0cG9zaXRpb25zOiBbXSxcblx0XHRcdFx0ZXJyb3JzOiBbXVxuXHRcdFx0fSwgZ3JvdXBzID0gW11cblxuXHQvL2NvbG9yIHBlci1wb2ludFxuXHRjb2xvckJ1ZmZlciA9IHJlZ2wuYnVmZmVyKHtcblx0XHR1c2FnZTogJ2R5bmFtaWMnLFxuXHRcdHR5cGU6ICd1aW50OCcsXG5cdFx0ZGF0YTogbmV3IFVpbnQ4QXJyYXkoMClcblx0fSlcblx0Ly94eS1wb3NpdGlvbiBwZXItcG9pbnRcblx0cG9zaXRpb25CdWZmZXIgPSByZWdsLmJ1ZmZlcih7XG5cdFx0dXNhZ2U6ICdkeW5hbWljJyxcblx0XHR0eXBlOiAnZmxvYXQnLFxuXHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KDApXG5cdH0pXG5cdC8veHktcG9zaXRpb24gZmxvYXQzMi1mcmFjdGlvblxuXHRwb3NpdGlvbkZyYWN0QnVmZmVyID0gcmVnbC5idWZmZXIoe1xuXHRcdHVzYWdlOiAnZHluYW1pYycsXG5cdFx0dHlwZTogJ2Zsb2F0Jyxcblx0XHRkYXRhOiBuZXcgVWludDhBcnJheSgwKVxuXHR9KVxuXHQvLzQgZXJyb3JzIHBlci1wb2ludFxuXHRlcnJvckJ1ZmZlciA9IHJlZ2wuYnVmZmVyKHtcblx0XHR1c2FnZTogJ2R5bmFtaWMnLFxuXHRcdHR5cGU6ICdmbG9hdCcsXG5cdFx0ZGF0YTogbmV3IFVpbnQ4QXJyYXkoMClcblx0fSlcblx0Ly9lcnJvciBiYXIgbWVzaFxuXHRtZXNoQnVmZmVyID0gcmVnbC5idWZmZXIoe1xuXHRcdHVzYWdlOiAnc3RhdGljJyxcblx0XHR0eXBlOiAnZmxvYXQnLFxuXHRcdGRhdGE6IFdFSUdIVFNcblx0fSlcblxuXHR1cGRhdGUob3B0aW9ucylcblxuXHQvL2RyYXdpbmcgbWV0aG9kXG5cdGRyYXdFcnJvcnMgPSByZWdsKHtcblx0XHR2ZXJ0OiBcIlxcblxcdFxcdHByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG5cXG5cXHRcXHRhdHRyaWJ1dGUgdmVjMiBwb3NpdGlvbiwgcG9zaXRpb25GcmFjdDtcXG5cXHRcXHRhdHRyaWJ1dGUgdmVjNCBlcnJvcjtcXG5cXHRcXHRhdHRyaWJ1dGUgdmVjNCBjb2xvcjtcXG5cXG5cXHRcXHRhdHRyaWJ1dGUgdmVjMiBkaXJlY3Rpb24sIGxpbmVPZmZzZXQsIGNhcE9mZnNldDtcXG5cXG5cXHRcXHR1bmlmb3JtIHZlYzQgdmlld3BvcnQ7XFxuXFx0XFx0dW5pZm9ybSBmbG9hdCBsaW5lV2lkdGgsIGNhcFNpemU7XFxuXFx0XFx0dW5pZm9ybSB2ZWMyIHNjYWxlLCBzY2FsZUZyYWN0LCB0cmFuc2xhdGUsIHRyYW5zbGF0ZUZyYWN0O1xcblxcblxcdFxcdHZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxuXFxuXFx0XFx0dm9pZCBtYWluKCkge1xcblxcdFxcdFxcdGZyYWdDb2xvciA9IGNvbG9yIC8gMjU1LjtcXG5cXG5cXHRcXHRcXHR2ZWMyIHBpeGVsT2Zmc2V0ID0gbGluZVdpZHRoICogbGluZU9mZnNldCArIChjYXBTaXplICsgbGluZVdpZHRoKSAqIGNhcE9mZnNldDtcXG5cXG5cXHRcXHRcXHR2ZWMyIGR4eSA9IC1zdGVwKC41LCBkaXJlY3Rpb24ueHkpICogZXJyb3IueHogKyBzdGVwKGRpcmVjdGlvbi54eSwgdmVjMigtLjUpKSAqIGVycm9yLnl3O1xcblxcblxcdFxcdFxcdHZlYzIgcG9zaXRpb24gPSBwb3NpdGlvbiArIGR4eTtcXG5cXG5cXHRcXHRcXHR2ZWMyIHBvcyA9IChwb3NpdGlvbiArIHRyYW5zbGF0ZSkgKiBzY2FsZVxcblxcdFxcdFxcdFxcdCsgKHBvc2l0aW9uRnJhY3QgKyB0cmFuc2xhdGVGcmFjdCkgKiBzY2FsZVxcblxcdFxcdFxcdFxcdCsgKHBvc2l0aW9uICsgdHJhbnNsYXRlKSAqIHNjYWxlRnJhY3RcXG5cXHRcXHRcXHRcXHQrIChwb3NpdGlvbkZyYWN0ICsgdHJhbnNsYXRlRnJhY3QpICogc2NhbGVGcmFjdDtcXG5cXG5cXHRcXHRcXHRwb3MgKz0gcGl4ZWxPZmZzZXQgLyB2aWV3cG9ydC56dztcXG5cXG5cXHRcXHRcXHRnbF9Qb3NpdGlvbiA9IHZlYzQocG9zICogMi4gLSAxLiwgMCwgMSk7XFxuXFx0XFx0fVxcblxcdFxcdFwiLFxuXG5cdFx0ZnJhZzogXCJcXG5cXHRcXHRwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuXFxuXFx0XFx0dmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG5cXG5cXHRcXHR1bmlmb3JtIGZsb2F0IG9wYWNpdHk7XFxuXFxuXFx0XFx0dm9pZCBtYWluKCkge1xcblxcdFxcdFxcdGdsX0ZyYWdDb2xvciA9IGZyYWdDb2xvcjtcXG5cXHRcXHRcXHRnbF9GcmFnQ29sb3IuYSAqPSBvcGFjaXR5O1xcblxcdFxcdH1cXG5cXHRcXHRcIixcblxuXHRcdHVuaWZvcm1zOiB7XG5cdFx0XHRyYW5nZTogcmVnbC5wcm9wKCdyYW5nZScpLFxuXHRcdFx0bGluZVdpZHRoOiByZWdsLnByb3AoJ2xpbmVXaWR0aCcpLFxuXHRcdFx0Y2FwU2l6ZTogcmVnbC5wcm9wKCdjYXBTaXplJyksXG5cdFx0XHRvcGFjaXR5OiByZWdsLnByb3AoJ29wYWNpdHknKSxcblx0XHRcdHNjYWxlOiByZWdsLnByb3AoJ3NjYWxlJyksXG5cdFx0XHR0cmFuc2xhdGU6IHJlZ2wucHJvcCgndHJhbnNsYXRlJyksXG5cdFx0XHRzY2FsZUZyYWN0OiByZWdsLnByb3AoJ3NjYWxlRnJhY3QnKSxcblx0XHRcdHRyYW5zbGF0ZUZyYWN0OiByZWdsLnByb3AoJ3RyYW5zbGF0ZUZyYWN0JyksXG5cdFx0XHR2aWV3cG9ydDogZnVuY3Rpb24gKGN0eCwgcHJvcCkgeyByZXR1cm4gW3Byb3Audmlld3BvcnQueCwgcHJvcC52aWV3cG9ydC55LCBjdHgudmlld3BvcnRXaWR0aCwgY3R4LnZpZXdwb3J0SGVpZ2h0XTsgfVxuXHRcdH0sXG5cblx0XHRhdHRyaWJ1dGVzOiB7XG5cdFx0XHQvL2R5bmFtaWMgYXR0cmlidXRlc1xuXHRcdFx0Y29sb3I6IHtcblx0XHRcdFx0YnVmZmVyOiBjb2xvckJ1ZmZlcixcblx0XHRcdFx0b2Zmc2V0OiBmdW5jdGlvbiAoY3R4LCBwcm9wKSB7IHJldHVybiBwcm9wLm9mZnNldCAqIDQ7IH0sXG5cdFx0XHRcdGRpdmlzb3I6IDEsXG5cdFx0XHR9LFxuXHRcdFx0cG9zaXRpb246IHtcblx0XHRcdFx0YnVmZmVyOiBwb3NpdGlvbkJ1ZmZlcixcblx0XHRcdFx0b2Zmc2V0OiBmdW5jdGlvbiAoY3R4LCBwcm9wKSB7IHJldHVybiBwcm9wLm9mZnNldCAqIDg7IH0sXG5cdFx0XHRcdGRpdmlzb3I6IDFcblx0XHRcdH0sXG5cdFx0XHRwb3NpdGlvbkZyYWN0OiB7XG5cdFx0XHRcdGJ1ZmZlcjogcG9zaXRpb25GcmFjdEJ1ZmZlcixcblx0XHRcdFx0b2Zmc2V0OiBmdW5jdGlvbiAoY3R4LCBwcm9wKSB7IHJldHVybiBwcm9wLm9mZnNldCAqIDg7IH0sXG5cdFx0XHRcdGRpdmlzb3I6IDFcblx0XHRcdH0sXG5cdFx0XHRlcnJvcjoge1xuXHRcdFx0XHRidWZmZXI6IGVycm9yQnVmZmVyLFxuXHRcdFx0XHRvZmZzZXQ6IGZ1bmN0aW9uIChjdHgsIHByb3ApIHsgcmV0dXJuIHByb3Aub2Zmc2V0ICogMTY7IH0sXG5cdFx0XHRcdGRpdmlzb3I6IDFcblx0XHRcdH0sXG5cblx0XHRcdC8vc3RhdGljIGF0dHJpYnV0ZXNcblx0XHRcdGRpcmVjdGlvbjoge1xuXHRcdFx0XHRidWZmZXI6IG1lc2hCdWZmZXIsXG5cdFx0XHRcdHN0cmlkZTogMjQsXG5cdFx0XHRcdG9mZnNldDogMFxuXHRcdFx0fSxcblx0XHRcdGxpbmVPZmZzZXQ6IHtcblx0XHRcdFx0YnVmZmVyOiBtZXNoQnVmZmVyLFxuXHRcdFx0XHRzdHJpZGU6IDI0LFxuXHRcdFx0XHRvZmZzZXQ6IDhcblx0XHRcdH0sXG5cdFx0XHRjYXBPZmZzZXQ6IHtcblx0XHRcdFx0YnVmZmVyOiBtZXNoQnVmZmVyLFxuXHRcdFx0XHRzdHJpZGU6IDI0LFxuXHRcdFx0XHRvZmZzZXQ6IDE2XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdHByaW1pdGl2ZTogJ3RyaWFuZ2xlcycsXG5cblx0XHRibGVuZDoge1xuXHRcdFx0ZW5hYmxlOiB0cnVlLFxuXHRcdFx0Y29sb3I6IFswLDAsMCwwXSxcblx0XHRcdGVxdWF0aW9uOiB7XG5cdFx0XHRcdHJnYjogJ2FkZCcsXG5cdFx0XHRcdGFscGhhOiAnYWRkJ1xuXHRcdFx0fSxcblx0XHRcdGZ1bmM6IHtcblx0XHRcdFx0c3JjUkdCOiAnc3JjIGFscGhhJyxcblx0XHRcdFx0ZHN0UkdCOiAnb25lIG1pbnVzIHNyYyBhbHBoYScsXG5cdFx0XHRcdHNyY0FscGhhOiAnb25lIG1pbnVzIGRzdCBhbHBoYScsXG5cdFx0XHRcdGRzdEFscGhhOiAnb25lJ1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRkZXB0aDoge1xuXHRcdFx0ZW5hYmxlOiBmYWxzZVxuXHRcdH0sXG5cblx0XHRzY2lzc29yOiB7XG5cdFx0XHRlbmFibGU6IHRydWUsXG5cdFx0XHRib3g6IHJlZ2wucHJvcCgndmlld3BvcnQnKVxuXHRcdH0sXG5cdFx0dmlld3BvcnQ6IHJlZ2wucHJvcCgndmlld3BvcnQnKSxcblx0XHRzdGVuY2lsOiBmYWxzZSxcblxuXHRcdGluc3RhbmNlczogcmVnbC5wcm9wKCdjb3VudCcpLFxuXHRcdGNvdW50OiBXRUlHSFRTLmxlbmd0aFxuXHR9KVxuXG5cdC8vZXhwb3NlIEFQSVxuXHRleHRlbmQoZXJyb3IyZCwge1xuXHRcdHVwZGF0ZTogdXBkYXRlLFxuXHRcdGRyYXc6IGRyYXcsXG5cdFx0ZGVzdHJveTogZGVzdHJveSxcblx0XHRyZWdsOiByZWdsLFxuXHRcdGdsOiBnbCxcblx0XHRjYW52YXM6IGdsLmNhbnZhcyxcblx0XHRncm91cHM6IGdyb3Vwc1xuXHR9KVxuXG5cdHJldHVybiBlcnJvcjJkXG5cblx0ZnVuY3Rpb24gZXJyb3IyZCAob3B0cykge1xuXHRcdC8vdXBkYXRlXG5cdFx0aWYgKG9wdHMpIHtcblx0XHRcdHVwZGF0ZShvcHRzKVxuXHRcdH1cblxuXHRcdC8vZGVzdHJveVxuXHRcdGVsc2UgaWYgKG9wdHMgPT09IG51bGwpIHtcblx0XHRcdGRlc3Ryb3koKVxuXHRcdH1cblxuXHRcdGRyYXcoKVxuXHR9XG5cblxuXHQvL21haW4gZHJhdyBtZXRob2Rcblx0ZnVuY3Rpb24gZHJhdyAob3B0aW9ucykge1xuXHRcdGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ251bWJlcicpIHsgcmV0dXJuIGRyYXdHcm91cChvcHRpb25zKSB9XG5cblx0XHQvL21ha2Ugb3B0aW9ucyBhIGJhdGNoXG5cdFx0aWYgKG9wdGlvbnMgJiYgIUFycmF5LmlzQXJyYXkob3B0aW9ucykpIHsgb3B0aW9ucyA9IFtvcHRpb25zXSB9XG5cblxuXHRcdHJlZ2wuX3JlZnJlc2goKVxuXG5cdFx0Ly9yZW5kZXIgbXVsdGlwbGUgcG9seWxpbmVzIHZpYSByZWdsIGJhdGNoXG5cdFx0Z3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHMsIGkpIHtcblx0XHRcdGlmICghcykgeyByZXR1cm4gfVxuXG5cdFx0XHRpZiAob3B0aW9ucykge1xuXHRcdFx0XHRpZiAoIW9wdGlvbnNbaV0pIHsgcy5kcmF3ID0gZmFsc2UgfVxuXHRcdFx0XHRlbHNlIHsgcy5kcmF3ID0gdHJ1ZSB9XG5cdFx0XHR9XG5cblx0XHRcdC8vaWdub3JlIGRyYXcgZmxhZyBmb3Igb25lIHBhc3Ncblx0XHRcdGlmICghcy5kcmF3KSB7XG5cdFx0XHRcdHMuZHJhdyA9IHRydWU7XG5cdFx0XHRcdHJldHVyblxuXHRcdFx0fVxuXG5cdFx0XHRkcmF3R3JvdXAoaSlcblx0XHR9KVxuXHR9XG5cblx0Ly9kcmF3IHNpbmdsZSBlcnJvciBncm91cCBieSBpZFxuXHRmdW5jdGlvbiBkcmF3R3JvdXAgKHMpIHtcblx0XHRpZiAodHlwZW9mIHMgPT09ICdudW1iZXInKSB7IHMgPSBncm91cHNbc10gfVxuXHRcdGlmIChzID09IG51bGwpIHsgcmV0dXJuIH1cblxuXHRcdGlmICghKHMgJiYgcy5jb3VudCAmJiBzLmNvbG9yICYmIHMub3BhY2l0eSAmJiBzLnBvc2l0aW9ucyAmJiBzLnBvc2l0aW9ucy5sZW5ndGggPiAxKSkgeyByZXR1cm4gfVxuXG5cdFx0cy5zY2FsZVJhdGlvID0gW1xuXHRcdFx0cy5zY2FsZVswXSAqIHMudmlld3BvcnQud2lkdGgsXG5cdFx0XHRzLnNjYWxlWzFdICogcy52aWV3cG9ydC5oZWlnaHRcblx0XHRdXG5cblx0XHRkcmF3RXJyb3JzKHMpXG5cblx0XHRpZiAocy5hZnRlcikgeyBzLmFmdGVyKHMpIH1cblx0fVxuXG5cdGZ1bmN0aW9uIHVwZGF0ZSAob3B0aW9ucykge1xuXHRcdGlmICghb3B0aW9ucykgeyByZXR1cm4gfVxuXG5cdFx0Ly9kaXJlY3QgcG9pbnRzIGFyZ3VtZW50XG5cdFx0aWYgKG9wdGlvbnMubGVuZ3RoICE9IG51bGwpIHtcblx0XHRcdGlmICh0eXBlb2Ygb3B0aW9uc1swXSA9PT0gJ251bWJlcicpIHsgb3B0aW9ucyA9IFt7cG9zaXRpb25zOiBvcHRpb25zfV0gfVxuXHRcdH1cblxuXHRcdC8vbWFrZSBvcHRpb25zIGEgYmF0Y2hcblx0XHRlbHNlIGlmICghQXJyYXkuaXNBcnJheShvcHRpb25zKSkgeyBvcHRpb25zID0gW29wdGlvbnNdIH1cblxuXHRcdC8vZ2xvYmFsIGNvdW50IG9mIHBvaW50c1xuXHRcdHZhciBwb2ludENvdW50ID0gMCwgZXJyb3JDb3VudCA9IDBcblxuXHRcdGVycm9yMmQuZ3JvdXBzID0gZ3JvdXBzID0gb3B0aW9ucy5tYXAoZnVuY3Rpb24gKG9wdGlvbnMsIGkpIHtcblx0XHRcdHZhciBncm91cCA9IGdyb3Vwc1tpXVxuXG5cdFx0XHRpZiAoIW9wdGlvbnMpIHsgcmV0dXJuIGdyb3VwIH1cblx0XHRcdGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnZnVuY3Rpb24nKSB7IG9wdGlvbnMgPSB7YWZ0ZXI6IG9wdGlvbnN9IH1cblx0XHRcdGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zWzBdID09PSAnbnVtYmVyJykgeyBvcHRpb25zID0ge3Bvc2l0aW9uczogb3B0aW9uc30gfVxuXG5cdFx0XHQvL2NvcHkgb3B0aW9ucyB0byBhdm9pZCBtdXRhdGlvbiAmIGhhbmRsZSBhbGlhc2VzXG5cdFx0XHRvcHRpb25zID0gcGljayhvcHRpb25zLCB7XG5cdFx0XHRcdGNvbG9yOiAnY29sb3IgY29sb3JzIGZpbGwnLFxuXHRcdFx0XHRjYXBTaXplOiAnY2FwU2l6ZSBjYXAgY2Fwc2l6ZSBjYXAtc2l6ZScsXG5cdFx0XHRcdGxpbmVXaWR0aDogJ2xpbmVXaWR0aCBsaW5lLXdpZHRoIHdpZHRoIGxpbmUgdGhpY2tuZXNzJyxcblx0XHRcdFx0b3BhY2l0eTogJ29wYWNpdHkgYWxwaGEnLFxuXHRcdFx0XHRyYW5nZTogJ3JhbmdlIGRhdGFCb3gnLFxuXHRcdFx0XHR2aWV3cG9ydDogJ3ZpZXdwb3J0IHZpZXdCb3gnLFxuXHRcdFx0XHRlcnJvcnM6ICdlcnJvcnMgZXJyb3InLFxuXHRcdFx0XHRwb3NpdGlvbnM6ICdwb3NpdGlvbnMgcG9zaXRpb24gZGF0YSBwb2ludHMnXG5cdFx0XHR9KVxuXG5cdFx0XHRpZiAoIWdyb3VwKSB7XG5cdFx0XHRcdGdyb3Vwc1tpXSA9IGdyb3VwID0ge1xuXHRcdFx0XHRcdGlkOiBpLFxuXHRcdFx0XHRcdHNjYWxlOiBudWxsLFxuXHRcdFx0XHRcdHRyYW5zbGF0ZTogbnVsbCxcblx0XHRcdFx0XHRzY2FsZUZyYWN0OiBudWxsLFxuXHRcdFx0XHRcdHRyYW5zbGF0ZUZyYWN0OiBudWxsLFxuXHRcdFx0XHRcdGRyYXc6IHRydWVcblx0XHRcdFx0fVxuXHRcdFx0XHRvcHRpb25zID0gZXh0ZW5kKHt9LCBkZWZhdWx0cywgb3B0aW9ucylcblx0XHRcdH1cblxuXHRcdFx0dXBkYXRlRGlmZihncm91cCwgb3B0aW9ucywgW3tcblx0XHRcdFx0bGluZVdpZHRoOiBmdW5jdGlvbiAodikgeyByZXR1cm4gK3YgKiAuNTsgfSxcblx0XHRcdFx0Y2FwU2l6ZTogZnVuY3Rpb24gKHYpIHsgcmV0dXJuICt2ICogLjU7IH0sXG5cdFx0XHRcdG9wYWNpdHk6IHBhcnNlRmxvYXQsXG5cdFx0XHRcdGVycm9yczogZnVuY3Rpb24gKGVycm9ycykge1xuXHRcdFx0XHRcdGVycm9ycyA9IGZsYXR0ZW4oZXJyb3JzKVxuXG5cdFx0XHRcdFx0ZXJyb3JDb3VudCArPSBlcnJvcnMubGVuZ3RoXG5cdFx0XHRcdFx0cmV0dXJuIGVycm9yc1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRwb3NpdGlvbnM6IGZ1bmN0aW9uIChwb3NpdGlvbnMsIHN0YXRlKSB7XG5cdFx0XHRcdFx0cG9zaXRpb25zID0gZmxhdHRlbihwb3NpdGlvbnMsICdmbG9hdDY0Jylcblx0XHRcdFx0XHRzdGF0ZS5jb3VudCA9IE1hdGguZmxvb3IocG9zaXRpb25zLmxlbmd0aCAvIDIpXG5cdFx0XHRcdFx0c3RhdGUuYm91bmRzID0gZ2V0Qm91bmRzKHBvc2l0aW9ucywgMilcblx0XHRcdFx0XHRzdGF0ZS5vZmZzZXQgPSBwb2ludENvdW50XG5cblx0XHRcdFx0XHRwb2ludENvdW50ICs9IHN0YXRlLmNvdW50XG5cblx0XHRcdFx0XHRyZXR1cm4gcG9zaXRpb25zXG5cdFx0XHRcdH1cblx0XHRcdH0sIHtcblx0XHRcdFx0Y29sb3I6IGZ1bmN0aW9uIChjb2xvcnMsIHN0YXRlKSB7XG5cdFx0XHRcdFx0dmFyIGNvdW50ID0gc3RhdGUuY291bnRcblxuXHRcdFx0XHRcdGlmICghY29sb3JzKSB7IGNvbG9ycyA9ICd0cmFuc3BhcmVudCcgfVxuXG5cdFx0XHRcdFx0Ly8gJ2JsYWNrJyBvciBbMCwwLDAsMF0gY2FzZVxuXHRcdFx0XHRcdGlmICghQXJyYXkuaXNBcnJheShjb2xvcnMpIHx8IHR5cGVvZiBjb2xvcnNbMF0gPT09ICdudW1iZXInKSB7XG5cdFx0XHRcdFx0XHR2YXIgY29sb3IgPSBjb2xvcnNcblx0XHRcdFx0XHRcdGNvbG9ycyA9IEFycmF5KGNvdW50KVxuXHRcdFx0XHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG5cdFx0XHRcdFx0XHRcdGNvbG9yc1tpXSA9IGNvbG9yXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKGNvbG9ycy5sZW5ndGggPCBjb3VudCkgeyB0aHJvdyBFcnJvcignTm90IGVub3VnaCBjb2xvcnMnKSB9XG5cblx0XHRcdFx0XHR2YXIgY29sb3JEYXRhID0gbmV3IFVpbnQ4QXJyYXkoY291bnQgKiA0KVxuXG5cdFx0XHRcdFx0Ly9jb252ZXJ0IGNvbG9ycyB0byBmbG9hdCBhcnJheXNcblx0XHRcdFx0XHRmb3IgKHZhciBpJDEgPSAwOyBpJDEgPCBjb3VudDsgaSQxKyspIHtcblx0XHRcdFx0XHRcdHZhciBjID0gcmdiYShjb2xvcnNbaSQxXSwgJ3VpbnQ4Jylcblx0XHRcdFx0XHRcdGNvbG9yRGF0YS5zZXQoYywgaSQxICogNClcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4gY29sb3JEYXRhXG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0cmFuZ2U6IGZ1bmN0aW9uIChyYW5nZSwgc3RhdGUsIG9wdGlvbnMpIHtcblx0XHRcdFx0XHR2YXIgYm91bmRzID0gc3RhdGUuYm91bmRzXG5cdFx0XHRcdFx0aWYgKCFyYW5nZSkgeyByYW5nZSA9IGJvdW5kcyB9XG5cblx0XHRcdFx0XHRzdGF0ZS5zY2FsZSA9IFsxIC8gKHJhbmdlWzJdIC0gcmFuZ2VbMF0pLCAxIC8gKHJhbmdlWzNdIC0gcmFuZ2VbMV0pXVxuXHRcdFx0XHRcdHN0YXRlLnRyYW5zbGF0ZSA9IFstcmFuZ2VbMF0sIC1yYW5nZVsxXV1cblxuXHRcdFx0XHRcdHN0YXRlLnNjYWxlRnJhY3QgPSBmcmFjdDMyKHN0YXRlLnNjYWxlKVxuXHRcdFx0XHRcdHN0YXRlLnRyYW5zbGF0ZUZyYWN0ID0gZnJhY3QzMihzdGF0ZS50cmFuc2xhdGUpXG5cblx0XHRcdFx0XHRyZXR1cm4gcmFuZ2Vcblx0XHRcdFx0fSxcblxuXHRcdFx0XHR2aWV3cG9ydDogZnVuY3Rpb24gKHZwKSB7XG5cdFx0XHRcdFx0dmFyIHZpZXdwb3J0XG5cblx0XHRcdFx0XHRpZiAoQXJyYXkuaXNBcnJheSh2cCkpIHtcblx0XHRcdFx0XHRcdHZpZXdwb3J0ID0ge1xuXHRcdFx0XHRcdFx0XHR4OiB2cFswXSxcblx0XHRcdFx0XHRcdFx0eTogdnBbMV0sXG5cdFx0XHRcdFx0XHRcdHdpZHRoOiB2cFsyXSAtIHZwWzBdLFxuXHRcdFx0XHRcdFx0XHRoZWlnaHQ6IHZwWzNdIC0gdnBbMV1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSBpZiAodnApIHtcblx0XHRcdFx0XHRcdHZpZXdwb3J0ID0ge1xuXHRcdFx0XHRcdFx0XHR4OiB2cC54IHx8IHZwLmxlZnQgfHwgMCxcblx0XHRcdFx0XHRcdFx0eTogdnAueSB8fCB2cC50b3AgfHwgMFxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZiAodnAucmlnaHQpIHsgdmlld3BvcnQud2lkdGggPSB2cC5yaWdodCAtIHZpZXdwb3J0LnggfVxuXHRcdFx0XHRcdFx0ZWxzZSB7IHZpZXdwb3J0LndpZHRoID0gdnAudyB8fCB2cC53aWR0aCB8fCAwIH1cblxuXHRcdFx0XHRcdFx0aWYgKHZwLmJvdHRvbSkgeyB2aWV3cG9ydC5oZWlnaHQgPSB2cC5ib3R0b20gLSB2aWV3cG9ydC55IH1cblx0XHRcdFx0XHRcdGVsc2UgeyB2aWV3cG9ydC5oZWlnaHQgPSB2cC5oIHx8IHZwLmhlaWdodCB8fCAwIH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHR2aWV3cG9ydCA9IHtcblx0XHRcdFx0XHRcdFx0eDogMCwgeTogMCxcblx0XHRcdFx0XHRcdFx0d2lkdGg6IGdsLmRyYXdpbmdCdWZmZXJXaWR0aCxcblx0XHRcdFx0XHRcdFx0aGVpZ2h0OiBnbC5kcmF3aW5nQnVmZmVySGVpZ2h0XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cmV0dXJuIHZpZXdwb3J0XG5cdFx0XHRcdH1cblx0XHRcdH1dKVxuXG5cdFx0XHRyZXR1cm4gZ3JvdXBcblx0XHR9KVxuXG5cdFx0aWYgKHBvaW50Q291bnQgfHwgZXJyb3JDb3VudCkge1xuXHRcdFx0dmFyIGxlbiA9IGdyb3Vwcy5yZWR1Y2UoZnVuY3Rpb24gKGFjYywgZ3JvdXAsIGkpIHtcblx0XHRcdFx0cmV0dXJuIGFjYyArIChncm91cCA/IGdyb3VwLmNvdW50IDogMClcblx0XHRcdH0sIDApXG5cblx0XHRcdHZhciBwb3NpdGlvbkRhdGEgPSBuZXcgRmxvYXQ2NEFycmF5KGxlbiAqIDIpXG5cdFx0XHR2YXIgY29sb3JEYXRhID0gbmV3IFVpbnQ4QXJyYXkobGVuICogNClcblx0XHRcdHZhciBlcnJvckRhdGEgPSBuZXcgRmxvYXQzMkFycmF5KGxlbiAqIDQpXG5cblx0XHRcdGdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChncm91cCwgaSkge1xuXHRcdFx0XHRpZiAoIWdyb3VwKSB7IHJldHVybiB9XG5cdFx0XHRcdHZhciBwb3NpdGlvbnMgPSBncm91cC5wb3NpdGlvbnM7XG5cdFx0XHRcdHZhciBjb3VudCA9IGdyb3VwLmNvdW50O1xuXHRcdFx0XHR2YXIgb2Zmc2V0ID0gZ3JvdXAub2Zmc2V0O1xuXHRcdFx0XHR2YXIgY29sb3IgPSBncm91cC5jb2xvcjtcblx0XHRcdFx0dmFyIGVycm9ycyA9IGdyb3VwLmVycm9ycztcblx0XHRcdFx0aWYgKCFjb3VudCkgeyByZXR1cm4gfVxuXG5cdFx0XHRcdGNvbG9yRGF0YS5zZXQoY29sb3IsIG9mZnNldCAqIDQpXG5cdFx0XHRcdGVycm9yRGF0YS5zZXQoZXJyb3JzLCBvZmZzZXQgKiA0KVxuXHRcdFx0XHRwb3NpdGlvbkRhdGEuc2V0KHBvc2l0aW9ucywgb2Zmc2V0ICogMilcblx0XHRcdH0pXG5cblx0XHRcdHBvc2l0aW9uQnVmZmVyKGZsb2F0MzIocG9zaXRpb25EYXRhKSlcblx0XHRcdHBvc2l0aW9uRnJhY3RCdWZmZXIoZnJhY3QzMihwb3NpdGlvbkRhdGEpKVxuXHRcdFx0Y29sb3JCdWZmZXIoY29sb3JEYXRhKVxuXHRcdFx0ZXJyb3JCdWZmZXIoZXJyb3JEYXRhKVxuXHRcdH1cblxuXHR9XG5cblx0ZnVuY3Rpb24gZGVzdHJveSAoKSB7XG5cdFx0cG9zaXRpb25CdWZmZXIuZGVzdHJveSgpXG5cdFx0cG9zaXRpb25GcmFjdEJ1ZmZlci5kZXN0cm95KClcblx0XHRjb2xvckJ1ZmZlci5kZXN0cm95KClcblx0XHRlcnJvckJ1ZmZlci5kZXN0cm95KClcblx0XHRtZXNoQnVmZmVyLmRlc3Ryb3koKVxuXHR9XG59XG5cbn0se1wiYXJyYXktYm91bmRzXCI6NjUsXCJjb2xvci1ub3JtYWxpemVcIjoxMjAsXCJmbGF0dGVuLXZlcnRleC1kYXRhXCI6MjI3LFwib2JqZWN0LWFzc2lnblwiOjQ1NCxcInBpY2stYnktYWxpYXNcIjo0NjUsXCJ0by1mbG9hdDMyXCI6NTM4LFwidXBkYXRlLWRpZmZcIjo1NDl9XSw0OTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cblxudmFyIHJnYmEgPSBfZGVyZXFfKCdjb2xvci1ub3JtYWxpemUnKVxudmFyIGdldEJvdW5kcyA9IF9kZXJlcV8oJ2FycmF5LWJvdW5kcycpXG52YXIgZXh0ZW5kID0gX2RlcmVxXygnb2JqZWN0LWFzc2lnbicpXG52YXIgZ2xzbGlmeSA9IF9kZXJlcV8oJ2dsc2xpZnknKVxudmFyIHBpY2sgPSBfZGVyZXFfKCdwaWNrLWJ5LWFsaWFzJylcbnZhciBmbGF0dGVuID0gX2RlcmVxXygnZmxhdHRlbi12ZXJ0ZXgtZGF0YScpXG52YXIgdHJpYW5ndWxhdGUgPSBfZGVyZXFfKCdlYXJjdXQnKVxudmFyIG5vcm1hbGl6ZSA9IF9kZXJlcV8oJ2FycmF5LW5vcm1hbGl6ZScpXG52YXIgcmVmID0gX2RlcmVxXygndG8tZmxvYXQzMicpO1xudmFyIGZsb2F0MzIgPSByZWYuZmxvYXQzMjtcbnZhciBmcmFjdDMyID0gcmVmLmZyYWN0MzI7XG52YXIgV2Vha01hcCA9IF9kZXJlcV8oJ2VzNi13ZWFrLW1hcCcpXG52YXIgcGFyc2VSZWN0ID0gX2RlcmVxXygncGFyc2UtcmVjdCcpXG5cblxubW9kdWxlLmV4cG9ydHMgPSBMaW5lMkRcblxuXG4vKiogQGNvbnN0cnVjdG9yICovXG5mdW5jdGlvbiBMaW5lMkQgKHJlZ2wsIG9wdGlvbnMpIHtcblx0aWYgKCEodGhpcyBpbnN0YW5jZW9mIExpbmUyRCkpIHsgcmV0dXJuIG5ldyBMaW5lMkQocmVnbCwgb3B0aW9ucykgfVxuXG5cdGlmICh0eXBlb2YgcmVnbCA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdGlmICghb3B0aW9ucykgeyBvcHRpb25zID0ge30gfVxuXHRcdG9wdGlvbnMucmVnbCA9IHJlZ2xcblx0fVxuXHRlbHNlIHtcblx0XHRvcHRpb25zID0gcmVnbFxuXHR9XG5cdGlmIChvcHRpb25zLmxlbmd0aCkgeyBvcHRpb25zLnBvc2l0aW9ucyA9IG9wdGlvbnMgfVxuXHRyZWdsID0gb3B0aW9ucy5yZWdsXG5cblx0aWYgKCFyZWdsLmhhc0V4dGVuc2lvbignQU5HTEVfaW5zdGFuY2VkX2FycmF5cycpKSB7XG5cdFx0dGhyb3cgRXJyb3IoJ3JlZ2wtZXJyb3IyZDogYEFOR0xFX2luc3RhbmNlZF9hcnJheXNgIGV4dGVuc2lvbiBzaG91bGQgYmUgZW5hYmxlZCcpO1xuXHR9XG5cblx0Ly8gcGVyc2lzdGVudCB2YXJpYWJsZXNcblx0dGhpcy5nbCA9IHJlZ2wuX2dsXG5cdHRoaXMucmVnbCA9IHJlZ2xcblxuXHQvLyBsaXN0IG9mIG9wdGlvbnMgZm9yIGxpbmVzXG5cdHRoaXMucGFzc2VzID0gW11cblxuXHQvLyBjYWNoZWQgc2hhZGVycyBpbnN0YW5jZVxuXHR0aGlzLnNoYWRlcnMgPSBMaW5lMkQuc2hhZGVycy5oYXMocmVnbCkgPyBMaW5lMkQuc2hhZGVycy5nZXQocmVnbCkgOiBMaW5lMkQuc2hhZGVycy5zZXQocmVnbCwgTGluZTJELmNyZWF0ZVNoYWRlcnMocmVnbCkpLmdldChyZWdsKVxuXG5cblx0Ly8gaW5pdCBkZWZhdWx0c1xuXHR0aGlzLnVwZGF0ZShvcHRpb25zKVxufVxuXG5cbkxpbmUyRC5kYXNoTXVsdCA9IDJcbkxpbmUyRC5tYXhQYXR0ZXJuTGVuZ3RoID0gMjU2XG5MaW5lMkQucHJlY2lzaW9uVGhyZXNob2xkID0gM2U2XG5MaW5lMkQubWF4UG9pbnRzID0gMWU0XG5MaW5lMkQubWF4TGluZXMgPSAyMDQ4XG5cblxuLy8gY2FjaGUgb2YgY3JlYXRlZCBkcmF3IGNhbGxzIHBlci1yZWdsIGluc3RhbmNlXG5MaW5lMkQuc2hhZGVycyA9IG5ldyBXZWFrTWFwKClcblxuXG4vLyBjcmVhdGUgc3RhdGljIHNoYWRlcnMgb25jZVxuTGluZTJELmNyZWF0ZVNoYWRlcnMgPSBmdW5jdGlvbiAocmVnbCkge1xuXHR2YXIgb2Zmc2V0QnVmZmVyID0gcmVnbC5idWZmZXIoe1xuXHRcdHVzYWdlOiAnc3RhdGljJyxcblx0XHR0eXBlOiAnZmxvYXQnLFxuXHRcdGRhdGE6IFswLDEsIDAsMCwgMSwxLCAxLDBdXG5cdH0pXG5cblx0dmFyIHNoYWRlck9wdGlvbnMgPSB7XG5cdFx0cHJpbWl0aXZlOiAndHJpYW5nbGUgc3RyaXAnLFxuXHRcdGluc3RhbmNlczogcmVnbC5wcm9wKCdjb3VudCcpLFxuXHRcdGNvdW50OiA0LFxuXHRcdG9mZnNldDogMCxcblxuXHRcdHVuaWZvcm1zOiB7XG5cdFx0XHRtaXRlck1vZGU6IGZ1bmN0aW9uIChjdHgsIHByb3ApIHsgcmV0dXJuIHByb3Auam9pbiA9PT0gJ3JvdW5kJyA/IDIgOiAxOyB9LFxuXHRcdFx0bWl0ZXJMaW1pdDogcmVnbC5wcm9wKCdtaXRlckxpbWl0JyksXG5cdFx0XHRzY2FsZTogcmVnbC5wcm9wKCdzY2FsZScpLFxuXHRcdFx0c2NhbGVGcmFjdDogcmVnbC5wcm9wKCdzY2FsZUZyYWN0JyksXG5cdFx0XHR0cmFuc2xhdGVGcmFjdDogcmVnbC5wcm9wKCd0cmFuc2xhdGVGcmFjdCcpLFxuXHRcdFx0dHJhbnNsYXRlOiByZWdsLnByb3AoJ3RyYW5zbGF0ZScpLFxuXHRcdFx0dGhpY2tuZXNzOiByZWdsLnByb3AoJ3RoaWNrbmVzcycpLFxuXHRcdFx0ZGFzaFBhdHRlcm46IHJlZ2wucHJvcCgnZGFzaFRleHR1cmUnKSxcblx0XHRcdG9wYWNpdHk6IHJlZ2wucHJvcCgnb3BhY2l0eScpLFxuXHRcdFx0cGl4ZWxSYXRpbzogcmVnbC5jb250ZXh0KCdwaXhlbFJhdGlvJyksXG5cdFx0XHRpZDogcmVnbC5wcm9wKCdpZCcpLFxuXHRcdFx0ZGFzaFNpemU6IHJlZ2wucHJvcCgnZGFzaExlbmd0aCcpLFxuXHRcdFx0dmlld3BvcnQ6IGZ1bmN0aW9uIChjLCBwKSB7IHJldHVybiBbcC52aWV3cG9ydC54LCBwLnZpZXdwb3J0LnksIGMudmlld3BvcnRXaWR0aCwgYy52aWV3cG9ydEhlaWdodF07IH0sXG5cdFx0XHRkZXB0aDogcmVnbC5wcm9wKCdkZXB0aCcpXG5cdFx0fSxcblxuXHRcdGJsZW5kOiB7XG5cdFx0XHRlbmFibGU6IHRydWUsXG5cdFx0XHRjb2xvcjogWzAsMCwwLDBdLFxuXHRcdFx0ZXF1YXRpb246IHtcblx0XHRcdFx0cmdiOiAnYWRkJyxcblx0XHRcdFx0YWxwaGE6ICdhZGQnXG5cdFx0XHR9LFxuXHRcdFx0ZnVuYzoge1xuXHRcdFx0XHRzcmNSR0I6ICdzcmMgYWxwaGEnLFxuXHRcdFx0XHRkc3RSR0I6ICdvbmUgbWludXMgc3JjIGFscGhhJyxcblx0XHRcdFx0c3JjQWxwaGE6ICdvbmUgbWludXMgZHN0IGFscGhhJyxcblx0XHRcdFx0ZHN0QWxwaGE6ICdvbmUnXG5cdFx0XHR9XG5cdFx0fSxcblx0XHRkZXB0aDoge1xuXHRcdFx0ZW5hYmxlOiBmdW5jdGlvbiAoYywgcCkge1xuXHRcdFx0XHRyZXR1cm4gIXAub3ZlcmxheVxuXHRcdFx0fVxuXHRcdH0sXG5cdFx0c3RlbmNpbDoge2VuYWJsZTogZmFsc2V9LFxuXHRcdHNjaXNzb3I6IHtcblx0XHRcdGVuYWJsZTogdHJ1ZSxcblx0XHRcdGJveDogcmVnbC5wcm9wKCd2aWV3cG9ydCcpXG5cdFx0fSxcblx0XHR2aWV3cG9ydDogcmVnbC5wcm9wKCd2aWV3cG9ydCcpXG5cdH1cblxuXG5cdC8vIHNpbXBsaWZpZWQgcmVjdGFuZ3VsYXIgbGluZSBzaGFkZXJcblx0dmFyIGRyYXdSZWN0TGluZSA9IHJlZ2woZXh0ZW5kKHtcblx0XHR2ZXJ0OiBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMyIGFDb29yZCwgYkNvb3JkLCBhQ29vcmRGcmFjdCwgYkNvb3JkRnJhY3Q7XFxuYXR0cmlidXRlIHZlYzQgY29sb3I7XFxuYXR0cmlidXRlIGZsb2F0IGxpbmVFbmQsIGxpbmVUb3A7XFxuXFxudW5pZm9ybSB2ZWMyIHNjYWxlLCBzY2FsZUZyYWN0LCB0cmFuc2xhdGUsIHRyYW5zbGF0ZUZyYWN0O1xcbnVuaWZvcm0gZmxvYXQgdGhpY2tuZXNzLCBwaXhlbFJhdGlvLCBpZCwgZGVwdGg7XFxudW5pZm9ybSB2ZWM0IHZpZXdwb3J0O1xcblxcbnZhcnlpbmcgdmVjNCBmcmFnQ29sb3I7XFxudmFyeWluZyB2ZWMyIHRhbmdlbnQ7XFxuXFxudmVjMiBwcm9qZWN0KHZlYzIgcG9zaXRpb24sIHZlYzIgcG9zaXRpb25GcmFjdCwgdmVjMiBzY2FsZSwgdmVjMiBzY2FsZUZyYWN0LCB2ZWMyIHRyYW5zbGF0ZSwgdmVjMiB0cmFuc2xhdGVGcmFjdCkge1xcblxcdC8vIHRoZSBvcmRlciBpcyBpbXBvcnRhbnRcXG5cXHRyZXR1cm4gcG9zaXRpb24gKiBzY2FsZSArIHRyYW5zbGF0ZVxcbiAgICAgICArIHBvc2l0aW9uRnJhY3QgKiBzY2FsZSArIHRyYW5zbGF0ZUZyYWN0XFxuICAgICAgICsgcG9zaXRpb24gKiBzY2FsZUZyYWN0XFxuICAgICAgICsgcG9zaXRpb25GcmFjdCAqIHNjYWxlRnJhY3Q7XFxufVxcblxcbnZvaWQgbWFpbigpIHtcXG5cXHRmbG9hdCBsaW5lU3RhcnQgPSAxLiAtIGxpbmVFbmQ7XFxuXFx0ZmxvYXQgbGluZU9mZnNldCA9IGxpbmVUb3AgKiAyLiAtIDEuO1xcblxcblxcdHZlYzIgZGlmZiA9IChiQ29vcmQgKyBiQ29vcmRGcmFjdCAtIGFDb29yZCAtIGFDb29yZEZyYWN0KTtcXG5cXHR0YW5nZW50ID0gbm9ybWFsaXplKGRpZmYgKiBzY2FsZSAqIHZpZXdwb3J0Lnp3KTtcXG5cXHR2ZWMyIG5vcm1hbCA9IHZlYzIoLXRhbmdlbnQueSwgdGFuZ2VudC54KTtcXG5cXG5cXHR2ZWMyIHBvc2l0aW9uID0gcHJvamVjdChhQ29vcmQsIGFDb29yZEZyYWN0LCBzY2FsZSwgc2NhbGVGcmFjdCwgdHJhbnNsYXRlLCB0cmFuc2xhdGVGcmFjdCkgKiBsaW5lU3RhcnRcXG5cXHRcXHQrIHByb2plY3QoYkNvb3JkLCBiQ29vcmRGcmFjdCwgc2NhbGUsIHNjYWxlRnJhY3QsIHRyYW5zbGF0ZSwgdHJhbnNsYXRlRnJhY3QpICogbGluZUVuZFxcblxcblxcdFxcdCsgdGhpY2tuZXNzICogbm9ybWFsICogLjUgKiBsaW5lT2Zmc2V0IC8gdmlld3BvcnQuenc7XFxuXFxuXFx0Z2xfUG9zaXRpb24gPSB2ZWM0KHBvc2l0aW9uICogMi4wIC0gMS4wLCBkZXB0aCwgMSk7XFxuXFxuXFx0ZnJhZ0NvbG9yID0gY29sb3IgLyAyNTUuO1xcbn1cXG5cIl0pLFxuXHRcdGZyYWc6IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudW5pZm9ybSBzYW1wbGVyMkQgZGFzaFBhdHRlcm47XFxuXFxudW5pZm9ybSBmbG9hdCBkYXNoU2l6ZSwgcGl4ZWxSYXRpbywgdGhpY2tuZXNzLCBvcGFjaXR5LCBpZDtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcbnZhcnlpbmcgdmVjMiB0YW5nZW50O1xcblxcbnZvaWQgbWFpbigpIHtcXG5cXHRmbG9hdCBhbHBoYSA9IDEuO1xcblxcblxcdGZsb2F0IHQgPSBmcmFjdChkb3QodGFuZ2VudCwgZ2xfRnJhZ0Nvb3JkLnh5KSAvIGRhc2hTaXplKSAqIC41ICsgLjI1O1xcblxcdGZsb2F0IGRhc2ggPSB0ZXh0dXJlMkQoZGFzaFBhdHRlcm4sIHZlYzIodCwgLjUpKS5yO1xcblxcblxcdGdsX0ZyYWdDb2xvciA9IGZyYWdDb2xvcjtcXG5cXHRnbF9GcmFnQ29sb3IuYSAqPSBhbHBoYSAqIG9wYWNpdHkgKiBkYXNoO1xcbn1cXG5cIl0pLFxuXG5cdFx0YXR0cmlidXRlczoge1xuXHRcdFx0Ly8gaWYgcG9pbnQgaXMgYXQgdGhlIGVuZCBvZiBzZWdtZW50XG5cdFx0XHRsaW5lRW5kOiB7XG5cdFx0XHRcdGJ1ZmZlcjogb2Zmc2V0QnVmZmVyLFxuXHRcdFx0XHRkaXZpc29yOiAwLFxuXHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdG9mZnNldDogMFxuXHRcdFx0fSxcblx0XHRcdC8vIGlmIHBvaW50IGlzIGF0IHRoZSB0b3Agb2Ygc2VnbWVudFxuXHRcdFx0bGluZVRvcDoge1xuXHRcdFx0XHRidWZmZXI6IG9mZnNldEJ1ZmZlcixcblx0XHRcdFx0ZGl2aXNvcjogMCxcblx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRvZmZzZXQ6IDRcblx0XHRcdH0sXG5cdFx0XHQvLyBiZWdpbm5pbmcgb2YgbGluZSBjb29yZGluYXRlXG5cdFx0XHRhQ29vcmQ6IHtcblx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ3Bvc2l0aW9uQnVmZmVyJyksXG5cdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0b2Zmc2V0OiA4LFxuXHRcdFx0XHRkaXZpc29yOiAxXG5cdFx0XHR9LFxuXHRcdFx0Ly8gZW5kIG9mIGxpbmUgY29vcmRpbmF0ZVxuXHRcdFx0YkNvb3JkOiB7XG5cdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdwb3NpdGlvbkJ1ZmZlcicpLFxuXHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdG9mZnNldDogMTYsXG5cdFx0XHRcdGRpdmlzb3I6IDFcblx0XHRcdH0sXG5cdFx0XHRhQ29vcmRGcmFjdDoge1xuXHRcdFx0XHRidWZmZXI6IHJlZ2wucHJvcCgncG9zaXRpb25GcmFjdEJ1ZmZlcicpLFxuXHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdG9mZnNldDogOCxcblx0XHRcdFx0ZGl2aXNvcjogMVxuXHRcdFx0fSxcblx0XHRcdGJDb29yZEZyYWN0OiB7XG5cdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdwb3NpdGlvbkZyYWN0QnVmZmVyJyksXG5cdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0b2Zmc2V0OiAxNixcblx0XHRcdFx0ZGl2aXNvcjogMVxuXHRcdFx0fSxcblx0XHRcdGNvbG9yOiB7XG5cdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdjb2xvckJ1ZmZlcicpLFxuXHRcdFx0XHRzdHJpZGU6IDQsXG5cdFx0XHRcdG9mZnNldDogMCxcblx0XHRcdFx0ZGl2aXNvcjogMVxuXHRcdFx0fVxuXHRcdH1cblx0fSwgc2hhZGVyT3B0aW9ucykpXG5cblx0Ly8gY3JlYXRlIHJlZ2wgZHJhd1xuXHR2YXIgZHJhd01pdGVyTGluZVxuXG5cdHRyeSB7XG5cdFx0ZHJhd01pdGVyTGluZSA9IHJlZ2woZXh0ZW5kKHtcblx0XHRcdC8vIGN1bGxpbmcgcmVtb3ZlcyBwb2x5Z29uIGNyZWFzaW5nXG5cdFx0XHRjdWxsOiB7XG5cdFx0XHRcdGVuYWJsZTogdHJ1ZSxcblx0XHRcdFx0ZmFjZTogJ2JhY2snXG5cdFx0XHR9LFxuXG5cdFx0XHR2ZXJ0OiBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSB2ZWMyIGFDb29yZCwgYkNvb3JkLCBuZXh0Q29vcmQsIHByZXZDb29yZDtcXG5hdHRyaWJ1dGUgdmVjNCBhQ29sb3IsIGJDb2xvcjtcXG5hdHRyaWJ1dGUgZmxvYXQgbGluZUVuZCwgbGluZVRvcDtcXG5cXG51bmlmb3JtIHZlYzIgc2NhbGUsIHRyYW5zbGF0ZTtcXG51bmlmb3JtIGZsb2F0IHRoaWNrbmVzcywgcGl4ZWxSYXRpbywgaWQsIGRlcHRoO1xcbnVuaWZvcm0gdmVjNCB2aWV3cG9ydDtcXG51bmlmb3JtIGZsb2F0IG1pdGVyTGltaXQsIG1pdGVyTW9kZTtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcbnZhcnlpbmcgdmVjNCBzdGFydEN1dG9mZiwgZW5kQ3V0b2ZmO1xcbnZhcnlpbmcgdmVjMiB0YW5nZW50O1xcbnZhcnlpbmcgdmVjMiBzdGFydENvb3JkLCBlbmRDb29yZDtcXG52YXJ5aW5nIGZsb2F0IGVuYWJsZVN0YXJ0TWl0ZXIsIGVuYWJsZUVuZE1pdGVyO1xcblxcbmNvbnN0IGZsb2F0IFJFVkVSU0VfVEhSRVNIT0xEID0gLS44NzU7XFxuY29uc3QgZmxvYXQgTUlOX0RJRkYgPSAxZS02O1xcblxcbi8vIFRPRE86IHBvc3NpYmxlIG9wdGltaXphdGlvbnM6IGF2b2lkIG92ZXJjYWxjdWxhdGluZyBhbGwgZm9yIHZlcnRpY2VzIGFuZCBjYWxjIGp1c3Qgb25lIGluc3RlYWRcXG4vLyBUT0RPOiBwcmVjYWxjdWxhdGUgZG90IHByb2R1Y3RzLCBub3JtYWxpemUgdGhpbmdzIGJlZm9yZWhlYWQgZXRjLlxcbi8vIFRPRE86IHJlZmFjdG9yIHRvIHJlY3Rhbmd1bGFyIGFsZ29yaXRobVxcblxcbmZsb2F0IGRpc3RUb0xpbmUodmVjMiBwLCB2ZWMyIGEsIHZlYzIgYikge1xcblxcdHZlYzIgZGlmZiA9IGIgLSBhO1xcblxcdHZlYzIgcGVycCA9IG5vcm1hbGl6ZSh2ZWMyKC1kaWZmLnksIGRpZmYueCkpO1xcblxcdHJldHVybiBkb3QocCAtIGEsIHBlcnApO1xcbn1cXG5cXG5ib29sIGlzTmFOKCBmbG9hdCB2YWwgKXtcXG4gIHJldHVybiAoIHZhbCA8IDAuMCB8fCAwLjAgPCB2YWwgfHwgdmFsID09IDAuMCApID8gZmFsc2UgOiB0cnVlO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuXFx0dmVjMiBhQ29vcmQgPSBhQ29vcmQsIGJDb29yZCA9IGJDb29yZCwgcHJldkNvb3JkID0gcHJldkNvb3JkLCBuZXh0Q29vcmQgPSBuZXh0Q29vcmQ7XFxuXFxuICB2ZWMyIGFkanVzdGVkU2NhbGU7XFxuICBhZGp1c3RlZFNjYWxlLnggPSAoYWJzKHNjYWxlLngpIDwgTUlOX0RJRkYpID8gTUlOX0RJRkYgOiBzY2FsZS54O1xcbiAgYWRqdXN0ZWRTY2FsZS55ID0gKGFicyhzY2FsZS55KSA8IE1JTl9ESUZGKSA/IE1JTl9ESUZGIDogc2NhbGUueTtcXG5cXG4gIHZlYzIgc2NhbGVSYXRpbyA9IGFkanVzdGVkU2NhbGUgKiB2aWV3cG9ydC56dztcXG5cXHR2ZWMyIG5vcm1hbFdpZHRoID0gdGhpY2tuZXNzIC8gc2NhbGVSYXRpbztcXG5cXG5cXHRmbG9hdCBsaW5lU3RhcnQgPSAxLiAtIGxpbmVFbmQ7XFxuXFx0ZmxvYXQgbGluZUJvdCA9IDEuIC0gbGluZVRvcDtcXG5cXG5cXHRmcmFnQ29sb3IgPSAobGluZVN0YXJ0ICogYUNvbG9yICsgbGluZUVuZCAqIGJDb2xvcikgLyAyNTUuO1xcblxcblxcdGlmIChpc05hTihhQ29vcmQueCkgfHwgaXNOYU4oYUNvb3JkLnkpIHx8IGlzTmFOKGJDb29yZC54KSB8fCBpc05hTihiQ29vcmQueSkpIHJldHVybjtcXG5cXG5cXHRpZiAoYUNvb3JkID09IHByZXZDb29yZCkgcHJldkNvb3JkID0gYUNvb3JkICsgbm9ybWFsaXplKGJDb29yZCAtIGFDb29yZCk7XFxuXFx0aWYgKGJDb29yZCA9PSBuZXh0Q29vcmQpIG5leHRDb29yZCA9IGJDb29yZCAtIG5vcm1hbGl6ZShiQ29vcmQgLSBhQ29vcmQpO1xcblxcblxcdHZlYzIgcHJldkRpZmYgPSBhQ29vcmQgLSBwcmV2Q29vcmQ7XFxuXFx0dmVjMiBjdXJyRGlmZiA9IGJDb29yZCAtIGFDb29yZDtcXG5cXHR2ZWMyIG5leHREaWZmID0gbmV4dENvb3JkIC0gYkNvb3JkO1xcblxcblxcdHZlYzIgcHJldlRhbmdlbnQgPSBub3JtYWxpemUocHJldkRpZmYgKiBzY2FsZVJhdGlvKTtcXG5cXHR2ZWMyIGN1cnJUYW5nZW50ID0gbm9ybWFsaXplKGN1cnJEaWZmICogc2NhbGVSYXRpbyk7XFxuXFx0dmVjMiBuZXh0VGFuZ2VudCA9IG5vcm1hbGl6ZShuZXh0RGlmZiAqIHNjYWxlUmF0aW8pO1xcblxcblxcdHZlYzIgcHJldk5vcm1hbCA9IHZlYzIoLXByZXZUYW5nZW50LnksIHByZXZUYW5nZW50LngpO1xcblxcdHZlYzIgY3Vyck5vcm1hbCA9IHZlYzIoLWN1cnJUYW5nZW50LnksIGN1cnJUYW5nZW50LngpO1xcblxcdHZlYzIgbmV4dE5vcm1hbCA9IHZlYzIoLW5leHRUYW5nZW50LnksIG5leHRUYW5nZW50LngpO1xcblxcblxcdHZlYzIgc3RhcnRKb2luRGlyZWN0aW9uID0gbm9ybWFsaXplKHByZXZUYW5nZW50IC0gY3VyclRhbmdlbnQpO1xcblxcdHZlYzIgZW5kSm9pbkRpcmVjdGlvbiA9IG5vcm1hbGl6ZShjdXJyVGFuZ2VudCAtIG5leHRUYW5nZW50KTtcXG5cXG5cXHQvLyBjb2xsYXBzZWQvdW5pZGlyZWN0aW9uYWwgc2VnbWVudCBjYXNlc1xcblxcdC8vIEZJWE1FOiB0aGVyZSBzaG91bGQgYmUgbW9yZSBlbGVnYW50IHNvbHV0aW9uXFxuXFx0dmVjMiBwcmV2VGFuRGlmZiA9IGFicyhwcmV2VGFuZ2VudCAtIGN1cnJUYW5nZW50KTtcXG5cXHR2ZWMyIG5leHRUYW5EaWZmID0gYWJzKG5leHRUYW5nZW50IC0gY3VyclRhbmdlbnQpO1xcblxcdGlmIChtYXgocHJldlRhbkRpZmYueCwgcHJldlRhbkRpZmYueSkgPCBNSU5fRElGRikge1xcblxcdFxcdHN0YXJ0Sm9pbkRpcmVjdGlvbiA9IGN1cnJOb3JtYWw7XFxuXFx0fVxcblxcdGlmIChtYXgobmV4dFRhbkRpZmYueCwgbmV4dFRhbkRpZmYueSkgPCBNSU5fRElGRikge1xcblxcdFxcdGVuZEpvaW5EaXJlY3Rpb24gPSBjdXJyTm9ybWFsO1xcblxcdH1cXG5cXHRpZiAoYUNvb3JkID09IGJDb29yZCkge1xcblxcdFxcdGVuZEpvaW5EaXJlY3Rpb24gPSBzdGFydEpvaW5EaXJlY3Rpb247XFxuXFx0XFx0Y3Vyck5vcm1hbCA9IHByZXZOb3JtYWw7XFxuXFx0XFx0Y3VyclRhbmdlbnQgPSBwcmV2VGFuZ2VudDtcXG5cXHR9XFxuXFxuXFx0dGFuZ2VudCA9IGN1cnJUYW5nZW50O1xcblxcblxcdC8vY2FsY3VsYXRlIGpvaW4gc2hpZnRzIHJlbGF0aXZlIHRvIG5vcm1hbHNcXG5cXHRmbG9hdCBzdGFydEpvaW5TaGlmdCA9IGRvdChjdXJyTm9ybWFsLCBzdGFydEpvaW5EaXJlY3Rpb24pO1xcblxcdGZsb2F0IGVuZEpvaW5TaGlmdCA9IGRvdChjdXJyTm9ybWFsLCBlbmRKb2luRGlyZWN0aW9uKTtcXG5cXG5cXHRmbG9hdCBzdGFydE1pdGVyUmF0aW8gPSBhYnMoMS4gLyBzdGFydEpvaW5TaGlmdCk7XFxuXFx0ZmxvYXQgZW5kTWl0ZXJSYXRpbyA9IGFicygxLiAvIGVuZEpvaW5TaGlmdCk7XFxuXFxuXFx0dmVjMiBzdGFydEpvaW4gPSBzdGFydEpvaW5EaXJlY3Rpb24gKiBzdGFydE1pdGVyUmF0aW87XFxuXFx0dmVjMiBlbmRKb2luID0gZW5kSm9pbkRpcmVjdGlvbiAqIGVuZE1pdGVyUmF0aW87XFxuXFxuXFx0dmVjMiBzdGFydFRvcEpvaW4sIHN0YXJ0Qm90Sm9pbiwgZW5kVG9wSm9pbiwgZW5kQm90Sm9pbjtcXG5cXHRzdGFydFRvcEpvaW4gPSBzaWduKHN0YXJ0Sm9pblNoaWZ0KSAqIHN0YXJ0Sm9pbiAqIC41O1xcblxcdHN0YXJ0Qm90Sm9pbiA9IC1zdGFydFRvcEpvaW47XFxuXFxuXFx0ZW5kVG9wSm9pbiA9IHNpZ24oZW5kSm9pblNoaWZ0KSAqIGVuZEpvaW4gKiAuNTtcXG5cXHRlbmRCb3RKb2luID0gLWVuZFRvcEpvaW47XFxuXFxuXFx0dmVjMiBhVG9wQ29vcmQgPSBhQ29vcmQgKyBub3JtYWxXaWR0aCAqIHN0YXJ0VG9wSm9pbjtcXG5cXHR2ZWMyIGJUb3BDb29yZCA9IGJDb29yZCArIG5vcm1hbFdpZHRoICogZW5kVG9wSm9pbjtcXG5cXHR2ZWMyIGFCb3RDb29yZCA9IGFDb29yZCArIG5vcm1hbFdpZHRoICogc3RhcnRCb3RKb2luO1xcblxcdHZlYzIgYkJvdENvb3JkID0gYkNvb3JkICsgbm9ybWFsV2lkdGggKiBlbmRCb3RKb2luO1xcblxcblxcdC8vbWl0ZXIgYW50aS1jbGlwcGluZ1xcblxcdGZsb2F0IGJhQ2xpcHBpbmcgPSBkaXN0VG9MaW5lKGJDb29yZCwgYUNvb3JkLCBhQm90Q29vcmQpIC8gZG90KG5vcm1hbGl6ZShub3JtYWxXaWR0aCAqIGVuZEJvdEpvaW4pLCBub3JtYWxpemUobm9ybWFsV2lkdGgueXggKiB2ZWMyKC1zdGFydEJvdEpvaW4ueSwgc3RhcnRCb3RKb2luLngpKSk7XFxuXFx0ZmxvYXQgYWJDbGlwcGluZyA9IGRpc3RUb0xpbmUoYUNvb3JkLCBiQ29vcmQsIGJUb3BDb29yZCkgLyBkb3Qobm9ybWFsaXplKG5vcm1hbFdpZHRoICogc3RhcnRCb3RKb2luKSwgbm9ybWFsaXplKG5vcm1hbFdpZHRoLnl4ICogdmVjMigtZW5kQm90Sm9pbi55LCBlbmRCb3RKb2luLngpKSk7XFxuXFxuXFx0Ly9wcmV2ZW50IGNsb3NlIHRvIHJldmVyc2UgZGlyZWN0aW9uIHN3aXRjaFxcblxcdGJvb2wgcHJldlJldmVyc2UgPSBkb3QoY3VyclRhbmdlbnQsIHByZXZUYW5nZW50KSA8PSBSRVZFUlNFX1RIUkVTSE9MRCAmJiBhYnMoZG90KGN1cnJUYW5nZW50LCBwcmV2Tm9ybWFsKSkgKiBtaW4obGVuZ3RoKHByZXZEaWZmKSwgbGVuZ3RoKGN1cnJEaWZmKSkgPCAgbGVuZ3RoKG5vcm1hbFdpZHRoICogY3Vyck5vcm1hbCk7XFxuXFx0Ym9vbCBuZXh0UmV2ZXJzZSA9IGRvdChjdXJyVGFuZ2VudCwgbmV4dFRhbmdlbnQpIDw9IFJFVkVSU0VfVEhSRVNIT0xEICYmIGFicyhkb3QoY3VyclRhbmdlbnQsIG5leHROb3JtYWwpKSAqIG1pbihsZW5ndGgobmV4dERpZmYpLCBsZW5ndGgoY3VyckRpZmYpKSA8ICBsZW5ndGgobm9ybWFsV2lkdGggKiBjdXJyTm9ybWFsKTtcXG5cXG5cXHRpZiAocHJldlJldmVyc2UpIHtcXG5cXHRcXHQvL21ha2Ugam9pbiByZWN0YW5ndWxhclxcblxcdFxcdHZlYzIgbWl0ZXJTaGlmdCA9IG5vcm1hbFdpZHRoICogc3RhcnRKb2luRGlyZWN0aW9uICogbWl0ZXJMaW1pdCAqIC41O1xcblxcdFxcdGZsb2F0IG5vcm1hbEFkanVzdCA9IDEuIC0gbWluKG1pdGVyTGltaXQgLyBzdGFydE1pdGVyUmF0aW8sIDEuKTtcXG5cXHRcXHRhQm90Q29vcmQgPSBhQ29vcmQgKyBtaXRlclNoaWZ0IC0gbm9ybWFsQWRqdXN0ICogbm9ybWFsV2lkdGggKiBjdXJyTm9ybWFsICogLjU7XFxuXFx0XFx0YVRvcENvb3JkID0gYUNvb3JkICsgbWl0ZXJTaGlmdCArIG5vcm1hbEFkanVzdCAqIG5vcm1hbFdpZHRoICogY3Vyck5vcm1hbCAqIC41O1xcblxcdH1cXG5cXHRlbHNlIGlmICghbmV4dFJldmVyc2UgJiYgYmFDbGlwcGluZyA+IDAuICYmIGJhQ2xpcHBpbmcgPCBsZW5ndGgobm9ybWFsV2lkdGggKiBlbmRCb3RKb2luKSkge1xcblxcdFxcdC8vaGFuZGxlIG1pdGVyIGNsaXBwaW5nXFxuXFx0XFx0YlRvcENvb3JkIC09IG5vcm1hbFdpZHRoICogZW5kVG9wSm9pbjtcXG5cXHRcXHRiVG9wQ29vcmQgKz0gbm9ybWFsaXplKGVuZFRvcEpvaW4gKiBub3JtYWxXaWR0aCkgKiBiYUNsaXBwaW5nO1xcblxcdH1cXG5cXG5cXHRpZiAobmV4dFJldmVyc2UpIHtcXG5cXHRcXHQvL21ha2Ugam9pbiByZWN0YW5ndWxhclxcblxcdFxcdHZlYzIgbWl0ZXJTaGlmdCA9IG5vcm1hbFdpZHRoICogZW5kSm9pbkRpcmVjdGlvbiAqIG1pdGVyTGltaXQgKiAuNTtcXG5cXHRcXHRmbG9hdCBub3JtYWxBZGp1c3QgPSAxLiAtIG1pbihtaXRlckxpbWl0IC8gZW5kTWl0ZXJSYXRpbywgMS4pO1xcblxcdFxcdGJCb3RDb29yZCA9IGJDb29yZCArIG1pdGVyU2hpZnQgLSBub3JtYWxBZGp1c3QgKiBub3JtYWxXaWR0aCAqIGN1cnJOb3JtYWwgKiAuNTtcXG5cXHRcXHRiVG9wQ29vcmQgPSBiQ29vcmQgKyBtaXRlclNoaWZ0ICsgbm9ybWFsQWRqdXN0ICogbm9ybWFsV2lkdGggKiBjdXJyTm9ybWFsICogLjU7XFxuXFx0fVxcblxcdGVsc2UgaWYgKCFwcmV2UmV2ZXJzZSAmJiBhYkNsaXBwaW5nID4gMC4gJiYgYWJDbGlwcGluZyA8IGxlbmd0aChub3JtYWxXaWR0aCAqIHN0YXJ0Qm90Sm9pbikpIHtcXG5cXHRcXHQvL2hhbmRsZSBtaXRlciBjbGlwcGluZ1xcblxcdFxcdGFCb3RDb29yZCAtPSBub3JtYWxXaWR0aCAqIHN0YXJ0Qm90Sm9pbjtcXG5cXHRcXHRhQm90Q29vcmQgKz0gbm9ybWFsaXplKHN0YXJ0Qm90Sm9pbiAqIG5vcm1hbFdpZHRoKSAqIGFiQ2xpcHBpbmc7XFxuXFx0fVxcblxcblxcdHZlYzIgYVRvcFBvc2l0aW9uID0gKGFUb3BDb29yZCkgKiBhZGp1c3RlZFNjYWxlICsgdHJhbnNsYXRlO1xcblxcdHZlYzIgYUJvdFBvc2l0aW9uID0gKGFCb3RDb29yZCkgKiBhZGp1c3RlZFNjYWxlICsgdHJhbnNsYXRlO1xcblxcblxcdHZlYzIgYlRvcFBvc2l0aW9uID0gKGJUb3BDb29yZCkgKiBhZGp1c3RlZFNjYWxlICsgdHJhbnNsYXRlO1xcblxcdHZlYzIgYkJvdFBvc2l0aW9uID0gKGJCb3RDb29yZCkgKiBhZGp1c3RlZFNjYWxlICsgdHJhbnNsYXRlO1xcblxcblxcdC8vcG9zaXRpb24gaXMgbm9ybWFsaXplZCAwLi4xIGNvb3JkIG9uIHRoZSBzY3JlZW5cXG5cXHR2ZWMyIHBvc2l0aW9uID0gKGFUb3BQb3NpdGlvbiAqIGxpbmVUb3AgKyBhQm90UG9zaXRpb24gKiBsaW5lQm90KSAqIGxpbmVTdGFydCArIChiVG9wUG9zaXRpb24gKiBsaW5lVG9wICsgYkJvdFBvc2l0aW9uICogbGluZUJvdCkgKiBsaW5lRW5kO1xcblxcblxcdHN0YXJ0Q29vcmQgPSBhQ29vcmQgKiBzY2FsZVJhdGlvICsgdHJhbnNsYXRlICogdmlld3BvcnQuencgKyB2aWV3cG9ydC54eTtcXG5cXHRlbmRDb29yZCA9IGJDb29yZCAqIHNjYWxlUmF0aW8gKyB0cmFuc2xhdGUgKiB2aWV3cG9ydC56dyArIHZpZXdwb3J0Lnh5O1xcblxcblxcdGdsX1Bvc2l0aW9uID0gdmVjNChwb3NpdGlvbiAgKiAyLjAgLSAxLjAsIGRlcHRoLCAxKTtcXG5cXG5cXHRlbmFibGVTdGFydE1pdGVyID0gc3RlcChkb3QoY3VyclRhbmdlbnQsIHByZXZUYW5nZW50KSwgLjUpO1xcblxcdGVuYWJsZUVuZE1pdGVyID0gc3RlcChkb3QoY3VyclRhbmdlbnQsIG5leHRUYW5nZW50KSwgLjUpO1xcblxcblxcdC8vYmV2ZWwgbWl0ZXIgY3V0b2Zmc1xcblxcdGlmIChtaXRlck1vZGUgPT0gMS4pIHtcXG5cXHRcXHRpZiAoZW5hYmxlU3RhcnRNaXRlciA9PSAxLikge1xcblxcdFxcdFxcdHZlYzIgc3RhcnRNaXRlcldpZHRoID0gdmVjMihzdGFydEpvaW5EaXJlY3Rpb24pICogdGhpY2tuZXNzICogbWl0ZXJMaW1pdCAqIC41O1xcblxcdFxcdFxcdHN0YXJ0Q3V0b2ZmID0gdmVjNChhQ29vcmQsIGFDb29yZCk7XFxuXFx0XFx0XFx0c3RhcnRDdXRvZmYuencgKz0gdmVjMigtc3RhcnRKb2luRGlyZWN0aW9uLnksIHN0YXJ0Sm9pbkRpcmVjdGlvbi54KSAvIHNjYWxlUmF0aW87XFxuXFx0XFx0XFx0c3RhcnRDdXRvZmYgPSBzdGFydEN1dG9mZiAqIHNjYWxlUmF0aW8ueHl4eSArIHRyYW5zbGF0ZS54eXh5ICogdmlld3BvcnQuend6dztcXG5cXHRcXHRcXHRzdGFydEN1dG9mZiArPSB2aWV3cG9ydC54eXh5O1xcblxcdFxcdFxcdHN0YXJ0Q3V0b2ZmICs9IHN0YXJ0TWl0ZXJXaWR0aC54eXh5O1xcblxcdFxcdH1cXG5cXG5cXHRcXHRpZiAoZW5hYmxlRW5kTWl0ZXIgPT0gMS4pIHtcXG5cXHRcXHRcXHR2ZWMyIGVuZE1pdGVyV2lkdGggPSB2ZWMyKGVuZEpvaW5EaXJlY3Rpb24pICogdGhpY2tuZXNzICogbWl0ZXJMaW1pdCAqIC41O1xcblxcdFxcdFxcdGVuZEN1dG9mZiA9IHZlYzQoYkNvb3JkLCBiQ29vcmQpO1xcblxcdFxcdFxcdGVuZEN1dG9mZi56dyArPSB2ZWMyKC1lbmRKb2luRGlyZWN0aW9uLnksIGVuZEpvaW5EaXJlY3Rpb24ueCkgIC8gc2NhbGVSYXRpbztcXG5cXHRcXHRcXHRlbmRDdXRvZmYgPSBlbmRDdXRvZmYgKiBzY2FsZVJhdGlvLnh5eHkgKyB0cmFuc2xhdGUueHl4eSAqIHZpZXdwb3J0Lnp3enc7XFxuXFx0XFx0XFx0ZW5kQ3V0b2ZmICs9IHZpZXdwb3J0Lnh5eHk7XFxuXFx0XFx0XFx0ZW5kQ3V0b2ZmICs9IGVuZE1pdGVyV2lkdGgueHl4eTtcXG5cXHRcXHR9XFxuXFx0fVxcblxcblxcdC8vcm91bmQgbWl0ZXIgY3V0b2Zmc1xcblxcdGVsc2UgaWYgKG1pdGVyTW9kZSA9PSAyLikge1xcblxcdFxcdGlmIChlbmFibGVTdGFydE1pdGVyID09IDEuKSB7XFxuXFx0XFx0XFx0dmVjMiBzdGFydE1pdGVyV2lkdGggPSB2ZWMyKHN0YXJ0Sm9pbkRpcmVjdGlvbikgKiB0aGlja25lc3MgKiBhYnMoZG90KHN0YXJ0Sm9pbkRpcmVjdGlvbiwgY3Vyck5vcm1hbCkpICogLjU7XFxuXFx0XFx0XFx0c3RhcnRDdXRvZmYgPSB2ZWM0KGFDb29yZCwgYUNvb3JkKTtcXG5cXHRcXHRcXHRzdGFydEN1dG9mZi56dyArPSB2ZWMyKC1zdGFydEpvaW5EaXJlY3Rpb24ueSwgc3RhcnRKb2luRGlyZWN0aW9uLngpIC8gc2NhbGVSYXRpbztcXG5cXHRcXHRcXHRzdGFydEN1dG9mZiA9IHN0YXJ0Q3V0b2ZmICogc2NhbGVSYXRpby54eXh5ICsgdHJhbnNsYXRlLnh5eHkgKiB2aWV3cG9ydC56d3p3O1xcblxcdFxcdFxcdHN0YXJ0Q3V0b2ZmICs9IHZpZXdwb3J0Lnh5eHk7XFxuXFx0XFx0XFx0c3RhcnRDdXRvZmYgKz0gc3RhcnRNaXRlcldpZHRoLnh5eHk7XFxuXFx0XFx0fVxcblxcblxcdFxcdGlmIChlbmFibGVFbmRNaXRlciA9PSAxLikge1xcblxcdFxcdFxcdHZlYzIgZW5kTWl0ZXJXaWR0aCA9IHZlYzIoZW5kSm9pbkRpcmVjdGlvbikgKiB0aGlja25lc3MgKiBhYnMoZG90KGVuZEpvaW5EaXJlY3Rpb24sIGN1cnJOb3JtYWwpKSAqIC41O1xcblxcdFxcdFxcdGVuZEN1dG9mZiA9IHZlYzQoYkNvb3JkLCBiQ29vcmQpO1xcblxcdFxcdFxcdGVuZEN1dG9mZi56dyArPSB2ZWMyKC1lbmRKb2luRGlyZWN0aW9uLnksIGVuZEpvaW5EaXJlY3Rpb24ueCkgIC8gc2NhbGVSYXRpbztcXG5cXHRcXHRcXHRlbmRDdXRvZmYgPSBlbmRDdXRvZmYgKiBzY2FsZVJhdGlvLnh5eHkgKyB0cmFuc2xhdGUueHl4eSAqIHZpZXdwb3J0Lnp3enc7XFxuXFx0XFx0XFx0ZW5kQ3V0b2ZmICs9IHZpZXdwb3J0Lnh5eHk7XFxuXFx0XFx0XFx0ZW5kQ3V0b2ZmICs9IGVuZE1pdGVyV2lkdGgueHl4eTtcXG5cXHRcXHR9XFxuXFx0fVxcbn1cXG5cIl0pLFxuXHRcdFx0ZnJhZzogZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG51bmlmb3JtIHNhbXBsZXIyRCBkYXNoUGF0dGVybjtcXG51bmlmb3JtIGZsb2F0IGRhc2hTaXplLCBwaXhlbFJhdGlvLCB0aGlja25lc3MsIG9wYWNpdHksIGlkLCBtaXRlck1vZGU7XFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG52YXJ5aW5nIHZlYzIgdGFuZ2VudDtcXG52YXJ5aW5nIHZlYzQgc3RhcnRDdXRvZmYsIGVuZEN1dG9mZjtcXG52YXJ5aW5nIHZlYzIgc3RhcnRDb29yZCwgZW5kQ29vcmQ7XFxudmFyeWluZyBmbG9hdCBlbmFibGVTdGFydE1pdGVyLCBlbmFibGVFbmRNaXRlcjtcXG5cXG5mbG9hdCBkaXN0VG9MaW5lKHZlYzIgcCwgdmVjMiBhLCB2ZWMyIGIpIHtcXG5cXHR2ZWMyIGRpZmYgPSBiIC0gYTtcXG5cXHR2ZWMyIHBlcnAgPSBub3JtYWxpemUodmVjMigtZGlmZi55LCBkaWZmLngpKTtcXG5cXHRyZXR1cm4gZG90KHAgLSBhLCBwZXJwKTtcXG59XFxuXFxudm9pZCBtYWluKCkge1xcblxcdGZsb2F0IGFscGhhID0gMS4sIGRpc3RUb1N0YXJ0LCBkaXN0VG9FbmQ7XFxuXFx0ZmxvYXQgY3V0b2ZmID0gdGhpY2tuZXNzICogLjU7XFxuXFxuXFx0Ly9iZXZlbCBtaXRlclxcblxcdGlmIChtaXRlck1vZGUgPT0gMS4pIHtcXG5cXHRcXHRpZiAoZW5hYmxlU3RhcnRNaXRlciA9PSAxLikge1xcblxcdFxcdFxcdGRpc3RUb1N0YXJ0ID0gZGlzdFRvTGluZShnbF9GcmFnQ29vcmQueHksIHN0YXJ0Q3V0b2ZmLnh5LCBzdGFydEN1dG9mZi56dyk7XFxuXFx0XFx0XFx0aWYgKGRpc3RUb1N0YXJ0IDwgLTEuKSB7XFxuXFx0XFx0XFx0XFx0ZGlzY2FyZDtcXG5cXHRcXHRcXHRcXHRyZXR1cm47XFxuXFx0XFx0XFx0fVxcblxcdFxcdFxcdGFscGhhICo9IG1pbihtYXgoZGlzdFRvU3RhcnQgKyAxLiwgMC4pLCAxLik7XFxuXFx0XFx0fVxcblxcblxcdFxcdGlmIChlbmFibGVFbmRNaXRlciA9PSAxLikge1xcblxcdFxcdFxcdGRpc3RUb0VuZCA9IGRpc3RUb0xpbmUoZ2xfRnJhZ0Nvb3JkLnh5LCBlbmRDdXRvZmYueHksIGVuZEN1dG9mZi56dyk7XFxuXFx0XFx0XFx0aWYgKGRpc3RUb0VuZCA8IC0xLikge1xcblxcdFxcdFxcdFxcdGRpc2NhcmQ7XFxuXFx0XFx0XFx0XFx0cmV0dXJuO1xcblxcdFxcdFxcdH1cXG5cXHRcXHRcXHRhbHBoYSAqPSBtaW4obWF4KGRpc3RUb0VuZCArIDEuLCAwLiksIDEuKTtcXG5cXHRcXHR9XFxuXFx0fVxcblxcblxcdC8vIHJvdW5kIG1pdGVyXFxuXFx0ZWxzZSBpZiAobWl0ZXJNb2RlID09IDIuKSB7XFxuXFx0XFx0aWYgKGVuYWJsZVN0YXJ0TWl0ZXIgPT0gMS4pIHtcXG5cXHRcXHRcXHRkaXN0VG9TdGFydCA9IGRpc3RUb0xpbmUoZ2xfRnJhZ0Nvb3JkLnh5LCBzdGFydEN1dG9mZi54eSwgc3RhcnRDdXRvZmYuencpO1xcblxcdFxcdFxcdGlmIChkaXN0VG9TdGFydCA8IDAuKSB7XFxuXFx0XFx0XFx0XFx0ZmxvYXQgcmFkaXVzID0gbGVuZ3RoKGdsX0ZyYWdDb29yZC54eSAtIHN0YXJ0Q29vcmQpO1xcblxcblxcdFxcdFxcdFxcdGlmKHJhZGl1cyA+IGN1dG9mZiArIC41KSB7XFxuXFx0XFx0XFx0XFx0XFx0ZGlzY2FyZDtcXG5cXHRcXHRcXHRcXHRcXHRyZXR1cm47XFxuXFx0XFx0XFx0XFx0fVxcblxcblxcdFxcdFxcdFxcdGFscGhhIC09IHNtb290aHN0ZXAoY3V0b2ZmIC0gLjUsIGN1dG9mZiArIC41LCByYWRpdXMpO1xcblxcdFxcdFxcdH1cXG5cXHRcXHR9XFxuXFxuXFx0XFx0aWYgKGVuYWJsZUVuZE1pdGVyID09IDEuKSB7XFxuXFx0XFx0XFx0ZGlzdFRvRW5kID0gZGlzdFRvTGluZShnbF9GcmFnQ29vcmQueHksIGVuZEN1dG9mZi54eSwgZW5kQ3V0b2ZmLnp3KTtcXG5cXHRcXHRcXHRpZiAoZGlzdFRvRW5kIDwgMC4pIHtcXG5cXHRcXHRcXHRcXHRmbG9hdCByYWRpdXMgPSBsZW5ndGgoZ2xfRnJhZ0Nvb3JkLnh5IC0gZW5kQ29vcmQpO1xcblxcblxcdFxcdFxcdFxcdGlmKHJhZGl1cyA+IGN1dG9mZiArIC41KSB7XFxuXFx0XFx0XFx0XFx0XFx0ZGlzY2FyZDtcXG5cXHRcXHRcXHRcXHRcXHRyZXR1cm47XFxuXFx0XFx0XFx0XFx0fVxcblxcblxcdFxcdFxcdFxcdGFscGhhIC09IHNtb290aHN0ZXAoY3V0b2ZmIC0gLjUsIGN1dG9mZiArIC41LCByYWRpdXMpO1xcblxcdFxcdFxcdH1cXG5cXHRcXHR9XFxuXFx0fVxcblxcblxcdGZsb2F0IHQgPSBmcmFjdChkb3QodGFuZ2VudCwgZ2xfRnJhZ0Nvb3JkLnh5KSAvIGRhc2hTaXplKSAqIC41ICsgLjI1O1xcblxcdGZsb2F0IGRhc2ggPSB0ZXh0dXJlMkQoZGFzaFBhdHRlcm4sIHZlYzIodCwgLjUpKS5yO1xcblxcblxcdGdsX0ZyYWdDb2xvciA9IGZyYWdDb2xvcjtcXG5cXHRnbF9GcmFnQ29sb3IuYSAqPSBhbHBoYSAqIG9wYWNpdHkgKiBkYXNoO1xcbn1cXG5cIl0pLFxuXG5cdFx0XHRhdHRyaWJ1dGVzOiB7XG5cdFx0XHRcdC8vIGlzIGxpbmUgZW5kXG5cdFx0XHRcdGxpbmVFbmQ6IHtcblx0XHRcdFx0XHRidWZmZXI6IG9mZnNldEJ1ZmZlcixcblx0XHRcdFx0XHRkaXZpc29yOiAwLFxuXHRcdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0XHRvZmZzZXQ6IDBcblx0XHRcdFx0fSxcblx0XHRcdFx0Ly8gaXMgbGluZSB0b3Bcblx0XHRcdFx0bGluZVRvcDoge1xuXHRcdFx0XHRcdGJ1ZmZlcjogb2Zmc2V0QnVmZmVyLFxuXHRcdFx0XHRcdGRpdmlzb3I6IDAsXG5cdFx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRcdG9mZnNldDogNFxuXHRcdFx0XHR9LFxuXHRcdFx0XHQvLyBsZWZ0IGNvbG9yXG5cdFx0XHRcdGFDb2xvcjoge1xuXHRcdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdjb2xvckJ1ZmZlcicpLFxuXHRcdFx0XHRcdHN0cmlkZTogNCxcblx0XHRcdFx0XHRvZmZzZXQ6IDAsXG5cdFx0XHRcdFx0ZGl2aXNvcjogMVxuXHRcdFx0XHR9LFxuXHRcdFx0XHQvLyByaWdodCBjb2xvclxuXHRcdFx0XHRiQ29sb3I6IHtcblx0XHRcdFx0XHRidWZmZXI6IHJlZ2wucHJvcCgnY29sb3JCdWZmZXInKSxcblx0XHRcdFx0XHRzdHJpZGU6IDQsXG5cdFx0XHRcdFx0b2Zmc2V0OiA0LFxuXHRcdFx0XHRcdGRpdmlzb3I6IDFcblx0XHRcdFx0fSxcblx0XHRcdFx0cHJldkNvb3JkOiB7XG5cdFx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ3Bvc2l0aW9uQnVmZmVyJyksXG5cdFx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRcdG9mZnNldDogMCxcblx0XHRcdFx0XHRkaXZpc29yOiAxXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGFDb29yZDoge1xuXHRcdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdwb3NpdGlvbkJ1ZmZlcicpLFxuXHRcdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0XHRvZmZzZXQ6IDgsXG5cdFx0XHRcdFx0ZGl2aXNvcjogMVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRiQ29vcmQ6IHtcblx0XHRcdFx0XHRidWZmZXI6IHJlZ2wucHJvcCgncG9zaXRpb25CdWZmZXInKSxcblx0XHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdFx0b2Zmc2V0OiAxNixcblx0XHRcdFx0XHRkaXZpc29yOiAxXG5cdFx0XHRcdH0sXG5cdFx0XHRcdG5leHRDb29yZDoge1xuXHRcdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdwb3NpdGlvbkJ1ZmZlcicpLFxuXHRcdFx0XHRcdHN0cmlkZTogOCxcblx0XHRcdFx0XHRvZmZzZXQ6IDI0LFxuXHRcdFx0XHRcdGRpdmlzb3I6IDFcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sIHNoYWRlck9wdGlvbnMpKVxuXHR9IGNhdGNoIChlKSB7XG5cdFx0Ly8gSUUvYmFkIFdlYmtpdCBmYWxsYmFja1xuXHRcdGRyYXdNaXRlckxpbmUgPSBkcmF3UmVjdExpbmVcblx0fVxuXG5cdC8vIGZpbGwgc2hhZGVyXG5cdHZhciBkcmF3RmlsbCA9IHJlZ2woe1xuXHRcdHByaW1pdGl2ZTogJ3RyaWFuZ2xlJyxcblx0XHRlbGVtZW50czogZnVuY3Rpb24gKGN0eCwgcHJvcCkgeyByZXR1cm4gcHJvcC50cmlhbmdsZXM7IH0sXG5cdFx0b2Zmc2V0OiAwLFxuXG5cdFx0dmVydDogZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgdmVjMiBwb3NpdGlvbiwgcG9zaXRpb25GcmFjdDtcXG5cXG51bmlmb3JtIHZlYzQgY29sb3I7XFxudW5pZm9ybSB2ZWMyIHNjYWxlLCBzY2FsZUZyYWN0LCB0cmFuc2xhdGUsIHRyYW5zbGF0ZUZyYWN0O1xcbnVuaWZvcm0gZmxvYXQgcGl4ZWxSYXRpbywgaWQ7XFxudW5pZm9ybSB2ZWM0IHZpZXdwb3J0O1xcbnVuaWZvcm0gZmxvYXQgb3BhY2l0eTtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcblxcbmNvbnN0IGZsb2F0IE1BWF9MSU5FUyA9IDI1Ni47XFxuXFxudm9pZCBtYWluKCkge1xcblxcdGZsb2F0IGRlcHRoID0gKE1BWF9MSU5FUyAtIDQuIC0gaWQpIC8gKE1BWF9MSU5FUyk7XFxuXFxuXFx0dmVjMiBwb3NpdGlvbiA9IHBvc2l0aW9uICogc2NhbGUgKyB0cmFuc2xhdGVcXG4gICAgICAgKyBwb3NpdGlvbkZyYWN0ICogc2NhbGUgKyB0cmFuc2xhdGVGcmFjdFxcbiAgICAgICArIHBvc2l0aW9uICogc2NhbGVGcmFjdFxcbiAgICAgICArIHBvc2l0aW9uRnJhY3QgKiBzY2FsZUZyYWN0O1xcblxcblxcdGdsX1Bvc2l0aW9uID0gdmVjNChwb3NpdGlvbiAqIDIuMCAtIDEuMCwgZGVwdGgsIDEpO1xcblxcblxcdGZyYWdDb2xvciA9IGNvbG9yIC8gMjU1LjtcXG5cXHRmcmFnQ29sb3IuYSAqPSBvcGFjaXR5O1xcbn1cXG5cIl0pLFxuXHRcdGZyYWc6IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvcjtcXG5cXG52b2lkIG1haW4oKSB7XFxuXFx0Z2xfRnJhZ0NvbG9yID0gZnJhZ0NvbG9yO1xcbn1cXG5cIl0pLFxuXG5cdFx0dW5pZm9ybXM6IHtcblx0XHRcdHNjYWxlOiByZWdsLnByb3AoJ3NjYWxlJyksXG5cdFx0XHRjb2xvcjogcmVnbC5wcm9wKCdmaWxsJyksXG5cdFx0XHRzY2FsZUZyYWN0OiByZWdsLnByb3AoJ3NjYWxlRnJhY3QnKSxcblx0XHRcdHRyYW5zbGF0ZUZyYWN0OiByZWdsLnByb3AoJ3RyYW5zbGF0ZUZyYWN0JyksXG5cdFx0XHR0cmFuc2xhdGU6IHJlZ2wucHJvcCgndHJhbnNsYXRlJyksXG5cdFx0XHRvcGFjaXR5OiByZWdsLnByb3AoJ29wYWNpdHknKSxcblx0XHRcdHBpeGVsUmF0aW86IHJlZ2wuY29udGV4dCgncGl4ZWxSYXRpbycpLFxuXHRcdFx0aWQ6IHJlZ2wucHJvcCgnaWQnKSxcblx0XHRcdHZpZXdwb3J0OiBmdW5jdGlvbiAoY3R4LCBwcm9wKSB7IHJldHVybiBbcHJvcC52aWV3cG9ydC54LCBwcm9wLnZpZXdwb3J0LnksIGN0eC52aWV3cG9ydFdpZHRoLCBjdHgudmlld3BvcnRIZWlnaHRdOyB9XG5cdFx0fSxcblxuXHRcdGF0dHJpYnV0ZXM6IHtcblx0XHRcdHBvc2l0aW9uOiB7XG5cdFx0XHRcdGJ1ZmZlcjogcmVnbC5wcm9wKCdwb3NpdGlvbkJ1ZmZlcicpLFxuXHRcdFx0XHRzdHJpZGU6IDgsXG5cdFx0XHRcdG9mZnNldDogOFxuXHRcdFx0fSxcblx0XHRcdHBvc2l0aW9uRnJhY3Q6IHtcblx0XHRcdFx0YnVmZmVyOiByZWdsLnByb3AoJ3Bvc2l0aW9uRnJhY3RCdWZmZXInKSxcblx0XHRcdFx0c3RyaWRlOiA4LFxuXHRcdFx0XHRvZmZzZXQ6IDhcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0YmxlbmQ6IHNoYWRlck9wdGlvbnMuYmxlbmQsXG5cblx0XHRkZXB0aDogeyBlbmFibGU6IGZhbHNlIH0sXG5cdFx0c2Npc3Nvcjogc2hhZGVyT3B0aW9ucy5zY2lzc29yLFxuXHRcdHN0ZW5jaWw6IHNoYWRlck9wdGlvbnMuc3RlbmNpbCxcblx0XHR2aWV3cG9ydDogc2hhZGVyT3B0aW9ucy52aWV3cG9ydFxuXHR9KVxuXG5cdHJldHVybiB7XG5cdFx0ZmlsbDogZHJhd0ZpbGwsIHJlY3Q6IGRyYXdSZWN0TGluZSwgbWl0ZXI6IGRyYXdNaXRlckxpbmVcblx0fVxufVxuXG5cbi8vIHVzZWQgdG8gZm9yIG5ldyBsaW5lcyBpbnN0YW5jZXNcbkxpbmUyRC5kZWZhdWx0cyA9IHtcblx0ZGFzaGVzOiBudWxsLFxuXHRqb2luOiAnbWl0ZXInLFxuXHRtaXRlckxpbWl0OiAxLFxuXHR0aGlja25lc3M6IDEwLFxuXHRjYXA6ICdzcXVhcmUnLFxuXHRjb2xvcjogJ2JsYWNrJyxcblx0b3BhY2l0eTogMSxcblx0b3ZlcmxheTogZmFsc2UsXG5cdHZpZXdwb3J0OiBudWxsLFxuXHRyYW5nZTogbnVsbCxcblx0Y2xvc2U6IGZhbHNlLFxuXHRmaWxsOiBudWxsXG59XG5cblxuTGluZTJELnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciByZWY7XG5cblx0dmFyIGFyZ3MgPSBbXSwgbGVuID0gYXJndW1lbnRzLmxlbmd0aDtcblx0d2hpbGUgKCBsZW4tLSApIGFyZ3NbIGxlbiBdID0gYXJndW1lbnRzWyBsZW4gXTtcblx0aWYgKGFyZ3MubGVuZ3RoKSB7XG5cdFx0KHJlZiA9IHRoaXMpLnVwZGF0ZS5hcHBseShyZWYsIGFyZ3MpXG5cdH1cblxuXHR0aGlzLmRyYXcoKVxufVxuXG5cbkxpbmUyRC5wcm90b3R5cGUuZHJhdyA9IGZ1bmN0aW9uICgpIHtcblx0dmFyIHRoaXMkMSA9IHRoaXM7XG5cdHZhciBhcmdzID0gW10sIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG5cdHdoaWxlICggbGVuLS0gKSBhcmdzWyBsZW4gXSA9IGFyZ3VtZW50c1sgbGVuIF07XG5cblx0Ly8gcmVuZGVyIG11bHRpcGxlIHBvbHlsaW5lcyB2aWEgcmVnbCBiYXRjaFxuXHQoYXJncy5sZW5ndGggPyBhcmdzIDogdGhpcy5wYXNzZXMpLmZvckVhY2goZnVuY3Rpb24gKHMsIGkpIHtcblx0XHR2YXIgcmVmO1xuXG5cdFx0Ly8gcmVuZGVyIGFycmF5IHBhc3MgYXMgYSBsaXN0IG9mIHBhc3Nlc1xuXHRcdGlmIChzICYmIEFycmF5LmlzQXJyYXkocykpIHsgcmV0dXJuIChyZWYgPSB0aGlzJDEpLmRyYXcuYXBwbHkocmVmLCBzKSB9XG5cblx0XHRpZiAodHlwZW9mIHMgPT09ICdudW1iZXInKSB7IHMgPSB0aGlzJDEucGFzc2VzW3NdIH1cblxuXHRcdGlmICghKHMgJiYgcy5jb3VudCA+IDEgJiYgcy5vcGFjaXR5KSkgeyByZXR1cm4gfVxuXG5cdFx0dGhpcyQxLnJlZ2wuX3JlZnJlc2goKVxuXG5cdFx0aWYgKHMuZmlsbCAmJiBzLnRyaWFuZ2xlcyAmJiBzLnRyaWFuZ2xlcy5sZW5ndGggPiAyKSB7XG5cdFx0XHR0aGlzJDEuc2hhZGVycy5maWxsKHMpXG5cdFx0fVxuXG5cdFx0aWYgKCFzLnRoaWNrbmVzcykgeyByZXR1cm4gfVxuXG5cdFx0Ly8gaGlnaCBzY2FsZSBpcyBvbmx5IGF2YWlsYWJsZSBmb3IgcmVjdCBtb2RlIHdpdGggcHJlY2lzaW9uXG5cdFx0aWYgKHMuc2NhbGVbMF0gKiBzLnZpZXdwb3J0LndpZHRoID4gTGluZTJELnByZWNpc2lvblRocmVzaG9sZCB8fCBzLnNjYWxlWzFdICogcy52aWV3cG9ydC5oZWlnaHQgPiBMaW5lMkQucHJlY2lzaW9uVGhyZXNob2xkKSB7XG5cdFx0XHR0aGlzJDEuc2hhZGVycy5yZWN0KHMpXG5cdFx0fVxuXG5cdFx0Ly8gdGhpbiB0aGlzLnBhc3NlcyBvciB0b28gbWFueSBwb2ludHMgYXJlIHJlbmRlcmVkIGFzIHNpbXBsaWZpZWQgcmVjdCBzaGFkZXJcblx0XHRlbHNlIGlmIChzLmpvaW4gPT09ICdyZWN0JyB8fCAoIXMuam9pbiAmJiAocy50aGlja25lc3MgPD0gMiB8fCBzLmNvdW50ID49IExpbmUyRC5tYXhQb2ludHMpKSkge1xuXHRcdFx0dGhpcyQxLnNoYWRlcnMucmVjdChzKVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHRoaXMkMS5zaGFkZXJzLm1pdGVyKHMpXG5cdFx0fVxuXHR9KVxuXG5cdHJldHVybiB0aGlzXG59XG5cbkxpbmUyRC5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcblx0dmFyIHRoaXMkMSA9IHRoaXM7XG5cblx0aWYgKCFvcHRpb25zKSB7IHJldHVybiB9XG5cblx0aWYgKG9wdGlvbnMubGVuZ3RoICE9IG51bGwpIHtcblx0XHRpZiAodHlwZW9mIG9wdGlvbnNbMF0gPT09ICdudW1iZXInKSB7IG9wdGlvbnMgPSBbe3Bvc2l0aW9uczogb3B0aW9uc31dIH1cblx0fVxuXG5cdC8vIG1ha2Ugb3B0aW9ucyBhIGJhdGNoXG5cdGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KG9wdGlvbnMpKSB7IG9wdGlvbnMgPSBbb3B0aW9uc10gfVxuXG5cdHZhciByZWYgPSB0aGlzO1xuXHR2YXIgcmVnbCA9IHJlZi5yZWdsO1xuXHR2YXIgZ2wgPSByZWYuZ2w7XG5cblx0Ly8gcHJvY2VzcyBwZXItbGluZSBzZXR0aW5nc1xuXHRvcHRpb25zLmZvckVhY2goZnVuY3Rpb24gKG8sIGkpIHtcblx0XHR2YXIgc3RhdGUgPSB0aGlzJDEucGFzc2VzW2ldXG5cblx0XHRpZiAobyA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB9XG5cblx0XHQvLyBudWxsLWFyZ3VtZW50IHJlbW92ZXMgcGFzc1xuXHRcdGlmIChvID09PSBudWxsKSB7XG5cdFx0XHR0aGlzJDEucGFzc2VzW2ldID0gbnVsbFxuXHRcdFx0cmV0dXJuXG5cdFx0fVxuXG5cdFx0aWYgKHR5cGVvZiBvWzBdID09PSAnbnVtYmVyJykgeyBvID0ge3Bvc2l0aW9uczogb30gfVxuXG5cdFx0Ly8gaGFuZGxlIGFsaWFzZXNcblx0XHRvID0gcGljayhvLCB7XG5cdFx0XHRwb3NpdGlvbnM6ICdwb3NpdGlvbnMgcG9pbnRzIGRhdGEgY29vcmRzJyxcblx0XHRcdHRoaWNrbmVzczogJ3RoaWNrbmVzcyBsaW5lV2lkdGggbGluZVdpZHRocyBsaW5lLXdpZHRoIGxpbmV3aWR0aCB3aWR0aCBzdHJva2Utd2lkdGggc3Ryb2tld2lkdGggc3Ryb2tlV2lkdGgnLFxuXHRcdFx0am9pbjogJ2xpbmVKb2luIGxpbmVqb2luIGpvaW4gdHlwZSBtb2RlJyxcblx0XHRcdG1pdGVyTGltaXQ6ICdtaXRlcmxpbWl0IG1pdGVyTGltaXQnLFxuXHRcdFx0ZGFzaGVzOiAnZGFzaCBkYXNoZXMgZGFzaGFycmF5IGRhc2gtYXJyYXkgZGFzaEFycmF5Jyxcblx0XHRcdGNvbG9yOiAnY29sb3IgY29sb3VyIHN0cm9rZSBjb2xvcnMgY29sb3VycyBzdHJva2UtY29sb3Igc3Ryb2tlQ29sb3InLFxuXHRcdFx0ZmlsbDogJ2ZpbGwgZmlsbC1jb2xvciBmaWxsQ29sb3InLFxuXHRcdFx0b3BhY2l0eTogJ2FscGhhIG9wYWNpdHknLFxuXHRcdFx0b3ZlcmxheTogJ292ZXJsYXkgY3JlYXNlIG92ZXJsYXAgaW50ZXJzZWN0Jyxcblx0XHRcdGNsb3NlOiAnY2xvc2VkIGNsb3NlIGNsb3NlZC1wYXRoIGNsb3NlUGF0aCcsXG5cdFx0XHRyYW5nZTogJ3JhbmdlIGRhdGFCb3gnLFxuXHRcdFx0dmlld3BvcnQ6ICd2aWV3cG9ydCB2aWV3Qm94Jyxcblx0XHRcdGhvbGU6ICdob2xlcyBob2xlIGhvbGxvdydcblx0XHR9KVxuXG5cdFx0Ly8gaW5pdCBzdGF0ZVxuXHRcdGlmICghc3RhdGUpIHtcblx0XHRcdHRoaXMkMS5wYXNzZXNbaV0gPSBzdGF0ZSA9IHtcblx0XHRcdFx0aWQ6IGksXG5cdFx0XHRcdHNjYWxlOiBudWxsLFxuXHRcdFx0XHRzY2FsZUZyYWN0OiBudWxsLFxuXHRcdFx0XHR0cmFuc2xhdGU6IG51bGwsXG5cdFx0XHRcdHRyYW5zbGF0ZUZyYWN0OiBudWxsLFxuXHRcdFx0XHRjb3VudDogMCxcblx0XHRcdFx0aG9sZTogW10sXG5cdFx0XHRcdGRlcHRoOiAwLFxuXG5cdFx0XHRcdGRhc2hMZW5ndGg6IDEsXG5cdFx0XHRcdGRhc2hUZXh0dXJlOiByZWdsLnRleHR1cmUoe1xuXHRcdFx0XHRcdGNoYW5uZWxzOiAxLFxuXHRcdFx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KFsyNTVdKSxcblx0XHRcdFx0XHR3aWR0aDogMSxcblx0XHRcdFx0XHRoZWlnaHQ6IDEsXG5cdFx0XHRcdFx0bWFnOiAnbGluZWFyJyxcblx0XHRcdFx0XHRtaW46ICdsaW5lYXInXG5cdFx0XHRcdH0pLFxuXG5cdFx0XHRcdGNvbG9yQnVmZmVyOiByZWdsLmJ1ZmZlcih7XG5cdFx0XHRcdFx0dXNhZ2U6ICdkeW5hbWljJyxcblx0XHRcdFx0XHR0eXBlOiAndWludDgnLFxuXHRcdFx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KClcblx0XHRcdFx0fSksXG5cdFx0XHRcdHBvc2l0aW9uQnVmZmVyOiByZWdsLmJ1ZmZlcih7XG5cdFx0XHRcdFx0dXNhZ2U6ICdkeW5hbWljJyxcblx0XHRcdFx0XHR0eXBlOiAnZmxvYXQnLFxuXHRcdFx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KClcblx0XHRcdFx0fSksXG5cdFx0XHRcdHBvc2l0aW9uRnJhY3RCdWZmZXI6IHJlZ2wuYnVmZmVyKHtcblx0XHRcdFx0XHR1c2FnZTogJ2R5bmFtaWMnLFxuXHRcdFx0XHRcdHR5cGU6ICdmbG9hdCcsXG5cdFx0XHRcdFx0ZGF0YTogbmV3IFVpbnQ4QXJyYXkoKVxuXHRcdFx0XHR9KVxuXHRcdFx0fVxuXG5cdFx0XHRvID0gZXh0ZW5kKHt9LCBMaW5lMkQuZGVmYXVsdHMsIG8pXG5cdFx0fVxuXHRcdGlmIChvLnRoaWNrbmVzcyAhPSBudWxsKSB7IHN0YXRlLnRoaWNrbmVzcyA9IHBhcnNlRmxvYXQoby50aGlja25lc3MpIH1cblx0XHRpZiAoby5vcGFjaXR5ICE9IG51bGwpIHsgc3RhdGUub3BhY2l0eSA9IHBhcnNlRmxvYXQoby5vcGFjaXR5KSB9XG5cdFx0aWYgKG8ubWl0ZXJMaW1pdCAhPSBudWxsKSB7IHN0YXRlLm1pdGVyTGltaXQgPSBwYXJzZUZsb2F0KG8ubWl0ZXJMaW1pdCkgfVxuXHRcdGlmIChvLm92ZXJsYXkgIT0gbnVsbCkge1xuXHRcdFx0c3RhdGUub3ZlcmxheSA9ICEhby5vdmVybGF5XG5cdFx0XHRpZiAoaSA8IExpbmUyRC5tYXhMaW5lcykge1xuXHRcdFx0XHRzdGF0ZS5kZXB0aCA9IDIgKiAoTGluZTJELm1heExpbmVzIC0gMSAtIGkgJSBMaW5lMkQubWF4TGluZXMpIC8gTGluZTJELm1heExpbmVzIC0gMS47XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmIChvLmpvaW4gIT0gbnVsbCkgeyBzdGF0ZS5qb2luID0gby5qb2luIH1cblx0XHRpZiAoby5ob2xlICE9IG51bGwpIHsgc3RhdGUuaG9sZSA9IG8uaG9sZSB9XG5cdFx0aWYgKG8uZmlsbCAhPSBudWxsKSB7IHN0YXRlLmZpbGwgPSAhby5maWxsID8gbnVsbCA6IHJnYmEoby5maWxsLCAndWludDgnKSB9XG5cdFx0aWYgKG8udmlld3BvcnQgIT0gbnVsbCkgeyBzdGF0ZS52aWV3cG9ydCA9IHBhcnNlUmVjdChvLnZpZXdwb3J0KSB9XG5cblx0XHRpZiAoIXN0YXRlLnZpZXdwb3J0KSB7XG5cdFx0XHRzdGF0ZS52aWV3cG9ydCA9IHBhcnNlUmVjdChbXG5cdFx0XHRcdGdsLmRyYXdpbmdCdWZmZXJXaWR0aCxcblx0XHRcdFx0Z2wuZHJhd2luZ0J1ZmZlckhlaWdodFxuXHRcdFx0XSlcblx0XHR9XG5cblx0XHRpZiAoby5jbG9zZSAhPSBudWxsKSB7IHN0YXRlLmNsb3NlID0gby5jbG9zZSB9XG5cblx0XHQvLyByZXNldCBwb3NpdGlvbnNcblx0XHRpZiAoby5wb3NpdGlvbnMgPT09IG51bGwpIHsgby5wb3NpdGlvbnMgPSBbXSB9XG5cdFx0aWYgKG8ucG9zaXRpb25zKSB7XG5cdFx0XHR2YXIgcG9zaXRpb25zLCBjb3VudFxuXG5cdFx0XHQvLyBpZiBwb3NpdGlvbnMgYXJlIGFuIG9iamVjdCB3aXRoIHgveVxuXHRcdFx0aWYgKG8ucG9zaXRpb25zLnggJiYgby5wb3NpdGlvbnMueSkge1xuXHRcdFx0XHR2YXIgeFBvcyA9IG8ucG9zaXRpb25zLnhcblx0XHRcdFx0dmFyIHlQb3MgPSBvLnBvc2l0aW9ucy55XG5cdFx0XHRcdGNvdW50ID0gc3RhdGUuY291bnQgPSBNYXRoLm1heChcblx0XHRcdFx0XHR4UG9zLmxlbmd0aCxcblx0XHRcdFx0XHR5UG9zLmxlbmd0aFxuXHRcdFx0XHQpXG5cdFx0XHRcdHBvc2l0aW9ucyA9IG5ldyBGbG9hdDY0QXJyYXkoY291bnQgKiAyKVxuXHRcdFx0XHRmb3IgKHZhciBpJDEgPSAwOyBpJDEgPCBjb3VudDsgaSQxKyspIHtcblx0XHRcdFx0XHRwb3NpdGlvbnNbaSQxICogMl0gPSB4UG9zW2kkMV1cblx0XHRcdFx0XHRwb3NpdGlvbnNbaSQxICogMiArIDFdID0geVBvc1tpJDFdXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRwb3NpdGlvbnMgPSBmbGF0dGVuKG8ucG9zaXRpb25zLCAnZmxvYXQ2NCcpXG5cdFx0XHRcdGNvdW50ID0gc3RhdGUuY291bnQgPSBNYXRoLmZsb29yKHBvc2l0aW9ucy5sZW5ndGggLyAyKVxuXHRcdFx0fVxuXG5cdFx0XHR2YXIgYm91bmRzID0gc3RhdGUuYm91bmRzID0gZ2V0Qm91bmRzKHBvc2l0aW9ucywgMilcblxuXHRcdFx0Ly8gY3JlYXRlIGZpbGwgcG9zaXRpb25zXG5cdFx0XHQvLyBGSVhNRTogZmlsbCBwb3NpdGlvbnMgY2FuIGJlIHNldCBvbmx5IGFsb25nIHdpdGggcG9zaXRpb25zXG5cdFx0XHRpZiAoc3RhdGUuZmlsbCkge1xuXHRcdFx0XHR2YXIgcG9zID0gW11cblxuXHRcdFx0XHQvLyBmaWx0ZXIgYmFkIHZlcnRpY2VzIGFuZCByZW1hcCB0cmlhbmdsZXMgdG8gZW5zdXJlIHNoYXBlXG5cdFx0XHRcdHZhciBpZHMgPSB7fVxuXHRcdFx0XHR2YXIgbGFzdElkID0gMFxuXG5cdFx0XHRcdGZvciAodmFyIGkkMiA9IDAsIHB0ciA9IDAsIGwgPSBzdGF0ZS5jb3VudDsgaSQyIDwgbDsgaSQyKyspIHtcblx0XHRcdFx0XHR2YXIgeCA9IHBvc2l0aW9uc1tpJDIqMl1cblx0XHRcdFx0XHR2YXIgeSA9IHBvc2l0aW9uc1tpJDIqMiArIDFdXG5cdFx0XHRcdFx0aWYgKGlzTmFOKHgpIHx8IGlzTmFOKHkpIHx8IHggPT0gbnVsbCB8fCB5ID09IG51bGwpIHtcblx0XHRcdFx0XHRcdHggPSBwb3NpdGlvbnNbbGFzdElkKjJdXG5cdFx0XHRcdFx0XHR5ID0gcG9zaXRpb25zW2xhc3RJZCoyICsgMV1cblx0XHRcdFx0XHRcdGlkc1tpJDJdID0gbGFzdElkXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0bGFzdElkID0gaSQyXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHBvc1twdHIrK10gPSB4XG5cdFx0XHRcdFx0cG9zW3B0cisrXSA9IHlcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHZhciB0cmlhbmdsZXMgPSB0cmlhbmd1bGF0ZShwb3MsIHN0YXRlLmhvbGUgfHwgW10pXG5cblx0XHRcdFx0Zm9yICh2YXIgaSQzID0gMCwgbCQxID0gdHJpYW5nbGVzLmxlbmd0aDsgaSQzIDwgbCQxOyBpJDMrKykge1xuXHRcdFx0XHRcdGlmIChpZHNbdHJpYW5nbGVzW2kkM11dICE9IG51bGwpIHsgdHJpYW5nbGVzW2kkM10gPSBpZHNbdHJpYW5nbGVzW2kkM11dIH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHN0YXRlLnRyaWFuZ2xlcyA9IHRyaWFuZ2xlc1xuXHRcdFx0fVxuXG5cdFx0XHQvLyB1cGRhdGUgcG9zaXRpb24gYnVmZmVyc1xuXHRcdFx0dmFyIG5wb3MgPSBuZXcgRmxvYXQ2NEFycmF5KHBvc2l0aW9ucylcblx0XHRcdG5vcm1hbGl6ZShucG9zLCAyLCBib3VuZHMpXG5cblx0XHRcdHZhciBwb3NpdGlvbkRhdGEgPSBuZXcgRmxvYXQ2NEFycmF5KGNvdW50ICogMiArIDYpXG5cblx0XHRcdC8vIHJvdGF0ZSBmaXJzdCBzZWdtZW50IGpvaW5cblx0XHRcdGlmIChzdGF0ZS5jbG9zZSkge1xuXHRcdFx0XHRpZiAocG9zaXRpb25zWzBdID09PSBwb3NpdGlvbnNbY291bnQqMiAtIDJdICYmXG5cdFx0XHRcdFx0cG9zaXRpb25zWzFdID09PSBwb3NpdGlvbnNbY291bnQqMiAtIDFdKSB7XG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhWzBdID0gbnBvc1tjb3VudCoyIC0gNF1cblx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbMV0gPSBucG9zW2NvdW50KjIgLSAzXVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdHBvc2l0aW9uRGF0YVswXSA9IG5wb3NbY291bnQqMiAtIDJdXG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhWzFdID0gbnBvc1tjb3VudCoyIC0gMV1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHBvc2l0aW9uRGF0YVswXSA9IG5wb3NbMF1cblx0XHRcdFx0cG9zaXRpb25EYXRhWzFdID0gbnBvc1sxXVxuXHRcdFx0fVxuXG5cdFx0XHRwb3NpdGlvbkRhdGEuc2V0KG5wb3MsIDIpXG5cblx0XHRcdC8vIGFkZCBsYXN0IHNlZ21lbnRcblx0XHRcdGlmIChzdGF0ZS5jbG9zZSkge1xuXHRcdFx0XHQvLyBpZ25vcmUgY29pbmNpZGluZyBzdGFydC9lbmRcblx0XHRcdFx0aWYgKHBvc2l0aW9uc1swXSA9PT0gcG9zaXRpb25zW2NvdW50KjIgLSAyXSAmJlxuXHRcdFx0XHRcdHBvc2l0aW9uc1sxXSA9PT0gcG9zaXRpb25zW2NvdW50KjIgLSAxXSkge1xuXHRcdFx0XHRcdHBvc2l0aW9uRGF0YVtjb3VudCoyICsgMl0gPSBucG9zWzJdXG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhW2NvdW50KjIgKyAzXSA9IG5wb3NbM11cblx0XHRcdFx0XHRzdGF0ZS5jb3VudCAtPSAxXG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhW2NvdW50KjIgKyAyXSA9IG5wb3NbMF1cblx0XHRcdFx0XHRwb3NpdGlvbkRhdGFbY291bnQqMiArIDNdID0gbnBvc1sxXVxuXHRcdFx0XHRcdHBvc2l0aW9uRGF0YVtjb3VudCoyICsgNF0gPSBucG9zWzJdXG5cdFx0XHRcdFx0cG9zaXRpb25EYXRhW2NvdW50KjIgKyA1XSA9IG5wb3NbM11cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Ly8gYWRkIHN0dWJcblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRwb3NpdGlvbkRhdGFbY291bnQqMiArIDJdID0gbnBvc1tjb3VudCoyIC0gMl1cblx0XHRcdFx0cG9zaXRpb25EYXRhW2NvdW50KjIgKyAzXSA9IG5wb3NbY291bnQqMiAtIDFdXG5cdFx0XHRcdHBvc2l0aW9uRGF0YVtjb3VudCoyICsgNF0gPSBucG9zW2NvdW50KjIgLSAyXVxuXHRcdFx0XHRwb3NpdGlvbkRhdGFbY291bnQqMiArIDVdID0gbnBvc1tjb3VudCoyIC0gMV1cblx0XHRcdH1cblxuXHRcdFx0c3RhdGUucG9zaXRpb25CdWZmZXIoZmxvYXQzMihwb3NpdGlvbkRhdGEpKVxuXHRcdFx0c3RhdGUucG9zaXRpb25GcmFjdEJ1ZmZlcihmcmFjdDMyKHBvc2l0aW9uRGF0YSkpXG5cdFx0fVxuXG5cdFx0aWYgKG8ucmFuZ2UpIHtcblx0XHRcdHN0YXRlLnJhbmdlID0gby5yYW5nZVxuXHRcdH0gZWxzZSBpZiAoIXN0YXRlLnJhbmdlKSB7XG5cdFx0XHRzdGF0ZS5yYW5nZSA9IHN0YXRlLmJvdW5kc1xuXHRcdH1cblxuXHRcdGlmICgoby5yYW5nZSB8fCBvLnBvc2l0aW9ucykgJiYgc3RhdGUuY291bnQpIHtcblx0XHRcdHZhciBib3VuZHMkMSA9IHN0YXRlLmJvdW5kc1xuXG5cdFx0XHR2YXIgYm91bmRzVyA9IGJvdW5kcyQxWzJdIC0gYm91bmRzJDFbMF0sXG5cdFx0XHRcdGJvdW5kc0ggPSBib3VuZHMkMVszXSAtIGJvdW5kcyQxWzFdXG5cblx0XHRcdHZhciByYW5nZVcgPSBzdGF0ZS5yYW5nZVsyXSAtIHN0YXRlLnJhbmdlWzBdLFxuXHRcdFx0XHRyYW5nZUggPSBzdGF0ZS5yYW5nZVszXSAtIHN0YXRlLnJhbmdlWzFdXG5cblx0XHRcdHN0YXRlLnNjYWxlID0gW1xuXHRcdFx0XHRib3VuZHNXIC8gcmFuZ2VXLFxuXHRcdFx0XHRib3VuZHNIIC8gcmFuZ2VIXG5cdFx0XHRdXG5cdFx0XHRzdGF0ZS50cmFuc2xhdGUgPSBbXG5cdFx0XHRcdC1zdGF0ZS5yYW5nZVswXSAvIHJhbmdlVyArIGJvdW5kcyQxWzBdIC8gcmFuZ2VXIHx8IDAsXG5cdFx0XHRcdC1zdGF0ZS5yYW5nZVsxXSAvIHJhbmdlSCArIGJvdW5kcyQxWzFdIC8gcmFuZ2VIIHx8IDBcblx0XHRcdF1cblxuXHRcdFx0c3RhdGUuc2NhbGVGcmFjdCA9IGZyYWN0MzIoc3RhdGUuc2NhbGUpXG5cdFx0XHRzdGF0ZS50cmFuc2xhdGVGcmFjdCA9IGZyYWN0MzIoc3RhdGUudHJhbnNsYXRlKVxuXHRcdH1cblxuXHRcdGlmIChvLmRhc2hlcykge1xuXHRcdFx0dmFyIGRhc2hMZW5ndGggPSAwLiwgZGFzaERhdGFcblxuXHRcdFx0aWYgKCFvLmRhc2hlcyB8fCBvLmRhc2hlcy5sZW5ndGggPCAyKSB7XG5cdFx0XHRcdGRhc2hMZW5ndGggPSAxLlxuXHRcdFx0XHRkYXNoRGF0YSA9IG5ldyBVaW50OEFycmF5KFsyNTUsIDI1NSwgMjU1LCAyNTUsIDI1NSwgMjU1LCAyNTUsIDI1NV0pXG5cdFx0XHR9XG5cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRkYXNoTGVuZ3RoID0gMC47XG5cdFx0XHRcdGZvcih2YXIgaSQ0ID0gMDsgaSQ0IDwgby5kYXNoZXMubGVuZ3RoOyArK2kkNCkge1xuXHRcdFx0XHRcdGRhc2hMZW5ndGggKz0gby5kYXNoZXNbaSQ0XVxuXHRcdFx0XHR9XG5cdFx0XHRcdGRhc2hEYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGFzaExlbmd0aCAqIExpbmUyRC5kYXNoTXVsdClcblx0XHRcdFx0dmFyIHB0ciQxID0gMFxuXHRcdFx0XHR2YXIgZmlsbENvbG9yID0gMjU1XG5cblx0XHRcdFx0Ly8gcmVwZWF0IHRleHR1cmUgdHdvIHRpbWVzIHRvIHByb3ZpZGUgc21vb3RoIDAtc3RlcFxuXHRcdFx0XHRmb3IgKHZhciBrID0gMDsgayA8IDI7IGsrKykge1xuXHRcdFx0XHRcdGZvcih2YXIgaSQ1ID0gMDsgaSQ1IDwgby5kYXNoZXMubGVuZ3RoOyArK2kkNSkge1xuXHRcdFx0XHRcdFx0Zm9yKHZhciBqID0gMCwgbCQyID0gby5kYXNoZXNbaSQ1XSAqIExpbmUyRC5kYXNoTXVsdCAqIC41OyBqIDwgbCQyOyArK2opIHtcblx0XHRcdFx0XHRcdFx0ZGFzaERhdGFbcHRyJDErK10gPSBmaWxsQ29sb3Jcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGZpbGxDb2xvciBePSAyNTVcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0c3RhdGUuZGFzaExlbmd0aCA9IGRhc2hMZW5ndGhcblx0XHRcdHN0YXRlLmRhc2hUZXh0dXJlKHtcblx0XHRcdFx0Y2hhbm5lbHM6IDEsXG5cdFx0XHRcdGRhdGE6IGRhc2hEYXRhLFxuXHRcdFx0XHR3aWR0aDogZGFzaERhdGEubGVuZ3RoLFxuXHRcdFx0XHRoZWlnaHQ6IDEsXG5cdFx0XHRcdG1hZzogJ2xpbmVhcicsXG5cdFx0XHRcdG1pbjogJ2xpbmVhcidcblx0XHRcdH0sIDAsIDApXG5cdFx0fVxuXG5cdFx0aWYgKG8uY29sb3IpIHtcblx0XHRcdHZhciBjb3VudCQxID0gc3RhdGUuY291bnRcblx0XHRcdHZhciBjb2xvcnMgPSBvLmNvbG9yXG5cblx0XHRcdGlmICghY29sb3JzKSB7IGNvbG9ycyA9ICd0cmFuc3BhcmVudCcgfVxuXG5cdFx0XHR2YXIgY29sb3JEYXRhID0gbmV3IFVpbnQ4QXJyYXkoY291bnQkMSAqIDQgKyA0KVxuXG5cdFx0XHQvLyBjb252ZXJ0IGNvbG9ycyB0byB0eXBlZCBhcnJheXNcblx0XHRcdGlmICghQXJyYXkuaXNBcnJheShjb2xvcnMpIHx8IHR5cGVvZiBjb2xvcnNbMF0gPT09ICdudW1iZXInKSB7XG5cdFx0XHRcdHZhciBjID0gcmdiYShjb2xvcnMsICd1aW50OCcpXG5cblx0XHRcdFx0Zm9yICh2YXIgaSQ2ID0gMDsgaSQ2IDwgY291bnQkMSArIDE7IGkkNisrKSB7XG5cdFx0XHRcdFx0Y29sb3JEYXRhLnNldChjLCBpJDYgKiA0KVxuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb3IgKHZhciBpJDcgPSAwOyBpJDcgPCBjb3VudCQxOyBpJDcrKykge1xuXHRcdFx0XHRcdHZhciBjJDEgPSByZ2JhKGNvbG9yc1tpJDddLCAndWludDgnKVxuXHRcdFx0XHRcdGNvbG9yRGF0YS5zZXQoYyQxLCBpJDcgKiA0KVxuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbG9yRGF0YS5zZXQocmdiYShjb2xvcnNbMF0sICd1aW50OCcpLCBjb3VudCQxICogNClcblx0XHRcdH1cblxuXHRcdFx0c3RhdGUuY29sb3JCdWZmZXIoe1xuXHRcdFx0XHR1c2FnZTogJ2R5bmFtaWMnLFxuXHRcdFx0XHR0eXBlOiAndWludDgnLFxuXHRcdFx0XHRkYXRhOiBjb2xvckRhdGFcblx0XHRcdH0pXG5cdFx0fVxuXHR9KVxuXG5cdC8vIHJlbW92ZSB1bm1lbnRpb25lZCBwYXNzZXNcblx0aWYgKG9wdGlvbnMubGVuZ3RoIDwgdGhpcy5wYXNzZXMubGVuZ3RoKSB7XG5cdFx0Zm9yICh2YXIgaSA9IG9wdGlvbnMubGVuZ3RoOyBpIDwgdGhpcy5wYXNzZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHZhciBwYXNzID0gdGhpcyQxLnBhc3Nlc1tpXVxuXHRcdFx0aWYgKCFwYXNzKSB7IGNvbnRpbnVlIH1cblx0XHRcdHBhc3MuY29sb3JCdWZmZXIuZGVzdHJveSgpXG5cdFx0XHRwYXNzLnBvc2l0aW9uQnVmZmVyLmRlc3Ryb3koKVxuXHRcdFx0cGFzcy5kYXNoVGV4dHVyZS5kZXN0cm95KClcblx0XHR9XG5cdFx0dGhpcy5wYXNzZXMubGVuZ3RoID0gb3B0aW9ucy5sZW5ndGhcblx0fVxuXG5cdC8vIHJlbW92ZSBudWxsIGl0ZW1zXG5cdHZhciBwYXNzZXMgPSBbXVxuXHRmb3IgKHZhciBpJDEgPSAwOyBpJDEgPCB0aGlzLnBhc3Nlcy5sZW5ndGg7IGkkMSsrKSB7XG5cdFx0aWYgKHRoaXMkMS5wYXNzZXNbaSQxXSAhPT0gbnVsbCkgeyBwYXNzZXMucHVzaCh0aGlzJDEucGFzc2VzW2kkMV0pIH1cblx0fVxuXHR0aGlzLnBhc3NlcyA9IHBhc3Nlc1xuXG5cdHJldHVybiB0aGlzXG59XG5cbkxpbmUyRC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcblx0dGhpcy5wYXNzZXMuZm9yRWFjaChmdW5jdGlvbiAocGFzcykge1xuXHRcdHBhc3MuY29sb3JCdWZmZXIuZGVzdHJveSgpXG5cdFx0cGFzcy5wb3NpdGlvbkJ1ZmZlci5kZXN0cm95KClcblx0XHRwYXNzLmRhc2hUZXh0dXJlLmRlc3Ryb3koKVxuXHR9KVxuXG5cdHRoaXMucGFzc2VzLmxlbmd0aCA9IDBcblxuXHRyZXR1cm4gdGhpc1xufVxuXG59LHtcImFycmF5LWJvdW5kc1wiOjY1LFwiYXJyYXktbm9ybWFsaXplXCI6NjYsXCJjb2xvci1ub3JtYWxpemVcIjoxMjAsXCJlYXJjdXRcIjo0OTIsXCJlczYtd2Vhay1tYXBcIjo0OTMsXCJmbGF0dGVuLXZlcnRleC1kYXRhXCI6MjI3LFwiZ2xzbGlmeVwiOjQwOSxcIm9iamVjdC1hc3NpZ25cIjo0NTQsXCJwYXJzZS1yZWN0XCI6NDU5LFwicGljay1ieS1hbGlhc1wiOjQ2NSxcInRvLWZsb2F0MzJcIjo1Mzh9XSw0OTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGVhcmN1dDtcbm1vZHVsZS5leHBvcnRzLmRlZmF1bHQgPSBlYXJjdXQ7XG5cbmZ1bmN0aW9uIGVhcmN1dChkYXRhLCBob2xlSW5kaWNlcywgZGltKSB7XG5cbiAgICBkaW0gPSBkaW0gfHwgMjtcblxuICAgIHZhciBoYXNIb2xlcyA9IGhvbGVJbmRpY2VzICYmIGhvbGVJbmRpY2VzLmxlbmd0aCxcbiAgICAgICAgb3V0ZXJMZW4gPSBoYXNIb2xlcyA/IGhvbGVJbmRpY2VzWzBdICogZGltIDogZGF0YS5sZW5ndGgsXG4gICAgICAgIG91dGVyTm9kZSA9IGxpbmtlZExpc3QoZGF0YSwgMCwgb3V0ZXJMZW4sIGRpbSwgdHJ1ZSksXG4gICAgICAgIHRyaWFuZ2xlcyA9IFtdO1xuXG4gICAgaWYgKCFvdXRlck5vZGUgfHwgb3V0ZXJOb2RlLm5leHQgPT09IG91dGVyTm9kZS5wcmV2KSByZXR1cm4gdHJpYW5nbGVzO1xuXG4gICAgdmFyIG1pblgsIG1pblksIG1heFgsIG1heFksIHgsIHksIGludlNpemU7XG5cbiAgICBpZiAoaGFzSG9sZXMpIG91dGVyTm9kZSA9IGVsaW1pbmF0ZUhvbGVzKGRhdGEsIGhvbGVJbmRpY2VzLCBvdXRlck5vZGUsIGRpbSk7XG5cbiAgICAvLyBpZiB0aGUgc2hhcGUgaXMgbm90IHRvbyBzaW1wbGUsIHdlJ2xsIHVzZSB6LW9yZGVyIGN1cnZlIGhhc2ggbGF0ZXI7IGNhbGN1bGF0ZSBwb2x5Z29uIGJib3hcbiAgICBpZiAoZGF0YS5sZW5ndGggPiA4MCAqIGRpbSkge1xuICAgICAgICBtaW5YID0gbWF4WCA9IGRhdGFbMF07XG4gICAgICAgIG1pblkgPSBtYXhZID0gZGF0YVsxXTtcblxuICAgICAgICBmb3IgKHZhciBpID0gZGltOyBpIDwgb3V0ZXJMZW47IGkgKz0gZGltKSB7XG4gICAgICAgICAgICB4ID0gZGF0YVtpXTtcbiAgICAgICAgICAgIHkgPSBkYXRhW2kgKyAxXTtcbiAgICAgICAgICAgIGlmICh4IDwgbWluWCkgbWluWCA9IHg7XG4gICAgICAgICAgICBpZiAoeSA8IG1pblkpIG1pblkgPSB5O1xuICAgICAgICAgICAgaWYgKHggPiBtYXhYKSBtYXhYID0geDtcbiAgICAgICAgICAgIGlmICh5ID4gbWF4WSkgbWF4WSA9IHk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBtaW5YLCBtaW5ZIGFuZCBpbnZTaXplIGFyZSBsYXRlciB1c2VkIHRvIHRyYW5zZm9ybSBjb29yZHMgaW50byBpbnRlZ2VycyBmb3Igei1vcmRlciBjYWxjdWxhdGlvblxuICAgICAgICBpbnZTaXplID0gTWF0aC5tYXgobWF4WCAtIG1pblgsIG1heFkgLSBtaW5ZKTtcbiAgICAgICAgaW52U2l6ZSA9IGludlNpemUgIT09IDAgPyAxIC8gaW52U2l6ZSA6IDA7XG4gICAgfVxuXG4gICAgZWFyY3V0TGlua2VkKG91dGVyTm9kZSwgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUpO1xuXG4gICAgcmV0dXJuIHRyaWFuZ2xlcztcbn1cblxuLy8gY3JlYXRlIGEgY2lyY3VsYXIgZG91Ymx5IGxpbmtlZCBsaXN0IGZyb20gcG9seWdvbiBwb2ludHMgaW4gdGhlIHNwZWNpZmllZCB3aW5kaW5nIG9yZGVyXG5mdW5jdGlvbiBsaW5rZWRMaXN0KGRhdGEsIHN0YXJ0LCBlbmQsIGRpbSwgY2xvY2t3aXNlKSB7XG4gICAgdmFyIGksIGxhc3Q7XG5cbiAgICBpZiAoY2xvY2t3aXNlID09PSAoc2lnbmVkQXJlYShkYXRhLCBzdGFydCwgZW5kLCBkaW0pID4gMCkpIHtcbiAgICAgICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkgKz0gZGltKSBsYXN0ID0gaW5zZXJ0Tm9kZShpLCBkYXRhW2ldLCBkYXRhW2kgKyAxXSwgbGFzdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yIChpID0gZW5kIC0gZGltOyBpID49IHN0YXJ0OyBpIC09IGRpbSkgbGFzdCA9IGluc2VydE5vZGUoaSwgZGF0YVtpXSwgZGF0YVtpICsgMV0sIGxhc3QpO1xuICAgIH1cblxuICAgIGlmIChsYXN0ICYmIGVxdWFscyhsYXN0LCBsYXN0Lm5leHQpKSB7XG4gICAgICAgIHJlbW92ZU5vZGUobGFzdCk7XG4gICAgICAgIGxhc3QgPSBsYXN0Lm5leHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxhc3Q7XG59XG5cbi8vIGVsaW1pbmF0ZSBjb2xpbmVhciBvciBkdXBsaWNhdGUgcG9pbnRzXG5mdW5jdGlvbiBmaWx0ZXJQb2ludHMoc3RhcnQsIGVuZCkge1xuICAgIGlmICghc3RhcnQpIHJldHVybiBzdGFydDtcbiAgICBpZiAoIWVuZCkgZW5kID0gc3RhcnQ7XG5cbiAgICB2YXIgcCA9IHN0YXJ0LFxuICAgICAgICBhZ2FpbjtcbiAgICBkbyB7XG4gICAgICAgIGFnYWluID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKCFwLnN0ZWluZXIgJiYgKGVxdWFscyhwLCBwLm5leHQpIHx8IGFyZWEocC5wcmV2LCBwLCBwLm5leHQpID09PSAwKSkge1xuICAgICAgICAgICAgcmVtb3ZlTm9kZShwKTtcbiAgICAgICAgICAgIHAgPSBlbmQgPSBwLnByZXY7XG4gICAgICAgICAgICBpZiAocCA9PT0gcC5uZXh0KSBicmVhaztcbiAgICAgICAgICAgIGFnYWluID0gdHJ1ZTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcCA9IHAubmV4dDtcbiAgICAgICAgfVxuICAgIH0gd2hpbGUgKGFnYWluIHx8IHAgIT09IGVuZCk7XG5cbiAgICByZXR1cm4gZW5kO1xufVxuXG4vLyBtYWluIGVhciBzbGljaW5nIGxvb3Agd2hpY2ggdHJpYW5ndWxhdGVzIGEgcG9seWdvbiAoZ2l2ZW4gYXMgYSBsaW5rZWQgbGlzdClcbmZ1bmN0aW9uIGVhcmN1dExpbmtlZChlYXIsIHRyaWFuZ2xlcywgZGltLCBtaW5YLCBtaW5ZLCBpbnZTaXplLCBwYXNzKSB7XG4gICAgaWYgKCFlYXIpIHJldHVybjtcblxuICAgIC8vIGludGVybGluayBwb2x5Z29uIG5vZGVzIGluIHotb3JkZXJcbiAgICBpZiAoIXBhc3MgJiYgaW52U2l6ZSkgaW5kZXhDdXJ2ZShlYXIsIG1pblgsIG1pblksIGludlNpemUpO1xuXG4gICAgdmFyIHN0b3AgPSBlYXIsXG4gICAgICAgIHByZXYsIG5leHQ7XG5cbiAgICAvLyBpdGVyYXRlIHRocm91Z2ggZWFycywgc2xpY2luZyB0aGVtIG9uZSBieSBvbmVcbiAgICB3aGlsZSAoZWFyLnByZXYgIT09IGVhci5uZXh0KSB7XG4gICAgICAgIHByZXYgPSBlYXIucHJldjtcbiAgICAgICAgbmV4dCA9IGVhci5uZXh0O1xuXG4gICAgICAgIGlmIChpbnZTaXplID8gaXNFYXJIYXNoZWQoZWFyLCBtaW5YLCBtaW5ZLCBpbnZTaXplKSA6IGlzRWFyKGVhcikpIHtcbiAgICAgICAgICAgIC8vIGN1dCBvZmYgdGhlIHRyaWFuZ2xlXG4gICAgICAgICAgICB0cmlhbmdsZXMucHVzaChwcmV2LmkgLyBkaW0pO1xuICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goZWFyLmkgLyBkaW0pO1xuICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2gobmV4dC5pIC8gZGltKTtcblxuICAgICAgICAgICAgcmVtb3ZlTm9kZShlYXIpO1xuXG4gICAgICAgICAgICAvLyBza2lwcGluZyB0aGUgbmV4dCB2ZXJ0ZXggbGVhZHMgdG8gbGVzcyBzbGl2ZXIgdHJpYW5nbGVzXG4gICAgICAgICAgICBlYXIgPSBuZXh0Lm5leHQ7XG4gICAgICAgICAgICBzdG9wID0gbmV4dC5uZXh0O1xuXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVhciA9IG5leHQ7XG5cbiAgICAgICAgLy8gaWYgd2UgbG9vcGVkIHRocm91Z2ggdGhlIHdob2xlIHJlbWFpbmluZyBwb2x5Z29uIGFuZCBjYW4ndCBmaW5kIGFueSBtb3JlIGVhcnNcbiAgICAgICAgaWYgKGVhciA9PT0gc3RvcCkge1xuICAgICAgICAgICAgLy8gdHJ5IGZpbHRlcmluZyBwb2ludHMgYW5kIHNsaWNpbmcgYWdhaW5cbiAgICAgICAgICAgIGlmICghcGFzcykge1xuICAgICAgICAgICAgICAgIGVhcmN1dExpbmtlZChmaWx0ZXJQb2ludHMoZWFyKSwgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUsIDEpO1xuXG4gICAgICAgICAgICAvLyBpZiB0aGlzIGRpZG4ndCB3b3JrLCB0cnkgY3VyaW5nIGFsbCBzbWFsbCBzZWxmLWludGVyc2VjdGlvbnMgbG9jYWxseVxuICAgICAgICAgICAgfSBlbHNlIGlmIChwYXNzID09PSAxKSB7XG4gICAgICAgICAgICAgICAgZWFyID0gY3VyZUxvY2FsSW50ZXJzZWN0aW9ucyhlYXIsIHRyaWFuZ2xlcywgZGltKTtcbiAgICAgICAgICAgICAgICBlYXJjdXRMaW5rZWQoZWFyLCB0cmlhbmdsZXMsIGRpbSwgbWluWCwgbWluWSwgaW52U2l6ZSwgMik7XG5cbiAgICAgICAgICAgIC8vIGFzIGEgbGFzdCByZXNvcnQsIHRyeSBzcGxpdHRpbmcgdGhlIHJlbWFpbmluZyBwb2x5Z29uIGludG8gdHdvXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBhc3MgPT09IDIpIHtcbiAgICAgICAgICAgICAgICBzcGxpdEVhcmN1dChlYXIsIHRyaWFuZ2xlcywgZGltLCBtaW5YLCBtaW5ZLCBpbnZTaXplKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8vIGNoZWNrIHdoZXRoZXIgYSBwb2x5Z29uIG5vZGUgZm9ybXMgYSB2YWxpZCBlYXIgd2l0aCBhZGphY2VudCBub2Rlc1xuZnVuY3Rpb24gaXNFYXIoZWFyKSB7XG4gICAgdmFyIGEgPSBlYXIucHJldixcbiAgICAgICAgYiA9IGVhcixcbiAgICAgICAgYyA9IGVhci5uZXh0O1xuXG4gICAgaWYgKGFyZWEoYSwgYiwgYykgPj0gMCkgcmV0dXJuIGZhbHNlOyAvLyByZWZsZXgsIGNhbid0IGJlIGFuIGVhclxuXG4gICAgLy8gbm93IG1ha2Ugc3VyZSB3ZSBkb24ndCBoYXZlIG90aGVyIHBvaW50cyBpbnNpZGUgdGhlIHBvdGVudGlhbCBlYXJcbiAgICB2YXIgcCA9IGVhci5uZXh0Lm5leHQ7XG5cbiAgICB3aGlsZSAocCAhPT0gZWFyLnByZXYpIHtcbiAgICAgICAgaWYgKHBvaW50SW5UcmlhbmdsZShhLngsIGEueSwgYi54LCBiLnksIGMueCwgYy55LCBwLngsIHAueSkgJiZcbiAgICAgICAgICAgIGFyZWEocC5wcmV2LCBwLCBwLm5leHQpID49IDApIHJldHVybiBmYWxzZTtcbiAgICAgICAgcCA9IHAubmV4dDtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaXNFYXJIYXNoZWQoZWFyLCBtaW5YLCBtaW5ZLCBpbnZTaXplKSB7XG4gICAgdmFyIGEgPSBlYXIucHJldixcbiAgICAgICAgYiA9IGVhcixcbiAgICAgICAgYyA9IGVhci5uZXh0O1xuXG4gICAgaWYgKGFyZWEoYSwgYiwgYykgPj0gMCkgcmV0dXJuIGZhbHNlOyAvLyByZWZsZXgsIGNhbid0IGJlIGFuIGVhclxuXG4gICAgLy8gdHJpYW5nbGUgYmJveDsgbWluICYgbWF4IGFyZSBjYWxjdWxhdGVkIGxpa2UgdGhpcyBmb3Igc3BlZWRcbiAgICB2YXIgbWluVFggPSBhLnggPCBiLnggPyAoYS54IDwgYy54ID8gYS54IDogYy54KSA6IChiLnggPCBjLnggPyBiLnggOiBjLngpLFxuICAgICAgICBtaW5UWSA9IGEueSA8IGIueSA/IChhLnkgPCBjLnkgPyBhLnkgOiBjLnkpIDogKGIueSA8IGMueSA/IGIueSA6IGMueSksXG4gICAgICAgIG1heFRYID0gYS54ID4gYi54ID8gKGEueCA+IGMueCA/IGEueCA6IGMueCkgOiAoYi54ID4gYy54ID8gYi54IDogYy54KSxcbiAgICAgICAgbWF4VFkgPSBhLnkgPiBiLnkgPyAoYS55ID4gYy55ID8gYS55IDogYy55KSA6IChiLnkgPiBjLnkgPyBiLnkgOiBjLnkpO1xuXG4gICAgLy8gei1vcmRlciByYW5nZSBmb3IgdGhlIGN1cnJlbnQgdHJpYW5nbGUgYmJveDtcbiAgICB2YXIgbWluWiA9IHpPcmRlcihtaW5UWCwgbWluVFksIG1pblgsIG1pblksIGludlNpemUpLFxuICAgICAgICBtYXhaID0gek9yZGVyKG1heFRYLCBtYXhUWSwgbWluWCwgbWluWSwgaW52U2l6ZSk7XG5cbiAgICB2YXIgcCA9IGVhci5wcmV2WixcbiAgICAgICAgbiA9IGVhci5uZXh0WjtcblxuICAgIC8vIGxvb2sgZm9yIHBvaW50cyBpbnNpZGUgdGhlIHRyaWFuZ2xlIGluIGJvdGggZGlyZWN0aW9uc1xuICAgIHdoaWxlIChwICYmIHAueiA+PSBtaW5aICYmIG4gJiYgbi56IDw9IG1heFopIHtcbiAgICAgICAgaWYgKHAgIT09IGVhci5wcmV2ICYmIHAgIT09IGVhci5uZXh0ICYmXG4gICAgICAgICAgICBwb2ludEluVHJpYW5nbGUoYS54LCBhLnksIGIueCwgYi55LCBjLngsIGMueSwgcC54LCBwLnkpICYmXG4gICAgICAgICAgICBhcmVhKHAucHJldiwgcCwgcC5uZXh0KSA+PSAwKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHAgPSBwLnByZXZaO1xuXG4gICAgICAgIGlmIChuICE9PSBlYXIucHJldiAmJiBuICE9PSBlYXIubmV4dCAmJlxuICAgICAgICAgICAgcG9pbnRJblRyaWFuZ2xlKGEueCwgYS55LCBiLngsIGIueSwgYy54LCBjLnksIG4ueCwgbi55KSAmJlxuICAgICAgICAgICAgYXJlYShuLnByZXYsIG4sIG4ubmV4dCkgPj0gMCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBuID0gbi5uZXh0WjtcbiAgICB9XG5cbiAgICAvLyBsb29rIGZvciByZW1haW5pbmcgcG9pbnRzIGluIGRlY3JlYXNpbmcgei1vcmRlclxuICAgIHdoaWxlIChwICYmIHAueiA+PSBtaW5aKSB7XG4gICAgICAgIGlmIChwICE9PSBlYXIucHJldiAmJiBwICE9PSBlYXIubmV4dCAmJlxuICAgICAgICAgICAgcG9pbnRJblRyaWFuZ2xlKGEueCwgYS55LCBiLngsIGIueSwgYy54LCBjLnksIHAueCwgcC55KSAmJlxuICAgICAgICAgICAgYXJlYShwLnByZXYsIHAsIHAubmV4dCkgPj0gMCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBwID0gcC5wcmV2WjtcbiAgICB9XG5cbiAgICAvLyBsb29rIGZvciByZW1haW5pbmcgcG9pbnRzIGluIGluY3JlYXNpbmcgei1vcmRlclxuICAgIHdoaWxlIChuICYmIG4ueiA8PSBtYXhaKSB7XG4gICAgICAgIGlmIChuICE9PSBlYXIucHJldiAmJiBuICE9PSBlYXIubmV4dCAmJlxuICAgICAgICAgICAgcG9pbnRJblRyaWFuZ2xlKGEueCwgYS55LCBiLngsIGIueSwgYy54LCBjLnksIG4ueCwgbi55KSAmJlxuICAgICAgICAgICAgYXJlYShuLnByZXYsIG4sIG4ubmV4dCkgPj0gMCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBuID0gbi5uZXh0WjtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuLy8gZ28gdGhyb3VnaCBhbGwgcG9seWdvbiBub2RlcyBhbmQgY3VyZSBzbWFsbCBsb2NhbCBzZWxmLWludGVyc2VjdGlvbnNcbmZ1bmN0aW9uIGN1cmVMb2NhbEludGVyc2VjdGlvbnMoc3RhcnQsIHRyaWFuZ2xlcywgZGltKSB7XG4gICAgdmFyIHAgPSBzdGFydDtcbiAgICBkbyB7XG4gICAgICAgIHZhciBhID0gcC5wcmV2LFxuICAgICAgICAgICAgYiA9IHAubmV4dC5uZXh0O1xuXG4gICAgICAgIGlmICghZXF1YWxzKGEsIGIpICYmIGludGVyc2VjdHMoYSwgcCwgcC5uZXh0LCBiKSAmJiBsb2NhbGx5SW5zaWRlKGEsIGIpICYmIGxvY2FsbHlJbnNpZGUoYiwgYSkpIHtcblxuICAgICAgICAgICAgdHJpYW5nbGVzLnB1c2goYS5pIC8gZGltKTtcbiAgICAgICAgICAgIHRyaWFuZ2xlcy5wdXNoKHAuaSAvIGRpbSk7XG4gICAgICAgICAgICB0cmlhbmdsZXMucHVzaChiLmkgLyBkaW0pO1xuXG4gICAgICAgICAgICAvLyByZW1vdmUgdHdvIG5vZGVzIGludm9sdmVkXG4gICAgICAgICAgICByZW1vdmVOb2RlKHApO1xuICAgICAgICAgICAgcmVtb3ZlTm9kZShwLm5leHQpO1xuXG4gICAgICAgICAgICBwID0gc3RhcnQgPSBiO1xuICAgICAgICB9XG4gICAgICAgIHAgPSBwLm5leHQ7XG4gICAgfSB3aGlsZSAocCAhPT0gc3RhcnQpO1xuXG4gICAgcmV0dXJuIHA7XG59XG5cbi8vIHRyeSBzcGxpdHRpbmcgcG9seWdvbiBpbnRvIHR3byBhbmQgdHJpYW5ndWxhdGUgdGhlbSBpbmRlcGVuZGVudGx5XG5mdW5jdGlvbiBzcGxpdEVhcmN1dChzdGFydCwgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUpIHtcbiAgICAvLyBsb29rIGZvciBhIHZhbGlkIGRpYWdvbmFsIHRoYXQgZGl2aWRlcyB0aGUgcG9seWdvbiBpbnRvIHR3b1xuICAgIHZhciBhID0gc3RhcnQ7XG4gICAgZG8ge1xuICAgICAgICB2YXIgYiA9IGEubmV4dC5uZXh0O1xuICAgICAgICB3aGlsZSAoYiAhPT0gYS5wcmV2KSB7XG4gICAgICAgICAgICBpZiAoYS5pICE9PSBiLmkgJiYgaXNWYWxpZERpYWdvbmFsKGEsIGIpKSB7XG4gICAgICAgICAgICAgICAgLy8gc3BsaXQgdGhlIHBvbHlnb24gaW4gdHdvIGJ5IHRoZSBkaWFnb25hbFxuICAgICAgICAgICAgICAgIHZhciBjID0gc3BsaXRQb2x5Z29uKGEsIGIpO1xuXG4gICAgICAgICAgICAgICAgLy8gZmlsdGVyIGNvbGluZWFyIHBvaW50cyBhcm91bmQgdGhlIGN1dHNcbiAgICAgICAgICAgICAgICBhID0gZmlsdGVyUG9pbnRzKGEsIGEubmV4dCk7XG4gICAgICAgICAgICAgICAgYyA9IGZpbHRlclBvaW50cyhjLCBjLm5leHQpO1xuXG4gICAgICAgICAgICAgICAgLy8gcnVuIGVhcmN1dCBvbiBlYWNoIGhhbGZcbiAgICAgICAgICAgICAgICBlYXJjdXRMaW5rZWQoYSwgdHJpYW5nbGVzLCBkaW0sIG1pblgsIG1pblksIGludlNpemUpO1xuICAgICAgICAgICAgICAgIGVhcmN1dExpbmtlZChjLCB0cmlhbmdsZXMsIGRpbSwgbWluWCwgbWluWSwgaW52U2l6ZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYiA9IGIubmV4dDtcbiAgICAgICAgfVxuICAgICAgICBhID0gYS5uZXh0O1xuICAgIH0gd2hpbGUgKGEgIT09IHN0YXJ0KTtcbn1cblxuLy8gbGluayBldmVyeSBob2xlIGludG8gdGhlIG91dGVyIGxvb3AsIHByb2R1Y2luZyBhIHNpbmdsZS1yaW5nIHBvbHlnb24gd2l0aG91dCBob2xlc1xuZnVuY3Rpb24gZWxpbWluYXRlSG9sZXMoZGF0YSwgaG9sZUluZGljZXMsIG91dGVyTm9kZSwgZGltKSB7XG4gICAgdmFyIHF1ZXVlID0gW10sXG4gICAgICAgIGksIGxlbiwgc3RhcnQsIGVuZCwgbGlzdDtcblxuICAgIGZvciAoaSA9IDAsIGxlbiA9IGhvbGVJbmRpY2VzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHN0YXJ0ID0gaG9sZUluZGljZXNbaV0gKiBkaW07XG4gICAgICAgIGVuZCA9IGkgPCBsZW4gLSAxID8gaG9sZUluZGljZXNbaSArIDFdICogZGltIDogZGF0YS5sZW5ndGg7XG4gICAgICAgIGxpc3QgPSBsaW5rZWRMaXN0KGRhdGEsIHN0YXJ0LCBlbmQsIGRpbSwgZmFsc2UpO1xuICAgICAgICBpZiAobGlzdCA9PT0gbGlzdC5uZXh0KSBsaXN0LnN0ZWluZXIgPSB0cnVlO1xuICAgICAgICBxdWV1ZS5wdXNoKGdldExlZnRtb3N0KGxpc3QpKTtcbiAgICB9XG5cbiAgICBxdWV1ZS5zb3J0KGNvbXBhcmVYKTtcblxuICAgIC8vIHByb2Nlc3MgaG9sZXMgZnJvbSBsZWZ0IHRvIHJpZ2h0XG4gICAgZm9yIChpID0gMDsgaSA8IHF1ZXVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGVsaW1pbmF0ZUhvbGUocXVldWVbaV0sIG91dGVyTm9kZSk7XG4gICAgICAgIG91dGVyTm9kZSA9IGZpbHRlclBvaW50cyhvdXRlck5vZGUsIG91dGVyTm9kZS5uZXh0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0ZXJOb2RlO1xufVxuXG5mdW5jdGlvbiBjb21wYXJlWChhLCBiKSB7XG4gICAgcmV0dXJuIGEueCAtIGIueDtcbn1cblxuLy8gZmluZCBhIGJyaWRnZSBiZXR3ZWVuIHZlcnRpY2VzIHRoYXQgY29ubmVjdHMgaG9sZSB3aXRoIGFuIG91dGVyIHJpbmcgYW5kIGFuZCBsaW5rIGl0XG5mdW5jdGlvbiBlbGltaW5hdGVIb2xlKGhvbGUsIG91dGVyTm9kZSkge1xuICAgIG91dGVyTm9kZSA9IGZpbmRIb2xlQnJpZGdlKGhvbGUsIG91dGVyTm9kZSk7XG4gICAgaWYgKG91dGVyTm9kZSkge1xuICAgICAgICB2YXIgYiA9IHNwbGl0UG9seWdvbihvdXRlck5vZGUsIGhvbGUpO1xuICAgICAgICBmaWx0ZXJQb2ludHMoYiwgYi5uZXh0KTtcbiAgICB9XG59XG5cbi8vIERhdmlkIEViZXJseSdzIGFsZ29yaXRobSBmb3IgZmluZGluZyBhIGJyaWRnZSBiZXR3ZWVuIGhvbGUgYW5kIG91dGVyIHBvbHlnb25cbmZ1bmN0aW9uIGZpbmRIb2xlQnJpZGdlKGhvbGUsIG91dGVyTm9kZSkge1xuICAgIHZhciBwID0gb3V0ZXJOb2RlLFxuICAgICAgICBoeCA9IGhvbGUueCxcbiAgICAgICAgaHkgPSBob2xlLnksXG4gICAgICAgIHF4ID0gLUluZmluaXR5LFxuICAgICAgICBtO1xuXG4gICAgLy8gZmluZCBhIHNlZ21lbnQgaW50ZXJzZWN0ZWQgYnkgYSByYXkgZnJvbSB0aGUgaG9sZSdzIGxlZnRtb3N0IHBvaW50IHRvIHRoZSBsZWZ0O1xuICAgIC8vIHNlZ21lbnQncyBlbmRwb2ludCB3aXRoIGxlc3NlciB4IHdpbGwgYmUgcG90ZW50aWFsIGNvbm5lY3Rpb24gcG9pbnRcbiAgICBkbyB7XG4gICAgICAgIGlmIChoeSA8PSBwLnkgJiYgaHkgPj0gcC5uZXh0LnkgJiYgcC5uZXh0LnkgIT09IHAueSkge1xuICAgICAgICAgICAgdmFyIHggPSBwLnggKyAoaHkgLSBwLnkpICogKHAubmV4dC54IC0gcC54KSAvIChwLm5leHQueSAtIHAueSk7XG4gICAgICAgICAgICBpZiAoeCA8PSBoeCAmJiB4ID4gcXgpIHtcbiAgICAgICAgICAgICAgICBxeCA9IHg7XG4gICAgICAgICAgICAgICAgaWYgKHggPT09IGh4KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChoeSA9PT0gcC55KSByZXR1cm4gcDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGh5ID09PSBwLm5leHQueSkgcmV0dXJuIHAubmV4dDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbSA9IHAueCA8IHAubmV4dC54ID8gcCA6IHAubmV4dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBwID0gcC5uZXh0O1xuICAgIH0gd2hpbGUgKHAgIT09IG91dGVyTm9kZSk7XG5cbiAgICBpZiAoIW0pIHJldHVybiBudWxsO1xuXG4gICAgaWYgKGh4ID09PSBxeCkgcmV0dXJuIG0ucHJldjsgLy8gaG9sZSB0b3VjaGVzIG91dGVyIHNlZ21lbnQ7IHBpY2sgbG93ZXIgZW5kcG9pbnRcblxuICAgIC8vIGxvb2sgZm9yIHBvaW50cyBpbnNpZGUgdGhlIHRyaWFuZ2xlIG9mIGhvbGUgcG9pbnQsIHNlZ21lbnQgaW50ZXJzZWN0aW9uIGFuZCBlbmRwb2ludDtcbiAgICAvLyBpZiB0aGVyZSBhcmUgbm8gcG9pbnRzIGZvdW5kLCB3ZSBoYXZlIGEgdmFsaWQgY29ubmVjdGlvbjtcbiAgICAvLyBvdGhlcndpc2UgY2hvb3NlIHRoZSBwb2ludCBvZiB0aGUgbWluaW11bSBhbmdsZSB3aXRoIHRoZSByYXkgYXMgY29ubmVjdGlvbiBwb2ludFxuXG4gICAgdmFyIHN0b3AgPSBtLFxuICAgICAgICBteCA9IG0ueCxcbiAgICAgICAgbXkgPSBtLnksXG4gICAgICAgIHRhbk1pbiA9IEluZmluaXR5LFxuICAgICAgICB0YW47XG5cbiAgICBwID0gbS5uZXh0O1xuXG4gICAgd2hpbGUgKHAgIT09IHN0b3ApIHtcbiAgICAgICAgaWYgKGh4ID49IHAueCAmJiBwLnggPj0gbXggJiYgaHggIT09IHAueCAmJlxuICAgICAgICAgICAgICAgIHBvaW50SW5UcmlhbmdsZShoeSA8IG15ID8gaHggOiBxeCwgaHksIG14LCBteSwgaHkgPCBteSA/IHF4IDogaHgsIGh5LCBwLngsIHAueSkpIHtcblxuICAgICAgICAgICAgdGFuID0gTWF0aC5hYnMoaHkgLSBwLnkpIC8gKGh4IC0gcC54KTsgLy8gdGFuZ2VudGlhbFxuXG4gICAgICAgICAgICBpZiAoKHRhbiA8IHRhbk1pbiB8fCAodGFuID09PSB0YW5NaW4gJiYgcC54ID4gbS54KSkgJiYgbG9jYWxseUluc2lkZShwLCBob2xlKSkge1xuICAgICAgICAgICAgICAgIG0gPSBwO1xuICAgICAgICAgICAgICAgIHRhbk1pbiA9IHRhbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHAgPSBwLm5leHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG07XG59XG5cbi8vIGludGVybGluayBwb2x5Z29uIG5vZGVzIGluIHotb3JkZXJcbmZ1bmN0aW9uIGluZGV4Q3VydmUoc3RhcnQsIG1pblgsIG1pblksIGludlNpemUpIHtcbiAgICB2YXIgcCA9IHN0YXJ0O1xuICAgIGRvIHtcbiAgICAgICAgaWYgKHAueiA9PT0gbnVsbCkgcC56ID0gek9yZGVyKHAueCwgcC55LCBtaW5YLCBtaW5ZLCBpbnZTaXplKTtcbiAgICAgICAgcC5wcmV2WiA9IHAucHJldjtcbiAgICAgICAgcC5uZXh0WiA9IHAubmV4dDtcbiAgICAgICAgcCA9IHAubmV4dDtcbiAgICB9IHdoaWxlIChwICE9PSBzdGFydCk7XG5cbiAgICBwLnByZXZaLm5leHRaID0gbnVsbDtcbiAgICBwLnByZXZaID0gbnVsbDtcblxuICAgIHNvcnRMaW5rZWQocCk7XG59XG5cbi8vIFNpbW9uIFRhdGhhbSdzIGxpbmtlZCBsaXN0IG1lcmdlIHNvcnQgYWxnb3JpdGhtXG4vLyBodHRwOi8vd3d3LmNoaWFyay5ncmVlbmVuZC5vcmcudWsvfnNndGF0aGFtL2FsZ29yaXRobXMvbGlzdHNvcnQuaHRtbFxuZnVuY3Rpb24gc29ydExpbmtlZChsaXN0KSB7XG4gICAgdmFyIGksIHAsIHEsIGUsIHRhaWwsIG51bU1lcmdlcywgcFNpemUsIHFTaXplLFxuICAgICAgICBpblNpemUgPSAxO1xuXG4gICAgZG8ge1xuICAgICAgICBwID0gbGlzdDtcbiAgICAgICAgbGlzdCA9IG51bGw7XG4gICAgICAgIHRhaWwgPSBudWxsO1xuICAgICAgICBudW1NZXJnZXMgPSAwO1xuXG4gICAgICAgIHdoaWxlIChwKSB7XG4gICAgICAgICAgICBudW1NZXJnZXMrKztcbiAgICAgICAgICAgIHEgPSBwO1xuICAgICAgICAgICAgcFNpemUgPSAwO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGluU2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcFNpemUrKztcbiAgICAgICAgICAgICAgICBxID0gcS5uZXh0WjtcbiAgICAgICAgICAgICAgICBpZiAoIXEpIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcVNpemUgPSBpblNpemU7XG5cbiAgICAgICAgICAgIHdoaWxlIChwU2l6ZSA+IDAgfHwgKHFTaXplID4gMCAmJiBxKSkge1xuXG4gICAgICAgICAgICAgICAgaWYgKHBTaXplICE9PSAwICYmIChxU2l6ZSA9PT0gMCB8fCAhcSB8fCBwLnogPD0gcS56KSkge1xuICAgICAgICAgICAgICAgICAgICBlID0gcDtcbiAgICAgICAgICAgICAgICAgICAgcCA9IHAubmV4dFo7XG4gICAgICAgICAgICAgICAgICAgIHBTaXplLS07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZSA9IHE7XG4gICAgICAgICAgICAgICAgICAgIHEgPSBxLm5leHRaO1xuICAgICAgICAgICAgICAgICAgICBxU2l6ZS0tO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0YWlsKSB0YWlsLm5leHRaID0gZTtcbiAgICAgICAgICAgICAgICBlbHNlIGxpc3QgPSBlO1xuXG4gICAgICAgICAgICAgICAgZS5wcmV2WiA9IHRhaWw7XG4gICAgICAgICAgICAgICAgdGFpbCA9IGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHAgPSBxO1xuICAgICAgICB9XG5cbiAgICAgICAgdGFpbC5uZXh0WiA9IG51bGw7XG4gICAgICAgIGluU2l6ZSAqPSAyO1xuXG4gICAgfSB3aGlsZSAobnVtTWVyZ2VzID4gMSk7XG5cbiAgICByZXR1cm4gbGlzdDtcbn1cblxuLy8gei1vcmRlciBvZiBhIHBvaW50IGdpdmVuIGNvb3JkcyBhbmQgaW52ZXJzZSBvZiB0aGUgbG9uZ2VyIHNpZGUgb2YgZGF0YSBiYm94XG5mdW5jdGlvbiB6T3JkZXIoeCwgeSwgbWluWCwgbWluWSwgaW52U2l6ZSkge1xuICAgIC8vIGNvb3JkcyBhcmUgdHJhbnNmb3JtZWQgaW50byBub24tbmVnYXRpdmUgMTUtYml0IGludGVnZXIgcmFuZ2VcbiAgICB4ID0gMzI3NjcgKiAoeCAtIG1pblgpICogaW52U2l6ZTtcbiAgICB5ID0gMzI3NjcgKiAoeSAtIG1pblkpICogaW52U2l6ZTtcblxuICAgIHggPSAoeCB8ICh4IDw8IDgpKSAmIDB4MDBGRjAwRkY7XG4gICAgeCA9ICh4IHwgKHggPDwgNCkpICYgMHgwRjBGMEYwRjtcbiAgICB4ID0gKHggfCAoeCA8PCAyKSkgJiAweDMzMzMzMzMzO1xuICAgIHggPSAoeCB8ICh4IDw8IDEpKSAmIDB4NTU1NTU1NTU7XG5cbiAgICB5ID0gKHkgfCAoeSA8PCA4KSkgJiAweDAwRkYwMEZGO1xuICAgIHkgPSAoeSB8ICh5IDw8IDQpKSAmIDB4MEYwRjBGMEY7XG4gICAgeSA9ICh5IHwgKHkgPDwgMikpICYgMHgzMzMzMzMzMztcbiAgICB5ID0gKHkgfCAoeSA8PCAxKSkgJiAweDU1NTU1NTU1O1xuXG4gICAgcmV0dXJuIHggfCAoeSA8PCAxKTtcbn1cblxuLy8gZmluZCB0aGUgbGVmdG1vc3Qgbm9kZSBvZiBhIHBvbHlnb24gcmluZ1xuZnVuY3Rpb24gZ2V0TGVmdG1vc3Qoc3RhcnQpIHtcbiAgICB2YXIgcCA9IHN0YXJ0LFxuICAgICAgICBsZWZ0bW9zdCA9IHN0YXJ0O1xuICAgIGRvIHtcbiAgICAgICAgaWYgKHAueCA8IGxlZnRtb3N0LnggfHwgKHAueCA9PT0gbGVmdG1vc3QueCAmJiBwLnkgPCBsZWZ0bW9zdC55KSkgbGVmdG1vc3QgPSBwO1xuICAgICAgICBwID0gcC5uZXh0O1xuICAgIH0gd2hpbGUgKHAgIT09IHN0YXJ0KTtcblxuICAgIHJldHVybiBsZWZ0bW9zdDtcbn1cblxuLy8gY2hlY2sgaWYgYSBwb2ludCBsaWVzIHdpdGhpbiBhIGNvbnZleCB0cmlhbmdsZVxuZnVuY3Rpb24gcG9pbnRJblRyaWFuZ2xlKGF4LCBheSwgYngsIGJ5LCBjeCwgY3ksIHB4LCBweSkge1xuICAgIHJldHVybiAoY3ggLSBweCkgKiAoYXkgLSBweSkgLSAoYXggLSBweCkgKiAoY3kgLSBweSkgPj0gMCAmJlxuICAgICAgICAgICAoYXggLSBweCkgKiAoYnkgLSBweSkgLSAoYnggLSBweCkgKiAoYXkgLSBweSkgPj0gMCAmJlxuICAgICAgICAgICAoYnggLSBweCkgKiAoY3kgLSBweSkgLSAoY3ggLSBweCkgKiAoYnkgLSBweSkgPj0gMDtcbn1cblxuLy8gY2hlY2sgaWYgYSBkaWFnb25hbCBiZXR3ZWVuIHR3byBwb2x5Z29uIG5vZGVzIGlzIHZhbGlkIChsaWVzIGluIHBvbHlnb24gaW50ZXJpb3IpXG5mdW5jdGlvbiBpc1ZhbGlkRGlhZ29uYWwoYSwgYikge1xuICAgIHJldHVybiBhLm5leHQuaSAhPT0gYi5pICYmIGEucHJldi5pICE9PSBiLmkgJiYgIWludGVyc2VjdHNQb2x5Z29uKGEsIGIpICYmXG4gICAgICAgICAgIGxvY2FsbHlJbnNpZGUoYSwgYikgJiYgbG9jYWxseUluc2lkZShiLCBhKSAmJiBtaWRkbGVJbnNpZGUoYSwgYik7XG59XG5cbi8vIHNpZ25lZCBhcmVhIG9mIGEgdHJpYW5nbGVcbmZ1bmN0aW9uIGFyZWEocCwgcSwgcikge1xuICAgIHJldHVybiAocS55IC0gcC55KSAqIChyLnggLSBxLngpIC0gKHEueCAtIHAueCkgKiAoci55IC0gcS55KTtcbn1cblxuLy8gY2hlY2sgaWYgdHdvIHBvaW50cyBhcmUgZXF1YWxcbmZ1bmN0aW9uIGVxdWFscyhwMSwgcDIpIHtcbiAgICByZXR1cm4gcDEueCA9PT0gcDIueCAmJiBwMS55ID09PSBwMi55O1xufVxuXG4vLyBjaGVjayBpZiB0d28gc2VnbWVudHMgaW50ZXJzZWN0XG5mdW5jdGlvbiBpbnRlcnNlY3RzKHAxLCBxMSwgcDIsIHEyKSB7XG4gICAgaWYgKChlcXVhbHMocDEsIHExKSAmJiBlcXVhbHMocDIsIHEyKSkgfHxcbiAgICAgICAgKGVxdWFscyhwMSwgcTIpICYmIGVxdWFscyhwMiwgcTEpKSkgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIGFyZWEocDEsIHExLCBwMikgPiAwICE9PSBhcmVhKHAxLCBxMSwgcTIpID4gMCAmJlxuICAgICAgICAgICBhcmVhKHAyLCBxMiwgcDEpID4gMCAhPT0gYXJlYShwMiwgcTIsIHExKSA+IDA7XG59XG5cbi8vIGNoZWNrIGlmIGEgcG9seWdvbiBkaWFnb25hbCBpbnRlcnNlY3RzIGFueSBwb2x5Z29uIHNlZ21lbnRzXG5mdW5jdGlvbiBpbnRlcnNlY3RzUG9seWdvbihhLCBiKSB7XG4gICAgdmFyIHAgPSBhO1xuICAgIGRvIHtcbiAgICAgICAgaWYgKHAuaSAhPT0gYS5pICYmIHAubmV4dC5pICE9PSBhLmkgJiYgcC5pICE9PSBiLmkgJiYgcC5uZXh0LmkgIT09IGIuaSAmJlxuICAgICAgICAgICAgICAgIGludGVyc2VjdHMocCwgcC5uZXh0LCBhLCBiKSkgcmV0dXJuIHRydWU7XG4gICAgICAgIHAgPSBwLm5leHQ7XG4gICAgfSB3aGlsZSAocCAhPT0gYSk7XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIGNoZWNrIGlmIGEgcG9seWdvbiBkaWFnb25hbCBpcyBsb2NhbGx5IGluc2lkZSB0aGUgcG9seWdvblxuZnVuY3Rpb24gbG9jYWxseUluc2lkZShhLCBiKSB7XG4gICAgcmV0dXJuIGFyZWEoYS5wcmV2LCBhLCBhLm5leHQpIDwgMCA/XG4gICAgICAgIGFyZWEoYSwgYiwgYS5uZXh0KSA+PSAwICYmIGFyZWEoYSwgYS5wcmV2LCBiKSA+PSAwIDpcbiAgICAgICAgYXJlYShhLCBiLCBhLnByZXYpIDwgMCB8fCBhcmVhKGEsIGEubmV4dCwgYikgPCAwO1xufVxuXG4vLyBjaGVjayBpZiB0aGUgbWlkZGxlIHBvaW50IG9mIGEgcG9seWdvbiBkaWFnb25hbCBpcyBpbnNpZGUgdGhlIHBvbHlnb25cbmZ1bmN0aW9uIG1pZGRsZUluc2lkZShhLCBiKSB7XG4gICAgdmFyIHAgPSBhLFxuICAgICAgICBpbnNpZGUgPSBmYWxzZSxcbiAgICAgICAgcHggPSAoYS54ICsgYi54KSAvIDIsXG4gICAgICAgIHB5ID0gKGEueSArIGIueSkgLyAyO1xuICAgIGRvIHtcbiAgICAgICAgaWYgKCgocC55ID4gcHkpICE9PSAocC5uZXh0LnkgPiBweSkpICYmIHAubmV4dC55ICE9PSBwLnkgJiZcbiAgICAgICAgICAgICAgICAocHggPCAocC5uZXh0LnggLSBwLngpICogKHB5IC0gcC55KSAvIChwLm5leHQueSAtIHAueSkgKyBwLngpKVxuICAgICAgICAgICAgaW5zaWRlID0gIWluc2lkZTtcbiAgICAgICAgcCA9IHAubmV4dDtcbiAgICB9IHdoaWxlIChwICE9PSBhKTtcblxuICAgIHJldHVybiBpbnNpZGU7XG59XG5cbi8vIGxpbmsgdHdvIHBvbHlnb24gdmVydGljZXMgd2l0aCBhIGJyaWRnZTsgaWYgdGhlIHZlcnRpY2VzIGJlbG9uZyB0byB0aGUgc2FtZSByaW5nLCBpdCBzcGxpdHMgcG9seWdvbiBpbnRvIHR3bztcbi8vIGlmIG9uZSBiZWxvbmdzIHRvIHRoZSBvdXRlciByaW5nIGFuZCBhbm90aGVyIHRvIGEgaG9sZSwgaXQgbWVyZ2VzIGl0IGludG8gYSBzaW5nbGUgcmluZ1xuZnVuY3Rpb24gc3BsaXRQb2x5Z29uKGEsIGIpIHtcbiAgICB2YXIgYTIgPSBuZXcgTm9kZShhLmksIGEueCwgYS55KSxcbiAgICAgICAgYjIgPSBuZXcgTm9kZShiLmksIGIueCwgYi55KSxcbiAgICAgICAgYW4gPSBhLm5leHQsXG4gICAgICAgIGJwID0gYi5wcmV2O1xuXG4gICAgYS5uZXh0ID0gYjtcbiAgICBiLnByZXYgPSBhO1xuXG4gICAgYTIubmV4dCA9IGFuO1xuICAgIGFuLnByZXYgPSBhMjtcblxuICAgIGIyLm5leHQgPSBhMjtcbiAgICBhMi5wcmV2ID0gYjI7XG5cbiAgICBicC5uZXh0ID0gYjI7XG4gICAgYjIucHJldiA9IGJwO1xuXG4gICAgcmV0dXJuIGIyO1xufVxuXG4vLyBjcmVhdGUgYSBub2RlIGFuZCBvcHRpb25hbGx5IGxpbmsgaXQgd2l0aCBwcmV2aW91cyBvbmUgKGluIGEgY2lyY3VsYXIgZG91Ymx5IGxpbmtlZCBsaXN0KVxuZnVuY3Rpb24gaW5zZXJ0Tm9kZShpLCB4LCB5LCBsYXN0KSB7XG4gICAgdmFyIHAgPSBuZXcgTm9kZShpLCB4LCB5KTtcblxuICAgIGlmICghbGFzdCkge1xuICAgICAgICBwLnByZXYgPSBwO1xuICAgICAgICBwLm5leHQgPSBwO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgcC5uZXh0ID0gbGFzdC5uZXh0O1xuICAgICAgICBwLnByZXYgPSBsYXN0O1xuICAgICAgICBsYXN0Lm5leHQucHJldiA9IHA7XG4gICAgICAgIGxhc3QubmV4dCA9IHA7XG4gICAgfVxuICAgIHJldHVybiBwO1xufVxuXG5mdW5jdGlvbiByZW1vdmVOb2RlKHApIHtcbiAgICBwLm5leHQucHJldiA9IHAucHJldjtcbiAgICBwLnByZXYubmV4dCA9IHAubmV4dDtcblxuICAgIGlmIChwLnByZXZaKSBwLnByZXZaLm5leHRaID0gcC5uZXh0WjtcbiAgICBpZiAocC5uZXh0WikgcC5uZXh0Wi5wcmV2WiA9IHAucHJldlo7XG59XG5cbmZ1bmN0aW9uIE5vZGUoaSwgeCwgeSkge1xuICAgIC8vIHZlcnRleCBpbmRleCBpbiBjb29yZGluYXRlcyBhcnJheVxuICAgIHRoaXMuaSA9IGk7XG5cbiAgICAvLyB2ZXJ0ZXggY29vcmRpbmF0ZXNcbiAgICB0aGlzLnggPSB4O1xuICAgIHRoaXMueSA9IHk7XG5cbiAgICAvLyBwcmV2aW91cyBhbmQgbmV4dCB2ZXJ0ZXggbm9kZXMgaW4gYSBwb2x5Z29uIHJpbmdcbiAgICB0aGlzLnByZXYgPSBudWxsO1xuICAgIHRoaXMubmV4dCA9IG51bGw7XG5cbiAgICAvLyB6LW9yZGVyIGN1cnZlIHZhbHVlXG4gICAgdGhpcy56ID0gbnVsbDtcblxuICAgIC8vIHByZXZpb3VzIGFuZCBuZXh0IG5vZGVzIGluIHotb3JkZXJcbiAgICB0aGlzLnByZXZaID0gbnVsbDtcbiAgICB0aGlzLm5leHRaID0gbnVsbDtcblxuICAgIC8vIGluZGljYXRlcyB3aGV0aGVyIHRoaXMgaXMgYSBzdGVpbmVyIHBvaW50XG4gICAgdGhpcy5zdGVpbmVyID0gZmFsc2U7XG59XG5cbi8vIHJldHVybiBhIHBlcmNlbnRhZ2UgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBwb2x5Z29uIGFyZWEgYW5kIGl0cyB0cmlhbmd1bGF0aW9uIGFyZWE7XG4vLyB1c2VkIHRvIHZlcmlmeSBjb3JyZWN0bmVzcyBvZiB0cmlhbmd1bGF0aW9uXG5lYXJjdXQuZGV2aWF0aW9uID0gZnVuY3Rpb24gKGRhdGEsIGhvbGVJbmRpY2VzLCBkaW0sIHRyaWFuZ2xlcykge1xuICAgIHZhciBoYXNIb2xlcyA9IGhvbGVJbmRpY2VzICYmIGhvbGVJbmRpY2VzLmxlbmd0aDtcbiAgICB2YXIgb3V0ZXJMZW4gPSBoYXNIb2xlcyA/IGhvbGVJbmRpY2VzWzBdICogZGltIDogZGF0YS5sZW5ndGg7XG5cbiAgICB2YXIgcG9seWdvbkFyZWEgPSBNYXRoLmFicyhzaWduZWRBcmVhKGRhdGEsIDAsIG91dGVyTGVuLCBkaW0pKTtcbiAgICBpZiAoaGFzSG9sZXMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGhvbGVJbmRpY2VzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgc3RhcnQgPSBob2xlSW5kaWNlc1tpXSAqIGRpbTtcbiAgICAgICAgICAgIHZhciBlbmQgPSBpIDwgbGVuIC0gMSA/IGhvbGVJbmRpY2VzW2kgKyAxXSAqIGRpbSA6IGRhdGEubGVuZ3RoO1xuICAgICAgICAgICAgcG9seWdvbkFyZWEgLT0gTWF0aC5hYnMoc2lnbmVkQXJlYShkYXRhLCBzdGFydCwgZW5kLCBkaW0pKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB0cmlhbmdsZXNBcmVhID0gMDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdHJpYW5nbGVzLmxlbmd0aDsgaSArPSAzKSB7XG4gICAgICAgIHZhciBhID0gdHJpYW5nbGVzW2ldICogZGltO1xuICAgICAgICB2YXIgYiA9IHRyaWFuZ2xlc1tpICsgMV0gKiBkaW07XG4gICAgICAgIHZhciBjID0gdHJpYW5nbGVzW2kgKyAyXSAqIGRpbTtcbiAgICAgICAgdHJpYW5nbGVzQXJlYSArPSBNYXRoLmFicyhcbiAgICAgICAgICAgIChkYXRhW2FdIC0gZGF0YVtjXSkgKiAoZGF0YVtiICsgMV0gLSBkYXRhW2EgKyAxXSkgLVxuICAgICAgICAgICAgKGRhdGFbYV0gLSBkYXRhW2JdKSAqIChkYXRhW2MgKyAxXSAtIGRhdGFbYSArIDFdKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBvbHlnb25BcmVhID09PSAwICYmIHRyaWFuZ2xlc0FyZWEgPT09IDAgPyAwIDpcbiAgICAgICAgTWF0aC5hYnMoKHRyaWFuZ2xlc0FyZWEgLSBwb2x5Z29uQXJlYSkgLyBwb2x5Z29uQXJlYSk7XG59O1xuXG5mdW5jdGlvbiBzaWduZWRBcmVhKGRhdGEsIHN0YXJ0LCBlbmQsIGRpbSkge1xuICAgIHZhciBzdW0gPSAwO1xuICAgIGZvciAodmFyIGkgPSBzdGFydCwgaiA9IGVuZCAtIGRpbTsgaSA8IGVuZDsgaSArPSBkaW0pIHtcbiAgICAgICAgc3VtICs9IChkYXRhW2pdIC0gZGF0YVtpXSkgKiAoZGF0YVtpICsgMV0gKyBkYXRhW2ogKyAxXSk7XG4gICAgICAgIGogPSBpO1xuICAgIH1cbiAgICByZXR1cm4gc3VtO1xufVxuXG4vLyB0dXJuIGEgcG9seWdvbiBpbiBhIG11bHRpLWRpbWVuc2lvbmFsIGFycmF5IGZvcm0gKGUuZy4gYXMgaW4gR2VvSlNPTikgaW50byBhIGZvcm0gRWFyY3V0IGFjY2VwdHNcbmVhcmN1dC5mbGF0dGVuID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICB2YXIgZGltID0gZGF0YVswXVswXS5sZW5ndGgsXG4gICAgICAgIHJlc3VsdCA9IHt2ZXJ0aWNlczogW10sIGhvbGVzOiBbXSwgZGltZW5zaW9uczogZGltfSxcbiAgICAgICAgaG9sZUluZGV4ID0gMDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGRhdGFbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGZvciAodmFyIGQgPSAwOyBkIDwgZGltOyBkKyspIHJlc3VsdC52ZXJ0aWNlcy5wdXNoKGRhdGFbaV1bal1bZF0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpID4gMCkge1xuICAgICAgICAgICAgaG9sZUluZGV4ICs9IGRhdGFbaSAtIDFdLmxlbmd0aDtcbiAgICAgICAgICAgIHJlc3VsdC5ob2xlcy5wdXNoKGhvbGVJbmRleCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbn0se31dLDQ5MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5hcmd1bWVudHNbNF1bMzE4XVswXS5hcHBseShleHBvcnRzLGFyZ3VtZW50cylcbn0se1wiLi9pcy1pbXBsZW1lbnRlZFwiOjQ5NCxcIi4vcG9seWZpbGxcIjo0OTYsXCJkdXBcIjozMTh9XSw0OTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuYXJndW1lbnRzWzRdWzMxOV1bMF0uYXBwbHkoZXhwb3J0cyxhcmd1bWVudHMpXG59LHtcImR1cFwiOjMxOX1dLDQ5NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5hcmd1bWVudHNbNF1bMzIwXVswXS5hcHBseShleHBvcnRzLGFyZ3VtZW50cylcbn0se1wiZHVwXCI6MzIwfV0sNDk2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbmFyZ3VtZW50c1s0XVszMjFdWzBdLmFwcGx5KGV4cG9ydHMsYXJndW1lbnRzKVxufSx7XCIuL2lzLW5hdGl2ZS1pbXBsZW1lbnRlZFwiOjQ5NSxcImRcIjoxNTEsXCJkdXBcIjozMjEsXCJlczUtZXh0L29iamVjdC9pcy12YWx1ZVwiOjE5NCxcImVzNS1leHQvb2JqZWN0L3NldC1wcm90b3R5cGUtb2ZcIjoyMDAsXCJlczUtZXh0L29iamVjdC92YWxpZC1vYmplY3RcIjoyMDQsXCJlczUtZXh0L29iamVjdC92YWxpZC12YWx1ZVwiOjIwNSxcImVzNS1leHQvc3RyaW5nL3JhbmRvbS11bmlxXCI6MjEwLFwiZXM2LWl0ZXJhdG9yL2Zvci1vZlwiOjIxMixcImVzNi1pdGVyYXRvci9nZXRcIjoyMTMsXCJlczYtc3ltYm9sXCI6MjE5fV0sNDk3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gX3NsaWNlZFRvQXJyYXkoYXJyLCBpKSB7XG4gIHJldHVybiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB8fCBfaXRlcmFibGVUb0FycmF5TGltaXQoYXJyLCBpKSB8fCBfbm9uSXRlcmFibGVSZXN0KCk7XG59XG5cbmZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHtcbiAgcmV0dXJuIF9hcnJheVdpdGhvdXRIb2xlcyhhcnIpIHx8IF9pdGVyYWJsZVRvQXJyYXkoYXJyKSB8fCBfbm9uSXRlcmFibGVTcHJlYWQoKTtcbn1cblxuZnVuY3Rpb24gX2FycmF5V2l0aG91dEhvbGVzKGFycikge1xuICBpZiAoQXJyYXkuaXNBcnJheShhcnIpKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIGFycjIgPSBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7IGkgPCBhcnIubGVuZ3RoOyBpKyspIGFycjJbaV0gPSBhcnJbaV07XG5cbiAgICByZXR1cm4gYXJyMjtcbiAgfVxufVxuXG5mdW5jdGlvbiBfYXJyYXlXaXRoSG9sZXMoYXJyKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGFycikpIHJldHVybiBhcnI7XG59XG5cbmZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikge1xuICBpZiAoU3ltYm9sLml0ZXJhdG9yIGluIE9iamVjdChpdGVyKSB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaXRlcikgPT09IFwiW29iamVjdCBBcmd1bWVudHNdXCIpIHJldHVybiBBcnJheS5mcm9tKGl0ZXIpO1xufVxuXG5mdW5jdGlvbiBfaXRlcmFibGVUb0FycmF5TGltaXQoYXJyLCBpKSB7XG4gIHZhciBfYXJyID0gW107XG4gIHZhciBfbiA9IHRydWU7XG4gIHZhciBfZCA9IGZhbHNlO1xuICB2YXIgX2UgPSB1bmRlZmluZWQ7XG5cbiAgdHJ5IHtcbiAgICBmb3IgKHZhciBfaSA9IGFycltTeW1ib2wuaXRlcmF0b3JdKCksIF9zOyAhKF9uID0gKF9zID0gX2kubmV4dCgpKS5kb25lKTsgX24gPSB0cnVlKSB7XG4gICAgICBfYXJyLnB1c2goX3MudmFsdWUpO1xuXG4gICAgICBpZiAoaSAmJiBfYXJyLmxlbmd0aCA9PT0gaSkgYnJlYWs7XG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBfZCA9IHRydWU7XG4gICAgX2UgPSBlcnI7XG4gIH0gZmluYWxseSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICghX24gJiYgX2lbXCJyZXR1cm5cIl0gIT0gbnVsbCkgX2lbXCJyZXR1cm5cIl0oKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKF9kKSB0aHJvdyBfZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2Fycjtcbn1cblxuZnVuY3Rpb24gX25vbkl0ZXJhYmxlU3ByZWFkKCkge1xuICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBhdHRlbXB0IHRvIHNwcmVhZCBub24taXRlcmFibGUgaW5zdGFuY2VcIik7XG59XG5cbmZ1bmN0aW9uIF9ub25JdGVyYWJsZVJlc3QoKSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gZGVzdHJ1Y3R1cmUgbm9uLWl0ZXJhYmxlIGluc3RhbmNlXCIpO1xufVxuXG52YXIgcmdiYSA9IF9kZXJlcV8oJ2NvbG9yLW5vcm1hbGl6ZScpO1xuXG52YXIgZ2V0Qm91bmRzID0gX2RlcmVxXygnYXJyYXktYm91bmRzJyk7XG5cbnZhciBjb2xvcklkID0gX2RlcmVxXygnY29sb3ItaWQnKTtcblxudmFyIGNsdXN0ZXIgPSBfZGVyZXFfKCdwb2ludC1jbHVzdGVyJyk7XG5cbnZhciBleHRlbmQgPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJyk7XG5cbnZhciBnbHNsaWZ5ID0gX2RlcmVxXygnZ2xzbGlmeScpO1xuXG52YXIgcGljayA9IF9kZXJlcV8oJ3BpY2stYnktYWxpYXMnKTtcblxudmFyIHVwZGF0ZURpZmYgPSBfZGVyZXFfKCd1cGRhdGUtZGlmZicpO1xuXG52YXIgZmxhdHRlbiA9IF9kZXJlcV8oJ2ZsYXR0ZW4tdmVydGV4LWRhdGEnKTtcblxudmFyIGllID0gX2RlcmVxXygnaXMtaWV4cGxvcmVyJyk7XG5cbnZhciBmMzIgPSBfZGVyZXFfKCd0by1mbG9hdDMyJyk7XG5cbnZhciBwYXJzZVJlY3QgPSBfZGVyZXFfKCdwYXJzZS1yZWN0Jyk7XG5cbnZhciBzY2F0dGVyID0gU2NhdHRlcjtcblxuZnVuY3Rpb24gU2NhdHRlcihyZWdsLCBvcHRpb25zKSB7XG4gIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNjYXR0ZXIpKSByZXR1cm4gbmV3IFNjYXR0ZXIocmVnbCwgb3B0aW9ucyk7XG5cbiAgaWYgKHR5cGVvZiByZWdsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0ge307XG4gICAgb3B0aW9ucy5yZWdsID0gcmVnbDtcbiAgfSBlbHNlIHtcbiAgICBvcHRpb25zID0gcmVnbDtcbiAgICByZWdsID0gbnVsbDtcbiAgfVxuXG4gIGlmIChvcHRpb25zICYmIG9wdGlvbnMubGVuZ3RoKSBvcHRpb25zLnBvc2l0aW9ucyA9IG9wdGlvbnM7XG4gIHJlZ2wgPSBvcHRpb25zLnJlZ2w7IC8vIHBlcnNpc3RlbnQgdmFyaWFibGVzXG5cbiAgdmFyIGdsID0gcmVnbC5fZ2wsXG4gICAgICBwYWxldHRlVGV4dHVyZSxcbiAgICAgIHBhbGV0dGUgPSBbXSxcbiAgICAgIHBhbGV0dGVJZHMgPSB7fSxcbiAgICAgIC8vIHN0YXRlXG4gIGdyb3VwcyA9IFtdLFxuICAgICAgLy8gdGV4dHVyZXMgZm9yIG1hcmtlciBrZXlzXG4gIG1hcmtlclRleHR1cmVzID0gW251bGxdLFxuICAgICAgbWFya2VyQ2FjaGUgPSBbbnVsbF07XG4gIHZhciBtYXhDb2xvcnMgPSAyNTUsXG4gICAgICBtYXhTaXplID0gMTAwOyAvLyBkaXJlY3QgY29sb3IgYnVmZmVyIG1vZGVcbiAgLy8gSUUgZG9lcyBub3Qgc3VwcG9ydCBwYWxldHRlIGFueXdheXNcblxuICB0aGlzLnRvb01hbnlDb2xvcnMgPSBpZTsgLy8gdGV4dHVyZSB3aXRoIGNvbG9yIHBhbGV0dGVcblxuICBwYWxldHRlVGV4dHVyZSA9IHJlZ2wudGV4dHVyZSh7XG4gICAgZGF0YTogbmV3IFVpbnQ4QXJyYXkobWF4Q29sb3JzICogNCksXG4gICAgd2lkdGg6IG1heENvbG9ycyxcbiAgICBoZWlnaHQ6IDEsXG4gICAgdHlwZTogJ3VpbnQ4JyxcbiAgICBmb3JtYXQ6ICdyZ2JhJyxcbiAgICB3cmFwUzogJ2NsYW1wJyxcbiAgICB3cmFwVDogJ2NsYW1wJyxcbiAgICBtYWc6ICduZWFyZXN0JyxcbiAgICBtaW46ICduZWFyZXN0J1xuICB9KTtcbiAgZXh0ZW5kKHRoaXMsIHtcbiAgICByZWdsOiByZWdsLFxuICAgIGdsOiBnbCxcbiAgICBncm91cHM6IGdyb3VwcyxcbiAgICBtYXJrZXJDYWNoZTogbWFya2VyQ2FjaGUsXG4gICAgbWFya2VyVGV4dHVyZXM6IG1hcmtlclRleHR1cmVzLFxuICAgIHBhbGV0dGU6IHBhbGV0dGUsXG4gICAgcGFsZXR0ZUlkczogcGFsZXR0ZUlkcyxcbiAgICBwYWxldHRlVGV4dHVyZTogcGFsZXR0ZVRleHR1cmUsXG4gICAgbWF4Q29sb3JzOiBtYXhDb2xvcnMsXG4gICAgbWF4U2l6ZTogbWF4U2l6ZSxcbiAgICBjYW52YXM6IGdsLmNhbnZhc1xuICB9KTtcbiAgdGhpcy51cGRhdGUob3B0aW9ucyk7IC8vIGNvbW1vbiBzaGFkZXIgb3B0aW9uc1xuXG4gIHZhciBzaGFkZXJPcHRpb25zID0ge1xuICAgIHVuaWZvcm1zOiB7XG4gICAgICBwaXhlbFJhdGlvOiByZWdsLmNvbnRleHQoJ3BpeGVsUmF0aW8nKSxcbiAgICAgIHBhbGV0dGU6IHBhbGV0dGVUZXh0dXJlLFxuICAgICAgcGFsZXR0ZVNpemU6IGZ1bmN0aW9uIHBhbGV0dGVTaXplKGN0eCwgcHJvcCkge1xuICAgICAgICByZXR1cm4gW190aGlzLnRvb01hbnlDb2xvcnMgPyAwIDogbWF4Q29sb3JzLCBwYWxldHRlVGV4dHVyZS5oZWlnaHRdO1xuICAgICAgfSxcbiAgICAgIHNjYWxlOiByZWdsLnByb3AoJ3NjYWxlJyksXG4gICAgICBzY2FsZUZyYWN0OiByZWdsLnByb3AoJ3NjYWxlRnJhY3QnKSxcbiAgICAgIHRyYW5zbGF0ZTogcmVnbC5wcm9wKCd0cmFuc2xhdGUnKSxcbiAgICAgIHRyYW5zbGF0ZUZyYWN0OiByZWdsLnByb3AoJ3RyYW5zbGF0ZUZyYWN0JyksXG4gICAgICBvcGFjaXR5OiByZWdsLnByb3AoJ29wYWNpdHknKSxcbiAgICAgIG1hcmtlcjogcmVnbC5wcm9wKCdtYXJrZXJUZXh0dXJlJylcbiAgICB9LFxuICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgIC8vIEZJWE1FOiBvcHRpbWl6ZSB0aGVzZSBwYXJ0c1xuICAgICAgeDogZnVuY3Rpb24geChjdHgsIHByb3ApIHtcbiAgICAgICAgcmV0dXJuIHByb3AueEF0dHIgfHwge1xuICAgICAgICAgIGJ1ZmZlcjogcHJvcC5wb3NpdGlvbkJ1ZmZlcixcbiAgICAgICAgICBzdHJpZGU6IDgsXG4gICAgICAgICAgb2Zmc2V0OiAwXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgeTogZnVuY3Rpb24geShjdHgsIHByb3ApIHtcbiAgICAgICAgcmV0dXJuIHByb3AueUF0dHIgfHwge1xuICAgICAgICAgIGJ1ZmZlcjogcHJvcC5wb3NpdGlvbkJ1ZmZlcixcbiAgICAgICAgICBzdHJpZGU6IDgsXG4gICAgICAgICAgb2Zmc2V0OiA0XG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgeEZyYWN0OiBmdW5jdGlvbiB4RnJhY3QoY3R4LCBwcm9wKSB7XG4gICAgICAgIHJldHVybiBwcm9wLnhBdHRyID8ge1xuICAgICAgICAgIGNvbnN0YW50OiBbMCwgMF1cbiAgICAgICAgfSA6IHtcbiAgICAgICAgICBidWZmZXI6IHByb3AucG9zaXRpb25GcmFjdEJ1ZmZlcixcbiAgICAgICAgICBzdHJpZGU6IDgsXG4gICAgICAgICAgb2Zmc2V0OiAwXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgeUZyYWN0OiBmdW5jdGlvbiB5RnJhY3QoY3R4LCBwcm9wKSB7XG4gICAgICAgIHJldHVybiBwcm9wLnlBdHRyID8ge1xuICAgICAgICAgIGNvbnN0YW50OiBbMCwgMF1cbiAgICAgICAgfSA6IHtcbiAgICAgICAgICBidWZmZXI6IHByb3AucG9zaXRpb25GcmFjdEJ1ZmZlcixcbiAgICAgICAgICBzdHJpZGU6IDgsXG4gICAgICAgICAgb2Zmc2V0OiA0XG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgc2l6ZTogZnVuY3Rpb24gc2l6ZShjdHgsIHByb3ApIHtcbiAgICAgICAgcmV0dXJuIHByb3Auc2l6ZS5sZW5ndGggPyB7XG4gICAgICAgICAgYnVmZmVyOiBwcm9wLnNpemVCdWZmZXIsXG4gICAgICAgICAgc3RyaWRlOiAyLFxuICAgICAgICAgIG9mZnNldDogMFxuICAgICAgICB9IDoge1xuICAgICAgICAgIGNvbnN0YW50OiBbTWF0aC5yb3VuZChwcm9wLnNpemUgKiAyNTUgLyBfdGhpcy5tYXhTaXplKV1cbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICBib3JkZXJTaXplOiBmdW5jdGlvbiBib3JkZXJTaXplKGN0eCwgcHJvcCkge1xuICAgICAgICByZXR1cm4gcHJvcC5ib3JkZXJTaXplLmxlbmd0aCA/IHtcbiAgICAgICAgICBidWZmZXI6IHByb3Auc2l6ZUJ1ZmZlcixcbiAgICAgICAgICBzdHJpZGU6IDIsXG4gICAgICAgICAgb2Zmc2V0OiAxXG4gICAgICAgIH0gOiB7XG4gICAgICAgICAgY29uc3RhbnQ6IFtNYXRoLnJvdW5kKHByb3AuYm9yZGVyU2l6ZSAqIDI1NSAvIF90aGlzLm1heFNpemUpXVxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICAgIGNvbG9ySWQ6IGZ1bmN0aW9uIGNvbG9ySWQoY3R4LCBwcm9wKSB7XG4gICAgICAgIHJldHVybiBwcm9wLmNvbG9yLmxlbmd0aCA/IHtcbiAgICAgICAgICBidWZmZXI6IHByb3AuY29sb3JCdWZmZXIsXG4gICAgICAgICAgc3RyaWRlOiBfdGhpcy50b29NYW55Q29sb3JzID8gOCA6IDQsXG4gICAgICAgICAgb2Zmc2V0OiAwXG4gICAgICAgIH0gOiB7XG4gICAgICAgICAgY29uc3RhbnQ6IF90aGlzLnRvb01hbnlDb2xvcnMgPyBwYWxldHRlLnNsaWNlKHByb3AuY29sb3IgKiA0LCBwcm9wLmNvbG9yICogNCArIDQpIDogW3Byb3AuY29sb3JdXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgYm9yZGVyQ29sb3JJZDogZnVuY3Rpb24gYm9yZGVyQ29sb3JJZChjdHgsIHByb3ApIHtcbiAgICAgICAgcmV0dXJuIHByb3AuYm9yZGVyQ29sb3IubGVuZ3RoID8ge1xuICAgICAgICAgIGJ1ZmZlcjogcHJvcC5jb2xvckJ1ZmZlcixcbiAgICAgICAgICBzdHJpZGU6IF90aGlzLnRvb01hbnlDb2xvcnMgPyA4IDogNCxcbiAgICAgICAgICBvZmZzZXQ6IF90aGlzLnRvb01hbnlDb2xvcnMgPyA0IDogMlxuICAgICAgICB9IDoge1xuICAgICAgICAgIGNvbnN0YW50OiBfdGhpcy50b29NYW55Q29sb3JzID8gcGFsZXR0ZS5zbGljZShwcm9wLmJvcmRlckNvbG9yICogNCwgcHJvcC5ib3JkZXJDb2xvciAqIDQgKyA0KSA6IFtwcm9wLmJvcmRlckNvbG9yXVxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICAgIGlzQWN0aXZlOiBmdW5jdGlvbiBpc0FjdGl2ZShjdHgsIHByb3ApIHtcbiAgICAgICAgcmV0dXJuIHByb3AuYWN0aXZhdGlvbiA9PT0gdHJ1ZSA/IHtcbiAgICAgICAgICBjb25zdGFudDogWzFdXG4gICAgICAgIH0gOiBwcm9wLmFjdGl2YXRpb24gPyBwcm9wLmFjdGl2YXRpb24gOiB7XG4gICAgICAgICAgY29uc3RhbnQ6IFswXVxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0sXG4gICAgYmxlbmQ6IHtcbiAgICAgIGVuYWJsZTogdHJ1ZSxcbiAgICAgIGNvbG9yOiBbMCwgMCwgMCwgMV0sXG4gICAgICAvLyBwaG90b3Nob3AgYmxlbmRpbmdcbiAgICAgIGZ1bmM6IHtcbiAgICAgICAgc3JjUkdCOiAnc3JjIGFscGhhJyxcbiAgICAgICAgZHN0UkdCOiAnb25lIG1pbnVzIHNyYyBhbHBoYScsXG4gICAgICAgIHNyY0FscGhhOiAnb25lIG1pbnVzIGRzdCBhbHBoYScsXG4gICAgICAgIGRzdEFscGhhOiAnb25lJ1xuICAgICAgfVxuICAgIH0sXG4gICAgc2Npc3Nvcjoge1xuICAgICAgZW5hYmxlOiB0cnVlLFxuICAgICAgYm94OiByZWdsLnByb3AoJ3ZpZXdwb3J0JylcbiAgICB9LFxuICAgIHZpZXdwb3J0OiByZWdsLnByb3AoJ3ZpZXdwb3J0JyksXG4gICAgc3RlbmNpbDoge1xuICAgICAgZW5hYmxlOiBmYWxzZVxuICAgIH0sXG4gICAgZGVwdGg6IHtcbiAgICAgIGVuYWJsZTogZmFsc2VcbiAgICB9LFxuICAgIGVsZW1lbnRzOiByZWdsLnByb3AoJ2VsZW1lbnRzJyksXG4gICAgY291bnQ6IHJlZ2wucHJvcCgnY291bnQnKSxcbiAgICBvZmZzZXQ6IHJlZ2wucHJvcCgnb2Zmc2V0JyksXG4gICAgcHJpbWl0aXZlOiAncG9pbnRzJyAvLyBkcmF3IHNkZi1tYXJrZXJcblxuICB9O1xuICB2YXIgbWFya2VyT3B0aW9ucyA9IGV4dGVuZCh7fSwgc2hhZGVyT3B0aW9ucyk7XG4gIG1hcmtlck9wdGlvbnMuZnJhZyA9IGdsc2xpZnkoW1wicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xcbiNkZWZpbmUgR0xTTElGWSAxXFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvciwgZnJhZ0JvcmRlckNvbG9yO1xcbnZhcnlpbmcgZmxvYXQgZnJhZ1dpZHRoLCBmcmFnQm9yZGVyQ29sb3JMZXZlbCwgZnJhZ0NvbG9yTGV2ZWw7XFxuXFxudW5pZm9ybSBzYW1wbGVyMkQgbWFya2VyO1xcbnVuaWZvcm0gZmxvYXQgcGl4ZWxSYXRpbywgb3BhY2l0eTtcXG5cXG5mbG9hdCBzbW9vdGhTdGVwKGZsb2F0IHgsIGZsb2F0IHkpIHtcXG4gIHJldHVybiAxLjAgLyAoMS4wICsgZXhwKDUwLjAqKHggLSB5KSkpO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICBmbG9hdCBkaXN0ID0gdGV4dHVyZTJEKG1hcmtlciwgZ2xfUG9pbnRDb29yZCkuciwgZGVsdGEgPSBmcmFnV2lkdGg7XFxuXFxuICAvLyBtYXgtZGlzdGFuY2UgYWxwaGFcXG4gIGlmIChkaXN0IDwgMC4wMDMpIGRpc2NhcmQ7XFxuXFxuICAvLyBudWxsLWJvcmRlciBjYXNlXFxuICBpZiAoZnJhZ0JvcmRlckNvbG9yTGV2ZWwgPT0gZnJhZ0NvbG9yTGV2ZWwgfHwgZnJhZ0JvcmRlckNvbG9yLmEgPT0gMC4pIHtcXG4gICAgZmxvYXQgY29sb3JBbXQgPSBzbW9vdGhzdGVwKC41IC0gZGVsdGEsIC41ICsgZGVsdGEsIGRpc3QpO1xcbiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KGZyYWdDb2xvci5yZ2IsIGNvbG9yQW10ICogZnJhZ0NvbG9yLmEgKiBvcGFjaXR5KTtcXG4gIH1cXG4gIGVsc2Uge1xcbiAgICBmbG9hdCBib3JkZXJDb2xvckFtdCA9IHNtb290aHN0ZXAoZnJhZ0JvcmRlckNvbG9yTGV2ZWwgLSBkZWx0YSwgZnJhZ0JvcmRlckNvbG9yTGV2ZWwgKyBkZWx0YSwgZGlzdCk7XFxuICAgIGZsb2F0IGNvbG9yQW10ID0gc21vb3Roc3RlcChmcmFnQ29sb3JMZXZlbCAtIGRlbHRhLCBmcmFnQ29sb3JMZXZlbCArIGRlbHRhLCBkaXN0KTtcXG5cXG4gICAgdmVjNCBjb2xvciA9IGZyYWdCb3JkZXJDb2xvcjtcXG4gICAgY29sb3IuYSAqPSBib3JkZXJDb2xvckFtdDtcXG4gICAgY29sb3IgPSBtaXgoY29sb3IsIGZyYWdDb2xvciwgY29sb3JBbXQpO1xcbiAgICBjb2xvci5hICo9IG9wYWNpdHk7XFxuXFxuICAgIGdsX0ZyYWdDb2xvciA9IGNvbG9yO1xcbiAgfVxcblxcbn1cXG5cIl0pO1xuICBtYXJrZXJPcHRpb25zLnZlcnQgPSBnbHNsaWZ5KFtcInByZWNpc2lvbiBoaWdocCBmbG9hdDtcXG4jZGVmaW5lIEdMU0xJRlkgMVxcblxcbmF0dHJpYnV0ZSBmbG9hdCB4LCB5LCB4RnJhY3QsIHlGcmFjdDtcXG5hdHRyaWJ1dGUgZmxvYXQgc2l6ZSwgYm9yZGVyU2l6ZTtcXG5hdHRyaWJ1dGUgdmVjNCBjb2xvcklkLCBib3JkZXJDb2xvcklkO1xcbmF0dHJpYnV0ZSBmbG9hdCBpc0FjdGl2ZTtcXG5cXG51bmlmb3JtIHZlYzIgc2NhbGUsIHNjYWxlRnJhY3QsIHRyYW5zbGF0ZSwgdHJhbnNsYXRlRnJhY3QsIHBhbGV0dGVTaXplO1xcbnVuaWZvcm0gZmxvYXQgcGl4ZWxSYXRpbztcXG51bmlmb3JtIHNhbXBsZXIyRCBwYWxldHRlO1xcblxcbmNvbnN0IGZsb2F0IG1heFNpemUgPSAxMDAuO1xcbmNvbnN0IGZsb2F0IGJvcmRlckxldmVsID0gLjU7XFxuXFxudmFyeWluZyB2ZWM0IGZyYWdDb2xvciwgZnJhZ0JvcmRlckNvbG9yO1xcbnZhcnlpbmcgZmxvYXQgZnJhZ1BvaW50U2l6ZSwgZnJhZ0JvcmRlclJhZGl1cywgZnJhZ1dpZHRoLCBmcmFnQm9yZGVyQ29sb3JMZXZlbCwgZnJhZ0NvbG9yTGV2ZWw7XFxuXFxuYm9vbCBpc0RpcmVjdCA9IChwYWxldHRlU2l6ZS54IDwgMS4pO1xcblxcbnZlYzQgZ2V0Q29sb3IodmVjNCBpZCkge1xcbiAgcmV0dXJuIGlzRGlyZWN0ID8gaWQgLyAyNTUuIDogdGV4dHVyZTJEKHBhbGV0dGUsXFxuICAgIHZlYzIoXFxuICAgICAgKGlkLnggKyAuNSkgLyBwYWxldHRlU2l6ZS54LFxcbiAgICAgIChpZC55ICsgLjUpIC8gcGFsZXR0ZVNpemUueVxcbiAgICApXFxuICApO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICBpZiAoaXNBY3RpdmUgPT0gMC4pIHJldHVybjtcXG5cXG4gIHZlYzIgcG9zaXRpb24gPSB2ZWMyKHgsIHkpO1xcbiAgdmVjMiBwb3NpdGlvbkZyYWN0ID0gdmVjMih4RnJhY3QsIHlGcmFjdCk7XFxuXFxuICB2ZWM0IGNvbG9yID0gZ2V0Q29sb3IoY29sb3JJZCk7XFxuICB2ZWM0IGJvcmRlckNvbG9yID0gZ2V0Q29sb3IoYm9yZGVyQ29sb3JJZCk7XFxuXFxuICBmbG9hdCBzaXplID0gc2l6ZSAqIG1heFNpemUgLyAyNTUuO1xcbiAgZmxvYXQgYm9yZGVyU2l6ZSA9IGJvcmRlclNpemUgKiBtYXhTaXplIC8gMjU1LjtcXG5cXG4gIGdsX1BvaW50U2l6ZSA9IDIuICogc2l6ZSAqIHBpeGVsUmF0aW87XFxuICBmcmFnUG9pbnRTaXplID0gc2l6ZSAqIHBpeGVsUmF0aW87XFxuXFxuICB2ZWMyIHBvcyA9IChwb3NpdGlvbiArIHRyYW5zbGF0ZSkgKiBzY2FsZVxcbiAgICAgICsgKHBvc2l0aW9uRnJhY3QgKyB0cmFuc2xhdGVGcmFjdCkgKiBzY2FsZVxcbiAgICAgICsgKHBvc2l0aW9uICsgdHJhbnNsYXRlKSAqIHNjYWxlRnJhY3RcXG4gICAgICArIChwb3NpdGlvbkZyYWN0ICsgdHJhbnNsYXRlRnJhY3QpICogc2NhbGVGcmFjdDtcXG5cXG4gIGdsX1Bvc2l0aW9uID0gdmVjNChwb3MgKiAyLiAtIDEuLCAwLCAxKTtcXG5cXG4gIGZyYWdDb2xvciA9IGNvbG9yO1xcbiAgZnJhZ0JvcmRlckNvbG9yID0gYm9yZGVyQ29sb3I7XFxuICBmcmFnV2lkdGggPSAxLiAvIGdsX1BvaW50U2l6ZTtcXG5cXG4gIGZyYWdCb3JkZXJDb2xvckxldmVsID0gY2xhbXAoYm9yZGVyTGV2ZWwgLSBib3JkZXJMZXZlbCAqIGJvcmRlclNpemUgLyBzaXplLCAwLiwgMS4pO1xcbiAgZnJhZ0NvbG9yTGV2ZWwgPSBjbGFtcChib3JkZXJMZXZlbCArICgxLiAtIGJvcmRlckxldmVsKSAqIGJvcmRlclNpemUgLyBzaXplLCAwLiwgMS4pO1xcbn1cIl0pO1xuICB0aGlzLmRyYXdNYXJrZXIgPSByZWdsKG1hcmtlck9wdGlvbnMpOyAvLyBkcmF3IGNpcmNsZVxuXG4gIHZhciBjaXJjbGVPcHRpb25zID0gZXh0ZW5kKHt9LCBzaGFkZXJPcHRpb25zKTtcbiAgY2lyY2xlT3B0aW9ucy5mcmFnID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yLCBmcmFnQm9yZGVyQ29sb3I7XFxuXFxudW5pZm9ybSBmbG9hdCBvcGFjaXR5O1xcbnZhcnlpbmcgZmxvYXQgZnJhZ0JvcmRlclJhZGl1cywgZnJhZ1dpZHRoO1xcblxcbmZsb2F0IHNtb290aFN0ZXAoZmxvYXQgZWRnZTAsIGZsb2F0IGVkZ2UxLCBmbG9hdCB4KSB7XFxuXFx0ZmxvYXQgdDtcXG5cXHR0ID0gY2xhbXAoKHggLSBlZGdlMCkgLyAoZWRnZTEgLSBlZGdlMCksIDAuMCwgMS4wKTtcXG5cXHRyZXR1cm4gdCAqIHQgKiAoMy4wIC0gMi4wICogdCk7XFxufVxcblxcbnZvaWQgbWFpbigpIHtcXG5cXHRmbG9hdCByYWRpdXMsIGFscGhhID0gMS4wLCBkZWx0YSA9IGZyYWdXaWR0aDtcXG5cXG5cXHRyYWRpdXMgPSBsZW5ndGgoMi4wICogZ2xfUG9pbnRDb29yZC54eSAtIDEuMCk7XFxuXFxuXFx0aWYgKHJhZGl1cyA+IDEuMCArIGRlbHRhKSB7XFxuXFx0XFx0ZGlzY2FyZDtcXG5cXHR9XFxuXFxuXFx0YWxwaGEgLT0gc21vb3Roc3RlcCgxLjAgLSBkZWx0YSwgMS4wICsgZGVsdGEsIHJhZGl1cyk7XFxuXFxuXFx0ZmxvYXQgYm9yZGVyUmFkaXVzID0gZnJhZ0JvcmRlclJhZGl1cztcXG5cXHRmbG9hdCByYXRpbyA9IHNtb290aHN0ZXAoYm9yZGVyUmFkaXVzIC0gZGVsdGEsIGJvcmRlclJhZGl1cyArIGRlbHRhLCByYWRpdXMpO1xcblxcdHZlYzQgY29sb3IgPSBtaXgoZnJhZ0NvbG9yLCBmcmFnQm9yZGVyQ29sb3IsIHJhdGlvKTtcXG5cXHRjb2xvci5hICo9IGFscGhhICogb3BhY2l0eTtcXG5cXHRnbF9GcmFnQ29sb3IgPSBjb2xvcjtcXG59XFxuXCJdKTtcbiAgY2lyY2xlT3B0aW9ucy52ZXJ0ID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG5hdHRyaWJ1dGUgZmxvYXQgeCwgeSwgeEZyYWN0LCB5RnJhY3Q7XFxuYXR0cmlidXRlIGZsb2F0IHNpemUsIGJvcmRlclNpemU7XFxuYXR0cmlidXRlIHZlYzQgY29sb3JJZCwgYm9yZGVyQ29sb3JJZDtcXG5hdHRyaWJ1dGUgZmxvYXQgaXNBY3RpdmU7XFxuXFxudW5pZm9ybSB2ZWMyIHNjYWxlLCBzY2FsZUZyYWN0LCB0cmFuc2xhdGUsIHRyYW5zbGF0ZUZyYWN0O1xcbnVuaWZvcm0gZmxvYXQgcGl4ZWxSYXRpbztcXG51bmlmb3JtIHNhbXBsZXIyRCBwYWxldHRlO1xcbnVuaWZvcm0gdmVjMiBwYWxldHRlU2l6ZTtcXG5cXG5jb25zdCBmbG9hdCBtYXhTaXplID0gMTAwLjtcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yLCBmcmFnQm9yZGVyQ29sb3I7XFxudmFyeWluZyBmbG9hdCBmcmFnQm9yZGVyUmFkaXVzLCBmcmFnV2lkdGg7XFxuXFxuYm9vbCBpc0RpcmVjdCA9IChwYWxldHRlU2l6ZS54IDwgMS4pO1xcblxcbnZlYzQgZ2V0Q29sb3IodmVjNCBpZCkge1xcbiAgcmV0dXJuIGlzRGlyZWN0ID8gaWQgLyAyNTUuIDogdGV4dHVyZTJEKHBhbGV0dGUsXFxuICAgIHZlYzIoXFxuICAgICAgKGlkLnggKyAuNSkgLyBwYWxldHRlU2l6ZS54LFxcbiAgICAgIChpZC55ICsgLjUpIC8gcGFsZXR0ZVNpemUueVxcbiAgICApXFxuICApO1xcbn1cXG5cXG52b2lkIG1haW4oKSB7XFxuICAvLyBpZ25vcmUgaW5hY3RpdmUgcG9pbnRzXFxuICBpZiAoaXNBY3RpdmUgPT0gMC4pIHJldHVybjtcXG5cXG4gIHZlYzIgcG9zaXRpb24gPSB2ZWMyKHgsIHkpO1xcbiAgdmVjMiBwb3NpdGlvbkZyYWN0ID0gdmVjMih4RnJhY3QsIHlGcmFjdCk7XFxuXFxuICB2ZWM0IGNvbG9yID0gZ2V0Q29sb3IoY29sb3JJZCk7XFxuICB2ZWM0IGJvcmRlckNvbG9yID0gZ2V0Q29sb3IoYm9yZGVyQ29sb3JJZCk7XFxuXFxuICBmbG9hdCBzaXplID0gc2l6ZSAqIG1heFNpemUgLyAyNTUuO1xcbiAgZmxvYXQgYm9yZGVyU2l6ZSA9IGJvcmRlclNpemUgKiBtYXhTaXplIC8gMjU1LjtcXG5cXG4gIGdsX1BvaW50U2l6ZSA9IChzaXplICsgYm9yZGVyU2l6ZSkgKiBwaXhlbFJhdGlvO1xcblxcbiAgdmVjMiBwb3MgPSAocG9zaXRpb24gKyB0cmFuc2xhdGUpICogc2NhbGVcXG4gICAgICArIChwb3NpdGlvbkZyYWN0ICsgdHJhbnNsYXRlRnJhY3QpICogc2NhbGVcXG4gICAgICArIChwb3NpdGlvbiArIHRyYW5zbGF0ZSkgKiBzY2FsZUZyYWN0XFxuICAgICAgKyAocG9zaXRpb25GcmFjdCArIHRyYW5zbGF0ZUZyYWN0KSAqIHNjYWxlRnJhY3Q7XFxuXFxuICBnbF9Qb3NpdGlvbiA9IHZlYzQocG9zICogMi4gLSAxLiwgMCwgMSk7XFxuXFxuICBmcmFnQm9yZGVyUmFkaXVzID0gMS4gLSAyLiAqIGJvcmRlclNpemUgLyAoc2l6ZSArIGJvcmRlclNpemUpO1xcbiAgZnJhZ0NvbG9yID0gY29sb3I7XFxuICBmcmFnQm9yZGVyQ29sb3IgPSBib3JkZXJDb2xvci5hID09IDAuIHx8IGJvcmRlclNpemUgPT0gMC4gPyB2ZWM0KGNvbG9yLnJnYiwgMC4pIDogYm9yZGVyQ29sb3I7XFxuICBmcmFnV2lkdGggPSAxLiAvIGdsX1BvaW50U2l6ZTtcXG59XFxuXCJdKTsgLy8gcG9seWZpbGwgSUVcblxuICBpZiAoaWUpIHtcbiAgICBjaXJjbGVPcHRpb25zLmZyYWcgPSBjaXJjbGVPcHRpb25zLmZyYWcucmVwbGFjZSgnc21vb3Roc3RlcCcsICdzbW9vdGhTdGVwJyk7XG4gICAgbWFya2VyT3B0aW9ucy5mcmFnID0gbWFya2VyT3B0aW9ucy5mcmFnLnJlcGxhY2UoJ3Ntb290aHN0ZXAnLCAnc21vb3RoU3RlcCcpO1xuICB9XG5cbiAgdGhpcy5kcmF3Q2lyY2xlID0gcmVnbChjaXJjbGVPcHRpb25zKTtcbn0gLy8gc2luZ2xlIHBhc3MgZGVmYXVsdHNcblxuXG5TY2F0dGVyLmRlZmF1bHRzID0ge1xuICBjb2xvcjogJ2JsYWNrJyxcbiAgYm9yZGVyQ29sb3I6ICd0cmFuc3BhcmVudCcsXG4gIGJvcmRlclNpemU6IDAsXG4gIHNpemU6IDEyLFxuICBvcGFjaXR5OiAxLFxuICBtYXJrZXI6IHVuZGVmaW5lZCxcbiAgdmlld3BvcnQ6IG51bGwsXG4gIHJhbmdlOiBudWxsLFxuICBwaXhlbFNpemU6IG51bGwsXG4gIGNvdW50OiAwLFxuICBvZmZzZXQ6IDAsXG4gIGJvdW5kczogbnVsbCxcbiAgcG9zaXRpb25zOiBbXSxcbiAgc25hcDogMWU0IC8vIHVwZGF0ZSAmIHJlZHJhd1xuXG59O1xuXG5TY2F0dGVyLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgdGhpcy51cGRhdGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIHRoaXMuZHJhdygpO1xuICByZXR1cm4gdGhpcztcbn07IC8vIGRyYXcgYWxsIGdyb3VwcyBvciBvbmx5IGluZGljYXRlZCBvbmVzXG5cblxuU2NhdHRlci5wcm90b3R5cGUuZHJhdyA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgYXJnc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgfVxuXG4gIHZhciBncm91cHMgPSB0aGlzLmdyb3VwczsgLy8gaWYgZGlyZWN0bHkgYXJyYXkgcGFzc2VkIC0gdHJlYXQgYXMgcGFzc2VzXG5cbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAxICYmIEFycmF5LmlzQXJyYXkoYXJnc1swXSkgJiYgKGFyZ3NbMF1bMF0gPT09IG51bGwgfHwgQXJyYXkuaXNBcnJheShhcmdzWzBdWzBdKSkpIHtcbiAgICBhcmdzID0gYXJnc1swXTtcbiAgfSAvLyBGSVhNRTogcmVtb3ZlIG9uY2UgaHR0cHM6Ly9naXRodWIuY29tL3JlZ2wtcHJvamVjdC9yZWdsL2lzc3Vlcy80NzQgcmVzb2x2ZWRcblxuXG4gIHRoaXMucmVnbC5fcmVmcmVzaCgpO1xuXG4gIGlmIChhcmdzLmxlbmd0aCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5kcmF3SXRlbShpLCBhcmdzW2ldKTtcbiAgICB9XG4gIH0gLy8gZHJhdyBhbGwgcGFzc2VzXG4gIGVsc2Uge1xuICAgICAgZ3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKGdyb3VwLCBpKSB7XG4gICAgICAgIF90aGlzMi5kcmF3SXRlbShpKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICByZXR1cm4gdGhpcztcbn07IC8vIGRyYXcgc3BlY2lmaWMgc2NhdHRlciBncm91cFxuXG5cblNjYXR0ZXIucHJvdG90eXBlLmRyYXdJdGVtID0gZnVuY3Rpb24gKGlkLCBlbHMpIHtcbiAgdmFyIGdyb3VwcyA9IHRoaXMuZ3JvdXBzO1xuICB2YXIgZ3JvdXAgPSBncm91cHNbaWRdOyAvLyBkZWJ1ZyB2aWV3cG9ydFxuICAvLyBsZXQgeyB2aWV3cG9ydCB9ID0gZ3JvdXBcbiAgLy8gZ2wuZW5hYmxlKGdsLlNDSVNTT1JfVEVTVCk7XG4gIC8vIGdsLnNjaXNzb3Iodmlld3BvcnQueCwgdmlld3BvcnQueSwgdmlld3BvcnQud2lkdGgsIHZpZXdwb3J0LmhlaWdodCk7XG4gIC8vIGdsLmNsZWFyQ29sb3IoMCwgMCwgMCwgLjUpO1xuICAvLyBnbC5jbGVhcihnbC5DT0xPUl9CVUZGRVJfQklUKTtcblxuICBpZiAodHlwZW9mIGVscyA9PT0gJ251bWJlcicpIHtcbiAgICBpZCA9IGVscztcbiAgICBncm91cCA9IGdyb3Vwc1tlbHNdO1xuICAgIGVscyA9IG51bGw7XG4gIH1cblxuICBpZiAoIShncm91cCAmJiBncm91cC5jb3VudCAmJiBncm91cC5vcGFjaXR5KSkgcmV0dXJuOyAvLyBkcmF3IGNpcmNsZXNcblxuICBpZiAoZ3JvdXAuYWN0aXZhdGlvblswXSkge1xuICAgIC8vIFRPRE86IG9wdGltaXplIHRoaXMgcGVyZm9ybWFuY2UgYnkgbWFraW5nIGdyb3VwcyBhbmQgcmVnbC50aGlzIHByb3BzXG4gICAgdGhpcy5kcmF3Q2lyY2xlKHRoaXMuZ2V0TWFya2VyRHJhd09wdGlvbnMoMCwgZ3JvdXAsIGVscykpO1xuICB9IC8vIGRyYXcgYWxsIG90aGVyIGF2YWlsYWJsZSBtYXJrZXJzXG5cblxuICB2YXIgYmF0Y2ggPSBbXTtcblxuICBmb3IgKHZhciBpID0gMTsgaSA8IGdyb3VwLmFjdGl2YXRpb24ubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIWdyb3VwLmFjdGl2YXRpb25baV0gfHwgZ3JvdXAuYWN0aXZhdGlvbltpXSAhPT0gdHJ1ZSAmJiAhZ3JvdXAuYWN0aXZhdGlvbltpXS5kYXRhLmxlbmd0aCkgY29udGludWU7XG4gICAgYmF0Y2gucHVzaC5hcHBseShiYXRjaCwgX3RvQ29uc3VtYWJsZUFycmF5KHRoaXMuZ2V0TWFya2VyRHJhd09wdGlvbnMoaSwgZ3JvdXAsIGVscykpKTtcbiAgfVxuXG4gIGlmIChiYXRjaC5sZW5ndGgpIHtcbiAgICB0aGlzLmRyYXdNYXJrZXIoYmF0Y2gpO1xuICB9XG59OyAvLyBnZXQgb3B0aW9ucyBmb3IgdGhlIG1hcmtlciBpZHNcblxuXG5TY2F0dGVyLnByb3RvdHlwZS5nZXRNYXJrZXJEcmF3T3B0aW9ucyA9IGZ1bmN0aW9uIChtYXJrZXJJZCwgZ3JvdXAsIGVsZW1lbnRzKSB7XG4gIHZhciByYW5nZSA9IGdyb3VwLnJhbmdlLFxuICAgICAgdHJlZSA9IGdyb3VwLnRyZWUsXG4gICAgICB2aWV3cG9ydCA9IGdyb3VwLnZpZXdwb3J0LFxuICAgICAgYWN0aXZhdGlvbiA9IGdyb3VwLmFjdGl2YXRpb24sXG4gICAgICBzZWxlY3Rpb25CdWZmZXIgPSBncm91cC5zZWxlY3Rpb25CdWZmZXIsXG4gICAgICBjb3VudCA9IGdyb3VwLmNvdW50O1xuICB2YXIgcmVnbCA9IHRoaXMucmVnbDsgLy8gZGlyZWN0IHBvaW50c1xuXG4gIGlmICghdHJlZSkge1xuICAgIC8vIGlmIGVsZW1lbnRzIGFycmF5IC0gZHJhdyB1bmNsdXN0ZXJlZCBwb2ludHNcbiAgICBpZiAoZWxlbWVudHMpIHtcbiAgICAgIHJldHVybiBbZXh0ZW5kKHt9LCBncm91cCwge1xuICAgICAgICBtYXJrZXJUZXh0dXJlOiB0aGlzLm1hcmtlclRleHR1cmVzW21hcmtlcklkXSxcbiAgICAgICAgYWN0aXZhdGlvbjogYWN0aXZhdGlvblttYXJrZXJJZF0sXG4gICAgICAgIGNvdW50OiBlbGVtZW50cy5sZW5ndGgsXG4gICAgICAgIGVsZW1lbnRzOiBlbGVtZW50cyxcbiAgICAgICAgb2Zmc2V0OiAwXG4gICAgICB9KV07XG4gICAgfVxuXG4gICAgcmV0dXJuIFtleHRlbmQoe30sIGdyb3VwLCB7XG4gICAgICBtYXJrZXJUZXh0dXJlOiB0aGlzLm1hcmtlclRleHR1cmVzW21hcmtlcklkXSxcbiAgICAgIGFjdGl2YXRpb246IGFjdGl2YXRpb25bbWFya2VySWRdLFxuICAgICAgb2Zmc2V0OiAwXG4gICAgfSldO1xuICB9IC8vIGNsdXN0ZXJlZCBwb2ludHNcblxuXG4gIHZhciBiYXRjaCA9IFtdO1xuICB2YXIgbG9kID0gdHJlZS5yYW5nZShyYW5nZSwge1xuICAgIGxvZDogdHJ1ZSxcbiAgICBweDogWyhyYW5nZVsyXSAtIHJhbmdlWzBdKSAvIHZpZXdwb3J0LndpZHRoLCAocmFuZ2VbM10gLSByYW5nZVsxXSkgLyB2aWV3cG9ydC5oZWlnaHRdXG4gIH0pOyAvLyBlbmFibGUgZWxlbWVudHMgYnkgdXNpbmcgc2VsZWN0aW9uIGJ1ZmZlclxuXG4gIGlmIChlbGVtZW50cykge1xuICAgIHZhciBtYXJrZXJBY3RpdmF0aW9uID0gYWN0aXZhdGlvblttYXJrZXJJZF07XG4gICAgdmFyIG1hc2sgPSBtYXJrZXJBY3RpdmF0aW9uLmRhdGE7XG4gICAgdmFyIGRhdGEgPSBuZXcgVWludDhBcnJheShjb3VudCk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgaWQgPSBlbGVtZW50c1tpXTtcbiAgICAgIGRhdGFbaWRdID0gbWFzayA/IG1hc2tbaWRdIDogMTtcbiAgICB9XG5cbiAgICBzZWxlY3Rpb25CdWZmZXIuc3ViZGF0YShkYXRhKTtcbiAgfVxuXG4gIGZvciAodmFyIGwgPSBsb2QubGVuZ3RoOyBsLS07KSB7XG4gICAgdmFyIF9sb2QkbCA9IF9zbGljZWRUb0FycmF5KGxvZFtsXSwgMiksXG4gICAgICAgIGZyb20gPSBfbG9kJGxbMF0sXG4gICAgICAgIHRvID0gX2xvZCRsWzFdO1xuXG4gICAgYmF0Y2gucHVzaChleHRlbmQoe30sIGdyb3VwLCB7XG4gICAgICBtYXJrZXJUZXh0dXJlOiB0aGlzLm1hcmtlclRleHR1cmVzW21hcmtlcklkXSxcbiAgICAgIGFjdGl2YXRpb246IGVsZW1lbnRzID8gc2VsZWN0aW9uQnVmZmVyIDogYWN0aXZhdGlvblttYXJrZXJJZF0sXG4gICAgICBvZmZzZXQ6IGZyb20sXG4gICAgICBjb3VudDogdG8gLSBmcm9tXG4gICAgfSkpO1xuICB9XG5cbiAgcmV0dXJuIGJhdGNoO1xufTsgLy8gdXBkYXRlIGdyb3VwcyBvcHRpb25zXG5cblxuU2NhdHRlci5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgX3RoaXMzID0gdGhpcztcblxuICBmb3IgKHZhciBfbGVuMiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBuZXcgQXJyYXkoX2xlbjIpLCBfa2V5MiA9IDA7IF9rZXkyIDwgX2xlbjI7IF9rZXkyKyspIHtcbiAgICBhcmdzW19rZXkyXSA9IGFyZ3VtZW50c1tfa2V5Ml07XG4gIH1cblxuICBpZiAoIWFyZ3MubGVuZ3RoKSByZXR1cm47IC8vIHBhc3NlcyBhcmUgYXMgc2luZ2xlIGFycmF5XG5cbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAxICYmIEFycmF5LmlzQXJyYXkoYXJnc1swXSkpIGFyZ3MgPSBhcmdzWzBdO1xuICB2YXIgZ3JvdXBzID0gdGhpcy5ncm91cHMsXG4gICAgICBnbCA9IHRoaXMuZ2wsXG4gICAgICByZWdsID0gdGhpcy5yZWdsLFxuICAgICAgbWF4U2l6ZSA9IHRoaXMubWF4U2l6ZSxcbiAgICAgIG1heENvbG9ycyA9IHRoaXMubWF4Q29sb3JzLFxuICAgICAgcGFsZXR0ZSA9IHRoaXMucGFsZXR0ZTtcbiAgdGhpcy5ncm91cHMgPSBncm91cHMgPSBhcmdzLm1hcChmdW5jdGlvbiAob3B0aW9ucywgaSkge1xuICAgIHZhciBncm91cCA9IGdyb3Vwc1tpXTtcbiAgICBpZiAob3B0aW9ucyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gZ3JvdXA7XG4gICAgaWYgKG9wdGlvbnMgPT09IG51bGwpIG9wdGlvbnMgPSB7XG4gICAgICBwb3NpdGlvbnM6IG51bGxcbiAgICB9O2Vsc2UgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnZnVuY3Rpb24nKSBvcHRpb25zID0ge1xuICAgICAgb25kcmF3OiBvcHRpb25zXG4gICAgfTtlbHNlIGlmICh0eXBlb2Ygb3B0aW9uc1swXSA9PT0gJ251bWJlcicpIG9wdGlvbnMgPSB7XG4gICAgICBwb3NpdGlvbnM6IG9wdGlvbnMgLy8gY29weSBvcHRpb25zIHRvIGF2b2lkIG11dGF0aW9uICYgaGFuZGxlIGFsaWFzZXNcblxuICAgIH07XG4gICAgb3B0aW9ucyA9IHBpY2sob3B0aW9ucywge1xuICAgICAgcG9zaXRpb25zOiAncG9zaXRpb25zIGRhdGEgcG9pbnRzJyxcbiAgICAgIHNuYXA6ICdzbmFwIGNsdXN0ZXIgbG9kIHRyZWUnLFxuICAgICAgc2l6ZTogJ3NpemVzIHNpemUgcmFkaXVzJyxcbiAgICAgIGJvcmRlclNpemU6ICdib3JkZXJTaXplcyBib3JkZXJTaXplIGJvcmRlci1zaXplIGJvcmRlcnNpemUgYm9yZGVyV2lkdGggYm9yZGVyV2lkdGhzIGJvcmRlci13aWR0aCBib3JkZXJ3aWR0aCBzdHJva2Utd2lkdGggc3Ryb2tlV2lkdGggc3Ryb2tld2lkdGggb3V0bGluZScsXG4gICAgICBjb2xvcjogJ2NvbG9ycyBjb2xvciBmaWxsIGZpbGwtY29sb3IgZmlsbENvbG9yJyxcbiAgICAgIGJvcmRlckNvbG9yOiAnYm9yZGVyQ29sb3JzIGJvcmRlckNvbG9yIHN0cm9rZSBzdHJva2UtY29sb3Igc3Ryb2tlQ29sb3InLFxuICAgICAgbWFya2VyOiAnbWFya2VycyBtYXJrZXIgc2hhcGUnLFxuICAgICAgcmFuZ2U6ICdyYW5nZSBkYXRhQm94IGRhdGFib3gnLFxuICAgICAgdmlld3BvcnQ6ICd2aWV3cG9ydCB2aWV3UG9ydCB2aWV3Qm94IHZpZXdib3gnLFxuICAgICAgb3BhY2l0eTogJ29wYWNpdHkgYWxwaGEgdHJhbnNwYXJlbmN5JyxcbiAgICAgIGJvdW5kczogJ2JvdW5kIGJvdW5kcyBib3VuZGFyaWVzIGxpbWl0cycsXG4gICAgICB0b29NYW55Q29sb3JzOiAndG9vTWFueUNvbG9ycyBwYWxldHRlIHBhbGV0dGVNb2RlIG9wdGltaXplUGFsZXR0ZSBlbmFibGVQYWxldHRlJ1xuICAgIH0pO1xuICAgIGlmIChvcHRpb25zLnBvc2l0aW9ucyA9PT0gbnVsbCkgb3B0aW9ucy5wb3NpdGlvbnMgPSBbXTtcbiAgICBpZiAob3B0aW9ucy50b29NYW55Q29sb3JzICE9IG51bGwpIF90aGlzMy50b29NYW55Q29sb3JzID0gb3B0aW9ucy50b29NYW55Q29sb3JzO1xuXG4gICAgaWYgKCFncm91cCkge1xuICAgICAgZ3JvdXBzW2ldID0gZ3JvdXAgPSB7XG4gICAgICAgIGlkOiBpLFxuICAgICAgICBzY2FsZTogbnVsbCxcbiAgICAgICAgdHJhbnNsYXRlOiBudWxsLFxuICAgICAgICBzY2FsZUZyYWN0OiBudWxsLFxuICAgICAgICB0cmFuc2xhdGVGcmFjdDogbnVsbCxcbiAgICAgICAgLy8gYnVmZmVycyBmb3IgYWN0aXZlIG1hcmtlcnNcbiAgICAgICAgYWN0aXZhdGlvbjogW10sXG4gICAgICAgIC8vIGJ1ZmZlciBmb3IgZmlsdGVyZWQgbWFya2Vyc1xuICAgICAgICBzZWxlY3Rpb25CdWZmZXI6IHJlZ2wuYnVmZmVyKHtcbiAgICAgICAgICBkYXRhOiBuZXcgVWludDhBcnJheSgwKSxcbiAgICAgICAgICB1c2FnZTogJ3N0cmVhbScsXG4gICAgICAgICAgdHlwZTogJ3VpbnQ4J1xuICAgICAgICB9KSxcbiAgICAgICAgLy8gYnVmZmVycyB3aXRoIGRhdGE6IGl0IGlzIGZhc3RlciB0byBzd2l0Y2ggdGhlbSBwZXItcGFzc1xuICAgICAgICAvLyB0aGFuIHByb3ZpZGUgb25lIGNvbmdyZWdhdGUgYnVmZmVyXG4gICAgICAgIHNpemVCdWZmZXI6IHJlZ2wuYnVmZmVyKHtcbiAgICAgICAgICBkYXRhOiBuZXcgVWludDhBcnJheSgwKSxcbiAgICAgICAgICB1c2FnZTogJ2R5bmFtaWMnLFxuICAgICAgICAgIHR5cGU6ICd1aW50OCdcbiAgICAgICAgfSksXG4gICAgICAgIGNvbG9yQnVmZmVyOiByZWdsLmJ1ZmZlcih7XG4gICAgICAgICAgZGF0YTogbmV3IFVpbnQ4QXJyYXkoMCksXG4gICAgICAgICAgdXNhZ2U6ICdkeW5hbWljJyxcbiAgICAgICAgICB0eXBlOiAndWludDgnXG4gICAgICAgIH0pLFxuICAgICAgICBwb3NpdGlvbkJ1ZmZlcjogcmVnbC5idWZmZXIoe1xuICAgICAgICAgIGRhdGE6IG5ldyBVaW50OEFycmF5KDApLFxuICAgICAgICAgIHVzYWdlOiAnZHluYW1pYycsXG4gICAgICAgICAgdHlwZTogJ2Zsb2F0J1xuICAgICAgICB9KSxcbiAgICAgICAgcG9zaXRpb25GcmFjdEJ1ZmZlcjogcmVnbC5idWZmZXIoe1xuICAgICAgICAgIGRhdGE6IG5ldyBVaW50OEFycmF5KDApLFxuICAgICAgICAgIHVzYWdlOiAnZHluYW1pYycsXG4gICAgICAgICAgdHlwZTogJ2Zsb2F0J1xuICAgICAgICB9KVxuICAgICAgfTtcbiAgICAgIG9wdGlvbnMgPSBleHRlbmQoe30sIFNjYXR0ZXIuZGVmYXVsdHMsIG9wdGlvbnMpO1xuICAgIH0gLy8gZm9yY2UgdXBkYXRlIHRyaWdnZXJzXG5cblxuICAgIGlmIChvcHRpb25zLnBvc2l0aW9ucyAmJiAhKCdtYXJrZXInIGluIG9wdGlvbnMpKSB7XG4gICAgICBvcHRpb25zLm1hcmtlciA9IGdyb3VwLm1hcmtlcjtcbiAgICAgIGRlbGV0ZSBncm91cC5tYXJrZXI7XG4gICAgfSAvLyB1cGRhdGluZyBtYXJrZXJzIGNhdXNlIHJlY2FsY3VsYXRpbmcgc25hcHBpbmdcblxuXG4gICAgaWYgKG9wdGlvbnMubWFya2VyICYmICEoJ3Bvc2l0aW9ucycgaW4gb3B0aW9ucykpIHtcbiAgICAgIG9wdGlvbnMucG9zaXRpb25zID0gZ3JvdXAucG9zaXRpb25zO1xuICAgICAgZGVsZXRlIGdyb3VwLnBvc2l0aW9ucztcbiAgICB9IC8vIGdsb2JhbCBjb3VudCBvZiBwb2ludHNcblxuXG4gICAgdmFyIGhhc1NpemUgPSAwLFxuICAgICAgICBoYXNDb2xvciA9IDA7XG4gICAgdXBkYXRlRGlmZihncm91cCwgb3B0aW9ucywgW3tcbiAgICAgIHNuYXA6IHRydWUsXG4gICAgICBzaXplOiBmdW5jdGlvbiBzaXplKHMsIGdyb3VwKSB7XG4gICAgICAgIGlmIChzID09IG51bGwpIHMgPSBTY2F0dGVyLmRlZmF1bHRzLnNpemU7XG4gICAgICAgIGhhc1NpemUgKz0gcyAmJiBzLmxlbmd0aCA/IDEgOiAwO1xuICAgICAgICByZXR1cm4gcztcbiAgICAgIH0sXG4gICAgICBib3JkZXJTaXplOiBmdW5jdGlvbiBib3JkZXJTaXplKHMsIGdyb3VwKSB7XG4gICAgICAgIGlmIChzID09IG51bGwpIHMgPSBTY2F0dGVyLmRlZmF1bHRzLmJvcmRlclNpemU7XG4gICAgICAgIGhhc1NpemUgKz0gcyAmJiBzLmxlbmd0aCA/IDEgOiAwO1xuICAgICAgICByZXR1cm4gcztcbiAgICAgIH0sXG4gICAgICBvcGFjaXR5OiBwYXJzZUZsb2F0LFxuICAgICAgLy8gYWRkIGNvbG9ycyB0byBwYWxldHRlLCBzYXZlIHJlZmVyZW5jZXNcbiAgICAgIGNvbG9yOiBmdW5jdGlvbiBjb2xvcihjLCBncm91cCkge1xuICAgICAgICBpZiAoYyA9PSBudWxsKSBjID0gU2NhdHRlci5kZWZhdWx0cy5jb2xvcjtcbiAgICAgICAgYyA9IF90aGlzMy51cGRhdGVDb2xvcihjKTtcbiAgICAgICAgaGFzQ29sb3IrKztcbiAgICAgICAgcmV0dXJuIGM7XG4gICAgICB9LFxuICAgICAgYm9yZGVyQ29sb3I6IGZ1bmN0aW9uIGJvcmRlckNvbG9yKGMsIGdyb3VwKSB7XG4gICAgICAgIGlmIChjID09IG51bGwpIGMgPSBTY2F0dGVyLmRlZmF1bHRzLmJvcmRlckNvbG9yO1xuICAgICAgICBjID0gX3RoaXMzLnVwZGF0ZUNvbG9yKGMpO1xuICAgICAgICBoYXNDb2xvcisrO1xuICAgICAgICByZXR1cm4gYztcbiAgICAgIH0sXG4gICAgICBib3VuZHM6IGZ1bmN0aW9uIGJvdW5kcyhfYm91bmRzLCBncm91cCwgb3B0aW9ucykge1xuICAgICAgICBpZiAoISgncmFuZ2UnIGluIG9wdGlvbnMpKSBvcHRpb25zLnJhbmdlID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIF9ib3VuZHM7XG4gICAgICB9LFxuICAgICAgcG9zaXRpb25zOiBmdW5jdGlvbiBwb3NpdGlvbnMoX3Bvc2l0aW9ucywgZ3JvdXAsIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHNuYXAgPSBncm91cC5zbmFwO1xuICAgICAgICB2YXIgcG9zaXRpb25CdWZmZXIgPSBncm91cC5wb3NpdGlvbkJ1ZmZlcixcbiAgICAgICAgICAgIHBvc2l0aW9uRnJhY3RCdWZmZXIgPSBncm91cC5wb3NpdGlvbkZyYWN0QnVmZmVyLFxuICAgICAgICAgICAgc2VsZWN0aW9uQnVmZmVyID0gZ3JvdXAuc2VsZWN0aW9uQnVmZmVyOyAvLyBzZXBhcmF0ZSBidWZmZXJzIGZvciB4L3kgY29vcmRpbmF0ZXNcblxuICAgICAgICBpZiAoX3Bvc2l0aW9ucy54IHx8IF9wb3NpdGlvbnMueSkge1xuICAgICAgICAgIGlmIChfcG9zaXRpb25zLngubGVuZ3RoKSB7XG4gICAgICAgICAgICBncm91cC54QXR0ciA9IHtcbiAgICAgICAgICAgICAgYnVmZmVyOiByZWdsLmJ1ZmZlcihfcG9zaXRpb25zLngpLFxuICAgICAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgICAgIHN0cmlkZTogNCxcbiAgICAgICAgICAgICAgY291bnQ6IF9wb3NpdGlvbnMueC5sZW5ndGhcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdyb3VwLnhBdHRyID0ge1xuICAgICAgICAgICAgICBidWZmZXI6IF9wb3NpdGlvbnMueC5idWZmZXIsXG4gICAgICAgICAgICAgIG9mZnNldDogX3Bvc2l0aW9ucy54Lm9mZnNldCAqIDQgfHwgMCxcbiAgICAgICAgICAgICAgc3RyaWRlOiAoX3Bvc2l0aW9ucy54LnN0cmlkZSB8fCAxKSAqIDQsXG4gICAgICAgICAgICAgIGNvdW50OiBfcG9zaXRpb25zLnguY291bnRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKF9wb3NpdGlvbnMueS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGdyb3VwLnlBdHRyID0ge1xuICAgICAgICAgICAgICBidWZmZXI6IHJlZ2wuYnVmZmVyKF9wb3NpdGlvbnMueSksXG4gICAgICAgICAgICAgIG9mZnNldDogMCxcbiAgICAgICAgICAgICAgc3RyaWRlOiA0LFxuICAgICAgICAgICAgICBjb3VudDogX3Bvc2l0aW9ucy55Lmxlbmd0aFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ3JvdXAueUF0dHIgPSB7XG4gICAgICAgICAgICAgIGJ1ZmZlcjogX3Bvc2l0aW9ucy55LmJ1ZmZlcixcbiAgICAgICAgICAgICAgb2Zmc2V0OiBfcG9zaXRpb25zLnkub2Zmc2V0ICogNCB8fCAwLFxuICAgICAgICAgICAgICBzdHJpZGU6IChfcG9zaXRpb25zLnkuc3RyaWRlIHx8IDEpICogNCxcbiAgICAgICAgICAgICAgY291bnQ6IF9wb3NpdGlvbnMueS5jb3VudFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBncm91cC5jb3VudCA9IE1hdGgubWF4KGdyb3VwLnhBdHRyLmNvdW50LCBncm91cC55QXR0ci5jb3VudCk7XG4gICAgICAgICAgcmV0dXJuIF9wb3NpdGlvbnM7XG4gICAgICAgIH1cblxuICAgICAgICBfcG9zaXRpb25zID0gZmxhdHRlbihfcG9zaXRpb25zLCAnZmxvYXQ2NCcpO1xuICAgICAgICB2YXIgY291bnQgPSBncm91cC5jb3VudCA9IE1hdGguZmxvb3IoX3Bvc2l0aW9ucy5sZW5ndGggLyAyKTtcbiAgICAgICAgdmFyIGJvdW5kcyA9IGdyb3VwLmJvdW5kcyA9IGNvdW50ID8gZ2V0Qm91bmRzKF9wb3NpdGlvbnMsIDIpIDogbnVsbDsgLy8gaWYgcmFuZ2UgaXMgbm90IHByb3ZpZGVkIHVwZGF0ZWQgLSByZWNhbGMgaXRcblxuICAgICAgICBpZiAoIW9wdGlvbnMucmFuZ2UgJiYgIWdyb3VwLnJhbmdlKSB7XG4gICAgICAgICAgZGVsZXRlIGdyb3VwLnJhbmdlO1xuICAgICAgICAgIG9wdGlvbnMucmFuZ2UgPSBib3VuZHM7XG4gICAgICAgIH0gLy8gcmVzZXQgbWFya2VyXG5cblxuICAgICAgICBpZiAoIW9wdGlvbnMubWFya2VyICYmICFncm91cC5tYXJrZXIpIHtcbiAgICAgICAgICBkZWxldGUgZ3JvdXAubWFya2VyO1xuICAgICAgICAgIG9wdGlvbnMubWFya2VyID0gbnVsbDtcbiAgICAgICAgfSAvLyBidWlsZCBjbHVzdGVyIHRyZWUgaWYgcmVxdWlyZWRcblxuXG4gICAgICAgIGlmIChzbmFwICYmIChzbmFwID09PSB0cnVlIHx8IGNvdW50ID4gc25hcCkpIHtcbiAgICAgICAgICBncm91cC50cmVlID0gY2x1c3RlcihfcG9zaXRpb25zLCB7XG4gICAgICAgICAgICBib3VuZHM6IGJvdW5kc1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IC8vIGV4aXN0aW5nIHRyZWUgaW5zdGFuY2VcbiAgICAgICAgZWxzZSBpZiAoc25hcCAmJiBzbmFwLmxlbmd0aCkge1xuICAgICAgICAgICAgZ3JvdXAudHJlZSA9IHNuYXA7XG4gICAgICAgICAgfVxuXG4gICAgICAgIGlmIChncm91cC50cmVlKSB7XG4gICAgICAgICAgdmFyIG9wdHMgPSB7XG4gICAgICAgICAgICBwcmltaXRpdmU6ICdwb2ludHMnLFxuICAgICAgICAgICAgdXNhZ2U6ICdzdGF0aWMnLFxuICAgICAgICAgICAgZGF0YTogZ3JvdXAudHJlZSxcbiAgICAgICAgICAgIHR5cGU6ICd1aW50MzInXG4gICAgICAgICAgfTtcbiAgICAgICAgICBpZiAoZ3JvdXAuZWxlbWVudHMpIGdyb3VwLmVsZW1lbnRzKG9wdHMpO2Vsc2UgZ3JvdXAuZWxlbWVudHMgPSByZWdsLmVsZW1lbnRzKG9wdHMpO1xuICAgICAgICB9IC8vIHVwZGF0ZSBwb3NpdGlvbiBidWZmZXJzXG5cblxuICAgICAgICBwb3NpdGlvbkJ1ZmZlcih7XG4gICAgICAgICAgZGF0YTogZjMyLmZsb2F0KF9wb3NpdGlvbnMpLFxuICAgICAgICAgIHVzYWdlOiAnZHluYW1pYydcbiAgICAgICAgfSk7XG4gICAgICAgIHBvc2l0aW9uRnJhY3RCdWZmZXIoe1xuICAgICAgICAgIGRhdGE6IGYzMi5mcmFjdChfcG9zaXRpb25zKSxcbiAgICAgICAgICB1c2FnZTogJ2R5bmFtaWMnXG4gICAgICAgIH0pOyAvLyBleHBhbmQgc2VsZWN0aW9uQnVmZmVyXG5cbiAgICAgICAgc2VsZWN0aW9uQnVmZmVyKHtcbiAgICAgICAgICBkYXRhOiBuZXcgVWludDhBcnJheShjb3VudCksXG4gICAgICAgICAgdHlwZTogJ3VpbnQ4JyxcbiAgICAgICAgICB1c2FnZTogJ3N0cmVhbSdcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBfcG9zaXRpb25zO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIC8vIGNyZWF0ZSBtYXJrZXIgaWRzIGNvcnJlc3BvbmRpbmcgdG8ga25vd24gbWFya2VyIHRleHR1cmVzXG4gICAgICBtYXJrZXI6IGZ1bmN0aW9uIG1hcmtlcihtYXJrZXJzLCBncm91cCwgb3B0aW9ucykge1xuICAgICAgICB2YXIgYWN0aXZhdGlvbiA9IGdyb3VwLmFjdGl2YXRpb247IC8vIHJlc2V0IG1hcmtlciBlbGVtZW50c1xuXG4gICAgICAgIGFjdGl2YXRpb24uZm9yRWFjaChmdW5jdGlvbiAoYnVmZmVyKSB7XG4gICAgICAgICAgcmV0dXJuIGJ1ZmZlciAmJiBidWZmZXIuZGVzdHJveSAmJiBidWZmZXIuZGVzdHJveSgpO1xuICAgICAgICB9KTtcbiAgICAgICAgYWN0aXZhdGlvbi5sZW5ndGggPSAwOyAvLyBzaW5nbGUgc2RmIG1hcmtlclxuXG4gICAgICAgIGlmICghbWFya2VycyB8fCB0eXBlb2YgbWFya2Vyc1swXSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICB2YXIgaWQgPSBfdGhpczMuYWRkTWFya2VyKG1hcmtlcnMpO1xuXG4gICAgICAgICAgYWN0aXZhdGlvbltpZF0gPSB0cnVlO1xuICAgICAgICB9IC8vIHBlci1wb2ludCBtYXJrZXJzIHVzZSBtYXNrIGJ1ZmZlcnMgdG8gZW5hYmxlIG1hcmtlcnMgaW4gdmVydCBzaGFkZXJcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgbWFya2VyTWFza3MgPSBbXTtcblxuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBsID0gTWF0aC5taW4obWFya2Vycy5sZW5ndGgsIGdyb3VwLmNvdW50KTsgX2kgPCBsOyBfaSsrKSB7XG4gICAgICAgICAgICAgIHZhciBfaWQgPSBfdGhpczMuYWRkTWFya2VyKG1hcmtlcnNbX2ldKTtcblxuICAgICAgICAgICAgICBpZiAoIW1hcmtlck1hc2tzW19pZF0pIG1hcmtlck1hc2tzW19pZF0gPSBuZXcgVWludDhBcnJheShncm91cC5jb3VudCk7IC8vIGVuYWJsZSBtYXJrZXIgYnkgZGVmYXVsdFxuXG4gICAgICAgICAgICAgIG1hcmtlck1hc2tzW19pZF1bX2ldID0gMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yICh2YXIgX2lkMiA9IDA7IF9pZDIgPCBtYXJrZXJNYXNrcy5sZW5ndGg7IF9pZDIrKykge1xuICAgICAgICAgICAgICBpZiAoIW1hcmtlck1hc2tzW19pZDJdKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgdmFyIG9wdHMgPSB7XG4gICAgICAgICAgICAgICAgZGF0YTogbWFya2VyTWFza3NbX2lkMl0sXG4gICAgICAgICAgICAgICAgdHlwZTogJ3VpbnQ4JyxcbiAgICAgICAgICAgICAgICB1c2FnZTogJ3N0YXRpYydcbiAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICBpZiAoIWFjdGl2YXRpb25bX2lkMl0pIHtcbiAgICAgICAgICAgICAgICBhY3RpdmF0aW9uW19pZDJdID0gcmVnbC5idWZmZXIob3B0cyk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYWN0aXZhdGlvbltfaWQyXShvcHRzKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGFjdGl2YXRpb25bX2lkMl0uZGF0YSA9IG1hcmtlck1hc2tzW19pZDJdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbWFya2VycztcbiAgICAgIH0sXG4gICAgICByYW5nZTogZnVuY3Rpb24gcmFuZ2UoX3JhbmdlLCBncm91cCwgb3B0aW9ucykge1xuICAgICAgICB2YXIgYm91bmRzID0gZ3JvdXAuYm91bmRzOyAvLyBGSVhNRTogd2h5IGRvIHdlIG5lZWQgdGhpcz9cblxuICAgICAgICBpZiAoIWJvdW5kcykgcmV0dXJuO1xuICAgICAgICBpZiAoIV9yYW5nZSkgX3JhbmdlID0gYm91bmRzO1xuICAgICAgICBncm91cC5zY2FsZSA9IFsxIC8gKF9yYW5nZVsyXSAtIF9yYW5nZVswXSksIDEgLyAoX3JhbmdlWzNdIC0gX3JhbmdlWzFdKV07XG4gICAgICAgIGdyb3VwLnRyYW5zbGF0ZSA9IFstX3JhbmdlWzBdLCAtX3JhbmdlWzFdXTtcbiAgICAgICAgZ3JvdXAuc2NhbGVGcmFjdCA9IGYzMi5mcmFjdChncm91cC5zY2FsZSk7XG4gICAgICAgIGdyb3VwLnRyYW5zbGF0ZUZyYWN0ID0gZjMyLmZyYWN0KGdyb3VwLnRyYW5zbGF0ZSk7XG4gICAgICAgIHJldHVybiBfcmFuZ2U7XG4gICAgICB9LFxuICAgICAgdmlld3BvcnQ6IGZ1bmN0aW9uIHZpZXdwb3J0KHZwKSB7XG4gICAgICAgIHZhciByZWN0ID0gcGFyc2VSZWN0KHZwIHx8IFtnbC5kcmF3aW5nQnVmZmVyV2lkdGgsIGdsLmRyYXdpbmdCdWZmZXJIZWlnaHRdKTsgLy8gbm9ybWFsaXplIHZpZXdwb3J0IHRvIHRoZSBjYW52YXMgY29vcmRpbmF0ZXNcbiAgICAgICAgLy8gcmVjdC55ID0gZ2wuZHJhd2luZ0J1ZmZlckhlaWdodCAtIHJlY3QuaGVpZ2h0IC0gcmVjdC55XG5cbiAgICAgICAgcmV0dXJuIHJlY3Q7XG4gICAgICB9XG4gICAgfV0pOyAvLyB1cGRhdGUgc2l6ZSBidWZmZXIsIGlmIG5lZWRlZFxuXG4gICAgaWYgKGhhc1NpemUpIHtcbiAgICAgIHZhciBfZ3JvdXAgPSBncm91cCxcbiAgICAgICAgICBjb3VudCA9IF9ncm91cC5jb3VudCxcbiAgICAgICAgICBzaXplID0gX2dyb3VwLnNpemUsXG4gICAgICAgICAgYm9yZGVyU2l6ZSA9IF9ncm91cC5ib3JkZXJTaXplLFxuICAgICAgICAgIHNpemVCdWZmZXIgPSBfZ3JvdXAuc2l6ZUJ1ZmZlcjtcbiAgICAgIHZhciBzaXplcyA9IG5ldyBVaW50OEFycmF5KGNvdW50ICogMik7XG5cbiAgICAgIGlmIChzaXplLmxlbmd0aCB8fCBib3JkZXJTaXplLmxlbmd0aCkge1xuICAgICAgICBmb3IgKHZhciBfaTIgPSAwOyBfaTIgPCBjb3VudDsgX2kyKyspIHtcbiAgICAgICAgICAvLyB3ZSBkb3duc2NhbGUgc2l6ZSB0byBhbGxvdyBmb3IgZnJhY3Rpb25zXG4gICAgICAgICAgc2l6ZXNbX2kyICogMl0gPSBNYXRoLnJvdW5kKChzaXplW19pMl0gPT0gbnVsbCA/IHNpemUgOiBzaXplW19pMl0pICogMjU1IC8gbWF4U2l6ZSk7XG4gICAgICAgICAgc2l6ZXNbX2kyICogMiArIDFdID0gTWF0aC5yb3VuZCgoYm9yZGVyU2l6ZVtfaTJdID09IG51bGwgPyBib3JkZXJTaXplIDogYm9yZGVyU2l6ZVtfaTJdKSAqIDI1NSAvIG1heFNpemUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHNpemVCdWZmZXIoe1xuICAgICAgICBkYXRhOiBzaXplcyxcbiAgICAgICAgdXNhZ2U6ICdkeW5hbWljJ1xuICAgICAgfSk7XG4gICAgfSAvLyB1cGRhdGUgY29sb3IgYnVmZmVyIGlmIG5lZWRlZFxuXG5cbiAgICBpZiAoaGFzQ29sb3IpIHtcbiAgICAgIHZhciBfZ3JvdXAyID0gZ3JvdXAsXG4gICAgICAgICAgX2NvdW50ID0gX2dyb3VwMi5jb3VudCxcbiAgICAgICAgICBjb2xvciA9IF9ncm91cDIuY29sb3IsXG4gICAgICAgICAgYm9yZGVyQ29sb3IgPSBfZ3JvdXAyLmJvcmRlckNvbG9yLFxuICAgICAgICAgIGNvbG9yQnVmZmVyID0gX2dyb3VwMi5jb2xvckJ1ZmZlcjtcbiAgICAgIHZhciBjb2xvcnM7IC8vIGlmIHRvbyBtYW55IGNvbG9ycyAtIHB1dCBjb2xvcnMgdG8gYnVmZmVyIGRpcmVjdGx5XG5cbiAgICAgIGlmIChfdGhpczMudG9vTWFueUNvbG9ycykge1xuICAgICAgICBpZiAoY29sb3IubGVuZ3RoIHx8IGJvcmRlckNvbG9yLmxlbmd0aCkge1xuICAgICAgICAgIGNvbG9ycyA9IG5ldyBVaW50OEFycmF5KF9jb3VudCAqIDgpO1xuXG4gICAgICAgICAgZm9yICh2YXIgX2kzID0gMDsgX2kzIDwgX2NvdW50OyBfaTMrKykge1xuICAgICAgICAgICAgdmFyIF9jb2xvcklkID0gY29sb3JbX2kzXTtcbiAgICAgICAgICAgIGNvbG9yc1tfaTMgKiA4XSA9IHBhbGV0dGVbX2NvbG9ySWQgKiA0XTtcbiAgICAgICAgICAgIGNvbG9yc1tfaTMgKiA4ICsgMV0gPSBwYWxldHRlW19jb2xvcklkICogNCArIDFdO1xuICAgICAgICAgICAgY29sb3JzW19pMyAqIDggKyAyXSA9IHBhbGV0dGVbX2NvbG9ySWQgKiA0ICsgMl07XG4gICAgICAgICAgICBjb2xvcnNbX2kzICogOCArIDNdID0gcGFsZXR0ZVtfY29sb3JJZCAqIDQgKyAzXTtcbiAgICAgICAgICAgIHZhciBib3JkZXJDb2xvcklkID0gYm9yZGVyQ29sb3JbX2kzXTtcbiAgICAgICAgICAgIGNvbG9yc1tfaTMgKiA4ICsgNF0gPSBwYWxldHRlW2JvcmRlckNvbG9ySWQgKiA0XTtcbiAgICAgICAgICAgIGNvbG9yc1tfaTMgKiA4ICsgNV0gPSBwYWxldHRlW2JvcmRlckNvbG9ySWQgKiA0ICsgMV07XG4gICAgICAgICAgICBjb2xvcnNbX2kzICogOCArIDZdID0gcGFsZXR0ZVtib3JkZXJDb2xvcklkICogNCArIDJdO1xuICAgICAgICAgICAgY29sb3JzW19pMyAqIDggKyA3XSA9IHBhbGV0dGVbYm9yZGVyQ29sb3JJZCAqIDQgKyAzXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gLy8gaWYgbGltaXRlZCBhbW91bnQgb2YgY29sb3JzIC0ga2VlcCBwYWxldHRlIGNvbG9yIHBpY2tpbmdcbiAgICAgIC8vIHRoYXQgc2F2ZXMgc2lnbmlmaWNhbnQgbWVtb3J5XG4gICAgICBlbHNlIHtcbiAgICAgICAgICBpZiAoY29sb3IubGVuZ3RoIHx8IGJvcmRlckNvbG9yLmxlbmd0aCkge1xuICAgICAgICAgICAgLy8gd2UgbmVlZCBzbGlnaHQgZGF0YSBpbmNyZWFzZSBieSAyIGR1ZSB0byB2ZWM0IGJvcmRlcklkIGluIHNoYWRlclxuICAgICAgICAgICAgY29sb3JzID0gbmV3IFVpbnQ4QXJyYXkoX2NvdW50ICogNCArIDIpO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBfaTQgPSAwOyBfaTQgPCBfY291bnQ7IF9pNCsrKSB7XG4gICAgICAgICAgICAgIC8vIHB1dCBjb2xvciBjb29yZHMgaW4gcGFsZXR0ZSB0ZXh0dXJlXG4gICAgICAgICAgICAgIGlmIChjb2xvcltfaTRdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjb2xvcnNbX2k0ICogNF0gPSBjb2xvcltfaTRdICUgbWF4Q29sb3JzO1xuICAgICAgICAgICAgICAgIGNvbG9yc1tfaTQgKiA0ICsgMV0gPSBNYXRoLmZsb29yKGNvbG9yW19pNF0gLyBtYXhDb2xvcnMpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKGJvcmRlckNvbG9yW19pNF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbG9yc1tfaTQgKiA0ICsgMl0gPSBib3JkZXJDb2xvcltfaTRdICUgbWF4Q29sb3JzO1xuICAgICAgICAgICAgICAgIGNvbG9yc1tfaTQgKiA0ICsgM10gPSBNYXRoLmZsb29yKGJvcmRlckNvbG9yW19pNF0gLyBtYXhDb2xvcnMpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgIGNvbG9yQnVmZmVyKHtcbiAgICAgICAgZGF0YTogY29sb3JzIHx8IG5ldyBVaW50OEFycmF5KDApLFxuICAgICAgICB0eXBlOiAndWludDgnLFxuICAgICAgICB1c2FnZTogJ2R5bmFtaWMnXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ3JvdXA7XG4gIH0pO1xufTsgLy8gZ2V0IChhbmQgY3JlYXRlKSBtYXJrZXIgdGV4dHVyZSBpZFxuXG5cblNjYXR0ZXIucHJvdG90eXBlLmFkZE1hcmtlciA9IGZ1bmN0aW9uIChzZGYpIHtcbiAgdmFyIG1hcmtlclRleHR1cmVzID0gdGhpcy5tYXJrZXJUZXh0dXJlcyxcbiAgICAgIHJlZ2wgPSB0aGlzLnJlZ2wsXG4gICAgICBtYXJrZXJDYWNoZSA9IHRoaXMubWFya2VyQ2FjaGU7XG4gIHZhciBwb3MgPSBzZGYgPT0gbnVsbCA/IDAgOiBtYXJrZXJDYWNoZS5pbmRleE9mKHNkZik7XG4gIGlmIChwb3MgPj0gMCkgcmV0dXJuIHBvczsgLy8gY29udmVydCBzZGYgdG8gMC4uMjU1IHJhbmdlXG5cbiAgdmFyIGRpc3RBcnI7XG5cbiAgaWYgKHNkZiBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgfHwgc2RmIGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXkpIHtcbiAgICBkaXN0QXJyID0gc2RmO1xuICB9IGVsc2Uge1xuICAgIGRpc3RBcnIgPSBuZXcgVWludDhBcnJheShzZGYubGVuZ3RoKTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gc2RmLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgZGlzdEFycltpXSA9IHNkZltpXSAqIDI1NTtcbiAgICB9XG4gIH1cblxuICB2YXIgcmFkaXVzID0gTWF0aC5mbG9vcihNYXRoLnNxcnQoZGlzdEFyci5sZW5ndGgpKTtcbiAgcG9zID0gbWFya2VyVGV4dHVyZXMubGVuZ3RoO1xuICBtYXJrZXJDYWNoZS5wdXNoKHNkZik7XG4gIG1hcmtlclRleHR1cmVzLnB1c2gocmVnbC50ZXh0dXJlKHtcbiAgICBjaGFubmVsczogMSxcbiAgICBkYXRhOiBkaXN0QXJyLFxuICAgIHJhZGl1czogcmFkaXVzLFxuICAgIG1hZzogJ2xpbmVhcicsXG4gICAgbWluOiAnbGluZWFyJ1xuICB9KSk7XG4gIHJldHVybiBwb3M7XG59OyAvLyByZWdpc3RlciBjb2xvciB0byBwYWxldHRlLCByZXR1cm4gaXQncyBpbmRleCBvciBsaXN0IG9mIGluZGV4ZXNcblxuXG5TY2F0dGVyLnByb3RvdHlwZS51cGRhdGVDb2xvciA9IGZ1bmN0aW9uIChjb2xvcnMpIHtcbiAgdmFyIHBhbGV0dGVJZHMgPSB0aGlzLnBhbGV0dGVJZHMsXG4gICAgICBwYWxldHRlID0gdGhpcy5wYWxldHRlLFxuICAgICAgbWF4Q29sb3JzID0gdGhpcy5tYXhDb2xvcnM7XG5cbiAgaWYgKCFBcnJheS5pc0FycmF5KGNvbG9ycykpIHtcbiAgICBjb2xvcnMgPSBbY29sb3JzXTtcbiAgfVxuXG4gIHZhciBpZHggPSBbXTsgLy8gaWYgY29sb3IgZ3JvdXBzIC0gZmxhdHRlbiB0aGVtXG5cbiAgaWYgKHR5cGVvZiBjb2xvcnNbMF0gPT09ICdudW1iZXInKSB7XG4gICAgdmFyIGdyb3VwZWQgPSBbXTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbG9ycykpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY29sb3JzLmxlbmd0aDsgaSArPSA0KSB7XG4gICAgICAgIGdyb3VwZWQucHVzaChjb2xvcnMuc2xpY2UoaSwgaSArIDQpKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yICh2YXIgX2k1ID0gMDsgX2k1IDwgY29sb3JzLmxlbmd0aDsgX2k1ICs9IDQpIHtcbiAgICAgICAgZ3JvdXBlZC5wdXNoKGNvbG9ycy5zdWJhcnJheShfaTUsIF9pNSArIDQpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb2xvcnMgPSBncm91cGVkO1xuICB9XG5cbiAgZm9yICh2YXIgX2k2ID0gMDsgX2k2IDwgY29sb3JzLmxlbmd0aDsgX2k2KyspIHtcbiAgICB2YXIgY29sb3IgPSBjb2xvcnNbX2k2XTtcbiAgICBjb2xvciA9IHJnYmEoY29sb3IsICd1aW50OCcpO1xuICAgIHZhciBpZCA9IGNvbG9ySWQoY29sb3IsIGZhbHNlKTsgLy8gaWYgbmV3IGNvbG9yIC0gc2F2ZSBpdFxuXG4gICAgaWYgKHBhbGV0dGVJZHNbaWRdID09IG51bGwpIHtcbiAgICAgIHZhciBwb3MgPSBwYWxldHRlLmxlbmd0aDtcbiAgICAgIHBhbGV0dGVJZHNbaWRdID0gTWF0aC5mbG9vcihwb3MgLyA0KTtcbiAgICAgIHBhbGV0dGVbcG9zXSA9IGNvbG9yWzBdO1xuICAgICAgcGFsZXR0ZVtwb3MgKyAxXSA9IGNvbG9yWzFdO1xuICAgICAgcGFsZXR0ZVtwb3MgKyAyXSA9IGNvbG9yWzJdO1xuICAgICAgcGFsZXR0ZVtwb3MgKyAzXSA9IGNvbG9yWzNdO1xuICAgIH1cblxuICAgIGlkeFtfaTZdID0gcGFsZXR0ZUlkc1tpZF07XG4gIH0gLy8gZGV0ZWN0IGlmIHRvbyBtYW55IGNvbG9ycyBpbiBwYWxldHRlXG5cblxuICBpZiAoIXRoaXMudG9vTWFueUNvbG9ycyAmJiBwYWxldHRlLmxlbmd0aCA+IG1heENvbG9ycyAqIDQpIHRoaXMudG9vTWFueUNvbG9ycyA9IHRydWU7IC8vIGxpbWl0IG1heCBjb2xvclxuXG4gIHRoaXMudXBkYXRlUGFsZXR0ZShwYWxldHRlKTsgLy8ga2VlcCBzdGF0aWMgaW5kZXggZm9yIHNpbmdsZS1jb2xvciBwcm9wZXJ0eVxuXG4gIHJldHVybiBpZHgubGVuZ3RoID09PSAxID8gaWR4WzBdIDogaWR4O1xufTtcblxuU2NhdHRlci5wcm90b3R5cGUudXBkYXRlUGFsZXR0ZSA9IGZ1bmN0aW9uIChwYWxldHRlKSB7XG4gIGlmICh0aGlzLnRvb01hbnlDb2xvcnMpIHJldHVybjtcbiAgdmFyIG1heENvbG9ycyA9IHRoaXMubWF4Q29sb3JzLFxuICAgICAgcGFsZXR0ZVRleHR1cmUgPSB0aGlzLnBhbGV0dGVUZXh0dXJlO1xuICB2YXIgcmVxdWlyZWRIZWlnaHQgPSBNYXRoLmNlaWwocGFsZXR0ZS5sZW5ndGggKiAuMjUgLyBtYXhDb2xvcnMpOyAvLyBwYWQgZGF0YVxuXG4gIGlmIChyZXF1aXJlZEhlaWdodCA+IDEpIHtcbiAgICBwYWxldHRlID0gcGFsZXR0ZS5zbGljZSgpO1xuXG4gICAgZm9yICh2YXIgaSA9IHBhbGV0dGUubGVuZ3RoICogLjI1ICUgbWF4Q29sb3JzOyBpIDwgcmVxdWlyZWRIZWlnaHQgKiBtYXhDb2xvcnM7IGkrKykge1xuICAgICAgcGFsZXR0ZS5wdXNoKDAsIDAsIDAsIDApO1xuICAgIH1cbiAgfSAvLyBlbnN1cmUgaGVpZ2h0XG5cblxuICBpZiAocGFsZXR0ZVRleHR1cmUuaGVpZ2h0IDwgcmVxdWlyZWRIZWlnaHQpIHtcbiAgICBwYWxldHRlVGV4dHVyZS5yZXNpemUobWF4Q29sb3JzLCByZXF1aXJlZEhlaWdodCk7XG4gIH0gLy8gdXBkYXRlIGZ1bGwgZGF0YVxuXG5cbiAgcGFsZXR0ZVRleHR1cmUuc3ViaW1hZ2Uoe1xuICAgIHdpZHRoOiBNYXRoLm1pbihwYWxldHRlLmxlbmd0aCAqIC4yNSwgbWF4Q29sb3JzKSxcbiAgICBoZWlnaHQ6IHJlcXVpcmVkSGVpZ2h0LFxuICAgIGRhdGE6IHBhbGV0dGVcbiAgfSwgMCwgMCk7XG59OyAvLyByZW1vdmUgdW51c2VkIHN0dWZmXG5cblxuU2NhdHRlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5ncm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZ3JvdXApIHtcbiAgICBncm91cC5zaXplQnVmZmVyLmRlc3Ryb3koKTtcbiAgICBncm91cC5wb3NpdGlvbkJ1ZmZlci5kZXN0cm95KCk7XG4gICAgZ3JvdXAucG9zaXRpb25GcmFjdEJ1ZmZlci5kZXN0cm95KCk7XG4gICAgZ3JvdXAuY29sb3JCdWZmZXIuZGVzdHJveSgpO1xuICAgIGdyb3VwLmFjdGl2YXRpb24uZm9yRWFjaChmdW5jdGlvbiAoYikge1xuICAgICAgcmV0dXJuIGIgJiYgYi5kZXN0cm95ICYmIGIuZGVzdHJveSgpO1xuICAgIH0pO1xuICAgIGdyb3VwLnNlbGVjdGlvbkJ1ZmZlci5kZXN0cm95KCk7XG4gICAgaWYgKGdyb3VwLmVsZW1lbnRzKSBncm91cC5lbGVtZW50cy5kZXN0cm95KCk7XG4gIH0pO1xuICB0aGlzLmdyb3Vwcy5sZW5ndGggPSAwO1xuICB0aGlzLnBhbGV0dGVUZXh0dXJlLmRlc3Ryb3koKTtcbiAgdGhpcy5tYXJrZXJUZXh0dXJlcy5mb3JFYWNoKGZ1bmN0aW9uICh0eHQpIHtcbiAgICByZXR1cm4gdHh0ICYmIHR4dC5kZXN0cm95ICYmIHR4dC5kZXN0cm95KCk7XG4gIH0pO1xuICByZXR1cm4gdGhpcztcbn07XG5cbnZhciBleHRlbmQkMSA9IF9kZXJlcV8oJ29iamVjdC1hc3NpZ24nKTtcblxudmFyIHJlZ2xTY2F0dGVyMmQgPSBmdW5jdGlvbiByZWdsU2NhdHRlcjJkKHJlZ2wsIG9wdGlvbnMpIHtcbiAgdmFyIHNjYXR0ZXIkJDEgPSBuZXcgc2NhdHRlcihyZWdsLCBvcHRpb25zKTtcbiAgdmFyIHJlbmRlciA9IHNjYXR0ZXIkJDEucmVuZGVyLmJpbmQoc2NhdHRlciQkMSk7IC8vIGV4cG9zZSBBUElcblxuICBleHRlbmQkMShyZW5kZXIsIHtcbiAgICByZW5kZXI6IHJlbmRlcixcbiAgICB1cGRhdGU6IHNjYXR0ZXIkJDEudXBkYXRlLmJpbmQoc2NhdHRlciQkMSksXG4gICAgZHJhdzogc2NhdHRlciQkMS5kcmF3LmJpbmQoc2NhdHRlciQkMSksXG4gICAgZGVzdHJveTogc2NhdHRlciQkMS5kZXN0cm95LmJpbmQoc2NhdHRlciQkMSksXG4gICAgcmVnbDogc2NhdHRlciQkMS5yZWdsLFxuICAgIGdsOiBzY2F0dGVyJCQxLmdsLFxuICAgIGNhbnZhczogc2NhdHRlciQkMS5nbC5jYW52YXMsXG4gICAgZ3JvdXBzOiBzY2F0dGVyJCQxLmdyb3VwcyxcbiAgICBtYXJrZXJzOiBzY2F0dGVyJCQxLm1hcmtlckNhY2hlLFxuICAgIHBhbGV0dGU6IHNjYXR0ZXIkJDEucGFsZXR0ZVxuICB9KTtcbiAgcmV0dXJuIHJlbmRlcjtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gcmVnbFNjYXR0ZXIyZDtcblxufSx7XCJhcnJheS1ib3VuZHNcIjo2NSxcImNvbG9yLWlkXCI6MTE4LFwiY29sb3Itbm9ybWFsaXplXCI6MTIwLFwiZmxhdHRlbi12ZXJ0ZXgtZGF0YVwiOjIyNyxcImdsc2xpZnlcIjo0MDksXCJpcy1pZXhwbG9yZXJcIjo0MTksXCJvYmplY3QtYXNzaWduXCI6NDU0LFwicGFyc2UtcmVjdFwiOjQ1OSxcInBpY2stYnktYWxpYXNcIjo0NjUsXCJwb2ludC1jbHVzdGVyXCI6NDk5LFwidG8tZmxvYXQzMlwiOjUzOCxcInVwZGF0ZS1kaWZmXCI6NTQ5fV0sNDk4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbmFyZ3VtZW50c1s0XVsxMTFdWzBdLmFwcGx5KGV4cG9ydHMsYXJndW1lbnRzKVxufSx7XCJkdXBcIjoxMTF9XSw0OTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IF9kZXJlcV8oJy4vcXVhZCcpXHJcbn0se1wiLi9xdWFkXCI6NTAwfV0sNTAwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxyXG4gKiBAbW9kdWxlICBwb2ludC1jbHVzdGVyL3F1YWRcclxuICpcclxuICogQnVja2V0IGJhc2VkIHF1YWQgdHJlZSBjbHVzdGVyaW5nXHJcbiAqL1xyXG5cclxuJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgc2VhcmNoID0gX2RlcmVxXygnYmluYXJ5LXNlYXJjaC1ib3VuZHMnKVxyXG52YXIgY2xhbXAgPSBfZGVyZXFfKCdjbGFtcCcpXHJcbnZhciByZWN0ID0gX2RlcmVxXygncGFyc2UtcmVjdCcpXHJcbnZhciBnZXRCb3VuZHMgPSBfZGVyZXFfKCdhcnJheS1ib3VuZHMnKVxyXG52YXIgcGljayA9IF9kZXJlcV8oJ3BpY2stYnktYWxpYXMnKVxyXG52YXIgZGVmaW5lZCA9IF9kZXJlcV8oJ2RlZmluZWQnKVxyXG52YXIgZmxhdHRlbiA9IF9kZXJlcV8oJ2ZsYXR0ZW4tdmVydGV4LWRhdGEnKVxyXG52YXIgaXNPYmogPSBfZGVyZXFfKCdpcy1vYmonKVxyXG52YXIgZHR5cGUgPSBfZGVyZXFfKCdkdHlwZScpXHJcbnZhciBsb2cyID0gX2RlcmVxXygnbWF0aC1sb2cyJylcclxuXHJcbnZhciBNQVhfR1JPVVBfSUQgPSAxMDczNzQxODI0XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNsdXN0ZXIgKHNyY1BvaW50cywgb3B0aW9ucykge1xyXG5cdGlmICghb3B0aW9ucykgeyBvcHRpb25zID0ge30gfVxyXG5cclxuXHRzcmNQb2ludHMgPSBmbGF0dGVuKHNyY1BvaW50cywgJ2Zsb2F0NjQnKVxyXG5cclxuXHRvcHRpb25zID0gcGljayhvcHRpb25zLCB7XHJcblx0XHRib3VuZHM6ICdyYW5nZSBib3VuZHMgZGF0YUJveCBkYXRhYm94JyxcclxuXHRcdG1heERlcHRoOiAnZGVwdGggbWF4RGVwdGggbWF4ZGVwdGggbGV2ZWwgbWF4TGV2ZWwgbWF4bGV2ZWwgbGV2ZWxzJyxcclxuXHRcdGR0eXBlOiAndHlwZSBkdHlwZSBmb3JtYXQgb3V0IGRzdCBvdXRwdXQgZGVzdGluYXRpb24nXHJcblx0XHQvLyBzb3J0OiAnc29ydEJ5IHNvcnRieSBzb3J0JyxcclxuXHRcdC8vIHBpY2s6ICdwaWNrIGxldmVsUG9pbnQnLFxyXG5cdFx0Ly8gbm9kZVNpemU6ICdub2RlIG5vZGVTaXplIG1pbk5vZGVTaXplIG1pblNpemUgc2l6ZSdcclxuXHR9KVxyXG5cclxuXHQvLyBsZXQgbm9kZVNpemUgPSBkZWZpbmVkKG9wdGlvbnMubm9kZVNpemUsIDEpXHJcblx0dmFyIG1heERlcHRoID0gZGVmaW5lZChvcHRpb25zLm1heERlcHRoLCAyNTUpXHJcblx0dmFyIGJvdW5kcyA9IGRlZmluZWQob3B0aW9ucy5ib3VuZHMsIGdldEJvdW5kcyhzcmNQb2ludHMsIDIpKVxyXG5cdGlmIChib3VuZHNbMF0gPT09IGJvdW5kc1syXSkgeyBib3VuZHNbMl0rKyB9XHJcblx0aWYgKGJvdW5kc1sxXSA9PT0gYm91bmRzWzNdKSB7IGJvdW5kc1szXSsrIH1cclxuXHJcblx0dmFyIHBvaW50cyA9IG5vcm1hbGl6ZShzcmNQb2ludHMsIGJvdW5kcylcclxuXHJcblx0Ly8gaW5pdCB2YXJpYWJsZXNcclxuXHR2YXIgbiA9IHNyY1BvaW50cy5sZW5ndGggPj4+IDFcclxuXHR2YXIgaWRzXHJcblx0aWYgKCFvcHRpb25zLmR0eXBlKSB7IG9wdGlvbnMuZHR5cGUgPSAnYXJyYXknIH1cclxuXHJcblx0aWYgKHR5cGVvZiBvcHRpb25zLmR0eXBlID09PSAnc3RyaW5nJykge1xyXG5cdFx0aWRzID0gbmV3IChkdHlwZShvcHRpb25zLmR0eXBlKSkobilcclxuXHR9XHJcblx0ZWxzZSBpZiAob3B0aW9ucy5kdHlwZSkge1xyXG5cdFx0aWRzID0gb3B0aW9ucy5kdHlwZVxyXG5cdFx0aWYgKEFycmF5LmlzQXJyYXkoaWRzKSkgeyBpZHMubGVuZ3RoID0gbiB9XHJcblx0fVxyXG5cdGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKSB7XHJcblx0XHRpZHNbaV0gPSBpXHJcblx0fVxyXG5cclxuXHQvLyByZXByZXNlbnRhdGl2ZSBwb2ludCBpbmRleGVzIGZvciBsZXZlbHNcclxuXHR2YXIgbGV2ZWxzID0gW11cclxuXHJcblx0Ly8gc3RhcnRpbmcgaW5kZXhlcyBvZiBzdWJyYW5nZXMgaW4gc3ViIGxldmVscywgbGV2ZWxzLmxlbmd0aCAqIDRcclxuXHR2YXIgc3VibGV2ZWxzID0gW11cclxuXHJcblx0Ly8gdW5pcXVlIGdyb3VwIGlkcywgc29ydGVkIGluIHotY3VydmUgZmFzaGlvbiB3aXRoaW4gbGV2ZWxzIGJ5IHNoaWZ0aW5nIGJpdHNcclxuXHR2YXIgZ3JvdXBzID0gW11cclxuXHJcblx0Ly8gbGV2ZWwgb2Zmc2V0cyBpbiBgaWRzYFxyXG5cdHZhciBvZmZzZXRzID0gW11cclxuXHJcblxyXG5cdC8vIHNvcnQgcG9pbnRzXHJcblx0c29ydCgwLCAwLCAxLCBpZHMsIDAsIDEpXHJcblxyXG5cclxuXHQvLyByZXR1cm4gcmVvcmRlcmVkIGlkcyB3aXRoIHByb3ZpZGVkIG1ldGhvZHNcclxuXHQvLyBzYXZlIGxldmVsIG9mZnNldHMgaW4gb3V0cHV0IGJ1ZmZlclxyXG5cdHZhciBvZmZzZXQgPSAwXHJcblx0Zm9yICh2YXIgbGV2ZWwgPSAwOyBsZXZlbCA8IGxldmVscy5sZW5ndGg7IGxldmVsKyspIHtcclxuXHRcdHZhciBsZXZlbEl0ZW1zID0gbGV2ZWxzW2xldmVsXVxyXG5cdFx0aWYgKGlkcy5zZXQpIHsgaWRzLnNldChsZXZlbEl0ZW1zLCBvZmZzZXQpIH1cclxuXHRcdGVsc2Uge1xyXG5cdFx0XHRmb3IgKHZhciBpJDEgPSAwLCBsID0gbGV2ZWxJdGVtcy5sZW5ndGg7IGkkMSA8IGw7IGkkMSsrKSB7XHJcblx0XHRcdFx0aWRzW2kkMSArIG9mZnNldF0gPSBsZXZlbEl0ZW1zW2kkMV1cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0dmFyIG5leHRPZmZzZXQgPSBvZmZzZXQgKyBsZXZlbHNbbGV2ZWxdLmxlbmd0aFxyXG5cdFx0b2Zmc2V0c1tsZXZlbF0gPSBbb2Zmc2V0LCBuZXh0T2Zmc2V0XVxyXG5cdFx0b2Zmc2V0ID0gbmV4dE9mZnNldFxyXG5cdH1cclxuXHJcblx0aWRzLnJhbmdlID0gcmFuZ2VcclxuXHJcblx0cmV0dXJuIGlkc1xyXG5cclxuXHJcblxyXG5cdC8vIEZJWE1FOiBpdCBpcyBwb3NzaWJsZSB0byBjcmVhdGUgb25lIHR5cGVkIGFycmF5IGhlYXAgYW5kIHJldXNlIHRoYXQgdG8gYXZvaWQgbWVtb3J5IGJsb3dcclxuXHRmdW5jdGlvbiBzb3J0ICh4LCB5LCBkaWFtLCBpZHMsIGxldmVsLCBncm91cCkge1xyXG5cdFx0aWYgKCFpZHMubGVuZ3RoKSB7IHJldHVybiBudWxsIH1cclxuXHJcblx0XHQvLyBzYXZlIGZpcnN0IHBvaW50IGFzIGxldmVsIHJlcHJlc2VudGF0aXZlXHJcblx0XHR2YXIgbGV2ZWxJdGVtcyA9IGxldmVsc1tsZXZlbF0gfHwgKGxldmVsc1tsZXZlbF0gPSBbXSlcclxuXHRcdHZhciBsZXZlbEdyb3VwcyA9IGdyb3Vwc1tsZXZlbF0gfHwgKGdyb3Vwc1tsZXZlbF0gPSBbXSlcclxuXHRcdHZhciBzdWJsZXZlbCA9IHN1YmxldmVsc1tsZXZlbF0gfHwgKHN1YmxldmVsc1tsZXZlbF0gPSBbXSlcclxuXHRcdHZhciBvZmZzZXQgPSBsZXZlbEl0ZW1zLmxlbmd0aFxyXG5cclxuXHRcdGxldmVsKytcclxuXHJcblx0XHQvLyBtYXggZGVwdGggcmVhY2hlZCAtIHB1dCBhbGwgaXRlbXMgaW50byBhIGZpcnN0IGdyb3VwXHJcblx0XHQvLyBhbHRlcm5hdGl2ZWx5IC0gaWYgZ3JvdXAgaWQgb3ZlcmZsb3cgLSBhdm9pZCBwcm9jZWVkaW5nXHJcblx0XHRpZiAobGV2ZWwgPiBtYXhEZXB0aCB8fCBncm91cCA+IE1BWF9HUk9VUF9JRCkge1xyXG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGlkcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRcdGxldmVsSXRlbXMucHVzaChpZHNbaV0pXHJcblx0XHRcdFx0bGV2ZWxHcm91cHMucHVzaChncm91cClcclxuXHRcdFx0XHRzdWJsZXZlbC5wdXNoKG51bGwsIG51bGwsIG51bGwsIG51bGwpXHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHJldHVybiBvZmZzZXRcclxuXHRcdH1cclxuXHJcblx0XHRsZXZlbEl0ZW1zLnB1c2goaWRzWzBdKVxyXG5cdFx0bGV2ZWxHcm91cHMucHVzaChncm91cClcclxuXHJcblx0XHRpZiAoaWRzLmxlbmd0aCA8PSAxKSB7XHJcblx0XHRcdHN1YmxldmVsLnB1c2gobnVsbCwgbnVsbCwgbnVsbCwgbnVsbClcclxuXHRcdFx0cmV0dXJuIG9mZnNldFxyXG5cdFx0fVxyXG5cclxuXHJcblx0XHR2YXIgZDIgPSBkaWFtICogLjVcclxuXHRcdHZhciBjeCA9IHggKyBkMiwgY3kgPSB5ICsgZDJcclxuXHJcblx0XHQvLyBkaXN0cmlidXRlIHBvaW50cyBieSA0IGJ1Y2tldHNcclxuXHRcdHZhciBsb2xvID0gW10sIGxvaGkgPSBbXSwgaGlsbyA9IFtdLCBoaWhpID0gW11cclxuXHJcblx0XHRmb3IgKHZhciBpJDEgPSAxLCBsID0gaWRzLmxlbmd0aDsgaSQxIDwgbDsgaSQxKyspIHtcclxuXHRcdFx0dmFyIGlkeCA9IGlkc1tpJDFdLFxyXG5cdFx0XHRcdHgkMSA9IHBvaW50c1tpZHggKiAyXSxcclxuXHRcdFx0XHR5JDEgPSBwb2ludHNbaWR4ICogMiArIDFdXHJcblx0XHRcdHgkMSA8IGN4ID8gKHkkMSA8IGN5ID8gbG9sby5wdXNoKGlkeCkgOiBsb2hpLnB1c2goaWR4KSkgOiAoeSQxIDwgY3kgPyBoaWxvLnB1c2goaWR4KSA6IGhpaGkucHVzaChpZHgpKVxyXG5cdFx0fVxyXG5cclxuXHRcdGdyb3VwIDw8PSAyXHJcblxyXG5cdFx0c3VibGV2ZWwucHVzaChcclxuXHRcdFx0c29ydCh4LCB5LCBkMiwgbG9sbywgbGV2ZWwsIGdyb3VwKSxcclxuXHRcdFx0c29ydCh4LCBjeSwgZDIsIGxvaGksIGxldmVsLCBncm91cCArIDEpLFxyXG5cdFx0XHRzb3J0KGN4LCB5LCBkMiwgaGlsbywgbGV2ZWwsIGdyb3VwICsgMiksXHJcblx0XHRcdHNvcnQoY3gsIGN5LCBkMiwgaGloaSwgbGV2ZWwsIGdyb3VwICsgMylcclxuXHRcdClcclxuXHJcblx0XHRyZXR1cm4gb2Zmc2V0XHJcblx0fVxyXG5cclxuXHQvLyBnZXQgYWxsIHBvaW50cyB3aXRoaW4gdGhlIHBhc3NlZCByYW5nZVxyXG5cdGZ1bmN0aW9uIHJhbmdlICgpIHtcblx0XHR2YXIgYXJncyA9IFtdLCBsZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuXHRcdHdoaWxlICggbGVuLS0gKSBhcmdzWyBsZW4gXSA9IGFyZ3VtZW50c1sgbGVuIF07XG5cclxuXHRcdHZhciBvcHRpb25zXHJcblxyXG5cdFx0aWYgKGlzT2JqKGFyZ3NbYXJncy5sZW5ndGggLSAxXSkpIHtcclxuXHRcdFx0dmFyIGFyZyA9IGFyZ3MucG9wKClcclxuXHJcblx0XHRcdC8vIGRldGVjdCBpZiB0aGF0IHdhcyBhIHJlY3Qgb2JqZWN0XHJcblx0XHRcdGlmICghYXJncy5sZW5ndGggJiYgKGFyZy54ICE9IG51bGwgfHwgYXJnLmwgIT0gbnVsbCB8fCBhcmcubGVmdCAhPSBudWxsKSkge1xyXG5cdFx0XHRcdGFyZ3MgPSBbYXJnXVxyXG5cdFx0XHRcdG9wdGlvbnMgPSB7fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRvcHRpb25zID0gcGljayhhcmcsIHtcclxuXHRcdFx0XHRsZXZlbDogJ2xldmVsIG1heExldmVsJyxcclxuXHRcdFx0XHRkOiAnZCBkaWFtIGRpYW1ldGVyIHIgcmFkaXVzIHB4IHB4U2l6ZSBwaXhlbCBwaXhlbFNpemUgbWF4RCBzaXplIG1pblNpemUnLFxyXG5cdFx0XHRcdGxvZDogJ2xvZCBkZXRhaWxzIHJhbmdlcyBvZmZzZXRzJ1xyXG5cdFx0XHR9KVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSB7XHJcblx0XHRcdG9wdGlvbnMgPSB7fVxyXG5cdFx0fVxyXG5cclxuXHRcdGlmICghYXJncy5sZW5ndGgpIHsgYXJncyA9IGJvdW5kcyB9XHJcblxyXG5cdFx0dmFyIGJveCA9IHJlY3QuYXBwbHkoIHZvaWQgMCwgYXJncyApXHJcblxyXG5cdFx0dmFyIHJlZiA9IFtcclxuXHRcdFx0TWF0aC5taW4oYm94LngsIGJveC54ICsgYm94LndpZHRoKSxcclxuXHRcdFx0TWF0aC5taW4oYm94LnksIGJveC55ICsgYm94LmhlaWdodCksXHJcblx0XHRcdE1hdGgubWF4KGJveC54LCBib3gueCArIGJveC53aWR0aCksXHJcblx0XHRcdE1hdGgubWF4KGJveC55LCBib3gueSArIGJveC5oZWlnaHQpXHJcblx0XHRdO1xuXHRcdHZhciBtaW5YID0gcmVmWzBdO1xuXHRcdHZhciBtaW5ZID0gcmVmWzFdO1xuXHRcdHZhciBtYXhYID0gcmVmWzJdO1xuXHRcdHZhciBtYXhZID0gcmVmWzNdO1xyXG5cclxuXHRcdHZhciByZWYkMSA9IG5vcm1hbGl6ZShbbWluWCwgbWluWSwgbWF4WCwgbWF4WV0sIGJvdW5kcyApO1xuXHRcdHZhciBubWluWCA9IHJlZiQxWzBdO1xuXHRcdHZhciBubWluWSA9IHJlZiQxWzFdO1xuXHRcdHZhciBubWF4WCA9IHJlZiQxWzJdO1xuXHRcdHZhciBubWF4WSA9IHJlZiQxWzNdO1xyXG5cclxuXHRcdHZhciBtYXhMZXZlbCA9IGRlZmluZWQob3B0aW9ucy5sZXZlbCwgbGV2ZWxzLmxlbmd0aClcclxuXHJcblx0XHQvLyBsaW1pdCBtYXhMZXZlbCBieSBweCBzaXplXHJcblx0XHRpZiAob3B0aW9ucy5kICE9IG51bGwpIHtcclxuXHRcdFx0dmFyIGRcclxuXHRcdFx0aWYgKHR5cGVvZiBvcHRpb25zLmQgPT09ICdudW1iZXInKSB7IGQgPSBbb3B0aW9ucy5kLCBvcHRpb25zLmRdIH1cclxuXHRcdFx0ZWxzZSBpZiAob3B0aW9ucy5kLmxlbmd0aCkgeyBkID0gb3B0aW9ucy5kIH1cclxuXHJcblx0XHRcdG1heExldmVsID0gTWF0aC5taW4oXHJcblx0XHRcdFx0TWF0aC5tYXgoXHJcblx0XHRcdFx0XHRNYXRoLmNlaWwoLWxvZzIoTWF0aC5hYnMoZFswXSkgLyAoYm91bmRzWzJdIC0gYm91bmRzWzBdKSkpLFxyXG5cdFx0XHRcdFx0TWF0aC5jZWlsKC1sb2cyKE1hdGguYWJzKGRbMV0pIC8gKGJvdW5kc1szXSAtIGJvdW5kc1sxXSkpKVxyXG5cdFx0XHRcdCksXHJcblx0XHRcdFx0bWF4TGV2ZWxcclxuXHRcdFx0KVxyXG5cdFx0fVxyXG5cdFx0bWF4TGV2ZWwgPSBNYXRoLm1pbihtYXhMZXZlbCwgbGV2ZWxzLmxlbmd0aClcclxuXHJcblx0XHQvLyByZXR1cm4gbGV2ZWxzIG9mIGRldGFpbHNcclxuXHRcdGlmIChvcHRpb25zLmxvZCkge1xyXG5cdFx0XHRyZXR1cm4gbG9kKG5taW5YLCBubWluWSwgbm1heFgsIG5tYXhZLCBtYXhMZXZlbClcclxuXHRcdH1cclxuXHJcblxyXG5cclxuXHRcdC8vIGRvIHNlbGVjdGlvbiBpZHNcclxuXHRcdHZhciBzZWxlY3Rpb24gPSBbXVxyXG5cclxuXHRcdC8vIEZJWE1FOiBwcm9iYWJseSB3ZSBjYW4gZG8gTE9EIGhlcmUgYmVmb3JlaGVhZFxyXG5cdFx0c2VsZWN0KCAwLCAwLCAxLCAwLCAwLCAxKVxyXG5cclxuXHRcdGZ1bmN0aW9uIHNlbGVjdCAoIGxveCwgbG95LCBkLCBsZXZlbCwgZnJvbSwgdG8gKSB7XHJcblx0XHRcdGlmIChmcm9tID09PSBudWxsIHx8IHRvID09PSBudWxsKSB7IHJldHVybiB9XHJcblxyXG5cdFx0XHR2YXIgaGl4ID0gbG94ICsgZFxyXG5cdFx0XHR2YXIgaGl5ID0gbG95ICsgZFxyXG5cclxuXHRcdFx0Ly8gaWYgYm94IGRvZXMgbm90IGludGVyc2VjdCBsZXZlbCAtIGlnbm9yZVxyXG5cdFx0XHRpZiAoIG5taW5YID4gaGl4IHx8IG5taW5ZID4gaGl5IHx8IG5tYXhYIDwgbG94IHx8IG5tYXhZIDwgbG95ICkgeyByZXR1cm4gfVxyXG5cdFx0XHRpZiAoIGxldmVsID49IG1heExldmVsICkgeyByZXR1cm4gfVxyXG5cdFx0XHRpZiAoIGZyb20gPT09IHRvICkgeyByZXR1cm4gfVxyXG5cclxuXHRcdFx0Ly8gaWYgcG9pbnRzIGZhbGwgaW50byBib3ggcmFuZ2UgLSB0YWtlIGl0XHJcblx0XHRcdHZhciBsZXZlbEl0ZW1zID0gbGV2ZWxzW2xldmVsXVxyXG5cclxuXHRcdFx0aWYgKHRvID09PSB1bmRlZmluZWQpIHsgdG8gPSBsZXZlbEl0ZW1zLmxlbmd0aCB9XHJcblxyXG5cdFx0XHRmb3IgKHZhciBpID0gZnJvbTsgaSA8IHRvOyBpKyspIHtcclxuXHRcdFx0XHR2YXIgaWQgPSBsZXZlbEl0ZW1zW2ldXHJcblxyXG5cdFx0XHRcdHZhciBweCA9IHNyY1BvaW50c1sgaWQgKiAyIF1cclxuXHRcdFx0XHR2YXIgcHkgPSBzcmNQb2ludHNbIGlkICogMiArIDEgXVxyXG5cclxuXHRcdFx0XHRpZiAoIHB4ID49IG1pblggJiYgcHggPD0gbWF4WCAmJiBweSA+PSBtaW5ZICYmIHB5IDw9IG1heFkgKSB7c2VsZWN0aW9uLnB1c2goaWQpXHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyBmb3IgZXZlcnkgc3Vic2VjdGlvbiBkbyBzZWxlY3RcclxuXHRcdFx0dmFyIG9mZnNldHMgPSBzdWJsZXZlbHNbIGxldmVsIF1cclxuXHRcdFx0dmFyIG9mZjAgPSBvZmZzZXRzWyBmcm9tICogNCArIDAgXVxyXG5cdFx0XHR2YXIgb2ZmMSA9IG9mZnNldHNbIGZyb20gKiA0ICsgMSBdXHJcblx0XHRcdHZhciBvZmYyID0gb2Zmc2V0c1sgZnJvbSAqIDQgKyAyIF1cclxuXHRcdFx0dmFyIG9mZjMgPSBvZmZzZXRzWyBmcm9tICogNCArIDMgXVxyXG5cdFx0XHR2YXIgZW5kID0gbmV4dE9mZnNldChvZmZzZXRzLCBmcm9tICsgMSlcclxuXHJcblx0XHRcdHZhciBkMiA9IGQgKiAuNVxyXG5cdFx0XHR2YXIgbmV4dExldmVsID0gbGV2ZWwgKyAxXHJcblx0XHRcdHNlbGVjdCggbG94LCBsb3ksIGQyLCBuZXh0TGV2ZWwsIG9mZjAsIG9mZjEgfHwgb2ZmMiB8fCBvZmYzIHx8IGVuZClcclxuXHRcdFx0c2VsZWN0KCBsb3gsIGxveSArIGQyLCBkMiwgbmV4dExldmVsLCBvZmYxLCBvZmYyIHx8IG9mZjMgfHwgZW5kKVxyXG5cdFx0XHRzZWxlY3QoIGxveCArIGQyLCBsb3ksIGQyLCBuZXh0TGV2ZWwsIG9mZjIsIG9mZjMgfHwgZW5kKVxyXG5cdFx0XHRzZWxlY3QoIGxveCArIGQyLCBsb3kgKyBkMiwgZDIsIG5leHRMZXZlbCwgb2ZmMywgZW5kKVxyXG5cdFx0fVxyXG5cclxuXHRcdGZ1bmN0aW9uIG5leHRPZmZzZXQob2Zmc2V0cywgZnJvbSkge1xyXG5cdFx0XHR2YXIgb2Zmc2V0ID0gbnVsbCwgaSA9IDBcclxuXHRcdFx0d2hpbGUob2Zmc2V0ID09PSBudWxsKSB7XHJcblx0XHRcdFx0b2Zmc2V0ID0gb2Zmc2V0c1sgZnJvbSAqIDQgKyBpIF1cclxuXHRcdFx0XHRpKytcclxuXHRcdFx0XHRpZiAoaSA+IG9mZnNldHMubGVuZ3RoKSB7IHJldHVybiBudWxsIH1cclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gb2Zmc2V0XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHNlbGVjdGlvblxyXG5cdH1cclxuXHJcblx0Ly8gZ2V0IHJhbmdlIG9mZnNldHMgd2l0aGluIGxldmVscyB0byByZW5kZXIgbG9kcyBhcHByb3ByaWF0ZSBmb3Igem9vbSBsZXZlbFxyXG5cdC8vIFRPRE86IGl0IGlzIHBvc3NpYmxlIHRvIHN0b3JlIG1pblNpemUgb2YgYSBwb2ludCB0byBvcHRpbWl6ZSBuZWVkZSBsZXZlbCBjYWxjXHJcblx0ZnVuY3Rpb24gbG9kIChsb3gsIGxveSwgaGl4LCBoaXksIG1heExldmVsKSB7XHJcblx0XHR2YXIgcmFuZ2VzID0gW11cclxuXHJcblx0XHRmb3IgKHZhciBsZXZlbCA9IDA7IGxldmVsIDwgbWF4TGV2ZWw7IGxldmVsKyspIHtcclxuXHRcdFx0dmFyIGxldmVsR3JvdXBzID0gZ3JvdXBzW2xldmVsXVxyXG5cdFx0XHR2YXIgZnJvbSA9IG9mZnNldHNbbGV2ZWxdWzBdXHJcblxyXG5cdFx0XHR2YXIgbGV2ZWxHcm91cFN0YXJ0ID0gZ3JvdXAobG94LCBsb3ksIGxldmVsKVxyXG5cdFx0XHR2YXIgbGV2ZWxHcm91cEVuZCA9IGdyb3VwKGhpeCwgaGl5LCBsZXZlbClcclxuXHJcblx0XHRcdC8vIEZJWE1FOiB1dGlsaXplIHN1YmxldmVscyB0byBzcGVlZCB1cCBzZWFyY2ggcmFuZ2UgaGVyZVxyXG5cdFx0XHR2YXIgc3RhcnRPZmZzZXQgPSBzZWFyY2guZ2UobGV2ZWxHcm91cHMsIGxldmVsR3JvdXBTdGFydClcclxuXHRcdFx0dmFyIGVuZE9mZnNldCA9IHNlYXJjaC5ndChsZXZlbEdyb3VwcywgbGV2ZWxHcm91cEVuZCwgc3RhcnRPZmZzZXQsIGxldmVsR3JvdXBzLmxlbmd0aCAtIDEpXHJcblxyXG5cdFx0XHRyYW5nZXNbbGV2ZWxdID0gW3N0YXJ0T2Zmc2V0ICsgZnJvbSwgZW5kT2Zmc2V0ICsgZnJvbV1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gcmFuZ2VzXHJcblx0fVxyXG5cclxuXHQvLyBnZXQgZ3JvdXAgaWQgY2xvc2VzdCB0byB0aGUgeCx5IGNvb3JkaW5hdGUsIGNvcnJlc3BvbmRpbmcgdG8gYSBsZXZlbFxyXG5cdGZ1bmN0aW9uIGdyb3VwICh4LCB5LCBsZXZlbCkge1xyXG5cdFx0dmFyIGdyb3VwID0gMVxyXG5cclxuXHRcdHZhciBjeCA9IC41LCBjeSA9IC41XHJcblx0XHR2YXIgZGlhbSA9IC41XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBsZXZlbDsgaSsrKSB7XHJcblx0XHRcdGdyb3VwIDw8PSAyXHJcblxyXG5cdFx0XHRncm91cCArPSB4IDwgY3ggPyAoeSA8IGN5ID8gMCA6IDEpIDogKHkgPCBjeSA/IDIgOiAzKVxyXG5cclxuXHRcdFx0ZGlhbSAqPSAuNVxyXG5cclxuXHRcdFx0Y3ggKz0geCA8IGN4ID8gLWRpYW0gOiBkaWFtXHJcblx0XHRcdGN5ICs9IHkgPCBjeSA/IC1kaWFtIDogZGlhbVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBncm91cFxyXG5cdH1cclxufVxyXG5cclxuXHJcbi8vIG5vcm1hbGl6ZSBwb2ludHMgYnkgYm91bmRzXHJcbmZ1bmN0aW9uIG5vcm1hbGl6ZSAocHRzLCBib3VuZHMpIHtcclxuXHR2YXIgbG94ID0gYm91bmRzWzBdO1xuXHR2YXIgbG95ID0gYm91bmRzWzFdO1xuXHR2YXIgaGl4ID0gYm91bmRzWzJdO1xuXHR2YXIgaGl5ID0gYm91bmRzWzNdO1xyXG5cdHZhciBzY2FsZVggPSAxLjAgLyAoaGl4IC0gbG94KVxyXG5cdHZhciBzY2FsZVkgPSAxLjAgLyAoaGl5IC0gbG95KVxyXG5cdHZhciByZXN1bHQgPSBuZXcgQXJyYXkocHRzLmxlbmd0aClcclxuXHJcblx0Zm9yICh2YXIgaSA9IDAsIG4gPSBwdHMubGVuZ3RoIC8gMjsgaSA8IG47IGkrKykge1xyXG5cdFx0cmVzdWx0WzIqaV0gPSBjbGFtcCgocHRzWzIqaV0gLSBsb3gpICogc2NhbGVYLCAwLCAxKVxyXG5cdFx0cmVzdWx0WzIqaSsxXSA9IGNsYW1wKChwdHNbMippKzFdIC0gbG95KSAqIHNjYWxlWSwgMCwgMSlcclxuXHR9XHJcblxyXG5cdHJldHVybiByZXN1bHRcclxufVxyXG59LHtcImFycmF5LWJvdW5kc1wiOjY1LFwiYmluYXJ5LXNlYXJjaC1ib3VuZHNcIjo0OTgsXCJjbGFtcFwiOjExNSxcImRlZmluZWRcIjoxNjQsXCJkdHlwZVwiOjE2OSxcImZsYXR0ZW4tdmVydGV4LWRhdGFcIjoyMjcsXCJpcy1vYmpcIjo0MjEsXCJtYXRoLWxvZzJcIjo0MzIsXCJwYXJzZS1yZWN0XCI6NDU5LFwicGljay1ieS1hbGlhc1wiOjQ2NX1dLDUwMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxuXG52YXIgY3JlYXRlU2NhdHRlciA9IF9kZXJlcV8oJ3JlZ2wtc2NhdHRlcjJkJylcbnZhciBwaWNrID0gX2RlcmVxXygncGljay1ieS1hbGlhcycpXG52YXIgZ2V0Qm91bmRzID0gX2RlcmVxXygnYXJyYXktYm91bmRzJylcbnZhciByYWYgPSBfZGVyZXFfKCdyYWYnKVxudmFyIGFyclJhbmdlID0gX2RlcmVxXygnYXJyYXktcmFuZ2UnKVxudmFyIHJlY3QgPSBfZGVyZXFfKCdwYXJzZS1yZWN0JylcbnZhciBmbGF0dGVuID0gX2RlcmVxXygnZmxhdHRlbi12ZXJ0ZXgtZGF0YScpXG5cblxubW9kdWxlLmV4cG9ydHMgPSBTUExPTVxuXG5cbi8vIEBjb25zdHJ1Y3RvclxuZnVuY3Rpb24gU1BMT00gKHJlZ2wsIG9wdGlvbnMpIHtcblx0aWYgKCEodGhpcyBpbnN0YW5jZW9mIFNQTE9NKSkgeyByZXR1cm4gbmV3IFNQTE9NKHJlZ2wsIG9wdGlvbnMpIH1cblxuXHQvLyByZW5kZXIgcGFzc2VzXG5cdHRoaXMudHJhY2VzID0gW11cblxuXHQvLyBwYXNzZXMgZm9yIHNjYXR0ZXIsIGNvbWJpbmVkIGFjcm9zcyB0cmFjZXNcblx0dGhpcy5wYXNzZXMgPSB7fVxuXG5cdHRoaXMucmVnbCA9IHJlZ2xcblxuXHQvLyBtYWluIHNjYXR0ZXIgZHJhd2luZyBpbnN0YW5jZVxuXHR0aGlzLnNjYXR0ZXIgPSBjcmVhdGVTY2F0dGVyKHJlZ2wpXG5cblx0dGhpcy5jYW52YXMgPSB0aGlzLnNjYXR0ZXIuY2FudmFzXG59XG5cblxuLy8gdXBkYXRlICYgZHJhdyBwYXNzZXMgb25jZSBwZXIgZnJhbWVcblNQTE9NLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciB0aGlzJDEgPSB0aGlzO1xuXHR2YXIgcmVmO1xuXG5cdHZhciBhcmdzID0gW10sIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG5cdHdoaWxlICggbGVuLS0gKSBhcmdzWyBsZW4gXSA9IGFyZ3VtZW50c1sgbGVuIF07XG5cdGlmIChhcmdzLmxlbmd0aCkge1xuXHRcdChyZWYgPSB0aGlzKS51cGRhdGUuYXBwbHkocmVmLCBhcmdzKVxuXHR9XG5cblx0aWYgKHRoaXMucmVnbC5hdHRyaWJ1dGVzLnByZXNlcnZlRHJhd2luZ0J1ZmZlcikgeyByZXR1cm4gdGhpcy5kcmF3KCkgfVxuXG5cdC8vIG1ha2Ugc3VyZSBkcmF3IGlzIG5vdCBjYWxsZWQgbW9yZSBvZnRlbiB0aGFuIG9uY2UgYSBmcmFtZVxuXHRpZiAodGhpcy5kaXJ0eSkge1xuXHRcdGlmICh0aGlzLnBsYW5uZWQgPT0gbnVsbCkge1xuXHRcdFx0dGhpcy5wbGFubmVkID0gcmFmKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0dGhpcyQxLmRyYXcoKVxuXHRcdFx0XHR0aGlzJDEuZGlydHkgPSB0cnVlXG5cdFx0XHRcdHRoaXMkMS5wbGFubmVkID0gbnVsbFxuXHRcdFx0fSlcblx0XHR9XG5cdH1cblx0ZWxzZSB7XG5cdFx0dGhpcy5kcmF3KClcblx0XHR0aGlzLmRpcnR5ID0gdHJ1ZVxuXHRcdHJhZihmdW5jdGlvbiAoKSB7XG5cdFx0XHR0aGlzJDEuZGlydHkgPSBmYWxzZVxuXHRcdH0pXG5cdH1cblxuXHRyZXR1cm4gdGhpc1xufVxuXG5cbi8vIHVwZGF0ZSBwYXNzZXNcblNQTE9NLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciB0aGlzJDEgPSB0aGlzO1xuXHR2YXIgcmVmO1xuXG5cdHZhciBhcmdzID0gW10sIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG5cdHdoaWxlICggbGVuLS0gKSBhcmdzWyBsZW4gXSA9IGFyZ3VtZW50c1sgbGVuIF07XG5cdGlmICghYXJncy5sZW5ndGgpIHsgcmV0dXJuIH1cblxuXHRmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcblx0XHR0aGlzJDEudXBkYXRlSXRlbShpLCBhcmdzW2ldKVxuXHR9XG5cblx0Ly8gcmVtb3ZlIG51bGxlZCBwYXNzZXNcblx0dGhpcy50cmFjZXMgPSB0aGlzLnRyYWNlcy5maWx0ZXIoQm9vbGVhbilcblxuXHQvLyBGSVhNRTogdXBkYXRlIHBhc3NlcyBpbmRlcGVuZGVudGx5XG5cdHZhciBwYXNzZXMgPSBbXVxuXHR2YXIgb2Zmc2V0ID0gMFxuXHRmb3IgKHZhciBpJDEgPSAwOyBpJDEgPCB0aGlzLnRyYWNlcy5sZW5ndGg7IGkkMSsrKSB7XG5cdFx0dmFyIHRyYWNlID0gdGhpcyQxLnRyYWNlc1tpJDFdXG5cdFx0dmFyIHRyYWNlUGFzc2VzID0gdGhpcyQxLnRyYWNlc1tpJDFdLnBhc3Nlc1xuXHRcdGZvciAodmFyIGogPSAwOyBqIDwgdHJhY2VQYXNzZXMubGVuZ3RoOyBqKyspIHtcblx0XHRcdHBhc3Nlcy5wdXNoKHRoaXMkMS5wYXNzZXNbdHJhY2VQYXNzZXNbal1dKVxuXHRcdH1cblx0XHQvLyBzYXZlIG9mZnNldCBvZiBwYXNzZXNcblx0XHR0cmFjZS5wYXNzT2Zmc2V0ID0gb2Zmc2V0XG5cdFx0b2Zmc2V0ICs9IHRyYWNlLnBhc3Nlcy5sZW5ndGhcblx0fVxuXG5cdChyZWYgPSB0aGlzLnNjYXR0ZXIpLnVwZGF0ZS5hcHBseShyZWYsIHBhc3NlcylcblxuXHRyZXR1cm4gdGhpc1xufVxuXG5cbi8vIHVwZGF0ZSB0cmFjZSBieSBpbmRleCwgbm90IHN1cHBvc2VkIHRvIGJlIGNhbGxlZCBkaXJlY3RseVxuU1BMT00ucHJvdG90eXBlLnVwZGF0ZUl0ZW0gPSBmdW5jdGlvbiAoaSwgb3B0aW9ucykge1xuXHR2YXIgdGhpcyQxID0gdGhpcztcblxuXHR2YXIgcmVmID0gdGhpcztcblx0dmFyIHJlZ2wgPSByZWYucmVnbDtcblxuXHQvLyByZW1vdmUgcGFzcyBpZiBudWxsXG5cdGlmIChvcHRpb25zID09PSBudWxsKSB7XG5cdFx0dGhpcy50cmFjZXNbaV0gPSBudWxsXG5cdFx0cmV0dXJuIHRoaXNcblx0fVxuXG5cdGlmICghb3B0aW9ucykgeyByZXR1cm4gdGhpcyB9XG5cblx0dmFyIG8gPSBwaWNrKG9wdGlvbnMsIHtcblx0XHRkYXRhOiAnZGF0YSBpdGVtcyBjb2x1bW5zIHJvd3MgdmFsdWVzIGRpbWVuc2lvbnMgc2FtcGxlcyB4Jyxcblx0XHRzbmFwOiAnc25hcCBjbHVzdGVyJyxcblx0XHRzaXplOiAnc2l6ZXMgc2l6ZSByYWRpdXMnLFxuXHRcdGNvbG9yOiAnY29sb3JzIGNvbG9yIGZpbGwgZmlsbC1jb2xvciBmaWxsQ29sb3InLFxuXHRcdG9wYWNpdHk6ICdvcGFjaXR5IGFscGhhIHRyYW5zcGFyZW5jeSBvcGFxdWUnLFxuXHRcdGJvcmRlclNpemU6ICdib3JkZXJTaXplcyBib3JkZXJTaXplIGJvcmRlci1zaXplIGJvcmRlcnNpemUgYm9yZGVyV2lkdGggYm9yZGVyV2lkdGhzIGJvcmRlci13aWR0aCBib3JkZXJ3aWR0aCBzdHJva2Utd2lkdGggc3Ryb2tlV2lkdGggc3Ryb2tld2lkdGggb3V0bGluZScsXG5cdFx0Ym9yZGVyQ29sb3I6ICdib3JkZXJDb2xvcnMgYm9yZGVyQ29sb3IgYm9yZGVyY29sb3Igc3Ryb2tlIHN0cm9rZS1jb2xvciBzdHJva2VDb2xvcicsXG5cdFx0bWFya2VyOiAnbWFya2VycyBtYXJrZXIgc2hhcGUnLFxuXHRcdHJhbmdlOiAncmFuZ2UgcmFuZ2VzIGRhdGFib3ggZGF0YUJveCcsXG5cdFx0dmlld3BvcnQ6ICd2aWV3cG9ydCB2aWV3Qm94IHZpZXdib3gnLFxuXHRcdGRvbWFpbjogJ2RvbWFpbiBkb21haW5zIGFyZWEgYXJlYXMnLFxuXHRcdHBhZGRpbmc6ICdwYWQgcGFkZGluZyBwYWRkaW5ncyBwYWRzIG1hcmdpbiBtYXJnaW5zJyxcblx0XHR0cmFuc3Bvc2U6ICd0cmFuc3Bvc2UgdHJhbnNwb3NlZCcsXG5cdFx0ZGlhZ29uYWw6ICdkaWFnb25hbCBkaWFnIHNob3dEaWFnb25hbCcsXG5cdFx0dXBwZXI6ICd1cHBlciB1cCB0b3AgdXBwZXJoYWxmIHVwcGVySGFsZiBzaG93dXBwZXJoYWxmIHNob3dVcHBlciBzaG93VXBwZXJIYWxmJyxcblx0XHRsb3dlcjogJ2xvd2VyIGxvdyBib3R0b20gbG93ZXJoYWxmIGxvd2VySGFsZiBzaG93bG93ZXJoYWxmIHNob3dMb3dlckhhbGYgc2hvd0xvd2VyJ1xuXHR9KVxuXG5cdC8vIHdlIHByb3ZpZGUgcmVnbCBidWZmZXIgcGVyLXRyYWNlLCBzaW5jZSB0cmFjZSBkYXRhIGNhbiBiZSBjaGFuZ2VkXG5cdHZhciB0cmFjZSA9ICh0aGlzLnRyYWNlc1tpXSB8fCAodGhpcy50cmFjZXNbaV0gPSB7XG5cdFx0aWQ6IGksXG5cdFx0YnVmZmVyOiByZWdsLmJ1ZmZlcih7XG5cdFx0XHR1c2FnZTogJ2R5bmFtaWMnLFxuXHRcdFx0dHlwZTogJ2Zsb2F0Jyxcblx0XHRcdGRhdGE6IG5ldyBVaW50OEFycmF5KClcblx0XHR9KSxcblx0XHRjb2xvcjogJ2JsYWNrJyxcblx0XHRtYXJrZXI6IG51bGwsXG5cdFx0c2l6ZTogMTIsXG5cdFx0Ym9yZGVyQ29sb3I6ICd0cmFuc3BhcmVudCcsXG5cdFx0Ym9yZGVyU2l6ZTogMSxcblx0XHR2aWV3cG9ydDogIHJlY3QoW3JlZ2wuX2dsLmRyYXdpbmdCdWZmZXJXaWR0aCwgcmVnbC5fZ2wuZHJhd2luZ0J1ZmZlckhlaWdodF0pLFxuXHRcdHBhZGRpbmc6IFswLCAwLCAwLCAwXSxcblx0XHRvcGFjaXR5OiAxLFxuXHRcdGRpYWdvbmFsOiB0cnVlLFxuXHRcdHVwcGVyOiB0cnVlLFxuXHRcdGxvd2VyOiB0cnVlXG5cdH0pKVxuXG5cblx0Ly8gc2F2ZSBzdHlsZXNcblx0aWYgKG8uY29sb3IgIT0gbnVsbCkge1xuXHRcdHRyYWNlLmNvbG9yID0gby5jb2xvclxuXHR9XG5cdGlmIChvLnNpemUgIT0gbnVsbCkge1xuXHRcdHRyYWNlLnNpemUgPSBvLnNpemVcblx0fVxuXHRpZiAoby5tYXJrZXIgIT0gbnVsbCkge1xuXHRcdHRyYWNlLm1hcmtlciA9IG8ubWFya2VyXG5cdH1cblx0aWYgKG8uYm9yZGVyQ29sb3IgIT0gbnVsbCkge1xuXHRcdHRyYWNlLmJvcmRlckNvbG9yID0gby5ib3JkZXJDb2xvclxuXHR9XG5cdGlmIChvLmJvcmRlclNpemUgIT0gbnVsbCkge1xuXHRcdHRyYWNlLmJvcmRlclNpemUgPSBvLmJvcmRlclNpemVcblx0fVxuXHRpZiAoby5vcGFjaXR5ICE9IG51bGwpIHtcblx0XHR0cmFjZS5vcGFjaXR5ID0gby5vcGFjaXR5XG5cdH1cblx0aWYgKG8udmlld3BvcnQpIHtcblx0XHR0cmFjZS52aWV3cG9ydCA9IHJlY3Qoby52aWV3cG9ydClcblx0fVxuXHRpZiAoby5kaWFnb25hbCAhPSBudWxsKSB7IHRyYWNlLmRpYWdvbmFsID0gby5kaWFnb25hbCB9XG5cdGlmIChvLnVwcGVyICE9IG51bGwpIHsgdHJhY2UudXBwZXIgPSBvLnVwcGVyIH1cblx0aWYgKG8ubG93ZXIgIT0gbnVsbCkgeyB0cmFjZS5sb3dlciA9IG8ubG93ZXIgfVxuXG5cdC8vIHB1dCBmbGF0dGVuZWQgZGF0YSBpbnRvIGJ1ZmZlclxuXHRpZiAoby5kYXRhKSB7XG5cdFx0dHJhY2UuYnVmZmVyKGZsYXR0ZW4oby5kYXRhKSlcblx0XHR0cmFjZS5jb2x1bW5zID0gby5kYXRhLmxlbmd0aFxuXHRcdHRyYWNlLmNvdW50ID0gby5kYXRhWzBdLmxlbmd0aFxuXG5cdFx0Ly8gZGV0ZWN0IGJvdW5kcyBwZXItY29sdW1uXG5cdFx0dHJhY2UuYm91bmRzID0gW11cblxuXHRcdGZvciAodmFyIGkkMSA9IDA7IGkkMSA8IHRyYWNlLmNvbHVtbnM7IGkkMSsrKSB7XG5cdFx0XHR0cmFjZS5ib3VuZHNbaSQxXSA9IGdldEJvdW5kcyhvLmRhdGFbaSQxXSwgMSlcblx0XHR9XG5cdH1cblxuXHQvLyBhZGQgcHJvcGVyIHJhbmdlIHVwZGF0aW5nIG1hcmtlcnNcblx0dmFyIG11bHRpcmFuZ2Vcblx0aWYgKG8ucmFuZ2UpIHtcblx0XHR0cmFjZS5yYW5nZSA9IG8ucmFuZ2Vcblx0XHRtdWx0aXJhbmdlID0gdHJhY2UucmFuZ2UgJiYgdHlwZW9mIHRyYWNlLnJhbmdlWzBdICE9PSAnbnVtYmVyJ1xuXHR9XG5cblx0aWYgKG8uZG9tYWluKSB7XG5cdFx0dHJhY2UuZG9tYWluID0gby5kb21haW5cblx0fVxuXHR2YXIgbXVsdGlwYWRkaW5nID0gZmFsc2Vcblx0aWYgKG8ucGFkZGluZyAhPSBudWxsKSB7XG5cdFx0Ly8gbXVsdGlwbGUgcGFkZGluZ3Ncblx0XHRpZiAoQXJyYXkuaXNBcnJheShvLnBhZGRpbmcpICYmIG8ucGFkZGluZy5sZW5ndGggPT09IHRyYWNlLmNvbHVtbnMgJiYgdHlwZW9mIG8ucGFkZGluZ1tvLnBhZGRpbmcubGVuZ3RoIC0gMV0gPT09ICdudW1iZXInKSB7XG5cdFx0XHR0cmFjZS5wYWRkaW5nID0gby5wYWRkaW5nLm1hcChnZXRQYWQpXG5cdFx0XHRtdWx0aXBhZGRpbmcgPSB0cnVlXG5cdFx0fVxuXHRcdC8vIHNpbmdsZSBwYWRkaW5nXG5cdFx0ZWxzZSB7XG5cdFx0XHR0cmFjZS5wYWRkaW5nID0gZ2V0UGFkKG8ucGFkZGluZylcblx0XHR9XG5cdH1cblxuXHQvLyBjcmVhdGUgcGFzc2VzXG5cdHZhciBtID0gdHJhY2UuY29sdW1uc1xuXHR2YXIgbiA9IHRyYWNlLmNvdW50XG5cblx0dmFyIHcgPSB0cmFjZS52aWV3cG9ydC53aWR0aFxuXHR2YXIgaCA9IHRyYWNlLnZpZXdwb3J0LmhlaWdodFxuXHR2YXIgbGVmdCA9IHRyYWNlLnZpZXdwb3J0Lnhcblx0dmFyIHRvcCA9IHRyYWNlLnZpZXdwb3J0Lnlcblx0dmFyIGl3ID0gdyAvIG1cblx0dmFyIGloID0gaCAvIG1cblxuXHR0cmFjZS5wYXNzZXMgPSBbXVxuXG5cdGZvciAodmFyIGkkMiA9IDA7IGkkMiA8IG07IGkkMisrKSB7XG5cdFx0Zm9yICh2YXIgaiA9IDA7IGogPCBtOyBqKyspIHtcblx0XHRcdGlmICghdHJhY2UuZGlhZ29uYWwgJiYgaiA9PT0gaSQyKSB7IGNvbnRpbnVlIH1cblx0XHRcdGlmICghdHJhY2UudXBwZXIgJiYgaSQyID4gaikgeyBjb250aW51ZSB9XG5cdFx0XHRpZiAoIXRyYWNlLmxvd2VyICYmIGkkMiA8IGopIHsgY29udGludWUgfVxuXG5cdFx0XHR2YXIga2V5ID0gcGFzc0lkKHRyYWNlLmlkLCBpJDIsIGopXG5cblx0XHRcdHZhciBwYXNzID0gdGhpcyQxLnBhc3Nlc1trZXldIHx8ICh0aGlzJDEucGFzc2VzW2tleV0gPSB7fSlcblxuXHRcdFx0aWYgKG8uZGF0YSkge1xuXHRcdFx0XHRpZiAoby50cmFuc3Bvc2UpIHtcblx0XHRcdFx0XHRwYXNzLnBvc2l0aW9ucyA9IHtcblx0XHRcdFx0XHRcdHg6IHtidWZmZXI6IHRyYWNlLmJ1ZmZlciwgb2Zmc2V0OiBqLCBjb3VudDogbiwgc3RyaWRlOiBtfSxcblx0XHRcdFx0XHRcdHk6IHtidWZmZXI6IHRyYWNlLmJ1ZmZlciwgb2Zmc2V0OiBpJDIsIGNvdW50OiBuLCBzdHJpZGU6IG19XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdHBhc3MucG9zaXRpb25zID0ge1xuXHRcdFx0XHRcdFx0eDoge2J1ZmZlcjogdHJhY2UuYnVmZmVyLCBvZmZzZXQ6IGogKiBuLCBjb3VudDogbn0sXG5cdFx0XHRcdFx0XHR5OiB7YnVmZmVyOiB0cmFjZS5idWZmZXIsIG9mZnNldDogaSQyICogbiwgY291bnQ6IG59XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0cGFzcy5ib3VuZHMgPSBnZXRCb3godHJhY2UuYm91bmRzLCBpJDIsIGopXG5cdFx0XHR9XG5cblx0XHRcdGlmIChvLmRvbWFpbiB8fCBvLnZpZXdwb3J0IHx8IG8uZGF0YSkge1xuXHRcdFx0XHR2YXIgcGFkID0gbXVsdGlwYWRkaW5nID8gZ2V0Qm94KHRyYWNlLnBhZGRpbmcsIGkkMiwgaikgOiB0cmFjZS5wYWRkaW5nXG5cdFx0XHRcdGlmICh0cmFjZS5kb21haW4pIHtcblx0XHRcdFx0XHR2YXIgcmVmJDEgPSBnZXRCb3godHJhY2UuZG9tYWluLCBpJDIsIGopO1xuXHRcdFx0XHRcdHZhciBsb3ggPSByZWYkMVswXTtcblx0XHRcdFx0XHR2YXIgbG95ID0gcmVmJDFbMV07XG5cdFx0XHRcdFx0dmFyIGhpeCA9IHJlZiQxWzJdO1xuXHRcdFx0XHRcdHZhciBoaXkgPSByZWYkMVszXTtcblxuXHRcdFx0XHRcdHBhc3Mudmlld3BvcnQgPSBbXG5cdFx0XHRcdFx0XHRsZWZ0ICsgbG94ICogdyArIHBhZFswXSxcblx0XHRcdFx0XHRcdHRvcCArIGxveSAqIGggKyBwYWRbMV0sXG5cdFx0XHRcdFx0XHRsZWZ0ICsgaGl4ICogdyAtIHBhZFsyXSxcblx0XHRcdFx0XHRcdHRvcCArIGhpeSAqIGggLSBwYWRbM11cblx0XHRcdFx0XHRdXG5cdFx0XHRcdH1cblx0XHRcdFx0Ly8gY29uc2lkZXIgYXV0by1kb21haW4gZXF1aXBhcnRpYWxcblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0cGFzcy52aWV3cG9ydCA9IFtcblx0XHRcdFx0XHRcdGxlZnQgKyBqICogaXcgKyBpdyAqIHBhZFswXSxcblx0XHRcdFx0XHRcdHRvcCArIGkkMiAqIGloICsgaWggKiBwYWRbMV0sXG5cdFx0XHRcdFx0XHRsZWZ0ICsgKGogKyAxKSAqIGl3IC0gaXcgKiBwYWRbMl0sXG5cdFx0XHRcdFx0XHR0b3AgKyAoaSQyICsgMSkgKiBpaCAtIGloICogcGFkWzNdXG5cdFx0XHRcdFx0XVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmIChvLmNvbG9yKSB7IHBhc3MuY29sb3IgPSB0cmFjZS5jb2xvciB9XG5cdFx0XHRpZiAoby5zaXplKSB7IHBhc3Muc2l6ZSA9IHRyYWNlLnNpemUgfVxuXHRcdFx0aWYgKG8ubWFya2VyKSB7IHBhc3MubWFya2VyID0gdHJhY2UubWFya2VyIH1cblx0XHRcdGlmIChvLmJvcmRlclNpemUpIHsgcGFzcy5ib3JkZXJTaXplID0gdHJhY2UuYm9yZGVyU2l6ZSB9XG5cdFx0XHRpZiAoby5ib3JkZXJDb2xvcikgeyBwYXNzLmJvcmRlckNvbG9yID0gdHJhY2UuYm9yZGVyQ29sb3IgfVxuXHRcdFx0aWYgKG8ub3BhY2l0eSkgeyBwYXNzLm9wYWNpdHkgPSB0cmFjZS5vcGFjaXR5IH1cblxuXHRcdFx0aWYgKG8ucmFuZ2UpIHtcblx0XHRcdFx0cGFzcy5yYW5nZSA9IG11bHRpcmFuZ2UgPyBnZXRCb3godHJhY2UucmFuZ2UsIGkkMiwgaikgOiB0cmFjZS5yYW5nZSB8fCBwYXNzLmJvdW5kc1xuXHRcdFx0fVxuXG5cdFx0XHR0cmFjZS5wYXNzZXMucHVzaChrZXkpXG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHRoaXNcbn1cblxuXG4vLyBkcmF3IGFsbCBvciBwYXNzZWQgcGFzc2VzXG5TUExPTS5wcm90b3R5cGUuZHJhdyA9IGZ1bmN0aW9uICgpIHtcblx0dmFyIHRoaXMkMSA9IHRoaXM7XG5cdHZhciByZWYkMjtcblxuXHR2YXIgYXJncyA9IFtdLCBsZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuXHR3aGlsZSAoIGxlbi0tICkgYXJnc1sgbGVuIF0gPSBhcmd1bWVudHNbIGxlbiBdO1xuXHRpZiAoIWFyZ3MubGVuZ3RoKSB7XG5cdFx0dGhpcy5zY2F0dGVyLmRyYXcoKVxuXHR9XG5cdGVsc2Uge1xuXHRcdHZhciBpZHggPSBbXVxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuXHRcdFx0Ly8gZHJhdygwLCAyLCA1KSAtIGRyYXcgdHJhY2VzXG5cdFx0XHRpZiAodHlwZW9mIGFyZ3NbaV0gPT09ICdudW1iZXInICkge1xuXHRcdFx0XHR2YXIgcmVmID0gdGhpcyQxLnRyYWNlc1thcmdzW2ldXTtcblx0XHRcdFx0dmFyIHBhc3NlcyA9IHJlZi5wYXNzZXM7XG5cdFx0XHRcdHZhciBwYXNzT2Zmc2V0ID0gcmVmLnBhc3NPZmZzZXQ7XG5cdFx0XHRcdGlkeC5wdXNoLmFwcGx5KGlkeCwgYXJyUmFuZ2UocGFzc09mZnNldCwgcGFzc09mZnNldCArIHBhc3Nlcy5sZW5ndGgpKVxuXHRcdFx0fVxuXHRcdFx0Ly8gZHJhdyhbMCwgMSwgMiAuLi5dLCBbMywgNCwgNV0pIC0gZHJhdyBwb2ludHNcblx0XHRcdGVsc2UgaWYgKGFyZ3NbaV0ubGVuZ3RoKSB7XG5cdFx0XHRcdHZhciBlbHMgPSBhcmdzW2ldXG5cdFx0XHRcdHZhciByZWYkMSA9IHRoaXMkMS50cmFjZXNbaV07XG5cdFx0XHRcdHZhciBwYXNzZXMkMSA9IHJlZiQxLnBhc3Nlcztcblx0XHRcdFx0dmFyIHBhc3NPZmZzZXQkMSA9IHJlZiQxLnBhc3NPZmZzZXQ7XG5cdFx0XHRcdHBhc3NlcyQxID0gcGFzc2VzJDEubWFwKGZ1bmN0aW9uIChwYXNzSWQsIGkpIHtcblx0XHRcdFx0XHRpZHhbcGFzc09mZnNldCQxICsgaV0gPSBlbHNcblx0XHRcdFx0fSlcblx0XHRcdH1cblx0XHR9XG5cdFx0KHJlZiQyID0gdGhpcy5zY2F0dGVyKS5kcmF3LmFwcGx5KHJlZiQyLCBpZHgpXG5cdH1cblxuXHRyZXR1cm4gdGhpc1xufVxuXG5cbi8vIGRpc3Bvc2UgcmVzb3VyY2VzXG5TUExPTS5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcblx0dGhpcy50cmFjZXMuZm9yRWFjaChmdW5jdGlvbiAodHJhY2UpIHtcblx0XHRpZiAodHJhY2UuYnVmZmVyICYmIHRyYWNlLmJ1ZmZlci5kZXN0cm95KSB7IHRyYWNlLmJ1ZmZlci5kZXN0cm95KCkgfVxuXHR9KVxuXHR0aGlzLnRyYWNlcyA9IG51bGxcblx0dGhpcy5wYXNzZXMgPSBudWxsXG5cblx0dGhpcy5zY2F0dGVyLmRlc3Ryb3koKVxuXG5cdHJldHVybiB0aGlzXG59XG5cblxuLy8gcmV0dXJuIHBhc3MgY29ycmVzcG9uZGluZyB0byB0cmFjZSBpLSBqLSBzcXVhcmVcbmZ1bmN0aW9uIHBhc3NJZCAodHJhY2UsIGksIGopIHtcblx0dmFyIGlkID0gKHRyYWNlLmlkICE9IG51bGwgPyB0cmFjZS5pZCA6IHRyYWNlKVxuXHR2YXIgbiA9IGlcblx0dmFyIG0gPSBqXG5cdHZhciBrZXkgPSBpZCA8PCAxNiB8IChuICYgMHhmZikgPDwgOCB8IG0gJiAweGZmXG5cblx0cmV0dXJuIGtleVxufVxuXG5cbi8vIHJldHVybiBib3VuZGluZyBib3ggY29ycmVzcG9uZGluZyB0byBhIHBhc3NcbmZ1bmN0aW9uIGdldEJveCAoaXRlbXMsIGksIGopIHtcblx0dmFyIGlsb3gsIGlsb3ksIGloaXgsIGloaXksIGpsb3gsIGpsb3ksIGpoaXgsIGpoaXlcblx0dmFyIGlpdGVtID0gaXRlbXNbaV0sIGppdGVtID0gaXRlbXNbal1cblxuXHRpZiAoaWl0ZW0ubGVuZ3RoID4gMikge1xuXHRcdGlsb3ggPSBpaXRlbVswXVxuXHRcdGloaXggPSBpaXRlbVsyXVxuXHRcdGlsb3kgPSBpaXRlbVsxXVxuXHRcdGloaXkgPSBpaXRlbVszXVxuXHR9XG5cdGVsc2UgaWYgKGlpdGVtLmxlbmd0aCkge1xuXHRcdGlsb3ggPSBpbG95ID0gaWl0ZW1bMF1cblx0XHRpaGl4ID0gaWhpeSA9IGlpdGVtWzFdXG5cdH1cblx0ZWxzZSB7XG5cdFx0aWxveCA9IGlpdGVtLnhcblx0XHRpbG95ID0gaWl0ZW0ueVxuXHRcdGloaXggPSBpaXRlbS54ICsgaWl0ZW0ud2lkdGhcblx0XHRpaGl5ID0gaWl0ZW0ueSArIGlpdGVtLmhlaWdodFxuXHR9XG5cblx0aWYgKGppdGVtLmxlbmd0aCA+IDIpIHtcblx0XHRqbG94ID0gaml0ZW1bMF1cblx0XHRqaGl4ID0gaml0ZW1bMl1cblx0XHRqbG95ID0gaml0ZW1bMV1cblx0XHRqaGl5ID0gaml0ZW1bM11cblx0fVxuXHRlbHNlIGlmIChqaXRlbS5sZW5ndGgpIHtcblx0XHRqbG94ID0gamxveSA9IGppdGVtWzBdXG5cdFx0amhpeCA9IGpoaXkgPSBqaXRlbVsxXVxuXHR9XG5cdGVsc2Uge1xuXHRcdGpsb3ggPSBqaXRlbS54XG5cdFx0amxveSA9IGppdGVtLnlcblx0XHRqaGl4ID0gaml0ZW0ueCArIGppdGVtLndpZHRoXG5cdFx0amhpeSA9IGppdGVtLnkgKyBqaXRlbS5oZWlnaHRcblx0fVxuXG5cdHJldHVybiBbIGpsb3gsIGlsb3ksIGpoaXgsIGloaXkgXVxufVxuXG5cbmZ1bmN0aW9uIGdldFBhZCAoYXJnKSB7XG5cdGlmICh0eXBlb2YgYXJnID09PSAnbnVtYmVyJykgeyByZXR1cm4gW2FyZywgYXJnLCBhcmcsIGFyZ10gfVxuXHRlbHNlIGlmIChhcmcubGVuZ3RoID09PSAyKSB7IHJldHVybiBbYXJnWzBdLCBhcmdbMV0sIGFyZ1swXSwgYXJnWzFdXSB9XG5cdGVsc2Uge1xuXHRcdHZhciBib3ggPSByZWN0KGFyZylcblx0XHRyZXR1cm4gW2JveC54LCBib3gueSwgYm94LnggKyBib3gud2lkdGgsIGJveC55ICsgYm94LmhlaWdodF1cblx0fVxufVxuXG59LHtcImFycmF5LWJvdW5kc1wiOjY1LFwiYXJyYXktcmFuZ2VcIjo2NyxcImZsYXR0ZW4tdmVydGV4LWRhdGFcIjoyMjcsXCJwYXJzZS1yZWN0XCI6NDU5LFwicGljay1ieS1hbGlhc1wiOjQ2NSxcInJhZlwiOjQ4NCxcInJlZ2wtc2NhdHRlcjJkXCI6NDk3fV0sNTAyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbihmdW5jdGlvbihhYSxpYSl7XCJvYmplY3RcIj09PXR5cGVvZiBleHBvcnRzJiZcInVuZGVmaW5lZFwiIT09dHlwZW9mIG1vZHVsZT9tb2R1bGUuZXhwb3J0cz1pYSgpOlwiZnVuY3Rpb25cIj09PXR5cGVvZiBkZWZpbmUmJmRlZmluZS5hbWQ/ZGVmaW5lKGlhKTphYS5jcmVhdGVSRUdMPWlhKCl9KSh0aGlzLGZ1bmN0aW9uKCl7ZnVuY3Rpb24gYWEoYSxiKXt0aGlzLmlkPUFiKys7dGhpcy50eXBlPWE7dGhpcy5kYXRhPWJ9ZnVuY3Rpb24gaWEoYSl7aWYoMD09PWEubGVuZ3RoKXJldHVybltdO3ZhciBiPWEuY2hhckF0KDApLGM9YS5jaGFyQXQoYS5sZW5ndGgtMSk7aWYoMTxhLmxlbmd0aCYmYj09PWMmJignXCInPT09Ynx8XCInXCI9PT1iKSlyZXR1cm5bJ1wiJythLnN1YnN0cigxLGEubGVuZ3RoLTIpLnJlcGxhY2UoL1xcXFwvZyxcIlxcXFxcXFxcXCIpLnJlcGxhY2UoL1wiL2csJ1xcXFxcIicpKydcIiddO2lmKGI9L1xcWyhmYWxzZXx0cnVlfG51bGx8XFxkK3wnW14nXSonfFwiW15cIl0qXCIpXFxdLy5leGVjKGEpKXJldHVybiBpYShhLnN1YnN0cigwLFxuYi5pbmRleCkpLmNvbmNhdChpYShiWzFdKSkuY29uY2F0KGlhKGEuc3Vic3RyKGIuaW5kZXgrYlswXS5sZW5ndGgpKSk7Yj1hLnNwbGl0KFwiLlwiKTtpZigxPT09Yi5sZW5ndGgpcmV0dXJuWydcIicrYS5yZXBsYWNlKC9cXFxcL2csXCJcXFxcXFxcXFwiKS5yZXBsYWNlKC9cIi9nLCdcXFxcXCInKSsnXCInXTthPVtdO2ZvcihjPTA7YzxiLmxlbmd0aDsrK2MpYT1hLmNvbmNhdChpYShiW2NdKSk7cmV0dXJuIGF9ZnVuY3Rpb24gWmEoYSl7cmV0dXJuXCJbXCIraWEoYSkuam9pbihcIl1bXCIpK1wiXVwifWZ1bmN0aW9uIEJiKCl7dmFyIGE9e1wiXCI6MH0sYj1bXCJcIl07cmV0dXJue2lkOmZ1bmN0aW9uKGMpe3ZhciBlPWFbY107aWYoZSlyZXR1cm4gZTtlPWFbY109Yi5sZW5ndGg7Yi5wdXNoKGMpO3JldHVybiBlfSxzdHI6ZnVuY3Rpb24oYSl7cmV0dXJuIGJbYV19fX1mdW5jdGlvbiBDYihhLGIsYyl7ZnVuY3Rpb24gZSgpe3ZhciBiPXdpbmRvdy5pbm5lcldpZHRoLGU9d2luZG93LmlubmVySGVpZ2h0O2EhPT1kb2N1bWVudC5ib2R5JiZcbihlPWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksYj1lLnJpZ2h0LWUubGVmdCxlPWUuYm90dG9tLWUudG9wKTtnLndpZHRoPWMqYjtnLmhlaWdodD1jKmU7RShnLnN0eWxlLHt3aWR0aDpiK1wicHhcIixoZWlnaHQ6ZStcInB4XCJ9KX12YXIgZz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpO0UoZy5zdHlsZSx7Ym9yZGVyOjAsbWFyZ2luOjAscGFkZGluZzowLHRvcDowLGxlZnQ6MH0pO2EuYXBwZW5kQ2hpbGQoZyk7YT09PWRvY3VtZW50LmJvZHkmJihnLnN0eWxlLnBvc2l0aW9uPVwiYWJzb2x1dGVcIixFKGEuc3R5bGUse21hcmdpbjowLHBhZGRpbmc6MH0pKTt3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcInJlc2l6ZVwiLGUsITEpO2UoKTtyZXR1cm57Y2FudmFzOmcsb25EZXN0cm95OmZ1bmN0aW9uKCl7d2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIixlKTthLnJlbW92ZUNoaWxkKGcpfX19ZnVuY3Rpb24gRGIoYSxiKXtmdW5jdGlvbiBjKGMpe3RyeXtyZXR1cm4gYS5nZXRDb250ZXh0KGMsXG5iKX1jYXRjaChnKXtyZXR1cm4gbnVsbH19cmV0dXJuIGMoXCJ3ZWJnbFwiKXx8YyhcImV4cGVyaW1lbnRhbC13ZWJnbFwiKXx8YyhcIndlYmdsLWV4cGVyaW1lbnRhbFwiKX1mdW5jdGlvbiAkYShhKXtyZXR1cm5cInN0cmluZ1wiPT09dHlwZW9mIGE/YS5zcGxpdCgpOmF9ZnVuY3Rpb24gYWIoYSl7cmV0dXJuXCJzdHJpbmdcIj09PXR5cGVvZiBhP2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYSk6YX1mdW5jdGlvbiBFYihhKXt2YXIgYj1hfHx7fSxjLGUsZyxkO2E9e307dmFyIG49W10sZj1bXSxyPVwidW5kZWZpbmVkXCI9PT10eXBlb2Ygd2luZG93PzE6d2luZG93LmRldmljZVBpeGVsUmF0aW8scT0hMSx0PWZ1bmN0aW9uKGEpe30sbT1mdW5jdGlvbigpe307XCJzdHJpbmdcIj09PXR5cGVvZiBiP2M9ZG9jdW1lbnQucXVlcnlTZWxlY3RvcihiKTpcIm9iamVjdFwiPT09dHlwZW9mIGImJihcInN0cmluZ1wiPT09dHlwZW9mIGIubm9kZU5hbWUmJlwiZnVuY3Rpb25cIj09PXR5cGVvZiBiLmFwcGVuZENoaWxkJiZcImZ1bmN0aW9uXCI9PT1cbnR5cGVvZiBiLmdldEJvdW5kaW5nQ2xpZW50UmVjdD9jPWI6XCJmdW5jdGlvblwiPT09dHlwZW9mIGIuZHJhd0FycmF5c3x8XCJmdW5jdGlvblwiPT09dHlwZW9mIGIuZHJhd0VsZW1lbnRzPyhkPWIsZz1kLmNhbnZhcyk6KFwiZ2xcImluIGI/ZD1iLmdsOlwiY2FudmFzXCJpbiBiP2c9YWIoYi5jYW52YXMpOlwiY29udGFpbmVyXCJpbiBiJiYoZT1hYihiLmNvbnRhaW5lcikpLFwiYXR0cmlidXRlc1wiaW4gYiYmKGE9Yi5hdHRyaWJ1dGVzKSxcImV4dGVuc2lvbnNcImluIGImJihuPSRhKGIuZXh0ZW5zaW9ucykpLFwib3B0aW9uYWxFeHRlbnNpb25zXCJpbiBiJiYoZj0kYShiLm9wdGlvbmFsRXh0ZW5zaW9ucykpLFwib25Eb25lXCJpbiBiJiYodD1iLm9uRG9uZSksXCJwcm9maWxlXCJpbiBiJiYocT0hIWIucHJvZmlsZSksXCJwaXhlbFJhdGlvXCJpbiBiJiYocj0rYi5waXhlbFJhdGlvKSkpO2MmJihcImNhbnZhc1wiPT09Yy5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpP2c9YzplPWMpO2lmKCFkKXtpZighZyl7Yz1DYihlfHxkb2N1bWVudC5ib2R5LFxudCxyKTtpZighYylyZXR1cm4gbnVsbDtnPWMuY2FudmFzO209Yy5vbkRlc3Ryb3l9ZD1EYihnLGEpfXJldHVybiBkP3tnbDpkLGNhbnZhczpnLGNvbnRhaW5lcjplLGV4dGVuc2lvbnM6bixvcHRpb25hbEV4dGVuc2lvbnM6ZixwaXhlbFJhdGlvOnIscHJvZmlsZTpxLG9uRG9uZTp0LG9uRGVzdHJveTptfToobSgpLHQoXCJ3ZWJnbCBub3Qgc3VwcG9ydGVkLCB0cnkgdXBncmFkaW5nIHlvdXIgYnJvd3NlciBvciBncmFwaGljcyBkcml2ZXJzIGh0dHA6Ly9nZXQud2ViZ2wub3JnXCIpLG51bGwpfWZ1bmN0aW9uIEZiKGEsYil7ZnVuY3Rpb24gYyhiKXtiPWIudG9Mb3dlckNhc2UoKTt2YXIgYzt0cnl7Yz1lW2JdPWEuZ2V0RXh0ZW5zaW9uKGIpfWNhdGNoKGcpe31yZXR1cm4hIWN9Zm9yKHZhciBlPXt9LGc9MDtnPGIuZXh0ZW5zaW9ucy5sZW5ndGg7KytnKXt2YXIgZD1iLmV4dGVuc2lvbnNbZ107aWYoIWMoZCkpcmV0dXJuIGIub25EZXN0cm95KCksYi5vbkRvbmUoJ1wiJytkKydcIiBleHRlbnNpb24gaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgY3VycmVudCBXZWJHTCBjb250ZXh0LCB0cnkgdXBncmFkaW5nIHlvdXIgc3lzdGVtIG9yIGEgZGlmZmVyZW50IGJyb3dzZXInKSxcbm51bGx9Yi5vcHRpb25hbEV4dGVuc2lvbnMuZm9yRWFjaChjKTtyZXR1cm57ZXh0ZW5zaW9uczplLHJlc3RvcmU6ZnVuY3Rpb24oKXtPYmplY3Qua2V5cyhlKS5mb3JFYWNoKGZ1bmN0aW9uKGEpe2lmKGVbYV0mJiFjKGEpKXRocm93IEVycm9yKFwiKHJlZ2wpOiBlcnJvciByZXN0b3JpbmcgZXh0ZW5zaW9uIFwiK2EpO30pfX19ZnVuY3Rpb24gSihhLGIpe2Zvcih2YXIgYz1BcnJheShhKSxlPTA7ZTxhOysrZSljW2VdPWIoZSk7cmV0dXJuIGN9ZnVuY3Rpb24gYmIoYSl7dmFyIGIsYztiPSg2NTUzNTxhKTw8NDthPj4+PWI7Yz0oMjU1PGEpPDwzO2E+Pj49YztifD1jO2M9KDE1PGEpPDwyO2E+Pj49YztifD1jO2M9KDM8YSk8PDE7cmV0dXJuIGJ8Y3xhPj4+Yz4+MX1mdW5jdGlvbiBjYigpe2Z1bmN0aW9uIGEoYSl7YTp7Zm9yKHZhciBiPTE2OzI2ODQzNTQ1Nj49YjtiKj0xNilpZihhPD1iKXthPWI7YnJlYWsgYX1hPTB9Yj1jW2JiKGEpPj4yXTtyZXR1cm4gMDxiLmxlbmd0aD9iLnBvcCgpOlxubmV3IEFycmF5QnVmZmVyKGEpfWZ1bmN0aW9uIGIoYSl7Y1tiYihhLmJ5dGVMZW5ndGgpPj4yXS5wdXNoKGEpfXZhciBjPUooOCxmdW5jdGlvbigpe3JldHVybltdfSk7cmV0dXJue2FsbG9jOmEsZnJlZTpiLGFsbG9jVHlwZTpmdW5jdGlvbihiLGMpe3ZhciBkPW51bGw7c3dpdGNoKGIpe2Nhc2UgNTEyMDpkPW5ldyBJbnQ4QXJyYXkoYShjKSwwLGMpO2JyZWFrO2Nhc2UgNTEyMTpkPW5ldyBVaW50OEFycmF5KGEoYyksMCxjKTticmVhaztjYXNlIDUxMjI6ZD1uZXcgSW50MTZBcnJheShhKDIqYyksMCxjKTticmVhaztjYXNlIDUxMjM6ZD1uZXcgVWludDE2QXJyYXkoYSgyKmMpLDAsYyk7YnJlYWs7Y2FzZSA1MTI0OmQ9bmV3IEludDMyQXJyYXkoYSg0KmMpLDAsYyk7YnJlYWs7Y2FzZSA1MTI1OmQ9bmV3IFVpbnQzMkFycmF5KGEoNCpjKSwwLGMpO2JyZWFrO2Nhc2UgNTEyNjpkPW5ldyBGbG9hdDMyQXJyYXkoYSg0KmMpLDAsYyk7YnJlYWs7ZGVmYXVsdDpyZXR1cm4gbnVsbH1yZXR1cm4gZC5sZW5ndGghPT1cbmM/ZC5zdWJhcnJheSgwLGMpOmR9LGZyZWVUeXBlOmZ1bmN0aW9uKGEpe2IoYS5idWZmZXIpfX19ZnVuY3Rpb24gbWEoYSl7cmV0dXJuISFhJiZcIm9iamVjdFwiPT09dHlwZW9mIGEmJkFycmF5LmlzQXJyYXkoYS5zaGFwZSkmJkFycmF5LmlzQXJyYXkoYS5zdHJpZGUpJiZcIm51bWJlclwiPT09dHlwZW9mIGEub2Zmc2V0JiZhLnNoYXBlLmxlbmd0aD09PWEuc3RyaWRlLmxlbmd0aCYmKEFycmF5LmlzQXJyYXkoYS5kYXRhKXx8TShhLmRhdGEpKX1mdW5jdGlvbiBkYihhLGIsYyxlLGcsZCl7Zm9yKHZhciBuPTA7bjxiOysrbilmb3IodmFyIGY9YVtuXSxyPTA7cjxjOysrcilmb3IodmFyIHE9ZltyXSx0PTA7dDxlOysrdClnW2QrK109cVt0XX1mdW5jdGlvbiBlYihhLGIsYyxlLGcpe2Zvcih2YXIgZD0xLG49YysxO248Yi5sZW5ndGg7KytuKWQqPWJbbl07dmFyIGY9YltjXTtpZig0PT09Yi5sZW5ndGgtYyl7dmFyIHI9YltjKzFdLHE9YltjKzJdO2I9YltjKzNdO2ZvcihuPTA7bjxmOysrbilkYihhW25dLFxucixxLGIsZSxnKSxnKz1kfWVsc2UgZm9yKG49MDtuPGY7KytuKWViKGFbbl0sYixjKzEsZSxnKSxnKz1kfWZ1bmN0aW9uIEhhKGEpe3JldHVybiBJYVtPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYSldfDB9ZnVuY3Rpb24gZmIoYSxiKXtmb3IodmFyIGM9MDtjPGIubGVuZ3RoOysrYylhW2NdPWJbY119ZnVuY3Rpb24gZ2IoYSxiLGMsZSxnLGQsbil7Zm9yKHZhciBmPTAscj0wO3I8YzsrK3IpZm9yKHZhciBxPTA7cTxlOysrcSlhW2YrK109YltnKnIrZCpxK25dfWZ1bmN0aW9uIEdiKGEsYixjLGUpe2Z1bmN0aW9uIGcoYil7dGhpcy5pZD1yKys7dGhpcy5idWZmZXI9YS5jcmVhdGVCdWZmZXIoKTt0aGlzLnR5cGU9Yjt0aGlzLnVzYWdlPTM1MDQ0O3RoaXMuYnl0ZUxlbmd0aD0wO3RoaXMuZGltZW5zaW9uPTE7dGhpcy5kdHlwZT01MTIxO3RoaXMucGVyc2lzdGVudERhdGE9bnVsbDtjLnByb2ZpbGUmJih0aGlzLnN0YXRzPXtzaXplOjB9KX1mdW5jdGlvbiBkKGIsYyxrKXtiLmJ5dGVMZW5ndGg9XG5jLmJ5dGVMZW5ndGg7YS5idWZmZXJEYXRhKGIudHlwZSxjLGspfWZ1bmN0aW9uIG4oYSxiLGMsaCxsLGUpe2EudXNhZ2U9YztpZihBcnJheS5pc0FycmF5KGIpKXtpZihhLmR0eXBlPWh8fDUxMjYsMDxiLmxlbmd0aClpZihBcnJheS5pc0FycmF5KGJbMF0pKXtsPWhiKGIpO2Zvcih2YXIgdj1oPTE7djxsLmxlbmd0aDsrK3YpaCo9bFt2XTthLmRpbWVuc2lvbj1oO2I9UWEoYixsLGEuZHR5cGUpO2QoYSxiLGMpO2U/YS5wZXJzaXN0ZW50RGF0YT1iOnguZnJlZVR5cGUoYil9ZWxzZVwibnVtYmVyXCI9PT10eXBlb2YgYlswXT8oYS5kaW1lbnNpb249bCxsPXguYWxsb2NUeXBlKGEuZHR5cGUsYi5sZW5ndGgpLGZiKGwsYiksZChhLGwsYyksZT9hLnBlcnNpc3RlbnREYXRhPWw6eC5mcmVlVHlwZShsKSk6TShiWzBdKSYmKGEuZGltZW5zaW9uPWJbMF0ubGVuZ3RoLGEuZHR5cGU9aHx8SGEoYlswXSl8fDUxMjYsYj1RYShiLFtiLmxlbmd0aCxiWzBdLmxlbmd0aF0sYS5kdHlwZSksZChhLGIsYyksXG5lP2EucGVyc2lzdGVudERhdGE9Yjp4LmZyZWVUeXBlKGIpKX1lbHNlIGlmKE0oYikpYS5kdHlwZT1ofHxIYShiKSxhLmRpbWVuc2lvbj1sLGQoYSxiLGMpLGUmJihhLnBlcnNpc3RlbnREYXRhPW5ldyBVaW50OEFycmF5KG5ldyBVaW50OEFycmF5KGIuYnVmZmVyKSkpO2Vsc2UgaWYobWEoYikpe2w9Yi5zaGFwZTt2YXIgZz1iLnN0cmlkZSx2PWIub2Zmc2V0LGY9MCxxPTAscj0wLHQ9MDsxPT09bC5sZW5ndGg/KGY9bFswXSxxPTEscj1nWzBdLHQ9MCk6Mj09PWwubGVuZ3RoJiYoZj1sWzBdLHE9bFsxXSxyPWdbMF0sdD1nWzFdKTthLmR0eXBlPWh8fEhhKGIuZGF0YSl8fDUxMjY7YS5kaW1lbnNpb249cTtsPXguYWxsb2NUeXBlKGEuZHR5cGUsZipxKTtnYihsLGIuZGF0YSxmLHEscix0LHYpO2QoYSxsLGMpO2U/YS5wZXJzaXN0ZW50RGF0YT1sOnguZnJlZVR5cGUobCl9fWZ1bmN0aW9uIGYoYyl7Yi5idWZmZXJDb3VudC0tO2Zvcih2YXIgZD0wO2Q8ZS5zdGF0ZS5sZW5ndGg7KytkKXt2YXIgaz1cbmUuc3RhdGVbZF07ay5idWZmZXI9PT1jJiYoYS5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoZCksay5idWZmZXI9bnVsbCl9YS5kZWxldGVCdWZmZXIoYy5idWZmZXIpO2MuYnVmZmVyPW51bGw7ZGVsZXRlIHFbYy5pZF19dmFyIHI9MCxxPXt9O2cucHJvdG90eXBlLmJpbmQ9ZnVuY3Rpb24oKXthLmJpbmRCdWZmZXIodGhpcy50eXBlLHRoaXMuYnVmZmVyKX07Zy5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe2YodGhpcyl9O3ZhciB0PVtdO2MucHJvZmlsZSYmKGIuZ2V0VG90YWxCdWZmZXJTaXplPWZ1bmN0aW9uKCl7dmFyIGE9MDtPYmplY3Qua2V5cyhxKS5mb3JFYWNoKGZ1bmN0aW9uKGIpe2ErPXFbYl0uc3RhdHMuc2l6ZX0pO3JldHVybiBhfSk7cmV0dXJue2NyZWF0ZTpmdW5jdGlvbihtLGUsZCxoKXtmdW5jdGlvbiBsKGIpe3ZhciBtPTM1MDQ0LGU9bnVsbCxkPTAsaz0wLGc9MTtBcnJheS5pc0FycmF5KGIpfHxNKGIpfHxtYShiKT9lPWI6XCJudW1iZXJcIj09PXR5cGVvZiBiP1xuZD1ifDA6YiYmKFwiZGF0YVwiaW4gYiYmKGU9Yi5kYXRhKSxcInVzYWdlXCJpbiBiJiYobT1qYltiLnVzYWdlXSksXCJ0eXBlXCJpbiBiJiYoaz1SYVtiLnR5cGVdKSxcImRpbWVuc2lvblwiaW4gYiYmKGc9Yi5kaW1lbnNpb258MCksXCJsZW5ndGhcImluIGImJihkPWIubGVuZ3RofDApKTt1LmJpbmQoKTtlP24odSxlLG0sayxnLGgpOihkJiZhLmJ1ZmZlckRhdGEodS50eXBlLGQsbSksdS5kdHlwZT1rfHw1MTIxLHUudXNhZ2U9bSx1LmRpbWVuc2lvbj1nLHUuYnl0ZUxlbmd0aD1kKTtjLnByb2ZpbGUmJih1LnN0YXRzLnNpemU9dS5ieXRlTGVuZ3RoKmphW3UuZHR5cGVdKTtyZXR1cm4gbH1iLmJ1ZmZlckNvdW50Kys7dmFyIHU9bmV3IGcoZSk7cVt1LmlkXT11O2R8fGwobSk7bC5fcmVnbFR5cGU9XCJidWZmZXJcIjtsLl9idWZmZXI9dTtsLnN1YmRhdGE9ZnVuY3Rpb24oYixjKXt2YXIgbT0oY3x8MCl8MCxlO3UuYmluZCgpO2lmKE0oYikpYS5idWZmZXJTdWJEYXRhKHUudHlwZSxtLGIpO2Vsc2UgaWYoQXJyYXkuaXNBcnJheShiKSl7aWYoMDxcbmIubGVuZ3RoKWlmKFwibnVtYmVyXCI9PT10eXBlb2YgYlswXSl7dmFyIGQ9eC5hbGxvY1R5cGUodS5kdHlwZSxiLmxlbmd0aCk7ZmIoZCxiKTthLmJ1ZmZlclN1YkRhdGEodS50eXBlLG0sZCk7eC5mcmVlVHlwZShkKX1lbHNlIGlmKEFycmF5LmlzQXJyYXkoYlswXSl8fE0oYlswXSkpZT1oYihiKSxkPVFhKGIsZSx1LmR0eXBlKSxhLmJ1ZmZlclN1YkRhdGEodS50eXBlLG0sZCkseC5mcmVlVHlwZShkKX1lbHNlIGlmKG1hKGIpKXtlPWIuc2hhcGU7dmFyIGg9Yi5zdHJpZGUsaz1kPTAsZz0wLEY9MDsxPT09ZS5sZW5ndGg/KGQ9ZVswXSxrPTEsZz1oWzBdLEY9MCk6Mj09PWUubGVuZ3RoJiYoZD1lWzBdLGs9ZVsxXSxnPWhbMF0sRj1oWzFdKTtlPUFycmF5LmlzQXJyYXkoYi5kYXRhKT91LmR0eXBlOkhhKGIuZGF0YSk7ZT14LmFsbG9jVHlwZShlLGQqayk7Z2IoZSxiLmRhdGEsZCxrLGcsRixiLm9mZnNldCk7YS5idWZmZXJTdWJEYXRhKHUudHlwZSxtLGUpO3guZnJlZVR5cGUoZSl9cmV0dXJuIGx9O1xuYy5wcm9maWxlJiYobC5zdGF0cz11LnN0YXRzKTtsLmRlc3Ryb3k9ZnVuY3Rpb24oKXtmKHUpfTtyZXR1cm4gbH0sY3JlYXRlU3RyZWFtOmZ1bmN0aW9uKGEsYil7dmFyIGM9dC5wb3AoKTtjfHwoYz1uZXcgZyhhKSk7Yy5iaW5kKCk7bihjLGIsMzUwNDAsMCwxLCExKTtyZXR1cm4gY30sZGVzdHJveVN0cmVhbTpmdW5jdGlvbihhKXt0LnB1c2goYSl9LGNsZWFyOmZ1bmN0aW9uKCl7UyhxKS5mb3JFYWNoKGYpO3QuZm9yRWFjaChmKX0sZ2V0QnVmZmVyOmZ1bmN0aW9uKGEpe3JldHVybiBhJiZhLl9idWZmZXIgaW5zdGFuY2VvZiBnP2EuX2J1ZmZlcjpudWxsfSxyZXN0b3JlOmZ1bmN0aW9uKCl7UyhxKS5mb3JFYWNoKGZ1bmN0aW9uKGIpe2IuYnVmZmVyPWEuY3JlYXRlQnVmZmVyKCk7YS5iaW5kQnVmZmVyKGIudHlwZSxiLmJ1ZmZlcik7YS5idWZmZXJEYXRhKGIudHlwZSxiLnBlcnNpc3RlbnREYXRhfHxiLmJ5dGVMZW5ndGgsYi51c2FnZSl9KX0sX2luaXRCdWZmZXI6bn19ZnVuY3Rpb24gSGIoYSxcbmIsYyxlKXtmdW5jdGlvbiBnKGEpe3RoaXMuaWQ9cisrO2ZbdGhpcy5pZF09dGhpczt0aGlzLmJ1ZmZlcj1hO3RoaXMucHJpbVR5cGU9NDt0aGlzLnR5cGU9dGhpcy52ZXJ0Q291bnQ9MH1mdW5jdGlvbiBkKGUsZCxnLGgsbCx1LHYpe2UuYnVmZmVyLmJpbmQoKTtpZihkKXt2YXIgZj12O3Z8fE0oZCkmJighbWEoZCl8fE0oZC5kYXRhKSl8fChmPWIub2VzX2VsZW1lbnRfaW5kZXhfdWludD81MTI1OjUxMjMpO2MuX2luaXRCdWZmZXIoZS5idWZmZXIsZCxnLGYsMyl9ZWxzZSBhLmJ1ZmZlckRhdGEoMzQ5NjMsdSxnKSxlLmJ1ZmZlci5kdHlwZT1mfHw1MTIxLGUuYnVmZmVyLnVzYWdlPWcsZS5idWZmZXIuZGltZW5zaW9uPTMsZS5idWZmZXIuYnl0ZUxlbmd0aD11O2Y9djtpZighdil7c3dpdGNoKGUuYnVmZmVyLmR0eXBlKXtjYXNlIDUxMjE6Y2FzZSA1MTIwOmY9NTEyMTticmVhaztjYXNlIDUxMjM6Y2FzZSA1MTIyOmY9NTEyMzticmVhaztjYXNlIDUxMjU6Y2FzZSA1MTI0OmY9NTEyNX1lLmJ1ZmZlci5kdHlwZT1cbmZ9ZS50eXBlPWY7ZD1sOzA+ZCYmKGQ9ZS5idWZmZXIuYnl0ZUxlbmd0aCw1MTIzPT09Zj9kPj49MTo1MTI1PT09ZiYmKGQ+Pj0yKSk7ZS52ZXJ0Q291bnQ9ZDtkPWg7MD5oJiYoZD00LGg9ZS5idWZmZXIuZGltZW5zaW9uLDE9PT1oJiYoZD0wKSwyPT09aCYmKGQ9MSksMz09PWgmJihkPTQpKTtlLnByaW1UeXBlPWR9ZnVuY3Rpb24gbihhKXtlLmVsZW1lbnRzQ291bnQtLTtkZWxldGUgZlthLmlkXTthLmJ1ZmZlci5kZXN0cm95KCk7YS5idWZmZXI9bnVsbH12YXIgZj17fSxyPTAscT17dWludDg6NTEyMSx1aW50MTY6NTEyM307Yi5vZXNfZWxlbWVudF9pbmRleF91aW50JiYocS51aW50MzI9NTEyNSk7Zy5wcm90b3R5cGUuYmluZD1mdW5jdGlvbigpe3RoaXMuYnVmZmVyLmJpbmQoKX07dmFyIHQ9W107cmV0dXJue2NyZWF0ZTpmdW5jdGlvbihhLGIpe2Z1bmN0aW9uIGsoYSl7aWYoYSlpZihcIm51bWJlclwiPT09dHlwZW9mIGEpaChhKSxsLnByaW1UeXBlPTQsbC52ZXJ0Q291bnQ9YXwwLFxubC50eXBlPTUxMjE7ZWxzZXt2YXIgYj1udWxsLGM9MzUwNDQsZT0tMSxnPS0xLGY9MCxtPTA7aWYoQXJyYXkuaXNBcnJheShhKXx8TShhKXx8bWEoYSkpYj1hO2Vsc2UgaWYoXCJkYXRhXCJpbiBhJiYoYj1hLmRhdGEpLFwidXNhZ2VcImluIGEmJihjPWpiW2EudXNhZ2VdKSxcInByaW1pdGl2ZVwiaW4gYSYmKGU9U2FbYS5wcmltaXRpdmVdKSxcImNvdW50XCJpbiBhJiYoZz1hLmNvdW50fDApLFwidHlwZVwiaW4gYSYmKG09cVthLnR5cGVdKSxcImxlbmd0aFwiaW4gYSlmPWEubGVuZ3RofDA7ZWxzZSBpZihmPWcsNTEyMz09PW18fDUxMjI9PT1tKWYqPTI7ZWxzZSBpZig1MTI1PT09bXx8NTEyND09PW0pZio9NDtkKGwsYixjLGUsZyxmLG0pfWVsc2UgaCgpLGwucHJpbVR5cGU9NCxsLnZlcnRDb3VudD0wLGwudHlwZT01MTIxO3JldHVybiBrfXZhciBoPWMuY3JlYXRlKG51bGwsMzQ5NjMsITApLGw9bmV3IGcoaC5fYnVmZmVyKTtlLmVsZW1lbnRzQ291bnQrKztrKGEpO2suX3JlZ2xUeXBlPVwiZWxlbWVudHNcIjtcbmsuX2VsZW1lbnRzPWw7ay5zdWJkYXRhPWZ1bmN0aW9uKGEsYil7aC5zdWJkYXRhKGEsYik7cmV0dXJuIGt9O2suZGVzdHJveT1mdW5jdGlvbigpe24obCl9O3JldHVybiBrfSxjcmVhdGVTdHJlYW06ZnVuY3Rpb24oYSl7dmFyIGI9dC5wb3AoKTtifHwoYj1uZXcgZyhjLmNyZWF0ZShudWxsLDM0OTYzLCEwLCExKS5fYnVmZmVyKSk7ZChiLGEsMzUwNDAsLTEsLTEsMCwwKTtyZXR1cm4gYn0sZGVzdHJveVN0cmVhbTpmdW5jdGlvbihhKXt0LnB1c2goYSl9LGdldEVsZW1lbnRzOmZ1bmN0aW9uKGEpe3JldHVyblwiZnVuY3Rpb25cIj09PXR5cGVvZiBhJiZhLl9lbGVtZW50cyBpbnN0YW5jZW9mIGc/YS5fZWxlbWVudHM6bnVsbH0sY2xlYXI6ZnVuY3Rpb24oKXtTKGYpLmZvckVhY2gobil9fX1mdW5jdGlvbiBrYihhKXtmb3IodmFyIGI9eC5hbGxvY1R5cGUoNTEyMyxhLmxlbmd0aCksYz0wO2M8YS5sZW5ndGg7KytjKWlmKGlzTmFOKGFbY10pKWJbY109NjU1MzU7ZWxzZSBpZihJbmZpbml0eT09PVxuYVtjXSliW2NdPTMxNzQ0O2Vsc2UgaWYoLUluZmluaXR5PT09YVtjXSliW2NdPTY0NTEyO2Vsc2V7bGJbMF09YVtjXTt2YXIgZT1JYlswXSxnPWU+Pj4zMTw8MTUsZD0oZTw8MT4+PjI0KS0xMjcsZT1lPj4xMyYxMDIzO2JbY109LTI0PmQ/ZzotMTQ+ZD9nKyhlKzEwMjQ+Pi0xNC1kKToxNTxkP2crMzE3NDQ6ZysoZCsxNTw8MTApK2V9cmV0dXJuIGJ9ZnVuY3Rpb24gcGEoYSl7cmV0dXJuIEFycmF5LmlzQXJyYXkoYSl8fE0oYSl9ZnVuY3Rpb24gRWEoYSl7cmV0dXJuXCJbb2JqZWN0IFwiK2ErXCJdXCJ9ZnVuY3Rpb24gbWIoYSl7cmV0dXJuIEFycmF5LmlzQXJyYXkoYSkmJigwPT09YS5sZW5ndGh8fFwibnVtYmVyXCI9PT10eXBlb2YgYVswXSl9ZnVuY3Rpb24gbmIoYSl7cmV0dXJuIEFycmF5LmlzQXJyYXkoYSkmJjAhPT1hLmxlbmd0aCYmcGEoYVswXSk/ITA6ITF9ZnVuY3Rpb24gbmEoYSl7cmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhKX1mdW5jdGlvbiBUYShhKXtpZighYSlyZXR1cm4hMTtcbnZhciBiPW5hKGEpO3JldHVybiAwPD1KYi5pbmRleE9mKGIpPyEwOm1iKGEpfHxuYihhKXx8bWEoYSl9ZnVuY3Rpb24gb2IoYSxiKXszNjE5Mz09PWEudHlwZT8oYS5kYXRhPWtiKGIpLHguZnJlZVR5cGUoYikpOmEuZGF0YT1ifWZ1bmN0aW9uIEphKGEsYixjLGUsZyxkKXthPVwidW5kZWZpbmVkXCIhPT10eXBlb2YgeVthXT95W2FdOkxbYV0qcWFbYl07ZCYmKGEqPTYpO2lmKGcpe2ZvcihlPTA7MTw9YzspZSs9YSpjKmMsYy89MjtyZXR1cm4gZX1yZXR1cm4gYSpjKmV9ZnVuY3Rpb24gS2IoYSxiLGMsZSxnLGQsbil7ZnVuY3Rpb24gZigpe3RoaXMuZm9ybWF0PXRoaXMuaW50ZXJuYWxmb3JtYXQ9NjQwODt0aGlzLnR5cGU9NTEyMTt0aGlzLmZsaXBZPXRoaXMucHJlbXVsdGlwbHlBbHBoYT10aGlzLmNvbXByZXNzZWQ9ITE7dGhpcy51bnBhY2tBbGlnbm1lbnQ9MTt0aGlzLmNvbG9yU3BhY2U9Mzc0NDQ7dGhpcy5jaGFubmVscz10aGlzLmhlaWdodD10aGlzLndpZHRoPTB9ZnVuY3Rpb24gcihhLFxuYil7YS5pbnRlcm5hbGZvcm1hdD1iLmludGVybmFsZm9ybWF0O2EuZm9ybWF0PWIuZm9ybWF0O2EudHlwZT1iLnR5cGU7YS5jb21wcmVzc2VkPWIuY29tcHJlc3NlZDthLnByZW11bHRpcGx5QWxwaGE9Yi5wcmVtdWx0aXBseUFscGhhO2EuZmxpcFk9Yi5mbGlwWTthLnVucGFja0FsaWdubWVudD1iLnVucGFja0FsaWdubWVudDthLmNvbG9yU3BhY2U9Yi5jb2xvclNwYWNlO2Eud2lkdGg9Yi53aWR0aDthLmhlaWdodD1iLmhlaWdodDthLmNoYW5uZWxzPWIuY2hhbm5lbHN9ZnVuY3Rpb24gcShhLGIpe2lmKFwib2JqZWN0XCI9PT10eXBlb2YgYiYmYil7XCJwcmVtdWx0aXBseUFscGhhXCJpbiBiJiYoYS5wcmVtdWx0aXBseUFscGhhPWIucHJlbXVsdGlwbHlBbHBoYSk7XCJmbGlwWVwiaW4gYiYmKGEuZmxpcFk9Yi5mbGlwWSk7XCJhbGlnbm1lbnRcImluIGImJihhLnVucGFja0FsaWdubWVudD1iLmFsaWdubWVudCk7XCJjb2xvclNwYWNlXCJpbiBiJiYoYS5jb2xvclNwYWNlPXdhW2IuY29sb3JTcGFjZV0pO1xuXCJ0eXBlXCJpbiBiJiYoYS50eXBlPUdbYi50eXBlXSk7dmFyIGM9YS53aWR0aCxlPWEuaGVpZ2h0LGQ9YS5jaGFubmVscyxoPSExO1wic2hhcGVcImluIGI/KGM9Yi5zaGFwZVswXSxlPWIuc2hhcGVbMV0sMz09PWIuc2hhcGUubGVuZ3RoJiYoZD1iLnNoYXBlWzJdLGg9ITApKTooXCJyYWRpdXNcImluIGImJihjPWU9Yi5yYWRpdXMpLFwid2lkdGhcImluIGImJihjPWIud2lkdGgpLFwiaGVpZ2h0XCJpbiBiJiYoZT1iLmhlaWdodCksXCJjaGFubmVsc1wiaW4gYiYmKGQ9Yi5jaGFubmVscyxoPSEwKSk7YS53aWR0aD1jfDA7YS5oZWlnaHQ9ZXwwO2EuY2hhbm5lbHM9ZHwwO2M9ITE7XCJmb3JtYXRcImluIGImJihjPWIuZm9ybWF0LGU9YS5pbnRlcm5hbGZvcm1hdD1VW2NdLGEuZm9ybWF0PUxiW2VdLGMgaW4gRyYmIShcInR5cGVcImluIGIpJiYoYS50eXBlPUdbY10pLGMgaW4gVyYmKGEuY29tcHJlc3NlZD0hMCksYz0hMCk7IWgmJmM/YS5jaGFubmVscz1MW2EuZm9ybWF0XTpoJiYhYyYmYS5jaGFubmVscyE9PVxuTGFbYS5mb3JtYXRdJiYoYS5mb3JtYXQ9YS5pbnRlcm5hbGZvcm1hdD1MYVthLmNoYW5uZWxzXSl9fWZ1bmN0aW9uIHQoYil7YS5waXhlbFN0b3JlaSgzNzQ0MCxiLmZsaXBZKTthLnBpeGVsU3RvcmVpKDM3NDQxLGIucHJlbXVsdGlwbHlBbHBoYSk7YS5waXhlbFN0b3JlaSgzNzQ0MyxiLmNvbG9yU3BhY2UpO2EucGl4ZWxTdG9yZWkoMzMxNyxiLnVucGFja0FsaWdubWVudCl9ZnVuY3Rpb24gbSgpe2YuY2FsbCh0aGlzKTt0aGlzLnlPZmZzZXQ9dGhpcy54T2Zmc2V0PTA7dGhpcy5kYXRhPW51bGw7dGhpcy5uZWVkc0ZyZWU9ITE7dGhpcy5lbGVtZW50PW51bGw7dGhpcy5uZWVkc0NvcHk9ITF9ZnVuY3Rpb24gQyhhLGIpe3ZhciBjPW51bGw7VGEoYik/Yz1iOmImJihxKGEsYiksXCJ4XCJpbiBiJiYoYS54T2Zmc2V0PWIueHwwKSxcInlcImluIGImJihhLnlPZmZzZXQ9Yi55fDApLFRhKGIuZGF0YSkmJihjPWIuZGF0YSkpO2lmKGIuY29weSl7dmFyIGU9Zy52aWV3cG9ydFdpZHRoLGQ9Zy52aWV3cG9ydEhlaWdodDtcbmEud2lkdGg9YS53aWR0aHx8ZS1hLnhPZmZzZXQ7YS5oZWlnaHQ9YS5oZWlnaHR8fGQtYS55T2Zmc2V0O2EubmVlZHNDb3B5PSEwfWVsc2UgaWYoIWMpYS53aWR0aD1hLndpZHRofHwxLGEuaGVpZ2h0PWEuaGVpZ2h0fHwxLGEuY2hhbm5lbHM9YS5jaGFubmVsc3x8NDtlbHNlIGlmKE0oYykpYS5jaGFubmVscz1hLmNoYW5uZWxzfHw0LGEuZGF0YT1jLFwidHlwZVwiaW4gYnx8NTEyMSE9PWEudHlwZXx8KGEudHlwZT1JYVtPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYyldfDApO2Vsc2UgaWYobWIoYykpe2EuY2hhbm5lbHM9YS5jaGFubmVsc3x8NDtlPWM7ZD1lLmxlbmd0aDtzd2l0Y2goYS50eXBlKXtjYXNlIDUxMjE6Y2FzZSA1MTIzOmNhc2UgNTEyNTpjYXNlIDUxMjY6ZD14LmFsbG9jVHlwZShhLnR5cGUsZCk7ZC5zZXQoZSk7YS5kYXRhPWQ7YnJlYWs7Y2FzZSAzNjE5MzphLmRhdGE9a2IoZSl9YS5hbGlnbm1lbnQ9MTthLm5lZWRzRnJlZT0hMH1lbHNlIGlmKG1hKGMpKXtlPVxuYy5kYXRhO0FycmF5LmlzQXJyYXkoZSl8fDUxMjEhPT1hLnR5cGV8fChhLnR5cGU9SWFbT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGUpXXwwKTt2YXIgZD1jLnNoYXBlLGg9Yy5zdHJpZGUsZixsLHAsdzszPT09ZC5sZW5ndGg/KHA9ZFsyXSx3PWhbMl0pOnc9cD0xO2Y9ZFswXTtsPWRbMV07ZD1oWzBdO2g9aFsxXTthLmFsaWdubWVudD0xO2Eud2lkdGg9ZjthLmhlaWdodD1sO2EuY2hhbm5lbHM9cDthLmZvcm1hdD1hLmludGVybmFsZm9ybWF0PUxhW3BdO2EubmVlZHNGcmVlPSEwO2Y9dztjPWMub2Zmc2V0O3A9YS53aWR0aDt3PWEuaGVpZ2h0O2w9YS5jaGFubmVscztmb3IodmFyIHo9eC5hbGxvY1R5cGUoMzYxOTM9PT1hLnR5cGU/NTEyNjphLnR5cGUscCp3KmwpLEk9MCxmYT0wO2ZhPHc7KytmYSlmb3IodmFyIGdhPTA7Z2E8cDsrK2dhKWZvcih2YXIgeGE9MDt4YTxsOysreGEpeltJKytdPWVbZCpnYStoKmZhK2YqeGErY107b2IoYSx6KX1lbHNlIGlmKG5hKGMpPT09XG5VYXx8bmEoYyk9PT1wYiluYShjKT09PVVhP2EuZWxlbWVudD1jOmEuZWxlbWVudD1jLmNhbnZhcyxhLndpZHRoPWEuZWxlbWVudC53aWR0aCxhLmhlaWdodD1hLmVsZW1lbnQuaGVpZ2h0LGEuY2hhbm5lbHM9NDtlbHNlIGlmKG5hKGMpPT09cWIpYS5lbGVtZW50PWMsYS53aWR0aD1jLndpZHRoLGEuaGVpZ2h0PWMuaGVpZ2h0LGEuY2hhbm5lbHM9NDtlbHNlIGlmKG5hKGMpPT09cmIpYS5lbGVtZW50PWMsYS53aWR0aD1jLm5hdHVyYWxXaWR0aCxhLmhlaWdodD1jLm5hdHVyYWxIZWlnaHQsYS5jaGFubmVscz00O2Vsc2UgaWYobmEoYyk9PT1zYilhLmVsZW1lbnQ9YyxhLndpZHRoPWMudmlkZW9XaWR0aCxhLmhlaWdodD1jLnZpZGVvSGVpZ2h0LGEuY2hhbm5lbHM9NDtlbHNlIGlmKG5iKGMpKXtlPWEud2lkdGh8fGNbMF0ubGVuZ3RoO2Q9YS5oZWlnaHR8fGMubGVuZ3RoO2g9YS5jaGFubmVscztoPXBhKGNbMF1bMF0pP2h8fGNbMF1bMF0ubGVuZ3RoOmh8fDE7Zj1NYS5zaGFwZShjKTtcbnA9MTtmb3Iodz0wO3c8Zi5sZW5ndGg7Kyt3KXAqPWZbd107cD14LmFsbG9jVHlwZSgzNjE5Mz09PWEudHlwZT81MTI2OmEudHlwZSxwKTtNYS5mbGF0dGVuKGMsZixcIlwiLHApO29iKGEscCk7YS5hbGlnbm1lbnQ9MTthLndpZHRoPWU7YS5oZWlnaHQ9ZDthLmNoYW5uZWxzPWg7YS5mb3JtYXQ9YS5pbnRlcm5hbGZvcm1hdD1MYVtoXTthLm5lZWRzRnJlZT0hMH19ZnVuY3Rpb24gayhiLGMsZCxoLGYpe3ZhciBnPWIuZWxlbWVudCxsPWIuZGF0YSxrPWIuaW50ZXJuYWxmb3JtYXQscD1iLmZvcm1hdCx3PWIudHlwZSx6PWIud2lkdGgsST1iLmhlaWdodDt0KGIpO2c/YS50ZXhTdWJJbWFnZTJEKGMsZixkLGgscCx3LGcpOmIuY29tcHJlc3NlZD9hLmNvbXByZXNzZWRUZXhTdWJJbWFnZTJEKGMsZixkLGgsayx6LEksbCk6Yi5uZWVkc0NvcHk/KGUoKSxhLmNvcHlUZXhTdWJJbWFnZTJEKGMsZixkLGgsYi54T2Zmc2V0LGIueU9mZnNldCx6LEkpKTphLnRleFN1YkltYWdlMkQoYyxmLGQsaCx6LFxuSSxwLHcsbCl9ZnVuY3Rpb24gaCgpe3JldHVybiBQLnBvcCgpfHxuZXcgbX1mdW5jdGlvbiBsKGEpe2EubmVlZHNGcmVlJiZ4LmZyZWVUeXBlKGEuZGF0YSk7bS5jYWxsKGEpO1AucHVzaChhKX1mdW5jdGlvbiB1KCl7Zi5jYWxsKHRoaXMpO3RoaXMuZ2VuTWlwbWFwcz0hMTt0aGlzLm1pcG1hcEhpbnQ9NDM1Mjt0aGlzLm1pcG1hc2s9MDt0aGlzLmltYWdlcz1BcnJheSgxNil9ZnVuY3Rpb24gdihhLGIsYyl7dmFyIGQ9YS5pbWFnZXNbMF09aCgpO2EubWlwbWFzaz0xO2Qud2lkdGg9YS53aWR0aD1iO2QuaGVpZ2h0PWEuaGVpZ2h0PWM7ZC5jaGFubmVscz1hLmNoYW5uZWxzPTR9ZnVuY3Rpb24gTihhLGIpe3ZhciBjPW51bGw7aWYoVGEoYikpYz1hLmltYWdlc1swXT1oKCkscihjLGEpLEMoYyxiKSxhLm1pcG1hc2s9MTtlbHNlIGlmKHEoYSxiKSxBcnJheS5pc0FycmF5KGIubWlwbWFwKSlmb3IodmFyIGQ9Yi5taXBtYXAsZT0wO2U8ZC5sZW5ndGg7KytlKWM9YS5pbWFnZXNbZV09aCgpLFxucihjLGEpLGMud2lkdGg+Pj1lLGMuaGVpZ2h0Pj49ZSxDKGMsZFtlXSksYS5taXBtYXNrfD0xPDxlO2Vsc2UgYz1hLmltYWdlc1swXT1oKCkscihjLGEpLEMoYyxiKSxhLm1pcG1hc2s9MTtyKGEsYS5pbWFnZXNbMF0pfWZ1bmN0aW9uIEIoYixjKXtmb3IodmFyIGQ9Yi5pbWFnZXMsaD0wO2g8ZC5sZW5ndGgmJmRbaF07KytoKXt2YXIgZj1kW2hdLGc9YyxsPWgsaz1mLmVsZW1lbnQscD1mLmRhdGEsdz1mLmludGVybmFsZm9ybWF0LHo9Zi5mb3JtYXQsST1mLnR5cGUsZmE9Zi53aWR0aCxnYT1mLmhlaWdodCx4YT1mLmNoYW5uZWxzO3QoZik7az9hLnRleEltYWdlMkQoZyxsLHoseixJLGspOmYuY29tcHJlc3NlZD9hLmNvbXByZXNzZWRUZXhJbWFnZTJEKGcsbCx3LGZhLGdhLDAscCk6Zi5uZWVkc0NvcHk/KGUoKSxhLmNvcHlUZXhJbWFnZTJEKGcsbCx6LGYueE9mZnNldCxmLnlPZmZzZXQsZmEsZ2EsMCkpOigoZj0hcCkmJihwPXguemVyby5hbGxvY1R5cGUoSSxmYSpnYSp4YSkpLGEudGV4SW1hZ2UyRChnLFxubCx6LGZhLGdhLDAseixJLHApLGYmJnAmJnguemVyby5mcmVlVHlwZShwKSl9fWZ1bmN0aW9uIEQoKXt2YXIgYT10Yi5wb3AoKXx8bmV3IHU7Zi5jYWxsKGEpO2Zvcih2YXIgYj1hLm1pcG1hc2s9MDsxNj5iOysrYilhLmltYWdlc1tiXT1udWxsO3JldHVybiBhfWZ1bmN0aW9uIGliKGEpe2Zvcih2YXIgYj1hLmltYWdlcyxjPTA7YzxiLmxlbmd0aDsrK2MpYltjXSYmbChiW2NdKSxiW2NdPW51bGw7dGIucHVzaChhKX1mdW5jdGlvbiB5KCl7dGhpcy5tYWdGaWx0ZXI9dGhpcy5taW5GaWx0ZXI9OTcyODt0aGlzLndyYXBUPXRoaXMud3JhcFM9MzMwNzE7dGhpcy5hbmlzb3Ryb3BpYz0xO3RoaXMuZ2VuTWlwbWFwcz0hMTt0aGlzLm1pcG1hcEhpbnQ9NDM1Mn1mdW5jdGlvbiBPKGEsYil7XCJtaW5cImluIGImJihhLm1pbkZpbHRlcj1WYVtiLm1pbl0sMDw9TWIuaW5kZXhPZihhLm1pbkZpbHRlcikmJiEoXCJmYWNlc1wiaW4gYikmJihhLmdlbk1pcG1hcHM9ITApKTtcIm1hZ1wiaW4gYiYmKGEubWFnRmlsdGVyPVxuVltiLm1hZ10pO3ZhciBjPWEud3JhcFMsZD1hLndyYXBUO2lmKFwid3JhcFwiaW4gYil7dmFyIGU9Yi53cmFwO1wic3RyaW5nXCI9PT10eXBlb2YgZT9jPWQ9S1tlXTpBcnJheS5pc0FycmF5KGUpJiYoYz1LW2VbMF1dLGQ9S1tlWzFdXSl9ZWxzZVwid3JhcFNcImluIGImJihjPUtbYi53cmFwU10pLFwid3JhcFRcImluIGImJihkPUtbYi53cmFwVF0pO2Eud3JhcFM9YzthLndyYXBUPWQ7XCJhbmlzb3Ryb3BpY1wiaW4gYiYmKGEuYW5pc290cm9waWM9Yi5hbmlzb3Ryb3BpYyk7aWYoXCJtaXBtYXBcImluIGIpe2M9ITE7c3dpdGNoKHR5cGVvZiBiLm1pcG1hcCl7Y2FzZSBcInN0cmluZ1wiOmEubWlwbWFwSGludD11YVtiLm1pcG1hcF07Yz1hLmdlbk1pcG1hcHM9ITA7YnJlYWs7Y2FzZSBcImJvb2xlYW5cIjpjPWEuZ2VuTWlwbWFwcz1iLm1pcG1hcDticmVhaztjYXNlIFwib2JqZWN0XCI6YS5nZW5NaXBtYXBzPSExLGM9ITB9IWN8fFwibWluXCJpbiBifHwoYS5taW5GaWx0ZXI9OTk4NCl9fWZ1bmN0aW9uIFIoYyxkKXthLnRleFBhcmFtZXRlcmkoZCxcbjEwMjQxLGMubWluRmlsdGVyKTthLnRleFBhcmFtZXRlcmkoZCwxMDI0MCxjLm1hZ0ZpbHRlcik7YS50ZXhQYXJhbWV0ZXJpKGQsMTAyNDIsYy53cmFwUyk7YS50ZXhQYXJhbWV0ZXJpKGQsMTAyNDMsYy53cmFwVCk7Yi5leHRfdGV4dHVyZV9maWx0ZXJfYW5pc290cm9waWMmJmEudGV4UGFyYW1ldGVyaShkLDM0MDQ2LGMuYW5pc290cm9waWMpO2MuZ2VuTWlwbWFwcyYmKGEuaGludCgzMzE3MCxjLm1pcG1hcEhpbnQpLGEuZ2VuZXJhdGVNaXBtYXAoZCkpfWZ1bmN0aW9uIEYoYil7Zi5jYWxsKHRoaXMpO3RoaXMubWlwbWFzaz0wO3RoaXMuaW50ZXJuYWxmb3JtYXQ9NjQwODt0aGlzLmlkPXlhKys7dGhpcy5yZWZDb3VudD0xO3RoaXMudGFyZ2V0PWI7dGhpcy50ZXh0dXJlPWEuY3JlYXRlVGV4dHVyZSgpO3RoaXMudW5pdD0tMTt0aGlzLmJpbmRDb3VudD0wO3RoaXMudGV4SW5mbz1uZXcgeTtuLnByb2ZpbGUmJih0aGlzLnN0YXRzPXtzaXplOjB9KX1mdW5jdGlvbiBUKGIpe2EuYWN0aXZlVGV4dHVyZSgzMzk4NCk7XG5hLmJpbmRUZXh0dXJlKGIudGFyZ2V0LGIudGV4dHVyZSl9ZnVuY3Rpb24gQWEoKXt2YXIgYj1oYVswXTtiP2EuYmluZFRleHR1cmUoYi50YXJnZXQsYi50ZXh0dXJlKTphLmJpbmRUZXh0dXJlKDM1NTMsbnVsbCl9ZnVuY3Rpb24gQShiKXt2YXIgYz1iLnRleHR1cmUsZT1iLnVuaXQsaD1iLnRhcmdldDswPD1lJiYoYS5hY3RpdmVUZXh0dXJlKDMzOTg0K2UpLGEuYmluZFRleHR1cmUoaCxudWxsKSxoYVtlXT1udWxsKTthLmRlbGV0ZVRleHR1cmUoYyk7Yi50ZXh0dXJlPW51bGw7Yi5wYXJhbXM9bnVsbDtiLnBpeGVscz1udWxsO2IucmVmQ291bnQ9MDtkZWxldGUgWFtiLmlkXTtkLnRleHR1cmVDb3VudC0tfXZhciB1YT17XCJkb24ndCBjYXJlXCI6NDM1MixcImRvbnQgY2FyZVwiOjQzNTIsbmljZTo0MzU0LGZhc3Q6NDM1M30sSz17cmVwZWF0OjEwNDk3LGNsYW1wOjMzMDcxLG1pcnJvcjozMzY0OH0sVj17bmVhcmVzdDo5NzI4LGxpbmVhcjo5NzI5fSxWYT1FKHttaXBtYXA6OTk4NyxcIm5lYXJlc3QgbWlwbWFwIG5lYXJlc3RcIjo5OTg0LFxuXCJsaW5lYXIgbWlwbWFwIG5lYXJlc3RcIjo5OTg1LFwibmVhcmVzdCBtaXBtYXAgbGluZWFyXCI6OTk4NixcImxpbmVhciBtaXBtYXAgbGluZWFyXCI6OTk4N30sViksd2E9e25vbmU6MCxicm93c2VyOjM3NDQ0fSxHPXt1aW50ODo1MTIxLHJnYmE0OjMyODE5LHJnYjU2NTozMzYzNSxcInJnYjUgYTFcIjozMjgyMH0sVT17YWxwaGE6NjQwNixsdW1pbmFuY2U6NjQwOSxcImx1bWluYW5jZSBhbHBoYVwiOjY0MTAscmdiOjY0MDcscmdiYTo2NDA4LHJnYmE0OjMyODU0LFwicmdiNSBhMVwiOjMyODU1LHJnYjU2NTozNjE5NH0sVz17fTtiLmV4dF9zcmdiJiYoVS5zcmdiPTM1OTA0LFUuc3JnYmE9MzU5MDYpO2Iub2VzX3RleHR1cmVfZmxvYXQmJihHLmZsb2F0MzI9R1tcImZsb2F0XCJdPTUxMjYpO2Iub2VzX3RleHR1cmVfaGFsZl9mbG9hdCYmKEcuZmxvYXQxNj1HW1wiaGFsZiBmbG9hdFwiXT0zNjE5Myk7Yi53ZWJnbF9kZXB0aF90ZXh0dXJlJiYoRShVLHtkZXB0aDo2NDAyLFwiZGVwdGggc3RlbmNpbFwiOjM0MDQxfSksXG5FKEcse3VpbnQxNjo1MTIzLHVpbnQzMjo1MTI1LFwiZGVwdGggc3RlbmNpbFwiOjM0MDQyfSkpO2Iud2ViZ2xfY29tcHJlc3NlZF90ZXh0dXJlX3MzdGMmJkUoVyx7XCJyZ2IgczN0YyBkeHQxXCI6MzM3NzYsXCJyZ2JhIHMzdGMgZHh0MVwiOjMzNzc3LFwicmdiYSBzM3RjIGR4dDNcIjozMzc3OCxcInJnYmEgczN0YyBkeHQ1XCI6MzM3Nzl9KTtiLndlYmdsX2NvbXByZXNzZWRfdGV4dHVyZV9hdGMmJkUoVyx7XCJyZ2IgYXRjXCI6MzU5ODYsXCJyZ2JhIGF0YyBleHBsaWNpdCBhbHBoYVwiOjM1OTg3LFwicmdiYSBhdGMgaW50ZXJwb2xhdGVkIGFscGhhXCI6MzQ3OTh9KTtiLndlYmdsX2NvbXByZXNzZWRfdGV4dHVyZV9wdnJ0YyYmRShXLHtcInJnYiBwdnJ0YyA0YnBwdjFcIjozNTg0MCxcInJnYiBwdnJ0YyAyYnBwdjFcIjozNTg0MSxcInJnYmEgcHZydGMgNGJwcHYxXCI6MzU4NDIsXCJyZ2JhIHB2cnRjIDJicHB2MVwiOjM1ODQzfSk7Yi53ZWJnbF9jb21wcmVzc2VkX3RleHR1cmVfZXRjMSYmKFdbXCJyZ2IgZXRjMVwiXT0zNjE5Nik7XG52YXIgTmI9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYS5nZXRQYXJhbWV0ZXIoMzQ0NjcpKTtPYmplY3Qua2V5cyhXKS5mb3JFYWNoKGZ1bmN0aW9uKGEpe3ZhciBiPVdbYV07MDw9TmIuaW5kZXhPZihiKSYmKFVbYV09Yil9KTt2YXIgY2E9T2JqZWN0LmtleXMoVSk7Yy50ZXh0dXJlRm9ybWF0cz1jYTt2YXIgSj1bXTtPYmplY3Qua2V5cyhVKS5mb3JFYWNoKGZ1bmN0aW9uKGEpe0pbVVthXV09YX0pO3ZhciBkYT1bXTtPYmplY3Qua2V5cyhHKS5mb3JFYWNoKGZ1bmN0aW9uKGEpe2RhW0dbYV1dPWF9KTt2YXIgb2E9W107T2JqZWN0LmtleXMoVikuZm9yRWFjaChmdW5jdGlvbihhKXtvYVtWW2FdXT1hfSk7dmFyIHphPVtdO09iamVjdC5rZXlzKFZhKS5mb3JFYWNoKGZ1bmN0aW9uKGEpe3phW1ZhW2FdXT1hfSk7dmFyIGthPVtdO09iamVjdC5rZXlzKEspLmZvckVhY2goZnVuY3Rpb24oYSl7a2FbS1thXV09YX0pO3ZhciBMYj1jYS5yZWR1Y2UoZnVuY3Rpb24oYSxiKXt2YXIgYz1cblVbYl07NjQwOT09PWN8fDY0MDY9PT1jfHw2NDA5PT09Y3x8NjQxMD09PWN8fDY0MDI9PT1jfHwzNDA0MT09PWM/YVtjXT1jOjMyODU1PT09Y3x8MDw9Yi5pbmRleE9mKFwicmdiYVwiKT9hW2NdPTY0MDg6YVtjXT02NDA3O3JldHVybiBhfSx7fSksUD1bXSx0Yj1bXSx5YT0wLFg9e30sZWE9Yy5tYXhUZXh0dXJlVW5pdHMsaGE9QXJyYXkoZWEpLm1hcChmdW5jdGlvbigpe3JldHVybiBudWxsfSk7RShGLnByb3RvdHlwZSx7YmluZDpmdW5jdGlvbigpe3RoaXMuYmluZENvdW50Kz0xO3ZhciBiPXRoaXMudW5pdDtpZigwPmIpe2Zvcih2YXIgYz0wO2M8ZWE7KytjKXt2YXIgZT1oYVtjXTtpZihlKXtpZigwPGUuYmluZENvdW50KWNvbnRpbnVlO2UudW5pdD0tMX1oYVtjXT10aGlzO2I9YzticmVha31uLnByb2ZpbGUmJmQubWF4VGV4dHVyZVVuaXRzPGIrMSYmKGQubWF4VGV4dHVyZVVuaXRzPWIrMSk7dGhpcy51bml0PWI7YS5hY3RpdmVUZXh0dXJlKDMzOTg0K2IpO2EuYmluZFRleHR1cmUodGhpcy50YXJnZXQsXG50aGlzLnRleHR1cmUpfXJldHVybiBifSx1bmJpbmQ6ZnVuY3Rpb24oKXstLXRoaXMuYmluZENvdW50fSxkZWNSZWY6ZnVuY3Rpb24oKXswPj0tLXRoaXMucmVmQ291bnQmJkEodGhpcyl9fSk7bi5wcm9maWxlJiYoZC5nZXRUb3RhbFRleHR1cmVTaXplPWZ1bmN0aW9uKCl7dmFyIGE9MDtPYmplY3Qua2V5cyhYKS5mb3JFYWNoKGZ1bmN0aW9uKGIpe2ErPVhbYl0uc3RhdHMuc2l6ZX0pO3JldHVybiBhfSk7cmV0dXJue2NyZWF0ZTJEOmZ1bmN0aW9uKGIsYyl7ZnVuY3Rpb24gZShhLGIpe3ZhciBjPWYudGV4SW5mbzt5LmNhbGwoYyk7dmFyIGQ9RCgpO1wibnVtYmVyXCI9PT10eXBlb2YgYT9cIm51bWJlclwiPT09dHlwZW9mIGI/dihkLGF8MCxifDApOnYoZCxhfDAsYXwwKTphPyhPKGMsYSksTihkLGEpKTp2KGQsMSwxKTtjLmdlbk1pcG1hcHMmJihkLm1pcG1hc2s9KGQud2lkdGg8PDEpLTEpO2YubWlwbWFzaz1kLm1pcG1hc2s7cihmLGQpO2YuaW50ZXJuYWxmb3JtYXQ9ZC5pbnRlcm5hbGZvcm1hdDtcbmUud2lkdGg9ZC53aWR0aDtlLmhlaWdodD1kLmhlaWdodDtUKGYpO0IoZCwzNTUzKTtSKGMsMzU1Myk7QWEoKTtpYihkKTtuLnByb2ZpbGUmJihmLnN0YXRzLnNpemU9SmEoZi5pbnRlcm5hbGZvcm1hdCxmLnR5cGUsZC53aWR0aCxkLmhlaWdodCxjLmdlbk1pcG1hcHMsITEpKTtlLmZvcm1hdD1KW2YuaW50ZXJuYWxmb3JtYXRdO2UudHlwZT1kYVtmLnR5cGVdO2UubWFnPW9hW2MubWFnRmlsdGVyXTtlLm1pbj16YVtjLm1pbkZpbHRlcl07ZS53cmFwUz1rYVtjLndyYXBTXTtlLndyYXBUPWthW2Mud3JhcFRdO3JldHVybiBlfXZhciBmPW5ldyBGKDM1NTMpO1hbZi5pZF09ZjtkLnRleHR1cmVDb3VudCsrO2UoYixjKTtlLnN1YmltYWdlPWZ1bmN0aW9uKGEsYixjLGQpe2J8PTA7Y3w9MDtkfD0wO3ZhciBwPWgoKTtyKHAsZik7cC53aWR0aD0wO3AuaGVpZ2h0PTA7QyhwLGEpO3Aud2lkdGg9cC53aWR0aHx8KGYud2lkdGg+PmQpLWI7cC5oZWlnaHQ9cC5oZWlnaHR8fChmLmhlaWdodD4+ZCktXG5jO1QoZik7ayhwLDM1NTMsYixjLGQpO0FhKCk7bChwKTtyZXR1cm4gZX07ZS5yZXNpemU9ZnVuY3Rpb24oYixjKXt2YXIgZD1ifDAsaD1jfDB8fGQ7aWYoZD09PWYud2lkdGgmJmg9PT1mLmhlaWdodClyZXR1cm4gZTtlLndpZHRoPWYud2lkdGg9ZDtlLmhlaWdodD1mLmhlaWdodD1oO1QoZik7Zm9yKHZhciBwLHc9Zi5jaGFubmVscyx6PWYudHlwZSxJPTA7Zi5taXBtYXNrPj5JOysrSSl7dmFyIGZhPWQ+PkksZ2E9aD4+STtpZighZmF8fCFnYSlicmVhaztwPXguemVyby5hbGxvY1R5cGUoeixmYSpnYSp3KTthLnRleEltYWdlMkQoMzU1MyxJLGYuZm9ybWF0LGZhLGdhLDAsZi5mb3JtYXQsZi50eXBlLHApO3AmJnguemVyby5mcmVlVHlwZShwKX1BYSgpO24ucHJvZmlsZSYmKGYuc3RhdHMuc2l6ZT1KYShmLmludGVybmFsZm9ybWF0LGYudHlwZSxkLGgsITEsITEpKTtyZXR1cm4gZX07ZS5fcmVnbFR5cGU9XCJ0ZXh0dXJlMmRcIjtlLl90ZXh0dXJlPWY7bi5wcm9maWxlJiYoZS5zdGF0cz1cbmYuc3RhdHMpO2UuZGVzdHJveT1mdW5jdGlvbigpe2YuZGVjUmVmKCl9O3JldHVybiBlfSxjcmVhdGVDdWJlOmZ1bmN0aW9uKGIsYyxlLGYsZyx1YSl7ZnVuY3Rpb24gQShhLGIsYyxkLGUsZil7dmFyIEgsWT1tLnRleEluZm87eS5jYWxsKFkpO2ZvcihIPTA7Nj5IOysrSClwW0hdPUQoKTtpZihcIm51bWJlclwiPT09dHlwZW9mIGF8fCFhKWZvcihhPWF8MHx8MSxIPTA7Nj5IOysrSCl2KHBbSF0sYSxhKTtlbHNlIGlmKFwib2JqZWN0XCI9PT10eXBlb2YgYSlpZihiKU4ocFswXSxhKSxOKHBbMV0sYiksTihwWzJdLGMpLE4ocFszXSxkKSxOKHBbNF0sZSksTihwWzVdLGYpO2Vsc2UgaWYoTyhZLGEpLHEobSxhKSxcImZhY2VzXCJpbiBhKWZvcihhPWEuZmFjZXMsSD0wOzY+SDsrK0gpcihwW0hdLG0pLE4ocFtIXSxhW0hdKTtlbHNlIGZvcihIPTA7Nj5IOysrSClOKHBbSF0sYSk7cihtLHBbMF0pO20ubWlwbWFzaz1ZLmdlbk1pcG1hcHM/KHBbMF0ud2lkdGg8PDEpLTE6cFswXS5taXBtYXNrO20uaW50ZXJuYWxmb3JtYXQ9XG5wWzBdLmludGVybmFsZm9ybWF0O0Eud2lkdGg9cFswXS53aWR0aDtBLmhlaWdodD1wWzBdLmhlaWdodDtUKG0pO2ZvcihIPTA7Nj5IOysrSClCKHBbSF0sMzQwNjkrSCk7UihZLDM0MDY3KTtBYSgpO24ucHJvZmlsZSYmKG0uc3RhdHMuc2l6ZT1KYShtLmludGVybmFsZm9ybWF0LG0udHlwZSxBLndpZHRoLEEuaGVpZ2h0LFkuZ2VuTWlwbWFwcywhMCkpO0EuZm9ybWF0PUpbbS5pbnRlcm5hbGZvcm1hdF07QS50eXBlPWRhW20udHlwZV07QS5tYWc9b2FbWS5tYWdGaWx0ZXJdO0EubWluPXphW1kubWluRmlsdGVyXTtBLndyYXBTPWthW1kud3JhcFNdO0Eud3JhcFQ9a2FbWS53cmFwVF07Zm9yKEg9MDs2Pkg7KytIKWliKHBbSF0pO3JldHVybiBBfXZhciBtPW5ldyBGKDM0MDY3KTtYW20uaWRdPW07ZC5jdWJlQ291bnQrKzt2YXIgcD1BcnJheSg2KTtBKGIsYyxlLGYsZyx1YSk7QS5zdWJpbWFnZT1mdW5jdGlvbihhLGIsYyxwLGQpe2N8PTA7cHw9MDtkfD0wO3ZhciBlPWgoKTtyKGUsbSk7XG5lLndpZHRoPTA7ZS5oZWlnaHQ9MDtDKGUsYik7ZS53aWR0aD1lLndpZHRofHwobS53aWR0aD4+ZCktYztlLmhlaWdodD1lLmhlaWdodHx8KG0uaGVpZ2h0Pj5kKS1wO1QobSk7ayhlLDM0MDY5K2EsYyxwLGQpO0FhKCk7bChlKTtyZXR1cm4gQX07QS5yZXNpemU9ZnVuY3Rpb24oYil7Ynw9MDtpZihiIT09bS53aWR0aCl7QS53aWR0aD1tLndpZHRoPWI7QS5oZWlnaHQ9bS5oZWlnaHQ9YjtUKG0pO2Zvcih2YXIgYz0wOzY+YzsrK2MpZm9yKHZhciBwPTA7bS5taXBtYXNrPj5wOysrcClhLnRleEltYWdlMkQoMzQwNjkrYyxwLG0uZm9ybWF0LGI+PnAsYj4+cCwwLG0uZm9ybWF0LG0udHlwZSxudWxsKTtBYSgpO24ucHJvZmlsZSYmKG0uc3RhdHMuc2l6ZT1KYShtLmludGVybmFsZm9ybWF0LG0udHlwZSxBLndpZHRoLEEuaGVpZ2h0LCExLCEwKSk7cmV0dXJuIEF9fTtBLl9yZWdsVHlwZT1cInRleHR1cmVDdWJlXCI7QS5fdGV4dHVyZT1tO24ucHJvZmlsZSYmKEEuc3RhdHM9bS5zdGF0cyk7QS5kZXN0cm95PVxuZnVuY3Rpb24oKXttLmRlY1JlZigpfTtyZXR1cm4gQX0sY2xlYXI6ZnVuY3Rpb24oKXtmb3IodmFyIGI9MDtiPGVhOysrYilhLmFjdGl2ZVRleHR1cmUoMzM5ODQrYiksYS5iaW5kVGV4dHVyZSgzNTUzLG51bGwpLGhhW2JdPW51bGw7UyhYKS5mb3JFYWNoKEEpO2QuY3ViZUNvdW50PTA7ZC50ZXh0dXJlQ291bnQ9MH0sZ2V0VGV4dHVyZTpmdW5jdGlvbihhKXtyZXR1cm4gbnVsbH0scmVzdG9yZTpmdW5jdGlvbigpe2Zvcih2YXIgYj0wO2I8ZWE7KytiKXt2YXIgYz1oYVtiXTtjJiYoYy5iaW5kQ291bnQ9MCxjLnVuaXQ9LTEsaGFbYl09bnVsbCl9UyhYKS5mb3JFYWNoKGZ1bmN0aW9uKGIpe2IudGV4dHVyZT1hLmNyZWF0ZVRleHR1cmUoKTthLmJpbmRUZXh0dXJlKGIudGFyZ2V0LGIudGV4dHVyZSk7Zm9yKHZhciBjPTA7MzI+YzsrK2MpaWYoMCE9PShiLm1pcG1hc2smMTw8YykpaWYoMzU1Mz09PWIudGFyZ2V0KWEudGV4SW1hZ2UyRCgzNTUzLGMsYi5pbnRlcm5hbGZvcm1hdCxiLndpZHRoPj5cbmMsYi5oZWlnaHQ+PmMsMCxiLmludGVybmFsZm9ybWF0LGIudHlwZSxudWxsKTtlbHNlIGZvcih2YXIgZD0wOzY+ZDsrK2QpYS50ZXhJbWFnZTJEKDM0MDY5K2QsYyxiLmludGVybmFsZm9ybWF0LGIud2lkdGg+PmMsYi5oZWlnaHQ+PmMsMCxiLmludGVybmFsZm9ybWF0LGIudHlwZSxudWxsKTtSKGIudGV4SW5mbyxiLnRhcmdldCl9KX19fWZ1bmN0aW9uIE9iKGEsYixjLGUsZyxkKXtmdW5jdGlvbiBuKGEsYixjKXt0aGlzLnRhcmdldD1hO3RoaXMudGV4dHVyZT1iO3RoaXMucmVuZGVyYnVmZmVyPWM7dmFyIGQ9YT0wO2I/KGE9Yi53aWR0aCxkPWIuaGVpZ2h0KTpjJiYoYT1jLndpZHRoLGQ9Yy5oZWlnaHQpO3RoaXMud2lkdGg9YTt0aGlzLmhlaWdodD1kfWZ1bmN0aW9uIGYoYSl7YSYmKGEudGV4dHVyZSYmYS50ZXh0dXJlLl90ZXh0dXJlLmRlY1JlZigpLGEucmVuZGVyYnVmZmVyJiZhLnJlbmRlcmJ1ZmZlci5fcmVuZGVyYnVmZmVyLmRlY1JlZigpKX1mdW5jdGlvbiByKGEsYixjKXthJiZcbihhLnRleHR1cmU/YS50ZXh0dXJlLl90ZXh0dXJlLnJlZkNvdW50Kz0xOmEucmVuZGVyYnVmZmVyLl9yZW5kZXJidWZmZXIucmVmQ291bnQrPTEpfWZ1bmN0aW9uIHEoYixjKXtjJiYoYy50ZXh0dXJlP2EuZnJhbWVidWZmZXJUZXh0dXJlMkQoMzYxNjAsYixjLnRhcmdldCxjLnRleHR1cmUuX3RleHR1cmUudGV4dHVyZSwwKTphLmZyYW1lYnVmZmVyUmVuZGVyYnVmZmVyKDM2MTYwLGIsMzYxNjEsYy5yZW5kZXJidWZmZXIuX3JlbmRlcmJ1ZmZlci5yZW5kZXJidWZmZXIpKX1mdW5jdGlvbiB0KGEpe3ZhciBiPTM1NTMsYz1udWxsLGQ9bnVsbCxlPWE7XCJvYmplY3RcIj09PXR5cGVvZiBhJiYoZT1hLmRhdGEsXCJ0YXJnZXRcImluIGEmJihiPWEudGFyZ2V0fDApKTthPWUuX3JlZ2xUeXBlO1widGV4dHVyZTJkXCI9PT1hP2M9ZTpcInRleHR1cmVDdWJlXCI9PT1hP2M9ZTpcInJlbmRlcmJ1ZmZlclwiPT09YSYmKGQ9ZSxiPTM2MTYxKTtyZXR1cm4gbmV3IG4oYixjLGQpfWZ1bmN0aW9uIG0oYSxiLGMsZCxcbmYpe2lmKGMpcmV0dXJuIGE9ZS5jcmVhdGUyRCh7d2lkdGg6YSxoZWlnaHQ6Yixmb3JtYXQ6ZCx0eXBlOmZ9KSxhLl90ZXh0dXJlLnJlZkNvdW50PTAsbmV3IG4oMzU1MyxhLG51bGwpO2E9Zy5jcmVhdGUoe3dpZHRoOmEsaGVpZ2h0OmIsZm9ybWF0OmR9KTthLl9yZW5kZXJidWZmZXIucmVmQ291bnQ9MDtyZXR1cm4gbmV3IG4oMzYxNjEsbnVsbCxhKX1mdW5jdGlvbiBDKGEpe3JldHVybiBhJiYoYS50ZXh0dXJlfHxhLnJlbmRlcmJ1ZmZlcil9ZnVuY3Rpb24gayhhLGIsYyl7YSYmKGEudGV4dHVyZT9hLnRleHR1cmUucmVzaXplKGIsYyk6YS5yZW5kZXJidWZmZXImJmEucmVuZGVyYnVmZmVyLnJlc2l6ZShiLGMpLGEud2lkdGg9YixhLmhlaWdodD1jKX1mdW5jdGlvbiBoKCl7dGhpcy5pZD1PKys7Ult0aGlzLmlkXT10aGlzO3RoaXMuZnJhbWVidWZmZXI9YS5jcmVhdGVGcmFtZWJ1ZmZlcigpO3RoaXMuaGVpZ2h0PXRoaXMud2lkdGg9MDt0aGlzLmNvbG9yQXR0YWNobWVudHM9W107dGhpcy5kZXB0aFN0ZW5jaWxBdHRhY2htZW50PVxudGhpcy5zdGVuY2lsQXR0YWNobWVudD10aGlzLmRlcHRoQXR0YWNobWVudD1udWxsfWZ1bmN0aW9uIGwoYSl7YS5jb2xvckF0dGFjaG1lbnRzLmZvckVhY2goZik7ZihhLmRlcHRoQXR0YWNobWVudCk7ZihhLnN0ZW5jaWxBdHRhY2htZW50KTtmKGEuZGVwdGhTdGVuY2lsQXR0YWNobWVudCl9ZnVuY3Rpb24gdShiKXthLmRlbGV0ZUZyYW1lYnVmZmVyKGIuZnJhbWVidWZmZXIpO2IuZnJhbWVidWZmZXI9bnVsbDtkLmZyYW1lYnVmZmVyQ291bnQtLTtkZWxldGUgUltiLmlkXX1mdW5jdGlvbiB2KGIpe3ZhciBkO2EuYmluZEZyYW1lYnVmZmVyKDM2MTYwLGIuZnJhbWVidWZmZXIpO3ZhciBlPWIuY29sb3JBdHRhY2htZW50cztmb3IoZD0wO2Q8ZS5sZW5ndGg7KytkKXEoMzYwNjQrZCxlW2RdKTtmb3IoZD1lLmxlbmd0aDtkPGMubWF4Q29sb3JBdHRhY2htZW50czsrK2QpYS5mcmFtZWJ1ZmZlclRleHR1cmUyRCgzNjE2MCwzNjA2NCtkLDM1NTMsbnVsbCwwKTthLmZyYW1lYnVmZmVyVGV4dHVyZTJEKDM2MTYwLFxuMzMzMDYsMzU1MyxudWxsLDApO2EuZnJhbWVidWZmZXJUZXh0dXJlMkQoMzYxNjAsMzYwOTYsMzU1MyxudWxsLDApO2EuZnJhbWVidWZmZXJUZXh0dXJlMkQoMzYxNjAsMzYxMjgsMzU1MyxudWxsLDApO3EoMzYwOTYsYi5kZXB0aEF0dGFjaG1lbnQpO3EoMzYxMjgsYi5zdGVuY2lsQXR0YWNobWVudCk7cSgzMzMwNixiLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQpO2EuY2hlY2tGcmFtZWJ1ZmZlclN0YXR1cygzNjE2MCk7YS5pc0NvbnRleHRMb3N0KCk7YS5iaW5kRnJhbWVidWZmZXIoMzYxNjAsQi5uZXh0P0IubmV4dC5mcmFtZWJ1ZmZlcjpudWxsKTtCLmN1cj1CLm5leHQ7YS5nZXRFcnJvcigpfWZ1bmN0aW9uIE4oYSxiKXtmdW5jdGlvbiBjKGEsYil7dmFyIGQsZj0wLGg9MCxnPSEwLGs9ITA7ZD1udWxsO3ZhciBxPSEwLHU9XCJyZ2JhXCIsbj1cInVpbnQ4XCIsTj0xLGRhPW51bGwsb2E9bnVsbCxCPW51bGwsa2E9ITE7aWYoXCJudW1iZXJcIj09PXR5cGVvZiBhKWY9YXwwLGg9YnwwfHxmO2Vsc2UgaWYoYSl7XCJzaGFwZVwiaW5cbmE/KGg9YS5zaGFwZSxmPWhbMF0saD1oWzFdKTooXCJyYWRpdXNcImluIGEmJihmPWg9YS5yYWRpdXMpLFwid2lkdGhcImluIGEmJihmPWEud2lkdGgpLFwiaGVpZ2h0XCJpbiBhJiYoaD1hLmhlaWdodCkpO2lmKFwiY29sb3JcImluIGF8fFwiY29sb3JzXCJpbiBhKWQ9YS5jb2xvcnx8YS5jb2xvcnMsQXJyYXkuaXNBcnJheShkKTtpZighZCl7XCJjb2xvckNvdW50XCJpbiBhJiYoTj1hLmNvbG9yQ291bnR8MCk7XCJjb2xvclRleHR1cmVcImluIGEmJihxPSEhYS5jb2xvclRleHR1cmUsdT1cInJnYmE0XCIpO2lmKFwiY29sb3JUeXBlXCJpbiBhJiYobj1hLmNvbG9yVHlwZSwhcSkpaWYoXCJoYWxmIGZsb2F0XCI9PT1ufHxcImZsb2F0MTZcIj09PW4pdT1cInJnYmExNmZcIjtlbHNlIGlmKFwiZmxvYXRcIj09PW58fFwiZmxvYXQzMlwiPT09bil1PVwicmdiYTMyZlwiO1wiY29sb3JGb3JtYXRcImluIGEmJih1PWEuY29sb3JGb3JtYXQsMDw9eC5pbmRleE9mKHUpP3E9ITA6MDw9RC5pbmRleE9mKHUpJiYocT0hMSkpfWlmKFwiZGVwdGhUZXh0dXJlXCJpblxuYXx8XCJkZXB0aFN0ZW5jaWxUZXh0dXJlXCJpbiBhKWthPSEoIWEuZGVwdGhUZXh0dXJlJiYhYS5kZXB0aFN0ZW5jaWxUZXh0dXJlKTtcImRlcHRoXCJpbiBhJiYoXCJib29sZWFuXCI9PT10eXBlb2YgYS5kZXB0aD9nPWEuZGVwdGg6KGRhPWEuZGVwdGgsaz0hMSkpO1wic3RlbmNpbFwiaW4gYSYmKFwiYm9vbGVhblwiPT09dHlwZW9mIGEuc3RlbmNpbD9rPWEuc3RlbmNpbDoob2E9YS5zdGVuY2lsLGc9ITEpKTtcImRlcHRoU3RlbmNpbFwiaW4gYSYmKFwiYm9vbGVhblwiPT09dHlwZW9mIGEuZGVwdGhTdGVuY2lsP2c9az1hLmRlcHRoU3RlbmNpbDooQj1hLmRlcHRoU3RlbmNpbCxrPWc9ITEpKX1lbHNlIGY9aD0xO3ZhciBGPW51bGwseT1udWxsLEU9bnVsbCxUPW51bGw7aWYoQXJyYXkuaXNBcnJheShkKSlGPWQubWFwKHQpO2Vsc2UgaWYoZClGPVt0KGQpXTtlbHNlIGZvcihGPUFycmF5KE4pLGQ9MDtkPE47KytkKUZbZF09bShmLGgscSx1LG4pO2Y9Znx8RlswXS53aWR0aDtoPWh8fEZbMF0uaGVpZ2h0O2RhP1xueT10KGRhKTpnJiYhayYmKHk9bShmLGgsa2EsXCJkZXB0aFwiLFwidWludDMyXCIpKTtvYT9FPXQob2EpOmsmJiFnJiYoRT1tKGYsaCwhMSxcInN0ZW5jaWxcIixcInVpbnQ4XCIpKTtCP1Q9dChCKTohZGEmJiFvYSYmayYmZyYmKFQ9bShmLGgsa2EsXCJkZXB0aCBzdGVuY2lsXCIsXCJkZXB0aCBzdGVuY2lsXCIpKTtnPW51bGw7Zm9yKGQ9MDtkPEYubGVuZ3RoOysrZClyKEZbZF0sZixoKSxGW2RdJiZGW2RdLnRleHR1cmUmJihrPVdhW0ZbZF0udGV4dHVyZS5fdGV4dHVyZS5mb3JtYXRdKk5hW0ZbZF0udGV4dHVyZS5fdGV4dHVyZS50eXBlXSxudWxsPT09ZyYmKGc9aykpO3IoeSxmLGgpO3IoRSxmLGgpO3IoVCxmLGgpO2woZSk7ZS53aWR0aD1mO2UuaGVpZ2h0PWg7ZS5jb2xvckF0dGFjaG1lbnRzPUY7ZS5kZXB0aEF0dGFjaG1lbnQ9eTtlLnN0ZW5jaWxBdHRhY2htZW50PUU7ZS5kZXB0aFN0ZW5jaWxBdHRhY2htZW50PVQ7Yy5jb2xvcj1GLm1hcChDKTtjLmRlcHRoPUMoeSk7Yy5zdGVuY2lsPUMoRSk7XG5jLmRlcHRoU3RlbmNpbD1DKFQpO2Mud2lkdGg9ZS53aWR0aDtjLmhlaWdodD1lLmhlaWdodDt2KGUpO3JldHVybiBjfXZhciBlPW5ldyBoO2QuZnJhbWVidWZmZXJDb3VudCsrO2MoYSxiKTtyZXR1cm4gRShjLHtyZXNpemU6ZnVuY3Rpb24oYSxiKXt2YXIgZD1NYXRoLm1heChhfDAsMSksZj1NYXRoLm1heChifDB8fGQsMSk7aWYoZD09PWUud2lkdGgmJmY9PT1lLmhlaWdodClyZXR1cm4gYztmb3IodmFyIGg9ZS5jb2xvckF0dGFjaG1lbnRzLGc9MDtnPGgubGVuZ3RoOysrZylrKGhbZ10sZCxmKTtrKGUuZGVwdGhBdHRhY2htZW50LGQsZik7ayhlLnN0ZW5jaWxBdHRhY2htZW50LGQsZik7ayhlLmRlcHRoU3RlbmNpbEF0dGFjaG1lbnQsZCxmKTtlLndpZHRoPWMud2lkdGg9ZDtlLmhlaWdodD1jLmhlaWdodD1mO3YoZSk7cmV0dXJuIGN9LF9yZWdsVHlwZTpcImZyYW1lYnVmZmVyXCIsX2ZyYW1lYnVmZmVyOmUsZGVzdHJveTpmdW5jdGlvbigpe3UoZSk7bChlKX0sdXNlOmZ1bmN0aW9uKGEpe0Iuc2V0RkJPKHtmcmFtZWJ1ZmZlcjpjfSxcbmEpfX0pfXZhciBCPXtjdXI6bnVsbCxuZXh0Om51bGwsZGlydHk6ITEsc2V0RkJPOm51bGx9LHg9W1wicmdiYVwiXSxEPVtcInJnYmE0XCIsXCJyZ2I1NjVcIixcInJnYjUgYTFcIl07Yi5leHRfc3JnYiYmRC5wdXNoKFwic3JnYmFcIik7Yi5leHRfY29sb3JfYnVmZmVyX2hhbGZfZmxvYXQmJkQucHVzaChcInJnYmExNmZcIixcInJnYjE2ZlwiKTtiLndlYmdsX2NvbG9yX2J1ZmZlcl9mbG9hdCYmRC5wdXNoKFwicmdiYTMyZlwiKTt2YXIgeT1bXCJ1aW50OFwiXTtiLm9lc190ZXh0dXJlX2hhbGZfZmxvYXQmJnkucHVzaChcImhhbGYgZmxvYXRcIixcImZsb2F0MTZcIik7Yi5vZXNfdGV4dHVyZV9mbG9hdCYmeS5wdXNoKFwiZmxvYXRcIixcImZsb2F0MzJcIik7dmFyIE89MCxSPXt9O3JldHVybiBFKEIse2dldEZyYW1lYnVmZmVyOmZ1bmN0aW9uKGEpe3JldHVyblwiZnVuY3Rpb25cIj09PXR5cGVvZiBhJiZcImZyYW1lYnVmZmVyXCI9PT1hLl9yZWdsVHlwZSYmKGE9YS5fZnJhbWVidWZmZXIsYSBpbnN0YW5jZW9mIGgpP2E6bnVsbH0sY3JlYXRlOk4sXG5jcmVhdGVDdWJlOmZ1bmN0aW9uKGEpe2Z1bmN0aW9uIGIoYSl7dmFyIGQsZj17Y29sb3I6bnVsbH0saD0wLGc9bnVsbDtkPVwicmdiYVwiO3ZhciBsPVwidWludDhcIixtPTE7aWYoXCJudW1iZXJcIj09PXR5cGVvZiBhKWg9YXwwO2Vsc2UgaWYoYSl7XCJzaGFwZVwiaW4gYT9oPWEuc2hhcGVbMF06KFwicmFkaXVzXCJpbiBhJiYoaD1hLnJhZGl1c3wwKSxcIndpZHRoXCJpbiBhP2g9YS53aWR0aHwwOlwiaGVpZ2h0XCJpbiBhJiYoaD1hLmhlaWdodHwwKSk7aWYoXCJjb2xvclwiaW4gYXx8XCJjb2xvcnNcImluIGEpZz1hLmNvbG9yfHxhLmNvbG9ycyxBcnJheS5pc0FycmF5KGcpO2d8fChcImNvbG9yQ291bnRcImluIGEmJihtPWEuY29sb3JDb3VudHwwKSxcImNvbG9yVHlwZVwiaW4gYSYmKGw9YS5jb2xvclR5cGUpLFwiY29sb3JGb3JtYXRcImluIGEmJihkPWEuY29sb3JGb3JtYXQpKTtcImRlcHRoXCJpbiBhJiYoZi5kZXB0aD1hLmRlcHRoKTtcInN0ZW5jaWxcImluIGEmJihmLnN0ZW5jaWw9YS5zdGVuY2lsKTtcImRlcHRoU3RlbmNpbFwiaW5cbmEmJihmLmRlcHRoU3RlbmNpbD1hLmRlcHRoU3RlbmNpbCl9ZWxzZSBoPTE7aWYoZylpZihBcnJheS5pc0FycmF5KGcpKWZvcihhPVtdLGQ9MDtkPGcubGVuZ3RoOysrZClhW2RdPWdbZF07ZWxzZSBhPVtnXTtlbHNlIGZvcihhPUFycmF5KG0pLGc9e3JhZGl1czpoLGZvcm1hdDpkLHR5cGU6bH0sZD0wO2Q8bTsrK2QpYVtkXT1lLmNyZWF0ZUN1YmUoZyk7Zi5jb2xvcj1BcnJheShhLmxlbmd0aCk7Zm9yKGQ9MDtkPGEubGVuZ3RoOysrZCltPWFbZF0saD1ofHxtLndpZHRoLGYuY29sb3JbZF09e3RhcmdldDozNDA2OSxkYXRhOmFbZF19O2ZvcihkPTA7Nj5kOysrZCl7Zm9yKG09MDttPGEubGVuZ3RoOysrbSlmLmNvbG9yW21dLnRhcmdldD0zNDA2OStkOzA8ZCYmKGYuZGVwdGg9Y1swXS5kZXB0aCxmLnN0ZW5jaWw9Y1swXS5zdGVuY2lsLGYuZGVwdGhTdGVuY2lsPWNbMF0uZGVwdGhTdGVuY2lsKTtpZihjW2RdKWNbZF0oZik7ZWxzZSBjW2RdPU4oZil9cmV0dXJuIEUoYix7d2lkdGg6aCxcbmhlaWdodDpoLGNvbG9yOmF9KX12YXIgYz1BcnJheSg2KTtiKGEpO3JldHVybiBFKGIse2ZhY2VzOmMscmVzaXplOmZ1bmN0aW9uKGEpe3ZhciBkPWF8MDtpZihkPT09Yi53aWR0aClyZXR1cm4gYjt2YXIgZT1iLmNvbG9yO2ZvcihhPTA7YTxlLmxlbmd0aDsrK2EpZVthXS5yZXNpemUoZCk7Zm9yKGE9MDs2PmE7KythKWNbYV0ucmVzaXplKGQpO2Iud2lkdGg9Yi5oZWlnaHQ9ZDtyZXR1cm4gYn0sX3JlZ2xUeXBlOlwiZnJhbWVidWZmZXJDdWJlXCIsZGVzdHJveTpmdW5jdGlvbigpe2MuZm9yRWFjaChmdW5jdGlvbihhKXthLmRlc3Ryb3koKX0pfX0pfSxjbGVhcjpmdW5jdGlvbigpe1MoUikuZm9yRWFjaCh1KX0scmVzdG9yZTpmdW5jdGlvbigpe0IuY3VyPW51bGw7Qi5uZXh0PW51bGw7Qi5kaXJ0eT0hMDtTKFIpLmZvckVhY2goZnVuY3Rpb24oYil7Yi5mcmFtZWJ1ZmZlcj1hLmNyZWF0ZUZyYW1lYnVmZmVyKCk7dihiKX0pfX0pfWZ1bmN0aW9uIHViKCl7dGhpcy53PXRoaXMuej10aGlzLnk9XG50aGlzLng9dGhpcy5zdGF0ZT0wO3RoaXMuYnVmZmVyPW51bGw7dGhpcy5zaXplPTA7dGhpcy5ub3JtYWxpemVkPSExO3RoaXMudHlwZT01MTI2O3RoaXMuZGl2aXNvcj10aGlzLnN0cmlkZT10aGlzLm9mZnNldD0wfWZ1bmN0aW9uIFBiKGEsYixjLGUpe2E9Yy5tYXhBdHRyaWJ1dGVzO2I9QXJyYXkoYSk7Zm9yKGM9MDtjPGE7KytjKWJbY109bmV3IHViO3JldHVybntSZWNvcmQ6dWIsc2NvcGU6e30sc3RhdGU6Yn19ZnVuY3Rpb24gUWIoYSxiLGMsZSl7ZnVuY3Rpb24gZyhhLGIsYyxkKXt0aGlzLm5hbWU9YTt0aGlzLmlkPWI7dGhpcy5sb2NhdGlvbj1jO3RoaXMuaW5mbz1kfWZ1bmN0aW9uIGQoYSxiKXtmb3IodmFyIGM9MDtjPGEubGVuZ3RoOysrYylpZihhW2NdLmlkPT09Yi5pZCl7YVtjXS5sb2NhdGlvbj1iLmxvY2F0aW9uO3JldHVybn1hLnB1c2goYil9ZnVuY3Rpb24gbihjLGQsZSl7ZT0zNTYzMj09PWM/cTp0O3ZhciBmPWVbZF07aWYoIWYpe3ZhciBnPWIuc3RyKGQpLGY9YS5jcmVhdGVTaGFkZXIoYyk7XG5hLnNoYWRlclNvdXJjZShmLGcpO2EuY29tcGlsZVNoYWRlcihmKTtlW2RdPWZ9cmV0dXJuIGZ9ZnVuY3Rpb24gZihhLGIpe3RoaXMuaWQ9aysrO3RoaXMuZnJhZ0lkPWE7dGhpcy52ZXJ0SWQ9Yjt0aGlzLnByb2dyYW09bnVsbDt0aGlzLnVuaWZvcm1zPVtdO3RoaXMuYXR0cmlidXRlcz1bXTtlLnByb2ZpbGUmJih0aGlzLnN0YXRzPXt1bmlmb3Jtc0NvdW50OjAsYXR0cmlidXRlc0NvdW50OjB9KX1mdW5jdGlvbiByKGMsZil7dmFyIG0sazttPW4oMzU2MzIsYy5mcmFnSWQpO2s9bigzNTYzMyxjLnZlcnRJZCk7dmFyIHE9Yy5wcm9ncmFtPWEuY3JlYXRlUHJvZ3JhbSgpO2EuYXR0YWNoU2hhZGVyKHEsbSk7YS5hdHRhY2hTaGFkZXIocSxrKTthLmxpbmtQcm9ncmFtKHEpO3ZhciByPWEuZ2V0UHJvZ3JhbVBhcmFtZXRlcihxLDM1NzE4KTtlLnByb2ZpbGUmJihjLnN0YXRzLnVuaWZvcm1zQ291bnQ9cik7dmFyIHQ9Yy51bmlmb3Jtcztmb3IobT0wO208cjsrK20paWYoaz1hLmdldEFjdGl2ZVVuaWZvcm0ocSxcbm0pKWlmKDE8ay5zaXplKWZvcih2YXIgQz0wO0M8ay5zaXplOysrQyl7dmFyIHk9ay5uYW1lLnJlcGxhY2UoXCJbMF1cIixcIltcIitDK1wiXVwiKTtkKHQsbmV3IGcoeSxiLmlkKHkpLGEuZ2V0VW5pZm9ybUxvY2F0aW9uKHEseSksaykpfWVsc2UgZCh0LG5ldyBnKGsubmFtZSxiLmlkKGsubmFtZSksYS5nZXRVbmlmb3JtTG9jYXRpb24ocSxrLm5hbWUpLGspKTtyPWEuZ2V0UHJvZ3JhbVBhcmFtZXRlcihxLDM1NzIxKTtlLnByb2ZpbGUmJihjLnN0YXRzLmF0dHJpYnV0ZXNDb3VudD1yKTt0PWMuYXR0cmlidXRlcztmb3IobT0wO208cjsrK20pKGs9YS5nZXRBY3RpdmVBdHRyaWIocSxtKSkmJmQodCxuZXcgZyhrLm5hbWUsYi5pZChrLm5hbWUpLGEuZ2V0QXR0cmliTG9jYXRpb24ocSxrLm5hbWUpLGspKX12YXIgcT17fSx0PXt9LG09e30sQz1bXSxrPTA7ZS5wcm9maWxlJiYoYy5nZXRNYXhVbmlmb3Jtc0NvdW50PWZ1bmN0aW9uKCl7dmFyIGE9MDtDLmZvckVhY2goZnVuY3Rpb24oYil7Yi5zdGF0cy51bmlmb3Jtc0NvdW50PlxuYSYmKGE9Yi5zdGF0cy51bmlmb3Jtc0NvdW50KX0pO3JldHVybiBhfSxjLmdldE1heEF0dHJpYnV0ZXNDb3VudD1mdW5jdGlvbigpe3ZhciBhPTA7Qy5mb3JFYWNoKGZ1bmN0aW9uKGIpe2Iuc3RhdHMuYXR0cmlidXRlc0NvdW50PmEmJihhPWIuc3RhdHMuYXR0cmlidXRlc0NvdW50KX0pO3JldHVybiBhfSk7cmV0dXJue2NsZWFyOmZ1bmN0aW9uKCl7dmFyIGI9YS5kZWxldGVTaGFkZXIuYmluZChhKTtTKHEpLmZvckVhY2goYik7cT17fTtTKHQpLmZvckVhY2goYik7dD17fTtDLmZvckVhY2goZnVuY3Rpb24oYil7YS5kZWxldGVQcm9ncmFtKGIucHJvZ3JhbSl9KTtDLmxlbmd0aD0wO209e307Yy5zaGFkZXJDb3VudD0wfSxwcm9ncmFtOmZ1bmN0aW9uKGEsYixkKXt2YXIgZT1tW2JdO2V8fChlPW1bYl09e30pO3ZhciBnPWVbYV07Z3x8KGc9bmV3IGYoYixhKSxjLnNoYWRlckNvdW50KysscihnLGQpLGVbYV09ZyxDLnB1c2goZykpO3JldHVybiBnfSxyZXN0b3JlOmZ1bmN0aW9uKCl7cT1cbnt9O3Q9e307Zm9yKHZhciBhPTA7YTxDLmxlbmd0aDsrK2EpcihDW2FdKX0sc2hhZGVyOm4sZnJhZzotMSx2ZXJ0Oi0xfX1mdW5jdGlvbiBSYihhLGIsYyxlLGcsZCxuKXtmdW5jdGlvbiBmKGQpe3ZhciBmO2Y9bnVsbD09PWIubmV4dD81MTIxOmIubmV4dC5jb2xvckF0dGFjaG1lbnRzWzBdLnRleHR1cmUuX3RleHR1cmUudHlwZTt2YXIgZz0wLHI9MCxrPWUuZnJhbWVidWZmZXJXaWR0aCxoPWUuZnJhbWVidWZmZXJIZWlnaHQsbD1udWxsO00oZCk/bD1kOmQmJihnPWQueHwwLHI9ZC55fDAsaz0oZC53aWR0aHx8ZS5mcmFtZWJ1ZmZlcldpZHRoLWcpfDAsaD0oZC5oZWlnaHR8fGUuZnJhbWVidWZmZXJIZWlnaHQtcil8MCxsPWQuZGF0YXx8bnVsbCk7YygpO2Q9aypoKjQ7bHx8KDUxMjE9PT1mP2w9bmV3IFVpbnQ4QXJyYXkoZCk6NTEyNj09PWYmJihsPWx8fG5ldyBGbG9hdDMyQXJyYXkoZCkpKTthLnBpeGVsU3RvcmVpKDMzMzMsNCk7YS5yZWFkUGl4ZWxzKGcscixrLGgsNjQwOCxmLFxubCk7cmV0dXJuIGx9ZnVuY3Rpb24gcihhKXt2YXIgYztiLnNldEZCTyh7ZnJhbWVidWZmZXI6YS5mcmFtZWJ1ZmZlcn0sZnVuY3Rpb24oKXtjPWYoYSl9KTtyZXR1cm4gY31yZXR1cm4gZnVuY3Rpb24oYSl7cmV0dXJuIGEmJlwiZnJhbWVidWZmZXJcImluIGE/cihhKTpmKGEpfX1mdW5jdGlvbiBCYShhKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYSl9ZnVuY3Rpb24gQ2EoYSl7cmV0dXJuIEJhKGEpLmpvaW4oXCJcIil9ZnVuY3Rpb24gU2IoKXtmdW5jdGlvbiBhKCl7dmFyIGE9W10sYj1bXTtyZXR1cm4gRShmdW5jdGlvbigpe2EucHVzaC5hcHBseShhLEJhKGFyZ3VtZW50cykpfSx7ZGVmOmZ1bmN0aW9uKCl7dmFyIGQ9XCJ2XCIrYysrO2IucHVzaChkKTswPGFyZ3VtZW50cy5sZW5ndGgmJihhLnB1c2goZCxcIj1cIiksYS5wdXNoLmFwcGx5KGEsQmEoYXJndW1lbnRzKSksYS5wdXNoKFwiO1wiKSk7cmV0dXJuIGR9LHRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIENhKFswPGIubGVuZ3RoP1xuXCJ2YXIgXCIrYitcIjtcIjpcIlwiLENhKGEpXSl9fSl9ZnVuY3Rpb24gYigpe2Z1bmN0aW9uIGIoYSxlKXtkKGEsZSxcIj1cIixjLmRlZihhLGUpLFwiO1wiKX12YXIgYz1hKCksZD1hKCksZT1jLnRvU3RyaW5nLGc9ZC50b1N0cmluZztyZXR1cm4gRShmdW5jdGlvbigpe2MuYXBwbHkoYyxCYShhcmd1bWVudHMpKX0se2RlZjpjLmRlZixlbnRyeTpjLGV4aXQ6ZCxzYXZlOmIsc2V0OmZ1bmN0aW9uKGEsZCxlKXtiKGEsZCk7YyhhLGQsXCI9XCIsZSxcIjtcIil9LHRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIGUoKStnKCl9fSl9dmFyIGM9MCxlPVtdLGc9W10sZD1hKCksbj17fTtyZXR1cm57Z2xvYmFsOmQsbGluazpmdW5jdGlvbihhKXtmb3IodmFyIGI9MDtiPGcubGVuZ3RoOysrYilpZihnW2JdPT09YSlyZXR1cm4gZVtiXTtiPVwiZ1wiK2MrKztlLnB1c2goYik7Zy5wdXNoKGEpO3JldHVybiBifSxibG9jazphLHByb2M6ZnVuY3Rpb24oYSxjKXtmdW5jdGlvbiBkKCl7dmFyIGE9XCJhXCIrZS5sZW5ndGg7ZS5wdXNoKGEpO1xucmV0dXJuIGF9dmFyIGU9W107Yz1jfHwwO2Zvcih2YXIgZz0wO2c8YzsrK2cpZCgpO3ZhciBnPWIoKSxDPWcudG9TdHJpbmc7cmV0dXJuIG5bYV09RShnLHthcmc6ZCx0b1N0cmluZzpmdW5jdGlvbigpe3JldHVybiBDYShbXCJmdW5jdGlvbihcIixlLmpvaW4oKSxcIil7XCIsQygpLFwifVwiXSl9fSl9LHNjb3BlOmIsY29uZDpmdW5jdGlvbigpe3ZhciBhPUNhKGFyZ3VtZW50cyksYz1iKCksZD1iKCksZT1jLnRvU3RyaW5nLGc9ZC50b1N0cmluZztyZXR1cm4gRShjLHt0aGVuOmZ1bmN0aW9uKCl7Yy5hcHBseShjLEJhKGFyZ3VtZW50cykpO3JldHVybiB0aGlzfSxcImVsc2VcIjpmdW5jdGlvbigpe2QuYXBwbHkoZCxCYShhcmd1bWVudHMpKTtyZXR1cm4gdGhpc30sdG9TdHJpbmc6ZnVuY3Rpb24oKXt2YXIgYj1nKCk7YiYmKGI9XCJlbHNle1wiK2IrXCJ9XCIpO3JldHVybiBDYShbXCJpZihcIixhLFwiKXtcIixlKCksXCJ9XCIsYl0pfX0pfSxjb21waWxlOmZ1bmN0aW9uKCl7dmFyIGE9WydcInVzZSBzdHJpY3RcIjsnLFxuZCxcInJldHVybiB7XCJdO09iamVjdC5rZXlzKG4pLmZvckVhY2goZnVuY3Rpb24oYil7YS5wdXNoKCdcIicsYiwnXCI6JyxuW2JdLnRvU3RyaW5nKCksXCIsXCIpfSk7YS5wdXNoKFwifVwiKTt2YXIgYj1DYShhKS5yZXBsYWNlKC87L2csXCI7XFxuXCIpLnJlcGxhY2UoL30vZyxcIn1cXG5cIikucmVwbGFjZSgvey9nLFwie1xcblwiKTtyZXR1cm4gRnVuY3Rpb24uYXBwbHkobnVsbCxlLmNvbmNhdChiKSkuYXBwbHkobnVsbCxnKX19fWZ1bmN0aW9uIE9hKGEpe3JldHVybiBBcnJheS5pc0FycmF5KGEpfHxNKGEpfHxtYShhKX1mdW5jdGlvbiB2YihhKXtyZXR1cm4gYS5zb3J0KGZ1bmN0aW9uKGEsYyl7cmV0dXJuXCJ2aWV3cG9ydFwiPT09YT8tMTpcInZpZXdwb3J0XCI9PT1jPzE6YTxjPy0xOjF9KX1mdW5jdGlvbiBaKGEsYixjLGUpe3RoaXMudGhpc0RlcD1hO3RoaXMuY29udGV4dERlcD1iO3RoaXMucHJvcERlcD1jO3RoaXMuYXBwZW5kPWV9ZnVuY3Rpb24gdmEoYSl7cmV0dXJuIGEmJiEoYS50aGlzRGVwfHxhLmNvbnRleHREZXB8fFxuYS5wcm9wRGVwKX1mdW5jdGlvbiBEKGEpe3JldHVybiBuZXcgWighMSwhMSwhMSxhKX1mdW5jdGlvbiBQKGEsYil7dmFyIGM9YS50eXBlO3JldHVybiAwPT09Yz8oYz1hLmRhdGEubGVuZ3RoLG5ldyBaKCEwLDE8PWMsMjw9YyxiKSk6ND09PWM/KGM9YS5kYXRhLG5ldyBaKGMudGhpc0RlcCxjLmNvbnRleHREZXAsYy5wcm9wRGVwLGIpKTpuZXcgWigzPT09YywyPT09YywxPT09YyxiKX1mdW5jdGlvbiBUYihhLGIsYyxlLGcsZCxuLGYscixxLHQsbSxDLGssaCl7ZnVuY3Rpb24gbChhKXtyZXR1cm4gYS5yZXBsYWNlKFwiLlwiLFwiX1wiKX1mdW5jdGlvbiB1KGEsYixjKXt2YXIgZD1sKGEpO0thLnB1c2goYSk7RmFbZF09cmFbZF09ISFjO3NhW2RdPWJ9ZnVuY3Rpb24gdihhLGIsYyl7dmFyIGQ9bChhKTtLYS5wdXNoKGEpO0FycmF5LmlzQXJyYXkoYyk/KHJhW2RdPWMuc2xpY2UoKSxGYVtkXT1jLnNsaWNlKCkpOnJhW2RdPUZhW2RdPWM7dGFbZF09Yn1mdW5jdGlvbiBOKCl7dmFyIGE9U2IoKSxcbmM9YS5saW5rLGQ9YS5nbG9iYWw7YS5pZD1xYSsrO2EuYmF0Y2hJZD1cIjBcIjt2YXIgZT1jKG5hKSxmPWEuc2hhcmVkPXtwcm9wczpcImEwXCJ9O09iamVjdC5rZXlzKG5hKS5mb3JFYWNoKGZ1bmN0aW9uKGEpe2ZbYV09ZC5kZWYoZSxcIi5cIixhKX0pO3ZhciBnPWEubmV4dD17fSx4YT1hLmN1cnJlbnQ9e307T2JqZWN0LmtleXModGEpLmZvckVhY2goZnVuY3Rpb24oYSl7QXJyYXkuaXNBcnJheShyYVthXSkmJihnW2FdPWQuZGVmKGYubmV4dCxcIi5cIixhKSx4YVthXT1kLmRlZihmLmN1cnJlbnQsXCIuXCIsYSkpfSk7dmFyIEg9YS5jb25zdGFudHM9e307T2JqZWN0LmtleXMoYWEpLmZvckVhY2goZnVuY3Rpb24oYSl7SFthXT1kLmRlZihKU09OLnN0cmluZ2lmeShhYVthXSkpfSk7YS5pbnZva2U9ZnVuY3Rpb24oYixkKXtzd2l0Y2goZC50eXBlKXtjYXNlIDA6dmFyIGU9W1widGhpc1wiLGYuY29udGV4dCxmLnByb3BzLGEuYmF0Y2hJZF07cmV0dXJuIGIuZGVmKGMoZC5kYXRhKSxcIi5jYWxsKFwiLGUuc2xpY2UoMCxcbk1hdGgubWF4KGQuZGF0YS5sZW5ndGgrMSw0KSksXCIpXCIpO2Nhc2UgMTpyZXR1cm4gYi5kZWYoZi5wcm9wcyxkLmRhdGEpO2Nhc2UgMjpyZXR1cm4gYi5kZWYoZi5jb250ZXh0LGQuZGF0YSk7Y2FzZSAzOnJldHVybiBiLmRlZihcInRoaXNcIixkLmRhdGEpO2Nhc2UgNDpyZXR1cm4gZC5kYXRhLmFwcGVuZChhLGIpLGQuZGF0YS5yZWZ9fTthLmF0dHJpYkNhY2hlPXt9O3ZhciBZPXt9O2Euc2NvcGVBdHRyaWI9ZnVuY3Rpb24oYSl7YT1iLmlkKGEpO2lmKGEgaW4gWSlyZXR1cm4gWVthXTt2YXIgZD1xLnNjb3BlW2FdO2R8fChkPXEuc2NvcGVbYV09bmV3IHlhKTtyZXR1cm4gWVthXT1jKGQpfTtyZXR1cm4gYX1mdW5jdGlvbiBCKGEpe3ZhciBiPWFbXCJzdGF0aWNcIl07YT1hLmR5bmFtaWM7dmFyIGM7aWYoXCJwcm9maWxlXCJpbiBiKXt2YXIgZD0hIWIucHJvZmlsZTtjPUQoZnVuY3Rpb24oYSxiKXtyZXR1cm4gZH0pO2MuZW5hYmxlPWR9ZWxzZSBpZihcInByb2ZpbGVcImluIGEpe3ZhciBlPWEucHJvZmlsZTtcbmM9UChlLGZ1bmN0aW9uKGEsYil7cmV0dXJuIGEuaW52b2tlKGIsZSl9KX1yZXR1cm4gY31mdW5jdGlvbiB5KGEsYil7dmFyIGM9YVtcInN0YXRpY1wiXSxkPWEuZHluYW1pYztpZihcImZyYW1lYnVmZmVyXCJpbiBjKXt2YXIgZT1jLmZyYW1lYnVmZmVyO3JldHVybiBlPyhlPWYuZ2V0RnJhbWVidWZmZXIoZSksRChmdW5jdGlvbihhLGIpe3ZhciBjPWEubGluayhlKSxkPWEuc2hhcmVkO2Iuc2V0KGQuZnJhbWVidWZmZXIsXCIubmV4dFwiLGMpO2Q9ZC5jb250ZXh0O2Iuc2V0KGQsXCIuZnJhbWVidWZmZXJXaWR0aFwiLGMrXCIud2lkdGhcIik7Yi5zZXQoZCxcIi5mcmFtZWJ1ZmZlckhlaWdodFwiLGMrXCIuaGVpZ2h0XCIpO3JldHVybiBjfSkpOkQoZnVuY3Rpb24oYSxiKXt2YXIgYz1hLnNoYXJlZDtiLnNldChjLmZyYW1lYnVmZmVyLFwiLm5leHRcIixcIm51bGxcIik7Yz1jLmNvbnRleHQ7Yi5zZXQoYyxcIi5mcmFtZWJ1ZmZlcldpZHRoXCIsYytcIi5kcmF3aW5nQnVmZmVyV2lkdGhcIik7Yi5zZXQoYyxcIi5mcmFtZWJ1ZmZlckhlaWdodFwiLFxuYytcIi5kcmF3aW5nQnVmZmVySGVpZ2h0XCIpO3JldHVyblwibnVsbFwifSl9aWYoXCJmcmFtZWJ1ZmZlclwiaW4gZCl7dmFyIGc9ZC5mcmFtZWJ1ZmZlcjtyZXR1cm4gUChnLGZ1bmN0aW9uKGEsYil7dmFyIGM9YS5pbnZva2UoYixnKSxkPWEuc2hhcmVkLGU9ZC5mcmFtZWJ1ZmZlcixjPWIuZGVmKGUsXCIuZ2V0RnJhbWVidWZmZXIoXCIsYyxcIilcIik7Yi5zZXQoZSxcIi5uZXh0XCIsYyk7ZD1kLmNvbnRleHQ7Yi5zZXQoZCxcIi5mcmFtZWJ1ZmZlcldpZHRoXCIsYytcIj9cIitjK1wiLndpZHRoOlwiK2QrXCIuZHJhd2luZ0J1ZmZlcldpZHRoXCIpO2Iuc2V0KGQsXCIuZnJhbWVidWZmZXJIZWlnaHRcIixjK1wiP1wiK2MrXCIuaGVpZ2h0OlwiK2QrXCIuZHJhd2luZ0J1ZmZlckhlaWdodFwiKTtyZXR1cm4gY30pfXJldHVybiBudWxsfWZ1bmN0aW9uIHgoYSxiLGMpe2Z1bmN0aW9uIGQoYSl7aWYoYSBpbiBlKXt2YXIgYz1lW2FdO2E9ITA7dmFyIHA9Yy54fDAsYmE9Yy55fDAsZyxoO1wid2lkdGhcImluIGM/Zz1jLndpZHRofDA6YT0hMTtcblwiaGVpZ2h0XCJpbiBjP2g9Yy5oZWlnaHR8MDphPSExO3JldHVybiBuZXcgWighYSYmYiYmYi50aGlzRGVwLCFhJiZiJiZiLmNvbnRleHREZXAsIWEmJmImJmIucHJvcERlcCxmdW5jdGlvbihhLGIpe3ZhciBkPWEuc2hhcmVkLmNvbnRleHQsZT1nO1wid2lkdGhcImluIGN8fChlPWIuZGVmKGQsXCIuXCIsXCJmcmFtZWJ1ZmZlcldpZHRoXCIsXCItXCIscCkpO3ZhciBmPWg7XCJoZWlnaHRcImluIGN8fChmPWIuZGVmKGQsXCIuXCIsXCJmcmFtZWJ1ZmZlckhlaWdodFwiLFwiLVwiLGJhKSk7cmV0dXJuW3AsYmEsZSxmXX0pfWlmKGEgaW4gZil7dmFyIHo9ZlthXTthPVAoeixmdW5jdGlvbihhLGIpe3ZhciBjPWEuaW52b2tlKGIseiksZD1hLnNoYXJlZC5jb250ZXh0LGU9Yi5kZWYoYyxcIi54fDBcIikscD1iLmRlZihjLFwiLnl8MFwiKSxZPWIuZGVmKCdcIndpZHRoXCIgaW4gJyxjLFwiP1wiLGMsXCIud2lkdGh8MDpcIixcIihcIixkLFwiLlwiLFwiZnJhbWVidWZmZXJXaWR0aFwiLFwiLVwiLGUsXCIpXCIpLGM9Yi5kZWYoJ1wiaGVpZ2h0XCIgaW4gJyxcbmMsXCI/XCIsYyxcIi5oZWlnaHR8MDpcIixcIihcIixkLFwiLlwiLFwiZnJhbWVidWZmZXJIZWlnaHRcIixcIi1cIixwLFwiKVwiKTtyZXR1cm5bZSxwLFksY119KTtiJiYoYS50aGlzRGVwPWEudGhpc0RlcHx8Yi50aGlzRGVwLGEuY29udGV4dERlcD1hLmNvbnRleHREZXB8fGIuY29udGV4dERlcCxhLnByb3BEZXA9YS5wcm9wRGVwfHxiLnByb3BEZXApO3JldHVybiBhfXJldHVybiBiP25ldyBaKGIudGhpc0RlcCxiLmNvbnRleHREZXAsYi5wcm9wRGVwLGZ1bmN0aW9uKGEsYil7dmFyIGM9YS5zaGFyZWQuY29udGV4dDtyZXR1cm5bMCwwLGIuZGVmKGMsXCIuXCIsXCJmcmFtZWJ1ZmZlcldpZHRoXCIpLGIuZGVmKGMsXCIuXCIsXCJmcmFtZWJ1ZmZlckhlaWdodFwiKV19KTpudWxsfXZhciBlPWFbXCJzdGF0aWNcIl0sZj1hLmR5bmFtaWM7aWYoYT1kKFwidmlld3BvcnRcIikpe3ZhciBnPWE7YT1uZXcgWihhLnRoaXNEZXAsYS5jb250ZXh0RGVwLGEucHJvcERlcCxmdW5jdGlvbihhLGIpe3ZhciBjPWcuYXBwZW5kKGEsYiksZD1hLnNoYXJlZC5jb250ZXh0O1xuYi5zZXQoZCxcIi52aWV3cG9ydFdpZHRoXCIsY1syXSk7Yi5zZXQoZCxcIi52aWV3cG9ydEhlaWdodFwiLGNbM10pO3JldHVybiBjfSl9cmV0dXJue3ZpZXdwb3J0OmEsc2Npc3Nvcl9ib3g6ZChcInNjaXNzb3IuYm94XCIpfX1mdW5jdGlvbiBFKGEpe2Z1bmN0aW9uIGMoYSl7aWYoYSBpbiBkKXt2YXIgcD1iLmlkKGRbYV0pO2E9RChmdW5jdGlvbigpe3JldHVybiBwfSk7YS5pZD1wO3JldHVybiBhfWlmKGEgaW4gZSl7dmFyIGY9ZVthXTtyZXR1cm4gUChmLGZ1bmN0aW9uKGEsYil7dmFyIGM9YS5pbnZva2UoYixmKTtyZXR1cm4gYi5kZWYoYS5zaGFyZWQuc3RyaW5ncyxcIi5pZChcIixjLFwiKVwiKX0pfXJldHVybiBudWxsfXZhciBkPWFbXCJzdGF0aWNcIl0sZT1hLmR5bmFtaWMsZj1jKFwiZnJhZ1wiKSxnPWMoXCJ2ZXJ0XCIpLGg9bnVsbDt2YShmKSYmdmEoZyk/KGg9dC5wcm9ncmFtKGcuaWQsZi5pZCksYT1EKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGEubGluayhoKX0pKTphPW5ldyBaKGYmJmYudGhpc0RlcHx8XG5nJiZnLnRoaXNEZXAsZiYmZi5jb250ZXh0RGVwfHxnJiZnLmNvbnRleHREZXAsZiYmZi5wcm9wRGVwfHxnJiZnLnByb3BEZXAsZnVuY3Rpb24oYSxiKXt2YXIgYz1hLnNoYXJlZC5zaGFkZXIsZDtkPWY/Zi5hcHBlbmQoYSxiKTpiLmRlZihjLFwiLlwiLFwiZnJhZ1wiKTt2YXIgZTtlPWc/Zy5hcHBlbmQoYSxiKTpiLmRlZihjLFwiLlwiLFwidmVydFwiKTtyZXR1cm4gYi5kZWYoYytcIi5wcm9ncmFtKFwiK2UrXCIsXCIrZCtcIilcIil9KTtyZXR1cm57ZnJhZzpmLHZlcnQ6Zyxwcm9nVmFyOmEscHJvZ3JhbTpofX1mdW5jdGlvbiBPKGEsYil7ZnVuY3Rpb24gYyhhLGIpe2lmKGEgaW4gZSl7dmFyIGQ9ZVthXXwwO3JldHVybiBEKGZ1bmN0aW9uKGEsYyl7YiYmKGEuT0ZGU0VUPWQpO3JldHVybiBkfSl9aWYoYSBpbiBmKXt2YXIgcD1mW2FdO3JldHVybiBQKHAsZnVuY3Rpb24oYSxjKXt2YXIgZD1hLmludm9rZShjLHApO2ImJihhLk9GRlNFVD1kKTtyZXR1cm4gZH0pfXJldHVybiBiJiZnP0QoZnVuY3Rpb24oYSxcbmIpe2EuT0ZGU0VUPVwiMFwiO3JldHVybiAwfSk6bnVsbH12YXIgZT1hW1wic3RhdGljXCJdLGY9YS5keW5hbWljLGc9ZnVuY3Rpb24oKXtpZihcImVsZW1lbnRzXCJpbiBlKXt2YXIgYT1lLmVsZW1lbnRzO09hKGEpP2E9ZC5nZXRFbGVtZW50cyhkLmNyZWF0ZShhLCEwKSk6YSYmKGE9ZC5nZXRFbGVtZW50cyhhKSk7dmFyIGI9RChmdW5jdGlvbihiLGMpe2lmKGEpe3ZhciBkPWIubGluayhhKTtyZXR1cm4gYi5FTEVNRU5UUz1kfXJldHVybiBiLkVMRU1FTlRTPW51bGx9KTtiLnZhbHVlPWE7cmV0dXJuIGJ9aWYoXCJlbGVtZW50c1wiaW4gZil7dmFyIGM9Zi5lbGVtZW50cztyZXR1cm4gUChjLGZ1bmN0aW9uKGEsYil7dmFyIGQ9YS5zaGFyZWQsZT1kLmlzQnVmZmVyQXJncyxkPWQuZWxlbWVudHMscD1hLmludm9rZShiLGMpLGY9Yi5kZWYoXCJudWxsXCIpLGU9Yi5kZWYoZSxcIihcIixwLFwiKVwiKSxwPWEuY29uZChlKS50aGVuKGYsXCI9XCIsZCxcIi5jcmVhdGVTdHJlYW0oXCIscCxcIik7XCIpW1wiZWxzZVwiXShmLFwiPVwiLFxuZCxcIi5nZXRFbGVtZW50cyhcIixwLFwiKTtcIik7Yi5lbnRyeShwKTtiLmV4aXQoYS5jb25kKGUpLnRoZW4oZCxcIi5kZXN0cm95U3RyZWFtKFwiLGYsXCIpO1wiKSk7cmV0dXJuIGEuRUxFTUVOVFM9Zn0pfXJldHVybiBudWxsfSgpLGg9YyhcIm9mZnNldFwiLCEwKTtyZXR1cm57ZWxlbWVudHM6ZyxwcmltaXRpdmU6ZnVuY3Rpb24oKXtpZihcInByaW1pdGl2ZVwiaW4gZSl7dmFyIGE9ZS5wcmltaXRpdmU7cmV0dXJuIEQoZnVuY3Rpb24oYixjKXtyZXR1cm4gU2FbYV19KX1pZihcInByaW1pdGl2ZVwiaW4gZil7dmFyIGI9Zi5wcmltaXRpdmU7cmV0dXJuIFAoYixmdW5jdGlvbihhLGMpe3ZhciBkPWEuY29uc3RhbnRzLnByaW1UeXBlcyxlPWEuaW52b2tlKGMsYik7cmV0dXJuIGMuZGVmKGQsXCJbXCIsZSxcIl1cIil9KX1yZXR1cm4gZz92YShnKT9nLnZhbHVlP0QoZnVuY3Rpb24oYSxiKXtyZXR1cm4gYi5kZWYoYS5FTEVNRU5UUyxcIi5wcmltVHlwZVwiKX0pOkQoZnVuY3Rpb24oKXtyZXR1cm4gNH0pOm5ldyBaKGcudGhpc0RlcCxcbmcuY29udGV4dERlcCxnLnByb3BEZXAsZnVuY3Rpb24oYSxiKXt2YXIgYz1hLkVMRU1FTlRTO3JldHVybiBiLmRlZihjLFwiP1wiLGMsXCIucHJpbVR5cGU6XCIsNCl9KTpudWxsfSgpLGNvdW50OmZ1bmN0aW9uKCl7aWYoXCJjb3VudFwiaW4gZSl7dmFyIGE9ZS5jb3VudHwwO3JldHVybiBEKGZ1bmN0aW9uKCl7cmV0dXJuIGF9KX1pZihcImNvdW50XCJpbiBmKXt2YXIgYj1mLmNvdW50O3JldHVybiBQKGIsZnVuY3Rpb24oYSxjKXtyZXR1cm4gYS5pbnZva2UoYyxiKX0pfXJldHVybiBnP3ZhKGcpP2c/aD9uZXcgWihoLnRoaXNEZXAsaC5jb250ZXh0RGVwLGgucHJvcERlcCxmdW5jdGlvbihhLGIpe3JldHVybiBiLmRlZihhLkVMRU1FTlRTLFwiLnZlcnRDb3VudC1cIixhLk9GRlNFVCl9KTpEKGZ1bmN0aW9uKGEsYil7cmV0dXJuIGIuZGVmKGEuRUxFTUVOVFMsXCIudmVydENvdW50XCIpfSk6RChmdW5jdGlvbigpe3JldHVybi0xfSk6bmV3IFooZy50aGlzRGVwfHxoLnRoaXNEZXAsZy5jb250ZXh0RGVwfHxcbmguY29udGV4dERlcCxnLnByb3BEZXB8fGgucHJvcERlcCxmdW5jdGlvbihhLGIpe3ZhciBjPWEuRUxFTUVOVFM7cmV0dXJuIGEuT0ZGU0VUP2IuZGVmKGMsXCI/XCIsYyxcIi52ZXJ0Q291bnQtXCIsYS5PRkZTRVQsXCI6LTFcIik6Yi5kZWYoYyxcIj9cIixjLFwiLnZlcnRDb3VudDotMVwiKX0pOm51bGx9KCksaW5zdGFuY2VzOmMoXCJpbnN0YW5jZXNcIiwhMSksb2Zmc2V0Omh9fWZ1bmN0aW9uIFIoYSxiKXt2YXIgYz1hW1wic3RhdGljXCJdLGQ9YS5keW5hbWljLGU9e307S2EuZm9yRWFjaChmdW5jdGlvbihhKXtmdW5jdGlvbiBiKGYsZyl7aWYoYSBpbiBjKXt2YXIgdz1mKGNbYV0pO2VbcF09RChmdW5jdGlvbigpe3JldHVybiB3fSl9ZWxzZSBpZihhIGluIGQpe3ZhciBoPWRbYV07ZVtwXT1QKGgsZnVuY3Rpb24oYSxiKXtyZXR1cm4gZyhhLGIsYS5pbnZva2UoYixoKSl9KX19dmFyIHA9bChhKTtzd2l0Y2goYSl7Y2FzZSBcImN1bGwuZW5hYmxlXCI6Y2FzZSBcImJsZW5kLmVuYWJsZVwiOmNhc2UgXCJkaXRoZXJcIjpjYXNlIFwic3RlbmNpbC5lbmFibGVcIjpjYXNlIFwiZGVwdGguZW5hYmxlXCI6Y2FzZSBcInNjaXNzb3IuZW5hYmxlXCI6Y2FzZSBcInBvbHlnb25PZmZzZXQuZW5hYmxlXCI6Y2FzZSBcInNhbXBsZS5hbHBoYVwiOmNhc2UgXCJzYW1wbGUuZW5hYmxlXCI6Y2FzZSBcImRlcHRoLm1hc2tcIjpyZXR1cm4gYihmdW5jdGlvbihhKXtyZXR1cm4gYX0sXG5mdW5jdGlvbihhLGIsYyl7cmV0dXJuIGN9KTtjYXNlIFwiZGVwdGguZnVuY1wiOnJldHVybiBiKGZ1bmN0aW9uKGEpe3JldHVybiBYYVthXX0sZnVuY3Rpb24oYSxiLGMpe3JldHVybiBiLmRlZihhLmNvbnN0YW50cy5jb21wYXJlRnVuY3MsXCJbXCIsYyxcIl1cIil9KTtjYXNlIFwiZGVwdGgucmFuZ2VcIjpyZXR1cm4gYihmdW5jdGlvbihhKXtyZXR1cm4gYX0sZnVuY3Rpb24oYSxiLGMpe2E9Yi5kZWYoXCIrXCIsYyxcIlswXVwiKTtiPWIuZGVmKFwiK1wiLGMsXCJbMV1cIik7cmV0dXJuW2EsYl19KTtjYXNlIFwiYmxlbmQuZnVuY1wiOnJldHVybiBiKGZ1bmN0aW9uKGEpe3JldHVybltHYVtcInNyY1JHQlwiaW4gYT9hLnNyY1JHQjphLnNyY10sR2FbXCJkc3RSR0JcImluIGE/YS5kc3RSR0I6YS5kc3RdLEdhW1wic3JjQWxwaGFcImluIGE/YS5zcmNBbHBoYTphLnNyY10sR2FbXCJkc3RBbHBoYVwiaW4gYT9hLmRzdEFscGhhOmEuZHN0XV19LGZ1bmN0aW9uKGEsYixjKXtmdW5jdGlvbiBkKGEsZSl7cmV0dXJuIGIuZGVmKCdcIicsXG5hLGUsJ1wiIGluICcsYyxcIj9cIixjLFwiLlwiLGEsZSxcIjpcIixjLFwiLlwiLGEpfWE9YS5jb25zdGFudHMuYmxlbmRGdW5jczt2YXIgZT1kKFwic3JjXCIsXCJSR0JcIikscD1kKFwiZHN0XCIsXCJSR0JcIiksZT1iLmRlZihhLFwiW1wiLGUsXCJdXCIpLGY9Yi5kZWYoYSxcIltcIixkKFwic3JjXCIsXCJBbHBoYVwiKSxcIl1cIikscD1iLmRlZihhLFwiW1wiLHAsXCJdXCIpO2E9Yi5kZWYoYSxcIltcIixkKFwiZHN0XCIsXCJBbHBoYVwiKSxcIl1cIik7cmV0dXJuW2UscCxmLGFdfSk7Y2FzZSBcImJsZW5kLmVxdWF0aW9uXCI6cmV0dXJuIGIoZnVuY3Rpb24oYSl7aWYoXCJzdHJpbmdcIj09PXR5cGVvZiBhKXJldHVybltYW2FdLFhbYV1dO2lmKFwib2JqZWN0XCI9PT10eXBlb2YgYSlyZXR1cm5bWFthLnJnYl0sWFthLmFscGhhXV19LGZ1bmN0aW9uKGEsYixjKXt2YXIgZD1hLmNvbnN0YW50cy5ibGVuZEVxdWF0aW9ucyxlPWIuZGVmKCkscD1iLmRlZigpO2E9YS5jb25kKFwidHlwZW9mIFwiLGMsJz09PVwic3RyaW5nXCInKTthLnRoZW4oZSxcIj1cIixwLFwiPVwiLGQsXCJbXCIsXG5jLFwiXTtcIik7YVtcImVsc2VcIl0oZSxcIj1cIixkLFwiW1wiLGMsXCIucmdiXTtcIixwLFwiPVwiLGQsXCJbXCIsYyxcIi5hbHBoYV07XCIpO2IoYSk7cmV0dXJuW2UscF19KTtjYXNlIFwiYmxlbmQuY29sb3JcIjpyZXR1cm4gYihmdW5jdGlvbihhKXtyZXR1cm4gSig0LGZ1bmN0aW9uKGIpe3JldHVybithW2JdfSl9LGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSig0LGZ1bmN0aW9uKGEpe3JldHVybiBiLmRlZihcIitcIixjLFwiW1wiLGEsXCJdXCIpfSl9KTtjYXNlIFwic3RlbmNpbC5tYXNrXCI6cmV0dXJuIGIoZnVuY3Rpb24oYSl7cmV0dXJuIGF8MH0sZnVuY3Rpb24oYSxiLGMpe3JldHVybiBiLmRlZihjLFwifDBcIil9KTtjYXNlIFwic3RlbmNpbC5mdW5jXCI6cmV0dXJuIGIoZnVuY3Rpb24oYSl7cmV0dXJuW1hhW2EuY21wfHxcImtlZXBcIl0sYS5yZWZ8fDAsXCJtYXNrXCJpbiBhP2EubWFzazotMV19LGZ1bmN0aW9uKGEsYixjKXthPWIuZGVmKCdcImNtcFwiIGluICcsYyxcIj9cIixhLmNvbnN0YW50cy5jb21wYXJlRnVuY3MsXCJbXCIsYyxcIi5jbXBdXCIsXG5cIjpcIiw3NjgwKTt2YXIgZD1iLmRlZihjLFwiLnJlZnwwXCIpO2I9Yi5kZWYoJ1wibWFza1wiIGluICcsYyxcIj9cIixjLFwiLm1hc2t8MDotMVwiKTtyZXR1cm5bYSxkLGJdfSk7Y2FzZSBcInN0ZW5jaWwub3BGcm9udFwiOmNhc2UgXCJzdGVuY2lsLm9wQmFja1wiOnJldHVybiBiKGZ1bmN0aW9uKGIpe3JldHVybltcInN0ZW5jaWwub3BCYWNrXCI9PT1hPzEwMjk6MTAyOCxQYVtiLmZhaWx8fFwia2VlcFwiXSxQYVtiLnpmYWlsfHxcImtlZXBcIl0sUGFbYi56cGFzc3x8XCJrZWVwXCJdXX0sZnVuY3Rpb24oYixjLGQpe2Z1bmN0aW9uIGUoYSl7cmV0dXJuIGMuZGVmKCdcIicsYSwnXCIgaW4gJyxkLFwiP1wiLHAsXCJbXCIsZCxcIi5cIixhLFwiXTpcIiw3NjgwKX12YXIgcD1iLmNvbnN0YW50cy5zdGVuY2lsT3BzO3JldHVybltcInN0ZW5jaWwub3BCYWNrXCI9PT1hPzEwMjk6MTAyOCxlKFwiZmFpbFwiKSxlKFwiemZhaWxcIiksZShcInpwYXNzXCIpXX0pO2Nhc2UgXCJwb2x5Z29uT2Zmc2V0Lm9mZnNldFwiOnJldHVybiBiKGZ1bmN0aW9uKGEpe3JldHVyblthLmZhY3RvcnxcbjAsYS51bml0c3wwXX0sZnVuY3Rpb24oYSxiLGMpe2E9Yi5kZWYoYyxcIi5mYWN0b3J8MFwiKTtiPWIuZGVmKGMsXCIudW5pdHN8MFwiKTtyZXR1cm5bYSxiXX0pO2Nhc2UgXCJjdWxsLmZhY2VcIjpyZXR1cm4gYihmdW5jdGlvbihhKXt2YXIgYj0wO1wiZnJvbnRcIj09PWE/Yj0xMDI4OlwiYmFja1wiPT09YSYmKGI9MTAyOSk7cmV0dXJuIGJ9LGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gYi5kZWYoYywnPT09XCJmcm9udFwiPycsMTAyOCxcIjpcIiwxMDI5KX0pO2Nhc2UgXCJsaW5lV2lkdGhcIjpyZXR1cm4gYihmdW5jdGlvbihhKXtyZXR1cm4gYX0sZnVuY3Rpb24oYSxiLGMpe3JldHVybiBjfSk7Y2FzZSBcImZyb250RmFjZVwiOnJldHVybiBiKGZ1bmN0aW9uKGEpe3JldHVybiB3YlthXX0sZnVuY3Rpb24oYSxiLGMpe3JldHVybiBiLmRlZihjKyc9PT1cImN3XCI/MjMwNDoyMzA1Jyl9KTtjYXNlIFwiY29sb3JNYXNrXCI6cmV0dXJuIGIoZnVuY3Rpb24oYSl7cmV0dXJuIGEubWFwKGZ1bmN0aW9uKGEpe3JldHVybiEhYX0pfSxcbmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSig0LGZ1bmN0aW9uKGEpe3JldHVyblwiISFcIitjK1wiW1wiK2ErXCJdXCJ9KX0pO2Nhc2UgXCJzYW1wbGUuY292ZXJhZ2VcIjpyZXR1cm4gYihmdW5jdGlvbihhKXtyZXR1cm5bXCJ2YWx1ZVwiaW4gYT9hLnZhbHVlOjEsISFhLmludmVydF19LGZ1bmN0aW9uKGEsYixjKXthPWIuZGVmKCdcInZhbHVlXCIgaW4gJyxjLFwiPytcIixjLFwiLnZhbHVlOjFcIik7Yj1iLmRlZihcIiEhXCIsYyxcIi5pbnZlcnRcIik7cmV0dXJuW2EsYl19KX19KTtyZXR1cm4gZX1mdW5jdGlvbiBGKGEsYil7dmFyIGM9YVtcInN0YXRpY1wiXSxkPWEuZHluYW1pYyxlPXt9O09iamVjdC5rZXlzKGMpLmZvckVhY2goZnVuY3Rpb24oYSl7dmFyIGI9Y1thXSxkO2lmKFwibnVtYmVyXCI9PT10eXBlb2YgYnx8XCJib29sZWFuXCI9PT10eXBlb2YgYilkPUQoZnVuY3Rpb24oKXtyZXR1cm4gYn0pO2Vsc2UgaWYoXCJmdW5jdGlvblwiPT09dHlwZW9mIGIpe3ZhciBwPWIuX3JlZ2xUeXBlO2lmKFwidGV4dHVyZTJkXCI9PT1wfHxcblwidGV4dHVyZUN1YmVcIj09PXApZD1EKGZ1bmN0aW9uKGEpe3JldHVybiBhLmxpbmsoYil9KTtlbHNlIGlmKFwiZnJhbWVidWZmZXJcIj09PXB8fFwiZnJhbWVidWZmZXJDdWJlXCI9PT1wKWQ9RChmdW5jdGlvbihhKXtyZXR1cm4gYS5saW5rKGIuY29sb3JbMF0pfSl9ZWxzZSBwYShiKSYmKGQ9RChmdW5jdGlvbihhKXtyZXR1cm4gYS5nbG9iYWwuZGVmKFwiW1wiLEooYi5sZW5ndGgsZnVuY3Rpb24oYSl7cmV0dXJuIGJbYV19KSxcIl1cIil9KSk7ZC52YWx1ZT1iO2VbYV09ZH0pO09iamVjdC5rZXlzKGQpLmZvckVhY2goZnVuY3Rpb24oYSl7dmFyIGI9ZFthXTtlW2FdPVAoYixmdW5jdGlvbihhLGMpe3JldHVybiBhLmludm9rZShjLGIpfSl9KTtyZXR1cm4gZX1mdW5jdGlvbiBUKGEsYyl7dmFyIGQ9YVtcInN0YXRpY1wiXSxlPWEuZHluYW1pYyxmPXt9O09iamVjdC5rZXlzKGQpLmZvckVhY2goZnVuY3Rpb24oYSl7dmFyIGM9ZFthXSxlPWIuaWQoYSkscD1uZXcgeWE7aWYoT2EoYykpcC5zdGF0ZT0xLFxucC5idWZmZXI9Zy5nZXRCdWZmZXIoZy5jcmVhdGUoYywzNDk2MiwhMSwhMCkpLHAudHlwZT0wO2Vsc2V7dmFyIHc9Zy5nZXRCdWZmZXIoYyk7aWYodylwLnN0YXRlPTEscC5idWZmZXI9dyxwLnR5cGU9MDtlbHNlIGlmKFwiY29uc3RhbnRcImluIGMpe3ZhciBoPWMuY29uc3RhbnQ7cC5idWZmZXI9XCJudWxsXCI7cC5zdGF0ZT0yO1wibnVtYmVyXCI9PT10eXBlb2YgaD9wLng9aDpEYS5mb3JFYWNoKGZ1bmN0aW9uKGEsYil7YjxoLmxlbmd0aCYmKHBbYV09aFtiXSl9KX1lbHNle3ZhciB3PU9hKGMuYnVmZmVyKT9nLmdldEJ1ZmZlcihnLmNyZWF0ZShjLmJ1ZmZlciwzNDk2MiwhMSwhMCkpOmcuZ2V0QnVmZmVyKGMuYnVmZmVyKSxrPWMub2Zmc2V0fDAsbT1jLnN0cmlkZXwwLEk9Yy5zaXplfDAsbD0hIWMubm9ybWFsaXplZCxuPTA7XCJ0eXBlXCJpbiBjJiYobj1SYVtjLnR5cGVdKTtjPWMuZGl2aXNvcnwwO3AuYnVmZmVyPXc7cC5zdGF0ZT0xO3Auc2l6ZT1JO3Aubm9ybWFsaXplZD1sO3AudHlwZT1cbm58fHcuZHR5cGU7cC5vZmZzZXQ9aztwLnN0cmlkZT1tO3AuZGl2aXNvcj1jfX1mW2FdPUQoZnVuY3Rpb24oYSxiKXt2YXIgYz1hLmF0dHJpYkNhY2hlO2lmKGUgaW4gYylyZXR1cm4gY1tlXTt2YXIgZD17aXNTdHJlYW06ITF9O09iamVjdC5rZXlzKHApLmZvckVhY2goZnVuY3Rpb24oYSl7ZFthXT1wW2FdfSk7cC5idWZmZXImJihkLmJ1ZmZlcj1hLmxpbmsocC5idWZmZXIpLGQudHlwZT1kLnR5cGV8fGQuYnVmZmVyK1wiLmR0eXBlXCIpO3JldHVybiBjW2VdPWR9KX0pO09iamVjdC5rZXlzKGUpLmZvckVhY2goZnVuY3Rpb24oYSl7dmFyIGI9ZVthXTtmW2FdPVAoYixmdW5jdGlvbihhLGMpe2Z1bmN0aW9uIGQoYSl7Yyh3W2FdLFwiPVwiLGUsXCIuXCIsYSxcInwwO1wiKX12YXIgZT1hLmludm9rZShjLGIpLHA9YS5zaGFyZWQsZj1wLmlzQnVmZmVyQXJncyxnPXAuYnVmZmVyLHc9e2lzU3RyZWFtOmMuZGVmKCExKX0saD1uZXcgeWE7aC5zdGF0ZT0xO09iamVjdC5rZXlzKGgpLmZvckVhY2goZnVuY3Rpb24oYSl7d1thXT1cbmMuZGVmKFwiXCIraFthXSl9KTt2YXIgej13LmJ1ZmZlcixrPXcudHlwZTtjKFwiaWYoXCIsZixcIihcIixlLFwiKSl7XCIsdy5pc1N0cmVhbSxcIj10cnVlO1wiLHosXCI9XCIsZyxcIi5jcmVhdGVTdHJlYW0oXCIsMzQ5NjIsXCIsXCIsZSxcIik7XCIsayxcIj1cIix6LFwiLmR0eXBlO1wiLFwifWVsc2V7XCIseixcIj1cIixnLFwiLmdldEJ1ZmZlcihcIixlLFwiKTtcIixcImlmKFwiLHosXCIpe1wiLGssXCI9XCIseixcIi5kdHlwZTtcIiwnfWVsc2UgaWYoXCJjb25zdGFudFwiIGluICcsZSxcIil7XCIsdy5zdGF0ZSxcIj1cIiwyLFwiO1wiLFwiaWYodHlwZW9mIFwiK2UrJy5jb25zdGFudCA9PT0gXCJudW1iZXJcIil7Jyx3W0RhWzBdXSxcIj1cIixlLFwiLmNvbnN0YW50O1wiLERhLnNsaWNlKDEpLm1hcChmdW5jdGlvbihhKXtyZXR1cm4gd1thXX0pLmpvaW4oXCI9XCIpLFwiPTA7XCIsXCJ9ZWxzZXtcIixEYS5tYXAoZnVuY3Rpb24oYSxiKXtyZXR1cm4gd1thXStcIj1cIitlK1wiLmNvbnN0YW50Lmxlbmd0aD5cIitiK1wiP1wiK2UrXCIuY29uc3RhbnRbXCIrYitcIl06MDtcIn0pLmpvaW4oXCJcIiksXCJ9fWVsc2V7XCIsXG5cImlmKFwiLGYsXCIoXCIsZSxcIi5idWZmZXIpKXtcIix6LFwiPVwiLGcsXCIuY3JlYXRlU3RyZWFtKFwiLDM0OTYyLFwiLFwiLGUsXCIuYnVmZmVyKTtcIixcIn1lbHNle1wiLHosXCI9XCIsZyxcIi5nZXRCdWZmZXIoXCIsZSxcIi5idWZmZXIpO1wiLFwifVwiLGssJz1cInR5cGVcIiBpbiAnLGUsXCI/XCIscC5nbFR5cGVzLFwiW1wiLGUsXCIudHlwZV06XCIseixcIi5kdHlwZTtcIix3Lm5vcm1hbGl6ZWQsXCI9ISFcIixlLFwiLm5vcm1hbGl6ZWQ7XCIpO2QoXCJzaXplXCIpO2QoXCJvZmZzZXRcIik7ZChcInN0cmlkZVwiKTtkKFwiZGl2aXNvclwiKTtjKFwifX1cIik7Yy5leGl0KFwiaWYoXCIsdy5pc1N0cmVhbSxcIil7XCIsZyxcIi5kZXN0cm95U3RyZWFtKFwiLHosXCIpO1wiLFwifVwiKTtyZXR1cm4gd30pfSk7cmV0dXJuIGZ9ZnVuY3Rpb24gTShhKXt2YXIgYj1hW1wic3RhdGljXCJdLGM9YS5keW5hbWljLGQ9e307T2JqZWN0LmtleXMoYikuZm9yRWFjaChmdW5jdGlvbihhKXt2YXIgYz1iW2FdO2RbYV09RChmdW5jdGlvbihhLGIpe3JldHVyblwibnVtYmVyXCI9PT10eXBlb2YgY3x8XG5cImJvb2xlYW5cIj09PXR5cGVvZiBjP1wiXCIrYzphLmxpbmsoYyl9KX0pO09iamVjdC5rZXlzKGMpLmZvckVhY2goZnVuY3Rpb24oYSl7dmFyIGI9Y1thXTtkW2FdPVAoYixmdW5jdGlvbihhLGMpe3JldHVybiBhLmludm9rZShjLGIpfSl9KTtyZXR1cm4gZH1mdW5jdGlvbiBBKGEsYixjLGQsZSl7dmFyIGY9eShhLGUpLGc9eChhLGYsZSksaD1PKGEsZSksaz1SKGEsZSksbT1FKGEsZSksYmE9Zy52aWV3cG9ydDtiYSYmKGsudmlld3BvcnQ9YmEpO2JhPWwoXCJzY2lzc29yLmJveFwiKTsoZz1nW2JhXSkmJihrW2JhXT1nKTtnPTA8T2JqZWN0LmtleXMoaykubGVuZ3RoO2Y9e2ZyYW1lYnVmZmVyOmYsZHJhdzpoLHNoYWRlcjptLHN0YXRlOmssZGlydHk6Z307Zi5wcm9maWxlPUIoYSxlKTtmLnVuaWZvcm1zPUYoYyxlKTtmLmF0dHJpYnV0ZXM9VChiLGUpO2YuY29udGV4dD1NKGQsZSk7cmV0dXJuIGZ9ZnVuY3Rpb24gdWEoYSxiLGMpe3ZhciBkPWEuc2hhcmVkLmNvbnRleHQsZT1hLnNjb3BlKCk7XG5PYmplY3Qua2V5cyhjKS5mb3JFYWNoKGZ1bmN0aW9uKGYpe2Iuc2F2ZShkLFwiLlwiK2YpO2UoZCxcIi5cIixmLFwiPVwiLGNbZl0uYXBwZW5kKGEsYiksXCI7XCIpfSk7YihlKX1mdW5jdGlvbiBLKGEsYixjLGQpe3ZhciBlPWEuc2hhcmVkLGY9ZS5nbCxnPWUuZnJhbWVidWZmZXIsaDtoYSYmKGg9Yi5kZWYoZS5leHRlbnNpb25zLFwiLndlYmdsX2RyYXdfYnVmZmVyc1wiKSk7dmFyIGs9YS5jb25zdGFudHMsZT1rLmRyYXdCdWZmZXIsaz1rLmJhY2tCdWZmZXI7YT1jP2MuYXBwZW5kKGEsYik6Yi5kZWYoZyxcIi5uZXh0XCIpO2R8fGIoXCJpZihcIixhLFwiIT09XCIsZyxcIi5jdXIpe1wiKTtiKFwiaWYoXCIsYSxcIil7XCIsZixcIi5iaW5kRnJhbWVidWZmZXIoXCIsMzYxNjAsXCIsXCIsYSxcIi5mcmFtZWJ1ZmZlcik7XCIpO2hhJiZiKGgsXCIuZHJhd0J1ZmZlcnNXRUJHTChcIixlLFwiW1wiLGEsXCIuY29sb3JBdHRhY2htZW50cy5sZW5ndGhdKTtcIik7YihcIn1lbHNle1wiLGYsXCIuYmluZEZyYW1lYnVmZmVyKFwiLDM2MTYwLFwiLG51bGwpO1wiKTtcbmhhJiZiKGgsXCIuZHJhd0J1ZmZlcnNXRUJHTChcIixrLFwiKTtcIik7YihcIn1cIixnLFwiLmN1cj1cIixhLFwiO1wiKTtkfHxiKFwifVwiKX1mdW5jdGlvbiBWKGEsYixjKXt2YXIgZD1hLnNoYXJlZCxlPWQuZ2wsZj1hLmN1cnJlbnQsZz1hLm5leHQsaD1kLmN1cnJlbnQsaz1kLm5leHQsbT1hLmNvbmQoaCxcIi5kaXJ0eVwiKTtLYS5mb3JFYWNoKGZ1bmN0aW9uKGIpe2I9bChiKTtpZighKGIgaW4gYy5zdGF0ZSkpe3ZhciBkLHc7aWYoYiBpbiBnKXtkPWdbYl07dz1mW2JdO3ZhciBJPUoocmFbYl0ubGVuZ3RoLGZ1bmN0aW9uKGEpe3JldHVybiBtLmRlZihkLFwiW1wiLGEsXCJdXCIpfSk7bShhLmNvbmQoSS5tYXAoZnVuY3Rpb24oYSxiKXtyZXR1cm4gYStcIiE9PVwiK3crXCJbXCIrYitcIl1cIn0pLmpvaW4oXCJ8fFwiKSkudGhlbihlLFwiLlwiLHRhW2JdLFwiKFwiLEksXCIpO1wiLEkubWFwKGZ1bmN0aW9uKGEsYil7cmV0dXJuIHcrXCJbXCIrYitcIl09XCIrYX0pLmpvaW4oXCI7XCIpLFwiO1wiKSl9ZWxzZSBkPW0uZGVmKGssXCIuXCIsYiksST1hLmNvbmQoZCxcblwiIT09XCIsaCxcIi5cIixiKSxtKEkpLGIgaW4gc2E/SShhLmNvbmQoZCkudGhlbihlLFwiLmVuYWJsZShcIixzYVtiXSxcIik7XCIpW1wiZWxzZVwiXShlLFwiLmRpc2FibGUoXCIsc2FbYl0sXCIpO1wiKSxoLFwiLlwiLGIsXCI9XCIsZCxcIjtcIik6SShlLFwiLlwiLHRhW2JdLFwiKFwiLGQsXCIpO1wiLGgsXCIuXCIsYixcIj1cIixkLFwiO1wiKX19KTswPT09T2JqZWN0LmtleXMoYy5zdGF0ZSkubGVuZ3RoJiZtKGgsXCIuZGlydHk9ZmFsc2U7XCIpO2IobSl9ZnVuY3Rpb24gUShhLGIsYyxkKXt2YXIgZT1hLnNoYXJlZCxmPWEuY3VycmVudCxnPWUuY3VycmVudCxoPWUuZ2w7dmIoT2JqZWN0LmtleXMoYykpLmZvckVhY2goZnVuY3Rpb24oZSl7dmFyIGs9Y1tlXTtpZighZHx8ZChrKSl7dmFyIG09ay5hcHBlbmQoYSxiKTtpZihzYVtlXSl7dmFyIGw9c2FbZV07dmEoayk/bT9iKGgsXCIuZW5hYmxlKFwiLGwsXCIpO1wiKTpiKGgsXCIuZGlzYWJsZShcIixsLFwiKTtcIik6YihhLmNvbmQobSkudGhlbihoLFwiLmVuYWJsZShcIixsLFwiKTtcIilbXCJlbHNlXCJdKGgsXG5cIi5kaXNhYmxlKFwiLGwsXCIpO1wiKSk7YihnLFwiLlwiLGUsXCI9XCIsbSxcIjtcIil9ZWxzZSBpZihwYShtKSl7dmFyIG49ZltlXTtiKGgsXCIuXCIsdGFbZV0sXCIoXCIsbSxcIik7XCIsbS5tYXAoZnVuY3Rpb24oYSxiKXtyZXR1cm4gbitcIltcIitiK1wiXT1cIithfSkuam9pbihcIjtcIiksXCI7XCIpfWVsc2UgYihoLFwiLlwiLHRhW2VdLFwiKFwiLG0sXCIpO1wiLGcsXCIuXCIsZSxcIj1cIixtLFwiO1wiKX19KX1mdW5jdGlvbiB3YShhLGIpe2VhJiYoYS5pbnN0YW5jaW5nPWIuZGVmKGEuc2hhcmVkLmV4dGVuc2lvbnMsXCIuYW5nbGVfaW5zdGFuY2VkX2FycmF5c1wiKSl9ZnVuY3Rpb24gRyhhLGIsYyxkLGUpe2Z1bmN0aW9uIGYoKXtyZXR1cm5cInVuZGVmaW5lZFwiPT09dHlwZW9mIHBlcmZvcm1hbmNlP1wiRGF0ZS5ub3coKVwiOlwicGVyZm9ybWFuY2Uubm93KClcIn1mdW5jdGlvbiBnKGEpe3Q9Yi5kZWYoKTthKHQsXCI9XCIsZigpLFwiO1wiKTtcInN0cmluZ1wiPT09dHlwZW9mIGU/YShiYSxcIi5jb3VudCs9XCIsZSxcIjtcIik6YShiYSxcIi5jb3VudCsrO1wiKTtcbmsmJihkPyhyPWIuZGVmKCksYShyLFwiPVwiLHEsXCIuZ2V0TnVtUGVuZGluZ1F1ZXJpZXMoKTtcIikpOmEocSxcIi5iZWdpblF1ZXJ5KFwiLGJhLFwiKTtcIikpfWZ1bmN0aW9uIGgoYSl7YShiYSxcIi5jcHVUaW1lKz1cIixmKCksXCItXCIsdCxcIjtcIik7ayYmKGQ/YShxLFwiLnB1c2hTY29wZVN0YXRzKFwiLHIsXCIsXCIscSxcIi5nZXROdW1QZW5kaW5nUXVlcmllcygpLFwiLGJhLFwiKTtcIik6YShxLFwiLmVuZFF1ZXJ5KCk7XCIpKX1mdW5jdGlvbiBtKGEpe3ZhciBjPWIuZGVmKG4sXCIucHJvZmlsZVwiKTtiKG4sXCIucHJvZmlsZT1cIixhLFwiO1wiKTtiLmV4aXQobixcIi5wcm9maWxlPVwiLGMsXCI7XCIpfXZhciBsPWEuc2hhcmVkLGJhPWEuc3RhdHMsbj1sLmN1cnJlbnQscT1sLnRpbWVyO2M9Yy5wcm9maWxlO3ZhciB0LHI7aWYoYyl7aWYodmEoYykpe2MuZW5hYmxlPyhnKGIpLGgoYi5leGl0KSxtKFwidHJ1ZVwiKSk6bShcImZhbHNlXCIpO3JldHVybn1jPWMuYXBwZW5kKGEsYik7bShjKX1lbHNlIGM9Yi5kZWYobixcIi5wcm9maWxlXCIpO1xubD1hLmJsb2NrKCk7ZyhsKTtiKFwiaWYoXCIsYyxcIil7XCIsbCxcIn1cIik7YT1hLmJsb2NrKCk7aChhKTtiLmV4aXQoXCJpZihcIixjLFwiKXtcIixhLFwifVwiKX1mdW5jdGlvbiBVKGEsYixjLGQsZSl7ZnVuY3Rpb24gZihhKXtzd2l0Y2goYSl7Y2FzZSAzNTY2NDpjYXNlIDM1NjY3OmNhc2UgMzU2NzE6cmV0dXJuIDI7Y2FzZSAzNTY2NTpjYXNlIDM1NjY4OmNhc2UgMzU2NzI6cmV0dXJuIDM7Y2FzZSAzNTY2NjpjYXNlIDM1NjY5OmNhc2UgMzU2NzM6cmV0dXJuIDQ7ZGVmYXVsdDpyZXR1cm4gMX19ZnVuY3Rpb24gZyhjLGQsZSl7ZnVuY3Rpb24gZigpe2IoXCJpZighXCIseixcIi5idWZmZXIpe1wiLGssXCIuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoXCIsbCxcIik7fVwiKTt2YXIgYz1lLnR5cGUsZztnPWUuc2l6ZT9iLmRlZihlLnNpemUsXCJ8fFwiLGQpOmQ7YihcImlmKFwiLHosXCIudHlwZSE9PVwiLGMsXCJ8fFwiLHosXCIuc2l6ZSE9PVwiLGcsXCJ8fFwiLHEubWFwKGZ1bmN0aW9uKGEpe3JldHVybiB6K1wiLlwiK2ErXCIhPT1cIitlW2FdfSkuam9pbihcInx8XCIpLFxuXCIpe1wiLGssXCIuYmluZEJ1ZmZlcihcIiwzNDk2MixcIixcIixJLFwiLmJ1ZmZlcik7XCIsayxcIi52ZXJ0ZXhBdHRyaWJQb2ludGVyKFwiLFtsLGcsYyxlLm5vcm1hbGl6ZWQsZS5zdHJpZGUsZS5vZmZzZXRdLFwiKTtcIix6LFwiLnR5cGU9XCIsYyxcIjtcIix6LFwiLnNpemU9XCIsZyxcIjtcIixxLm1hcChmdW5jdGlvbihhKXtyZXR1cm4geitcIi5cIithK1wiPVwiK2VbYV0rXCI7XCJ9KS5qb2luKFwiXCIpLFwifVwiKTtlYSYmKGM9ZS5kaXZpc29yLGIoXCJpZihcIix6LFwiLmRpdmlzb3IhPT1cIixjLFwiKXtcIixhLmluc3RhbmNpbmcsXCIudmVydGV4QXR0cmliRGl2aXNvckFOR0xFKFwiLFtsLGNdLFwiKTtcIix6LFwiLmRpdmlzb3I9XCIsYyxcIjt9XCIpKX1mdW5jdGlvbiBtKCl7YihcImlmKFwiLHosXCIuYnVmZmVyKXtcIixrLFwiLmRpc2FibGVWZXJ0ZXhBdHRyaWJBcnJheShcIixsLFwiKTtcIixcIn1pZihcIixEYS5tYXAoZnVuY3Rpb24oYSxiKXtyZXR1cm4geitcIi5cIithK1wiIT09XCIrbltiXX0pLmpvaW4oXCJ8fFwiKSxcIil7XCIsayxcIi52ZXJ0ZXhBdHRyaWI0ZihcIixcbmwsXCIsXCIsbixcIik7XCIsRGEubWFwKGZ1bmN0aW9uKGEsYil7cmV0dXJuIHorXCIuXCIrYStcIj1cIituW2JdK1wiO1wifSkuam9pbihcIlwiKSxcIn1cIil9dmFyIGs9aC5nbCxsPWIuZGVmKGMsXCIubG9jYXRpb25cIiksej1iLmRlZihoLmF0dHJpYnV0ZXMsXCJbXCIsbCxcIl1cIik7Yz1lLnN0YXRlO3ZhciBJPWUuYnVmZmVyLG49W2UueCxlLnksZS56LGUud10scT1bXCJidWZmZXJcIixcIm5vcm1hbGl6ZWRcIixcIm9mZnNldFwiLFwic3RyaWRlXCJdOzE9PT1jP2YoKToyPT09Yz9tKCk6KGIoXCJpZihcIixjLFwiPT09XCIsMSxcIil7XCIpLGYoKSxiKFwifWVsc2V7XCIpLG0oKSxiKFwifVwiKSl9dmFyIGg9YS5zaGFyZWQ7ZC5mb3JFYWNoKGZ1bmN0aW9uKGQpe3ZhciBoPWQubmFtZSxrPWMuYXR0cmlidXRlc1toXSxtO2lmKGspe2lmKCFlKGspKXJldHVybjttPWsuYXBwZW5kKGEsYil9ZWxzZXtpZighZSh4YikpcmV0dXJuO3ZhciBsPWEuc2NvcGVBdHRyaWIoaCk7bT17fTtPYmplY3Qua2V5cyhuZXcgeWEpLmZvckVhY2goZnVuY3Rpb24oYSl7bVthXT1cbmIuZGVmKGwsXCIuXCIsYSl9KX1nKGEubGluayhkKSxmKGQuaW5mby50eXBlKSxtKX0pfWZ1bmN0aW9uIFcoYSxjLGQsZSxmKXtmb3IodmFyIGc9YS5zaGFyZWQsaD1nLmdsLGssbT0wO208ZS5sZW5ndGg7KyttKXt2YXIgbD1lW21dLG49bC5uYW1lLHE9bC5pbmZvLnR5cGUsdD1kLnVuaWZvcm1zW25dLGw9YS5saW5rKGwpK1wiLmxvY2F0aW9uXCIscjtpZih0KXtpZighZih0KSljb250aW51ZTtpZih2YSh0KSl7bj10LnZhbHVlO2lmKDM1Njc4PT09cXx8MzU2ODA9PT1xKXE9YS5saW5rKG4uX3RleHR1cmV8fG4uY29sb3JbMF0uX3RleHR1cmUpLGMoaCxcIi51bmlmb3JtMWkoXCIsbCxcIixcIixxK1wiLmJpbmQoKSk7XCIpLGMuZXhpdChxLFwiLnVuYmluZCgpO1wiKTtlbHNlIGlmKDM1Njc0PT09cXx8MzU2NzU9PT1xfHwzNTY3Nj09PXEpbj1hLmdsb2JhbC5kZWYoXCJuZXcgRmxvYXQzMkFycmF5KFtcIitBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChuKStcIl0pXCIpLHQ9MiwzNTY3NT09PXE/dD0zOjM1Njc2PT09XG5xJiYodD00KSxjKGgsXCIudW5pZm9ybU1hdHJpeFwiLHQsXCJmdihcIixsLFwiLGZhbHNlLFwiLG4sXCIpO1wiKTtlbHNle3N3aXRjaChxKXtjYXNlIDUxMjY6az1cIjFmXCI7YnJlYWs7Y2FzZSAzNTY2NDprPVwiMmZcIjticmVhaztjYXNlIDM1NjY1Oms9XCIzZlwiO2JyZWFrO2Nhc2UgMzU2NjY6az1cIjRmXCI7YnJlYWs7Y2FzZSAzNTY3MDprPVwiMWlcIjticmVhaztjYXNlIDUxMjQ6az1cIjFpXCI7YnJlYWs7Y2FzZSAzNTY3MTprPVwiMmlcIjticmVhaztjYXNlIDM1NjY3Oms9XCIyaVwiO2JyZWFrO2Nhc2UgMzU2NzI6az1cIjNpXCI7YnJlYWs7Y2FzZSAzNTY2ODprPVwiM2lcIjticmVhaztjYXNlIDM1NjczOms9XCI0aVwiO2JyZWFrO2Nhc2UgMzU2Njk6az1cIjRpXCJ9YyhoLFwiLnVuaWZvcm1cIixrLFwiKFwiLGwsXCIsXCIscGEobik/QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobik6bixcIik7XCIpfWNvbnRpbnVlfWVsc2Ugcj10LmFwcGVuZChhLGMpfWVsc2V7aWYoIWYoeGIpKWNvbnRpbnVlO3I9Yy5kZWYoZy51bmlmb3JtcyxcIltcIixcbmIuaWQobiksXCJdXCIpfTM1Njc4PT09cT9jKFwiaWYoXCIscixcIiYmXCIsciwnLl9yZWdsVHlwZT09PVwiZnJhbWVidWZmZXJcIil7JyxyLFwiPVwiLHIsXCIuY29sb3JbMF07XCIsXCJ9XCIpOjM1NjgwPT09cSYmYyhcImlmKFwiLHIsXCImJlwiLHIsJy5fcmVnbFR5cGU9PT1cImZyYW1lYnVmZmVyQ3ViZVwiKXsnLHIsXCI9XCIscixcIi5jb2xvclswXTtcIixcIn1cIik7bj0xO3N3aXRjaChxKXtjYXNlIDM1Njc4OmNhc2UgMzU2ODA6cT1jLmRlZihyLFwiLl90ZXh0dXJlXCIpO2MoaCxcIi51bmlmb3JtMWkoXCIsbCxcIixcIixxLFwiLmJpbmQoKSk7XCIpO2MuZXhpdChxLFwiLnVuYmluZCgpO1wiKTtjb250aW51ZTtjYXNlIDUxMjQ6Y2FzZSAzNTY3MDprPVwiMWlcIjticmVhaztjYXNlIDM1NjY3OmNhc2UgMzU2NzE6az1cIjJpXCI7bj0yO2JyZWFrO2Nhc2UgMzU2Njg6Y2FzZSAzNTY3MjprPVwiM2lcIjtuPTM7YnJlYWs7Y2FzZSAzNTY2OTpjYXNlIDM1NjczOms9XCI0aVwiO249NDticmVhaztjYXNlIDUxMjY6az1cIjFmXCI7YnJlYWs7Y2FzZSAzNTY2NDprPVxuXCIyZlwiO249MjticmVhaztjYXNlIDM1NjY1Oms9XCIzZlwiO249MzticmVhaztjYXNlIDM1NjY2Oms9XCI0ZlwiO249NDticmVhaztjYXNlIDM1Njc0Oms9XCJNYXRyaXgyZnZcIjticmVhaztjYXNlIDM1Njc1Oms9XCJNYXRyaXgzZnZcIjticmVhaztjYXNlIDM1Njc2Oms9XCJNYXRyaXg0ZnZcIn1jKGgsXCIudW5pZm9ybVwiLGssXCIoXCIsbCxcIixcIik7aWYoXCJNXCI9PT1rLmNoYXJBdCgwKSl7dmFyIGw9TWF0aC5wb3cocS0zNTY3NCsyLDIpLHY9YS5nbG9iYWwuZGVmKFwibmV3IEZsb2F0MzJBcnJheShcIixsLFwiKVwiKTtjKFwiZmFsc2UsKEFycmF5LmlzQXJyYXkoXCIscixcIil8fFwiLHIsXCIgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkpP1wiLHIsXCI6KFwiLEoobCxmdW5jdGlvbihhKXtyZXR1cm4gditcIltcIithK1wiXT1cIityK1wiW1wiK2ErXCJdXCJ9KSxcIixcIix2LFwiKVwiKX1lbHNlIDE8bj9jKEoobixmdW5jdGlvbihhKXtyZXR1cm4gcitcIltcIithK1wiXVwifSkpOmMocik7YyhcIik7XCIpfX1mdW5jdGlvbiBTKGEsYixjLGQpe2Z1bmN0aW9uIGUoZil7dmFyIGc9XG5sW2ZdO3JldHVybiBnP2cuY29udGV4dERlcCYmZC5jb250ZXh0RHluYW1pY3x8Zy5wcm9wRGVwP2cuYXBwZW5kKGEsYyk6Zy5hcHBlbmQoYSxiKTpiLmRlZihtLFwiLlwiLGYpfWZ1bmN0aW9uIGYoKXtmdW5jdGlvbiBhKCl7Yyh1LFwiLmRyYXdFbGVtZW50c0luc3RhbmNlZEFOR0xFKFwiLFtxLHQsQyxyK1wiPDwoKFwiK0MrXCItNTEyMSk+PjEpXCIsdl0sXCIpO1wiKX1mdW5jdGlvbiBiKCl7Yyh1LFwiLmRyYXdBcnJheXNJbnN0YW5jZWRBTkdMRShcIixbcSxyLHQsdl0sXCIpO1wiKX1uP2RhP2EoKTooYyhcImlmKFwiLG4sXCIpe1wiKSxhKCksYyhcIn1lbHNle1wiKSxiKCksYyhcIn1cIikpOmIoKX1mdW5jdGlvbiBnKCl7ZnVuY3Rpb24gYSgpe2MoaytcIi5kcmF3RWxlbWVudHMoXCIrW3EsdCxDLHIrXCI8PCgoXCIrQytcIi01MTIxKT4+MSlcIl0rXCIpO1wiKX1mdW5jdGlvbiBiKCl7YyhrK1wiLmRyYXdBcnJheXMoXCIrW3Escix0XStcIik7XCIpfW4/ZGE/YSgpOihjKFwiaWYoXCIsbixcIil7XCIpLGEoKSxjKFwifWVsc2V7XCIpLGIoKSxjKFwifVwiKSk6XG5iKCl9dmFyIGg9YS5zaGFyZWQsaz1oLmdsLG09aC5kcmF3LGw9ZC5kcmF3LG49ZnVuY3Rpb24oKXt2YXIgZT1sLmVsZW1lbnRzLGY9YjtpZihlKXtpZihlLmNvbnRleHREZXAmJmQuY29udGV4dER5bmFtaWN8fGUucHJvcERlcClmPWM7ZT1lLmFwcGVuZChhLGYpfWVsc2UgZT1mLmRlZihtLFwiLlwiLFwiZWxlbWVudHNcIik7ZSYmZihcImlmKFwiK2UrXCIpXCIraytcIi5iaW5kQnVmZmVyKDM0OTYzLFwiK2UrXCIuYnVmZmVyLmJ1ZmZlcik7XCIpO3JldHVybiBlfSgpLHE9ZShcInByaW1pdGl2ZVwiKSxyPWUoXCJvZmZzZXRcIiksdD1mdW5jdGlvbigpe3ZhciBlPWwuY291bnQsZj1iO2lmKGUpe2lmKGUuY29udGV4dERlcCYmZC5jb250ZXh0RHluYW1pY3x8ZS5wcm9wRGVwKWY9YztlPWUuYXBwZW5kKGEsZil9ZWxzZSBlPWYuZGVmKG0sXCIuXCIsXCJjb3VudFwiKTtyZXR1cm4gZX0oKTtpZihcIm51bWJlclwiPT09dHlwZW9mIHQpe2lmKDA9PT10KXJldHVybn1lbHNlIGMoXCJpZihcIix0LFwiKXtcIiksYy5leGl0KFwifVwiKTt2YXIgdixcbnU7ZWEmJih2PWUoXCJpbnN0YW5jZXNcIiksdT1hLmluc3RhbmNpbmcpO3ZhciBDPW4rXCIudHlwZVwiLGRhPWwuZWxlbWVudHMmJnZhKGwuZWxlbWVudHMpO2VhJiYoXCJudW1iZXJcIiE9PXR5cGVvZiB2fHwwPD12KT9cInN0cmluZ1wiPT09dHlwZW9mIHY/KGMoXCJpZihcIix2LFwiPjApe1wiKSxmKCksYyhcIn1lbHNlIGlmKFwiLHYsXCI8MCl7XCIpLGcoKSxjKFwifVwiKSk6ZigpOmcoKX1mdW5jdGlvbiBjYShhLGIsYyxkLGUpe2I9TigpO2U9Yi5wcm9jKFwiYm9keVwiLGUpO2VhJiYoYi5pbnN0YW5jaW5nPWUuZGVmKGIuc2hhcmVkLmV4dGVuc2lvbnMsXCIuYW5nbGVfaW5zdGFuY2VkX2FycmF5c1wiKSk7YShiLGUsYyxkKTtyZXR1cm4gYi5jb21waWxlKCkuYm9keX1mdW5jdGlvbiBMKGEsYixjLGQpe3dhKGEsYik7VShhLGIsYyxkLmF0dHJpYnV0ZXMsZnVuY3Rpb24oKXtyZXR1cm4hMH0pO1coYSxiLGMsZC51bmlmb3JtcyxmdW5jdGlvbigpe3JldHVybiEwfSk7UyhhLGIsYixjKX1mdW5jdGlvbiBkYShhLGIpe3ZhciBjPVxuYS5wcm9jKFwiZHJhd1wiLDEpO3dhKGEsYyk7dWEoYSxjLGIuY29udGV4dCk7SyhhLGMsYi5mcmFtZWJ1ZmZlcik7VihhLGMsYik7UShhLGMsYi5zdGF0ZSk7RyhhLGMsYiwhMSwhMCk7dmFyIGQ9Yi5zaGFkZXIucHJvZ1Zhci5hcHBlbmQoYSxjKTtjKGEuc2hhcmVkLmdsLFwiLnVzZVByb2dyYW0oXCIsZCxcIi5wcm9ncmFtKTtcIik7aWYoYi5zaGFkZXIucHJvZ3JhbSlMKGEsYyxiLGIuc2hhZGVyLnByb2dyYW0pO2Vsc2V7dmFyIGU9YS5nbG9iYWwuZGVmKFwie31cIiksZj1jLmRlZihkLFwiLmlkXCIpLGc9Yy5kZWYoZSxcIltcIixmLFwiXVwiKTtjKGEuY29uZChnKS50aGVuKGcsXCIuY2FsbCh0aGlzLGEwKTtcIilbXCJlbHNlXCJdKGcsXCI9XCIsZSxcIltcIixmLFwiXT1cIixhLmxpbmsoZnVuY3Rpb24oYyl7cmV0dXJuIGNhKEwsYSxiLGMsMSl9KSxcIihcIixkLFwiKTtcIixnLFwiLmNhbGwodGhpcyxhMCk7XCIpKX0wPE9iamVjdC5rZXlzKGIuc3RhdGUpLmxlbmd0aCYmYyhhLnNoYXJlZC5jdXJyZW50LFwiLmRpcnR5PXRydWU7XCIpfVxuZnVuY3Rpb24gb2EoYSxiLGMsZCl7ZnVuY3Rpb24gZSgpe3JldHVybiEwfWEuYmF0Y2hJZD1cImExXCI7d2EoYSxiKTtVKGEsYixjLGQuYXR0cmlidXRlcyxlKTtXKGEsYixjLGQudW5pZm9ybXMsZSk7UyhhLGIsYixjKX1mdW5jdGlvbiB6YShhLGIsYyxkKXtmdW5jdGlvbiBlKGEpe3JldHVybiBhLmNvbnRleHREZXAmJmd8fGEucHJvcERlcH1mdW5jdGlvbiBmKGEpe3JldHVybiFlKGEpfXdhKGEsYik7dmFyIGc9Yy5jb250ZXh0RGVwLGg9Yi5kZWYoKSxrPWIuZGVmKCk7YS5zaGFyZWQucHJvcHM9azthLmJhdGNoSWQ9aDt2YXIgbT1hLnNjb3BlKCksbD1hLnNjb3BlKCk7YihtLmVudHJ5LFwiZm9yKFwiLGgsXCI9MDtcIixoLFwiPFwiLFwiYTFcIixcIjsrK1wiLGgsXCIpe1wiLGssXCI9XCIsXCJhMFwiLFwiW1wiLGgsXCJdO1wiLGwsXCJ9XCIsbS5leGl0KTtjLm5lZWRzQ29udGV4dCYmdWEoYSxsLGMuY29udGV4dCk7Yy5uZWVkc0ZyYW1lYnVmZmVyJiZLKGEsbCxjLmZyYW1lYnVmZmVyKTtRKGEsbCxjLnN0YXRlLGUpO2MucHJvZmlsZSYmXG5lKGMucHJvZmlsZSkmJkcoYSxsLGMsITEsITApO2Q/KFUoYSxtLGMsZC5hdHRyaWJ1dGVzLGYpLFUoYSxsLGMsZC5hdHRyaWJ1dGVzLGUpLFcoYSxtLGMsZC51bmlmb3JtcyxmKSxXKGEsbCxjLGQudW5pZm9ybXMsZSksUyhhLG0sbCxjKSk6KGI9YS5nbG9iYWwuZGVmKFwie31cIiksZD1jLnNoYWRlci5wcm9nVmFyLmFwcGVuZChhLGwpLGs9bC5kZWYoZCxcIi5pZFwiKSxtPWwuZGVmKGIsXCJbXCIsayxcIl1cIiksbChhLnNoYXJlZC5nbCxcIi51c2VQcm9ncmFtKFwiLGQsXCIucHJvZ3JhbSk7XCIsXCJpZighXCIsbSxcIil7XCIsbSxcIj1cIixiLFwiW1wiLGssXCJdPVwiLGEubGluayhmdW5jdGlvbihiKXtyZXR1cm4gY2Eob2EsYSxjLGIsMil9KSxcIihcIixkLFwiKTt9XCIsbSxcIi5jYWxsKHRoaXMsYTBbXCIsaCxcIl0sXCIsaCxcIik7XCIpKX1mdW5jdGlvbiBrYShhLGIpe2Z1bmN0aW9uIGMoYSl7cmV0dXJuIGEuY29udGV4dERlcCYmZXx8YS5wcm9wRGVwfXZhciBkPWEucHJvYyhcImJhdGNoXCIsMik7YS5iYXRjaElkPVwiMFwiO3dhKGEsXG5kKTt2YXIgZT0hMSxmPSEwO09iamVjdC5rZXlzKGIuY29udGV4dCkuZm9yRWFjaChmdW5jdGlvbihhKXtlPWV8fGIuY29udGV4dFthXS5wcm9wRGVwfSk7ZXx8KHVhKGEsZCxiLmNvbnRleHQpLGY9ITEpO3ZhciBnPWIuZnJhbWVidWZmZXIsaD0hMTtnPyhnLnByb3BEZXA/ZT1oPSEwOmcuY29udGV4dERlcCYmZSYmKGg9ITApLGh8fEsoYSxkLGcpKTpLKGEsZCxudWxsKTtiLnN0YXRlLnZpZXdwb3J0JiZiLnN0YXRlLnZpZXdwb3J0LnByb3BEZXAmJihlPSEwKTtWKGEsZCxiKTtRKGEsZCxiLnN0YXRlLGZ1bmN0aW9uKGEpe3JldHVybiFjKGEpfSk7Yi5wcm9maWxlJiZjKGIucHJvZmlsZSl8fEcoYSxkLGIsITEsXCJhMVwiKTtiLmNvbnRleHREZXA9ZTtiLm5lZWRzQ29udGV4dD1mO2IubmVlZHNGcmFtZWJ1ZmZlcj1oO2Y9Yi5zaGFkZXIucHJvZ1ZhcjtpZihmLmNvbnRleHREZXAmJmV8fGYucHJvcERlcCl6YShhLGQsYixudWxsKTtlbHNlIGlmKGY9Zi5hcHBlbmQoYSxkKSxkKGEuc2hhcmVkLmdsLFxuXCIudXNlUHJvZ3JhbShcIixmLFwiLnByb2dyYW0pO1wiKSxiLnNoYWRlci5wcm9ncmFtKXphKGEsZCxiLGIuc2hhZGVyLnByb2dyYW0pO2Vsc2V7dmFyIGc9YS5nbG9iYWwuZGVmKFwie31cIiksaD1kLmRlZihmLFwiLmlkXCIpLGs9ZC5kZWYoZyxcIltcIixoLFwiXVwiKTtkKGEuY29uZChrKS50aGVuKGssXCIuY2FsbCh0aGlzLGEwLGExKTtcIilbXCJlbHNlXCJdKGssXCI9XCIsZyxcIltcIixoLFwiXT1cIixhLmxpbmsoZnVuY3Rpb24oYyl7cmV0dXJuIGNhKHphLGEsYixjLDIpfSksXCIoXCIsZixcIik7XCIsayxcIi5jYWxsKHRoaXMsYTAsYTEpO1wiKSl9MDxPYmplY3Qua2V5cyhiLnN0YXRlKS5sZW5ndGgmJmQoYS5zaGFyZWQuY3VycmVudCxcIi5kaXJ0eT10cnVlO1wiKX1mdW5jdGlvbiBpYShhLGMpe2Z1bmN0aW9uIGQoYil7dmFyIGc9Yy5zaGFkZXJbYl07ZyYmZS5zZXQoZi5zaGFkZXIsXCIuXCIrYixnLmFwcGVuZChhLGUpKX12YXIgZT1hLnByb2MoXCJzY29wZVwiLDMpO2EuYmF0Y2hJZD1cImEyXCI7dmFyIGY9YS5zaGFyZWQsZz1mLmN1cnJlbnQ7XG51YShhLGUsYy5jb250ZXh0KTtjLmZyYW1lYnVmZmVyJiZjLmZyYW1lYnVmZmVyLmFwcGVuZChhLGUpO3ZiKE9iamVjdC5rZXlzKGMuc3RhdGUpKS5mb3JFYWNoKGZ1bmN0aW9uKGIpe3ZhciBkPWMuc3RhdGVbYl0uYXBwZW5kKGEsZSk7cGEoZCk/ZC5mb3JFYWNoKGZ1bmN0aW9uKGMsZCl7ZS5zZXQoYS5uZXh0W2JdLFwiW1wiK2QrXCJdXCIsYyl9KTplLnNldChmLm5leHQsXCIuXCIrYixkKX0pO0coYSxlLGMsITAsITApO1tcImVsZW1lbnRzXCIsXCJvZmZzZXRcIixcImNvdW50XCIsXCJpbnN0YW5jZXNcIixcInByaW1pdGl2ZVwiXS5mb3JFYWNoKGZ1bmN0aW9uKGIpe3ZhciBkPWMuZHJhd1tiXTtkJiZlLnNldChmLmRyYXcsXCIuXCIrYixcIlwiK2QuYXBwZW5kKGEsZSkpfSk7T2JqZWN0LmtleXMoYy51bmlmb3JtcykuZm9yRWFjaChmdW5jdGlvbihkKXtlLnNldChmLnVuaWZvcm1zLFwiW1wiK2IuaWQoZCkrXCJdXCIsYy51bmlmb3Jtc1tkXS5hcHBlbmQoYSxlKSl9KTtPYmplY3Qua2V5cyhjLmF0dHJpYnV0ZXMpLmZvckVhY2goZnVuY3Rpb24oYil7dmFyIGQ9XG5jLmF0dHJpYnV0ZXNbYl0uYXBwZW5kKGEsZSksZj1hLnNjb3BlQXR0cmliKGIpO09iamVjdC5rZXlzKG5ldyB5YSkuZm9yRWFjaChmdW5jdGlvbihhKXtlLnNldChmLFwiLlwiK2EsZFthXSl9KX0pO2QoXCJ2ZXJ0XCIpO2QoXCJmcmFnXCIpOzA8T2JqZWN0LmtleXMoYy5zdGF0ZSkubGVuZ3RoJiYoZShnLFwiLmRpcnR5PXRydWU7XCIpLGUuZXhpdChnLFwiLmRpcnR5PXRydWU7XCIpKTtlKFwiYTEoXCIsYS5zaGFyZWQuY29udGV4dCxcIixhMCxcIixhLmJhdGNoSWQsXCIpO1wiKX1mdW5jdGlvbiBtYShhKXtpZihcIm9iamVjdFwiPT09dHlwZW9mIGEmJiFwYShhKSl7Zm9yKHZhciBiPU9iamVjdC5rZXlzKGEpLGM9MDtjPGIubGVuZ3RoOysrYylpZihsYS5pc0R5bmFtaWMoYVtiW2NdXSkpcmV0dXJuITA7cmV0dXJuITF9fWZ1bmN0aW9uIGphKGEsYixjKXtmdW5jdGlvbiBkKGEsYil7Zy5mb3JFYWNoKGZ1bmN0aW9uKGMpe3ZhciBkPWVbY107bGEuaXNEeW5hbWljKGQpJiYoZD1hLmludm9rZShiLGQpLGIobCxcIi5cIixcbmMsXCI9XCIsZCxcIjtcIikpfSl9dmFyIGU9YltcInN0YXRpY1wiXVtjXTtpZihlJiZtYShlKSl7dmFyIGY9YS5nbG9iYWwsZz1PYmplY3Qua2V5cyhlKSxoPSExLGs9ITEsbT0hMSxsPWEuZ2xvYmFsLmRlZihcInt9XCIpO2cuZm9yRWFjaChmdW5jdGlvbihiKXt2YXIgYz1lW2JdO2lmKGxhLmlzRHluYW1pYyhjKSlcImZ1bmN0aW9uXCI9PT10eXBlb2YgYyYmKGM9ZVtiXT1sYS51bmJveChjKSksYj1QKGMsbnVsbCksaD1ofHxiLnRoaXNEZXAsbT1tfHxiLnByb3BEZXAsaz1rfHxiLmNvbnRleHREZXA7ZWxzZXtmKGwsXCIuXCIsYixcIj1cIik7c3dpdGNoKHR5cGVvZiBjKXtjYXNlIFwibnVtYmVyXCI6ZihjKTticmVhaztjYXNlIFwic3RyaW5nXCI6ZignXCInLGMsJ1wiJyk7YnJlYWs7Y2FzZSBcIm9iamVjdFwiOkFycmF5LmlzQXJyYXkoYykmJmYoXCJbXCIsYy5qb2luKCksXCJdXCIpO2JyZWFrO2RlZmF1bHQ6ZihhLmxpbmsoYykpfWYoXCI7XCIpfX0pO2IuZHluYW1pY1tjXT1uZXcgbGEuRHluYW1pY1ZhcmlhYmxlKDQse3RoaXNEZXA6aCxcbmNvbnRleHREZXA6ayxwcm9wRGVwOm0scmVmOmwsYXBwZW5kOmR9KTtkZWxldGUgYltcInN0YXRpY1wiXVtjXX19dmFyIHlhPXEuUmVjb3JkLFg9e2FkZDozMjc3NCxzdWJ0cmFjdDozMjc3OCxcInJldmVyc2Ugc3VidHJhY3RcIjozMjc3OX07Yy5leHRfYmxlbmRfbWlubWF4JiYoWC5taW49MzI3NzUsWC5tYXg9MzI3NzYpO3ZhciBlYT1jLmFuZ2xlX2luc3RhbmNlZF9hcnJheXMsaGE9Yy53ZWJnbF9kcmF3X2J1ZmZlcnMscmE9e2RpcnR5OiEwLHByb2ZpbGU6aC5wcm9maWxlfSxGYT17fSxLYT1bXSxzYT17fSx0YT17fTt1KFwiZGl0aGVyXCIsMzAyNCk7dShcImJsZW5kLmVuYWJsZVwiLDMwNDIpO3YoXCJibGVuZC5jb2xvclwiLFwiYmxlbmRDb2xvclwiLFswLDAsMCwwXSk7dihcImJsZW5kLmVxdWF0aW9uXCIsXCJibGVuZEVxdWF0aW9uU2VwYXJhdGVcIixbMzI3NzQsMzI3NzRdKTt2KFwiYmxlbmQuZnVuY1wiLFwiYmxlbmRGdW5jU2VwYXJhdGVcIixbMSwwLDEsMF0pO3UoXCJkZXB0aC5lbmFibGVcIiwyOTI5LCEwKTtcbnYoXCJkZXB0aC5mdW5jXCIsXCJkZXB0aEZ1bmNcIiw1MTMpO3YoXCJkZXB0aC5yYW5nZVwiLFwiZGVwdGhSYW5nZVwiLFswLDFdKTt2KFwiZGVwdGgubWFza1wiLFwiZGVwdGhNYXNrXCIsITApO3YoXCJjb2xvck1hc2tcIixcImNvbG9yTWFza1wiLFshMCwhMCwhMCwhMF0pO3UoXCJjdWxsLmVuYWJsZVwiLDI4ODQpO3YoXCJjdWxsLmZhY2VcIixcImN1bGxGYWNlXCIsMTAyOSk7dihcImZyb250RmFjZVwiLFwiZnJvbnRGYWNlXCIsMjMwNSk7dihcImxpbmVXaWR0aFwiLFwibGluZVdpZHRoXCIsMSk7dShcInBvbHlnb25PZmZzZXQuZW5hYmxlXCIsMzI4MjMpO3YoXCJwb2x5Z29uT2Zmc2V0Lm9mZnNldFwiLFwicG9seWdvbk9mZnNldFwiLFswLDBdKTt1KFwic2FtcGxlLmFscGhhXCIsMzI5MjYpO3UoXCJzYW1wbGUuZW5hYmxlXCIsMzI5MjgpO3YoXCJzYW1wbGUuY292ZXJhZ2VcIixcInNhbXBsZUNvdmVyYWdlXCIsWzEsITFdKTt1KFwic3RlbmNpbC5lbmFibGVcIiwyOTYwKTt2KFwic3RlbmNpbC5tYXNrXCIsXCJzdGVuY2lsTWFza1wiLC0xKTt2KFwic3RlbmNpbC5mdW5jXCIsXG5cInN0ZW5jaWxGdW5jXCIsWzUxOSwwLC0xXSk7dihcInN0ZW5jaWwub3BGcm9udFwiLFwic3RlbmNpbE9wU2VwYXJhdGVcIixbMTAyOCw3NjgwLDc2ODAsNzY4MF0pO3YoXCJzdGVuY2lsLm9wQmFja1wiLFwic3RlbmNpbE9wU2VwYXJhdGVcIixbMTAyOSw3NjgwLDc2ODAsNzY4MF0pO3UoXCJzY2lzc29yLmVuYWJsZVwiLDMwODkpO3YoXCJzY2lzc29yLmJveFwiLFwic2Npc3NvclwiLFswLDAsYS5kcmF3aW5nQnVmZmVyV2lkdGgsYS5kcmF3aW5nQnVmZmVySGVpZ2h0XSk7dihcInZpZXdwb3J0XCIsXCJ2aWV3cG9ydFwiLFswLDAsYS5kcmF3aW5nQnVmZmVyV2lkdGgsYS5kcmF3aW5nQnVmZmVySGVpZ2h0XSk7dmFyIG5hPXtnbDphLGNvbnRleHQ6QyxzdHJpbmdzOmIsbmV4dDpGYSxjdXJyZW50OnJhLGRyYXc6bSxlbGVtZW50czpkLGJ1ZmZlcjpnLHNoYWRlcjp0LGF0dHJpYnV0ZXM6cS5zdGF0ZSx1bmlmb3JtczpyLGZyYW1lYnVmZmVyOmYsZXh0ZW5zaW9uczpjLHRpbWVyOmssaXNCdWZmZXJBcmdzOk9hfSxhYT17cHJpbVR5cGVzOlNhLFxuY29tcGFyZUZ1bmNzOlhhLGJsZW5kRnVuY3M6R2EsYmxlbmRFcXVhdGlvbnM6WCxzdGVuY2lsT3BzOlBhLGdsVHlwZXM6UmEsb3JpZW50YXRpb25UeXBlOndifTtoYSYmKGFhLmJhY2tCdWZmZXI9WzEwMjldLGFhLmRyYXdCdWZmZXI9SihlLm1heERyYXdidWZmZXJzLGZ1bmN0aW9uKGEpe3JldHVybiAwPT09YT9bMF06SihhLGZ1bmN0aW9uKGEpe3JldHVybiAzNjA2NCthfSl9KSk7dmFyIHFhPTA7cmV0dXJue25leHQ6RmEsY3VycmVudDpyYSxwcm9jczpmdW5jdGlvbigpe3ZhciBhPU4oKSxiPWEucHJvYyhcInBvbGxcIiksYz1hLnByb2MoXCJyZWZyZXNoXCIpLGQ9YS5ibG9jaygpO2IoZCk7YyhkKTt2YXIgZj1hLnNoYXJlZCxnPWYuZ2wsaD1mLm5leHQsaz1mLmN1cnJlbnQ7ZChrLFwiLmRpcnR5PWZhbHNlO1wiKTtLKGEsYik7SyhhLGMsbnVsbCwhMCk7dmFyIG07ZWEmJihtPWEubGluayhlYSkpO2Zvcih2YXIgbD0wO2w8ZS5tYXhBdHRyaWJ1dGVzOysrbCl7dmFyIG49Yy5kZWYoZi5hdHRyaWJ1dGVzLFxuXCJbXCIsbCxcIl1cIikscT1hLmNvbmQobixcIi5idWZmZXJcIik7cS50aGVuKGcsXCIuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoXCIsbCxcIik7XCIsZyxcIi5iaW5kQnVmZmVyKFwiLDM0OTYyLFwiLFwiLG4sXCIuYnVmZmVyLmJ1ZmZlcik7XCIsZyxcIi52ZXJ0ZXhBdHRyaWJQb2ludGVyKFwiLGwsXCIsXCIsbixcIi5zaXplLFwiLG4sXCIudHlwZSxcIixuLFwiLm5vcm1hbGl6ZWQsXCIsbixcIi5zdHJpZGUsXCIsbixcIi5vZmZzZXQpO1wiKVtcImVsc2VcIl0oZyxcIi5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoXCIsbCxcIik7XCIsZyxcIi52ZXJ0ZXhBdHRyaWI0ZihcIixsLFwiLFwiLG4sXCIueCxcIixuLFwiLnksXCIsbixcIi56LFwiLG4sXCIudyk7XCIsbixcIi5idWZmZXI9bnVsbDtcIik7YyhxKTtlYSYmYyhtLFwiLnZlcnRleEF0dHJpYkRpdmlzb3JBTkdMRShcIixsLFwiLFwiLG4sXCIuZGl2aXNvcik7XCIpfU9iamVjdC5rZXlzKHNhKS5mb3JFYWNoKGZ1bmN0aW9uKGUpe3ZhciBmPXNhW2VdLG09ZC5kZWYoaCxcIi5cIixlKSxsPWEuYmxvY2soKTtsKFwiaWYoXCIsbSxcIil7XCIsXG5nLFwiLmVuYWJsZShcIixmLFwiKX1lbHNle1wiLGcsXCIuZGlzYWJsZShcIixmLFwiKX1cIixrLFwiLlwiLGUsXCI9XCIsbSxcIjtcIik7YyhsKTtiKFwiaWYoXCIsbSxcIiE9PVwiLGssXCIuXCIsZSxcIil7XCIsbCxcIn1cIil9KTtPYmplY3Qua2V5cyh0YSkuZm9yRWFjaChmdW5jdGlvbihlKXt2YXIgZj10YVtlXSxtPXJhW2VdLGwsbixxPWEuYmxvY2soKTtxKGcsXCIuXCIsZixcIihcIik7cGEobSk/KGY9bS5sZW5ndGgsbD1hLmdsb2JhbC5kZWYoaCxcIi5cIixlKSxuPWEuZ2xvYmFsLmRlZihrLFwiLlwiLGUpLHEoSihmLGZ1bmN0aW9uKGEpe3JldHVybiBsK1wiW1wiK2ErXCJdXCJ9KSxcIik7XCIsSihmLGZ1bmN0aW9uKGEpe3JldHVybiBuK1wiW1wiK2ErXCJdPVwiK2wrXCJbXCIrYStcIl07XCJ9KS5qb2luKFwiXCIpKSxiKFwiaWYoXCIsSihmLGZ1bmN0aW9uKGEpe3JldHVybiBsK1wiW1wiK2ErXCJdIT09XCIrbitcIltcIithK1wiXVwifSkuam9pbihcInx8XCIpLFwiKXtcIixxLFwifVwiKSk6KGw9ZC5kZWYoaCxcIi5cIixlKSxuPWQuZGVmKGssXCIuXCIsZSkscShsLFwiKTtcIixrLFwiLlwiLGUsXG5cIj1cIixsLFwiO1wiKSxiKFwiaWYoXCIsbCxcIiE9PVwiLG4sXCIpe1wiLHEsXCJ9XCIpKTtjKHEpfSk7cmV0dXJuIGEuY29tcGlsZSgpfSgpLGNvbXBpbGU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgZj1OKCk7Zi5zdGF0cz1mLmxpbmsoZSk7T2JqZWN0LmtleXMoYltcInN0YXRpY1wiXSkuZm9yRWFjaChmdW5jdGlvbihhKXtqYShmLGIsYSl9KTtVYi5mb3JFYWNoKGZ1bmN0aW9uKGIpe2phKGYsYSxiKX0pO2M9QShhLGIsYyxkLGYpO2RhKGYsYyk7aWEoZixjKTtrYShmLGMpO3JldHVybiBmLmNvbXBpbGUoKX19fWZ1bmN0aW9uIHliKGEsYil7Zm9yKHZhciBjPTA7YzxhLmxlbmd0aDsrK2MpaWYoYVtjXT09PWIpcmV0dXJuIGM7cmV0dXJuLTF9dmFyIEU9ZnVuY3Rpb24oYSxiKXtmb3IodmFyIGM9T2JqZWN0LmtleXMoYiksZT0wO2U8Yy5sZW5ndGg7KytlKWFbY1tlXV09YltjW2VdXTtyZXR1cm4gYX0sQWI9MCxsYT17RHluYW1pY1ZhcmlhYmxlOmFhLGRlZmluZTpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgYWEoYSxcblphKGIrXCJcIikpfSxpc0R5bmFtaWM6ZnVuY3Rpb24oYSl7cmV0dXJuXCJmdW5jdGlvblwiPT09dHlwZW9mIGEmJiFhLl9yZWdsVHlwZXx8YSBpbnN0YW5jZW9mIGFhfSx1bmJveDpmdW5jdGlvbihhLGIpe3JldHVyblwiZnVuY3Rpb25cIj09PXR5cGVvZiBhP25ldyBhYSgwLGEpOmF9LGFjY2Vzc29yOlphfSxZYT17bmV4dDpcImZ1bmN0aW9uXCI9PT10eXBlb2YgcmVxdWVzdEFuaW1hdGlvbkZyYW1lP2Z1bmN0aW9uKGEpe3JldHVybiByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoYSl9OmZ1bmN0aW9uKGEpe3JldHVybiBzZXRUaW1lb3V0KGEsMTYpfSxjYW5jZWw6XCJmdW5jdGlvblwiPT09dHlwZW9mIGNhbmNlbEFuaW1hdGlvbkZyYW1lP2Z1bmN0aW9uKGEpe3JldHVybiBjYW5jZWxBbmltYXRpb25GcmFtZShhKX06Y2xlYXJUaW1lb3V0fSx6Yj1cInVuZGVmaW5lZFwiIT09dHlwZW9mIHBlcmZvcm1hbmNlJiZwZXJmb3JtYW5jZS5ub3c/ZnVuY3Rpb24oKXtyZXR1cm4gcGVyZm9ybWFuY2Uubm93KCl9OmZ1bmN0aW9uKCl7cmV0dXJuK25ldyBEYXRlfSxcbng9Y2IoKTt4Lnplcm89Y2IoKTt2YXIgVmI9ZnVuY3Rpb24oYSxiKXt2YXIgYz0xO2IuZXh0X3RleHR1cmVfZmlsdGVyX2FuaXNvdHJvcGljJiYoYz1hLmdldFBhcmFtZXRlcigzNDA0NykpO3ZhciBlPTEsZz0xO2Iud2ViZ2xfZHJhd19idWZmZXJzJiYoZT1hLmdldFBhcmFtZXRlcigzNDg1MiksZz1hLmdldFBhcmFtZXRlcigzNjA2MykpO3ZhciBkPSEhYi5vZXNfdGV4dHVyZV9mbG9hdDtpZihkKXtkPWEuY3JlYXRlVGV4dHVyZSgpO2EuYmluZFRleHR1cmUoMzU1MyxkKTthLnRleEltYWdlMkQoMzU1MywwLDY0MDgsMSwxLDAsNjQwOCw1MTI2LG51bGwpO3ZhciBuPWEuY3JlYXRlRnJhbWVidWZmZXIoKTthLmJpbmRGcmFtZWJ1ZmZlcigzNjE2MCxuKTthLmZyYW1lYnVmZmVyVGV4dHVyZTJEKDM2MTYwLDM2MDY0LDM1NTMsZCwwKTthLmJpbmRUZXh0dXJlKDM1NTMsbnVsbCk7aWYoMzYwNTMhPT1hLmNoZWNrRnJhbWVidWZmZXJTdGF0dXMoMzYxNjApKWQ9ITE7ZWxzZXthLnZpZXdwb3J0KDAsXG4wLDEsMSk7YS5jbGVhckNvbG9yKDEsMCwwLDEpO2EuY2xlYXIoMTYzODQpO3ZhciBmPXguYWxsb2NUeXBlKDUxMjYsNCk7YS5yZWFkUGl4ZWxzKDAsMCwxLDEsNjQwOCw1MTI2LGYpO2EuZ2V0RXJyb3IoKT9kPSExOihhLmRlbGV0ZUZyYW1lYnVmZmVyKG4pLGEuZGVsZXRlVGV4dHVyZShkKSxkPTE9PT1mWzBdKTt4LmZyZWVUeXBlKGYpfX1mPSEwO1widW5kZWZpbmVkXCIhPT10eXBlb2YgbmF2aWdhdG9yJiYoL01TSUUvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCl8fC9UcmlkZW50XFwvLy50ZXN0KG5hdmlnYXRvci5hcHBWZXJzaW9uKXx8L0VkZ2UvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpfHwoZj1hLmNyZWF0ZVRleHR1cmUoKSxuPXguYWxsb2NUeXBlKDUxMjEsMzYpLGEuYWN0aXZlVGV4dHVyZSgzMzk4NCksYS5iaW5kVGV4dHVyZSgzNDA2NyxmKSxhLnRleEltYWdlMkQoMzQwNjksMCw2NDA4LDMsMywwLDY0MDgsNTEyMSxuKSx4LmZyZWVUeXBlKG4pLGEuYmluZFRleHR1cmUoMzQwNjcsXG5udWxsKSxhLmRlbGV0ZVRleHR1cmUoZiksZj0hYS5nZXRFcnJvcigpKTtyZXR1cm57Y29sb3JCaXRzOlthLmdldFBhcmFtZXRlcigzNDEwKSxhLmdldFBhcmFtZXRlcigzNDExKSxhLmdldFBhcmFtZXRlcigzNDEyKSxhLmdldFBhcmFtZXRlcigzNDEzKV0sZGVwdGhCaXRzOmEuZ2V0UGFyYW1ldGVyKDM0MTQpLHN0ZW5jaWxCaXRzOmEuZ2V0UGFyYW1ldGVyKDM0MTUpLHN1YnBpeGVsQml0czphLmdldFBhcmFtZXRlcigzNDA4KSxleHRlbnNpb25zOk9iamVjdC5rZXlzKGIpLmZpbHRlcihmdW5jdGlvbihhKXtyZXR1cm4hIWJbYV19KSxtYXhBbmlzb3Ryb3BpYzpjLG1heERyYXdidWZmZXJzOmUsbWF4Q29sb3JBdHRhY2htZW50czpnLHBvaW50U2l6ZURpbXM6YS5nZXRQYXJhbWV0ZXIoMzM5MDEpLGxpbmVXaWR0aERpbXM6YS5nZXRQYXJhbWV0ZXIoMzM5MDIpLG1heFZpZXdwb3J0RGltczphLmdldFBhcmFtZXRlcigzMzg2KSxtYXhDb21iaW5lZFRleHR1cmVVbml0czphLmdldFBhcmFtZXRlcigzNTY2MSksXG5tYXhDdWJlTWFwU2l6ZTphLmdldFBhcmFtZXRlcigzNDA3NiksbWF4UmVuZGVyYnVmZmVyU2l6ZTphLmdldFBhcmFtZXRlcigzNDAyNCksbWF4VGV4dHVyZVVuaXRzOmEuZ2V0UGFyYW1ldGVyKDM0OTMwKSxtYXhUZXh0dXJlU2l6ZTphLmdldFBhcmFtZXRlcigzMzc5KSxtYXhBdHRyaWJ1dGVzOmEuZ2V0UGFyYW1ldGVyKDM0OTIxKSxtYXhWZXJ0ZXhVbmlmb3JtczphLmdldFBhcmFtZXRlcigzNjM0NyksbWF4VmVydGV4VGV4dHVyZVVuaXRzOmEuZ2V0UGFyYW1ldGVyKDM1NjYwKSxtYXhWYXJ5aW5nVmVjdG9yczphLmdldFBhcmFtZXRlcigzNjM0OCksbWF4RnJhZ21lbnRVbmlmb3JtczphLmdldFBhcmFtZXRlcigzNjM0OSksZ2xzbDphLmdldFBhcmFtZXRlcigzNTcyNCkscmVuZGVyZXI6YS5nZXRQYXJhbWV0ZXIoNzkzNyksdmVuZG9yOmEuZ2V0UGFyYW1ldGVyKDc5MzYpLHZlcnNpb246YS5nZXRQYXJhbWV0ZXIoNzkzOCkscmVhZEZsb2F0OmQsbnBvdFRleHR1cmVDdWJlOmZ9fSxcbk09ZnVuY3Rpb24oYSl7cmV0dXJuIGEgaW5zdGFuY2VvZiBVaW50OEFycmF5fHxhIGluc3RhbmNlb2YgVWludDE2QXJyYXl8fGEgaW5zdGFuY2VvZiBVaW50MzJBcnJheXx8YSBpbnN0YW5jZW9mIEludDhBcnJheXx8YSBpbnN0YW5jZW9mIEludDE2QXJyYXl8fGEgaW5zdGFuY2VvZiBJbnQzMkFycmF5fHxhIGluc3RhbmNlb2YgRmxvYXQzMkFycmF5fHxhIGluc3RhbmNlb2YgRmxvYXQ2NEFycmF5fHxhIGluc3RhbmNlb2YgVWludDhDbGFtcGVkQXJyYXl9LFM9ZnVuY3Rpb24oYSl7cmV0dXJuIE9iamVjdC5rZXlzKGEpLm1hcChmdW5jdGlvbihiKXtyZXR1cm4gYVtiXX0pfSxNYT17c2hhcGU6ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPVtdO2EubGVuZ3RoO2E9YVswXSliLnB1c2goYS5sZW5ndGgpO3JldHVybiBifSxmbGF0dGVuOmZ1bmN0aW9uKGEsYixjLGUpe3ZhciBnPTE7aWYoYi5sZW5ndGgpZm9yKHZhciBkPTA7ZDxiLmxlbmd0aDsrK2QpZyo9YltkXTtlbHNlIGc9MDtjPWV8fHguYWxsb2NUeXBlKGMsXG5nKTtzd2l0Y2goYi5sZW5ndGgpe2Nhc2UgMDpicmVhaztjYXNlIDE6ZT1iWzBdO2ZvcihiPTA7YjxlOysrYiljW2JdPWFbYl07YnJlYWs7Y2FzZSAyOmU9YlswXTtiPWJbMV07Zm9yKGQ9Zz0wO2Q8ZTsrK2QpZm9yKHZhciBuPWFbZF0sZj0wO2Y8YjsrK2YpY1tnKytdPW5bZl07YnJlYWs7Y2FzZSAzOmRiKGEsYlswXSxiWzFdLGJbMl0sYywwKTticmVhaztkZWZhdWx0OmViKGEsYiwwLGMsMCl9cmV0dXJuIGN9fSxJYT17XCJbb2JqZWN0IEludDhBcnJheV1cIjo1MTIwLFwiW29iamVjdCBJbnQxNkFycmF5XVwiOjUxMjIsXCJbb2JqZWN0IEludDMyQXJyYXldXCI6NTEyNCxcIltvYmplY3QgVWludDhBcnJheV1cIjo1MTIxLFwiW29iamVjdCBVaW50OENsYW1wZWRBcnJheV1cIjo1MTIxLFwiW29iamVjdCBVaW50MTZBcnJheV1cIjo1MTIzLFwiW29iamVjdCBVaW50MzJBcnJheV1cIjo1MTI1LFwiW29iamVjdCBGbG9hdDMyQXJyYXldXCI6NTEyNixcIltvYmplY3QgRmxvYXQ2NEFycmF5XVwiOjUxMjEsXCJbb2JqZWN0IEFycmF5QnVmZmVyXVwiOjUxMjF9LFxuUmE9e2ludDg6NTEyMCxpbnQxNjo1MTIyLGludDMyOjUxMjQsdWludDg6NTEyMSx1aW50MTY6NTEyMyx1aW50MzI6NTEyNSxcImZsb2F0XCI6NTEyNixmbG9hdDMyOjUxMjZ9LGpiPXtkeW5hbWljOjM1MDQ4LHN0cmVhbTozNTA0MCxcInN0YXRpY1wiOjM1MDQ0fSxRYT1NYS5mbGF0dGVuLGhiPU1hLnNoYXBlLGphPVtdO2phWzUxMjBdPTE7amFbNTEyMl09MjtqYVs1MTI0XT00O2phWzUxMjFdPTE7amFbNTEyM109MjtqYVs1MTI1XT00O2phWzUxMjZdPTQ7dmFyIFNhPXtwb2ludHM6MCxwb2ludDowLGxpbmVzOjEsbGluZToxLHRyaWFuZ2xlczo0LHRyaWFuZ2xlOjQsXCJsaW5lIGxvb3BcIjoyLFwibGluZSBzdHJpcFwiOjMsXCJ0cmlhbmdsZSBzdHJpcFwiOjUsXCJ0cmlhbmdsZSBmYW5cIjo2fSxsYj1uZXcgRmxvYXQzMkFycmF5KDEpLEliPW5ldyBVaW50MzJBcnJheShsYi5idWZmZXIpLE1iPVs5OTg0LDk5ODYsOTk4NSw5OTg3XSxMYT1bMCw2NDA5LDY0MTAsNjQwNyw2NDA4XSxMPXt9O0xbNjQwOV09XG5MWzY0MDZdPUxbNjQwMl09MTtMWzM0MDQxXT1MWzY0MTBdPTI7TFs2NDA3XT1MWzM1OTA0XT0zO0xbNjQwOF09TFszNTkwNl09NDt2YXIgVWE9RWEoXCJIVE1MQ2FudmFzRWxlbWVudFwiKSxwYj1FYShcIkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyRFwiKSxxYj1FYShcIkltYWdlQml0bWFwXCIpLHJiPUVhKFwiSFRNTEltYWdlRWxlbWVudFwiKSxzYj1FYShcIkhUTUxWaWRlb0VsZW1lbnRcIiksSmI9T2JqZWN0LmtleXMoSWEpLmNvbmNhdChbVWEscGIscWIscmIsc2JdKSxxYT1bXTtxYVs1MTIxXT0xO3FhWzUxMjZdPTQ7cWFbMzYxOTNdPTI7cWFbNTEyM109MjtxYVs1MTI1XT00O3ZhciB5PVtdO3lbMzI4NTRdPTI7eVszMjg1NV09Mjt5WzM2MTk0XT0yO3lbMzQwNDFdPTQ7eVszMzc3Nl09LjU7eVszMzc3N109LjU7eVszMzc3OF09MTt5WzMzNzc5XT0xO3lbMzU5ODZdPS41O3lbMzU5ODddPTE7eVszNDc5OF09MTt5WzM1ODQwXT0uNTt5WzM1ODQxXT0uMjU7eVszNTg0Ml09LjU7eVszNTg0M109LjI1O1xueVszNjE5Nl09LjU7dmFyIFE9W107UVszMjg1NF09MjtRWzMyODU1XT0yO1FbMzYxOTRdPTI7UVszMzE4OV09MjtRWzM2MTY4XT0xO1FbMzQwNDFdPTQ7UVszNTkwN109NDtRWzM0ODM2XT0xNjtRWzM0ODQyXT04O1FbMzQ4NDNdPTY7dmFyIFdiPWZ1bmN0aW9uKGEsYixjLGUsZyl7ZnVuY3Rpb24gZChhKXt0aGlzLmlkPXErKzt0aGlzLnJlZkNvdW50PTE7dGhpcy5yZW5kZXJidWZmZXI9YTt0aGlzLmZvcm1hdD0zMjg1NDt0aGlzLmhlaWdodD10aGlzLndpZHRoPTA7Zy5wcm9maWxlJiYodGhpcy5zdGF0cz17c2l6ZTowfSl9ZnVuY3Rpb24gbihiKXt2YXIgYz1iLnJlbmRlcmJ1ZmZlcjthLmJpbmRSZW5kZXJidWZmZXIoMzYxNjEsbnVsbCk7YS5kZWxldGVSZW5kZXJidWZmZXIoYyk7Yi5yZW5kZXJidWZmZXI9bnVsbDtiLnJlZkNvdW50PTA7ZGVsZXRlIHRbYi5pZF07ZS5yZW5kZXJidWZmZXJDb3VudC0tfXZhciBmPXtyZ2JhNDozMjg1NCxyZ2I1NjU6MzYxOTQsXCJyZ2I1IGExXCI6MzI4NTUsXG5kZXB0aDozMzE4OSxzdGVuY2lsOjM2MTY4LFwiZGVwdGggc3RlbmNpbFwiOjM0MDQxfTtiLmV4dF9zcmdiJiYoZi5zcmdiYT0zNTkwNyk7Yi5leHRfY29sb3JfYnVmZmVyX2hhbGZfZmxvYXQmJihmLnJnYmExNmY9MzQ4NDIsZi5yZ2IxNmY9MzQ4NDMpO2Iud2ViZ2xfY29sb3JfYnVmZmVyX2Zsb2F0JiYoZi5yZ2JhMzJmPTM0ODM2KTt2YXIgcj1bXTtPYmplY3Qua2V5cyhmKS5mb3JFYWNoKGZ1bmN0aW9uKGEpe3JbZlthXV09YX0pO3ZhciBxPTAsdD17fTtkLnByb3RvdHlwZS5kZWNSZWY9ZnVuY3Rpb24oKXswPj0tLXRoaXMucmVmQ291bnQmJm4odGhpcyl9O2cucHJvZmlsZSYmKGUuZ2V0VG90YWxSZW5kZXJidWZmZXJTaXplPWZ1bmN0aW9uKCl7dmFyIGE9MDtPYmplY3Qua2V5cyh0KS5mb3JFYWNoKGZ1bmN0aW9uKGIpe2ErPXRbYl0uc3RhdHMuc2l6ZX0pO3JldHVybiBhfSk7cmV0dXJue2NyZWF0ZTpmdW5jdGlvbihiLGMpe2Z1bmN0aW9uIGsoYixjKXt2YXIgZD0wLGU9MCxtPTMyODU0O1xuXCJvYmplY3RcIj09PXR5cGVvZiBiJiZiPyhcInNoYXBlXCJpbiBiPyhlPWIuc2hhcGUsZD1lWzBdfDAsZT1lWzFdfDApOihcInJhZGl1c1wiaW4gYiYmKGQ9ZT1iLnJhZGl1c3wwKSxcIndpZHRoXCJpbiBiJiYoZD1iLndpZHRofDApLFwiaGVpZ2h0XCJpbiBiJiYoZT1iLmhlaWdodHwwKSksXCJmb3JtYXRcImluIGImJihtPWZbYi5mb3JtYXRdKSk6XCJudW1iZXJcIj09PXR5cGVvZiBiPyhkPWJ8MCxlPVwibnVtYmVyXCI9PT10eXBlb2YgYz9jfDA6ZCk6Ynx8KGQ9ZT0xKTtpZihkIT09aC53aWR0aHx8ZSE9PWguaGVpZ2h0fHxtIT09aC5mb3JtYXQpcmV0dXJuIGsud2lkdGg9aC53aWR0aD1kLGsuaGVpZ2h0PWguaGVpZ2h0PWUsaC5mb3JtYXQ9bSxhLmJpbmRSZW5kZXJidWZmZXIoMzYxNjEsaC5yZW5kZXJidWZmZXIpLGEucmVuZGVyYnVmZmVyU3RvcmFnZSgzNjE2MSxtLGQsZSksZy5wcm9maWxlJiYoaC5zdGF0cy5zaXplPVFbaC5mb3JtYXRdKmgud2lkdGgqaC5oZWlnaHQpLGsuZm9ybWF0PXJbaC5mb3JtYXRdLFxua312YXIgaD1uZXcgZChhLmNyZWF0ZVJlbmRlcmJ1ZmZlcigpKTt0W2guaWRdPWg7ZS5yZW5kZXJidWZmZXJDb3VudCsrO2soYixjKTtrLnJlc2l6ZT1mdW5jdGlvbihiLGMpe3ZhciBkPWJ8MCxlPWN8MHx8ZDtpZihkPT09aC53aWR0aCYmZT09PWguaGVpZ2h0KXJldHVybiBrO2sud2lkdGg9aC53aWR0aD1kO2suaGVpZ2h0PWguaGVpZ2h0PWU7YS5iaW5kUmVuZGVyYnVmZmVyKDM2MTYxLGgucmVuZGVyYnVmZmVyKTthLnJlbmRlcmJ1ZmZlclN0b3JhZ2UoMzYxNjEsaC5mb3JtYXQsZCxlKTtnLnByb2ZpbGUmJihoLnN0YXRzLnNpemU9UVtoLmZvcm1hdF0qaC53aWR0aCpoLmhlaWdodCk7cmV0dXJuIGt9O2suX3JlZ2xUeXBlPVwicmVuZGVyYnVmZmVyXCI7ay5fcmVuZGVyYnVmZmVyPWg7Zy5wcm9maWxlJiYoay5zdGF0cz1oLnN0YXRzKTtrLmRlc3Ryb3k9ZnVuY3Rpb24oKXtoLmRlY1JlZigpfTtyZXR1cm4ga30sY2xlYXI6ZnVuY3Rpb24oKXtTKHQpLmZvckVhY2gobil9LHJlc3RvcmU6ZnVuY3Rpb24oKXtTKHQpLmZvckVhY2goZnVuY3Rpb24oYil7Yi5yZW5kZXJidWZmZXI9XG5hLmNyZWF0ZVJlbmRlcmJ1ZmZlcigpO2EuYmluZFJlbmRlcmJ1ZmZlcigzNjE2MSxiLnJlbmRlcmJ1ZmZlcik7YS5yZW5kZXJidWZmZXJTdG9yYWdlKDM2MTYxLGIuZm9ybWF0LGIud2lkdGgsYi5oZWlnaHQpfSk7YS5iaW5kUmVuZGVyYnVmZmVyKDM2MTYxLG51bGwpfX19LFdhPVtdO1dhWzY0MDhdPTQ7V2FbNjQwN109Mzt2YXIgTmE9W107TmFbNTEyMV09MTtOYVs1MTI2XT00O05hWzM2MTkzXT0yO3ZhciBEYT1bXCJ4XCIsXCJ5XCIsXCJ6XCIsXCJ3XCJdLFViPVwiYmxlbmQuZnVuYyBibGVuZC5lcXVhdGlvbiBzdGVuY2lsLmZ1bmMgc3RlbmNpbC5vcEZyb250IHN0ZW5jaWwub3BCYWNrIHNhbXBsZS5jb3ZlcmFnZSB2aWV3cG9ydCBzY2lzc29yLmJveCBwb2x5Z29uT2Zmc2V0Lm9mZnNldFwiLnNwbGl0KFwiIFwiKSxHYT17MDowLDE6MSx6ZXJvOjAsb25lOjEsXCJzcmMgY29sb3JcIjo3NjgsXCJvbmUgbWludXMgc3JjIGNvbG9yXCI6NzY5LFwic3JjIGFscGhhXCI6NzcwLFwib25lIG1pbnVzIHNyYyBhbHBoYVwiOjc3MSxcblwiZHN0IGNvbG9yXCI6Nzc0LFwib25lIG1pbnVzIGRzdCBjb2xvclwiOjc3NSxcImRzdCBhbHBoYVwiOjc3MixcIm9uZSBtaW51cyBkc3QgYWxwaGFcIjo3NzMsXCJjb25zdGFudCBjb2xvclwiOjMyNzY5LFwib25lIG1pbnVzIGNvbnN0YW50IGNvbG9yXCI6MzI3NzAsXCJjb25zdGFudCBhbHBoYVwiOjMyNzcxLFwib25lIG1pbnVzIGNvbnN0YW50IGFscGhhXCI6MzI3NzIsXCJzcmMgYWxwaGEgc2F0dXJhdGVcIjo3NzZ9LFhhPXtuZXZlcjo1MTIsbGVzczo1MTMsXCI8XCI6NTEzLGVxdWFsOjUxNCxcIj1cIjo1MTQsXCI9PVwiOjUxNCxcIj09PVwiOjUxNCxsZXF1YWw6NTE1LFwiPD1cIjo1MTUsZ3JlYXRlcjo1MTYsXCI+XCI6NTE2LG5vdGVxdWFsOjUxNyxcIiE9XCI6NTE3LFwiIT09XCI6NTE3LGdlcXVhbDo1MTgsXCI+PVwiOjUxOCxhbHdheXM6NTE5fSxQYT17MDowLHplcm86MCxrZWVwOjc2ODAscmVwbGFjZTo3NjgxLGluY3JlbWVudDo3NjgyLGRlY3JlbWVudDo3NjgzLFwiaW5jcmVtZW50IHdyYXBcIjozNDA1NSxcImRlY3JlbWVudCB3cmFwXCI6MzQwNTYsXG5pbnZlcnQ6NTM4Nn0sd2I9e2N3OjIzMDQsY2N3OjIzMDV9LHhiPW5ldyBaKCExLCExLCExLGZ1bmN0aW9uKCl7fSksWGI9ZnVuY3Rpb24oYSxiKXtmdW5jdGlvbiBjKCl7dGhpcy5lbmRRdWVyeUluZGV4PXRoaXMuc3RhcnRRdWVyeUluZGV4PS0xO3RoaXMuc3VtPTA7dGhpcy5zdGF0cz1udWxsfWZ1bmN0aW9uIGUoYSxiLGQpe3ZhciBlPW4ucG9wKCl8fG5ldyBjO2Uuc3RhcnRRdWVyeUluZGV4PWE7ZS5lbmRRdWVyeUluZGV4PWI7ZS5zdW09MDtlLnN0YXRzPWQ7Zi5wdXNoKGUpfWlmKCFiLmV4dF9kaXNqb2ludF90aW1lcl9xdWVyeSlyZXR1cm4gbnVsbDt2YXIgZz1bXSxkPVtdLG49W10sZj1bXSxyPVtdLHE9W107cmV0dXJue2JlZ2luUXVlcnk6ZnVuY3Rpb24oYSl7dmFyIGM9Zy5wb3AoKXx8Yi5leHRfZGlzam9pbnRfdGltZXJfcXVlcnkuY3JlYXRlUXVlcnlFWFQoKTtiLmV4dF9kaXNqb2ludF90aW1lcl9xdWVyeS5iZWdpblF1ZXJ5RVhUKDM1MDA3LGMpO2QucHVzaChjKTtlKGQubGVuZ3RoLVxuMSxkLmxlbmd0aCxhKX0sZW5kUXVlcnk6ZnVuY3Rpb24oKXtiLmV4dF9kaXNqb2ludF90aW1lcl9xdWVyeS5lbmRRdWVyeUVYVCgzNTAwNyl9LHB1c2hTY29wZVN0YXRzOmUsdXBkYXRlOmZ1bmN0aW9uKCl7dmFyIGEsYzthPWQubGVuZ3RoO2lmKDAhPT1hKXtxLmxlbmd0aD1NYXRoLm1heChxLmxlbmd0aCxhKzEpO3IubGVuZ3RoPU1hdGgubWF4KHIubGVuZ3RoLGErMSk7clswXT0wO3ZhciBlPXFbMF09MDtmb3IoYz1hPTA7YzxkLmxlbmd0aDsrK2Mpe3ZhciBrPWRbY107Yi5leHRfZGlzam9pbnRfdGltZXJfcXVlcnkuZ2V0UXVlcnlPYmplY3RFWFQoaywzNDkxOSk/KGUrPWIuZXh0X2Rpc2pvaW50X3RpbWVyX3F1ZXJ5LmdldFF1ZXJ5T2JqZWN0RVhUKGssMzQ5MTgpLGcucHVzaChrKSk6ZFthKytdPWs7cltjKzFdPWU7cVtjKzFdPWF9ZC5sZW5ndGg9YTtmb3IoYz1hPTA7YzxmLmxlbmd0aDsrK2Mpe3ZhciBlPWZbY10saD1lLnN0YXJ0UXVlcnlJbmRleCxrPWUuZW5kUXVlcnlJbmRleDtcbmUuc3VtKz1yW2tdLXJbaF07aD1xW2hdO2s9cVtrXTtrPT09aD8oZS5zdGF0cy5ncHVUaW1lKz1lLnN1bS8xRTYsbi5wdXNoKGUpKTooZS5zdGFydFF1ZXJ5SW5kZXg9aCxlLmVuZFF1ZXJ5SW5kZXg9ayxmW2ErK109ZSl9Zi5sZW5ndGg9YX19LGdldE51bVBlbmRpbmdRdWVyaWVzOmZ1bmN0aW9uKCl7cmV0dXJuIGQubGVuZ3RofSxjbGVhcjpmdW5jdGlvbigpe2cucHVzaC5hcHBseShnLGQpO2Zvcih2YXIgYT0wO2E8Zy5sZW5ndGg7YSsrKWIuZXh0X2Rpc2pvaW50X3RpbWVyX3F1ZXJ5LmRlbGV0ZVF1ZXJ5RVhUKGdbYV0pO2QubGVuZ3RoPTA7Zy5sZW5ndGg9MH0scmVzdG9yZTpmdW5jdGlvbigpe2QubGVuZ3RoPTA7Zy5sZW5ndGg9MH19fTtyZXR1cm4gZnVuY3Rpb24oYSl7ZnVuY3Rpb24gYigpe2lmKDA9PT1HLmxlbmd0aClCJiZCLnVwZGF0ZSgpLGNhPW51bGw7ZWxzZXtjYT1ZYS5uZXh0KGIpO3QoKTtmb3IodmFyIGE9Ry5sZW5ndGgtMTswPD1hOy0tYSl7dmFyIGM9R1thXTtjJiZcbmMoTyxudWxsLDApfWsuZmx1c2goKTtCJiZCLnVwZGF0ZSgpfX1mdW5jdGlvbiBjKCl7IWNhJiYwPEcubGVuZ3RoJiYoY2E9WWEubmV4dChiKSl9ZnVuY3Rpb24gZSgpe2NhJiYoWWEuY2FuY2VsKGIpLGNhPW51bGwpfWZ1bmN0aW9uIGcoYSl7YS5wcmV2ZW50RGVmYXVsdCgpO2UoKTtVLmZvckVhY2goZnVuY3Rpb24oYSl7YSgpfSl9ZnVuY3Rpb24gZChhKXtrLmdldEVycm9yKCk7bC5yZXN0b3JlKCk7US5yZXN0b3JlKCk7Ri5yZXN0b3JlKCk7QS5yZXN0b3JlKCk7TS5yZXN0b3JlKCk7Sy5yZXN0b3JlKCk7QiYmQi5yZXN0b3JlKCk7Vi5wcm9jcy5yZWZyZXNoKCk7YygpO1cuZm9yRWFjaChmdW5jdGlvbihhKXthKCl9KX1mdW5jdGlvbiBuKGEpe2Z1bmN0aW9uIGIoYSl7dmFyIGM9e30sZD17fTtPYmplY3Qua2V5cyhhKS5mb3JFYWNoKGZ1bmN0aW9uKGIpe3ZhciBlPWFbYl07bGEuaXNEeW5hbWljKGUpP2RbYl09bGEudW5ib3goZSxiKTpjW2JdPWV9KTtyZXR1cm57ZHluYW1pYzpkLFxuXCJzdGF0aWNcIjpjfX1mdW5jdGlvbiBjKGEpe2Zvcig7bS5sZW5ndGg8YTspbS5wdXNoKG51bGwpO3JldHVybiBtfXZhciBkPWIoYS5jb250ZXh0fHx7fSksZT1iKGEudW5pZm9ybXN8fHt9KSxmPWIoYS5hdHRyaWJ1dGVzfHx7fSksZz1iKGZ1bmN0aW9uKGEpe2Z1bmN0aW9uIGIoYSl7aWYoYSBpbiBjKXt2YXIgZD1jW2FdO2RlbGV0ZSBjW2FdO09iamVjdC5rZXlzKGQpLmZvckVhY2goZnVuY3Rpb24oYil7Y1thK1wiLlwiK2JdPWRbYl19KX19dmFyIGM9RSh7fSxhKTtkZWxldGUgYy51bmlmb3JtcztkZWxldGUgYy5hdHRyaWJ1dGVzO2RlbGV0ZSBjLmNvbnRleHQ7XCJzdGVuY2lsXCJpbiBjJiZjLnN0ZW5jaWwub3AmJihjLnN0ZW5jaWwub3BCYWNrPWMuc3RlbmNpbC5vcEZyb250PWMuc3RlbmNpbC5vcCxkZWxldGUgYy5zdGVuY2lsLm9wKTtiKFwiYmxlbmRcIik7YihcImRlcHRoXCIpO2IoXCJjdWxsXCIpO2IoXCJzdGVuY2lsXCIpO2IoXCJwb2x5Z29uT2Zmc2V0XCIpO2IoXCJzY2lzc29yXCIpO2IoXCJzYW1wbGVcIik7XG5yZXR1cm4gY30oYSkpO2E9e2dwdVRpbWU6MCxjcHVUaW1lOjAsY291bnQ6MH07dmFyIGQ9Vi5jb21waWxlKGcsZixlLGQsYSksaD1kLmRyYXcsaz1kLmJhdGNoLGw9ZC5zY29wZSxtPVtdO3JldHVybiBFKGZ1bmN0aW9uKGEsYil7dmFyIGQ7aWYoXCJmdW5jdGlvblwiPT09dHlwZW9mIGEpcmV0dXJuIGwuY2FsbCh0aGlzLG51bGwsYSwwKTtpZihcImZ1bmN0aW9uXCI9PT10eXBlb2YgYilpZihcIm51bWJlclwiPT09dHlwZW9mIGEpZm9yKGQ9MDtkPGE7KytkKWwuY2FsbCh0aGlzLG51bGwsYixkKTtlbHNlIGlmKEFycmF5LmlzQXJyYXkoYSkpZm9yKGQ9MDtkPGEubGVuZ3RoOysrZClsLmNhbGwodGhpcyxhW2RdLGIsZCk7ZWxzZSByZXR1cm4gbC5jYWxsKHRoaXMsYSxiLDApO2Vsc2UgaWYoXCJudW1iZXJcIj09PXR5cGVvZiBhKXtpZigwPGEpcmV0dXJuIGsuY2FsbCh0aGlzLGMoYXwwKSxhfDApfWVsc2UgaWYoQXJyYXkuaXNBcnJheShhKSl7aWYoYS5sZW5ndGgpcmV0dXJuIGsuY2FsbCh0aGlzLFxuYSxhLmxlbmd0aCl9ZWxzZSByZXR1cm4gaC5jYWxsKHRoaXMsYSl9LHtzdGF0czphfSl9ZnVuY3Rpb24gZihhLGIpe3ZhciBjPTA7Vi5wcm9jcy5wb2xsKCk7dmFyIGQ9Yi5jb2xvcjtkJiYoay5jbGVhckNvbG9yKCtkWzBdfHwwLCtkWzFdfHwwLCtkWzJdfHwwLCtkWzNdfHwwKSxjfD0xNjM4NCk7XCJkZXB0aFwiaW4gYiYmKGsuY2xlYXJEZXB0aCgrYi5kZXB0aCksY3w9MjU2KTtcInN0ZW5jaWxcImluIGImJihrLmNsZWFyU3RlbmNpbChiLnN0ZW5jaWx8MCksY3w9MTAyNCk7ay5jbGVhcihjKX1mdW5jdGlvbiByKGEpe0cucHVzaChhKTtjKCk7cmV0dXJue2NhbmNlbDpmdW5jdGlvbigpe2Z1bmN0aW9uIGIoKXt2YXIgYT15YihHLGIpO0dbYV09R1tHLmxlbmd0aC0xXTstLUcubGVuZ3RoOzA+PUcubGVuZ3RoJiZlKCl9dmFyIGM9eWIoRyxhKTtHW2NdPWJ9fX1mdW5jdGlvbiBxKCl7dmFyIGE9Uy52aWV3cG9ydCxiPVMuc2Npc3Nvcl9ib3g7YVswXT1hWzFdPWJbMF09YlsxXT0wO08udmlld3BvcnRXaWR0aD1cbk8uZnJhbWVidWZmZXJXaWR0aD1PLmRyYXdpbmdCdWZmZXJXaWR0aD1hWzJdPWJbMl09ay5kcmF3aW5nQnVmZmVyV2lkdGg7Ty52aWV3cG9ydEhlaWdodD1PLmZyYW1lYnVmZmVySGVpZ2h0PU8uZHJhd2luZ0J1ZmZlckhlaWdodD1hWzNdPWJbM109ay5kcmF3aW5nQnVmZmVySGVpZ2h0fWZ1bmN0aW9uIHQoKXtPLnRpY2srPTE7Ty50aW1lPXkoKTtxKCk7Vi5wcm9jcy5wb2xsKCl9ZnVuY3Rpb24gbSgpe3EoKTtWLnByb2NzLnJlZnJlc2goKTtCJiZCLnVwZGF0ZSgpfWZ1bmN0aW9uIHkoKXtyZXR1cm4oemIoKS1EKS8xRTN9YT1FYihhKTtpZighYSlyZXR1cm4gbnVsbDt2YXIgaz1hLmdsLGg9ay5nZXRDb250ZXh0QXR0cmlidXRlcygpO2suaXNDb250ZXh0TG9zdCgpO3ZhciBsPUZiKGssYSk7aWYoIWwpcmV0dXJuIG51bGw7dmFyIHU9QmIoKSx2PXtidWZmZXJDb3VudDowLGVsZW1lbnRzQ291bnQ6MCxmcmFtZWJ1ZmZlckNvdW50OjAsc2hhZGVyQ291bnQ6MCx0ZXh0dXJlQ291bnQ6MCxcbmN1YmVDb3VudDowLHJlbmRlcmJ1ZmZlckNvdW50OjAsbWF4VGV4dHVyZVVuaXRzOjB9LHg9bC5leHRlbnNpb25zLEI9WGIoayx4KSxEPXpiKCksSj1rLmRyYXdpbmdCdWZmZXJXaWR0aCxQPWsuZHJhd2luZ0J1ZmZlckhlaWdodCxPPXt0aWNrOjAsdGltZTowLHZpZXdwb3J0V2lkdGg6Six2aWV3cG9ydEhlaWdodDpQLGZyYW1lYnVmZmVyV2lkdGg6SixmcmFtZWJ1ZmZlckhlaWdodDpQLGRyYXdpbmdCdWZmZXJXaWR0aDpKLGRyYXdpbmdCdWZmZXJIZWlnaHQ6UCxwaXhlbFJhdGlvOmEucGl4ZWxSYXRpb30sUj1WYihrLHgpLEo9UGIoayx4LFIsdSksRj1HYihrLHYsYSxKKSxUPUhiKGsseCxGLHYpLFE9UWIoayx1LHYsYSksQT1LYihrLHgsUixmdW5jdGlvbigpe1YucHJvY3MucG9sbCgpfSxPLHYsYSksTT1XYihrLHgsUix2LGEpLEs9T2Ioayx4LFIsQSxNLHYpLFY9VGIoayx1LHgsUixGLFQsQSxLLHt9LEosUSx7ZWxlbWVudHM6bnVsbCxwcmltaXRpdmU6NCxjb3VudDotMSxvZmZzZXQ6MCxcbmluc3RhbmNlczotMX0sTyxCLGEpLHU9UmIoayxLLFYucHJvY3MucG9sbCxPLGgseCxSKSxTPVYubmV4dCxMPWsuY2FudmFzLEc9W10sVT1bXSxXPVtdLFo9W2Eub25EZXN0cm95XSxjYT1udWxsO0wmJihMLmFkZEV2ZW50TGlzdGVuZXIoXCJ3ZWJnbGNvbnRleHRsb3N0XCIsZywhMSksTC5hZGRFdmVudExpc3RlbmVyKFwid2ViZ2xjb250ZXh0cmVzdG9yZWRcIixkLCExKSk7dmFyIGFhPUsuc2V0RkJPPW4oe2ZyYW1lYnVmZmVyOmxhLmRlZmluZS5jYWxsKG51bGwsMSxcImZyYW1lYnVmZmVyXCIpfSk7bSgpO2g9RShuLHtjbGVhcjpmdW5jdGlvbihhKXtpZihcImZyYW1lYnVmZmVyXCJpbiBhKWlmKGEuZnJhbWVidWZmZXImJlwiZnJhbWVidWZmZXJDdWJlXCI9PT1hLmZyYW1lYnVmZmVyX3JlZ2xUeXBlKWZvcih2YXIgYj0wOzY+YjsrK2IpYWEoRSh7ZnJhbWVidWZmZXI6YS5mcmFtZWJ1ZmZlci5mYWNlc1tiXX0sYSksZik7ZWxzZSBhYShhLGYpO2Vsc2UgZihudWxsLGEpfSxwcm9wOmxhLmRlZmluZS5iaW5kKG51bGwsXG4xKSxjb250ZXh0OmxhLmRlZmluZS5iaW5kKG51bGwsMiksXCJ0aGlzXCI6bGEuZGVmaW5lLmJpbmQobnVsbCwzKSxkcmF3Om4oe30pLGJ1ZmZlcjpmdW5jdGlvbihhKXtyZXR1cm4gRi5jcmVhdGUoYSwzNDk2MiwhMSwhMSl9LGVsZW1lbnRzOmZ1bmN0aW9uKGEpe3JldHVybiBULmNyZWF0ZShhLCExKX0sdGV4dHVyZTpBLmNyZWF0ZTJELGN1YmU6QS5jcmVhdGVDdWJlLHJlbmRlcmJ1ZmZlcjpNLmNyZWF0ZSxmcmFtZWJ1ZmZlcjpLLmNyZWF0ZSxmcmFtZWJ1ZmZlckN1YmU6Sy5jcmVhdGVDdWJlLGF0dHJpYnV0ZXM6aCxmcmFtZTpyLG9uOmZ1bmN0aW9uKGEsYil7dmFyIGM7c3dpdGNoKGEpe2Nhc2UgXCJmcmFtZVwiOnJldHVybiByKGIpO2Nhc2UgXCJsb3N0XCI6Yz1VO2JyZWFrO2Nhc2UgXCJyZXN0b3JlXCI6Yz1XO2JyZWFrO2Nhc2UgXCJkZXN0cm95XCI6Yz1afWMucHVzaChiKTtyZXR1cm57Y2FuY2VsOmZ1bmN0aW9uKCl7Zm9yKHZhciBhPTA7YTxjLmxlbmd0aDsrK2EpaWYoY1thXT09PWIpe2NbYV09XG5jW2MubGVuZ3RoLTFdO2MucG9wKCk7YnJlYWt9fX19LGxpbWl0czpSLGhhc0V4dGVuc2lvbjpmdW5jdGlvbihhKXtyZXR1cm4gMDw9Ui5leHRlbnNpb25zLmluZGV4T2YoYS50b0xvd2VyQ2FzZSgpKX0scmVhZDp1LGRlc3Ryb3k6ZnVuY3Rpb24oKXtHLmxlbmd0aD0wO2UoKTtMJiYoTC5yZW1vdmVFdmVudExpc3RlbmVyKFwid2ViZ2xjb250ZXh0bG9zdFwiLGcpLEwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIndlYmdsY29udGV4dHJlc3RvcmVkXCIsZCkpO1EuY2xlYXIoKTtLLmNsZWFyKCk7TS5jbGVhcigpO0EuY2xlYXIoKTtULmNsZWFyKCk7Ri5jbGVhcigpO0ImJkIuY2xlYXIoKTtaLmZvckVhY2goZnVuY3Rpb24oYSl7YSgpfSl9LF9nbDprLF9yZWZyZXNoOm0scG9sbDpmdW5jdGlvbigpe3QoKTtCJiZCLnVwZGF0ZSgpfSxub3c6eSxzdGF0czp2fSk7YS5vbkRvbmUobnVsbCxoKTtyZXR1cm4gaH19KTtcblxufSx7fV0sNTAzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qIVxuICogcmVwZWF0LXN0cmluZyA8aHR0cHM6Ly9naXRodWIuY29tL2pvbnNjaGxpbmtlcnQvcmVwZWF0LXN0cmluZz5cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTQtMjAxNSwgSm9uIFNjaGxpbmtlcnQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFJlc3VsdHMgY2FjaGVcbiAqL1xuXG52YXIgcmVzID0gJyc7XG52YXIgY2FjaGU7XG5cbi8qKlxuICogRXhwb3NlIGByZXBlYXRgXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSByZXBlYXQ7XG5cbi8qKlxuICogUmVwZWF0IHRoZSBnaXZlbiBgc3RyaW5nYCB0aGUgc3BlY2lmaWVkIGBudW1iZXJgXG4gKiBvZiB0aW1lcy5cbiAqXG4gKiAqKkV4YW1wbGU6KipcbiAqXG4gKiBgYGBqc1xuICogdmFyIHJlcGVhdCA9IHJlcXVpcmUoJ3JlcGVhdC1zdHJpbmcnKTtcbiAqIHJlcGVhdCgnQScsIDUpO1xuICogLy89PiBBQUFBQVxuICogYGBgXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGBzdHJpbmdgIFRoZSBzdHJpbmcgdG8gcmVwZWF0XG4gKiBAcGFyYW0ge051bWJlcn0gYG51bWJlcmAgVGhlIG51bWJlciBvZiB0aW1lcyB0byByZXBlYXQgdGhlIHN0cmluZ1xuICogQHJldHVybiB7U3RyaW5nfSBSZXBlYXRlZCBzdHJpbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gcmVwZWF0KHN0ciwgbnVtKSB7XG4gIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2V4cGVjdGVkIGEgc3RyaW5nJyk7XG4gIH1cblxuICAvLyBjb3ZlciBjb21tb24sIHF1aWNrIHVzZSBjYXNlc1xuICBpZiAobnVtID09PSAxKSByZXR1cm4gc3RyO1xuICBpZiAobnVtID09PSAyKSByZXR1cm4gc3RyICsgc3RyO1xuXG4gIHZhciBtYXggPSBzdHIubGVuZ3RoICogbnVtO1xuICBpZiAoY2FjaGUgIT09IHN0ciB8fCB0eXBlb2YgY2FjaGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgY2FjaGUgPSBzdHI7XG4gICAgcmVzID0gJyc7XG4gIH0gZWxzZSBpZiAocmVzLmxlbmd0aCA+PSBtYXgpIHtcbiAgICByZXR1cm4gcmVzLnN1YnN0cigwLCBtYXgpO1xuICB9XG5cbiAgd2hpbGUgKG1heCA+IHJlcy5sZW5ndGggJiYgbnVtID4gMSkge1xuICAgIGlmIChudW0gJiAxKSB7XG4gICAgICByZXMgKz0gc3RyO1xuICAgIH1cblxuICAgIG51bSA+Pj0gMTtcbiAgICBzdHIgKz0gc3RyO1xuICB9XG5cbiAgcmVzICs9IHN0cjtcbiAgcmVzID0gcmVzLnN1YnN0cigwLCBtYXgpO1xuICByZXR1cm4gcmVzO1xufVxuXG59LHt9XSw1MDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuKGZ1bmN0aW9uIChnbG9iYWwpe1xubW9kdWxlLmV4cG9ydHMgPVxuICBnbG9iYWwucGVyZm9ybWFuY2UgJiZcbiAgZ2xvYmFsLnBlcmZvcm1hbmNlLm5vdyA/IGZ1bmN0aW9uIG5vdygpIHtcbiAgICByZXR1cm4gcGVyZm9ybWFuY2Uubm93KClcbiAgfSA6IERhdGUubm93IHx8IGZ1bmN0aW9uIG5vdygpIHtcbiAgICByZXR1cm4gK25ldyBEYXRlXG4gIH1cblxufSkuY2FsbCh0aGlzLHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pXG59LHt9XSw1MDU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxubW9kdWxlLmV4cG9ydHMgPSBjb21wcmVzc0V4cGFuc2lvblxuXG5mdW5jdGlvbiBjb21wcmVzc0V4cGFuc2lvbihlKSB7XG4gIHZhciBtID0gZS5sZW5ndGhcbiAgdmFyIFEgPSBlW2UubGVuZ3RoLTFdXG4gIHZhciBib3R0b20gPSBtXG4gIGZvcih2YXIgaT1tLTI7IGk+PTA7IC0taSkge1xuICAgIHZhciBhID0gUVxuICAgIHZhciBiID0gZVtpXVxuICAgIFEgPSBhICsgYlxuICAgIHZhciBidiA9IFEgLSBhXG4gICAgdmFyIHEgPSBiIC0gYnZcbiAgICBpZihxKSB7XG4gICAgICBlWy0tYm90dG9tXSA9IFFcbiAgICAgIFEgPSBxXG4gICAgfVxuICB9XG4gIHZhciB0b3AgPSAwXG4gIGZvcih2YXIgaT1ib3R0b207IGk8bTsgKytpKSB7XG4gICAgdmFyIGEgPSBlW2ldXG4gICAgdmFyIGIgPSBRXG4gICAgUSA9IGEgKyBiXG4gICAgdmFyIGJ2ID0gUSAtIGFcbiAgICB2YXIgcSA9IGIgLSBidlxuICAgIGlmKHEpIHtcbiAgICAgIGVbdG9wKytdID0gcVxuICAgIH1cbiAgfVxuICBlW3RvcCsrXSA9IFFcbiAgZS5sZW5ndGggPSB0b3BcbiAgcmV0dXJuIGVcbn1cbn0se31dLDUwNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG52YXIgdHdvUHJvZHVjdCA9IF9kZXJlcV8oXCJ0d28tcHJvZHVjdFwiKVxudmFyIHJvYnVzdFN1bSA9IF9kZXJlcV8oXCJyb2J1c3Qtc3VtXCIpXG52YXIgcm9idXN0U2NhbGUgPSBfZGVyZXFfKFwicm9idXN0LXNjYWxlXCIpXG52YXIgY29tcHJlc3MgPSBfZGVyZXFfKFwicm9idXN0LWNvbXByZXNzXCIpXG5cbnZhciBOVU1fRVhQQU5ERUQgPSA2XG5cbmZ1bmN0aW9uIGNvZmFjdG9yKG0sIGMpIHtcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShtLmxlbmd0aC0xKVxuICBmb3IodmFyIGk9MTsgaTxtLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHIgPSByZXN1bHRbaS0xXSA9IG5ldyBBcnJheShtLmxlbmd0aC0xKVxuICAgIGZvcih2YXIgaj0wLGs9MDsgajxtLmxlbmd0aDsgKytqKSB7XG4gICAgICBpZihqID09PSBjKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICByW2srK10gPSBtW2ldW2pdXG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuZnVuY3Rpb24gbWF0cml4KG4pIHtcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShuKVxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICByZXN1bHRbaV0gPSBuZXcgQXJyYXkobilcbiAgICBmb3IodmFyIGo9MDsgajxuOyArK2opIHtcbiAgICAgIHJlc3VsdFtpXVtqXSA9IFtcIm1bXCIsIGksIFwiXVtcIiwgaiwgXCJdXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBzaWduKG4pIHtcbiAgaWYobiAmIDEpIHtcbiAgICByZXR1cm4gXCItXCJcbiAgfVxuICByZXR1cm4gXCJcIlxufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZVN1bShleHByKSB7XG4gIGlmKGV4cHIubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGV4cHJbMF1cbiAgfSBlbHNlIGlmKGV4cHIubGVuZ3RoID09PSAyKSB7XG4gICAgcmV0dXJuIFtcInN1bShcIiwgZXhwclswXSwgXCIsXCIsIGV4cHJbMV0sIFwiKVwiXS5qb2luKFwiXCIpXG4gIH0gZWxzZSB7XG4gICAgdmFyIG0gPSBleHByLmxlbmd0aD4+MVxuICAgIHJldHVybiBbXCJzdW0oXCIsIGdlbmVyYXRlU3VtKGV4cHIuc2xpY2UoMCwgbSkpLCBcIixcIiwgZ2VuZXJhdGVTdW0oZXhwci5zbGljZShtKSksIFwiKVwiXS5qb2luKFwiXCIpXG4gIH1cbn1cblxuZnVuY3Rpb24gZGV0ZXJtaW5hbnQobSkge1xuICBpZihtLmxlbmd0aCA9PT0gMikge1xuICAgIHJldHVybiBbXCJzdW0ocHJvZChcIiwgbVswXVswXSwgXCIsXCIsIG1bMV1bMV0sIFwiKSxwcm9kKC1cIiwgbVswXVsxXSwgXCIsXCIsIG1bMV1bMF0sIFwiKSlcIl0uam9pbihcIlwiKVxuICB9IGVsc2Uge1xuICAgIHZhciBleHByID0gW11cbiAgICBmb3IodmFyIGk9MDsgaTxtLmxlbmd0aDsgKytpKSB7XG4gICAgICBleHByLnB1c2goW1wic2NhbGUoXCIsIGRldGVybWluYW50KGNvZmFjdG9yKG0sIGkpKSwgXCIsXCIsIHNpZ24oaSksIG1bMF1baV0sIFwiKVwiXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgICByZXR1cm4gZ2VuZXJhdGVTdW0oZXhwcilcbiAgfVxufVxuXG5mdW5jdGlvbiBjb21waWxlRGV0ZXJtaW5hbnQobikge1xuICB2YXIgcHJvYyA9IG5ldyBGdW5jdGlvbihcInN1bVwiLCBcInNjYWxlXCIsIFwicHJvZFwiLCBcImNvbXByZXNzXCIsIFtcbiAgICBcImZ1bmN0aW9uIHJvYnVzdERldGVybWluYW50XCIsbiwgXCIobSl7cmV0dXJuIGNvbXByZXNzKFwiLCBcbiAgICAgIGRldGVybWluYW50KG1hdHJpeChuKSksXG4gICAgXCIpfTtyZXR1cm4gcm9idXN0RGV0ZXJtaW5hbnRcIiwgbl0uam9pbihcIlwiKSlcbiAgcmV0dXJuIHByb2Mocm9idXN0U3VtLCByb2J1c3RTY2FsZSwgdHdvUHJvZHVjdCwgY29tcHJlc3MpXG59XG5cbnZhciBDQUNIRSA9IFtcbiAgZnVuY3Rpb24gcm9idXN0RGV0ZXJtaW5hbnQwKCkgeyByZXR1cm4gWzBdIH0sXG4gIGZ1bmN0aW9uIHJvYnVzdERldGVybWluYW50MShtKSB7IHJldHVybiBbbVswXVswXV0gfVxuXVxuXG5mdW5jdGlvbiBnZW5lcmF0ZURpc3BhdGNoKCkge1xuICB3aGlsZShDQUNIRS5sZW5ndGggPCBOVU1fRVhQQU5ERUQpIHtcbiAgICBDQUNIRS5wdXNoKGNvbXBpbGVEZXRlcm1pbmFudChDQUNIRS5sZW5ndGgpKVxuICB9XG4gIHZhciBwcm9jQXJncyA9IFtdXG4gIHZhciBjb2RlID0gW1wiZnVuY3Rpb24gcm9idXN0RGV0ZXJtaW5hbnQobSl7c3dpdGNoKG0ubGVuZ3RoKXtcIl1cbiAgZm9yKHZhciBpPTA7IGk8TlVNX0VYUEFOREVEOyArK2kpIHtcbiAgICBwcm9jQXJncy5wdXNoKFwiZGV0XCIgKyBpKVxuICAgIGNvZGUucHVzaChcImNhc2UgXCIsIGksIFwiOnJldHVybiBkZXRcIiwgaSwgXCIobSk7XCIpXG4gIH1cbiAgY29kZS5wdXNoKFwifVxcXG52YXIgZGV0PUNBQ0hFW20ubGVuZ3RoXTtcXFxuaWYoIWRldClcXFxuZGV0PUNBQ0hFW20ubGVuZ3RoXT1nZW4obS5sZW5ndGgpO1xcXG5yZXR1cm4gZGV0KG0pO1xcXG59XFxcbnJldHVybiByb2J1c3REZXRlcm1pbmFudFwiKVxuICBwcm9jQXJncy5wdXNoKFwiQ0FDSEVcIiwgXCJnZW5cIiwgY29kZS5qb2luKFwiXCIpKVxuICB2YXIgcHJvYyA9IEZ1bmN0aW9uLmFwcGx5KHVuZGVmaW5lZCwgcHJvY0FyZ3MpXG4gIG1vZHVsZS5leHBvcnRzID0gcHJvYy5hcHBseSh1bmRlZmluZWQsIENBQ0hFLmNvbmNhdChbQ0FDSEUsIGNvbXBpbGVEZXRlcm1pbmFudF0pKVxuICBmb3IodmFyIGk9MDsgaTxDQUNIRS5sZW5ndGg7ICsraSkge1xuICAgIG1vZHVsZS5leHBvcnRzW2ldID0gQ0FDSEVbaV1cbiAgfVxufVxuXG5nZW5lcmF0ZURpc3BhdGNoKClcbn0se1wicm9idXN0LWNvbXByZXNzXCI6NTA1LFwicm9idXN0LXNjYWxlXCI6NTEyLFwicm9idXN0LXN1bVwiOjUxNSxcInR3by1wcm9kdWN0XCI6NTQzfV0sNTA3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciB0d29Qcm9kdWN0ID0gX2RlcmVxXyhcInR3by1wcm9kdWN0XCIpXG52YXIgcm9idXN0U3VtID0gX2RlcmVxXyhcInJvYnVzdC1zdW1cIilcblxubW9kdWxlLmV4cG9ydHMgPSByb2J1c3REb3RQcm9kdWN0XG5cbmZ1bmN0aW9uIHJvYnVzdERvdFByb2R1Y3QoYSwgYikge1xuICB2YXIgciA9IHR3b1Byb2R1Y3QoYVswXSwgYlswXSlcbiAgZm9yKHZhciBpPTE7IGk8YS5sZW5ndGg7ICsraSkge1xuICAgIHIgPSByb2J1c3RTdW0ociwgdHdvUHJvZHVjdChhW2ldLCBiW2ldKSlcbiAgfVxuICByZXR1cm4gclxufVxufSx7XCJyb2J1c3Qtc3VtXCI6NTE1LFwidHdvLXByb2R1Y3RcIjo1NDN9XSw1MDg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxudmFyIHR3b1Byb2R1Y3QgPSBfZGVyZXFfKFwidHdvLXByb2R1Y3RcIilcbnZhciByb2J1c3RTdW0gPSBfZGVyZXFfKFwicm9idXN0LXN1bVwiKVxudmFyIHJvYnVzdERpZmYgPSBfZGVyZXFfKFwicm9idXN0LXN1YnRyYWN0XCIpXG52YXIgcm9idXN0U2NhbGUgPSBfZGVyZXFfKFwicm9idXN0LXNjYWxlXCIpXG5cbnZhciBOVU1fRVhQQU5EID0gNlxuXG5mdW5jdGlvbiBjb2ZhY3RvcihtLCBjKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobS5sZW5ndGgtMSlcbiAgZm9yKHZhciBpPTE7IGk8bS5sZW5ndGg7ICsraSkge1xuICAgIHZhciByID0gcmVzdWx0W2ktMV0gPSBuZXcgQXJyYXkobS5sZW5ndGgtMSlcbiAgICBmb3IodmFyIGo9MCxrPTA7IGo8bS5sZW5ndGg7ICsraikge1xuICAgICAgaWYoaiA9PT0gYykge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgcltrKytdID0gbVtpXVtqXVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIG1hdHJpeChuKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gbmV3IEFycmF5KG4pXG4gICAgZm9yKHZhciBqPTA7IGo8bjsgKytqKSB7XG4gICAgICByZXN1bHRbaV1bal0gPSBbXCJtXCIsIGosIFwiW1wiLCAobi1pLTIpLCBcIl1cIl0uam9pbihcIlwiKVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlU3VtKGV4cHIpIHtcbiAgaWYoZXhwci5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gZXhwclswXVxuICB9IGVsc2UgaWYoZXhwci5sZW5ndGggPT09IDIpIHtcbiAgICByZXR1cm4gW1wic3VtKFwiLCBleHByWzBdLCBcIixcIiwgZXhwclsxXSwgXCIpXCJdLmpvaW4oXCJcIilcbiAgfSBlbHNlIHtcbiAgICB2YXIgbSA9IGV4cHIubGVuZ3RoPj4xXG4gICAgcmV0dXJuIFtcInN1bShcIiwgZ2VuZXJhdGVTdW0oZXhwci5zbGljZSgwLCBtKSksIFwiLFwiLCBnZW5lcmF0ZVN1bShleHByLnNsaWNlKG0pKSwgXCIpXCJdLmpvaW4oXCJcIilcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlUHJvZHVjdChhLCBiKSB7XG4gIGlmKGEuY2hhckF0KDApID09PSBcIm1cIikge1xuICAgIGlmKGIuY2hhckF0KDApID09PSBcIndcIikge1xuICAgICAgdmFyIHRva3MgPSBhLnNwbGl0KFwiW1wiKVxuICAgICAgcmV0dXJuIFtcIndcIiwgYi5zdWJzdHIoMSksIFwibVwiLCB0b2tzWzBdLnN1YnN0cigxKV0uam9pbihcIlwiKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW1wicHJvZChcIiwgYSwgXCIsXCIsIGIsIFwiKVwiXS5qb2luKFwiXCIpXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBtYWtlUHJvZHVjdChiLCBhKVxuICB9XG59XG5cbmZ1bmN0aW9uIHNpZ24ocykge1xuICBpZihzICYgMSAhPT0gMCkge1xuICAgIHJldHVybiBcIi1cIlxuICB9XG4gIHJldHVybiBcIlwiXG59XG5cbmZ1bmN0aW9uIGRldGVybWluYW50KG0pIHtcbiAgaWYobS5sZW5ndGggPT09IDIpIHtcbiAgICByZXR1cm4gW1tcImRpZmYoXCIsIG1ha2VQcm9kdWN0KG1bMF1bMF0sIG1bMV1bMV0pLCBcIixcIiwgbWFrZVByb2R1Y3QobVsxXVswXSwgbVswXVsxXSksIFwiKVwiXS5qb2luKFwiXCIpXVxuICB9IGVsc2Uge1xuICAgIHZhciBleHByID0gW11cbiAgICBmb3IodmFyIGk9MDsgaTxtLmxlbmd0aDsgKytpKSB7XG4gICAgICBleHByLnB1c2goW1wic2NhbGUoXCIsIGdlbmVyYXRlU3VtKGRldGVybWluYW50KGNvZmFjdG9yKG0sIGkpKSksIFwiLFwiLCBzaWduKGkpLCBtWzBdW2ldLCBcIilcIl0uam9pbihcIlwiKSlcbiAgICB9XG4gICAgcmV0dXJuIGV4cHJcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlU3F1YXJlKGQsIG4pIHtcbiAgdmFyIHRlcm1zID0gW11cbiAgZm9yKHZhciBpPTA7IGk8bi0yOyArK2kpIHtcbiAgICB0ZXJtcy5wdXNoKFtcInByb2QobVwiLCBkLCBcIltcIiwgaSwgXCJdLG1cIiwgZCwgXCJbXCIsIGksIFwiXSlcIl0uam9pbihcIlwiKSlcbiAgfVxuICByZXR1cm4gZ2VuZXJhdGVTdW0odGVybXMpXG59XG5cbmZ1bmN0aW9uIG9yaWVudGF0aW9uKG4pIHtcbiAgdmFyIHBvcyA9IFtdXG4gIHZhciBuZWcgPSBbXVxuICB2YXIgbSA9IG1hdHJpeChuKVxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICBtWzBdW2ldID0gXCIxXCJcbiAgICBtW24tMV1baV0gPSBcIndcIitpXG4gIH0gXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIGlmKChpJjEpPT09MCkge1xuICAgICAgcG9zLnB1c2guYXBwbHkocG9zLGRldGVybWluYW50KGNvZmFjdG9yKG0sIGkpKSlcbiAgICB9IGVsc2Uge1xuICAgICAgbmVnLnB1c2guYXBwbHkobmVnLGRldGVybWluYW50KGNvZmFjdG9yKG0sIGkpKSlcbiAgICB9XG4gIH1cbiAgdmFyIHBvc0V4cHIgPSBnZW5lcmF0ZVN1bShwb3MpXG4gIHZhciBuZWdFeHByID0gZ2VuZXJhdGVTdW0obmVnKVxuICB2YXIgZnVuY05hbWUgPSBcImV4YWN0SW5TcGhlcmVcIiArIG5cbiAgdmFyIGZ1bmNBcmdzID0gW11cbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgZnVuY0FyZ3MucHVzaChcIm1cIiArIGkpXG4gIH1cbiAgdmFyIGNvZGUgPSBbXCJmdW5jdGlvbiBcIiwgZnVuY05hbWUsIFwiKFwiLCBmdW5jQXJncy5qb2luKCksIFwiKXtcIl1cbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgY29kZS5wdXNoKFwidmFyIHdcIixpLFwiPVwiLG1ha2VTcXVhcmUoaSxuKSxcIjtcIilcbiAgICBmb3IodmFyIGo9MDsgajxuOyArK2opIHtcbiAgICAgIGlmKGogIT09IGkpIHtcbiAgICAgICAgY29kZS5wdXNoKFwidmFyIHdcIixpLFwibVwiLGosXCI9c2NhbGUod1wiLGksXCIsbVwiLGosXCJbMF0pO1wiKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICBjb2RlLnB1c2goXCJ2YXIgcD1cIiwgcG9zRXhwciwgXCIsbj1cIiwgbmVnRXhwciwgXCIsZD1kaWZmKHAsbik7cmV0dXJuIGRbZC5sZW5ndGgtMV07fXJldHVybiBcIiwgZnVuY05hbWUpXG4gIHZhciBwcm9jID0gbmV3IEZ1bmN0aW9uKFwic3VtXCIsIFwiZGlmZlwiLCBcInByb2RcIiwgXCJzY2FsZVwiLCBjb2RlLmpvaW4oXCJcIikpXG4gIHJldHVybiBwcm9jKHJvYnVzdFN1bSwgcm9idXN0RGlmZiwgdHdvUHJvZHVjdCwgcm9idXN0U2NhbGUpXG59XG5cbmZ1bmN0aW9uIGluU3BoZXJlMCgpIHsgcmV0dXJuIDAgfVxuZnVuY3Rpb24gaW5TcGhlcmUxKCkgeyByZXR1cm4gMCB9XG5mdW5jdGlvbiBpblNwaGVyZTIoKSB7IHJldHVybiAwIH1cblxudmFyIENBQ0hFRCA9IFtcbiAgaW5TcGhlcmUwLFxuICBpblNwaGVyZTEsXG4gIGluU3BoZXJlMlxuXVxuXG5mdW5jdGlvbiBzbG93SW5TcGhlcmUoYXJncykge1xuICB2YXIgcHJvYyA9IENBQ0hFRFthcmdzLmxlbmd0aF1cbiAgaWYoIXByb2MpIHtcbiAgICBwcm9jID0gQ0FDSEVEW2FyZ3MubGVuZ3RoXSA9IG9yaWVudGF0aW9uKGFyZ3MubGVuZ3RoKVxuICB9XG4gIHJldHVybiBwcm9jLmFwcGx5KHVuZGVmaW5lZCwgYXJncylcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVJblNwaGVyZVRlc3QoKSB7XG4gIHdoaWxlKENBQ0hFRC5sZW5ndGggPD0gTlVNX0VYUEFORCkge1xuICAgIENBQ0hFRC5wdXNoKG9yaWVudGF0aW9uKENBQ0hFRC5sZW5ndGgpKVxuICB9XG4gIHZhciBhcmdzID0gW11cbiAgdmFyIHByb2NBcmdzID0gW1wic2xvd1wiXVxuICBmb3IodmFyIGk9MDsgaTw9TlVNX0VYUEFORDsgKytpKSB7XG4gICAgYXJncy5wdXNoKFwiYVwiICsgaSlcbiAgICBwcm9jQXJncy5wdXNoKFwib1wiICsgaSlcbiAgfVxuICB2YXIgY29kZSA9IFtcbiAgICBcImZ1bmN0aW9uIHRlc3RJblNwaGVyZShcIiwgYXJncy5qb2luKCksIFwiKXtzd2l0Y2goYXJndW1lbnRzLmxlbmd0aCl7Y2FzZSAwOmNhc2UgMTpyZXR1cm4gMDtcIlxuICBdXG4gIGZvcih2YXIgaT0yOyBpPD1OVU1fRVhQQU5EOyArK2kpIHtcbiAgICBjb2RlLnB1c2goXCJjYXNlIFwiLCBpLCBcIjpyZXR1cm4gb1wiLCBpLCBcIihcIiwgYXJncy5zbGljZSgwLCBpKS5qb2luKCksIFwiKTtcIilcbiAgfVxuICBjb2RlLnB1c2goXCJ9dmFyIHM9bmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO2Zvcih2YXIgaT0wO2k8YXJndW1lbnRzLmxlbmd0aDsrK2kpe3NbaV09YXJndW1lbnRzW2ldfTtyZXR1cm4gc2xvdyhzKTt9cmV0dXJuIHRlc3RJblNwaGVyZVwiKVxuICBwcm9jQXJncy5wdXNoKGNvZGUuam9pbihcIlwiKSlcblxuICB2YXIgcHJvYyA9IEZ1bmN0aW9uLmFwcGx5KHVuZGVmaW5lZCwgcHJvY0FyZ3MpXG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBwcm9jLmFwcGx5KHVuZGVmaW5lZCwgW3Nsb3dJblNwaGVyZV0uY29uY2F0KENBQ0hFRCkpXG4gIGZvcih2YXIgaT0wOyBpPD1OVU1fRVhQQU5EOyArK2kpIHtcbiAgICBtb2R1bGUuZXhwb3J0c1tpXSA9IENBQ0hFRFtpXVxuICB9XG59XG5cbmdlbmVyYXRlSW5TcGhlcmVUZXN0KClcbn0se1wicm9idXN0LXNjYWxlXCI6NTEyLFwicm9idXN0LXN1YnRyYWN0XCI6NTE0LFwicm9idXN0LXN1bVwiOjUxNSxcInR3by1wcm9kdWN0XCI6NTQzfV0sNTA5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciBkZXRlcm1pbmFudCA9IF9kZXJlcV8oXCJyb2J1c3QtZGV0ZXJtaW5hbnRcIilcblxudmFyIE5VTV9FWFBBTkQgPSA2XG5cbmZ1bmN0aW9uIGdlbmVyYXRlU29sdmVyKG4pIHtcbiAgdmFyIGZ1bmNOYW1lID0gXCJyb2J1c3RMaW5lYXJTb2x2ZVwiICsgbiArIFwiZFwiXG4gIHZhciBjb2RlID0gW1wiZnVuY3Rpb24gXCIsIGZ1bmNOYW1lLCBcIihBLGIpe3JldHVybiBbXCJdXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIGNvZGUucHVzaChcImRldChbXCIpXG4gICAgZm9yKHZhciBqPTA7IGo8bjsgKytqKSB7XG4gICAgICBpZihqID4gMCkge1xuICAgICAgICBjb2RlLnB1c2goXCIsXCIpXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goXCJbXCIpXG4gICAgICBmb3IodmFyIGs9MDsgazxuOyArK2spIHtcbiAgICAgICAgaWYoayA+IDApIHtcbiAgICAgICAgICBjb2RlLnB1c2goXCIsXCIpXG4gICAgICAgIH1cbiAgICAgICAgaWYoayA9PT0gaSkge1xuICAgICAgICAgIGNvZGUucHVzaChcIitiW1wiLCBqLCBcIl1cIilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb2RlLnB1c2goXCIrQVtcIiwgaiwgXCJdW1wiLCBrLCBcIl1cIilcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29kZS5wdXNoKFwiXVwiKVxuICAgIH1cbiAgICBjb2RlLnB1c2goXCJdKSxcIilcbiAgfVxuICBjb2RlLnB1c2goXCJkZXQoQSldfXJldHVybiBcIiwgZnVuY05hbWUpXG4gIHZhciBwcm9jID0gbmV3IEZ1bmN0aW9uKFwiZGV0XCIsIGNvZGUuam9pbihcIlwiKSlcbiAgaWYobiA8IDYpIHtcbiAgICByZXR1cm4gcHJvYyhkZXRlcm1pbmFudFtuXSlcbiAgfVxuICByZXR1cm4gcHJvYyhkZXRlcm1pbmFudClcbn1cblxuZnVuY3Rpb24gcm9idXN0TGluZWFyU29sdmUwZCgpIHtcbiAgcmV0dXJuIFsgMCBdXG59XG5cbmZ1bmN0aW9uIHJvYnVzdExpbmVhclNvbHZlMWQoQSwgYikge1xuICByZXR1cm4gWyBbIGJbMF0gXSwgWyBBWzBdWzBdIF0gXVxufVxuXG52YXIgQ0FDSEUgPSBbXG4gIHJvYnVzdExpbmVhclNvbHZlMGQsXG4gIHJvYnVzdExpbmVhclNvbHZlMWRcbl1cblxuZnVuY3Rpb24gZ2VuZXJhdGVEaXNwYXRjaCgpIHtcbiAgd2hpbGUoQ0FDSEUubGVuZ3RoIDwgTlVNX0VYUEFORCkge1xuICAgIENBQ0hFLnB1c2goZ2VuZXJhdGVTb2x2ZXIoQ0FDSEUubGVuZ3RoKSlcbiAgfVxuICB2YXIgcHJvY0FyZ3MgPSBbXVxuICB2YXIgY29kZSA9IFtcImZ1bmN0aW9uIGRpc3BhdGNoTGluZWFyU29sdmUoQSxiKXtzd2l0Y2goQS5sZW5ndGgpe1wiXVxuICBmb3IodmFyIGk9MDsgaTxOVU1fRVhQQU5EOyArK2kpIHtcbiAgICBwcm9jQXJncy5wdXNoKFwic1wiICsgaSlcbiAgICBjb2RlLnB1c2goXCJjYXNlIFwiLCBpLCBcIjpyZXR1cm4gc1wiLCBpLCBcIihBLGIpO1wiKVxuICB9XG4gIGNvZGUucHVzaChcIn12YXIgcz1DQUNIRVtBLmxlbmd0aF07aWYoIXMpcz1DQUNIRVtBLmxlbmd0aF09ZyhBLmxlbmd0aCk7cmV0dXJuIHMoQSxiKX1yZXR1cm4gZGlzcGF0Y2hMaW5lYXJTb2x2ZVwiKVxuICBwcm9jQXJncy5wdXNoKFwiQ0FDSEVcIiwgXCJnXCIsIGNvZGUuam9pbihcIlwiKSlcbiAgdmFyIHByb2MgPSBGdW5jdGlvbi5hcHBseSh1bmRlZmluZWQsIHByb2NBcmdzKVxuICBtb2R1bGUuZXhwb3J0cyA9IHByb2MuYXBwbHkodW5kZWZpbmVkLCBDQUNIRS5jb25jYXQoW0NBQ0hFLCBnZW5lcmF0ZVNvbHZlcl0pKVxuICBmb3IodmFyIGk9MDsgaTxOVU1fRVhQQU5EOyArK2kpIHtcbiAgICBtb2R1bGUuZXhwb3J0c1tpXSA9IENBQ0hFW2ldXG4gIH1cbn1cblxuZ2VuZXJhdGVEaXNwYXRjaCgpXG59LHtcInJvYnVzdC1kZXRlcm1pbmFudFwiOjUwNn1dLDUxMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG52YXIgdHdvUHJvZHVjdCA9IF9kZXJlcV8oXCJ0d28tcHJvZHVjdFwiKVxudmFyIHJvYnVzdFN1bSA9IF9kZXJlcV8oXCJyb2J1c3Qtc3VtXCIpXG52YXIgcm9idXN0U2NhbGUgPSBfZGVyZXFfKFwicm9idXN0LXNjYWxlXCIpXG52YXIgcm9idXN0U3VidHJhY3QgPSBfZGVyZXFfKFwicm9idXN0LXN1YnRyYWN0XCIpXG5cbnZhciBOVU1fRVhQQU5EID0gNVxuXG52YXIgRVBTSUxPTiAgICAgPSAxLjExMDIyMzAyNDYyNTE1NjVlLTE2XG52YXIgRVJSQk9VTkQzICAgPSAoMy4wICsgMTYuMCAqIEVQU0lMT04pICogRVBTSUxPTlxudmFyIEVSUkJPVU5ENCAgID0gKDcuMCArIDU2LjAgKiBFUFNJTE9OKSAqIEVQU0lMT05cblxuZnVuY3Rpb24gY29mYWN0b3IobSwgYykge1xuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG0ubGVuZ3RoLTEpXG4gIGZvcih2YXIgaT0xOyBpPG0ubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgciA9IHJlc3VsdFtpLTFdID0gbmV3IEFycmF5KG0ubGVuZ3RoLTEpXG4gICAgZm9yKHZhciBqPTAsaz0wOyBqPG0ubGVuZ3RoOyArK2opIHtcbiAgICAgIGlmKGogPT09IGMpIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIHJbaysrXSA9IG1baV1bal1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBtYXRyaXgobikge1xuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG4pXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIHJlc3VsdFtpXSA9IG5ldyBBcnJheShuKVxuICAgIGZvcih2YXIgaj0wOyBqPG47ICsraikge1xuICAgICAgcmVzdWx0W2ldW2pdID0gW1wibVwiLCBqLCBcIltcIiwgKG4taS0xKSwgXCJdXCJdLmpvaW4oXCJcIilcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG5mdW5jdGlvbiBzaWduKG4pIHtcbiAgaWYobiAmIDEpIHtcbiAgICByZXR1cm4gXCItXCJcbiAgfVxuICByZXR1cm4gXCJcIlxufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZVN1bShleHByKSB7XG4gIGlmKGV4cHIubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGV4cHJbMF1cbiAgfSBlbHNlIGlmKGV4cHIubGVuZ3RoID09PSAyKSB7XG4gICAgcmV0dXJuIFtcInN1bShcIiwgZXhwclswXSwgXCIsXCIsIGV4cHJbMV0sIFwiKVwiXS5qb2luKFwiXCIpXG4gIH0gZWxzZSB7XG4gICAgdmFyIG0gPSBleHByLmxlbmd0aD4+MVxuICAgIHJldHVybiBbXCJzdW0oXCIsIGdlbmVyYXRlU3VtKGV4cHIuc2xpY2UoMCwgbSkpLCBcIixcIiwgZ2VuZXJhdGVTdW0oZXhwci5zbGljZShtKSksIFwiKVwiXS5qb2luKFwiXCIpXG4gIH1cbn1cblxuZnVuY3Rpb24gZGV0ZXJtaW5hbnQobSkge1xuICBpZihtLmxlbmd0aCA9PT0gMikge1xuICAgIHJldHVybiBbW1wic3VtKHByb2QoXCIsIG1bMF1bMF0sIFwiLFwiLCBtWzFdWzFdLCBcIikscHJvZCgtXCIsIG1bMF1bMV0sIFwiLFwiLCBtWzFdWzBdLCBcIikpXCJdLmpvaW4oXCJcIildXG4gIH0gZWxzZSB7XG4gICAgdmFyIGV4cHIgPSBbXVxuICAgIGZvcih2YXIgaT0wOyBpPG0ubGVuZ3RoOyArK2kpIHtcbiAgICAgIGV4cHIucHVzaChbXCJzY2FsZShcIiwgZ2VuZXJhdGVTdW0oZGV0ZXJtaW5hbnQoY29mYWN0b3IobSwgaSkpKSwgXCIsXCIsIHNpZ24oaSksIG1bMF1baV0sIFwiKVwiXS5qb2luKFwiXCIpKVxuICAgIH1cbiAgICByZXR1cm4gZXhwclxuICB9XG59XG5cbmZ1bmN0aW9uIG9yaWVudGF0aW9uKG4pIHtcbiAgdmFyIHBvcyA9IFtdXG4gIHZhciBuZWcgPSBbXVxuICB2YXIgbSA9IG1hdHJpeChuKVxuICB2YXIgYXJncyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIGlmKChpJjEpPT09MCkge1xuICAgICAgcG9zLnB1c2guYXBwbHkocG9zLCBkZXRlcm1pbmFudChjb2ZhY3RvcihtLCBpKSkpXG4gICAgfSBlbHNlIHtcbiAgICAgIG5lZy5wdXNoLmFwcGx5KG5lZywgZGV0ZXJtaW5hbnQoY29mYWN0b3IobSwgaSkpKVxuICAgIH1cbiAgICBhcmdzLnB1c2goXCJtXCIgKyBpKVxuICB9XG4gIHZhciBwb3NFeHByID0gZ2VuZXJhdGVTdW0ocG9zKVxuICB2YXIgbmVnRXhwciA9IGdlbmVyYXRlU3VtKG5lZylcbiAgdmFyIGZ1bmNOYW1lID0gXCJvcmllbnRhdGlvblwiICsgbiArIFwiRXhhY3RcIlxuICB2YXIgY29kZSA9IFtcImZ1bmN0aW9uIFwiLCBmdW5jTmFtZSwgXCIoXCIsIGFyZ3Muam9pbigpLCBcIil7dmFyIHA9XCIsIHBvc0V4cHIsIFwiLG49XCIsIG5lZ0V4cHIsIFwiLGQ9c3ViKHAsbik7XFxcbnJldHVybiBkW2QubGVuZ3RoLTFdO307cmV0dXJuIFwiLCBmdW5jTmFtZV0uam9pbihcIlwiKVxuICB2YXIgcHJvYyA9IG5ldyBGdW5jdGlvbihcInN1bVwiLCBcInByb2RcIiwgXCJzY2FsZVwiLCBcInN1YlwiLCBjb2RlKVxuICByZXR1cm4gcHJvYyhyb2J1c3RTdW0sIHR3b1Byb2R1Y3QsIHJvYnVzdFNjYWxlLCByb2J1c3RTdWJ0cmFjdClcbn1cblxudmFyIG9yaWVudGF0aW9uM0V4YWN0ID0gb3JpZW50YXRpb24oMylcbnZhciBvcmllbnRhdGlvbjRFeGFjdCA9IG9yaWVudGF0aW9uKDQpXG5cbnZhciBDQUNIRUQgPSBbXG4gIGZ1bmN0aW9uIG9yaWVudGF0aW9uMCgpIHsgcmV0dXJuIDAgfSxcbiAgZnVuY3Rpb24gb3JpZW50YXRpb24xKCkgeyByZXR1cm4gMCB9LFxuICBmdW5jdGlvbiBvcmllbnRhdGlvbjIoYSwgYikgeyBcbiAgICByZXR1cm4gYlswXSAtIGFbMF1cbiAgfSxcbiAgZnVuY3Rpb24gb3JpZW50YXRpb24zKGEsIGIsIGMpIHtcbiAgICB2YXIgbCA9IChhWzFdIC0gY1sxXSkgKiAoYlswXSAtIGNbMF0pXG4gICAgdmFyIHIgPSAoYVswXSAtIGNbMF0pICogKGJbMV0gLSBjWzFdKVxuICAgIHZhciBkZXQgPSBsIC0gclxuICAgIHZhciBzXG4gICAgaWYobCA+IDApIHtcbiAgICAgIGlmKHIgPD0gMCkge1xuICAgICAgICByZXR1cm4gZGV0XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzID0gbCArIHJcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYobCA8IDApIHtcbiAgICAgIGlmKHIgPj0gMCkge1xuICAgICAgICByZXR1cm4gZGV0XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzID0gLShsICsgcilcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRldFxuICAgIH1cbiAgICB2YXIgdG9sID0gRVJSQk9VTkQzICogc1xuICAgIGlmKGRldCA+PSB0b2wgfHwgZGV0IDw9IC10b2wpIHtcbiAgICAgIHJldHVybiBkZXRcbiAgICB9XG4gICAgcmV0dXJuIG9yaWVudGF0aW9uM0V4YWN0KGEsIGIsIGMpXG4gIH0sXG4gIGZ1bmN0aW9uIG9yaWVudGF0aW9uNChhLGIsYyxkKSB7XG4gICAgdmFyIGFkeCA9IGFbMF0gLSBkWzBdXG4gICAgdmFyIGJkeCA9IGJbMF0gLSBkWzBdXG4gICAgdmFyIGNkeCA9IGNbMF0gLSBkWzBdXG4gICAgdmFyIGFkeSA9IGFbMV0gLSBkWzFdXG4gICAgdmFyIGJkeSA9IGJbMV0gLSBkWzFdXG4gICAgdmFyIGNkeSA9IGNbMV0gLSBkWzFdXG4gICAgdmFyIGFkeiA9IGFbMl0gLSBkWzJdXG4gICAgdmFyIGJkeiA9IGJbMl0gLSBkWzJdXG4gICAgdmFyIGNkeiA9IGNbMl0gLSBkWzJdXG4gICAgdmFyIGJkeGNkeSA9IGJkeCAqIGNkeVxuICAgIHZhciBjZHhiZHkgPSBjZHggKiBiZHlcbiAgICB2YXIgY2R4YWR5ID0gY2R4ICogYWR5XG4gICAgdmFyIGFkeGNkeSA9IGFkeCAqIGNkeVxuICAgIHZhciBhZHhiZHkgPSBhZHggKiBiZHlcbiAgICB2YXIgYmR4YWR5ID0gYmR4ICogYWR5XG4gICAgdmFyIGRldCA9IGFkeiAqIChiZHhjZHkgLSBjZHhiZHkpIFxuICAgICAgICAgICAgKyBiZHogKiAoY2R4YWR5IC0gYWR4Y2R5KVxuICAgICAgICAgICAgKyBjZHogKiAoYWR4YmR5IC0gYmR4YWR5KVxuICAgIHZhciBwZXJtYW5lbnQgPSAoTWF0aC5hYnMoYmR4Y2R5KSArIE1hdGguYWJzKGNkeGJkeSkpICogTWF0aC5hYnMoYWR6KVxuICAgICAgICAgICAgICAgICAgKyAoTWF0aC5hYnMoY2R4YWR5KSArIE1hdGguYWJzKGFkeGNkeSkpICogTWF0aC5hYnMoYmR6KVxuICAgICAgICAgICAgICAgICAgKyAoTWF0aC5hYnMoYWR4YmR5KSArIE1hdGguYWJzKGJkeGFkeSkpICogTWF0aC5hYnMoY2R6KVxuICAgIHZhciB0b2wgPSBFUlJCT1VORDQgKiBwZXJtYW5lbnRcbiAgICBpZiAoKGRldCA+IHRvbCkgfHwgKC1kZXQgPiB0b2wpKSB7XG4gICAgICByZXR1cm4gZGV0XG4gICAgfVxuICAgIHJldHVybiBvcmllbnRhdGlvbjRFeGFjdChhLGIsYyxkKVxuICB9XG5dXG5cbmZ1bmN0aW9uIHNsb3dPcmllbnQoYXJncykge1xuICB2YXIgcHJvYyA9IENBQ0hFRFthcmdzLmxlbmd0aF1cbiAgaWYoIXByb2MpIHtcbiAgICBwcm9jID0gQ0FDSEVEW2FyZ3MubGVuZ3RoXSA9IG9yaWVudGF0aW9uKGFyZ3MubGVuZ3RoKVxuICB9XG4gIHJldHVybiBwcm9jLmFwcGx5KHVuZGVmaW5lZCwgYXJncylcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVPcmllbnRhdGlvblByb2MoKSB7XG4gIHdoaWxlKENBQ0hFRC5sZW5ndGggPD0gTlVNX0VYUEFORCkge1xuICAgIENBQ0hFRC5wdXNoKG9yaWVudGF0aW9uKENBQ0hFRC5sZW5ndGgpKVxuICB9XG4gIHZhciBhcmdzID0gW11cbiAgdmFyIHByb2NBcmdzID0gW1wic2xvd1wiXVxuICBmb3IodmFyIGk9MDsgaTw9TlVNX0VYUEFORDsgKytpKSB7XG4gICAgYXJncy5wdXNoKFwiYVwiICsgaSlcbiAgICBwcm9jQXJncy5wdXNoKFwib1wiICsgaSlcbiAgfVxuICB2YXIgY29kZSA9IFtcbiAgICBcImZ1bmN0aW9uIGdldE9yaWVudGF0aW9uKFwiLCBhcmdzLmpvaW4oKSwgXCIpe3N3aXRjaChhcmd1bWVudHMubGVuZ3RoKXtjYXNlIDA6Y2FzZSAxOnJldHVybiAwO1wiXG4gIF1cbiAgZm9yKHZhciBpPTI7IGk8PU5VTV9FWFBBTkQ7ICsraSkge1xuICAgIGNvZGUucHVzaChcImNhc2UgXCIsIGksIFwiOnJldHVybiBvXCIsIGksIFwiKFwiLCBhcmdzLnNsaWNlKDAsIGkpLmpvaW4oKSwgXCIpO1wiKVxuICB9XG4gIGNvZGUucHVzaChcIn12YXIgcz1uZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCk7Zm9yKHZhciBpPTA7aTxhcmd1bWVudHMubGVuZ3RoOysraSl7c1tpXT1hcmd1bWVudHNbaV19O3JldHVybiBzbG93KHMpO31yZXR1cm4gZ2V0T3JpZW50YXRpb25cIilcbiAgcHJvY0FyZ3MucHVzaChjb2RlLmpvaW4oXCJcIikpXG5cbiAgdmFyIHByb2MgPSBGdW5jdGlvbi5hcHBseSh1bmRlZmluZWQsIHByb2NBcmdzKVxuICBtb2R1bGUuZXhwb3J0cyA9IHByb2MuYXBwbHkodW5kZWZpbmVkLCBbc2xvd09yaWVudF0uY29uY2F0KENBQ0hFRCkpXG4gIGZvcih2YXIgaT0wOyBpPD1OVU1fRVhQQU5EOyArK2kpIHtcbiAgICBtb2R1bGUuZXhwb3J0c1tpXSA9IENBQ0hFRFtpXVxuICB9XG59XG5cbmdlbmVyYXRlT3JpZW50YXRpb25Qcm9jKClcbn0se1wicm9idXN0LXNjYWxlXCI6NTEyLFwicm9idXN0LXN1YnRyYWN0XCI6NTE0LFwicm9idXN0LXN1bVwiOjUxNSxcInR3by1wcm9kdWN0XCI6NTQzfV0sNTExOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciByb2J1c3RTdW0gPSBfZGVyZXFfKFwicm9idXN0LXN1bVwiKVxudmFyIHJvYnVzdFNjYWxlID0gX2RlcmVxXyhcInJvYnVzdC1zY2FsZVwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHJvYnVzdFByb2R1Y3RcblxuZnVuY3Rpb24gcm9idXN0UHJvZHVjdChhLCBiKSB7XG4gIGlmKGEubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIHJvYnVzdFNjYWxlKGIsIGFbMF0pXG4gIH1cbiAgaWYoYi5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gcm9idXN0U2NhbGUoYSwgYlswXSlcbiAgfVxuICBpZihhLmxlbmd0aCA9PT0gMCB8fCBiLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbMF1cbiAgfVxuICB2YXIgciA9IFswXVxuICBpZihhLmxlbmd0aCA8IGIubGVuZ3RoKSB7XG4gICAgZm9yKHZhciBpPTA7IGk8YS5sZW5ndGg7ICsraSkge1xuICAgICAgciA9IHJvYnVzdFN1bShyLCByb2J1c3RTY2FsZShiLCBhW2ldKSlcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgZm9yKHZhciBpPTA7IGk8Yi5sZW5ndGg7ICsraSkge1xuICAgICAgciA9IHJvYnVzdFN1bShyLCByb2J1c3RTY2FsZShhLCBiW2ldKSlcbiAgICB9ICAgIFxuICB9XG4gIHJldHVybiByXG59XG59LHtcInJvYnVzdC1zY2FsZVwiOjUxMixcInJvYnVzdC1zdW1cIjo1MTV9XSw1MTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCJcblxudmFyIHR3b1Byb2R1Y3QgPSBfZGVyZXFfKFwidHdvLXByb2R1Y3RcIilcbnZhciB0d29TdW0gPSBfZGVyZXFfKFwidHdvLXN1bVwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHNjYWxlTGluZWFyRXhwYW5zaW9uXG5cbmZ1bmN0aW9uIHNjYWxlTGluZWFyRXhwYW5zaW9uKGUsIHNjYWxlKSB7XG4gIHZhciBuID0gZS5sZW5ndGhcbiAgaWYobiA9PT0gMSkge1xuICAgIHZhciB0cyA9IHR3b1Byb2R1Y3QoZVswXSwgc2NhbGUpXG4gICAgaWYodHNbMF0pIHtcbiAgICAgIHJldHVybiB0c1xuICAgIH1cbiAgICByZXR1cm4gWyB0c1sxXSBdXG4gIH1cbiAgdmFyIGcgPSBuZXcgQXJyYXkoMiAqIG4pXG4gIHZhciBxID0gWzAuMSwgMC4xXVxuICB2YXIgdCA9IFswLjEsIDAuMV1cbiAgdmFyIGNvdW50ID0gMFxuICB0d29Qcm9kdWN0KGVbMF0sIHNjYWxlLCBxKVxuICBpZihxWzBdKSB7XG4gICAgZ1tjb3VudCsrXSA9IHFbMF1cbiAgfVxuICBmb3IodmFyIGk9MTsgaTxuOyArK2kpIHtcbiAgICB0d29Qcm9kdWN0KGVbaV0sIHNjYWxlLCB0KVxuICAgIHZhciBwcSA9IHFbMV1cbiAgICB0d29TdW0ocHEsIHRbMF0sIHEpXG4gICAgaWYocVswXSkge1xuICAgICAgZ1tjb3VudCsrXSA9IHFbMF1cbiAgICB9XG4gICAgdmFyIGEgPSB0WzFdXG4gICAgdmFyIGIgPSBxWzFdXG4gICAgdmFyIHggPSBhICsgYlxuICAgIHZhciBidiA9IHggLSBhXG4gICAgdmFyIHkgPSBiIC0gYnZcbiAgICBxWzFdID0geFxuICAgIGlmKHkpIHtcbiAgICAgIGdbY291bnQrK10gPSB5XG4gICAgfVxuICB9XG4gIGlmKHFbMV0pIHtcbiAgICBnW2NvdW50KytdID0gcVsxXVxuICB9XG4gIGlmKGNvdW50ID09PSAwKSB7XG4gICAgZ1tjb3VudCsrXSA9IDAuMFxuICB9XG4gIGcubGVuZ3RoID0gY291bnRcbiAgcmV0dXJuIGdcbn1cbn0se1widHdvLXByb2R1Y3RcIjo1NDMsXCJ0d28tc3VtXCI6NTQ0fV0sNTEzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gc2VnbWVudHNJbnRlcnNlY3RcblxudmFyIG9yaWVudCA9IF9kZXJlcV8oXCJyb2J1c3Qtb3JpZW50YXRpb25cIilbM11cblxuZnVuY3Rpb24gY2hlY2tDb2xsaW5lYXIoYTAsIGExLCBiMCwgYjEpIHtcblxuICBmb3IodmFyIGQ9MDsgZDwyOyArK2QpIHtcbiAgICB2YXIgeDAgPSBhMFtkXVxuICAgIHZhciB5MCA9IGExW2RdXG4gICAgdmFyIGwwID0gTWF0aC5taW4oeDAsIHkwKVxuICAgIHZhciBoMCA9IE1hdGgubWF4KHgwLCB5MCkgICAgXG5cbiAgICB2YXIgeDEgPSBiMFtkXVxuICAgIHZhciB5MSA9IGIxW2RdXG4gICAgdmFyIGwxID0gTWF0aC5taW4oeDEsIHkxKVxuICAgIHZhciBoMSA9IE1hdGgubWF4KHgxLCB5MSkgICAgXG5cbiAgICBpZihoMSA8IGwwIHx8IGgwIDwgbDEpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlXG59XG5cbmZ1bmN0aW9uIHNlZ21lbnRzSW50ZXJzZWN0KGEwLCBhMSwgYjAsIGIxKSB7XG4gIHZhciB4MCA9IG9yaWVudChhMCwgYjAsIGIxKVxuICB2YXIgeTAgPSBvcmllbnQoYTEsIGIwLCBiMSlcbiAgaWYoKHgwID4gMCAmJiB5MCA+IDApIHx8ICh4MCA8IDAgJiYgeTAgPCAwKSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgdmFyIHgxID0gb3JpZW50KGIwLCBhMCwgYTEpXG4gIHZhciB5MSA9IG9yaWVudChiMSwgYTAsIGExKVxuICBpZigoeDEgPiAwICYmIHkxID4gMCkgfHwgKHgxIDwgMCAmJiB5MSA8IDApKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvL0NoZWNrIGZvciBkZWdlbmVyYXRlIGNvbGxpbmVhciBjYXNlXG4gIGlmKHgwID09PSAwICYmIHkwID09PSAwICYmIHgxID09PSAwICYmIHkxID09PSAwKSB7XG4gICAgcmV0dXJuIGNoZWNrQ29sbGluZWFyKGEwLCBhMSwgYjAsIGIxKVxuICB9XG5cbiAgcmV0dXJuIHRydWVcbn1cbn0se1wicm9idXN0LW9yaWVudGF0aW9uXCI6NTEwfV0sNTE0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gcm9idXN0U3VidHJhY3RcblxuLy9FYXN5IGNhc2U6IEFkZCB0d28gc2NhbGFyc1xuZnVuY3Rpb24gc2NhbGFyU2NhbGFyKGEsIGIpIHtcbiAgdmFyIHggPSBhICsgYlxuICB2YXIgYnYgPSB4IC0gYVxuICB2YXIgYXYgPSB4IC0gYnZcbiAgdmFyIGJyID0gYiAtIGJ2XG4gIHZhciBhciA9IGEgLSBhdlxuICB2YXIgeSA9IGFyICsgYnJcbiAgaWYoeSkge1xuICAgIHJldHVybiBbeSwgeF1cbiAgfVxuICByZXR1cm4gW3hdXG59XG5cbmZ1bmN0aW9uIHJvYnVzdFN1YnRyYWN0KGUsIGYpIHtcbiAgdmFyIG5lID0gZS5sZW5ndGh8MFxuICB2YXIgbmYgPSBmLmxlbmd0aHwwXG4gIGlmKG5lID09PSAxICYmIG5mID09PSAxKSB7XG4gICAgcmV0dXJuIHNjYWxhclNjYWxhcihlWzBdLCAtZlswXSlcbiAgfVxuICB2YXIgbiA9IG5lICsgbmZcbiAgdmFyIGcgPSBuZXcgQXJyYXkobilcbiAgdmFyIGNvdW50ID0gMFxuICB2YXIgZXB0ciA9IDBcbiAgdmFyIGZwdHIgPSAwXG4gIHZhciBhYnMgPSBNYXRoLmFic1xuICB2YXIgZWkgPSBlW2VwdHJdXG4gIHZhciBlYSA9IGFicyhlaSlcbiAgdmFyIGZpID0gLWZbZnB0cl1cbiAgdmFyIGZhID0gYWJzKGZpKVxuICB2YXIgYSwgYlxuICBpZihlYSA8IGZhKSB7XG4gICAgYiA9IGVpXG4gICAgZXB0ciArPSAxXG4gICAgaWYoZXB0ciA8IG5lKSB7XG4gICAgICBlaSA9IGVbZXB0cl1cbiAgICAgIGVhID0gYWJzKGVpKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBiID0gZmlcbiAgICBmcHRyICs9IDFcbiAgICBpZihmcHRyIDwgbmYpIHtcbiAgICAgIGZpID0gLWZbZnB0cl1cbiAgICAgIGZhID0gYWJzKGZpKVxuICAgIH1cbiAgfVxuICBpZigoZXB0ciA8IG5lICYmIGVhIDwgZmEpIHx8IChmcHRyID49IG5mKSkge1xuICAgIGEgPSBlaVxuICAgIGVwdHIgKz0gMVxuICAgIGlmKGVwdHIgPCBuZSkge1xuICAgICAgZWkgPSBlW2VwdHJdXG4gICAgICBlYSA9IGFicyhlaSlcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgYSA9IGZpXG4gICAgZnB0ciArPSAxXG4gICAgaWYoZnB0ciA8IG5mKSB7XG4gICAgICBmaSA9IC1mW2ZwdHJdXG4gICAgICBmYSA9IGFicyhmaSlcbiAgICB9XG4gIH1cbiAgdmFyIHggPSBhICsgYlxuICB2YXIgYnYgPSB4IC0gYVxuICB2YXIgeSA9IGIgLSBidlxuICB2YXIgcTAgPSB5XG4gIHZhciBxMSA9IHhcbiAgdmFyIF94LCBfYnYsIF9hdiwgX2JyLCBfYXJcbiAgd2hpbGUoZXB0ciA8IG5lICYmIGZwdHIgPCBuZikge1xuICAgIGlmKGVhIDwgZmEpIHtcbiAgICAgIGEgPSBlaVxuICAgICAgZXB0ciArPSAxXG4gICAgICBpZihlcHRyIDwgbmUpIHtcbiAgICAgICAgZWkgPSBlW2VwdHJdXG4gICAgICAgIGVhID0gYWJzKGVpKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBhID0gZmlcbiAgICAgIGZwdHIgKz0gMVxuICAgICAgaWYoZnB0ciA8IG5mKSB7XG4gICAgICAgIGZpID0gLWZbZnB0cl1cbiAgICAgICAgZmEgPSBhYnMoZmkpXG4gICAgICB9XG4gICAgfVxuICAgIGIgPSBxMFxuICAgIHggPSBhICsgYlxuICAgIGJ2ID0geCAtIGFcbiAgICB5ID0gYiAtIGJ2XG4gICAgaWYoeSkge1xuICAgICAgZ1tjb3VudCsrXSA9IHlcbiAgICB9XG4gICAgX3ggPSBxMSArIHhcbiAgICBfYnYgPSBfeCAtIHExXG4gICAgX2F2ID0gX3ggLSBfYnZcbiAgICBfYnIgPSB4IC0gX2J2XG4gICAgX2FyID0gcTEgLSBfYXZcbiAgICBxMCA9IF9hciArIF9iclxuICAgIHExID0gX3hcbiAgfVxuICB3aGlsZShlcHRyIDwgbmUpIHtcbiAgICBhID0gZWlcbiAgICBiID0gcTBcbiAgICB4ID0gYSArIGJcbiAgICBidiA9IHggLSBhXG4gICAgeSA9IGIgLSBidlxuICAgIGlmKHkpIHtcbiAgICAgIGdbY291bnQrK10gPSB5XG4gICAgfVxuICAgIF94ID0gcTEgKyB4XG4gICAgX2J2ID0gX3ggLSBxMVxuICAgIF9hdiA9IF94IC0gX2J2XG4gICAgX2JyID0geCAtIF9idlxuICAgIF9hciA9IHExIC0gX2F2XG4gICAgcTAgPSBfYXIgKyBfYnJcbiAgICBxMSA9IF94XG4gICAgZXB0ciArPSAxXG4gICAgaWYoZXB0ciA8IG5lKSB7XG4gICAgICBlaSA9IGVbZXB0cl1cbiAgICB9XG4gIH1cbiAgd2hpbGUoZnB0ciA8IG5mKSB7XG4gICAgYSA9IGZpXG4gICAgYiA9IHEwXG4gICAgeCA9IGEgKyBiXG4gICAgYnYgPSB4IC0gYVxuICAgIHkgPSBiIC0gYnZcbiAgICBpZih5KSB7XG4gICAgICBnW2NvdW50KytdID0geVxuICAgIH0gXG4gICAgX3ggPSBxMSArIHhcbiAgICBfYnYgPSBfeCAtIHExXG4gICAgX2F2ID0gX3ggLSBfYnZcbiAgICBfYnIgPSB4IC0gX2J2XG4gICAgX2FyID0gcTEgLSBfYXZcbiAgICBxMCA9IF9hciArIF9iclxuICAgIHExID0gX3hcbiAgICBmcHRyICs9IDFcbiAgICBpZihmcHRyIDwgbmYpIHtcbiAgICAgIGZpID0gLWZbZnB0cl1cbiAgICB9XG4gIH1cbiAgaWYocTApIHtcbiAgICBnW2NvdW50KytdID0gcTBcbiAgfVxuICBpZihxMSkge1xuICAgIGdbY291bnQrK10gPSBxMVxuICB9XG4gIGlmKCFjb3VudCkge1xuICAgIGdbY291bnQrK10gPSAwLjAgIFxuICB9XG4gIGcubGVuZ3RoID0gY291bnRcbiAgcmV0dXJuIGdcbn1cbn0se31dLDUxNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IGxpbmVhckV4cGFuc2lvblN1bVxuXG4vL0Vhc3kgY2FzZTogQWRkIHR3byBzY2FsYXJzXG5mdW5jdGlvbiBzY2FsYXJTY2FsYXIoYSwgYikge1xuICB2YXIgeCA9IGEgKyBiXG4gIHZhciBidiA9IHggLSBhXG4gIHZhciBhdiA9IHggLSBidlxuICB2YXIgYnIgPSBiIC0gYnZcbiAgdmFyIGFyID0gYSAtIGF2XG4gIHZhciB5ID0gYXIgKyBiclxuICBpZih5KSB7XG4gICAgcmV0dXJuIFt5LCB4XVxuICB9XG4gIHJldHVybiBbeF1cbn1cblxuZnVuY3Rpb24gbGluZWFyRXhwYW5zaW9uU3VtKGUsIGYpIHtcbiAgdmFyIG5lID0gZS5sZW5ndGh8MFxuICB2YXIgbmYgPSBmLmxlbmd0aHwwXG4gIGlmKG5lID09PSAxICYmIG5mID09PSAxKSB7XG4gICAgcmV0dXJuIHNjYWxhclNjYWxhcihlWzBdLCBmWzBdKVxuICB9XG4gIHZhciBuID0gbmUgKyBuZlxuICB2YXIgZyA9IG5ldyBBcnJheShuKVxuICB2YXIgY291bnQgPSAwXG4gIHZhciBlcHRyID0gMFxuICB2YXIgZnB0ciA9IDBcbiAgdmFyIGFicyA9IE1hdGguYWJzXG4gIHZhciBlaSA9IGVbZXB0cl1cbiAgdmFyIGVhID0gYWJzKGVpKVxuICB2YXIgZmkgPSBmW2ZwdHJdXG4gIHZhciBmYSA9IGFicyhmaSlcbiAgdmFyIGEsIGJcbiAgaWYoZWEgPCBmYSkge1xuICAgIGIgPSBlaVxuICAgIGVwdHIgKz0gMVxuICAgIGlmKGVwdHIgPCBuZSkge1xuICAgICAgZWkgPSBlW2VwdHJdXG4gICAgICBlYSA9IGFicyhlaSlcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgYiA9IGZpXG4gICAgZnB0ciArPSAxXG4gICAgaWYoZnB0ciA8IG5mKSB7XG4gICAgICBmaSA9IGZbZnB0cl1cbiAgICAgIGZhID0gYWJzKGZpKVxuICAgIH1cbiAgfVxuICBpZigoZXB0ciA8IG5lICYmIGVhIDwgZmEpIHx8IChmcHRyID49IG5mKSkge1xuICAgIGEgPSBlaVxuICAgIGVwdHIgKz0gMVxuICAgIGlmKGVwdHIgPCBuZSkge1xuICAgICAgZWkgPSBlW2VwdHJdXG4gICAgICBlYSA9IGFicyhlaSlcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgYSA9IGZpXG4gICAgZnB0ciArPSAxXG4gICAgaWYoZnB0ciA8IG5mKSB7XG4gICAgICBmaSA9IGZbZnB0cl1cbiAgICAgIGZhID0gYWJzKGZpKVxuICAgIH1cbiAgfVxuICB2YXIgeCA9IGEgKyBiXG4gIHZhciBidiA9IHggLSBhXG4gIHZhciB5ID0gYiAtIGJ2XG4gIHZhciBxMCA9IHlcbiAgdmFyIHExID0geFxuICB2YXIgX3gsIF9idiwgX2F2LCBfYnIsIF9hclxuICB3aGlsZShlcHRyIDwgbmUgJiYgZnB0ciA8IG5mKSB7XG4gICAgaWYoZWEgPCBmYSkge1xuICAgICAgYSA9IGVpXG4gICAgICBlcHRyICs9IDFcbiAgICAgIGlmKGVwdHIgPCBuZSkge1xuICAgICAgICBlaSA9IGVbZXB0cl1cbiAgICAgICAgZWEgPSBhYnMoZWkpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGEgPSBmaVxuICAgICAgZnB0ciArPSAxXG4gICAgICBpZihmcHRyIDwgbmYpIHtcbiAgICAgICAgZmkgPSBmW2ZwdHJdXG4gICAgICAgIGZhID0gYWJzKGZpKVxuICAgICAgfVxuICAgIH1cbiAgICBiID0gcTBcbiAgICB4ID0gYSArIGJcbiAgICBidiA9IHggLSBhXG4gICAgeSA9IGIgLSBidlxuICAgIGlmKHkpIHtcbiAgICAgIGdbY291bnQrK10gPSB5XG4gICAgfVxuICAgIF94ID0gcTEgKyB4XG4gICAgX2J2ID0gX3ggLSBxMVxuICAgIF9hdiA9IF94IC0gX2J2XG4gICAgX2JyID0geCAtIF9idlxuICAgIF9hciA9IHExIC0gX2F2XG4gICAgcTAgPSBfYXIgKyBfYnJcbiAgICBxMSA9IF94XG4gIH1cbiAgd2hpbGUoZXB0ciA8IG5lKSB7XG4gICAgYSA9IGVpXG4gICAgYiA9IHEwXG4gICAgeCA9IGEgKyBiXG4gICAgYnYgPSB4IC0gYVxuICAgIHkgPSBiIC0gYnZcbiAgICBpZih5KSB7XG4gICAgICBnW2NvdW50KytdID0geVxuICAgIH1cbiAgICBfeCA9IHExICsgeFxuICAgIF9idiA9IF94IC0gcTFcbiAgICBfYXYgPSBfeCAtIF9idlxuICAgIF9iciA9IHggLSBfYnZcbiAgICBfYXIgPSBxMSAtIF9hdlxuICAgIHEwID0gX2FyICsgX2JyXG4gICAgcTEgPSBfeFxuICAgIGVwdHIgKz0gMVxuICAgIGlmKGVwdHIgPCBuZSkge1xuICAgICAgZWkgPSBlW2VwdHJdXG4gICAgfVxuICB9XG4gIHdoaWxlKGZwdHIgPCBuZikge1xuICAgIGEgPSBmaVxuICAgIGIgPSBxMFxuICAgIHggPSBhICsgYlxuICAgIGJ2ID0geCAtIGFcbiAgICB5ID0gYiAtIGJ2XG4gICAgaWYoeSkge1xuICAgICAgZ1tjb3VudCsrXSA9IHlcbiAgICB9IFxuICAgIF94ID0gcTEgKyB4XG4gICAgX2J2ID0gX3ggLSBxMVxuICAgIF9hdiA9IF94IC0gX2J2XG4gICAgX2JyID0geCAtIF9idlxuICAgIF9hciA9IHExIC0gX2F2XG4gICAgcTAgPSBfYXIgKyBfYnJcbiAgICBxMSA9IF94XG4gICAgZnB0ciArPSAxXG4gICAgaWYoZnB0ciA8IG5mKSB7XG4gICAgICBmaSA9IGZbZnB0cl1cbiAgICB9XG4gIH1cbiAgaWYocTApIHtcbiAgICBnW2NvdW50KytdID0gcTBcbiAgfVxuICBpZihxMSkge1xuICAgIGdbY291bnQrK10gPSBxMVxuICB9XG4gIGlmKCFjb3VudCkge1xuICAgIGdbY291bnQrK10gPSAwLjAgIFxuICB9XG4gIGcubGVuZ3RoID0gY291bnRcbiAgcmV0dXJuIGdcbn1cbn0se31dLDUxNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNpZ251bSh4KSB7XG4gIGlmKHggPCAwKSB7IHJldHVybiAtMSB9XG4gIGlmKHggPiAwKSB7IHJldHVybiAxIH1cbiAgcmV0dXJuIDAuMFxufVxufSx7fV0sNTE3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJvdW5kYXJ5XG5cbnZhciBibmQgPSBfZGVyZXFfKCdib3VuZGFyeS1jZWxscycpXG52YXIgcmVkdWNlID0gX2RlcmVxXygncmVkdWNlLXNpbXBsaWNpYWwtY29tcGxleCcpXG5cbmZ1bmN0aW9uIGJvdW5kYXJ5KGNlbGxzKSB7XG4gIHJldHVybiByZWR1Y2UoYm5kKGNlbGxzKSlcbn1cblxufSx7XCJib3VuZGFyeS1jZWxsc1wiOjk1LFwicmVkdWNlLXNpbXBsaWNpYWwtY29tcGxleFwiOjQ4OX1dLDUxODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBleHRyYWN0Q29udG91clxuXG52YXIgbmRhcnJheSA9IF9kZXJlcV8oJ25kYXJyYXknKVxudmFyIHBvb2wgICAgPSBfZGVyZXFfKCd0eXBlZGFycmF5LXBvb2wnKVxudmFyIG5kc29ydCAgPSBfZGVyZXFfKCduZGFycmF5LXNvcnQnKVxuXG52YXIgY29udG91ckFsZ29yaXRobSA9IF9kZXJlcV8oJy4vbGliL2NvZGVnZW4nKVxuXG5mdW5jdGlvbiBnZXREaW1lbnNpb24oY2VsbHMpIHtcbiAgdmFyIG51bUNlbGxzID0gY2VsbHMubGVuZ3RoXG4gIHZhciBkID0gMFxuICBmb3IodmFyIGk9MDsgaTxudW1DZWxsczsgKytpKSB7XG4gICAgZCA9IE1hdGgubWF4KGQsIGNlbGxzW2ldLmxlbmd0aCl8MFxuICB9XG4gIHJldHVybiBkLTFcbn1cblxuZnVuY3Rpb24gZ2V0U2lnbnModmFsdWVzLCBsZXZlbCkge1xuICB2YXIgbnVtVmVydHMgICAgPSB2YWx1ZXMubGVuZ3RoXG4gIHZhciB2ZXJ0ZXhTaWducyA9IHBvb2wubWFsbG9jVWludDgobnVtVmVydHMpXG4gIGZvcih2YXIgaT0wOyBpPG51bVZlcnRzOyArK2kpIHtcbiAgICB2ZXJ0ZXhTaWduc1tpXSA9ICh2YWx1ZXNbaV0gPCBsZXZlbCl8MFxuICB9XG4gIHJldHVybiB2ZXJ0ZXhTaWduc1xufVxuXG5mdW5jdGlvbiBnZXRFZGdlcyhjZWxscywgZCkge1xuICB2YXIgbnVtQ2VsbHMgPSBjZWxscy5sZW5ndGhcbiAgdmFyIG1heEVkZ2VzID0gKChkICogKGQrMSkvMikgKiBudW1DZWxscyl8MFxuICB2YXIgZWRnZXMgICAgPSBwb29sLm1hbGxvY1VpbnQzMihtYXhFZGdlcyoyKVxuICB2YXIgZVB0ciAgICAgPSAwXG4gIGZvcih2YXIgaT0wOyBpPG51bUNlbGxzOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgdmFyIGQgPSBjLmxlbmd0aFxuICAgIGZvcih2YXIgaj0wOyBqPGQ7ICsraikge1xuICAgICAgZm9yKHZhciBrPTA7IGs8ajsgKytrKSB7XG4gICAgICAgIHZhciBhID0gY1trXVxuICAgICAgICB2YXIgYiA9IGNbal1cbiAgICAgICAgZWRnZXNbZVB0cisrXSA9IE1hdGgubWluKGEsYil8MFxuICAgICAgICBlZGdlc1tlUHRyKytdID0gTWF0aC5tYXgoYSxiKXwwXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHZhciBuZWRnZXMgPSAoZVB0ci8yKXwwXG4gIG5kc29ydChuZGFycmF5KGVkZ2VzLCBbbmVkZ2VzLDJdKSkgXG4gIHZhciBwdHIgPSAyXG4gIGZvcih2YXIgaT0yOyBpPGVQdHI7IGkrPTIpIHtcbiAgICBpZihlZGdlc1tpLTJdID09PSBlZGdlc1tpXSAmJlxuICAgICAgIGVkZ2VzW2ktMV0gPT09IGVkZ2VzW2krMV0pIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGVkZ2VzW3B0cisrXSA9IGVkZ2VzW2ldXG4gICAgZWRnZXNbcHRyKytdID0gZWRnZXNbaSsxXVxuICB9XG5cbiAgcmV0dXJuIG5kYXJyYXkoZWRnZXMsIFsocHRyLzIpfDAsIDJdKVxufVxuXG5mdW5jdGlvbiBnZXRDcm9zc2luZ1dlaWdodHMoZWRnZXMsIHZhbHVlcywgc2lnbnMsIGxldmVsKSB7XG4gIHZhciBlZGF0YSAgICAgPSBlZGdlcy5kYXRhXG4gIHZhciBudW1FZGdlcyAgPSBlZGdlcy5zaGFwZVswXVxuICB2YXIgd2VpZ2h0cyAgID0gcG9vbC5tYWxsb2NEb3VibGUobnVtRWRnZXMpXG4gIHZhciBwdHIgICAgICAgPSAwXG4gIGZvcih2YXIgaT0wOyBpPG51bUVkZ2VzOyArK2kpIHtcbiAgICB2YXIgYSAgPSBlZGF0YVsyKmldXG4gICAgdmFyIGIgID0gZWRhdGFbMippKzFdXG4gICAgaWYoc2lnbnNbYV0gPT09IHNpZ25zW2JdKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICB2YXIgdmEgPSB2YWx1ZXNbYV1cbiAgICB2YXIgdmIgPSB2YWx1ZXNbYl1cbiAgICBlZGF0YVsyKnB0cl0gICAgID0gYVxuICAgIGVkYXRhWzIqcHRyKzFdICAgPSBiXG4gICAgd2VpZ2h0c1twdHIrK10gICA9ICh2YiAtIGxldmVsKSAvICh2YiAtIHZhKVxuICB9XG4gIGVkZ2VzLnNoYXBlWzBdID0gcHRyXG4gIHJldHVybiBuZGFycmF5KHdlaWdodHMsIFtwdHJdKVxufVxuXG5mdW5jdGlvbiBnZXRDYXNjYWRlKGVkZ2VzLCBudW1WZXJ0cykge1xuICB2YXIgcmVzdWx0ICAgPSBwb29sLm1hbGxvY0ludDMyKG51bVZlcnRzKjIpXG4gIHZhciBudW1FZGdlcyA9IGVkZ2VzLnNoYXBlWzBdXG4gIHZhciBlZGF0YSAgICA9IGVkZ2VzLmRhdGFcbiAgcmVzdWx0WzBdICAgID0gMFxuICB2YXIgbGFzdFYgICAgPSAwXG4gIGZvcih2YXIgaT0wOyBpPG51bUVkZ2VzOyArK2kpIHtcbiAgICB2YXIgYSA9IGVkYXRhWzIqaV1cbiAgICBpZihhICE9PSBsYXN0Vikge1xuICAgICAgcmVzdWx0WzIqbGFzdFYrMV0gPSBpXG4gICAgICB3aGlsZSgrK2xhc3RWIDwgYSkge1xuICAgICAgICByZXN1bHRbMipsYXN0Vl0gPSBpXG4gICAgICAgIHJlc3VsdFsyKmxhc3RWKzFdID0gaVxuICAgICAgfVxuICAgICAgcmVzdWx0WzIqbGFzdFZdID0gaVxuICAgIH1cbiAgfVxuICByZXN1bHRbMipsYXN0VisxXSA9IG51bUVkZ2VzXG4gIHdoaWxlKCsrbGFzdFYgPCBudW1WZXJ0cykge1xuICAgIHJlc3VsdFsyKmxhc3RWXSA9IHJlc3VsdFsyKmxhc3RWKzFdID0gbnVtRWRnZXNcbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIHVucGFja0VkZ2VzKGVkZ2VzKSB7XG4gIHZhciBuZSA9IGVkZ2VzLnNoYXBlWzBdfDBcbiAgdmFyIGVkYXRhID0gZWRnZXMuZGF0YVxuICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KG5lKVxuICBmb3IodmFyIGk9MDsgaTxuZTsgKytpKSB7XG4gICAgcmVzdWx0W2ldID0gW2VkYXRhWzIqaV0sIGVkYXRhWzIqaSsxXV1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RDb250b3VyKGNlbGxzLCB2YWx1ZXMsIGxldmVsLCBkKSB7XG4gIGxldmVsID0gbGV2ZWx8fDAuMFxuXG4gIC8vSWYgdXNlciBkaWRuJ3Qgc3BlY2lmeSBgZGAsIHVzZSBicnV0ZSBmb3JjZSBzY2FuXG4gIGlmKHR5cGVvZiBkID09PSAndW5kZWZpbmVkJykge1xuICAgIGQgPSBnZXREaW1lbnNpb24oY2VsbHMpXG4gIH1cblxuICAvL0NvdW50IG51bWJlciBvZiBjZWxsc1xuICB2YXIgbnVtQ2VsbHMgPSBjZWxscy5sZW5ndGhcbiAgaWYobnVtQ2VsbHMgPT09IDAgfHwgZCA8IDEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY2VsbHM6ICAgICAgICAgW10sXG4gICAgICB2ZXJ0ZXhJZHM6ICAgICBbXSxcbiAgICAgIHZlcnRleFdlaWdodHM6IFtdXG4gICAgfVxuICB9XG5cbiAgLy9SZWFkIGluIHZlcnRleCBzaWduc1xuICB2YXIgdmVydGV4U2lnbnMgPSBnZXRTaWducyh2YWx1ZXMsICtsZXZlbClcblxuICAvL0ZpcnN0IGdldCAxLXNrZWxldG9uLCBmaW5kIGFsbCBjcm9zc2luZ3NcbiAgdmFyIGVkZ2VzICAgPSBnZXRFZGdlcyhjZWxscywgZClcbiAgdmFyIHdlaWdodHMgPSBnZXRDcm9zc2luZ1dlaWdodHMoZWRnZXMsIHZhbHVlcywgdmVydGV4U2lnbnMsICtsZXZlbClcblxuICAvL0J1aWxkIHZlcnRleCBjYXNjYWRlIHRvIHNwZWVkIHVwIGJpbmFyeSBzZWFyY2hcbiAgdmFyIHZjYXNjYWRlID0gZ2V0Q2FzY2FkZShlZGdlcywgdmFsdWVzLmxlbmd0aHwwKVxuXG4gIC8vVGhlbiBjb25zdHJ1Y3QgY2VsbHNcbiAgdmFyIGZhY2VzID0gY29udG91ckFsZ29yaXRobShkKShjZWxscywgZWRnZXMuZGF0YSwgdmNhc2NhZGUsIHZlcnRleFNpZ25zKVxuXG4gIC8vVW5wYWNrIGRhdGEgaW50byBwcmV0dHkgZm9ybWF0XG4gIHZhciB1ZWRnZXMgICA9IHVucGFja0VkZ2VzKGVkZ2VzKVxuICB2YXIgdXdlaWdodHMgPSBbXS5zbGljZS5jYWxsKHdlaWdodHMuZGF0YSwgMCwgd2VpZ2h0cy5zaGFwZVswXSlcblxuICAvL1JlbGVhc2UgZGF0YVxuICBwb29sLmZyZWUodmVydGV4U2lnbnMpXG4gIHBvb2wuZnJlZShlZGdlcy5kYXRhKVxuICBwb29sLmZyZWUod2VpZ2h0cy5kYXRhKVxuICBwb29sLmZyZWUodmNhc2NhZGUpXG4gIFxuICByZXR1cm4ge1xuICAgIGNlbGxzOiAgICAgICAgIGZhY2VzLFxuICAgIHZlcnRleElkczogICAgIHVlZGdlcyxcbiAgICB2ZXJ0ZXhXZWlnaHRzOiB1d2VpZ2h0c1xuICB9XG59XG59LHtcIi4vbGliL2NvZGVnZW5cIjo1MTksXCJuZGFycmF5XCI6NDUwLFwibmRhcnJheS1zb3J0XCI6NDQ4LFwidHlwZWRhcnJheS1wb29sXCI6NTQ1fV0sNTE5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldFBvbHlnb25pemVyXG5cbnZhciBwb29sID0gX2RlcmVxXygndHlwZWRhcnJheS1wb29sJylcbnZhciBjcmVhdGVNU1RhYmxlID0gX2RlcmVxXygnbWFyY2hpbmctc2ltcGxleC10YWJsZScpXG5cbnZhciBDQUNIRSA9IHt9XG5cbmZ1bmN0aW9uIGNyZWF0ZUNlbGxQb2x5Z29uaXplcihkKSB7XG4gIHZhciBtYXhDZWxsU2l6ZSA9IDBcbiAgdmFyIHRhYmxlcyA9IG5ldyBBcnJheShkKzEpXG4gIHRhYmxlc1swXSA9IFsgW10gXVxuICBmb3IodmFyIGk9MTsgaTw9ZDsgKytpKSB7XG4gICAgdmFyIHRhYiA9IHRhYmxlc1tpXSA9IGNyZWF0ZU1TVGFibGUoaSlcbiAgICBmb3IodmFyIGo9MDsgajx0YWIubGVuZ3RoOyArK2opIHtcbiAgICAgIG1heENlbGxTaXplID0gTWF0aC5tYXgobWF4Q2VsbFNpemUsIHRhYltpXS5sZW5ndGgpXG4gICAgfVxuICB9XG5cbiAgdmFyIGNvZGUgID0gW1xuICAnZnVuY3Rpb24gQihDLEUsaSxqKXsnLFxuICAgICd2YXIgYT1NYXRoLm1pbihpLGopfDAsYj1NYXRoLm1heChpLGopfDAsbD1DWzIqYV0saD1DWzIqYSsxXTsnLFxuICAgICd3aGlsZShsPGgpeycsXG4gICAgICAndmFyIG09KGwraCk+PjEsdj1FWzIqbSsxXTsnLFxuICAgICAgJ2lmKHY9PT1iKXtyZXR1cm4gbX0nLFxuICAgICAgJ2lmKGI8dil7aD1tfWVsc2V7bD1tKzF9JyxcbiAgICAnfScsXG4gICAgJ3JldHVybiBsOycsXG4gICd9OycsXG4gICdmdW5jdGlvbiBnZXRDb250b3VyJywgZCwgJ2QoRixFLEMsUyl7JyxcbiAgICAndmFyIG49Ri5sZW5ndGgsUj1bXTsnLFxuICAgICdmb3IodmFyIGk9MDtpPG47KytpKXt2YXIgYz1GW2ldLGw9Yy5sZW5ndGg7J1xuICBdXG5cbiAgZnVuY3Rpb24gZ2VuZXJhdGVDYXNlKGZhY2V0cykge1xuICAgIGlmKGZhY2V0cy5sZW5ndGggPD0gMCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGNvZGUucHVzaCgnUi5wdXNoKCcpXG4gICAgZm9yKHZhciBpPTA7IGk8ZmFjZXRzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgZmFjZXQgPSBmYWNldHNbaV1cbiAgICAgIGlmKGkgPiAwKSB7XG4gICAgICAgIGNvZGUucHVzaCgnLCcpXG4gICAgICB9XG4gICAgICBjb2RlLnB1c2goJ1snKVxuICAgICAgZm9yKHZhciBqPTA7IGo8ZmFjZXQubGVuZ3RoOyArK2opIHtcbiAgICAgICAgdmFyIGYgPSBmYWNldFtqXVxuICAgICAgICBpZihqID4gMCkge1xuICAgICAgICAgIGNvZGUucHVzaCgnLCcpXG4gICAgICAgIH1cbiAgICAgICAgY29kZS5wdXNoKCdCKEMsRSxjWycsIGZbMF0sICddLGNbJywgZlsxXSwgJ10pJylcbiAgICAgIH1cbiAgICAgIGNvZGUucHVzaCgnXScpXG4gICAgfVxuICAgIGNvZGUucHVzaCgnKTsnKVxuICB9XG5cbiAgZm9yKHZhciBpPWQrMTsgaT4xOyAtLWkpIHtcbiAgICBpZihpIDwgZCsxKSB7XG4gICAgICBjb2RlLnB1c2goJ2Vsc2UgJylcbiAgICB9XG4gICAgY29kZS5wdXNoKCdpZihsPT09JywgaSwgJyl7JylcblxuICAgIC8vR2VuZXJhdGUgbWFza1xuICAgIHZhciBtYXNrU3RyID0gW11cbiAgICBmb3IodmFyIGo9MDsgajxpOyArK2opIHtcbiAgICAgIG1hc2tTdHIucHVzaCgnKFNbY1snK2orJ11dPDwnK2orJyknKVxuICAgIH1cblxuICAgIC8vUGVyZm9ybSB0YWJsZSBsb29rIHVwXG4gICAgY29kZS5wdXNoKCd2YXIgTT0nLCBtYXNrU3RyLmpvaW4oJysnKSwgXG4gICAgICAnO2lmKE09PT0wfHxNPT09JywgKDE8PGkpLTEsIFxuICAgICAgICAnKXtjb250aW51ZX1zd2l0Y2goTSl7JylcblxuICAgIHZhciB0YWIgPSB0YWJsZXNbaS0xXVxuICAgIGZvcih2YXIgaj0wOyBqPHRhYi5sZW5ndGg7ICsraikge1xuICAgICAgY29kZS5wdXNoKCdjYXNlICcsIGosICc6JylcbiAgICAgIGdlbmVyYXRlQ2FzZSh0YWJbal0pXG4gICAgICBjb2RlLnB1c2goJ2JyZWFrOycpXG4gICAgfVxuICAgIGNvZGUucHVzaCgnfX0nKVxuICB9XG4gIGNvZGUucHVzaCgnfXJldHVybiBSO307cmV0dXJuIGdldENvbnRvdXInLCBkLCAnZCcpXG5cbiAgdmFyIHByb2MgPSBuZXcgRnVuY3Rpb24oJ3Bvb2wnLCBjb2RlLmpvaW4oJycpKVxuICByZXR1cm4gcHJvYyhwb29sKVxufVxuXG5mdW5jdGlvbiBnZXRQb2x5Z29uaXplcihkKSB7XG4gIHZhciBhbGcgPSBDQUNIRVtkXVxuICBpZighYWxnKSB7XG4gICAgYWxnID0gQ0FDSEVbZF0gPSBjcmVhdGVDZWxsUG9seWdvbml6ZXIoZCkgXG4gIH1cbiAgcmV0dXJuIGFsZ1xufVxufSx7XCJtYXJjaGluZy1zaW1wbGV4LXRhYmxlXCI6NDI3LFwidHlwZWRhcnJheS1wb29sXCI6NTQ1fV0sNTIwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiOyBcInVzZSByZXN0cmljdFwiO1xuXG52YXIgYml0cyAgICAgID0gX2RlcmVxXyhcImJpdC10d2lkZGxlXCIpXG4gICwgVW5pb25GaW5kID0gX2RlcmVxXyhcInVuaW9uLWZpbmRcIilcblxuLy9SZXR1cm5zIHRoZSBkaW1lbnNpb24gb2YgYSBjZWxsIGNvbXBsZXhcbmZ1bmN0aW9uIGRpbWVuc2lvbihjZWxscykge1xuICB2YXIgZCA9IDBcbiAgICAsIG1heCA9IE1hdGgubWF4XG4gIGZvcih2YXIgaT0wLCBpbD1jZWxscy5sZW5ndGg7IGk8aWw7ICsraSkge1xuICAgIGQgPSBtYXgoZCwgY2VsbHNbaV0ubGVuZ3RoKVxuICB9XG4gIHJldHVybiBkLTFcbn1cbmV4cG9ydHMuZGltZW5zaW9uID0gZGltZW5zaW9uXG5cbi8vQ291bnRzIHRoZSBudW1iZXIgb2YgdmVydGljZXMgaW4gZmFjZXNcbmZ1bmN0aW9uIGNvdW50VmVydGljZXMoY2VsbHMpIHtcbiAgdmFyIHZjID0gLTFcbiAgICAsIG1heCA9IE1hdGgubWF4XG4gIGZvcih2YXIgaT0wLCBpbD1jZWxscy5sZW5ndGg7IGk8aWw7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICBmb3IodmFyIGo9MCwgamw9Yy5sZW5ndGg7IGo8amw7ICsraikge1xuICAgICAgdmMgPSBtYXgodmMsIGNbal0pXG4gICAgfVxuICB9XG4gIHJldHVybiB2YysxXG59XG5leHBvcnRzLmNvdW50VmVydGljZXMgPSBjb3VudFZlcnRpY2VzXG5cbi8vUmV0dXJucyBhIGRlZXAgY29weSBvZiBjZWxsc1xuZnVuY3Rpb24gY2xvbmVDZWxscyhjZWxscykge1xuICB2YXIgbmNlbGxzID0gbmV3IEFycmF5KGNlbGxzLmxlbmd0aClcbiAgZm9yKHZhciBpPTAsIGlsPWNlbGxzLmxlbmd0aDsgaTxpbDsgKytpKSB7XG4gICAgbmNlbGxzW2ldID0gY2VsbHNbaV0uc2xpY2UoMClcbiAgfVxuICByZXR1cm4gbmNlbGxzXG59XG5leHBvcnRzLmNsb25lQ2VsbHMgPSBjbG9uZUNlbGxzXG5cbi8vUmFua3MgYSBwYWlyIG9mIGNlbGxzIHVwIHRvIHBlcm11dGF0aW9uXG5mdW5jdGlvbiBjb21wYXJlQ2VsbHMoYSwgYikge1xuICB2YXIgbiA9IGEubGVuZ3RoXG4gICAgLCB0ID0gYS5sZW5ndGggLSBiLmxlbmd0aFxuICAgICwgbWluID0gTWF0aC5taW5cbiAgaWYodCkge1xuICAgIHJldHVybiB0XG4gIH1cbiAgc3dpdGNoKG4pIHtcbiAgICBjYXNlIDA6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlIDE6XG4gICAgICByZXR1cm4gYVswXSAtIGJbMF07XG4gICAgY2FzZSAyOlxuICAgICAgdmFyIGQgPSBhWzBdK2FbMV0tYlswXS1iWzFdXG4gICAgICBpZihkKSB7XG4gICAgICAgIHJldHVybiBkXG4gICAgICB9XG4gICAgICByZXR1cm4gbWluKGFbMF0sYVsxXSkgLSBtaW4oYlswXSxiWzFdKVxuICAgIGNhc2UgMzpcbiAgICAgIHZhciBsMSA9IGFbMF0rYVsxXVxuICAgICAgICAsIG0xID0gYlswXStiWzFdXG4gICAgICBkID0gbDErYVsyXSAtIChtMStiWzJdKVxuICAgICAgaWYoZCkge1xuICAgICAgICByZXR1cm4gZFxuICAgICAgfVxuICAgICAgdmFyIGwwID0gbWluKGFbMF0sIGFbMV0pXG4gICAgICAgICwgbTAgPSBtaW4oYlswXSwgYlsxXSlcbiAgICAgICAgLCBkICA9IG1pbihsMCwgYVsyXSkgLSBtaW4obTAsIGJbMl0pXG4gICAgICBpZihkKSB7XG4gICAgICAgIHJldHVybiBkXG4gICAgICB9XG4gICAgICByZXR1cm4gbWluKGwwK2FbMl0sIGwxKSAtIG1pbihtMCtiWzJdLCBtMSlcbiAgICBcbiAgICAvL1RPRE86IE1heWJlIG9wdGltaXplIG49NCBhcyB3ZWxsP1xuICAgIFxuICAgIGRlZmF1bHQ6XG4gICAgICB2YXIgYXMgPSBhLnNsaWNlKDApXG4gICAgICBhcy5zb3J0KClcbiAgICAgIHZhciBicyA9IGIuc2xpY2UoMClcbiAgICAgIGJzLnNvcnQoKVxuICAgICAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgICAgIHQgPSBhc1tpXSAtIGJzW2ldXG4gICAgICAgIGlmKHQpIHtcbiAgICAgICAgICByZXR1cm4gdFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gMFxuICB9XG59XG5leHBvcnRzLmNvbXBhcmVDZWxscyA9IGNvbXBhcmVDZWxsc1xuXG5mdW5jdGlvbiBjb21wYXJlWmlwcGVkKGEsIGIpIHtcbiAgcmV0dXJuIGNvbXBhcmVDZWxscyhhWzBdLCBiWzBdKVxufVxuXG4vL1B1dHMgYSBjZWxsIGNvbXBsZXggaW50byBub3JtYWwgb3JkZXIgZm9yIHRoZSBwdXJwb3NlcyBvZiBmaW5kQ2VsbCBxdWVyaWVzXG5mdW5jdGlvbiBub3JtYWxpemUoY2VsbHMsIGF0dHIpIHtcbiAgaWYoYXR0cikge1xuICAgIHZhciBsZW4gPSBjZWxscy5sZW5ndGhcbiAgICB2YXIgemlwcGVkID0gbmV3IEFycmF5KGxlbilcbiAgICBmb3IodmFyIGk9MDsgaTxsZW47ICsraSkge1xuICAgICAgemlwcGVkW2ldID0gW2NlbGxzW2ldLCBhdHRyW2ldXVxuICAgIH1cbiAgICB6aXBwZWQuc29ydChjb21wYXJlWmlwcGVkKVxuICAgIGZvcih2YXIgaT0wOyBpPGxlbjsgKytpKSB7XG4gICAgICBjZWxsc1tpXSA9IHppcHBlZFtpXVswXVxuICAgICAgYXR0cltpXSA9IHppcHBlZFtpXVsxXVxuICAgIH1cbiAgICByZXR1cm4gY2VsbHNcbiAgfSBlbHNlIHtcbiAgICBjZWxscy5zb3J0KGNvbXBhcmVDZWxscylcbiAgICByZXR1cm4gY2VsbHNcbiAgfVxufVxuZXhwb3J0cy5ub3JtYWxpemUgPSBub3JtYWxpemVcblxuLy9SZW1vdmVzIGFsbCBkdXBsaWNhdGUgY2VsbHMgaW4gdGhlIGNvbXBsZXhcbmZ1bmN0aW9uIHVuaXF1ZShjZWxscykge1xuICBpZihjZWxscy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW11cbiAgfVxuICB2YXIgcHRyID0gMVxuICAgICwgbGVuID0gY2VsbHMubGVuZ3RoXG4gIGZvcih2YXIgaT0xOyBpPGxlbjsgKytpKSB7XG4gICAgdmFyIGEgPSBjZWxsc1tpXVxuICAgIGlmKGNvbXBhcmVDZWxscyhhLCBjZWxsc1tpLTFdKSkge1xuICAgICAgaWYoaSA9PT0gcHRyKSB7XG4gICAgICAgIHB0cisrXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjZWxsc1twdHIrK10gPSBhXG4gICAgfVxuICB9XG4gIGNlbGxzLmxlbmd0aCA9IHB0clxuICByZXR1cm4gY2VsbHNcbn1cbmV4cG9ydHMudW5pcXVlID0gdW5pcXVlO1xuXG4vL0ZpbmRzIGEgY2VsbCBpbiBhIG5vcm1hbGl6ZWQgY2VsbCBjb21wbGV4XG5mdW5jdGlvbiBmaW5kQ2VsbChjZWxscywgYykge1xuICB2YXIgbG8gPSAwXG4gICAgLCBoaSA9IGNlbGxzLmxlbmd0aC0xXG4gICAgLCByICA9IC0xXG4gIHdoaWxlIChsbyA8PSBoaSkge1xuICAgIHZhciBtaWQgPSAobG8gKyBoaSkgPj4gMVxuICAgICAgLCBzICAgPSBjb21wYXJlQ2VsbHMoY2VsbHNbbWlkXSwgYylcbiAgICBpZihzIDw9IDApIHtcbiAgICAgIGlmKHMgPT09IDApIHtcbiAgICAgICAgciA9IG1pZFxuICAgICAgfVxuICAgICAgbG8gPSBtaWQgKyAxXG4gICAgfSBlbHNlIGlmKHMgPiAwKSB7XG4gICAgICBoaSA9IG1pZCAtIDFcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJcbn1cbmV4cG9ydHMuZmluZENlbGwgPSBmaW5kQ2VsbDtcblxuLy9CdWlsZHMgYW4gaW5kZXggZm9yIGFuIG4tY2VsbC4gIFRoaXMgaXMgbW9yZSBnZW5lcmFsIHRoYW4gZHVhbCwgYnV0IGxlc3MgZWZmaWNpZW50XG5mdW5jdGlvbiBpbmNpZGVuY2UoZnJvbV9jZWxscywgdG9fY2VsbHMpIHtcbiAgdmFyIGluZGV4ID0gbmV3IEFycmF5KGZyb21fY2VsbHMubGVuZ3RoKVxuICBmb3IodmFyIGk9MCwgaWw9aW5kZXgubGVuZ3RoOyBpPGlsOyArK2kpIHtcbiAgICBpbmRleFtpXSA9IFtdXG4gIH1cbiAgdmFyIGIgPSBbXVxuICBmb3IodmFyIGk9MCwgbj10b19jZWxscy5sZW5ndGg7IGk8bjsgKytpKSB7XG4gICAgdmFyIGMgPSB0b19jZWxsc1tpXVxuICAgIHZhciBjbCA9IGMubGVuZ3RoXG4gICAgZm9yKHZhciBrPTEsIGtuPSgxPDxjbCk7IGs8a247ICsraykge1xuICAgICAgYi5sZW5ndGggPSBiaXRzLnBvcENvdW50KGspXG4gICAgICB2YXIgbCA9IDBcbiAgICAgIGZvcih2YXIgaj0wOyBqPGNsOyArK2opIHtcbiAgICAgICAgaWYoayAmICgxPDxqKSkge1xuICAgICAgICAgIGJbbCsrXSA9IGNbal1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdmFyIGlkeD1maW5kQ2VsbChmcm9tX2NlbGxzLCBiKVxuICAgICAgaWYoaWR4IDwgMCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgd2hpbGUodHJ1ZSkge1xuICAgICAgICBpbmRleFtpZHgrK10ucHVzaChpKVxuICAgICAgICBpZihpZHggPj0gZnJvbV9jZWxscy5sZW5ndGggfHwgY29tcGFyZUNlbGxzKGZyb21fY2VsbHNbaWR4XSwgYikgIT09IDApIHtcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBpbmRleFxufVxuZXhwb3J0cy5pbmNpZGVuY2UgPSBpbmNpZGVuY2VcblxuLy9Db21wdXRlcyB0aGUgZHVhbCBvZiB0aGUgbWVzaC4gIFRoaXMgaXMgYmFzaWNhbGx5IGFuIG9wdGltaXplZCB2ZXJzaW9uIG9mIGJ1aWxkSW5kZXggZm9yIHRoZSBzaXR1YXRpb24gd2hlcmUgZnJvbV9jZWxscyBpcyBqdXN0IHRoZSBsaXN0IG9mIHZlcnRpY2VzXG5mdW5jdGlvbiBkdWFsKGNlbGxzLCB2ZXJ0ZXhfY291bnQpIHtcbiAgaWYoIXZlcnRleF9jb3VudCkge1xuICAgIHJldHVybiBpbmNpZGVuY2UodW5pcXVlKHNrZWxldG9uKGNlbGxzLCAwKSksIGNlbGxzLCAwKVxuICB9XG4gIHZhciByZXMgPSBuZXcgQXJyYXkodmVydGV4X2NvdW50KVxuICBmb3IodmFyIGk9MDsgaTx2ZXJ0ZXhfY291bnQ7ICsraSkge1xuICAgIHJlc1tpXSA9IFtdXG4gIH1cbiAgZm9yKHZhciBpPTAsIGxlbj1jZWxscy5sZW5ndGg7IGk8bGVuOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgZm9yKHZhciBqPTAsIGNsPWMubGVuZ3RoOyBqPGNsOyArK2opIHtcbiAgICAgIHJlc1tjW2pdXS5wdXNoKGkpXG4gICAgfVxuICB9XG4gIHJldHVybiByZXNcbn1cbmV4cG9ydHMuZHVhbCA9IGR1YWxcblxuLy9FbnVtZXJhdGVzIGFsbCBjZWxscyBpbiB0aGUgY29tcGxleFxuZnVuY3Rpb24gZXhwbG9kZShjZWxscykge1xuICB2YXIgcmVzdWx0ID0gW11cbiAgZm9yKHZhciBpPTAsIGlsPWNlbGxzLmxlbmd0aDsgaTxpbDsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgICAgLCBjbCA9IGMubGVuZ3RofDBcbiAgICBmb3IodmFyIGo9MSwgamw9KDE8PGNsKTsgajxqbDsgKytqKSB7XG4gICAgICB2YXIgYiA9IFtdXG4gICAgICBmb3IodmFyIGs9MDsgazxjbDsgKytrKSB7XG4gICAgICAgIGlmKChqID4+PiBrKSAmIDEpIHtcbiAgICAgICAgICBiLnB1c2goY1trXSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmVzdWx0LnB1c2goYilcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5vcm1hbGl6ZShyZXN1bHQpXG59XG5leHBvcnRzLmV4cGxvZGUgPSBleHBsb2RlXG5cbi8vRW51bWVyYXRlcyBhbGwgb2YgdGhlIG4tY2VsbHMgb2YgYSBjZWxsIGNvbXBsZXhcbmZ1bmN0aW9uIHNrZWxldG9uKGNlbGxzLCBuKSB7XG4gIGlmKG4gPCAwKSB7XG4gICAgcmV0dXJuIFtdXG4gIH1cbiAgdmFyIHJlc3VsdCA9IFtdXG4gICAgLCBrMCAgICAgPSAoMTw8KG4rMSkpLTFcbiAgZm9yKHZhciBpPTA7IGk8Y2VsbHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgYyA9IGNlbGxzW2ldXG4gICAgZm9yKHZhciBrPWswOyBrPCgxPDxjLmxlbmd0aCk7IGs9Yml0cy5uZXh0Q29tYmluYXRpb24oaykpIHtcbiAgICAgIHZhciBiID0gbmV3IEFycmF5KG4rMSlcbiAgICAgICAgLCBsID0gMFxuICAgICAgZm9yKHZhciBqPTA7IGo8Yy5sZW5ndGg7ICsraikge1xuICAgICAgICBpZihrICYgKDE8PGopKSB7XG4gICAgICAgICAgYltsKytdID0gY1tqXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXN1bHQucHVzaChiKVxuICAgIH1cbiAgfVxuICByZXR1cm4gbm9ybWFsaXplKHJlc3VsdClcbn1cbmV4cG9ydHMuc2tlbGV0b24gPSBza2VsZXRvbjtcblxuLy9Db21wdXRlcyB0aGUgYm91bmRhcnkgb2YgYWxsIGNlbGxzLCBkb2VzIG5vdCByZW1vdmUgZHVwbGljYXRlc1xuZnVuY3Rpb24gYm91bmRhcnkoY2VsbHMpIHtcbiAgdmFyIHJlcyA9IFtdXG4gIGZvcih2YXIgaT0wLGlsPWNlbGxzLmxlbmd0aDsgaTxpbDsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wLGNsPWMubGVuZ3RoOyBqPGNsOyArK2opIHtcbiAgICAgIHZhciBiID0gbmV3IEFycmF5KGMubGVuZ3RoLTEpXG4gICAgICBmb3IodmFyIGs9MCwgbD0wOyBrPGNsOyArK2spIHtcbiAgICAgICAgaWYoayAhPT0gaikge1xuICAgICAgICAgIGJbbCsrXSA9IGNba11cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmVzLnB1c2goYilcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5vcm1hbGl6ZShyZXMpXG59XG5leHBvcnRzLmJvdW5kYXJ5ID0gYm91bmRhcnk7XG5cbi8vQ29tcHV0ZXMgY29ubmVjdGVkIGNvbXBvbmVudHMgZm9yIGEgZGVuc2UgY2VsbCBjb21wbGV4XG5mdW5jdGlvbiBjb25uZWN0ZWRDb21wb25lbnRzX2RlbnNlKGNlbGxzLCB2ZXJ0ZXhfY291bnQpIHtcbiAgdmFyIGxhYmVscyA9IG5ldyBVbmlvbkZpbmQodmVydGV4X2NvdW50KVxuICBmb3IodmFyIGk9MDsgaTxjZWxscy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBjID0gY2VsbHNbaV1cbiAgICBmb3IodmFyIGo9MDsgajxjLmxlbmd0aDsgKytqKSB7XG4gICAgICBmb3IodmFyIGs9aisxOyBrPGMubGVuZ3RoOyArK2spIHtcbiAgICAgICAgbGFiZWxzLmxpbmsoY1tqXSwgY1trXSlcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdmFyIGNvbXBvbmVudHMgPSBbXVxuICAgICwgY29tcG9uZW50X2xhYmVscyA9IGxhYmVscy5yYW5rc1xuICBmb3IodmFyIGk9MDsgaTxjb21wb25lbnRfbGFiZWxzLmxlbmd0aDsgKytpKSB7XG4gICAgY29tcG9uZW50X2xhYmVsc1tpXSA9IC0xXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8Y2VsbHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgbCA9IGxhYmVscy5maW5kKGNlbGxzW2ldWzBdKVxuICAgIGlmKGNvbXBvbmVudF9sYWJlbHNbbF0gPCAwKSB7XG4gICAgICBjb21wb25lbnRfbGFiZWxzW2xdID0gY29tcG9uZW50cy5sZW5ndGhcbiAgICAgIGNvbXBvbmVudHMucHVzaChbY2VsbHNbaV0uc2xpY2UoMCldKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb21wb25lbnRzW2NvbXBvbmVudF9sYWJlbHNbbF1dLnB1c2goY2VsbHNbaV0uc2xpY2UoMCkpXG4gICAgfVxuICB9XG4gIHJldHVybiBjb21wb25lbnRzXG59XG5cbi8vQ29tcHV0ZXMgY29ubmVjdGVkIGNvbXBvbmVudHMgZm9yIGEgc3BhcnNlIGdyYXBoXG5mdW5jdGlvbiBjb25uZWN0ZWRDb21wb25lbnRzX3NwYXJzZShjZWxscykge1xuICB2YXIgdmVydGljZXMgID0gdW5pcXVlKG5vcm1hbGl6ZShza2VsZXRvbihjZWxscywgMCkpKVxuICAgICwgbGFiZWxzICAgID0gbmV3IFVuaW9uRmluZCh2ZXJ0aWNlcy5sZW5ndGgpXG4gIGZvcih2YXIgaT0wOyBpPGNlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPGMubGVuZ3RoOyArK2opIHtcbiAgICAgIHZhciB2aiA9IGZpbmRDZWxsKHZlcnRpY2VzLCBbY1tqXV0pXG4gICAgICBmb3IodmFyIGs9aisxOyBrPGMubGVuZ3RoOyArK2spIHtcbiAgICAgICAgbGFiZWxzLmxpbmsodmosIGZpbmRDZWxsKHZlcnRpY2VzLCBbY1trXV0pKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICB2YXIgY29tcG9uZW50cyAgICAgICAgPSBbXVxuICAgICwgY29tcG9uZW50X2xhYmVscyAgPSBsYWJlbHMucmFua3NcbiAgZm9yKHZhciBpPTA7IGk8Y29tcG9uZW50X2xhYmVscy5sZW5ndGg7ICsraSkge1xuICAgIGNvbXBvbmVudF9sYWJlbHNbaV0gPSAtMVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPGNlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGwgPSBsYWJlbHMuZmluZChmaW5kQ2VsbCh2ZXJ0aWNlcywgW2NlbGxzW2ldWzBdXSkpO1xuICAgIGlmKGNvbXBvbmVudF9sYWJlbHNbbF0gPCAwKSB7XG4gICAgICBjb21wb25lbnRfbGFiZWxzW2xdID0gY29tcG9uZW50cy5sZW5ndGhcbiAgICAgIGNvbXBvbmVudHMucHVzaChbY2VsbHNbaV0uc2xpY2UoMCldKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb21wb25lbnRzW2NvbXBvbmVudF9sYWJlbHNbbF1dLnB1c2goY2VsbHNbaV0uc2xpY2UoMCkpXG4gICAgfVxuICB9XG4gIHJldHVybiBjb21wb25lbnRzXG59XG5cbi8vQ29tcHV0ZXMgY29ubmVjdGVkIGNvbXBvbmVudHMgZm9yIGEgY2VsbCBjb21wbGV4XG5mdW5jdGlvbiBjb25uZWN0ZWRDb21wb25lbnRzKGNlbGxzLCB2ZXJ0ZXhfY291bnQpIHtcbiAgaWYodmVydGV4X2NvdW50KSB7XG4gICAgcmV0dXJuIGNvbm5lY3RlZENvbXBvbmVudHNfZGVuc2UoY2VsbHMsIHZlcnRleF9jb3VudClcbiAgfVxuICByZXR1cm4gY29ubmVjdGVkQ29tcG9uZW50c19zcGFyc2UoY2VsbHMpXG59XG5leHBvcnRzLmNvbm5lY3RlZENvbXBvbmVudHMgPSBjb25uZWN0ZWRDb21wb25lbnRzXG5cbn0se1wiYml0LXR3aWRkbGVcIjo5MixcInVuaW9uLWZpbmRcIjo1NDZ9XSw1MjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuYXJndW1lbnRzWzRdWzkyXVswXS5hcHBseShleHBvcnRzLGFyZ3VtZW50cylcbn0se1wiZHVwXCI6OTJ9XSw1MjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuYXJndW1lbnRzWzRdWzUyMF1bMF0uYXBwbHkoZXhwb3J0cyxhcmd1bWVudHMpXG59LHtcImJpdC10d2lkZGxlXCI6NTIxLFwiZHVwXCI6NTIwLFwidW5pb24tZmluZFwiOjUyM31dLDUyMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIjsgXCJ1c2UgcmVzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBVbmlvbkZpbmQ7XG5cbmZ1bmN0aW9uIFVuaW9uRmluZChjb3VudCkge1xuICB0aGlzLnJvb3RzID0gbmV3IEFycmF5KGNvdW50KTtcbiAgdGhpcy5yYW5rcyA9IG5ldyBBcnJheShjb3VudCk7XG4gIFxuICBmb3IodmFyIGk9MDsgaTxjb3VudDsgKytpKSB7XG4gICAgdGhpcy5yb290c1tpXSA9IGk7XG4gICAgdGhpcy5yYW5rc1tpXSA9IDA7XG4gIH1cbn1cblxuVW5pb25GaW5kLnByb3RvdHlwZS5sZW5ndGggPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMucm9vdHMubGVuZ3RoO1xufVxuXG5VbmlvbkZpbmQucHJvdG90eXBlLm1ha2VTZXQgPSBmdW5jdGlvbigpIHtcbiAgdmFyIG4gPSB0aGlzLnJvb3RzLmxlbmd0aDtcbiAgdGhpcy5yb290cy5wdXNoKG4pO1xuICB0aGlzLnJhbmtzLnB1c2goMCk7XG4gIHJldHVybiBuO1xufVxuXG5VbmlvbkZpbmQucHJvdG90eXBlLmZpbmQgPSBmdW5jdGlvbih4KSB7XG4gIHZhciByb290cyA9IHRoaXMucm9vdHM7XG4gIHdoaWxlKHJvb3RzW3hdICE9PSB4KSB7XG4gICAgdmFyIHkgPSByb290c1t4XTtcbiAgICByb290c1t4XSA9IHJvb3RzW3ldO1xuICAgIHggPSB5O1xuICB9XG4gIHJldHVybiB4O1xufVxuXG5VbmlvbkZpbmQucHJvdG90eXBlLmxpbmsgPSBmdW5jdGlvbih4LCB5KSB7XG4gIHZhciB4ciA9IHRoaXMuZmluZCh4KVxuICAgICwgeXIgPSB0aGlzLmZpbmQoeSk7XG4gIGlmKHhyID09PSB5cikge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgcmFua3MgPSB0aGlzLnJhbmtzXG4gICAgLCByb290cyA9IHRoaXMucm9vdHNcbiAgICAsIHhkICAgID0gcmFua3NbeHJdXG4gICAgLCB5ZCAgICA9IHJhbmtzW3lyXTtcbiAgaWYoeGQgPCB5ZCkge1xuICAgIHJvb3RzW3hyXSA9IHlyO1xuICB9IGVsc2UgaWYoeWQgPCB4ZCkge1xuICAgIHJvb3RzW3lyXSA9IHhyO1xuICB9IGVsc2Uge1xuICAgIHJvb3RzW3lyXSA9IHhyO1xuICAgICsrcmFua3NbeHJdO1xuICB9XG59XG5cblxufSx7fV0sNTI0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gc2ltcGxpZnlQb2x5Z29uXG5cbnZhciBvcmllbnQgPSBfZGVyZXFfKFwicm9idXN0LW9yaWVudGF0aW9uXCIpXG52YXIgc2MgPSBfZGVyZXFfKFwic2ltcGxpY2lhbC1jb21wbGV4XCIpXG5cbmZ1bmN0aW9uIGVycm9yV2VpZ2h0KGJhc2UsIGEsIGIpIHtcbiAgdmFyIGFyZWEgPSBNYXRoLmFicyhvcmllbnQoYmFzZSwgYSwgYikpXG4gIHZhciBwZXJpbSA9IE1hdGguc3FydChNYXRoLnBvdyhhWzBdIC0gYlswXSwgMikgKyBNYXRoLnBvdyhhWzFdLWJbMV0sIDIpKVxuICByZXR1cm4gYXJlYSAvIHBlcmltXG59XG5cbmZ1bmN0aW9uIHNpbXBsaWZ5UG9seWdvbihjZWxscywgcG9zaXRpb25zLCBtaW5BcmVhKSB7XG5cbiAgdmFyIG4gPSBwb3NpdGlvbnMubGVuZ3RoXG4gIHZhciBuYyA9IGNlbGxzLmxlbmd0aFxuICB2YXIgaW52ID0gbmV3IEFycmF5KG4pXG4gIHZhciBvdXR2ID0gbmV3IEFycmF5KG4pXG4gIHZhciB3ZWlnaHRzID0gbmV3IEFycmF5KG4pXG4gIHZhciBkZWFkID0gbmV3IEFycmF5KG4pXG4gIFxuICAvL0luaXRpYWxpemUgdGFibGVzXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIGludltpXSA9IG91dHZbaV0gPSAtMVxuICAgIHdlaWdodHNbaV0gPSBJbmZpbml0eVxuICAgIGRlYWRbaV0gPSBmYWxzZVxuICB9XG5cbiAgLy9Db21wdXRlIG5laWdoYm9yc1xuICBmb3IodmFyIGk9MDsgaTxuYzsgKytpKSB7XG4gICAgdmFyIGMgPSBjZWxsc1tpXVxuICAgIGlmKGMubGVuZ3RoICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnB1dCBtdXN0IGJlIGEgZ3JhcGhcIilcbiAgICB9XG4gICAgdmFyIHMgPSBjWzFdXG4gICAgdmFyIHQgPSBjWzBdXG4gICAgaWYob3V0dlt0XSAhPT0gLTEpIHtcbiAgICAgIG91dHZbdF0gPSAtMlxuICAgIH0gZWxzZSB7XG4gICAgICBvdXR2W3RdID0gc1xuICAgIH1cbiAgICBpZihpbnZbc10gIT09IC0xKSB7XG4gICAgICBpbnZbc10gPSAtMlxuICAgIH0gZWxzZSB7XG4gICAgICBpbnZbc10gPSB0XG4gICAgfVxuICB9XG5cbiAgLy9VcGRhdGVzIHRoZSB3ZWlnaHQgZm9yIHZlcnRleCBpXG4gIGZ1bmN0aW9uIGNvbXB1dGVXZWlnaHQoaSkge1xuICAgIGlmKGRlYWRbaV0pIHtcbiAgICAgIHJldHVybiBJbmZpbml0eVxuICAgIH1cbiAgICAvL1RPRE86IENoZWNrIHRoYXQgdGhlIGxpbmUgc2VnbWVudCBkb2Vzbid0IGNyb3NzIG9uY2Ugc2ltcGxpZmllZFxuICAgIHZhciBzID0gaW52W2ldXG4gICAgdmFyIHQgPSBvdXR2W2ldXG4gICAgaWYoKHM8MCkgfHwgKHQ8MCkpIHtcbiAgICAgIHJldHVybiBJbmZpbml0eVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZXJyb3JXZWlnaHQocG9zaXRpb25zW2ldLCBwb3NpdGlvbnNbc10sIHBvc2l0aW9uc1t0XSlcbiAgICB9XG4gIH1cblxuICAvL1N3YXBzIHR3byBub2RlcyBvbiB0aGUgaGVhcCAoaSxqKSBhcmUgdGhlIGluZGV4IG9mIHRoZSBub2Rlc1xuICBmdW5jdGlvbiBoZWFwU3dhcChpLGopIHtcbiAgICB2YXIgYSA9IGhlYXBbaV1cbiAgICB2YXIgYiA9IGhlYXBbal1cbiAgICBoZWFwW2ldID0gYlxuICAgIGhlYXBbal0gPSBhXG4gICAgaW5kZXhbYV0gPSBqXG4gICAgaW5kZXhbYl0gPSBpXG4gIH1cblxuICAvL1JldHVybnMgdGhlIHdlaWdodCBvZiBub2RlIGkgb24gdGhlIGhlYXBcbiAgZnVuY3Rpb24gaGVhcFdlaWdodChpKSB7XG4gICAgcmV0dXJuIHdlaWdodHNbaGVhcFtpXV1cbiAgfVxuXG4gIGZ1bmN0aW9uIGhlYXBQYXJlbnQoaSkge1xuICAgIGlmKGkgJiAxKSB7XG4gICAgICByZXR1cm4gKGkgLSAxKSA+PiAxXG4gICAgfVxuICAgIHJldHVybiAoaSA+PiAxKSAtIDFcbiAgfVxuXG4gIC8vQnViYmxlIGVsZW1lbnQgaSBkb3duIHRoZSBoZWFwXG4gIGZ1bmN0aW9uIGhlYXBEb3duKGkpIHtcbiAgICB2YXIgdyA9IGhlYXBXZWlnaHQoaSlcbiAgICB3aGlsZSh0cnVlKSB7XG4gICAgICB2YXIgdHcgPSB3XG4gICAgICB2YXIgbGVmdCAgPSAyKmkgKyAxXG4gICAgICB2YXIgcmlnaHQgPSAyKihpICsgMSlcbiAgICAgIHZhciBuZXh0ID0gaVxuICAgICAgaWYobGVmdCA8IGhlYXBDb3VudCkge1xuICAgICAgICB2YXIgbHcgPSBoZWFwV2VpZ2h0KGxlZnQpXG4gICAgICAgIGlmKGx3IDwgdHcpIHtcbiAgICAgICAgICBuZXh0ID0gbGVmdFxuICAgICAgICAgIHR3ID0gbHdcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYocmlnaHQgPCBoZWFwQ291bnQpIHtcbiAgICAgICAgdmFyIHJ3ID0gaGVhcFdlaWdodChyaWdodClcbiAgICAgICAgaWYocncgPCB0dykge1xuICAgICAgICAgIG5leHQgPSByaWdodFxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZihuZXh0ID09PSBpKSB7XG4gICAgICAgIHJldHVybiBpXG4gICAgICB9XG4gICAgICBoZWFwU3dhcChpLCBuZXh0KVxuICAgICAgaSA9IG5leHQgICAgICBcbiAgICB9XG4gIH1cblxuICAvL0J1YmJsZXMgZWxlbWVudCBpIHVwIHRoZSBoZWFwXG4gIGZ1bmN0aW9uIGhlYXBVcChpKSB7XG4gICAgdmFyIHcgPSBoZWFwV2VpZ2h0KGkpXG4gICAgd2hpbGUoaSA+IDApIHtcbiAgICAgIHZhciBwYXJlbnQgPSBoZWFwUGFyZW50KGkpXG4gICAgICBpZihwYXJlbnQgPj0gMCkge1xuICAgICAgICB2YXIgcHcgPSBoZWFwV2VpZ2h0KHBhcmVudClcbiAgICAgICAgaWYodyA8IHB3KSB7XG4gICAgICAgICAgaGVhcFN3YXAoaSwgcGFyZW50KVxuICAgICAgICAgIGkgPSBwYXJlbnRcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gaVxuICAgIH1cbiAgfVxuXG4gIC8vUG9wIG1pbmltdW0gZWxlbWVudFxuICBmdW5jdGlvbiBoZWFwUG9wKCkge1xuICAgIGlmKGhlYXBDb3VudCA+IDApIHtcbiAgICAgIHZhciBoZWFkID0gaGVhcFswXVxuICAgICAgaGVhcFN3YXAoMCwgaGVhcENvdW50LTEpXG4gICAgICBoZWFwQ291bnQgLT0gMVxuICAgICAgaGVhcERvd24oMClcbiAgICAgIHJldHVybiBoZWFkXG4gICAgfVxuICAgIHJldHVybiAtMVxuICB9XG5cbiAgLy9VcGRhdGUgaGVhcCBpdGVtIGlcbiAgZnVuY3Rpb24gaGVhcFVwZGF0ZShpLCB3KSB7XG4gICAgdmFyIGEgPSBoZWFwW2ldXG4gICAgaWYod2VpZ2h0c1thXSA9PT0gdykge1xuICAgICAgcmV0dXJuIGlcbiAgICB9XG4gICAgd2VpZ2h0c1thXSA9IC1JbmZpbml0eVxuICAgIGhlYXBVcChpKVxuICAgIGhlYXBQb3AoKVxuICAgIHdlaWdodHNbYV0gPSB3XG4gICAgaGVhcENvdW50ICs9IDFcbiAgICByZXR1cm4gaGVhcFVwKGhlYXBDb3VudC0xKVxuICB9XG5cbiAgLy9LaWxscyBhIHZlcnRleCAoYXNzdW1lIHZlcnRleCBhbHJlYWR5IHJlbW92ZWQgZnJvbSBoZWFwKVxuICBmdW5jdGlvbiBraWxsKGkpIHtcbiAgICBpZihkZWFkW2ldKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgLy9LaWxsIHZlcnRleFxuICAgIGRlYWRbaV0gPSB0cnVlXG4gICAgLy9GaXh1cCB0b3BvbG9neVxuICAgIHZhciBzID0gaW52W2ldXG4gICAgdmFyIHQgPSBvdXR2W2ldXG4gICAgaWYoaW52W3RdID49IDApIHtcbiAgICAgIGludlt0XSA9IHNcbiAgICB9XG4gICAgaWYob3V0dltzXSA+PSAwKSB7XG4gICAgICBvdXR2W3NdID0gdFxuICAgIH1cblxuICAgIC8vVXBkYXRlIHdlaWdodHMgb24gcyBhbmQgdFxuICAgIGlmKGluZGV4W3NdID49IDApIHtcbiAgICAgIGhlYXBVcGRhdGUoaW5kZXhbc10sIGNvbXB1dGVXZWlnaHQocykpXG4gICAgfVxuICAgIGlmKGluZGV4W3RdID49IDApIHtcbiAgICAgIGhlYXBVcGRhdGUoaW5kZXhbdF0sIGNvbXB1dGVXZWlnaHQodCkpXG4gICAgfVxuICB9XG5cbiAgLy9Jbml0aWFsaXplIHdlaWdodHMgYW5kIGhlYXBcbiAgdmFyIGhlYXAgPSBbXVxuICB2YXIgaW5kZXggPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgdmFyIHcgPSB3ZWlnaHRzW2ldID0gY29tcHV0ZVdlaWdodChpKVxuICAgIGlmKHcgPCBJbmZpbml0eSkge1xuICAgICAgaW5kZXhbaV0gPSBoZWFwLmxlbmd0aFxuICAgICAgaGVhcC5wdXNoKGkpXG4gICAgfSBlbHNlIHtcbiAgICAgIGluZGV4W2ldID0gLTFcbiAgICB9XG4gIH1cbiAgdmFyIGhlYXBDb3VudCA9IGhlYXAubGVuZ3RoXG4gIGZvcih2YXIgaT1oZWFwQ291bnQ+PjE7IGk+PTA7IC0taSkge1xuICAgIGhlYXBEb3duKGkpXG4gIH1cbiAgXG4gIC8vS2lsbCB2ZXJ0aWNlc1xuICB3aGlsZSh0cnVlKSB7XG4gICAgdmFyIGhtaW4gPSBoZWFwUG9wKClcbiAgICBpZigoaG1pbiA8IDApIHx8ICh3ZWlnaHRzW2htaW5dID4gbWluQXJlYSkpIHtcbiAgICAgIGJyZWFrXG4gICAgfVxuICAgIGtpbGwoaG1pbilcbiAgfVxuXG4gIC8vQnVpbGQgY29sbGFwc2VkIHZlcnRleCB0YWJsZVxuICB2YXIgbnBvc2l0aW9ucyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIGlmKCFkZWFkW2ldKSB7XG4gICAgICBpbmRleFtpXSA9IG5wb3NpdGlvbnMubGVuZ3RoXG4gICAgICBucG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2ldLnNsaWNlKCkpXG4gICAgfVxuICB9XG4gIHZhciBudiA9IG5wb3NpdGlvbnMubGVuZ3RoXG5cbiAgZnVuY3Rpb24gdG9ydG9pc2VIYXJlKHNlcSwgc3RhcnQpIHtcbiAgICBpZihzZXFbc3RhcnRdIDwgMCkge1xuICAgICAgcmV0dXJuIHN0YXJ0XG4gICAgfVxuICAgIHZhciB0ID0gc3RhcnRcbiAgICB2YXIgaCA9IHN0YXJ0XG4gICAgZG8ge1xuICAgICAgLy9XYWxrIHR3byBzdGVwcyB3aXRoIGhcbiAgICAgIHZhciBuaCA9IHNlcVtoXVxuICAgICAgaWYoIWRlYWRbaF0gfHwgbmggPCAwIHx8IG5oID09PSBoKSB7XG4gICAgICAgIGJyZWFrXG4gICAgICB9XG4gICAgICBoID0gbmhcbiAgICAgIG5oID0gc2VxW2hdXG4gICAgICBpZighZGVhZFtoXSB8fCBuaCA8IDAgfHwgbmggPT09IGgpIHtcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICAgIGggPSBuaFxuXG4gICAgICAvL1dhbGsgb25lIHN0ZXAgd2l0aCB0XG4gICAgICB0ID0gc2VxW3RdXG4gICAgfSB3aGlsZSh0ICE9PSBoKVxuICAgIC8vQ29tcHJlc3MgY3ljbGVzXG4gICAgZm9yKHZhciB2PXN0YXJ0OyB2IT09aDsgdiA9IHNlcVt2XSkge1xuICAgICAgc2VxW3ZdID0gaFxuICAgIH1cbiAgICByZXR1cm4gaFxuICB9XG5cbiAgdmFyIG5jZWxscyA9IFtdXG4gIGNlbGxzLmZvckVhY2goZnVuY3Rpb24oYykge1xuICAgIHZhciB0aW4gPSB0b3J0b2lzZUhhcmUoaW52LCBjWzBdKVxuICAgIHZhciB0b3V0ID0gdG9ydG9pc2VIYXJlKG91dHYsIGNbMV0pXG4gICAgaWYodGluID49IDAgJiYgdG91dCA+PSAwICYmIHRpbiAhPT0gdG91dCkge1xuICAgICAgdmFyIGNpbiA9IGluZGV4W3Rpbl1cbiAgICAgIHZhciBjb3V0ID0gaW5kZXhbdG91dF1cbiAgICAgIGlmKGNpbiAhPT0gY291dCkge1xuICAgICAgICBuY2VsbHMucHVzaChbIGNpbiwgY291dCBdKVxuICAgICAgfVxuICAgIH1cbiAgfSlcblxuICAvL05vcm1hbGl6ZSByZXN1bHRcbiAgc2MudW5pcXVlKHNjLm5vcm1hbGl6ZShuY2VsbHMpKVxuXG4gIC8vUmV0dXJuIGZpbmFsIGxpc3Qgb2YgY2VsbHNcbiAgcmV0dXJuIHtcbiAgICBwb3NpdGlvbnM6IG5wb3NpdGlvbnMsXG4gICAgZWRnZXM6IG5jZWxsc1xuICB9XG59XG59LHtcInJvYnVzdC1vcmllbnRhdGlvblwiOjUxMCxcInNpbXBsaWNpYWwtY29tcGxleFwiOjUyMn1dLDUyNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IG9yZGVyU2VnbWVudHNcblxudmFyIG9yaWVudCA9IF9kZXJlcV8oXCJyb2J1c3Qtb3JpZW50YXRpb25cIilcblxuZnVuY3Rpb24gaG9yaXpvbnRhbE9yZGVyKGEsIGIpIHtcbiAgdmFyIGJsLCBiclxuICBpZihiWzBdWzBdIDwgYlsxXVswXSkge1xuICAgIGJsID0gYlswXVxuICAgIGJyID0gYlsxXVxuICB9IGVsc2UgaWYoYlswXVswXSA+IGJbMV1bMF0pIHtcbiAgICBibCA9IGJbMV1cbiAgICBiciA9IGJbMF1cbiAgfSBlbHNlIHtcbiAgICB2YXIgYWxvID0gTWF0aC5taW4oYVswXVsxXSwgYVsxXVsxXSlcbiAgICB2YXIgYWhpID0gTWF0aC5tYXgoYVswXVsxXSwgYVsxXVsxXSlcbiAgICB2YXIgYmxvID0gTWF0aC5taW4oYlswXVsxXSwgYlsxXVsxXSlcbiAgICB2YXIgYmhpID0gTWF0aC5tYXgoYlswXVsxXSwgYlsxXVsxXSlcbiAgICBpZihhaGkgPCBibG8pIHtcbiAgICAgIHJldHVybiBhaGkgLSBibG9cbiAgICB9XG4gICAgaWYoYWxvID4gYmhpKSB7XG4gICAgICByZXR1cm4gYWxvIC0gYmhpXG4gICAgfVxuICAgIHJldHVybiBhaGkgLSBiaGlcbiAgfVxuICB2YXIgYWwsIGFyXG4gIGlmKGFbMF1bMV0gPCBhWzFdWzFdKSB7XG4gICAgYWwgPSBhWzBdXG4gICAgYXIgPSBhWzFdXG4gIH0gZWxzZSB7XG4gICAgYWwgPSBhWzFdXG4gICAgYXIgPSBhWzBdXG4gIH1cbiAgdmFyIGQgPSBvcmllbnQoYnIsIGJsLCBhbClcbiAgaWYoZCkge1xuICAgIHJldHVybiBkXG4gIH1cbiAgZCA9IG9yaWVudChiciwgYmwsIGFyKVxuICBpZihkKSB7XG4gICAgcmV0dXJuIGRcbiAgfVxuICByZXR1cm4gYXIgLSBiclxufVxuXG5mdW5jdGlvbiBvcmRlclNlZ21lbnRzKGIsIGEpIHtcbiAgdmFyIGFsLCBhclxuICBpZihhWzBdWzBdIDwgYVsxXVswXSkge1xuICAgIGFsID0gYVswXVxuICAgIGFyID0gYVsxXVxuICB9IGVsc2UgaWYoYVswXVswXSA+IGFbMV1bMF0pIHtcbiAgICBhbCA9IGFbMV1cbiAgICBhciA9IGFbMF1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gaG9yaXpvbnRhbE9yZGVyKGEsIGIpXG4gIH1cbiAgdmFyIGJsLCBiclxuICBpZihiWzBdWzBdIDwgYlsxXVswXSkge1xuICAgIGJsID0gYlswXVxuICAgIGJyID0gYlsxXVxuICB9IGVsc2UgaWYoYlswXVswXSA+IGJbMV1bMF0pIHtcbiAgICBibCA9IGJbMV1cbiAgICBiciA9IGJbMF1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gLWhvcml6b250YWxPcmRlcihiLCBhKVxuICB9XG4gIHZhciBkMSA9IG9yaWVudChhbCwgYXIsIGJyKVxuICB2YXIgZDIgPSBvcmllbnQoYWwsIGFyLCBibClcbiAgaWYoZDEgPCAwKSB7XG4gICAgaWYoZDIgPD0gMCkge1xuICAgICAgcmV0dXJuIGQxXG4gICAgfVxuICB9IGVsc2UgaWYoZDEgPiAwKSB7XG4gICAgaWYoZDIgPj0gMCkge1xuICAgICAgcmV0dXJuIGQxXG4gICAgfVxuICB9IGVsc2UgaWYoZDIpIHtcbiAgICByZXR1cm4gZDJcbiAgfVxuICBkMSA9IG9yaWVudChiciwgYmwsIGFyKVxuICBkMiA9IG9yaWVudChiciwgYmwsIGFsKVxuICBpZihkMSA8IDApIHtcbiAgICBpZihkMiA8PSAwKSB7XG4gICAgICByZXR1cm4gZDFcbiAgICB9XG4gIH0gZWxzZSBpZihkMSA+IDApIHtcbiAgICBpZihkMiA+PSAwKSB7XG4gICAgICByZXR1cm4gZDFcbiAgICB9XG4gIH0gZWxzZSBpZihkMikge1xuICAgIHJldHVybiBkMlxuICB9XG4gIHJldHVybiBhclswXSAtIGJyWzBdXG59XG59LHtcInJvYnVzdC1vcmllbnRhdGlvblwiOjUxMH1dLDUyNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVNsYWJEZWNvbXBvc2l0aW9uXG5cbnZhciBib3VuZHMgPSBfZGVyZXFfKFwiYmluYXJ5LXNlYXJjaC1ib3VuZHNcIilcbnZhciBjcmVhdGVSQlRyZWUgPSBfZGVyZXFfKFwiZnVuY3Rpb25hbC1yZWQtYmxhY2stdHJlZVwiKVxudmFyIG9yaWVudCA9IF9kZXJlcV8oXCJyb2J1c3Qtb3JpZW50YXRpb25cIilcbnZhciBvcmRlclNlZ21lbnRzID0gX2RlcmVxXyhcIi4vbGliL29yZGVyLXNlZ21lbnRzXCIpXG5cbmZ1bmN0aW9uIFNsYWJEZWNvbXBvc2l0aW9uKHNsYWJzLCBjb29yZGluYXRlcywgaG9yaXpvbnRhbCkge1xuICB0aGlzLnNsYWJzID0gc2xhYnNcbiAgdGhpcy5jb29yZGluYXRlcyA9IGNvb3JkaW5hdGVzXG4gIHRoaXMuaG9yaXpvbnRhbCA9IGhvcml6b250YWxcbn1cblxudmFyIHByb3RvID0gU2xhYkRlY29tcG9zaXRpb24ucHJvdG90eXBlXG5cbmZ1bmN0aW9uIGNvbXBhcmVIb3Jpem9udGFsKGUsIHkpIHtcbiAgcmV0dXJuIGUueSAtIHlcbn1cblxuZnVuY3Rpb24gc2VhcmNoQnVja2V0KHJvb3QsIHApIHtcbiAgdmFyIGxhc3ROb2RlID0gbnVsbFxuICB3aGlsZShyb290KSB7XG4gICAgdmFyIHNlZyA9IHJvb3Qua2V5XG4gICAgdmFyIGwsIHJcbiAgICBpZihzZWdbMF1bMF0gPCBzZWdbMV1bMF0pIHtcbiAgICAgIGwgPSBzZWdbMF1cbiAgICAgIHIgPSBzZWdbMV1cbiAgICB9IGVsc2Uge1xuICAgICAgbCA9IHNlZ1sxXVxuICAgICAgciA9IHNlZ1swXVxuICAgIH1cbiAgICB2YXIgbyA9IG9yaWVudChsLCByLCBwKVxuICAgIGlmKG8gPCAwKSB7XG4gICAgICByb290ID0gcm9vdC5sZWZ0XG4gICAgfSBlbHNlIGlmKG8gPiAwKSB7XG4gICAgICBpZihwWzBdICE9PSBzZWdbMV1bMF0pIHtcbiAgICAgICAgbGFzdE5vZGUgPSByb290XG4gICAgICAgIHJvb3QgPSByb290LnJpZ2h0XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgdmFsID0gc2VhcmNoQnVja2V0KHJvb3QucmlnaHQsIHApXG4gICAgICAgIGlmKHZhbCkge1xuICAgICAgICAgIHJldHVybiB2YWxcbiAgICAgICAgfVxuICAgICAgICByb290ID0gcm9vdC5sZWZ0XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmKHBbMF0gIT09IHNlZ1sxXVswXSkge1xuICAgICAgICByZXR1cm4gcm9vdFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHZhbCA9IHNlYXJjaEJ1Y2tldChyb290LnJpZ2h0LCBwKVxuICAgICAgICBpZih2YWwpIHtcbiAgICAgICAgICByZXR1cm4gdmFsXG4gICAgICAgIH1cbiAgICAgICAgcm9vdCA9IHJvb3QubGVmdFxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gbGFzdE5vZGVcbn1cblxucHJvdG8uY2FzdFVwID0gZnVuY3Rpb24ocCkge1xuICB2YXIgYnVja2V0ID0gYm91bmRzLmxlKHRoaXMuY29vcmRpbmF0ZXMsIHBbMF0pXG4gIGlmKGJ1Y2tldCA8IDApIHtcbiAgICByZXR1cm4gLTFcbiAgfVxuICB2YXIgcm9vdCA9IHRoaXMuc2xhYnNbYnVja2V0XVxuICB2YXIgaGl0Tm9kZSA9IHNlYXJjaEJ1Y2tldCh0aGlzLnNsYWJzW2J1Y2tldF0sIHApXG4gIHZhciBsYXN0SGl0ID0gLTFcbiAgaWYoaGl0Tm9kZSkge1xuICAgIGxhc3RIaXQgPSBoaXROb2RlLnZhbHVlXG4gIH1cbiAgLy9FZGdlIGNhc2U6IG5lZWQgdG8gaGFuZGxlIGhvcml6b250YWwgc2VnbWVudHMgKHN1Y2tzKVxuICBpZih0aGlzLmNvb3JkaW5hdGVzW2J1Y2tldF0gPT09IHBbMF0pIHtcbiAgICB2YXIgbGFzdFNlZ21lbnQgPSBudWxsXG4gICAgaWYoaGl0Tm9kZSkge1xuICAgICAgbGFzdFNlZ21lbnQgPSBoaXROb2RlLmtleVxuICAgIH1cbiAgICBpZihidWNrZXQgPiAwKSB7XG4gICAgICB2YXIgb3RoZXJIaXROb2RlID0gc2VhcmNoQnVja2V0KHRoaXMuc2xhYnNbYnVja2V0LTFdLCBwKVxuICAgICAgaWYob3RoZXJIaXROb2RlKSB7XG4gICAgICAgIGlmKGxhc3RTZWdtZW50KSB7XG4gICAgICAgICAgaWYob3JkZXJTZWdtZW50cyhvdGhlckhpdE5vZGUua2V5LCBsYXN0U2VnbWVudCkgPiAwKSB7XG4gICAgICAgICAgICBsYXN0U2VnbWVudCA9IG90aGVySGl0Tm9kZS5rZXlcbiAgICAgICAgICAgIGxhc3RIaXQgPSBvdGhlckhpdE5vZGUudmFsdWVcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbGFzdEhpdCA9IG90aGVySGl0Tm9kZS52YWx1ZVxuICAgICAgICAgIGxhc3RTZWdtZW50ID0gb3RoZXJIaXROb2RlLmtleVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHZhciBob3JpeiA9IHRoaXMuaG9yaXpvbnRhbFtidWNrZXRdXG4gICAgaWYoaG9yaXoubGVuZ3RoID4gMCkge1xuICAgICAgdmFyIGhidWNrZXQgPSBib3VuZHMuZ2UoaG9yaXosIHBbMV0sIGNvbXBhcmVIb3Jpem9udGFsKVxuICAgICAgaWYoaGJ1Y2tldCA8IGhvcml6Lmxlbmd0aCkge1xuICAgICAgICB2YXIgZSA9IGhvcml6W2hidWNrZXRdXG4gICAgICAgIGlmKHBbMV0gPT09IGUueSkge1xuICAgICAgICAgIGlmKGUuY2xvc2VkKSB7XG4gICAgICAgICAgICByZXR1cm4gZS5pbmRleFxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3aGlsZShoYnVja2V0IDwgaG9yaXoubGVuZ3RoLTEgJiYgaG9yaXpbaGJ1Y2tldCsxXS55ID09PSBwWzFdKSB7XG4gICAgICAgICAgICAgIGhidWNrZXQgPSBoYnVja2V0KzFcbiAgICAgICAgICAgICAgZSA9IGhvcml6W2hidWNrZXRdXG4gICAgICAgICAgICAgIGlmKGUuY2xvc2VkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGUuaW5kZXhcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoZS55ID09PSBwWzFdICYmICFlLnN0YXJ0KSB7XG4gICAgICAgICAgICAgIGhidWNrZXQgPSBoYnVja2V0KzFcbiAgICAgICAgICAgICAgaWYoaGJ1Y2tldCA+PSBob3Jpei5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGFzdEhpdFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGUgPSBob3JpeltoYnVja2V0XVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvL0NoZWNrIGlmIGUgaXMgYWJvdmUvYmVsb3cgbGFzdCBzZWdtZW50XG4gICAgICAgIGlmKGUuc3RhcnQpIHtcbiAgICAgICAgICBpZihsYXN0U2VnbWVudCkge1xuICAgICAgICAgICAgdmFyIG8gPSBvcmllbnQobGFzdFNlZ21lbnRbMF0sIGxhc3RTZWdtZW50WzFdLCBbcFswXSwgZS55XSlcbiAgICAgICAgICAgIGlmKGxhc3RTZWdtZW50WzBdWzBdID4gbGFzdFNlZ21lbnRbMV1bMF0pIHtcbiAgICAgICAgICAgICAgbyA9IC1vXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihvID4gMCkge1xuICAgICAgICAgICAgICBsYXN0SGl0ID0gZS5pbmRleFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsYXN0SGl0ID0gZS5pbmRleFxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKGUueSAhPT0gcFsxXSkge1xuICAgICAgICAgIGxhc3RIaXQgPSBlLmluZGV4XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGxhc3RIaXRcbn1cblxuZnVuY3Rpb24gSW50ZXJ2YWxTZWdtZW50KHksIGluZGV4LCBzdGFydCwgY2xvc2VkKSB7XG4gIHRoaXMueSA9IHlcbiAgdGhpcy5pbmRleCA9IGluZGV4XG4gIHRoaXMuc3RhcnQgPSBzdGFydFxuICB0aGlzLmNsb3NlZCA9IGNsb3NlZFxufVxuXG5mdW5jdGlvbiBFdmVudCh4LCBzZWdtZW50LCBjcmVhdGUsIGluZGV4KSB7XG4gIHRoaXMueCA9IHhcbiAgdGhpcy5zZWdtZW50ID0gc2VnbWVudFxuICB0aGlzLmNyZWF0ZSA9IGNyZWF0ZVxuICB0aGlzLmluZGV4ID0gaW5kZXhcbn1cblxuXG5mdW5jdGlvbiBjcmVhdGVTbGFiRGVjb21wb3NpdGlvbihzZWdtZW50cykge1xuICB2YXIgbnVtU2VnbWVudHMgPSBzZWdtZW50cy5sZW5ndGhcbiAgdmFyIG51bUV2ZW50cyA9IDIgKiBudW1TZWdtZW50c1xuICB2YXIgZXZlbnRzID0gbmV3IEFycmF5KG51bUV2ZW50cylcbiAgZm9yKHZhciBpPTA7IGk8bnVtU2VnbWVudHM7ICsraSkge1xuICAgIHZhciBzID0gc2VnbWVudHNbaV1cbiAgICB2YXIgZiA9IHNbMF1bMF0gPCBzWzFdWzBdXG4gICAgZXZlbnRzWzIqaV0gPSBuZXcgRXZlbnQoc1swXVswXSwgcywgZiwgaSlcbiAgICBldmVudHNbMippKzFdID0gbmV3IEV2ZW50KHNbMV1bMF0sIHMsICFmLCBpKVxuICB9XG4gIGV2ZW50cy5zb3J0KGZ1bmN0aW9uKGEsYikge1xuICAgIHZhciBkID0gYS54IC0gYi54XG4gICAgaWYoZCkge1xuICAgICAgcmV0dXJuIGRcbiAgICB9XG4gICAgZCA9IGEuY3JlYXRlIC0gYi5jcmVhdGVcbiAgICBpZihkKSB7XG4gICAgICByZXR1cm4gZFxuICAgIH1cbiAgICByZXR1cm4gTWF0aC5taW4oYS5zZWdtZW50WzBdWzFdLCBhLnNlZ21lbnRbMV1bMV0pIC0gTWF0aC5taW4oYi5zZWdtZW50WzBdWzFdLCBiLnNlZ21lbnRbMV1bMV0pXG4gIH0pXG4gIHZhciB0cmVlID0gY3JlYXRlUkJUcmVlKG9yZGVyU2VnbWVudHMpXG4gIHZhciBzbGFicyA9IFtdXG4gIHZhciBsaW5lcyA9IFtdXG4gIHZhciBob3Jpem9udGFsID0gW11cbiAgdmFyIGxhc3RYID0gLUluZmluaXR5XG4gIGZvcih2YXIgaT0wOyBpPG51bUV2ZW50czsgKSB7XG4gICAgdmFyIHggPSBldmVudHNbaV0ueFxuICAgIHZhciBob3JpeiA9IFtdXG4gICAgd2hpbGUoaSA8IG51bUV2ZW50cykge1xuICAgICAgdmFyIGUgPSBldmVudHNbaV1cbiAgICAgIGlmKGUueCAhPT0geCkge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgICAgaSArPSAxXG4gICAgICBpZihlLnNlZ21lbnRbMF1bMF0gPT09IGUueCAmJiBlLnNlZ21lbnRbMV1bMF0gPT09IGUueCkge1xuICAgICAgICBpZihlLmNyZWF0ZSkge1xuICAgICAgICAgIGlmKGUuc2VnbWVudFswXVsxXSA8IGUuc2VnbWVudFsxXVsxXSkge1xuICAgICAgICAgICAgaG9yaXoucHVzaChuZXcgSW50ZXJ2YWxTZWdtZW50KFxuICAgICAgICAgICAgICAgIGUuc2VnbWVudFswXVsxXSxcbiAgICAgICAgICAgICAgICBlLmluZGV4LFxuICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgdHJ1ZSkpXG4gICAgICAgICAgICBob3Jpei5wdXNoKG5ldyBJbnRlcnZhbFNlZ21lbnQoXG4gICAgICAgICAgICAgICAgZS5zZWdtZW50WzFdWzFdLFxuICAgICAgICAgICAgICAgIGUuaW5kZXgsXG4gICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICAgICAgZmFsc2UpKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBob3Jpei5wdXNoKG5ldyBJbnRlcnZhbFNlZ21lbnQoXG4gICAgICAgICAgICAgICAgZS5zZWdtZW50WzFdWzFdLFxuICAgICAgICAgICAgICAgIGUuaW5kZXgsXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICBmYWxzZSkpXG4gICAgICAgICAgICBob3Jpei5wdXNoKG5ldyBJbnRlcnZhbFNlZ21lbnQoXG4gICAgICAgICAgICAgICAgZS5zZWdtZW50WzBdWzFdLFxuICAgICAgICAgICAgICAgIGUuaW5kZXgsXG4gICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICAgICAgdHJ1ZSkpXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZihlLmNyZWF0ZSkge1xuICAgICAgICAgIHRyZWUgPSB0cmVlLmluc2VydChlLnNlZ21lbnQsIGUuaW5kZXgpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJlZSA9IHRyZWUucmVtb3ZlKGUuc2VnbWVudClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBzbGFicy5wdXNoKHRyZWUucm9vdClcbiAgICBsaW5lcy5wdXNoKHgpXG4gICAgaG9yaXpvbnRhbC5wdXNoKGhvcml6KVxuICB9XG4gIHJldHVybiBuZXcgU2xhYkRlY29tcG9zaXRpb24oc2xhYnMsIGxpbmVzLCBob3Jpem9udGFsKVxufVxufSx7XCIuL2xpYi9vcmRlci1zZWdtZW50c1wiOjUyNSxcImJpbmFyeS1zZWFyY2gtYm91bmRzXCI6OTEsXCJmdW5jdGlvbmFsLXJlZC1ibGFjay10cmVlXCI6MjMwLFwicm9idXN0LW9yaWVudGF0aW9uXCI6NTEwfV0sNTI3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbnZhciByb2J1c3REb3QgPSBfZGVyZXFfKFwicm9idXN0LWRvdC1wcm9kdWN0XCIpXG52YXIgcm9idXN0U3VtID0gX2RlcmVxXyhcInJvYnVzdC1zdW1cIilcblxubW9kdWxlLmV4cG9ydHMgPSBzcGxpdFBvbHlnb25cbm1vZHVsZS5leHBvcnRzLnBvc2l0aXZlID0gcG9zaXRpdmVcbm1vZHVsZS5leHBvcnRzLm5lZ2F0aXZlID0gbmVnYXRpdmVcblxuZnVuY3Rpb24gcGxhbmVUKHAsIHBsYW5lKSB7XG4gIHZhciByID0gcm9idXN0U3VtKHJvYnVzdERvdChwLCBwbGFuZSksIFtwbGFuZVtwbGFuZS5sZW5ndGgtMV1dKVxuICByZXR1cm4gcltyLmxlbmd0aC0xXVxufVxuXG5cbi8vQ2FuJ3QgZG8gdGhpcyBleGFjdGx5IGFuZCBlbWl0IGEgZmxvYXRpbmcgcG9pbnQgcmVzdWx0XG5mdW5jdGlvbiBsZXJwVyhhLCB3YSwgYiwgd2IpIHtcbiAgdmFyIGQgPSB3YiAtIHdhXG4gIHZhciB0ID0gLXdhIC8gZFxuICBpZih0IDwgMC4wKSB7XG4gICAgdCA9IDAuMFxuICB9IGVsc2UgaWYodCA+IDEuMCkge1xuICAgIHQgPSAxLjBcbiAgfVxuICB2YXIgdGkgPSAxLjAgLSB0XG4gIHZhciBuID0gYS5sZW5ndGhcbiAgdmFyIHIgPSBuZXcgQXJyYXkobilcbiAgZm9yKHZhciBpPTA7IGk8bjsgKytpKSB7XG4gICAgcltpXSA9IHQgKiBhW2ldICsgdGkgKiBiW2ldXG4gIH1cbiAgcmV0dXJuIHJcbn1cblxuZnVuY3Rpb24gc3BsaXRQb2x5Z29uKHBvaW50cywgcGxhbmUpIHtcbiAgdmFyIHBvcyA9IFtdXG4gIHZhciBuZWcgPSBbXVxuICB2YXIgYSA9IHBsYW5lVChwb2ludHNbcG9pbnRzLmxlbmd0aC0xXSwgcGxhbmUpXG4gIGZvcih2YXIgcz1wb2ludHNbcG9pbnRzLmxlbmd0aC0xXSwgdD1wb2ludHNbMF0sIGk9MDsgaTxwb2ludHMubGVuZ3RoOyArK2ksIHM9dCkge1xuICAgIHQgPSBwb2ludHNbaV1cbiAgICB2YXIgYiA9IHBsYW5lVCh0LCBwbGFuZSlcbiAgICBpZigoYSA8IDAgJiYgYiA+IDApIHx8IChhID4gMCAmJiBiIDwgMCkpIHtcbiAgICAgIHZhciBwID0gbGVycFcocywgYiwgdCwgYSlcbiAgICAgIHBvcy5wdXNoKHApXG4gICAgICBuZWcucHVzaChwLnNsaWNlKCkpXG4gICAgfVxuICAgIGlmKGIgPCAwKSB7XG4gICAgICBuZWcucHVzaCh0LnNsaWNlKCkpXG4gICAgfSBlbHNlIGlmKGIgPiAwKSB7XG4gICAgICBwb3MucHVzaCh0LnNsaWNlKCkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHBvcy5wdXNoKHQuc2xpY2UoKSlcbiAgICAgIG5lZy5wdXNoKHQuc2xpY2UoKSlcbiAgICB9XG4gICAgYSA9IGJcbiAgfVxuICByZXR1cm4geyBwb3NpdGl2ZTogcG9zLCBuZWdhdGl2ZTogbmVnIH1cbn1cblxuZnVuY3Rpb24gcG9zaXRpdmUocG9pbnRzLCBwbGFuZSkge1xuICB2YXIgcG9zID0gW11cbiAgdmFyIGEgPSBwbGFuZVQocG9pbnRzW3BvaW50cy5sZW5ndGgtMV0sIHBsYW5lKVxuICBmb3IodmFyIHM9cG9pbnRzW3BvaW50cy5sZW5ndGgtMV0sIHQ9cG9pbnRzWzBdLCBpPTA7IGk8cG9pbnRzLmxlbmd0aDsgKytpLCBzPXQpIHtcbiAgICB0ID0gcG9pbnRzW2ldXG4gICAgdmFyIGIgPSBwbGFuZVQodCwgcGxhbmUpXG4gICAgaWYoKGEgPCAwICYmIGIgPiAwKSB8fCAoYSA+IDAgJiYgYiA8IDApKSB7XG4gICAgICBwb3MucHVzaChsZXJwVyhzLCBiLCB0LCBhKSlcbiAgICB9XG4gICAgaWYoYiA+PSAwKSB7XG4gICAgICBwb3MucHVzaCh0LnNsaWNlKCkpXG4gICAgfVxuICAgIGEgPSBiXG4gIH1cbiAgcmV0dXJuIHBvc1xufVxuXG5mdW5jdGlvbiBuZWdhdGl2ZShwb2ludHMsIHBsYW5lKSB7XG4gIHZhciBuZWcgPSBbXVxuICB2YXIgYSA9IHBsYW5lVChwb2ludHNbcG9pbnRzLmxlbmd0aC0xXSwgcGxhbmUpXG4gIGZvcih2YXIgcz1wb2ludHNbcG9pbnRzLmxlbmd0aC0xXSwgdD1wb2ludHNbMF0sIGk9MDsgaTxwb2ludHMubGVuZ3RoOyArK2ksIHM9dCkge1xuICAgIHQgPSBwb2ludHNbaV1cbiAgICB2YXIgYiA9IHBsYW5lVCh0LCBwbGFuZSlcbiAgICBpZigoYSA8IDAgJiYgYiA+IDApIHx8IChhID4gMCAmJiBiIDwgMCkpIHtcbiAgICAgIG5lZy5wdXNoKGxlcnBXKHMsIGIsIHQsIGEpKVxuICAgIH1cbiAgICBpZihiIDw9IDApIHtcbiAgICAgIG5lZy5wdXNoKHQuc2xpY2UoKSlcbiAgICB9XG4gICAgYSA9IGJcbiAgfVxuICByZXR1cm4gbmVnXG59XG59LHtcInJvYnVzdC1kb3QtcHJvZHVjdFwiOjUwNyxcInJvYnVzdC1zdW1cIjo1MTV9XSw1Mjg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyogZ2xvYmFsIHdpbmRvdywgZXhwb3J0cywgZGVmaW5lICovXG5cbiFmdW5jdGlvbigpIHtcbiAgICAndXNlIHN0cmljdCdcblxuICAgIHZhciByZSA9IHtcbiAgICAgICAgbm90X3N0cmluZzogL1tec10vLFxuICAgICAgICBub3RfYm9vbDogL1tedF0vLFxuICAgICAgICBub3RfdHlwZTogL1teVF0vLFxuICAgICAgICBub3RfcHJpbWl0aXZlOiAvW152XS8sXG4gICAgICAgIG51bWJlcjogL1tkaWVmZ10vLFxuICAgICAgICBudW1lcmljX2FyZzogL1tiY2RpZWZndXhYXS8sXG4gICAgICAgIGpzb246IC9bal0vLFxuICAgICAgICBub3RfanNvbjogL1teal0vLFxuICAgICAgICB0ZXh0OiAvXlteXFx4MjVdKy8sXG4gICAgICAgIG1vZHVsbzogL15cXHgyNXsyfS8sXG4gICAgICAgIHBsYWNlaG9sZGVyOiAvXlxceDI1KD86KFsxLTldXFxkKilcXCR8XFwoKFteKV0rKVxcKSk/KFxcKyk/KDB8J1teJF0pPygtKT8oXFxkKyk/KD86XFwuKFxcZCspKT8oW2ItZ2lqb3N0VHV2eFhdKS8sXG4gICAgICAgIGtleTogL14oW2Etel9dW2Etel9cXGRdKikvaSxcbiAgICAgICAga2V5X2FjY2VzczogL15cXC4oW2Etel9dW2Etel9cXGRdKikvaSxcbiAgICAgICAgaW5kZXhfYWNjZXNzOiAvXlxcWyhcXGQrKVxcXS8sXG4gICAgICAgIHNpZ246IC9eWystXS9cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzcHJpbnRmKGtleSkge1xuICAgICAgICAvLyBgYXJndW1lbnRzYCBpcyBub3QgYW4gYXJyYXksIGJ1dCBzaG91bGQgYmUgZmluZSBmb3IgdGhpcyBjYWxsXG4gICAgICAgIHJldHVybiBzcHJpbnRmX2Zvcm1hdChzcHJpbnRmX3BhcnNlKGtleSksIGFyZ3VtZW50cylcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2c3ByaW50ZihmbXQsIGFyZ3YpIHtcbiAgICAgICAgcmV0dXJuIHNwcmludGYuYXBwbHkobnVsbCwgW2ZtdF0uY29uY2F0KGFyZ3YgfHwgW10pKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNwcmludGZfZm9ybWF0KHBhcnNlX3RyZWUsIGFyZ3YpIHtcbiAgICAgICAgdmFyIGN1cnNvciA9IDEsIHRyZWVfbGVuZ3RoID0gcGFyc2VfdHJlZS5sZW5ndGgsIGFyZywgb3V0cHV0ID0gJycsIGksIGssIHBoLCBwYWQsIHBhZF9jaGFyYWN0ZXIsIHBhZF9sZW5ndGgsIGlzX3Bvc2l0aXZlLCBzaWduXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0cmVlX2xlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHBhcnNlX3RyZWVbaV0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0ICs9IHBhcnNlX3RyZWVbaV1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBwYXJzZV90cmVlW2ldID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgIHBoID0gcGFyc2VfdHJlZVtpXSAvLyBjb252ZW5pZW5jZSBwdXJwb3NlcyBvbmx5XG4gICAgICAgICAgICAgICAgaWYgKHBoLmtleXMpIHsgLy8ga2V5d29yZCBhcmd1bWVudFxuICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmd2W2N1cnNvcl1cbiAgICAgICAgICAgICAgICAgICAgZm9yIChrID0gMDsgayA8IHBoLmtleXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmcgPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHNwcmludGYoJ1tzcHJpbnRmXSBDYW5ub3QgYWNjZXNzIHByb3BlcnR5IFwiJXNcIiBvZiB1bmRlZmluZWQgdmFsdWUgXCIlc1wiJywgcGgua2V5c1trXSwgcGgua2V5c1trLTFdKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IGFyZ1twaC5rZXlzW2tdXVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHBoLnBhcmFtX25vKSB7IC8vIHBvc2l0aW9uYWwgYXJndW1lbnQgKGV4cGxpY2l0KVxuICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmd2W3BoLnBhcmFtX25vXVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHsgLy8gcG9zaXRpb25hbCBhcmd1bWVudCAoaW1wbGljaXQpXG4gICAgICAgICAgICAgICAgICAgIGFyZyA9IGFyZ3ZbY3Vyc29yKytdXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHJlLm5vdF90eXBlLnRlc3QocGgudHlwZSkgJiYgcmUubm90X3ByaW1pdGl2ZS50ZXN0KHBoLnR5cGUpICYmIGFyZyBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGFyZyA9IGFyZygpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHJlLm51bWVyaWNfYXJnLnRlc3QocGgudHlwZSkgJiYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInICYmIGlzTmFOKGFyZykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3Ioc3ByaW50ZignW3NwcmludGZdIGV4cGVjdGluZyBudW1iZXIgYnV0IGZvdW5kICVUJywgYXJnKSlcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocmUubnVtYmVyLnRlc3QocGgudHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNfcG9zaXRpdmUgPSBhcmcgPj0gMFxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHN3aXRjaCAocGgudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdiJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IHBhcnNlSW50KGFyZywgMTApLnRvU3RyaW5nKDIpXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdjJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IFN0cmluZy5mcm9tQ2hhckNvZGUocGFyc2VJbnQoYXJnLCAxMCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnaSc6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBwYXJzZUludChhcmcsIDEwKVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnaic6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBKU09OLnN0cmluZ2lmeShhcmcsIG51bGwsIHBoLndpZHRoID8gcGFyc2VJbnQocGgud2lkdGgpIDogMClcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2UnOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gcGgucHJlY2lzaW9uID8gcGFyc2VGbG9hdChhcmcpLnRvRXhwb25lbnRpYWwocGgucHJlY2lzaW9uKSA6IHBhcnNlRmxvYXQoYXJnKS50b0V4cG9uZW50aWFsKClcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2YnOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gcGgucHJlY2lzaW9uID8gcGFyc2VGbG9hdChhcmcpLnRvRml4ZWQocGgucHJlY2lzaW9uKSA6IHBhcnNlRmxvYXQoYXJnKVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZyc6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBwaC5wcmVjaXNpb24gPyBTdHJpbmcoTnVtYmVyKGFyZy50b1ByZWNpc2lvbihwaC5wcmVjaXNpb24pKSkgOiBwYXJzZUZsb2F0KGFyZylcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ28nOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gKHBhcnNlSW50KGFyZywgMTApID4+PiAwKS50b1N0cmluZyg4KVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgPSBTdHJpbmcoYXJnKVxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gKHBoLnByZWNpc2lvbiA/IGFyZy5zdWJzdHJpbmcoMCwgcGgucHJlY2lzaW9uKSA6IGFyZylcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3QnOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gU3RyaW5nKCEhYXJnKVxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gKHBoLnByZWNpc2lvbiA/IGFyZy5zdWJzdHJpbmcoMCwgcGgucHJlY2lzaW9uKSA6IGFyZylcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ1QnOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGFyZykuc2xpY2UoOCwgLTEpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IChwaC5wcmVjaXNpb24gPyBhcmcuc3Vic3RyaW5nKDAsIHBoLnByZWNpc2lvbikgOiBhcmcpXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgICAgICBjYXNlICd1JzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IHBhcnNlSW50KGFyZywgMTApID4+PiAwXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgICAgICBjYXNlICd2JzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IGFyZy52YWx1ZU9mKClcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IChwaC5wcmVjaXNpb24gPyBhcmcuc3Vic3RyaW5nKDAsIHBoLnByZWNpc2lvbikgOiBhcmcpXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgICAgICBjYXNlICd4JzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IChwYXJzZUludChhcmcsIDEwKSA+Pj4gMCkudG9TdHJpbmcoMTYpXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdYJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZyA9IChwYXJzZUludChhcmcsIDEwKSA+Pj4gMCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChyZS5qc29uLnRlc3QocGgudHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICs9IGFyZ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlLm51bWJlci50ZXN0KHBoLnR5cGUpICYmICghaXNfcG9zaXRpdmUgfHwgcGguc2lnbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpZ24gPSBpc19wb3NpdGl2ZSA/ICcrJyA6ICctJ1xuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gYXJnLnRvU3RyaW5nKCkucmVwbGFjZShyZS5zaWduLCAnJylcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpZ24gPSAnJ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHBhZF9jaGFyYWN0ZXIgPSBwaC5wYWRfY2hhciA/IHBoLnBhZF9jaGFyID09PSAnMCcgPyAnMCcgOiBwaC5wYWRfY2hhci5jaGFyQXQoMSkgOiAnICdcbiAgICAgICAgICAgICAgICAgICAgcGFkX2xlbmd0aCA9IHBoLndpZHRoIC0gKHNpZ24gKyBhcmcpLmxlbmd0aFxuICAgICAgICAgICAgICAgICAgICBwYWQgPSBwaC53aWR0aCA/IChwYWRfbGVuZ3RoID4gMCA/IHBhZF9jaGFyYWN0ZXIucmVwZWF0KHBhZF9sZW5ndGgpIDogJycpIDogJydcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ICs9IHBoLmFsaWduID8gc2lnbiArIGFyZyArIHBhZCA6IChwYWRfY2hhcmFjdGVyID09PSAnMCcgPyBzaWduICsgcGFkICsgYXJnIDogcGFkICsgc2lnbiArIGFyZylcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dHB1dFxuICAgIH1cblxuICAgIHZhciBzcHJpbnRmX2NhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKVxuXG4gICAgZnVuY3Rpb24gc3ByaW50Zl9wYXJzZShmbXQpIHtcbiAgICAgICAgaWYgKHNwcmludGZfY2FjaGVbZm10XSkge1xuICAgICAgICAgICAgcmV0dXJuIHNwcmludGZfY2FjaGVbZm10XVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIF9mbXQgPSBmbXQsIG1hdGNoLCBwYXJzZV90cmVlID0gW10sIGFyZ19uYW1lcyA9IDBcbiAgICAgICAgd2hpbGUgKF9mbXQpIHtcbiAgICAgICAgICAgIGlmICgobWF0Y2ggPSByZS50ZXh0LmV4ZWMoX2ZtdCkpICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcGFyc2VfdHJlZS5wdXNoKG1hdGNoWzBdKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoKG1hdGNoID0gcmUubW9kdWxvLmV4ZWMoX2ZtdCkpICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcGFyc2VfdHJlZS5wdXNoKCclJylcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKChtYXRjaCA9IHJlLnBsYWNlaG9sZGVyLmV4ZWMoX2ZtdCkpICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoWzJdKSB7XG4gICAgICAgICAgICAgICAgICAgIGFyZ19uYW1lcyB8PSAxXG4gICAgICAgICAgICAgICAgICAgIHZhciBmaWVsZF9saXN0ID0gW10sIHJlcGxhY2VtZW50X2ZpZWxkID0gbWF0Y2hbMl0sIGZpZWxkX21hdGNoID0gW11cbiAgICAgICAgICAgICAgICAgICAgaWYgKChmaWVsZF9tYXRjaCA9IHJlLmtleS5leGVjKHJlcGxhY2VtZW50X2ZpZWxkKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkX2xpc3QucHVzaChmaWVsZF9tYXRjaFsxXSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlICgocmVwbGFjZW1lbnRfZmllbGQgPSByZXBsYWNlbWVudF9maWVsZC5zdWJzdHJpbmcoZmllbGRfbWF0Y2hbMF0ubGVuZ3RoKSkgIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKChmaWVsZF9tYXRjaCA9IHJlLmtleV9hY2Nlc3MuZXhlYyhyZXBsYWNlbWVudF9maWVsZCkpICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkX2xpc3QucHVzaChmaWVsZF9tYXRjaFsxXSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoKGZpZWxkX21hdGNoID0gcmUuaW5kZXhfYWNjZXNzLmV4ZWMocmVwbGFjZW1lbnRfZmllbGQpKSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZF9saXN0LnB1c2goZmllbGRfbWF0Y2hbMV0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1tzcHJpbnRmXSBmYWlsZWQgdG8gcGFyc2UgbmFtZWQgYXJndW1lbnQga2V5JylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1tzcHJpbnRmXSBmYWlsZWQgdG8gcGFyc2UgbmFtZWQgYXJndW1lbnQga2V5JylcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBtYXRjaFsyXSA9IGZpZWxkX2xpc3RcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFyZ19uYW1lcyB8PSAyXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChhcmdfbmFtZXMgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdbc3ByaW50Zl0gbWl4aW5nIHBvc2l0aW9uYWwgYW5kIG5hbWVkIHBsYWNlaG9sZGVycyBpcyBub3QgKHlldCkgc3VwcG9ydGVkJylcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwYXJzZV90cmVlLnB1c2goXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBtYXRjaFswXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtX25vOiAgICBtYXRjaFsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXM6ICAgICAgICBtYXRjaFsyXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpZ246ICAgICAgICBtYXRjaFszXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhZF9jaGFyOiAgICBtYXRjaFs0XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFsaWduOiAgICAgICBtYXRjaFs1XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiAgICAgICBtYXRjaFs2XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZWNpc2lvbjogICBtYXRjaFs3XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICAgICAgICBtYXRjaFs4XVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdbc3ByaW50Zl0gdW5leHBlY3RlZCBwbGFjZWhvbGRlcicpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfZm10ID0gX2ZtdC5zdWJzdHJpbmcobWF0Y2hbMF0ubGVuZ3RoKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzcHJpbnRmX2NhY2hlW2ZtdF0gPSBwYXJzZV90cmVlXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogZXhwb3J0IHRvIGVpdGhlciBicm93c2VyIG9yIG5vZGUuanNcbiAgICAgKi9cbiAgICAvKiBlc2xpbnQtZGlzYWJsZSBxdW90ZS1wcm9wcyAqL1xuICAgIGlmICh0eXBlb2YgZXhwb3J0cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgZXhwb3J0c1snc3ByaW50ZiddID0gc3ByaW50ZlxuICAgICAgICBleHBvcnRzWyd2c3ByaW50ZiddID0gdnNwcmludGZcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHdpbmRvd1snc3ByaW50ZiddID0gc3ByaW50ZlxuICAgICAgICB3aW5kb3dbJ3ZzcHJpbnRmJ10gPSB2c3ByaW50ZlxuXG4gICAgICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZVsnYW1kJ10pIHtcbiAgICAgICAgICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAnc3ByaW50Zic6IHNwcmludGYsXG4gICAgICAgICAgICAgICAgICAgICd2c3ByaW50Zic6IHZzcHJpbnRmXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKiBlc2xpbnQtZW5hYmxlIHF1b3RlLXByb3BzICovXG59KCk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcblxufSx7fV0sNTI5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIHBhcmVuID0gX2RlcmVxXygncGFyZW50aGVzaXMnKVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzcGxpdEJ5IChzdHJpbmcsIHNlcGFyYXRvciwgbykge1xyXG5cdGlmIChzdHJpbmcgPT0gbnVsbCkgdGhyb3cgRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IHNob3VsZCBiZSBhIHN0cmluZycpXHJcblx0aWYgKHNlcGFyYXRvciA9PSBudWxsKSB0aHJvdyBFcnJvcignU2VwYXJhdG9yIHNob3VsZCBiZSBhIHN0cmluZyBvciBhIFJlZ0V4cCcpXHJcblxyXG5cdGlmICghbykgbyA9IHt9XHJcblx0ZWxzZSBpZiAodHlwZW9mIG8gPT09ICdzdHJpbmcnIHx8IEFycmF5LmlzQXJyYXkobykpIHtcclxuXHRcdG8gPSB7aWdub3JlOiBvfVxyXG5cdH1cclxuXHJcblx0aWYgKG8uZXNjYXBlID09IG51bGwpIG8uZXNjYXBlID0gdHJ1ZVxyXG5cdGlmIChvLmlnbm9yZSA9PSBudWxsKSBvLmlnbm9yZSA9IFsnW10nLCAnKCknLCAne30nLCAnPD4nLCAnXCJcIicsIFwiJydcIiwgJ2BgJywgJ+KAnOKAnScsICfCq8K7J11cclxuXHRlbHNlIHtcclxuXHRcdGlmICh0eXBlb2Ygby5pZ25vcmUgPT09ICdzdHJpbmcnKSB7by5pZ25vcmUgPSBbby5pZ25vcmVdfVxyXG5cclxuXHRcdG8uaWdub3JlID0gby5pZ25vcmUubWFwKGZ1bmN0aW9uIChwYWlyKSB7XHJcblx0XHRcdC8vICdcIicg4oaSICdcIlwiJ1xyXG5cdFx0XHRpZiAocGFpci5sZW5ndGggPT09IDEpIHBhaXIgPSBwYWlyICsgcGFpclxyXG5cdFx0XHRyZXR1cm4gcGFpclxyXG5cdFx0fSlcclxuXHR9XHJcblxyXG5cdHZhciB0b2tlbnMgPSBwYXJlbi5wYXJzZShzdHJpbmcsIHtmbGF0OiB0cnVlLCBicmFja2V0czogby5pZ25vcmV9KVxyXG5cdHZhciBzdHIgPSB0b2tlbnNbMF1cclxuXHJcblx0dmFyIHBhcnRzID0gc3RyLnNwbGl0KHNlcGFyYXRvcilcclxuXHJcblx0Ly8gam9pbiBwYXJ0cyBzZXBhcmF0ZWQgYnkgZXNjYXBlXHJcblx0aWYgKG8uZXNjYXBlKSB7XHJcblx0XHR2YXIgY2xlYW5QYXJ0cyA9IFtdXHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdHZhciBwcmV2ID0gcGFydHNbaV1cclxuXHRcdFx0dmFyIHBhcnQgPSBwYXJ0c1tpICsgMV1cclxuXHJcblx0XHRcdGlmIChwcmV2W3ByZXYubGVuZ3RoIC0gMV0gPT09ICdcXFxcJyAmJiBwcmV2W3ByZXYubGVuZ3RoIC0gMl0gIT09ICdcXFxcJykge1xyXG5cdFx0XHRcdGNsZWFuUGFydHMucHVzaChwcmV2ICsgc2VwYXJhdG9yICsgcGFydClcclxuXHRcdFx0XHRpKytcclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRjbGVhblBhcnRzLnB1c2gocHJldilcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0cGFydHMgPSBjbGVhblBhcnRzXHJcblx0fVxyXG5cclxuXHQvLyBvcGVuIHBhcmVucyBwYWNrICYgYXBwbHkgdW5xdW90ZXMsIGlmIGFueVxyXG5cdGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcclxuXHRcdHRva2Vuc1swXSA9IHBhcnRzW2ldXHJcblx0XHRwYXJ0c1tpXSA9IHBhcmVuLnN0cmluZ2lmeSh0b2tlbnMsIHtmbGF0OiB0cnVlfSlcclxuXHR9XHJcblxyXG5cdHJldHVybiBwYXJ0c1xyXG59XHJcblxufSx7XCJwYXJlbnRoZXNpc1wiOjQ1OH1dLDUzMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IHN0cm9uZ2x5Q29ubmVjdGVkQ29tcG9uZW50c1xuXG5mdW5jdGlvbiBzdHJvbmdseUNvbm5lY3RlZENvbXBvbmVudHMoYWRqTGlzdCkge1xuICB2YXIgbnVtVmVydGljZXMgPSBhZGpMaXN0Lmxlbmd0aDtcbiAgdmFyIGluZGV4ID0gbmV3IEFycmF5KG51bVZlcnRpY2VzKVxuICB2YXIgbG93VmFsdWUgPSBuZXcgQXJyYXkobnVtVmVydGljZXMpXG4gIHZhciBhY3RpdmUgPSBuZXcgQXJyYXkobnVtVmVydGljZXMpXG4gIHZhciBjaGlsZCA9IG5ldyBBcnJheShudW1WZXJ0aWNlcylcbiAgdmFyIHNjYyA9IG5ldyBBcnJheShudW1WZXJ0aWNlcylcbiAgdmFyIHNjY0xpbmtzID0gbmV3IEFycmF5KG51bVZlcnRpY2VzKVxuICBcbiAgLy9Jbml0aWFsaXplIHRhYmxlc1xuICBmb3IodmFyIGk9MDsgaTxudW1WZXJ0aWNlczsgKytpKSB7XG4gICAgaW5kZXhbaV0gPSAtMVxuICAgIGxvd1ZhbHVlW2ldID0gMFxuICAgIGFjdGl2ZVtpXSA9IGZhbHNlXG4gICAgY2hpbGRbaV0gPSAwXG4gICAgc2NjW2ldID0gLTFcbiAgICBzY2NMaW5rc1tpXSA9IFtdXG4gIH1cblxuICAvLyBUaGUgc3Ryb25nQ29ubmVjdCBmdW5jdGlvblxuICB2YXIgY291bnQgPSAwXG4gIHZhciBjb21wb25lbnRzID0gW11cbiAgdmFyIHNjY0Fkakxpc3QgPSBbXVxuXG4gIGZ1bmN0aW9uIHN0cm9uZ0Nvbm5lY3Qodikge1xuICAgIC8vIFRvIGF2b2lkIHJ1bm5pbmcgb3V0IG9mIHN0YWNrIHNwYWNlLCB0aGlzIGVtdWxhdGVzIHRoZSByZWN1cnNpdmUgYmVoYXZpb3VyIG9mIHRoZSBub3JtYWwgYWxnb3JpdGhtLCBlZmZlY3RpdmVseSB1c2luZyBUIGFzIHRoZSBjYWxsIHN0YWNrLlxuICAgIHZhciBTID0gW3ZdLCBUID0gW3ZdXG4gICAgaW5kZXhbdl0gPSBsb3dWYWx1ZVt2XSA9IGNvdW50XG4gICAgYWN0aXZlW3ZdID0gdHJ1ZVxuICAgIGNvdW50ICs9IDFcbiAgICB3aGlsZShULmxlbmd0aCA+IDApIHtcbiAgICAgIHYgPSBUW1QubGVuZ3RoLTFdXG4gICAgICB2YXIgZSA9IGFkakxpc3Rbdl1cbiAgICAgIGlmIChjaGlsZFt2XSA8IGUubGVuZ3RoKSB7IC8vIElmIHdlJ3JlIG5vdCBkb25lIGl0ZXJhdGluZyBvdmVyIHRoZSBjaGlsZHJlbiwgZmlyc3QgdHJ5IGZpbmlzaGluZyB0aGF0LlxuICAgICAgICBmb3IodmFyIGk9Y2hpbGRbdl07IGk8ZS5sZW5ndGg7ICsraSkgeyAvLyBTdGFydCB3aGVyZSB3ZSBsZWZ0IG9mZi5cbiAgICAgICAgICB2YXIgdSA9IGVbaV1cbiAgICAgICAgICBpZihpbmRleFt1XSA8IDApIHtcbiAgICAgICAgICAgIGluZGV4W3VdID0gbG93VmFsdWVbdV0gPSBjb3VudFxuICAgICAgICAgICAgYWN0aXZlW3VdID0gdHJ1ZVxuICAgICAgICAgICAgY291bnQgKz0gMVxuICAgICAgICAgICAgUy5wdXNoKHUpXG4gICAgICAgICAgICBULnB1c2godSlcbiAgICAgICAgICAgIGJyZWFrIC8vIEZpcnN0IHJlY3Vyc2UsIHRoZW4gY29udGludWUgaGVyZSAod2l0aCB0aGUgc2FtZSBjaGlsZCEpLlxuICAgICAgICAgICAgLy8gVGhlcmUgaXMgYSBzbGlnaHQgY2hhbmdlIHRvIFRhcmphbidzIGFsZ29yaXRobSBoZXJlLlxuICAgICAgICAgICAgLy8gTm9ybWFsbHksIGFmdGVyIGhhdmluZyByZWN1cnNlZCwgd2Ugc2V0IGxvd1ZhbHVlIGxpa2Ugd2UgZG8gZm9yIGFuIGFjdGl2ZSBjaGlsZCAoYWx0aG91Z2ggc29tZSB2YXJpYW50cyBvZiB0aGUgYWxnb3JpdGhtIGRvIGl0IHNsaWdodGx5IGRpZmZlcmVudGx5KS5cbiAgICAgICAgICAgIC8vIEhlcmUsIHdlIG9ubHkgZG8gc28gaWYgdGhlIGNoaWxkIHdlIHJlY3Vyc2VkIG9uIGlzIHN0aWxsIGFjdGl2ZS5cbiAgICAgICAgICAgIC8vIFRoZSByZWFzb25pbmcgaXMgdGhhdCBpZiBpdCBpcyBubyBsb25nZXIgYWN0aXZlLCBpdCBtdXN0IGhhdmUgaGFkIGEgbG93VmFsdWUgZXF1YWwgdG8gaXRzIG93biBpbmRleCwgd2hpY2ggbWVhbnMgdGhhdCBpdCBpcyBuZWNlc3NhcmlseSBoaWdoZXIgdGhhbiBvdXIgbG93VmFsdWUuXG4gICAgICAgICAgfSBlbHNlIGlmIChhY3RpdmVbdV0pIHtcbiAgICAgICAgICAgIGxvd1ZhbHVlW3ZdID0gTWF0aC5taW4obG93VmFsdWVbdl0sIGxvd1ZhbHVlW3VdKXwwXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzY2NbdV0gPj0gMCkge1xuICAgICAgICAgICAgLy8gTm9kZSB2IGlzIG5vdCB5ZXQgYXNzaWduZWQgYW4gc2NjLCBidXQgb25jZSBpdCBpcyB0aGF0IHNjYyBjYW4gYXBwYXJlbnRseSByZWFjaCBzY2NbdV0uXG4gICAgICAgICAgICBzY2NMaW5rc1t2XS5wdXNoKHNjY1t1XSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2hpbGRbdl0gPSBpIC8vIFJlbWVtYmVyIHdoZXJlIHdlIGxlZnQgb2ZmLlxuICAgICAgfSBlbHNlIHsgLy8gSWYgd2UncmUgZG9uZSBpdGVyYXRpbmcgb3ZlciB0aGUgY2hpbGRyZW4sIGNoZWNrIHdoZXRoZXIgd2UgaGF2ZSBhbiBzY2MuXG4gICAgICAgIGlmKGxvd1ZhbHVlW3ZdID09PSBpbmRleFt2XSkgeyAvLyBUT0RPOiBJdCAvbWlnaHQvIGJlIHRydWUgdGhhdCBUIGlzIGFsd2F5cyBhIHByZWZpeCBvZiBTIChhdCB0aGlzIHBvaW50ISEhKSwgYW5kIGlmIHNvLCB0aGlzIGNvdWxkIGJlIHVzZWQgaGVyZS5cbiAgICAgICAgICB2YXIgY29tcG9uZW50ID0gW11cbiAgICAgICAgICB2YXIgbGlua3MgPSBbXSwgbGlua0NvdW50ID0gMFxuICAgICAgICAgIGZvcih2YXIgaT1TLmxlbmd0aC0xOyBpPj0wOyAtLWkpIHtcbiAgICAgICAgICAgIHZhciB3ID0gU1tpXVxuICAgICAgICAgICAgYWN0aXZlW3ddID0gZmFsc2VcbiAgICAgICAgICAgIGNvbXBvbmVudC5wdXNoKHcpXG4gICAgICAgICAgICBsaW5rcy5wdXNoKHNjY0xpbmtzW3ddKVxuICAgICAgICAgICAgbGlua0NvdW50ICs9IHNjY0xpbmtzW3ddLmxlbmd0aFxuICAgICAgICAgICAgc2NjW3ddID0gY29tcG9uZW50cy5sZW5ndGhcbiAgICAgICAgICAgIGlmKHcgPT09IHYpIHtcbiAgICAgICAgICAgICAgUy5sZW5ndGggPSBpXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbXBvbmVudHMucHVzaChjb21wb25lbnQpXG4gICAgICAgICAgdmFyIGFsbExpbmtzID0gbmV3IEFycmF5KGxpbmtDb3VudClcbiAgICAgICAgICBmb3IodmFyIGk9MDsgaTxsaW5rcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZm9yKHZhciBqPTA7IGo8bGlua3NbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgYWxsTGlua3NbLS1saW5rQ291bnRdID0gbGlua3NbaV1bal1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgc2NjQWRqTGlzdC5wdXNoKGFsbExpbmtzKVxuICAgICAgICB9XG4gICAgICAgIFQucG9wKCkgLy8gTm93IHdlJ3JlIGZpbmlzaGVkIGV4cGxvcmluZyB0aGlzIHBhcnRpY3VsYXIgbm9kZSAobm9ybWFsbHkgY29ycmVzcG9uZHMgdG8gdGhlIHJldHVybiBzdGF0ZW1lbnQpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9SdW4gc3Ryb25nIGNvbm5lY3Qgc3RhcnRpbmcgZnJvbSBlYWNoIHZlcnRleFxuICBmb3IodmFyIGk9MDsgaTxudW1WZXJ0aWNlczsgKytpKSB7XG4gICAgaWYoaW5kZXhbaV0gPCAwKSB7XG4gICAgICBzdHJvbmdDb25uZWN0KGkpXG4gICAgfVxuICB9XG4gIFxuICAvLyBDb21wYWN0IHNjY0Fkakxpc3RcbiAgdmFyIG5ld0VcbiAgZm9yKHZhciBpPTA7IGk8c2NjQWRqTGlzdC5sZW5ndGg7IGkrKykge1xuICAgIHZhciBlID0gc2NjQWRqTGlzdFtpXVxuICAgIGlmIChlLmxlbmd0aCA9PT0gMCkgY29udGludWVcbiAgICBlLnNvcnQoZnVuY3Rpb24gKGEsYikgeyByZXR1cm4gYS1iOyB9KVxuICAgIG5ld0UgPSBbZVswXV1cbiAgICBmb3IodmFyIGo9MTsgajxlLmxlbmd0aDsgaisrKSB7XG4gICAgICBpZiAoZVtqXSAhPT0gZVtqLTFdKSB7XG4gICAgICAgIG5ld0UucHVzaChlW2pdKVxuICAgICAgfVxuICAgIH1cbiAgICBzY2NBZGpMaXN0W2ldID0gbmV3RVxuICB9ICBcblxuICByZXR1cm4ge2NvbXBvbmVudHM6IGNvbXBvbmVudHMsIGFkamFjZW5jeUxpc3Q6IHNjY0Fkakxpc3R9XG59XG5cbn0se31dLDUzMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IHN1cmZhY2VOZXRzXG5cbnZhciBnZW5lcmF0ZUNvbnRvdXJFeHRyYWN0b3IgPSBfZGVyZXFfKFwibmRhcnJheS1leHRyYWN0LWNvbnRvdXJcIilcbnZhciB0cmlhbmd1bGF0ZUN1YmUgPSBfZGVyZXFfKFwidHJpYW5ndWxhdGUtaHlwZXJjdWJlXCIpXG52YXIgemVyb0Nyb3NzaW5ncyA9IF9kZXJlcV8oXCJ6ZXJvLWNyb3NzaW5nc1wiKVxuXG5mdW5jdGlvbiBidWlsZFN1cmZhY2VOZXRzKG9yZGVyLCBkdHlwZSkge1xuICB2YXIgZGltZW5zaW9uID0gb3JkZXIubGVuZ3RoXG4gIHZhciBjb2RlID0gW1wiJ3VzZSBzdHJpY3QnO1wiXVxuICB2YXIgZnVuY05hbWUgPSBcInN1cmZhY2VOZXRzXCIgKyBvcmRlci5qb2luKFwiX1wiKSArIFwiZFwiICsgZHR5cGVcblxuICAvL0NvbnRvdXIgZXh0cmFjdGlvbiBmdW5jdGlvblxuICBjb2RlLnB1c2goXG4gICAgXCJ2YXIgY29udG91cj1nZW5Db250b3VyKHtcIixcbiAgICAgIFwib3JkZXI6W1wiLCBvcmRlci5qb2luKCksIFwiXSxcIixcbiAgICAgIFwic2NhbGFyQXJndW1lbnRzOiAzLFwiLFxuICAgICAgXCJwaGFzZTpmdW5jdGlvbiBwaGFzZUZ1bmMocCxhLGIsYykgeyByZXR1cm4gKHAgPiBjKXwwIH0sXCIpXG4gIGlmKGR0eXBlID09PSBcImdlbmVyaWNcIikge1xuICAgIGNvZGUucHVzaChcImdldHRlcnM6WzBdLFwiKVxuICB9XG5cbiAgLy9HZW5lcmF0ZSB2ZXJ0ZXggZnVuY3Rpb25cbiAgdmFyIGN1YmVBcmdzID0gW11cbiAgdmFyIGV4dHJhQXJncyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPGRpbWVuc2lvbjsgKytpKSB7XG4gICAgY3ViZUFyZ3MucHVzaChcImRcIiArIGkpXG4gICAgZXh0cmFBcmdzLnB1c2goXCJkXCIgKyBpKVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPCgxPDxkaW1lbnNpb24pOyArK2kpIHtcbiAgICBjdWJlQXJncy5wdXNoKFwidlwiICsgaSlcbiAgICBleHRyYUFyZ3MucHVzaChcInZcIiArIGkpXG4gIH1cbiAgZm9yKHZhciBpPTA7IGk8KDE8PGRpbWVuc2lvbik7ICsraSkge1xuICAgIGN1YmVBcmdzLnB1c2goXCJwXCIgKyBpKVxuICAgIGV4dHJhQXJncy5wdXNoKFwicFwiICsgaSlcbiAgfVxuICBjdWJlQXJncy5wdXNoKFwiYVwiLCBcImJcIiwgXCJjXCIpXG4gIGV4dHJhQXJncy5wdXNoKFwiYVwiLCBcImNcIilcbiAgY29kZS5wdXNoKFwidmVydGV4OmZ1bmN0aW9uIHZlcnRleEZ1bmMoXCIsIGN1YmVBcmdzLmpvaW4oKSwgXCIpe1wiKVxuICAvL01hc2sgYXJncyB0b2dldGhlclxuICB2YXIgbWFza1N0ciA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPCgxPDxkaW1lbnNpb24pOyArK2kpIHtcbiAgICBtYXNrU3RyLnB1c2goXCIocFwiICsgaSArIFwiPDxcIiArIGkgKyBcIilcIilcbiAgfVxuICAvL0dlbmVyYXRlIHZhcmlhYmxlcyBhbmQgZ2lnYW50byBzd2l0Y2ggc3RhdGVtZW50XG4gIGNvZGUucHVzaChcInZhciBtPShcIiwgbWFza1N0ci5qb2luKFwiK1wiKSwgXCIpfDA7aWYobT09PTB8fG09PT1cIiwgKDE8PCgxPDxkaW1lbnNpb24pKS0xLCBcIil7cmV0dXJufVwiKVxuICB2YXIgZXh0cmFGdW5jcyA9IFtdXG4gIHZhciBjdXJyZW50RnVuYyA9IFtdXG4gIGlmKDE8PCgxPDxkaW1lbnNpb24pIDw9IDEyOCkge1xuICAgIGNvZGUucHVzaChcInN3aXRjaChtKXtcIilcbiAgICBjdXJyZW50RnVuYyA9IGNvZGVcbiAgfSBlbHNlIHtcbiAgICBjb2RlLnB1c2goXCJzd2l0Y2gobT4+Pjcpe1wiKVxuICB9XG4gIGZvcih2YXIgaT0wOyBpPDE8PCgxPDxkaW1lbnNpb24pOyArK2kpIHtcbiAgICBpZigxPDwoMTw8ZGltZW5zaW9uKSA+IDEyOCkge1xuICAgICAgaWYoKGklMTI4KT09PTApIHtcbiAgICAgICAgaWYoZXh0cmFGdW5jcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY3VycmVudEZ1bmMucHVzaChcIn19XCIpXG4gICAgICAgIH1cbiAgICAgICAgdmFyIGVmTmFtZSA9IFwidkV4dHJhXCIgKyBleHRyYUZ1bmNzLmxlbmd0aFxuICAgICAgICBjb2RlLnB1c2goXCJjYXNlIFwiLCAoaT4+PjcpLCBcIjpcIiwgZWZOYW1lLCBcIihtJjB4N2YsXCIsIGV4dHJhQXJncy5qb2luKCksIFwiKTticmVhaztcIilcbiAgICAgICAgY3VycmVudEZ1bmMgPSBbXG4gICAgICAgICAgXCJmdW5jdGlvbiBcIiwgZWZOYW1lLCBcIihtLFwiLCBleHRyYUFyZ3Muam9pbigpLCBcIil7c3dpdGNoKG0pe1wiXG4gICAgICAgIF1cbiAgICAgICAgZXh0cmFGdW5jcy5wdXNoKGN1cnJlbnRGdW5jKVxuICAgICAgfSAgXG4gICAgfVxuICAgIGN1cnJlbnRGdW5jLnB1c2goXCJjYXNlIFwiLCAoaSYweDdmKSwgXCI6XCIpXG4gICAgdmFyIGNyb3NzaW5ncyA9IG5ldyBBcnJheShkaW1lbnNpb24pXG4gICAgdmFyIGRlbm9tcyA9IG5ldyBBcnJheShkaW1lbnNpb24pXG4gICAgdmFyIGNyb3NzaW5nQ291bnQgPSBuZXcgQXJyYXkoZGltZW5zaW9uKVxuICAgIHZhciBiaWFzID0gbmV3IEFycmF5KGRpbWVuc2lvbilcbiAgICB2YXIgdG90YWxDcm9zc2luZ3MgPSAwXG4gICAgZm9yKHZhciBqPTA7IGo8ZGltZW5zaW9uOyArK2opIHtcbiAgICAgIGNyb3NzaW5nc1tqXSA9IFtdXG4gICAgICBkZW5vbXNbal0gPSBbXVxuICAgICAgY3Jvc3NpbmdDb3VudFtqXSA9IDBcbiAgICAgIGJpYXNbal0gPSAwXG4gICAgfVxuICAgIGZvcih2YXIgaj0wOyBqPCgxPDxkaW1lbnNpb24pOyArK2opIHtcbiAgICAgIGZvcih2YXIgaz0wOyBrPGRpbWVuc2lvbjsgKytrKSB7XG4gICAgICAgIHZhciB1ID0gaiBeICgxPDxrKVxuICAgICAgICBpZih1ID4gaikge1xuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgICAgaWYoIShpJigxPDx1KSkgIT09ICEoaSYoMTw8aikpKSB7XG4gICAgICAgICAgdmFyIHNpZ24gPSAxXG4gICAgICAgICAgaWYoaSYoMTw8dSkpIHtcbiAgICAgICAgICAgIGRlbm9tc1trXS5wdXNoKFwidlwiICsgdSArIFwiLXZcIiArIGopXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbm9tc1trXS5wdXNoKFwidlwiICsgaiArIFwiLXZcIiArIHUpXG4gICAgICAgICAgICBzaWduID0gLXNpZ25cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYoc2lnbiA8IDApIHtcbiAgICAgICAgICAgIGNyb3NzaW5nc1trXS5wdXNoKFwiLXZcIiArIGogKyBcIi12XCIgKyB1KVxuICAgICAgICAgICAgY3Jvc3NpbmdDb3VudFtrXSArPSAyXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNyb3NzaW5nc1trXS5wdXNoKFwidlwiICsgaiArIFwiK3ZcIiArIHUpXG4gICAgICAgICAgICBjcm9zc2luZ0NvdW50W2tdIC09IDIgICAgICAgICAgICBcbiAgICAgICAgICB9XG4gICAgICAgICAgdG90YWxDcm9zc2luZ3MgKz0gMVxuICAgICAgICAgIGZvcih2YXIgbD0wOyBsPGRpbWVuc2lvbjsgKytsKSB7XG4gICAgICAgICAgICBpZihsID09PSBrKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih1JigxPDxsKSkge1xuICAgICAgICAgICAgICBiaWFzW2xdICs9IDFcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGJpYXNbbF0gLT0gMVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICB2YXIgdmVydGV4U3RyID0gW11cbiAgICBmb3IodmFyIGs9MDsgazxkaW1lbnNpb247ICsraykge1xuICAgICAgaWYoY3Jvc3NpbmdzW2tdLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB2ZXJ0ZXhTdHIucHVzaChcImRcIiArIGsgKyBcIi0wLjVcIilcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBjU3RyID0gXCJcIlxuICAgICAgICBpZihjcm9zc2luZ0NvdW50W2tdIDwgMCkge1xuICAgICAgICAgIGNTdHIgPSBjcm9zc2luZ0NvdW50W2tdICsgXCIqY1wiXG4gICAgICAgIH0gZWxzZSBpZihjcm9zc2luZ0NvdW50W2tdID4gMCkge1xuICAgICAgICAgIGNTdHIgPSBcIitcIiArIGNyb3NzaW5nQ291bnRba10gKyBcIipjXCJcbiAgICAgICAgfVxuICAgICAgICB2YXIgd2VpZ2h0ID0gMC41ICogKGNyb3NzaW5nc1trXS5sZW5ndGggLyB0b3RhbENyb3NzaW5ncylcbiAgICAgICAgdmFyIHNoaWZ0ID0gMC41ICsgMC41ICogKGJpYXNba10gLyB0b3RhbENyb3NzaW5ncylcbiAgICAgICAgdmVydGV4U3RyLnB1c2goXCJkXCIgKyBrICsgXCItXCIgKyBzaGlmdCArIFwiLVwiICsgd2VpZ2h0ICsgXCIqKFwiICsgY3Jvc3NpbmdzW2tdLmpvaW4oXCIrXCIpICsgY1N0ciArIFwiKS8oXCIgKyBkZW5vbXNba10uam9pbihcIitcIikgKyBcIilcIilcbiAgICAgICAgXG4gICAgICB9XG4gICAgfVxuICAgIGN1cnJlbnRGdW5jLnB1c2goXCJhLnB1c2goW1wiLCB2ZXJ0ZXhTdHIuam9pbigpLCBcIl0pO1wiLFxuICAgICAgXCJicmVhaztcIilcbiAgfVxuICBjb2RlLnB1c2goXCJ9fSxcIilcbiAgaWYoZXh0cmFGdW5jcy5sZW5ndGggPiAwKSB7XG4gICAgY3VycmVudEZ1bmMucHVzaChcIn19XCIpXG4gIH1cblxuICAvL0NyZWF0ZSBmYWNlIGZ1bmN0aW9uXG4gIHZhciBmYWNlQXJncyA9IFtdXG4gIGZvcih2YXIgaT0wOyBpPCgxPDwoZGltZW5zaW9uLTEpKTsgKytpKSB7XG4gICAgZmFjZUFyZ3MucHVzaChcInZcIiArIGkpXG4gIH1cbiAgZmFjZUFyZ3MucHVzaChcImMwXCIsIFwiYzFcIiwgXCJwMFwiLCBcInAxXCIsIFwiYVwiLCBcImJcIiwgXCJjXCIpXG4gIGNvZGUucHVzaChcImNlbGw6ZnVuY3Rpb24gY2VsbEZ1bmMoXCIsIGZhY2VBcmdzLmpvaW4oKSwgXCIpe1wiKVxuXG4gIHZhciBmYWNldHMgPSB0cmlhbmd1bGF0ZUN1YmUoZGltZW5zaW9uLTEpXG4gIGNvZGUucHVzaChcImlmKHAwKXtiLnB1c2goXCIsXG4gICAgZmFjZXRzLm1hcChmdW5jdGlvbihmKSB7XG4gICAgICByZXR1cm4gXCJbXCIgKyBmLm1hcChmdW5jdGlvbih2KSB7XG4gICAgICAgIHJldHVybiBcInZcIiArIHZcbiAgICAgIH0pICsgXCJdXCJcbiAgICB9KS5qb2luKCksIFwiKX1lbHNle2IucHVzaChcIixcbiAgICBmYWNldHMubWFwKGZ1bmN0aW9uKGYpIHtcbiAgICAgIHZhciBlID0gZi5zbGljZSgpXG4gICAgICBlLnJldmVyc2UoKVxuICAgICAgcmV0dXJuIFwiW1wiICsgZS5tYXAoZnVuY3Rpb24odikge1xuICAgICAgICByZXR1cm4gXCJ2XCIgKyB2XG4gICAgICB9KSArIFwiXVwiXG4gICAgfSkuam9pbigpLFxuICAgIFwiKX19fSk7ZnVuY3Rpb24gXCIsIGZ1bmNOYW1lLCBcIihhcnJheSxsZXZlbCl7dmFyIHZlcnRzPVtdLGNlbGxzPVtdO2NvbnRvdXIoYXJyYXksdmVydHMsY2VsbHMsbGV2ZWwpO3JldHVybiB7cG9zaXRpb25zOnZlcnRzLGNlbGxzOmNlbGxzfTt9IHJldHVybiBcIiwgZnVuY05hbWUsIFwiO1wiKVxuXG4gIGZvcih2YXIgaT0wOyBpPGV4dHJhRnVuY3MubGVuZ3RoOyArK2kpIHtcbiAgICBjb2RlLnB1c2goZXh0cmFGdW5jc1tpXS5qb2luKFwiXCIpKVxuICB9XG5cbiAgLy9Db21waWxlIGFuZCBsaW5rXG4gIHZhciBwcm9jID0gbmV3IEZ1bmN0aW9uKFwiZ2VuQ29udG91clwiLCBjb2RlLmpvaW4oXCJcIikpXG4gIHJldHVybiBwcm9jKGdlbmVyYXRlQ29udG91ckV4dHJhY3Rvcilcbn1cblxuLy8xRCBjYXNlOiBOZWVkIHRvIGhhbmRsZSBzcGVjaWFsbHlcbmZ1bmN0aW9uIG1lc2gxRChhcnJheSwgbGV2ZWwpIHtcbiAgdmFyIHpjID0gemVyb0Nyb3NzaW5ncyhhcnJheSwgbGV2ZWwpXG4gIHZhciBuID0gemMubGVuZ3RoXG4gIHZhciBucG9zID0gbmV3IEFycmF5KG4pXG4gIHZhciBuY2VsID0gbmV3IEFycmF5KG4pXG4gIGZvcih2YXIgaT0wOyBpPG47ICsraSkge1xuICAgIG5wb3NbaV0gPSBbIHpjW2ldIF1cbiAgICBuY2VsW2ldID0gWyBpIF1cbiAgfVxuICByZXR1cm4ge1xuICAgIHBvc2l0aW9uczogbnBvcyxcbiAgICBjZWxsczogbmNlbFxuICB9XG59XG5cbnZhciBDQUNIRSA9IHt9XG5cbmZ1bmN0aW9uIHN1cmZhY2VOZXRzKGFycmF5LGxldmVsKSB7XG4gIGlmKGFycmF5LmRpbWVuc2lvbiA8PSAwKSB7XG4gICAgcmV0dXJuIHsgcG9zaXRpb25zOiBbXSwgY2VsbHM6IFtdIH1cbiAgfSBlbHNlIGlmKGFycmF5LmRpbWVuc2lvbiA9PT0gMSkge1xuICAgIHJldHVybiBtZXNoMUQoYXJyYXksIGxldmVsKVxuICB9XG4gIHZhciB0eXBlc2lnID0gYXJyYXkub3JkZXIuam9pbigpICsgXCItXCIgKyBhcnJheS5kdHlwZVxuICB2YXIgcHJvYyA9IENBQ0hFW3R5cGVzaWddXG4gIHZhciBsZXZlbCA9ICgrbGV2ZWwpIHx8IDAuMFxuICBpZighcHJvYykge1xuICAgIHByb2MgPSBDQUNIRVt0eXBlc2lnXSA9IGJ1aWxkU3VyZmFjZU5ldHMoYXJyYXkub3JkZXIsIGFycmF5LmR0eXBlKVxuICB9XG4gIHJldHVybiBwcm9jKGFycmF5LGxldmVsKVxufVxufSx7XCJuZGFycmF5LWV4dHJhY3QtY29udG91clwiOjQzOSxcInRyaWFuZ3VsYXRlLWh5cGVyY3ViZVwiOjU0MSxcInplcm8tY3Jvc3NpbmdzXCI6NTc0fV0sNTMyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuXG52YXIgX3NsaWNlZFRvQXJyYXkgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIHNsaWNlSXRlcmF0b3IoYXJyLCBpKSB7IHZhciBfYXJyID0gW107IHZhciBfbiA9IHRydWU7IHZhciBfZCA9IGZhbHNlOyB2YXIgX2UgPSB1bmRlZmluZWQ7IHRyeSB7IGZvciAodmFyIF9pID0gYXJyW1N5bWJvbC5pdGVyYXRvcl0oKSwgX3M7ICEoX24gPSAoX3MgPSBfaS5uZXh0KCkpLmRvbmUpOyBfbiA9IHRydWUpIHsgX2Fyci5wdXNoKF9zLnZhbHVlKTsgaWYgKGkgJiYgX2Fyci5sZW5ndGggPT09IGkpIGJyZWFrOyB9IH0gY2F0Y2ggKGVycikgeyBfZCA9IHRydWU7IF9lID0gZXJyOyB9IGZpbmFsbHkgeyB0cnkgeyBpZiAoIV9uICYmIF9pW1wicmV0dXJuXCJdKSBfaVtcInJldHVyblwiXSgpOyB9IGZpbmFsbHkgeyBpZiAoX2QpIHRocm93IF9lOyB9IH0gcmV0dXJuIF9hcnI7IH0gcmV0dXJuIGZ1bmN0aW9uIChhcnIsIGkpIHsgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgeyByZXR1cm4gYXJyOyB9IGVsc2UgaWYgKFN5bWJvbC5pdGVyYXRvciBpbiBPYmplY3QoYXJyKSkgeyByZXR1cm4gc2xpY2VJdGVyYXRvcihhcnIsIGkpOyB9IGVsc2UgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBhdHRlbXB0IHRvIGRlc3RydWN0dXJlIG5vbi1pdGVyYWJsZSBpbnN0YW5jZVwiKTsgfSB9OyB9KCk7XG5cbnZhciBUQVUgPSBNYXRoLlBJICogMjtcblxudmFyIG1hcFRvRWxsaXBzZSA9IGZ1bmN0aW9uIG1hcFRvRWxsaXBzZShfcmVmLCByeCwgcnksIGNvc3BoaSwgc2lucGhpLCBjZW50ZXJ4LCBjZW50ZXJ5KSB7XG4gIHZhciB4ID0gX3JlZi54LFxuICAgICAgeSA9IF9yZWYueTtcblxuICB4ICo9IHJ4O1xuICB5ICo9IHJ5O1xuXG4gIHZhciB4cCA9IGNvc3BoaSAqIHggLSBzaW5waGkgKiB5O1xuICB2YXIgeXAgPSBzaW5waGkgKiB4ICsgY29zcGhpICogeTtcblxuICByZXR1cm4ge1xuICAgIHg6IHhwICsgY2VudGVyeCxcbiAgICB5OiB5cCArIGNlbnRlcnlcbiAgfTtcbn07XG5cbnZhciBhcHByb3hVbml0QXJjID0gZnVuY3Rpb24gYXBwcm94VW5pdEFyYyhhbmcxLCBhbmcyKSB7XG4gIC8vIFNlZSBodHRwOi8vc3BlbmNlcm1vcnRlbnNlbi5jb20vYXJ0aWNsZXMvYmV6aWVyLWNpcmNsZS8gZm9yIHRoZSBkZXJpdmF0aW9uXG4gIC8vIG9mIHRoaXMgY29uc3RhbnQuXG4gIC8vIE5vdGU6IFdlIG5lZWQgdG8ga2VlcCB0aGUgc2lnbiBvZiBhbmcyLCBiZWNhdXNlIHRoaXMgZGV0ZXJtaW5lcyB0aGVcbiAgLy8gICAgICAgZGlyZWN0aW9uIG9mIHRoZSBhcmMgdXNpbmcgdGhlIHN3ZWVwLWZsYWcgcGFyYW1ldGVyLlxuICB2YXIgYyA9IDAuNTUxOTE1MDI0NDk0ICogKGFuZzIgPCAwID8gLTEgOiAxKTtcblxuICB2YXIgeDEgPSBNYXRoLmNvcyhhbmcxKTtcbiAgdmFyIHkxID0gTWF0aC5zaW4oYW5nMSk7XG4gIHZhciB4MiA9IE1hdGguY29zKGFuZzEgKyBhbmcyKTtcbiAgdmFyIHkyID0gTWF0aC5zaW4oYW5nMSArIGFuZzIpO1xuXG4gIHJldHVybiBbe1xuICAgIHg6IHgxIC0geTEgKiBjLFxuICAgIHk6IHkxICsgeDEgKiBjXG4gIH0sIHtcbiAgICB4OiB4MiArIHkyICogYyxcbiAgICB5OiB5MiAtIHgyICogY1xuICB9LCB7XG4gICAgeDogeDIsXG4gICAgeTogeTJcbiAgfV07XG59O1xuXG52YXIgdmVjdG9yQW5nbGUgPSBmdW5jdGlvbiB2ZWN0b3JBbmdsZSh1eCwgdXksIHZ4LCB2eSkge1xuICB2YXIgc2lnbiA9IHV4ICogdnkgLSB1eSAqIHZ4IDwgMCA/IC0xIDogMTtcbiAgdmFyIHVtYWcgPSBNYXRoLnNxcnQodXggKiB1eCArIHV5ICogdXkpO1xuICB2YXIgdm1hZyA9IE1hdGguc3FydCh1eCAqIHV4ICsgdXkgKiB1eSk7XG4gIHZhciBkb3QgPSB1eCAqIHZ4ICsgdXkgKiB2eTtcblxuICB2YXIgZGl2ID0gZG90IC8gKHVtYWcgKiB2bWFnKTtcblxuICBpZiAoZGl2ID4gMSkge1xuICAgIGRpdiA9IDE7XG4gIH1cblxuICBpZiAoZGl2IDwgLTEpIHtcbiAgICBkaXYgPSAtMTtcbiAgfVxuXG4gIHJldHVybiBzaWduICogTWF0aC5hY29zKGRpdik7XG59O1xuXG52YXIgZ2V0QXJjQ2VudGVyID0gZnVuY3Rpb24gZ2V0QXJjQ2VudGVyKHB4LCBweSwgY3gsIGN5LCByeCwgcnksIGxhcmdlQXJjRmxhZywgc3dlZXBGbGFnLCBzaW5waGksIGNvc3BoaSwgcHhwLCBweXApIHtcbiAgdmFyIHJ4c3EgPSBNYXRoLnBvdyhyeCwgMik7XG4gIHZhciByeXNxID0gTWF0aC5wb3cocnksIDIpO1xuICB2YXIgcHhwc3EgPSBNYXRoLnBvdyhweHAsIDIpO1xuICB2YXIgcHlwc3EgPSBNYXRoLnBvdyhweXAsIDIpO1xuXG4gIHZhciByYWRpY2FudCA9IHJ4c3EgKiByeXNxIC0gcnhzcSAqIHB5cHNxIC0gcnlzcSAqIHB4cHNxO1xuXG4gIGlmIChyYWRpY2FudCA8IDApIHtcbiAgICByYWRpY2FudCA9IDA7XG4gIH1cblxuICByYWRpY2FudCAvPSByeHNxICogcHlwc3EgKyByeXNxICogcHhwc3E7XG4gIHJhZGljYW50ID0gTWF0aC5zcXJ0KHJhZGljYW50KSAqIChsYXJnZUFyY0ZsYWcgPT09IHN3ZWVwRmxhZyA/IC0xIDogMSk7XG5cbiAgdmFyIGNlbnRlcnhwID0gcmFkaWNhbnQgKiByeCAvIHJ5ICogcHlwO1xuICB2YXIgY2VudGVyeXAgPSByYWRpY2FudCAqIC1yeSAvIHJ4ICogcHhwO1xuXG4gIHZhciBjZW50ZXJ4ID0gY29zcGhpICogY2VudGVyeHAgLSBzaW5waGkgKiBjZW50ZXJ5cCArIChweCArIGN4KSAvIDI7XG4gIHZhciBjZW50ZXJ5ID0gc2lucGhpICogY2VudGVyeHAgKyBjb3NwaGkgKiBjZW50ZXJ5cCArIChweSArIGN5KSAvIDI7XG5cbiAgdmFyIHZ4MSA9IChweHAgLSBjZW50ZXJ4cCkgLyByeDtcbiAgdmFyIHZ5MSA9IChweXAgLSBjZW50ZXJ5cCkgLyByeTtcbiAgdmFyIHZ4MiA9ICgtcHhwIC0gY2VudGVyeHApIC8gcng7XG4gIHZhciB2eTIgPSAoLXB5cCAtIGNlbnRlcnlwKSAvIHJ5O1xuXG4gIHZhciBhbmcxID0gdmVjdG9yQW5nbGUoMSwgMCwgdngxLCB2eTEpO1xuICB2YXIgYW5nMiA9IHZlY3RvckFuZ2xlKHZ4MSwgdnkxLCB2eDIsIHZ5Mik7XG5cbiAgaWYgKHN3ZWVwRmxhZyA9PT0gMCAmJiBhbmcyID4gMCkge1xuICAgIGFuZzIgLT0gVEFVO1xuICB9XG5cbiAgaWYgKHN3ZWVwRmxhZyA9PT0gMSAmJiBhbmcyIDwgMCkge1xuICAgIGFuZzIgKz0gVEFVO1xuICB9XG5cbiAgcmV0dXJuIFtjZW50ZXJ4LCBjZW50ZXJ5LCBhbmcxLCBhbmcyXTtcbn07XG5cbnZhciBhcmNUb0JlemllciA9IGZ1bmN0aW9uIGFyY1RvQmV6aWVyKF9yZWYyKSB7XG4gIHZhciBweCA9IF9yZWYyLnB4LFxuICAgICAgcHkgPSBfcmVmMi5weSxcbiAgICAgIGN4ID0gX3JlZjIuY3gsXG4gICAgICBjeSA9IF9yZWYyLmN5LFxuICAgICAgcnggPSBfcmVmMi5yeCxcbiAgICAgIHJ5ID0gX3JlZjIucnksXG4gICAgICBfcmVmMiR4QXhpc1JvdGF0aW9uID0gX3JlZjIueEF4aXNSb3RhdGlvbixcbiAgICAgIHhBeGlzUm90YXRpb24gPSBfcmVmMiR4QXhpc1JvdGF0aW9uID09PSB1bmRlZmluZWQgPyAwIDogX3JlZjIkeEF4aXNSb3RhdGlvbixcbiAgICAgIF9yZWYyJGxhcmdlQXJjRmxhZyA9IF9yZWYyLmxhcmdlQXJjRmxhZyxcbiAgICAgIGxhcmdlQXJjRmxhZyA9IF9yZWYyJGxhcmdlQXJjRmxhZyA9PT0gdW5kZWZpbmVkID8gMCA6IF9yZWYyJGxhcmdlQXJjRmxhZyxcbiAgICAgIF9yZWYyJHN3ZWVwRmxhZyA9IF9yZWYyLnN3ZWVwRmxhZyxcbiAgICAgIHN3ZWVwRmxhZyA9IF9yZWYyJHN3ZWVwRmxhZyA9PT0gdW5kZWZpbmVkID8gMCA6IF9yZWYyJHN3ZWVwRmxhZztcblxuICB2YXIgY3VydmVzID0gW107XG5cbiAgaWYgKHJ4ID09PSAwIHx8IHJ5ID09PSAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgdmFyIHNpbnBoaSA9IE1hdGguc2luKHhBeGlzUm90YXRpb24gKiBUQVUgLyAzNjApO1xuICB2YXIgY29zcGhpID0gTWF0aC5jb3MoeEF4aXNSb3RhdGlvbiAqIFRBVSAvIDM2MCk7XG5cbiAgdmFyIHB4cCA9IGNvc3BoaSAqIChweCAtIGN4KSAvIDIgKyBzaW5waGkgKiAocHkgLSBjeSkgLyAyO1xuICB2YXIgcHlwID0gLXNpbnBoaSAqIChweCAtIGN4KSAvIDIgKyBjb3NwaGkgKiAocHkgLSBjeSkgLyAyO1xuXG4gIGlmIChweHAgPT09IDAgJiYgcHlwID09PSAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgcnggPSBNYXRoLmFicyhyeCk7XG4gIHJ5ID0gTWF0aC5hYnMocnkpO1xuXG4gIHZhciBsYW1iZGEgPSBNYXRoLnBvdyhweHAsIDIpIC8gTWF0aC5wb3cocngsIDIpICsgTWF0aC5wb3cocHlwLCAyKSAvIE1hdGgucG93KHJ5LCAyKTtcblxuICBpZiAobGFtYmRhID4gMSkge1xuICAgIHJ4ICo9IE1hdGguc3FydChsYW1iZGEpO1xuICAgIHJ5ICo9IE1hdGguc3FydChsYW1iZGEpO1xuICB9XG5cbiAgdmFyIF9nZXRBcmNDZW50ZXIgPSBnZXRBcmNDZW50ZXIocHgsIHB5LCBjeCwgY3ksIHJ4LCByeSwgbGFyZ2VBcmNGbGFnLCBzd2VlcEZsYWcsIHNpbnBoaSwgY29zcGhpLCBweHAsIHB5cCksXG4gICAgICBfZ2V0QXJjQ2VudGVyMiA9IF9zbGljZWRUb0FycmF5KF9nZXRBcmNDZW50ZXIsIDQpLFxuICAgICAgY2VudGVyeCA9IF9nZXRBcmNDZW50ZXIyWzBdLFxuICAgICAgY2VudGVyeSA9IF9nZXRBcmNDZW50ZXIyWzFdLFxuICAgICAgYW5nMSA9IF9nZXRBcmNDZW50ZXIyWzJdLFxuICAgICAgYW5nMiA9IF9nZXRBcmNDZW50ZXIyWzNdO1xuXG4gIC8vIElmICdhbmcyJyA9PSA5MC4wMDAwMDAwMDAxLCB0aGVuIGByYXRpb2Agd2lsbCBldmFsdWF0ZSB0b1xuICAvLyAxLjAwMDAwMDAwMDEuIFRoaXMgY2F1c2VzIGBzZWdtZW50c2AgdG8gYmUgZ3JlYXRlciB0aGFuIG9uZSwgd2hpY2ggaXMgYW5cbiAgLy8gdW5lY2Vzc2FyeSBzcGxpdCwgYW5kIGFkZHMgZXh0cmEgcG9pbnRzIHRvIHRoZSBiZXppZXIgY3VydmUuIFRvIGFsbGV2aWF0ZVxuICAvLyB0aGlzIGlzc3VlLCB3ZSByb3VuZCB0byAxLjAgd2hlbiB0aGUgcmF0aW8gaXMgY2xvc2UgdG8gMS4wLlxuXG5cbiAgdmFyIHJhdGlvID0gTWF0aC5hYnMoYW5nMikgLyAoVEFVIC8gNCk7XG4gIGlmIChNYXRoLmFicygxLjAgLSByYXRpbykgPCAwLjAwMDAwMDEpIHtcbiAgICByYXRpbyA9IDEuMDtcbiAgfVxuXG4gIHZhciBzZWdtZW50cyA9IE1hdGgubWF4KE1hdGguY2VpbChyYXRpbyksIDEpO1xuXG4gIGFuZzIgLz0gc2VnbWVudHM7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZWdtZW50czsgaSsrKSB7XG4gICAgY3VydmVzLnB1c2goYXBwcm94VW5pdEFyYyhhbmcxLCBhbmcyKSk7XG4gICAgYW5nMSArPSBhbmcyO1xuICB9XG5cbiAgcmV0dXJuIGN1cnZlcy5tYXAoZnVuY3Rpb24gKGN1cnZlKSB7XG4gICAgdmFyIF9tYXBUb0VsbGlwc2UgPSBtYXBUb0VsbGlwc2UoY3VydmVbMF0sIHJ4LCByeSwgY29zcGhpLCBzaW5waGksIGNlbnRlcngsIGNlbnRlcnkpLFxuICAgICAgICB4MSA9IF9tYXBUb0VsbGlwc2UueCxcbiAgICAgICAgeTEgPSBfbWFwVG9FbGxpcHNlLnk7XG5cbiAgICB2YXIgX21hcFRvRWxsaXBzZTIgPSBtYXBUb0VsbGlwc2UoY3VydmVbMV0sIHJ4LCByeSwgY29zcGhpLCBzaW5waGksIGNlbnRlcngsIGNlbnRlcnkpLFxuICAgICAgICB4MiA9IF9tYXBUb0VsbGlwc2UyLngsXG4gICAgICAgIHkyID0gX21hcFRvRWxsaXBzZTIueTtcblxuICAgIHZhciBfbWFwVG9FbGxpcHNlMyA9IG1hcFRvRWxsaXBzZShjdXJ2ZVsyXSwgcngsIHJ5LCBjb3NwaGksIHNpbnBoaSwgY2VudGVyeCwgY2VudGVyeSksXG4gICAgICAgIHggPSBfbWFwVG9FbGxpcHNlMy54LFxuICAgICAgICB5ID0gX21hcFRvRWxsaXBzZTMueTtcblxuICAgIHJldHVybiB7IHgxOiB4MSwgeTE6IHkxLCB4MjogeDIsIHkyOiB5MiwgeDogeCwgeTogeSB9O1xuICB9KTtcbn07XG5cbmV4cG9ydHMuZGVmYXVsdCA9IGFyY1RvQmV6aWVyO1xubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzLmRlZmF1bHQ7XG59LHt9XSw1MzM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXHJcblxyXG52YXIgcGFyc2UgPSBfZGVyZXFfKCdwYXJzZS1zdmctcGF0aCcpXHJcbnZhciBhYnMgPSBfZGVyZXFfKCdhYnMtc3ZnLXBhdGgnKVxyXG52YXIgbm9ybWFsaXplID0gX2RlcmVxXygnbm9ybWFsaXplLXN2Zy1wYXRoJylcclxudmFyIGlzU3ZnUGF0aCA9IF9kZXJlcV8oJ2lzLXN2Zy1wYXRoJylcclxudmFyIGFzc2VydCA9IF9kZXJlcV8oJ2Fzc2VydCcpXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHBhdGhCb3VuZHNcclxuXHJcblxyXG5mdW5jdGlvbiBwYXRoQm91bmRzKHBhdGgpIHtcclxuICAvLyBFUzYgc3RyaW5nIHRwbCBjYWxsXHJcbiAgaWYgKEFycmF5LmlzQXJyYXkocGF0aCkgJiYgcGF0aC5sZW5ndGggPT09IDEgJiYgdHlwZW9mIHBhdGhbMF0gPT09ICdzdHJpbmcnKSBwYXRoID0gcGF0aFswXVxyXG5cclxuICAvLyBzdmcgcGF0aCBzdHJpbmdcclxuICBpZiAodHlwZW9mIHBhdGggPT09ICdzdHJpbmcnKSB7XHJcbiAgICBhc3NlcnQoaXNTdmdQYXRoKHBhdGgpLCAnU3RyaW5nIGlzIG5vdCBhbiBTVkcgcGF0aC4nKVxyXG4gICAgcGF0aCA9IHBhcnNlKHBhdGgpXHJcbiAgfVxyXG5cclxuICBhc3NlcnQoQXJyYXkuaXNBcnJheShwYXRoKSwgJ0FyZ3VtZW50IHNob3VsZCBiZSBhIHN0cmluZyBvciBhbiBhcnJheSBvZiBwYXRoIHNlZ21lbnRzLicpXHJcblxyXG4gIHBhdGggPSBhYnMocGF0aClcclxuICBwYXRoID0gbm9ybWFsaXplKHBhdGgpXHJcblxyXG4gIGlmICghcGF0aC5sZW5ndGgpIHJldHVybiBbMCwgMCwgMCwgMF1cclxuXHJcbiAgdmFyIGJvdW5kcyA9IFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XVxyXG5cclxuICBmb3IgKHZhciBpID0gMCwgbCA9IHBhdGgubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XHJcbiAgICB2YXIgcG9pbnRzID0gcGF0aFtpXS5zbGljZSgxKVxyXG5cclxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgcG9pbnRzLmxlbmd0aDsgaiArPSAyKSB7XHJcbiAgICAgIGlmIChwb2ludHNbaiArIDBdIDwgYm91bmRzWzBdKSBib3VuZHNbMF0gPSBwb2ludHNbaiArIDBdXHJcbiAgICAgIGlmIChwb2ludHNbaiArIDFdIDwgYm91bmRzWzFdKSBib3VuZHNbMV0gPSBwb2ludHNbaiArIDFdXHJcbiAgICAgIGlmIChwb2ludHNbaiArIDBdID4gYm91bmRzWzJdKSBib3VuZHNbMl0gPSBwb2ludHNbaiArIDBdXHJcbiAgICAgIGlmIChwb2ludHNbaiArIDFdID4gYm91bmRzWzNdKSBib3VuZHNbM10gPSBwb2ludHNbaiArIDFdXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gYm91bmRzXHJcbn1cclxuXG59LHtcImFicy1zdmctcGF0aFwiOjYwLFwiYXNzZXJ0XCI6NjgsXCJpcy1zdmctcGF0aFwiOjQyNCxcIm5vcm1hbGl6ZS1zdmctcGF0aFwiOjUzNCxcInBhcnNlLXN2Zy1wYXRoXCI6NDYwfV0sNTM0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBub3JtYWxpemVcclxuXHJcbnZhciBhcmNUb0N1cnZlID0gX2RlcmVxXygnc3ZnLWFyYy10by1jdWJpYy1iZXppZXInKVxyXG5cclxuZnVuY3Rpb24gbm9ybWFsaXplKHBhdGgpe1xyXG4gIC8vIGluaXQgc3RhdGVcclxuICB2YXIgcHJldlxyXG4gIHZhciByZXN1bHQgPSBbXVxyXG4gIHZhciBiZXppZXJYID0gMFxyXG4gIHZhciBiZXppZXJZID0gMFxyXG4gIHZhciBzdGFydFggPSAwXHJcbiAgdmFyIHN0YXJ0WSA9IDBcclxuICB2YXIgcXVhZFggPSBudWxsXHJcbiAgdmFyIHF1YWRZID0gbnVsbFxyXG4gIHZhciB4ID0gMFxyXG4gIHZhciB5ID0gMFxyXG5cclxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gcGF0aC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG4gICAgdmFyIHNlZyA9IHBhdGhbaV1cclxuICAgIHZhciBjb21tYW5kID0gc2VnWzBdXHJcblxyXG4gICAgc3dpdGNoIChjb21tYW5kKSB7XHJcbiAgICAgIGNhc2UgJ00nOlxyXG4gICAgICAgIHN0YXJ0WCA9IHNlZ1sxXVxyXG4gICAgICAgIHN0YXJ0WSA9IHNlZ1syXVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgJ0EnOlxyXG4gICAgICAgIHZhciBjdXJ2ZXMgPSBhcmNUb0N1cnZlKHtcclxuICAgICAgICAgIHB4OiB4LFxyXG4gICAgICAgICAgcHk6IHksXHJcbiAgICAgICAgICBjeDogc2VnWzZdLFxyXG4gICAgICAgICAgY3k6ICBzZWdbN10sXHJcbiAgICAgICAgICByeDogc2VnWzFdLFxyXG4gICAgICAgICAgcnk6IHNlZ1syXSxcclxuICAgICAgICAgIHhBeGlzUm90YXRpb246IHNlZ1szXSxcclxuICAgICAgICAgIGxhcmdlQXJjRmxhZzogc2VnWzRdLFxyXG4gICAgICAgICAgc3dlZXBGbGFnOiBzZWdbNV1cclxuICAgICAgICB9KVxyXG5cclxuICAgICAgICAvLyBudWxsLWN1cnZlc1xyXG4gICAgICAgIGlmICghY3VydmVzLmxlbmd0aCkgY29udGludWVcclxuXHJcbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIGM7IGogPCBjdXJ2ZXMubGVuZ3RoOyBqKyspIHtcclxuICAgICAgICAgIGMgPSBjdXJ2ZXNbal1cclxuICAgICAgICAgIHNlZyA9IFsnQycsIGMueDEsIGMueTEsIGMueDIsIGMueTIsIGMueCwgYy55XVxyXG4gICAgICAgICAgaWYgKGogPCBjdXJ2ZXMubGVuZ3RoIC0gMSkgcmVzdWx0LnB1c2goc2VnKVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYnJlYWtcclxuICAgICAgY2FzZSAnUyc6XHJcbiAgICAgICAgLy8gZGVmYXVsdCBjb250cm9sIHBvaW50XHJcbiAgICAgICAgdmFyIGN4ID0geFxyXG4gICAgICAgIHZhciBjeSA9IHlcclxuICAgICAgICBpZiAocHJldiA9PSAnQycgfHwgcHJldiA9PSAnUycpIHtcclxuICAgICAgICAgIGN4ICs9IGN4IC0gYmV6aWVyWCAvLyByZWZsZWN0IHRoZSBwcmV2aW91cyBjb21tYW5kJ3MgY29udHJvbFxyXG4gICAgICAgICAgY3kgKz0gY3kgLSBiZXppZXJZIC8vIHBvaW50IHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IHBvaW50XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHNlZyA9IFsnQycsIGN4LCBjeSwgc2VnWzFdLCBzZWdbMl0sIHNlZ1szXSwgc2VnWzRdXVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgJ1QnOlxyXG4gICAgICAgIGlmIChwcmV2ID09ICdRJyB8fCBwcmV2ID09ICdUJykge1xyXG4gICAgICAgICAgcXVhZFggPSB4ICogMiAtIHF1YWRYIC8vIGFzIHdpdGggJ1MnIHJlZmxlY3QgcHJldmlvdXMgY29udHJvbCBwb2ludFxyXG4gICAgICAgICAgcXVhZFkgPSB5ICogMiAtIHF1YWRZXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHF1YWRYID0geFxyXG4gICAgICAgICAgcXVhZFkgPSB5XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHNlZyA9IHF1YWRyYXRpYyh4LCB5LCBxdWFkWCwgcXVhZFksIHNlZ1sxXSwgc2VnWzJdKVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgJ1EnOlxyXG4gICAgICAgIHF1YWRYID0gc2VnWzFdXHJcbiAgICAgICAgcXVhZFkgPSBzZWdbMl1cclxuICAgICAgICBzZWcgPSBxdWFkcmF0aWMoeCwgeSwgc2VnWzFdLCBzZWdbMl0sIHNlZ1szXSwgc2VnWzRdKVxyXG4gICAgICAgIGJyZWFrXHJcbiAgICAgIGNhc2UgJ0wnOlxyXG4gICAgICAgIHNlZyA9IGxpbmUoeCwgeSwgc2VnWzFdLCBzZWdbMl0pXHJcbiAgICAgICAgYnJlYWtcclxuICAgICAgY2FzZSAnSCc6XHJcbiAgICAgICAgc2VnID0gbGluZSh4LCB5LCBzZWdbMV0sIHkpXHJcbiAgICAgICAgYnJlYWtcclxuICAgICAgY2FzZSAnVic6XHJcbiAgICAgICAgc2VnID0gbGluZSh4LCB5LCB4LCBzZWdbMV0pXHJcbiAgICAgICAgYnJlYWtcclxuICAgICAgY2FzZSAnWic6XHJcbiAgICAgICAgc2VnID0gbGluZSh4LCB5LCBzdGFydFgsIHN0YXJ0WSlcclxuICAgICAgICBicmVha1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHVwZGF0ZSBzdGF0ZVxyXG4gICAgcHJldiA9IGNvbW1hbmRcclxuICAgIHggPSBzZWdbc2VnLmxlbmd0aCAtIDJdXHJcbiAgICB5ID0gc2VnW3NlZy5sZW5ndGggLSAxXVxyXG4gICAgaWYgKHNlZy5sZW5ndGggPiA0KSB7XHJcbiAgICAgIGJlemllclggPSBzZWdbc2VnLmxlbmd0aCAtIDRdXHJcbiAgICAgIGJlemllclkgPSBzZWdbc2VnLmxlbmd0aCAtIDNdXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBiZXppZXJYID0geFxyXG4gICAgICBiZXppZXJZID0geVxyXG4gICAgfVxyXG4gICAgcmVzdWx0LnB1c2goc2VnKVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJlc3VsdFxyXG59XHJcblxyXG5mdW5jdGlvbiBsaW5lKHgxLCB5MSwgeDIsIHkyKXtcclxuICByZXR1cm4gWydDJywgeDEsIHkxLCB4MiwgeTIsIHgyLCB5Ml1cclxufVxyXG5cclxuZnVuY3Rpb24gcXVhZHJhdGljKHgxLCB5MSwgY3gsIGN5LCB4MiwgeTIpe1xyXG4gIHJldHVybiBbXHJcbiAgICAnQycsXHJcbiAgICB4MS8zICsgKDIvMykgKiBjeCxcclxuICAgIHkxLzMgKyAoMi8zKSAqIGN5LFxyXG4gICAgeDIvMyArICgyLzMpICogY3gsXHJcbiAgICB5Mi8zICsgKDIvMykgKiBjeSxcclxuICAgIHgyLFxyXG4gICAgeTJcclxuICBdXHJcbn1cclxuXG59LHtcInN2Zy1hcmMtdG8tY3ViaWMtYmV6aWVyXCI6NTMyfV0sNTM1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbid1c2Ugc3RyaWN0J1xyXG5cclxudmFyIHBhdGhCb3VuZHMgPSBfZGVyZXFfKCdzdmctcGF0aC1ib3VuZHMnKVxyXG52YXIgcGFyc2VQYXRoID0gX2RlcmVxXygncGFyc2Utc3ZnLXBhdGgnKVxyXG52YXIgZHJhd1BhdGggPSBfZGVyZXFfKCdkcmF3LXN2Zy1wYXRoJylcclxudmFyIGlzU3ZnUGF0aCA9IF9kZXJlcV8oJ2lzLXN2Zy1wYXRoJylcclxudmFyIGJpdG1hcFNkZiA9IF9kZXJlcV8oJ2JpdG1hcC1zZGYnKVxyXG5cclxudmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpXHJcbnZhciBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKVxyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gcGF0aFNkZlxyXG5cclxuXHJcbmZ1bmN0aW9uIHBhdGhTZGYgKHBhdGgsIG9wdGlvbnMpIHtcclxuXHRpZiAoIWlzU3ZnUGF0aChwYXRoKSkgdGhyb3cgRXJyb3IoJ0FyZ3VtZW50IHNob3VsZCBiZSB2YWxpZCBzdmcgcGF0aCBzdHJpbmcnKVxyXG5cclxuXHRpZiAoIW9wdGlvbnMpIG9wdGlvbnMgPSB7fVxyXG5cclxuXHR2YXIgdywgaFxyXG5cdGlmIChvcHRpb25zLnNoYXBlKSB7XHJcblx0XHR3ID0gb3B0aW9ucy5zaGFwZVswXVxyXG5cdFx0aCA9IG9wdGlvbnMuc2hhcGVbMV1cclxuXHR9XHJcblx0ZWxzZSB7XHJcblx0XHR3ID0gY2FudmFzLndpZHRoID0gb3B0aW9ucy53IHx8IG9wdGlvbnMud2lkdGggfHwgMjAwXHJcblx0XHRoID0gY2FudmFzLmhlaWdodCA9IG9wdGlvbnMuaCB8fCBvcHRpb25zLmhlaWdodCB8fCAyMDBcclxuXHR9XHJcblx0dmFyIHNpemUgPSBNYXRoLm1pbih3LCBoKVxyXG5cclxuXHR2YXIgc3Ryb2tlID0gb3B0aW9ucy5zdHJva2UgfHwgMFxyXG5cclxuXHR2YXIgdmlld2JveCA9IG9wdGlvbnMudmlld2JveCB8fCBvcHRpb25zLnZpZXdCb3ggfHwgcGF0aEJvdW5kcyhwYXRoKVxyXG5cdHZhciBzY2FsZSA9IFt3IC8gKHZpZXdib3hbMl0gLSB2aWV3Ym94WzBdKSwgaCAvICh2aWV3Ym94WzNdIC0gdmlld2JveFsxXSldXHJcblx0dmFyIG1heFNjYWxlID0gTWF0aC5taW4oc2NhbGVbMF0gfHwgMCwgc2NhbGVbMV0gfHwgMCkgLyAyXHJcblxyXG5cdC8vY2xlYXIgY3R4XHJcblx0Y3R4LmZpbGxTdHlsZSA9ICdibGFjaydcclxuXHRjdHguZmlsbFJlY3QoMCwgMCwgdywgaClcclxuXHJcblx0Y3R4LmZpbGxTdHlsZSA9ICd3aGl0ZSdcclxuXHJcblx0aWYgKHN0cm9rZSlcdHtcclxuXHRcdGlmICh0eXBlb2Ygc3Ryb2tlICE9ICdudW1iZXInKSBzdHJva2UgPSAxXHJcblx0XHRpZiAoc3Ryb2tlID4gMCkge1xyXG5cdFx0XHRjdHguc3Ryb2tlU3R5bGUgPSAnd2hpdGUnXHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0Y3R4LnN0cm9rZVN0eWxlID0gJ2JsYWNrJ1xyXG5cdFx0fVxyXG5cclxuXHRcdGN0eC5saW5lV2lkdGggPSBNYXRoLmFicyhzdHJva2UpXHJcblx0fVxyXG5cclxuXHRjdHgudHJhbnNsYXRlKHcgKiAuNSwgaCAqIC41KVxyXG5cdGN0eC5zY2FsZShtYXhTY2FsZSwgbWF4U2NhbGUpXHJcblxyXG5cdC8vaWYgY2FudmFzIHN2ZyBwYXRocyBhcGkgaXMgYXZhaWxhYmxlXHJcblx0aWYgKGlzUGF0aDJEU3VwcG9ydGVkKCkpIHtcclxuXHRcdHZhciBwYXRoMmQgPSBuZXcgUGF0aDJEKHBhdGgpXHJcblx0XHRjdHguZmlsbChwYXRoMmQpXHJcblx0XHRzdHJva2UgJiYgY3R4LnN0cm9rZShwYXRoMmQpXHJcblx0fVxyXG5cdC8vZmFsbGJhY2sgdG8gYmV6aWVyLWN1cnZlc1xyXG5cdGVsc2Uge1xyXG5cdFx0dmFyIHNlZ21lbnRzID0gcGFyc2VQYXRoKHBhdGgpXHJcblx0XHRkcmF3UGF0aChjdHgsIHNlZ21lbnRzKVxyXG5cdFx0Y3R4LmZpbGwoKVxyXG5cdFx0c3Ryb2tlICYmIGN0eC5zdHJva2UoKVxyXG5cdH1cclxuXHJcblx0Y3R4LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTtcclxuXHJcblx0dmFyIGRhdGEgPSBiaXRtYXBTZGYoY3R4LCB7XHJcblx0XHRjdXRvZmY6IG9wdGlvbnMuY3V0b2ZmICE9IG51bGwgPyBvcHRpb25zLmN1dG9mZiA6IC41LFxyXG5cdFx0cmFkaXVzOiBvcHRpb25zLnJhZGl1cyAhPSBudWxsID8gb3B0aW9ucy5yYWRpdXMgOiBzaXplICogLjVcclxuXHR9KVxyXG5cclxuXHRyZXR1cm4gZGF0YVxyXG59XHJcblxyXG52YXIgcGF0aDJEU3VwcG9ydGVkXHJcblxyXG5mdW5jdGlvbiBpc1BhdGgyRFN1cHBvcnRlZCAoKSB7XHJcblx0aWYgKHBhdGgyRFN1cHBvcnRlZCAhPSBudWxsKSByZXR1cm4gcGF0aDJEU3VwcG9ydGVkXHJcblxyXG5cdHZhciBjdHggPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKS5nZXRDb250ZXh0KCcyZCcpXHJcblx0Y3R4LmNhbnZhcy53aWR0aCA9IGN0eC5jYW52YXMuaGVpZ2h0ID0gMVxyXG5cclxuXHRpZiAoIXdpbmRvdy5QYXRoMkQpIHJldHVybiBwYXRoMkRTdXBwb3J0ZWQgPSBmYWxzZVxyXG5cclxuXHR2YXIgcGF0aCA9IG5ldyBQYXRoMkQoJ00wLDBoMXYxaC0xdi0xWicpXHJcblxyXG5cdGN0eC5maWxsU3R5bGUgPSAnYmxhY2snXHJcblx0Y3R4LmZpbGwocGF0aClcclxuXHJcblx0dmFyIGlkYXRhID0gY3R4LmdldEltYWdlRGF0YSgwLDAsMSwxKVxyXG5cclxuXHRyZXR1cm4gcGF0aDJEU3VwcG9ydGVkID0gaWRhdGEgJiYgaWRhdGEuZGF0YSAmJiBpZGF0YS5kYXRhWzNdID09PSAyNTVcclxufVxyXG5cbn0se1wiYml0bWFwLXNkZlwiOjkzLFwiZHJhdy1zdmctcGF0aFwiOjE2OCxcImlzLXN2Zy1wYXRoXCI6NDI0LFwicGFyc2Utc3ZnLXBhdGhcIjo0NjAsXCJzdmctcGF0aC1ib3VuZHNcIjo1MzN9XSw1MzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuKGZ1bmN0aW9uIChwcm9jZXNzKXtcbid1c2Ugc3RyaWN0J1xuXG5tb2R1bGUuZXhwb3J0cyA9IHRleHRHZXRcblxudmFyIHZlY3Rvcml6ZVRleHQgPSBfZGVyZXFfKCd2ZWN0b3JpemUtdGV4dCcpXG5cbnZhciBnbG9iYWxzID0gd2luZG93IHx8IHByb2Nlc3MuZ2xvYmFsIHx8IHt9XG52YXIgX19URVhUX0NBQ0hFICA9IGdsb2JhbHMuX19URVhUX0NBQ0hFIHx8IHt9XG5nbG9iYWxzLl9fVEVYVF9DQUNIRSA9IHt9XG5cbmZ1bmN0aW9uIHVud3JhcChtZXNoKSB7XG4gIHZhciBjZWxscyAgICAgPSBtZXNoLmNlbGxzXG4gIHZhciBwb3NpdGlvbnMgPSBtZXNoLnBvc2l0aW9uc1xuICB2YXIgZGF0YSAgICAgID0gbmV3IEZsb2F0MzJBcnJheShjZWxscy5sZW5ndGggKiA2KVxuICB2YXIgcHRyICAgICAgID0gMFxuICB2YXIgc2hhcGVYICAgID0gMFxuICBmb3IodmFyIGk9MDsgaTxjZWxscy5sZW5ndGg7ICsraSkge1xuICAgIHZhciB0cmkgPSBjZWxsc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgdmFyIHBvaW50ID0gcG9zaXRpb25zW3RyaVtqXV1cbiAgICAgIGRhdGFbcHRyKytdID0gcG9pbnRbMF1cbiAgICAgIGRhdGFbcHRyKytdID0gcG9pbnRbMV0gKyAxLjRcbiAgICAgIHNoYXBlWCAgICAgID0gTWF0aC5tYXgocG9pbnRbMF0sIHNoYXBlWClcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBkYXRhOiAgZGF0YSxcbiAgICBzaGFwZTogc2hhcGVYXG4gIH1cbn1cblxuZnVuY3Rpb24gdGV4dEdldChmb250LCB0ZXh0LCBvcHRzKSB7XG4gIHZhciBvcHRzID0gb3B0cyB8fCB7fVxuICB2YXIgZm9udGNhY2hlID0gX19URVhUX0NBQ0hFW2ZvbnRdXG4gIGlmKCFmb250Y2FjaGUpIHtcbiAgICBmb250Y2FjaGUgPSBfX1RFWFRfQ0FDSEVbZm9udF0gPSB7XG4gICAgICAnICc6IHtcbiAgICAgICAgZGF0YTogICBuZXcgRmxvYXQzMkFycmF5KDApLFxuICAgICAgICBzaGFwZTogMC4yXG4gICAgICB9XG4gICAgfVxuICB9XG4gIHZhciBtZXNoID0gZm9udGNhY2hlW3RleHRdXG4gIGlmKCFtZXNoKSB7XG4gICAgaWYodGV4dC5sZW5ndGggPD0gMSB8fCAhL1xcZC8udGVzdCh0ZXh0KSkge1xuICAgICAgbWVzaCA9IGZvbnRjYWNoZVt0ZXh0XSA9IHVud3JhcCh2ZWN0b3JpemVUZXh0KHRleHQsIHtcbiAgICAgICAgdHJpYW5nbGVzOiAgICAgdHJ1ZSxcbiAgICAgICAgZm9udDogICAgICAgICAgZm9udCxcbiAgICAgICAgdGV4dEFsaWduOiAgICAgb3B0cy50ZXh0QWxpZ24gfHwgJ2xlZnQnLFxuICAgICAgICB0ZXh0QmFzZWxpbmU6ICAnYWxwaGFiZXRpYycsXG4gICAgICAgIHN0eWxldGFnczoge1xuICAgICAgICAgICAgYnJlYWtsaW5lczogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgYm9sZHM6IHRydWUsXG4gICAgICAgICAgICAgICBpdGFsaWNzOiB0cnVlLFxuICAgICAgICAgICAgc3Vic2NyaXB0czogdHJ1ZSxcbiAgICAgICAgICBzdXBlcnNjcmlwdHM6IHRydWVcbiAgICAgICAgfVxuICAgICAgfSkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBwYXJ0cyA9IHRleHQuc3BsaXQoLyhcXGR8XFxzKS8pXG4gICAgICB2YXIgYnVmZmVyID0gbmV3IEFycmF5KHBhcnRzLmxlbmd0aClcbiAgICAgIHZhciBidWZmZXJTaXplID0gMFxuICAgICAgdmFyIHNoYXBlWCA9IDBcbiAgICAgIGZvcih2YXIgaT0wOyBpPHBhcnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGJ1ZmZlcltpXSA9IHRleHRHZXQoZm9udCwgcGFydHNbaV0pXG4gICAgICAgIGJ1ZmZlclNpemUgKz0gYnVmZmVyW2ldLmRhdGEubGVuZ3RoXG4gICAgICAgIHNoYXBlWCArPSBidWZmZXJbaV0uc2hhcGVcbiAgICAgICAgaWYoaT4wKSB7XG4gICAgICAgICAgc2hhcGVYICs9IDAuMDJcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgZGF0YSA9IG5ldyBGbG9hdDMyQXJyYXkoYnVmZmVyU2l6ZSlcbiAgICAgIHZhciBwdHIgICAgID0gMFxuICAgICAgdmFyIHhPZmZzZXQgPSAtMC41ICogc2hhcGVYXG4gICAgICBmb3IodmFyIGk9MDsgaTxidWZmZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIGJkYXRhID0gYnVmZmVyW2ldLmRhdGFcbiAgICAgICAgZm9yKHZhciBqPTA7IGo8YmRhdGEubGVuZ3RoOyBqKz0yKSB7XG4gICAgICAgICAgZGF0YVtwdHIrK10gPSBiZGF0YVtqXSArIHhPZmZzZXRcbiAgICAgICAgICBkYXRhW3B0cisrXSA9IGJkYXRhW2orMV1cbiAgICAgICAgfVxuICAgICAgICB4T2Zmc2V0ICs9IGJ1ZmZlcltpXS5zaGFwZSArIDAuMDJcbiAgICAgIH1cblxuICAgICAgbWVzaCA9IGZvbnRjYWNoZVt0ZXh0XSA9IHtcbiAgICAgICAgZGF0YTogIGRhdGEsXG4gICAgICAgIHNoYXBlOiBzaGFwZVhcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAgcmV0dXJuIG1lc2hcbn1cblxufSkuY2FsbCh0aGlzLF9kZXJlcV8oJ19wcm9jZXNzJykpXG59LHtcIl9wcm9jZXNzXCI6NDgyLFwidmVjdG9yaXplLXRleHRcIjo1NTB9XSw1Mzc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLy8gVGlueUNvbG9yIHYxLjQuMVxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2Jncmlucy9UaW55Q29sb3Jcbi8vIEJyaWFuIEdyaW5zdGVhZCwgTUlUIExpY2Vuc2VcblxuKGZ1bmN0aW9uKE1hdGgpIHtcblxudmFyIHRyaW1MZWZ0ID0gL15cXHMrLyxcbiAgICB0cmltUmlnaHQgPSAvXFxzKyQvLFxuICAgIHRpbnlDb3VudGVyID0gMCxcbiAgICBtYXRoUm91bmQgPSBNYXRoLnJvdW5kLFxuICAgIG1hdGhNaW4gPSBNYXRoLm1pbixcbiAgICBtYXRoTWF4ID0gTWF0aC5tYXgsXG4gICAgbWF0aFJhbmRvbSA9IE1hdGgucmFuZG9tO1xuXG5mdW5jdGlvbiB0aW55Y29sb3IgKGNvbG9yLCBvcHRzKSB7XG5cbiAgICBjb2xvciA9IChjb2xvcikgPyBjb2xvciA6ICcnO1xuICAgIG9wdHMgPSBvcHRzIHx8IHsgfTtcblxuICAgIC8vIElmIGlucHV0IGlzIGFscmVhZHkgYSB0aW55Y29sb3IsIHJldHVybiBpdHNlbGZcbiAgICBpZiAoY29sb3IgaW5zdGFuY2VvZiB0aW55Y29sb3IpIHtcbiAgICAgICByZXR1cm4gY29sb3I7XG4gICAgfVxuICAgIC8vIElmIHdlIGFyZSBjYWxsZWQgYXMgYSBmdW5jdGlvbiwgY2FsbCB1c2luZyBuZXcgaW5zdGVhZFxuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiB0aW55Y29sb3IpKSB7XG4gICAgICAgIHJldHVybiBuZXcgdGlueWNvbG9yKGNvbG9yLCBvcHRzKTtcbiAgICB9XG5cbiAgICB2YXIgcmdiID0gaW5wdXRUb1JHQihjb2xvcik7XG4gICAgdGhpcy5fb3JpZ2luYWxJbnB1dCA9IGNvbG9yLFxuICAgIHRoaXMuX3IgPSByZ2IucixcbiAgICB0aGlzLl9nID0gcmdiLmcsXG4gICAgdGhpcy5fYiA9IHJnYi5iLFxuICAgIHRoaXMuX2EgPSByZ2IuYSxcbiAgICB0aGlzLl9yb3VuZEEgPSBtYXRoUm91bmQoMTAwKnRoaXMuX2EpIC8gMTAwLFxuICAgIHRoaXMuX2Zvcm1hdCA9IG9wdHMuZm9ybWF0IHx8IHJnYi5mb3JtYXQ7XG4gICAgdGhpcy5fZ3JhZGllbnRUeXBlID0gb3B0cy5ncmFkaWVudFR5cGU7XG5cbiAgICAvLyBEb24ndCBsZXQgdGhlIHJhbmdlIG9mIFswLDI1NV0gY29tZSBiYWNrIGluIFswLDFdLlxuICAgIC8vIFBvdGVudGlhbGx5IGxvc2UgYSBsaXR0bGUgYml0IG9mIHByZWNpc2lvbiBoZXJlLCBidXQgd2lsbCBmaXggaXNzdWVzIHdoZXJlXG4gICAgLy8gLjUgZ2V0cyBpbnRlcnByZXRlZCBhcyBoYWxmIG9mIHRoZSB0b3RhbCwgaW5zdGVhZCBvZiBoYWxmIG9mIDFcbiAgICAvLyBJZiBpdCB3YXMgc3VwcG9zZWQgdG8gYmUgMTI4LCB0aGlzIHdhcyBhbHJlYWR5IHRha2VuIGNhcmUgb2YgYnkgYGlucHV0VG9SZ2JgXG4gICAgaWYgKHRoaXMuX3IgPCAxKSB7IHRoaXMuX3IgPSBtYXRoUm91bmQodGhpcy5fcik7IH1cbiAgICBpZiAodGhpcy5fZyA8IDEpIHsgdGhpcy5fZyA9IG1hdGhSb3VuZCh0aGlzLl9nKTsgfVxuICAgIGlmICh0aGlzLl9iIDwgMSkgeyB0aGlzLl9iID0gbWF0aFJvdW5kKHRoaXMuX2IpOyB9XG5cbiAgICB0aGlzLl9vayA9IHJnYi5vaztcbiAgICB0aGlzLl90Y19pZCA9IHRpbnlDb3VudGVyKys7XG59XG5cbnRpbnljb2xvci5wcm90b3R5cGUgPSB7XG4gICAgaXNEYXJrOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QnJpZ2h0bmVzcygpIDwgMTI4O1xuICAgIH0sXG4gICAgaXNMaWdodDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAhdGhpcy5pc0RhcmsoKTtcbiAgICB9LFxuICAgIGlzVmFsaWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fb2s7XG4gICAgfSxcbiAgICBnZXRPcmlnaW5hbElucHV0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl9vcmlnaW5hbElucHV0O1xuICAgIH0sXG4gICAgZ2V0Rm9ybWF0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Zvcm1hdDtcbiAgICB9LFxuICAgIGdldEFscGhhOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2E7XG4gICAgfSxcbiAgICBnZXRCcmlnaHRuZXNzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgLy9odHRwOi8vd3d3LnczLm9yZy9UUi9BRVJUI2NvbG9yLWNvbnRyYXN0XG4gICAgICAgIHZhciByZ2IgPSB0aGlzLnRvUmdiKCk7XG4gICAgICAgIHJldHVybiAocmdiLnIgKiAyOTkgKyByZ2IuZyAqIDU4NyArIHJnYi5iICogMTE0KSAvIDEwMDA7XG4gICAgfSxcbiAgICBnZXRMdW1pbmFuY2U6IGZ1bmN0aW9uKCkge1xuICAgICAgICAvL2h0dHA6Ly93d3cudzMub3JnL1RSLzIwMDgvUkVDLVdDQUcyMC0yMDA4MTIxMS8jcmVsYXRpdmVsdW1pbmFuY2VkZWZcbiAgICAgICAgdmFyIHJnYiA9IHRoaXMudG9SZ2IoKTtcbiAgICAgICAgdmFyIFJzUkdCLCBHc1JHQiwgQnNSR0IsIFIsIEcsIEI7XG4gICAgICAgIFJzUkdCID0gcmdiLnIvMjU1O1xuICAgICAgICBHc1JHQiA9IHJnYi5nLzI1NTtcbiAgICAgICAgQnNSR0IgPSByZ2IuYi8yNTU7XG5cbiAgICAgICAgaWYgKFJzUkdCIDw9IDAuMDM5MjgpIHtSID0gUnNSR0IgLyAxMi45Mjt9IGVsc2Uge1IgPSBNYXRoLnBvdygoKFJzUkdCICsgMC4wNTUpIC8gMS4wNTUpLCAyLjQpO31cbiAgICAgICAgaWYgKEdzUkdCIDw9IDAuMDM5MjgpIHtHID0gR3NSR0IgLyAxMi45Mjt9IGVsc2Uge0cgPSBNYXRoLnBvdygoKEdzUkdCICsgMC4wNTUpIC8gMS4wNTUpLCAyLjQpO31cbiAgICAgICAgaWYgKEJzUkdCIDw9IDAuMDM5MjgpIHtCID0gQnNSR0IgLyAxMi45Mjt9IGVsc2Uge0IgPSBNYXRoLnBvdygoKEJzUkdCICsgMC4wNTUpIC8gMS4wNTUpLCAyLjQpO31cbiAgICAgICAgcmV0dXJuICgwLjIxMjYgKiBSKSArICgwLjcxNTIgKiBHKSArICgwLjA3MjIgKiBCKTtcbiAgICB9LFxuICAgIHNldEFscGhhOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICB0aGlzLl9hID0gYm91bmRBbHBoYSh2YWx1ZSk7XG4gICAgICAgIHRoaXMuX3JvdW5kQSA9IG1hdGhSb3VuZCgxMDAqdGhpcy5fYSkgLyAxMDA7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgdG9Ic3Y6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgaHN2ID0gcmdiVG9Ic3YodGhpcy5fciwgdGhpcy5fZywgdGhpcy5fYik7XG4gICAgICAgIHJldHVybiB7IGg6IGhzdi5oICogMzYwLCBzOiBoc3YucywgdjogaHN2LnYsIGE6IHRoaXMuX2EgfTtcbiAgICB9LFxuICAgIHRvSHN2U3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGhzdiA9IHJnYlRvSHN2KHRoaXMuX3IsIHRoaXMuX2csIHRoaXMuX2IpO1xuICAgICAgICB2YXIgaCA9IG1hdGhSb3VuZChoc3YuaCAqIDM2MCksIHMgPSBtYXRoUm91bmQoaHN2LnMgKiAxMDApLCB2ID0gbWF0aFJvdW5kKGhzdi52ICogMTAwKTtcbiAgICAgICAgcmV0dXJuICh0aGlzLl9hID09IDEpID9cbiAgICAgICAgICBcImhzdihcIiAgKyBoICsgXCIsIFwiICsgcyArIFwiJSwgXCIgKyB2ICsgXCIlKVwiIDpcbiAgICAgICAgICBcImhzdmEoXCIgKyBoICsgXCIsIFwiICsgcyArIFwiJSwgXCIgKyB2ICsgXCIlLCBcIisgdGhpcy5fcm91bmRBICsgXCIpXCI7XG4gICAgfSxcbiAgICB0b0hzbDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBoc2wgPSByZ2JUb0hzbCh0aGlzLl9yLCB0aGlzLl9nLCB0aGlzLl9iKTtcbiAgICAgICAgcmV0dXJuIHsgaDogaHNsLmggKiAzNjAsIHM6IGhzbC5zLCBsOiBoc2wubCwgYTogdGhpcy5fYSB9O1xuICAgIH0sXG4gICAgdG9Ic2xTdHJpbmc6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgaHNsID0gcmdiVG9Ic2wodGhpcy5fciwgdGhpcy5fZywgdGhpcy5fYik7XG4gICAgICAgIHZhciBoID0gbWF0aFJvdW5kKGhzbC5oICogMzYwKSwgcyA9IG1hdGhSb3VuZChoc2wucyAqIDEwMCksIGwgPSBtYXRoUm91bmQoaHNsLmwgKiAxMDApO1xuICAgICAgICByZXR1cm4gKHRoaXMuX2EgPT0gMSkgP1xuICAgICAgICAgIFwiaHNsKFwiICArIGggKyBcIiwgXCIgKyBzICsgXCIlLCBcIiArIGwgKyBcIiUpXCIgOlxuICAgICAgICAgIFwiaHNsYShcIiArIGggKyBcIiwgXCIgKyBzICsgXCIlLCBcIiArIGwgKyBcIiUsIFwiKyB0aGlzLl9yb3VuZEEgKyBcIilcIjtcbiAgICB9LFxuICAgIHRvSGV4OiBmdW5jdGlvbihhbGxvdzNDaGFyKSB7XG4gICAgICAgIHJldHVybiByZ2JUb0hleCh0aGlzLl9yLCB0aGlzLl9nLCB0aGlzLl9iLCBhbGxvdzNDaGFyKTtcbiAgICB9LFxuICAgIHRvSGV4U3RyaW5nOiBmdW5jdGlvbihhbGxvdzNDaGFyKSB7XG4gICAgICAgIHJldHVybiAnIycgKyB0aGlzLnRvSGV4KGFsbG93M0NoYXIpO1xuICAgIH0sXG4gICAgdG9IZXg4OiBmdW5jdGlvbihhbGxvdzRDaGFyKSB7XG4gICAgICAgIHJldHVybiByZ2JhVG9IZXgodGhpcy5fciwgdGhpcy5fZywgdGhpcy5fYiwgdGhpcy5fYSwgYWxsb3c0Q2hhcik7XG4gICAgfSxcbiAgICB0b0hleDhTdHJpbmc6IGZ1bmN0aW9uKGFsbG93NENoYXIpIHtcbiAgICAgICAgcmV0dXJuICcjJyArIHRoaXMudG9IZXg4KGFsbG93NENoYXIpO1xuICAgIH0sXG4gICAgdG9SZ2I6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4geyByOiBtYXRoUm91bmQodGhpcy5fciksIGc6IG1hdGhSb3VuZCh0aGlzLl9nKSwgYjogbWF0aFJvdW5kKHRoaXMuX2IpLCBhOiB0aGlzLl9hIH07XG4gICAgfSxcbiAgICB0b1JnYlN0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5fYSA9PSAxKSA/XG4gICAgICAgICAgXCJyZ2IoXCIgICsgbWF0aFJvdW5kKHRoaXMuX3IpICsgXCIsIFwiICsgbWF0aFJvdW5kKHRoaXMuX2cpICsgXCIsIFwiICsgbWF0aFJvdW5kKHRoaXMuX2IpICsgXCIpXCIgOlxuICAgICAgICAgIFwicmdiYShcIiArIG1hdGhSb3VuZCh0aGlzLl9yKSArIFwiLCBcIiArIG1hdGhSb3VuZCh0aGlzLl9nKSArIFwiLCBcIiArIG1hdGhSb3VuZCh0aGlzLl9iKSArIFwiLCBcIiArIHRoaXMuX3JvdW5kQSArIFwiKVwiO1xuICAgIH0sXG4gICAgdG9QZXJjZW50YWdlUmdiOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHsgcjogbWF0aFJvdW5kKGJvdW5kMDEodGhpcy5fciwgMjU1KSAqIDEwMCkgKyBcIiVcIiwgZzogbWF0aFJvdW5kKGJvdW5kMDEodGhpcy5fZywgMjU1KSAqIDEwMCkgKyBcIiVcIiwgYjogbWF0aFJvdW5kKGJvdW5kMDEodGhpcy5fYiwgMjU1KSAqIDEwMCkgKyBcIiVcIiwgYTogdGhpcy5fYSB9O1xuICAgIH0sXG4gICAgdG9QZXJjZW50YWdlUmdiU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLl9hID09IDEpID9cbiAgICAgICAgICBcInJnYihcIiAgKyBtYXRoUm91bmQoYm91bmQwMSh0aGlzLl9yLCAyNTUpICogMTAwKSArIFwiJSwgXCIgKyBtYXRoUm91bmQoYm91bmQwMSh0aGlzLl9nLCAyNTUpICogMTAwKSArIFwiJSwgXCIgKyBtYXRoUm91bmQoYm91bmQwMSh0aGlzLl9iLCAyNTUpICogMTAwKSArIFwiJSlcIiA6XG4gICAgICAgICAgXCJyZ2JhKFwiICsgbWF0aFJvdW5kKGJvdW5kMDEodGhpcy5fciwgMjU1KSAqIDEwMCkgKyBcIiUsIFwiICsgbWF0aFJvdW5kKGJvdW5kMDEodGhpcy5fZywgMjU1KSAqIDEwMCkgKyBcIiUsIFwiICsgbWF0aFJvdW5kKGJvdW5kMDEodGhpcy5fYiwgMjU1KSAqIDEwMCkgKyBcIiUsIFwiICsgdGhpcy5fcm91bmRBICsgXCIpXCI7XG4gICAgfSxcbiAgICB0b05hbWU6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fYSA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIFwidHJhbnNwYXJlbnRcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9hIDwgMSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGhleE5hbWVzW3JnYlRvSGV4KHRoaXMuX3IsIHRoaXMuX2csIHRoaXMuX2IsIHRydWUpXSB8fCBmYWxzZTtcbiAgICB9LFxuICAgIHRvRmlsdGVyOiBmdW5jdGlvbihzZWNvbmRDb2xvcikge1xuICAgICAgICB2YXIgaGV4OFN0cmluZyA9ICcjJyArIHJnYmFUb0FyZ2JIZXgodGhpcy5fciwgdGhpcy5fZywgdGhpcy5fYiwgdGhpcy5fYSk7XG4gICAgICAgIHZhciBzZWNvbmRIZXg4U3RyaW5nID0gaGV4OFN0cmluZztcbiAgICAgICAgdmFyIGdyYWRpZW50VHlwZSA9IHRoaXMuX2dyYWRpZW50VHlwZSA/IFwiR3JhZGllbnRUeXBlID0gMSwgXCIgOiBcIlwiO1xuXG4gICAgICAgIGlmIChzZWNvbmRDb2xvcikge1xuICAgICAgICAgICAgdmFyIHMgPSB0aW55Y29sb3Ioc2Vjb25kQ29sb3IpO1xuICAgICAgICAgICAgc2Vjb25kSGV4OFN0cmluZyA9ICcjJyArIHJnYmFUb0FyZ2JIZXgocy5fciwgcy5fZywgcy5fYiwgcy5fYSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gXCJwcm9naWQ6RFhJbWFnZVRyYW5zZm9ybS5NaWNyb3NvZnQuZ3JhZGllbnQoXCIrZ3JhZGllbnRUeXBlK1wic3RhcnRDb2xvcnN0cj1cIitoZXg4U3RyaW5nK1wiLGVuZENvbG9yc3RyPVwiK3NlY29uZEhleDhTdHJpbmcrXCIpXCI7XG4gICAgfSxcbiAgICB0b1N0cmluZzogZnVuY3Rpb24oZm9ybWF0KSB7XG4gICAgICAgIHZhciBmb3JtYXRTZXQgPSAhIWZvcm1hdDtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0IHx8IHRoaXMuX2Zvcm1hdDtcblxuICAgICAgICB2YXIgZm9ybWF0dGVkU3RyaW5nID0gZmFsc2U7XG4gICAgICAgIHZhciBoYXNBbHBoYSA9IHRoaXMuX2EgPCAxICYmIHRoaXMuX2EgPj0gMDtcbiAgICAgICAgdmFyIG5lZWRzQWxwaGFGb3JtYXQgPSAhZm9ybWF0U2V0ICYmIGhhc0FscGhhICYmIChmb3JtYXQgPT09IFwiaGV4XCIgfHwgZm9ybWF0ID09PSBcImhleDZcIiB8fCBmb3JtYXQgPT09IFwiaGV4M1wiIHx8IGZvcm1hdCA9PT0gXCJoZXg0XCIgfHwgZm9ybWF0ID09PSBcImhleDhcIiB8fCBmb3JtYXQgPT09IFwibmFtZVwiKTtcblxuICAgICAgICBpZiAobmVlZHNBbHBoYUZvcm1hdCkge1xuICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIGZvciBcInRyYW5zcGFyZW50XCIsIGFsbCBvdGhlciBub24tYWxwaGEgZm9ybWF0c1xuICAgICAgICAgICAgLy8gd2lsbCByZXR1cm4gcmdiYSB3aGVuIHRoZXJlIGlzIHRyYW5zcGFyZW5jeS5cbiAgICAgICAgICAgIGlmIChmb3JtYXQgPT09IFwibmFtZVwiICYmIHRoaXMuX2EgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50b05hbWUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvUmdiU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gXCJyZ2JcIikge1xuICAgICAgICAgICAgZm9ybWF0dGVkU3RyaW5nID0gdGhpcy50b1JnYlN0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmb3JtYXQgPT09IFwicHJnYlwiKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZWRTdHJpbmcgPSB0aGlzLnRvUGVyY2VudGFnZVJnYlN0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmb3JtYXQgPT09IFwiaGV4XCIgfHwgZm9ybWF0ID09PSBcImhleDZcIikge1xuICAgICAgICAgICAgZm9ybWF0dGVkU3RyaW5nID0gdGhpcy50b0hleFN0cmluZygpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmb3JtYXQgPT09IFwiaGV4M1wiKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZWRTdHJpbmcgPSB0aGlzLnRvSGV4U3RyaW5nKHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmb3JtYXQgPT09IFwiaGV4NFwiKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZWRTdHJpbmcgPSB0aGlzLnRvSGV4OFN0cmluZyh0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZm9ybWF0ID09PSBcImhleDhcIikge1xuICAgICAgICAgICAgZm9ybWF0dGVkU3RyaW5nID0gdGhpcy50b0hleDhTdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZm9ybWF0ID09PSBcIm5hbWVcIikge1xuICAgICAgICAgICAgZm9ybWF0dGVkU3RyaW5nID0gdGhpcy50b05hbWUoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZm9ybWF0ID09PSBcImhzbFwiKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZWRTdHJpbmcgPSB0aGlzLnRvSHNsU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gXCJoc3ZcIikge1xuICAgICAgICAgICAgZm9ybWF0dGVkU3RyaW5nID0gdGhpcy50b0hzdlN0cmluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZvcm1hdHRlZFN0cmluZyB8fCB0aGlzLnRvSGV4U3RyaW5nKCk7XG4gICAgfSxcbiAgICBjbG9uZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aW55Y29sb3IodGhpcy50b1N0cmluZygpKTtcbiAgICB9LFxuXG4gICAgX2FwcGx5TW9kaWZpY2F0aW9uOiBmdW5jdGlvbihmbiwgYXJncykge1xuICAgICAgICB2YXIgY29sb3IgPSBmbi5hcHBseShudWxsLCBbdGhpc10uY29uY2F0KFtdLnNsaWNlLmNhbGwoYXJncykpKTtcbiAgICAgICAgdGhpcy5fciA9IGNvbG9yLl9yO1xuICAgICAgICB0aGlzLl9nID0gY29sb3IuX2c7XG4gICAgICAgIHRoaXMuX2IgPSBjb2xvci5fYjtcbiAgICAgICAgdGhpcy5zZXRBbHBoYShjb2xvci5fYSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgbGlnaHRlbjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseU1vZGlmaWNhdGlvbihsaWdodGVuLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgYnJpZ2h0ZW46IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlNb2RpZmljYXRpb24oYnJpZ2h0ZW4sIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICBkYXJrZW46IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlNb2RpZmljYXRpb24oZGFya2VuLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgZGVzYXR1cmF0ZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseU1vZGlmaWNhdGlvbihkZXNhdHVyYXRlLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgc2F0dXJhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlNb2RpZmljYXRpb24oc2F0dXJhdGUsIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICBncmV5c2NhbGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlNb2RpZmljYXRpb24oZ3JleXNjYWxlLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgc3BpbjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseU1vZGlmaWNhdGlvbihzcGluLCBhcmd1bWVudHMpO1xuICAgIH0sXG5cbiAgICBfYXBwbHlDb21iaW5hdGlvbjogZnVuY3Rpb24oZm4sIGFyZ3MpIHtcbiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KG51bGwsIFt0aGlzXS5jb25jYXQoW10uc2xpY2UuY2FsbChhcmdzKSkpO1xuICAgIH0sXG4gICAgYW5hbG9nb3VzOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5Q29tYmluYXRpb24oYW5hbG9nb3VzLCBhcmd1bWVudHMpO1xuICAgIH0sXG4gICAgY29tcGxlbWVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUNvbWJpbmF0aW9uKGNvbXBsZW1lbnQsIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICBtb25vY2hyb21hdGljOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5Q29tYmluYXRpb24obW9ub2Nocm9tYXRpYywgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHNwbGl0Y29tcGxlbWVudDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUNvbWJpbmF0aW9uKHNwbGl0Y29tcGxlbWVudCwgYXJndW1lbnRzKTtcbiAgICB9LFxuICAgIHRyaWFkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5Q29tYmluYXRpb24odHJpYWQsIGFyZ3VtZW50cyk7XG4gICAgfSxcbiAgICB0ZXRyYWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlDb21iaW5hdGlvbih0ZXRyYWQsIGFyZ3VtZW50cyk7XG4gICAgfVxufTtcblxuLy8gSWYgaW5wdXQgaXMgYW4gb2JqZWN0LCBmb3JjZSAxIGludG8gXCIxLjBcIiB0byBoYW5kbGUgcmF0aW9zIHByb3Blcmx5XG4vLyBTdHJpbmcgaW5wdXQgcmVxdWlyZXMgXCIxLjBcIiBhcyBpbnB1dCwgc28gMSB3aWxsIGJlIHRyZWF0ZWQgYXMgMVxudGlueWNvbG9yLmZyb21SYXRpbyA9IGZ1bmN0aW9uKGNvbG9yLCBvcHRzKSB7XG4gICAgaWYgKHR5cGVvZiBjb2xvciA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHZhciBuZXdDb2xvciA9IHt9O1xuICAgICAgICBmb3IgKHZhciBpIGluIGNvbG9yKSB7XG4gICAgICAgICAgICBpZiAoY29sb3IuaGFzT3duUHJvcGVydHkoaSkpIHtcbiAgICAgICAgICAgICAgICBpZiAoaSA9PT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Q29sb3JbaV0gPSBjb2xvcltpXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld0NvbG9yW2ldID0gY29udmVydFRvUGVyY2VudGFnZShjb2xvcltpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbG9yID0gbmV3Q29sb3I7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRpbnljb2xvcihjb2xvciwgb3B0cyk7XG59O1xuXG4vLyBHaXZlbiBhIHN0cmluZyBvciBvYmplY3QsIGNvbnZlcnQgdGhhdCBpbnB1dCB0byBSR0Jcbi8vIFBvc3NpYmxlIHN0cmluZyBpbnB1dHM6XG4vL1xuLy8gICAgIFwicmVkXCJcbi8vICAgICBcIiNmMDBcIiBvciBcImYwMFwiXG4vLyAgICAgXCIjZmYwMDAwXCIgb3IgXCJmZjAwMDBcIlxuLy8gICAgIFwiI2ZmMDAwMDAwXCIgb3IgXCJmZjAwMDAwMFwiXG4vLyAgICAgXCJyZ2IgMjU1IDAgMFwiIG9yIFwicmdiICgyNTUsIDAsIDApXCJcbi8vICAgICBcInJnYiAxLjAgMCAwXCIgb3IgXCJyZ2IgKDEsIDAsIDApXCJcbi8vICAgICBcInJnYmEgKDI1NSwgMCwgMCwgMSlcIiBvciBcInJnYmEgMjU1LCAwLCAwLCAxXCJcbi8vICAgICBcInJnYmEgKDEuMCwgMCwgMCwgMSlcIiBvciBcInJnYmEgMS4wLCAwLCAwLCAxXCJcbi8vICAgICBcImhzbCgwLCAxMDAlLCA1MCUpXCIgb3IgXCJoc2wgMCAxMDAlIDUwJVwiXG4vLyAgICAgXCJoc2xhKDAsIDEwMCUsIDUwJSwgMSlcIiBvciBcImhzbGEgMCAxMDAlIDUwJSwgMVwiXG4vLyAgICAgXCJoc3YoMCwgMTAwJSwgMTAwJSlcIiBvciBcImhzdiAwIDEwMCUgMTAwJVwiXG4vL1xuZnVuY3Rpb24gaW5wdXRUb1JHQihjb2xvcikge1xuXG4gICAgdmFyIHJnYiA9IHsgcjogMCwgZzogMCwgYjogMCB9O1xuICAgIHZhciBhID0gMTtcbiAgICB2YXIgcyA9IG51bGw7XG4gICAgdmFyIHYgPSBudWxsO1xuICAgIHZhciBsID0gbnVsbDtcbiAgICB2YXIgb2sgPSBmYWxzZTtcbiAgICB2YXIgZm9ybWF0ID0gZmFsc2U7XG5cbiAgICBpZiAodHlwZW9mIGNvbG9yID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgY29sb3IgPSBzdHJpbmdJbnB1dFRvT2JqZWN0KGNvbG9yKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGNvbG9yID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgaWYgKGlzVmFsaWRDU1NVbml0KGNvbG9yLnIpICYmIGlzVmFsaWRDU1NVbml0KGNvbG9yLmcpICYmIGlzVmFsaWRDU1NVbml0KGNvbG9yLmIpKSB7XG4gICAgICAgICAgICByZ2IgPSByZ2JUb1JnYihjb2xvci5yLCBjb2xvci5nLCBjb2xvci5iKTtcbiAgICAgICAgICAgIG9rID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvcm1hdCA9IFN0cmluZyhjb2xvci5yKS5zdWJzdHIoLTEpID09PSBcIiVcIiA/IFwicHJnYlwiIDogXCJyZ2JcIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpc1ZhbGlkQ1NTVW5pdChjb2xvci5oKSAmJiBpc1ZhbGlkQ1NTVW5pdChjb2xvci5zKSAmJiBpc1ZhbGlkQ1NTVW5pdChjb2xvci52KSkge1xuICAgICAgICAgICAgcyA9IGNvbnZlcnRUb1BlcmNlbnRhZ2UoY29sb3Iucyk7XG4gICAgICAgICAgICB2ID0gY29udmVydFRvUGVyY2VudGFnZShjb2xvci52KTtcbiAgICAgICAgICAgIHJnYiA9IGhzdlRvUmdiKGNvbG9yLmgsIHMsIHYpO1xuICAgICAgICAgICAgb2sgPSB0cnVlO1xuICAgICAgICAgICAgZm9ybWF0ID0gXCJoc3ZcIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpc1ZhbGlkQ1NTVW5pdChjb2xvci5oKSAmJiBpc1ZhbGlkQ1NTVW5pdChjb2xvci5zKSAmJiBpc1ZhbGlkQ1NTVW5pdChjb2xvci5sKSkge1xuICAgICAgICAgICAgcyA9IGNvbnZlcnRUb1BlcmNlbnRhZ2UoY29sb3Iucyk7XG4gICAgICAgICAgICBsID0gY29udmVydFRvUGVyY2VudGFnZShjb2xvci5sKTtcbiAgICAgICAgICAgIHJnYiA9IGhzbFRvUmdiKGNvbG9yLmgsIHMsIGwpO1xuICAgICAgICAgICAgb2sgPSB0cnVlO1xuICAgICAgICAgICAgZm9ybWF0ID0gXCJoc2xcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb2xvci5oYXNPd25Qcm9wZXJ0eShcImFcIikpIHtcbiAgICAgICAgICAgIGEgPSBjb2xvci5hO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYSA9IGJvdW5kQWxwaGEoYSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBvazogb2ssXG4gICAgICAgIGZvcm1hdDogY29sb3IuZm9ybWF0IHx8IGZvcm1hdCxcbiAgICAgICAgcjogbWF0aE1pbigyNTUsIG1hdGhNYXgocmdiLnIsIDApKSxcbiAgICAgICAgZzogbWF0aE1pbigyNTUsIG1hdGhNYXgocmdiLmcsIDApKSxcbiAgICAgICAgYjogbWF0aE1pbigyNTUsIG1hdGhNYXgocmdiLmIsIDApKSxcbiAgICAgICAgYTogYVxuICAgIH07XG59XG5cblxuLy8gQ29udmVyc2lvbiBGdW5jdGlvbnNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8vIGByZ2JUb0hzbGAsIGByZ2JUb0hzdmAsIGBoc2xUb1JnYmAsIGBoc3ZUb1JnYmAgbW9kaWZpZWQgZnJvbTpcbi8vIDxodHRwOi8vbWppamFja3Nvbi5jb20vMjAwOC8wMi9yZ2ItdG8taHNsLWFuZC1yZ2ItdG8taHN2LWNvbG9yLW1vZGVsLWNvbnZlcnNpb24tYWxnb3JpdGhtcy1pbi1qYXZhc2NyaXB0PlxuXG4vLyBgcmdiVG9SZ2JgXG4vLyBIYW5kbGUgYm91bmRzIC8gcGVyY2VudGFnZSBjaGVja2luZyB0byBjb25mb3JtIHRvIENTUyBjb2xvciBzcGVjXG4vLyA8aHR0cDovL3d3dy53My5vcmcvVFIvY3NzMy1jb2xvci8+XG4vLyAqQXNzdW1lczoqIHIsIGcsIGIgaW4gWzAsIDI1NV0gb3IgWzAsIDFdXG4vLyAqUmV0dXJuczoqIHsgciwgZywgYiB9IGluIFswLCAyNTVdXG5mdW5jdGlvbiByZ2JUb1JnYihyLCBnLCBiKXtcbiAgICByZXR1cm4ge1xuICAgICAgICByOiBib3VuZDAxKHIsIDI1NSkgKiAyNTUsXG4gICAgICAgIGc6IGJvdW5kMDEoZywgMjU1KSAqIDI1NSxcbiAgICAgICAgYjogYm91bmQwMShiLCAyNTUpICogMjU1XG4gICAgfTtcbn1cblxuLy8gYHJnYlRvSHNsYFxuLy8gQ29udmVydHMgYW4gUkdCIGNvbG9yIHZhbHVlIHRvIEhTTC5cbi8vICpBc3N1bWVzOiogciwgZywgYW5kIGIgYXJlIGNvbnRhaW5lZCBpbiBbMCwgMjU1XSBvciBbMCwgMV1cbi8vICpSZXR1cm5zOiogeyBoLCBzLCBsIH0gaW4gWzAsMV1cbmZ1bmN0aW9uIHJnYlRvSHNsKHIsIGcsIGIpIHtcblxuICAgIHIgPSBib3VuZDAxKHIsIDI1NSk7XG4gICAgZyA9IGJvdW5kMDEoZywgMjU1KTtcbiAgICBiID0gYm91bmQwMShiLCAyNTUpO1xuXG4gICAgdmFyIG1heCA9IG1hdGhNYXgociwgZywgYiksIG1pbiA9IG1hdGhNaW4ociwgZywgYik7XG4gICAgdmFyIGgsIHMsIGwgPSAobWF4ICsgbWluKSAvIDI7XG5cbiAgICBpZihtYXggPT0gbWluKSB7XG4gICAgICAgIGggPSBzID0gMDsgLy8gYWNocm9tYXRpY1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIGQgPSBtYXggLSBtaW47XG4gICAgICAgIHMgPSBsID4gMC41ID8gZCAvICgyIC0gbWF4IC0gbWluKSA6IGQgLyAobWF4ICsgbWluKTtcbiAgICAgICAgc3dpdGNoKG1heCkge1xuICAgICAgICAgICAgY2FzZSByOiBoID0gKGcgLSBiKSAvIGQgKyAoZyA8IGIgPyA2IDogMCk7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBnOiBoID0gKGIgLSByKSAvIGQgKyAyOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgYjogaCA9IChyIC0gZykgLyBkICsgNDsgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBoIC89IDY7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgaDogaCwgczogcywgbDogbCB9O1xufVxuXG4vLyBgaHNsVG9SZ2JgXG4vLyBDb252ZXJ0cyBhbiBIU0wgY29sb3IgdmFsdWUgdG8gUkdCLlxuLy8gKkFzc3VtZXM6KiBoIGlzIGNvbnRhaW5lZCBpbiBbMCwgMV0gb3IgWzAsIDM2MF0gYW5kIHMgYW5kIGwgYXJlIGNvbnRhaW5lZCBbMCwgMV0gb3IgWzAsIDEwMF1cbi8vICpSZXR1cm5zOiogeyByLCBnLCBiIH0gaW4gdGhlIHNldCBbMCwgMjU1XVxuZnVuY3Rpb24gaHNsVG9SZ2IoaCwgcywgbCkge1xuICAgIHZhciByLCBnLCBiO1xuXG4gICAgaCA9IGJvdW5kMDEoaCwgMzYwKTtcbiAgICBzID0gYm91bmQwMShzLCAxMDApO1xuICAgIGwgPSBib3VuZDAxKGwsIDEwMCk7XG5cbiAgICBmdW5jdGlvbiBodWUycmdiKHAsIHEsIHQpIHtcbiAgICAgICAgaWYodCA8IDApIHQgKz0gMTtcbiAgICAgICAgaWYodCA+IDEpIHQgLT0gMTtcbiAgICAgICAgaWYodCA8IDEvNikgcmV0dXJuIHAgKyAocSAtIHApICogNiAqIHQ7XG4gICAgICAgIGlmKHQgPCAxLzIpIHJldHVybiBxO1xuICAgICAgICBpZih0IDwgMi8zKSByZXR1cm4gcCArIChxIC0gcCkgKiAoMi8zIC0gdCkgKiA2O1xuICAgICAgICByZXR1cm4gcDtcbiAgICB9XG5cbiAgICBpZihzID09PSAwKSB7XG4gICAgICAgIHIgPSBnID0gYiA9IGw7IC8vIGFjaHJvbWF0aWNcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBxID0gbCA8IDAuNSA/IGwgKiAoMSArIHMpIDogbCArIHMgLSBsICogcztcbiAgICAgICAgdmFyIHAgPSAyICogbCAtIHE7XG4gICAgICAgIHIgPSBodWUycmdiKHAsIHEsIGggKyAxLzMpO1xuICAgICAgICBnID0gaHVlMnJnYihwLCBxLCBoKTtcbiAgICAgICAgYiA9IGh1ZTJyZ2IocCwgcSwgaCAtIDEvMyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgcjogciAqIDI1NSwgZzogZyAqIDI1NSwgYjogYiAqIDI1NSB9O1xufVxuXG4vLyBgcmdiVG9Ic3ZgXG4vLyBDb252ZXJ0cyBhbiBSR0IgY29sb3IgdmFsdWUgdG8gSFNWXG4vLyAqQXNzdW1lczoqIHIsIGcsIGFuZCBiIGFyZSBjb250YWluZWQgaW4gdGhlIHNldCBbMCwgMjU1XSBvciBbMCwgMV1cbi8vICpSZXR1cm5zOiogeyBoLCBzLCB2IH0gaW4gWzAsMV1cbmZ1bmN0aW9uIHJnYlRvSHN2KHIsIGcsIGIpIHtcblxuICAgIHIgPSBib3VuZDAxKHIsIDI1NSk7XG4gICAgZyA9IGJvdW5kMDEoZywgMjU1KTtcbiAgICBiID0gYm91bmQwMShiLCAyNTUpO1xuXG4gICAgdmFyIG1heCA9IG1hdGhNYXgociwgZywgYiksIG1pbiA9IG1hdGhNaW4ociwgZywgYik7XG4gICAgdmFyIGgsIHMsIHYgPSBtYXg7XG5cbiAgICB2YXIgZCA9IG1heCAtIG1pbjtcbiAgICBzID0gbWF4ID09PSAwID8gMCA6IGQgLyBtYXg7XG5cbiAgICBpZihtYXggPT0gbWluKSB7XG4gICAgICAgIGggPSAwOyAvLyBhY2hyb21hdGljXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBzd2l0Y2gobWF4KSB7XG4gICAgICAgICAgICBjYXNlIHI6IGggPSAoZyAtIGIpIC8gZCArIChnIDwgYiA/IDYgOiAwKTsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIGc6IGggPSAoYiAtIHIpIC8gZCArIDI7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBiOiBoID0gKHIgLSBnKSAvIGQgKyA0OyBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBoIC89IDY7XG4gICAgfVxuICAgIHJldHVybiB7IGg6IGgsIHM6IHMsIHY6IHYgfTtcbn1cblxuLy8gYGhzdlRvUmdiYFxuLy8gQ29udmVydHMgYW4gSFNWIGNvbG9yIHZhbHVlIHRvIFJHQi5cbi8vICpBc3N1bWVzOiogaCBpcyBjb250YWluZWQgaW4gWzAsIDFdIG9yIFswLCAzNjBdIGFuZCBzIGFuZCB2IGFyZSBjb250YWluZWQgaW4gWzAsIDFdIG9yIFswLCAxMDBdXG4vLyAqUmV0dXJuczoqIHsgciwgZywgYiB9IGluIHRoZSBzZXQgWzAsIDI1NV1cbiBmdW5jdGlvbiBoc3ZUb1JnYihoLCBzLCB2KSB7XG5cbiAgICBoID0gYm91bmQwMShoLCAzNjApICogNjtcbiAgICBzID0gYm91bmQwMShzLCAxMDApO1xuICAgIHYgPSBib3VuZDAxKHYsIDEwMCk7XG5cbiAgICB2YXIgaSA9IE1hdGguZmxvb3IoaCksXG4gICAgICAgIGYgPSBoIC0gaSxcbiAgICAgICAgcCA9IHYgKiAoMSAtIHMpLFxuICAgICAgICBxID0gdiAqICgxIC0gZiAqIHMpLFxuICAgICAgICB0ID0gdiAqICgxIC0gKDEgLSBmKSAqIHMpLFxuICAgICAgICBtb2QgPSBpICUgNixcbiAgICAgICAgciA9IFt2LCBxLCBwLCBwLCB0LCB2XVttb2RdLFxuICAgICAgICBnID0gW3QsIHYsIHYsIHEsIHAsIHBdW21vZF0sXG4gICAgICAgIGIgPSBbcCwgcCwgdCwgdiwgdiwgcV1bbW9kXTtcblxuICAgIHJldHVybiB7IHI6IHIgKiAyNTUsIGc6IGcgKiAyNTUsIGI6IGIgKiAyNTUgfTtcbn1cblxuLy8gYHJnYlRvSGV4YFxuLy8gQ29udmVydHMgYW4gUkdCIGNvbG9yIHRvIGhleFxuLy8gQXNzdW1lcyByLCBnLCBhbmQgYiBhcmUgY29udGFpbmVkIGluIHRoZSBzZXQgWzAsIDI1NV1cbi8vIFJldHVybnMgYSAzIG9yIDYgY2hhcmFjdGVyIGhleFxuZnVuY3Rpb24gcmdiVG9IZXgociwgZywgYiwgYWxsb3czQ2hhcikge1xuXG4gICAgdmFyIGhleCA9IFtcbiAgICAgICAgcGFkMihtYXRoUm91bmQocikudG9TdHJpbmcoMTYpKSxcbiAgICAgICAgcGFkMihtYXRoUm91bmQoZykudG9TdHJpbmcoMTYpKSxcbiAgICAgICAgcGFkMihtYXRoUm91bmQoYikudG9TdHJpbmcoMTYpKVxuICAgIF07XG5cbiAgICAvLyBSZXR1cm4gYSAzIGNoYXJhY3RlciBoZXggaWYgcG9zc2libGVcbiAgICBpZiAoYWxsb3czQ2hhciAmJiBoZXhbMF0uY2hhckF0KDApID09IGhleFswXS5jaGFyQXQoMSkgJiYgaGV4WzFdLmNoYXJBdCgwKSA9PSBoZXhbMV0uY2hhckF0KDEpICYmIGhleFsyXS5jaGFyQXQoMCkgPT0gaGV4WzJdLmNoYXJBdCgxKSkge1xuICAgICAgICByZXR1cm4gaGV4WzBdLmNoYXJBdCgwKSArIGhleFsxXS5jaGFyQXQoMCkgKyBoZXhbMl0uY2hhckF0KDApO1xuICAgIH1cblxuICAgIHJldHVybiBoZXguam9pbihcIlwiKTtcbn1cblxuLy8gYHJnYmFUb0hleGBcbi8vIENvbnZlcnRzIGFuIFJHQkEgY29sb3IgcGx1cyBhbHBoYSB0cmFuc3BhcmVuY3kgdG8gaGV4XG4vLyBBc3N1bWVzIHIsIGcsIGIgYXJlIGNvbnRhaW5lZCBpbiB0aGUgc2V0IFswLCAyNTVdIGFuZFxuLy8gYSBpbiBbMCwgMV0uIFJldHVybnMgYSA0IG9yIDggY2hhcmFjdGVyIHJnYmEgaGV4XG5mdW5jdGlvbiByZ2JhVG9IZXgociwgZywgYiwgYSwgYWxsb3c0Q2hhcikge1xuXG4gICAgdmFyIGhleCA9IFtcbiAgICAgICAgcGFkMihtYXRoUm91bmQocikudG9TdHJpbmcoMTYpKSxcbiAgICAgICAgcGFkMihtYXRoUm91bmQoZykudG9TdHJpbmcoMTYpKSxcbiAgICAgICAgcGFkMihtYXRoUm91bmQoYikudG9TdHJpbmcoMTYpKSxcbiAgICAgICAgcGFkMihjb252ZXJ0RGVjaW1hbFRvSGV4KGEpKVxuICAgIF07XG5cbiAgICAvLyBSZXR1cm4gYSA0IGNoYXJhY3RlciBoZXggaWYgcG9zc2libGVcbiAgICBpZiAoYWxsb3c0Q2hhciAmJiBoZXhbMF0uY2hhckF0KDApID09IGhleFswXS5jaGFyQXQoMSkgJiYgaGV4WzFdLmNoYXJBdCgwKSA9PSBoZXhbMV0uY2hhckF0KDEpICYmIGhleFsyXS5jaGFyQXQoMCkgPT0gaGV4WzJdLmNoYXJBdCgxKSAmJiBoZXhbM10uY2hhckF0KDApID09IGhleFszXS5jaGFyQXQoMSkpIHtcbiAgICAgICAgcmV0dXJuIGhleFswXS5jaGFyQXQoMCkgKyBoZXhbMV0uY2hhckF0KDApICsgaGV4WzJdLmNoYXJBdCgwKSArIGhleFszXS5jaGFyQXQoMCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGhleC5qb2luKFwiXCIpO1xufVxuXG4vLyBgcmdiYVRvQXJnYkhleGBcbi8vIENvbnZlcnRzIGFuIFJHQkEgY29sb3IgdG8gYW4gQVJHQiBIZXg4IHN0cmluZ1xuLy8gUmFyZWx5IHVzZWQsIGJ1dCByZXF1aXJlZCBmb3IgXCJ0b0ZpbHRlcigpXCJcbmZ1bmN0aW9uIHJnYmFUb0FyZ2JIZXgociwgZywgYiwgYSkge1xuXG4gICAgdmFyIGhleCA9IFtcbiAgICAgICAgcGFkMihjb252ZXJ0RGVjaW1hbFRvSGV4KGEpKSxcbiAgICAgICAgcGFkMihtYXRoUm91bmQocikudG9TdHJpbmcoMTYpKSxcbiAgICAgICAgcGFkMihtYXRoUm91bmQoZykudG9TdHJpbmcoMTYpKSxcbiAgICAgICAgcGFkMihtYXRoUm91bmQoYikudG9TdHJpbmcoMTYpKVxuICAgIF07XG5cbiAgICByZXR1cm4gaGV4LmpvaW4oXCJcIik7XG59XG5cbi8vIGBlcXVhbHNgXG4vLyBDYW4gYmUgY2FsbGVkIHdpdGggYW55IHRpbnljb2xvciBpbnB1dFxudGlueWNvbG9yLmVxdWFscyA9IGZ1bmN0aW9uIChjb2xvcjEsIGNvbG9yMikge1xuICAgIGlmICghY29sb3IxIHx8ICFjb2xvcjIpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgcmV0dXJuIHRpbnljb2xvcihjb2xvcjEpLnRvUmdiU3RyaW5nKCkgPT0gdGlueWNvbG9yKGNvbG9yMikudG9SZ2JTdHJpbmcoKTtcbn07XG5cbnRpbnljb2xvci5yYW5kb20gPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGlueWNvbG9yLmZyb21SYXRpbyh7XG4gICAgICAgIHI6IG1hdGhSYW5kb20oKSxcbiAgICAgICAgZzogbWF0aFJhbmRvbSgpLFxuICAgICAgICBiOiBtYXRoUmFuZG9tKClcbiAgICB9KTtcbn07XG5cblxuLy8gTW9kaWZpY2F0aW9uIEZ1bmN0aW9uc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gVGhhbmtzIHRvIGxlc3MuanMgZm9yIHNvbWUgb2YgdGhlIGJhc2ljcyBoZXJlXG4vLyA8aHR0cHM6Ly9naXRodWIuY29tL2Nsb3VkaGVhZC9sZXNzLmpzL2Jsb2IvbWFzdGVyL2xpYi9sZXNzL2Z1bmN0aW9ucy5qcz5cblxuZnVuY3Rpb24gZGVzYXR1cmF0ZShjb2xvciwgYW1vdW50KSB7XG4gICAgYW1vdW50ID0gKGFtb3VudCA9PT0gMCkgPyAwIDogKGFtb3VudCB8fCAxMCk7XG4gICAgdmFyIGhzbCA9IHRpbnljb2xvcihjb2xvcikudG9Ic2woKTtcbiAgICBoc2wucyAtPSBhbW91bnQgLyAxMDA7XG4gICAgaHNsLnMgPSBjbGFtcDAxKGhzbC5zKTtcbiAgICByZXR1cm4gdGlueWNvbG9yKGhzbCk7XG59XG5cbmZ1bmN0aW9uIHNhdHVyYXRlKGNvbG9yLCBhbW91bnQpIHtcbiAgICBhbW91bnQgPSAoYW1vdW50ID09PSAwKSA/IDAgOiAoYW1vdW50IHx8IDEwKTtcbiAgICB2YXIgaHNsID0gdGlueWNvbG9yKGNvbG9yKS50b0hzbCgpO1xuICAgIGhzbC5zICs9IGFtb3VudCAvIDEwMDtcbiAgICBoc2wucyA9IGNsYW1wMDEoaHNsLnMpO1xuICAgIHJldHVybiB0aW55Y29sb3IoaHNsKTtcbn1cblxuZnVuY3Rpb24gZ3JleXNjYWxlKGNvbG9yKSB7XG4gICAgcmV0dXJuIHRpbnljb2xvcihjb2xvcikuZGVzYXR1cmF0ZSgxMDApO1xufVxuXG5mdW5jdGlvbiBsaWdodGVuIChjb2xvciwgYW1vdW50KSB7XG4gICAgYW1vdW50ID0gKGFtb3VudCA9PT0gMCkgPyAwIDogKGFtb3VudCB8fCAxMCk7XG4gICAgdmFyIGhzbCA9IHRpbnljb2xvcihjb2xvcikudG9Ic2woKTtcbiAgICBoc2wubCArPSBhbW91bnQgLyAxMDA7XG4gICAgaHNsLmwgPSBjbGFtcDAxKGhzbC5sKTtcbiAgICByZXR1cm4gdGlueWNvbG9yKGhzbCk7XG59XG5cbmZ1bmN0aW9uIGJyaWdodGVuKGNvbG9yLCBhbW91bnQpIHtcbiAgICBhbW91bnQgPSAoYW1vdW50ID09PSAwKSA/IDAgOiAoYW1vdW50IHx8IDEwKTtcbiAgICB2YXIgcmdiID0gdGlueWNvbG9yKGNvbG9yKS50b1JnYigpO1xuICAgIHJnYi5yID0gbWF0aE1heCgwLCBtYXRoTWluKDI1NSwgcmdiLnIgLSBtYXRoUm91bmQoMjU1ICogLSAoYW1vdW50IC8gMTAwKSkpKTtcbiAgICByZ2IuZyA9IG1hdGhNYXgoMCwgbWF0aE1pbigyNTUsIHJnYi5nIC0gbWF0aFJvdW5kKDI1NSAqIC0gKGFtb3VudCAvIDEwMCkpKSk7XG4gICAgcmdiLmIgPSBtYXRoTWF4KDAsIG1hdGhNaW4oMjU1LCByZ2IuYiAtIG1hdGhSb3VuZCgyNTUgKiAtIChhbW91bnQgLyAxMDApKSkpO1xuICAgIHJldHVybiB0aW55Y29sb3IocmdiKTtcbn1cblxuZnVuY3Rpb24gZGFya2VuIChjb2xvciwgYW1vdW50KSB7XG4gICAgYW1vdW50ID0gKGFtb3VudCA9PT0gMCkgPyAwIDogKGFtb3VudCB8fCAxMCk7XG4gICAgdmFyIGhzbCA9IHRpbnljb2xvcihjb2xvcikudG9Ic2woKTtcbiAgICBoc2wubCAtPSBhbW91bnQgLyAxMDA7XG4gICAgaHNsLmwgPSBjbGFtcDAxKGhzbC5sKTtcbiAgICByZXR1cm4gdGlueWNvbG9yKGhzbCk7XG59XG5cbi8vIFNwaW4gdGFrZXMgYSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSBhbW91bnQgd2l0aGluIFstMzYwLCAzNjBdIGluZGljYXRpbmcgdGhlIGNoYW5nZSBvZiBodWUuXG4vLyBWYWx1ZXMgb3V0c2lkZSBvZiB0aGlzIHJhbmdlIHdpbGwgYmUgd3JhcHBlZCBpbnRvIHRoaXMgcmFuZ2UuXG5mdW5jdGlvbiBzcGluKGNvbG9yLCBhbW91bnQpIHtcbiAgICB2YXIgaHNsID0gdGlueWNvbG9yKGNvbG9yKS50b0hzbCgpO1xuICAgIHZhciBodWUgPSAoaHNsLmggKyBhbW91bnQpICUgMzYwO1xuICAgIGhzbC5oID0gaHVlIDwgMCA/IDM2MCArIGh1ZSA6IGh1ZTtcbiAgICByZXR1cm4gdGlueWNvbG9yKGhzbCk7XG59XG5cbi8vIENvbWJpbmF0aW9uIEZ1bmN0aW9uc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBUaGFua3MgdG8galF1ZXJ5IHhDb2xvciBmb3Igc29tZSBvZiB0aGUgaWRlYXMgYmVoaW5kIHRoZXNlXG4vLyA8aHR0cHM6Ly9naXRodWIuY29tL2luZnVzaW9uL2pRdWVyeS14Y29sb3IvYmxvYi9tYXN0ZXIvanF1ZXJ5Lnhjb2xvci5qcz5cblxuZnVuY3Rpb24gY29tcGxlbWVudChjb2xvcikge1xuICAgIHZhciBoc2wgPSB0aW55Y29sb3IoY29sb3IpLnRvSHNsKCk7XG4gICAgaHNsLmggPSAoaHNsLmggKyAxODApICUgMzYwO1xuICAgIHJldHVybiB0aW55Y29sb3IoaHNsKTtcbn1cblxuZnVuY3Rpb24gdHJpYWQoY29sb3IpIHtcbiAgICB2YXIgaHNsID0gdGlueWNvbG9yKGNvbG9yKS50b0hzbCgpO1xuICAgIHZhciBoID0gaHNsLmg7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgdGlueWNvbG9yKGNvbG9yKSxcbiAgICAgICAgdGlueWNvbG9yKHsgaDogKGggKyAxMjApICUgMzYwLCBzOiBoc2wucywgbDogaHNsLmwgfSksXG4gICAgICAgIHRpbnljb2xvcih7IGg6IChoICsgMjQwKSAlIDM2MCwgczogaHNsLnMsIGw6IGhzbC5sIH0pXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gdGV0cmFkKGNvbG9yKSB7XG4gICAgdmFyIGhzbCA9IHRpbnljb2xvcihjb2xvcikudG9Ic2woKTtcbiAgICB2YXIgaCA9IGhzbC5oO1xuICAgIHJldHVybiBbXG4gICAgICAgIHRpbnljb2xvcihjb2xvciksXG4gICAgICAgIHRpbnljb2xvcih7IGg6IChoICsgOTApICUgMzYwLCBzOiBoc2wucywgbDogaHNsLmwgfSksXG4gICAgICAgIHRpbnljb2xvcih7IGg6IChoICsgMTgwKSAlIDM2MCwgczogaHNsLnMsIGw6IGhzbC5sIH0pLFxuICAgICAgICB0aW55Y29sb3IoeyBoOiAoaCArIDI3MCkgJSAzNjAsIHM6IGhzbC5zLCBsOiBoc2wubCB9KVxuICAgIF07XG59XG5cbmZ1bmN0aW9uIHNwbGl0Y29tcGxlbWVudChjb2xvcikge1xuICAgIHZhciBoc2wgPSB0aW55Y29sb3IoY29sb3IpLnRvSHNsKCk7XG4gICAgdmFyIGggPSBoc2wuaDtcbiAgICByZXR1cm4gW1xuICAgICAgICB0aW55Y29sb3IoY29sb3IpLFxuICAgICAgICB0aW55Y29sb3IoeyBoOiAoaCArIDcyKSAlIDM2MCwgczogaHNsLnMsIGw6IGhzbC5sfSksXG4gICAgICAgIHRpbnljb2xvcih7IGg6IChoICsgMjE2KSAlIDM2MCwgczogaHNsLnMsIGw6IGhzbC5sfSlcbiAgICBdO1xufVxuXG5mdW5jdGlvbiBhbmFsb2dvdXMoY29sb3IsIHJlc3VsdHMsIHNsaWNlcykge1xuICAgIHJlc3VsdHMgPSByZXN1bHRzIHx8IDY7XG4gICAgc2xpY2VzID0gc2xpY2VzIHx8IDMwO1xuXG4gICAgdmFyIGhzbCA9IHRpbnljb2xvcihjb2xvcikudG9Ic2woKTtcbiAgICB2YXIgcGFydCA9IDM2MCAvIHNsaWNlcztcbiAgICB2YXIgcmV0ID0gW3Rpbnljb2xvcihjb2xvcildO1xuXG4gICAgZm9yIChoc2wuaCA9ICgoaHNsLmggLSAocGFydCAqIHJlc3VsdHMgPj4gMSkpICsgNzIwKSAlIDM2MDsgLS1yZXN1bHRzOyApIHtcbiAgICAgICAgaHNsLmggPSAoaHNsLmggKyBwYXJ0KSAlIDM2MDtcbiAgICAgICAgcmV0LnB1c2godGlueWNvbG9yKGhzbCkpO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBtb25vY2hyb21hdGljKGNvbG9yLCByZXN1bHRzKSB7XG4gICAgcmVzdWx0cyA9IHJlc3VsdHMgfHwgNjtcbiAgICB2YXIgaHN2ID0gdGlueWNvbG9yKGNvbG9yKS50b0hzdigpO1xuICAgIHZhciBoID0gaHN2LmgsIHMgPSBoc3YucywgdiA9IGhzdi52O1xuICAgIHZhciByZXQgPSBbXTtcbiAgICB2YXIgbW9kaWZpY2F0aW9uID0gMSAvIHJlc3VsdHM7XG5cbiAgICB3aGlsZSAocmVzdWx0cy0tKSB7XG4gICAgICAgIHJldC5wdXNoKHRpbnljb2xvcih7IGg6IGgsIHM6IHMsIHY6IHZ9KSk7XG4gICAgICAgIHYgPSAodiArIG1vZGlmaWNhdGlvbikgJSAxO1xuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG59XG5cbi8vIFV0aWxpdHkgRnVuY3Rpb25zXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxudGlueWNvbG9yLm1peCA9IGZ1bmN0aW9uKGNvbG9yMSwgY29sb3IyLCBhbW91bnQpIHtcbiAgICBhbW91bnQgPSAoYW1vdW50ID09PSAwKSA/IDAgOiAoYW1vdW50IHx8IDUwKTtcblxuICAgIHZhciByZ2IxID0gdGlueWNvbG9yKGNvbG9yMSkudG9SZ2IoKTtcbiAgICB2YXIgcmdiMiA9IHRpbnljb2xvcihjb2xvcjIpLnRvUmdiKCk7XG5cbiAgICB2YXIgcCA9IGFtb3VudCAvIDEwMDtcblxuICAgIHZhciByZ2JhID0ge1xuICAgICAgICByOiAoKHJnYjIuciAtIHJnYjEucikgKiBwKSArIHJnYjEucixcbiAgICAgICAgZzogKChyZ2IyLmcgLSByZ2IxLmcpICogcCkgKyByZ2IxLmcsXG4gICAgICAgIGI6ICgocmdiMi5iIC0gcmdiMS5iKSAqIHApICsgcmdiMS5iLFxuICAgICAgICBhOiAoKHJnYjIuYSAtIHJnYjEuYSkgKiBwKSArIHJnYjEuYVxuICAgIH07XG5cbiAgICByZXR1cm4gdGlueWNvbG9yKHJnYmEpO1xufTtcblxuXG4vLyBSZWFkYWJpbGl0eSBGdW5jdGlvbnNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gPGh0dHA6Ly93d3cudzMub3JnL1RSLzIwMDgvUkVDLVdDQUcyMC0yMDA4MTIxMS8jY29udHJhc3QtcmF0aW9kZWYgKFdDQUcgVmVyc2lvbiAyKVxuXG4vLyBgY29udHJhc3RgXG4vLyBBbmFseXplIHRoZSAyIGNvbG9ycyBhbmQgcmV0dXJucyB0aGUgY29sb3IgY29udHJhc3QgZGVmaW5lZCBieSAoV0NBRyBWZXJzaW9uIDIpXG50aW55Y29sb3IucmVhZGFiaWxpdHkgPSBmdW5jdGlvbihjb2xvcjEsIGNvbG9yMikge1xuICAgIHZhciBjMSA9IHRpbnljb2xvcihjb2xvcjEpO1xuICAgIHZhciBjMiA9IHRpbnljb2xvcihjb2xvcjIpO1xuICAgIHJldHVybiAoTWF0aC5tYXgoYzEuZ2V0THVtaW5hbmNlKCksYzIuZ2V0THVtaW5hbmNlKCkpKzAuMDUpIC8gKE1hdGgubWluKGMxLmdldEx1bWluYW5jZSgpLGMyLmdldEx1bWluYW5jZSgpKSswLjA1KTtcbn07XG5cbi8vIGBpc1JlYWRhYmxlYFxuLy8gRW5zdXJlIHRoYXQgZm9yZWdyb3VuZCBhbmQgYmFja2dyb3VuZCBjb2xvciBjb21iaW5hdGlvbnMgbWVldCBXQ0FHMiBndWlkZWxpbmVzLlxuLy8gVGhlIHRoaXJkIGFyZ3VtZW50IGlzIGFuIG9wdGlvbmFsIE9iamVjdC5cbi8vICAgICAgdGhlICdsZXZlbCcgcHJvcGVydHkgc3RhdGVzICdBQScgb3IgJ0FBQScgLSBpZiBtaXNzaW5nIG9yIGludmFsaWQsIGl0IGRlZmF1bHRzIHRvICdBQSc7XG4vLyAgICAgIHRoZSAnc2l6ZScgcHJvcGVydHkgc3RhdGVzICdsYXJnZScgb3IgJ3NtYWxsJyAtIGlmIG1pc3Npbmcgb3IgaW52YWxpZCwgaXQgZGVmYXVsdHMgdG8gJ3NtYWxsJy5cbi8vIElmIHRoZSBlbnRpcmUgb2JqZWN0IGlzIGFic2VudCwgaXNSZWFkYWJsZSBkZWZhdWx0cyB0byB7bGV2ZWw6XCJBQVwiLHNpemU6XCJzbWFsbFwifS5cblxuLy8gKkV4YW1wbGUqXG4vLyAgICB0aW55Y29sb3IuaXNSZWFkYWJsZShcIiMwMDBcIiwgXCIjMTExXCIpID0+IGZhbHNlXG4vLyAgICB0aW55Y29sb3IuaXNSZWFkYWJsZShcIiMwMDBcIiwgXCIjMTExXCIse2xldmVsOlwiQUFcIixzaXplOlwibGFyZ2VcIn0pID0+IGZhbHNlXG50aW55Y29sb3IuaXNSZWFkYWJsZSA9IGZ1bmN0aW9uKGNvbG9yMSwgY29sb3IyLCB3Y2FnMikge1xuICAgIHZhciByZWFkYWJpbGl0eSA9IHRpbnljb2xvci5yZWFkYWJpbGl0eShjb2xvcjEsIGNvbG9yMik7XG4gICAgdmFyIHdjYWcyUGFybXMsIG91dDtcblxuICAgIG91dCA9IGZhbHNlO1xuXG4gICAgd2NhZzJQYXJtcyA9IHZhbGlkYXRlV0NBRzJQYXJtcyh3Y2FnMik7XG4gICAgc3dpdGNoICh3Y2FnMlBhcm1zLmxldmVsICsgd2NhZzJQYXJtcy5zaXplKSB7XG4gICAgICAgIGNhc2UgXCJBQXNtYWxsXCI6XG4gICAgICAgIGNhc2UgXCJBQUFsYXJnZVwiOlxuICAgICAgICAgICAgb3V0ID0gcmVhZGFiaWxpdHkgPj0gNC41O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJBQWxhcmdlXCI6XG4gICAgICAgICAgICBvdXQgPSByZWFkYWJpbGl0eSA+PSAzO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJBQUFzbWFsbFwiOlxuICAgICAgICAgICAgb3V0ID0gcmVhZGFiaWxpdHkgPj0gNztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xuXG59O1xuXG4vLyBgbW9zdFJlYWRhYmxlYFxuLy8gR2l2ZW4gYSBiYXNlIGNvbG9yIGFuZCBhIGxpc3Qgb2YgcG9zc2libGUgZm9yZWdyb3VuZCBvciBiYWNrZ3JvdW5kXG4vLyBjb2xvcnMgZm9yIHRoYXQgYmFzZSwgcmV0dXJucyB0aGUgbW9zdCByZWFkYWJsZSBjb2xvci5cbi8vIE9wdGlvbmFsbHkgcmV0dXJucyBCbGFjayBvciBXaGl0ZSBpZiB0aGUgbW9zdCByZWFkYWJsZSBjb2xvciBpcyB1bnJlYWRhYmxlLlxuLy8gKkV4YW1wbGUqXG4vLyAgICB0aW55Y29sb3IubW9zdFJlYWRhYmxlKHRpbnljb2xvci5tb3N0UmVhZGFibGUoXCIjMTIzXCIsIFtcIiMxMjRcIiwgXCIjMTI1XCJdLHtpbmNsdWRlRmFsbGJhY2tDb2xvcnM6ZmFsc2V9KS50b0hleFN0cmluZygpOyAvLyBcIiMxMTIyNTVcIlxuLy8gICAgdGlueWNvbG9yLm1vc3RSZWFkYWJsZSh0aW55Y29sb3IubW9zdFJlYWRhYmxlKFwiIzEyM1wiLCBbXCIjMTI0XCIsIFwiIzEyNVwiXSx7aW5jbHVkZUZhbGxiYWNrQ29sb3JzOnRydWV9KS50b0hleFN0cmluZygpOyAgLy8gXCIjZmZmZmZmXCJcbi8vICAgIHRpbnljb2xvci5tb3N0UmVhZGFibGUoXCIjYTgwMTVhXCIsIFtcIiNmYWYzZjNcIl0se2luY2x1ZGVGYWxsYmFja0NvbG9yczp0cnVlLGxldmVsOlwiQUFBXCIsc2l6ZTpcImxhcmdlXCJ9KS50b0hleFN0cmluZygpOyAvLyBcIiNmYWYzZjNcIlxuLy8gICAgdGlueWNvbG9yLm1vc3RSZWFkYWJsZShcIiNhODAxNWFcIiwgW1wiI2ZhZjNmM1wiXSx7aW5jbHVkZUZhbGxiYWNrQ29sb3JzOnRydWUsbGV2ZWw6XCJBQUFcIixzaXplOlwic21hbGxcIn0pLnRvSGV4U3RyaW5nKCk7IC8vIFwiI2ZmZmZmZlwiXG50aW55Y29sb3IubW9zdFJlYWRhYmxlID0gZnVuY3Rpb24oYmFzZUNvbG9yLCBjb2xvckxpc3QsIGFyZ3MpIHtcbiAgICB2YXIgYmVzdENvbG9yID0gbnVsbDtcbiAgICB2YXIgYmVzdFNjb3JlID0gMDtcbiAgICB2YXIgcmVhZGFiaWxpdHk7XG4gICAgdmFyIGluY2x1ZGVGYWxsYmFja0NvbG9ycywgbGV2ZWwsIHNpemUgO1xuICAgIGFyZ3MgPSBhcmdzIHx8IHt9O1xuICAgIGluY2x1ZGVGYWxsYmFja0NvbG9ycyA9IGFyZ3MuaW5jbHVkZUZhbGxiYWNrQ29sb3JzIDtcbiAgICBsZXZlbCA9IGFyZ3MubGV2ZWw7XG4gICAgc2l6ZSA9IGFyZ3Muc2l6ZTtcblxuICAgIGZvciAodmFyIGk9IDA7IGkgPCBjb2xvckxpc3QubGVuZ3RoIDsgaSsrKSB7XG4gICAgICAgIHJlYWRhYmlsaXR5ID0gdGlueWNvbG9yLnJlYWRhYmlsaXR5KGJhc2VDb2xvciwgY29sb3JMaXN0W2ldKTtcbiAgICAgICAgaWYgKHJlYWRhYmlsaXR5ID4gYmVzdFNjb3JlKSB7XG4gICAgICAgICAgICBiZXN0U2NvcmUgPSByZWFkYWJpbGl0eTtcbiAgICAgICAgICAgIGJlc3RDb2xvciA9IHRpbnljb2xvcihjb2xvckxpc3RbaV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRpbnljb2xvci5pc1JlYWRhYmxlKGJhc2VDb2xvciwgYmVzdENvbG9yLCB7XCJsZXZlbFwiOmxldmVsLFwic2l6ZVwiOnNpemV9KSB8fCAhaW5jbHVkZUZhbGxiYWNrQ29sb3JzKSB7XG4gICAgICAgIHJldHVybiBiZXN0Q29sb3I7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBhcmdzLmluY2x1ZGVGYWxsYmFja0NvbG9ycz1mYWxzZTtcbiAgICAgICAgcmV0dXJuIHRpbnljb2xvci5tb3N0UmVhZGFibGUoYmFzZUNvbG9yLFtcIiNmZmZcIiwgXCIjMDAwXCJdLGFyZ3MpO1xuICAgIH1cbn07XG5cblxuLy8gQmlnIExpc3Qgb2YgQ29sb3JzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS1cbi8vIDxodHRwOi8vd3d3LnczLm9yZy9UUi9jc3MzLWNvbG9yLyNzdmctY29sb3I+XG52YXIgbmFtZXMgPSB0aW55Y29sb3IubmFtZXMgPSB7XG4gICAgYWxpY2VibHVlOiBcImYwZjhmZlwiLFxuICAgIGFudGlxdWV3aGl0ZTogXCJmYWViZDdcIixcbiAgICBhcXVhOiBcIjBmZlwiLFxuICAgIGFxdWFtYXJpbmU6IFwiN2ZmZmQ0XCIsXG4gICAgYXp1cmU6IFwiZjBmZmZmXCIsXG4gICAgYmVpZ2U6IFwiZjVmNWRjXCIsXG4gICAgYmlzcXVlOiBcImZmZTRjNFwiLFxuICAgIGJsYWNrOiBcIjAwMFwiLFxuICAgIGJsYW5jaGVkYWxtb25kOiBcImZmZWJjZFwiLFxuICAgIGJsdWU6IFwiMDBmXCIsXG4gICAgYmx1ZXZpb2xldDogXCI4YTJiZTJcIixcbiAgICBicm93bjogXCJhNTJhMmFcIixcbiAgICBidXJseXdvb2Q6IFwiZGViODg3XCIsXG4gICAgYnVybnRzaWVubmE6IFwiZWE3ZTVkXCIsXG4gICAgY2FkZXRibHVlOiBcIjVmOWVhMFwiLFxuICAgIGNoYXJ0cmV1c2U6IFwiN2ZmZjAwXCIsXG4gICAgY2hvY29sYXRlOiBcImQyNjkxZVwiLFxuICAgIGNvcmFsOiBcImZmN2Y1MFwiLFxuICAgIGNvcm5mbG93ZXJibHVlOiBcIjY0OTVlZFwiLFxuICAgIGNvcm5zaWxrOiBcImZmZjhkY1wiLFxuICAgIGNyaW1zb246IFwiZGMxNDNjXCIsXG4gICAgY3lhbjogXCIwZmZcIixcbiAgICBkYXJrYmx1ZTogXCIwMDAwOGJcIixcbiAgICBkYXJrY3lhbjogXCIwMDhiOGJcIixcbiAgICBkYXJrZ29sZGVucm9kOiBcImI4ODYwYlwiLFxuICAgIGRhcmtncmF5OiBcImE5YTlhOVwiLFxuICAgIGRhcmtncmVlbjogXCIwMDY0MDBcIixcbiAgICBkYXJrZ3JleTogXCJhOWE5YTlcIixcbiAgICBkYXJra2hha2k6IFwiYmRiNzZiXCIsXG4gICAgZGFya21hZ2VudGE6IFwiOGIwMDhiXCIsXG4gICAgZGFya29saXZlZ3JlZW46IFwiNTU2YjJmXCIsXG4gICAgZGFya29yYW5nZTogXCJmZjhjMDBcIixcbiAgICBkYXJrb3JjaGlkOiBcIjk5MzJjY1wiLFxuICAgIGRhcmtyZWQ6IFwiOGIwMDAwXCIsXG4gICAgZGFya3NhbG1vbjogXCJlOTk2N2FcIixcbiAgICBkYXJrc2VhZ3JlZW46IFwiOGZiYzhmXCIsXG4gICAgZGFya3NsYXRlYmx1ZTogXCI0ODNkOGJcIixcbiAgICBkYXJrc2xhdGVncmF5OiBcIjJmNGY0ZlwiLFxuICAgIGRhcmtzbGF0ZWdyZXk6IFwiMmY0ZjRmXCIsXG4gICAgZGFya3R1cnF1b2lzZTogXCIwMGNlZDFcIixcbiAgICBkYXJrdmlvbGV0OiBcIjk0MDBkM1wiLFxuICAgIGRlZXBwaW5rOiBcImZmMTQ5M1wiLFxuICAgIGRlZXBza3libHVlOiBcIjAwYmZmZlwiLFxuICAgIGRpbWdyYXk6IFwiNjk2OTY5XCIsXG4gICAgZGltZ3JleTogXCI2OTY5NjlcIixcbiAgICBkb2RnZXJibHVlOiBcIjFlOTBmZlwiLFxuICAgIGZpcmVicmljazogXCJiMjIyMjJcIixcbiAgICBmbG9yYWx3aGl0ZTogXCJmZmZhZjBcIixcbiAgICBmb3Jlc3RncmVlbjogXCIyMjhiMjJcIixcbiAgICBmdWNoc2lhOiBcImYwZlwiLFxuICAgIGdhaW5zYm9ybzogXCJkY2RjZGNcIixcbiAgICBnaG9zdHdoaXRlOiBcImY4ZjhmZlwiLFxuICAgIGdvbGQ6IFwiZmZkNzAwXCIsXG4gICAgZ29sZGVucm9kOiBcImRhYTUyMFwiLFxuICAgIGdyYXk6IFwiODA4MDgwXCIsXG4gICAgZ3JlZW46IFwiMDA4MDAwXCIsXG4gICAgZ3JlZW55ZWxsb3c6IFwiYWRmZjJmXCIsXG4gICAgZ3JleTogXCI4MDgwODBcIixcbiAgICBob25leWRldzogXCJmMGZmZjBcIixcbiAgICBob3RwaW5rOiBcImZmNjliNFwiLFxuICAgIGluZGlhbnJlZDogXCJjZDVjNWNcIixcbiAgICBpbmRpZ286IFwiNGIwMDgyXCIsXG4gICAgaXZvcnk6IFwiZmZmZmYwXCIsXG4gICAga2hha2k6IFwiZjBlNjhjXCIsXG4gICAgbGF2ZW5kZXI6IFwiZTZlNmZhXCIsXG4gICAgbGF2ZW5kZXJibHVzaDogXCJmZmYwZjVcIixcbiAgICBsYXduZ3JlZW46IFwiN2NmYzAwXCIsXG4gICAgbGVtb25jaGlmZm9uOiBcImZmZmFjZFwiLFxuICAgIGxpZ2h0Ymx1ZTogXCJhZGQ4ZTZcIixcbiAgICBsaWdodGNvcmFsOiBcImYwODA4MFwiLFxuICAgIGxpZ2h0Y3lhbjogXCJlMGZmZmZcIixcbiAgICBsaWdodGdvbGRlbnJvZHllbGxvdzogXCJmYWZhZDJcIixcbiAgICBsaWdodGdyYXk6IFwiZDNkM2QzXCIsXG4gICAgbGlnaHRncmVlbjogXCI5MGVlOTBcIixcbiAgICBsaWdodGdyZXk6IFwiZDNkM2QzXCIsXG4gICAgbGlnaHRwaW5rOiBcImZmYjZjMVwiLFxuICAgIGxpZ2h0c2FsbW9uOiBcImZmYTA3YVwiLFxuICAgIGxpZ2h0c2VhZ3JlZW46IFwiMjBiMmFhXCIsXG4gICAgbGlnaHRza3libHVlOiBcIjg3Y2VmYVwiLFxuICAgIGxpZ2h0c2xhdGVncmF5OiBcIjc4OVwiLFxuICAgIGxpZ2h0c2xhdGVncmV5OiBcIjc4OVwiLFxuICAgIGxpZ2h0c3RlZWxibHVlOiBcImIwYzRkZVwiLFxuICAgIGxpZ2h0eWVsbG93OiBcImZmZmZlMFwiLFxuICAgIGxpbWU6IFwiMGYwXCIsXG4gICAgbGltZWdyZWVuOiBcIjMyY2QzMlwiLFxuICAgIGxpbmVuOiBcImZhZjBlNlwiLFxuICAgIG1hZ2VudGE6IFwiZjBmXCIsXG4gICAgbWFyb29uOiBcIjgwMDAwMFwiLFxuICAgIG1lZGl1bWFxdWFtYXJpbmU6IFwiNjZjZGFhXCIsXG4gICAgbWVkaXVtYmx1ZTogXCIwMDAwY2RcIixcbiAgICBtZWRpdW1vcmNoaWQ6IFwiYmE1NWQzXCIsXG4gICAgbWVkaXVtcHVycGxlOiBcIjkzNzBkYlwiLFxuICAgIG1lZGl1bXNlYWdyZWVuOiBcIjNjYjM3MVwiLFxuICAgIG1lZGl1bXNsYXRlYmx1ZTogXCI3YjY4ZWVcIixcbiAgICBtZWRpdW1zcHJpbmdncmVlbjogXCIwMGZhOWFcIixcbiAgICBtZWRpdW10dXJxdW9pc2U6IFwiNDhkMWNjXCIsXG4gICAgbWVkaXVtdmlvbGV0cmVkOiBcImM3MTU4NVwiLFxuICAgIG1pZG5pZ2h0Ymx1ZTogXCIxOTE5NzBcIixcbiAgICBtaW50Y3JlYW06IFwiZjVmZmZhXCIsXG4gICAgbWlzdHlyb3NlOiBcImZmZTRlMVwiLFxuICAgIG1vY2Nhc2luOiBcImZmZTRiNVwiLFxuICAgIG5hdmFqb3doaXRlOiBcImZmZGVhZFwiLFxuICAgIG5hdnk6IFwiMDAwMDgwXCIsXG4gICAgb2xkbGFjZTogXCJmZGY1ZTZcIixcbiAgICBvbGl2ZTogXCI4MDgwMDBcIixcbiAgICBvbGl2ZWRyYWI6IFwiNmI4ZTIzXCIsXG4gICAgb3JhbmdlOiBcImZmYTUwMFwiLFxuICAgIG9yYW5nZXJlZDogXCJmZjQ1MDBcIixcbiAgICBvcmNoaWQ6IFwiZGE3MGQ2XCIsXG4gICAgcGFsZWdvbGRlbnJvZDogXCJlZWU4YWFcIixcbiAgICBwYWxlZ3JlZW46IFwiOThmYjk4XCIsXG4gICAgcGFsZXR1cnF1b2lzZTogXCJhZmVlZWVcIixcbiAgICBwYWxldmlvbGV0cmVkOiBcImRiNzA5M1wiLFxuICAgIHBhcGF5YXdoaXA6IFwiZmZlZmQ1XCIsXG4gICAgcGVhY2hwdWZmOiBcImZmZGFiOVwiLFxuICAgIHBlcnU6IFwiY2Q4NTNmXCIsXG4gICAgcGluazogXCJmZmMwY2JcIixcbiAgICBwbHVtOiBcImRkYTBkZFwiLFxuICAgIHBvd2RlcmJsdWU6IFwiYjBlMGU2XCIsXG4gICAgcHVycGxlOiBcIjgwMDA4MFwiLFxuICAgIHJlYmVjY2FwdXJwbGU6IFwiNjYzMzk5XCIsXG4gICAgcmVkOiBcImYwMFwiLFxuICAgIHJvc3licm93bjogXCJiYzhmOGZcIixcbiAgICByb3lhbGJsdWU6IFwiNDE2OWUxXCIsXG4gICAgc2FkZGxlYnJvd246IFwiOGI0NTEzXCIsXG4gICAgc2FsbW9uOiBcImZhODA3MlwiLFxuICAgIHNhbmR5YnJvd246IFwiZjRhNDYwXCIsXG4gICAgc2VhZ3JlZW46IFwiMmU4YjU3XCIsXG4gICAgc2Vhc2hlbGw6IFwiZmZmNWVlXCIsXG4gICAgc2llbm5hOiBcImEwNTIyZFwiLFxuICAgIHNpbHZlcjogXCJjMGMwYzBcIixcbiAgICBza3libHVlOiBcIjg3Y2VlYlwiLFxuICAgIHNsYXRlYmx1ZTogXCI2YTVhY2RcIixcbiAgICBzbGF0ZWdyYXk6IFwiNzA4MDkwXCIsXG4gICAgc2xhdGVncmV5OiBcIjcwODA5MFwiLFxuICAgIHNub3c6IFwiZmZmYWZhXCIsXG4gICAgc3ByaW5nZ3JlZW46IFwiMDBmZjdmXCIsXG4gICAgc3RlZWxibHVlOiBcIjQ2ODJiNFwiLFxuICAgIHRhbjogXCJkMmI0OGNcIixcbiAgICB0ZWFsOiBcIjAwODA4MFwiLFxuICAgIHRoaXN0bGU6IFwiZDhiZmQ4XCIsXG4gICAgdG9tYXRvOiBcImZmNjM0N1wiLFxuICAgIHR1cnF1b2lzZTogXCI0MGUwZDBcIixcbiAgICB2aW9sZXQ6IFwiZWU4MmVlXCIsXG4gICAgd2hlYXQ6IFwiZjVkZWIzXCIsXG4gICAgd2hpdGU6IFwiZmZmXCIsXG4gICAgd2hpdGVzbW9rZTogXCJmNWY1ZjVcIixcbiAgICB5ZWxsb3c6IFwiZmYwXCIsXG4gICAgeWVsbG93Z3JlZW46IFwiOWFjZDMyXCJcbn07XG5cbi8vIE1ha2UgaXQgZWFzeSB0byBhY2Nlc3MgY29sb3JzIHZpYSBgaGV4TmFtZXNbaGV4XWBcbnZhciBoZXhOYW1lcyA9IHRpbnljb2xvci5oZXhOYW1lcyA9IGZsaXAobmFtZXMpO1xuXG5cbi8vIFV0aWxpdGllc1xuLy8gLS0tLS0tLS0tXG5cbi8vIGB7ICduYW1lMSc6ICd2YWwxJyB9YCBiZWNvbWVzIGB7ICd2YWwxJzogJ25hbWUxJyB9YFxuZnVuY3Rpb24gZmxpcChvKSB7XG4gICAgdmFyIGZsaXBwZWQgPSB7IH07XG4gICAgZm9yICh2YXIgaSBpbiBvKSB7XG4gICAgICAgIGlmIChvLmhhc093blByb3BlcnR5KGkpKSB7XG4gICAgICAgICAgICBmbGlwcGVkW29baV1dID0gaTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmxpcHBlZDtcbn1cblxuLy8gUmV0dXJuIGEgdmFsaWQgYWxwaGEgdmFsdWUgWzAsMV0gd2l0aCBhbGwgaW52YWxpZCB2YWx1ZXMgYmVpbmcgc2V0IHRvIDFcbmZ1bmN0aW9uIGJvdW5kQWxwaGEoYSkge1xuICAgIGEgPSBwYXJzZUZsb2F0KGEpO1xuXG4gICAgaWYgKGlzTmFOKGEpIHx8IGEgPCAwIHx8IGEgPiAxKSB7XG4gICAgICAgIGEgPSAxO1xuICAgIH1cblxuICAgIHJldHVybiBhO1xufVxuXG4vLyBUYWtlIGlucHV0IGZyb20gWzAsIG5dIGFuZCByZXR1cm4gaXQgYXMgWzAsIDFdXG5mdW5jdGlvbiBib3VuZDAxKG4sIG1heCkge1xuICAgIGlmIChpc09uZVBvaW50WmVybyhuKSkgeyBuID0gXCIxMDAlXCI7IH1cblxuICAgIHZhciBwcm9jZXNzUGVyY2VudCA9IGlzUGVyY2VudGFnZShuKTtcbiAgICBuID0gbWF0aE1pbihtYXgsIG1hdGhNYXgoMCwgcGFyc2VGbG9hdChuKSkpO1xuXG4gICAgLy8gQXV0b21hdGljYWxseSBjb252ZXJ0IHBlcmNlbnRhZ2UgaW50byBudW1iZXJcbiAgICBpZiAocHJvY2Vzc1BlcmNlbnQpIHtcbiAgICAgICAgbiA9IHBhcnNlSW50KG4gKiBtYXgsIDEwKSAvIDEwMDtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgZmxvYXRpbmcgcG9pbnQgcm91bmRpbmcgZXJyb3JzXG4gICAgaWYgKChNYXRoLmFicyhuIC0gbWF4KSA8IDAuMDAwMDAxKSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICB9XG5cbiAgICAvLyBDb252ZXJ0IGludG8gWzAsIDFdIHJhbmdlIGlmIGl0IGlzbid0IGFscmVhZHlcbiAgICByZXR1cm4gKG4gJSBtYXgpIC8gcGFyc2VGbG9hdChtYXgpO1xufVxuXG4vLyBGb3JjZSBhIG51bWJlciBiZXR3ZWVuIDAgYW5kIDFcbmZ1bmN0aW9uIGNsYW1wMDEodmFsKSB7XG4gICAgcmV0dXJuIG1hdGhNaW4oMSwgbWF0aE1heCgwLCB2YWwpKTtcbn1cblxuLy8gUGFyc2UgYSBiYXNlLTE2IGhleCB2YWx1ZSBpbnRvIGEgYmFzZS0xMCBpbnRlZ2VyXG5mdW5jdGlvbiBwYXJzZUludEZyb21IZXgodmFsKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHZhbCwgMTYpO1xufVxuXG4vLyBOZWVkIHRvIGhhbmRsZSAxLjAgYXMgMTAwJSwgc2luY2Ugb25jZSBpdCBpcyBhIG51bWJlciwgdGhlcmUgaXMgbm8gZGlmZmVyZW5jZSBiZXR3ZWVuIGl0IGFuZCAxXG4vLyA8aHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy83NDIyMDcyL2phdmFzY3JpcHQtaG93LXRvLWRldGVjdC1udW1iZXItYXMtYS1kZWNpbWFsLWluY2x1ZGluZy0xLTA+XG5mdW5jdGlvbiBpc09uZVBvaW50WmVybyhuKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBuID09IFwic3RyaW5nXCIgJiYgbi5pbmRleE9mKCcuJykgIT0gLTEgJiYgcGFyc2VGbG9hdChuKSA9PT0gMTtcbn1cblxuLy8gQ2hlY2sgdG8gc2VlIGlmIHN0cmluZyBwYXNzZWQgaW4gaXMgYSBwZXJjZW50YWdlXG5mdW5jdGlvbiBpc1BlcmNlbnRhZ2Uobikge1xuICAgIHJldHVybiB0eXBlb2YgbiA9PT0gXCJzdHJpbmdcIiAmJiBuLmluZGV4T2YoJyUnKSAhPSAtMTtcbn1cblxuLy8gRm9yY2UgYSBoZXggdmFsdWUgdG8gaGF2ZSAyIGNoYXJhY3RlcnNcbmZ1bmN0aW9uIHBhZDIoYykge1xuICAgIHJldHVybiBjLmxlbmd0aCA9PSAxID8gJzAnICsgYyA6ICcnICsgYztcbn1cblxuLy8gUmVwbGFjZSBhIGRlY2ltYWwgd2l0aCBpdCdzIHBlcmNlbnRhZ2UgdmFsdWVcbmZ1bmN0aW9uIGNvbnZlcnRUb1BlcmNlbnRhZ2Uobikge1xuICAgIGlmIChuIDw9IDEpIHtcbiAgICAgICAgbiA9IChuICogMTAwKSArIFwiJVwiO1xuICAgIH1cblxuICAgIHJldHVybiBuO1xufVxuXG4vLyBDb252ZXJ0cyBhIGRlY2ltYWwgdG8gYSBoZXggdmFsdWVcbmZ1bmN0aW9uIGNvbnZlcnREZWNpbWFsVG9IZXgoZCkge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKHBhcnNlRmxvYXQoZCkgKiAyNTUpLnRvU3RyaW5nKDE2KTtcbn1cbi8vIENvbnZlcnRzIGEgaGV4IHZhbHVlIHRvIGEgZGVjaW1hbFxuZnVuY3Rpb24gY29udmVydEhleFRvRGVjaW1hbChoKSB7XG4gICAgcmV0dXJuIChwYXJzZUludEZyb21IZXgoaCkgLyAyNTUpO1xufVxuXG52YXIgbWF0Y2hlcnMgPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAvLyA8aHR0cDovL3d3dy53My5vcmcvVFIvY3NzMy12YWx1ZXMvI2ludGVnZXJzPlxuICAgIHZhciBDU1NfSU5URUdFUiA9IFwiWy1cXFxcK10/XFxcXGQrJT9cIjtcblxuICAgIC8vIDxodHRwOi8vd3d3LnczLm9yZy9UUi9jc3MzLXZhbHVlcy8jbnVtYmVyLXZhbHVlPlxuICAgIHZhciBDU1NfTlVNQkVSID0gXCJbLVxcXFwrXT9cXFxcZCpcXFxcLlxcXFxkKyU/XCI7XG5cbiAgICAvLyBBbGxvdyBwb3NpdGl2ZS9uZWdhdGl2ZSBpbnRlZ2VyL251bWJlci4gIERvbid0IGNhcHR1cmUgdGhlIGVpdGhlci9vciwganVzdCB0aGUgZW50aXJlIG91dGNvbWUuXG4gICAgdmFyIENTU19VTklUID0gXCIoPzpcIiArIENTU19OVU1CRVIgKyBcIil8KD86XCIgKyBDU1NfSU5URUdFUiArIFwiKVwiO1xuXG4gICAgLy8gQWN0dWFsIG1hdGNoaW5nLlxuICAgIC8vIFBhcmVudGhlc2VzIGFuZCBjb21tYXMgYXJlIG9wdGlvbmFsLCBidXQgbm90IHJlcXVpcmVkLlxuICAgIC8vIFdoaXRlc3BhY2UgY2FuIHRha2UgdGhlIHBsYWNlIG9mIGNvbW1hcyBvciBvcGVuaW5nIHBhcmVuXG4gICAgdmFyIFBFUk1JU1NJVkVfTUFUQ0gzID0gXCJbXFxcXHN8XFxcXChdKyhcIiArIENTU19VTklUICsgXCIpWyx8XFxcXHNdKyhcIiArIENTU19VTklUICsgXCIpWyx8XFxcXHNdKyhcIiArIENTU19VTklUICsgXCIpXFxcXHMqXFxcXCk/XCI7XG4gICAgdmFyIFBFUk1JU1NJVkVfTUFUQ0g0ID0gXCJbXFxcXHN8XFxcXChdKyhcIiArIENTU19VTklUICsgXCIpWyx8XFxcXHNdKyhcIiArIENTU19VTklUICsgXCIpWyx8XFxcXHNdKyhcIiArIENTU19VTklUICsgXCIpWyx8XFxcXHNdKyhcIiArIENTU19VTklUICsgXCIpXFxcXHMqXFxcXCk/XCI7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBDU1NfVU5JVDogbmV3IFJlZ0V4cChDU1NfVU5JVCksXG4gICAgICAgIHJnYjogbmV3IFJlZ0V4cChcInJnYlwiICsgUEVSTUlTU0lWRV9NQVRDSDMpLFxuICAgICAgICByZ2JhOiBuZXcgUmVnRXhwKFwicmdiYVwiICsgUEVSTUlTU0lWRV9NQVRDSDQpLFxuICAgICAgICBoc2w6IG5ldyBSZWdFeHAoXCJoc2xcIiArIFBFUk1JU1NJVkVfTUFUQ0gzKSxcbiAgICAgICAgaHNsYTogbmV3IFJlZ0V4cChcImhzbGFcIiArIFBFUk1JU1NJVkVfTUFUQ0g0KSxcbiAgICAgICAgaHN2OiBuZXcgUmVnRXhwKFwiaHN2XCIgKyBQRVJNSVNTSVZFX01BVENIMyksXG4gICAgICAgIGhzdmE6IG5ldyBSZWdFeHAoXCJoc3ZhXCIgKyBQRVJNSVNTSVZFX01BVENINCksXG4gICAgICAgIGhleDM6IC9eIz8oWzAtOWEtZkEtRl17MX0pKFswLTlhLWZBLUZdezF9KShbMC05YS1mQS1GXXsxfSkkLyxcbiAgICAgICAgaGV4NjogL14jPyhbMC05YS1mQS1GXXsyfSkoWzAtOWEtZkEtRl17Mn0pKFswLTlhLWZBLUZdezJ9KSQvLFxuICAgICAgICBoZXg0OiAvXiM/KFswLTlhLWZBLUZdezF9KShbMC05YS1mQS1GXXsxfSkoWzAtOWEtZkEtRl17MX0pKFswLTlhLWZBLUZdezF9KSQvLFxuICAgICAgICBoZXg4OiAvXiM/KFswLTlhLWZBLUZdezJ9KShbMC05YS1mQS1GXXsyfSkoWzAtOWEtZkEtRl17Mn0pKFswLTlhLWZBLUZdezJ9KSQvXG4gICAgfTtcbn0pKCk7XG5cbi8vIGBpc1ZhbGlkQ1NTVW5pdGBcbi8vIFRha2UgaW4gYSBzaW5nbGUgc3RyaW5nIC8gbnVtYmVyIGFuZCBjaGVjayB0byBzZWUgaWYgaXQgbG9va3MgbGlrZSBhIENTUyB1bml0XG4vLyAoc2VlIGBtYXRjaGVyc2AgYWJvdmUgZm9yIGRlZmluaXRpb24pLlxuZnVuY3Rpb24gaXNWYWxpZENTU1VuaXQoY29sb3IpIHtcbiAgICByZXR1cm4gISFtYXRjaGVycy5DU1NfVU5JVC5leGVjKGNvbG9yKTtcbn1cblxuLy8gYHN0cmluZ0lucHV0VG9PYmplY3RgXG4vLyBQZXJtaXNzaXZlIHN0cmluZyBwYXJzaW5nLiAgVGFrZSBpbiBhIG51bWJlciBvZiBmb3JtYXRzLCBhbmQgb3V0cHV0IGFuIG9iamVjdFxuLy8gYmFzZWQgb24gZGV0ZWN0ZWQgZm9ybWF0LiAgUmV0dXJucyBgeyByLCBnLCBiIH1gIG9yIGB7IGgsIHMsIGwgfWAgb3IgYHsgaCwgcywgdn1gXG5mdW5jdGlvbiBzdHJpbmdJbnB1dFRvT2JqZWN0KGNvbG9yKSB7XG5cbiAgICBjb2xvciA9IGNvbG9yLnJlcGxhY2UodHJpbUxlZnQsJycpLnJlcGxhY2UodHJpbVJpZ2h0LCAnJykudG9Mb3dlckNhc2UoKTtcbiAgICB2YXIgbmFtZWQgPSBmYWxzZTtcbiAgICBpZiAobmFtZXNbY29sb3JdKSB7XG4gICAgICAgIGNvbG9yID0gbmFtZXNbY29sb3JdO1xuICAgICAgICBuYW1lZCA9IHRydWU7XG4gICAgfVxuICAgIGVsc2UgaWYgKGNvbG9yID09ICd0cmFuc3BhcmVudCcpIHtcbiAgICAgICAgcmV0dXJuIHsgcjogMCwgZzogMCwgYjogMCwgYTogMCwgZm9ybWF0OiBcIm5hbWVcIiB9O1xuICAgIH1cblxuICAgIC8vIFRyeSB0byBtYXRjaCBzdHJpbmcgaW5wdXQgdXNpbmcgcmVndWxhciBleHByZXNzaW9ucy5cbiAgICAvLyBLZWVwIG1vc3Qgb2YgdGhlIG51bWJlciBib3VuZGluZyBvdXQgb2YgdGhpcyBmdW5jdGlvbiAtIGRvbid0IHdvcnJ5IGFib3V0IFswLDFdIG9yIFswLDEwMF0gb3IgWzAsMzYwXVxuICAgIC8vIEp1c3QgcmV0dXJuIGFuIG9iamVjdCBhbmQgbGV0IHRoZSBjb252ZXJzaW9uIGZ1bmN0aW9ucyBoYW5kbGUgdGhhdC5cbiAgICAvLyBUaGlzIHdheSB0aGUgcmVzdWx0IHdpbGwgYmUgdGhlIHNhbWUgd2hldGhlciB0aGUgdGlueWNvbG9yIGlzIGluaXRpYWxpemVkIHdpdGggc3RyaW5nIG9yIG9iamVjdC5cbiAgICB2YXIgbWF0Y2g7XG4gICAgaWYgKChtYXRjaCA9IG1hdGNoZXJzLnJnYi5leGVjKGNvbG9yKSkpIHtcbiAgICAgICAgcmV0dXJuIHsgcjogbWF0Y2hbMV0sIGc6IG1hdGNoWzJdLCBiOiBtYXRjaFszXSB9O1xuICAgIH1cbiAgICBpZiAoKG1hdGNoID0gbWF0Y2hlcnMucmdiYS5leGVjKGNvbG9yKSkpIHtcbiAgICAgICAgcmV0dXJuIHsgcjogbWF0Y2hbMV0sIGc6IG1hdGNoWzJdLCBiOiBtYXRjaFszXSwgYTogbWF0Y2hbNF0gfTtcbiAgICB9XG4gICAgaWYgKChtYXRjaCA9IG1hdGNoZXJzLmhzbC5leGVjKGNvbG9yKSkpIHtcbiAgICAgICAgcmV0dXJuIHsgaDogbWF0Y2hbMV0sIHM6IG1hdGNoWzJdLCBsOiBtYXRjaFszXSB9O1xuICAgIH1cbiAgICBpZiAoKG1hdGNoID0gbWF0Y2hlcnMuaHNsYS5leGVjKGNvbG9yKSkpIHtcbiAgICAgICAgcmV0dXJuIHsgaDogbWF0Y2hbMV0sIHM6IG1hdGNoWzJdLCBsOiBtYXRjaFszXSwgYTogbWF0Y2hbNF0gfTtcbiAgICB9XG4gICAgaWYgKChtYXRjaCA9IG1hdGNoZXJzLmhzdi5leGVjKGNvbG9yKSkpIHtcbiAgICAgICAgcmV0dXJuIHsgaDogbWF0Y2hbMV0sIHM6IG1hdGNoWzJdLCB2OiBtYXRjaFszXSB9O1xuICAgIH1cbiAgICBpZiAoKG1hdGNoID0gbWF0Y2hlcnMuaHN2YS5leGVjKGNvbG9yKSkpIHtcbiAgICAgICAgcmV0dXJuIHsgaDogbWF0Y2hbMV0sIHM6IG1hdGNoWzJdLCB2OiBtYXRjaFszXSwgYTogbWF0Y2hbNF0gfTtcbiAgICB9XG4gICAgaWYgKChtYXRjaCA9IG1hdGNoZXJzLmhleDguZXhlYyhjb2xvcikpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByOiBwYXJzZUludEZyb21IZXgobWF0Y2hbMV0pLFxuICAgICAgICAgICAgZzogcGFyc2VJbnRGcm9tSGV4KG1hdGNoWzJdKSxcbiAgICAgICAgICAgIGI6IHBhcnNlSW50RnJvbUhleChtYXRjaFszXSksXG4gICAgICAgICAgICBhOiBjb252ZXJ0SGV4VG9EZWNpbWFsKG1hdGNoWzRdKSxcbiAgICAgICAgICAgIGZvcm1hdDogbmFtZWQgPyBcIm5hbWVcIiA6IFwiaGV4OFwiXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmICgobWF0Y2ggPSBtYXRjaGVycy5oZXg2LmV4ZWMoY29sb3IpKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcjogcGFyc2VJbnRGcm9tSGV4KG1hdGNoWzFdKSxcbiAgICAgICAgICAgIGc6IHBhcnNlSW50RnJvbUhleChtYXRjaFsyXSksXG4gICAgICAgICAgICBiOiBwYXJzZUludEZyb21IZXgobWF0Y2hbM10pLFxuICAgICAgICAgICAgZm9ybWF0OiBuYW1lZCA/IFwibmFtZVwiIDogXCJoZXhcIlxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoKG1hdGNoID0gbWF0Y2hlcnMuaGV4NC5leGVjKGNvbG9yKSkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHI6IHBhcnNlSW50RnJvbUhleChtYXRjaFsxXSArICcnICsgbWF0Y2hbMV0pLFxuICAgICAgICAgICAgZzogcGFyc2VJbnRGcm9tSGV4KG1hdGNoWzJdICsgJycgKyBtYXRjaFsyXSksXG4gICAgICAgICAgICBiOiBwYXJzZUludEZyb21IZXgobWF0Y2hbM10gKyAnJyArIG1hdGNoWzNdKSxcbiAgICAgICAgICAgIGE6IGNvbnZlcnRIZXhUb0RlY2ltYWwobWF0Y2hbNF0gKyAnJyArIG1hdGNoWzRdKSxcbiAgICAgICAgICAgIGZvcm1hdDogbmFtZWQgPyBcIm5hbWVcIiA6IFwiaGV4OFwiXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmICgobWF0Y2ggPSBtYXRjaGVycy5oZXgzLmV4ZWMoY29sb3IpKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcjogcGFyc2VJbnRGcm9tSGV4KG1hdGNoWzFdICsgJycgKyBtYXRjaFsxXSksXG4gICAgICAgICAgICBnOiBwYXJzZUludEZyb21IZXgobWF0Y2hbMl0gKyAnJyArIG1hdGNoWzJdKSxcbiAgICAgICAgICAgIGI6IHBhcnNlSW50RnJvbUhleChtYXRjaFszXSArICcnICsgbWF0Y2hbM10pLFxuICAgICAgICAgICAgZm9ybWF0OiBuYW1lZCA/IFwibmFtZVwiIDogXCJoZXhcIlxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVXQ0FHMlBhcm1zKHBhcm1zKSB7XG4gICAgLy8gcmV0dXJuIHZhbGlkIFdDQUcyIHBhcm1zIGZvciBpc1JlYWRhYmxlLlxuICAgIC8vIElmIGlucHV0IHBhcm1zIGFyZSBpbnZhbGlkLCByZXR1cm4ge1wibGV2ZWxcIjpcIkFBXCIsIFwic2l6ZVwiOlwic21hbGxcIn1cbiAgICB2YXIgbGV2ZWwsIHNpemU7XG4gICAgcGFybXMgPSBwYXJtcyB8fCB7XCJsZXZlbFwiOlwiQUFcIiwgXCJzaXplXCI6XCJzbWFsbFwifTtcbiAgICBsZXZlbCA9IChwYXJtcy5sZXZlbCB8fCBcIkFBXCIpLnRvVXBwZXJDYXNlKCk7XG4gICAgc2l6ZSA9IChwYXJtcy5zaXplIHx8IFwic21hbGxcIikudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAobGV2ZWwgIT09IFwiQUFcIiAmJiBsZXZlbCAhPT0gXCJBQUFcIikge1xuICAgICAgICBsZXZlbCA9IFwiQUFcIjtcbiAgICB9XG4gICAgaWYgKHNpemUgIT09IFwic21hbGxcIiAmJiBzaXplICE9PSBcImxhcmdlXCIpIHtcbiAgICAgICAgc2l6ZSA9IFwic21hbGxcIjtcbiAgICB9XG4gICAgcmV0dXJuIHtcImxldmVsXCI6bGV2ZWwsIFwic2l6ZVwiOnNpemV9O1xufVxuXG4vLyBOb2RlOiBFeHBvcnQgZnVuY3Rpb25cbmlmICh0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSB0aW55Y29sb3I7XG59XG4vLyBBTUQvcmVxdWlyZWpzOiBEZWZpbmUgdGhlIG1vZHVsZVxuZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgZGVmaW5lKGZ1bmN0aW9uICgpIHtyZXR1cm4gdGlueWNvbG9yO30pO1xufVxuLy8gQnJvd3NlcjogRXhwb3NlIHRvIHdpbmRvd1xuZWxzZSB7XG4gICAgd2luZG93LnRpbnljb2xvciA9IHRpbnljb2xvcjtcbn1cblxufSkoTWF0aCk7XG5cbn0se31dLDUzODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKiBAbW9kdWxlIHRvLWZsb2F0MzIgKi9cclxuXHJcbid1c2Ugc3RyaWN0J1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBmbG9hdDMyXHJcbm1vZHVsZS5leHBvcnRzLmZsb2F0MzIgPVxyXG5tb2R1bGUuZXhwb3J0cy5mbG9hdCA9IGZsb2F0MzJcclxubW9kdWxlLmV4cG9ydHMuZnJhY3QzMiA9XHJcbm1vZHVsZS5leHBvcnRzLmZyYWN0ID0gZnJhY3QzMlxyXG5cclxudmFyIG5hcnIgPSBuZXcgRmxvYXQzMkFycmF5KDEpXHJcblxyXG4vLyByZXR1cm4gZnJhY3Rpb25hbCBwYXJ0IG9mIGZsb2F0MzIgYXJyYXlcclxuZnVuY3Rpb24gZnJhY3QzMiAoYXJyKSB7XHJcblx0aWYgKGFyci5sZW5ndGgpIHtcclxuXHRcdHZhciBmcmFjdCA9IGZsb2F0MzIoYXJyKVxyXG5cdFx0Zm9yICh2YXIgaSA9IDAsIGwgPSBmcmFjdC5sZW5ndGg7IGkgPCBsOyBpKyspIHtcclxuXHRcdFx0ZnJhY3RbaV0gPSBhcnJbaV0gLSBmcmFjdFtpXVxyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIGZyYWN0XHJcblx0fVxyXG5cclxuXHQvLyBudW1iZXJcclxuXHRyZXR1cm4gZmxvYXQzMihhcnIgLSBmbG9hdDMyKGFycikpXHJcbn1cclxuXHJcbi8vIG1ha2Ugc3VyZSBkYXRhIGlzIGZsb2F0MzIgYXJyYXlcclxuZnVuY3Rpb24gZmxvYXQzMiAoYXJyKSB7XHJcblx0aWYgKGFyci5sZW5ndGgpIHtcclxuXHRcdGlmIChhcnIgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkpIHJldHVybiBhcnJcclxuXHRcdHZhciBmbG9hdCA9IG5ldyBGbG9hdDMyQXJyYXkoYXJyKVxyXG5cdFx0ZmxvYXQuc2V0KGFycilcclxuXHRcdHJldHVybiBmbG9hdFxyXG5cdH1cclxuXHJcblx0Ly8gbnVtYmVyXHJcblx0bmFyclswXSA9IGFyclxyXG5cdHJldHVybiBuYXJyWzBdXHJcbn1cclxuXG59LHt9XSw1Mzk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuJ3VzZSBzdHJpY3QnXG5cbnZhciBwYXJzZVVuaXQgPSBfZGVyZXFfKCdwYXJzZS11bml0JylcblxubW9kdWxlLmV4cG9ydHMgPSB0b1BYXG5cbnZhciBQSVhFTFNfUEVSX0lOQ0ggPSA5NlxuXG5mdW5jdGlvbiBnZXRQcm9wZXJ0eUluUFgoZWxlbWVudCwgcHJvcCkge1xuICB2YXIgcGFydHMgPSBwYXJzZVVuaXQoZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KS5nZXRQcm9wZXJ0eVZhbHVlKHByb3ApKVxuICByZXR1cm4gcGFydHNbMF0gKiB0b1BYKHBhcnRzWzFdLCBlbGVtZW50KVxufVxuXG4vL1RoaXMgYnJ1dGFsIGhhY2sgaXMgbmVlZGVkXG5mdW5jdGlvbiBnZXRTaXplQnJ1dGFsKHVuaXQsIGVsZW1lbnQpIHtcbiAgdmFyIHRlc3RESVYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICB0ZXN0RElWLnN0eWxlWydmb250LXNpemUnXSA9ICcxMjgnICsgdW5pdFxuICBlbGVtZW50LmFwcGVuZENoaWxkKHRlc3RESVYpXG4gIHZhciBzaXplID0gZ2V0UHJvcGVydHlJblBYKHRlc3RESVYsICdmb250LXNpemUnKSAvIDEyOFxuICBlbGVtZW50LnJlbW92ZUNoaWxkKHRlc3RESVYpXG4gIHJldHVybiBzaXplXG59XG5cbmZ1bmN0aW9uIHRvUFgoc3RyLCBlbGVtZW50KSB7XG4gIGVsZW1lbnQgPSBlbGVtZW50IHx8IGRvY3VtZW50LmJvZHlcbiAgc3RyID0gKHN0ciB8fCAncHgnKS50cmltKCkudG9Mb3dlckNhc2UoKVxuICBpZihlbGVtZW50ID09PSB3aW5kb3cgfHwgZWxlbWVudCA9PT0gZG9jdW1lbnQpIHtcbiAgICBlbGVtZW50ID0gZG9jdW1lbnQuYm9keSBcbiAgfVxuICBzd2l0Y2goc3RyKSB7XG4gICAgY2FzZSAnJSc6ICAvL0FtYmlndW91cywgbm90IHN1cmUgaWYgd2Ugc2hvdWxkIHVzZSB3aWR0aCBvciBoZWlnaHRcbiAgICAgIHJldHVybiBlbGVtZW50LmNsaWVudEhlaWdodCAvIDEwMC4wXG4gICAgY2FzZSAnY2gnOlxuICAgIGNhc2UgJ2V4JzpcbiAgICAgIHJldHVybiBnZXRTaXplQnJ1dGFsKHN0ciwgZWxlbWVudClcbiAgICBjYXNlICdlbSc6XG4gICAgICByZXR1cm4gZ2V0UHJvcGVydHlJblBYKGVsZW1lbnQsICdmb250LXNpemUnKVxuICAgIGNhc2UgJ3JlbSc6XG4gICAgICByZXR1cm4gZ2V0UHJvcGVydHlJblBYKGRvY3VtZW50LmJvZHksICdmb250LXNpemUnKVxuICAgIGNhc2UgJ3Z3JzpcbiAgICAgIHJldHVybiB3aW5kb3cuaW5uZXJXaWR0aC8xMDBcbiAgICBjYXNlICd2aCc6XG4gICAgICByZXR1cm4gd2luZG93LmlubmVySGVpZ2h0LzEwMFxuICAgIGNhc2UgJ3ZtaW4nOlxuICAgICAgcmV0dXJuIE1hdGgubWluKHdpbmRvdy5pbm5lcldpZHRoLCB3aW5kb3cuaW5uZXJIZWlnaHQpIC8gMTAwXG4gICAgY2FzZSAndm1heCc6XG4gICAgICByZXR1cm4gTWF0aC5tYXgod2luZG93LmlubmVyV2lkdGgsIHdpbmRvdy5pbm5lckhlaWdodCkgLyAxMDBcbiAgICBjYXNlICdpbic6XG4gICAgICByZXR1cm4gUElYRUxTX1BFUl9JTkNIXG4gICAgY2FzZSAnY20nOlxuICAgICAgcmV0dXJuIFBJWEVMU19QRVJfSU5DSCAvIDIuNTRcbiAgICBjYXNlICdtbSc6XG4gICAgICByZXR1cm4gUElYRUxTX1BFUl9JTkNIIC8gMjUuNFxuICAgIGNhc2UgJ3B0JzpcbiAgICAgIHJldHVybiBQSVhFTFNfUEVSX0lOQ0ggLyA3MlxuICAgIGNhc2UgJ3BjJzpcbiAgICAgIHJldHVybiBQSVhFTFNfUEVSX0lOQ0ggLyA2XG4gIH1cbiAgcmV0dXJuIDFcbn1cbn0se1wicGFyc2UtdW5pdFwiOjQ2MX1dLDU0MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBodHRwczovL2dpdGh1Yi5jb20vdG9wb2pzb24vdG9wb2pzb24tY2xpZW50IFZlcnNpb24gMi4xLjAuIENvcHlyaWdodCAyMDE2IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcbiAgKGZhY3RvcnkoKGdsb2JhbC50b3BvanNvbiA9IGdsb2JhbC50b3BvanNvbiB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIGlkZW50aXR5ID0gZnVuY3Rpb24oeCkge1xuICByZXR1cm4geDtcbn07XG5cbnZhciB0cmFuc2Zvcm0gPSBmdW5jdGlvbih0b3BvbG9neSkge1xuICBpZiAoKHRyYW5zZm9ybSA9IHRvcG9sb2d5LnRyYW5zZm9ybSkgPT0gbnVsbCkgcmV0dXJuIGlkZW50aXR5O1xuICB2YXIgdHJhbnNmb3JtLFxuICAgICAgeDAsXG4gICAgICB5MCxcbiAgICAgIGt4ID0gdHJhbnNmb3JtLnNjYWxlWzBdLFxuICAgICAga3kgPSB0cmFuc2Zvcm0uc2NhbGVbMV0sXG4gICAgICBkeCA9IHRyYW5zZm9ybS50cmFuc2xhdGVbMF0sXG4gICAgICBkeSA9IHRyYW5zZm9ybS50cmFuc2xhdGVbMV07XG4gIHJldHVybiBmdW5jdGlvbihwb2ludCwgaSkge1xuICAgIGlmICghaSkgeDAgPSB5MCA9IDA7XG4gICAgcG9pbnRbMF0gPSAoeDAgKz0gcG9pbnRbMF0pICoga3ggKyBkeDtcbiAgICBwb2ludFsxXSA9ICh5MCArPSBwb2ludFsxXSkgKiBreSArIGR5O1xuICAgIHJldHVybiBwb2ludDtcbiAgfTtcbn07XG5cbnZhciBiYm94ID0gZnVuY3Rpb24odG9wb2xvZ3kpIHtcbiAgdmFyIGJib3ggPSB0b3BvbG9neS5iYm94O1xuXG4gIGZ1bmN0aW9uIGJib3hQb2ludChwMCkge1xuICAgIHAxWzBdID0gcDBbMF0sIHAxWzFdID0gcDBbMV0sIHQocDEpO1xuICAgIGlmIChwMVswXSA8IHgwKSB4MCA9IHAxWzBdO1xuICAgIGlmIChwMVswXSA+IHgxKSB4MSA9IHAxWzBdO1xuICAgIGlmIChwMVsxXSA8IHkwKSB5MCA9IHAxWzFdO1xuICAgIGlmIChwMVsxXSA+IHkxKSB5MSA9IHAxWzFdO1xuICB9XG5cbiAgZnVuY3Rpb24gYmJveEdlb21ldHJ5KG8pIHtcbiAgICBzd2l0Y2ggKG8udHlwZSkge1xuICAgICAgY2FzZSBcIkdlb21ldHJ5Q29sbGVjdGlvblwiOiBvLmdlb21ldHJpZXMuZm9yRWFjaChiYm94R2VvbWV0cnkpOyBicmVhaztcbiAgICAgIGNhc2UgXCJQb2ludFwiOiBiYm94UG9pbnQoby5jb29yZGluYXRlcyk7IGJyZWFrO1xuICAgICAgY2FzZSBcIk11bHRpUG9pbnRcIjogby5jb29yZGluYXRlcy5mb3JFYWNoKGJib3hQb2ludCk7IGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGlmICghYmJveCkge1xuICAgIHZhciB0ID0gdHJhbnNmb3JtKHRvcG9sb2d5KSwgcDAsIHAxID0gbmV3IEFycmF5KDIpLCBuYW1lLFxuICAgICAgICB4MCA9IEluZmluaXR5LCB5MCA9IHgwLCB4MSA9IC14MCwgeTEgPSAteDA7XG5cbiAgICB0b3BvbG9neS5hcmNzLmZvckVhY2goZnVuY3Rpb24oYXJjKSB7XG4gICAgICB2YXIgaSA9IC0xLCBuID0gYXJjLmxlbmd0aDtcbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIHAwID0gYXJjW2ldLCBwMVswXSA9IHAwWzBdLCBwMVsxXSA9IHAwWzFdLCB0KHAxLCBpKTtcbiAgICAgICAgaWYgKHAxWzBdIDwgeDApIHgwID0gcDFbMF07XG4gICAgICAgIGlmIChwMVswXSA+IHgxKSB4MSA9IHAxWzBdO1xuICAgICAgICBpZiAocDFbMV0gPCB5MCkgeTAgPSBwMVsxXTtcbiAgICAgICAgaWYgKHAxWzFdID4geTEpIHkxID0gcDFbMV07XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBmb3IgKG5hbWUgaW4gdG9wb2xvZ3kub2JqZWN0cykge1xuICAgICAgYmJveEdlb21ldHJ5KHRvcG9sb2d5Lm9iamVjdHNbbmFtZV0pO1xuICAgIH1cblxuICAgIGJib3ggPSB0b3BvbG9neS5iYm94ID0gW3gwLCB5MCwgeDEsIHkxXTtcbiAgfVxuXG4gIHJldHVybiBiYm94O1xufTtcblxudmFyIHJldmVyc2UgPSBmdW5jdGlvbihhcnJheSwgbikge1xuICB2YXIgdCwgaiA9IGFycmF5Lmxlbmd0aCwgaSA9IGogLSBuO1xuICB3aGlsZSAoaSA8IC0taikgdCA9IGFycmF5W2ldLCBhcnJheVtpKytdID0gYXJyYXlbal0sIGFycmF5W2pdID0gdDtcbn07XG5cbnZhciBmZWF0dXJlID0gZnVuY3Rpb24odG9wb2xvZ3ksIG8pIHtcbiAgcmV0dXJuIG8udHlwZSA9PT0gXCJHZW9tZXRyeUNvbGxlY3Rpb25cIlxuICAgICAgPyB7dHlwZTogXCJGZWF0dXJlQ29sbGVjdGlvblwiLCBmZWF0dXJlczogby5nZW9tZXRyaWVzLm1hcChmdW5jdGlvbihvKSB7IHJldHVybiBmZWF0dXJlJDEodG9wb2xvZ3ksIG8pOyB9KX1cbiAgICAgIDogZmVhdHVyZSQxKHRvcG9sb2d5LCBvKTtcbn07XG5cbmZ1bmN0aW9uIGZlYXR1cmUkMSh0b3BvbG9neSwgbykge1xuICB2YXIgaWQgPSBvLmlkLFxuICAgICAgYmJveCA9IG8uYmJveCxcbiAgICAgIHByb3BlcnRpZXMgPSBvLnByb3BlcnRpZXMgPT0gbnVsbCA/IHt9IDogby5wcm9wZXJ0aWVzLFxuICAgICAgZ2VvbWV0cnkgPSBvYmplY3QodG9wb2xvZ3ksIG8pO1xuICByZXR1cm4gaWQgPT0gbnVsbCAmJiBiYm94ID09IG51bGwgPyB7dHlwZTogXCJGZWF0dXJlXCIsIHByb3BlcnRpZXM6IHByb3BlcnRpZXMsIGdlb21ldHJ5OiBnZW9tZXRyeX1cbiAgICAgIDogYmJveCA9PSBudWxsID8ge3R5cGU6IFwiRmVhdHVyZVwiLCBpZDogaWQsIHByb3BlcnRpZXM6IHByb3BlcnRpZXMsIGdlb21ldHJ5OiBnZW9tZXRyeX1cbiAgICAgIDoge3R5cGU6IFwiRmVhdHVyZVwiLCBpZDogaWQsIGJib3g6IGJib3gsIHByb3BlcnRpZXM6IHByb3BlcnRpZXMsIGdlb21ldHJ5OiBnZW9tZXRyeX07XG59XG5cbmZ1bmN0aW9uIG9iamVjdCh0b3BvbG9neSwgbykge1xuICB2YXIgdHJhbnNmb3JtUG9pbnQgPSB0cmFuc2Zvcm0odG9wb2xvZ3kpLFxuICAgICAgYXJjcyA9IHRvcG9sb2d5LmFyY3M7XG5cbiAgZnVuY3Rpb24gYXJjKGksIHBvaW50cykge1xuICAgIGlmIChwb2ludHMubGVuZ3RoKSBwb2ludHMucG9wKCk7XG4gICAgZm9yICh2YXIgYSA9IGFyY3NbaSA8IDAgPyB+aSA6IGldLCBrID0gMCwgbiA9IGEubGVuZ3RoOyBrIDwgbjsgKytrKSB7XG4gICAgICBwb2ludHMucHVzaCh0cmFuc2Zvcm1Qb2ludChhW2tdLnNsaWNlKCksIGspKTtcbiAgICB9XG4gICAgaWYgKGkgPCAwKSByZXZlcnNlKHBvaW50cywgbik7XG4gIH1cblxuICBmdW5jdGlvbiBwb2ludChwKSB7XG4gICAgcmV0dXJuIHRyYW5zZm9ybVBvaW50KHAuc2xpY2UoKSk7XG4gIH1cblxuICBmdW5jdGlvbiBsaW5lKGFyY3MpIHtcbiAgICB2YXIgcG9pbnRzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBhcmNzLmxlbmd0aDsgaSA8IG47ICsraSkgYXJjKGFyY3NbaV0sIHBvaW50cyk7XG4gICAgaWYgKHBvaW50cy5sZW5ndGggPCAyKSBwb2ludHMucHVzaChwb2ludHNbMF0uc2xpY2UoKSk7XG4gICAgcmV0dXJuIHBvaW50cztcbiAgfVxuXG4gIGZ1bmN0aW9uIHJpbmcoYXJjcykge1xuICAgIHZhciBwb2ludHMgPSBsaW5lKGFyY3MpO1xuICAgIHdoaWxlIChwb2ludHMubGVuZ3RoIDwgNCkgcG9pbnRzLnB1c2gocG9pbnRzWzBdLnNsaWNlKCkpO1xuICAgIHJldHVybiBwb2ludHM7XG4gIH1cblxuICBmdW5jdGlvbiBwb2x5Z29uKGFyY3MpIHtcbiAgICByZXR1cm4gYXJjcy5tYXAocmluZyk7XG4gIH1cblxuICBmdW5jdGlvbiBnZW9tZXRyeShvKSB7XG4gICAgdmFyIHR5cGUgPSBvLnR5cGUsIGNvb3JkaW5hdGVzO1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBcIkdlb21ldHJ5Q29sbGVjdGlvblwiOiByZXR1cm4ge3R5cGU6IHR5cGUsIGdlb21ldHJpZXM6IG8uZ2VvbWV0cmllcy5tYXAoZ2VvbWV0cnkpfTtcbiAgICAgIGNhc2UgXCJQb2ludFwiOiBjb29yZGluYXRlcyA9IHBvaW50KG8uY29vcmRpbmF0ZXMpOyBicmVhaztcbiAgICAgIGNhc2UgXCJNdWx0aVBvaW50XCI6IGNvb3JkaW5hdGVzID0gby5jb29yZGluYXRlcy5tYXAocG9pbnQpOyBicmVhaztcbiAgICAgIGNhc2UgXCJMaW5lU3RyaW5nXCI6IGNvb3JkaW5hdGVzID0gbGluZShvLmFyY3MpOyBicmVhaztcbiAgICAgIGNhc2UgXCJNdWx0aUxpbmVTdHJpbmdcIjogY29vcmRpbmF0ZXMgPSBvLmFyY3MubWFwKGxpbmUpOyBicmVhaztcbiAgICAgIGNhc2UgXCJQb2x5Z29uXCI6IGNvb3JkaW5hdGVzID0gcG9seWdvbihvLmFyY3MpOyBicmVhaztcbiAgICAgIGNhc2UgXCJNdWx0aVBvbHlnb25cIjogY29vcmRpbmF0ZXMgPSBvLmFyY3MubWFwKHBvbHlnb24pOyBicmVhaztcbiAgICAgIGRlZmF1bHQ6IHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4ge3R5cGU6IHR5cGUsIGNvb3JkaW5hdGVzOiBjb29yZGluYXRlc307XG4gIH1cblxuICByZXR1cm4gZ2VvbWV0cnkobyk7XG59XG5cbnZhciBzdGl0Y2ggPSBmdW5jdGlvbih0b3BvbG9neSwgYXJjcykge1xuICB2YXIgc3RpdGNoZWRBcmNzID0ge30sXG4gICAgICBmcmFnbWVudEJ5U3RhcnQgPSB7fSxcbiAgICAgIGZyYWdtZW50QnlFbmQgPSB7fSxcbiAgICAgIGZyYWdtZW50cyA9IFtdLFxuICAgICAgZW1wdHlJbmRleCA9IC0xO1xuXG4gIC8vIFN0aXRjaCBlbXB0eSBhcmNzIGZpcnN0LCBzaW5jZSB0aGV5IG1heSBiZSBzdWJzdW1lZCBieSBvdGhlciBhcmNzLlxuICBhcmNzLmZvckVhY2goZnVuY3Rpb24oaSwgaikge1xuICAgIHZhciBhcmMgPSB0b3BvbG9neS5hcmNzW2kgPCAwID8gfmkgOiBpXSwgdDtcbiAgICBpZiAoYXJjLmxlbmd0aCA8IDMgJiYgIWFyY1sxXVswXSAmJiAhYXJjWzFdWzFdKSB7XG4gICAgICB0ID0gYXJjc1srK2VtcHR5SW5kZXhdLCBhcmNzW2VtcHR5SW5kZXhdID0gaSwgYXJjc1tqXSA9IHQ7XG4gICAgfVxuICB9KTtcblxuICBhcmNzLmZvckVhY2goZnVuY3Rpb24oaSkge1xuICAgIHZhciBlID0gZW5kcyhpKSxcbiAgICAgICAgc3RhcnQgPSBlWzBdLFxuICAgICAgICBlbmQgPSBlWzFdLFxuICAgICAgICBmLCBnO1xuXG4gICAgaWYgKGYgPSBmcmFnbWVudEJ5RW5kW3N0YXJ0XSkge1xuICAgICAgZGVsZXRlIGZyYWdtZW50QnlFbmRbZi5lbmRdO1xuICAgICAgZi5wdXNoKGkpO1xuICAgICAgZi5lbmQgPSBlbmQ7XG4gICAgICBpZiAoZyA9IGZyYWdtZW50QnlTdGFydFtlbmRdKSB7XG4gICAgICAgIGRlbGV0ZSBmcmFnbWVudEJ5U3RhcnRbZy5zdGFydF07XG4gICAgICAgIHZhciBmZyA9IGcgPT09IGYgPyBmIDogZi5jb25jYXQoZyk7XG4gICAgICAgIGZyYWdtZW50QnlTdGFydFtmZy5zdGFydCA9IGYuc3RhcnRdID0gZnJhZ21lbnRCeUVuZFtmZy5lbmQgPSBnLmVuZF0gPSBmZztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZyYWdtZW50QnlTdGFydFtmLnN0YXJ0XSA9IGZyYWdtZW50QnlFbmRbZi5lbmRdID0gZjtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGYgPSBmcmFnbWVudEJ5U3RhcnRbZW5kXSkge1xuICAgICAgZGVsZXRlIGZyYWdtZW50QnlTdGFydFtmLnN0YXJ0XTtcbiAgICAgIGYudW5zaGlmdChpKTtcbiAgICAgIGYuc3RhcnQgPSBzdGFydDtcbiAgICAgIGlmIChnID0gZnJhZ21lbnRCeUVuZFtzdGFydF0pIHtcbiAgICAgICAgZGVsZXRlIGZyYWdtZW50QnlFbmRbZy5lbmRdO1xuICAgICAgICB2YXIgZ2YgPSBnID09PSBmID8gZiA6IGcuY29uY2F0KGYpO1xuICAgICAgICBmcmFnbWVudEJ5U3RhcnRbZ2Yuc3RhcnQgPSBnLnN0YXJ0XSA9IGZyYWdtZW50QnlFbmRbZ2YuZW5kID0gZi5lbmRdID0gZ2Y7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmcmFnbWVudEJ5U3RhcnRbZi5zdGFydF0gPSBmcmFnbWVudEJ5RW5kW2YuZW5kXSA9IGY7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGYgPSBbaV07XG4gICAgICBmcmFnbWVudEJ5U3RhcnRbZi5zdGFydCA9IHN0YXJ0XSA9IGZyYWdtZW50QnlFbmRbZi5lbmQgPSBlbmRdID0gZjtcbiAgICB9XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGVuZHMoaSkge1xuICAgIHZhciBhcmMgPSB0b3BvbG9neS5hcmNzW2kgPCAwID8gfmkgOiBpXSwgcDAgPSBhcmNbMF0sIHAxO1xuICAgIGlmICh0b3BvbG9neS50cmFuc2Zvcm0pIHAxID0gWzAsIDBdLCBhcmMuZm9yRWFjaChmdW5jdGlvbihkcCkgeyBwMVswXSArPSBkcFswXSwgcDFbMV0gKz0gZHBbMV07IH0pO1xuICAgIGVsc2UgcDEgPSBhcmNbYXJjLmxlbmd0aCAtIDFdO1xuICAgIHJldHVybiBpIDwgMCA/IFtwMSwgcDBdIDogW3AwLCBwMV07XG4gIH1cblxuICBmdW5jdGlvbiBmbHVzaChmcmFnbWVudEJ5RW5kLCBmcmFnbWVudEJ5U3RhcnQpIHtcbiAgICBmb3IgKHZhciBrIGluIGZyYWdtZW50QnlFbmQpIHtcbiAgICAgIHZhciBmID0gZnJhZ21lbnRCeUVuZFtrXTtcbiAgICAgIGRlbGV0ZSBmcmFnbWVudEJ5U3RhcnRbZi5zdGFydF07XG4gICAgICBkZWxldGUgZi5zdGFydDtcbiAgICAgIGRlbGV0ZSBmLmVuZDtcbiAgICAgIGYuZm9yRWFjaChmdW5jdGlvbihpKSB7IHN0aXRjaGVkQXJjc1tpIDwgMCA/IH5pIDogaV0gPSAxOyB9KTtcbiAgICAgIGZyYWdtZW50cy5wdXNoKGYpO1xuICAgIH1cbiAgfVxuXG4gIGZsdXNoKGZyYWdtZW50QnlFbmQsIGZyYWdtZW50QnlTdGFydCk7XG4gIGZsdXNoKGZyYWdtZW50QnlTdGFydCwgZnJhZ21lbnRCeUVuZCk7XG4gIGFyY3MuZm9yRWFjaChmdW5jdGlvbihpKSB7IGlmICghc3RpdGNoZWRBcmNzW2kgPCAwID8gfmkgOiBpXSkgZnJhZ21lbnRzLnB1c2goW2ldKTsgfSk7XG5cbiAgcmV0dXJuIGZyYWdtZW50cztcbn07XG5cbnZhciBtZXNoID0gZnVuY3Rpb24odG9wb2xvZ3kpIHtcbiAgcmV0dXJuIG9iamVjdCh0b3BvbG9neSwgbWVzaEFyY3MuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG59O1xuXG5mdW5jdGlvbiBtZXNoQXJjcyh0b3BvbG9neSwgb2JqZWN0JCQxLCBmaWx0ZXIpIHtcbiAgdmFyIGFyY3MsIGksIG47XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkgYXJjcyA9IGV4dHJhY3RBcmNzKHRvcG9sb2d5LCBvYmplY3QkJDEsIGZpbHRlcik7XG4gIGVsc2UgZm9yIChpID0gMCwgYXJjcyA9IG5ldyBBcnJheShuID0gdG9wb2xvZ3kuYXJjcy5sZW5ndGgpOyBpIDwgbjsgKytpKSBhcmNzW2ldID0gaTtcbiAgcmV0dXJuIHt0eXBlOiBcIk11bHRpTGluZVN0cmluZ1wiLCBhcmNzOiBzdGl0Y2godG9wb2xvZ3ksIGFyY3MpfTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdEFyY3ModG9wb2xvZ3ksIG9iamVjdCQkMSwgZmlsdGVyKSB7XG4gIHZhciBhcmNzID0gW10sXG4gICAgICBnZW9tc0J5QXJjID0gW10sXG4gICAgICBnZW9tO1xuXG4gIGZ1bmN0aW9uIGV4dHJhY3QwKGkpIHtcbiAgICB2YXIgaiA9IGkgPCAwID8gfmkgOiBpO1xuICAgIChnZW9tc0J5QXJjW2pdIHx8IChnZW9tc0J5QXJjW2pdID0gW10pKS5wdXNoKHtpOiBpLCBnOiBnZW9tfSk7XG4gIH1cblxuICBmdW5jdGlvbiBleHRyYWN0MShhcmNzKSB7XG4gICAgYXJjcy5mb3JFYWNoKGV4dHJhY3QwKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGV4dHJhY3QyKGFyY3MpIHtcbiAgICBhcmNzLmZvckVhY2goZXh0cmFjdDEpO1xuICB9XG5cbiAgZnVuY3Rpb24gZXh0cmFjdDMoYXJjcykge1xuICAgIGFyY3MuZm9yRWFjaChleHRyYWN0Mik7XG4gIH1cblxuICBmdW5jdGlvbiBnZW9tZXRyeShvKSB7XG4gICAgc3dpdGNoIChnZW9tID0gbywgby50eXBlKSB7XG4gICAgICBjYXNlIFwiR2VvbWV0cnlDb2xsZWN0aW9uXCI6IG8uZ2VvbWV0cmllcy5mb3JFYWNoKGdlb21ldHJ5KTsgYnJlYWs7XG4gICAgICBjYXNlIFwiTGluZVN0cmluZ1wiOiBleHRyYWN0MShvLmFyY3MpOyBicmVhaztcbiAgICAgIGNhc2UgXCJNdWx0aUxpbmVTdHJpbmdcIjogY2FzZSBcIlBvbHlnb25cIjogZXh0cmFjdDIoby5hcmNzKTsgYnJlYWs7XG4gICAgICBjYXNlIFwiTXVsdGlQb2x5Z29uXCI6IGV4dHJhY3QzKG8uYXJjcyk7IGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGdlb21ldHJ5KG9iamVjdCQkMSk7XG5cbiAgZ2VvbXNCeUFyYy5mb3JFYWNoKGZpbHRlciA9PSBudWxsXG4gICAgICA/IGZ1bmN0aW9uKGdlb21zKSB7IGFyY3MucHVzaChnZW9tc1swXS5pKTsgfVxuICAgICAgOiBmdW5jdGlvbihnZW9tcykgeyBpZiAoZmlsdGVyKGdlb21zWzBdLmcsIGdlb21zW2dlb21zLmxlbmd0aCAtIDFdLmcpKSBhcmNzLnB1c2goZ2VvbXNbMF0uaSk7IH0pO1xuXG4gIHJldHVybiBhcmNzO1xufVxuXG5mdW5jdGlvbiBwbGFuYXJSaW5nQXJlYShyaW5nKSB7XG4gIHZhciBpID0gLTEsIG4gPSByaW5nLmxlbmd0aCwgYSwgYiA9IHJpbmdbbiAtIDFdLCBhcmVhID0gMDtcbiAgd2hpbGUgKCsraSA8IG4pIGEgPSBiLCBiID0gcmluZ1tpXSwgYXJlYSArPSBhWzBdICogYlsxXSAtIGFbMV0gKiBiWzBdO1xuICByZXR1cm4gTWF0aC5hYnMoYXJlYSk7IC8vIE5vdGU6IGRvdWJsZWQgYXJlYSFcbn1cblxudmFyIG1lcmdlID0gZnVuY3Rpb24odG9wb2xvZ3kpIHtcbiAgcmV0dXJuIG9iamVjdCh0b3BvbG9neSwgbWVyZ2VBcmNzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpO1xufTtcblxuZnVuY3Rpb24gbWVyZ2VBcmNzKHRvcG9sb2d5LCBvYmplY3RzKSB7XG4gIHZhciBwb2x5Z29uc0J5QXJjID0ge30sXG4gICAgICBwb2x5Z29ucyA9IFtdLFxuICAgICAgZ3JvdXBzID0gW107XG5cbiAgb2JqZWN0cy5mb3JFYWNoKGdlb21ldHJ5KTtcblxuICBmdW5jdGlvbiBnZW9tZXRyeShvKSB7XG4gICAgc3dpdGNoIChvLnR5cGUpIHtcbiAgICAgIGNhc2UgXCJHZW9tZXRyeUNvbGxlY3Rpb25cIjogby5nZW9tZXRyaWVzLmZvckVhY2goZ2VvbWV0cnkpOyBicmVhaztcbiAgICAgIGNhc2UgXCJQb2x5Z29uXCI6IGV4dHJhY3Qoby5hcmNzKTsgYnJlYWs7XG4gICAgICBjYXNlIFwiTXVsdGlQb2x5Z29uXCI6IG8uYXJjcy5mb3JFYWNoKGV4dHJhY3QpOyBicmVhaztcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBleHRyYWN0KHBvbHlnb24pIHtcbiAgICBwb2x5Z29uLmZvckVhY2goZnVuY3Rpb24ocmluZykge1xuICAgICAgcmluZy5mb3JFYWNoKGZ1bmN0aW9uKGFyYykge1xuICAgICAgICAocG9seWdvbnNCeUFyY1thcmMgPSBhcmMgPCAwID8gfmFyYyA6IGFyY10gfHwgKHBvbHlnb25zQnlBcmNbYXJjXSA9IFtdKSkucHVzaChwb2x5Z29uKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHBvbHlnb25zLnB1c2gocG9seWdvbik7XG4gIH1cblxuICBmdW5jdGlvbiBhcmVhKHJpbmcpIHtcbiAgICByZXR1cm4gcGxhbmFyUmluZ0FyZWEob2JqZWN0KHRvcG9sb2d5LCB7dHlwZTogXCJQb2x5Z29uXCIsIGFyY3M6IFtyaW5nXX0pLmNvb3JkaW5hdGVzWzBdKTtcbiAgfVxuXG4gIHBvbHlnb25zLmZvckVhY2goZnVuY3Rpb24ocG9seWdvbikge1xuICAgIGlmICghcG9seWdvbi5fKSB7XG4gICAgICB2YXIgZ3JvdXAgPSBbXSxcbiAgICAgICAgICBuZWlnaGJvcnMgPSBbcG9seWdvbl07XG4gICAgICBwb2x5Z29uLl8gPSAxO1xuICAgICAgZ3JvdXBzLnB1c2goZ3JvdXApO1xuICAgICAgd2hpbGUgKHBvbHlnb24gPSBuZWlnaGJvcnMucG9wKCkpIHtcbiAgICAgICAgZ3JvdXAucHVzaChwb2x5Z29uKTtcbiAgICAgICAgcG9seWdvbi5mb3JFYWNoKGZ1bmN0aW9uKHJpbmcpIHtcbiAgICAgICAgICByaW5nLmZvckVhY2goZnVuY3Rpb24oYXJjKSB7XG4gICAgICAgICAgICBwb2x5Z29uc0J5QXJjW2FyYyA8IDAgPyB+YXJjIDogYXJjXS5mb3JFYWNoKGZ1bmN0aW9uKHBvbHlnb24pIHtcbiAgICAgICAgICAgICAgaWYgKCFwb2x5Z29uLl8pIHtcbiAgICAgICAgICAgICAgICBwb2x5Z29uLl8gPSAxO1xuICAgICAgICAgICAgICAgIG5laWdoYm9ycy5wdXNoKHBvbHlnb24pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICBwb2x5Z29ucy5mb3JFYWNoKGZ1bmN0aW9uKHBvbHlnb24pIHtcbiAgICBkZWxldGUgcG9seWdvbi5fO1xuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHR5cGU6IFwiTXVsdGlQb2x5Z29uXCIsXG4gICAgYXJjczogZ3JvdXBzLm1hcChmdW5jdGlvbihwb2x5Z29ucykge1xuICAgICAgdmFyIGFyY3MgPSBbXSwgbjtcblxuICAgICAgLy8gRXh0cmFjdCB0aGUgZXh0ZXJpb3IgKHVuaXF1ZSkgYXJjcy5cbiAgICAgIHBvbHlnb25zLmZvckVhY2goZnVuY3Rpb24ocG9seWdvbikge1xuICAgICAgICBwb2x5Z29uLmZvckVhY2goZnVuY3Rpb24ocmluZykge1xuICAgICAgICAgIHJpbmcuZm9yRWFjaChmdW5jdGlvbihhcmMpIHtcbiAgICAgICAgICAgIGlmIChwb2x5Z29uc0J5QXJjW2FyYyA8IDAgPyB+YXJjIDogYXJjXS5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICAgIGFyY3MucHVzaChhcmMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBTdGl0Y2ggdGhlIGFyY3MgaW50byBvbmUgb3IgbW9yZSByaW5ncy5cbiAgICAgIGFyY3MgPSBzdGl0Y2godG9wb2xvZ3ksIGFyY3MpO1xuXG4gICAgICAvLyBJZiBtb3JlIHRoYW4gb25lIHJpbmcgaXMgcmV0dXJuZWQsXG4gICAgICAvLyBhdCBtb3N0IG9uZSBvZiB0aGVzZSByaW5ncyBjYW4gYmUgdGhlIGV4dGVyaW9yO1xuICAgICAgLy8gY2hvb3NlIHRoZSBvbmUgd2l0aCB0aGUgZ3JlYXRlc3QgYWJzb2x1dGUgYXJlYS5cbiAgICAgIGlmICgobiA9IGFyY3MubGVuZ3RoKSA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDEsIGsgPSBhcmVhKGFyY3NbMF0pLCBraSwgdDsgaSA8IG47ICsraSkge1xuICAgICAgICAgIGlmICgoa2kgPSBhcmVhKGFyY3NbaV0pKSA+IGspIHtcbiAgICAgICAgICAgIHQgPSBhcmNzWzBdLCBhcmNzWzBdID0gYXJjc1tpXSwgYXJjc1tpXSA9IHQsIGsgPSBraTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGFyY3M7XG4gICAgfSlcbiAgfTtcbn1cblxudmFyIGJpc2VjdCA9IGZ1bmN0aW9uKGEsIHgpIHtcbiAgdmFyIGxvID0gMCwgaGkgPSBhLmxlbmd0aDtcbiAgd2hpbGUgKGxvIDwgaGkpIHtcbiAgICB2YXIgbWlkID0gbG8gKyBoaSA+Pj4gMTtcbiAgICBpZiAoYVttaWRdIDwgeCkgbG8gPSBtaWQgKyAxO1xuICAgIGVsc2UgaGkgPSBtaWQ7XG4gIH1cbiAgcmV0dXJuIGxvO1xufTtcblxudmFyIG5laWdoYm9ycyA9IGZ1bmN0aW9uKG9iamVjdHMpIHtcbiAgdmFyIGluZGV4ZXNCeUFyYyA9IHt9LCAvLyBhcmMgaW5kZXggLT4gYXJyYXkgb2Ygb2JqZWN0IGluZGV4ZXNcbiAgICAgIG5laWdoYm9ycyA9IG9iamVjdHMubWFwKGZ1bmN0aW9uKCkgeyByZXR1cm4gW107IH0pO1xuXG4gIGZ1bmN0aW9uIGxpbmUoYXJjcywgaSkge1xuICAgIGFyY3MuZm9yRWFjaChmdW5jdGlvbihhKSB7XG4gICAgICBpZiAoYSA8IDApIGEgPSB+YTtcbiAgICAgIHZhciBvID0gaW5kZXhlc0J5QXJjW2FdO1xuICAgICAgaWYgKG8pIG8ucHVzaChpKTtcbiAgICAgIGVsc2UgaW5kZXhlc0J5QXJjW2FdID0gW2ldO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gcG9seWdvbihhcmNzLCBpKSB7XG4gICAgYXJjcy5mb3JFYWNoKGZ1bmN0aW9uKGFyYykgeyBsaW5lKGFyYywgaSk7IH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2VvbWV0cnkobywgaSkge1xuICAgIGlmIChvLnR5cGUgPT09IFwiR2VvbWV0cnlDb2xsZWN0aW9uXCIpIG8uZ2VvbWV0cmllcy5mb3JFYWNoKGZ1bmN0aW9uKG8pIHsgZ2VvbWV0cnkobywgaSk7IH0pO1xuICAgIGVsc2UgaWYgKG8udHlwZSBpbiBnZW9tZXRyeVR5cGUpIGdlb21ldHJ5VHlwZVtvLnR5cGVdKG8uYXJjcywgaSk7XG4gIH1cblxuICB2YXIgZ2VvbWV0cnlUeXBlID0ge1xuICAgIExpbmVTdHJpbmc6IGxpbmUsXG4gICAgTXVsdGlMaW5lU3RyaW5nOiBwb2x5Z29uLFxuICAgIFBvbHlnb246IHBvbHlnb24sXG4gICAgTXVsdGlQb2x5Z29uOiBmdW5jdGlvbihhcmNzLCBpKSB7IGFyY3MuZm9yRWFjaChmdW5jdGlvbihhcmMpIHsgcG9seWdvbihhcmMsIGkpOyB9KTsgfVxuICB9O1xuXG4gIG9iamVjdHMuZm9yRWFjaChnZW9tZXRyeSk7XG5cbiAgZm9yICh2YXIgaSBpbiBpbmRleGVzQnlBcmMpIHtcbiAgICBmb3IgKHZhciBpbmRleGVzID0gaW5kZXhlc0J5QXJjW2ldLCBtID0gaW5kZXhlcy5sZW5ndGgsIGogPSAwOyBqIDwgbTsgKytqKSB7XG4gICAgICBmb3IgKHZhciBrID0gaiArIDE7IGsgPCBtOyArK2spIHtcbiAgICAgICAgdmFyIGlqID0gaW5kZXhlc1tqXSwgaWsgPSBpbmRleGVzW2tdLCBuO1xuICAgICAgICBpZiAoKG4gPSBuZWlnaGJvcnNbaWpdKVtpID0gYmlzZWN0KG4sIGlrKV0gIT09IGlrKSBuLnNwbGljZShpLCAwLCBpayk7XG4gICAgICAgIGlmICgobiA9IG5laWdoYm9yc1tpa10pW2kgPSBiaXNlY3QobiwgaWopXSAhPT0gaWopIG4uc3BsaWNlKGksIDAsIGlqKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmVpZ2hib3JzO1xufTtcblxudmFyIHF1YW50aXplID0gZnVuY3Rpb24odG9wb2xvZ3ksIG4pIHtcbiAgaWYgKCEoKG4gPSBNYXRoLmZsb29yKG4pKSA+PSAyKSkgdGhyb3cgbmV3IEVycm9yKFwibiBtdXN0IGJlIOKJpTJcIik7XG4gIGlmICh0b3BvbG9neS50cmFuc2Zvcm0pIHRocm93IG5ldyBFcnJvcihcImFscmVhZHkgcXVhbnRpemVkXCIpO1xuICB2YXIgYmIgPSBiYm94KHRvcG9sb2d5KSwgbmFtZSxcbiAgICAgIGR4ID0gYmJbMF0sIGt4ID0gKGJiWzJdIC0gZHgpIC8gKG4gLSAxKSB8fCAxLFxuICAgICAgZHkgPSBiYlsxXSwga3kgPSAoYmJbM10gLSBkeSkgLyAobiAtIDEpIHx8IDE7XG5cbiAgZnVuY3Rpb24gcXVhbnRpemVQb2ludChwKSB7XG4gICAgcFswXSA9IE1hdGgucm91bmQoKHBbMF0gLSBkeCkgLyBreCk7XG4gICAgcFsxXSA9IE1hdGgucm91bmQoKHBbMV0gLSBkeSkgLyBreSk7XG4gIH1cblxuICBmdW5jdGlvbiBxdWFudGl6ZUdlb21ldHJ5KG8pIHtcbiAgICBzd2l0Y2ggKG8udHlwZSkge1xuICAgICAgY2FzZSBcIkdlb21ldHJ5Q29sbGVjdGlvblwiOiBvLmdlb21ldHJpZXMuZm9yRWFjaChxdWFudGl6ZUdlb21ldHJ5KTsgYnJlYWs7XG4gICAgICBjYXNlIFwiUG9pbnRcIjogcXVhbnRpemVQb2ludChvLmNvb3JkaW5hdGVzKTsgYnJlYWs7XG4gICAgICBjYXNlIFwiTXVsdGlQb2ludFwiOiBvLmNvb3JkaW5hdGVzLmZvckVhY2gocXVhbnRpemVQb2ludCk7IGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHRvcG9sb2d5LmFyY3MuZm9yRWFjaChmdW5jdGlvbihhcmMpIHtcbiAgICB2YXIgaSA9IDEsXG4gICAgICAgIGogPSAxLFxuICAgICAgICBuID0gYXJjLmxlbmd0aCxcbiAgICAgICAgcGkgPSBhcmNbMF0sXG4gICAgICAgIHgwID0gcGlbMF0gPSBNYXRoLnJvdW5kKChwaVswXSAtIGR4KSAvIGt4KSxcbiAgICAgICAgeTAgPSBwaVsxXSA9IE1hdGgucm91bmQoKHBpWzFdIC0gZHkpIC8ga3kpLFxuICAgICAgICBwaixcbiAgICAgICAgeDEsXG4gICAgICAgIHkxO1xuXG4gICAgZm9yICg7IGkgPCBuOyArK2kpIHtcbiAgICAgIHBpID0gYXJjW2ldO1xuICAgICAgeDEgPSBNYXRoLnJvdW5kKChwaVswXSAtIGR4KSAvIGt4KTtcbiAgICAgIHkxID0gTWF0aC5yb3VuZCgocGlbMV0gLSBkeSkgLyBreSk7XG4gICAgICBpZiAoeDEgIT09IHgwIHx8IHkxICE9PSB5MCkge1xuICAgICAgICBwaiA9IGFyY1tqKytdO1xuICAgICAgICBwalswXSA9IHgxIC0geDAsIHgwID0geDE7XG4gICAgICAgIHBqWzFdID0geTEgLSB5MCwgeTAgPSB5MTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaiA8IDIpIHtcbiAgICAgIHBqID0gYXJjW2orK107XG4gICAgICBwalswXSA9IDA7XG4gICAgICBwalsxXSA9IDA7XG4gICAgfVxuXG4gICAgYXJjLmxlbmd0aCA9IGo7XG4gIH0pO1xuXG4gIGZvciAobmFtZSBpbiB0b3BvbG9neS5vYmplY3RzKSB7XG4gICAgcXVhbnRpemVHZW9tZXRyeSh0b3BvbG9neS5vYmplY3RzW25hbWVdKTtcbiAgfVxuXG4gIHRvcG9sb2d5LnRyYW5zZm9ybSA9IHtcbiAgICBzY2FsZTogW2t4LCBreV0sXG4gICAgdHJhbnNsYXRlOiBbZHgsIGR5XVxuICB9O1xuXG4gIHJldHVybiB0b3BvbG9neTtcbn07XG5cbnZhciB1bnRyYW5zZm9ybSA9IGZ1bmN0aW9uKHRvcG9sb2d5KSB7XG4gIGlmICgodHJhbnNmb3JtID0gdG9wb2xvZ3kudHJhbnNmb3JtKSA9PSBudWxsKSByZXR1cm4gaWRlbnRpdHk7XG4gIHZhciB0cmFuc2Zvcm0sXG4gICAgICB4MCxcbiAgICAgIHkwLFxuICAgICAga3ggPSB0cmFuc2Zvcm0uc2NhbGVbMF0sXG4gICAgICBreSA9IHRyYW5zZm9ybS5zY2FsZVsxXSxcbiAgICAgIGR4ID0gdHJhbnNmb3JtLnRyYW5zbGF0ZVswXSxcbiAgICAgIGR5ID0gdHJhbnNmb3JtLnRyYW5zbGF0ZVsxXTtcbiAgcmV0dXJuIGZ1bmN0aW9uKHBvaW50LCBpKSB7XG4gICAgaWYgKCFpKSB4MCA9IHkwID0gMDtcbiAgICB2YXIgeDEgPSBNYXRoLnJvdW5kKChwb2ludFswXSAtIGR4KSAvIGt4KSxcbiAgICAgICAgeTEgPSBNYXRoLnJvdW5kKChwb2ludFsxXSAtIGR5KSAvIGt5KTtcbiAgICBwb2ludFswXSA9IHgxIC0geDAsIHgwID0geDE7XG4gICAgcG9pbnRbMV0gPSB5MSAtIHkwLCB5MCA9IHkxO1xuICAgIHJldHVybiBwb2ludDtcbiAgfTtcbn07XG5cbmV4cG9ydHMuYmJveCA9IGJib3g7XG5leHBvcnRzLmZlYXR1cmUgPSBmZWF0dXJlO1xuZXhwb3J0cy5tZXNoID0gbWVzaDtcbmV4cG9ydHMubWVzaEFyY3MgPSBtZXNoQXJjcztcbmV4cG9ydHMubWVyZ2UgPSBtZXJnZTtcbmV4cG9ydHMubWVyZ2VBcmNzID0gbWVyZ2VBcmNzO1xuZXhwb3J0cy5uZWlnaGJvcnMgPSBuZWlnaGJvcnM7XG5leHBvcnRzLnF1YW50aXplID0gcXVhbnRpemU7XG5leHBvcnRzLnRyYW5zZm9ybSA9IHRyYW5zZm9ybTtcbmV4cG9ydHMudW50cmFuc2Zvcm0gPSB1bnRyYW5zZm9ybTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcblxufSx7fV0sNTQxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gdHJpYW5ndWxhdGVDdWJlXG5cbnZhciBwZXJtID0gX2RlcmVxXyhcInBlcm11dGF0aW9uLXJhbmtcIilcbnZhciBzZ24gPSBfZGVyZXFfKFwicGVybXV0YXRpb24tcGFyaXR5XCIpXG52YXIgZ2FtbWEgPSBfZGVyZXFfKFwiZ2FtbWFcIilcblxuZnVuY3Rpb24gdHJpYW5ndWxhdGVDdWJlKGRpbWVuc2lvbikge1xuICBpZihkaW1lbnNpb24gPCAwKSB7XG4gICAgcmV0dXJuIFsgXVxuICB9XG4gIGlmKGRpbWVuc2lvbiA9PT0gMCkge1xuICAgIHJldHVybiBbIFswXSBdXG4gIH1cbiAgdmFyIGRmYWN0b3JpYWwgPSBNYXRoLnJvdW5kKGdhbW1hKGRpbWVuc2lvbisxKSl8MFxuICB2YXIgcmVzdWx0ID0gW11cbiAgZm9yKHZhciBpPTA7IGk8ZGZhY3RvcmlhbDsgKytpKSB7XG4gICAgdmFyIHAgPSBwZXJtLnVucmFuayhkaW1lbnNpb24sIGkpXG4gICAgdmFyIGNlbGwgPSBbIDAgXVxuICAgIHZhciB2ID0gMFxuICAgIGZvcih2YXIgaj0wOyBqPHAubGVuZ3RoOyArK2opIHtcbiAgICAgIHYgKz0gKDE8PHBbal0pXG4gICAgICBjZWxsLnB1c2godilcbiAgICB9XG4gICAgaWYoc2duKHApIDwgMSkge1xuICAgICAgY2VsbFswXSA9IHZcbiAgICAgIGNlbGxbZGltZW5zaW9uXSA9IDBcbiAgICB9XG4gICAgcmVzdWx0LnB1c2goY2VsbClcbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG59LHtcImdhbW1hXCI6MjMxLFwicGVybXV0YXRpb24tcGFyaXR5XCI6NDYzLFwicGVybXV0YXRpb24tcmFua1wiOjQ2NH1dLDU0MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4ndXNlIHN0cmljdCdcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVUdXJudGFibGVDb250cm9sbGVyXG5cbnZhciBmaWx0ZXJWZWN0b3IgPSBfZGVyZXFfKCdmaWx0ZXJlZC12ZWN0b3InKVxudmFyIGludmVydDQ0ICAgICA9IF9kZXJlcV8oJ2dsLW1hdDQvaW52ZXJ0JylcbnZhciByb3RhdGVNICAgICAgPSBfZGVyZXFfKCdnbC1tYXQ0L3JvdGF0ZScpXG52YXIgY3Jvc3MgICAgICAgID0gX2RlcmVxXygnZ2wtdmVjMy9jcm9zcycpXG52YXIgbm9ybWFsaXplMyAgID0gX2RlcmVxXygnZ2wtdmVjMy9ub3JtYWxpemUnKVxudmFyIGRvdDMgICAgICAgICA9IF9kZXJlcV8oJ2dsLXZlYzMvZG90JylcblxuZnVuY3Rpb24gbGVuMyh4LCB5LCB6KSB7XG4gIHJldHVybiBNYXRoLnNxcnQoTWF0aC5wb3coeCwgMikgKyBNYXRoLnBvdyh5LCAyKSArIE1hdGgucG93KHosIDIpKVxufVxuXG5mdW5jdGlvbiBjbGFtcDEoeCkge1xuICByZXR1cm4gTWF0aC5taW4oMS4wLCBNYXRoLm1heCgtMS4wLCB4KSlcbn1cblxuZnVuY3Rpb24gZmluZE9ydGhvUGFpcih2KSB7XG4gIHZhciB2eCA9IE1hdGguYWJzKHZbMF0pXG4gIHZhciB2eSA9IE1hdGguYWJzKHZbMV0pXG4gIHZhciB2eiA9IE1hdGguYWJzKHZbMl0pXG5cbiAgdmFyIHUgPSBbMCwwLDBdXG4gIGlmKHZ4ID4gTWF0aC5tYXgodnksIHZ6KSkge1xuICAgIHVbMl0gPSAxXG4gIH0gZWxzZSBpZih2eSA+IE1hdGgubWF4KHZ4LCB2eikpIHtcbiAgICB1WzBdID0gMVxuICB9IGVsc2Uge1xuICAgIHVbMV0gPSAxXG4gIH1cblxuICB2YXIgdnYgPSAwXG4gIHZhciB1diA9IDBcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpICkge1xuICAgIHZ2ICs9IHZbaV0gKiB2W2ldXG4gICAgdXYgKz0gdVtpXSAqIHZbaV1cbiAgfVxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICB1W2ldIC09ICh1diAvIHZ2KSAqICB2W2ldXG4gIH1cbiAgbm9ybWFsaXplMyh1LCB1KVxuICByZXR1cm4gdVxufVxuXG5mdW5jdGlvbiBUdXJudGFibGVDb250cm9sbGVyKHpvb21NaW4sIHpvb21NYXgsIGNlbnRlciwgdXAsIHJpZ2h0LCByYWRpdXMsIHRoZXRhLCBwaGkpIHtcbiAgdGhpcy5jZW50ZXIgPSBmaWx0ZXJWZWN0b3IoY2VudGVyKVxuICB0aGlzLnVwICAgICA9IGZpbHRlclZlY3Rvcih1cClcbiAgdGhpcy5yaWdodCAgPSBmaWx0ZXJWZWN0b3IocmlnaHQpXG4gIHRoaXMucmFkaXVzID0gZmlsdGVyVmVjdG9yKFtyYWRpdXNdKVxuICB0aGlzLmFuZ2xlICA9IGZpbHRlclZlY3RvcihbdGhldGEsIHBoaV0pXG4gIHRoaXMuYW5nbGUuYm91bmRzID0gW1stSW5maW5pdHksLU1hdGguUEkvMl0sIFtJbmZpbml0eSxNYXRoLlBJLzJdXVxuICB0aGlzLnNldERpc3RhbmNlTGltaXRzKHpvb21NaW4sIHpvb21NYXgpXG5cbiAgdGhpcy5jb21wdXRlZENlbnRlciA9IHRoaXMuY2VudGVyLmN1cnZlKDApXG4gIHRoaXMuY29tcHV0ZWRVcCAgICAgPSB0aGlzLnVwLmN1cnZlKDApXG4gIHRoaXMuY29tcHV0ZWRSaWdodCAgPSB0aGlzLnJpZ2h0LmN1cnZlKDApXG4gIHRoaXMuY29tcHV0ZWRSYWRpdXMgPSB0aGlzLnJhZGl1cy5jdXJ2ZSgwKVxuICB0aGlzLmNvbXB1dGVkQW5nbGUgID0gdGhpcy5hbmdsZS5jdXJ2ZSgwKVxuICB0aGlzLmNvbXB1dGVkVG93YXJkID0gWzAsMCwwXVxuICB0aGlzLmNvbXB1dGVkRXllICAgID0gWzAsMCwwXVxuICB0aGlzLmNvbXB1dGVkTWF0cml4ID0gbmV3IEFycmF5KDE2KVxuICBmb3IodmFyIGk9MDsgaTwxNjsgKytpKSB7XG4gICAgdGhpcy5jb21wdXRlZE1hdHJpeFtpXSA9IDAuNVxuICB9XG5cbiAgdGhpcy5yZWNhbGNNYXRyaXgoMClcbn1cblxudmFyIHByb3RvID0gVHVybnRhYmxlQ29udHJvbGxlci5wcm90b3R5cGVcblxucHJvdG8uc2V0RGlzdGFuY2VMaW1pdHMgPSBmdW5jdGlvbihtaW5EaXN0LCBtYXhEaXN0KSB7XG4gIGlmKG1pbkRpc3QgPiAwKSB7XG4gICAgbWluRGlzdCA9IE1hdGgubG9nKG1pbkRpc3QpXG4gIH0gZWxzZSB7XG4gICAgbWluRGlzdCA9IC1JbmZpbml0eVxuICB9XG4gIGlmKG1heERpc3QgPiAwKSB7XG4gICAgbWF4RGlzdCA9IE1hdGgubG9nKG1heERpc3QpXG4gIH0gZWxzZSB7XG4gICAgbWF4RGlzdCA9IEluZmluaXR5XG4gIH1cbiAgbWF4RGlzdCA9IE1hdGgubWF4KG1heERpc3QsIG1pbkRpc3QpXG4gIHRoaXMucmFkaXVzLmJvdW5kc1swXVswXSA9IG1pbkRpc3RcbiAgdGhpcy5yYWRpdXMuYm91bmRzWzFdWzBdID0gbWF4RGlzdFxufVxuXG5wcm90by5nZXREaXN0YW5jZUxpbWl0cyA9IGZ1bmN0aW9uKG91dCkge1xuICB2YXIgYm91bmRzID0gdGhpcy5yYWRpdXMuYm91bmRzWzBdXG4gIGlmKG91dCkge1xuICAgIG91dFswXSA9IE1hdGguZXhwKGJvdW5kc1swXVswXSlcbiAgICBvdXRbMV0gPSBNYXRoLmV4cChib3VuZHNbMV1bMF0pXG4gICAgcmV0dXJuIG91dFxuICB9XG4gIHJldHVybiBbIE1hdGguZXhwKGJvdW5kc1swXVswXSksIE1hdGguZXhwKGJvdW5kc1sxXVswXSkgXVxufVxuXG5wcm90by5yZWNhbGNNYXRyaXggPSBmdW5jdGlvbih0KSB7XG4gIC8vUmVjb21wdXRlIGN1cnZlc1xuICB0aGlzLmNlbnRlci5jdXJ2ZSh0KVxuICB0aGlzLnVwLmN1cnZlKHQpXG4gIHRoaXMucmlnaHQuY3VydmUodClcbiAgdGhpcy5yYWRpdXMuY3VydmUodClcbiAgdGhpcy5hbmdsZS5jdXJ2ZSh0KVxuXG4gIC8vQ29tcHV0ZSBmcmFtZSBmb3IgY2FtZXJhIG1hdHJpeFxuICB2YXIgdXAgICAgID0gdGhpcy5jb21wdXRlZFVwXG4gIHZhciByaWdodCAgPSB0aGlzLmNvbXB1dGVkUmlnaHRcbiAgdmFyIHV1ID0gMC4wXG4gIHZhciB1ciA9IDAuMFxuICBmb3IodmFyIGk9MDsgaTwzOyArK2kpIHtcbiAgICB1ciArPSB1cFtpXSAqIHJpZ2h0W2ldXG4gICAgdXUgKz0gdXBbaV0gKiB1cFtpXVxuICB9XG4gIHZhciB1bCA9IE1hdGguc3FydCh1dSlcbiAgdmFyIHJyID0gMC4wXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHJpZ2h0W2ldIC09IHVwW2ldICogdXIgLyB1dVxuICAgIHJyICAgICAgICs9IHJpZ2h0W2ldICogcmlnaHRbaV1cbiAgICB1cFtpXSAgICAvPSB1bFxuICB9XG4gIHZhciBybCA9IE1hdGguc3FydChycilcbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgcmlnaHRbaV0gLz0gcmxcbiAgfVxuXG4gIC8vQ29tcHV0ZSB0b3dhcmQgdmVjdG9yXG4gIHZhciB0b3dhcmQgPSB0aGlzLmNvbXB1dGVkVG93YXJkXG4gIGNyb3NzKHRvd2FyZCwgdXAsIHJpZ2h0KVxuICBub3JtYWxpemUzKHRvd2FyZCwgdG93YXJkKVxuXG4gIC8vQ29tcHV0ZSBhbmd1bGFyIHBhcmFtZXRlcnNcbiAgdmFyIHJhZGl1cyA9IE1hdGguZXhwKHRoaXMuY29tcHV0ZWRSYWRpdXNbMF0pXG4gIHZhciB0aGV0YSAgPSB0aGlzLmNvbXB1dGVkQW5nbGVbMF1cbiAgdmFyIHBoaSAgICA9IHRoaXMuY29tcHV0ZWRBbmdsZVsxXVxuXG4gIHZhciBjdGhldGEgPSBNYXRoLmNvcyh0aGV0YSlcbiAgdmFyIHN0aGV0YSA9IE1hdGguc2luKHRoZXRhKVxuICB2YXIgY3BoaSAgID0gTWF0aC5jb3MocGhpKVxuICB2YXIgc3BoaSAgID0gTWF0aC5zaW4ocGhpKVxuXG4gIHZhciBjZW50ZXIgPSB0aGlzLmNvbXB1dGVkQ2VudGVyXG5cbiAgdmFyIHd4ID0gY3RoZXRhICogY3BoaSBcbiAgdmFyIHd5ID0gc3RoZXRhICogY3BoaVxuICB2YXIgd3ogPSBzcGhpXG5cbiAgdmFyIHN4ID0gLWN0aGV0YSAqIHNwaGlcbiAgdmFyIHN5ID0gLXN0aGV0YSAqIHNwaGlcbiAgdmFyIHN6ID0gY3BoaVxuXG4gIHZhciBleWUgPSB0aGlzLmNvbXB1dGVkRXllXG4gIHZhciBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHZhciB4ICAgICAgPSB3eCAqIHJpZ2h0W2ldICsgd3kgKiB0b3dhcmRbaV0gKyB3eiAqIHVwW2ldXG4gICAgbWF0WzQqaSsxXSA9IHN4ICogcmlnaHRbaV0gKyBzeSAqIHRvd2FyZFtpXSArIHN6ICogdXBbaV1cbiAgICBtYXRbNCppKzJdID0geFxuICAgIG1hdFs0KmkrM10gPSAwLjBcbiAgfVxuXG4gIHZhciBheCA9IG1hdFsxXVxuICB2YXIgYXkgPSBtYXRbNV1cbiAgdmFyIGF6ID0gbWF0WzldXG4gIHZhciBieCA9IG1hdFsyXVxuICB2YXIgYnkgPSBtYXRbNl1cbiAgdmFyIGJ6ID0gbWF0WzEwXVxuICB2YXIgY3ggPSBheSAqIGJ6IC0gYXogKiBieVxuICB2YXIgY3kgPSBheiAqIGJ4IC0gYXggKiBielxuICB2YXIgY3ogPSBheCAqIGJ5IC0gYXkgKiBieFxuICB2YXIgY2wgPSBsZW4zKGN4LCBjeSwgY3opXG4gIGN4IC89IGNsXG4gIGN5IC89IGNsXG4gIGN6IC89IGNsXG4gIG1hdFswXSA9IGN4XG4gIG1hdFs0XSA9IGN5XG4gIG1hdFs4XSA9IGN6XG5cbiAgZm9yKHZhciBpPTA7IGk8MzsgKytpKSB7XG4gICAgZXllW2ldID0gY2VudGVyW2ldICsgbWF0WzIrNCppXSpyYWRpdXNcbiAgfVxuXG4gIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgIHZhciByciA9IDAuMFxuICAgIGZvcih2YXIgaj0wOyBqPDM7ICsraikge1xuICAgICAgcnIgKz0gbWF0W2krNCpqXSAqIGV5ZVtqXVxuICAgIH1cbiAgICBtYXRbMTIraV0gPSAtcnJcbiAgfVxuICBtYXRbMTVdID0gMS4wXG59XG5cbnByb3RvLmdldE1hdHJpeCA9IGZ1bmN0aW9uKHQsIHJlc3VsdCkge1xuICB0aGlzLnJlY2FsY01hdHJpeCh0KVxuICB2YXIgbWF0ID0gdGhpcy5jb21wdXRlZE1hdHJpeFxuICBpZihyZXN1bHQpIHtcbiAgICBmb3IodmFyIGk9MDsgaTwxNjsgKytpKSB7XG4gICAgICByZXN1bHRbaV0gPSBtYXRbaV1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG4gIHJldHVybiBtYXRcbn1cblxudmFyIHpBeGlzID0gWzAsMCwwXVxucHJvdG8ucm90YXRlID0gZnVuY3Rpb24odCwgZHRoZXRhLCBkcGhpLCBkcm9sbCkge1xuICB0aGlzLmFuZ2xlLm1vdmUodCwgZHRoZXRhLCBkcGhpKVxuICBpZihkcm9sbCkge1xuICAgIHRoaXMucmVjYWxjTWF0cml4KHQpXG5cbiAgICB2YXIgbWF0ID0gdGhpcy5jb21wdXRlZE1hdHJpeFxuICAgIHpBeGlzWzBdID0gbWF0WzJdXG4gICAgekF4aXNbMV0gPSBtYXRbNl1cbiAgICB6QXhpc1syXSA9IG1hdFsxMF1cblxuICAgIHZhciB1cCAgICAgPSB0aGlzLmNvbXB1dGVkVXBcbiAgICB2YXIgcmlnaHQgID0gdGhpcy5jb21wdXRlZFJpZ2h0XG4gICAgdmFyIHRvd2FyZCA9IHRoaXMuY29tcHV0ZWRUb3dhcmRcblxuICAgIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgICAgbWF0WzQqaV0gICA9IHVwW2ldXG4gICAgICBtYXRbNCppKzFdID0gcmlnaHRbaV1cbiAgICAgIG1hdFs0KmkrMl0gPSB0b3dhcmRbaV1cbiAgICB9XG4gICAgcm90YXRlTShtYXQsIG1hdCwgZHJvbGwsIHpBeGlzKVxuICAgIGZvcih2YXIgaT0wOyBpPDM7ICsraSkge1xuICAgICAgdXBbaV0gPSAgICBtYXRbNCppXVxuICAgICAgcmlnaHRbaV0gPSBtYXRbNCppKzFdXG4gICAgfVxuXG4gICAgdGhpcy51cC5zZXQodCwgdXBbMF0sIHVwWzFdLCB1cFsyXSlcbiAgICB0aGlzLnJpZ2h0LnNldCh0LCByaWdodFswXSwgcmlnaHRbMV0sIHJpZ2h0WzJdKVxuICB9XG59XG5cbnByb3RvLnBhbiA9IGZ1bmN0aW9uKHQsIGR4LCBkeSwgZHopIHtcbiAgZHggPSBkeCB8fCAwLjBcbiAgZHkgPSBkeSB8fCAwLjBcbiAgZHogPSBkeiB8fCAwLjBcblxuICB0aGlzLnJlY2FsY01hdHJpeCh0KVxuICB2YXIgbWF0ID0gdGhpcy5jb21wdXRlZE1hdHJpeFxuXG4gIHZhciBkaXN0ID0gTWF0aC5leHAodGhpcy5jb21wdXRlZFJhZGl1c1swXSlcblxuICB2YXIgdXggPSBtYXRbMV1cbiAgdmFyIHV5ID0gbWF0WzVdXG4gIHZhciB1eiA9IG1hdFs5XVxuICB2YXIgdWwgPSBsZW4zKHV4LCB1eSwgdXopXG4gIHV4IC89IHVsXG4gIHV5IC89IHVsXG4gIHV6IC89IHVsXG5cbiAgdmFyIHJ4ID0gbWF0WzBdXG4gIHZhciByeSA9IG1hdFs0XVxuICB2YXIgcnogPSBtYXRbOF1cbiAgdmFyIHJ1ID0gcnggKiB1eCArIHJ5ICogdXkgKyByeiAqIHV6XG4gIHJ4IC09IHV4ICogcnVcbiAgcnkgLT0gdXkgKiBydVxuICByeiAtPSB1eiAqIHJ1XG4gIHZhciBybCA9IGxlbjMocngsIHJ5LCByeilcbiAgcnggLz0gcmxcbiAgcnkgLz0gcmxcbiAgcnogLz0gcmxcblxuICB2YXIgdnggPSByeCAqIGR4ICsgdXggKiBkeVxuICB2YXIgdnkgPSByeSAqIGR4ICsgdXkgKiBkeVxuICB2YXIgdnogPSByeiAqIGR4ICsgdXogKiBkeVxuICB0aGlzLmNlbnRlci5tb3ZlKHQsIHZ4LCB2eSwgdnopXG5cbiAgLy9VcGRhdGUgei1jb21wb25lbnQgb2YgcmFkaXVzXG4gIHZhciByYWRpdXMgPSBNYXRoLmV4cCh0aGlzLmNvbXB1dGVkUmFkaXVzWzBdKVxuICByYWRpdXMgPSBNYXRoLm1heCgxZS00LCByYWRpdXMgKyBkeilcbiAgdGhpcy5yYWRpdXMuc2V0KHQsIE1hdGgubG9nKHJhZGl1cykpXG59XG5cbnByb3RvLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uKHQsIGR4LCBkeSwgZHopIHtcbiAgdGhpcy5jZW50ZXIubW92ZSh0LFxuICAgIGR4fHwwLjAsXG4gICAgZHl8fDAuMCxcbiAgICBkenx8MC4wKVxufVxuXG4vL1JlY2VudGVycyB0aGUgY29vcmRpbmF0ZSBheGVzXG5wcm90by5zZXRNYXRyaXggPSBmdW5jdGlvbih0LCBtYXQsIGF4ZXMsIG5vU25hcCkge1xuICBcbiAgLy9HZXQgdGhlIGF4ZXMgZm9yIHRhcmVcbiAgdmFyIHVzaGlmdCA9IDFcbiAgaWYodHlwZW9mIGF4ZXMgPT09ICdudW1iZXInKSB7XG4gICAgdXNoaWZ0ID0gKGF4ZXMpfDBcbiAgfSBcbiAgaWYodXNoaWZ0IDwgMCB8fCB1c2hpZnQgPiAzKSB7XG4gICAgdXNoaWZ0ID0gMVxuICB9XG4gIHZhciB2c2hpZnQgPSAodXNoaWZ0ICsgMikgJSAzXG4gIHZhciBmc2hpZnQgPSAodXNoaWZ0ICsgMSkgJSAzXG5cbiAgLy9SZWNvbXB1dGUgc3RhdGUgZm9yIG5ldyB0IHZhbHVlXG4gIGlmKCFtYXQpIHsgXG4gICAgdGhpcy5yZWNhbGNNYXRyaXgodClcbiAgICBtYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XG4gIH1cblxuICAvL0dldCByaWdodCBhbmQgdXAgdmVjdG9yc1xuICB2YXIgdXggPSBtYXRbdXNoaWZ0XVxuICB2YXIgdXkgPSBtYXRbdXNoaWZ0KzRdXG4gIHZhciB1eiA9IG1hdFt1c2hpZnQrOF1cbiAgaWYoIW5vU25hcCkge1xuICAgIHZhciB1bCA9IGxlbjModXgsIHV5LCB1eilcbiAgICB1eCAvPSB1bFxuICAgIHV5IC89IHVsXG4gICAgdXogLz0gdWxcbiAgfSBlbHNlIHtcbiAgICB2YXIgYXggPSBNYXRoLmFicyh1eClcbiAgICB2YXIgYXkgPSBNYXRoLmFicyh1eSlcbiAgICB2YXIgYXogPSBNYXRoLmFicyh1eilcbiAgICB2YXIgYW0gPSBNYXRoLm1heChheCxheSxheilcbiAgICBpZihheCA9PT0gYW0pIHtcbiAgICAgIHV4ID0gKHV4IDwgMCkgPyAtMSA6IDFcbiAgICAgIHV5ID0gdXogPSAwXG4gICAgfSBlbHNlIGlmKGF6ID09PSBhbSkge1xuICAgICAgdXogPSAodXogPCAwKSA/IC0xIDogMVxuICAgICAgdXggPSB1eSA9IDBcbiAgICB9IGVsc2Uge1xuICAgICAgdXkgPSAodXkgPCAwKSA/IC0xIDogMVxuICAgICAgdXggPSB1eiA9IDBcbiAgICB9XG4gIH1cblxuICB2YXIgcnggPSBtYXRbdnNoaWZ0XVxuICB2YXIgcnkgPSBtYXRbdnNoaWZ0KzRdXG4gIHZhciByeiA9IG1hdFt2c2hpZnQrOF1cbiAgdmFyIHJ1ID0gcnggKiB1eCArIHJ5ICogdXkgKyByeiAqIHV6XG4gIHJ4IC09IHV4ICogcnVcbiAgcnkgLT0gdXkgKiBydVxuICByeiAtPSB1eiAqIHJ1XG4gIHZhciBybCA9IGxlbjMocngsIHJ5LCByeilcbiAgcnggLz0gcmxcbiAgcnkgLz0gcmxcbiAgcnogLz0gcmxcbiAgXG4gIHZhciBmeCA9IHV5ICogcnogLSB1eiAqIHJ5XG4gIHZhciBmeSA9IHV6ICogcnggLSB1eCAqIHJ6XG4gIHZhciBmeiA9IHV4ICogcnkgLSB1eSAqIHJ4XG4gIHZhciBmbCA9IGxlbjMoZngsIGZ5LCBmeilcbiAgZnggLz0gZmxcbiAgZnkgLz0gZmxcbiAgZnogLz0gZmxcblxuICB0aGlzLmNlbnRlci5qdW1wKHQsIGV4LCBleSwgZXopXG4gIHRoaXMucmFkaXVzLmlkbGUodClcbiAgdGhpcy51cC5qdW1wKHQsIHV4LCB1eSwgdXopXG4gIHRoaXMucmlnaHQuanVtcCh0LCByeCwgcnksIHJ6KVxuXG4gIHZhciBwaGksIHRoZXRhXG4gIGlmKHVzaGlmdCA9PT0gMikge1xuICAgIHZhciBjeCA9IG1hdFsxXVxuICAgIHZhciBjeSA9IG1hdFs1XVxuICAgIHZhciBjeiA9IG1hdFs5XVxuICAgIHZhciBjciA9IGN4ICogcnggKyBjeSAqIHJ5ICsgY3ogKiByelxuICAgIHZhciBjZiA9IGN4ICogZnggKyBjeSAqIGZ5ICsgY3ogKiBmelxuICAgIGlmKHR1IDwgMCkge1xuICAgICAgcGhpID0gLU1hdGguUEkvMlxuICAgIH0gZWxzZSB7XG4gICAgICBwaGkgPSBNYXRoLlBJLzJcbiAgICB9XG4gICAgdGhldGEgPSBNYXRoLmF0YW4yKGNmLCBjcilcbiAgfSBlbHNlIHtcbiAgICB2YXIgdHggPSBtYXRbMl1cbiAgICB2YXIgdHkgPSBtYXRbNl1cbiAgICB2YXIgdHogPSBtYXRbMTBdXG4gICAgdmFyIHR1ID0gdHggKiB1eCArIHR5ICogdXkgKyB0eiAqIHV6XG4gICAgdmFyIHRyID0gdHggKiByeCArIHR5ICogcnkgKyB0eiAqIHJ6XG4gICAgdmFyIHRmID0gdHggKiBmeCArIHR5ICogZnkgKyB0eiAqIGZ6XG5cbiAgICBwaGkgPSBNYXRoLmFzaW4oY2xhbXAxKHR1KSlcbiAgICB0aGV0YSA9IE1hdGguYXRhbjIodGYsIHRyKVxuICB9XG5cbiAgdGhpcy5hbmdsZS5qdW1wKHQsIHRoZXRhLCBwaGkpXG5cbiAgdGhpcy5yZWNhbGNNYXRyaXgodClcbiAgdmFyIGR4ID0gbWF0WzJdXG4gIHZhciBkeSA9IG1hdFs2XVxuICB2YXIgZHogPSBtYXRbMTBdXG5cbiAgdmFyIGltYXQgPSB0aGlzLmNvbXB1dGVkTWF0cml4XG4gIGludmVydDQ0KGltYXQsIG1hdClcbiAgdmFyIHcgID0gaW1hdFsxNV1cbiAgdmFyIGV4ID0gaW1hdFsxMl0gLyB3XG4gIHZhciBleSA9IGltYXRbMTNdIC8gd1xuICB2YXIgZXogPSBpbWF0WzE0XSAvIHdcblxuICB2YXIgZ3MgPSBNYXRoLmV4cCh0aGlzLmNvbXB1dGVkUmFkaXVzWzBdKVxuICB0aGlzLmNlbnRlci5qdW1wKHQsIGV4LWR4KmdzLCBleS1keSpncywgZXotZHoqZ3MpXG59XG5cbnByb3RvLmxhc3RUID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBNYXRoLm1heChcbiAgICB0aGlzLmNlbnRlci5sYXN0VCgpLFxuICAgIHRoaXMudXAubGFzdFQoKSxcbiAgICB0aGlzLnJpZ2h0Lmxhc3RUKCksXG4gICAgdGhpcy5yYWRpdXMubGFzdFQoKSxcbiAgICB0aGlzLmFuZ2xlLmxhc3RUKCkpXG59XG5cbnByb3RvLmlkbGUgPSBmdW5jdGlvbih0KSB7XG4gIHRoaXMuY2VudGVyLmlkbGUodClcbiAgdGhpcy51cC5pZGxlKHQpXG4gIHRoaXMucmlnaHQuaWRsZSh0KVxuICB0aGlzLnJhZGl1cy5pZGxlKHQpXG4gIHRoaXMuYW5nbGUuaWRsZSh0KVxufVxuXG5wcm90by5mbHVzaCA9IGZ1bmN0aW9uKHQpIHtcbiAgdGhpcy5jZW50ZXIuZmx1c2godClcbiAgdGhpcy51cC5mbHVzaCh0KVxuICB0aGlzLnJpZ2h0LmZsdXNoKHQpXG4gIHRoaXMucmFkaXVzLmZsdXNoKHQpXG4gIHRoaXMuYW5nbGUuZmx1c2godClcbn1cblxucHJvdG8uc2V0RGlzdGFuY2UgPSBmdW5jdGlvbih0LCBkKSB7XG4gIGlmKGQgPiAwKSB7XG4gICAgdGhpcy5yYWRpdXMuc2V0KHQsIE1hdGgubG9nKGQpKVxuICB9XG59XG5cbnByb3RvLmxvb2tBdCA9IGZ1bmN0aW9uKHQsIGV5ZSwgY2VudGVyLCB1cCkge1xuICB0aGlzLnJlY2FsY01hdHJpeCh0KVxuXG4gIGV5ZSAgICA9IGV5ZSAgICB8fCB0aGlzLmNvbXB1dGVkRXllXG4gIGNlbnRlciA9IGNlbnRlciB8fCB0aGlzLmNvbXB1dGVkQ2VudGVyXG4gIHVwICAgICA9IHVwICAgICB8fCB0aGlzLmNvbXB1dGVkVXBcblxuICB2YXIgdXggPSB1cFswXVxuICB2YXIgdXkgPSB1cFsxXVxuICB2YXIgdXogPSB1cFsyXVxuICB2YXIgdWwgPSBsZW4zKHV4LCB1eSwgdXopXG4gIGlmKHVsIDwgMWUtNikge1xuICAgIHJldHVyblxuICB9XG4gIHV4IC89IHVsXG4gIHV5IC89IHVsXG4gIHV6IC89IHVsXG5cbiAgdmFyIHR4ID0gZXllWzBdIC0gY2VudGVyWzBdXG4gIHZhciB0eSA9IGV5ZVsxXSAtIGNlbnRlclsxXVxuICB2YXIgdHogPSBleWVbMl0gLSBjZW50ZXJbMl1cbiAgdmFyIHRsID0gbGVuMyh0eCwgdHksIHR6KVxuICBpZih0bCA8IDFlLTYpIHtcbiAgICByZXR1cm5cbiAgfVxuICB0eCAvPSB0bFxuICB0eSAvPSB0bFxuICB0eiAvPSB0bFxuXG4gIHZhciByaWdodCA9IHRoaXMuY29tcHV0ZWRSaWdodFxuICB2YXIgcnggPSByaWdodFswXVxuICB2YXIgcnkgPSByaWdodFsxXVxuICB2YXIgcnogPSByaWdodFsyXVxuICB2YXIgcnUgPSB1eCpyeCArIHV5KnJ5ICsgdXoqcnpcbiAgcnggLT0gcnUgKiB1eFxuICByeSAtPSBydSAqIHV5XG4gIHJ6IC09IHJ1ICogdXpcbiAgdmFyIHJsID0gbGVuMyhyeCwgcnksIHJ6KVxuXG4gIGlmKHJsIDwgMC4wMSkge1xuICAgIHJ4ID0gdXkgKiB0eiAtIHV6ICogdHlcbiAgICByeSA9IHV6ICogdHggLSB1eCAqIHR6XG4gICAgcnogPSB1eCAqIHR5IC0gdXkgKiB0eFxuICAgIHJsID0gbGVuMyhyeCwgcnksIHJ6KVxuICAgIGlmKHJsIDwgMWUtNikge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICB9XG4gIHJ4IC89IHJsXG4gIHJ5IC89IHJsXG4gIHJ6IC89IHJsXG5cbiAgdGhpcy51cC5zZXQodCwgdXgsIHV5LCB1eilcbiAgdGhpcy5yaWdodC5zZXQodCwgcngsIHJ5LCByeilcbiAgdGhpcy5jZW50ZXIuc2V0KHQsIGNlbnRlclswXSwgY2VudGVyWzFdLCBjZW50ZXJbMl0pXG4gIHRoaXMucmFkaXVzLnNldCh0LCBNYXRoLmxvZyh0bCkpXG5cbiAgdmFyIGZ4ID0gdXkgKiByeiAtIHV6ICogcnlcbiAgdmFyIGZ5ID0gdXogKiByeCAtIHV4ICogcnpcbiAgdmFyIGZ6ID0gdXggKiByeSAtIHV5ICogcnhcbiAgdmFyIGZsID0gbGVuMyhmeCwgZnksIGZ6KVxuICBmeCAvPSBmbFxuICBmeSAvPSBmbFxuICBmeiAvPSBmbFxuXG4gIHZhciB0dSA9IHV4KnR4ICsgdXkqdHkgKyB1eip0elxuICB2YXIgdHIgPSByeCp0eCArIHJ5KnR5ICsgcnoqdHpcbiAgdmFyIHRmID0gZngqdHggKyBmeSp0eSArIGZ6KnR6XG5cbiAgdmFyIHBoaSAgID0gTWF0aC5hc2luKGNsYW1wMSh0dSkpXG4gIHZhciB0aGV0YSA9IE1hdGguYXRhbjIodGYsIHRyKVxuXG4gIHZhciBhbmdsZVN0YXRlID0gdGhpcy5hbmdsZS5fc3RhdGVcbiAgdmFyIGxhc3RUaGV0YSAgPSBhbmdsZVN0YXRlW2FuZ2xlU3RhdGUubGVuZ3RoLTFdXG4gIHZhciBsYXN0UGhpICAgID0gYW5nbGVTdGF0ZVthbmdsZVN0YXRlLmxlbmd0aC0yXVxuICBsYXN0VGhldGEgICAgICA9IGxhc3RUaGV0YSAlICgyLjAgKiBNYXRoLlBJKVxuICB2YXIgZHAgPSBNYXRoLmFicyhsYXN0VGhldGEgKyAyLjAgKiBNYXRoLlBJIC0gdGhldGEpXG4gIHZhciBkMCA9IE1hdGguYWJzKGxhc3RUaGV0YSAtIHRoZXRhKVxuICB2YXIgZG4gPSBNYXRoLmFicyhsYXN0VGhldGEgLSAyLjAgKiBNYXRoLlBJIC0gdGhldGEpXG4gIGlmKGRwIDwgZDApIHtcbiAgICBsYXN0VGhldGEgKz0gMi4wICogTWF0aC5QSVxuICB9XG4gIGlmKGRuIDwgZDApIHtcbiAgICBsYXN0VGhldGEgLT0gMi4wICogTWF0aC5QSVxuICB9XG5cbiAgdGhpcy5hbmdsZS5qdW1wKHRoaXMuYW5nbGUubGFzdFQoKSwgbGFzdFRoZXRhLCBsYXN0UGhpKVxuICB0aGlzLmFuZ2xlLnNldCh0LCB0aGV0YSwgcGhpKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVUdXJudGFibGVDb250cm9sbGVyKG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cblxuICB2YXIgY2VudGVyID0gb3B0aW9ucy5jZW50ZXIgfHwgWzAsMCwwXVxuICB2YXIgdXAgICAgID0gb3B0aW9ucy51cCAgICAgfHwgWzAsMSwwXVxuICB2YXIgcmlnaHQgID0gb3B0aW9ucy5yaWdodCAgfHwgZmluZE9ydGhvUGFpcih1cClcbiAgdmFyIHJhZGl1cyA9IG9wdGlvbnMucmFkaXVzIHx8IDEuMFxuICB2YXIgdGhldGEgID0gb3B0aW9ucy50aGV0YSAgfHwgMC4wXG4gIHZhciBwaGkgICAgPSBvcHRpb25zLnBoaSAgICB8fCAwLjBcblxuICBjZW50ZXIgPSBbXS5zbGljZS5jYWxsKGNlbnRlciwgMCwgMylcblxuICB1cCA9IFtdLnNsaWNlLmNhbGwodXAsIDAsIDMpXG4gIG5vcm1hbGl6ZTModXAsIHVwKVxuXG4gIHJpZ2h0ID0gW10uc2xpY2UuY2FsbChyaWdodCwgMCwgMylcbiAgbm9ybWFsaXplMyhyaWdodCwgcmlnaHQpXG5cbiAgaWYoJ2V5ZScgaW4gb3B0aW9ucykge1xuICAgIHZhciBleWUgPSBvcHRpb25zLmV5ZVxuICAgIHZhciB0b3dhcmQgPSBbXG4gICAgICBleWVbMF0tY2VudGVyWzBdLFxuICAgICAgZXllWzFdLWNlbnRlclsxXSxcbiAgICAgIGV5ZVsyXS1jZW50ZXJbMl1cbiAgICBdXG4gICAgY3Jvc3MocmlnaHQsIHRvd2FyZCwgdXApXG4gICAgaWYobGVuMyhyaWdodFswXSwgcmlnaHRbMV0sIHJpZ2h0WzJdKSA8IDFlLTYpIHtcbiAgICAgIHJpZ2h0ID0gZmluZE9ydGhvUGFpcih1cClcbiAgICB9IGVsc2Uge1xuICAgICAgbm9ybWFsaXplMyhyaWdodCwgcmlnaHQpXG4gICAgfVxuXG4gICAgcmFkaXVzID0gbGVuMyh0b3dhcmRbMF0sIHRvd2FyZFsxXSwgdG93YXJkWzJdKVxuXG4gICAgdmFyIHV0ID0gZG90Myh1cCwgdG93YXJkKSAvIHJhZGl1c1xuICAgIHZhciBydCA9IGRvdDMocmlnaHQsIHRvd2FyZCkgLyByYWRpdXNcbiAgICBwaGkgICAgPSBNYXRoLmFjb3ModXQpXG4gICAgdGhldGEgID0gTWF0aC5hY29zKHJ0KVxuICB9XG5cbiAgLy9Vc2UgbG9nYXJpdGhtaWMgY29vcmRpbmF0ZXMgZm9yIHJhZGl1c1xuICByYWRpdXMgPSBNYXRoLmxvZyhyYWRpdXMpXG5cbiAgLy9SZXR1cm4gdGhlIGNvbnRyb2xsZXJcbiAgcmV0dXJuIG5ldyBUdXJudGFibGVDb250cm9sbGVyKFxuICAgIG9wdGlvbnMuem9vbU1pbixcbiAgICBvcHRpb25zLnpvb21NYXgsXG4gICAgY2VudGVyLFxuICAgIHVwLFxuICAgIHJpZ2h0LFxuICAgIHJhZGl1cyxcbiAgICB0aGV0YSxcbiAgICBwaGkpXG59XG59LHtcImZpbHRlcmVkLXZlY3RvclwiOjIyNixcImdsLW1hdDQvaW52ZXJ0XCI6MjY1LFwiZ2wtbWF0NC9yb3RhdGVcIjoyNzAsXCJnbC12ZWMzL2Nyb3NzXCI6MzM0LFwiZ2wtdmVjMy9kb3RcIjozMzksXCJnbC12ZWMzL25vcm1hbGl6ZVwiOjM1Nn1dLDU0MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IHR3b1Byb2R1Y3RcblxudmFyIFNQTElUVEVSID0gKyhNYXRoLnBvdygyLCAyNykgKyAxLjApXG5cbmZ1bmN0aW9uIHR3b1Byb2R1Y3QoYSwgYiwgcmVzdWx0KSB7XG4gIHZhciB4ID0gYSAqIGJcblxuICB2YXIgYyA9IFNQTElUVEVSICogYVxuICB2YXIgYWJpZyA9IGMgLSBhXG4gIHZhciBhaGkgPSBjIC0gYWJpZ1xuICB2YXIgYWxvID0gYSAtIGFoaVxuXG4gIHZhciBkID0gU1BMSVRURVIgKiBiXG4gIHZhciBiYmlnID0gZCAtIGJcbiAgdmFyIGJoaSA9IGQgLSBiYmlnXG4gIHZhciBibG8gPSBiIC0gYmhpXG5cbiAgdmFyIGVycjEgPSB4IC0gKGFoaSAqIGJoaSlcbiAgdmFyIGVycjIgPSBlcnIxIC0gKGFsbyAqIGJoaSlcbiAgdmFyIGVycjMgPSBlcnIyIC0gKGFoaSAqIGJsbylcblxuICB2YXIgeSA9IGFsbyAqIGJsbyAtIGVycjNcblxuICBpZihyZXN1bHQpIHtcbiAgICByZXN1bHRbMF0gPSB5XG4gICAgcmVzdWx0WzFdID0geFxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIHJldHVybiBbIHksIHggXVxufVxufSx7fV0sNTQ0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gZmFzdFR3b1N1bVxuXG5mdW5jdGlvbiBmYXN0VHdvU3VtKGEsIGIsIHJlc3VsdCkge1xuXHR2YXIgeCA9IGEgKyBiXG5cdHZhciBidiA9IHggLSBhXG5cdHZhciBhdiA9IHggLSBidlxuXHR2YXIgYnIgPSBiIC0gYnZcblx0dmFyIGFyID0gYSAtIGF2XG5cdGlmKHJlc3VsdCkge1xuXHRcdHJlc3VsdFswXSA9IGFyICsgYnJcblx0XHRyZXN1bHRbMV0gPSB4XG5cdFx0cmV0dXJuIHJlc3VsdFxuXHR9XG5cdHJldHVybiBbYXIrYnIsIHhdXG59XG59LHt9XSw1NDU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuKGZ1bmN0aW9uIChnbG9iYWwsQnVmZmVyKXtcbid1c2Ugc3RyaWN0J1xuXG52YXIgYml0cyA9IF9kZXJlcV8oJ2JpdC10d2lkZGxlJylcbnZhciBkdXAgPSBfZGVyZXFfKCdkdXAnKVxuXG4vL0xlZ2FjeSBwb29sIHN1cHBvcnRcbmlmKCFnbG9iYWwuX19UWVBFREFSUkFZX1BPT0wpIHtcbiAgZ2xvYmFsLl9fVFlQRURBUlJBWV9QT09MID0ge1xuICAgICAgVUlOVDggICA6IGR1cChbMzIsIDBdKVxuICAgICwgVUlOVDE2ICA6IGR1cChbMzIsIDBdKVxuICAgICwgVUlOVDMyICA6IGR1cChbMzIsIDBdKVxuICAgICwgSU5UOCAgICA6IGR1cChbMzIsIDBdKVxuICAgICwgSU5UMTYgICA6IGR1cChbMzIsIDBdKVxuICAgICwgSU5UMzIgICA6IGR1cChbMzIsIDBdKVxuICAgICwgRkxPQVQgICA6IGR1cChbMzIsIDBdKVxuICAgICwgRE9VQkxFICA6IGR1cChbMzIsIDBdKVxuICAgICwgREFUQSAgICA6IGR1cChbMzIsIDBdKVxuICAgICwgVUlOVDhDICA6IGR1cChbMzIsIDBdKVxuICAgICwgQlVGRkVSICA6IGR1cChbMzIsIDBdKVxuICB9XG59XG5cbnZhciBoYXNVaW50OEMgPSAodHlwZW9mIFVpbnQ4Q2xhbXBlZEFycmF5KSAhPT0gJ3VuZGVmaW5lZCdcbnZhciBQT09MID0gZ2xvYmFsLl9fVFlQRURBUlJBWV9QT09MXG5cbi8vVXBncmFkZSBwb29sXG5pZighUE9PTC5VSU5UOEMpIHtcbiAgUE9PTC5VSU5UOEMgPSBkdXAoWzMyLCAwXSlcbn1cbmlmKCFQT09MLkJVRkZFUikge1xuICBQT09MLkJVRkZFUiA9IGR1cChbMzIsIDBdKVxufVxuXG4vL05ldyB0ZWNobmlxdWU6IE9ubHkgYWxsb2NhdGUgZnJvbSBBcnJheUJ1ZmZlclZpZXcgYW5kIEJ1ZmZlclxudmFyIERBVEEgICAgPSBQT09MLkRBVEFcbiAgLCBCVUZGRVIgID0gUE9PTC5CVUZGRVJcblxuZXhwb3J0cy5mcmVlID0gZnVuY3Rpb24gZnJlZShhcnJheSkge1xuICBpZihCdWZmZXIuaXNCdWZmZXIoYXJyYXkpKSB7XG4gICAgQlVGRkVSW2JpdHMubG9nMihhcnJheS5sZW5ndGgpXS5wdXNoKGFycmF5KVxuICB9IGVsc2Uge1xuICAgIGlmKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhcnJheSkgIT09ICdbb2JqZWN0IEFycmF5QnVmZmVyXScpIHtcbiAgICAgIGFycmF5ID0gYXJyYXkuYnVmZmVyXG4gICAgfVxuICAgIGlmKCFhcnJheSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIHZhciBuID0gYXJyYXkubGVuZ3RoIHx8IGFycmF5LmJ5dGVMZW5ndGhcbiAgICB2YXIgbG9nX24gPSBiaXRzLmxvZzIobil8MFxuICAgIERBVEFbbG9nX25dLnB1c2goYXJyYXkpXG4gIH1cbn1cblxuZnVuY3Rpb24gZnJlZUFycmF5QnVmZmVyKGJ1ZmZlcikge1xuICBpZighYnVmZmVyKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdmFyIG4gPSBidWZmZXIubGVuZ3RoIHx8IGJ1ZmZlci5ieXRlTGVuZ3RoXG4gIHZhciBsb2dfbiA9IGJpdHMubG9nMihuKVxuICBEQVRBW2xvZ19uXS5wdXNoKGJ1ZmZlcilcbn1cblxuZnVuY3Rpb24gZnJlZVR5cGVkQXJyYXkoYXJyYXkpIHtcbiAgZnJlZUFycmF5QnVmZmVyKGFycmF5LmJ1ZmZlcilcbn1cblxuZXhwb3J0cy5mcmVlVWludDggPVxuZXhwb3J0cy5mcmVlVWludDE2ID1cbmV4cG9ydHMuZnJlZVVpbnQzMiA9XG5leHBvcnRzLmZyZWVJbnQ4ID1cbmV4cG9ydHMuZnJlZUludDE2ID1cbmV4cG9ydHMuZnJlZUludDMyID1cbmV4cG9ydHMuZnJlZUZsb2F0MzIgPSBcbmV4cG9ydHMuZnJlZUZsb2F0ID1cbmV4cG9ydHMuZnJlZUZsb2F0NjQgPSBcbmV4cG9ydHMuZnJlZURvdWJsZSA9IFxuZXhwb3J0cy5mcmVlVWludDhDbGFtcGVkID0gXG5leHBvcnRzLmZyZWVEYXRhVmlldyA9IGZyZWVUeXBlZEFycmF5XG5cbmV4cG9ydHMuZnJlZUFycmF5QnVmZmVyID0gZnJlZUFycmF5QnVmZmVyXG5cbmV4cG9ydHMuZnJlZUJ1ZmZlciA9IGZ1bmN0aW9uIGZyZWVCdWZmZXIoYXJyYXkpIHtcbiAgQlVGRkVSW2JpdHMubG9nMihhcnJheS5sZW5ndGgpXS5wdXNoKGFycmF5KVxufVxuXG5leHBvcnRzLm1hbGxvYyA9IGZ1bmN0aW9uIG1hbGxvYyhuLCBkdHlwZSkge1xuICBpZihkdHlwZSA9PT0gdW5kZWZpbmVkIHx8IGR0eXBlID09PSAnYXJyYXlidWZmZXInKSB7XG4gICAgcmV0dXJuIG1hbGxvY0FycmF5QnVmZmVyKG4pXG4gIH0gZWxzZSB7XG4gICAgc3dpdGNoKGR0eXBlKSB7XG4gICAgICBjYXNlICd1aW50OCc6XG4gICAgICAgIHJldHVybiBtYWxsb2NVaW50OChuKVxuICAgICAgY2FzZSAndWludDE2JzpcbiAgICAgICAgcmV0dXJuIG1hbGxvY1VpbnQxNihuKVxuICAgICAgY2FzZSAndWludDMyJzpcbiAgICAgICAgcmV0dXJuIG1hbGxvY1VpbnQzMihuKVxuICAgICAgY2FzZSAnaW50OCc6XG4gICAgICAgIHJldHVybiBtYWxsb2NJbnQ4KG4pXG4gICAgICBjYXNlICdpbnQxNic6XG4gICAgICAgIHJldHVybiBtYWxsb2NJbnQxNihuKVxuICAgICAgY2FzZSAnaW50MzInOlxuICAgICAgICByZXR1cm4gbWFsbG9jSW50MzIobilcbiAgICAgIGNhc2UgJ2Zsb2F0JzpcbiAgICAgIGNhc2UgJ2Zsb2F0MzInOlxuICAgICAgICByZXR1cm4gbWFsbG9jRmxvYXQobilcbiAgICAgIGNhc2UgJ2RvdWJsZSc6XG4gICAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgICAgcmV0dXJuIG1hbGxvY0RvdWJsZShuKVxuICAgICAgY2FzZSAndWludDhfY2xhbXBlZCc6XG4gICAgICAgIHJldHVybiBtYWxsb2NVaW50OENsYW1wZWQobilcbiAgICAgIGNhc2UgJ2J1ZmZlcic6XG4gICAgICAgIHJldHVybiBtYWxsb2NCdWZmZXIobilcbiAgICAgIGNhc2UgJ2RhdGEnOlxuICAgICAgY2FzZSAnZGF0YXZpZXcnOlxuICAgICAgICByZXR1cm4gbWFsbG9jRGF0YVZpZXcobilcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG51bGxcbn1cblxuZnVuY3Rpb24gbWFsbG9jQXJyYXlCdWZmZXIobikge1xuICB2YXIgbiA9IGJpdHMubmV4dFBvdzIobilcbiAgdmFyIGxvZ19uID0gYml0cy5sb2cyKG4pXG4gIHZhciBkID0gREFUQVtsb2dfbl1cbiAgaWYoZC5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIGQucG9wKClcbiAgfVxuICByZXR1cm4gbmV3IEFycmF5QnVmZmVyKG4pXG59XG5leHBvcnRzLm1hbGxvY0FycmF5QnVmZmVyID0gbWFsbG9jQXJyYXlCdWZmZXJcblxuZnVuY3Rpb24gbWFsbG9jVWludDgobikge1xuICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkobWFsbG9jQXJyYXlCdWZmZXIobiksIDAsIG4pXG59XG5leHBvcnRzLm1hbGxvY1VpbnQ4ID0gbWFsbG9jVWludDhcblxuZnVuY3Rpb24gbWFsbG9jVWludDE2KG4pIHtcbiAgcmV0dXJuIG5ldyBVaW50MTZBcnJheShtYWxsb2NBcnJheUJ1ZmZlcigyKm4pLCAwLCBuKVxufVxuZXhwb3J0cy5tYWxsb2NVaW50MTYgPSBtYWxsb2NVaW50MTZcblxuZnVuY3Rpb24gbWFsbG9jVWludDMyKG4pIHtcbiAgcmV0dXJuIG5ldyBVaW50MzJBcnJheShtYWxsb2NBcnJheUJ1ZmZlcig0Km4pLCAwLCBuKVxufVxuZXhwb3J0cy5tYWxsb2NVaW50MzIgPSBtYWxsb2NVaW50MzJcblxuZnVuY3Rpb24gbWFsbG9jSW50OChuKSB7XG4gIHJldHVybiBuZXcgSW50OEFycmF5KG1hbGxvY0FycmF5QnVmZmVyKG4pLCAwLCBuKVxufVxuZXhwb3J0cy5tYWxsb2NJbnQ4ID0gbWFsbG9jSW50OFxuXG5mdW5jdGlvbiBtYWxsb2NJbnQxNihuKSB7XG4gIHJldHVybiBuZXcgSW50MTZBcnJheShtYWxsb2NBcnJheUJ1ZmZlcigyKm4pLCAwLCBuKVxufVxuZXhwb3J0cy5tYWxsb2NJbnQxNiA9IG1hbGxvY0ludDE2XG5cbmZ1bmN0aW9uIG1hbGxvY0ludDMyKG4pIHtcbiAgcmV0dXJuIG5ldyBJbnQzMkFycmF5KG1hbGxvY0FycmF5QnVmZmVyKDQqbiksIDAsIG4pXG59XG5leHBvcnRzLm1hbGxvY0ludDMyID0gbWFsbG9jSW50MzJcblxuZnVuY3Rpb24gbWFsbG9jRmxvYXQobikge1xuICByZXR1cm4gbmV3IEZsb2F0MzJBcnJheShtYWxsb2NBcnJheUJ1ZmZlcig0Km4pLCAwLCBuKVxufVxuZXhwb3J0cy5tYWxsb2NGbG9hdDMyID0gZXhwb3J0cy5tYWxsb2NGbG9hdCA9IG1hbGxvY0Zsb2F0XG5cbmZ1bmN0aW9uIG1hbGxvY0RvdWJsZShuKSB7XG4gIHJldHVybiBuZXcgRmxvYXQ2NEFycmF5KG1hbGxvY0FycmF5QnVmZmVyKDgqbiksIDAsIG4pXG59XG5leHBvcnRzLm1hbGxvY0Zsb2F0NjQgPSBleHBvcnRzLm1hbGxvY0RvdWJsZSA9IG1hbGxvY0RvdWJsZVxuXG5mdW5jdGlvbiBtYWxsb2NVaW50OENsYW1wZWQobikge1xuICBpZihoYXNVaW50OEMpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KG1hbGxvY0FycmF5QnVmZmVyKG4pLCAwLCBuKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBtYWxsb2NVaW50OChuKVxuICB9XG59XG5leHBvcnRzLm1hbGxvY1VpbnQ4Q2xhbXBlZCA9IG1hbGxvY1VpbnQ4Q2xhbXBlZFxuXG5mdW5jdGlvbiBtYWxsb2NEYXRhVmlldyhuKSB7XG4gIHJldHVybiBuZXcgRGF0YVZpZXcobWFsbG9jQXJyYXlCdWZmZXIobiksIDAsIG4pXG59XG5leHBvcnRzLm1hbGxvY0RhdGFWaWV3ID0gbWFsbG9jRGF0YVZpZXdcblxuZnVuY3Rpb24gbWFsbG9jQnVmZmVyKG4pIHtcbiAgbiA9IGJpdHMubmV4dFBvdzIobilcbiAgdmFyIGxvZ19uID0gYml0cy5sb2cyKG4pXG4gIHZhciBjYWNoZSA9IEJVRkZFUltsb2dfbl1cbiAgaWYoY2FjaGUubGVuZ3RoID4gMCkge1xuICAgIHJldHVybiBjYWNoZS5wb3AoKVxuICB9XG4gIHJldHVybiBuZXcgQnVmZmVyKG4pXG59XG5leHBvcnRzLm1hbGxvY0J1ZmZlciA9IG1hbGxvY0J1ZmZlclxuXG5leHBvcnRzLmNsZWFyQ2FjaGUgPSBmdW5jdGlvbiBjbGVhckNhY2hlKCkge1xuICBmb3IodmFyIGk9MDsgaTwzMjsgKytpKSB7XG4gICAgUE9PTC5VSU5UOFtpXS5sZW5ndGggPSAwXG4gICAgUE9PTC5VSU5UMTZbaV0ubGVuZ3RoID0gMFxuICAgIFBPT0wuVUlOVDMyW2ldLmxlbmd0aCA9IDBcbiAgICBQT09MLklOVDhbaV0ubGVuZ3RoID0gMFxuICAgIFBPT0wuSU5UMTZbaV0ubGVuZ3RoID0gMFxuICAgIFBPT0wuSU5UMzJbaV0ubGVuZ3RoID0gMFxuICAgIFBPT0wuRkxPQVRbaV0ubGVuZ3RoID0gMFxuICAgIFBPT0wuRE9VQkxFW2ldLmxlbmd0aCA9IDBcbiAgICBQT09MLlVJTlQ4Q1tpXS5sZW5ndGggPSAwXG4gICAgREFUQVtpXS5sZW5ndGggPSAwXG4gICAgQlVGRkVSW2ldLmxlbmd0aCA9IDBcbiAgfVxufVxufSkuY2FsbCh0aGlzLHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30sX2RlcmVxXyhcImJ1ZmZlclwiKS5CdWZmZXIpXG59LHtcImJpdC10d2lkZGxlXCI6OTIsXCJidWZmZXJcIjoxMDUsXCJkdXBcIjoxNzB9XSw1NDY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuXCJ1c2Ugc3RyaWN0XCI7IFwidXNlIHJlc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0gVW5pb25GaW5kO1xuXG5mdW5jdGlvbiBVbmlvbkZpbmQoY291bnQpIHtcbiAgdGhpcy5yb290cyA9IG5ldyBBcnJheShjb3VudCk7XG4gIHRoaXMucmFua3MgPSBuZXcgQXJyYXkoY291bnQpO1xuICBcbiAgZm9yKHZhciBpPTA7IGk8Y291bnQ7ICsraSkge1xuICAgIHRoaXMucm9vdHNbaV0gPSBpO1xuICAgIHRoaXMucmFua3NbaV0gPSAwO1xuICB9XG59XG5cbnZhciBwcm90byA9IFVuaW9uRmluZC5wcm90b3R5cGVcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvLCBcImxlbmd0aFwiLCB7XG4gIFwiZ2V0XCI6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnJvb3RzLmxlbmd0aFxuICB9XG59KVxuXG5wcm90by5tYWtlU2V0ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBuID0gdGhpcy5yb290cy5sZW5ndGg7XG4gIHRoaXMucm9vdHMucHVzaChuKTtcbiAgdGhpcy5yYW5rcy5wdXNoKDApO1xuICByZXR1cm4gbjtcbn1cblxucHJvdG8uZmluZCA9IGZ1bmN0aW9uKHgpIHtcbiAgdmFyIHgwID0geFxuICB2YXIgcm9vdHMgPSB0aGlzLnJvb3RzO1xuICB3aGlsZShyb290c1t4XSAhPT0geCkge1xuICAgIHggPSByb290c1t4XVxuICB9XG4gIHdoaWxlKHJvb3RzW3gwXSAhPT0geCkge1xuICAgIHZhciB5ID0gcm9vdHNbeDBdXG4gICAgcm9vdHNbeDBdID0geFxuICAgIHgwID0geVxuICB9XG4gIHJldHVybiB4O1xufVxuXG5wcm90by5saW5rID0gZnVuY3Rpb24oeCwgeSkge1xuICB2YXIgeHIgPSB0aGlzLmZpbmQoeClcbiAgICAsIHlyID0gdGhpcy5maW5kKHkpO1xuICBpZih4ciA9PT0geXIpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIHJhbmtzID0gdGhpcy5yYW5rc1xuICAgICwgcm9vdHMgPSB0aGlzLnJvb3RzXG4gICAgLCB4ZCAgICA9IHJhbmtzW3hyXVxuICAgICwgeWQgICAgPSByYW5rc1t5cl07XG4gIGlmKHhkIDwgeWQpIHtcbiAgICByb290c1t4cl0gPSB5cjtcbiAgfSBlbHNlIGlmKHlkIDwgeGQpIHtcbiAgICByb290c1t5cl0gPSB4cjtcbiAgfSBlbHNlIHtcbiAgICByb290c1t5cl0gPSB4cjtcbiAgICArK3JhbmtzW3hyXTtcbiAgfVxufVxufSx7fV0sNTQ3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbmZ1bmN0aW9uIHVuaXF1ZV9wcmVkKGxpc3QsIGNvbXBhcmUpIHtcbiAgdmFyIHB0ciA9IDFcbiAgICAsIGxlbiA9IGxpc3QubGVuZ3RoXG4gICAgLCBhPWxpc3RbMF0sIGI9bGlzdFswXVxuICBmb3IodmFyIGk9MTsgaTxsZW47ICsraSkge1xuICAgIGIgPSBhXG4gICAgYSA9IGxpc3RbaV1cbiAgICBpZihjb21wYXJlKGEsIGIpKSB7XG4gICAgICBpZihpID09PSBwdHIpIHtcbiAgICAgICAgcHRyKytcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGxpc3RbcHRyKytdID0gYVxuICAgIH1cbiAgfVxuICBsaXN0Lmxlbmd0aCA9IHB0clxuICByZXR1cm4gbGlzdFxufVxuXG5mdW5jdGlvbiB1bmlxdWVfZXEobGlzdCkge1xuICB2YXIgcHRyID0gMVxuICAgICwgbGVuID0gbGlzdC5sZW5ndGhcbiAgICAsIGE9bGlzdFswXSwgYiA9IGxpc3RbMF1cbiAgZm9yKHZhciBpPTE7IGk8bGVuOyArK2ksIGI9YSkge1xuICAgIGIgPSBhXG4gICAgYSA9IGxpc3RbaV1cbiAgICBpZihhICE9PSBiKSB7XG4gICAgICBpZihpID09PSBwdHIpIHtcbiAgICAgICAgcHRyKytcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cbiAgICAgIGxpc3RbcHRyKytdID0gYVxuICAgIH1cbiAgfVxuICBsaXN0Lmxlbmd0aCA9IHB0clxuICByZXR1cm4gbGlzdFxufVxuXG5mdW5jdGlvbiB1bmlxdWUobGlzdCwgY29tcGFyZSwgc29ydGVkKSB7XG4gIGlmKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGxpc3RcbiAgfVxuICBpZihjb21wYXJlKSB7XG4gICAgaWYoIXNvcnRlZCkge1xuICAgICAgbGlzdC5zb3J0KGNvbXBhcmUpXG4gICAgfVxuICAgIHJldHVybiB1bmlxdWVfcHJlZChsaXN0LCBjb21wYXJlKVxuICB9XG4gIGlmKCFzb3J0ZWQpIHtcbiAgICBsaXN0LnNvcnQoKVxuICB9XG4gIHJldHVybiB1bmlxdWVfZXEobGlzdClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB1bmlxdWVcblxufSx7fV0sNTQ4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciByZWcgPSAvW1xcJ1xcXCJdL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHVucXVvdGUoc3RyKSB7XG4gIGlmICghc3RyKSB7XG4gICAgcmV0dXJuICcnXG4gIH1cbiAgaWYgKHJlZy50ZXN0KHN0ci5jaGFyQXQoMCkpKSB7XG4gICAgc3RyID0gc3RyLnN1YnN0cigxKVxuICB9XG4gIGlmIChyZWcudGVzdChzdHIuY2hhckF0KHN0ci5sZW5ndGggLSAxKSkpIHtcbiAgICBzdHIgPSBzdHIuc3Vic3RyKDAsIHN0ci5sZW5ndGggLSAxKVxuICB9XG4gIHJldHVybiBzdHJcbn1cblxufSx7fV0sNTQ5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxyXG4gKiBAbW9kdWxlIHVwZGF0ZS1kaWZmXHJcbiAqL1xyXG5cclxuJ3VzZSBzdHJpY3QnXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHVwZGF0ZURpZmYgKG9iaiwgZGlmZiwgbWFwcGVycykge1xyXG5cdGlmICghQXJyYXkuaXNBcnJheShtYXBwZXJzKSkgbWFwcGVycyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKVxyXG5cclxuXHRmb3IgKHZhciBpID0gMCwgbCA9IG1hcHBlcnMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XHJcblx0XHR2YXIgZGljdCA9IG1hcHBlcnNbaV1cclxuXHRcdGZvciAodmFyIHByb3AgaW4gZGljdCkge1xyXG5cdFx0XHRpZiAoZGlmZltwcm9wXSAhPT0gdW5kZWZpbmVkICYmICFBcnJheS5pc0FycmF5KGRpZmZbcHJvcF0pICYmIG9ialtwcm9wXSA9PT0gZGlmZltwcm9wXSkgY29udGludWVcclxuXHJcblx0XHRcdGlmIChwcm9wIGluIGRpZmYpIHtcclxuXHRcdFx0XHR2YXIgcmVzdWx0XHJcblxyXG5cdFx0XHRcdGlmIChkaWN0W3Byb3BdID09PSB0cnVlKSByZXN1bHQgPSBkaWZmW3Byb3BdXHJcblx0XHRcdFx0ZWxzZSBpZiAoZGljdFtwcm9wXSA9PT0gZmFsc2UpIGNvbnRpbnVlXHJcblx0XHRcdFx0ZWxzZSBpZiAodHlwZW9mIGRpY3RbcHJvcF0gPT09ICdmdW5jdGlvbicpIHtcclxuXHRcdFx0XHRcdHJlc3VsdCA9IGRpY3RbcHJvcF0oZGlmZltwcm9wXSwgb2JqLCBkaWZmKVxyXG5cdFx0XHRcdFx0aWYgKHJlc3VsdCA9PT0gdW5kZWZpbmVkKSBjb250aW51ZVxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0b2JqW3Byb3BdID0gcmVzdWx0XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHJldHVybiBvYmpcclxufVxyXG5cbn0se31dLDU1MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5cInVzZSBzdHJpY3RcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVRleHRcblxudmFyIHZlY3Rvcml6ZVRleHQgPSBfZGVyZXFfKFwiLi9saWIvdnRleHRcIilcbnZhciBkZWZhdWx0Q2FudmFzID0gbnVsbFxudmFyIGRlZmF1bHRDb250ZXh0ID0gbnVsbFxuXG5pZih0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gIGRlZmF1bHRDYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKVxuICBkZWZhdWx0Q2FudmFzLndpZHRoID0gODE5MlxuICBkZWZhdWx0Q2FudmFzLmhlaWdodCA9IDEwMjRcbiAgZGVmYXVsdENvbnRleHQgPSBkZWZhdWx0Q2FudmFzLmdldENvbnRleHQoXCIyZFwiKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVUZXh0KHN0ciwgb3B0aW9ucykge1xuICBpZigodHlwZW9mIG9wdGlvbnMgIT09IFwib2JqZWN0XCIpIHx8IChvcHRpb25zID09PSBudWxsKSkge1xuICAgIG9wdGlvbnMgPSB7fVxuICB9XG4gIHJldHVybiB2ZWN0b3JpemVUZXh0KFxuICAgIHN0cixcbiAgICBvcHRpb25zLmNhbnZhcyB8fCBkZWZhdWx0Q2FudmFzLFxuICAgIG9wdGlvbnMuY29udGV4dCB8fCBkZWZhdWx0Q29udGV4dCxcbiAgICBvcHRpb25zKVxufVxuXG59LHtcIi4vbGliL3Z0ZXh0XCI6NTUxfV0sNTUxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbm1vZHVsZS5leHBvcnRzID0gdmVjdG9yaXplVGV4dFxubW9kdWxlLmV4cG9ydHMucHJvY2Vzc1BpeGVscyA9IHByb2Nlc3NQaXhlbHNcblxudmFyIHN1cmZhY2VOZXRzID0gX2RlcmVxXygnc3VyZmFjZS1uZXRzJylcbnZhciBuZGFycmF5ID0gX2RlcmVxXygnbmRhcnJheScpXG52YXIgc2ltcGxpZnkgPSBfZGVyZXFfKCdzaW1wbGlmeS1wbGFuYXItZ3JhcGgnKVxudmFyIGNsZWFuUFNMRyA9IF9kZXJlcV8oJ2NsZWFuLXBzbGcnKVxudmFyIGNkdDJkID0gX2RlcmVxXygnY2R0MmQnKVxudmFyIHRvUG9seWdvbkNyYXBweSA9IF9kZXJlcV8oJ3BsYW5hci1ncmFwaC10by1wb2x5bGluZScpXG5cbnZhciBUQUdfYm9sZCA9IFwiYlwiXG52YXIgQ0hSX2JvbGQgPSAnYnwnXG5cbnZhciBUQUdfaXRhbGljID0gXCJpXCJcbnZhciBDSFJfaXRhbGljID0gJ2l8J1xuXG52YXIgVEFHX3N1cGVyID0gXCJzdXBcIlxudmFyIENIUl9zdXBlcjAgPSAnKydcbnZhciBDSFJfc3VwZXIgPSAnKzEnXG5cbnZhciBUQUdfc3ViID0gXCJzdWJcIlxudmFyIENIUl9zdWIwID0gJy0nXG52YXIgQ0hSX3N1YiA9ICctMSdcblxuZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBUQUdfQ0hSLCBzdHIsIG1hcCkge1xuXG4gIHZhciBvcG5UYWcgPSAgXCI8XCIgICsgdGFnICsgXCI+XCJcbiAgdmFyIGNsc1RhZyA9ICBcIjwvXCIgKyB0YWcgKyBcIj5cIlxuXG4gIHZhciBuT1BOID0gb3BuVGFnLmxlbmd0aFxuICB2YXIgbkNMUyA9IGNsc1RhZy5sZW5ndGhcblxuICB2YXIgaXNSZWN1cnNpdmUgPSAoVEFHX0NIUlswXSA9PT0gQ0hSX3N1cGVyMCkgfHxcbiAgICAgICAgICAgICAgICAgICAgKFRBR19DSFJbMF0gPT09IENIUl9zdWIwKTtcblxuICB2YXIgYSA9IDBcbiAgdmFyIGIgPSAtbkNMU1xuICB3aGlsZSAoYSA+IC0xKSB7XG4gICAgYSA9IHN0ci5pbmRleE9mKG9wblRhZywgYSlcbiAgICBpZihhID09PSAtMSkgYnJlYWtcblxuICAgIGIgPSBzdHIuaW5kZXhPZihjbHNUYWcsIGEgKyBuT1BOKVxuICAgIGlmKGIgPT09IC0xKSBicmVha1xuXG4gICAgaWYoYiA8PSBhKSBicmVha1xuXG4gICAgZm9yKHZhciBpID0gYTsgaSA8IGIgKyBuQ0xTOyArK2kpe1xuICAgICAgaWYoKGkgPCBhICsgbk9QTikgfHwgKGkgPj0gYikpIHtcbiAgICAgICAgbWFwW2ldID0gbnVsbFxuICAgICAgICBzdHIgPSBzdHIuc3Vic3RyKDAsIGkpICsgXCIgXCIgKyBzdHIuc3Vic3RyKGkgKyAxKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYobWFwW2ldICE9PSBudWxsKSB7XG4gICAgICAgICAgdmFyIHBvcyA9IG1hcFtpXS5pbmRleE9mKFRBR19DSFJbMF0pXG4gICAgICAgICAgaWYocG9zID09PSAtMSkge1xuICAgICAgICAgICAgbWFwW2ldICs9IFRBR19DSFJcbiAgICAgICAgICB9IGVsc2UgeyAvLyBpLmUuIHRvIGhhbmRsZSBtdWx0aXBsZSBzdWIvc3VwZXItc2NyaXB0c1xuICAgICAgICAgICAgaWYoaXNSZWN1cnNpdmUpIHtcbiAgICAgICAgICAgICAgLy8gaS5lIHRvIGluY3JlYXNlIHRoZSBzdWIvc3VwIG51bWJlclxuICAgICAgICAgICAgICBtYXBbaV0gPSBtYXBbaV0uc3Vic3RyKDAsIHBvcyArIDEpICsgKDEgKyBwYXJzZUludChtYXBbaV1bcG9zICsgMV0pKSArIG1hcFtpXS5zdWJzdHIocG9zICsgMilcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc3RhcnQgPSBhICsgbk9QTlxuICAgIHZhciByZW1haW5pbmdTdHIgPSBzdHIuc3Vic3RyKHN0YXJ0LCBiIC0gc3RhcnQpXG5cbiAgICB2YXIgYyA9IHJlbWFpbmluZ1N0ci5pbmRleE9mKG9wblRhZylcbiAgICBpZihjICE9PSAtMSkgYSA9IGNcbiAgICBlbHNlIGEgPSBiICsgbkNMU1xuICB9XG5cbiAgcmV0dXJuIG1hcFxufVxuXG5mdW5jdGlvbiB0cmFuc2Zvcm1Qb3NpdGlvbnMocG9zaXRpb25zLCBvcHRpb25zLCBzaXplKSB7XG4gIHZhciBhbGlnbiA9IG9wdGlvbnMudGV4dEFsaWduIHx8IFwic3RhcnRcIlxuICB2YXIgYmFzZWxpbmUgPSBvcHRpb25zLnRleHRCYXNlbGluZSB8fCBcImFscGhhYmV0aWNcIlxuXG4gIHZhciBsbyA9IFsxPDwzMCwgMTw8MzBdXG4gIHZhciBoaSA9IFswLDBdXG4gIHZhciBuID0gcG9zaXRpb25zLmxlbmd0aFxuICBmb3IodmFyIGk9MDsgaTxuOyArK2kpIHtcbiAgICB2YXIgcCA9IHBvc2l0aW9uc1tpXVxuICAgIGZvcih2YXIgaj0wOyBqPDI7ICsraikge1xuICAgICAgbG9bal0gPSBNYXRoLm1pbihsb1tqXSwgcFtqXSl8MFxuICAgICAgaGlbal0gPSBNYXRoLm1heChoaVtqXSwgcFtqXSl8MFxuICAgIH1cbiAgfVxuXG4gIHZhciB4U2hpZnQgPSAwXG4gIHN3aXRjaChhbGlnbikge1xuICAgIGNhc2UgXCJjZW50ZXJcIjpcbiAgICAgIHhTaGlmdCA9IC0wLjUgKiAobG9bMF0gKyBoaVswXSlcbiAgICBicmVha1xuXG4gICAgY2FzZSBcInJpZ2h0XCI6XG4gICAgY2FzZSBcImVuZFwiOlxuICAgICAgeFNoaWZ0ID0gLWhpWzBdXG4gICAgYnJlYWtcblxuICAgIGNhc2UgXCJsZWZ0XCI6XG4gICAgY2FzZSBcInN0YXJ0XCI6XG4gICAgICB4U2hpZnQgPSAtbG9bMF1cbiAgICBicmVha1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInZlY3Rvcml6ZS10ZXh0OiBVbnJlY29nbml6ZWQgdGV4dEFsaWduOiAnXCIgKyBhbGlnbiArIFwiJ1wiKVxuICB9XG5cbiAgdmFyIHlTaGlmdCA9IDBcbiAgc3dpdGNoKGJhc2VsaW5lKSB7XG4gICAgY2FzZSBcImhhbmdpbmdcIjpcbiAgICBjYXNlIFwidG9wXCI6XG4gICAgICB5U2hpZnQgPSAtbG9bMV1cbiAgICBicmVha1xuXG4gICAgY2FzZSBcIm1pZGRsZVwiOlxuICAgICAgeVNoaWZ0ID0gLTAuNSAqIChsb1sxXSArIGhpWzFdKVxuICAgIGJyZWFrXG5cbiAgICBjYXNlIFwiYWxwaGFiZXRpY1wiOlxuICAgIGNhc2UgXCJpZGVvZ3JhcGhpY1wiOlxuICAgICAgeVNoaWZ0ID0gLTMgKiBzaXplXG4gICAgYnJlYWtcblxuICAgIGNhc2UgXCJib3R0b21cIjpcbiAgICAgIHlTaGlmdCA9IC1oaVsxXVxuICAgIGJyZWFrXG5cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwidmVjdG9yaXplLXRleHQ6IFVucmVjb2dpbml6ZWQgdGV4dEJhc2VsaW5lOiAnXCIgKyBiYXNlbGluZSArIFwiJ1wiKVxuICB9XG5cbiAgdmFyIHNjYWxlID0gMS4wIC8gc2l6ZVxuICBpZihcImxpbmVIZWlnaHRcIiBpbiBvcHRpb25zKSB7XG4gICAgc2NhbGUgKj0gK29wdGlvbnMubGluZUhlaWdodFxuICB9IGVsc2UgaWYoXCJ3aWR0aFwiIGluIG9wdGlvbnMpIHtcbiAgICBzY2FsZSA9IG9wdGlvbnMud2lkdGggLyAoaGlbMF0gLSBsb1swXSlcbiAgfSBlbHNlIGlmKFwiaGVpZ2h0XCIgaW4gb3B0aW9ucykge1xuICAgIHNjYWxlID0gb3B0aW9ucy5oZWlnaHQgLyAoaGlbMV0gLSBsb1sxXSlcbiAgfVxuXG4gIHJldHVybiBwb3NpdGlvbnMubWFwKGZ1bmN0aW9uKHApIHtcbiAgICByZXR1cm4gWyBzY2FsZSAqIChwWzBdICsgeFNoaWZ0KSwgc2NhbGUgKiAocFsxXSArIHlTaGlmdCkgXVxuICB9KVxufVxuXG5mdW5jdGlvbiBnZXRQaXhlbHMoY2FudmFzLCBjb250ZXh0LCByYXdTdHJpbmcsIGZvbnRTaXplLCBsaW5lU3BhY2luZywgc3R5bGV0YWdzKSB7XG5cbiAgcmF3U3RyaW5nID0gcmF3U3RyaW5nLnJlcGxhY2UoL1xcbi9nLCAnJykgLy8gZG9uJ3QgYWNjZXB0IFxcbiBpbiB0aGUgaW5wdXRcblxuICBpZihzdHlsZXRhZ3MuYnJlYWtsaW5lcyA9PT0gdHJ1ZSkge1xuICAgIHJhd1N0cmluZyA9IHJhd1N0cmluZy5yZXBsYWNlKC9cXDxiclxcPi9nLCAnXFxuJykgLy8gcmVwbGFjZSA8YnI+IHRhZ3Mgd2l0aCBcXG4gaW4gdGhlIHN0cmluZ1xuICB9IGVsc2Uge1xuICAgIHJhd1N0cmluZyA9IHJhd1N0cmluZy5yZXBsYWNlKC9cXDxiclxcPi9nLCAnICcpIC8vIGRvbid0IGFjY2VwdCA8YnI+IHRhZ3MgaW4gdGhlIGlucHV0IGFuZCByZXBsYWNlIHdpdGggc3BhY2UgaW4gdGhpcyBjYXNlXG4gIH1cblxuICB2YXIgYWN0aXZlU3R5bGUgPSBcIlwiXG4gIHZhciBtYXAgPSBbXVxuICBmb3IoaiA9IDA7IGogPCByYXdTdHJpbmcubGVuZ3RoOyArK2opIHtcbiAgICBtYXBbal0gPSBhY3RpdmVTdHlsZVxuICB9XG5cbiAgaWYoc3R5bGV0YWdzLmJvbGRzID09PSB0cnVlKSBtYXAgPSBwYXJzZVRhZyhUQUdfYm9sZCwgQ0hSX2JvbGQsIHJhd1N0cmluZywgbWFwKVxuICBpZihzdHlsZXRhZ3MuaXRhbGljcyA9PT0gdHJ1ZSkgbWFwID0gcGFyc2VUYWcoVEFHX2l0YWxpYywgQ0hSX2l0YWxpYywgcmF3U3RyaW5nLCBtYXApXG4gIGlmKHN0eWxldGFncy5zdXBlcnNjcmlwdHMgPT09IHRydWUpIG1hcCA9IHBhcnNlVGFnKFRBR19zdXBlciwgQ0hSX3N1cGVyLCByYXdTdHJpbmcsIG1hcClcbiAgaWYoc3R5bGV0YWdzLnN1YnNjcmlwdHMgPT09IHRydWUpIG1hcCA9IHBhcnNlVGFnKFRBR19zdWIsIENIUl9zdWIsIHJhd1N0cmluZywgbWFwKVxuXG4gIHZhciBhbGxTdHlsZXMgPSBbXVxuICB2YXIgcGxhaW5UZXh0ID0gXCJcIlxuICBmb3IoaiA9IDA7IGogPCByYXdTdHJpbmcubGVuZ3RoOyArK2opIHtcbiAgICBpZihtYXBbal0gIT09IG51bGwpIHtcbiAgICAgIHBsYWluVGV4dCArPSByYXdTdHJpbmdbal1cbiAgICAgIGFsbFN0eWxlcy5wdXNoKG1hcFtqXSlcbiAgICB9XG4gIH1cblxuICB2YXIgYWxsVGV4dHMgPSBwbGFpblRleHQuc3BsaXQoJ1xcbicpXG5cbiAgdmFyIG51bWJlck9mTGluZXMgPSBhbGxUZXh0cy5sZW5ndGhcbiAgdmFyIGxpbmVIZWlnaHQgPSBNYXRoLnJvdW5kKGxpbmVTcGFjaW5nICogZm9udFNpemUpXG4gIHZhciBvZmZzZXRYID0gZm9udFNpemVcbiAgdmFyIG9mZnNldFkgPSBmb250U2l6ZSAqIDJcbiAgdmFyIG1heFdpZHRoID0gMFxuICB2YXIgbWluSGVpZ2h0ID0gbnVtYmVyT2ZMaW5lcyAqIGxpbmVIZWlnaHQgKyBvZmZzZXRZXG5cbiAgaWYoY2FudmFzLmhlaWdodCA8IG1pbkhlaWdodCkge1xuICAgIGNhbnZhcy5oZWlnaHQgPSBtaW5IZWlnaHRcbiAgfVxuXG4gIGNvbnRleHQuZmlsbFN0eWxlID0gXCIjMDAwXCJcbiAgY29udGV4dC5maWxsUmVjdCgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpXG5cbiAgY29udGV4dC5maWxsU3R5bGUgPSBcIiNmZmZcIlxuICB2YXIgaSwgaiwgeFBvcywgeVBvcywgelBvc1xuICB2YXIgbkRvbmUgPSAwXG5cbiAgdmFyIGJ1ZmZlciA9IFwiXCJcbiAgZnVuY3Rpb24gd3JpdGVCdWZmZXIoKSB7XG4gICAgaWYoYnVmZmVyICE9PSBcIlwiKSB7XG4gICAgICB2YXIgZGVsdGEgPSBjb250ZXh0Lm1lYXN1cmVUZXh0KGJ1ZmZlcikud2lkdGhcblxuICAgICAgY29udGV4dC5maWxsVGV4dChidWZmZXIsIG9mZnNldFggKyB4UG9zLCBvZmZzZXRZICsgeVBvcylcbiAgICAgIHhQb3MgKz0gZGVsdGFcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBnZXRUZXh0Rm9udFNpemUoKSB7XG4gICAgcmV0dXJuIFwiXCIgKyBNYXRoLnJvdW5kKHpQb3MpICsgXCJweCBcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoYW5nZVN0eWxlKG9sZFN0eWxlLCBuZXdTdHlsZSkge1xuICAgIHZhciBjdHhGb250ID0gXCJcIiArIGNvbnRleHQuZm9udDtcblxuICAgIGlmKHN0eWxldGFncy5zdWJzY3JpcHRzID09PSB0cnVlKSB7XG4gICAgICB2YXIgb2xkSW5kZXhfU3ViID0gb2xkU3R5bGUuaW5kZXhPZihDSFJfc3ViMCk7XG4gICAgICB2YXIgbmV3SW5kZXhfU3ViID0gbmV3U3R5bGUuaW5kZXhPZihDSFJfc3ViMCk7XG5cbiAgICAgIHZhciBvbGRTdWIgPSAob2xkSW5kZXhfU3ViID4gLTEpID8gcGFyc2VJbnQob2xkU3R5bGVbMSArIG9sZEluZGV4X1N1Yl0pIDogMDtcbiAgICAgIHZhciBuZXdTdWIgPSAobmV3SW5kZXhfU3ViID4gLTEpID8gcGFyc2VJbnQobmV3U3R5bGVbMSArIG5ld0luZGV4X1N1Yl0pIDogMDtcblxuICAgICAgaWYob2xkU3ViICE9PSBuZXdTdWIpIHtcbiAgICAgICAgY3R4Rm9udCA9IGN0eEZvbnQucmVwbGFjZShnZXRUZXh0Rm9udFNpemUoKSwgXCI/cHggXCIpXG4gICAgICAgIHpQb3MgKj0gTWF0aC5wb3coMC43NSwgKG5ld1N1YiAtIG9sZFN1YikpXG4gICAgICAgIGN0eEZvbnQgPSBjdHhGb250LnJlcGxhY2UoXCI/cHggXCIsIGdldFRleHRGb250U2l6ZSgpKVxuICAgICAgfVxuICAgICAgeVBvcyArPSAwLjI1ICogbGluZUhlaWdodCAqIChuZXdTdWIgLSBvbGRTdWIpO1xuICAgIH1cblxuICAgIGlmKHN0eWxldGFncy5zdXBlcnNjcmlwdHMgPT09IHRydWUpIHtcbiAgICAgIHZhciBvbGRJbmRleF9TdXBlciA9IG9sZFN0eWxlLmluZGV4T2YoQ0hSX3N1cGVyMCk7XG4gICAgICB2YXIgbmV3SW5kZXhfU3VwZXIgPSBuZXdTdHlsZS5pbmRleE9mKENIUl9zdXBlcjApO1xuXG4gICAgICB2YXIgb2xkU3VwZXIgPSAob2xkSW5kZXhfU3VwZXIgPiAtMSkgPyBwYXJzZUludChvbGRTdHlsZVsxICsgb2xkSW5kZXhfU3VwZXJdKSA6IDA7XG4gICAgICB2YXIgbmV3U3VwZXIgPSAobmV3SW5kZXhfU3VwZXIgPiAtMSkgPyBwYXJzZUludChuZXdTdHlsZVsxICsgbmV3SW5kZXhfU3VwZXJdKSA6IDA7XG5cbiAgICAgIGlmKG9sZFN1cGVyICE9PSBuZXdTdXBlcikge1xuICAgICAgICBjdHhGb250ID0gY3R4Rm9udC5yZXBsYWNlKGdldFRleHRGb250U2l6ZSgpLCBcIj9weCBcIilcbiAgICAgICAgelBvcyAqPSBNYXRoLnBvdygwLjc1LCAobmV3U3VwZXIgLSBvbGRTdXBlcikpXG4gICAgICAgIGN0eEZvbnQgPSBjdHhGb250LnJlcGxhY2UoXCI/cHggXCIsIGdldFRleHRGb250U2l6ZSgpKVxuICAgICAgfVxuICAgICAgeVBvcyAtPSAwLjI1ICogbGluZUhlaWdodCAqIChuZXdTdXBlciAtIG9sZFN1cGVyKTtcbiAgICB9XG5cbiAgICBpZihzdHlsZXRhZ3MuYm9sZHMgPT09IHRydWUpIHtcbiAgICAgIHZhciB3YXNCb2xkID0gKG9sZFN0eWxlLmluZGV4T2YoQ0hSX2JvbGQpID4gLTEpXG4gICAgICB2YXIgaXNfQm9sZCA9IChuZXdTdHlsZS5pbmRleE9mKENIUl9ib2xkKSA+IC0xKVxuXG4gICAgICBpZighd2FzQm9sZCAmJiBpc19Cb2xkKSB7XG4gICAgICAgIGlmKHdhc0l0YWxpYykge1xuICAgICAgICAgIGN0eEZvbnQgPSBjdHhGb250LnJlcGxhY2UoXCJpdGFsaWMgXCIsIFwiaXRhbGljIGJvbGQgXCIpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY3R4Rm9udCA9IFwiYm9sZCBcIiArIGN0eEZvbnRcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYod2FzQm9sZCAmJiAhaXNfQm9sZCkge1xuICAgICAgICBjdHhGb250ID0gY3R4Rm9udC5yZXBsYWNlKFwiYm9sZCBcIiwgJycpXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYoc3R5bGV0YWdzLml0YWxpY3MgPT09IHRydWUpIHtcbiAgICAgIHZhciB3YXNJdGFsaWMgPSAob2xkU3R5bGUuaW5kZXhPZihDSFJfaXRhbGljKSA+IC0xKVxuICAgICAgdmFyIGlzX0l0YWxpYyA9IChuZXdTdHlsZS5pbmRleE9mKENIUl9pdGFsaWMpID4gLTEpXG5cbiAgICAgIGlmKCF3YXNJdGFsaWMgJiYgaXNfSXRhbGljKSB7XG4gICAgICAgIGN0eEZvbnQgPSBcIml0YWxpYyBcIiArIGN0eEZvbnRcbiAgICAgIH1cbiAgICAgIGlmKHdhc0l0YWxpYyAmJiAhaXNfSXRhbGljKSB7XG4gICAgICAgIGN0eEZvbnQgPSBjdHhGb250LnJlcGxhY2UoXCJpdGFsaWMgXCIsICcnKVxuICAgICAgfVxuICAgIH1cbiAgICBjb250ZXh0LmZvbnQgPSBjdHhGb250XG4gIH1cblxuICBmb3IoaSA9IDA7IGkgPCBudW1iZXJPZkxpbmVzOyArK2kpIHtcbiAgICB2YXIgdHh0ID0gYWxsVGV4dHNbaV0gKyAnXFxuJ1xuICAgIHhQb3MgPSAwXG4gICAgeVBvcyA9IGkgKiBsaW5lSGVpZ2h0XG4gICAgelBvcyA9IGZvbnRTaXplXG5cbiAgICBidWZmZXIgPSBcIlwiXG4gICAgXG4gICAgZm9yKGogPSAwOyBqIDwgdHh0Lmxlbmd0aDsgKytqKSB7XG4gICAgICB2YXIgc3R5bGUgPSAoaiArIG5Eb25lIDwgYWxsU3R5bGVzLmxlbmd0aCkgPyBhbGxTdHlsZXNbaiArIG5Eb25lXSA6IGFsbFN0eWxlc1thbGxTdHlsZXMubGVuZ3RoIC0gMV1cbiAgICAgIGlmKGFjdGl2ZVN0eWxlID09PSBzdHlsZSkge1xuICAgICAgICBidWZmZXIgKz0gdHh0W2pdXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3cml0ZUJ1ZmZlcigpXG4gICAgICAgIGJ1ZmZlciA9IHR4dFtqXVxuXG4gICAgICAgIGlmKHN0eWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjaGFuZ2VTdHlsZShhY3RpdmVTdHlsZSwgc3R5bGUpXG4gICAgICAgICAgYWN0aXZlU3R5bGUgPSBzdHlsZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHdyaXRlQnVmZmVyKClcblxuICAgIG5Eb25lICs9IHR4dC5sZW5ndGhcblxuICAgIHZhciB3aWR0aCA9IE1hdGgucm91bmQoeFBvcyArIDIgKiBvZmZzZXRYKSB8IDBcbiAgICBpZihtYXhXaWR0aCA8IHdpZHRoKSBtYXhXaWR0aCA9IHdpZHRoXG4gIH1cblxuICAvL0N1dCBwaXhlbHMgZnJvbSBpbWFnZVxuICB2YXIgeEN1dCA9IG1heFdpZHRoXG4gIHZhciB5Q3V0ID0gb2Zmc2V0WSArIGxpbmVIZWlnaHQgKiBudW1iZXJPZkxpbmVzXG4gIHZhciBwaXhlbHMgPSBuZGFycmF5KGNvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIHhDdXQsIHlDdXQpLmRhdGEsIFt5Q3V0LCB4Q3V0LCA0XSlcbiAgcmV0dXJuIHBpeGVscy5waWNrKC0xLCAtMSwgMCkudHJhbnNwb3NlKDEsIDApXG59XG5cbmZ1bmN0aW9uIGdldENvbnRvdXIocGl4ZWxzLCBkb1NpbXBsaWZ5KSB7XG4gIHZhciBjb250b3VyID0gc3VyZmFjZU5ldHMocGl4ZWxzLCAxMjgpXG4gIGlmKGRvU2ltcGxpZnkpIHtcbiAgICByZXR1cm4gc2ltcGxpZnkoY29udG91ci5jZWxscywgY29udG91ci5wb3NpdGlvbnMsIDAuMjUpXG4gIH1cbiAgcmV0dXJuIHtcbiAgICBlZGdlczogY29udG91ci5jZWxscyxcbiAgICBwb3NpdGlvbnM6IGNvbnRvdXIucG9zaXRpb25zXG4gIH1cbn1cblxuZnVuY3Rpb24gcHJvY2Vzc1BpeGVsc0ltcGwocGl4ZWxzLCBvcHRpb25zLCBzaXplLCBzaW1wbGlmeSkge1xuICAvL0V4dHJhY3QgY29udG91clxuICB2YXIgY29udG91ciA9IGdldENvbnRvdXIocGl4ZWxzLCBzaW1wbGlmeSlcblxuICAvL0FwcGx5IHdhcnAgdG8gcG9zaXRpb25zXG4gIHZhciBwb3NpdGlvbnMgPSB0cmFuc2Zvcm1Qb3NpdGlvbnMoY29udG91ci5wb3NpdGlvbnMsIG9wdGlvbnMsIHNpemUpXG4gIHZhciBlZGdlcyAgICAgPSBjb250b3VyLmVkZ2VzXG4gIHZhciBmbGlwID0gXCJjY3dcIiA9PT0gb3B0aW9ucy5vcmllbnRhdGlvblxuXG4gIC8vQ2xlYW4gdXAgdGhlIFBTTEcsIHJlc29sdmUgc2VsZiBpbnRlcnNlY3Rpb25zLCBldGMuXG4gIGNsZWFuUFNMRyhwb3NpdGlvbnMsIGVkZ2VzKVxuXG4gIC8vSWYgdHJpYW5ndWxhdGUgZmxhZyBwYXNzZWQsIHRyaWFuZ3VsYXRlIHRoZSByZXN1bHRcbiAgaWYob3B0aW9ucy5wb2x5Z29ucyB8fCBvcHRpb25zLnBvbHlnb24gfHwgb3B0aW9ucy5wb2x5bGluZSkge1xuICAgIHZhciByZXN1bHQgPSB0b1BvbHlnb25DcmFwcHkoZWRnZXMsIHBvc2l0aW9ucylcbiAgICB2YXIgbnJlc3VsdCA9IG5ldyBBcnJheShyZXN1bHQubGVuZ3RoKVxuICAgIGZvcih2YXIgaT0wOyBpPHJlc3VsdC5sZW5ndGg7ICsraSkge1xuICAgICAgdmFyIGxvb3BzID0gcmVzdWx0W2ldXG4gICAgICB2YXIgbmxvb3BzID0gbmV3IEFycmF5KGxvb3BzLmxlbmd0aClcbiAgICAgIGZvcih2YXIgaj0wOyBqPGxvb3BzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgIHZhciBsb29wID0gbG9vcHNbal1cbiAgICAgICAgdmFyIG5sb29wID0gbmV3IEFycmF5KGxvb3AubGVuZ3RoKVxuICAgICAgICBmb3IodmFyIGs9MDsgazxsb29wLmxlbmd0aDsgKytrKSB7XG4gICAgICAgICAgbmxvb3Bba10gPSBwb3NpdGlvbnNbbG9vcFtrXV0uc2xpY2UoKVxuICAgICAgICB9XG4gICAgICAgIGlmKGZsaXApIHtcbiAgICAgICAgICBubG9vcC5yZXZlcnNlKClcbiAgICAgICAgfVxuICAgICAgICBubG9vcHNbal0gPSBubG9vcFxuICAgICAgfVxuICAgICAgbnJlc3VsdFtpXSA9IG5sb29wc1xuICAgIH1cbiAgICByZXR1cm4gbnJlc3VsdFxuICB9IGVsc2UgaWYob3B0aW9ucy50cmlhbmdsZXMgfHwgb3B0aW9ucy50cmlhbmd1bGF0ZSB8fCBvcHRpb25zLnRyaWFuZ2xlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNlbGxzOiBjZHQyZChwb3NpdGlvbnMsIGVkZ2VzLCB7XG4gICAgICAgIGRlbGF1bmF5OiBmYWxzZSxcbiAgICAgICAgZXh0ZXJpb3I6IGZhbHNlLFxuICAgICAgICBpbnRlcmlvcjogdHJ1ZVxuICAgICAgfSksXG4gICAgICBwb3NpdGlvbnM6IHBvc2l0aW9uc1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4ge1xuICAgICAgZWRnZXM6ICAgICBlZGdlcyxcbiAgICAgIHBvc2l0aW9uczogcG9zaXRpb25zXG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHByb2Nlc3NQaXhlbHMocGl4ZWxzLCBvcHRpb25zLCBzaXplKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHByb2Nlc3NQaXhlbHNJbXBsKHBpeGVscywgb3B0aW9ucywgc2l6ZSwgdHJ1ZSlcbiAgfSBjYXRjaChlKSB7fVxuICB0cnkge1xuICAgIHJldHVybiBwcm9jZXNzUGl4ZWxzSW1wbChwaXhlbHMsIG9wdGlvbnMsIHNpemUsIGZhbHNlKVxuICB9IGNhdGNoKGUpIHt9XG4gIGlmKG9wdGlvbnMucG9seWdvbnMgfHwgb3B0aW9ucy5wb2x5bGluZSB8fCBvcHRpb25zLnBvbHlnb24pIHtcbiAgICByZXR1cm4gW11cbiAgfVxuICBpZihvcHRpb25zLnRyaWFuZ2xlcyB8fCBvcHRpb25zLnRyaWFuZ3VsYXRlIHx8IG9wdGlvbnMudHJpYW5nbGUpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY2VsbHM6IFtdLFxuICAgICAgcG9zaXRpb25zOiBbXVxuICAgIH1cbiAgfVxuICByZXR1cm4ge1xuICAgIGVkZ2VzOiBbXSxcbiAgICBwb3NpdGlvbnM6IFtdXG4gIH1cbn1cblxuZnVuY3Rpb24gdmVjdG9yaXplVGV4dChzdHIsIGNhbnZhcywgY29udGV4dCwgb3B0aW9ucykge1xuICB2YXIgc2l6ZSA9IDY0XG4gIHZhciBsaW5lU3BhY2luZyA9IDEuMjVcbiAgdmFyIHN0eWxldGFncyA9IHtcbiAgICBicmVha2xpbmVzOiBmYWxzZSxcbiAgICBib2xkczogZmFsc2UsXG4gICAgaXRhbGljczogZmFsc2UsXG4gICAgc3Vic2NyaXB0czogZmFsc2UsXG4gICAgc3VwZXJzY3JpcHRzOiBmYWxzZVxuICB9XG5cbiAgaWYob3B0aW9ucykge1xuXG4gICAgaWYob3B0aW9ucy5zaXplICYmXG4gICAgICAgb3B0aW9ucy5zaXplID4gMCkgc2l6ZSA9XG4gICAgICAgb3B0aW9ucy5zaXplXG5cbiAgICBpZihvcHRpb25zLmxpbmVTcGFjaW5nICYmXG4gICAgICAgb3B0aW9ucy5saW5lU3BhY2luZyA+IDApIGxpbmVTcGFjaW5nID1cbiAgICAgICBvcHRpb25zLmxpbmVTcGFjaW5nXG5cbiAgICBpZihvcHRpb25zLnN0eWxldGFncyAmJlxuICAgICAgIG9wdGlvbnMuc3R5bGV0YWdzLmJyZWFrbGluZXMpIHN0eWxldGFncy5icmVha2xpbmVzID1cbiAgICAgICBvcHRpb25zLnN0eWxldGFncy5icmVha2xpbmVzID8gdHJ1ZSA6IGZhbHNlXG5cbiAgICBpZihvcHRpb25zLnN0eWxldGFncyAmJlxuICAgICAgIG9wdGlvbnMuc3R5bGV0YWdzLmJvbGRzKSBzdHlsZXRhZ3MuYm9sZHMgPVxuICAgICAgIG9wdGlvbnMuc3R5bGV0YWdzLmJvbGRzID8gdHJ1ZSA6IGZhbHNlXG5cbiAgICBpZihvcHRpb25zLnN0eWxldGFncyAmJlxuICAgICAgIG9wdGlvbnMuc3R5bGV0YWdzLml0YWxpY3MpIHN0eWxldGFncy5pdGFsaWNzID1cbiAgICAgICBvcHRpb25zLnN0eWxldGFncy5pdGFsaWNzID8gdHJ1ZSA6IGZhbHNlXG5cbiAgICBpZihvcHRpb25zLnN0eWxldGFncyAmJlxuICAgICAgIG9wdGlvbnMuc3R5bGV0YWdzLnN1YnNjcmlwdHMpIHN0eWxldGFncy5zdWJzY3JpcHRzID1cbiAgICAgICBvcHRpb25zLnN0eWxldGFncy5zdWJzY3JpcHRzID8gdHJ1ZSA6IGZhbHNlXG5cbiAgICBpZihvcHRpb25zLnN0eWxldGFncyAmJlxuICAgICAgIG9wdGlvbnMuc3R5bGV0YWdzLnN1cGVyc2NyaXB0cykgc3R5bGV0YWdzLnN1cGVyc2NyaXB0cyA9XG4gICAgICAgb3B0aW9ucy5zdHlsZXRhZ3Muc3VwZXJzY3JpcHRzID8gdHJ1ZSA6IGZhbHNlXG4gIH1cblxuICBjb250ZXh0LmZvbnQgPSBbXG4gICAgb3B0aW9ucy5mb250U3R5bGUsXG4gICAgb3B0aW9ucy5mb250VmFyaWFudCxcbiAgICBvcHRpb25zLmZvbnRXZWlnaHQsXG4gICAgc2l6ZSArIFwicHhcIixcbiAgICBvcHRpb25zLmZvbnRcbiAgXS5maWx0ZXIoZnVuY3Rpb24oZCkge3JldHVybiBkfSkuam9pbihcIiBcIilcbiAgY29udGV4dC50ZXh0QWxpZ24gPSBcInN0YXJ0XCJcbiAgY29udGV4dC50ZXh0QmFzZWxpbmUgPSBcImFscGhhYmV0aWNcIlxuICBjb250ZXh0LmRpcmVjdGlvbiA9IFwibHRyXCJcblxuICB2YXIgcGl4ZWxzID0gZ2V0UGl4ZWxzKGNhbnZhcywgY29udGV4dCwgc3RyLCBzaXplLCBsaW5lU3BhY2luZywgc3R5bGV0YWdzKVxuXG4gIHJldHVybiBwcm9jZXNzUGl4ZWxzKHBpeGVscywgb3B0aW9ucywgc2l6ZSlcbn1cblxufSx7XCJjZHQyZFwiOjEwNixcImNsZWFuLXBzbGdcIjoxMTYsXCJuZGFycmF5XCI6NDUwLFwicGxhbmFyLWdyYXBoLXRvLXBvbHlsaW5lXCI6NDY4LFwic2ltcGxpZnktcGxhbmFyLWdyYXBoXCI6NTI0LFwic3VyZmFjZS1uZXRzXCI6NTMxfV0sNTUyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8vIENvcHlyaWdodCAoQykgMjAxMSBHb29nbGUgSW5jLlxuLy9cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4vLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4vLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbi8vXG4vLyBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbi8vXG4vLyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4vLyBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4vLyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbi8vIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbi8vIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgSW5zdGFsbCBhIGxlYWt5IFdlYWtNYXAgZW11bGF0aW9uIG9uIHBsYXRmb3JtcyB0aGF0XG4gKiBkb24ndCBwcm92aWRlIGEgYnVpbHQtaW4gb25lLlxuICpcbiAqIDxwPkFzc3VtZXMgdGhhdCBhbiBFUzUgcGxhdGZvcm0gd2hlcmUsIGlmIHtAY29kZSBXZWFrTWFwfSBpc1xuICogYWxyZWFkeSBwcmVzZW50LCB0aGVuIGl0IGNvbmZvcm1zIHRvIHRoZSBhbnRpY2lwYXRlZCBFUzZcbiAqIHNwZWNpZmljYXRpb24uIFRvIHJ1biB0aGlzIGZpbGUgb24gYW4gRVM1IG9yIGFsbW9zdCBFUzVcbiAqIGltcGxlbWVudGF0aW9uIHdoZXJlIHRoZSB7QGNvZGUgV2Vha01hcH0gc3BlY2lmaWNhdGlvbiBkb2VzIG5vdFxuICogcXVpdGUgY29uZm9ybSwgcnVuIDxjb2RlPnJlcGFpckVTNS5qczwvY29kZT4gZmlyc3QuXG4gKlxuICogPHA+RXZlbiB0aG91Z2ggV2Vha01hcE1vZHVsZSBpcyBub3QgZ2xvYmFsLCB0aGUgbGludGVyIHRoaW5rcyBpdFxuICogaXMsIHdoaWNoIGlzIHdoeSBpdCBpcyBpbiB0aGUgb3ZlcnJpZGVzIGxpc3QgYmVsb3cuXG4gKlxuICogPHA+Tk9URTogQmVmb3JlIHVzaW5nIHRoaXMgV2Vha01hcCBlbXVsYXRpb24gaW4gYSBub24tU0VTXG4gKiBlbnZpcm9ubWVudCwgc2VlIHRoZSBub3RlIGJlbG93IGFib3V0IGhpZGRlblJlY29yZC5cbiAqXG4gKiBAYXV0aG9yIE1hcmsgUy4gTWlsbGVyXG4gKiBAcmVxdWlyZXMgY3J5cHRvLCBBcnJheUJ1ZmZlciwgVWludDhBcnJheSwgbmF2aWdhdG9yLCBjb25zb2xlXG4gKiBAb3ZlcnJpZGVzIFdlYWtNYXAsIHNlcywgUHJveHlcbiAqIEBvdmVycmlkZXMgV2Vha01hcE1vZHVsZVxuICovXG5cbi8qKlxuICogVGhpcyB7QGNvZGUgV2Vha01hcH0gZW11bGF0aW9uIGlzIG9ic2VydmFibHkgZXF1aXZhbGVudCB0byB0aGVcbiAqIEVTLUhhcm1vbnkgV2Vha01hcCwgYnV0IHdpdGggbGVha2llciBnYXJiYWdlIGNvbGxlY3Rpb24gcHJvcGVydGllcy5cbiAqXG4gKiA8cD5BcyB3aXRoIHRydWUgV2Vha01hcHMsIGluIHRoaXMgZW11bGF0aW9uLCBhIGtleSBkb2VzIG5vdFxuICogcmV0YWluIG1hcHMgaW5kZXhlZCBieSB0aGF0IGtleSBhbmQgKGNydWNpYWxseSkgYSBtYXAgZG9lcyBub3RcbiAqIHJldGFpbiB0aGUga2V5cyBpdCBpbmRleGVzLiBBIG1hcCBieSBpdHNlbGYgYWxzbyBkb2VzIG5vdCByZXRhaW5cbiAqIHRoZSB2YWx1ZXMgYXNzb2NpYXRlZCB3aXRoIHRoYXQgbWFwLlxuICpcbiAqIDxwPkhvd2V2ZXIsIHRoZSB2YWx1ZXMgYXNzb2NpYXRlZCB3aXRoIGEga2V5IGluIHNvbWUgbWFwIGFyZVxuICogcmV0YWluZWQgc28gbG9uZyBhcyB0aGF0IGtleSBpcyByZXRhaW5lZCBhbmQgdGhvc2UgYXNzb2NpYXRpb25zIGFyZVxuICogbm90IG92ZXJyaWRkZW4uIEZvciBleGFtcGxlLCB3aGVuIHVzZWQgdG8gc3VwcG9ydCBtZW1icmFuZXMsIGFsbFxuICogdmFsdWVzIGV4cG9ydGVkIGZyb20gYSBnaXZlbiBtZW1icmFuZSB3aWxsIGxpdmUgZm9yIHRoZSBsaWZldGltZVxuICogdGhleSB3b3VsZCBoYXZlIGhhZCBpbiB0aGUgYWJzZW5jZSBvZiBhbiBpbnRlcnBvc2VkIG1lbWJyYW5lLiBFdmVuXG4gKiB3aGVuIHRoZSBtZW1icmFuZSBpcyByZXZva2VkLCBhbGwgb2JqZWN0cyB0aGF0IHdvdWxkIGhhdmUgYmVlblxuICogcmVhY2hhYmxlIGluIHRoZSBhYnNlbmNlIG9mIHJldm9jYXRpb24gd2lsbCBzdGlsbCBiZSByZWFjaGFibGUsIGFzXG4gKiBmYXIgYXMgdGhlIEdDIGNhbiB0ZWxsLCBldmVuIHRob3VnaCB0aGV5IHdpbGwgbm8gbG9uZ2VyIGJlIHJlbGV2YW50XG4gKiB0byBvbmdvaW5nIGNvbXB1dGF0aW9uLlxuICpcbiAqIDxwPlRoZSBBUEkgaW1wbGVtZW50ZWQgaGVyZSBpcyBhcHByb3hpbWF0ZWx5IHRoZSBBUEkgYXMgaW1wbGVtZW50ZWRcbiAqIGluIEZGNi4wYTEgYW5kIGFncmVlZCB0byBieSBNYXJrTSwgQW5kcmVhcyBHYWwsIGFuZCBEYXZlIEhlcm1hbixcbiAqIHJhdGhlciB0aGFuIHRoZSBvZmZpYWxseSBhcHByb3ZlZCBwcm9wb3NhbCBwYWdlLiBUT0RPKGVyaWdodHMpOlxuICogdXBncmFkZSB0aGUgZWNtYXNjcmlwdCBXZWFrTWFwIHByb3Bvc2FsIHBhZ2UgdG8gZXhwbGFpbiB0aGlzIEFQSVxuICogY2hhbmdlIGFuZCBwcmVzZW50IHRvIEVjbWFTY3JpcHQgY29tbWl0dGVlIGZvciB0aGVpciBhcHByb3ZhbC5cbiAqXG4gKiA8cD5UaGUgZmlyc3QgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBlbXVsYXRpb24gaGVyZSBhbmQgdGhhdCBpblxuICogRkY2LjBhMSBpcyB0aGUgcHJlc2VuY2Ugb2Ygbm9uIGVudW1lcmFibGUge0Bjb2RlIGdldF9fXywgaGFzX19fLFxuICogc2V0X19fLCBhbmQgZGVsZXRlX19ffSBtZXRob2RzIG9uIFdlYWtNYXAgaW5zdGFuY2VzIHRvIHJlcHJlc2VudFxuICogd2hhdCB3b3VsZCBiZSB0aGUgaGlkZGVuIGludGVybmFsIHByb3BlcnRpZXMgb2YgYSBwcmltaXRpdmVcbiAqIGltcGxlbWVudGF0aW9uLiBXaGVyZWFzIHRoZSBGRjYuMGExIFdlYWtNYXAucHJvdG90eXBlIG1ldGhvZHNcbiAqIHJlcXVpcmUgdGhlaXIge0Bjb2RlIHRoaXN9IHRvIGJlIGEgZ2VudWluZSBXZWFrTWFwIGluc3RhbmNlIChpLmUuLFxuICogYW4gb2JqZWN0IG9mIHtAY29kZSBbW0NsYXNzXV19IFwiV2Vha01hcH0pLCBzaW5jZSB0aGVyZSBpcyBub3RoaW5nXG4gKiB1bmZvcmdlYWJsZSBhYm91dCB0aGUgcHNldWRvLWludGVybmFsIG1ldGhvZCBuYW1lcyB1c2VkIGhlcmUsXG4gKiBub3RoaW5nIHByZXZlbnRzIHRoZXNlIGVtdWxhdGVkIHByb3RvdHlwZSBtZXRob2RzIGZyb20gYmVpbmdcbiAqIGFwcGxpZWQgdG8gbm9uLVdlYWtNYXBzIHdpdGggcHNldWRvLWludGVybmFsIG1ldGhvZHMgb2YgdGhlIHNhbWVcbiAqIG5hbWVzLlxuICpcbiAqIDxwPkFub3RoZXIgZGlmZmVyZW5jZSBpcyB0aGF0IG91ciBlbXVsYXRlZCB7QGNvZGVcbiAqIFdlYWtNYXAucHJvdG90eXBlfSBpcyBub3QgaXRzZWxmIGEgV2Vha01hcC4gQSBwcm9ibGVtIHdpdGggdGhlXG4gKiBjdXJyZW50IEZGNi4wYTEgQVBJIGlzIHRoYXQgV2Vha01hcC5wcm90b3R5cGUgaXMgaXRzZWxmIGEgV2Vha01hcFxuICogcHJvdmlkaW5nIGFtYmllbnQgbXV0YWJpbGl0eSBhbmQgYW4gYW1iaWVudCBjb21tdW5pY2F0aW9uc1xuICogY2hhbm5lbC4gVGh1cywgaWYgYSBXZWFrTWFwIGlzIGFscmVhZHkgcHJlc2VudCBhbmQgaGFzIHRoaXNcbiAqIHByb2JsZW0sIHJlcGFpckVTNS5qcyB3cmFwcyBpdCBpbiBhIHNhZmUgd3JhcHBwZXIgaW4gb3JkZXIgdG9cbiAqIHByZXZlbnQgYWNjZXNzIHRvIHRoaXMgY2hhbm5lbC4gKFNlZVxuICogUEFUQ0hfTVVUQUJMRV9GUk9aRU5fV0VBS01BUF9QUk9UTyBpbiByZXBhaXJFUzUuanMpLlxuICovXG5cbi8qKlxuICogSWYgdGhpcyBpcyBhIGZ1bGwgPGEgaHJlZj1cbiAqIFwiaHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL2VzLWxhYi93aWtpL1NlY3VyZWFibGVFUzVcIlxuICogPnNlY3VyZWFibGUgRVM1PC9hPiBwbGF0Zm9ybSBhbmQgdGhlIEVTLUhhcm1vbnkge0Bjb2RlIFdlYWtNYXB9IGlzXG4gKiBhYnNlbnQsIGluc3RhbGwgYW4gYXBwcm94aW1hdGUgZW11bGF0aW9uLlxuICpcbiAqIDxwPklmIFdlYWtNYXAgaXMgcHJlc2VudCBidXQgY2Fubm90IHN0b3JlIHNvbWUgb2JqZWN0cywgdXNlIG91ciBhcHByb3hpbWF0ZVxuICogZW11bGF0aW9uIGFzIGEgd3JhcHBlci5cbiAqXG4gKiA8cD5JZiB0aGlzIGlzIGFsbW9zdCBhIHNlY3VyZWFibGUgRVM1IHBsYXRmb3JtLCB0aGVuIFdlYWtNYXAuanNcbiAqIHNob3VsZCBiZSBydW4gYWZ0ZXIgcmVwYWlyRVM1LmpzLlxuICpcbiAqIDxwPlNlZSB7QGNvZGUgV2Vha01hcH0gZm9yIGRvY3VtZW50YXRpb24gb2YgdGhlIGdhcmJhZ2UgY29sbGVjdGlvblxuICogcHJvcGVydGllcyBvZiB0aGlzIFdlYWtNYXAgZW11bGF0aW9uLlxuICovXG4oZnVuY3Rpb24gV2Vha01hcE1vZHVsZSgpIHtcbiAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgaWYgKHR5cGVvZiBzZXMgIT09ICd1bmRlZmluZWQnICYmIHNlcy5vayAmJiAhc2VzLm9rKCkpIHtcbiAgICAvLyBhbHJlYWR5IHRvbyBicm9rZW4sIHNvIGdpdmUgdXBcbiAgICByZXR1cm47XG4gIH1cblxuICAvKipcbiAgICogSW4gc29tZSBjYXNlcyAoY3VycmVudCBGaXJlZm94KSwgd2UgbXVzdCBtYWtlIGEgY2hvaWNlIGJldHdlZWVuIGFcbiAgICogV2Vha01hcCB3aGljaCBpcyBjYXBhYmxlIG9mIHVzaW5nIGFsbCB2YXJpZXRpZXMgb2YgaG9zdCBvYmplY3RzIGFzXG4gICAqIGtleXMgYW5kIG9uZSB3aGljaCBpcyBjYXBhYmxlIG9mIHNhZmVseSB1c2luZyBwcm94aWVzIGFzIGtleXMuIFNlZVxuICAgKiBjb21tZW50cyBiZWxvdyBhYm91dCBIb3N0V2Vha01hcCBhbmQgRG91YmxlV2Vha01hcCBmb3IgZGV0YWlscy5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiAod2hpY2ggaXMgYSBnbG9iYWwsIG5vdCBleHBvc2VkIHRvIGd1ZXN0cykgbWFya3MgYVxuICAgKiBXZWFrTWFwIGFzIHBlcm1pdHRlZCB0byBkbyB3aGF0IGlzIG5lY2Vzc2FyeSB0byBpbmRleCBhbGwgaG9zdFxuICAgKiBvYmplY3RzLCBhdCB0aGUgY29zdCBvZiBtYWtpbmcgaXQgdW5zYWZlIGZvciBwcm94aWVzLlxuICAgKlxuICAgKiBEbyBub3QgYXBwbHkgdGhpcyBmdW5jdGlvbiB0byBhbnl0aGluZyB3aGljaCBpcyBub3QgYSBnZW51aW5lXG4gICAqIGZyZXNoIFdlYWtNYXAuXG4gICAqL1xuICBmdW5jdGlvbiB3ZWFrTWFwUGVybWl0SG9zdE9iamVjdHMobWFwKSB7XG4gICAgLy8gaWRlbnRpdHkgb2YgZnVuY3Rpb24gdXNlZCBhcyBhIHNlY3JldCAtLSBnb29kIGVub3VnaCBhbmQgY2hlYXBcbiAgICBpZiAobWFwLnBlcm1pdEhvc3RPYmplY3RzX19fKSB7XG4gICAgICBtYXAucGVybWl0SG9zdE9iamVjdHNfX18od2Vha01hcFBlcm1pdEhvc3RPYmplY3RzKTtcbiAgICB9XG4gIH1cbiAgaWYgKHR5cGVvZiBzZXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgc2VzLndlYWtNYXBQZXJtaXRIb3N0T2JqZWN0cyA9IHdlYWtNYXBQZXJtaXRIb3N0T2JqZWN0cztcbiAgfVxuXG4gIC8vIElFIDExIGhhcyBubyBQcm94eSBidXQgaGFzIGEgYnJva2VuIFdlYWtNYXAgc3VjaCB0aGF0IHdlIG5lZWQgdG8gcGF0Y2hcbiAgLy8gaXQgdXNpbmcgRG91YmxlV2Vha01hcDsgdGhpcyBmbGFnIHRlbGxzIERvdWJsZVdlYWtNYXAgc28uXG4gIHZhciBkb3VibGVXZWFrTWFwQ2hlY2tTaWxlbnRGYWlsdXJlID0gZmFsc2U7XG5cbiAgLy8gQ2hlY2sgaWYgdGhlcmUgaXMgYWxyZWFkeSBhIGdvb2QtZW5vdWdoIFdlYWtNYXAgaW1wbGVtZW50YXRpb24sIGFuZCBpZiBzb1xuICAvLyBleGl0IHdpdGhvdXQgcmVwbGFjaW5nIGl0LlxuICBpZiAodHlwZW9mIFdlYWtNYXAgPT09ICdmdW5jdGlvbicpIHtcbiAgICB2YXIgSG9zdFdlYWtNYXAgPSBXZWFrTWFwO1xuICAgIC8vIFRoZXJlIGlzIGEgV2Vha01hcCAtLSBpcyBpdCBnb29kIGVub3VnaD9cbiAgICBpZiAodHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgL0ZpcmVmb3gvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICAgIC8vIFdlJ3JlIG5vdyAqYXNzdW1pbmcgbm90KiwgYmVjYXVzZSBhcyBvZiB0aGlzIHdyaXRpbmcgKDIwMTMtMDUtMDYpXG4gICAgICAvLyBGaXJlZm94J3MgV2Vha01hcHMgaGF2ZSBhIG1pc2NlbGxhbnkgb2Ygb2JqZWN0cyB0aGV5IHdvbid0IGFjY2VwdCwgYW5kXG4gICAgICAvLyB3ZSBkb24ndCB3YW50IHRvIG1ha2UgYW4gZXhoYXVzdGl2ZSBsaXN0LCBhbmQgdGVzdGluZyBmb3IganVzdCBvbmVcbiAgICAgIC8vIHdpbGwgYmUgYSBwcm9ibGVtIGlmIHRoYXQgb25lIGlzIGZpeGVkIGFsb25lIChhcyB0aGV5IGRpZCBmb3IgRXZlbnQpLlxuXG4gICAgICAvLyBJZiB0aGVyZSBpcyBhIHBsYXRmb3JtIHRoYXQgd2UgKmNhbiogcmVsaWFibHkgdGVzdCBvbiwgaGVyZSdzIGhvdyB0b1xuICAgICAgLy8gZG8gaXQ6XG4gICAgICAvLyAgdmFyIHByb2JsZW1hdGljID0gLi4uIDtcbiAgICAgIC8vICB2YXIgdGVzdEhvc3RNYXAgPSBuZXcgSG9zdFdlYWtNYXAoKTtcbiAgICAgIC8vICB0cnkge1xuICAgICAgLy8gICAgdGVzdEhvc3RNYXAuc2V0KHByb2JsZW1hdGljLCAxKTsgIC8vIEZpcmVmb3ggMjAgd2lsbCB0aHJvdyBoZXJlXG4gICAgICAvLyAgICBpZiAodGVzdEhvc3RNYXAuZ2V0KHByb2JsZW1hdGljKSA9PT0gMSkge1xuICAgICAgLy8gICAgICByZXR1cm47XG4gICAgICAvLyAgICB9XG4gICAgICAvLyAgfSBjYXRjaCAoZSkge31cblxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJRSAxMSBidWc6IFdlYWtNYXBzIHNpbGVudGx5IGZhaWwgdG8gc3RvcmUgZnJvemVuIG9iamVjdHMuXG4gICAgICB2YXIgdGVzdE1hcCA9IG5ldyBIb3N0V2Vha01hcCgpO1xuICAgICAgdmFyIHRlc3RPYmplY3QgPSBPYmplY3QuZnJlZXplKHt9KTtcbiAgICAgIHRlc3RNYXAuc2V0KHRlc3RPYmplY3QsIDEpO1xuICAgICAgaWYgKHRlc3RNYXAuZ2V0KHRlc3RPYmplY3QpICE9PSAxKSB7XG4gICAgICAgIGRvdWJsZVdlYWtNYXBDaGVja1NpbGVudEZhaWx1cmUgPSB0cnVlO1xuICAgICAgICAvLyBGYWxsIHRocm91Z2ggdG8gaW5zdGFsbGluZyBvdXIgV2Vha01hcC5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gV2Vha01hcDtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZhciBob3AgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O1xuICB2YXIgZ29wbiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzO1xuICB2YXIgZGVmUHJvcCA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTtcbiAgdmFyIGlzRXh0ZW5zaWJsZSA9IE9iamVjdC5pc0V4dGVuc2libGU7XG5cbiAgLyoqXG4gICAqIFNlY3VyaXR5IGRlcGVuZHMgb24gSElEREVOX05BTUUgYmVpbmcgYm90aCA8aT51bmd1ZXNzYWJsZTwvaT4gYW5kXG4gICAqIDxpPnVuZGlzY292ZXJhYmxlPC9pPiBieSB1bnRydXN0ZWQgY29kZS5cbiAgICpcbiAgICogPHA+R2l2ZW4gdGhlIGtub3duIHdlYWtuZXNzZXMgb2YgTWF0aC5yYW5kb20oKSBvbiBleGlzdGluZ1xuICAgKiBicm93c2VycywgaXQgZG9lcyBub3QgZ2VuZXJhdGUgdW5ndWVzc2FiaWxpdHkgd2UgY2FuIGJlIGNvbmZpZGVudFxuICAgKiBvZi5cbiAgICpcbiAgICogPHA+SXQgaXMgdGhlIG1vbmtleSBwYXRjaGluZyBsb2dpYyBpbiB0aGlzIGZpbGUgdGhhdCBpcyBpbnRlbmRlZFxuICAgKiB0byBlbnN1cmUgdW5kaXNjb3ZlcmFiaWxpdHkuIFRoZSBiYXNpYyBpZGVhIGlzIHRoYXQgdGhlcmUgYXJlXG4gICAqIHRocmVlIGZ1bmRhbWVudGFsIG1lYW5zIG9mIGRpc2NvdmVyaW5nIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0OlxuICAgKiBUaGUgZm9yL2luIGxvb3AsIE9iamVjdC5rZXlzKCksIGFuZCBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcygpLFxuICAgKiBhcyB3ZWxsIGFzIHNvbWUgcHJvcG9zZWQgRVM2IGV4dGVuc2lvbnMgdGhhdCBhcHBlYXIgb24gb3VyXG4gICAqIHdoaXRlbGlzdC4gVGhlIGZpcnN0IHR3byBvbmx5IGRpc2NvdmVyIGVudW1lcmFibGUgcHJvcGVydGllcywgYW5kXG4gICAqIHdlIG9ubHkgdXNlIEhJRERFTl9OQU1FIHRvIG5hbWUgYSBub24tZW51bWVyYWJsZSBwcm9wZXJ0eSwgc28gdGhlXG4gICAqIG9ubHkgcmVtYWluaW5nIHRocmVhdCBzaG91bGQgYmUgZ2V0T3duUHJvcGVydHlOYW1lcyBhbmQgc29tZVxuICAgKiBwcm9wb3NlZCBFUzYgZXh0ZW5zaW9ucyB0aGF0IGFwcGVhciBvbiBvdXIgd2hpdGVsaXN0LiBXZSBtb25rZXlcbiAgICogcGF0Y2ggdGhlbSB0byByZW1vdmUgSElEREVOX05BTUUgZnJvbSB0aGUgbGlzdCBvZiBwcm9wZXJ0aWVzIHRoZXlcbiAgICogcmV0dXJucy5cbiAgICpcbiAgICogPHA+VE9ETyhlcmlnaHRzKTogT24gYSBwbGF0Zm9ybSB3aXRoIGJ1aWx0LWluIFByb3hpZXMsIHByb3hpZXNcbiAgICogY291bGQgYmUgdXNlZCB0byB0cmFwIGFuZCB0aGVyZWJ5IGRpc2NvdmVyIHRoZSBISURERU5fTkFNRSwgc28gd2VcbiAgICogbmVlZCB0byBtb25rZXkgcGF0Y2ggUHJveHkuY3JlYXRlLCBQcm94eS5jcmVhdGVGdW5jdGlvbiwgZXRjLCBpblxuICAgKiBvcmRlciB0byB3cmFwIHRoZSBwcm92aWRlZCBoYW5kbGVyIHdpdGggdGhlIHJlYWwgaGFuZGxlciB3aGljaFxuICAgKiBmaWx0ZXJzIG91dCBhbGwgdHJhcHMgdXNpbmcgSElEREVOX05BTUUuXG4gICAqXG4gICAqIDxwPlRPRE8oZXJpZ2h0cyk6IFJldmlzaXQgTWlrZSBTdGF5J3Mgc3VnZ2VzdGlvbiB0aGF0IHdlIHVzZSBhblxuICAgKiBlbmNhcHN1bGF0ZWQgZnVuY3Rpb24gYXQgYSBub3QtbmVjZXNzYXJpbHktc2VjcmV0IG5hbWUsIHdoaWNoXG4gICAqIHVzZXMgdGhlIFN0aWVnbGVyIHNoYXJlZC1zdGF0ZSByaWdodHMgYW1wbGlmaWNhdGlvbiBwYXR0ZXJuIHRvXG4gICAqIHJldmVhbCB0aGUgYXNzb2NpYXRlZCB2YWx1ZSBvbmx5IHRvIHRoZSBXZWFrTWFwIGluIHdoaWNoIHRoaXMga2V5XG4gICAqIGlzIGFzc29jaWF0ZWQgd2l0aCB0aGF0IHZhbHVlLiBTaW5jZSBvbmx5IHRoZSBrZXkgcmV0YWlucyB0aGVcbiAgICogZnVuY3Rpb24sIHRoZSBmdW5jdGlvbiBjYW4gYWxzbyByZW1lbWJlciB0aGUga2V5IHdpdGhvdXQgY2F1c2luZ1xuICAgKiBsZWFrYWdlIG9mIHRoZSBrZXksIHNvIHRoaXMgZG9lc24ndCB2aW9sYXRlIG91ciBnZW5lcmFsIGdjXG4gICAqIGdvYWxzLiBJbiBhZGRpdGlvbiwgYmVjYXVzZSB0aGUgbmFtZSBuZWVkIG5vdCBiZSBhIGd1YXJkZWRcbiAgICogc2VjcmV0LCB3ZSBjb3VsZCBlZmZpY2llbnRseSBoYW5kbGUgY3Jvc3MtZnJhbWUgZnJvemVuIGtleXMuXG4gICAqL1xuICB2YXIgSElEREVOX05BTUVfUFJFRklYID0gJ3dlYWttYXA6JztcbiAgdmFyIEhJRERFTl9OQU1FID0gSElEREVOX05BTUVfUFJFRklYICsgJ2lkZW50OicgKyBNYXRoLnJhbmRvbSgpICsgJ19fXyc7XG5cbiAgaWYgKHR5cGVvZiBjcnlwdG8gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2YgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgICAgdHlwZW9mIEFycmF5QnVmZmVyID09PSAnZnVuY3Rpb24nICYmXG4gICAgICB0eXBlb2YgVWludDhBcnJheSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHZhciBhYiA9IG5ldyBBcnJheUJ1ZmZlcigyNSk7XG4gICAgdmFyIHU4cyA9IG5ldyBVaW50OEFycmF5KGFiKTtcbiAgICBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKHU4cyk7XG4gICAgSElEREVOX05BTUUgPSBISURERU5fTkFNRV9QUkVGSVggKyAncmFuZDonICtcbiAgICAgIEFycmF5LnByb3RvdHlwZS5tYXAuY2FsbCh1OHMsIGZ1bmN0aW9uKHU4KSB7XG4gICAgICAgIHJldHVybiAodTggJSAzNikudG9TdHJpbmcoMzYpO1xuICAgICAgfSkuam9pbignJykgKyAnX19fJztcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzTm90SGlkZGVuTmFtZShuYW1lKSB7XG4gICAgcmV0dXJuICEoXG4gICAgICAgIG5hbWUuc3Vic3RyKDAsIEhJRERFTl9OQU1FX1BSRUZJWC5sZW5ndGgpID09IEhJRERFTl9OQU1FX1BSRUZJWCAmJlxuICAgICAgICBuYW1lLnN1YnN0cihuYW1lLmxlbmd0aCAtIDMpID09PSAnX19fJyk7XG4gIH1cblxuICAvKipcbiAgICogTW9ua2V5IHBhdGNoIGdldE93blByb3BlcnR5TmFtZXMgdG8gYXZvaWQgcmV2ZWFsaW5nIHRoZVxuICAgKiBISURERU5fTkFNRS5cbiAgICpcbiAgICogPHA+VGhlIEVTNS4xIHNwZWMgcmVxdWlyZXMgZWFjaCBuYW1lIHRvIGFwcGVhciBvbmx5IG9uY2UsIGJ1dCBhc1xuICAgKiBvZiB0aGlzIHdyaXRpbmcsIHRoaXMgcmVxdWlyZW1lbnQgaXMgY29udHJvdmVyc2lhbCBmb3IgRVM2LCBzbyB3ZVxuICAgKiBtYWRlIHRoaXMgY29kZSByb2J1c3QgYWdhaW5zdCB0aGlzIGNhc2UuIElmIHRoZSByZXN1bHRpbmcgZXh0cmFcbiAgICogc2VhcmNoIHR1cm5zIG91dCB0byBiZSBleHBlbnNpdmUsIHdlIGNhbiBwcm9iYWJseSByZWxheCB0aGlzIG9uY2VcbiAgICogRVM2IGlzIGFkZXF1YXRlbHkgc3VwcG9ydGVkIG9uIGFsbCBtYWpvciBicm93c2VycywgaWZmIG5vIGJyb3dzZXJcbiAgICogdmVyc2lvbnMgd2Ugc3VwcG9ydCBhdCB0aGF0IHRpbWUgaGF2ZSByZWxheGVkIHRoaXMgY29uc3RyYWludFxuICAgKiB3aXRob3V0IHByb3ZpZGluZyBidWlsdC1pbiBFUzYgV2Vha01hcHMuXG4gICAqL1xuICBkZWZQcm9wKE9iamVjdCwgJ2dldE93blByb3BlcnR5TmFtZXMnLCB7XG4gICAgdmFsdWU6IGZ1bmN0aW9uIGZha2VHZXRPd25Qcm9wZXJ0eU5hbWVzKG9iaikge1xuICAgICAgcmV0dXJuIGdvcG4ob2JqKS5maWx0ZXIoaXNOb3RIaWRkZW5OYW1lKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBnZXRQcm9wZXJ0eU5hbWVzIGlzIG5vdCBpbiBFUzUgYnV0IGl0IGlzIHByb3Bvc2VkIGZvciBFUzYgYW5kXG4gICAqIGRvZXMgYXBwZWFyIGluIG91ciB3aGl0ZWxpc3QsIHNvIHdlIG5lZWQgdG8gY2xlYW4gaXQgdG9vLlxuICAgKi9cbiAgaWYgKCdnZXRQcm9wZXJ0eU5hbWVzJyBpbiBPYmplY3QpIHtcbiAgICB2YXIgb3JpZ2luYWxHZXRQcm9wZXJ0eU5hbWVzID0gT2JqZWN0LmdldFByb3BlcnR5TmFtZXM7XG4gICAgZGVmUHJvcChPYmplY3QsICdnZXRQcm9wZXJ0eU5hbWVzJywge1xuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZha2VHZXRQcm9wZXJ0eU5hbWVzKG9iaikge1xuICAgICAgICByZXR1cm4gb3JpZ2luYWxHZXRQcm9wZXJ0eU5hbWVzKG9iaikuZmlsdGVyKGlzTm90SGlkZGVuTmFtZSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogPHA+VG8gdHJlYXQgb2JqZWN0cyBhcyBpZGVudGl0eS1rZXlzIHdpdGggcmVhc29uYWJsZSBlZmZpY2llbmN5XG4gICAqIG9uIEVTNSBieSBpdHNlbGYgKGkuZS4sIHdpdGhvdXQgYW55IG9iamVjdC1rZXllZCBjb2xsZWN0aW9ucyksIHdlXG4gICAqIG5lZWQgdG8gYWRkIGEgaGlkZGVuIHByb3BlcnR5IHRvIHN1Y2gga2V5IG9iamVjdHMgd2hlbiB3ZVxuICAgKiBjYW4uIFRoaXMgcmFpc2VzIHNldmVyYWwgaXNzdWVzOlxuICAgKiA8dWw+XG4gICAqIDxsaT5BcnJhbmdpbmcgdG8gYWRkIHRoaXMgcHJvcGVydHkgdG8gb2JqZWN0cyBiZWZvcmUgd2UgbG9zZSB0aGVcbiAgICogICAgIGNoYW5jZSwgYW5kXG4gICAqIDxsaT5IaWRpbmcgdGhlIGV4aXN0ZW5jZSBvZiB0aGlzIG5ldyBwcm9wZXJ0eSBmcm9tIG1vc3RcbiAgICogICAgIEphdmFTY3JpcHQgY29kZS5cbiAgICogPGxpPlByZXZlbnRpbmcgPGk+Y2VydGlmaWNhdGlvbiB0aGVmdDwvaT4sIHdoZXJlIG9uZSBvYmplY3QgaXNcbiAgICogICAgIGNyZWF0ZWQgZmFsc2VseSBjbGFpbWluZyB0byBiZSB0aGUga2V5IG9mIGFuIGFzc29jaWF0aW9uXG4gICAqICAgICBhY3R1YWxseSBrZXllZCBieSBhbm90aGVyIG9iamVjdC5cbiAgICogPGxpPlByZXZlbnRpbmcgPGk+dmFsdWUgdGhlZnQ8L2k+LCB3aGVyZSB1bnRydXN0ZWQgY29kZSB3aXRoXG4gICAqICAgICBhY2Nlc3MgdG8gYSBrZXkgb2JqZWN0IGJ1dCBub3QgYSB3ZWFrIG1hcCBuZXZlcnRoZWxlc3NcbiAgICogICAgIG9idGFpbnMgYWNjZXNzIHRvIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhhdCBrZXkgaW4gdGhhdFxuICAgKiAgICAgd2VhayBtYXAuXG4gICAqIDwvdWw+XG4gICAqIFdlIGRvIHNvIGJ5XG4gICAqIDx1bD5cbiAgICogPGxpPk1ha2luZyB0aGUgbmFtZSBvZiB0aGUgaGlkZGVuIHByb3BlcnR5IHVuZ3Vlc3NhYmxlLCBzbyBcIltdXCJcbiAgICogICAgIGluZGV4aW5nLCB3aGljaCB3ZSBjYW5ub3QgaW50ZXJjZXB0LCBjYW5ub3QgYmUgdXNlZCB0byBhY2Nlc3NcbiAgICogICAgIGEgcHJvcGVydHkgd2l0aG91dCBrbm93aW5nIHRoZSBuYW1lLlxuICAgKiA8bGk+TWFraW5nIHRoZSBoaWRkZW4gcHJvcGVydHkgbm9uLWVudW1lcmFibGUsIHNvIHdlIG5lZWQgbm90XG4gICAqICAgICB3b3JyeSBhYm91dCBmb3ItaW4gbG9vcHMgb3Ige0Bjb2RlIE9iamVjdC5rZXlzfSxcbiAgICogPGxpPm1vbmtleSBwYXRjaGluZyB0aG9zZSByZWZsZWN0aXZlIG1ldGhvZHMgdGhhdCB3b3VsZFxuICAgKiAgICAgcHJldmVudCBleHRlbnNpb25zLCB0byBhZGQgdGhpcyBoaWRkZW4gcHJvcGVydHkgZmlyc3QsXG4gICAqIDxsaT5tb25rZXkgcGF0Y2hpbmcgdGhvc2UgbWV0aG9kcyB0aGF0IHdvdWxkIHJldmVhbCB0aGlzXG4gICAqICAgICBoaWRkZW4gcHJvcGVydHkuXG4gICAqIDwvdWw+XG4gICAqIFVuZm9ydHVuYXRlbHksIGJlY2F1c2Ugb2Ygc2FtZS1vcmlnaW4gaWZyYW1lcywgd2UgY2Fubm90IHJlbGlhYmx5XG4gICAqIGFkZCB0aGlzIGhpZGRlbiBwcm9wZXJ0eSBiZWZvcmUgYW4gb2JqZWN0IGJlY29tZXNcbiAgICogbm9uLWV4dGVuc2libGUuIEluc3RlYWQsIGlmIHdlIGVuY291bnRlciBhIG5vbi1leHRlbnNpYmxlIG9iamVjdFxuICAgKiB3aXRob3V0IGEgaGlkZGVuIHJlY29yZCB0aGF0IHdlIGNhbiBkZXRlY3QgKHdoZXRoZXIgb3Igbm90IGl0IGhhc1xuICAgKiBhIGhpZGRlbiByZWNvcmQgc3RvcmVkIHVuZGVyIGEgbmFtZSBzZWNyZXQgdG8gdXMpLCB0aGVuIHdlIGp1c3RcbiAgICogdXNlIHRoZSBrZXkgb2JqZWN0IGl0c2VsZiB0byByZXByZXNlbnQgaXRzIGlkZW50aXR5IGluIGEgYnJ1dGVcbiAgICogZm9yY2UgbGVha3kgbWFwIHN0b3JlZCBpbiB0aGUgd2VhayBtYXAsIGxvc2luZyBhbGwgdGhlIGFkdmFudGFnZXNcbiAgICogb2Ygd2Vha25lc3MgZm9yIHRoZXNlLlxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0SGlkZGVuUmVjb3JkKGtleSkge1xuICAgIGlmIChrZXkgIT09IE9iamVjdChrZXkpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdOb3QgYW4gb2JqZWN0OiAnICsga2V5KTtcbiAgICB9XG4gICAgdmFyIGhpZGRlblJlY29yZCA9IGtleVtISURERU5fTkFNRV07XG4gICAgaWYgKGhpZGRlblJlY29yZCAmJiBoaWRkZW5SZWNvcmQua2V5ID09PSBrZXkpIHsgcmV0dXJuIGhpZGRlblJlY29yZDsgfVxuICAgIGlmICghaXNFeHRlbnNpYmxlKGtleSkpIHtcbiAgICAgIC8vIFdlYWsgbWFwIG11c3QgYnJ1dGUgZm9yY2UsIGFzIGV4cGxhaW5lZCBpbiBkb2MtY29tbWVudCBhYm92ZS5cbiAgICAgIHJldHVybiB2b2lkIDA7XG4gICAgfVxuXG4gICAgLy8gVGhlIGhpZGRlblJlY29yZCBhbmQgdGhlIGtleSBwb2ludCBkaXJlY3RseSBhdCBlYWNoIG90aGVyLCB2aWFcbiAgICAvLyB0aGUgXCJrZXlcIiBhbmQgSElEREVOX05BTUUgcHJvcGVydGllcyByZXNwZWN0aXZlbHkuIFRoZSBrZXlcbiAgICAvLyBmaWVsZCBpcyBmb3IgcXVpY2tseSB2ZXJpZnlpbmcgdGhhdCB0aGlzIGhpZGRlbiByZWNvcmQgaXMgYW5cbiAgICAvLyBvd24gcHJvcGVydHksIG5vdCBhIGhpZGRlbiByZWNvcmQgZnJvbSB1cCB0aGUgcHJvdG90eXBlIGNoYWluLlxuICAgIC8vXG4gICAgLy8gTk9URTogQmVjYXVzZSB0aGlzIFdlYWtNYXAgZW11bGF0aW9uIGlzIG1lYW50IG9ubHkgZm9yIHN5c3RlbXMgbGlrZVxuICAgIC8vIFNFUyB3aGVyZSBPYmplY3QucHJvdG90eXBlIGlzIGZyb3plbiB3aXRob3V0IGFueSBudW1lcmljXG4gICAgLy8gcHJvcGVydGllcywgaXQgaXMgb2sgdG8gdXNlIGFuIG9iamVjdCBsaXRlcmFsIGZvciB0aGUgaGlkZGVuUmVjb3JkLlxuICAgIC8vIFRoaXMgaGFzIHR3byBhZHZhbnRhZ2VzOlxuICAgIC8vICogSXQgaXMgbXVjaCBmYXN0ZXIgaW4gYSBwZXJmb3JtYW5jZSBjcml0aWNhbCBwbGFjZVxuICAgIC8vICogSXQgYXZvaWRzIHJlbHlpbmcgb24gT2JqZWN0LmNyZWF0ZShudWxsKSwgd2hpY2ggaGFkIGJlZW5cbiAgICAvLyAgIHByb2JsZW1hdGljIG9uIENocm9tZSAyOC4wLjE0ODAuMC4gU2VlXG4gICAgLy8gICBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2dvb2dsZS1jYWphL2lzc3Vlcy9kZXRhaWw/aWQ9MTY4N1xuICAgIGhpZGRlblJlY29yZCA9IHsga2V5OiBrZXkgfTtcblxuICAgIC8vIFdoZW4gdXNpbmcgdGhpcyBXZWFrTWFwIGVtdWxhdGlvbiBvbiBwbGF0Zm9ybXMgd2hlcmVcbiAgICAvLyBPYmplY3QucHJvdG90eXBlIG1pZ2h0IG5vdCBiZSBmcm96ZW4gYW5kIE9iamVjdC5jcmVhdGUobnVsbCkgaXNcbiAgICAvLyByZWxpYWJsZSwgdXNlIHRoZSBmb2xsb3dpbmcgdHdvIGNvbW1lbnRlZCBvdXQgbGluZXMgaW5zdGVhZC5cbiAgICAvLyBoaWRkZW5SZWNvcmQgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIC8vIGhpZGRlblJlY29yZC5rZXkgPSBrZXk7XG5cbiAgICAvLyBQbGVhc2UgY29udGFjdCB1cyBpZiB5b3UgbmVlZCB0aGlzIHRvIHdvcmsgb24gcGxhdGZvcm1zIHdoZXJlXG4gICAgLy8gT2JqZWN0LnByb3RvdHlwZSBtaWdodCBub3QgYmUgZnJvemVuIGFuZFxuICAgIC8vIE9iamVjdC5jcmVhdGUobnVsbCkgbWlnaHQgbm90IGJlIHJlbGlhYmxlLlxuXG4gICAgdHJ5IHtcbiAgICAgIGRlZlByb3Aoa2V5LCBISURERU5fTkFNRSwge1xuICAgICAgICB2YWx1ZTogaGlkZGVuUmVjb3JkLFxuICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBoaWRkZW5SZWNvcmQ7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIFVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgaXNFeHRlbnNpYmxlIHNlZW1zIHRvIG1pc3JlcG9ydCB3aGV0aGVyXG4gICAgICAvLyB0aGUgSElEREVOX05BTUUgY2FuIGJlIGRlZmluZWQuXG4gICAgICAvLyBUaGUgY2lyY3Vtc3RhbmNlcyBoYXZlIG5vdCBiZWVuIGlzb2xhdGVkLCBidXQgYXQgbGVhc3QgYWZmZWN0XG4gICAgICAvLyBOb2RlLmpzIHYwLjEwLjI2IG9uIFRyYXZpc0NJIC8gTGludXgsIGJ1dCBub3QgdGhlIHNhbWUgdmVyc2lvbiBvZlxuICAgICAgLy8gTm9kZS5qcyBvbiBPUyBYLlxuICAgICAgcmV0dXJuIHZvaWQgMDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTW9ua2V5IHBhdGNoIG9wZXJhdGlvbnMgdGhhdCB3b3VsZCBtYWtlIHRoZWlyIGFyZ3VtZW50XG4gICAqIG5vbi1leHRlbnNpYmxlLlxuICAgKlxuICAgKiA8cD5UaGUgbW9ua2V5IHBhdGNoZWQgdmVyc2lvbnMgdGhyb3cgYSBUeXBlRXJyb3IgaWYgdGhlaXJcbiAgICogYXJndW1lbnQgaXMgbm90IGFuIG9iamVjdCwgc28gaXQgc2hvdWxkIG9ubHkgYmUgZG9uZSB0byBmdW5jdGlvbnNcbiAgICogdGhhdCBzaG91bGQgdGhyb3cgYSBUeXBlRXJyb3IgYW55d2F5IGlmIHRoZWlyIGFyZ3VtZW50IGlzIG5vdCBhblxuICAgKiBvYmplY3QuXG4gICAqL1xuICAoZnVuY3Rpb24oKXtcbiAgICB2YXIgb2xkRnJlZXplID0gT2JqZWN0LmZyZWV6ZTtcbiAgICBkZWZQcm9wKE9iamVjdCwgJ2ZyZWV6ZScsIHtcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpZGVudGlmeWluZ0ZyZWV6ZShvYmopIHtcbiAgICAgICAgZ2V0SGlkZGVuUmVjb3JkKG9iaik7XG4gICAgICAgIHJldHVybiBvbGRGcmVlemUob2JqKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB2YXIgb2xkU2VhbCA9IE9iamVjdC5zZWFsO1xuICAgIGRlZlByb3AoT2JqZWN0LCAnc2VhbCcsIHtcbiAgICAgIHZhbHVlOiBmdW5jdGlvbiBpZGVudGlmeWluZ1NlYWwob2JqKSB7XG4gICAgICAgIGdldEhpZGRlblJlY29yZChvYmopO1xuICAgICAgICByZXR1cm4gb2xkU2VhbChvYmopO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHZhciBvbGRQcmV2ZW50RXh0ZW5zaW9ucyA9IE9iamVjdC5wcmV2ZW50RXh0ZW5zaW9ucztcbiAgICBkZWZQcm9wKE9iamVjdCwgJ3ByZXZlbnRFeHRlbnNpb25zJywge1xuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGlkZW50aWZ5aW5nUHJldmVudEV4dGVuc2lvbnMob2JqKSB7XG4gICAgICAgIGdldEhpZGRlblJlY29yZChvYmopO1xuICAgICAgICByZXR1cm4gb2xkUHJldmVudEV4dGVuc2lvbnMob2JqKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSkoKTtcblxuICBmdW5jdGlvbiBjb25zdEZ1bmMoZnVuYykge1xuICAgIGZ1bmMucHJvdG90eXBlID0gbnVsbDtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShmdW5jKTtcbiAgfVxuXG4gIHZhciBjYWxsZWRBc0Z1bmN0aW9uV2FybmluZ0RvbmUgPSBmYWxzZTtcbiAgZnVuY3Rpb24gY2FsbGVkQXNGdW5jdGlvbldhcm5pbmcoKSB7XG4gICAgLy8gRnV0dXJlIEVTNiBXZWFrTWFwIGlzIGN1cnJlbnRseSAoMjAxMy0wOS0xMCkgZXhwZWN0ZWQgdG8gcmVqZWN0IFdlYWtNYXAoKVxuICAgIC8vIGJ1dCB3ZSB1c2VkIHRvIHBlcm1pdCBpdCBhbmQgZG8gaXQgb3Vyc2VsdmVzLCBzbyB3YXJuIG9ubHkuXG4gICAgaWYgKCFjYWxsZWRBc0Z1bmN0aW9uV2FybmluZ0RvbmUgJiYgdHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBjYWxsZWRBc0Z1bmN0aW9uV2FybmluZ0RvbmUgPSB0cnVlO1xuICAgICAgY29uc29sZS53YXJuKCdXZWFrTWFwIHNob3VsZCBiZSBpbnZva2VkIGFzIG5ldyBXZWFrTWFwKCksIG5vdCAnICtcbiAgICAgICAgICAnV2Vha01hcCgpLiBUaGlzIHdpbGwgYmUgYW4gZXJyb3IgaW4gdGhlIGZ1dHVyZS4nKTtcbiAgICB9XG4gIH1cblxuICB2YXIgbmV4dElkID0gMDtcblxuICB2YXIgT3VyV2Vha01hcCA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBPdXJXZWFrTWFwKSkgeyAgLy8gYXBwcm94aW1hdGUgdGVzdCBmb3IgbmV3IC4uLigpXG4gICAgICBjYWxsZWRBc0Z1bmN0aW9uV2FybmluZygpO1xuICAgIH1cblxuICAgIC8vIFdlIGFyZSBjdXJyZW50bHkgKDEyLzI1LzIwMTIpIG5ldmVyIGVuY291bnRlcmluZyBhbnkgcHJlbWF0dXJlbHlcbiAgICAvLyBub24tZXh0ZW5zaWJsZSBrZXlzLlxuICAgIHZhciBrZXlzID0gW107IC8vIGJydXRlIGZvcmNlIGZvciBwcmVtYXR1cmVseSBub24tZXh0ZW5zaWJsZSBrZXlzLlxuICAgIHZhciB2YWx1ZXMgPSBbXTsgLy8gYnJ1dGUgZm9yY2UgZm9yIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICAgIHZhciBpZCA9IG5leHRJZCsrO1xuXG4gICAgZnVuY3Rpb24gZ2V0X19fKGtleSwgb3B0X2RlZmF1bHQpIHtcbiAgICAgIHZhciBpbmRleDtcbiAgICAgIHZhciBoaWRkZW5SZWNvcmQgPSBnZXRIaWRkZW5SZWNvcmQoa2V5KTtcbiAgICAgIGlmIChoaWRkZW5SZWNvcmQpIHtcbiAgICAgICAgcmV0dXJuIGlkIGluIGhpZGRlblJlY29yZCA/IGhpZGRlblJlY29yZFtpZF0gOiBvcHRfZGVmYXVsdDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGluZGV4ID0ga2V5cy5pbmRleE9mKGtleSk7XG4gICAgICAgIHJldHVybiBpbmRleCA+PSAwID8gdmFsdWVzW2luZGV4XSA6IG9wdF9kZWZhdWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhc19fXyhrZXkpIHtcbiAgICAgIHZhciBoaWRkZW5SZWNvcmQgPSBnZXRIaWRkZW5SZWNvcmQoa2V5KTtcbiAgICAgIGlmIChoaWRkZW5SZWNvcmQpIHtcbiAgICAgICAgcmV0dXJuIGlkIGluIGhpZGRlblJlY29yZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBrZXlzLmluZGV4T2Yoa2V5KSA+PSAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldF9fXyhrZXksIHZhbHVlKSB7XG4gICAgICB2YXIgaW5kZXg7XG4gICAgICB2YXIgaGlkZGVuUmVjb3JkID0gZ2V0SGlkZGVuUmVjb3JkKGtleSk7XG4gICAgICBpZiAoaGlkZGVuUmVjb3JkKSB7XG4gICAgICAgIGhpZGRlblJlY29yZFtpZF0gPSB2YWx1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGluZGV4ID0ga2V5cy5pbmRleE9mKGtleSk7XG4gICAgICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICAgICAgdmFsdWVzW2luZGV4XSA9IHZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIFNpbmNlIHNvbWUgYnJvd3NlcnMgcHJlZW1wdGl2ZWx5IHRlcm1pbmF0ZSBzbG93IHR1cm5zIGJ1dFxuICAgICAgICAgIC8vIHRoZW4gY29udGludWUgY29tcHV0aW5nIHdpdGggcHJlc3VtYWJseSBjb3JydXB0ZWQgaGVhcFxuICAgICAgICAgIC8vIHN0YXRlLCB3ZSBoZXJlIGRlZmVuc2l2ZWx5IGdldCBrZXlzLmxlbmd0aCBmaXJzdCBhbmQgdGhlblxuICAgICAgICAgIC8vIHVzZSBpdCB0byB1cGRhdGUgYm90aCB0aGUgdmFsdWVzIGFuZCBrZXlzIGFycmF5cywga2VlcGluZ1xuICAgICAgICAgIC8vIHRoZW0gaW4gc3luYy5cbiAgICAgICAgICBpbmRleCA9IGtleXMubGVuZ3RoO1xuICAgICAgICAgIHZhbHVlc1tpbmRleF0gPSB2YWx1ZTtcbiAgICAgICAgICAvLyBJZiB3ZSBjcmFzaCBoZXJlLCB2YWx1ZXMgd2lsbCBiZSBvbmUgbG9uZ2VyIHRoYW4ga2V5cy5cbiAgICAgICAgICBrZXlzW2luZGV4XSA9IGtleTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGVsZXRlX19fKGtleSkge1xuICAgICAgdmFyIGhpZGRlblJlY29yZCA9IGdldEhpZGRlblJlY29yZChrZXkpO1xuICAgICAgdmFyIGluZGV4LCBsYXN0SW5kZXg7XG4gICAgICBpZiAoaGlkZGVuUmVjb3JkKSB7XG4gICAgICAgIHJldHVybiBpZCBpbiBoaWRkZW5SZWNvcmQgJiYgZGVsZXRlIGhpZGRlblJlY29yZFtpZF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbmRleCA9IGtleXMuaW5kZXhPZihrZXkpO1xuICAgICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNpbmNlIHNvbWUgYnJvd3NlcnMgcHJlZW1wdGl2ZWx5IHRlcm1pbmF0ZSBzbG93IHR1cm5zIGJ1dFxuICAgICAgICAvLyB0aGVuIGNvbnRpbnVlIGNvbXB1dGluZyB3aXRoIHBvdGVudGlhbGx5IGNvcnJ1cHRlZCBoZWFwXG4gICAgICAgIC8vIHN0YXRlLCB3ZSBoZXJlIGRlZmVuc2l2ZWx5IGdldCBrZXlzLmxlbmd0aCBmaXJzdCBhbmQgdGhlbiB1c2VcbiAgICAgICAgLy8gaXQgdG8gdXBkYXRlIGJvdGggdGhlIGtleXMgYW5kIHRoZSB2YWx1ZXMgYXJyYXksIGtlZXBpbmdcbiAgICAgICAgLy8gdGhlbSBpbiBzeW5jLiBXZSB1cGRhdGUgdGhlIHR3byB3aXRoIGFuIG9yZGVyIG9mIGFzc2lnbm1lbnRzLFxuICAgICAgICAvLyBzdWNoIHRoYXQgYW55IHByZWZpeCBvZiB0aGVzZSBhc3NpZ25tZW50cyB3aWxsIHByZXNlcnZlIHRoZVxuICAgICAgICAvLyBrZXkvdmFsdWUgY29ycmVzcG9uZGVuY2UsIGVpdGhlciBiZWZvcmUgb3IgYWZ0ZXIgdGhlIGRlbGV0ZS5cbiAgICAgICAgLy8gTm90ZSB0aGF0IHRoaXMgbmVlZHMgdG8gd29yayBjb3JyZWN0bHkgd2hlbiBpbmRleCA9PT0gbGFzdEluZGV4LlxuICAgICAgICBsYXN0SW5kZXggPSBrZXlzLmxlbmd0aCAtIDE7XG4gICAgICAgIGtleXNbaW5kZXhdID0gdm9pZCAwO1xuICAgICAgICAvLyBJZiB3ZSBjcmFzaCBoZXJlLCB0aGVyZSdzIGEgdm9pZCAwIGluIHRoZSBrZXlzIGFycmF5LCBidXRcbiAgICAgICAgLy8gbm8gb3BlcmF0aW9uIHdpbGwgY2F1c2UgYSBcImtleXMuaW5kZXhPZih2b2lkIDApXCIsIHNpbmNlXG4gICAgICAgIC8vIGdldEhpZGRlblJlY29yZCh2b2lkIDApIHdpbGwgYWx3YXlzIHRocm93IGFuIGVycm9yIGZpcnN0LlxuICAgICAgICB2YWx1ZXNbaW5kZXhdID0gdmFsdWVzW2xhc3RJbmRleF07XG4gICAgICAgIC8vIElmIHdlIGNyYXNoIGhlcmUsIHZhbHVlc1tpbmRleF0gY2Fubm90IGJlIGZvdW5kIGhlcmUsXG4gICAgICAgIC8vIGJlY2F1c2Uga2V5c1tpbmRleF0gaXMgdm9pZCAwLlxuICAgICAgICBrZXlzW2luZGV4XSA9IGtleXNbbGFzdEluZGV4XTtcbiAgICAgICAgLy8gSWYgaW5kZXggPT09IGxhc3RJbmRleCBhbmQgd2UgY3Jhc2ggaGVyZSwgdGhlbiBrZXlzW2luZGV4XVxuICAgICAgICAvLyBpcyBzdGlsbCB2b2lkIDAsIHNpbmNlIHRoZSBhbGlhc2luZyBraWxsZWQgdGhlIHByZXZpb3VzIGtleS5cbiAgICAgICAga2V5cy5sZW5ndGggPSBsYXN0SW5kZXg7XG4gICAgICAgIC8vIElmIHdlIGNyYXNoIGhlcmUsIGtleXMgd2lsbCBiZSBvbmUgc2hvcnRlciB0aGFuIHZhbHVlcy5cbiAgICAgICAgdmFsdWVzLmxlbmd0aCA9IGxhc3RJbmRleDtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5jcmVhdGUoT3VyV2Vha01hcC5wcm90b3R5cGUsIHtcbiAgICAgIGdldF9fXzogICAgeyB2YWx1ZTogY29uc3RGdW5jKGdldF9fXykgfSxcbiAgICAgIGhhc19fXzogICAgeyB2YWx1ZTogY29uc3RGdW5jKGhhc19fXykgfSxcbiAgICAgIHNldF9fXzogICAgeyB2YWx1ZTogY29uc3RGdW5jKHNldF9fXykgfSxcbiAgICAgIGRlbGV0ZV9fXzogeyB2YWx1ZTogY29uc3RGdW5jKGRlbGV0ZV9fXykgfVxuICAgIH0pO1xuICB9O1xuXG4gIE91cldlYWtNYXAucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShPYmplY3QucHJvdG90eXBlLCB7XG4gICAgZ2V0OiB7XG4gICAgICAvKipcbiAgICAgICAqIFJldHVybiB0aGUgdmFsdWUgbW9zdCByZWNlbnRseSBhc3NvY2lhdGVkIHdpdGgga2V5LCBvclxuICAgICAgICogb3B0X2RlZmF1bHQgaWYgbm9uZS5cbiAgICAgICAqL1xuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldChrZXksIG9wdF9kZWZhdWx0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldF9fXyhrZXksIG9wdF9kZWZhdWx0KTtcbiAgICAgIH0sXG4gICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0sXG5cbiAgICBoYXM6IHtcbiAgICAgIC8qKlxuICAgICAgICogSXMgdGhlcmUgYSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGgga2V5IGluIHRoaXMgV2Vha01hcD9cbiAgICAgICAqL1xuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGhhcyhrZXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFzX19fKGtleSk7XG4gICAgICB9LFxuICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICB9LFxuXG4gICAgc2V0OiB7XG4gICAgICAvKipcbiAgICAgICAqIEFzc29jaWF0ZSB2YWx1ZSB3aXRoIGtleSBpbiB0aGlzIFdlYWtNYXAsIG92ZXJ3cml0aW5nIGFueVxuICAgICAgICogcHJldmlvdXMgYXNzb2NpYXRpb24gaWYgcHJlc2VudC5cbiAgICAgICAqL1xuICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNldChrZXksIHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNldF9fXyhrZXksIHZhbHVlKTtcbiAgICAgIH0sXG4gICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0sXG5cbiAgICAnZGVsZXRlJzoge1xuICAgICAgLyoqXG4gICAgICAgKiBSZW1vdmUgYW55IGFzc29jaWF0aW9uIGZvciBrZXkgaW4gdGhpcyBXZWFrTWFwLCByZXR1cm5pbmdcbiAgICAgICAqIHdoZXRoZXIgdGhlcmUgd2FzIG9uZS5cbiAgICAgICAqXG4gICAgICAgKiA8cD5Ob3RlIHRoYXQgdGhlIGJvb2xlYW4gcmV0dXJuIGhlcmUgZG9lcyBub3Qgd29yayBsaWtlIHRoZVxuICAgICAgICoge0Bjb2RlIGRlbGV0ZX0gb3BlcmF0b3IuIFRoZSB7QGNvZGUgZGVsZXRlfSBvcGVyYXRvciByZXR1cm5zXG4gICAgICAgKiB3aGV0aGVyIHRoZSBkZWxldGlvbiBzdWNjZWVkcyBhdCBicmluZ2luZyBhYm91dCBhIHN0YXRlIGluXG4gICAgICAgKiB3aGljaCB0aGUgZGVsZXRlZCBwcm9wZXJ0eSBpcyBhYnNlbnQuIFRoZSB7QGNvZGUgZGVsZXRlfVxuICAgICAgICogb3BlcmF0b3IgdGhlcmVmb3JlIHJldHVybnMgdHJ1ZSBpZiB0aGUgcHJvcGVydHkgd2FzIGFscmVhZHlcbiAgICAgICAqIGFic2VudCwgd2hlcmVhcyB0aGlzIHtAY29kZSBkZWxldGV9IG1ldGhvZCByZXR1cm5zIGZhbHNlIGlmXG4gICAgICAgKiB0aGUgYXNzb2NpYXRpb24gd2FzIGFscmVhZHkgYWJzZW50LlxuICAgICAgICovXG4gICAgICB2YWx1ZTogZnVuY3Rpb24gcmVtb3ZlKGtleSkge1xuICAgICAgICByZXR1cm4gdGhpcy5kZWxldGVfX18oa2V5KTtcbiAgICAgIH0sXG4gICAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH1cbiAgfSk7XG5cbiAgaWYgKHR5cGVvZiBIb3N0V2Vha01hcCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIChmdW5jdGlvbigpIHtcbiAgICAgIC8vIElmIHdlIGdvdCBoZXJlLCB0aGVuIHRoZSBwbGF0Zm9ybSBoYXMgYSBXZWFrTWFwIGJ1dCB3ZSBhcmUgY29uY2VybmVkXG4gICAgICAvLyB0aGF0IGl0IG1heSByZWZ1c2UgdG8gc3RvcmUgc29tZSBrZXkgdHlwZXMuIFRoZXJlZm9yZSwgbWFrZSBhIG1hcFxuICAgICAgLy8gaW1wbGVtZW50YXRpb24gd2hpY2ggbWFrZXMgdXNlIG9mIGJvdGggYXMgcG9zc2libGUuXG5cbiAgICAgIC8vIEluIHRoaXMgbW9kZSB3ZSBhcmUgYWx3YXlzIHVzaW5nIGRvdWJsZSBtYXBzLCBzbyB3ZSBhcmUgbm90IHByb3h5LXNhZmUuXG4gICAgICAvLyBUaGlzIGNvbWJpbmF0aW9uIGRvZXMgbm90IG9jY3VyIGluIGFueSBrbm93biBicm93c2VyLCBidXQgd2UgaGFkIGJlc3RcbiAgICAgIC8vIGJlIHNhZmUuXG4gICAgICBpZiAoZG91YmxlV2Vha01hcENoZWNrU2lsZW50RmFpbHVyZSAmJiB0eXBlb2YgUHJveHkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIFByb3h5ID0gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBEb3VibGVXZWFrTWFwKCkge1xuICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgT3VyV2Vha01hcCkpIHsgIC8vIGFwcHJveGltYXRlIHRlc3QgZm9yIG5ldyAuLi4oKVxuICAgICAgICAgIGNhbGxlZEFzRnVuY3Rpb25XYXJuaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcmVmZXJhYmxlLCB0cnVseSB3ZWFrIG1hcC5cbiAgICAgICAgdmFyIGhtYXAgPSBuZXcgSG9zdFdlYWtNYXAoKTtcblxuICAgICAgICAvLyBPdXIgaGlkZGVuLXByb3BlcnR5LWJhc2VkIHBzZXVkby13ZWFrLW1hcC4gTGF6aWx5IGluaXRpYWxpemVkIGluIHRoZVxuICAgICAgICAvLyAnc2V0JyBpbXBsZW1lbnRhdGlvbjsgdGh1cyB3ZSBjYW4gYXZvaWQgcGVyZm9ybWluZyBleHRyYSBsb29rdXBzIGlmXG4gICAgICAgIC8vIHdlIGtub3cgYWxsIGVudHJpZXMgYWN0dWFsbHkgc3RvcmVkIGFyZSBlbnRlcmVkIGluICdobWFwJy5cbiAgICAgICAgdmFyIG9tYXAgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgLy8gSGlkZGVuLXByb3BlcnR5IG1hcHMgYXJlIG5vdCBjb21wYXRpYmxlIHdpdGggcHJveGllcyBiZWNhdXNlIHByb3hpZXNcbiAgICAgICAgLy8gY2FuIG9ic2VydmUgdGhlIGhpZGRlbiBuYW1lIGFuZCBlaXRoZXIgYWNjaWRlbnRhbGx5IGV4cG9zZSBpdCBvciBmYWlsXG4gICAgICAgIC8vIHRvIGFsbG93IHRoZSBoaWRkZW4gcHJvcGVydHkgdG8gYmUgc2V0LiBUaGVyZWZvcmUsIHdlIGRvIG5vdCBhbGxvd1xuICAgICAgICAvLyBhcmJpdHJhcnkgV2Vha01hcHMgdG8gc3dpdGNoIHRvIHVzaW5nIGhpZGRlbiBwcm9wZXJ0aWVzLCBidXQgb25seVxuICAgICAgICAvLyB0aG9zZSB3aGljaCBuZWVkIHRoZSBhYmlsaXR5LCBhbmQgdW5wcml2aWxlZ2VkIGNvZGUgaXMgbm90IGFsbG93ZWRcbiAgICAgICAgLy8gdG8gc2V0IHRoZSBmbGFnLlxuICAgICAgICAvL1xuICAgICAgICAvLyAoRXhjZXB0IGluIGRvdWJsZVdlYWtNYXBDaGVja1NpbGVudEZhaWx1cmUgbW9kZSBpbiB3aGljaCBjYXNlIHdlXG4gICAgICAgIC8vIGRpc2FibGUgcHJveGllcy4pXG4gICAgICAgIHZhciBlbmFibGVTd2l0Y2hpbmcgPSBmYWxzZTtcblxuICAgICAgICBmdW5jdGlvbiBkZ2V0KGtleSwgb3B0X2RlZmF1bHQpIHtcbiAgICAgICAgICBpZiAob21hcCkge1xuICAgICAgICAgICAgcmV0dXJuIGhtYXAuaGFzKGtleSkgPyBobWFwLmdldChrZXkpXG4gICAgICAgICAgICAgICAgOiBvbWFwLmdldF9fXyhrZXksIG9wdF9kZWZhdWx0KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGhtYXAuZ2V0KGtleSwgb3B0X2RlZmF1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGRoYXMoa2V5KSB7XG4gICAgICAgICAgcmV0dXJuIGhtYXAuaGFzKGtleSkgfHwgKG9tYXAgPyBvbWFwLmhhc19fXyhrZXkpIDogZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGRzZXQ7XG4gICAgICAgIGlmIChkb3VibGVXZWFrTWFwQ2hlY2tTaWxlbnRGYWlsdXJlKSB7XG4gICAgICAgICAgZHNldCA9IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgIGhtYXAuc2V0KGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgaWYgKCFobWFwLmhhcyhrZXkpKSB7XG4gICAgICAgICAgICAgIGlmICghb21hcCkgeyBvbWFwID0gbmV3IE91cldlYWtNYXAoKTsgfVxuICAgICAgICAgICAgICBvbWFwLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZHNldCA9IGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgIGlmIChlbmFibGVTd2l0Y2hpbmcpIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBobWFwLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGlmICghb21hcCkgeyBvbWFwID0gbmV3IE91cldlYWtNYXAoKTsgfVxuICAgICAgICAgICAgICAgIG9tYXAuc2V0X19fKGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBobWFwLnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBkZGVsZXRlKGtleSkge1xuICAgICAgICAgIHZhciByZXN1bHQgPSAhIWhtYXBbJ2RlbGV0ZSddKGtleSk7XG4gICAgICAgICAgaWYgKG9tYXApIHsgcmV0dXJuIG9tYXAuZGVsZXRlX19fKGtleSkgfHwgcmVzdWx0OyB9XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBPYmplY3QuY3JlYXRlKE91cldlYWtNYXAucHJvdG90eXBlLCB7XG4gICAgICAgICAgZ2V0X19fOiAgICB7IHZhbHVlOiBjb25zdEZ1bmMoZGdldCkgfSxcbiAgICAgICAgICBoYXNfX186ICAgIHsgdmFsdWU6IGNvbnN0RnVuYyhkaGFzKSB9LFxuICAgICAgICAgIHNldF9fXzogICAgeyB2YWx1ZTogY29uc3RGdW5jKGRzZXQpIH0sXG4gICAgICAgICAgZGVsZXRlX19fOiB7IHZhbHVlOiBjb25zdEZ1bmMoZGRlbGV0ZSkgfSxcbiAgICAgICAgICBwZXJtaXRIb3N0T2JqZWN0c19fXzogeyB2YWx1ZTogY29uc3RGdW5jKGZ1bmN0aW9uKHRva2VuKSB7XG4gICAgICAgICAgICBpZiAodG9rZW4gPT09IHdlYWtNYXBQZXJtaXRIb3N0T2JqZWN0cykge1xuICAgICAgICAgICAgICBlbmFibGVTd2l0Y2hpbmcgPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdib2d1cyBjYWxsIHRvIHBlcm1pdEhvc3RPYmplY3RzX19fJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSl9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgRG91YmxlV2Vha01hcC5wcm90b3R5cGUgPSBPdXJXZWFrTWFwLnByb3RvdHlwZTtcbiAgICAgIG1vZHVsZS5leHBvcnRzID0gRG91YmxlV2Vha01hcDtcblxuICAgICAgLy8gZGVmaW5lIC5jb25zdHJ1Y3RvciB0byBoaWRlIE91cldlYWtNYXAgY3RvclxuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFdlYWtNYXAucHJvdG90eXBlLCAnY29uc3RydWN0b3InLCB7XG4gICAgICAgIHZhbHVlOiBXZWFrTWFwLFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSwgIC8vIGFzIGRlZmF1bHQgLmNvbnN0cnVjdG9yIGlzXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWVcbiAgICAgIH0pO1xuICAgIH0pKCk7XG4gIH0gZWxzZSB7XG4gICAgLy8gVGhlcmUgaXMgbm8gaG9zdCBXZWFrTWFwLCBzbyB3ZSBtdXN0IHVzZSB0aGUgZW11bGF0aW9uLlxuXG4gICAgLy8gRW11bGF0ZWQgV2Vha01hcHMgYXJlIGluY29tcGF0aWJsZSB3aXRoIG5hdGl2ZSBwcm94aWVzIChiZWNhdXNlIHByb3hpZXNcbiAgICAvLyBjYW4gb2JzZXJ2ZSB0aGUgaGlkZGVuIG5hbWUpLCBzbyB3ZSBtdXN0IGRpc2FibGUgUHJveHkgdXNhZ2UgKGluXG4gICAgLy8gQXJyYXlMaWtlIGFuZCBEb21hZG8sIGN1cnJlbnRseSkuXG4gICAgaWYgKHR5cGVvZiBQcm94eSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIFByb3h5ID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIG1vZHVsZS5leHBvcnRzID0gT3VyV2Vha01hcDtcbiAgfVxufSkoKTtcblxufSx7fV0sNTUzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbnZhciBoaWRkZW5TdG9yZSA9IF9kZXJlcV8oJy4vaGlkZGVuLXN0b3JlLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU3RvcmU7XG5cbmZ1bmN0aW9uIGNyZWF0ZVN0b3JlKCkge1xuICAgIHZhciBrZXkgPSB7fTtcblxuICAgIHJldHVybiBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgIGlmICgodHlwZW9mIG9iaiAhPT0gJ29iamVjdCcgfHwgb2JqID09PSBudWxsKSAmJlxuICAgICAgICAgICAgdHlwZW9mIG9iaiAhPT0gJ2Z1bmN0aW9uJ1xuICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignV2Vha21hcC1zaGltOiBLZXkgbXVzdCBiZSBvYmplY3QnKVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHN0b3JlID0gb2JqLnZhbHVlT2Yoa2V5KTtcbiAgICAgICAgcmV0dXJuIHN0b3JlICYmIHN0b3JlLmlkZW50aXR5ID09PSBrZXkgP1xuICAgICAgICAgICAgc3RvcmUgOiBoaWRkZW5TdG9yZShvYmosIGtleSk7XG4gICAgfTtcbn1cblxufSx7XCIuL2hpZGRlbi1zdG9yZS5qc1wiOjU1NH1dLDU1NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5tb2R1bGUuZXhwb3J0cyA9IGhpZGRlblN0b3JlO1xuXG5mdW5jdGlvbiBoaWRkZW5TdG9yZShvYmosIGtleSkge1xuICAgIHZhciBzdG9yZSA9IHsgaWRlbnRpdHk6IGtleSB9O1xuICAgIHZhciB2YWx1ZU9mID0gb2JqLnZhbHVlT2Y7XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBcInZhbHVlT2ZcIiwge1xuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUgIT09IGtleSA/XG4gICAgICAgICAgICAgICAgdmFsdWVPZi5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogc3RvcmU7XG4gICAgICAgIH0sXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgfSk7XG5cbiAgICByZXR1cm4gc3RvcmU7XG59XG5cbn0se31dLDU1NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vLyBPcmlnaW5hbCAtIEBHb3pvbGEuXG4vLyBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9Hb3phbGEvMTI2OTk5MVxuLy8gVGhpcyBpcyBhIHJlaW1wbGVtZW50ZWQgdmVyc2lvbiAod2l0aCBhIGZldyBidWcgZml4ZXMpLlxuXG52YXIgY3JlYXRlU3RvcmUgPSBfZGVyZXFfKCcuL2NyZWF0ZS1zdG9yZS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHdlYWtNYXA7XG5cbmZ1bmN0aW9uIHdlYWtNYXAoKSB7XG4gICAgdmFyIHByaXZhdGVzID0gY3JlYXRlU3RvcmUoKTtcblxuICAgIHJldHVybiB7XG4gICAgICAgICdnZXQnOiBmdW5jdGlvbiAoa2V5LCBmYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHN0b3JlID0gcHJpdmF0ZXMoa2V5KVxuICAgICAgICAgICAgcmV0dXJuIHN0b3JlLmhhc093blByb3BlcnR5KCd2YWx1ZScpID9cbiAgICAgICAgICAgICAgICBzdG9yZS52YWx1ZSA6IGZhbGxiYWNrXG4gICAgICAgIH0sXG4gICAgICAgICdzZXQnOiBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgcHJpdmF0ZXMoa2V5KS52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG4gICAgICAgICdoYXMnOiBmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiAndmFsdWUnIGluIHByaXZhdGVzKGtleSk7XG4gICAgICAgIH0sXG4gICAgICAgICdkZWxldGUnOiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gZGVsZXRlIHByaXZhdGVzKGtleSkudmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbn0se1wiLi9jcmVhdGUtc3RvcmUuanNcIjo1NTN9XSw1NTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xudmFyIGdldENvbnRleHQgPSBfZGVyZXFfKCdnZXQtY2FudmFzLWNvbnRleHQnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdldFdlYkdMQ29udGV4dCAob3B0KSB7XG4gIHJldHVybiBnZXRDb250ZXh0KCd3ZWJnbCcsIG9wdClcbn1cblxufSx7XCJnZXQtY2FudmFzLWNvbnRleHRcIjoyMzJ9XSw1NTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBUcmFkaXRpb25hbCBDaGluZXNlIGNhbGVuZGFyIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBOaWNvbGFzIFJpZXNjbyAoZW5xdWlyaWVzQG5pY29sYXNyaWVzY28ubmV0KSBEZWNlbWJlciAyMDE2LlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IF9kZXJlcV8oJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJyk7XG5cblxudmFyIGdyZWdvcmlhbkNhbGVuZGFyID0gbWFpbi5pbnN0YW5jZSgpO1xuXG4vKiogSW1wbGVtZW50YXRpb24gb2YgdGhlIHRyYWRpdGlvbmFsIENoaW5lc2UgY2FsZW5kYXIuXG4gICAgU291cmNlIG9mIGNhbGVuZGFyIHRhYmxlcyBodHRwczovL2dpdGh1Yi5jb20vaXNlZTE1L0x1bmFyLVNvbGFyLUNhbGVuZGFyLUNvbnZlcnRlciAuXG4gICAgQGNsYXNzIENoaW5lc2VDYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBDaGluZXNlQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuQ2hpbmVzZUNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKENoaW5lc2VDYWxlbmRhci5wcm90b3R5cGUsIHtcbiAgICAvKiogVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnQ2hpbmVzZScsXG4gICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBHcmVnb3JpYW4gZXBvY2g6IDEgSmFudWFyeSAwMDAxIENFLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXIgKi9cbiAgICBqZEVwb2NoOiAxNzIxNDI1LjUsXG4gICAgLyoqIDxjb2RlPnRydWU8L2NvZGU+IGlmIGhhcyBhIHllYXIgemVybywgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBUaGlzIGNhbGVuZGFyIHVzZXMgbW9udGggaW5kaWNlcyB0byBhY2NvdW50IGZvciBpbnRlcmNhbGFyeSBtb250aHMuIFxuICAgICAgICBAbWVtYmVyb2YgQ2hpbmVzZUNhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDAsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgVGhpcyBjYWxlbmRhciB1c2VzIG1vbnRoIGluZGljZXMgdG8gYWNjb3VudCBmb3IgaW50ZXJjYWxhcnkgbW9udGhzLiBcbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhciAqL1xuICAgIGZpcnN0TW9udGg6IDAsXG4gICAgLyoqIFRoZSBtaW5pbXVtIGRheSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnQ2hpbmVzZScsXG4gICAgICAgICAgICBlcG9jaHM6IFsnQkVDJywgJ0VDJ10sXG4gICAgICAgICAgICBtb250aE51bWJlcnM6IGZ1bmN0aW9uKGRhdGUsIHBhZGRlZCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gZGF0ZS5tYXRjaChNT05USF9OVU1CRVJfUkVHRVhQKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChtYXRjaCkgPyBtYXRjaFswXSA6ICcnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKGRhdGUpO1xuICAgICAgICAgICAgICAgIHZhciBtb250aEluZGV4ID0gZGF0ZS5tb250aCgpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1vbnRoID0gJycgKyB0aGlzLnRvQ2hpbmVzZU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhZGRlZCAmJiBtb250aC5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoID0gXCIwXCIgKyBtb250aDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0ludGVyY2FsYXJ5TW9udGgoeWVhciwgbW9udGhJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9udGggKz0gJ2knO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBtb250aDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2ggPSBkYXRlLm1hdGNoKE1PTlRIX05BTUVfUkVHRVhQKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChtYXRjaCkgPyBtYXRjaFswXSA6ICcnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKGRhdGUpO1xuICAgICAgICAgICAgICAgIHZhciBtb250aEluZGV4ID0gZGF0ZS5tb250aCgpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1vbnRoID0gdGhpcy50b0NoaW5lc2VNb250aCh5ZWFyLCBtb250aEluZGV4KTtcblxuICAgICAgICAgICAgICAgIHZhciBtb250aE5hbWUgPSBbJ+S4gOaciCcsJ+S6jOaciCcsJ+S4ieaciCcsJ+Wbm+aciCcsJ+S6lOaciCcsJ+WFreaciCcsXG4gICAgICAgICAgICAgICAgICAgICfkuIPmnIgnLCflhavmnIgnLCfkuZ3mnIgnLCfljYHmnIgnLCfljYHkuIDmnIgnLCfljYHkuozmnIgnXVttb250aCAtIDFdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNJbnRlcmNhbGFyeU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZSA9ICfpl7AnICsgbW9udGhOYW1lO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBtb250aE5hbWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2ggPSBkYXRlLm1hdGNoKE1PTlRIX1NIT1JUX05BTUVfUkVHRVhQKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChtYXRjaCkgPyBtYXRjaFswXSA6ICcnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKGRhdGUpO1xuICAgICAgICAgICAgICAgIHZhciBtb250aEluZGV4ID0gZGF0ZS5tb250aCgpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1vbnRoID0gdGhpcy50b0NoaW5lc2VNb250aCh5ZWFyLCBtb250aEluZGV4KTtcblxuICAgICAgICAgICAgICAgIHZhciBtb250aE5hbWUgPSBbJ+S4gCcsJ+S6jCcsJ+S4iScsJ+WbmycsJ+S6lCcsJ+WFrScsXG4gICAgICAgICAgICAgICAgICAgICfkuIMnLCflhasnLCfkuZ0nLCfljYEnLCfljYHkuIAnLCfljYHkuownXVttb250aCAtIDFdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNJbnRlcmNhbGFyeU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZSA9ICfpl7AnICsgbW9udGhOYW1lO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBtb250aE5hbWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGFyc2VNb250aDogZnVuY3Rpb24oeWVhciwgbW9udGhTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKHllYXIpO1xuICAgICAgICAgICAgICAgIHZhciBtb250aCA9IHBhcnNlSW50KG1vbnRoU3RyaW5nKTtcbiAgICAgICAgICAgICAgICB2YXIgaXNJbnRlcmNhbGFyeTtcblxuICAgICAgICAgICAgICAgIGlmICghaXNOYU4obW9udGgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpID0gbW9udGhTdHJpbmdbbW9udGhTdHJpbmcubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgICAgIGlzSW50ZXJjYWxhcnkgPSAoaSA9PT0gJ2knIHx8IGkgPT09ICdJJyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1vbnRoU3RyaW5nWzBdID09PSAn6ZewJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNJbnRlcmNhbGFyeSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb250aFN0cmluZyA9IG1vbnRoU3RyaW5nLnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobW9udGhTdHJpbmdbbW9udGhTdHJpbmcubGVuZ3RoIC0gMV0gPT09ICfmnIgnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb250aFN0cmluZyA9IG1vbnRoU3RyaW5nLnN1YnN0cmluZygwLCBtb250aFN0cmluZy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBtb250aCA9IDEgK1xuICAgICAgICAgICAgICAgICAgICAgICAgWyfkuIAnLCfkuownLCfkuIknLCflm5snLCfkupQnLCflha0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ+S4gycsJ+WFqycsJ+S5nScsJ+WNgScsJ+WNgeS4gCcsJ+WNgeS6jCddLmluZGV4T2YobW9udGhTdHJpbmcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtb250aEluZGV4ID0gdGhpcy50b01vbnRoSW5kZXgoeWVhciwgbW9udGgsIGlzSW50ZXJjYWxhcnkpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aEluZGV4O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRheU5hbWVzOiBbJ1N1bmRheScsICdNb25kYXknLCAnVHVlc2RheScsICdXZWRuZXNkYXknLCAnVGh1cnNkYXknLCAnRnJpZGF5JywgJ1NhdHVyZGF5J10sXG4gICAgICAgICAgICBkYXlOYW1lc1Nob3J0OiBbJ1N1bicsICdNb24nLCAnVHVlJywgJ1dlZCcsICdUaHUnLCAnRnJpJywgJ1NhdCddLFxuICAgICAgICAgICAgZGF5TmFtZXNNaW46IFsnU3UnLCAnTW8nLCAnVHUnLCAnV2UnLCAnVGgnLCAnRnInLCAnU2EnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICd5eXl5L21tL2RkJyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiAxLFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIENoZWNrIHRoYXQgYSBjYW5kaWRhdGUgZGF0ZSBpcyBmcm9tIHRoZSBzYW1lIGNhbGVuZGFyIGFuZCBpcyB2YWxpZC5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcHJpdmF0ZVxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSBvciB0aGUgeWVhciB0byB2YWxpZGF0ZS5cbiAgICAgICAgQHBhcmFtIGVycm9yIHtzdHJpbmd9IEVycm9yIG1lc3NhZ2UgaWYgaW52YWxpZC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiB5ZWFyIG91dCBvZiByYW5nZS4gKi9cbiAgICBfdmFsaWRhdGVZZWFyOiBmdW5jdGlvbih5ZWFyLCBlcnJvcikge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHllYXIgIT09ICdudW1iZXInIHx8IHllYXIgPCAxODg4IHx8IHllYXIgPiAyMTExKSB7XG4gICAgICAgICAgICB0aHJvdyBlcnJvci5yZXBsYWNlKC9cXHswXFx9LywgdGhpcy5sb2NhbC5uYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB5ZWFyO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG1vbnRoIGluZGV4IChpLmUuIGFjY291bnRpbmcgZm9yIGludGVyY2FsYXJ5IG1vbnRocykuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIHllYXIuXG4gICAgICAgIEBwYXJhbSBtb250aCB7bnVtYmVyfSBUaGUgbW9udGggKDEgZm9yIGZpcnN0IG1vbnRoKS5cbiAgICAgICAgQHBhcmFtIFtpc0ludGVyY2FsYXJ5PWZhbHNlXSB7Ym9vbGVhbn0gSWYgbW9udGggaXMgaW50ZXJjYWxhcnkuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG1vbnRoIGluZGV4ICgwIGZvciBmaXJzdCBtb250aCkuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9Nb250aEluZGV4OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgaXNJbnRlcmNhbGFyeSkge1xuICAgICAgICAvLyBjb21wdXRlIGludGVyY2FsYXJ5IG1vbnRoIGluIHRoZSB5ZWFyICgwIGlmIG5vbmUpXG4gICAgICAgIHZhciBpbnRlcmNhbGFyeU1vbnRoID0gdGhpcy5pbnRlcmNhbGFyeU1vbnRoKHllYXIpO1xuXG4gICAgICAgIC8vIHZhbGlkYXRlIG1vbnRoXG4gICAgICAgIHZhciBpbnZhbGlkSW50ZXJjYWxhcnlNb250aCA9IFxuICAgICAgICAgICAgKGlzSW50ZXJjYWxhcnkgJiYgbW9udGggIT09IGludGVyY2FsYXJ5TW9udGgpO1xuICAgICAgICBpZiAoaW52YWxpZEludGVyY2FsYXJ5TW9udGggfHwgbW9udGggPCAxIHx8IG1vbnRoID4gMTIpIHtcbiAgICAgICAgICAgIHRocm93IG1haW4ubG9jYWwuaW52YWxpZE1vbnRoXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcezBcXH0vLCB0aGlzLmxvY2FsLm5hbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29tcHV0ZSBtb250aCBpbmRleFxuICAgICAgICB2YXIgbW9udGhJbmRleDtcblxuICAgICAgICBpZiAoIWludGVyY2FsYXJ5TW9udGgpIHtcbiAgICAgICAgICAgIG1vbnRoSW5kZXggPSBtb250aCAtIDE7XG4gICAgICAgIH0gZWxzZSBpZighaXNJbnRlcmNhbGFyeSAmJiBtb250aCA8PSBpbnRlcmNhbGFyeU1vbnRoKSB7XG4gICAgICAgICAgICBtb250aEluZGV4ID0gbW9udGggLSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbW9udGhJbmRleCA9IG1vbnRoO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1vbnRoSW5kZXg7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbW9udGggKGkuZS4gYWNjb3VudGluZyBmb3IgaW50ZXJjYWxhcnkgbW9udGhzKS5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gbW9udGhJbmRleCB7bnVtYmVyfSBUaGUgbW9udGggaW5kZXggKDAgZm9yIGZpcnN0IG1vbnRoKS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbW9udGggKDEgZm9yIGZpcnN0IG1vbnRoKS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0NoaW5lc2VNb250aDogZnVuY3Rpb24oeWVhciwgbW9udGhJbmRleCkge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgICAgICBtb250aEluZGV4ID0geWVhci5tb250aCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29tcHV0ZSBpbnRlcmNhbGFyeSBtb250aCBpbiB0aGUgeWVhciAoMCBpZiBub25lKVxuICAgICAgICB2YXIgaW50ZXJjYWxhcnlNb250aCA9IHRoaXMuaW50ZXJjYWxhcnlNb250aCh5ZWFyKTtcblxuICAgICAgICAvLyB2YWxpZGF0ZSBtb250aFxuICAgICAgICB2YXIgbWF4TW9udGhJbmRleCA9IChpbnRlcmNhbGFyeU1vbnRoKSA/IDEyIDogMTE7XG4gICAgICAgIGlmIChtb250aEluZGV4IDwgMCB8fCBtb250aEluZGV4ID4gbWF4TW9udGhJbmRleCkge1xuICAgICAgICAgICAgdGhyb3cgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGhcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFx7MFxcfS8sIHRoaXMubG9jYWwubmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjb21wdXRlIENoaW5lc2UgbW9udGhcbiAgICAgICAgdmFyIG1vbnRoO1xuXG4gICAgICAgIGlmICghaW50ZXJjYWxhcnlNb250aCkge1xuICAgICAgICAgICAgbW9udGggPSBtb250aEluZGV4ICsgMTtcbiAgICAgICAgfSBlbHNlIGlmKG1vbnRoSW5kZXggPCBpbnRlcmNhbGFyeU1vbnRoKSB7XG4gICAgICAgICAgICBtb250aCA9IG1vbnRoSW5kZXggKyAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbW9udGggPSBtb250aEluZGV4O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1vbnRoO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSBpbnRlcmNhbGFyeSBtb250aCBvZiBhIHllYXIgKGlmIGFueSkuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBpbnRlcmNhbGFyeSBtb250aCBudW1iZXIsIG9yIDAgaWYgbm9uZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBpbnRlcmNhbGFyeU1vbnRoOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHllYXIgPSB0aGlzLl92YWxpZGF0ZVllYXIoeWVhcik7XG5cbiAgICAgICAgdmFyIG1vbnRoRGF5c1RhYmxlID0gTFVOQVJfTU9OVEhfREFZU1t5ZWFyIC0gTFVOQVJfTU9OVEhfREFZU1swXV07XG4gICAgICAgIHZhciBpbnRlcmNhbGFyeU1vbnRoID0gbW9udGhEYXlzVGFibGUgPj4gMTM7XG5cbiAgICAgICAgcmV0dXJuIGludGVyY2FsYXJ5TW9udGg7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgYW4gaW50ZXJjYWxhcnkgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoSW5kZXhdIHtudW1iZXJ9IFRoZSBtb250aCBpbmRleCB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGFuIGludGVyY2FsYXJ5IG1vbnRoLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGlzSW50ZXJjYWxhcnlNb250aDogZnVuY3Rpb24oeWVhciwgbW9udGhJbmRleCkge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgICAgICBtb250aEluZGV4ID0geWVhci5tb250aCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGludGVyY2FsYXJ5TW9udGggPSB0aGlzLmludGVyY2FsYXJ5TW9udGgoeWVhcik7XG5cbiAgICAgICAgcmV0dXJuICEhaW50ZXJjYWxhcnlNb250aCAmJiBpbnRlcmNhbGFyeU1vbnRoID09PSBtb250aEluZGV4O1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgQ2hpbmVzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4gKHRoaXMuaW50ZXJjYWxhcnlNb250aCh5ZWFyKSAhPT0gMCk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZSAtIElTTyA4NjAxLlxuICAgICAgICBAbWVtYmVyb2YgQ2hpbmVzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aEluZGV4XSB7bnVtYmVyfSBUaGUgbW9udGggaW5kZXggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aEluZGV4LCBkYXkpIHtcbiAgICAgICAgLy8gY29tcHV0ZSBDaGluZXNlIG5ldyB5ZWFyXG4gICAgICAgIHZhciB2YWxpZGF0ZWRZZWFyID1cbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRlWWVhcih5ZWFyLCBtYWluLmxvY2FsLmludmFsaWR5ZWFyKTtcbiAgICAgICAgdmFyIHBhY2tlZERhdGUgPVxuICAgICAgICAgICAgQ0hJTkVTRV9ORVdfWUVBUlt2YWxpZGF0ZWRZZWFyIC0gQ0hJTkVTRV9ORVdfWUVBUlswXV07XG5cbiAgICAgICAgdmFyIHkgPSAocGFja2VkRGF0ZSA+PiA5KSAmIDB4RkZGO1xuICAgICAgICB2YXIgbSA9IChwYWNrZWREYXRlID4+IDUpICYgMHgwRjtcbiAgICAgICAgdmFyIGQgPSBwYWNrZWREYXRlICYgMHgxRjtcbiAgICAgICAgXG4gICAgICAgIC8vIGZpbmQgZmlyc3QgVGhydXNkYXkgb2YgdGhlIHllYXJcbiAgICAgICAgdmFyIGZpcnN0VGh1cnNkYXk7XG4gICAgICAgIGZpcnN0VGh1cnNkYXkgPSBncmVnb3JpYW5DYWxlbmRhci5uZXdEYXRlKHksIG0sIGQpO1xuICAgICAgICBmaXJzdFRodXJzZGF5LmFkZCg0IC0gKGZpcnN0VGh1cnNkYXkuZGF5T2ZXZWVrKCkgfHwgNyksICdkJyk7XG5cbiAgICAgICAgLy8gY29tcHV0ZSBkYXlzIGZyb20gZmlyc3QgVGh1cnNkYXlcbiAgICAgICAgdmFyIG9mZnNldCA9XG4gICAgICAgICAgICB0aGlzLnRvSkQoeWVhciwgbW9udGhJbmRleCwgZGF5KSAtIGZpcnN0VGh1cnNkYXkudG9KRCgpO1xuICAgICAgICByZXR1cm4gMSArIE1hdGguZmxvb3Iob2Zmc2V0IC8gNyk7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIG1vbnRocyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgbW9udGhzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIG1vbnRoc0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4gKHRoaXMubGVhcFllYXIoeWVhcikpID8gMTMgOiAxMjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgQ2hpbmVzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoSW5kZXhdIHtudW1iZXJ9IFRoZSBtb250aCBpbmRleC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGhJbmRleCkge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICBtb250aEluZGV4ID0geWVhci5tb250aCgpO1xuICAgICAgICAgICAgeWVhciA9IHllYXIueWVhcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgeWVhciA9IHRoaXMuX3ZhbGlkYXRlWWVhcih5ZWFyKTtcblxuICAgICAgICB2YXIgbW9udGhEYXlzVGFibGUgPSBMVU5BUl9NT05USF9EQVlTW3llYXIgLSBMVU5BUl9NT05USF9EQVlTWzBdXTtcblxuICAgICAgICB2YXIgaW50ZXJjYWxhcnlNb250aCA9IG1vbnRoRGF5c1RhYmxlID4+IDEzO1xuICAgICAgICB2YXIgbWF4TW9udGhJbmRleCA9IChpbnRlcmNhbGFyeU1vbnRoKSA/IDEyIDogMTE7XG4gICAgICAgIGlmIChtb250aEluZGV4ID4gbWF4TW9udGhJbmRleCkge1xuICAgICAgICAgICAgdGhyb3cgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGhcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFx7MFxcfS8sIHRoaXMubG9jYWwubmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZGF5c0luTW9udGggPSAobW9udGhEYXlzVGFibGUgJiAoMSA8PCAoMTIgLSBtb250aEluZGV4KSkpID9cbiAgICAgICAgICAgIDMwIDogMjk7XG5cbiAgICAgICAgcmV0dXJuIGRheXNJbk1vbnRoO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoSW5kZXhdIHtudW1iZXJ9IFRoZSBtb250aCBpbmRleCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHdlZWsgZGF5LCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtEYXk6IGZ1bmN0aW9uKHllYXIsIG1vbnRoSW5kZXgsIGRheSkge1xuICAgICAgICByZXR1cm4gKHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoSW5kZXgsIGRheSkgfHwgNykgPCA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoSW5kZXhdIHtudW1iZXJ9IFRoZSBtb250aCBpbmRleCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoSW5kZXgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICB5ZWFyID0gdGhpcy5fdmFsaWRhdGVZZWFyKGRhdGUueWVhcigpKTtcbiAgICAgICAgbW9udGhJbmRleCA9IGRhdGUubW9udGgoKTtcbiAgICAgICAgZGF5ID0gZGF0ZS5kYXkoKTtcblxuICAgICAgICB2YXIgaXNJbnRlcmNhbGFyeSA9IHRoaXMuaXNJbnRlcmNhbGFyeU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuICAgICAgICB2YXIgbW9udGggPSB0aGlzLnRvQ2hpbmVzZU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuXG4gICAgICAgIHZhciBzb2xhciA9IHRvU29sYXIoeWVhciwgbW9udGgsIGRheSwgaXNJbnRlcmNhbGFyeSk7XG5cbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbkNhbGVuZGFyLnRvSkQoc29sYXIueWVhciwgc29sYXIubW9udGgsIHNvbGFyLmRheSk7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDaGluZXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIHZhciBkYXRlID0gZ3JlZ29yaWFuQ2FsZW5kYXIuZnJvbUpEKGpkKTtcbiAgICAgICAgdmFyIGx1bmFyID0gdG9MdW5hcihkYXRlLnllYXIoKSwgZGF0ZS5tb250aCgpLCBkYXRlLmRheSgpKTtcbiAgICAgICAgdmFyIG1vbnRoSW5kZXggPSB0aGlzLnRvTW9udGhJbmRleChcbiAgICAgICAgICAgIGx1bmFyLnllYXIsIGx1bmFyLm1vbnRoLCBsdW5hci5pc0ludGVyY2FsYXJ5KTtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZShsdW5hci55ZWFyLCBtb250aEluZGV4LCBsdW5hci5kYXkpO1xuICAgIH0sXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIHN0cmluZy5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0gZGF0ZVN0cmluZyB7c3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50aW5nIGEgQ2hpbmVzZSBkYXRlXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgbmV3IGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlLiAqL1xuICAgIGZyb21TdHJpbmc6IGZ1bmN0aW9uKGRhdGVTdHJpbmcpIHtcbiAgICAgICAgdmFyIG1hdGNoID0gZGF0ZVN0cmluZy5tYXRjaChEQVRFX1JFR0VYUCk7XG5cbiAgICAgICAgdmFyIHllYXIgPSB0aGlzLl92YWxpZGF0ZVllYXIoK21hdGNoWzFdKTtcblxuICAgICAgICB2YXIgbW9udGggPSArbWF0Y2hbMl07XG4gICAgICAgIHZhciBpc0ludGVyY2FsYXJ5ID0gISFtYXRjaFszXTtcbiAgICAgICAgdmFyIG1vbnRoSW5kZXggPSB0aGlzLnRvTW9udGhJbmRleCh5ZWFyLCBtb250aCwgaXNJbnRlcmNhbGFyeSk7XG5cbiAgICAgICAgdmFyIGRheSA9ICttYXRjaFs0XTtcblxuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoSW5kZXgsIGRheSk7XG4gICAgfSxcblxuICAgIC8qKiBBZGQgcGVyaW9kKHMpIHRvIGEgZGF0ZS5cbiAgICAgICAgQ2F0ZXIgZm9yIG5vIHllYXIgemVyby5cbiAgICAgICAgQG1lbWJlcm9mIENoaW5lc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0gZGF0ZSB7Q0RhdGV9IFRoZSBzdGFydGluZyBkYXRlLlxuICAgICAgICBAcGFyYW0gb2Zmc2V0IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgcGVyaW9kcyB0byBhZGp1c3QgYnkuXG4gICAgICAgIEBwYXJhbSBwZXJpb2Qge3N0cmluZ30gT25lIG9mICd5JyBmb3IgeWVhciwgJ20nIGZvciBtb250aCwgJ3cnIGZvciB3ZWVrLCAnZCcgZm9yIGRheS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSB1cGRhdGVkIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBhZGQ6IGZ1bmN0aW9uKGRhdGUsIG9mZnNldCwgcGVyaW9kKSB7XG4gICAgICAgIHZhciB5ZWFyID0gZGF0ZS55ZWFyKCk7XG4gICAgICAgIHZhciBtb250aEluZGV4ID0gZGF0ZS5tb250aCgpO1xuICAgICAgICB2YXIgaXNJbnRlcmNhbGFyeSA9IHRoaXMuaXNJbnRlcmNhbGFyeU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuICAgICAgICB2YXIgbW9udGggPSB0aGlzLnRvQ2hpbmVzZU1vbnRoKHllYXIsIG1vbnRoSW5kZXgpO1xuXG4gICAgICAgIHZhciBjZGF0ZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihDaGluZXNlQ2FsZW5kYXIucHJvdG90eXBlKVxuICAgICAgICAgICAgLmFkZC5jYWxsKHRoaXMsIGRhdGUsIG9mZnNldCwgcGVyaW9kKTtcblxuICAgICAgICBpZiAocGVyaW9kID09PSAneScpIHtcbiAgICAgICAgICAgIC8vIFJlc3luYyBtb250aFxuICAgICAgICAgICAgdmFyIHJlc3VsdFllYXIgPSBjZGF0ZS55ZWFyKCk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0TW9udGhJbmRleCA9IGNkYXRlLm1vbnRoKCk7XG5cbiAgICAgICAgICAgIC8vIFVzaW5nIHRoZSBmYWN0IHRoZSBtb250aCBpbmRleCBvZiBhbiBpbnRlcmNhbGFyeSBtb250aFxuICAgICAgICAgICAgLy8gZXF1YWxzIGl0cyBtb250aCBudW1iZXI6XG4gICAgICAgICAgICB2YXIgcmVzdWx0Q2FuQmVJbnRlcmNhbGFyeU1vbnRoID1cbiAgICAgICAgICAgICAgICB0aGlzLmlzSW50ZXJjYWxhcnlNb250aChyZXN1bHRZZWFyLCBtb250aCk7XG5cbiAgICAgICAgICAgIHZhciBjb3JyZWN0ZWRNb250aEluZGV4ID1cbiAgICAgICAgICAgICAgICAoaXNJbnRlcmNhbGFyeSAmJiByZXN1bHRDYW5CZUludGVyY2FsYXJ5TW9udGgpID9cbiAgICAgICAgICAgICAgICB0aGlzLnRvTW9udGhJbmRleChyZXN1bHRZZWFyLCBtb250aCwgdHJ1ZSkgOlxuICAgICAgICAgICAgICAgIHRoaXMudG9Nb250aEluZGV4KHJlc3VsdFllYXIsIG1vbnRoLCBmYWxzZSk7XG5cbiAgICAgICAgICAgIGlmIChjb3JyZWN0ZWRNb250aEluZGV4ICE9PSByZXN1bHRNb250aEluZGV4KSB7XG4gICAgICAgICAgICAgICAgY2RhdGUubW9udGgoY29ycmVjdGVkTW9udGhJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2RhdGU7XG4gICAgfSxcbn0pO1xuXG4vLyBVc2VkIGJ5IENoaW5lc2VDYWxlbmRhci5wcm90b3R5cGUuZnJvbVN0cmluZ1xudmFyIERBVEVfUkVHRVhQID0gL15cXHMqKC0/XFxkXFxkXFxkXFxkfFxcZFxcZClbLS9dKFxcZD9cXGQpKFtpSV0/KVstL10oXFxkP1xcZCkvbTtcbnZhciBNT05USF9OVU1CRVJfUkVHRVhQID0gL15cXGQ/XFxkW2lJXT8vbTtcbnZhciBNT05USF9OQU1FX1JFR0VYUCA9IC9e6ZewP+WNgT9b5LiA5LqM5LiJ5Zub5LqU5YWt5LiD5YWr5LmdXT/mnIgvbTtcbnZhciBNT05USF9TSE9SVF9OQU1FX1JFR0VYUCA9IC9e6ZewP+WNgT9b5LiA5LqM5LiJ5Zub5LqU5YWt5LiD5YWr5LmdXT8vbTtcblxuLy8gQ2hpbmVzZSBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMuY2hpbmVzZSA9IENoaW5lc2VDYWxlbmRhcjtcblxuLy8gQ2hpbmVzZSBjYWxlbmRhciB0YWJsZXMgZnJvbSB5ZWFyIDE4ODggdG8gMjExMVxuLy9cbi8vIFNvdXJjZTpcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9pc2VlMTUvTHVuYXItU29sYXItQ2FsZW5kYXItQ29udmVydGVyLmdpdFxuXG4vLyBUYWJsZSBvZiBpbnRlcmNhbGFyeSBtb250aHMgYW5kIGRheXMgcGVyIG1vbnRoIGZyb20geWVhciAxODg4IHRvIDIxMTFcbi8vXG4vLyBiaXQgKDEyIC0gaSk6ICAgICAgICBkYXlzIGluIHRoZSBpXnRoIG1vbnRoXG4vLyAgICAgICAgICAgICAgICAgICAgICAoPSAwIGlmIGledGggbHVuYXIgbW9udGggaGFzIDI5IGRheXMpXG4vLyAgICAgICAgICAgICAgICAgICAgICAoPSAxIGlmIGledGggbHVuYXIgbW9udGggaGFzIDMwIGRheXMpXG4vLyAgICAgICAgICAgICAgICAgICAgICAoZmlyc3QgbW9udGggaW4gbHVuYXIgeWVhciBpcyBpID0gMClcbi8vIGJpdHMgKDEzLDE0LDE1LDE2KTogIGludGVyY2FsYXJ5IG1vbnRoXG4vLyAgICAgICAgICAgICAgICAgICAgICAoPSAwIGlmIGx1bmFyIHllYXIgaGFzIG5vIGludGVyY2FsYXJ5IG1vbnRoKVxudmFyIExVTkFSX01PTlRIX0RBWVMgPSBbMTg4NywgMHgxNjk0LCAweDE2YWEsIDB4NGFkNSxcbiAgICAweGFiNiwgMHhjNGI3LCAweDRhZSwgMHhhNTYsIDB4YjUyYSwgMHgxZDJhLCAweGQ1NCwgMHg3NWFhLCAweDE1NmEsXG4gICAgMHgxMDk2ZCwgMHg5NWMsIDB4MTRhZSwgMHhhYTRkLCAweDFhNGMsIDB4MWIyYSwgMHg4ZDU1LCAweGFkNCxcbiAgICAweDEzNWEsIDB4NDk1ZCwgMHg5NWMsIDB4ZDQ5YiwgMHgxNDlhLCAweDFhNGEsIDB4YmFhNSwgMHgxNmE4LFxuICAgIDB4MWFkNCwgMHg1MmRhLCAweDEyYjYsIDB4ZTkzNywgMHg5MmUsIDB4MTQ5NiwgMHhiNjRiLCAweGQ0YSxcbiAgICAweGRhOCwgMHg5NWI1LCAweDU2YywgMHgxMmFlLCAweDQ5MmYsIDB4OTJlLCAweGNjOTYsIDB4MWE5NCxcbiAgICAweDFkNGEsIDB4YWRhOSwgMHhiNWEsIDB4NTZjLCAweDcyNmUsIDB4MTI1YywgMHhmOTJkLCAweDE5MmEsXG4gICAgMHgxYTk0LCAweGRiNGEsIDB4MTZhYSwgMHhhZDQsIDB4OTU1YiwgMHg0YmEsIDB4MTI1YSwgMHg1OTJiLFxuICAgIDB4MTUyYSwgMHhmNjk1LCAweGQ5NCwgMHgxNmFhLCAweGFhYjUsIDB4OWI0LCAweDE0YjYsIDB4NmE1NyxcbiAgICAweGE1NiwgMHgxMTUyYSwgMHgxZDJhLCAweGQ1NCwgMHhkNWFhLCAweDE1NmEsIDB4OTZjLCAweDk0YWUsXG4gICAgMHgxNGFlLCAweGE0YywgMHg3ZDI2LCAweDFiMmEsIDB4ZWI1NSwgMHhhZDQsIDB4MTJkYSwgMHhhOTVkLFxuICAgIDB4OTVhLCAweDE0OWEsIDB4OWE0ZCwgMHgxYTRhLCAweDExYWE1LCAweDE2YTgsIDB4MTZkNCwgMHhkMmRhLFxuICAgIDB4MTJiNiwgMHg5MzYsIDB4OTQ5NywgMHgxNDk2LCAweDE1NjRiLCAweGQ0YSwgMHhkYTgsIDB4ZDViNCxcbiAgICAweDE1NmMsIDB4MTJhZSwgMHhhOTJmLCAweDkyZSwgMHhjOTYsIDB4NmQ0YSwgMHgxZDRhLCAweDEwZDY1LFxuICAgIDB4YjU4LCAweDE1NmMsIDB4YjI2ZCwgMHgxMjVjLCAweDE5MmMsIDB4OWE5NSwgMHgxYTk0LCAweDFiNGEsXG4gICAgMHg0YjU1LCAweGFkNCwgMHhmNTViLCAweDRiYSwgMHgxMjVhLCAweGI5MmIsIDB4MTUyYSwgMHgxNjk0LFxuICAgIDB4OTZhYSwgMHgxNWFhLCAweDEyYWI1LCAweDk3NCwgMHgxNGI2LCAweGNhNTcsIDB4YTU2LCAweDE1MjYsXG4gICAgMHg4ZTk1LCAweGQ1NCwgMHgxNWFhLCAweDQ5YjUsIDB4OTZjLCAweGQ0YWUsIDB4MTQ5YywgMHgxYTRjLFxuICAgIDB4YmQyNiwgMHgxYWE2LCAweGI1NCwgMHg2ZDZhLCAweDEyZGEsIDB4MTY5NWQsIDB4OTVhLCAweDE0OWEsXG4gICAgMHhkYTRiLCAweDFhNGEsIDB4MWFhNCwgMHhiYjU0LCAweDE2YjQsIDB4YWRhLCAweDQ5NWIsIDB4OTM2LFxuICAgIDB4ZjQ5NywgMHgxNDk2LCAweDE1NGEsIDB4YjZhNSwgMHhkYTQsIDB4MTViNCwgMHg2YWI2LCAweDEyNmUsXG4gICAgMHgxMDkyZiwgMHg5MmUsIDB4Yzk2LCAweGNkNGEsIDB4MWQ0YSwgMHhkNjQsIDB4OTU2YywgMHgxNTVjLFxuICAgIDB4MTI1YywgMHg3OTJlLCAweDE5MmMsIDB4ZmE5NSwgMHgxYTk0LCAweDFiNGEsIDB4YWI1NSwgMHhhZDQsXG4gICAgMHgxNGRhLCAweDhhNWQsIDB4YTVhLCAweDExNTJiLCAweDE1MmEsIDB4MTY5NCwgMHhkNmFhLCAweDE1YWEsXG4gICAgMHhhYjQsIDB4OTRiYSwgMHgxNGI2LCAweGE1NiwgMHg3NTI3LCAweGQyNiwgMHhlZTUzLCAweGQ1NCwgMHgxNWFhLFxuICAgIDB4YTliNSwgMHg5NmMsIDB4MTRhZSwgMHg4YTRlLCAweDFhNGMsIDB4MTFkMjYsIDB4MWFhNCwgMHgxYjU0LFxuICAgIDB4Y2Q2YSwgMHhhZGEsIDB4OTVjLCAweDk0OWQsIDB4MTQ5YSwgMHgxYTJhLCAweDViMjUsIDB4MWFhNCxcbiAgICAweGZiNTIsIDB4MTZiNCwgMHhhYmEsIDB4YTk1YiwgMHg5MzYsIDB4MTQ5NiwgMHg5YTRiLCAweDE1NGEsXG4gICAgMHgxMzZhNSwgMHhkYTQsIDB4MTVhY107XG5cbi8vIFRhYmxlIG9mIENoaW5lc2UgTmV3IFllYXJzIGZyb20geWVhciAxODg4IHRvIDIxMTFcbi8vIFxuLy8gYml0cyAoMCB0byA0KTogICBzb2xhciBkYXlcbi8vIGJpdHMgKDUgdG8gOCk6ICAgc29sYXIgbW9udGhcbi8vIGJpdHMgKDkgdG8gMjApOiAgc29sYXIgeWVhclxudmFyIENISU5FU0VfTkVXX1lFQVIgPSBbMTg4NywgMHhlYzA0YywgMHhlYzIzZiwgMHhlYzQzNSwgMHhlYzY0OSxcbiAgICAweGVjODNlLCAweGVjYTUxLCAweGVjYzQ2LCAweGVjZTNhLCAweGVkMDRkLCAweGVkMjQyLCAweGVkNDM2LFxuICAgIDB4ZWQ2NGEsIDB4ZWQ4M2YsIDB4ZWRhNTMsIDB4ZWRjNDgsIDB4ZWRlM2QsIDB4ZWUwNTAsIDB4ZWUyNDQsXG4gICAgMHhlZTQzOSwgMHhlZTY0ZCwgMHhlZTg0MiwgMHhlZWEzNiwgMHhlZWM0YSwgMHhlZWUzZSwgMHhlZjA1MixcbiAgICAweGVmMjQ2LCAweGVmNDNhLCAweGVmNjRlLCAweGVmODQzLCAweGVmYTM3LCAweGVmYzRiLCAweGVmZTQxLFxuICAgIDB4ZjAwNTQsIDB4ZjAyNDgsIDB4ZjA0M2MsIDB4ZjA2NTAsIDB4ZjA4NDUsIDB4ZjBhMzgsIDB4ZjBjNGQsXG4gICAgMHhmMGU0MiwgMHhmMTAzNywgMHhmMTI0YSwgMHhmMTQzZSwgMHhmMTY1MSwgMHhmMTg0NiwgMHhmMWEzYSxcbiAgICAweGYxYzRlLCAweGYxZTQ0LCAweGYyMDM4LCAweGYyMjRiLCAweGYyNDNmLCAweGYyNjUzLCAweGYyODQ4LFxuICAgIDB4ZjJhM2IsIDB4ZjJjNGYsIDB4ZjJlNDUsIDB4ZjMwMzksIDB4ZjMyNGQsIDB4ZjM0NDIsIDB4ZjM2MzYsXG4gICAgMHhmMzg0YSwgMHhmM2EzZCwgMHhmM2M1MSwgMHhmM2U0NiwgMHhmNDAzYiwgMHhmNDI0ZSwgMHhmNDQ0MyxcbiAgICAweGY0NjM4LCAweGY0ODRjLCAweGY0YTNmLCAweGY0YzUyLCAweGY0ZTQ4LCAweGY1MDNjLCAweGY1MjRmLFxuICAgIDB4ZjU0NDUsIDB4ZjU2MzksIDB4ZjU4NGQsIDB4ZjVhNDIsIDB4ZjVjMzUsIDB4ZjVlNDksIDB4ZjYwM2UsXG4gICAgMHhmNjI1MSwgMHhmNjQ0NiwgMHhmNjYzYiwgMHhmNjg0ZiwgMHhmNmE0MywgMHhmNmMzNywgMHhmNmU0YixcbiAgICAweGY3MDNmLCAweGY3MjUyLCAweGY3NDQ3LCAweGY3NjNjLCAweGY3ODUwLCAweGY3YTQ1LCAweGY3YzM5LFxuICAgIDB4ZjdlNGQsIDB4ZjgwNDIsIDB4ZjgyNTQsIDB4Zjg0NDksIDB4Zjg2M2QsIDB4Zjg4NTEsIDB4ZjhhNDYsXG4gICAgMHhmOGMzYiwgMHhmOGU0ZiwgMHhmOTA0NCwgMHhmOTIzNywgMHhmOTQ0YSwgMHhmOTYzZiwgMHhmOTg1MyxcbiAgICAweGY5YTQ3LCAweGY5YzNjLCAweGY5ZTUwLCAweGZhMDQ1LCAweGZhMjM4LCAweGZhNDRjLCAweGZhNjQxLFxuICAgIDB4ZmE4MzYsIDB4ZmFhNDksIDB4ZmFjM2QsIDB4ZmFlNTIsIDB4ZmIwNDcsIDB4ZmIyM2EsIDB4ZmI0NGUsXG4gICAgMHhmYjY0MywgMHhmYjgzNywgMHhmYmE0YSwgMHhmYmMzZiwgMHhmYmU1MywgMHhmYzA0OCwgMHhmYzIzYyxcbiAgICAweGZjNDUwLCAweGZjNjQ1LCAweGZjODM5LCAweGZjYTRjLCAweGZjYzQxLCAweGZjZTM2LCAweGZkMDRhLFxuICAgIDB4ZmQyM2QsIDB4ZmQ0NTEsIDB4ZmQ2NDYsIDB4ZmQ4M2EsIDB4ZmRhNGQsIDB4ZmRjNDMsIDB4ZmRlMzcsXG4gICAgMHhmZTA0YiwgMHhmZTIzZiwgMHhmZTQ1MywgMHhmZTY0OCwgMHhmZTgzYywgMHhmZWE0ZiwgMHhmZWM0NCxcbiAgICAweGZlZTM4LCAweGZmMDRjLCAweGZmMjQxLCAweGZmNDM2LCAweGZmNjRhLCAweGZmODNlLCAweGZmYTUxLFxuICAgIDB4ZmZjNDYsIDB4ZmZlM2EsIDB4MTAwMDRlLCAweDEwMDI0MiwgMHgxMDA0MzcsIDB4MTAwNjRiLCAweDEwMDg0MSxcbiAgICAweDEwMGE1MywgMHgxMDBjNDgsIDB4MTAwZTNjLCAweDEwMTA0ZiwgMHgxMDEyNDQsIDB4MTAxNDM4LFxuICAgIDB4MTAxNjRjLCAweDEwMTg0MiwgMHgxMDFhMzUsIDB4MTAxYzQ5LCAweDEwMWUzZCwgMHgxMDIwNTEsXG4gICAgMHgxMDIyNDUsIDB4MTAyNDNhLCAweDEwMjY0ZSwgMHgxMDI4NDMsIDB4MTAyYTM3LCAweDEwMmM0YixcbiAgICAweDEwMmUzZiwgMHgxMDMwNTMsIDB4MTAzMjQ3LCAweDEwMzQzYiwgMHgxMDM2NGYsIDB4MTAzODQ1LFxuICAgIDB4MTAzYTM4LCAweDEwM2M0YywgMHgxMDNlNDIsIDB4MTA0MDM2LCAweDEwNDI0OSwgMHgxMDQ0M2QsXG4gICAgMHgxMDQ2NTEsIDB4MTA0ODQ2LCAweDEwNGEzYSwgMHgxMDRjNGUsIDB4MTA0ZTQzLCAweDEwNTAzOCxcbiAgICAweDEwNTI0YSwgMHgxMDU0M2UsIDB4MTA1NjUyLCAweDEwNTg0NywgMHgxMDVhM2IsIDB4MTA1YzRmLFxuICAgIDB4MTA1ZTQ1LCAweDEwNjAzOSwgMHgxMDYyNGMsIDB4MTA2NDQxLCAweDEwNjYzNSwgMHgxMDY4NDksXG4gICAgMHgxMDZhM2QsIDB4MTA2YzUxLCAweDEwNmU0NywgMHgxMDcwM2MsIDB4MTA3MjRmLCAweDEwNzQ0NCxcbiAgICAweDEwNzYzOCwgMHgxMDc4NGMsIDB4MTA3YTNmLCAweDEwN2M1MywgMHgxMDdlNDhdO1xuXG5mdW5jdGlvbiB0b0x1bmFyKHllYXJPckRhdGUsIG1vbnRoT3JSZXN1bHQsIGRheSwgcmVzdWx0KSB7XG4gICAgdmFyIHNvbGFyRGF0ZTtcbiAgICB2YXIgbHVuYXJEYXRlO1xuXG4gICAgaWYodHlwZW9mIHllYXJPckRhdGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHNvbGFyRGF0ZSA9IHllYXJPckRhdGU7XG4gICAgICAgIGx1bmFyRGF0ZSA9IG1vbnRoT3JSZXN1bHQgfHwge307XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaXNWYWxpZFllYXIgPSAodHlwZW9mIHllYXJPckRhdGUgPT09ICdudW1iZXInKSAmJlxuICAgICAgICAgICAgKHllYXJPckRhdGUgPj0gMTg4OCkgJiYgKHllYXJPckRhdGUgPD0gMjExMSk7XG4gICAgICAgIGlmKCFpc1ZhbGlkWWVhcilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlNvbGFyIHllYXIgb3V0c2lkZSByYW5nZSAxODg4LTIxMTFcIik7XG5cbiAgICAgICAgdmFyIGlzVmFsaWRNb250aCA9ICh0eXBlb2YgbW9udGhPclJlc3VsdCA9PT0gJ251bWJlcicpICYmXG4gICAgICAgICAgICAobW9udGhPclJlc3VsdCA+PSAxKSAmJiAobW9udGhPclJlc3VsdCA8PSAxMik7XG4gICAgICAgIGlmKCFpc1ZhbGlkTW9udGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb2xhciBtb250aCBvdXRzaWRlIHJhbmdlIDEgLSAxMlwiKTtcblxuICAgICAgICB2YXIgaXNWYWxpZERheSA9ICh0eXBlb2YgZGF5ID09PSAnbnVtYmVyJykgJiYgKGRheSA+PSAxKSAmJiAoZGF5IDw9IDMxKTtcbiAgICAgICAgaWYoIWlzVmFsaWREYXkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb2xhciBkYXkgb3V0c2lkZSByYW5nZSAxIC0gMzFcIik7XG5cbiAgICAgICAgc29sYXJEYXRlID0ge1xuICAgICAgICAgICAgeWVhcjogeWVhck9yRGF0ZSxcbiAgICAgICAgICAgIG1vbnRoOiBtb250aE9yUmVzdWx0LFxuICAgICAgICAgICAgZGF5OiBkYXksXG4gICAgICAgIH07XG4gICAgICAgIGx1bmFyRGF0ZSA9IHJlc3VsdCB8fCB7fTtcbiAgICB9XG5cbiAgICAvLyBDb21wdXRlIENoaW5lc2UgbmV3IHllYXIgYW5kIGx1bmFyIHllYXJcbiAgICB2YXIgY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlID1cbiAgICAgICAgQ0hJTkVTRV9ORVdfWUVBUltzb2xhckRhdGUueWVhciAtIENISU5FU0VfTkVXX1lFQVJbMF1dO1xuXG4gICAgdmFyIHBhY2tlZERhdGUgPSAoc29sYXJEYXRlLnllYXIgPDwgOSkgfCAoc29sYXJEYXRlLm1vbnRoIDw8IDUpXG4gICAgICAgIHwgc29sYXJEYXRlLmRheTtcblxuICAgIGx1bmFyRGF0ZS55ZWFyID0gKHBhY2tlZERhdGUgPj0gY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlKSA/XG4gICAgICAgIHNvbGFyRGF0ZS55ZWFyIDpcbiAgICAgICAgc29sYXJEYXRlLnllYXIgLSAxO1xuXG4gICAgY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlID1cbiAgICAgICAgQ0hJTkVTRV9ORVdfWUVBUltsdW5hckRhdGUueWVhciAtIENISU5FU0VfTkVXX1lFQVJbMF1dO1xuXG4gICAgdmFyIHkgPSAoY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlID4+IDkpICYgMHhGRkY7XG4gICAgdmFyIG0gPSAoY2hpbmVzZU5ld1llYXJQYWNrZWREYXRlID4+IDUpICYgMHgwRjtcbiAgICB2YXIgZCA9IGNoaW5lc2VOZXdZZWFyUGFja2VkRGF0ZSAmIDB4MUY7XG5cbiAgICAvLyBDb21wdXRlIGRheXMgZnJvbSBuZXcgeWVhclxuICAgIHZhciBkYXlzRnJvbU5ld1llYXI7XG5cbiAgICB2YXIgY2hpbmVzZU5ld1llYXJKU0RhdGUgPSBuZXcgRGF0ZSh5LCBtIC0xLCBkKTtcbiAgICB2YXIganNEYXRlID0gbmV3IERhdGUoc29sYXJEYXRlLnllYXIsIHNvbGFyRGF0ZS5tb250aCAtIDEsIHNvbGFyRGF0ZS5kYXkpO1xuXG4gICAgZGF5c0Zyb21OZXdZZWFyID0gTWF0aC5yb3VuZChcbiAgICAgICAgKGpzRGF0ZSAtIGNoaW5lc2VOZXdZZWFySlNEYXRlKSAvICgyNCAqIDM2MDAgKiAxMDAwKSk7XG5cbiAgICAvLyBDb21wdXRlIGx1bmFyIG1vbnRoIGFuZCBkYXlcbiAgICB2YXIgbW9udGhEYXlzVGFibGUgPSBMVU5BUl9NT05USF9EQVlTW2x1bmFyRGF0ZS55ZWFyIC0gTFVOQVJfTU9OVEhfREFZU1swXV07XG5cbiAgICB2YXIgaTtcbiAgICBmb3IoaSA9IDA7IGkgPCAxMzsgaSsrKSB7XG4gICAgICAgIHZhciBkYXlzSW5Nb250aCA9IChtb250aERheXNUYWJsZSAmICgxIDw8ICgxMiAtIGkpKSkgPyAzMCA6IDI5O1xuXG4gICAgICAgIGlmIChkYXlzRnJvbU5ld1llYXIgPCBkYXlzSW5Nb250aCkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBkYXlzRnJvbU5ld1llYXIgLT0gZGF5c0luTW9udGg7XG4gICAgfVxuXG4gICAgdmFyIGludGVyY2FsYXJ5TW9udGggPSBtb250aERheXNUYWJsZSA+PiAxMztcbiAgICBpZiAoIWludGVyY2FsYXJ5TW9udGggfHwgaSA8IGludGVyY2FsYXJ5TW9udGgpIHtcbiAgICAgICAgbHVuYXJEYXRlLmlzSW50ZXJjYWxhcnkgPSBmYWxzZTtcbiAgICAgICAgbHVuYXJEYXRlLm1vbnRoID0gMSArIGk7XG4gICAgfSBlbHNlIGlmIChpID09PSBpbnRlcmNhbGFyeU1vbnRoKSB7XG4gICAgICAgIGx1bmFyRGF0ZS5pc0ludGVyY2FsYXJ5ID0gdHJ1ZTtcbiAgICAgICAgbHVuYXJEYXRlLm1vbnRoID0gaTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsdW5hckRhdGUuaXNJbnRlcmNhbGFyeSA9IGZhbHNlO1xuICAgICAgICBsdW5hckRhdGUubW9udGggPSBpO1xuICAgIH1cblxuICAgIGx1bmFyRGF0ZS5kYXkgPSAxICsgZGF5c0Zyb21OZXdZZWFyO1xuXG4gICAgcmV0dXJuIGx1bmFyRGF0ZTtcbn1cblxuZnVuY3Rpb24gdG9Tb2xhcih5ZWFyT3JEYXRlLCBtb250aE9yUmVzdWx0LCBkYXksIGlzSW50ZXJjYWxhcnlPclJlc3VsdCwgcmVzdWx0KSB7XG4gICAgdmFyIHNvbGFyRGF0ZTtcbiAgICB2YXIgbHVuYXJEYXRlO1xuXG4gICAgaWYodHlwZW9mIHllYXJPckRhdGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGx1bmFyRGF0ZSA9IHllYXJPckRhdGU7XG4gICAgICAgIHNvbGFyRGF0ZSA9IG1vbnRoT3JSZXN1bHQgfHwge307XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaXNWYWxpZFllYXIgPSAodHlwZW9mIHllYXJPckRhdGUgPT09ICdudW1iZXInKSAmJlxuICAgICAgICAgICAgKHllYXJPckRhdGUgPj0gMTg4OCkgJiYgKHllYXJPckRhdGUgPD0gMjExMSk7XG4gICAgICAgIGlmKCFpc1ZhbGlkWWVhcilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkx1bmFyIHllYXIgb3V0c2lkZSByYW5nZSAxODg4LTIxMTFcIik7XG5cbiAgICAgICAgdmFyIGlzVmFsaWRNb250aCA9ICh0eXBlb2YgbW9udGhPclJlc3VsdCA9PT0gJ251bWJlcicpICYmXG4gICAgICAgICAgICAobW9udGhPclJlc3VsdCA+PSAxKSAmJiAobW9udGhPclJlc3VsdCA8PSAxMik7XG4gICAgICAgIGlmKCFpc1ZhbGlkTW9udGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJMdW5hciBtb250aCBvdXRzaWRlIHJhbmdlIDEgLSAxMlwiKTtcblxuICAgICAgICB2YXIgaXNWYWxpZERheSA9ICh0eXBlb2YgZGF5ID09PSAnbnVtYmVyJykgJiYgKGRheSA+PSAxKSAmJiAoZGF5IDw9IDMwKTtcbiAgICAgICAgaWYoIWlzVmFsaWREYXkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJMdW5hciBkYXkgb3V0c2lkZSByYW5nZSAxIC0gMzBcIik7XG5cbiAgICAgICAgdmFyIGlzSW50ZXJjYWxhcnk7XG4gICAgICAgIGlmKHR5cGVvZiBpc0ludGVyY2FsYXJ5T3JSZXN1bHQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBpc0ludGVyY2FsYXJ5ID0gZmFsc2U7XG4gICAgICAgICAgICBzb2xhckRhdGUgPSBpc0ludGVyY2FsYXJ5T3JSZXN1bHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpc0ludGVyY2FsYXJ5ID0gISFpc0ludGVyY2FsYXJ5T3JSZXN1bHQ7XG4gICAgICAgICAgICBzb2xhckRhdGUgPSByZXN1bHQgfHwge307XG4gICAgICAgIH1cblxuICAgICAgICBsdW5hckRhdGUgPSB7XG4gICAgICAgICAgICB5ZWFyOiB5ZWFyT3JEYXRlLFxuICAgICAgICAgICAgbW9udGg6IG1vbnRoT3JSZXN1bHQsXG4gICAgICAgICAgICBkYXk6IGRheSxcbiAgICAgICAgICAgIGlzSW50ZXJjYWxhcnk6IGlzSW50ZXJjYWxhcnksXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gQ29tcHV0ZSBkYXlzIGZyb20gbmV3IHllYXJcbiAgICB2YXIgZGF5c0Zyb21OZXdZZWFyO1xuXG4gICAgZGF5c0Zyb21OZXdZZWFyID0gbHVuYXJEYXRlLmRheSAtIDE7XG5cbiAgICB2YXIgbW9udGhEYXlzVGFibGUgPSBMVU5BUl9NT05USF9EQVlTW2x1bmFyRGF0ZS55ZWFyIC0gTFVOQVJfTU9OVEhfREFZU1swXV07XG4gICAgdmFyIGludGVyY2FsYXJ5TW9udGggPSBtb250aERheXNUYWJsZSA+PiAxMztcblxuICAgIHZhciBtb250aHNGcm9tTmV3WWVhcjtcbiAgICBpZiAoIWludGVyY2FsYXJ5TW9udGgpIHtcbiAgICAgICAgbW9udGhzRnJvbU5ld1llYXIgPSBsdW5hckRhdGUubW9udGggLSAxO1xuICAgIH0gZWxzZSBpZiAobHVuYXJEYXRlLm1vbnRoID4gaW50ZXJjYWxhcnlNb250aCkge1xuICAgICAgICBtb250aHNGcm9tTmV3WWVhciA9IGx1bmFyRGF0ZS5tb250aDtcbiAgICB9IGVsc2UgaWYgKGx1bmFyRGF0ZS5pc0ludGVyY2FsYXJ5KSB7XG4gICAgICAgIG1vbnRoc0Zyb21OZXdZZWFyID0gbHVuYXJEYXRlLm1vbnRoO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1vbnRoc0Zyb21OZXdZZWFyID0gbHVuYXJEYXRlLm1vbnRoIC0gMTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbW9udGhzRnJvbU5ld1llYXI7IGkrKykge1xuICAgICAgICB2YXIgZGF5c0luTW9udGggPSAobW9udGhEYXlzVGFibGUgJiAoMSA8PCAoMTIgLSBpKSkpID8gMzAgOiAyOTtcbiAgICAgICAgZGF5c0Zyb21OZXdZZWFyICs9IGRheXNJbk1vbnRoO1xuICAgIH1cblxuICAgIC8vIENvbXB1dGUgQ2hpbmVzZSBuZXcgeWVhclxuICAgIHZhciBwYWNrZWREYXRlID0gQ0hJTkVTRV9ORVdfWUVBUltsdW5hckRhdGUueWVhciAtIENISU5FU0VfTkVXX1lFQVJbMF1dO1xuXG4gICAgdmFyIHkgPSAocGFja2VkRGF0ZSA+PiA5KSAmIDB4RkZGO1xuICAgIHZhciBtID0gKHBhY2tlZERhdGUgPj4gNSkgJiAweDBGO1xuICAgIHZhciBkID0gcGFja2VkRGF0ZSAmIDB4MUY7XG5cbiAgICAvLyBDb21wdXRlIHNvbGFyIGRhdGVcbiAgICB2YXIganNEYXRlID0gbmV3IERhdGUoeSwgbSAtIDEsIGQgKyBkYXlzRnJvbU5ld1llYXIpO1xuXG4gICAgc29sYXJEYXRlLnllYXIgPSBqc0RhdGUuZ2V0RnVsbFllYXIoKTtcbiAgICBzb2xhckRhdGUubW9udGggPSAxICsganNEYXRlLmdldE1vbnRoKCk7XG4gICAgc29sYXJEYXRlLmRheSA9IGpzRGF0ZS5nZXREYXRlKCk7XG5cbiAgICByZXR1cm4gc29sYXJEYXRlO1xufVxuXG5cbn0se1wiLi4vbWFpblwiOjU3MSxcIm9iamVjdC1hc3NpZ25cIjo0NTR9XSw1NTg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBDb3B0aWMgY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEtlaXRoIFdvb2QgKHdvb2Qua2VpdGh7YXR9b3B0dXNuZXQuY29tLmF1KSBGZWJydWFyeSAyMDEwLlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IF9kZXJlcV8oJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJyk7XG5cblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBDb3B0aWMgY2FsZW5kYXIuXG4gICAgU2VlIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvcHRpY19jYWxlbmRhclwiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29wdGljX2NhbGVuZGFyPC9hPi5cbiAgICBTZWUgYWxzbyBDYWxlbmRyaWNhbCBDYWxjdWxhdGlvbnM6IFRoZSBNaWxsZW5uaXVtIEVkaXRpb25cbiAgICAoPGEgaHJlZj1cImh0dHA6Ly9lbXIuY3MuaWl0LmVkdS9ob21lL3JlaW5nb2xkL2NhbGVuZGFyLWJvb2svaW5kZXguc2h0bWxcIj5odHRwOi8vZW1yLmNzLmlpdC5lZHUvaG9tZS9yZWluZ29sZC9jYWxlbmRhci1ib29rL2luZGV4LnNodG1sPC9hPikuXG4gICAgQGNsYXNzIENvcHRpY0NhbGVuZGFyXG4gICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgKGRlZmF1bHQgRW5nbGlzaCkgZm9yIGxvY2FsaXNhdGlvbi4gKi9cbmZ1bmN0aW9uIENvcHRpY0NhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cbkNvcHRpY0NhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKENvcHRpY0NhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyICovXG4gICAgbmFtZTogJ0NvcHRpYycsXG4gICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIENvcHRpYyBlcG9jaDogMjkgQXVndXN0IDI4NCBDRSAoR3JlZ29yaWFuKS5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyICovXG4gICAgamRFcG9jaDogMTgyNTAyOS41LFxuICAgIC8qKiBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyTW9udGg6IFszMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCA1XSxcbiAgICAvKiogPGNvZGU+dHJ1ZTwvY29kZT4gaWYgaGFzIGEgeWVhciB6ZXJvLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogMSxcbiAgICAvKiogVGhlIG1pbmltdW0gZGF5IG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBDb3B0aWNDYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnQ29wdGljJyxcbiAgICAgICAgICAgIGVwb2NoczogWydCQU0nLCAnQU0nXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXM6IFsnVGhvdXQnLCAnUGFvcGknLCAnSGF0aG9yJywgJ0tvaWFrJywgJ1RvYmknLCAnTWVzaGlyJyxcbiAgICAgICAgICAgICdQYXJlbWhhdCcsICdQYXJlbW91ZGUnLCAnUGFzaG9ucycsICdQYW9uaScsICdFcGlwJywgJ01lc29yaScsICdQaSBLb2dpIEVuYXZvdCddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ1RobycsICdQYW8nLCAnSGF0aCcsICdLb2knLCAnVG9iJywgJ01lc2gnLFxuICAgICAgICAgICAgJ1BhdCcsICdQYWQnLCAnUGFzaCcsICdQYW8nLCAnRXBpJywgJ01lc28nLCAnUGlLJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydUa3lyaWFrYScsICdQZXNuYXUnLCAnUHNob21lbnQnLCAnUGVmdG9vdScsICdQdGlvdScsICdQc29vdScsICdQc2FiYmF0b24nXSxcbiAgICAgICAgICAgIGRheU5hbWVzU2hvcnQ6IFsnVGt5JywgJ1BlcycsICdQc2gnLCAnUGVmJywgJ1B0aScsICdQc28nLCAnUHNhJ10sXG4gICAgICAgICAgICBkYXlOYW1lc01pbjogWydUaycsICdQZXMnLCAnUHNoJywgJ1BlZicsICdQdCcsICdQc28nLCAnUHNhJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAnZGQvbW0veXl5eScsXG4gICAgICAgICAgICBmaXJzdERheTogMCxcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBDb3B0aWNDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHZhciB5ZWFyID0gZGF0ZS55ZWFyKCkgKyAoZGF0ZS55ZWFyKCkgPCAwID8gMSA6IDApOyAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgcmV0dXJuIHllYXIgJSA0ID09PSAzIHx8IHllYXIgJSA0ID09PSAtMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgbW9udGhzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIG1vbnRocy5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBtb250aHNJblllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBtYWluLmxvY2FsLmludmFsaWRZZWFyIHx8IG1haW4ucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAxMztcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB0aGUgd2VlayBvZiB0aGUgeWVhciBmb3IgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyKSB0aGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIC8vIEZpbmQgU3VuZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBTdW5kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCgtY2hlY2tEYXRlLmRheU9mV2VlaygpLCAnZCcpO1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigoY2hlY2tEYXRlLmRheU9mWWVhcigpIC0gMSkgLyA3KSArIDE7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSBtb250aC5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGguXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzIGluIHRoaXMgbW9udGguXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luTW9udGg6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheXNQZXJNb250aFtkYXRlLm1vbnRoKCkgLSAxXSArXG4gICAgICAgICAgICAoZGF0ZS5tb250aCgpID09PSAxMyAmJiB0aGlzLmxlYXBZZWFyKGRhdGUueWVhcigpKSA/IDEgOiAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgQ29wdGljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gbW9udGgge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBkYXkge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHdlZWsgZGF5LCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtEYXk6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLmRheU9mV2Vlayh5ZWFyLCBtb250aCwgZGF5KSB8fCA3KSA8IDY7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgSnVsaWFuIGRhdGUgZXF1aXZhbGVudCBmb3IgdGhpcyBkYXRlLFxuICAgICAgICBpLmUuIGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbi5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcikgdGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICB5ZWFyID0gZGF0ZS55ZWFyKCk7XG4gICAgICAgIGlmICh5ZWFyIDwgMCkgeyB5ZWFyKys7IH0gLy8gTm8geWVhciB6ZXJvXG4gICAgICAgIHJldHVybiBkYXRlLmRheSgpICsgKGRhdGUubW9udGgoKSAtIDEpICogMzAgK1xuICAgICAgICAgICAgKHllYXIgLSAxKSAqIDM2NSArIE1hdGguZmxvb3IoeWVhciAvIDQpICsgdGhpcy5qZEVwb2NoIC0gMTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENvcHRpY0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBqZCB7bnVtYmVyfSBUaGUgSnVsaWFuIGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpEOiBmdW5jdGlvbihqZCkge1xuICAgICAgICB2YXIgYyA9IE1hdGguZmxvb3IoamQpICsgMC41IC0gdGhpcy5qZEVwb2NoO1xuICAgICAgICB2YXIgeWVhciA9IE1hdGguZmxvb3IoKGMgLSBNYXRoLmZsb29yKChjICsgMzY2KSAvIDE0NjEpKSAvIDM2NSkgKyAxO1xuICAgICAgICBpZiAoeWVhciA8PSAwKSB7IHllYXItLTsgfSAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgYyA9IE1hdGguZmxvb3IoamQpICsgMC41IC0gdGhpcy5uZXdEYXRlKHllYXIsIDEsIDEpLnRvSkQoKTtcbiAgICAgICAgdmFyIG1vbnRoID0gTWF0aC5mbG9vcihjIC8gMzApICsgMTtcbiAgICAgICAgdmFyIGRheSA9IGMgLSAobW9udGggLSAxKSAqIDMwICsgMTtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICB9XG59KTtcblxuLy8gQ29wdGljIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy5jb3B0aWMgPSBDb3B0aWNDYWxlbmRhcjtcblxuXG59LHtcIi4uL21haW5cIjo1NzEsXCJvYmplY3QtYXNzaWduXCI6NDU0fV0sNTU5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgRGlzY3dvcmxkIGNhbGVuZGFyIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBLZWl0aCBXb29kICh3b29kLmtlaXRoe2F0fW9wdHVzbmV0LmNvbS5hdSkgSmFudWFyeSAyMDE2LlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IF9kZXJlcV8oJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJyk7XG5cblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBEaXNjd29ybGQgY2FsZW5kYXIgLSBVbnNlZW4gVW5pdmVyc2l0eSB2ZXJzaW9uLlxuICAgIFNlZSBhbHNvIDxhIGhyZWY9XCJodHRwOi8vd2lraS5sc3BhY2Uub3JnL21lZGlhd2lraS9EaXNjd29ybGRfY2FsZW5kYXJcIj5odHRwOi8vd2lraS5sc3BhY2Uub3JnL21lZGlhd2lraS9EaXNjd29ybGRfY2FsZW5kYXI8L2E+XG4gICAgYW5kIDxhIGhyZWY9XCJodHRwOi8vZGlzY3dvcmxkLndpa2lhLmNvbS93aWtpL0Rpc2N3b3JsZF9jYWxlbmRhclwiPmh0dHA6Ly9kaXNjd29ybGQud2lraWEuY29tL3dpa2kvRGlzY3dvcmxkX2NhbGVuZGFyPC9hPi5cbiAgICBAY2xhc3MgRGlzY3dvcmxkQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gRGlzY3dvcmxkQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuRGlzY3dvcmxkQ2FsZW5kYXIucHJvdG90eXBlID0gbmV3IG1haW4uYmFzZUNhbGVuZGFyO1xuXG5hc3NpZ24oRGlzY3dvcmxkQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnRGlzY3dvcmxkJyxcbiAgICAvKiogSnVsaWFuIGRhdGUgb2Ygc3RhcnQgb2YgRGlzY3dvcmxkIGVwb2NoOiAxIEphbnVhcnkgMDAwMSBDRS5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyICovXG4gICAgamRFcG9jaDogMTcyMTQyNS41LFxuICAgIC8qKiBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyTW9udGg6IFsxNiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMl0sXG4gICAgLyoqIDxjb2RlPnRydWU8L2NvZGU+IGlmIGhhcyBhIHllYXIgemVybywgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyICovXG4gICAgaGFzWWVhclplcm86IGZhbHNlLFxuICAgIC8qKiBUaGUgbWluaW11bSBtb250aCBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAxLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhciAqL1xuICAgIGZpcnN0TW9udGg6IDEsXG4gICAgLyoqIFRoZSBtaW5pbXVtIGRheSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhciAqL1xuICAgIG1pbkRheTogMSxcblxuICAgIC8qKiBMb2NhbGlzYXRpb25zIGZvciB0aGUgcGx1Z2luLlxuICAgICAgICBFbnRyaWVzIGFyZSBvYmplY3RzIGluZGV4ZWQgYnkgdGhlIGxhbmd1YWdlIGNvZGUgKCcnIGJlaW5nIHRoZSBkZWZhdWx0IFVTL0VuZ2xpc2gpLlxuICAgICAgICBFYWNoIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBhdHRyaWJ1dGVzLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC4gKi9cbiAgICByZWdpb25hbE9wdGlvbnM6IHsgLy8gTG9jYWxpc2F0aW9uc1xuICAgICAgICAnJzoge1xuICAgICAgICAgICAgbmFtZTogJ0Rpc2N3b3JsZCcsXG4gICAgICAgICAgICBlcG9jaHM6IFsnQlVDJywgJ1VDJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBbJ0ljaycsICdPZmZsZScsICdGZWJydWFyeScsICdNYXJjaCcsICdBcHJpbCcsICdNYXknLCAnSnVuZScsXG4gICAgICAgICAgICAnR3J1bmUnLCAnQXVndXN0JywgJ1NwdW5lJywgJ1Nla3RvYmVyJywgJ0VtYmVyJywgJ0RlY2VtYmVyJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzU2hvcnQ6IFsnSWNrJywgJ09mZicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0dydScsICdBdWcnLCAnU3B1JywgJ1NlaycsICdFbWInLCAnRGVjJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydTdW5kYXknLCAnT2N0ZWRheScsICdNb25kYXknLCAnVHVlc2RheScsICdXZWRuZXNkYXknLCAnVGh1cnNkYXknLCAnRnJpZGF5JywgJ1NhdHVyZGF5J10sXG4gICAgICAgICAgICBkYXlOYW1lc1Nob3J0OiBbJ1N1bicsICdPY3QnLCAnTW9uJywgJ1R1ZScsICdXZWQnLCAnVGh1JywgJ0ZyaScsICdTYXQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ1N1JywgJ09jJywgJ01vJywgJ1R1JywgJ1dlJywgJ1RoJywgJ0ZyJywgJ1NhJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAneXl5eS9tbS9kZCcsXG4gICAgICAgICAgICBmaXJzdERheTogMixcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIG1vbnRocyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBtb250aHMuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbW9udGhzSW5ZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuIDEzO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiA0MDA7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICAvLyBGaW5kIFN1bmRheSBvZiB0aGlzIHdlZWsgc3RhcnRpbmcgb24gU3VuZGF5XG4gICAgICAgIHZhciBjaGVja0RhdGUgPSB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgICAgIGNoZWNrRGF0ZS5hZGQoLWNoZWNrRGF0ZS5kYXlPZldlZWsoKSwgJ2QnKTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGNoZWNrRGF0ZS5kYXlPZlllYXIoKSAtIDEpIC8gOCkgKyAxO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIG9mIHRoZSBtb250aC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIG1vbnRoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgbW9udGgveWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbih5ZWFyLCBtb250aCkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGgpO1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlzUGVyTW9udGhbZGF0ZS5tb250aCgpIC0gMV07XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSB3ZWVrLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXJcbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMuICovXG4gICAgZGF5c0luV2VlazogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiA4O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIGRheSBvZiB0aGUgd2VlayBmb3IgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZGF5IG9mIHRoZSB3ZWVrOiAwIHRvIG51bWJlciBvZiBkYXlzIC0gMS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlPZldlZWs6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgcmV0dXJuIChkYXRlLmRheSgpICsgMSkgJSA4O1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBEaXNjd29ybGRDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHdlZWsgZGF5LCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtEYXk6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRvdyA9IHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgICAgICByZXR1cm4gKGRvdyA+PSAyICYmIGRvdyA8PSA2KTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYWJvdXQgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgRGlzY3dvcmxkQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7b2JqZWN0fSBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIC0gY29udGVudHMgZGVwZW5kcyBvbiBjYWxlbmRhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBleHRyYUluZm86IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgcmV0dXJuIHtjZW50dXJ5OiBjZW50dXJpZXNbTWF0aC5mbG9vcigoZGF0ZS55ZWFyKCkgLSAxKSAvIDEwMCkgKyAxXSB8fCAnJ307XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgSnVsaWFuIGRhdGUgZXF1aXZhbGVudCBmb3IgdGhpcyBkYXRlLFxuICAgICAgICBpLmUuIGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbi5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICB5ZWFyID0gZGF0ZS55ZWFyKCkgKyAoZGF0ZS55ZWFyKCkgPCAwID8gMSA6IDApO1xuICAgICAgICBtb250aCA9IGRhdGUubW9udGgoKTtcbiAgICAgICAgZGF5ID0gZGF0ZS5kYXkoKTtcbiAgICAgICAgcmV0dXJuIGRheSArIChtb250aCA+IDEgPyAxNiA6IDApICsgKG1vbnRoID4gMiA/IChtb250aCAtIDIpICogMzIgOiAwKSArXG4gICAgICAgICAgICAoeWVhciAtIDEpICogNDAwICsgdGhpcy5qZEVwb2NoIC0gMTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIERpc2N3b3JsZENhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBqZCB7bnVtYmVyfSBUaGUgSnVsaWFuIGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpEOiBmdW5jdGlvbihqZCkge1xuICAgICAgICBqZCA9IE1hdGguZmxvb3IoamQgKyAwLjUpIC0gTWF0aC5mbG9vcih0aGlzLmpkRXBvY2gpIC0gMTtcbiAgICAgICAgdmFyIHllYXIgPSBNYXRoLmZsb29yKGpkIC8gNDAwKSArIDE7XG4gICAgICAgIGpkIC09ICh5ZWFyIC0gMSkgKiA0MDA7XG4gICAgICAgIGpkICs9IChqZCA+IDE1ID8gMTYgOiAwKTtcbiAgICAgICAgdmFyIG1vbnRoID0gTWF0aC5mbG9vcihqZCAvIDMyKSArIDE7XG4gICAgICAgIHZhciBkYXkgPSBqZCAtIChtb250aCAtIDEpICogMzIgKyAxO1xuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKHllYXIgPD0gMCA/IHllYXIgLSAxIDogeWVhciwgbW9udGgsIGRheSk7XG4gICAgfVxufSk7XG5cbi8vIE5hbWVzIG9mIHRoZSBjZW50dXJpZXNcbnZhciBjZW50dXJpZXMgPSB7XG4gICAgMjA6ICdGcnVpdGJhdCcsXG4gICAgMjE6ICdBbmNob3Z5J1xufTtcblxuLy8gRGlzY3dvcmxkIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy5kaXNjd29ybGQgPSBEaXNjd29ybGRDYWxlbmRhcjtcblxuXG59LHtcIi4uL21haW5cIjo1NzEsXCJvYmplY3QtYXNzaWduXCI6NDU0fV0sNTYwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgRXRoaW9waWFuIGNhbGVuZGFyIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBLZWl0aCBXb29kICh3b29kLmtlaXRoe2F0fW9wdHVzbmV0LmNvbS5hdSkgRmVicnVhcnkgMjAxMC5cbiAgIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIChodHRwOi8va2VpdGgtd29vZC5uYW1lL2xpY2VuY2UuaHRtbCkgbGljZW5zZS4gXG4gICBQbGVhc2UgYXR0cmlidXRlIHRoZSBhdXRob3IgaWYgeW91IHVzZSBpdC4gKi9cblxudmFyIG1haW4gPSBfZGVyZXFfKCcuLi9tYWluJyk7XG52YXIgYXNzaWduID0gX2RlcmVxXygnb2JqZWN0LWFzc2lnbicpO1xuXG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgRXRoaW9waWFuIGNhbGVuZGFyLlxuICAgIFNlZSA8YSBocmVmPVwiaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9FdGhpb3BpYW5fY2FsZW5kYXJcIj5odHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0V0aGlvcGlhbl9jYWxlbmRhcjwvYT4uXG4gICAgU2VlIGFsc28gQ2FsZW5kcmljYWwgQ2FsY3VsYXRpb25zOiBUaGUgTWlsbGVubml1bSBFZGl0aW9uXG4gICAgKDxhIGhyZWY9XCJodHRwOi8vZW1yLmNzLmlpdC5lZHUvaG9tZS9yZWluZ29sZC9jYWxlbmRhci1ib29rL2luZGV4LnNodG1sXCI+aHR0cDovL2Vtci5jcy5paXQuZWR1L2hvbWUvcmVpbmdvbGQvY2FsZW5kYXItYm9vay9pbmRleC5zaHRtbDwvYT4pLlxuICAgIEBjbGFzcyBFdGhpb3BpYW5DYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBFdGhpb3BpYW5DYWxlbmRhcihsYW5ndWFnZSkge1xuICAgIHRoaXMubG9jYWwgPSB0aGlzLnJlZ2lvbmFsT3B0aW9uc1tsYW5ndWFnZSB8fCAnJ10gfHwgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddO1xufVxuXG5FdGhpb3BpYW5DYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihFdGhpb3BpYW5DYWxlbmRhci5wcm90b3R5cGUsIHtcbiAgICAvKiogVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhciAqL1xuICAgIG5hbWU6ICdFdGhpb3BpYW4nLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBFdGhpb3BpYW4gZXBvY2g6IDI3IEF1Z3VzdCA4IENFIChHcmVnb3JpYW4pLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXIgKi9cbiAgICBqZEVwb2NoOiAxNzI0MjIwLjUsXG4gICAgLyoqIERheXMgcGVyIG1vbnRoIGluIGEgY29tbW9uIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDVdLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXIgKi9cbiAgICBtaW5Nb250aDogMSxcbiAgICAvKiogVGhlIGZpcnN0IG1vbnRoIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIEV0aGlvcGlhbkNhbGVuZGFyXG4gICAgICAgIEBwcm9wZXJ0eSBuYW1lIHtzdHJpbmd9IFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAcHJvcGVydHkgZXBvY2hzIHtzdHJpbmdbXX0gVGhlIGVwb2NoIG5hbWVzLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNNaW4ge3N0cmluZ1tdfSBUaGUgbWluaW1hbCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRhdGVGb3JtYXQge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICAgICAgICAgIFNlZSB0aGUgb3B0aW9ucyBvbiA8YSBocmVmPVwiQmFzZUNhbGVuZGFyLmh0bWwjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgZGV0YWlscy5cbiAgICAgICAgQHByb3BlcnR5IGZpcnN0RGF5IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlaywgc3RhcnRpbmcgYXQgMC5cbiAgICAgICAgQHByb3BlcnR5IGlzUlRMIHtudW1iZXJ9IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgbG9jYWxpc2F0aW9uIHJlYWRzIHJpZ2h0LXRvLWxlZnQuICovXG4gICAgcmVnaW9uYWxPcHRpb25zOiB7IC8vIExvY2FsaXNhdGlvbnNcbiAgICAgICAgJyc6IHtcbiAgICAgICAgICAgIG5hbWU6ICdFdGhpb3BpYW4nLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JFRScsICdFRSddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydNZXNrZXJlbScsICdUaWtlbWV0JywgJ0hpZGFyJywgJ1RhaGVzYXMnLCAnVGlyJywgJ1lla2F0aXQnLFxuICAgICAgICAgICAgJ01lZ2FiaXQnLCAnTWlhemlhJywgJ0dlbmJvdCcsICdTZW5lJywgJ0hhbWxlJywgJ05laGFzZScsICdQYWd1bWUnXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydDogWydNZXMnLCAnVGlrJywgJ0hpZCcsICdUYWgnLCAnVGlyJywgJ1llaycsXG4gICAgICAgICAgICAnTWVnJywgJ01pYScsICdHZW4nLCAnU2VuJywgJ0hhbScsICdOZWgnLCAnUGFnJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydFaHVkJywgJ1NlZ25vJywgJ01ha3NlZ25vJywgJ0lyb2InLCAnSGFtdXMnLCAnQXJiJywgJ0tpZGFtZSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydFaHUnLCAnU2VnJywgJ01haycsICdJcm8nLCAnSGFtJywgJ0FyYicsICdLaWQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ0VoJywgJ1NlJywgJ01hJywgJ0lyJywgJ0hhJywgJ0FyJywgJ0tpJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAnZGQvbW0veXl5eScsXG4gICAgICAgICAgICBmaXJzdERheTogMCxcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHZhciB5ZWFyID0gZGF0ZS55ZWFyKCkgKyAoZGF0ZS55ZWFyKCkgPCAwID8gMSA6IDApOyAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgcmV0dXJuIHllYXIgJSA0ID09PSAzIHx8IHllYXIgJSA0ID09PSAtMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgbW9udGhzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEV0aGlvcGlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIG1vbnRocy5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBtb250aHNJblllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBtYWluLmxvY2FsLmludmFsaWRZZWFyIHx8IG1haW4ucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAxMztcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB0aGUgd2VlayBvZiB0aGUgeWVhciBmb3IgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIC8vIEZpbmQgU3VuZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBTdW5kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCgtY2hlY2tEYXRlLmRheU9mV2VlaygpLCAnZCcpO1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigoY2hlY2tEYXRlLmRheU9mWWVhcigpIC0gMSkgLyA3KSArIDE7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSBtb250aC5cbiAgICAgICAgQG1lbWJlcm9mIEV0aGlvcGlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGguXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzIGluIHRoaXMgbW9udGguXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luTW9udGg6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheXNQZXJNb250aFtkYXRlLm1vbnRoKCkgLSAxXSArXG4gICAgICAgICAgICAoZGF0ZS5tb250aCgpID09PSAxMyAmJiB0aGlzLmxlYXBZZWFyKGRhdGUueWVhcigpKSA/IDEgOiAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgRXRoaW9waWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiAodGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgfHwgNykgPCA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgeWVhciA9IGRhdGUueWVhcigpO1xuICAgICAgICBpZiAoeWVhciA8IDApIHsgeWVhcisrOyB9IC8vIE5vIHllYXIgemVyb1xuICAgICAgICByZXR1cm4gZGF0ZS5kYXkoKSArIChkYXRlLm1vbnRoKCkgLSAxKSAqIDMwICtcbiAgICAgICAgICAgICh5ZWFyIC0gMSkgKiAzNjUgKyBNYXRoLmZsb29yKHllYXIgLyA0KSArIHRoaXMuamRFcG9jaCAtIDE7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBFdGhpb3BpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gdGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSB0aGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgdmFyIGMgPSBNYXRoLmZsb29yKGpkKSArIDAuNSAtIHRoaXMuamRFcG9jaDtcbiAgICAgICAgdmFyIHllYXIgPSBNYXRoLmZsb29yKChjIC0gTWF0aC5mbG9vcigoYyArIDM2NikgLyAxNDYxKSkgLyAzNjUpICsgMTtcbiAgICAgICAgaWYgKHllYXIgPD0gMCkgeyB5ZWFyLS07IH0gLy8gTm8geWVhciB6ZXJvXG4gICAgICAgIGMgPSBNYXRoLmZsb29yKGpkKSArIDAuNSAtIHRoaXMubmV3RGF0ZSh5ZWFyLCAxLCAxKS50b0pEKCk7XG4gICAgICAgIHZhciBtb250aCA9IE1hdGguZmxvb3IoYyAvIDMwKSArIDE7XG4gICAgICAgIHZhciBkYXkgPSBjIC0gKG1vbnRoIC0gMSkgKiAzMCArIDE7XG4gICAgICAgIHJldHVybiB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgfVxufSk7XG5cbi8vIEV0aGlvcGlhbiBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMuZXRoaW9waWFuID0gRXRoaW9waWFuQ2FsZW5kYXI7XG5cblxufSx7XCIuLi9tYWluXCI6NTcxLFwib2JqZWN0LWFzc2lnblwiOjQ1NH1dLDU2MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKlxuICogV29ybGQgQ2FsZW5kYXJzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFyc1xuICpcbiAqIEJhdGNoLWNvbnZlcnRlZCBmcm9tIGtid29vZC9jYWxlbmRhcnNcbiAqIE1hbnkgdGhhbmtzIHRvIEtlaXRoIFdvb2QgYW5kIGFsbCBvZiB0aGUgY29udHJpYnV0b3JzIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0IVxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbu+7vy8qIGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvY2FsZW5kYXJzLmh0bWxcbiAgIEhlYnJldyBjYWxlbmRhciBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEF1Z3VzdCAyMDA5LlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IF9kZXJlcV8oJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJyk7XG5cblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBIZWJyZXcgY2l2aWwgY2FsZW5kYXIuXG4gICAgQmFzZWQgb24gY29kZSBmcm9tIDxhIGhyZWY9XCJodHRwOi8vd3d3LmZvdXJtaWxhYi5jaC9kb2N1bWVudHMvY2FsZW5kYXIvXCI+aHR0cDovL3d3dy5mb3VybWlsYWIuY2gvZG9jdW1lbnRzL2NhbGVuZGFyLzwvYT4uXG4gICAgU2VlIGFsc28gPGEgaHJlZj1cImh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSGVicmV3X2NhbGVuZGFyXCI+aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9IZWJyZXdfY2FsZW5kYXI8L2E+LlxuICAgIEBjbGFzcyBIZWJyZXdDYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBIZWJyZXdDYWxlbmRhcihsYW5ndWFnZSkge1xuICAgIHRoaXMubG9jYWwgPSB0aGlzLnJlZ2lvbmFsT3B0aW9uc1tsYW5ndWFnZSB8fCAnJ10gfHwgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddO1xufVxuXG5IZWJyZXdDYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihIZWJyZXdDYWxlbmRhci5wcm90b3R5cGUsIHtcbiAgICAvKiogVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhciAqL1xuICAgIG5hbWU6ICdIZWJyZXcnLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBIZWJyZXcgZXBvY2g6IDcgT2N0b2JlciAzNzYxIEJDRS5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyICovXG4gICAgamRFcG9jaDogMzQ3OTk1LjUsXG4gICAgLyoqIERheXMgcGVyIG1vbnRoIGluIGEgY29tbW9uIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMwLCAyOSwgMzAsIDI5LCAzMCwgMjksIDMwLCAyOSwgMzAsIDI5LCAzMCwgMjksIDI5XSxcbiAgICAvKiogPGNvZGU+dHJ1ZTwvY29kZT4gaWYgaGFzIGEgeWVhciB6ZXJvLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogNyxcbiAgICAvKiogVGhlIG1pbmltdW0gZGF5IG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnSGVicmV3JyxcbiAgICAgICAgICAgIGVwb2NoczogWydCQU0nLCAnQU0nXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXM6IFsnTmlzYW4nLCAnSXlhcicsICdTaXZhbicsICdUYW1tdXonLCAnQXYnLCAnRWx1bCcsXG4gICAgICAgICAgICAnVGlzaHJlaScsICdDaGVzaHZhbicsICdLaXNsZXYnLCAnVGV2ZXQnLCAnU2hldmF0JywgJ0FkYXInLCAnQWRhciBJSSddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ05pcycsICdJeWEnLCAnU2l2JywgJ1RhbScsICdBdicsICdFbHUnLCAnVGlzJywgJ0NoZScsICdLaXMnLCAnVGV2JywgJ1NoZScsICdBZGEnLCAnQWQyJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydZb20gUmlzaG9uJywgJ1lvbSBTaGVuaScsICdZb20gU2hsaXNoaScsICdZb20gUmV2aVxcJ2knLCAnWW9tIENoYW1pc2hpJywgJ1lvbSBTaGlzaGknLCAnWW9tIFNoYWJiYXQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzU2hvcnQ6IFsnUmlzJywgJ1NoZScsICdTaGwnLCAnUmV2JywgJ0NoYScsICdTaGknLCAnU2hhJ10sXG4gICAgICAgICAgICBkYXlOYW1lc01pbjogWydSaScsJ1NoZScsJ1NobCcsJ1JlJywnQ2gnLCdTaGknLCdTaGEnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICdkZC9tbS95eXl5JyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiAwLFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xlYXBZZWFyKGRhdGUueWVhcigpKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtudW1iZXJ9IFRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgX2xlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHllYXIgPSAoeWVhciA8IDAgPyB5ZWFyICsgMSA6IHllYXIpO1xuICAgICAgICByZXR1cm4gbW9kKHllYXIgKiA3ICsgMSwgMTkpIDwgNztcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgbW9udGhzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIG1vbnRocy5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBtb250aHNJblllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gdGhpcy5fbGVhcFllYXIoeWVhci55ZWFyID8geWVhci55ZWFyKCkgOiB5ZWFyKSA/IDEzIDogMTI7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICAvLyBGaW5kIFN1bmRheSBvZiB0aGlzIHdlZWsgc3RhcnRpbmcgb24gU3VuZGF5XG4gICAgICAgIHZhciBjaGVja0RhdGUgPSB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgICAgIGNoZWNrRGF0ZS5hZGQoLWNoZWNrRGF0ZS5kYXlPZldlZWsoKSwgJ2QnKTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGNoZWNrRGF0ZS5kYXlPZlllYXIoKSAtIDEpIC8gNykgKyAxO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgeWVhciA9IGRhdGUueWVhcigpO1xuICAgICAgICByZXR1cm4gdGhpcy50b0pEKCh5ZWFyID09PSAtMSA/ICsxIDogeWVhciArIDEpLCA3LCAxKSAtIHRoaXMudG9KRCh5ZWFyLCA3LCAxKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgaWYgKHllYXIueWVhcikge1xuICAgICAgICAgICAgbW9udGggPSB5ZWFyLm1vbnRoKCk7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiAobW9udGggPT09IDEyICYmIHRoaXMubGVhcFllYXIoeWVhcikgPyAzMCA6IC8vIEFkYXIgSVxuICAgICAgICAgICAgICAgIChtb250aCA9PT0gOCAmJiBtb2QodGhpcy5kYXlzSW5ZZWFyKHllYXIpLCAxMCkgPT09IDUgPyAzMCA6IC8vIENoZXNodmFuIGluIHNobGVtYWggeWVhclxuICAgICAgICAgICAgICAgIChtb250aCA9PT0gOSAmJiBtb2QodGhpcy5kYXlzSW5ZZWFyKHllYXIpLCAxMCkgPT09IDMgPyAyOSA6IC8vIEtpc2xldiBpbiBjaGFzZXJhaCB5ZWFyXG4gICAgICAgICAgICAgICAgdGhpcy5kYXlzUGVyTW9udGhbbW9udGggLSAxXSkpKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRheU9mV2Vlayh5ZWFyLCBtb250aCwgZGF5KSAhPT0gNjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYWJvdXQgYSBkYXRlIC0geWVhciB0eXBlLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7b2JqZWN0fSBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIC0gY29udGVudHMgZGVwZW5kcyBvbiBjYWxlbmRhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBleHRyYUluZm86IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgcmV0dXJuIHt5ZWFyVHlwZTogKHRoaXMubGVhcFllYXIoZGF0ZSkgPyAnZW1ib2xpc21pYycgOiAnY29tbW9uJykgKyAnICcgK1xuICAgICAgICAgICAgWydkZWZpY2llbnQnLCAncmVndWxhcicsICdjb21wbGV0ZSddW3RoaXMuZGF5c0luWWVhcihkYXRlKSAlIDEwIC0gM119O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBIZWJyZXdDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGUpfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZXF1aXZhbGVudCBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0pEOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgbW9udGggPSBkYXRlLm1vbnRoKCk7XG4gICAgICAgIGRheSA9IGRhdGUuZGF5KCk7XG4gICAgICAgIHZhciBhZGpZZWFyID0gKHllYXIgPD0gMCA/IHllYXIgKyAxIDogeWVhcik7XG4gICAgICAgIHZhciBqZCA9IHRoaXMuamRFcG9jaCArIHRoaXMuX2RlbGF5MShhZGpZZWFyKSArXG4gICAgICAgICAgICB0aGlzLl9kZWxheTIoYWRqWWVhcikgKyBkYXkgKyAxO1xuICAgICAgICBpZiAobW9udGggPCA3KSB7XG4gICAgICAgICAgICBmb3IgKHZhciBtID0gNzsgbSA8PSB0aGlzLm1vbnRoc0luWWVhcih5ZWFyKTsgbSsrKSB7XG4gICAgICAgICAgICAgICAgamQgKz0gdGhpcy5kYXlzSW5Nb250aCh5ZWFyLCBtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAodmFyIG0gPSAxOyBtIDwgbW9udGg7IG0rKykge1xuICAgICAgICAgICAgICAgIGpkICs9IHRoaXMuZGF5c0luTW9udGgoeWVhciwgbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmb3IgKHZhciBtID0gNzsgbSA8IG1vbnRoOyBtKyspIHtcbiAgICAgICAgICAgICAgICBqZCArPSB0aGlzLmRheXNJbk1vbnRoKHllYXIsIG0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBqZDtcbiAgICB9LFxuXG4gICAgLyoqIFRlc3QgZm9yIGRlbGF5IG9mIHN0YXJ0IG9mIG5ldyB5ZWFyIGFuZCB0byBhdm9pZFxuICAgICAgICBTdW5kYXksIFdlZG5lc2RheSwgb3IgRnJpZGF5IGFzIHN0YXJ0IG9mIHRoZSBuZXcgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEhlYnJld0NhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtudW1iZXJ9IFRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGRheXMgdG8gb2Zmc2V0IGJ5LiAqL1xuICAgIF9kZWxheTE6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIG1vbnRocyA9IE1hdGguZmxvb3IoKDIzNSAqIHllYXIgLSAyMzQpIC8gMTkpO1xuICAgICAgICB2YXIgcGFydHMgPSAxMjA4NCArIDEzNzUzICogbW9udGhzO1xuICAgICAgICB2YXIgZGF5ID0gbW9udGhzICogMjkgKyBNYXRoLmZsb29yKHBhcnRzIC8gMjU5MjApO1xuICAgICAgICBpZiAobW9kKDMgKiAoZGF5ICsgMSksIDcpIDwgMykge1xuICAgICAgICAgICAgZGF5Kys7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRheTtcbiAgICB9LFxuXG4gICAgLyoqIENoZWNrIGZvciBkZWxheSBpbiBzdGFydCBvZiBuZXcgeWVhciBkdWUgdG8gbGVuZ3RoIG9mIGFkamFjZW50IHllYXJzLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZGF5cyB0byBvZmZzZXQgYnkuICovXG4gICAgX2RlbGF5MjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB2YXIgbGFzdCA9IHRoaXMuX2RlbGF5MSh5ZWFyIC0gMSk7XG4gICAgICAgIHZhciBwcmVzZW50ID0gdGhpcy5fZGVsYXkxKHllYXIpO1xuICAgICAgICB2YXIgbmV4dCA9IHRoaXMuX2RlbGF5MSh5ZWFyICsgMSk7XG4gICAgICAgIHJldHVybiAoKG5leHQgLSBwcmVzZW50KSA9PT0gMzU2ID8gMiA6ICgocHJlc2VudCAtIGxhc3QpID09PSAzODIgPyAxIDogMCkpO1xuICAgIH0sXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIEp1bGlhbiBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgSGVicmV3Q2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIGpkID0gTWF0aC5mbG9vcihqZCkgKyAwLjU7XG4gICAgICAgIHZhciB5ZWFyID0gTWF0aC5mbG9vcigoKGpkIC0gdGhpcy5qZEVwb2NoKSAqIDk4NDk2LjApIC8gMzU5NzUzNTEuMCkgLSAxO1xuICAgICAgICB3aGlsZSAoamQgPj0gdGhpcy50b0pEKCh5ZWFyID09PSAtMSA/ICsxIDogeWVhciArIDEpLCA3LCAxKSkge1xuICAgICAgICAgICAgeWVhcisrO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtb250aCA9IChqZCA8IHRoaXMudG9KRCh5ZWFyLCAxLCAxKSkgPyA3IDogMTtcbiAgICAgICAgd2hpbGUgKGpkID4gdGhpcy50b0pEKHllYXIsIG1vbnRoLCB0aGlzLmRheXNJbk1vbnRoKHllYXIsIG1vbnRoKSkpIHtcbiAgICAgICAgICAgIG1vbnRoKys7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRheSA9IGpkIC0gdGhpcy50b0pEKHllYXIsIG1vbnRoLCAxKSArIDE7XG4gICAgICAgIHJldHVybiB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgfVxufSk7XG5cbi8vIE1vZHVsdXMgZnVuY3Rpb24gd2hpY2ggd29ya3MgZm9yIG5vbi1pbnRlZ2Vycy5cbmZ1bmN0aW9uIG1vZChhLCBiKSB7XG4gICAgcmV0dXJuIGEgLSAoYiAqIE1hdGguZmxvb3IoYSAvIGIpKTtcbn1cblxuLy8gSGVicmV3IGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy5oZWJyZXcgPSBIZWJyZXdDYWxlbmRhcjtcblxuXG59LHtcIi4uL21haW5cIjo1NzEsXCJvYmplY3QtYXNzaWduXCI6NDU0fV0sNTYyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgSXNsYW1pYyBjYWxlbmRhciBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEF1Z3VzdCAyMDA5LlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IF9kZXJlcV8oJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJyk7XG5cblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBJc2xhbWljIG9yICcxNiBjaXZpbCcgY2FsZW5kYXIuXG4gICAgQmFzZWQgb24gY29kZSBmcm9tIDxhIGhyZWY9XCJodHRwOi8vd3d3LmlyYW5jaGFtYmVyLmNvbS9jYWxlbmRhci9jb252ZXJ0ZXIvaXJhbmlhbl9jYWxlbmRhcl9jb252ZXJ0ZXIucGhwXCI+aHR0cDovL3d3dy5pcmFuY2hhbWJlci5jb20vY2FsZW5kYXIvY29udmVydGVyL2lyYW5pYW5fY2FsZW5kYXJfY29udmVydGVyLnBocDwvYT4uXG4gICAgU2VlIGFsc28gPGEgaHJlZj1cImh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSXNsYW1pY19jYWxlbmRhclwiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSXNsYW1pY19jYWxlbmRhcjwvYT4uXG4gICAgQGNsYXNzIElzbGFtaWNDYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBJc2xhbWljQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuSXNsYW1pY0NhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKElzbGFtaWNDYWxlbmRhci5wcm90b3R5cGUsIHtcbiAgICAvKiogVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnSXNsYW1pYycsXG4gICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIElzbGFtaWMgZXBvY2g6IDE2IEp1bHkgNjIyIENFLlxuICAgICAgICBAbWVtYmVyb2YgSXNsYW1pY0NhbGVuZGFyICovXG4gICAgamRFcG9jaDogMTk0ODQzOS41LFxuICAgIC8qKiBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSXNsYW1pY0NhbGVuZGFyICovXG4gICAgZGF5c1Blck1vbnRoOiBbMzAsIDI5LCAzMCwgMjksIDMwLCAyOSwgMzAsIDI5LCAzMCwgMjksIDMwLCAyOV0sXG4gICAgLyoqIDxjb2RlPnRydWU8L2NvZGU+IGlmIGhhcyBhIHllYXIgemVybywgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgSXNsYW1pY0NhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhciAqL1xuICAgIGZpcnN0TW9udGg6IDEsXG4gICAgLyoqIFRoZSBtaW5pbXVtIGRheSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnSXNsYW1pYycsXG4gICAgICAgICAgICBlcG9jaHM6IFsnQkgnLCAnQUgnXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXM6IFsnTXVoYXJyYW0nLCAnU2FmYXInLCAnUmFiaVxcJyBhbC1hd3dhbCcsICdSYWJpXFwnIGFsLXRoYW5pJywgJ0p1bWFkYSBhbC1hd3dhbCcsICdKdW1hZGEgYWwtdGhhbmknLFxuICAgICAgICAgICAgJ1JhamFiJywgJ1NoYVxcJ2FiYW4nLCAnUmFtYWRhbicsICdTaGF3d2FsJywgJ0RodSBhbC1RaVxcJ2RhaCcsICdEaHUgYWwtSGlqamFoJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzU2hvcnQ6IFsnTXVoJywgJ1NhZicsICdSYWIxJywgJ1JhYjInLCAnSnVtMScsICdKdW0yJywgJ1JhaicsICdTaGFcXCcnLCAnUmFtJywgJ1NoYXcnLCAnRGh1UScsICdEaHVIJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydZYXdtIGFsLWFoYWQnLCAnWWF3bSBhbC1pdGhuYXluJywgJ1lhd20gYXRoLXRodWxhYXRoYWFcXCcnLFxuICAgICAgICAgICAgJ1lhd20gYWwtYXJiaVxcJ2FhXFwnJywgJ1lhd20gYWwta2hhbcSrcycsICdZYXdtIGFsLWp1bVxcJ2EnLCAnWWF3bSBhcy1zYWJ0J10sXG4gICAgICAgICAgICBkYXlOYW1lc1Nob3J0OiBbJ0FoYScsICdJdGgnLCAnVGh1JywgJ0FyYicsICdLaGEnLCAnSnVtJywgJ1NhYiddLFxuICAgICAgICAgICAgZGF5TmFtZXNNaW46IFsnQWgnLCdJdCcsJ1RoJywnQXInLCdLaCcsJ0p1JywnU2EnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICd5eXl5L21tL2RkJyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiA2LFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAoZGF0ZS55ZWFyKCkgKiAxMSArIDE0KSAlIDMwIDwgMTE7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgLy8gRmluZCBTdW5kYXkgb2YgdGhpcyB3ZWVrIHN0YXJ0aW5nIG9uIFN1bmRheVxuICAgICAgICB2YXIgY2hlY2tEYXRlID0gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgICAgICBjaGVja0RhdGUuYWRkKC1jaGVja0RhdGUuZGF5T2ZXZWVrKCksICdkJyk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKChjaGVja0RhdGUuZGF5T2ZZZWFyKCkgLSAxKSAvIDcpICsgMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cy5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5ZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5sZWFwWWVhcih5ZWFyKSA/IDM1NSA6IDM1NCk7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSBtb250aC5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIG9mIHRoZSBtb250aC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIG1vbnRoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgbW9udGgveWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbih5ZWFyLCBtb250aCkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGgpO1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlzUGVyTW9udGhbZGF0ZS5tb250aCgpIC0gMV0gK1xuICAgICAgICAgICAgKGRhdGUubW9udGgoKSA9PT0gMTIgJiYgdGhpcy5sZWFwWWVhcihkYXRlLnllYXIoKSkgPyAxIDogMCk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgYSB3ZWVrIGRheS5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHdlZWsgZGF5LCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtEYXk6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpICE9PSA1O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBJc2xhbWljQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZXF1aXZhbGVudCBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0pEOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgbW9udGggPSBkYXRlLm1vbnRoKCk7XG4gICAgICAgIGRheSA9IGRhdGUuZGF5KCk7XG4gICAgICAgIHllYXIgPSAoeWVhciA8PSAwID8geWVhciArIDEgOiB5ZWFyKTtcbiAgICAgICAgcmV0dXJuIGRheSArIE1hdGguY2VpbCgyOS41ICogKG1vbnRoIC0gMSkpICsgKHllYXIgLSAxKSAqIDM1NCArXG4gICAgICAgICAgICBNYXRoLmZsb29yKCgzICsgKDExICogeWVhcikpIC8gMzApICsgdGhpcy5qZEVwb2NoIC0gMTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIElzbGFtaWNDYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgamQgPSBNYXRoLmZsb29yKGpkKSArIDAuNTtcbiAgICAgICAgdmFyIHllYXIgPSBNYXRoLmZsb29yKCgzMCAqIChqZCAtIHRoaXMuamRFcG9jaCkgKyAxMDY0NikgLyAxMDYzMSk7XG4gICAgICAgIHllYXIgPSAoeWVhciA8PSAwID8geWVhciAtIDEgOiB5ZWFyKTtcbiAgICAgICAgdmFyIG1vbnRoID0gTWF0aC5taW4oMTIsIE1hdGguY2VpbCgoamQgLSAyOSAtIHRoaXMudG9KRCh5ZWFyLCAxLCAxKSkgLyAyOS41KSArIDEpO1xuICAgICAgICB2YXIgZGF5ID0gamQgLSB0aGlzLnRvSkQoeWVhciwgbW9udGgsIDEpICsgMTtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICB9XG59KTtcblxuLy8gSXNsYW1pYyAoMTYgY2l2aWwpIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy5pc2xhbWljID0gSXNsYW1pY0NhbGVuZGFyO1xuXG5cbn0se1wiLi4vbWFpblwiOjU3MSxcIm9iamVjdC1hc3NpZ25cIjo0NTR9XSw1NjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBKdWxpYW4gY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEtlaXRoIFdvb2QgKHdvb2Qua2VpdGh7YXR9b3B0dXNuZXQuY29tLmF1KSBBdWd1c3QgMjAwOS5cbiAgIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIChodHRwOi8va2VpdGgtd29vZC5uYW1lL2xpY2VuY2UuaHRtbCkgbGljZW5zZS4gXG4gICBQbGVhc2UgYXR0cmlidXRlIHRoZSBhdXRob3IgaWYgeW91IHVzZSBpdC4gKi9cblxudmFyIG1haW4gPSBfZGVyZXFfKCcuLi9tYWluJyk7XG52YXIgYXNzaWduID0gX2RlcmVxXygnb2JqZWN0LWFzc2lnbicpO1xuXG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgSnVsaWFuIGNhbGVuZGFyLlxuICAgIEJhc2VkIG9uIGNvZGUgZnJvbSA8YSBocmVmPVwiaHR0cDovL3d3dy5mb3VybWlsYWIuY2gvZG9jdW1lbnRzL2NhbGVuZGFyL1wiPmh0dHA6Ly93d3cuZm91cm1pbGFiLmNoL2RvY3VtZW50cy9jYWxlbmRhci88L2E+LlxuICAgIFNlZSBhbHNvIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0p1bGlhbl9jYWxlbmRhclwiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSnVsaWFuX2NhbGVuZGFyPC9hPi5cbiAgICBAY2xhc3MgSnVsaWFuQ2FsZW5kYXJcbiAgICBAYXVnbWVudHMgQmFzZUNhbGVuZGFyXG4gICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgKGRlZmF1bHQgRW5nbGlzaCkgZm9yIGxvY2FsaXNhdGlvbi4gKi9cbmZ1bmN0aW9uIEp1bGlhbkNhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cbkp1bGlhbkNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKEp1bGlhbkNhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgbmFtZTogJ0p1bGlhbicsXG4gICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIEp1bGlhbiBlcG9jaDogMSBKYW51YXJ5IDAwMDEgQUQgPSAzMCBEZWNlbWJlciAwMDAxIEJDRS5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgamRFcG9jaDogMTcyMTQyMy41LFxuICAgIC8qKiBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgSnVsaWFuQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyTW9udGg6IFszMSwgMjgsIDMxLCAzMCwgMzEsIDMwLCAzMSwgMzEsIDMwLCAzMSwgMzAsIDMxXSxcbiAgICAvKiogPGNvZGU+dHJ1ZTwvY29kZT4gaWYgaGFzIGEgeWVhciB6ZXJvLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAbWVtYmVyb2YgSnVsaWFuQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogMSxcbiAgICAvKiogVGhlIG1pbmltdW0gZGF5IG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBKdWxpYW5DYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnSnVsaWFuJyxcbiAgICAgICAgICAgIGVwb2NoczogWydCQycsICdBRCddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJyxcbiAgICAgICAgICAgICdKdWx5JywgJ0F1Z3VzdCcsICdTZXB0ZW1iZXInLCAnT2N0b2JlcicsICdOb3ZlbWJlcicsICdEZWNlbWJlciddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydTdW5kYXknLCAnTW9uZGF5JywgJ1R1ZXNkYXknLCAnV2VkbmVzZGF5JywgJ1RodXJzZGF5JywgJ0ZyaWRheScsICdTYXR1cmRheSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydTdW4nLCAnTW9uJywgJ1R1ZScsICdXZWQnLCAnVGh1JywgJ0ZyaScsICdTYXQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ1N1JywgJ01vJywgJ1R1JywgJ1dlJywgJ1RoJywgJ0ZyJywgJ1NhJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAnbW0vZGQveXl5eScsXG4gICAgICAgICAgICBmaXJzdERheTogMCxcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBKdWxpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHZhciB5ZWFyID0gKGRhdGUueWVhcigpIDwgMCA/IGRhdGUueWVhcigpICsgMSA6IGRhdGUueWVhcigpKTsgLy8gTm8geWVhciB6ZXJvXG4gICAgICAgIHJldHVybiAoeWVhciAlIDQpID09PSAwO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUgLSBJU08gODYwMS5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICAvLyBGaW5kIFRodXJzZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBNb25kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCg0IC0gKGNoZWNrRGF0ZS5kYXlPZldlZWsoKSB8fCA3KSwgJ2QnKTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGNoZWNrRGF0ZS5kYXlPZlllYXIoKSAtIDEpIC8gNykgKyAxO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBKdWxpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIG9mIHRoZSBtb250aC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIG1vbnRoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgbW9udGgveWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbih5ZWFyLCBtb250aCkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGgpO1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlzUGVyTW9udGhbZGF0ZS5tb250aCgpIC0gMV0gK1xuICAgICAgICAgICAgKGRhdGUubW9udGgoKSA9PT0gMiAmJiB0aGlzLmxlYXBZZWFyKGRhdGUueWVhcigpKSA/IDEgOiAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgSnVsaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBhIHdlZWsgZGF5LCBmYWxzZSBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gKHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpIHx8IDcpIDwgNjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBKdWxpYW4gZGF0ZSBlcXVpdmFsZW50IGZvciB0aGlzIGRhdGUsXG4gICAgICAgIGkuZS4gZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDQ3MTMgQkNFIEdyZWVud2ljaCBub29uLlxuICAgICAgICBAbWVtYmVyb2YgSnVsaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZXF1aXZhbGVudCBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0pEOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgbW9udGggPSBkYXRlLm1vbnRoKCk7XG4gICAgICAgIGRheSA9IGRhdGUuZGF5KCk7XG4gICAgICAgIGlmICh5ZWFyIDwgMCkgeyB5ZWFyKys7IH0gLy8gTm8geWVhciB6ZXJvXG4gICAgICAgIC8vIEplYW4gTWVldXMgYWxnb3JpdGhtLCBcIkFzdHJvbm9taWNhbCBBbGdvcml0aG1zXCIsIDE5OTFcbiAgICAgICAgaWYgKG1vbnRoIDw9IDIpIHtcbiAgICAgICAgICAgIHllYXItLTtcbiAgICAgICAgICAgIG1vbnRoICs9IDEyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKDM2NS4yNSAqICh5ZWFyICsgNDcxNikpICtcbiAgICAgICAgICAgIE1hdGguZmxvb3IoMzAuNjAwMSAqIChtb250aCArIDEpKSArIGRheSAtIDE1MjQuNTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIEp1bGlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBqZCB7bnVtYmVyfSBUaGUgSnVsaWFuIGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpEOiBmdW5jdGlvbihqZCkge1xuICAgICAgICAvLyBKZWFuIE1lZXVzIGFsZ29yaXRobSwgXCJBc3Ryb25vbWljYWwgQWxnb3JpdGhtc1wiLCAxOTkxXG4gICAgICAgIHZhciBhID0gTWF0aC5mbG9vcihqZCArIDAuNSk7XG4gICAgICAgIHZhciBiID0gYSArIDE1MjQ7XG4gICAgICAgIHZhciBjID0gTWF0aC5mbG9vcigoYiAtIDEyMi4xKSAvIDM2NS4yNSk7XG4gICAgICAgIHZhciBkID0gTWF0aC5mbG9vcigzNjUuMjUgKiBjKTtcbiAgICAgICAgdmFyIGUgPSBNYXRoLmZsb29yKChiIC0gZCkgLyAzMC42MDAxKTtcbiAgICAgICAgdmFyIG1vbnRoID0gZSAtIE1hdGguZmxvb3IoZSA8IDE0ID8gMSA6IDEzKTtcbiAgICAgICAgdmFyIHllYXIgPSBjIC0gTWF0aC5mbG9vcihtb250aCA+IDIgPyA0NzE2IDogNDcxNSk7XG4gICAgICAgIHZhciBkYXkgPSBiIC0gZCAtIE1hdGguZmxvb3IoMzAuNjAwMSAqIGUpO1xuICAgICAgICBpZiAoeWVhciA8PSAwKSB7IHllYXItLTsgfSAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICB9XG59KTtcblxuLy8gSnVsaWFuIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy5qdWxpYW4gPSBKdWxpYW5DYWxlbmRhcjtcblxuXG59LHtcIi4uL21haW5cIjo1NzEsXCJvYmplY3QtYXNzaWduXCI6NDU0fV0sNTY0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgTWF5YW4gY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEtlaXRoIFdvb2QgKHdvb2Qua2VpdGh7YXR9b3B0dXNuZXQuY29tLmF1KSBBdWd1c3QgMjAwOS5cbiAgIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIChodHRwOi8va2VpdGgtd29vZC5uYW1lL2xpY2VuY2UuaHRtbCkgbGljZW5zZS4gXG4gICBQbGVhc2UgYXR0cmlidXRlIHRoZSBhdXRob3IgaWYgeW91IHVzZSBpdC4gKi9cblxudmFyIG1haW4gPSBfZGVyZXFfKCcuLi9tYWluJyk7XG52YXIgYXNzaWduID0gX2RlcmVxXygnb2JqZWN0LWFzc2lnbicpO1xuXG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgTWF5YW4gTG9uZyBDb3VudCBjYWxlbmRhci5cbiAgICBTZWUgYWxzbyA8YSBocmVmPVwiaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NYXlhbl9jYWxlbmRhclwiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTWF5YW5fY2FsZW5kYXI8L2E+LlxuICAgIEBjbGFzcyBNYXlhbkNhbGVuZGFyXG4gICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgKGRlZmF1bHQgRW5nbGlzaCkgZm9yIGxvY2FsaXNhdGlvbi4gKi9cbmZ1bmN0aW9uIE1heWFuQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuTWF5YW5DYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihNYXlhbkNhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnTWF5YW4nLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBNYXlhbiBlcG9jaDogMTEgQXVndXN0IDMxMTQgQkNFLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhciAqL1xuICAgIGpkRXBvY2g6IDU4NDI4Mi41LFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyICovXG4gICAgaGFzWWVhclplcm86IHRydWUsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXIgKi9cbiAgICBtaW5Nb250aDogMCxcbiAgICAvKiogVGhlIGZpcnN0IG1vbnRoIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhciAqL1xuICAgIGZpcnN0TW9udGg6IDAsXG4gICAgLyoqIFRoZSBtaW5pbXVtIGRheSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyICovXG4gICAgbWluRGF5OiAwLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwcm9wZXJ0eSBuYW1lIHtzdHJpbmd9IFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAcHJvcGVydHkgZXBvY2hzIHtzdHJpbmdbXX0gVGhlIGVwb2NoIG5hbWVzLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNNaW4ge3N0cmluZ1tdfSBUaGUgbWluaW1hbCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRhdGVGb3JtYXQge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICAgICAgICAgIFNlZSB0aGUgb3B0aW9ucyBvbiA8YSBocmVmPVwiQmFzZUNhbGVuZGFyLmh0bWwjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgZGV0YWlscy5cbiAgICAgICAgQHByb3BlcnR5IGZpcnN0RGF5IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlaywgc3RhcnRpbmcgYXQgMC5cbiAgICAgICAgQHByb3BlcnR5IGlzUlRMIHtudW1iZXJ9IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgbG9jYWxpc2F0aW9uIHJlYWRzIHJpZ2h0LXRvLWxlZnQuXG4gICAgICAgIEBwcm9wZXJ0eSBoYWFiTW9udGhzIHtzdHJpbmdbXX0gVGhlIG5hbWVzIG9mIHRoZSBIYWFiIG1vbnRocy5cbiAgICAgICAgQHByb3BlcnR5IHR6b2xraW5Nb250aHMge3N0cmluZ1tdfSBUaGUgbmFtZXMgb2YgdGhlIFR6b2xraW4gbW9udGhzLiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnTWF5YW4nLFxuICAgICAgICAgICAgZXBvY2hzOiBbJycsICcnXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXM6IFsnMCcsICcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnLCAnOScsXG4gICAgICAgICAgICAnMTAnLCAnMTEnLCAnMTInLCAnMTMnLCAnMTQnLCAnMTUnLCAnMTYnLCAnMTcnXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydDogWycwJywgJzEnLCAnMicsICczJywgJzQnLCAnNScsICc2JywgJzcnLCAnOCcsICc5JyxcbiAgICAgICAgICAgICcxMCcsICcxMScsICcxMicsICcxMycsICcxNCcsICcxNScsICcxNicsICcxNyddLFxuICAgICAgICAgICAgZGF5TmFtZXM6IFsnMCcsICcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnLCAnOScsXG4gICAgICAgICAgICAnMTAnLCAnMTEnLCAnMTInLCAnMTMnLCAnMTQnLCAnMTUnLCAnMTYnLCAnMTcnLCAnMTgnLCAnMTknXSxcbiAgICAgICAgICAgIGRheU5hbWVzU2hvcnQ6IFsnMCcsICcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnLCAnOScsXG4gICAgICAgICAgICAnMTAnLCAnMTEnLCAnMTInLCAnMTMnLCAnMTQnLCAnMTUnLCAnMTYnLCAnMTcnLCAnMTgnLCAnMTknXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJzAnLCAnMScsICcyJywgJzMnLCAnNCcsICc1JywgJzYnLCAnNycsICc4JywgJzknLFxuICAgICAgICAgICAgJzEwJywgJzExJywgJzEyJywgJzEzJywgJzE0JywgJzE1JywgJzE2JywgJzE3JywgJzE4JywgJzE5J10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAnWVlZWS5tLmQnLFxuICAgICAgICAgICAgZmlyc3REYXk6IDAsXG4gICAgICAgICAgICBpc1JUTDogZmFsc2UsXG4gICAgICAgICAgICBoYWFiTW9udGhzOiBbJ1BvcCcsICdVbycsICdaaXAnLCAnWm90eicsICdUemVjJywgJ1h1bCcsICdZYXhraW4nLCAnTW9sJywgJ0NoZW4nLCAnWWF4JyxcbiAgICAgICAgICAgICdaYWMnLCAnQ2VoJywgJ01hYycsICdLYW5raW4nLCAnTXVhbicsICdQYXgnLCAnS2F5YWInLCAnQ3Vta3UnLCAnVWF5ZWInXSxcbiAgICAgICAgICAgIHR6b2xraW5Nb250aHM6IFsnSW1peCcsICdJaycsICdBa2JhbCcsICdLYW4nLCAnQ2hpY2NoYW4nLCAnQ2ltaScsICdNYW5paycsICdMYW1hdCcsICdNdWx1YycsICdPYycsXG4gICAgICAgICAgICAnQ2h1ZW4nLCAnRWInLCAnQmVuJywgJ0l4JywgJ01lbicsICdDaWInLCAnQ2FiYW4nLCAnRXR6bmFiJywgJ0NhdWFjJywgJ0FoYXUnXVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9LFxuXG4gICAgLyoqIEZvcm1hdCB0aGUgeWVhciwgaWYgbm90IGEgc2ltcGxlIHNlcXVlbnRpYWwgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBmb3JtYXQgb3IgdGhlIHllYXIgdG8gZm9ybWF0LlxuICAgICAgICBAcmV0dXJuIHtzdHJpbmd9IFRoZSBmb3JtYXR0ZWQgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBmb3JtYXRZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICB5ZWFyID0gZGF0ZS55ZWFyKCk7XG4gICAgICAgIHZhciBiYWt0dW4gPSBNYXRoLmZsb29yKHllYXIgLyA0MDApO1xuICAgICAgICB5ZWFyID0geWVhciAlIDQwMDtcbiAgICAgICAgeWVhciArPSAoeWVhciA8IDAgPyA0MDAgOiAwKTtcbiAgICAgICAgdmFyIGthdHVuID0gTWF0aC5mbG9vcih5ZWFyIC8gMjApO1xuICAgICAgICByZXR1cm4gYmFrdHVuICsgJy4nICsga2F0dW4gKyAnLicgKyAoeWVhciAlIDIwKTtcbiAgICB9LFxuXG4gICAgLyoqIENvbnZlcnQgZnJvbSB0aGUgZm9ybWF0dGVkIHllYXIgYmFjayB0byBhIHNpbmdsZSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFycyB7c3RyaW5nfSBUaGUgeWVhciBhcyBuLm4ubi5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgc2VxdWVudGlhbCB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgdmFsdWUgaXMgc3VwcGxpZWQuICovXG4gICAgZm9yWWVhcjogZnVuY3Rpb24oeWVhcnMpIHtcbiAgICAgICAgeWVhcnMgPSB5ZWFycy5zcGxpdCgnLicpO1xuICAgICAgICBpZiAoeWVhcnMubGVuZ3RoIDwgMykge1xuICAgICAgICAgICAgdGhyb3cgJ0ludmFsaWQgTWF5YW4geWVhcic7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHllYXIgPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHllYXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgeSA9IHBhcnNlSW50KHllYXJzW2ldLCAxMCk7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMoeSkgPiAxOSB8fCAoaSA+IDAgJiYgeSA8IDApKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgJ0ludmFsaWQgTWF5YW4geWVhcic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB5ZWFyID0geWVhciAqIDIwICsgeTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geWVhcjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgbW9udGhzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgbW9udGhzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIG1vbnRoc0luWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAxODtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB0aGUgd2VlayBvZiB0aGUgeWVhciBmb3IgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHJldHVybiAwO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cy5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5ZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuIDM2MDtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIG9mIHRoZSBtb250aC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIG1vbnRoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgbW9udGgveWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbih5ZWFyLCBtb250aCkge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgcmV0dXJuIDIwO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgd2Vlay5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMuICovXG4gICAgZGF5c0luV2VlazogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiA1OyAvLyBKdXN0IGZvciBmb3JtYXR0aW5nXG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgZGF5IG9mIHRoZSB3ZWVrIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGRheSBvZiB0aGUgd2VlazogMCB0byBudW1iZXIgb2YgZGF5cyAtIDEuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5T2ZXZWVrOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHJldHVybiBkYXRlLmRheSgpO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgd2VlayBkYXksIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIGFib3V0IGEgZGF0ZSAtIEhhYWIgYW5kIFR6b2xraW4gZXF1aXZhbGVudHMuXG4gICAgICAgIEBtZW1iZXJvZiBNYXlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge29iamVjdH0gQWRkaXRpb25hbCBpbmZvcm1hdGlvbiAtIGNvbnRlbnRzIGRlcGVuZHMgb24gY2FsZW5kYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZXh0cmFJbmZvOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHZhciBqZCA9IGRhdGUudG9KRCgpO1xuICAgICAgICB2YXIgaGFhYiA9IHRoaXMuX3RvSGFhYihqZCk7XG4gICAgICAgIHZhciB0em9sa2luID0gdGhpcy5fdG9Uem9sa2luKGpkKTtcbiAgICAgICAgcmV0dXJuIHtoYWFiTW9udGhOYW1lOiB0aGlzLmxvY2FsLmhhYWJNb250aHNbaGFhYlswXSAtIDFdLFxuICAgICAgICAgICAgaGFhYk1vbnRoOiBoYWFiWzBdLCBoYWFiRGF5OiBoYWFiWzFdLFxuICAgICAgICAgICAgdHpvbGtpbkRheU5hbWU6IHRoaXMubG9jYWwudHpvbGtpbk1vbnRoc1t0em9sa2luWzBdIC0gMV0sXG4gICAgICAgICAgICB0em9sa2luRGF5OiB0em9sa2luWzBdLCB0em9sa2luVHJlY2VuYTogdHpvbGtpblsxXX07XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSBIYWFiIGRhdGUgZnJvbSBhIEp1bGlhbiBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcHJpdmF0ZVxuICAgICAgICBAcGFyYW0gamQgIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyW119IENvcnJlc3BvbmRpbmcgSGFhYiBtb250aCBhbmQgZGF5LiAqL1xuICAgIF90b0hhYWI6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIGpkIC09IHRoaXMuamRFcG9jaDtcbiAgICAgICAgdmFyIGRheSA9IG1vZChqZCArIDggKyAoKDE4IC0gMSkgKiAyMCksIDM2NSk7XG4gICAgICAgIHJldHVybiBbTWF0aC5mbG9vcihkYXkgLyAyMCkgKyAxLCBtb2QoZGF5LCAyMCldO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgVHpvbGtpbiBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyW119IENvcnJlc3BvbmRpbmcgVHpvbGtpbiBkYXkgYW5kIHRyZWNlbmEuICovXG4gICAgX3RvVHpvbGtpbjogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgamQgLT0gdGhpcy5qZEVwb2NoO1xuICAgICAgICByZXR1cm4gW2Ftb2QoamQgKyAyMCwgMjApLCBhbW9kKGpkICsgNCwgMTMpXTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBKdWxpYW4gZGF0ZSBlcXVpdmFsZW50IGZvciB0aGlzIGRhdGUsXG4gICAgICAgIGkuZS4gZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDQ3MTMgQkNFIEdyZWVud2ljaCBub29uLlxuICAgICAgICBAbWVtYmVyb2YgTWF5YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgcmV0dXJuIGRhdGUuZGF5KCkgKyAoZGF0ZS5tb250aCgpICogMjApICsgKGRhdGUueWVhcigpICogMzYwKSArIHRoaXMuamRFcG9jaDtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIE1heWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIGpkID0gTWF0aC5mbG9vcihqZCkgKyAwLjUgLSB0aGlzLmpkRXBvY2g7XG4gICAgICAgIHZhciB5ZWFyID0gTWF0aC5mbG9vcihqZCAvIDM2MCk7XG4gICAgICAgIGpkID0gamQgJSAzNjA7XG4gICAgICAgIGpkICs9IChqZCA8IDAgPyAzNjAgOiAwKTtcbiAgICAgICAgdmFyIG1vbnRoID0gTWF0aC5mbG9vcihqZCAvIDIwKTtcbiAgICAgICAgdmFyIGRheSA9IGpkICUgMjA7XG4gICAgICAgIHJldHVybiB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgfVxufSk7XG5cbi8vIE1vZHVsdXMgZnVuY3Rpb24gd2hpY2ggd29ya3MgZm9yIG5vbi1pbnRlZ2Vycy5cbmZ1bmN0aW9uIG1vZChhLCBiKSB7XG4gICAgcmV0dXJuIGEgLSAoYiAqIE1hdGguZmxvb3IoYSAvIGIpKTtcbn1cblxuLy8gTW9kdWx1cyBmdW5jdGlvbiB3aGljaCByZXR1cm5zIG51bWVyYXRvciBpZiBtb2R1bHVzIGlzIHplcm8uXG5mdW5jdGlvbiBhbW9kKGEsIGIpIHtcbiAgICByZXR1cm4gbW9kKGEgLSAxLCBiKSArIDE7XG59XG5cbi8vIE1heWFuIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy5tYXlhbiA9IE1heWFuQ2FsZW5kYXI7XG5cblxufSx7XCIuLi9tYWluXCI6NTcxLFwib2JqZWN0LWFzc2lnblwiOjQ1NH1dLDU2NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKlxuICogV29ybGQgQ2FsZW5kYXJzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFyc1xuICpcbiAqIEJhdGNoLWNvbnZlcnRlZCBmcm9tIGtid29vZC9jYWxlbmRhcnNcbiAqIE1hbnkgdGhhbmtzIHRvIEtlaXRoIFdvb2QgYW5kIGFsbCBvZiB0aGUgY29udHJpYnV0b3JzIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0IVxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbi8qIGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvY2FsZW5kYXJzLmh0bWxcbiAgIE5hbmFrc2hhaGkgY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEtlaXRoIFdvb2QgKHdvb2Qua2VpdGh7YXR9b3B0dXNuZXQuY29tLmF1KSBKYW51YXJ5IDIwMTYuXG4gICBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCAoaHR0cDovL2tlaXRoLXdvb2QubmFtZS9saWNlbmNlLmh0bWwpIGxpY2Vuc2UuIFxuICAgUGxlYXNlIGF0dHJpYnV0ZSB0aGUgYXV0aG9yIGlmIHlvdSB1c2UgaXQuICovXG5cbnZhciBtYWluID0gX2RlcmVxXygnLi4vbWFpbicpO1xudmFyIGFzc2lnbiA9IF9kZXJlcV8oJ29iamVjdC1hc3NpZ24nKTtcblxuXG4vKiogSW1wbGVtZW50YXRpb24gb2YgdGhlIE5hbmFrc2hhaGkgY2FsZW5kYXIuXG4gICAgU2VlIGFsc28gPGEgaHJlZj1cImh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL05hbmFrc2hhaGlfY2FsZW5kYXJcIj5odHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9OYW5ha3NoYWhpX2NhbGVuZGFyPC9hPi5cbiAgICBAY2xhc3MgTmFuYWtzaGFoaUNhbGVuZGFyXG4gICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgKGRlZmF1bHQgRW5nbGlzaCkgZm9yIGxvY2FsaXNhdGlvbi4gKi9cbmZ1bmN0aW9uIE5hbmFrc2hhaGlDYWxlbmRhcihsYW5ndWFnZSkge1xuICAgIHRoaXMubG9jYWwgPSB0aGlzLnJlZ2lvbmFsT3B0aW9uc1tsYW5ndWFnZSB8fCAnJ10gfHwgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddO1xufVxuXG5OYW5ha3NoYWhpQ2FsZW5kYXIucHJvdG90eXBlID0gbmV3IG1haW4uYmFzZUNhbGVuZGFyO1xuXG52YXIgZ3JlZ29yaWFuID0gbWFpbi5pbnN0YW5jZSgnZ3JlZ29yaWFuJyk7XG5cbmFzc2lnbihOYW5ha3NoYWhpQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyICovXG4gICAgbmFtZTogJ05hbmFrc2hhaGknLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBOYW5ha3NoYWhpIGVwb2NoOiAxNCBNYXJjaCAxNDY5IENFLlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyICovXG4gICAgamRFcG9jaDogMjI1NzY3My41LFxuICAgIC8qKiBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyICovXG4gICAgZGF5c1Blck1vbnRoOiBbMzEsIDMxLCAzMSwgMzEsIDMxLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMF0sXG4gICAgLyoqIDxjb2RlPnRydWU8L2NvZGU+IGlmIGhhcyBhIHllYXIgemVybywgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQG1lbWJlcm9mIE5hbmFrc2hhaGlDYWxlbmRhciAqL1xuICAgIGhhc1llYXJaZXJvOiBmYWxzZSxcbiAgICAvKiogVGhlIG1pbmltdW0gbW9udGggbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE5hbmFrc2hhaGlDYWxlbmRhciAqL1xuICAgIGZpcnN0TW9udGg6IDEsXG4gICAgLyoqIFRoZSBtaW5pbXVtIGRheSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBOYW5ha3NoYWhpQ2FsZW5kYXIgKi9cbiAgICBtaW5EYXk6IDEsXG5cbiAgICAvKiogTG9jYWxpc2F0aW9ucyBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgRW50cmllcyBhcmUgb2JqZWN0cyBpbmRleGVkIGJ5IHRoZSBsYW5ndWFnZSBjb2RlICgnJyBiZWluZyB0aGUgZGVmYXVsdCBVUy9FbmdsaXNoKS5cbiAgICAgICAgRWFjaCBvYmplY3QgaGFzIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcy5cbiAgICAgICAgQG1lbWJlcm9mIE5hbmFrc2hhaGlDYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnTmFuYWtzaGFoaScsXG4gICAgICAgICAgICBlcG9jaHM6IFsnQk4nLCAnQU4nXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXM6IFsnQ2hldCcsICdWYWlzYWtoJywgJ0pldGgnLCAnSGFyaCcsICdTYXdhbicsICdCaGFkb24nLFxuICAgICAgICAgICAgJ0Fzc3UnLCAnS2F0YWsnLCAnTWFnaGFyJywgJ1BvaCcsICdNYWdoJywgJ1BoYWd1biddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ0NoZScsICdWYWknLCAnSmV0JywgJ0hhcicsICdTYXcnLCAnQmhhJywgJ0FzcycsICdLYXQnLCAnTWdyJywgJ1BvaCcsICdNZ2gnLCAnUGhhJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydTb212YWFyJywgJ01hbmdhbHZhcicsICdCdWRodmFhcicsICdWZWVydmFhcicsICdTaHVrYXJ2YWFyJywgJ1NhbmljaGFydmFhcicsICdFdHZhYXInXSxcbiAgICAgICAgICAgIGRheU5hbWVzU2hvcnQ6IFsnU29tJywgJ01hbmdhbCcsICdCdWRoJywgJ1ZlZXInLCAnU2h1a2FyJywgJ1NhbmljaGFyJywgJ0V0J10sXG4gICAgICAgICAgICBkYXlOYW1lc01pbjogWydTbycsICdNYScsICdCdScsICdWZScsICdTaCcsICdTYScsICdFdCddLFxuICAgICAgICAgICAgZGlnaXRzOiBudWxsLFxuICAgICAgICAgICAgZGF0ZUZvcm1hdDogJ2RkLW1tLXl5eXknLFxuICAgICAgICAgICAgZmlyc3REYXk6IDAsXG4gICAgICAgICAgICBpc1JUTDogZmFsc2VcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgTmFuYWtzaGFoaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LFxuICAgICAgICAgICAgbWFpbi5sb2NhbC5pbnZhbGlkWWVhciB8fCBtYWluLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gZ3JlZ29yaWFuLmxlYXBZZWFyKGRhdGUueWVhcigpICsgKGRhdGUueWVhcigpIDwgMSA/IDEgOiAwKSArIDE0NjkpO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBOYW5ha3NoYWhpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIC8vIEZpbmQgTW9uZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBNb25kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCgxIC0gKGNoZWNrRGF0ZS5kYXlPZldlZWsoKSB8fCA3KSwgJ2QnKTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGNoZWNrRGF0ZS5kYXlPZlllYXIoKSAtIDEpIC8gNykgKyAxO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBOYW5ha3NoYWhpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZE1vbnRoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5c1Blck1vbnRoW2RhdGUubW9udGgoKSAtIDFdICtcbiAgICAgICAgICAgIChkYXRlLm1vbnRoKCkgPT09IDEyICYmIHRoaXMubGVhcFllYXIoZGF0ZS55ZWFyKCkpID8gMSA6IDApO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBOYW5ha3NoYWhpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiAodGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgfHwgNykgPCA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBOYW5ha3NoYWhpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZXF1aXZhbGVudCBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0pEOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGgpO1xuICAgICAgICB2YXIgeWVhciA9IGRhdGUueWVhcigpO1xuICAgICAgICBpZiAoeWVhciA8IDApIHsgeWVhcisrOyB9IC8vIE5vIHllYXIgemVyb1xuICAgICAgICB2YXIgZG95ID0gZGF0ZS5kYXkoKTtcbiAgICAgICAgZm9yICh2YXIgbSA9IDE7IG0gPCBkYXRlLm1vbnRoKCk7IG0rKykge1xuICAgICAgICAgICAgZG95ICs9IHRoaXMuZGF5c1Blck1vbnRoW20gLSAxXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZG95ICsgZ3JlZ29yaWFuLnRvSkQoeWVhciArIDE0NjgsIDMsIDEzKTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIE5hbmFrc2hhaGlDYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24oamQpIHtcbiAgICAgICAgamQgPSBNYXRoLmZsb29yKGpkICsgMC41KTtcbiAgICAgICAgdmFyIHllYXIgPSBNYXRoLmZsb29yKChqZCAtICh0aGlzLmpkRXBvY2ggLSAxKSkgLyAzNjYpO1xuICAgICAgICB3aGlsZSAoamQgPj0gdGhpcy50b0pEKHllYXIgKyAxLCAxLCAxKSkge1xuICAgICAgICAgICAgeWVhcisrO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkYXkgPSBqZCAtIE1hdGguZmxvb3IodGhpcy50b0pEKHllYXIsIDEsIDEpICsgMC41KSArIDE7XG4gICAgICAgIHZhciBtb250aCA9IDE7XG4gICAgICAgIHdoaWxlIChkYXkgPiB0aGlzLmRheXNJbk1vbnRoKHllYXIsIG1vbnRoKSkge1xuICAgICAgICAgICAgZGF5IC09IHRoaXMuZGF5c0luTW9udGgoeWVhciwgbW9udGgpO1xuICAgICAgICAgICAgbW9udGgrKztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgIH1cbn0pO1xuXG4vLyBOYW5ha3NoYWhpIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy5uYW5ha3NoYWhpID0gTmFuYWtzaGFoaUNhbGVuZGFyO1xuXG5cbn0se1wiLi4vbWFpblwiOjU3MSxcIm9iamVjdC1hc3NpZ25cIjo0NTR9XSw1NjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBOZXBhbGkgY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEFydHVyIE5ldW1hbm4gKGljdC5wcm9qZWN0c3thdH1uZXBhbC5pbmYub3JnKSBBcHJpbCAyMDEzLlxuICAgQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgKGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvbGljZW5jZS5odG1sKSBsaWNlbnNlLiBcbiAgIFBsZWFzZSBhdHRyaWJ1dGUgdGhlIGF1dGhvciBpZiB5b3UgdXNlIGl0LiAqL1xuXG52YXIgbWFpbiA9IF9kZXJlcV8oJy4uL21haW4nKTtcbnZhciBhc3NpZ24gPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJyk7XG5cblxuLyoqIEltcGxlbWVudGF0aW9uIG9mIHRoZSBOZXBhbGkgY2l2aWwgY2FsZW5kYXIuXG4gICAgQmFzZWQgb24gdGhlIGlkZWFzIGZyb20gXG4gICAgPGEgaHJlZj1cImh0dHA6Ly9jb2RlaXNzdWUuY29tL2FydGljbGVzL2EwNGUwNTBkZWE3NDY4Zi9hbGdvcml0aG0tdG8tY29udmVydC1lbmdsaXNoLWRhdGUtdG8tbmVwYWxpLWRhdGUtdXNpbmctYy1uZXRcIj5odHRwOi8vY29kZWlzc3VlLmNvbS9hcnRpY2xlcy9hMDRlMDUwZGVhNzQ2OGYvYWxnb3JpdGhtLXRvLWNvbnZlcnQtZW5nbGlzaC1kYXRlLXRvLW5lcGFsaS1kYXRlLXVzaW5nLWMtbmV0PC9hPlxuICAgIGFuZCA8YSBocmVmPVwiaHR0cDovL2JpcmVuajJlZS5ibG9nc3BvdC5jb20vMjAxMS8wNC9uZXBhbGktY2FsZW5kYXItaW4tamF2YS5odG1sXCI+aHR0cDovL2JpcmVuajJlZS5ibG9nc3BvdC5jb20vMjAxMS8wNC9uZXBhbGktY2FsZW5kYXItaW4tamF2YS5odG1sPC9hPlxuICAgIFNlZSBhbHNvIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL05lcGFsaV9jYWxlbmRhclwiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTmVwYWxpX2NhbGVuZGFyPC9hPlxuICAgIGFuZCA8YSBocmVmPVwiaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQmlrcmFtX1NhbXdhdFwiPmh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jpa3JhbV9TYW13YXQ8L2E+LlxuICAgIEBjbGFzcyBOZXBhbGlDYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBOZXBhbGlDYWxlbmRhcihsYW5ndWFnZSkge1xuICAgIHRoaXMubG9jYWwgPSB0aGlzLnJlZ2lvbmFsT3B0aW9uc1tsYW5ndWFnZSB8fCAnJ10gfHwgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddO1xufVxuXG5OZXBhbGlDYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihOZXBhbGlDYWxlbmRhci5wcm90b3R5cGUsIHtcbiAgICAvKiogVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBtZW1iZXJvZiBOZXBhbGlDYWxlbmRhciAqL1xuICAgIG5hbWU6ICdOZXBhbGknLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBOZXBhbGkgZXBvY2g6IDE0IEFwcmlsIDU3IEJDRS5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyICovXG4gICAgamRFcG9jaDogMTcwMDcwOS41LFxuICAgIC8qKiBEYXlzIHBlciBtb250aCBpbiBhIGNvbW1vbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyTW9udGg6IFszMSwgMzEsIDMyLCAzMiwgMzEsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzAsIDMwXSxcbiAgICAvKiogPGNvZGU+dHJ1ZTwvY29kZT4gaWYgaGFzIGEgeWVhciB6ZXJvLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogMSxcbiAgICAvKiogVGhlIG1pbmltdW0gZGF5IG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLCBcbiAgICAvKiogVGhlIG51bWJlciBvZiBkYXlzIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyWWVhcjogMzY1LFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBOZXBhbGlDYWxlbmRhclxuICAgICAgICBAcHJvcGVydHkgbmFtZSB7c3RyaW5nfSBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQHByb3BlcnR5IGVwb2NocyB7c3RyaW5nW119IFRoZSBlcG9jaCBuYW1lcy5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzTWluIHtzdHJpbmdbXX0gVGhlIG1pbmltYWwgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXRlRm9ybWF0IHtzdHJpbmd9IFRoZSBkYXRlIGZvcm1hdCBmb3IgdGhpcyBjYWxlbmRhci5cbiAgICAgICAgICAgICAgICBTZWUgdGhlIG9wdGlvbnMgb24gPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4gZm9yIGRldGFpbHMuXG4gICAgICAgIEBwcm9wZXJ0eSBmaXJzdERheSB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWssIHN0YXJ0aW5nIGF0IDAuXG4gICAgICAgIEBwcm9wZXJ0eSBpc1JUTCB7bnVtYmVyfSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGxvY2FsaXNhdGlvbiByZWFkcyByaWdodC10by1sZWZ0LiAqL1xuICAgIHJlZ2lvbmFsT3B0aW9uczogeyAvLyBMb2NhbGlzYXRpb25zXG4gICAgICAgICcnOiB7XG4gICAgICAgICAgICBuYW1lOiAnTmVwYWxpJyxcbiAgICAgICAgICAgIGVwb2NoczogWydCQlMnLCAnQUJTJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBbJ0JhaXNha2gnLCAnSmVzdGhhJywgJ0FzaGFkaCcsICdTaHJhd2FuJywgJ0JoYWRyYScsICdBc2h3aW4nLFxuICAgICAgICAgICAgJ0thcnRpaycsICdNYW5nc2lyJywgJ1BhdXNoJywgJ01hbmdoJywgJ0ZhbGd1bicsICdDaGFpdHJhJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzU2hvcnQ6IFsnQmFpJywgJ0plJywgJ0FzJywgJ1NocmEnLCAnQmhhJywgJ0FzaCcsICdLYXInLCAnTWFuZycsICdQYXUnLCAnTWEnLCAnRmFsJywgJ0NoYWknXSxcbiAgICAgICAgICAgIGRheU5hbWVzOiBbJ0FhaXRhYmFhcicsICdTb21iYWFyJywgJ01hbmdsYmFhcicsICdCdWRoYWJhYXInLCAnQmloaWJhYXInLCAnU2h1a3JhYmFhcicsICdTaGFuaWJhYXInXSxcbiAgICAgICAgICAgIGRheU5hbWVzU2hvcnQ6IFsnQWFpdGEnLCAnU29tJywgJ01hbmdsJywgJ0J1ZGhhJywgJ0JpaGknLCAnU2h1a3JhJywgJ1NoYW5pJ10sXG4gICAgICAgICAgICBkYXlOYW1lc01pbjogWydBYWknLCAnU28nLCAnTWFuJywgJ0J1JywgJ0JpJywgJ1NodScsICdTaGEnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICdkZC9tbS95eXl5JyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiAxLFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBpbiBhIGxlYXAgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBpcyBhIGxlYXAgeWVhciwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBsZWFwWWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlzSW5ZZWFyKHllYXIpICE9PSB0aGlzLmRheXNQZXJZZWFyO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBOZXBhbGlDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgLy8gRmluZCBTdW5kYXkgb2YgdGhpcyB3ZWVrIHN0YXJ0aW5nIG9uIFN1bmRheVxuICAgICAgICB2YXIgY2hlY2tEYXRlID0gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgICAgICBjaGVja0RhdGUuYWRkKC1jaGVja0RhdGUuZGF5T2ZXZWVrKCksICdkJyk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKChjaGVja0RhdGUuZGF5T2ZZZWFyKCkgLSAxKSAvIDcpICsgMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBOZXBhbGlDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJblllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkWWVhcik7XG4gICAgICAgIHllYXIgPSBkYXRlLnllYXIoKTtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLk5FUEFMSV9DQUxFTkRBUl9EQVRBW3llYXJdID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF5c1BlclllYXI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRheXNQZXJZZWFyID0gMDtcbiAgICAgICAgZm9yICh2YXIgbW9udGhfbnVtYmVyID0gdGhpcy5taW5Nb250aDsgbW9udGhfbnVtYmVyIDw9IDEyOyBtb250aF9udW1iZXIrKykge1xuICAgICAgICAgICAgZGF5c1BlclllYXIgKz0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVt5ZWFyXVttb250aF9udW1iZXJdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkYXlzUGVyWWVhcjtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcnwgVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgaWYgKHllYXIueWVhcikge1xuICAgICAgICAgICAgbW9udGggPSB5ZWFyLm1vbnRoKCk7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiAodHlwZW9mIHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbeWVhcl0gPT09ICd1bmRlZmluZWQnID9cbiAgICAgICAgICAgIHRoaXMuZGF5c1Blck1vbnRoW21vbnRoIC0gMV0gOiB0aGlzLk5FUEFMSV9DQUxFTkRBUl9EQVRBW3llYXJdW21vbnRoXSk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgYSB3ZWVrIGRheS5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgd2VlayBkYXksIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgIT09IDY7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgSnVsaWFuIGRhdGUgZXF1aXZhbGVudCBmb3IgdGhpcyBkYXRlLFxuICAgICAgICBpLmUuIGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbi5cbiAgICAgICAgQG1lbWJlcm9mIE5lcGFsaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24obmVwYWxpWWVhciwgbmVwYWxpTW9udGgsIG5lcGFsaURheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKG5lcGFsaVllYXIsIG5lcGFsaU1vbnRoLCBuZXBhbGlEYXksIG1haW4ubG9jYWwuaW52YWxpZERhdGUpO1xuICAgICAgICBuZXBhbGlZZWFyID0gZGF0ZS55ZWFyKCk7XG4gICAgICAgIG5lcGFsaU1vbnRoID0gZGF0ZS5tb250aCgpO1xuICAgICAgICBuZXBhbGlEYXkgPSBkYXRlLmRheSgpO1xuICAgICAgICB2YXIgZ3JlZ29yaWFuQ2FsZW5kYXIgPSBtYWluLmluc3RhbmNlKCk7XG4gICAgICAgIHZhciBncmVnb3JpYW5EYXlPZlllYXIgPSAwOyAvLyBXZSB3aWxsIGFkZCBhbGwgdGhlIGRheXMgdGhhdCB3ZW50IGJ5IHNpbmNlXG4gICAgICAgIC8vIHRoZSAxc3QuIEphbnVhcnkgYW5kIHRoZW4gd2UgY2FuIGdldCB0aGUgR3JlZ29yaWFuIERhdGVcbiAgICAgICAgdmFyIG5lcGFsaU1vbnRoVG9DaGVjayA9IG5lcGFsaU1vbnRoO1xuICAgICAgICB2YXIgbmVwYWxpWWVhclRvQ2hlY2sgPSBuZXBhbGlZZWFyO1xuICAgICAgICB0aGlzLl9jcmVhdGVNaXNzaW5nQ2FsZW5kYXJEYXRhKG5lcGFsaVllYXIpO1xuICAgICAgICAvLyBHZXQgdGhlIGNvcnJlY3QgeWVhclxuICAgICAgICB2YXIgZ3JlZ29yaWFuWWVhciA9IG5lcGFsaVllYXIgLSAobmVwYWxpTW9udGhUb0NoZWNrID4gOSB8fCAobmVwYWxpTW9udGhUb0NoZWNrID09PSA5ICYmXG4gICAgICAgICAgICBuZXBhbGlEYXkgPj0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyVG9DaGVja11bMF0pID8gNTYgOiA1Nyk7XG4gICAgICAgIC8vIEZpcnN0IHdlIGFkZCB0aGUgYW1vdW50IG9mIGRheXMgaW4gdGhlIGFjdHVhbCBOZXBhbGkgbW9udGggYXMgdGhlIGRheSBvZiB5ZWFyIGluIHRoZVxuICAgICAgICAvLyBHcmVnb3JpYW4gb25lIGJlY2F1c2UgYXQgbGVhc3QgdGhpcyBkYXlzIGFyZSBnb25lIHNpbmNlIHRoZSAxc3QuIEphbi4gXG4gICAgICAgIGlmIChuZXBhbGlNb250aCAhPT0gOSkge1xuICAgICAgICAgICAgZ3JlZ29yaWFuRGF5T2ZZZWFyID0gbmVwYWxpRGF5O1xuICAgICAgICAgICAgbmVwYWxpTW9udGhUb0NoZWNrLS07XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm93IHdlIGxvb3AgdGhyb3cgYWxsIE5lcGFsaSBtb250aCBhbmQgYWRkIHRoZSBhbW91bnQgb2YgZGF5cyB0byBncmVnb3JpYW5EYXlPZlllYXIgXG4gICAgICAgIC8vIHdlIGRvIHRoaXMgdGlsbCB3ZSByZWFjaCBQYXVzaCAoOXRoIG1vbnRoKS4gMXN0LiBKYW51YXJ5IGFsd2F5cyBmYWxscyBpbiB0aGlzIG1vbnRoICBcbiAgICAgICAgd2hpbGUgKG5lcGFsaU1vbnRoVG9DaGVjayAhPT0gOSkge1xuICAgICAgICAgICAgaWYgKG5lcGFsaU1vbnRoVG9DaGVjayA8PSAwKSB7XG4gICAgICAgICAgICAgICAgbmVwYWxpTW9udGhUb0NoZWNrID0gMTI7XG4gICAgICAgICAgICAgICAgbmVwYWxpWWVhclRvQ2hlY2stLTtcbiAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICBncmVnb3JpYW5EYXlPZlllYXIgKz0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyVG9DaGVja11bbmVwYWxpTW9udGhUb0NoZWNrXTtcbiAgICAgICAgICAgIG5lcGFsaU1vbnRoVG9DaGVjay0tO1xuICAgICAgICB9ICAgICAgICBcbiAgICAgICAgLy8gSWYgdGhlIGRhdGUgdGhhdCBoYXMgdG8gYmUgY29udmVydGVkIGlzIGluIFBhdXNoIChtb250aCBuby4gOSkgd2UgaGF2ZSB0byBkbyBzb21lIG90aGVyIGNhbGN1bGF0aW9uXG4gICAgICAgIGlmIChuZXBhbGlNb250aCA9PT0gOSkge1xuICAgICAgICAgICAgLy8gQWRkIHRoZSBkYXlzIHRoYXQgYXJlIHBhc3NlZCBzaW5jZSB0aGUgZmlyc3QgZGF5IG9mIFBhdXNoIGFuZCBzdWJzdHJhY3QgdGhlXG4gICAgICAgICAgICAvLyBhbW91bnQgb2YgZGF5cyB0aGF0IGxpZSBiZXR3ZWVuIDFzdC4gSmFuIGFuZCAxc3QgUGF1c2hcbiAgICAgICAgICAgIGdyZWdvcmlhbkRheU9mWWVhciArPSBuZXBhbGlEYXkgLSB0aGlzLk5FUEFMSV9DQUxFTkRBUl9EQVRBW25lcGFsaVllYXJUb0NoZWNrXVswXTtcbiAgICAgICAgICAgIC8vIEZvciB0aGUgZmlyc3QgZGF5cyBvZiBQYXVzaCB3ZSBhcmUgbm93IGluIG5lZ2F0aXZlIHZhbHVlcyxcbiAgICAgICAgICAgIC8vIGJlY2F1c2UgaW4gdGhlIGVuZCBvZiB0aGUgZ3JlZ29yaWFuIHllYXIgd2Ugc3Vic3RyYWN0XG4gICAgICAgICAgICAvLyAzNjUgLyAzNjYgZGF5cyAoUC5TLiByZW1lbWJlciBtYXRoIGluIHNjaG9vbCArIC0gZ2l2ZXMgLSlcbiAgICAgICAgICAgIGlmIChncmVnb3JpYW5EYXlPZlllYXIgPCAwKSB7XG4gICAgICAgICAgICAgICAgZ3JlZ29yaWFuRGF5T2ZZZWFyICs9IGdyZWdvcmlhbkNhbGVuZGFyLmRheXNJblllYXIoZ3JlZ29yaWFuWWVhcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBncmVnb3JpYW5EYXlPZlllYXIgKz0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyVG9DaGVja11bOV0gLVxuICAgICAgICAgICAgICAgIHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbbmVwYWxpWWVhclRvQ2hlY2tdWzBdO1xuICAgICAgICB9ICAgICAgICBcbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbkNhbGVuZGFyLm5ld0RhdGUoZ3JlZ29yaWFuWWVhciwgMSAsMSkuYWRkKGdyZWdvcmlhbkRheU9mWWVhciwgJ2QnKS50b0pEKCk7XG4gICAgfSxcbiAgICBcbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIEp1bGlhbiBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgTmVwYWxpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIHZhciBncmVnb3JpYW5DYWxlbmRhciA9ICBtYWluLmluc3RhbmNlKCk7XG4gICAgICAgIHZhciBncmVnb3JpYW5EYXRlID0gZ3JlZ29yaWFuQ2FsZW5kYXIuZnJvbUpEKGpkKTtcbiAgICAgICAgdmFyIGdyZWdvcmlhblllYXIgPSBncmVnb3JpYW5EYXRlLnllYXIoKTtcbiAgICAgICAgdmFyIGdyZWdvcmlhbkRheU9mWWVhciA9IGdyZWdvcmlhbkRhdGUuZGF5T2ZZZWFyKCk7XG4gICAgICAgIHZhciBuZXBhbGlZZWFyID0gZ3JlZ29yaWFuWWVhciArIDU2OyAvL3RoaXMgaXMgbm90IGZpbmFsLCBpdCBjb3VsZCBiZSBhbHNvICs1NyBidXQgKzU2IGlzIGFsd2F5cyB0cnVlIGZvciAxc3QgSmFuLlxuICAgICAgICB0aGlzLl9jcmVhdGVNaXNzaW5nQ2FsZW5kYXJEYXRhKG5lcGFsaVllYXIpO1xuICAgICAgICB2YXIgbmVwYWxpTW9udGggPSA5OyAvLyBKYW4gMSBhbHdheXMgZmFsbCBpbiBOZXBhbGkgbW9udGggUGF1c2ggd2hpY2ggaXMgdGhlIDl0aCBtb250aCBvZiBOZXBhbGkgY2FsZW5kYXIuXG4gICAgICAgIC8vIEdldCB0aGUgTmVwYWxpIGRheSBpbiBQYXVzaCAobW9udGggOSkgb2YgMXN0IEphbnVhcnkgXG4gICAgICAgIHZhciBkYXlPZkZpcnN0SmFuSW5QYXVzaCA9IHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbbmVwYWxpWWVhcl1bMF07XG4gICAgICAgIC8vIENoZWNrIGhvdyBtYW55IGRheXMgYXJlIGxlZnQgb2YgUGF1c2ggLlxuICAgICAgICAvLyBEYXlzIGNhbGN1bGF0ZWQgZnJvbSAxc3QgSmFuIHRpbGwgdGhlIGVuZCBvZiB0aGUgYWN0dWFsIE5lcGFsaSBtb250aCwgXG4gICAgICAgIC8vIHdlIHVzZSB0aGlzIHZhbHVlIHRvIGNoZWNrIGlmIHRoZSBncmVnb3JpYW4gRGF0ZSBpcyBpbiB0aGUgYWN0dWFsIE5lcGFsaSBtb250aC5cbiAgICAgICAgdmFyIGRheXNTaW5jZUphbkZpcnN0VG9FbmRPZk5lcGFsaU1vbnRoID1cbiAgICAgICAgICAgIHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbbmVwYWxpWWVhcl1bbmVwYWxpTW9udGhdIC0gZGF5T2ZGaXJzdEphbkluUGF1c2ggKyAxO1xuICAgICAgICAvLyBJZiB0aGUgZ3JlZ29yaWFuIGRheS1vZi15ZWFyIGlzIHNtYWxsZXIgbyBlcXVhbCB0aGFuIHRoZSBzdW0gb2YgZGF5cyBiZXR3ZWVuIHRoZSAxc3QgSmFudWFyeSBhbmQgXG4gICAgICAgIC8vIHRoZSBlbmQgb2YgdGhlIGFjdHVhbCBuZXBhbGkgbW9udGggd2UgZm91bmQgdGhlIGNvcnJlY3QgbmVwYWxpIG1vbnRoLlxuICAgICAgICAvLyBFeGFtcGxlOiBcbiAgICAgICAgLy8gVGhlIDR0aCBGZWJydWFyeSAyMDExIGlzIHRoZSBncmVnb3JpYW5EYXlPZlllYXIgMzUgKDMxIGRheXMgb2YgSmFudWFyeSArIDQpXG4gICAgICAgIC8vIDFzdCBKYW51YXJ5IDIwMTEgaXMgaW4gdGhlIG5lcGFsaSB5ZWFyIDIwNjcsIHdoZXJlIDFzdC4gSmFudWFyeSBpcyBpbiB0aGUgMTd0aCBkYXkgb2YgUGF1c2ggKDl0aCBtb250aClcbiAgICAgICAgLy8gSW4gMjA2NyBQYXVzaCBoYXMgMzBkYXlzLCBUaGlzIG1lYW5zICgzMC0xNysxPTE0KSB0aGVyZSBhcmUgMTRkYXlzIGJldHdlZW4gMXN0IEphbnVhcnkgYW5kIGVuZCBvZiBQYXVzaCBcbiAgICAgICAgLy8gKGluY2x1ZGluZyAxN3RoIEphbnVhcnkpXG4gICAgICAgIC8vIFRoZSBncmVnb3JpYW5EYXlPZlllYXIgKDM1KSBpcyBiaWdnZXIgdGhhbiAxNCwgc28gd2UgY2hlY2sgdGhlIG5leHQgbW9udGhcbiAgICAgICAgLy8gVGhlIG5leHQgbmVwYWxpIG1vbnRoIChNYW5naCkgaGFzIDI5IGRheXMgXG4gICAgICAgIC8vIDI5KzE0PTQzLCB0aGlzIGlzIGJpZ2dlciB0aGFuIGdyZWdvcmlhbkRheU9mWWVhcigzNSkgc28sIHdlIGZvdW5kIHRoZSBjb3JyZWN0IG5lcGFsaSBtb250aFxuICAgICAgICB3aGlsZSAoZ3JlZ29yaWFuRGF5T2ZZZWFyID4gZGF5c1NpbmNlSmFuRmlyc3RUb0VuZE9mTmVwYWxpTW9udGgpIHtcbiAgICAgICAgICAgIG5lcGFsaU1vbnRoKys7XG4gICAgICAgICAgICBpZiAobmVwYWxpTW9udGggPiAxMikge1xuICAgICAgICAgICAgICAgIG5lcGFsaU1vbnRoID0gMTtcbiAgICAgICAgICAgICAgICBuZXBhbGlZZWFyKys7XG4gICAgICAgICAgICB9ICAgIFxuICAgICAgICAgICAgZGF5c1NpbmNlSmFuRmlyc3RUb0VuZE9mTmVwYWxpTW9udGggKz0gdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyXVtuZXBhbGlNb250aF07XG4gICAgICAgIH1cbiAgICAgICAgLy8gVGhlIGxhc3Qgc3RlcCBpcyB0byBjYWxjdWxhdGUgdGhlIG5lcGFsaSBkYXktb2YtbW9udGhcbiAgICAgICAgLy8gdG8gY29udGludWUgb3VyIGV4YW1wbGUgZnJvbSBiZWZvcmU6XG4gICAgICAgIC8vIHdlIGNhbGN1bGF0ZWQgdGhlcmUgYXJlIDQzIGRheXMgZnJvbSAxc3QuIEphbnVhcnkgKDE3IFBhdXNoKSB0aWxsIGVuZCBvZiBNYW5naCAoMjkgZGF5cylcbiAgICAgICAgLy8gd2hlbiB3ZSBzdWJ0cmFjdCBmcm9tIHRoaXMgNDMgZGF5cyB0aGUgZGF5LW9mLXllYXIgb2YgdGhlIHRoZSBHcmVnb3JpYW4gZGF0ZSAoMzUpLFxuICAgICAgICAvLyB3ZSBrbm93IGhvdyBmYXIgdGhlIHNlYXJjaGVkIGRheSBpcyBhd2F5IGZyb20gdGhlIGVuZCBvZiB0aGUgTmVwYWxpIG1vbnRoLlxuICAgICAgICAvLyBTbyB3ZSBzaW1wbHkgc3VidHJhY3QgdGhpcyBudW1iZXIgZnJvbSB0aGUgYW1vdW50IG9mIGRheXMgaW4gdGhpcyBtb250aCAoMzApIFxuICAgICAgICB2YXIgbmVwYWxpRGF5T2ZNb250aCA9IHRoaXMuTkVQQUxJX0NBTEVOREFSX0RBVEFbbmVwYWxpWWVhcl1bbmVwYWxpTW9udGhdIC1cbiAgICAgICAgICAgIChkYXlzU2luY2VKYW5GaXJzdFRvRW5kT2ZOZXBhbGlNb250aCAtIGdyZWdvcmlhbkRheU9mWWVhcik7ICAgICAgICBcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZShuZXBhbGlZZWFyLCBuZXBhbGlNb250aCwgbmVwYWxpRGF5T2ZNb250aCk7XG4gICAgfSxcbiAgICBcbiAgICAvKiogQ3JlYXRlcyBtaXNzaW5nIGRhdGEgaW4gdGhlIE5FUEFMSV9DQUxFTkRBUl9EQVRBIHRhYmxlLlxuICAgICAgICBUaGlzIGRhdGEgd2lsbCBub3QgYmUgY29ycmVjdCBidXQganVzdCBnaXZlIGFuIGVzdGltYXRlZCByZXN1bHQuIE1vc3RseSAtLysgMSBkYXlcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIG5lcGFsaVllYXIge251bWJlcn0gVGhlIG1pc3NpbmcgeWVhciBudW1iZXIuICovXG4gICAgX2NyZWF0ZU1pc3NpbmdDYWxlbmRhckRhdGE6IGZ1bmN0aW9uKG5lcGFsaVllYXIpIHtcbiAgICAgICAgdmFyIHRtcF9jYWxlbmRhcl9kYXRhID0gdGhpcy5kYXlzUGVyTW9udGguc2xpY2UoMCk7XG4gICAgICAgIHRtcF9jYWxlbmRhcl9kYXRhLnVuc2hpZnQoMTcpO1xuICAgICAgICBmb3IgKHZhciBuZXBhbGlZZWFyVG9DcmVhdGUgPSAobmVwYWxpWWVhciAtIDEpOyBuZXBhbGlZZWFyVG9DcmVhdGUgPCAobmVwYWxpWWVhciArIDIpOyBuZXBhbGlZZWFyVG9DcmVhdGUrKykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLk5FUEFMSV9DQUxFTkRBUl9EQVRBW25lcGFsaVllYXJUb0NyZWF0ZV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ORVBBTElfQ0FMRU5EQVJfREFUQVtuZXBhbGlZZWFyVG9DcmVhdGVdID0gdG1wX2NhbGVuZGFyX2RhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIFxuICAgIE5FUEFMSV9DQUxFTkRBUl9EQVRBOiAge1xuICAgICAgICAvLyBUaGVzZSBkYXRhIGFyZSBmcm9tIGh0dHA6Ly93d3cuYXNoZXNoLmNvbS5ucFxuICAgICAgICAxOTcwOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTcxOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMiwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTcyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTczOiBbMTksIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAxOTc0OiBbMTksIDMxLCAzMSwgMzIsIDMwLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTc1OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMCwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTc2OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAxOTc3OiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAxOTc4OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTc5OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTgwOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAxOTgxOiBbMTgsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTgyOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTgzOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTg0OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAxOTg1OiBbMTgsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTg2OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTg3OiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTg4OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAxOTg5OiBbMTgsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTkwOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTkxOiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLCAgICBcbiAgICAgICAgLy8gVGhlc2UgZGF0YSBhcmUgZnJvbSBodHRwOi8vbmVwYWxpY2FsZW5kYXIucmF0MzIuY29tL2luZGV4LnBocFxuICAgICAgICAxOTkyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAxOTkzOiBbMTgsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk0OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk1OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk2OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAxOTk3OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk4OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAxOTk5OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDAwOiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDAxOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDAyOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDAzOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDA0OiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDA1OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDA2OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDA3OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDA4OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAyOSwgMzFdLFxuICAgICAgICAyMDA5OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDEwOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDExOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDEyOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDEzOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE0OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE1OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDE2OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE3OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE4OiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDE5OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDIwOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDIxOiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDIyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDIzOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDI0OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDI1OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDI2OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDI3OiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDI4OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDI5OiBbMTgsIDMxLCAzMSwgMzIsIDMxLCAzMiwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDMwOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMzAsIDMwLCAzMCwgMzFdLFxuICAgICAgICAyMDMxOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzEsIDMxLCAzMSwgMzEsIDMxLCAzMSwgMzFdLFxuICAgICAgICAyMDMyOiBbMTcsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzIsIDMyLCAzMiwgMzJdLFxuICAgICAgICAyMDMzOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDM0OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDM1OiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAyOSwgMzFdLFxuICAgICAgICAyMDM2OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDM3OiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDM4OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDM5OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQwOiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQxOiBbMTgsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDQzOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ0OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ1OiBbMTgsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ2OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDQ3OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ4OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDQ5OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDUwOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDUxOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDUyOiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDUzOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDU0OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDU1OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDMwLCAyOSwgMzBdLFxuICAgICAgICAyMDU2OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMiwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDU3OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDU4OiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDU5OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDYwOiBbMTcsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDYxOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDYyOiBbMTcsIDMwLCAzMiwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDYzOiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDY0OiBbMTcsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDY1OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDY2OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAyOSwgMzFdLFxuICAgICAgICAyMDY3OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDY4OiBbMTcsIDMxLCAzMSwgMzIsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDY5OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDcwOiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDI5LCAzMCwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDcxOiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDcyOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDczOiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzFdLFxuICAgICAgICAyMDc0OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDc1OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDc2OiBbMTYsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDc3OiBbMTcsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDMwLCAyOSwgMzFdLFxuICAgICAgICAyMDc4OiBbMTcsIDMxLCAzMSwgMzEsIDMyLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDc5OiBbMTcsIDMxLCAzMSwgMzIsIDMxLCAzMSwgMzEsIDMwLCAyOSwgMzAsIDI5LCAzMCwgMzBdLFxuICAgICAgICAyMDgwOiBbMTYsIDMxLCAzMiwgMzEsIDMyLCAzMSwgMzAsIDMwLCAzMCwgMjksIDI5LCAzMCwgMzBdLFxuICAgICAgICAvLyBUaGVzZSBkYXRhIGFyZSBmcm9tIGh0dHA6Ly93d3cuYXNoZXNoLmNvbS5ucC9uZXBhbGktY2FsZW5kYXIvXG4gICAgICAgIDIwODE6IFsxNywgMzEsIDMxLCAzMiwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODI6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODM6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODQ6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODU6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODY6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODc6IFsxNiwgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODg6IFsxNiwgMzAsIDMxLCAzMiwgMzIsIDMwLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwODk6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTA6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTE6IFsxNiwgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTI6IFsxNiwgMzEsIDMxLCAzMiwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTM6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTQ6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTU6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMzAsIDI5LCAzMCwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTY6IFsxNywgMzAsIDMxLCAzMiwgMzIsIDMxLCAzMCwgMzAsIDI5LCAzMCwgMjksIDMwLCAzMF0sXG4gICAgICAgIDIwOTc6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMxLCAzMCwgMzAsIDMwLCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIwOTg6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMjksIDMwLCAyOSwgMzAsIDMwLCAzMV0sXG4gICAgICAgIDIwOTk6IFsxNywgMzEsIDMxLCAzMiwgMzEsIDMxLCAzMSwgMzAsIDI5LCAyOSwgMzAsIDMwLCAzMF0sXG4gICAgICAgIDIxMDA6IFsxNywgMzEsIDMyLCAzMSwgMzIsIDMwLCAzMSwgMzAsIDI5LCAzMCwgMjksIDMwLCAzMF0gICAgXG4gICAgfVxufSk7ICAgIFxuXG4vLyBOZXBhbGkgY2FsZW5kYXIgaW1wbGVtZW50YXRpb25cbm1haW4uY2FsZW5kYXJzLm5lcGFsaSA9IE5lcGFsaUNhbGVuZGFyO1xuXG5cbn0se1wiLi4vbWFpblwiOjU3MSxcIm9iamVjdC1hc3NpZ25cIjo0NTR9XSw1Njc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBQZXJzaWFuIGNhbGVuZGFyIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBLZWl0aCBXb29kICh3b29kLmtlaXRoe2F0fW9wdHVzbmV0LmNvbS5hdSkgQXVndXN0IDIwMDkuXG4gICBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCAoaHR0cDovL2tlaXRoLXdvb2QubmFtZS9saWNlbmNlLmh0bWwpIGxpY2Vuc2UuIFxuICAgUGxlYXNlIGF0dHJpYnV0ZSB0aGUgYXV0aG9yIGlmIHlvdSB1c2UgaXQuICovXG5cbnZhciBtYWluID0gX2RlcmVxXygnLi4vbWFpbicpO1xudmFyIGFzc2lnbiA9IF9kZXJlcV8oJ29iamVjdC1hc3NpZ24nKTtcblxuXG4vKiogSW1wbGVtZW50YXRpb24gb2YgdGhlIFBlcnNpYW4gb3IgSmFsYWxpIGNhbGVuZGFyLlxuICAgIEJhc2VkIG9uIGNvZGUgZnJvbSA8YSBocmVmPVwiaHR0cDovL3d3dy5pcmFuY2hhbWJlci5jb20vY2FsZW5kYXIvY29udmVydGVyL2lyYW5pYW5fY2FsZW5kYXJfY29udmVydGVyLnBocFwiPmh0dHA6Ly93d3cuaXJhbmNoYW1iZXIuY29tL2NhbGVuZGFyL2NvbnZlcnRlci9pcmFuaWFuX2NhbGVuZGFyX2NvbnZlcnRlci5waHA8L2E+LlxuICAgIFNlZSBhbHNvIDxhIGhyZWY9XCJodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lyYW5pYW5fY2FsZW5kYXJcIj5odHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lyYW5pYW5fY2FsZW5kYXI8L2E+LlxuICAgIEBjbGFzcyBQZXJzaWFuQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gUGVyc2lhbkNhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cblBlcnNpYW5DYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihQZXJzaWFuQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgUGVyc2lhbkNhbGVuZGFyICovXG4gICAgbmFtZTogJ1BlcnNpYW4nLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBQZXJzaWFuIGVwb2NoOiAxOSBNYXJjaCA2MjIgQ0UuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXIgKi9cbiAgICBqZEVwb2NoOiAxOTQ4MzIwLjUsXG4gICAgLyoqIERheXMgcGVyIG1vbnRoIGluIGEgY29tbW9uIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXIgKi9cbiAgICBkYXlzUGVyTW9udGg6IFszMSwgMzEsIDMxLCAzMSwgMzEsIDMxLCAzMCwgMzAsIDMwLCAzMCwgMzAsIDI5XSxcbiAgICAvKiogPGNvZGU+dHJ1ZTwvY29kZT4gaWYgaGFzIGEgeWVhciB6ZXJvLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAbWVtYmVyb2YgUGVyc2lhbkNhbGVuZGFyICovXG4gICAgaGFzWWVhclplcm86IGZhbHNlLFxuICAgIC8qKiBUaGUgbWluaW11bSBtb250aCBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXIgKi9cbiAgICBtaW5Nb250aDogMSxcbiAgICAvKiogVGhlIGZpcnN0IG1vbnRoIGluIHRoZSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgUGVyc2lhbkNhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogMSxcbiAgICAvKiogVGhlIG1pbmltdW0gZGF5IG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIFBlcnNpYW5DYWxlbmRhciAqL1xuICAgIG1pbkRheTogMSxcblxuICAgIC8qKiBMb2NhbGlzYXRpb25zIGZvciB0aGUgcGx1Z2luLlxuICAgICAgICBFbnRyaWVzIGFyZSBvYmplY3RzIGluZGV4ZWQgYnkgdGhlIGxhbmd1YWdlIGNvZGUgKCcnIGJlaW5nIHRoZSBkZWZhdWx0IFVTL0VuZ2xpc2gpLlxuICAgICAgICBFYWNoIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBhdHRyaWJ1dGVzLlxuICAgICAgICBAbWVtYmVyb2YgUGVyc2lhbkNhbGVuZGFyXG4gICAgICAgIEBwcm9wZXJ0eSBuYW1lIHtzdHJpbmd9IFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAcHJvcGVydHkgZXBvY2hzIHtzdHJpbmdbXX0gVGhlIGVwb2NoIG5hbWVzLlxuICAgICAgICBAcHJvcGVydHkgbW9udGhOYW1lcyB7c3RyaW5nW119IFRoZSBsb25nIG5hbWVzIG9mIHRoZSBtb250aHMgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc1Nob3J0IHtzdHJpbmdbXX0gVGhlIHNob3J0IG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXNNaW4ge3N0cmluZ1tdfSBUaGUgbWluaW1hbCBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRhdGVGb3JtYXQge3N0cmluZ30gVGhlIGRhdGUgZm9ybWF0IGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICAgICAgICAgIFNlZSB0aGUgb3B0aW9ucyBvbiA8YSBocmVmPVwiQmFzZUNhbGVuZGFyLmh0bWwjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgZGV0YWlscy5cbiAgICAgICAgQHByb3BlcnR5IGZpcnN0RGF5IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlaywgc3RhcnRpbmcgYXQgMC5cbiAgICAgICAgQHByb3BlcnR5IGlzUlRMIHtudW1iZXJ9IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgbG9jYWxpc2F0aW9uIHJlYWRzIHJpZ2h0LXRvLWxlZnQuICovXG4gICAgcmVnaW9uYWxPcHRpb25zOiB7IC8vIExvY2FsaXNhdGlvbnNcbiAgICAgICAgJyc6IHtcbiAgICAgICAgICAgIG5hbWU6ICdQZXJzaWFuJyxcbiAgICAgICAgICAgIGVwb2NoczogWydCUCcsICdBUCddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydGYXJ2YXJkaW4nLCAnT3JkaWJlaGVzaHQnLCAnS2hvcmRhZCcsICdUaXInLCAnTW9yZGFkJywgJ1NoYWhyaXZhcicsXG4gICAgICAgICAgICAnTWVocicsICdBYmFuJywgJ0F6YXInLCAnRGF5JywgJ0JhaG1hbicsICdFc2ZhbmQnXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydDogWydGYXInLCAnT3JkJywgJ0tobycsICdUaXInLCAnTW9yJywgJ1NoYScsICdNZWgnLCAnQWJhJywgJ0F6YScsICdEYXknLCAnQmFoJywgJ0VzZiddLFxuICAgICAgICAgICAgZGF5TmFtZXM6IFsnWWVrc2hhbWJlJywgJ0Rvc2hhbWJlJywgJ1Nlc2hhbWJlJywgJ0Now6ZoYXJzaGFtYmUnLCAnUGFuanNoYW1iZScsICdKb21cXCdlJywgJ1NoYW1iZSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydZZWsnLCAnRG8nLCAnU2UnLCAnQ2jDpicsICdQYW5qJywgJ0pvbScsICdTaGEnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ1llJywnRG8nLCdTZScsJ0NoJywnUGEnLCdKbycsJ1NoJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAneXl5eS9tbS9kZCcsXG4gICAgICAgICAgICBmaXJzdERheTogNixcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gKCgoKChkYXRlLnllYXIoKSAtIChkYXRlLnllYXIoKSA+IDAgPyA0NzQgOiA0NzMpKSAlIDI4MjApICtcbiAgICAgICAgICAgIDQ3NCArIDM4KSAqIDY4MikgJSAyODE2KSA8IDY4MjtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB0aGUgd2VlayBvZiB0aGUgeWVhciBmb3IgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgUGVyc2lhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICAvLyBGaW5kIFNhdHVyZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBTYXR1cmRheVxuICAgICAgICB2YXIgY2hlY2tEYXRlID0gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgICAgICBjaGVja0RhdGUuYWRkKC0oKGNoZWNrRGF0ZS5kYXlPZldlZWsoKSArIDEpICUgNyksICdkJyk7XG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKChjaGVja0RhdGUuZGF5T2ZZZWFyKCkgLSAxKSAvIDcpICsgMTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgUGVyc2lhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGguXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzIGluIHRoaXMgbW9udGguXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luTW9udGg6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheXNQZXJNb250aFtkYXRlLm1vbnRoKCkgLSAxXSArXG4gICAgICAgICAgICAoZGF0ZS5tb250aCgpID09PSAxMiAmJiB0aGlzLmxlYXBZZWFyKGRhdGUueWVhcigpKSA/IDEgOiAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgUGVyc2lhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgd2VlayBkYXksIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgIT09IDU7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgSnVsaWFuIGRhdGUgZXF1aXZhbGVudCBmb3IgdGhpcyBkYXRlLFxuICAgICAgICBpLmUuIGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbi5cbiAgICAgICAgQG1lbWJlcm9mIFBlcnNpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgeWVhciA9IGRhdGUueWVhcigpO1xuICAgICAgICBtb250aCA9IGRhdGUubW9udGgoKTtcbiAgICAgICAgZGF5ID0gZGF0ZS5kYXkoKTtcbiAgICAgICAgdmFyIGVwQmFzZSA9IHllYXIgLSAoeWVhciA+PSAwID8gNDc0IDogNDczKTtcbiAgICAgICAgdmFyIGVwWWVhciA9IDQ3NCArIG1vZChlcEJhc2UsIDI4MjApO1xuICAgICAgICByZXR1cm4gZGF5ICsgKG1vbnRoIDw9IDcgPyAobW9udGggLSAxKSAqIDMxIDogKG1vbnRoIC0gMSkgKiAzMCArIDYpICtcbiAgICAgICAgICAgIE1hdGguZmxvb3IoKGVwWWVhciAqIDY4MiAtIDExMCkgLyAyODE2KSArIChlcFllYXIgLSAxKSAqIDM2NSArXG4gICAgICAgICAgICBNYXRoLmZsb29yKGVwQmFzZSAvIDI4MjApICogMTAyOTk4MyArIHRoaXMuamRFcG9jaCAtIDE7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBQZXJzaWFuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIGpkID0gTWF0aC5mbG9vcihqZCkgKyAwLjU7XG4gICAgICAgIHZhciBkZXBvY2ggPSBqZCAtIHRoaXMudG9KRCg0NzUsIDEsIDEpO1xuICAgICAgICB2YXIgY3ljbGUgPSBNYXRoLmZsb29yKGRlcG9jaCAvIDEwMjk5ODMpO1xuICAgICAgICB2YXIgY3llYXIgPSBtb2QoZGVwb2NoLCAxMDI5OTgzKTtcbiAgICAgICAgdmFyIHljeWNsZSA9IDI4MjA7XG4gICAgICAgIGlmIChjeWVhciAhPT0gMTAyOTk4Mikge1xuICAgICAgICAgICAgdmFyIGF1eDEgPSBNYXRoLmZsb29yKGN5ZWFyIC8gMzY2KTtcbiAgICAgICAgICAgIHZhciBhdXgyID0gbW9kKGN5ZWFyLCAzNjYpO1xuICAgICAgICAgICAgeWN5Y2xlID0gTWF0aC5mbG9vcigoKDIxMzQgKiBhdXgxKSArICgyODE2ICogYXV4MikgKyAyODE1KSAvIDEwMjg1MjIpICsgYXV4MSArIDE7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHllYXIgPSB5Y3ljbGUgKyAoMjgyMCAqIGN5Y2xlKSArIDQ3NDtcbiAgICAgICAgeWVhciA9ICh5ZWFyIDw9IDAgPyB5ZWFyIC0gMSA6IHllYXIpO1xuICAgICAgICB2YXIgeWRheSA9IGpkIC0gdGhpcy50b0pEKHllYXIsIDEsIDEpICsgMTtcbiAgICAgICAgdmFyIG1vbnRoID0gKHlkYXkgPD0gMTg2ID8gTWF0aC5jZWlsKHlkYXkgLyAzMSkgOiBNYXRoLmNlaWwoKHlkYXkgLSA2KSAvIDMwKSk7XG4gICAgICAgIHZhciBkYXkgPSBqZCAtIHRoaXMudG9KRCh5ZWFyLCBtb250aCwgMSkgKyAxO1xuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgIH1cbn0pO1xuXG4vLyBNb2R1bHVzIGZ1bmN0aW9uIHdoaWNoIHdvcmtzIGZvciBub24taW50ZWdlcnMuXG5mdW5jdGlvbiBtb2QoYSwgYikge1xuICAgIHJldHVybiBhIC0gKGIgKiBNYXRoLmZsb29yKGEgLyBiKSk7XG59XG5cbi8vIFBlcnNpYW4gKEphbGFsaSkgY2FsZW5kYXIgaW1wbGVtZW50YXRpb25cbm1haW4uY2FsZW5kYXJzLnBlcnNpYW4gPSBQZXJzaWFuQ2FsZW5kYXI7XG5tYWluLmNhbGVuZGFycy5qYWxhbGkgPSBQZXJzaWFuQ2FsZW5kYXI7XG5cblxufSx7XCIuLi9tYWluXCI6NTcxLFwib2JqZWN0LWFzc2lnblwiOjQ1NH1dLDU2ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKlxuICogV29ybGQgQ2FsZW5kYXJzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFyc1xuICpcbiAqIEJhdGNoLWNvbnZlcnRlZCBmcm9tIGtid29vZC9jYWxlbmRhcnNcbiAqIE1hbnkgdGhhbmtzIHRvIEtlaXRoIFdvb2QgYW5kIGFsbCBvZiB0aGUgY29udHJpYnV0b3JzIHRvIHRoZSBvcmlnaW5hbCBwcm9qZWN0IVxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICovXG5cbu+7vy8qIGh0dHA6Ly9rZWl0aC13b29kLm5hbWUvY2FsZW5kYXJzLmh0bWxcbiAgIFRhaXdhbmVzZSAoTWluZ3VvKSBjYWxlbmRhciBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEZlYnJ1YXJ5IDIwMTAuXG4gICBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCAoaHR0cDovL2tlaXRoLXdvb2QubmFtZS9saWNlbmNlLmh0bWwpIGxpY2Vuc2UuIFxuICAgUGxlYXNlIGF0dHJpYnV0ZSB0aGUgYXV0aG9yIGlmIHlvdSB1c2UgaXQuICovXG5cbnZhciBtYWluID0gX2RlcmVxXygnLi4vbWFpbicpO1xudmFyIGFzc2lnbiA9IF9kZXJlcV8oJ29iamVjdC1hc3NpZ24nKTtcblxuXG52YXIgZ3JlZ29yaWFuQ2FsZW5kYXIgPSBtYWluLmluc3RhbmNlKCk7XG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgVGFpd2FuZXNlIGNhbGVuZGFyLlxuICAgIFNlZSBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01pbmd1b19jYWxlbmRhci5cbiAgICBAY2xhc3MgVGFpd2FuQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gVGFpd2FuQ2FsZW5kYXIobGFuZ3VhZ2UpIHtcbiAgICB0aGlzLmxvY2FsID0gdGhpcy5yZWdpb25hbE9wdGlvbnNbbGFuZ3VhZ2UgfHwgJyddIHx8IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbn1cblxuVGFpd2FuQ2FsZW5kYXIucHJvdG90eXBlID0gbmV3IG1haW4uYmFzZUNhbGVuZGFyO1xuXG5hc3NpZ24oVGFpd2FuQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnVGFpd2FuJyxcbiAgICAvKiogSnVsaWFuIGRhdGUgb2Ygc3RhcnQgb2YgVGFpd2FuIGVwb2NoOiAxIEphbnVhcnkgMTkxMiBDRSAoR3JlZ29yaWFuKS5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyICovXG4gICAgamRFcG9jaDogMjQxOTQwMi41LFxuICAgIC8qKiBEaWZmZXJlbmNlIGluIHllYXJzIGJldHdlZW4gVGFpd2FuIGFuZCBHcmVnb3JpYW4gY2FsZW5kYXJzLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXIgKi9cbiAgICB5ZWFyc09mZnNldDogMTkxMSxcbiAgICAvKiogRGF5cyBwZXIgbW9udGggaW4gYSBjb21tb24geWVhci5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyICovXG4gICAgZGF5c1Blck1vbnRoOiBbMzEsIDI4LCAzMSwgMzAsIDMxLCAzMCwgMzEsIDMxLCAzMCwgMzEsIDMwLCAzMV0sXG4gICAgLyoqIDxjb2RlPnRydWU8L2NvZGU+IGlmIGhhcyBhIHllYXIgemVybywgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyICovXG4gICAgaGFzWWVhclplcm86IGZhbHNlLFxuICAgIC8qKiBUaGUgbWluaW11bSBtb250aCBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAxLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhciAqL1xuICAgIGZpcnN0TW9udGg6IDEsXG4gICAgLyoqIFRoZSBtaW5pbXVtIGRheSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhciAqL1xuICAgIG1pbkRheTogMSxcblxuICAgIC8qKiBMb2NhbGlzYXRpb25zIGZvciB0aGUgcGx1Z2luLlxuICAgICAgICBFbnRyaWVzIGFyZSBvYmplY3RzIGluZGV4ZWQgYnkgdGhlIGxhbmd1YWdlIGNvZGUgKCcnIGJlaW5nIHRoZSBkZWZhdWx0IFVTL0VuZ2xpc2gpLlxuICAgICAgICBFYWNoIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBhdHRyaWJ1dGVzLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC4gKi9cbiAgICByZWdpb25hbE9wdGlvbnM6IHsgLy8gTG9jYWxpc2F0aW9uc1xuICAgICAgICAnJzoge1xuICAgICAgICAgICAgbmFtZTogJ1RhaXdhbicsXG4gICAgICAgICAgICBlcG9jaHM6IFsnQlJPQycsICdST0MnXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXM6IFsnSmFudWFyeScsICdGZWJydWFyeScsICdNYXJjaCcsICdBcHJpbCcsICdNYXknLCAnSnVuZScsXG4gICAgICAgICAgICAnSnVseScsICdBdWd1c3QnLCAnU2VwdGVtYmVyJywgJ09jdG9iZXInLCAnTm92ZW1iZXInLCAnRGVjZW1iZXInXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydDogWydKYW4nLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsICdKdWwnLCAnQXVnJywgJ1NlcCcsICdPY3QnLCAnTm92JywgJ0RlYyddLFxuICAgICAgICAgICAgZGF5TmFtZXM6IFsnU3VuZGF5JywgJ01vbmRheScsICdUdWVzZGF5JywgJ1dlZG5lc2RheScsICdUaHVyc2RheScsICdGcmlkYXknLCAnU2F0dXJkYXknXSxcbiAgICAgICAgICAgIGRheU5hbWVzU2hvcnQ6IFsnU3VuJywgJ01vbicsICdUdWUnLCAnV2VkJywgJ1RodScsICdGcmknLCAnU2F0J10sXG4gICAgICAgICAgICBkYXlOYW1lc01pbjogWydTdScsICdNbycsICdUdScsICdXZScsICdUaCcsICdGcicsICdTYSddLFxuICAgICAgICAgICAgZGlnaXRzOiBudWxsLFxuICAgICAgICAgICAgZGF0ZUZvcm1hdDogJ3l5eXkvbW0vZGQnLFxuICAgICAgICAgICAgZmlyc3REYXk6IDEsXG4gICAgICAgICAgICBpc1JUTDogZmFsc2VcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICB2YXIgeWVhciA9IHRoaXMuX3QyZ1llYXIoZGF0ZS55ZWFyKCkpO1xuICAgICAgICByZXR1cm4gZ3JlZ29yaWFuQ2FsZW5kYXIubGVhcFllYXIoeWVhcik7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZSAtIElTTyA4NjAxLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICB2YXIgeWVhciA9IHRoaXMuX3QyZ1llYXIoZGF0ZS55ZWFyKCkpO1xuICAgICAgICByZXR1cm4gZ3JlZ29yaWFuQ2FsZW5kYXIud2Vla09mWWVhcih5ZWFyLCBkYXRlLm1vbnRoKCksIGRhdGUuZGF5KCkpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIG9mIHRoZSBtb250aC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIG1vbnRoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgbW9udGgveWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbih5ZWFyLCBtb250aCkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCB0aGlzLm1pbkRheSwgbWFpbi5sb2NhbC5pbnZhbGlkTW9udGgpO1xuICAgICAgICByZXR1cm4gdGhpcy5kYXlzUGVyTW9udGhbZGF0ZS5tb250aCgpIC0gMV0gK1xuICAgICAgICAgICAgKGRhdGUubW9udGgoKSA9PT0gMiAmJiB0aGlzLmxlYXBZZWFyKGRhdGUueWVhcigpKSA/IDEgOiAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB3aGV0aGVyIHRoaXMgZGF0ZSBpcyBhIHdlZWsgZGF5LlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiAodGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgfHwgNykgPCA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBUYWl3YW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LCBtYWluLmxvY2FsLmludmFsaWREYXRlKTtcbiAgICAgICAgdmFyIHllYXIgPSB0aGlzLl90MmdZZWFyKGRhdGUueWVhcigpKTtcbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbkNhbGVuZGFyLnRvSkQoeWVhciwgZGF0ZS5tb250aCgpLCBkYXRlLmRheSgpKTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBqZCB7bnVtYmVyfSBUaGUgSnVsaWFuIGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpEOiBmdW5jdGlvbihqZCkge1xuICAgICAgICB2YXIgZGF0ZSA9IGdyZWdvcmlhbkNhbGVuZGFyLmZyb21KRChqZCk7XG4gICAgICAgIHZhciB5ZWFyID0gdGhpcy5fZzJ0WWVhcihkYXRlLnllYXIoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLm5ld0RhdGUoeWVhciwgZGF0ZS5tb250aCgpLCBkYXRlLmRheSgpKTtcbiAgICB9LFxuXG4gICAgLyoqIENvbnZlcnQgVGFpd2FuZXNlIHRvIEdyZWdvcmlhbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgVGFpd2FuQ2FsZW5kYXJcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIFRhaXdhbmVzZSB5ZWFyLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBjb3JyZXNwb25kaW5nIEdyZWdvcmlhbiB5ZWFyLiAqL1xuICAgIF90MmdZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHJldHVybiB5ZWFyICsgdGhpcy55ZWFyc09mZnNldCArICh5ZWFyID49IC10aGlzLnllYXJzT2Zmc2V0ICYmIHllYXIgPD0gLTEgPyAxIDogMCk7XG4gICAgfSxcblxuICAgIC8qKiBDb252ZXJ0IEdyZWdvcmlhbiB0byBUYWl3YW5lc2UgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIFRhaXdhbkNhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtudW1iZXJ9IFRoZSBHcmVnb3JpYW4geWVhci5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgY29ycmVzcG9uZGluZyBUYWl3YW5lc2UgeWVhci4gKi9cbiAgICBfZzJ0WWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4geWVhciAtIHRoaXMueWVhcnNPZmZzZXQgLSAoeWVhciA+PSAxICYmIHllYXIgPD0gdGhpcy55ZWFyc09mZnNldCA/IDEgOiAwKTtcbiAgICB9XG59KTtcblxuLy8gVGFpd2FuIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy50YWl3YW4gPSBUYWl3YW5DYWxlbmRhcjtcblxuXG59LHtcIi4uL21haW5cIjo1NzEsXCJvYmplY3QtYXNzaWduXCI6NDU0fV0sNTY5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgVGhhaSBjYWxlbmRhciBmb3IgalF1ZXJ5IHYyLjAuMi5cbiAgIFdyaXR0ZW4gYnkgS2VpdGggV29vZCAod29vZC5rZWl0aHthdH1vcHR1c25ldC5jb20uYXUpIEZlYnJ1YXJ5IDIwMTAuXG4gICBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCAoaHR0cDovL2tlaXRoLXdvb2QubmFtZS9saWNlbmNlLmh0bWwpIGxpY2Vuc2UuIFxuICAgUGxlYXNlIGF0dHJpYnV0ZSB0aGUgYXV0aG9yIGlmIHlvdSB1c2UgaXQuICovXG5cbnZhciBtYWluID0gX2RlcmVxXygnLi4vbWFpbicpO1xudmFyIGFzc2lnbiA9IF9kZXJlcV8oJ29iamVjdC1hc3NpZ24nKTtcblxuXG52YXIgZ3JlZ29yaWFuQ2FsZW5kYXIgPSBtYWluLmluc3RhbmNlKCk7XG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgVGhhaSBjYWxlbmRhci5cbiAgICBTZWUgaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9UaGFpX2NhbGVuZGFyLlxuICAgIEBjbGFzcyBUaGFpQ2FsZW5kYXJcbiAgICBAcGFyYW0gW2xhbmd1YWdlPScnXSB7c3RyaW5nfSBUaGUgbGFuZ3VhZ2UgY29kZSAoZGVmYXVsdCBFbmdsaXNoKSBmb3IgbG9jYWxpc2F0aW9uLiAqL1xuZnVuY3Rpb24gVGhhaUNhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cblRoYWlDYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgbWFpbi5iYXNlQ2FsZW5kYXI7XG5cbmFzc2lnbihUaGFpQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyICovXG4gICAgbmFtZTogJ1RoYWknLFxuICAgIC8qKiBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBUaGFpIGVwb2NoOiAxIEphbnVhcnkgNTQzIEJDRSAoR3JlZ29yaWFuKS5cbiAgICAgICAgQG1lbWJlcm9mIFRoYWlDYWxlbmRhciAqL1xuICAgIGpkRXBvY2g6IDE1MjMwOTguNSxcbiAgICAvKiogRGlmZmVyZW5jZSBpbiB5ZWFycyBiZXR3ZWVuIFRoYWkgYW5kIEdyZWdvcmlhbiBjYWxlbmRhcnMuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXIgKi9cbiAgICB5ZWFyc09mZnNldDogNTQzLCBcbiAgICAvKiogRGF5cyBwZXIgbW9udGggaW4gYSBjb21tb24geWVhci5cbiAgICAgICAgQG1lbWJlcm9mIFRoYWlDYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMxLCAyOCwgMzEsIDMwLCAzMSwgMzAsIDMxLCAzMSwgMzAsIDMxLCAzMCwgMzFdLFxuICAgIC8qKiA8Y29kZT50cnVlPC9jb2RlPiBpZiBoYXMgYSB5ZWFyIHplcm8sIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIFRoYWlDYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAxLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXIgKi9cbiAgICBmaXJzdE1vbnRoOiAxLFxuICAgIC8qKiBUaGUgbWluaW11bSBkYXkgbnVtYmVyLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyICovXG4gICAgbWluRGF5OiAxLFxuXG4gICAgLyoqIExvY2FsaXNhdGlvbnMgZm9yIHRoZSBwbHVnaW4uXG4gICAgICAgIEVudHJpZXMgYXJlIG9iamVjdHMgaW5kZXhlZCBieSB0aGUgbGFuZ3VhZ2UgY29kZSAoJycgYmVpbmcgdGhlIGRlZmF1bHQgVVMvRW5nbGlzaCkuXG4gICAgICAgIEVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nIGF0dHJpYnV0ZXMuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC4gKi9cbiAgICByZWdpb25hbE9wdGlvbnM6IHsgLy8gTG9jYWxpc2F0aW9uc1xuICAgICAgICAnJzoge1xuICAgICAgICAgICAgbmFtZTogJ1RoYWknLFxuICAgICAgICAgICAgZXBvY2hzOiBbJ0JCRScsICdCRSddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJyxcbiAgICAgICAgICAgICdKdWx5JywgJ0F1Z3VzdCcsICdTZXB0ZW1iZXInLCAnT2N0b2JlcicsICdOb3ZlbWJlcicsICdEZWNlbWJlciddLFxuICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0OiBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ10sXG4gICAgICAgICAgICBkYXlOYW1lczogWydTdW5kYXknLCAnTW9uZGF5JywgJ1R1ZXNkYXknLCAnV2VkbmVzZGF5JywgJ1RodXJzZGF5JywgJ0ZyaWRheScsICdTYXR1cmRheSddLFxuICAgICAgICAgICAgZGF5TmFtZXNTaG9ydDogWydTdW4nLCAnTW9uJywgJ1R1ZScsICdXZWQnLCAnVGh1JywgJ0ZyaScsICdTYXQnXSxcbiAgICAgICAgICAgIGRheU5hbWVzTWluOiBbJ1N1JywgJ01vJywgJ1R1JywgJ1dlJywgJ1RoJywgJ0ZyJywgJ1NhJ10sXG4gICAgICAgICAgICBkaWdpdHM6IG51bGwsXG4gICAgICAgICAgICBkYXRlRm9ybWF0OiAnZGQvbW0veXl5eScsXG4gICAgICAgICAgICBmaXJzdERheTogMCxcbiAgICAgICAgICAgIGlzUlRMOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksIG1haW4ubG9jYWwuaW52YWxpZFllYXIpO1xuICAgICAgICB2YXIgeWVhciA9IHRoaXMuX3QyZ1llYXIoZGF0ZS55ZWFyKCkpO1xuICAgICAgICByZXR1cm4gZ3JlZ29yaWFuQ2FsZW5kYXIubGVhcFllYXIoeWVhcik7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgdGhlIHdlZWsgb2YgdGhlIHllYXIgZm9yIGEgZGF0ZSAtIElTTyA4NjAxLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgdmFyIHllYXIgPSB0aGlzLl90MmdZZWFyKGRhdGUueWVhcigpKTtcbiAgICAgICAgcmV0dXJuIGdyZWdvcmlhbkNhbGVuZGFyLndlZWtPZlllYXIoeWVhciwgZGF0ZS5tb250aCgpLCBkYXRlLmRheSgpKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgb2YgdGhlIG1vbnRoLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGguXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzIGluIHRoaXMgbW9udGguXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBtb250aC95ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZGF5c0luTW9udGg6IGZ1bmN0aW9uKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheXNQZXJNb250aFtkYXRlLm1vbnRoKCkgLSAxXSArXG4gICAgICAgICAgICAoZGF0ZS5tb250aCgpID09PSAyICYmIHRoaXMubGVhcFllYXIoZGF0ZS55ZWFyKCkpID8gMSA6IDApO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB3ZWVrIGRheSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB3ZWVrRGF5OiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHJldHVybiAodGhpcy5kYXlPZldlZWsoeWVhciwgbW9udGgsIGRheSkgfHwgNykgPCA2O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gY29udmVydCBvciB0aGUgeWVhciB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgZXF1aXZhbGVudCBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICB0b0pEOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHZhciB5ZWFyID0gdGhpcy5fdDJnWWVhcihkYXRlLnllYXIoKSk7XG4gICAgICAgIHJldHVybiBncmVnb3JpYW5DYWxlbmRhci50b0pEKHllYXIsIGRhdGUubW9udGgoKSwgZGF0ZS5kYXkoKSk7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIHZhciBkYXRlID0gZ3JlZ29yaWFuQ2FsZW5kYXIuZnJvbUpEKGpkKTtcbiAgICAgICAgdmFyIHllYXIgPSB0aGlzLl9nMnRZZWFyKGRhdGUueWVhcigpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMubmV3RGF0ZSh5ZWFyLCBkYXRlLm1vbnRoKCksIGRhdGUuZGF5KCkpO1xuICAgIH0sXG5cbiAgICAvKiogQ29udmVydCBUaGFpIHRvIEdyZWdvcmlhbiB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgVGhhaUNhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtudW1iZXJ9IFRoZSBUaGFpIHllYXIuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGNvcnJlc3BvbmRpbmcgR3JlZ29yaWFuIHllYXIuICovXG4gICAgX3QyZ1llYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgcmV0dXJuIHllYXIgLSB0aGlzLnllYXJzT2Zmc2V0IC0gKHllYXIgPj0gMSAmJiB5ZWFyIDw9IHRoaXMueWVhcnNPZmZzZXQgPyAxIDogMCk7XG4gICAgfSxcblxuICAgIC8qKiBDb252ZXJ0IEdyZWdvcmlhbiB0byBUaGFpIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBUaGFpQ2FsZW5kYXJcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIEdyZWdvcmlhbiB5ZWFyLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBjb3JyZXNwb25kaW5nIFRoYWkgeWVhci4gKi9cbiAgICBfZzJ0WWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICByZXR1cm4geWVhciArIHRoaXMueWVhcnNPZmZzZXQgKyAoeWVhciA+PSAtdGhpcy55ZWFyc09mZnNldCAmJiB5ZWFyIDw9IC0xID8gMSA6IDApO1xuICAgIH1cbn0pO1xuXG4vLyBUaGFpIGNhbGVuZGFyIGltcGxlbWVudGF0aW9uXG5tYWluLmNhbGVuZGFycy50aGFpID0gVGhhaUNhbGVuZGFyO1xuXG5cbn0se1wiLi4vbWFpblwiOjU3MSxcIm9iamVjdC1hc3NpZ25cIjo0NTR9XSw1NzA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBVbW1BbFF1cmEgY2FsZW5kYXIgZm9yIGpRdWVyeSB2Mi4wLjIuXG4gICBXcml0dGVuIGJ5IEFtcm8gT3NhbWEgTWFyY2ggMjAxMy5cbiAgIE1vZGlmaWVkIGJ5IEJpbm5vb2guY29tICYgd3d3LmVsbS5zYSAtIDIwMTQgLSBBZGRlZCBkYXRlcyBiYWNrIHRvIDEyNzYgSGlqcmkgeWVhci5cbiAgIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIChodHRwOi8va2VpdGgtd29vZC5uYW1lL2xpY2VuY2UuaHRtbCkgbGljZW5zZS4gXG4gICBQbGVhc2UgYXR0cmlidXRlIHRoZSBhdXRob3IgaWYgeW91IHVzZSBpdC4gKi9cblxudmFyIG1haW4gPSBfZGVyZXFfKCcuLi9tYWluJyk7XG52YXIgYXNzaWduID0gX2RlcmVxXygnb2JqZWN0LWFzc2lnbicpO1xuXG5cbi8qKiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgVW1tQWxRdXJhIG9yICdzYXVkaScgY2FsZW5kYXIuXG4gICAgU2VlIGFsc28gPGEgaHJlZj1cImh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSXNsYW1pY19jYWxlbmRhciNTYXVkaV9BcmFiaWEuMjdzX1VtbV9hbC1RdXJhX2NhbGVuZGFyXCI+aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Jc2xhbWljX2NhbGVuZGFyI1NhdWRpX0FyYWJpYS4yN3NfVW1tX2FsLVF1cmFfY2FsZW5kYXI8L2E+LlxuICAgIDxhIGhyZWY9XCJodHRwOi8vd3d3LnVtbXVscXVyYS5vcmcuc2EvQWJvdXQuYXNweFwiPmh0dHA6Ly93d3cudW1tdWxxdXJhLm9yZy5zYS9BYm91dC5hc3B4PC9hPlxuICAgIDxhIGhyZWY9XCJodHRwOi8vd3d3LnN0YWZmLnNjaWVuY2UudXUubmwvfmdlbnQwMTEzL2lzbGFtL3VtbWFscXVyYS5odG1cIj5odHRwOi8vd3d3LnN0YWZmLnNjaWVuY2UudXUubmwvfmdlbnQwMTEzL2lzbGFtL3VtbWFscXVyYS5odG08L2E+XG4gICAgQGNsYXNzIFVtbUFsUXVyYUNhbGVuZGFyXG4gICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgKGRlZmF1bHQgRW5nbGlzaCkgZm9yIGxvY2FsaXNhdGlvbi4gKi9cbmZ1bmN0aW9uIFVtbUFsUXVyYUNhbGVuZGFyKGxhbmd1YWdlKSB7XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zW2xhbmd1YWdlIHx8ICcnXSB8fCB0aGlzLnJlZ2lvbmFsT3B0aW9uc1snJ107XG59XG5cblVtbUFsUXVyYUNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBtYWluLmJhc2VDYWxlbmRhcjtcblxuYXNzaWduKFVtbUFsUXVyYUNhbGVuZGFyLnByb3RvdHlwZSwge1xuICAgIC8qKiBUaGUgY2FsZW5kYXIgbmFtZS5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyICovXG4gICAgbmFtZTogJ1VtbUFsUXVyYScsXG4gICAgLy9qZEVwb2NoOiAxOTQ4NDQwLCAvLyBKdWxpYW4gZGF0ZSBvZiBzdGFydCBvZiBVbW1BbFF1cmEgZXBvY2g6IDE0IE1hcmNoIDE5MzcgQ0VcbiAgICAvL2RheXNQZXJNb250aDogLy8gRGF5cyBwZXIgbW9udGggaW4gYSBjb21tb24geWVhciwgcmVwbGFjZWQgYnkgYSBtZXRob2QuXG4gICAgLyoqIDxjb2RlPnRydWU8L2NvZGU+IGlmIGhhcyBhIHllYXIgemVybywgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyICovXG4gICAgaGFzWWVhclplcm86IGZhbHNlLFxuICAgIC8qKiBUaGUgbWluaW11bSBtb250aCBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhciAqL1xuICAgIG1pbk1vbnRoOiAxLFxuICAgIC8qKiBUaGUgZmlyc3QgbW9udGggaW4gdGhlIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhciAqL1xuICAgIGZpcnN0TW9udGg6IDEsXG4gICAgLyoqIFRoZSBtaW5pbXVtIGRheSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhciAqL1xuICAgIG1pbkRheTogMSxcblxuICAgIC8qKiBMb2NhbGlzYXRpb25zIGZvciB0aGUgcGx1Z2luLlxuICAgICAgICBFbnRyaWVzIGFyZSBvYmplY3RzIGluZGV4ZWQgYnkgdGhlIGxhbmd1YWdlIGNvZGUgKCcnIGJlaW5nIHRoZSBkZWZhdWx0IFVTL0VuZ2xpc2gpLlxuICAgICAgICBFYWNoIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBhdHRyaWJ1dGVzLlxuICAgICAgICBAbWVtYmVyb2YgVW1tQWxRdXJhQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC4gKi9cbiAgICByZWdpb25hbE9wdGlvbnM6IHsgLy8gTG9jYWxpc2F0aW9uc1xuICAgICAgICAnJzoge1xuICAgICAgICAgICAgbmFtZTogJ1VtbSBhbC1RdXJhJyxcbiAgICAgICAgICAgIGVwb2NoczogWydCSCcsICdBSCddLFxuICAgICAgICAgICAgbW9udGhOYW1lczogWydBbC1NdWhhcnJhbScsICdTYWZhcicsICdSYWJpXFwnIGFsLWF3d2FsJywgJ1JhYmlcXCcgQWwtVGhhbmknLCAnSnVtYWRhIEFsLUF3d2FsJywgJ0p1bWFkYSBBbC1UaGFuaScsXG4gICAgICAgICAgICAnUmFqYWInLCAnU2hhXFwnYWJhbicsICdSYW1hZGFuJywgJ1NoYXd3YWwnLCAnRGh1IGFsLVFpXFwnZGFoJywgJ0RodSBhbC1IaWpqYWgnXSxcbiAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydDogWydNdWgnLCAnU2FmJywgJ1JhYjEnLCAnUmFiMicsICdKdW0xJywgJ0p1bTInLCAnUmFqJywgJ1NoYVxcJycsICdSYW0nLCAnU2hhdycsICdEaHVRJywgJ0RodUgnXSxcbiAgICAgICAgICAgIGRheU5hbWVzOiBbJ1lhd20gYWwtQWhhZCcsICdZYXdtIGFsLUl0aG5haW4nLCAnWWF3bSBhbC1UaGFsxIF0aMSB4oCZJywgJ1lhd20gYWwtQXJiYeKAmMSB4oCZJywgJ1lhd20gYWwtS2hhbcSrcycsICdZYXdtIGFsLUp1beKAmGEnLCAnWWF3bSBhbC1TYWJ0J10sXG4gICAgICAgICAgICBkYXlOYW1lc01pbjogWydBaCcsICdJdGgnLCAnVGgnLCAnQXInLCAnS2gnLCAnSnUnLCAnU2EnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICd5eXl5L21tL2RkJyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiA2LFxuICAgICAgICAgICAgaXNSVEw6IHRydWVcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGluIGEgbGVhcCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgVW1tQWxRdXJhQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbiAoeWVhcikge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuICh0aGlzLmRheXNJblllYXIoZGF0ZS55ZWFyKCkpID09PSAzNTUpO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyIGZvciBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtPZlllYXI6IGZ1bmN0aW9uICh5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIC8vIEZpbmQgU3VuZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBTdW5kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCgtY2hlY2tEYXRlLmRheU9mV2VlaygpLCAnZCcpO1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigoY2hlY2tEYXRlLmRheU9mWWVhcigpIC0gMSkgLyA3KSArIDE7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgVW1tQWxRdXJhQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cy5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5ZZWFyOiBmdW5jdGlvbiAoeWVhcikge1xuICAgICAgICB2YXIgZGF5c0NvdW50ID0gMDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gMTI7IGkrKykge1xuICAgICAgICAgICAgZGF5c0NvdW50ICs9IHRoaXMuZGF5c0luTW9udGgoeWVhciwgaSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRheXNDb3VudDtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgZGF5cyBpbiBhIG1vbnRoLlxuICAgICAgICBAbWVtYmVyb2YgVW1tQWxRdXJhQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciBvZiB0aGUgbW9udGguXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aC5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBtb250aC5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIG1vbnRoL3llYXIgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlzSW5Nb250aDogZnVuY3Rpb24gKHllYXIsIG1vbnRoKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5LCBtYWluLmxvY2FsLmludmFsaWRNb250aCk7XG4gICAgICAgIHZhciBtY2pkbiA9IGRhdGUudG9KRCgpIC0gMjQwMDAwMCArIDAuNTsgLy8gTW9kaWZpZWQgQ2hyb25vbG9naWNhbCBKdWxpYW4gRGF5IE51bWJlciAoTUNKRE4pXG4gICAgICAgIC8vIHRoZSBNQ0pETidzIG9mIHRoZSBzdGFydCBvZiB0aGUgbHVuYXRpb25zIGluIHRoZSBVbW0gYWwtUXVyYSBjYWxlbmRhciBhcmUgc3RvcmVkIGluIHRoZSAndW1tYWxxdXJhX2RhdCcgYXJyYXlcbiAgICAgICAgdmFyIGluZGV4ID0gMDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB1bW1hbHF1cmFfZGF0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodW1tYWxxdXJhX2RhdFtpXSA+IG1jamRuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICh1bW1hbHF1cmFfZGF0W2luZGV4XSAtIHVtbWFscXVyYV9kYXRbaW5kZXggLSAxXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAzMDsgLy8gVW5rbm93biBvdXRzaWRlXG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgYSB3ZWVrIGRheS5cbiAgICAgICAgQG1lbWJlcm9mIFVtbUFsUXVyYUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgd2VlayBkYXksIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24gKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpICE9PSA1O1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIEp1bGlhbiBkYXRlIGVxdWl2YWxlbnQgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiBkYXlzIHNpbmNlIEphbnVhcnkgMSwgNDcxMyBCQ0UgR3JlZW53aWNoIG5vb24uXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBlcXVpdmFsZW50IEp1bGlhbiBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHRvSkQ6IGZ1bmN0aW9uICh5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSwgbWFpbi5sb2NhbC5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHZhciBpbmRleCA9ICgxMiAqIChkYXRlLnllYXIoKSAtIDEpKSArIGRhdGUubW9udGgoKSAtIDE1MjkyO1xuICAgICAgICB2YXIgbWNqZG4gPSBkYXRlLmRheSgpICsgdW1tYWxxdXJhX2RhdFtpbmRleCAtIDFdIC0gMTtcbiAgICAgICAgcmV0dXJuIG1jamRuICsgMjQwMDAwMCAtIDAuNTsgLy8gTW9kaWZpZWQgQ2hyb25vbG9naWNhbCBKdWxpYW4gRGF5IE51bWJlciAoTUNKRE4pXG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgSnVsaWFuIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhclxuICAgICAgICBAcGFyYW0gamQge251bWJlcn0gVGhlIEp1bGlhbiBkYXRlIHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXF1aXZhbGVudCBkYXRlLiAqL1xuICAgIGZyb21KRDogZnVuY3Rpb24gKGpkKSB7XG4gICAgICAgIHZhciBtY2pkbiA9IGpkIC0gMjQwMDAwMCArIDAuNTsgLy8gTW9kaWZpZWQgQ2hyb25vbG9naWNhbCBKdWxpYW4gRGF5IE51bWJlciAoTUNKRE4pXG4gICAgICAgIC8vIHRoZSBNQ0pETidzIG9mIHRoZSBzdGFydCBvZiB0aGUgbHVuYXRpb25zIGluIHRoZSBVbW0gYWwtUXVyYSBjYWxlbmRhciBcbiAgICAgICAgLy8gYXJlIHN0b3JlZCBpbiB0aGUgJ3VtbWFscXVyYV9kYXQnIGFycmF5XG4gICAgICAgIHZhciBpbmRleCA9IDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdW1tYWxxdXJhX2RhdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHVtbWFscXVyYV9kYXRbaV0gPiBtY2pkbikgYnJlYWs7XG4gICAgICAgICAgICBpbmRleCsrO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsdW5hdGlvbiA9IGluZGV4ICsgMTUyOTI7IC8vVW1tQWxRdXJhIEx1bmF0aW9uIE51bWJlclxuICAgICAgICB2YXIgaWkgPSBNYXRoLmZsb29yKChsdW5hdGlvbiAtIDEpIC8gMTIpO1xuICAgICAgICB2YXIgeWVhciA9IGlpICsgMTtcbiAgICAgICAgdmFyIG1vbnRoID0gbHVuYXRpb24gLSAxMiAqIGlpO1xuICAgICAgICB2YXIgZGF5ID0gbWNqZG4gLSB1bW1hbHF1cmFfZGF0W2luZGV4IC0gMV0gKyAxO1xuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgYSBkYXRlIGlzIHZhbGlkIGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICBAbWVtYmVyb2YgVW1tQWxRdXJhQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIG1vbnRoIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gZGF5IHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgYSB2YWxpZCBkYXRlLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LiAqL1xuICAgIGlzVmFsaWQ6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIHZhbGlkID0gbWFpbi5iYXNlQ2FsZW5kYXIucHJvdG90eXBlLmlzVmFsaWQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgaWYgKHZhbGlkKSB7XG4gICAgICAgICAgICB5ZWFyID0gKHllYXIueWVhciAhPSBudWxsID8geWVhci55ZWFyIDogeWVhcik7XG4gICAgICAgICAgICB2YWxpZCA9ICh5ZWFyID49IDEyNzYgJiYgeWVhciA8PSAxNTAwKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsaWQ7XG4gICAgfSxcblxuICAgIC8qKiBDaGVjayB0aGF0IGEgY2FuZGlkYXRlIGRhdGUgaXMgZnJvbSB0aGUgc2FtZSBjYWxlbmRhciBhbmQgaXMgdmFsaWQuXG4gICAgICAgIEBtZW1iZXJvZiBVbW1BbFF1cmFDYWxlbmRhclxuICAgICAgICBAcHJpdmF0ZVxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byB2YWxpZGF0ZSBvciB0aGUgeWVhciB0byB2YWxpZGF0ZS5cbiAgICAgICAgQHBhcmFtIG1vbnRoIHtudW1iZXJ9IFRoZSBtb250aCB0byB2YWxpZGF0ZS5cbiAgICAgICAgQHBhcmFtIGRheSB7bnVtYmVyfSBUaGUgZGF5IHRvIHZhbGlkYXRlLlxuICAgICAgICBAcGFyYW0gZXJyb3Ige3N0cmluZ30gRXJyb3IgbWVzc2FnZSBpZiBpbnZhbGlkLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGRpZmZlcmVudCBjYWxlbmRhcnMgdXNlZCBvciBpbnZhbGlkIGRhdGUuICovXG4gICAgX3ZhbGlkYXRlOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5LCBlcnJvcikge1xuICAgICAgICB2YXIgZGF0ZSA9IG1haW4uYmFzZUNhbGVuZGFyLnByb3RvdHlwZS5fdmFsaWRhdGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgaWYgKGRhdGUueWVhciA8IDEyNzYgfHwgZGF0ZS55ZWFyID4gMTUwMCkge1xuICAgICAgICAgICAgdGhyb3cgZXJyb3IucmVwbGFjZSgvXFx7MFxcfS8sIHRoaXMubG9jYWwubmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfVxufSk7XG5cbi8vIFVtbUFsUXVyYSBjYWxlbmRhciBpbXBsZW1lbnRhdGlvblxubWFpbi5jYWxlbmRhcnMudW1tYWxxdXJhID0gVW1tQWxRdXJhQ2FsZW5kYXI7XG5cbnZhciB1bW1hbHF1cmFfZGF0ID0gW1xuICAgIDIwLCAgICA1MCwgICAgNzksICAgIDEwOSwgICAxMzgsICAgMTY4LCAgIDE5NywgICAyMjcsICAgMjU2LCAgIDI4NiwgICAzMTUsICAgMzQ1LCAgIDM3NCwgICA0MDQsICAgNDMzLCAgIDQ2MywgICA0OTIsICAgNTIyLCAgIDU1MSwgICA1ODEsIFxuICAgIDYxMSwgICA2NDEsICAgNjcwLCAgIDcwMCwgICA3MjksICAgNzU5LCAgIDc4OCwgICA4MTgsICAgODQ3LCAgIDg3NywgICA5MDYsICAgOTM2LCAgIDk2NSwgICA5OTUsICAgMTAyNCwgIDEwNTQsICAxMDgzLCAgMTExMywgIDExNDIsICAxMTcyLFxuICAgIDEyMDEsICAxMjMxLCAgMTI2MCwgIDEyOTAsICAxMzIwLCAgMTM1MCwgIDEzNzksICAxNDA5LCAgMTQzOCwgIDE0NjgsICAxNDk3LCAgMTUyNywgIDE1NTYsICAxNTg2LCAgMTYxNSwgIDE2NDUsICAxNjc0LCAgMTcwNCwgIDE3MzMsICAxNzYzLFxuICAgIDE3OTIsICAxODIyLCAgMTg1MSwgIDE4ODEsICAxOTEwLCAgMTk0MCwgIDE5NjksICAxOTk5LCAgMjAyOCwgIDIwNTgsICAyMDg3LCAgMjExNywgIDIxNDYsICAyMTc2LCAgMjIwNSwgIDIyMzUsICAyMjY0LCAgMjI5NCwgIDIzMjMsICAyMzUzLFxuICAgIDIzODMsICAyNDEzLCAgMjQ0MiwgIDI0NzIsICAyNTAxLCAgMjUzMSwgIDI1NjAsICAyNTkwLCAgMjYxOSwgIDI2NDksICAyNjc4LCAgMjcwOCwgIDI3MzcsICAyNzY3LCAgMjc5NiwgIDI4MjYsICAyODU1LCAgMjg4NSwgIDI5MTQsICAyOTQ0LFxuICAgIDI5NzMsICAzMDAzLCAgMzAzMiwgIDMwNjIsICAzMDkxLCAgMzEyMSwgIDMxNTAsICAzMTgwLCAgMzIwOSwgIDMyMzksICAzMjY4LCAgMzI5OCwgIDMzMjcsICAzMzU3LCAgMzM4NiwgIDM0MTYsICAzNDQ2LCAgMzQ3NiwgIDM1MDUsICAzNTM1LFxuICAgIDM1NjQsICAzNTk0LCAgMzYyMywgIDM2NTMsICAzNjgyLCAgMzcxMiwgIDM3NDEsICAzNzcxLCAgMzgwMCwgIDM4MzAsICAzODU5LCAgMzg4OSwgIDM5MTgsICAzOTQ4LCAgMzk3NywgIDQwMDcsICA0MDM2LCAgNDA2NiwgIDQwOTUsICA0MTI1LFxuICAgIDQxNTUsICA0MTg1LCAgNDIxNCwgIDQyNDQsICA0MjczLCAgNDMwMywgIDQzMzIsICA0MzYyLCAgNDM5MSwgIDQ0MjEsICA0NDUwLCAgNDQ4MCwgIDQ1MDksICA0NTM5LCAgNDU2OCwgIDQ1OTgsICA0NjI3LCAgNDY1NywgIDQ2ODYsICA0NzE2LFxuICAgIDQ3NDUsICA0Nzc1LCAgNDgwNCwgIDQ4MzQsICA0ODYzLCAgNDg5MywgIDQ5MjIsICA0OTUyLCAgNDk4MSwgIDUwMTEsICA1MDQwLCAgNTA3MCwgIDUwOTksICA1MTI5LCAgNTE1OCwgIDUxODgsICA1MjE4LCAgNTI0OCwgIDUyNzcsICA1MzA3LFxuICAgIDUzMzYsICA1MzY2LCAgNTM5NSwgIDU0MjUsICA1NDU0LCAgNTQ4NCwgIDU1MTMsICA1NTQzLCAgNTU3MiwgIDU2MDIsICA1NjMxLCAgNTY2MSwgIDU2OTAsICA1NzIwLCAgNTc0OSwgIDU3NzksICA1ODA4LCAgNTgzOCwgIDU4NjcsICA1ODk3LFxuICAgIDU5MjYsICA1OTU2LCAgNTk4NSwgIDYwMTUsICA2MDQ0LCAgNjA3NCwgIDYxMDMsICA2MTMzLCAgNjE2MiwgIDYxOTIsICA2MjIxLCAgNjI1MSwgIDYyODEsICA2MzExLCAgNjM0MCwgIDYzNzAsICA2Mzk5LCAgNjQyOSwgIDY0NTgsICA2NDg4LFxuICAgIDY1MTcsICA2NTQ3LCAgNjU3NiwgIDY2MDYsICA2NjM1LCAgNjY2NSwgIDY2OTQsICA2NzI0LCAgNjc1MywgIDY3ODMsICA2ODEyLCAgNjg0MiwgIDY4NzEsICA2OTAxLCAgNjkzMCwgIDY5NjAsICA2OTg5LCAgNzAxOSwgIDcwNDgsICA3MDc4LFxuICAgIDcxMDcsICA3MTM3LCAgNzE2NiwgIDcxOTYsICA3MjI1LCAgNzI1NSwgIDcyODQsICA3MzE0LCAgNzM0NCwgIDczNzQsICA3NDAzLCAgNzQzMywgIDc0NjIsICA3NDkyLCAgNzUyMSwgIDc1NTEsICA3NTgwLCAgNzYxMCwgIDc2MzksICA3NjY5LFxuICAgIDc2OTgsICA3NzI4LCAgNzc1NywgIDc3ODcsICA3ODE2LCAgNzg0NiwgIDc4NzUsICA3OTA1LCAgNzkzNCwgIDc5NjQsICA3OTkzLCAgODAyMywgIDgwNTMsICA4MDgzLCAgODExMiwgIDgxNDIsICA4MTcxLCAgODIwMSwgIDgyMzAsICA4MjYwLFxuICAgIDgyODksICA4MzE5LCAgODM0OCwgIDgzNzgsICA4NDA3LCAgODQzNywgIDg0NjYsICA4NDk2LCAgODUyNSwgIDg1NTUsICA4NTg0LCAgODYxNCwgIDg2NDMsICA4NjczLCAgODcwMiwgIDg3MzIsICA4NzYxLCAgODc5MSwgIDg4MjEsICA4ODUwLFxuICAgIDg4ODAsICA4OTA5LCAgODkzOCwgIDg5NjgsICA4OTk3LCAgOTAyNywgIDkwNTYsICA5MDg2LCAgOTExNSwgIDkxNDUsICA5MTc1LCAgOTIwNSwgIDkyMzQsICA5MjY0LCAgOTI5MywgIDkzMjIsICA5MzUyLCAgOTM4MSwgIDk0MTAsICA5NDQwLFxuICAgIDk0NzAsICA5NDk5LCAgOTUyOSwgIDk1NTksICA5NTg5LCAgOTYxOCwgIDk2NDgsICA5Njc3LCAgOTcwNiwgIDk3MzYsICA5NzY1LCAgOTc5NCwgIDk4MjQsICA5ODUzLCAgOTg4MywgIDk5MTMsICA5OTQzLCAgOTk3MiwgIDEwMDAyLCAxMDAzMixcbiAgICAxMDA2MSwgMTAwOTAsIDEwMTIwLCAxMDE0OSwgMTAxNzgsIDEwMjA4LCAxMDIzNywgMTAyNjcsIDEwMjk3LCAxMDMyNiwgMTAzNTYsIDEwMzg2LCAxMDQxNSwgMTA0NDUsIDEwNDc0LCAxMDUwNCwgMTA1MzMsIDEwNTYyLCAxMDU5MiwgMTA2MjEsXG4gICAgMTA2NTEsIDEwNjgwLCAxMDcxMCwgMTA3NDAsIDEwNzcwLCAxMDc5OSwgMTA4MjksIDEwODU4LCAxMDg4OCwgMTA5MTcsIDEwOTQ3LCAxMDk3NiwgMTEwMDUsIDExMDM1LCAxMTA2NCwgMTEwOTQsIDExMTI0LCAxMTE1MywgMTExODMsIDExMjEzLFxuICAgIDExMjQyLCAxMTI3MiwgMTEzMDEsIDExMzMxLCAxMTM2MCwgMTEzODksIDExNDE5LCAxMTQ0OCwgMTE0NzgsIDExNTA3LCAxMTUzNywgMTE1NjcsIDExNTk2LCAxMTYyNiwgMTE2NTUsIDExNjg1LCAxMTcxNSwgMTE3NDQsIDExNzc0LCAxMTgwMyxcbiAgICAxMTgzMiwgMTE4NjIsIDExODkxLCAxMTkyMSwgMTE5NTAsIDExOTgwLCAxMjAxMCwgMTIwMzksIDEyMDY5LCAxMjA5OSwgMTIxMjgsIDEyMTU4LCAxMjE4NywgMTIyMTYsIDEyMjQ2LCAxMjI3NSwgMTIzMDQsIDEyMzM0LCAxMjM2NCwgMTIzOTMsXG4gICAgMTI0MjMsIDEyNDUzLCAxMjQ4MywgMTI1MTIsIDEyNTQyLCAxMjU3MSwgMTI2MDAsIDEyNjMwLCAxMjY1OSwgMTI2ODgsIDEyNzE4LCAxMjc0NywgMTI3NzcsIDEyODA3LCAxMjgzNywgMTI4NjYsIDEyODk2LCAxMjkyNiwgMTI5NTUsIDEyOTg0LFxuICAgIDEzMDE0LCAxMzA0MywgMTMwNzIsIDEzMTAyLCAxMzEzMSwgMTMxNjEsIDEzMTkxLCAxMzIyMCwgMTMyNTAsIDEzMjgwLCAxMzMxMCwgMTMzMzksIDEzMzY4LCAxMzM5OCwgMTM0MjcsIDEzNDU2LCAxMzQ4NiwgMTM1MTUsIDEzNTQ1LCAxMzU3NCxcbiAgICAxMzYwNCwgMTM2MzQsIDEzNjY0LCAxMzY5MywgMTM3MjMsIDEzNzUyLCAxMzc4MiwgMTM4MTEsIDEzODQwLCAxMzg3MCwgMTM4OTksIDEzOTI5LCAxMzk1OCwgMTM5ODgsIDE0MDE4LCAxNDA0NywgMTQwNzcsIDE0MTA3LCAxNDEzNiwgMTQxNjYsXG4gICAgMTQxOTUsIDE0MjI0LCAxNDI1NCwgMTQyODMsIDE0MzEzLCAxNDM0MiwgMTQzNzIsIDE0NDAxLCAxNDQzMSwgMTQ0NjEsIDE0NDkwLCAxNDUyMCwgMTQ1NTAsIDE0NTc5LCAxNDYwOSwgMTQ2MzgsIDE0NjY3LCAxNDY5NywgMTQ3MjYsIDE0NzU2LFxuICAgIDE0Nzg1LCAxNDgxNSwgMTQ4NDQsIDE0ODc0LCAxNDkwNCwgMTQ5MzMsIDE0OTYzLCAxNDk5MywgMTUwMjEsIDE1MDUxLCAxNTA4MSwgMTUxMTAsIDE1MTQwLCAxNTE2OSwgMTUxOTksIDE1MjI4LCAxNTI1OCwgMTUyODcsIDE1MzE3LCAxNTM0NyxcbiAgICAxNTM3NywgMTU0MDYsIDE1NDM2LCAxNTQ2NSwgMTU0OTQsIDE1NTI0LCAxNTU1MywgMTU1ODIsIDE1NjEyLCAxNTY0MSwgMTU2NzEsIDE1NzAxLCAxNTczMSwgMTU3NjAsIDE1NzkwLCAxNTgyMCwgMTU4NDksIDE1ODc4LCAxNTkwOCwgMTU5MzcsXG4gICAgMTU5NjYsIDE1OTk2LCAxNjAyNSwgMTYwNTUsIDE2MDg1LCAxNjExNCwgMTYxNDQsIDE2MTc0LCAxNjIwNCwgMTYyMzMsIDE2MjYyLCAxNjI5MiwgMTYzMjEsIDE2MzUwLCAxNjM4MCwgMTY0MDksIDE2NDM5LCAxNjQ2OCwgMTY0OTgsIDE2NTI4LFxuICAgIDE2NTU4LCAxNjU4NywgMTY2MTcsIDE2NjQ2LCAxNjY3NiwgMTY3MDUsIDE2NzM0LCAxNjc2NCwgMTY3OTMsIDE2ODIzLCAxNjg1MiwgMTY4ODIsIDE2OTEyLCAxNjk0MSwgMTY5NzEsIDE3MDAxLCAxNzAzMCwgMTcwNjAsIDE3MDg5LCAxNzExOCxcbiAgICAxNzE0OCwgMTcxNzcsIDE3MjA3LCAxNzIzNiwgMTcyNjYsIDE3Mjk1LCAxNzMyNSwgMTczNTUsIDE3Mzg0LCAxNzQxNCwgMTc0NDQsIDE3NDczLCAxNzUwMiwgMTc1MzIsIDE3NTYxLCAxNzU5MSwgMTc2MjAsIDE3NjUwLCAxNzY3OSwgMTc3MDksXG4gICAgMTc3MzgsIDE3NzY4LCAxNzc5OCwgMTc4MjcsIDE3ODU3LCAxNzg4NiwgMTc5MTYsIDE3OTQ1LCAxNzk3NSwgMTgwMDQsIDE4MDM0LCAxODA2MywgMTgwOTMsIDE4MTIyLCAxODE1MiwgMTgxODEsIDE4MjExLCAxODI0MSwgMTgyNzAsIDE4MzAwLFxuICAgIDE4MzMwLCAxODM1OSwgMTgzODgsIDE4NDE4LCAxODQ0NywgMTg0NzYsIDE4NTA2LCAxODUzNSwgMTg1NjUsIDE4NTk1LCAxODYyNSwgMTg2NTQsIDE4Njg0LCAxODcxNCwgMTg3NDMsIDE4NzcyLCAxODgwMiwgMTg4MzEsIDE4ODYwLCAxODg5MCxcbiAgICAxODkxOSwgMTg5NDksIDE4OTc5LCAxOTAwOCwgMTkwMzgsIDE5MDY4LCAxOTA5OCwgMTkxMjcsIDE5MTU2LCAxOTE4NiwgMTkyMTUsIDE5MjQ0LCAxOTI3NCwgMTkzMDMsIDE5MzMzLCAxOTM2MiwgMTkzOTIsIDE5NDIyLCAxOTQ1MiwgMTk0ODEsXG4gICAgMTk1MTEsIDE5NTQwLCAxOTU3MCwgMTk1OTksIDE5NjI4LCAxOTY1OCwgMTk2ODcsIDE5NzE3LCAxOTc0NiwgMTk3NzYsIDE5ODA2LCAxOTgzNiwgMTk4NjUsIDE5ODk1LCAxOTkyNCwgMTk5NTQsIDE5OTgzLCAyMDAxMiwgMjAwNDIsIDIwMDcxLFxuICAgIDIwMTAxLCAyMDEzMCwgMjAxNjAsIDIwMTkwLCAyMDIxOSwgMjAyNDksIDIwMjc5LCAyMDMwOCwgMjAzMzgsIDIwMzY3LCAyMDM5NiwgMjA0MjYsIDIwNDU1LCAyMDQ4NSwgMjA1MTQsIDIwNTQ0LCAyMDU3MywgMjA2MDMsIDIwNjMzLCAyMDY2MixcbiAgICAyMDY5MiwgMjA3MjEsIDIwNzUxLCAyMDc4MCwgMjA4MTAsIDIwODM5LCAyMDg2OSwgMjA4OTgsIDIwOTI4LCAyMDk1NywgMjA5ODcsIDIxMDE2LCAyMTA0NiwgMjEwNzYsIDIxMTA1LCAyMTEzNSwgMjExNjQsIDIxMTk0LCAyMTIyMywgMjEyNTMsXG4gICAgMjEyODIsIDIxMzEyLCAyMTM0MSwgMjEzNzEsIDIxNDAwLCAyMTQzMCwgMjE0NTksIDIxNDg5LCAyMTUxOSwgMjE1NDgsIDIxNTc4LCAyMTYwNywgMjE2MzcsIDIxNjY2LCAyMTY5NiwgMjE3MjUsIDIxNzU0LCAyMTc4NCwgMjE4MTMsIDIxODQzLFxuICAgIDIxODczLCAyMTkwMiwgMjE5MzIsIDIxOTYyLCAyMTk5MSwgMjIwMjEsIDIyMDUwLCAyMjA4MCwgMjIxMDksIDIyMTM4LCAyMjE2OCwgMjIxOTcsIDIyMjI3LCAyMjI1NiwgMjIyODYsIDIyMzE2LCAyMjM0NiwgMjIzNzUsIDIyNDA1LCAyMjQzNCxcbiAgICAyMjQ2NCwgMjI0OTMsIDIyNTIyLCAyMjU1MiwgMjI1ODEsIDIyNjExLCAyMjY0MCwgMjI2NzAsIDIyNzAwLCAyMjczMCwgMjI3NTksIDIyNzg5LCAyMjgxOCwgMjI4NDgsIDIyODc3LCAyMjkwNiwgMjI5MzYsIDIyOTY1LCAyMjk5NCwgMjMwMjQsXG4gICAgMjMwNTQsIDIzMDgzLCAyMzExMywgMjMxNDMsIDIzMTczLCAyMzIwMiwgMjMyMzIsIDIzMjYxLCAyMzI5MCwgMjMzMjAsIDIzMzQ5LCAyMzM3OSwgMjM0MDgsIDIzNDM4LCAyMzQ2NywgMjM0OTcsIDIzNTI3LCAyMzU1NiwgMjM1ODYsIDIzNjE2LFxuICAgIDIzNjQ1LCAyMzY3NCwgMjM3MDQsIDIzNzMzLCAyMzc2MywgMjM3OTIsIDIzODIyLCAyMzg1MSwgMjM4ODEsIDIzOTEwLCAyMzk0MCwgMjM5NzAsIDIzOTk5LCAyNDAyOSwgMjQwNTgsIDI0MDg4LCAyNDExNywgMjQxNDcsIDI0MTc2LCAyNDIwNixcbiAgICAyNDIzNSwgMjQyNjUsIDI0Mjk0LCAyNDMyNCwgMjQzNTMsIDI0MzgzLCAyNDQxMywgMjQ0NDIsIDI0NDcyLCAyNDUwMSwgMjQ1MzEsIDI0NTYwLCAyNDU5MCwgMjQ2MTksIDI0NjQ4LCAyNDY3OCwgMjQ3MDcsIDI0NzM3LCAyNDc2NywgMjQ3OTYsXG4gICAgMjQ4MjYsIDI0ODU2LCAyNDg4NSwgMjQ5MTUsIDI0OTQ0LCAyNDk3NCwgMjUwMDMsIDI1MDMyLCAyNTA2MiwgMjUwOTEsIDI1MTIxLCAyNTE1MCwgMjUxODAsIDI1MjEwLCAyNTI0MCwgMjUyNjksIDI1Mjk5LCAyNTMyOCwgMjUzNTgsIDI1Mzg3LFxuICAgIDI1NDE2LCAyNTQ0NiwgMjU0NzUsIDI1NTA1LCAyNTUzNCwgMjU1NjQsIDI1NTk0LCAyNTYyNCwgMjU2NTMsIDI1NjgzLCAyNTcxMiwgMjU3NDIsIDI1NzcxLCAyNTgwMCwgMjU4MzAsIDI1ODU5LCAyNTg4OCwgMjU5MTgsIDI1OTQ4LCAyNTk3NyxcbiAgICAyNjAwNywgMjYwMzcsIDI2MDY3LCAyNjA5NiwgMjYxMjYsIDI2MTU1LCAyNjE4NCwgMjYyMTQsIDI2MjQzLCAyNjI3MiwgMjYzMDIsIDI2MzMyLCAyNjM2MSwgMjYzOTEsIDI2NDIxLCAyNjQ1MSwgMjY0ODAsIDI2NTEwLCAyNjUzOSwgMjY1NjgsXG4gICAgMjY1OTgsIDI2NjI3LCAyNjY1NiwgMjY2ODYsIDI2NzE1LCAyNjc0NSwgMjY3NzUsIDI2ODA1LCAyNjgzNCwgMjY4NjQsIDI2ODkzLCAyNjkyMywgMjY5NTIsIDI2OTgyLCAyNzAxMSwgMjcwNDEsIDI3MDcwLCAyNzA5OSwgMjcxMjksIDI3MTU5LFxuICAgIDI3MTg4LCAyNzIxOCwgMjcyNDgsIDI3Mjc3LCAyNzMwNywgMjczMzYsIDI3MzY2LCAyNzM5NSwgMjc0MjUsIDI3NDU0LCAyNzQ4NCwgMjc1MTMsIDI3NTQyLCAyNzU3MiwgMjc2MDIsIDI3NjMxLCAyNzY2MSwgMjc2OTEsIDI3NzIwLCAyNzc1MCxcbiAgICAyNzc3OSwgMjc4MDksIDI3ODM4LCAyNzg2OCwgMjc4OTcsIDI3OTI2LCAyNzk1NiwgMjc5ODUsIDI4MDE1LCAyODA0NSwgMjgwNzQsIDI4MTA0LCAyODEzNCwgMjgxNjMsIDI4MTkzLCAyODIyMiwgMjgyNTIsIDI4MjgxLCAyODMxMCwgMjgzNDAsXG4gICAgMjgzNjksIDI4Mzk5LCAyODQyOCwgMjg0NTgsIDI4NDg4LCAyODUxNywgMjg1NDcsIDI4NTc3LFxuICAgIC8vIEZyb20gMTM1NlxuICAgIDI4NjA3LCAyODYzNiwgMjg2NjUsIDI4Njk1LCAyODcyNCwgMjg3NTQsIDI4NzgzLCAyODgxMywgMjg4NDMsIDI4ODcyLCAyODkwMSwgMjg5MzEsIDI4OTYwLCAyODk5MCwgMjkwMTksIDI5MDQ5LCAyOTA3OCwgMjkxMDgsIDI5MTM3LCAyOTE2NyxcbiAgICAyOTE5NiwgMjkyMjYsIDI5MjU1LCAyOTI4NSwgMjkzMTUsIDI5MzQ1LCAyOTM3NSwgMjk0MDQsIDI5NDM0LCAyOTQ2MywgMjk0OTIsIDI5NTIyLCAyOTU1MSwgMjk1ODAsIDI5NjEwLCAyOTY0MCwgMjk2NjksIDI5Njk5LCAyOTcyOSwgMjk3NTksXG4gICAgMjk3ODgsIDI5ODE4LCAyOTg0NywgMjk4NzYsIDI5OTA2LCAyOTkzNSwgMjk5NjQsIDI5OTk0LCAzMDAyMywgMzAwNTMsIDMwMDgyLCAzMDExMiwgMzAxNDEsIDMwMTcxLCAzMDIwMCwgMzAyMzAsIDMwMjU5LCAzMDI4OSwgMzAzMTgsIDMwMzQ4LFxuICAgIDMwMzc4LCAzMDQwOCwgMzA0MzcsIDMwNDY3LCAzMDQ5NiwgMzA1MjYsIDMwNTU1LCAzMDU4NSwgMzA2MTQsIDMwNjQ0LCAzMDY3MywgMzA3MDMsIDMwNzMyLCAzMDc2MiwgMzA3OTEsIDMwODIxLCAzMDg1MCwgMzA4ODAsIDMwOTA5LCAzMDkzOSxcbiAgICAzMDk2OCwgMzA5OTgsIDMxMDI3LCAzMTA1NywgMzEwODYsIDMxMTE2LCAzMTE0NSwgMzExNzUsIDMxMjA0LCAzMTIzNCwgMzEyNjMsIDMxMjkzLCAzMTMyMiwgMzEzNTIsIDMxMzgxLCAzMTQxMSwgMzE0NDEsIDMxNDcxLCAzMTUwMCwgMzE1MzAsXG4gICAgMzE1NTksIDMxNTg5LCAzMTYxOCwgMzE2NDgsIDMxNjc2LCAzMTcwNiwgMzE3MzYsIDMxNzY2LCAzMTc5NSwgMzE4MjUsIDMxODU0LCAzMTg4NCwgMzE5MTMsIDMxOTQzLCAzMTk3MiwgMzIwMDIsIDMyMDMxLCAzMjA2MSwgMzIwOTAsIDMyMTIwLFxuICAgIDMyMTUwLCAzMjE4MCwgMzIyMDksIDMyMjM5LCAzMjI2OCwgMzIyOTgsIDMyMzI3LCAzMjM1NywgMzIzODYsIDMyNDE2LCAzMjQ0NSwgMzI0NzUsIDMyNTA0LCAzMjUzNCwgMzI1NjMsIDMyNTkzLCAzMjYyMiwgMzI2NTIsIDMyNjgxLCAzMjcxMSxcbiAgICAzMjc0MCwgMzI3NzAsIDMyNzk5LCAzMjgyOSwgMzI4NTgsIDMyODg4LCAzMjkxNywgMzI5NDcsIDMyOTc2LCAzMzAwNiwgMzMwMzUsIDMzMDY1LCAzMzA5NCwgMzMxMjQsIDMzMTUzLCAzMzE4MywgMzMyMTMsIDMzMjQzLCAzMzI3MiwgMzMzMDIsXG4gICAgMzMzMzEsIDMzMzYxLCAzMzM5MCwgMzM0MjAsIDMzNDUwLCAzMzQ3OSwgMzM1MDksIDMzNTM5LCAzMzU2OCwgMzM1OTgsIDMzNjI3LCAzMzY1NywgMzM2ODYsIDMzNzE2LCAzMzc0NSwgMzM3NzUsIDMzODA0LCAzMzgzNCwgMzM4NjMsIDMzODkzLFxuICAgIDMzOTIyLCAzMzk1MiwgMzM5ODEsIDM0MDExLCAzNDA0MCwgMzQwNjksIDM0MDk5LCAzNDEyOCwgMzQxNTgsIDM0MTg3LCAzNDIxNywgMzQyNDcsIDM0Mjc3LCAzNDMwNiwgMzQzMzYsIDM0MzY1LCAzNDM5NSwgMzQ0MjQsIDM0NDU0LCAzNDQ4MyxcbiAgICAzNDUxMiwgMzQ1NDIsIDM0NTcxLCAzNDYwMSwgMzQ2MzEsIDM0NjYwLCAzNDY5MCwgMzQ3MTksIDM0NzQ5LCAzNDc3OCwgMzQ4MDgsIDM0ODM3LCAzNDg2NywgMzQ4OTYsIDM0OTI2LCAzNDk1NSwgMzQ5ODUsIDM1MDE1LCAzNTA0NCwgMzUwNzQsXG4gICAgMzUxMDMsIDM1MTMzLCAzNTE2MiwgMzUxOTIsIDM1MjIyLCAzNTI1MSwgMzUyODAsIDM1MzEwLCAzNTM0MCwgMzUzNzAsIDM1Mzk5LCAzNTQyOSwgMzU0NTgsIDM1NDg4LCAzNTUxNywgMzU1NDcsIDM1NTc2LCAzNTYwNSwgMzU2MzUsIDM1NjY1LFxuICAgIDM1Njk0LCAzNTcyMywgMzU3NTMsIDM1NzgyLCAzNTgxMSwgMzU4NDEsIDM1ODcxLCAzNTkwMSwgMzU5MzAsIDM1OTYwLCAzNTk4OSwgMzYwMTksIDM2MDQ4LCAzNjA3OCwgMzYxMDcsIDM2MTM2LCAzNjE2NiwgMzYxOTUsIDM2MjI1LCAzNjI1NCxcbiAgICAzNjI4NCwgMzYzMTQsIDM2MzQzLCAzNjM3MywgMzY0MDMsIDM2NDMzLCAzNjQ2MiwgMzY0OTIsIDM2NTIxLCAzNjU1MSwgMzY1ODAsIDM2NjEwLCAzNjYzOSwgMzY2NjksIDM2Njk4LCAzNjcyOCwgMzY3NTcsIDM2Nzg2LCAzNjgxNiwgMzY4NDUsXG4gICAgMzY4NzUsIDM2OTA0LCAzNjkzNCwgMzY5NjMsIDM2OTkzLCAzNzAyMiwgMzcwNTIsIDM3MDgxLCAzNzExMSwgMzcxNDEsIDM3MTcwLCAzNzIwMCwgMzcyMjksIDM3MjU5LCAzNzI4OCwgMzczMTgsIDM3MzQ3LCAzNzM3NywgMzc0MDYsIDM3NDM2LFxuICAgIDM3NDY1LCAzNzQ5NSwgMzc1MjQsIDM3NTU0LCAzNzU4NCwgMzc2MTMsIDM3NjQzLCAzNzY3MiwgMzc3MDEsIDM3NzMxLCAzNzc2MCwgMzc3OTAsIDM3ODE5LCAzNzg0OSwgMzc4NzgsIDM3OTA4LCAzNzkzOCwgMzc5NjcsIDM3OTk3LCAzODAyNyxcbiAgICAzODA1NiwgMzgwODUsIDM4MTE1LCAzODE0NCwgMzgxNzQsIDM4MjAzLCAzODIzMywgMzgyNjIsIDM4MjkyLCAzODMyMiwgMzgzNTEsIDM4MzgxLCAzODQxMCwgMzg0NDAsIDM4NDY5LCAzODQ5OSwgMzg1MjgsIDM4NTU4LCAzODU4NywgMzg2MTcsXG4gICAgMzg2NDYsIDM4Njc2LCAzODcwNSwgMzg3MzUsIDM4NzY0LCAzODc5NCwgMzg4MjMsIDM4ODUzLCAzODg4MiwgMzg5MTIsIDM4OTQxLCAzODk3MSwgMzkwMDEsIDM5MDMwLCAzOTA1OSwgMzkwODksIDM5MTE4LCAzOTE0OCwgMzkxNzgsIDM5MjA4LFxuICAgIDM5MjM3LCAzOTI2NywgMzkyOTcsIDM5MzI2LCAzOTM1NSwgMzkzODUsIDM5NDE0LCAzOTQ0NCwgMzk0NzMsIDM5NTAzLCAzOTUzMiwgMzk1NjIsIDM5NTkyLCAzOTYyMSwgMzk2NTAsIDM5NjgwLCAzOTcwOSwgMzk3MzksIDM5NzY4LCAzOTc5OCxcbiAgICAzOTgyNywgMzk4NTcsIDM5ODg2LCAzOTkxNiwgMzk5NDYsIDM5OTc1LCA0MDAwNSwgNDAwMzUsIDQwMDY0LCA0MDA5NCwgNDAxMjMsIDQwMTUzLCA0MDE4MiwgNDAyMTIsIDQwMjQxLCA0MDI3MSwgNDAzMDAsIDQwMzMwLCA0MDM1OSwgNDAzODksXG4gICAgNDA0MTgsIDQwNDQ4LCA0MDQ3NywgNDA1MDcsIDQwNTM2LCA0MDU2NiwgNDA1OTUsIDQwNjI1LCA0MDY1NSwgNDA2ODUsIDQwNzE0LCA0MDc0NCwgNDA3NzMsIDQwODAzLCA0MDgzMiwgNDA4NjIsIDQwODkyLCA0MDkyMSwgNDA5NTEsIDQwOTgwLFxuICAgIDQxMDA5LCA0MTAzOSwgNDEwNjgsIDQxMDk4LCA0MTEyNywgNDExNTcsIDQxMTg2LCA0MTIxNiwgNDEyNDUsIDQxMjc1LCA0MTMwNCwgNDEzMzQsIDQxMzY0LCA0MTM5MywgNDE0MjIsIDQxNDUyLCA0MTQ4MSwgNDE1MTEsIDQxNTQwLCA0MTU3MCxcbiAgICA0MTU5OSwgNDE2MjksIDQxNjU4LCA0MTY4OCwgNDE3MTgsIDQxNzQ4LCA0MTc3NywgNDE4MDcsIDQxODM2LCA0MTg2NSwgNDE4OTQsIDQxOTI0LCA0MTk1MywgNDE5ODMsIDQyMDEyLCA0MjA0MiwgNDIwNzIsIDQyMTAyLCA0MjEzMSwgNDIxNjEsXG4gICAgNDIxOTAsIDQyMjIwLCA0MjI0OSwgNDIyNzksIDQyMzA4LCA0MjMzNywgNDIzNjcsIDQyMzk3LCA0MjQyNiwgNDI0NTYsIDQyNDg1LCA0MjUxNSwgNDI1NDUsIDQyNTc0LCA0MjYwNCwgNDI2MzMsIDQyNjYyLCA0MjY5MiwgNDI3MjEsIDQyNzUxLFxuICAgIDQyNzgwLCA0MjgxMCwgNDI4MzksIDQyODY5LCA0Mjg5OSwgNDI5MjksIDQyOTU4LCA0Mjk4OCwgNDMwMTcsIDQzMDQ2LCA0MzA3NiwgNDMxMDUsIDQzMTM1LCA0MzE2NCwgNDMxOTQsIDQzMjIzLCA0MzI1MywgNDMyODMsIDQzMzEyLCA0MzM0MixcbiAgICA0MzM3MSwgNDM0MDEsIDQzNDMwLCA0MzQ2MCwgNDM0ODksIDQzNTE5LCA0MzU0OCwgNDM1NzgsIDQzNjA3LCA0MzYzNywgNDM2NjYsIDQzNjk2LCA0MzcyNiwgNDM3NTUsIDQzNzg1LCA0MzgxNCwgNDM4NDQsIDQzODczLCA0MzkwMywgNDM5MzIsXG4gICAgNDM5NjIsIDQzOTkxLCA0NDAyMSwgNDQwNTAsIDQ0MDgwLCA0NDEwOSwgNDQxMzksIDQ0MTY5LCA0NDE5OCwgNDQyMjgsIDQ0MjU4LCA0NDI4NywgNDQzMTcsIDQ0MzQ2LCA0NDM3NSwgNDQ0MDUsIDQ0NDM0LCA0NDQ2NCwgNDQ0OTMsIDQ0NTIzLFxuICAgIDQ0NTUzLCA0NDU4MiwgNDQ2MTIsIDQ0NjQxLCA0NDY3MSwgNDQ3MDAsIDQ0NzMwLCA0NDc1OSwgNDQ3ODgsIDQ0ODE4LCA0NDg0NywgNDQ4NzcsIDQ0OTA2LCA0NDkzNiwgNDQ5NjYsIDQ0OTk2LCA0NTAyNSwgNDUwNTUsIDQ1MDg0LCA0NTExNCxcbiAgICA0NTE0MywgNDUxNzIsIDQ1MjAyLCA0NTIzMSwgNDUyNjEsIDQ1MjkwLCA0NTMyMCwgNDUzNTAsIDQ1MzgwLCA0NTQwOSwgNDU0MzksIDQ1NDY4LCA0NTQ5OCwgNDU1MjcsIDQ1NTU2LCA0NTU4NiwgNDU2MTUsIDQ1NjQ0LCA0NTY3NCwgNDU3MDQsXG4gICAgNDU3MzMsIDQ1NzYzLCA0NTc5MywgNDU4MjMsIDQ1ODUyLCA0NTg4MiwgNDU5MTEsIDQ1OTQwLCA0NTk3MCwgNDU5OTksIDQ2MDI4LCA0NjA1OCwgNDYwODgsIDQ2MTE3LCA0NjE0NywgNDYxNzcsIDQ2MjA2LCA0NjIzNiwgNDYyNjUsIDQ2Mjk1LFxuICAgIDQ2MzI0LCA0NjM1NCwgNDYzODMsIDQ2NDEzLCA0NjQ0MiwgNDY0NzIsIDQ2NTAxLCA0NjUzMSwgNDY1NjAsIDQ2NTkwLCA0NjYyMCwgNDY2NDksIDQ2Njc5LCA0NjcwOCwgNDY3MzgsIDQ2NzY3LCA0Njc5NywgNDY4MjYsIDQ2ODU2LCA0Njg4NSxcbiAgICA0NjkxNSwgNDY5NDQsIDQ2OTc0LCA0NzAwMywgNDcwMzMsIDQ3MDYzLCA0NzA5MiwgNDcxMjIsIDQ3MTUxLCA0NzE4MSwgNDcyMTAsIDQ3MjQwLCA0NzI2OSwgNDcyOTgsIDQ3MzI4LCA0NzM1NywgNDczODcsIDQ3NDE3LCA0NzQ0NiwgNDc0NzYsXG4gICAgNDc1MDYsIDQ3NTM1LCA0NzU2NSwgNDc1OTQsIDQ3NjI0LCA0NzY1MywgNDc2ODIsIDQ3NzEyLCA0Nzc0MSwgNDc3NzEsIDQ3ODAwLCA0NzgzMCwgNDc4NjAsIDQ3ODkwLCA0NzkxOSwgNDc5NDksIDQ3OTc4LCA0ODAwOCwgNDgwMzcsIDQ4MDY2LFxuICAgIDQ4MDk2LCA0ODEyNSwgNDgxNTUsIDQ4MTg0LCA0ODIxNCwgNDgyNDQsIDQ4MjczLCA0ODMwMywgNDgzMzMsIDQ4MzYyLCA0ODM5MiwgNDg0MjEsIDQ4NDUwLCA0ODQ4MCwgNDg1MDksIDQ4NTM4LCA0ODU2OCwgNDg1OTgsIDQ4NjI3LCA0ODY1NyxcbiAgICA0ODY4NywgNDg3MTcsIDQ4NzQ2LCA0ODc3NiwgNDg4MDUsIDQ4ODM0LCA0ODg2NCwgNDg4OTMsIDQ4OTIyLCA0ODk1MiwgNDg5ODIsIDQ5MDExLCA0OTA0MSwgNDkwNzEsIDQ5MTAwLCA0OTEzMCwgNDkxNjAsIDQ5MTg5LCA0OTIxOCwgNDkyNDgsXG4gICAgNDkyNzcsIDQ5MzA2LCA0OTMzNiwgNDkzNjUsIDQ5Mzk1LCA0OTQyNSwgNDk0NTUsIDQ5NDg0LCA0OTUxNCwgNDk1NDMsIDQ5NTczLCA0OTYwMiwgNDk2MzIsIDQ5NjYxLCA0OTY5MCwgNDk3MjAsIDQ5NzQ5LCA0OTc3OSwgNDk4MDksIDQ5ODM4LFxuICAgIDQ5ODY4LCA0OTg5OCwgNDk5MjcsIDQ5OTU3LCA0OTk4NiwgNTAwMTYsIDUwMDQ1LCA1MDA3NSwgNTAxMDQsIDUwMTMzLCA1MDE2MywgNTAxOTIsIDUwMjIyLCA1MDI1MiwgNTAyODEsIDUwMzExLCA1MDM0MCwgNTAzNzAsIDUwNDAwLCA1MDQyOSxcbiAgICA1MDQ1OSwgNTA0ODgsIDUwNTE4LCA1MDU0NywgNTA1NzYsIDUwNjA2LCA1MDYzNSwgNTA2NjUsIDUwNjk0LCA1MDcyNCwgNTA3NTQsIDUwNzg0LCA1MDgxMywgNTA4NDMsIDUwODcyLCA1MDkwMiwgNTA5MzEsIDUwOTYwLCA1MDk5MCwgNTEwMTksXG4gICAgNTEwNDksIDUxMDc4LCA1MTEwOCwgNTExMzgsIDUxMTY3LCA1MTE5NywgNTEyMjcsIDUxMjU2LCA1MTI4NiwgNTEzMTUsIDUxMzQ1LCA1MTM3NCwgNTE0MDMsIDUxNDMzLCA1MTQ2MiwgNTE0OTIsIDUxNTIyLCA1MTU1MiwgNTE1ODIsIDUxNjExLFxuICAgIDUxNjQxLCA1MTY3MCwgNTE2OTksIDUxNzI5LCA1MTc1OCwgNTE3ODcsIDUxODE2LCA1MTg0NiwgNTE4NzYsIDUxOTA2LCA1MTkzNiwgNTE5NjUsIDUxOTk1LCA1MjAyNSwgNTIwNTQsIDUyMDgzLCA1MjExMywgNTIxNDIsIDUyMTcxLCA1MjIwMCxcbiAgICA1MjIzMCwgNTIyNjAsIDUyMjkwLCA1MjMxOSwgNTIzNDksIDUyMzc5LCA1MjQwOCwgNTI0MzgsIDUyNDY3LCA1MjQ5NywgNTI1MjYsIDUyNTU1LCA1MjU4NSwgNTI2MTQsIDUyNjQ0LCA1MjY3MywgNTI3MDMsIDUyNzMzLCA1Mjc2MiwgNTI3OTIsXG4gICAgNTI4MjIsIDUyODUxLCA1Mjg4MSwgNTI5MTAsIDUyOTM5LCA1Mjk2OSwgNTI5OTgsIDUzMDI4LCA1MzA1NywgNTMwODcsIDUzMTE2LCA1MzE0NiwgNTMxNzYsIDUzMjA1LCA1MzIzNSwgNTMyNjQsIDUzMjk0LCA1MzMyNCwgNTMzNTMsIDUzMzgzLFxuICAgIDUzNDEyLCA1MzQ0MSwgNTM0NzEsIDUzNTAwLCA1MzUzMCwgNTM1NTksIDUzNTg5LCA1MzYxOSwgNTM2NDgsIDUzNjc4LCA1MzcwOCwgNTM3MzcsIDUzNzY3LCA1Mzc5NiwgNTM4MjUsIDUzODU1LCA1Mzg4NCwgNTM5MTMsIDUzOTQzLCA1Mzk3MyxcbiAgICA1NDAwMywgNTQwMzIsIDU0MDYyLCA1NDA5MiwgNTQxMjEsIDU0MTUxLCA1NDE4MCwgNTQyMDksIDU0MjM5LCA1NDI2OCwgNTQyOTcsIDU0MzI3LCA1NDM1NywgNTQzODcsIDU0NDE2LCA1NDQ0NiwgNTQ0NzYsIDU0NTA1LCA1NDUzNSwgNTQ1NjQsXG4gICAgNTQ1OTMsIDU0NjIzLCA1NDY1MiwgNTQ2ODEsIDU0NzExLCA1NDc0MSwgNTQ3NzAsIDU0ODAwLCA1NDgzMCwgNTQ4NTksIDU0ODg5LCA1NDkxOSwgNTQ5NDgsIDU0OTc3LCA1NTAwNywgNTUwMzYsIDU1MDY2LCA1NTA5NSwgNTUxMjUsIDU1MTU0LFxuICAgIDU1MTg0LCA1NTIxMywgNTUyNDMsIDU1MjczLCA1NTMwMiwgNTUzMzIsIDU1MzYxLCA1NTM5MSwgNTU0MjAsIDU1NDUwLCA1NTQ3OSwgNTU1MDgsIDU1NTM4LCA1NTU2NywgNTU1OTcsIDU1NjI3LCA1NTY1NywgNTU2ODYsIDU1NzE2LCA1NTc0NSxcbiAgICA1NTc3NSwgNTU4MDQsIDU1ODM0LCA1NTg2MywgNTU4OTIsIDU1OTIyLCA1NTk1MSwgNTU5ODEsIDU2MDExLCA1NjA0MCwgNTYwNzAsIDU2MTAwLCA1NjEyOSwgNTYxNTksIDU2MTg4LCA1NjIxOCwgNTYyNDcsIDU2Mjc2LCA1NjMwNiwgNTYzMzUsXG4gICAgNTYzNjUsIDU2Mzk0LCA1NjQyNCwgNTY0NTQsIDU2NDgzLCA1NjUxMywgNTY1NDMsIDU2NTcyLCA1NjYwMSwgNTY2MzEsIDU2NjYwLCA1NjY5MCwgNTY3MTksIDU2NzQ5LCA1Njc3OCwgNTY4MDgsIDU2ODM3LCA1Njg2NywgNTY4OTcsIDU2OTI2LFxuICAgIDU2OTU2LCA1Njk4NSwgNTcwMTUsIDU3MDQ0LCA1NzA3NCwgNTcxMDMsIDU3MTMzLCA1NzE2MiwgNTcxOTIsIDU3MjIxLCA1NzI1MSwgNTcyODAsIDU3MzEwLCA1NzM0MCwgNTczNjksIDU3Mzk5LCA1NzQyOSwgNTc0NTgsIDU3NDg3LCA1NzUxNyxcbiAgICA1NzU0NiwgNTc1NzYsIDU3NjA1LCA1NzYzNCwgNTc2NjQsIDU3Njk0LCA1NzcyMywgNTc3NTMsIDU3NzgzLCA1NzgxMywgNTc4NDIsIDU3ODcxLCA1NzkwMSwgNTc5MzAsIDU3OTU5LCA1Nzk4OSwgNTgwMTgsIDU4MDQ4LCA1ODA3NywgNTgxMDcsXG4gICAgNTgxMzcsIDU4MTY3LCA1ODE5NiwgNTgyMjYsIDU4MjU1LCA1ODI4NSwgNTgzMTQsIDU4MzQzLCA1ODM3MywgNTg0MDIsIDU4NDMyLCA1ODQ2MSwgNTg0OTEsIDU4NTIxLCA1ODU1MSwgNTg1ODAsIDU4NjEwLCA1ODYzOSwgNTg2NjksIDU4Njk4LFxuICAgIDU4NzI3LCA1ODc1NywgNTg3ODYsIDU4ODE2LCA1ODg0NSwgNTg4NzUsIDU4OTA1LCA1ODkzNCwgNTg5NjQsIDU4OTk0LCA1OTAyMywgNTkwNTMsIDU5MDgyLCA1OTExMSwgNTkxNDEsIDU5MTcwLCA1OTIwMCwgNTkyMjksIDU5MjU5LCA1OTI4OCxcbiAgICA1OTMxOCwgNTkzNDgsIDU5Mzc3LCA1OTQwNywgNTk0MzYsIDU5NDY2LCA1OTQ5NSwgNTk1MjUsIDU5NTU0LCA1OTU4NCwgNTk2MTMsIDU5NjQzLCA1OTY3MiwgNTk3MDIsIDU5NzMxLCA1OTc2MSwgNTk3OTEsIDU5ODIwLCA1OTg1MCwgNTk4NzksXG4gICAgNTk5MDksIDU5OTM5LCA1OTk2OCwgNTk5OTcsIDYwMDI3LCA2MDA1NiwgNjAwODYsIDYwMTE1LCA2MDE0NSwgNjAxNzQsIDYwMjA0LCA2MDIzNCwgNjAyNjQsIDYwMjkzLCA2MDMyMywgNjAzNTIsIDYwMzgxLCA2MDQxMSwgNjA0NDAsIDYwNDY5LFxuICAgIDYwNDk5LCA2MDUyOCwgNjA1NTgsIDYwNTg4LCA2MDYxOCwgNjA2NDgsIDYwNjc3LCA2MDcwNywgNjA3MzYsIDYwNzY1LCA2MDc5NSwgNjA4MjQsIDYwODUzLCA2MDg4MywgNjA5MTIsIDYwOTQyLCA2MDk3MiwgNjEwMDIsIDYxMDMxLCA2MTA2MSxcbiAgICA2MTA5MCwgNjExMjAsIDYxMTQ5LCA2MTE3OSwgNjEyMDgsIDYxMjM3LCA2MTI2NywgNjEyOTYsIDYxMzI2LCA2MTM1NiwgNjEzODUsIDYxNDE1LCA2MTQ0NSwgNjE0NzQsIDYxNTA0LCA2MTUzMywgNjE1NjMsIDYxNTkyLCA2MTYyMSwgNjE2NTEsXG4gICAgNjE2ODAsIDYxNzEwLCA2MTczOSwgNjE3NjksIDYxNzk5LCA2MTgyOCwgNjE4NTgsIDYxODg4LCA2MTkxNywgNjE5NDcsIDYxOTc2LCA2MjAwNiwgNjIwMzUsIDYyMDY0LCA2MjA5NCwgNjIxMjMsIDYyMTUzLCA2MjE4MiwgNjIyMTIsIDYyMjQyLFxuICAgIDYyMjcxLCA2MjMwMSwgNjIzMzEsIDYyMzYwLCA2MjM5MCwgNjI0MTksIDYyNDQ4LCA2MjQ3OCwgNjI1MDcsIDYyNTM3LCA2MjU2NiwgNjI1OTYsIDYyNjI1LCA2MjY1NSwgNjI2ODUsIDYyNzE1LCA2Mjc0NCwgNjI3NzQsIDYyODAzLCA2MjgzMixcbiAgICA2Mjg2MiwgNjI4OTEsIDYyOTIxLCA2Mjk1MCwgNjI5ODAsIDYzMDA5LCA2MzAzOSwgNjMwNjksIDYzMDk5LCA2MzEyOCwgNjMxNTcsIDYzMTg3LCA2MzIxNiwgNjMyNDYsIDYzMjc1LCA2MzMwNSwgNjMzMzQsIDYzMzYzLCA2MzM5MywgNjM0MjMsXG4gICAgNjM0NTMsIDYzNDgyLCA2MzUxMiwgNjM1NDEsIDYzNTcxLCA2MzYwMCwgNjM2MzAsIDYzNjU5LCA2MzY4OSwgNjM3MTgsIDYzNzQ3LCA2Mzc3NywgNjM4MDcsIDYzODM2LCA2Mzg2NiwgNjM4OTUsIDYzOTI1LCA2Mzk1NSwgNjM5ODQsIDY0MDE0LFxuICAgIDY0MDQzLCA2NDA3MywgNjQxMDIsIDY0MTMxLCA2NDE2MSwgNjQxOTAsIDY0MjIwLCA2NDI0OSwgNjQyNzksIDY0MzA5LCA2NDMzOSwgNjQzNjgsIDY0Mzk4LCA2NDQyNywgNjQ0NTcsIDY0NDg2LCA2NDUxNSwgNjQ1NDUsIDY0NTc0LCA2NDYwMyxcbiAgICA2NDYzMywgNjQ2NjMsIDY0NjkyLCA2NDcyMiwgNjQ3NTIsIDY0NzgyLCA2NDgxMSwgNjQ4NDEsIDY0ODcwLCA2NDg5OSwgNjQ5MjksIDY0OTU4LCA2NDk4NywgNjUwMTcsIDY1MDQ3LCA2NTA3NiwgNjUxMDYsIDY1MTM2LCA2NTE2NiwgNjUxOTUsXG4gICAgNjUyMjUsIDY1MjU0LCA2NTI4MywgNjUzMTMsIDY1MzQyLCA2NTM3MSwgNjU0MDEsIDY1NDMxLCA2NTQ2MCwgNjU0OTAsIDY1NTIwLCA2NTU0OSwgNjU1NzksIDY1NjA4LCA2NTYzOCwgNjU2NjcsIDY1Njk3LCA2NTcyNiwgNjU3NTUsIDY1Nzg1LFxuICAgIDY1ODE1LCA2NTg0NCwgNjU4NzQsIDY1OTAzLCA2NTkzMywgNjU5NjMsIDY1OTkyLCA2NjAyMiwgNjYwNTEsIDY2MDgxLCA2NjExMCwgNjYxNDAsIDY2MTY5LCA2NjE5OSwgNjYyMjgsIDY2MjU4LCA2NjI4NywgNjYzMTcsIDY2MzQ2LCA2NjM3NixcbiAgICA2NjQwNSwgNjY0MzUsIDY2NDY1LCA2NjQ5NCwgNjY1MjQsIDY2NTUzLCA2NjU4MywgNjY2MTIsIDY2NjQxLCA2NjY3MSwgNjY3MDAsIDY2NzMwLCA2Njc2MCwgNjY3ODksIDY2ODE5LCA2Njg0OSwgNjY4NzgsIDY2OTA4LCA2NjkzNywgNjY5NjcsXG4gICAgNjY5OTYsIDY3MDI1LCA2NzA1NSwgNjcwODQsIDY3MTE0LCA2NzE0MywgNjcxNzMsIDY3MjAzLCA2NzIzMywgNjcyNjIsIDY3MjkyLCA2NzMyMSwgNjczNTEsIDY3MzgwLCA2NzQwOSwgNjc0MzksIDY3NDY4LCA2NzQ5NywgNjc1MjcsIDY3NTU3LFxuICAgIDY3NTg3LCA2NzYxNywgNjc2NDYsIDY3Njc2LCA2NzcwNSwgNjc3MzUsIDY3NzY0LCA2Nzc5MywgNjc4MjMsIDY3ODUyLCA2Nzg4MiwgNjc5MTEsIDY3OTQxLCA2Nzk3MSwgNjgwMDAsIDY4MDMwLCA2ODA2MCwgNjgwODksIDY4MTE5LCA2ODE0OCxcbiAgICA2ODE3NywgNjgyMDcsIDY4MjM2LCA2ODI2NiwgNjgyOTUsIDY4MzI1LCA2ODM1NCwgNjgzODQsIDY4NDE0LCA2ODQ0MywgNjg0NzMsIDY4NTAyLCA2ODUzMiwgNjg1NjEsIDY4NTkxLCA2ODYyMCwgNjg2NTAsIDY4Njc5LCA2ODcwOCwgNjg3MzgsXG4gICAgNjg3NjgsIDY4Nzk3LCA2ODgyNywgNjg4NTcsIDY4ODg2LCA2ODkxNiwgNjg5NDYsIDY4OTc1LCA2OTAwNCwgNjkwMzQsIDY5MDYzLCA2OTA5MiwgNjkxMjIsIDY5MTUyLCA2OTE4MSwgNjkyMTEsIDY5MjQwLCA2OTI3MCwgNjkzMDAsIDY5MzMwLFxuICAgIDY5MzU5LCA2OTM4OCwgNjk0MTgsIDY5NDQ3LCA2OTQ3NiwgNjk1MDYsIDY5NTM1LCA2OTU2NSwgNjk1OTUsIDY5NjI0LCA2OTY1NCwgNjk2ODQsIDY5NzEzLCA2OTc0MywgNjk3NzIsIDY5ODAyLCA2OTgzMSwgNjk4NjEsIDY5ODkwLCA2OTkxOSxcbiAgICA2OTk0OSwgNjk5NzgsIDcwMDA4LCA3MDAzOCwgNzAwNjcsIDcwMDk3LCA3MDEyNiwgNzAxNTYsIDcwMTg2LCA3MDIxNSwgNzAyNDUsIDcwMjc0LCA3MDMwMywgNzAzMzMsIDcwMzYyLCA3MDM5MiwgNzA0MjEsIDcwNDUxLCA3MDQ4MSwgNzA1MTAsXG4gICAgNzA1NDAsIDcwNTcwLCA3MDU5OSwgNzA2MjksIDcwNjU4LCA3MDY4NywgNzA3MTcsIDcwNzQ2LCA3MDc3NiwgNzA4MDUsIDcwODM1LCA3MDg2NCwgNzA4OTQsIDcwOTI0LCA3MDk1NCwgNzA5ODMsIDcxMDEzLCA3MTA0MiwgNzEwNzEsIDcxMTAxLFxuICAgIDcxMTMwLCA3MTE1OSwgNzExODksIDcxMjE4LCA3MTI0OCwgNzEyNzgsIDcxMzA4LCA3MTMzNywgNzEzNjcsIDcxMzk3LCA3MTQyNiwgNzE0NTUsIDcxNDg1LCA3MTUxNCwgNzE1NDMsIDcxNTczLCA3MTYwMiwgNzE2MzIsIDcxNjYyLCA3MTY5MSxcbiAgICA3MTcyMSwgNzE3NTEsIDcxNzgxLCA3MTgxMCwgNzE4MzksIDcxODY5LCA3MTg5OCwgNzE5MjcsIDcxOTU3LCA3MTk4NiwgNzIwMTYsIDcyMDQ2LCA3MjA3NSwgNzIxMDUsIDcyMTM1LCA3MjE2NCwgNzIxOTQsIDcyMjIzLCA3MjI1MywgNzIyODIsXG4gICAgNzIzMTEsIDcyMzQxLCA3MjM3MCwgNzI0MDAsIDcyNDI5LCA3MjQ1OSwgNzI0ODksIDcyNTE4LCA3MjU0OCwgNzI1NzcsIDcyNjA3LCA3MjYzNywgNzI2NjYsIDcyNjk1LCA3MjcyNSwgNzI3NTQsIDcyNzg0LCA3MjgxMywgNzI4NDMsIDcyODcyLFxuICAgIDcyOTAyLCA3MjkzMSwgNzI5NjEsIDcyOTkxLCA3MzAyMCwgNzMwNTAsIDczMDgwLCA3MzEwOSwgNzMxMzksIDczMTY4LCA3MzE5NywgNzMyMjcsIDczMjU2LCA3MzI4NiwgNzMzMTUsIDczMzQ1LCA3MzM3NSwgNzM0MDQsIDczNDM0LCA3MzQ2NCxcbiAgICA3MzQ5MywgNzM1MjMsIDczNTUyLCA3MzU4MSwgNzM2MTEsIDczNjQwLCA3MzY2OSwgNzM2OTksIDczNzI5LCA3Mzc1OCwgNzM3ODgsIDczODE4LCA3Mzg0OCwgNzM4NzcsIDczOTA3LCA3MzkzNiwgNzM5NjUsIDczOTk1LCA3NDAyNCwgNzQwNTMsXG4gICAgNzQwODMsIDc0MTEzLCA3NDE0MiwgNzQxNzIsIDc0MjAyLCA3NDIzMSwgNzQyNjEsIDc0MjkxLCA3NDMyMCwgNzQzNDksIDc0Mzc5LCA3NDQwOCwgNzQ0MzcsIDc0NDY3LCA3NDQ5NywgNzQ1MjYsIDc0NTU2LCA3NDU4NiwgNzQ2MTUsIDc0NjQ1LFxuICAgIDc0Njc1LCA3NDcwNCwgNzQ3MzMsIDc0NzYzLCA3NDc5MiwgNzQ4MjIsIDc0ODUxLCA3NDg4MSwgNzQ5MTAsIDc0OTQwLCA3NDk2OSwgNzQ5OTksIDc1MDI5LCA3NTA1OCwgNzUwODgsIDc1MTE3LCA3NTE0NywgNzUxNzYsIDc1MjA2LCA3NTIzNSxcbiAgICA3NTI2NCwgNzUyOTQsIDc1MzIzLCA3NTM1MywgNzUzODMsIDc1NDEyLCA3NTQ0MiwgNzU0NzIsIDc1NTAxLCA3NTUzMSwgNzU1NjAsIDc1NTkwLCA3NTYxOSwgNzU2NDgsIDc1Njc4LCA3NTcwNywgNzU3MzcsIDc1NzY2LCA3NTc5NiwgNzU4MjYsXG4gICAgNzU4NTYsIDc1ODg1LCA3NTkxNSwgNzU5NDQsIDc1OTc0LCA3NjAwMywgNzYwMzIsIDc2MDYyLCA3NjA5MSwgNzYxMjEsIDc2MTUwLCA3NjE4MCwgNzYyMTAsIDc2MjM5LCA3NjI2OSwgNzYyOTksIDc2MzI4LCA3NjM1OCwgNzYzODcsIDc2NDE2LFxuICAgIDc2NDQ2LCA3NjQ3NSwgNzY1MDUsIDc2NTM0LCA3NjU2NCwgNzY1OTMsIDc2NjIzLCA3NjY1MywgNzY2ODIsIDc2NzEyLCA3Njc0MSwgNzY3NzEsIDc2ODAxLCA3NjgzMCwgNzY4NTksIDc2ODg5LCA3NjkxOCwgNzY5NDgsIDc2OTc3LCA3NzAwNyxcbiAgICA3NzAzNiwgNzcwNjYsIDc3MDk2LCA3NzEyNSwgNzcxNTUsIDc3MTg1LCA3NzIxNCwgNzcyNDMsIDc3MjczLCA3NzMwMiwgNzczMzIsIDc3MzYxLCA3NzM5MCwgNzc0MjAsIDc3NDUwLCA3NzQ3OSwgNzc1MDksIDc3NTM5LCA3NzU2OSwgNzc1OTgsXG4gICAgNzc2MjcsIDc3NjU3LCA3NzY4NiwgNzc3MTUsIDc3NzQ1LCA3Nzc3NCwgNzc4MDQsIDc3ODMzLCA3Nzg2MywgNzc4OTMsIDc3OTIzLCA3Nzk1MiwgNzc5ODIsIDc4MDExLCA3ODA0MSwgNzgwNzAsIDc4MDk5LCA3ODEyOSwgNzgxNTgsIDc4MTg4LFxuICAgIDc4MjE3LCA3ODI0NywgNzgyNzcsIDc4MzA3LCA3ODMzNiwgNzgzNjYsIDc4Mzk1LCA3ODQyNSwgNzg0NTQsIDc4NDgzLCA3ODUxMywgNzg1NDIsIDc4NTcyLCA3ODYwMSwgNzg2MzEsIDc4NjYxLCA3ODY5MCwgNzg3MjAsIDc4NzUwLCA3ODc3OSxcbiAgICA3ODgwOCwgNzg4MzgsIDc4ODY3LCA3ODg5NywgNzg5MjYsIDc4OTU2LCA3ODk4NSwgNzkwMTUsIDc5MDQ0LCA3OTA3NCwgNzkxMDQsIDc5MTMzLCA3OTE2MywgNzkxOTIsIDc5MjIyLCA3OTI1MSwgNzkyODEsIDc5MzEwLCA3OTM0MCwgNzkzNjksXG4gICAgNzkzOTksIDc5NDI4LCA3OTQ1OCwgNzk0ODcsIDc5NTE3LCA3OTU0NiwgNzk1NzYsIDc5NjA2LCA3OTYzNSwgNzk2NjUsIDc5Njk1LCA3OTcyNCwgNzk3NTMsIDc5NzgzLCA3OTgxMiwgNzk4NDEsIDc5ODcxLCA3OTkwMCwgNzk5MzAsIDc5OTYwLFxuICAgIDc5OTkwXTtcblxuXG59LHtcIi4uL21haW5cIjo1NzEsXCJvYmplY3QtYXNzaWduXCI6NDU0fV0sNTcxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qXG4gKiBXb3JsZCBDYWxlbmRhcnNcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGV4Y2pvaG5zb24vd29ybGQtY2FsZW5kYXJzXG4gKlxuICogQmF0Y2gtY29udmVydGVkIGZyb20ga2J3b29kL2NhbGVuZGFyc1xuICogTWFueSB0aGFua3MgdG8gS2VpdGggV29vZCBhbmQgYWxsIG9mIHRoZSBjb250cmlidXRvcnMgdG8gdGhlIG9yaWdpbmFsIHByb2plY3QhXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxu77u/LyogaHR0cDovL2tlaXRoLXdvb2QubmFtZS9jYWxlbmRhcnMuaHRtbFxuICAgQ2FsZW5kYXJzIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBLZWl0aCBXb29kICh3b29kLmtlaXRoe2F0fW9wdHVzbmV0LmNvbS5hdSkgQXVndXN0IDIwMDkuXG4gICBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCAoaHR0cDovL2tlaXRoLXdvb2QubmFtZS9saWNlbmNlLmh0bWwpIGxpY2Vuc2UuIFxuICAgUGxlYXNlIGF0dHJpYnV0ZSB0aGUgYXV0aG9yIGlmIHlvdSB1c2UgaXQuICovXG5cbnZhciBhc3NpZ24gPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJyk7XG5cblxuZnVuY3Rpb24gQ2FsZW5kYXJzKCkge1xuICAgIHRoaXMucmVnaW9uYWxPcHRpb25zID0gW107XG4gICAgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddID0ge1xuICAgICAgICBpbnZhbGlkQ2FsZW5kYXI6ICdDYWxlbmRhciB7MH0gbm90IGZvdW5kJyxcbiAgICAgICAgaW52YWxpZERhdGU6ICdJbnZhbGlkIHswfSBkYXRlJyxcbiAgICAgICAgaW52YWxpZE1vbnRoOiAnSW52YWxpZCB7MH0gbW9udGgnLFxuICAgICAgICBpbnZhbGlkWWVhcjogJ0ludmFsaWQgezB9IHllYXInLFxuICAgICAgICBkaWZmZXJlbnRDYWxlbmRhcnM6ICdDYW5ub3QgbWl4IHswfSBhbmQgezF9IGRhdGVzJ1xuICAgIH07XG4gICAgdGhpcy5sb2NhbCA9IHRoaXMucmVnaW9uYWxPcHRpb25zWycnXTtcbiAgICB0aGlzLmNhbGVuZGFycyA9IHt9O1xuICAgIHRoaXMuX2xvY2FsQ2FscyA9IHt9O1xufVxuXG4vKiogQ3JlYXRlIHRoZSBjYWxlbmRhcnMgcGx1Z2luLlxuICAgIDxwPlByb3ZpZGVzIHN1cHBvcnQgZm9yIHZhcmlvdXMgd29ybGQgY2FsZW5kYXJzIGluIGEgY29uc2lzdGVudCBtYW5uZXIuPC9wPlxuICAgICBAY2xhc3MgQ2FsZW5kYXJzXG4gICAgQGV4YW1wbGUgX2V4cG9ydHMuaW5zdGFuY2UoJ2p1bGlhbicpLm5ld0RhdGUoMjAxNCwgMTIsIDI1KSAqL1xuYXNzaWduKENhbGVuZGFycy5wcm90b3R5cGUsIHtcblxuICAgIC8qKiBPYnRhaW4gYSBjYWxlbmRhciBpbXBsZW1lbnRhdGlvbiBhbmQgbG9jYWxpc2F0aW9uLlxuICAgICAgICBAbWVtYmVyb2YgQ2FsZW5kYXJzXG4gICAgICAgIEBwYXJhbSBbbmFtZT0nZ3JlZ29yaWFuJ10ge3N0cmluZ30gVGhlIG5hbWUgb2YgdGhlIGNhbGVuZGFyLCBlLmcuICdncmVnb3JpYW4nLCAncGVyc2lhbicsICdpc2xhbWljJy5cbiAgICAgICAgQHBhcmFtIFtsYW5ndWFnZT0nJ10ge3N0cmluZ30gVGhlIGxhbmd1YWdlIGNvZGUgdG8gdXNlIGZvciBsb2NhbGlzYXRpb24gKGRlZmF1bHQgaXMgRW5nbGlzaCkuXG4gICAgICAgIEByZXR1cm4ge0NhbGVuZGFyfSBUaGUgY2FsZW5kYXIgYW5kIGxvY2FsaXNhdGlvbi5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBjYWxlbmRhciBub3QgZm91bmQuICovXG4gICAgaW5zdGFuY2U6IGZ1bmN0aW9uKG5hbWUsIGxhbmd1YWdlKSB7XG4gICAgICAgIG5hbWUgPSAobmFtZSB8fCAnZ3JlZ29yaWFuJykudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgbGFuZ3VhZ2UgPSBsYW5ndWFnZSB8fCAnJztcbiAgICAgICAgdmFyIGNhbCA9IHRoaXMuX2xvY2FsQ2Fsc1tuYW1lICsgJy0nICsgbGFuZ3VhZ2VdO1xuICAgICAgICBpZiAoIWNhbCAmJiB0aGlzLmNhbGVuZGFyc1tuYW1lXSkge1xuICAgICAgICAgICAgY2FsID0gbmV3IHRoaXMuY2FsZW5kYXJzW25hbWVdKGxhbmd1YWdlKTtcbiAgICAgICAgICAgIHRoaXMuX2xvY2FsQ2Fsc1tuYW1lICsgJy0nICsgbGFuZ3VhZ2VdID0gY2FsO1xuICAgICAgICB9XG4gICAgICAgIGlmICghY2FsKSB7XG4gICAgICAgICAgICB0aHJvdyAodGhpcy5sb2NhbC5pbnZhbGlkQ2FsZW5kYXIgfHwgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWRDYWxlbmRhcikuXG4gICAgICAgICAgICAgICAgcmVwbGFjZSgvXFx7MFxcfS8sIG5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjYWw7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSAtIGZvciB0b2RheSBpZiBubyBvdGhlciBwYXJhbWV0ZXJzIGdpdmVuLlxuICAgICAgICBAbWVtYmVyb2YgQ2FsZW5kYXJzXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvcHkgb3IgdGhlIHllYXIgZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEBwYXJhbSBbY2FsZW5kYXI9J2dyZWdvcmlhbiddIHtCYXNlQ2FsZW5kYXJ8c3RyaW5nfSBUaGUgdW5kZXJseWluZyBjYWxlbmRhciBvciB0aGUgbmFtZSBvZiB0aGUgY2FsZW5kYXIuXG4gICAgICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSB0byB1c2UgZm9yIGxvY2FsaXNhdGlvbiAoZGVmYXVsdCBFbmdsaXNoKS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBuZXcgZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUuICovXG4gICAgbmV3RGF0ZTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSwgY2FsZW5kYXIsIGxhbmd1YWdlKSB7XG4gICAgICAgIGNhbGVuZGFyID0gKHllYXIgIT0gbnVsbCAmJiB5ZWFyLnllYXIgPyB5ZWFyLmNhbGVuZGFyKCkgOiAodHlwZW9mIGNhbGVuZGFyID09PSAnc3RyaW5nJyA/XG4gICAgICAgICAgICB0aGlzLmluc3RhbmNlKGNhbGVuZGFyLCBsYW5ndWFnZSkgOiBjYWxlbmRhcikpIHx8IHRoaXMuaW5zdGFuY2UoKTtcbiAgICAgICAgcmV0dXJuIGNhbGVuZGFyLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgfSxcbiAgICBcbiAgICAvKiogQSBzaW1wbGUgZGlnaXQgc3Vic3RpdHV0aW9uIGZ1bmN0aW9uIGZvciBsb2NhbGlzaW5nIG51bWJlcnMgdmlhIHRoZSBDYWxlbmRhciBkaWdpdHMgb3B0aW9uLlxuICAgICAgICBAbWVtYmVyIENhbGVuZGFyc1xuICAgICAgICBAcGFyYW0gZGlnaXRzIHtzdHJpbmdbXX0gVGhlIHN1YnN0aXR1dGUgZGlnaXRzLCBmb3IgMCB0aHJvdWdoIDkuXG4gICAgICAgIEByZXR1cm4ge2Z1bmN0aW9ufSBUaGUgc3Vic3RpdHV0aW9uIGZ1bmN0aW9uLiAqL1xuICAgIHN1YnN0aXR1dGVEaWdpdHM6IGZ1bmN0aW9uKGRpZ2l0cykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiAodmFsdWUgKyAnJykucmVwbGFjZSgvWzAtOV0vZywgZnVuY3Rpb24oZGlnaXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGlnaXRzW2RpZ2l0XTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBcbiAgICAvKiogRGlnaXQgc3Vic3RpdHV0aW9uIGZ1bmN0aW9uIGZvciBsb2NhbGlzaW5nIENoaW5lc2Ugc3R5bGUgbnVtYmVycyB2aWEgdGhlIENhbGVuZGFyIGRpZ2l0cyBvcHRpb24uXG4gICAgICAgIEBtZW1iZXIgQ2FsZW5kYXJzXG4gICAgICAgIEBwYXJhbSBkaWdpdHMge3N0cmluZ1tdfSBUaGUgc3Vic3RpdHV0ZSBkaWdpdHMsIGZvciAwIHRocm91Z2ggOS5cbiAgICAgICAgQHBhcmFtIHBvd2VycyB7c3RyaW5nW119IFRoZSBjaGFyYWN0ZXJzIGRlbm90aW5nIHBvd2VycyBvZiAxMCwgaS5lLiAxLCAxMCwgMTAwLCAxMDAwLlxuICAgICAgICBAcmV0dXJuIHtmdW5jdGlvbn0gVGhlIHN1YnN0aXR1dGlvbiBmdW5jdGlvbi4gKi9cbiAgICBzdWJzdGl0dXRlQ2hpbmVzZURpZ2l0czogZnVuY3Rpb24oZGlnaXRzLCBwb3dlcnMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgICB2YXIgbG9jYWxOdW1iZXIgPSAnJztcbiAgICAgICAgICAgIHZhciBwb3dlciA9IDA7XG4gICAgICAgICAgICB3aGlsZSAodmFsdWUgPiAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVuaXRzID0gdmFsdWUgJSAxMDtcbiAgICAgICAgICAgICAgICBsb2NhbE51bWJlciA9ICh1bml0cyA9PT0gMCA/ICcnIDogZGlnaXRzW3VuaXRzXSArIHBvd2Vyc1twb3dlcl0pICsgbG9jYWxOdW1iZXI7XG4gICAgICAgICAgICAgICAgcG93ZXIrKztcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IE1hdGguZmxvb3IodmFsdWUgLyAxMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobG9jYWxOdW1iZXIuaW5kZXhPZihkaWdpdHNbMV0gKyBwb3dlcnNbMV0pID09PSAwKSB7XG4gICAgICAgICAgICAgICAgbG9jYWxOdW1iZXIgPSBsb2NhbE51bWJlci5zdWJzdHIoMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbG9jYWxOdW1iZXIgfHwgZGlnaXRzWzBdO1xuICAgICAgICB9XG4gICAgfVxufSk7XG5cbi8qKiBHZW5lcmljIGRhdGUsIGJhc2VkIG9uIGEgcGFydGljdWxhciBjYWxlbmRhci5cbiAgICBAY2xhc3MgQ0RhdGVcbiAgICBAcGFyYW0gY2FsZW5kYXIge0Jhc2VDYWxlbmRhcn0gVGhlIHVuZGVybHlpbmcgY2FsZW5kYXIgaW1wbGVtZW50YXRpb24uXG4gICAgQHBhcmFtIHllYXIge251bWJlcn0gVGhlIHllYXIgZm9yIHRoaXMgZGF0ZS5cbiAgICBAcGFyYW0gbW9udGgge251bWJlcn0gVGhlIG1vbnRoIGZvciB0aGlzIGRhdGUuXG4gICAgQHBhcmFtIGRheSB7bnVtYmVyfSBUaGUgZGF5IGZvciB0aGlzIGRhdGUuXG4gICAgQHJldHVybiB7Q0RhdGV9IFRoZSBkYXRlIG9iamVjdC5cbiAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZS4gKi9cbmZ1bmN0aW9uIENEYXRlKGNhbGVuZGFyLCB5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgdGhpcy5fY2FsZW5kYXIgPSBjYWxlbmRhcjtcbiAgICB0aGlzLl95ZWFyID0geWVhcjtcbiAgICB0aGlzLl9tb250aCA9IG1vbnRoO1xuICAgIHRoaXMuX2RheSA9IGRheTtcbiAgICBpZiAodGhpcy5fY2FsZW5kYXIuX3ZhbGlkYXRlTGV2ZWwgPT09IDAgJiZcbiAgICAgICAgICAgICF0aGlzLl9jYWxlbmRhci5pc1ZhbGlkKHRoaXMuX3llYXIsIHRoaXMuX21vbnRoLCB0aGlzLl9kYXkpKSB7XG4gICAgICAgIHRocm93IChfZXhwb3J0cy5sb2NhbC5pbnZhbGlkRGF0ZSB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWREYXRlKS5cbiAgICAgICAgICAgIHJlcGxhY2UoL1xcezBcXH0vLCB0aGlzLl9jYWxlbmRhci5sb2NhbC5uYW1lKTtcbiAgICB9XG59XG5cbi8qKiBQYWQgYSBudW1lcmljIHZhbHVlIHdpdGggbGVhZGluZyB6ZXJvZXMuXG4gICAgQHByaXZhdGVcbiAgICBAcGFyYW0gdmFsdWUge251bWJlcn0gVGhlIG51bWJlciB0byBmb3JtYXQuXG4gICAgQHBhcmFtIGxlbmd0aCB7bnVtYmVyfSBUaGUgbWluaW11bSBsZW5ndGguXG4gICAgQHJldHVybiB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIG51bWJlci4gKi9cbmZ1bmN0aW9uIHBhZCh2YWx1ZSwgbGVuZ3RoKSB7XG4gICAgdmFsdWUgPSAnJyArIHZhbHVlO1xuICAgIHJldHVybiAnMDAwMDAwJy5zdWJzdHJpbmcoMCwgbGVuZ3RoIC0gdmFsdWUubGVuZ3RoKSArIHZhbHVlO1xufVxuXG5hc3NpZ24oQ0RhdGUucHJvdG90eXBlLCB7XG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcGFyYW0gW3llYXJdIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvcHkgb3IgdGhlIHllYXIgZm9yIHRoZSBkYXRlIChkZWZhdWx0IHRoaXMgZGF0ZSkuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IGZvciB0aGUgZGF0ZS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBuZXcgZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUuICovXG4gICAgbmV3RGF0ZTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIubmV3RGF0ZSgoeWVhciA9PSBudWxsID8gdGhpcyA6IHllYXIpLCBtb250aCwgZGF5KTtcbiAgICB9LFxuXG4gICAgLyoqIFNldCBvciByZXRyaWV2ZSB0aGUgeWVhciBmb3IgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHBhcmFtIFt5ZWFyXSB7bnVtYmVyfSBUaGUgeWVhciBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcnxDRGF0ZX0gVGhlIGRhdGUncyB5ZWFyIChpZiBubyBwYXJhbWV0ZXIpIG9yIHRoZSB1cGRhdGVkIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlLiAqL1xuICAgIHllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgcmV0dXJuIChhcmd1bWVudHMubGVuZ3RoID09PSAwID8gdGhpcy5feWVhciA6IHRoaXMuc2V0KHllYXIsICd5JykpO1xuICAgIH0sXG5cbiAgICAvKiogU2V0IG9yIHJldHJpZXZlIHRoZSBtb250aCBmb3IgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIGZvciB0aGUgZGF0ZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfENEYXRlfSBUaGUgZGF0ZSdzIG1vbnRoIChpZiBubyBwYXJhbWV0ZXIpIG9yIHRoZSB1cGRhdGVkIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlLiAqL1xuICAgIG1vbnRoOiBmdW5jdGlvbihtb250aCkge1xuICAgICAgICByZXR1cm4gKGFyZ3VtZW50cy5sZW5ndGggPT09IDAgPyB0aGlzLl9tb250aCA6IHRoaXMuc2V0KG1vbnRoLCAnbScpKTtcbiAgICB9LFxuXG4gICAgLyoqIFNldCBvciByZXRyaWV2ZSB0aGUgZGF5IGZvciB0aGlzIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcnxDRGF0YX0gVGhlIGRhdGUncyBkYXkgKGlmIG5vIHBhcmFtZXRlcikgb3IgdGhlIHVwZGF0ZWQgZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUuICovXG4gICAgZGF5OiBmdW5jdGlvbihkYXkpIHtcbiAgICAgICAgcmV0dXJuIChhcmd1bWVudHMubGVuZ3RoID09PSAwID8gdGhpcy5fZGF5IDogdGhpcy5zZXQoZGF5LCAnZCcpKTtcbiAgICB9LFxuXG4gICAgLyoqIFNldCBuZXcgdmFsdWVzIGZvciB0aGlzIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcGFyYW0geWVhciB7bnVtYmVyfSBUaGUgeWVhciBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEBwYXJhbSBtb250aCB7bnVtYmVyfSBUaGUgbW9udGggZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcGFyYW0gZGF5IHtudW1iZXJ9IFRoZSBkYXkgZm9yIHRoZSBkYXRlLlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIHVwZGF0ZWQgZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUuICovXG4gICAgZGF0ZTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICBpZiAoIXRoaXMuX2NhbGVuZGFyLmlzVmFsaWQoeWVhciwgbW9udGgsIGRheSkpIHtcbiAgICAgICAgICAgIHRocm93IChfZXhwb3J0cy5sb2NhbC5pbnZhbGlkRGF0ZSB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWREYXRlKS5cbiAgICAgICAgICAgICAgICByZXBsYWNlKC9cXHswXFx9LywgdGhpcy5fY2FsZW5kYXIubG9jYWwubmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5feWVhciA9IHllYXI7XG4gICAgICAgIHRoaXMuX21vbnRoID0gbW9udGg7XG4gICAgICAgIHRoaXMuX2RheSA9IGRheTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiB0aGlzIGlzIGEgbGVhcCB5ZWFyLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LiAqL1xuICAgIGxlYXBZZWFyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLmxlYXBZZWFyKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIGVwb2NoIGRlc2lnbmF0b3IgZm9yIHRoaXMgZGF0ZSwgZS5nLiBCQ0Ugb3IgQ0UuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtzdHJpbmd9IFRoZSBjdXJyZW50IGVwb2NoLiAqL1xuICAgIGVwb2NoOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLmVwb2NoKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogRm9ybWF0IHRoZSB5ZWFyLCBpZiBub3QgYSBzaW1wbGUgc2VxdWVudGlhbCBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtzdHJpbmd9IFRoZSBmb3JtYXR0ZWQgeWVhci4gKi9cbiAgICBmb3JtYXRZZWFyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLmZvcm1hdFllYXIodGhpcyk7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbW9udGggb2YgdGhlIHllYXIgZm9yIHRoaXMgZGF0ZSxcbiAgICAgICAgaS5lLiB0aGUgbW9udGgncyBwb3NpdGlvbiB3aXRoaW4gYSBudW1iZXJlZCB5ZWFyLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbW9udGggb2YgdGhlIHllYXI6IDxjb2RlPm1pbk1vbnRoPC9jb2RlPiB0byBtb250aHMgcGVyIHllYXIuICovXG4gICAgbW9udGhPZlllYXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIubW9udGhPZlllYXIodGhpcyk7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgd2VlayBvZiB0aGUgeWVhciBmb3IgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgd2VlayBvZiB0aGUgeWVhcjogMSB0byB3ZWVrcyBwZXIgeWVhci4gKi9cbiAgICB3ZWVrT2ZZZWFyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLndlZWtPZlllYXIodGhpcyk7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gdGhlIHllYXIgZm9yIHRoaXMgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzIGluIHRoaXMgeWVhci4gKi9cbiAgICBkYXlzSW5ZZWFyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLmRheXNJblllYXIodGhpcyk7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgZGF5IG9mIHRoZSB5ZWFyIGZvciB0aGlzIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBkYXkgb2YgdGhlIHllYXI6IDEgdG8gZGF5cyBwZXIgeWVhci4gKi9cbiAgICBkYXlPZlllYXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIuZGF5T2ZZZWFyKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIHRoZSBtb250aCBmb3IgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGRheXMuICovXG4gICAgZGF5c0luTW9udGg6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIuZGF5c0luTW9udGgodGhpcyk7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgZGF5IG9mIHRoZSB3ZWVrIGZvciB0aGlzIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBkYXkgb2YgdGhlIHdlZWs6IDAgdG8gbnVtYmVyIG9mIGRheXMgLSAxLiAqL1xuICAgIGRheU9mV2VlazogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5kYXlPZldlZWsodGhpcyk7XG4gICAgfSxcblxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgYSB3ZWVrIGRheS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgd2VlayBkYXksIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuICovXG4gICAgd2Vla0RheTogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci53ZWVrRGF5KHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBhYm91dCB0aGlzIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtvYmplY3R9IEFkZGl0aW9uYWwgaW5mb3JtYXRpb24gLSBjb250ZW50cyBkZXBlbmRzIG9uIGNhbGVuZGFyLiAqL1xuICAgIGV4dHJhSW5mbzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5leHRyYUluZm8odGhpcyk7XG4gICAgfSxcblxuICAgIC8qKiBBZGQgcGVyaW9kKHMpIHRvIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEBwYXJhbSBvZmZzZXQge251bWJlcn0gVGhlIG51bWJlciBvZiBwZXJpb2RzIHRvIGFkanVzdCBieS5cbiAgICAgICAgQHBhcmFtIHBlcmlvZCB7c3RyaW5nfSBPbmUgb2YgJ3knIGZvciB5ZWFyLCAnbScgZm9yIG1vbnRoLCAndycgZm9yIHdlZWssICdkJyBmb3IgZGF5LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIHVwZGF0ZWQgZGF0ZS4gKi9cbiAgICBhZGQ6IGZ1bmN0aW9uKG9mZnNldCwgcGVyaW9kKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5hZGQodGhpcywgb2Zmc2V0LCBwZXJpb2QpO1xuICAgIH0sXG5cbiAgICAvKiogU2V0IGEgcG9ydGlvbiBvZiB0aGUgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEBwYXJhbSB2YWx1ZSB7bnVtYmVyfSBUaGUgbmV3IHZhbHVlIGZvciB0aGUgcGVyaW9kLlxuICAgICAgICBAcGFyYW0gcGVyaW9kIHtzdHJpbmd9IE9uZSBvZiAneScgZm9yIHllYXIsICdtJyBmb3IgbW9udGgsICdkJyBmb3IgZGF5LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIHVwZGF0ZWQgZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBub3QgYSB2YWxpZCBkYXRlLiAqL1xuICAgIHNldDogZnVuY3Rpb24odmFsdWUsIHBlcmlvZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIuc2V0KHRoaXMsIHZhbHVlLCBwZXJpb2QpO1xuICAgIH0sXG5cbiAgICAvKiogQ29tcGFyZSB0aGlzIGRhdGUgdG8gYW5vdGhlciBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHBhcmFtIGRhdGUge0NEYXRlfSBUaGUgb3RoZXIgZGF0ZS5cbiAgICAgICAgQHJldHVybiB7bnVtYmVyfSAtMSBpZiB0aGlzIGRhdGUgaXMgYmVmb3JlIHRoZSBvdGhlciBkYXRlLFxuICAgICAgICAgICAgICAgIDAgaWYgdGhleSBhcmUgZXF1YWwsIG9yICsxIGlmIHRoaXMgZGF0ZSBpcyBhZnRlciB0aGUgb3RoZXIgZGF0ZS4gKi9cbiAgICBjb21wYXJlVG86IGZ1bmN0aW9uKGRhdGUpIHtcbiAgICAgICAgaWYgKHRoaXMuX2NhbGVuZGFyLm5hbWUgIT09IGRhdGUuX2NhbGVuZGFyLm5hbWUpIHtcbiAgICAgICAgICAgIHRocm93IChfZXhwb3J0cy5sb2NhbC5kaWZmZXJlbnRDYWxlbmRhcnMgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5kaWZmZXJlbnRDYWxlbmRhcnMpLlxuICAgICAgICAgICAgICAgIHJlcGxhY2UoL1xcezBcXH0vLCB0aGlzLl9jYWxlbmRhci5sb2NhbC5uYW1lKS5yZXBsYWNlKC9cXHsxXFx9LywgZGF0ZS5fY2FsZW5kYXIubG9jYWwubmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGMgPSAodGhpcy5feWVhciAhPT0gZGF0ZS5feWVhciA/IHRoaXMuX3llYXIgLSBkYXRlLl95ZWFyIDpcbiAgICAgICAgICAgIHRoaXMuX21vbnRoICE9PSBkYXRlLl9tb250aCA/IHRoaXMubW9udGhPZlllYXIoKSAtIGRhdGUubW9udGhPZlllYXIoKSA6XG4gICAgICAgICAgICB0aGlzLl9kYXkgLSBkYXRlLl9kYXkpO1xuICAgICAgICByZXR1cm4gKGMgPT09IDAgPyAwIDogKGMgPCAwID8gLTEgOiArMSkpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIGNhbGVuZGFyIGJhY2tpbmcgdGhpcyBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHJldHVybiB7QmFzZUNhbGVuZGFyfSBUaGUgY2FsZW5kYXIgaW1wbGVtZW50YXRpb24uICovXG4gICAgY2FsZW5kYXI6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXI7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgSnVsaWFuIGRhdGUgZXF1aXZhbGVudCBmb3IgdGhpcyBkYXRlLFxuICAgICAgICBpLmUuIGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbi5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuICovXG4gICAgdG9KRDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci50b0pEKHRoaXMpO1xuICAgIH0sXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIEp1bGlhbiBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHBhcmFtIGpkIHtudW1iZXJ9IFRoZSBKdWxpYW4gZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSkQ6IGZ1bmN0aW9uKGpkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5mcm9tSkQoamQpO1xuICAgIH0sXG5cbiAgICAvKiogQ29udmVydCB0aGlzIGRhdGUgdG8gYSBzdGFuZGFyZCAoR3JlZ29yaWFuKSBKYXZhU2NyaXB0IERhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtEYXRlfSBUaGUgZXF1aXZhbGVudCBKYXZhU2NyaXB0IGRhdGUuICovXG4gICAgdG9KU0RhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2FsZW5kYXIudG9KU0RhdGUodGhpcyk7XG4gICAgfSxcblxuICAgIC8qKiBDcmVhdGUgYSBuZXcgZGF0ZSBmcm9tIGEgc3RhbmRhcmQgKEdyZWdvcmlhbikgSmF2YVNjcmlwdCBEYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQ0RhdGVcbiAgICAgICAgQHBhcmFtIGpzZCB7RGF0ZX0gVGhlIEphdmFTY3JpcHQgZGF0ZSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIGVxdWl2YWxlbnQgZGF0ZS4gKi9cbiAgICBmcm9tSlNEYXRlOiBmdW5jdGlvbihqc2QpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhbGVuZGFyLmZyb21KU0RhdGUoanNkKTtcbiAgICB9LFxuXG4gICAgLyoqIENvbnZlcnQgdG8gYSBzdHJpbmcgZm9yIGRpc3BsYXkuXG4gICAgICAgIEBtZW1iZXJvZiBDRGF0ZVxuICAgICAgICBAcmV0dXJuIHtzdHJpbmd9IFRoaXMgZGF0ZSBhcyBhIHN0cmluZy4gKi9cbiAgICB0b1N0cmluZzogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAodGhpcy55ZWFyKCkgPCAwID8gJy0nIDogJycpICsgcGFkKE1hdGguYWJzKHRoaXMueWVhcigpKSwgNCkgK1xuICAgICAgICAgICAgJy0nICsgcGFkKHRoaXMubW9udGgoKSwgMikgKyAnLScgKyBwYWQodGhpcy5kYXkoKSwgMik7XG4gICAgfVxufSk7XG5cbi8qKiBCYXNpYyBmdW5jdGlvbmFsaXR5IGZvciBhbGwgY2FsZW5kYXJzLlxuICAgIE90aGVyIGNhbGVuZGFycyBzaG91bGQgZXh0ZW5kIHRoaXM6XG4gICAgPHByZT5PdGhlckNhbGVuZGFyLnByb3RvdHlwZSA9IG5ldyBCYXNlQ2FsZW5kYXI7PC9wcmU+XG4gICAgQGNsYXNzIEJhc2VDYWxlbmRhciAqL1xuZnVuY3Rpb24gQmFzZUNhbGVuZGFyKCkge1xuICAgIHRoaXMuc2hvcnRZZWFyQ3V0b2ZmID0gJysxMCc7XG59XG5cbmFzc2lnbihCYXNlQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgX3ZhbGlkYXRlTGV2ZWw6IDAsIC8vIFwiU3RhY2tcIiB0byB0dXJuIHZhbGlkYXRpb24gb24vb2ZmXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgd2l0aGluIHRoaXMgY2FsZW5kYXIgLSB0b2RheSBpZiBubyBwYXJhbWV0ZXJzIGdpdmVuLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGR1cGxpY2F0ZSBvciB0aGUgeWVhciBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCBmb3IgdGhlIGRhdGUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IGZvciB0aGUgZGF0ZS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBuZXcgZGF0ZS5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBub3QgYSB2YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbmV3RGF0ZTogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICBpZiAoeWVhciA9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b2RheSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh5ZWFyLnllYXIpIHtcbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksXG4gICAgICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZERhdGUgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRGF0ZSk7XG4gICAgICAgICAgICBkYXkgPSB5ZWFyLmRheSgpO1xuICAgICAgICAgICAgbW9udGggPSB5ZWFyLm1vbnRoKCk7XG4gICAgICAgICAgICB5ZWFyID0geWVhci55ZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBDRGF0ZSh0aGlzLCB5ZWFyLCBtb250aCwgZGF5KTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZvciB0b2RheS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVG9kYXkncyBkYXRlLiAqL1xuICAgIHRvZGF5OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZnJvbUpTRGF0ZShuZXcgRGF0ZSgpKTtcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBlcG9jaCBkZXNpZ25hdG9yIGZvciB0aGlzIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtzdHJpbmd9IFRoZSBjdXJyZW50IGVwb2NoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGVwb2NoOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHZhciBkYXRlID0gdGhpcy5fdmFsaWRhdGUoeWVhciwgdGhpcy5taW5Nb250aCwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkWWVhciB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWRZZWFyKTtcbiAgICAgICAgcmV0dXJuIChkYXRlLnllYXIoKSA8IDAgPyB0aGlzLmxvY2FsLmVwb2Noc1swXSA6IHRoaXMubG9jYWwuZXBvY2hzWzFdKTtcbiAgICB9LFxuXG4gICAgLyoqIEZvcm1hdCB0aGUgeWVhciwgaWYgbm90IGEgc2ltcGxlIHNlcXVlbnRpYWwgbnVtYmVyXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZm9ybWF0IG9yIHRoZSB5ZWFyIHRvIGZvcm1hdC5cbiAgICAgICAgQHJldHVybiB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHllYXIuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgZm9ybWF0WWVhcjogZnVuY3Rpb24oeWVhcikge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZFllYXIgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAoZGF0ZS55ZWFyKCkgPCAwID8gJy0nIDogJycpICsgcGFkKE1hdGguYWJzKGRhdGUueWVhcigpKSwgNClcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBudW1iZXIgb2YgbW9udGhzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBtb250aHMuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbW9udGhzSW5ZZWFyOiBmdW5jdGlvbih5ZWFyKSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHllYXIsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZFllYXIgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkWWVhcik7XG4gICAgICAgIHJldHVybiAxMjtcbiAgICB9LFxuXG4gICAgLyoqIENhbGN1bGF0ZSB0aGUgbW9udGgncyBvcmRpbmFsIHBvc2l0aW9uIHdpdGhpbiB0aGUgeWVhciAtXG4gICAgICAgIGZvciB0aG9zZSBjYWxlbmRhcnMgdGhhdCBkb24ndCBzdGFydCBhdCBtb250aCAxIVxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGV4YW1pbmUgb3IgdGhlIHllYXIgdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIG1vbnRoIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBvcmRpbmFsIHBvc2l0aW9uLCBzdGFydGluZyBmcm9tIDxjb2RlPm1pbk1vbnRoPC9jb2RlPi5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIHllYXIvbW9udGggb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBtb250aE9mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgdGhpcy5taW5EYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkTW9udGggfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkTW9udGgpO1xuICAgICAgICByZXR1cm4gKGRhdGUubW9udGgoKSArIHRoaXMubW9udGhzSW5ZZWFyKGRhdGUpIC0gdGhpcy5maXJzdE1vbnRoKSAlXG4gICAgICAgICAgICB0aGlzLm1vbnRoc0luWWVhcihkYXRlKSArIHRoaXMubWluTW9udGg7XG4gICAgfSxcblxuICAgIC8qKiBDYWxjdWxhdGUgYWN0dWFsIG1vbnRoIGZyb20gb3JkaW5hbCBwb3NpdGlvbiwgc3RhcnRpbmcgZnJvbSBtaW5Nb250aC5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7bnVtYmVyfSBUaGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gb3JkIHtudW1iZXJ9IFRoZSBtb250aCdzIG9yZGluYWwgcG9zaXRpb24uXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG1vbnRoJ3MgbnVtYmVyLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhci9tb250aC4gKi9cbiAgICBmcm9tTW9udGhPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG9yZCkge1xuICAgICAgICB2YXIgbSA9IChvcmQgKyB0aGlzLmZpcnN0TW9udGggLSAyICogdGhpcy5taW5Nb250aCkgJVxuICAgICAgICAgICAgdGhpcy5tb250aHNJblllYXIoeWVhcikgKyB0aGlzLm1pbk1vbnRoO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWRNb250aCB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiBtO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgeWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJblllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWRZZWFyIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZFllYXIpO1xuICAgICAgICByZXR1cm4gKHRoaXMubGVhcFllYXIoZGF0ZSkgPyAzNjYgOiAzNjUpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIGRheSBvZiB0aGUgeWVhciBmb3IgYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGRheSBvZiB0aGUgeWVhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBkYXlPZlllYXI6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZERhdGUgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHJldHVybiBkYXRlLnRvSkQoKSAtIHRoaXMubmV3RGF0ZShkYXRlLnllYXIoKSxcbiAgICAgICAgICAgIHRoaXMuZnJvbU1vbnRoT2ZZZWFyKGRhdGUueWVhcigpLCB0aGlzLm1pbk1vbnRoKSwgdGhpcy5taW5EYXkpLnRvSkQoKSArIDE7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgbnVtYmVyIG9mIGRheXMgaW4gYSB3ZWVrLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkYXlzLiAqL1xuICAgIGRheXNJbldlZWs6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gNztcbiAgICB9LFxuXG4gICAgLyoqIFJldHJpZXZlIHRoZSBkYXkgb2YgdGhlIHdlZWsgZm9yIGEgZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBkYXkgb2YgdGhlIHdlZWs6IDAgdG8gbnVtYmVyIG9mIGRheXMgLSAxLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheU9mV2VlazogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkRGF0ZSB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWREYXRlKTtcbiAgICAgICAgcmV0dXJuIChNYXRoLmZsb29yKHRoaXMudG9KRChkYXRlKSkgKyAyKSAlIHRoaXMuZGF5c0luV2VlaygpO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBhYm91dCBhIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIHllYXIge0NEYXRlfG51bWJlcn0gVGhlIGRhdGUgdG8gZXhhbWluZSBvciB0aGUgeWVhciB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIFtkYXldIHtudW1iZXJ9IFRoZSBkYXkgdG8gZXhhbWluZS5cbiAgICAgICAgQHJldHVybiB7b2JqZWN0fSBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIC0gY29udGVudHMgZGVwZW5kcyBvbiBjYWxlbmRhci5cbiAgICAgICAgQHRocm93cyBFcnJvciBpZiBhbiBpbnZhbGlkIGRhdGUgb3IgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBleHRyYUluZm86IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGUoeWVhciwgbW9udGgsIGRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWREYXRlIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZERhdGUpO1xuICAgICAgICByZXR1cm4ge307XG4gICAgfSxcblxuICAgIC8qKiBBZGQgcGVyaW9kKHMpIHRvIGEgZGF0ZS5cbiAgICAgICAgQ2F0ZXIgZm9yIG5vIHllYXIgemVyby5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0gZGF0ZSB7Q0RhdGV9IFRoZSBzdGFydGluZyBkYXRlLlxuICAgICAgICBAcGFyYW0gb2Zmc2V0IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgcGVyaW9kcyB0byBhZGp1c3QgYnkuXG4gICAgICAgIEBwYXJhbSBwZXJpb2Qge3N0cmluZ30gT25lIG9mICd5JyBmb3IgeWVhciwgJ20nIGZvciBtb250aCwgJ3cnIGZvciB3ZWVrLCAnZCcgZm9yIGRheS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSB1cGRhdGVkIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYSBkaWZmZXJlbnQgY2FsZW5kYXIgdXNlZC4gKi9cbiAgICBhZGQ6IGZ1bmN0aW9uKGRhdGUsIG9mZnNldCwgcGVyaW9kKSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKGRhdGUsIHRoaXMubWluTW9udGgsIHRoaXMubWluRGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZERhdGUgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb3JyZWN0QWRkKGRhdGUsIHRoaXMuX2FkZChkYXRlLCBvZmZzZXQsIHBlcmlvZCksIG9mZnNldCwgcGVyaW9kKTtcbiAgICB9LFxuXG4gICAgLyoqIEFkZCBwZXJpb2QocykgdG8gYSBkYXRlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSBkYXRlIHtDRGF0ZX0gVGhlIHN0YXJ0aW5nIGRhdGUuXG4gICAgICAgIEBwYXJhbSBvZmZzZXQge251bWJlcn0gVGhlIG51bWJlciBvZiBwZXJpb2RzIHRvIGFkanVzdCBieS5cbiAgICAgICAgQHBhcmFtIHBlcmlvZCB7c3RyaW5nfSBPbmUgb2YgJ3knIGZvciB5ZWFyLCAnbScgZm9yIG1vbnRoLCAndycgZm9yIHdlZWssICdkJyBmb3IgZGF5LlxuICAgICAgICBAcmV0dXJuIHtDRGF0ZX0gVGhlIHVwZGF0ZWQgZGF0ZS4gKi9cbiAgICBfYWRkOiBmdW5jdGlvbihkYXRlLCBvZmZzZXQsIHBlcmlvZCkge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZUxldmVsKys7XG4gICAgICAgIGlmIChwZXJpb2QgPT09ICdkJyB8fCBwZXJpb2QgPT09ICd3Jykge1xuICAgICAgICAgICAgdmFyIGpkID0gZGF0ZS50b0pEKCkgKyBvZmZzZXQgKiAocGVyaW9kID09PSAndycgPyB0aGlzLmRheXNJbldlZWsoKSA6IDEpO1xuICAgICAgICAgICAgdmFyIGQgPSBkYXRlLmNhbGVuZGFyKCkuZnJvbUpEKGpkKTtcbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRlTGV2ZWwtLTtcbiAgICAgICAgICAgIHJldHVybiBbZC55ZWFyKCksIGQubW9udGgoKSwgZC5kYXkoKV07XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZhciB5ID0gZGF0ZS55ZWFyKCkgKyAocGVyaW9kID09PSAneScgPyBvZmZzZXQgOiAwKTtcbiAgICAgICAgICAgIHZhciBtID0gZGF0ZS5tb250aE9mWWVhcigpICsgKHBlcmlvZCA9PT0gJ20nID8gb2Zmc2V0IDogMCk7XG4gICAgICAgICAgICB2YXIgZCA9IGRhdGUuZGF5KCk7Ly8gKyAocGVyaW9kID09PSAnZCcgPyBvZmZzZXQgOiAwKSArXG4gICAgICAgICAgICAgICAgLy8ocGVyaW9kID09PSAndycgPyBvZmZzZXQgKiB0aGlzLmRheXNJbldlZWsoKSA6IDApO1xuICAgICAgICAgICAgdmFyIHJlc3luY1llYXJNb250aCA9IGZ1bmN0aW9uKGNhbGVuZGFyKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKG0gPCBjYWxlbmRhci5taW5Nb250aCkge1xuICAgICAgICAgICAgICAgICAgICB5LS07XG4gICAgICAgICAgICAgICAgICAgIG0gKz0gY2FsZW5kYXIubW9udGhzSW5ZZWFyKHkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgeWVhck1vbnRocyA9IGNhbGVuZGFyLm1vbnRoc0luWWVhcih5KTtcbiAgICAgICAgICAgICAgICB3aGlsZSAobSA+IHllYXJNb250aHMgLSAxICsgY2FsZW5kYXIubWluTW9udGgpIHtcbiAgICAgICAgICAgICAgICAgICAgeSsrO1xuICAgICAgICAgICAgICAgICAgICBtIC09IHllYXJNb250aHM7XG4gICAgICAgICAgICAgICAgICAgIHllYXJNb250aHMgPSBjYWxlbmRhci5tb250aHNJblllYXIoeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChwZXJpb2QgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgIGlmIChkYXRlLm1vbnRoKCkgIT09IHRoaXMuZnJvbU1vbnRoT2ZZZWFyKHksIG0pKSB7IC8vIEhlYnJld1xuICAgICAgICAgICAgICAgICAgICBtID0gdGhpcy5uZXdEYXRlKHksIGRhdGUubW9udGgoKSwgdGhpcy5taW5EYXkpLm1vbnRoT2ZZZWFyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG0gPSBNYXRoLm1pbihtLCB0aGlzLm1vbnRoc0luWWVhcih5KSk7XG4gICAgICAgICAgICAgICAgZCA9IE1hdGgubWluKGQsIHRoaXMuZGF5c0luTW9udGgoeSwgdGhpcy5mcm9tTW9udGhPZlllYXIoeSwgbSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHBlcmlvZCA9PT0gJ20nKSB7XG4gICAgICAgICAgICAgICAgcmVzeW5jWWVhck1vbnRoKHRoaXMpO1xuICAgICAgICAgICAgICAgIGQgPSBNYXRoLm1pbihkLCB0aGlzLmRheXNJbk1vbnRoKHksIHRoaXMuZnJvbU1vbnRoT2ZZZWFyKHksIG0pKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgeW1kID0gW3ksIHRoaXMuZnJvbU1vbnRoT2ZZZWFyKHksIG0pLCBkXTtcbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRlTGV2ZWwtLTtcbiAgICAgICAgICAgIHJldHVybiB5bWQ7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRlTGV2ZWwtLTtcbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgLyoqIENvcnJlY3QgYSBjYW5kaWRhdGUgZGF0ZSBhZnRlciBhZGRpbmcgcGVyaW9kKHMpIHRvIGEgZGF0ZS5cbiAgICAgICAgSGFuZGxlIG5vIHllYXIgemVybyBpZiBuZWNlc3NhcnkuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHByaXZhdGVcbiAgICAgICAgQHBhcmFtIGRhdGUge0NEYXRlfSBUaGUgc3RhcnRpbmcgZGF0ZS5cbiAgICAgICAgQHBhcmFtIHltZCB7bnVtYmVyW119IFRoZSBhZGRlZCBkYXRlLlxuICAgICAgICBAcGFyYW0gb2Zmc2V0IHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgcGVyaW9kcyB0byBhZGp1c3QgYnkuXG4gICAgICAgIEBwYXJhbSBwZXJpb2Qge3N0cmluZ30gT25lIG9mICd5JyBmb3IgeWVhciwgJ20nIGZvciBtb250aCwgJ3cnIGZvciB3ZWVrLCAnZCcgZm9yIGRheS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSB1cGRhdGVkIGRhdGUuICovXG4gICAgX2NvcnJlY3RBZGQ6IGZ1bmN0aW9uKGRhdGUsIHltZCwgb2Zmc2V0LCBwZXJpb2QpIHtcbiAgICAgICAgaWYgKCF0aGlzLmhhc1llYXJaZXJvICYmIChwZXJpb2QgPT09ICd5JyB8fCBwZXJpb2QgPT09ICdtJykpIHtcbiAgICAgICAgICAgIGlmICh5bWRbMF0gPT09IDAgfHwgLy8gSW4geWVhciB6ZXJvXG4gICAgICAgICAgICAgICAgICAgIChkYXRlLnllYXIoKSA+IDApICE9PSAoeW1kWzBdID4gMCkpIHsgLy8gQ3Jvc3NlZCB5ZWFyIHplcm9cbiAgICAgICAgICAgICAgICB2YXIgYWRqID0ge3k6IFsxLCAxLCAneSddLCBtOiBbMSwgdGhpcy5tb250aHNJblllYXIoLTEpLCAnbSddLFxuICAgICAgICAgICAgICAgICAgICB3OiBbdGhpcy5kYXlzSW5XZWVrKCksIHRoaXMuZGF5c0luWWVhcigtMSksICdkJ10sXG4gICAgICAgICAgICAgICAgICAgIGQ6IFsxLCB0aGlzLmRheXNJblllYXIoLTEpLCAnZCddfVtwZXJpb2RdO1xuICAgICAgICAgICAgICAgIHZhciBkaXIgPSAob2Zmc2V0IDwgMCA/IC0xIDogKzEpO1xuICAgICAgICAgICAgICAgIHltZCA9IHRoaXMuX2FkZChkYXRlLCBvZmZzZXQgKiBhZGpbMF0gKyBkaXIgKiBhZGpbMV0sIGFkalsyXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGUuZGF0ZSh5bWRbMF0sIHltZFsxXSwgeW1kWzJdKTtcbiAgICB9LFxuXG4gICAgLyoqIFNldCBhIHBvcnRpb24gb2YgdGhlIGRhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGRhdGUge0NEYXRlfSBUaGUgc3RhcnRpbmcgZGF0ZS5cbiAgICAgICAgQHBhcmFtIHZhbHVlIHtudW1iZXJ9IFRoZSBuZXcgdmFsdWUgZm9yIHRoZSBwZXJpb2QuXG4gICAgICAgIEBwYXJhbSBwZXJpb2Qge3N0cmluZ30gT25lIG9mICd5JyBmb3IgeWVhciwgJ20nIGZvciBtb250aCwgJ2QnIGZvciBkYXkuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgdXBkYXRlZCBkYXRlLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHNldDogZnVuY3Rpb24oZGF0ZSwgdmFsdWUsIHBlcmlvZCkge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZShkYXRlLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWREYXRlIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZERhdGUpO1xuICAgICAgICB2YXIgeSA9IChwZXJpb2QgPT09ICd5JyA/IHZhbHVlIDogZGF0ZS55ZWFyKCkpO1xuICAgICAgICB2YXIgbSA9IChwZXJpb2QgPT09ICdtJyA/IHZhbHVlIDogZGF0ZS5tb250aCgpKTtcbiAgICAgICAgdmFyIGQgPSAocGVyaW9kID09PSAnZCcgPyB2YWx1ZSA6IGRhdGUuZGF5KCkpO1xuICAgICAgICBpZiAocGVyaW9kID09PSAneScgfHwgcGVyaW9kID09PSAnbScpIHtcbiAgICAgICAgICAgIGQgPSBNYXRoLm1pbihkLCB0aGlzLmRheXNJbk1vbnRoKHksIG0pKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZS5kYXRlKHksIG0sIGQpO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgYSBkYXRlIGlzIHZhbGlkIGZvciB0aGlzIGNhbGVuZGFyLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtudW1iZXJ9IFRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBtb250aCB7bnVtYmVyfSBUaGUgbW9udGggdG8gZXhhbWluZS5cbiAgICAgICAgQHBhcmFtIGRheSB7bnVtYmVyfSBUaGUgZGF5IHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIGEgdmFsaWQgZGF0ZSwgPGNvZGU+ZmFsc2U8L2NvZGU+IGlmIG5vdC4gKi9cbiAgICBpc1ZhbGlkOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5KSB7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlTGV2ZWwrKztcbiAgICAgICAgdmFyIHZhbGlkID0gKHRoaXMuaGFzWWVhclplcm8gfHwgeWVhciAhPT0gMCk7XG4gICAgICAgIGlmICh2YWxpZCkge1xuICAgICAgICAgICAgdmFyIGRhdGUgPSB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIHRoaXMubWluRGF5KTtcbiAgICAgICAgICAgIHZhbGlkID0gKG1vbnRoID49IHRoaXMubWluTW9udGggJiYgbW9udGggLSB0aGlzLm1pbk1vbnRoIDwgdGhpcy5tb250aHNJblllYXIoZGF0ZSkpICYmXG4gICAgICAgICAgICAgICAgKGRheSA+PSB0aGlzLm1pbkRheSAmJiBkYXkgLSB0aGlzLm1pbkRheSA8IHRoaXMuZGF5c0luTW9udGgoZGF0ZSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlTGV2ZWwtLTtcbiAgICAgICAgcmV0dXJuIHZhbGlkO1xuICAgIH0sXG5cbiAgICAvKiogQ29udmVydCB0aGUgZGF0ZSB0byBhIHN0YW5kYXJkIChHcmVnb3JpYW4pIEphdmFTY3JpcHQgRGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtEYXRlfSBUaGUgZXF1aXZhbGVudCBKYXZhU2NyaXB0IGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KU0RhdGU6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZERhdGUgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHJldHVybiBfZXhwb3J0cy5pbnN0YW5jZSgpLmZyb21KRCh0aGlzLnRvSkQoZGF0ZSkpLnRvSlNEYXRlKCk7XG4gICAgfSxcblxuICAgIC8qKiBDb252ZXJ0IHRoZSBkYXRlIGZyb20gYSBzdGFuZGFyZCAoR3JlZ29yaWFuKSBKYXZhU2NyaXB0IERhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGpzZCB7RGF0ZX0gVGhlIEphdmFTY3JpcHQgZGF0ZS5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGNhbGVuZGFyIGRhdGUuICovXG4gICAgZnJvbUpTRGF0ZTogZnVuY3Rpb24oanNkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZyb21KRChfZXhwb3J0cy5pbnN0YW5jZSgpLmZyb21KU0RhdGUoanNkKS50b0pEKCkpO1xuICAgIH0sXG5cbiAgICAvKiogQ2hlY2sgdGhhdCBhIGNhbmRpZGF0ZSBkYXRlIGlzIGZyb20gdGhlIHNhbWUgY2FsZW5kYXIgYW5kIGlzIHZhbGlkLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwcml2YXRlXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIHZhbGlkYXRlIG9yIHRoZSB5ZWFyIHRvIHZhbGlkYXRlLlxuICAgICAgICBAcGFyYW0gW21vbnRoXSB7bnVtYmVyfSBUaGUgbW9udGggdG8gdmFsaWRhdGUuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIHZhbGlkYXRlLlxuICAgICAgICBAcGFyYW0gZXJyb3Ige3N0cmluZ30gUnJyb3IgbWVzc2FnZSBpZiBpbnZhbGlkLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGRpZmZlcmVudCBjYWxlbmRhcnMgdXNlZCBvciBpbnZhbGlkIGRhdGUuICovXG4gICAgX3ZhbGlkYXRlOiBmdW5jdGlvbih5ZWFyLCBtb250aCwgZGF5LCBlcnJvcikge1xuICAgICAgICBpZiAoeWVhci55ZWFyKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fdmFsaWRhdGVMZXZlbCA9PT0gMCAmJiB0aGlzLm5hbWUgIT09IHllYXIuY2FsZW5kYXIoKS5uYW1lKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgKF9leHBvcnRzLmxvY2FsLmRpZmZlcmVudENhbGVuZGFycyB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmRpZmZlcmVudENhbGVuZGFycykuXG4gICAgICAgICAgICAgICAgICAgIHJlcGxhY2UoL1xcezBcXH0vLCB0aGlzLmxvY2FsLm5hbWUpLnJlcGxhY2UoL1xcezFcXH0vLCB5ZWFyLmNhbGVuZGFyKCkubG9jYWwubmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4geWVhcjtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdGhpcy5fdmFsaWRhdGVMZXZlbCsrO1xuICAgICAgICAgICAgaWYgKHRoaXMuX3ZhbGlkYXRlTGV2ZWwgPT09IDEgJiYgIXRoaXMuaXNWYWxpZCh5ZWFyLCBtb250aCwgZGF5KSkge1xuICAgICAgICAgICAgICAgIHRocm93IGVycm9yLnJlcGxhY2UoL1xcezBcXH0vLCB0aGlzLmxvY2FsLm5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRhdGUgPSB0aGlzLm5ld0RhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0ZUxldmVsLS07XG4gICAgICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhpcy5fdmFsaWRhdGVMZXZlbC0tO1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuXG4vKiogSW1wbGVtZW50YXRpb24gb2YgdGhlIFByb2xlcHRpYyBHcmVnb3JpYW4gQ2FsZW5kYXIuXG4gICAgU2VlIDxhIGhyZWY9XCI6aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HcmVnb3JpYW5fY2FsZW5kYXJcIj5odHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dyZWdvcmlhbl9jYWxlbmRhcjwvYT5cbiAgICBhbmQgPGEgaHJlZj1cImh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUHJvbGVwdGljX0dyZWdvcmlhbl9jYWxlbmRhclwiPmh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUHJvbGVwdGljX0dyZWdvcmlhbl9jYWxlbmRhcjwvYT4uXG4gICAgQGNsYXNzIEdyZWdvcmlhbkNhbGVuZGFyXG4gICAgQGF1Z21lbnRzIEJhc2VDYWxlbmRhclxuICAgIEBwYXJhbSBbbGFuZ3VhZ2U9JyddIHtzdHJpbmd9IFRoZSBsYW5ndWFnZSBjb2RlIChkZWZhdWx0IEVuZ2xpc2gpIGZvciBsb2NhbGlzYXRpb24uICovXG5mdW5jdGlvbiBHcmVnb3JpYW5DYWxlbmRhcihsYW5ndWFnZSkge1xuICAgIHRoaXMubG9jYWwgPSB0aGlzLnJlZ2lvbmFsT3B0aW9uc1tsYW5ndWFnZV0gfHwgdGhpcy5yZWdpb25hbE9wdGlvbnNbJyddO1xufVxuXG5HcmVnb3JpYW5DYWxlbmRhci5wcm90b3R5cGUgPSBuZXcgQmFzZUNhbGVuZGFyO1xuXG5hc3NpZ24oR3JlZ29yaWFuQ2FsZW5kYXIucHJvdG90eXBlLCB7XG4gICAgLyoqIFRoZSBjYWxlbmRhciBuYW1lLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXIgKi9cbiAgICBuYW1lOiAnR3JlZ29yaWFuJyxcbiAgICAgLyoqIEp1bGlhbiBkYXRlIG9mIHN0YXJ0IG9mIEdyZWdvcmlhbiBlcG9jaDogMSBKYW51YXJ5IDAwMDEgQ0UuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhciAqL1xuICAgIGpkRXBvY2g6IDE3MjE0MjUuNSxcbiAgICAgLyoqIERheXMgcGVyIG1vbnRoIGluIGEgY29tbW9uIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhciAqL1xuICAgIGRheXNQZXJNb250aDogWzMxLCAyOCwgMzEsIDMwLCAzMSwgMzAsIDMxLCAzMSwgMzAsIDMxLCAzMCwgMzFdLFxuICAgICAvKiogPGNvZGU+dHJ1ZTwvY29kZT4gaWYgaGFzIGEgeWVhciB6ZXJvLCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXIgKi9cbiAgICBoYXNZZWFyWmVybzogZmFsc2UsXG4gICAgLyoqIFRoZSBtaW5pbXVtIG1vbnRoIG51bWJlci5cbiAgICAgICAgQG1lbWJlcm9mIEdyZWdvcmlhbkNhbGVuZGFyICovXG4gICAgbWluTW9udGg6IDEsXG4gICAgLyoqIFRoZSBmaXJzdCBtb250aCBpbiB0aGUgeWVhci5cbiAgICAgICAgQG1lbWJlcm9mIEdyZWdvcmlhbkNhbGVuZGFyICovXG4gICAgZmlyc3RNb250aDogMSxcbiAgICAgLyoqIFRoZSBtaW5pbXVtIGRheSBudW1iZXIuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhciAqL1xuICAgIG1pbkRheTogMSxcblxuICAgIC8qKiBMb2NhbGlzYXRpb25zIGZvciB0aGUgcGx1Z2luLlxuICAgICAgICBFbnRyaWVzIGFyZSBvYmplY3RzIGluZGV4ZWQgYnkgdGhlIGxhbmd1YWdlIGNvZGUgKCcnIGJlaW5nIHRoZSBkZWZhdWx0IFVTL0VuZ2xpc2gpLlxuICAgICAgICBFYWNoIG9iamVjdCBoYXMgdGhlIGZvbGxvd2luZyBhdHRyaWJ1dGVzLlxuICAgICAgICBAbWVtYmVyb2YgR3JlZ29yaWFuQ2FsZW5kYXJcbiAgICAgICAgQHByb3BlcnR5IG5hbWUge3N0cmluZ30gVGhlIGNhbGVuZGFyIG5hbWUuXG4gICAgICAgIEBwcm9wZXJ0eSBlcG9jaHMge3N0cmluZ1tdfSBUaGUgZXBvY2ggbmFtZXMuXG4gICAgICAgIEBwcm9wZXJ0eSBtb250aE5hbWVzIHtzdHJpbmdbXX0gVGhlIGxvbmcgbmFtZXMgb2YgdGhlIG1vbnRocyBvZiB0aGUgeWVhci5cbiAgICAgICAgQHByb3BlcnR5IG1vbnRoTmFtZXNTaG9ydCB7c3RyaW5nW119IFRoZSBzaG9ydCBuYW1lcyBvZiB0aGUgbW9udGhzIG9mIHRoZSB5ZWFyLlxuICAgICAgICBAcHJvcGVydHkgZGF5TmFtZXMge3N0cmluZ1tdfSBUaGUgbG9uZyBuYW1lcyBvZiB0aGUgZGF5cyBvZiB0aGUgd2Vlay5cbiAgICAgICAgQHByb3BlcnR5IGRheU5hbWVzU2hvcnQge3N0cmluZ1tdfSBUaGUgc2hvcnQgbmFtZXMgb2YgdGhlIGRheXMgb2YgdGhlIHdlZWsuXG4gICAgICAgIEBwcm9wZXJ0eSBkYXlOYW1lc01pbiB7c3RyaW5nW119IFRoZSBtaW5pbWFsIG5hbWVzIG9mIHRoZSBkYXlzIG9mIHRoZSB3ZWVrLlxuICAgICAgICBAcHJvcGVydHkgZGF0ZUZvcm1hdCB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgZm9yIHRoaXMgY2FsZW5kYXIuXG4gICAgICAgICAgICAgICAgU2VlIHRoZSBvcHRpb25zIG9uIDxhIGhyZWY9XCJCYXNlQ2FsZW5kYXIuaHRtbCNmb3JtYXREYXRlXCI+PGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT48L2E+IGZvciBkZXRhaWxzLlxuICAgICAgICBAcHJvcGVydHkgZmlyc3REYXkge251bWJlcn0gVGhlIG51bWJlciBvZiB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLCBzdGFydGluZyBhdCAwLlxuICAgICAgICBAcHJvcGVydHkgaXNSVEwge251bWJlcn0gPGNvZGU+dHJ1ZTwvY29kZT4gaWYgdGhpcyBsb2NhbGlzYXRpb24gcmVhZHMgcmlnaHQtdG8tbGVmdC4gKi9cbiAgICByZWdpb25hbE9wdGlvbnM6IHsgLy8gTG9jYWxpc2F0aW9uc1xuICAgICAgICAnJzoge1xuICAgICAgICAgICAgbmFtZTogJ0dyZWdvcmlhbicsXG4gICAgICAgICAgICBlcG9jaHM6IFsnQkNFJywgJ0NFJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzOiBbJ0phbnVhcnknLCAnRmVicnVhcnknLCAnTWFyY2gnLCAnQXByaWwnLCAnTWF5JywgJ0p1bmUnLFxuICAgICAgICAgICAgJ0p1bHknLCAnQXVndXN0JywgJ1NlcHRlbWJlcicsICdPY3RvYmVyJywgJ05vdmVtYmVyJywgJ0RlY2VtYmVyJ10sXG4gICAgICAgICAgICBtb250aE5hbWVzU2hvcnQ6IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLCAnT2N0JywgJ05vdicsICdEZWMnXSxcbiAgICAgICAgICAgIGRheU5hbWVzOiBbJ1N1bmRheScsICdNb25kYXknLCAnVHVlc2RheScsICdXZWRuZXNkYXknLCAnVGh1cnNkYXknLCAnRnJpZGF5JywgJ1NhdHVyZGF5J10sXG4gICAgICAgICAgICBkYXlOYW1lc1Nob3J0OiBbJ1N1bicsICdNb24nLCAnVHVlJywgJ1dlZCcsICdUaHUnLCAnRnJpJywgJ1NhdCddLFxuICAgICAgICAgICAgZGF5TmFtZXNNaW46IFsnU3UnLCAnTW8nLCAnVHUnLCAnV2UnLCAnVGgnLCAnRnInLCAnU2EnXSxcbiAgICAgICAgICAgIGRpZ2l0czogbnVsbCxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQ6ICdtbS9kZC95eXl5JyxcbiAgICAgICAgICAgIGZpcnN0RGF5OiAwLFxuICAgICAgICAgICAgaXNSVEw6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9LFxuICAgIFxuICAgIC8qKiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGRhdGUgaXMgaW4gYSBsZWFwIHllYXIuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEByZXR1cm4ge2Jvb2xlYW59IDxjb2RlPnRydWU8L2NvZGU+IGlmIHRoaXMgaXMgYSBsZWFwIHllYXIsIDxjb2RlPmZhbHNlPC9jb2RlPiBpZiBub3QuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCB5ZWFyIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgbGVhcFllYXI6IGZ1bmN0aW9uKHllYXIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCB0aGlzLm1pbk1vbnRoLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWRZZWFyIHx8IF9leHBvcnRzLnJlZ2lvbmFsT3B0aW9uc1snJ10uaW52YWxpZFllYXIpO1xuICAgICAgICB2YXIgeWVhciA9IGRhdGUueWVhcigpICsgKGRhdGUueWVhcigpIDwgMCA/IDEgOiAwKTsgLy8gTm8geWVhciB6ZXJvXG4gICAgICAgIHJldHVybiB5ZWFyICUgNCA9PT0gMCAmJiAoeWVhciAlIDEwMCAhPT0gMCB8fCB5ZWFyICUgNDAwID09PSAwKTtcbiAgICB9LFxuXG4gICAgLyoqIERldGVybWluZSB0aGUgd2VlayBvZiB0aGUgeWVhciBmb3IgYSBkYXRlIC0gSVNPIDg2MDEuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSB3ZWVrIG9mIHRoZSB5ZWFyLCBzdGFydGluZyBmcm9tIDEuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgd2Vla09mWWVhcjogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICAvLyBGaW5kIFRodXJzZGF5IG9mIHRoaXMgd2VlayBzdGFydGluZyBvbiBNb25kYXlcbiAgICAgICAgdmFyIGNoZWNrRGF0ZSA9IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgICAgY2hlY2tEYXRlLmFkZCg0IC0gKGNoZWNrRGF0ZS5kYXlPZldlZWsoKSB8fCA3KSwgJ2QnKTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKGNoZWNrRGF0ZS5kYXlPZlllYXIoKSAtIDEpIC8gNykgKyAxO1xuICAgIH0sXG5cbiAgICAvKiogUmV0cmlldmUgdGhlIG51bWJlciBvZiBkYXlzIGluIGEgbW9udGguXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIG9mIHRoZSBtb250aC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoLlxuICAgICAgICBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIG1vbnRoLlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgbW9udGgveWVhciBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIGRheXNJbk1vbnRoOiBmdW5jdGlvbih5ZWFyLCBtb250aCkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCB0aGlzLm1pbkRheSxcbiAgICAgICAgICAgIF9leHBvcnRzLmxvY2FsLmludmFsaWRNb250aCB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWRNb250aCk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheXNQZXJNb250aFtkYXRlLm1vbnRoKCkgLSAxXSArXG4gICAgICAgICAgICAoZGF0ZS5tb250aCgpID09PSAyICYmIHRoaXMubGVhcFllYXIoZGF0ZS55ZWFyKCkpID8gMSA6IDApO1xuICAgIH0sXG5cbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBkYXRlIGlzIGEgd2VlayBkYXkuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBleGFtaW5lIG9yIHRoZSB5ZWFyIHRvIGV4YW1pbmUuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBleGFtaW5lLlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBleGFtaW5lLlxuICAgICAgICBAcmV0dXJuIHtib29sZWFufSA8Y29kZT50cnVlPC9jb2RlPiBpZiBhIHdlZWsgZGF5LCA8Y29kZT5mYWxzZTwvY29kZT4gaWYgbm90LlxuICAgICAgICBAdGhyb3dzIEVycm9yIGlmIGFuIGludmFsaWQgZGF0ZSBvciBhIGRpZmZlcmVudCBjYWxlbmRhciB1c2VkLiAqL1xuICAgIHdlZWtEYXk6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLmRheU9mV2Vlayh5ZWFyLCBtb250aCwgZGF5KSB8fCA3KSA8IDY7XG4gICAgfSxcblxuICAgIC8qKiBSZXRyaWV2ZSB0aGUgSnVsaWFuIGRhdGUgZXF1aXZhbGVudCBmb3IgdGhpcyBkYXRlLFxuICAgICAgICBpLmUuIGRheXMgc2luY2UgSmFudWFyeSAxLCA0NzEzIEJDRSBHcmVlbndpY2ggbm9vbi5cbiAgICAgICAgQG1lbWJlcm9mIEdyZWdvcmlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSB5ZWFyIHtDRGF0ZXxudW1iZXJ9IFRoZSBkYXRlIHRvIGNvbnZlcnQgb3IgdGhlIHllYXIgdG8gY29udmVydC5cbiAgICAgICAgQHBhcmFtIFttb250aF0ge251bWJlcn0gVGhlIG1vbnRoIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbZGF5XSB7bnVtYmVyfSBUaGUgZGF5IHRvIGNvbnZlcnQuXG4gICAgICAgIEByZXR1cm4ge251bWJlcn0gVGhlIGVxdWl2YWxlbnQgSnVsaWFuIGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KRDogZnVuY3Rpb24oeWVhciwgbW9udGgsIGRheSkge1xuICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuX3ZhbGlkYXRlKHllYXIsIG1vbnRoLCBkYXksXG4gICAgICAgICAgICBfZXhwb3J0cy5sb2NhbC5pbnZhbGlkRGF0ZSB8fCBfZXhwb3J0cy5yZWdpb25hbE9wdGlvbnNbJyddLmludmFsaWREYXRlKTtcbiAgICAgICAgeWVhciA9IGRhdGUueWVhcigpO1xuICAgICAgICBtb250aCA9IGRhdGUubW9udGgoKTtcbiAgICAgICAgZGF5ID0gZGF0ZS5kYXkoKTtcbiAgICAgICAgaWYgKHllYXIgPCAwKSB7IHllYXIrKzsgfSAvLyBObyB5ZWFyIHplcm9cbiAgICAgICAgLy8gSmVhbiBNZWV1cyBhbGdvcml0aG0sIFwiQXN0cm9ub21pY2FsIEFsZ29yaXRobXNcIiwgMTk5MVxuICAgICAgICBpZiAobW9udGggPCAzKSB7XG4gICAgICAgICAgICBtb250aCArPSAxMjtcbiAgICAgICAgICAgIHllYXItLTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYSA9IE1hdGguZmxvb3IoeWVhciAvIDEwMCk7XG4gICAgICAgIHZhciBiID0gMiAtIGEgKyBNYXRoLmZsb29yKGEgLyA0KTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoMzY1LjI1ICogKHllYXIgKyA0NzE2KSkgK1xuICAgICAgICAgICAgTWF0aC5mbG9vcigzMC42MDAxICogKG1vbnRoICsgMSkpICsgZGF5ICsgYiAtIDE1MjQuNTtcbiAgICB9LFxuXG4gICAgLyoqIENyZWF0ZSBhIG5ldyBkYXRlIGZyb20gYSBKdWxpYW4gZGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIEdyZWdvcmlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBqZCB7bnVtYmVyfSBUaGUgSnVsaWFuIGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpEOiBmdW5jdGlvbihqZCkge1xuICAgICAgICAvLyBKZWFuIE1lZXVzIGFsZ29yaXRobSwgXCJBc3Ryb25vbWljYWwgQWxnb3JpdGhtc1wiLCAxOTkxXG4gICAgICAgIHZhciB6ID0gTWF0aC5mbG9vcihqZCArIDAuNSk7XG4gICAgICAgIHZhciBhID0gTWF0aC5mbG9vcigoeiAtIDE4NjcyMTYuMjUpIC8gMzY1MjQuMjUpO1xuICAgICAgICBhID0geiArIDEgKyBhIC0gTWF0aC5mbG9vcihhIC8gNCk7XG4gICAgICAgIHZhciBiID0gYSArIDE1MjQ7XG4gICAgICAgIHZhciBjID0gTWF0aC5mbG9vcigoYiAtIDEyMi4xKSAvIDM2NS4yNSk7XG4gICAgICAgIHZhciBkID0gTWF0aC5mbG9vcigzNjUuMjUgKiBjKTtcbiAgICAgICAgdmFyIGUgPSBNYXRoLmZsb29yKChiIC0gZCkgLyAzMC42MDAxKTtcbiAgICAgICAgdmFyIGRheSA9IGIgLSBkIC0gTWF0aC5mbG9vcihlICogMzAuNjAwMSk7XG4gICAgICAgIHZhciBtb250aCA9IGUgLSAoZSA+IDEzLjUgPyAxMyA6IDEpO1xuICAgICAgICB2YXIgeWVhciA9IGMgLSAobW9udGggPiAyLjUgPyA0NzE2IDogNDcxNSk7XG4gICAgICAgIGlmICh5ZWFyIDw9IDApIHsgeWVhci0tOyB9IC8vIE5vIHllYXIgemVyb1xuICAgICAgICByZXR1cm4gdGhpcy5uZXdEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgIH0sXG5cbiAgICAvKiogQ29udmVydCB0aGlzIGRhdGUgdG8gYSBzdGFuZGFyZCAoR3JlZ29yaWFuKSBKYXZhU2NyaXB0IERhdGUuXG4gICAgICAgIEBtZW1iZXJvZiBHcmVnb3JpYW5DYWxlbmRhclxuICAgICAgICBAcGFyYW0geWVhciB7Q0RhdGV8bnVtYmVyfSBUaGUgZGF0ZSB0byBjb252ZXJ0IG9yIHRoZSB5ZWFyIHRvIGNvbnZlcnQuXG4gICAgICAgIEBwYXJhbSBbbW9udGhdIHtudW1iZXJ9IFRoZSBtb250aCB0byBjb252ZXJ0LlxuICAgICAgICBAcGFyYW0gW2RheV0ge251bWJlcn0gVGhlIGRheSB0byBjb252ZXJ0LlxuICAgICAgICBAcmV0dXJuIHtEYXRlfSBUaGUgZXF1aXZhbGVudCBKYXZhU2NyaXB0IGRhdGUuXG4gICAgICAgIEB0aHJvd3MgRXJyb3IgaWYgYW4gaW52YWxpZCBkYXRlIG9yIGEgZGlmZmVyZW50IGNhbGVuZGFyIHVzZWQuICovXG4gICAgdG9KU0RhdGU6IGZ1bmN0aW9uKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgICAgICAgdmFyIGRhdGUgPSB0aGlzLl92YWxpZGF0ZSh5ZWFyLCBtb250aCwgZGF5LFxuICAgICAgICAgICAgX2V4cG9ydHMubG9jYWwuaW52YWxpZERhdGUgfHwgX2V4cG9ydHMucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRGF0ZSk7XG4gICAgICAgIHZhciBqc2QgPSBuZXcgRGF0ZShkYXRlLnllYXIoKSwgZGF0ZS5tb250aCgpIC0gMSwgZGF0ZS5kYXkoKSk7XG4gICAgICAgIGpzZC5zZXRIb3VycygwKTtcbiAgICAgICAganNkLnNldE1pbnV0ZXMoMCk7XG4gICAgICAgIGpzZC5zZXRTZWNvbmRzKDApO1xuICAgICAgICBqc2Quc2V0TWlsbGlzZWNvbmRzKDApO1xuICAgICAgICAvLyBIb3VycyBtYXkgYmUgbm9uLXplcm8gb24gZGF5bGlnaHQgc2F2aW5nIGN1dC1vdmVyOlxuICAgICAgICAvLyA+IDEyIHdoZW4gbWlkbmlnaHQgY2hhbmdlb3ZlciwgYnV0IHRoZW4gY2Fubm90IGdlbmVyYXRlXG4gICAgICAgIC8vIG1pZG5pZ2h0IGRhdGV0aW1lLCBzbyBqdW1wIHRvIDFBTSwgb3RoZXJ3aXNlIHJlc2V0LlxuICAgICAgICBqc2Quc2V0SG91cnMoanNkLmdldEhvdXJzKCkgPiAxMiA/IGpzZC5nZXRIb3VycygpICsgMiA6IDApO1xuICAgICAgICByZXR1cm4ganNkO1xuICAgIH0sXG5cbiAgICAvKiogQ3JlYXRlIGEgbmV3IGRhdGUgZnJvbSBhIHN0YW5kYXJkIChHcmVnb3JpYW4pIEphdmFTY3JpcHQgRGF0ZS5cbiAgICAgICAgQG1lbWJlcm9mIEdyZWdvcmlhbkNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBqc2Qge0RhdGV9IFRoZSBKYXZhU2NyaXB0IGRhdGUgdG8gY29udmVydC5cbiAgICAgICAgQHJldHVybiB7Q0RhdGV9IFRoZSBlcXVpdmFsZW50IGRhdGUuICovXG4gICAgZnJvbUpTRGF0ZTogZnVuY3Rpb24oanNkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5ld0RhdGUoanNkLmdldEZ1bGxZZWFyKCksIGpzZC5nZXRNb250aCgpICsgMSwganNkLmdldERhdGUoKSk7XG4gICAgfVxufSk7XG5cbi8vIFNpbmdsZXRvbiBtYW5hZ2VyXG52YXIgX2V4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IG5ldyBDYWxlbmRhcnMoKTtcblxuLy8gRGF0ZSB0ZW1wbGF0ZVxuX2V4cG9ydHMuY2RhdGUgPSBDRGF0ZTtcblxuLy8gQmFzZSBjYWxlbmRhciB0ZW1wbGF0ZVxuX2V4cG9ydHMuYmFzZUNhbGVuZGFyID0gQmFzZUNhbGVuZGFyO1xuXG4vLyBHcmVnb3JpYW4gY2FsZW5kYXIgaW1wbGVtZW50YXRpb25cbl9leHBvcnRzLmNhbGVuZGFycy5ncmVnb3JpYW4gPSBHcmVnb3JpYW5DYWxlbmRhcjtcblxuXG59LHtcIm9iamVjdC1hc3NpZ25cIjo0NTR9XSw1NzI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLypcbiAqIFdvcmxkIENhbGVuZGFyc1xuICogaHR0cHM6Ly9naXRodWIuY29tL2FsZXhjam9obnNvbi93b3JsZC1jYWxlbmRhcnNcbiAqXG4gKiBCYXRjaC1jb252ZXJ0ZWQgZnJvbSBrYndvb2QvY2FsZW5kYXJzXG4gKiBNYW55IHRoYW5rcyB0byBLZWl0aCBXb29kIGFuZCBhbGwgb2YgdGhlIGNvbnRyaWJ1dG9ycyB0byB0aGUgb3JpZ2luYWwgcHJvamVjdCFcbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqL1xuXG7vu78vKiBodHRwOi8va2VpdGgtd29vZC5uYW1lL2NhbGVuZGFycy5odG1sXG4gICBDYWxlbmRhcnMgZXh0cmFzIGZvciBqUXVlcnkgdjIuMC4yLlxuICAgV3JpdHRlbiBieSBLZWl0aCBXb29kICh3b29kLmtlaXRoe2F0fW9wdHVzbmV0LmNvbS5hdSkgQXVndXN0IDIwMDkuXG4gICBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCAoaHR0cDovL2tlaXRoLXdvb2QubmFtZS9saWNlbmNlLmh0bWwpIGxpY2Vuc2UuIFxuICAgUGxlYXNlIGF0dHJpYnV0ZSB0aGUgYXV0aG9yIGlmIHlvdSB1c2UgaXQuICovXG5cbnZhciBhc3NpZ24gPSBfZGVyZXFfKCdvYmplY3QtYXNzaWduJyk7XG52YXIgbWFpbiA9IF9kZXJlcV8oJy4vbWFpbicpO1xuXG5cbmFzc2lnbihtYWluLnJlZ2lvbmFsT3B0aW9uc1snJ10sIHtcbiAgICBpbnZhbGlkQXJndW1lbnRzOiAnSW52YWxpZCBhcmd1bWVudHMnLFxuICAgIGludmFsaWRGb3JtYXQ6ICdDYW5ub3QgZm9ybWF0IGEgZGF0ZSBmcm9tIGFub3RoZXIgY2FsZW5kYXInLFxuICAgIG1pc3NpbmdOdW1iZXJBdDogJ01pc3NpbmcgbnVtYmVyIGF0IHBvc2l0aW9uIHswfScsXG4gICAgdW5rbm93bk5hbWVBdDogJ1Vua25vd24gbmFtZSBhdCBwb3NpdGlvbiB7MH0nLFxuICAgIHVuZXhwZWN0ZWRMaXRlcmFsQXQ6ICdVbmV4cGVjdGVkIGxpdGVyYWwgYXQgcG9zaXRpb24gezB9JyxcbiAgICB1bmV4cGVjdGVkVGV4dDogJ0FkZGl0aW9uYWwgdGV4dCBmb3VuZCBhdCBlbmQnXG59KTtcbm1haW4ubG9jYWwgPSBtYWluLnJlZ2lvbmFsT3B0aW9uc1snJ107XG5cbmFzc2lnbihtYWluLmNkYXRlLnByb3RvdHlwZSwge1xuXG4gICAgLyoqIEZvcm1hdCB0aGlzIGRhdGUuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIENEYXRlXG4gICAgICAgIEBwYXJhbSBbZm9ybWF0XSB7c3RyaW5nfSBUaGUgZGF0ZSBmb3JtYXQgdG8gdXNlIChzZWUgPGEgaHJlZj1cIkJhc2VDYWxlbmRhci5odG1sI2Zvcm1hdERhdGVcIj48Y29kZT5mb3JtYXREYXRlPC9jb2RlPjwvYT4pLlxuICAgICAgICBAcGFyYW0gW3NldHRpbmdzXSB7b2JqZWN0fSBPcHRpb25zIGZvciB0aGUgPGNvZGU+Zm9ybWF0RGF0ZTwvY29kZT4gZnVuY3Rpb24uXG4gICAgICAgIEByZXR1cm4ge3N0cmluZ30gVGhlIGZvcm1hdHRlZCBkYXRlLiAqL1xuICAgIGZvcm1hdERhdGU6IGZ1bmN0aW9uKGZvcm1hdCwgc2V0dGluZ3MpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBzZXR0aW5ncyA9IGZvcm1hdDtcbiAgICAgICAgICAgIGZvcm1hdCA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9jYWxlbmRhci5mb3JtYXREYXRlKGZvcm1hdCB8fCAnJywgdGhpcywgc2V0dGluZ3MpO1xuICAgIH1cbn0pO1xuXG5hc3NpZ24obWFpbi5iYXNlQ2FsZW5kYXIucHJvdG90eXBlLCB7XG5cbiAgICBVTklYX0VQT0NIOiBtYWluLmluc3RhbmNlKCkubmV3RGF0ZSgxOTcwLCAxLCAxKS50b0pEKCksXG4gICAgU0VDU19QRVJfREFZOiAyNCAqIDYwICogNjAsXG4gICAgVElDS1NfRVBPQ0g6IG1haW4uaW5zdGFuY2UoKS5qZEVwb2NoLCAvLyAxIEphbnVhcnkgMDAwMSBDRVxuICAgIFRJQ0tTX1BFUl9EQVk6IDI0ICogNjAgKiA2MCAqIDEwMDAwMDAwLFxuXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgQVRPTSAoUkZDIDMzMzkvSVNPIDg2MDEpLlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXIgKi9cbiAgICBBVE9NOiAneXl5eS1tbS1kZCcsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgY29va2llcy5cbiAgICAgICAgRm91bmQgaW4gdGhlIDxjb2RlPmpxdWVyeS5jYWxlbmRhcnMucGx1cy5qczwvY29kZT4gbW9kdWxlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyICovXG4gICAgQ09PS0lFOiAnRCwgZGQgTSB5eXl5JyxcbiAgICAvKiogRGF0ZSBmb3JtIGZvciBmdWxsIGRhdGUuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIEZVTEw6ICdERCwgTU0gZCwgeXl5eScsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgSVNPIDg2MDEuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIElTT184NjAxOiAneXl5eS1tbS1kZCcsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgSnVsaWFuIGRhdGUuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIEpVTElBTjogJ0onLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIFJGQyA4MjIuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIFJGQ184MjI6ICdELCBkIE0geXknLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIFJGQyA4NTAuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIFJGQ184NTA6ICdERCwgZGQtTS15eScsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgUkZDIDEwMzYuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIFJGQ18xMDM2OiAnRCwgZCBNIHl5JyxcbiAgICAvKiogRGF0ZSBmb3JtIGZvciBSRkMgMTEyMy5cbiAgICAgICAgRm91bmQgaW4gdGhlIDxjb2RlPmpxdWVyeS5jYWxlbmRhcnMucGx1cy5qczwvY29kZT4gbW9kdWxlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyICovXG4gICAgUkZDXzExMjM6ICdELCBkIE0geXl5eScsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgUkZDIDI4MjIuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIFJGQ18yODIyOiAnRCwgZCBNIHl5eXknLFxuICAgIC8qKiBEYXRlIGZvcm0gZm9yIFJTUyAoUkZDIDgyMikuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIFJTUzogJ0QsIGQgTSB5eScsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgV2luZG93cyB0aWNrcy5cbiAgICAgICAgRm91bmQgaW4gdGhlIDxjb2RlPmpxdWVyeS5jYWxlbmRhcnMucGx1cy5qczwvY29kZT4gbW9kdWxlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyICovXG4gICAgVElDS1M6ICchJyxcbiAgICAvKiogRGF0ZSBmb3JtIGZvciBVbml4IHRpbWVzdGFtcC5cbiAgICAgICAgRm91bmQgaW4gdGhlIDxjb2RlPmpxdWVyeS5jYWxlbmRhcnMucGx1cy5qczwvY29kZT4gbW9kdWxlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyICovXG4gICAgVElNRVNUQU1QOiAnQCcsXG4gICAgLyoqIERhdGUgZm9ybSBmb3IgVzNjIChJU08gODYwMSkuXG4gICAgICAgIEZvdW5kIGluIHRoZSA8Y29kZT5qcXVlcnkuY2FsZW5kYXJzLnBsdXMuanM8L2NvZGU+IG1vZHVsZS5cbiAgICAgICAgQG1lbWJlcm9mIEJhc2VDYWxlbmRhciAqL1xuICAgIFczQzogJ3l5eXktbW0tZGQnLFxuXG4gICAgLyoqIEZvcm1hdCBhIGRhdGUgb2JqZWN0IGludG8gYSBzdHJpbmcgdmFsdWUuXG4gICAgICAgIFRoZSBmb3JtYXQgY2FuIGJlIGNvbWJpbmF0aW9ucyBvZiB0aGUgZm9sbG93aW5nOlxuICAgICAgICA8dWw+XG4gICAgICAgIDxsaT5kICAtIGRheSBvZiBtb250aCAobm8gbGVhZGluZyB6ZXJvKTwvbGk+XG4gICAgICAgIDxsaT5kZCAtIGRheSBvZiBtb250aCAodHdvIGRpZ2l0KTwvbGk+XG4gICAgICAgIDxsaT5vICAtIGRheSBvZiB5ZWFyIChubyBsZWFkaW5nIHplcm9zKTwvbGk+XG4gICAgICAgIDxsaT5vbyAtIGRheSBvZiB5ZWFyICh0aHJlZSBkaWdpdCk8L2xpPlxuICAgICAgICA8bGk+RCAgLSBkYXkgbmFtZSBzaG9ydDwvbGk+XG4gICAgICAgIDxsaT5ERCAtIGRheSBuYW1lIGxvbmc8L2xpPlxuICAgICAgICA8bGk+dyAgLSB3ZWVrIG9mIHllYXIgKG5vIGxlYWRpbmcgemVybyk8L2xpPlxuICAgICAgICA8bGk+d3cgLSB3ZWVrIG9mIHllYXIgKHR3byBkaWdpdCk8L2xpPlxuICAgICAgICA8bGk+bSAgLSBtb250aCBvZiB5ZWFyIChubyBsZWFkaW5nIHplcm8pPC9saT5cbiAgICAgICAgPGxpPm1tIC0gbW9udGggb2YgeWVhciAodHdvIGRpZ2l0KTwvbGk+XG4gICAgICAgIDxsaT5NICAtIG1vbnRoIG5hbWUgc2hvcnQ8L2xpPlxuICAgICAgICA8bGk+TU0gLSBtb250aCBuYW1lIGxvbmc8L2xpPlxuICAgICAgICA8bGk+eXkgLSB5ZWFyICh0d28gZGlnaXQpPC9saT5cbiAgICAgICAgPGxpPnl5eXkgLSB5ZWFyIChmb3VyIGRpZ2l0KTwvbGk+XG4gICAgICAgIDxsaT5ZWVlZIC0gZm9ybWF0dGVkIHllYXI8L2xpPlxuICAgICAgICA8bGk+SiAgLSBKdWxpYW4gZGF0ZSAoZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDQ3MTMgQkNFIEdyZWVud2ljaCBub29uKTwvbGk+XG4gICAgICAgIDxsaT5AICAtIFVuaXggdGltZXN0YW1wIChzIHNpbmNlIDAxLzAxLzE5NzApPC9saT5cbiAgICAgICAgPGxpPiEgIC0gV2luZG93cyB0aWNrcyAoMTAwbnMgc2luY2UgMDEvMDEvMDAwMSk8L2xpPlxuICAgICAgICA8bGk+Jy4uLicgLSBsaXRlcmFsIHRleHQ8L2xpPlxuICAgICAgICA8bGk+JycgLSBzaW5nbGUgcXVvdGU8L2xpPlxuICAgICAgICA8L3VsPlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIFtmb3JtYXRdIHtzdHJpbmd9IFRoZSBkZXNpcmVkIGZvcm1hdCBvZiB0aGUgZGF0ZSAoZGVmYXVsdHMgdG8gY2FsZW5kYXIgZm9ybWF0KS5cbiAgICAgICAgQHBhcmFtIGRhdGUge0NEYXRlfSBUaGUgZGF0ZSB2YWx1ZSB0byBmb3JtYXQuXG4gICAgICAgIEBwYXJhbSBbc2V0dGluZ3NdIHtvYmplY3R9IEFkZGl0aW9uIG9wdGlvbnMsIHdob3NlIGF0dHJpYnV0ZXMgaW5jbHVkZTpcbiAgICAgICAgQHByb3BlcnR5IFtkYXlOYW1lc1Nob3J0XSB7c3RyaW5nW119IEFiYnJldmlhdGVkIG5hbWVzIG9mIHRoZSBkYXlzIGZyb20gU3VuZGF5LlxuICAgICAgICBAcHJvcGVydHkgW2RheU5hbWVzXSB7c3RyaW5nW119IE5hbWVzIG9mIHRoZSBkYXlzIGZyb20gU3VuZGF5LlxuICAgICAgICBAcHJvcGVydHkgW21vbnRoTmFtZXNTaG9ydF0ge3N0cmluZ1tdfSBBYmJyZXZpYXRlZCBuYW1lcyBvZiB0aGUgbW9udGhzLlxuICAgICAgICBAcHJvcGVydHkgW21vbnRoTmFtZXNdIHtzdHJpbmdbXX0gTmFtZXMgb2YgdGhlIG1vbnRocy5cbiAgICAgICAgQHByb3BlcnR5IFtjYWxjdWxhdGVXZWVrXSB7Q2FsZW5kYXJzUGlja2VyQ2FsY3VsYXRlV2Vla30gRnVuY3Rpb24gdGhhdCBkZXRlcm1pbmVzIHdlZWsgb2YgdGhlIHllYXIuXG4gICAgICAgIEBwcm9wZXJ0eSBbbG9jYWxOdW1iZXJzPWZhbHNlXSB7Ym9vbGVhbn0gPGNvZGU+dHJ1ZTwvY29kZT4gdG8gbG9jYWxpc2UgbnVtYmVycyAoaWYgYXZhaWxhYmxlKSxcbiAgICAgICAgICAgICAgICAgIDxjb2RlPmZhbHNlPC9jb2RlPiB0byB1c2Ugbm9ybWFsIEFyYWJpYyBudW1lcmFscy5cbiAgICAgICAgQHJldHVybiB7c3RyaW5nfSBUaGUgZGF0ZSBpbiB0aGUgYWJvdmUgZm9ybWF0LlxuICAgICAgICBAdGhyb3dzIEVycm9ycyBpZiB0aGUgZGF0ZSBpcyBmcm9tIGEgZGlmZmVyZW50IGNhbGVuZGFyLiAqL1xuICAgIGZvcm1hdERhdGU6IGZ1bmN0aW9uKGZvcm1hdCwgZGF0ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBzZXR0aW5ncyA9IGRhdGU7XG4gICAgICAgICAgICBkYXRlID0gZm9ybWF0O1xuICAgICAgICAgICAgZm9ybWF0ID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFkYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRhdGUuY2FsZW5kYXIoKSAhPT0gdGhpcykge1xuICAgICAgICAgICAgdGhyb3cgbWFpbi5sb2NhbC5pbnZhbGlkRm9ybWF0IHx8IG1haW4ucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkRm9ybWF0O1xuICAgICAgICB9XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdCB8fCB0aGlzLmxvY2FsLmRhdGVGb3JtYXQ7XG4gICAgICAgIHNldHRpbmdzID0gc2V0dGluZ3MgfHwge307XG4gICAgICAgIHZhciBkYXlOYW1lc1Nob3J0ID0gc2V0dGluZ3MuZGF5TmFtZXNTaG9ydCB8fCB0aGlzLmxvY2FsLmRheU5hbWVzU2hvcnQ7XG4gICAgICAgIHZhciBkYXlOYW1lcyA9IHNldHRpbmdzLmRheU5hbWVzIHx8IHRoaXMubG9jYWwuZGF5TmFtZXM7XG4gICAgICAgIHZhciBtb250aE51bWJlcnMgPSBzZXR0aW5ncy5tb250aE51bWJlcnMgfHwgdGhpcy5sb2NhbC5tb250aE51bWJlcnM7XG4gICAgICAgIHZhciBtb250aE5hbWVzU2hvcnQgPSBzZXR0aW5ncy5tb250aE5hbWVzU2hvcnQgfHwgdGhpcy5sb2NhbC5tb250aE5hbWVzU2hvcnQ7XG4gICAgICAgIHZhciBtb250aE5hbWVzID0gc2V0dGluZ3MubW9udGhOYW1lcyB8fCB0aGlzLmxvY2FsLm1vbnRoTmFtZXM7XG4gICAgICAgIHZhciBjYWxjdWxhdGVXZWVrID0gc2V0dGluZ3MuY2FsY3VsYXRlV2VlayB8fCB0aGlzLmxvY2FsLmNhbGN1bGF0ZVdlZWs7XG4gICAgICAgIC8vIENoZWNrIHdoZXRoZXIgYSBmb3JtYXQgY2hhcmFjdGVyIGlzIGRvdWJsZWRcbiAgICAgICAgdmFyIGRvdWJsZWQgPSBmdW5jdGlvbihtYXRjaCwgc3RlcCkge1xuICAgICAgICAgICAgdmFyIG1hdGNoZXMgPSAxO1xuICAgICAgICAgICAgd2hpbGUgKGlGb3JtYXQgKyBtYXRjaGVzIDwgZm9ybWF0Lmxlbmd0aCAmJiBmb3JtYXQuY2hhckF0KGlGb3JtYXQgKyBtYXRjaGVzKSA9PT0gbWF0Y2gpIHtcbiAgICAgICAgICAgICAgICBtYXRjaGVzKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpRm9ybWF0ICs9IG1hdGNoZXMgLSAxO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IobWF0Y2hlcyAvIChzdGVwIHx8IDEpKSA+IDE7XG4gICAgICAgIH07XG4gICAgICAgIC8vIEZvcm1hdCBhIG51bWJlciwgd2l0aCBsZWFkaW5nIHplcm9lcyBpZiBuZWNlc3NhcnlcbiAgICAgICAgdmFyIGZvcm1hdE51bWJlciA9IGZ1bmN0aW9uKG1hdGNoLCB2YWx1ZSwgbGVuLCBzdGVwKSB7XG4gICAgICAgICAgICB2YXIgbnVtID0gJycgKyB2YWx1ZTtcbiAgICAgICAgICAgIGlmIChkb3VibGVkKG1hdGNoLCBzdGVwKSkge1xuICAgICAgICAgICAgICAgIHdoaWxlIChudW0ubGVuZ3RoIDwgbGVuKSB7XG4gICAgICAgICAgICAgICAgICAgIG51bSA9ICcwJyArIG51bTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVtO1xuICAgICAgICB9O1xuICAgICAgICAvLyBGb3JtYXQgYSBuYW1lLCBzaG9ydCBvciBsb25nIGFzIHJlcXVlc3RlZFxuICAgICAgICB2YXIgZm9ybWF0TmFtZSA9IGZ1bmN0aW9uKG1hdGNoLCB2YWx1ZSwgc2hvcnROYW1lcywgbG9uZ05hbWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gKGRvdWJsZWQobWF0Y2gpID8gbG9uZ05hbWVzW3ZhbHVlXSA6IHNob3J0TmFtZXNbdmFsdWVdKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gRm9ybWF0IG1vbnRoIG51bWJlclxuICAgICAgICAvLyAoZS5nLiBDaGluZXNlIGNhbGVuZGFyIG5lZWRzIHRvIGFjY291bnQgZm9yIGludGVyY2FsYXJ5IG1vbnRocylcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gdGhpcztcbiAgICAgICAgdmFyIGZvcm1hdE1vbnRoID0gZnVuY3Rpb24oZGF0ZSkge1xuICAgICAgICAgICAgcmV0dXJuICh0eXBlb2YgbW9udGhOdW1iZXJzID09PSAnZnVuY3Rpb24nKSA/XG4gICAgICAgICAgICAgICAgbW9udGhOdW1iZXJzLmNhbGwoY2FsZW5kYXIsIGRhdGUsIGRvdWJsZWQoJ20nKSkgOlxuICAgICAgICAgICAgICAgIGxvY2FsaXNlTnVtYmVycyhmb3JtYXROdW1iZXIoJ20nLCBkYXRlLm1vbnRoKCksIDIpKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gRm9ybWF0IGEgbW9udGggbmFtZSwgc2hvcnQgb3IgbG9uZyBhcyByZXF1ZXN0ZWRcbiAgICAgICAgdmFyIGZvcm1hdE1vbnRoTmFtZSA9IGZ1bmN0aW9uKGRhdGUsIHVzZUxvbmdOYW1lKSB7XG4gICAgICAgICAgICBpZiAodXNlTG9uZ05hbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHR5cGVvZiBtb250aE5hbWVzID09PSAnZnVuY3Rpb24nKSA/XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZXMuY2FsbChjYWxlbmRhciwgZGF0ZSkgOlxuICAgICAgICAgICAgICAgICAgICBtb250aE5hbWVzW2RhdGUubW9udGgoKSAtIGNhbGVuZGFyLm1pbk1vbnRoXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICh0eXBlb2YgbW9udGhOYW1lc1Nob3J0ID09PSAnZnVuY3Rpb24nKSA/XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydC5jYWxsKGNhbGVuZGFyLCBkYXRlKSA6XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZXNTaG9ydFtkYXRlLm1vbnRoKCkgLSBjYWxlbmRhci5taW5Nb250aF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8vIExvY2FsaXNlIG51bWJlcnMgaWYgcmVxdWVzdGVkIGFuZCBhdmFpbGFibGVcbiAgICAgICAgdmFyIGRpZ2l0cyA9IHRoaXMubG9jYWwuZGlnaXRzO1xuICAgICAgICB2YXIgbG9jYWxpc2VOdW1iZXJzID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiAoc2V0dGluZ3MubG9jYWxOdW1iZXJzICYmIGRpZ2l0cyA/IGRpZ2l0cyh2YWx1ZSkgOiB2YWx1ZSk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBvdXRwdXQgPSAnJztcbiAgICAgICAgdmFyIGxpdGVyYWwgPSBmYWxzZTtcbiAgICAgICAgZm9yICh2YXIgaUZvcm1hdCA9IDA7IGlGb3JtYXQgPCBmb3JtYXQubGVuZ3RoOyBpRm9ybWF0KyspIHtcbiAgICAgICAgICAgIGlmIChsaXRlcmFsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZvcm1hdC5jaGFyQXQoaUZvcm1hdCkgPT09IFwiJ1wiICYmICFkb3VibGVkKFwiJ1wiKSkge1xuICAgICAgICAgICAgICAgICAgICBsaXRlcmFsID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gZm9ybWF0LmNoYXJBdChpRm9ybWF0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGZvcm1hdC5jaGFyQXQoaUZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZCc6IG91dHB1dCArPSBsb2NhbGlzZU51bWJlcnMoZm9ybWF0TnVtYmVyKCdkJywgZGF0ZS5kYXkoKSwgMikpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnRCc6IG91dHB1dCArPSBmb3JtYXROYW1lKCdEJywgZGF0ZS5kYXlPZldlZWsoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRheU5hbWVzU2hvcnQsIGRheU5hbWVzKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ28nOiBvdXRwdXQgKz0gZm9ybWF0TnVtYmVyKCdvJywgZGF0ZS5kYXlPZlllYXIoKSwgMyk7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICd3Jzogb3V0cHV0ICs9IGZvcm1hdE51bWJlcigndycsIGRhdGUud2Vla09mWWVhcigpLCAyKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ20nOiBvdXRwdXQgKz0gZm9ybWF0TW9udGgoZGF0ZSk7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdNJzogb3V0cHV0ICs9IGZvcm1hdE1vbnRoTmFtZShkYXRlLCBkb3VibGVkKCdNJykpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAneSc6XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gKGRvdWJsZWQoJ3knLCAyKSA/IGRhdGUueWVhcigpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGF0ZS55ZWFyKCkgJSAxMDAgPCAxMCA/ICcwJyA6ICcnKSArIGRhdGUueWVhcigpICUgMTAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdZJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvdWJsZWQoJ1knLCAyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dCArPSBkYXRlLmZvcm1hdFllYXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdKJzogb3V0cHV0ICs9IGRhdGUudG9KRCgpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnQCc6IG91dHB1dCArPSAoZGF0ZS50b0pEKCkgLSB0aGlzLlVOSVhfRVBPQ0gpICogdGhpcy5TRUNTX1BFUl9EQVk7IGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICchJzogb3V0cHV0ICs9IChkYXRlLnRvSkQoKSAtIHRoaXMuVElDS1NfRVBPQ0gpICogdGhpcy5USUNLU19QRVJfREFZOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcIidcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb3VibGVkKFwiJ1wiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dCArPSBcIidcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpdGVyYWwgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQgKz0gZm9ybWF0LmNoYXJBdChpRm9ybWF0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICB9LFxuXG4gICAgLyoqIFBhcnNlIGEgc3RyaW5nIHZhbHVlIGludG8gYSBkYXRlIG9iamVjdC5cbiAgICAgICAgU2VlIDxhIGhyZWY9XCIjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPiBmb3IgdGhlIHBvc3NpYmxlIGZvcm1hdHMsIHBsdXM6XG4gICAgICAgIDx1bD5cbiAgICAgICAgPGxpPiogLSBpZ25vcmUgcmVzdCBvZiBzdHJpbmc8L2xpPlxuICAgICAgICA8L3VsPlxuICAgICAgICBGb3VuZCBpbiB0aGUgPGNvZGU+anF1ZXJ5LmNhbGVuZGFycy5wbHVzLmpzPC9jb2RlPiBtb2R1bGUuXG4gICAgICAgIEBtZW1iZXJvZiBCYXNlQ2FsZW5kYXJcbiAgICAgICAgQHBhcmFtIGZvcm1hdCB7c3RyaW5nfSBUaGUgZXhwZWN0ZWQgZm9ybWF0IG9mIHRoZSBkYXRlICgnJyBmb3IgZGVmYXVsdCBjYWxlbmRhciBmb3JtYXQpLlxuICAgICAgICBAcGFyYW0gdmFsdWUge3N0cmluZ30gVGhlIGRhdGUgaW4gdGhlIGFib3ZlIGZvcm1hdC5cbiAgICAgICAgQHBhcmFtIFtzZXR0aW5nc10ge29iamVjdH0gQWRkaXRpb25hbCBvcHRpb25zIHdob3NlIGF0dHJpYnV0ZXMgaW5jbHVkZTpcbiAgICAgICAgQHByb3BlcnR5IFtzaG9ydFllYXJDdXRvZmZdIHtudW1iZXJ9IFRoZSBjdXRvZmYgeWVhciBmb3IgZGV0ZXJtaW5pbmcgdGhlIGNlbnR1cnkuXG4gICAgICAgIEBwcm9wZXJ0eSBbZGF5TmFtZXNTaG9ydF0ge3N0cmluZ1tdfSBBYmJyZXZpYXRlZCBuYW1lcyBvZiB0aGUgZGF5cyBmcm9tIFN1bmRheS5cbiAgICAgICAgQHByb3BlcnR5IFtkYXlOYW1lc10ge3N0cmluZ1tdfSBOYW1lcyBvZiB0aGUgZGF5cyBmcm9tIFN1bmRheS5cbiAgICAgICAgQHByb3BlcnR5IFttb250aE5hbWVzU2hvcnRdIHtzdHJpbmdbXX0gQWJicmV2aWF0ZWQgbmFtZXMgb2YgdGhlIG1vbnRocy5cbiAgICAgICAgQHByb3BlcnR5IFttb250aE5hbWVzXSB7c3RyaW5nW119IE5hbWVzIG9mIHRoZSBtb250aHMuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZXh0cmFjdGVkIGRhdGUgdmFsdWUgb3IgPGNvZGU+bnVsbDwvY29kZT4gaWYgdmFsdWUgaXMgYmxhbmsuXG4gICAgICAgIEB0aHJvd3MgRXJyb3JzIGlmIHRoZSBmb3JtYXQgYW5kL29yIHZhbHVlIGFyZSBtaXNzaW5nLFxuICAgICAgICAgICAgICAgIGlmIHRoZSB2YWx1ZSBkb2Vzbid0IG1hdGNoIHRoZSBmb3JtYXQsIG9yIGlmIHRoZSBkYXRlIGlzIGludmFsaWQuICovXG4gICAgcGFyc2VEYXRlOiBmdW5jdGlvbihmb3JtYXQsIHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbWFpbi5sb2NhbC5pbnZhbGlkQXJndW1lbnRzIHx8IG1haW4ucmVnaW9uYWxPcHRpb25zWycnXS5pbnZhbGlkQXJndW1lbnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhbHVlID0gKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgPyB2YWx1ZS50b1N0cmluZygpIDogdmFsdWUgKyAnJyk7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGZvcm1hdCA9IGZvcm1hdCB8fCB0aGlzLmxvY2FsLmRhdGVGb3JtYXQ7XG4gICAgICAgIHNldHRpbmdzID0gc2V0dGluZ3MgfHwge307XG4gICAgICAgIHZhciBzaG9ydFllYXJDdXRvZmYgPSBzZXR0aW5ncy5zaG9ydFllYXJDdXRvZmYgfHwgdGhpcy5zaG9ydFllYXJDdXRvZmY7XG4gICAgICAgIHNob3J0WWVhckN1dG9mZiA9ICh0eXBlb2Ygc2hvcnRZZWFyQ3V0b2ZmICE9PSAnc3RyaW5nJyA/IHNob3J0WWVhckN1dG9mZiA6XG4gICAgICAgICAgICB0aGlzLnRvZGF5KCkueWVhcigpICUgMTAwICsgcGFyc2VJbnQoc2hvcnRZZWFyQ3V0b2ZmLCAxMCkpO1xuICAgICAgICB2YXIgZGF5TmFtZXNTaG9ydCA9IHNldHRpbmdzLmRheU5hbWVzU2hvcnQgfHwgdGhpcy5sb2NhbC5kYXlOYW1lc1Nob3J0O1xuICAgICAgICB2YXIgZGF5TmFtZXMgPSBzZXR0aW5ncy5kYXlOYW1lcyB8fCB0aGlzLmxvY2FsLmRheU5hbWVzO1xuICAgICAgICB2YXIgcGFyc2VNb250aCA9IHNldHRpbmdzLnBhcnNlTW9udGggfHwgdGhpcy5sb2NhbC5wYXJzZU1vbnRoO1xuICAgICAgICB2YXIgbW9udGhOdW1iZXJzID0gc2V0dGluZ3MubW9udGhOdW1iZXJzIHx8IHRoaXMubG9jYWwubW9udGhOdW1iZXJzO1xuICAgICAgICB2YXIgbW9udGhOYW1lc1Nob3J0ID0gc2V0dGluZ3MubW9udGhOYW1lc1Nob3J0IHx8IHRoaXMubG9jYWwubW9udGhOYW1lc1Nob3J0O1xuICAgICAgICB2YXIgbW9udGhOYW1lcyA9IHNldHRpbmdzLm1vbnRoTmFtZXMgfHwgdGhpcy5sb2NhbC5tb250aE5hbWVzO1xuICAgICAgICB2YXIgamQgPSAtMTtcbiAgICAgICAgdmFyIHllYXIgPSAtMTtcbiAgICAgICAgdmFyIG1vbnRoID0gLTE7XG4gICAgICAgIHZhciBkYXkgPSAtMTtcbiAgICAgICAgdmFyIGRveSA9IC0xO1xuICAgICAgICB2YXIgc2hvcnRZZWFyID0gZmFsc2U7XG4gICAgICAgIHZhciBsaXRlcmFsID0gZmFsc2U7XG4gICAgICAgIC8vIENoZWNrIHdoZXRoZXIgYSBmb3JtYXQgY2hhcmFjdGVyIGlzIGRvdWJsZWRcbiAgICAgICAgdmFyIGRvdWJsZWQgPSBmdW5jdGlvbihtYXRjaCwgc3RlcCkge1xuICAgICAgICAgICAgdmFyIG1hdGNoZXMgPSAxO1xuICAgICAgICAgICAgd2hpbGUgKGlGb3JtYXQgKyBtYXRjaGVzIDwgZm9ybWF0Lmxlbmd0aCAmJiBmb3JtYXQuY2hhckF0KGlGb3JtYXQgKyBtYXRjaGVzKSA9PT0gbWF0Y2gpIHtcbiAgICAgICAgICAgICAgICBtYXRjaGVzKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpRm9ybWF0ICs9IG1hdGNoZXMgLSAxO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IobWF0Y2hlcyAvIChzdGVwIHx8IDEpKSA+IDE7XG4gICAgICAgIH07XG4gICAgICAgIC8vIEV4dHJhY3QgYSBudW1iZXIgZnJvbSB0aGUgc3RyaW5nIHZhbHVlXG4gICAgICAgIHZhciBnZXROdW1iZXIgPSBmdW5jdGlvbihtYXRjaCwgc3RlcCkge1xuICAgICAgICAgICAgdmFyIGlzRG91YmxlZCA9IGRvdWJsZWQobWF0Y2gsIHN0ZXApO1xuICAgICAgICAgICAgdmFyIHNpemUgPSBbMiwgMywgaXNEb3VibGVkID8gNCA6IDIsIGlzRG91YmxlZCA/IDQgOiAyLCAxMCwgMTEsIDIwXVsnb3lZSkAhJy5pbmRleE9mKG1hdGNoKSArIDFdO1xuICAgICAgICAgICAgdmFyIGRpZ2l0cyA9IG5ldyBSZWdFeHAoJ14tP1xcXFxkezEsJyArIHNpemUgKyAnfScpO1xuICAgICAgICAgICAgdmFyIG51bSA9IHZhbHVlLnN1YnN0cmluZyhpVmFsdWUpLm1hdGNoKGRpZ2l0cyk7XG4gICAgICAgICAgICBpZiAoIW51bSkge1xuICAgICAgICAgICAgICAgIHRocm93IChtYWluLmxvY2FsLm1pc3NpbmdOdW1iZXJBdCB8fCBtYWluLnJlZ2lvbmFsT3B0aW9uc1snJ10ubWlzc2luZ051bWJlckF0KS5cbiAgICAgICAgICAgICAgICAgICAgcmVwbGFjZSgvXFx7MFxcfS8sIGlWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpVmFsdWUgKz0gbnVtWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUludChudW1bMF0sIDEwKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gRXh0cmFjdCBhIG1vbnRoIG51bWJlciBmcm9tIHRoZSBzdHJpbmcgdmFsdWVcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gdGhpcztcbiAgICAgICAgdmFyIGdldE1vbnRoTnVtYmVyID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1vbnRoTnVtYmVycyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGRvdWJsZWQoJ20nKTsgIC8vIHVwZGF0ZSBpRm9ybWF0XG4gICAgICAgICAgICAgICAgdmFyIG1vbnRoID0gbW9udGhOdW1iZXJzLmNhbGwoY2FsZW5kYXIsIHZhbHVlLnN1YnN0cmluZyhpVmFsdWUpKTtcbiAgICAgICAgICAgICAgICBpVmFsdWUgKz0gbW9udGgubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGdldE51bWJlcignbScpO1xuICAgICAgICB9O1xuICAgICAgICAvLyBFeHRyYWN0IGEgbmFtZSBmcm9tIHRoZSBzdHJpbmcgdmFsdWUgYW5kIGNvbnZlcnQgdG8gYW4gaW5kZXhcbiAgICAgICAgdmFyIGdldE5hbWUgPSBmdW5jdGlvbihtYXRjaCwgc2hvcnROYW1lcywgbG9uZ05hbWVzLCBzdGVwKSB7XG4gICAgICAgICAgICB2YXIgbmFtZXMgPSAoZG91YmxlZChtYXRjaCwgc3RlcCkgPyBsb25nTmFtZXMgOiBzaG9ydE5hbWVzKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWUuc3Vic3RyKGlWYWx1ZSwgbmFtZXNbaV0ubGVuZ3RoKS50b0xvd2VyQ2FzZSgpID09PSBuYW1lc1tpXS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlWYWx1ZSArPSBuYW1lc1tpXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpICsgY2FsZW5kYXIubWluTW9udGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgKG1haW4ubG9jYWwudW5rbm93bk5hbWVBdCB8fCBtYWluLnJlZ2lvbmFsT3B0aW9uc1snJ10udW5rbm93bk5hbWVBdCkuXG4gICAgICAgICAgICAgICAgcmVwbGFjZSgvXFx7MFxcfS8sIGlWYWx1ZSk7XG4gICAgICAgIH07XG4gICAgICAgIC8vIEV4dHJhY3QgYSBtb250aCBudW1iZXIgZnJvbSB0aGUgc3RyaW5nIHZhbHVlXG4gICAgICAgIHZhciBnZXRNb250aE5hbWUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbW9udGhOYW1lcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHZhciBtb250aCA9IGRvdWJsZWQoJ00nKSA/XG4gICAgICAgICAgICAgICAgICAgIG1vbnRoTmFtZXMuY2FsbChjYWxlbmRhciwgdmFsdWUuc3Vic3RyaW5nKGlWYWx1ZSkpIDpcbiAgICAgICAgICAgICAgICAgICAgbW9udGhOYW1lc1Nob3J0LmNhbGwoY2FsZW5kYXIsIHZhbHVlLnN1YnN0cmluZyhpVmFsdWUpKTtcbiAgICAgICAgICAgICAgICBpVmFsdWUgKz0gbW9udGgubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHJldHVybiBtb250aDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGdldE5hbWUoJ00nLCBtb250aE5hbWVzU2hvcnQsIG1vbnRoTmFtZXMpO1xuICAgICAgICB9O1xuICAgICAgICAvLyBDb25maXJtIHRoYXQgYSBsaXRlcmFsIGNoYXJhY3RlciBtYXRjaGVzIHRoZSBzdHJpbmcgdmFsdWVcbiAgICAgICAgdmFyIGNoZWNrTGl0ZXJhbCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKHZhbHVlLmNoYXJBdChpVmFsdWUpICE9PSBmb3JtYXQuY2hhckF0KGlGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgKG1haW4ubG9jYWwudW5leHBlY3RlZExpdGVyYWxBdCB8fFxuICAgICAgICAgICAgICAgICAgICBtYWluLnJlZ2lvbmFsT3B0aW9uc1snJ10udW5leHBlY3RlZExpdGVyYWxBdCkucmVwbGFjZSgvXFx7MFxcfS8sIGlWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpVmFsdWUrKztcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGlWYWx1ZSA9IDA7XG4gICAgICAgIGZvciAodmFyIGlGb3JtYXQgPSAwOyBpRm9ybWF0IDwgZm9ybWF0Lmxlbmd0aDsgaUZvcm1hdCsrKSB7XG4gICAgICAgICAgICBpZiAobGl0ZXJhbCkge1xuICAgICAgICAgICAgICAgIGlmIChmb3JtYXQuY2hhckF0KGlGb3JtYXQpID09PSBcIidcIiAmJiAhZG91YmxlZChcIidcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbGl0ZXJhbCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tMaXRlcmFsKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChmb3JtYXQuY2hhckF0KGlGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2QnOiBkYXkgPSBnZXROdW1iZXIoJ2QnKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ0QnOiBnZXROYW1lKCdEJywgZGF5TmFtZXNTaG9ydCwgZGF5TmFtZXMpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbyc6IGRveSA9IGdldE51bWJlcignbycpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAndyc6IGdldE51bWJlcigndycpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbSc6IG1vbnRoID0gZ2V0TW9udGhOdW1iZXIoKTsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ00nOiBtb250aCA9IGdldE1vbnRoTmFtZSgpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAneSc6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaVNhdmUgPSBpRm9ybWF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgc2hvcnRZZWFyID0gIWRvdWJsZWQoJ3knLCAyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlGb3JtYXQgPSBpU2F2ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHllYXIgPSBnZXROdW1iZXIoJ3knLCAyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdZJzogeWVhciA9IGdldE51bWJlcignWScsIDIpOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnSic6XG4gICAgICAgICAgICAgICAgICAgICAgICBqZCA9IGdldE51bWJlcignSicpICsgMC41O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlLmNoYXJBdChpVmFsdWUpID09PSAnLicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpVmFsdWUrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXROdW1iZXIoJ0onKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdAJzogamQgPSBnZXROdW1iZXIoJ0AnKSAvIHRoaXMuU0VDU19QRVJfREFZICsgdGhpcy5VTklYX0VQT0NIOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnISc6IGpkID0gZ2V0TnVtYmVyKCchJykgLyB0aGlzLlRJQ0tTX1BFUl9EQVkgKyB0aGlzLlRJQ0tTX0VQT0NIOyBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnKic6IGlWYWx1ZSA9IHZhbHVlLmxlbmd0aDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCInXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG91YmxlZChcIidcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpdGVyYWwgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6IGNoZWNrTGl0ZXJhbCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaVZhbHVlIDwgdmFsdWUubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aHJvdyBtYWluLmxvY2FsLnVuZXhwZWN0ZWRUZXh0IHx8IG1haW4ucmVnaW9uYWxPcHRpb25zWycnXS51bmV4cGVjdGVkVGV4dDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoeWVhciA9PT0gLTEpIHtcbiAgICAgICAgICAgIHllYXIgPSB0aGlzLnRvZGF5KCkueWVhcigpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHllYXIgPCAxMDAgJiYgc2hvcnRZZWFyKSB7XG4gICAgICAgICAgICB5ZWFyICs9IChzaG9ydFllYXJDdXRvZmYgPT09IC0xID8gMTkwMCA6IHRoaXMudG9kYXkoKS55ZWFyKCkgLVxuICAgICAgICAgICAgICAgIHRoaXMudG9kYXkoKS55ZWFyKCkgJSAxMDAgLSAoeWVhciA8PSBzaG9ydFllYXJDdXRvZmYgPyAwIDogMTAwKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBtb250aCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIG1vbnRoID0gcGFyc2VNb250aC5jYWxsKHRoaXMsIHllYXIsIG1vbnRoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZG95ID4gLTEpIHtcbiAgICAgICAgICAgIG1vbnRoID0gMTtcbiAgICAgICAgICAgIGRheSA9IGRveTtcbiAgICAgICAgICAgIGZvciAodmFyIGRpbSA9IHRoaXMuZGF5c0luTW9udGgoeWVhciwgbW9udGgpOyBkYXkgPiBkaW07IGRpbSA9IHRoaXMuZGF5c0luTW9udGgoeWVhciwgbW9udGgpKSB7XG4gICAgICAgICAgICAgICAgbW9udGgrKztcbiAgICAgICAgICAgICAgICBkYXkgLT0gZGltO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoamQgPiAtMSA/IHRoaXMuZnJvbUpEKGpkKSA6IHRoaXMubmV3RGF0ZSh5ZWFyLCBtb250aCwgZGF5KSk7XG4gICAgfSxcblxuICAgIC8qKiBBIGRhdGUgbWF5IGJlIHNwZWNpZmllZCBhcyBhbiBleGFjdCB2YWx1ZSBvciBhIHJlbGF0aXZlIG9uZS5cbiAgICAgICAgRm91bmQgaW4gdGhlIDxjb2RlPmpxdWVyeS5jYWxlbmRhcnMucGx1cy5qczwvY29kZT4gbW9kdWxlLlxuICAgICAgICBAbWVtYmVyb2YgQmFzZUNhbGVuZGFyXG4gICAgICAgIEBwYXJhbSBkYXRlU3BlYyB7Q0RhdGV8bnVtYmVyfHN0cmluZ30gVGhlIGRhdGUgYXMgYW4gb2JqZWN0IG9yIHN0cmluZyBpbiB0aGUgZ2l2ZW4gZm9ybWF0IG9yXG4gICAgICAgICAgICAgICAgYW4gb2Zmc2V0IC0gbnVtZXJpYyBkYXlzIGZyb20gdG9kYXksIG9yIHN0cmluZyBhbW91bnRzIGFuZCBwZXJpb2RzLCBlLmcuICcrMW0gKzJ3Jy5cbiAgICAgICAgQHBhcmFtIGRlZmF1bHREYXRlIHtDRGF0ZX0gVGhlIGRhdGUgdG8gdXNlIGlmIG5vIG90aGVyIHN1cHBsaWVkLCBtYXkgYmUgPGNvZGU+bnVsbDwvY29kZT4uXG4gICAgICAgIEBwYXJhbSBjdXJyZW50RGF0ZSB7Q0RhdGV9IFRoZSBjdXJyZW50IGRhdGUgYXMgYSBwb3NzaWJsZSBiYXNpcyBmb3IgcmVsYXRpdmUgZGF0ZXMsXG4gICAgICAgICAgICAgICAgaWYgPGNvZGU+bnVsbDwvY29kZT4gdG9kYXkgaXMgdXNlZCAob3B0aW9uYWwpXG4gICAgICAgIEBwYXJhbSBbZGF0ZUZvcm1hdF0ge3N0cmluZ30gVGhlIGV4cGVjdGVkIGRhdGUgZm9ybWF0IC0gc2VlIDxhIGhyZWY9XCIjZm9ybWF0RGF0ZVwiPjxjb2RlPmZvcm1hdERhdGU8L2NvZGU+PC9hPi5cbiAgICAgICAgQHBhcmFtIFtzZXR0aW5nc10ge29iamVjdH0gQWRkaXRpb25hbCBvcHRpb25zIHdob3NlIGF0dHJpYnV0ZXMgaW5jbHVkZTpcbiAgICAgICAgQHByb3BlcnR5IFtzaG9ydFllYXJDdXRvZmZdIHtudW1iZXJ9IFRoZSBjdXRvZmYgeWVhciBmb3IgZGV0ZXJtaW5pbmcgdGhlIGNlbnR1cnkuXG4gICAgICAgIEBwcm9wZXJ0eSBbZGF5TmFtZXNTaG9ydF0ge3N0cmluZ1tdfSBBYmJyZXZpYXRlZCBuYW1lcyBvZiB0aGUgZGF5cyBmcm9tIFN1bmRheS5cbiAgICAgICAgQHByb3BlcnR5IFtkYXlOYW1lc10ge3N0cmluZ1tdfSBOYW1lcyBvZiB0aGUgZGF5cyBmcm9tIFN1bmRheS5cbiAgICAgICAgQHByb3BlcnR5IFttb250aE5hbWVzU2hvcnRdIHtzdHJpbmdbXX0gQWJicmV2aWF0ZWQgbmFtZXMgb2YgdGhlIG1vbnRocy5cbiAgICAgICAgQHByb3BlcnR5IFttb250aE5hbWVzXSB7c3RyaW5nW119IE5hbWVzIG9mIHRoZSBtb250aHMuXG4gICAgICAgIEByZXR1cm4ge0NEYXRlfSBUaGUgZGVjb2RlZCBkYXRlLiAqL1xuICAgIGRldGVybWluZURhdGU6IGZ1bmN0aW9uKGRhdGVTcGVjLCBkZWZhdWx0RGF0ZSwgY3VycmVudERhdGUsIGRhdGVGb3JtYXQsIHNldHRpbmdzKSB7XG4gICAgICAgIGlmIChjdXJyZW50RGF0ZSAmJiB0eXBlb2YgY3VycmVudERhdGUgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBzZXR0aW5ncyA9IGRhdGVGb3JtYXQ7XG4gICAgICAgICAgICBkYXRlRm9ybWF0ID0gY3VycmVudERhdGU7XG4gICAgICAgICAgICBjdXJyZW50RGF0ZSA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiBkYXRlRm9ybWF0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgc2V0dGluZ3MgPSBkYXRlRm9ybWF0O1xuICAgICAgICAgICAgZGF0ZUZvcm1hdCA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRoaXM7XG4gICAgICAgIHZhciBvZmZzZXRTdHJpbmcgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbGVuZGFyLnBhcnNlRGF0ZShkYXRlRm9ybWF0LCBvZmZzZXQsIHNldHRpbmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgLy8gSWdub3JlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvZmZzZXQgPSBvZmZzZXQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIHZhciBkYXRlID0gKG9mZnNldC5tYXRjaCgvXmMvKSAmJiBjdXJyZW50RGF0ZSA/XG4gICAgICAgICAgICAgICAgY3VycmVudERhdGUubmV3RGF0ZSgpIDogbnVsbCkgfHwgY2FsZW5kYXIudG9kYXkoKTtcbiAgICAgICAgICAgIHZhciBwYXR0ZXJuID0gLyhbKy1dP1swLTldKylcXHMqKGR8d3xtfHkpPy9nO1xuICAgICAgICAgICAgdmFyIG1hdGNoZXMgPSBwYXR0ZXJuLmV4ZWMob2Zmc2V0KTtcbiAgICAgICAgICAgIHdoaWxlIChtYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgZGF0ZS5hZGQocGFyc2VJbnQobWF0Y2hlc1sxXSwgMTApLCBtYXRjaGVzWzJdIHx8ICdkJyk7XG4gICAgICAgICAgICAgICAgbWF0Y2hlcyA9IHBhdHRlcm4uZXhlYyhvZmZzZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgICAgIH07XG4gICAgICAgIGRlZmF1bHREYXRlID0gKGRlZmF1bHREYXRlID8gZGVmYXVsdERhdGUubmV3RGF0ZSgpIDogbnVsbCk7XG4gICAgICAgIGRhdGVTcGVjID0gKGRhdGVTcGVjID09IG51bGwgPyBkZWZhdWx0RGF0ZSA6XG4gICAgICAgICAgICAodHlwZW9mIGRhdGVTcGVjID09PSAnc3RyaW5nJyA/IG9mZnNldFN0cmluZyhkYXRlU3BlYykgOiAodHlwZW9mIGRhdGVTcGVjID09PSAnbnVtYmVyJyA/XG4gICAgICAgICAgICAoaXNOYU4oZGF0ZVNwZWMpIHx8IGRhdGVTcGVjID09PSBJbmZpbml0eSB8fCBkYXRlU3BlYyA9PT0gLUluZmluaXR5ID8gZGVmYXVsdERhdGUgOlxuICAgICAgICAgICAgY2FsZW5kYXIudG9kYXkoKS5hZGQoZGF0ZVNwZWMsICdkJykpIDogY2FsZW5kYXIubmV3RGF0ZShkYXRlU3BlYykpKSk7XG4gICAgICAgIHJldHVybiBkYXRlU3BlYztcbiAgICB9XG59KTtcblxuXG59LHtcIi4vbWFpblwiOjU3MSxcIm9iamVjdC1hc3NpZ25cIjo0NTR9XSw1NzM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xubW9kdWxlLmV4cG9ydHMgPSBfZGVyZXFfKCdjd2lzZS1jb21waWxlcicpKHtcbiAgICBhcmdzOiBbJ2FycmF5Jywge1xuICAgICAgICBvZmZzZXQ6IFsxXSxcbiAgICAgICAgYXJyYXk6IDBcbiAgICB9LCAnc2NhbGFyJywgJ3NjYWxhcicsICdpbmRleCddLFxuICAgIHByZToge1xuICAgICAgICBcImJvZHlcIjogXCJ7fVwiLFxuICAgICAgICBcImFyZ3NcIjogW10sXG4gICAgICAgIFwidGhpc1ZhcnNcIjogW10sXG4gICAgICAgIFwibG9jYWxWYXJzXCI6IFtdXG4gICAgfSxcbiAgICBwb3N0OiB7XG4gICAgICAgIFwiYm9keVwiOiBcInt9XCIsXG4gICAgICAgIFwiYXJnc1wiOiBbXSxcbiAgICAgICAgXCJ0aGlzVmFyc1wiOiBbXSxcbiAgICAgICAgXCJsb2NhbFZhcnNcIjogW11cbiAgICB9LFxuICAgIGJvZHk6IHtcbiAgICAgICAgXCJib2R5XCI6IFwie1xcbiAgICAgICAgdmFyIF9pbmxpbmVfMV9kYSA9IF9pbmxpbmVfMV9hcmcwXyAtIF9pbmxpbmVfMV9hcmczX1xcbiAgICAgICAgdmFyIF9pbmxpbmVfMV9kYiA9IF9pbmxpbmVfMV9hcmcxXyAtIF9pbmxpbmVfMV9hcmczX1xcbiAgICAgICAgaWYoKF9pbmxpbmVfMV9kYSA+PSAwKSAhPT0gKF9pbmxpbmVfMV9kYiA+PSAwKSkge1xcbiAgICAgICAgICBfaW5saW5lXzFfYXJnMl8ucHVzaChfaW5saW5lXzFfYXJnNF9bMF0gKyAwLjUgKyAwLjUgKiAoX2lubGluZV8xX2RhICsgX2lubGluZV8xX2RiKSAvIChfaW5saW5lXzFfZGEgLSBfaW5saW5lXzFfZGIpKVxcbiAgICAgICAgfVxcbiAgICAgIH1cIixcbiAgICAgICAgXCJhcmdzXCI6IFt7XG4gICAgICAgICAgICBcIm5hbWVcIjogXCJfaW5saW5lXzFfYXJnMF9cIixcbiAgICAgICAgICAgIFwibHZhbHVlXCI6IGZhbHNlLFxuICAgICAgICAgICAgXCJydmFsdWVcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiY291bnRcIjogMVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBcIm5hbWVcIjogXCJfaW5saW5lXzFfYXJnMV9cIixcbiAgICAgICAgICAgIFwibHZhbHVlXCI6IGZhbHNlLFxuICAgICAgICAgICAgXCJydmFsdWVcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiY291bnRcIjogMVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBcIm5hbWVcIjogXCJfaW5saW5lXzFfYXJnMl9cIixcbiAgICAgICAgICAgIFwibHZhbHVlXCI6IGZhbHNlLFxuICAgICAgICAgICAgXCJydmFsdWVcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiY291bnRcIjogMVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBcIm5hbWVcIjogXCJfaW5saW5lXzFfYXJnM19cIixcbiAgICAgICAgICAgIFwibHZhbHVlXCI6IGZhbHNlLFxuICAgICAgICAgICAgXCJydmFsdWVcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiY291bnRcIjogMlxuICAgICAgICB9LCB7XG4gICAgICAgICAgICBcIm5hbWVcIjogXCJfaW5saW5lXzFfYXJnNF9cIixcbiAgICAgICAgICAgIFwibHZhbHVlXCI6IGZhbHNlLFxuICAgICAgICAgICAgXCJydmFsdWVcIjogdHJ1ZSxcbiAgICAgICAgICAgIFwiY291bnRcIjogMVxuICAgICAgICB9XSxcbiAgICAgICAgXCJ0aGlzVmFyc1wiOiBbXSxcbiAgICAgICAgXCJsb2NhbFZhcnNcIjogW1wiX2lubGluZV8xX2RhXCIsIFwiX2lubGluZV8xX2RiXCJdXG4gICAgfSxcbiAgICBmdW5jTmFtZTogJ3plcm9Dcm9zc2luZ3MnXG59KVxuXG59LHtcImN3aXNlLWNvbXBpbGVyXCI6MTQ2fV0sNTc0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcblwidXNlIHN0cmljdFwiXG5cbm1vZHVsZS5leHBvcnRzID0gZmluZFplcm9Dcm9zc2luZ3NcblxudmFyIGNvcmUgPSBfZGVyZXFfKFwiLi9saWIvemMtY29yZVwiKVxuXG5mdW5jdGlvbiBmaW5kWmVyb0Nyb3NzaW5ncyhhcnJheSwgbGV2ZWwpIHtcbiAgdmFyIGNyb3NzID0gW11cbiAgbGV2ZWwgPSArbGV2ZWwgfHwgMC4wXG4gIGNvcmUoYXJyYXkuaGkoYXJyYXkuc2hhcGVbMF0tMSksIGNyb3NzLCBsZXZlbClcbiAgcmV0dXJuIGNyb3NzXG59XG59LHtcIi4vbGliL3pjLWNvcmVcIjo1NzN9XSw1NzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIEFsbCBwYXRocyBhcmUgdHVuZWQgZm9yIG1heGltdW0gc2NhbGFiaWxpdHkgb2YgdGhlIGFycm93aGVhZCxcbiAqIGllIHRocm91Z2hvdXQgYXJyb3d3aWR0aD0wLjMuLjMgdGhlIGhlYWQgaXMgam9pbmVkIHNtb290aGx5XG4gKiB0byB0aGUgbGluZSwgd2l0aCB0aGUgbGluZSBjb21pbmcgZnJvbSB0aGUgbGVmdCBhbmQgZW5kaW5nIGF0ICgwLCAwKS5cbiAqXG4gKiBgYmFja29mZmAgaXMgdGhlIGRpc3RhbmNlIHRvIG1vdmUgdGhlIGFycm93aGVhZCBhbmQgdGhlIGVuZCBvZiB0aGUgbGluZSxcbiAqIGluIG9yZGVyIHRoYXQgdGhlIGFycm93aGVhZCBwb2ludHMgdG8gdGhlIGRlc2lyZWQgcGxhY2UsIGVpdGhlciBhdFxuICogdGhlIHRpcCBvZiB0aGUgYXJyb3cgb3IgKGluIHRoZSBjYXNlIG9mIGNpcmNsZSBvciBzcXVhcmUpXG4gKiB0aGUgY2VudGVyIG9mIHRoZSBzeW1ib2wuXG4gKlxuICogYG5vUm90YXRlYCwgaWYgdHJ1dGh5LCBzYXlzIHRoYXQgdGhpcyBhcnJvd2hlYWQgc2hvdWxkIG5vdCByb3RhdGUgd2l0aCB0aGVcbiAqIGFycm93LiBUaGF0J3MgdGhlIGNhc2UgZm9yIHNxdWFyZXMsIHdoaWNoIHNob3VsZCBhbHdheXMgYmUgc3RyYWlnaHQsIGFuZFxuICogY2lyY2xlcywgZm9yIHdoaWNoIGl0J3MgaXJyZWxldmFudC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IFtcbiAgICAvLyBubyBhcnJvd1xuICAgIHtcbiAgICAgICAgcGF0aDogJycsXG4gICAgICAgIGJhY2tvZmY6IDBcbiAgICB9LFxuICAgIC8vIHdpZGUgd2l0aCBmbGF0IGJhY2tcbiAgICB7XG4gICAgICAgIHBhdGg6ICdNLTIuNCwtM1YzTDAuNiwwWicsXG4gICAgICAgIGJhY2tvZmY6IDAuNlxuICAgIH0sXG4gICAgLy8gbmFycm93ZXIgd2l0aCBmbGF0IGJhY2tcbiAgICB7XG4gICAgICAgIHBhdGg6ICdNLTMuNywtMi41VjIuNUwxLjMsMFonLFxuICAgICAgICBiYWNrb2ZmOiAxLjNcbiAgICB9LFxuICAgIC8vIGJhcmJlZFxuICAgIHtcbiAgICAgICAgcGF0aDogJ00tNC40NSwtM0wtMS42NSwtMC4yVjAuMkwtNC40NSwzTDEuNTUsMFonLFxuICAgICAgICBiYWNrb2ZmOiAxLjU1XG4gICAgfSxcbiAgICAvLyB3aWRlIGxpbmUtZHJhd25cbiAgICB7XG4gICAgICAgIHBhdGg6ICdNLTIuMiwtMi4yTC0wLjIsLTAuMlYwLjJMLTIuMiwyLjJMLTEuNCwzTDEuNiwwTC0xLjQsLTNaJyxcbiAgICAgICAgYmFja29mZjogMS42XG4gICAgfSxcbiAgICAvLyBuYXJyb3dlciBsaW5lLWRyYXduXG4gICAge1xuICAgICAgICBwYXRoOiAnTS00LjQsLTIuMUwtMC42LC0wLjJWMC4yTC00LjQsMi4xTC00LDNMMiwwTC00LC0zWicsXG4gICAgICAgIGJhY2tvZmY6IDJcbiAgICB9LFxuICAgIC8vIGNpcmNsZVxuICAgIHtcbiAgICAgICAgcGF0aDogJ00yLDBBMiwyIDAgMSwxIDAsLTJBMiwyIDAgMCwxIDIsMFonLFxuICAgICAgICBiYWNrb2ZmOiAwLFxuICAgICAgICBub1JvdGF0ZTogdHJ1ZVxuICAgIH0sXG4gICAgLy8gc3F1YXJlXG4gICAge1xuICAgICAgICBwYXRoOiAnTTIsMlYtMkgtMlYyWicsXG4gICAgICAgIGJhY2tvZmY6IDAsXG4gICAgICAgIG5vUm90YXRlOiB0cnVlXG4gICAgfVxuXTtcblxufSx7fV0sNTc2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEFSUk9XUEFUSFMgPSBfZGVyZXFfKCcuL2Fycm93X3BhdGhzJyk7XG52YXIgZm9udEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgY2FydGVzaWFuQ29uc3RhbnRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cycpO1xudmFyIHRlbXBsYXRlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gdGVtcGxhdGVkQXJyYXkoJ2Fubm90YXRpb24nLCB7XG4gICAgdmlzaWJsZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0ZXh0YW5nbGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FuZ2xlJyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBjb2xvckVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSksXG4gICAgd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMSxcbiAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhlaWdodDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAxLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgb3BhY2l0eToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYWxpZ246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgZGZsdDogJ2NlbnRlcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmFsaWduOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3RvcCcsICdtaWRkbGUnLCAnYm90dG9tJ10sXG4gICAgICAgIGRmbHQ6ICdtaWRkbGUnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJnY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogJ3JnYmEoMCwwLDAsMCknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcmNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6ICdyZ2JhKDAsMCwwLDApJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3JkZXJwYWQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBhcnJvd1xuICAgIHNob3dhcnJvdzoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhcnJvd2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXJyb3doZWFkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IEFSUk9XUEFUSFMubGVuZ3RoLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN0YXJ0YXJyb3doZWFkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IEFSUk9XUEFUSFMubGVuZ3RoLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFycm93c2lkZToge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBmbGFnczogWydlbmQnLCAnc3RhcnQnXSxcbiAgICAgICAgZXh0cmFzOiBbJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ2VuZCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXJyb3dzaXplOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAuMyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN0YXJ0YXJyb3dzaXplOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAuMyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFycm93d2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMC4xLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RhbmRvZmY6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN0YXJ0c3RhbmRvZmY6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGF4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBheHJlZjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIGRmbHQ6ICdwaXhlbCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgJ3BpeGVsJyxcbiAgICAgICAgICAgIGNhcnRlc2lhbkNvbnN0YW50cy5pZFJlZ2V4LngudG9TdHJpbmcoKVxuICAgICAgICBdLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBheXJlZjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIGRmbHQ6ICdwaXhlbCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgJ3BpeGVsJyxcbiAgICAgICAgICAgIGNhcnRlc2lhbkNvbnN0YW50cy5pZFJlZ2V4LnkudG9TdHJpbmcoKVxuICAgICAgICBdLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBwb3NpdGlvbmluZ1xuICAgIHhyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICdwYXBlcicsXG4gICAgICAgICAgICBjYXJ0ZXNpYW5Db25zdGFudHMuaWRSZWdleC54LnRvU3RyaW5nKClcbiAgICAgICAgXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHhhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYXV0bycsICdsZWZ0JywgJ2NlbnRlcicsICdyaWdodCddLFxuICAgICAgICBkZmx0OiAnYXV0bycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4c2hpZnQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5cmVmOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAncGFwZXInLFxuICAgICAgICAgICAgY2FydGVzaWFuQ29uc3RhbnRzLmlkUmVnZXgueS50b1N0cmluZygpXG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAndG9wJywgJ21pZGRsZScsICdib3R0b20nXSxcbiAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeXNoaWZ0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY2xpY2t0b3Nob3c6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtmYWxzZSwgJ29ub2ZmJywgJ29ub3V0J10sXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHhjbGljazoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5Y2xpY2s6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVybGFiZWw6IHtcbiAgICAgICAgYmdjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGJvcmRlcmNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnXG4gICAgfSxcbiAgICBjYXB0dXJlZXZlbnRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuXG4gICAgX2RlcHJlY2F0ZWQ6IHtcbiAgICAgICAgcmVmOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfVxufSk7XG5cbn0se1wiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9jb25zdGFudHNcIjo3NzMsXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTMsXCIuL2Fycm93X3BhdGhzXCI6NTc1fV0sNTc3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG5cbnZhciBkcmF3ID0gX2RlcmVxXygnLi9kcmF3JykuZHJhdztcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGNBdXRvcmFuZ2UoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBhbm5vdGF0aW9uTGlzdCA9IExpYi5maWx0ZXJWaXNpYmxlKGZ1bGxMYXlvdXQuYW5ub3RhdGlvbnMpO1xuXG4gICAgaWYoYW5ub3RhdGlvbkxpc3QubGVuZ3RoICYmIGdkLl9mdWxsRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIExpYi5zeW5jT3JBc3luYyhbZHJhdywgYW5uQXV0b3JhbmdlXSwgZ2QpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGFubkF1dG9yYW5nZShnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICAvLyBmaW5kIHRoZSBib3VuZGluZyBib3hlcyBmb3IgZWFjaCBvZiB0aGVzZSBhbm5vdGF0aW9ucydcbiAgICAvLyByZWxhdGl2ZSB0byB0aGVpciBhbmNob3IgcG9pbnRzXG4gICAgLy8gdXNlIHRoZSBhcnJvdyBhbmQgdGhlIHRleHQgYmcgcmVjdGFuZ2xlLFxuICAgIC8vIGFzIHRoZSB3aG9sZSBhbm5vIG1heSBpbmNsdWRlIGhpZGRlbiB0ZXh0IGluIGl0cyBiYm94XG4gICAgTGliLmZpbHRlclZpc2libGUoZnVsbExheW91dC5hbm5vdGF0aW9ucykuZm9yRWFjaChmdW5jdGlvbihhbm4pIHtcbiAgICAgICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIGFubi54cmVmKTtcbiAgICAgICAgdmFyIHlhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIGFubi55cmVmKTtcblxuICAgICAgICBhbm4uX2V4dHJlbWVzID0ge307XG4gICAgICAgIGlmKHhhKSBjYWxjQXhpc0V4cGFuc2lvbihhbm4sIHhhKTtcbiAgICAgICAgaWYoeWEpIGNhbGNBeGlzRXhwYW5zaW9uKGFubiwgeWEpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBjYWxjQXhpc0V4cGFuc2lvbihhbm4sIGF4KSB7XG4gICAgdmFyIGF4SWQgPSBheC5faWQ7XG4gICAgdmFyIGxldHRlciA9IGF4SWQuY2hhckF0KDApO1xuICAgIHZhciBwb3MgPSBhbm5bbGV0dGVyXTtcbiAgICB2YXIgYXBvcyA9IGFublsnYScgKyBsZXR0ZXJdO1xuICAgIHZhciByZWYgPSBhbm5bbGV0dGVyICsgJ3JlZiddO1xuICAgIHZhciBhcmVmID0gYW5uWydhJyArIGxldHRlciArICdyZWYnXTtcbiAgICB2YXIgcGFkcGx1cyA9IGFublsnXycgKyBsZXR0ZXIgKyAncGFkcGx1cyddO1xuICAgIHZhciBwYWRtaW51cyA9IGFublsnXycgKyBsZXR0ZXIgKyAncGFkbWludXMnXTtcbiAgICB2YXIgc2hpZnQgPSB7eDogMSwgeTogLTF9W2xldHRlcl0gKiBhbm5bbGV0dGVyICsgJ3NoaWZ0J107XG4gICAgdmFyIGhlYWRTaXplID0gMyAqIGFubi5hcnJvd3NpemUgKiBhbm4uYXJyb3d3aWR0aCB8fCAwO1xuICAgIHZhciBoZWFkUGx1cyA9IGhlYWRTaXplICsgc2hpZnQ7XG4gICAgdmFyIGhlYWRNaW51cyA9IGhlYWRTaXplIC0gc2hpZnQ7XG4gICAgdmFyIHN0YXJ0SGVhZFNpemUgPSAzICogYW5uLnN0YXJ0YXJyb3dzaXplICogYW5uLmFycm93d2lkdGggfHwgMDtcbiAgICB2YXIgc3RhcnRIZWFkUGx1cyA9IHN0YXJ0SGVhZFNpemUgKyBzaGlmdDtcbiAgICB2YXIgc3RhcnRIZWFkTWludXMgPSBzdGFydEhlYWRTaXplIC0gc2hpZnQ7XG4gICAgdmFyIGV4dHJlbWVzO1xuXG4gICAgaWYoYXJlZiA9PT0gcmVmKSB7XG4gICAgICAgIC8vIGV4cGFuZCBmb3IgdGhlIGFycm93aGVhZCAocGFkZGVkIGJ5IGFycm93aGVhZClcbiAgICAgICAgdmFyIGV4dHJlbWVBcnJvd0hlYWQgPSBBeGVzLmZpbmRFeHRyZW1lcyhheCwgW2F4LnIyYyhwb3MpXSwge1xuICAgICAgICAgICAgcHBhZHBsdXM6IGhlYWRQbHVzLFxuICAgICAgICAgICAgcHBhZG1pbnVzOiBoZWFkTWludXNcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGFnYWluIGZvciB0aGUgdGV4dGJveCAocGFkZGVkIGJ5IHRleHRib3gpXG4gICAgICAgIHZhciBleHRyZW1lVGV4dCA9IEF4ZXMuZmluZEV4dHJlbWVzKGF4LCBbYXgucjJjKGFwb3MpXSwge1xuICAgICAgICAgICAgcHBhZHBsdXM6IE1hdGgubWF4KHBhZHBsdXMsIHN0YXJ0SGVhZFBsdXMpLFxuICAgICAgICAgICAgcHBhZG1pbnVzOiBNYXRoLm1heChwYWRtaW51cywgc3RhcnRIZWFkTWludXMpXG4gICAgICAgIH0pO1xuICAgICAgICBleHRyZW1lcyA9IHtcbiAgICAgICAgICAgIG1pbjogW2V4dHJlbWVBcnJvd0hlYWQubWluWzBdLCBleHRyZW1lVGV4dC5taW5bMF1dLFxuICAgICAgICAgICAgbWF4OiBbZXh0cmVtZUFycm93SGVhZC5tYXhbMF0sIGV4dHJlbWVUZXh0Lm1heFswXV1cbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzdGFydEhlYWRQbHVzID0gYXBvcyA/IHN0YXJ0SGVhZFBsdXMgKyBhcG9zIDogc3RhcnRIZWFkUGx1cztcbiAgICAgICAgc3RhcnRIZWFkTWludXMgPSBhcG9zID8gc3RhcnRIZWFkTWludXMgLSBhcG9zIDogc3RhcnRIZWFkTWludXM7XG4gICAgICAgIGV4dHJlbWVzID0gQXhlcy5maW5kRXh0cmVtZXMoYXgsIFtheC5yMmMocG9zKV0sIHtcbiAgICAgICAgICAgIHBwYWRwbHVzOiBNYXRoLm1heChwYWRwbHVzLCBoZWFkUGx1cywgc3RhcnRIZWFkUGx1cyksXG4gICAgICAgICAgICBwcGFkbWludXM6IE1hdGgubWF4KHBhZG1pbnVzLCBoZWFkTWludXMsIHN0YXJ0SGVhZE1pbnVzKVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhbm4uX2V4dHJlbWVzW2F4SWRdID0gZXh0cmVtZXM7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuL2RyYXdcIjo1ODJ9XSw1Nzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIGFycmF5RWRpdG9yID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLmFycmF5RWRpdG9yO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBoYXNDbGlja1RvU2hvdzogaGFzQ2xpY2tUb1Nob3csXG4gICAgb25DbGljazogb25DbGlja1xufTtcblxuLypcbiAqIGhhc0NsaWNrVG9TaG93OiBkb2VzIHRoZSBnaXZlbiBob3ZlckRhdGEgaGF2ZSBBTlkgYW5ub3RhdGlvbnMgd2hpY2ggd2lsbFxuICogdHVybiBPTiBpZiB3ZSBjbGljayBoZXJlPyAodXNlZCBieSBob3ZlciBldmVudHMgdG8gc2V0IGN1cnNvcilcbiAqXG4gKiBnZDogZ3JhcGhEaXZcbiAqIGhvdmVyRGF0YTogYSBob3ZlckRhdGEgYXJyYXksIGFzIGluY2x1ZGVkIHdpdGggdGhlICpwbG90bHlfaG92ZXIqIG9yXG4gKiAgICAgKnBsb3RseV9jbGljayogZXZlbnRzIGluIHRoZSBgcG9pbnRzYCBhdHRyaWJ1dGVcbiAqXG4gKiByZXR1cm5zOiBib29sZWFuXG4gKi9cbmZ1bmN0aW9uIGhhc0NsaWNrVG9TaG93KGdkLCBob3ZlckRhdGEpIHtcbiAgICB2YXIgc2V0cyA9IGdldFRvZ2dsZVNldHMoZ2QsIGhvdmVyRGF0YSk7XG4gICAgcmV0dXJuIHNldHMub24ubGVuZ3RoID4gMCB8fCBzZXRzLmV4cGxpY2l0T2ZmLmxlbmd0aCA+IDA7XG59XG5cbi8qXG4gKiBvbkNsaWNrOiBwZXJmb3JtIHRoZSB0b2dnbGluZyAodmlhIFBsb3RseS51cGRhdGUpIGltcGxpZWQgYnkgY2xpY2tpbmdcbiAqIGF0IHRoaXMgaG92ZXJEYXRhXG4gKlxuICogZ2Q6IGdyYXBoRGl2XG4gKiBob3ZlckRhdGE6IGEgaG92ZXJEYXRhIGFycmF5LCBhcyBpbmNsdWRlZCB3aXRoIHRoZSAqcGxvdGx5X2hvdmVyKiBvclxuICogICAgICpwbG90bHlfY2xpY2sqIGV2ZW50cyBpbiB0aGUgYHBvaW50c2AgYXR0cmlidXRlXG4gKlxuICogcmV0dXJuczogUHJvbWlzZSB0aGF0IHRoZSB1cGRhdGUgaXMgY29tcGxldGVcbiAqL1xuZnVuY3Rpb24gb25DbGljayhnZCwgaG92ZXJEYXRhKSB7XG4gICAgdmFyIHRvZ2dsZVNldHMgPSBnZXRUb2dnbGVTZXRzKGdkLCBob3ZlckRhdGEpO1xuICAgIHZhciBvblNldCA9IHRvZ2dsZVNldHMub247XG4gICAgdmFyIG9mZlNldCA9IHRvZ2dsZVNldHMub2ZmLmNvbmNhdCh0b2dnbGVTZXRzLmV4cGxpY2l0T2ZmKTtcbiAgICB2YXIgdXBkYXRlID0ge307XG4gICAgdmFyIGFubm90YXRpb25zT3V0ID0gZ2QuX2Z1bGxMYXlvdXQuYW5ub3RhdGlvbnM7XG4gICAgdmFyIGksIGVkaXRIZWxwZXJzO1xuXG4gICAgaWYoIShvblNldC5sZW5ndGggfHwgb2ZmU2V0Lmxlbmd0aCkpIHJldHVybjtcblxuICAgIGZvcihpID0gMDsgaSA8IG9uU2V0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGVkaXRIZWxwZXJzID0gYXJyYXlFZGl0b3IoZ2QubGF5b3V0LCAnYW5ub3RhdGlvbnMnLCBhbm5vdGF0aW9uc091dFtvblNldFtpXV0pO1xuICAgICAgICBlZGl0SGVscGVycy5tb2RpZnlJdGVtKCd2aXNpYmxlJywgdHJ1ZSk7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KHVwZGF0ZSwgZWRpdEhlbHBlcnMuZ2V0VXBkYXRlT2JqKCkpO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IG9mZlNldC5sZW5ndGg7IGkrKykge1xuICAgICAgICBlZGl0SGVscGVycyA9IGFycmF5RWRpdG9yKGdkLmxheW91dCwgJ2Fubm90YXRpb25zJywgYW5ub3RhdGlvbnNPdXRbb2ZmU2V0W2ldXSk7XG4gICAgICAgIGVkaXRIZWxwZXJzLm1vZGlmeUl0ZW0oJ3Zpc2libGUnLCBmYWxzZSk7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KHVwZGF0ZSwgZWRpdEhlbHBlcnMuZ2V0VXBkYXRlT2JqKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBSZWdpc3RyeS5jYWxsKCd1cGRhdGUnLCBnZCwge30sIHVwZGF0ZSk7XG59XG5cbi8qXG4gKiBnZXRUb2dnbGVTZXRzOiBmaW5kIHRoZSBhbm5vdGF0aW9ucyB3aGljaCB3aWxsIHR1cm4gb24gb3Igb2ZmIGF0IHRoaXNcbiAqIGhvdmVyRGF0YVxuICpcbiAqIGdkOiBncmFwaERpdlxuICogaG92ZXJEYXRhOiBhIGhvdmVyRGF0YSBhcnJheSwgYXMgaW5jbHVkZWQgd2l0aCB0aGUgKnBsb3RseV9ob3Zlciogb3JcbiAqICAgICAqcGxvdGx5X2NsaWNrKiBldmVudHMgaW4gdGhlIGBwb2ludHNgIGF0dHJpYnV0ZVxuICpcbiAqIHJldHVybnM6IHtcbiAqICAgb246IEFycmF5IChpbmRpY2VzIG9mIGFubm90YXRpb25zIHRvIHR1cm4gb24pLFxuICogICBvZmY6IEFycmF5IChpbmRpY2VzIHRvIHR1cm4gb2ZmIGJlY2F1c2UgeW91J3JlIG5vdCBob3ZlcmluZyBvbiB0aGVtKSxcbiAqICAgZXhwbGljaXRPZmY6IEFycmF5IChpbmRpY2VzIHRvIHR1cm4gb2ZmIGJlY2F1c2UgeW91ICphcmUqIGhvdmVyaW5nIG9uIHRoZW0pXG4gKiB9XG4gKi9cbmZ1bmN0aW9uIGdldFRvZ2dsZVNldHMoZ2QsIGhvdmVyRGF0YSkge1xuICAgIHZhciBhbm5vdGF0aW9ucyA9IGdkLl9mdWxsTGF5b3V0LmFubm90YXRpb25zO1xuICAgIHZhciBvblNldCA9IFtdO1xuICAgIHZhciBvZmZTZXQgPSBbXTtcbiAgICB2YXIgZXhwbGljaXRPZmZTZXQgPSBbXTtcbiAgICB2YXIgaG92ZXJMZW4gPSAoaG92ZXJEYXRhIHx8IFtdKS5sZW5ndGg7XG5cbiAgICB2YXIgaSwgaiwgYW5uaSwgc2hvd01vZGUsIHBvaW50aiwgeGEsIHlhLCB0b2dnbGVUeXBlO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYW5ub3RhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYW5uaSA9IGFubm90YXRpb25zW2ldO1xuICAgICAgICBzaG93TW9kZSA9IGFubmkuY2xpY2t0b3Nob3c7XG5cbiAgICAgICAgaWYoc2hvd01vZGUpIHtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGhvdmVyTGVuOyBqKyspIHtcbiAgICAgICAgICAgICAgICBwb2ludGogPSBob3ZlckRhdGFbal07XG4gICAgICAgICAgICAgICAgeGEgPSBwb2ludGoueGF4aXM7XG4gICAgICAgICAgICAgICAgeWEgPSBwb2ludGoueWF4aXM7XG5cbiAgICAgICAgICAgICAgICBpZih4YS5faWQgPT09IGFubmkueHJlZiAmJlxuICAgICAgICAgICAgICAgICAgICB5YS5faWQgPT09IGFubmkueXJlZiAmJlxuICAgICAgICAgICAgICAgICAgICB4YS5kMnIocG9pbnRqLngpID09PSBjbGlja0RhdGEycihhbm5pLl94Y2xpY2ssIHhhKSAmJlxuICAgICAgICAgICAgICAgICAgICB5YS5kMnIocG9pbnRqLnkpID09PSBjbGlja0RhdGEycihhbm5pLl95Y2xpY2ssIHlhKVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAvLyBtYXRjaCEgdG9nZ2xlIHRoaXMgYW5ub3RhdGlvblxuICAgICAgICAgICAgICAgICAgICAvLyByZWdhcmRsZXNzIG9mIGl0cyBjbGlja3Rvc2hvdyBtb2RlXG4gICAgICAgICAgICAgICAgICAgIC8vIGJ1dCBpZiBpdCdzIG9ub3V0IG1vZGUsIG9mZiBpcyBpbXBsaWNpdFxuICAgICAgICAgICAgICAgICAgICBpZihhbm5pLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHNob3dNb2RlID09PSAnb25vdXQnKSB0b2dnbGVUeXBlID0gb2ZmU2V0O1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB0b2dnbGVUeXBlID0gZXhwbGljaXRPZmZTZXQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b2dnbGVUeXBlID0gb25TZXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdG9nZ2xlVHlwZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGogPT09IGhvdmVyTGVuKSB7XG4gICAgICAgICAgICAgICAgLy8gbm8gbWF0Y2ggLSBvbmx5IHR1cm4gdGhpcyBhbm5vdGF0aW9uIE9GRiwgYW5kIG9ubHkgaWZcbiAgICAgICAgICAgICAgICAvLyBzaG93bW9kZSBpcyAnb25vdXQnXG4gICAgICAgICAgICAgICAgaWYoYW5uaS52aXNpYmxlICYmIHNob3dNb2RlID09PSAnb25vdXQnKSBvZmZTZXQucHVzaChpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7b246IG9uU2V0LCBvZmY6IG9mZlNldCwgZXhwbGljaXRPZmY6IGV4cGxpY2l0T2ZmU2V0fTtcbn1cblxuLy8gdG8gaGFuZGxlIGxvZyBheGVzIHVudGlsIHYyXG5mdW5jdGlvbiBjbGlja0RhdGEycihkLCBheCkge1xuICAgIHJldHVybiBheC50eXBlID09PSAnbG9nJyA/IGF4LmwycihkKSA6IGF4LmQycihkKTtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDd9XSw1Nzk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb2xvcicpO1xuXG4vLyBkZWZhdWx0cyBjb21tb24gdG8gJ2Fubm90YXRpb25zJyBhbmQgJ2Fubm90YXRpb25zM2QnXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZUFubm90YXRpb25Db21tb25EZWZhdWx0cyhhbm5JbiwgYW5uT3V0LCBmdWxsTGF5b3V0LCBjb2VyY2UpIHtcbiAgICBjb2VyY2UoJ29wYWNpdHknKTtcbiAgICB2YXIgYmdDb2xvciA9IGNvZXJjZSgnYmdjb2xvcicpO1xuXG4gICAgdmFyIGJvcmRlckNvbG9yID0gY29lcmNlKCdib3JkZXJjb2xvcicpO1xuICAgIHZhciBib3JkZXJPcGFjaXR5ID0gQ29sb3Iub3BhY2l0eShib3JkZXJDb2xvcik7XG5cbiAgICBjb2VyY2UoJ2JvcmRlcnBhZCcpO1xuXG4gICAgdmFyIGJvcmRlcldpZHRoID0gY29lcmNlKCdib3JkZXJ3aWR0aCcpO1xuICAgIHZhciBzaG93QXJyb3cgPSBjb2VyY2UoJ3Nob3dhcnJvdycpO1xuXG4gICAgY29lcmNlKCd0ZXh0Jywgc2hvd0Fycm93ID8gJyAnIDogZnVsbExheW91dC5fZGZsdFRpdGxlLmFubm90YXRpb24pO1xuICAgIGNvZXJjZSgndGV4dGFuZ2xlJyk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnZm9udCcsIGZ1bGxMYXlvdXQuZm9udCk7XG5cbiAgICBjb2VyY2UoJ3dpZHRoJyk7XG4gICAgY29lcmNlKCdhbGlnbicpO1xuXG4gICAgdmFyIGggPSBjb2VyY2UoJ2hlaWdodCcpO1xuICAgIGlmKGgpIGNvZXJjZSgndmFsaWduJyk7XG5cbiAgICBpZihzaG93QXJyb3cpIHtcbiAgICAgICAgdmFyIGFycm93c2lkZSA9IGNvZXJjZSgnYXJyb3dzaWRlJyk7XG4gICAgICAgIHZhciBhcnJvd2hlYWQ7XG4gICAgICAgIHZhciBhcnJvd3NpemU7XG5cbiAgICAgICAgaWYoYXJyb3dzaWRlLmluZGV4T2YoJ2VuZCcpICE9PSAtMSkge1xuICAgICAgICAgICAgYXJyb3doZWFkID0gY29lcmNlKCdhcnJvd2hlYWQnKTtcbiAgICAgICAgICAgIGFycm93c2l6ZSA9IGNvZXJjZSgnYXJyb3dzaXplJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihhcnJvd3NpZGUuaW5kZXhPZignc3RhcnQnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnc3RhcnRhcnJvd2hlYWQnLCBhcnJvd2hlYWQpO1xuICAgICAgICAgICAgY29lcmNlKCdzdGFydGFycm93c2l6ZScsIGFycm93c2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29lcmNlKCdhcnJvd2NvbG9yJywgYm9yZGVyT3BhY2l0eSA/IGFubk91dC5ib3JkZXJjb2xvciA6IENvbG9yLmRlZmF1bHRMaW5lKTtcbiAgICAgICAgY29lcmNlKCdhcnJvd3dpZHRoJywgKChib3JkZXJPcGFjaXR5ICYmIGJvcmRlcldpZHRoKSB8fCAxKSAqIDIpO1xuICAgICAgICBjb2VyY2UoJ3N0YW5kb2ZmJyk7XG4gICAgICAgIGNvZXJjZSgnc3RhcnRzdGFuZG9mZicpO1xuICAgIH1cblxuICAgIHZhciBob3ZlclRleHQgPSBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIHZhciBnbG9iYWxIb3ZlckxhYmVsID0gZnVsbExheW91dC5ob3ZlcmxhYmVsIHx8IHt9O1xuXG4gICAgaWYoaG92ZXJUZXh0KSB7XG4gICAgICAgIHZhciBob3ZlckJHID0gY29lcmNlKCdob3ZlcmxhYmVsLmJnY29sb3InLCBnbG9iYWxIb3ZlckxhYmVsLmJnY29sb3IgfHxcbiAgICAgICAgICAgIChDb2xvci5vcGFjaXR5KGJnQ29sb3IpID8gQ29sb3IucmdiKGJnQ29sb3IpIDogQ29sb3IuZGVmYXVsdExpbmUpXG4gICAgICAgICk7XG5cbiAgICAgICAgdmFyIGhvdmVyQm9yZGVyID0gY29lcmNlKCdob3ZlcmxhYmVsLmJvcmRlcmNvbG9yJywgZ2xvYmFsSG92ZXJMYWJlbC5ib3JkZXJjb2xvciB8fFxuICAgICAgICAgICAgQ29sb3IuY29udHJhc3QoaG92ZXJCRylcbiAgICAgICAgKTtcblxuICAgICAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICdob3ZlcmxhYmVsLmZvbnQnLCB7XG4gICAgICAgICAgICBmYW1pbHk6IGdsb2JhbEhvdmVyTGFiZWwuZm9udC5mYW1pbHksXG4gICAgICAgICAgICBzaXplOiBnbG9iYWxIb3ZlckxhYmVsLmZvbnQuc2l6ZSxcbiAgICAgICAgICAgIGNvbG9yOiBnbG9iYWxIb3ZlckxhYmVsLmZvbnQuY29sb3IgfHwgaG92ZXJCb3JkZXJcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdjYXB0dXJlZXZlbnRzJywgISFob3ZlclRleHQpO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi9jb2xvclwiOjU5M31dLDU4MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgdG9Mb2dSYW5nZSA9IF9kZXJlcV8oJy4uLy4uL2xpYi90b19sb2dfcmFuZ2UnKTtcblxuLypcbiAqIGNvbnZlcnRDb29yZHM6IHdoZW4gY29udmVydGluZyBhbiBheGlzIGJldHdlZW4gbG9nIGFuZCBsaW5lYXJcbiAqIHlvdSBuZWVkIHRvIGFsdGVyIGFueSBhbm5vdGF0aW9ucyBvbiB0aGF0IGF4aXMgdG8ga2VlcCB0aGVtXG4gKiBwb2ludGluZyBhdCB0aGUgc2FtZSBkYXRhIHBvaW50LlxuICogSW4gdjIuMCB0aGlzIHdpbGwgYmVjb21lIG9ic29sZXRlXG4gKlxuICogZ2Q6IHRoZSBwbG90IGRpdlxuICogYXg6IHRoZSBheGlzIGJlaW5nIGNoYW5nZWRcbiAqIG5ld1R5cGU6IHRoZSB0eXBlIGl0J3MgZ2V0dGluZ1xuICogZG9FeHRyYTogZnVuY3Rpb24oYXR0ciwgdmFsKSBmcm9tIGluc2lkZSByZWxheW91dCB0aGF0IHNldHMgdGhlIGF0dHJpYnV0ZS5cbiAqICAgICBVc2UgdGhpcyB0byBtYWtlIHRoZSBjaGFuZ2VzIGFzIGl0J3MgYXdhcmUgaWYgYW55IG90aGVyIGNoYW5nZXMgaW4gdGhlXG4gKiAgICAgc2FtZSByZWxheW91dCBjYWxsIHNob3VsZCBvdmVycmlkZSB0aGlzIGNvbnZlcnNpb24uXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29udmVydENvb3JkcyhnZCwgYXgsIG5ld1R5cGUsIGRvRXh0cmEpIHtcbiAgICBheCA9IGF4IHx8IHt9O1xuXG4gICAgdmFyIHRvTG9nID0gKG5ld1R5cGUgPT09ICdsb2cnKSAmJiAoYXgudHlwZSA9PT0gJ2xpbmVhcicpO1xuICAgIHZhciBmcm9tTG9nID0gKG5ld1R5cGUgPT09ICdsaW5lYXInKSAmJiAoYXgudHlwZSA9PT0gJ2xvZycpO1xuXG4gICAgaWYoISh0b0xvZyB8fCBmcm9tTG9nKSkgcmV0dXJuO1xuXG4gICAgdmFyIGFubm90YXRpb25zID0gZ2QuX2Z1bGxMYXlvdXQuYW5ub3RhdGlvbnM7XG4gICAgdmFyIGF4TGV0dGVyID0gYXguX2lkLmNoYXJBdCgwKTtcbiAgICB2YXIgYW5uO1xuICAgIHZhciBhdHRyUHJlZml4O1xuXG4gICAgZnVuY3Rpb24gY29udmVydChhdHRyKSB7XG4gICAgICAgIHZhciBjdXJyZW50VmFsID0gYW5uW2F0dHJdO1xuICAgICAgICB2YXIgbmV3VmFsID0gbnVsbDtcblxuICAgICAgICBpZih0b0xvZykgbmV3VmFsID0gdG9Mb2dSYW5nZShjdXJyZW50VmFsLCBheC5yYW5nZSk7XG4gICAgICAgIGVsc2UgbmV3VmFsID0gTWF0aC5wb3coMTAsIGN1cnJlbnRWYWwpO1xuXG4gICAgICAgIC8vIGlmIGNvbnZlcnNpb24gZmFpbGVkLCBkZWxldGUgdGhlIHZhbHVlIHNvIGl0IGdldHMgYSBkZWZhdWx0IHZhbHVlXG4gICAgICAgIGlmKCFpc051bWVyaWMobmV3VmFsKSkgbmV3VmFsID0gbnVsbDtcblxuICAgICAgICBkb0V4dHJhKGF0dHJQcmVmaXggKyBhdHRyLCBuZXdWYWwpO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhbm5vdGF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBhbm4gPSBhbm5vdGF0aW9uc1tpXTtcbiAgICAgICAgYXR0clByZWZpeCA9ICdhbm5vdGF0aW9uc1snICsgaSArICddLic7XG5cbiAgICAgICAgaWYoYW5uW2F4TGV0dGVyICsgJ3JlZiddID09PSBheC5faWQpIGNvbnZlcnQoYXhMZXR0ZXIpO1xuICAgICAgICBpZihhbm5bJ2EnICsgYXhMZXR0ZXIgKyAncmVmJ10gPT09IGF4Ll9pZCkgY29udmVydCgnYScgKyBheExldHRlcik7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWIvdG9fbG9nX3JhbmdlXCI6NzQ1LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSw1ODE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG5cbnZhciBoYW5kbGVBbm5vdGF0aW9uQ29tbW9uRGVmYXVsdHMgPSBfZGVyZXFfKCcuL2NvbW1vbl9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQpIHtcbiAgICBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIHtcbiAgICAgICAgbmFtZTogJ2Fubm90YXRpb25zJyxcbiAgICAgICAgaGFuZGxlSXRlbURlZmF1bHRzOiBoYW5kbGVBbm5vdGF0aW9uRGVmYXVsdHNcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZUFubm90YXRpb25EZWZhdWx0cyhhbm5JbiwgYW5uT3V0LCBmdWxsTGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoYW5uSW4sIGFubk91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcbiAgICB2YXIgY2xpY2tUb1Nob3cgPSBjb2VyY2UoJ2NsaWNrdG9zaG93Jyk7XG5cbiAgICBpZighKHZpc2libGUgfHwgY2xpY2tUb1Nob3cpKSByZXR1cm47XG5cbiAgICBoYW5kbGVBbm5vdGF0aW9uQ29tbW9uRGVmYXVsdHMoYW5uSW4sIGFubk91dCwgZnVsbExheW91dCwgY29lcmNlKTtcblxuICAgIHZhciBzaG93QXJyb3cgPSBhbm5PdXQuc2hvd2Fycm93O1xuXG4gICAgLy8gcG9zaXRpb25pbmdcbiAgICB2YXIgYXhMZXR0ZXJzID0gWyd4JywgJ3knXTtcbiAgICB2YXIgYXJyb3dQb3NEZmx0ID0gWy0xMCwgLTMwXTtcbiAgICB2YXIgZ2RNb2NrID0ge19mdWxsTGF5b3V0OiBmdWxsTGF5b3V0fTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhMZXR0ZXJzW2ldO1xuXG4gICAgICAgIC8vIHhyZWYsIHlyZWZcbiAgICAgICAgdmFyIGF4UmVmID0gQXhlcy5jb2VyY2VSZWYoYW5uSW4sIGFubk91dCwgZ2RNb2NrLCBheExldHRlciwgJycsICdwYXBlcicpO1xuXG4gICAgICAgIGlmKGF4UmVmICE9PSAncGFwZXInKSB7XG4gICAgICAgICAgICB2YXIgYXggPSBBeGVzLmdldEZyb21JZChnZE1vY2ssIGF4UmVmKTtcbiAgICAgICAgICAgIGF4Ll9hbm5JbmRpY2VzLnB1c2goYW5uT3V0Ll9pbmRleCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB4LCB5XG4gICAgICAgIEF4ZXMuY29lcmNlUG9zaXRpb24oYW5uT3V0LCBnZE1vY2ssIGNvZXJjZSwgYXhSZWYsIGF4TGV0dGVyLCAwLjUpO1xuXG4gICAgICAgIGlmKHNob3dBcnJvdykge1xuICAgICAgICAgICAgdmFyIGFycm93UG9zQXR0ciA9ICdhJyArIGF4TGV0dGVyO1xuICAgICAgICAgICAgLy8gYXhyZWYsIGF5cmVmXG4gICAgICAgICAgICB2YXIgYWF4UmVmID0gQXhlcy5jb2VyY2VSZWYoYW5uSW4sIGFubk91dCwgZ2RNb2NrLCBhcnJvd1Bvc0F0dHIsICdwaXhlbCcpO1xuXG4gICAgICAgICAgICAvLyBmb3Igbm93IHRoZSBhcnJvdyBjYW4gb25seSBiZSBvbiB0aGUgc2FtZSBheGlzIG9yIHNwZWNpZmllZCBhcyBwaXhlbHNcbiAgICAgICAgICAgIC8vIFRPRE86IHNvbWV0aW1lIGl0IG1pZ2h0IGJlIGludGVyZXN0aW5nIHRvIGFsbG93IGl0IHRvIGJlIG9uICphbnkqIGF4aXNcbiAgICAgICAgICAgIC8vIGJ1dCB0aGF0IHdvdWxkIHJlcXVpcmUgdXBkYXRlcyB0byBkcmF3aW5nICYgYXV0b3JhbmdlIGNvZGUgYW5kIG1heWJlIG1vcmVcbiAgICAgICAgICAgIGlmKGFheFJlZiAhPT0gJ3BpeGVsJyAmJiBhYXhSZWYgIT09IGF4UmVmKSB7XG4gICAgICAgICAgICAgICAgYWF4UmVmID0gYW5uT3V0W2Fycm93UG9zQXR0cl0gPSAncGl4ZWwnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBheCwgYXlcbiAgICAgICAgICAgIHZhciBhRGZsdCA9IChhYXhSZWYgPT09ICdwaXhlbCcpID8gYXJyb3dQb3NEZmx0W2ldIDogMC40O1xuICAgICAgICAgICAgQXhlcy5jb2VyY2VQb3NpdGlvbihhbm5PdXQsIGdkTW9jaywgY29lcmNlLCBhYXhSZWYsIGFycm93UG9zQXR0ciwgYURmbHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8geGFuY2hvciwgeWFuY2hvclxuICAgICAgICBjb2VyY2UoYXhMZXR0ZXIgKyAnYW5jaG9yJyk7XG5cbiAgICAgICAgLy8geHNoaWZ0LCB5c2hpZnRcbiAgICAgICAgY29lcmNlKGF4TGV0dGVyICsgJ3NoaWZ0Jyk7XG4gICAgfVxuXG4gICAgLy8gaWYgeW91IGhhdmUgb25lIGNvb3JkaW5hdGUgeW91IHNob3VsZCBoYXZlIGJvdGhcbiAgICBMaWIubm9uZU9yQWxsKGFubkluLCBhbm5PdXQsIFsneCcsICd5J10pO1xuXG4gICAgLy8gaWYgeW91IGhhdmUgb25lIHBhcnQgb2YgYXJyb3cgbGVuZ3RoIHlvdSBzaG91bGQgaGF2ZSBib3RoXG4gICAgaWYoc2hvd0Fycm93KSB7XG4gICAgICAgIExpYi5ub25lT3JBbGwoYW5uSW4sIGFubk91dCwgWydheCcsICdheSddKTtcbiAgICB9XG5cbiAgICBpZihjbGlja1RvU2hvdykge1xuICAgICAgICB2YXIgeENsaWNrID0gY29lcmNlKCd4Y2xpY2snKTtcbiAgICAgICAgdmFyIHlDbGljayA9IGNvZXJjZSgneWNsaWNrJyk7XG5cbiAgICAgICAgLy8gcHV0IHRoZSBhY3R1YWwgY2xpY2sgZGF0YSB0byBiaW5kIHRvIGludG8gcHJpdmF0ZSBhdHRyaWJ1dGVzXG4gICAgICAgIC8vIHNvIHdlIGRvbid0IGhhdmUgdG8gZG8gdGhpcyBsaXR0bGUgYml0IG9mIGxvZ2ljIG9uIGV2ZXJ5IGhvdmVyIGV2ZW50XG4gICAgICAgIGFubk91dC5feGNsaWNrID0gKHhDbGljayA9PT0gdW5kZWZpbmVkKSA/XG4gICAgICAgICAgICBhbm5PdXQueCA6XG4gICAgICAgICAgICBBeGVzLmNsZWFuUG9zaXRpb24oeENsaWNrLCBnZE1vY2ssIGFubk91dC54cmVmKTtcbiAgICAgICAgYW5uT3V0Ll95Y2xpY2sgPSAoeUNsaWNrID09PSB1bmRlZmluZWQpID9cbiAgICAgICAgICAgIGFubk91dC55IDpcbiAgICAgICAgICAgIEF4ZXMuY2xlYW5Qb3NpdGlvbih5Q2xpY2ssIGdkTW9jaywgYW5uT3V0LnlyZWYpO1xuICAgIH1cbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHNcIjo3NjMsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4vYXR0cmlidXRlc1wiOjU3NixcIi4vY29tbW9uX2RlZmF1bHRzXCI6NTc5fV0sNTgyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBQbG90cyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL3Bsb3RzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb2xvcicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi9kcmF3aW5nJyk7XG52YXIgRnggPSBfZGVyZXFfKCcuLi9meCcpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIHNldEN1cnNvciA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zZXRjdXJzb3InKTtcbnZhciBkcmFnRWxlbWVudCA9IF9kZXJlcV8oJy4uL2RyYWdlbGVtZW50Jyk7XG52YXIgYXJyYXlFZGl0b3IgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykuYXJyYXlFZGl0b3I7XG5cbnZhciBkcmF3QXJyb3dIZWFkID0gX2RlcmVxXygnLi9kcmF3X2Fycm93X2hlYWQnKTtcblxuLy8gQW5ub3RhdGlvbnMgYXJlIHN0b3JlZCBpbiBnZC5sYXlvdXQuYW5ub3RhdGlvbnMsIGFuIGFycmF5IG9mIG9iamVjdHNcbi8vIGluZGV4IGNhbiBwb2ludCB0byBvbmUgaXRlbSBpbiB0aGlzIGFycmF5LFxuLy8gIG9yIG5vbi1udW1lcmljIHRvIHNpbXBseSBhZGQgYSBuZXcgb25lXG4vLyAgb3IgLTEgdG8gbW9kaWZ5IGFsbCBleGlzdGluZ1xuLy8gb3B0IGNhbiBiZSB0aGUgZnVsbCBvcHRpb25zIG9iamVjdCwgb3Igb25lIGtleSAodG8gYmUgc2V0IHRvIHZhbHVlKVxuLy8gIG9yIHVuZGVmaW5lZCB0byBzaW1wbHkgcmVkcmF3XG4vLyBpZiBvcHQgaXMgYmxhbmssIHZhbCBjYW4gYmUgJ2FkZCcgb3IgYSBmdWxsIG9wdGlvbnMgb2JqZWN0IHRvIGFkZCBhIG5ld1xuLy8gIGFubm90YXRpb24gYXQgdGhhdCBwb2ludCBpbiB0aGUgYXJyYXksIG9yICdyZW1vdmUnIHRvIGRlbGV0ZSB0aGlzIG9uZVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBkcmF3OiBkcmF3LFxuICAgIGRyYXdPbmU6IGRyYXdPbmUsXG4gICAgZHJhd1JhdzogZHJhd1Jhd1xufTtcblxuLypcbiAqIGRyYXc6IGRyYXcgYWxsIGFubm90YXRpb25zIHdpdGhvdXQgYW55IG5ldyBtb2RpZmljYXRpb25zXG4gKi9cbmZ1bmN0aW9uIGRyYXcoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgZnVsbExheW91dC5faW5mb2xheWVyLnNlbGVjdEFsbCgnLmFubm90YXRpb24nKS5yZW1vdmUoKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsTGF5b3V0LmFubm90YXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGZ1bGxMYXlvdXQuYW5ub3RhdGlvbnNbaV0udmlzaWJsZSkge1xuICAgICAgICAgICAgZHJhd09uZShnZCwgaSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gUGxvdHMucHJldmlvdXNQcm9taXNlcyhnZCk7XG59XG5cbi8qXG4gKiBkcmF3T25lOiBkcmF3IGEgc2luZ2xlIGNhcnRlc2lhbiBvciBwYXBlci1yZWYgYW5ub3RhdGlvbiwgcG90ZW50aWFsbHkgd2l0aCBtb2RpZmljYXRpb25zXG4gKlxuICogaW5kZXggKGludCk6IHRoZSBhbm5vdGF0aW9uIHRvIGRyYXdcbiAqL1xuZnVuY3Rpb24gZHJhd09uZShnZCwgaW5kZXgpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBvcHRpb25zID0gZnVsbExheW91dC5hbm5vdGF0aW9uc1tpbmRleF0gfHwge307XG4gICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIG9wdGlvbnMueHJlZik7XG4gICAgdmFyIHlhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIG9wdGlvbnMueXJlZik7XG5cbiAgICBpZih4YSkgeGEuc2V0U2NhbGUoKTtcbiAgICBpZih5YSkgeWEuc2V0U2NhbGUoKTtcblxuICAgIGRyYXdSYXcoZ2QsIG9wdGlvbnMsIGluZGV4LCBmYWxzZSwgeGEsIHlhKTtcbn1cblxuLyoqXG4gKiBkcmF3UmF3OiBkcmF3IGEgc2luZ2xlIGFubm90YXRpb24sIHBvdGVudGlhbGx5IHdpdGggbW9kaWZpY2F0aW9uc1xuICpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyA6IHRoaXMgYW5ub3RhdGlvbidzIGZ1bGxMYXlvdXQgb3B0aW9uc1xuICogQHBhcmFtIHtpbnRlZ2VyfSBpbmRleCA6IGluZGV4IGluICdhbm5vdGF0aW9ucycgY29udGFpbmVyIG9mIHRoZSBhbm5vdGF0aW9uIHRvIGRyYXdcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdWJwbG90SWQgOiBpZCBvZiB0aGUgYW5ub3RhdGlvbidzIHN1YnBsb3RcbiAqICAtIHVzZSBmYWxzZSBmb3IgMmQgKGkuZS4gY2FydGVzaWFuIG9yIHBhcGVyLXJlZikgYW5ub3RhdGlvbnNcbiAqIEBwYXJhbSB7b2JqZWN0IHwgdW5kZWZpbmVkfSB4YSA6IGZ1bGwgeC1heGlzIG9iamVjdCB0byBjb21wdXRlIHN1YnBsb3QgcG9zLXRvLXB4XG4gKiBAcGFyYW0ge29iamVjdCB8IHVuZGVmaW5lZH0geWEgOiAuLi4geS1heGlzXG4gKi9cbmZ1bmN0aW9uIGRyYXdSYXcoZ2QsIG9wdGlvbnMsIGluZGV4LCBzdWJwbG90SWQsIHhhLCB5YSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGdzID0gZ2QuX2Z1bGxMYXlvdXQuX3NpemU7XG4gICAgdmFyIGVkaXRzID0gZ2QuX2NvbnRleHQuZWRpdHM7XG5cbiAgICB2YXIgY2xhc3NOYW1lLCBjb250YWluZXJTdHI7XG5cbiAgICBpZihzdWJwbG90SWQpIHtcbiAgICAgICAgY2xhc3NOYW1lID0gJ2Fubm90YXRpb24tJyArIHN1YnBsb3RJZDtcbiAgICAgICAgY29udGFpbmVyU3RyID0gc3VicGxvdElkICsgJy5hbm5vdGF0aW9ucyc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY2xhc3NOYW1lID0gJ2Fubm90YXRpb24nO1xuICAgICAgICBjb250YWluZXJTdHIgPSAnYW5ub3RhdGlvbnMnO1xuICAgIH1cblxuICAgIHZhciBlZGl0SGVscGVycyA9IGFycmF5RWRpdG9yKGdkLmxheW91dCwgY29udGFpbmVyU3RyLCBvcHRpb25zKTtcbiAgICB2YXIgbW9kaWZ5QmFzZSA9IGVkaXRIZWxwZXJzLm1vZGlmeUJhc2U7XG4gICAgdmFyIG1vZGlmeUl0ZW0gPSBlZGl0SGVscGVycy5tb2RpZnlJdGVtO1xuICAgIHZhciBnZXRVcGRhdGVPYmogPSBlZGl0SGVscGVycy5nZXRVcGRhdGVPYmo7XG5cbiAgICAvLyByZW1vdmUgdGhlIGV4aXN0aW5nIGFubm90YXRpb24gaWYgdGhlcmUgaXMgb25lXG4gICAgZnVsbExheW91dC5faW5mb2xheWVyXG4gICAgICAgIC5zZWxlY3RBbGwoJy4nICsgY2xhc3NOYW1lICsgJ1tkYXRhLWluZGV4PVwiJyArIGluZGV4ICsgJ1wiXScpXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIHZhciBhbm5DbGlwSUQgPSAnY2xpcCcgKyBmdWxsTGF5b3V0Ll91aWQgKyAnX2FubicgKyBpbmRleDtcblxuICAgIC8vIHRoaXMgYW5ub3RhdGlvbiBpcyBnb25lIC0gcXVpdCBub3cgYWZ0ZXIgZGVsZXRpbmcgaXRcbiAgICAvLyBUT0RPOiB1c2UgZDMgaWRpb21zIGluc3RlYWQgb2YgZGVsZXRpbmcgYW5kIHJlZHJhd2luZyBldmVyeSB0aW1lXG4gICAgaWYoIW9wdGlvbnMuX2lucHV0IHx8IG9wdGlvbnMudmlzaWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgZDMuc2VsZWN0QWxsKCcjJyArIGFubkNsaXBJRCkucmVtb3ZlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBjYWxjdWxhdGVkIHBpeGVsIHBvc2l0aW9uc1xuICAgIC8vIHggJiB5IGVhY2ggd2lsbCBnZXQgdGV4dCwgaGVhZCwgYW5kIHRhaWwgYXMgYXBwcm9wcmlhdGVcbiAgICB2YXIgYW5uUG9zUHggPSB7eDoge30sIHk6IHt9fTtcbiAgICB2YXIgdGV4dGFuZ2xlID0gK29wdGlvbnMudGV4dGFuZ2xlIHx8IDA7XG5cbiAgICAvLyBjcmVhdGUgdGhlIGNvbXBvbmVudHNcbiAgICAvLyBtYWRlIGEgc2luZ2xlIGdyb3VwIHRvIGNvbnRhaW4gYWxsLCBzbyBvcGFjaXR5IGNhbiB3b3JrIHJpZ2h0XG4gICAgLy8gd2l0aCBib3JkZXIvYXJyb3cgdG9nZXRoZXIgdGhpcyBjb3VsZCBoYW5kbGUgYSB3aG9sZSBidW5jaCBvZlxuICAgIC8vIGNsZWFudXAgYXQgdGhpcyBwb2ludCwgYnV0IHdvcmtzIGZvciBub3dcbiAgICB2YXIgYW5uR3JvdXAgPSBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY2xhc3NOYW1lLCB0cnVlKVxuICAgICAgICAuYXR0cignZGF0YS1pbmRleCcsIFN0cmluZyhpbmRleCkpXG4gICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIG9wdGlvbnMub3BhY2l0eSk7XG5cbiAgICAvLyBhbm90aGVyIGdyb3VwIGZvciB0ZXh0K2JhY2tncm91bmQgc28gdGhhdCB0aGV5IGNhbiByb3RhdGUgdG9nZXRoZXJcbiAgICB2YXIgYW5uVGV4dEdyb3VwID0gYW5uR3JvdXAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2Fubm90YXRpb24tdGV4dC1nJywgdHJ1ZSk7XG5cbiAgICB2YXIgZWRpdFRleHRQb3NpdGlvbiA9IGVkaXRzW29wdGlvbnMuc2hvd2Fycm93ID8gJ2Fubm90YXRpb25UYWlsJyA6ICdhbm5vdGF0aW9uUG9zaXRpb24nXTtcbiAgICB2YXIgdGV4dEV2ZW50cyA9IG9wdGlvbnMuY2FwdHVyZWV2ZW50cyB8fCBlZGl0cy5hbm5vdGF0aW9uVGV4dCB8fCBlZGl0VGV4dFBvc2l0aW9uO1xuXG4gICAgZnVuY3Rpb24gbWFrZUV2ZW50RGF0YShpbml0aWFsRXZlbnQpIHtcbiAgICAgICAgdmFyIGV2ZW50RGF0YSA9IHtcbiAgICAgICAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgICAgICAgIGFubm90YXRpb246IG9wdGlvbnMuX2lucHV0LFxuICAgICAgICAgICAgZnVsbEFubm90YXRpb246IG9wdGlvbnMsXG4gICAgICAgICAgICBldmVudDogaW5pdGlhbEV2ZW50XG4gICAgICAgIH07XG4gICAgICAgIGlmKHN1YnBsb3RJZCkge1xuICAgICAgICAgICAgZXZlbnREYXRhLnN1YnBsb3RJZCA9IHN1YnBsb3RJZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZXZlbnREYXRhO1xuICAgIH1cblxuICAgIHZhciBhbm5UZXh0R3JvdXBJbm5lciA9IGFublRleHRHcm91cC5hcHBlbmQoJ2cnKVxuICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgdGV4dEV2ZW50cyA/ICdhbGwnIDogbnVsbClcbiAgICAgICAgLmNhbGwoc2V0Q3Vyc29yLCAncG9pbnRlcicpXG4gICAgICAgIC5vbignY2xpY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGdkLl9kcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2NsaWNrYW5ub3RhdGlvbicsIG1ha2VFdmVudERhdGEoZDMuZXZlbnQpKTtcbiAgICAgICAgfSk7XG5cbiAgICBpZihvcHRpb25zLmhvdmVydGV4dCkge1xuICAgICAgICBhbm5UZXh0R3JvdXBJbm5lclxuICAgICAgICAub24oJ21vdXNlb3ZlcicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGhvdmVyT3B0aW9ucyA9IG9wdGlvbnMuaG92ZXJsYWJlbDtcbiAgICAgICAgICAgIHZhciBob3ZlckZvbnQgPSBob3Zlck9wdGlvbnMuZm9udDtcbiAgICAgICAgICAgIHZhciBiQm94ID0gdGhpcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIHZhciBiQm94UmVmID0gZ2QuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgICAgIEZ4LmxvbmVIb3Zlcih7XG4gICAgICAgICAgICAgICAgeDA6IGJCb3gubGVmdCAtIGJCb3hSZWYubGVmdCxcbiAgICAgICAgICAgICAgICB4MTogYkJveC5yaWdodCAtIGJCb3hSZWYubGVmdCxcbiAgICAgICAgICAgICAgICB5OiAoYkJveC50b3AgKyBiQm94LmJvdHRvbSkgLyAyIC0gYkJveFJlZi50b3AsXG4gICAgICAgICAgICAgICAgdGV4dDogb3B0aW9ucy5ob3ZlcnRleHQsXG4gICAgICAgICAgICAgICAgY29sb3I6IGhvdmVyT3B0aW9ucy5iZ2NvbG9yLFxuICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiBob3Zlck9wdGlvbnMuYm9yZGVyY29sb3IsXG4gICAgICAgICAgICAgICAgZm9udEZhbWlseTogaG92ZXJGb250LmZhbWlseSxcbiAgICAgICAgICAgICAgICBmb250U2l6ZTogaG92ZXJGb250LnNpemUsXG4gICAgICAgICAgICAgICAgZm9udENvbG9yOiBob3ZlckZvbnQuY29sb3JcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIubm9kZSgpLFxuICAgICAgICAgICAgICAgIG91dGVyQ29udGFpbmVyOiBmdWxsTGF5b3V0Ll9wYXBlci5ub2RlKCksXG4gICAgICAgICAgICAgICAgZ2Q6IGdkXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdtb3VzZW91dCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgRngubG9uZVVuaG92ZXIoZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgYm9yZGVyd2lkdGggPSBvcHRpb25zLmJvcmRlcndpZHRoO1xuICAgIHZhciBib3JkZXJwYWQgPSBvcHRpb25zLmJvcmRlcnBhZDtcbiAgICB2YXIgYm9yZGVyZnVsbCA9IGJvcmRlcndpZHRoICsgYm9yZGVycGFkO1xuXG4gICAgdmFyIGFublRleHRCRyA9IGFublRleHRHcm91cElubmVyLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdiZycpXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgYm9yZGVyd2lkdGggKyAncHgnKVxuICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIG9wdGlvbnMuYm9yZGVyY29sb3IpXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIG9wdGlvbnMuYmdjb2xvcik7XG5cbiAgICB2YXIgaXNTaXplQ29uc3RyYWluZWQgPSBvcHRpb25zLndpZHRoIHx8IG9wdGlvbnMuaGVpZ2h0O1xuXG4gICAgdmFyIGFublRleHRDbGlwID0gZnVsbExheW91dC5fdG9wY2xpcHNcbiAgICAgICAgLnNlbGVjdEFsbCgnIycgKyBhbm5DbGlwSUQpXG4gICAgICAgIC5kYXRhKGlzU2l6ZUNvbnN0cmFpbmVkID8gWzBdIDogW10pO1xuXG4gICAgYW5uVGV4dENsaXAuZW50ZXIoKS5hcHBlbmQoJ2NsaXBQYXRoJylcbiAgICAgICAgLmNsYXNzZWQoJ2FubmNsaXAnLCB0cnVlKVxuICAgICAgICAuYXR0cignaWQnLCBhbm5DbGlwSUQpXG4gICAgICAuYXBwZW5kKCdyZWN0Jyk7XG4gICAgYW5uVGV4dENsaXAuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdmFyIGZvbnQgPSBvcHRpb25zLmZvbnQ7XG5cbiAgICB2YXIgdGV4dCA9IGZ1bGxMYXlvdXQuX21ldGEgP1xuICAgICAgICBMaWIudGVtcGxhdGVTdHJpbmcob3B0aW9ucy50ZXh0LCBmdWxsTGF5b3V0Ll9tZXRhKSA6XG4gICAgICAgIG9wdGlvbnMudGV4dDtcblxuICAgIHZhciBhbm5UZXh0ID0gYW5uVGV4dEdyb3VwSW5uZXIuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmNsYXNzZWQoJ2Fubm90YXRpb24tdGV4dCcsIHRydWUpXG4gICAgICAgIC50ZXh0KHRleHQpO1xuXG4gICAgZnVuY3Rpb24gdGV4dExheW91dChzKSB7XG4gICAgICAgIHMuY2FsbChEcmF3aW5nLmZvbnQsIGZvbnQpXG4gICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6IHtcbiAgICAgICAgICAgICAgICBsZWZ0OiAnc3RhcnQnLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiAnZW5kJ1xuICAgICAgICAgICAgfVtvcHRpb25zLmFsaWduXSB8fCAnbWlkZGxlJ1xuICAgICAgICB9KTtcblxuICAgICAgICBzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zKHMsIGdkLCBkcmF3R3JhcGhpY2FsRWxlbWVudHMpO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3R3JhcGhpY2FsRWxlbWVudHMoKSB7XG4gICAgICAgIC8vIGlmIHRoZSB0ZXh0IGhhcyAqb25seSogYSBsaW5rLCBtYWtlIHRoZSB3aG9sZSBib3ggaW50byBhIGxpbmtcbiAgICAgICAgdmFyIGFuY2hvcjMgPSBhbm5UZXh0LnNlbGVjdEFsbCgnYScpO1xuICAgICAgICBpZihhbmNob3IzLnNpemUoKSA9PT0gMSAmJiBhbmNob3IzLnRleHQoKSA9PT0gYW5uVGV4dC50ZXh0KCkpIHtcbiAgICAgICAgICAgIHZhciB3aG9sZUxpbmsgPSBhbm5UZXh0R3JvdXBJbm5lci5pbnNlcnQoJ2EnLCAnOmZpcnN0LWNoaWxkJykuYXR0cih7XG4gICAgICAgICAgICAgICAgJ3hsaW5rOnhsaW5rOmhyZWYnOiBhbmNob3IzLmF0dHIoJ3hsaW5rOmhyZWYnKSxcbiAgICAgICAgICAgICAgICAneGxpbms6eGxpbms6c2hvdyc6IGFuY2hvcjMuYXR0cigneGxpbms6c2hvdycpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnN0eWxlKHtjdXJzb3I6ICdwb2ludGVyJ30pO1xuXG4gICAgICAgICAgICB3aG9sZUxpbmsubm9kZSgpLmFwcGVuZENoaWxkKGFublRleHRCRy5ub2RlKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1hdGhqYXhHcm91cCA9IGFublRleHRHcm91cElubmVyLnNlbGVjdCgnLmFubm90YXRpb24tdGV4dC1tYXRoLWdyb3VwJyk7XG4gICAgICAgIHZhciBoYXNNYXRoamF4ID0gIW1hdGhqYXhHcm91cC5lbXB0eSgpO1xuICAgICAgICB2YXIgYW5udGV4dEJCID0gRHJhd2luZy5iQm94KFxuICAgICAgICAgICAgICAgIChoYXNNYXRoamF4ID8gbWF0aGpheEdyb3VwIDogYW5uVGV4dCkubm9kZSgpKTtcbiAgICAgICAgdmFyIHRleHRXaWR0aCA9IGFubnRleHRCQi53aWR0aDtcbiAgICAgICAgdmFyIHRleHRIZWlnaHQgPSBhbm50ZXh0QkIuaGVpZ2h0O1xuICAgICAgICB2YXIgYW5uV2lkdGggPSBvcHRpb25zLndpZHRoIHx8IHRleHRXaWR0aDtcbiAgICAgICAgdmFyIGFubkhlaWdodCA9IG9wdGlvbnMuaGVpZ2h0IHx8IHRleHRIZWlnaHQ7XG4gICAgICAgIHZhciBvdXRlcldpZHRoID0gTWF0aC5yb3VuZChhbm5XaWR0aCArIDIgKiBib3JkZXJmdWxsKTtcbiAgICAgICAgdmFyIG91dGVySGVpZ2h0ID0gTWF0aC5yb3VuZChhbm5IZWlnaHQgKyAyICogYm9yZGVyZnVsbCk7XG5cbiAgICAgICAgZnVuY3Rpb24gc2hpZnRGcmFjdGlvbih2LCBhbmNob3IpIHtcbiAgICAgICAgICAgIGlmKGFuY2hvciA9PT0gJ2F1dG8nKSB7XG4gICAgICAgICAgICAgICAgaWYodiA8IDEgLyAzKSBhbmNob3IgPSAnbGVmdCc7XG4gICAgICAgICAgICAgICAgZWxzZSBpZih2ID4gMiAvIDMpIGFuY2hvciA9ICdyaWdodCc7XG4gICAgICAgICAgICAgICAgZWxzZSBhbmNob3IgPSAnY2VudGVyJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgY2VudGVyOiAwLFxuICAgICAgICAgICAgICAgIG1pZGRsZTogMCxcbiAgICAgICAgICAgICAgICBsZWZ0OiAwLjUsXG4gICAgICAgICAgICAgICAgYm90dG9tOiAtMC41LFxuICAgICAgICAgICAgICAgIHJpZ2h0OiAtMC41LFxuICAgICAgICAgICAgICAgIHRvcDogMC41XG4gICAgICAgICAgICB9W2FuY2hvcl07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYW5ub3RhdGlvbklzT2Zmc2NyZWVuID0gZmFsc2U7XG4gICAgICAgIHZhciBsZXR0ZXJzID0gWyd4JywgJ3knXTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGV0dGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGF4TGV0dGVyID0gbGV0dGVyc1tpXTtcbiAgICAgICAgICAgIHZhciBheFJlZiA9IG9wdGlvbnNbYXhMZXR0ZXIgKyAncmVmJ10gfHwgYXhMZXR0ZXI7XG4gICAgICAgICAgICB2YXIgdGFpbFJlZiA9IG9wdGlvbnNbJ2EnICsgYXhMZXR0ZXIgKyAncmVmJ107XG4gICAgICAgICAgICB2YXIgYXggPSB7eDogeGEsIHk6IHlhfVtheExldHRlcl07XG4gICAgICAgICAgICB2YXIgZGltQW5nbGUgPSAodGV4dGFuZ2xlICsgKGF4TGV0dGVyID09PSAneCcgPyAwIDogLTkwKSkgKiBNYXRoLlBJIC8gMTgwO1xuICAgICAgICAgICAgLy8gbm90ZSB0aGF0IHRoZXNlIHR3byBjYW4gYmUgZWl0aGVyIHBvc2l0aXZlIG9yIG5lZ2F0aXZlXG4gICAgICAgICAgICB2YXIgYW5uU2l6ZUZyb21XaWR0aCA9IG91dGVyV2lkdGggKiBNYXRoLmNvcyhkaW1BbmdsZSk7XG4gICAgICAgICAgICB2YXIgYW5uU2l6ZUZyb21IZWlnaHQgPSBvdXRlckhlaWdodCAqIE1hdGguc2luKGRpbUFuZ2xlKTtcbiAgICAgICAgICAgIC8vIGJ1dCB0aGlzIG9uZSBpcyB0aGUgcG9zaXRpdmUgdG90YWwgc2l6ZVxuICAgICAgICAgICAgdmFyIGFublNpemUgPSBNYXRoLmFicyhhbm5TaXplRnJvbVdpZHRoKSArIE1hdGguYWJzKGFublNpemVGcm9tSGVpZ2h0KTtcbiAgICAgICAgICAgIHZhciBhbmNob3IgPSBvcHRpb25zW2F4TGV0dGVyICsgJ2FuY2hvciddO1xuICAgICAgICAgICAgdmFyIG92ZXJhbGxTaGlmdCA9IG9wdGlvbnNbYXhMZXR0ZXIgKyAnc2hpZnQnXSAqIChheExldHRlciA9PT0gJ3gnID8gMSA6IC0xKTtcbiAgICAgICAgICAgIHZhciBwb3NQeCA9IGFublBvc1B4W2F4TGV0dGVyXTtcbiAgICAgICAgICAgIHZhciBiYXNlUHg7XG4gICAgICAgICAgICB2YXIgdGV4dFBhZFNoaWZ0O1xuICAgICAgICAgICAgdmFyIGFsaWduUG9zaXRpb247XG4gICAgICAgICAgICB2YXIgYXV0b0FsaWduRnJhY3Rpb247XG4gICAgICAgICAgICB2YXIgdGV4dFNoaWZ0O1xuXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogY2FsY3VsYXRlIHRoZSAqcHJpbWFyeSogcGl4ZWwgcG9zaXRpb25cbiAgICAgICAgICAgICAqIHdoaWNoIGlzIHRoZSBhcnJvd2hlYWQgaWYgdGhlcmUgaXMgb25lLFxuICAgICAgICAgICAgICogb3RoZXJ3aXNlIHRoZSB0ZXh0IGFuY2hvciBwb2ludFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZihheCkge1xuICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIGFubm90YXRpb24gaXMgb2ZmIHNjcmVlbiwgdG8gYnlwYXNzIERPTSBtYW5pcHVsYXRpb25zXG4gICAgICAgICAgICAgICAgdmFyIHBvc0ZyYWN0aW9uID0gYXgucjJmcmFjdGlvbihvcHRpb25zW2F4TGV0dGVyXSk7XG4gICAgICAgICAgICAgICAgaWYocG9zRnJhY3Rpb24gPCAwIHx8IHBvc0ZyYWN0aW9uID4gMSkge1xuICAgICAgICAgICAgICAgICAgICBpZih0YWlsUmVmID09PSBheFJlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zRnJhY3Rpb24gPSBheC5yMmZyYWN0aW9uKG9wdGlvbnNbJ2EnICsgYXhMZXR0ZXJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHBvc0ZyYWN0aW9uIDwgMCB8fCBwb3NGcmFjdGlvbiA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uSXNPZmZzY3JlZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbklzT2Zmc2NyZWVuID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBiYXNlUHggPSBheC5fb2Zmc2V0ICsgYXgucjJwKG9wdGlvbnNbYXhMZXR0ZXJdKTtcbiAgICAgICAgICAgICAgICBhdXRvQWxpZ25GcmFjdGlvbiA9IDAuNTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYoYXhMZXR0ZXIgPT09ICd4Jykge1xuICAgICAgICAgICAgICAgICAgICBhbGlnblBvc2l0aW9uID0gb3B0aW9uc1theExldHRlcl07XG4gICAgICAgICAgICAgICAgICAgIGJhc2VQeCA9IGdzLmwgKyBncy53ICogYWxpZ25Qb3NpdGlvbjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhbGlnblBvc2l0aW9uID0gMSAtIG9wdGlvbnNbYXhMZXR0ZXJdO1xuICAgICAgICAgICAgICAgICAgICBiYXNlUHggPSBncy50ICsgZ3MuaCAqIGFsaWduUG9zaXRpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF1dG9BbGlnbkZyYWN0aW9uID0gb3B0aW9ucy5zaG93YXJyb3cgPyAwLjUgOiBhbGlnblBvc2l0aW9uO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBub3cgdHJhbnNsYXRlIHRoaXMgaW50byBwaXhlbCBwb3NpdGlvbnMgb2YgaGVhZCwgdGFpbCwgYW5kIHRleHRcbiAgICAgICAgICAgIC8vIGFzIHdlbGwgYXMgcGFkZGluZ3MgZm9yIGF1dG9yYW5nZVxuICAgICAgICAgICAgaWYob3B0aW9ucy5zaG93YXJyb3cpIHtcbiAgICAgICAgICAgICAgICBwb3NQeC5oZWFkID0gYmFzZVB4O1xuXG4gICAgICAgICAgICAgICAgdmFyIGFycm93TGVuZ3RoID0gb3B0aW9uc1snYScgKyBheExldHRlcl07XG5cbiAgICAgICAgICAgICAgICAvLyB3aXRoIGFuIGFycm93LCB0aGUgdGV4dCByb3RhdGVzIGFyb3VuZCB0aGUgYW5jaG9yIHBvaW50XG4gICAgICAgICAgICAgICAgdGV4dFNoaWZ0ID0gYW5uU2l6ZUZyb21XaWR0aCAqIHNoaWZ0RnJhY3Rpb24oMC41LCBvcHRpb25zLnhhbmNob3IpIC1cbiAgICAgICAgICAgICAgICAgICAgYW5uU2l6ZUZyb21IZWlnaHQgKiBzaGlmdEZyYWN0aW9uKDAuNSwgb3B0aW9ucy55YW5jaG9yKTtcblxuICAgICAgICAgICAgICAgIGlmKHRhaWxSZWYgPT09IGF4UmVmKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvc1B4LnRhaWwgPSBheC5fb2Zmc2V0ICsgYXgucjJwKGFycm93TGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGFpbCBpcyBkYXRhLXJlZmVyZW5jZWQ6IGF1dG9yYW5nZSBwYWRzIHRoZSB0ZXh0IGluIHB4IGZyb20gdGhlIHRhaWxcbiAgICAgICAgICAgICAgICAgICAgdGV4dFBhZFNoaWZ0ID0gdGV4dFNoaWZ0O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBvc1B4LnRhaWwgPSBiYXNlUHggKyBhcnJvd0xlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGFpbCBpcyBzcGVjaWZpZWQgaW4gcHggZnJvbSBoZWFkLCBzbyBhdXRvcmFuZ2UgYWxzbyBwYWRzIHZzIGhlYWRcbiAgICAgICAgICAgICAgICAgICAgdGV4dFBhZFNoaWZ0ID0gdGV4dFNoaWZ0ICsgYXJyb3dMZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcG9zUHgudGV4dCA9IHBvc1B4LnRhaWwgKyB0ZXh0U2hpZnQ7XG5cbiAgICAgICAgICAgICAgICAvLyBjb25zdHJhaW4gcGl4ZWwvcGFwZXIgcmVmZXJlbmNlZCBzbyB0aGUgZHJhZ2dlcnMgYXJlIGF0IGxlYXN0XG4gICAgICAgICAgICAgICAgLy8gcGFydGlhbGx5IHZpc2libGVcbiAgICAgICAgICAgICAgICB2YXIgbWF4UHggPSBmdWxsTGF5b3V0WyhheExldHRlciA9PT0gJ3gnKSA/ICd3aWR0aCcgOiAnaGVpZ2h0J107XG4gICAgICAgICAgICAgICAgaWYoYXhSZWYgPT09ICdwYXBlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9zUHguaGVhZCA9IExpYi5jb25zdHJhaW4ocG9zUHguaGVhZCwgMSwgbWF4UHggLSAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYodGFpbFJlZiA9PT0gJ3BpeGVsJykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2hpZnRQbHVzID0gLU1hdGgubWF4KHBvc1B4LnRhaWwgLSAzLCBwb3NQeC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNoaWZ0TWludXMgPSBNYXRoLm1pbihwb3NQeC50YWlsICsgMywgcG9zUHgudGV4dCkgLSBtYXhQeDtcbiAgICAgICAgICAgICAgICAgICAgaWYoc2hpZnRQbHVzID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zUHgudGFpbCArPSBzaGlmdFBsdXM7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NQeC50ZXh0ICs9IHNoaWZ0UGx1cztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHNoaWZ0TWludXMgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NQeC50YWlsIC09IHNoaWZ0TWludXM7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NQeC50ZXh0IC09IHNoaWZ0TWludXM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwb3NQeC50YWlsICs9IG92ZXJhbGxTaGlmdDtcbiAgICAgICAgICAgICAgICBwb3NQeC5oZWFkICs9IG92ZXJhbGxTaGlmdDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gd2l0aCBubyBhcnJvdywgdGhlIHRleHQgcm90YXRlcyBhbmQgKnRoZW4qIHdlIHB1dCB0aGUgYW5jaG9yXG4gICAgICAgICAgICAgICAgLy8gcmVsYXRpdmUgdG8gdGhlIG5ldyBib3VuZGluZyBib3hcbiAgICAgICAgICAgICAgICB0ZXh0U2hpZnQgPSBhbm5TaXplICogc2hpZnRGcmFjdGlvbihhdXRvQWxpZ25GcmFjdGlvbiwgYW5jaG9yKTtcbiAgICAgICAgICAgICAgICB0ZXh0UGFkU2hpZnQgPSB0ZXh0U2hpZnQ7XG4gICAgICAgICAgICAgICAgcG9zUHgudGV4dCA9IGJhc2VQeCArIHRleHRTaGlmdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcG9zUHgudGV4dCArPSBvdmVyYWxsU2hpZnQ7XG4gICAgICAgICAgICB0ZXh0U2hpZnQgKz0gb3ZlcmFsbFNoaWZ0O1xuICAgICAgICAgICAgdGV4dFBhZFNoaWZ0ICs9IG92ZXJhbGxTaGlmdDtcblxuICAgICAgICAgICAgLy8gcGFkcGx1cy9taW51cyBhcmUgdXNlZCBieSBhdXRvcmFuZ2VcbiAgICAgICAgICAgIG9wdGlvbnNbJ18nICsgYXhMZXR0ZXIgKyAncGFkcGx1cyddID0gKGFublNpemUgLyAyKSArIHRleHRQYWRTaGlmdDtcbiAgICAgICAgICAgIG9wdGlvbnNbJ18nICsgYXhMZXR0ZXIgKyAncGFkbWludXMnXSA9IChhbm5TaXplIC8gMikgLSB0ZXh0UGFkU2hpZnQ7XG5cbiAgICAgICAgICAgIC8vIHNpemUvc2hpZnQgYXJlIHVzZWQgZHVyaW5nIGRyYWdnaW5nXG4gICAgICAgICAgICBvcHRpb25zWydfJyArIGF4TGV0dGVyICsgJ3NpemUnXSA9IGFublNpemU7XG4gICAgICAgICAgICBvcHRpb25zWydfJyArIGF4TGV0dGVyICsgJ3NoaWZ0J10gPSB0ZXh0U2hpZnQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXZSBoYXZlIGV2ZXJ5dGhpbmcgd2UgbmVlZCBmb3IgY2FsY0F1dG9yYW5nZSBhdCB0aGlzIHBvaW50LFxuICAgICAgICAvLyB3ZSBjYW4gc2FmZWx5IGV4aXQgLSB1bmxlc3Mgd2UncmUgY3VycmVudGx5IGRyYWdnaW5nIHRoZSBwbG90XG4gICAgICAgIGlmKCFnZC5fZHJhZ2dpbmcgJiYgYW5ub3RhdGlvbklzT2Zmc2NyZWVuKSB7XG4gICAgICAgICAgICBhbm5UZXh0R3JvdXBJbm5lci5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB4U2hpZnQgPSAwO1xuICAgICAgICB2YXIgeVNoaWZ0ID0gMDtcblxuICAgICAgICBpZihvcHRpb25zLmFsaWduICE9PSAnbGVmdCcpIHtcbiAgICAgICAgICAgIHhTaGlmdCA9IChhbm5XaWR0aCAtIHRleHRXaWR0aCkgKiAob3B0aW9ucy5hbGlnbiA9PT0gJ2NlbnRlcicgPyAwLjUgOiAxKTtcbiAgICAgICAgfVxuICAgICAgICBpZihvcHRpb25zLnZhbGlnbiAhPT0gJ3RvcCcpIHtcbiAgICAgICAgICAgIHlTaGlmdCA9IChhbm5IZWlnaHQgLSB0ZXh0SGVpZ2h0KSAqIChvcHRpb25zLnZhbGlnbiA9PT0gJ21pZGRsZScgPyAwLjUgOiAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGhhc01hdGhqYXgpIHtcbiAgICAgICAgICAgIG1hdGhqYXhHcm91cC5zZWxlY3QoJ3N2ZycpLmF0dHIoe1xuICAgICAgICAgICAgICAgIHg6IGJvcmRlcmZ1bGwgKyB4U2hpZnQgLSAxLFxuICAgICAgICAgICAgICAgIHk6IGJvcmRlcmZ1bGwgKyB5U2hpZnRcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIGlzU2l6ZUNvbnN0cmFpbmVkID8gYW5uQ2xpcElEIDogbnVsbCwgZ2QpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHRleHR5ID0gYm9yZGVyZnVsbCArIHlTaGlmdCAtIGFubnRleHRCQi50b3A7XG4gICAgICAgICAgICB2YXIgdGV4dHggPSBib3JkZXJmdWxsICsgeFNoaWZ0IC0gYW5udGV4dEJCLmxlZnQ7XG5cbiAgICAgICAgICAgIGFublRleHQuY2FsbChzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0LCB0ZXh0eCwgdGV4dHkpXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRDbGlwVXJsLCBpc1NpemVDb25zdHJhaW5lZCA/IGFubkNsaXBJRCA6IG51bGwsIGdkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFublRleHRDbGlwLnNlbGVjdCgncmVjdCcpLmNhbGwoRHJhd2luZy5zZXRSZWN0LCBib3JkZXJmdWxsLCBib3JkZXJmdWxsLFxuICAgICAgICAgICAgYW5uV2lkdGgsIGFubkhlaWdodCk7XG5cbiAgICAgICAgYW5uVGV4dEJHLmNhbGwoRHJhd2luZy5zZXRSZWN0LCBib3JkZXJ3aWR0aCAvIDIsIGJvcmRlcndpZHRoIC8gMixcbiAgICAgICAgICAgIG91dGVyV2lkdGggLSBib3JkZXJ3aWR0aCwgb3V0ZXJIZWlnaHQgLSBib3JkZXJ3aWR0aCk7XG5cbiAgICAgICAgYW5uVGV4dEdyb3VwSW5uZXIuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSxcbiAgICAgICAgICAgIE1hdGgucm91bmQoYW5uUG9zUHgueC50ZXh0IC0gb3V0ZXJXaWR0aCAvIDIpLFxuICAgICAgICAgICAgTWF0aC5yb3VuZChhbm5Qb3NQeC55LnRleHQgLSBvdXRlckhlaWdodCAvIDIpKTtcblxuICAgICAgICAvKlxuICAgICAgICAgKiByb3RhdGUgdGV4dCBhbmQgYmFja2dyb3VuZFxuICAgICAgICAgKiB3ZSBhbHJlYWR5IGNhbGN1bGF0ZWQgdGhlIHRleHQgY2VudGVyIHBvc2l0aW9uICphcyByb3RhdGVkKlxuICAgICAgICAgKiBiZWNhdXNlIHdlIG5lZWRlZCB0aGF0IGZvciBhdXRvcmFuZ2luZyBhbnl3YXksIHNvIG5vdyB3aGV0aGVyXG4gICAgICAgICAqIHdlIGhhdmUgYW4gYXJyb3cgb3Igbm90LCB3ZSByb3RhdGUgYWJvdXQgdGhlIHRleHQgY2VudGVyLlxuICAgICAgICAgKi9cbiAgICAgICAgYW5uVGV4dEdyb3VwLmF0dHIoe3RyYW5zZm9ybTogJ3JvdGF0ZSgnICsgdGV4dGFuZ2xlICsgJywnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5Qb3NQeC54LnRleHQgKyAnLCcgKyBhbm5Qb3NQeC55LnRleHQgKyAnKSd9KTtcblxuICAgICAgICAvKlxuICAgICAgICAgKiBhZGQgdGhlIGFycm93XG4gICAgICAgICAqIHVzZXMgb3B0aW9uc1thcnJvd3dpZHRoLGFycm93Y29sb3IsYXJyb3doZWFkXSBmb3Igc3R5bGluZ1xuICAgICAgICAgKiBkeCBhbmQgZHkgYXJlIG5vcm1hbGx5IHplcm8sIGJ1dCB3aGVuIHlvdSBhcmUgZHJhZ2dpbmcgdGhlIHRleHRib3hcbiAgICAgICAgICogd2hpbGUgdGhlIGhlYWQgc3RheXMgcHV0LCBkeCBhbmQgZHkgYXJlIHRoZSBwaXhlbCBvZmZzZXRzXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgZHJhd0Fycm93ID0gZnVuY3Rpb24oZHgsIGR5KSB7XG4gICAgICAgICAgICBhbm5Hcm91cFxuICAgICAgICAgICAgICAgIC5zZWxlY3RBbGwoJy5hbm5vdGF0aW9uLWFycm93LWcnKVxuICAgICAgICAgICAgICAgIC5yZW1vdmUoKTtcblxuICAgICAgICAgICAgdmFyIGhlYWRYID0gYW5uUG9zUHgueC5oZWFkO1xuICAgICAgICAgICAgdmFyIGhlYWRZID0gYW5uUG9zUHgueS5oZWFkO1xuICAgICAgICAgICAgdmFyIHRhaWxYID0gYW5uUG9zUHgueC50YWlsICsgZHg7XG4gICAgICAgICAgICB2YXIgdGFpbFkgPSBhbm5Qb3NQeC55LnRhaWwgKyBkeTtcbiAgICAgICAgICAgIHZhciB0ZXh0WCA9IGFublBvc1B4LngudGV4dCArIGR4O1xuICAgICAgICAgICAgdmFyIHRleHRZID0gYW5uUG9zUHgueS50ZXh0ICsgZHk7XG5cbiAgICAgICAgICAgIC8vIGZpbmQgdGhlIGVkZ2Ugb2YgdGhlIHRleHQgYm94LCB3aGVyZSB3ZSdsbCBzdGFydCB0aGUgYXJyb3c6XG4gICAgICAgICAgICAvLyBjcmVhdGUgdHJhbnNmb3JtIG1hdHJpeCB0byByb3RhdGUgdGhlIHRleHQgYm94IGNvcm5lcnNcbiAgICAgICAgICAgIHZhciB0cmFuc2Zvcm0gPSBMaWIucm90YXRpb25YWU1hdHJpeCh0ZXh0YW5nbGUsIHRleHRYLCB0ZXh0WSk7XG4gICAgICAgICAgICB2YXIgYXBwbHlUcmFuc2Zvcm0gPSBMaWIuYXBwbHkyRFRyYW5zZm9ybSh0cmFuc2Zvcm0pO1xuICAgICAgICAgICAgdmFyIGFwcGx5VHJhbnNmb3JtMiA9IExpYi5hcHBseTJEVHJhbnNmb3JtMih0cmFuc2Zvcm0pO1xuXG4gICAgICAgICAgICAvLyBjYWxjdWxhdGUgYW5kIHRyYW5zZm9ybSBib3VuZGluZyBib3hcbiAgICAgICAgICAgIHZhciB3aWR0aCA9ICthbm5UZXh0QkcuYXR0cignd2lkdGgnKTtcbiAgICAgICAgICAgIHZhciBoZWlnaHQgPSArYW5uVGV4dEJHLmF0dHIoJ2hlaWdodCcpO1xuICAgICAgICAgICAgdmFyIHhMZWZ0ID0gdGV4dFggLSAwLjUgKiB3aWR0aDtcbiAgICAgICAgICAgIHZhciB4UmlnaHQgPSB4TGVmdCArIHdpZHRoO1xuICAgICAgICAgICAgdmFyIHlUb3AgPSB0ZXh0WSAtIDAuNSAqIGhlaWdodDtcbiAgICAgICAgICAgIHZhciB5Qm90dG9tID0geVRvcCArIGhlaWdodDtcbiAgICAgICAgICAgIHZhciBlZGdlcyA9IFtcbiAgICAgICAgICAgICAgICBbeExlZnQsIHlUb3AsIHhMZWZ0LCB5Qm90dG9tXSxcbiAgICAgICAgICAgICAgICBbeExlZnQsIHlCb3R0b20sIHhSaWdodCwgeUJvdHRvbV0sXG4gICAgICAgICAgICAgICAgW3hSaWdodCwgeUJvdHRvbSwgeFJpZ2h0LCB5VG9wXSxcbiAgICAgICAgICAgICAgICBbeFJpZ2h0LCB5VG9wLCB4TGVmdCwgeVRvcF1cbiAgICAgICAgICAgIF0ubWFwKGFwcGx5VHJhbnNmb3JtMik7XG5cbiAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgbGluZSBpZiBpdCBlbmRzIGluc2lkZSB0aGUgYm94LiAgVXNlIHJheVxuICAgICAgICAgICAgLy8gY2FzdGluZyBmb3Igcm90YXRlZCBib3hlczogc2VlIHdoaWNoIGVkZ2VzIGludGVyc2VjdCBhXG4gICAgICAgICAgICAvLyBsaW5lIGZyb20gdGhlIGFycm93aGVhZCB0byBmYXIgYXdheSBhbmQgcmVkdWNlIHdpdGggeG9yXG4gICAgICAgICAgICAvLyB0byBnZXQgdGhlIHBhcml0eSBvZiB0aGUgbnVtYmVyIG9mIGludGVyc2VjdGlvbnMuXG4gICAgICAgICAgICBpZihlZGdlcy5yZWR1Y2UoZnVuY3Rpb24oYSwgeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhIF5cbiAgICAgICAgICAgICAgICAgICAgISFMaWIuc2VnbWVudHNJbnRlcnNlY3QoaGVhZFgsIGhlYWRZLCBoZWFkWCArIDFlNiwgaGVhZFkgKyAxZTYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeFswXSwgeFsxXSwgeFsyXSwgeFszXSk7XG4gICAgICAgICAgICB9LCBmYWxzZSkpIHtcbiAgICAgICAgICAgICAgICAvLyBubyBsaW5lIG9yIGFycm93IC0gc28gcXVpdCBkcmF3QXJyb3cgbm93XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBlZGdlcy5mb3JFYWNoKGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgICAgICAgICB2YXIgcCA9IExpYi5zZWdtZW50c0ludGVyc2VjdCh0YWlsWCwgdGFpbFksIGhlYWRYLCBoZWFkWSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4WzBdLCB4WzFdLCB4WzJdLCB4WzNdKTtcbiAgICAgICAgICAgICAgICBpZihwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhaWxYID0gcC54O1xuICAgICAgICAgICAgICAgICAgICB0YWlsWSA9IHAueTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIHN0cm9rZXdpZHRoID0gb3B0aW9ucy5hcnJvd3dpZHRoO1xuICAgICAgICAgICAgdmFyIGFycm93Q29sb3IgPSBvcHRpb25zLmFycm93Y29sb3I7XG4gICAgICAgICAgICB2YXIgYXJyb3dTaWRlID0gb3B0aW9ucy5hcnJvd3NpZGU7XG5cbiAgICAgICAgICAgIHZhciBhcnJvd0dyb3VwID0gYW5uR3JvdXAuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAuc3R5bGUoe29wYWNpdHk6IENvbG9yLm9wYWNpdHkoYXJyb3dDb2xvcil9KVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdhbm5vdGF0aW9uLWFycm93LWcnLCB0cnVlKTtcblxuICAgICAgICAgICAgdmFyIGFycm93ID0gYXJyb3dHcm91cC5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgICAgIC5hdHRyKCdkJywgJ00nICsgdGFpbFggKyAnLCcgKyB0YWlsWSArICdMJyArIGhlYWRYICsgJywnICsgaGVhZFkpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBzdHJva2V3aWR0aCArICdweCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBDb2xvci5yZ2IoYXJyb3dDb2xvcikpO1xuXG4gICAgICAgICAgICBkcmF3QXJyb3dIZWFkKGFycm93LCBhcnJvd1NpZGUsIG9wdGlvbnMpO1xuXG4gICAgICAgICAgICAvLyB0aGUgYXJyb3cgZHJhZ2dlciBpcyBhIHNtYWxsIHNxdWFyZSByaWdodCBhdCB0aGUgaGVhZCwgdGhlbiBhIGxpbmUgdG8gdGhlIHRhaWwsXG4gICAgICAgICAgICAvLyBhbGwgZXhwYW5kZWQgYnkgYSBzdHJva2Ugd2lkdGggb2YgNnB4IHBsdXMgdGhlIGFycm93IGxpbmUgd2lkdGhcbiAgICAgICAgICAgIGlmKGVkaXRzLmFubm90YXRpb25Qb3NpdGlvbiAmJiBhcnJvdy5ub2RlKCkucGFyZW50Tm9kZSAmJiAhc3VicGxvdElkKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFycm93RHJhZ0hlYWRYID0gaGVhZFg7XG4gICAgICAgICAgICAgICAgdmFyIGFycm93RHJhZ0hlYWRZID0gaGVhZFk7XG4gICAgICAgICAgICAgICAgaWYob3B0aW9ucy5zdGFuZG9mZikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYXJyb3dMZW5ndGggPSBNYXRoLnNxcnQoTWF0aC5wb3coaGVhZFggLSB0YWlsWCwgMikgKyBNYXRoLnBvdyhoZWFkWSAtIHRhaWxZLCAyKSk7XG4gICAgICAgICAgICAgICAgICAgIGFycm93RHJhZ0hlYWRYICs9IG9wdGlvbnMuc3RhbmRvZmYgKiAodGFpbFggLSBoZWFkWCkgLyBhcnJvd0xlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgYXJyb3dEcmFnSGVhZFkgKz0gb3B0aW9ucy5zdGFuZG9mZiAqICh0YWlsWSAtIGhlYWRZKSAvIGFycm93TGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgYXJyb3dEcmFnID0gYXJyb3dHcm91cC5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgICAgICAgICAuY2xhc3NlZCgnYW5ub3RhdGlvbi1hcnJvdycsIHRydWUpXG4gICAgICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdhbm5kcmFnJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ2N1cnNvci1tb3ZlJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZDogJ00zLDNILTNWLTNIM1pNMCwwTCcgKyAodGFpbFggLSBhcnJvd0RyYWdIZWFkWCkgKyAnLCcgKyAodGFpbFkgLSBhcnJvd0RyYWdIZWFkWSksXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIGFycm93RHJhZ0hlYWRYICsgJywnICsgYXJyb3dEcmFnSGVhZFkgKyAnKSdcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCAoc3Ryb2tld2lkdGggKyA2KSArICdweCcpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgJ3JnYmEoMCwwLDAsMCknKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCAncmdiYSgwLDAsMCwwKScpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFubngwLCBhbm55MDtcblxuICAgICAgICAgICAgICAgIC8vIGRyYWdnZXIgZm9yIHRoZSBhcnJvdyAmIGhlYWQ6IHRyYW5zbGF0ZXMgdGhlIHdob2xlIHRoaW5nXG4gICAgICAgICAgICAgICAgLy8gKGhlYWQvdGFpbC90ZXh0KSBhbGwgdG9nZXRoZXJcbiAgICAgICAgICAgICAgICBkcmFnRWxlbWVudC5pbml0KHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogYXJyb3dEcmFnLm5vZGUoKSxcbiAgICAgICAgICAgICAgICAgICAgZ2Q6IGdkLFxuICAgICAgICAgICAgICAgICAgICBwcmVwRm46IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IERyYXdpbmcuZ2V0VHJhbnNsYXRlKGFublRleHRHcm91cElubmVyKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgYW5ueDAgPSBwb3MueDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFubnkwID0gcG9zLnk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih4YSAmJiB4YS5hdXRvcmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RpZnlCYXNlKHhhLl9uYW1lICsgJy5hdXRvcmFuZ2UnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHlhICYmIHlhLmF1dG9yYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmeUJhc2UoeWEuX25hbWUgKyAnLmF1dG9yYW5nZScsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBtb3ZlRm46IGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFubnh5MCA9IGFwcGx5VHJhbnNmb3JtKGFubngwLCBhbm55MCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgeGNlbnRlciA9IGFubnh5MFswXSArIGR4O1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHljZW50ZXIgPSBhbm54eTBbMV0gKyBkeTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFublRleHRHcm91cElubmVyLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsIHhjZW50ZXIsIHljZW50ZXIpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd4JywgeGEgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhhLnAycih4YS5yMnAob3B0aW9ucy54KSArIGR4KSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG9wdGlvbnMueCArIChkeCAvIGdzLncpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd5JywgeWEgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlhLnAycih5YS5yMnAob3B0aW9ucy55KSArIGR5KSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG9wdGlvbnMueSAtIChkeSAvIGdzLmgpKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKG9wdGlvbnMuYXhyZWYgPT09IG9wdGlvbnMueHJlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ2F4JywgeGEucDJyKHhhLnIycChvcHRpb25zLmF4KSArIGR4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKG9wdGlvbnMuYXlyZWYgPT09IG9wdGlvbnMueXJlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ2F5JywgeWEucDJyKHlhLnIycChvcHRpb25zLmF5KSArIGR5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGFycm93R3JvdXAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgZHggKyAnLCcgKyBkeSArICcpJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbm5UZXh0R3JvdXAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAncm90YXRlKCcgKyB0ZXh0YW5nbGUgKyAnLCcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4Y2VudGVyICsgJywnICsgeWNlbnRlciArICcpJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGRvbmVGbjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVsYXlvdXQnLCBnZCwgZ2V0VXBkYXRlT2JqKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5vdGVzQm94ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmpzLW5vdGVzLWJveC1wYW5lbCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYobm90ZXNCb3gpIG5vdGVzQm94LnJlZHJhdyhub3Rlc0JveC5zZWxlY3RlZE9iaik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBpZihvcHRpb25zLnNob3dhcnJvdykgZHJhd0Fycm93KDAsIDApO1xuXG4gICAgICAgIC8vIHVzZXIgZHJhZ2dpbmcgdGhlIGFubm90YXRpb24gKHRleHQsIG5vdCBhcnJvdylcbiAgICAgICAgaWYoZWRpdFRleHRQb3NpdGlvbikge1xuICAgICAgICAgICAgdmFyIGJhc2VUZXh0VHJhbnNmb3JtO1xuXG4gICAgICAgICAgICAvLyBkcmFnZ2VyIGZvciB0aGUgdGV4dGJveDogaWYgdGhlcmUncyBhbiBhcnJvdywganVzdCBkcmFnIHRoZVxuICAgICAgICAgICAgLy8gdGV4dGJveCBhbmQgdGFpbCwgbGVhdmUgdGhlIGhlYWQgdW50b3VjaGVkXG4gICAgICAgICAgICBkcmFnRWxlbWVudC5pbml0KHtcbiAgICAgICAgICAgICAgICBlbGVtZW50OiBhbm5UZXh0R3JvdXBJbm5lci5ub2RlKCksXG4gICAgICAgICAgICAgICAgZ2Q6IGdkLFxuICAgICAgICAgICAgICAgIHByZXBGbjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhc2VUZXh0VHJhbnNmb3JtID0gYW5uVGV4dEdyb3VwLmF0dHIoJ3RyYW5zZm9ybScpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgbW92ZUZuOiBmdW5jdGlvbihkeCwgZHkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNzciA9ICdwb2ludGVyJztcbiAgICAgICAgICAgICAgICAgICAgaWYob3B0aW9ucy5zaG93YXJyb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKG9wdGlvbnMuYXhyZWYgPT09IG9wdGlvbnMueHJlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ2F4JywgeGEucDJyKHhhLnIycChvcHRpb25zLmF4KSArIGR4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ2F4Jywgb3B0aW9ucy5heCArIGR4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYob3B0aW9ucy5heXJlZiA9PT0gb3B0aW9ucy55cmVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgnYXknLCB5YS5wMnIoeWEucjJwKG9wdGlvbnMuYXkpICsgZHkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgnYXknLCBvcHRpb25zLmF5ICsgZHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBkcmF3QXJyb3coZHgsIGR5KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKCFzdWJwbG90SWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB4VXBkYXRlLCB5VXBkYXRlO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoeGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4VXBkYXRlID0geGEucDJyKHhhLnIycChvcHRpb25zLngpICsgZHgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgd2lkdGhGcmFjdGlvbiA9IG9wdGlvbnMuX3hzaXplIC8gZ3MudztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgeExlZnQgPSBvcHRpb25zLnggKyAob3B0aW9ucy5feHNoaWZ0IC0gb3B0aW9ucy54c2hpZnQpIC8gZ3MudyAtIHdpZHRoRnJhY3Rpb24gLyAyO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeFVwZGF0ZSA9IGRyYWdFbGVtZW50LmFsaWduKHhMZWZ0ICsgZHggLyBncy53LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aEZyYWN0aW9uLCAwLCAxLCBvcHRpb25zLnhhbmNob3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZih5YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlVcGRhdGUgPSB5YS5wMnIoeWEucjJwKG9wdGlvbnMueSkgKyBkeSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBoZWlnaHRGcmFjdGlvbiA9IG9wdGlvbnMuX3lzaXplIC8gZ3MuaDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgeUJvdHRvbSA9IG9wdGlvbnMueSAtIChvcHRpb25zLl95c2hpZnQgKyBvcHRpb25zLnlzaGlmdCkgLyBncy5oIC0gaGVpZ2h0RnJhY3Rpb24gLyAyO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeVVwZGF0ZSA9IGRyYWdFbGVtZW50LmFsaWduKHlCb3R0b20gLSBkeSAvIGdzLmgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodEZyYWN0aW9uLCAwLCAxLCBvcHRpb25zLnlhbmNob3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneCcsIHhVcGRhdGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneScsIHlVcGRhdGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIXhhIHx8ICF5YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNzciA9IGRyYWdFbGVtZW50LmdldEN1cnNvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeGEgPyAwLjUgOiB4VXBkYXRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5YSA/IDAuNSA6IHlVcGRhdGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMueGFuY2hvciwgb3B0aW9ucy55YW5jaG9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHJldHVybjtcblxuICAgICAgICAgICAgICAgICAgICBhbm5UZXh0R3JvdXAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIGR4ICsgJywnICsgZHkgKyAnKScgKyBiYXNlVGV4dFRyYW5zZm9ybVxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBzZXRDdXJzb3IoYW5uVGV4dEdyb3VwSW5uZXIsIGNzcik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjbGlja0ZuOiBmdW5jdGlvbihfLCBpbml0aWFsRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYob3B0aW9ucy5jYXB0dXJlZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfY2xpY2thbm5vdGF0aW9uJywgbWFrZUV2ZW50RGF0YShpbml0aWFsRXZlbnQpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZG9uZUZuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgc2V0Q3Vyc29yKGFublRleHRHcm91cElubmVyKTtcbiAgICAgICAgICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIGdldFVwZGF0ZU9iaigpKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vdGVzQm94ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmpzLW5vdGVzLWJveC1wYW5lbCcpO1xuICAgICAgICAgICAgICAgICAgICBpZihub3Rlc0JveCkgbm90ZXNCb3gucmVkcmF3KG5vdGVzQm94LnNlbGVjdGVkT2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGVkaXRzLmFubm90YXRpb25UZXh0KSB7XG4gICAgICAgIGFublRleHQuY2FsbChzdmdUZXh0VXRpbHMubWFrZUVkaXRhYmxlLCB7ZGVsZWdhdGU6IGFublRleHRHcm91cElubmVyLCBnZDogZ2R9KVxuICAgICAgICAgICAgLmNhbGwodGV4dExheW91dClcbiAgICAgICAgICAgIC5vbignZWRpdCcsIGZ1bmN0aW9uKF90ZXh0KSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucy50ZXh0ID0gX3RleHQ7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNhbGwodGV4dExheW91dCk7XG5cbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd0ZXh0JywgX3RleHQpO1xuXG4gICAgICAgICAgICAgICAgaWYoeGEgJiYgeGEuYXV0b3JhbmdlKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZGlmeUJhc2UoeGEuX25hbWUgKyAnLmF1dG9yYW5nZScsIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZih5YSAmJiB5YS5hdXRvcmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kaWZ5QmFzZSh5YS5fbmFtZSArICcuYXV0b3JhbmdlJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIGdldFVwZGF0ZU9iaigpKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH0gZWxzZSBhbm5UZXh0LmNhbGwodGV4dExheW91dCk7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL3NldGN1cnNvclwiOjczOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uLy4uL3Bsb3RzL3Bsb3RzXCI6ODI4LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9jb2xvclwiOjU5MyxcIi4uL2RyYWdlbGVtZW50XCI6NjExLFwiLi4vZHJhd2luZ1wiOjYxNCxcIi4uL2Z4XCI6NjMyLFwiLi9kcmF3X2Fycm93X2hlYWRcIjo1ODMsXCJkM1wiOjE2M31dLDU4MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIENvbG9yID0gX2RlcmVxXygnLi4vY29sb3InKTtcblxudmFyIEFSUk9XUEFUSFMgPSBfZGVyZXFfKCcuL2Fycm93X3BhdGhzJyk7XG5cbi8qKlxuICogQWRkIGFycm93aGVhZChzKSB0byBhIHBhdGggb3IgbGluZSBlbGVtZW50XG4gKlxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IGVsMzogYSBkMy1zZWxlY3RlZCBsaW5lIG9yIHBhdGggZWxlbWVudFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBlbmRzOiAnbm9uZScsICdzdGFydCcsICdlbmQnLCBvciAnc3RhcnQrZW5kJyBmb3Igd2hpY2ggZW5kcyBnZXQgYXJyb3doZWFkc1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zOiBzdHlsZSBpbmZvcm1hdGlvbi4gTXVzdCBoYXZlIGFsbCB0aGUgZm9sbG93aW5nOlxuICogQHBhcmFtIHtudW1iZXJ9IG9wdGlvbnMuYXJyb3doZWFkOiBlbmQgaGVhZCBzdHlsZSAtIHNlZSAuL2Fycm93X3BhdGhzXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5zdGFydGFycm93aGVhZDogc3RhcnQgaGVhZCBzdHlsZSAtIHNlZSAuL2Fycm93X3BhdGhzXG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5hcnJvd3NpemU6IHJlbGF0aXZlIHNpemUgb2YgdGhlIGVuZCBoZWFkIHZzIGxpbmUgd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLnN0YXJ0YXJyb3dzaXplOiByZWxhdGl2ZSBzaXplIG9mIHRoZSBzdGFydCBoZWFkIHZzIGxpbmUgd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLnN0YW5kb2ZmOiBkaXN0YW5jZSBpbiBweCB0byBtb3ZlIHRoZSBlbmQgYXJyb3cgcG9pbnQgZnJvbSBpdHMgdGFyZ2V0XG4gKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5zdGFydHN0YW5kb2ZmOiBkaXN0YW5jZSBpbiBweCB0byBtb3ZlIHRoZSBzdGFydCBhcnJvdyBwb2ludCBmcm9tIGl0cyB0YXJnZXRcbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLmFycm93d2lkdGg6IHdpZHRoIG9mIHRoZSBhcnJvdyBsaW5lXG4gKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5hcnJvd2NvbG9yOiBjb2xvciBvZiB0aGUgYXJyb3cgbGluZSwgZm9yIHRoZSBoZWFkIHRvIG1hdGNoXG4gKiAgICAgTm90ZSB0aGF0IHRoZSBvcGFjaXR5IG9mIHRoaXMgY29sb3IgaXMgaWdub3JlZCwgYXMgaXQncyBhc3N1bWVkIHRoZSBjb250YWluZXJcbiAqICAgICBvZiBib3RoIHRoZSBsaW5lIGFuZCBoZWFkIGhhcyBvcGFjaXR5IGFwcGxpZWQgdG8gaXQgc28gdGhlcmUgaXNuJ3QgZ3JlYXRlciBvcGFjaXR5XG4gKiAgICAgd2hlcmUgdGhleSBvdmVybGFwLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRyYXdBcnJvd0hlYWQoZWwzLCBlbmRzLCBvcHRpb25zKSB7XG4gICAgdmFyIGVsID0gZWwzLm5vZGUoKTtcbiAgICB2YXIgaGVhZFN0eWxlID0gQVJST1dQQVRIU1tvcHRpb25zLmFycm93aGVhZCB8fCAwXTtcbiAgICB2YXIgc3RhcnRIZWFkU3R5bGUgPSBBUlJPV1BBVEhTW29wdGlvbnMuc3RhcnRhcnJvd2hlYWQgfHwgMF07XG4gICAgdmFyIHNjYWxlID0gKG9wdGlvbnMuYXJyb3d3aWR0aCB8fCAxKSAqIChvcHRpb25zLmFycm93c2l6ZSB8fCAxKTtcbiAgICB2YXIgc3RhcnRTY2FsZSA9IChvcHRpb25zLmFycm93d2lkdGggfHwgMSkgKiAob3B0aW9ucy5zdGFydGFycm93c2l6ZSB8fCAxKTtcbiAgICB2YXIgZG9TdGFydCA9IGVuZHMuaW5kZXhPZignc3RhcnQnKSA+PSAwO1xuICAgIHZhciBkb0VuZCA9IGVuZHMuaW5kZXhPZignZW5kJykgPj0gMDtcbiAgICB2YXIgYmFja09mZiA9IGhlYWRTdHlsZS5iYWNrb2ZmICogc2NhbGUgKyBvcHRpb25zLnN0YW5kb2ZmO1xuICAgIHZhciBzdGFydEJhY2tPZmYgPSBzdGFydEhlYWRTdHlsZS5iYWNrb2ZmICogc3RhcnRTY2FsZSArIG9wdGlvbnMuc3RhcnRzdGFuZG9mZjtcblxuICAgIHZhciBzdGFydCwgZW5kLCBzdGFydFJvdCwgZW5kUm90O1xuXG4gICAgaWYoZWwubm9kZU5hbWUgPT09ICdsaW5lJykge1xuICAgICAgICBzdGFydCA9IHt4OiArZWwzLmF0dHIoJ3gxJyksIHk6ICtlbDMuYXR0cigneTEnKX07XG4gICAgICAgIGVuZCA9IHt4OiArZWwzLmF0dHIoJ3gyJyksIHk6ICtlbDMuYXR0cigneTInKX07XG5cbiAgICAgICAgdmFyIGR4ID0gc3RhcnQueCAtIGVuZC54O1xuICAgICAgICB2YXIgZHkgPSBzdGFydC55IC0gZW5kLnk7XG5cbiAgICAgICAgc3RhcnRSb3QgPSBNYXRoLmF0YW4yKGR5LCBkeCk7XG4gICAgICAgIGVuZFJvdCA9IHN0YXJ0Um90ICsgTWF0aC5QSTtcbiAgICAgICAgaWYoYmFja09mZiAmJiBzdGFydEJhY2tPZmYpIHtcbiAgICAgICAgICAgIGlmKGJhY2tPZmYgKyBzdGFydEJhY2tPZmYgPiBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpKSB7XG4gICAgICAgICAgICAgICAgaGlkZUxpbmUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihiYWNrT2ZmKSB7XG4gICAgICAgICAgICBpZihiYWNrT2ZmICogYmFja09mZiA+IGR4ICogZHggKyBkeSAqIGR5KSB7XG4gICAgICAgICAgICAgICAgaGlkZUxpbmUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgYmFja09mZlggPSBiYWNrT2ZmICogTWF0aC5jb3Moc3RhcnRSb3QpO1xuICAgICAgICAgICAgdmFyIGJhY2tPZmZZID0gYmFja09mZiAqIE1hdGguc2luKHN0YXJ0Um90KTtcblxuICAgICAgICAgICAgZW5kLnggKz0gYmFja09mZlg7XG4gICAgICAgICAgICBlbmQueSArPSBiYWNrT2ZmWTtcbiAgICAgICAgICAgIGVsMy5hdHRyKHt4MjogZW5kLngsIHkyOiBlbmQueX0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoc3RhcnRCYWNrT2ZmKSB7XG4gICAgICAgICAgICBpZihzdGFydEJhY2tPZmYgKiBzdGFydEJhY2tPZmYgPiBkeCAqIGR4ICsgZHkgKiBkeSkge1xuICAgICAgICAgICAgICAgIGhpZGVMaW5lKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHN0YXJ0QmFja09mZlggPSBzdGFydEJhY2tPZmYgKiBNYXRoLmNvcyhzdGFydFJvdCk7XG4gICAgICAgICAgICB2YXIgc3RhcnRiYWNrT2ZmWSA9IHN0YXJ0QmFja09mZiAqIE1hdGguc2luKHN0YXJ0Um90KTtcblxuICAgICAgICAgICAgc3RhcnQueCAtPSBzdGFydEJhY2tPZmZYO1xuICAgICAgICAgICAgc3RhcnQueSAtPSBzdGFydGJhY2tPZmZZO1xuICAgICAgICAgICAgZWwzLmF0dHIoe3gxOiBzdGFydC54LCB5MTogc3RhcnQueX0pO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKGVsLm5vZGVOYW1lID09PSAncGF0aCcpIHtcbiAgICAgICAgdmFyIHBhdGhsZW4gPSBlbC5nZXRUb3RhbExlbmd0aCgpO1xuICAgICAgICAvLyB1c2luZyBkYXNoIHRvIGhpZGUgdGhlIGJhY2tPZmYgcmVnaW9uIG9mIHRoZSBwYXRoLlxuICAgICAgICAvLyBpZiB3ZSBldmVyIGFsbG93IGRhc2ggZm9yIHRoZSBhcnJvdyB3ZSdsbCBoYXZlIHRvXG4gICAgICAgIC8vIGRvIGJldHRlciB0aGFuIHRoaXMgaGFjay4uLiBtYXliZSBqdXN0IG1hbnVhbGx5XG4gICAgICAgIC8vIGNvbWJpbmUgdGhlIHR3b1xuICAgICAgICB2YXIgZGFzaEFycmF5ID0gJyc7XG5cbiAgICAgICAgaWYocGF0aGxlbiA8IGJhY2tPZmYgKyBzdGFydEJhY2tPZmYpIHtcbiAgICAgICAgICAgIGhpZGVMaW5lKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuXG4gICAgICAgIHZhciBzdGFydDAgPSBlbC5nZXRQb2ludEF0TGVuZ3RoKDApO1xuICAgICAgICB2YXIgZHN0YXJ0ID0gZWwuZ2V0UG9pbnRBdExlbmd0aCgwLjEpO1xuXG4gICAgICAgIHN0YXJ0Um90ID0gTWF0aC5hdGFuMihzdGFydDAueSAtIGRzdGFydC55LCBzdGFydDAueCAtIGRzdGFydC54KTtcbiAgICAgICAgc3RhcnQgPSBlbC5nZXRQb2ludEF0TGVuZ3RoKE1hdGgubWluKHN0YXJ0QmFja09mZiwgcGF0aGxlbikpO1xuXG4gICAgICAgIGRhc2hBcnJheSA9ICcwcHgsJyArIHN0YXJ0QmFja09mZiArICdweCwnO1xuXG4gICAgICAgIHZhciBlbmQwID0gZWwuZ2V0UG9pbnRBdExlbmd0aChwYXRobGVuKTtcbiAgICAgICAgdmFyIGRlbmQgPSBlbC5nZXRQb2ludEF0TGVuZ3RoKHBhdGhsZW4gLSAwLjEpO1xuXG4gICAgICAgIGVuZFJvdCA9IE1hdGguYXRhbjIoZW5kMC55IC0gZGVuZC55LCBlbmQwLnggLSBkZW5kLngpO1xuICAgICAgICBlbmQgPSBlbC5nZXRQb2ludEF0TGVuZ3RoKE1hdGgubWF4KDAsIHBhdGhsZW4gLSBiYWNrT2ZmKSk7XG5cbiAgICAgICAgdmFyIHNob3J0ZW5pbmcgPSBkYXNoQXJyYXkgPyBzdGFydEJhY2tPZmYgKyBiYWNrT2ZmIDogYmFja09mZjtcbiAgICAgICAgZGFzaEFycmF5ICs9IChwYXRobGVuIC0gc2hvcnRlbmluZykgKyAncHgsJyArIHBhdGhsZW4gKyAncHgnO1xuXG4gICAgICAgIGVsMy5zdHlsZSgnc3Ryb2tlLWRhc2hhcnJheScsIGRhc2hBcnJheSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGlkZUxpbmUoKSB7IGVsMy5zdHlsZSgnc3Ryb2tlLWRhc2hhcnJheScsICcwcHgsMTAwcHgnKTsgfVxuXG4gICAgZnVuY3Rpb24gZHJhd2hlYWQoYXJyb3dIZWFkU3R5bGUsIHAsIHJvdCwgYXJyb3dTY2FsZSkge1xuICAgICAgICBpZighYXJyb3dIZWFkU3R5bGUucGF0aCkgcmV0dXJuO1xuICAgICAgICBpZihhcnJvd0hlYWRTdHlsZS5ub1JvdGF0ZSkgcm90ID0gMDtcblxuICAgICAgICBkMy5zZWxlY3QoZWwucGFyZW50Tm9kZSkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgICAnY2xhc3MnOiBlbDMuYXR0cignY2xhc3MnKSxcbiAgICAgICAgICAgICAgICBkOiBhcnJvd0hlYWRTdHlsZS5wYXRoLFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTpcbiAgICAgICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgcC54ICsgJywnICsgcC55ICsgJyknICtcbiAgICAgICAgICAgICAgICAgICAgKHJvdCA/ICdyb3RhdGUoJyArIChyb3QgKiAxODAgLyBNYXRoLlBJKSArICcpJyA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAgICdzY2FsZSgnICsgYXJyb3dTY2FsZSArICcpJ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgZmlsbDogQ29sb3IucmdiKG9wdGlvbnMuYXJyb3djb2xvciksXG4gICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IDBcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKGRvU3RhcnQpIGRyYXdoZWFkKHN0YXJ0SGVhZFN0eWxlLCBzdGFydCwgc3RhcnRSb3QsIHN0YXJ0U2NhbGUpO1xuICAgIGlmKGRvRW5kKSBkcmF3aGVhZChoZWFkU3R5bGUsIGVuZCwgZW5kUm90LCBzY2FsZSk7XG59O1xuXG59LHtcIi4uL2NvbG9yXCI6NTkzLFwiLi9hcnJvd19wYXRoc1wiOjU3NSxcImQzXCI6MTYzfV0sNTg0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZHJhd01vZHVsZSA9IF9kZXJlcV8oJy4vZHJhdycpO1xudmFyIGNsaWNrTW9kdWxlID0gX2RlcmVxXygnLi9jbGljaycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAnY29tcG9uZW50JyxcbiAgICBuYW1lOiAnYW5ub3RhdGlvbnMnLFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBpbmNsdWRlQmFzZVBsb3Q6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9pbmNsdWRlX2NvbXBvbmVudHMnKSgnYW5ub3RhdGlvbnMnKSxcblxuICAgIGNhbGNBdXRvcmFuZ2U6IF9kZXJlcV8oJy4vY2FsY19hdXRvcmFuZ2UnKSxcbiAgICBkcmF3OiBkcmF3TW9kdWxlLmRyYXcsXG4gICAgZHJhd09uZTogZHJhd01vZHVsZS5kcmF3T25lLFxuICAgIGRyYXdSYXc6IGRyYXdNb2R1bGUuZHJhd1JhdyxcblxuICAgIGhhc0NsaWNrVG9TaG93OiBjbGlja01vZHVsZS5oYXNDbGlja1RvU2hvdyxcbiAgICBvbkNsaWNrOiBjbGlja01vZHVsZS5vbkNsaWNrLFxuXG4gICAgY29udmVydENvb3JkczogX2RlcmVxXygnLi9jb252ZXJ0X2Nvb3JkcycpXG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9pbmNsdWRlX2NvbXBvbmVudHNcIjo3NzcsXCIuL2F0dHJpYnV0ZXNcIjo1NzYsXCIuL2NhbGNfYXV0b3JhbmdlXCI6NTc3LFwiLi9jbGlja1wiOjU3OCxcIi4vY29udmVydF9jb29yZHNcIjo1ODAsXCIuL2RlZmF1bHRzXCI6NTgxLFwiLi9kcmF3XCI6NTgyfV0sNTg1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYW5uQXR0cyA9IF9kZXJlcV8oJy4uL2Fubm90YXRpb25zL2F0dHJpYnV0ZXMnKTtcbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcbnZhciB0ZW1wbGF0ZWRBcnJheSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKS50ZW1wbGF0ZWRBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh0ZW1wbGF0ZWRBcnJheSgnYW5ub3RhdGlvbicsIHtcbiAgICB2aXNpYmxlOiBhbm5BdHRzLnZpc2libGUsXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgeToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgejoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGF5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHhhbmNob3I6IGFubkF0dHMueGFuY2hvcixcbiAgICB4c2hpZnQ6IGFubkF0dHMueHNoaWZ0LFxuICAgIHlhbmNob3I6IGFubkF0dHMueWFuY2hvcixcbiAgICB5c2hpZnQ6IGFubkF0dHMueXNoaWZ0LFxuXG4gICAgdGV4dDogYW5uQXR0cy50ZXh0LFxuICAgIHRleHRhbmdsZTogYW5uQXR0cy50ZXh0YW5nbGUsXG4gICAgZm9udDogYW5uQXR0cy5mb250LFxuICAgIHdpZHRoOiBhbm5BdHRzLndpZHRoLFxuICAgIGhlaWdodDogYW5uQXR0cy5oZWlnaHQsXG4gICAgb3BhY2l0eTogYW5uQXR0cy5vcGFjaXR5LFxuICAgIGFsaWduOiBhbm5BdHRzLmFsaWduLFxuICAgIHZhbGlnbjogYW5uQXR0cy52YWxpZ24sXG4gICAgYmdjb2xvcjogYW5uQXR0cy5iZ2NvbG9yLFxuICAgIGJvcmRlcmNvbG9yOiBhbm5BdHRzLmJvcmRlcmNvbG9yLFxuICAgIGJvcmRlcnBhZDogYW5uQXR0cy5ib3JkZXJwYWQsXG4gICAgYm9yZGVyd2lkdGg6IGFubkF0dHMuYm9yZGVyd2lkdGgsXG4gICAgc2hvd2Fycm93OiBhbm5BdHRzLnNob3dhcnJvdyxcbiAgICBhcnJvd2NvbG9yOiBhbm5BdHRzLmFycm93Y29sb3IsXG4gICAgYXJyb3doZWFkOiBhbm5BdHRzLmFycm93aGVhZCxcbiAgICBzdGFydGFycm93aGVhZDogYW5uQXR0cy5zdGFydGFycm93aGVhZCxcbiAgICBhcnJvd3NpZGU6IGFubkF0dHMuYXJyb3dzaWRlLFxuICAgIGFycm93c2l6ZTogYW5uQXR0cy5hcnJvd3NpemUsXG4gICAgc3RhcnRhcnJvd3NpemU6IGFubkF0dHMuc3RhcnRhcnJvd3NpemUsXG4gICAgYXJyb3d3aWR0aDogYW5uQXR0cy5hcnJvd3dpZHRoLFxuICAgIHN0YW5kb2ZmOiBhbm5BdHRzLnN0YW5kb2ZmLFxuICAgIHN0YXJ0c3RhbmRvZmY6IGFubkF0dHMuc3RhcnRzdGFuZG9mZixcbiAgICBob3ZlcnRleHQ6IGFubkF0dHMuaG92ZXJ0ZXh0LFxuICAgIGhvdmVybGFiZWw6IGFubkF0dHMuaG92ZXJsYWJlbCxcbiAgICBjYXB0dXJlZXZlbnRzOiBhbm5BdHRzLmNhcHR1cmVldmVudHMsXG5cbiAgICAvLyBtYXliZXMgbGF0ZXI/XG4gICAgLy8gY2xpY2t0b3Nob3c6IGFubkF0dHMuY2xpY2t0b3Nob3csXG4gICAgLy8geGNsaWNrOiBhbm5BdHRzLnhjbGljayxcbiAgICAvLyB5Y2xpY2s6IGFubkF0dHMueWNsaWNrLFxuXG4gICAgLy8gbm90IG5lZWRlZCFcbiAgICAvLyBheHJlZjogJ3BpeGVsJ1xuICAgIC8vIGF5cmVmOiAncGl4ZWwnXG4gICAgLy8geHJlZjogJ3gnXG4gICAgLy8geXJlZjogJ3lcbiAgICAvLyB6cmVmOiAneidcbn0pLCAnY2FsYycsICdmcm9tLXJvb3QnKTtcblxufSx7XCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uL2Fubm90YXRpb25zL2F0dHJpYnV0ZXNcIjo1NzZ9XSw1ODY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29udmVydChzY2VuZSkge1xuICAgIHZhciBmdWxsU2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIGFubnMgPSBmdWxsU2NlbmVMYXlvdXQuYW5ub3RhdGlvbnM7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYW5ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBtb2NrQW5uQXhlcyhhbm5zW2ldLCBzY2VuZSk7XG4gICAgfVxuXG4gICAgc2NlbmUuZnVsbExheW91dC5faW5mb2xheWVyXG4gICAgICAgIC5zZWxlY3RBbGwoJy5hbm5vdGF0aW9uLScgKyBzY2VuZS5pZClcbiAgICAgICAgLnJlbW92ZSgpO1xufTtcblxuZnVuY3Rpb24gbW9ja0FubkF4ZXMoYW5uLCBzY2VuZSkge1xuICAgIHZhciBmdWxsU2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIGRvbWFpbiA9IGZ1bGxTY2VuZUxheW91dC5kb21haW47XG4gICAgdmFyIHNpemUgPSBzY2VuZS5mdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgdmFyIGJhc2UgPSB7XG4gICAgICAgIC8vIHRoaXMgZ2V0cyBmaWxsIGluIG9uIHJlbmRlclxuICAgICAgICBwZGF0YTogbnVsbCxcblxuICAgICAgICAvLyB0byBnZXQgc2V0Q29udmVydCB0byBub3QgZXhlY3V0ZSBjbGVhbmx5XG4gICAgICAgIHR5cGU6ICdsaW5lYXInLFxuXG4gICAgICAgIC8vIGRvbid0IHRyeSB0byB1cGRhdGUgdGhlbSBvbiBgZWRpdGFibGU6IHRydWVgXG4gICAgICAgIGF1dG9yYW5nZTogZmFsc2UsXG5cbiAgICAgICAgLy8gc2V0IGluZmluaXRlIHJhbmdlIHNvIHRoYXQgYW5ub3RhdGlvbiBkcmF3IHJvdXRpbmVcbiAgICAgICAgLy8gZG9lcyBub3QgdHJ5IHRvIHJlbW92ZSAnb3V0c2lkZS1yYW5nZScgYW5ub3RhdGlvbnMsXG4gICAgICAgIC8vIHRoaXMgY2FzZSBpcyBoYW5kbGVkIGluIHRoZSByZW5kZXIgbG9vcFxuICAgICAgICByYW5nZTogWy1JbmZpbml0eSwgSW5maW5pdHldXG4gICAgfTtcblxuICAgIGFubi5feGEgPSB7fTtcbiAgICBMaWIuZXh0ZW5kRmxhdChhbm4uX3hhLCBiYXNlKTtcbiAgICBBeGVzLnNldENvbnZlcnQoYW5uLl94YSk7XG4gICAgYW5uLl94YS5fb2Zmc2V0ID0gc2l6ZS5sICsgZG9tYWluLnhbMF0gKiBzaXplLnc7XG4gICAgYW5uLl94YS5sMnAgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIDAuNSAqICgxICsgYW5uLl9wZGF0YVswXSAvIGFubi5fcGRhdGFbM10pICogc2l6ZS53ICogKGRvbWFpbi54WzFdIC0gZG9tYWluLnhbMF0pO1xuICAgIH07XG5cbiAgICBhbm4uX3lhID0ge307XG4gICAgTGliLmV4dGVuZEZsYXQoYW5uLl95YSwgYmFzZSk7XG4gICAgQXhlcy5zZXRDb252ZXJ0KGFubi5feWEpO1xuICAgIGFubi5feWEuX29mZnNldCA9IHNpemUudCArICgxIC0gZG9tYWluLnlbMV0pICogc2l6ZS5oO1xuICAgIGFubi5feWEubDJwID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAwLjUgKiAoMSAtIGFubi5fcGRhdGFbMV0gLyBhbm4uX3BkYXRhWzNdKSAqIHNpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKTtcbiAgICB9O1xufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3fV0sNTg3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVBbm5vdGF0aW9uQ29tbW9uRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9hbm5vdGF0aW9ucy9jb21tb25fZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlRGVmYXVsdHMoc2NlbmVMYXlvdXRJbiwgc2NlbmVMYXlvdXRPdXQsIG9wdHMpIHtcbiAgICBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzKHNjZW5lTGF5b3V0SW4sIHNjZW5lTGF5b3V0T3V0LCB7XG4gICAgICAgIG5hbWU6ICdhbm5vdGF0aW9ucycsXG4gICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogaGFuZGxlQW5ub3RhdGlvbkRlZmF1bHRzLFxuICAgICAgICBmdWxsTGF5b3V0OiBvcHRzLmZ1bGxMYXlvdXRcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZUFubm90YXRpb25EZWZhdWx0cyhhbm5JbiwgYW5uT3V0LCBzY2VuZUxheW91dCwgb3B0cykge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGFubkluLCBhbm5PdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvZXJjZVBvc2l0aW9uKGF4TGV0dGVyKSB7XG4gICAgICAgIHZhciBheE5hbWUgPSBheExldHRlciArICdheGlzJztcblxuICAgICAgICAvLyBtb2NrIGluIHN1Y2ggd2F5IHRoYXQgZ2V0RnJvbUlkIGdyYWJzIGNvcnJlY3QgM0QgYXhpc1xuICAgICAgICB2YXIgZ2RNb2NrID0geyBfZnVsbExheW91dDoge30gfTtcbiAgICAgICAgZ2RNb2NrLl9mdWxsTGF5b3V0W2F4TmFtZV0gPSBzY2VuZUxheW91dFtheE5hbWVdO1xuXG4gICAgICAgIHJldHVybiBBeGVzLmNvZXJjZVBvc2l0aW9uKGFubk91dCwgZ2RNb2NrLCBjb2VyY2UsIGF4TGV0dGVyLCBheExldHRlciwgMC41KTtcbiAgICB9XG5cblxuICAgIHZhciB2aXNpYmxlID0gY29lcmNlKCd2aXNpYmxlJyk7XG4gICAgaWYoIXZpc2libGUpIHJldHVybjtcblxuICAgIGhhbmRsZUFubm90YXRpb25Db21tb25EZWZhdWx0cyhhbm5JbiwgYW5uT3V0LCBvcHRzLmZ1bGxMYXlvdXQsIGNvZXJjZSk7XG5cbiAgICBjb2VyY2VQb3NpdGlvbigneCcpO1xuICAgIGNvZXJjZVBvc2l0aW9uKCd5Jyk7XG4gICAgY29lcmNlUG9zaXRpb24oJ3onKTtcblxuICAgIC8vIGlmIHlvdSBoYXZlIG9uZSBjb29yZGluYXRlIHlvdSBzaG91bGQgYWxsIHRocmVlXG4gICAgTGliLm5vbmVPckFsbChhbm5JbiwgYW5uT3V0LCBbJ3gnLCAneScsICd6J10pO1xuXG4gICAgLy8gaGFyZC1zZXQgaGVyZSBmb3IgY29tcGxldGVuZXNzXG4gICAgYW5uT3V0LnhyZWYgPSAneCc7XG4gICAgYW5uT3V0LnlyZWYgPSAneSc7XG4gICAgYW5uT3V0LnpyZWYgPSAneic7XG5cbiAgICBjb2VyY2UoJ3hhbmNob3InKTtcbiAgICBjb2VyY2UoJ3lhbmNob3InKTtcbiAgICBjb2VyY2UoJ3hzaGlmdCcpO1xuICAgIGNvZXJjZSgneXNoaWZ0Jyk7XG5cbiAgICBpZihhbm5PdXQuc2hvd2Fycm93KSB7XG4gICAgICAgIGFubk91dC5heHJlZiA9ICdwaXhlbCc7XG4gICAgICAgIGFubk91dC5heXJlZiA9ICdwaXhlbCc7XG5cbiAgICAgICAgLy8gVE9ETyBtYXliZSBkZWZhdWx0IHZhbHVlcyBzaG91bGQgYmUgYmlnZ2VyIHRoYW4gdGhlIDJEIGNhc2U/XG4gICAgICAgIGNvZXJjZSgnYXgnLCAtMTApO1xuICAgICAgICBjb2VyY2UoJ2F5JywgLTMwKTtcblxuICAgICAgICAvLyBpZiB5b3UgaGF2ZSBvbmUgcGFydCBvZiBhcnJvdyBsZW5ndGggeW91IHNob3VsZCBoYXZlIGJvdGhcbiAgICAgICAgTGliLm5vbmVPckFsbChhbm5JbiwgYW5uT3V0LCBbJ2F4JywgJ2F5J10pO1xuICAgIH1cbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHNcIjo3NjMsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL2Fubm90YXRpb25zL2NvbW1vbl9kZWZhdWx0c1wiOjU3OSxcIi4vYXR0cmlidXRlc1wiOjU4NX1dLDU4ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkcmF3UmF3ID0gX2RlcmVxXygnLi4vYW5ub3RhdGlvbnMvZHJhdycpLmRyYXdSYXc7XG52YXIgcHJvamVjdCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2dsM2QvcHJvamVjdCcpO1xudmFyIGF4TGV0dGVycyA9IFsneCcsICd5JywgJ3onXTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkcmF3KHNjZW5lKSB7XG4gICAgdmFyIGZ1bGxTY2VuZUxheW91dCA9IHNjZW5lLmZ1bGxTY2VuZUxheW91dDtcbiAgICB2YXIgZGF0YVNjYWxlID0gc2NlbmUuZGF0YVNjYWxlO1xuICAgIHZhciBhbm5zID0gZnVsbFNjZW5lTGF5b3V0LmFubm90YXRpb25zO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFubnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGFubiA9IGFubnNbaV07XG4gICAgICAgIHZhciBhbm5vdGF0aW9uSXNPZmZzY3JlZW4gPSBmYWxzZTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgMzsgaisrKSB7XG4gICAgICAgICAgICB2YXIgYXhMZXR0ZXIgPSBheExldHRlcnNbal07XG4gICAgICAgICAgICB2YXIgcG9zID0gYW5uW2F4TGV0dGVyXTtcbiAgICAgICAgICAgIHZhciBheCA9IGZ1bGxTY2VuZUxheW91dFtheExldHRlciArICdheGlzJ107XG4gICAgICAgICAgICB2YXIgcG9zRnJhY3Rpb24gPSBheC5yMmZyYWN0aW9uKHBvcyk7XG5cbiAgICAgICAgICAgIGlmKHBvc0ZyYWN0aW9uIDwgMCB8fCBwb3NGcmFjdGlvbiA+IDEpIHtcbiAgICAgICAgICAgICAgICBhbm5vdGF0aW9uSXNPZmZzY3JlZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoYW5ub3RhdGlvbklzT2Zmc2NyZWVuKSB7XG4gICAgICAgICAgICBzY2VuZS5mdWxsTGF5b3V0Ll9pbmZvbGF5ZXJcbiAgICAgICAgICAgICAgICAuc2VsZWN0KCcuYW5ub3RhdGlvbi0nICsgc2NlbmUuaWQgKyAnW2RhdGEtaW5kZXg9XCInICsgaSArICdcIl0nKVxuICAgICAgICAgICAgICAgIC5yZW1vdmUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFubi5fcGRhdGEgPSBwcm9qZWN0KHNjZW5lLmdscGxvdC5jYW1lcmFQYXJhbXMsIFtcbiAgICAgICAgICAgICAgICBmdWxsU2NlbmVMYXlvdXQueGF4aXMucjJsKGFubi54KSAqIGRhdGFTY2FsZVswXSxcbiAgICAgICAgICAgICAgICBmdWxsU2NlbmVMYXlvdXQueWF4aXMucjJsKGFubi55KSAqIGRhdGFTY2FsZVsxXSxcbiAgICAgICAgICAgICAgICBmdWxsU2NlbmVMYXlvdXQuemF4aXMucjJsKGFubi56KSAqIGRhdGFTY2FsZVsyXVxuICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgIGRyYXdSYXcoc2NlbmUuZ3JhcGhEaXYsIGFubiwgaSwgc2NlbmUuaWQsIGFubi5feGEsIGFubi5feWEpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9nbDNkL3Byb2plY3RcIjo4MTYsXCIuLi9hbm5vdGF0aW9ucy9kcmF3XCI6NTgyfV0sNTg5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogJ2Fubm90YXRpb25zM2QnLFxuXG4gICAgc2NoZW1hOiB7XG4gICAgICAgIHN1YnBsb3RzOiB7XG4gICAgICAgICAgICBzY2VuZToge2Fubm90YXRpb25zOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKX1cbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBoYW5kbGVEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGluY2x1ZGVCYXNlUGxvdDogaW5jbHVkZUdMM0QsXG5cbiAgICBjb252ZXJ0OiBfZGVyZXFfKCcuL2NvbnZlcnQnKSxcbiAgICBkcmF3OiBfZGVyZXFfKCcuL2RyYXcnKVxufTtcblxuZnVuY3Rpb24gaW5jbHVkZUdMM0QobGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgIHZhciBHTDNEID0gUmVnaXN0cnkuc3VicGxvdHNSZWdpc3RyeS5nbDNkO1xuICAgIGlmKCFHTDNEKSByZXR1cm47XG5cbiAgICB2YXIgYXR0clJlZ2V4ID0gR0wzRC5hdHRyUmVnZXg7XG5cbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGxheW91dEluKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgayA9IGtleXNbaV07XG4gICAgICAgIGlmKGF0dHJSZWdleC50ZXN0KGspICYmIChsYXlvdXRJbltrXS5hbm5vdGF0aW9ucyB8fCBbXSkubGVuZ3RoKSB7XG4gICAgICAgICAgICBMaWIucHVzaFVuaXF1ZShsYXlvdXRPdXQuX2Jhc2VQbG90TW9kdWxlcywgR0wzRCk7XG4gICAgICAgICAgICBMaWIucHVzaFVuaXF1ZShsYXlvdXRPdXQuX3N1YnBsb3RzLmdsM2QsIGspO1xuICAgICAgICB9XG4gICAgfVxufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9hdHRyaWJ1dGVzXCI6NTg1LFwiLi9jb252ZXJ0XCI6NTg2LFwiLi9kZWZhdWx0c1wiOjU4NyxcIi4vZHJhd1wiOjU4OH1dLDU5MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8vIGEgdHJpbW1lZCBkb3duIHZlcnNpb24gb2Y6XG4vLyBodHRwczovL2dpdGh1Yi5jb20vYWxleGNqb2huc29uL3dvcmxkLWNhbGVuZGFycy9ibG9iL21hc3Rlci9kaXN0L2luZGV4LmpzXG5cbm1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnd29ybGQtY2FsZW5kYXJzL2Rpc3QvbWFpbicpO1xuXG5fZGVyZXFfKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9wbHVzJyk7XG5cbl9kZXJlcV8oJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9jaGluZXNlJyk7XG5fZGVyZXFfKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvY29wdGljJyk7XG5fZGVyZXFfKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvZGlzY3dvcmxkJyk7XG5fZGVyZXFfKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvZXRoaW9waWFuJyk7XG5fZGVyZXFfKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvaGVicmV3Jyk7XG5fZGVyZXFfKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvaXNsYW1pYycpO1xuX2RlcmVxXygnd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL2p1bGlhbicpO1xuX2RlcmVxXygnd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL21heWFuJyk7XG5fZGVyZXFfKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvbmFuYWtzaGFoaScpO1xuX2RlcmVxXygnd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL25lcGFsaScpO1xuX2RlcmVxXygnd29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL3BlcnNpYW4nKTtcbl9kZXJlcV8oJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy90YWl3YW4nKTtcbl9kZXJlcV8oJ3dvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy90aGFpJyk7XG5fZGVyZXFfKCd3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvdW1tYWxxdXJhJyk7XG5cbn0se1wid29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL2NoaW5lc2VcIjo1NTcsXCJ3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvY29wdGljXCI6NTU4LFwid29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL2Rpc2N3b3JsZFwiOjU1OSxcIndvcmxkLWNhbGVuZGFycy9kaXN0L2NhbGVuZGFycy9ldGhpb3BpYW5cIjo1NjAsXCJ3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvaGVicmV3XCI6NTYxLFwid29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL2lzbGFtaWNcIjo1NjIsXCJ3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvanVsaWFuXCI6NTYzLFwid29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL21heWFuXCI6NTY0LFwid29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL25hbmFrc2hhaGlcIjo1NjUsXCJ3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvbmVwYWxpXCI6NTY2LFwid29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL3BlcnNpYW5cIjo1NjcsXCJ3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvdGFpd2FuXCI6NTY4LFwid29ybGQtY2FsZW5kYXJzL2Rpc3QvY2FsZW5kYXJzL3RoYWlcIjo1NjksXCJ3b3JsZC1jYWxlbmRhcnMvZGlzdC9jYWxlbmRhcnMvdW1tYWxxdXJhXCI6NTcwLFwid29ybGQtY2FsZW5kYXJzL2Rpc3QvbWFpblwiOjU3MSxcIndvcmxkLWNhbGVuZGFycy9kaXN0L3BsdXNcIjo1NzJ9XSw1OTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY2FsZW5kYXJzID0gX2RlcmVxXygnLi9jYWxlbmRhcnMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKTtcblxudmFyIEVQT0NISkQgPSBjb25zdGFudHMuRVBPQ0hKRDtcbnZhciBPTkVEQVkgPSBjb25zdGFudHMuT05FREFZO1xuXG52YXIgYXR0cmlidXRlcyA9IHtcbiAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgdmFsdWVzOiBPYmplY3Qua2V5cyhjYWxlbmRhcnMuY2FsZW5kYXJzKSxcbiAgICBcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIGRmbHQ6ICdncmVnb3JpYW4nXG59O1xuXG52YXIgaGFuZGxlRGVmYXVsdHMgPSBmdW5jdGlvbihjb250SW4sIGNvbnRPdXQsIGF0dHIsIGRmbHQpIHtcbiAgICB2YXIgYXR0cnMgPSB7fTtcbiAgICBhdHRyc1thdHRyXSA9IGF0dHJpYnV0ZXM7XG5cbiAgICByZXR1cm4gTGliLmNvZXJjZShjb250SW4sIGNvbnRPdXQsIGF0dHJzLCBhdHRyLCBkZmx0KTtcbn07XG5cbnZhciBoYW5kbGVUcmFjZURlZmF1bHRzID0gZnVuY3Rpb24odHJhY2VJbiwgdHJhY2VPdXQsIGNvb3JkcywgbGF5b3V0KSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBoYW5kbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29vcmRzW2ldICsgJ2NhbGVuZGFyJywgbGF5b3V0LmNhbGVuZGFyKTtcbiAgICB9XG59O1xuXG4vLyBlYWNoIGNhbGVuZGFyIG5lZWRzIGl0cyBvd24gZGVmYXVsdCBjYW5vbmljYWwgdGljay4gSSB3b3VsZCBsb3ZlIHRvIHVzZVxuLy8gMjAwMC0wMS0wMSAob3IgZXZlbiAwMDAwLTAxLTAxKSBmb3IgdGhlbSBhbGwgYnV0IHRoZXkgZG9uJ3QgbmVjZXNzYXJpbHlcbi8vIGFsbCBzdXBwb3J0IGVpdGhlciBvZiB0aG9zZSBkYXRlcy4gSW5zdGVhZCBJJ2xsIHVzZSB0aGUgbW9zdCBzaWduaWZpY2FudFxuLy8gbnVtYmVyIHRoZXkgKmRvKiBzdXBwb3J0LCBiaWFzZWQgdG93YXJkIHRoZSBwcmVzZW50IGRheS5cbnZhciBDQU5PTklDQUxfVElDSyA9IHtcbiAgICBjaGluZXNlOiAnMjAwMC0wMS0wMScsXG4gICAgY29wdGljOiAnMjAwMC0wMS0wMScsXG4gICAgZGlzY3dvcmxkOiAnMjAwMC0wMS0wMScsXG4gICAgZXRoaW9waWFuOiAnMjAwMC0wMS0wMScsXG4gICAgaGVicmV3OiAnNTAwMC0wMS0wMScsXG4gICAgaXNsYW1pYzogJzEwMDAtMDEtMDEnLFxuICAgIGp1bGlhbjogJzIwMDAtMDEtMDEnLFxuICAgIG1heWFuOiAnNTAwMC0wMS0wMScsXG4gICAgbmFuYWtzaGFoaTogJzEwMDAtMDEtMDEnLFxuICAgIG5lcGFsaTogJzIwMDAtMDEtMDEnLFxuICAgIHBlcnNpYW46ICcxMDAwLTAxLTAxJyxcbiAgICBqYWxhbGk6ICcxMDAwLTAxLTAxJyxcbiAgICB0YWl3YW46ICcxMDAwLTAxLTAxJyxcbiAgICB0aGFpOiAnMjAwMC0wMS0wMScsXG4gICAgdW1tYWxxdXJhOiAnMTQwMC0wMS0wMSdcbn07XG5cbi8vIFN0YXJ0IG9uIGEgU3VuZGF5IC0gZm9yIHdlZWsgdGlja3Ncbi8vIERpc2N3b3JsZCBhbmQgTWF5YW4gY2FsZW5kYXJzIGRvbid0IGhhdmUgNy1kYXkgd2Vla3MgYnV0IHdlJ3JlIGdvaW5nIHRvIGdpdmUgdGhlbVxuLy8gNy1kYXkgd2VlayB0aWNrcyBzbyBzdGFydCBvbiBvdXIgU3VuZGF5cy5cbi8vIElmIGFueW9uZSByZWFsbHkgY2FyZXMgd2UgY2FuIGN1c3RvbWl6ZSB0aGUgYXV0byB0aWNrIHNwYWNpbmdzIGZvciB0aGVzZSBjYWxlbmRhcnMuXG52YXIgQ0FOT05JQ0FMX1NVTkRBWSA9IHtcbiAgICBjaGluZXNlOiAnMjAwMC0wMS0wMicsXG4gICAgY29wdGljOiAnMjAwMC0wMS0wMycsXG4gICAgZGlzY3dvcmxkOiAnMjAwMC0wMS0wMycsXG4gICAgZXRoaW9waWFuOiAnMjAwMC0wMS0wNScsXG4gICAgaGVicmV3OiAnNTAwMC0wMS0wMScsXG4gICAgaXNsYW1pYzogJzEwMDAtMDEtMDInLFxuICAgIGp1bGlhbjogJzIwMDAtMDEtMDMnLFxuICAgIG1heWFuOiAnNTAwMC0wMS0wMScsXG4gICAgbmFuYWtzaGFoaTogJzEwMDAtMDEtMDUnLFxuICAgIG5lcGFsaTogJzIwMDAtMDEtMDUnLFxuICAgIHBlcnNpYW46ICcxMDAwLTAxLTAxJyxcbiAgICBqYWxhbGk6ICcxMDAwLTAxLTAxJyxcbiAgICB0YWl3YW46ICcxMDAwLTAxLTA0JyxcbiAgICB0aGFpOiAnMjAwMC0wMS0wNCcsXG4gICAgdW1tYWxxdXJhOiAnMTQwMC0wMS0wNidcbn07XG5cbnZhciBERkxUUkFOR0UgPSB7XG4gICAgY2hpbmVzZTogWycyMDAwLTAxLTAxJywgJzIwMDEtMDEtMDEnXSxcbiAgICBjb3B0aWM6IFsnMTcwMC0wMS0wMScsICcxNzAxLTAxLTAxJ10sXG4gICAgZGlzY3dvcmxkOiBbJzE4MDAtMDEtMDEnLCAnMTgwMS0wMS0wMSddLFxuICAgIGV0aGlvcGlhbjogWycyMDAwLTAxLTAxJywgJzIwMDEtMDEtMDEnXSxcbiAgICBoZWJyZXc6IFsnNTcwMC0wMS0wMScsICc1NzAxLTAxLTAxJ10sXG4gICAgaXNsYW1pYzogWycxNDAwLTAxLTAxJywgJzE0MDEtMDEtMDEnXSxcbiAgICBqdWxpYW46IFsnMjAwMC0wMS0wMScsICcyMDAxLTAxLTAxJ10sXG4gICAgbWF5YW46IFsnNTIwMC0wMS0wMScsICc1MjAxLTAxLTAxJ10sXG4gICAgbmFuYWtzaGFoaTogWycwNTAwLTAxLTAxJywgJzA1MDEtMDEtMDEnXSxcbiAgICBuZXBhbGk6IFsnMjAwMC0wMS0wMScsICcyMDAxLTAxLTAxJ10sXG4gICAgcGVyc2lhbjogWycxNDAwLTAxLTAxJywgJzE0MDEtMDEtMDEnXSxcbiAgICBqYWxhbGk6IFsnMTQwMC0wMS0wMScsICcxNDAxLTAxLTAxJ10sXG4gICAgdGFpd2FuOiBbJzAxMDAtMDEtMDEnLCAnMDEwMS0wMS0wMSddLFxuICAgIHRoYWk6IFsnMjUwMC0wMS0wMScsICcyNTAxLTAxLTAxJ10sXG4gICAgdW1tYWxxdXJhOiBbJzE0MDAtMDEtMDEnLCAnMTQwMS0wMS0wMSddXG59O1xuXG4vKlxuICogY29udmVydCBkMyB0ZW1wbGF0ZXMgdG8gd29ybGQtY2FsZW5kYXJzIHRlbXBsYXRlcywgc28gb3VyIHVzZXJzIG9ubHkgbmVlZFxuICogdG8ga25vdyBkMydzIHNwZWNpZmllcnMuIE1hcCBzcGFjZSBwYWRkaW5nIHRvIG5vIHBhZGRpbmcsIGFuZCB1bmtub3duIGZpZWxkc1xuICogdG8gYW4gdWdseSBwbGFjZWhvbGRlclxuICovXG52YXIgVU5LTk9XTiA9ICcjIyc7XG52YXIgZDNUb1dvcmxkQ2FsZW5kYXJzID0ge1xuICAgICdkJzogeycwJzogJ2RkJywgJy0nOiAnZCd9LCAvLyAyLWRpZ2l0IG9yIHVucGFkZGVkIGRheSBvZiBtb250aFxuICAgICdlJzogeycwJzogJ2QnLCAnLSc6ICdkJ30sIC8vIGFsdGVybmF0ZSwgYWx3YXlzIHVucGFkZGVkIGRheSBvZiBtb250aFxuICAgICdhJzogeycwJzogJ0QnLCAnLSc6ICdEJ30sIC8vIHNob3J0IHdlZWtkYXkgbmFtZVxuICAgICdBJzogeycwJzogJ0REJywgJy0nOiAnREQnfSwgLy8gZnVsbCB3ZWVrZGF5IG5hbWVcbiAgICAnaic6IHsnMCc6ICdvbycsICctJzogJ28nfSwgLy8gMy1kaWdpdCBvciB1bnBhZGRlZCBkYXkgb2YgdGhlIHllYXJcbiAgICAnVyc6IHsnMCc6ICd3dycsICctJzogJ3cnfSwgLy8gMi1kaWdpdCBvciB1bnBhZGRlZCB3ZWVrIG9mIHRoZSB5ZWFyIChNb25kYXkgZmlyc3QpXG4gICAgJ20nOiB7JzAnOiAnbW0nLCAnLSc6ICdtJ30sIC8vIDItZGlnaXQgb3IgdW5wYWRkZWQgbW9udGggbnVtYmVyXG4gICAgJ2InOiB7JzAnOiAnTScsICctJzogJ00nfSwgLy8gc2hvcnQgbW9udGggbmFtZVxuICAgICdCJzogeycwJzogJ01NJywgJy0nOiAnTU0nfSwgLy8gZnVsbCBtb250aCBuYW1lXG4gICAgJ3knOiB7JzAnOiAneXknLCAnLSc6ICd5eSd9LCAvLyAyLWRpZ2l0IHllYXIgKG1hcCB1bnBhZGRlZCB0byB6ZXJvLXBhZGRlZClcbiAgICAnWSc6IHsnMCc6ICd5eXl5JywgJy0nOiAneXl5eSd9LCAvLyA0LWRpZ2l0IHllYXIgKG1hcCB1bnBhZGRlZCB0byB6ZXJvLXBhZGRlZClcbiAgICAnVSc6IFVOS05PV04sIC8vIFN1bmRheS1maXJzdCB3ZWVrIG9mIHRoZSB5ZWFyXG4gICAgJ3cnOiBVTktOT1dOLCAvLyBkYXkgb2YgdGhlIHdlZWsgWzAoc3VuZGF5KSw2XVxuICAgIC8vIGNvbWJpbmVkIGZvcm1hdCwgd2UgcmVwbGFjZSB0aGUgZGF0ZSBwYXJ0IHdpdGggdGhlIHdvcmxkLWNhbGVuZGFyIHZlcnNpb25cbiAgICAvLyBhbmQgdGhlICVYIHN0YXlzIHRoZXJlIGZvciBkMyB0byBoYW5kbGUgd2l0aCB0aW1lIHBhcnRzXG4gICAgJ2MnOiB7JzAnOiAnRCBNIGQgJVggeXl5eScsICctJzogJ0QgTSBkICVYIHl5eXknfSxcbiAgICAneCc6IHsnMCc6ICdtbS9kZC95eXl5JywgJy0nOiAnbW0vZGQveXl5eSd9XG59O1xuXG5mdW5jdGlvbiB3b3JsZENhbEZtdChmbXQsIHgsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGRhdGVKRCA9IE1hdGguZmxvb3IoKHggKyAwLjA1KSAvIE9ORURBWSkgKyBFUE9DSEpEO1xuICAgIHZhciBjRGF0ZSA9IGdldENhbChjYWxlbmRhcikuZnJvbUpEKGRhdGVKRCk7XG4gICAgdmFyIGkgPSAwO1xuICAgIHZhciBtb2RpZmllciwgZGlyZWN0aXZlLCBkaXJlY3RpdmVMZW4sIGRpcmVjdGl2ZU9iaiwgcmVwbGFjZW1lbnRQYXJ0O1xuXG4gICAgd2hpbGUoKGkgPSBmbXQuaW5kZXhPZignJScsIGkpKSAhPT0gLTEpIHtcbiAgICAgICAgbW9kaWZpZXIgPSBmbXQuY2hhckF0KGkgKyAxKTtcbiAgICAgICAgaWYobW9kaWZpZXIgPT09ICcwJyB8fCBtb2RpZmllciA9PT0gJy0nIHx8IG1vZGlmaWVyID09PSAnXycpIHtcbiAgICAgICAgICAgIGRpcmVjdGl2ZUxlbiA9IDM7XG4gICAgICAgICAgICBkaXJlY3RpdmUgPSBmbXQuY2hhckF0KGkgKyAyKTtcbiAgICAgICAgICAgIGlmKG1vZGlmaWVyID09PSAnXycpIG1vZGlmaWVyID0gJy0nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGlyZWN0aXZlID0gbW9kaWZpZXI7XG4gICAgICAgICAgICBtb2RpZmllciA9ICcwJztcbiAgICAgICAgICAgIGRpcmVjdGl2ZUxlbiA9IDI7XG4gICAgICAgIH1cbiAgICAgICAgZGlyZWN0aXZlT2JqID0gZDNUb1dvcmxkQ2FsZW5kYXJzW2RpcmVjdGl2ZV07XG4gICAgICAgIGlmKCFkaXJlY3RpdmVPYmopIHtcbiAgICAgICAgICAgIGkgKz0gZGlyZWN0aXZlTGVuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY29kZSBpcyByZWNvZ25pemVkIGFzIGEgZGF0ZSBwYXJ0IGJ1dCB3b3JsZC1jYWxlbmRhcnMgZG9lc24ndCBzdXBwb3J0IGl0XG4gICAgICAgICAgICBpZihkaXJlY3RpdmVPYmogPT09IFVOS05PV04pIHJlcGxhY2VtZW50UGFydCA9IFVOS05PV047XG5cbiAgICAgICAgICAgIC8vIGZvcm1hdCB0aGUgY0RhdGUgYWNjb3JkaW5nIHRvIHRoZSB0cmFuc2xhdGVkIGRpcmVjdGl2ZVxuICAgICAgICAgICAgZWxzZSByZXBsYWNlbWVudFBhcnQgPSBjRGF0ZS5mb3JtYXREYXRlKGRpcmVjdGl2ZU9ialttb2RpZmllcl0pO1xuXG4gICAgICAgICAgICBmbXQgPSBmbXQuc3Vic3RyKDAsIGkpICsgcmVwbGFjZW1lbnRQYXJ0ICsgZm10LnN1YnN0cihpICsgZGlyZWN0aXZlTGVuKTtcbiAgICAgICAgICAgIGkgKz0gcmVwbGFjZW1lbnRQYXJ0Lmxlbmd0aDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZm10O1xufVxuXG4vLyBjYWNoZSB3b3JsZCBjYWxlbmRhcnMsIHNvIHdlIGRvbid0IGhhdmUgdG8gcmVpbnN0YW50aWF0ZVxuLy8gZHVyaW5nIGVhY2ggZGF0ZS10aW1lIGNvbnZlcnNpb25cbnZhciBhbGxDYWxzID0ge307XG5mdW5jdGlvbiBnZXRDYWwoY2FsZW5kYXIpIHtcbiAgICB2YXIgY2FsZW5kYXJPYmogPSBhbGxDYWxzW2NhbGVuZGFyXTtcbiAgICBpZihjYWxlbmRhck9iaikgcmV0dXJuIGNhbGVuZGFyT2JqO1xuXG4gICAgY2FsZW5kYXJPYmogPSBhbGxDYWxzW2NhbGVuZGFyXSA9IGNhbGVuZGFycy5pbnN0YW5jZShjYWxlbmRhcik7XG4gICAgcmV0dXJuIGNhbGVuZGFyT2JqO1xufVxuXG5mdW5jdGlvbiBtYWtlQXR0cnMoZGVzY3JpcHRpb24pIHtcbiAgICByZXR1cm4gTGliLmV4dGVuZEZsYXQoe30sIGF0dHJpYnV0ZXMsIHsgZGVzY3JpcHRpb246IGRlc2NyaXB0aW9uIH0pO1xufVxuXG5mdW5jdGlvbiBtYWtlVHJhY2VBdHRyc0Rlc2NyaXB0aW9uKGNvb3JkKSB7XG4gICAgcmV0dXJuICdTZXRzIHRoZSBjYWxlbmRhciBzeXN0ZW0gdG8gdXNlIHdpdGggYCcgKyBjb29yZCArICdgIGRhdGUgZGF0YS4nO1xufVxuXG52YXIgeEF0dHJzID0ge1xuICAgIHhjYWxlbmRhcjogbWFrZUF0dHJzKG1ha2VUcmFjZUF0dHJzRGVzY3JpcHRpb24oJ3gnKSlcbn07XG5cbnZhciB4eUF0dHJzID0gTGliLmV4dGVuZEZsYXQoe30sIHhBdHRycywge1xuICAgIHljYWxlbmRhcjogbWFrZUF0dHJzKG1ha2VUcmFjZUF0dHJzRGVzY3JpcHRpb24oJ3knKSlcbn0pO1xuXG52YXIgeHl6QXR0cnMgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgeHlBdHRycywge1xuICAgIHpjYWxlbmRhcjogbWFrZUF0dHJzKG1ha2VUcmFjZUF0dHJzRGVzY3JpcHRpb24oJ3onKSlcbn0pO1xuXG52YXIgYXhpc0F0dHJzID0gbWFrZUF0dHJzKFtcbiAgICAnU2V0cyB0aGUgY2FsZW5kYXIgc3lzdGVtIHRvIHVzZSBmb3IgYHJhbmdlYCBhbmQgYHRpY2swYCcsXG4gICAgJ2lmIHRoaXMgaXMgYSBkYXRlIGF4aXMuIFRoaXMgZG9lcyBub3Qgc2V0IHRoZSBjYWxlbmRhciBmb3InLFxuICAgICdpbnRlcnByZXRpbmcgZGF0YSBvbiB0aGlzIGF4aXMsIHRoYXRcXCdzIHNwZWNpZmllZCBpbiB0aGUgdHJhY2UnLFxuICAgICdvciB2aWEgdGhlIGdsb2JhbCBgbGF5b3V0LmNhbGVuZGFyYCdcbl0uam9pbignICcpKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogJ2NhbGVuZGFycycsXG5cbiAgICBzY2hlbWE6IHtcbiAgICAgICAgdHJhY2VzOiB7XG4gICAgICAgICAgICBzY2F0dGVyOiB4eUF0dHJzLFxuICAgICAgICAgICAgYmFyOiB4eUF0dHJzLFxuICAgICAgICAgICAgYm94OiB4eUF0dHJzLFxuICAgICAgICAgICAgaGVhdG1hcDogeHlBdHRycyxcbiAgICAgICAgICAgIGNvbnRvdXI6IHh5QXR0cnMsXG4gICAgICAgICAgICBoaXN0b2dyYW06IHh5QXR0cnMsXG4gICAgICAgICAgICBoaXN0b2dyYW0yZDogeHlBdHRycyxcbiAgICAgICAgICAgIGhpc3RvZ3JhbTJkY29udG91cjogeHlBdHRycyxcbiAgICAgICAgICAgIHNjYXR0ZXIzZDogeHl6QXR0cnMsXG4gICAgICAgICAgICBzdXJmYWNlOiB4eXpBdHRycyxcbiAgICAgICAgICAgIG1lc2gzZDogeHl6QXR0cnMsXG4gICAgICAgICAgICBzY2F0dGVyZ2w6IHh5QXR0cnMsXG4gICAgICAgICAgICBvaGxjOiB4QXR0cnMsXG4gICAgICAgICAgICBjYW5kbGVzdGljazogeEF0dHJzXG4gICAgICAgIH0sXG4gICAgICAgIGxheW91dDoge1xuICAgICAgICAgICAgY2FsZW5kYXI6IG1ha2VBdHRycyhbXG4gICAgICAgICAgICAgICAgJ1NldHMgdGhlIGRlZmF1bHQgY2FsZW5kYXIgc3lzdGVtIHRvIHVzZSBmb3IgaW50ZXJwcmV0aW5nIGFuZCcsXG4gICAgICAgICAgICAgICAgJ2Rpc3BsYXlpbmcgZGF0ZXMgdGhyb3VnaG91dCB0aGUgcGxvdC4nXG4gICAgICAgICAgICBdLmpvaW4oJyAnKSlcbiAgICAgICAgfSxcbiAgICAgICAgc3VicGxvdHM6IHtcbiAgICAgICAgICAgIHhheGlzOiB7Y2FsZW5kYXI6IGF4aXNBdHRyc30sXG4gICAgICAgICAgICB5YXhpczoge2NhbGVuZGFyOiBheGlzQXR0cnN9LFxuICAgICAgICAgICAgc2NlbmU6IHtcbiAgICAgICAgICAgICAgICB4YXhpczoge2NhbGVuZGFyOiBheGlzQXR0cnN9LFxuICAgICAgICAgICAgICAgIC8vIFRPRE86IGl0J3MgYWN0dWFsbHkgcmVkdW5kYW50IHRvIGluY2x1ZGUgeWF4aXMgYW5kIHpheGlzIGhlcmVcbiAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIGluIHRoZSBzY2VuZSBhdHRyaWJ1dGVzIHRoZXNlIGFyZSB0aGUgc2FtZSBvYmplY3Qgc28gbWVyZ2luZ1xuICAgICAgICAgICAgICAgIC8vIGludG8gb25lIG1lcmdlcyBpbnRvIHRoZW0gYWxsLiBIb3dldmVyLCBJIGxlZnQgdGhlbSBpbiBmb3IgcGFyaXR5IHdpdGhcbiAgICAgICAgICAgICAgICAvLyBjYXJ0ZXNpYW4sIHdoZXJlIHlheGlzIGlzIHVudXNlZCB1bnRpbCB3ZSBQbG90c2NoZW1hLmdldCgpIHdoZW4gd2VcbiAgICAgICAgICAgICAgICAvLyB1c2UgaXRzIHByZXNlbmNlIG9yIGFic2VuY2UgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdG8gZGVsZXRlIGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICAvLyBmcm9tIHlheGlzIGlmIHRoZXkgb25seSBhcHBseSB0byB4IChyYW5nZXNlbGVjdG9yL3Jhbmdlc2xpZGVyKVxuICAgICAgICAgICAgICAgIHlheGlzOiB7Y2FsZW5kYXI6IGF4aXNBdHRyc30sXG4gICAgICAgICAgICAgICAgemF4aXM6IHtjYWxlbmRhcjogYXhpc0F0dHJzfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBvbGFyOiB7XG4gICAgICAgICAgICAgICAgcmFkaWFsYXhpczoge2NhbGVuZGFyOiBheGlzQXR0cnN9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHRyYW5zZm9ybXM6IHtcbiAgICAgICAgICAgIGZpbHRlcjoge1xuICAgICAgICAgICAgICAgIHZhbHVlY2FsZW5kYXI6IG1ha2VBdHRycyhbXG4gICAgICAgICAgICAgICAgICAgICdTZXRzIHRoZSBjYWxlbmRhciBzeXN0ZW0gdG8gdXNlIGZvciBgdmFsdWVgLCBpZiBpdCBpcyBhIGRhdGUuJ1xuICAgICAgICAgICAgICAgIF0uam9pbignICcpKSxcbiAgICAgICAgICAgICAgICB0YXJnZXRjYWxlbmRhcjogbWFrZUF0dHJzKFtcbiAgICAgICAgICAgICAgICAgICAgJ1NldHMgdGhlIGNhbGVuZGFyIHN5c3RlbSB0byB1c2UgZm9yIGB0YXJnZXRgLCBpZiBpdCBpcyBhbicsXG4gICAgICAgICAgICAgICAgICAgICdhcnJheSBvZiBkYXRlcy4gSWYgYHRhcmdldGAgaXMgYSBzdHJpbmcgKGVnICp4Kikgd2UgdXNlIHRoZScsXG4gICAgICAgICAgICAgICAgICAgICdjb3JyZXNwb25kaW5nIHRyYWNlIGF0dHJpYnV0ZSAoZWcgYHhjYWxlbmRhcmApIGlmIGl0IGV4aXN0cywnLFxuICAgICAgICAgICAgICAgICAgICAnZXZlbiBpZiBgdGFyZ2V0Y2FsZW5kYXJgIGlzIHByb3ZpZGVkLidcbiAgICAgICAgICAgICAgICBdLmpvaW4oJyAnKSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBhdHRyaWJ1dGVzLFxuXG4gICAgaGFuZGxlRGVmYXVsdHM6IGhhbmRsZURlZmF1bHRzLFxuICAgIGhhbmRsZVRyYWNlRGVmYXVsdHM6IGhhbmRsZVRyYWNlRGVmYXVsdHMsXG5cbiAgICBDQU5PTklDQUxfU1VOREFZOiBDQU5PTklDQUxfU1VOREFZLFxuICAgIENBTk9OSUNBTF9USUNLOiBDQU5PTklDQUxfVElDSyxcbiAgICBERkxUUkFOR0U6IERGTFRSQU5HRSxcblxuICAgIGdldENhbDogZ2V0Q2FsLFxuICAgIHdvcmxkQ2FsRm10OiB3b3JsZENhbEZtdFxufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vbGliXCI6NzE5LFwiLi9jYWxlbmRhcnNcIjo1OTB9XSw1OTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbi8vIElNUE9SVEFOVCAtIGRlZmF1bHQgY29sb3JzIHNob3VsZCBiZSBpbiBoZXggZm9yIGNvbXBhdGliaWxpdHlcbmV4cG9ydHMuZGVmYXVsdHMgPSBbXG4gICAgJyMxZjc3YjQnLCAgLy8gbXV0ZWQgYmx1ZVxuICAgICcjZmY3ZjBlJywgIC8vIHNhZmV0eSBvcmFuZ2VcbiAgICAnIzJjYTAyYycsICAvLyBjb29rZWQgYXNwYXJhZ3VzIGdyZWVuXG4gICAgJyNkNjI3MjgnLCAgLy8gYnJpY2sgcmVkXG4gICAgJyM5NDY3YmQnLCAgLy8gbXV0ZWQgcHVycGxlXG4gICAgJyM4YzU2NGInLCAgLy8gY2hlc3RudXQgYnJvd25cbiAgICAnI2UzNzdjMicsICAvLyByYXNwYmVycnkgeW9ndXJ0IHBpbmtcbiAgICAnIzdmN2Y3ZicsICAvLyBtaWRkbGUgZ3JheVxuICAgICcjYmNiZDIyJywgIC8vIGN1cnJ5IHllbGxvdy1ncmVlblxuICAgICcjMTdiZWNmJyAgIC8vIGJsdWUtdGVhbFxuXTtcblxuZXhwb3J0cy5kZWZhdWx0TGluZSA9ICcjNDQ0JztcblxuZXhwb3J0cy5saWdodExpbmUgPSAnI2VlZSc7XG5cbmV4cG9ydHMuYmFja2dyb3VuZCA9ICcjZmZmJztcblxuZXhwb3J0cy5ib3JkZXJMaW5lID0gJyNCRUM4RDknO1xuXG4vLyB3aXRoIGF4aXMuY29sb3IgYW5kIENvbG9yLmludGVycCB3ZSBhcmVuJ3QgdXNpbmcgbGlnaHRMaW5lXG4vLyBpdHNlbGYgYW55bW9yZSwgaW5zdGVhZCBpbnRlcnBvbGF0aW5nIGJldHdlZW4gYXhpcy5jb2xvclxuLy8gYW5kIHRoZSBiYWNrZ3JvdW5kIGNvbG9yIHVzaW5nIHRpbnljb2xvci5taXguIGxpZ2h0RnJhY3Rpb25cbi8vIGdpdmVzIGJhY2sgZXhhY3RseSBsaWdodExpbmUgaWYgdGhlIG90aGVyIGNvbG9ycyBhcmUgZGVmYXVsdHMuXG5leHBvcnRzLmxpZ2h0RnJhY3Rpb24gPSAxMDAgKiAoMHhlIC0gMHg0KSAvICgweGYgLSAweDQpO1xuXG59LHt9XSw1OTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciB0aW55Y29sb3IgPSBfZGVyZXFfKCd0aW55Y29sb3IyJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIGNvbG9yID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxudmFyIGNvbG9yQXR0cnMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbmNvbG9yLmRlZmF1bHRzID0gY29sb3JBdHRycy5kZWZhdWx0cztcbnZhciBkZWZhdWx0TGluZSA9IGNvbG9yLmRlZmF1bHRMaW5lID0gY29sb3JBdHRycy5kZWZhdWx0TGluZTtcbmNvbG9yLmxpZ2h0TGluZSA9IGNvbG9yQXR0cnMubGlnaHRMaW5lO1xudmFyIGJhY2tncm91bmQgPSBjb2xvci5iYWNrZ3JvdW5kID0gY29sb3JBdHRycy5iYWNrZ3JvdW5kO1xuXG4vKlxuICogdGlueVJHQjogdHVybiBhIHRpbnljb2xvciBpbnRvIGFuIHJnYiBzdHJpbmcsIGJ1dFxuICogdW5saWtlIHRoZSBidWlsdC1pbiB0aW55Y29sb3IudG9SZ2JTdHJpbmcgdGhpcyBuZXZlciBpbmNsdWRlcyBhbHBoYVxuICovXG5jb2xvci50aW55UkdCID0gZnVuY3Rpb24odGMpIHtcbiAgICB2YXIgYyA9IHRjLnRvUmdiKCk7XG4gICAgcmV0dXJuICdyZ2IoJyArIE1hdGgucm91bmQoYy5yKSArICcsICcgK1xuICAgICAgICBNYXRoLnJvdW5kKGMuZykgKyAnLCAnICsgTWF0aC5yb3VuZChjLmIpICsgJyknO1xufTtcblxuY29sb3IucmdiID0gZnVuY3Rpb24oY3N0cikgeyByZXR1cm4gY29sb3IudGlueVJHQih0aW55Y29sb3IoY3N0cikpOyB9O1xuXG5jb2xvci5vcGFjaXR5ID0gZnVuY3Rpb24oY3N0cikgeyByZXR1cm4gY3N0ciA/IHRpbnljb2xvcihjc3RyKS5nZXRBbHBoYSgpIDogMDsgfTtcblxuY29sb3IuYWRkT3BhY2l0eSA9IGZ1bmN0aW9uKGNzdHIsIG9wKSB7XG4gICAgdmFyIGMgPSB0aW55Y29sb3IoY3N0cikudG9SZ2IoKTtcbiAgICByZXR1cm4gJ3JnYmEoJyArIE1hdGgucm91bmQoYy5yKSArICcsICcgK1xuICAgICAgICBNYXRoLnJvdW5kKGMuZykgKyAnLCAnICsgTWF0aC5yb3VuZChjLmIpICsgJywgJyArIG9wICsgJyknO1xufTtcblxuLy8gY29tYmluZSB0d28gY29sb3JzIGludG8gb25lIGFwcGFyZW50IGNvbG9yXG4vLyBpZiBiYWNrIGhhcyB0cmFuc3BhcmVuY3kgb3IgaXMgbWlzc2luZyxcbi8vIGNvbG9yLmJhY2tncm91bmQgaXMgYXNzdW1lZCBiZWhpbmQgaXRcbmNvbG9yLmNvbWJpbmUgPSBmdW5jdGlvbihmcm9udCwgYmFjaykge1xuICAgIHZhciBmYyA9IHRpbnljb2xvcihmcm9udCkudG9SZ2IoKTtcbiAgICBpZihmYy5hID09PSAxKSByZXR1cm4gdGlueWNvbG9yKGZyb250KS50b1JnYlN0cmluZygpO1xuXG4gICAgdmFyIGJjID0gdGlueWNvbG9yKGJhY2sgfHwgYmFja2dyb3VuZCkudG9SZ2IoKTtcbiAgICB2YXIgYmNmbGF0ID0gYmMuYSA9PT0gMSA/IGJjIDoge1xuICAgICAgICByOiAyNTUgKiAoMSAtIGJjLmEpICsgYmMuciAqIGJjLmEsXG4gICAgICAgIGc6IDI1NSAqICgxIC0gYmMuYSkgKyBiYy5nICogYmMuYSxcbiAgICAgICAgYjogMjU1ICogKDEgLSBiYy5hKSArIGJjLmIgKiBiYy5hXG4gICAgfTtcbiAgICB2YXIgZmNmbGF0ID0ge1xuICAgICAgICByOiBiY2ZsYXQuciAqICgxIC0gZmMuYSkgKyBmYy5yICogZmMuYSxcbiAgICAgICAgZzogYmNmbGF0LmcgKiAoMSAtIGZjLmEpICsgZmMuZyAqIGZjLmEsXG4gICAgICAgIGI6IGJjZmxhdC5iICogKDEgLSBmYy5hKSArIGZjLmIgKiBmYy5hXG4gICAgfTtcbiAgICByZXR1cm4gdGlueWNvbG9yKGZjZmxhdCkudG9SZ2JTdHJpbmcoKTtcbn07XG5cbi8qXG4gKiBDcmVhdGUgYSBjb2xvciB0aGF0IGNvbnRyYXN0cyB3aXRoIGNzdHIuXG4gKlxuICogSWYgY3N0ciBpcyBhIGRhcmsgY29sb3IsIHdlIGxpZ2h0ZW4gaXQ7IGlmIGl0J3MgbGlnaHQsIHdlIGRhcmtlbi5cbiAqXG4gKiBJZiBsaWdodEFtb3VudCAvIGRhcmtBbW91bnQgYXJlIHVzZWQsIHdlIGFkanVzdCBieSB0aGVzZSBwZXJjZW50YWdlcyxcbiAqIG90aGVyd2lzZSB3ZSBnbyBhbGwgdGhlIHdheSB0byB3aGl0ZSBvciBibGFjay5cbiAqL1xuY29sb3IuY29udHJhc3QgPSBmdW5jdGlvbihjc3RyLCBsaWdodEFtb3VudCwgZGFya0Ftb3VudCkge1xuICAgIHZhciB0YyA9IHRpbnljb2xvcihjc3RyKTtcblxuICAgIGlmKHRjLmdldEFscGhhKCkgIT09IDEpIHRjID0gdGlueWNvbG9yKGNvbG9yLmNvbWJpbmUoY3N0ciwgYmFja2dyb3VuZCkpO1xuXG4gICAgdmFyIG5ld0NvbG9yID0gdGMuaXNEYXJrKCkgP1xuICAgICAgICAobGlnaHRBbW91bnQgPyB0Yy5saWdodGVuKGxpZ2h0QW1vdW50KSA6IGJhY2tncm91bmQpIDpcbiAgICAgICAgKGRhcmtBbW91bnQgPyB0Yy5kYXJrZW4oZGFya0Ftb3VudCkgOiBkZWZhdWx0TGluZSk7XG5cbiAgICByZXR1cm4gbmV3Q29sb3IudG9TdHJpbmcoKTtcbn07XG5cbmNvbG9yLnN0cm9rZSA9IGZ1bmN0aW9uKHMsIGMpIHtcbiAgICB2YXIgdGMgPSB0aW55Y29sb3IoYyk7XG4gICAgcy5zdHlsZSh7J3N0cm9rZSc6IGNvbG9yLnRpbnlSR0IodGMpLCAnc3Ryb2tlLW9wYWNpdHknOiB0Yy5nZXRBbHBoYSgpfSk7XG59O1xuXG5jb2xvci5maWxsID0gZnVuY3Rpb24ocywgYykge1xuICAgIHZhciB0YyA9IHRpbnljb2xvcihjKTtcbiAgICBzLnN0eWxlKHtcbiAgICAgICAgJ2ZpbGwnOiBjb2xvci50aW55UkdCKHRjKSxcbiAgICAgICAgJ2ZpbGwtb3BhY2l0eSc6IHRjLmdldEFscGhhKClcbiAgICB9KTtcbn07XG5cbi8vIHNlYXJjaCBjb250YWluZXIgZm9yIGNvbG9ycyB3aXRoIHRoZSBkZXByZWNhdGVkIHJnYihmcmFjdGlvbnMpIGZvcm1hdFxuLy8gYW5kIGNvbnZlcnQgdGhlbSB0byByZ2IoMC0yNTUgdmFsdWVzKVxuY29sb3IuY2xlYW4gPSBmdW5jdGlvbihjb250YWluZXIpIHtcbiAgICBpZighY29udGFpbmVyIHx8IHR5cGVvZiBjb250YWluZXIgIT09ICdvYmplY3QnKSByZXR1cm47XG5cbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGNvbnRhaW5lcik7XG4gICAgdmFyIGksIGosIGtleSwgdmFsO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBrZXkgPSBrZXlzW2ldO1xuICAgICAgICB2YWwgPSBjb250YWluZXJba2V5XTtcblxuICAgICAgICBpZihrZXkuc3Vic3RyKGtleS5sZW5ndGggLSA1KSA9PT0gJ2NvbG9yJykge1xuICAgICAgICAgICAgLy8gb25seSBzYW5pdGl6ZSBrZXlzIHRoYXQgZW5kIGluIFwiY29sb3JcIiBvciBcImNvbG9yc2NhbGVcIlxuXG4gICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KHZhbCkpIHtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCB2YWwubGVuZ3RoOyBqKyspIHZhbFtqXSA9IGNsZWFuT25lKHZhbFtqXSk7XG4gICAgICAgICAgICB9IGVsc2UgY29udGFpbmVyW2tleV0gPSBjbGVhbk9uZSh2YWwpO1xuICAgICAgICB9IGVsc2UgaWYoa2V5LnN1YnN0cihrZXkubGVuZ3RoIC0gMTApID09PSAnY29sb3JzY2FsZScgJiYgQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgICAgICAgICAvLyBjb2xvcnNjYWxlcyBoYXZlIHRoZSBmb3JtYXQgW1swLCBjb2xvcjFdLCBbZnJhYywgY29sb3IyXSwgLi4uIFsxLCBjb2xvck5dXVxuXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCB2YWwubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KHZhbFtqXSkpIHZhbFtqXVsxXSA9IGNsZWFuT25lKHZhbFtqXVsxXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihBcnJheS5pc0FycmF5KHZhbCkpIHtcbiAgICAgICAgICAgIC8vIHJlY3Vyc2UgaW50byBhcnJheXMgb2Ygb2JqZWN0cywgYW5kIHBsYWluIG9iamVjdHNcblxuICAgICAgICAgICAgdmFyIGVsMCA9IHZhbFswXTtcbiAgICAgICAgICAgIGlmKCFBcnJheS5pc0FycmF5KGVsMCkgJiYgZWwwICYmIHR5cGVvZiBlbDAgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgdmFsLmxlbmd0aDsgaisrKSBjb2xvci5jbGVhbih2YWxbal0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYodmFsICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnKSBjb2xvci5jbGVhbih2YWwpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGNsZWFuT25lKHZhbCkge1xuICAgIGlmKGlzTnVtZXJpYyh2YWwpIHx8IHR5cGVvZiB2YWwgIT09ICdzdHJpbmcnKSByZXR1cm4gdmFsO1xuXG4gICAgdmFyIHZhbFRyaW0gPSB2YWwudHJpbSgpO1xuICAgIGlmKHZhbFRyaW0uc3Vic3RyKDAsIDMpICE9PSAncmdiJykgcmV0dXJuIHZhbDtcblxuICAgIHZhciBtYXRjaCA9IHZhbFRyaW0ubWF0Y2goL15yZ2JhP1xccypcXCgoW14oKV0qKVxcKSQvKTtcbiAgICBpZighbWF0Y2gpIHJldHVybiB2YWw7XG5cbiAgICB2YXIgcGFydHMgPSBtYXRjaFsxXS50cmltKCkuc3BsaXQoL1xccypbXFxzLF1cXHMqLyk7XG4gICAgdmFyIHJnYmEgPSB2YWxUcmltLmNoYXJBdCgzKSA9PT0gJ2EnICYmIHBhcnRzLmxlbmd0aCA9PT0gNDtcbiAgICBpZighcmdiYSAmJiBwYXJ0cy5sZW5ndGggIT09IDMpIHJldHVybiB2YWw7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoIXBhcnRzW2ldLmxlbmd0aCkgcmV0dXJuIHZhbDtcbiAgICAgICAgcGFydHNbaV0gPSBOdW1iZXIocGFydHNbaV0pO1xuXG4gICAgICAgIGlmKCEocGFydHNbaV0gPj0gMCkpIHtcbiAgICAgICAgICAgIC8vIGFsbCBwYXJ0cyBtdXN0IGJlIG5vbi1uZWdhdGl2ZSBudW1iZXJzXG5cbiAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgIH1cblxuICAgICAgICBpZihpID09PSAzKSB7XG4gICAgICAgICAgICAvLyBhbHBoYT4xIGdldHMgY2xpcHBlZCB0byAxXG5cbiAgICAgICAgICAgIGlmKHBhcnRzW2ldID4gMSkgcGFydHNbaV0gPSAxO1xuICAgICAgICB9IGVsc2UgaWYocGFydHNbaV0gPj0gMSkge1xuICAgICAgICAgICAgLy8gciwgZywgYiBtdXN0IGJlIDwgMSAoaWUgMSBpdHNlbGYgaXMgbm90IGFsbG93ZWQpXG5cbiAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcmdiU3RyID0gTWF0aC5yb3VuZChwYXJ0c1swXSAqIDI1NSkgKyAnLCAnICtcbiAgICAgICAgTWF0aC5yb3VuZChwYXJ0c1sxXSAqIDI1NSkgKyAnLCAnICtcbiAgICAgICAgTWF0aC5yb3VuZChwYXJ0c1syXSAqIDI1NSk7XG5cbiAgICBpZihyZ2JhKSByZXR1cm4gJ3JnYmEoJyArIHJnYlN0ciArICcsICcgKyBwYXJ0c1szXSArICcpJztcbiAgICByZXR1cm4gJ3JnYignICsgcmdiU3RyICsgJyknO1xufVxuXG59LHtcIi4vYXR0cmlidXRlc1wiOjU5MixcImZhc3QtaXNudW1lcmljXCI6MjI1LFwidGlueWNvbG9yMlwiOjUzN31dLDU5NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBheGVzQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBmb250QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4vLyBUT0RPOiBvbmx5IHJpZ2h0IGlzIHN1cHBvcnRlZCBjdXJyZW50bHlcbi8vICAgICBvcmllbnQ6IHtcbi8vICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuLy8gICAgICAgICBcbi8vICAgICAgICAgdmFsdWVzOiBbJ2xlZnQnLCAncmlnaHQnLCAndG9wJywgJ2JvdHRvbSddLFxuLy8gICAgICAgICBkZmx0OiAncmlnaHQnLFxuLy8gICAgICAgICBcbi8vICAgICB9LFxuICAgIHRoaWNrbmVzc21vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZnJhY3Rpb24nLCAncGl4ZWxzJ10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAncGl4ZWxzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aGlja25lc3M6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDMwLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxlbm1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZnJhY3Rpb24nLCAncGl4ZWxzJ10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnZnJhY3Rpb24nLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxlbjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAxLjAyLFxuICAgICAgICBtaW46IC0yLFxuICAgICAgICBtYXg6IDMsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHhhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgZGZsdDogJ2xlZnQnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB4cGFkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxMCxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogMC41LFxuICAgICAgICBtaW46IC0yLFxuICAgICAgICBtYXg6IDMsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeWFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWyd0b3AnLCAnbWlkZGxlJywgJ2JvdHRvbSddLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ21pZGRsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeXBhZDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMTAsXG4gICAgICAgIFxuICAgIH0sXG4gICAgLy8gYSBwb3NzaWJsZSBsaW5lIGFyb3VuZCB0aGUgYmFyIGl0c2VsZlxuICAgIG91dGxpbmVjb2xvcjogYXhlc0F0dHJzLmxpbmVjb2xvcixcbiAgICBvdXRsaW5ld2lkdGg6IGF4ZXNBdHRycy5saW5ld2lkdGgsXG4gICAgLy8gU2hvdWxkIG91dGxpbmV3aWR0aCBoYXZlIHtkZmx0OiAwfSA/XG4gICAgLy8gYW5vdGhlciBwb3NzaWJsZSBsaW5lIG91dHNpZGUgdGhlIHBhZGRpbmcgYW5kIHRpY2sgbGFiZWxzXG4gICAgYm9yZGVyY29sb3I6IGF4ZXNBdHRycy5saW5lY29sb3IsXG4gICAgYm9yZGVyd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYmdjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ3JnYmEoMCwwLDAsMCknLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIHRpY2sgYW5kIHRpdGxlIHByb3BlcnRpZXMgbmFtZWQgYW5kIGZ1bmN0aW9uIGV4YWN0bHkgYXMgaW4gYXhlc1xuICAgIHRpY2ttb2RlOiBheGVzQXR0cnMudGlja21vZGUsXG4gICAgbnRpY2tzOiBheGVzQXR0cnMubnRpY2tzLFxuICAgIHRpY2swOiBheGVzQXR0cnMudGljazAsXG4gICAgZHRpY2s6IGF4ZXNBdHRycy5kdGljayxcbiAgICB0aWNrdmFsczogYXhlc0F0dHJzLnRpY2t2YWxzLFxuICAgIHRpY2t0ZXh0OiBheGVzQXR0cnMudGlja3RleHQsXG4gICAgdGlja3M6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy50aWNrcywge2RmbHQ6ICcnfSksXG4gICAgdGlja2xlbjogYXhlc0F0dHJzLnRpY2tsZW4sXG4gICAgdGlja3dpZHRoOiBheGVzQXR0cnMudGlja3dpZHRoLFxuICAgIHRpY2tjb2xvcjogYXhlc0F0dHJzLnRpY2tjb2xvcixcbiAgICBzaG93dGlja2xhYmVsczogYXhlc0F0dHJzLnNob3d0aWNrbGFiZWxzLFxuICAgIHRpY2tmb250OiBmb250QXR0cnMoe1xuICAgICAgICBcbiAgICB9KSxcbiAgICB0aWNrYW5nbGU6IGF4ZXNBdHRycy50aWNrYW5nbGUsXG4gICAgdGlja2Zvcm1hdDogYXhlc0F0dHJzLnRpY2tmb3JtYXQsXG4gICAgdGlja2Zvcm1hdHN0b3BzOiBheGVzQXR0cnMudGlja2Zvcm1hdHN0b3BzLFxuICAgIHRpY2twcmVmaXg6IGF4ZXNBdHRycy50aWNrcHJlZml4LFxuICAgIHNob3d0aWNrcHJlZml4OiBheGVzQXR0cnMuc2hvd3RpY2twcmVmaXgsXG4gICAgdGlja3N1ZmZpeDogYXhlc0F0dHJzLnRpY2tzdWZmaXgsXG4gICAgc2hvd3RpY2tzdWZmaXg6IGF4ZXNBdHRycy5zaG93dGlja3N1ZmZpeCxcbiAgICBzZXBhcmF0ZXRob3VzYW5kczogYXhlc0F0dHJzLnNlcGFyYXRldGhvdXNhbmRzLFxuICAgIGV4cG9uZW50Zm9ybWF0OiBheGVzQXR0cnMuZXhwb25lbnRmb3JtYXQsXG4gICAgc2hvd2V4cG9uZW50OiBheGVzQXR0cnMuc2hvd2V4cG9uZW50LFxuICAgIHRpdGxlOiB7XG4gICAgICAgIHRleHQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgc2lkZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ3JpZ2h0JywgJ3RvcCcsICdib3R0b20nXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogJ3RvcCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBfZGVwcmVjYXRlZDoge1xuICAgICAgICB0aXRsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB0aXRsZWZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIHRpdGxlc2lkZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ3JpZ2h0JywgJ3RvcCcsICdib3R0b20nXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogJ3RvcCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH1cbn0sICdjb2xvcmJhcnMnLCAnZnJvbS1yb290Jyk7XG5cbn0se1wiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXNcIjo3NTAsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo3NzksXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTN9XSw1OTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjbjoge1xuICAgICAgICBjb2xvcmJhcjogJ2NvbG9yYmFyJyxcbiAgICAgICAgY2JiZzogJ2NiYmcnLFxuICAgICAgICBjYmZpbGw6ICdjYmZpbGwnLFxuICAgICAgICBjYmZpbGxzOiAnY2JmaWxscycsXG4gICAgICAgIGNibGluZTogJ2NibGluZScsXG4gICAgICAgIGNibGluZXM6ICdjYmxpbmVzJyxcbiAgICAgICAgY2JheGlzOiAnY2JheGlzJyxcbiAgICAgICAgY2J0aXRsZXVuc2hpZnQ6ICdjYnRpdGxldW5zaGlmdCcsXG4gICAgICAgIGNidGl0bGU6ICdjYnRpdGxlJyxcbiAgICAgICAgY2JvdXRsaW5lOiAnY2JvdXRsaW5lJyxcbiAgICAgICAgY3Jpc3A6ICdjcmlzcCcsXG4gICAgICAgIGpzUGxhY2Vob2xkZXI6ICdqcy1wbGFjZWhvbGRlcidcbiAgICB9XG59O1xuXG59LHt9XSw1OTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBUZW1wbGF0ZSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcblxudmFyIGhhbmRsZVRpY2tWYWx1ZURlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfdmFsdWVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrTWFya0RlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfbWFya19kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfbGFiZWxfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb2xvcmJhckRlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGxheW91dCkge1xuICAgIHZhciBjb2xvcmJhck91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcihjb250YWluZXJPdXQsICdjb2xvcmJhcicpO1xuICAgIHZhciBjb2xvcmJhckluID0gY29udGFpbmVySW4uY29sb3JiYXIgfHwge307XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShjb2xvcmJhckluLCBjb2xvcmJhck91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHRoaWNrbmVzc21vZGUgPSBjb2VyY2UoJ3RoaWNrbmVzc21vZGUnKTtcbiAgICBjb2VyY2UoJ3RoaWNrbmVzcycsICh0aGlja25lc3Ntb2RlID09PSAnZnJhY3Rpb24nKSA/XG4gICAgICAgIDMwIC8gKGxheW91dC53aWR0aCAtIGxheW91dC5tYXJnaW4ubCAtIGxheW91dC5tYXJnaW4ucikgOlxuICAgICAgICAzMFxuICAgICk7XG5cbiAgICB2YXIgbGVubW9kZSA9IGNvZXJjZSgnbGVubW9kZScpO1xuICAgIGNvZXJjZSgnbGVuJywgKGxlbm1vZGUgPT09ICdmcmFjdGlvbicpID9cbiAgICAgICAgMSA6XG4gICAgICAgIGxheW91dC5oZWlnaHQgLSBsYXlvdXQubWFyZ2luLnQgLSBsYXlvdXQubWFyZ2luLmJcbiAgICApO1xuXG4gICAgY29lcmNlKCd4Jyk7XG4gICAgY29lcmNlKCd4YW5jaG9yJyk7XG4gICAgY29lcmNlKCd4cGFkJyk7XG4gICAgY29lcmNlKCd5Jyk7XG4gICAgY29lcmNlKCd5YW5jaG9yJyk7XG4gICAgY29lcmNlKCd5cGFkJyk7XG4gICAgTGliLm5vbmVPckFsbChjb2xvcmJhckluLCBjb2xvcmJhck91dCwgWyd4JywgJ3knXSk7XG5cbiAgICBjb2VyY2UoJ291dGxpbmVjb2xvcicpO1xuICAgIGNvZXJjZSgnb3V0bGluZXdpZHRoJyk7XG4gICAgY29lcmNlKCdib3JkZXJjb2xvcicpO1xuICAgIGNvZXJjZSgnYm9yZGVyd2lkdGgnKTtcbiAgICBjb2VyY2UoJ2JnY29sb3InKTtcblxuICAgIGhhbmRsZVRpY2tWYWx1ZURlZmF1bHRzKGNvbG9yYmFySW4sIGNvbG9yYmFyT3V0LCBjb2VyY2UsICdsaW5lYXInKTtcblxuICAgIHZhciBvcHRzID0ge291dGVyVGlja3M6IGZhbHNlLCBmb250OiBsYXlvdXQuZm9udH07XG4gICAgaGFuZGxlVGlja0xhYmVsRGVmYXVsdHMoY29sb3JiYXJJbiwgY29sb3JiYXJPdXQsIGNvZXJjZSwgJ2xpbmVhcicsIG9wdHMpO1xuICAgIGhhbmRsZVRpY2tNYXJrRGVmYXVsdHMoY29sb3JiYXJJbiwgY29sb3JiYXJPdXQsIGNvZXJjZSwgJ2xpbmVhcicsIG9wdHMpO1xuXG4gICAgY29lcmNlKCd0aXRsZS50ZXh0JywgbGF5b3V0Ll9kZmx0VGl0bGUuY29sb3JiYXIpO1xuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3RpdGxlLmZvbnQnLCBsYXlvdXQuZm9udCk7XG4gICAgY29lcmNlKCd0aXRsZS5zaWRlJyk7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vdGlja19sYWJlbF9kZWZhdWx0c1wiOjc4NixcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi90aWNrX21hcmtfZGVmYXVsdHNcIjo3ODcsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vdGlja192YWx1ZV9kZWZhdWx0c1wiOjc4OCxcIi4vYXR0cmlidXRlc1wiOjU5NH1dLDU5NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgdGlueWNvbG9yID0gX2RlcmVxXygndGlueWNvbG9yMicpO1xuXG52YXIgUGxvdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9wbG90cycpO1xudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBkcmFnRWxlbWVudCA9IF9kZXJlcV8oJy4uL2RyYWdlbGVtZW50Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIHNldEN1cnNvciA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zZXRjdXJzb3InKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vZHJhd2luZycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vY29sb3InKTtcbnZhciBUaXRsZXMgPSBfZGVyZXFfKCcuLi90aXRsZXMnKTtcbnZhciBzdmdUZXh0VXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcbnZhciBmbGlwU2NhbGUgPSBfZGVyZXFfKCcuLi9jb2xvcnNjYWxlL2hlbHBlcnMnKS5mbGlwU2NhbGU7XG5cbnZhciBoYW5kbGVBeGlzRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19kZWZhdWx0cycpO1xudmFyIGhhbmRsZUF4aXNQb3NpdGlvbkRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3Bvc2l0aW9uX2RlZmF1bHRzJyk7XG52YXIgYXhpc0xheW91dEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbnZhciBhbGlnbm1lbnRDb25zdGFudHMgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50Jyk7XG52YXIgTElORV9TUEFDSU5HID0gYWxpZ25tZW50Q29uc3RhbnRzLkxJTkVfU1BBQ0lORztcbnZhciBGUk9NX1RMID0gYWxpZ25tZW50Q29uc3RhbnRzLkZST01fVEw7XG52YXIgRlJPTV9CUiA9IGFsaWdubWVudENvbnN0YW50cy5GUk9NX0JSO1xuXG52YXIgY24gPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpLmNuO1xuXG5mdW5jdGlvbiBkcmF3KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciBjb2xvckJhcnMgPSBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXJcbiAgICAgICAgLnNlbGVjdEFsbCgnZy4nICsgY24uY29sb3JiYXIpXG4gICAgICAgIC5kYXRhKG1ha2VDb2xvckJhckRhdGEoZ2QpLCBmdW5jdGlvbihvcHRzKSB7IHJldHVybiBvcHRzLl9pZDsgfSk7XG5cbiAgICBjb2xvckJhcnMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCBmdW5jdGlvbihvcHRzKSB7IHJldHVybiBvcHRzLl9pZDsgfSlcbiAgICAgICAgLmNsYXNzZWQoY24uY29sb3JiYXIsIHRydWUpO1xuXG4gICAgY29sb3JCYXJzLmVhY2goZnVuY3Rpb24ob3B0cykge1xuICAgICAgICB2YXIgZyA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGcsICdyZWN0JywgY24uY2JiZyk7XG4gICAgICAgIExpYi5lbnN1cmVTaW5nbGUoZywgJ2cnLCBjbi5jYmZpbGxzKTtcbiAgICAgICAgTGliLmVuc3VyZVNpbmdsZShnLCAnZycsIGNuLmNibGluZXMpO1xuICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGcsICdnJywgY24uY2JheGlzLCBmdW5jdGlvbihzKSB7IHMuY2xhc3NlZChjbi5jcmlzcCwgdHJ1ZSk7IH0pO1xuICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGcsICdnJywgY24uY2J0aXRsZXVuc2hpZnQsIGZ1bmN0aW9uKHMpIHsgcy5hcHBlbmQoJ2cnKS5jbGFzc2VkKGNuLmNidGl0bGUsIHRydWUpOyB9KTtcbiAgICAgICAgTGliLmVuc3VyZVNpbmdsZShnLCAncmVjdCcsIGNuLmNib3V0bGluZSk7XG5cbiAgICAgICAgdmFyIGRvbmUgPSBkcmF3Q29sb3JCYXIoZywgb3B0cywgZ2QpO1xuICAgICAgICBpZihkb25lICYmIGRvbmUudGhlbikgKGdkLl9wcm9taXNlcyB8fCBbXSkucHVzaChkb25lKTtcblxuICAgICAgICBpZihnZC5fY29udGV4dC5lZGl0cy5jb2xvcmJhclBvc2l0aW9uKSB7XG4gICAgICAgICAgICBtYWtlRWRpdGFibGUoZywgb3B0cywgZ2QpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBjb2xvckJhcnMuZXhpdCgpXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKG9wdHMpIHsgUGxvdHMuYXV0b01hcmdpbihnZCwgb3B0cy5faWQpOyB9KVxuICAgICAgICAucmVtb3ZlKCk7XG5cbiAgICBjb2xvckJhcnMub3JkZXIoKTtcbn1cblxuZnVuY3Rpb24gbWFrZUNvbG9yQmFyRGF0YShnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGNhbGNkYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIG91dCA9IFtdO1xuXG4gICAgLy8gc2luZ2xlIG91dCBpdGVtXG4gICAgdmFyIG9wdHM7XG4gICAgLy8gY29sb3JiYXIgYXR0ciBwYXJlbnQgY29udGFpbmVyXG4gICAgdmFyIGNvbnQ7XG4gICAgLy8gdHJhY2UgYXR0ciBjb250YWluZXJcbiAgICB2YXIgdHJhY2U7XG4gICAgLy8gY29sb3JiYXIgb3B0aW9uc1xuICAgIHZhciBjYk9wdDtcblxuICAgIGZ1bmN0aW9uIGluaXRPcHRzKG9wdHMpIHtcbiAgICAgICAgcmV0dXJuIGV4dGVuZEZsYXQob3B0cywge1xuICAgICAgICAgICAgLy8gZmlsbGNvbG9yIGNhbiBiZSBhIGQzIHNjYWxlLCBkb21haW4gaXMgeiB2YWx1ZXMsIHJhbmdlIGlzIGNvbG9yc1xuICAgICAgICAgICAgLy8gb3IgbGVhdmUgaXQgb3V0IGZvciBubyBmaWxsLFxuICAgICAgICAgICAgLy8gb3Igc2V0IHRvIGEgc3RyaW5nIGNvbnN0YW50IGZvciBzaW5nbGUtY29sb3IgZmlsbFxuICAgICAgICAgICAgX2ZpbGxjb2xvcjogbnVsbCxcbiAgICAgICAgICAgIC8vIGxpbmUuY29sb3IgaGFzIHRoZSBzYW1lIG9wdGlvbnMgYXMgZmlsbGNvbG9yXG4gICAgICAgICAgICBfbGluZToge2NvbG9yOiBudWxsLCB3aWR0aDogbnVsbCwgZGFzaDogbnVsbH0sXG4gICAgICAgICAgICAvLyBsZXZlbHMgb2YgbGluZXMgdG8gZHJhdy5cbiAgICAgICAgICAgIC8vIG5vdGUgdGhhdCB0aGlzIERPRVMgTk9UIGRldGVybWluZSB0aGUgZXh0ZW50IG9mIHRoZSBiYXJcbiAgICAgICAgICAgIC8vIHRoYXQncyBnaXZlbiBieSB0aGUgZG9tYWluIG9mIGZpbGxjb2xvclxuICAgICAgICAgICAgLy8gKG9yIGxpbmUuY29sb3IgaWYgbm8gZmlsbGNvbG9yIGRvbWFpbilcbiAgICAgICAgICAgIF9sZXZlbHM6IHtzdGFydDogbnVsbCwgZW5kOiBudWxsLCBzaXplOiBudWxsfSxcbiAgICAgICAgICAgIC8vIHNlcGFyYXRlIGZpbGwgbGV2ZWxzIChmb3IgZXhhbXBsZSwgaGVhdG1hcCBjb2xvcmluZyBvZiBhXG4gICAgICAgICAgICAvLyBjb250b3VyIG1hcCkgaWYgdGhpcyBpcyBvbWl0dGVkLCBmaWxsY29sb3JzIHdpbGwgYmVcbiAgICAgICAgICAgIC8vIGV2YWx1YXRlZCBoYWxmd2F5IGJldHdlZW4gbGV2ZWxzXG4gICAgICAgICAgICBfZmlsbGxldmVsczogbnVsbCxcbiAgICAgICAgICAgIC8vIGZvciBjb250aW51b3VzIGNvbG9yc2NhbGVzOiBmaWxsIHdpdGggYSBncmFkaWVudCBpbnN0ZWFkIG9mIGV4cGxpY2l0IGxldmVsc1xuICAgICAgICAgICAgLy8gdmFsdWUgc2hvdWxkIGJlIHRoZSBjb2xvcnNjYWxlIFtbMCwgYzBdLCBbdjEsIGMxXSwgLi4uLCBbMSwgY0VuZF1dXG4gICAgICAgICAgICBfZmlsbGdyYWRpZW50OiBudWxsLFxuICAgICAgICAgICAgLy8gd2hlbiB1c2luZyBhIGdyYWRpZW50LCB3ZSBuZWVkIHRoZSBkYXRhIHJhbmdlIHNwZWNpZmllZCBzZXBhcmF0ZWx5XG4gICAgICAgICAgICBfenJhbmdlOiBudWxsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNhbGNPcHRzKCkge1xuICAgICAgICBpZih0eXBlb2YgY2JPcHQuY2FsYyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2JPcHQuY2FsYyhnZCwgdHJhY2UsIG9wdHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3B0cy5fZmlsbGdyYWRpZW50ID0gY29udC5yZXZlcnNlc2NhbGUgP1xuICAgICAgICAgICAgICAgIGZsaXBTY2FsZShjb250LmNvbG9yc2NhbGUpIDpcbiAgICAgICAgICAgICAgICBjb250LmNvbG9yc2NhbGU7XG4gICAgICAgICAgICBvcHRzLl96cmFuZ2UgPSBbY29udFtjYk9wdC5taW5dLCBjb250W2NiT3B0Lm1heF1dO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjZCA9IGNhbGNkYXRhW2ldO1xuICAgICAgICB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgICAgICB2YXIgbW9kdWxlT3B0cyA9IHRyYWNlLl9tb2R1bGUuY29sb3JiYXI7XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSA9PT0gdHJ1ZSAmJiBtb2R1bGVPcHRzKSB7XG4gICAgICAgICAgICB2YXIgYWxsb3dzTXVsdGlwbG90Q2JzID0gQXJyYXkuaXNBcnJheShtb2R1bGVPcHRzKTtcbiAgICAgICAgICAgIHZhciBjYk9wdHMgPSBhbGxvd3NNdWx0aXBsb3RDYnMgPyBtb2R1bGVPcHRzIDogW21vZHVsZU9wdHNdO1xuXG4gICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2JPcHRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgY2JPcHQgPSBjYk9wdHNbal07XG4gICAgICAgICAgICAgICAgdmFyIGNvbnROYW1lID0gY2JPcHQuY29udGFpbmVyO1xuICAgICAgICAgICAgICAgIGNvbnQgPSBjb250TmFtZSA/IHRyYWNlW2NvbnROYW1lXSA6IHRyYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYoY29udCAmJiBjb250LnNob3dzY2FsZSkge1xuICAgICAgICAgICAgICAgICAgICBvcHRzID0gaW5pdE9wdHMoY29udC5jb2xvcmJhcik7XG4gICAgICAgICAgICAgICAgICAgIG9wdHMuX2lkID0gJ2NiJyArIHRyYWNlLnVpZCArIChhbGxvd3NNdWx0aXBsb3RDYnMgJiYgY29udE5hbWUgPyAnLScgKyBjb250TmFtZSA6ICcnKTtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5fdHJhY2VJbmRleCA9IHRyYWNlLmluZGV4O1xuICAgICAgICAgICAgICAgICAgICBvcHRzLl9wcm9wUHJlZml4ID0gKGNvbnROYW1lID8gY29udE5hbWUgKyAnLicgOiAnJykgKyAnY29sb3JiYXIuJztcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5fbWV0YSA9IHRyYWNlLl9tZXRhO1xuICAgICAgICAgICAgICAgICAgICBjYWxjT3B0cygpO1xuICAgICAgICAgICAgICAgICAgICBvdXQucHVzaChvcHRzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IodmFyIGsgaW4gZnVsbExheW91dC5fY29sb3JBeGVzKSB7XG4gICAgICAgIGNvbnQgPSBmdWxsTGF5b3V0W2tdO1xuXG4gICAgICAgIGlmKGNvbnQuc2hvd3NjYWxlKSB7XG4gICAgICAgICAgICB2YXIgY29sb3JBeE9wdHMgPSBmdWxsTGF5b3V0Ll9jb2xvckF4ZXNba107XG5cbiAgICAgICAgICAgIG9wdHMgPSBpbml0T3B0cyhjb250LmNvbG9yYmFyKTtcbiAgICAgICAgICAgIG9wdHMuX2lkID0gJ2NiJyArIGs7XG4gICAgICAgICAgICBvcHRzLl9wcm9wUHJlZml4ID0gayArICcuY29sb3JiYXIuJztcbiAgICAgICAgICAgIG9wdHMuX21ldGEgPSBmdWxsTGF5b3V0Ll9tZXRhO1xuXG4gICAgICAgICAgICBjYk9wdCA9IHttaW46ICdjbWluJywgbWF4OiAnY21heCd9O1xuICAgICAgICAgICAgaWYoY29sb3JBeE9wdHNbMF0gIT09ICdoZWF0bWFwJykge1xuICAgICAgICAgICAgICAgIHRyYWNlID0gY29sb3JBeE9wdHNbMV07XG4gICAgICAgICAgICAgICAgY2JPcHQuY2FsYyA9IHRyYWNlLl9tb2R1bGUuY29sb3JiYXIuY2FsYztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FsY09wdHMoKTtcbiAgICAgICAgICAgIG91dC5wdXNoKG9wdHMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gZHJhd0NvbG9yQmFyKGcsIG9wdHMsIGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZ3MgPSBmdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgdmFyIGZpbGxDb2xvciA9IG9wdHMuX2ZpbGxjb2xvcjtcbiAgICB2YXIgbGluZSA9IG9wdHMuX2xpbmU7XG4gICAgdmFyIHRpdGxlID0gb3B0cy50aXRsZTtcbiAgICB2YXIgdGl0bGVTaWRlID0gdGl0bGUuc2lkZTtcblxuICAgIHZhciB6cmFuZ2UgPSBvcHRzLl96cmFuZ2UgfHxcbiAgICAgICAgZDMuZXh0ZW50KCh0eXBlb2YgZmlsbENvbG9yID09PSAnZnVuY3Rpb24nID8gZmlsbENvbG9yIDogbGluZS5jb2xvcikuZG9tYWluKCkpO1xuXG4gICAgdmFyIGxpbmVDb2xvcm1hcCA9IHR5cGVvZiBsaW5lLmNvbG9yID09PSAnZnVuY3Rpb24nID9cbiAgICAgICAgbGluZS5jb2xvciA6XG4gICAgICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gbGluZS5jb2xvcjsgfTtcbiAgICB2YXIgZmlsbENvbG9ybWFwID0gdHlwZW9mIGZpbGxDb2xvciA9PT0gJ2Z1bmN0aW9uJyA/XG4gICAgICAgIGZpbGxDb2xvciA6XG4gICAgICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gZmlsbENvbG9yOyB9O1xuXG4gICAgdmFyIGxldmVsc0luID0gb3B0cy5fbGV2ZWxzO1xuICAgIHZhciBsZXZlbHNPdXQgPSBjYWxjTGV2ZWxzKGdkLCBvcHRzLCB6cmFuZ2UpO1xuICAgIHZhciBmaWxsTGV2ZWxzID0gbGV2ZWxzT3V0LmZpbGw7XG4gICAgdmFyIGxpbmVMZXZlbHMgPSBsZXZlbHNPdXQubGluZTtcblxuICAgIC8vIHdlIGNhbGN1bGF0ZSBwaXhlbCBzaXplcyBiYXNlZCBvbiB0aGUgc3BlY2lmaWVkIGdyYXBoIHNpemUsXG4gICAgLy8gbm90IHRoZSBhY3R1YWwgKGluIGNhc2Ugc29tZXRoaW5nIHB1c2hlZCB0aGUgbWFyZ2lucyBhcm91bmQpXG4gICAgLy8gd2hpY2ggaXMgYSBsaXR0bGUgb2RkIGJ1dCBhdm9pZHMgYW4gb2RkIGl0ZXJhdGl2ZSBlZmZlY3RcbiAgICAvLyB3aGVuIHRoZSBjb2xvcmJhciBpdHNlbGYgaXMgcHVzaGluZyB0aGUgbWFyZ2lucy5cbiAgICAvLyBidXQgdGhlbiB0aGUgZnJhY3Rpb25hbCBzaXplIGlzIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlXG4gICAgLy8gYWN0dWFsIGdyYXBoIHNpemUsIHNvIHRoYXQgdGhlIGF4ZXMgd2lsbCBzaXplIGNvcnJlY3RseS5cbiAgICB2YXIgdGhpY2tQeCA9IE1hdGgucm91bmQob3B0cy50aGlja25lc3MgKiAob3B0cy50aGlja25lc3Ntb2RlID09PSAnZnJhY3Rpb24nID8gZ3MudyA6IDEpKTtcbiAgICB2YXIgdGhpY2tGcmFjID0gdGhpY2tQeCAvIGdzLnc7XG4gICAgdmFyIGxlblB4ID0gTWF0aC5yb3VuZChvcHRzLmxlbiAqIChvcHRzLmxlbm1vZGUgPT09ICdmcmFjdGlvbicgPyBncy5oIDogMSkpO1xuICAgIHZhciBsZW5GcmFjID0gbGVuUHggLyBncy5oO1xuICAgIHZhciB4cGFkRnJhYyA9IG9wdHMueHBhZCAvIGdzLnc7XG4gICAgdmFyIHlFeHRyYVB4ID0gKG9wdHMuYm9yZGVyd2lkdGggKyBvcHRzLm91dGxpbmV3aWR0aCkgLyAyO1xuICAgIHZhciB5cGFkRnJhYyA9IG9wdHMueXBhZCAvIGdzLmg7XG5cbiAgICAvLyB4IHBvc2l0aW9uaW5nOiBkbyBpdCBpbml0aWFsbHkganVzdCBmb3IgbGVmdCBhbmNob3IsXG4gICAgLy8gdGhlbiBmaXggYXQgdGhlIGVuZCAoc2luY2Ugd2UgZG9uJ3Qga25vdyB0aGUgd2lkdGggeWV0KVxuICAgIHZhciB4TGVmdCA9IE1hdGgucm91bmQob3B0cy54ICogZ3MudyArIG9wdHMueHBhZCk7XG4gICAgLy8gZm9yIGRyYWdnaW5nLi4uIHRoaXMgaXMgZ2V0dGluZyBhIGxpdHRsZSBtdWRkbGVkLi4uXG4gICAgdmFyIHhMZWZ0RnJhYyA9IG9wdHMueCAtIHRoaWNrRnJhYyAqICh7bWlkZGxlOiAwLjUsIHJpZ2h0OiAxfVtvcHRzLnhhbmNob3JdIHx8IDApO1xuXG4gICAgLy8geSBwb3NpdGlvbmluZyB3ZSBjYW4gZG8gY29ycmVjdGx5IGZyb20gdGhlIHN0YXJ0XG4gICAgdmFyIHlCb3R0b21GcmFjID0gb3B0cy55ICsgbGVuRnJhYyAqICgoe3RvcDogLTAuNSwgYm90dG9tOiAwLjV9W29wdHMueWFuY2hvcl0gfHwgMCkgLSAwLjUpO1xuICAgIHZhciB5Qm90dG9tUHggPSBNYXRoLnJvdW5kKGdzLmggKiAoMSAtIHlCb3R0b21GcmFjKSk7XG4gICAgdmFyIHlUb3BQeCA9IHlCb3R0b21QeCAtIGxlblB4O1xuXG4gICAgLy8gc3Rhc2ggYSBmZXcgdGhpbmdzIGZvciBtYWtlRWRpdGFibGVcbiAgICBvcHRzLl9sZW5GcmFjID0gbGVuRnJhYztcbiAgICBvcHRzLl90aGlja0ZyYWMgPSB0aGlja0ZyYWM7XG4gICAgb3B0cy5feExlZnRGcmFjID0geExlZnRGcmFjO1xuICAgIG9wdHMuX3lCb3R0b21GcmFjID0geUJvdHRvbUZyYWM7XG5cbiAgICB2YXIgYXggPSBtb2NrQ29sb3JCYXJBeGlzKGdkLCBvcHRzLCB6cmFuZ2UpO1xuXG4gICAgLy8gcG9zaXRpb24gY2FuJ3QgZ28gaW4gdGhyb3VnaCBzdXBwbHlEZWZhdWx0c1xuICAgIC8vIGJlY2F1c2UgdGhhdCByZXN0cmljdHMgaXQgdG8gWzAsMV1cbiAgICBheC5wb3NpdGlvbiA9IG9wdHMueCArIHhwYWRGcmFjICsgdGhpY2tGcmFjO1xuXG4gICAgaWYoWyd0b3AnLCAnYm90dG9tJ10uaW5kZXhPZih0aXRsZVNpZGUpICE9PSAtMSkge1xuICAgICAgICBheC50aXRsZS5zaWRlID0gdGl0bGVTaWRlO1xuICAgICAgICBheC50aXRsZXggPSBvcHRzLnggKyB4cGFkRnJhYztcbiAgICAgICAgYXgudGl0bGV5ID0geUJvdHRvbUZyYWMgKyAodGl0bGUuc2lkZSA9PT0gJ3RvcCcgPyBsZW5GcmFjIC0geXBhZEZyYWMgOiB5cGFkRnJhYyk7XG4gICAgfVxuXG4gICAgaWYobGluZS5jb2xvciAmJiBvcHRzLnRpY2ttb2RlID09PSAnYXV0bycpIHtcbiAgICAgICAgYXgudGlja21vZGUgPSAnbGluZWFyJztcbiAgICAgICAgYXgudGljazAgPSBsZXZlbHNJbi5zdGFydDtcbiAgICAgICAgdmFyIGR0aWNrID0gbGV2ZWxzSW4uc2l6ZTtcbiAgICAgICAgLy8gZXhwYW5kIGlmIHRvbyBtYW55IGNvbnRvdXJzLCBzbyB3ZSBkb24ndCBnZXQgdG9vIG1hbnkgdGlja3NcbiAgICAgICAgdmFyIGF1dG9OdGljayA9IExpYi5jb25zdHJhaW4oKHlCb3R0b21QeCAtIHlUb3BQeCkgLyA1MCwgNCwgMTUpICsgMTtcbiAgICAgICAgdmFyIGR0RmFjdG9yID0gKHpyYW5nZVsxXSAtIHpyYW5nZVswXSkgLyAoKG9wdHMubnRpY2tzIHx8IGF1dG9OdGljaykgKiBkdGljayk7XG4gICAgICAgIGlmKGR0RmFjdG9yID4gMSkge1xuICAgICAgICAgICAgdmFyIGR0ZXhwID0gTWF0aC5wb3coMTAsIE1hdGguZmxvb3IoTWF0aC5sb2coZHRGYWN0b3IpIC8gTWF0aC5MTjEwKSk7XG4gICAgICAgICAgICBkdGljayAqPSBkdGV4cCAqIExpYi5yb3VuZFVwKGR0RmFjdG9yIC8gZHRleHAsIFsyLCA1LCAxMF0pO1xuICAgICAgICAgICAgLy8gaWYgdGhlIGNvbnRvdXJzIGFyZSBhdCByb3VuZCBtdWx0aXBsZXMsIHJlc2V0IHRpY2swXG4gICAgICAgICAgICAvLyBzbyB0aGV5J3JlIHN0aWxsIGF0IHJvdW5kIG11bHRpcGxlcy4gT3RoZXJ3aXNlLFxuICAgICAgICAgICAgLy8ga2VlcCB0aGUgZmlyc3QgbGFiZWwgb24gdGhlIGZpcnN0IGNvbnRvdXIgbGV2ZWxcbiAgICAgICAgICAgIGlmKChNYXRoLmFicyhsZXZlbHNJbi5zdGFydCkgLyBsZXZlbHNJbi5zaXplICsgMWUtNikgJSAxIDwgMmUtNikge1xuICAgICAgICAgICAgICAgIGF4LnRpY2swID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBheC5kdGljayA9IGR0aWNrO1xuICAgIH1cblxuICAgIC8vIHNldCBkb21haW4gYWZ0ZXIgaW5pdCwgYmVjYXVzZSB3ZSBtYXkgd2FudCB0b1xuICAgIC8vIGFsbG93IGl0IG91dHNpZGUgWzAsMV1cbiAgICBheC5kb21haW4gPSBbXG4gICAgICAgIHlCb3R0b21GcmFjICsgeXBhZEZyYWMsXG4gICAgICAgIHlCb3R0b21GcmFjICsgbGVuRnJhYyAtIHlwYWRGcmFjXG4gICAgXTtcblxuICAgIGF4LnNldFNjYWxlKCk7XG5cbiAgICBnLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIE1hdGgucm91bmQoZ3MubCkgKyAnLCcgKyBNYXRoLnJvdW5kKGdzLnQpICsgJyknKTtcblxuICAgIHZhciB0aXRsZUNvbnQgPSBnLnNlbGVjdCgnLicgKyBjbi5jYnRpdGxldW5zaGlmdClcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoLScgKyBNYXRoLnJvdW5kKGdzLmwpICsgJywtJyArIE1hdGgucm91bmQoZ3MudCkgKyAnKScpO1xuXG4gICAgdmFyIGF4TGF5ZXIgPSBnLnNlbGVjdCgnLicgKyBjbi5jYmF4aXMpO1xuICAgIHZhciB0aXRsZUVsO1xuICAgIHZhciB0aXRsZUhlaWdodCA9IDA7XG5cbiAgICBmdW5jdGlvbiBkcmF3VGl0bGUodGl0bGVDbGFzcywgdGl0bGVPcHRzKSB7XG4gICAgICAgIHZhciBkZmx0VGl0bGVPcHRzID0ge1xuICAgICAgICAgICAgcHJvcENvbnRhaW5lcjogYXgsXG4gICAgICAgICAgICBwcm9wTmFtZTogb3B0cy5fcHJvcFByZWZpeCArICd0aXRsZScsXG4gICAgICAgICAgICB0cmFjZUluZGV4OiBvcHRzLl90cmFjZUluZGV4LFxuICAgICAgICAgICAgX21ldGE6IG9wdHMuX21ldGEsXG4gICAgICAgICAgICBwbGFjZWhvbGRlcjogZnVsbExheW91dC5fZGZsdFRpdGxlLmNvbG9yYmFyLFxuICAgICAgICAgICAgY29udGFpbmVyR3JvdXA6IGcuc2VsZWN0KCcuJyArIGNuLmNidGl0bGUpXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gdGhpcyBjbGFzcy10by1yb3RhdGUgdGhpbmcgd2l0aCBjb252ZXJ0VG9Uc3BhbnMgaXNcbiAgICAgICAgLy8gZ2V0dGluZyBoYWNraWVyIGFuZCBoYWNraWVyLi4uIGRlbGV0ZSBncm91cHMgd2l0aCB0aGVcbiAgICAgICAgLy8gd3JvbmcgY2xhc3MgKGluIGNhc2UgZWFybGllciB0aGUgY29sb3JiYXIgd2FzIGRyYXduIG9uXG4gICAgICAgIC8vIGEgZGlmZmVyZW50IHNpZGUsIEkgdGhpbms/KVxuICAgICAgICB2YXIgb3RoZXJDbGFzcyA9IHRpdGxlQ2xhc3MuY2hhckF0KDApID09PSAnaCcgP1xuICAgICAgICAgICAgdGl0bGVDbGFzcy5zdWJzdHIoMSkgOlxuICAgICAgICAgICAgJ2gnICsgdGl0bGVDbGFzcztcbiAgICAgICAgZy5zZWxlY3RBbGwoJy4nICsgb3RoZXJDbGFzcyArICcsLicgKyBvdGhlckNsYXNzICsgJy1tYXRoLWdyb3VwJykucmVtb3ZlKCk7XG5cbiAgICAgICAgVGl0bGVzLmRyYXcoZ2QsIHRpdGxlQ2xhc3MsIGV4dGVuZEZsYXQoZGZsdFRpdGxlT3B0cywgdGl0bGVPcHRzIHx8IHt9KSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd0R1bW15VGl0bGUoKSB7XG4gICAgICAgIGlmKFsndG9wJywgJ2JvdHRvbSddLmluZGV4T2YodGl0bGVTaWRlKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIC8vIGRyYXcgdGhlIHRpdGxlIHNvIHdlIGtub3cgaG93IG11Y2ggcm9vbSBpdCBuZWVkc1xuICAgICAgICAgICAgLy8gd2hlbiB3ZSBzcXVpc2ggdGhlIGF4aXMuIFRoaXMgb25lIG9ubHkgYXBwbGllcyB0b1xuICAgICAgICAgICAgLy8gdG9wIG9yIGJvdHRvbSB0aXRsZXMsIG5vdCByaWdodCBzaWRlLlxuICAgICAgICAgICAgdmFyIHggPSBncy5sICsgKG9wdHMueCArIHhwYWRGcmFjKSAqIGdzLnc7XG4gICAgICAgICAgICB2YXIgZm9udFNpemUgPSBheC50aXRsZS5mb250LnNpemU7XG4gICAgICAgICAgICB2YXIgeTtcblxuICAgICAgICAgICAgaWYodGl0bGVTaWRlID09PSAndG9wJykge1xuICAgICAgICAgICAgICAgIHkgPSAoMSAtICh5Qm90dG9tRnJhYyArIGxlbkZyYWMgLSB5cGFkRnJhYykpICogZ3MuaCArXG4gICAgICAgICAgICAgICAgICAgIGdzLnQgKyAzICsgZm9udFNpemUgKiAwLjc1O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB5ID0gKDEgLSAoeUJvdHRvbUZyYWMgKyB5cGFkRnJhYykpICogZ3MuaCArXG4gICAgICAgICAgICAgICAgICAgIGdzLnQgLSAzIC0gZm9udFNpemUgKiAwLjI1O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZHJhd1RpdGxlKGF4Ll9pZCArICd0aXRsZScsIHtcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiB7eDogeCwgeTogeSwgJ3RleHQtYW5jaG9yJzogJ3N0YXJ0J31cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd0NiVGl0bGUoKSB7XG4gICAgICAgIGlmKFsndG9wJywgJ2JvdHRvbSddLmluZGV4T2YodGl0bGVTaWRlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHZhciBmb250U2l6ZSA9IGF4LnRpdGxlLmZvbnQuc2l6ZTtcbiAgICAgICAgICAgIHZhciB5ID0gYXguX29mZnNldCArIGF4Ll9sZW5ndGggLyAyO1xuICAgICAgICAgICAgdmFyIHggPSBncy5sICsgKGF4LnBvc2l0aW9uIHx8IDApICogZ3MudyArICgoYXguc2lkZSA9PT0gJ3JpZ2h0JykgP1xuICAgICAgICAgICAgICAgIDEwICsgZm9udFNpemUgKiAoKGF4LnNob3d0aWNrbGFiZWxzID8gMSA6IDAuNSkpIDpcbiAgICAgICAgICAgICAgICAtMTAgLSBmb250U2l6ZSAqICgoYXguc2hvd3RpY2tsYWJlbHMgPyAwLjUgOiAwKSkpO1xuXG4gICAgICAgICAgICAvLyB0aGUgJ2gnICsgaXMgYSBoYWNrIHRvIGdldCBhcm91bmQgdGhlIGZhY3QgdGhhdFxuICAgICAgICAgICAgLy8gY29udmVydFRvVHNwYW5zIHJvdGF0ZXMgYW55ICd5Li4uJyBjbGFzcyBieSA5MCBkZWdyZWVzLlxuICAgICAgICAgICAgLy8gVE9ETzogZmluZCBhIGJldHRlciB3YXkgdG8gY29udHJvbCB0aGlzLlxuICAgICAgICAgICAgZHJhd1RpdGxlKCdoJyArIGF4Ll9pZCArICd0aXRsZScsIHtcbiAgICAgICAgICAgICAgICBhdm9pZDoge1xuICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb246IGQzLnNlbGVjdChnZCkuc2VsZWN0QWxsKCdnLicgKyBheC5faWQgKyAndGljaycpLFxuICAgICAgICAgICAgICAgICAgICBzaWRlOiB0aXRsZVNpZGUsXG4gICAgICAgICAgICAgICAgICAgIG9mZnNldExlZnQ6IGdzLmwsXG4gICAgICAgICAgICAgICAgICAgIG9mZnNldFRvcDogMCxcbiAgICAgICAgICAgICAgICAgICAgbWF4U2hpZnQ6IGZ1bGxMYXlvdXQud2lkdGhcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHt4OiB4LCB5OiB5LCAndGV4dC1hbmNob3InOiAnbWlkZGxlJ30sXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiB7cm90YXRlOiAnLTkwJywgb2Zmc2V0OiAwfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3QXhpcygpIHtcbiAgICAgICAgaWYoWyd0b3AnLCAnYm90dG9tJ10uaW5kZXhPZih0aXRsZVNpZGUpICE9PSAtMSkge1xuICAgICAgICAgICAgLy8gc3F1aXNoIHRoZSBheGlzIHRvcCB0byBtYWtlIHJvb20gZm9yIHRoZSB0aXRsZVxuICAgICAgICAgICAgdmFyIHRpdGxlR3JvdXAgPSBnLnNlbGVjdCgnLicgKyBjbi5jYnRpdGxlKTtcbiAgICAgICAgICAgIHZhciB0aXRsZVRleHQgPSB0aXRsZUdyb3VwLnNlbGVjdCgndGV4dCcpO1xuICAgICAgICAgICAgdmFyIHRpdGxlVHJhbnMgPSBbLW9wdHMub3V0bGluZXdpZHRoIC8gMiwgb3B0cy5vdXRsaW5ld2lkdGggLyAyXTtcbiAgICAgICAgICAgIHZhciBtYXRoSmF4Tm9kZSA9IHRpdGxlR3JvdXBcbiAgICAgICAgICAgICAgICAuc2VsZWN0KCcuaCcgKyBheC5faWQgKyAndGl0bGUtbWF0aC1ncm91cCcpXG4gICAgICAgICAgICAgICAgLm5vZGUoKTtcbiAgICAgICAgICAgIHZhciBsaW5lU2l6ZSA9IDE1LjY7XG4gICAgICAgICAgICBpZih0aXRsZVRleHQubm9kZSgpKSB7XG4gICAgICAgICAgICAgICAgbGluZVNpemUgPSBwYXJzZUludCh0aXRsZVRleHQubm9kZSgpLnN0eWxlLmZvbnRTaXplLCAxMCkgKiBMSU5FX1NQQUNJTkc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihtYXRoSmF4Tm9kZSkge1xuICAgICAgICAgICAgICAgIHRpdGxlSGVpZ2h0ID0gRHJhd2luZy5iQm94KG1hdGhKYXhOb2RlKS5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgaWYodGl0bGVIZWlnaHQgPiBsaW5lU2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBub3QgZW50aXJlbHkgc3VyZSBob3cgbWF0aGpheCBpcyBkb2luZ1xuICAgICAgICAgICAgICAgICAgICAvLyB2ZXJ0aWNhbCBhbGlnbm1lbnQsIGJ1dCB0aGlzIHNlZW1zIHRvIHdvcmsuXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlVHJhbnNbMV0gLT0gKHRpdGxlSGVpZ2h0IC0gbGluZVNpemUpIC8gMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYodGl0bGVUZXh0Lm5vZGUoKSAmJiAhdGl0bGVUZXh0LmNsYXNzZWQoY24uanNQbGFjZWhvbGRlcikpIHtcbiAgICAgICAgICAgICAgICB0aXRsZUhlaWdodCA9IERyYXdpbmcuYkJveCh0aXRsZVRleHQubm9kZSgpKS5oZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih0aXRsZUhlaWdodCkge1xuICAgICAgICAgICAgICAgIC8vIGJ1ZmZlciBidHduIGNvbG9yYmFyIGFuZCB0aXRsZVxuICAgICAgICAgICAgICAgIC8vIFRPRE86IGNvbmZpZ3VyYWJsZVxuICAgICAgICAgICAgICAgIHRpdGxlSGVpZ2h0ICs9IDU7XG5cbiAgICAgICAgICAgICAgICBpZih0aXRsZVNpZGUgPT09ICd0b3AnKSB7XG4gICAgICAgICAgICAgICAgICAgIGF4LmRvbWFpblsxXSAtPSB0aXRsZUhlaWdodCAvIGdzLmg7XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlVHJhbnNbMV0gKj0gLTE7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXguZG9tYWluWzBdICs9IHRpdGxlSGVpZ2h0IC8gZ3MuaDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5saW5lcyA9IHN2Z1RleHRVdGlscy5saW5lQ291bnQodGl0bGVUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGVUcmFuc1sxXSArPSAoMSAtIG5saW5lcykgKiBsaW5lU2l6ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aXRsZUdyb3VwLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIHRpdGxlVHJhbnMgKyAnKScpO1xuICAgICAgICAgICAgICAgIGF4LnNldFNjYWxlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBnLnNlbGVjdEFsbCgnLicgKyBjbi5jYmZpbGxzICsgJywuJyArIGNuLmNibGluZXMpXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgwLCcgKyBNYXRoLnJvdW5kKGdzLmggKiAoMSAtIGF4LmRvbWFpblsxXSkpICsgJyknKTtcblxuICAgICAgICBheExheWVyLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMCwnICsgTWF0aC5yb3VuZCgtZ3MudCkgKyAnKScpO1xuXG4gICAgICAgIHZhciBmaWxscyA9IGcuc2VsZWN0KCcuJyArIGNuLmNiZmlsbHMpXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCdyZWN0LicgKyBjbi5jYmZpbGwpXG4gICAgICAgICAgICAuZGF0YShmaWxsTGV2ZWxzKTtcbiAgICAgICAgZmlsbHMuZW50ZXIoKS5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAgICAgLmNsYXNzZWQoY24uY2JmaWxsLCB0cnVlKVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2UnLCAnbm9uZScpO1xuICAgICAgICBmaWxscy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgdmFyIHpCb3VuZHMgPSB6cmFuZ2VcbiAgICAgICAgICAgIC5tYXAoYXguYzJwKVxuICAgICAgICAgICAgLm1hcChNYXRoLnJvdW5kKVxuICAgICAgICAgICAgLnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYSAtIGI7IH0pO1xuXG4gICAgICAgIGZpbGxzLmVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgdmFyIHogPSBbXG4gICAgICAgICAgICAgICAgKGkgPT09IDApID8genJhbmdlWzBdIDogKGZpbGxMZXZlbHNbaV0gKyBmaWxsTGV2ZWxzW2kgLSAxXSkgLyAyLFxuICAgICAgICAgICAgICAgIChpID09PSBmaWxsTGV2ZWxzLmxlbmd0aCAtIDEpID8genJhbmdlWzFdIDogKGZpbGxMZXZlbHNbaV0gKyBmaWxsTGV2ZWxzW2kgKyAxXSkgLyAyXG4gICAgICAgICAgICBdXG4gICAgICAgICAgICAubWFwKGF4LmMycClcbiAgICAgICAgICAgIC5tYXAoTWF0aC5yb3VuZCk7XG5cbiAgICAgICAgICAgIC8vIG9mZnNldCB0aGUgc2lkZSBhZGpvaW5pbmcgdGhlIG5leHQgcmVjdGFuZ2xlIHNvIHRoZXlcbiAgICAgICAgICAgIC8vIG92ZXJsYXAsIHRvIHByZXZlbnQgYW50aWFsaWFzaW5nIGdhcHNcbiAgICAgICAgICAgIHpbMV0gPSBMaWIuY29uc3RyYWluKHpbMV0gKyAoelsxXSA+IHpbMF0pID8gMSA6IC0xLCB6Qm91bmRzWzBdLCB6Qm91bmRzWzFdKTtcblxuXG4gICAgICAgICAgICAvLyBDb2xvcmJhciBjYW5ub3QgY3VycmVudGx5IHN1cHBvcnQgb3BhY2l0aWVzIHNvIHdlXG4gICAgICAgICAgICAvLyB1c2UgYW4gb3BhcXVlIGZpbGwgZXZlbiB3aGVuIGFscGhhIGNoYW5uZWxzIHByZXNlbnRcbiAgICAgICAgICAgIHZhciBmaWxsRWwgPSBkMy5zZWxlY3QodGhpcykuYXR0cih7XG4gICAgICAgICAgICAgICAgeDogeExlZnQsXG4gICAgICAgICAgICAgICAgd2lkdGg6IE1hdGgubWF4KHRoaWNrUHgsIDIpLFxuICAgICAgICAgICAgICAgIHk6IGQzLm1pbih6KSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IE1hdGgubWF4KGQzLm1heCh6KSAtIGQzLm1pbih6KSwgMiksXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYob3B0cy5fZmlsbGdyYWRpZW50KSB7XG4gICAgICAgICAgICAgICAgRHJhd2luZy5ncmFkaWVudChmaWxsRWwsIGdkLCBvcHRzLl9pZCwgJ3ZlcnRpY2FsJywgb3B0cy5fZmlsbGdyYWRpZW50LCAnZmlsbCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyB0aW55Y29sb3IgY2FuJ3QgaGFuZGxlIGV4cG9uZW50cyBhbmRcbiAgICAgICAgICAgICAgICAvLyBhdCB0aGlzIHNjYWxlLCByZW1vdmluZyBpdCBtYWtlcyBubyBkaWZmZXJlbmNlLlxuICAgICAgICAgICAgICAgIHZhciBjb2xvclN0cmluZyA9IGZpbGxDb2xvcm1hcChkKS5yZXBsYWNlKCdlLScsICcnKTtcbiAgICAgICAgICAgICAgICBmaWxsRWwuYXR0cignZmlsbCcsIHRpbnljb2xvcihjb2xvclN0cmluZykudG9IZXhTdHJpbmcoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBsaW5lcyA9IGcuc2VsZWN0KCcuJyArIGNuLmNibGluZXMpXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCdwYXRoLicgKyBjbi5jYmxpbmUpXG4gICAgICAgICAgICAuZGF0YShsaW5lLmNvbG9yICYmIGxpbmUud2lkdGggPyBsaW5lTGV2ZWxzIDogW10pO1xuICAgICAgICBsaW5lcy5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAuY2xhc3NlZChjbi5jYmxpbmUsIHRydWUpO1xuICAgICAgICBsaW5lcy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIGxpbmVzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAgICAgLmF0dHIoJ2QnLCAnTScgKyB4TGVmdCArICcsJyArXG4gICAgICAgICAgICAgICAgICAgIChNYXRoLnJvdW5kKGF4LmMycChkKSkgKyAobGluZS53aWR0aCAvIDIpICUgMSkgKyAnaCcgKyB0aGlja1B4KVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcubGluZUdyb3VwU3R5bGUsIGxpbmUud2lkdGgsIGxpbmVDb2xvcm1hcChkKSwgbGluZS5kYXNoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gZm9yY2UgZnVsbCByZWRyYXcgb2YgbGFiZWxzIGFuZCB0aWNrc1xuICAgICAgICBheExheWVyLnNlbGVjdEFsbCgnZy4nICsgYXguX2lkICsgJ3RpY2sscGF0aCcpLnJlbW92ZSgpO1xuXG4gICAgICAgIHZhciBzaGlmdCA9IHhMZWZ0ICsgdGhpY2tQeCArXG4gICAgICAgICAgICAob3B0cy5vdXRsaW5ld2lkdGggfHwgMCkgLyAyIC0gKG9wdHMudGlja3MgPT09ICdvdXRzaWRlJyA/IDEgOiAwKTtcblxuICAgICAgICB2YXIgdmFscyA9IEF4ZXMuY2FsY1RpY2tzKGF4KTtcbiAgICAgICAgdmFyIHRyYW5zRm4gPSBBeGVzLm1ha2VUcmFuc0ZuKGF4KTtcbiAgICAgICAgdmFyIHRpY2tTaWduID0gQXhlcy5nZXRUaWNrU2lnbnMoYXgpWzJdO1xuXG4gICAgICAgIEF4ZXMuZHJhd1RpY2tzKGdkLCBheCwge1xuICAgICAgICAgICAgdmFsczogYXgudGlja3MgPT09ICdpbnNpZGUnID8gQXhlcy5jbGlwRW5kcyhheCwgdmFscykgOiB2YWxzLFxuICAgICAgICAgICAgbGF5ZXI6IGF4TGF5ZXIsXG4gICAgICAgICAgICBwYXRoOiBBeGVzLm1ha2VUaWNrUGF0aChheCwgc2hpZnQsIHRpY2tTaWduKSxcbiAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm5cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIEF4ZXMuZHJhd0xhYmVscyhnZCwgYXgsIHtcbiAgICAgICAgICAgIHZhbHM6IHZhbHMsXG4gICAgICAgICAgICBsYXllcjogYXhMYXllcixcbiAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm4sXG4gICAgICAgICAgICBsYWJlbEZuczogQXhlcy5tYWtlTGFiZWxGbnMoYXgsIHNoaWZ0KVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyB3YWl0IGZvciB0aGUgYXhpcyAmIHRpdGxlIHRvIGZpbmlzaCByZW5kZXJpbmcgYmVmb3JlXG4gICAgLy8gY29udGludWluZyBwb3NpdGlvbmluZ1xuICAgIC8vIFRPRE86IHdoeSBhcmUgd2UgcmVkcmF3aW5nIG11bHRpcGxlIHRpbWVzIG5vdyB3aXRoIHRoaXM/XG4gICAgLy8gSSBndWVzcyBhdXRvTWFyZ2luIGRvZXNuJ3QgbGlrZSBiZWluZyBwb3N0LXByb21pc2U/XG4gICAgZnVuY3Rpb24gcG9zaXRpb25DQigpIHtcbiAgICAgICAgdmFyIGlubmVyV2lkdGggPSB0aGlja1B4ICsgb3B0cy5vdXRsaW5ld2lkdGggLyAyICsgRHJhd2luZy5iQm94KGF4TGF5ZXIubm9kZSgpKS53aWR0aDtcbiAgICAgICAgdGl0bGVFbCA9IHRpdGxlQ29udC5zZWxlY3QoJ3RleHQnKTtcblxuICAgICAgICBpZih0aXRsZUVsLm5vZGUoKSAmJiAhdGl0bGVFbC5jbGFzc2VkKGNuLmpzUGxhY2Vob2xkZXIpKSB7XG4gICAgICAgICAgICB2YXIgbWF0aEpheE5vZGUgPSB0aXRsZUNvbnQuc2VsZWN0KCcuaCcgKyBheC5faWQgKyAndGl0bGUtbWF0aC1ncm91cCcpLm5vZGUoKTtcbiAgICAgICAgICAgIHZhciB0aXRsZVdpZHRoO1xuICAgICAgICAgICAgaWYobWF0aEpheE5vZGUgJiYgWyd0b3AnLCAnYm90dG9tJ10uaW5kZXhPZih0aXRsZVNpZGUpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHRpdGxlV2lkdGggPSBEcmF3aW5nLmJCb3gobWF0aEpheE5vZGUpLndpZHRoO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBub3RlOiB0aGUgZm9ybXVsYSBiZWxvdyB3b3JrcyBmb3IgYWxsIHRpdGxlIHNpZGVzLFxuICAgICAgICAgICAgICAgIC8vIChleGNlcHQgZm9yIHRvcC9ib3R0b20gbWF0aGpheCwgYWJvdmUpXG4gICAgICAgICAgICAgICAgLy8gYnV0IHRoZSB3ZWlyZCBncy5sIGlzIGJlY2F1c2UgdGhlIHRpdGxldW5zaGlmdFxuICAgICAgICAgICAgICAgIC8vIHRyYW5zZm9ybSBnZXRzIHJlbW92ZWQgYnkgRHJhd2luZy5iQm94XG4gICAgICAgICAgICAgICAgdGl0bGVXaWR0aCA9IERyYXdpbmcuYkJveCh0aXRsZUNvbnQubm9kZSgpKS5yaWdodCAtIHhMZWZ0IC0gZ3MubDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlubmVyV2lkdGggPSBNYXRoLm1heChpbm5lcldpZHRoLCB0aXRsZVdpZHRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBvdXRlcndpZHRoID0gMiAqIG9wdHMueHBhZCArIGlubmVyV2lkdGggKyBvcHRzLmJvcmRlcndpZHRoICsgb3B0cy5vdXRsaW5ld2lkdGggLyAyO1xuICAgICAgICB2YXIgb3V0ZXJoZWlnaHQgPSB5Qm90dG9tUHggLSB5VG9wUHg7XG5cbiAgICAgICAgZy5zZWxlY3QoJy4nICsgY24uY2JiZykuYXR0cih7XG4gICAgICAgICAgICB4OiB4TGVmdCAtIG9wdHMueHBhZCAtIChvcHRzLmJvcmRlcndpZHRoICsgb3B0cy5vdXRsaW5ld2lkdGgpIC8gMixcbiAgICAgICAgICAgIHk6IHlUb3BQeCAtIHlFeHRyYVB4LFxuICAgICAgICAgICAgd2lkdGg6IE1hdGgubWF4KG91dGVyd2lkdGgsIDIpLFxuICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLm1heChvdXRlcmhlaWdodCArIDIgKiB5RXh0cmFQeCwgMilcbiAgICAgICAgfSlcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgb3B0cy5iZ2NvbG9yKVxuICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIG9wdHMuYm9yZGVyY29sb3IpXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgb3B0cy5ib3JkZXJ3aWR0aCk7XG5cbiAgICAgICAgZy5zZWxlY3RBbGwoJy4nICsgY24uY2JvdXRsaW5lKS5hdHRyKHtcbiAgICAgICAgICAgIHg6IHhMZWZ0LFxuICAgICAgICAgICAgeTogeVRvcFB4ICsgb3B0cy55cGFkICsgKHRpdGxlU2lkZSA9PT0gJ3RvcCcgPyB0aXRsZUhlaWdodCA6IDApLFxuICAgICAgICAgICAgd2lkdGg6IE1hdGgubWF4KHRoaWNrUHgsIDIpLFxuICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLm1heChvdXRlcmhlaWdodCAtIDIgKiBvcHRzLnlwYWQgLSB0aXRsZUhlaWdodCwgMilcbiAgICAgICAgfSlcbiAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBvcHRzLm91dGxpbmVjb2xvcilcbiAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgIGZpbGw6ICdub25lJyxcbiAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiBvcHRzLm91dGxpbmV3aWR0aFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBmaXggcG9zaXRpb25pbmcgZm9yIHhhbmNob3IhPSdsZWZ0J1xuICAgICAgICB2YXIgeG9mZnNldCA9ICh7Y2VudGVyOiAwLjUsIHJpZ2h0OiAxfVtvcHRzLnhhbmNob3JdIHx8IDApICogb3V0ZXJ3aWR0aDtcbiAgICAgICAgZy5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyAoZ3MubCAtIHhvZmZzZXQpICsgJywnICsgZ3MudCArICcpJyk7XG5cbiAgICAgICAgLy8gYXV0byBtYXJnaW4gYWRqdXN0bWVudFxuICAgICAgICB2YXIgbWFyZ2luT3B0cyA9IHt9O1xuICAgICAgICB2YXIgdEZyYWMgPSBGUk9NX1RMW29wdHMueWFuY2hvcl07XG4gICAgICAgIHZhciBiRnJhYyA9IEZST01fQlJbb3B0cy55YW5jaG9yXTtcbiAgICAgICAgaWYob3B0cy5sZW5tb2RlID09PSAncGl4ZWxzJykge1xuICAgICAgICAgICAgbWFyZ2luT3B0cy55ID0gb3B0cy55O1xuICAgICAgICAgICAgbWFyZ2luT3B0cy50ID0gb3V0ZXJoZWlnaHQgKiB0RnJhYztcbiAgICAgICAgICAgIG1hcmdpbk9wdHMuYiA9IG91dGVyaGVpZ2h0ICogYkZyYWM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYXJnaW5PcHRzLnQgPSBtYXJnaW5PcHRzLmIgPSAwO1xuICAgICAgICAgICAgbWFyZ2luT3B0cy55dCA9IG9wdHMueSArIG9wdHMubGVuICogdEZyYWM7XG4gICAgICAgICAgICBtYXJnaW5PcHRzLnliID0gb3B0cy55IC0gb3B0cy5sZW4gKiBiRnJhYztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsRnJhYyA9IEZST01fVExbb3B0cy54YW5jaG9yXTtcbiAgICAgICAgdmFyIHJGcmFjID0gRlJPTV9CUltvcHRzLnhhbmNob3JdO1xuICAgICAgICBpZihvcHRzLnRoaWNrbmVzc21vZGUgPT09ICdwaXhlbHMnKSB7XG4gICAgICAgICAgICBtYXJnaW5PcHRzLnggPSBvcHRzLng7XG4gICAgICAgICAgICBtYXJnaW5PcHRzLmwgPSBvdXRlcndpZHRoICogbEZyYWM7XG4gICAgICAgICAgICBtYXJnaW5PcHRzLnIgPSBvdXRlcndpZHRoICogckZyYWM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgZXh0cmFUaGlja25lc3MgPSBvdXRlcndpZHRoIC0gdGhpY2tQeDtcbiAgICAgICAgICAgIG1hcmdpbk9wdHMubCA9IGV4dHJhVGhpY2tuZXNzICogbEZyYWM7XG4gICAgICAgICAgICBtYXJnaW5PcHRzLnIgPSBleHRyYVRoaWNrbmVzcyAqIHJGcmFjO1xuICAgICAgICAgICAgbWFyZ2luT3B0cy54bCA9IG9wdHMueCAtIG9wdHMudGhpY2tuZXNzICogbEZyYWM7XG4gICAgICAgICAgICBtYXJnaW5PcHRzLnhyID0gb3B0cy54ICsgb3B0cy50aGlja25lc3MgKiByRnJhYztcbiAgICAgICAgfVxuXG4gICAgICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsIG9wdHMuX2lkLCBtYXJnaW5PcHRzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gTGliLnN5bmNPckFzeW5jKFtcbiAgICAgICAgUGxvdHMucHJldmlvdXNQcm9taXNlcyxcbiAgICAgICAgZHJhd0R1bW15VGl0bGUsXG4gICAgICAgIGRyYXdBeGlzLFxuICAgICAgICBkcmF3Q2JUaXRsZSxcbiAgICAgICAgUGxvdHMucHJldmlvdXNQcm9taXNlcyxcbiAgICAgICAgcG9zaXRpb25DQlxuICAgIF0sIGdkKTtcbn1cblxuZnVuY3Rpb24gbWFrZUVkaXRhYmxlKGcsIG9wdHMsIGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZ3MgPSBmdWxsTGF5b3V0Ll9zaXplO1xuICAgIHZhciB0MCwgeGYsIHlmO1xuXG4gICAgZHJhZ0VsZW1lbnQuaW5pdCh7XG4gICAgICAgIGVsZW1lbnQ6IGcubm9kZSgpLFxuICAgICAgICBnZDogZ2QsXG4gICAgICAgIHByZXBGbjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB0MCA9IGcuYXR0cigndHJhbnNmb3JtJyk7XG4gICAgICAgICAgICBzZXRDdXJzb3IoZyk7XG4gICAgICAgIH0sXG4gICAgICAgIG1vdmVGbjogZnVuY3Rpb24oZHgsIGR5KSB7XG4gICAgICAgICAgICBnLmF0dHIoJ3RyYW5zZm9ybScsIHQwICsgJyAnICsgJ3RyYW5zbGF0ZSgnICsgZHggKyAnLCcgKyBkeSArICcpJyk7XG5cbiAgICAgICAgICAgIHhmID0gZHJhZ0VsZW1lbnQuYWxpZ24ob3B0cy5feExlZnRGcmFjICsgKGR4IC8gZ3MudyksIG9wdHMuX3RoaWNrRnJhYyxcbiAgICAgICAgICAgICAgICAwLCAxLCBvcHRzLnhhbmNob3IpO1xuICAgICAgICAgICAgeWYgPSBkcmFnRWxlbWVudC5hbGlnbihvcHRzLl95Qm90dG9tRnJhYyAtIChkeSAvIGdzLmgpLCBvcHRzLl9sZW5GcmFjLFxuICAgICAgICAgICAgICAgIDAsIDEsIG9wdHMueWFuY2hvcik7XG5cbiAgICAgICAgICAgIHZhciBjc3IgPSBkcmFnRWxlbWVudC5nZXRDdXJzb3IoeGYsIHlmLCBvcHRzLnhhbmNob3IsIG9wdHMueWFuY2hvcik7XG4gICAgICAgICAgICBzZXRDdXJzb3IoZywgY3NyKTtcbiAgICAgICAgfSxcbiAgICAgICAgZG9uZUZuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHNldEN1cnNvcihnKTtcblxuICAgICAgICAgICAgaWYoeGYgIT09IHVuZGVmaW5lZCAmJiB5ZiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0ZSA9IHt9O1xuICAgICAgICAgICAgICAgIHVwZGF0ZVtvcHRzLl9wcm9wUHJlZml4ICsgJ3gnXSA9IHhmO1xuICAgICAgICAgICAgICAgIHVwZGF0ZVtvcHRzLl9wcm9wUHJlZml4ICsgJ3knXSA9IHlmO1xuICAgICAgICAgICAgICAgIGlmKG9wdHMuX3RyYWNlSW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVzdHlsZScsIGdkLCB1cGRhdGUsIG9wdHMuX3RyYWNlSW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCB1cGRhdGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBjYWxjTGV2ZWxzKGdkLCBvcHRzLCB6cmFuZ2UpIHtcbiAgICB2YXIgbGV2ZWxzSW4gPSBvcHRzLl9sZXZlbHM7XG4gICAgdmFyIGxpbmVMZXZlbHMgPSBbXTtcbiAgICB2YXIgZmlsbExldmVscyA9IFtdO1xuICAgIHZhciBsO1xuICAgIHZhciBpO1xuXG4gICAgdmFyIGwwID0gbGV2ZWxzSW4uZW5kICsgbGV2ZWxzSW4uc2l6ZSAvIDEwMDtcbiAgICB2YXIgbHMgPSBsZXZlbHNJbi5zaXplO1xuICAgIHZhciB6cjAgPSAoMS4wMDEgKiB6cmFuZ2VbMF0gLSAwLjAwMSAqIHpyYW5nZVsxXSk7XG4gICAgdmFyIHpyMSA9ICgxLjAwMSAqIHpyYW5nZVsxXSAtIDAuMDAxICogenJhbmdlWzBdKTtcblxuICAgIGZvcihpID0gMDsgaSA8IDFlNTsgaSsrKSB7XG4gICAgICAgIGwgPSBsZXZlbHNJbi5zdGFydCArIGkgKiBscztcbiAgICAgICAgaWYobHMgPiAwID8gKGwgPj0gbDApIDogKGwgPD0gbDApKSBicmVhaztcbiAgICAgICAgaWYobCA+IHpyMCAmJiBsIDwgenIxKSBsaW5lTGV2ZWxzLnB1c2gobCk7XG4gICAgfVxuXG4gICAgaWYob3B0cy5fZmlsbGdyYWRpZW50KSB7XG4gICAgICAgIGZpbGxMZXZlbHMgPSBbMF07XG4gICAgfSBlbHNlIGlmKHR5cGVvZiBvcHRzLl9maWxsY29sb3IgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdmFyIGZpbGxMZXZlbHNJbiA9IG9wdHMuX2ZpbGxsZXZlbHM7XG5cbiAgICAgICAgaWYoZmlsbExldmVsc0luKSB7XG4gICAgICAgICAgICBsMCA9IGZpbGxMZXZlbHNJbi5lbmQgKyBmaWxsTGV2ZWxzSW4uc2l6ZSAvIDEwMDtcbiAgICAgICAgICAgIGxzID0gZmlsbExldmVsc0luLnNpemU7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCAxZTU7IGkrKykge1xuICAgICAgICAgICAgICAgIGwgPSBmaWxsTGV2ZWxzSW4uc3RhcnQgKyBpICogbHM7XG4gICAgICAgICAgICAgICAgaWYobHMgPiAwID8gKGwgPj0gbDApIDogKGwgPD0gbDApKSBicmVhaztcbiAgICAgICAgICAgICAgICBpZihsID4genJhbmdlWzBdICYmIGwgPCB6cmFuZ2VbMV0pIGZpbGxMZXZlbHMucHVzaChsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZpbGxMZXZlbHMgPSBsaW5lTGV2ZWxzLm1hcChmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHYgLSBsZXZlbHNJbi5zaXplIC8gMjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZmlsbExldmVscy5wdXNoKGZpbGxMZXZlbHNbZmlsbExldmVscy5sZW5ndGggLSAxXSArIGxldmVsc0luLnNpemUpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKG9wdHMuX2ZpbGxjb2xvciAmJiB0eXBlb2Ygb3B0cy5fZmlsbGNvbG9yID09PSAnc3RyaW5nJykge1xuICAgICAgICAvLyBkb2Vzbid0IG1hdHRlciB3aGF0IHRoaXMgdmFsdWUgaXMsIHdpdGggYSBzaW5nbGUgdmFsdWVcbiAgICAgICAgLy8gd2UnbGwgbWFrZSBhIHNpbmdsZSBmaWxsIHJlY3QgY292ZXJpbmcgdGhlIHdob2xlIGJhclxuICAgICAgICBmaWxsTGV2ZWxzID0gWzBdO1xuICAgIH1cblxuICAgIGlmKGxldmVsc0luLnNpemUgPCAwKSB7XG4gICAgICAgIGxpbmVMZXZlbHMucmV2ZXJzZSgpO1xuICAgICAgICBmaWxsTGV2ZWxzLnJldmVyc2UoKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge2xpbmU6IGxpbmVMZXZlbHMsIGZpbGw6IGZpbGxMZXZlbHN9O1xufVxuXG5mdW5jdGlvbiBtb2NrQ29sb3JCYXJBeGlzKGdkLCBvcHRzLCB6cmFuZ2UpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgdmFyIGNiQXhpc0luID0ge1xuICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgcmFuZ2U6IHpyYW5nZSxcbiAgICAgICAgdGlja21vZGU6IG9wdHMudGlja21vZGUsXG4gICAgICAgIG50aWNrczogb3B0cy5udGlja3MsXG4gICAgICAgIHRpY2swOiBvcHRzLnRpY2swLFxuICAgICAgICBkdGljazogb3B0cy5kdGljayxcbiAgICAgICAgdGlja3ZhbHM6IG9wdHMudGlja3ZhbHMsXG4gICAgICAgIHRpY2t0ZXh0OiBvcHRzLnRpY2t0ZXh0LFxuICAgICAgICB0aWNrczogb3B0cy50aWNrcyxcbiAgICAgICAgdGlja2xlbjogb3B0cy50aWNrbGVuLFxuICAgICAgICB0aWNrd2lkdGg6IG9wdHMudGlja3dpZHRoLFxuICAgICAgICB0aWNrY29sb3I6IG9wdHMudGlja2NvbG9yLFxuICAgICAgICBzaG93dGlja2xhYmVsczogb3B0cy5zaG93dGlja2xhYmVscyxcbiAgICAgICAgdGlja2ZvbnQ6IG9wdHMudGlja2ZvbnQsXG4gICAgICAgIHRpY2thbmdsZTogb3B0cy50aWNrYW5nbGUsXG4gICAgICAgIHRpY2tmb3JtYXQ6IG9wdHMudGlja2Zvcm1hdCxcbiAgICAgICAgZXhwb25lbnRmb3JtYXQ6IG9wdHMuZXhwb25lbnRmb3JtYXQsXG4gICAgICAgIHNlcGFyYXRldGhvdXNhbmRzOiBvcHRzLnNlcGFyYXRldGhvdXNhbmRzLFxuICAgICAgICBzaG93ZXhwb25lbnQ6IG9wdHMuc2hvd2V4cG9uZW50LFxuICAgICAgICBzaG93dGlja3ByZWZpeDogb3B0cy5zaG93dGlja3ByZWZpeCxcbiAgICAgICAgdGlja3ByZWZpeDogb3B0cy50aWNrcHJlZml4LFxuICAgICAgICBzaG93dGlja3N1ZmZpeDogb3B0cy5zaG93dGlja3N1ZmZpeCxcbiAgICAgICAgdGlja3N1ZmZpeDogb3B0cy50aWNrc3VmZml4LFxuICAgICAgICB0aXRsZTogb3B0cy50aXRsZSxcbiAgICAgICAgc2hvd2xpbmU6IHRydWUsXG4gICAgICAgIGFuY2hvcjogJ2ZyZWUnLFxuICAgICAgICBzaWRlOiAncmlnaHQnLFxuICAgICAgICBwb3NpdGlvbjogMVxuICAgIH07XG5cbiAgICB2YXIgY2JBeGlzT3V0ID0ge1xuICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgX2lkOiAneScgKyBvcHRzLl9pZFxuICAgIH07XG5cbiAgICB2YXIgYXhpc09wdGlvbnMgPSB7XG4gICAgICAgIGxldHRlcjogJ3knLFxuICAgICAgICBmb250OiBmdWxsTGF5b3V0LmZvbnQsXG4gICAgICAgIG5vSG92ZXI6IHRydWUsXG4gICAgICAgIG5vVGlja3NvbjogdHJ1ZSxcbiAgICAgICAgY2FsZW5kYXI6IGZ1bGxMYXlvdXQuY2FsZW5kYXIgIC8vIG5vdCByZWFsbHkgbmVjZXNzYXJ5ICh5ZXQ/KVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShjYkF4aXNJbiwgY2JBeGlzT3V0LCBheGlzTGF5b3V0QXR0cnMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGhhbmRsZUF4aXNEZWZhdWx0cyhjYkF4aXNJbiwgY2JBeGlzT3V0LCBjb2VyY2UsIGF4aXNPcHRpb25zLCBmdWxsTGF5b3V0KTtcbiAgICBoYW5kbGVBeGlzUG9zaXRpb25EZWZhdWx0cyhjYkF4aXNJbiwgY2JBeGlzT3V0LCBjb2VyY2UsIGF4aXNPcHRpb25zKTtcblxuICAgIHJldHVybiBjYkF4aXNPdXQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGRyYXc6IGRyYXdcbn07XG5cbn0se1wiLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudFwiOjY4OCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9saWIvc2V0Y3Vyc29yXCI6NzM5LFwiLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzXCI6NzQzLFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19kZWZhdWx0c1wiOjc2OSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlc1wiOjc3OSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9wb3NpdGlvbl9kZWZhdWx0c1wiOjc4MixcIi4uLy4uL3Bsb3RzL3Bsb3RzXCI6ODI4LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9jb2xvclwiOjU5MyxcIi4uL2NvbG9yc2NhbGUvaGVscGVyc1wiOjYwNCxcIi4uL2RyYWdlbGVtZW50XCI6NjExLFwiLi4vZHJhd2luZ1wiOjYxNCxcIi4uL3RpdGxlc1wiOjY4MSxcIi4vY29uc3RhbnRzXCI6NTk1LFwiZDNcIjoxNjMsXCJ0aW55Y29sb3IyXCI6NTM3fV0sNTk4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYXNDb2xvcmJhcihjb250YWluZXIpIHtcbiAgICByZXR1cm4gTGliLmlzUGxhaW5PYmplY3QoY29udGFpbmVyLmNvbG9yYmFyKTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sNTk5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogJ2NvbG9yYmFyJyxcblxuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG5cbiAgICBkcmF3OiBfZGVyZXFfKCcuL2RyYXcnKS5kcmF3LFxuICAgIGhhc0NvbG9yYmFyOiBfZGVyZXFfKCcuL2hhc19jb2xvcmJhcicpXG59O1xuXG59LHtcIi4vYXR0cmlidXRlc1wiOjU5NCxcIi4vZGVmYXVsdHNcIjo1OTYsXCIuL2RyYXdcIjo1OTcsXCIuL2hhc19jb2xvcmJhclwiOjU5OH1dLDYwMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvcmJhckF0dHJzID0gX2RlcmVxXygnLi4vY29sb3JiYXIvYXR0cmlidXRlcycpO1xudmFyIGNvdW50ZXJSZWdleCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9yZWdleCcpLmNvdW50ZXI7XG5cbnZhciBwYWxldHRlcyA9IF9kZXJlcV8oJy4vc2NhbGVzLmpzJykuc2NhbGVzO1xudmFyIHBhbGV0dGVTdHIgPSBPYmplY3Qua2V5cyhwYWxldHRlcyk7XG5cbmZ1bmN0aW9uIGNvZGUocykge1xuICAgIHJldHVybiAnYCcgKyBzICsgJ2AnO1xufVxuXG4vKipcbiAqIE1ha2UgY29sb3JzY2FsZSBhdHRyaWJ1dGUgZGVjbGFyYXRpb25zIGZvclxuICpcbiAqIC0gY29sb3JzY2FsZSxcbiAqIC0gKGN8eilhdXRvLCAoY3x6KW1pbiwgKGN8eiltYXgsXG4gKiAtIGF1dG9jb2xvcnNjYWxlLCByZXZlcnNlc2NhbGUsXG4gKiAtIHNob3dzY2FsZSAob3B0aW9uYWxseSlcbiAqIC0gY29sb3IgKG9wdGlvbmFsbHkpXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbnRleHQgKGRmbHQ6ICcnLCBpLmUuIGZyb20gdHJhY2Ugcm9vdCk6XG4gKiAgICAgdGhlIGNvbnRhaW5lciB0aGlzIGlzIGluICgnJywgKm1hcmtlciosICptYXJrZXIubGluZSogZXRjKVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzOlxuICogICAtIGNMZXR0ZXIge3N0cmluZ30gKGRmbHQ6ICdjJyk6XG4gKiAgICAgbGVhZGluZyBsZXR0ZXIgZm9yICdtaW4nLCAnbWF4IGFuZCAnYXV0bycgYXR0cmlidXRlIChlaXRoZXIgJ3onIG9yICdjJylcbiAqXG4gKiAgIC0gY29sb3JBdHRyIHtzdHJpbmd9IChkZmx0OiAneicgaWYgYGNMZXR0ZXI6ICd6J2AsICdjb2xvcicgaWYgYGNMZXR0ZXI6ICdjJ2ApOlxuICogICAgIChmb3IgZGVzY3JpcHRpb25zKSBzZXRzIHRoZSBuYW1lIG9mIHRoZSBjb2xvciBhdHRyaWJ1dGUgdGhhdCBtYXBzIHRvIHRoZSBjb2xvcnNjYWxlLlxuICpcbiAqICAgICBOLkIuIGlmIGBjb2xvckF0dHI6ICdjb2xvcidgLCB3ZSBpbmNsdWRlIHRoZSBgY29sb3JgIGRlY2xhcmF0aW9uIGhlcmUuXG4gKlxuICogICAtIG9ubHlJZk51bWVyaWNhbCB7c3RyaW5nfSAoZGZsdDogZmFsc2UnIGlmIGBjTGV0dGVyOiAneidgLCB0cnVlIGlmIGBjTGV0dGVyOiAnYydgKTpcbiAqICAgICAoZm9yIGRlc2NyaXB0aW9ucykgc2V0IHRvIHRydWUgaWYgY29sb3JzY2FsZSBhdHRyaWJ1dGUgb25seVxuICpcbiAqICAgLSBjb2xvcnNjYWxlRGZsdCB7c3RyaW5nfTpcbiAqICAgICBvdmVycmlkZXMgdGhlIGNvbG9yc2NhbGUgZGZsdFxuICpcbiAqICAgLSBhdXRvQ29sb3JEZmx0IHtib29sZWFufSAoZGZsdCB0cnVlKTpcbiAqICAgICBub3JtYWxseSBhdXRvY29sb3JzY2FsZS5kZmx0IGlzIGB0cnVlYCwgYnV0IHBhc3MgYGZhbHNlYCB0byBvdmVycmlkZVxuICpcbiAqICAgLSBub1NjYWxlIHtib29sZWFufSAoZGZsdDogdHJ1ZSBpZiBgY29udGV4dDogJ21hcmtlci5saW5lJ2AsIGZhbHNlIG90aGVyd2lzZSk6XG4gKiAgICAgc2V0IHRvIGBmYWxzZWAgdG8gbm90IGluY2x1ZGUgc2hvd3NjYWxlIGF0dHJpYnV0ZSAoZS5nLiBmb3IgJ21hcmtlci5saW5lJylcbiAqXG4gKiAgIC0gc2hvd1NjYWxlRGZsdCB7Ym9vbGVhbn0gKGRmbHQ6IHRydWUgaWYgYGNMZXR0ZXI6ICd6J2AsIGZhbHNlIG90aGVyd2lzZSlcbiAqXG4gKiAgIC0gZWRpdFR5cGVPdmVycmlkZSB7Ym9vbGVhbn0gKGRmbHQ6ICcnKTpcbiAqICAgICBtb3N0IG9mIHRoZXNlIGF0dHJpYnV0ZXMgYWxyZWFkeSByZXF1aXJlIGEgcmVjYWxjLCBidXQgdGhlIG9uZXMgdGhhdCBkbyBub3RcbiAqICAgICBoYXZlIGVkaXRUeXBlICpzdHlsZSogb3IgKnBsb3QqIHVubGVzcyB5b3Ugb3ZlcnJpZGUgKHByZXN1bWFibHkgd2l0aCAqY2FsYyopXG4gKlxuICogICAtIGFuaW0ge2Jvb2xlYW4pIChkZmx0OiB1bmRlZmluZWQpOiBpcyAnY29sb3InIGFuaW1hdGFibGU/XG4gKlxuICogQHJldHVybiB7b2JqZWN0fVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNvbG9yU2NhbGVBdHRycyhjb250ZXh0LCBvcHRzKSB7XG4gICAgY29udGV4dCA9IGNvbnRleHQgfHwgJyc7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICB2YXIgY0xldHRlciA9IG9wdHMuY0xldHRlciB8fCAnYyc7XG4gICAgdmFyIG9ubHlJZk51bWVyaWNhbCA9ICgnb25seUlmTnVtZXJpY2FsJyBpbiBvcHRzKSA/IG9wdHMub25seUlmTnVtZXJpY2FsIDogQm9vbGVhbihjb250ZXh0KTtcbiAgICB2YXIgbm9TY2FsZSA9ICgnbm9TY2FsZScgaW4gb3B0cykgPyBvcHRzLm5vU2NhbGUgOiBjb250ZXh0ID09PSAnbWFya2VyLmxpbmUnO1xuICAgIHZhciBzaG93U2NhbGVEZmx0ID0gKCdzaG93U2NhbGVEZmx0JyBpbiBvcHRzKSA/IG9wdHMuc2hvd1NjYWxlRGZsdCA6IGNMZXR0ZXIgPT09ICd6JztcbiAgICB2YXIgY29sb3JzY2FsZURmbHQgPSB0eXBlb2Ygb3B0cy5jb2xvcnNjYWxlRGZsdCA9PT0gJ3N0cmluZycgPyBwYWxldHRlc1tvcHRzLmNvbG9yc2NhbGVEZmx0XSA6IG51bGw7XG4gICAgdmFyIGVkaXRUeXBlT3ZlcnJpZGUgPSBvcHRzLmVkaXRUeXBlT3ZlcnJpZGUgfHwgJyc7XG4gICAgdmFyIGNvbnRleHRIZWFkID0gY29udGV4dCA/IChjb250ZXh0ICsgJy4nKSA6ICcnO1xuXG4gICAgdmFyIGNvbG9yQXR0ciwgY29sb3JBdHRyRnVsbDtcblxuICAgIGlmKCdjb2xvckF0dHInIGluIG9wdHMpIHtcbiAgICAgICAgY29sb3JBdHRyID0gb3B0cy5jb2xvckF0dHI7XG4gICAgICAgIGNvbG9yQXR0ckZ1bGwgPSBvcHRzLmNvbG9yQXR0cjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb2xvckF0dHIgPSB7ejogJ3onLCBjOiAnY29sb3InfVtjTGV0dGVyXTtcbiAgICAgICAgY29sb3JBdHRyRnVsbCA9ICdpbiAnICsgY29kZShjb250ZXh0SGVhZCArIGNvbG9yQXR0cik7XG4gICAgfVxuXG4gICAgdmFyIGVmZmVjdERlc2MgPSBvbmx5SWZOdW1lcmljYWwgP1xuICAgICAgICAnIEhhcyBhbiBlZmZlY3Qgb25seSBpZiAnICsgY29sb3JBdHRyRnVsbCArICdpcyBzZXQgdG8gYSBudW1lcmljYWwgYXJyYXkuJyA6XG4gICAgICAgICcnO1xuXG4gICAgdmFyIGF1dG8gPSBjTGV0dGVyICsgJ2F1dG8nO1xuICAgIHZhciBtaW4gPSBjTGV0dGVyICsgJ21pbic7XG4gICAgdmFyIG1heCA9IGNMZXR0ZXIgKyAnbWF4JztcbiAgICB2YXIgbWlkID0gY0xldHRlciArICdtaWQnO1xuICAgIHZhciBhdXRvRnVsbCA9IGNvZGUoY29udGV4dEhlYWQgKyBhdXRvKTtcbiAgICB2YXIgbWluRnVsbCA9IGNvZGUoY29udGV4dEhlYWQgKyBtaW4pO1xuICAgIHZhciBtYXhGdWxsID0gY29kZShjb250ZXh0SGVhZCArIG1heCk7XG4gICAgdmFyIG1pbm1heEZ1bGwgPSBtaW5GdWxsICsgJyBhbmQgJyArIG1heEZ1bGw7XG4gICAgdmFyIGF1dG9JbXBsaWVkRWRpdHMgPSB7fTtcbiAgICBhdXRvSW1wbGllZEVkaXRzW21pbl0gPSBhdXRvSW1wbGllZEVkaXRzW21heF0gPSB1bmRlZmluZWQ7XG4gICAgdmFyIG1pbm1heEltcGxpZWRFZGl0cyA9IHt9O1xuICAgIG1pbm1heEltcGxpZWRFZGl0c1thdXRvXSA9IGZhbHNlO1xuXG4gICAgdmFyIGF0dHJzID0ge307XG5cbiAgICBpZihjb2xvckF0dHIgPT09ICdjb2xvcicpIHtcbiAgICAgICAgYXR0cnMuY29sb3IgPSB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6IGVkaXRUeXBlT3ZlcnJpZGUgfHwgJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmKG9wdHMuYW5pbSkge1xuICAgICAgICAgICAgYXR0cnMuY29sb3IuYW5pbSA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhdHRyc1thdXRvXSA9IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiBhdXRvSW1wbGllZEVkaXRzLFxuICAgICAgICBcbiAgICB9O1xuXG4gICAgYXR0cnNbbWluXSA9IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBlZGl0VHlwZTogZWRpdFR5cGVPdmVycmlkZSB8fCAncGxvdCcsXG4gICAgICAgIGltcGxpZWRFZGl0czogbWlubWF4SW1wbGllZEVkaXRzLFxuICAgICAgICBcbiAgICB9O1xuXG4gICAgYXR0cnNbbWF4XSA9IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBlZGl0VHlwZTogZWRpdFR5cGVPdmVycmlkZSB8fCAncGxvdCcsXG4gICAgICAgIGltcGxpZWRFZGl0czogbWlubWF4SW1wbGllZEVkaXRzLFxuICAgICAgICBcbiAgICB9O1xuXG4gICAgYXR0cnNbbWlkXSA9IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBpbXBsaWVkRWRpdHM6IGF1dG9JbXBsaWVkRWRpdHMsXG4gICAgICAgIFxuICAgIH07XG5cbiAgICBhdHRycy5jb2xvcnNjYWxlID0ge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3JzY2FsZScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBkZmx0OiBjb2xvcnNjYWxlRGZsdCxcbiAgICAgICAgaW1wbGllZEVkaXRzOiB7YXV0b2NvbG9yc2NhbGU6IGZhbHNlfSxcbiAgICAgICAgXG4gICAgfTtcblxuICAgIGF0dHJzLmF1dG9jb2xvcnNjYWxlID0ge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICAvLyBnZXRzIG92ZXJyb2RlIGluICdoZWF0bWFwJyAmICdzdXJmYWNlJyBmb3IgYmFja3dhcmRzIGNvbXAuXG4gICAgICAgIGRmbHQ6IG9wdHMuYXV0b0NvbG9yRGZsdCA9PT0gZmFsc2UgPyBmYWxzZSA6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGltcGxpZWRFZGl0czoge2NvbG9yc2NhbGU6IHVuZGVmaW5lZH0sXG4gICAgICAgIFxuICAgIH07XG5cbiAgICBhdHRycy5yZXZlcnNlc2NhbGUgPSB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9O1xuXG4gICAgaWYoIW5vU2NhbGUpIHtcbiAgICAgICAgYXR0cnMuc2hvd3NjYWxlID0ge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiBzaG93U2NhbGVEZmx0LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9O1xuXG4gICAgICAgIGF0dHJzLmNvbG9yYmFyID0gY29sb3JiYXJBdHRycztcbiAgICB9XG5cbiAgICBpZighb3B0cy5ub0NvbG9yQXhpcykge1xuICAgICAgICBhdHRycy5jb2xvcmF4aXMgPSB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3VicGxvdGlkJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgcmVnZXg6IGNvdW50ZXJSZWdleCgnY29sb3JheGlzJyksXG4gICAgICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBhdHRycztcbn07XG5cbn0se1wiLi4vLi4vbGliL3JlZ2V4XCI6NzM1LFwiLi4vY29sb3JiYXIvYXR0cmlidXRlc1wiOjU5NCxcIi4vc2NhbGVzLmpzXCI6NjA4fV0sNjAxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBleHRyYWN0T3B0cyA9IF9kZXJlcV8oJy4vaGVscGVycycpLmV4dHJhY3RPcHRzO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlLCBvcHRzKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgdmFscyA9IG9wdHMudmFscztcbiAgICB2YXIgY29udGFpbmVyU3RyID0gb3B0cy5jb250YWluZXJTdHI7XG5cbiAgICB2YXIgY29udGFpbmVyID0gY29udGFpbmVyU3RyID9cbiAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBjb250YWluZXJTdHIpLmdldCgpIDpcbiAgICAgICAgdHJhY2U7XG5cbiAgICB2YXIgY09wdHMgPSBleHRyYWN0T3B0cyhjb250YWluZXIpO1xuICAgIHZhciBhdXRvID0gY09wdHMuYXV0byAhPT0gZmFsc2U7XG4gICAgdmFyIG1pbiA9IGNPcHRzLm1pbjtcbiAgICB2YXIgbWF4ID0gY09wdHMubWF4O1xuICAgIHZhciBtaWQgPSBjT3B0cy5taWQ7XG5cbiAgICB2YXIgbWluVmFsID0gZnVuY3Rpb24oKSB7IHJldHVybiBMaWIuYWdnTnVtcyhNYXRoLm1pbiwgbnVsbCwgdmFscyk7IH07XG4gICAgdmFyIG1heFZhbCA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gTGliLmFnZ051bXMoTWF0aC5tYXgsIG51bGwsIHZhbHMpOyB9O1xuXG4gICAgaWYobWluID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbWluID0gbWluVmFsKCk7XG4gICAgfSBlbHNlIGlmKGF1dG8pIHtcbiAgICAgICAgaWYoY29udGFpbmVyLl9jb2xvckF4ICYmIGlzTnVtZXJpYyhtaW4pKSB7XG4gICAgICAgICAgICBtaW4gPSBNYXRoLm1pbihtaW4sIG1pblZhbCgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1pbiA9IG1pblZhbCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYobWF4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbWF4ID0gbWF4VmFsKCk7XG4gICAgfSBlbHNlIGlmKGF1dG8pIHtcbiAgICAgICAgaWYoY29udGFpbmVyLl9jb2xvckF4ICYmIGlzTnVtZXJpYyhtYXgpKSB7XG4gICAgICAgICAgICBtYXggPSBNYXRoLm1heChtYXgsIG1heFZhbCgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1heCA9IG1heFZhbCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoYXV0byAmJiBtaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZihtYXggLSBtaWQgPiBtaWQgLSBtaW4pIHtcbiAgICAgICAgICAgIG1pbiA9IG1pZCAtIChtYXggLSBtaWQpO1xuICAgICAgICB9IGVsc2UgaWYobWF4IC0gbWlkIDwgbWlkIC0gbWluKSB7XG4gICAgICAgICAgICBtYXggPSBtaWQgKyAobWlkIC0gbWluKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKG1pbiA9PT0gbWF4KSB7XG4gICAgICAgIG1pbiAtPSAwLjU7XG4gICAgICAgIG1heCArPSAwLjU7XG4gICAgfVxuXG4gICAgY09wdHMuX3N5bmMoJ21pbicsIG1pbik7XG4gICAgY09wdHMuX3N5bmMoJ21heCcsIG1heCk7XG5cbiAgICBpZihjT3B0cy5hdXRvY29sb3JzY2FsZSkge1xuICAgICAgICB2YXIgc2NsO1xuICAgICAgICBpZihtaW4gKiBtYXggPCAwKSBzY2wgPSBmdWxsTGF5b3V0LmNvbG9yc2NhbGUuZGl2ZXJnaW5nO1xuICAgICAgICBlbHNlIGlmKG1pbiA+PSAwKSBzY2wgPSBmdWxsTGF5b3V0LmNvbG9yc2NhbGUuc2VxdWVudGlhbDtcbiAgICAgICAgZWxzZSBzY2wgPSBmdWxsTGF5b3V0LmNvbG9yc2NhbGUuc2VxdWVudGlhbG1pbnVzO1xuICAgICAgICBjT3B0cy5fc3luYygnY29sb3JzY2FsZScsIHNjbCk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuL2hlbHBlcnNcIjo2MDQsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDYwMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBoYXNDb2xvcnNjYWxlID0gX2RlcmVxXygnLi9oZWxwZXJzJykuaGFzQ29sb3JzY2FsZTtcbnZhciBleHRyYWN0T3B0cyA9IF9kZXJlcV8oJy4vaGVscGVycycpLmV4dHJhY3RPcHRzO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyb3NzVHJhY2VEZWZhdWx0cyhmdWxsRGF0YSwgZnVsbExheW91dCkge1xuICAgIGZ1bmN0aW9uIHJlcGxhY2UoY29udCwgaykge1xuICAgICAgICB2YXIgdmFsID0gY29udFsnXycgKyBrXTtcbiAgICAgICAgaWYodmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbnRba10gPSB2YWw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZWxpbmtDb2xvckF0dHMob3V0ZXJDb250LCBjYk9wdCkge1xuICAgICAgICB2YXIgY29udCA9IGNiT3B0LmNvbnRhaW5lciA/XG4gICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkob3V0ZXJDb250LCBjYk9wdC5jb250YWluZXIpLmdldCgpIDpcbiAgICAgICAgICAgIG91dGVyQ29udDtcblxuICAgICAgICBpZihjb250KSB7XG4gICAgICAgICAgICBpZihjb250LmNvbG9yYXhpcykge1xuICAgICAgICAgICAgICAgIC8vIHN0YXNoIHJlZiB0byBjb2xvciBheGlzXG4gICAgICAgICAgICAgICAgY29udC5fY29sb3JBeCA9IGZ1bGxMYXlvdXRbY29udC5jb2xvcmF4aXNdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgY09wdHMgPSBleHRyYWN0T3B0cyhjb250KTtcbiAgICAgICAgICAgICAgICB2YXIgaXNBdXRvID0gY09wdHMuYXV0bztcblxuICAgICAgICAgICAgICAgIGlmKGlzQXV0byB8fCBjT3B0cy5taW4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXBsYWNlKGNvbnQsIGNiT3B0Lm1pbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKGlzQXV0byB8fCBjT3B0cy5tYXggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXBsYWNlKGNvbnQsIGNiT3B0Lm1heCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKGNPcHRzLmF1dG9jb2xvcnNjYWxlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcGxhY2UoY29udCwgJ2NvbG9yc2NhbGUnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG4gICAgICAgIHZhciBjYk9wdHMgPSB0cmFjZS5fbW9kdWxlLmNvbG9yYmFyO1xuXG4gICAgICAgIGlmKGNiT3B0cykge1xuICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShjYk9wdHMpKSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNiT3B0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICByZWxpbmtDb2xvckF0dHModHJhY2UsIGNiT3B0c1tqXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZWxpbmtDb2xvckF0dHModHJhY2UsIGNiT3B0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlLCAnbWFya2VyLmxpbmUnKSkge1xuICAgICAgICAgICAgcmVsaW5rQ29sb3JBdHRzKHRyYWNlLCB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiAnbWFya2VyLmxpbmUnLFxuICAgICAgICAgICAgICAgIG1pbjogJ2NtaW4nLFxuICAgICAgICAgICAgICAgIG1heDogJ2NtYXgnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcih2YXIgayBpbiBmdWxsTGF5b3V0Ll9jb2xvckF4ZXMpIHtcbiAgICAgICAgcmVsaW5rQ29sb3JBdHRzKGZ1bGxMYXlvdXRba10sIHttaW46ICdjbWluJywgbWF4OiAnY21heCd9KTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4vaGVscGVyc1wiOjYwNH1dLDYwMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgaGFzQ29sb3JiYXIgPSBfZGVyZXFfKCcuLi9jb2xvcmJhci9oYXNfY29sb3JiYXInKTtcbnZhciBjb2xvcmJhckRlZmF1bHRzID0gX2RlcmVxXygnLi4vY29sb3JiYXIvZGVmYXVsdHMnKTtcblxudmFyIGlzVmFsaWRTY2FsZSA9IF9kZXJlcV8oJy4vc2NhbGVzJykuaXNWYWxpZDtcbnZhciB0cmFjZUlzID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKS50cmFjZUlzO1xuXG5mdW5jdGlvbiBucE1heWJlKHBhcmVudENvbnQsIHByZWZpeCkge1xuICAgIHZhciBjb250YWluZXJTdHIgPSBwcmVmaXguc2xpY2UoMCwgcHJlZml4Lmxlbmd0aCAtIDEpO1xuICAgIHJldHVybiBwcmVmaXggP1xuICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkocGFyZW50Q29udCwgY29udGFpbmVyU3RyKS5nZXQoKSB8fCB7fSA6XG4gICAgICAgIHBhcmVudENvbnQ7XG59XG5cbi8qKlxuICogQ29sb3JzY2FsZSAvIGNvbG9yYmFyIGRlZmF1bHQgaGFuZGxlclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYXJlbnRDb250SW4gOiB1c2VyIChpbnB1dCkgcGFyZW50IGNvbnRhaW5lciAoZS5nLiB0cmFjZSBvciBsYXlvdXQgY29sb3JheGlzIG9iamVjdClcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYXJlbnRDb250T3V0IDogZnVsbCBwYXJlbnQgY29udGFpbmVyXG4gKiBAcGFyYW0ge29iamVjdH0gbGF5b3V0IDogKGZ1bGwpIGxheW91dCBvYmplY3RcbiAqIEBwYXJhbSB7Zm59IGNvZXJjZSA6IExpYi5jb2VyY2Ugd3JhcHBlclxuICogQHBhcmFtIHtvYmplY3R9IG9wdHMgOlxuICogLSBwcmVmaXgge3N0cmluZ30gOiBhdHRyIHN0cmluZyBwcmVmaXggdG8gY29sb3JzY2FsZSBjb250YWluZXIgZnJvbSBwYXJlbnQgcm9vdFxuICogLSBjTGV0dGVyIHtzdHJpbmd9IDogJ2Mgb3IgJ3onIGNvbG9yIGxldHRlclxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNvbG9yU2NhbGVEZWZhdWx0cyhwYXJlbnRDb250SW4sIHBhcmVudENvbnRPdXQsIGxheW91dCwgY29lcmNlLCBvcHRzKSB7XG4gICAgdmFyIHByZWZpeCA9IG9wdHMucHJlZml4O1xuICAgIHZhciBjTGV0dGVyID0gb3B0cy5jTGV0dGVyO1xuICAgIHZhciBpblRyYWNlID0gJ19tb2R1bGUnIGluIHBhcmVudENvbnRPdXQ7XG4gICAgdmFyIGNvbnRhaW5lckluID0gbnBNYXliZShwYXJlbnRDb250SW4sIHByZWZpeCk7XG4gICAgdmFyIGNvbnRhaW5lck91dCA9IG5wTWF5YmUocGFyZW50Q29udE91dCwgcHJlZml4KTtcbiAgICB2YXIgdGVtcGxhdGUgPSBucE1heWJlKHBhcmVudENvbnRPdXQuX3RlbXBsYXRlIHx8IHt9LCBwcmVmaXgpIHx8IHt9O1xuXG4gICAgLy8gY29sb3JTY2FsZURlZmF1bHRzIHdyYXBwZXIgY2FsbGVkIGlmLWV2ZXIgd2UgbmVlZCB0byByZXNldCB0aGUgY29sb3JzY2FsZVxuICAgIC8vIGF0dHJpYnV0ZXMgZm9yIGNvbnRhaW5lcnMgdGhhdCB3ZXJlIGxpbmtlZCB0byBpbnZhbGlkIGNvbG9yIGF4ZXNcbiAgICB2YXIgdGhpc0ZuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGRlbGV0ZSBwYXJlbnRDb250SW4uY29sb3JheGlzO1xuICAgICAgICBkZWxldGUgcGFyZW50Q29udE91dC5jb2xvcmF4aXM7XG4gICAgICAgIHJldHVybiBjb2xvclNjYWxlRGVmYXVsdHMocGFyZW50Q29udEluLCBwYXJlbnRDb250T3V0LCBsYXlvdXQsIGNvZXJjZSwgb3B0cyk7XG4gICAgfTtcblxuICAgIGlmKGluVHJhY2UpIHtcbiAgICAgICAgdmFyIGNvbG9yQXhlcyA9IGxheW91dC5fY29sb3JBeGVzIHx8IHt9O1xuICAgICAgICB2YXIgY29sb3JBeCA9IGNvZXJjZShwcmVmaXggKyAnY29sb3JheGlzJyk7XG5cbiAgICAgICAgaWYoY29sb3JBeCkge1xuICAgICAgICAgICAgdmFyIGNvbG9yYmFyVmlzdWFscyA9IChcbiAgICAgICAgICAgICAgICB0cmFjZUlzKHBhcmVudENvbnRPdXQsICdjb250b3VyJykgJiZcbiAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkocGFyZW50Q29udE91dCwgJ2NvbnRvdXJzLmNvbG9yaW5nJykuZ2V0KClcbiAgICAgICAgICAgICkgfHwgJ2hlYXRtYXAnO1xuXG4gICAgICAgICAgICB2YXIgc3Rhc2ggPSBjb2xvckF4ZXNbY29sb3JBeF07XG5cbiAgICAgICAgICAgIGlmKHN0YXNoKSB7XG4gICAgICAgICAgICAgICAgc3Rhc2hbMl0ucHVzaCh0aGlzRm4pO1xuXG4gICAgICAgICAgICAgICAgaWYoc3Rhc2hbMF0gIT09IGNvbG9yYmFyVmlzdWFscykge1xuICAgICAgICAgICAgICAgICAgICBzdGFzaFswXSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBMaWIud2FybihbXG4gICAgICAgICAgICAgICAgICAgICAgICAnSWdub3JpbmcgY29sb3JheGlzOicsIGNvbG9yQXgsICdzZXR0aW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICdhcyBpdCBpcyBsaW5rZWQgdG8gaW5jb21wYXRpYmxlIGNvbG9yc2NhbGVzLidcbiAgICAgICAgICAgICAgICAgICAgXS5qb2luKCcgJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gc3Rhc2g6XG4gICAgICAgICAgICAgICAgLy8gLSBjb2xvcmJhciB2aXN1YWwgJ3R5cGUnXG4gICAgICAgICAgICAgICAgLy8gLSBjb2xvcmJhciBvcHRpb25zIHRvIGhlbHAgaW4gQ29sb3JiYXIuZHJhd1xuICAgICAgICAgICAgICAgIC8vIC0gbGlzdCBvZiBjb2xvclNjYWxlRGVmYXVsdHMgd3JhcHBlciBmdW5jdGlvbnNcbiAgICAgICAgICAgICAgICBjb2xvckF4ZXNbY29sb3JBeF0gPSBbY29sb3JiYXJWaXN1YWxzLCBwYXJlbnRDb250T3V0LCBbdGhpc0ZuXV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbWluSW4gPSBjb250YWluZXJJbltjTGV0dGVyICsgJ21pbiddO1xuICAgIHZhciBtYXhJbiA9IGNvbnRhaW5lckluW2NMZXR0ZXIgKyAnbWF4J107XG4gICAgdmFyIHZhbGlkTWluTWF4ID0gaXNOdW1lcmljKG1pbkluKSAmJiBpc051bWVyaWMobWF4SW4pICYmIChtaW5JbiA8IG1heEluKTtcbiAgICB2YXIgYXV0byA9IGNvZXJjZShwcmVmaXggKyBjTGV0dGVyICsgJ2F1dG8nLCAhdmFsaWRNaW5NYXgpO1xuXG4gICAgaWYoYXV0bykge1xuICAgICAgICBjb2VyY2UocHJlZml4ICsgY0xldHRlciArICdtaWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb2VyY2UocHJlZml4ICsgY0xldHRlciArICdtaW4nKTtcbiAgICAgICAgY29lcmNlKHByZWZpeCArIGNMZXR0ZXIgKyAnbWF4Jyk7XG4gICAgfVxuXG4gICAgLy8gaGFuZGxlcyBib3RoIHRoZSB0cmFjZSBjYXNlIChhdXRvY29sb3JzY2FsZSBpcyBmYWxzZSBieSBkZWZhdWx0KSBhbmRcbiAgICAvLyB0aGUgbWFya2VyIGFuZCBtYXJrZXIubGluZSBjYXNlIChhdXRvY29sb3JzY2FsZSBpcyB0cnVlIGJ5IGRlZmF1bHQpXG4gICAgdmFyIHNjbEluID0gY29udGFpbmVySW4uY29sb3JzY2FsZTtcbiAgICB2YXIgc2NsVGVtcGxhdGUgPSB0ZW1wbGF0ZS5jb2xvcnNjYWxlO1xuICAgIHZhciBhdXRvQ29sb3JzY2FsZURmbHQ7XG4gICAgaWYoc2NsSW4gIT09IHVuZGVmaW5lZCkgYXV0b0NvbG9yc2NhbGVEZmx0ID0gIWlzVmFsaWRTY2FsZShzY2xJbik7XG4gICAgaWYoc2NsVGVtcGxhdGUgIT09IHVuZGVmaW5lZCkgYXV0b0NvbG9yc2NhbGVEZmx0ID0gIWlzVmFsaWRTY2FsZShzY2xUZW1wbGF0ZSk7XG4gICAgY29lcmNlKHByZWZpeCArICdhdXRvY29sb3JzY2FsZScsIGF1dG9Db2xvcnNjYWxlRGZsdCk7XG5cbiAgICBjb2VyY2UocHJlZml4ICsgJ2NvbG9yc2NhbGUnKTtcbiAgICBjb2VyY2UocHJlZml4ICsgJ3JldmVyc2VzY2FsZScpO1xuXG4gICAgaWYocHJlZml4ICE9PSAnbWFya2VyLmxpbmUuJykge1xuICAgICAgICAvLyBoYW5kbGVzIGJvdGggdGhlIHRyYWNlIGNhc2Ugd2hlcmUgdGhlIGRmbHQgaXMgbGlzdGVkIGluIGF0dHJpYnV0ZXMgYW5kXG4gICAgICAgIC8vIHRoZSBtYXJrZXIgY2FzZSB3aGVyZSB0aGUgZGZsdCBpcyBkZXRlcm1pbmVkIGJ5IGhhc0NvbG9yYmFyXG4gICAgICAgIHZhciBzaG93U2NhbGVEZmx0O1xuICAgICAgICBpZihwcmVmaXggJiYgaW5UcmFjZSkgc2hvd1NjYWxlRGZsdCA9IGhhc0NvbG9yYmFyKGNvbnRhaW5lckluKTtcblxuICAgICAgICB2YXIgc2hvd1NjYWxlID0gY29lcmNlKHByZWZpeCArICdzaG93c2NhbGUnLCBzaG93U2NhbGVEZmx0KTtcbiAgICAgICAgaWYoc2hvd1NjYWxlKSBjb2xvcmJhckRlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGxheW91dCk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4uL2NvbG9yYmFyL2RlZmF1bHRzXCI6NTk2LFwiLi4vY29sb3JiYXIvaGFzX2NvbG9yYmFyXCI6NTk4LFwiLi9zY2FsZXNcIjo2MDgsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDYwNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgdGlueWNvbG9yID0gX2RlcmVxXygndGlueWNvbG9yMicpO1xudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uL2NvbG9yJyk7XG5cbnZhciBpc1ZhbGlkU2NhbGUgPSBfZGVyZXFfKCcuL3NjYWxlcycpLmlzVmFsaWQ7XG5cbmZ1bmN0aW9uIGhhc0NvbG9yc2NhbGUodHJhY2UsIGNvbnRhaW5lclN0cikge1xuICAgIHZhciBjb250YWluZXIgPSBjb250YWluZXJTdHIgP1xuICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkodHJhY2UsIGNvbnRhaW5lclN0cikuZ2V0KCkgfHwge30gOlxuICAgICAgICB0cmFjZTtcbiAgICB2YXIgY29sb3IgPSBjb250YWluZXIuY29sb3I7XG5cbiAgICB2YXIgaXNBcnJheVdpdGhPbmVOdW1iZXIgPSBmYWxzZTtcbiAgICBpZihMaWIuaXNBcnJheU9yVHlwZWRBcnJheShjb2xvcikpIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNvbG9yLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihpc051bWVyaWMoY29sb3JbaV0pKSB7XG4gICAgICAgICAgICAgICAgaXNBcnJheVdpdGhPbmVOdW1iZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIChcbiAgICAgICAgTGliLmlzUGxhaW5PYmplY3QoY29udGFpbmVyKSAmJiAoXG4gICAgICAgICAgICBpc0FycmF5V2l0aE9uZU51bWJlciB8fFxuICAgICAgICAgICAgY29udGFpbmVyLnNob3dzY2FsZSA9PT0gdHJ1ZSB8fFxuICAgICAgICAgICAgKGlzTnVtZXJpYyhjb250YWluZXIuY21pbikgJiYgaXNOdW1lcmljKGNvbnRhaW5lci5jbWF4KSkgfHxcbiAgICAgICAgICAgIGlzVmFsaWRTY2FsZShjb250YWluZXIuY29sb3JzY2FsZSkgfHxcbiAgICAgICAgICAgIExpYi5pc1BsYWluT2JqZWN0KGNvbnRhaW5lci5jb2xvcmJhcilcbiAgICAgICAgKVxuICAgICk7XG59XG5cbnZhciBjb25zdGFudEF0dHJzID0gWydzaG93c2NhbGUnLCAnYXV0b2NvbG9yc2NhbGUnLCAnY29sb3JzY2FsZScsICdyZXZlcnNlc2NhbGUnLCAnY29sb3JiYXInXTtcbnZhciBsZXR0ZXJBdHRycyA9IFsnbWluJywgJ21heCcsICdtaWQnLCAnYXV0byddO1xuXG4vKipcbiAqIEV4dHJhY3QgJ2MnIC8gJ3onLCB0cmFjZSAvIGNvbG9yIGF4aXMgY29sb3JzY2FsZSBvcHRpb25zXG4gKlxuICogTm90ZSB0aGF0IGl0IHdvdWxkIGJlIG5pY2UgdG8gcmVwbGFjZSBhbGwgeiogd2l0aCBjKiBlcXVpdmFsZW50cyBpbiB2MlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb250IDogYXR0cmlidXRlIGNvbnRhaW5lclxuICogQHJldHVybiB7b2JqZWN0fTpcbiAqICAtIG1pbjogY21pbiBvciB6bWluXG4gKiAgLSBtYXg6IGNtYXggb3Igem1heFxuICogIC0gbWlkOiBjbWlkIG9yIHptaWRcbiAqICAtIGF1dG86IGNhdXRvIG9yIHphdXRvXG4gKiAgLSAqc2NhbGU6ICpzY2FsZSBhdHRyc1xuICogIC0gY29sb3JiYXI6IGNvbG9yYmFyXG4gKiAgLSBfc3luYzogZnVuY3Rpb24gc3luY2luZyBhdHRyIGFuZCB1bmRlcnNjb3JlIGR1YWwgKHVzZWZ1bCB3aGVuIGNhbGMnaW5nIG1pbi9tYXgpXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RPcHRzKGNvbnQpIHtcbiAgICB2YXIgY29sb3JBeCA9IGNvbnQuX2NvbG9yQXg7XG4gICAgdmFyIGNvbnQyID0gY29sb3JBeCA/IGNvbG9yQXggOiBjb250O1xuICAgIHZhciBvdXQgPSB7fTtcbiAgICB2YXIgY0xldHRlcjtcbiAgICB2YXIgaSwgaztcblxuICAgIGZvcihpID0gMDsgaSA8IGNvbnN0YW50QXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgayA9IGNvbnN0YW50QXR0cnNbaV07XG4gICAgICAgIG91dFtrXSA9IGNvbnQyW2tdO1xuICAgIH1cblxuICAgIGlmKGNvbG9yQXgpIHtcbiAgICAgICAgY0xldHRlciA9ICdjJztcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGV0dGVyQXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGsgPSBsZXR0ZXJBdHRyc1tpXTtcbiAgICAgICAgICAgIG91dFtrXSA9IGNvbnQyWydjJyArIGtdO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGsyO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZXR0ZXJBdHRycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgayA9IGxldHRlckF0dHJzW2ldO1xuICAgICAgICAgICAgazIgPSAnYycgKyBrO1xuICAgICAgICAgICAgaWYoazIgaW4gY29udDIpIHtcbiAgICAgICAgICAgICAgICBvdXRba10gPSBjb250MltrMl07XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBrMiA9ICd6JyArIGs7XG4gICAgICAgICAgICBpZihrMiBpbiBjb250Mikge1xuICAgICAgICAgICAgICAgIG91dFtrXSA9IGNvbnQyW2syXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjTGV0dGVyID0gazIuY2hhckF0KDApO1xuICAgIH1cblxuICAgIG91dC5fc3luYyA9IGZ1bmN0aW9uKGssIHYpIHtcbiAgICAgICAgdmFyIGsyID0gbGV0dGVyQXR0cnMuaW5kZXhPZihrKSAhPT0gLTEgPyBjTGV0dGVyICsgayA6IGs7XG4gICAgICAgIGNvbnQyW2syXSA9IGNvbnQyWydfJyArIGsyXSA9IHY7XG4gICAgfTtcblxuICAgIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogRXh0cmFjdCBjb2xvcnNjYWxlIGludG8gbnVtZXJpYyBkb21haW4gYW5kIGNvbG9yIHJhbmdlLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb250IGNvbG9yc2NhbGUgY29udGFpbmVyIChlLmcuIHRyYWNlLCBtYXJrZXIpXG4gKiAgLSBjb2xvcnNjYWxlIHthcnJheSBvZiBhcnJheXN9XG4gKiAgLSBjbWluL3ptaW4ge251bWJlcn1cbiAqICAtIGNtYXgvem1heCB7bnVtYmVyfVxuICogIC0gcmV2ZXJzZXNjYWxlIHtib29sZWFufVxuICpcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqICAtIGRvbWFpbiB7YXJyYXl9XG4gKiAgLSByYW5nZSB7YXJyYXl9XG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RTY2FsZShjb250KSB7XG4gICAgdmFyIGNPcHRzID0gZXh0cmFjdE9wdHMoY29udCk7XG4gICAgdmFyIGNtaW4gPSBjT3B0cy5taW47XG4gICAgdmFyIGNtYXggPSBjT3B0cy5tYXg7XG5cbiAgICB2YXIgc2NsID0gY09wdHMucmV2ZXJzZXNjYWxlID9cbiAgICAgICAgZmxpcFNjYWxlKGNPcHRzLmNvbG9yc2NhbGUpIDpcbiAgICAgICAgY09wdHMuY29sb3JzY2FsZTtcblxuICAgIHZhciBOID0gc2NsLmxlbmd0aDtcbiAgICB2YXIgZG9tYWluID0gbmV3IEFycmF5KE4pO1xuICAgIHZhciByYW5nZSA9IG5ldyBBcnJheShOKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBOOyBpKyspIHtcbiAgICAgICAgdmFyIHNpID0gc2NsW2ldO1xuICAgICAgICBkb21haW5baV0gPSBjbWluICsgc2lbMF0gKiAoY21heCAtIGNtaW4pO1xuICAgICAgICByYW5nZVtpXSA9IHNpWzFdO1xuICAgIH1cblxuICAgIHJldHVybiB7ZG9tYWluOiBkb21haW4sIHJhbmdlOiByYW5nZX07XG59XG5cbmZ1bmN0aW9uIGZsaXBTY2FsZShzY2wpIHtcbiAgICB2YXIgTiA9IHNjbC5sZW5ndGg7XG4gICAgdmFyIHNjbE5ldyA9IG5ldyBBcnJheShOKTtcblxuICAgIGZvcih2YXIgaSA9IE4gLSAxLCBqID0gMDsgaSA+PSAwOyBpLS0sIGorKykge1xuICAgICAgICB2YXIgc2kgPSBzY2xbaV07XG4gICAgICAgIHNjbE5ld1tqXSA9IFsxIC0gc2lbMF0sIHNpWzFdXTtcbiAgICB9XG4gICAgcmV0dXJuIHNjbE5ldztcbn1cblxuLyoqXG4gKiBHZW5lcmFsIGNvbG9yc2NhbGUgZnVuY3Rpb24gZ2VuZXJhdG9yLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBzcGVjcyBvdXRwdXQgb2YgQ29sb3JzY2FsZS5leHRyYWN0U2NhbGUgb3IgcHJlY29tcHV0ZWQgZG9tYWluLCByYW5nZS5cbiAqICAtIGRvbWFpbiB7YXJyYXl9XG4gKiAgLSByYW5nZSB7YXJyYXl9XG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqICAtIG5vTnVtZXJpY0NoZWNrIHtib29sZWFufSBpZiB0cnVlLCBzY2FsZSBmdW5jIGJ5cGFzc2VzIG51bWVyaWMgY2hlY2tzXG4gKiAgLSByZXR1cm5BcnJheSB7Ym9vbGVhbn0gaWYgdHJ1ZSwgc2NhbGUgZnVuYyByZXR1cm4gNC1pdGVtIGFycmF5IGluc3RlYWQgb2YgY29sb3Igc3RyaW5nc1xuICpcbiAqIEByZXR1cm4ge2Z1bmN0aW9ufVxuICovXG5mdW5jdGlvbiBtYWtlQ29sb3JTY2FsZUZ1bmMoc3BlY3MsIG9wdHMpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgIHZhciBkb21haW4gPSBzcGVjcy5kb21haW47XG4gICAgdmFyIHJhbmdlID0gc3BlY3MucmFuZ2U7XG4gICAgdmFyIE4gPSByYW5nZS5sZW5ndGg7XG4gICAgdmFyIF9yYW5nZSA9IG5ldyBBcnJheShOKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBOOyBpKyspIHtcbiAgICAgICAgdmFyIHJnYmEgPSB0aW55Y29sb3IocmFuZ2VbaV0pLnRvUmdiKCk7XG4gICAgICAgIF9yYW5nZVtpXSA9IFtyZ2JhLnIsIHJnYmEuZywgcmdiYS5iLCByZ2JhLmFdO1xuICAgIH1cblxuICAgIHZhciBfc2NsRnVuYyA9IGQzLnNjYWxlLmxpbmVhcigpXG4gICAgICAgIC5kb21haW4oZG9tYWluKVxuICAgICAgICAucmFuZ2UoX3JhbmdlKVxuICAgICAgICAuY2xhbXAodHJ1ZSk7XG5cbiAgICB2YXIgbm9OdW1lcmljQ2hlY2sgPSBvcHRzLm5vTnVtZXJpY0NoZWNrO1xuICAgIHZhciByZXR1cm5BcnJheSA9IG9wdHMucmV0dXJuQXJyYXk7XG4gICAgdmFyIHNjbEZ1bmM7XG5cbiAgICBpZihub051bWVyaWNDaGVjayAmJiByZXR1cm5BcnJheSkge1xuICAgICAgICBzY2xGdW5jID0gX3NjbEZ1bmM7XG4gICAgfSBlbHNlIGlmKG5vTnVtZXJpY0NoZWNrKSB7XG4gICAgICAgIHNjbEZ1bmMgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICByZXR1cm4gY29sb3JBcnJheTJyYmdhKF9zY2xGdW5jKHYpKTtcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYocmV0dXJuQXJyYXkpIHtcbiAgICAgICAgc2NsRnVuYyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIGlmKGlzTnVtZXJpYyh2KSkgcmV0dXJuIF9zY2xGdW5jKHYpO1xuICAgICAgICAgICAgZWxzZSBpZih0aW55Y29sb3IodikuaXNWYWxpZCgpKSByZXR1cm4gdjtcbiAgICAgICAgICAgIGVsc2UgcmV0dXJuIENvbG9yLmRlZmF1bHRMaW5lO1xuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNjbEZ1bmMgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICBpZihpc051bWVyaWModikpIHJldHVybiBjb2xvckFycmF5MnJiZ2EoX3NjbEZ1bmModikpO1xuICAgICAgICAgICAgZWxzZSBpZih0aW55Y29sb3IodikuaXNWYWxpZCgpKSByZXR1cm4gdjtcbiAgICAgICAgICAgIGVsc2UgcmV0dXJuIENvbG9yLmRlZmF1bHRMaW5lO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIGNvbG9yYmFyIGRyYXcgbG9va3MgaW50byB0aGUgZDMgc2NhbGUgY2xvc3VyZSBmb3IgZG9tYWluIGFuZCByYW5nZVxuICAgIHNjbEZ1bmMuZG9tYWluID0gX3NjbEZ1bmMuZG9tYWluO1xuICAgIHNjbEZ1bmMucmFuZ2UgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHJhbmdlOyB9O1xuXG4gICAgcmV0dXJuIHNjbEZ1bmM7XG59XG5cbmZ1bmN0aW9uIG1ha2VDb2xvclNjYWxlRnVuY0Zyb21UcmFjZSh0cmFjZSwgb3B0cykge1xuICAgIHJldHVybiBtYWtlQ29sb3JTY2FsZUZ1bmMoZXh0cmFjdFNjYWxlKHRyYWNlKSwgb3B0cyk7XG59XG5cbmZ1bmN0aW9uIGNvbG9yQXJyYXkycmJnYShjb2xvckFycmF5KSB7XG4gICAgdmFyIGNvbG9yT2JqID0ge1xuICAgICAgICByOiBjb2xvckFycmF5WzBdLFxuICAgICAgICBnOiBjb2xvckFycmF5WzFdLFxuICAgICAgICBiOiBjb2xvckFycmF5WzJdLFxuICAgICAgICBhOiBjb2xvckFycmF5WzNdXG4gICAgfTtcblxuICAgIHJldHVybiB0aW55Y29sb3IoY29sb3JPYmopLnRvUmdiU3RyaW5nKCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhhc0NvbG9yc2NhbGU6IGhhc0NvbG9yc2NhbGUsXG4gICAgZXh0cmFjdE9wdHM6IGV4dHJhY3RPcHRzLFxuICAgIGV4dHJhY3RTY2FsZTogZXh0cmFjdFNjYWxlLFxuICAgIGZsaXBTY2FsZTogZmxpcFNjYWxlLFxuICAgIG1ha2VDb2xvclNjYWxlRnVuYzogbWFrZUNvbG9yU2NhbGVGdW5jLFxuICAgIG1ha2VDb2xvclNjYWxlRnVuY0Zyb21UcmFjZTogbWFrZUNvbG9yU2NhbGVGdW5jRnJvbVRyYWNlXG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2NvbG9yXCI6NTkzLFwiLi9zY2FsZXNcIjo2MDgsXCJkM1wiOjE2MyxcImZhc3QtaXNudW1lcmljXCI6MjI1LFwidGlueWNvbG9yMlwiOjUzN31dLDYwNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2FsZXMgPSBfZGVyZXFfKCcuL3NjYWxlcycpO1xudmFyIGhlbHBlcnMgPSBfZGVyZXFfKCcuL2hlbHBlcnMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogJ2NvbG9yc2NhbGUnLFxuXG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpLFxuXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2RlZmF1bHRzJyksXG4gICAgaGFuZGxlRGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjcm9zc1RyYWNlRGVmYXVsdHM6IF9kZXJlcV8oJy4vY3Jvc3NfdHJhY2VfZGVmYXVsdHMnKSxcblxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLFxuXG4gICAgLy8gLi9zY2FsZXMuanMgaXMgcmVxdWlyZWQgaW4gbGliL2NvZXJjZS5qcyA7XG4gICAgLy8gaXQgbmVlZHMgdG8gYmUgYSBzZXBlcmF0ZSBtb2R1bGUgdG8gYXZvaWQgY2lyY3VsYXIgYSBkZXBlbmRlbmN5XG4gICAgc2NhbGVzOiBzY2FsZXMuc2NhbGVzLFxuICAgIGRlZmF1bHRTY2FsZTogc2NhbGVzLmRlZmF1bHRTY2FsZSxcbiAgICBnZXRTY2FsZTogc2NhbGVzLmdldCxcbiAgICBpc1ZhbGlkU2NhbGU6IHNjYWxlcy5pc1ZhbGlkLFxuXG4gICAgaGFzQ29sb3JzY2FsZTogaGVscGVycy5oYXNDb2xvcnNjYWxlLFxuICAgIGV4dHJhY3RPcHRzOiBoZWxwZXJzLmV4dHJhY3RPcHRzLFxuICAgIGV4dHJhY3RTY2FsZTogaGVscGVycy5leHRyYWN0U2NhbGUsXG4gICAgZmxpcFNjYWxlOiBoZWxwZXJzLmZsaXBTY2FsZSxcbiAgICBtYWtlQ29sb3JTY2FsZUZ1bmM6IGhlbHBlcnMubWFrZUNvbG9yU2NhbGVGdW5jLFxuICAgIG1ha2VDb2xvclNjYWxlRnVuY0Zyb21UcmFjZTogaGVscGVycy5tYWtlQ29sb3JTY2FsZUZ1bmNGcm9tVHJhY2Vcbn07XG5cbn0se1wiLi9hdHRyaWJ1dGVzXCI6NjAwLFwiLi9jYWxjXCI6NjAxLFwiLi9jcm9zc190cmFjZV9kZWZhdWx0c1wiOjYwMixcIi4vZGVmYXVsdHNcIjo2MDMsXCIuL2hlbHBlcnNcIjo2MDQsXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6NjA2LFwiLi9sYXlvdXRfZGVmYXVsdHNcIjo2MDcsXCIuL3NjYWxlc1wiOjYwOH1dLDYwNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBzY2FsZXMgPSBfZGVyZXFfKCcuL3NjYWxlcycpLnNjYWxlcztcblxudmFyIG1zZyA9ICdOb3RlIHRoYXQgYGF1dG9jb2xvcnNjYWxlYCBtdXN0IGJlIHRydWUgZm9yIHRoaXMgYXR0cmlidXRlIHRvIHdvcmsuJztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcblxuICAgIGNvbG9yc2NhbGU6IHtcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcblxuICAgICAgICBzZXF1ZW50aWFsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3JzY2FsZScsXG4gICAgICAgICAgICBkZmx0OiBzY2FsZXMuUmVkcyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzZXF1ZW50aWFsbWludXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcnNjYWxlJyxcbiAgICAgICAgICAgIGRmbHQ6IHNjYWxlcy5CbHVlcyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBkaXZlcmdpbmc6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcnNjYWxlJyxcbiAgICAgICAgICAgIGRmbHQ6IHNjYWxlcy5SZEJ1LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgY29sb3JheGlzOiBleHRlbmRGbGF0KHtcbiAgICAgICAgLy8gbm90IHJlYWxseSBhICdzdWJwbG90JyBhdHRyaWJ1dGUgY29udGFpbmVyLFxuICAgICAgICAvLyBidXQgdGhpcyBpcyB0aGUgZmxhZyB3ZSB1c2UgdG8gZGVub3RlIGF0dHJpYnV0ZXMgdGhhdFxuICAgICAgICAvLyBzdXBwb3J0IHlheGlzLCB5YXhpczIsIHlheGlzMywgLi4uIGNvdW50ZXJzXG4gICAgICAgIF9pc1N1YnBsb3RPYmo6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sIGNvbG9yU2NhbGVBdHRycygnJywge1xuICAgICAgICBjb2xvckF0dHI6ICdjb3JyZXNwb25kaW5nIHRyYWNlIGNvbG9yIGFycmF5KHMpJyxcbiAgICAgICAgbm9Db2xvckF4aXM6IHRydWUsXG4gICAgICAgIHNob3dTY2FsZURmbHQ6IHRydWVcbiAgICB9KSlcbn07XG5cbn0se1wiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4vYXR0cmlidXRlc1wiOjYwMCxcIi4vc2NhbGVzXCI6NjA4fV0sNjA3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIFRlbXBsYXRlID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xuXG52YXIgY29sb3JTY2FsZUF0dHJzID0gX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGNvbG9yU2NhbGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4vZGVmYXVsdHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGF5b3V0SW4sIGxheW91dE91dCwgY29sb3JTY2FsZUF0dHJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2NvbG9yc2NhbGUuc2VxdWVudGlhbCcpO1xuICAgIGNvZXJjZSgnY29sb3JzY2FsZS5zZXF1ZW50aWFsbWludXMnKTtcbiAgICBjb2VyY2UoJ2NvbG9yc2NhbGUuZGl2ZXJnaW5nJyk7XG5cbiAgICB2YXIgY29sb3JBeGVzID0gbGF5b3V0T3V0Ll9jb2xvckF4ZXM7XG4gICAgdmFyIGNvbG9yQXhJbiwgY29sb3JBeE91dDtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZUF4KGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoY29sb3JBeEluLCBjb2xvckF4T3V0LCBjb2xvclNjYWxlQXR0cnMuY29sb3JheGlzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGsgaW4gY29sb3JBeGVzKSB7XG4gICAgICAgIHZhciBzdGFzaCA9IGNvbG9yQXhlc1trXTtcblxuICAgICAgICBpZihzdGFzaFswXSkge1xuICAgICAgICAgICAgY29sb3JBeEluID0gbGF5b3V0SW5ba10gfHwge307XG4gICAgICAgICAgICBjb2xvckF4T3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKGxheW91dE91dCwgaywgJ2NvbG9yYXhpcycpO1xuICAgICAgICAgICAgY29sb3JBeE91dC5fbmFtZSA9IGs7XG4gICAgICAgICAgICBjb2xvclNjYWxlRGVmYXVsdHMoY29sb3JBeEluLCBjb2xvckF4T3V0LCBsYXlvdXRPdXQsIGNvZXJjZUF4LCB7cHJlZml4OiAnJywgY0xldHRlcjogJ2MnfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyByZS1jb2VyY2UgY29sb3JzY2FsZSBhdHRyaWJ1dGVzIHcvbyBjb2xvcmF4aXNcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzdGFzaFsyXS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHN0YXNoWzJdW2ldKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgbGF5b3V0T3V0Ll9jb2xvckF4ZXNba107XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuL2RlZmF1bHRzXCI6NjAzLFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjYwNn1dLDYwODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciB0aW55Y29sb3IgPSBfZGVyZXFfKCd0aW55Y29sb3IyJyk7XG5cbnZhciBzY2FsZXMgPSB7XG4gICAgJ0dyZXlzJzogW1xuICAgICAgICBbMCwgJ3JnYigwLDAsMCknXSwgWzEsICdyZ2IoMjU1LDI1NSwyNTUpJ11cbiAgICBdLFxuXG4gICAgJ1lsR25CdSc6IFtcbiAgICAgICAgWzAsICdyZ2IoOCwyOSw4OCknXSwgWzAuMTI1LCAncmdiKDM3LDUyLDE0OCknXSxcbiAgICAgICAgWzAuMjUsICdyZ2IoMzQsOTQsMTY4KSddLCBbMC4zNzUsICdyZ2IoMjksMTQ1LDE5MiknXSxcbiAgICAgICAgWzAuNSwgJ3JnYig2NSwxODIsMTk2KSddLCBbMC42MjUsICdyZ2IoMTI3LDIwNSwxODcpJ10sXG4gICAgICAgIFswLjc1LCAncmdiKDE5OSwyMzMsMTgwKSddLCBbMC44NzUsICdyZ2IoMjM3LDI0OCwyMTcpJ10sXG4gICAgICAgIFsxLCAncmdiKDI1NSwyNTUsMjE3KSddXG4gICAgXSxcblxuICAgICdHcmVlbnMnOiBbXG4gICAgICAgIFswLCAncmdiKDAsNjgsMjcpJ10sIFswLjEyNSwgJ3JnYigwLDEwOSw0NCknXSxcbiAgICAgICAgWzAuMjUsICdyZ2IoMzUsMTM5LDY5KSddLCBbMC4zNzUsICdyZ2IoNjUsMTcxLDkzKSddLFxuICAgICAgICBbMC41LCAncmdiKDExNiwxOTYsMTE4KSddLCBbMC42MjUsICdyZ2IoMTYxLDIxNywxNTUpJ10sXG4gICAgICAgIFswLjc1LCAncmdiKDE5OSwyMzMsMTkyKSddLCBbMC44NzUsICdyZ2IoMjI5LDI0NSwyMjQpJ10sXG4gICAgICAgIFsxLCAncmdiKDI0NywyNTIsMjQ1KSddXG4gICAgXSxcblxuICAgICdZbE9yUmQnOiBbXG4gICAgICAgIFswLCAncmdiKDEyOCwwLDM4KSddLCBbMC4xMjUsICdyZ2IoMTg5LDAsMzgpJ10sXG4gICAgICAgIFswLjI1LCAncmdiKDIyNywyNiwyOCknXSwgWzAuMzc1LCAncmdiKDI1Miw3OCw0MiknXSxcbiAgICAgICAgWzAuNSwgJ3JnYigyNTMsMTQxLDYwKSddLCBbMC42MjUsICdyZ2IoMjU0LDE3OCw3NiknXSxcbiAgICAgICAgWzAuNzUsICdyZ2IoMjU0LDIxNywxMTgpJ10sIFswLjg3NSwgJ3JnYigyNTUsMjM3LDE2MCknXSxcbiAgICAgICAgWzEsICdyZ2IoMjU1LDI1NSwyMDQpJ11cbiAgICBdLFxuXG4gICAgJ0JsdWVyZWQnOiBbXG4gICAgICAgIFswLCAncmdiKDAsMCwyNTUpJ10sIFsxLCAncmdiKDI1NSwwLDApJ11cbiAgICBdLFxuXG4gICAgLy8gbW9kaWZpZWQgUmRCdSBiYXNlZCBvblxuICAgIC8vIGh0dHA6Ly93d3cua2VubmV0aG1vcmVsYW5kLmNvbS9jb2xvci1tYXBzL1xuICAgICdSZEJ1JzogW1xuICAgICAgICBbMCwgJ3JnYig1LDEwLDE3MiknXSwgWzAuMzUsICdyZ2IoMTA2LDEzNywyNDcpJ10sXG4gICAgICAgIFswLjUsICdyZ2IoMTkwLDE5MCwxOTApJ10sIFswLjYsICdyZ2IoMjIwLDE3MCwxMzIpJ10sXG4gICAgICAgIFswLjcsICdyZ2IoMjMwLDE0NSw5MCknXSwgWzEsICdyZ2IoMTc4LDEwLDI4KSddXG4gICAgXSxcblxuICAgIC8vIFNjYWxlIGZvciBub24tbmVnYXRpdmUgbnVtZXJpYyB2YWx1ZXNcbiAgICAnUmVkcyc6IFtcbiAgICAgICAgWzAsICdyZ2IoMjIwLDIyMCwyMjApJ10sIFswLjIsICdyZ2IoMjQ1LDE5NSwxNTcpJ10sXG4gICAgICAgIFswLjQsICdyZ2IoMjQ1LDE2MCwxMDUpJ10sIFsxLCAncmdiKDE3OCwxMCwyOCknXVxuICAgIF0sXG5cbiAgICAvLyBTY2FsZSBmb3Igbm9uLXBvc2l0aXZlIG51bWVyaWMgdmFsdWVzXG4gICAgJ0JsdWVzJzogW1xuICAgICAgICBbMCwgJ3JnYig1LDEwLDE3MiknXSwgWzAuMzUsICdyZ2IoNDAsNjAsMTkwKSddLFxuICAgICAgICBbMC41LCAncmdiKDcwLDEwMCwyNDUpJ10sIFswLjYsICdyZ2IoOTAsMTIwLDI0NSknXSxcbiAgICAgICAgWzAuNywgJ3JnYigxMDYsMTM3LDI0NyknXSwgWzEsICdyZ2IoMjIwLDIyMCwyMjApJ11cbiAgICBdLFxuXG4gICAgJ1BpY25pYyc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCwwLDI1NSknXSwgWzAuMSwgJ3JnYig1MSwxNTMsMjU1KSddLFxuICAgICAgICBbMC4yLCAncmdiKDEwMiwyMDQsMjU1KSddLCBbMC4zLCAncmdiKDE1MywyMDQsMjU1KSddLFxuICAgICAgICBbMC40LCAncmdiKDIwNCwyMDQsMjU1KSddLCBbMC41LCAncmdiKDI1NSwyNTUsMjU1KSddLFxuICAgICAgICBbMC42LCAncmdiKDI1NSwyMDQsMjU1KSddLCBbMC43LCAncmdiKDI1NSwxNTMsMjU1KSddLFxuICAgICAgICBbMC44LCAncmdiKDI1NSwxMDIsMjA0KSddLCBbMC45LCAncmdiKDI1NSwxMDIsMTAyKSddLFxuICAgICAgICBbMSwgJ3JnYigyNTUsMCwwKSddXG4gICAgXSxcblxuICAgICdSYWluYm93JzogW1xuICAgICAgICBbMCwgJ3JnYigxNTAsMCw5MCknXSwgWzAuMTI1LCAncmdiKDAsMCwyMDApJ10sXG4gICAgICAgIFswLjI1LCAncmdiKDAsMjUsMjU1KSddLCBbMC4zNzUsICdyZ2IoMCwxNTIsMjU1KSddLFxuICAgICAgICBbMC41LCAncmdiKDQ0LDI1NSwxNTApJ10sIFswLjYyNSwgJ3JnYigxNTEsMjU1LDApJ10sXG4gICAgICAgIFswLjc1LCAncmdiKDI1NSwyMzQsMCknXSwgWzAuODc1LCAncmdiKDI1NSwxMTEsMCknXSxcbiAgICAgICAgWzEsICdyZ2IoMjU1LDAsMCknXVxuICAgIF0sXG5cbiAgICAnUG9ydGxhbmQnOiBbXG4gICAgICAgIFswLCAncmdiKDEyLDUxLDEzMSknXSwgWzAuMjUsICdyZ2IoMTAsMTM2LDE4NiknXSxcbiAgICAgICAgWzAuNSwgJ3JnYigyNDIsMjExLDU2KSddLCBbMC43NSwgJ3JnYigyNDIsMTQzLDU2KSddLFxuICAgICAgICBbMSwgJ3JnYigyMTcsMzAsMzApJ11cbiAgICBdLFxuXG4gICAgJ0pldCc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCwwLDEzMSknXSwgWzAuMTI1LCAncmdiKDAsNjAsMTcwKSddLFxuICAgICAgICBbMC4zNzUsICdyZ2IoNSwyNTUsMjU1KSddLCBbMC42MjUsICdyZ2IoMjU1LDI1NSwwKSddLFxuICAgICAgICBbMC44NzUsICdyZ2IoMjUwLDAsMCknXSwgWzEsICdyZ2IoMTI4LDAsMCknXVxuICAgIF0sXG5cbiAgICAnSG90JzogW1xuICAgICAgICBbMCwgJ3JnYigwLDAsMCknXSwgWzAuMywgJ3JnYigyMzAsMCwwKSddLFxuICAgICAgICBbMC42LCAncmdiKDI1NSwyMTAsMCknXSwgWzEsICdyZ2IoMjU1LDI1NSwyNTUpJ11cbiAgICBdLFxuXG4gICAgJ0JsYWNrYm9keSc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCwwLDApJ10sIFswLjIsICdyZ2IoMjMwLDAsMCknXSxcbiAgICAgICAgWzAuNCwgJ3JnYigyMzAsMjEwLDApJ10sIFswLjcsICdyZ2IoMjU1LDI1NSwyNTUpJ10sXG4gICAgICAgIFsxLCAncmdiKDE2MCwyMDAsMjU1KSddXG4gICAgXSxcblxuICAgICdFYXJ0aCc6IFtcbiAgICAgICAgWzAsICdyZ2IoMCwwLDEzMCknXSwgWzAuMSwgJ3JnYigwLDE4MCwxODApJ10sXG4gICAgICAgIFswLjIsICdyZ2IoNDAsMjEwLDQwKSddLCBbMC40LCAncmdiKDIzMCwyMzAsNTApJ10sXG4gICAgICAgIFswLjYsICdyZ2IoMTIwLDcwLDIwKSddLCBbMSwgJ3JnYigyNTUsMjU1LDI1NSknXVxuICAgIF0sXG5cbiAgICAnRWxlY3RyaWMnOiBbXG4gICAgICAgIFswLCAncmdiKDAsMCwwKSddLCBbMC4xNSwgJ3JnYigzMCwwLDEwMCknXSxcbiAgICAgICAgWzAuNCwgJ3JnYigxMjAsMCwxMDApJ10sIFswLjYsICdyZ2IoMTYwLDkwLDApJ10sXG4gICAgICAgIFswLjgsICdyZ2IoMjMwLDIwMCwwKSddLCBbMSwgJ3JnYigyNTUsMjUwLDIyMCknXVxuICAgIF0sXG5cbiAgICAnVmlyaWRpcyc6IFtcbiAgICAgICAgWzAsICcjNDQwMTU0J10sIFswLjA2Mjc0NTA5ODAzOTIxNTY5LCAnIzQ4MTg2YSddLFxuICAgICAgICBbMC4xMjU0OTAxOTYwNzg0MzEzNywgJyM0NzJkN2InXSwgWzAuMTg4MjM1Mjk0MTE3NjQ3MDYsICcjNDI0MDg2J10sXG4gICAgICAgIFswLjI1MDk4MDM5MjE1Njg2Mjc0LCAnIzNiNTI4YiddLCBbMC4zMTM3MjU0OTAxOTYwNzg0LCAnIzMzNjM4ZCddLFxuICAgICAgICBbMC4zNzY0NzA1ODgyMzUyOTQxLCAnIzJjNzI4ZSddLCBbMC40MzkyMTU2ODYyNzQ1MDk4LCAnIzI2ODI4ZSddLFxuICAgICAgICBbMC41MDE5NjA3ODQzMTM3MjU1LCAnIzIxOTE4YyddLCBbMC41NjQ3MDU4ODIzNTI5NDEyLCAnIzFmYTA4OCddLFxuICAgICAgICBbMC42Mjc0NTA5ODAzOTIxNTY5LCAnIzI4YWU4MCddLCBbMC42OTAxOTYwNzg0MzEzNzI1LCAnIzNmYmM3MyddLFxuICAgICAgICBbMC43NTI5NDExNzY0NzA1ODgyLCAnIzVlYzk2MiddLCBbMC44MTU2ODYyNzQ1MDk4MDM5LCAnIzg0ZDQ0YiddLFxuICAgICAgICBbMC44Nzg0MzEzNzI1NDkwMTk2LCAnI2FkZGMzMCddLCBbMC45NDExNzY0NzA1ODgyMzUzLCAnI2Q4ZTIxOSddLFxuICAgICAgICBbMSwgJyNmZGU3MjUnXVxuICAgIF0sXG5cbiAgICAnQ2l2aWRpcyc6IFtcbiAgICAgICAgWzAuMDAwMDAwLCAncmdiKDAsMzIsNzYpJ10sIFswLjA1ODgyNCwgJ3JnYigwLDQyLDEwMiknXSxcbiAgICAgICAgWzAuMTE3NjQ3LCAncmdiKDAsNTIsMTEwKSddLCBbMC4xNzY0NzEsICdyZ2IoMzksNjMsMTA4KSddLFxuICAgICAgICBbMC4yMzUyOTQsICdyZ2IoNjAsNzQsMTA3KSddLCBbMC4yOTQxMTgsICdyZ2IoNzYsODUsMTA3KSddLFxuICAgICAgICBbMC4zNTI5NDEsICdyZ2IoOTEsOTUsMTA5KSddLCBbMC40MTE3NjUsICdyZ2IoMTA0LDEwNiwxMTIpJ10sXG4gICAgICAgIFswLjQ3MDU4OCwgJ3JnYigxMTcsMTE3LDExNyknXSwgWzAuNTI5NDEyLCAncmdiKDEzMSwxMjksMTIwKSddLFxuICAgICAgICBbMC41ODgyMzUsICdyZ2IoMTQ2LDE0MCwxMjApJ10sIFswLjY0NzA1OSwgJ3JnYigxNjEsMTUyLDExOCknXSxcbiAgICAgICAgWzAuNzA1ODgyLCAncmdiKDE3NiwxNjUsMTE0KSddLCBbMC43NjQ3MDYsICdyZ2IoMTkyLDE3NywxMDkpJ10sXG4gICAgICAgIFswLjgyMzUyOSwgJ3JnYigyMDksMTkxLDEwMiknXSwgWzAuODgyMzUzLCAncmdiKDIyNSwyMDQsOTIpJ10sXG4gICAgICAgIFswLjk0MTE3NiwgJ3JnYigyNDMsMjE5LDc5KSddLCBbMS4wMDAwMDAsICdyZ2IoMjU1LDIzMyw2OSknXVxuICAgIF1cbn07XG5cbnZhciBkZWZhdWx0U2NhbGUgPSBzY2FsZXMuUmRCdTtcblxuZnVuY3Rpb24gZ2V0U2NhbGUoc2NsLCBkZmx0KSB7XG4gICAgaWYoIWRmbHQpIGRmbHQgPSBkZWZhdWx0U2NhbGU7XG4gICAgaWYoIXNjbCkgcmV0dXJuIGRmbHQ7XG5cbiAgICBmdW5jdGlvbiBwYXJzZVNjYWxlKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2NsID0gc2NhbGVzW3NjbF0gfHwgSlNPTi5wYXJzZShzY2wpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgIHNjbCA9IGRmbHQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZih0eXBlb2Ygc2NsID09PSAnc3RyaW5nJykge1xuICAgICAgICBwYXJzZVNjYWxlKCk7XG4gICAgICAgIC8vIG9jY2FzaW9uYWxseSBzY2wgaXMgZG91YmxlLUpTT04gZW5jb2RlZC4uLlxuICAgICAgICBpZih0eXBlb2Ygc2NsID09PSAnc3RyaW5nJykgcGFyc2VTY2FsZSgpO1xuICAgIH1cblxuICAgIGlmKCFpc1ZhbGlkU2NhbGVBcnJheShzY2wpKSByZXR1cm4gZGZsdDtcbiAgICByZXR1cm4gc2NsO1xufVxuXG5cbmZ1bmN0aW9uIGlzVmFsaWRTY2FsZUFycmF5KHNjbCkge1xuICAgIHZhciBoaWdoZXN0VmFsID0gMDtcblxuICAgIGlmKCFBcnJheS5pc0FycmF5KHNjbCkgfHwgc2NsLmxlbmd0aCA8IDIpIHJldHVybiBmYWxzZTtcblxuICAgIGlmKCFzY2xbMF0gfHwgIXNjbFtzY2wubGVuZ3RoIC0gMV0pIHJldHVybiBmYWxzZTtcblxuICAgIGlmKCtzY2xbMF1bMF0gIT09IDAgfHwgK3NjbFtzY2wubGVuZ3RoIC0gMV1bMF0gIT09IDEpIHJldHVybiBmYWxzZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzY2wubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNpID0gc2NsW2ldO1xuXG4gICAgICAgIGlmKHNpLmxlbmd0aCAhPT0gMiB8fCArc2lbMF0gPCBoaWdoZXN0VmFsIHx8ICF0aW55Y29sb3Ioc2lbMV0pLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaGlnaGVzdFZhbCA9ICtzaVswXTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaXNWYWxpZFNjYWxlKHNjbCkge1xuICAgIGlmKHNjYWxlc1tzY2xdICE9PSB1bmRlZmluZWQpIHJldHVybiB0cnVlO1xuICAgIGVsc2UgcmV0dXJuIGlzVmFsaWRTY2FsZUFycmF5KHNjbCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHNjYWxlczogc2NhbGVzLFxuICAgIGRlZmF1bHRTY2FsZTogZGVmYXVsdFNjYWxlLFxuXG4gICAgZ2V0OiBnZXRTY2FsZSxcbiAgICBpc1ZhbGlkOiBpc1ZhbGlkU2NhbGVcbn07XG5cbn0se1widGlueWNvbG9yMlwiOjUzN31dLDYwOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG4vLyBmb3IgYXV0b21hdGljIGFsaWdubWVudCBvbiBkcmFnZ2luZywgPDEvMyBtZWFucyBsZWZ0IGFsaWduLFxuLy8gPjIvMyBtZWFucyByaWdodCwgYW5kIGJldHdlZW4gaXMgY2VudGVyLiBQaWNrIHRoZSByaWdodCBmcmFjdGlvblxuLy8gYmFzZWQgb24gd2hlcmUgeW91IGFyZSwgYW5kIHJldHVybiB0aGUgZnJhY3Rpb24gY29ycmVzcG9uZGluZyB0b1xuLy8gdGhhdCBwb3NpdGlvbiBvbiB0aGUgb2JqZWN0XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGFsaWduKHYsIGR2LCB2MCwgdjEsIGFuY2hvcikge1xuICAgIHZhciB2bWluID0gKHYgLSB2MCkgLyAodjEgLSB2MCk7XG4gICAgdmFyIHZtYXggPSB2bWluICsgZHYgLyAodjEgLSB2MCk7XG4gICAgdmFyIHZjID0gKHZtaW4gKyB2bWF4KSAvIDI7XG5cbiAgICAvLyBleHBsaWNpdGx5IHNwZWNpZmllZCBhbmNob3JcbiAgICBpZihhbmNob3IgPT09ICdsZWZ0JyB8fCBhbmNob3IgPT09ICdib3R0b20nKSByZXR1cm4gdm1pbjtcbiAgICBpZihhbmNob3IgPT09ICdjZW50ZXInIHx8IGFuY2hvciA9PT0gJ21pZGRsZScpIHJldHVybiB2YztcbiAgICBpZihhbmNob3IgPT09ICdyaWdodCcgfHwgYW5jaG9yID09PSAndG9wJykgcmV0dXJuIHZtYXg7XG5cbiAgICAvLyBhdXRvbWF0aWMgYmFzZWQgb24gcG9zaXRpb25cbiAgICBpZih2bWluIDwgKDIgLyAzKSAtIHZjKSByZXR1cm4gdm1pbjtcbiAgICBpZih2bWF4ID4gKDQgLyAzKSAtIHZjKSByZXR1cm4gdm1heDtcbiAgICByZXR1cm4gdmM7XG59O1xuXG59LHt9XSw2MTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxuXG4vLyBzZXQgY3Vyc29ycyBwb2ludGluZyB0b3dhcmQgdGhlIGNsb3Nlc3QgY29ybmVyL3NpZGUsXG4vLyB0byBpbmRpY2F0ZSBhbGlnbm1lbnRcbi8vIHggYW5kIHkgYXJlIDAtMSwgZnJhY3Rpb25zIG9mIHRoZSBwbG90IGFyZWFcbnZhciBjdXJzb3JzZXQgPSBbXG4gICAgWydzdy1yZXNpemUnLCAncy1yZXNpemUnLCAnc2UtcmVzaXplJ10sXG4gICAgWyd3LXJlc2l6ZScsICdtb3ZlJywgJ2UtcmVzaXplJ10sXG4gICAgWydudy1yZXNpemUnLCAnbi1yZXNpemUnLCAnbmUtcmVzaXplJ11cbl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0Q3Vyc29yKHgsIHksIHhhbmNob3IsIHlhbmNob3IpIHtcbiAgICBpZih4YW5jaG9yID09PSAnbGVmdCcpIHggPSAwO1xuICAgIGVsc2UgaWYoeGFuY2hvciA9PT0gJ2NlbnRlcicpIHggPSAxO1xuICAgIGVsc2UgaWYoeGFuY2hvciA9PT0gJ3JpZ2h0JykgeCA9IDI7XG4gICAgZWxzZSB4ID0gTGliLmNvbnN0cmFpbihNYXRoLmZsb29yKHggKiAzKSwgMCwgMik7XG5cbiAgICBpZih5YW5jaG9yID09PSAnYm90dG9tJykgeSA9IDA7XG4gICAgZWxzZSBpZih5YW5jaG9yID09PSAnbWlkZGxlJykgeSA9IDE7XG4gICAgZWxzZSBpZih5YW5jaG9yID09PSAndG9wJykgeSA9IDI7XG4gICAgZWxzZSB5ID0gTGliLmNvbnN0cmFpbihNYXRoLmZsb29yKHkgKiAzKSwgMCwgMik7XG5cbiAgICByZXR1cm4gY3Vyc29yc2V0W3ldW3hdO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTl9XSw2MTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbW91c2VPZmZzZXQgPSBfZGVyZXFfKCdtb3VzZS1ldmVudC1vZmZzZXQnKTtcbnZhciBoYXNIb3ZlciA9IF9kZXJlcV8oJ2hhcy1ob3ZlcicpO1xudmFyIHN1cHBvcnRzUGFzc2l2ZSA9IF9kZXJlcV8oJ2hhcy1wYXNzaXZlLWV2ZW50cycpO1xuXG52YXIgcmVtb3ZlRWxlbWVudCA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLnJlbW92ZUVsZW1lbnQ7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cycpO1xuXG52YXIgZHJhZ0VsZW1lbnQgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5kcmFnRWxlbWVudC5hbGlnbiA9IF9kZXJlcV8oJy4vYWxpZ24nKTtcbmRyYWdFbGVtZW50LmdldEN1cnNvciA9IF9kZXJlcV8oJy4vY3Vyc29yJyk7XG5cbnZhciB1bmhvdmVyID0gX2RlcmVxXygnLi91bmhvdmVyJyk7XG5kcmFnRWxlbWVudC51bmhvdmVyID0gdW5ob3Zlci53cmFwcGVkO1xuZHJhZ0VsZW1lbnQudW5ob3ZlclJhdyA9IHVuaG92ZXIucmF3O1xuXG4vKipcbiAqIEFic3RyYWN0cyBjbGljayAmIGRyYWcgaW50ZXJhY3Rpb25zXG4gKlxuICogRHVyaW5nIHRoZSBpbnRlcmFjdGlvbiwgYSBcImNvdmVyU2xpcFwiIGVsZW1lbnQgLSBhIHRyYW5zcGFyZW50XG4gKiBkaXYgY292ZXJpbmcgdGhlIHdob2xlIHBhZ2UgLSBpcyBjcmVhdGVkLCB3aGljaCBoYXMgdHdvIGtleSBlZmZlY3RzOlxuICogLSBMZXRzIHlvdSBkcmFnIGJleW9uZCB0aGUgYm91bmRhcmllcyBvZiB0aGUgcGxvdCBpdHNlbGYgd2l0aG91dFxuICogICBkcm9wcGluZyAoYnV0IGlmIHlvdSBkcmFnIGFsbCB0aGUgd2F5IG91dCBvZiB0aGUgYnJvd3NlciB3aW5kb3cgdGhlXG4gKiAgIGludGVyYWN0aW9uIHdpbGwgZW5kKVxuICogLSBGcmVlemVzIHRoZSBjdXJzb3I6IHdoYXRldmVyIG1vdXNlIGN1cnNvciB0aGUgZHJhZyBlbGVtZW50IGhhZCB3aGVuIHRoZVxuICogICBpbnRlcmFjdGlvbiBzdGFydGVkIGdldHMgY29waWVkIHRvIHRoZSBjb3ZlclNsaXAgZm9yIHVzZSB1bnRpbCBtb3VzZXVwXG4gKlxuICogSWYgdGhlIHVzZXIgZXhlY3V0ZXMgYSBkcmFnIGJpZ2dlciB0aGFuIE1JTkRSQUcsIGNhbGxiYWNrcyB3aWxsIGZpcmUgYXM6XG4gKiAgICAgIHByZXBGbiwgbW92ZUZuICgxIG9yIG1vcmUgdGltZXMpLCBkb25lRm5cbiAqIElmIHRoZSB1c2VyIGRvZXMgbm90IGRyYWcgZW5vdWdoLCBwcmVwRm4gYW5kIGNsaWNrRm4gd2lsbCBmaXJlLlxuICpcbiAqIE5vdGU6IElmIHlvdSBjYW5jZWwgY29udGV4dG1lbnUsIGNsaWNrRm4gd2lsbCBmaXJlIGV2ZW4gd2l0aCBhIHJpZ2h0IGNsaWNrXG4gKiAodW5saWtlIG5hdGl2ZSBldmVudHMpIHNvIHlvdSdsbCBnZXQgYSBgcGxvdGx5X2NsaWNrYCBldmVudC4gQ2FuY2VsIGNvbnRleHQgZWc6XG4gKiAgICBnZC5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIGZ1bmN0aW9uKGUpIHsgZS5wcmV2ZW50RGVmYXVsdCgpOyB9KTtcbiAqIFRPRE86IHdlIHNob3VsZCBwcm9iYWJseSB0dXJuIHRoaXMgaW50byBhIGBjb25maWdgIHBhcmFtZXRlciwgc28gd2UgY2FuIGZpeCBpdFxuICogc3VjaCB0aGF0IGlmIHlvdSAqZG9uJ3QqIGNhbmNlbCBjb250ZXh0bWVudSwgd2UgY2FuIHByZXZlbnQgcGFydGlhbCBkcmFncywgd2hpY2hcbiAqIHB1dCB5b3UgaW4gYSB3ZWlyZCBzdGF0ZS5cbiAqXG4gKiBJZiB0aGUgdXNlciBjbGlja3MgbXVsdGlwbGUgdGltZXMgcXVpY2tseSwgY2xpY2tGbiB3aWxsIGZpcmUgZWFjaCB0aW1lXG4gKiBidXQgbnVtQ2xpY2tzIHdpbGwgaW5jcmVhc2UgdG8gaGVscCB5b3UgcmVjb2duaXplIGRvdWJsZWNsaWNrcy5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyB3aXRoIGtleXM6XG4gKiAgICAgIGVsZW1lbnQgKHJlcXVpcmVkKSB0aGUgRE9NIGVsZW1lbnQgdG8gZHJhZ1xuICogICAgICBwcmVwRm4gKG9wdGlvbmFsKSBmdW5jdGlvbihldmVudCwgc3RhcnRYLCBzdGFydFkpXG4gKiAgICAgICAgICBleGVjdXRlZCBvbiBtb3VzZWRvd25cbiAqICAgICAgICAgIHN0YXJ0WCBhbmQgc3RhcnRZIGFyZSB0aGUgY2xpZW50WCBhbmQgY2xpZW50WSBwaXhlbCBwb3NpdGlvblxuICogICAgICAgICAgb2YgdGhlIG1vdXNlZG93biBldmVudFxuICogICAgICBtb3ZlRm4gKG9wdGlvbmFsKSBmdW5jdGlvbihkeCwgZHkpXG4gKiAgICAgICAgICBleGVjdXRlZCBvbiBtb3ZlLCBPTkxZIGFmdGVyIHdlJ3ZlIGV4Y2VlZGVkIE1JTkRSQUdcbiAqICAgICAgICAgICh3ZSBrZWVwIGV4ZWN1dGluZyBtb3ZlRm4gaWYgeW91IG1vdmUgYmFjayB0byB3aGVyZSB5b3Ugc3RhcnRlZClcbiAqICAgICAgICAgIGR4IGFuZCBkeSBhcmUgdGhlIG5ldCBwaXhlbCBvZmZzZXQgb2YgdGhlIGRyYWcsXG4gKiAgICAgICAgICBkcmFnZ2VkIGlzIHRydWUvZmFsc2UsIGhhcyB0aGUgbW91c2UgbW92ZWQgZW5vdWdoIHRvXG4gKiAgICAgICAgICBjb25zdGl0dXRlIGEgZHJhZ1xuICogICAgICBkb25lRm4gKG9wdGlvbmFsKSBmdW5jdGlvbihlKVxuICogICAgICAgICAgZXhlY3V0ZWQgb24gbW91c2V1cCwgT05MWSBpZiB3ZSBleGNlZWRlZCBNSU5EUkFHIChzbyB5b3UgY2FuIGJlXG4gKiAgICAgICAgICBzdXJlIHRoYXQgbW92ZUZuIGhhcyBiZWVuIGNhbGxlZCBhdCBsZWFzdCBvbmNlKVxuICogICAgICAgICAgbnVtQ2xpY2tzIGlzIGhvdyBtYW55IGNsaWNrcyB3ZSd2ZSByZWdpc3RlcmVkIHdpdGhpblxuICogICAgICAgICAgYSBkb3VibGVjbGljayB0aW1lXG4gKiAgICAgICAgICBlIGlzIHRoZSBvcmlnaW5hbCBtb3VzZXVwIGV2ZW50XG4gKiAgICAgIGNsaWNrRm4gKG9wdGlvbmFsKSBmdW5jdGlvbihudW1DbGlja3MsIGUpXG4gKiAgICAgICAgICBleGVjdXRlZCBvbiBtb3VzZXVwIGlmIHdlIGhhdmUgTk9UIGV4Y2VlZGVkIE1JTkRSQUcgKGllIG1vdmVGblxuICogICAgICAgICAgaGFzIG5vdCBiZWVuIGNhbGxlZCBhdCBhbGwpXG4gKiAgICAgICAgICBudW1DbGlja3MgaXMgaG93IG1hbnkgY2xpY2tzIHdlJ3ZlIHJlZ2lzdGVyZWQgd2l0aGluXG4gKiAgICAgICAgICBhIGRvdWJsZWNsaWNrIHRpbWVcbiAqICAgICAgICAgIGUgaXMgdGhlIG9yaWdpbmFsIG1vdXNlZG93biBldmVudFxuICogICAgICBjbGFtcEZuIChvcHRpb25hbCwgZnVuY3Rpb24oZHgsIGR5KSByZXR1cm4gW2R4MiwgZHkyXSlcbiAqICAgICAgICAgIFByb3ZpZGUgY3VzdG9tIGNsYW1waW5nIGZ1bmN0aW9uIGZvciBzbWFsbCBkaXNwbGFjZW1lbnRzLlxuICogICAgICAgICAgQnkgZGVmYXVsdCwgY2xhbXBpbmcgaXMgZG9uZSB1c2luZyBgbWluRHJhZ2AgdG8geCBhbmQgeSBkaXNwbGFjZW1lbnRzXG4gKiAgICAgICAgICBpbmRlcGVuZGVudGx5LlxuICovXG5kcmFnRWxlbWVudC5pbml0ID0gZnVuY3Rpb24gaW5pdChvcHRpb25zKSB7XG4gICAgdmFyIGdkID0gb3B0aW9ucy5nZDtcbiAgICB2YXIgbnVtQ2xpY2tzID0gMTtcbiAgICB2YXIgZG91YmxlQ2xpY2tEZWxheSA9IGdkLl9jb250ZXh0LmRvdWJsZUNsaWNrRGVsYXk7XG4gICAgdmFyIGVsZW1lbnQgPSBvcHRpb25zLmVsZW1lbnQ7XG5cbiAgICB2YXIgc3RhcnRYLFxuICAgICAgICBzdGFydFksXG4gICAgICAgIG5ld01vdXNlRG93blRpbWUsXG4gICAgICAgIGN1cnNvcixcbiAgICAgICAgZHJhZ0NvdmVyLFxuICAgICAgICBpbml0aWFsRXZlbnQsXG4gICAgICAgIGluaXRpYWxUYXJnZXQsXG4gICAgICAgIHJpZ2h0Q2xpY2s7XG5cbiAgICBpZighZ2QuX21vdXNlRG93blRpbWUpIGdkLl9tb3VzZURvd25UaW1lID0gMDtcblxuICAgIGVsZW1lbnQuc3R5bGUucG9pbnRlckV2ZW50cyA9ICdhbGwnO1xuXG4gICAgZWxlbWVudC5vbm1vdXNlZG93biA9IG9uU3RhcnQ7XG5cbiAgICBpZighc3VwcG9ydHNQYXNzaXZlKSB7XG4gICAgICAgIGVsZW1lbnQub250b3VjaHN0YXJ0ID0gb25TdGFydDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZihlbGVtZW50Ll9vbnRvdWNoc3RhcnQpIHtcbiAgICAgICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIGVsZW1lbnQuX29udG91Y2hzdGFydCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudC5fb250b3VjaHN0YXJ0ID0gb25TdGFydDtcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0Jywgb25TdGFydCwge3Bhc3NpdmU6IGZhbHNlfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gX2NsYW1wRm4oZHgsIGR5LCBtaW5EcmFnKSB7XG4gICAgICAgIGlmKE1hdGguYWJzKGR4KSA8IG1pbkRyYWcpIGR4ID0gMDtcbiAgICAgICAgaWYoTWF0aC5hYnMoZHkpIDwgbWluRHJhZykgZHkgPSAwO1xuICAgICAgICByZXR1cm4gW2R4LCBkeV07XG4gICAgfVxuXG4gICAgdmFyIGNsYW1wRm4gPSBvcHRpb25zLmNsYW1wRm4gfHwgX2NsYW1wRm47XG5cbiAgICBmdW5jdGlvbiBvblN0YXJ0KGUpIHtcbiAgICAgICAgLy8gbWFrZSBkcmFnZ2luZyBhbmQgZHJhZ2dlZCBpbnRvIHByb3BlcnRpZXMgb2YgZ2RcbiAgICAgICAgLy8gc28gdGhhdCBvdGhlcnMgY2FuIGxvb2sgYXQgYW5kIG1vZGlmeSB0aGVtXG4gICAgICAgIGdkLl9kcmFnZ2VkID0gZmFsc2U7XG4gICAgICAgIGdkLl9kcmFnZ2luZyA9IHRydWU7XG4gICAgICAgIHZhciBvZmZzZXQgPSBwb2ludGVyT2Zmc2V0KGUpO1xuICAgICAgICBzdGFydFggPSBvZmZzZXRbMF07XG4gICAgICAgIHN0YXJ0WSA9IG9mZnNldFsxXTtcbiAgICAgICAgaW5pdGlhbFRhcmdldCA9IGUudGFyZ2V0O1xuICAgICAgICBpbml0aWFsRXZlbnQgPSBlO1xuICAgICAgICByaWdodENsaWNrID0gZS5idXR0b25zID09PSAyIHx8IGUuY3RybEtleTtcblxuICAgICAgICAvLyBmaXggRnguaG92ZXIgZm9yIHRvdWNoIGV2ZW50c1xuICAgICAgICBpZih0eXBlb2YgZS5jbGllbnRYID09PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgZS5jbGllbnRZID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgZS5jbGllbnRYID0gc3RhcnRYO1xuICAgICAgICAgICAgZS5jbGllbnRZID0gc3RhcnRZO1xuICAgICAgICB9XG5cbiAgICAgICAgbmV3TW91c2VEb3duVGltZSA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7XG4gICAgICAgIGlmKG5ld01vdXNlRG93blRpbWUgLSBnZC5fbW91c2VEb3duVGltZSA8IGRvdWJsZUNsaWNrRGVsYXkpIHtcbiAgICAgICAgICAgIC8vIGluIGEgY2xpY2sgdHJhaW5cbiAgICAgICAgICAgIG51bUNsaWNrcyArPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gbmV3IGNsaWNrIHRyYWluXG4gICAgICAgICAgICBudW1DbGlja3MgPSAxO1xuICAgICAgICAgICAgZ2QuX21vdXNlRG93blRpbWUgPSBuZXdNb3VzZURvd25UaW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYob3B0aW9ucy5wcmVwRm4pIG9wdGlvbnMucHJlcEZuKGUsIHN0YXJ0WCwgc3RhcnRZKTtcblxuICAgICAgICBpZihoYXNIb3ZlciAmJiAhcmlnaHRDbGljaykge1xuICAgICAgICAgICAgZHJhZ0NvdmVyID0gY292ZXJTbGlwKCk7XG4gICAgICAgICAgICBkcmFnQ292ZXIuc3R5bGUuY3Vyc29yID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkuY3Vyc29yO1xuICAgICAgICB9IGVsc2UgaWYoIWhhc0hvdmVyKSB7XG4gICAgICAgICAgICAvLyBkb2N1bWVudCBhY3RzIGFzIGEgZHJhZ2NvdmVyIGZvciBtb2JpbGUsIGJjIHdlIGNhbid0IGNyZWF0ZSBkcmFnY292ZXIgZHluYW1pY2FsbHlcbiAgICAgICAgICAgIGRyYWdDb3ZlciA9IGRvY3VtZW50O1xuICAgICAgICAgICAgY3Vyc29yID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KS5jdXJzb3I7XG4gICAgICAgICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkuY3Vyc29yO1xuICAgICAgICB9XG5cbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIG9uRG9uZSk7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgb25Eb25lKTtcblxuICAgICAgICBpZihvcHRpb25zLmRyYWdtb2RlICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgb25Nb3ZlKTtcbiAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIG9uTW92ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25Nb3ZlKGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHZhciBvZmZzZXQgPSBwb2ludGVyT2Zmc2V0KGUpO1xuICAgICAgICB2YXIgbWluRHJhZyA9IG9wdGlvbnMubWluRHJhZyB8fCBjb25zdGFudHMuTUlORFJBRztcbiAgICAgICAgdmFyIGR4ZHkgPSBjbGFtcEZuKG9mZnNldFswXSAtIHN0YXJ0WCwgb2Zmc2V0WzFdIC0gc3RhcnRZLCBtaW5EcmFnKTtcbiAgICAgICAgdmFyIGR4ID0gZHhkeVswXTtcbiAgICAgICAgdmFyIGR5ID0gZHhkeVsxXTtcblxuICAgICAgICBpZihkeCB8fCBkeSkge1xuICAgICAgICAgICAgZ2QuX2RyYWdnZWQgPSB0cnVlO1xuICAgICAgICAgICAgZHJhZ0VsZW1lbnQudW5ob3ZlcihnZCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihnZC5fZHJhZ2dlZCAmJiBvcHRpb25zLm1vdmVGbiAmJiAhcmlnaHRDbGljaykge1xuICAgICAgICAgICAgZ2QuX2RyYWdkYXRhID0ge1xuICAgICAgICAgICAgICAgIGVsZW1lbnQ6IGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgZHg6IGR4LFxuICAgICAgICAgICAgICAgIGR5OiBkeVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIG9wdGlvbnMubW92ZUZuKGR4LCBkeSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25Eb25lKGUpIHtcbiAgICAgICAgZGVsZXRlIGdkLl9kcmFnZGF0YTtcblxuICAgICAgICBpZihvcHRpb25zLmRyYWdtb2RlICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgb25Nb3ZlKTtcbiAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIG9uTW92ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Eb25lKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBvbkRvbmUpO1xuXG4gICAgICAgIGlmKGhhc0hvdmVyKSB7XG4gICAgICAgICAgICByZW1vdmVFbGVtZW50KGRyYWdDb3Zlcik7XG4gICAgICAgIH0gZWxzZSBpZihjdXJzb3IpIHtcbiAgICAgICAgICAgIGRyYWdDb3Zlci5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yID0gY3Vyc29yO1xuICAgICAgICAgICAgY3Vyc29yID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFnZC5fZHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIGdkLl9kcmFnZ2VkID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZ2QuX2RyYWdnaW5nID0gZmFsc2U7XG5cbiAgICAgICAgLy8gZG9uJ3QgY291bnQgYXMgYSBkYmxDbGljayB1bmxlc3MgdGhlIG1vdXNlVXAgaXMgYWxzbyB3aXRoaW5cbiAgICAgICAgLy8gdGhlIGRibGNsaWNrIGRlbGF5XG4gICAgICAgIGlmKChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLSBnZC5fbW91c2VEb3duVGltZSA+IGRvdWJsZUNsaWNrRGVsYXkpIHtcbiAgICAgICAgICAgIG51bUNsaWNrcyA9IE1hdGgubWF4KG51bUNsaWNrcyAtIDEsIDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZ2QuX2RyYWdnZWQpIHtcbiAgICAgICAgICAgIGlmKG9wdGlvbnMuZG9uZUZuKSBvcHRpb25zLmRvbmVGbigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYob3B0aW9ucy5jbGlja0ZuKSBvcHRpb25zLmNsaWNrRm4obnVtQ2xpY2tzLCBpbml0aWFsRXZlbnQpO1xuXG4gICAgICAgICAgICAvLyBJZiB3ZSBoYXZlbid0IGRyYWdnZWQsIHRoaXMgc2hvdWxkIGJlIGEgY2xpY2suIEJ1dCBiZWNhdXNlIG9mIHRoZVxuICAgICAgICAgICAgLy8gY292ZXJTbGlwIGNoYW5naW5nIHRoZSBlbGVtZW50LCB0aGUgbmF0dXJhbCBzeXN0ZW0gbWlnaHQgbm90IGdlbmVyYXRlIG9uZSxcbiAgICAgICAgICAgIC8vIHNvIHdlIG5lZWQgdG8gbWFrZSBvdXIgb3duLiBCdXQgcmlnaHQgY2xpY2tzIGRvbid0IG5vcm1hbGx5IGdlbmVyYXRlXG4gICAgICAgICAgICAvLyBjbGljayBldmVudHMsIG9ubHkgY29udGV4dG1lbnUgZXZlbnRzLCB3aGljaCBoYXBwZW4gb24gbW91c2Vkb3duLlxuICAgICAgICAgICAgaWYoIXJpZ2h0Q2xpY2spIHtcbiAgICAgICAgICAgICAgICB2YXIgZTI7XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBlMiA9IG5ldyBNb3VzZUV2ZW50KCdjbGljaycsIGUpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2goZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBvZmZzZXQgPSBwb2ludGVyT2Zmc2V0KGUpO1xuICAgICAgICAgICAgICAgICAgICBlMiA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO1xuICAgICAgICAgICAgICAgICAgICBlMi5pbml0TW91c2VFdmVudCgnY2xpY2snLFxuICAgICAgICAgICAgICAgICAgICAgICAgZS5idWJibGVzLCBlLmNhbmNlbGFibGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBlLnZpZXcsIGUuZGV0YWlsLFxuICAgICAgICAgICAgICAgICAgICAgICAgZS5zY3JlZW5YLCBlLnNjcmVlblksXG4gICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRbMF0sIG9mZnNldFsxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuY3RybEtleSwgZS5hbHRLZXksIGUuc2hpZnRLZXksIGUubWV0YUtleSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGUuYnV0dG9uLCBlLnJlbGF0ZWRUYXJnZXQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGluaXRpYWxUYXJnZXQuZGlzcGF0Y2hFdmVudChlMik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBnZC5fZHJhZ2dpbmcgPSBmYWxzZTtcbiAgICAgICAgZ2QuX2RyYWdnZWQgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGNvdmVyU2xpcCgpIHtcbiAgICB2YXIgY292ZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgIGNvdmVyLmNsYXNzTmFtZSA9ICdkcmFnY292ZXInO1xuICAgIHZhciBjU3R5bGUgPSBjb3Zlci5zdHlsZTtcbiAgICBjU3R5bGUucG9zaXRpb24gPSAnZml4ZWQnO1xuICAgIGNTdHlsZS5sZWZ0ID0gMDtcbiAgICBjU3R5bGUucmlnaHQgPSAwO1xuICAgIGNTdHlsZS50b3AgPSAwO1xuICAgIGNTdHlsZS5ib3R0b20gPSAwO1xuICAgIGNTdHlsZS56SW5kZXggPSA5OTk5OTk5OTk7XG4gICAgY1N0eWxlLmJhY2tncm91bmQgPSAnbm9uZSc7XG5cbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGNvdmVyKTtcblxuICAgIHJldHVybiBjb3Zlcjtcbn1cblxuZHJhZ0VsZW1lbnQuY292ZXJTbGlwID0gY292ZXJTbGlwO1xuXG5mdW5jdGlvbiBwb2ludGVyT2Zmc2V0KGUpIHtcbiAgICByZXR1cm4gbW91c2VPZmZzZXQoXG4gICAgICAgIGUuY2hhbmdlZFRvdWNoZXMgPyBlLmNoYW5nZWRUb3VjaGVzWzBdIDogZSxcbiAgICAgICAgZG9jdW1lbnQuYm9keVxuICAgICk7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50c1wiOjc3MyxcIi4vYWxpZ25cIjo2MDksXCIuL2N1cnNvclwiOjYxMCxcIi4vdW5ob3ZlclwiOjYxMixcImhhcy1ob3ZlclwiOjQxMCxcImhhcy1wYXNzaXZlLWV2ZW50c1wiOjQxMSxcIm1vdXNlLWV2ZW50LW9mZnNldFwiOjQzNn1dLDYxMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBFdmVudHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXZlbnRzJyk7XG52YXIgdGhyb3R0bGUgPSBfZGVyZXFfKCcuLi8uLi9saWIvdGhyb3R0bGUnKTtcbnZhciBnZXRHcmFwaERpdiA9IF9kZXJlcV8oJy4uLy4uL2xpYi9kb20nKS5nZXRHcmFwaERpdjtcblxudmFyIGhvdmVyQ29uc3RhbnRzID0gX2RlcmVxXygnLi4vZngvY29uc3RhbnRzJyk7XG5cbnZhciB1bmhvdmVyID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxudW5ob3Zlci53cmFwcGVkID0gZnVuY3Rpb24oZ2QsIGV2dCwgc3VicGxvdCkge1xuICAgIGdkID0gZ2V0R3JhcGhEaXYoZ2QpO1xuXG4gICAgLy8gSW1wb3J0YW50LCBjbGVhciBhbnkgcXVldWVkIGhvdmVyc1xuICAgIGlmKGdkLl9mdWxsTGF5b3V0KSB7XG4gICAgICAgIHRocm90dGxlLmNsZWFyKGdkLl9mdWxsTGF5b3V0Ll91aWQgKyBob3ZlckNvbnN0YW50cy5IT1ZFUklEKTtcbiAgICB9XG5cbiAgICB1bmhvdmVyLnJhdyhnZCwgZXZ0LCBzdWJwbG90KTtcbn07XG5cblxuLy8gcmVtb3ZlIGhvdmVyIGVmZmVjdHMgb24gbW91c2Ugb3V0LCBhbmQgZW1pdCB1bmhvdmVyIGV2ZW50XG51bmhvdmVyLnJhdyA9IGZ1bmN0aW9uIHJhdyhnZCwgZXZ0KSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgb2xkaG92ZXJkYXRhID0gZ2QuX2hvdmVyZGF0YTtcblxuICAgIGlmKCFldnQpIGV2dCA9IHt9O1xuICAgIGlmKGV2dC50YXJnZXQgJiZcbiAgICAgICBFdmVudHMudHJpZ2dlckhhbmRsZXIoZ2QsICdwbG90bHlfYmVmb3JlaG92ZXInLCBldnQpID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZnVsbExheW91dC5faG92ZXJsYXllci5zZWxlY3RBbGwoJ2cnKS5yZW1vdmUoKTtcbiAgICBmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLnNlbGVjdEFsbCgnbGluZScpLnJlbW92ZSgpO1xuICAgIGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIuc2VsZWN0QWxsKCdjaXJjbGUnKS5yZW1vdmUoKTtcbiAgICBnZC5faG92ZXJkYXRhID0gdW5kZWZpbmVkO1xuXG4gICAgaWYoZXZ0LnRhcmdldCAmJiBvbGRob3ZlcmRhdGEpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3VuaG92ZXInLCB7XG4gICAgICAgICAgICBldmVudDogZXZ0LFxuICAgICAgICAgICAgcG9pbnRzOiBvbGRob3ZlcmRhdGFcbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWIvZG9tXCI6NzA4LFwiLi4vLi4vbGliL2V2ZW50c1wiOjcwOSxcIi4uLy4uL2xpYi90aHJvdHRsZVwiOjc0NCxcIi4uL2Z4L2NvbnN0YW50c1wiOjYyNn1dLDYxMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5kYXNoID0ge1xuICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgIC8vIHN0cmluZyB0eXBlIHVzdWFsbHkgZG9lc24ndCB0YWtlIHZhbHVlcy4uLiB0aGlzIG9uZSBzaG91bGQgcmVhbGx5IGJlXG4gICAgLy8gYSBzcGVjaWFsIHR5cGUgb3IgYXQgbGVhc3QgYSBzcGVjaWFsIGNvZXJjaW9uIGZ1bmN0aW9uLCBmcm9tIHRoZSBHVUlcbiAgICAvLyB5b3Ugb25seSBnZXQgdGhlc2UgdmFsdWVzIGJ1dCBlbHNld2hlcmUgdGhlIHVzZXIgY2FuIHN1cHBseSBhIGxpc3Qgb2ZcbiAgICAvLyBkYXNoIGxlbmd0aHMgaW4gcHgsIGFuZCBpdCB3aWxsIGJlIGhvbm9yZWRcbiAgICB2YWx1ZXM6IFsnc29saWQnLCAnZG90JywgJ2Rhc2gnLCAnbG9uZ2Rhc2gnLCAnZGFzaGRvdCcsICdsb25nZGFzaGRvdCddLFxuICAgIGRmbHQ6ICdzb2xpZCcsXG4gICAgXG4gICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgXG59O1xuXG59LHt9XSw2MTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcbnZhciB0aW55Y29sb3IgPSBfZGVyZXFfKCd0aW55Y29sb3IyJyk7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb2xvcicpO1xudmFyIENvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi9jb2xvcnNjYWxlJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gX2RlcmVxXygnLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG5cbnZhciB4bWxuc05hbWVzcGFjZXMgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlcycpO1xudmFyIGFsaWdubWVudCA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKTtcbnZhciBMSU5FX1NQQUNJTkcgPSBhbGlnbm1lbnQuTElORV9TUEFDSU5HO1xudmFyIERFU0VMRUNURElNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2ludGVyYWN0aW9ucycpLkRFU0VMRUNURElNO1xuXG52YXIgc3ViVHlwZXMgPSBfZGVyZXFfKCcuLi8uLi90cmFjZXMvc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIG1ha2VCdWJibGVTaXplRm4gPSBfZGVyZXFfKCcuLi8uLi90cmFjZXMvc2NhdHRlci9tYWtlX2J1YmJsZV9zaXplX2Z1bmMnKTtcblxudmFyIGRyYXdpbmcgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gc3R5bGluZyBmdW5jdGlvbnMgZm9yIHBsb3QgZWxlbWVudHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmRyYXdpbmcuZm9udCA9IGZ1bmN0aW9uKHMsIGZhbWlseSwgc2l6ZSwgY29sb3IpIHtcbiAgICAvLyBhbHNvIGFsbG93IHRoZSBmb3JtIGZvbnQocywge2ZhbWlseSwgc2l6ZSwgY29sb3J9KVxuICAgIGlmKExpYi5pc1BsYWluT2JqZWN0KGZhbWlseSkpIHtcbiAgICAgICAgY29sb3IgPSBmYW1pbHkuY29sb3I7XG4gICAgICAgIHNpemUgPSBmYW1pbHkuc2l6ZTtcbiAgICAgICAgZmFtaWx5ID0gZmFtaWx5LmZhbWlseTtcbiAgICB9XG4gICAgaWYoZmFtaWx5KSBzLnN0eWxlKCdmb250LWZhbWlseScsIGZhbWlseSk7XG4gICAgaWYoc2l6ZSArIDEpIHMuc3R5bGUoJ2ZvbnQtc2l6ZScsIHNpemUgKyAncHgnKTtcbiAgICBpZihjb2xvcikgcy5jYWxsKENvbG9yLmZpbGwsIGNvbG9yKTtcbn07XG5cbi8qXG4gKiBQb3NpdGlvbmluZyBoZWxwZXJzXG4gKiBOb3RlOiBkbyBub3QgdXNlIGBzZXRQb3NpdGlvbmAgd2l0aCA8dGV4dD4gbm9kZXMgbW9kaWZpZWQgYnlcbiAqIGBzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zYC4gVXNlIGBzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0YFxuICogaW5zdGVhZCwgc28gdGhhdCA8dHNwYW4ubGluZT4gZWxlbWVudHMgZ2V0IHVwZGF0ZWQgdG8gbWF0Y2guXG4gKi9cbmRyYXdpbmcuc2V0UG9zaXRpb24gPSBmdW5jdGlvbihzLCB4LCB5KSB7IHMuYXR0cigneCcsIHgpLmF0dHIoJ3knLCB5KTsgfTtcbmRyYXdpbmcuc2V0U2l6ZSA9IGZ1bmN0aW9uKHMsIHcsIGgpIHsgcy5hdHRyKCd3aWR0aCcsIHcpLmF0dHIoJ2hlaWdodCcsIGgpOyB9O1xuZHJhd2luZy5zZXRSZWN0ID0gZnVuY3Rpb24ocywgeCwgeSwgdywgaCkge1xuICAgIHMuY2FsbChkcmF3aW5nLnNldFBvc2l0aW9uLCB4LCB5KS5jYWxsKGRyYXdpbmcuc2V0U2l6ZSwgdywgaCk7XG59O1xuXG4vKiogVHJhbnNsYXRlIG5vZGVcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gZCA6IGNhbGNkYXRhIHBvaW50IGl0ZW1cbiAqIEBwYXJhbSB7c2VsfSBzZWwgOiBkMyBzZWxjdGlvbiBvZiBub2RlIHRvIHRyYW5zbGF0ZVxuICogQHBhcmFtIHtvYmplY3R9IHhhIDogY29ycmVzcG9uZGluZyBmdWxsIHhheGlzIG9iamVjdFxuICogQHBhcmFtIHtvYmplY3R9IHlhIDogY29ycmVzcG9uZGluZyBmdWxsIHlheGlzIG9iamVjdFxuICpcbiAqIEByZXR1cm4ge2Jvb2xlYW59IDpcbiAqICB0cnVlIGlmIHNlbGVjdGlvbiBnb3QgdHJhbnNsYXRlZFxuICogIGZhbHNlIGlmIHNlbGVjdGlvbiBjb3VsZCBub3QgZ2V0IHRyYW5zbGF0ZWRcbiAqL1xuZHJhd2luZy50cmFuc2xhdGVQb2ludCA9IGZ1bmN0aW9uKGQsIHNlbCwgeGEsIHlhKSB7XG4gICAgdmFyIHggPSB4YS5jMnAoZC54KTtcbiAgICB2YXIgeSA9IHlhLmMycChkLnkpO1xuXG4gICAgaWYoaXNOdW1lcmljKHgpICYmIGlzTnVtZXJpYyh5KSAmJiBzZWwubm9kZSgpKSB7XG4gICAgICAgIC8vIGZvciBtdWx0aWxpbmUgdGV4dCB0aGlzIHdvcmtzIGJldHRlclxuICAgICAgICBpZihzZWwubm9kZSgpLm5vZGVOYW1lID09PSAndGV4dCcpIHtcbiAgICAgICAgICAgIHNlbC5hdHRyKCd4JywgeCkuYXR0cigneScsIHkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIHggKyAnLCcgKyB5ICsgJyknKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbmRyYXdpbmcudHJhbnNsYXRlUG9pbnRzID0gZnVuY3Rpb24ocywgeGEsIHlhKSB7XG4gICAgcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHNlbCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgZHJhd2luZy50cmFuc2xhdGVQb2ludChkLCBzZWwsIHhhLCB5YSk7XG4gICAgfSk7XG59O1xuXG5kcmF3aW5nLmhpZGVPdXRzaWRlUmFuZ2VQb2ludCA9IGZ1bmN0aW9uKGQsIHNlbCwgeGEsIHlhLCB4Y2FsZW5kYXIsIHljYWxlbmRhcikge1xuICAgIHNlbC5hdHRyKFxuICAgICAgICAnZGlzcGxheScsXG4gICAgICAgICh4YS5pc1B0V2l0aGluUmFuZ2UoZCwgeGNhbGVuZGFyKSAmJiB5YS5pc1B0V2l0aGluUmFuZ2UoZCwgeWNhbGVuZGFyKSkgPyBudWxsIDogJ25vbmUnXG4gICAgKTtcbn07XG5cbmRyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50cyA9IGZ1bmN0aW9uKHRyYWNlR3JvdXBzLCBzdWJwbG90KSB7XG4gICAgaWYoIXN1YnBsb3QuX2hhc0NsaXBPbkF4aXNGYWxzZSkgcmV0dXJuO1xuXG4gICAgdmFyIHhhID0gc3VicGxvdC54YXhpcztcbiAgICB2YXIgeWEgPSBzdWJwbG90LnlheGlzO1xuXG4gICAgdHJhY2VHcm91cHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGRbMF0udHJhY2U7XG4gICAgICAgIHZhciB4Y2FsZW5kYXIgPSB0cmFjZS54Y2FsZW5kYXI7XG4gICAgICAgIHZhciB5Y2FsZW5kYXIgPSB0cmFjZS55Y2FsZW5kYXI7XG4gICAgICAgIHZhciBzZWxlY3RvciA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdiYXItbGlrZScpID8gJy5iYXJ0ZXh0JyA6ICcucG9pbnQsLnRleHRwb2ludCc7XG5cbiAgICAgICAgdHJhY2VHcm91cHMuc2VsZWN0QWxsKHNlbGVjdG9yKS5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGRyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50KGQsIGQzLnNlbGVjdCh0aGlzKSwgeGEsIHlhLCB4Y2FsZW5kYXIsIHljYWxlbmRhcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuZHJhd2luZy5jcmlzcFJvdW5kID0gZnVuY3Rpb24oZ2QsIGxpbmVXaWR0aCwgZGZsdCkge1xuICAgIC8vIGZvciBsaW5lcyB0aGF0IGRpc2FibGUgYW50aWFsaWFzaW5nIHdlIHdhbnQgdG9cbiAgICAvLyBtYWtlIHN1cmUgdGhlIHdpZHRoIGlzIGFuIGludGVnZXIsIGFuZCBhdCBsZWFzdCAxIGlmIGl0J3Mgbm9uemVyb1xuXG4gICAgaWYoIWxpbmVXaWR0aCB8fCAhaXNOdW1lcmljKGxpbmVXaWR0aCkpIHJldHVybiBkZmx0IHx8IDA7XG5cbiAgICAvLyBidXQgbm90IGZvciBzdGF0aWMgcGxvdHMgLSB0aGVzZSBkb24ndCBnZXQgYW50aWFsaWFzZWQgYW55d2F5LlxuICAgIGlmKGdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHJldHVybiBsaW5lV2lkdGg7XG5cbiAgICBpZihsaW5lV2lkdGggPCAxKSByZXR1cm4gMTtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChsaW5lV2lkdGgpO1xufTtcblxuZHJhd2luZy5zaW5nbGVMaW5lU3R5bGUgPSBmdW5jdGlvbihkLCBzLCBsdywgbGMsIGxkKSB7XG4gICAgcy5zdHlsZSgnZmlsbCcsICdub25lJyk7XG4gICAgdmFyIGxpbmUgPSAoKChkIHx8IFtdKVswXSB8fCB7fSkudHJhY2UgfHwge30pLmxpbmUgfHwge307XG4gICAgdmFyIGx3MSA9IGx3IHx8IGxpbmUud2lkdGggfHwgMDtcbiAgICB2YXIgZGFzaCA9IGxkIHx8IGxpbmUuZGFzaCB8fCAnJztcblxuICAgIENvbG9yLnN0cm9rZShzLCBsYyB8fCBsaW5lLmNvbG9yKTtcbiAgICBkcmF3aW5nLmRhc2hMaW5lKHMsIGRhc2gsIGx3MSk7XG59O1xuXG5kcmF3aW5nLmxpbmVHcm91cFN0eWxlID0gZnVuY3Rpb24ocywgbHcsIGxjLCBsZCkge1xuICAgIHMuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpXG4gICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgbGluZSA9ICgoKGQgfHwgW10pWzBdIHx8IHt9KS50cmFjZSB8fCB7fSkubGluZSB8fCB7fTtcbiAgICAgICAgdmFyIGx3MSA9IGx3IHx8IGxpbmUud2lkdGggfHwgMDtcbiAgICAgICAgdmFyIGRhc2ggPSBsZCB8fCBsaW5lLmRhc2ggfHwgJyc7XG5cbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIGxjIHx8IGxpbmUuY29sb3IpXG4gICAgICAgICAgICAuY2FsbChkcmF3aW5nLmRhc2hMaW5lLCBkYXNoLCBsdzEpO1xuICAgIH0pO1xufTtcblxuZHJhd2luZy5kYXNoTGluZSA9IGZ1bmN0aW9uKHMsIGRhc2gsIGxpbmVXaWR0aCkge1xuICAgIGxpbmVXaWR0aCA9ICtsaW5lV2lkdGggfHwgMDtcblxuICAgIGRhc2ggPSBkcmF3aW5nLmRhc2hTdHlsZShkYXNoLCBsaW5lV2lkdGgpO1xuXG4gICAgcy5zdHlsZSh7XG4gICAgICAgICdzdHJva2UtZGFzaGFycmF5JzogZGFzaCxcbiAgICAgICAgJ3N0cm9rZS13aWR0aCc6IGxpbmVXaWR0aCArICdweCdcbiAgICB9KTtcbn07XG5cbmRyYXdpbmcuZGFzaFN0eWxlID0gZnVuY3Rpb24oZGFzaCwgbGluZVdpZHRoKSB7XG4gICAgbGluZVdpZHRoID0gK2xpbmVXaWR0aCB8fCAxO1xuICAgIHZhciBkbHcgPSBNYXRoLm1heChsaW5lV2lkdGgsIDMpO1xuXG4gICAgaWYoZGFzaCA9PT0gJ3NvbGlkJykgZGFzaCA9ICcnO1xuICAgIGVsc2UgaWYoZGFzaCA9PT0gJ2RvdCcpIGRhc2ggPSBkbHcgKyAncHgsJyArIGRsdyArICdweCc7XG4gICAgZWxzZSBpZihkYXNoID09PSAnZGFzaCcpIGRhc2ggPSAoMyAqIGRsdykgKyAncHgsJyArICgzICogZGx3KSArICdweCc7XG4gICAgZWxzZSBpZihkYXNoID09PSAnbG9uZ2Rhc2gnKSBkYXNoID0gKDUgKiBkbHcpICsgJ3B4LCcgKyAoNSAqIGRsdykgKyAncHgnO1xuICAgIGVsc2UgaWYoZGFzaCA9PT0gJ2Rhc2hkb3QnKSB7XG4gICAgICAgIGRhc2ggPSAoMyAqIGRsdykgKyAncHgsJyArIGRsdyArICdweCwnICsgZGx3ICsgJ3B4LCcgKyBkbHcgKyAncHgnO1xuICAgIH0gZWxzZSBpZihkYXNoID09PSAnbG9uZ2Rhc2hkb3QnKSB7XG4gICAgICAgIGRhc2ggPSAoNSAqIGRsdykgKyAncHgsJyArICgyICogZGx3KSArICdweCwnICsgZGx3ICsgJ3B4LCcgKyAoMiAqIGRsdykgKyAncHgnO1xuICAgIH1cbiAgICAvLyBvdGhlcndpc2UgdXNlciB3cm90ZSB0aGUgZGFzaGFycmF5IHRoZW1zZWx2ZXMgLSBsZWF2ZSBpdCBiZVxuXG4gICAgcmV0dXJuIGRhc2g7XG59O1xuXG4vLyBTYW1lIGFzIGZpbGxHcm91cFN0eWxlLCBleGNlcHQgaW4gdGhpcyBjYXNlIHRoZSBzZWxlY3Rpb24gbWF5IGJlIGEgdHJhbnNpdGlvblxuZHJhd2luZy5zaW5nbGVGaWxsU3R5bGUgPSBmdW5jdGlvbihzZWwpIHtcbiAgICB2YXIgbm9kZSA9IGQzLnNlbGVjdChzZWwubm9kZSgpKTtcbiAgICB2YXIgZGF0YSA9IG5vZGUuZGF0YSgpO1xuICAgIHZhciBmaWxsY29sb3IgPSAoKChkYXRhWzBdIHx8IFtdKVswXSB8fCB7fSkudHJhY2UgfHwge30pLmZpbGxjb2xvcjtcbiAgICBpZihmaWxsY29sb3IpIHtcbiAgICAgICAgc2VsLmNhbGwoQ29sb3IuZmlsbCwgZmlsbGNvbG9yKTtcbiAgICB9XG59O1xuXG5kcmF3aW5nLmZpbGxHcm91cFN0eWxlID0gZnVuY3Rpb24ocykge1xuICAgIHMuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIDApXG4gICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgc2hhcGUgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIC8vIE4uQi4gJ2QnIHdvbid0IGJlIGEgY2FsY2RhdGEgaXRlbSB3aGVuXG4gICAgICAgIC8vIGZpbGwgIT09ICdub25lJyBvbiBhIHNlZ21lbnQtbGVzcyBhbmQgbWFya2VyLWxlc3MgdHJhY2VcbiAgICAgICAgaWYoZFswXS50cmFjZSkge1xuICAgICAgICAgICAgc2hhcGUuY2FsbChDb2xvci5maWxsLCBkWzBdLnRyYWNlLmZpbGxjb2xvcik7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbnZhciBTWU1CT0xERUZTID0gX2RlcmVxXygnLi9zeW1ib2xfZGVmcycpO1xuXG5kcmF3aW5nLnN5bWJvbE5hbWVzID0gW107XG5kcmF3aW5nLnN5bWJvbEZ1bmNzID0gW107XG5kcmF3aW5nLnN5bWJvbE5lZWRMaW5lcyA9IHt9O1xuZHJhd2luZy5zeW1ib2xOb0RvdCA9IHt9O1xuZHJhd2luZy5zeW1ib2xOb0ZpbGwgPSB7fTtcbmRyYXdpbmcuc3ltYm9sTGlzdCA9IFtdO1xuXG5PYmplY3Qua2V5cyhTWU1CT0xERUZTKS5mb3JFYWNoKGZ1bmN0aW9uKGspIHtcbiAgICB2YXIgc3ltRGVmID0gU1lNQk9MREVGU1trXTtcbiAgICBkcmF3aW5nLnN5bWJvbExpc3QgPSBkcmF3aW5nLnN5bWJvbExpc3QuY29uY2F0KFxuICAgICAgICBbc3ltRGVmLm4sIGssIHN5bURlZi5uICsgMTAwLCBrICsgJy1vcGVuJ10pO1xuICAgIGRyYXdpbmcuc3ltYm9sTmFtZXNbc3ltRGVmLm5dID0gaztcbiAgICBkcmF3aW5nLnN5bWJvbEZ1bmNzW3N5bURlZi5uXSA9IHN5bURlZi5mO1xuICAgIGlmKHN5bURlZi5uZWVkTGluZSkge1xuICAgICAgICBkcmF3aW5nLnN5bWJvbE5lZWRMaW5lc1tzeW1EZWYubl0gPSB0cnVlO1xuICAgIH1cbiAgICBpZihzeW1EZWYubm9Eb3QpIHtcbiAgICAgICAgZHJhd2luZy5zeW1ib2xOb0RvdFtzeW1EZWYubl0gPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRyYXdpbmcuc3ltYm9sTGlzdCA9IGRyYXdpbmcuc3ltYm9sTGlzdC5jb25jYXQoXG4gICAgICAgICAgICBbc3ltRGVmLm4gKyAyMDAsIGsgKyAnLWRvdCcsIHN5bURlZi5uICsgMzAwLCBrICsgJy1vcGVuLWRvdCddKTtcbiAgICB9XG4gICAgaWYoc3ltRGVmLm5vRmlsbCkge1xuICAgICAgICBkcmF3aW5nLnN5bWJvbE5vRmlsbFtzeW1EZWYubl0gPSB0cnVlO1xuICAgIH1cbn0pO1xuXG52YXIgTUFYU1lNQk9MID0gZHJhd2luZy5zeW1ib2xOYW1lcy5sZW5ndGg7XG4vLyBhZGQgYSBkb3QgaW4gdGhlIG1pZGRsZSBvZiB0aGUgc3ltYm9sXG52YXIgRE9UUEFUSCA9ICdNMCwwLjVMMC41LDBMMCwtMC41TC0wLjUsMFonO1xuXG5kcmF3aW5nLnN5bWJvbE51bWJlciA9IGZ1bmN0aW9uKHYpIHtcbiAgICBpZih0eXBlb2YgdiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIHZiYXNlID0gMDtcbiAgICAgICAgaWYodi5pbmRleE9mKCctb3BlbicpID4gMCkge1xuICAgICAgICAgICAgdmJhc2UgPSAxMDA7XG4gICAgICAgICAgICB2ID0gdi5yZXBsYWNlKCctb3BlbicsICcnKTtcbiAgICAgICAgfVxuICAgICAgICBpZih2LmluZGV4T2YoJy1kb3QnKSA+IDApIHtcbiAgICAgICAgICAgIHZiYXNlICs9IDIwMDtcbiAgICAgICAgICAgIHYgPSB2LnJlcGxhY2UoJy1kb3QnLCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgdiA9IGRyYXdpbmcuc3ltYm9sTmFtZXMuaW5kZXhPZih2KTtcbiAgICAgICAgaWYodiA+PSAwKSB7IHYgKz0gdmJhc2U7IH1cbiAgICB9XG4gICAgaWYoKHYgJSAxMDAgPj0gTUFYU1lNQk9MKSB8fCB2ID49IDQwMCkgeyByZXR1cm4gMDsgfVxuICAgIHJldHVybiBNYXRoLmZsb29yKE1hdGgubWF4KHYsIDApKTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VQb2ludFBhdGgoc3ltYm9sTnVtYmVyLCByKSB7XG4gICAgdmFyIGJhc2UgPSBzeW1ib2xOdW1iZXIgJSAxMDA7XG4gICAgcmV0dXJuIGRyYXdpbmcuc3ltYm9sRnVuY3NbYmFzZV0ocikgKyAoc3ltYm9sTnVtYmVyID49IDIwMCA/IERPVFBBVEggOiAnJyk7XG59XG5cbnZhciBIT1JaR1JBRElFTlQgPSB7eDE6IDEsIHgyOiAwLCB5MTogMCwgeTI6IDB9O1xudmFyIFZFUlRHUkFESUVOVCA9IHt4MTogMCwgeDI6IDAsIHkxOiAxLCB5MjogMH07XG52YXIgc3RvcEZvcm1hdHRlciA9IGQzLmZvcm1hdCgnfi4xZicpO1xudmFyIGdyYWRpZW50SW5mbyA9IHtcbiAgICByYWRpYWw6IHtub2RlOiAncmFkaWFsR3JhZGllbnQnfSxcbiAgICByYWRpYWxyZXZlcnNlZDoge25vZGU6ICdyYWRpYWxHcmFkaWVudCcsIHJldmVyc2VkOiB0cnVlfSxcbiAgICBob3Jpem9udGFsOiB7bm9kZTogJ2xpbmVhckdyYWRpZW50JywgYXR0cnM6IEhPUlpHUkFESUVOVH0sXG4gICAgaG9yaXpvbnRhbHJldmVyc2VkOiB7bm9kZTogJ2xpbmVhckdyYWRpZW50JywgYXR0cnM6IEhPUlpHUkFESUVOVCwgcmV2ZXJzZWQ6IHRydWV9LFxuICAgIHZlcnRpY2FsOiB7bm9kZTogJ2xpbmVhckdyYWRpZW50JywgYXR0cnM6IFZFUlRHUkFESUVOVH0sXG4gICAgdmVydGljYWxyZXZlcnNlZDoge25vZGU6ICdsaW5lYXJHcmFkaWVudCcsIGF0dHJzOiBWRVJUR1JBRElFTlQsIHJldmVyc2VkOiB0cnVlfVxufTtcblxuLyoqXG4gKiBncmFkaWVudDogY3JlYXRlIGFuZCBhcHBseSBhIGdyYWRpZW50IGZpbGxcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gc2VsOiBkMyBzZWxlY3Rpb24gdG8gYXBwbHkgdGhpcyBncmFkaWVudCB0b1xuICogICAgIFlvdSBjYW4gdXNlIGBzZWxlY3Rpb24uY2FsbChEcmF3aW5nLmdyYWRpZW50LCAuLi4pYFxuICogQHBhcmFtIHtET00gZWxlbWVudH0gZ2Q6IHRoZSBncmFwaCBkaXYgYHNlbGAgaXMgcGFydCBvZlxuICogQHBhcmFtIHtzdHJpbmd9IGdyYWRpZW50SUQ6IGEgdW5pcXVlICh3aXRoaW4gdGhpcyBwbG90KSBpZGVudGlmaWVyXG4gKiAgICAgZm9yIHRoaXMgZ3JhZGllbnQsIHNvIHRoYXQgd2UgZG9uJ3QgY3JlYXRlIHVubmVjZXNzYXJ5IGRlZmluaXRpb25zXG4gKiBAcGFyYW0ge3N0cmluZ30gdHlwZTogJ3JhZGlhbCcsICdob3Jpem9udGFsJywgb3IgJ3ZlcnRpY2FsJywgb3B0aW9uYWxseSB3aXRoXG4gKiAgICAgJ3JldmVyc2VkJyBhdCB0aGUgZW5kLiBOb3JtYWxseSByYWRpYWwgZ29lcyBjZW50ZXIgdG8gZWRnZSxcbiAqICAgICBob3Jpem9udGFsIGdvZXMgcmlnaHQgdG8gbGVmdCwgYW5kIHZlcnRpY2FsIGdvZXMgYm90dG9tIHRvIHRvcFxuICogQHBhcmFtIHthcnJheX0gY29sb3JzY2FsZTogYXMgaW4gYXR0cmlidXRlIHZhbHVlcywgW1tmcmFjdGlvbiwgY29sb3JdLCAuLi5dXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcDogdGhlIHByb3BlcnR5IHRvIGFwcGx5IHRvLCAnZmlsbCcgb3IgJ3N0cm9rZSdcbiAqL1xuZHJhd2luZy5ncmFkaWVudCA9IGZ1bmN0aW9uKHNlbCwgZ2QsIGdyYWRpZW50SUQsIHR5cGUsIGNvbG9yc2NhbGUsIHByb3ApIHtcbiAgICB2YXIgbGVuID0gY29sb3JzY2FsZS5sZW5ndGg7XG4gICAgdmFyIGluZm8gPSBncmFkaWVudEluZm9bdHlwZV07XG4gICAgdmFyIGNvbG9yU3RvcHMgPSBuZXcgQXJyYXkobGVuKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaWYoaW5mby5yZXZlcnNlZCkge1xuICAgICAgICAgICAgY29sb3JTdG9wc1tsZW4gLSAxIC0gaV0gPSBbc3RvcEZvcm1hdHRlcigoMSAtIGNvbG9yc2NhbGVbaV1bMF0pICogMTAwKSwgY29sb3JzY2FsZVtpXVsxXV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb2xvclN0b3BzW2ldID0gW3N0b3BGb3JtYXR0ZXIoY29sb3JzY2FsZVtpXVswXSAqIDEwMCksIGNvbG9yc2NhbGVbaV1bMV1dO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGZ1bGxJRCA9ICdnJyArIGdkLl9mdWxsTGF5b3V0Ll91aWQgKyAnLScgKyBncmFkaWVudElEO1xuXG4gICAgdmFyIGdyYWRpZW50ID0gZ2QuX2Z1bGxMYXlvdXQuX2RlZnMuc2VsZWN0KCcuZ3JhZGllbnRzJylcbiAgICAgICAgLnNlbGVjdEFsbCgnIycgKyBmdWxsSUQpXG4gICAgICAgIC5kYXRhKFt0eXBlICsgY29sb3JTdG9wcy5qb2luKCc7JyldLCBMaWIuaWRlbnRpdHkpO1xuXG4gICAgZ3JhZGllbnQuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgZ3JhZGllbnQuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKGluZm8ubm9kZSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBpZihpbmZvLmF0dHJzKSBlbC5hdHRyKGluZm8uYXR0cnMpO1xuXG4gICAgICAgICAgICBlbC5hdHRyKCdpZCcsIGZ1bGxJRCk7XG5cbiAgICAgICAgICAgIHZhciBzdG9wcyA9IGVsLnNlbGVjdEFsbCgnc3RvcCcpXG4gICAgICAgICAgICAgICAgLmRhdGEoY29sb3JTdG9wcyk7XG4gICAgICAgICAgICBzdG9wcy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgICAgICBzdG9wcy5lbnRlcigpLmFwcGVuZCgnc3RvcCcpO1xuXG4gICAgICAgICAgICBzdG9wcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGMgPSB0aW55Y29sb3IoZFsxXSk7XG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IGRbMF0gKyAnJScsXG4gICAgICAgICAgICAgICAgICAgICdzdG9wLWNvbG9yJzogQ29sb3IudGlueVJHQih0YyksXG4gICAgICAgICAgICAgICAgICAgICdzdG9wLW9wYWNpdHknOiB0Yy5nZXRBbHBoYSgpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICBzZWwuc3R5bGUocHJvcCwgZ2V0RnVsbFVybChmdWxsSUQsIGdkKSlcbiAgICAgICAgLnN0eWxlKHByb3AgKyAnLW9wYWNpdHknLCBudWxsKTtcbn07XG5cbi8qXG4gKiBNYWtlIHRoZSBncmFkaWVudHMgY29udGFpbmVyIGFuZCBjbGVhciBvdXQgYW55IHByZXZpb3VzIGdyYWRpZW50cy5cbiAqIFdlIG5ldmVyIGNvbGxlY3QgYWxsIHRoZSBncmFkaWVudHMgd2UgbmVlZCBpbiBvbmUgcGxhY2UsXG4gKiBzbyB3ZSBjYW4ndCBldmVyIHJlbW92ZSBncmFkaWVudHMgdGhhdCBoYXZlIHN0b3BwZWQgYmVpbmcgdXNlZnVsLFxuICogZXhjZXB0IGFsbCBhdCBvbmNlIGJlZm9yZSBhIGZ1bGwgcmVkcmF3LlxuICogVGhlIHVwc2lkZSBvZiB0aGlzIGlzIGFyYml0cmFyeSBwb2ludHMgY2FuIHNoYXJlIGdyYWRpZW50IGRlZnNcbiAqL1xuZHJhd2luZy5pbml0R3JhZGllbnRzID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZ3JhZGllbnRzR3JvdXAgPSBMaWIuZW5zdXJlU2luZ2xlKGdkLl9mdWxsTGF5b3V0Ll9kZWZzLCAnZycsICdncmFkaWVudHMnKTtcbiAgICBncmFkaWVudHNHcm91cC5zZWxlY3RBbGwoJ2xpbmVhckdyYWRpZW50LHJhZGlhbEdyYWRpZW50JykucmVtb3ZlKCk7XG59O1xuXG5cbmRyYXdpbmcucG9pbnRTdHlsZSA9IGZ1bmN0aW9uKHMsIHRyYWNlLCBnZCkge1xuICAgIGlmKCFzLnNpemUoKSkgcmV0dXJuO1xuXG4gICAgdmFyIGZucyA9IGRyYXdpbmcubWFrZVBvaW50U3R5bGVGbnModHJhY2UpO1xuXG4gICAgcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgZHJhd2luZy5zaW5nbGVQb2ludFN0eWxlKGQsIGQzLnNlbGVjdCh0aGlzKSwgdHJhY2UsIGZucywgZ2QpO1xuICAgIH0pO1xufTtcblxuZHJhd2luZy5zaW5nbGVQb2ludFN0eWxlID0gZnVuY3Rpb24oZCwgc2VsLCB0cmFjZSwgZm5zLCBnZCkge1xuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXI7XG4gICAgdmFyIG1hcmtlckxpbmUgPSBtYXJrZXIubGluZTtcblxuICAgIHNlbC5zdHlsZSgnb3BhY2l0eScsXG4gICAgICAgIGZucy5zZWxlY3RlZE9wYWNpdHlGbiA/IGZucy5zZWxlY3RlZE9wYWNpdHlGbihkKSA6XG4gICAgICAgICAgICAoZC5tbyA9PT0gdW5kZWZpbmVkID8gbWFya2VyLm9wYWNpdHkgOiBkLm1vKVxuICAgICk7XG5cbiAgICBpZihmbnMubXMybXJjKSB7XG4gICAgICAgIHZhciByO1xuXG4gICAgICAgIC8vIGhhbmRsZSBtdWx0aS10cmFjZSBncmFwaCBlZGl0IGNhc2VcbiAgICAgICAgaWYoZC5tcyA9PT0gJ3ZhcmlvdXMnIHx8IG1hcmtlci5zaXplID09PSAndmFyaW91cycpIHtcbiAgICAgICAgICAgIHIgPSAzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgciA9IGZucy5tczJtcmMoZC5tcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzdG9yZSB0aGUgY2FsY3VsYXRlZCBzaXplIHNvIGhvdmVyIGNhbiB1c2UgaXRcbiAgICAgICAgZC5tcmMgPSByO1xuXG4gICAgICAgIGlmKGZucy5zZWxlY3RlZFNpemVGbikge1xuICAgICAgICAgICAgciA9IGQubXJjID0gZm5zLnNlbGVjdGVkU2l6ZUZuKGQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHVybiB0aGUgc3ltYm9sIGludG8gYSBzYW5pdGl6ZWQgbnVtYmVyXG4gICAgICAgIHZhciB4ID0gZHJhd2luZy5zeW1ib2xOdW1iZXIoZC5teCB8fCBtYXJrZXIuc3ltYm9sKSB8fCAwO1xuXG4gICAgICAgIC8vIHNhdmUgaWYgdGhpcyBtYXJrZXIgaXMgb3BlblxuICAgICAgICAvLyBiZWNhdXNlIHRoYXQgaW1wYWN0cyBob3cgdG8gaGFuZGxlIGNvbG9yc1xuICAgICAgICBkLm9tID0geCAlIDIwMCA+PSAxMDA7XG5cbiAgICAgICAgc2VsLmF0dHIoJ2QnLCBtYWtlUG9pbnRQYXRoKHgsIHIpKTtcbiAgICB9XG5cbiAgICB2YXIgcGVyUG9pbnRHcmFkaWVudCA9IGZhbHNlO1xuICAgIHZhciBmaWxsQ29sb3IsIGxpbmVDb2xvciwgbGluZVdpZHRoO1xuXG4gICAgLy8gJ3NvJyBpcyBzdXNwZWN0ZWQgb3V0bGllcnMsIGZvciBib3ggcGxvdHNcbiAgICBpZihkLnNvKSB7XG4gICAgICAgIGxpbmVXaWR0aCA9IG1hcmtlckxpbmUub3V0bGllcndpZHRoO1xuICAgICAgICBsaW5lQ29sb3IgPSBtYXJrZXJMaW5lLm91dGxpZXJjb2xvcjtcbiAgICAgICAgZmlsbENvbG9yID0gbWFya2VyLm91dGxpZXJjb2xvcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbWFya2VyTGluZVdpZHRoID0gKG1hcmtlckxpbmUgfHwge30pLndpZHRoO1xuXG4gICAgICAgIGxpbmVXaWR0aCA9IChcbiAgICAgICAgICAgIGQubWx3ICsgMSB8fFxuICAgICAgICAgICAgbWFya2VyTGluZVdpZHRoICsgMSB8fFxuICAgICAgICAgICAgLy8gVE9ETzogd2UgbmVlZCB0aGUgbGF0dGVyIGZvciBsZWdlbmRzLi4uIGNhbiB3ZSBnZXQgcmlkIG9mIGl0P1xuICAgICAgICAgICAgKGQudHJhY2UgPyAoZC50cmFjZS5tYXJrZXIubGluZSB8fCB7fSkud2lkdGggOiAwKSArIDFcbiAgICAgICAgKSAtIDEgfHwgMDtcblxuICAgICAgICBpZignbWxjJyBpbiBkKSBsaW5lQ29sb3IgPSBkLm1sY2MgPSBmbnMubGluZVNjYWxlKGQubWxjKTtcbiAgICAgICAgLy8gd2VpcmQgY2FzZTogYXJyYXkgd2Fzbid0IGxvbmcgZW5vdWdoIHRvIGFwcGx5IHRvIGV2ZXJ5IHBvaW50XG4gICAgICAgIGVsc2UgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyTGluZS5jb2xvcikpIGxpbmVDb2xvciA9IENvbG9yLmRlZmF1bHRMaW5lO1xuICAgICAgICBlbHNlIGxpbmVDb2xvciA9IG1hcmtlckxpbmUuY29sb3I7XG5cbiAgICAgICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyLmNvbG9yKSkge1xuICAgICAgICAgICAgZmlsbENvbG9yID0gQ29sb3IuZGVmYXVsdExpbmU7XG4gICAgICAgICAgICBwZXJQb2ludEdyYWRpZW50ID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCdtYycgaW4gZCkge1xuICAgICAgICAgICAgZmlsbENvbG9yID0gZC5tY2MgPSBmbnMubWFya2VyU2NhbGUoZC5tYyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmaWxsQ29sb3IgPSBtYXJrZXIuY29sb3IgfHwgJ3JnYmEoMCwwLDAsMCknO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZm5zLnNlbGVjdGVkQ29sb3JGbikge1xuICAgICAgICAgICAgZmlsbENvbG9yID0gZm5zLnNlbGVjdGVkQ29sb3JGbihkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGQub20pIHtcbiAgICAgICAgLy8gb3BlbiBtYXJrZXJzIGNhbid0IGhhdmUgemVybyBsaW5ld2lkdGgsIGRlZmF1bHQgdG8gMXB4LFxuICAgICAgICAvLyBhbmQgdXNlIGZpbGwgY29sb3IgYXMgc3Ryb2tlIGNvbG9yXG4gICAgICAgIHNlbC5jYWxsKENvbG9yLnN0cm9rZSwgZmlsbENvbG9yKVxuICAgICAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogKGxpbmVXaWR0aCB8fCAxKSArICdweCcsXG4gICAgICAgICAgICAgICAgZmlsbDogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzZWwuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIGxpbmVXaWR0aCArICdweCcpO1xuXG4gICAgICAgIHZhciBtYXJrZXJHcmFkaWVudCA9IG1hcmtlci5ncmFkaWVudDtcblxuICAgICAgICB2YXIgZ3JhZGllbnRUeXBlID0gZC5tZ3Q7XG4gICAgICAgIGlmKGdyYWRpZW50VHlwZSkgcGVyUG9pbnRHcmFkaWVudCA9IHRydWU7XG4gICAgICAgIGVsc2UgZ3JhZGllbnRUeXBlID0gbWFya2VyR3JhZGllbnQgJiYgbWFya2VyR3JhZGllbnQudHlwZTtcblxuICAgICAgICAvLyBmb3IgbGVnZW5kIC0gYXJyYXlzIHdpbGwgcHJvcGFnYXRlIHRocm91Z2ggaGVyZSwgYnV0IHdlIGRvbid0IG5lZWRcbiAgICAgICAgLy8gdG8gdHJlYXQgaXQgYXMgcGVyLXBvaW50LlxuICAgICAgICBpZihBcnJheS5pc0FycmF5KGdyYWRpZW50VHlwZSkpIHtcbiAgICAgICAgICAgIGdyYWRpZW50VHlwZSA9IGdyYWRpZW50VHlwZVswXTtcbiAgICAgICAgICAgIGlmKCFncmFkaWVudEluZm9bZ3JhZGllbnRUeXBlXSkgZ3JhZGllbnRUeXBlID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGdyYWRpZW50VHlwZSAmJiBncmFkaWVudFR5cGUgIT09ICdub25lJykge1xuICAgICAgICAgICAgdmFyIGdyYWRpZW50Q29sb3IgPSBkLm1nYztcbiAgICAgICAgICAgIGlmKGdyYWRpZW50Q29sb3IpIHBlclBvaW50R3JhZGllbnQgPSB0cnVlO1xuICAgICAgICAgICAgZWxzZSBncmFkaWVudENvbG9yID0gbWFya2VyR3JhZGllbnQuY29sb3I7XG5cbiAgICAgICAgICAgIHZhciBncmFkaWVudElEID0gdHJhY2UudWlkO1xuICAgICAgICAgICAgaWYocGVyUG9pbnRHcmFkaWVudCkgZ3JhZGllbnRJRCArPSAnLScgKyBkLmk7XG5cbiAgICAgICAgICAgIGRyYXdpbmcuZ3JhZGllbnQoc2VsLCBnZCwgZ3JhZGllbnRJRCwgZ3JhZGllbnRUeXBlLFxuICAgICAgICAgICAgICAgIFtbMCwgZ3JhZGllbnRDb2xvcl0sIFsxLCBmaWxsQ29sb3JdXSwgJ2ZpbGwnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIENvbG9yLmZpbGwoc2VsLCBmaWxsQ29sb3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobGluZVdpZHRoKSB7XG4gICAgICAgICAgICBDb2xvci5zdHJva2Uoc2VsLCBsaW5lQ29sb3IpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuZHJhd2luZy5tYWtlUG9pbnRTdHlsZUZucyA9IGZ1bmN0aW9uKHRyYWNlKSB7XG4gICAgdmFyIG91dCA9IHt9O1xuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXI7XG5cbiAgICAvLyBhbGxvdyBhcnJheSBtYXJrZXIgYW5kIG1hcmtlciBsaW5lIGNvbG9ycyB0byBiZVxuICAgIC8vIHNjYWxlZCBieSBnaXZlbiBtYXggYW5kIG1pbiB0byBjb2xvcnNjYWxlc1xuICAgIG91dC5tYXJrZXJTY2FsZSA9IGRyYXdpbmcudHJ5Q29sb3JzY2FsZShtYXJrZXIsICcnKTtcbiAgICBvdXQubGluZVNjYWxlID0gZHJhd2luZy50cnlDb2xvcnNjYWxlKG1hcmtlciwgJ2xpbmUnKTtcblxuICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdzeW1ib2xzJykpIHtcbiAgICAgICAgb3V0Lm1zMm1yYyA9IHN1YlR5cGVzLmlzQnViYmxlKHRyYWNlKSA/XG4gICAgICAgICAgICBtYWtlQnViYmxlU2l6ZUZuKHRyYWNlKSA6XG4gICAgICAgICAgICBmdW5jdGlvbigpIHsgcmV0dXJuIChtYXJrZXIuc2l6ZSB8fCA2KSAvIDI7IH07XG4gICAgfVxuXG4gICAgaWYodHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHtcbiAgICAgICAgTGliLmV4dGVuZEZsYXQob3V0LCBkcmF3aW5nLm1ha2VTZWxlY3RlZFBvaW50U3R5bGVGbnModHJhY2UpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZHJhd2luZy5tYWtlU2VsZWN0ZWRQb2ludFN0eWxlRm5zID0gZnVuY3Rpb24odHJhY2UpIHtcbiAgICB2YXIgb3V0ID0ge307XG5cbiAgICB2YXIgc2VsZWN0ZWRBdHRycyA9IHRyYWNlLnNlbGVjdGVkIHx8IHt9O1xuICAgIHZhciB1bnNlbGVjdGVkQXR0cnMgPSB0cmFjZS51bnNlbGVjdGVkIHx8IHt9O1xuXG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlciB8fCB7fTtcbiAgICB2YXIgc2VsZWN0ZWRNYXJrZXIgPSBzZWxlY3RlZEF0dHJzLm1hcmtlciB8fCB7fTtcbiAgICB2YXIgdW5zZWxlY3RlZE1hcmtlciA9IHVuc2VsZWN0ZWRBdHRycy5tYXJrZXIgfHwge307XG5cbiAgICB2YXIgbW8gPSBtYXJrZXIub3BhY2l0eTtcbiAgICB2YXIgc21vID0gc2VsZWN0ZWRNYXJrZXIub3BhY2l0eTtcbiAgICB2YXIgdXNtbyA9IHVuc2VsZWN0ZWRNYXJrZXIub3BhY2l0eTtcbiAgICB2YXIgc21vSXNEZWZpbmVkID0gc21vICE9PSB1bmRlZmluZWQ7XG4gICAgdmFyIHVzbW9Jc0RlZmluZWQgPSB1c21vICE9PSB1bmRlZmluZWQ7XG5cbiAgICBpZihMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtbykgfHwgc21vSXNEZWZpbmVkIHx8IHVzbW9Jc0RlZmluZWQpIHtcbiAgICAgICAgb3V0LnNlbGVjdGVkT3BhY2l0eUZuID0gZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGJhc2UgPSBkLm1vID09PSB1bmRlZmluZWQgPyBtYXJrZXIub3BhY2l0eSA6IGQubW87XG5cbiAgICAgICAgICAgIGlmKGQuc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc21vSXNEZWZpbmVkID8gc21vIDogYmFzZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVzbW9Jc0RlZmluZWQgPyB1c21vIDogREVTRUxFQ1RESU0gKiBiYXNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBtYyA9IG1hcmtlci5jb2xvcjtcbiAgICB2YXIgc21jID0gc2VsZWN0ZWRNYXJrZXIuY29sb3I7XG4gICAgdmFyIHVzbWMgPSB1bnNlbGVjdGVkTWFya2VyLmNvbG9yO1xuXG4gICAgaWYoc21jIHx8IHVzbWMpIHtcbiAgICAgICAgb3V0LnNlbGVjdGVkQ29sb3JGbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBiYXNlID0gZC5tY2MgfHwgbWM7XG5cbiAgICAgICAgICAgIGlmKGQuc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc21jIHx8IGJhc2U7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB1c21jIHx8IGJhc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIG1zID0gbWFya2VyLnNpemU7XG4gICAgdmFyIHNtcyA9IHNlbGVjdGVkTWFya2VyLnNpemU7XG4gICAgdmFyIHVzbXMgPSB1bnNlbGVjdGVkTWFya2VyLnNpemU7XG4gICAgdmFyIHNtc0lzRGVmaW5lZCA9IHNtcyAhPT0gdW5kZWZpbmVkO1xuICAgIHZhciB1c21zSXNEZWZpbmVkID0gdXNtcyAhPT0gdW5kZWZpbmVkO1xuXG4gICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3N5bWJvbHMnKSAmJiAoc21zSXNEZWZpbmVkIHx8IHVzbXNJc0RlZmluZWQpKSB7XG4gICAgICAgIG91dC5zZWxlY3RlZFNpemVGbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBiYXNlID0gZC5tcmMgfHwgbXMgLyAyO1xuXG4gICAgICAgICAgICBpZihkLnNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNtc0lzRGVmaW5lZCA/IHNtcyAvIDIgOiBiYXNlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdXNtc0lzRGVmaW5lZCA/IHVzbXMgLyAyIDogYmFzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZHJhd2luZy5tYWtlU2VsZWN0ZWRUZXh0U3R5bGVGbnMgPSBmdW5jdGlvbih0cmFjZSkge1xuICAgIHZhciBvdXQgPSB7fTtcblxuICAgIHZhciBzZWxlY3RlZEF0dHJzID0gdHJhY2Uuc2VsZWN0ZWQgfHwge307XG4gICAgdmFyIHVuc2VsZWN0ZWRBdHRycyA9IHRyYWNlLnVuc2VsZWN0ZWQgfHwge307XG5cbiAgICB2YXIgdGV4dEZvbnQgPSB0cmFjZS50ZXh0Zm9udCB8fCB7fTtcbiAgICB2YXIgc2VsZWN0ZWRUZXh0Rm9udCA9IHNlbGVjdGVkQXR0cnMudGV4dGZvbnQgfHwge307XG4gICAgdmFyIHVuc2VsZWN0ZWRUZXh0Rm9udCA9IHVuc2VsZWN0ZWRBdHRycy50ZXh0Zm9udCB8fCB7fTtcblxuICAgIHZhciB0YyA9IHRleHRGb250LmNvbG9yO1xuICAgIHZhciBzdGMgPSBzZWxlY3RlZFRleHRGb250LmNvbG9yO1xuICAgIHZhciB1dGMgPSB1bnNlbGVjdGVkVGV4dEZvbnQuY29sb3I7XG5cbiAgICBvdXQuc2VsZWN0ZWRUZXh0Q29sb3JGbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGJhc2UgPSBkLnRjIHx8IHRjO1xuXG4gICAgICAgIGlmKGQuc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBzdGMgfHwgYmFzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKHV0YykgcmV0dXJuIHV0YztcbiAgICAgICAgICAgIGVsc2UgcmV0dXJuIHN0YyA/IGJhc2UgOiBDb2xvci5hZGRPcGFjaXR5KGJhc2UsIERFU0VMRUNURElNKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZHJhd2luZy5zZWxlY3RlZFBvaW50U3R5bGUgPSBmdW5jdGlvbihzLCB0cmFjZSkge1xuICAgIGlmKCFzLnNpemUoKSB8fCAhdHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHJldHVybjtcblxuICAgIHZhciBmbnMgPSBkcmF3aW5nLm1ha2VTZWxlY3RlZFBvaW50U3R5bGVGbnModHJhY2UpO1xuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXIgfHwge307XG4gICAgdmFyIHNlcSA9IFtdO1xuXG4gICAgaWYoZm5zLnNlbGVjdGVkT3BhY2l0eUZuKSB7XG4gICAgICAgIHNlcS5wdXNoKGZ1bmN0aW9uKHB0LCBkKSB7XG4gICAgICAgICAgICBwdC5zdHlsZSgnb3BhY2l0eScsIGZucy5zZWxlY3RlZE9wYWNpdHlGbihkKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKGZucy5zZWxlY3RlZENvbG9yRm4pIHtcbiAgICAgICAgc2VxLnB1c2goZnVuY3Rpb24ocHQsIGQpIHtcbiAgICAgICAgICAgIENvbG9yLmZpbGwocHQsIGZucy5zZWxlY3RlZENvbG9yRm4oZCkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihmbnMuc2VsZWN0ZWRTaXplRm4pIHtcbiAgICAgICAgc2VxLnB1c2goZnVuY3Rpb24ocHQsIGQpIHtcbiAgICAgICAgICAgIHZhciBteCA9IGQubXggfHwgbWFya2VyLnN5bWJvbCB8fCAwO1xuICAgICAgICAgICAgdmFyIG1yYzIgPSBmbnMuc2VsZWN0ZWRTaXplRm4oZCk7XG5cbiAgICAgICAgICAgIHB0LmF0dHIoJ2QnLCBtYWtlUG9pbnRQYXRoKGRyYXdpbmcuc3ltYm9sTnVtYmVyKG14KSwgbXJjMikpO1xuXG4gICAgICAgICAgICAvLyBzYXZlIGZvciBEcmF3aW5nLnNlbGVjdGVkVGV4dFN0eWxlXG4gICAgICAgICAgICBkLm1yYzIgPSBtcmMyO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihzZXEubGVuZ3RoKSB7XG4gICAgICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgcHQgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2VxLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgc2VxW2ldKHB0LCBkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxuZHJhd2luZy50cnlDb2xvcnNjYWxlID0gZnVuY3Rpb24obWFya2VyLCBwcmVmaXgpIHtcbiAgICB2YXIgY29udCA9IHByZWZpeCA/IExpYi5uZXN0ZWRQcm9wZXJ0eShtYXJrZXIsIHByZWZpeCkuZ2V0KCkgOiBtYXJrZXI7XG5cbiAgICBpZihjb250KSB7XG4gICAgICAgIHZhciBjb2xvckFycmF5ID0gY29udC5jb2xvcjtcbiAgICAgICAgaWYoKGNvbnQuY29sb3JzY2FsZSB8fCBjb250Ll9jb2xvckF4KSAmJiBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShjb2xvckFycmF5KSkge1xuICAgICAgICAgICAgcmV0dXJuIENvbG9yc2NhbGUubWFrZUNvbG9yU2NhbGVGdW5jRnJvbVRyYWNlKGNvbnQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBMaWIuaWRlbnRpdHk7XG59O1xuXG52YXIgVEVYVE9GRlNFVFNJR04gPSB7XG4gICAgc3RhcnQ6IDEsIGVuZDogLTEsIG1pZGRsZTogMCwgYm90dG9tOiAxLCB0b3A6IC0xXG59O1xuXG5mdW5jdGlvbiB0ZXh0UG9pbnRQb3NpdGlvbihzLCB0ZXh0UG9zaXRpb24sIGZvbnRTaXplLCBtYXJrZXJSYWRpdXMpIHtcbiAgICB2YXIgZ3JvdXAgPSBkMy5zZWxlY3Qocy5ub2RlKCkucGFyZW50Tm9kZSk7XG5cbiAgICB2YXIgdiA9IHRleHRQb3NpdGlvbi5pbmRleE9mKCd0b3AnKSAhPT0gLTEgP1xuICAgICAgICAndG9wJyA6XG4gICAgICAgIHRleHRQb3NpdGlvbi5pbmRleE9mKCdib3R0b20nKSAhPT0gLTEgPyAnYm90dG9tJyA6ICdtaWRkbGUnO1xuICAgIHZhciBoID0gdGV4dFBvc2l0aW9uLmluZGV4T2YoJ2xlZnQnKSAhPT0gLTEgP1xuICAgICAgICAnZW5kJyA6XG4gICAgICAgIHRleHRQb3NpdGlvbi5pbmRleE9mKCdyaWdodCcpICE9PSAtMSA/ICdzdGFydCcgOiAnbWlkZGxlJztcblxuICAgIC8vIGlmIG1hcmtlcnMgYXJlIHNob3duLCBvZmZzZXQgYSBsaXR0bGUgbW9yZSB0aGFuXG4gICAgLy8gdGhlIG5vbWluYWwgbWFya2VyIHNpemVcbiAgICAvLyBpZSAyLzEuNiAqIG5vbWluYWwsIGJjcyBzb21lIG1hcmtlcnMgYXJlIGEgYml0IGJpZ2dlclxuICAgIHZhciByID0gbWFya2VyUmFkaXVzID8gbWFya2VyUmFkaXVzIC8gMC44ICsgMSA6IDA7XG5cbiAgICB2YXIgbnVtTGluZXMgPSAoc3ZnVGV4dFV0aWxzLmxpbmVDb3VudChzKSAtIDEpICogTElORV9TUEFDSU5HICsgMTtcbiAgICB2YXIgZHggPSBURVhUT0ZGU0VUU0lHTltoXSAqIHI7XG4gICAgdmFyIGR5ID0gZm9udFNpemUgKiAwLjc1ICsgVEVYVE9GRlNFVFNJR05bdl0gKiByICtcbiAgICAgICAgKFRFWFRPRkZTRVRTSUdOW3ZdIC0gMSkgKiBudW1MaW5lcyAqIGZvbnRTaXplIC8gMjtcblxuICAgIC8vIGZpeCB0aGUgb3ZlcmFsbCB0ZXh0IGdyb3VwIHBvc2l0aW9uXG4gICAgcy5hdHRyKCd0ZXh0LWFuY2hvcicsIGgpO1xuICAgIGdyb3VwLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIGR4ICsgJywnICsgZHkgKyAnKScpO1xufVxuXG5mdW5jdGlvbiBleHRyYWNUZXh0Rm9udFNpemUoZCwgdHJhY2UpIHtcbiAgICB2YXIgZm9udFNpemUgPSBkLnRzIHx8IHRyYWNlLnRleHRmb250LnNpemU7XG4gICAgcmV0dXJuIChpc051bWVyaWMoZm9udFNpemUpICYmIGZvbnRTaXplID4gMCkgPyBmb250U2l6ZSA6IDA7XG59XG5cbi8vIGRyYXcgdGV4dCBhdCBwb2ludHNcbmRyYXdpbmcudGV4dFBvaW50U3R5bGUgPSBmdW5jdGlvbihzLCB0cmFjZSwgZ2QpIHtcbiAgICBpZighcy5zaXplKCkpIHJldHVybjtcblxuICAgIHZhciBzZWxlY3RlZFRleHRDb2xvckZuO1xuXG4gICAgaWYodHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHtcbiAgICAgICAgdmFyIGZucyA9IGRyYXdpbmcubWFrZVNlbGVjdGVkVGV4dFN0eWxlRm5zKHRyYWNlKTtcbiAgICAgICAgc2VsZWN0ZWRUZXh0Q29sb3JGbiA9IGZucy5zZWxlY3RlZFRleHRDb2xvckZuO1xuICAgIH1cblxuICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdGV4dCA9IExpYi5leHRyYWN0T3B0aW9uKGQsIHRyYWNlLCAndHgnLCAndGV4dCcpO1xuXG4gICAgICAgIGlmKCF0ZXh0ICYmIHRleHQgIT09IDApIHtcbiAgICAgICAgICAgIHAucmVtb3ZlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcG9zID0gZC50cCB8fCB0cmFjZS50ZXh0cG9zaXRpb247XG4gICAgICAgIHZhciBmb250U2l6ZSA9IGV4dHJhY1RleHRGb250U2l6ZShkLCB0cmFjZSk7XG4gICAgICAgIHZhciBmb250Q29sb3IgPSBzZWxlY3RlZFRleHRDb2xvckZuID9cbiAgICAgICAgICAgIHNlbGVjdGVkVGV4dENvbG9yRm4oZCkgOlxuICAgICAgICAgICAgKGQudGMgfHwgdHJhY2UudGV4dGZvbnQuY29sb3IpO1xuXG4gICAgICAgIHAuY2FsbChkcmF3aW5nLmZvbnQsXG4gICAgICAgICAgICAgICAgZC50ZiB8fCB0cmFjZS50ZXh0Zm9udC5mYW1pbHksXG4gICAgICAgICAgICAgICAgZm9udFNpemUsXG4gICAgICAgICAgICAgICAgZm9udENvbG9yKVxuICAgICAgICAgICAgLnRleHQodGV4dClcbiAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKVxuICAgICAgICAgICAgLmNhbGwodGV4dFBvaW50UG9zaXRpb24sIHBvcywgZm9udFNpemUsIGQubXJjKTtcbiAgICB9KTtcbn07XG5cbmRyYXdpbmcuc2VsZWN0ZWRUZXh0U3R5bGUgPSBmdW5jdGlvbihzLCB0cmFjZSkge1xuICAgIGlmKCFzLnNpemUoKSB8fCAhdHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHJldHVybjtcblxuICAgIHZhciBmbnMgPSBkcmF3aW5nLm1ha2VTZWxlY3RlZFRleHRTdHlsZUZucyh0cmFjZSk7XG5cbiAgICBzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgdHggPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciB0YyA9IGZucy5zZWxlY3RlZFRleHRDb2xvckZuKGQpO1xuICAgICAgICB2YXIgdHAgPSBkLnRwIHx8IHRyYWNlLnRleHRwb3NpdGlvbjtcbiAgICAgICAgdmFyIGZvbnRTaXplID0gZXh0cmFjVGV4dEZvbnRTaXplKGQsIHRyYWNlKTtcblxuICAgICAgICBDb2xvci5maWxsKHR4LCB0Yyk7XG4gICAgICAgIHRleHRQb2ludFBvc2l0aW9uKHR4LCB0cCwgZm9udFNpemUsIGQubXJjMiB8fCBkLm1yYyk7XG4gICAgfSk7XG59O1xuXG4vLyBnZW5lcmFsaXplZCBDYXRtdWxsLVJvbSBzcGxpbmVzLCBwZXJcbi8vIGh0dHA6Ly93d3cuY2VteXVrc2VsLmNvbS9yZXNlYXJjaC9jYXRtdWxscm9tX3BhcmFtL2NhdG11bGxyb20ucGRmXG52YXIgQ2F0bXVsbFJvbUV4cCA9IDAuNTtcbmRyYXdpbmcuc21vb3Rob3BlbiA9IGZ1bmN0aW9uKHB0cywgc21vb3RobmVzcykge1xuICAgIGlmKHB0cy5sZW5ndGggPCAzKSB7IHJldHVybiAnTScgKyBwdHMuam9pbignTCcpO31cbiAgICB2YXIgcGF0aCA9ICdNJyArIHB0c1swXTtcbiAgICB2YXIgdGFuZ2VudHMgPSBbXTtcbiAgICB2YXIgaTtcbiAgICBmb3IoaSA9IDE7IGkgPCBwdHMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgIHRhbmdlbnRzLnB1c2gobWFrZVRhbmdlbnQocHRzW2kgLSAxXSwgcHRzW2ldLCBwdHNbaSArIDFdLCBzbW9vdGhuZXNzKSk7XG4gICAgfVxuICAgIHBhdGggKz0gJ1EnICsgdGFuZ2VudHNbMF1bMF0gKyAnICcgKyBwdHNbMV07XG4gICAgZm9yKGkgPSAyOyBpIDwgcHRzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICBwYXRoICs9ICdDJyArIHRhbmdlbnRzW2kgLSAyXVsxXSArICcgJyArIHRhbmdlbnRzW2kgLSAxXVswXSArICcgJyArIHB0c1tpXTtcbiAgICB9XG4gICAgcGF0aCArPSAnUScgKyB0YW5nZW50c1twdHMubGVuZ3RoIC0gM11bMV0gKyAnICcgKyBwdHNbcHRzLmxlbmd0aCAtIDFdO1xuICAgIHJldHVybiBwYXRoO1xufTtcblxuZHJhd2luZy5zbW9vdGhjbG9zZWQgPSBmdW5jdGlvbihwdHMsIHNtb290aG5lc3MpIHtcbiAgICBpZihwdHMubGVuZ3RoIDwgMykgeyByZXR1cm4gJ00nICsgcHRzLmpvaW4oJ0wnKSArICdaJzsgfVxuICAgIHZhciBwYXRoID0gJ00nICsgcHRzWzBdO1xuICAgIHZhciBwTGFzdCA9IHB0cy5sZW5ndGggLSAxO1xuICAgIHZhciB0YW5nZW50cyA9IFttYWtlVGFuZ2VudChwdHNbcExhc3RdLCBwdHNbMF0sIHB0c1sxXSwgc21vb3RobmVzcyldO1xuICAgIHZhciBpO1xuICAgIGZvcihpID0gMTsgaSA8IHBMYXN0OyBpKyspIHtcbiAgICAgICAgdGFuZ2VudHMucHVzaChtYWtlVGFuZ2VudChwdHNbaSAtIDFdLCBwdHNbaV0sIHB0c1tpICsgMV0sIHNtb290aG5lc3MpKTtcbiAgICB9XG4gICAgdGFuZ2VudHMucHVzaChcbiAgICAgICAgbWFrZVRhbmdlbnQocHRzW3BMYXN0IC0gMV0sIHB0c1twTGFzdF0sIHB0c1swXSwgc21vb3RobmVzcylcbiAgICApO1xuXG4gICAgZm9yKGkgPSAxOyBpIDw9IHBMYXN0OyBpKyspIHtcbiAgICAgICAgcGF0aCArPSAnQycgKyB0YW5nZW50c1tpIC0gMV1bMV0gKyAnICcgKyB0YW5nZW50c1tpXVswXSArICcgJyArIHB0c1tpXTtcbiAgICB9XG4gICAgcGF0aCArPSAnQycgKyB0YW5nZW50c1twTGFzdF1bMV0gKyAnICcgKyB0YW5nZW50c1swXVswXSArICcgJyArIHB0c1swXSArICdaJztcbiAgICByZXR1cm4gcGF0aDtcbn07XG5cbmZ1bmN0aW9uIG1ha2VUYW5nZW50KHByZXZwdCwgdGhpc3B0LCBuZXh0cHQsIHNtb290aG5lc3MpIHtcbiAgICB2YXIgZDF4ID0gcHJldnB0WzBdIC0gdGhpc3B0WzBdO1xuICAgIHZhciBkMXkgPSBwcmV2cHRbMV0gLSB0aGlzcHRbMV07XG4gICAgdmFyIGQyeCA9IG5leHRwdFswXSAtIHRoaXNwdFswXTtcbiAgICB2YXIgZDJ5ID0gbmV4dHB0WzFdIC0gdGhpc3B0WzFdO1xuICAgIHZhciBkMWEgPSBNYXRoLnBvdyhkMXggKiBkMXggKyBkMXkgKiBkMXksIENhdG11bGxSb21FeHAgLyAyKTtcbiAgICB2YXIgZDJhID0gTWF0aC5wb3coZDJ4ICogZDJ4ICsgZDJ5ICogZDJ5LCBDYXRtdWxsUm9tRXhwIC8gMik7XG4gICAgdmFyIG51bXggPSAoZDJhICogZDJhICogZDF4IC0gZDFhICogZDFhICogZDJ4KSAqIHNtb290aG5lc3M7XG4gICAgdmFyIG51bXkgPSAoZDJhICogZDJhICogZDF5IC0gZDFhICogZDFhICogZDJ5KSAqIHNtb290aG5lc3M7XG4gICAgdmFyIGRlbm9tMSA9IDMgKiBkMmEgKiAoZDFhICsgZDJhKTtcbiAgICB2YXIgZGVub20yID0gMyAqIGQxYSAqIChkMWEgKyBkMmEpO1xuICAgIHJldHVybiBbXG4gICAgICAgIFtcbiAgICAgICAgICAgIGQzLnJvdW5kKHRoaXNwdFswXSArIChkZW5vbTEgJiYgbnVteCAvIGRlbm9tMSksIDIpLFxuICAgICAgICAgICAgZDMucm91bmQodGhpc3B0WzFdICsgKGRlbm9tMSAmJiBudW15IC8gZGVub20xKSwgMilcbiAgICAgICAgXSwgW1xuICAgICAgICAgICAgZDMucm91bmQodGhpc3B0WzBdIC0gKGRlbm9tMiAmJiBudW14IC8gZGVub20yKSwgMiksXG4gICAgICAgICAgICBkMy5yb3VuZCh0aGlzcHRbMV0gLSAoZGVub20yICYmIG51bXkgLyBkZW5vbTIpLCAyKVxuICAgICAgICBdXG4gICAgXTtcbn1cblxuLy8gc3RlcCBwYXRocyAtIHJldHVybnMgYSBnZW5lcmF0b3IgZnVuY3Rpb24gZm9yIHBhdGhzXG4vLyB3aXRoIHRoZSBnaXZlbiBzdGVwIHNoYXBlXG52YXIgU1RFUFBBVEggPSB7XG4gICAgaHY6IGZ1bmN0aW9uKHAwLCBwMSkge1xuICAgICAgICByZXR1cm4gJ0gnICsgZDMucm91bmQocDFbMF0sIDIpICsgJ1YnICsgZDMucm91bmQocDFbMV0sIDIpO1xuICAgIH0sXG4gICAgdmg6IGZ1bmN0aW9uKHAwLCBwMSkge1xuICAgICAgICByZXR1cm4gJ1YnICsgZDMucm91bmQocDFbMV0sIDIpICsgJ0gnICsgZDMucm91bmQocDFbMF0sIDIpO1xuICAgIH0sXG4gICAgaHZoOiBmdW5jdGlvbihwMCwgcDEpIHtcbiAgICAgICAgcmV0dXJuICdIJyArIGQzLnJvdW5kKChwMFswXSArIHAxWzBdKSAvIDIsIDIpICsgJ1YnICtcbiAgICAgICAgICAgIGQzLnJvdW5kKHAxWzFdLCAyKSArICdIJyArIGQzLnJvdW5kKHAxWzBdLCAyKTtcbiAgICB9LFxuICAgIHZodjogZnVuY3Rpb24ocDAsIHAxKSB7XG4gICAgICAgIHJldHVybiAnVicgKyBkMy5yb3VuZCgocDBbMV0gKyBwMVsxXSkgLyAyLCAyKSArICdIJyArXG4gICAgICAgICAgICBkMy5yb3VuZChwMVswXSwgMikgKyAnVicgKyBkMy5yb3VuZChwMVsxXSwgMik7XG4gICAgfVxufTtcbnZhciBTVEVQTElORUFSID0gZnVuY3Rpb24ocDAsIHAxKSB7XG4gICAgcmV0dXJuICdMJyArIGQzLnJvdW5kKHAxWzBdLCAyKSArICcsJyArIGQzLnJvdW5kKHAxWzFdLCAyKTtcbn07XG5kcmF3aW5nLnN0ZXBzID0gZnVuY3Rpb24oc2hhcGUpIHtcbiAgICB2YXIgb25lc3RlcCA9IFNURVBQQVRIW3NoYXBlXSB8fCBTVEVQTElORUFSO1xuICAgIHJldHVybiBmdW5jdGlvbihwdHMpIHtcbiAgICAgICAgdmFyIHBhdGggPSAnTScgKyBkMy5yb3VuZChwdHNbMF1bMF0sIDIpICsgJywnICsgZDMucm91bmQocHRzWzBdWzFdLCAyKTtcbiAgICAgICAgZm9yKHZhciBpID0gMTsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgcGF0aCArPSBvbmVzdGVwKHB0c1tpIC0gMV0sIHB0c1tpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHBhdGg7XG4gICAgfTtcbn07XG5cbi8vIG9mZi1zY3JlZW4gc3ZnIHJlbmRlciB0ZXN0aW5nIGVsZW1lbnQsIHNoYXJlZCBieSB0aGUgd2hvbGUgcGFnZVxuLy8gdXNlcyB0aGUgaWQgJ2pzLXBsb3RseS10ZXN0ZXInIGFuZCBzdG9yZXMgaXQgaW4gZHJhd2luZy50ZXN0ZXJcbmRyYXdpbmcubWFrZVRlc3RlciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0ZXN0ZXIgPSBMaWIuZW5zdXJlU2luZ2xlQnlJZChkMy5zZWxlY3QoJ2JvZHknKSwgJ3N2ZycsICdqcy1wbG90bHktdGVzdGVyJywgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoeG1sbnNOYW1lc3BhY2VzLnN2Z0F0dHJzKVxuICAgICAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgICAgICAgICBsZWZ0OiAnLTEwMDAwcHgnLFxuICAgICAgICAgICAgICAgIHRvcDogJy0xMDAwMHB4JyxcbiAgICAgICAgICAgICAgICB3aWR0aDogJzkwMDBweCcsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiAnOTAwMHB4JyxcbiAgICAgICAgICAgICAgICAnei1pbmRleCc6ICcxJ1xuICAgICAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBicm93c2VycyBkaWZmZXIgb24gaG93IHRoZXkgZGVzY3JpYmUgdGhlIGJvdW5kaW5nIHJlY3Qgb2ZcbiAgICAvLyB0aGUgc3ZnIGlmIGl0cyBjb250ZW50cyBzcGlsbCBvdmVyLi4uIHNvIG1ha2UgYSAxeDFweFxuICAgIC8vIHJlZmVyZW5jZSBwb2ludCB3ZSBjYW4gbWVhc3VyZSBvZmYgb2YuXG4gICAgdmFyIHRlc3RyZWYgPSBMaWIuZW5zdXJlU2luZ2xlKHRlc3RlciwgJ3BhdGgnLCAnanMtcmVmZXJlbmNlLXBvaW50JywgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoJ2QnLCAnTTAsMEgxVjFIMFonKVxuICAgICAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogMCxcbiAgICAgICAgICAgICAgICBmaWxsOiAnYmxhY2snXG4gICAgICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRyYXdpbmcudGVzdGVyID0gdGVzdGVyO1xuICAgIGRyYXdpbmcudGVzdHJlZiA9IHRlc3RyZWY7XG59O1xuXG4vKlxuICogdXNlIG91ciBvZmZzY3JlZW4gdGVzdGVyIHRvIGdldCBhIGNsaWVudFJlY3QgZm9yIGFuIGVsZW1lbnQsXG4gKiBpbiBhIHJlZmVyZW5jZSBmcmFtZSB3aGVyZSBpdCBpc24ndCB0cmFuc2xhdGVkIChvciB0cmFuc2Zvcm1lZCkgYW5kXG4gKiBpdHMgYW5jaG9yIHBvaW50IGlzIGF0ICgwLDApXG4gKiBhbHdheXMgcmV0dXJucyBhIGNvcHkgb2YgdGhlIGJib3gsIHNvIHRoZSBjYWxsZXIgY2FuIG1vZGlmeSBpdCBzYWZlbHlcbiAqXG4gKiBAcGFyYW0ge1NWR0VsZW1lbnR9IG5vZGU6IHRoZSBlbGVtZW50IHRvIG1lYXN1cmUuIElmIHBvc3NpYmxlIHRoaXMgc2hvdWxkIGJlXG4gKiAgIGEgPHRleHQ+IG9yIE1hdGhKYXggPGc+IGVsZW1lbnQgdGhhdCdzIGFscmVhZHkgcGFzc2VkIHRocm91Z2hcbiAqICAgYGNvbnZlcnRUb1RzcGFuc2AgYmVjYXVzZSBpbiB0aGF0IGNhc2Ugd2UgY2FuIGNhY2hlIHRoZSByZXN1bHRzLCBidXQgaXQnc1xuICogICBwb3NzaWJsZSB0byBwYXNzIGluIGFueSBzdmcgZWxlbWVudC5cbiAqXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGluVGVzdGVyOiBpcyB0aGlzIGVsZW1lbnQgYWxyZWFkeSBpbiBgZHJhd2luZy50ZXN0ZXJgP1xuICogICBJZiB5b3UgYXJlIG1lYXN1cmluZyBhIGR1bW15IGVsZW1lbnQsIHJhdGhlciB0aGFuIG9uZSB5b3UgcmVhbGx5IGludGVuZFxuICogICB0byB1c2Ugb24gdGhlIHBsb3QsIG1ha2luZyBpdCBpbiBgZHJhd2luZy50ZXN0ZXJgIGluIHRoZSBmaXJzdCBwbGFjZVxuICogICBhbGxvd3MgdXMgdG8gdGVzdCBmYXN0ZXIgYmVjYXVzZSBpdCBjdXRzIG91dCBjbG9uaW5nIGFuZCBhcHBlbmRpbmcgaXQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGhhc2g6IGZvciBpbnRlcm5hbCB1c2Ugb25seSwgaWYgd2UgYWxyZWFkeSBrbm93IHRoZSBjYWNoZSBrZXlcbiAqICAgZm9yIHRoaXMgZWxlbWVudCBiZWZvcmVoYW5kLlxuICpcbiAqIEByZXR1cm4ge29iamVjdH06IGEgcGxhaW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHdpZHRoLCBoZWlnaHQsIGxlZnQsIHJpZ2h0LFxuICogICB0b3AsIGFuZCBib3R0b20gb2YgYG5vZGVgXG4gKi9cbmRyYXdpbmcuc2F2ZWRCQm94ZXMgPSB7fTtcbnZhciBzYXZlZEJCb3hlc0NvdW50ID0gMDtcbnZhciBtYXhTYXZlZEJCb3hlcyA9IDEwMDAwO1xuXG5kcmF3aW5nLmJCb3ggPSBmdW5jdGlvbihub2RlLCBpblRlc3RlciwgaGFzaCkge1xuICAgIC8qXG4gICAgICogQ2FjaGUgZWxlbWVudHMgd2UndmUgYWxyZWFkeSBtZWFzdXJlZCBzbyB3ZSBkb24ndCBoYXZlIHRvXG4gICAgICogcmVtZWFzdXJlIHRoZSBzYW1lIHRoaW5nIG1hbnkgdGltZXNcbiAgICAgKiBXZSBoYXZlIGEgZmV3IGJCb3ggY2FsbGVycyB0aG91Z2ggd2hvIHBhc3MgYSBub2RlIGxhcmdlciB0aGFuXG4gICAgICogYSA8dGV4dD4gb3IgYSBNYXRoSmF4IDxnPiwgc3VjaCBhcyBhbiBheGlzIGdyb3VwIGNvbnRhaW5pbmcgbWFueSBsYWJlbHMuXG4gICAgICogVGhlc2Ugd2lsbCBub3QgZ2VuZXJhdGUgYSBoYXNoICh1bmxlc3Mgd2UgZmlndXJlIG91dCBhbiBhcHByb3ByaWF0ZVxuICAgICAqIGhhc2gga2V5IGZvciB0aGVtKSBhbmQgdGh1cyB3ZSB3aWxsIG5vdCBoYXNoIHRoZW0uXG4gICAgICovXG4gICAgaWYoIWhhc2gpIGhhc2ggPSBub2RlSGFzaChub2RlKTtcbiAgICB2YXIgb3V0O1xuICAgIGlmKGhhc2gpIHtcbiAgICAgICAgb3V0ID0gZHJhd2luZy5zYXZlZEJCb3hlc1toYXNoXTtcbiAgICAgICAgaWYob3V0KSByZXR1cm4gTGliLmV4dGVuZEZsYXQoe30sIG91dCk7XG4gICAgfSBlbHNlIGlmKG5vZGUuY2hpbGROb2Rlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgLypcbiAgICAgICAgICogSWYgd2UgaGF2ZSBvbmx5IG9uZSBjaGlsZCBlbGVtZW50LCB3aGljaCBpcyBpdHNlbGYgaGFzaGFibGUsIG1ha2VcbiAgICAgICAgICogYSBuZXcgaGFzaCBmcm9tIHRoaXMgZWxlbWVudCBwbHVzIGl0cyB4LHksdHJhbnNmb3JtXG4gICAgICAgICAqIFRoZXNlIGJvdW5kaW5nIGJveGVzICppbmNsdWRlKiB4LHksdHJhbnNmb3JtIC0gbW9zdGx5IGZvciB1c2UgYnlcbiAgICAgICAgICogY2FsbGVycyB0cnlpbmcgdG8gYXZvaWQgb3ZlcmxhcHMgKGllIHRpdGxlcylcbiAgICAgICAgICovXG4gICAgICAgIHZhciBpbm5lck5vZGUgPSBub2RlLmNoaWxkTm9kZXNbMF07XG5cbiAgICAgICAgaGFzaCA9IG5vZGVIYXNoKGlubmVyTm9kZSk7XG4gICAgICAgIGlmKGhhc2gpIHtcbiAgICAgICAgICAgIHZhciB4ID0gK2lubmVyTm9kZS5nZXRBdHRyaWJ1dGUoJ3gnKSB8fCAwO1xuICAgICAgICAgICAgdmFyIHkgPSAraW5uZXJOb2RlLmdldEF0dHJpYnV0ZSgneScpIHx8IDA7XG4gICAgICAgICAgICB2YXIgdHJhbnNmb3JtID0gaW5uZXJOb2RlLmdldEF0dHJpYnV0ZSgndHJhbnNmb3JtJyk7XG5cbiAgICAgICAgICAgIGlmKCF0cmFuc2Zvcm0pIHtcbiAgICAgICAgICAgICAgICAvLyBpbiB0aGlzIGNhc2UsIGp1c3QgdmFyeWluZyB4IGFuZCB5LCBkb24ndCBib3RoZXIgY2FjaGluZ1xuICAgICAgICAgICAgICAgIC8vIHRoZSBmaW5hbCBiQm94IGJlY2F1c2UgdGhlIGFsdGVyYXRpb24gaXMgcXVpY2suXG4gICAgICAgICAgICAgICAgdmFyIGlubmVyQkIgPSBkcmF3aW5nLmJCb3goaW5uZXJOb2RlLCBmYWxzZSwgaGFzaCk7XG4gICAgICAgICAgICAgICAgaWYoeCkge1xuICAgICAgICAgICAgICAgICAgICBpbm5lckJCLmxlZnQgKz0geDtcbiAgICAgICAgICAgICAgICAgICAgaW5uZXJCQi5yaWdodCArPSB4O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZih5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlubmVyQkIudG9wICs9IHk7XG4gICAgICAgICAgICAgICAgICAgIGlubmVyQkIuYm90dG9tICs9IHk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBpbm5lckJCO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIGVsc2Ugd2UgaGF2ZSBhIHRyYW5zZm9ybSAtIHJhdGhlciB0aGFuIG1ha2UgYSBjb21wbGljYXRlZFxuICAgICAgICAgICAgICogKGFuZCBlcnJvci1wcm9uZSBhbmQgcHJvYmFibHkgc2xvdykgdHJhbnNmb3JtIHBhcnNlci9jYWxjdWxhdG9yLFxuICAgICAgICAgICAgICoganVzdCBjb250aW51ZSBvbiBjYWxjdWxhdGluZyB0aGUgYm91bmRpbmdDbGllbnRSZWN0IG9mIHRoZSBncm91cFxuICAgICAgICAgICAgICogYW5kIHVzZSB0aGUgbmV3IGNvbXBvc2l0ZSBoYXNoIHRvIGNhY2hlIGl0LlxuICAgICAgICAgICAgICogVGhhdCBzYWlkLCBgaW5uZXJOb2RlLnRyYW5zZm9ybS5iYXNlVmFsYCBpcyBhbiBhcnJheSBvZlxuICAgICAgICAgICAgICogYFNWR1RyYW5zZm9ybWAgb2JqZWN0cywgdGhhdCAqZG8qIHNlZW0gdG8gaGF2ZSBhIG5pY2UgbWF0cml4XG4gICAgICAgICAgICAgKiBtdWx0aXBsaWNhdGlvbiBpbnRlcmZhY2UgdGhhdCB3ZSBjb3VsZCB1c2UgdG8gYXZvaWQgbWFraW5nXG4gICAgICAgICAgICAgKiBhbm90aGVyIGdldEJvdW5kaW5nQ2xpZW50UmVjdCBjYWxsLi4uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGhhc2ggKz0gJ34nICsgeCArICd+JyArIHkgKyAnficgKyB0cmFuc2Zvcm07XG5cbiAgICAgICAgICAgIG91dCA9IGRyYXdpbmcuc2F2ZWRCQm94ZXNbaGFzaF07XG4gICAgICAgICAgICBpZihvdXQpIHJldHVybiBMaWIuZXh0ZW5kRmxhdCh7fSwgb3V0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB2YXIgdGVzdE5vZGUsIHRlc3RlcjtcbiAgICBpZihpblRlc3Rlcikge1xuICAgICAgICB0ZXN0Tm9kZSA9IG5vZGU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGVzdGVyID0gZHJhd2luZy50ZXN0ZXIubm9kZSgpO1xuXG4gICAgICAgIC8vIGNvcHkgdGhlIG5vZGUgdG8gdGVzdCBpbnRvIHRoZSB0ZXN0ZXJcbiAgICAgICAgdGVzdE5vZGUgPSBub2RlLmNsb25lTm9kZSh0cnVlKTtcbiAgICAgICAgdGVzdGVyLmFwcGVuZENoaWxkKHRlc3ROb2RlKTtcbiAgICB9XG5cbiAgICAvLyBzdGFuZGFyZGl6ZSBpdHMgcG9zaXRpb24gKGFuZCBuZXdsaW5lIHRzcGFucyBpZiBhbnkpXG4gICAgZDMuc2VsZWN0KHRlc3ROb2RlKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgbnVsbClcbiAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCwgMCwgMCk7XG5cbiAgICB2YXIgdGVzdFJlY3QgPSB0ZXN0Tm9kZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgcmVmUmVjdCA9IGRyYXdpbmcudGVzdHJlZlxuICAgICAgICAubm9kZSgpXG4gICAgICAgIC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIGlmKCFpblRlc3RlcikgdGVzdGVyLnJlbW92ZUNoaWxkKHRlc3ROb2RlKTtcblxuICAgIHZhciBiYiA9IHtcbiAgICAgICAgaGVpZ2h0OiB0ZXN0UmVjdC5oZWlnaHQsXG4gICAgICAgIHdpZHRoOiB0ZXN0UmVjdC53aWR0aCxcbiAgICAgICAgbGVmdDogdGVzdFJlY3QubGVmdCAtIHJlZlJlY3QubGVmdCxcbiAgICAgICAgdG9wOiB0ZXN0UmVjdC50b3AgLSByZWZSZWN0LnRvcCxcbiAgICAgICAgcmlnaHQ6IHRlc3RSZWN0LnJpZ2h0IC0gcmVmUmVjdC5sZWZ0LFxuICAgICAgICBib3R0b206IHRlc3RSZWN0LmJvdHRvbSAtIHJlZlJlY3QudG9wXG4gICAgfTtcblxuICAgIC8vIG1ha2Ugc3VyZSB3ZSBkb24ndCBoYXZlIHRvbyBtYW55IHNhdmVkIGJveGVzLFxuICAgIC8vIG9yIGEgbG9uZyBzZXNzaW9uIGNvdWxkIG92ZXJsb2FkIG9uIG1lbW9yeVxuICAgIC8vIGJ5IHNhdmluZyBib3hlcyBmb3IgbG9uZy1nb25lIGVsZW1lbnRzXG4gICAgaWYoc2F2ZWRCQm94ZXNDb3VudCA+PSBtYXhTYXZlZEJCb3hlcykge1xuICAgICAgICBkcmF3aW5nLnNhdmVkQkJveGVzID0ge307XG4gICAgICAgIHNhdmVkQkJveGVzQ291bnQgPSAwO1xuICAgIH1cblxuICAgIC8vIGNhY2hlIHRoaXMgYmJveFxuICAgIGlmKGhhc2gpIGRyYXdpbmcuc2F2ZWRCQm94ZXNbaGFzaF0gPSBiYjtcbiAgICBzYXZlZEJCb3hlc0NvdW50Kys7XG5cbiAgICByZXR1cm4gTGliLmV4dGVuZEZsYXQoe30sIGJiKTtcbn07XG5cbi8vIGNhcHR1cmUgZXZlcnl0aGluZyBhYm91dCBhIG5vZGUgKGF0IGxlYXN0IGluIG91ciB1c2FnZSkgdGhhdFxuLy8gaW1wYWN0cyBpdHMgYm91bmRpbmcgYm94LCBnaXZlbiB0aGF0IGJCb3ggY2xlYXJzIHgsIHksIGFuZCB0cmFuc2Zvcm1cbmZ1bmN0aW9uIG5vZGVIYXNoKG5vZGUpIHtcbiAgICB2YXIgaW5wdXRUZXh0ID0gbm9kZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtdW5mb3JtYXR0ZWQnKTtcbiAgICBpZihpbnB1dFRleHQgPT09IG51bGwpIHJldHVybjtcbiAgICByZXR1cm4gaW5wdXRUZXh0ICtcbiAgICAgICAgbm9kZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtbWF0aCcpICtcbiAgICAgICAgbm9kZS5nZXRBdHRyaWJ1dGUoJ3RleHQtYW5jaG9yJykgK1xuICAgICAgICBub2RlLmdldEF0dHJpYnV0ZSgnc3R5bGUnKTtcbn1cblxuLyoqXG4gKiBTZXQgY2xpcFBhdGggVVJMIGluIGEgd2F5IHRoYXQgd29yayBmb3IgYWxsIHNpdHVhdGlvbnMuXG4gKlxuICogSW4gZGV0YWlscywgZ3JhcGhzIG9uIHBhZ2VzIHdpdGggPGJhc2U+IEhUTUwgdGFncyBuZWVkIHRvIHByZXBlbmRcbiAqIHRoZSBjbGlwIHBhdGggaWRzIHdpdGggdGhlIHBhZ2UncyBiYXNlIHVybCBFWENFUFQgZHVyaW5nIHRvSW1hZ2UgZXhwb3J0cy5cbiAqXG4gKiBAcGFyYW0ge2QzIHNlbGVjdGlvbn0gcyA6IG5vZGUgdG8gYWRkIGNsaXAtcGF0aCBhdHRyaWJ1dGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbElkIDogbG9jYWwgY2xpcC1wYXRoICh3L28gYmFzZSB1cmwpIGlkXG4gKiBAcGFyYW0ge0RPTSBlbGVtZW50IHx8IG9iamVjdH0gZ2RcbiAqIC0gY29udGV4dC5fYmFzZVVybCB7c3RyaW5nfVxuICogLSBjb250ZXh0Ll9leHBvcnRlZFBsb3Qge2Jvb2xlYW59XG4gKi9cbmRyYXdpbmcuc2V0Q2xpcFVybCA9IGZ1bmN0aW9uKHMsIGxvY2FsSWQsIGdkKSB7XG4gICAgcy5hdHRyKCdjbGlwLXBhdGgnLCBnZXRGdWxsVXJsKGxvY2FsSWQsIGdkKSk7XG59O1xuXG5mdW5jdGlvbiBnZXRGdWxsVXJsKGxvY2FsSWQsIGdkKSB7XG4gICAgaWYoIWxvY2FsSWQpIHJldHVybiBudWxsO1xuXG4gICAgdmFyIGNvbnRleHQgPSBnZC5fY29udGV4dDtcbiAgICB2YXIgYmFzZVVybCA9IGNvbnRleHQuX2V4cG9ydGVkUGxvdCA/ICcnIDogKGNvbnRleHQuX2Jhc2VVcmwgfHwgJycpO1xuICAgIHJldHVybiAndXJsKFxcJycgKyBiYXNlVXJsICsgJyMnICsgbG9jYWxJZCArICdcXCcpJztcbn1cblxuZHJhd2luZy5nZXRUcmFuc2xhdGUgPSBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgLy8gTm90ZSB0aGUgc2VwYXJhdG9yIFteXFxkXSBiZXR3ZWVuIHggYW5kIHkgaW4gdGhpcyByZWdleFxuICAgIC8vIFdlIGdlbmVyYWxseSB1c2UgJywnIGJ1dCBJRSB3aWxsIGNvbnZlcnQgaXQgdG8gJyAnXG4gICAgdmFyIHJlID0gLy4qXFxidHJhbnNsYXRlXFwoKC0/XFxkKlxcLj9cXGQqKVteLVxcZF0qKC0/XFxkKlxcLj9cXGQqKVteXFxkXS4qLztcbiAgICB2YXIgZ2V0dGVyID0gZWxlbWVudC5hdHRyID8gJ2F0dHInIDogJ2dldEF0dHJpYnV0ZSc7XG4gICAgdmFyIHRyYW5zZm9ybSA9IGVsZW1lbnRbZ2V0dGVyXSgndHJhbnNmb3JtJykgfHwgJyc7XG5cbiAgICB2YXIgdHJhbnNsYXRlID0gdHJhbnNmb3JtLnJlcGxhY2UocmUsIGZ1bmN0aW9uKG1hdGNoLCBwMSwgcDIpIHtcbiAgICAgICAgcmV0dXJuIFtwMSwgcDJdLmpvaW4oJyAnKTtcbiAgICB9KVxuICAgIC5zcGxpdCgnICcpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogK3RyYW5zbGF0ZVswXSB8fCAwLFxuICAgICAgICB5OiArdHJhbnNsYXRlWzFdIHx8IDBcbiAgICB9O1xufTtcblxuZHJhd2luZy5zZXRUcmFuc2xhdGUgPSBmdW5jdGlvbihlbGVtZW50LCB4LCB5KSB7XG4gICAgdmFyIHJlID0gLyhcXGJ0cmFuc2xhdGVcXCguKj9cXCk7PykvO1xuICAgIHZhciBnZXR0ZXIgPSBlbGVtZW50LmF0dHIgPyAnYXR0cicgOiAnZ2V0QXR0cmlidXRlJztcbiAgICB2YXIgc2V0dGVyID0gZWxlbWVudC5hdHRyID8gJ2F0dHInIDogJ3NldEF0dHJpYnV0ZSc7XG4gICAgdmFyIHRyYW5zZm9ybSA9IGVsZW1lbnRbZ2V0dGVyXSgndHJhbnNmb3JtJykgfHwgJyc7XG5cbiAgICB4ID0geCB8fCAwO1xuICAgIHkgPSB5IHx8IDA7XG5cbiAgICB0cmFuc2Zvcm0gPSB0cmFuc2Zvcm0ucmVwbGFjZShyZSwgJycpLnRyaW0oKTtcbiAgICB0cmFuc2Zvcm0gKz0gJyB0cmFuc2xhdGUoJyArIHggKyAnLCAnICsgeSArICcpJztcbiAgICB0cmFuc2Zvcm0gPSB0cmFuc2Zvcm0udHJpbSgpO1xuXG4gICAgZWxlbWVudFtzZXR0ZXJdKCd0cmFuc2Zvcm0nLCB0cmFuc2Zvcm0pO1xuXG4gICAgcmV0dXJuIHRyYW5zZm9ybTtcbn07XG5cbmRyYXdpbmcuZ2V0U2NhbGUgPSBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgdmFyIHJlID0gLy4qXFxic2NhbGVcXCgoXFxkKlxcLj9cXGQqKVteXFxkXSooXFxkKlxcLj9cXGQqKVteXFxkXS4qLztcbiAgICB2YXIgZ2V0dGVyID0gZWxlbWVudC5hdHRyID8gJ2F0dHInIDogJ2dldEF0dHJpYnV0ZSc7XG4gICAgdmFyIHRyYW5zZm9ybSA9IGVsZW1lbnRbZ2V0dGVyXSgndHJhbnNmb3JtJykgfHwgJyc7XG5cbiAgICB2YXIgdHJhbnNsYXRlID0gdHJhbnNmb3JtLnJlcGxhY2UocmUsIGZ1bmN0aW9uKG1hdGNoLCBwMSwgcDIpIHtcbiAgICAgICAgcmV0dXJuIFtwMSwgcDJdLmpvaW4oJyAnKTtcbiAgICB9KVxuICAgIC5zcGxpdCgnICcpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogK3RyYW5zbGF0ZVswXSB8fCAxLFxuICAgICAgICB5OiArdHJhbnNsYXRlWzFdIHx8IDFcbiAgICB9O1xufTtcblxuZHJhd2luZy5zZXRTY2FsZSA9IGZ1bmN0aW9uKGVsZW1lbnQsIHgsIHkpIHtcbiAgICB2YXIgcmUgPSAvKFxcYnNjYWxlXFwoLio/XFwpOz8pLztcbiAgICB2YXIgZ2V0dGVyID0gZWxlbWVudC5hdHRyID8gJ2F0dHInIDogJ2dldEF0dHJpYnV0ZSc7XG4gICAgdmFyIHNldHRlciA9IGVsZW1lbnQuYXR0ciA/ICdhdHRyJyA6ICdzZXRBdHRyaWJ1dGUnO1xuICAgIHZhciB0cmFuc2Zvcm0gPSBlbGVtZW50W2dldHRlcl0oJ3RyYW5zZm9ybScpIHx8ICcnO1xuXG4gICAgeCA9IHggfHwgMTtcbiAgICB5ID0geSB8fCAxO1xuXG4gICAgdHJhbnNmb3JtID0gdHJhbnNmb3JtLnJlcGxhY2UocmUsICcnKS50cmltKCk7XG4gICAgdHJhbnNmb3JtICs9ICcgc2NhbGUoJyArIHggKyAnLCAnICsgeSArICcpJztcbiAgICB0cmFuc2Zvcm0gPSB0cmFuc2Zvcm0udHJpbSgpO1xuXG4gICAgZWxlbWVudFtzZXR0ZXJdKCd0cmFuc2Zvcm0nLCB0cmFuc2Zvcm0pO1xuXG4gICAgcmV0dXJuIHRyYW5zZm9ybTtcbn07XG5cbnZhciBTQ0FMRV9SRSA9IC9cXHMqc2MuKi87XG5cbmRyYXdpbmcuc2V0UG9pbnRHcm91cFNjYWxlID0gZnVuY3Rpb24oc2VsZWN0aW9uLCB4U2NhbGUsIHlTY2FsZSkge1xuICAgIHhTY2FsZSA9IHhTY2FsZSB8fCAxO1xuICAgIHlTY2FsZSA9IHlTY2FsZSB8fCAxO1xuXG4gICAgaWYoIXNlbGVjdGlvbikgcmV0dXJuO1xuXG4gICAgLy8gVGhlIHNhbWUgc2NhbGUgdHJhbnNmb3JtIGZvciBldmVyeSBwb2ludDpcbiAgICB2YXIgc2NhbGUgPSAoeFNjYWxlID09PSAxICYmIHlTY2FsZSA9PT0gMSkgP1xuICAgICAgICAnJyA6XG4gICAgICAgICcgc2NhbGUoJyArIHhTY2FsZSArICcsJyArIHlTY2FsZSArICcpJztcblxuICAgIHNlbGVjdGlvbi5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdCA9ICh0aGlzLmdldEF0dHJpYnV0ZSgndHJhbnNmb3JtJykgfHwgJycpLnJlcGxhY2UoU0NBTEVfUkUsICcnKTtcbiAgICAgICAgdCArPSBzY2FsZTtcbiAgICAgICAgdCA9IHQudHJpbSgpO1xuICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgndHJhbnNmb3JtJywgdCk7XG4gICAgfSk7XG59O1xuXG52YXIgVEVYVF9QT0lOVF9MQVNUX1RSQU5TTEFUSU9OX1JFID0gL3RyYW5zbGF0ZVxcKFteKV0qXFwpXFxzKiQvO1xuXG5kcmF3aW5nLnNldFRleHRQb2ludHNTY2FsZSA9IGZ1bmN0aW9uKHNlbGVjdGlvbiwgeFNjYWxlLCB5U2NhbGUpIHtcbiAgICBpZighc2VsZWN0aW9uKSByZXR1cm47XG5cbiAgICBzZWxlY3Rpb24uZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHRyYW5zZm9ybXM7XG4gICAgICAgIHZhciBlbCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIHRleHQgPSBlbC5zZWxlY3QoJ3RleHQnKTtcblxuICAgICAgICBpZighdGV4dC5ub2RlKCkpIHJldHVybjtcblxuICAgICAgICB2YXIgeCA9IHBhcnNlRmxvYXQodGV4dC5hdHRyKCd4JykgfHwgMCk7XG4gICAgICAgIHZhciB5ID0gcGFyc2VGbG9hdCh0ZXh0LmF0dHIoJ3knKSB8fCAwKTtcblxuICAgICAgICB2YXIgZXhpc3RpbmdUcmFuc2Zvcm0gPSAoZWwuYXR0cigndHJhbnNmb3JtJykgfHwgJycpLm1hdGNoKFRFWFRfUE9JTlRfTEFTVF9UUkFOU0xBVElPTl9SRSk7XG5cbiAgICAgICAgaWYoeFNjYWxlID09PSAxICYmIHlTY2FsZSA9PT0gMSkge1xuICAgICAgICAgICAgdHJhbnNmb3JtcyA9IFtdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHJhbnNmb3JtcyA9IFtcbiAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgKyB4ICsgJywnICsgeSArICcpJyxcbiAgICAgICAgICAgICAgICAnc2NhbGUoJyArIHhTY2FsZSArICcsJyArIHlTY2FsZSArICcpJyxcbiAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgKyAoLXgpICsgJywnICsgKC15KSArICcpJyxcbiAgICAgICAgICAgIF07XG4gICAgICAgIH1cblxuICAgICAgICBpZihleGlzdGluZ1RyYW5zZm9ybSkge1xuICAgICAgICAgICAgdHJhbnNmb3Jtcy5wdXNoKGV4aXN0aW5nVHJhbnNmb3JtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVsLmF0dHIoJ3RyYW5zZm9ybScsIHRyYW5zZm9ybXMuam9pbignICcpKTtcbiAgICB9KTtcbn07XG5cbn0se1wiLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudFwiOjY4OCxcIi4uLy4uL2NvbnN0YW50cy9pbnRlcmFjdGlvbnNcIjo2OTQsXCIuLi8uLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlc1wiOjY5NixcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vLi4vdHJhY2VzL3NjYXR0ZXIvbWFrZV9idWJibGVfc2l6ZV9mdW5jXCI6MTEyOCxcIi4uLy4uL3RyYWNlcy9zY2F0dGVyL3N1YnR5cGVzXCI6MTEzNSxcIi4uL2NvbG9yXCI6NTkzLFwiLi4vY29sb3JzY2FsZVwiOjYwNSxcIi4vc3ltYm9sX2RlZnNcIjo2MTUsXCJkM1wiOjE2MyxcImZhc3QtaXNudW1lcmljXCI6MjI1LFwidGlueWNvbG9yMlwiOjUzN31dLDYxNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxuLyoqIE1hcmtlciBzeW1ib2wgZGVmaW5pdGlvbnNcbiAqIHVzZXJzIGNhbiBzcGVjaWZ5IG1hcmtlcnMgZWl0aGVyIGJ5IG51bWJlciBvciBuYW1lXG4gKiBhZGQgMTAwIChvciAnLW9wZW4nKSBhbmQgeW91IGdldCBhbiBvcGVuIG1hcmtlclxuICogIG9wZW4gbWFya2VycyBoYXZlIG5vIGZpbGwgYW5kIHVzZSBsaW5lIGNvbG9yIGFzIHRoZSBzdHJva2UgY29sb3JcbiAqIGFkZCAyMDAgKG9yICctZG90JykgYW5kIHlvdSBnZXQgYSBkb3QgaW4gdGhlIG1pZGRsZVxuICogYWRkIGJvdGggYW5kIHlvdSBnZXQgYm90aFxuICovXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNpcmNsZToge1xuICAgICAgICBuOiAwLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnMgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyBycyArICcsMEEnICsgcnMgKyAnLCcgKyBycyArICcgMCAxLDEgMCwtJyArIHJzICtcbiAgICAgICAgICAgICAgICAnQScgKyBycyArICcsJyArIHJzICsgJyAwIDAsMSAnICsgcnMgKyAnLDBaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgc3F1YXJlOiB7XG4gICAgICAgIG46IDEsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBycyA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHJzICsgJywnICsgcnMgKyAnSC0nICsgcnMgKyAnVi0nICsgcnMgKyAnSCcgKyBycyArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZGlhbW9uZDoge1xuICAgICAgICBuOiAyLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcmQgPSBkMy5yb3VuZChyICogMS4zLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByZCArICcsMEwwLCcgKyByZCArICdMLScgKyByZCArICcsMEwwLC0nICsgcmQgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNyb3NzOiB7XG4gICAgICAgIG46IDMsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciByYyA9IGQzLnJvdW5kKHIgKiAwLjQsIDIpO1xuICAgICAgICAgICAgdmFyIHJjMiA9IGQzLnJvdW5kKHIgKiAxLjIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHJjMiArICcsJyArIHJjICsgJ0gnICsgcmMgKyAnVicgKyByYzIgKyAnSC0nICsgcmMgK1xuICAgICAgICAgICAgICAgICdWJyArIHJjICsgJ0gtJyArIHJjMiArICdWLScgKyByYyArICdILScgKyByYyArICdWLScgKyByYzIgK1xuICAgICAgICAgICAgICAgICdIJyArIHJjICsgJ1YtJyArIHJjICsgJ0gnICsgcmMyICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB4OiB7XG4gICAgICAgIG46IDQsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciByeCA9IGQzLnJvdW5kKHIgKiAwLjggLyBNYXRoLnNxcnQoMiksIDIpO1xuICAgICAgICAgICAgdmFyIG5lID0gJ2wnICsgcnggKyAnLCcgKyByeDtcbiAgICAgICAgICAgIHZhciBzZSA9ICdsJyArIHJ4ICsgJywtJyArIHJ4O1xuICAgICAgICAgICAgdmFyIHN3ID0gJ2wtJyArIHJ4ICsgJywtJyArIHJ4O1xuICAgICAgICAgICAgdmFyIG53ID0gJ2wtJyArIHJ4ICsgJywnICsgcng7XG4gICAgICAgICAgICByZXR1cm4gJ00wLCcgKyByeCArIG5lICsgc2UgKyBzdyArIHNlICsgc3cgKyBudyArIHN3ICsgbncgKyBuZSArIG53ICsgbmUgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICd0cmlhbmdsZS11cCc6IHtcbiAgICAgICAgbjogNSxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJ0ID0gZDMucm91bmQociAqIDIgLyBNYXRoLnNxcnQoMyksIDIpO1xuICAgICAgICAgICAgdmFyIHIyID0gZDMucm91bmQociAvIDIsIDIpO1xuICAgICAgICAgICAgdmFyIHJzID0gZDMucm91bmQociwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00tJyArIHJ0ICsgJywnICsgcjIgKyAnSCcgKyBydCArICdMMCwtJyArIHJzICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAndHJpYW5nbGUtZG93bic6IHtcbiAgICAgICAgbjogNixcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJ0ID0gZDMucm91bmQociAqIDIgLyBNYXRoLnNxcnQoMyksIDIpO1xuICAgICAgICAgICAgdmFyIHIyID0gZDMucm91bmQociAvIDIsIDIpO1xuICAgICAgICAgICAgdmFyIHJzID0gZDMucm91bmQociwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00tJyArIHJ0ICsgJywtJyArIHIyICsgJ0gnICsgcnQgKyAnTDAsJyArIHJzICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAndHJpYW5nbGUtbGVmdCc6IHtcbiAgICAgICAgbjogNyxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJ0ID0gZDMucm91bmQociAqIDIgLyBNYXRoLnNxcnQoMyksIDIpO1xuICAgICAgICAgICAgdmFyIHIyID0gZDMucm91bmQociAvIDIsIDIpO1xuICAgICAgICAgICAgdmFyIHJzID0gZDMucm91bmQociwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcjIgKyAnLC0nICsgcnQgKyAnVicgKyBydCArICdMLScgKyBycyArICcsMFonO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAndHJpYW5nbGUtcmlnaHQnOiB7XG4gICAgICAgIG46IDgsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBydCA9IGQzLnJvdW5kKHIgKiAyIC8gTWF0aC5zcXJ0KDMpLCAyKTtcbiAgICAgICAgICAgIHZhciByMiA9IGQzLnJvdW5kKHIgLyAyLCAyKTtcbiAgICAgICAgICAgIHZhciBycyA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyByMiArICcsLScgKyBydCArICdWJyArIHJ0ICsgJ0wnICsgcnMgKyAnLDBaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ3RyaWFuZ2xlLW5lJzoge1xuICAgICAgICBuOiA5LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcjEgPSBkMy5yb3VuZChyICogMC42LCAyKTtcbiAgICAgICAgICAgIHZhciByMiA9IGQzLnJvdW5kKHIgKiAxLjIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyByMiArICcsLScgKyByMSArICdIJyArIHIxICsgJ1YnICsgcjIgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICd0cmlhbmdsZS1zZSc6IHtcbiAgICAgICAgbjogMTAsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciByMSA9IGQzLnJvdW5kKHIgKiAwLjYsIDIpO1xuICAgICAgICAgICAgdmFyIHIyID0gZDMucm91bmQociAqIDEuMiwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcjEgKyAnLC0nICsgcjIgKyAnVicgKyByMSArICdILScgKyByMiArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ3RyaWFuZ2xlLXN3Jzoge1xuICAgICAgICBuOiAxMSxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHIxID0gZDMucm91bmQociAqIDAuNiwgMik7XG4gICAgICAgICAgICB2YXIgcjIgPSBkMy5yb3VuZChyICogMS4yLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByMiArICcsJyArIHIxICsgJ0gtJyArIHIxICsgJ1YtJyArIHIyICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAndHJpYW5nbGUtbncnOiB7XG4gICAgICAgIG46IDEyLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcjEgPSBkMy5yb3VuZChyICogMC42LCAyKTtcbiAgICAgICAgICAgIHZhciByMiA9IGQzLnJvdW5kKHIgKiAxLjIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyByMSArICcsJyArIHIyICsgJ1YtJyArIHIxICsgJ0gnICsgcjIgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHBlbnRhZ29uOiB7XG4gICAgICAgIG46IDEzLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgeDEgPSBkMy5yb3VuZChyICogMC45NTEsIDIpO1xuICAgICAgICAgICAgdmFyIHgyID0gZDMucm91bmQociAqIDAuNTg4LCAyKTtcbiAgICAgICAgICAgIHZhciB5MCA9IGQzLnJvdW5kKC1yLCAyKTtcbiAgICAgICAgICAgIHZhciB5MSA9IGQzLnJvdW5kKHIgKiAtMC4zMDksIDIpO1xuICAgICAgICAgICAgdmFyIHkyID0gZDMucm91bmQociAqIDAuODA5LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyB4MSArICcsJyArIHkxICsgJ0wnICsgeDIgKyAnLCcgKyB5MiArICdILScgKyB4MiArXG4gICAgICAgICAgICAgICAgJ0wtJyArIHgxICsgJywnICsgeTEgKyAnTDAsJyArIHkwICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBoZXhhZ29uOiB7XG4gICAgICAgIG46IDE0LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgeTAgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHZhciB5MSA9IGQzLnJvdW5kKHIgLyAyLCAyKTtcbiAgICAgICAgICAgIHZhciB4ID0gZDMucm91bmQociAqIE1hdGguc3FydCgzKSAvIDIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHggKyAnLC0nICsgeTEgKyAnVicgKyB5MSArICdMMCwnICsgeTAgK1xuICAgICAgICAgICAgICAgICdMLScgKyB4ICsgJywnICsgeTEgKyAnVi0nICsgeTEgKyAnTDAsLScgKyB5MCArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaGV4YWdvbjI6IHtcbiAgICAgICAgbjogMTUsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciB4MCA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgdmFyIHgxID0gZDMucm91bmQociAvIDIsIDIpO1xuICAgICAgICAgICAgdmFyIHkgPSBkMy5yb3VuZChyICogTWF0aC5zcXJ0KDMpIC8gMiwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00tJyArIHgxICsgJywnICsgeSArICdIJyArIHgxICsgJ0wnICsgeDAgK1xuICAgICAgICAgICAgICAgICcsMEwnICsgeDEgKyAnLC0nICsgeSArICdILScgKyB4MSArICdMLScgKyB4MCArICcsMFonO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBvY3RhZ29uOiB7XG4gICAgICAgIG46IDE2LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgYSA9IGQzLnJvdW5kKHIgKiAwLjkyNCwgMik7XG4gICAgICAgICAgICB2YXIgYiA9IGQzLnJvdW5kKHIgKiAwLjM4MywgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00tJyArIGIgKyAnLC0nICsgYSArICdIJyArIGIgKyAnTCcgKyBhICsgJywtJyArIGIgKyAnVicgKyBiICtcbiAgICAgICAgICAgICAgICAnTCcgKyBiICsgJywnICsgYSArICdILScgKyBiICsgJ0wtJyArIGEgKyAnLCcgKyBiICsgJ1YtJyArIGIgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHN0YXI6IHtcbiAgICAgICAgbjogMTcsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBycyA9IHIgKiAxLjQ7XG4gICAgICAgICAgICB2YXIgeDEgPSBkMy5yb3VuZChycyAqIDAuMjI1LCAyKTtcbiAgICAgICAgICAgIHZhciB4MiA9IGQzLnJvdW5kKHJzICogMC45NTEsIDIpO1xuICAgICAgICAgICAgdmFyIHgzID0gZDMucm91bmQocnMgKiAwLjM2MywgMik7XG4gICAgICAgICAgICB2YXIgeDQgPSBkMy5yb3VuZChycyAqIDAuNTg4LCAyKTtcbiAgICAgICAgICAgIHZhciB5MCA9IGQzLnJvdW5kKC1ycywgMik7XG4gICAgICAgICAgICB2YXIgeTEgPSBkMy5yb3VuZChycyAqIC0wLjMwOSwgMik7XG4gICAgICAgICAgICB2YXIgeTMgPSBkMy5yb3VuZChycyAqIDAuMTE4LCAyKTtcbiAgICAgICAgICAgIHZhciB5NCA9IGQzLnJvdW5kKHJzICogMC44MDksIDIpO1xuICAgICAgICAgICAgdmFyIHk1ID0gZDMucm91bmQocnMgKiAwLjM4MiwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgeDEgKyAnLCcgKyB5MSArICdIJyArIHgyICsgJ0wnICsgeDMgKyAnLCcgKyB5MyArXG4gICAgICAgICAgICAgICAgJ0wnICsgeDQgKyAnLCcgKyB5NCArICdMMCwnICsgeTUgKyAnTC0nICsgeDQgKyAnLCcgKyB5NCArXG4gICAgICAgICAgICAgICAgJ0wtJyArIHgzICsgJywnICsgeTMgKyAnTC0nICsgeDIgKyAnLCcgKyB5MSArICdILScgKyB4MSArXG4gICAgICAgICAgICAgICAgJ0wwLCcgKyB5MCArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaGV4YWdyYW06IHtcbiAgICAgICAgbjogMTgsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciB5ID0gZDMucm91bmQociAqIDAuNjYsIDIpO1xuICAgICAgICAgICAgdmFyIHgxID0gZDMucm91bmQociAqIDAuMzgsIDIpO1xuICAgICAgICAgICAgdmFyIHgyID0gZDMucm91bmQociAqIDAuNzYsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyB4MiArICcsMGwtJyArIHgxICsgJywtJyArIHkgKyAnaCcgKyB4MiArXG4gICAgICAgICAgICAgICAgJ2wnICsgeDEgKyAnLC0nICsgeSArICdsJyArIHgxICsgJywnICsgeSArICdoJyArIHgyICtcbiAgICAgICAgICAgICAgICAnbC0nICsgeDEgKyAnLCcgKyB5ICsgJ2wnICsgeDEgKyAnLCcgKyB5ICsgJ2gtJyArIHgyICtcbiAgICAgICAgICAgICAgICAnbC0nICsgeDEgKyAnLCcgKyB5ICsgJ2wtJyArIHgxICsgJywtJyArIHkgKyAnaC0nICsgeDIgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICdzdGFyLXRyaWFuZ2xlLXVwJzoge1xuICAgICAgICBuOiAxOSxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHggPSBkMy5yb3VuZChyICogTWF0aC5zcXJ0KDMpICogMC44LCAyKTtcbiAgICAgICAgICAgIHZhciB5MSA9IGQzLnJvdW5kKHIgKiAwLjgsIDIpO1xuICAgICAgICAgICAgdmFyIHkyID0gZDMucm91bmQociAqIDEuNiwgMik7XG4gICAgICAgICAgICB2YXIgcmMgPSBkMy5yb3VuZChyICogNCwgMik7XG4gICAgICAgICAgICB2YXIgYVBhcnQgPSAnQSAnICsgcmMgKyAnLCcgKyByYyArICcgMCAwIDEgJztcbiAgICAgICAgICAgIHJldHVybiAnTS0nICsgeCArICcsJyArIHkxICsgYVBhcnQgKyB4ICsgJywnICsgeTEgK1xuICAgICAgICAgICAgICAgIGFQYXJ0ICsgJzAsLScgKyB5MiArIGFQYXJ0ICsgJy0nICsgeCArICcsJyArIHkxICsgJ1onO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAnc3Rhci10cmlhbmdsZS1kb3duJzoge1xuICAgICAgICBuOiAyMCxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHggPSBkMy5yb3VuZChyICogTWF0aC5zcXJ0KDMpICogMC44LCAyKTtcbiAgICAgICAgICAgIHZhciB5MSA9IGQzLnJvdW5kKHIgKiAwLjgsIDIpO1xuICAgICAgICAgICAgdmFyIHkyID0gZDMucm91bmQociAqIDEuNiwgMik7XG4gICAgICAgICAgICB2YXIgcmMgPSBkMy5yb3VuZChyICogNCwgMik7XG4gICAgICAgICAgICB2YXIgYVBhcnQgPSAnQSAnICsgcmMgKyAnLCcgKyByYyArICcgMCAwIDEgJztcbiAgICAgICAgICAgIHJldHVybiAnTScgKyB4ICsgJywtJyArIHkxICsgYVBhcnQgKyAnLScgKyB4ICsgJywtJyArIHkxICtcbiAgICAgICAgICAgICAgICBhUGFydCArICcwLCcgKyB5MiArIGFQYXJ0ICsgeCArICcsLScgKyB5MSArICdaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ3N0YXItc3F1YXJlJzoge1xuICAgICAgICBuOiAyMSxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJwID0gZDMucm91bmQociAqIDEuMSwgMik7XG4gICAgICAgICAgICB2YXIgcmMgPSBkMy5yb3VuZChyICogMiwgMik7XG4gICAgICAgICAgICB2YXIgYVBhcnQgPSAnQSAnICsgcmMgKyAnLCcgKyByYyArICcgMCAwIDEgJztcbiAgICAgICAgICAgIHJldHVybiAnTS0nICsgcnAgKyAnLC0nICsgcnAgKyBhUGFydCArICctJyArIHJwICsgJywnICsgcnAgK1xuICAgICAgICAgICAgICAgIGFQYXJ0ICsgcnAgKyAnLCcgKyBycCArIGFQYXJ0ICsgcnAgKyAnLC0nICsgcnAgK1xuICAgICAgICAgICAgICAgIGFQYXJ0ICsgJy0nICsgcnAgKyAnLC0nICsgcnAgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICdzdGFyLWRpYW1vbmQnOiB7XG4gICAgICAgIG46IDIyLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnAgPSBkMy5yb3VuZChyICogMS40LCAyKTtcbiAgICAgICAgICAgIHZhciByYyA9IGQzLnJvdW5kKHIgKiAxLjksIDIpO1xuICAgICAgICAgICAgdmFyIGFQYXJ0ID0gJ0EgJyArIHJjICsgJywnICsgcmMgKyAnIDAgMCAxICc7XG4gICAgICAgICAgICByZXR1cm4gJ00tJyArIHJwICsgJywwJyArIGFQYXJ0ICsgJzAsJyArIHJwICtcbiAgICAgICAgICAgICAgICBhUGFydCArIHJwICsgJywwJyArIGFQYXJ0ICsgJzAsLScgKyBycCArXG4gICAgICAgICAgICAgICAgYVBhcnQgKyAnLScgKyBycCArICcsMCcgKyAnWic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICdkaWFtb25kLXRhbGwnOiB7XG4gICAgICAgIG46IDIzLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgeCA9IGQzLnJvdW5kKHIgKiAwLjcsIDIpO1xuICAgICAgICAgICAgdmFyIHkgPSBkMy5yb3VuZChyICogMS40LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTTAsJyArIHkgKyAnTCcgKyB4ICsgJywwTDAsLScgKyB5ICsgJ0wtJyArIHggKyAnLDBaJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgJ2RpYW1vbmQtd2lkZSc6IHtcbiAgICAgICAgbjogMjQsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciB4ID0gZDMucm91bmQociAqIDEuNCwgMik7XG4gICAgICAgICAgICB2YXIgeSA9IGQzLnJvdW5kKHIgKiAwLjcsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNMCwnICsgeSArICdMJyArIHggKyAnLDBMMCwtJyArIHkgKyAnTC0nICsgeCArICcsMFonO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBob3VyZ2xhc3M6IHtcbiAgICAgICAgbjogMjUsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBycyA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHJzICsgJywnICsgcnMgKyAnSC0nICsgcnMgKyAnTCcgKyBycyArICcsLScgKyBycyArICdILScgKyBycyArICdaJztcbiAgICAgICAgfSxcbiAgICAgICAgbm9Eb3Q6IHRydWVcbiAgICB9LFxuICAgIGJvd3RpZToge1xuICAgICAgICBuOiAyNixcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJzID0gZDMucm91bmQociwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00nICsgcnMgKyAnLCcgKyBycyArICdWLScgKyBycyArICdMLScgKyBycyArICcsJyArIHJzICsgJ1YtJyArIHJzICsgJ1onO1xuICAgICAgICB9LFxuICAgICAgICBub0RvdDogdHJ1ZVxuICAgIH0sXG4gICAgJ2NpcmNsZS1jcm9zcyc6IHtcbiAgICAgICAgbjogMjcsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBycyA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNMCwnICsgcnMgKyAnVi0nICsgcnMgKyAnTScgKyBycyArICcsMEgtJyArIHJzICtcbiAgICAgICAgICAgICAgICAnTScgKyBycyArICcsMEEnICsgcnMgKyAnLCcgKyBycyArICcgMCAxLDEgMCwtJyArIHJzICtcbiAgICAgICAgICAgICAgICAnQScgKyBycyArICcsJyArIHJzICsgJyAwIDAsMSAnICsgcnMgKyAnLDBaJztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlXG4gICAgfSxcbiAgICAnY2lyY2xlLXgnOiB7XG4gICAgICAgIG46IDI4LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnMgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHZhciByYyA9IGQzLnJvdW5kKHIgLyBNYXRoLnNxcnQoMiksIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHJjICsgJywnICsgcmMgKyAnTC0nICsgcmMgKyAnLC0nICsgcmMgK1xuICAgICAgICAgICAgICAgICdNJyArIHJjICsgJywtJyArIHJjICsgJ0wtJyArIHJjICsgJywnICsgcmMgK1xuICAgICAgICAgICAgICAgICdNJyArIHJzICsgJywwQScgKyBycyArICcsJyArIHJzICsgJyAwIDEsMSAwLC0nICsgcnMgK1xuICAgICAgICAgICAgICAgICdBJyArIHJzICsgJywnICsgcnMgKyAnIDAgMCwxICcgKyBycyArICcsMFonO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWVcbiAgICB9LFxuICAgICdzcXVhcmUtY3Jvc3MnOiB7XG4gICAgICAgIG46IDI5LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnMgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTTAsJyArIHJzICsgJ1YtJyArIHJzICsgJ00nICsgcnMgKyAnLDBILScgKyBycyArXG4gICAgICAgICAgICAgICAgJ00nICsgcnMgKyAnLCcgKyBycyArICdILScgKyBycyArICdWLScgKyBycyArICdIJyArIHJzICsgJ1onO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWVcbiAgICB9LFxuICAgICdzcXVhcmUteCc6IHtcbiAgICAgICAgbjogMzAsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciBycyA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHJzICsgJywnICsgcnMgKyAnTC0nICsgcnMgKyAnLC0nICsgcnMgK1xuICAgICAgICAgICAgICAgICdNJyArIHJzICsgJywtJyArIHJzICsgJ0wtJyArIHJzICsgJywnICsgcnMgK1xuICAgICAgICAgICAgICAgICdNJyArIHJzICsgJywnICsgcnMgKyAnSC0nICsgcnMgKyAnVi0nICsgcnMgKyAnSCcgKyBycyArICdaJztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlXG4gICAgfSxcbiAgICAnZGlhbW9uZC1jcm9zcyc6IHtcbiAgICAgICAgbjogMzEsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciByZCA9IGQzLnJvdW5kKHIgKiAxLjMsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHJkICsgJywwTDAsJyArIHJkICsgJ0wtJyArIHJkICsgJywwTDAsLScgKyByZCArICdaJyArXG4gICAgICAgICAgICAgICAgJ00wLC0nICsgcmQgKyAnVicgKyByZCArICdNLScgKyByZCArICcsMEgnICsgcmQ7XG4gICAgICAgIH0sXG4gICAgICAgIG5lZWRMaW5lOiB0cnVlLFxuICAgICAgICBub0RvdDogdHJ1ZVxuICAgIH0sXG4gICAgJ2RpYW1vbmQteCc6IHtcbiAgICAgICAgbjogMzIsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciByZCA9IGQzLnJvdW5kKHIgKiAxLjMsIDIpO1xuICAgICAgICAgICAgdmFyIHIyID0gZDMucm91bmQociAqIDAuNjUsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHJkICsgJywwTDAsJyArIHJkICsgJ0wtJyArIHJkICsgJywwTDAsLScgKyByZCArICdaJyArXG4gICAgICAgICAgICAgICAgJ00tJyArIHIyICsgJywtJyArIHIyICsgJ0wnICsgcjIgKyAnLCcgKyByMiArXG4gICAgICAgICAgICAgICAgJ00tJyArIHIyICsgJywnICsgcjIgKyAnTCcgKyByMiArICcsLScgKyByMjtcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlXG4gICAgfSxcbiAgICAnY3Jvc3MtdGhpbic6IHtcbiAgICAgICAgbjogMzMsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciByYyA9IGQzLnJvdW5kKHIgKiAxLjQsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNMCwnICsgcmMgKyAnVi0nICsgcmMgKyAnTScgKyByYyArICcsMEgtJyArIHJjO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH0sXG4gICAgJ3gtdGhpbic6IHtcbiAgICAgICAgbjogMzQsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciByeCA9IGQzLnJvdW5kKHIsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHJ4ICsgJywnICsgcnggKyAnTC0nICsgcnggKyAnLC0nICsgcnggK1xuICAgICAgICAgICAgICAgICdNJyArIHJ4ICsgJywtJyArIHJ4ICsgJ0wtJyArIHJ4ICsgJywnICsgcng7XG4gICAgICAgIH0sXG4gICAgICAgIG5lZWRMaW5lOiB0cnVlLFxuICAgICAgICBub0RvdDogdHJ1ZSxcbiAgICAgICAgbm9GaWxsOiB0cnVlXG4gICAgfSxcbiAgICBhc3Rlcmlzazoge1xuICAgICAgICBuOiAzNSxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHJjID0gZDMucm91bmQociAqIDEuMiwgMik7XG4gICAgICAgICAgICB2YXIgcnMgPSBkMy5yb3VuZChyICogMC44NSwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00wLCcgKyByYyArICdWLScgKyByYyArICdNJyArIHJjICsgJywwSC0nICsgcmMgK1xuICAgICAgICAgICAgICAgICdNJyArIHJzICsgJywnICsgcnMgKyAnTC0nICsgcnMgKyAnLC0nICsgcnMgK1xuICAgICAgICAgICAgICAgICdNJyArIHJzICsgJywtJyArIHJzICsgJ0wtJyArIHJzICsgJywnICsgcnM7XG4gICAgICAgIH0sXG4gICAgICAgIG5lZWRMaW5lOiB0cnVlLFxuICAgICAgICBub0RvdDogdHJ1ZSxcbiAgICAgICAgbm9GaWxsOiB0cnVlXG4gICAgfSxcbiAgICBoYXNoOiB7XG4gICAgICAgIG46IDM2LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcjEgPSBkMy5yb3VuZChyIC8gMiwgMik7XG4gICAgICAgICAgICB2YXIgcjIgPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByMSArICcsJyArIHIyICsgJ1YtJyArIHIyICtcbiAgICAgICAgICAgICAgICAnbS0nICsgcjIgKyAnLDBWJyArIHIyICtcbiAgICAgICAgICAgICAgICAnTScgKyByMiArICcsJyArIHIxICsgJ0gtJyArIHIyICtcbiAgICAgICAgICAgICAgICAnbTAsLScgKyByMiArICdIJyArIHIyO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9GaWxsOiB0cnVlXG4gICAgfSxcbiAgICAneS11cCc6IHtcbiAgICAgICAgbjogMzcsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciB4ID0gZDMucm91bmQociAqIDEuMiwgMik7XG4gICAgICAgICAgICB2YXIgeTAgPSBkMy5yb3VuZChyICogMS42LCAyKTtcbiAgICAgICAgICAgIHZhciB5MSA9IGQzLnJvdW5kKHIgKiAwLjgsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyB4ICsgJywnICsgeTEgKyAnTDAsME0nICsgeCArICcsJyArIHkxICsgJ0wwLDBNMCwtJyArIHkwICsgJ0wwLDAnO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH0sXG4gICAgJ3ktZG93bic6IHtcbiAgICAgICAgbjogMzgsXG4gICAgICAgIGY6IGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgIHZhciB4ID0gZDMucm91bmQociAqIDEuMiwgMik7XG4gICAgICAgICAgICB2YXIgeTAgPSBkMy5yb3VuZChyICogMS42LCAyKTtcbiAgICAgICAgICAgIHZhciB5MSA9IGQzLnJvdW5kKHIgKiAwLjgsIDIpO1xuICAgICAgICAgICAgcmV0dXJuICdNLScgKyB4ICsgJywtJyArIHkxICsgJ0wwLDBNJyArIHggKyAnLC0nICsgeTEgKyAnTDAsME0wLCcgKyB5MCArICdMMCwwJztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlLFxuICAgICAgICBub0ZpbGw6IHRydWVcbiAgICB9LFxuICAgICd5LWxlZnQnOiB7XG4gICAgICAgIG46IDM5LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgeSA9IGQzLnJvdW5kKHIgKiAxLjIsIDIpO1xuICAgICAgICAgICAgdmFyIHgwID0gZDMucm91bmQociAqIDEuNiwgMik7XG4gICAgICAgICAgICB2YXIgeDEgPSBkMy5yb3VuZChyICogMC44LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyB4MSArICcsJyArIHkgKyAnTDAsME0nICsgeDEgKyAnLC0nICsgeSArICdMMCwwTS0nICsgeDAgKyAnLDBMMCwwJztcbiAgICAgICAgfSxcbiAgICAgICAgbmVlZExpbmU6IHRydWUsXG4gICAgICAgIG5vRG90OiB0cnVlLFxuICAgICAgICBub0ZpbGw6IHRydWVcbiAgICB9LFxuICAgICd5LXJpZ2h0Jzoge1xuICAgICAgICBuOiA0MCxcbiAgICAgICAgZjogZnVuY3Rpb24ocikge1xuICAgICAgICAgICAgdmFyIHkgPSBkMy5yb3VuZChyICogMS4yLCAyKTtcbiAgICAgICAgICAgIHZhciB4MCA9IGQzLnJvdW5kKHIgKiAxLjYsIDIpO1xuICAgICAgICAgICAgdmFyIHgxID0gZDMucm91bmQociAqIDAuOCwgMik7XG4gICAgICAgICAgICByZXR1cm4gJ00tJyArIHgxICsgJywnICsgeSArICdMMCwwTS0nICsgeDEgKyAnLC0nICsgeSArICdMMCwwTScgKyB4MCArICcsMEwwLDAnO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH0sXG4gICAgJ2xpbmUtZXcnOiB7XG4gICAgICAgIG46IDQxLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcmMgPSBkMy5yb3VuZChyICogMS40LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByYyArICcsMEgtJyArIHJjO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH0sXG4gICAgJ2xpbmUtbnMnOiB7XG4gICAgICAgIG46IDQyLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcmMgPSBkMy5yb3VuZChyICogMS40LCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTTAsJyArIHJjICsgJ1YtJyArIHJjO1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH0sXG4gICAgJ2xpbmUtbmUnOiB7XG4gICAgICAgIG46IDQzLFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnggPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByeCArICcsLScgKyByeCArICdMLScgKyByeCArICcsJyArIHJ4O1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH0sXG4gICAgJ2xpbmUtbncnOiB7XG4gICAgICAgIG46IDQ0LFxuICAgICAgICBmOiBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICB2YXIgcnggPSBkMy5yb3VuZChyLCAyKTtcbiAgICAgICAgICAgIHJldHVybiAnTScgKyByeCArICcsJyArIHJ4ICsgJ0wtJyArIHJ4ICsgJywtJyArIHJ4O1xuICAgICAgICB9LFxuICAgICAgICBuZWVkTGluZTogdHJ1ZSxcbiAgICAgICAgbm9Eb3Q6IHRydWUsXG4gICAgICAgIG5vRmlsbDogdHJ1ZVxuICAgIH1cbn07XG5cbn0se1wiZDNcIjoxNjN9XSw2MTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3BlcmNlbnQnLCAnY29uc3RhbnQnLCAnc3FydCcsICdkYXRhJ10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN5bW1ldHJpYzoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFycmF5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhcnJheW1pbnVzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB2YWx1ZToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmFsdWVtaW51czoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdHJhY2VyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH0sXG4gICAgdHJhY2VyZWZtaW51czoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfSxcbiAgICBjb3B5X3lzdHlsZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICBjb3B5X3pzdHlsZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH0sXG4gICAgY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRoaWNrbmVzczoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAyLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcblxuICAgIF9kZXByZWNhdGVkOiB7XG4gICAgICAgIG9wYWNpdHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfVxufTtcblxufSx7fV0sNjE3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBtYWtlQ29tcHV0ZUVycm9yID0gX2RlcmVxXygnLi9jb21wdXRlX2Vycm9yJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCkge1xuICAgIHZhciBjYWxjZGF0YSA9IGdkLmNhbGNkYXRhO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjVHJhY2UgPSBjYWxjZGF0YVtpXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuXG4gICAgICAgIGlmKHRyYWNlLnZpc2libGUgPT09IHRydWUgJiYgUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ2Vycm9yQmFyc09LJykpIHtcbiAgICAgICAgICAgIHZhciB4YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS54YXhpcyk7XG4gICAgICAgICAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMpO1xuICAgICAgICAgICAgY2FsY09uZUF4aXMoY2FsY1RyYWNlLCB0cmFjZSwgeGEsICd4Jyk7XG4gICAgICAgICAgICBjYWxjT25lQXhpcyhjYWxjVHJhY2UsIHRyYWNlLCB5YSwgJ3knKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGNhbGNPbmVBeGlzKGNhbGNUcmFjZSwgdHJhY2UsIGF4aXMsIGNvb3JkKSB7XG4gICAgdmFyIG9wdHMgPSB0cmFjZVsnZXJyb3JfJyArIGNvb3JkXSB8fCB7fTtcbiAgICB2YXIgaXNWaXNpYmxlID0gKG9wdHMudmlzaWJsZSAmJiBbJ2xpbmVhcicsICdsb2cnXS5pbmRleE9mKGF4aXMudHlwZSkgIT09IC0xKTtcbiAgICB2YXIgdmFscyA9IFtdO1xuXG4gICAgaWYoIWlzVmlzaWJsZSkgcmV0dXJuO1xuXG4gICAgdmFyIGNvbXB1dGVFcnJvciA9IG1ha2VDb21wdXRlRXJyb3Iob3B0cyk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY1RyYWNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjUHQgPSBjYWxjVHJhY2VbaV07XG5cbiAgICAgICAgdmFyIGlJbiA9IGNhbGNQdC5pO1xuXG4gICAgICAgIC8vIGZvciB0eXBlcyB0aGF0IGRvbid0IGluY2x1ZGUgYGlgIGluIGVhY2ggY2FsY2RhdGEgcG9pbnRcbiAgICAgICAgaWYoaUluID09PSB1bmRlZmluZWQpIGlJbiA9IGk7XG5cbiAgICAgICAgLy8gZm9yIHN0YWNrZWQgYXJlYSBpbnNlcnRlZCBwb2ludHNcbiAgICAgICAgLy8gVE9ETzogZXJyb3JiYXJzIGhhdmUgYmVlbiB0ZXN0ZWQgY3Vyc29yaWx5IHdpdGggc3RhY2tlZCBhcmVhLFxuICAgICAgICAvLyBidXQgbm90IHRob3JvdWdobHkuIEl0J3Mgbm90IGV2ZW4gcmVhbGx5IGNsZWFyIHdoYXQgeW91IHdhbnQgdG8gZG86XG4gICAgICAgIC8vIFNob3VsZCBpdCBqdXN0IGJlIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhhdCB0cmFjZSdzIHNpemUgZGF0YT9cbiAgICAgICAgLy8gU2hvdWxkIHlvdSBhZGQgZXJyb3JzIGZyb20gYmVsb3cgaW4gcXVhZHJhdHVyZT9cbiAgICAgICAgLy8gQW5kIHdoYXQgYWJvdXQgbm9ybWFsaXphdGlvbiwgd2hlcmUgaW4gcHJpbmNpcGxlIHRoZSBlcnJvcnMgc2hyaW5rXG4gICAgICAgIC8vIGFnYWluIHdoZW4geW91IGdldCB1cCB0byB0aGUgdG9wIGVuZD9cbiAgICAgICAgLy8gT25lIG9wdGlvbiB3b3VsZCBiZSB0byBmb3JiaWQgZXJyb3JiYXJzIHdpdGggc3RhY2tpbmcgdW50aWwgd2VcbiAgICAgICAgLy8gZGVjaWRlIGhvdyB0byBoYW5kbGUgdGhlc2UgcXVlc3Rpb25zLlxuICAgICAgICBlbHNlIGlmKGlJbiA9PT0gbnVsbCkgY29udGludWU7XG5cbiAgICAgICAgdmFyIGNhbGNDb29yZCA9IGNhbGNQdFtjb29yZF07XG5cbiAgICAgICAgaWYoIWlzTnVtZXJpYyhheGlzLmMybChjYWxjQ29vcmQpKSkgY29udGludWU7XG5cbiAgICAgICAgdmFyIGVycm9ycyA9IGNvbXB1dGVFcnJvcihjYWxjQ29vcmQsIGlJbik7XG4gICAgICAgIGlmKGlzTnVtZXJpYyhlcnJvcnNbMF0pICYmIGlzTnVtZXJpYyhlcnJvcnNbMV0pKSB7XG4gICAgICAgICAgICB2YXIgc2hvZSA9IGNhbGNQdFtjb29yZCArICdzJ10gPSBjYWxjQ29vcmQgLSBlcnJvcnNbMF07XG4gICAgICAgICAgICB2YXIgaGF0ID0gY2FsY1B0W2Nvb3JkICsgJ2gnXSA9IGNhbGNDb29yZCArIGVycm9yc1sxXTtcbiAgICAgICAgICAgIHZhbHMucHVzaChzaG9lLCBoYXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGF4SWQgPSBheGlzLl9pZDtcbiAgICB2YXIgYmFzZUV4dHJlbWVzID0gdHJhY2UuX2V4dHJlbWVzW2F4SWRdO1xuICAgIHZhciBleHRyZW1lcyA9IEF4ZXMuZmluZEV4dHJlbWVzKFxuICAgICAgICBheGlzLFxuICAgICAgICB2YWxzLFxuICAgICAgICBMaWIuZXh0ZW5kRmxhdCh7dG96ZXJvOiBiYXNlRXh0cmVtZXMub3B0cy50b3plcm99LCB7cGFkZGVkOiB0cnVlfSlcbiAgICApO1xuICAgIGJhc2VFeHRyZW1lcy5taW4gPSBiYXNlRXh0cmVtZXMubWluLmNvbmNhdChleHRyZW1lcy5taW4pO1xuICAgIGJhc2VFeHRyZW1lcy5tYXggPSBiYXNlRXh0cmVtZXMubWF4LmNvbmNhdChleHRyZW1lcy5tYXgpO1xufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2NvbXB1dGVfZXJyb3JcIjo2MTgsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDYxODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG4vKipcbiAqIEVycm9yIGJhciBjb21wdXRpbmcgZnVuY3Rpb24gZ2VuZXJhdG9yXG4gKlxuICogTi5CLiBUaGUgZ2VuZXJhdGVkIGZ1bmN0aW9uIGRvZXMgbm90IGNsZWFuIHRoZSBkYXRhUHQgZW50cmllcy4gTm9uLW51bWVyaWNcbiAqIGVudHJpZXMgcmVzdWx0IGluIHVuZGVmaW5lZCBlcnJvciBtYWduaXR1ZGVzLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzIGVycm9yIGJhciBhdHRyaWJ1dGVzXG4gKlxuICogQHJldHVybiB7ZnVuY3Rpb259IDpcbiAqICAgICAgQHBhcmFtIHtudW1lcmljfSBkYXRhUHQgZGF0YSBwb2ludCBmcm9tIHdoZXJlIHRvIGNvbXB1dGUgdGhlIGVycm9yIG1hZ25pdHVkZVxuICogICAgICBAcGFyYW0ge251bWJlcn0gaW5kZXggaW5kZXggb2YgZGF0YVB0IGluIGl0cyBjb3JyZXNwb25kaW5nIGRhdGEgYXJyYXlcbiAqICAgICAgQHJldHVybiB7YXJyYXl9XG4gKiAgICAgICAgLSBlcnJvclswXSA6IGVycm9yIG1hZ25pdHVkZSBpbiB0aGUgbmVnYXRpdmUgZGlyZWN0aW9uXG4gKiAgICAgICAgLSBlcnJvclsxXSA6IFwiIFwiIFwiIFwiIHBvc2l0aXZlIFwiXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWFrZUNvbXB1dGVFcnJvcihvcHRzKSB7XG4gICAgdmFyIHR5cGUgPSBvcHRzLnR5cGU7XG4gICAgdmFyIHN5bW1ldHJpYyA9IG9wdHMuc3ltbWV0cmljO1xuXG4gICAgaWYodHlwZSA9PT0gJ2RhdGEnKSB7XG4gICAgICAgIHZhciBhcnJheSA9IG9wdHMuYXJyYXkgfHwgW107XG5cbiAgICAgICAgaWYoc3ltbWV0cmljKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gY29tcHV0ZUVycm9yKGRhdGFQdCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsID0gKyhhcnJheVtpbmRleF0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBbdmFsLCB2YWxdO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBhcnJheW1pbnVzID0gb3B0cy5hcnJheW1pbnVzIHx8IFtdO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGNvbXB1dGVFcnJvcihkYXRhUHQsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIHZhbCA9ICthcnJheVtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIHZhbE1pbnVzID0gK2FycmF5bWludXNbaW5kZXhdO1xuICAgICAgICAgICAgICAgIC8vIGluIGNhc2Ugb25lIGlzIHByZXNlbnQgYW5kIHRoZSBvdGhlciBpcyBtaXNzaW5nLCBmaWxsIGluIDBcbiAgICAgICAgICAgICAgICAvLyBzbyB3ZSBzdGlsbCBzZWUgdGhlIHByZXNlbnQgb25lLiBNb3N0bHkgdXNlZnVsIGR1cmluZyBtYW51YWxcbiAgICAgICAgICAgICAgICAvLyBkYXRhIGVudHJ5LlxuICAgICAgICAgICAgICAgIGlmKCFpc05hTih2YWwpIHx8ICFpc05hTih2YWxNaW51cykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFt2YWxNaW51cyB8fCAwLCB2YWwgfHwgMF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBbTmFOLCBOYU5dO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBjb21wdXRlRXJyb3JWYWx1ZSA9IG1ha2VDb21wdXRlRXJyb3JWYWx1ZSh0eXBlLCBvcHRzLnZhbHVlKTtcbiAgICAgICAgdmFyIGNvbXB1dGVFcnJvclZhbHVlTWludXMgPSBtYWtlQ29tcHV0ZUVycm9yVmFsdWUodHlwZSwgb3B0cy52YWx1ZW1pbnVzKTtcblxuICAgICAgICBpZihzeW1tZXRyaWMgfHwgb3B0cy52YWx1ZW1pbnVzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBjb21wdXRlRXJyb3IoZGF0YVB0KSB7XG4gICAgICAgICAgICAgICAgdmFyIHZhbCA9IGNvbXB1dGVFcnJvclZhbHVlKGRhdGFQdCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFt2YWwsIHZhbF07XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGNvbXB1dGVFcnJvcihkYXRhUHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgICAgICBjb21wdXRlRXJyb3JWYWx1ZU1pbnVzKGRhdGFQdCksXG4gICAgICAgICAgICAgICAgICAgIGNvbXB1dGVFcnJvclZhbHVlKGRhdGFQdClcbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qKlxuICogQ29tcHV0ZSBlcnJvciBiYXIgbWFnbml0dWRlIChmb3IgYWxsIHR5cGVzIGV4Y2VwdCBkYXRhKVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIGVycm9yIGJhciB0eXBlXG4gKiBAcGFyYW0ge251bWVyaWN9IHZhbHVlIGVycm9yIGJhciB2YWx1ZVxuICpcbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSA6XG4gKiAgICAgIEBwYXJhbSB7bnVtZXJpY30gZGF0YVB0XG4gKi9cbmZ1bmN0aW9uIG1ha2VDb21wdXRlRXJyb3JWYWx1ZSh0eXBlLCB2YWx1ZSkge1xuICAgIGlmKHR5cGUgPT09ICdwZXJjZW50Jykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oZGF0YVB0KSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5hYnMoZGF0YVB0ICogdmFsdWUgLyAxMDApO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZih0eXBlID09PSAnY29uc3RhbnQnKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmFicyh2YWx1ZSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmKHR5cGUgPT09ICdzcXJ0Jykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oZGF0YVB0KSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5zcXJ0KE1hdGguYWJzKGRhdGFQdCkpO1xuICAgICAgICB9O1xuICAgIH1cbn1cblxufSx7fV0sNjE5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgVGVtcGxhdGUgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbih0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBvcHRzKSB7XG4gICAgdmFyIG9iak5hbWUgPSAnZXJyb3JfJyArIG9wdHMuYXhpcztcbiAgICB2YXIgY29udGFpbmVyT3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKHRyYWNlT3V0LCBvYmpOYW1lKTtcbiAgICB2YXIgY29udGFpbmVySW4gPSB0cmFjZUluW29iak5hbWVdIHx8IHt9O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGhhc0Vycm9yQmFycyA9IChcbiAgICAgICAgY29udGFpbmVySW4uYXJyYXkgIT09IHVuZGVmaW5lZCB8fFxuICAgICAgICBjb250YWluZXJJbi52YWx1ZSAhPT0gdW5kZWZpbmVkIHx8XG4gICAgICAgIGNvbnRhaW5lckluLnR5cGUgPT09ICdzcXJ0J1xuICAgICk7XG5cbiAgICB2YXIgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScsIGhhc0Vycm9yQmFycyk7XG5cbiAgICBpZih2aXNpYmxlID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgdmFyIHR5cGUgPSBjb2VyY2UoJ3R5cGUnLCAnYXJyYXknIGluIGNvbnRhaW5lckluID8gJ2RhdGEnIDogJ3BlcmNlbnQnKTtcbiAgICB2YXIgc3ltbWV0cmljID0gdHJ1ZTtcblxuICAgIGlmKHR5cGUgIT09ICdzcXJ0Jykge1xuICAgICAgICBzeW1tZXRyaWMgPSBjb2VyY2UoJ3N5bW1ldHJpYycsXG4gICAgICAgICAgICAhKCh0eXBlID09PSAnZGF0YScgPyAnYXJyYXltaW51cycgOiAndmFsdWVtaW51cycpIGluIGNvbnRhaW5lckluKSk7XG4gICAgfVxuXG4gICAgaWYodHlwZSA9PT0gJ2RhdGEnKSB7XG4gICAgICAgIGNvZXJjZSgnYXJyYXknKTtcbiAgICAgICAgY29lcmNlKCd0cmFjZXJlZicpO1xuICAgICAgICBpZighc3ltbWV0cmljKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ2FycmF5bWludXMnKTtcbiAgICAgICAgICAgIGNvZXJjZSgndHJhY2VyZWZtaW51cycpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKHR5cGUgPT09ICdwZXJjZW50JyB8fCB0eXBlID09PSAnY29uc3RhbnQnKSB7XG4gICAgICAgIGNvZXJjZSgndmFsdWUnKTtcbiAgICAgICAgaWYoIXN5bW1ldHJpYykgY29lcmNlKCd2YWx1ZW1pbnVzJyk7XG4gICAgfVxuXG4gICAgdmFyIGNvcHlBdHRyID0gJ2NvcHlfJyArIG9wdHMuaW5oZXJpdCArICdzdHlsZSc7XG4gICAgaWYob3B0cy5pbmhlcml0KSB7XG4gICAgICAgIHZhciBpbmhlcml0T2JqID0gdHJhY2VPdXRbJ2Vycm9yXycgKyBvcHRzLmluaGVyaXRdO1xuICAgICAgICBpZigoaW5oZXJpdE9iaiB8fCB7fSkudmlzaWJsZSkge1xuICAgICAgICAgICAgY29lcmNlKGNvcHlBdHRyLCAhKGNvbnRhaW5lckluLmNvbG9yIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNOdW1lcmljKGNvbnRhaW5lckluLnRoaWNrbmVzcykgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc051bWVyaWMoY29udGFpbmVySW4ud2lkdGgpKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYoIW9wdHMuaW5oZXJpdCB8fCAhY29udGFpbmVyT3V0W2NvcHlBdHRyXSkge1xuICAgICAgICBjb2VyY2UoJ2NvbG9yJywgZGVmYXVsdENvbG9yKTtcbiAgICAgICAgY29lcmNlKCd0aGlja25lc3MnKTtcbiAgICAgICAgY29lcmNlKCd3aWR0aCcsIFJlZ2lzdHJ5LnRyYWNlSXModHJhY2VPdXQsICdnbDNkJykgPyAwIDogNCk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2F0dHJpYnV0ZXNcIjo2MTYsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDYyMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxudmFyIHh5QXR0cnMgPSB7XG4gICAgZXJyb3JfeDogTGliLmV4dGVuZEZsYXQoe30sIGF0dHJpYnV0ZXMpLFxuICAgIGVycm9yX3k6IExpYi5leHRlbmRGbGF0KHt9LCBhdHRyaWJ1dGVzKVxufTtcbmRlbGV0ZSB4eUF0dHJzLmVycm9yX3guY29weV96c3R5bGU7XG5kZWxldGUgeHlBdHRycy5lcnJvcl95LmNvcHlfenN0eWxlO1xuZGVsZXRlIHh5QXR0cnMuZXJyb3JfeS5jb3B5X3lzdHlsZTtcblxudmFyIHh5ekF0dHJzID0ge1xuICAgIGVycm9yX3g6IExpYi5leHRlbmRGbGF0KHt9LCBhdHRyaWJ1dGVzKSxcbiAgICBlcnJvcl95OiBMaWIuZXh0ZW5kRmxhdCh7fSwgYXR0cmlidXRlcyksXG4gICAgZXJyb3JfejogTGliLmV4dGVuZEZsYXQoe30sIGF0dHJpYnV0ZXMpXG59O1xuZGVsZXRlIHh5ekF0dHJzLmVycm9yX3guY29weV95c3R5bGU7XG5kZWxldGUgeHl6QXR0cnMuZXJyb3JfeS5jb3B5X3lzdHlsZTtcbmRlbGV0ZSB4eXpBdHRycy5lcnJvcl96LmNvcHlfeXN0eWxlO1xuZGVsZXRlIHh5ekF0dHJzLmVycm9yX3ouY29weV96c3R5bGU7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICdjb21wb25lbnQnLFxuICAgIG5hbWU6ICdlcnJvcmJhcnMnLFxuXG4gICAgc2NoZW1hOiB7XG4gICAgICAgIHRyYWNlczoge1xuICAgICAgICAgICAgc2NhdHRlcjogeHlBdHRycyxcbiAgICAgICAgICAgIGJhcjogeHlBdHRycyxcbiAgICAgICAgICAgIGhpc3RvZ3JhbTogeHlBdHRycyxcbiAgICAgICAgICAgIHNjYXR0ZXIzZDogb3ZlcnJpZGVBbGwoeHl6QXR0cnMsICdjYWxjJywgJ25lc3RlZCcpLFxuICAgICAgICAgICAgc2NhdHRlcmdsOiBvdmVycmlkZUFsbCh4eUF0dHJzLCAnY2FsYycsICduZXN0ZWQnKVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG5cbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBtYWtlQ29tcHV0ZUVycm9yOiBfZGVyZXFfKCcuL2NvbXB1dGVfZXJyb3InKSxcblxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuL3N0eWxlJyksXG4gICAgaG92ZXJJbmZvOiBob3ZlckluZm9cbn07XG5cbmZ1bmN0aW9uIGhvdmVySW5mbyhjYWxjUG9pbnQsIHRyYWNlLCBob3ZlclBvaW50KSB7XG4gICAgaWYoKHRyYWNlLmVycm9yX3kgfHwge30pLnZpc2libGUpIHtcbiAgICAgICAgaG92ZXJQb2ludC55ZXJyID0gY2FsY1BvaW50LnloIC0gY2FsY1BvaW50Lnk7XG4gICAgICAgIGlmKCF0cmFjZS5lcnJvcl95LnN5bW1ldHJpYykgaG92ZXJQb2ludC55ZXJybmVnID0gY2FsY1BvaW50LnkgLSBjYWxjUG9pbnQueXM7XG4gICAgfVxuICAgIGlmKCh0cmFjZS5lcnJvcl94IHx8IHt9KS52aXNpYmxlKSB7XG4gICAgICAgIGhvdmVyUG9pbnQueGVyciA9IGNhbGNQb2ludC54aCAtIGNhbGNQb2ludC54O1xuICAgICAgICBpZighdHJhY2UuZXJyb3JfeC5zeW1tZXRyaWMpIGhvdmVyUG9pbnQueGVycm5lZyA9IGNhbGNQb2ludC54IC0gY2FsY1BvaW50LnhzO1xuICAgIH1cbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi9hdHRyaWJ1dGVzXCI6NjE2LFwiLi9jYWxjXCI6NjE3LFwiLi9jb21wdXRlX2Vycm9yXCI6NjE4LFwiLi9kZWZhdWx0c1wiOjYxOSxcIi4vcGxvdFwiOjYyMSxcIi4vc3R5bGVcIjo2MjJ9XSw2MjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi9kcmF3aW5nJyk7XG52YXIgc3ViVHlwZXMgPSBfZGVyZXFfKCcuLi8uLi90cmFjZXMvc2NhdHRlci9zdWJ0eXBlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHRyYWNlcywgcGxvdGluZm8sIHRyYW5zaXRpb25PcHRzKSB7XG4gICAgdmFyIGlzTmV3O1xuXG4gICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICB2YXIgaGFzQW5pbWF0aW9uID0gdHJhbnNpdGlvbk9wdHMgJiYgdHJhbnNpdGlvbk9wdHMuZHVyYXRpb24gPiAwO1xuXG4gICAgdHJhY2VzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuICAgICAgICAvLyB8fCB7fSBpcyBpbiBjYXNlIHRoZSB0cmFjZSAoc3BlY2lmaWNhbGx5IHNjYXR0ZXJ0ZXJuYXJ5KVxuICAgICAgICAvLyBkb2Vzbid0IHN1cHBvcnQgZXJyb3IgYmFycyBhdCBhbGwsIGJ1dCBkb2VzIGdvIHRocm91Z2hcbiAgICAgICAgLy8gdGhlIHNjYXR0ZXIucGxvdCBtZWNoYW5pY3MsIHdoaWNoIGNhbGxzIEVycm9yQmFycy5wbG90XG4gICAgICAgIC8vIGludGVybmFsbHlcbiAgICAgICAgdmFyIHhPYmogPSB0cmFjZS5lcnJvcl94IHx8IHt9O1xuICAgICAgICB2YXIgeU9iaiA9IHRyYWNlLmVycm9yX3kgfHwge307XG5cbiAgICAgICAgdmFyIGtleUZ1bmM7XG5cbiAgICAgICAgaWYodHJhY2UuaWRzKSB7XG4gICAgICAgICAgICBrZXlGdW5jID0gZnVuY3Rpb24oZCkge3JldHVybiBkLmlkO307XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc3BhcnNlID0gKFxuICAgICAgICAgICAgc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkgJiZcbiAgICAgICAgICAgIHRyYWNlLm1hcmtlci5tYXhkaXNwbGF5ZWQgPiAwXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYoIXlPYmoudmlzaWJsZSAmJiAheE9iai52aXNpYmxlKSBkID0gW107XG5cbiAgICAgICAgdmFyIGVycm9yYmFycyA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ2cuZXJyb3JiYXInKVxuICAgICAgICAgICAgLmRhdGEoZCwga2V5RnVuYyk7XG5cbiAgICAgICAgZXJyb3JiYXJzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgICAgICBpZighZC5sZW5ndGgpIHJldHVybjtcblxuICAgICAgICBpZigheE9iai52aXNpYmxlKSBlcnJvcmJhcnMuc2VsZWN0QWxsKCdwYXRoLnhlcnJvcicpLnJlbW92ZSgpO1xuICAgICAgICBpZigheU9iai52aXNpYmxlKSBlcnJvcmJhcnMuc2VsZWN0QWxsKCdwYXRoLnllcnJvcicpLnJlbW92ZSgpO1xuXG4gICAgICAgIGVycm9yYmFycy5zdHlsZSgnb3BhY2l0eScsIDEpO1xuXG4gICAgICAgIHZhciBlbnRlciA9IGVycm9yYmFycy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAuY2xhc3NlZCgnZXJyb3JiYXInLCB0cnVlKTtcblxuICAgICAgICBpZihoYXNBbmltYXRpb24pIHtcbiAgICAgICAgICAgIGVudGVyLnN0eWxlKCdvcGFjaXR5JywgMCkudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgLmR1cmF0aW9uKHRyYW5zaXRpb25PcHRzLmR1cmF0aW9uKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKGVycm9yYmFycywgcGxvdGluZm8ubGF5ZXJDbGlwSWQsIGdkKTtcblxuICAgICAgICBlcnJvcmJhcnMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3JiYXIgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgY29vcmRzID0gZXJyb3JDb29yZHMoZCwgeGEsIHlhKTtcblxuICAgICAgICAgICAgaWYoc3BhcnNlICYmICFkLnZpcykgcmV0dXJuO1xuXG4gICAgICAgICAgICB2YXIgcGF0aDtcblxuICAgICAgICAgICAgdmFyIHllcnJvciA9IGVycm9yYmFyLnNlbGVjdCgncGF0aC55ZXJyb3InKTtcbiAgICAgICAgICAgIGlmKHlPYmoudmlzaWJsZSAmJiBpc051bWVyaWMoY29vcmRzLngpICYmXG4gICAgICAgICAgICAgICAgICAgIGlzTnVtZXJpYyhjb29yZHMueWgpICYmXG4gICAgICAgICAgICAgICAgICAgIGlzTnVtZXJpYyhjb29yZHMueXMpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHl3ID0geU9iai53aWR0aDtcblxuICAgICAgICAgICAgICAgIHBhdGggPSAnTScgKyAoY29vcmRzLnggLSB5dykgKyAnLCcgK1xuICAgICAgICAgICAgICAgICAgICBjb29yZHMueWggKyAnaCcgKyAoMiAqIHl3KSArIC8vIGhhdFxuICAgICAgICAgICAgICAgICAgICAnbS0nICsgeXcgKyAnLDBWJyArIGNvb3Jkcy55czsgLy8gYmFyXG5cblxuICAgICAgICAgICAgICAgIGlmKCFjb29yZHMubm9ZUykgcGF0aCArPSAnbS0nICsgeXcgKyAnLDBoJyArICgyICogeXcpOyAvLyBzaG9lXG5cbiAgICAgICAgICAgICAgICBpc05ldyA9ICF5ZXJyb3Iuc2l6ZSgpO1xuXG4gICAgICAgICAgICAgICAgaWYoaXNOZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgeWVycm9yID0gZXJyb3JiYXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3llcnJvcicsIHRydWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihoYXNBbmltYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgeWVycm9yID0geWVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmR1cmF0aW9uKHRyYW5zaXRpb25PcHRzLmR1cmF0aW9uKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5lYXNlKHRyYW5zaXRpb25PcHRzLmVhc2luZyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgeWVycm9yLmF0dHIoJ2QnLCBwYXRoKTtcbiAgICAgICAgICAgIH0gZWxzZSB5ZXJyb3IucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgIHZhciB4ZXJyb3IgPSBlcnJvcmJhci5zZWxlY3QoJ3BhdGgueGVycm9yJyk7XG4gICAgICAgICAgICBpZih4T2JqLnZpc2libGUgJiYgaXNOdW1lcmljKGNvb3Jkcy55KSAmJlxuICAgICAgICAgICAgICAgICAgICBpc051bWVyaWMoY29vcmRzLnhoKSAmJlxuICAgICAgICAgICAgICAgICAgICBpc051bWVyaWMoY29vcmRzLnhzKSkge1xuICAgICAgICAgICAgICAgIHZhciB4dyA9ICh4T2JqLmNvcHlfeXN0eWxlID8geU9iaiA6IHhPYmopLndpZHRoO1xuXG4gICAgICAgICAgICAgICAgcGF0aCA9ICdNJyArIGNvb3Jkcy54aCArICcsJyArXG4gICAgICAgICAgICAgICAgICAgIChjb29yZHMueSAtIHh3KSArICd2JyArICgyICogeHcpICsgLy8gaGF0XG4gICAgICAgICAgICAgICAgICAgICdtMCwtJyArIHh3ICsgJ0gnICsgY29vcmRzLnhzOyAvLyBiYXJcblxuICAgICAgICAgICAgICAgIGlmKCFjb29yZHMubm9YUykgcGF0aCArPSAnbTAsLScgKyB4dyArICd2JyArICgyICogeHcpOyAvLyBzaG9lXG5cbiAgICAgICAgICAgICAgICBpc05ldyA9ICF4ZXJyb3Iuc2l6ZSgpO1xuXG4gICAgICAgICAgICAgICAgaWYoaXNOZXcpIHtcbiAgICAgICAgICAgICAgICAgICAgeGVycm9yID0gZXJyb3JiYXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3hlcnJvcicsIHRydWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihoYXNBbmltYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgeGVycm9yID0geGVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmR1cmF0aW9uKHRyYW5zaXRpb25PcHRzLmR1cmF0aW9uKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5lYXNlKHRyYW5zaXRpb25PcHRzLmVhc2luZyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgeGVycm9yLmF0dHIoJ2QnLCBwYXRoKTtcbiAgICAgICAgICAgIH0gZWxzZSB4ZXJyb3IucmVtb3ZlKCk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuLy8gY29tcHV0ZSB0aGUgY29vcmRpbmF0ZXMgb2YgdGhlIGVycm9yLWJhciBvYmplY3RzXG5mdW5jdGlvbiBlcnJvckNvb3JkcyhkLCB4YSwgeWEpIHtcbiAgICB2YXIgb3V0ID0ge1xuICAgICAgICB4OiB4YS5jMnAoZC54KSxcbiAgICAgICAgeTogeWEuYzJwKGQueSlcbiAgICB9O1xuXG4gICAgLy8gY2FsY3VsYXRlIHRoZSBlcnJvciBiYXIgc2l6ZSBhbmQgaGF0IGFuZCBzaG9lIGxvY2F0aW9uc1xuICAgIGlmKGQueWggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBvdXQueWggPSB5YS5jMnAoZC55aCk7XG4gICAgICAgIG91dC55cyA9IHlhLmMycChkLnlzKTtcblxuICAgICAgICAvLyBpZiB0aGUgc2hvZXMgZ28gb2ZmLXNjYWxlIChpZSBsb2cgc2NhbGUsIGVycm9yIGJhcnMgcGFzdCB6ZXJvKVxuICAgICAgICAvLyBjbGlwIHRoZSBiYXIgYW5kIGhpZGUgdGhlIHNob2VzXG4gICAgICAgIGlmKCFpc051bWVyaWMob3V0LnlzKSkge1xuICAgICAgICAgICAgb3V0Lm5vWVMgPSB0cnVlO1xuICAgICAgICAgICAgb3V0LnlzID0geWEuYzJwKGQueXMsIHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoZC54aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG91dC54aCA9IHhhLmMycChkLnhoKTtcbiAgICAgICAgb3V0LnhzID0geGEuYzJwKGQueHMpO1xuXG4gICAgICAgIGlmKCFpc051bWVyaWMob3V0LnhzKSkge1xuICAgICAgICAgICAgb3V0Lm5vWFMgPSB0cnVlO1xuICAgICAgICAgICAgb3V0LnhzID0geGEuYzJwKGQueHMsIHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxufSx7XCIuLi8uLi90cmFjZXMvc2NhdHRlci9zdWJ0eXBlc1wiOjExMzUsXCIuLi9kcmF3aW5nXCI6NjE0LFwiZDNcIjoxNjMsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDYyMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIENvbG9yID0gX2RlcmVxXygnLi4vY29sb3InKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN0eWxlKHRyYWNlcykge1xuICAgIHRyYWNlcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZTtcbiAgICAgICAgdmFyIHlPYmogPSB0cmFjZS5lcnJvcl95IHx8IHt9O1xuICAgICAgICB2YXIgeE9iaiA9IHRyYWNlLmVycm9yX3ggfHwge307XG5cbiAgICAgICAgdmFyIHMgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgcy5zZWxlY3RBbGwoJ3BhdGgueWVycm9yJylcbiAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgeU9iai50aGlja25lc3MgKyAncHgnKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCB5T2JqLmNvbG9yKTtcblxuICAgICAgICBpZih4T2JqLmNvcHlfeXN0eWxlKSB4T2JqID0geU9iajtcblxuICAgICAgICBzLnNlbGVjdEFsbCgncGF0aC54ZXJyb3InKVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCB4T2JqLnRoaWNrbmVzcyArICdweCcpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIHhPYmouY29sb3IpO1xuICAgIH0pO1xufTtcblxufSx7XCIuLi9jb2xvclwiOjU5MyxcImQzXCI6MTYzfV0sNjIzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGZvbnRBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGhvdmVyTGFiZWxBdHRycyA9IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKS5ob3ZlcmxhYmVsO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaG92ZXJsYWJlbDoge1xuICAgICAgICBiZ2NvbG9yOiBleHRlbmRGbGF0KHt9LCBob3ZlckxhYmVsQXR0cnMuYmdjb2xvciwge1xuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgYm9yZGVyY29sb3I6IGV4dGVuZEZsYXQoe30sIGhvdmVyTGFiZWxBdHRycy5ib3JkZXJjb2xvciwge1xuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBhbGlnbjogZXh0ZW5kRmxhdCh7fSwgaG92ZXJMYWJlbEF0dHJzLmFsaWduLCB7YXJyYXlPazogdHJ1ZX0pLFxuICAgICAgICBuYW1lbGVuZ3RoOiBleHRlbmRGbGF0KHt9LCBob3ZlckxhYmVsQXR0cnMubmFtZWxlbmd0aCwge2FycmF5T2s6IHRydWV9KSxcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJ1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlc1wiOjc5MyxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo2MzN9XSw2MjQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QpIHtcbiAgICB2YXIgY2FsY2RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgZnVuY3Rpb24gbWFrZUNvZXJjZUhvdmVySW5mbyh0cmFjZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24odmFsKSB7XG4gICAgICAgICAgICByZXR1cm4gTGliLmNvZXJjZUhvdmVyaW5mbyh7aG92ZXJpbmZvOiB2YWx9LCB7X21vZHVsZTogdHJhY2UuX21vZHVsZX0sIGZ1bGxMYXlvdXQpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2QgPSBjYWxjZGF0YVtpXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICAgICAgLy8gZG9uJ3QgaW5jbHVkZSBob3ZlciBjYWxjIGZpZWxkcyBmb3IgcGllIHRyYWNlc1xuICAgICAgICAvLyBhcyBjYWxjZGF0YSBpdGVtcyBtaWdodCBiZSBzb3J0ZWQgYnkgdmFsdWUgYW5kXG4gICAgICAgIC8vIHdvbid0IG1hdGNoIHRoZSBkYXRhIGFycmF5IG9yZGVyLlxuICAgICAgICBpZihSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAncGllLWxpa2UnKSkgY29udGludWU7XG5cbiAgICAgICAgdmFyIGZpbGxGbiA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICcyZE1hcCcpID8gcGFzdGUgOiBMaWIuZmlsbEFycmF5O1xuXG4gICAgICAgIGZpbGxGbih0cmFjZS5ob3ZlcmluZm8sIGNkLCAnaGknLCBtYWtlQ29lcmNlSG92ZXJJbmZvKHRyYWNlKSk7XG5cbiAgICAgICAgaWYodHJhY2UuaG92ZXJ0ZW1wbGF0ZSkgZmlsbEZuKHRyYWNlLmhvdmVydGVtcGxhdGUsIGNkLCAnaHQnKTtcblxuICAgICAgICBpZighdHJhY2UuaG92ZXJsYWJlbCkgY29udGludWU7XG5cbiAgICAgICAgZmlsbEZuKHRyYWNlLmhvdmVybGFiZWwuYmdjb2xvciwgY2QsICdoYmcnKTtcbiAgICAgICAgZmlsbEZuKHRyYWNlLmhvdmVybGFiZWwuYm9yZGVyY29sb3IsIGNkLCAnaGJjJyk7XG4gICAgICAgIGZpbGxGbih0cmFjZS5ob3ZlcmxhYmVsLmZvbnQuc2l6ZSwgY2QsICdodHMnKTtcbiAgICAgICAgZmlsbEZuKHRyYWNlLmhvdmVybGFiZWwuZm9udC5jb2xvciwgY2QsICdodGMnKTtcbiAgICAgICAgZmlsbEZuKHRyYWNlLmhvdmVybGFiZWwuZm9udC5mYW1pbHksIGNkLCAnaHRmJyk7XG4gICAgICAgIGZpbGxGbih0cmFjZS5ob3ZlcmxhYmVsLm5hbWVsZW5ndGgsIGNkLCAnaG5sJyk7XG4gICAgICAgIGZpbGxGbih0cmFjZS5ob3ZlcmxhYmVsLmFsaWduLCBjZCwgJ2h0YScpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHBhc3RlKHRyYWNlQXR0ciwgY2QsIGNkQXR0ciwgZm4pIHtcbiAgICBmbiA9IGZuIHx8IExpYi5pZGVudGl0eTtcblxuICAgIGlmKEFycmF5LmlzQXJyYXkodHJhY2VBdHRyKSkge1xuICAgICAgICBjZFswXVtjZEF0dHJdID0gZm4odHJhY2VBdHRyKTtcbiAgICB9XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDd9XSw2MjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIGhvdmVyID0gX2RlcmVxXygnLi9ob3ZlcicpLmhvdmVyO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNsaWNrKGdkLCBldnQsIHN1YnBsb3QpIHtcbiAgICB2YXIgYW5ub3RhdGlvbnNEb25lID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdhbm5vdGF0aW9ucycsICdvbkNsaWNrJykoZ2QsIGdkLl9ob3ZlcmRhdGEpO1xuXG4gICAgLy8gZmFsbGJhY2sgdG8gZmFpbC1zYWZlIGluIGNhc2UgdGhlIHBsb3QgdHlwZSdzIGhvdmVyIG1ldGhvZCBkb2Vzbid0IHBhc3MgdGhlIHN1YnBsb3QuXG4gICAgLy8gVGVybmFyeSwgZm9yIGV4YW1wbGUsIGRpZG4ndCwgYnV0IGl0IHdhcyBjYXVnaHQgYmVjYXVzZSB0ZXN0ZWQuXG4gICAgaWYoc3VicGxvdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIFRoZSB0cnVlIGZsYWcgYXQgdGhlIGVuZCBjYXVzZXMgaXQgdG8gcmUtcnVuIHRoZSBob3ZlciBjb21wdXRhdGlvbiB0byBmaWd1cmUgb3V0ICp3aGljaCpcbiAgICAgICAgLy8gcG9pbnQgaXMgYmVpbmcgY2xpY2tlZC4gV2l0aG91dCB0aGlzLCBjbGlja2luZyBpcyBzb21ld2hhdCB1bnJlbGlhYmxlLlxuICAgICAgICBob3ZlcihnZCwgZXZ0LCBzdWJwbG90LCB0cnVlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbWl0Q2xpY2soKSB7IGdkLmVtaXQoJ3Bsb3RseV9jbGljaycsIHtwb2ludHM6IGdkLl9ob3ZlcmRhdGEsIGV2ZW50OiBldnR9KTsgfVxuXG4gICAgaWYoZ2QuX2hvdmVyZGF0YSAmJiBldnQgJiYgZXZ0LnRhcmdldCkge1xuICAgICAgICBpZihhbm5vdGF0aW9uc0RvbmUgJiYgYW5ub3RhdGlvbnNEb25lLnRoZW4pIHtcbiAgICAgICAgICAgIGFubm90YXRpb25zRG9uZS50aGVuKGVtaXRDbGljayk7XG4gICAgICAgIH0gZWxzZSBlbWl0Q2xpY2soKTtcblxuICAgICAgICAvLyB3aHkgZG8gd2UgZ2V0IGEgZG91YmxlIGV2ZW50IHdpdGhvdXQgdGhpcz8/P1xuICAgICAgICBpZihldnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKSBldnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4vaG92ZXJcIjo2Mjl9XSw2MjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAvLyBob3ZlciBsYWJlbHMgZm9yIG11bHRpcGxlIGhvcml6b250YWwgYmFycyBnZXQgdGlsdGVkIGJ5IHRoaXMgYW5nbGVcbiAgICBZQU5HTEU6IDYwLFxuXG4gICAgLy8gc2l6ZSBhbmQgZGlzcGxheSBjb25zdGFudHMgZm9yIGhvdmVyIHRleHRcblxuICAgIC8vIHBpeGVsIHNpemUgb2YgaG92ZXIgYXJyb3dzXG4gICAgSE9WRVJBUlJPV1NJWkU6IDYsXG4gICAgLy8gcGl4ZWxzIHBhZGRpbmcgYXJvdW5kIHRleHRcbiAgICBIT1ZFUlRFWFRQQUQ6IDMsXG4gICAgLy8gaG92ZXIgZm9udFxuICAgIEhPVkVSRk9OVFNJWkU6IDEzLFxuICAgIEhPVkVSRk9OVDogJ0FyaWFsLCBzYW5zLXNlcmlmJyxcblxuICAgIC8vIG1pbmltdW0gdGltZSAobXNlYykgYmV0d2VlbiBob3ZlciBjYWxsc1xuICAgIEhPVkVSTUlOVElNRTogNTAsXG5cbiAgICAvLyBJRCBzdWZmaXggKHdpdGggZnVsbExheW91dC5fdWlkKSBmb3IgaG92ZXIgZXZlbnRzIGluIHRoZSB0aHJvdHRsZSBjYWNoZVxuICAgIEhPVkVSSUQ6ICctaG92ZXInXG59O1xuXG59LHt9XSw2Mjc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZUhvdmVyTGFiZWxEZWZhdWx0cyA9IF9kZXJlcV8oJy4vaG92ZXJsYWJlbF9kZWZhdWx0cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgb3B0cyA9IExpYi5leHRlbmRGbGF0KHt9LCBsYXlvdXQuaG92ZXJsYWJlbCk7XG4gICAgaWYodHJhY2VPdXQuaG92ZXJ0ZW1wbGF0ZSkgb3B0cy5uYW1lbGVuZ3RoID0gLTE7XG5cbiAgICBoYW5kbGVIb3ZlckxhYmVsRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgb3B0cyk7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4vYXR0cmlidXRlc1wiOjYyMyxcIi4vaG92ZXJsYWJlbF9kZWZhdWx0c1wiOjYzMH1dLDYyODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxuLy8gbG9vayBmb3IgZWl0aGVyIHN1YnBsb3Qgb3IgeGF4aXMgYW5kIHlheGlzIGF0dHJpYnV0ZXNcbi8vIGRvZXMgbm90IGhhbmRsZSBzcGxvbSBjYXNlXG5leHBvcnRzLmdldFN1YnBsb3QgPSBmdW5jdGlvbiBnZXRTdWJwbG90KHRyYWNlKSB7XG4gICAgcmV0dXJuIHRyYWNlLnN1YnBsb3QgfHwgKHRyYWNlLnhheGlzICsgdHJhY2UueWF4aXMpIHx8IHRyYWNlLmdlbztcbn07XG5cbi8vIGlzIHRyYWNlIGluIGdpdmVuIGxpc3Qgb2Ygc3VicGxvdHM/XG4vLyBkb2VzIGhhbmRsZSBzcGxvbSBjYXNlXG5leHBvcnRzLmlzVHJhY2VJblN1YnBsb3RzID0gZnVuY3Rpb24gaXNUcmFjZUluU3VicGxvdHModHJhY2UsIHN1YnBsb3RzKSB7XG4gICAgaWYodHJhY2UudHlwZSA9PT0gJ3NwbG9tJykge1xuICAgICAgICB2YXIgeGF4ZXMgPSB0cmFjZS54YXhlcyB8fCBbXTtcbiAgICAgICAgdmFyIHlheGVzID0gdHJhY2UueWF4ZXMgfHwgW107XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB4YXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IHlheGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYoc3VicGxvdHMuaW5kZXhPZih4YXhlc1tpXSArIHlheGVzW2pdKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3VicGxvdHMuaW5kZXhPZihleHBvcnRzLmdldFN1YnBsb3QodHJhY2UpKSAhPT0gLTE7XG59O1xuXG4vLyBjb252ZW5pZW5jZSBmdW5jdGlvbnMgZm9yIG1hcHBpbmcgYWxsIHJlbGV2YW50IGF4ZXNcbmV4cG9ydHMuZmxhdCA9IGZ1bmN0aW9uIGZsYXQoc3VicGxvdHMsIHYpIHtcbiAgICB2YXIgb3V0ID0gbmV3IEFycmF5KHN1YnBsb3RzLmxlbmd0aCk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG91dFtpXSA9IHY7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59O1xuXG5leHBvcnRzLnAyYyA9IGZ1bmN0aW9uIHAyYyhheEFycmF5LCB2KSB7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShheEFycmF5Lmxlbmd0aCk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4QXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgb3V0W2ldID0gYXhBcnJheVtpXS5wMmModik7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59O1xuXG5leHBvcnRzLmdldERpc3RhbmNlRnVuY3Rpb24gPSBmdW5jdGlvbiBnZXREaXN0YW5jZUZ1bmN0aW9uKG1vZGUsIGR4LCBkeSwgZHh5KSB7XG4gICAgaWYobW9kZSA9PT0gJ2Nsb3Nlc3QnKSByZXR1cm4gZHh5IHx8IGV4cG9ydHMucXVhZHJhdHVyZShkeCwgZHkpO1xuICAgIHJldHVybiBtb2RlID09PSAneCcgPyBkeCA6IGR5O1xufTtcblxuZXhwb3J0cy5nZXRDbG9zZXN0ID0gZnVuY3Rpb24gZ2V0Q2xvc2VzdChjZCwgZGlzdGZuLCBwb2ludERhdGEpIHtcbiAgICAvLyBkbyB3ZSBhbHJlYWR5IGhhdmUgYSBwb2ludCBudW1iZXI/IChhcnJheSBtb2RlIG9ubHkpXG4gICAgaWYocG9pbnREYXRhLmluZGV4ICE9PSBmYWxzZSkge1xuICAgICAgICBpZihwb2ludERhdGEuaW5kZXggPj0gMCAmJiBwb2ludERhdGEuaW5kZXggPCBjZC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHBvaW50RGF0YS5kaXN0YW5jZSA9IDA7XG4gICAgICAgIH0gZWxzZSBwb2ludERhdGEuaW5kZXggPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBhcHBseSB0aGUgZGlzdGFuY2UgZnVuY3Rpb24gdG8gZWFjaCBkYXRhIHBvaW50XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGxvbmdlc3QgbG9vcC4uLiBpZiB0aGlzIGJvZ3MgZG93biwgd2UgbWF5IG5lZWRcbiAgICAgICAgLy8gdG8gY3JlYXRlIHByZS1zb3J0ZWQgZGF0YSAoYnkgeCBvciB5KSwgbm90IHN1cmUgaG93IHRvXG4gICAgICAgIC8vIGRvIHRoaXMgZm9yICdjbG9zZXN0J1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBuZXdEaXN0YW5jZSA9IGRpc3RmbihjZFtpXSk7XG4gICAgICAgICAgICBpZihuZXdEaXN0YW5jZSA8PSBwb2ludERhdGEuZGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICBwb2ludERhdGEuaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgIHBvaW50RGF0YS5kaXN0YW5jZSA9IG5ld0Rpc3RhbmNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwb2ludERhdGE7XG59O1xuXG4vKlxuICogcHNldWRvLWRpc3RhbmNlIGZ1bmN0aW9uIGZvciBob3ZlciBlZmZlY3RzIG9uIGFyZWFzOiBpbnNpZGUgdGhlIHJlZ2lvblxuICogZGlzdGFuY2UgaXMgZmluaXRlIChgcGFzc1ZhbGApLCBvdXRzaWRlIGl0J3MgSW5maW5pdHkuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHYwOiBzaWduZWQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBjdXJyZW50IHBvc2l0aW9uIGFuZCB0aGUgbGVmdCBlZGdlXG4gKiBAcGFyYW0ge251bWJlcn0gdjE6IHNpZ25lZCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGN1cnJlbnQgcG9zaXRpb24gYW5kIHRoZSByaWdodCBlZGdlXG4gKiBAcGFyYW0ge251bWJlcn0gcGFzc1ZhbDogdGhlIHZhbHVlIHRvIHJldHVybiBvbiBzdWNjZXNzXG4gKi9cbmV4cG9ydHMuaW5ib3ggPSBmdW5jdGlvbiBpbmJveCh2MCwgdjEsIHBhc3NWYWwpIHtcbiAgICByZXR1cm4gKHYwICogdjEgPCAwIHx8IHYwID09PSAwKSA/IHBhc3NWYWwgOiBJbmZpbml0eTtcbn07XG5cbmV4cG9ydHMucXVhZHJhdHVyZSA9IGZ1bmN0aW9uIHF1YWRyYXR1cmUoZHgsIGR5KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgIHZhciB4ID0gZHgoZGkpO1xuICAgICAgICB2YXIgeSA9IGR5KGRpKTtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh4ICogeCArIHkgKiB5KTtcbiAgICB9O1xufTtcblxuLyoqIEZpbGwgZXZlbnQgZGF0YSBwb2ludCBvYmplY3QgZm9yIGhvdmVyIGFuZCBzZWxlY3Rpb24uXG4gKiAgSW52b2tlcyBfbW9kdWxlLmV2ZW50RGF0YSBpZiBwcmVzZW50LlxuICpcbiAqIE4uQi4gbm90ZSB0aGF0IHBvaW50ICdpbmRleCcgY29ycmVzcG9uZHMgdG8gaW5wdXQgZGF0YSBhcnJheSBpbmRleFxuICogIHdoZXJlYXMgJ251bWJlcicgaXMgaXRzIHBvc3QtdHJhbnNmb3JtIHZlcnNpb24uXG4gKlxuICogSWYgdGhlIGhvdmVyZWQvc2VsZWN0ZWQgcHQgY29ycmVzcG9uZHMgdG8gYW4gbXVsdGlwbGUgaW5wdXQgcG9pbnRzXG4gKiAoZS5nLiBmb3IgaGlzdG9ncmFtIGFuZCB0cmFuc2Zvcm1lZCB0cmFjZXMpLCAncG9pbnROdW1iZXJzYCBhbmQgJ3BvaW50SW5kaWNlcydcbiAqIGFyZSBpbmNsdWRlIGluIHRoZSBldmVudCBkYXRhLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwdFxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlXG4gKiBAcGFyYW0ge29iamVjdH0gY2RcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqL1xuZXhwb3J0cy5tYWtlRXZlbnREYXRhID0gZnVuY3Rpb24gbWFrZUV2ZW50RGF0YShwdCwgdHJhY2UsIGNkKSB7XG4gICAgLy8gaG92ZXIgdXNlcyAnaW5kZXgnLCBzZWxlY3QgdXNlcyAncG9pbnROdW1iZXInXG4gICAgdmFyIHBvaW50TnVtYmVyID0gJ2luZGV4JyBpbiBwdCA/IHB0LmluZGV4IDogcHQucG9pbnROdW1iZXI7XG5cbiAgICB2YXIgb3V0ID0ge1xuICAgICAgICBkYXRhOiB0cmFjZS5faW5wdXQsXG4gICAgICAgIGZ1bGxEYXRhOiB0cmFjZSxcbiAgICAgICAgY3VydmVOdW1iZXI6IHRyYWNlLmluZGV4LFxuICAgICAgICBwb2ludE51bWJlcjogcG9pbnROdW1iZXJcbiAgICB9O1xuXG4gICAgaWYodHJhY2UuX2luZGV4VG9Qb2ludHMpIHtcbiAgICAgICAgdmFyIHBvaW50SW5kaWNlcyA9IHRyYWNlLl9pbmRleFRvUG9pbnRzW3BvaW50TnVtYmVyXTtcblxuICAgICAgICBpZihwb2ludEluZGljZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICBvdXQucG9pbnRJbmRleCA9IHBvaW50SW5kaWNlc1swXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG91dC5wb2ludEluZGljZXMgPSBwb2ludEluZGljZXM7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBvdXQucG9pbnRJbmRleCA9IHBvaW50TnVtYmVyO1xuICAgIH1cblxuICAgIGlmKHRyYWNlLl9tb2R1bGUuZXZlbnREYXRhKSB7XG4gICAgICAgIG91dCA9IHRyYWNlLl9tb2R1bGUuZXZlbnREYXRhKG91dCwgcHQsIHRyYWNlLCBjZCwgcG9pbnROdW1iZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKCd4VmFsJyBpbiBwdCkgb3V0LnggPSBwdC54VmFsO1xuICAgICAgICBlbHNlIGlmKCd4JyBpbiBwdCkgb3V0LnggPSBwdC54O1xuXG4gICAgICAgIGlmKCd5VmFsJyBpbiBwdCkgb3V0LnkgPSBwdC55VmFsO1xuICAgICAgICBlbHNlIGlmKCd5JyBpbiBwdCkgb3V0LnkgPSBwdC55O1xuXG4gICAgICAgIGlmKHB0LnhhKSBvdXQueGF4aXMgPSBwdC54YTtcbiAgICAgICAgaWYocHQueWEpIG91dC55YXhpcyA9IHB0LnlhO1xuICAgICAgICBpZihwdC56TGFiZWxWYWwgIT09IHVuZGVmaW5lZCkgb3V0LnogPSBwdC56TGFiZWxWYWw7XG4gICAgfVxuXG4gICAgZXhwb3J0cy5hcHBlbmRBcnJheVBvaW50VmFsdWUob3V0LCB0cmFjZSwgcG9pbnROdW1iZXIpO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKiBBcHBlbmRzIHZhbHVlcyBpbnNpZGUgYXJyYXkgYXR0cmlidXRlcyBjb3JyZXNwb25kaW5nIHRvIGdpdmVuIHBvaW50IG51bWJlclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwb2ludERhdGEgOiBwb2ludCBkYXRhIG9iamVjdCAoZ2V0cyBtdXRhdGVkIGhlcmUpXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2UgOiBmdWxsIHRyYWNlIG9iamVjdFxuICogQHBhcmFtIHtudW1iZXJ8QXJyYXkobnVtYmVyKX0gcG9pbnROdW1iZXIgOiBwb2ludCBudW1iZXIuIE1heSBiZSBhIGxlbmd0aC0yIGFycmF5XG4gKiAgICAgW3JvdywgY29sXSB0byBkaWcgaW50byAyRCBhcnJheXNcbiAqL1xuZXhwb3J0cy5hcHBlbmRBcnJheVBvaW50VmFsdWUgPSBmdW5jdGlvbihwb2ludERhdGEsIHRyYWNlLCBwb2ludE51bWJlcikge1xuICAgIHZhciBhcnJheUF0dHJzID0gdHJhY2UuX2FycmF5QXR0cnM7XG5cbiAgICBpZighYXJyYXlBdHRycykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFycmF5QXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGFzdHIgPSBhcnJheUF0dHJzW2ldO1xuICAgICAgICB2YXIga2V5ID0gZ2V0UG9pbnRLZXkoYXN0cik7XG5cbiAgICAgICAgaWYocG9pbnREYXRhW2tleV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdmFyIHZhbCA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgYXN0cikuZ2V0KCk7XG4gICAgICAgICAgICB2YXIgcG9pbnRWYWwgPSBnZXRQb2ludERhdGEodmFsLCBwb2ludE51bWJlcik7XG5cbiAgICAgICAgICAgIGlmKHBvaW50VmFsICE9PSB1bmRlZmluZWQpIHBvaW50RGF0YVtrZXldID0gcG9pbnRWYWw7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vKipcbiAqIEFwcGVuZHMgdmFsdWVzIGluc2lkZSBhcnJheSBhdHRyaWJ1dGVzIGNvcnJlc3BvbmRpbmcgdG8gZ2l2ZW4gcG9pbnQgbnVtYmVyIGFycmF5XG4gKiBGb3IgdXNlIHdoZW4gcG9pbnREYXRhIHJlZmVyZW5jZXMgYSBwbG90IGVudGl0eSB0aGF0IGFyb3NlIChvciBwb3RlbnRpYWxseSBhcm9zZSlcbiAqIGZyb20gbXVsdGlwbGUgcG9pbnRzIGluIHRoZSBpbnB1dCBkYXRhXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHBvaW50RGF0YSA6IHBvaW50IGRhdGEgb2JqZWN0IChnZXRzIG11dGF0ZWQgaGVyZSlcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFjZSA6IGZ1bGwgdHJhY2Ugb2JqZWN0XG4gKiBAcGFyYW0ge0FycmF5KG51bWJlcil8QXJyYXkoQXJyYXkobnVtYmVyKSl9IHBvaW50TnVtYmVycyA6IEFycmF5IG9mIHBvaW50IG51bWJlcnMuXG4gKiAgICAgRWFjaCBlbnRyeSBpbiB0aGUgYXJyYXkgbWF5IGl0c2VsZiBiZSBhIGxlbmd0aC0yIGFycmF5IFtyb3csIGNvbF0gdG8gZGlnIGludG8gMkQgYXJyYXlzXG4gKi9cbmV4cG9ydHMuYXBwZW5kQXJyYXlNdWx0aVBvaW50VmFsdWVzID0gZnVuY3Rpb24ocG9pbnREYXRhLCB0cmFjZSwgcG9pbnROdW1iZXJzKSB7XG4gICAgdmFyIGFycmF5QXR0cnMgPSB0cmFjZS5fYXJyYXlBdHRycztcblxuICAgIGlmKCFhcnJheUF0dHJzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJyYXlBdHRycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXN0ciA9IGFycmF5QXR0cnNbaV07XG4gICAgICAgIHZhciBrZXkgPSBnZXRQb2ludEtleShhc3RyKTtcblxuICAgICAgICBpZihwb2ludERhdGFba2V5XSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB2YXIgdmFsID0gTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBhc3RyKS5nZXQoKTtcbiAgICAgICAgICAgIHZhciBrZXlWYWwgPSBuZXcgQXJyYXkocG9pbnROdW1iZXJzLmxlbmd0aCk7XG5cbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBwb2ludE51bWJlcnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBrZXlWYWxbal0gPSBnZXRQb2ludERhdGEodmFsLCBwb2ludE51bWJlcnNbal0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcG9pbnREYXRhW2tleV0gPSBrZXlWYWw7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG52YXIgcG9pbnRLZXlNYXAgPSB7XG4gICAgaWRzOiAnaWQnLFxuICAgIGxvY2F0aW9uczogJ2xvY2F0aW9uJyxcbiAgICBsYWJlbHM6ICdsYWJlbCcsXG4gICAgdmFsdWVzOiAndmFsdWUnLFxuICAgICdtYXJrZXIuY29sb3JzJzogJ2NvbG9yJyxcbiAgICBwYXJlbnRzOiAncGFyZW50J1xufTtcblxuZnVuY3Rpb24gZ2V0UG9pbnRLZXkoYXN0cikge1xuICAgIHJldHVybiBwb2ludEtleU1hcFthc3RyXSB8fCBhc3RyO1xufVxuXG5mdW5jdGlvbiBnZXRQb2ludERhdGEodmFsLCBwb2ludE51bWJlcikge1xuICAgIGlmKEFycmF5LmlzQXJyYXkocG9pbnROdW1iZXIpKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodmFsKSAmJiBBcnJheS5pc0FycmF5KHZhbFtwb2ludE51bWJlclswXV0pKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsW3BvaW50TnVtYmVyWzBdXVtwb2ludE51bWJlclsxXV07XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdmFsW3BvaW50TnVtYmVyXTtcbiAgICB9XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sNjI5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIHRpbnljb2xvciA9IF9kZXJlcV8oJ3Rpbnljb2xvcjInKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEV2ZW50cyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9ldmVudHMnKTtcbnZhciBzdmdUZXh0VXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcbnZhciBvdmVycmlkZUN1cnNvciA9IF9kZXJlcV8oJy4uLy4uL2xpYi9vdmVycmlkZV9jdXJzb3InKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vZHJhd2luZycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vY29sb3InKTtcbnZhciBkcmFnRWxlbWVudCA9IF9kZXJlcV8oJy4uL2RyYWdlbGVtZW50Jyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xuXG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG5cbi8vIGhvdmVyIGxhYmVscyBmb3IgbXVsdGlwbGUgaG9yaXpvbnRhbCBiYXJzIGdldCB0aWx0ZWQgYnkgc29tZSBhbmdsZSxcbi8vIHRoZW4gbmVlZCB0byBiZSBvZmZzZXQgZGlmZmVyZW50bHkgaWYgdGhleSBvdmVybGFwXG52YXIgWUFOR0xFID0gY29uc3RhbnRzLllBTkdMRTtcbnZhciBZQV9SQURJQU5TID0gTWF0aC5QSSAqIFlBTkdMRSAvIDE4MDtcblxuLy8gZXhwYW5zaW9uIG9mIHByb2plY3RlZCBoZWlnaHRcbnZhciBZRkFDVE9SID0gMSAvIE1hdGguc2luKFlBX1JBRElBTlMpO1xuXG4vLyB0byBtYWtlIHRoZSBhcHByb3ByaWF0ZSBwb3N0LXJvdGF0aW9uIHggb2Zmc2V0LFxuLy8geW91IG5lZWQgYm90aCB4IGFuZCB5IG9mZnNldHNcbnZhciBZU0hJRlRYID0gTWF0aC5jb3MoWUFfUkFESUFOUyk7XG52YXIgWVNISUZUWSA9IE1hdGguc2luKFlBX1JBRElBTlMpO1xuXG4vLyBzaXplIGFuZCBkaXNwbGF5IGNvbnN0YW50cyBmb3IgaG92ZXIgdGV4dFxudmFyIEhPVkVSQVJST1dTSVpFID0gY29uc3RhbnRzLkhPVkVSQVJST1dTSVpFO1xudmFyIEhPVkVSVEVYVFBBRCA9IGNvbnN0YW50cy5IT1ZFUlRFWFRQQUQ7XG5cbi8vIGZ4LmhvdmVyOiBoaWdobGlnaHQgZGF0YSBvbiBob3ZlclxuLy8gZXZ0IGNhbiBiZSBhIG1vdXNlbW92ZSBldmVudCwgb3IgYW4gb2JqZWN0IHdpdGggZGF0YSBhYm91dCB3aGF0IHBvaW50c1xuLy8gICB0byBob3ZlciBvblxuLy8gICAgICB7eHB4LHlweFssaG92ZXJtb2RlXX0gLSBwaXhlbCBsb2NhdGlvbnMgZnJvbSB0b3AgbGVmdFxuLy8gICAgICAgICAgKHdpdGggb3B0aW9uYWwgb3ZlcnJpZGluZyBob3Zlcm1vZGUpXG4vLyAgICAgIHt4dmFsLHl2YWxbLGhvdmVybW9kZV19IC0gZGF0YSB2YWx1ZXNcbi8vICAgICAgW3tjdXJ2ZU51bWJlciwocG9pbnROdW1iZXJ8eHZhbCBhbmQvb3IgeXZhbCl9XSAtXG4vLyAgICAgICAgICAgICAgYXJyYXkgb2Ygc3BlY2lmaWMgcG9pbnRzIHRvIGhpZ2hsaWdodFxuLy8gICAgICAgICAgcG9pbnROdW1iZXIgaXMgYSBzaW5nbGUgaW50ZWdlciBpZiBnZC5kYXRhW2N1cnZlTnVtYmVyXSBpcyAxRCxcbi8vICAgICAgICAgICAgICBvciBhIHR3by1lbGVtZW50IGFycmF5IGlmIGl0J3MgMkRcbi8vICAgICAgICAgIHh2YWwgYW5kIHl2YWwgYXJlIGRhdGEgdmFsdWVzLFxuLy8gICAgICAgICAgICAgIDFEIGRhdGEgbWF5IHNwZWNpZnkgZWl0aGVyIG9yIGJvdGgsXG4vLyAgICAgICAgICAgICAgMkQgZGF0YSBtdXN0IHNwZWNpZnkgYm90aFxuLy8gc3VicGxvdCBpcyBhbiBpZCBzdHJpbmcgKGRlZmF1bHQgXCJ4eVwiKVxuLy8gbWFrZXMgdXNlIG9mIGdsLmhvdmVybW9kZSwgd2hpY2ggY2FuIGJlOlxuLy8gICAgICB4IChmaW5kIHRoZSBwb2ludHMgd2l0aCB0aGUgY2xvc2VzdCB4IHZhbHVlcywgaWUgYSBjb2x1bW4pLFxuLy8gICAgICBjbG9zZXN0IChmaW5kIHRoZSBzaW5nbGUgY2xvc2VzdCBwb2ludClcbi8vICAgIGludGVybmFsbHkgdGhlcmUgYXJlIHR3byBtb3JlIHRoYXQgb2NjYXNpb25hbGx5IGdldCB1c2VkOlxuLy8gICAgICB5IChwaWNrIG91dCBhIHJvdyAtIG9ubHkgdXNlZCBmb3IgbXVsdGlwbGUgaG9yaXpvbnRhbCBiYXIgY2hhcnRzKVxuLy8gICAgICBhcnJheSAodXNlZCB3aGVuIHRoZSB1c2VyIHNwZWNpZmllcyBhbiBleHBsaWNpdFxuLy8gICAgICAgICAgYXJyYXkgb2YgcG9pbnRzIHRvIGhvdmVyIG9uKVxuLy9cbi8vIFdlIHdyYXAgdGhlIGhvdmVycyBpbiBhIHRpbWVyLCB0byBsaW1pdCB0aGVpciBmcmVxdWVuY3kuXG4vLyBUaGUgYWN0dWFsIHJlbmRlcmluZyBpcyBkb25lIGJ5IHByaXZhdGUgZnVuY3Rpb24gX2hvdmVyLlxuZXhwb3J0cy5ob3ZlciA9IGZ1bmN0aW9uIGhvdmVyKGdkLCBldnQsIHN1YnBsb3QsIG5vSG92ZXJFdmVudCkge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIExpYi50aHJvdHRsZShcbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX3VpZCArIGNvbnN0YW50cy5IT1ZFUklELFxuICAgICAgICBjb25zdGFudHMuSE9WRVJNSU5USU1FLFxuICAgICAgICBmdW5jdGlvbigpIHsgX2hvdmVyKGdkLCBldnQsIHN1YnBsb3QsIG5vSG92ZXJFdmVudCk7IH1cbiAgICApO1xufTtcblxuLypcbiAqIERyYXcgYSBzaW5nbGUgaG92ZXIgaXRlbSBvciBhbiBhcnJheSBvZiBob3ZlciBpdGVtIGluIGEgcHJlLWV4aXN0aW5nIHN2ZyBjb250YWluZXIgc29tZXdoZXJlXG4gKiBob3Zlckl0ZW0gc2hvdWxkIGhhdmUga2V5czpcbiAqICAgIC0geCBhbmQgeSAob3IgeDAsIHgxLCB5MCwgYW5kIHkxKTpcbiAqICAgICAgdGhlIHBpeGVsIHBvc2l0aW9uIHRvIG1hcmssIHJlbGF0aXZlIHRvIG9wdHMuY29udGFpbmVyXG4gKiAgICAtIHhMYWJlbCwgeUxhYmVsLCB6TGFiZWwsIHRleHQsIGFuZCBuYW1lOlxuICogICAgICBpbmZvIHRvIGdvIGluIHRoZSBsYWJlbFxuICogICAgLSBjb2xvcjpcbiAqICAgICAgdGhlIGJhY2tncm91bmQgY29sb3IgZm9yIHRoZSBsYWJlbC5cbiAqICAgIC0gaWRlYWxBbGlnbiAob3B0aW9uYWwpOlxuICogICAgICAnbGVmdCcgb3IgJ3JpZ2h0JyBmb3Igd2hpY2ggc2lkZSBvZiB0aGUgeC95IGJveCB0byB0cnkgdG8gcHV0IHRoaXMgb24gZmlyc3RcbiAqICAgIC0gYm9yZGVyQ29sb3IgKG9wdGlvbmFsKTpcbiAqICAgICAgY29sb3IgZm9yIHRoZSBib3JkZXIsIGRlZmF1bHRzIHRvIHN0cm9uZ2VzdCBjb250cmFzdCB3aXRoIGNvbG9yXG4gKiAgICAtIGZvbnRGYW1pbHkgKG9wdGlvbmFsKTpcbiAqICAgICAgc3RyaW5nLCB0aGUgZm9udCBmb3IgdGhpcyBsYWJlbCwgZGVmYXVsdHMgdG8gY29uc3RhbnRzLkhPVkVSRk9OVFxuICogICAgLSBmb250U2l6ZSAob3B0aW9uYWwpOlxuICogICAgICB0aGUgbGFiZWwgZm9udCBzaXplLCBkZWZhdWx0cyB0byBjb25zdGFudHMuSE9WRVJGT05UU0laRVxuICogICAgLSBmb250Q29sb3IgKG9wdGlvbmFsKTpcbiAqICAgICAgZGVmYXVsdHMgdG8gYm9yZGVyQ29sb3JcbiAqIG9wdHMgc2hvdWxkIGhhdmUga2V5czpcbiAqICAgIC0gYmdDb2xvcjpcbiAqICAgICAgdGhlIGJhY2tncm91bmQgY29sb3IgdGhpcyBpcyBhZ2FpbnN0LCB1c2VkIGlmIHRoZSB0cmFjZSBpc1xuICogICAgICBub24tb3BhcXVlLCBhbmQgZm9yIHRoZSBuYW1lLCB3aGljaCBnb2VzIG91dHNpZGUgdGhlIGJveFxuICogICAgLSBjb250YWluZXI6XG4gKiAgICAgIGEgPHN2Zz4gb3IgPGc+IGVsZW1lbnQgdG8gYWRkIHRoZSBob3ZlciBsYWJlbCB0b1xuICogICAgLSBvdXRlckNvbnRhaW5lcjpcbiAqICAgICAgbm9ybWFsbHkgYSBwYXJlbnQgb2YgYGNvbnRhaW5lcmAsIHNldHMgdGhlIGJvdW5kaW5nIGJveCB0byB1c2UgdG9cbiAqICAgICAgY29uc3RyYWluIHRoZSBob3ZlciBsYWJlbCBhbmQgZGV0ZXJtaW5lIHdoZXRoZXIgdG8gc2hvdyBpdCBvbiB0aGUgbGVmdCBvciByaWdodFxuICogb3B0cyBjYW4gaGF2ZSBvcHRpb25hbCBrZXlzOlxuICogICAgLSBhbmNob3JJbmRleDpcbiAgICAgICAgdGhlIGluZGV4IG9mIHRoZSBob3ZlciBpdGVtIHVzZWQgYXMgYW4gYW5jaG9yIGZvciBwb3NpdGlvbmluZy5cbiAgICAgICAgVGhlIG90aGVyIGhvdmVyIGl0ZW1zIHdpbGwgYmUgcHVzaGVkIHVwIG9yIGRvd24gdG8gcHJldmVudCBvdmVybGFwLlxuICovXG5leHBvcnRzLmxvbmVIb3ZlciA9IGZ1bmN0aW9uIGxvbmVIb3Zlcihob3Zlckl0ZW1zLCBvcHRzKSB7XG4gICAgdmFyIG11bHRpSG92ZXIgPSB0cnVlO1xuICAgIGlmKCFBcnJheS5pc0FycmF5KGhvdmVySXRlbXMpKSB7XG4gICAgICAgIG11bHRpSG92ZXIgPSBmYWxzZTtcbiAgICAgICAgaG92ZXJJdGVtcyA9IFtob3Zlckl0ZW1zXTtcbiAgICB9XG5cbiAgICB2YXIgcG9pbnRzRGF0YSA9IGhvdmVySXRlbXMubWFwKGZ1bmN0aW9uKGhvdmVySXRlbSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29sb3I6IGhvdmVySXRlbS5jb2xvciB8fCBDb2xvci5kZWZhdWx0TGluZSxcbiAgICAgICAgICAgIHgwOiBob3Zlckl0ZW0ueDAgfHwgaG92ZXJJdGVtLnggfHwgMCxcbiAgICAgICAgICAgIHgxOiBob3Zlckl0ZW0ueDEgfHwgaG92ZXJJdGVtLnggfHwgMCxcbiAgICAgICAgICAgIHkwOiBob3Zlckl0ZW0ueTAgfHwgaG92ZXJJdGVtLnkgfHwgMCxcbiAgICAgICAgICAgIHkxOiBob3Zlckl0ZW0ueTEgfHwgaG92ZXJJdGVtLnkgfHwgMCxcbiAgICAgICAgICAgIHhMYWJlbDogaG92ZXJJdGVtLnhMYWJlbCxcbiAgICAgICAgICAgIHlMYWJlbDogaG92ZXJJdGVtLnlMYWJlbCxcbiAgICAgICAgICAgIHpMYWJlbDogaG92ZXJJdGVtLnpMYWJlbCxcbiAgICAgICAgICAgIHRleHQ6IGhvdmVySXRlbS50ZXh0LFxuICAgICAgICAgICAgbmFtZTogaG92ZXJJdGVtLm5hbWUsXG4gICAgICAgICAgICBpZGVhbEFsaWduOiBob3Zlckl0ZW0uaWRlYWxBbGlnbixcblxuICAgICAgICAgICAgLy8gb3B0aW9uYWwgZXh0cmEgYml0cyBvZiBzdHlsaW5nXG4gICAgICAgICAgICBib3JkZXJDb2xvcjogaG92ZXJJdGVtLmJvcmRlckNvbG9yLFxuICAgICAgICAgICAgZm9udEZhbWlseTogaG92ZXJJdGVtLmZvbnRGYW1pbHksXG4gICAgICAgICAgICBmb250U2l6ZTogaG92ZXJJdGVtLmZvbnRTaXplLFxuICAgICAgICAgICAgZm9udENvbG9yOiBob3Zlckl0ZW0uZm9udENvbG9yLFxuICAgICAgICAgICAgbmFtZUxlbmd0aDogaG92ZXJJdGVtLm5hbWVMZW5ndGgsXG4gICAgICAgICAgICB0ZXh0QWxpZ246IGhvdmVySXRlbS50ZXh0QWxpZ24sXG5cbiAgICAgICAgICAgIC8vIGZpbGxlciB0byBtYWtlIGNyZWF0ZUhvdmVyVGV4dCBoYXBweVxuICAgICAgICAgICAgdHJhY2U6IGhvdmVySXRlbS50cmFjZSB8fCB7XG4gICAgICAgICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgICAgICAgaG92ZXJpbmZvOiAnJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHhhOiB7X29mZnNldDogMH0sXG4gICAgICAgICAgICB5YToge19vZmZzZXQ6IDB9LFxuICAgICAgICAgICAgaW5kZXg6IDAsXG5cbiAgICAgICAgICAgIGhvdmVydGVtcGxhdGU6IGhvdmVySXRlbS5ob3ZlcnRlbXBsYXRlIHx8IGZhbHNlLFxuICAgICAgICAgICAgZXZlbnREYXRhOiBob3Zlckl0ZW0uZXZlbnREYXRhIHx8IGZhbHNlLFxuICAgICAgICAgICAgaG92ZXJ0ZW1wbGF0ZUxhYmVsczogaG92ZXJJdGVtLmhvdmVydGVtcGxhdGVMYWJlbHMgfHwgZmFsc2UsXG4gICAgICAgIH07XG4gICAgfSk7XG5cbiAgICB2YXIgY29udGFpbmVyMyA9IGQzLnNlbGVjdChvcHRzLmNvbnRhaW5lcik7XG4gICAgdmFyIG91dGVyQ29udGFpbmVyMyA9IG9wdHMub3V0ZXJDb250YWluZXIgPyBkMy5zZWxlY3Qob3B0cy5vdXRlckNvbnRhaW5lcikgOiBjb250YWluZXIzO1xuXG4gICAgdmFyIGZ1bGxPcHRzID0ge1xuICAgICAgICBob3Zlcm1vZGU6ICdjbG9zZXN0JyxcbiAgICAgICAgcm90YXRlTGFiZWxzOiBmYWxzZSxcbiAgICAgICAgYmdDb2xvcjogb3B0cy5iZ0NvbG9yIHx8IENvbG9yLmJhY2tncm91bmQsXG4gICAgICAgIGNvbnRhaW5lcjogY29udGFpbmVyMyxcbiAgICAgICAgb3V0ZXJDb250YWluZXI6IG91dGVyQ29udGFpbmVyM1xuICAgIH07XG5cbiAgICB2YXIgaG92ZXJMYWJlbCA9IGNyZWF0ZUhvdmVyVGV4dChwb2ludHNEYXRhLCBmdWxsT3B0cywgb3B0cy5nZCk7XG5cbiAgICAvLyBGaXggdmVydGljYWwgb3ZlcmxhcFxuICAgIHZhciB0b29sdGlwU3BhY2luZyA9IDU7XG4gICAgdmFyIGxhc3RCb3R0b21ZID0gMDtcbiAgICB2YXIgYW5jaG9yID0gMDtcbiAgICBob3ZlckxhYmVsXG4gICAgICAgIC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtyZXR1cm4gYS55MCAtIGIueTA7fSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgdmFyIHRvcFkgPSBkLnkwIC0gZC5ieSAvIDI7XG5cbiAgICAgICAgICAgIGlmKCh0b3BZIC0gdG9vbHRpcFNwYWNpbmcpIDwgbGFzdEJvdHRvbVkpIHtcbiAgICAgICAgICAgICAgICBkLm9mZnNldCA9IChsYXN0Qm90dG9tWSAtIHRvcFkpICsgdG9vbHRpcFNwYWNpbmc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGQub2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGFzdEJvdHRvbVkgPSB0b3BZICsgZC5ieSArIGQub2Zmc2V0O1xuXG4gICAgICAgICAgICBpZihpID09PSBvcHRzLmFuY2hvckluZGV4IHx8IDApIGFuY2hvciA9IGQub2Zmc2V0O1xuICAgICAgICB9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBkLm9mZnNldCAtPSBhbmNob3I7XG4gICAgICAgIH0pO1xuXG4gICAgYWxpZ25Ib3ZlclRleHQoaG92ZXJMYWJlbCwgZnVsbE9wdHMucm90YXRlTGFiZWxzKTtcblxuICAgIHJldHVybiBtdWx0aUhvdmVyID8gaG92ZXJMYWJlbCA6IGhvdmVyTGFiZWwubm9kZSgpO1xufTtcblxuLy8gVGhlIGFjdHVhbCBpbXBsZW1lbnRhdGlvbiBpcyBoZXJlOlxuZnVuY3Rpb24gX2hvdmVyKGdkLCBldnQsIHN1YnBsb3QsIG5vSG92ZXJFdmVudCkge1xuICAgIGlmKCFzdWJwbG90KSBzdWJwbG90ID0gJ3h5JztcblxuICAgIC8vIGlmIHRoZSB1c2VyIHBhc3NlZCBpbiBhbiBhcnJheSBvZiBzdWJwbG90cyxcbiAgICAvLyB1c2UgdGhvc2UgaW5zdGVhZCBvZiBmaW5kaW5nIG92ZXJsYXllZCBwbG90c1xuICAgIHZhciBzdWJwbG90cyA9IEFycmF5LmlzQXJyYXkoc3VicGxvdCkgPyBzdWJwbG90IDogW3N1YnBsb3RdO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgcGxvdHMgPSBmdWxsTGF5b3V0Ll9wbG90cyB8fCBbXTtcbiAgICB2YXIgcGxvdGluZm8gPSBwbG90c1tzdWJwbG90XTtcbiAgICB2YXIgaGFzQ2FydGVzaWFuID0gZnVsbExheW91dC5faGFzKCdjYXJ0ZXNpYW4nKTtcblxuICAgIC8vIGxpc3Qgb2YgYWxsIG92ZXJsYWlkIHN1YnBsb3RzIHRvIGxvb2sgYXRcbiAgICBpZihwbG90aW5mbykge1xuICAgICAgICB2YXIgb3ZlcmxheWVkU3VicGxvdHMgPSBwbG90aW5mby5vdmVybGF5cy5tYXAoZnVuY3Rpb24ocGkpIHtcbiAgICAgICAgICAgIHJldHVybiBwaS5pZDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3VicGxvdHMgPSBzdWJwbG90cy5jb25jYXQob3ZlcmxheWVkU3VicGxvdHMpO1xuICAgIH1cblxuICAgIHZhciBsZW4gPSBzdWJwbG90cy5sZW5ndGg7XG4gICAgdmFyIHhhQXJyYXkgPSBuZXcgQXJyYXkobGVuKTtcbiAgICB2YXIgeWFBcnJheSA9IG5ldyBBcnJheShsZW4pO1xuICAgIHZhciBzdXBwb3J0c0NvbXBhcmUgPSBmYWxzZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgc3BJZCA9IHN1YnBsb3RzW2ldO1xuXG4gICAgICAgIC8vICdjYXJ0ZXNpYW4nIGNhc2VcbiAgICAgICAgdmFyIHBsb3RPYmogPSBwbG90c1tzcElkXTtcbiAgICAgICAgaWYocGxvdE9iaikge1xuICAgICAgICAgICAgc3VwcG9ydHNDb21wYXJlID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gVE9ETyBtYWtlIHN1cmUgdGhhdCBmdWxsTGF5b3V0X3Bsb3RzIGF4aXMgcmVmc1xuICAgICAgICAgICAgLy8gZ2V0IHVwZGF0ZWQgcHJvcGVybHkgc28gdGhhdCB3ZSBkb24ndCBoYXZlXG4gICAgICAgICAgICAvLyB0byB1c2UgQXhlcy5nZXRGcm9tSWQgaW4gZ2VuZXJhbC5cblxuICAgICAgICAgICAgeGFBcnJheVtpXSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBwbG90T2JqLnhheGlzLl9pZCk7XG4gICAgICAgICAgICB5YUFycmF5W2ldID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHBsb3RPYmoueWF4aXMuX2lkKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gb3RoZXIgc3VicGxvdCB0eXBlc1xuICAgICAgICB2YXIgX3N1YnBsb3QgPSBmdWxsTGF5b3V0W3NwSWRdLl9zdWJwbG90O1xuICAgICAgICB4YUFycmF5W2ldID0gX3N1YnBsb3QueGF4aXM7XG4gICAgICAgIHlhQXJyYXlbaV0gPSBfc3VicGxvdC55YXhpcztcbiAgICB9XG5cbiAgICB2YXIgaG92ZXJtb2RlID0gZXZ0LmhvdmVybW9kZSB8fCBmdWxsTGF5b3V0LmhvdmVybW9kZTtcblxuICAgIGlmKGhvdmVybW9kZSAmJiAhc3VwcG9ydHNDb21wYXJlKSBob3Zlcm1vZGUgPSAnY2xvc2VzdCc7XG5cbiAgICBpZihbJ3gnLCAneScsICdjbG9zZXN0J10uaW5kZXhPZihob3Zlcm1vZGUpID09PSAtMSB8fCAhZ2QuY2FsY2RhdGEgfHxcbiAgICAgICAgICAgIGdkLnF1ZXJ5U2VsZWN0b3IoJy56b29tYm94JykgfHwgZ2QuX2RyYWdnaW5nKSB7XG4gICAgICAgIHJldHVybiBkcmFnRWxlbWVudC51bmhvdmVyUmF3KGdkLCBldnQpO1xuICAgIH1cblxuICAgIHZhciBob3ZlcmRpc3RhbmNlID0gZnVsbExheW91dC5ob3ZlcmRpc3RhbmNlID09PSAtMSA/IEluZmluaXR5IDogZnVsbExheW91dC5ob3ZlcmRpc3RhbmNlO1xuICAgIHZhciBzcGlrZWRpc3RhbmNlID0gZnVsbExheW91dC5zcGlrZWRpc3RhbmNlID09PSAtMSA/IEluZmluaXR5IDogZnVsbExheW91dC5zcGlrZWRpc3RhbmNlO1xuXG4gICAgLy8gaG92ZXJEYXRhOiB0aGUgc2V0IG9mIGNhbmRpZGF0ZSBwb2ludHMgd2UndmUgZm91bmQgdG8gaGlnaGxpZ2h0XG4gICAgdmFyIGhvdmVyRGF0YSA9IFtdO1xuXG4gICAgLy8gc2VhcmNoRGF0YTogdGhlIGRhdGEgdG8gc2VhcmNoIGluLiBNb3N0bHkgdGhpcyBpcyBqdXN0IGEgY29weSBvZlxuICAgIC8vIGdkLmNhbGNkYXRhLCBmaWx0ZXJlZCB0byB0aGUgc3VicGxvdCBhbmQgb3ZlcmxheXMgd2UncmUgb25cbiAgICAvLyBidXQgaWYgYSBwb2ludCBhcnJheSBpcyBzdXBwbGllZCBpdCB3aWxsIGJlIGEgbWFwcGluZ1xuICAgIC8vIG9mIGluZGljYXRlZCBjdXJ2ZXNcbiAgICB2YXIgc2VhcmNoRGF0YSA9IFtdO1xuXG4gICAgLy8gW3h8eV12YWxBcnJheTogdGhlIGF4aXMgdmFsdWVzIG9mIHRoZSBob3ZlciBldmVudFxuICAgIC8vIG1hcHBlZCBvbnRvIGVhY2ggb2YgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBvdmVybGFpZCBzdWJwbG90c1xuICAgIHZhciB4dmFsQXJyYXksIHl2YWxBcnJheTtcblxuICAgIHZhciBpdGVtbnVtLCBjdXJ2ZW51bSwgY2QsIHRyYWNlLCBzdWJwbG90SWQsIHN1YnBsb3RpLCBtb2RlLFxuICAgICAgICB4dmFsLCB5dmFsLCBwb2ludERhdGEsIGNsb3NlZGF0YVByZXZpb3VzTGVuZ3RoO1xuXG4gICAgLy8gc3Bpa2VQb2ludHM6IHRoZSBzZXQgb2YgY2FuZGlkYXRlIHBvaW50cyB3ZSd2ZSBmb3VuZCB0byBkcmF3IHNwaWtlcyB0b1xuICAgIHZhciBzcGlrZVBvaW50cyA9IHtcbiAgICAgICAgaExpbmVQb2ludDogbnVsbCxcbiAgICAgICAgdkxpbmVQb2ludDogbnVsbFxuICAgIH07XG5cbiAgICAvLyBkb2VzIHN1YnBsb3QgaGF2ZSBvbmUgKG9yIG1vcmUpIGhvcml6b250YWwgdHJhY2VzP1xuICAgIC8vIFRoaXMgaXMgdXNlZCB0byBkZXRlcm1pbmUgd2hldGhlciB3ZSByb3RhdGUgdGhlIGxhYmVscyBvciBub3RcbiAgICB2YXIgaGFzT25lSG9yaXpvbnRhbFRyYWNlID0gZmFsc2U7XG5cbiAgICAvLyBGaWd1cmUgb3V0IHdoYXQgd2UncmUgaG92ZXJpbmcgb246XG4gICAgLy8gbW91c2UgbG9jYXRpb24gb3IgdXNlci1zdXBwbGllZCBkYXRhXG5cbiAgICBpZihBcnJheS5pc0FycmF5KGV2dCkpIHtcbiAgICAgICAgLy8gdXNlciBzcGVjaWZpZWQgYW4gYXJyYXkgb2YgcG9pbnRzIHRvIGhpZ2hsaWdodFxuICAgICAgICBob3Zlcm1vZGUgPSAnYXJyYXknO1xuICAgICAgICBmb3IoaXRlbW51bSA9IDA7IGl0ZW1udW0gPCBldnQubGVuZ3RoOyBpdGVtbnVtKyspIHtcbiAgICAgICAgICAgIGNkID0gZ2QuY2FsY2RhdGFbZXZ0W2l0ZW1udW1dLmN1cnZlTnVtYmVyIHx8IDBdO1xuICAgICAgICAgICAgaWYoY2QpIHtcbiAgICAgICAgICAgICAgICB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgICAgICAgICAgICAgIGlmKGNkWzBdLnRyYWNlLmhvdmVyaW5mbyAhPT0gJ3NraXAnKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlYXJjaERhdGEucHVzaChjZCk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc09uZUhvcml6b250YWxUcmFjZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBmb3IoY3VydmVudW0gPSAwOyBjdXJ2ZW51bSA8IGdkLmNhbGNkYXRhLmxlbmd0aDsgY3VydmVudW0rKykge1xuICAgICAgICAgICAgY2QgPSBnZC5jYWxjZGF0YVtjdXJ2ZW51bV07XG4gICAgICAgICAgICB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgICAgICAgICAgaWYodHJhY2UuaG92ZXJpbmZvICE9PSAnc2tpcCcgJiYgaGVscGVycy5pc1RyYWNlSW5TdWJwbG90cyh0cmFjZSwgc3VicGxvdHMpKSB7XG4gICAgICAgICAgICAgICAgc2VhcmNoRGF0YS5wdXNoKGNkKTtcbiAgICAgICAgICAgICAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc09uZUhvcml6b250YWxUcmFjZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gW3h8eV1weDogdGhlIHBpeGVscyAoZnJvbSB0b3AgbGVmdCkgb2YgdGhlIG1vdXNlIGxvY2F0aW9uXG4gICAgICAgIC8vIG9uIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgcGxvdCBhcmVhXG4gICAgICAgIC8vIGFkZCBwb2ludGVyWHxZIHByb3BlcnR5IGZvciBkcmF3aW5nIHRoZSBzcGlrZXMgaW4gc3Bpa2VzbmFwICdjdXJzb3InIHNpdHVhdGlvblxuICAgICAgICB2YXIgaGFzVXNlckNhbGxlZEhvdmVyID0gIWV2dC50YXJnZXQ7XG4gICAgICAgIHZhciB4cHgsIHlweDtcblxuICAgICAgICBpZihoYXNVc2VyQ2FsbGVkSG92ZXIpIHtcbiAgICAgICAgICAgIGlmKCd4cHgnIGluIGV2dCkgeHB4ID0gZXZ0LnhweDtcbiAgICAgICAgICAgIGVsc2UgeHB4ID0geGFBcnJheVswXS5fbGVuZ3RoIC8gMjtcblxuICAgICAgICAgICAgaWYoJ3lweCcgaW4gZXZ0KSB5cHggPSBldnQueXB4O1xuICAgICAgICAgICAgZWxzZSB5cHggPSB5YUFycmF5WzBdLl9sZW5ndGggLyAyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZmlyZSB0aGUgYmVmb3JlaG92ZXIgZXZlbnQgYW5kIHF1aXQgaWYgaXQgcmV0dXJucyBmYWxzZVxuICAgICAgICAgICAgLy8gbm90ZSB0aGF0IHdlJ3JlIG9ubHkgY2FsbGluZyB0aGlzIG9uIHJlYWwgbW91c2UgZXZlbnRzLCBzb1xuICAgICAgICAgICAgLy8gbWFudWFsIGNhbGxzIHRvIGZ4LmhvdmVyIHdpbGwgYWx3YXlzIHJ1bi5cbiAgICAgICAgICAgIGlmKEV2ZW50cy50cmlnZ2VySGFuZGxlcihnZCwgJ3Bsb3RseV9iZWZvcmVob3ZlcicsIGV2dCkgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZGJiID0gZXZ0LnRhcmdldC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgICAgICAgeHB4ID0gZXZ0LmNsaWVudFggLSBkYmIubGVmdDtcbiAgICAgICAgICAgIHlweCA9IGV2dC5jbGllbnRZIC0gZGJiLnRvcDtcblxuICAgICAgICAgICAgLy8gaW4gY2FzZSBob3ZlciB3YXMgY2FsbGVkIGZyb20gbW91c2VvdXQgaW50byBob3ZlcnRleHQsXG4gICAgICAgICAgICAvLyBpdCdzIHBvc3NpYmxlIHlvdSdyZSBub3QgYWN0dWFsbHkgb3ZlciB0aGUgcGxvdCBhbnltb3JlXG4gICAgICAgICAgICBpZih4cHggPCAwIHx8IHhweCA+IHhhQXJyYXlbMF0uX2xlbmd0aCB8fCB5cHggPCAwIHx8IHlweCA+IHlhQXJyYXlbMF0uX2xlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkcmFnRWxlbWVudC51bmhvdmVyUmF3KGdkLCBldnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZXZ0LnBvaW50ZXJYID0geHB4ICsgeGFBcnJheVswXS5fb2Zmc2V0O1xuICAgICAgICBldnQucG9pbnRlclkgPSB5cHggKyB5YUFycmF5WzBdLl9vZmZzZXQ7XG5cbiAgICAgICAgaWYoJ3h2YWwnIGluIGV2dCkgeHZhbEFycmF5ID0gaGVscGVycy5mbGF0KHN1YnBsb3RzLCBldnQueHZhbCk7XG4gICAgICAgIGVsc2UgeHZhbEFycmF5ID0gaGVscGVycy5wMmMoeGFBcnJheSwgeHB4KTtcblxuICAgICAgICBpZigneXZhbCcgaW4gZXZ0KSB5dmFsQXJyYXkgPSBoZWxwZXJzLmZsYXQoc3VicGxvdHMsIGV2dC55dmFsKTtcbiAgICAgICAgZWxzZSB5dmFsQXJyYXkgPSBoZWxwZXJzLnAyYyh5YUFycmF5LCB5cHgpO1xuXG4gICAgICAgIGlmKCFpc051bWVyaWMoeHZhbEFycmF5WzBdKSB8fCAhaXNOdW1lcmljKHl2YWxBcnJheVswXSkpIHtcbiAgICAgICAgICAgIExpYi53YXJuKCdGeC5ob3ZlciBmYWlsZWQnLCBldnQsIGdkKTtcbiAgICAgICAgICAgIHJldHVybiBkcmFnRWxlbWVudC51bmhvdmVyUmF3KGdkLCBldnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGhlIHBpeGVsIGRpc3RhbmNlIHRvIGJlYXQgYXMgYSBtYXRjaGluZyBwb2ludFxuICAgIC8vIGluICd4JyBvciAneScgbW9kZSB0aGlzIHJlc2V0cyBmb3IgZWFjaCB0cmFjZVxuICAgIHZhciBkaXN0YW5jZSA9IEluZmluaXR5O1xuXG4gICAgLy8gZmluZCB0aGUgY2xvc2VzdCBwb2ludCBpbiBlYWNoIHRyYWNlXG4gICAgLy8gdGhpcyBpcyBtaW5pbXVtIGR4IGFuZC9vciBkeSwgZGVwZW5kaW5nIG9uIG1vZGVcbiAgICAvLyBhbmQgdGhlIHBpeGVsIHBvc2l0aW9uIGZvciB0aGUgbGFiZWwgKGxhYmVsWHB4LCBsYWJlbFlweClcbiAgICBmb3IoY3VydmVudW0gPSAwOyBjdXJ2ZW51bSA8IHNlYXJjaERhdGEubGVuZ3RoOyBjdXJ2ZW51bSsrKSB7XG4gICAgICAgIGNkID0gc2VhcmNoRGF0YVtjdXJ2ZW51bV07XG5cbiAgICAgICAgLy8gZmlsdGVyIG91dCBpbnZpc2libGUgb3IgYnJva2VuIGRhdGFcbiAgICAgICAgaWYoIWNkIHx8ICFjZFswXSB8fCAhY2RbMF0udHJhY2UpIGNvbnRpbnVlO1xuXG4gICAgICAgIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSAhPT0gdHJ1ZSB8fCB0cmFjZS5fbGVuZ3RoID09PSAwKSBjb250aW51ZTtcblxuICAgICAgICAvLyBFeHBsaWNpdGx5IGJhaWwgb3V0IGZvciB0aGVzZSB0d28uIEkgZG9uJ3Qga25vdyBob3cgdG8gb3RoZXJ3aXNlIHByZXZlbnRcbiAgICAgICAgLy8gdGhlIHJlc3Qgb2YgdGhpcyBmdW5jdGlvbiBmcm9tIHJ1bm5pbmcgYW5kIGZhaWxpbmdcbiAgICAgICAgaWYoWydjYXJwZXQnLCAnY29udG91cmNhcnBldCddLmluZGV4T2YodHJhY2UuX21vZHVsZS5uYW1lKSAhPT0gLTEpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdzcGxvbScpIHtcbiAgICAgICAgICAgIC8vIHNwbG9tIHRyYWNlcyBkbyBub3QgZ2VuZXJhdGUgb3ZlcmxheSBzdWJwbG90cyxcbiAgICAgICAgICAgIC8vIGl0IGlzIHNhZmUgdG8gYXNzdW1lIGhlcmUgc3Bsb20gdHJhY2VzIGNvcnJlc3BvbmQgdG8gdGhlIDB0aCBzdWJwbG90XG4gICAgICAgICAgICBzdWJwbG90aSA9IDA7XG4gICAgICAgICAgICBzdWJwbG90SWQgPSBzdWJwbG90c1tzdWJwbG90aV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdWJwbG90SWQgPSBoZWxwZXJzLmdldFN1YnBsb3QodHJhY2UpO1xuICAgICAgICAgICAgc3VicGxvdGkgPSBzdWJwbG90cy5pbmRleE9mKHN1YnBsb3RJZCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB3aXRoaW4gb25lIHRyYWNlIG1vZGUgY2FuIHNvbWV0aW1lcyBiZSBvdmVycmlkZGVuXG4gICAgICAgIG1vZGUgPSBob3Zlcm1vZGU7XG5cbiAgICAgICAgLy8gY29udGFpbmVyIGZvciBuZXcgcG9pbnQsIGFsc28gdXNlZCB0byBwYXNzIGluZm8gaW50byBtb2R1bGUuaG92ZXJQb2ludHNcbiAgICAgICAgcG9pbnREYXRhID0ge1xuICAgICAgICAgICAgLy8gdHJhY2UgcHJvcGVydGllc1xuICAgICAgICAgICAgY2Q6IGNkLFxuICAgICAgICAgICAgdHJhY2U6IHRyYWNlLFxuICAgICAgICAgICAgeGE6IHhhQXJyYXlbc3VicGxvdGldLFxuICAgICAgICAgICAgeWE6IHlhQXJyYXlbc3VicGxvdGldLFxuXG4gICAgICAgICAgICAvLyBtYXggZGlzdGFuY2VzIGZvciBob3ZlciBhbmQgc3Bpa2VzIC0gZm9yIHBvaW50cyB0aGF0IHdhbnQgdG8gc2hvdyBidXQgZG8gbm90XG4gICAgICAgICAgICAvLyB3YW50IHRvIG92ZXJyaWRlIG90aGVyIHBvaW50cywgc2V0IGRpc3RhbmNlL3NwaWtlRGlzdGFuY2UgZXF1YWwgdG8gbWF4KkRpc3RhbmNlXG4gICAgICAgICAgICAvLyBhbmQgaXQgd2lsbCBub3QgZ2V0IGZpbHRlcmVkIG91dCBidXQgaXQgd2lsbCBiZSBndWFyYW50ZWVkIHRvIGhhdmUgYSBncmVhdGVyXG4gICAgICAgICAgICAvLyBkaXN0YW5jZSB0aGFuIGFueSBwb2ludCB0aGF0IGNhbGN1bGF0ZWQgYSByZWFsIGRpc3RhbmNlLlxuICAgICAgICAgICAgbWF4SG92ZXJEaXN0YW5jZTogaG92ZXJkaXN0YW5jZSxcbiAgICAgICAgICAgIG1heFNwaWtlRGlzdGFuY2U6IHNwaWtlZGlzdGFuY2UsXG5cbiAgICAgICAgICAgIC8vIHBvaW50IHByb3BlcnRpZXMgLSBvdmVycmlkZSBhbGwgb2YgdGhlc2VcbiAgICAgICAgICAgIGluZGV4OiBmYWxzZSwgLy8gcG9pbnQgaW5kZXggaW4gdHJhY2UgLSBvbmx5IHVzZWQgYnkgcGxvdGx5LmpzIGhvdmVyZGF0YSBjb25zdW1lcnNcbiAgICAgICAgICAgIGRpc3RhbmNlOiBNYXRoLm1pbihkaXN0YW5jZSwgaG92ZXJkaXN0YW5jZSksIC8vIHBpeGVsIGRpc3RhbmNlIG9yIHBzZXVkby1kaXN0YW5jZVxuXG4gICAgICAgICAgICAvLyBkaXN0YW5jZS9wc2V1ZG8tZGlzdGFuY2UgZm9yIHNwaWtlcy4gVGhpcyBkaXN0YW5jZSBzaG91bGQgYWx3YXlzIGJlIGNhbGN1bGF0ZWRcbiAgICAgICAgICAgIC8vIGFzIGlmIGluIFwiY2xvc2VzdFwiIG1vZGUsIGFuZCBzaG91bGQgb25seSBiZSBzZXQgaWYgdGhpcyBwb2ludCBzaG91bGRcbiAgICAgICAgICAgIC8vIGdlbmVyYXRlIGEgc3Bpa2UuXG4gICAgICAgICAgICBzcGlrZURpc3RhbmNlOiBJbmZpbml0eSxcblxuICAgICAgICAgICAgLy8gaW4gc29tZSBjYXNlcyB0aGUgc3Bpa2VzIGhhdmUgZGlmZmVyZW50IHBvc2l0aW9uaW5nIGZyb20gdGhlIGhvdmVyIGxhYmVsXG4gICAgICAgICAgICAvLyB0aGV5IGRvbid0IG5lZWQgeDAveDEsIGp1c3Qgb25lIHBvc2l0aW9uXG4gICAgICAgICAgICB4U3Bpa2U6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHlTcGlrZTogdW5kZWZpbmVkLFxuXG4gICAgICAgICAgICAvLyB3aGVyZSBhbmQgaG93IHRvIGRpc3BsYXkgdGhlIGhvdmVyIGxhYmVsXG4gICAgICAgICAgICBjb2xvcjogQ29sb3IuZGVmYXVsdExpbmUsIC8vIHRyYWNlIGNvbG9yXG4gICAgICAgICAgICBuYW1lOiB0cmFjZS5uYW1lLFxuICAgICAgICAgICAgeDA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHgxOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB5MDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgeTE6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHhMYWJlbFZhbDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgeUxhYmVsVmFsOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB6TGFiZWxWYWw6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHRleHQ6IHVuZGVmaW5lZFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIGFkZCByZWYgdG8gc3VicGxvdCBvYmplY3QgKG5vbi1jYXJ0ZXNpYW4gY2FzZSlcbiAgICAgICAgaWYoZnVsbExheW91dFtzdWJwbG90SWRdKSB7XG4gICAgICAgICAgICBwb2ludERhdGEuc3VicGxvdCA9IGZ1bGxMYXlvdXRbc3VicGxvdElkXS5fc3VicGxvdDtcbiAgICAgICAgfVxuICAgICAgICAvLyBhZGQgcmVmIHRvIHNwbG9tIHNjZW5lXG4gICAgICAgIGlmKGZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzICYmIGZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzW3RyYWNlLnVpZF0pIHtcbiAgICAgICAgICAgIHBvaW50RGF0YS5zY2VuZSA9IGZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzW3RyYWNlLnVpZF07XG4gICAgICAgIH1cblxuICAgICAgICBjbG9zZWRhdGFQcmV2aW91c0xlbmd0aCA9IGhvdmVyRGF0YS5sZW5ndGg7XG5cbiAgICAgICAgLy8gZm9yIGEgaGlnaGxpZ2h0aW5nIGFycmF5LCBmaWd1cmUgb3V0IHdoYXRcbiAgICAgICAgLy8gd2UncmUgc2VhcmNoaW5nIGZvciB3aXRoIHRoaXMgZWxlbWVudFxuICAgICAgICBpZihtb2RlID09PSAnYXJyYXknKSB7XG4gICAgICAgICAgICB2YXIgc2VsZWN0aW9uID0gZXZ0W2N1cnZlbnVtXTtcbiAgICAgICAgICAgIGlmKCdwb2ludE51bWJlcicgaW4gc2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgcG9pbnREYXRhLmluZGV4ID0gc2VsZWN0aW9uLnBvaW50TnVtYmVyO1xuICAgICAgICAgICAgICAgIG1vZGUgPSAnY2xvc2VzdCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vZGUgPSAnJztcbiAgICAgICAgICAgICAgICBpZigneHZhbCcgaW4gc2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHh2YWwgPSBzZWxlY3Rpb24ueHZhbDtcbiAgICAgICAgICAgICAgICAgICAgbW9kZSA9ICd4JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYoJ3l2YWwnIGluIHNlbGVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICB5dmFsID0gc2VsZWN0aW9uLnl2YWw7XG4gICAgICAgICAgICAgICAgICAgIG1vZGUgPSBtb2RlID8gJ2Nsb3Nlc3QnIDogJ3knO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHh2YWwgPSB4dmFsQXJyYXlbc3VicGxvdGldO1xuICAgICAgICAgICAgeXZhbCA9IHl2YWxBcnJheVtzdWJwbG90aV07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBOb3cgaWYgdGhlcmUgaXMgcmFuZ2UgdG8gbG9vayBpbiwgZmluZCB0aGUgcG9pbnRzIHRvIGhvdmVyLlxuICAgICAgICBpZihob3ZlcmRpc3RhbmNlICE9PSAwKSB7XG4gICAgICAgICAgICBpZih0cmFjZS5fbW9kdWxlICYmIHRyYWNlLl9tb2R1bGUuaG92ZXJQb2ludHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3UG9pbnRzID0gdHJhY2UuX21vZHVsZS5ob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIG1vZGUsIGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIpO1xuICAgICAgICAgICAgICAgIGlmKG5ld1BvaW50cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3UG9pbnQ7XG4gICAgICAgICAgICAgICAgICAgIGZvcih2YXIgbmV3UG9pbnROdW0gPSAwOyBuZXdQb2ludE51bSA8IG5ld1BvaW50cy5sZW5ndGg7IG5ld1BvaW50TnVtKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1BvaW50ID0gbmV3UG9pbnRzW25ld1BvaW50TnVtXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhuZXdQb2ludC54MCkgJiYgaXNOdW1lcmljKG5ld1BvaW50LnkwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvdmVyRGF0YS5wdXNoKGNsZWFuUG9pbnQobmV3UG9pbnQsIGhvdmVybW9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMaWIubG9nKCdVbnJlY29nbml6ZWQgdHJhY2UgdHlwZSBpbiBob3ZlcjonLCB0cmFjZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpbiBjbG9zZXN0IG1vZGUsIHJlbW92ZSBhbnkgZXhpc3RpbmcgKGZhcnRoZXIpIHBvaW50c1xuICAgICAgICAvLyBhbmQgZG9uJ3QgbG9vayBhbnkgZmFydGhlciB0aGFuIHRoaXMgbGF0ZXN0IHBvaW50IChvciBwb2ludHMsIHNvbWVcbiAgICAgICAgLy8gdHJhY2VzIGxpa2UgYm94ICYgdmlvbGluIG1ha2UgbXVsdGlwbGUgaG92ZXIgbGFiZWxzIGF0IG9uY2UpXG4gICAgICAgIGlmKGhvdmVybW9kZSA9PT0gJ2Nsb3Nlc3QnICYmIGhvdmVyRGF0YS5sZW5ndGggPiBjbG9zZWRhdGFQcmV2aW91c0xlbmd0aCkge1xuICAgICAgICAgICAgaG92ZXJEYXRhLnNwbGljZSgwLCBjbG9zZWRhdGFQcmV2aW91c0xlbmd0aCk7XG4gICAgICAgICAgICBkaXN0YW5jZSA9IGhvdmVyRGF0YVswXS5kaXN0YW5jZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5vdyBpZiB0aGVyZSBpcyByYW5nZSB0byBsb29rIGluLCBmaW5kIHRoZSBwb2ludHMgdG8gZHJhdyB0aGUgc3Bpa2VsaW5lc1xuICAgICAgICAvLyBEbyBpdCBvbmx5IGlmIHRoZXJlIGlzIG5vIGhvdmVyRGF0YVxuICAgICAgICBpZihoYXNDYXJ0ZXNpYW4gJiYgKHNwaWtlZGlzdGFuY2UgIT09IDApKSB7XG4gICAgICAgICAgICBpZihob3ZlckRhdGEubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcG9pbnREYXRhLmRpc3RhbmNlID0gc3Bpa2VkaXN0YW5jZTtcbiAgICAgICAgICAgICAgICBwb2ludERhdGEuaW5kZXggPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgY2xvc2VzdFBvaW50cyA9IHRyYWNlLl9tb2R1bGUuaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCAnY2xvc2VzdCcsIGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIpO1xuICAgICAgICAgICAgICAgIGlmKGNsb3Nlc3RQb2ludHMpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xvc2VzdFBvaW50cyA9IGNsb3Nlc3RQb2ludHMuZmlsdGVyKGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzb21lIGhvdmVyIHBvaW50cywgbGlrZSBzY2F0dGVyIGZpbGxzLCBkbyBub3QgYWxsb3cgc3Bpa2VzLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc28gd2lsbCBnZW5lcmF0ZSBhIGhvdmVyIHBvaW50IGJ1dCB3aXRob3V0IGEgdmFsaWQgc3Bpa2VEaXN0YW5jZVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50LnNwaWtlRGlzdGFuY2UgPD0gc3Bpa2VkaXN0YW5jZTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKGNsb3Nlc3RQb2ludHMgJiYgY2xvc2VzdFBvaW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRtcFBvaW50O1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2xvc2VzdFZQb2ludHMgPSBjbG9zZXN0UG9pbnRzLmZpbHRlcihmdW5jdGlvbihwb2ludCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50LnhhLnNob3dzcGlrZXM7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZihjbG9zZXN0VlBvaW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjbG9zZXN0VlB0ID0gY2xvc2VzdFZQb2ludHNbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihpc051bWVyaWMoY2xvc2VzdFZQdC54MCkgJiYgaXNOdW1lcmljKGNsb3Nlc3RWUHQueTApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wUG9pbnQgPSBmaWxsU3Bpa2VQb2ludChjbG9zZXN0VlB0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZighc3Bpa2VQb2ludHMudkxpbmVQb2ludCB8fCAoc3Bpa2VQb2ludHMudkxpbmVQb2ludC5zcGlrZURpc3RhbmNlID4gdG1wUG9pbnQuc3Bpa2VEaXN0YW5jZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Bpa2VQb2ludHMudkxpbmVQb2ludCA9IHRtcFBvaW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBjbG9zZXN0SFBvaW50cyA9IGNsb3Nlc3RQb2ludHMuZmlsdGVyKGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcG9pbnQueWEuc2hvd3NwaWtlcztcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGNsb3Nlc3RIUG9pbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNsb3Nlc3RIUHQgPSBjbG9zZXN0SFBvaW50c1swXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhjbG9zZXN0SFB0LngwKSAmJiBpc051bWVyaWMoY2xvc2VzdEhQdC55MCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXBQb2ludCA9IGZpbGxTcGlrZVBvaW50KGNsb3Nlc3RIUHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKCFzcGlrZVBvaW50cy5oTGluZVBvaW50IHx8IChzcGlrZVBvaW50cy5oTGluZVBvaW50LnNwaWtlRGlzdGFuY2UgPiB0bXBQb2ludC5zcGlrZURpc3RhbmNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGlrZVBvaW50cy5oTGluZVBvaW50ID0gdG1wUG9pbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2VsZWN0Q2xvc2VzdFBvaW50KHBvaW50c0RhdGEsIHNwaWtlZGlzdGFuY2UpIHtcbiAgICAgICAgdmFyIHJlc3VsdFBvaW50ID0gbnVsbDtcbiAgICAgICAgdmFyIG1pbkRpc3RhbmNlID0gSW5maW5pdHk7XG4gICAgICAgIHZhciB0aGlzU3Bpa2VEaXN0YW5jZTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHBvaW50c0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXNTcGlrZURpc3RhbmNlID0gcG9pbnRzRGF0YVtpXS5zcGlrZURpc3RhbmNlO1xuICAgICAgICAgICAgaWYodGhpc1NwaWtlRGlzdGFuY2UgPCBtaW5EaXN0YW5jZSAmJiB0aGlzU3Bpa2VEaXN0YW5jZSA8PSBzcGlrZWRpc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0UG9pbnQgPSBwb2ludHNEYXRhW2ldO1xuICAgICAgICAgICAgICAgIG1pbkRpc3RhbmNlID0gdGhpc1NwaWtlRGlzdGFuY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdFBvaW50O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpbGxTcGlrZVBvaW50KHBvaW50KSB7XG4gICAgICAgIGlmKCFwb2ludCkgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4YTogcG9pbnQueGEsXG4gICAgICAgICAgICB5YTogcG9pbnQueWEsXG4gICAgICAgICAgICB4OiBwb2ludC54U3Bpa2UgIT09IHVuZGVmaW5lZCA/IHBvaW50LnhTcGlrZSA6IChwb2ludC54MCArIHBvaW50LngxKSAvIDIsXG4gICAgICAgICAgICB5OiBwb2ludC55U3Bpa2UgIT09IHVuZGVmaW5lZCA/IHBvaW50LnlTcGlrZSA6IChwb2ludC55MCArIHBvaW50LnkxKSAvIDIsXG4gICAgICAgICAgICBkaXN0YW5jZTogcG9pbnQuZGlzdGFuY2UsXG4gICAgICAgICAgICBzcGlrZURpc3RhbmNlOiBwb2ludC5zcGlrZURpc3RhbmNlLFxuICAgICAgICAgICAgY3VydmVOdW1iZXI6IHBvaW50LnRyYWNlLmluZGV4LFxuICAgICAgICAgICAgY29sb3I6IHBvaW50LmNvbG9yLFxuICAgICAgICAgICAgcG9pbnROdW1iZXI6IHBvaW50LmluZGV4XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIHNwaWtlbGluZU9wdHMgPSB7XG4gICAgICAgIGZ1bGxMYXlvdXQ6IGZ1bGxMYXlvdXQsXG4gICAgICAgIGNvbnRhaW5lcjogZnVsbExheW91dC5faG92ZXJsYXllcixcbiAgICAgICAgb3V0ZXJDb250YWluZXI6IGZ1bGxMYXlvdXQuX3BhcGVyZGl2LFxuICAgICAgICBldmVudDogZXZ0XG4gICAgfTtcbiAgICB2YXIgb2xkc3Bpa2Vwb2ludHMgPSBnZC5fc3Bpa2Vwb2ludHM7XG4gICAgdmFyIG5ld3NwaWtlcG9pbnRzID0ge1xuICAgICAgICB2TGluZVBvaW50OiBzcGlrZVBvaW50cy52TGluZVBvaW50LFxuICAgICAgICBoTGluZVBvaW50OiBzcGlrZVBvaW50cy5oTGluZVBvaW50XG4gICAgfTtcbiAgICBnZC5fc3Bpa2Vwb2ludHMgPSBuZXdzcGlrZXBvaW50cztcblxuICAgIC8vIE5vdyBpZiBpdCBpcyBub3QgcmVzdHJpY3RlZCBieSBzcGlrZWRpc3RhbmNlIG9wdGlvbiwgc2V0IHRoZSBwb2ludHMgdG8gZHJhdyB0aGUgc3Bpa2VsaW5lc1xuICAgIGlmKGhhc0NhcnRlc2lhbiAmJiAoc3Bpa2VkaXN0YW5jZSAhPT0gMCkpIHtcbiAgICAgICAgaWYoaG92ZXJEYXRhLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgICAgdmFyIHRtcEhQb2ludERhdGEgPSBob3ZlckRhdGEuZmlsdGVyKGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50LnlhLnNob3dzcGlrZXM7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciB0bXBIUG9pbnQgPSBzZWxlY3RDbG9zZXN0UG9pbnQodG1wSFBvaW50RGF0YSwgc3Bpa2VkaXN0YW5jZSk7XG4gICAgICAgICAgICBzcGlrZVBvaW50cy5oTGluZVBvaW50ID0gZmlsbFNwaWtlUG9pbnQodG1wSFBvaW50KTtcblxuICAgICAgICAgICAgdmFyIHRtcFZQb2ludERhdGEgPSBob3ZlckRhdGEuZmlsdGVyKGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50LnhhLnNob3dzcGlrZXM7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciB0bXBWUG9pbnQgPSBzZWxlY3RDbG9zZXN0UG9pbnQodG1wVlBvaW50RGF0YSwgc3Bpa2VkaXN0YW5jZSk7XG4gICAgICAgICAgICBzcGlrZVBvaW50cy52TGluZVBvaW50ID0gZmlsbFNwaWtlUG9pbnQodG1wVlBvaW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGlmIGhvdmVyRGF0YSBpcyBlbXB0eSBjaGVjayBmb3IgdGhlIHNwaWtlcyB0byBkcmF3IGFuZCBxdWl0IGlmIHRoZXJlIGFyZSBub25lXG4gICAgaWYoaG92ZXJEYXRhLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gZHJhZ0VsZW1lbnQudW5ob3ZlclJhdyhnZCwgZXZ0KTtcbiAgICAgICAgaWYoaGFzQ2FydGVzaWFuICYmICgoc3Bpa2VQb2ludHMuaExpbmVQb2ludCAhPT0gbnVsbCkgfHwgKHNwaWtlUG9pbnRzLnZMaW5lUG9pbnQgIT09IG51bGwpKSkge1xuICAgICAgICAgICAgaWYoc3Bpa2VzQ2hhbmdlZChvbGRzcGlrZXBvaW50cykpIHtcbiAgICAgICAgICAgICAgICBjcmVhdGVTcGlrZWxpbmVzKHNwaWtlUG9pbnRzLCBzcGlrZWxpbmVPcHRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGlmKGhhc0NhcnRlc2lhbikge1xuICAgICAgICBpZihzcGlrZXNDaGFuZ2VkKG9sZHNwaWtlcG9pbnRzKSkge1xuICAgICAgICAgICAgY3JlYXRlU3Bpa2VsaW5lcyhzcGlrZVBvaW50cywgc3Bpa2VsaW5lT3B0cyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBob3ZlckRhdGEuc29ydChmdW5jdGlvbihkMSwgZDIpIHsgcmV0dXJuIGQxLmRpc3RhbmNlIC0gZDIuZGlzdGFuY2U7IH0pO1xuXG4gICAgLy8gbGFzdGx5LCBlbWl0IGN1c3RvbSBob3Zlci91bmhvdmVyIGV2ZW50c1xuICAgIHZhciBvbGRob3ZlcmRhdGEgPSBnZC5faG92ZXJkYXRhO1xuICAgIHZhciBuZXdob3ZlcmRhdGEgPSBbXTtcblxuICAgIC8vIHB1bGwgb3V0IGp1c3QgdGhlIGRhdGEgdGhhdCdzIHVzZWZ1bCB0b1xuICAgIC8vIG90aGVyIHBlb3BsZSBhbmQgc2VuZCBpdCB0byB0aGUgZXZlbnRcbiAgICBmb3IoaXRlbW51bSA9IDA7IGl0ZW1udW0gPCBob3ZlckRhdGEubGVuZ3RoOyBpdGVtbnVtKyspIHtcbiAgICAgICAgdmFyIHB0ID0gaG92ZXJEYXRhW2l0ZW1udW1dO1xuICAgICAgICB2YXIgZXZlbnREYXRhID0gaGVscGVycy5tYWtlRXZlbnREYXRhKHB0LCBwdC50cmFjZSwgcHQuY2QpO1xuXG4gICAgICAgIGlmKHB0LmhvdmVydGVtcGxhdGUgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICB2YXIgaHQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmKHB0LmNkW3B0LmluZGV4XSAmJiBwdC5jZFtwdC5pbmRleF0uaHQpIHtcbiAgICAgICAgICAgICAgICBodCA9IHB0LmNkW3B0LmluZGV4XS5odDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHB0LmhvdmVydGVtcGxhdGUgPSBodCB8fCBwdC50cmFjZS5ob3ZlcnRlbXBsYXRlIHx8IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcHQuZXZlbnREYXRhID0gW2V2ZW50RGF0YV07XG4gICAgICAgIG5ld2hvdmVyZGF0YS5wdXNoKGV2ZW50RGF0YSk7XG4gICAgfVxuXG4gICAgZ2QuX2hvdmVyZGF0YSA9IG5ld2hvdmVyZGF0YTtcblxuICAgIHZhciByb3RhdGVMYWJlbHMgPSAoXG4gICAgICAgIChob3Zlcm1vZGUgPT09ICd5JyAmJiAoc2VhcmNoRGF0YS5sZW5ndGggPiAxIHx8IGhvdmVyRGF0YS5sZW5ndGggPiAxKSkgfHxcbiAgICAgICAgKGhvdmVybW9kZSA9PT0gJ2Nsb3Nlc3QnICYmIGhhc09uZUhvcml6b250YWxUcmFjZSAmJiBob3ZlckRhdGEubGVuZ3RoID4gMSlcbiAgICApO1xuXG4gICAgdmFyIGJnQ29sb3IgPSBDb2xvci5jb21iaW5lKFxuICAgICAgICBmdWxsTGF5b3V0LnBsb3RfYmdjb2xvciB8fCBDb2xvci5iYWNrZ3JvdW5kLFxuICAgICAgICBmdWxsTGF5b3V0LnBhcGVyX2JnY29sb3JcbiAgICApO1xuXG4gICAgdmFyIGxhYmVsT3B0cyA9IHtcbiAgICAgICAgaG92ZXJtb2RlOiBob3Zlcm1vZGUsXG4gICAgICAgIHJvdGF0ZUxhYmVsczogcm90YXRlTGFiZWxzLFxuICAgICAgICBiZ0NvbG9yOiBiZ0NvbG9yLFxuICAgICAgICBjb250YWluZXI6IGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIsXG4gICAgICAgIG91dGVyQ29udGFpbmVyOiBmdWxsTGF5b3V0Ll9wYXBlcmRpdixcbiAgICAgICAgY29tbW9uTGFiZWxPcHRzOiBmdWxsTGF5b3V0LmhvdmVybGFiZWwsXG4gICAgICAgIGhvdmVyZGlzdGFuY2U6IGZ1bGxMYXlvdXQuaG92ZXJkaXN0YW5jZVxuICAgIH07XG5cbiAgICB2YXIgaG92ZXJMYWJlbHMgPSBjcmVhdGVIb3ZlclRleHQoaG92ZXJEYXRhLCBsYWJlbE9wdHMsIGdkKTtcblxuICAgIGhvdmVyQXZvaWRPdmVybGFwcyhob3ZlckxhYmVscywgcm90YXRlTGFiZWxzID8gJ3hhJyA6ICd5YScsIGZ1bGxMYXlvdXQpO1xuXG4gICAgYWxpZ25Ib3ZlclRleHQoaG92ZXJMYWJlbHMsIHJvdGF0ZUxhYmVscyk7XG5cbiAgICAvLyBUT0RPOiB0YWdOYW1lIGhhY2sgaXMgbmVlZGVkIHRvIGFwcGVhc2UgZ2VvLmpzJ3MgaGFjayBvZiB1c2luZyBldnQudGFyZ2V0PXRydWVcbiAgICAvLyB3ZSBzaG91bGQgaW1wcm92ZSB0aGUgXCJmeFwiIEFQSSBzbyBvdGhlciBwbG90cyBjYW4gdXNlIGl0IHdpdGhvdXQgdGhlc2UgaGFjay5cbiAgICBpZihldnQudGFyZ2V0ICYmIGV2dC50YXJnZXQudGFnTmFtZSkge1xuICAgICAgICB2YXIgaGFzQ2xpY2tUb1Nob3cgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Fubm90YXRpb25zJywgJ2hhc0NsaWNrVG9TaG93JykoZ2QsIG5ld2hvdmVyZGF0YSk7XG4gICAgICAgIG92ZXJyaWRlQ3Vyc29yKGQzLnNlbGVjdChldnQudGFyZ2V0KSwgaGFzQ2xpY2tUb1Nob3cgPyAncG9pbnRlcicgOiAnJyk7XG4gICAgfVxuXG4gICAgLy8gZG9uJ3QgZW1pdCBldmVudHMgaWYgY2FsbGVkIG1hbnVhbGx5XG4gICAgaWYoIWV2dC50YXJnZXQgfHwgbm9Ib3ZlckV2ZW50IHx8ICFob3ZlckNoYW5nZWQoZ2QsIGV2dCwgb2xkaG92ZXJkYXRhKSkgcmV0dXJuO1xuXG4gICAgaWYob2xkaG92ZXJkYXRhKSB7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV91bmhvdmVyJywge1xuICAgICAgICAgICAgZXZlbnQ6IGV2dCxcbiAgICAgICAgICAgIHBvaW50czogb2xkaG92ZXJkYXRhXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGdkLmVtaXQoJ3Bsb3RseV9ob3ZlcicsIHtcbiAgICAgICAgZXZlbnQ6IGV2dCxcbiAgICAgICAgcG9pbnRzOiBnZC5faG92ZXJkYXRhLFxuICAgICAgICB4YXhlczogeGFBcnJheSxcbiAgICAgICAgeWF4ZXM6IHlhQXJyYXksXG4gICAgICAgIHh2YWxzOiB4dmFsQXJyYXksXG4gICAgICAgIHl2YWxzOiB5dmFsQXJyYXlcbiAgICB9KTtcbn1cblxudmFyIEVYVFJBX1NUUklOR19SRUdFWCA9IC88ZXh0cmE+KFtcXHNcXFNdKik8XFwvZXh0cmE+LztcblxuZnVuY3Rpb24gY3JlYXRlSG92ZXJUZXh0KGhvdmVyRGF0YSwgb3B0cywgZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBob3Zlcm1vZGUgPSBvcHRzLmhvdmVybW9kZTtcbiAgICB2YXIgcm90YXRlTGFiZWxzID0gb3B0cy5yb3RhdGVMYWJlbHM7XG4gICAgdmFyIGJnQ29sb3IgPSBvcHRzLmJnQ29sb3I7XG4gICAgdmFyIGNvbnRhaW5lciA9IG9wdHMuY29udGFpbmVyO1xuICAgIHZhciBvdXRlckNvbnRhaW5lciA9IG9wdHMub3V0ZXJDb250YWluZXI7XG4gICAgdmFyIGNvbW1vbkxhYmVsT3B0cyA9IG9wdHMuY29tbW9uTGFiZWxPcHRzIHx8IHt9O1xuXG4gICAgLy8gb3B0cy5mb250RmFtaWx5L1NpemUgYXJlIHVzZWQgZm9yIHRoZSBjb21tb24gbGFiZWxcbiAgICAvLyBhbmQgYXMgZGVmYXVsdHMgZm9yIGVhY2ggaG92ZXIgbGFiZWwsIHRob3VnaCB0aGUgaW5kaXZpZHVhbCBsYWJlbHNcbiAgICAvLyBjYW4gb3ZlcnJpZGUgdGhpcy5cbiAgICB2YXIgZm9udEZhbWlseSA9IG9wdHMuZm9udEZhbWlseSB8fCBjb25zdGFudHMuSE9WRVJGT05UO1xuICAgIHZhciBmb250U2l6ZSA9IG9wdHMuZm9udFNpemUgfHwgY29uc3RhbnRzLkhPVkVSRk9OVFNJWkU7XG5cbiAgICB2YXIgYzAgPSBob3ZlckRhdGFbMF07XG4gICAgdmFyIHhhID0gYzAueGE7XG4gICAgdmFyIHlhID0gYzAueWE7XG4gICAgdmFyIGNvbW1vbkF0dHIgPSBob3Zlcm1vZGUgPT09ICd5JyA/ICd5TGFiZWwnIDogJ3hMYWJlbCc7XG4gICAgdmFyIHQwID0gYzBbY29tbW9uQXR0cl07XG4gICAgdmFyIHQwMCA9IChTdHJpbmcodDApIHx8ICcnKS5zcGxpdCgnICcpWzBdO1xuICAgIHZhciBvdXRlckNvbnRhaW5lckJCID0gb3V0ZXJDb250YWluZXIubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHZhciBvdXRlclRvcCA9IG91dGVyQ29udGFpbmVyQkIudG9wO1xuICAgIHZhciBvdXRlcldpZHRoID0gb3V0ZXJDb250YWluZXJCQi53aWR0aDtcbiAgICB2YXIgb3V0ZXJIZWlnaHQgPSBvdXRlckNvbnRhaW5lckJCLmhlaWdodDtcblxuICAgIC8vIHNob3cgdGhlIGNvbW1vbiBsYWJlbCwgaWYgYW55LCBvbiB0aGUgYXhpc1xuICAgIC8vIG5ldmVyIHNob3cgYSBjb21tb24gbGFiZWwgaW4gYXJyYXkgbW9kZSxcbiAgICAvLyBldmVuIGlmIHNvbWV0aW1lcyB0aGVyZSBjb3VsZCBiZSBvbmVcbiAgICB2YXIgc2hvd0NvbW1vbkxhYmVsID0gKFxuICAgICAgICAodDAgIT09IHVuZGVmaW5lZCkgJiZcbiAgICAgICAgKGMwLmRpc3RhbmNlIDw9IG9wdHMuaG92ZXJkaXN0YW5jZSkgJiZcbiAgICAgICAgKGhvdmVybW9kZSA9PT0gJ3gnIHx8IGhvdmVybW9kZSA9PT0gJ3knKVxuICAgICk7XG5cbiAgICAvLyBhbGwgaG92ZXIgdHJhY2VzIGhvdmVyaW5mbyBtdXN0IGNvbnRhaW4gdGhlIGhvdmVybW9kZVxuICAgIC8vIHRvIGhhdmUgY29tbW9uIGxhYmVsc1xuICAgIGlmKHNob3dDb21tb25MYWJlbCkge1xuICAgICAgICB2YXIgYWxsSGF2ZVogPSB0cnVlO1xuICAgICAgICB2YXIgaSwgdHJhY2VIb3ZlcmluZm87XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGhvdmVyRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoYWxsSGF2ZVogJiYgaG92ZXJEYXRhW2ldLnpMYWJlbCA9PT0gdW5kZWZpbmVkKSBhbGxIYXZlWiA9IGZhbHNlO1xuXG4gICAgICAgICAgICB0cmFjZUhvdmVyaW5mbyA9IGhvdmVyRGF0YVtpXS5ob3ZlcmluZm8gfHwgaG92ZXJEYXRhW2ldLnRyYWNlLmhvdmVyaW5mbztcbiAgICAgICAgICAgIGlmKHRyYWNlSG92ZXJpbmZvKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcnRzID0gQXJyYXkuaXNBcnJheSh0cmFjZUhvdmVyaW5mbykgPyB0cmFjZUhvdmVyaW5mbyA6IHRyYWNlSG92ZXJpbmZvLnNwbGl0KCcrJyk7XG4gICAgICAgICAgICAgICAgaWYocGFydHMuaW5kZXhPZignYWxsJykgPT09IC0xICYmXG4gICAgICAgICAgICAgICAgICAgIHBhcnRzLmluZGV4T2YoaG92ZXJtb2RlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgc2hvd0NvbW1vbkxhYmVsID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHh5eiBsYWJlbHMgcHV0IGFsbCBpbmZvIGluIHRoZWlyIG1haW4gbGFiZWwsIHNvIGhhdmUgbm8gbmVlZCBvZiBhIGNvbW1vbiBsYWJlbFxuICAgICAgICBpZihhbGxIYXZlWikgc2hvd0NvbW1vbkxhYmVsID0gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIGNvbW1vbkxhYmVsID0gY29udGFpbmVyLnNlbGVjdEFsbCgnZy5heGlzdGV4dCcpXG4gICAgICAgIC5kYXRhKHNob3dDb21tb25MYWJlbCA/IFswXSA6IFtdKTtcbiAgICBjb21tb25MYWJlbC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdheGlzdGV4dCcsIHRydWUpO1xuICAgIGNvbW1vbkxhYmVsLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGNvbW1vbkxhYmVsLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBsYWJlbCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGxwYXRoID0gTGliLmVuc3VyZVNpbmdsZShsYWJlbCwgJ3BhdGgnLCAnJywgZnVuY3Rpb24ocykge1xuICAgICAgICAgICAgcy5zdHlsZSh7J3N0cm9rZS13aWR0aCc6ICcxcHgnfSk7XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgbHRleHQgPSBMaWIuZW5zdXJlU2luZ2xlKGxhYmVsLCAndGV4dCcsICcnLCBmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICAvLyBwcm9oaWJpdCB0ZXggaW50ZXJwcmV0YXRpb24gdW50aWwgd2UgY2FuIGhhbmRsZVxuICAgICAgICAgICAgLy8gdGV4IGFuZCByZWd1bGFyIHRleHQgdG9nZXRoZXJcbiAgICAgICAgICAgIHMuYXR0cignZGF0YS1ub3RleCcsIDEpO1xuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgY29tbW9uQmdDb2xvciA9IGNvbW1vbkxhYmVsT3B0cy5iZ2NvbG9yIHx8IENvbG9yLmRlZmF1bHRMaW5lO1xuICAgICAgICB2YXIgY29tbW9uU3Ryb2tlID0gY29tbW9uTGFiZWxPcHRzLmJvcmRlcmNvbG9yIHx8IENvbG9yLmNvbnRyYXN0KGNvbW1vbkJnQ29sb3IpO1xuICAgICAgICB2YXIgY29udHJhc3RDb2xvciA9IENvbG9yLmNvbnRyYXN0KGNvbW1vbkJnQ29sb3IpO1xuXG4gICAgICAgIGxwYXRoLnN0eWxlKHtcbiAgICAgICAgICAgIGZpbGw6IGNvbW1vbkJnQ29sb3IsXG4gICAgICAgICAgICBzdHJva2U6IGNvbW1vblN0cm9rZVxuICAgICAgICB9KTtcblxuICAgICAgICBsdGV4dC50ZXh0KHQwKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LFxuICAgICAgICAgICAgICAgIGNvbW1vbkxhYmVsT3B0cy5mb250LmZhbWlseSB8fCBmb250RmFtaWx5LFxuICAgICAgICAgICAgICAgIGNvbW1vbkxhYmVsT3B0cy5mb250LnNpemUgfHwgZm9udFNpemUsXG4gICAgICAgICAgICAgICAgY29tbW9uTGFiZWxPcHRzLmZvbnQuY29sb3IgfHwgY29udHJhc3RDb2xvclxuICAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQsIDAsIDApXG4gICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG5cbiAgICAgICAgbGFiZWwuYXR0cigndHJhbnNmb3JtJywgJycpO1xuXG4gICAgICAgIHZhciB0YmIgPSBsdGV4dC5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGlmKGhvdmVybW9kZSA9PT0gJ3gnKSB7XG4gICAgICAgICAgICBsdGV4dC5hdHRyKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKVxuICAgICAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQsIDAsICh4YS5zaWRlID09PSAndG9wJyA/XG4gICAgICAgICAgICAgICAgICAgIChvdXRlclRvcCAtIHRiYi5ib3R0b20gLSBIT1ZFUkFSUk9XU0laRSAtIEhPVkVSVEVYVFBBRCkgOlxuICAgICAgICAgICAgICAgICAgICAob3V0ZXJUb3AgLSB0YmIudG9wICsgSE9WRVJBUlJPV1NJWkUgKyBIT1ZFUlRFWFRQQUQpKSk7XG5cbiAgICAgICAgICAgIHZhciB0b3BzaWduID0geGEuc2lkZSA9PT0gJ3RvcCcgPyAnLScgOiAnJztcbiAgICAgICAgICAgIGxwYXRoLmF0dHIoJ2QnLCAnTTAsMCcgK1xuICAgICAgICAgICAgICAgICdMJyArIEhPVkVSQVJST1dTSVpFICsgJywnICsgdG9wc2lnbiArIEhPVkVSQVJST1dTSVpFICtcbiAgICAgICAgICAgICAgICAnSCcgKyAoSE9WRVJURVhUUEFEICsgdGJiLndpZHRoIC8gMikgK1xuICAgICAgICAgICAgICAgICd2JyArIHRvcHNpZ24gKyAoSE9WRVJURVhUUEFEICogMiArIHRiYi5oZWlnaHQpICtcbiAgICAgICAgICAgICAgICAnSC0nICsgKEhPVkVSVEVYVFBBRCArIHRiYi53aWR0aCAvIDIpICtcbiAgICAgICAgICAgICAgICAnVicgKyB0b3BzaWduICsgSE9WRVJBUlJPV1NJWkUgKyAnSC0nICsgSE9WRVJBUlJPV1NJWkUgKyAnWicpO1xuXG4gICAgICAgICAgICBsYWJlbC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgK1xuICAgICAgICAgICAgICAgICh4YS5fb2Zmc2V0ICsgKGMwLngwICsgYzAueDEpIC8gMikgKyAnLCcgK1xuICAgICAgICAgICAgICAgICh5YS5fb2Zmc2V0ICsgKHhhLnNpZGUgPT09ICd0b3AnID8gMCA6IHlhLl9sZW5ndGgpKSArICcpJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsdGV4dC5hdHRyKCd0ZXh0LWFuY2hvcicsIHlhLnNpZGUgPT09ICdyaWdodCcgPyAnc3RhcnQnIDogJ2VuZCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCxcbiAgICAgICAgICAgICAgICAgICAgKHlhLnNpZGUgPT09ICdyaWdodCcgPyAxIDogLTEpICogKEhPVkVSVEVYVFBBRCArIEhPVkVSQVJST1dTSVpFKSxcbiAgICAgICAgICAgICAgICAgICAgb3V0ZXJUb3AgLSB0YmIudG9wIC0gdGJiLmhlaWdodCAvIDIpO1xuXG4gICAgICAgICAgICB2YXIgbGVmdHNpZ24gPSB5YS5zaWRlID09PSAncmlnaHQnID8gJycgOiAnLSc7XG4gICAgICAgICAgICBscGF0aC5hdHRyKCdkJywgJ00wLDAnICtcbiAgICAgICAgICAgICAgICAnTCcgKyBsZWZ0c2lnbiArIEhPVkVSQVJST1dTSVpFICsgJywnICsgSE9WRVJBUlJPV1NJWkUgK1xuICAgICAgICAgICAgICAgICdWJyArIChIT1ZFUlRFWFRQQUQgKyB0YmIuaGVpZ2h0IC8gMikgK1xuICAgICAgICAgICAgICAgICdoJyArIGxlZnRzaWduICsgKEhPVkVSVEVYVFBBRCAqIDIgKyB0YmIud2lkdGgpICtcbiAgICAgICAgICAgICAgICAnVi0nICsgKEhPVkVSVEVYVFBBRCArIHRiYi5oZWlnaHQgLyAyKSArXG4gICAgICAgICAgICAgICAgJ0gnICsgbGVmdHNpZ24gKyBIT1ZFUkFSUk9XU0laRSArICdWLScgKyBIT1ZFUkFSUk9XU0laRSArICdaJyk7XG5cbiAgICAgICAgICAgIGxhYmVsLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArXG4gICAgICAgICAgICAgICAgKHhhLl9vZmZzZXQgKyAoeWEuc2lkZSA9PT0gJ3JpZ2h0JyA/IHhhLl9sZW5ndGggOiAwKSkgKyAnLCcgK1xuICAgICAgICAgICAgICAgICh5YS5fb2Zmc2V0ICsgKGMwLnkwICsgYzAueTEpIC8gMikgKyAnKScpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHJlbW92ZSB0aGUgXCJjbG9zZSBidXQgbm90IHF1aXRlXCIgcG9pbnRzXG4gICAgICAgIC8vIGJlY2F1c2Ugb2YgZXJyb3IgYmFycywgb25seSB0YWtlIHVwIHRvIGEgc3BhY2VcbiAgICAgICAgaG92ZXJEYXRhID0gaG92ZXJEYXRhLmZpbHRlcihmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gKGQuekxhYmVsVmFsICE9PSB1bmRlZmluZWQpIHx8XG4gICAgICAgICAgICAgICAgKGRbY29tbW9uQXR0cl0gfHwgJycpLnNwbGl0KCcgJylbMF0gPT09IHQwMDtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBzaG93IGFsbCB0aGUgaW5kaXZpZHVhbCBsYWJlbHNcblxuICAgIC8vIGZpcnN0IGNyZWF0ZSB0aGUgb2JqZWN0c1xuICAgIHZhciBob3ZlckxhYmVscyA9IGNvbnRhaW5lci5zZWxlY3RBbGwoJ2cuaG92ZXJ0ZXh0JylcbiAgICAgICAgLmRhdGEoaG92ZXJEYXRhLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAvLyBOLkIuIHdoZW4gbXVsdGlwbGUgaXRlbXMgaGF2ZSB0aGUgc2FtZSByZXN1bHQga2V5LWZ1bmN0aW9uIHZhbHVlLFxuICAgICAgICAgICAgLy8gb25seSB0aGUgZmlyc3Qgb2YgdGhvc2UgaXRlbXMgaW4gaG92ZXJEYXRhIGdldHMgcmVuZGVyZWRcbiAgICAgICAgICAgIHJldHVybiBbZC50cmFjZS5pbmRleCwgZC5pbmRleCwgZC54MCwgZC55MCwgZC5uYW1lLCBkLmF0dHIsIGQueGEsIGQueWEgfHwgJyddLmpvaW4oJywnKTtcbiAgICAgICAgfSk7XG4gICAgaG92ZXJMYWJlbHMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnaG92ZXJ0ZXh0JywgdHJ1ZSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgZyA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIC8vIHRyYWNlIG5hbWUgbGFiZWwgKHJlY3QgYW5kIHRleHQubmFtZSlcbiAgICAgICAgICAgIGcuYXBwZW5kKCdyZWN0JylcbiAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBDb2xvci5hZGRPcGFjaXR5KGJnQ29sb3IsIDAuOCkpO1xuICAgICAgICAgICAgZy5hcHBlbmQoJ3RleHQnKS5jbGFzc2VkKCduYW1lJywgdHJ1ZSk7XG4gICAgICAgICAgICAvLyB0cmFjZSBkYXRhIGxhYmVsIChwYXRoIGFuZCB0ZXh0Lm51bXMpXG4gICAgICAgICAgICBnLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCAnMXB4Jyk7XG4gICAgICAgICAgICBnLmFwcGVuZCgndGV4dCcpLmNsYXNzZWQoJ251bXMnLCB0cnVlKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZm9udCwgZm9udEZhbWlseSwgZm9udFNpemUpO1xuICAgICAgICB9KTtcbiAgICBob3ZlckxhYmVscy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAvLyB0aGVuIHB1dCB0aGUgdGV4dCBpbiwgcG9zaXRpb24gdGhlIHBvaW50ZXIgdG8gdGhlIGRhdGEsXG4gICAgLy8gYW5kIGZpZ3VyZSBvdXQgc2l6ZXNcbiAgICBob3ZlckxhYmVscy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGcgPSBkMy5zZWxlY3QodGhpcykuYXR0cigndHJhbnNmb3JtJywgJycpO1xuICAgICAgICB2YXIgbmFtZSA9ICcnO1xuICAgICAgICB2YXIgdGV4dCA9ICcnO1xuXG4gICAgICAgIC8vIGNvbWJpbmUgcG9zc2libGUgbm9uLW9wYXF1ZSB0cmFjZSBjb2xvciB3aXRoIGJnQ29sb3JcbiAgICAgICAgdmFyIGNvbG9yMCA9IGQuYmdjb2xvciB8fCBkLmNvbG9yO1xuICAgICAgICAvLyBjb2xvciBmb3IgJ251bXMnIHBhcnQgb2YgdGhlIGxhYmVsXG4gICAgICAgIHZhciBudW1zQ29sb3IgPSBDb2xvci5jb21iaW5lKFxuICAgICAgICAgICAgQ29sb3Iub3BhY2l0eShjb2xvcjApID8gY29sb3IwIDogQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgICAgICBiZ0NvbG9yXG4gICAgICAgICk7XG4gICAgICAgIC8vIGNvbG9yIGZvciAnbmFtZScgcGFydCBvZiB0aGUgbGFiZWxcbiAgICAgICAgdmFyIG5hbWVDb2xvciA9IENvbG9yLmNvbWJpbmUoXG4gICAgICAgICAgICBDb2xvci5vcGFjaXR5KGQuY29sb3IpID8gZC5jb2xvciA6IENvbG9yLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgYmdDb2xvclxuICAgICAgICApO1xuICAgICAgICAvLyBmaW5kIGEgY29udHJhc3RpbmcgY29sb3IgZm9yIGJvcmRlciBhbmQgdGV4dFxuICAgICAgICB2YXIgY29udHJhc3RDb2xvciA9IGQuYm9yZGVyQ29sb3IgfHwgQ29sb3IuY29udHJhc3QobnVtc0NvbG9yKTtcblxuICAgICAgICAvLyB0byBnZXQgY3VzdG9tICduYW1lJyBsYWJlbHMgcGFzcyBjbGVhblBvaW50XG4gICAgICAgIGlmKGQubmFtZU92ZXJyaWRlICE9PSB1bmRlZmluZWQpIGQubmFtZSA9IGQubmFtZU92ZXJyaWRlO1xuXG4gICAgICAgIGlmKGQubmFtZSkge1xuICAgICAgICAgICAgaWYoZC50cmFjZS5fbWV0YSkge1xuICAgICAgICAgICAgICAgIGQubmFtZSA9IExpYi50ZW1wbGF0ZVN0cmluZyhkLm5hbWUsIGQudHJhY2UuX21ldGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbmFtZSA9IHBsYWluVGV4dChkLm5hbWUsIGQubmFtZUxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihkLnpMYWJlbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZihkLnhMYWJlbCAhPT0gdW5kZWZpbmVkKSB0ZXh0ICs9ICd4OiAnICsgZC54TGFiZWwgKyAnPGJyPic7XG4gICAgICAgICAgICBpZihkLnlMYWJlbCAhPT0gdW5kZWZpbmVkKSB0ZXh0ICs9ICd5OiAnICsgZC55TGFiZWwgKyAnPGJyPic7XG4gICAgICAgICAgICBpZihkLnRyYWNlLnR5cGUgIT09ICdjaG9yb3BsZXRoJyAmJiBkLnRyYWNlLnR5cGUgIT09ICdjaG9yb3BsZXRobWFwYm94Jykge1xuICAgICAgICAgICAgICAgIHRleHQgKz0gKHRleHQgPyAnejogJyA6ICcnKSArIGQuekxhYmVsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoc2hvd0NvbW1vbkxhYmVsICYmIGRbaG92ZXJtb2RlICsgJ0xhYmVsJ10gPT09IHQwKSB7XG4gICAgICAgICAgICB0ZXh0ID0gZFsoaG92ZXJtb2RlID09PSAneCcgPyAneScgOiAneCcpICsgJ0xhYmVsJ10gfHwgJyc7XG4gICAgICAgIH0gZWxzZSBpZihkLnhMYWJlbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZihkLnlMYWJlbCAhPT0gdW5kZWZpbmVkICYmIGQudHJhY2UudHlwZSAhPT0gJ3NjYXR0ZXJjYXJwZXQnKSB7XG4gICAgICAgICAgICAgICAgdGV4dCA9IGQueUxhYmVsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoZC55TGFiZWwgPT09IHVuZGVmaW5lZCkgdGV4dCA9IGQueExhYmVsO1xuICAgICAgICBlbHNlIHRleHQgPSAnKCcgKyBkLnhMYWJlbCArICcsICcgKyBkLnlMYWJlbCArICcpJztcblxuICAgICAgICBpZigoZC50ZXh0IHx8IGQudGV4dCA9PT0gMCkgJiYgIUFycmF5LmlzQXJyYXkoZC50ZXh0KSkge1xuICAgICAgICAgICAgdGV4dCArPSAodGV4dCA/ICc8YnI+JyA6ICcnKSArIGQudGV4dDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVzZWQgYnkgb3RoZXIgbW9kdWxlcyAoaW5pdGlhbGx5IGp1c3QgdGVybmFyeSkgdGhhdFxuICAgICAgICAvLyBtYW5hZ2UgdGhlaXIgb3duIGhvdmVyaW5mbyBpbmRlcGVuZGVudCBvZiBjbGVhblBvaW50XG4gICAgICAgIC8vIHRoZSByZXN0IG9mIHRoaXMgd2lsbCBzdGlsbCBhcHBseSwgc28gc3VjaCBtb2R1bGVzXG4gICAgICAgIC8vIGNhbiBzdGlsbCBwdXQgdGhpbmdzIGluICh4fHl8eilMYWJlbCwgdGV4dCwgYW5kIG5hbWVcbiAgICAgICAgLy8gYW5kIGhvdmVyaW5mbyB3aWxsIHN0aWxsIGRldGVybWluZSB0aGVpciB2aXNpYmlsaXR5XG4gICAgICAgIGlmKGQuZXh0cmFUZXh0ICE9PSB1bmRlZmluZWQpIHRleHQgKz0gKHRleHQgPyAnPGJyPicgOiAnJykgKyBkLmV4dHJhVGV4dDtcblxuICAgICAgICAvLyBpZiAndGV4dCcgaXMgZW1wdHkgYXQgdGhpcyBwb2ludCxcbiAgICAgICAgLy8gYW5kIGhvdmVydGVtcGxhdGUgaXMgbm90IGRlZmluZWQsXG4gICAgICAgIC8vIHB1dCAnbmFtZScgaW4gbWFpbiBsYWJlbCBhbmQgZG9uJ3Qgc2hvdyBzZWNvbmRhcnkgbGFiZWxcbiAgICAgICAgaWYodGV4dCA9PT0gJycgJiYgIWQuaG92ZXJ0ZW1wbGF0ZSkge1xuICAgICAgICAgICAgLy8gaWYgJ25hbWUnIGlzIGFsc28gZW1wdHksIHJlbW92ZSBlbnRpcmUgbGFiZWxcbiAgICAgICAgICAgIGlmKG5hbWUgPT09ICcnKSBnLnJlbW92ZSgpO1xuICAgICAgICAgICAgdGV4dCA9IG5hbWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBob3ZlcnRlbXBsYXRlXG4gICAgICAgIHZhciBkM2xvY2FsZSA9IGZ1bGxMYXlvdXQuX2QzbG9jYWxlO1xuICAgICAgICB2YXIgaG92ZXJ0ZW1wbGF0ZSA9IGQuaG92ZXJ0ZW1wbGF0ZSB8fCBmYWxzZTtcbiAgICAgICAgdmFyIGhvdmVydGVtcGxhdGVMYWJlbHMgPSBkLmhvdmVydGVtcGxhdGVMYWJlbHMgfHwgZDtcbiAgICAgICAgdmFyIGV2ZW50RGF0YSA9IGQuZXZlbnREYXRhWzBdIHx8IHt9O1xuICAgICAgICBpZihob3ZlcnRlbXBsYXRlKSB7XG4gICAgICAgICAgICB0ZXh0ID0gTGliLmhvdmVydGVtcGxhdGVTdHJpbmcoXG4gICAgICAgICAgICAgICAgaG92ZXJ0ZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICBob3ZlcnRlbXBsYXRlTGFiZWxzLFxuICAgICAgICAgICAgICAgIGQzbG9jYWxlLFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YSxcbiAgICAgICAgICAgICAgICBkLnRyYWNlLl9tZXRhXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKEVYVFJBX1NUUklOR19SRUdFWCwgZnVuY3Rpb24obWF0Y2gsIGV4dHJhKSB7XG4gICAgICAgICAgICAgICAgLy8gYXNzaWduIG5hbWUgZm9yIHNlY29uZGFyeSB0ZXh0IGxhYmVsXG4gICAgICAgICAgICAgICAgbmFtZSA9IHBsYWluVGV4dChleHRyYSwgZC5uYW1lTGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgZnJvbSBtYWluIHRleHQgbGFiZWxcbiAgICAgICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG1haW4gbGFiZWxcbiAgICAgICAgdmFyIHR4ID0gZy5zZWxlY3QoJ3RleHQubnVtcycpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsXG4gICAgICAgICAgICAgICAgZC5mb250RmFtaWx5IHx8IGZvbnRGYW1pbHksXG4gICAgICAgICAgICAgICAgZC5mb250U2l6ZSB8fCBmb250U2l6ZSxcbiAgICAgICAgICAgICAgICBkLmZvbnRDb2xvciB8fCBjb250cmFzdENvbG9yKVxuICAgICAgICAgICAgLnRleHQodGV4dClcbiAgICAgICAgICAgIC5hdHRyKCdkYXRhLW5vdGV4JywgMSlcbiAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQsIDAsIDApXG4gICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG5cbiAgICAgICAgdmFyIHR4MiA9IGcuc2VsZWN0KCd0ZXh0Lm5hbWUnKTtcbiAgICAgICAgdmFyIHR4MndpZHRoID0gMDtcbiAgICAgICAgdmFyIHR4MmhlaWdodCA9IDA7XG5cbiAgICAgICAgLy8gc2Vjb25kYXJ5IGxhYmVsIGZvciBub24tZW1wdHkgJ25hbWUnXG4gICAgICAgIGlmKG5hbWUgJiYgbmFtZSAhPT0gdGV4dCkge1xuICAgICAgICAgICAgdHgyLmNhbGwoRHJhd2luZy5mb250LFxuICAgICAgICAgICAgICAgICAgICBkLmZvbnRGYW1pbHkgfHwgZm9udEZhbWlseSxcbiAgICAgICAgICAgICAgICAgICAgZC5mb250U2l6ZSB8fCBmb250U2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgbmFtZUNvbG9yKVxuICAgICAgICAgICAgICAgIC50ZXh0KG5hbWUpXG4gICAgICAgICAgICAgICAgLmF0dHIoJ2RhdGEtbm90ZXgnLCAxKVxuICAgICAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQsIDAsIDApXG4gICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgICAgICB2YXIgdDJiYiA9IHR4Mi5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICB0eDJ3aWR0aCA9IHQyYmIud2lkdGggKyAyICogSE9WRVJURVhUUEFEO1xuICAgICAgICAgICAgdHgyaGVpZ2h0ID0gdDJiYi5oZWlnaHQgKyAyICogSE9WRVJURVhUUEFEO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHgyLnJlbW92ZSgpO1xuICAgICAgICAgICAgZy5zZWxlY3QoJ3JlY3QnKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGcuc2VsZWN0KCdwYXRoJykuc3R5bGUoe1xuICAgICAgICAgICAgZmlsbDogbnVtc0NvbG9yLFxuICAgICAgICAgICAgc3Ryb2tlOiBjb250cmFzdENvbG9yXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciB0YmIgPSB0eC5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBodHggPSBkLnhhLl9vZmZzZXQgKyAoZC54MCArIGQueDEpIC8gMjtcbiAgICAgICAgdmFyIGh0eSA9IGQueWEuX29mZnNldCArIChkLnkwICsgZC55MSkgLyAyO1xuICAgICAgICB2YXIgZHggPSBNYXRoLmFicyhkLngxIC0gZC54MCk7XG4gICAgICAgIHZhciBkeSA9IE1hdGguYWJzKGQueTEgLSBkLnkwKTtcbiAgICAgICAgdmFyIHR4VG90YWxXaWR0aCA9IHRiYi53aWR0aCArIEhPVkVSQVJST1dTSVpFICsgSE9WRVJURVhUUEFEICsgdHgyd2lkdGg7XG4gICAgICAgIHZhciBhbmNob3JTdGFydE9LLCBhbmNob3JFbmRPSztcblxuICAgICAgICBkLnR5MCA9IG91dGVyVG9wIC0gdGJiLnRvcDtcbiAgICAgICAgZC5ieCA9IHRiYi53aWR0aCArIDIgKiBIT1ZFUlRFWFRQQUQ7XG4gICAgICAgIGQuYnkgPSBNYXRoLm1heCh0YmIuaGVpZ2h0ICsgMiAqIEhPVkVSVEVYVFBBRCwgdHgyaGVpZ2h0KTtcbiAgICAgICAgZC5hbmNob3IgPSAnc3RhcnQnO1xuICAgICAgICBkLnR4d2lkdGggPSB0YmIud2lkdGg7XG4gICAgICAgIGQudHgyd2lkdGggPSB0eDJ3aWR0aDtcbiAgICAgICAgZC5vZmZzZXQgPSAwO1xuXG4gICAgICAgIGlmKHJvdGF0ZUxhYmVscykge1xuICAgICAgICAgICAgZC5wb3MgPSBodHg7XG4gICAgICAgICAgICBhbmNob3JTdGFydE9LID0gaHR5ICsgZHkgLyAyICsgdHhUb3RhbFdpZHRoIDw9IG91dGVySGVpZ2h0O1xuICAgICAgICAgICAgYW5jaG9yRW5kT0sgPSBodHkgLSBkeSAvIDIgLSB0eFRvdGFsV2lkdGggPj0gMDtcbiAgICAgICAgICAgIGlmKChkLmlkZWFsQWxpZ24gPT09ICd0b3AnIHx8ICFhbmNob3JTdGFydE9LKSAmJiBhbmNob3JFbmRPSykge1xuICAgICAgICAgICAgICAgIGh0eSAtPSBkeSAvIDI7XG4gICAgICAgICAgICAgICAgZC5hbmNob3IgPSAnZW5kJztcbiAgICAgICAgICAgIH0gZWxzZSBpZihhbmNob3JTdGFydE9LKSB7XG4gICAgICAgICAgICAgICAgaHR5ICs9IGR5IC8gMjtcbiAgICAgICAgICAgICAgICBkLmFuY2hvciA9ICdzdGFydCc7XG4gICAgICAgICAgICB9IGVsc2UgZC5hbmNob3IgPSAnbWlkZGxlJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGQucG9zID0gaHR5O1xuICAgICAgICAgICAgYW5jaG9yU3RhcnRPSyA9IGh0eCArIGR4IC8gMiArIHR4VG90YWxXaWR0aCA8PSBvdXRlcldpZHRoO1xuICAgICAgICAgICAgYW5jaG9yRW5kT0sgPSBodHggLSBkeCAvIDIgLSB0eFRvdGFsV2lkdGggPj0gMDtcblxuICAgICAgICAgICAgaWYoKGQuaWRlYWxBbGlnbiA9PT0gJ2xlZnQnIHx8ICFhbmNob3JTdGFydE9LKSAmJiBhbmNob3JFbmRPSykge1xuICAgICAgICAgICAgICAgIGh0eCAtPSBkeCAvIDI7XG4gICAgICAgICAgICAgICAgZC5hbmNob3IgPSAnZW5kJztcbiAgICAgICAgICAgIH0gZWxzZSBpZihhbmNob3JTdGFydE9LKSB7XG4gICAgICAgICAgICAgICAgaHR4ICs9IGR4IC8gMjtcbiAgICAgICAgICAgICAgICBkLmFuY2hvciA9ICdzdGFydCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGQuYW5jaG9yID0gJ21pZGRsZSc7XG5cbiAgICAgICAgICAgICAgICB2YXIgdHhIYWxmV2lkdGggPSB0eFRvdGFsV2lkdGggLyAyO1xuICAgICAgICAgICAgICAgIHZhciBvdmVyZmxvd1IgPSBodHggKyB0eEhhbGZXaWR0aCAtIG91dGVyV2lkdGg7XG4gICAgICAgICAgICAgICAgdmFyIG92ZXJmbG93TCA9IGh0eCAtIHR4SGFsZldpZHRoO1xuICAgICAgICAgICAgICAgIGlmKG92ZXJmbG93UiA+IDApIGh0eCAtPSBvdmVyZmxvd1I7XG4gICAgICAgICAgICAgICAgaWYob3ZlcmZsb3dMIDwgMCkgaHR4ICs9IC1vdmVyZmxvd0w7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0eC5hdHRyKCd0ZXh0LWFuY2hvcicsIGQuYW5jaG9yKTtcbiAgICAgICAgaWYodHgyd2lkdGgpIHR4Mi5hdHRyKCd0ZXh0LWFuY2hvcicsIGQuYW5jaG9yKTtcbiAgICAgICAgZy5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBodHggKyAnLCcgKyBodHkgKyAnKScgK1xuICAgICAgICAgICAgKHJvdGF0ZUxhYmVscyA/ICdyb3RhdGUoJyArIFlBTkdMRSArICcpJyA6ICcnKSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gaG92ZXJMYWJlbHM7XG59XG5cbi8vIE1ha2UgZ3JvdXBzIG9mIHRvdWNoaW5nIHBvaW50cywgYW5kIHdpdGhpbiBlYWNoIGdyb3VwXG4vLyBtb3ZlIGVhY2ggcG9pbnQgc28gdGhhdCBubyBsYWJlbHMgb3ZlcmxhcCwgYnV0IHRoZSBhdmVyYWdlXG4vLyBsYWJlbCBwb3NpdGlvbiBpcyB0aGUgc2FtZSBhcyBpdCB3YXMgYmVmb3JlIG1vdmluZy4gSW5kaWNlbnRhbGx5LFxuLy8gdGhpcyBpcyBlcXVpdmFsZW50IHRvIHNheWluZyBhbGwgdGhlIGxhYmVscyBhcmUgb24gZXF1YWwgbGluZWFyXG4vLyBzcHJpbmdzIGFib3V0IHRoZWlyIGluaXRpYWwgcG9zaXRpb24uIEluaXRpYWxseSwgZWFjaCBwb2ludCBpc1xuLy8gaXRzIG93biBncm91cCwgYnV0IGFzIHdlIGZpbmQgb3ZlcmxhcHMgd2Ugd2lsbCBjbHVtcCB0aGUgcG9pbnRzLlxuLy9cbi8vIEFsc28sIHRoZXJlIGFyZSBoYXJkIGNvbnN0cmFpbnRzIGF0IHRoZSBlZGdlcyBvZiB0aGUgZ3JhcGhzLFxuLy8gdGhhdCBwdXNoIGFsbCBncm91cHMgdG8gdGhlIG1pZGRsZSBzbyB0aGV5IGFyZSB2aXNpYmxlLiBJIGRvbid0XG4vLyBrbm93IHdoYXQgaGFwcGVucyBpZiB0aGUgZ3JvdXAgc3BhbnMgYWxsIHRoZSB3YXkgZnJvbSBvbmUgZWRnZSB0b1xuLy8gdGhlIG90aGVyLCB0aG91Z2ggaXQgaGFyZGx5IG1hdHRlcnMgLSB0aGVyZSdzIGp1c3QgdG9vIG11Y2hcbi8vIGluZm9ybWF0aW9uIHRoZW4uXG5mdW5jdGlvbiBob3ZlckF2b2lkT3ZlcmxhcHMoaG92ZXJMYWJlbHMsIGF4S2V5LCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIG51bW1vdmVzID0gMDtcbiAgICB2YXIgYXhTaWduID0gMTtcbiAgICB2YXIgbkxhYmVscyA9IGhvdmVyTGFiZWxzLnNpemUoKTtcblxuICAgIC8vIG1ha2UgZ3JvdXBzIG9mIHRvdWNoaW5nIHBvaW50c1xuICAgIHZhciBwb2ludGdyb3VwcyA9IG5ldyBBcnJheShuTGFiZWxzKTtcbiAgICB2YXIgayA9IDA7XG5cbiAgICBob3ZlckxhYmVscy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGF4ID0gZFtheEtleV07XG4gICAgICAgIHZhciBheElzWCA9IGF4Ll9pZC5jaGFyQXQoMCkgPT09ICd4JztcbiAgICAgICAgdmFyIHJuZyA9IGF4LnJhbmdlO1xuXG4gICAgICAgIGlmKGsgPT09IDAgJiYgcm5nICYmICgocm5nWzBdID4gcm5nWzFdKSAhPT0gYXhJc1gpKSB7XG4gICAgICAgICAgICBheFNpZ24gPSAtMTtcbiAgICAgICAgfVxuICAgICAgICBwb2ludGdyb3Vwc1trKytdID0gW3tcbiAgICAgICAgICAgIGRhdHVtOiBkLFxuICAgICAgICAgICAgdHJhY2VJbmRleDogZC50cmFjZS5pbmRleCxcbiAgICAgICAgICAgIGRwOiAwLFxuICAgICAgICAgICAgcG9zOiBkLnBvcyxcbiAgICAgICAgICAgIHBvc3JlZjogZC5wb3NyZWYsXG4gICAgICAgICAgICBzaXplOiBkLmJ5ICogKGF4SXNYID8gWUZBQ1RPUiA6IDEpIC8gMixcbiAgICAgICAgICAgIHBtaW46IDAsXG4gICAgICAgICAgICBwbWF4OiAoYXhJc1ggPyBmdWxsTGF5b3V0LndpZHRoIDogZnVsbExheW91dC5oZWlnaHQpXG4gICAgICAgIH1dO1xuICAgIH0pO1xuXG4gICAgcG9pbnRncm91cHMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiAoYVswXS5wb3NyZWYgLSBiWzBdLnBvc3JlZikgfHxcbiAgICAgICAgICAgIC8vIGZvciBlcXVhbCBwb3NpdGlvbnMsIHNvcnQgdHJhY2UgaW5kaWNlcyBpbmNyZWFzaW5nIG9yIGRlY3JlYXNpbmdcbiAgICAgICAgICAgIC8vIGRlcGVuZGluZyBvbiB3aGV0aGVyIHRoZSBheGlzIGlzIHJldmVyc2VkIG9yIG5vdC4uLiBzbyBzdGFja2VkXG4gICAgICAgICAgICAvLyB0cmFjZXMgd2lsbCBnZW5lcmFsbHkga2VlcCB0aGVpciBvcmRlciBldmVuIGlmIG9uZSB0cmFjZSBhZGRzXG4gICAgICAgICAgICAvLyBub3RoaW5nIHRvIHRoZSBzdGFjay5cbiAgICAgICAgICAgIChheFNpZ24gKiAoYlswXS50cmFjZUluZGV4IC0gYVswXS50cmFjZUluZGV4KSk7XG4gICAgfSk7XG5cbiAgICB2YXIgZG9uZXBvc2l0aW9uaW5nLCB0b3BPdmVybGFwLCBib3R0b21PdmVybGFwLCBpLCBqLCBwdGksIHN1bWRwO1xuXG4gICAgZnVuY3Rpb24gY29uc3RyYWluR3JvdXAoZ3JwKSB7XG4gICAgICAgIHZhciBtaW5QdCA9IGdycFswXTtcbiAgICAgICAgdmFyIG1heFB0ID0gZ3JwW2dycC5sZW5ndGggLSAxXTtcblxuICAgICAgICAvLyBvdmVybGFwIHdpdGggdGhlIHRvcCAtIHBvc2l0aXZlIHZhbHMgYXJlIG92ZXJsYXBzXG4gICAgICAgIHRvcE92ZXJsYXAgPSBtaW5QdC5wbWluIC0gbWluUHQucG9zIC0gbWluUHQuZHAgKyBtaW5QdC5zaXplO1xuXG4gICAgICAgIC8vIG92ZXJsYXAgd2l0aCB0aGUgYm90dG9tIC0gcG9zaXRpdmUgdmFscyBhcmUgb3ZlcmxhcHNcbiAgICAgICAgYm90dG9tT3ZlcmxhcCA9IG1heFB0LnBvcyArIG1heFB0LmRwICsgbWF4UHQuc2l6ZSAtIG1pblB0LnBtYXg7XG5cbiAgICAgICAgLy8gY2hlY2sgZm9yIG1pbiBvdmVybGFwIGZpcnN0LCBzbyB0aGF0IHdlIGFsd2F5c1xuICAgICAgICAvLyBzZWUgdGhlIGxhcmdlc3QgbGFiZWxzXG4gICAgICAgIC8vIGFsbG93IGZvciAuMDFweCBvdmVybGFwLCBzbyB3ZSBkb24ndCBnZXQgYW5cbiAgICAgICAgLy8gaW5maW5pdGUgbG9vcCBmcm9tIHJvdW5kaW5nIGVycm9yc1xuICAgICAgICBpZih0b3BPdmVybGFwID4gMC4wMSkge1xuICAgICAgICAgICAgZm9yKGogPSBncnAubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIGdycFtqXS5kcCArPSB0b3BPdmVybGFwO1xuICAgICAgICAgICAgZG9uZXBvc2l0aW9uaW5nID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYoYm90dG9tT3ZlcmxhcCA8IDAuMDEpIHJldHVybjtcbiAgICAgICAgaWYodG9wT3ZlcmxhcCA8IC0wLjAxKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHN1cmUgd2UncmUgbm90IHB1c2hpbmcgYmFjayBhbmQgZm9ydGhcbiAgICAgICAgICAgIGZvcihqID0gZ3JwLmxlbmd0aCAtIDE7IGogPj0gMDsgai0tKSBncnBbal0uZHAgLT0gYm90dG9tT3ZlcmxhcDtcbiAgICAgICAgICAgIGRvbmVwb3NpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmKCFkb25lcG9zaXRpb25pbmcpIHJldHVybjtcblxuICAgICAgICAvLyBubyByb29tIHRvIGZpeCBwb3NpdGlvbmluZywgZGVsZXRlIG9mZi1zY3JlZW4gcG9pbnRzXG5cbiAgICAgICAgLy8gZmlyc3Qgc2VlIGhvdyBtYW55IHBvaW50cyB3ZSBuZWVkIHRvIGRlbGV0ZVxuICAgICAgICB2YXIgZGVsZXRlQ291bnQgPSAwO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBncnAubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHB0aSA9IGdycFtpXTtcbiAgICAgICAgICAgIGlmKHB0aS5wb3MgKyBwdGkuZHAgKyBwdGkuc2l6ZSA+IG1pblB0LnBtYXgpIGRlbGV0ZUNvdW50Kys7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzdGFydCBieSBkZWxldGluZyBwb2ludHMgd2hvc2UgZGF0YSBpcyBvZmYgc2NyZWVuXG4gICAgICAgIGZvcihpID0gZ3JwLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBpZihkZWxldGVDb3VudCA8PSAwKSBicmVhaztcbiAgICAgICAgICAgIHB0aSA9IGdycFtpXTtcblxuICAgICAgICAgICAgLy8gcG9zIGhhcyBhbHJlYWR5IGJlZW4gY29uc3RyYWluZWQgdG8gW3BtaW4scG1heF1cbiAgICAgICAgICAgIC8vIHNvIGxvb2sgZm9yIHBvaW50cyBjbG9zZSB0byB0aGF0IHRvIGRlbGV0ZVxuICAgICAgICAgICAgaWYocHRpLnBvcyA+IG1pblB0LnBtYXggLSAxKSB7XG4gICAgICAgICAgICAgICAgcHRpLmRlbCA9IHRydWU7XG4gICAgICAgICAgICAgICAgZGVsZXRlQ291bnQtLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBncnAubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGRlbGV0ZUNvdW50IDw9IDApIGJyZWFrO1xuICAgICAgICAgICAgcHRpID0gZ3JwW2ldO1xuXG4gICAgICAgICAgICAvLyBwb3MgaGFzIGFscmVhZHkgYmVlbiBjb25zdHJhaW5lZCB0byBbcG1pbixwbWF4XVxuICAgICAgICAgICAgLy8gc28gbG9vayBmb3IgcG9pbnRzIGNsb3NlIHRvIHRoYXQgdG8gZGVsZXRlXG4gICAgICAgICAgICBpZihwdGkucG9zIDwgbWluUHQucG1pbiArIDEpIHtcbiAgICAgICAgICAgICAgICBwdGkuZGVsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBkZWxldGVDb3VudC0tO1xuXG4gICAgICAgICAgICAgICAgLy8gc2hpZnQgdGhlIHdob2xlIGdyb3VwIG1pbnVzIGludG8gdGhpcyBuZXcgc3BhY2VcbiAgICAgICAgICAgICAgICBib3R0b21PdmVybGFwID0gcHRpLnNpemUgKiAyO1xuICAgICAgICAgICAgICAgIGZvcihqID0gZ3JwLmxlbmd0aCAtIDE7IGogPj0gMDsgai0tKSBncnBbal0uZHAgLT0gYm90dG9tT3ZlcmxhcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyB0aGVuIGRlbGV0ZSBwb2ludHMgdGhhdCBnbyBvZmYgdGhlIGJvdHRvbVxuICAgICAgICBmb3IoaSA9IGdycC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgaWYoZGVsZXRlQ291bnQgPD0gMCkgYnJlYWs7XG4gICAgICAgICAgICBwdGkgPSBncnBbaV07XG4gICAgICAgICAgICBpZihwdGkucG9zICsgcHRpLmRwICsgcHRpLnNpemUgPiBtaW5QdC5wbWF4KSB7XG4gICAgICAgICAgICAgICAgcHRpLmRlbCA9IHRydWU7XG4gICAgICAgICAgICAgICAgZGVsZXRlQ291bnQtLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGxvb3AgdGhyb3VnaCBncm91cHMsIGNvbWJpbmluZyB0aGVtIGlmIHRoZXkgb3ZlcmxhcCxcbiAgICAvLyB1bnRpbCBub3RoaW5nIG1vdmVzXG4gICAgd2hpbGUoIWRvbmVwb3NpdGlvbmluZyAmJiBudW1tb3ZlcyA8PSBuTGFiZWxzKSB7XG4gICAgICAgIC8vIHRvIGF2b2lkIGluZmluaXRlIGxvb3BzLCBkb24ndCBtb3ZlIG1vcmUgdGltZXNcbiAgICAgICAgLy8gdGhhbiB0aGVyZSBhcmUgdHJhY2VzXG4gICAgICAgIG51bW1vdmVzKys7XG5cbiAgICAgICAgLy8gYXNzdW1lIG5vdGhpbmcgd2lsbCBtb3ZlIGluIHRoaXMgaXRlcmF0aW9uLFxuICAgICAgICAvLyByZXZlcnNlIHRoaXMgaWYgaXQgZG9lc1xuICAgICAgICBkb25lcG9zaXRpb25pbmcgPSB0cnVlO1xuICAgICAgICBpID0gMDtcbiAgICAgICAgd2hpbGUoaSA8IHBvaW50Z3JvdXBzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIC8vIHRoZSBoaWdoZXIgKGcwKSBhbmQgbG93ZXIgKGcxKSBwb2ludCBncm91cFxuICAgICAgICAgICAgdmFyIGcwID0gcG9pbnRncm91cHNbaV07XG4gICAgICAgICAgICB2YXIgZzEgPSBwb2ludGdyb3Vwc1tpICsgMV07XG5cbiAgICAgICAgICAgIC8vIHRoZSBsb3dlc3QgcG9pbnQgaW4gdGhlIGhpZ2hlciBncm91cCAocDApXG4gICAgICAgICAgICAvLyB0aGUgaGlnaGVzdCBwb2ludCBpbiB0aGUgbG93ZXIgZ3JvdXAgKHAxKVxuICAgICAgICAgICAgdmFyIHAwID0gZzBbZzAubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICB2YXIgcDEgPSBnMVswXTtcbiAgICAgICAgICAgIHRvcE92ZXJsYXAgPSBwMC5wb3MgKyBwMC5kcCArIHAwLnNpemUgLSBwMS5wb3MgLSBwMS5kcCArIHAxLnNpemU7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgZ3JvdXAgcG9pbnRzIHRoYXQgbGllIG9uIHRoZSBzYW1lIGF4ZXNcbiAgICAgICAgICAgIGlmKHRvcE92ZXJsYXAgPiAwLjAxICYmIChwMC5wbWluID09PSBwMS5wbWluKSAmJiAocDAucG1heCA9PT0gcDEucG1heCkpIHtcbiAgICAgICAgICAgICAgICAvLyBwdXNoIHRoZSBuZXcgcG9pbnQocykgYWRkZWQgdG8gdGhpcyBncm91cCBvdXQgb2YgdGhlIHdheVxuICAgICAgICAgICAgICAgIGZvcihqID0gZzEubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIGcxW2pdLmRwICs9IHRvcE92ZXJsYXA7XG5cbiAgICAgICAgICAgICAgICAvLyBhZGQgdGhlbSB0byB0aGUgZ3JvdXBcbiAgICAgICAgICAgICAgICBnMC5wdXNoLmFwcGx5KGcwLCBnMSk7XG4gICAgICAgICAgICAgICAgcG9pbnRncm91cHMuc3BsaWNlKGkgKyAxLCAxKTtcblxuICAgICAgICAgICAgICAgIC8vIGFkanVzdCBmb3IgbWluaW11bSBhdmVyYWdlIG1vdmVtZW50XG4gICAgICAgICAgICAgICAgc3VtZHAgPSAwO1xuICAgICAgICAgICAgICAgIGZvcihqID0gZzAubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHN1bWRwICs9IGcwW2pdLmRwO1xuICAgICAgICAgICAgICAgIGJvdHRvbU92ZXJsYXAgPSBzdW1kcCAvIGcwLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IGcwLmxlbmd0aCAtIDE7IGogPj0gMDsgai0tKSBnMFtqXS5kcCAtPSBib3R0b21PdmVybGFwO1xuICAgICAgICAgICAgICAgIGRvbmVwb3NpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgfSBlbHNlIGkrKztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIGlmIHdlJ3JlIGdvaW5nIG9mZiB0aGUgcGxvdCBvbiBlaXRoZXIgc2lkZSBhbmQgZml4XG4gICAgICAgIHBvaW50Z3JvdXBzLmZvckVhY2goY29uc3RyYWluR3JvdXApO1xuICAgIH1cblxuICAgIC8vIG5vdyBwdXQgdGhlc2Ugb2Zmc2V0cyBpbnRvIGhvdmVyRGF0YVxuICAgIGZvcihpID0gcG9pbnRncm91cHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGdycCA9IHBvaW50Z3JvdXBzW2ldO1xuICAgICAgICBmb3IoaiA9IGdycC5sZW5ndGggLSAxOyBqID49IDA7IGotLSkge1xuICAgICAgICAgICAgdmFyIHB0ID0gZ3JwW2pdO1xuICAgICAgICAgICAgdmFyIGhvdmVyUHQgPSBwdC5kYXR1bTtcbiAgICAgICAgICAgIGhvdmVyUHQub2Zmc2V0ID0gcHQuZHA7XG4gICAgICAgICAgICBob3ZlclB0LmRlbCA9IHB0LmRlbDtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gYWxpZ25Ib3ZlclRleHQoaG92ZXJMYWJlbHMsIHJvdGF0ZUxhYmVscykge1xuICAgIC8vIGZpbmFsbHkgc2V0IHRoZSB0ZXh0IHBvc2l0aW9uaW5nIHJlbGF0aXZlIHRvIHRoZSBkYXRhIGFuZCBkcmF3IHRoZVxuICAgIC8vIGJveCBhcm91bmQgaXRcbiAgICBob3ZlckxhYmVscy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGcgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIGlmKGQuZGVsKSByZXR1cm4gZy5yZW1vdmUoKTtcblxuICAgICAgICB2YXIgdHggPSBnLnNlbGVjdCgndGV4dC5udW1zJyk7XG4gICAgICAgIHZhciBhbmNob3IgPSBkLmFuY2hvcjtcbiAgICAgICAgdmFyIGhvcnpTaWduID0gYW5jaG9yID09PSAnZW5kJyA/IC0xIDogMTtcbiAgICAgICAgdmFyIGFsaWduU2hpZnQgPSB7c3RhcnQ6IDEsIGVuZDogLTEsIG1pZGRsZTogMH1bYW5jaG9yXTtcbiAgICAgICAgdmFyIHR4eCA9IGFsaWduU2hpZnQgKiAoSE9WRVJBUlJPV1NJWkUgKyBIT1ZFUlRFWFRQQUQpO1xuICAgICAgICB2YXIgdHgyeCA9IHR4eCArIGFsaWduU2hpZnQgKiAoZC50eHdpZHRoICsgSE9WRVJURVhUUEFEKTtcbiAgICAgICAgdmFyIG9mZnNldFggPSAwO1xuICAgICAgICB2YXIgb2Zmc2V0WSA9IGQub2Zmc2V0O1xuXG4gICAgICAgIGlmKGFuY2hvciA9PT0gJ21pZGRsZScpIHtcbiAgICAgICAgICAgIHR4eCAtPSBkLnR4MndpZHRoIC8gMjtcbiAgICAgICAgICAgIHR4MnggKz0gZC50eHdpZHRoIC8gMiArIEhPVkVSVEVYVFBBRDtcbiAgICAgICAgfVxuICAgICAgICBpZihyb3RhdGVMYWJlbHMpIHtcbiAgICAgICAgICAgIG9mZnNldFkgKj0gLVlTSElGVFk7XG4gICAgICAgICAgICBvZmZzZXRYID0gZC5vZmZzZXQgKiBZU0hJRlRYO1xuICAgICAgICB9XG5cbiAgICAgICAgZy5zZWxlY3QoJ3BhdGgnKS5hdHRyKCdkJywgYW5jaG9yID09PSAnbWlkZGxlJyA/XG4gICAgICAgICAgICAvLyBtaWRkbGUgYWxpZ25lZDogcmVjdCBjZW50ZXJlZCBvbiBkYXRhXG4gICAgICAgICAgICAoJ00tJyArIChkLmJ4IC8gMiArIGQudHgyd2lkdGggLyAyKSArICcsJyArIChvZmZzZXRZIC0gZC5ieSAvIDIpICtcbiAgICAgICAgICAgICAgJ2gnICsgZC5ieCArICd2JyArIGQuYnkgKyAnaC0nICsgZC5ieCArICdaJykgOlxuICAgICAgICAgICAgLy8gbGVmdCBvciByaWdodCBhbGlnbmVkOiBzaWRlIHJlY3Qgd2l0aCBhcnJvdyB0byBkYXRhXG4gICAgICAgICAgICAoJ00wLDBMJyArIChob3J6U2lnbiAqIEhPVkVSQVJST1dTSVpFICsgb2Zmc2V0WCkgKyAnLCcgKyAoSE9WRVJBUlJPV1NJWkUgKyBvZmZzZXRZKSArXG4gICAgICAgICAgICAgICAgJ3YnICsgKGQuYnkgLyAyIC0gSE9WRVJBUlJPV1NJWkUpICtcbiAgICAgICAgICAgICAgICAnaCcgKyAoaG9yelNpZ24gKiBkLmJ4KSArXG4gICAgICAgICAgICAgICAgJ3YtJyArIGQuYnkgK1xuICAgICAgICAgICAgICAgICdIJyArIChob3J6U2lnbiAqIEhPVkVSQVJST1dTSVpFICsgb2Zmc2V0WCkgK1xuICAgICAgICAgICAgICAgICdWJyArIChvZmZzZXRZIC0gSE9WRVJBUlJPV1NJWkUpICtcbiAgICAgICAgICAgICAgICAnWicpKTtcblxuICAgICAgICB2YXIgcG9zWCA9IHR4eCArIG9mZnNldFg7XG4gICAgICAgIHZhciBwb3NZID0gb2Zmc2V0WSArIGQudHkwIC0gZC5ieSAvIDIgKyBIT1ZFUlRFWFRQQUQ7XG4gICAgICAgIHZhciB0ZXh0QWxpZ24gPSBkLnRleHRBbGlnbiB8fCAnYXV0byc7XG5cbiAgICAgICAgaWYodGV4dEFsaWduICE9PSAnYXV0bycpIHtcbiAgICAgICAgICAgIGlmKHRleHRBbGlnbiA9PT0gJ2xlZnQnICYmIGFuY2hvciAhPT0gJ3N0YXJ0Jykge1xuICAgICAgICAgICAgICAgIHR4LmF0dHIoJ3RleHQtYW5jaG9yJywgJ3N0YXJ0Jyk7XG4gICAgICAgICAgICAgICAgcG9zWCA9IGFuY2hvciA9PT0gJ21pZGRsZScgP1xuICAgICAgICAgICAgICAgICAgICAtZC5ieCAvIDIgLSBkLnR4MndpZHRoIC8gMiArIEhPVkVSVEVYVFBBRCA6XG4gICAgICAgICAgICAgICAgICAgIC1kLmJ4IC0gSE9WRVJURVhUUEFEO1xuICAgICAgICAgICAgfSBlbHNlIGlmKHRleHRBbGlnbiA9PT0gJ3JpZ2h0JyAmJiBhbmNob3IgIT09ICdlbmQnKSB7XG4gICAgICAgICAgICAgICAgdHguYXR0cigndGV4dC1hbmNob3InLCAnZW5kJyk7XG4gICAgICAgICAgICAgICAgcG9zWCA9IGFuY2hvciA9PT0gJ21pZGRsZScgP1xuICAgICAgICAgICAgICAgICAgICBkLmJ4IC8gMiAtIGQudHgyd2lkdGggLyAyIC0gSE9WRVJURVhUUEFEIDpcbiAgICAgICAgICAgICAgICAgICAgZC5ieCArIEhPVkVSVEVYVFBBRDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHR4LmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCwgcG9zWCwgcG9zWSk7XG5cbiAgICAgICAgaWYoZC50eDJ3aWR0aCkge1xuICAgICAgICAgICAgZy5zZWxlY3QoJ3RleHQubmFtZScpXG4gICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCxcbiAgICAgICAgICAgICAgICAgICAgdHgyeCArIGFsaWduU2hpZnQgKiBIT1ZFUlRFWFRQQUQgKyBvZmZzZXRYLFxuICAgICAgICAgICAgICAgICAgICBvZmZzZXRZICsgZC50eTAgLSBkLmJ5IC8gMiArIEhPVkVSVEVYVFBBRCk7XG4gICAgICAgICAgICBnLnNlbGVjdCgncmVjdCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRSZWN0LFxuICAgICAgICAgICAgICAgICAgICB0eDJ4ICsgKGFsaWduU2hpZnQgLSAxKSAqIGQudHgyd2lkdGggLyAyICsgb2Zmc2V0WCxcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0WSAtIGQuYnkgLyAyIC0gMSxcbiAgICAgICAgICAgICAgICAgICAgZC50eDJ3aWR0aCwgZC5ieSArIDIpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGNsZWFuUG9pbnQoZCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIGluZGV4ID0gZC5pbmRleDtcbiAgICB2YXIgdHJhY2UgPSBkLnRyYWNlIHx8IHt9O1xuICAgIHZhciBjZDAgPSBkLmNkWzBdO1xuICAgIHZhciBjZCA9IGQuY2RbaW5kZXhdIHx8IHt9O1xuXG4gICAgZnVuY3Rpb24gcGFzcyh2KSB7XG4gICAgICAgIHJldHVybiB2IHx8IChpc051bWVyaWModikgJiYgdiA9PT0gMCk7XG4gICAgfVxuXG4gICAgdmFyIGdldFZhbCA9IEFycmF5LmlzQXJyYXkoaW5kZXgpID9cbiAgICAgICAgZnVuY3Rpb24oY2FsY0tleSwgdHJhY2VLZXkpIHtcbiAgICAgICAgICAgIHZhciB2ID0gTGliLmNhc3RPcHRpb24oY2QwLCBpbmRleCwgY2FsY0tleSk7XG4gICAgICAgICAgICByZXR1cm4gcGFzcyh2KSA/IHYgOiBMaWIuZXh0cmFjdE9wdGlvbih7fSwgdHJhY2UsICcnLCB0cmFjZUtleSk7XG4gICAgICAgIH0gOlxuICAgICAgICBmdW5jdGlvbihjYWxjS2V5LCB0cmFjZUtleSkge1xuICAgICAgICAgICAgcmV0dXJuIExpYi5leHRyYWN0T3B0aW9uKGNkLCB0cmFjZSwgY2FsY0tleSwgdHJhY2VLZXkpO1xuICAgICAgICB9O1xuXG4gICAgZnVuY3Rpb24gZmlsbChrZXksIGNhbGNLZXksIHRyYWNlS2V5KSB7XG4gICAgICAgIHZhciB2YWwgPSBnZXRWYWwoY2FsY0tleSwgdHJhY2VLZXkpO1xuICAgICAgICBpZihwYXNzKHZhbCkpIGRba2V5XSA9IHZhbDtcbiAgICB9XG5cbiAgICBmaWxsKCdob3ZlcmluZm8nLCAnaGknLCAnaG92ZXJpbmZvJyk7XG4gICAgZmlsbCgnYmdjb2xvcicsICdoYmcnLCAnaG92ZXJsYWJlbC5iZ2NvbG9yJyk7XG4gICAgZmlsbCgnYm9yZGVyQ29sb3InLCAnaGJjJywgJ2hvdmVybGFiZWwuYm9yZGVyY29sb3InKTtcbiAgICBmaWxsKCdmb250RmFtaWx5JywgJ2h0ZicsICdob3ZlcmxhYmVsLmZvbnQuZmFtaWx5Jyk7XG4gICAgZmlsbCgnZm9udFNpemUnLCAnaHRzJywgJ2hvdmVybGFiZWwuZm9udC5zaXplJyk7XG4gICAgZmlsbCgnZm9udENvbG9yJywgJ2h0YycsICdob3ZlcmxhYmVsLmZvbnQuY29sb3InKTtcbiAgICBmaWxsKCduYW1lTGVuZ3RoJywgJ2hubCcsICdob3ZlcmxhYmVsLm5hbWVsZW5ndGgnKTtcbiAgICBmaWxsKCd0ZXh0QWxpZ24nLCAnaHRhJywgJ2hvdmVybGFiZWwuYWxpZ24nKTtcblxuICAgIGQucG9zcmVmID0gKGhvdmVybW9kZSA9PT0gJ3knIHx8IChob3Zlcm1vZGUgPT09ICdjbG9zZXN0JyAmJiB0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSkgP1xuICAgICAgICAoZC54YS5fb2Zmc2V0ICsgKGQueDAgKyBkLngxKSAvIDIpIDpcbiAgICAgICAgKGQueWEuX29mZnNldCArIChkLnkwICsgZC55MSkgLyAyKTtcblxuICAgIC8vIHRoZW4gY29uc3RyYWluIGFsbCB0aGUgcG9zaXRpb25zIHRvIGJlIG9uIHRoZSBwbG90XG4gICAgZC54MCA9IExpYi5jb25zdHJhaW4oZC54MCwgMCwgZC54YS5fbGVuZ3RoKTtcbiAgICBkLngxID0gTGliLmNvbnN0cmFpbihkLngxLCAwLCBkLnhhLl9sZW5ndGgpO1xuICAgIGQueTAgPSBMaWIuY29uc3RyYWluKGQueTAsIDAsIGQueWEuX2xlbmd0aCk7XG4gICAgZC55MSA9IExpYi5jb25zdHJhaW4oZC55MSwgMCwgZC55YS5fbGVuZ3RoKTtcblxuICAgIC8vIGFuZCBjb252ZXJ0IHRoZSB4IGFuZCB5IGxhYmVsIHZhbHVlcyBpbnRvIGZvcm1hdHRlZCB0ZXh0XG4gICAgaWYoZC54TGFiZWxWYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBkLnhMYWJlbCA9ICgneExhYmVsJyBpbiBkKSA/IGQueExhYmVsIDogQXhlcy5ob3ZlckxhYmVsVGV4dChkLnhhLCBkLnhMYWJlbFZhbCk7XG4gICAgICAgIGQueFZhbCA9IGQueGEuYzJkKGQueExhYmVsVmFsKTtcbiAgICB9XG4gICAgaWYoZC55TGFiZWxWYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBkLnlMYWJlbCA9ICgneUxhYmVsJyBpbiBkKSA/IGQueUxhYmVsIDogQXhlcy5ob3ZlckxhYmVsVGV4dChkLnlhLCBkLnlMYWJlbFZhbCk7XG4gICAgICAgIGQueVZhbCA9IGQueWEuYzJkKGQueUxhYmVsVmFsKTtcbiAgICB9XG5cbiAgICAvLyBUcmFjZXMgbGlrZSBoZWF0bWFwcyBnZW5lcmF0ZSB0aGUgekxhYmVsIGluIHRoZWlyIGhvdmVyUG9pbnRzIGZ1bmN0aW9uXG4gICAgaWYoZC56TGFiZWxWYWwgIT09IHVuZGVmaW5lZCAmJiBkLnpMYWJlbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGQuekxhYmVsID0gU3RyaW5nKGQuekxhYmVsVmFsKTtcbiAgICB9XG5cbiAgICAvLyBmb3IgYm94IG1lYW5zIGFuZCBlcnJvciBiYXJzLCBhZGQgdGhlIHJhbmdlIHRvIHRoZSBsYWJlbFxuICAgIGlmKCFpc05hTihkLnhlcnIpICYmICEoZC54YS50eXBlID09PSAnbG9nJyAmJiBkLnhlcnIgPD0gMCkpIHtcbiAgICAgICAgdmFyIHhlVGV4dCA9IEF4ZXMudGlja1RleHQoZC54YSwgZC54YS5jMmwoZC54ZXJyKSwgJ2hvdmVyJykudGV4dDtcbiAgICAgICAgaWYoZC54ZXJybmVnICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGQueExhYmVsICs9ICcgKycgKyB4ZVRleHQgKyAnIC8gLScgK1xuICAgICAgICAgICAgICAgIEF4ZXMudGlja1RleHQoZC54YSwgZC54YS5jMmwoZC54ZXJybmVnKSwgJ2hvdmVyJykudGV4dDtcbiAgICAgICAgfSBlbHNlIGQueExhYmVsICs9ICcgwrEgJyArIHhlVGV4dDtcblxuICAgICAgICAvLyBzbWFsbCBkaXN0YW5jZSBwZW5hbHR5IGZvciBlcnJvciBiYXJzLCBzbyB0aGF0IGlmIHRoZXJlIGFyZVxuICAgICAgICAvLyB0cmFjZXMgd2l0aCBlcnJvcnMgYW5kIHNvbWUgd2l0aG91dCwgdGhlIGVycm9yIGJhciBsYWJlbCB3aWxsXG4gICAgICAgIC8vIGhvaXN0IHVwIHRvIHRoZSBwb2ludFxuICAgICAgICBpZihob3Zlcm1vZGUgPT09ICd4JykgZC5kaXN0YW5jZSArPSAxO1xuICAgIH1cbiAgICBpZighaXNOYU4oZC55ZXJyKSAmJiAhKGQueWEudHlwZSA9PT0gJ2xvZycgJiYgZC55ZXJyIDw9IDApKSB7XG4gICAgICAgIHZhciB5ZVRleHQgPSBBeGVzLnRpY2tUZXh0KGQueWEsIGQueWEuYzJsKGQueWVyciksICdob3ZlcicpLnRleHQ7XG4gICAgICAgIGlmKGQueWVycm5lZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBkLnlMYWJlbCArPSAnICsnICsgeWVUZXh0ICsgJyAvIC0nICtcbiAgICAgICAgICAgICAgICBBeGVzLnRpY2tUZXh0KGQueWEsIGQueWEuYzJsKGQueWVycm5lZyksICdob3ZlcicpLnRleHQ7XG4gICAgICAgIH0gZWxzZSBkLnlMYWJlbCArPSAnIMKxICcgKyB5ZVRleHQ7XG5cbiAgICAgICAgaWYoaG92ZXJtb2RlID09PSAneScpIGQuZGlzdGFuY2UgKz0gMTtcbiAgICB9XG5cbiAgICB2YXIgaW5mb21vZGUgPSBkLmhvdmVyaW5mbyB8fCBkLnRyYWNlLmhvdmVyaW5mbztcblxuICAgIGlmKGluZm9tb2RlICYmIGluZm9tb2RlICE9PSAnYWxsJykge1xuICAgICAgICBpbmZvbW9kZSA9IEFycmF5LmlzQXJyYXkoaW5mb21vZGUpID8gaW5mb21vZGUgOiBpbmZvbW9kZS5zcGxpdCgnKycpO1xuICAgICAgICBpZihpbmZvbW9kZS5pbmRleE9mKCd4JykgPT09IC0xKSBkLnhMYWJlbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYoaW5mb21vZGUuaW5kZXhPZigneScpID09PSAtMSkgZC55TGFiZWwgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmKGluZm9tb2RlLmluZGV4T2YoJ3onKSA9PT0gLTEpIGQuekxhYmVsID0gdW5kZWZpbmVkO1xuICAgICAgICBpZihpbmZvbW9kZS5pbmRleE9mKCd0ZXh0JykgPT09IC0xKSBkLnRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmKGluZm9tb2RlLmluZGV4T2YoJ25hbWUnKSA9PT0gLTEpIGQubmFtZSA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gZDtcbn1cblxuZnVuY3Rpb24gY3JlYXRlU3Bpa2VsaW5lcyhjbG9zZXN0UG9pbnRzLCBvcHRzKSB7XG4gICAgdmFyIGNvbnRhaW5lciA9IG9wdHMuY29udGFpbmVyO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gb3B0cy5mdWxsTGF5b3V0O1xuICAgIHZhciBldnQgPSBvcHRzLmV2ZW50O1xuICAgIHZhciBzaG93WSA9ICEhY2xvc2VzdFBvaW50cy5oTGluZVBvaW50O1xuICAgIHZhciBzaG93WCA9ICEhY2xvc2VzdFBvaW50cy52TGluZVBvaW50O1xuXG4gICAgdmFyIHhhLCB5YTtcblxuICAgIC8vIFJlbW92ZSBvbGQgc3Bpa2VsaW5lIGl0ZW1zXG4gICAgY29udGFpbmVyLnNlbGVjdEFsbCgnLnNwaWtlbGluZScpLnJlbW92ZSgpO1xuXG4gICAgaWYoIShzaG93WCB8fCBzaG93WSkpIHJldHVybjtcblxuICAgIHZhciBjb250cmFzdENvbG9yID0gQ29sb3IuY29tYmluZShmdWxsTGF5b3V0LnBsb3RfYmdjb2xvciwgZnVsbExheW91dC5wYXBlcl9iZ2NvbG9yKTtcblxuICAgIC8vIEhvcml6b250YWwgbGluZSAodG8geS1heGlzKVxuICAgIGlmKHNob3dZKSB7XG4gICAgICAgIHZhciBoTGluZVBvaW50ID0gY2xvc2VzdFBvaW50cy5oTGluZVBvaW50O1xuICAgICAgICB2YXIgaExpbmVQb2ludFgsIGhMaW5lUG9pbnRZO1xuXG4gICAgICAgIHhhID0gaExpbmVQb2ludCAmJiBoTGluZVBvaW50LnhhO1xuICAgICAgICB5YSA9IGhMaW5lUG9pbnQgJiYgaExpbmVQb2ludC55YTtcbiAgICAgICAgdmFyIHlTbmFwID0geWEuc3Bpa2VzbmFwO1xuXG4gICAgICAgIGlmKHlTbmFwID09PSAnY3Vyc29yJykge1xuICAgICAgICAgICAgaExpbmVQb2ludFggPSBldnQucG9pbnRlclg7XG4gICAgICAgICAgICBoTGluZVBvaW50WSA9IGV2dC5wb2ludGVyWTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhMaW5lUG9pbnRYID0geGEuX29mZnNldCArIGhMaW5lUG9pbnQueDtcbiAgICAgICAgICAgIGhMaW5lUG9pbnRZID0geWEuX29mZnNldCArIGhMaW5lUG9pbnQueTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGZsdEhMaW5lQ29sb3IgPSB0aW55Y29sb3IucmVhZGFiaWxpdHkoaExpbmVQb2ludC5jb2xvciwgY29udHJhc3RDb2xvcikgPCAxLjUgP1xuICAgICAgICAgICAgQ29sb3IuY29udHJhc3QoY29udHJhc3RDb2xvcikgOiBoTGluZVBvaW50LmNvbG9yO1xuICAgICAgICB2YXIgeU1vZGUgPSB5YS5zcGlrZW1vZGU7XG4gICAgICAgIHZhciB5VGhpY2tuZXNzID0geWEuc3Bpa2V0aGlja25lc3M7XG4gICAgICAgIHZhciB5Q29sb3IgPSB5YS5zcGlrZWNvbG9yIHx8IGRmbHRITGluZUNvbG9yO1xuICAgICAgICB2YXIgeUJCID0geWEuX2JvdW5kaW5nQm94O1xuICAgICAgICB2YXIgeEVkZ2UgPSAoKHlCQi5sZWZ0ICsgeUJCLnJpZ2h0KSAvIDIpIDwgaExpbmVQb2ludFggPyB5QkIucmlnaHQgOiB5QkIubGVmdDtcbiAgICAgICAgdmFyIHhCYXNlLCB4RW5kU3Bpa2U7XG5cbiAgICAgICAgaWYoeU1vZGUuaW5kZXhPZigndG9heGlzJykgIT09IC0xIHx8IHlNb2RlLmluZGV4T2YoJ2Fjcm9zcycpICE9PSAtMSkge1xuICAgICAgICAgICAgaWYoeU1vZGUuaW5kZXhPZigndG9heGlzJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgeEJhc2UgPSB4RWRnZTtcbiAgICAgICAgICAgICAgICB4RW5kU3Bpa2UgPSBoTGluZVBvaW50WDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHlNb2RlLmluZGV4T2YoJ2Fjcm9zcycpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHhCYXNlID0geWEuX2NvdW50ZXJTcGFuWzBdO1xuICAgICAgICAgICAgICAgIHhFbmRTcGlrZSA9IHlhLl9jb3VudGVyU3BhblsxXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRm9yZWdyb3VuZCBob3Jpem9udGFsIGxpbmUgKHRvIHktYXhpcylcbiAgICAgICAgICAgIGNvbnRhaW5lci5pbnNlcnQoJ2xpbmUnLCAnOmZpcnN0LWNoaWxkJylcbiAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHgxOiB4QmFzZSxcbiAgICAgICAgICAgICAgICAgICAgeDI6IHhFbmRTcGlrZSxcbiAgICAgICAgICAgICAgICAgICAgeTE6IGhMaW5lUG9pbnRZLFxuICAgICAgICAgICAgICAgICAgICB5MjogaExpbmVQb2ludFksXG4gICAgICAgICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiB5VGhpY2tuZXNzLFxuICAgICAgICAgICAgICAgICAgICBzdHJva2U6IHlDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS1kYXNoYXJyYXknOiBEcmF3aW5nLmRhc2hTdHlsZSh5YS5zcGlrZWRhc2gsIHlUaGlja25lc3MpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnc3Bpa2VsaW5lJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnY3Jpc3AnLCB0cnVlKTtcblxuICAgICAgICAgICAgLy8gQmFja2dyb3VuZCBob3Jpem9udGFsIExpbmUgKHRvIHktYXhpcylcbiAgICAgICAgICAgIGNvbnRhaW5lci5pbnNlcnQoJ2xpbmUnLCAnOmZpcnN0LWNoaWxkJylcbiAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHgxOiB4QmFzZSxcbiAgICAgICAgICAgICAgICAgICAgeDI6IHhFbmRTcGlrZSxcbiAgICAgICAgICAgICAgICAgICAgeTE6IGhMaW5lUG9pbnRZLFxuICAgICAgICAgICAgICAgICAgICB5MjogaExpbmVQb2ludFksXG4gICAgICAgICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiB5VGhpY2tuZXNzICsgMixcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlOiBjb250cmFzdENvbG9yXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnc3Bpa2VsaW5lJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnY3Jpc3AnLCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBZIGF4aXMgbWFya2VyXG4gICAgICAgIGlmKHlNb2RlLmluZGV4T2YoJ21hcmtlcicpICE9PSAtMSkge1xuICAgICAgICAgICAgY29udGFpbmVyLmluc2VydCgnY2lyY2xlJywgJzpmaXJzdC1jaGlsZCcpXG4gICAgICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICBjeDogeEVkZ2UgKyAoeWEuc2lkZSAhPT0gJ3JpZ2h0JyA/IHlUaGlja25lc3MgOiAteVRoaWNrbmVzcyksXG4gICAgICAgICAgICAgICAgICAgIGN5OiBoTGluZVBvaW50WSxcbiAgICAgICAgICAgICAgICAgICAgcjogeVRoaWNrbmVzcyxcbiAgICAgICAgICAgICAgICAgICAgZmlsbDogeUNvbG9yXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnc3Bpa2VsaW5lJywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihzaG93WCkge1xuICAgICAgICB2YXIgdkxpbmVQb2ludCA9IGNsb3Nlc3RQb2ludHMudkxpbmVQb2ludDtcbiAgICAgICAgdmFyIHZMaW5lUG9pbnRYLCB2TGluZVBvaW50WTtcblxuICAgICAgICB4YSA9IHZMaW5lUG9pbnQgJiYgdkxpbmVQb2ludC54YTtcbiAgICAgICAgeWEgPSB2TGluZVBvaW50ICYmIHZMaW5lUG9pbnQueWE7XG4gICAgICAgIHZhciB4U25hcCA9IHhhLnNwaWtlc25hcDtcblxuICAgICAgICBpZih4U25hcCA9PT0gJ2N1cnNvcicpIHtcbiAgICAgICAgICAgIHZMaW5lUG9pbnRYID0gZXZ0LnBvaW50ZXJYO1xuICAgICAgICAgICAgdkxpbmVQb2ludFkgPSBldnQucG9pbnRlclk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2TGluZVBvaW50WCA9IHhhLl9vZmZzZXQgKyB2TGluZVBvaW50Lng7XG4gICAgICAgICAgICB2TGluZVBvaW50WSA9IHlhLl9vZmZzZXQgKyB2TGluZVBvaW50Lnk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRmbHRWTGluZUNvbG9yID0gdGlueWNvbG9yLnJlYWRhYmlsaXR5KHZMaW5lUG9pbnQuY29sb3IsIGNvbnRyYXN0Q29sb3IpIDwgMS41ID9cbiAgICAgICAgICAgIENvbG9yLmNvbnRyYXN0KGNvbnRyYXN0Q29sb3IpIDogdkxpbmVQb2ludC5jb2xvcjtcbiAgICAgICAgdmFyIHhNb2RlID0geGEuc3Bpa2Vtb2RlO1xuICAgICAgICB2YXIgeFRoaWNrbmVzcyA9IHhhLnNwaWtldGhpY2tuZXNzO1xuICAgICAgICB2YXIgeENvbG9yID0geGEuc3Bpa2Vjb2xvciB8fCBkZmx0VkxpbmVDb2xvcjtcbiAgICAgICAgdmFyIHhCQiA9IHhhLl9ib3VuZGluZ0JveDtcbiAgICAgICAgdmFyIHlFZGdlID0gKCh4QkIudG9wICsgeEJCLmJvdHRvbSkgLyAyKSA8IHZMaW5lUG9pbnRZID8geEJCLmJvdHRvbSA6IHhCQi50b3A7XG4gICAgICAgIHZhciB5QmFzZSwgeUVuZFNwaWtlO1xuXG4gICAgICAgIGlmKHhNb2RlLmluZGV4T2YoJ3RvYXhpcycpICE9PSAtMSB8fCB4TW9kZS5pbmRleE9mKCdhY3Jvc3MnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGlmKHhNb2RlLmluZGV4T2YoJ3RvYXhpcycpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHlCYXNlID0geUVkZ2U7XG4gICAgICAgICAgICAgICAgeUVuZFNwaWtlID0gdkxpbmVQb2ludFk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih4TW9kZS5pbmRleE9mKCdhY3Jvc3MnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICB5QmFzZSA9IHhhLl9jb3VudGVyU3BhblswXTtcbiAgICAgICAgICAgICAgICB5RW5kU3Bpa2UgPSB4YS5fY291bnRlclNwYW5bMV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZvcmVncm91bmQgdmVydGljYWwgbGluZSAodG8geC1heGlzKVxuICAgICAgICAgICAgY29udGFpbmVyLmluc2VydCgnbGluZScsICc6Zmlyc3QtY2hpbGQnKVxuICAgICAgICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgeDE6IHZMaW5lUG9pbnRYLFxuICAgICAgICAgICAgICAgICAgICB4MjogdkxpbmVQb2ludFgsXG4gICAgICAgICAgICAgICAgICAgIHkxOiB5QmFzZSxcbiAgICAgICAgICAgICAgICAgICAgeTI6IHlFbmRTcGlrZSxcbiAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IHhUaGlja25lc3MsXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogeENvbG9yLFxuICAgICAgICAgICAgICAgICAgICAnc3Ryb2tlLWRhc2hhcnJheSc6IERyYXdpbmcuZGFzaFN0eWxlKHhhLnNwaWtlZGFzaCwgeFRoaWNrbmVzcylcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzcGlrZWxpbmUnLCB0cnVlKVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIHRydWUpO1xuXG4gICAgICAgICAgICAvLyBCYWNrZ3JvdW5kIHZlcnRpY2FsIGxpbmUgKHRvIHgtYXhpcylcbiAgICAgICAgICAgIGNvbnRhaW5lci5pbnNlcnQoJ2xpbmUnLCAnOmZpcnN0LWNoaWxkJylcbiAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHgxOiB2TGluZVBvaW50WCxcbiAgICAgICAgICAgICAgICAgICAgeDI6IHZMaW5lUG9pbnRYLFxuICAgICAgICAgICAgICAgICAgICB5MTogeUJhc2UsXG4gICAgICAgICAgICAgICAgICAgIHkyOiB5RW5kU3Bpa2UsXG4gICAgICAgICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiB4VGhpY2tuZXNzICsgMixcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlOiBjb250cmFzdENvbG9yXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnc3Bpa2VsaW5lJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnY3Jpc3AnLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFggYXhpcyBtYXJrZXJcbiAgICAgICAgaWYoeE1vZGUuaW5kZXhPZignbWFya2VyJykgIT09IC0xKSB7XG4gICAgICAgICAgICBjb250YWluZXIuaW5zZXJ0KCdjaXJjbGUnLCAnOmZpcnN0LWNoaWxkJylcbiAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIGN4OiB2TGluZVBvaW50WCxcbiAgICAgICAgICAgICAgICAgICAgY3k6IHlFZGdlIC0gKHhhLnNpZGUgIT09ICd0b3AnID8geFRoaWNrbmVzcyA6IC14VGhpY2tuZXNzKSxcbiAgICAgICAgICAgICAgICAgICAgcjogeFRoaWNrbmVzcyxcbiAgICAgICAgICAgICAgICAgICAgZmlsbDogeENvbG9yXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnc3Bpa2VsaW5lJywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGhvdmVyQ2hhbmdlZChnZCwgZXZ0LCBvbGRob3ZlcmRhdGEpIHtcbiAgICAvLyBkb24ndCBlbWl0IGFueSBldmVudHMgaWYgbm90aGluZyBjaGFuZ2VkXG4gICAgaWYoIW9sZGhvdmVyZGF0YSB8fCBvbGRob3ZlcmRhdGEubGVuZ3RoICE9PSBnZC5faG92ZXJkYXRhLmxlbmd0aCkgcmV0dXJuIHRydWU7XG5cbiAgICBmb3IodmFyIGkgPSBvbGRob3ZlcmRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIG9sZFB0ID0gb2xkaG92ZXJkYXRhW2ldO1xuICAgICAgICB2YXIgbmV3UHQgPSBnZC5faG92ZXJkYXRhW2ldO1xuXG4gICAgICAgIGlmKG9sZFB0LmN1cnZlTnVtYmVyICE9PSBuZXdQdC5jdXJ2ZU51bWJlciB8fFxuICAgICAgICAgICAgU3RyaW5nKG9sZFB0LnBvaW50TnVtYmVyKSAhPT0gU3RyaW5nKG5ld1B0LnBvaW50TnVtYmVyKSB8fFxuICAgICAgICAgICAgU3RyaW5nKG9sZFB0LnBvaW50TnVtYmVycykgIT09IFN0cmluZyhuZXdQdC5wb2ludE51bWJlcnMpXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBzcGlrZXNDaGFuZ2VkKGdkLCBvbGRzcGlrZXBvaW50cykge1xuICAgIC8vIGRvbid0IHJlbGF5b3V0IHRoZSBwbG90IGJlY2F1c2Ugb2YgbmV3IHNwaWtlbGluZXMgaWYgc3Bpa2VsaW5lcyBwb2ludHMgZGlkbid0IGNoYW5nZVxuICAgIGlmKCFvbGRzcGlrZXBvaW50cykgcmV0dXJuIHRydWU7XG4gICAgaWYob2xkc3Bpa2Vwb2ludHMudkxpbmVQb2ludCAhPT0gZ2QuX3NwaWtlcG9pbnRzLnZMaW5lUG9pbnQgfHxcbiAgICAgICAgb2xkc3Bpa2Vwb2ludHMuaExpbmVQb2ludCAhPT0gZ2QuX3NwaWtlcG9pbnRzLmhMaW5lUG9pbnRcbiAgICApIHJldHVybiB0cnVlO1xuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gcGxhaW5UZXh0KHMsIGxlbikge1xuICAgIHJldHVybiBzdmdUZXh0VXRpbHMucGxhaW5UZXh0KHMgfHwgJycsIHtcbiAgICAgICAgbGVuOiBsZW4sXG4gICAgICAgIGFsbG93ZWRUYWdzOiBbJ2JyJywgJ3N1YicsICdzdXAnLCAnYicsICdpJywgJ2VtJ11cbiAgICB9KTtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZXZlbnRzXCI6NzA5LFwiLi4vLi4vbGliL292ZXJyaWRlX2N1cnNvclwiOjczMCxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9jb2xvclwiOjU5MyxcIi4uL2RyYWdlbGVtZW50XCI6NjExLFwiLi4vZHJhd2luZ1wiOjYxNCxcIi4vY29uc3RhbnRzXCI6NjI2LFwiLi9oZWxwZXJzXCI6NjI4LFwiZDNcIjoxNjMsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNSxcInRpbnljb2xvcjJcIjo1Mzd9XSw2MzA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlSG92ZXJMYWJlbERlZmF1bHRzKGNvbnRJbiwgY29udE91dCwgY29lcmNlLCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICBjb2VyY2UoJ2hvdmVybGFiZWwuYmdjb2xvcicsIG9wdHMuYmdjb2xvcik7XG4gICAgY29lcmNlKCdob3ZlcmxhYmVsLmJvcmRlcmNvbG9yJywgb3B0cy5ib3JkZXJjb2xvcik7XG4gICAgY29lcmNlKCdob3ZlcmxhYmVsLm5hbWVsZW5ndGgnLCBvcHRzLm5hbWVsZW5ndGgpO1xuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2hvdmVybGFiZWwuZm9udCcsIG9wdHMuZm9udCk7XG4gICAgY29lcmNlKCdob3ZlcmxhYmVsLmFsaWduJywgb3B0cy5hbGlnbik7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOX1dLDYzMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBGT1JNQVRfTElOSyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9kb2NzJykuRk9STUFUX0xJTks7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob3B0cywgZXh0cmEpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcbiAgICBleHRyYSA9IGV4dHJhIHx8IHt9O1xuXG4gICAgdmFyIGRlc2NQYXJ0ID0gZXh0cmEuZGVzY3JpcHRpb24gPyAnICcgKyBleHRyYS5kZXNjcmlwdGlvbiA6ICcnO1xuICAgIHZhciBrZXlzID0gZXh0cmEua2V5cyB8fCBbXTtcbiAgICBpZihrZXlzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdmFyIHF1b3RlZEtleXMgPSBbXTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHF1b3RlZEtleXNbaV0gPSAnYCcgKyBrZXlzW2ldICsgJ2AnO1xuICAgICAgICB9XG4gICAgICAgIGRlc2NQYXJ0ID0gZGVzY1BhcnQgKyAnRmluYWxseSwgdGhlIHRlbXBsYXRlIHN0cmluZyBoYXMgYWNjZXNzIHRvICc7XG4gICAgICAgIGlmKGtleXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICBkZXNjUGFydCA9ICd2YXJpYWJsZSAnICsgcXVvdGVkS2V5c1swXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlc2NQYXJ0ID0gJ3ZhcmlhYmxlcyAnICsgcXVvdGVkS2V5cy5zbGljZSgwLCAtMSkuam9pbignLCAnKSArICcgYW5kICcgKyBxdW90ZWRLZXlzLnNsaWNlKC0xKSArICcuJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBob3ZlcnRlbXBsYXRlID0ge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBlZGl0VHlwZTogb3B0cy5lZGl0VHlwZSB8fCAnbm9uZScsXG4gICAgICAgIFxuICAgIH07XG5cbiAgICBpZihvcHRzLmFycmF5T2sgIT09IGZhbHNlKSB7XG4gICAgICAgIGhvdmVydGVtcGxhdGUuYXJyYXlPayA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGhvdmVydGVtcGxhdGU7XG59O1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9kb2NzXCI6NjkwfV0sNjMyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBkcmFnRWxlbWVudCA9IF9kZXJlcV8oJy4uL2RyYWdlbGVtZW50Jyk7XG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xudmFyIGxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJNb2R1bGUgPSBfZGVyZXFfKCcuL2hvdmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICdjb21wb25lbnQnLFxuICAgIG5hbWU6ICdmeCcsXG5cbiAgICBjb25zdGFudHM6IF9kZXJlcV8oJy4vY29uc3RhbnRzJyksXG4gICAgc2NoZW1hOiB7XG4gICAgICAgIGxheW91dDogbGF5b3V0QXR0cmlidXRlc1xuICAgIH0sXG5cbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBsYXlvdXRBdHRyaWJ1dGVzLFxuXG4gICAgc3VwcGx5TGF5b3V0R2xvYmFsRGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2dsb2JhbF9kZWZhdWx0cycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2RlZmF1bHRzJyksXG5cbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcblxuICAgIGdldERpc3RhbmNlRnVuY3Rpb246IGhlbHBlcnMuZ2V0RGlzdGFuY2VGdW5jdGlvbixcbiAgICBnZXRDbG9zZXN0OiBoZWxwZXJzLmdldENsb3Nlc3QsXG4gICAgaW5ib3g6IGhlbHBlcnMuaW5ib3gsXG4gICAgcXVhZHJhdHVyZTogaGVscGVycy5xdWFkcmF0dXJlLFxuICAgIGFwcGVuZEFycmF5UG9pbnRWYWx1ZTogaGVscGVycy5hcHBlbmRBcnJheVBvaW50VmFsdWUsXG5cbiAgICBjYXN0SG92ZXJPcHRpb246IGNhc3RIb3Zlck9wdGlvbixcbiAgICBjYXN0SG92ZXJpbmZvOiBjYXN0SG92ZXJpbmZvLFxuXG4gICAgaG92ZXI6IGhvdmVyTW9kdWxlLmhvdmVyLFxuICAgIHVuaG92ZXI6IGRyYWdFbGVtZW50LnVuaG92ZXIsXG5cbiAgICBsb25lSG92ZXI6IGhvdmVyTW9kdWxlLmxvbmVIb3ZlcixcbiAgICBsb25lVW5ob3ZlcjogbG9uZVVuaG92ZXIsXG5cbiAgICBjbGljazogX2RlcmVxXygnLi9jbGljaycpXG59O1xuXG5mdW5jdGlvbiBsb25lVW5ob3Zlcihjb250YWluZXJPclNlbGVjdGlvbikge1xuICAgIC8vIGR1Y2sgdHlwZSB3aGV0aGVyIHRoZSBhcmcgaXMgYSBkMyBzZWxlY3Rpb24gYmVjYXVzZSBpZTkgZG9lc24ndFxuICAgIC8vIGhhbmRsZSBpbnN0YW5jZW9mIGxpa2UgbW9kZXJuIGJyb3dzZXJzIGRvLlxuICAgIHZhciBzZWxlY3Rpb24gPSBMaWIuaXNEM1NlbGVjdGlvbihjb250YWluZXJPclNlbGVjdGlvbikgP1xuICAgICAgICAgICAgY29udGFpbmVyT3JTZWxlY3Rpb24gOlxuICAgICAgICAgICAgZDMuc2VsZWN0KGNvbnRhaW5lck9yU2VsZWN0aW9uKTtcblxuICAgIHNlbGVjdGlvbi5zZWxlY3RBbGwoJ2cuaG92ZXJ0ZXh0JykucmVtb3ZlKCk7XG4gICAgc2VsZWN0aW9uLnNlbGVjdEFsbCgnLnNwaWtlbGluZScpLnJlbW92ZSgpO1xufVxuXG4vLyBoZWxwZXJzIGZvciB0cmFjZXMgdGhhdCB1c2UgRngubG9uZUhvdmVyXG5cbmZ1bmN0aW9uIGNhc3RIb3Zlck9wdGlvbih0cmFjZSwgcHROdW1iZXIsIGF0dHIpIHtcbiAgICByZXR1cm4gTGliLmNhc3RPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnaG92ZXJsYWJlbC4nICsgYXR0cik7XG59XG5cbmZ1bmN0aW9uIGNhc3RIb3ZlcmluZm8odHJhY2UsIGZ1bGxMYXlvdXQsIHB0TnVtYmVyKSB7XG4gICAgZnVuY3Rpb24gX2NvZXJjZSh2YWwpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2VIb3ZlcmluZm8oe2hvdmVyaW5mbzogdmFsfSwge19tb2R1bGU6IHRyYWNlLl9tb2R1bGV9LCBmdWxsTGF5b3V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gTGliLmNhc3RPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnaG92ZXJpbmZvJywgX2NvZXJjZSk7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vZHJhZ2VsZW1lbnRcIjo2MTEsXCIuL2F0dHJpYnV0ZXNcIjo2MjMsXCIuL2NhbGNcIjo2MjQsXCIuL2NsaWNrXCI6NjI1LFwiLi9jb25zdGFudHNcIjo2MjYsXCIuL2RlZmF1bHRzXCI6NjI3LFwiLi9oZWxwZXJzXCI6NjI4LFwiLi9ob3ZlclwiOjYyOSxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo2MzMsXCIuL2xheW91dF9kZWZhdWx0c1wiOjYzNCxcIi4vbGF5b3V0X2dsb2JhbF9kZWZhdWx0c1wiOjYzNSxcImQzXCI6MTYzfV0sNjMzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG5cbnZhciBmb250QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKSh7XG4gICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICBcbn0pO1xuZm9udEF0dHJzLmZhbWlseS5kZmx0ID0gY29uc3RhbnRzLkhPVkVSRk9OVDtcbmZvbnRBdHRycy5zaXplLmRmbHQgPSBjb25zdGFudHMuSE9WRVJGT05UU0laRTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY2xpY2ttb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdmbGFnbGlzdCcsXG4gICAgICAgIFxuICAgICAgICBmbGFnczogWydldmVudCcsICdzZWxlY3QnXSxcbiAgICAgICAgZGZsdDogJ2V2ZW50JyxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgZXh0cmFzOiBbJ25vbmUnXSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkcmFnbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IFsnem9vbScsICdwYW4nLCAnc2VsZWN0JywgJ2xhc3NvJywgJ29yYml0JywgJ3R1cm50YWJsZScsIGZhbHNlXSxcbiAgICAgICAgZGZsdDogJ3pvb20nLFxuICAgICAgICBlZGl0VHlwZTogJ21vZGViYXInLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVybW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IFsneCcsICd5JywgJ2Nsb3Nlc3QnLCBmYWxzZV0sXG4gICAgICAgIGVkaXRUeXBlOiAnbW9kZWJhcicsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJkaXN0YW5jZToge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogLTEsXG4gICAgICAgIGRmbHQ6IDIwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzcGlrZWRpc3RhbmNlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAtMSxcbiAgICAgICAgZGZsdDogMjAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVybGFiZWw6IHtcbiAgICAgICAgYmdjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBib3JkZXJjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBmb250OiBmb250QXR0cnMsXG4gICAgICAgIGFsaWduOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdyaWdodCcsICdhdXRvJ10sXG4gICAgICAgICAgICBkZmx0OiAnYXV0bycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbmFtZWxlbmd0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICAgICAgbWluOiAtMSxcbiAgICAgICAgICAgIGRmbHQ6IDE1LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZSdcbiAgICB9LFxuICAgIHNlbGVjdGRpcmVjdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IFsnaCcsICd2JywgJ2QnLCAnYW55J10sXG4gICAgICAgIGRmbHQ6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJ1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzXCI6NzkzLFwiLi9jb25zdGFudHNcIjo2MjZ9XSw2MzQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGxheW91dEluLCBsYXlvdXRPdXQsIGxheW91dEF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBjbGlja21vZGUgPSBjb2VyY2UoJ2NsaWNrbW9kZScpO1xuXG4gICAgdmFyIGRyYWdNb2RlID0gY29lcmNlKCdkcmFnbW9kZScpO1xuICAgIGlmKGRyYWdNb2RlID09PSAnc2VsZWN0JykgY29lcmNlKCdzZWxlY3RkaXJlY3Rpb24nKTtcblxuICAgIHZhciBob3Zlcm1vZGVEZmx0O1xuICAgIGlmKGxheW91dE91dC5faGFzKCdjYXJ0ZXNpYW4nKSkge1xuICAgICAgICBpZihjbGlja21vZGUuaW5kZXhPZignc2VsZWN0JykgPiAtMSkge1xuICAgICAgICAgICAgaG92ZXJtb2RlRGZsdCA9ICdjbG9zZXN0JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGZsYWcgZm9yICdob3Jpem9udGFsJyBwbG90czpcbiAgICAgICAgICAgIC8vIGRldGVybWluZXMgdGhlIHN0YXRlIG9mIHRoZSBtb2RlIGJhciAnY29tcGFyZScgaG92ZXJtb2RlIGJ1dHRvblxuICAgICAgICAgICAgbGF5b3V0T3V0Ll9pc0hvcml6ID0gaXNIb3JpeihmdWxsRGF0YSwgbGF5b3V0T3V0KTtcbiAgICAgICAgICAgIGhvdmVybW9kZURmbHQgPSBsYXlvdXRPdXQuX2lzSG9yaXogPyAneScgOiAneCc7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaG92ZXJtb2RlRGZsdCA9ICdjbG9zZXN0JztcblxuICAgIHZhciBob3Zlck1vZGUgPSBjb2VyY2UoJ2hvdmVybW9kZScsIGhvdmVybW9kZURmbHQpO1xuICAgIGlmKGhvdmVyTW9kZSkge1xuICAgICAgICBjb2VyY2UoJ2hvdmVyZGlzdGFuY2UnKTtcbiAgICAgICAgY29lcmNlKCdzcGlrZWRpc3RhbmNlJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgb25seSBtYXBib3ggb3IgZ2VvIHN1YnBsb3RzIGlzIHByZXNlbnQgb24gZ3JhcGgsXG4gICAgLy8gcmVzZXQgJ3pvb20nIGRyYWdtb2RlIHRvICdwYW4nIHVudGlsICd6b29tJyBpcyBpbXBsZW1lbnRlZCxcbiAgICAvLyBzbyB0aGF0IHRoZSBjb3JyZWN0IG1vZGViYXIgYnV0dG9uIGlzIGFjdGl2ZVxuICAgIHZhciBoYXNNYXBib3ggPSBsYXlvdXRPdXQuX2hhcygnbWFwYm94Jyk7XG4gICAgdmFyIGhhc0dlbyA9IGxheW91dE91dC5faGFzKCdnZW8nKTtcbiAgICB2YXIgbGVuID0gbGF5b3V0T3V0Ll9iYXNlUGxvdE1vZHVsZXMubGVuZ3RoO1xuXG4gICAgaWYobGF5b3V0T3V0LmRyYWdtb2RlID09PSAnem9vbScgJiYgKFxuICAgICAgICAoKGhhc01hcGJveCB8fCBoYXNHZW8pICYmIGxlbiA9PT0gMSkgfHxcbiAgICAgICAgKGhhc01hcGJveCAmJiBoYXNHZW8gJiYgbGVuID09PSAyKVxuICAgICkpIHtcbiAgICAgICAgbGF5b3V0T3V0LmRyYWdtb2RlID0gJ3Bhbic7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gaXNIb3JpeihmdWxsRGF0YSwgZnVsbExheW91dCkge1xuICAgIHZhciBzdGFja09wdHMgPSBmdWxsTGF5b3V0Ll9zY2F0dGVyU3RhY2tPcHRzIHx8IHt9O1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICB2YXIgc3VicGxvdCA9IHRyYWNlLnhheGlzICsgdHJhY2UueWF4aXM7XG4gICAgICAgIHZhciBzdWJwbG90U3RhY2tPcHRzID0gc3RhY2tPcHRzW3N1YnBsb3RdIHx8IHt9O1xuICAgICAgICB2YXIgZ3JvdXBPcHRzID0gc3VicGxvdFN0YWNrT3B0c1t0cmFjZS5zdGFja2dyb3VwXSB8fCB7fTtcblxuICAgICAgICBpZih0cmFjZS5vcmllbnRhdGlvbiAhPT0gJ2gnICYmIGdyb3VwT3B0cy5vcmllbnRhdGlvbiAhPT0gJ2gnKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6NjMzfV0sNjM1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGhhbmRsZUhvdmVyTGFiZWxEZWZhdWx0cyA9IF9kZXJlcV8oJy4vaG92ZXJsYWJlbF9kZWZhdWx0cycpO1xudmFyIGxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0R2xvYmFsRGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGxheW91dEluLCBsYXlvdXRPdXQsIGxheW91dEF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGhhbmRsZUhvdmVyTGFiZWxEZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBjb2VyY2UpO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuL2hvdmVybGFiZWxfZGVmYXVsdHNcIjo2MzAsXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6NjMzfV0sNjM2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGNvdW50ZXJSZWdleCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9yZWdleCcpLmNvdW50ZXI7XG52YXIgZG9tYWluQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9kb21haW4nKS5hdHRyaWJ1dGVzO1xudmFyIGNhcnRlc2lhbklkUmVnZXggPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vY29uc3RhbnRzJykuaWRSZWdleDtcbnZhciBUZW1wbGF0ZSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcblxudmFyIGdyaWRBdHRycyA9IHtcbiAgICByb3dzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICByb3dvcmRlcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWyd0b3AgdG8gYm90dG9tJywgJ2JvdHRvbSB0byB0b3AnXSxcbiAgICAgICAgZGZsdDogJ3RvcCB0byBib3R0b20nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjb2x1bW5zOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzdWJwbG90czoge1xuICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgIGZyZWVMZW5ndGg6IHRydWUsXG4gICAgICAgIGRpbWVuc2lvbnM6IDIsXG4gICAgICAgIGl0ZW1zOiB7dmFsVHlwZTogJ2VudW1lcmF0ZWQnLCB2YWx1ZXM6IFtjb3VudGVyUmVnZXgoJ3h5JykudG9TdHJpbmcoKSwgJyddLCBlZGl0VHlwZTogJ3Bsb3QnfSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGF4ZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBmcmVlTGVuZ3RoOiB0cnVlLFxuICAgICAgICBpdGVtczoge3ZhbFR5cGU6ICdlbnVtZXJhdGVkJywgdmFsdWVzOiBbY2FydGVzaWFuSWRSZWdleC54LnRvU3RyaW5nKCksICcnXSwgZWRpdFR5cGU6ICdwbG90J30sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHlheGVzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgZnJlZUxlbmd0aDogdHJ1ZSxcbiAgICAgICAgaXRlbXM6IHt2YWxUeXBlOiAnZW51bWVyYXRlZCcsIHZhbHVlczogW2NhcnRlc2lhbklkUmVnZXgueS50b1N0cmluZygpLCAnJ10sIGVkaXRUeXBlOiAncGxvdCd9LFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBwYXR0ZXJuOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2luZGVwZW5kZW50JywgJ2NvdXBsZWQnXSxcbiAgICAgICAgZGZsdDogJ2NvdXBsZWQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4Z2FwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeWdhcDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICdncmlkJywgZWRpdFR5cGU6ICdwbG90Jywgbm9HcmlkQ2VsbDogdHJ1ZX0sIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgeHNpZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYm90dG9tJywgJ2JvdHRvbSBwbG90JywgJ3RvcCBwbG90JywgJ3RvcCddLFxuICAgICAgICBkZmx0OiAnYm90dG9tIHBsb3QnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5c2lkZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydsZWZ0JywgJ2xlZnQgcGxvdCcsICdyaWdodCBwbG90JywgJ3JpZ2h0J10sXG4gICAgICAgIGRmbHQ6ICdsZWZ0IHBsb3QnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ3Bsb3QnXG59O1xuXG5mdW5jdGlvbiBnZXRBeGVzKGxheW91dCwgZ3JpZCwgYXhMZXR0ZXIpIHtcbiAgICB2YXIgZ3JpZFZhbCA9IGdyaWRbYXhMZXR0ZXIgKyAnYXhlcyddO1xuICAgIHZhciBzcGxvbVZhbCA9IE9iamVjdC5rZXlzKChsYXlvdXQuX3NwbG9tQXhlcyB8fCB7fSlbYXhMZXR0ZXJdIHx8IHt9KTtcblxuICAgIGlmKEFycmF5LmlzQXJyYXkoZ3JpZFZhbCkpIHJldHVybiBncmlkVmFsO1xuICAgIGlmKHNwbG9tVmFsLmxlbmd0aCkgcmV0dXJuIHNwbG9tVmFsO1xufVxuXG4vLyB0aGUgc2hhcGUgb2YgdGhlIGdyaWQgLSB0aGlzIG5lZWRzIHRvIGJlIGRvbmUgQkVGT1JFIHN1cHBseURhdGFEZWZhdWx0c1xuLy8gc28gdGhhdCBub24tc3VicGxvdCB0cmFjZXMgY2FuIHBsYWNlIHRoZW1zZWx2ZXMgaW4gdGhlIGdyaWRcbmZ1bmN0aW9uIHNpemVEZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0KSB7XG4gICAgdmFyIGdyaWRJbiA9IGxheW91dEluLmdyaWQgfHwge307XG4gICAgdmFyIHhBeGVzID0gZ2V0QXhlcyhsYXlvdXRPdXQsIGdyaWRJbiwgJ3gnKTtcbiAgICB2YXIgeUF4ZXMgPSBnZXRBeGVzKGxheW91dE91dCwgZ3JpZEluLCAneScpO1xuXG4gICAgaWYoIWxheW91dEluLmdyaWQgJiYgIXhBeGVzICYmICF5QXhlcykgcmV0dXJuO1xuXG4gICAgdmFyIGhhc1N1YnBsb3RHcmlkID0gQXJyYXkuaXNBcnJheShncmlkSW4uc3VicGxvdHMpICYmIEFycmF5LmlzQXJyYXkoZ3JpZEluLnN1YnBsb3RzWzBdKTtcbiAgICB2YXIgaGFzWGF4ZXMgPSBBcnJheS5pc0FycmF5KHhBeGVzKTtcbiAgICB2YXIgaGFzWWF4ZXMgPSBBcnJheS5pc0FycmF5KHlBeGVzKTtcbiAgICB2YXIgaXNTcGxvbUdlbmVyYXRlZCA9IChcbiAgICAgICAgaGFzWGF4ZXMgJiYgeEF4ZXMgIT09IGdyaWRJbi54YXhlcyAmJlxuICAgICAgICBoYXNZYXhlcyAmJiB5QXhlcyAhPT0gZ3JpZEluLnlheGVzXG4gICAgKTtcblxuICAgIHZhciBkZmx0Um93cywgZGZsdENvbHVtbnM7XG5cbiAgICBpZihoYXNTdWJwbG90R3JpZCkge1xuICAgICAgICBkZmx0Um93cyA9IGdyaWRJbi5zdWJwbG90cy5sZW5ndGg7XG4gICAgICAgIGRmbHRDb2x1bW5zID0gZ3JpZEluLnN1YnBsb3RzWzBdLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZihoYXNZYXhlcykgZGZsdFJvd3MgPSB5QXhlcy5sZW5ndGg7XG4gICAgICAgIGlmKGhhc1hheGVzKSBkZmx0Q29sdW1ucyA9IHhBeGVzLmxlbmd0aDtcbiAgICB9XG5cbiAgICB2YXIgZ3JpZE91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcihsYXlvdXRPdXQsICdncmlkJyk7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShncmlkSW4sIGdyaWRPdXQsIGdyaWRBdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHJvd3MgPSBjb2VyY2UoJ3Jvd3MnLCBkZmx0Um93cyk7XG4gICAgdmFyIGNvbHVtbnMgPSBjb2VyY2UoJ2NvbHVtbnMnLCBkZmx0Q29sdW1ucyk7XG5cbiAgICBpZighKHJvd3MgKiBjb2x1bW5zID4gMSkpIHtcbiAgICAgICAgZGVsZXRlIGxheW91dE91dC5ncmlkO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYoIWhhc1N1YnBsb3RHcmlkICYmICFoYXNYYXhlcyAmJiAhaGFzWWF4ZXMpIHtcbiAgICAgICAgdmFyIHVzZURlZmF1bHRTdWJwbG90cyA9IGNvZXJjZSgncGF0dGVybicpID09PSAnaW5kZXBlbmRlbnQnO1xuICAgICAgICBpZih1c2VEZWZhdWx0U3VicGxvdHMpIGhhc1N1YnBsb3RHcmlkID0gdHJ1ZTtcbiAgICB9XG4gICAgZ3JpZE91dC5faGFzU3VicGxvdEdyaWQgPSBoYXNTdWJwbG90R3JpZDtcblxuICAgIHZhciByb3dPcmRlciA9IGNvZXJjZSgncm93b3JkZXInKTtcbiAgICB2YXIgcmV2ZXJzZWQgPSByb3dPcmRlciA9PT0gJ3RvcCB0byBib3R0b20nO1xuXG4gICAgdmFyIGRmbHRHYXBYID0gaGFzU3VicGxvdEdyaWQgPyAwLjIgOiAwLjE7XG4gICAgdmFyIGRmbHRHYXBZID0gaGFzU3VicGxvdEdyaWQgPyAwLjMgOiAwLjE7XG5cbiAgICB2YXIgZGZsdFNpZGVYLCBkZmx0U2lkZVk7XG4gICAgaWYoaXNTcGxvbUdlbmVyYXRlZCAmJiBsYXlvdXRPdXQuX3NwbG9tR3JpZERmbHQpIHtcbiAgICAgICAgZGZsdFNpZGVYID0gbGF5b3V0T3V0Ll9zcGxvbUdyaWREZmx0LnhzaWRlO1xuICAgICAgICBkZmx0U2lkZVkgPSBsYXlvdXRPdXQuX3NwbG9tR3JpZERmbHQueXNpZGU7XG4gICAgfVxuXG4gICAgZ3JpZE91dC5fZG9tYWlucyA9IHtcbiAgICAgICAgeDogZmlsbEdyaWRQb3NpdGlvbnMoJ3gnLCBjb2VyY2UsIGRmbHRHYXBYLCBkZmx0U2lkZVgsIGNvbHVtbnMpLFxuICAgICAgICB5OiBmaWxsR3JpZFBvc2l0aW9ucygneScsIGNvZXJjZSwgZGZsdEdhcFksIGRmbHRTaWRlWSwgcm93cywgcmV2ZXJzZWQpXG4gICAgfTtcbn1cblxuLy8gY29lcmNlIHggb3IgeSBzaXppbmcgYXR0cmlidXRlcyBhbmQgcmV0dXJuIGFuIGFycmF5IG9mIGRvbWFpbnMgZm9yIHRoaXMgZGlyZWN0aW9uXG5mdW5jdGlvbiBmaWxsR3JpZFBvc2l0aW9ucyhheExldHRlciwgY29lcmNlLCBkZmx0R2FwLCBkZmx0U2lkZSwgbGVuLCByZXZlcnNlZCkge1xuICAgIHZhciBkaXJHYXAgPSBjb2VyY2UoYXhMZXR0ZXIgKyAnZ2FwJywgZGZsdEdhcCk7XG4gICAgdmFyIGRvbWFpbiA9IGNvZXJjZSgnZG9tYWluLicgKyBheExldHRlcik7XG4gICAgY29lcmNlKGF4TGV0dGVyICsgJ3NpZGUnLCBkZmx0U2lkZSk7XG5cbiAgICB2YXIgb3V0ID0gbmV3IEFycmF5KGxlbik7XG4gICAgdmFyIHN0YXJ0ID0gZG9tYWluWzBdO1xuICAgIHZhciBzdGVwID0gKGRvbWFpblsxXSAtIHN0YXJ0KSAvIChsZW4gLSBkaXJHYXApO1xuICAgIHZhciBjZWxsRG9tYWluID0gc3RlcCAqICgxIC0gZGlyR2FwKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIGNlbGxTdGFydCA9IHN0YXJ0ICsgc3RlcCAqIGk7XG4gICAgICAgIG91dFtyZXZlcnNlZCA/IChsZW4gLSAxIC0gaSkgOiBpXSA9IFtjZWxsU3RhcnQsIGNlbGxTdGFydCArIGNlbGxEb21haW5dO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufVxuXG4vLyB0aGUgKGNhcnRlc2lhbikgY29udGVudHMgb2YgdGhlIGdyaWQgLSB0aGlzIG5lZWRzIHRvIGhhcHBlbiBBRlRFUiBzdXBwbHlEYXRhRGVmYXVsdHNcbi8vIHNvIHRoYXQgd2Uga25vdyB3aGF0IGNhcnRlc2lhbiBzdWJwbG90cyBhcmUgYXZhaWxhYmxlXG5mdW5jdGlvbiBjb250ZW50RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgIHZhciBncmlkT3V0ID0gbGF5b3V0T3V0LmdyaWQ7XG4gICAgLy8gbWFrZSBzdXJlIHdlIGdvdCB0byB0aGUgZW5kIG9mIGhhbmRsZUdyaWRTaXppbmdcbiAgICBpZighZ3JpZE91dCB8fCAhZ3JpZE91dC5fZG9tYWlucykgcmV0dXJuO1xuXG4gICAgdmFyIGdyaWRJbiA9IGxheW91dEluLmdyaWQgfHwge307XG4gICAgdmFyIHN1YnBsb3RzID0gbGF5b3V0T3V0Ll9zdWJwbG90cztcbiAgICB2YXIgaGFzU3VicGxvdEdyaWQgPSBncmlkT3V0Ll9oYXNTdWJwbG90R3JpZDtcbiAgICB2YXIgcm93cyA9IGdyaWRPdXQucm93cztcbiAgICB2YXIgY29sdW1ucyA9IGdyaWRPdXQuY29sdW1ucztcbiAgICB2YXIgdXNlRGVmYXVsdFN1YnBsb3RzID0gZ3JpZE91dC5wYXR0ZXJuID09PSAnaW5kZXBlbmRlbnQnO1xuXG4gICAgdmFyIGksIGosIHhJZCwgeUlkLCBzdWJwbG90SWQsIHN1YnBsb3RzT3V0LCB5UG9zO1xuXG4gICAgdmFyIGF4aXNNYXAgPSBncmlkT3V0Ll9heGlzTWFwID0ge307XG5cbiAgICBpZihoYXNTdWJwbG90R3JpZCkge1xuICAgICAgICB2YXIgc3VicGxvdHNJbiA9IGdyaWRJbi5zdWJwbG90cyB8fCBbXTtcbiAgICAgICAgc3VicGxvdHNPdXQgPSBncmlkT3V0LnN1YnBsb3RzID0gbmV3IEFycmF5KHJvd3MpO1xuICAgICAgICB2YXIgaW5kZXggPSAxO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHJvd3M7IGkrKykge1xuICAgICAgICAgICAgdmFyIHJvd091dCA9IHN1YnBsb3RzT3V0W2ldID0gbmV3IEFycmF5KGNvbHVtbnMpO1xuICAgICAgICAgICAgdmFyIHJvd0luID0gc3VicGxvdHNJbltpXSB8fCBbXTtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGNvbHVtbnM7IGorKykge1xuICAgICAgICAgICAgICAgIGlmKHVzZURlZmF1bHRTdWJwbG90cykge1xuICAgICAgICAgICAgICAgICAgICBzdWJwbG90SWQgPSAoaW5kZXggPT09IDEpID8gJ3h5JyA6ICgneCcgKyBpbmRleCArICd5JyArIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXgrKztcbiAgICAgICAgICAgICAgICB9IGVsc2Ugc3VicGxvdElkID0gcm93SW5bal07XG5cbiAgICAgICAgICAgICAgICByb3dPdXRbal0gPSAnJztcblxuICAgICAgICAgICAgICAgIGlmKHN1YnBsb3RzLmNhcnRlc2lhbi5pbmRleE9mKHN1YnBsb3RJZCkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHlQb3MgPSBzdWJwbG90SWQuaW5kZXhPZigneScpO1xuICAgICAgICAgICAgICAgICAgICB4SWQgPSBzdWJwbG90SWQuc2xpY2UoMCwgeVBvcyk7XG4gICAgICAgICAgICAgICAgICAgIHlJZCA9IHN1YnBsb3RJZC5zbGljZSh5UG9zKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoKGF4aXNNYXBbeElkXSAhPT0gdW5kZWZpbmVkICYmIGF4aXNNYXBbeElkXSAhPT0gaikgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIChheGlzTWFwW3lJZF0gIT09IHVuZGVmaW5lZCAmJiBheGlzTWFwW3lJZF0gIT09IGkpXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb3dPdXRbal0gPSBzdWJwbG90SWQ7XG4gICAgICAgICAgICAgICAgICAgIGF4aXNNYXBbeElkXSA9IGo7XG4gICAgICAgICAgICAgICAgICAgIGF4aXNNYXBbeUlkXSA9IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHhBeGVzID0gZ2V0QXhlcyhsYXlvdXRPdXQsIGdyaWRJbiwgJ3gnKTtcbiAgICAgICAgdmFyIHlBeGVzID0gZ2V0QXhlcyhsYXlvdXRPdXQsIGdyaWRJbiwgJ3knKTtcbiAgICAgICAgZ3JpZE91dC54YXhlcyA9IGZpbGxHcmlkQXhlcyh4QXhlcywgc3VicGxvdHMueGF4aXMsIGNvbHVtbnMsIGF4aXNNYXAsICd4Jyk7XG4gICAgICAgIGdyaWRPdXQueWF4ZXMgPSBmaWxsR3JpZEF4ZXMoeUF4ZXMsIHN1YnBsb3RzLnlheGlzLCByb3dzLCBheGlzTWFwLCAneScpO1xuICAgIH1cblxuICAgIHZhciBhbmNob3JzID0gZ3JpZE91dC5fYW5jaG9ycyA9IHt9O1xuICAgIHZhciByZXZlcnNlZCA9IGdyaWRPdXQucm93b3JkZXIgPT09ICd0b3AgdG8gYm90dG9tJztcblxuICAgIGZvcih2YXIgYXhpc0lkIGluIGF4aXNNYXApIHtcbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhpc0lkLmNoYXJBdCgwKTtcbiAgICAgICAgdmFyIHNpZGUgPSBncmlkT3V0W2F4TGV0dGVyICsgJ3NpZGUnXTtcblxuICAgICAgICB2YXIgaTAsIGluYywgaUZpbmFsO1xuXG4gICAgICAgIGlmKHNpZGUubGVuZ3RoIDwgOCkge1xuICAgICAgICAgICAgLy8gZ3JpZCBlZGdlIC0gIGllIG5vdCBcIiogcGxvdFwiIC0gbWFrZSB0aGVzZSBhcyBmcmVlIGF4ZXNcbiAgICAgICAgICAgIC8vIHNpbmNlIHdlJ3JlIG5vdCBndWFyYW50ZWVkIHRvIGhhdmUgYSBzdWJwbG90IHRoZXJlIGF0IGFsbFxuICAgICAgICAgICAgYW5jaG9yc1theGlzSWRdID0gJ2ZyZWUnO1xuICAgICAgICB9IGVsc2UgaWYoYXhMZXR0ZXIgPT09ICd4Jykge1xuICAgICAgICAgICAgaWYoKHNpZGUuY2hhckF0KDApID09PSAndCcpID09PSByZXZlcnNlZCkge1xuICAgICAgICAgICAgICAgIGkwID0gMDtcbiAgICAgICAgICAgICAgICBpbmMgPSAxO1xuICAgICAgICAgICAgICAgIGlGaW5hbCA9IHJvd3M7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGkwID0gcm93cyAtIDE7XG4gICAgICAgICAgICAgICAgaW5jID0gLTE7XG4gICAgICAgICAgICAgICAgaUZpbmFsID0gLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihoYXNTdWJwbG90R3JpZCkge1xuICAgICAgICAgICAgICAgIHZhciBjb2x1bW4gPSBheGlzTWFwW2F4aXNJZF07XG4gICAgICAgICAgICAgICAgZm9yKGkgPSBpMDsgaSAhPT0gaUZpbmFsOyBpICs9IGluYykge1xuICAgICAgICAgICAgICAgICAgICBzdWJwbG90SWQgPSBzdWJwbG90c091dFtpXVtjb2x1bW5dO1xuICAgICAgICAgICAgICAgICAgICBpZighc3VicGxvdElkKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgeVBvcyA9IHN1YnBsb3RJZC5pbmRleE9mKCd5Jyk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHN1YnBsb3RJZC5zbGljZSgwLCB5UG9zKSA9PT0gYXhpc0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbmNob3JzW2F4aXNJZF0gPSBzdWJwbG90SWQuc2xpY2UoeVBvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSBpMDsgaSAhPT0gaUZpbmFsOyBpICs9IGluYykge1xuICAgICAgICAgICAgICAgICAgICB5SWQgPSBncmlkT3V0LnlheGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZihzdWJwbG90cy5jYXJ0ZXNpYW4uaW5kZXhPZihheGlzSWQgKyB5SWQpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5jaG9yc1theGlzSWRdID0geUlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZigoc2lkZS5jaGFyQXQoMCkgPT09ICdsJykpIHtcbiAgICAgICAgICAgICAgICBpMCA9IDA7XG4gICAgICAgICAgICAgICAgaW5jID0gMTtcbiAgICAgICAgICAgICAgICBpRmluYWwgPSBjb2x1bW5zO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpMCA9IGNvbHVtbnMgLSAxO1xuICAgICAgICAgICAgICAgIGluYyA9IC0xO1xuICAgICAgICAgICAgICAgIGlGaW5hbCA9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoaGFzU3VicGxvdEdyaWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcm93ID0gYXhpc01hcFtheGlzSWRdO1xuICAgICAgICAgICAgICAgIGZvcihpID0gaTA7IGkgIT09IGlGaW5hbDsgaSArPSBpbmMpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VicGxvdElkID0gc3VicGxvdHNPdXRbcm93XVtpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoIXN1YnBsb3RJZCkgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIHlQb3MgPSBzdWJwbG90SWQuaW5kZXhPZigneScpO1xuICAgICAgICAgICAgICAgICAgICBpZihzdWJwbG90SWQuc2xpY2UoeVBvcykgPT09IGF4aXNJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5jaG9yc1theGlzSWRdID0gc3VicGxvdElkLnNsaWNlKDAsIHlQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZvcihpID0gaTA7IGkgIT09IGlGaW5hbDsgaSArPSBpbmMpIHtcbiAgICAgICAgICAgICAgICAgICAgeElkID0gZ3JpZE91dC54YXhlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc3VicGxvdHMuY2FydGVzaWFuLmluZGV4T2YoeElkICsgYXhpc0lkKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuY2hvcnNbYXhpc0lkXSA9IHhJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmaWxsR3JpZEF4ZXMoYXhlc0luLCBheGVzQWxsb3dlZCwgbGVuLCBheGlzTWFwLCBheExldHRlcikge1xuICAgIHZhciBvdXQgPSBuZXcgQXJyYXkobGVuKTtcbiAgICB2YXIgaTtcblxuICAgIGZ1bmN0aW9uIGZpbGxPbmVBeGlzKGksIGF4aXNJZCkge1xuICAgICAgICBpZihheGVzQWxsb3dlZC5pbmRleE9mKGF4aXNJZCkgIT09IC0xICYmIGF4aXNNYXBbYXhpc0lkXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBvdXRbaV0gPSBheGlzSWQ7XG4gICAgICAgICAgICBheGlzTWFwW2F4aXNJZF0gPSBpO1xuICAgICAgICB9IGVsc2Ugb3V0W2ldID0gJyc7XG4gICAgfVxuXG4gICAgaWYoQXJyYXkuaXNBcnJheShheGVzSW4pKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBmaWxsT25lQXhpcyhpLCBheGVzSW5baV0pO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZGVmYXVsdCBheGlzIGxpc3QgaXMgdGhlIGZpcnN0IGBsZW5gIGF4aXMgaWRzXG4gICAgICAgIGZpbGxPbmVBeGlzKDAsIGF4TGV0dGVyKTtcbiAgICAgICAgZm9yKGkgPSAxOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGZpbGxPbmVBeGlzKGksIGF4TGV0dGVyICsgKGkgKyAxKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAnY29tcG9uZW50JyxcbiAgICBuYW1lOiAnZ3JpZCcsXG5cbiAgICBzY2hlbWE6IHtcbiAgICAgICAgbGF5b3V0OiB7Z3JpZDogZ3JpZEF0dHJzfVxuICAgIH0sXG5cbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBncmlkQXR0cnMsXG4gICAgc2l6ZURlZmF1bHRzOiBzaXplRGVmYXVsdHMsXG4gICAgY29udGVudERlZmF1bHRzOiBjb250ZW50RGVmYXVsdHNcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL3JlZ2V4XCI6NzM1LFwiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9jb25zdGFudHNcIjo3NzMsXCIuLi8uLi9wbG90cy9kb21haW5cIjo3OTJ9XSw2Mzc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY2FydGVzaWFuQ29uc3RhbnRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cycpO1xudmFyIHRlbXBsYXRlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gdGVtcGxhdGVkQXJyYXkoJ2ltYWdlJywge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc291cmNlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbGF5ZXI6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYmVsb3cnLCAnYWJvdmUnXSxcbiAgICAgICAgZGZsdDogJ2Fib3ZlJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHNpemV4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2l6ZXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBzaXppbmc6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZmlsbCcsICdjb250YWluJywgJ3N0cmV0Y2gnXSxcbiAgICAgICAgZGZsdDogJ2NvbnRhaW4nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgb3BhY2l0eToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgeToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHhhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgZGZsdDogJ2xlZnQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgeWFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWyd0b3AnLCAnbWlkZGxlJywgJ2JvdHRvbSddLFxuICAgICAgICBkZmx0OiAndG9wJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHhyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICdwYXBlcicsXG4gICAgICAgICAgICBjYXJ0ZXNpYW5Db25zdGFudHMuaWRSZWdleC54LnRvU3RyaW5nKClcbiAgICAgICAgXSxcbiAgICAgICAgZGZsdDogJ3BhcGVyJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHlyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICdwYXBlcicsXG4gICAgICAgICAgICBjYXJ0ZXNpYW5Db25zdGFudHMuaWRSZWdleC55LnRvU3RyaW5nKClcbiAgICAgICAgXSxcbiAgICAgICAgZGZsdDogJ3BhcGVyJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdydcbn0pO1xuXG59LHtcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vY29uc3RhbnRzXCI6NzczfV0sNjM4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcbnZhciB0b0xvZ1JhbmdlID0gX2RlcmVxXygnLi4vLi4vbGliL3RvX2xvZ19yYW5nZScpO1xuXG4vKlxuICogY29udmVydENvb3Jkczogd2hlbiBjb252ZXJ0aW5nIGFuIGF4aXMgYmV0d2VlbiBsb2cgYW5kIGxpbmVhclxuICogeW91IG5lZWQgdG8gYWx0ZXIgYW55IGltYWdlcyBvbiB0aGF0IGF4aXMgdG8ga2VlcCB0aGVtXG4gKiBwb2ludGluZyBhdCB0aGUgc2FtZSBkYXRhIHBvaW50LlxuICogSW4gdjIuMCB0aGlzIHdpbGwgYmVjb21lIG9ic29sZXRlIChvciBwZXJoYXBzIHNpemUgd2lsbCBzdGlsbCBuZWVkIGNvbnZlcnNpb24/KVxuICogd2UgY29udmVydCBzaXplIGJ5IGRlY2xhcmluZyB0aGF0IHRoZSBtYXhpbXVtIGV4dGVudCAqaW4gZGF0YSB1bml0cyogc2hvdWxkIGJlXG4gKiB0aGUgc2FtZSwgYXNzdW1pbmcgdGhlIGltYWdlIGlzIGFuY2hvcmVkIGJ5IGl0cyBjZW50ZXIgKGNvdWxkIHJlbW92ZSB0aGF0IHJlc3RyaWN0aW9uXG4gKiBpZiB3ZSB0aGluayBpdCdzIGltcG9ydGFudCkgZXZlbiB0aG91Z2ggdGhlIGFjdHVhbCBsZWZ0IGFuZCByaWdodCB2YWx1ZXMgd2lsbCBub3QgYmVcbiAqIHF1aXRlIHRoZSBzYW1lIHNpbmNlIHRoZSBzY2FsZSBiZWNvbWVzIG5vbmxpbmVhciAoYW5kIGNlbnRyYWwgYW5jaG9yIG1lYW5zIHRoZSBwaXhlbFxuICogY2VudGVyIG9mIHRoZSBpbWFnZSwgbm90IHRoZSBkYXRhIHVuaXRzIGNlbnRlcilcbiAqXG4gKiBnZDogdGhlIHBsb3QgZGl2XG4gKiBheDogdGhlIGF4aXMgYmVpbmcgY2hhbmdlZFxuICogbmV3VHlwZTogdGhlIHR5cGUgaXQncyBnZXR0aW5nXG4gKiBkb0V4dHJhOiBmdW5jdGlvbihhdHRyLCB2YWwpIGZyb20gaW5zaWRlIHJlbGF5b3V0IHRoYXQgc2V0cyB0aGUgYXR0cmlidXRlLlxuICogICAgIFVzZSB0aGlzIHRvIG1ha2UgdGhlIGNoYW5nZXMgYXMgaXQncyBhd2FyZSBpZiBhbnkgb3RoZXIgY2hhbmdlcyBpbiB0aGVcbiAqICAgICBzYW1lIHJlbGF5b3V0IGNhbGwgc2hvdWxkIG92ZXJyaWRlIHRoaXMgY29udmVyc2lvbi5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb252ZXJ0Q29vcmRzKGdkLCBheCwgbmV3VHlwZSwgZG9FeHRyYSkge1xuICAgIGF4ID0gYXggfHwge307XG5cbiAgICB2YXIgdG9Mb2cgPSAobmV3VHlwZSA9PT0gJ2xvZycpICYmIChheC50eXBlID09PSAnbGluZWFyJyk7XG4gICAgdmFyIGZyb21Mb2cgPSAobmV3VHlwZSA9PT0gJ2xpbmVhcicpICYmIChheC50eXBlID09PSAnbG9nJyk7XG5cbiAgICBpZighKHRvTG9nIHx8IGZyb21Mb2cpKSByZXR1cm47XG5cbiAgICB2YXIgaW1hZ2VzID0gZ2QuX2Z1bGxMYXlvdXQuaW1hZ2VzO1xuICAgIHZhciBheExldHRlciA9IGF4Ll9pZC5jaGFyQXQoMCk7XG4gICAgdmFyIGltYWdlO1xuICAgIHZhciBhdHRyUHJlZml4O1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGltYWdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpbWFnZSA9IGltYWdlc1tpXTtcbiAgICAgICAgYXR0clByZWZpeCA9ICdpbWFnZXNbJyArIGkgKyAnXS4nO1xuXG4gICAgICAgIGlmKGltYWdlW2F4TGV0dGVyICsgJ3JlZiddID09PSBheC5faWQpIHtcbiAgICAgICAgICAgIHZhciBjdXJyZW50UG9zID0gaW1hZ2VbYXhMZXR0ZXJdO1xuICAgICAgICAgICAgdmFyIGN1cnJlbnRTaXplID0gaW1hZ2VbJ3NpemUnICsgYXhMZXR0ZXJdO1xuICAgICAgICAgICAgdmFyIG5ld1BvcyA9IG51bGw7XG4gICAgICAgICAgICB2YXIgbmV3U2l6ZSA9IG51bGw7XG5cbiAgICAgICAgICAgIGlmKHRvTG9nKSB7XG4gICAgICAgICAgICAgICAgbmV3UG9zID0gdG9Mb2dSYW5nZShjdXJyZW50UG9zLCBheC5yYW5nZSk7XG5cbiAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSBpbnZlcnNlIG9mIHRoZSBjb252ZXJzaW9uIHdlIGRvIGluIGZyb21Mb2cgYmVsb3dcbiAgICAgICAgICAgICAgICAvLyBzbyB0aGF0IHRoZSBjb252ZXJzaW9uIGlzIHJldmVyc2libGUgKG5vdGljZSB0aGUgZnJvbUxvZyBjb252ZXJzaW9uXG4gICAgICAgICAgICAgICAgLy8gaXMgbGlrZSBzaW5oLCBhbmQgdGhpcyBvbmUgbG9va3MgbGlrZSBhcmNzaW5oKVxuICAgICAgICAgICAgICAgIHZhciBkeCA9IGN1cnJlbnRTaXplIC8gTWF0aC5wb3coMTAsIG5ld1BvcykgLyAyO1xuICAgICAgICAgICAgICAgIG5ld1NpemUgPSAyICogTWF0aC5sb2coZHggKyBNYXRoLnNxcnQoMSArIGR4ICogZHgpKSAvIE1hdGguTE4xMDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV3UG9zID0gTWF0aC5wb3coMTAsIGN1cnJlbnRQb3MpO1xuICAgICAgICAgICAgICAgIG5ld1NpemUgPSBuZXdQb3MgKiAoTWF0aC5wb3coMTAsIGN1cnJlbnRTaXplIC8gMikgLSBNYXRoLnBvdygxMCwgLWN1cnJlbnRTaXplIC8gMikpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpZiBjb252ZXJzaW9uIGZhaWxlZCwgZGVsZXRlIHRoZSB2YWx1ZSBzbyBpdCBjYW4gZ2V0IGEgZGVmYXVsdCBsYXRlciBvblxuICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyhuZXdQb3MpKSB7XG4gICAgICAgICAgICAgICAgbmV3UG9zID0gbnVsbDtcbiAgICAgICAgICAgICAgICBuZXdTaXplID0gbnVsbDtcbiAgICAgICAgICAgIH0gZWxzZSBpZighaXNOdW1lcmljKG5ld1NpemUpKSBuZXdTaXplID0gbnVsbDtcblxuICAgICAgICAgICAgZG9FeHRyYShhdHRyUHJlZml4ICsgYXhMZXR0ZXIsIG5ld1Bvcyk7XG4gICAgICAgICAgICBkb0V4dHJhKGF0dHJQcmVmaXggKyAnc2l6ZScgKyBheExldHRlciwgbmV3U2l6ZSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYi90b19sb2dfcmFuZ2VcIjo3NDUsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDYzOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG52YXIgbmFtZSA9ICdpbWFnZXMnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQpIHtcbiAgICB2YXIgb3B0cyA9IHtcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgaGFuZGxlSXRlbURlZmF1bHRzOiBpbWFnZURlZmF1bHRzXG4gICAgfTtcblxuICAgIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgb3B0cyk7XG59O1xuXG5cbmZ1bmN0aW9uIGltYWdlRGVmYXVsdHMoaW1hZ2VJbiwgaW1hZ2VPdXQsIGZ1bGxMYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShpbWFnZUluLCBpbWFnZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHNvdXJjZSA9IGNvZXJjZSgnc291cmNlJyk7XG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnLCAhIXNvdXJjZSk7XG5cbiAgICBpZighdmlzaWJsZSkgcmV0dXJuIGltYWdlT3V0O1xuXG4gICAgY29lcmNlKCdsYXllcicpO1xuICAgIGNvZXJjZSgneGFuY2hvcicpO1xuICAgIGNvZXJjZSgneWFuY2hvcicpO1xuICAgIGNvZXJjZSgnc2l6ZXgnKTtcbiAgICBjb2VyY2UoJ3NpemV5Jyk7XG4gICAgY29lcmNlKCdzaXppbmcnKTtcbiAgICBjb2VyY2UoJ29wYWNpdHknKTtcblxuICAgIHZhciBnZE1vY2sgPSB7IF9mdWxsTGF5b3V0OiBmdWxsTGF5b3V0IH07XG4gICAgdmFyIGF4TGV0dGVycyA9IFsneCcsICd5J107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMjsgaSsrKSB7XG4gICAgICAgIC8vICdwYXBlcicgaXMgdGhlIGZhbGxiYWNrIGF4cmVmXG4gICAgICAgIHZhciBheExldHRlciA9IGF4TGV0dGVyc1tpXTtcbiAgICAgICAgdmFyIGF4UmVmID0gQXhlcy5jb2VyY2VSZWYoaW1hZ2VJbiwgaW1hZ2VPdXQsIGdkTW9jaywgYXhMZXR0ZXIsICdwYXBlcicpO1xuXG4gICAgICAgIGlmKGF4UmVmICE9PSAncGFwZXInKSB7XG4gICAgICAgICAgICB2YXIgYXggPSBBeGVzLmdldEZyb21JZChnZE1vY2ssIGF4UmVmKTtcbiAgICAgICAgICAgIGF4Ll9pbWdJbmRpY2VzLnB1c2goaW1hZ2VPdXQuX2luZGV4KTtcbiAgICAgICAgfVxuXG4gICAgICAgIEF4ZXMuY29lcmNlUG9zaXRpb24oaW1hZ2VPdXQsIGdkTW9jaywgY29lcmNlLCBheFJlZiwgYXhMZXR0ZXIsIDApO1xuICAgIH1cblxuICAgIHJldHVybiBpbWFnZU91dDtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHNcIjo3NjMsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4vYXR0cmlidXRlc1wiOjYzN31dLDY0MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uL2RyYXdpbmcnKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciB4bWxuc05hbWVzcGFjZXMgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRyYXcoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBpbWFnZURhdGFBYm92ZSA9IFtdO1xuICAgIHZhciBpbWFnZURhdGFTdWJwbG90ID0ge307XG4gICAgdmFyIGltYWdlRGF0YUJlbG93ID0gW107XG4gICAgdmFyIHN1YnBsb3Q7XG4gICAgdmFyIGk7XG5cbiAgICAvLyBTb3J0IGludG8gdG9wLCBzdWJwbG90LCBhbmQgYm90dG9tIGxheWVyc1xuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxMYXlvdXQuaW1hZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpbWcgPSBmdWxsTGF5b3V0LmltYWdlc1tpXTtcblxuICAgICAgICBpZihpbWcudmlzaWJsZSkge1xuICAgICAgICAgICAgaWYoaW1nLmxheWVyID09PSAnYmVsb3cnICYmIGltZy54cmVmICE9PSAncGFwZXInICYmIGltZy55cmVmICE9PSAncGFwZXInKSB7XG4gICAgICAgICAgICAgICAgc3VicGxvdCA9IGltZy54cmVmICsgaW1nLnlyZWY7XG5cbiAgICAgICAgICAgICAgICB2YXIgcGxvdGluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90XTtcblxuICAgICAgICAgICAgICAgIGlmKCFwbG90aW5mbykge1xuICAgICAgICAgICAgICAgICAgICAvLyBGYWxsIGJhY2sgdG8gX2ltYWdlTG93ZXJMYXllciBpbiBjYXNlIHRoZSByZXF1ZXN0ZWQgc3VicGxvdCBkb2Vzbid0IGV4aXN0LlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGNhbiBoYXBwZW4gaWYgeW91IHJlZmVyZW5jZSB0aGUgaW1hZ2UgdG8gYW4geCAvIHkgYXhpcyBjb21iaW5hdGlvblxuICAgICAgICAgICAgICAgICAgICAvLyB0aGF0IGRvZXNuJ3QgaGF2ZSBhbnkgZGF0YSBvbiBpdCAoYW5kIGxheWVyIGlzIGJlbG93KVxuICAgICAgICAgICAgICAgICAgICBpbWFnZURhdGFCZWxvdy5wdXNoKGltZyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKHBsb3RpbmZvLm1haW5wbG90KSB7XG4gICAgICAgICAgICAgICAgICAgIHN1YnBsb3QgPSBwbG90aW5mby5tYWlucGxvdC5pZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZighaW1hZ2VEYXRhU3VicGxvdFtzdWJwbG90XSkge1xuICAgICAgICAgICAgICAgICAgICBpbWFnZURhdGFTdWJwbG90W3N1YnBsb3RdID0gW107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGltYWdlRGF0YVN1YnBsb3Rbc3VicGxvdF0ucHVzaChpbWcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGltZy5sYXllciA9PT0gJ2Fib3ZlJykge1xuICAgICAgICAgICAgICAgIGltYWdlRGF0YUFib3ZlLnB1c2goaW1nKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaW1hZ2VEYXRhQmVsb3cucHVzaChpbWcpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICB2YXIgYW5jaG9ycyA9IHtcbiAgICAgICAgeDoge1xuICAgICAgICAgICAgbGVmdDogeyBzaXppbmc6ICd4TWluJywgb2Zmc2V0OiAwIH0sXG4gICAgICAgICAgICBjZW50ZXI6IHsgc2l6aW5nOiAneE1pZCcsIG9mZnNldDogLTEgLyAyIH0sXG4gICAgICAgICAgICByaWdodDogeyBzaXppbmc6ICd4TWF4Jywgb2Zmc2V0OiAtMSB9XG4gICAgICAgIH0sXG4gICAgICAgIHk6IHtcbiAgICAgICAgICAgIHRvcDogeyBzaXppbmc6ICdZTWluJywgb2Zmc2V0OiAwIH0sXG4gICAgICAgICAgICBtaWRkbGU6IHsgc2l6aW5nOiAnWU1pZCcsIG9mZnNldDogLTEgLyAyIH0sXG4gICAgICAgICAgICBib3R0b206IHsgc2l6aW5nOiAnWU1heCcsIG9mZnNldDogLTEgfVxuICAgICAgICB9XG4gICAgfTtcblxuXG4gICAgLy8gSW1hZ2VzIG11c3QgYmUgY29udmVydGVkIHRvIGRhdGFVUkwncyBmb3IgZXhwb3J0aW5nLlxuICAgIGZ1bmN0aW9uIHNldEltYWdlKGQpIHtcbiAgICAgICAgdmFyIHRoaXNJbWFnZSA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBpZih0aGlzLmltZyAmJiB0aGlzLmltZy5zcmMgPT09IGQuc291cmNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzSW1hZ2UuYXR0cigneG1sbnMnLCB4bWxuc05hbWVzcGFjZXMuc3ZnKTtcblxuICAgICAgICB2YXIgaW1hZ2VQcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgICAgICAgdmFyIGltZyA9IG5ldyBJbWFnZSgpO1xuICAgICAgICAgICAgdGhpcy5pbWcgPSBpbWc7XG5cbiAgICAgICAgICAgIC8vIElmIG5vdCBzZXQsIGEgYHRhaW50ZWQgY2FudmFzYCBlcnJvciBpcyB0aHJvd25cbiAgICAgICAgICAgIGltZy5zZXRBdHRyaWJ1dGUoJ2Nyb3NzT3JpZ2luJywgJ2Fub255bW91cycpO1xuICAgICAgICAgICAgaW1nLm9uZXJyb3IgPSBlcnJvckhhbmRsZXI7XG4gICAgICAgICAgICBpbWcub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgICAgIGNhbnZhcy53aWR0aCA9IHRoaXMud2lkdGg7XG4gICAgICAgICAgICAgICAgY2FudmFzLmhlaWdodCA9IHRoaXMuaGVpZ2h0O1xuXG4gICAgICAgICAgICAgICAgdmFyIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICAgICAgICAgIGN0eC5kcmF3SW1hZ2UodGhpcywgMCwgMCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgZGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuXG4gICAgICAgICAgICAgICAgdGhpc0ltYWdlLmF0dHIoJ3hsaW5rOmhyZWYnLCBkYXRhVVJMKTtcblxuICAgICAgICAgICAgICAgIC8vIHJlc29sdmUgcHJvbWlzZSBpbiBvbmxvYWQgaGFuZGxlciBpbnN0ZWFkIG9mIG9uICdsb2FkJyB0byBzdXBwb3J0IElFMTFcbiAgICAgICAgICAgICAgICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzE2ODVcbiAgICAgICAgICAgICAgICAvLyBmb3IgbW9yZSBkZXRhaWxzXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfTtcblxuXG4gICAgICAgICAgICB0aGlzSW1hZ2Uub24oJ2Vycm9yJywgZXJyb3JIYW5kbGVyKTtcblxuICAgICAgICAgICAgaW1nLnNyYyA9IGQuc291cmNlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvckhhbmRsZXIoKSB7XG4gICAgICAgICAgICAgICAgdGhpc0ltYWdlLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcblxuICAgICAgICBnZC5fcHJvbWlzZXMucHVzaChpbWFnZVByb21pc2UpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFwcGx5QXR0cmlidXRlcyhkKSB7XG4gICAgICAgIHZhciB0aGlzSW1hZ2UgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgLy8gQXhlcyBpZiBzcGVjaWZpZWRcbiAgICAgICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIGQueHJlZik7XG4gICAgICAgIHZhciB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBkLnlyZWYpO1xuXG4gICAgICAgIHZhciBzaXplID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICAgICAgdmFyIHdpZHRoID0geGEgPyBNYXRoLmFicyh4YS5sMnAoZC5zaXpleCkgLSB4YS5sMnAoMCkpIDogZC5zaXpleCAqIHNpemUudztcbiAgICAgICAgdmFyIGhlaWdodCA9IHlhID8gTWF0aC5hYnMoeWEubDJwKGQuc2l6ZXkpIC0geWEubDJwKDApKSA6IGQuc2l6ZXkgKiBzaXplLmg7XG5cbiAgICAgICAgLy8gT2Zmc2V0cyBmb3IgYW5jaG9yIHBvc2l0aW9uaW5nXG4gICAgICAgIHZhciB4T2Zmc2V0ID0gd2lkdGggKiBhbmNob3JzLnhbZC54YW5jaG9yXS5vZmZzZXQ7XG4gICAgICAgIHZhciB5T2Zmc2V0ID0gaGVpZ2h0ICogYW5jaG9ycy55W2QueWFuY2hvcl0ub2Zmc2V0O1xuXG4gICAgICAgIHZhciBzaXppbmcgPSBhbmNob3JzLnhbZC54YW5jaG9yXS5zaXppbmcgKyBhbmNob3JzLnlbZC55YW5jaG9yXS5zaXppbmc7XG5cbiAgICAgICAgLy8gRmluYWwgcG9zaXRpb25zXG4gICAgICAgIHZhciB4UG9zID0gKHhhID8geGEucjJwKGQueCkgKyB4YS5fb2Zmc2V0IDogZC54ICogc2l6ZS53ICsgc2l6ZS5sKSArIHhPZmZzZXQ7XG4gICAgICAgIHZhciB5UG9zID0gKHlhID8geWEucjJwKGQueSkgKyB5YS5fb2Zmc2V0IDogc2l6ZS5oIC0gZC55ICogc2l6ZS5oICsgc2l6ZS50KSArIHlPZmZzZXQ7XG5cbiAgICAgICAgLy8gQ29uc3RydWN0IHRoZSBwcm9wZXIgYXNwZWN0UmF0aW8gYXR0cmlidXRlXG4gICAgICAgIHN3aXRjaChkLnNpemluZykge1xuICAgICAgICAgICAgY2FzZSAnZmlsbCc6XG4gICAgICAgICAgICAgICAgc2l6aW5nICs9ICcgc2xpY2UnO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlICdzdHJldGNoJzpcbiAgICAgICAgICAgICAgICBzaXppbmcgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzSW1hZ2UuYXR0cih7XG4gICAgICAgICAgICB4OiB4UG9zLFxuICAgICAgICAgICAgeTogeVBvcyxcbiAgICAgICAgICAgIHdpZHRoOiB3aWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgICAgcHJlc2VydmVBc3BlY3RSYXRpbzogc2l6aW5nLFxuICAgICAgICAgICAgb3BhY2l0eTogZC5vcGFjaXR5XG4gICAgICAgIH0pO1xuXG5cbiAgICAgICAgLy8gU2V0IHByb3BlciBjbGlwcGluZyBvbiBpbWFnZXNcbiAgICAgICAgdmFyIHhJZCA9IHhhID8geGEuX2lkIDogJyc7XG4gICAgICAgIHZhciB5SWQgPSB5YSA/IHlhLl9pZCA6ICcnO1xuICAgICAgICB2YXIgY2xpcEF4ZXMgPSB4SWQgKyB5SWQ7XG5cbiAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKFxuICAgICAgICAgICAgdGhpc0ltYWdlLFxuICAgICAgICAgICAgY2xpcEF4ZXMgPyAoJ2NsaXAnICsgZnVsbExheW91dC5fdWlkICsgY2xpcEF4ZXMpIDogbnVsbCxcbiAgICAgICAgICAgIGdkXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgdmFyIGltYWdlc0JlbG93ID0gZnVsbExheW91dC5faW1hZ2VMb3dlckxheWVyLnNlbGVjdEFsbCgnaW1hZ2UnKVxuICAgICAgICAuZGF0YShpbWFnZURhdGFCZWxvdyk7XG4gICAgdmFyIGltYWdlc0Fib3ZlID0gZnVsbExheW91dC5faW1hZ2VVcHBlckxheWVyLnNlbGVjdEFsbCgnaW1hZ2UnKVxuICAgICAgICAuZGF0YShpbWFnZURhdGFBYm92ZSk7XG5cbiAgICBpbWFnZXNCZWxvdy5lbnRlcigpLmFwcGVuZCgnaW1hZ2UnKTtcbiAgICBpbWFnZXNBYm92ZS5lbnRlcigpLmFwcGVuZCgnaW1hZ2UnKTtcblxuICAgIGltYWdlc0JlbG93LmV4aXQoKS5yZW1vdmUoKTtcbiAgICBpbWFnZXNBYm92ZS5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBpbWFnZXNCZWxvdy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgc2V0SW1hZ2UuYmluZCh0aGlzKShkKTtcbiAgICAgICAgYXBwbHlBdHRyaWJ1dGVzLmJpbmQodGhpcykoZCk7XG4gICAgfSk7XG4gICAgaW1hZ2VzQWJvdmUuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHNldEltYWdlLmJpbmQodGhpcykoZCk7XG4gICAgICAgIGFwcGx5QXR0cmlidXRlcy5iaW5kKHRoaXMpKGQpO1xuICAgIH0pO1xuXG4gICAgdmFyIGFsbFN1YnBsb3RzID0gT2JqZWN0LmtleXMoZnVsbExheW91dC5fcGxvdHMpO1xuICAgIGZvcihpID0gMDsgaSA8IGFsbFN1YnBsb3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHN1YnBsb3QgPSBhbGxTdWJwbG90c1tpXTtcbiAgICAgICAgdmFyIHN1YnBsb3RPYmogPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90XTtcblxuICAgICAgICAvLyBmaWx0ZXIgb3V0IG92ZXJsYWlkIHBsb3RzICh3aGljaCBoYXZkIHRoZWlyIGltYWdlcyBvbiB0aGUgbWFpbiBwbG90KVxuICAgICAgICAvLyBhbmQgZ2wyZCBwbG90cyAod2hpY2ggZG9uJ3Qgc3VwcG9ydCBiZWxvdyBpbWFnZXMsIGF0IGxlYXN0IG5vdCB5ZXQpXG4gICAgICAgIGlmKCFzdWJwbG90T2JqLmltYWdlbGF5ZXIpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBpbWFnZXNPblN1YnBsb3QgPSBzdWJwbG90T2JqLmltYWdlbGF5ZXIuc2VsZWN0QWxsKCdpbWFnZScpXG4gICAgICAgICAgICAvLyBldmVuIGlmIHRoZXJlIGFyZSBubyBpbWFnZXMgb24gdGhpcyBzdWJwbG90LCB3ZSBuZWVkIHRvIHJ1blxuICAgICAgICAgICAgLy8gZW50ZXIgYW5kIGV4aXQgaW4gY2FzZSB0aGVyZSB3ZXJlIHByZXZpb3VzbHlcbiAgICAgICAgICAgIC5kYXRhKGltYWdlRGF0YVN1YnBsb3Rbc3VicGxvdF0gfHwgW10pO1xuXG4gICAgICAgIGltYWdlc09uU3VicGxvdC5lbnRlcigpLmFwcGVuZCgnaW1hZ2UnKTtcbiAgICAgICAgaW1hZ2VzT25TdWJwbG90LmV4aXQoKS5yZW1vdmUoKTtcblxuICAgICAgICBpbWFnZXNPblN1YnBsb3QuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBzZXRJbWFnZS5iaW5kKHRoaXMpKGQpO1xuICAgICAgICAgICAgYXBwbHlBdHRyaWJ1dGVzLmJpbmQodGhpcykoZCk7XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXNcIjo2OTYsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL2RyYXdpbmdcIjo2MTQsXCJkM1wiOjE2M31dLDY0MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICdjb21wb25lbnQnLFxuICAgIG5hbWU6ICdpbWFnZXMnLFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBpbmNsdWRlQmFzZVBsb3Q6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9pbmNsdWRlX2NvbXBvbmVudHMnKSgnaW1hZ2VzJyksXG5cbiAgICBkcmF3OiBfZGVyZXFfKCcuL2RyYXcnKSxcblxuICAgIGNvbnZlcnRDb29yZHM6IF9kZXJlcV8oJy4vY29udmVydF9jb29yZHMnKVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vaW5jbHVkZV9jb21wb25lbnRzXCI6Nzc3LFwiLi9hdHRyaWJ1dGVzXCI6NjM3LFwiLi9jb252ZXJ0X2Nvb3Jkc1wiOjYzOCxcIi4vZGVmYXVsdHNcIjo2MzksXCIuL2RyYXdcIjo2NDB9XSw2NDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZm9udEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRycyA9IF9kZXJlcV8oJy4uL2NvbG9yL2F0dHJpYnV0ZXMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBiZ2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2xlZ2VuZCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm9yZGVyY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3JkZXJ3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSksXG4gICAgb3JpZW50YXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsndicsICdoJ10sXG4gICAgICAgIGRmbHQ6ICd2JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0cmFjZW9yZGVyOiB7XG4gICAgICAgIHZhbFR5cGU6ICdmbGFnbGlzdCcsXG4gICAgICAgIGZsYWdzOiBbJ3JldmVyc2VkJywgJ2dyb3VwZWQnXSxcbiAgICAgICAgZXh0cmFzOiBbJ25vcm1hbCddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRyYWNlZ3JvdXBnYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMTAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2xlZ2VuZCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaXRlbXNpemluZzoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWyd0cmFjZScsICdjb25zdGFudCddLFxuICAgICAgICBkZmx0OiAndHJhY2UnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgaXRlbWNsaWNrOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3RvZ2dsZScsICd0b2dnbGVvdGhlcnMnLCBmYWxzZV0sXG4gICAgICAgIGRmbHQ6ICd0b2dnbGUnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGl0ZW1kb3VibGVjbGljazoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWyd0b2dnbGUnLCAndG9nZ2xlb3RoZXJzJywgZmFsc2VdLFxuICAgICAgICBkZmx0OiAndG9nZ2xlb3RoZXJzJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgZGZsdDogMS4wMixcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgZGZsdDogJ2xlZnQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAndG9wJywgJ21pZGRsZScsICdib3R0b20nXSxcbiAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsZWdlbmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHVpcmV2aXNpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHZhbGlnbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWyd0b3AnLCAnbWlkZGxlJywgJ2JvdHRvbSddLFxuICAgICAgICBkZmx0OiAnbWlkZGxlJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbGVnZW5kJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2xlZ2VuZCdcbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzXCI6NzkzLFwiLi4vY29sb3IvYXR0cmlidXRlc1wiOjU5Mn1dLDY0MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHNjcm9sbEJhcldpZHRoOiA2LFxuICAgIHNjcm9sbEJhck1pbkhlaWdodDogMjAsXG4gICAgc2Nyb2xsQmFyQ29sb3I6ICcjODA4QkE0JyxcbiAgICBzY3JvbGxCYXJNYXJnaW46IDQsXG4gICAgdGV4dE9mZnNldFg6IDQwXG59O1xuXG59LHt9XSw2NDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIFRlbXBsYXRlID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xuXG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIGJhc2VQbG90TGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbGVnZW5kRGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICB2YXIgY29udGFpbmVySW4gPSBsYXlvdXRJbi5sZWdlbmQgfHwge307XG5cbiAgICB2YXIgbGVnZW5kVHJhY2VDb3VudCA9IDA7XG4gICAgdmFyIGxlZ2VuZFJlYWxseUhhc0FUcmFjZSA9IGZhbHNlO1xuICAgIHZhciBkZWZhdWx0T3JkZXIgPSAnbm9ybWFsJztcblxuICAgIHZhciBkZWZhdWx0WCwgZGVmYXVsdFksIGRlZmF1bHRYQW5jaG9yLCBkZWZhdWx0WUFuY2hvcjtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2UgPSBmdWxsRGF0YVtpXTtcblxuICAgICAgICBpZighdHJhY2UudmlzaWJsZSkgY29udGludWU7XG5cbiAgICAgICAgLy8gTm90ZSB0aGF0IHdlIGV4cGxpY2l0bHkgY291bnQgYW55IHRyYWNlIHRoYXQgaXMgZWl0aGVyIHNob3duIG9yXG4gICAgICAgIC8vICp3b3VsZCogYmUgc2hvd24gYnkgZGVmYXVsdCwgdG93YXJkIHRoZSB0d28gdHJhY2VzIHlvdSBuZWVkIHRvXG4gICAgICAgIC8vIGVuc3VyZSB0aGUgbGVnZW5kIGlzIHNob3duIGJ5IGRlZmF1bHQsIGJlY2F1c2UgdGhpcyBjYW4gc3RpbGwgaGVscFxuICAgICAgICAvLyBkaXNhbWJpZ3VhdGUuXG4gICAgICAgIGlmKHRyYWNlLnNob3dsZWdlbmQgfHwgdHJhY2UuX2RmbHRTaG93TGVnZW5kKSB7XG4gICAgICAgICAgICBsZWdlbmRUcmFjZUNvdW50Kys7XG4gICAgICAgICAgICBpZih0cmFjZS5zaG93bGVnZW5kKSB7XG4gICAgICAgICAgICAgICAgbGVnZW5kUmVhbGx5SGFzQVRyYWNlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAvLyBBbHdheXMgc2hvdyB0aGUgbGVnZW5kIGJ5IGRlZmF1bHQgaWYgdGhlcmUncyBhIHBpZSxcbiAgICAgICAgICAgICAgICAvLyBvciBpZiB0aGVyZSdzIG9ubHkgb25lIHRyYWNlIGJ1dCBpdCdzIGV4cGxpY2l0bHkgc2hvd25cbiAgICAgICAgICAgICAgICBpZihSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAncGllLWxpa2UnKSB8fFxuICAgICAgICAgICAgICAgICAgICB0cmFjZS5faW5wdXQuc2hvd2xlZ2VuZCA9PT0gdHJ1ZVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBsZWdlbmRUcmFjZUNvdW50Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdiYXInKSAmJiBsYXlvdXRPdXQuYmFybW9kZSA9PT0gJ3N0YWNrJykgfHxcbiAgICAgICAgICAgICAgICBbJ3RvbmV4dHgnLCAndG9uZXh0eSddLmluZGV4T2YodHJhY2UuZmlsbCkgIT09IC0xKSB7XG4gICAgICAgICAgICBkZWZhdWx0T3JkZXIgPSBoZWxwZXJzLmlzR3JvdXBlZCh7dHJhY2VvcmRlcjogZGVmYXVsdE9yZGVyfSkgP1xuICAgICAgICAgICAgICAgICdncm91cGVkK3JldmVyc2VkJyA6ICdyZXZlcnNlZCc7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0cmFjZS5sZWdlbmRncm91cCAhPT0gdW5kZWZpbmVkICYmIHRyYWNlLmxlZ2VuZGdyb3VwICE9PSAnJykge1xuICAgICAgICAgICAgZGVmYXVsdE9yZGVyID0gaGVscGVycy5pc1JldmVyc2VkKHt0cmFjZW9yZGVyOiBkZWZhdWx0T3JkZXJ9KSA/XG4gICAgICAgICAgICAgICAgJ3JldmVyc2VkK2dyb3VwZWQnIDogJ2dyb3VwZWQnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHNob3dMZWdlbmQgPSBMaWIuY29lcmNlKGxheW91dEluLCBsYXlvdXRPdXQsXG4gICAgICAgIGJhc2VQbG90TGF5b3V0QXR0cmlidXRlcywgJ3Nob3dsZWdlbmQnLFxuICAgICAgICBsZWdlbmRSZWFsbHlIYXNBVHJhY2UgJiYgbGVnZW5kVHJhY2VDb3VudCA+IDEpO1xuXG4gICAgaWYoc2hvd0xlZ2VuZCA9PT0gZmFsc2UgJiYgIWNvbnRhaW5lckluLnVpcmV2aXNpb24pIHJldHVybjtcblxuICAgIHZhciBjb250YWluZXJPdXQgPSBUZW1wbGF0ZS5uZXdDb250YWluZXIobGF5b3V0T3V0LCAnbGVnZW5kJyk7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3VpcmV2aXNpb24nLCBsYXlvdXRPdXQudWlyZXZpc2lvbik7XG5cbiAgICBpZihzaG93TGVnZW5kID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgY29lcmNlKCdiZ2NvbG9yJywgbGF5b3V0T3V0LnBhcGVyX2JnY29sb3IpO1xuICAgIGNvZXJjZSgnYm9yZGVyY29sb3InKTtcbiAgICBjb2VyY2UoJ2JvcmRlcndpZHRoJyk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnZm9udCcsIGxheW91dE91dC5mb250KTtcblxuICAgIGNvZXJjZSgnb3JpZW50YXRpb24nKTtcbiAgICBpZihjb250YWluZXJPdXQub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICB2YXIgeGF4aXMgPSBsYXlvdXRJbi54YXhpcztcbiAgICAgICAgaWYoUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdyYW5nZXNsaWRlcicsICdpc1Zpc2libGUnKSh4YXhpcykpIHtcbiAgICAgICAgICAgIGRlZmF1bHRYID0gMDtcbiAgICAgICAgICAgIGRlZmF1bHRYQW5jaG9yID0gJ2xlZnQnO1xuICAgICAgICAgICAgZGVmYXVsdFkgPSAxLjE7XG4gICAgICAgICAgICBkZWZhdWx0WUFuY2hvciA9ICdib3R0b20nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVmYXVsdFggPSAwO1xuICAgICAgICAgICAgZGVmYXVsdFhBbmNob3IgPSAnbGVmdCc7XG4gICAgICAgICAgICBkZWZhdWx0WSA9IC0wLjE7XG4gICAgICAgICAgICBkZWZhdWx0WUFuY2hvciA9ICd0b3AnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29lcmNlKCd0cmFjZW9yZGVyJywgZGVmYXVsdE9yZGVyKTtcbiAgICBpZihoZWxwZXJzLmlzR3JvdXBlZChsYXlvdXRPdXQubGVnZW5kKSkgY29lcmNlKCd0cmFjZWdyb3VwZ2FwJyk7XG5cbiAgICBjb2VyY2UoJ2l0ZW1zaXppbmcnKTtcblxuICAgIGNvZXJjZSgnaXRlbWNsaWNrJyk7XG4gICAgY29lcmNlKCdpdGVtZG91YmxlY2xpY2snKTtcblxuICAgIGNvZXJjZSgneCcsIGRlZmF1bHRYKTtcbiAgICBjb2VyY2UoJ3hhbmNob3InLCBkZWZhdWx0WEFuY2hvcik7XG4gICAgY29lcmNlKCd5JywgZGVmYXVsdFkpO1xuICAgIGNvZXJjZSgneWFuY2hvcicsIGRlZmF1bHRZQW5jaG9yKTtcbiAgICBjb2VyY2UoJ3ZhbGlnbicpO1xuICAgIExpYi5ub25lT3JBbGwoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgWyd4JywgJ3knXSk7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9wbG90cy9sYXlvdXRfYXR0cmlidXRlc1wiOjgxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9hdHRyaWJ1dGVzXCI6NjQyLFwiLi9oZWxwZXJzXCI6NjQ4fV0sNjQ1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIFBsb3RzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvcGxvdHMnKTtcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgRXZlbnRzID0gX2RlcmVxXygnLi4vLi4vbGliL2V2ZW50cycpO1xudmFyIGRyYWdFbGVtZW50ID0gX2RlcmVxXygnLi4vZHJhZ2VsZW1lbnQnKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vZHJhd2luZycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vY29sb3InKTtcbnZhciBzdmdUZXh0VXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcbnZhciBoYW5kbGVDbGljayA9IF9kZXJlcV8oJy4vaGFuZGxlX2NsaWNrJyk7XG5cbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIGFsaWdubWVudENvbnN0YW50cyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKTtcbnZhciBMSU5FX1NQQUNJTkcgPSBhbGlnbm1lbnRDb25zdGFudHMuTElORV9TUEFDSU5HO1xudmFyIEZST01fVEwgPSBhbGlnbm1lbnRDb25zdGFudHMuRlJPTV9UTDtcbnZhciBGUk9NX0JSID0gYWxpZ25tZW50Q29uc3RhbnRzLkZST01fQlI7XG5cbnZhciBnZXRMZWdlbmREYXRhID0gX2RlcmVxXygnLi9nZXRfbGVnZW5kX2RhdGEnKTtcbnZhciBzdHlsZSA9IF9kZXJlcV8oJy4vc3R5bGUnKTtcbnZhciBoZWxwZXJzID0gX2RlcmVxXygnLi9oZWxwZXJzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZHJhdyhnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGNsaXBJZCA9ICdsZWdlbmQnICsgZnVsbExheW91dC5fdWlkO1xuXG4gICAgaWYoIWZ1bGxMYXlvdXQuX2luZm9sYXllciB8fCAhZ2QuY2FsY2RhdGEpIHJldHVybjtcblxuICAgIGlmKCFnZC5fbGVnZW5kTW91c2VEb3duVGltZSkgZ2QuX2xlZ2VuZE1vdXNlRG93blRpbWUgPSAwO1xuXG4gICAgdmFyIG9wdHMgPSBmdWxsTGF5b3V0LmxlZ2VuZDtcbiAgICB2YXIgbGVnZW5kRGF0YSA9IGZ1bGxMYXlvdXQuc2hvd2xlZ2VuZCAmJiBnZXRMZWdlbmREYXRhKGdkLmNhbGNkYXRhLCBvcHRzKTtcbiAgICB2YXIgaGlkZGVuU2xpY2VzID0gZnVsbExheW91dC5oaWRkZW5sYWJlbHMgfHwgW107XG5cbiAgICBpZighZnVsbExheW91dC5zaG93bGVnZW5kIHx8ICFsZWdlbmREYXRhLmxlbmd0aCkge1xuICAgICAgICBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuc2VsZWN0QWxsKCcubGVnZW5kJykucmVtb3ZlKCk7XG4gICAgICAgIGZ1bGxMYXlvdXQuX3RvcGRlZnMuc2VsZWN0KCcjJyArIGNsaXBJZCkucmVtb3ZlKCk7XG5cbiAgICAgICAgUGxvdHMuYXV0b01hcmdpbihnZCwgJ2xlZ2VuZCcpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIG1heExlbmd0aCA9IDA7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxlZ2VuZERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGxlZ2VuZERhdGFbaV0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBpdGVtID0gbGVnZW5kRGF0YVtpXVtqXVswXTtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IGl0ZW0udHJhY2U7XG4gICAgICAgICAgICB2YXIgaXNQaWVMaWtlID0gUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3BpZS1saWtlJyk7XG4gICAgICAgICAgICB2YXIgbmFtZSA9IGlzUGllTGlrZSA/IGl0ZW0ubGFiZWwgOiB0cmFjZS5uYW1lO1xuICAgICAgICAgICAgbWF4TGVuZ3RoID0gTWF0aC5tYXgobWF4TGVuZ3RoLCBuYW1lICYmIG5hbWUubGVuZ3RoIHx8IDApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGZpcnN0UmVuZGVyID0gZmFsc2U7XG4gICAgdmFyIGxlZ2VuZCA9IExpYi5lbnN1cmVTaW5nbGUoZnVsbExheW91dC5faW5mb2xheWVyLCAnZycsICdsZWdlbmQnLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cigncG9pbnRlci1ldmVudHMnLCAnYWxsJyk7XG4gICAgICAgIGZpcnN0UmVuZGVyID0gdHJ1ZTtcbiAgICB9KTtcblxuICAgIHZhciBjbGlwUGF0aCA9IExpYi5lbnN1cmVTaW5nbGVCeUlkKGZ1bGxMYXlvdXQuX3RvcGRlZnMsICdjbGlwUGF0aCcsIGNsaXBJZCwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmFwcGVuZCgncmVjdCcpO1xuICAgIH0pO1xuXG4gICAgdmFyIGJnID0gTGliLmVuc3VyZVNpbmdsZShsZWdlbmQsICdyZWN0JywgJ2JnJywgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoJ3NoYXBlLXJlbmRlcmluZycsICdjcmlzcEVkZ2VzJyk7XG4gICAgfSk7XG5cbiAgICBiZy5jYWxsKENvbG9yLnN0cm9rZSwgb3B0cy5ib3JkZXJjb2xvcilcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgb3B0cy5iZ2NvbG9yKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIG9wdHMuYm9yZGVyd2lkdGggKyAncHgnKTtcblxuICAgIHZhciBzY3JvbGxCb3ggPSBMaWIuZW5zdXJlU2luZ2xlKGxlZ2VuZCwgJ2cnLCAnc2Nyb2xsYm94Jyk7XG5cbiAgICB2YXIgc2Nyb2xsQmFyID0gTGliLmVuc3VyZVNpbmdsZShsZWdlbmQsICdyZWN0JywgJ3Njcm9sbGJhcicsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5hdHRyKHtcbiAgICAgICAgICAgIHJ4OiAyMCxcbiAgICAgICAgICAgIHJ5OiAzLFxuICAgICAgICAgICAgd2lkdGg6IDAsXG4gICAgICAgICAgICBoZWlnaHQ6IDBcbiAgICAgICAgfSlcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgJyM4MDhCQTQnKTtcbiAgICB9KTtcblxuICAgIHZhciBncm91cHMgPSBzY3JvbGxCb3guc2VsZWN0QWxsKCdnLmdyb3VwcycpXG4gICAgICAgIC5kYXRhKGxlZ2VuZERhdGEpO1xuXG4gICAgZ3JvdXBzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2dyb3VwcycpO1xuXG4gICAgZ3JvdXBzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIHZhciB0cmFjZXMgPSBncm91cHMuc2VsZWN0QWxsKCdnLnRyYWNlcycpXG4gICAgICAgIC5kYXRhKExpYi5pZGVudGl0eSk7XG5cbiAgICB0cmFjZXMuZW50ZXIoKS5hcHBlbmQoJ2cnKS5hdHRyKCdjbGFzcycsICd0cmFjZXMnKTtcbiAgICB0cmFjZXMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdHJhY2VzLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuICAgICAgICBpZihSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAncGllLWxpa2UnKSkge1xuICAgICAgICAgICAgcmV0dXJuIGhpZGRlblNsaWNlcy5pbmRleE9mKGRbMF0ubGFiZWwpICE9PSAtMSA/IDAuNSA6IDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdHJhY2UudmlzaWJsZSA9PT0gJ2xlZ2VuZG9ubHknID8gMC41IDogMTtcbiAgICAgICAgfVxuICAgIH0pXG4gICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgLmNhbGwoZHJhd1RleHRzLCBnZCwgbWF4TGVuZ3RoKTtcbiAgICB9KVxuICAgIC5jYWxsKHN0eWxlLCBnZClcbiAgICAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAuY2FsbChzZXR1cFRyYWNlVG9nZ2xlLCBnZCk7XG4gICAgfSk7XG5cbiAgICBMaWIuc3luY09yQXN5bmMoW1Bsb3RzLnByZXZpb3VzUHJvbWlzZXMsXG4gICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYoZmlyc3RSZW5kZXIpIHtcbiAgICAgICAgICAgICAgICBjb21wdXRlTGVnZW5kRGltZW5zaW9ucyhnZCwgZ3JvdXBzLCB0cmFjZXMpO1xuICAgICAgICAgICAgICAgIGV4cGFuZE1hcmdpbihnZCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBvc2l0aW9uIGFuZCBzaXplIHRoZSBsZWdlbmRcbiAgICAgICAgICAgIHZhciBseE1pbiA9IDA7XG4gICAgICAgICAgICB2YXIgbHhNYXggPSBmdWxsTGF5b3V0LndpZHRoO1xuICAgICAgICAgICAgdmFyIGx5TWluID0gMDtcbiAgICAgICAgICAgIHZhciBseU1heCA9IGZ1bGxMYXlvdXQuaGVpZ2h0O1xuXG4gICAgICAgICAgICBjb21wdXRlTGVnZW5kRGltZW5zaW9ucyhnZCwgZ3JvdXBzLCB0cmFjZXMpO1xuXG4gICAgICAgICAgICBpZihvcHRzLl9oZWlnaHQgPiBseU1heCkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBsZWdlbmQgZG9lc24ndCBmaXQgaW4gdGhlIHBsb3QgYXJlYSxcbiAgICAgICAgICAgICAgICAvLyBkbyBub3QgZXhwYW5kIHRoZSB2ZXJ0aWNhbCBtYXJnaW5zLlxuICAgICAgICAgICAgICAgIGV4cGFuZEhvcml6b250YWxNYXJnaW4oZ2QpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBleHBhbmRNYXJnaW4oZ2QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTY3JvbGwgc2VjdGlvbiBtdXN0IGJlIGV4ZWN1dGVkIGFmdGVyIHJlcG9zaXRpb25MZWdlbmQuXG4gICAgICAgICAgICAvLyBJdCByZXF1aXJlcyB0aGUgbGVnZW5kIHdpZHRoLCBoZWlnaHQsIHggYW5kIHkgdG8gcG9zaXRpb24gdGhlIHNjcm9sbGJveFxuICAgICAgICAgICAgLy8gYW5kIHRoZXNlIHZhbHVlcyBhcmUgbXV0YXRlZCBpbiByZXBvc2l0aW9uTGVnZW5kLlxuICAgICAgICAgICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICAgICAgICAgIHZhciBseCA9IGdzLmwgKyBncy53ICogb3B0cy54O1xuICAgICAgICAgICAgdmFyIGx5ID0gZ3MudCArIGdzLmggKiAoMSAtIG9wdHMueSk7XG5cbiAgICAgICAgICAgIGlmKExpYi5pc1JpZ2h0QW5jaG9yKG9wdHMpKSB7XG4gICAgICAgICAgICAgICAgbHggLT0gb3B0cy5fd2lkdGg7XG4gICAgICAgICAgICB9IGVsc2UgaWYoTGliLmlzQ2VudGVyQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgICAgICAgICAgbHggLT0gb3B0cy5fd2lkdGggLyAyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihMaWIuaXNCb3R0b21BbmNob3Iob3B0cykpIHtcbiAgICAgICAgICAgICAgICBseSAtPSBvcHRzLl9oZWlnaHQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYoTGliLmlzTWlkZGxlQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgICAgICAgICAgbHkgLT0gb3B0cy5faGVpZ2h0IC8gMjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoZSBsZWdlbmQgbGVmdCBhbmQgcmlnaHQgc2lkZXMgYXJlIHZpc2libGVcbiAgICAgICAgICAgIHZhciBsZWdlbmRXaWR0aCA9IG9wdHMuX3dpZHRoO1xuICAgICAgICAgICAgdmFyIGxlZ2VuZFdpZHRoTWF4ID0gZ3MudztcblxuICAgICAgICAgICAgaWYobGVnZW5kV2lkdGggPiBsZWdlbmRXaWR0aE1heCkge1xuICAgICAgICAgICAgICAgIGx4ID0gZ3MubDtcbiAgICAgICAgICAgICAgICBsZWdlbmRXaWR0aCA9IGxlZ2VuZFdpZHRoTWF4O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZihseCArIGxlZ2VuZFdpZHRoID4gbHhNYXgpIGx4ID0gbHhNYXggLSBsZWdlbmRXaWR0aDtcbiAgICAgICAgICAgICAgICBpZihseCA8IGx4TWluKSBseCA9IGx4TWluO1xuICAgICAgICAgICAgICAgIGxlZ2VuZFdpZHRoID0gTWF0aC5taW4obHhNYXggLSBseCwgb3B0cy5fd2lkdGgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlIGxlZ2VuZCB0b3AgYW5kIGJvdHRvbSBhcmUgdmlzaWJsZVxuICAgICAgICAgICAgLy8gKGxlZ2VuZHMgd2l0aCBhIHNjcm9sbCBiYXIgYXJlIG5vdCBhbGxvd2VkIHRvIHN0cmV0Y2ggYmV5b25kIHRoZSBleHRlbmRlZFxuICAgICAgICAgICAgLy8gbWFyZ2lucylcbiAgICAgICAgICAgIHZhciBsZWdlbmRIZWlnaHQgPSBvcHRzLl9oZWlnaHQ7XG4gICAgICAgICAgICB2YXIgbGVnZW5kSGVpZ2h0TWF4ID0gZ3MuaDtcblxuICAgICAgICAgICAgaWYobGVnZW5kSGVpZ2h0ID4gbGVnZW5kSGVpZ2h0TWF4KSB7XG4gICAgICAgICAgICAgICAgbHkgPSBncy50O1xuICAgICAgICAgICAgICAgIGxlZ2VuZEhlaWdodCA9IGxlZ2VuZEhlaWdodE1heDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYobHkgKyBsZWdlbmRIZWlnaHQgPiBseU1heCkgbHkgPSBseU1heCAtIGxlZ2VuZEhlaWdodDtcbiAgICAgICAgICAgICAgICBpZihseSA8IGx5TWluKSBseSA9IGx5TWluO1xuICAgICAgICAgICAgICAgIGxlZ2VuZEhlaWdodCA9IE1hdGgubWluKGx5TWF4IC0gbHksIG9wdHMuX2hlaWdodCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCBzaXplIGFuZCBwb3NpdGlvbiBvZiBhbGwgdGhlIGVsZW1lbnRzIHRoYXQgbWFrZSB1cCBhIGxlZ2VuZDpcbiAgICAgICAgICAgIC8vIGxlZ2VuZCwgYmFja2dyb3VuZCBhbmQgYm9yZGVyLCBzY3JvbGwgYm94IGFuZCBzY3JvbGwgYmFyXG4gICAgICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShsZWdlbmQsIGx4LCBseSk7XG5cbiAgICAgICAgICAgIC8vIHRvIGJlIHNhZmUsIHJlbW92ZSBwcmV2aW91cyBsaXN0ZW5lcnNcbiAgICAgICAgICAgIHNjcm9sbEJhci5vbignLmRyYWcnLCBudWxsKTtcbiAgICAgICAgICAgIGxlZ2VuZC5vbignd2hlZWwnLCBudWxsKTtcblxuICAgICAgICAgICAgaWYob3B0cy5faGVpZ2h0IDw9IGxlZ2VuZEhlaWdodCB8fCBnZC5fY29udGV4dC5zdGF0aWNQbG90KSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgc2Nyb2xsYmFyIHNob3VsZCBub3QgYmUgc2hvd24uXG4gICAgICAgICAgICAgICAgYmcuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiBsZWdlbmRXaWR0aCAtIG9wdHMuYm9yZGVyd2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodDogbGVnZW5kSGVpZ2h0IC0gb3B0cy5ib3JkZXJ3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgeDogb3B0cy5ib3JkZXJ3aWR0aCAvIDIsXG4gICAgICAgICAgICAgICAgICAgIHk6IG9wdHMuYm9yZGVyd2lkdGggLyAyXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShzY3JvbGxCb3gsIDAsIDApO1xuXG4gICAgICAgICAgICAgICAgY2xpcFBhdGguc2VsZWN0KCdyZWN0JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiBsZWdlbmRXaWR0aCAtIDIgKiBvcHRzLmJvcmRlcndpZHRoLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGxlZ2VuZEhlaWdodCAtIDIgKiBvcHRzLmJvcmRlcndpZHRoLFxuICAgICAgICAgICAgICAgICAgICB4OiBvcHRzLmJvcmRlcndpZHRoLFxuICAgICAgICAgICAgICAgICAgICB5OiBvcHRzLmJvcmRlcndpZHRoXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBEcmF3aW5nLnNldENsaXBVcmwoc2Nyb2xsQm94LCBjbGlwSWQsIGdkKTtcblxuICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0UmVjdChzY3JvbGxCYXIsIDAsIDAsIDAsIDApO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBvcHRzLl9zY3JvbGxZO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgc2Nyb2xsQmFySGVpZ2h0ID0gTWF0aC5tYXgoY29uc3RhbnRzLnNjcm9sbEJhck1pbkhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgbGVnZW5kSGVpZ2h0ICogbGVnZW5kSGVpZ2h0IC8gb3B0cy5faGVpZ2h0KTtcbiAgICAgICAgICAgICAgICB2YXIgc2Nyb2xsQmFyWU1heCA9IGxlZ2VuZEhlaWdodCAtXG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbEJhckhlaWdodCAtXG4gICAgICAgICAgICAgICAgICAgIDIgKiBjb25zdGFudHMuc2Nyb2xsQmFyTWFyZ2luO1xuICAgICAgICAgICAgICAgIHZhciBzY3JvbGxCb3hZTWF4ID0gb3B0cy5faGVpZ2h0IC0gbGVnZW5kSGVpZ2h0O1xuICAgICAgICAgICAgICAgIHZhciBzY3JvbGxSYXRpbyA9IHNjcm9sbEJhcllNYXggLyBzY3JvbGxCb3hZTWF4O1xuXG4gICAgICAgICAgICAgICAgdmFyIHNjcm9sbEJveFkgPSBNYXRoLm1pbihvcHRzLl9zY3JvbGxZIHx8IDAsIHNjcm9sbEJveFlNYXgpO1xuXG4gICAgICAgICAgICAgICAgLy8gaW5jcmVhc2UgdGhlIGJhY2tncm91bmQgYW5kIGNsaXAtcGF0aCB3aWR0aFxuICAgICAgICAgICAgICAgIC8vIGJ5IHRoZSBzY3JvbGxiYXIgd2lkdGggYW5kIG1hcmdpblxuICAgICAgICAgICAgICAgIGJnLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogbGVnZW5kV2lkdGggLVxuICAgICAgICAgICAgICAgICAgICAgICAgMiAqIG9wdHMuYm9yZGVyd2lkdGggK1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RhbnRzLnNjcm9sbEJhcldpZHRoICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0YW50cy5zY3JvbGxCYXJNYXJnaW4sXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodDogbGVnZW5kSGVpZ2h0IC0gb3B0cy5ib3JkZXJ3aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgeDogb3B0cy5ib3JkZXJ3aWR0aCAvIDIsXG4gICAgICAgICAgICAgICAgICAgIHk6IG9wdHMuYm9yZGVyd2lkdGggLyAyXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBjbGlwUGF0aC5zZWxlY3QoJ3JlY3QnKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IGxlZ2VuZFdpZHRoIC1cbiAgICAgICAgICAgICAgICAgICAgICAgIDIgKiBvcHRzLmJvcmRlcndpZHRoICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0YW50cy5zY3JvbGxCYXJXaWR0aCArXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdGFudHMuc2Nyb2xsQmFyTWFyZ2luLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGxlZ2VuZEhlaWdodCAtIDIgKiBvcHRzLmJvcmRlcndpZHRoLFxuICAgICAgICAgICAgICAgICAgICB4OiBvcHRzLmJvcmRlcndpZHRoLFxuICAgICAgICAgICAgICAgICAgICB5OiBvcHRzLmJvcmRlcndpZHRoICsgc2Nyb2xsQm94WVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKHNjcm9sbEJveCwgY2xpcElkLCBnZCk7XG5cbiAgICAgICAgICAgICAgICBzY3JvbGxIYW5kbGVyKHNjcm9sbEJveFksIHNjcm9sbEJhckhlaWdodCwgc2Nyb2xsUmF0aW8pO1xuXG4gICAgICAgICAgICAgICAgbGVnZW5kLm9uKCd3aGVlbCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBzY3JvbGxCb3hZID0gTGliLmNvbnN0cmFpbihcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdHMuX3Njcm9sbFkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQzLmV2ZW50LmRlbHRhWSAvIHNjcm9sbEJhcllNYXggKiBzY3JvbGxCb3hZTWF4LFxuICAgICAgICAgICAgICAgICAgICAgICAgMCwgc2Nyb2xsQm94WU1heCk7XG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbEhhbmRsZXIoc2Nyb2xsQm94WSwgc2Nyb2xsQmFySGVpZ2h0LCBzY3JvbGxSYXRpbyk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHNjcm9sbEJveFkgIT09IDAgJiYgc2Nyb2xsQm94WSAhPT0gc2Nyb2xsQm94WU1heCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZDMuZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50WTAsIHNjcm9sbEJveFkwO1xuXG4gICAgICAgICAgICAgICAgdmFyIGRyYWcgPSBkMy5iZWhhdmlvci5kcmFnKClcbiAgICAgICAgICAgICAgICAub24oJ2RyYWdzdGFydCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBldmVudFkwID0gZDMuZXZlbnQuc291cmNlRXZlbnQuY2xpZW50WTtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsQm94WTAgPSBzY3JvbGxCb3hZO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm9uKCdkcmFnJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlID0gZDMuZXZlbnQuc291cmNlRXZlbnQ7XG4gICAgICAgICAgICAgICAgICAgIGlmKGUuYnV0dG9ucyA9PT0gMiB8fCBlLmN0cmxLZXkpIHJldHVybjtcblxuICAgICAgICAgICAgICAgICAgICBzY3JvbGxCb3hZID0gTGliLmNvbnN0cmFpbihcbiAgICAgICAgICAgICAgICAgICAgICAgIChlLmNsaWVudFkgLSBldmVudFkwKSAvIHNjcm9sbFJhdGlvICsgc2Nyb2xsQm94WTAsXG4gICAgICAgICAgICAgICAgICAgICAgICAwLCBzY3JvbGxCb3hZTWF4KTtcbiAgICAgICAgICAgICAgICAgICAgc2Nyb2xsSGFuZGxlcihzY3JvbGxCb3hZLCBzY3JvbGxCYXJIZWlnaHQsIHNjcm9sbFJhdGlvKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHNjcm9sbEJhci5jYWxsKGRyYWcpO1xuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHNjcm9sbEhhbmRsZXIoc2Nyb2xsQm94WSwgc2Nyb2xsQmFySGVpZ2h0LCBzY3JvbGxSYXRpbykge1xuICAgICAgICAgICAgICAgIG9wdHMuX3Njcm9sbFkgPSBnZC5fZnVsbExheW91dC5sZWdlbmQuX3Njcm9sbFkgPSBzY3JvbGxCb3hZO1xuICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKHNjcm9sbEJveCwgMCwgLXNjcm9sbEJveFkpO1xuXG4gICAgICAgICAgICAgICAgRHJhd2luZy5zZXRSZWN0KFxuICAgICAgICAgICAgICAgICAgICBzY3JvbGxCYXIsXG4gICAgICAgICAgICAgICAgICAgIGxlZ2VuZFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICBjb25zdGFudHMuc2Nyb2xsQmFyTWFyZ2luICsgc2Nyb2xsQm94WSAqIHNjcm9sbFJhdGlvLFxuICAgICAgICAgICAgICAgICAgICBjb25zdGFudHMuc2Nyb2xsQmFyV2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIHNjcm9sbEJhckhlaWdodFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY2xpcFBhdGguc2VsZWN0KCdyZWN0JykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHk6IG9wdHMuYm9yZGVyd2lkdGggKyBzY3JvbGxCb3hZXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGdkLl9jb250ZXh0LmVkaXRzLmxlZ2VuZFBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgdmFyIHhmLCB5ZiwgeDAsIHkwO1xuXG4gICAgICAgICAgICAgICAgbGVnZW5kLmNsYXNzZWQoJ2N1cnNvci1tb3ZlJywgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICBkcmFnRWxlbWVudC5pbml0KHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudDogbGVnZW5kLm5vZGUoKSxcbiAgICAgICAgICAgICAgICAgICAgZ2Q6IGdkLFxuICAgICAgICAgICAgICAgICAgICBwcmVwRm46IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IERyYXdpbmcuZ2V0VHJhbnNsYXRlKGxlZ2VuZCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHgwID0gdHJhbnNmb3JtLng7XG4gICAgICAgICAgICAgICAgICAgICAgICB5MCA9IHRyYW5zZm9ybS55O1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBtb3ZlRm46IGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1ggPSB4MCArIGR4O1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1kgPSB5MCArIGR5O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShsZWdlbmQsIG5ld1gsIG5ld1kpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB4ZiA9IGRyYWdFbGVtZW50LmFsaWduKG5ld1gsIDAsIGdzLmwsIGdzLmwgKyBncy53LCBvcHRzLnhhbmNob3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgeWYgPSBkcmFnRWxlbWVudC5hbGlnbihuZXdZLCAwLCBncy50ICsgZ3MuaCwgZ3MudCwgb3B0cy55YW5jaG9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZG9uZUZuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHhmICE9PSB1bmRlZmluZWQgJiYgeWYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCB7J2xlZ2VuZC54JzogeGYsICdsZWdlbmQueSc6IHlmfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGNsaWNrRm46IGZ1bmN0aW9uKG51bUNsaWNrcywgZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNsaWNrZWRUcmFjZSA9IGZ1bGxMYXlvdXQuX2luZm9sYXllci5zZWxlY3RBbGwoJ2cudHJhY2VzJykuZmlsdGVyKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBiYm94ID0gdGhpcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLmNsaWVudFggPj0gYmJveC5sZWZ0ICYmIGUuY2xpZW50WCA8PSBiYm94LnJpZ2h0ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGUuY2xpZW50WSA+PSBiYm94LnRvcCAmJiBlLmNsaWVudFkgPD0gYmJveC5ib3R0b21cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihjbGlja2VkVHJhY2Uuc2l6ZSgpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaWNrT3JEb3VibGVDbGljayhnZCwgbGVnZW5kLCBjbGlja2VkVHJhY2UsIG51bUNsaWNrcywgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfV0sIGdkKTtcbn07XG5cbmZ1bmN0aW9uIGNsaWNrT3JEb3VibGVDbGljayhnZCwgbGVnZW5kLCBsZWdlbmRJdGVtLCBudW1DbGlja3MsIGV2dCkge1xuICAgIHZhciB0cmFjZSA9IGxlZ2VuZEl0ZW0uZGF0YSgpWzBdWzBdLnRyYWNlO1xuICAgIHZhciBldnREYXRhID0ge1xuICAgICAgICBldmVudDogZXZ0LFxuICAgICAgICBub2RlOiBsZWdlbmRJdGVtLm5vZGUoKSxcbiAgICAgICAgY3VydmVOdW1iZXI6IHRyYWNlLmluZGV4LFxuICAgICAgICBleHBhbmRlZEluZGV4OiB0cmFjZS5fZXhwYW5kZWRJbmRleCxcbiAgICAgICAgZGF0YTogZ2QuZGF0YSxcbiAgICAgICAgbGF5b3V0OiBnZC5sYXlvdXQsXG4gICAgICAgIGZyYW1lczogZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZXMsXG4gICAgICAgIGNvbmZpZzogZ2QuX2NvbnRleHQsXG4gICAgICAgIGZ1bGxEYXRhOiBnZC5fZnVsbERhdGEsXG4gICAgICAgIGZ1bGxMYXlvdXQ6IGdkLl9mdWxsTGF5b3V0XG4gICAgfTtcblxuICAgIGlmKHRyYWNlLl9ncm91cCkge1xuICAgICAgICBldnREYXRhLmdyb3VwID0gdHJhY2UuX2dyb3VwO1xuICAgIH1cbiAgICBpZihSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAncGllLWxpa2UnKSkge1xuICAgICAgICBldnREYXRhLmxhYmVsID0gbGVnZW5kSXRlbS5kYXR1bSgpWzBdLmxhYmVsO1xuICAgIH1cblxuICAgIHZhciBjbGlja1ZhbCA9IEV2ZW50cy50cmlnZ2VySGFuZGxlcihnZCwgJ3Bsb3RseV9sZWdlbmRjbGljaycsIGV2dERhdGEpO1xuICAgIGlmKGNsaWNrVmFsID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgaWYobnVtQ2xpY2tzID09PSAxKSB7XG4gICAgICAgIGxlZ2VuZC5fY2xpY2tUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGhhbmRsZUNsaWNrKGxlZ2VuZEl0ZW0sIGdkLCBudW1DbGlja3MpO1xuICAgICAgICB9LCBnZC5fY29udGV4dC5kb3VibGVDbGlja0RlbGF5KTtcbiAgICB9IGVsc2UgaWYobnVtQ2xpY2tzID09PSAyKSB7XG4gICAgICAgIGlmKGxlZ2VuZC5fY2xpY2tUaW1lb3V0KSBjbGVhclRpbWVvdXQobGVnZW5kLl9jbGlja1RpbWVvdXQpO1xuICAgICAgICBnZC5fbGVnZW5kTW91c2VEb3duVGltZSA9IDA7XG5cbiAgICAgICAgdmFyIGRibENsaWNrVmFsID0gRXZlbnRzLnRyaWdnZXJIYW5kbGVyKGdkLCAncGxvdGx5X2xlZ2VuZGRvdWJsZWNsaWNrJywgZXZ0RGF0YSk7XG4gICAgICAgIGlmKGRibENsaWNrVmFsICE9PSBmYWxzZSkgaGFuZGxlQ2xpY2sobGVnZW5kSXRlbSwgZ2QsIG51bUNsaWNrcyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmF3VGV4dHMoZywgZ2QsIG1heExlbmd0aCkge1xuICAgIHZhciBsZWdlbmRJdGVtID0gZy5kYXRhKClbMF1bMF07XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgdHJhY2UgPSBsZWdlbmRJdGVtLnRyYWNlO1xuICAgIHZhciBpc1BpZUxpa2UgPSBSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAncGllLWxpa2UnKTtcbiAgICB2YXIgdHJhY2VJbmRleCA9IHRyYWNlLmluZGV4O1xuICAgIHZhciBpc0VkaXRhYmxlID0gZ2QuX2NvbnRleHQuZWRpdHMubGVnZW5kVGV4dCAmJiAhaXNQaWVMaWtlO1xuXG4gICAgdmFyIG5hbWUgPSBpc1BpZUxpa2UgPyBsZWdlbmRJdGVtLmxhYmVsIDogdHJhY2UubmFtZTtcbiAgICBpZih0cmFjZS5fbWV0YSkge1xuICAgICAgICBuYW1lID0gTGliLnRlbXBsYXRlU3RyaW5nKG5hbWUsIHRyYWNlLl9tZXRhKTtcbiAgICB9XG5cbiAgICB2YXIgdGV4dEVsID0gTGliLmVuc3VyZVNpbmdsZShnLCAndGV4dCcsICdsZWdlbmR0ZXh0Jyk7XG5cbiAgICB0ZXh0RWwuYXR0cigndGV4dC1hbmNob3InLCAnc3RhcnQnKVxuICAgICAgICAuY2xhc3NlZCgndXNlci1zZWxlY3Qtbm9uZScsIHRydWUpXG4gICAgICAgIC5jYWxsKERyYXdpbmcuZm9udCwgZnVsbExheW91dC5sZWdlbmQuZm9udClcbiAgICAgICAgLnRleHQoaXNFZGl0YWJsZSA/IGVuc3VyZUxlbmd0aChuYW1lLCBtYXhMZW5ndGgpIDogbmFtZSk7XG5cbiAgICBzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0KHRleHRFbCwgY29uc3RhbnRzLnRleHRPZmZzZXRYLCAwKTtcblxuICAgIGZ1bmN0aW9uIHRleHRMYXlvdXQocykge1xuICAgICAgICBzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zKHMsIGdkLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGNvbXB1dGVUZXh0RGltZW5zaW9ucyhnLCBnZCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKGlzRWRpdGFibGUpIHtcbiAgICAgICAgdGV4dEVsLmNhbGwoc3ZnVGV4dFV0aWxzLm1ha2VFZGl0YWJsZSwge2dkOiBnZCwgdGV4dDogbmFtZX0pXG4gICAgICAgICAgICAuY2FsbCh0ZXh0TGF5b3V0KVxuICAgICAgICAgICAgLm9uKCdlZGl0JywgZnVuY3Rpb24obmV3TmFtZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dChlbnN1cmVMZW5ndGgobmV3TmFtZSwgbWF4TGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhbGwodGV4dExheW91dCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgZnVsbElucHV0ID0gbGVnZW5kSXRlbS50cmFjZS5fZnVsbElucHV0IHx8IHt9O1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGUgPSB7fTtcblxuICAgICAgICAgICAgICAgIGlmKFJlZ2lzdHJ5Lmhhc1RyYW5zZm9ybShmdWxsSW5wdXQsICdncm91cGJ5JykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGdyb3VwYnlJbmRpY2VzID0gUmVnaXN0cnkuZ2V0VHJhbnNmb3JtSW5kaWNlcyhmdWxsSW5wdXQsICdncm91cGJ5Jyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGdyb3VwYnlJbmRpY2VzW2dyb3VwYnlJbmRpY2VzLmxlbmd0aCAtIDFdO1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBrY29udCA9IExpYi5rZXllZENvbnRhaW5lcihmdWxsSW5wdXQsICd0cmFuc2Zvcm1zWycgKyBpbmRleCArICddLnN0eWxlcycsICd0YXJnZXQnLCAndmFsdWUubmFtZScpO1xuXG4gICAgICAgICAgICAgICAgICAgIGtjb250LnNldChsZWdlbmRJdGVtLnRyYWNlLl9ncm91cCwgbmV3TmFtZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlID0ga2NvbnQuY29uc3RydWN0VXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlLm5hbWUgPSBuZXdOYW1lO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVzdHlsZScsIGdkLCB1cGRhdGUsIHRyYWNlSW5kZXgpO1xuICAgICAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGV4dExheW91dCh0ZXh0RWwpO1xuICAgIH1cbn1cblxuLypcbiAqIE1ha2Ugc3VyZSB3ZSBoYXZlIGEgcmVhc29uYWJseSBjbGlja2FibGUgcmVnaW9uLlxuICogSWYgdGhpcyBzdHJpbmcgaXMgbWlzc2luZyBvciB2ZXJ5IHNob3J0LCBwYWQgaXQgd2l0aCBzcGFjZXMgb3V0IHRvIGF0IGxlYXN0XG4gKiA0IGNoYXJhY3RlcnMsIHVwIHRvIHRoZSBtYXggbGVuZ3RoIG9mIG90aGVyIGxhYmVscywgb24gdGhlIGFzc3VtcHRpb24gdGhhdFxuICogbW9zdCBjaGFyYWN0ZXJzIGFyZSB3aWRlciB0aGFuIHNwYWNlcyBzbyBhIHN0cmluZyBvZiBzcGFjZXMgd2lsbCB1c3VhbGx5IGJlXG4gKiBubyB3aWRlciB0aGFuIHRoZSByZWFsIGxhYmVscy5cbiAqL1xuZnVuY3Rpb24gZW5zdXJlTGVuZ3RoKHN0ciwgbWF4TGVuZ3RoKSB7XG4gICAgdmFyIHRhcmdldExlbmd0aCA9IE1hdGgubWF4KDQsIG1heExlbmd0aCk7XG4gICAgaWYoc3RyICYmIHN0ci50cmltKCkubGVuZ3RoID49IHRhcmdldExlbmd0aCAvIDIpIHJldHVybiBzdHI7XG4gICAgc3RyID0gc3RyIHx8ICcnO1xuICAgIGZvcih2YXIgaSA9IHRhcmdldExlbmd0aCAtIHN0ci5sZW5ndGg7IGkgPiAwOyBpLS0pIHN0ciArPSAnICc7XG4gICAgcmV0dXJuIHN0cjtcbn1cblxuZnVuY3Rpb24gc2V0dXBUcmFjZVRvZ2dsZShnLCBnZCkge1xuICAgIHZhciBkb3VibGVDbGlja0RlbGF5ID0gZ2QuX2NvbnRleHQuZG91YmxlQ2xpY2tEZWxheTtcbiAgICB2YXIgbmV3TW91c2VEb3duVGltZTtcbiAgICB2YXIgbnVtQ2xpY2tzID0gMTtcblxuICAgIHZhciB0cmFjZVRvZ2dsZSA9IExpYi5lbnN1cmVTaW5nbGUoZywgJ3JlY3QnLCAnbGVnZW5kdG9nZ2xlJywgZnVuY3Rpb24ocykge1xuICAgICAgICBzLnN0eWxlKCdjdXJzb3InLCAncG9pbnRlcicpXG4gICAgICAgICAgICAuYXR0cigncG9pbnRlci1ldmVudHMnLCAnYWxsJylcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsICdyZ2JhKDAsMCwwLDApJyk7XG4gICAgfSk7XG5cbiAgICB0cmFjZVRvZ2dsZS5vbignbW91c2Vkb3duJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIG5ld01vdXNlRG93blRpbWUgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuICAgICAgICBpZihuZXdNb3VzZURvd25UaW1lIC0gZ2QuX2xlZ2VuZE1vdXNlRG93blRpbWUgPCBkb3VibGVDbGlja0RlbGF5KSB7XG4gICAgICAgICAgICAvLyBpbiBhIGNsaWNrIHRyYWluXG4gICAgICAgICAgICBudW1DbGlja3MgKz0gMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG5ldyBjbGljayB0cmFpblxuICAgICAgICAgICAgbnVtQ2xpY2tzID0gMTtcbiAgICAgICAgICAgIGdkLl9sZWdlbmRNb3VzZURvd25UaW1lID0gbmV3TW91c2VEb3duVGltZTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHRyYWNlVG9nZ2xlLm9uKCdtb3VzZXVwJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmKGdkLl9kcmFnZ2VkIHx8IGdkLl9lZGl0aW5nKSByZXR1cm47XG4gICAgICAgIHZhciBsZWdlbmQgPSBnZC5fZnVsbExheW91dC5sZWdlbmQ7XG5cbiAgICAgICAgaWYoKG5ldyBEYXRlKCkpLmdldFRpbWUoKSAtIGdkLl9sZWdlbmRNb3VzZURvd25UaW1lID4gZG91YmxlQ2xpY2tEZWxheSkge1xuICAgICAgICAgICAgbnVtQ2xpY2tzID0gTWF0aC5tYXgobnVtQ2xpY2tzIC0gMSwgMSk7XG4gICAgICAgIH1cblxuICAgICAgICBjbGlja09yRG91YmxlQ2xpY2soZ2QsIGxlZ2VuZCwgZywgbnVtQ2xpY2tzLCBkMy5ldmVudCk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVUZXh0RGltZW5zaW9ucyhnLCBnZCkge1xuICAgIHZhciBsZWdlbmRJdGVtID0gZy5kYXRhKClbMF1bMF07XG5cbiAgICBpZighbGVnZW5kSXRlbS50cmFjZS5zaG93bGVnZW5kKSB7XG4gICAgICAgIGcucmVtb3ZlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgbWF0aGpheEdyb3VwID0gZy5zZWxlY3QoJ2dbY2xhc3MqPW1hdGgtZ3JvdXBdJyk7XG4gICAgdmFyIG1hdGhqYXhOb2RlID0gbWF0aGpheEdyb3VwLm5vZGUoKTtcbiAgICB2YXIgb3B0cyA9IGdkLl9mdWxsTGF5b3V0LmxlZ2VuZDtcbiAgICB2YXIgbGluZUhlaWdodCA9IG9wdHMuZm9udC5zaXplICogTElORV9TUEFDSU5HO1xuICAgIHZhciBoZWlnaHQsIHdpZHRoO1xuXG4gICAgaWYobWF0aGpheE5vZGUpIHtcbiAgICAgICAgdmFyIG1hdGhqYXhCQiA9IERyYXdpbmcuYkJveChtYXRoamF4Tm9kZSk7XG5cbiAgICAgICAgaGVpZ2h0ID0gbWF0aGpheEJCLmhlaWdodDtcbiAgICAgICAgd2lkdGggPSBtYXRoamF4QkIud2lkdGg7XG5cbiAgICAgICAgRHJhd2luZy5zZXRUcmFuc2xhdGUobWF0aGpheEdyb3VwLCAwLCAoaGVpZ2h0IC8gNCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB0ZXh0ID0gZy5zZWxlY3QoJy5sZWdlbmR0ZXh0Jyk7XG4gICAgICAgIHZhciB0ZXh0TGluZXMgPSBzdmdUZXh0VXRpbHMubGluZUNvdW50KHRleHQpO1xuICAgICAgICB2YXIgdGV4dE5vZGUgPSB0ZXh0Lm5vZGUoKTtcblxuICAgICAgICBoZWlnaHQgPSBsaW5lSGVpZ2h0ICogdGV4dExpbmVzO1xuICAgICAgICB3aWR0aCA9IHRleHROb2RlID8gRHJhd2luZy5iQm94KHRleHROb2RlKS53aWR0aCA6IDA7XG5cbiAgICAgICAgLy8gYXBwcm94aW1hdGlvbiB0byBoZWlnaHQgb2Zmc2V0IHRvIGNlbnRlciB0aGUgZm9udFxuICAgICAgICAvLyB0byBhdm9pZCBnZXRCb3VuZGluZ0NsaWVudFJlY3RcbiAgICAgICAgdmFyIHRleHRZID0gbGluZUhlaWdodCAqICgwLjMgKyAoMSAtIHRleHRMaW5lcykgLyAyKTtcbiAgICAgICAgc3ZnVGV4dFV0aWxzLnBvc2l0aW9uVGV4dCh0ZXh0LCBjb25zdGFudHMudGV4dE9mZnNldFgsIHRleHRZKTtcbiAgICB9XG5cbiAgICBsZWdlbmRJdGVtLmxpbmVIZWlnaHQgPSBsaW5lSGVpZ2h0O1xuICAgIGxlZ2VuZEl0ZW0uaGVpZ2h0ID0gTWF0aC5tYXgoaGVpZ2h0LCAxNikgKyAzO1xuICAgIGxlZ2VuZEl0ZW0ud2lkdGggPSB3aWR0aDtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZUxlZ2VuZERpbWVuc2lvbnMoZ2QsIGdyb3VwcywgdHJhY2VzKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgb3B0cyA9IGZ1bGxMYXlvdXQubGVnZW5kO1xuICAgIHZhciBib3JkZXJ3aWR0aCA9IG9wdHMuYm9yZGVyd2lkdGg7XG4gICAgdmFyIGlzR3JvdXBlZCA9IGhlbHBlcnMuaXNHcm91cGVkKG9wdHMpO1xuXG4gICAgdmFyIGV4dHJhV2lkdGggPSAwO1xuXG4gICAgdmFyIHRyYWNlR2FwID0gNTtcblxuICAgIG9wdHMuX3dpZHRoID0gMDtcbiAgICBvcHRzLl9oZWlnaHQgPSAwO1xuXG4gICAgaWYoaGVscGVycy5pc1ZlcnRpY2FsKG9wdHMpKSB7XG4gICAgICAgIGlmKGlzR3JvdXBlZCkge1xuICAgICAgICAgICAgZ3JvdXBzLmVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKHRoaXMsIDAsIGkgKiBvcHRzLnRyYWNlZ3JvdXBnYXApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0cmFjZXMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgbGVnZW5kSXRlbSA9IGRbMF07XG4gICAgICAgICAgICB2YXIgdGV4dEhlaWdodCA9IGxlZ2VuZEl0ZW0uaGVpZ2h0O1xuICAgICAgICAgICAgdmFyIHRleHRXaWR0aCA9IGxlZ2VuZEl0ZW0ud2lkdGg7XG5cbiAgICAgICAgICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKHRoaXMsXG4gICAgICAgICAgICAgICAgYm9yZGVyd2lkdGgsXG4gICAgICAgICAgICAgICAgKDUgKyBib3JkZXJ3aWR0aCArIG9wdHMuX2hlaWdodCArIHRleHRIZWlnaHQgLyAyKSk7XG5cbiAgICAgICAgICAgIG9wdHMuX2hlaWdodCArPSB0ZXh0SGVpZ2h0O1xuICAgICAgICAgICAgb3B0cy5fd2lkdGggPSBNYXRoLm1heChvcHRzLl93aWR0aCwgdGV4dFdpZHRoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgb3B0cy5fd2lkdGggKz0gNDUgKyBib3JkZXJ3aWR0aCAqIDI7XG4gICAgICAgIG9wdHMuX2hlaWdodCArPSAxMCArIGJvcmRlcndpZHRoICogMjtcblxuICAgICAgICBpZihpc0dyb3VwZWQpIHtcbiAgICAgICAgICAgIG9wdHMuX2hlaWdodCArPSAob3B0cy5fbGdyb3Vwc0xlbmd0aCAtIDEpICogb3B0cy50cmFjZWdyb3VwZ2FwO1xuICAgICAgICB9XG5cbiAgICAgICAgZXh0cmFXaWR0aCA9IDQwO1xuICAgIH0gZWxzZSBpZihpc0dyb3VwZWQpIHtcbiAgICAgICAgdmFyIG1heEhlaWdodCA9IDA7XG4gICAgICAgIHZhciBtYXhXaWR0aCA9IDA7XG4gICAgICAgIHZhciBncm91cERhdGEgPSBncm91cHMuZGF0YSgpO1xuXG4gICAgICAgIHZhciBtYXhJdGVtcyA9IDA7XG5cbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGdyb3VwRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGdyb3VwID0gZ3JvdXBEYXRhW2ldO1xuICAgICAgICAgICAgdmFyIGdyb3VwV2lkdGhzID0gZ3JvdXAubWFwKGZ1bmN0aW9uKGxlZ2VuZEl0ZW1BcnJheSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsZWdlbmRJdGVtQXJyYXlbMF0ud2lkdGg7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIGdyb3VwV2lkdGggPSBMaWIuYWdnTnVtcyhNYXRoLm1heCwgbnVsbCwgZ3JvdXBXaWR0aHMpO1xuICAgICAgICAgICAgdmFyIGdyb3VwSGVpZ2h0ID0gZ3JvdXAucmVkdWNlKGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSArIGJbMF0uaGVpZ2h0O1xuICAgICAgICAgICAgfSwgMCk7XG5cbiAgICAgICAgICAgIG1heFdpZHRoID0gTWF0aC5tYXgobWF4V2lkdGgsIGdyb3VwV2lkdGgpO1xuICAgICAgICAgICAgbWF4SGVpZ2h0ID0gTWF0aC5tYXgobWF4SGVpZ2h0LCBncm91cEhlaWdodCk7XG4gICAgICAgICAgICBtYXhJdGVtcyA9IE1hdGgubWF4KG1heEl0ZW1zLCBncm91cC5sZW5ndGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgbWF4V2lkdGggKz0gdHJhY2VHYXA7XG4gICAgICAgIG1heFdpZHRoICs9IDQwO1xuXG4gICAgICAgIHZhciBncm91cFhPZmZzZXRzID0gW29wdHMuX3dpZHRoXTtcbiAgICAgICAgdmFyIGdyb3VwWU9mZnNldHMgPSBbXTtcbiAgICAgICAgdmFyIHJvd051bSA9IDA7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGdyb3VwRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoZnVsbExheW91dC5fc2l6ZS53IDwgKGJvcmRlcndpZHRoICsgb3B0cy5fd2lkdGggKyB0cmFjZUdhcCArIG1heFdpZHRoKSkge1xuICAgICAgICAgICAgICAgIGdyb3VwWE9mZnNldHNbZ3JvdXBYT2Zmc2V0cy5sZW5ndGggLSAxXSA9IGdyb3VwWE9mZnNldHNbMF07XG4gICAgICAgICAgICAgICAgb3B0cy5fd2lkdGggPSBtYXhXaWR0aDtcbiAgICAgICAgICAgICAgICByb3dOdW0rKztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb3B0cy5fd2lkdGggKz0gbWF4V2lkdGggKyBib3JkZXJ3aWR0aDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHJvd1lPZmZzZXQgPSAocm93TnVtICogbWF4SGVpZ2h0KTtcbiAgICAgICAgICAgIHJvd1lPZmZzZXQgKz0gcm93TnVtID4gMCA/IG9wdHMudHJhY2Vncm91cGdhcCA6IDA7XG5cbiAgICAgICAgICAgIGdyb3VwWU9mZnNldHMucHVzaChyb3dZT2Zmc2V0KTtcbiAgICAgICAgICAgIGdyb3VwWE9mZnNldHMucHVzaChvcHRzLl93aWR0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBncm91cHMuZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZSh0aGlzLCBncm91cFhPZmZzZXRzW2ldLCBncm91cFlPZmZzZXRzW2ldKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZ3JvdXBzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgZ3JvdXAgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgZ3JvdXBUcmFjZXMgPSBncm91cC5zZWxlY3RBbGwoJ2cudHJhY2VzJyk7XG4gICAgICAgICAgICB2YXIgZ3JvdXBIZWlnaHQgPSAwO1xuXG4gICAgICAgICAgICBncm91cFRyYWNlcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGVnZW5kSXRlbSA9IGRbMF07XG4gICAgICAgICAgICAgICAgdmFyIHRleHRIZWlnaHQgPSBsZWdlbmRJdGVtLmhlaWdodDtcblxuICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKHRoaXMsXG4gICAgICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgICAgICg1ICsgYm9yZGVyd2lkdGggKyBncm91cEhlaWdodCArIHRleHRIZWlnaHQgLyAyKSk7XG5cbiAgICAgICAgICAgICAgICBncm91cEhlaWdodCArPSB0ZXh0SGVpZ2h0O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBtYXhZTGVnZW5kID0gZ3JvdXBZT2Zmc2V0c1tncm91cFlPZmZzZXRzLmxlbmd0aCAtIDFdICsgbWF4SGVpZ2h0O1xuICAgICAgICBvcHRzLl9oZWlnaHQgPSAxMCArIChib3JkZXJ3aWR0aCAqIDIpICsgbWF4WUxlZ2VuZDtcblxuICAgICAgICB2YXIgbWF4T2Zmc2V0ID0gTWF0aC5tYXguYXBwbHkobnVsbCwgZ3JvdXBYT2Zmc2V0cyk7XG4gICAgICAgIG9wdHMuX3dpZHRoID0gbWF4T2Zmc2V0ICsgbWF4V2lkdGggKyA0MDtcbiAgICAgICAgb3B0cy5fd2lkdGggKz0gYm9yZGVyd2lkdGggKiAyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciByb3dIZWlnaHQgPSAwO1xuICAgICAgICB2YXIgbWF4VHJhY2VIZWlnaHQgPSAwO1xuICAgICAgICB2YXIgbWF4VHJhY2VXaWR0aCA9IDA7XG4gICAgICAgIHZhciBvZmZzZXRYID0gMDtcbiAgICAgICAgdmFyIGZ1bGxUcmFjZXNXaWR0aCA9IDA7XG5cbiAgICAgICAgLy8gY2FsY3VsYXRlIGxhcmdlc3Qgd2lkdGggZm9yIHRyYWNlcyBhbmQgdXNlIGZvciB3aWR0aCBvZiBhbGwgbGVnZW5kIGl0ZW1zXG4gICAgICAgIHRyYWNlcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIG1heFRyYWNlV2lkdGggPSBNYXRoLm1heCg0MCArIGRbMF0ud2lkdGgsIG1heFRyYWNlV2lkdGgpO1xuICAgICAgICAgICAgZnVsbFRyYWNlc1dpZHRoICs9IDQwICsgZFswXS53aWR0aCArIHRyYWNlR2FwO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBjaGVjayBpZiBsZWdlbmQgZml0cyBpbiBvbmUgcm93XG4gICAgICAgIHZhciBvbmVSb3dMZWdlbmQgPSBmdWxsTGF5b3V0Ll9zaXplLncgPiBib3JkZXJ3aWR0aCArIGZ1bGxUcmFjZXNXaWR0aCAtIHRyYWNlR2FwO1xuXG4gICAgICAgIHRyYWNlcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBsZWdlbmRJdGVtID0gZFswXTtcbiAgICAgICAgICAgIHZhciB0cmFjZVdpZHRoID0gb25lUm93TGVnZW5kID8gNDAgKyBkWzBdLndpZHRoIDogbWF4VHJhY2VXaWR0aDtcblxuICAgICAgICAgICAgaWYoKGJvcmRlcndpZHRoICsgb2Zmc2V0WCArIHRyYWNlR2FwICsgdHJhY2VXaWR0aCkgPiBmdWxsTGF5b3V0Ll9zaXplLncpIHtcbiAgICAgICAgICAgICAgICBvZmZzZXRYID0gMDtcbiAgICAgICAgICAgICAgICByb3dIZWlnaHQgKz0gbWF4VHJhY2VIZWlnaHQ7XG4gICAgICAgICAgICAgICAgb3B0cy5faGVpZ2h0ICs9IG1heFRyYWNlSGVpZ2h0O1xuICAgICAgICAgICAgICAgIC8vIHJlc2V0IGZvciBuZXh0IHJvd1xuICAgICAgICAgICAgICAgIG1heFRyYWNlSGVpZ2h0ID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRHJhd2luZy5zZXRUcmFuc2xhdGUodGhpcyxcbiAgICAgICAgICAgICAgICAoYm9yZGVyd2lkdGggKyBvZmZzZXRYKSxcbiAgICAgICAgICAgICAgICAoNSArIGJvcmRlcndpZHRoICsgbGVnZW5kSXRlbS5oZWlnaHQgLyAyKSArIHJvd0hlaWdodCk7XG5cbiAgICAgICAgICAgIG9wdHMuX3dpZHRoICs9IHRyYWNlR2FwICsgdHJhY2VXaWR0aDtcblxuICAgICAgICAgICAgLy8ga2VlcCB0cmFjayBvZiB0YWxsZXN0IHRyYWNlIGluIGdyb3VwXG4gICAgICAgICAgICBvZmZzZXRYICs9IHRyYWNlR2FwICsgdHJhY2VXaWR0aDtcbiAgICAgICAgICAgIG1heFRyYWNlSGVpZ2h0ID0gTWF0aC5tYXgobGVnZW5kSXRlbS5oZWlnaHQsIG1heFRyYWNlSGVpZ2h0KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYob25lUm93TGVnZW5kKSB7XG4gICAgICAgICAgICBvcHRzLl9oZWlnaHQgPSBtYXhUcmFjZUhlaWdodDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9wdHMuX2hlaWdodCArPSBtYXhUcmFjZUhlaWdodDtcbiAgICAgICAgfVxuXG4gICAgICAgIG9wdHMuX3dpZHRoICs9IGJvcmRlcndpZHRoICogMjtcbiAgICAgICAgb3B0cy5faGVpZ2h0ICs9IDEwICsgYm9yZGVyd2lkdGggKiAyO1xuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSB3ZSdyZSBvbmx5IGdldHRpbmcgZnVsbCBwaXhlbHNcbiAgICBvcHRzLl93aWR0aCA9IE1hdGguY2VpbChvcHRzLl93aWR0aCk7XG4gICAgb3B0cy5faGVpZ2h0ID0gTWF0aC5jZWlsKG9wdHMuX2hlaWdodCk7XG5cbiAgICB2YXIgaXNFZGl0YWJsZSA9IChcbiAgICAgICAgZ2QuX2NvbnRleHQuZWRpdHMubGVnZW5kVGV4dCB8fFxuICAgICAgICBnZC5fY29udGV4dC5lZGl0cy5sZWdlbmRQb3NpdGlvblxuICAgICk7XG5cbiAgICB0cmFjZXMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBsZWdlbmRJdGVtID0gZFswXTtcbiAgICAgICAgdmFyIGJnID0gZDMuc2VsZWN0KHRoaXMpLnNlbGVjdCgnLmxlZ2VuZHRvZ2dsZScpO1xuXG4gICAgICAgIERyYXdpbmcuc2V0UmVjdChiZyxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAtbGVnZW5kSXRlbS5oZWlnaHQgLyAyLFxuICAgICAgICAgICAgKGlzRWRpdGFibGUgPyAwIDogb3B0cy5fd2lkdGgpICsgZXh0cmFXaWR0aCxcbiAgICAgICAgICAgIGxlZ2VuZEl0ZW0uaGVpZ2h0XG4gICAgICAgICk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGV4cGFuZE1hcmdpbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIG9wdHMgPSBmdWxsTGF5b3V0LmxlZ2VuZDtcblxuICAgIHZhciB4YW5jaG9yID0gJ2xlZnQnO1xuICAgIGlmKExpYi5pc1JpZ2h0QW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIHhhbmNob3IgPSAncmlnaHQnO1xuICAgIH0gZWxzZSBpZihMaWIuaXNDZW50ZXJBbmNob3Iob3B0cykpIHtcbiAgICAgICAgeGFuY2hvciA9ICdjZW50ZXInO1xuICAgIH1cblxuICAgIHZhciB5YW5jaG9yID0gJ3RvcCc7XG4gICAgaWYoTGliLmlzQm90dG9tQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIHlhbmNob3IgPSAnYm90dG9tJztcbiAgICB9IGVsc2UgaWYoTGliLmlzTWlkZGxlQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIHlhbmNob3IgPSAnbWlkZGxlJztcbiAgICB9XG5cbiAgICAvLyBsYXN0bHkgY2hlY2sgaWYgdGhlIG1hcmdpbiBhdXRvLWV4cGFuZCBoYXMgY2hhbmdlZFxuICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsICdsZWdlbmQnLCB7XG4gICAgICAgIHg6IG9wdHMueCxcbiAgICAgICAgeTogb3B0cy55LFxuICAgICAgICBsOiBvcHRzLl93aWR0aCAqIChGUk9NX1RMW3hhbmNob3JdKSxcbiAgICAgICAgcjogb3B0cy5fd2lkdGggKiAoRlJPTV9CUlt4YW5jaG9yXSksXG4gICAgICAgIGI6IG9wdHMuX2hlaWdodCAqIChGUk9NX0JSW3lhbmNob3JdKSxcbiAgICAgICAgdDogb3B0cy5faGVpZ2h0ICogKEZST01fVExbeWFuY2hvcl0pXG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGV4cGFuZEhvcml6b250YWxNYXJnaW4oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBvcHRzID0gZnVsbExheW91dC5sZWdlbmQ7XG5cbiAgICB2YXIgeGFuY2hvciA9ICdsZWZ0JztcbiAgICBpZihMaWIuaXNSaWdodEFuY2hvcihvcHRzKSkge1xuICAgICAgICB4YW5jaG9yID0gJ3JpZ2h0JztcbiAgICB9IGVsc2UgaWYoTGliLmlzQ2VudGVyQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIHhhbmNob3IgPSAnY2VudGVyJztcbiAgICB9XG5cbiAgICAvLyBsYXN0bHkgY2hlY2sgaWYgdGhlIG1hcmdpbiBhdXRvLWV4cGFuZCBoYXMgY2hhbmdlZFxuICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsICdsZWdlbmQnLCB7XG4gICAgICAgIHg6IG9wdHMueCxcbiAgICAgICAgeTogMC41LFxuICAgICAgICBsOiBvcHRzLl93aWR0aCAqIChGUk9NX1RMW3hhbmNob3JdKSxcbiAgICAgICAgcjogb3B0cy5fd2lkdGggKiAoRlJPTV9CUlt4YW5jaG9yXSksXG4gICAgICAgIGI6IDAsXG4gICAgICAgIHQ6IDBcbiAgICB9KTtcbn1cblxufSx7XCIuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50XCI6Njg4LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL2V2ZW50c1wiOjcwOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3Bsb3RzL3Bsb3RzXCI6ODI4LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9jb2xvclwiOjU5MyxcIi4uL2RyYWdlbGVtZW50XCI6NjExLFwiLi4vZHJhd2luZ1wiOjYxNCxcIi4vY29uc3RhbnRzXCI6NjQzLFwiLi9nZXRfbGVnZW5kX2RhdGFcIjo2NDYsXCIuL2hhbmRsZV9jbGlja1wiOjY0NyxcIi4vaGVscGVyc1wiOjY0OCxcIi4vc3R5bGVcIjo2NTAsXCJkM1wiOjE2M31dLDY0NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdldExlZ2VuZERhdGEoY2FsY2RhdGEsIG9wdHMpIHtcbiAgICB2YXIgbGdyb3VwVG9UcmFjZXMgPSB7fTtcbiAgICB2YXIgbGdyb3VwcyA9IFtdO1xuICAgIHZhciBoYXNPbmVOb25CbGFua0dyb3VwID0gZmFsc2U7XG4gICAgdmFyIHNsaWNlc1Nob3duID0ge307XG4gICAgdmFyIGxncm91cGkgPSAwO1xuICAgIHZhciBpLCBqO1xuXG4gICAgZnVuY3Rpb24gYWRkT25lSXRlbShsZWdlbmRHcm91cCwgbGVnZW5kSXRlbSkge1xuICAgICAgICAvLyBlYWNoICcnIGxlZ2VuZCBncm91cCBpcyB0cmVhdGVkIGFzIGEgc2VwYXJhdGUgZ3JvdXBcbiAgICAgICAgaWYobGVnZW5kR3JvdXAgPT09ICcnIHx8ICFoZWxwZXJzLmlzR3JvdXBlZChvcHRzKSkge1xuICAgICAgICAgICAgdmFyIHVuaXF1ZUdyb3VwID0gJ35+aScgKyBsZ3JvdXBpOyAvLyBUT0RPOiBjaGVjayB0aGlzIGFnYWluc3QgZnVsbERhdGEgbGVnZW5kZ3JvdXBzP1xuXG4gICAgICAgICAgICBsZ3JvdXBzLnB1c2godW5pcXVlR3JvdXApO1xuICAgICAgICAgICAgbGdyb3VwVG9UcmFjZXNbdW5pcXVlR3JvdXBdID0gW1tsZWdlbmRJdGVtXV07XG4gICAgICAgICAgICBsZ3JvdXBpKys7XG4gICAgICAgIH0gZWxzZSBpZihsZ3JvdXBzLmluZGV4T2YobGVnZW5kR3JvdXApID09PSAtMSkge1xuICAgICAgICAgICAgbGdyb3Vwcy5wdXNoKGxlZ2VuZEdyb3VwKTtcbiAgICAgICAgICAgIGhhc09uZU5vbkJsYW5rR3JvdXAgPSB0cnVlO1xuICAgICAgICAgICAgbGdyb3VwVG9UcmFjZXNbbGVnZW5kR3JvdXBdID0gW1tsZWdlbmRJdGVtXV07XG4gICAgICAgIH0gZWxzZSBsZ3JvdXBUb1RyYWNlc1tsZWdlbmRHcm91cF0ucHVzaChbbGVnZW5kSXRlbV0pO1xuICAgIH1cblxuICAgIC8vIGJ1aWxkIGFuIHsgbGVnZW5kZ3JvdXA6IFtjZDAsIGNkMF0sIC4uLiB9IG9iamVjdFxuICAgIGZvcihpID0gMDsgaSA8IGNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjZCA9IGNhbGNkYXRhW2ldO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICAgICAgdmFyIGxncm91cCA9IHRyYWNlLmxlZ2VuZGdyb3VwO1xuXG4gICAgICAgIGlmKCF0cmFjZS52aXNpYmxlIHx8ICF0cmFjZS5zaG93bGVnZW5kKSBjb250aW51ZTtcblxuICAgICAgICBpZihSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAncGllLWxpa2UnKSkge1xuICAgICAgICAgICAgaWYoIXNsaWNlc1Nob3duW2xncm91cF0pIHNsaWNlc1Nob3duW2xncm91cF0gPSB7fTtcblxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY2QubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgbGFiZWxqID0gY2Rbal0ubGFiZWw7XG5cbiAgICAgICAgICAgICAgICBpZighc2xpY2VzU2hvd25bbGdyb3VwXVtsYWJlbGpdKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZE9uZUl0ZW0obGdyb3VwLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogbGFiZWxqLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I6IGNkW2pdLmNvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgaTogY2Rbal0uaSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlOiB0cmFjZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHB0czogY2Rbal0ucHRzXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHNsaWNlc1Nob3duW2xncm91cF1bbGFiZWxqXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgYWRkT25lSXRlbShsZ3JvdXAsIGNkMCk7XG4gICAgfVxuXG4gICAgLy8gd29uJ3QgZHJhdyBhIGxlZ2VuZCBpbiB0aGlzIGNhc2VcbiAgICBpZighbGdyb3Vwcy5sZW5ndGgpIHJldHVybiBbXTtcblxuICAgIC8vIHJlYXJyYW5nZSBsZ3JvdXBUb1RyYWNlcyBpbnRvIGEgZDMtZnJpZW5kbHkgYXJyYXkgb2YgYXJyYXlzXG4gICAgdmFyIGxncm91cHNMZW5ndGggPSBsZ3JvdXBzLmxlbmd0aDtcbiAgICB2YXIgbHRyYWNlcztcbiAgICB2YXIgbGVnZW5kRGF0YTtcblxuICAgIGlmKGhhc09uZU5vbkJsYW5rR3JvdXAgJiYgaGVscGVycy5pc0dyb3VwZWQob3B0cykpIHtcbiAgICAgICAgbGVnZW5kRGF0YSA9IG5ldyBBcnJheShsZ3JvdXBzTGVuZ3RoKTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZ3JvdXBzTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGx0cmFjZXMgPSBsZ3JvdXBUb1RyYWNlc1tsZ3JvdXBzW2ldXTtcbiAgICAgICAgICAgIGxlZ2VuZERhdGFbaV0gPSBoZWxwZXJzLmlzUmV2ZXJzZWQob3B0cykgPyBsdHJhY2VzLnJldmVyc2UoKSA6IGx0cmFjZXM7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBjb2xsYXBzZSBhbGwgZ3JvdXBzIGludG8gb25lIGlmIGFsbCBncm91cHMgYXJlIGJsYW5rXG4gICAgICAgIGxlZ2VuZERhdGEgPSBbbmV3IEFycmF5KGxncm91cHNMZW5ndGgpXTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZ3JvdXBzTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGx0cmFjZXMgPSBsZ3JvdXBUb1RyYWNlc1tsZ3JvdXBzW2ldXVswXTtcbiAgICAgICAgICAgIGxlZ2VuZERhdGFbMF1baGVscGVycy5pc1JldmVyc2VkKG9wdHMpID8gbGdyb3Vwc0xlbmd0aCAtIGkgLSAxIDogaV0gPSBsdHJhY2VzO1xuICAgICAgICB9XG4gICAgICAgIGxncm91cHNMZW5ndGggPSAxO1xuICAgIH1cblxuICAgIC8vIG5lZWRlZCBpbiByZXBvc2l0aW9uTGVnZW5kXG4gICAgb3B0cy5fbGdyb3Vwc0xlbmd0aCA9IGxncm91cHNMZW5ndGg7XG4gICAgcmV0dXJuIGxlZ2VuZERhdGE7XG59O1xuXG59LHtcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9oZWxwZXJzXCI6NjQ4fV0sNjQ3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcblxudmFyIFNIT1dJU09MQVRFVElQID0gdHJ1ZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVDbGljayhnLCBnZCwgbnVtQ2xpY2tzKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIGlmKGdkLl9kcmFnZ2VkIHx8IGdkLl9lZGl0aW5nKSByZXR1cm47XG5cbiAgICB2YXIgaXRlbUNsaWNrID0gZnVsbExheW91dC5sZWdlbmQuaXRlbWNsaWNrO1xuICAgIHZhciBpdGVtRG91YmxlQ2xpY2sgPSBmdWxsTGF5b3V0LmxlZ2VuZC5pdGVtZG91YmxlY2xpY2s7XG5cbiAgICBpZihudW1DbGlja3MgPT09IDEgJiYgaXRlbUNsaWNrID09PSAndG9nZ2xlJyAmJiBpdGVtRG91YmxlQ2xpY2sgPT09ICd0b2dnbGVvdGhlcnMnICYmXG4gICAgICAgIFNIT1dJU09MQVRFVElQICYmIGdkLmRhdGEgJiYgZ2QuX2NvbnRleHQuc2hvd1RpcHNcbiAgICApIHtcbiAgICAgICAgTGliLm5vdGlmaWVyKExpYi5fKGdkLCAnRG91YmxlLWNsaWNrIG9uIGxlZ2VuZCB0byBpc29sYXRlIG9uZSB0cmFjZScpLCAnbG9uZycpO1xuICAgICAgICBTSE9XSVNPTEFURVRJUCA9IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIFNIT1dJU09MQVRFVElQID0gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIG1vZGU7XG4gICAgaWYobnVtQ2xpY2tzID09PSAxKSBtb2RlID0gaXRlbUNsaWNrO1xuICAgIGVsc2UgaWYobnVtQ2xpY2tzID09PSAyKSBtb2RlID0gaXRlbURvdWJsZUNsaWNrO1xuICAgIGlmKCFtb2RlKSByZXR1cm47XG5cbiAgICB2YXIgaGlkZGVuU2xpY2VzID0gZnVsbExheW91dC5oaWRkZW5sYWJlbHMgP1xuICAgICAgICBmdWxsTGF5b3V0LmhpZGRlbmxhYmVscy5zbGljZSgpIDpcbiAgICAgICAgW107XG5cbiAgICB2YXIgbGVnZW5kSXRlbSA9IGcuZGF0YSgpWzBdWzBdO1xuICAgIHZhciBmdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICB2YXIgZnVsbFRyYWNlID0gbGVnZW5kSXRlbS50cmFjZTtcbiAgICB2YXIgbGVnZW5kZ3JvdXAgPSBmdWxsVHJhY2UubGVnZW5kZ3JvdXA7XG5cbiAgICB2YXIgaSwgaiwga2NvbnQsIGtleSwga2V5cywgdmFsO1xuICAgIHZhciBhdHRyVXBkYXRlID0ge307XG4gICAgdmFyIGF0dHJJbmRpY2VzID0gW107XG4gICAgdmFyIGNhcnJzID0gW107XG4gICAgdmFyIGNhcnJJZHggPSBbXTtcblxuICAgIGZ1bmN0aW9uIGluc2VydFVwZGF0ZSh0cmFjZUluZGV4LCBrZXksIHZhbHVlKSB7XG4gICAgICAgIHZhciBhdHRySW5kZXggPSBhdHRySW5kaWNlcy5pbmRleE9mKHRyYWNlSW5kZXgpO1xuICAgICAgICB2YXIgdmFsdWVBcnJheSA9IGF0dHJVcGRhdGVba2V5XTtcbiAgICAgICAgaWYoIXZhbHVlQXJyYXkpIHtcbiAgICAgICAgICAgIHZhbHVlQXJyYXkgPSBhdHRyVXBkYXRlW2tleV0gPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF0dHJJbmRpY2VzLmluZGV4T2YodHJhY2VJbmRleCkgPT09IC0xKSB7XG4gICAgICAgICAgICBhdHRySW5kaWNlcy5wdXNoKHRyYWNlSW5kZXgpO1xuICAgICAgICAgICAgYXR0ckluZGV4ID0gYXR0ckluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlQXJyYXlbYXR0ckluZGV4XSA9IHZhbHVlO1xuXG4gICAgICAgIHJldHVybiBhdHRySW5kZXg7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0VmlzaWJpbGl0eShmdWxsVHJhY2UsIHZpc2liaWxpdHkpIHtcbiAgICAgICAgdmFyIGZ1bGxJbnB1dCA9IGZ1bGxUcmFjZS5fZnVsbElucHV0O1xuICAgICAgICBpZihSZWdpc3RyeS5oYXNUcmFuc2Zvcm0oZnVsbElucHV0LCAnZ3JvdXBieScpKSB7XG4gICAgICAgICAgICB2YXIga2NvbnQgPSBjYXJyc1tmdWxsSW5wdXQuaW5kZXhdO1xuICAgICAgICAgICAgaWYoIWtjb250KSB7XG4gICAgICAgICAgICAgICAgdmFyIGdyb3VwYnlJbmRpY2VzID0gUmVnaXN0cnkuZ2V0VHJhbnNmb3JtSW5kaWNlcyhmdWxsSW5wdXQsICdncm91cGJ5Jyk7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3RHcm91cGJ5SW5kZXggPSBncm91cGJ5SW5kaWNlc1tncm91cGJ5SW5kaWNlcy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICBrY29udCA9IExpYi5rZXllZENvbnRhaW5lcihmdWxsSW5wdXQsICd0cmFuc2Zvcm1zWycgKyBsYXN0R3JvdXBieUluZGV4ICsgJ10uc3R5bGVzJywgJ3RhcmdldCcsICd2YWx1ZS52aXNpYmxlJyk7XG4gICAgICAgICAgICAgICAgY2FycnNbZnVsbElucHV0LmluZGV4XSA9IGtjb250O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgY3VyU3RhdGUgPSBrY29udC5nZXQoZnVsbFRyYWNlLl9ncm91cCk7XG5cbiAgICAgICAgICAgIC8vIElmIG5vdCBzcGVjaWZpZWQsIGFzc3VtZSB2aXNpYmxlLiBUaGlzIGhhcHBlbnMgaWYgdGhlcmUgYXJlIG90aGVyIHN0eWxlXG4gICAgICAgICAgICAvLyBwcm9wZXJ0aWVzIHNldCBmb3IgYSBncm91cCBidXQgbm90IHRoZSB2aXNpYmlsaXR5LiBUaGVyZSBhcmUgbWFueSBzaW1pbGFyXG4gICAgICAgICAgICAvLyB3YXlzIHRvIGRvIHRoaXMgKGUuZy4gd2h5IG5vdCBqdXN0IGBjdXJTdGF0ZSA9IGZ1bGxUcmFjZS52aXNpYmxlYD8/PyBUaGVcbiAgICAgICAgICAgIC8vIGFuc3dlciBpczogYmVjYXVzZSBpdCBicmVha3Mgb3RoZXIgdGhpbmdzIGxpa2UgZ3JvdXBieSB0cmFjZSBuYW1lcyBpblxuICAgICAgICAgICAgLy8gc3VidGxlIHdheXMuKVxuICAgICAgICAgICAgaWYoY3VyU3RhdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGN1clN0YXRlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoY3VyU3RhdGUgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgLy8gdHJ1ZSAtPiBsZWdlbmRvbmx5LiBBbGwgb3RoZXJzIHRvZ2dsZSB0byB0cnVlOlxuICAgICAgICAgICAgICAgIGtjb250LnNldChmdWxsVHJhY2UuX2dyb3VwLCB2aXNpYmlsaXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhcnJJZHhbZnVsbElucHV0LmluZGV4XSA9IGluc2VydFVwZGF0ZShmdWxsSW5wdXQuaW5kZXgsICd2aXNpYmxlJywgZnVsbElucHV0LnZpc2libGUgPT09IGZhbHNlID8gZmFsc2UgOiB0cnVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGZhbHNlIC0+IGZhbHNlIChub3QgcG9zc2libGUgc2luY2Ugd2lsbCBub3QgYmUgdmlzaWJsZSBpbiBsZWdlbmQpXG4gICAgICAgICAgICAvLyB0cnVlIC0+IGxlZ2VuZG9ubHlcbiAgICAgICAgICAgIC8vIGxlZ2VuZG9ubHkgLT4gdHJ1ZVxuICAgICAgICAgICAgdmFyIG5leHRWaXNpYmlsaXR5ID0gZnVsbElucHV0LnZpc2libGUgPT09IGZhbHNlID8gZmFsc2UgOiB2aXNpYmlsaXR5O1xuXG4gICAgICAgICAgICBpbnNlcnRVcGRhdGUoZnVsbElucHV0LmluZGV4LCAndmlzaWJsZScsIG5leHRWaXNpYmlsaXR5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXMoZnVsbFRyYWNlLCAncGllLWxpa2UnKSkge1xuICAgICAgICB2YXIgdGhpc0xhYmVsID0gbGVnZW5kSXRlbS5sYWJlbDtcbiAgICAgICAgdmFyIHRoaXNMYWJlbEluZGV4ID0gaGlkZGVuU2xpY2VzLmluZGV4T2YodGhpc0xhYmVsKTtcblxuICAgICAgICBpZihtb2RlID09PSAndG9nZ2xlJykge1xuICAgICAgICAgICAgaWYodGhpc0xhYmVsSW5kZXggPT09IC0xKSBoaWRkZW5TbGljZXMucHVzaCh0aGlzTGFiZWwpO1xuICAgICAgICAgICAgZWxzZSBoaWRkZW5TbGljZXMuc3BsaWNlKHRoaXNMYWJlbEluZGV4LCAxKTtcbiAgICAgICAgfSBlbHNlIGlmKG1vZGUgPT09ICd0b2dnbGVvdGhlcnMnKSB7XG4gICAgICAgICAgICBoaWRkZW5TbGljZXMgPSBbXTtcbiAgICAgICAgICAgIGdkLmNhbGNkYXRhWzBdLmZvckVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIGlmKHRoaXNMYWJlbCAhPT0gZC5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBoaWRkZW5TbGljZXMucHVzaChkLmxhYmVsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmKGdkLl9mdWxsTGF5b3V0LmhpZGRlbmxhYmVscyAmJiBnZC5fZnVsbExheW91dC5oaWRkZW5sYWJlbHMubGVuZ3RoID09PSBoaWRkZW5TbGljZXMubGVuZ3RoICYmIHRoaXNMYWJlbEluZGV4ID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGhpZGRlblNsaWNlcyA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsICdoaWRkZW5sYWJlbHMnLCBoaWRkZW5TbGljZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBoYXNMZWdlbmRncm91cCA9IGxlZ2VuZGdyb3VwICYmIGxlZ2VuZGdyb3VwLmxlbmd0aDtcbiAgICAgICAgdmFyIHRyYWNlSW5kaWNlc0luR3JvdXAgPSBbXTtcbiAgICAgICAgdmFyIHRyYWNlaTtcbiAgICAgICAgaWYoaGFzTGVnZW5kZ3JvdXApIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdHJhY2VpID0gZnVsbERhdGFbaV07XG4gICAgICAgICAgICAgICAgaWYoIXRyYWNlaS52aXNpYmxlKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBpZih0cmFjZWkubGVnZW5kZ3JvdXAgPT09IGxlZ2VuZGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNlSW5kaWNlc0luR3JvdXAucHVzaChpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihtb2RlID09PSAndG9nZ2xlJykge1xuICAgICAgICAgICAgdmFyIG5leHRWaXNpYmlsaXR5O1xuXG4gICAgICAgICAgICBzd2l0Y2goZnVsbFRyYWNlLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIHRydWU6XG4gICAgICAgICAgICAgICAgICAgIG5leHRWaXNpYmlsaXR5ID0gJ2xlZ2VuZG9ubHknO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIGZhbHNlOlxuICAgICAgICAgICAgICAgICAgICBuZXh0VmlzaWJpbGl0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdsZWdlbmRvbmx5JzpcbiAgICAgICAgICAgICAgICAgICAgbmV4dFZpc2liaWxpdHkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaGFzTGVnZW5kZ3JvdXApIHtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZihmdWxsRGF0YVtpXS52aXNpYmxlICE9PSBmYWxzZSAmJiBmdWxsRGF0YVtpXS5sZWdlbmRncm91cCA9PT0gbGVnZW5kZ3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZpc2liaWxpdHkoZnVsbERhdGFbaV0sIG5leHRWaXNpYmlsaXR5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VmlzaWJpbGl0eShmdWxsVHJhY2UsIG5leHRWaXNpYmlsaXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKG1vZGUgPT09ICd0b2dnbGVvdGhlcnMnKSB7XG4gICAgICAgICAgICAvLyBDb21wdXRlIHRoZSBjbGlja2VkIGluZGV4LiBleHBhbmRlZEluZGV4IGRvZXMgd2hhdCB3ZSB3YW50IGZvciBleHBhbmRlZCB0cmFjZXNcbiAgICAgICAgICAgIC8vIGJ1dCBhbHNvIGN1bGxzIGhpZGRlbiB0cmFjZXMuIFRoYXQgbWVhbnMgd2UgaGF2ZSBzb21lIHdvcmsgdG8gZG8uXG4gICAgICAgICAgICB2YXIgaXNDbGlja2VkLCBpc0luR3JvdXAsIG90aGVyU3RhdGU7XG4gICAgICAgICAgICB2YXIgaXNJc29sYXRlZCA9IHRydWU7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlzQ2xpY2tlZCA9IGZ1bGxEYXRhW2ldID09PSBmdWxsVHJhY2U7XG4gICAgICAgICAgICAgICAgaWYoaXNDbGlja2VkKSBjb250aW51ZTtcblxuICAgICAgICAgICAgICAgIGlzSW5Hcm91cCA9IChoYXNMZWdlbmRncm91cCAmJiBmdWxsRGF0YVtpXS5sZWdlbmRncm91cCA9PT0gbGVnZW5kZ3JvdXApO1xuXG4gICAgICAgICAgICAgICAgaWYoIWlzSW5Hcm91cCAmJiBmdWxsRGF0YVtpXS52aXNpYmxlID09PSB0cnVlICYmICFSZWdpc3RyeS50cmFjZUlzKGZ1bGxEYXRhW2ldLCAnbm90TGVnZW5kSXNvbGF0YWJsZScpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzSXNvbGF0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIC8vIEZhbHNlIGlzIHN0aWNreTsgd2UgZG9uJ3QgY2hhbmdlIGl0LlxuICAgICAgICAgICAgICAgIGlmKGZ1bGxEYXRhW2ldLnZpc2libGUgPT09IGZhbHNlKSBjb250aW51ZTtcblxuICAgICAgICAgICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXMoZnVsbERhdGFbaV0sICdub3RMZWdlbmRJc29sYXRhYmxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgc3dpdGNoKGZ1bGxUcmFjZS52aXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2xlZ2VuZG9ubHknOlxuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VmlzaWJpbGl0eShmdWxsRGF0YVtpXSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSB0cnVlOlxuICAgICAgICAgICAgICAgICAgICAgICAgb3RoZXJTdGF0ZSA9IGlzSXNvbGF0ZWQgPyB0cnVlIDogJ2xlZ2VuZG9ubHknO1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNDbGlja2VkID0gZnVsbERhdGFbaV0gPT09IGZ1bGxUcmFjZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzSW5Hcm91cCA9IGlzQ2xpY2tlZCB8fCAoaGFzTGVnZW5kZ3JvdXAgJiYgZnVsbERhdGFbaV0ubGVnZW5kZ3JvdXAgPT09IGxlZ2VuZGdyb3VwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZpc2liaWxpdHkoZnVsbERhdGFbaV0sIGlzSW5Hcm91cCA/IHRydWUgOiBvdGhlclN0YXRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNhcnJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBrY29udCA9IGNhcnJzW2ldO1xuICAgICAgICAgICAgaWYoIWtjb250KSBjb250aW51ZTtcbiAgICAgICAgICAgIHZhciB1cGRhdGUgPSBrY29udC5jb25zdHJ1Y3RVcGRhdGUoKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZUtleXMgPSBPYmplY3Qua2V5cyh1cGRhdGUpO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgdXBkYXRlS2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGtleSA9IHVwZGF0ZUtleXNbal07XG4gICAgICAgICAgICAgICAgdmFsID0gYXR0clVwZGF0ZVtrZXldID0gYXR0clVwZGF0ZVtrZXldIHx8IFtdO1xuICAgICAgICAgICAgICAgIHZhbFtjYXJySWR4W2ldXSA9IHVwZGF0ZVtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhlIGxlbmd0aCBvZiB0aGUgdmFsdWUgYXJyYXlzIHNob3VsZCBiZSBlcXVhbCBhbmQgYW55IHVuc3BlY2lmaWVkXG4gICAgICAgIC8vIHZhbHVlcyBzaG91bGQgYmUgZXhwbGljaXRseSB1bmRlZmluZWQgZm9yIHRoZW0gdG8gZ2V0IHByb3Blcmx5IGN1bGxlZFxuICAgICAgICAvLyBhcyB1cGRhdGVzIGFuZCBub3QgYWNjaWRlbnRhbGx5IHJlc2V0IHRvIHRoZSBkZWZhdWx0IHZhbHVlLiBUaGlzIGZpbGxzXG4gICAgICAgIC8vIG91dCBzcGFyc2UgYXJyYXlzIHdpdGggdGhlIHJlcXVpcmVkIG51bWJlciBvZiB1bmRlZmluZWQgdmFsdWVzOlxuICAgICAgICBrZXlzID0gT2JqZWN0LmtleXMoYXR0clVwZGF0ZSk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBhdHRySW5kaWNlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIC8vIFVzZSBoYXNPd25Qcm9wZXR5IHRvIHByb3RlY3QgYWdhaW5zdCBmYWxzZXkgdmFsdWVzOlxuICAgICAgICAgICAgICAgIGlmKCFhdHRyVXBkYXRlW2tleV0uaGFzT3duUHJvcGVydHkoaikpIHtcbiAgICAgICAgICAgICAgICAgICAgYXR0clVwZGF0ZVtrZXldW2pdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZXN0eWxlJywgZ2QsIGF0dHJVcGRhdGUsIGF0dHJJbmRpY2VzKTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3fV0sNjQ4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLmlzR3JvdXBlZCA9IGZ1bmN0aW9uIGlzR3JvdXBlZChsZWdlbmRMYXlvdXQpIHtcbiAgICByZXR1cm4gKGxlZ2VuZExheW91dC50cmFjZW9yZGVyIHx8ICcnKS5pbmRleE9mKCdncm91cGVkJykgIT09IC0xO1xufTtcblxuZXhwb3J0cy5pc1ZlcnRpY2FsID0gZnVuY3Rpb24gaXNWZXJ0aWNhbChsZWdlbmRMYXlvdXQpIHtcbiAgICByZXR1cm4gbGVnZW5kTGF5b3V0Lm9yaWVudGF0aW9uICE9PSAnaCc7XG59O1xuXG5leHBvcnRzLmlzUmV2ZXJzZWQgPSBmdW5jdGlvbiBpc1JldmVyc2VkKGxlZ2VuZExheW91dCkge1xuICAgIHJldHVybiAobGVnZW5kTGF5b3V0LnRyYWNlb3JkZXIgfHwgJycpLmluZGV4T2YoJ3JldmVyc2VkJykgIT09IC0xO1xufTtcblxufSx7fV0sNjQ5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICdjb21wb25lbnQnLFxuICAgIG5hbWU6ICdsZWdlbmQnLFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcblxuICAgIGRyYXc6IF9kZXJlcV8oJy4vZHJhdycpLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuL3N0eWxlJylcbn07XG5cbn0se1wiLi9hdHRyaWJ1dGVzXCI6NjQyLFwiLi9kZWZhdWx0c1wiOjY0NCxcIi4vZHJhd1wiOjY0NSxcIi4vc3R5bGVcIjo2NTB9XSw2NTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi9kcmF3aW5nJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb2xvcicpO1xuXG52YXIgc3ViVHlwZXMgPSBfZGVyZXFfKCcuLi8uLi90cmFjZXMvc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIHN0eWxlUGllID0gX2RlcmVxXygnLi4vLi4vdHJhY2VzL3BpZS9zdHlsZV9vbmUnKTtcbnZhciBwaWVDYXN0T3B0aW9uID0gX2RlcmVxXygnLi4vLi4vdHJhY2VzL3BpZS9oZWxwZXJzJykuY2FzdE9wdGlvbjtcblxudmFyIENTVF9NQVJLRVJfU0laRSA9IDEyO1xudmFyIENTVF9MSU5FX1dJRFRIID0gNTtcbnZhciBDU1RfTUFSS0VSX0xJTkVfV0lEVEggPSAyO1xudmFyIE1BWF9MSU5FX1dJRFRIID0gMTA7XG52YXIgTUFYX01BUktFUl9MSU5FX1dJRFRIID0gNTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHlsZShzLCBnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGxlZ2VuZCA9IGZ1bGxMYXlvdXQubGVnZW5kO1xuICAgIHZhciBjb25zdGFudEl0ZW1TaXppbmcgPSBsZWdlbmQuaXRlbXNpemluZyA9PT0gJ2NvbnN0YW50JztcblxuICAgIGZ1bmN0aW9uIGJvdW5kTGluZVdpZHRoKG1sdywgY29udCwgbWF4LCBjc3QpIHtcbiAgICAgICAgdmFyIHY7XG4gICAgICAgIGlmKG1sdyArIDEpIHtcbiAgICAgICAgICAgIHYgPSBtbHc7XG4gICAgICAgIH0gZWxzZSBpZihjb250ICYmIGNvbnQud2lkdGggPiAwKSB7XG4gICAgICAgICAgICB2ID0gY29udC53aWR0aDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb25zdGFudEl0ZW1TaXppbmcgPyBjc3QgOiBNYXRoLm1pbih2LCBtYXgpO1xuICAgIH1cblxuICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciB0cmFjZUdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIHZhciBsYXllcnMgPSBMaWIuZW5zdXJlU2luZ2xlKHRyYWNlR3JvdXAsICdnJywgJ2xheWVycycpO1xuICAgICAgICBsYXllcnMuc3R5bGUoJ29wYWNpdHknLCBkWzBdLnRyYWNlLm9wYWNpdHkpO1xuXG4gICAgICAgIHZhciB2YWxpZ24gPSBsZWdlbmQudmFsaWduO1xuICAgICAgICB2YXIgbGluZUhlaWdodCA9IGRbMF0ubGluZUhlaWdodDtcbiAgICAgICAgdmFyIGhlaWdodCA9IGRbMF0uaGVpZ2h0O1xuXG4gICAgICAgIGlmKHZhbGlnbiA9PT0gJ21pZGRsZScgfHwgIWxpbmVIZWlnaHQgfHwgIWhlaWdodCkge1xuICAgICAgICAgICAgbGF5ZXJzLmF0dHIoJ3RyYW5zZm9ybScsIG51bGwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGZhY3RvciA9IHt0b3A6IDEsIGJvdHRvbTogLTF9W3ZhbGlnbl07XG4gICAgICAgICAgICB2YXIgbWFya2VyT2Zmc2V0WSA9IGZhY3RvciAqICgwLjUgKiAobGluZUhlaWdodCAtIGhlaWdodCArIDMpKTtcbiAgICAgICAgICAgIGxheWVycy5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDAsJyArIG1hcmtlck9mZnNldFkgKyAnKScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGZpbGwgPSBsYXllcnNcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJ2cubGVnZW5kZmlsbCcpXG4gICAgICAgICAgICAgICAgLmRhdGEoW2RdKTtcbiAgICAgICAgZmlsbC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAuY2xhc3NlZCgnbGVnZW5kZmlsbCcsIHRydWUpO1xuXG4gICAgICAgIHZhciBsaW5lID0gbGF5ZXJzXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCdnLmxlZ2VuZGxpbmVzJylcbiAgICAgICAgICAgICAgICAuZGF0YShbZF0pO1xuICAgICAgICBsaW5lLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdsZWdlbmRsaW5lcycsIHRydWUpO1xuXG4gICAgICAgIHZhciBzeW1ib2wgPSBsYXllcnNcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJ2cubGVnZW5kc3ltYm9scycpXG4gICAgICAgICAgICAgICAgLmRhdGEoW2RdKTtcbiAgICAgICAgc3ltYm9sLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdsZWdlbmRzeW1ib2xzJywgdHJ1ZSk7XG5cbiAgICAgICAgc3ltYm9sLnNlbGVjdEFsbCgnZy5sZWdlbmRwb2ludHMnKVxuICAgICAgICAgICAgLmRhdGEoW2RdKVxuICAgICAgICAgIC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAuY2xhc3NlZCgnbGVnZW5kcG9pbnRzJywgdHJ1ZSk7XG4gICAgfSlcbiAgICAuZWFjaChzdHlsZVdhdGVyZmFsbHMpXG4gICAgLmVhY2goc3R5bGVGdW5uZWxzKVxuICAgIC5lYWNoKHN0eWxlQmFycylcbiAgICAuZWFjaChzdHlsZUJveGVzKVxuICAgIC5lYWNoKHN0eWxlRnVubmVsYXJlYXMpXG4gICAgLmVhY2goc3R5bGVQaWVzKVxuICAgIC5lYWNoKHN0eWxlTGluZXMpXG4gICAgLmVhY2goc3R5bGVQb2ludHMpXG4gICAgLmVhY2goc3R5bGVDYW5kbGVzKVxuICAgIC5lYWNoKHN0eWxlT0hMQyk7XG5cbiAgICBmdW5jdGlvbiBzdHlsZUxpbmVzKGQpIHtcbiAgICAgICAgdmFyIGQwID0gZFswXTtcbiAgICAgICAgdmFyIHRyYWNlID0gZDAudHJhY2U7XG4gICAgICAgIHZhciBzaG93RmlsbCA9IHRyYWNlLnZpc2libGUgJiYgdHJhY2UuZmlsbCAmJiB0cmFjZS5maWxsICE9PSAnbm9uZSc7XG4gICAgICAgIHZhciBzaG93TGluZSA9IHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlKTtcbiAgICAgICAgdmFyIGNvbnRvdXJzID0gdHJhY2UuY29udG91cnM7XG4gICAgICAgIHZhciBzaG93R3JhZGllbnRMaW5lID0gZmFsc2U7XG4gICAgICAgIHZhciBzaG93R3JhZGllbnRGaWxsID0gZmFsc2U7XG4gICAgICAgIHZhciBkTW9kLCB0TW9kO1xuXG4gICAgICAgIGlmKGNvbnRvdXJzKSB7XG4gICAgICAgICAgICB2YXIgY29sb3JpbmcgPSBjb250b3Vycy5jb2xvcmluZztcblxuICAgICAgICAgICAgaWYoY29sb3JpbmcgPT09ICdsaW5lcycpIHtcbiAgICAgICAgICAgICAgICBzaG93R3JhZGllbnRMaW5lID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2hvd0xpbmUgPSBjb2xvcmluZyA9PT0gJ25vbmUnIHx8IGNvbG9yaW5nID09PSAnaGVhdG1hcCcgfHwgY29udG91cnMuc2hvd2xpbmVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihjb250b3Vycy50eXBlID09PSAnY29uc3RyYWludCcpIHtcbiAgICAgICAgICAgICAgICBzaG93RmlsbCA9IGNvbnRvdXJzLl9vcGVyYXRpb24gIT09ICc9JztcbiAgICAgICAgICAgIH0gZWxzZSBpZihjb2xvcmluZyA9PT0gJ2ZpbGwnIHx8IGNvbG9yaW5nID09PSAnaGVhdG1hcCcpIHtcbiAgICAgICAgICAgICAgICBzaG93R3JhZGllbnRGaWxsID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHdpdGggZmlsbCBhbmQgbm8gbWFya2VycyBvciB0ZXh0LCBtb3ZlIHRoZSBsaW5lIGFuZCBmaWxsIHVwIGEgYml0XG4gICAgICAgIC8vIHNvIGl0J3MgbW9yZSBjZW50ZXJlZFxuICAgICAgICB2YXIgbWFya2Vyc09yVGV4dCA9IHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpIHx8IHN1YlR5cGVzLmhhc1RleHQodHJhY2UpO1xuICAgICAgICB2YXIgYW55RmlsbCA9IHNob3dGaWxsIHx8IHNob3dHcmFkaWVudEZpbGw7XG4gICAgICAgIHZhciBhbnlMaW5lID0gc2hvd0xpbmUgfHwgc2hvd0dyYWRpZW50TGluZTtcbiAgICAgICAgdmFyIHBhdGhTdGFydCA9IChtYXJrZXJzT3JUZXh0IHx8ICFhbnlGaWxsKSA/ICdNNSwwJyA6XG4gICAgICAgICAgICAvLyB3aXRoIGEgbGluZSBsZWF2ZSBpdCBzbGlnaHRseSBiZWxvdyBjZW50ZXIsIHRvIGxlYXZlIHJvb20gZm9yIHRoZVxuICAgICAgICAgICAgLy8gbGluZSB0aGlja25lc3MgYW5kIGJlY2F1c2UgdGhlIGxpbmUgaXMgdXN1YWxseSBtb3JlIHByb21pbmVudFxuICAgICAgICAgICAgYW55TGluZSA/ICdNNSwtMicgOiAnTTUsLTMnO1xuXG4gICAgICAgIHZhciB0aGlzMyA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICB2YXIgZmlsbCA9IHRoaXMzLnNlbGVjdCgnLmxlZ2VuZGZpbGwnKS5zZWxlY3RBbGwoJ3BhdGgnKVxuICAgICAgICAgICAgLmRhdGEoc2hvd0ZpbGwgfHwgc2hvd0dyYWRpZW50RmlsbCA/IFtkXSA6IFtdKTtcbiAgICAgICAgZmlsbC5lbnRlcigpLmFwcGVuZCgncGF0aCcpLmNsYXNzZWQoJ2pzLWZpbGwnLCB0cnVlKTtcbiAgICAgICAgZmlsbC5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIGZpbGwuYXR0cignZCcsIHBhdGhTdGFydCArICdoMzB2NmgtMzB6JylcbiAgICAgICAgICAgIC5jYWxsKHNob3dGaWxsID8gRHJhd2luZy5maWxsR3JvdXBTdHlsZSA6IGZpbGxHcmFkaWVudCk7XG5cbiAgICAgICAgaWYoc2hvd0xpbmUgfHwgc2hvd0dyYWRpZW50TGluZSkge1xuICAgICAgICAgICAgdmFyIGx3ID0gYm91bmRMaW5lV2lkdGgodW5kZWZpbmVkLCB0cmFjZS5saW5lLCBNQVhfTElORV9XSURUSCwgQ1NUX0xJTkVfV0lEVEgpO1xuICAgICAgICAgICAgdE1vZCA9IExpYi5taW5FeHRlbmQodHJhY2UsIHtsaW5lOiB7d2lkdGg6IGx3fX0pO1xuICAgICAgICAgICAgZE1vZCA9IFtMaWIubWluRXh0ZW5kKGQwLCB7dHJhY2U6IHRNb2R9KV07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgbGluZSA9IHRoaXMzLnNlbGVjdCgnLmxlZ2VuZGxpbmVzJykuc2VsZWN0QWxsKCdwYXRoJylcbiAgICAgICAgICAgIC5kYXRhKHNob3dMaW5lIHx8IHNob3dHcmFkaWVudExpbmUgPyBbZE1vZF0gOiBbXSk7XG4gICAgICAgIGxpbmUuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKS5jbGFzc2VkKCdqcy1saW5lJywgdHJ1ZSk7XG4gICAgICAgIGxpbmUuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIC8vIHRoaXMgaXMgdWdseS4uLiBidXQgeW91IGNhbid0IGFwcGx5IGEgZ3JhZGllbnQgdG8gYSBwZXJmZWN0bHlcbiAgICAgICAgLy8gaG9yaXpvbnRhbCBvciB2ZXJ0aWNhbCBsaW5lLiBQcmVzdW1hYmx5IGJlY2F1c2UgdGhlblxuICAgICAgICAvLyB0aGUgc3lzdGVtIGRvZXNuJ3Qga25vdyBob3cgdG8gc2NhbGUgdmVydGljYWwgdmFyaWF0aW9uLCBldmVuXG4gICAgICAgIC8vIHRob3VnaCB0aGVyZSAqaXMqIG5vIHZlcnRpY2FsIHZhcmlhdGlvbiBpbiB0aGlzIGNhc2UuXG4gICAgICAgIC8vIHNvIGFkZCBhbiBpbnZpc2libHkgc21hbGwgYW5nbGUgdG8gdGhlIGxpbmVcbiAgICAgICAgLy8gVGhpcyBpc3N1ZSAoYW5kIHdvcmthcm91bmQpIGV4aXN0IGFjcm9zcyAoTWFjKSBDaHJvbWUsIEZGLCBhbmQgU2FmYXJpXG4gICAgICAgIGxpbmUuYXR0cignZCcsIHBhdGhTdGFydCArIChzaG93R3JhZGllbnRMaW5lID8gJ2wzMCwwLjAwMDEnIDogJ2gzMCcpKVxuICAgICAgICAgICAgLmNhbGwoc2hvd0xpbmUgPyBEcmF3aW5nLmxpbmVHcm91cFN0eWxlIDogbGluZUdyYWRpZW50KTtcblxuICAgICAgICBmdW5jdGlvbiBmaWxsR3JhZGllbnQocykge1xuICAgICAgICAgICAgaWYocy5zaXplKCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JhZGllbnRJRCA9ICdsZWdlbmRmaWxsLScgKyB0cmFjZS51aWQ7XG4gICAgICAgICAgICAgICAgRHJhd2luZy5ncmFkaWVudChzLCBnZCwgZ3JhZGllbnRJRCwgJ2hvcml6b250YWxyZXZlcnNlZCcsXG4gICAgICAgICAgICAgICAgICAgIHRyYWNlLmNvbG9yc2NhbGUsICdmaWxsJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBsaW5lR3JhZGllbnQocykge1xuICAgICAgICAgICAgaWYocy5zaXplKCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JhZGllbnRJRCA9ICdsZWdlbmRsaW5lLScgKyB0cmFjZS51aWQ7XG4gICAgICAgICAgICAgICAgRHJhd2luZy5saW5lR3JvdXBTdHlsZShzKTtcbiAgICAgICAgICAgICAgICBEcmF3aW5nLmdyYWRpZW50KHMsIGdkLCBncmFkaWVudElELCAnaG9yaXpvbnRhbHJldmVyc2VkJyxcbiAgICAgICAgICAgICAgICAgICAgdHJhY2UuY29sb3JzY2FsZSwgJ3N0cm9rZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3R5bGVQb2ludHMoZCkge1xuICAgICAgICB2YXIgZDAgPSBkWzBdO1xuICAgICAgICB2YXIgdHJhY2UgPSBkMC50cmFjZTtcbiAgICAgICAgdmFyIHNob3dNYXJrZXJzID0gc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSk7XG4gICAgICAgIHZhciBzaG93VGV4dCA9IHN1YlR5cGVzLmhhc1RleHQodHJhY2UpO1xuICAgICAgICB2YXIgc2hvd0xpbmVzID0gc3ViVHlwZXMuaGFzTGluZXModHJhY2UpO1xuICAgICAgICB2YXIgZE1vZCwgdE1vZDtcblxuICAgICAgICAvLyAnc2NhdHRlcjNkJyBkb24ndCB1c2UgZ2QuY2FsY2RhdGEsXG4gICAgICAgIC8vIHVzZSBkMC50cmFjZSB0byBpbmZlciBhcnJheU9rIGF0dHJpYnV0ZXNcblxuICAgICAgICBmdW5jdGlvbiBib3VuZFZhbChhdHRySW4sIGFycmF5VG9WYWxGbiwgYm91bmRzLCBjc3QpIHtcbiAgICAgICAgICAgIHZhciB2YWxJbiA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgYXR0ckluKS5nZXQoKTtcbiAgICAgICAgICAgIHZhciB2YWxUb0JvdW5kID0gKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHZhbEluKSAmJiBhcnJheVRvVmFsRm4pID9cbiAgICAgICAgICAgICAgICBhcnJheVRvVmFsRm4odmFsSW4pIDpcbiAgICAgICAgICAgICAgICB2YWxJbjtcblxuICAgICAgICAgICAgaWYoY29uc3RhbnRJdGVtU2l6aW5nICYmIHZhbFRvQm91bmQgJiYgY3N0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB2YWxUb0JvdW5kID0gY3N0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihib3VuZHMpIHtcbiAgICAgICAgICAgICAgICBpZih2YWxUb0JvdW5kIDwgYm91bmRzWzBdKSByZXR1cm4gYm91bmRzWzBdO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYodmFsVG9Cb3VuZCA+IGJvdW5kc1sxXSkgcmV0dXJuIGJvdW5kc1sxXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB2YWxUb0JvdW5kO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcGlja0ZpcnN0KGFycmF5KSB7IHJldHVybiBhcnJheVswXTsgfVxuXG4gICAgICAgIC8vIGNvbnN0cmFpbiB0ZXh0LCBtYXJrZXJzLCBldGMgc28gdGhleSdsbCBmaXQgb24gdGhlIGxlZ2VuZFxuICAgICAgICBpZihzaG93TWFya2VycyB8fCBzaG93VGV4dCB8fCBzaG93TGluZXMpIHtcbiAgICAgICAgICAgIHZhciBkRWRpdCA9IHt9O1xuICAgICAgICAgICAgdmFyIHRFZGl0ID0ge307XG5cbiAgICAgICAgICAgIGlmKHNob3dNYXJrZXJzKSB7XG4gICAgICAgICAgICAgICAgZEVkaXQubWMgPSBib3VuZFZhbCgnbWFya2VyLmNvbG9yJywgcGlja0ZpcnN0KTtcbiAgICAgICAgICAgICAgICBkRWRpdC5teCA9IGJvdW5kVmFsKCdtYXJrZXIuc3ltYm9sJywgcGlja0ZpcnN0KTtcbiAgICAgICAgICAgICAgICBkRWRpdC5tbyA9IGJvdW5kVmFsKCdtYXJrZXIub3BhY2l0eScsIExpYi5tZWFuLCBbMC4yLCAxXSk7XG4gICAgICAgICAgICAgICAgZEVkaXQubWxjID0gYm91bmRWYWwoJ21hcmtlci5saW5lLmNvbG9yJywgcGlja0ZpcnN0KTtcbiAgICAgICAgICAgICAgICBkRWRpdC5tbHcgPSBib3VuZFZhbCgnbWFya2VyLmxpbmUud2lkdGgnLCBMaWIubWVhbiwgWzAsIDVdLCBDU1RfTUFSS0VSX0xJTkVfV0lEVEgpO1xuICAgICAgICAgICAgICAgIHRFZGl0Lm1hcmtlciA9IHtcbiAgICAgICAgICAgICAgICAgICAgc2l6ZXJlZjogMSxcbiAgICAgICAgICAgICAgICAgICAgc2l6ZW1pbjogMSxcbiAgICAgICAgICAgICAgICAgICAgc2l6ZW1vZGU6ICdkaWFtZXRlcidcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgdmFyIG1zID0gYm91bmRWYWwoJ21hcmtlci5zaXplJywgTGliLm1lYW4sIFsyLCAxNl0sIENTVF9NQVJLRVJfU0laRSk7XG4gICAgICAgICAgICAgICAgZEVkaXQubXMgPSBtcztcbiAgICAgICAgICAgICAgICB0RWRpdC5tYXJrZXIuc2l6ZSA9IG1zO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihzaG93TGluZXMpIHtcbiAgICAgICAgICAgICAgICB0RWRpdC5saW5lID0ge1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogYm91bmRWYWwoJ2xpbmUud2lkdGgnLCBwaWNrRmlyc3QsIFswLCAxMF0sIENTVF9MSU5FX1dJRFRIKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHNob3dUZXh0KSB7XG4gICAgICAgICAgICAgICAgZEVkaXQudHggPSAnQWEnO1xuICAgICAgICAgICAgICAgIGRFZGl0LnRwID0gYm91bmRWYWwoJ3RleHRwb3NpdGlvbicsIHBpY2tGaXJzdCk7XG4gICAgICAgICAgICAgICAgZEVkaXQudHMgPSAxMDtcbiAgICAgICAgICAgICAgICBkRWRpdC50YyA9IGJvdW5kVmFsKCd0ZXh0Zm9udC5jb2xvcicsIHBpY2tGaXJzdCk7XG4gICAgICAgICAgICAgICAgZEVkaXQudGYgPSBib3VuZFZhbCgndGV4dGZvbnQuZmFtaWx5JywgcGlja0ZpcnN0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZE1vZCA9IFtMaWIubWluRXh0ZW5kKGQwLCBkRWRpdCldO1xuICAgICAgICAgICAgdE1vZCA9IExpYi5taW5FeHRlbmQodHJhY2UsIHRFZGl0KTtcblxuICAgICAgICAgICAgLy8gYWx3YXlzIHNob3cgbGVnZW5kIGl0ZW1zIGluIGJhc2Ugc3RhdGVcbiAgICAgICAgICAgIHRNb2Quc2VsZWN0ZWRwb2ludHMgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHB0Z3JvdXAgPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0KCdnLmxlZ2VuZHBvaW50cycpO1xuXG4gICAgICAgIHZhciBwdHMgPSBwdGdyb3VwLnNlbGVjdEFsbCgncGF0aC5zY2F0dGVycHRzJylcbiAgICAgICAgICAgIC5kYXRhKHNob3dNYXJrZXJzID8gZE1vZCA6IFtdKTtcbiAgICAgICAgLy8gbWFrZSBzdXJlIG1hcmtlciBpcyBvbiB0aGUgYm90dG9tLCBpbiBjYXNlIGl0IGVudGVycyBhZnRlciB0ZXh0XG4gICAgICAgIHB0cy5lbnRlcigpLmluc2VydCgncGF0aCcsICc6Zmlyc3QtY2hpbGQnKVxuICAgICAgICAgICAgLmNsYXNzZWQoJ3NjYXR0ZXJwdHMnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMjAsMCknKTtcbiAgICAgICAgcHRzLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgcHRzLmNhbGwoRHJhd2luZy5wb2ludFN0eWxlLCB0TW9kLCBnZCk7XG5cbiAgICAgICAgLy8gJ21yYycgaXMgc2V0IGluIHBvaW50U3R5bGUgYW5kIHVzZWQgaW4gdGV4dFBvaW50U3R5bGU6XG4gICAgICAgIC8vIGNvbnN0cmFpbiBpdCBoZXJlXG4gICAgICAgIGlmKHNob3dNYXJrZXJzKSBkTW9kWzBdLm1yYyA9IDM7XG5cbiAgICAgICAgdmFyIHR4dCA9IHB0Z3JvdXAuc2VsZWN0QWxsKCdnLnBvaW50dGV4dCcpXG4gICAgICAgICAgICAuZGF0YShzaG93VGV4dCA/IGRNb2QgOiBbXSk7XG4gICAgICAgIHR4dC5lbnRlcigpXG4gICAgICAgICAgICAuYXBwZW5kKCdnJykuY2xhc3NlZCgncG9pbnR0ZXh0JywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAuYXBwZW5kKCd0ZXh0JykuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgyMCwwKScpO1xuICAgICAgICB0eHQuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICB0eHQuc2VsZWN0QWxsKCd0ZXh0JykuY2FsbChEcmF3aW5nLnRleHRQb2ludFN0eWxlLCB0TW9kLCBnZCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3R5bGVXYXRlcmZhbGxzKGQpIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZTtcblxuICAgICAgICB2YXIgcHRzRGF0YSA9IFtdO1xuICAgICAgICBpZih0cmFjZS50eXBlID09PSAnd2F0ZXJmYWxsJyAmJiB0cmFjZS52aXNpYmxlKSB7XG4gICAgICAgICAgICBwdHNEYXRhID0gZFswXS5oYXNUb3RhbHMgP1xuICAgICAgICAgICAgICAgIFtbJ2luY3JlYXNpbmcnLCAnTS02LC02VjZIMFonXSwgWyd0b3RhbHMnLCAnTTYsNkgwTC02LC02SC0wWiddLCBbJ2RlY3JlYXNpbmcnLCAnTTYsNlYtNkgwWiddXSA6XG4gICAgICAgICAgICAgICAgW1snaW5jcmVhc2luZycsICdNLTYsLTZWNkg2WiddLCBbJ2RlY3JlYXNpbmcnLCAnTTYsNlYtNkgtNlonXV07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcHRzID0gZDMuc2VsZWN0KHRoaXMpLnNlbGVjdCgnZy5sZWdlbmRwb2ludHMnKVxuICAgICAgICAgICAgLnNlbGVjdEFsbCgncGF0aC5sZWdlbmR3YXRlcmZhbGwnKVxuICAgICAgICAgICAgLmRhdGEocHRzRGF0YSk7XG4gICAgICAgIHB0cy5lbnRlcigpLmFwcGVuZCgncGF0aCcpLmNsYXNzZWQoJ2xlZ2VuZHdhdGVyZmFsbCcsIHRydWUpXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgyMCwwKScpXG4gICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMSk7XG4gICAgICAgIHB0cy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgcHRzLmVhY2goZnVuY3Rpb24oZGQpIHtcbiAgICAgICAgICAgIHZhciBwdCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBjb250ID0gdHJhY2VbZGRbMF1dLm1hcmtlcjtcbiAgICAgICAgICAgIHZhciBsdyA9IGJvdW5kTGluZVdpZHRoKHVuZGVmaW5lZCwgY29udC5saW5lLCBNQVhfTUFSS0VSX0xJTkVfV0lEVEgsIENTVF9NQVJLRVJfTElORV9XSURUSCk7XG5cbiAgICAgICAgICAgIHB0LmF0dHIoJ2QnLCBkZFsxXSlcbiAgICAgICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIGx3ICsgJ3B4JylcbiAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBjb250LmNvbG9yKTtcblxuICAgICAgICAgICAgaWYobHcpIHtcbiAgICAgICAgICAgICAgICBwdC5jYWxsKENvbG9yLnN0cm9rZSwgY29udC5saW5lLmNvbG9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3R5bGVCYXJzKGQpIHtcbiAgICAgICAgc3R5bGVCYXJMaWtlKGQsIHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0eWxlRnVubmVscyhkKSB7XG4gICAgICAgIHN0eWxlQmFyTGlrZShkLCB0aGlzLCAnZnVubmVsJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3R5bGVCYXJMaWtlKGQsIGxUaGlzLCBkZXNpcmVkVHlwZSkge1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuICAgICAgICB2YXIgbWFya2VyID0gdHJhY2UubWFya2VyIHx8IHt9O1xuICAgICAgICB2YXIgbWFya2VyTGluZSA9IG1hcmtlci5saW5lIHx8IHt9O1xuXG4gICAgICAgIHZhciBpc1Zpc2libGUgPSAoIWRlc2lyZWRUeXBlKSA/IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdiYXInKSA6XG4gICAgICAgICAgICAodHJhY2UudHlwZSA9PT0gZGVzaXJlZFR5cGUgJiYgdHJhY2UudmlzaWJsZSk7XG5cbiAgICAgICAgdmFyIGJhcnBhdGggPSBkMy5zZWxlY3QobFRoaXMpLnNlbGVjdCgnZy5sZWdlbmRwb2ludHMnKVxuICAgICAgICAgICAgLnNlbGVjdEFsbCgncGF0aC5sZWdlbmQnICsgZGVzaXJlZFR5cGUpXG4gICAgICAgICAgICAuZGF0YShpc1Zpc2libGUgPyBbZF0gOiBbXSk7XG4gICAgICAgIGJhcnBhdGguZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKS5jbGFzc2VkKCdsZWdlbmQnICsgZGVzaXJlZFR5cGUsIHRydWUpXG4gICAgICAgICAgICAuYXR0cignZCcsICdNNiw2SC02Vi02SDZaJylcbiAgICAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDIwLDApJyk7XG4gICAgICAgIGJhcnBhdGguZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIGJhcnBhdGguZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgcCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBkMCA9IGRbMF07XG4gICAgICAgICAgICB2YXIgdyA9IGJvdW5kTGluZVdpZHRoKGQwLm1sdywgbWFya2VyLmxpbmUsIE1BWF9NQVJLRVJfTElORV9XSURUSCwgQ1NUX01BUktFUl9MSU5FX1dJRFRIKTtcblxuICAgICAgICAgICAgcC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgdyArICdweCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgZDAubWMgfHwgbWFya2VyLmNvbG9yKTtcblxuICAgICAgICAgICAgaWYodykgQ29sb3Iuc3Ryb2tlKHAsIGQwLm1sYyB8fCBtYXJrZXJMaW5lLmNvbG9yKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3R5bGVCb3hlcyhkKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGRbMF0udHJhY2U7XG5cbiAgICAgICAgdmFyIHB0cyA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoJ2cubGVnZW5kcG9pbnRzJylcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJ3BhdGgubGVnZW5kYm94JylcbiAgICAgICAgICAgIC5kYXRhKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdib3gtdmlvbGluJykgJiYgdHJhY2UudmlzaWJsZSA/IFtkXSA6IFtdKTtcbiAgICAgICAgcHRzLmVudGVyKCkuYXBwZW5kKCdwYXRoJykuY2xhc3NlZCgnbGVnZW5kYm94JywgdHJ1ZSlcbiAgICAgICAgICAgIC8vIGlmIHdlIHdhbnQgdGhlIG1lZGlhbiBiYXIsIHByZXBlbmQgTTYsMEgtNlxuICAgICAgICAgICAgLmF0dHIoJ2QnLCAnTTYsNkgtNlYtNkg2WicpXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgyMCwwKScpO1xuICAgICAgICBwdHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIHB0cy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHAgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgICAgIGlmKCh0cmFjZS5ib3hwb2ludHMgPT09ICdhbGwnIHx8IHRyYWNlLnBvaW50cyA9PT0gJ2FsbCcpICYmXG4gICAgICAgICAgICAgICAgQ29sb3Iub3BhY2l0eSh0cmFjZS5maWxsY29sb3IpID09PSAwICYmIENvbG9yLm9wYWNpdHkoKHRyYWNlLmxpbmUgfHwge30pLmNvbG9yKSA9PT0gMFxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRNb2QgPSBMaWIubWluRXh0ZW5kKHRyYWNlLCB7XG4gICAgICAgICAgICAgICAgICAgIG1hcmtlcjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogY29uc3RhbnRJdGVtU2l6aW5nID8gQ1NUX01BUktFUl9TSVpFIDogTGliLmNvbnN0cmFpbih0cmFjZS5tYXJrZXIuc2l6ZSwgMiwgMTYpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZXJlZjogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpemVtaW46IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBzaXplbW9kZTogJ2RpYW1ldGVyJ1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcHRzLmNhbGwoRHJhd2luZy5wb2ludFN0eWxlLCB0TW9kLCBnZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciB3ID0gYm91bmRMaW5lV2lkdGgodW5kZWZpbmVkLCB0cmFjZS5saW5lLCBNQVhfTUFSS0VSX0xJTkVfV0lEVEgsIENTVF9NQVJLRVJfTElORV9XSURUSCk7XG5cbiAgICAgICAgICAgICAgICBwLnN0eWxlKCdzdHJva2Utd2lkdGgnLCB3ICsgJ3B4JylcbiAgICAgICAgICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgdHJhY2UuZmlsbGNvbG9yKTtcblxuICAgICAgICAgICAgICAgIGlmKHcpIENvbG9yLnN0cm9rZShwLCB0cmFjZS5saW5lLmNvbG9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3R5bGVDYW5kbGVzKGQpIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZTtcblxuICAgICAgICB2YXIgcHRzID0gZDMuc2VsZWN0KHRoaXMpLnNlbGVjdCgnZy5sZWdlbmRwb2ludHMnKVxuICAgICAgICAgICAgLnNlbGVjdEFsbCgncGF0aC5sZWdlbmRjYW5kbGUnKVxuICAgICAgICAgICAgLmRhdGEodHJhY2UudHlwZSA9PT0gJ2NhbmRsZXN0aWNrJyAmJiB0cmFjZS52aXNpYmxlID8gW2QsIGRdIDogW10pO1xuICAgICAgICBwdHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKS5jbGFzc2VkKCdsZWdlbmRjYW5kbGUnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihfLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYoaSkgcmV0dXJuICdNLTE1LDBILThNLTgsNlYtNkg4Wic7IC8vIGluY3JlYXNpbmdcbiAgICAgICAgICAgICAgICByZXR1cm4gJ00xNSwwSDhNOCwtNlY2SC04Wic7IC8vIGRlY3JlYXNpbmdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgyMCwwKScpXG4gICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMSk7XG4gICAgICAgIHB0cy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgcHRzLmVhY2goZnVuY3Rpb24oXywgaSkge1xuICAgICAgICAgICAgdmFyIHAgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgY29udCA9IHRyYWNlW2kgPyAnaW5jcmVhc2luZycgOiAnZGVjcmVhc2luZyddO1xuICAgICAgICAgICAgdmFyIHcgPSBib3VuZExpbmVXaWR0aCh1bmRlZmluZWQsIGNvbnQubGluZSwgTUFYX01BUktFUl9MSU5FX1dJRFRILCBDU1RfTUFSS0VSX0xJTkVfV0lEVEgpO1xuXG4gICAgICAgICAgICBwLnN0eWxlKCdzdHJva2Utd2lkdGgnLCB3ICsgJ3B4JylcbiAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBjb250LmZpbGxjb2xvcik7XG5cbiAgICAgICAgICAgIGlmKHcpIENvbG9yLnN0cm9rZShwLCBjb250LmxpbmUuY29sb3IpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdHlsZU9ITEMoZCkge1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuXG4gICAgICAgIHZhciBwdHMgPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0KCdnLmxlZ2VuZHBvaW50cycpXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCdwYXRoLmxlZ2VuZG9obGMnKVxuICAgICAgICAgICAgLmRhdGEodHJhY2UudHlwZSA9PT0gJ29obGMnICYmIHRyYWNlLnZpc2libGUgPyBbZCwgZF0gOiBbXSk7XG4gICAgICAgIHB0cy5lbnRlcigpLmFwcGVuZCgncGF0aCcpLmNsYXNzZWQoJ2xlZ2VuZG9obGMnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihfLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYoaSkgcmV0dXJuICdNLTE1LDBIME0tOCwtNlYwJzsgLy8gaW5jcmVhc2luZ1xuICAgICAgICAgICAgICAgIHJldHVybiAnTTE1LDBIME04LDZWMCc7IC8vIGRlY3JlYXNpbmdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgyMCwwKScpXG4gICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMSk7XG4gICAgICAgIHB0cy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgcHRzLmVhY2goZnVuY3Rpb24oXywgaSkge1xuICAgICAgICAgICAgdmFyIHAgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgY29udCA9IHRyYWNlW2kgPyAnaW5jcmVhc2luZycgOiAnZGVjcmVhc2luZyddO1xuICAgICAgICAgICAgdmFyIHcgPSBib3VuZExpbmVXaWR0aCh1bmRlZmluZWQsIGNvbnQubGluZSwgTUFYX01BUktFUl9MSU5FX1dJRFRILCBDU1RfTUFSS0VSX0xJTkVfV0lEVEgpO1xuXG4gICAgICAgICAgICBwLnN0eWxlKCdmaWxsJywgJ25vbmUnKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZGFzaExpbmUsIGNvbnQubGluZS5kYXNoLCB3KTtcblxuICAgICAgICAgICAgaWYodykgQ29sb3Iuc3Ryb2tlKHAsIGNvbnQubGluZS5jb2xvcik7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0eWxlUGllcyhkKSB7XG4gICAgICAgIHN0eWxlUGllTGlrZShkLCB0aGlzLCAncGllJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3R5bGVGdW5uZWxhcmVhcyhkKSB7XG4gICAgICAgIHN0eWxlUGllTGlrZShkLCB0aGlzLCAnZnVubmVsYXJlYScpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0eWxlUGllTGlrZShkLCBsVGhpcywgZGVzaXJlZFR5cGUpIHtcbiAgICAgICAgdmFyIGQwID0gZFswXTtcbiAgICAgICAgdmFyIHRyYWNlID0gZDAudHJhY2U7XG5cbiAgICAgICAgdmFyIGlzVmlzaWJsZSA9ICghZGVzaXJlZFR5cGUpID8gUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgZGVzaXJlZFR5cGUpIDpcbiAgICAgICAgICAgICh0cmFjZS50eXBlID09PSBkZXNpcmVkVHlwZSAmJiB0cmFjZS52aXNpYmxlKTtcblxuICAgICAgICB2YXIgcHRzID0gZDMuc2VsZWN0KGxUaGlzKS5zZWxlY3QoJ2cubGVnZW5kcG9pbnRzJylcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJ3BhdGgubGVnZW5kJyArIGRlc2lyZWRUeXBlKVxuICAgICAgICAgICAgLmRhdGEoaXNWaXNpYmxlID8gW2RdIDogW10pO1xuICAgICAgICBwdHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKS5jbGFzc2VkKCdsZWdlbmQnICsgZGVzaXJlZFR5cGUsIHRydWUpXG4gICAgICAgICAgICAuYXR0cignZCcsICdNNiw2SC02Vi02SDZaJylcbiAgICAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKDIwLDApJyk7XG4gICAgICAgIHB0cy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgaWYocHRzLnNpemUoKSkge1xuICAgICAgICAgICAgdmFyIGNvbnQgPSAodHJhY2UubWFya2VyIHx8IHt9KS5saW5lO1xuICAgICAgICAgICAgdmFyIGx3ID0gYm91bmRMaW5lV2lkdGgocGllQ2FzdE9wdGlvbihjb250LndpZHRoLCBkMC5wdHMpLCBjb250LCBNQVhfTUFSS0VSX0xJTkVfV0lEVEgsIENTVF9NQVJLRVJfTElORV9XSURUSCk7XG5cbiAgICAgICAgICAgIHZhciB0TW9kID0gTGliLm1pbkV4dGVuZCh0cmFjZSwge21hcmtlcjoge2xpbmU6IHt3aWR0aDogbHd9fX0pO1xuICAgICAgICAgICAgLy8gc2luY2UgbWluRXh0ZW5kIGRvIG5vdCBzbGljZSBtb3JlIHRoYW4gMyBpdGVtcyB3ZSBuZWVkIHRvIHBhdGNoIGxpbmUuY29sb3IgaGVyZVxuICAgICAgICAgICAgdE1vZC5tYXJrZXIubGluZS5jb2xvciA9IGNvbnQuY29sb3I7XG5cbiAgICAgICAgICAgIHZhciBkME1vZCA9IExpYi5taW5FeHRlbmQoZDAsIHt0cmFjZTogdE1vZH0pO1xuXG4gICAgICAgICAgICBzdHlsZVBpZShwdHMsIGQwTW9kLCB0TW9kKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi8uLi90cmFjZXMvcGllL2hlbHBlcnNcIjoxMDkxLFwiLi4vLi4vdHJhY2VzL3BpZS9zdHlsZV9vbmVcIjoxMDk3LFwiLi4vLi4vdHJhY2VzL3NjYXR0ZXIvc3VidHlwZXNcIjoxMTM1LFwiLi4vY29sb3JcIjo1OTMsXCIuLi9kcmF3aW5nXCI6NjE0LFwiZDNcIjoxNjN9XSw2NTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIFBsb3RzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvcGxvdHMnKTtcbnZhciBheGlzSWRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgSWNvbnMgPSBfZGVyZXFfKCcuLi8uLi9mb250cy9wbG90aWNvbicpO1xuXG52YXIgXyA9IExpYi5fO1xuXG52YXIgbW9kZUJhckJ1dHRvbnMgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vKipcbiAqIE1vZGVCYXIgYnV0dG9ucyBjb25maWd1cmF0aW9uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqICAgICAgbmFtZSAvIGlkIG9mIHRoZSBidXR0b25zIChmb3IgdHJhY2tpbmcpXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVcbiAqICAgICAgdGV4dCB0aGF0IGFwcGVhcnMgd2hpbGUgaG92ZXJpbmcgb3ZlciB0aGUgYnV0dG9uLFxuICogICAgICBlbnRlciBudWxsLCBmYWxzZSBvciAnJyBmb3Igbm8gaG92ZXIgdGV4dFxuICogQHBhcmFtIHtzdHJpbmd9IGljb25cbiAqICAgICAgc3ZnIGljb24gb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgYnV0dG9uXG4gKiAgICAgIGNhbiBiZSBsaW5rZWQgdG8gUGxvdGx5Lkljb25zIHRvIHVzZSB0aGUgZGVmYXVsdCBwbG90bHkgaWNvbnNcbiAqIEBwYXJhbSB7c3RyaW5nfSBbZ3Jhdml0eV1cbiAqICAgICAgaWNvbiBwb3NpdGlvbmluZ1xuICogQHBhcmFtIHtmdW5jdGlvbn0gY2xpY2tcbiAqICAgICAgY2xpY2sgaGFuZGxlciBhc3NvY2lhdGVkIHdpdGggdGhlIGJ1dHRvbiwgYSBmdW5jdGlvbiBvZlxuICogICAgICAnZ2QnICh0aGUgbWFpbiBncmFwaCBvYmplY3QpIGFuZFxuICogICAgICAnZXYnICh0aGUgZXZlbnQgb2JqZWN0KVxuICogQHBhcmFtIHtzdHJpbmd9IFthdHRyXVxuICogICAgICBhdHRyaWJ1dGUgYXNzb2NpYXRlZCB3aXRoIGJ1dHRvbixcbiAqICAgICAgdXNlIHRoaXMgd2l0aCAndmFsJyB0byBrZWVwIHRyYWNrIG9mIHRoZSBzdGF0ZVxuICogQHBhcmFtIHsqfSBbdmFsXVxuICogICAgICBpbml0aWFsICdhdHRyJyB2YWx1ZSwgY2FuIGJlIGEgZnVuY3Rpb24gb2YgZ2RcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW3RvZ2dsZV1cbiAqICAgICAgaXMgdGhlIGJ1dHRvbiBhIHRvZ2dsZSBidXR0b24/XG4gKi9cbm1vZGVCYXJCdXR0b25zLnRvSW1hZ2UgPSB7XG4gICAgbmFtZTogJ3RvSW1hZ2UnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkge1xuICAgICAgICB2YXIgb3B0cyA9IGdkLl9jb250ZXh0LnRvSW1hZ2VCdXR0b25PcHRpb25zIHx8IHt9O1xuICAgICAgICB2YXIgZm9ybWF0ID0gb3B0cy5mb3JtYXQgfHwgJ3BuZyc7XG4gICAgICAgIHJldHVybiBmb3JtYXQgPT09ICdwbmcnID9cbiAgICAgICAgICAgIF8oZ2QsICdEb3dubG9hZCBwbG90IGFzIGEgcG5nJykgOiAvLyBsZWdhY3kgdGV4dFxuICAgICAgICAgICAgXyhnZCwgJ0Rvd25sb2FkIHBsb3QnKTsgLy8gZ2VuZXJpYyBub24tUE5HIHRleHRcbiAgICB9LFxuICAgIGljb246IEljb25zLmNhbWVyYSxcbiAgICBjbGljazogZnVuY3Rpb24oZ2QpIHtcbiAgICAgICAgdmFyIHRvSW1hZ2VCdXR0b25PcHRpb25zID0gZ2QuX2NvbnRleHQudG9JbWFnZUJ1dHRvbk9wdGlvbnM7XG4gICAgICAgIHZhciBvcHRzID0ge2Zvcm1hdDogdG9JbWFnZUJ1dHRvbk9wdGlvbnMuZm9ybWF0IHx8ICdwbmcnfTtcblxuICAgICAgICBMaWIubm90aWZpZXIoXyhnZCwgJ1Rha2luZyBzbmFwc2hvdCAtIHRoaXMgbWF5IHRha2UgYSBmZXcgc2Vjb25kcycpLCAnbG9uZycpO1xuXG4gICAgICAgIGlmKG9wdHMuZm9ybWF0ICE9PSAnc3ZnJyAmJiBMaWIuaXNJRSgpKSB7XG4gICAgICAgICAgICBMaWIubm90aWZpZXIoXyhnZCwgJ0lFIG9ubHkgc3VwcG9ydHMgc3ZnLiAgQ2hhbmdpbmcgZm9ybWF0IHRvIHN2Zy4nKSwgJ2xvbmcnKTtcbiAgICAgICAgICAgIG9wdHMuZm9ybWF0ID0gJ3N2Zyc7XG4gICAgICAgIH1cblxuICAgICAgICBbJ2ZpbGVuYW1lJywgJ3dpZHRoJywgJ2hlaWdodCcsICdzY2FsZSddLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgICAgICBpZihrZXkgaW4gdG9JbWFnZUJ1dHRvbk9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBvcHRzW2tleV0gPSB0b0ltYWdlQnV0dG9uT3B0aW9uc1trZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBSZWdpc3RyeS5jYWxsKCdkb3dubG9hZEltYWdlJywgZ2QsIG9wdHMpXG4gICAgICAgICAgLnRoZW4oZnVuY3Rpb24oZmlsZW5hbWUpIHtcbiAgICAgICAgICAgICAgTGliLm5vdGlmaWVyKF8oZ2QsICdTbmFwc2hvdCBzdWNjZWVkZWQnKSArICcgLSAnICsgZmlsZW5hbWUsICdsb25nJyk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIExpYi5ub3RpZmllcihfKGdkLCAnU29ycnksIHRoZXJlIHdhcyBhIHByb2JsZW0gZG93bmxvYWRpbmcgeW91ciBzbmFwc2hvdCEnKSwgJ2xvbmcnKTtcbiAgICAgICAgICB9KTtcbiAgICB9XG59O1xuXG5tb2RlQmFyQnV0dG9ucy5zZW5kRGF0YVRvQ2xvdWQgPSB7XG4gICAgbmFtZTogJ3NlbmREYXRhVG9DbG91ZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnRWRpdCBpbiBDaGFydCBTdHVkaW8nKTsgfSxcbiAgICBpY29uOiBJY29ucy5kaXNrLFxuICAgIGNsaWNrOiBmdW5jdGlvbihnZCkge1xuICAgICAgICBQbG90cy5zZW5kRGF0YVRvQ2xvdWQoZ2QpO1xuICAgIH1cbn07XG5cbm1vZGVCYXJCdXR0b25zLmVkaXRJbkNoYXJ0U3R1ZGlvID0ge1xuICAgIG5hbWU6ICdlZGl0SW5DaGFydFN0dWRpbycsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnRWRpdCBpbiBDaGFydCBTdHVkaW8nKTsgfSxcbiAgICBpY29uOiBJY29ucy5wZW5jaWwsXG4gICAgY2xpY2s6IGZ1bmN0aW9uKGdkKSB7XG4gICAgICAgIFBsb3RzLnNlbmREYXRhVG9DbG91ZChnZCk7XG4gICAgfVxufTtcblxubW9kZUJhckJ1dHRvbnMuem9vbTJkID0ge1xuICAgIG5hbWU6ICd6b29tMmQnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1pvb20nKTsgfSxcbiAgICBhdHRyOiAnZHJhZ21vZGUnLFxuICAgIHZhbDogJ3pvb20nLFxuICAgIGljb246IEljb25zLnpvb21ib3gsXG4gICAgY2xpY2s6IGhhbmRsZUNhcnRlc2lhblxufTtcblxubW9kZUJhckJ1dHRvbnMucGFuMmQgPSB7XG4gICAgbmFtZTogJ3BhbjJkJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdQYW4nKTsgfSxcbiAgICBhdHRyOiAnZHJhZ21vZGUnLFxuICAgIHZhbDogJ3BhbicsXG4gICAgaWNvbjogSWNvbnMucGFuLFxuICAgIGNsaWNrOiBoYW5kbGVDYXJ0ZXNpYW5cbn07XG5cbm1vZGVCYXJCdXR0b25zLnNlbGVjdDJkID0ge1xuICAgIG5hbWU6ICdzZWxlY3QyZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnQm94IFNlbGVjdCcpOyB9LFxuICAgIGF0dHI6ICdkcmFnbW9kZScsXG4gICAgdmFsOiAnc2VsZWN0JyxcbiAgICBpY29uOiBJY29ucy5zZWxlY3Rib3gsXG4gICAgY2xpY2s6IGhhbmRsZUNhcnRlc2lhblxufTtcblxubW9kZUJhckJ1dHRvbnMubGFzc28yZCA9IHtcbiAgICBuYW1lOiAnbGFzc28yZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnTGFzc28gU2VsZWN0Jyk7IH0sXG4gICAgYXR0cjogJ2RyYWdtb2RlJyxcbiAgICB2YWw6ICdsYXNzbycsXG4gICAgaWNvbjogSWNvbnMubGFzc28sXG4gICAgY2xpY2s6IGhhbmRsZUNhcnRlc2lhblxufTtcblxubW9kZUJhckJ1dHRvbnMuem9vbUluMmQgPSB7XG4gICAgbmFtZTogJ3pvb21JbjJkJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdab29tIGluJyk7IH0sXG4gICAgYXR0cjogJ3pvb20nLFxuICAgIHZhbDogJ2luJyxcbiAgICBpY29uOiBJY29ucy56b29tX3BsdXMsXG4gICAgY2xpY2s6IGhhbmRsZUNhcnRlc2lhblxufTtcblxubW9kZUJhckJ1dHRvbnMuem9vbU91dDJkID0ge1xuICAgIG5hbWU6ICd6b29tT3V0MmQnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1pvb20gb3V0Jyk7IH0sXG4gICAgYXR0cjogJ3pvb20nLFxuICAgIHZhbDogJ291dCcsXG4gICAgaWNvbjogSWNvbnMuem9vbV9taW51cyxcbiAgICBjbGljazogaGFuZGxlQ2FydGVzaWFuXG59O1xuXG5tb2RlQmFyQnV0dG9ucy5hdXRvU2NhbGUyZCA9IHtcbiAgICBuYW1lOiAnYXV0b1NjYWxlMmQnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ0F1dG9zY2FsZScpOyB9LFxuICAgIGF0dHI6ICd6b29tJyxcbiAgICB2YWw6ICdhdXRvJyxcbiAgICBpY29uOiBJY29ucy5hdXRvc2NhbGUsXG4gICAgY2xpY2s6IGhhbmRsZUNhcnRlc2lhblxufTtcblxubW9kZUJhckJ1dHRvbnMucmVzZXRTY2FsZTJkID0ge1xuICAgIG5hbWU6ICdyZXNldFNjYWxlMmQnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1Jlc2V0IGF4ZXMnKTsgfSxcbiAgICBhdHRyOiAnem9vbScsXG4gICAgdmFsOiAncmVzZXQnLFxuICAgIGljb246IEljb25zLmhvbWUsXG4gICAgY2xpY2s6IGhhbmRsZUNhcnRlc2lhblxufTtcblxubW9kZUJhckJ1dHRvbnMuaG92ZXJDbG9zZXN0Q2FydGVzaWFuID0ge1xuICAgIG5hbWU6ICdob3ZlckNsb3Nlc3RDYXJ0ZXNpYW4nLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1Nob3cgY2xvc2VzdCBkYXRhIG9uIGhvdmVyJyk7IH0sXG4gICAgYXR0cjogJ2hvdmVybW9kZScsXG4gICAgdmFsOiAnY2xvc2VzdCcsXG4gICAgaWNvbjogSWNvbnMudG9vbHRpcF9iYXNpYyxcbiAgICBncmF2aXR5OiAnbmUnLFxuICAgIGNsaWNrOiBoYW5kbGVDYXJ0ZXNpYW5cbn07XG5cbm1vZGVCYXJCdXR0b25zLmhvdmVyQ29tcGFyZUNhcnRlc2lhbiA9IHtcbiAgICBuYW1lOiAnaG92ZXJDb21wYXJlQ2FydGVzaWFuJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdDb21wYXJlIGRhdGEgb24gaG92ZXInKTsgfSxcbiAgICBhdHRyOiAnaG92ZXJtb2RlJyxcbiAgICB2YWw6IGZ1bmN0aW9uKGdkKSB7XG4gICAgICAgIHJldHVybiBnZC5fZnVsbExheW91dC5faXNIb3JpeiA/ICd5JyA6ICd4JztcbiAgICB9LFxuICAgIGljb246IEljb25zLnRvb2x0aXBfY29tcGFyZSxcbiAgICBncmF2aXR5OiAnbmUnLFxuICAgIGNsaWNrOiBoYW5kbGVDYXJ0ZXNpYW5cbn07XG5cbmZ1bmN0aW9uIGhhbmRsZUNhcnRlc2lhbihnZCwgZXYpIHtcbiAgICB2YXIgYnV0dG9uID0gZXYuY3VycmVudFRhcmdldDtcbiAgICB2YXIgYXN0ciA9IGJ1dHRvbi5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicpO1xuICAgIHZhciB2YWwgPSBidXR0b24uZ2V0QXR0cmlidXRlKCdkYXRhLXZhbCcpIHx8IHRydWU7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgYW9iaiA9IHt9O1xuICAgIHZhciBheExpc3QgPSBheGlzSWRzLmxpc3QoZ2QsIG51bGwsIHRydWUpO1xuICAgIHZhciBhbGxTcGlrZXNFbmFibGVkID0gJ29uJztcblxuICAgIHZhciBheCwgaTtcblxuICAgIGlmKGFzdHIgPT09ICd6b29tJykge1xuICAgICAgICB2YXIgbWFnID0gKHZhbCA9PT0gJ2luJykgPyAwLjUgOiAyO1xuICAgICAgICB2YXIgcjAgPSAoMSArIG1hZykgLyAyO1xuICAgICAgICB2YXIgcjEgPSAoMSAtIG1hZykgLyAyO1xuICAgICAgICB2YXIgYXhOYW1lO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXggPSBheExpc3RbaV07XG5cbiAgICAgICAgICAgIGlmKCFheC5maXhlZHJhbmdlKSB7XG4gICAgICAgICAgICAgICAgYXhOYW1lID0gYXguX25hbWU7XG4gICAgICAgICAgICAgICAgaWYodmFsID09PSAnYXV0bycpIGFvYmpbYXhOYW1lICsgJy5hdXRvcmFuZ2UnXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgZWxzZSBpZih2YWwgPT09ICdyZXNldCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoYXguX3JhbmdlSW5pdGlhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhb2JqW2F4TmFtZSArICcuYXV0b3JhbmdlJ10gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhbmdlSW5pdGlhbCA9IGF4Ll9yYW5nZUluaXRpYWwuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFvYmpbYXhOYW1lICsgJy5yYW5nZVswXSddID0gcmFuZ2VJbml0aWFsWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYW9ialtheE5hbWUgKyAnLnJhbmdlWzFdJ10gPSByYW5nZUluaXRpYWxbMV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYoYXguX3Nob3dTcGlrZUluaXRpYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYW9ialtheE5hbWUgKyAnLnNob3dzcGlrZXMnXSA9IGF4Ll9zaG93U3Bpa2VJbml0aWFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoYWxsU3Bpa2VzRW5hYmxlZCA9PT0gJ29uJyAmJiAhYXguX3Nob3dTcGlrZUluaXRpYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxTcGlrZXNFbmFibGVkID0gJ29mZic7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmFuZ2VOb3cgPSBbXG4gICAgICAgICAgICAgICAgICAgICAgICBheC5yMmwoYXgucmFuZ2VbMF0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXgucjJsKGF4LnJhbmdlWzFdKSxcbiAgICAgICAgICAgICAgICAgICAgXTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgcmFuZ2VOZXcgPSBbXG4gICAgICAgICAgICAgICAgICAgICAgICByMCAqIHJhbmdlTm93WzBdICsgcjEgKiByYW5nZU5vd1sxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHIwICogcmFuZ2VOb3dbMV0gKyByMSAqIHJhbmdlTm93WzBdXG4gICAgICAgICAgICAgICAgICAgIF07XG5cbiAgICAgICAgICAgICAgICAgICAgYW9ialtheE5hbWUgKyAnLnJhbmdlWzBdJ10gPSBheC5sMnIocmFuZ2VOZXdbMF0pO1xuICAgICAgICAgICAgICAgICAgICBhb2JqW2F4TmFtZSArICcucmFuZ2VbMV0nXSA9IGF4LmwycihyYW5nZU5ld1sxXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZ1bGxMYXlvdXQuX2NhcnRlc2lhblNwaWtlc0VuYWJsZWQgPSBhbGxTcGlrZXNFbmFibGVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGlmIEFMTCB0cmFjZXMgaGF2ZSBvcmllbnRhdGlvbiAnaCcsICdob3Zlcm1vZGUnOiAneCcgb3RoZXJ3aXNlOiAneSdcbiAgICAgICAgaWYoYXN0ciA9PT0gJ2hvdmVybW9kZScgJiYgKHZhbCA9PT0gJ3gnIHx8IHZhbCA9PT0gJ3knKSkge1xuICAgICAgICAgICAgdmFsID0gZnVsbExheW91dC5faXNIb3JpeiA/ICd5JyA6ICd4JztcbiAgICAgICAgICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtdmFsJywgdmFsKTtcbiAgICAgICAgfSBlbHNlIGlmKGFzdHIgPT09ICdob3Zlcm1vZGUnICYmIHZhbCA9PT0gJ2Nsb3Nlc3QnKSB7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBheCA9IGF4TGlzdFtpXTtcbiAgICAgICAgICAgICAgICBpZihhbGxTcGlrZXNFbmFibGVkID09PSAnb24nICYmICFheC5zaG93c3Bpa2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGFsbFNwaWtlc0VuYWJsZWQgPSAnb2ZmJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9jYXJ0ZXNpYW5TcGlrZXNFbmFibGVkID0gYWxsU3Bpa2VzRW5hYmxlZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGFvYmpbYXN0cl0gPSB2YWw7XG4gICAgfVxuXG4gICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIGFvYmopO1xufVxuXG5tb2RlQmFyQnV0dG9ucy56b29tM2QgPSB7XG4gICAgbmFtZTogJ3pvb20zZCcsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnWm9vbScpOyB9LFxuICAgIGF0dHI6ICdzY2VuZS5kcmFnbW9kZScsXG4gICAgdmFsOiAnem9vbScsXG4gICAgaWNvbjogSWNvbnMuem9vbWJveCxcbiAgICBjbGljazogaGFuZGxlRHJhZzNkXG59O1xuXG5tb2RlQmFyQnV0dG9ucy5wYW4zZCA9IHtcbiAgICBuYW1lOiAncGFuM2QnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1BhbicpOyB9LFxuICAgIGF0dHI6ICdzY2VuZS5kcmFnbW9kZScsXG4gICAgdmFsOiAncGFuJyxcbiAgICBpY29uOiBJY29ucy5wYW4sXG4gICAgY2xpY2s6IGhhbmRsZURyYWczZFxufTtcblxubW9kZUJhckJ1dHRvbnMub3JiaXRSb3RhdGlvbiA9IHtcbiAgICBuYW1lOiAnb3JiaXRSb3RhdGlvbicsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnT3JiaXRhbCByb3RhdGlvbicpOyB9LFxuICAgIGF0dHI6ICdzY2VuZS5kcmFnbW9kZScsXG4gICAgdmFsOiAnb3JiaXQnLFxuICAgIGljb246IEljb25zWyczZF9yb3RhdGUnXSxcbiAgICBjbGljazogaGFuZGxlRHJhZzNkXG59O1xuXG5tb2RlQmFyQnV0dG9ucy50YWJsZVJvdGF0aW9uID0ge1xuICAgIG5hbWU6ICd0YWJsZVJvdGF0aW9uJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdUdXJudGFibGUgcm90YXRpb24nKTsgfSxcbiAgICBhdHRyOiAnc2NlbmUuZHJhZ21vZGUnLFxuICAgIHZhbDogJ3R1cm50YWJsZScsXG4gICAgaWNvbjogSWNvbnNbJ3otYXhpcyddLFxuICAgIGNsaWNrOiBoYW5kbGVEcmFnM2Rcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZURyYWczZChnZCwgZXYpIHtcbiAgICB2YXIgYnV0dG9uID0gZXYuY3VycmVudFRhcmdldDtcbiAgICB2YXIgYXR0ciA9IGJ1dHRvbi5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicpO1xuICAgIHZhciB2YWwgPSBidXR0b24uZ2V0QXR0cmlidXRlKCdkYXRhLXZhbCcpIHx8IHRydWU7XG4gICAgdmFyIHNjZW5lSWRzID0gZ2QuX2Z1bGxMYXlvdXQuX3N1YnBsb3RzLmdsM2Q7XG4gICAgdmFyIGxheW91dFVwZGF0ZSA9IHt9O1xuXG4gICAgdmFyIHBhcnRzID0gYXR0ci5zcGxpdCgnLicpO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNjZW5lSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxheW91dFVwZGF0ZVtzY2VuZUlkc1tpXSArICcuJyArIHBhcnRzWzFdXSA9IHZhbDtcbiAgICB9XG5cbiAgICAvLyBmb3IgbXVsdGktdHlwZSBzdWJwbG90c1xuICAgIHZhciB2YWwyZCA9ICh2YWwgPT09ICdwYW4nKSA/IHZhbCA6ICd6b29tJztcbiAgICBsYXlvdXRVcGRhdGUuZHJhZ21vZGUgPSB2YWwyZDtcblxuICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCBsYXlvdXRVcGRhdGUpO1xufVxuXG5tb2RlQmFyQnV0dG9ucy5yZXNldENhbWVyYURlZmF1bHQzZCA9IHtcbiAgICBuYW1lOiAncmVzZXRDYW1lcmFEZWZhdWx0M2QnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1Jlc2V0IGNhbWVyYSB0byBkZWZhdWx0Jyk7IH0sXG4gICAgYXR0cjogJ3Jlc2V0RGVmYXVsdCcsXG4gICAgaWNvbjogSWNvbnMuaG9tZSxcbiAgICBjbGljazogaGFuZGxlQ2FtZXJhM2Rcbn07XG5cbm1vZGVCYXJCdXR0b25zLnJlc2V0Q2FtZXJhTGFzdFNhdmUzZCA9IHtcbiAgICBuYW1lOiAncmVzZXRDYW1lcmFMYXN0U2F2ZTNkJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdSZXNldCBjYW1lcmEgdG8gbGFzdCBzYXZlJyk7IH0sXG4gICAgYXR0cjogJ3Jlc2V0TGFzdFNhdmUnLFxuICAgIGljb246IEljb25zLm1vdmllLFxuICAgIGNsaWNrOiBoYW5kbGVDYW1lcmEzZFxufTtcblxuZnVuY3Rpb24gaGFuZGxlQ2FtZXJhM2QoZ2QsIGV2KSB7XG4gICAgdmFyIGJ1dHRvbiA9IGV2LmN1cnJlbnRUYXJnZXQ7XG4gICAgdmFyIGF0dHIgPSBidXR0b24uZ2V0QXR0cmlidXRlKCdkYXRhLWF0dHInKTtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzY2VuZUlkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzLmdsM2Q7XG4gICAgdmFyIGFvYmogPSB7fTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzY2VuZUlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc2NlbmVJZCA9IHNjZW5lSWRzW2ldO1xuICAgICAgICB2YXIga2V5ID0gc2NlbmVJZCArICcuY2FtZXJhJztcbiAgICAgICAgdmFyIHNjZW5lID0gZnVsbExheW91dFtzY2VuZUlkXS5fc2NlbmU7XG5cbiAgICAgICAgaWYoYXR0ciA9PT0gJ3Jlc2V0TGFzdFNhdmUnKSB7XG4gICAgICAgICAgICBhb2JqW2tleSArICcudXAnXSA9IHNjZW5lLnZpZXdJbml0aWFsLnVwO1xuICAgICAgICAgICAgYW9ialtrZXkgKyAnLmV5ZSddID0gc2NlbmUudmlld0luaXRpYWwuZXllO1xuICAgICAgICAgICAgYW9ialtrZXkgKyAnLmNlbnRlciddID0gc2NlbmUudmlld0luaXRpYWwuY2VudGVyO1xuICAgICAgICB9IGVsc2UgaWYoYXR0ciA9PT0gJ3Jlc2V0RGVmYXVsdCcpIHtcbiAgICAgICAgICAgIGFvYmpba2V5ICsgJy51cCddID0gbnVsbDtcbiAgICAgICAgICAgIGFvYmpba2V5ICsgJy5leWUnXSA9IG51bGw7XG4gICAgICAgICAgICBhb2JqW2tleSArICcuY2VudGVyJ10gPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIGFvYmopO1xufVxuXG5tb2RlQmFyQnV0dG9ucy5ob3ZlckNsb3Nlc3QzZCA9IHtcbiAgICBuYW1lOiAnaG92ZXJDbG9zZXN0M2QnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1RvZ2dsZSBzaG93IGNsb3Nlc3QgZGF0YSBvbiBob3ZlcicpOyB9LFxuICAgIGF0dHI6ICdob3Zlcm1vZGUnLFxuICAgIHZhbDogbnVsbCxcbiAgICB0b2dnbGU6IHRydWUsXG4gICAgaWNvbjogSWNvbnMudG9vbHRpcF9iYXNpYyxcbiAgICBncmF2aXR5OiAnbmUnLFxuICAgIGNsaWNrOiBoYW5kbGVIb3ZlcjNkXG59O1xuXG5mdW5jdGlvbiBnZXROZXh0SG92ZXIzZChnZCwgZXYpIHtcbiAgICB2YXIgYnV0dG9uID0gZXYuY3VycmVudFRhcmdldDtcbiAgICB2YXIgdmFsID0gYnV0dG9uLl9wcmV2aW91c1ZhbDtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzY2VuZUlkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzLmdsM2Q7XG5cbiAgICB2YXIgYXhlcyA9IFsneGF4aXMnLCAneWF4aXMnLCAnemF4aXMnXTtcblxuICAgIC8vIGluaXRpYWxpemUgJ2N1cnJlbnQgc3Bpa2UnIG9iamVjdCB0byBiZSBzdG9yZWQgaW4gdGhlIERPTVxuICAgIHZhciBjdXJyZW50U3Bpa2VzID0ge307XG4gICAgdmFyIGxheW91dFVwZGF0ZSA9IHt9O1xuXG4gICAgaWYodmFsKSB7XG4gICAgICAgIGxheW91dFVwZGF0ZSA9IHZhbDtcbiAgICAgICAgYnV0dG9uLl9wcmV2aW91c1ZhbCA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHNjZW5lSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2NlbmVJZCA9IHNjZW5lSWRzW2ldO1xuICAgICAgICAgICAgdmFyIHNjZW5lTGF5b3V0ID0gZnVsbExheW91dFtzY2VuZUlkXTtcblxuICAgICAgICAgICAgdmFyIGhvdmVybW9kZUFTdHIgPSBzY2VuZUlkICsgJy5ob3Zlcm1vZGUnO1xuICAgICAgICAgICAgY3VycmVudFNwaWtlc1tob3Zlcm1vZGVBU3RyXSA9IHNjZW5lTGF5b3V0LmhvdmVybW9kZTtcbiAgICAgICAgICAgIGxheW91dFVwZGF0ZVtob3Zlcm1vZGVBU3RyXSA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBjb3B5IGFsbCB0aGUgY3VycmVudCBzcGlrZSBhdHRyc1xuICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IDM7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBheGlzID0gYXhlc1tqXTtcbiAgICAgICAgICAgICAgICB2YXIgc3Bpa2VBU3RyID0gc2NlbmVJZCArICcuJyArIGF4aXMgKyAnLnNob3dzcGlrZXMnO1xuICAgICAgICAgICAgICAgIGxheW91dFVwZGF0ZVtzcGlrZUFTdHJdID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgY3VycmVudFNwaWtlc1tzcGlrZUFTdHJdID0gc2NlbmVMYXlvdXRbYXhpc10uc2hvd3NwaWtlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGJ1dHRvbi5fcHJldmlvdXNWYWwgPSBjdXJyZW50U3Bpa2VzO1xuICAgIH1cbiAgICByZXR1cm4gbGF5b3V0VXBkYXRlO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVIb3ZlcjNkKGdkLCBldikge1xuICAgIHZhciBsYXlvdXRVcGRhdGUgPSBnZXROZXh0SG92ZXIzZChnZCwgZXYpO1xuICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCBsYXlvdXRVcGRhdGUpO1xufVxuXG5tb2RlQmFyQnV0dG9ucy56b29tSW5HZW8gPSB7XG4gICAgbmFtZTogJ3pvb21JbkdlbycsXG4gICAgdGl0bGU6IGZ1bmN0aW9uKGdkKSB7IHJldHVybiBfKGdkLCAnWm9vbSBpbicpOyB9LFxuICAgIGF0dHI6ICd6b29tJyxcbiAgICB2YWw6ICdpbicsXG4gICAgaWNvbjogSWNvbnMuem9vbV9wbHVzLFxuICAgIGNsaWNrOiBoYW5kbGVHZW9cbn07XG5cbm1vZGVCYXJCdXR0b25zLnpvb21PdXRHZW8gPSB7XG4gICAgbmFtZTogJ3pvb21PdXRHZW8nLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1pvb20gb3V0Jyk7IH0sXG4gICAgYXR0cjogJ3pvb20nLFxuICAgIHZhbDogJ291dCcsXG4gICAgaWNvbjogSWNvbnMuem9vbV9taW51cyxcbiAgICBjbGljazogaGFuZGxlR2VvXG59O1xuXG5tb2RlQmFyQnV0dG9ucy5yZXNldEdlbyA9IHtcbiAgICBuYW1lOiAncmVzZXRHZW8nLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1Jlc2V0Jyk7IH0sXG4gICAgYXR0cjogJ3Jlc2V0JyxcbiAgICB2YWw6IG51bGwsXG4gICAgaWNvbjogSWNvbnMuYXV0b3NjYWxlLFxuICAgIGNsaWNrOiBoYW5kbGVHZW9cbn07XG5cbm1vZGVCYXJCdXR0b25zLmhvdmVyQ2xvc2VzdEdlbyA9IHtcbiAgICBuYW1lOiAnaG92ZXJDbG9zZXN0R2VvJyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdUb2dnbGUgc2hvdyBjbG9zZXN0IGRhdGEgb24gaG92ZXInKTsgfSxcbiAgICBhdHRyOiAnaG92ZXJtb2RlJyxcbiAgICB2YWw6IG51bGwsXG4gICAgdG9nZ2xlOiB0cnVlLFxuICAgIGljb246IEljb25zLnRvb2x0aXBfYmFzaWMsXG4gICAgZ3Jhdml0eTogJ25lJyxcbiAgICBjbGljazogdG9nZ2xlSG92ZXJcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZUdlbyhnZCwgZXYpIHtcbiAgICB2YXIgYnV0dG9uID0gZXYuY3VycmVudFRhcmdldDtcbiAgICB2YXIgYXR0ciA9IGJ1dHRvbi5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicpO1xuICAgIHZhciB2YWwgPSBidXR0b24uZ2V0QXR0cmlidXRlKCdkYXRhLXZhbCcpIHx8IHRydWU7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZ2VvSWRzID0gZnVsbExheW91dC5fc3VicGxvdHMuZ2VvO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGdlb0lkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBnZW9JZHNbaV07XG4gICAgICAgIHZhciBnZW9MYXlvdXQgPSBmdWxsTGF5b3V0W2lkXTtcblxuICAgICAgICBpZihhdHRyID09PSAnem9vbScpIHtcbiAgICAgICAgICAgIHZhciBzY2FsZSA9IGdlb0xheW91dC5wcm9qZWN0aW9uLnNjYWxlO1xuICAgICAgICAgICAgdmFyIG5ld1NjYWxlID0gKHZhbCA9PT0gJ2luJykgPyAyICogc2NhbGUgOiAwLjUgKiBzY2FsZTtcblxuICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIGlkICsgJy5wcm9qZWN0aW9uLnNjYWxlJywgbmV3U2NhbGUpO1xuICAgICAgICB9IGVsc2UgaWYoYXR0ciA9PT0gJ3Jlc2V0Jykge1xuICAgICAgICAgICAgcmVzZXRWaWV3KGdkLCAnZ2VvJyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbm1vZGVCYXJCdXR0b25zLmhvdmVyQ2xvc2VzdEdsMmQgPSB7XG4gICAgbmFtZTogJ2hvdmVyQ2xvc2VzdEdsMmQnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1RvZ2dsZSBzaG93IGNsb3Nlc3QgZGF0YSBvbiBob3ZlcicpOyB9LFxuICAgIGF0dHI6ICdob3Zlcm1vZGUnLFxuICAgIHZhbDogbnVsbCxcbiAgICB0b2dnbGU6IHRydWUsXG4gICAgaWNvbjogSWNvbnMudG9vbHRpcF9iYXNpYyxcbiAgICBncmF2aXR5OiAnbmUnLFxuICAgIGNsaWNrOiB0b2dnbGVIb3ZlclxufTtcblxubW9kZUJhckJ1dHRvbnMuaG92ZXJDbG9zZXN0UGllID0ge1xuICAgIG5hbWU6ICdob3ZlckNsb3Nlc3RQaWUnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1RvZ2dsZSBzaG93IGNsb3Nlc3QgZGF0YSBvbiBob3ZlcicpOyB9LFxuICAgIGF0dHI6ICdob3Zlcm1vZGUnLFxuICAgIHZhbDogJ2Nsb3Nlc3QnLFxuICAgIGljb246IEljb25zLnRvb2x0aXBfYmFzaWMsXG4gICAgZ3Jhdml0eTogJ25lJyxcbiAgICBjbGljazogdG9nZ2xlSG92ZXJcbn07XG5cbmZ1bmN0aW9uIGdldE5leHRIb3ZlcihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBpZihmdWxsTGF5b3V0LmhvdmVybW9kZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYoZnVsbExheW91dC5faGFzKCdjYXJ0ZXNpYW4nKSkge1xuICAgICAgICByZXR1cm4gZnVsbExheW91dC5faXNIb3JpeiA/ICd5JyA6ICd4JztcbiAgICB9XG4gICAgcmV0dXJuICdjbG9zZXN0Jztcbn1cblxuZnVuY3Rpb24gdG9nZ2xlSG92ZXIoZ2QpIHtcbiAgICB2YXIgbmV3SG92ZXIgPSBnZXROZXh0SG92ZXIoZ2QpO1xuICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCAnaG92ZXJtb2RlJywgbmV3SG92ZXIpO1xufVxuXG5tb2RlQmFyQnV0dG9ucy5yZXNldFZpZXdTYW5rZXkgPSB7XG4gICAgbmFtZTogJ3Jlc2V0U2Fua2V5R3JvdXAnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1Jlc2V0IHZpZXcnKTsgfSxcbiAgICBpY29uOiBJY29ucy5ob21lLFxuICAgIGNsaWNrOiBmdW5jdGlvbihnZCkge1xuICAgICAgICB2YXIgYU9iaiA9IHtcbiAgICAgICAgICAgICdub2RlLmdyb3Vwcyc6IFtdLFxuICAgICAgICAgICAgJ25vZGUueCc6IFtdLFxuICAgICAgICAgICAgJ25vZGUueSc6IFtdXG4gICAgICAgIH07XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBnZC5fZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB2aWV3SW5pdGlhbCA9IGdkLl9mdWxsRGF0YVtpXS5fdmlld0luaXRpYWw7XG4gICAgICAgICAgICBhT2JqWydub2RlLmdyb3VwcyddLnB1c2godmlld0luaXRpYWwubm9kZS5ncm91cHMuc2xpY2UoKSk7XG4gICAgICAgICAgICBhT2JqWydub2RlLngnXS5wdXNoKHZpZXdJbml0aWFsLm5vZGUueC5zbGljZSgpKTtcbiAgICAgICAgICAgIGFPYmpbJ25vZGUueSddLnB1c2godmlld0luaXRpYWwubm9kZS55LnNsaWNlKCkpO1xuICAgICAgICB9XG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ3Jlc3R5bGUnLCBnZCwgYU9iaik7XG4gICAgfVxufTtcblxuLy8gYnV0dG9ucyB3aGVuIG1vcmUgdGhlbiBvbmUgcGxvdCB0eXBlcyBhcmUgcHJlc2VudFxuXG5tb2RlQmFyQnV0dG9ucy50b2dnbGVIb3ZlciA9IHtcbiAgICBuYW1lOiAndG9nZ2xlSG92ZXInLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1RvZ2dsZSBzaG93IGNsb3Nlc3QgZGF0YSBvbiBob3ZlcicpOyB9LFxuICAgIGF0dHI6ICdob3Zlcm1vZGUnLFxuICAgIHZhbDogbnVsbCxcbiAgICB0b2dnbGU6IHRydWUsXG4gICAgaWNvbjogSWNvbnMudG9vbHRpcF9iYXNpYyxcbiAgICBncmF2aXR5OiAnbmUnLFxuICAgIGNsaWNrOiBmdW5jdGlvbihnZCwgZXYpIHtcbiAgICAgICAgdmFyIGxheW91dFVwZGF0ZSA9IGdldE5leHRIb3ZlcjNkKGdkLCBldik7XG4gICAgICAgIGxheW91dFVwZGF0ZS5ob3Zlcm1vZGUgPSBnZXROZXh0SG92ZXIoZ2QpO1xuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCBsYXlvdXRVcGRhdGUpO1xuICAgIH1cbn07XG5cbm1vZGVCYXJCdXR0b25zLnJlc2V0Vmlld3MgPSB7XG4gICAgbmFtZTogJ3Jlc2V0Vmlld3MnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1Jlc2V0IHZpZXdzJyk7IH0sXG4gICAgaWNvbjogSWNvbnMuaG9tZSxcbiAgICBjbGljazogZnVuY3Rpb24oZ2QsIGV2KSB7XG4gICAgICAgIHZhciBidXR0b24gPSBldi5jdXJyZW50VGFyZ2V0O1xuXG4gICAgICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicsICd6b29tJyk7XG4gICAgICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtdmFsJywgJ3Jlc2V0Jyk7XG4gICAgICAgIGhhbmRsZUNhcnRlc2lhbihnZCwgZXYpO1xuXG4gICAgICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicsICdyZXNldExhc3RTYXZlJyk7XG4gICAgICAgIGhhbmRsZUNhbWVyYTNkKGdkLCBldik7XG5cbiAgICAgICAgcmVzZXRWaWV3KGdkLCAnZ2VvJyk7XG4gICAgICAgIHJlc2V0VmlldyhnZCwgJ21hcGJveCcpO1xuICAgIH1cbn07XG5cbm1vZGVCYXJCdXR0b25zLnRvZ2dsZVNwaWtlbGluZXMgPSB7XG4gICAgbmFtZTogJ3RvZ2dsZVNwaWtlbGluZXMnLFxuICAgIHRpdGxlOiBmdW5jdGlvbihnZCkgeyByZXR1cm4gXyhnZCwgJ1RvZ2dsZSBTcGlrZSBMaW5lcycpOyB9LFxuICAgIGljb246IEljb25zLnNwaWtlbGluZSxcbiAgICBhdHRyOiAnX2NhcnRlc2lhblNwaWtlc0VuYWJsZWQnLFxuICAgIHZhbDogJ29uJyxcbiAgICBjbGljazogZnVuY3Rpb24oZ2QpIHtcbiAgICAgICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgICAgICBmdWxsTGF5b3V0Ll9jYXJ0ZXNpYW5TcGlrZXNFbmFibGVkID0gZnVsbExheW91dC5fY2FydGVzaWFuU3Bpa2VzRW5hYmxlZCA9PT0gJ29uJyA/ICdvZmYnIDogJ29uJztcblxuICAgICAgICB2YXIgYW9iaiA9IHNldFNwaWtlbGluZVZpc2liaWxpdHkoZ2QpO1xuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCBhb2JqKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBzZXRTcGlrZWxpbmVWaXNpYmlsaXR5KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgYXhMaXN0ID0gYXhpc0lkcy5saXN0KGdkLCBudWxsLCB0cnVlKTtcbiAgICB2YXIgYW9iaiA9IHt9O1xuXG4gICAgdmFyIGF4LCBheE5hbWU7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGF4ID0gYXhMaXN0W2ldO1xuICAgICAgICBheE5hbWUgPSBheC5fbmFtZTtcbiAgICAgICAgYW9ialtheE5hbWUgKyAnLnNob3dzcGlrZXMnXSA9IGZ1bGxMYXlvdXQuX2NhcnRlc2lhblNwaWtlc0VuYWJsZWQgPT09ICdvbicgPyB0cnVlIDogYXguX3Nob3dTcGlrZUluaXRpYWw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFvYmo7XG59XG5cbm1vZGVCYXJCdXR0b25zLnJlc2V0Vmlld01hcGJveCA9IHtcbiAgICBuYW1lOiAncmVzZXRWaWV3TWFwYm94JyxcbiAgICB0aXRsZTogZnVuY3Rpb24oZ2QpIHsgcmV0dXJuIF8oZ2QsICdSZXNldCB2aWV3Jyk7IH0sXG4gICAgYXR0cjogJ3Jlc2V0JyxcbiAgICBpY29uOiBJY29ucy5ob21lLFxuICAgIGNsaWNrOiBmdW5jdGlvbihnZCkge1xuICAgICAgICByZXNldFZpZXcoZ2QsICdtYXBib3gnKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiByZXNldFZpZXcoZ2QsIHN1YnBsb3RUeXBlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VicGxvdElkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW3N1YnBsb3RUeXBlXTtcbiAgICB2YXIgYU9iaiA9IHt9O1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkID0gc3VicGxvdElkc1tpXTtcbiAgICAgICAgdmFyIHN1YnBsb3RPYmogPSBmdWxsTGF5b3V0W2lkXS5fc3VicGxvdDtcbiAgICAgICAgdmFyIHZpZXdJbml0aWFsID0gc3VicGxvdE9iai52aWV3SW5pdGlhbDtcbiAgICAgICAgdmFyIHZpZXdLZXlzID0gT2JqZWN0LmtleXModmlld0luaXRpYWwpO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB2aWV3S2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGtleSA9IHZpZXdLZXlzW2pdO1xuICAgICAgICAgICAgYU9ialtpZCArICcuJyArIGtleV0gPSB2aWV3SW5pdGlhbFtrZXldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIGFPYmopO1xufVxuXG59LHtcIi4uLy4uL2ZvbnRzL3Bsb3RpY29uXCI6Njk5LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzXCI6NzcwLFwiLi4vLi4vcGxvdHMvcGxvdHNcIjo4MjgsXCIuLi8uLi9yZWdpc3RyeVwiOjg0N31dLDY1MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5tYW5hZ2UgPSBfZGVyZXFfKCcuL21hbmFnZScpO1xuXG59LHtcIi4vbWFuYWdlXCI6NjUzfV0sNjUzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXhpc0lkcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkcycpO1xudmFyIHNjYXR0ZXJTdWJUeXBlcyA9IF9kZXJlcV8oJy4uLy4uL3RyYWNlcy9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xuXG52YXIgY3JlYXRlTW9kZUJhciA9IF9kZXJlcV8oJy4vbW9kZWJhcicpO1xudmFyIG1vZGVCYXJCdXR0b25zID0gX2RlcmVxXygnLi9idXR0b25zJyk7XG5cbi8qKlxuICogTW9kZUJhciB3cmFwcGVyIGFyb3VuZCAnY3JlYXRlJyBhbmQgJ3VwZGF0ZScsXG4gKiBjaG9vc2VzIGJ1dHRvbnMgdG8gcGFzcyB0byBNb2RlQmFyIGNvbnN0cnVjdG9yIGJhc2VkIG9uXG4gKiBwbG90IHR5cGUgYW5kIHBsb3QgY29uZmlnLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBnZCBtYWluIHBsb3Qgb2JqZWN0XG4gKlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1hbmFnZU1vZGVCYXIoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBjb250ZXh0ID0gZ2QuX2NvbnRleHQ7XG4gICAgdmFyIG1vZGVCYXIgPSBmdWxsTGF5b3V0Ll9tb2RlQmFyO1xuXG4gICAgaWYoIWNvbnRleHQuZGlzcGxheU1vZGVCYXIgJiYgIWNvbnRleHQud2F0ZXJtYXJrKSB7XG4gICAgICAgIGlmKG1vZGVCYXIpIHtcbiAgICAgICAgICAgIG1vZGVCYXIuZGVzdHJveSgpO1xuICAgICAgICAgICAgZGVsZXRlIGZ1bGxMYXlvdXQuX21vZGVCYXI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmKCFBcnJheS5pc0FycmF5KGNvbnRleHQubW9kZUJhckJ1dHRvbnNUb1JlbW92ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFtcbiAgICAgICAgICAgICcqbW9kZUJhckJ1dHRvbnNUb1JlbW92ZSogY29uZmlndXJhdGlvbiBvcHRpb25zJyxcbiAgICAgICAgICAgICdtdXN0IGJlIGFuIGFycmF5LidcbiAgICAgICAgXS5qb2luKCcgJykpO1xuICAgIH1cblxuICAgIGlmKCFBcnJheS5pc0FycmF5KGNvbnRleHQubW9kZUJhckJ1dHRvbnNUb0FkZCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFtcbiAgICAgICAgICAgICcqbW9kZUJhckJ1dHRvbnNUb0FkZCogY29uZmlndXJhdGlvbiBvcHRpb25zJyxcbiAgICAgICAgICAgICdtdXN0IGJlIGFuIGFycmF5LidcbiAgICAgICAgXS5qb2luKCcgJykpO1xuICAgIH1cblxuICAgIHZhciBjdXN0b21CdXR0b25zID0gY29udGV4dC5tb2RlQmFyQnV0dG9ucztcbiAgICB2YXIgYnV0dG9uR3JvdXBzO1xuXG4gICAgaWYoQXJyYXkuaXNBcnJheShjdXN0b21CdXR0b25zKSAmJiBjdXN0b21CdXR0b25zLmxlbmd0aCkge1xuICAgICAgICBidXR0b25Hcm91cHMgPSBmaWxsQ3VzdG9tQnV0dG9uKGN1c3RvbUJ1dHRvbnMpO1xuICAgIH0gZWxzZSBpZighY29udGV4dC5kaXNwbGF5TW9kZUJhciAmJiBjb250ZXh0LndhdGVybWFyaykge1xuICAgICAgICBidXR0b25Hcm91cHMgPSBbXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBidXR0b25Hcm91cHMgPSBnZXRCdXR0b25Hcm91cHMoZ2QpO1xuICAgIH1cblxuICAgIGlmKG1vZGVCYXIpIG1vZGVCYXIudXBkYXRlKGdkLCBidXR0b25Hcm91cHMpO1xuICAgIGVsc2UgZnVsbExheW91dC5fbW9kZUJhciA9IGNyZWF0ZU1vZGVCYXIoZ2QsIGJ1dHRvbkdyb3Vwcyk7XG59O1xuXG4vLyBsb2dpYyBiZWhpbmQgd2hpY2ggYnV0dG9ucyBhcmUgZGlzcGxheWVkIGJ5IGRlZmF1bHRcbmZ1bmN0aW9uIGdldEJ1dHRvbkdyb3VwcyhnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhO1xuICAgIHZhciBjb250ZXh0ID0gZ2QuX2NvbnRleHQ7XG4gICAgdmFyIGJ1dHRvbnNUb1JlbW92ZSA9IGNvbnRleHQubW9kZUJhckJ1dHRvbnNUb1JlbW92ZTtcbiAgICB2YXIgYnV0dG9uc1RvQWRkID0gY29udGV4dC5tb2RlQmFyQnV0dG9uc1RvQWRkO1xuXG4gICAgdmFyIGhhc0NhcnRlc2lhbiA9IGZ1bGxMYXlvdXQuX2hhcygnY2FydGVzaWFuJyk7XG4gICAgdmFyIGhhc0dMM0QgPSBmdWxsTGF5b3V0Ll9oYXMoJ2dsM2QnKTtcbiAgICB2YXIgaGFzR2VvID0gZnVsbExheW91dC5faGFzKCdnZW8nKTtcbiAgICB2YXIgaGFzUGllID0gZnVsbExheW91dC5faGFzKCdwaWUnKTtcbiAgICB2YXIgaGFzRnVubmVsYXJlYSA9IGZ1bGxMYXlvdXQuX2hhcygnZnVubmVsYXJlYScpO1xuICAgIHZhciBoYXNHTDJEID0gZnVsbExheW91dC5faGFzKCdnbDJkJyk7XG4gICAgdmFyIGhhc1Rlcm5hcnkgPSBmdWxsTGF5b3V0Ll9oYXMoJ3Rlcm5hcnknKTtcbiAgICB2YXIgaGFzTWFwYm94ID0gZnVsbExheW91dC5faGFzKCdtYXBib3gnKTtcbiAgICB2YXIgaGFzUG9sYXIgPSBmdWxsTGF5b3V0Ll9oYXMoJ3BvbGFyJyk7XG4gICAgdmFyIGhhc1NhbmtleSA9IGZ1bGxMYXlvdXQuX2hhcygnc2Fua2V5Jyk7XG4gICAgdmFyIGFsbEF4ZXNGaXhlZCA9IGFyZUFsbEF4ZXNGaXhlZChmdWxsTGF5b3V0KTtcblxuICAgIHZhciBncm91cHMgPSBbXTtcblxuICAgIGZ1bmN0aW9uIGFkZEdyb3VwKG5ld0dyb3VwKSB7XG4gICAgICAgIGlmKCFuZXdHcm91cC5sZW5ndGgpIHJldHVybjtcblxuICAgICAgICB2YXIgb3V0ID0gW107XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG5ld0dyb3VwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgYnV0dG9uID0gbmV3R3JvdXBbaV07XG4gICAgICAgICAgICBpZihidXR0b25zVG9SZW1vdmUuaW5kZXhPZihidXR0b24pICE9PSAtMSkgY29udGludWU7XG4gICAgICAgICAgICBvdXQucHVzaChtb2RlQmFyQnV0dG9uc1tidXR0b25dKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdyb3Vwcy5wdXNoKG91dCk7XG4gICAgfVxuXG4gICAgLy8gYnV0dG9ucyBjb21tb24gdG8gYWxsIHBsb3QgdHlwZXNcbiAgICB2YXIgY29tbW9uR3JvdXAgPSBbJ3RvSW1hZ2UnXTtcbiAgICBpZihjb250ZXh0LnNob3dFZGl0SW5DaGFydFN0dWRpbykgY29tbW9uR3JvdXAucHVzaCgnZWRpdEluQ2hhcnRTdHVkaW8nKTtcbiAgICBlbHNlIGlmKGNvbnRleHQuc2hvd1NlbmRUb0Nsb3VkKSBjb21tb25Hcm91cC5wdXNoKCdzZW5kRGF0YVRvQ2xvdWQnKTtcbiAgICBhZGRHcm91cChjb21tb25Hcm91cCk7XG5cbiAgICB2YXIgem9vbUdyb3VwID0gW107XG4gICAgdmFyIGhvdmVyR3JvdXAgPSBbXTtcbiAgICB2YXIgcmVzZXRHcm91cCA9IFtdO1xuICAgIHZhciBkcmFnTW9kZUdyb3VwID0gW107XG5cbiAgICBpZigoaGFzQ2FydGVzaWFuIHx8IGhhc0dMMkQgfHwgaGFzUGllIHx8IGhhc0Z1bm5lbGFyZWEgfHwgaGFzVGVybmFyeSkgKyBoYXNHZW8gKyBoYXNHTDNEICsgaGFzTWFwYm94ICsgaGFzUG9sYXIgPiAxKSB7XG4gICAgICAgIC8vIGdyYXBocyB3aXRoIG1vcmUgdGhhbiBvbmUgcGxvdCB0eXBlcyBnZXQgJ3VuaW9uIGJ1dHRvbnMnXG4gICAgICAgIC8vIHdoaWNoIHJlc2V0IHRoZSB2aWV3IG9yIHRvZ2dsZSBob3ZlciBsYWJlbHMgYWNyb3NzIGFsbCBzdWJwbG90cy5cbiAgICAgICAgaG92ZXJHcm91cCA9IFsndG9nZ2xlSG92ZXInXTtcbiAgICAgICAgcmVzZXRHcm91cCA9IFsncmVzZXRWaWV3cyddO1xuICAgIH0gZWxzZSBpZihoYXNHZW8pIHtcbiAgICAgICAgem9vbUdyb3VwID0gWyd6b29tSW5HZW8nLCAnem9vbU91dEdlbyddO1xuICAgICAgICBob3Zlckdyb3VwID0gWydob3ZlckNsb3Nlc3RHZW8nXTtcbiAgICAgICAgcmVzZXRHcm91cCA9IFsncmVzZXRHZW8nXTtcbiAgICB9IGVsc2UgaWYoaGFzR0wzRCkge1xuICAgICAgICBob3Zlckdyb3VwID0gWydob3ZlckNsb3Nlc3QzZCddO1xuICAgICAgICByZXNldEdyb3VwID0gWydyZXNldENhbWVyYURlZmF1bHQzZCcsICdyZXNldENhbWVyYUxhc3RTYXZlM2QnXTtcbiAgICB9IGVsc2UgaWYoaGFzTWFwYm94KSB7XG4gICAgICAgIGhvdmVyR3JvdXAgPSBbJ3RvZ2dsZUhvdmVyJ107XG4gICAgICAgIHJlc2V0R3JvdXAgPSBbJ3Jlc2V0Vmlld01hcGJveCddO1xuICAgIH0gZWxzZSBpZihoYXNHTDJEKSB7XG4gICAgICAgIGhvdmVyR3JvdXAgPSBbJ2hvdmVyQ2xvc2VzdEdsMmQnXTtcbiAgICB9IGVsc2UgaWYoaGFzUGllKSB7XG4gICAgICAgIGhvdmVyR3JvdXAgPSBbJ2hvdmVyQ2xvc2VzdFBpZSddO1xuICAgIH0gZWxzZSBpZihoYXNTYW5rZXkpIHtcbiAgICAgICAgaG92ZXJHcm91cCA9IFsnaG92ZXJDbG9zZXN0Q2FydGVzaWFuJywgJ2hvdmVyQ29tcGFyZUNhcnRlc2lhbiddO1xuICAgICAgICByZXNldEdyb3VwID0gWydyZXNldFZpZXdTYW5rZXknXTtcbiAgICB9IGVsc2UgeyAvLyBoYXNQb2xhciwgaGFzVGVybmFyeVxuICAgICAgICAvLyBhbHdheXMgc2hvdyBhdCBsZWFzdCBvbmUgaG92ZXIgaWNvbi5cbiAgICAgICAgaG92ZXJHcm91cCA9IFsndG9nZ2xlSG92ZXInXTtcbiAgICB9XG4gICAgLy8gaWYgd2UgaGF2ZSBjYXJ0ZXNpYW4sIGFsbG93IHN3aXRjaGluZyBiZXR3ZWVuIGNsb3Nlc3QgYW5kIGNvbXBhcmVcbiAgICAvLyByZWdhcmRsZXNzIG9mIHdoYXQgb3RoZXIgdHlwZXMgYXJlIG9uIHRoZSBwbG90LCBzaW5jZSB0aGV5J2xsIGFsbFxuICAgIC8vIGp1c3QgdHJlYXQgYW55IHRydXRoeSBob3Zlcm1vZGUgYXMgJ2Nsb3Nlc3QnXG4gICAgaWYoaGFzQ2FydGVzaWFuKSB7XG4gICAgICAgIGhvdmVyR3JvdXAgPSBbJ3RvZ2dsZVNwaWtlbGluZXMnLCAnaG92ZXJDbG9zZXN0Q2FydGVzaWFuJywgJ2hvdmVyQ29tcGFyZUNhcnRlc2lhbiddO1xuICAgIH1cbiAgICBpZihoYXNOb0hvdmVyKGZ1bGxEYXRhKSkge1xuICAgICAgICBob3Zlckdyb3VwID0gW107XG4gICAgfVxuXG4gICAgaWYoKGhhc0NhcnRlc2lhbiB8fCBoYXNHTDJEKSAmJiAhYWxsQXhlc0ZpeGVkKSB7XG4gICAgICAgIHpvb21Hcm91cCA9IFsnem9vbUluMmQnLCAnem9vbU91dDJkJywgJ2F1dG9TY2FsZTJkJ107XG4gICAgICAgIGlmKHJlc2V0R3JvdXBbMF0gIT09ICdyZXNldFZpZXdzJykgcmVzZXRHcm91cCA9IFsncmVzZXRTY2FsZTJkJ107XG4gICAgfVxuXG4gICAgaWYoaGFzR0wzRCkge1xuICAgICAgICBkcmFnTW9kZUdyb3VwID0gWyd6b29tM2QnLCAncGFuM2QnLCAnb3JiaXRSb3RhdGlvbicsICd0YWJsZVJvdGF0aW9uJ107XG4gICAgfSBlbHNlIGlmKCgoaGFzQ2FydGVzaWFuIHx8IGhhc0dMMkQpICYmICFhbGxBeGVzRml4ZWQpIHx8IGhhc1Rlcm5hcnkpIHtcbiAgICAgICAgZHJhZ01vZGVHcm91cCA9IFsnem9vbTJkJywgJ3BhbjJkJ107XG4gICAgfSBlbHNlIGlmKGhhc01hcGJveCB8fCBoYXNHZW8pIHtcbiAgICAgICAgZHJhZ01vZGVHcm91cCA9IFsncGFuMmQnXTtcbiAgICB9IGVsc2UgaWYoaGFzUG9sYXIpIHtcbiAgICAgICAgZHJhZ01vZGVHcm91cCA9IFsnem9vbTJkJ107XG4gICAgfVxuICAgIGlmKGlzU2VsZWN0YWJsZShmdWxsRGF0YSkpIHtcbiAgICAgICAgZHJhZ01vZGVHcm91cC5wdXNoKCdzZWxlY3QyZCcsICdsYXNzbzJkJyk7XG4gICAgfVxuXG4gICAgYWRkR3JvdXAoZHJhZ01vZGVHcm91cCk7XG4gICAgYWRkR3JvdXAoem9vbUdyb3VwLmNvbmNhdChyZXNldEdyb3VwKSk7XG4gICAgYWRkR3JvdXAoaG92ZXJHcm91cCk7XG5cbiAgICByZXR1cm4gYXBwZW5kQnV0dG9uc1RvR3JvdXBzKGdyb3VwcywgYnV0dG9uc1RvQWRkKTtcbn1cblxuZnVuY3Rpb24gYXJlQWxsQXhlc0ZpeGVkKGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgYXhMaXN0ID0gYXhpc0lkcy5saXN0KHtfZnVsbExheW91dDogZnVsbExheW91dH0sIG51bGwsIHRydWUpO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZighYXhMaXN0W2ldLmZpeGVkcmFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xufVxuXG4vLyBsb29rIGZvciB0cmFjZXMgdGhhdCBzdXBwb3J0IHNlbGVjdGlvblxuLy8gdG8gYmUgdXBkYXRlZCBhcyB3ZSBhZGQgbW9yZSBzZWxlY3RQb2ludHMgaGFuZGxlcnNcbmZ1bmN0aW9uIGlzU2VsZWN0YWJsZShmdWxsRGF0YSkge1xuICAgIHZhciBzZWxlY3RhYmxlID0gZmFsc2U7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoc2VsZWN0YWJsZSkgYnJlYWs7XG5cbiAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgaWYoIXRyYWNlLl9tb2R1bGUgfHwgIXRyYWNlLl9tb2R1bGUuc2VsZWN0UG9pbnRzKSBjb250aW51ZTtcblxuICAgICAgICBpZihSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnc2NhdHRlci1saWtlJykpIHtcbiAgICAgICAgICAgIGlmKHNjYXR0ZXJTdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlKSB8fCBzY2F0dGVyU3ViVHlwZXMuaGFzVGV4dCh0cmFjZSkpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3RhYmxlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdib3gtdmlvbGluJykpIHtcbiAgICAgICAgICAgIGlmKHRyYWNlLmJveHBvaW50cyA9PT0gJ2FsbCcgfHwgdHJhY2UucG9pbnRzID09PSAnYWxsJykge1xuICAgICAgICAgICAgICAgIHNlbGVjdGFibGUgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gYXNzdW1lIHRoYXQgaW4gZ2VuZXJhbCBpZiB0aGUgdHJhY2UgbW9kdWxlIGhhcyBzZWxlY3RQb2ludHMsXG4gICAgICAgICAgICAvLyB0aGVuIGl0J3Mgc2VsZWN0YWJsZS4gU2NhdHRlciBpcyBhbiBleGNlcHRpb24gdG8gdGhpcyBiZWNhdXNlIGl0IG11c3RcbiAgICAgICAgICAgIC8vIGhhdmUgbWFya2VycyBvciB0ZXh0LCBub3QganVzdCBiZSBhIHNjYXR0ZXIgdHlwZS5cblxuICAgICAgICAgICAgc2VsZWN0YWJsZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0YWJsZTtcbn1cblxuLy8gY2hlY2sgd2hldGhlciBhbGwgdHJhY2UgYXJlICdub0hvdmVyJ1xuZnVuY3Rpb24gaGFzTm9Ib3ZlcihmdWxsRGF0YSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZighUmVnaXN0cnkudHJhY2VJcyhmdWxsRGF0YVtpXSwgJ25vSG92ZXInKSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gYXBwZW5kQnV0dG9uc1RvR3JvdXBzKGdyb3VwcywgYnV0dG9ucykge1xuICAgIGlmKGJ1dHRvbnMubGVuZ3RoKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoYnV0dG9uc1swXSkpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBidXR0b25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBzLnB1c2goYnV0dG9uc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBncm91cHMucHVzaChidXR0b25zKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ3JvdXBzO1xufVxuXG4vLyBmaWxsIGluIGN1c3RvbSBidXR0b25zIHJlZmVycmluZyB0byBkZWZhdWx0IG1vZGUgYmFyIGJ1dHRvbnNcbmZ1bmN0aW9uIGZpbGxDdXN0b21CdXR0b24oY3VzdG9tQnV0dG9ucykge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjdXN0b21CdXR0b25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBidXR0b25Hcm91cCA9IGN1c3RvbUJ1dHRvbnNbaV07XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGJ1dHRvbkdyb3VwLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgYnV0dG9uID0gYnV0dG9uR3JvdXBbal07XG5cbiAgICAgICAgICAgIGlmKHR5cGVvZiBidXR0b24gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaWYobW9kZUJhckJ1dHRvbnNbYnV0dG9uXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1c3RvbUJ1dHRvbnNbaV1bal0gPSBtb2RlQmFyQnV0dG9uc1tidXR0b25dO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihbXG4gICAgICAgICAgICAgICAgICAgICAgICAnKm1vZGVCYXJCdXR0b25zKiBjb25maWd1cmF0aW9uIG9wdGlvbnMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2ludmFsaWQgYnV0dG9uIG5hbWUnXG4gICAgICAgICAgICAgICAgICAgIF0uam9pbignICcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY3VzdG9tQnV0dG9ucztcbn1cblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHNcIjo3NzAsXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4uLy4uL3RyYWNlcy9zY2F0dGVyL3N1YnR5cGVzXCI6MTEzNSxcIi4vYnV0dG9uc1wiOjY1MSxcIi4vbW9kZWJhclwiOjY1NH1dLDY1NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgSWNvbnMgPSBfZGVyZXFfKCcuLi8uLi9mb250cy9wbG90aWNvbicpO1xudmFyIFBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcblxuLyoqXG4gKiBVSSBjb250cm9sbGVyIGZvciBpbnRlcmFjdGl2ZSBwbG90c1xuICogQENsYXNzXG4gKiBAUGFyYW0ge29iamVjdH0gb3B0c1xuICogQFBhcmFtIHtvYmplY3R9IG9wdHMuYnV0dG9ucyAgICBuZXN0ZWQgYXJyYXlzIG9mIGdyb3VwZWQgYnV0dG9ucyBjb25maWcgb2JqZWN0c1xuICogQFBhcmFtIHtvYmplY3R9IG9wdHMuY29udGFpbmVyICBjb250YWluZXIgZGl2IHRvIGFwcGVuZCBtb2RlQmFyXG4gKiBAUGFyYW0ge29iamVjdH0gb3B0cy5ncmFwaEluZm8gIHByaW1hcnkgcGxvdCBvYmplY3QgY29udGFpbmluZyBkYXRhIGFuZCBsYXlvdXRcbiAqL1xuZnVuY3Rpb24gTW9kZUJhcihvcHRzKSB7XG4gICAgdGhpcy5jb250YWluZXIgPSBvcHRzLmNvbnRhaW5lcjtcbiAgICB0aGlzLmVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgIHRoaXMudXBkYXRlKG9wdHMuZ3JhcGhJbmZvLCBvcHRzLmJ1dHRvbnMpO1xuXG4gICAgdGhpcy5jb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5lbGVtZW50KTtcbn1cblxudmFyIHByb3RvID0gTW9kZUJhci5wcm90b3R5cGU7XG5cbi8qKlxuICogVXBkYXRlIG1vZGVCYXIgKGJ1dHRvbnMgYW5kIGxvZ28pXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGdyYXBoSW5mbyAgcHJpbWFyeSBwbG90IG9iamVjdCBjb250YWluaW5nIGRhdGEgYW5kIGxheW91dFxuICogQHBhcmFtIHthcnJheSBvZiBhcnJheXN9IGJ1dHRvbnMgbmVzdGVkIGFycmF5cyBvZiBncm91cGVkIGJ1dHRvbnMgdG8gaW5pdGlhbGl6ZVxuICpcbiAqL1xucHJvdG8udXBkYXRlID0gZnVuY3Rpb24oZ3JhcGhJbmZvLCBidXR0b25zKSB7XG4gICAgdGhpcy5ncmFwaEluZm8gPSBncmFwaEluZm87XG5cbiAgICB2YXIgY29udGV4dCA9IHRoaXMuZ3JhcGhJbmZvLl9jb250ZXh0O1xuICAgIHZhciBmdWxsTGF5b3V0ID0gdGhpcy5ncmFwaEluZm8uX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIG1vZGVCYXJJZCA9ICdtb2RlYmFyLScgKyBmdWxsTGF5b3V0Ll91aWQ7XG5cbiAgICB0aGlzLmVsZW1lbnQuc2V0QXR0cmlidXRlKCdpZCcsIG1vZGVCYXJJZCk7XG4gICAgdGhpcy5fdWlkID0gbW9kZUJhcklkO1xuXG4gICAgdGhpcy5lbGVtZW50LmNsYXNzTmFtZSA9ICdtb2RlYmFyJztcbiAgICBpZihjb250ZXh0LmRpc3BsYXlNb2RlQmFyID09PSAnaG92ZXInKSB0aGlzLmVsZW1lbnQuY2xhc3NOYW1lICs9ICcgbW9kZWJhci0taG92ZXIgZWFzZS1iZyc7XG5cbiAgICBpZihmdWxsTGF5b3V0Lm1vZGViYXIub3JpZW50YXRpb24gPT09ICd2Jykge1xuICAgICAgICB0aGlzLmVsZW1lbnQuY2xhc3NOYW1lICs9ICcgdmVydGljYWwnO1xuICAgICAgICBidXR0b25zID0gYnV0dG9ucy5yZXZlcnNlKCk7XG4gICAgfVxuXG4gICAgdmFyIHN0eWxlID0gZnVsbExheW91dC5tb2RlYmFyO1xuICAgIHZhciBiZ1NlbGVjdG9yID0gY29udGV4dC5kaXNwbGF5TW9kZUJhciA9PT0gJ2hvdmVyJyA/ICcuanMtcGxvdGx5LXBsb3QgLnBsb3RseTpob3ZlciAnIDogJyc7XG5cbiAgICBMaWIuZGVsZXRlUmVsYXRlZFN0eWxlUnVsZShtb2RlQmFySWQpO1xuICAgIExpYi5hZGRSZWxhdGVkU3R5bGVSdWxlKG1vZGVCYXJJZCwgYmdTZWxlY3RvciArICcjJyArIG1vZGVCYXJJZCArICcgLm1vZGViYXItZ3JvdXAnLCAnYmFja2dyb3VuZC1jb2xvcjogJyArIHN0eWxlLmJnY29sb3IpO1xuICAgIExpYi5hZGRSZWxhdGVkU3R5bGVSdWxlKG1vZGVCYXJJZCwgJyMnICsgbW9kZUJhcklkICsgJyAubW9kZWJhci1idG4gLmljb24gcGF0aCcsICdmaWxsOiAnICsgc3R5bGUuY29sb3IpO1xuICAgIExpYi5hZGRSZWxhdGVkU3R5bGVSdWxlKG1vZGVCYXJJZCwgJyMnICsgbW9kZUJhcklkICsgJyAubW9kZWJhci1idG46aG92ZXIgLmljb24gcGF0aCcsICdmaWxsOiAnICsgc3R5bGUuYWN0aXZlY29sb3IpO1xuICAgIExpYi5hZGRSZWxhdGVkU3R5bGVSdWxlKG1vZGVCYXJJZCwgJyMnICsgbW9kZUJhcklkICsgJyAubW9kZWJhci1idG4uYWN0aXZlIC5pY29uIHBhdGgnLCAnZmlsbDogJyArIHN0eWxlLmFjdGl2ZWNvbG9yKTtcblxuICAgIC8vIGlmIGJ1dHRvbnMgb3IgbG9nbyBoYXZlIGNoYW5nZWQsIHJlZHJhdyBtb2RlYmFyIGludGVyaW9yXG4gICAgdmFyIG5lZWRzTmV3QnV0dG9ucyA9ICF0aGlzLmhhc0J1dHRvbnMoYnV0dG9ucyk7XG4gICAgdmFyIG5lZWRzTmV3TG9nbyA9ICh0aGlzLmhhc0xvZ28gIT09IGNvbnRleHQuZGlzcGxheWxvZ28pO1xuICAgIHZhciBuZWVkc05ld0xvY2FsZSA9ICh0aGlzLmxvY2FsZSAhPT0gY29udGV4dC5sb2NhbGUpO1xuXG4gICAgdGhpcy5sb2NhbGUgPSBjb250ZXh0LmxvY2FsZTtcblxuICAgIGlmKG5lZWRzTmV3QnV0dG9ucyB8fCBuZWVkc05ld0xvZ28gfHwgbmVlZHNOZXdMb2NhbGUpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVBbGxCdXR0b25zKCk7XG5cbiAgICAgICAgdGhpcy51cGRhdGVCdXR0b25zKGJ1dHRvbnMpO1xuXG4gICAgICAgIGlmKGNvbnRleHQud2F0ZXJtYXJrIHx8IGNvbnRleHQuZGlzcGxheWxvZ28pIHtcbiAgICAgICAgICAgIHZhciBsb2dvR3JvdXAgPSB0aGlzLmdldExvZ28oKTtcbiAgICAgICAgICAgIGlmKGNvbnRleHQud2F0ZXJtYXJrKSB7XG4gICAgICAgICAgICAgICAgbG9nb0dyb3VwLmNsYXNzTmFtZSA9IGxvZ29Hcm91cC5jbGFzc05hbWUgKyAnIHdhdGVybWFyayc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGZ1bGxMYXlvdXQubW9kZWJhci5vcmllbnRhdGlvbiA9PT0gJ3YnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50Lmluc2VydEJlZm9yZShsb2dvR3JvdXAsIHRoaXMuZWxlbWVudC5jaGlsZE5vZGVzWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50LmFwcGVuZENoaWxkKGxvZ29Hcm91cCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuaGFzTG9nbyA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZUFjdGl2ZUJ1dHRvbigpO1xufTtcblxucHJvdG8udXBkYXRlQnV0dG9ucyA9IGZ1bmN0aW9uKGJ1dHRvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdGhpcy5idXR0b25zID0gYnV0dG9ucztcbiAgICB0aGlzLmJ1dHRvbkVsZW1lbnRzID0gW107XG4gICAgdGhpcy5idXR0b25zTmFtZXMgPSBbXTtcblxuICAgIHRoaXMuYnV0dG9ucy5mb3JFYWNoKGZ1bmN0aW9uKGJ1dHRvbkdyb3VwKSB7XG4gICAgICAgIHZhciBncm91cCA9IF90aGlzLmNyZWF0ZUdyb3VwKCk7XG5cbiAgICAgICAgYnV0dG9uR3JvdXAuZm9yRWFjaChmdW5jdGlvbihidXR0b25Db25maWcpIHtcbiAgICAgICAgICAgIHZhciBidXR0b25OYW1lID0gYnV0dG9uQ29uZmlnLm5hbWU7XG4gICAgICAgICAgICBpZighYnV0dG9uTmFtZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignbXVzdCBwcm92aWRlIGJ1dHRvbiBcXCduYW1lXFwnIGluIGJ1dHRvbiBjb25maWcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKF90aGlzLmJ1dHRvbnNOYW1lcy5pbmRleE9mKGJ1dHRvbk5hbWUpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignYnV0dG9uIG5hbWUgXFwnJyArIGJ1dHRvbk5hbWUgKyAnXFwnIGlzIHRha2VuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfdGhpcy5idXR0b25zTmFtZXMucHVzaChidXR0b25OYW1lKTtcblxuICAgICAgICAgICAgdmFyIGJ1dHRvbiA9IF90aGlzLmNyZWF0ZUJ1dHRvbihidXR0b25Db25maWcpO1xuICAgICAgICAgICAgX3RoaXMuYnV0dG9uRWxlbWVudHMucHVzaChidXR0b24pO1xuICAgICAgICAgICAgZ3JvdXAuYXBwZW5kQ2hpbGQoYnV0dG9uKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgX3RoaXMuZWxlbWVudC5hcHBlbmRDaGlsZChncm91cCk7XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIEVtcHR5IGRpdiBmb3IgY29udGFpbmluZyBhIGdyb3VwIG9mIGJ1dHRvbnNcbiAqIEBSZXR1cm4ge0hUTUxlbGVtZW50fVxuICovXG5wcm90by5jcmVhdGVHcm91cCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBncm91cCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGdyb3VwLmNsYXNzTmFtZSA9ICdtb2RlYmFyLWdyb3VwJztcbiAgICByZXR1cm4gZ3JvdXA7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIG5ldyBidXR0b24gZGl2IGFuZCBzZXQgY29uc3RhbnQgYW5kIGNvbmZpZ3VyYWJsZSBhdHRyaWJ1dGVzXG4gKiBAUGFyYW0ge29iamVjdH0gY29uZmlnIChzZWUgLi9idXR0b25zLmpzIGZvciBtb3JlIGluZm8pXG4gKiBAUmV0dXJuIHtIVE1MZWxlbWVudH1cbiAqL1xucHJvdG8uY3JlYXRlQnV0dG9uID0gZnVuY3Rpb24oY29uZmlnKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgYnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuXG4gICAgYnV0dG9uLnNldEF0dHJpYnV0ZSgncmVsJywgJ3Rvb2x0aXAnKTtcbiAgICBidXR0b24uY2xhc3NOYW1lID0gJ21vZGViYXItYnRuJztcblxuICAgIHZhciB0aXRsZSA9IGNvbmZpZy50aXRsZTtcbiAgICBpZih0aXRsZSA9PT0gdW5kZWZpbmVkKSB0aXRsZSA9IGNvbmZpZy5uYW1lO1xuICAgIC8vIGZvciBsb2NhbGl6YXRpb246IGFsbG93IHRpdGxlIHRvIGJlIGEgY2FsbGFibGUgdGhhdCB0YWtlcyBnZCBhcyBhcmdcbiAgICBlbHNlIGlmKHR5cGVvZiB0aXRsZSA9PT0gJ2Z1bmN0aW9uJykgdGl0bGUgPSB0aXRsZSh0aGlzLmdyYXBoSW5mbyk7XG5cbiAgICBpZih0aXRsZSB8fCB0aXRsZSA9PT0gMCkgYnV0dG9uLnNldEF0dHJpYnV0ZSgnZGF0YS10aXRsZScsIHRpdGxlKTtcblxuICAgIGlmKGNvbmZpZy5hdHRyICE9PSB1bmRlZmluZWQpIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicsIGNvbmZpZy5hdHRyKTtcblxuICAgIHZhciB2YWwgPSBjb25maWcudmFsO1xuICAgIGlmKHZhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmKHR5cGVvZiB2YWwgPT09ICdmdW5jdGlvbicpIHZhbCA9IHZhbCh0aGlzLmdyYXBoSW5mbyk7XG4gICAgICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtdmFsJywgdmFsKTtcbiAgICB9XG5cbiAgICB2YXIgY2xpY2sgPSBjb25maWcuY2xpY2s7XG4gICAgaWYodHlwZW9mIGNsaWNrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbXVzdCBwcm92aWRlIGJ1dHRvbiBcXCdjbGlja1xcJyBmdW5jdGlvbiBpbiBidXR0b24gY29uZmlnJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgICAgIGNvbmZpZy5jbGljayhfdGhpcy5ncmFwaEluZm8sIGV2KTtcblxuICAgICAgICAgICAgLy8gb25seSBuZWVkZWQgZm9yICdob3ZlckNsb3Nlc3RHZW8nIHdoaWNoIGRvZXMgbm90IGNhbGwgcmVsYXlvdXRcbiAgICAgICAgICAgIF90aGlzLnVwZGF0ZUFjdGl2ZUJ1dHRvbihldi5jdXJyZW50VGFyZ2V0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYnV0dG9uLnNldEF0dHJpYnV0ZSgnZGF0YS10b2dnbGUnLCBjb25maWcudG9nZ2xlIHx8IGZhbHNlKTtcbiAgICBpZihjb25maWcudG9nZ2xlKSBkMy5zZWxlY3QoYnV0dG9uKS5jbGFzc2VkKCdhY3RpdmUnLCB0cnVlKTtcblxuICAgIHZhciBpY29uID0gY29uZmlnLmljb247XG4gICAgaWYodHlwZW9mIGljb24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgYnV0dG9uLmFwcGVuZENoaWxkKGljb24oKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYnV0dG9uLmFwcGVuZENoaWxkKHRoaXMuY3JlYXRlSWNvbihpY29uIHx8IEljb25zLnF1ZXN0aW9uKSk7XG4gICAgfVxuICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtZ3Jhdml0eScsIGNvbmZpZy5ncmF2aXR5IHx8ICduJyk7XG5cbiAgICByZXR1cm4gYnV0dG9uO1xufTtcblxuLyoqXG4gKiBBZGQgYW4gaWNvbiB0byBhIGJ1dHRvblxuICogQFBhcmFtIHtvYmplY3R9IHRoaXNJY29uXG4gKiBAUGFyYW0ge251bWJlcn0gdGhpc0ljb24ud2lkdGhcbiAqIEBQYXJhbSB7c3RyaW5nfSB0aGlzSWNvbi5wYXRoXG4gKiBAUGFyYW0ge3N0cmluZ30gdGhpc0ljb24uY29sb3JcbiAqIEBSZXR1cm4ge0hUTUxlbGVtZW50fVxuICovXG5wcm90by5jcmVhdGVJY29uID0gZnVuY3Rpb24odGhpc0ljb24pIHtcbiAgICB2YXIgaWNvbkhlaWdodCA9IGlzTnVtZXJpYyh0aGlzSWNvbi5oZWlnaHQpID9cbiAgICAgICAgTnVtYmVyKHRoaXNJY29uLmhlaWdodCkgOlxuICAgICAgICB0aGlzSWNvbi5hc2NlbnQgLSB0aGlzSWNvbi5kZXNjZW50O1xuICAgIHZhciBzdmdOUyA9ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Zyc7XG4gICAgdmFyIGljb247XG5cbiAgICBpZih0aGlzSWNvbi5wYXRoKSB7XG4gICAgICAgIGljb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoc3ZnTlMsICdzdmcnKTtcbiAgICAgICAgaWNvbi5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCBbMCwgMCwgdGhpc0ljb24ud2lkdGgsIGljb25IZWlnaHRdLmpvaW4oJyAnKSk7XG4gICAgICAgIGljb24uc2V0QXR0cmlidXRlKCdjbGFzcycsICdpY29uJyk7XG5cbiAgICAgICAgdmFyIHBhdGggPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoc3ZnTlMsICdwYXRoJyk7XG4gICAgICAgIHBhdGguc2V0QXR0cmlidXRlKCdkJywgdGhpc0ljb24ucGF0aCk7XG5cbiAgICAgICAgaWYodGhpc0ljb24udHJhbnNmb3JtKSB7XG4gICAgICAgICAgICBwYXRoLnNldEF0dHJpYnV0ZSgndHJhbnNmb3JtJywgdGhpc0ljb24udHJhbnNmb3JtKTtcbiAgICAgICAgfSBlbHNlIGlmKHRoaXNJY29uLmFzY2VudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyBMZWdhY3kgaWNvbiB0cmFuc2Zvcm0gY2FsY3VsYXRpb25cbiAgICAgICAgICAgIHBhdGguc2V0QXR0cmlidXRlKCd0cmFuc2Zvcm0nLCAnbWF0cml4KDEgMCAwIC0xIDAgJyArIHRoaXNJY29uLmFzY2VudCArICcpJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpY29uLmFwcGVuZENoaWxkKHBhdGgpO1xuICAgIH1cblxuICAgIGlmKHRoaXNJY29uLnN2Zykge1xuICAgICAgICB2YXIgc3ZnRG9jID0gUGFyc2VyLnBhcnNlRnJvbVN0cmluZyh0aGlzSWNvbi5zdmcsICdhcHBsaWNhdGlvbi94bWwnKTtcbiAgICAgICAgaWNvbiA9IHN2Z0RvYy5jaGlsZE5vZGVzWzBdO1xuICAgIH1cblxuICAgIGljb24uc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMWVtJyk7XG4gICAgaWNvbi5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgJzFlbScpO1xuXG4gICAgcmV0dXJuIGljb247XG59O1xuXG4vKipcbiAqIFVwZGF0ZXMgYWN0aXZlIGJ1dHRvbiB3aXRoIGF0dHJpYnV0ZSBzcGVjaWZpZWQgaW4gbGF5b3V0XG4gKiBAUGFyYW0ge29iamVjdH0gZ3JhcGhJbmZvIHBsb3Qgb2JqZWN0IGNvbnRhaW5pbmcgZGF0YSBhbmQgbGF5b3V0XG4gKiBAUmV0dXJuIHtIVE1MZWxlbWVudH1cbiAqL1xucHJvdG8udXBkYXRlQWN0aXZlQnV0dG9uID0gZnVuY3Rpb24oYnV0dG9uQ2xpY2tlZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gdGhpcy5ncmFwaEluZm8uX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGRhdGFBdHRyQ2xpY2tlZCA9IChidXR0b25DbGlja2VkICE9PSB1bmRlZmluZWQpID9cbiAgICAgICAgYnV0dG9uQ2xpY2tlZC5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicpIDpcbiAgICAgICAgbnVsbDtcblxuICAgIHRoaXMuYnV0dG9uRWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbihidXR0b24pIHtcbiAgICAgICAgdmFyIHRoaXN2YWwgPSBidXR0b24uZ2V0QXR0cmlidXRlKCdkYXRhLXZhbCcpIHx8IHRydWU7XG4gICAgICAgIHZhciBkYXRhQXR0ciA9IGJ1dHRvbi5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXR0cicpO1xuICAgICAgICB2YXIgaXNUb2dnbGVCdXR0b24gPSAoYnV0dG9uLmdldEF0dHJpYnV0ZSgnZGF0YS10b2dnbGUnKSA9PT0gJ3RydWUnKTtcbiAgICAgICAgdmFyIGJ1dHRvbjMgPSBkMy5zZWxlY3QoYnV0dG9uKTtcblxuICAgICAgICAvLyBVc2UgJ2RhdGEtdG9nZ2xlJyBhbmQgJ2J1dHRvbkNsaWNrZWQnIHRvIHRvZ2dsZSBidXR0b25zXG4gICAgICAgIC8vIHRoYXQgaGF2ZSBubyBvbmUtdG8tb25lIGVxdWl2YWxlbnQgaW4gZnVsbExheW91dFxuICAgICAgICBpZihpc1RvZ2dsZUJ1dHRvbikge1xuICAgICAgICAgICAgaWYoZGF0YUF0dHIgPT09IGRhdGFBdHRyQ2xpY2tlZCkge1xuICAgICAgICAgICAgICAgIGJ1dHRvbjMuY2xhc3NlZCgnYWN0aXZlJywgIWJ1dHRvbjMuY2xhc3NlZCgnYWN0aXZlJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHZhbCA9IChkYXRhQXR0ciA9PT0gbnVsbCkgP1xuICAgICAgICAgICAgICAgIGRhdGFBdHRyIDpcbiAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgZGF0YUF0dHIpLmdldCgpO1xuXG4gICAgICAgICAgICBidXR0b24zLmNsYXNzZWQoJ2FjdGl2ZScsIHZhbCA9PT0gdGhpc3ZhbCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgbW9kZUJhciBpcyBjb25maWd1cmVkIGFzIGJ1dHRvbiBjb25maWd1cmF0aW9uIGFyZ3VtZW50XG4gKlxuICogQFBhcmFtIHtvYmplY3R9IGJ1dHRvbnMgMmQgYXJyYXkgb2YgZ3JvdXBlZCBidXR0b24gY29uZmlnIG9iamVjdHNcbiAqIEBSZXR1cm4ge2Jvb2xlYW59XG4gKi9cbnByb3RvLmhhc0J1dHRvbnMgPSBmdW5jdGlvbihidXR0b25zKSB7XG4gICAgdmFyIGN1cnJlbnRCdXR0b25zID0gdGhpcy5idXR0b25zO1xuXG4gICAgaWYoIWN1cnJlbnRCdXR0b25zKSByZXR1cm4gZmFsc2U7XG5cbiAgICBpZihidXR0b25zLmxlbmd0aCAhPT0gY3VycmVudEJ1dHRvbnMubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYnV0dG9ucy5sZW5ndGg7ICsraSkge1xuICAgICAgICBpZihidXR0b25zW2ldLmxlbmd0aCAhPT0gY3VycmVudEJ1dHRvbnNbaV0ubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBidXR0b25zW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZihidXR0b25zW2ldW2pdLm5hbWUgIT09IGN1cnJlbnRCdXR0b25zW2ldW2pdLm5hbWUpIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtIVE1MRGl2RWxlbWVudH0gVGhlIGxvZ28gaW1hZ2Ugd3JhcHBlZCBpbiBhIGdyb3VwXG4gKi9cbnByb3RvLmdldExvZ28gPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZ3JvdXAgPSB0aGlzLmNyZWF0ZUdyb3VwKCk7XG4gICAgdmFyIGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG5cbiAgICBhLmhyZWYgPSAnaHR0cHM6Ly9wbG90Lmx5Lyc7XG4gICAgYS50YXJnZXQgPSAnX2JsYW5rJztcbiAgICBhLnNldEF0dHJpYnV0ZSgnZGF0YS10aXRsZScsIExpYi5fKHRoaXMuZ3JhcGhJbmZvLCAnUHJvZHVjZWQgd2l0aCBQbG90bHknKSk7XG4gICAgYS5jbGFzc05hbWUgPSAnbW9kZWJhci1idG4gcGxvdGx5anNpY29uIG1vZGViYXItYnRuLS1sb2dvJztcblxuICAgIGEuYXBwZW5kQ2hpbGQodGhpcy5jcmVhdGVJY29uKEljb25zLm5ld3Bsb3RseWxvZ28pKTtcblxuICAgIGdyb3VwLmFwcGVuZENoaWxkKGEpO1xuICAgIHJldHVybiBncm91cDtcbn07XG5cbnByb3RvLnJlbW92ZUFsbEJ1dHRvbnMgPSBmdW5jdGlvbigpIHtcbiAgICB3aGlsZSh0aGlzLmVsZW1lbnQuZmlyc3RDaGlsZCkge1xuICAgICAgICB0aGlzLmVsZW1lbnQucmVtb3ZlQ2hpbGQodGhpcy5lbGVtZW50LmZpcnN0Q2hpbGQpO1xuICAgIH1cblxuICAgIHRoaXMuaGFzTG9nbyA9IGZhbHNlO1xufTtcblxucHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uKCkge1xuICAgIExpYi5yZW1vdmVFbGVtZW50KHRoaXMuY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5tb2RlYmFyJykpO1xuICAgIExpYi5kZWxldGVSZWxhdGVkU3R5bGVSdWxlKHRoaXMuX3VpZCk7XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVNb2RlQmFyKGdkLCBidXR0b25zKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciBtb2RlQmFyID0gbmV3IE1vZGVCYXIoe1xuICAgICAgICBncmFwaEluZm86IGdkLFxuICAgICAgICBjb250YWluZXI6IGZ1bGxMYXlvdXQuX21vZGViYXJkaXYubm9kZSgpLFxuICAgICAgICBidXR0b25zOiBidXR0b25zXG4gICAgfSk7XG5cbiAgICBpZihmdWxsTGF5b3V0Ll9wcml2YXRlcGxvdCkge1xuICAgICAgICBkMy5zZWxlY3QobW9kZUJhci5lbGVtZW50KS5hcHBlbmQoJ3NwYW4nKVxuICAgICAgICAgICAgLmNsYXNzZWQoJ2JhZGdlLXByaXZhdGUgZmxvYXQtLWxlZnQnLCB0cnVlKVxuICAgICAgICAgICAgLnRleHQoJ1BSSVZBVEUnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbW9kZUJhcjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVNb2RlQmFyO1xuXG59LHtcIi4uLy4uL2ZvbnRzL3Bsb3RpY29uXCI6Njk5LFwiLi4vLi4vbGliXCI6NzE5LFwiZDNcIjoxNjMsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDY1NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBmb250QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gX2RlcmVxXygnLi4vY29sb3IvYXR0cmlidXRlcycpO1xudmFyIHRlbXBsYXRlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG52YXIgYnV0dG9uQXR0cnMgPSB0ZW1wbGF0ZWRBcnJheSgnYnV0dG9uJywge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzdGVwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWydtb250aCcsICd5ZWFyJywgJ2RheScsICdob3VyJywgJ21pbnV0ZScsICdzZWNvbmQnLCAnYWxsJ10sXG4gICAgICAgIGRmbHQ6ICdtb250aCcsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RlcG1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ2JhY2t3YXJkJywgJ3RvZGF0ZSddLFxuICAgICAgICBkZmx0OiAnYmFja3dhcmQnLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNvdW50OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxhYmVsOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgIFxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGJ1dHRvbnM6IGJ1dHRvbkF0dHJzLFxuXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAtMixcbiAgICAgICAgbWF4OiAzLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4YW5jaG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgZGZsdDogJ2xlZnQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IC0yLFxuICAgICAgICBtYXg6IDMsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHlhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYXV0bycsICd0b3AnLCAnbWlkZGxlJywgJ2JvdHRvbSddLFxuICAgICAgICBkZmx0OiAnYm90dG9tJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBmb250OiBmb250QXR0cnMoe1xuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9KSxcblxuICAgIGJnY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5saWdodExpbmUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFjdGl2ZWNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcmNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJvcmRlcndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVkaXRUeXBlOiAncGxvdCdcbn07XG5cbn0se1wiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlc1wiOjc5MyxcIi4uL2NvbG9yL2F0dHJpYnV0ZXNcIjo1OTJ9XSw2NTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gICAgLy8gJ3knIHBvc2l0aW9uIHBhZCBhYm92ZSBjb3VudGVyIGF4aXMgZG9tYWluXG4gICAgeVBhZDogMC4wMixcblxuICAgIC8vIG1pbmltdW0gYnV0dG9uIHdpZHRoIChyZWdhcmRsZXNzIG9mIHRleHQgc2l6ZSlcbiAgICBtaW5CdXR0b25XaWR0aDogMzAsXG5cbiAgICAvLyBidXR0b25zIHJlY3QgcmFkaWlcbiAgICByeDogMyxcbiAgICByeTogMyxcblxuICAgIC8vIGxpZ2h0IGZyYWN0aW9uIHVzZWQgdG8gY29tcHV0ZSB0aGUgJ2FjdGl2ZWNvbG9yJyBkZWZhdWx0XG4gICAgbGlnaHRBbW91bnQ6IDI1LFxuICAgIGRhcmtBbW91bnQ6IDEwXG59O1xuXG59LHt9XSw2NTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb2xvcicpO1xudmFyIFRlbXBsYXRlID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgbGF5b3V0LCBjb3VudGVyQXhlcywgY2FsZW5kYXIpIHtcbiAgICB2YXIgc2VsZWN0b3JJbiA9IGNvbnRhaW5lckluLnJhbmdlc2VsZWN0b3IgfHwge307XG4gICAgdmFyIHNlbGVjdG9yT3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKGNvbnRhaW5lck91dCwgJ3Jhbmdlc2VsZWN0b3InKTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHNlbGVjdG9ySW4sIHNlbGVjdG9yT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgYnV0dG9ucyA9IGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMoc2VsZWN0b3JJbiwgc2VsZWN0b3JPdXQsIHtcbiAgICAgICAgbmFtZTogJ2J1dHRvbnMnLFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IGJ1dHRvbkRlZmF1bHRzLFxuICAgICAgICBjYWxlbmRhcjogY2FsZW5kYXJcbiAgICB9KTtcblxuICAgIHZhciB2aXNpYmxlID0gY29lcmNlKCd2aXNpYmxlJywgYnV0dG9ucy5sZW5ndGggPiAwKTtcbiAgICBpZih2aXNpYmxlKSB7XG4gICAgICAgIHZhciBwb3NEZmx0ID0gZ2V0UG9zRGZsdChjb250YWluZXJPdXQsIGxheW91dCwgY291bnRlckF4ZXMpO1xuICAgICAgICBjb2VyY2UoJ3gnLCBwb3NEZmx0WzBdKTtcbiAgICAgICAgY29lcmNlKCd5JywgcG9zRGZsdFsxXSk7XG4gICAgICAgIExpYi5ub25lT3JBbGwoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgWyd4JywgJ3knXSk7XG5cbiAgICAgICAgY29lcmNlKCd4YW5jaG9yJyk7XG4gICAgICAgIGNvZXJjZSgneWFuY2hvcicpO1xuXG4gICAgICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2ZvbnQnLCBsYXlvdXQuZm9udCk7XG5cbiAgICAgICAgdmFyIGJnQ29sb3IgPSBjb2VyY2UoJ2JnY29sb3InKTtcbiAgICAgICAgY29lcmNlKCdhY3RpdmVjb2xvcicsIENvbG9yLmNvbnRyYXN0KGJnQ29sb3IsIGNvbnN0YW50cy5saWdodEFtb3VudCwgY29uc3RhbnRzLmRhcmtBbW91bnQpKTtcbiAgICAgICAgY29lcmNlKCdib3JkZXJjb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ2JvcmRlcndpZHRoJyk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gYnV0dG9uRGVmYXVsdHMoYnV0dG9uSW4sIGJ1dHRvbk91dCwgc2VsZWN0b3JPdXQsIG9wdHMpIHtcbiAgICB2YXIgY2FsZW5kYXIgPSBvcHRzLmNhbGVuZGFyO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoYnV0dG9uSW4sIGJ1dHRvbk91dCwgYXR0cmlidXRlcy5idXR0b25zLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScpO1xuXG4gICAgaWYodmlzaWJsZSkge1xuICAgICAgICB2YXIgc3RlcCA9IGNvZXJjZSgnc3RlcCcpO1xuICAgICAgICBpZihzdGVwICE9PSAnYWxsJykge1xuICAgICAgICAgICAgaWYoY2FsZW5kYXIgJiYgY2FsZW5kYXIgIT09ICdncmVnb3JpYW4nICYmIChzdGVwID09PSAnbW9udGgnIHx8IHN0ZXAgPT09ICd5ZWFyJykpIHtcbiAgICAgICAgICAgICAgICBidXR0b25PdXQuc3RlcG1vZGUgPSAnYmFja3dhcmQnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb2VyY2UoJ3N0ZXBtb2RlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvZXJjZSgnY291bnQnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvZXJjZSgnbGFiZWwnKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldFBvc0RmbHQoY29udGFpbmVyT3V0LCBsYXlvdXQsIGNvdW50ZXJBeGVzKSB7XG4gICAgdmFyIGFuY2hvcmVkTGlzdCA9IGNvdW50ZXJBeGVzLmZpbHRlcihmdW5jdGlvbihheCkge1xuICAgICAgICByZXR1cm4gbGF5b3V0W2F4XS5hbmNob3IgPT09IGNvbnRhaW5lck91dC5faWQ7XG4gICAgfSk7XG5cbiAgICB2YXIgcG9zWSA9IDA7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFuY2hvcmVkTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZG9tYWluID0gbGF5b3V0W2FuY2hvcmVkTGlzdFtpXV0uZG9tYWluO1xuICAgICAgICBpZihkb21haW4pIHBvc1kgPSBNYXRoLm1heChkb21haW5bMV0sIHBvc1kpO1xuICAgIH1cblxuICAgIHJldHVybiBbY29udGFpbmVyT3V0LmRvbWFpblswXSwgcG9zWSArIGNvbnN0YW50cy55UGFkXTtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzXCI6NzYzLFwiLi4vY29sb3JcIjo1OTMsXCIuL2F0dHJpYnV0ZXNcIjo2NTUsXCIuL2NvbnN0YW50c1wiOjY1Nn1dLDY1ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgUGxvdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9wbG90cycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vY29sb3InKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vZHJhd2luZycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIGF4aXNJZHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHMnKTtcblxudmFyIGFsaWdubWVudENvbnN0YW50cyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKTtcbnZhciBMSU5FX1NQQUNJTkcgPSBhbGlnbm1lbnRDb25zdGFudHMuTElORV9TUEFDSU5HO1xudmFyIEZST01fVEwgPSBhbGlnbm1lbnRDb25zdGFudHMuRlJPTV9UTDtcbnZhciBGUk9NX0JSID0gYWxpZ25tZW50Q29uc3RhbnRzLkZST01fQlI7XG5cbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIGdldFVwZGF0ZU9iamVjdCA9IF9kZXJlcV8oJy4vZ2V0X3VwZGF0ZV9vYmplY3QnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkcmF3KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciBzZWxlY3RvcnMgPSBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuc2VsZWN0QWxsKCcucmFuZ2VzZWxlY3RvcicpXG4gICAgICAgIC5kYXRhKG1ha2VTZWxlY3RvckRhdGEoZ2QpLCBzZWxlY3RvcktleUZ1bmMpO1xuXG4gICAgc2VsZWN0b3JzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ3Jhbmdlc2VsZWN0b3InLCB0cnVlKTtcblxuICAgIHNlbGVjdG9ycy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBzZWxlY3RvcnMuc3R5bGUoe1xuICAgICAgICBjdXJzb3I6ICdwb2ludGVyJyxcbiAgICAgICAgJ3BvaW50ZXItZXZlbnRzJzogJ2FsbCdcbiAgICB9KTtcblxuICAgIHNlbGVjdG9ycy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHNlbGVjdG9yID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgYXhpc0xheW91dCA9IGQ7XG4gICAgICAgIHZhciBzZWxlY3RvckxheW91dCA9IGF4aXNMYXlvdXQucmFuZ2VzZWxlY3RvcjtcblxuICAgICAgICB2YXIgYnV0dG9ucyA9IHNlbGVjdG9yLnNlbGVjdEFsbCgnZy5idXR0b24nKVxuICAgICAgICAgICAgLmRhdGEoTGliLmZpbHRlclZpc2libGUoc2VsZWN0b3JMYXlvdXQuYnV0dG9ucykpO1xuXG4gICAgICAgIGJ1dHRvbnMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAgICAgLmNsYXNzZWQoJ2J1dHRvbicsIHRydWUpO1xuXG4gICAgICAgIGJ1dHRvbnMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIGJ1dHRvbnMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgYnV0dG9uID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIHVwZGF0ZSA9IGdldFVwZGF0ZU9iamVjdChheGlzTGF5b3V0LCBkKTtcblxuICAgICAgICAgICAgZC5faXNBY3RpdmUgPSBpc0FjdGl2ZShheGlzTGF5b3V0LCBkLCB1cGRhdGUpO1xuXG4gICAgICAgICAgICBidXR0b24uY2FsbChkcmF3QnV0dG9uUmVjdCwgc2VsZWN0b3JMYXlvdXQsIGQpO1xuICAgICAgICAgICAgYnV0dG9uLmNhbGwoZHJhd0J1dHRvblRleHQsIHNlbGVjdG9yTGF5b3V0LCBkLCBnZCk7XG5cbiAgICAgICAgICAgIGJ1dHRvbi5vbignY2xpY2snLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBpZihnZC5fZHJhZ2dlZCkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIHVwZGF0ZSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgYnV0dG9uLm9uKCdtb3VzZW92ZXInLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBkLl9pc0hvdmVyZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJ1dHRvbi5jYWxsKGRyYXdCdXR0b25SZWN0LCBzZWxlY3RvckxheW91dCwgZCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgYnV0dG9uLm9uKCdtb3VzZW91dCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGQuX2lzSG92ZXJlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGJ1dHRvbi5jYWxsKGRyYXdCdXR0b25SZWN0LCBzZWxlY3RvckxheW91dCwgZCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmVwb3NpdGlvbihnZCwgYnV0dG9ucywgc2VsZWN0b3JMYXlvdXQsIGF4aXNMYXlvdXQuX25hbWUsIHNlbGVjdG9yKTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VTZWxlY3RvckRhdGEoZ2QpIHtcbiAgICB2YXIgYXhlcyA9IGF4aXNJZHMubGlzdChnZCwgJ3gnLCB0cnVlKTtcbiAgICB2YXIgZGF0YSA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF4aXMgPSBheGVzW2ldO1xuXG4gICAgICAgIGlmKGF4aXMucmFuZ2VzZWxlY3RvciAmJiBheGlzLnJhbmdlc2VsZWN0b3IudmlzaWJsZSkge1xuICAgICAgICAgICAgZGF0YS5wdXNoKGF4aXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGRhdGE7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdG9yS2V5RnVuYyhkKSB7XG4gICAgcmV0dXJuIGQuX2lkO1xufVxuXG5mdW5jdGlvbiBpc0FjdGl2ZShheGlzTGF5b3V0LCBvcHRzLCB1cGRhdGUpIHtcbiAgICBpZihvcHRzLnN0ZXAgPT09ICdhbGwnKSB7XG4gICAgICAgIHJldHVybiBheGlzTGF5b3V0LmF1dG9yYW5nZSA9PT0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHVwZGF0ZSk7XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGF4aXNMYXlvdXQucmFuZ2VbMF0gPT09IHVwZGF0ZVtrZXlzWzBdXSAmJlxuICAgICAgICAgICAgYXhpc0xheW91dC5yYW5nZVsxXSA9PT0gdXBkYXRlW2tleXNbMV1dXG4gICAgICAgICk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmF3QnV0dG9uUmVjdChidXR0b24sIHNlbGVjdG9yTGF5b3V0LCBkKSB7XG4gICAgdmFyIHJlY3QgPSBMaWIuZW5zdXJlU2luZ2xlKGJ1dHRvbiwgJ3JlY3QnLCAnc2VsZWN0b3ItcmVjdCcsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5hdHRyKCdzaGFwZS1yZW5kZXJpbmcnLCAnY3Jpc3BFZGdlcycpO1xuICAgIH0pO1xuXG4gICAgcmVjdC5hdHRyKHtcbiAgICAgICAgJ3J4JzogY29uc3RhbnRzLnJ4LFxuICAgICAgICAncnknOiBjb25zdGFudHMucnlcbiAgICB9KTtcblxuICAgIHJlY3QuY2FsbChDb2xvci5zdHJva2UsIHNlbGVjdG9yTGF5b3V0LmJvcmRlcmNvbG9yKVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBnZXRGaWxsQ29sb3Ioc2VsZWN0b3JMYXlvdXQsIGQpKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIHNlbGVjdG9yTGF5b3V0LmJvcmRlcndpZHRoICsgJ3B4Jyk7XG59XG5cbmZ1bmN0aW9uIGdldEZpbGxDb2xvcihzZWxlY3RvckxheW91dCwgZCkge1xuICAgIHJldHVybiAoZC5faXNBY3RpdmUgfHwgZC5faXNIb3ZlcmVkKSA/XG4gICAgICAgIHNlbGVjdG9yTGF5b3V0LmFjdGl2ZWNvbG9yIDpcbiAgICAgICAgc2VsZWN0b3JMYXlvdXQuYmdjb2xvcjtcbn1cblxuZnVuY3Rpb24gZHJhd0J1dHRvblRleHQoYnV0dG9uLCBzZWxlY3RvckxheW91dCwgZCwgZ2QpIHtcbiAgICBmdW5jdGlvbiB0ZXh0TGF5b3V0KHMpIHtcbiAgICAgICAgc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucyhzLCBnZCk7XG4gICAgfVxuXG4gICAgdmFyIHRleHQgPSBMaWIuZW5zdXJlU2luZ2xlKGJ1dHRvbiwgJ3RleHQnLCAnc2VsZWN0b3ItdGV4dCcsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5jbGFzc2VkKCd1c2VyLXNlbGVjdC1ub25lJywgdHJ1ZSlcbiAgICAgICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKTtcbiAgICB9KTtcblxuICAgIHRleHQuY2FsbChEcmF3aW5nLmZvbnQsIHNlbGVjdG9yTGF5b3V0LmZvbnQpXG4gICAgICAgIC50ZXh0KGdldExhYmVsKGQsIGdkLl9mdWxsTGF5b3V0Ll9tZXRhKSlcbiAgICAgICAgLmNhbGwodGV4dExheW91dCk7XG59XG5cbmZ1bmN0aW9uIGdldExhYmVsKG9wdHMsIF9tZXRhKSB7XG4gICAgaWYob3B0cy5sYWJlbCkge1xuICAgICAgICByZXR1cm4gX21ldGEgP1xuICAgICAgICAgICAgTGliLnRlbXBsYXRlU3RyaW5nKG9wdHMubGFiZWwsIF9tZXRhKSA6XG4gICAgICAgICAgICBvcHRzLmxhYmVsO1xuICAgIH1cblxuICAgIGlmKG9wdHMuc3RlcCA9PT0gJ2FsbCcpIHJldHVybiAnYWxsJztcblxuICAgIHJldHVybiBvcHRzLmNvdW50ICsgb3B0cy5zdGVwLmNoYXJBdCgwKTtcbn1cblxuZnVuY3Rpb24gcmVwb3NpdGlvbihnZCwgYnV0dG9ucywgb3B0cywgYXhOYW1lLCBzZWxlY3Rvcikge1xuICAgIHZhciB3aWR0aCA9IDA7XG4gICAgdmFyIGhlaWdodCA9IDA7XG5cbiAgICB2YXIgYm9yZGVyV2lkdGggPSBvcHRzLmJvcmRlcndpZHRoO1xuXG4gICAgYnV0dG9ucy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYnV0dG9uID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdGV4dCA9IGJ1dHRvbi5zZWxlY3QoJy5zZWxlY3Rvci10ZXh0Jyk7XG5cbiAgICAgICAgdmFyIHRIZWlnaHQgPSBvcHRzLmZvbnQuc2l6ZSAqIExJTkVfU1BBQ0lORztcbiAgICAgICAgdmFyIGhFZmYgPSBNYXRoLm1heCh0SGVpZ2h0ICogc3ZnVGV4dFV0aWxzLmxpbmVDb3VudCh0ZXh0KSwgMTYpICsgMztcblxuICAgICAgICBoZWlnaHQgPSBNYXRoLm1heChoZWlnaHQsIGhFZmYpO1xuICAgIH0pO1xuXG4gICAgYnV0dG9ucy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYnV0dG9uID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgcmVjdCA9IGJ1dHRvbi5zZWxlY3QoJy5zZWxlY3Rvci1yZWN0Jyk7XG4gICAgICAgIHZhciB0ZXh0ID0gYnV0dG9uLnNlbGVjdCgnLnNlbGVjdG9yLXRleHQnKTtcblxuICAgICAgICB2YXIgdFdpZHRoID0gdGV4dC5ub2RlKCkgJiYgRHJhd2luZy5iQm94KHRleHQubm9kZSgpKS53aWR0aDtcbiAgICAgICAgdmFyIHRIZWlnaHQgPSBvcHRzLmZvbnQuc2l6ZSAqIExJTkVfU1BBQ0lORztcbiAgICAgICAgdmFyIHRMaW5lcyA9IHN2Z1RleHRVdGlscy5saW5lQ291bnQodGV4dCk7XG5cbiAgICAgICAgdmFyIHdFZmYgPSBNYXRoLm1heCh0V2lkdGggKyAxMCwgY29uc3RhbnRzLm1pbkJ1dHRvbldpZHRoKTtcblxuICAgICAgICAvLyBUT0RPIGFkZCBNYXRoSmF4IHN1cHBvcnRcblxuICAgICAgICAvLyBUT0RPIGFkZCBidXR0b25nYXAgYXR0cmlidXRlXG5cbiAgICAgICAgYnV0dG9uLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArXG4gICAgICAgICAgICAoYm9yZGVyV2lkdGggKyB3aWR0aCkgKyAnLCcgKyBib3JkZXJXaWR0aCArXG4gICAgICAgICcpJyk7XG5cbiAgICAgICAgcmVjdC5hdHRyKHtcbiAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgd2lkdGg6IHdFZmYsXG4gICAgICAgICAgICBoZWlnaHQ6IGhlaWdodFxuICAgICAgICB9KTtcblxuICAgICAgICBzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0KHRleHQsIHdFZmYgLyAyLFxuICAgICAgICAgICAgaGVpZ2h0IC8gMiAtICgodExpbmVzIC0gMSkgKiB0SGVpZ2h0IC8gMikgKyAzKTtcblxuICAgICAgICB3aWR0aCArPSB3RWZmICsgNTtcbiAgICB9KTtcblxuICAgIHZhciBncmFwaFNpemUgPSBnZC5fZnVsbExheW91dC5fc2l6ZTtcbiAgICB2YXIgbHggPSBncmFwaFNpemUubCArIGdyYXBoU2l6ZS53ICogb3B0cy54O1xuICAgIHZhciBseSA9IGdyYXBoU2l6ZS50ICsgZ3JhcGhTaXplLmggKiAoMSAtIG9wdHMueSk7XG5cbiAgICB2YXIgeGFuY2hvciA9ICdsZWZ0JztcbiAgICBpZihMaWIuaXNSaWdodEFuY2hvcihvcHRzKSkge1xuICAgICAgICBseCAtPSB3aWR0aDtcbiAgICAgICAgeGFuY2hvciA9ICdyaWdodCc7XG4gICAgfVxuICAgIGlmKExpYi5pc0NlbnRlckFuY2hvcihvcHRzKSkge1xuICAgICAgICBseCAtPSB3aWR0aCAvIDI7XG4gICAgICAgIHhhbmNob3IgPSAnY2VudGVyJztcbiAgICB9XG5cbiAgICB2YXIgeWFuY2hvciA9ICd0b3AnO1xuICAgIGlmKExpYi5pc0JvdHRvbUFuY2hvcihvcHRzKSkge1xuICAgICAgICBseSAtPSBoZWlnaHQ7XG4gICAgICAgIHlhbmNob3IgPSAnYm90dG9tJztcbiAgICB9XG4gICAgaWYoTGliLmlzTWlkZGxlQW5jaG9yKG9wdHMpKSB7XG4gICAgICAgIGx5IC09IGhlaWdodCAvIDI7XG4gICAgICAgIHlhbmNob3IgPSAnbWlkZGxlJztcbiAgICB9XG5cbiAgICB3aWR0aCA9IE1hdGguY2VpbCh3aWR0aCk7XG4gICAgaGVpZ2h0ID0gTWF0aC5jZWlsKGhlaWdodCk7XG4gICAgbHggPSBNYXRoLnJvdW5kKGx4KTtcbiAgICBseSA9IE1hdGgucm91bmQobHkpO1xuXG4gICAgUGxvdHMuYXV0b01hcmdpbihnZCwgYXhOYW1lICsgJy1yYW5nZS1zZWxlY3RvcicsIHtcbiAgICAgICAgeDogb3B0cy54LFxuICAgICAgICB5OiBvcHRzLnksXG4gICAgICAgIGw6IHdpZHRoICogRlJPTV9UTFt4YW5jaG9yXSxcbiAgICAgICAgcjogd2lkdGggKiBGUk9NX0JSW3hhbmNob3JdLFxuICAgICAgICBiOiBoZWlnaHQgKiBGUk9NX0JSW3lhbmNob3JdLFxuICAgICAgICB0OiBoZWlnaHQgKiBGUk9NX1RMW3lhbmNob3JdXG4gICAgfSk7XG5cbiAgICBzZWxlY3Rvci5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBseCArICcsJyArIGx5ICsgJyknKTtcbn1cblxufSx7XCIuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50XCI6Njg4LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzXCI6NzQzLFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzXCI6NzcwLFwiLi4vLi4vcGxvdHMvcGxvdHNcIjo4MjgsXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4uL2NvbG9yXCI6NTkzLFwiLi4vZHJhd2luZ1wiOjYxNCxcIi4vY29uc3RhbnRzXCI6NjU2LFwiLi9nZXRfdXBkYXRlX29iamVjdFwiOjY1OSxcImQzXCI6MTYzfV0sNjU5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdldFVwZGF0ZU9iamVjdChheGlzTGF5b3V0LCBidXR0b25MYXlvdXQpIHtcbiAgICB2YXIgYXhOYW1lID0gYXhpc0xheW91dC5fbmFtZTtcbiAgICB2YXIgdXBkYXRlID0ge307XG5cbiAgICBpZihidXR0b25MYXlvdXQuc3RlcCA9PT0gJ2FsbCcpIHtcbiAgICAgICAgdXBkYXRlW2F4TmFtZSArICcuYXV0b3JhbmdlJ10gPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB4cmFuZ2UgPSBnZXRYUmFuZ2UoYXhpc0xheW91dCwgYnV0dG9uTGF5b3V0KTtcblxuICAgICAgICB1cGRhdGVbYXhOYW1lICsgJy5yYW5nZVswXSddID0geHJhbmdlWzBdO1xuICAgICAgICB1cGRhdGVbYXhOYW1lICsgJy5yYW5nZVsxXSddID0geHJhbmdlWzFdO1xuICAgIH1cblxuICAgIHJldHVybiB1cGRhdGU7XG59O1xuXG5mdW5jdGlvbiBnZXRYUmFuZ2UoYXhpc0xheW91dCwgYnV0dG9uTGF5b3V0KSB7XG4gICAgdmFyIGN1cnJlbnRSYW5nZSA9IGF4aXNMYXlvdXQucmFuZ2U7XG4gICAgdmFyIGJhc2UgPSBuZXcgRGF0ZShheGlzTGF5b3V0LnIybChjdXJyZW50UmFuZ2VbMV0pKTtcbiAgICB2YXIgc3RlcCA9IGJ1dHRvbkxheW91dC5zdGVwO1xuICAgIHZhciBjb3VudCA9IGJ1dHRvbkxheW91dC5jb3VudDtcbiAgICB2YXIgcmFuZ2UwO1xuXG4gICAgc3dpdGNoKGJ1dHRvbkxheW91dC5zdGVwbW9kZSkge1xuICAgICAgICBjYXNlICdiYWNrd2FyZCc6XG4gICAgICAgICAgICByYW5nZTAgPSBheGlzTGF5b3V0LmwycigrZDMudGltZVtzdGVwXS51dGMub2Zmc2V0KGJhc2UsIC1jb3VudCkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAndG9kYXRlJzpcbiAgICAgICAgICAgIHZhciBiYXNlMiA9IGQzLnRpbWVbc3RlcF0udXRjLm9mZnNldChiYXNlLCAtY291bnQpO1xuXG4gICAgICAgICAgICByYW5nZTAgPSBheGlzTGF5b3V0LmwycigrZDMudGltZVtzdGVwXS51dGMuY2VpbChiYXNlMikpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgdmFyIHJhbmdlMSA9IGN1cnJlbnRSYW5nZVsxXTtcblxuICAgIHJldHVybiBbcmFuZ2UwLCByYW5nZTFdO1xufVxuXG59LHtcImQzXCI6MTYzfV0sNjYwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogJ3Jhbmdlc2VsZWN0b3InLFxuXG4gICAgc2NoZW1hOiB7XG4gICAgICAgIHN1YnBsb3RzOiB7XG4gICAgICAgICAgICB4YXhpczoge3Jhbmdlc2VsZWN0b3I6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGxheW91dEF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIGhhbmRsZURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG5cbiAgICBkcmF3OiBfZGVyZXFfKCcuL2RyYXcnKVxufTtcblxufSx7XCIuL2F0dHJpYnV0ZXNcIjo2NTUsXCIuL2RlZmF1bHRzXCI6NjU3LFwiLi9kcmF3XCI6NjU4fV0sNjYxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yQXR0cmlidXRlcyA9IF9kZXJlcV8oJy4uL2NvbG9yL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYmdjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJpYnV0ZXMuYmFja2dyb3VuZCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm9yZGVyY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRyaWJ1dGVzLmRlZmF1bHRMaW5lLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3JkZXJ3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXV0b3JhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGltcGxpZWRFZGl0czogeydyYW5nZVswXSc6IHVuZGVmaW5lZCwgJ3JhbmdlWzFdJzogdW5kZWZpbmVkfSxcbiAgICAgICAgXG4gICAgfSxcbiAgICByYW5nZToge1xuICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgIFxuICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ2NhbGMnLCBpbXBsaWVkRWRpdHM6IHsnXmF1dG9yYW5nZSc6IGZhbHNlfX0sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAnY2FsYycsIGltcGxpZWRFZGl0czogeydeYXV0b3JhbmdlJzogZmFsc2V9fVxuICAgICAgICBdLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBpbXBsaWVkRWRpdHM6IHsnYXV0b3JhbmdlJzogZmFsc2V9LFxuICAgICAgICBcbiAgICB9LFxuICAgIHRoaWNrbmVzczoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMC4xNSxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuXG59LHtcIi4uL2NvbG9yL2F0dHJpYnV0ZXNcIjo1OTJ9XSw2NjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbGlzdEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHMnKS5saXN0O1xudmFyIGdldEF1dG9SYW5nZSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9hdXRvcmFuZ2UnKS5nZXRBdXRvUmFuZ2U7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjQXV0b3JhbmdlKGdkKSB7XG4gICAgdmFyIGF4ZXMgPSBsaXN0QXhlcyhnZCwgJ3gnLCB0cnVlKTtcblxuICAgIC8vIENvbXB1dGUgbmV3IHNsaWRlciByYW5nZSB1c2luZyBheGlzIGF1dG9yYW5nZSBpZiBuZWNlc3NhcnkuXG4gICAgLy9cbiAgICAvLyBDb3B5IGJhY2sgcmFuZ2UgdG8gaW5wdXQgcmFuZ2Ugc2xpZGVyIGNvbnRhaW5lciB0byBza2lwXG4gICAgLy8gdGhpcyBzdGVwIGluIHN1YnNlcXVlbnQgZHJhdyBjYWxscy5cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBheCA9IGF4ZXNbaV07XG4gICAgICAgIHZhciBvcHRzID0gYXhbY29uc3RhbnRzLm5hbWVdO1xuXG4gICAgICAgIGlmKG9wdHMgJiYgb3B0cy52aXNpYmxlICYmIG9wdHMuYXV0b3JhbmdlKSB7XG4gICAgICAgICAgICBvcHRzLl9pbnB1dC5hdXRvcmFuZ2UgPSB0cnVlO1xuICAgICAgICAgICAgb3B0cy5faW5wdXQucmFuZ2UgPSBvcHRzLnJhbmdlID0gZ2V0QXV0b1JhbmdlKGdkLCBheCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9hdXRvcmFuZ2VcIjo3NjYsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHNcIjo3NzAsXCIuL2NvbnN0YW50c1wiOjY2M31dLDY2MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gICAgLy8gYXR0cmlidXRlIGNvbnRhaW5lciBuYW1lXG4gICAgbmFtZTogJ3Jhbmdlc2xpZGVyJyxcblxuICAgIC8vIGNsYXNzIG5hbWVzXG5cbiAgICBjb250YWluZXJDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1jb250YWluZXInLFxuICAgIGJnQ2xhc3NOYW1lOiAncmFuZ2VzbGlkZXItYmcnLFxuICAgIHJhbmdlUGxvdENsYXNzTmFtZTogJ3Jhbmdlc2xpZGVyLXJhbmdlcGxvdCcsXG5cbiAgICBtYXNrTWluQ2xhc3NOYW1lOiAncmFuZ2VzbGlkZXItbWFzay1taW4nLFxuICAgIG1hc2tNYXhDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1tYXNrLW1heCcsXG4gICAgc2xpZGVCb3hDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1zbGlkZWJveCcsXG5cbiAgICBncmFiYmVyTWluQ2xhc3NOYW1lOiAncmFuZ2VzbGlkZXItZ3JhYmJlci1taW4nLFxuICAgIGdyYWJBcmVhTWluQ2xhc3NOYW1lOiAncmFuZ2VzbGlkZXItZ3JhYmFyZWEtbWluJyxcbiAgICBoYW5kbGVNaW5DbGFzc05hbWU6ICdyYW5nZXNsaWRlci1oYW5kbGUtbWluJyxcblxuICAgIGdyYWJiZXJNYXhDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1ncmFiYmVyLW1heCcsXG4gICAgZ3JhYkFyZWFNYXhDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1ncmFiYXJlYS1tYXgnLFxuICAgIGhhbmRsZU1heENsYXNzTmFtZTogJ3Jhbmdlc2xpZGVyLWhhbmRsZS1tYXgnLFxuXG4gICAgbWFza01pbk9wcEF4aXNDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1tYXNrLW1pbi1vcHAtYXhpcycsXG4gICAgbWFza01heE9wcEF4aXNDbGFzc05hbWU6ICdyYW5nZXNsaWRlci1tYXNrLW1heC1vcHAtYXhpcycsXG5cbiAgICAvLyBzdHlsZSBjb25zdGFudHNcblxuICAgIG1hc2tDb2xvcjogJ3JnYmEoMCwwLDAsMC40KScsXG4gICAgbWFza09wcEF4aXNDb2xvcjogJ3JnYmEoMCwwLDAsMC4yKScsXG5cbiAgICBzbGlkZUJveEZpbGw6ICd0cmFuc3BhcmVudCcsXG4gICAgc2xpZGVCb3hDdXJzb3I6ICdldy1yZXNpemUnLFxuXG4gICAgZ3JhYkFyZWFGaWxsOiAndHJhbnNwYXJlbnQnLFxuICAgIGdyYWJBcmVhQ3Vyc29yOiAnY29sLXJlc2l6ZScsXG4gICAgZ3JhYkFyZWFXaWR0aDogMTAsXG5cbiAgICBoYW5kbGVXaWR0aDogNCxcbiAgICBoYW5kbGVSYWRpdXM6IDEsXG4gICAgaGFuZGxlU3Ryb2tlV2lkdGg6IDEsXG5cbiAgICBleHRyYVBhZDogMTVcbn07XG5cbn0se31dLDY2NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBUZW1wbGF0ZSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcbnZhciBheGlzSWRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG52YXIgb3BwQXhpc0F0dHJzID0gX2RlcmVxXygnLi9vcHBheGlzX2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVEZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBheE5hbWUpIHtcbiAgICB2YXIgYXhJbiA9IGxheW91dEluW2F4TmFtZV07XG4gICAgdmFyIGF4T3V0ID0gbGF5b3V0T3V0W2F4TmFtZV07XG5cbiAgICBpZighKGF4SW4ucmFuZ2VzbGlkZXIgfHwgbGF5b3V0T3V0Ll9yZXF1ZXN0UmFuZ2VzbGlkZXJbYXhPdXQuX2lkXSkpIHJldHVybjtcblxuICAgIC8vIG5vdCBzdXBlciBwcm91ZCBvZiB0aGlzIChtYXliZSBzdG9yZSBfIGluIGF4aXMgb2JqZWN0IGluc3RlYWRcbiAgICBpZighTGliLmlzUGxhaW5PYmplY3QoYXhJbi5yYW5nZXNsaWRlcikpIHtcbiAgICAgICAgYXhJbi5yYW5nZXNsaWRlciA9IHt9O1xuICAgIH1cblxuICAgIHZhciBjb250YWluZXJJbiA9IGF4SW4ucmFuZ2VzbGlkZXI7XG4gICAgdmFyIGNvbnRhaW5lck91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcihheE91dCwgJ3Jhbmdlc2xpZGVyJyk7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgcmFuZ2VDb250YWluZXJJbiwgcmFuZ2VDb250YWluZXJPdXQ7XG4gICAgZnVuY3Rpb24gY29lcmNlUmFuZ2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShyYW5nZUNvbnRhaW5lckluLCByYW5nZUNvbnRhaW5lck91dCwgb3BwQXhpc0F0dHJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScpO1xuICAgIGlmKCF2aXNpYmxlKSByZXR1cm47XG5cbiAgICBjb2VyY2UoJ2JnY29sb3InLCBsYXlvdXRPdXQucGxvdF9iZ2NvbG9yKTtcbiAgICBjb2VyY2UoJ2JvcmRlcmNvbG9yJyk7XG4gICAgY29lcmNlKCdib3JkZXJ3aWR0aCcpO1xuICAgIGNvZXJjZSgndGhpY2tuZXNzJyk7XG5cbiAgICBjb2VyY2UoJ2F1dG9yYW5nZScsICFheE91dC5pc1ZhbGlkUmFuZ2UoY29udGFpbmVySW4ucmFuZ2UpKTtcbiAgICBjb2VyY2UoJ3JhbmdlJyk7XG5cbiAgICB2YXIgc3VicGxvdHMgPSBsYXlvdXRPdXQuX3N1YnBsb3RzO1xuICAgIGlmKHN1YnBsb3RzKSB7XG4gICAgICAgIHZhciB5SWRzID0gc3VicGxvdHMuY2FydGVzaWFuXG4gICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uKHN1YnBsb3RJZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdWJwbG90SWQuc3Vic3RyKDAsIHN1YnBsb3RJZC5pbmRleE9mKCd5JykpID09PSBheGlzSWRzLm5hbWUyaWQoYXhOYW1lKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAubWFwKGZ1bmN0aW9uKHN1YnBsb3RJZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdWJwbG90SWQuc3Vic3RyKHN1YnBsb3RJZC5pbmRleE9mKCd5JyksIHN1YnBsb3RJZC5sZW5ndGgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIHZhciB5TmFtZXMgPSBMaWIuc2ltcGxlTWFwKHlJZHMsIGF4aXNJZHMuaWQybmFtZSk7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB5TmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB5TmFtZSA9IHlOYW1lc1tpXTtcblxuICAgICAgICAgICAgcmFuZ2VDb250YWluZXJJbiA9IGNvbnRhaW5lckluW3lOYW1lXSB8fCB7fTtcbiAgICAgICAgICAgIHJhbmdlQ29udGFpbmVyT3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKGNvbnRhaW5lck91dCwgeU5hbWUsICd5YXhpcycpO1xuXG4gICAgICAgICAgICB2YXIgeUF4T3V0ID0gbGF5b3V0T3V0W3lOYW1lXTtcblxuICAgICAgICAgICAgdmFyIHJhbmdlbW9kZURmbHQ7XG4gICAgICAgICAgICBpZihyYW5nZUNvbnRhaW5lckluLnJhbmdlICYmIHlBeE91dC5pc1ZhbGlkUmFuZ2UocmFuZ2VDb250YWluZXJJbi5yYW5nZSkpIHtcbiAgICAgICAgICAgICAgICByYW5nZW1vZGVEZmx0ID0gJ2ZpeGVkJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHJhbmdlTW9kZSA9IGNvZXJjZVJhbmdlKCdyYW5nZW1vZGUnLCByYW5nZW1vZGVEZmx0KTtcbiAgICAgICAgICAgIGlmKHJhbmdlTW9kZSAhPT0gJ21hdGNoJykge1xuICAgICAgICAgICAgICAgIGNvZXJjZVJhbmdlKCdyYW5nZScsIHlBeE91dC5yYW5nZS5zbGljZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRvIG1hcCBiYWNrIHJhbmdlIHNsaWRlciAoYXV0bykgcmFuZ2VcbiAgICBjb250YWluZXJPdXQuX2lucHV0ID0gY29udGFpbmVySW47XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHNcIjo3NzAsXCIuL2F0dHJpYnV0ZXNcIjo2NjEsXCIuL29wcGF4aXNfYXR0cmlidXRlc1wiOjY2OH1dLDY2NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgUGxvdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9wbG90cycpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uL2RyYXdpbmcnKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uL2NvbG9yJyk7XG52YXIgVGl0bGVzID0gX2RlcmVxXygnLi4vdGl0bGVzJyk7XG5cbnZhciBDYXJ0ZXNpYW4gPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKTtcbnZhciBheGlzSURzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG5cbnZhciBkcmFnRWxlbWVudCA9IF9kZXJlcV8oJy4uL2RyYWdlbGVtZW50Jyk7XG52YXIgc2V0Q3Vyc29yID0gX2RlcmVxXygnLi4vLi4vbGliL3NldGN1cnNvcicpO1xuXG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHJhbmdlU2xpZGVyRGF0YSA9IGZ1bGxMYXlvdXQuX3JhbmdlU2xpZGVyRGF0YTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcmFuZ2VTbGlkZXJEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvcHRzID0gcmFuZ2VTbGlkZXJEYXRhW2ldW2NvbnN0YW50cy5uYW1lXTtcbiAgICAgICAgLy8gZnVsbExheW91dC5fdWlkIG1heSBub3QgZXhpc3Qgd2hlbiB3ZSBjYWxsIG1ha2VEYXRhXG4gICAgICAgIG9wdHMuX2NsaXBJZCA9IG9wdHMuX2lkICsgJy0nICsgZnVsbExheW91dC5fdWlkO1xuICAgIH1cblxuICAgIC8qXG4gICAgICogPGcgY29udGFpbmVyIC8+XG4gICAgICogIDxyZWN0IGJnIC8+XG4gICAgICogIDwgLi4uLiByYW5nZSBwbG90IC8+XG4gICAgICogIDxyZWN0IG1hc2stbWluIC8+XG4gICAgICogIDxyZWN0IG1hc2stbWF4IC8+XG4gICAgICogIDxyZWN0IHNsaWRlYm94IC8+XG4gICAgICogIDxnIGdyYWJiZXItbWluIC8+XG4gICAgICogICAgICA8cmVjdCBoYW5kbGUtbWluIC8+XG4gICAgICogICAgICA8cmVjdCBncmFiYXJlLW1pbiAvPlxuICAgICAqICA8ZyBncmFiYmVyLW1heCAvPlxuICAgICAqICAgICAgPHJlY3QgaGFuZGxlLW1heCAvPlxuICAgICAqICAgICAgPHJlY3QgZ3JhYmFyZS1tYXggLz5cbiAgICAgKlxuICAgICAqICAuLi5cbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIGtleUZ1bmN0aW9uKGF4aXNPcHRzKSB7XG4gICAgICAgIHJldHVybiBheGlzT3B0cy5fbmFtZTtcbiAgICB9XG5cbiAgICB2YXIgcmFuZ2VTbGlkZXJzID0gZnVsbExheW91dC5faW5mb2xheWVyXG4gICAgICAgIC5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5jb250YWluZXJDbGFzc05hbWUpXG4gICAgICAgIC5kYXRhKHJhbmdlU2xpZGVyRGF0YSwga2V5RnVuY3Rpb24pO1xuXG4gICAgLy8gcmVtb3ZlIGV4aXRpbmcgc2xpZGVycyBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBjbGlwIHBhdGhzXG4gICAgcmFuZ2VTbGlkZXJzLmV4aXQoKS5lYWNoKGZ1bmN0aW9uKGF4aXNPcHRzKSB7XG4gICAgICAgIHZhciBvcHRzID0gYXhpc09wdHNbY29uc3RhbnRzLm5hbWVdO1xuICAgICAgICBmdWxsTGF5b3V0Ll90b3BkZWZzLnNlbGVjdCgnIycgKyBvcHRzLl9jbGlwSWQpLnJlbW92ZSgpO1xuICAgIH0pLnJlbW92ZSgpO1xuXG4gICAgLy8gcmV0dXJuIGVhcmx5IGlmIG5vIHJhbmdlIHNsaWRlciBpcyB2aXNpYmxlXG4gICAgaWYocmFuZ2VTbGlkZXJEYXRhLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG4gICAgcmFuZ2VTbGlkZXJzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY29uc3RhbnRzLmNvbnRhaW5lckNsYXNzTmFtZSwgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpO1xuXG4gICAgLy8gZm9yIGFsbCBwcmVzZW50IHJhbmdlIHNsaWRlcnNcbiAgICByYW5nZVNsaWRlcnMuZWFjaChmdW5jdGlvbihheGlzT3B0cykge1xuICAgICAgICB2YXIgcmFuZ2VTbGlkZXIgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBvcHRzID0gYXhpc09wdHNbY29uc3RhbnRzLm5hbWVdO1xuICAgICAgICB2YXIgb3BwQXhpc09wdHMgPSBmdWxsTGF5b3V0W2F4aXNJRHMuaWQybmFtZShheGlzT3B0cy5hbmNob3IpXTtcbiAgICAgICAgdmFyIG9wcEF4aXNSYW5nZU9wdHMgPSBvcHRzW2F4aXNJRHMuaWQybmFtZShheGlzT3B0cy5hbmNob3IpXTtcblxuICAgICAgICAvLyB1cGRhdGUgcmFuZ2VcbiAgICAgICAgLy8gRXhwYW5kIHNsaWRlciByYW5nZSB0byB0aGUgYXhpcyByYW5nZVxuICAgICAgICBpZihvcHRzLnJhbmdlKSB7XG4gICAgICAgICAgICB2YXIgcm5nID0gTGliLnNpbXBsZU1hcChvcHRzLnJhbmdlLCBheGlzT3B0cy5yMmwpO1xuICAgICAgICAgICAgdmFyIGF4Um5nID0gTGliLnNpbXBsZU1hcChheGlzT3B0cy5yYW5nZSwgYXhpc09wdHMucjJsKTtcbiAgICAgICAgICAgIHZhciBuZXdSbmc7XG5cbiAgICAgICAgICAgIGlmKGF4Um5nWzBdIDwgYXhSbmdbMV0pIHtcbiAgICAgICAgICAgICAgICBuZXdSbmcgPSBbXG4gICAgICAgICAgICAgICAgICAgIE1hdGgubWluKHJuZ1swXSwgYXhSbmdbMF0pLFxuICAgICAgICAgICAgICAgICAgICBNYXRoLm1heChybmdbMV0sIGF4Um5nWzFdKVxuICAgICAgICAgICAgICAgIF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG5ld1JuZyA9IFtcbiAgICAgICAgICAgICAgICAgICAgTWF0aC5tYXgocm5nWzBdLCBheFJuZ1swXSksXG4gICAgICAgICAgICAgICAgICAgIE1hdGgubWluKHJuZ1sxXSwgYXhSbmdbMV0pXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgb3B0cy5yYW5nZSA9IG9wdHMuX2lucHV0LnJhbmdlID0gTGliLnNpbXBsZU1hcChuZXdSbmcsIGF4aXNPcHRzLmwycik7XG4gICAgICAgIH1cblxuICAgICAgICBheGlzT3B0cy5jbGVhblJhbmdlKCdyYW5nZXNsaWRlci5yYW5nZScpO1xuXG4gICAgICAgIC8vIHVwZGF0ZSByYW5nZSBzbGlkZXIgZGltZW5zaW9uc1xuXG4gICAgICAgIHZhciBtYXJnaW4gPSBmdWxsTGF5b3V0Lm1hcmdpbjtcbiAgICAgICAgdmFyIGdyYXBoU2l6ZSA9IGZ1bGxMYXlvdXQuX3NpemU7XG4gICAgICAgIHZhciBkb21haW4gPSBheGlzT3B0cy5kb21haW47XG4gICAgICAgIHZhciB0aWNrSGVpZ2h0ID0gb3B0cy5fdGlja0hlaWdodDtcblxuICAgICAgICB2YXIgb3BwQm90dG9tID0gb3B0cy5fb3BwQm90dG9tO1xuXG4gICAgICAgIG9wdHMuX3dpZHRoID0gZ3JhcGhTaXplLncgKiAoZG9tYWluWzFdIC0gZG9tYWluWzBdKTtcblxuICAgICAgICB2YXIgeCA9IE1hdGgucm91bmQobWFyZ2luLmwgKyAoZ3JhcGhTaXplLncgKiBkb21haW5bMF0pKTtcblxuICAgICAgICB2YXIgeSA9IE1hdGgucm91bmQoXG4gICAgICAgICAgICBncmFwaFNpemUudCArIGdyYXBoU2l6ZS5oICogKDEgLSBvcHBCb3R0b20pICtcbiAgICAgICAgICAgIHRpY2tIZWlnaHQgK1xuICAgICAgICAgICAgb3B0cy5fb2Zmc2V0U2hpZnQgKyBjb25zdGFudHMuZXh0cmFQYWRcbiAgICAgICAgKTtcblxuICAgICAgICByYW5nZVNsaWRlci5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyB4ICsgJywnICsgeSArICcpJyk7XG5cbiAgICAgICAgLy8gdXBkYXRlIGRhdGEgPC0tPiBwaXhlbCBjb29yZGluYXRlIGNvbnZlcnNpb24gbWV0aG9kc1xuXG4gICAgICAgIHZhciByYW5nZTAgPSBheGlzT3B0cy5yMmwob3B0cy5yYW5nZVswXSk7XG4gICAgICAgIHZhciByYW5nZTEgPSBheGlzT3B0cy5yMmwob3B0cy5yYW5nZVsxXSk7XG4gICAgICAgIHZhciBkaXN0ID0gcmFuZ2UxIC0gcmFuZ2UwO1xuXG4gICAgICAgIG9wdHMucDJkID0gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgcmV0dXJuICh2IC8gb3B0cy5fd2lkdGgpICogZGlzdCArIHJhbmdlMDtcbiAgICAgICAgfTtcblxuICAgICAgICBvcHRzLmQycCA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHJldHVybiAodiAtIHJhbmdlMCkgLyBkaXN0ICogb3B0cy5fd2lkdGg7XG4gICAgICAgIH07XG5cbiAgICAgICAgb3B0cy5fcmwgPSBbcmFuZ2UwLCByYW5nZTFdO1xuXG4gICAgICAgIGlmKG9wcEF4aXNSYW5nZU9wdHMucmFuZ2Vtb2RlICE9PSAnbWF0Y2gnKSB7XG4gICAgICAgICAgICB2YXIgcmFuZ2UwT3BwQXhpcyA9IG9wcEF4aXNPcHRzLnIybChvcHBBeGlzUmFuZ2VPcHRzLnJhbmdlWzBdKTtcbiAgICAgICAgICAgIHZhciByYW5nZTFPcHBBeGlzID0gb3BwQXhpc09wdHMucjJsKG9wcEF4aXNSYW5nZU9wdHMucmFuZ2VbMV0pO1xuICAgICAgICAgICAgdmFyIGRpc3RPcHBBeGlzID0gcmFuZ2UxT3BwQXhpcyAtIHJhbmdlME9wcEF4aXM7XG5cbiAgICAgICAgICAgIG9wdHMuZDJwT3BwQXhpcyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHYgLSByYW5nZTBPcHBBeGlzKSAvIGRpc3RPcHBBeGlzICogb3B0cy5faGVpZ2h0O1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVwZGF0ZSBpbm5lciBub2Rlc1xuXG4gICAgICAgIHJhbmdlU2xpZGVyXG4gICAgICAgICAgICAuY2FsbChkcmF3QmcsIGdkLCBheGlzT3B0cywgb3B0cylcbiAgICAgICAgICAgIC5jYWxsKGFkZENsaXBQYXRoLCBnZCwgYXhpc09wdHMsIG9wdHMpXG4gICAgICAgICAgICAuY2FsbChkcmF3UmFuZ2VQbG90LCBnZCwgYXhpc09wdHMsIG9wdHMpXG4gICAgICAgICAgICAuY2FsbChkcmF3TWFza3MsIGdkLCBheGlzT3B0cywgb3B0cywgb3BwQXhpc1JhbmdlT3B0cylcbiAgICAgICAgICAgIC5jYWxsKGRyYXdTbGlkZUJveCwgZ2QsIGF4aXNPcHRzLCBvcHRzKVxuICAgICAgICAgICAgLmNhbGwoZHJhd0dyYWJiZXJzLCBnZCwgYXhpc09wdHMsIG9wdHMpO1xuXG4gICAgICAgIC8vIHNldHVwIGRyYWcgZWxlbWVudFxuICAgICAgICBzZXR1cERyYWdFbGVtZW50KHJhbmdlU2xpZGVyLCBnZCwgYXhpc09wdHMsIG9wdHMpO1xuXG4gICAgICAgIC8vIHVwZGF0ZSBjdXJyZW50IHJhbmdlXG4gICAgICAgIHNldFBpeGVsUmFuZ2UocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cywgb3BwQXhpc09wdHMsIG9wcEF4aXNSYW5nZU9wdHMpO1xuXG4gICAgICAgIC8vIHRpdGxlIGdvZXMgbmV4dCB0byByYW5nZSBzbGlkZXIgaW5zdGVhZCBvZiB0aWNrIGxhYmVscywgc29cbiAgICAgICAgLy8ganVzdCB0YWtlIGl0IG92ZXIgYW5kIGRyYXcgaXQgZnJvbSBoZXJlXG4gICAgICAgIGlmKGF4aXNPcHRzLnNpZGUgPT09ICdib3R0b20nKSB7XG4gICAgICAgICAgICBUaXRsZXMuZHJhdyhnZCwgYXhpc09wdHMuX2lkICsgJ3RpdGxlJywge1xuICAgICAgICAgICAgICAgIHByb3BDb250YWluZXI6IGF4aXNPcHRzLFxuICAgICAgICAgICAgICAgIHByb3BOYW1lOiBheGlzT3B0cy5fbmFtZSArICcudGl0bGUnLFxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBmdWxsTGF5b3V0Ll9kZmx0VGl0bGUueCxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICAgICAgIHg6IGF4aXNPcHRzLl9vZmZzZXQgKyBheGlzT3B0cy5fbGVuZ3RoIC8gMixcbiAgICAgICAgICAgICAgICAgICAgeTogeSArIG9wdHMuX2hlaWdodCArIG9wdHMuX29mZnNldFNoaWZ0ICsgMTAgKyAxLjUgKiBheGlzT3B0cy50aXRsZS5mb250LnNpemUsXG4gICAgICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6ICdtaWRkbGUnXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIHNldHVwRHJhZ0VsZW1lbnQocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cykge1xuICAgIHZhciBzbGlkZUJveCA9IHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLnNsaWRlQm94Q2xhc3NOYW1lKS5ub2RlKCk7XG4gICAgdmFyIGdyYWJBcmVhTWluID0gcmFuZ2VTbGlkZXIuc2VsZWN0KCdyZWN0LicgKyBjb25zdGFudHMuZ3JhYkFyZWFNaW5DbGFzc05hbWUpLm5vZGUoKTtcbiAgICB2YXIgZ3JhYkFyZWFNYXggPSByYW5nZVNsaWRlci5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5ncmFiQXJlYU1heENsYXNzTmFtZSkubm9kZSgpO1xuXG4gICAgcmFuZ2VTbGlkZXIub24oJ21vdXNlZG93bicsIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgZXZlbnQgPSBkMy5ldmVudDtcbiAgICAgICAgdmFyIHRhcmdldCA9IGV2ZW50LnRhcmdldDtcbiAgICAgICAgdmFyIHN0YXJ0WCA9IGV2ZW50LmNsaWVudFg7XG4gICAgICAgIHZhciBvZmZzZXRYID0gc3RhcnRYIC0gcmFuZ2VTbGlkZXIubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQ7XG4gICAgICAgIHZhciBtaW5WYWwgPSBvcHRzLmQycChheGlzT3B0cy5fcmxbMF0pO1xuICAgICAgICB2YXIgbWF4VmFsID0gb3B0cy5kMnAoYXhpc09wdHMuX3JsWzFdKTtcblxuICAgICAgICB2YXIgZHJhZ0NvdmVyID0gZHJhZ0VsZW1lbnQuY292ZXJTbGlwKCk7XG5cbiAgICAgICAgZHJhZ0NvdmVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG1vdXNlTW92ZSk7XG4gICAgICAgIGRyYWdDb3Zlci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgbW91c2VVcCk7XG5cbiAgICAgICAgZnVuY3Rpb24gbW91c2VNb3ZlKGUpIHtcbiAgICAgICAgICAgIHZhciBkZWx0YSA9ICtlLmNsaWVudFggLSBzdGFydFg7XG4gICAgICAgICAgICB2YXIgcGl4ZWxNaW4sIHBpeGVsTWF4LCBjdXJzb3I7XG5cbiAgICAgICAgICAgIHN3aXRjaCh0YXJnZXQpIHtcbiAgICAgICAgICAgICAgICBjYXNlIHNsaWRlQm94OlxuICAgICAgICAgICAgICAgICAgICBjdXJzb3IgPSAnZXctcmVzaXplJztcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxNaW4gPSBtaW5WYWwgKyBkZWx0YTtcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxNYXggPSBtYXhWYWwgKyBkZWx0YTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlIGdyYWJBcmVhTWluOlxuICAgICAgICAgICAgICAgICAgICBjdXJzb3IgPSAnY29sLXJlc2l6ZSc7XG4gICAgICAgICAgICAgICAgICAgIHBpeGVsTWluID0gbWluVmFsICsgZGVsdGE7XG4gICAgICAgICAgICAgICAgICAgIHBpeGVsTWF4ID0gbWF4VmFsO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgZ3JhYkFyZWFNYXg6XG4gICAgICAgICAgICAgICAgICAgIGN1cnNvciA9ICdjb2wtcmVzaXplJztcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxNaW4gPSBtaW5WYWw7XG4gICAgICAgICAgICAgICAgICAgIHBpeGVsTWF4ID0gbWF4VmFsICsgZGVsdGE7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgY3Vyc29yID0gJ2V3LXJlc2l6ZSc7XG4gICAgICAgICAgICAgICAgICAgIHBpeGVsTWluID0gb2Zmc2V0WDtcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxNYXggPSBvZmZzZXRYICsgZGVsdGE7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihwaXhlbE1heCA8IHBpeGVsTWluKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRtcCA9IHBpeGVsTWF4O1xuICAgICAgICAgICAgICAgIHBpeGVsTWF4ID0gcGl4ZWxNaW47XG4gICAgICAgICAgICAgICAgcGl4ZWxNaW4gPSB0bXA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG9wdHMuX3BpeGVsTWluID0gcGl4ZWxNaW47XG4gICAgICAgICAgICBvcHRzLl9waXhlbE1heCA9IHBpeGVsTWF4O1xuXG4gICAgICAgICAgICBzZXRDdXJzb3IoZDMuc2VsZWN0KGRyYWdDb3ZlciksIGN1cnNvcik7XG4gICAgICAgICAgICBzZXREYXRhUmFuZ2UocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cyk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBtb3VzZVVwKCkge1xuICAgICAgICAgICAgZHJhZ0NvdmVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG1vdXNlTW92ZSk7XG4gICAgICAgICAgICBkcmFnQ292ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIG1vdXNlVXApO1xuICAgICAgICAgICAgTGliLnJlbW92ZUVsZW1lbnQoZHJhZ0NvdmVyKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBzZXREYXRhUmFuZ2UocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cykge1xuICAgIGZ1bmN0aW9uIGNsYW1wKHYpIHtcbiAgICAgICAgcmV0dXJuIGF4aXNPcHRzLmwycihMaWIuY29uc3RyYWluKHYsIG9wdHMuX3JsWzBdLCBvcHRzLl9ybFsxXSkpO1xuICAgIH1cblxuICAgIHZhciBkYXRhTWluID0gY2xhbXAob3B0cy5wMmQob3B0cy5fcGl4ZWxNaW4pKTtcbiAgICB2YXIgZGF0YU1heCA9IGNsYW1wKG9wdHMucDJkKG9wdHMuX3BpeGVsTWF4KSk7XG5cbiAgICB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZ1bmN0aW9uKCkge1xuICAgICAgICBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVsYXlvdXQnLCBnZCwgYXhpc09wdHMuX25hbWUgKyAnLnJhbmdlJywgW2RhdGFNaW4sIGRhdGFNYXhdKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gc2V0UGl4ZWxSYW5nZShyYW5nZVNsaWRlciwgZ2QsIGF4aXNPcHRzLCBvcHRzLCBvcHBBeGlzT3B0cywgb3BwQXhpc1JhbmdlT3B0cykge1xuICAgIHZhciBodzIgPSBjb25zdGFudHMuaGFuZGxlV2lkdGggLyAyO1xuXG4gICAgZnVuY3Rpb24gY2xhbXAodikge1xuICAgICAgICByZXR1cm4gTGliLmNvbnN0cmFpbih2LCAwLCBvcHRzLl93aWR0aCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xhbXBPcHBBeGlzKHYpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb25zdHJhaW4odiwgMCwgb3B0cy5faGVpZ2h0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjbGFtcEhhbmRsZSh2KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29uc3RyYWluKHYsIC1odzIsIG9wdHMuX3dpZHRoICsgaHcyKTtcbiAgICB9XG5cbiAgICB2YXIgcGl4ZWxNaW4gPSBjbGFtcChvcHRzLmQycChheGlzT3B0cy5fcmxbMF0pKTtcbiAgICB2YXIgcGl4ZWxNYXggPSBjbGFtcChvcHRzLmQycChheGlzT3B0cy5fcmxbMV0pKTtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLnNsaWRlQm94Q2xhc3NOYW1lKVxuICAgICAgICAuYXR0cigneCcsIHBpeGVsTWluKVxuICAgICAgICAuYXR0cignd2lkdGgnLCBwaXhlbE1heCAtIHBpeGVsTWluKTtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLm1hc2tNaW5DbGFzc05hbWUpXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIHBpeGVsTWluKTtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLm1hc2tNYXhDbGFzc05hbWUpXG4gICAgICAgIC5hdHRyKCd4JywgcGl4ZWxNYXgpXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIG9wdHMuX3dpZHRoIC0gcGl4ZWxNYXgpO1xuXG4gICAgaWYob3BwQXhpc1JhbmdlT3B0cy5yYW5nZW1vZGUgIT09ICdtYXRjaCcpIHtcbiAgICAgICAgdmFyIHBpeGVsTWluT3BwQXhpcyA9IG9wdHMuX2hlaWdodCAtIGNsYW1wT3BwQXhpcyhvcHRzLmQycE9wcEF4aXMob3BwQXhpc09wdHMuX3JsWzFdKSk7XG4gICAgICAgIHZhciBwaXhlbE1heE9wcEF4aXMgPSBvcHRzLl9oZWlnaHQgLSBjbGFtcE9wcEF4aXMob3B0cy5kMnBPcHBBeGlzKG9wcEF4aXNPcHRzLl9ybFswXSkpO1xuXG4gICAgICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgncmVjdC4nICsgY29uc3RhbnRzLm1hc2tNaW5PcHBBeGlzQ2xhc3NOYW1lKVxuICAgICAgICAgICAgLmF0dHIoJ3gnLCBwaXhlbE1pbilcbiAgICAgICAgICAgIC5hdHRyKCdoZWlnaHQnLCBwaXhlbE1pbk9wcEF4aXMpXG4gICAgICAgICAgICAuYXR0cignd2lkdGgnLCBwaXhlbE1heCAtIHBpeGVsTWluKTtcblxuICAgICAgICByYW5nZVNsaWRlci5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5tYXNrTWF4T3BwQXhpc0NsYXNzTmFtZSlcbiAgICAgICAgICAgIC5hdHRyKCd4JywgcGl4ZWxNaW4pXG4gICAgICAgICAgICAuYXR0cigneScsIHBpeGVsTWF4T3BwQXhpcylcbiAgICAgICAgICAgIC5hdHRyKCdoZWlnaHQnLCBvcHRzLl9oZWlnaHQgLSBwaXhlbE1heE9wcEF4aXMpXG4gICAgICAgICAgICAuYXR0cignd2lkdGgnLCBwaXhlbE1heCAtIHBpeGVsTWluKTtcblxuICAgICAgICByYW5nZVNsaWRlci5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5zbGlkZUJveENsYXNzTmFtZSlcbiAgICAgICAgICAgIC5hdHRyKCd5JywgcGl4ZWxNaW5PcHBBeGlzKVxuICAgICAgICAgICAgLmF0dHIoJ2hlaWdodCcsIHBpeGVsTWF4T3BwQXhpcyAtIHBpeGVsTWluT3BwQXhpcyk7XG4gICAgfVxuXG4gICAgLy8gYWRkIG9mZnNldCBmb3IgY3Jpc3BpZXIgY29ybmVyc1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL3B1bGwvMTQwOVxuICAgIHZhciBvZmZzZXQgPSAwLjU7XG5cbiAgICB2YXIgeE1pbiA9IE1hdGgucm91bmQoY2xhbXBIYW5kbGUocGl4ZWxNaW4gLSBodzIpKSAtIG9mZnNldDtcbiAgICB2YXIgeE1heCA9IE1hdGgucm91bmQoY2xhbXBIYW5kbGUocGl4ZWxNYXggLSBodzIpKSArIG9mZnNldDtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgnZy4nICsgY29uc3RhbnRzLmdyYWJiZXJNaW5DbGFzc05hbWUpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyB4TWluICsgJywnICsgb2Zmc2V0ICsgJyknKTtcblxuICAgIHJhbmdlU2xpZGVyLnNlbGVjdCgnZy4nICsgY29uc3RhbnRzLmdyYWJiZXJNYXhDbGFzc05hbWUpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyB4TWF4ICsgJywnICsgb2Zmc2V0ICsgJyknKTtcbn1cblxuZnVuY3Rpb24gZHJhd0JnKHJhbmdlU2xpZGVyLCBnZCwgYXhpc09wdHMsIG9wdHMpIHtcbiAgICB2YXIgYmcgPSBMaWIuZW5zdXJlU2luZ2xlKHJhbmdlU2xpZGVyLCAncmVjdCcsIGNvbnN0YW50cy5iZ0NsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoe1xuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAnc2hhcGUtcmVuZGVyaW5nJzogJ2NyaXNwRWRnZXMnXG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdmFyIGJvcmRlckNvcnJlY3QgPSAob3B0cy5ib3JkZXJ3aWR0aCAlIDIpID09PSAwID9cbiAgICAgICAgb3B0cy5ib3JkZXJ3aWR0aCA6XG4gICAgICAgIG9wdHMuYm9yZGVyd2lkdGggLSAxO1xuXG4gICAgdmFyIG9mZnNldFNoaWZ0ID0gLW9wdHMuX29mZnNldFNoaWZ0O1xuICAgIHZhciBsdyA9IERyYXdpbmcuY3Jpc3BSb3VuZChnZCwgb3B0cy5ib3JkZXJ3aWR0aCk7XG5cbiAgICBiZy5hdHRyKHtcbiAgICAgICAgd2lkdGg6IG9wdHMuX3dpZHRoICsgYm9yZGVyQ29ycmVjdCxcbiAgICAgICAgaGVpZ2h0OiBvcHRzLl9oZWlnaHQgKyBib3JkZXJDb3JyZWN0LFxuICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIG9mZnNldFNoaWZ0ICsgJywnICsgb2Zmc2V0U2hpZnQgKyAnKScsXG4gICAgICAgIGZpbGw6IG9wdHMuYmdjb2xvcixcbiAgICAgICAgc3Ryb2tlOiBvcHRzLmJvcmRlcmNvbG9yLFxuICAgICAgICAnc3Ryb2tlLXdpZHRoJzogbHdcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gYWRkQ2xpcFBhdGgocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cykge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICB2YXIgY2xpcFBhdGggPSBMaWIuZW5zdXJlU2luZ2xlQnlJZChmdWxsTGF5b3V0Ll90b3BkZWZzLCAnY2xpcFBhdGgnLCBvcHRzLl9jbGlwSWQsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5hcHBlbmQoJ3JlY3QnKS5hdHRyKHsgeDogMCwgeTogMCB9KTtcbiAgICB9KTtcblxuICAgIGNsaXBQYXRoLnNlbGVjdCgncmVjdCcpLmF0dHIoe1xuICAgICAgICB3aWR0aDogb3B0cy5fd2lkdGgsXG4gICAgICAgIGhlaWdodDogb3B0cy5faGVpZ2h0XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGRyYXdSYW5nZVBsb3QocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cykge1xuICAgIHZhciBjYWxjRGF0YSA9IGdkLmNhbGNkYXRhO1xuXG4gICAgdmFyIHJhbmdlUGxvdHMgPSByYW5nZVNsaWRlci5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5yYW5nZVBsb3RDbGFzc05hbWUpXG4gICAgICAgIC5kYXRhKGF4aXNPcHRzLl9zdWJwbG90c1dpdGgsIExpYi5pZGVudGl0eSk7XG5cbiAgICByYW5nZVBsb3RzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgZnVuY3Rpb24oaWQpIHsgcmV0dXJuIGNvbnN0YW50cy5yYW5nZVBsb3RDbGFzc05hbWUgKyAnICcgKyBpZDsgfSlcbiAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRDbGlwVXJsLCBvcHRzLl9jbGlwSWQsIGdkKTtcblxuICAgIHJhbmdlUGxvdHMub3JkZXIoKTtcblxuICAgIHJhbmdlUGxvdHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdmFyIG1haW5wbG90aW5mbztcblxuICAgIHJhbmdlUGxvdHMuZWFjaChmdW5jdGlvbihpZCwgaSkge1xuICAgICAgICB2YXIgcGxvdGdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgaXNNYWluUGxvdCA9IChpID09PSAwKTtcblxuICAgICAgICB2YXIgb3BwQXhpc09wdHMgPSBheGlzSURzLmdldEZyb21JZChnZCwgaWQsICd5Jyk7XG4gICAgICAgIHZhciBvcHBBeGlzTmFtZSA9IG9wcEF4aXNPcHRzLl9uYW1lO1xuICAgICAgICB2YXIgb3BwQXhpc1JhbmdlT3B0cyA9IG9wdHNbb3BwQXhpc05hbWVdO1xuXG4gICAgICAgIHZhciBtb2NrRmlndXJlID0ge1xuICAgICAgICAgICAgZGF0YTogW10sXG4gICAgICAgICAgICBsYXlvdXQ6IHtcbiAgICAgICAgICAgICAgICB4YXhpczoge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiBheGlzT3B0cy50eXBlLFxuICAgICAgICAgICAgICAgICAgICBkb21haW46IFswLCAxXSxcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2U6IG9wdHMucmFuZ2Uuc2xpY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgY2FsZW5kYXI6IGF4aXNPcHRzLmNhbGVuZGFyXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB3aWR0aDogb3B0cy5fd2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBvcHRzLl9oZWlnaHQsXG4gICAgICAgICAgICAgICAgbWFyZ2luOiB7IHQ6IDAsIGI6IDAsIGw6IDAsIHI6IDAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9jb250ZXh0OiBnZC5fY29udGV4dFxuICAgICAgICB9O1xuXG4gICAgICAgIG1vY2tGaWd1cmUubGF5b3V0W29wcEF4aXNOYW1lXSA9IHtcbiAgICAgICAgICAgIHR5cGU6IG9wcEF4aXNPcHRzLnR5cGUsXG4gICAgICAgICAgICBkb21haW46IFswLCAxXSxcbiAgICAgICAgICAgIHJhbmdlOiBvcHBBeGlzUmFuZ2VPcHRzLnJhbmdlbW9kZSAhPT0gJ21hdGNoJyA/IG9wcEF4aXNSYW5nZU9wdHMucmFuZ2Uuc2xpY2UoKSA6IG9wcEF4aXNPcHRzLnJhbmdlLnNsaWNlKCksXG4gICAgICAgICAgICBjYWxlbmRhcjogb3BwQXhpc09wdHMuY2FsZW5kYXJcbiAgICAgICAgfTtcblxuICAgICAgICBQbG90cy5zdXBwbHlEZWZhdWx0cyhtb2NrRmlndXJlKTtcblxuICAgICAgICB2YXIgeGEgPSBtb2NrRmlndXJlLl9mdWxsTGF5b3V0LnhheGlzO1xuICAgICAgICB2YXIgeWEgPSBtb2NrRmlndXJlLl9mdWxsTGF5b3V0W29wcEF4aXNOYW1lXTtcblxuICAgICAgICB4YS5jbGVhckNhbGMoKTtcbiAgICAgICAgeGEuc2V0U2NhbGUoKTtcbiAgICAgICAgeWEuY2xlYXJDYWxjKCk7XG4gICAgICAgIHlhLnNldFNjYWxlKCk7XG5cbiAgICAgICAgdmFyIHBsb3RpbmZvID0ge1xuICAgICAgICAgICAgaWQ6IGlkLFxuICAgICAgICAgICAgcGxvdGdyb3VwOiBwbG90Z3JvdXAsXG4gICAgICAgICAgICB4YXhpczogeGEsXG4gICAgICAgICAgICB5YXhpczogeWEsXG4gICAgICAgICAgICBpc1JhbmdlUGxvdDogdHJ1ZVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmKGlzTWFpblBsb3QpIG1haW5wbG90aW5mbyA9IHBsb3RpbmZvO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHBsb3RpbmZvLm1haW5wbG90ID0gJ3h5JztcbiAgICAgICAgICAgIHBsb3RpbmZvLm1haW5wbG90aW5mbyA9IG1haW5wbG90aW5mbztcbiAgICAgICAgfVxuXG4gICAgICAgIENhcnRlc2lhbi5yYW5nZVBsb3QoZ2QsIHBsb3RpbmZvLCBmaWx0ZXJSYW5nZVBsb3RDYWxjRGF0YShjYWxjRGF0YSwgaWQpKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZmlsdGVyUmFuZ2VQbG90Q2FsY0RhdGEoY2FsY0RhdGEsIHN1YnBsb3RJZCkge1xuICAgIHZhciBvdXQgPSBbXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1RyYWNlID0gY2FsY0RhdGFbaV07XG4gICAgICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgICAgICBpZih0cmFjZS54YXhpcyArIHRyYWNlLnlheGlzID09PSBzdWJwbG90SWQpIHtcbiAgICAgICAgICAgIG91dC5wdXNoKGNhbGNUcmFjZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufVxuXG5mdW5jdGlvbiBkcmF3TWFza3MocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cywgb3BwQXhpc1JhbmdlT3B0cykge1xuICAgIHZhciBtYXNrTWluID0gTGliLmVuc3VyZVNpbmdsZShyYW5nZVNsaWRlciwgJ3JlY3QnLCBjb25zdGFudHMubWFza01pbkNsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoe1xuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAnc2hhcGUtcmVuZGVyaW5nJzogJ2NyaXNwRWRnZXMnXG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgbWFza01pblxuICAgICAgICAuYXR0cignaGVpZ2h0Jywgb3B0cy5faGVpZ2h0KVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBjb25zdGFudHMubWFza0NvbG9yKTtcblxuICAgIHZhciBtYXNrTWF4ID0gTGliLmVuc3VyZVNpbmdsZShyYW5nZVNsaWRlciwgJ3JlY3QnLCBjb25zdGFudHMubWFza01heENsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoe1xuICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgICdzaGFwZS1yZW5kZXJpbmcnOiAnY3Jpc3BFZGdlcydcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBtYXNrTWF4XG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBvcHRzLl9oZWlnaHQpXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGNvbnN0YW50cy5tYXNrQ29sb3IpO1xuXG4gICAgLy8gbWFza3MgdXNlZCBmb3Igb3BwQXhpcyB6b29tXG4gICAgaWYob3BwQXhpc1JhbmdlT3B0cy5yYW5nZW1vZGUgIT09ICdtYXRjaCcpIHtcbiAgICAgICAgdmFyIG1hc2tNaW5PcHBBeGlzID0gTGliLmVuc3VyZVNpbmdsZShyYW5nZVNsaWRlciwgJ3JlY3QnLCBjb25zdGFudHMubWFza01pbk9wcEF4aXNDbGFzc05hbWUsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICAgIHMuYXR0cih7XG4gICAgICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgICAgICAnc2hhcGUtcmVuZGVyaW5nJzogJ2NyaXNwRWRnZXMnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbWFza01pbk9wcEF4aXNcbiAgICAgICAgICAgIC5hdHRyKCd3aWR0aCcsIG9wdHMuX3dpZHRoKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgY29uc3RhbnRzLm1hc2tPcHBBeGlzQ29sb3IpO1xuXG4gICAgICAgIHZhciBtYXNrTWF4T3BwQXhpcyA9IExpYi5lbnN1cmVTaW5nbGUocmFuZ2VTbGlkZXIsICdyZWN0JywgY29uc3RhbnRzLm1hc2tNYXhPcHBBeGlzQ2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICBzLmF0dHIoe1xuICAgICAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAgICAgJ3NoYXBlLXJlbmRlcmluZyc6ICdjcmlzcEVkZ2VzJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIG1hc2tNYXhPcHBBeGlzXG4gICAgICAgICAgICAuYXR0cignd2lkdGgnLCBvcHRzLl93aWR0aClcbiAgICAgICAgICAgIC5zdHlsZSgnYm9yZGVyLXRvcCcsIGNvbnN0YW50cy5tYXNrT3BwQm9yZGVyKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgY29uc3RhbnRzLm1hc2tPcHBBeGlzQ29sb3IpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZHJhd1NsaWRlQm94KHJhbmdlU2xpZGVyLCBnZCwgYXhpc09wdHMsIG9wdHMpIHtcbiAgICBpZihnZC5fY29udGV4dC5zdGF0aWNQbG90KSByZXR1cm47XG5cbiAgICB2YXIgc2xpZGVCb3ggPSBMaWIuZW5zdXJlU2luZ2xlKHJhbmdlU2xpZGVyLCAncmVjdCcsIGNvbnN0YW50cy5zbGlkZUJveENsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoe1xuICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgIGN1cnNvcjogY29uc3RhbnRzLnNsaWRlQm94Q3Vyc29yLFxuICAgICAgICAgICAgJ3NoYXBlLXJlbmRlcmluZyc6ICdjcmlzcEVkZ2VzJ1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIHNsaWRlQm94LmF0dHIoe1xuICAgICAgICBoZWlnaHQ6IG9wdHMuX2hlaWdodCxcbiAgICAgICAgZmlsbDogY29uc3RhbnRzLnNsaWRlQm94RmlsbFxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBkcmF3R3JhYmJlcnMocmFuZ2VTbGlkZXIsIGdkLCBheGlzT3B0cywgb3B0cykge1xuICAgIC8vIDxnIGdyYWJiZXIgLz5cbiAgICB2YXIgZ3JhYmJlck1pbiA9IExpYi5lbnN1cmVTaW5nbGUocmFuZ2VTbGlkZXIsICdnJywgY29uc3RhbnRzLmdyYWJiZXJNaW5DbGFzc05hbWUpO1xuICAgIHZhciBncmFiYmVyTWF4ID0gTGliLmVuc3VyZVNpbmdsZShyYW5nZVNsaWRlciwgJ2cnLCBjb25zdGFudHMuZ3JhYmJlck1heENsYXNzTmFtZSk7XG5cbiAgICAvLyA8ZyBoYW5kbGUgLz5cbiAgICB2YXIgaGFuZGxlRml4QXR0cnMgPSB7XG4gICAgICAgIHg6IDAsXG4gICAgICAgIHdpZHRoOiBjb25zdGFudHMuaGFuZGxlV2lkdGgsXG4gICAgICAgIHJ4OiBjb25zdGFudHMuaGFuZGxlUmFkaXVzLFxuICAgICAgICBmaWxsOiBDb2xvci5iYWNrZ3JvdW5kLFxuICAgICAgICBzdHJva2U6IENvbG9yLmRlZmF1bHRMaW5lLFxuICAgICAgICAnc3Ryb2tlLXdpZHRoJzogY29uc3RhbnRzLmhhbmRsZVN0cm9rZVdpZHRoLFxuICAgICAgICAnc2hhcGUtcmVuZGVyaW5nJzogJ2NyaXNwRWRnZXMnXG4gICAgfTtcbiAgICB2YXIgaGFuZGxlRHluYW1pY0F0dHJzID0ge1xuICAgICAgICB5OiBNYXRoLnJvdW5kKG9wdHMuX2hlaWdodCAvIDQpLFxuICAgICAgICBoZWlnaHQ6IE1hdGgucm91bmQob3B0cy5faGVpZ2h0IC8gMiksXG4gICAgfTtcbiAgICB2YXIgaGFuZGxlTWluID0gTGliLmVuc3VyZVNpbmdsZShncmFiYmVyTWluLCAncmVjdCcsIGNvbnN0YW50cy5oYW5kbGVNaW5DbGFzc05hbWUsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5hdHRyKGhhbmRsZUZpeEF0dHJzKTtcbiAgICB9KTtcbiAgICBoYW5kbGVNaW4uYXR0cihoYW5kbGVEeW5hbWljQXR0cnMpO1xuXG4gICAgdmFyIGhhbmRsZU1heCA9IExpYi5lbnN1cmVTaW5nbGUoZ3JhYmJlck1heCwgJ3JlY3QnLCBjb25zdGFudHMuaGFuZGxlTWF4Q2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cihoYW5kbGVGaXhBdHRycyk7XG4gICAgfSk7XG4gICAgaGFuZGxlTWF4LmF0dHIoaGFuZGxlRHluYW1pY0F0dHJzKTtcblxuICAgIC8vIDxnIGdyYWJhcmVhIC8+XG4gICAgaWYoZ2QuX2NvbnRleHQuc3RhdGljUGxvdCkgcmV0dXJuO1xuXG4gICAgdmFyIGdyYWJBcmVhRml4QXR0cnMgPSB7XG4gICAgICAgIHdpZHRoOiBjb25zdGFudHMuZ3JhYkFyZWFXaWR0aCxcbiAgICAgICAgeDogMCxcbiAgICAgICAgeTogMCxcbiAgICAgICAgZmlsbDogY29uc3RhbnRzLmdyYWJBcmVhRmlsbCxcbiAgICAgICAgY3Vyc29yOiBjb25zdGFudHMuZ3JhYkFyZWFDdXJzb3JcbiAgICB9O1xuXG4gICAgdmFyIGdyYWJBcmVhTWluID0gTGliLmVuc3VyZVNpbmdsZShncmFiYmVyTWluLCAncmVjdCcsIGNvbnN0YW50cy5ncmFiQXJlYU1pbkNsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmF0dHIoZ3JhYkFyZWFGaXhBdHRycyk7XG4gICAgfSk7XG4gICAgZ3JhYkFyZWFNaW4uYXR0cignaGVpZ2h0Jywgb3B0cy5faGVpZ2h0KTtcblxuICAgIHZhciBncmFiQXJlYU1heCA9IExpYi5lbnN1cmVTaW5nbGUoZ3JhYmJlck1heCwgJ3JlY3QnLCBjb25zdGFudHMuZ3JhYkFyZWFNYXhDbGFzc05hbWUsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5hdHRyKGdyYWJBcmVhRml4QXR0cnMpO1xuICAgIH0pO1xuICAgIGdyYWJBcmVhTWF4LmF0dHIoJ2hlaWdodCcsIG9wdHMuX2hlaWdodCk7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL3NldGN1cnNvclwiOjczOSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhblwiOjc3OCxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkc1wiOjc3MCxcIi4uLy4uL3Bsb3RzL3Bsb3RzXCI6ODI4LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9jb2xvclwiOjU5MyxcIi4uL2RyYWdlbGVtZW50XCI6NjExLFwiLi4vZHJhd2luZ1wiOjYxNCxcIi4uL3RpdGxlc1wiOjY4MSxcIi4vY29uc3RhbnRzXCI6NjYzLFwiZDNcIjoxNjN9XSw2NjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXhpc0lEcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkcycpO1xudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgbmFtZSA9IGNvbnN0YW50cy5uYW1lO1xuXG5mdW5jdGlvbiBpc1Zpc2libGUoYXgpIHtcbiAgICB2YXIgcmFuZ2VTbGlkZXIgPSBheCAmJiBheFtuYW1lXTtcbiAgICByZXR1cm4gcmFuZ2VTbGlkZXIgJiYgcmFuZ2VTbGlkZXIudmlzaWJsZTtcbn1cbmV4cG9ydHMuaXNWaXNpYmxlID0gaXNWaXNpYmxlO1xuXG5leHBvcnRzLm1ha2VEYXRhID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIHZhciBheGVzID0gYXhpc0lEcy5saXN0KHsgX2Z1bGxMYXlvdXQ6IGZ1bGxMYXlvdXQgfSwgJ3gnLCB0cnVlKTtcbiAgICB2YXIgbWFyZ2luID0gZnVsbExheW91dC5tYXJnaW47XG4gICAgdmFyIHJhbmdlU2xpZGVyRGF0YSA9IFtdO1xuXG4gICAgaWYoIWZ1bGxMYXlvdXQuX2hhcygnZ2wyZCcpKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgYXggPSBheGVzW2ldO1xuXG4gICAgICAgICAgICBpZihpc1Zpc2libGUoYXgpKSB7XG4gICAgICAgICAgICAgICAgcmFuZ2VTbGlkZXJEYXRhLnB1c2goYXgpO1xuXG4gICAgICAgICAgICAgICAgdmFyIG9wdHMgPSBheFtuYW1lXTtcbiAgICAgICAgICAgICAgICBvcHRzLl9pZCA9IG5hbWUgKyBheC5faWQ7XG4gICAgICAgICAgICAgICAgb3B0cy5faGVpZ2h0ID0gKGZ1bGxMYXlvdXQuaGVpZ2h0IC0gbWFyZ2luLmIgLSBtYXJnaW4udCkgKiBvcHRzLnRoaWNrbmVzcztcbiAgICAgICAgICAgICAgICBvcHRzLl9vZmZzZXRTaGlmdCA9IE1hdGguZmxvb3Iob3B0cy5ib3JkZXJ3aWR0aCAvIDIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVsbExheW91dC5fcmFuZ2VTbGlkZXJEYXRhID0gcmFuZ2VTbGlkZXJEYXRhO1xufTtcblxuZXhwb3J0cy5hdXRvTWFyZ2luT3B0cyA9IGZ1bmN0aW9uKGdkLCBheCkge1xuICAgIHZhciBvcHRzID0gYXhbbmFtZV07XG5cbiAgICB2YXIgb3BwQm90dG9tID0gSW5maW5pdHk7XG4gICAgdmFyIGNvdW50ZXJBeGVzID0gYXguX2NvdW50ZXJBeGVzO1xuICAgIGZvcih2YXIgaiA9IDA7IGogPCBjb3VudGVyQXhlcy5sZW5ndGg7IGorKykge1xuICAgICAgICB2YXIgY291bnRlcklkID0gY291bnRlckF4ZXNbal07XG4gICAgICAgIHZhciBvcHBBeGlzID0gYXhpc0lEcy5nZXRGcm9tSWQoZ2QsIGNvdW50ZXJJZCk7XG4gICAgICAgIG9wcEJvdHRvbSA9IE1hdGgubWluKG9wcEJvdHRvbSwgb3BwQXhpcy5kb21haW5bMF0pO1xuICAgIH1cbiAgICBvcHRzLl9vcHBCb3R0b20gPSBvcHBCb3R0b207XG5cbiAgICB2YXIgdGlja0hlaWdodCA9IChheC5zaWRlID09PSAnYm90dG9tJyAmJiBheC5fYm91bmRpbmdCb3guaGVpZ2h0KSB8fCAwO1xuICAgIG9wdHMuX3RpY2tIZWlnaHQgPSB0aWNrSGVpZ2h0O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogMCxcbiAgICAgICAgeTogb3BwQm90dG9tLFxuICAgICAgICBsOiAwLFxuICAgICAgICByOiAwLFxuICAgICAgICB0OiAwLFxuICAgICAgICBiOiBvcHRzLl9oZWlnaHQgKyBnZC5fZnVsbExheW91dC5tYXJnaW4uYiArIHRpY2tIZWlnaHQsXG4gICAgICAgIHBhZDogY29uc3RhbnRzLmV4dHJhUGFkICsgb3B0cy5fb2Zmc2V0U2hpZnQgKiAyXG4gICAgfTtcbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzXCI6NzcwLFwiLi9jb25zdGFudHNcIjo2NjN9XSw2Njc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgYXR0cnMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBvcHBBeGlzQXR0cnMgPSBfZGVyZXFfKCcuL29wcGF4aXNfYXR0cmlidXRlcycpO1xudmFyIGhlbHBlcnMgPSBfZGVyZXFfKCcuL2hlbHBlcnMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogJ3Jhbmdlc2xpZGVyJyxcblxuICAgIHNjaGVtYToge1xuICAgICAgICBzdWJwbG90czoge1xuICAgICAgICAgICAgeGF4aXM6IHtcbiAgICAgICAgICAgICAgICByYW5nZXNsaWRlcjogTGliLmV4dGVuZEZsYXQoe30sIGF0dHJzLCB7XG4gICAgICAgICAgICAgICAgICAgIHlheGlzOiBvcHBBeGlzQXR0cnNcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGxheW91dEF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIGhhbmRsZURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgY2FsY0F1dG9yYW5nZTogX2RlcmVxXygnLi9jYWxjX2F1dG9yYW5nZScpLFxuICAgIGRyYXc6IF9kZXJlcV8oJy4vZHJhdycpLFxuICAgIGlzVmlzaWJsZTogaGVscGVycy5pc1Zpc2libGUsXG4gICAgbWFrZURhdGE6IGhlbHBlcnMubWFrZURhdGEsXG4gICAgYXV0b01hcmdpbk9wdHM6IGhlbHBlcnMuYXV0b01hcmdpbk9wdHNcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi9hdHRyaWJ1dGVzXCI6NjYxLFwiLi9jYWxjX2F1dG9yYW5nZVwiOjY2MixcIi4vZGVmYXVsdHNcIjo2NjQsXCIuL2RyYXdcIjo2NjUsXCIuL2hlbHBlcnNcIjo2NjYsXCIuL29wcGF4aXNfYXR0cmlidXRlc1wiOjY2OH1dLDY2ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIC8vIG5vdCByZWFsbHkgYSAnc3VicGxvdCcgYXR0cmlidXRlIGNvbnRhaW5lcixcbiAgICAvLyBidXQgdGhpcyBpcyB0aGUgZmxhZyB3ZSB1c2UgdG8gZGVub3RlIGF0dHJpYnV0ZXMgdGhhdFxuICAgIC8vIHN1cHBvcnQgeWF4aXMsIHlheGlzMiwgeWF4aXMzLCAuLi4gY291bnRlcnNcbiAgICBfaXNTdWJwbG90T2JqOiB0cnVlLFxuXG4gICAgcmFuZ2Vtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAnZml4ZWQnLCAnbWF0Y2gnXSxcbiAgICAgICAgZGZsdDogJ21hdGNoJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcmFuZ2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdwbG90J30sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAncGxvdCd9XG4gICAgICAgIF0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufTtcblxufSx7fV0sNjY5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGFubkF0dHJzID0gX2RlcmVxXygnLi4vYW5ub3RhdGlvbnMvYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJMaW5lQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi90cmFjZXMvc2NhdHRlci9hdHRyaWJ1dGVzJykubGluZTtcbnZhciBkYXNoID0gX2RlcmVxXygnLi4vZHJhd2luZy9hdHRyaWJ1dGVzJykuZGFzaDtcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgdGVtcGxhdGVkQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykudGVtcGxhdGVkQXJyYXk7XG5cbm1vZHVsZS5leHBvcnRzID0gdGVtcGxhdGVkQXJyYXkoJ3NoYXBlJywge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2NpcmNsZScsICdyZWN0JywgJ3BhdGgnLCAnbGluZSddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsYXllcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydiZWxvdycsICdhYm92ZSddLFxuICAgICAgICBkZmx0OiAnYWJvdmUnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgeHJlZjogZXh0ZW5kRmxhdCh7fSwgYW5uQXR0cnMueHJlZiwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICB4c2l6ZW1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnc2NhbGVkJywgJ3BpeGVsJ10sXG4gICAgICAgIGRmbHQ6ICdzY2FsZWQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHgwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeDE6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHlyZWY6IGV4dGVuZEZsYXQoe30sIGFubkF0dHJzLnlyZWYsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgeXNpemVtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3NjYWxlZCcsICdwaXhlbCddLFxuICAgICAgICBkZmx0OiAnc2NhbGVkJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHlhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5MDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYythcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHkxOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBwYXRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBvcGFjaXR5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXJyYXlkcmF3JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsaW5lOiB7XG4gICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTGluZUF0dHJzLmNvbG9yLCB7ZWRpdFR5cGU6ICdhcnJheWRyYXcnfSksXG4gICAgICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTGluZUF0dHJzLndpZHRoLCB7ZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdyd9KSxcbiAgICAgICAgZGFzaDogZXh0ZW5kRmxhdCh7fSwgZGFzaCwge2VkaXRUeXBlOiAnYXJyYXlkcmF3J30pLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2FycmF5ZHJhdydcbiAgICB9LFxuICAgIGZpbGxjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiAncmdiYSgwLDAsMCwwKScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2FycmF5ZHJhdycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnXG59KTtcblxufSx7XCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uLy4uL3RyYWNlcy9zY2F0dGVyL2F0dHJpYnV0ZXNcIjoxMTEyLFwiLi4vYW5ub3RhdGlvbnMvYXR0cmlidXRlc1wiOjU3NixcIi4uL2RyYXdpbmcvYXR0cmlidXRlc1wiOjYxM31dLDY3MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsY0F1dG9yYW5nZShnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHNoYXBlTGlzdCA9IExpYi5maWx0ZXJWaXNpYmxlKGZ1bGxMYXlvdXQuc2hhcGVzKTtcblxuICAgIGlmKCFzaGFwZUxpc3QubGVuZ3RoIHx8ICFnZC5fZnVsbERhdGEubGVuZ3RoKSByZXR1cm47XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2hhcGVMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzaGFwZSA9IHNoYXBlTGlzdFtpXTtcbiAgICAgICAgc2hhcGUuX2V4dHJlbWVzID0ge307XG5cbiAgICAgICAgdmFyIGF4LCBib3VuZHM7XG5cbiAgICAgICAgaWYoc2hhcGUueHJlZiAhPT0gJ3BhcGVyJykge1xuICAgICAgICAgICAgdmFyIHZ4MCA9IHNoYXBlLnhzaXplbW9kZSA9PT0gJ3BpeGVsJyA/IHNoYXBlLnhhbmNob3IgOiBzaGFwZS54MDtcbiAgICAgICAgICAgIHZhciB2eDEgPSBzaGFwZS54c2l6ZW1vZGUgPT09ICdwaXhlbCcgPyBzaGFwZS54YW5jaG9yIDogc2hhcGUueDE7XG4gICAgICAgICAgICBheCA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBzaGFwZS54cmVmKTtcblxuICAgICAgICAgICAgYm91bmRzID0gc2hhcGVCb3VuZHMoYXgsIHZ4MCwgdngxLCBzaGFwZS5wYXRoLCBjb25zdGFudHMucGFyYW1Jc1gpO1xuICAgICAgICAgICAgaWYoYm91bmRzKSB7XG4gICAgICAgICAgICAgICAgc2hhcGUuX2V4dHJlbWVzW2F4Ll9pZF0gPSBBeGVzLmZpbmRFeHRyZW1lcyhheCwgYm91bmRzLCBjYWxjWFBhZGRpbmdPcHRpb25zKHNoYXBlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihzaGFwZS55cmVmICE9PSAncGFwZXInKSB7XG4gICAgICAgICAgICB2YXIgdnkwID0gc2hhcGUueXNpemVtb2RlID09PSAncGl4ZWwnID8gc2hhcGUueWFuY2hvciA6IHNoYXBlLnkwO1xuICAgICAgICAgICAgdmFyIHZ5MSA9IHNoYXBlLnlzaXplbW9kZSA9PT0gJ3BpeGVsJyA/IHNoYXBlLnlhbmNob3IgOiBzaGFwZS55MTtcbiAgICAgICAgICAgIGF4ID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHNoYXBlLnlyZWYpO1xuXG4gICAgICAgICAgICBib3VuZHMgPSBzaGFwZUJvdW5kcyhheCwgdnkwLCB2eTEsIHNoYXBlLnBhdGgsIGNvbnN0YW50cy5wYXJhbUlzWSk7XG4gICAgICAgICAgICBpZihib3VuZHMpIHtcbiAgICAgICAgICAgICAgICBzaGFwZS5fZXh0cmVtZXNbYXguX2lkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKGF4LCBib3VuZHMsIGNhbGNZUGFkZGluZ09wdGlvbnMoc2hhcGUpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGNhbGNYUGFkZGluZ09wdGlvbnMoc2hhcGUpIHtcbiAgICByZXR1cm4gY2FsY1BhZGRpbmdPcHRpb25zKHNoYXBlLmxpbmUud2lkdGgsIHNoYXBlLnhzaXplbW9kZSwgc2hhcGUueDAsIHNoYXBlLngxLCBzaGFwZS5wYXRoLCBmYWxzZSk7XG59XG5cbmZ1bmN0aW9uIGNhbGNZUGFkZGluZ09wdGlvbnMoc2hhcGUpIHtcbiAgICByZXR1cm4gY2FsY1BhZGRpbmdPcHRpb25zKHNoYXBlLmxpbmUud2lkdGgsIHNoYXBlLnlzaXplbW9kZSwgc2hhcGUueTAsIHNoYXBlLnkxLCBzaGFwZS5wYXRoLCB0cnVlKTtcbn1cblxuZnVuY3Rpb24gY2FsY1BhZGRpbmdPcHRpb25zKGxpbmVXaWR0aCwgc2l6ZU1vZGUsIHYwLCB2MSwgcGF0aCwgaXNZQXhpcykge1xuICAgIHZhciBwcGFkID0gbGluZVdpZHRoIC8gMjtcbiAgICB2YXIgYXhpc0RpcmVjdGlvblJldmVydGVkID0gaXNZQXhpcztcblxuICAgIGlmKHNpemVNb2RlID09PSAncGl4ZWwnKSB7XG4gICAgICAgIHZhciBjb29yZHMgPSBwYXRoID9cbiAgICAgICAgICAgIGhlbHBlcnMuZXh0cmFjdFBhdGhDb29yZHMocGF0aCwgaXNZQXhpcyA/IGNvbnN0YW50cy5wYXJhbUlzWSA6IGNvbnN0YW50cy5wYXJhbUlzWCkgOlxuICAgICAgICAgICAgW3YwLCB2MV07XG4gICAgICAgIHZhciBtYXhWYWx1ZSA9IExpYi5hZ2dOdW1zKE1hdGgubWF4LCBudWxsLCBjb29yZHMpO1xuICAgICAgICB2YXIgbWluVmFsdWUgPSBMaWIuYWdnTnVtcyhNYXRoLm1pbiwgbnVsbCwgY29vcmRzKTtcbiAgICAgICAgdmFyIGJlZm9yZVBhZCA9IG1pblZhbHVlIDwgMCA/IE1hdGguYWJzKG1pblZhbHVlKSArIHBwYWQgOiBwcGFkO1xuICAgICAgICB2YXIgYWZ0ZXJQYWQgPSBtYXhWYWx1ZSA+IDAgPyBtYXhWYWx1ZSArIHBwYWQgOiBwcGFkO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBwcGFkOiBwcGFkLFxuICAgICAgICAgICAgcHBhZHBsdXM6IGF4aXNEaXJlY3Rpb25SZXZlcnRlZCA/IGJlZm9yZVBhZCA6IGFmdGVyUGFkLFxuICAgICAgICAgICAgcHBhZG1pbnVzOiBheGlzRGlyZWN0aW9uUmV2ZXJ0ZWQgPyBhZnRlclBhZCA6IGJlZm9yZVBhZFxuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7cHBhZDogcHBhZH07XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzaGFwZUJvdW5kcyhheCwgdjAsIHYxLCBwYXRoLCBwYXJhbXNUb1VzZSkge1xuICAgIHZhciBjb252ZXJ0VmFsID0gKGF4LnR5cGUgPT09ICdjYXRlZ29yeScgfHwgYXgudHlwZSA9PT0gJ211bHRpY2F0ZWdvcnknKSA/IGF4LnIyYyA6IGF4LmQyYztcblxuICAgIGlmKHYwICE9PSB1bmRlZmluZWQpIHJldHVybiBbY29udmVydFZhbCh2MCksIGNvbnZlcnRWYWwodjEpXTtcbiAgICBpZighcGF0aCkgcmV0dXJuO1xuXG4gICAgdmFyIG1pbiA9IEluZmluaXR5O1xuICAgIHZhciBtYXggPSAtSW5maW5pdHk7XG4gICAgdmFyIHNlZ21lbnRzID0gcGF0aC5tYXRjaChjb25zdGFudHMuc2VnbWVudFJFKTtcbiAgICB2YXIgaTtcbiAgICB2YXIgc2VnbWVudDtcbiAgICB2YXIgZHJhd25QYXJhbTtcbiAgICB2YXIgcGFyYW1zO1xuICAgIHZhciB2YWw7XG5cbiAgICBpZihheC50eXBlID09PSAnZGF0ZScpIGNvbnZlcnRWYWwgPSBoZWxwZXJzLmRlY29kZURhdGUoY29udmVydFZhbCk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzZWdtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzZWdtZW50ID0gc2VnbWVudHNbaV07XG4gICAgICAgIGRyYXduUGFyYW0gPSBwYXJhbXNUb1VzZVtzZWdtZW50LmNoYXJBdCgwKV0uZHJhd247XG4gICAgICAgIGlmKGRyYXduUGFyYW0gPT09IHVuZGVmaW5lZCkgY29udGludWU7XG5cbiAgICAgICAgcGFyYW1zID0gc2VnbWVudHNbaV0uc3Vic3RyKDEpLm1hdGNoKGNvbnN0YW50cy5wYXJhbVJFKTtcbiAgICAgICAgaWYoIXBhcmFtcyB8fCBwYXJhbXMubGVuZ3RoIDwgZHJhd25QYXJhbSkgY29udGludWU7XG5cbiAgICAgICAgdmFsID0gY29udmVydFZhbChwYXJhbXNbZHJhd25QYXJhbV0pO1xuICAgICAgICBpZih2YWwgPCBtaW4pIG1pbiA9IHZhbDtcbiAgICAgICAgaWYodmFsID4gbWF4KSBtYXggPSB2YWw7XG4gICAgfVxuICAgIGlmKG1heCA+PSBtaW4pIHJldHVybiBbbWluLCBtYXhdO1xufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi9jb25zdGFudHNcIjo2NzEsXCIuL2hlbHBlcnNcIjo2NzR9XSw2NzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc2VnbWVudFJFOiAvW01MSFZRQ1RTWl1bXk1MSFZRQ1RTWl0qL2csXG4gICAgcGFyYW1SRTogL1teXFxzLF0rL2csXG5cbiAgICAvLyB3aGljaCBudW1iZXJzIGluIGVhY2ggcGF0aCBzZWdtZW50IGFyZSB4IChvciB5KSB2YWx1ZXNcbiAgICAvLyBkcmF3biBpcyB3aGljaCBwYXJhbSBpcyBhIGRyYXduIHBvaW50LCBhcyBvcHBvc2VkIHRvIGFcbiAgICAvLyBjb250cm9sIHBvaW50ICh3aGljaCBkb2Vzbid0IGNvdW50IHRvd2FyZCBhdXRvcmFuZ2UuXG4gICAgLy8gVE9ETzogdGhpcyBtZWFucyBjdXJ2ZWQgcGF0aHMgY291bGQgZXh0ZW5kIGJleW9uZCB0aGVcbiAgICAvLyBhdXRvcmFuZ2UgYm91bmRzLiBUaGlzIGlzIGEgYml0IHRyaWNreSB0byBnZXQgcmlnaHRcbiAgICAvLyB1bmxlc3Mgd2UgcmV2ZXJ0IHRvIGJvdW5kaW5nIGJveGVzLCBidXQgcGVyaGFwcyB0aGVyZSdzXG4gICAgLy8gYSBjYWxjdWxhdGlvbiB3ZSBjb3VsZCBkby4uLilcbiAgICBwYXJhbUlzWDoge1xuICAgICAgICBNOiB7MDogdHJ1ZSwgZHJhd246IDB9LFxuICAgICAgICBMOiB7MDogdHJ1ZSwgZHJhd246IDB9LFxuICAgICAgICBIOiB7MDogdHJ1ZSwgZHJhd246IDB9LFxuICAgICAgICBWOiB7fSxcbiAgICAgICAgUTogezA6IHRydWUsIDI6IHRydWUsIGRyYXduOiAyfSxcbiAgICAgICAgQzogezA6IHRydWUsIDI6IHRydWUsIDQ6IHRydWUsIGRyYXduOiA0fSxcbiAgICAgICAgVDogezA6IHRydWUsIGRyYXduOiAwfSxcbiAgICAgICAgUzogezA6IHRydWUsIDI6IHRydWUsIGRyYXduOiAyfSxcbiAgICAgICAgLy8gQTogezA6IHRydWUsIDU6IHRydWV9LFxuICAgICAgICBaOiB7fVxuICAgIH0sXG5cbiAgICBwYXJhbUlzWToge1xuICAgICAgICBNOiB7MTogdHJ1ZSwgZHJhd246IDF9LFxuICAgICAgICBMOiB7MTogdHJ1ZSwgZHJhd246IDF9LFxuICAgICAgICBIOiB7fSxcbiAgICAgICAgVjogezA6IHRydWUsIGRyYXduOiAwfSxcbiAgICAgICAgUTogezE6IHRydWUsIDM6IHRydWUsIGRyYXduOiAzfSxcbiAgICAgICAgQzogezE6IHRydWUsIDM6IHRydWUsIDU6IHRydWUsIGRyYXduOiA1fSxcbiAgICAgICAgVDogezE6IHRydWUsIGRyYXduOiAxfSxcbiAgICAgICAgUzogezE6IHRydWUsIDM6IHRydWUsIGRyYXduOiA1fSxcbiAgICAgICAgLy8gQTogezE6IHRydWUsIDY6IHRydWV9LFxuICAgICAgICBaOiB7fVxuICAgIH0sXG5cbiAgICBudW1QYXJhbXM6IHtcbiAgICAgICAgTTogMixcbiAgICAgICAgTDogMixcbiAgICAgICAgSDogMSxcbiAgICAgICAgVjogMSxcbiAgICAgICAgUTogNCxcbiAgICAgICAgQzogNixcbiAgICAgICAgVDogMixcbiAgICAgICAgUzogNCxcbiAgICAgICAgLy8gQTogNyxcbiAgICAgICAgWjogMFxuICAgIH1cbn07XG5cbn0se31dLDY3MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBoZWxwZXJzID0gX2RlcmVxXygnLi9oZWxwZXJzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0KSB7XG4gICAgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCB7XG4gICAgICAgIG5hbWU6ICdzaGFwZXMnLFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IGhhbmRsZVNoYXBlRGVmYXVsdHNcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZVNoYXBlRGVmYXVsdHMoc2hhcGVJbiwgc2hhcGVPdXQsIGZ1bGxMYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShzaGFwZUluLCBzaGFwZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcblxuICAgIGlmKCF2aXNpYmxlKSByZXR1cm47XG5cbiAgICBjb2VyY2UoJ2xheWVyJyk7XG4gICAgY29lcmNlKCdvcGFjaXR5Jyk7XG4gICAgY29lcmNlKCdmaWxsY29sb3InKTtcbiAgICBjb2VyY2UoJ2xpbmUuY29sb3InKTtcbiAgICBjb2VyY2UoJ2xpbmUud2lkdGgnKTtcbiAgICBjb2VyY2UoJ2xpbmUuZGFzaCcpO1xuXG4gICAgdmFyIGRmbHRUeXBlID0gc2hhcGVJbi5wYXRoID8gJ3BhdGgnIDogJ3JlY3QnO1xuICAgIHZhciBzaGFwZVR5cGUgPSBjb2VyY2UoJ3R5cGUnLCBkZmx0VHlwZSk7XG4gICAgdmFyIHhTaXplTW9kZSA9IGNvZXJjZSgneHNpemVtb2RlJyk7XG4gICAgdmFyIHlTaXplTW9kZSA9IGNvZXJjZSgneXNpemVtb2RlJyk7XG5cbiAgICAvLyBwb3NpdGlvbmluZ1xuICAgIHZhciBheExldHRlcnMgPSBbJ3gnLCAneSddO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhMZXR0ZXJzW2ldO1xuICAgICAgICB2YXIgYXR0ckFuY2hvciA9IGF4TGV0dGVyICsgJ2FuY2hvcic7XG4gICAgICAgIHZhciBzaXplTW9kZSA9IGF4TGV0dGVyID09PSAneCcgPyB4U2l6ZU1vZGUgOiB5U2l6ZU1vZGU7XG4gICAgICAgIHZhciBnZE1vY2sgPSB7X2Z1bGxMYXlvdXQ6IGZ1bGxMYXlvdXR9O1xuICAgICAgICB2YXIgYXg7XG4gICAgICAgIHZhciBwb3MycjtcbiAgICAgICAgdmFyIHIycG9zO1xuXG4gICAgICAgIC8vIHhyZWYsIHlyZWZcbiAgICAgICAgdmFyIGF4UmVmID0gQXhlcy5jb2VyY2VSZWYoc2hhcGVJbiwgc2hhcGVPdXQsIGdkTW9jaywgYXhMZXR0ZXIsICcnLCAncGFwZXInKTtcblxuICAgICAgICBpZihheFJlZiAhPT0gJ3BhcGVyJykge1xuICAgICAgICAgICAgYXggPSBBeGVzLmdldEZyb21JZChnZE1vY2ssIGF4UmVmKTtcbiAgICAgICAgICAgIGF4Ll9zaGFwZUluZGljZXMucHVzaChzaGFwZU91dC5faW5kZXgpO1xuICAgICAgICAgICAgcjJwb3MgPSBoZWxwZXJzLnJhbmdlVG9TaGFwZVBvc2l0aW9uKGF4KTtcbiAgICAgICAgICAgIHBvczJyID0gaGVscGVycy5zaGFwZVBvc2l0aW9uVG9SYW5nZShheCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwb3MyciA9IHIycG9zID0gTGliLmlkZW50aXR5O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29lcmNlIHgwLCB4MSwgeTAsIHkxXG4gICAgICAgIGlmKHNoYXBlVHlwZSAhPT0gJ3BhdGgnKSB7XG4gICAgICAgICAgICB2YXIgZGZsdDAgPSAwLjI1O1xuICAgICAgICAgICAgdmFyIGRmbHQxID0gMC43NTtcblxuICAgICAgICAgICAgLy8gaGFjayB1bnRpbCBWMi4wIHdoZW4gbG9nIGhhcyByZWd1bGFyIHJhbmdlIGJlaGF2aW9yIC0gbWFrZSBpdCBsb29rIGxpa2Ugb3RoZXJcbiAgICAgICAgICAgIC8vIHJhbmdlcyB0byBzZW5kIHRvIGNvZXJjZSwgdGhlbiBwdXQgaXQgYmFjayBhZnRlclxuICAgICAgICAgICAgLy8gdGhpcyBpcyBhbGwgdG8gZ2l2ZSByZWFzb25hYmxlIGRlZmF1bHQgcG9zaXRpb24gYmVoYXZpb3Igb24gbG9nIGF4ZXMsIHdoaWNoIGlzXG4gICAgICAgICAgICAvLyBhIHByZXR0eSB1bmltcG9ydGFudCBlZGdlIGNhc2Ugc28gd2UgY291bGQganVzdCBpZ25vcmUgdGhpcy5cbiAgICAgICAgICAgIHZhciBhdHRyMCA9IGF4TGV0dGVyICsgJzAnO1xuICAgICAgICAgICAgdmFyIGF0dHIxID0gYXhMZXR0ZXIgKyAnMSc7XG4gICAgICAgICAgICB2YXIgaW4wID0gc2hhcGVJblthdHRyMF07XG4gICAgICAgICAgICB2YXIgaW4xID0gc2hhcGVJblthdHRyMV07XG4gICAgICAgICAgICBzaGFwZUluW2F0dHIwXSA9IHBvczJyKHNoYXBlSW5bYXR0cjBdLCB0cnVlKTtcbiAgICAgICAgICAgIHNoYXBlSW5bYXR0cjFdID0gcG9zMnIoc2hhcGVJblthdHRyMV0sIHRydWUpO1xuXG4gICAgICAgICAgICBpZihzaXplTW9kZSA9PT0gJ3BpeGVsJykge1xuICAgICAgICAgICAgICAgIGNvZXJjZShhdHRyMCwgMCk7XG4gICAgICAgICAgICAgICAgY29lcmNlKGF0dHIxLCAxMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIEF4ZXMuY29lcmNlUG9zaXRpb24oc2hhcGVPdXQsIGdkTW9jaywgY29lcmNlLCBheFJlZiwgYXR0cjAsIGRmbHQwKTtcbiAgICAgICAgICAgICAgICBBeGVzLmNvZXJjZVBvc2l0aW9uKHNoYXBlT3V0LCBnZE1vY2ssIGNvZXJjZSwgYXhSZWYsIGF0dHIxLCBkZmx0MSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGhhY2sgcGFydCAyXG4gICAgICAgICAgICBzaGFwZU91dFthdHRyMF0gPSByMnBvcyhzaGFwZU91dFthdHRyMF0pO1xuICAgICAgICAgICAgc2hhcGVPdXRbYXR0cjFdID0gcjJwb3Moc2hhcGVPdXRbYXR0cjFdKTtcbiAgICAgICAgICAgIHNoYXBlSW5bYXR0cjBdID0gaW4wO1xuICAgICAgICAgICAgc2hhcGVJblthdHRyMV0gPSBpbjE7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb2VyY2UgeGFuY2hvciBhbmQgeWFuY2hvclxuICAgICAgICBpZihzaXplTW9kZSA9PT0gJ3BpeGVsJykge1xuICAgICAgICAgICAgLy8gSGFjayBmb3IgbG9nIGF4aXMgZGVzY3JpYmVkIGFib3ZlXG4gICAgICAgICAgICB2YXIgaW5BbmNob3IgPSBzaGFwZUluW2F0dHJBbmNob3JdO1xuICAgICAgICAgICAgc2hhcGVJblthdHRyQW5jaG9yXSA9IHBvczJyKHNoYXBlSW5bYXR0ckFuY2hvcl0sIHRydWUpO1xuXG4gICAgICAgICAgICBBeGVzLmNvZXJjZVBvc2l0aW9uKHNoYXBlT3V0LCBnZE1vY2ssIGNvZXJjZSwgYXhSZWYsIGF0dHJBbmNob3IsIDAuMjUpO1xuXG4gICAgICAgICAgICAvLyBIYWNrIHBhcnQgMlxuICAgICAgICAgICAgc2hhcGVPdXRbYXR0ckFuY2hvcl0gPSByMnBvcyhzaGFwZU91dFthdHRyQW5jaG9yXSk7XG4gICAgICAgICAgICBzaGFwZUluW2F0dHJBbmNob3JdID0gaW5BbmNob3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihzaGFwZVR5cGUgPT09ICdwYXRoJykge1xuICAgICAgICBjb2VyY2UoJ3BhdGgnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBMaWIubm9uZU9yQWxsKHNoYXBlSW4sIHNoYXBlT3V0LCBbJ3gwJywgJ3gxJywgJ3kwJywgJ3kxJ10pO1xuICAgIH1cbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHNcIjo3NjMsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4vYXR0cmlidXRlc1wiOjY2OSxcIi4vaGVscGVyc1wiOjY3NH1dLDY3MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uL2RyYXdpbmcnKTtcbnZhciBhcnJheUVkaXRvciA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKS5hcnJheUVkaXRvcjtcblxudmFyIGRyYWdFbGVtZW50ID0gX2RlcmVxXygnLi4vZHJhZ2VsZW1lbnQnKTtcbnZhciBzZXRDdXJzb3IgPSBfZGVyZXFfKCcuLi8uLi9saWIvc2V0Y3Vyc29yJyk7XG5cbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIGhlbHBlcnMgPSBfZGVyZXFfKCcuL2hlbHBlcnMnKTtcblxuXG4vLyBTaGFwZXMgYXJlIHN0b3JlZCBpbiBnZC5sYXlvdXQuc2hhcGVzLCBhbiBhcnJheSBvZiBvYmplY3RzXG4vLyBpbmRleCBjYW4gcG9pbnQgdG8gb25lIGl0ZW0gaW4gdGhpcyBhcnJheSxcbi8vICBvciBub24tbnVtZXJpYyB0byBzaW1wbHkgYWRkIGEgbmV3IG9uZVxuLy8gIG9yIC0xIHRvIG1vZGlmeSBhbGwgZXhpc3Rpbmdcbi8vIG9wdCBjYW4gYmUgdGhlIGZ1bGwgb3B0aW9ucyBvYmplY3QsIG9yIG9uZSBrZXkgKHRvIGJlIHNldCB0byB2YWx1ZSlcbi8vICBvciB1bmRlZmluZWQgdG8gc2ltcGx5IHJlZHJhd1xuLy8gaWYgb3B0IGlzIGJsYW5rLCB2YWwgY2FuIGJlICdhZGQnIG9yIGEgZnVsbCBvcHRpb25zIG9iamVjdCB0byBhZGQgYSBuZXdcbi8vICBhbm5vdGF0aW9uIGF0IHRoYXQgcG9pbnQgaW4gdGhlIGFycmF5LCBvciAncmVtb3ZlJyB0byBkZWxldGUgdGhpcyBvbmVcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZHJhdzogZHJhdyxcbiAgICBkcmF3T25lOiBkcmF3T25lXG59O1xuXG5mdW5jdGlvbiBkcmF3KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIC8vIFJlbW92ZSBwcmV2aW91cyBzaGFwZXMgYmVmb3JlIGRyYXdpbmcgbmV3IGluIHNoYXBlcyBpbiBmdWxsTGF5b3V0LnNoYXBlc1xuICAgIGZ1bGxMYXlvdXQuX3NoYXBlVXBwZXJMYXllci5zZWxlY3RBbGwoJ3BhdGgnKS5yZW1vdmUoKTtcbiAgICBmdWxsTGF5b3V0Ll9zaGFwZUxvd2VyTGF5ZXIuc2VsZWN0QWxsKCdwYXRoJykucmVtb3ZlKCk7XG5cbiAgICBmb3IodmFyIGsgaW4gZnVsbExheW91dC5fcGxvdHMpIHtcbiAgICAgICAgdmFyIHNoYXBlbGF5ZXIgPSBmdWxsTGF5b3V0Ll9wbG90c1trXS5zaGFwZWxheWVyO1xuICAgICAgICBpZihzaGFwZWxheWVyKSBzaGFwZWxheWVyLnNlbGVjdEFsbCgncGF0aCcpLnJlbW92ZSgpO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsTGF5b3V0LnNoYXBlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihmdWxsTGF5b3V0LnNoYXBlc1tpXS52aXNpYmxlKSB7XG4gICAgICAgICAgICBkcmF3T25lKGdkLCBpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG1heSBuZWVkIHRvIHJlc3VycmVjdCB0aGlzIGlmIHdlIHB1dCB0ZXh0IChMYVRlWCkgaW4gc2hhcGVzXG4gICAgLy8gcmV0dXJuIFBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpO1xufVxuXG5mdW5jdGlvbiBkcmF3T25lKGdkLCBpbmRleCkge1xuICAgIC8vIHJlbW92ZSB0aGUgZXhpc3Rpbmcgc2hhcGUgaWYgdGhlcmUgaXMgb25lLlxuICAgIC8vIGJlY2F1c2UgaW5kaWNlcyBjYW4gY2hhbmdlLCB3ZSBuZWVkIHRvIGxvb2sgaW4gYWxsIHNoYXBlIGxheWVyc1xuICAgIGdkLl9mdWxsTGF5b3V0Ll9wYXBlcmRpdlxuICAgICAgICAuc2VsZWN0QWxsKCcuc2hhcGVsYXllciBbZGF0YS1pbmRleD1cIicgKyBpbmRleCArICdcIl0nKVxuICAgICAgICAucmVtb3ZlKCk7XG5cbiAgICB2YXIgb3B0aW9ucyA9IGdkLl9mdWxsTGF5b3V0LnNoYXBlc1tpbmRleF0gfHwge307XG5cbiAgICAvLyB0aGlzIHNoYXBlIGlzIGdvbmUgLSBxdWl0IG5vdyBhZnRlciBkZWxldGluZyBpdFxuICAgIC8vIFRPRE86IHVzZSBkMyBpZGlvbXMgaW5zdGVhZCBvZiBkZWxldGluZyBhbmQgcmVkcmF3aW5nIGV2ZXJ5IHRpbWVcbiAgICBpZighb3B0aW9ucy5faW5wdXQgfHwgb3B0aW9ucy52aXNpYmxlID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgaWYob3B0aW9ucy5sYXllciAhPT0gJ2JlbG93Jykge1xuICAgICAgICBkcmF3U2hhcGUoZ2QuX2Z1bGxMYXlvdXQuX3NoYXBlVXBwZXJMYXllcik7XG4gICAgfSBlbHNlIGlmKG9wdGlvbnMueHJlZiA9PT0gJ3BhcGVyJyB8fCBvcHRpb25zLnlyZWYgPT09ICdwYXBlcicpIHtcbiAgICAgICAgZHJhd1NoYXBlKGdkLl9mdWxsTGF5b3V0Ll9zaGFwZUxvd2VyTGF5ZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBwbG90aW5mbyA9IGdkLl9mdWxsTGF5b3V0Ll9wbG90c1tvcHRpb25zLnhyZWYgKyBvcHRpb25zLnlyZWZdO1xuICAgICAgICBpZihwbG90aW5mbykge1xuICAgICAgICAgICAgdmFyIG1haW5QbG90ID0gcGxvdGluZm8ubWFpbnBsb3RpbmZvIHx8IHBsb3RpbmZvO1xuICAgICAgICAgICAgZHJhd1NoYXBlKG1haW5QbG90LnNoYXBlbGF5ZXIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gRmFsbCBiYWNrIHRvIF9zaGFwZUxvd2VyTGF5ZXIgaW4gY2FzZSB0aGUgcmVxdWVzdGVkIHN1YnBsb3QgZG9lc24ndCBleGlzdC5cbiAgICAgICAgICAgIC8vIFRoaXMgY2FuIGhhcHBlbiBpZiB5b3UgcmVmZXJlbmNlIHRoZSBzaGFwZSB0byBhbiB4IC8geSBheGlzIGNvbWJpbmF0aW9uXG4gICAgICAgICAgICAvLyB0aGF0IGRvZXNuJ3QgaGF2ZSBhbnkgZGF0YSBvbiBpdCAoYW5kIGxheWVyIGlzIGJlbG93KVxuICAgICAgICAgICAgZHJhd1NoYXBlKGdkLl9mdWxsTGF5b3V0Ll9zaGFwZUxvd2VyTGF5ZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1NoYXBlKHNoYXBlTGF5ZXIpIHtcbiAgICAgICAgdmFyIGF0dHJzID0ge1xuICAgICAgICAgICAgJ2RhdGEtaW5kZXgnOiBpbmRleCxcbiAgICAgICAgICAgICdmaWxsLXJ1bGUnOiAnZXZlbm9kZCcsXG4gICAgICAgICAgICBkOiBnZXRQYXRoU3RyaW5nKGdkLCBvcHRpb25zKVxuICAgICAgICB9O1xuICAgICAgICB2YXIgbGluZUNvbG9yID0gb3B0aW9ucy5saW5lLndpZHRoID8gb3B0aW9ucy5saW5lLmNvbG9yIDogJ3JnYmEoMCwwLDAsMCknO1xuXG4gICAgICAgIHZhciBwYXRoID0gc2hhcGVMYXllci5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgLmF0dHIoYXR0cnMpXG4gICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCBvcHRpb25zLm9wYWNpdHkpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIGxpbmVDb2xvcilcbiAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIG9wdGlvbnMuZmlsbGNvbG9yKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5kYXNoTGluZSwgb3B0aW9ucy5saW5lLmRhc2gsIG9wdGlvbnMubGluZS53aWR0aCk7XG5cbiAgICAgICAgc2V0Q2xpcFBhdGgocGF0aCwgZ2QsIG9wdGlvbnMpO1xuXG4gICAgICAgIGlmKGdkLl9jb250ZXh0LmVkaXRzLnNoYXBlUG9zaXRpb24pIHNldHVwRHJhZ0VsZW1lbnQoZ2QsIHBhdGgsIG9wdGlvbnMsIGluZGV4LCBzaGFwZUxheWVyKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldENsaXBQYXRoKHNoYXBlUGF0aCwgZ2QsIHNoYXBlT3B0aW9ucykge1xuICAgIC8vIG5vdGUgdGhhdCBmb3IgbGF5ZXI9XCJiZWxvd1wiIHRoZSBjbGlwQXhlcyBjYW4gYmUgZGlmZmVyZW50IGZyb20gdGhlXG4gICAgLy8gc3VicGxvdCB3ZSdyZSBkcmF3aW5nIHRoaXMgaW4uIFRoaXMgY291bGQgY2F1c2UgcHJvYmxlbXMgaWYgdGhlIHNoYXBlXG4gICAgLy8gc3BhbnMgdHdvIHN1YnBsb3RzLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzE0NTJcbiAgICB2YXIgY2xpcEF4ZXMgPSAoc2hhcGVPcHRpb25zLnhyZWYgKyBzaGFwZU9wdGlvbnMueXJlZikucmVwbGFjZSgvcGFwZXIvZywgJycpO1xuXG4gICAgRHJhd2luZy5zZXRDbGlwVXJsKFxuICAgICAgICBzaGFwZVBhdGgsXG4gICAgICAgIGNsaXBBeGVzID8gJ2NsaXAnICsgZ2QuX2Z1bGxMYXlvdXQuX3VpZCArIGNsaXBBeGVzIDogbnVsbCxcbiAgICAgICAgZ2RcbiAgICApO1xufVxuXG5mdW5jdGlvbiBzZXR1cERyYWdFbGVtZW50KGdkLCBzaGFwZVBhdGgsIHNoYXBlT3B0aW9ucywgaW5kZXgsIHNoYXBlTGF5ZXIpIHtcbiAgICB2YXIgTUlOV0lEVEggPSAxMDtcbiAgICB2YXIgTUlOSEVJR0hUID0gMTA7XG5cbiAgICB2YXIgeFBpeGVsU2l6ZWQgPSBzaGFwZU9wdGlvbnMueHNpemVtb2RlID09PSAncGl4ZWwnO1xuICAgIHZhciB5UGl4ZWxTaXplZCA9IHNoYXBlT3B0aW9ucy55c2l6ZW1vZGUgPT09ICdwaXhlbCc7XG4gICAgdmFyIGlzTGluZSA9IHNoYXBlT3B0aW9ucy50eXBlID09PSAnbGluZSc7XG4gICAgdmFyIGlzUGF0aCA9IHNoYXBlT3B0aW9ucy50eXBlID09PSAncGF0aCc7XG5cbiAgICB2YXIgZWRpdEhlbHBlcnMgPSBhcnJheUVkaXRvcihnZC5sYXlvdXQsICdzaGFwZXMnLCBzaGFwZU9wdGlvbnMpO1xuICAgIHZhciBtb2RpZnlJdGVtID0gZWRpdEhlbHBlcnMubW9kaWZ5SXRlbTtcblxuICAgIHZhciB4MCwgeTAsIHgxLCB5MSwgeEFuY2hvciwgeUFuY2hvcjtcbiAgICB2YXIgbjAsIHMwLCB3MCwgZTAsIG9wdE4sIG9wdFMsIG9wdFcsIG9wdEU7XG4gICAgdmFyIHBhdGhJbjtcblxuICAgIC8vIHNldHVwIGNvbnZlcnNpb24gZnVuY3Rpb25zXG4gICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHNoYXBlT3B0aW9ucy54cmVmKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgc2hhcGVPcHRpb25zLnlyZWYpO1xuICAgIHZhciB4MnAgPSBoZWxwZXJzLmdldERhdGFUb1BpeGVsKGdkLCB4YSk7XG4gICAgdmFyIHkycCA9IGhlbHBlcnMuZ2V0RGF0YVRvUGl4ZWwoZ2QsIHlhLCB0cnVlKTtcbiAgICB2YXIgcDJ4ID0gaGVscGVycy5nZXRQaXhlbFRvRGF0YShnZCwgeGEpO1xuICAgIHZhciBwMnkgPSBoZWxwZXJzLmdldFBpeGVsVG9EYXRhKGdkLCB5YSwgdHJ1ZSk7XG5cbiAgICB2YXIgc2Vuc29yeUVsZW1lbnQgPSBvYnRhaW5TZW5zb3J5RWxlbWVudCgpO1xuICAgIHZhciBkcmFnT3B0aW9ucyA9IHtcbiAgICAgICAgZWxlbWVudDogc2Vuc29yeUVsZW1lbnQubm9kZSgpLFxuICAgICAgICBnZDogZ2QsXG4gICAgICAgIHByZXBGbjogc3RhcnREcmFnLFxuICAgICAgICBkb25lRm46IGVuZERyYWcsXG4gICAgICAgIGNsaWNrRm46IGFib3J0RHJhZ1xuICAgIH07XG4gICAgdmFyIGRyYWdNb2RlO1xuXG4gICAgZHJhZ0VsZW1lbnQuaW5pdChkcmFnT3B0aW9ucyk7XG5cbiAgICBzZW5zb3J5RWxlbWVudC5ub2RlKCkub25tb3VzZW1vdmUgPSB1cGRhdGVEcmFnTW9kZTtcblxuICAgIGZ1bmN0aW9uIG9idGFpblNlbnNvcnlFbGVtZW50KCkge1xuICAgICAgICByZXR1cm4gaXNMaW5lID8gY3JlYXRlTGluZURyYWdIYW5kbGVzKCkgOiBzaGFwZVBhdGg7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlTGluZURyYWdIYW5kbGVzKCkge1xuICAgICAgICB2YXIgbWluU2Vuc29yeVdpZHRoID0gMTA7XG4gICAgICAgIHZhciBzZW5zb3J5V2lkdGggPSBNYXRoLm1heChzaGFwZU9wdGlvbnMubGluZS53aWR0aCwgbWluU2Vuc29yeVdpZHRoKTtcblxuICAgICAgICAvLyBIZWxwZXIgc2hhcGVzIGdyb3VwXG4gICAgICAgIC8vIE5vdGUgdGhhdCBieSBzZXR0aW5nIHRoZSBgZGF0YS1pbmRleGAgYXR0ciwgaXQgaXMgZW5zdXJlZCB0aGF0XG4gICAgICAgIC8vIHRoZSBoZWxwZXIgZ3JvdXAgaXMgcHVyZ2VkIGluIHRoaXMgbW9kdWxlcyBgZHJhd2AgZnVuY3Rpb25cbiAgICAgICAgdmFyIGcgPSBzaGFwZUxheWVyLmFwcGVuZCgnZycpXG4gICAgICAgICAgLmF0dHIoJ2RhdGEtaW5kZXgnLCBpbmRleCk7XG5cbiAgICAgICAgLy8gSGVscGVyIHBhdGggZm9yIG1vdmluZ1xuICAgICAgICBnLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgLmF0dHIoJ2QnLCBzaGFwZVBhdGguYXR0cignZCcpKVxuICAgICAgICAgIC5zdHlsZSh7XG4gICAgICAgICAgICAgICdjdXJzb3InOiAnbW92ZScsXG4gICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiBzZW5zb3J5V2lkdGgsXG4gICAgICAgICAgICAgICdzdHJva2Utb3BhY2l0eSc6ICcwJyAvLyBlbnN1cmUgbm90IHZpc2libGVcbiAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBIZWxwZXIgY2lyY2xlcyBmb3IgcmVzaXppbmdcbiAgICAgICAgdmFyIGNpcmNsZVN0eWxlID0ge1xuICAgICAgICAgICAgJ2ZpbGwtb3BhY2l0eSc6ICcwJyAvLyBlbnN1cmUgbm90IHZpc2libGVcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNpcmNsZVJhZGl1cyA9IHNlbnNvcnlXaWR0aCAvIDIgPiBtaW5TZW5zb3J5V2lkdGggPyBzZW5zb3J5V2lkdGggLyAyIDogbWluU2Vuc29yeVdpZHRoO1xuXG4gICAgICAgIGcuYXBwZW5kKCdjaXJjbGUnKVxuICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgJ2RhdGEtbGluZS1wb2ludCc6ICdzdGFydC1wb2ludCcsXG4gICAgICAgICAgICAgICdjeCc6IHhQaXhlbFNpemVkID8geDJwKHNoYXBlT3B0aW9ucy54YW5jaG9yKSArIHNoYXBlT3B0aW9ucy54MCA6IHgycChzaGFwZU9wdGlvbnMueDApLFxuICAgICAgICAgICAgICAnY3knOiB5UGl4ZWxTaXplZCA/IHkycChzaGFwZU9wdGlvbnMueWFuY2hvcikgLSBzaGFwZU9wdGlvbnMueTAgOiB5MnAoc2hhcGVPcHRpb25zLnkwKSxcbiAgICAgICAgICAgICAgJ3InOiBjaXJjbGVSYWRpdXNcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5zdHlsZShjaXJjbGVTdHlsZSlcbiAgICAgICAgICAuY2xhc3NlZCgnY3Vyc29yLWdyYWInLCB0cnVlKTtcblxuICAgICAgICBnLmFwcGVuZCgnY2lyY2xlJylcbiAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICdkYXRhLWxpbmUtcG9pbnQnOiAnZW5kLXBvaW50JyxcbiAgICAgICAgICAgICAgJ2N4JzogeFBpeGVsU2l6ZWQgPyB4MnAoc2hhcGVPcHRpb25zLnhhbmNob3IpICsgc2hhcGVPcHRpb25zLngxIDogeDJwKHNoYXBlT3B0aW9ucy54MSksXG4gICAgICAgICAgICAgICdjeSc6IHlQaXhlbFNpemVkID8geTJwKHNoYXBlT3B0aW9ucy55YW5jaG9yKSAtIHNoYXBlT3B0aW9ucy55MSA6IHkycChzaGFwZU9wdGlvbnMueTEpLFxuICAgICAgICAgICAgICAncic6IGNpcmNsZVJhZGl1c1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnN0eWxlKGNpcmNsZVN0eWxlKVxuICAgICAgICAgIC5jbGFzc2VkKCdjdXJzb3ItZ3JhYicsIHRydWUpO1xuXG4gICAgICAgIHJldHVybiBnO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZURyYWdNb2RlKGV2dCkge1xuICAgICAgICBpZihpc0xpbmUpIHtcbiAgICAgICAgICAgIGlmKGV2dC50YXJnZXQudGFnTmFtZSA9PT0gJ3BhdGgnKSB7XG4gICAgICAgICAgICAgICAgZHJhZ01vZGUgPSAnbW92ZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRyYWdNb2RlID0gZXZ0LnRhcmdldC5hdHRyaWJ1dGVzWydkYXRhLWxpbmUtcG9pbnQnXS52YWx1ZSA9PT0gJ3N0YXJ0LXBvaW50JyA/XG4gICAgICAgICAgICAgICAgICAncmVzaXplLW92ZXItc3RhcnQtcG9pbnQnIDogJ3Jlc2l6ZS1vdmVyLWVuZC1wb2ludCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBlbGVtZW50IG1pZ2h0IG5vdCBiZSBvbiBzY3JlZW4gYXQgdGltZSBvZiBzZXR1cCxcbiAgICAgICAgICAgIC8vIHNvIG9idGFpbiBib3VuZGluZyBib3ggaGVyZVxuICAgICAgICAgICAgdmFyIGRyYWdCQm94ID0gZHJhZ09wdGlvbnMuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgICAgICAgLy8gY2hvb3NlICdtb3ZlJyBvciAncmVzaXplJ1xuICAgICAgICAgICAgLy8gYmFzZWQgb24gaW5pdGlhbCBwb3NpdGlvbiBvZiBjdXJzb3Igd2l0aGluIHRoZSBkcmFnIGVsZW1lbnRcbiAgICAgICAgICAgIHZhciB3ID0gZHJhZ0JCb3gucmlnaHQgLSBkcmFnQkJveC5sZWZ0O1xuICAgICAgICAgICAgdmFyIGggPSBkcmFnQkJveC5ib3R0b20gLSBkcmFnQkJveC50b3A7XG4gICAgICAgICAgICB2YXIgeCA9IGV2dC5jbGllbnRYIC0gZHJhZ0JCb3gubGVmdDtcbiAgICAgICAgICAgIHZhciB5ID0gZXZ0LmNsaWVudFkgLSBkcmFnQkJveC50b3A7XG4gICAgICAgICAgICB2YXIgY3Vyc29yID0gKCFpc1BhdGggJiYgdyA+IE1JTldJRFRIICYmIGggPiBNSU5IRUlHSFQgJiYgIWV2dC5zaGlmdEtleSkgP1xuICAgICAgICAgICAgICAgIGRyYWdFbGVtZW50LmdldEN1cnNvcih4IC8gdywgMSAtIHkgLyBoKSA6XG4gICAgICAgICAgICAgICAgJ21vdmUnO1xuXG4gICAgICAgICAgICBzZXRDdXJzb3Ioc2hhcGVQYXRoLCBjdXJzb3IpO1xuXG4gICAgICAgICAgICAvLyBwb3NzaWJsZSB2YWx1ZXMgJ21vdmUnLCAnc3cnLCAndycsICdzZScsICdlJywgJ25lJywgJ24nLCAnbncnIGFuZCAndydcbiAgICAgICAgICAgIGRyYWdNb2RlID0gY3Vyc29yLnNwbGl0KCctJylbMF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzdGFydERyYWcoZXZ0KSB7XG4gICAgICAgIC8vIHNldHVwIHVwZGF0ZSBzdHJpbmdzIGFuZCBpbml0aWFsIHZhbHVlc1xuICAgICAgICBpZih4UGl4ZWxTaXplZCkge1xuICAgICAgICAgICAgeEFuY2hvciA9IHgycChzaGFwZU9wdGlvbnMueGFuY2hvcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYoeVBpeGVsU2l6ZWQpIHtcbiAgICAgICAgICAgIHlBbmNob3IgPSB5MnAoc2hhcGVPcHRpb25zLnlhbmNob3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoc2hhcGVPcHRpb25zLnR5cGUgPT09ICdwYXRoJykge1xuICAgICAgICAgICAgcGF0aEluID0gc2hhcGVPcHRpb25zLnBhdGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB4MCA9IHhQaXhlbFNpemVkID8gc2hhcGVPcHRpb25zLngwIDogeDJwKHNoYXBlT3B0aW9ucy54MCk7XG4gICAgICAgICAgICB5MCA9IHlQaXhlbFNpemVkID8gc2hhcGVPcHRpb25zLnkwIDogeTJwKHNoYXBlT3B0aW9ucy55MCk7XG4gICAgICAgICAgICB4MSA9IHhQaXhlbFNpemVkID8gc2hhcGVPcHRpb25zLngxIDogeDJwKHNoYXBlT3B0aW9ucy54MSk7XG4gICAgICAgICAgICB5MSA9IHlQaXhlbFNpemVkID8gc2hhcGVPcHRpb25zLnkxIDogeTJwKHNoYXBlT3B0aW9ucy55MSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih4MCA8IHgxKSB7XG4gICAgICAgICAgICB3MCA9IHgwO1xuICAgICAgICAgICAgb3B0VyA9ICd4MCc7XG4gICAgICAgICAgICBlMCA9IHgxO1xuICAgICAgICAgICAgb3B0RSA9ICd4MSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3MCA9IHgxO1xuICAgICAgICAgICAgb3B0VyA9ICd4MSc7XG4gICAgICAgICAgICBlMCA9IHgwO1xuICAgICAgICAgICAgb3B0RSA9ICd4MCc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGb3IgZml4ZWQgc2l6ZSBzaGFwZXMgdGFrZSBvcHBvc2luZyBkaXJlY3Rpb24gb2YgeS1heGlzIGludG8gYWNjb3VudC5cbiAgICAgICAgLy8gSGludDogRm9yIGRhdGEgc2l6ZWQgc2hhcGVzIHRoaXMgaXMgZG9uZSBieSB0aGUgeTJwIGZ1bmN0aW9uLlxuICAgICAgICBpZigoIXlQaXhlbFNpemVkICYmIHkwIDwgeTEpIHx8ICh5UGl4ZWxTaXplZCAmJiB5MCA+IHkxKSkge1xuICAgICAgICAgICAgbjAgPSB5MDtcbiAgICAgICAgICAgIG9wdE4gPSAneTAnO1xuICAgICAgICAgICAgczAgPSB5MTtcbiAgICAgICAgICAgIG9wdFMgPSAneTEnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbjAgPSB5MTtcbiAgICAgICAgICAgIG9wdE4gPSAneTEnO1xuICAgICAgICAgICAgczAgPSB5MDtcbiAgICAgICAgICAgIG9wdFMgPSAneTAnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc2V0dXAgZHJhZ01vZGUgYW5kIHRoZSBjb3JyZXNwb25kaW5nIGhhbmRsZXJcbiAgICAgICAgdXBkYXRlRHJhZ01vZGUoZXZ0KTtcbiAgICAgICAgcmVuZGVyVmlzdWFsQ3VlcyhzaGFwZUxheWVyLCBzaGFwZU9wdGlvbnMpO1xuICAgICAgICBkZWFjdGl2YXRlQ2xpcFBhdGhUZW1wb3JhcmlseShzaGFwZVBhdGgsIHNoYXBlT3B0aW9ucywgZ2QpO1xuICAgICAgICBkcmFnT3B0aW9ucy5tb3ZlRm4gPSAoZHJhZ01vZGUgPT09ICdtb3ZlJykgPyBtb3ZlU2hhcGUgOiByZXNpemVTaGFwZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbmREcmFnKCkge1xuICAgICAgICBzZXRDdXJzb3Ioc2hhcGVQYXRoKTtcbiAgICAgICAgcmVtb3ZlVmlzdWFsQ3VlcyhzaGFwZUxheWVyKTtcblxuICAgICAgICAvLyBEb24ndCByZWx5IG9uIGNsaXBQYXRoIGJlaW5nIGFjdGl2YXRlZCBkdXJpbmcgcmUtbGF5b3V0XG4gICAgICAgIHNldENsaXBQYXRoKHNoYXBlUGF0aCwgZ2QsIHNoYXBlT3B0aW9ucyk7XG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCBlZGl0SGVscGVycy5nZXRVcGRhdGVPYmooKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWJvcnREcmFnKCkge1xuICAgICAgICByZW1vdmVWaXN1YWxDdWVzKHNoYXBlTGF5ZXIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vdmVTaGFwZShkeCwgZHkpIHtcbiAgICAgICAgaWYoc2hhcGVPcHRpb25zLnR5cGUgPT09ICdwYXRoJykge1xuICAgICAgICAgICAgdmFyIG5vT3AgPSBmdW5jdGlvbihjb29yZCkgeyByZXR1cm4gY29vcmQ7IH07XG4gICAgICAgICAgICB2YXIgbW92ZVggPSBub09wO1xuICAgICAgICAgICAgdmFyIG1vdmVZID0gbm9PcDtcblxuICAgICAgICAgICAgaWYoeFBpeGVsU2l6ZWQpIHtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd4YW5jaG9yJywgc2hhcGVPcHRpb25zLnhhbmNob3IgPSBwMngoeEFuY2hvciArIGR4KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vdmVYID0gZnVuY3Rpb24gbW92ZVgoeCkgeyByZXR1cm4gcDJ4KHgycCh4KSArIGR4KTsgfTtcbiAgICAgICAgICAgICAgICBpZih4YSAmJiB4YS50eXBlID09PSAnZGF0ZScpIG1vdmVYID0gaGVscGVycy5lbmNvZGVEYXRlKG1vdmVYKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoeVBpeGVsU2l6ZWQpIHtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd5YW5jaG9yJywgc2hhcGVPcHRpb25zLnlhbmNob3IgPSBwMnkoeUFuY2hvciArIGR5KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vdmVZID0gZnVuY3Rpb24gbW92ZVkoeSkgeyByZXR1cm4gcDJ5KHkycCh5KSArIGR5KTsgfTtcbiAgICAgICAgICAgICAgICBpZih5YSAmJiB5YS50eXBlID09PSAnZGF0ZScpIG1vdmVZID0gaGVscGVycy5lbmNvZGVEYXRlKG1vdmVZKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbW9kaWZ5SXRlbSgncGF0aCcsIHNoYXBlT3B0aW9ucy5wYXRoID0gbW92ZVBhdGgocGF0aEluLCBtb3ZlWCwgbW92ZVkpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKHhQaXhlbFNpemVkKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneGFuY2hvcicsIHNoYXBlT3B0aW9ucy54YW5jaG9yID0gcDJ4KHhBbmNob3IgKyBkeCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd4MCcsIHNoYXBlT3B0aW9ucy54MCA9IHAyeCh4MCArIGR4KSk7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneDEnLCBzaGFwZU9wdGlvbnMueDEgPSBwMngoeDEgKyBkeCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZih5UGl4ZWxTaXplZCkge1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3lhbmNob3InLCBzaGFwZU9wdGlvbnMueWFuY2hvciA9IHAyeSh5QW5jaG9yICsgZHkpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneTAnLCBzaGFwZU9wdGlvbnMueTAgPSBwMnkoeTAgKyBkeSkpO1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3kxJywgc2hhcGVPcHRpb25zLnkxID0gcDJ5KHkxICsgZHkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNoYXBlUGF0aC5hdHRyKCdkJywgZ2V0UGF0aFN0cmluZyhnZCwgc2hhcGVPcHRpb25zKSk7XG4gICAgICAgIHJlbmRlclZpc3VhbEN1ZXMoc2hhcGVMYXllciwgc2hhcGVPcHRpb25zKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNpemVTaGFwZShkeCwgZHkpIHtcbiAgICAgICAgaWYoaXNQYXRoKSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBpbXBsZW1lbnQgcGF0aCByZXNpemUsIGRvbid0IGZvcmdldCB0byB1cGRhdGUgZHJhZ01vZGUgY29kZVxuICAgICAgICAgICAgdmFyIG5vT3AgPSBmdW5jdGlvbihjb29yZCkgeyByZXR1cm4gY29vcmQ7IH07XG4gICAgICAgICAgICB2YXIgbW92ZVggPSBub09wO1xuICAgICAgICAgICAgdmFyIG1vdmVZID0gbm9PcDtcblxuICAgICAgICAgICAgaWYoeFBpeGVsU2l6ZWQpIHtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd4YW5jaG9yJywgc2hhcGVPcHRpb25zLnhhbmNob3IgPSBwMngoeEFuY2hvciArIGR4KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vdmVYID0gZnVuY3Rpb24gbW92ZVgoeCkgeyByZXR1cm4gcDJ4KHgycCh4KSArIGR4KTsgfTtcbiAgICAgICAgICAgICAgICBpZih4YSAmJiB4YS50eXBlID09PSAnZGF0ZScpIG1vdmVYID0gaGVscGVycy5lbmNvZGVEYXRlKG1vdmVYKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoeVBpeGVsU2l6ZWQpIHtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKCd5YW5jaG9yJywgc2hhcGVPcHRpb25zLnlhbmNob3IgPSBwMnkoeUFuY2hvciArIGR5KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1vdmVZID0gZnVuY3Rpb24gbW92ZVkoeSkgeyByZXR1cm4gcDJ5KHkycCh5KSArIGR5KTsgfTtcbiAgICAgICAgICAgICAgICBpZih5YSAmJiB5YS50eXBlID09PSAnZGF0ZScpIG1vdmVZID0gaGVscGVycy5lbmNvZGVEYXRlKG1vdmVZKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbW9kaWZ5SXRlbSgncGF0aCcsIHNoYXBlT3B0aW9ucy5wYXRoID0gbW92ZVBhdGgocGF0aEluLCBtb3ZlWCwgbW92ZVkpKTtcbiAgICAgICAgfSBlbHNlIGlmKGlzTGluZSkge1xuICAgICAgICAgICAgaWYoZHJhZ01vZGUgPT09ICdyZXNpemUtb3Zlci1zdGFydC1wb2ludCcpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3WDAgPSB4MCArIGR4O1xuICAgICAgICAgICAgICAgIHZhciBuZXdZMCA9IHlQaXhlbFNpemVkID8geTAgLSBkeSA6IHkwICsgZHk7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneDAnLCBzaGFwZU9wdGlvbnMueDAgPSB4UGl4ZWxTaXplZCA/IG5ld1gwIDogcDJ4KG5ld1gwKSk7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbSgneTAnLCBzaGFwZU9wdGlvbnMueTAgPSB5UGl4ZWxTaXplZCA/IG5ld1kwIDogcDJ5KG5ld1kwKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoZHJhZ01vZGUgPT09ICdyZXNpemUtb3Zlci1lbmQtcG9pbnQnKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld1gxID0geDEgKyBkeDtcbiAgICAgICAgICAgICAgICB2YXIgbmV3WTEgPSB5UGl4ZWxTaXplZCA/IHkxIC0gZHkgOiB5MSArIGR5O1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3gxJywgc2hhcGVPcHRpb25zLngxID0geFBpeGVsU2l6ZWQgPyBuZXdYMSA6IHAyeChuZXdYMSkpO1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0oJ3kxJywgc2hhcGVPcHRpb25zLnkxID0geVBpeGVsU2l6ZWQgPyBuZXdZMSA6IHAyeShuZXdZMSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIG5ld04gPSAofmRyYWdNb2RlLmluZGV4T2YoJ24nKSkgPyBuMCArIGR5IDogbjA7XG4gICAgICAgICAgICB2YXIgbmV3UyA9ICh+ZHJhZ01vZGUuaW5kZXhPZigncycpKSA/IHMwICsgZHkgOiBzMDtcbiAgICAgICAgICAgIHZhciBuZXdXID0gKH5kcmFnTW9kZS5pbmRleE9mKCd3JykpID8gdzAgKyBkeCA6IHcwO1xuICAgICAgICAgICAgdmFyIG5ld0UgPSAofmRyYWdNb2RlLmluZGV4T2YoJ2UnKSkgPyBlMCArIGR4IDogZTA7XG5cbiAgICAgICAgICAgIC8vIERvIHRoaW5ncyBpbiBvcHBvc2luZyBkaXJlY3Rpb24gZm9yIHktYXhpcy5cbiAgICAgICAgICAgIC8vIEhpbnQ6IGZvciBkYXRhLXNpemVkIHNoYXBlcyB0aGUgcmV2ZXJzYWwgb2YgYXhpcyBkaXJlY3Rpb24gaXMgZG9uZSBpbiBwMnkuXG4gICAgICAgICAgICBpZih+ZHJhZ01vZGUuaW5kZXhPZignbicpICYmIHlQaXhlbFNpemVkKSBuZXdOID0gbjAgLSBkeTtcbiAgICAgICAgICAgIGlmKH5kcmFnTW9kZS5pbmRleE9mKCdzJykgJiYgeVBpeGVsU2l6ZWQpIG5ld1MgPSBzMCAtIGR5O1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgc2hhcGUgZXZlbnR1YWxseS4gQWdhaW4sIGJlIGF3YXJlIG9mIHRoZVxuICAgICAgICAgICAgLy8gb3Bwb3NpbmcgZGlyZWN0aW9uIG9mIHRoZSB5LWF4aXMgb2YgZml4ZWQgc2l6ZSBzaGFwZXMuXG4gICAgICAgICAgICBpZigoIXlQaXhlbFNpemVkICYmIG5ld1MgLSBuZXdOID4gTUlOSEVJR0hUKSB8fFxuICAgICAgICAgICAgICAoeVBpeGVsU2l6ZWQgJiYgbmV3TiAtIG5ld1MgPiBNSU5IRUlHSFQpKSB7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbShvcHROLCBzaGFwZU9wdGlvbnNbb3B0Tl0gPSB5UGl4ZWxTaXplZCA/IG5ld04gOiBwMnkobmV3TikpO1xuICAgICAgICAgICAgICAgIG1vZGlmeUl0ZW0ob3B0Uywgc2hhcGVPcHRpb25zW29wdFNdID0geVBpeGVsU2l6ZWQgPyBuZXdTIDogcDJ5KG5ld1MpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKG5ld0UgLSBuZXdXID4gTUlOV0lEVEgpIHtcbiAgICAgICAgICAgICAgICBtb2RpZnlJdGVtKG9wdFcsIHNoYXBlT3B0aW9uc1tvcHRXXSA9IHhQaXhlbFNpemVkID8gbmV3VyA6IHAyeChuZXdXKSk7XG4gICAgICAgICAgICAgICAgbW9kaWZ5SXRlbShvcHRFLCBzaGFwZU9wdGlvbnNbb3B0RV0gPSB4UGl4ZWxTaXplZCA/IG5ld0UgOiBwMngobmV3RSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2hhcGVQYXRoLmF0dHIoJ2QnLCBnZXRQYXRoU3RyaW5nKGdkLCBzaGFwZU9wdGlvbnMpKTtcbiAgICAgICAgcmVuZGVyVmlzdWFsQ3VlcyhzaGFwZUxheWVyLCBzaGFwZU9wdGlvbnMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbmRlclZpc3VhbEN1ZXMoc2hhcGVMYXllciwgc2hhcGVPcHRpb25zKSB7XG4gICAgICAgIGlmKHhQaXhlbFNpemVkIHx8IHlQaXhlbFNpemVkKSB7XG4gICAgICAgICAgICByZW5kZXJBbmNob3IoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHJlbmRlckFuY2hvcigpIHtcbiAgICAgICAgICAgIHZhciBpc05vdFBhdGggPSBzaGFwZU9wdGlvbnMudHlwZSAhPT0gJ3BhdGgnO1xuXG4gICAgICAgICAgICAvLyBkMyBqb2luIHdpdGggZHVtbXkgZGF0YSB0byBzYXRpc2Z5IGQzIGRhdGEtYmluZGluZ1xuICAgICAgICAgICAgdmFyIHZpc3VhbEN1ZXMgPSBzaGFwZUxheWVyLnNlbGVjdEFsbCgnLnZpc3VhbC1jdWUnKS5kYXRhKFswXSk7XG5cbiAgICAgICAgICAgIC8vIEVudGVyXG4gICAgICAgICAgICB2YXIgc3Ryb2tlV2lkdGggPSAxO1xuICAgICAgICAgICAgdmlzdWFsQ3Vlcy5lbnRlcigpXG4gICAgICAgICAgICAgIC5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAnZmlsbCc6ICcjZmZmJyxcbiAgICAgICAgICAgICAgICAgICdmaWxsLXJ1bGUnOiAnZXZlbm9kZCcsXG4gICAgICAgICAgICAgICAgICAnc3Ryb2tlJzogJyMwMDAnLFxuICAgICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IHN0cm9rZVdpZHRoXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5jbGFzc2VkKCd2aXN1YWwtY3VlJywgdHJ1ZSk7XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZVxuICAgICAgICAgICAgdmFyIHBvc1ggPSB4MnAoXG4gICAgICAgICAgICAgIHhQaXhlbFNpemVkID9cbiAgICAgICAgICAgICAgICBzaGFwZU9wdGlvbnMueGFuY2hvciA6XG4gICAgICAgICAgICAgICAgTGliLm1pZFJhbmdlKFxuICAgICAgICAgICAgICAgICAgaXNOb3RQYXRoID9cbiAgICAgICAgICAgICAgICAgICAgW3NoYXBlT3B0aW9ucy54MCwgc2hhcGVPcHRpb25zLngxXSA6XG4gICAgICAgICAgICAgICAgICAgIGhlbHBlcnMuZXh0cmFjdFBhdGhDb29yZHMoc2hhcGVPcHRpb25zLnBhdGgsIGNvbnN0YW50cy5wYXJhbUlzWCkpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdmFyIHBvc1kgPSB5MnAoXG4gICAgICAgICAgICAgIHlQaXhlbFNpemVkID9cbiAgICAgICAgICAgICAgICBzaGFwZU9wdGlvbnMueWFuY2hvciA6XG4gICAgICAgICAgICAgICAgTGliLm1pZFJhbmdlKFxuICAgICAgICAgICAgICAgICAgaXNOb3RQYXRoID9cbiAgICAgICAgICAgICAgICAgICAgW3NoYXBlT3B0aW9ucy55MCwgc2hhcGVPcHRpb25zLnkxXSA6XG4gICAgICAgICAgICAgICAgICAgIGhlbHBlcnMuZXh0cmFjdFBhdGhDb29yZHMoc2hhcGVPcHRpb25zLnBhdGgsIGNvbnN0YW50cy5wYXJhbUlzWSkpXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBwb3NYID0gaGVscGVycy5yb3VuZFBvc2l0aW9uRm9yU2hhcnBTdHJva2VSZW5kZXJpbmcocG9zWCwgc3Ryb2tlV2lkdGgpO1xuICAgICAgICAgICAgcG9zWSA9IGhlbHBlcnMucm91bmRQb3NpdGlvbkZvclNoYXJwU3Ryb2tlUmVuZGVyaW5nKHBvc1ksIHN0cm9rZVdpZHRoKTtcblxuICAgICAgICAgICAgaWYoeFBpeGVsU2l6ZWQgJiYgeVBpeGVsU2l6ZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3Jvc3NQYXRoID0gJ00nICsgKHBvc1ggLSAxIC0gc3Ryb2tlV2lkdGgpICsgJywnICsgKHBvc1kgLSAxIC0gc3Ryb2tlV2lkdGgpICtcbiAgICAgICAgICAgICAgICAgICdoLTh2Mmg4IHY4aDJ2LTggaDh2LTJoLTggdi04aC0yIFonO1xuICAgICAgICAgICAgICAgIHZpc3VhbEN1ZXMuYXR0cignZCcsIGNyb3NzUGF0aCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoeFBpeGVsU2l6ZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdkJhclBhdGggPSAnTScgKyAocG9zWCAtIDEgLSBzdHJva2VXaWR0aCkgKyAnLCcgKyAocG9zWSAtIDkgLSBzdHJva2VXaWR0aCkgK1xuICAgICAgICAgICAgICAgICAgJ3YxOCBoMiB2LTE4IFonO1xuICAgICAgICAgICAgICAgIHZpc3VhbEN1ZXMuYXR0cignZCcsIHZCYXJQYXRoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGhCYXJQYXRoID0gJ00nICsgKHBvc1ggLSA5IC0gc3Ryb2tlV2lkdGgpICsgJywnICsgKHBvc1kgLSAxIC0gc3Ryb2tlV2lkdGgpICtcbiAgICAgICAgICAgICAgICAgICdoMTggdjIgaC0xOCBaJztcbiAgICAgICAgICAgICAgICB2aXN1YWxDdWVzLmF0dHIoJ2QnLCBoQmFyUGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVWaXN1YWxDdWVzKHNoYXBlTGF5ZXIpIHtcbiAgICAgICAgc2hhcGVMYXllci5zZWxlY3RBbGwoJy52aXN1YWwtY3VlJykucmVtb3ZlKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZGVhY3RpdmF0ZUNsaXBQYXRoVGVtcG9yYXJpbHkoc2hhcGVQYXRoLCBzaGFwZU9wdGlvbnMsIGdkKSB7XG4gICAgICAgIHZhciB4cmVmID0gc2hhcGVPcHRpb25zLnhyZWY7XG4gICAgICAgIHZhciB5cmVmID0gc2hhcGVPcHRpb25zLnlyZWY7XG4gICAgICAgIHZhciB4YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB4cmVmKTtcbiAgICAgICAgdmFyIHlhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHlyZWYpO1xuXG4gICAgICAgIHZhciBjbGlwQXhlcyA9ICcnO1xuICAgICAgICBpZih4cmVmICE9PSAncGFwZXInICYmICF4YS5hdXRvcmFuZ2UpIGNsaXBBeGVzICs9IHhyZWY7XG4gICAgICAgIGlmKHlyZWYgIT09ICdwYXBlcicgJiYgIXlhLmF1dG9yYW5nZSkgY2xpcEF4ZXMgKz0geXJlZjtcblxuICAgICAgICBEcmF3aW5nLnNldENsaXBVcmwoXG4gICAgICAgICAgICBzaGFwZVBhdGgsXG4gICAgICAgICAgICBjbGlwQXhlcyA/ICdjbGlwJyArIGdkLl9mdWxsTGF5b3V0Ll91aWQgKyBjbGlwQXhlcyA6IG51bGwsXG4gICAgICAgICAgICBnZFxuICAgICAgICApO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0UGF0aFN0cmluZyhnZCwgb3B0aW9ucykge1xuICAgIHZhciB0eXBlID0gb3B0aW9ucy50eXBlO1xuICAgIHZhciB4YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBvcHRpb25zLnhyZWYpO1xuICAgIHZhciB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBvcHRpb25zLnlyZWYpO1xuICAgIHZhciBncyA9IGdkLl9mdWxsTGF5b3V0Ll9zaXplO1xuICAgIHZhciB4MnIsIHgycCwgeTJyLCB5MnA7XG4gICAgdmFyIHgwLCB4MSwgeTAsIHkxO1xuXG4gICAgaWYoeGEpIHtcbiAgICAgICAgeDJyID0gaGVscGVycy5zaGFwZVBvc2l0aW9uVG9SYW5nZSh4YSk7XG4gICAgICAgIHgycCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHhhLl9vZmZzZXQgKyB4YS5yMnAoeDJyKHYsIHRydWUpKTsgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB4MnAgPSBmdW5jdGlvbih2KSB7IHJldHVybiBncy5sICsgZ3MudyAqIHY7IH07XG4gICAgfVxuXG4gICAgaWYoeWEpIHtcbiAgICAgICAgeTJyID0gaGVscGVycy5zaGFwZVBvc2l0aW9uVG9SYW5nZSh5YSk7XG4gICAgICAgIHkycCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHlhLl9vZmZzZXQgKyB5YS5yMnAoeTJyKHYsIHRydWUpKTsgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB5MnAgPSBmdW5jdGlvbih2KSB7IHJldHVybiBncy50ICsgZ3MuaCAqICgxIC0gdik7IH07XG4gICAgfVxuXG4gICAgaWYodHlwZSA9PT0gJ3BhdGgnKSB7XG4gICAgICAgIGlmKHhhICYmIHhhLnR5cGUgPT09ICdkYXRlJykgeDJwID0gaGVscGVycy5kZWNvZGVEYXRlKHgycCk7XG4gICAgICAgIGlmKHlhICYmIHlhLnR5cGUgPT09ICdkYXRlJykgeTJwID0gaGVscGVycy5kZWNvZGVEYXRlKHkycCk7XG4gICAgICAgIHJldHVybiBjb252ZXJ0UGF0aChvcHRpb25zLCB4MnAsIHkycCk7XG4gICAgfVxuXG4gICAgaWYob3B0aW9ucy54c2l6ZW1vZGUgPT09ICdwaXhlbCcpIHtcbiAgICAgICAgdmFyIHhBbmNob3JQb3MgPSB4MnAob3B0aW9ucy54YW5jaG9yKTtcbiAgICAgICAgeDAgPSB4QW5jaG9yUG9zICsgb3B0aW9ucy54MDtcbiAgICAgICAgeDEgPSB4QW5jaG9yUG9zICsgb3B0aW9ucy54MTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB4MCA9IHgycChvcHRpb25zLngwKTtcbiAgICAgICAgeDEgPSB4MnAob3B0aW9ucy54MSk7XG4gICAgfVxuXG4gICAgaWYob3B0aW9ucy55c2l6ZW1vZGUgPT09ICdwaXhlbCcpIHtcbiAgICAgICAgdmFyIHlBbmNob3JQb3MgPSB5MnAob3B0aW9ucy55YW5jaG9yKTtcbiAgICAgICAgeTAgPSB5QW5jaG9yUG9zIC0gb3B0aW9ucy55MDtcbiAgICAgICAgeTEgPSB5QW5jaG9yUG9zIC0gb3B0aW9ucy55MTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB5MCA9IHkycChvcHRpb25zLnkwKTtcbiAgICAgICAgeTEgPSB5MnAob3B0aW9ucy55MSk7XG4gICAgfVxuXG4gICAgaWYodHlwZSA9PT0gJ2xpbmUnKSByZXR1cm4gJ00nICsgeDAgKyAnLCcgKyB5MCArICdMJyArIHgxICsgJywnICsgeTE7XG4gICAgaWYodHlwZSA9PT0gJ3JlY3QnKSByZXR1cm4gJ00nICsgeDAgKyAnLCcgKyB5MCArICdIJyArIHgxICsgJ1YnICsgeTEgKyAnSCcgKyB4MCArICdaJztcblxuICAgIC8vIGNpcmNsZVxuICAgIHZhciBjeCA9ICh4MCArIHgxKSAvIDI7XG4gICAgdmFyIGN5ID0gKHkwICsgeTEpIC8gMjtcbiAgICB2YXIgcnggPSBNYXRoLmFicyhjeCAtIHgwKTtcbiAgICB2YXIgcnkgPSBNYXRoLmFicyhjeSAtIHkwKTtcbiAgICB2YXIgckFyYyA9ICdBJyArIHJ4ICsgJywnICsgcnk7XG4gICAgdmFyIHJpZ2h0UHQgPSAoY3ggKyByeCkgKyAnLCcgKyBjeTtcbiAgICB2YXIgdG9wUHQgPSBjeCArICcsJyArIChjeSAtIHJ5KTtcbiAgICByZXR1cm4gJ00nICsgcmlnaHRQdCArIHJBcmMgKyAnIDAgMSwxICcgKyB0b3BQdCArXG4gICAgICAgIHJBcmMgKyAnIDAgMCwxICcgKyByaWdodFB0ICsgJ1onO1xufVxuXG5cbmZ1bmN0aW9uIGNvbnZlcnRQYXRoKG9wdGlvbnMsIHgycCwgeTJwKSB7XG4gICAgdmFyIHBhdGhJbiA9IG9wdGlvbnMucGF0aDtcbiAgICB2YXIgeFNpemVtb2RlID0gb3B0aW9ucy54c2l6ZW1vZGU7XG4gICAgdmFyIHlTaXplbW9kZSA9IG9wdGlvbnMueXNpemVtb2RlO1xuICAgIHZhciB4QW5jaG9yID0gb3B0aW9ucy54YW5jaG9yO1xuICAgIHZhciB5QW5jaG9yID0gb3B0aW9ucy55YW5jaG9yO1xuXG4gICAgcmV0dXJuIHBhdGhJbi5yZXBsYWNlKGNvbnN0YW50cy5zZWdtZW50UkUsIGZ1bmN0aW9uKHNlZ21lbnQpIHtcbiAgICAgICAgdmFyIHBhcmFtTnVtYmVyID0gMDtcbiAgICAgICAgdmFyIHNlZ21lbnRUeXBlID0gc2VnbWVudC5jaGFyQXQoMCk7XG4gICAgICAgIHZhciB4UGFyYW1zID0gY29uc3RhbnRzLnBhcmFtSXNYW3NlZ21lbnRUeXBlXTtcbiAgICAgICAgdmFyIHlQYXJhbXMgPSBjb25zdGFudHMucGFyYW1Jc1lbc2VnbWVudFR5cGVdO1xuICAgICAgICB2YXIgblBhcmFtcyA9IGNvbnN0YW50cy5udW1QYXJhbXNbc2VnbWVudFR5cGVdO1xuXG4gICAgICAgIHZhciBwYXJhbVN0cmluZyA9IHNlZ21lbnQuc3Vic3RyKDEpLnJlcGxhY2UoY29uc3RhbnRzLnBhcmFtUkUsIGZ1bmN0aW9uKHBhcmFtKSB7XG4gICAgICAgICAgICBpZih4UGFyYW1zW3BhcmFtTnVtYmVyXSkge1xuICAgICAgICAgICAgICAgIGlmKHhTaXplbW9kZSA9PT0gJ3BpeGVsJykgcGFyYW0gPSB4MnAoeEFuY2hvcikgKyBOdW1iZXIocGFyYW0pO1xuICAgICAgICAgICAgICAgIGVsc2UgcGFyYW0gPSB4MnAocGFyYW0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmKHlQYXJhbXNbcGFyYW1OdW1iZXJdKSB7XG4gICAgICAgICAgICAgICAgaWYoeVNpemVtb2RlID09PSAncGl4ZWwnKSBwYXJhbSA9IHkycCh5QW5jaG9yKSAtIE51bWJlcihwYXJhbSk7XG4gICAgICAgICAgICAgICAgZWxzZSBwYXJhbSA9IHkycChwYXJhbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYXJhbU51bWJlcisrO1xuXG4gICAgICAgICAgICBpZihwYXJhbU51bWJlciA+IG5QYXJhbXMpIHBhcmFtID0gJ1gnO1xuICAgICAgICAgICAgcmV0dXJuIHBhcmFtO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZihwYXJhbU51bWJlciA+IG5QYXJhbXMpIHtcbiAgICAgICAgICAgIHBhcmFtU3RyaW5nID0gcGFyYW1TdHJpbmcucmVwbGFjZSgvW1xccyxdKlguKi8sICcnKTtcbiAgICAgICAgICAgIExpYi5sb2coJ0lnbm9yaW5nIGV4dHJhIHBhcmFtcyBpbiBzZWdtZW50ICcgKyBzZWdtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzZWdtZW50VHlwZSArIHBhcmFtU3RyaW5nO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBtb3ZlUGF0aChwYXRoSW4sIG1vdmVYLCBtb3ZlWSkge1xuICAgIHJldHVybiBwYXRoSW4ucmVwbGFjZShjb25zdGFudHMuc2VnbWVudFJFLCBmdW5jdGlvbihzZWdtZW50KSB7XG4gICAgICAgIHZhciBwYXJhbU51bWJlciA9IDA7XG4gICAgICAgIHZhciBzZWdtZW50VHlwZSA9IHNlZ21lbnQuY2hhckF0KDApO1xuICAgICAgICB2YXIgeFBhcmFtcyA9IGNvbnN0YW50cy5wYXJhbUlzWFtzZWdtZW50VHlwZV07XG4gICAgICAgIHZhciB5UGFyYW1zID0gY29uc3RhbnRzLnBhcmFtSXNZW3NlZ21lbnRUeXBlXTtcbiAgICAgICAgdmFyIG5QYXJhbXMgPSBjb25zdGFudHMubnVtUGFyYW1zW3NlZ21lbnRUeXBlXTtcblxuICAgICAgICB2YXIgcGFyYW1TdHJpbmcgPSBzZWdtZW50LnN1YnN0cigxKS5yZXBsYWNlKGNvbnN0YW50cy5wYXJhbVJFLCBmdW5jdGlvbihwYXJhbSkge1xuICAgICAgICAgICAgaWYocGFyYW1OdW1iZXIgPj0gblBhcmFtcykgcmV0dXJuIHBhcmFtO1xuXG4gICAgICAgICAgICBpZih4UGFyYW1zW3BhcmFtTnVtYmVyXSkgcGFyYW0gPSBtb3ZlWChwYXJhbSk7XG4gICAgICAgICAgICBlbHNlIGlmKHlQYXJhbXNbcGFyYW1OdW1iZXJdKSBwYXJhbSA9IG1vdmVZKHBhcmFtKTtcblxuICAgICAgICAgICAgcGFyYW1OdW1iZXIrKztcblxuICAgICAgICAgICAgcmV0dXJuIHBhcmFtO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc2VnbWVudFR5cGUgKyBwYXJhbVN0cmluZztcbiAgICB9KTtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvc2V0Y3Vyc29yXCI6NzM5LFwiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9jb2xvclwiOjU5MyxcIi4uL2RyYWdlbGVtZW50XCI6NjExLFwiLi4vZHJhd2luZ1wiOjYxNCxcIi4vY29uc3RhbnRzXCI6NjcxLFwiLi9oZWxwZXJzXCI6Njc0fV0sNjc0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG4vLyBzcGVjaWFsIHBvc2l0aW9uIGNvbnZlcnNpb24gZnVuY3Rpb25zLi4uIGNhdGVnb3J5IGF4aXMgcG9zaXRpb25zIGNhbid0IGJlXG4vLyBzcGVjaWZpZWQgYnkgdGhlaXIgZGF0YSB2YWx1ZXMsIGJlY2F1c2UgdGhleSBkb24ndCBtYWtlIGEgY29udGludW91cyBtYXBwaW5nLlxuLy8gc28gdGhlc2UgaGF2ZSB0byBiZSBzcGVjaWZpZWQgaW4gdGVybXMgb2YgdGhlIGNhdGVnb3J5IHNlcmlhbCBudW1iZXJzLFxuLy8gYnV0IGNhbiB0YWtlIGZyYWN0aW9uYWwgdmFsdWVzLiBPdGhlciBheGlzIHR5cGVzIHdlIHNwZWNpZnkgcG9zaXRpb24gYmFzZWQgb25cbi8vIHRoZSBhY3R1YWwgZGF0YSB2YWx1ZXMuXG4vLyBUT0RPOiBpbiBWMi4wICh3aGVuIGxvZyBheGlzIHJhbmdlcyBhcmUgaW4gZGF0YSB1bml0cykgcmFuZ2UgYW5kIHNoYXBlIHBvc2l0aW9uXG4vLyB3aWxsIGJlIGlkZW50aWNhbCwgc28gcmFuZ2VUb1NoYXBlUG9zaXRpb24gYW5kIHNoYXBlUG9zaXRpb25Ub1JhbmdlIGNhbiBiZVxuLy8gcmVtb3ZlZCBlbnRpcmVseS5cblxuZXhwb3J0cy5yYW5nZVRvU2hhcGVQb3NpdGlvbiA9IGZ1bmN0aW9uKGF4KSB7XG4gICAgcmV0dXJuIChheC50eXBlID09PSAnbG9nJykgPyBheC5yMmQgOiBmdW5jdGlvbih2KSB7IHJldHVybiB2OyB9O1xufTtcblxuZXhwb3J0cy5zaGFwZVBvc2l0aW9uVG9SYW5nZSA9IGZ1bmN0aW9uKGF4KSB7XG4gICAgcmV0dXJuIChheC50eXBlID09PSAnbG9nJykgPyBheC5kMnIgOiBmdW5jdGlvbih2KSB7IHJldHVybiB2OyB9O1xufTtcblxuZXhwb3J0cy5kZWNvZGVEYXRlID0gZnVuY3Rpb24oY29udmVydFRvUHgpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odikge1xuICAgICAgICBpZih2LnJlcGxhY2UpIHYgPSB2LnJlcGxhY2UoJ18nLCAnICcpO1xuICAgICAgICByZXR1cm4gY29udmVydFRvUHgodik7XG4gICAgfTtcbn07XG5cbmV4cG9ydHMuZW5jb2RlRGF0ZSA9IGZ1bmN0aW9uKGNvbnZlcnRUb0RhdGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odikgeyByZXR1cm4gY29udmVydFRvRGF0ZSh2KS5yZXBsYWNlKCcgJywgJ18nKTsgfTtcbn07XG5cbmV4cG9ydHMuZXh0cmFjdFBhdGhDb29yZHMgPSBmdW5jdGlvbihwYXRoLCBwYXJhbXNUb1VzZSkge1xuICAgIHZhciBleHRyYWN0ZWRDb29yZGluYXRlcyA9IFtdO1xuXG4gICAgdmFyIHNlZ21lbnRzID0gcGF0aC5tYXRjaChjb25zdGFudHMuc2VnbWVudFJFKTtcbiAgICBzZWdtZW50cy5mb3JFYWNoKGZ1bmN0aW9uKHNlZ21lbnQpIHtcbiAgICAgICAgdmFyIHJlbGV2YW50UGFyYW1JZHggPSBwYXJhbXNUb1VzZVtzZWdtZW50LmNoYXJBdCgwKV0uZHJhd247XG4gICAgICAgIGlmKHJlbGV2YW50UGFyYW1JZHggPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgICAgIHZhciBwYXJhbXMgPSBzZWdtZW50LnN1YnN0cigxKS5tYXRjaChjb25zdGFudHMucGFyYW1SRSk7XG4gICAgICAgIGlmKCFwYXJhbXMgfHwgcGFyYW1zLmxlbmd0aCA8IHJlbGV2YW50UGFyYW1JZHgpIHJldHVybjtcblxuICAgICAgICBleHRyYWN0ZWRDb29yZGluYXRlcy5wdXNoKExpYi5jbGVhbk51bWJlcihwYXJhbXNbcmVsZXZhbnRQYXJhbUlkeF0pKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBleHRyYWN0ZWRDb29yZGluYXRlcztcbn07XG5cbmV4cG9ydHMuZ2V0RGF0YVRvUGl4ZWwgPSBmdW5jdGlvbihnZCwgYXhpcywgaXNWZXJ0aWNhbCkge1xuICAgIHZhciBncyA9IGdkLl9mdWxsTGF5b3V0Ll9zaXplO1xuICAgIHZhciBkYXRhVG9QaXhlbDtcblxuICAgIGlmKGF4aXMpIHtcbiAgICAgICAgdmFyIGQyciA9IGV4cG9ydHMuc2hhcGVQb3NpdGlvblRvUmFuZ2UoYXhpcyk7XG5cbiAgICAgICAgZGF0YVRvUGl4ZWwgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICByZXR1cm4gYXhpcy5fb2Zmc2V0ICsgYXhpcy5yMnAoZDJyKHYsIHRydWUpKTtcbiAgICAgICAgfTtcblxuICAgICAgICBpZihheGlzLnR5cGUgPT09ICdkYXRlJykgZGF0YVRvUGl4ZWwgPSBleHBvcnRzLmRlY29kZURhdGUoZGF0YVRvUGl4ZWwpO1xuICAgIH0gZWxzZSBpZihpc1ZlcnRpY2FsKSB7XG4gICAgICAgIGRhdGFUb1BpeGVsID0gZnVuY3Rpb24odikgeyByZXR1cm4gZ3MudCArIGdzLmggKiAoMSAtIHYpOyB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRhdGFUb1BpeGVsID0gZnVuY3Rpb24odikgeyByZXR1cm4gZ3MubCArIGdzLncgKiB2OyB9O1xuICAgIH1cblxuICAgIHJldHVybiBkYXRhVG9QaXhlbDtcbn07XG5cbmV4cG9ydHMuZ2V0UGl4ZWxUb0RhdGEgPSBmdW5jdGlvbihnZCwgYXhpcywgaXNWZXJ0aWNhbCkge1xuICAgIHZhciBncyA9IGdkLl9mdWxsTGF5b3V0Ll9zaXplO1xuICAgIHZhciBwaXhlbFRvRGF0YTtcblxuICAgIGlmKGF4aXMpIHtcbiAgICAgICAgdmFyIHIyZCA9IGV4cG9ydHMucmFuZ2VUb1NoYXBlUG9zaXRpb24oYXhpcyk7XG4gICAgICAgIHBpeGVsVG9EYXRhID0gZnVuY3Rpb24ocCkgeyByZXR1cm4gcjJkKGF4aXMucDJyKHAgLSBheGlzLl9vZmZzZXQpKTsgfTtcbiAgICB9IGVsc2UgaWYoaXNWZXJ0aWNhbCkge1xuICAgICAgICBwaXhlbFRvRGF0YSA9IGZ1bmN0aW9uKHApIHsgcmV0dXJuIDEgLSAocCAtIGdzLnQpIC8gZ3MuaDsgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwaXhlbFRvRGF0YSA9IGZ1bmN0aW9uKHApIHsgcmV0dXJuIChwIC0gZ3MubCkgLyBncy53OyB9O1xuICAgIH1cblxuICAgIHJldHVybiBwaXhlbFRvRGF0YTtcbn07XG5cbi8qKlxuICogQmFzZWQgb24gdGhlIGdpdmVuIHN0cm9rZSB3aWR0aCwgcm91bmRzIHRoZSBwYXNzZWRcbiAqIHBvc2l0aW9uIHZhbHVlIHRvIHJlcHJlc2VudCBlaXRoZXIgYSBmdWxsIG9yIGhhbGYgcGl4ZWwuXG4gKlxuICogSW4gY2FzZSBvZiBhbiBvZGQgc3Ryb2tlIHdpZHRoIChlLmcuIDEpLCB0aGlzIG1lYXN1cmUgZW5zdXJlc1xuICogdGhhdCBhIHN0cm9rZSBwb3NpdGlvbmVkIGF0IHRoZSByZXR1cm5lZCBwb3NpdGlvbiBpc24ndCByZW5kZXJlZFxuICogYmx1cnJ5IGR1ZSB0byBhbnRpLWFsaWFzaW5nLlxuICpcbiAqIEluIGNhc2Ugb2YgYW4gZXZlbiBzdHJva2Ugd2lkdGggKGUuZy4gMiksIHRoaXMgbWVhc3VyZSBlbnN1cmVzXG4gKiB0aGF0IHRoZSBwb3NpdGlvbiB2YWx1ZSBpcyB0cmFuc2Zvcm1lZCB0byBhIGZ1bGwgcGl4ZWwgdmFsdWVcbiAqIHNvIHRoYXQgYW50aS1hbGlhc2luZyBkb2Vzbid0IHRha2UgZWZmZWN0IGVpdGhlci5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zIFRoZSByYXcgcG9zaXRpb24gdmFsdWUgdG8gYmUgdHJhbnNmb3JtZWRcbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJva2VXaWR0aCBUaGUgc3Ryb2tlIHdpZHRoXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBlaXRoZXIgYW4gaW50ZWdlciBvciBhIC41IGRlY2ltYWwgbnVtYmVyXG4gKi9cbmV4cG9ydHMucm91bmRQb3NpdGlvbkZvclNoYXJwU3Ryb2tlUmVuZGVyaW5nID0gZnVuY3Rpb24ocG9zLCBzdHJva2VXaWR0aCkge1xuICAgIHZhciBzdHJva2VXaWR0aElzT2RkID0gTWF0aC5yb3VuZChzdHJva2VXaWR0aCAlIDIpID09PSAxO1xuICAgIHZhciBwb3NWYWxBc0ludCA9IE1hdGgucm91bmQocG9zKTtcblxuICAgIHJldHVybiBzdHJva2VXaWR0aElzT2RkID8gcG9zVmFsQXNJbnQgKyAwLjUgOiBwb3NWYWxBc0ludDtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi9jb25zdGFudHNcIjo2NzF9XSw2NzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkcmF3TW9kdWxlID0gX2RlcmVxXygnLi9kcmF3Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICdjb21wb25lbnQnLFxuICAgIG5hbWU6ICdzaGFwZXMnLFxuXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBpbmNsdWRlQmFzZVBsb3Q6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9pbmNsdWRlX2NvbXBvbmVudHMnKSgnc2hhcGVzJyksXG5cbiAgICBjYWxjQXV0b3JhbmdlOiBfZGVyZXFfKCcuL2NhbGNfYXV0b3JhbmdlJyksXG4gICAgZHJhdzogZHJhd01vZHVsZS5kcmF3LFxuICAgIGRyYXdPbmU6IGRyYXdNb2R1bGUuZHJhd09uZVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vaW5jbHVkZV9jb21wb25lbnRzXCI6Nzc3LFwiLi9hdHRyaWJ1dGVzXCI6NjY5LFwiLi9jYWxjX2F1dG9yYW5nZVwiOjY3MCxcIi4vZGVmYXVsdHNcIjo2NzIsXCIuL2RyYXdcIjo2NzN9XSw2NzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZm9udEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgcGFkQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9wYWRfYXR0cmlidXRlcycpO1xudmFyIGV4dGVuZERlZXBBbGwgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRGVlcEFsbDtcbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcbnZhciBhbmltYXRpb25BdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2FuaW1hdGlvbl9hdHRyaWJ1dGVzJyk7XG52YXIgdGVtcGxhdGVkQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykudGVtcGxhdGVkQXJyYXk7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcblxudmFyIHN0ZXBzQXR0cnMgPSB0ZW1wbGF0ZWRBcnJheSgnc3RlcCcsIHtcbiAgICB2aXNpYmxlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbWV0aG9kOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3Jlc3R5bGUnLCAncmVsYXlvdXQnLCAnYW5pbWF0ZScsICd1cGRhdGUnLCAnc2tpcCddLFxuICAgICAgICBkZmx0OiAncmVzdHlsZScsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGFyZ3M6IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZnJlZUxlbmd0aDogdHJ1ZSxcbiAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHsgdmFsVHlwZTogJ2FueScgfSxcbiAgICAgICAgICAgIHsgdmFsVHlwZTogJ2FueScgfSxcbiAgICAgICAgICAgIHsgdmFsVHlwZTogJ2FueScgfVxuICAgICAgICBdLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxhYmVsOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB2YWx1ZToge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgZXhlY3V0ZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICB9XG59KTtcblxubW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh0ZW1wbGF0ZWRBcnJheSgnc2xpZGVyJywge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGFjdGl2ZToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHN0ZXBzOiBzdGVwc0F0dHJzLFxuXG4gICAgbGVubW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydmcmFjdGlvbicsICdwaXhlbHMnXSxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICdmcmFjdGlvbicsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGVuOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgcGFkOiBleHRlbmREZWVwQWxsKHBhZEF0dHJzKHtlZGl0VHlwZTogJ2FycmF5ZHJhdyd9KSwge1xuICAgICAgICBcbiAgICB9LCB7dDoge2RmbHQ6IDIwfX0pLFxuICAgIHhhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYXV0bycsICdsZWZ0JywgJ2NlbnRlcicsICdyaWdodCddLFxuICAgICAgICBkZmx0OiAnbGVmdCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgeWFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhdXRvJywgJ3RvcCcsICdtaWRkbGUnLCAnYm90dG9tJ10sXG4gICAgICAgIGRmbHQ6ICd0b3AnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRyYW5zaXRpb246IHtcbiAgICAgICAgZHVyYXRpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAxNTAsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWFzaW5nOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IGFuaW1hdGlvbkF0dHJzLnRyYW5zaXRpb24uZWFzaW5nLnZhbHVlcyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogJ2N1YmljLWluLW91dCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBjdXJyZW50dmFsdWU6IHtcbiAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgeGFuY2hvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2xlZnQnLCAnY2VudGVyJywgJ3JpZ2h0J10sXG4gICAgICAgICAgICBkZmx0OiAnbGVmdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIG9mZnNldDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiAxMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgcHJlZml4OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgc3VmZml4OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KVxuICAgIH0sXG5cbiAgICBmb250OiBmb250QXR0cnMoe1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIGFjdGl2ZWJnY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGNvbnN0YW50cy5ncmlwQmdBY3RpdmVDb2xvcixcbiAgICAgICAgXG4gICAgfSxcbiAgICBiZ2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb25zdGFudHMucmFpbEJnQ29sb3IsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm9yZGVyY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29uc3RhbnRzLnJhaWxCb3JkZXJDb2xvcixcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm9yZGVyd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogY29uc3RhbnRzLnJhaWxCb3JkZXJXaWR0aCxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja2xlbjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiBjb25zdGFudHMudGlja0xlbmd0aCxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbnN0YW50cy50aWNrQ29sb3IsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2t3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBtaW5vcnRpY2tsZW46IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogY29uc3RhbnRzLm1pbm9yVGlja0xlbmd0aCxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH1cbn0pLCAnYXJyYXlkcmF3JywgJ2Zyb20tcm9vdCcpO1xuXG59LHtcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uLy4uL3Bsb3RzL2FuaW1hdGlvbl9hdHRyaWJ1dGVzXCI6NzYyLFwiLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzXCI6NzkzLFwiLi4vLi4vcGxvdHMvcGFkX2F0dHJpYnV0ZXNcIjo4MjcsXCIuL2NvbnN0YW50c1wiOjY3N31dLDY3NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuICAgIC8vIGxheW91dCBhdHRyaWJ1dGUgbmFtZVxuICAgIG5hbWU6ICdzbGlkZXJzJyxcblxuICAgIC8vIGNsYXNzIG5hbWVzXG4gICAgY29udGFpbmVyQ2xhc3NOYW1lOiAnc2xpZGVyLWNvbnRhaW5lcicsXG4gICAgZ3JvdXBDbGFzc05hbWU6ICdzbGlkZXItZ3JvdXAnLFxuICAgIGlucHV0QXJlYUNsYXNzOiAnc2xpZGVyLWlucHV0LWFyZWEnLFxuICAgIHJhaWxSZWN0Q2xhc3M6ICdzbGlkZXItcmFpbC1yZWN0JyxcbiAgICByYWlsVG91Y2hSZWN0Q2xhc3M6ICdzbGlkZXItcmFpbC10b3VjaC1yZWN0JyxcbiAgICBncmlwUmVjdENsYXNzOiAnc2xpZGVyLWdyaXAtcmVjdCcsXG4gICAgdGlja1JlY3RDbGFzczogJ3NsaWRlci10aWNrLXJlY3QnLFxuICAgIGlucHV0UHJveHlDbGFzczogJ3NsaWRlci1pbnB1dC1wcm94eScsXG4gICAgbGFiZWxzQ2xhc3M6ICdzbGlkZXItbGFiZWxzJyxcbiAgICBsYWJlbEdyb3VwQ2xhc3M6ICdzbGlkZXItbGFiZWwtZ3JvdXAnLFxuICAgIGxhYmVsQ2xhc3M6ICdzbGlkZXItbGFiZWwnLFxuICAgIGN1cnJlbnRWYWx1ZUNsYXNzOiAnc2xpZGVyLWN1cnJlbnQtdmFsdWUnLFxuXG4gICAgcmFpbEhlaWdodDogNSxcblxuICAgIC8vIERPTSBhdHRyaWJ1dGUgbmFtZSBpbiBidXR0b24gZ3JvdXAga2VlcGluZyB0cmFja1xuICAgIC8vIG9mIGFjdGl2ZSB1cGRhdGUgbWVudVxuICAgIG1lbnVJbmRleEF0dHJOYW1lOiAnc2xpZGVyLWFjdGl2ZS1pbmRleCcsXG5cbiAgICAvLyBpZCByb290IHBhc3MgdG8gUGxvdHMuYXV0b01hcmdpblxuICAgIGF1dG9NYXJnaW5JZFJvb3Q6ICdzbGlkZXItJyxcblxuICAgIC8vIG1pbiBpdGVtIHdpZHRoIC8gaGVpZ2h0XG4gICAgbWluV2lkdGg6IDMwLFxuICAgIG1pbkhlaWdodDogMzAsXG5cbiAgICAvLyBwYWRkaW5nIGFyb3VuZCBpdGVtIHRleHRcbiAgICB0ZXh0UGFkWDogNDAsXG5cbiAgICAvLyBhcnJvdyBvZmZzZXQgb2ZmIHJpZ2h0IGVkZ2VcbiAgICBhcnJvd09mZnNldFg6IDQsXG5cbiAgICByYWlsUmFkaXVzOiAyLFxuICAgIHJhaWxXaWR0aDogNSxcbiAgICByYWlsQm9yZGVyOiA0LFxuICAgIHJhaWxCb3JkZXJXaWR0aDogMSxcbiAgICByYWlsQm9yZGVyQ29sb3I6ICcjYmVjOGQ5JyxcbiAgICByYWlsQmdDb2xvcjogJyNmOGZhZmMnLFxuXG4gICAgLy8gVGhlIGRpc3RhbmNlIG9mIHRoZSByYWlsIGZyb20gdGhlIGVkZ2Ugb2YgdGhlIHRvdWNoYWJsZSBhcmVhXG4gICAgLy8gU2xpZ2h0bHkgbGVzcyB0aGFuIHRoZSBzdGVwIGluc2V0IGJlY2F1c2Ugb2YgdGhlIGN1cnZlZCBlZGdlc1xuICAgIC8vIG9mIHRoZSByYWlsXG4gICAgcmFpbEluc2V0OiA4LFxuXG4gICAgLy8gVGhlIGRpc3RhbmNlIGZyb20gdGhlIGV4dHJlbWFsIHRpY2sgbWFya3MgdG8gdGhlIGVkZ2Ugb2YgdGhlXG4gICAgLy8gdG91Y2hhYmxlIGFyZWEuIFRoaXMgaXMgYmFzaWNhbGx5IHRoZSBzYW1lIGFzIHRoZSBncmlwIHJhZGl1cyxcbiAgICAvLyBidXQgZm9yIG90aGVyIHN0eWxlcyBpdCB3b3VsZG4ndCByZWFsbHkgbmVlZCB0byBiZS5cbiAgICBzdGVwSW5zZXQ6IDEwLFxuXG4gICAgZ3JpcFJhZGl1czogMTAsXG4gICAgZ3JpcFdpZHRoOiAyMCxcbiAgICBncmlwSGVpZ2h0OiAyMCxcbiAgICBncmlwQm9yZGVyOiAyMCxcbiAgICBncmlwQm9yZGVyV2lkdGg6IDEsXG4gICAgZ3JpcEJvcmRlckNvbG9yOiAnI2JlYzhkOScsXG4gICAgZ3JpcEJnQ29sb3I6ICcjZjZmOGZhJyxcbiAgICBncmlwQmdBY3RpdmVDb2xvcjogJyNkYmRkZTAnLFxuXG4gICAgbGFiZWxQYWRkaW5nOiA4LFxuICAgIGxhYmVsT2Zmc2V0OiAwLFxuXG4gICAgdGlja1dpZHRoOiAxLFxuICAgIHRpY2tDb2xvcjogJyMzMzMnLFxuICAgIHRpY2tPZmZzZXQ6IDI1LFxuICAgIHRpY2tMZW5ndGg6IDcsXG5cbiAgICBtaW5vclRpY2tPZmZzZXQ6IDI1LFxuICAgIG1pbm9yVGlja0NvbG9yOiAnIzMzMycsXG4gICAgbWlub3JUaWNrTGVuZ3RoOiA0LFxuXG4gICAgLy8gRXh0cmEgc3BhY2UgYmVsb3cgdGhlIGN1cnJlbnQgdmFsdWUgbGFiZWw6XG4gICAgY3VycmVudFZhbHVlUGFkZGluZzogOCxcbiAgICBjdXJyZW50VmFsdWVJbnNldDogMCxcbn07XG5cbn0se31dLDY3ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcblxudmFyIG5hbWUgPSBjb25zdGFudHMubmFtZTtcbnZhciBzdGVwQXR0cnMgPSBhdHRyaWJ1dGVzLnN0ZXBzO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2xpZGVyc0RlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQpIHtcbiAgICBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIHtcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgaGFuZGxlSXRlbURlZmF1bHRzOiBzbGlkZXJEZWZhdWx0c1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gc2xpZGVyRGVmYXVsdHMoc2xpZGVySW4sIHNsaWRlck91dCwgbGF5b3V0T3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2Uoc2xpZGVySW4sIHNsaWRlck91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHN0ZXBzID0gaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyhzbGlkZXJJbiwgc2xpZGVyT3V0LCB7XG4gICAgICAgIG5hbWU6ICdzdGVwcycsXG4gICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogc3RlcERlZmF1bHRzXG4gICAgfSk7XG5cbiAgICB2YXIgc3RlcENvdW50ID0gMDtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3RlcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoc3RlcHNbaV0udmlzaWJsZSkgc3RlcENvdW50Kys7XG4gICAgfVxuXG4gICAgdmFyIHZpc2libGU7XG4gICAgLy8gSWYgaXQgaGFzIGZld2VyIHRoYW4gdHdvIG9wdGlvbnMsIGl0J3Mgbm90IHJlYWxseSBhIHNsaWRlclxuICAgIGlmKHN0ZXBDb3VudCA8IDIpIHZpc2libGUgPSBzbGlkZXJPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgIGVsc2UgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScpO1xuICAgIGlmKCF2aXNpYmxlKSByZXR1cm47XG5cbiAgICBzbGlkZXJPdXQuX3N0ZXBDb3VudCA9IHN0ZXBDb3VudDtcbiAgICB2YXIgdmlzU3RlcHMgPSBzbGlkZXJPdXQuX3Zpc2libGVTdGVwcyA9IExpYi5maWx0ZXJWaXNpYmxlKHN0ZXBzKTtcblxuICAgIHZhciBhY3RpdmUgPSBjb2VyY2UoJ2FjdGl2ZScpO1xuICAgIGlmKCEoc3RlcHNbYWN0aXZlXSB8fCB7fSkudmlzaWJsZSkgc2xpZGVyT3V0LmFjdGl2ZSA9IHZpc1N0ZXBzWzBdLl9pbmRleDtcblxuICAgIGNvZXJjZSgneCcpO1xuICAgIGNvZXJjZSgneScpO1xuICAgIExpYi5ub25lT3JBbGwoc2xpZGVySW4sIHNsaWRlck91dCwgWyd4JywgJ3knXSk7XG5cbiAgICBjb2VyY2UoJ3hhbmNob3InKTtcbiAgICBjb2VyY2UoJ3lhbmNob3InKTtcblxuICAgIGNvZXJjZSgnbGVuJyk7XG4gICAgY29lcmNlKCdsZW5tb2RlJyk7XG5cbiAgICBjb2VyY2UoJ3BhZC50Jyk7XG4gICAgY29lcmNlKCdwYWQucicpO1xuICAgIGNvZXJjZSgncGFkLmInKTtcbiAgICBjb2VyY2UoJ3BhZC5sJyk7XG5cbiAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICdmb250JywgbGF5b3V0T3V0LmZvbnQpO1xuXG4gICAgdmFyIGN1cnJlbnRWYWx1ZUlzVmlzaWJsZSA9IGNvZXJjZSgnY3VycmVudHZhbHVlLnZpc2libGUnKTtcblxuICAgIGlmKGN1cnJlbnRWYWx1ZUlzVmlzaWJsZSkge1xuICAgICAgICBjb2VyY2UoJ2N1cnJlbnR2YWx1ZS54YW5jaG9yJyk7XG4gICAgICAgIGNvZXJjZSgnY3VycmVudHZhbHVlLnByZWZpeCcpO1xuICAgICAgICBjb2VyY2UoJ2N1cnJlbnR2YWx1ZS5zdWZmaXgnKTtcbiAgICAgICAgY29lcmNlKCdjdXJyZW50dmFsdWUub2Zmc2V0Jyk7XG5cbiAgICAgICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnY3VycmVudHZhbHVlLmZvbnQnLCBzbGlkZXJPdXQuZm9udCk7XG4gICAgfVxuXG4gICAgY29lcmNlKCd0cmFuc2l0aW9uLmR1cmF0aW9uJyk7XG4gICAgY29lcmNlKCd0cmFuc2l0aW9uLmVhc2luZycpO1xuXG4gICAgY29lcmNlKCdiZ2NvbG9yJyk7XG4gICAgY29lcmNlKCdhY3RpdmViZ2NvbG9yJyk7XG4gICAgY29lcmNlKCdib3JkZXJjb2xvcicpO1xuICAgIGNvZXJjZSgnYm9yZGVyd2lkdGgnKTtcbiAgICBjb2VyY2UoJ3RpY2tsZW4nKTtcbiAgICBjb2VyY2UoJ3RpY2t3aWR0aCcpO1xuICAgIGNvZXJjZSgndGlja2NvbG9yJyk7XG4gICAgY29lcmNlKCdtaW5vcnRpY2tsZW4nKTtcbn1cblxuZnVuY3Rpb24gc3RlcERlZmF1bHRzKHZhbHVlSW4sIHZhbHVlT3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodmFsdWVJbiwgdmFsdWVPdXQsIHN0ZXBBdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZpc2libGU7XG4gICAgaWYodmFsdWVJbi5tZXRob2QgIT09ICdza2lwJyAmJiAhQXJyYXkuaXNBcnJheSh2YWx1ZUluLmFyZ3MpKSB7XG4gICAgICAgIHZpc2libGUgPSB2YWx1ZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgfSBlbHNlIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcblxuICAgIGlmKHZpc2libGUpIHtcbiAgICAgICAgY29lcmNlKCdtZXRob2QnKTtcbiAgICAgICAgY29lcmNlKCdhcmdzJyk7XG4gICAgICAgIHZhciBsYWJlbCA9IGNvZXJjZSgnbGFiZWwnLCAnc3RlcC0nICsgdmFsdWVPdXQuX2luZGV4KTtcbiAgICAgICAgY29lcmNlKCd2YWx1ZScsIGxhYmVsKTtcbiAgICAgICAgY29lcmNlKCdleGVjdXRlJyk7XG4gICAgfVxufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0c1wiOjc2MyxcIi4vYXR0cmlidXRlc1wiOjY3NixcIi4vY29uc3RhbnRzXCI6Njc3fV0sNjc5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIFBsb3RzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvcGxvdHMnKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uL2RyYXdpbmcnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBzdmdUZXh0VXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcbnZhciBhcnJheUVkaXRvciA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKS5hcnJheUVkaXRvcjtcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgYWxpZ25tZW50Q29uc3RhbnRzID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudCcpO1xudmFyIExJTkVfU1BBQ0lORyA9IGFsaWdubWVudENvbnN0YW50cy5MSU5FX1NQQUNJTkc7XG52YXIgRlJPTV9UTCA9IGFsaWdubWVudENvbnN0YW50cy5GUk9NX1RMO1xudmFyIEZST01fQlIgPSBhbGlnbm1lbnRDb25zdGFudHMuRlJPTV9CUjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkcmF3KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc2xpZGVyRGF0YSA9IG1ha2VTbGlkZXJEYXRhKGZ1bGxMYXlvdXQsIGdkKTtcblxuICAgIC8vIGRyYXcgYSBjb250YWluZXIgZm9yICphbGwqIHNsaWRlcnM6XG4gICAgdmFyIHNsaWRlcnMgPSBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXJcbiAgICAgICAgLnNlbGVjdEFsbCgnZy4nICsgY29uc3RhbnRzLmNvbnRhaW5lckNsYXNzTmFtZSlcbiAgICAgICAgLmRhdGEoc2xpZGVyRGF0YS5sZW5ndGggPiAwID8gWzBdIDogW10pO1xuXG4gICAgc2xpZGVycy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGNvbnN0YW50cy5jb250YWluZXJDbGFzc05hbWUsIHRydWUpXG4gICAgICAgIC5zdHlsZSgnY3Vyc29yJywgJ2V3LXJlc2l6ZScpO1xuXG4gICAgZnVuY3Rpb24gY2xlYXJTbGlkZXIoc2xpZGVyT3B0cykge1xuICAgICAgICBpZihzbGlkZXJPcHRzLl9jb21tYW5kT2JzZXJ2ZXIpIHtcbiAgICAgICAgICAgIHNsaWRlck9wdHMuX2NvbW1hbmRPYnNlcnZlci5yZW1vdmUoKTtcbiAgICAgICAgICAgIGRlbGV0ZSBzbGlkZXJPcHRzLl9jb21tYW5kT2JzZXJ2ZXI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBNb3N0IGNvbXBvbmVudHMgZG9uJ3QgbmVlZCB0byBleHBsaWNpdGx5IHJlbW92ZSBhdXRvTWFyZ2luLCBiZWNhdXNlXG4gICAgICAgIC8vIG1hcmdpblB1c2hlcnMgZG9lcyB0aGlzIC0gYnV0IHNsaWRlciB1cGRhdGVzIGRvbid0IGdvIHRocm91Z2hcbiAgICAgICAgLy8gYSBmdWxsIHJlcGxvdCBzbyB3ZSBuZWVkIHRvIGV4cGxpY2l0bHkgcmVtb3ZlIGl0LlxuICAgICAgICBQbG90cy5hdXRvTWFyZ2luKGdkLCBhdXRvTWFyZ2luSWQoc2xpZGVyT3B0cykpO1xuICAgIH1cblxuICAgIHNsaWRlcnMuZXhpdCgpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5ncm91cENsYXNzTmFtZSlcbiAgICAgICAgICAgIC5lYWNoKGNsZWFyU2xpZGVyKTtcbiAgICB9KVxuICAgIC5yZW1vdmUoKTtcblxuICAgIC8vIFJldHVybiBlYXJseSBpZiBubyBtZW51cyB2aXNpYmxlOlxuICAgIGlmKHNsaWRlckRhdGEubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICB2YXIgc2xpZGVyR3JvdXBzID0gc2xpZGVycy5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5ncm91cENsYXNzTmFtZSlcbiAgICAgICAgLmRhdGEoc2xpZGVyRGF0YSwga2V5RnVuY3Rpb24pO1xuXG4gICAgc2xpZGVyR3JvdXBzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY29uc3RhbnRzLmdyb3VwQ2xhc3NOYW1lLCB0cnVlKTtcblxuICAgIHNsaWRlckdyb3Vwcy5leGl0KClcbiAgICAgICAgLmVhY2goY2xlYXJTbGlkZXIpXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIC8vIEZpbmQgdGhlIGRpbWVuc2lvbnMgb2YgdGhlIHNsaWRlcnM6XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNsaWRlckRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNsaWRlck9wdHMgPSBzbGlkZXJEYXRhW2ldO1xuICAgICAgICBmaW5kRGltZW5zaW9ucyhnZCwgc2xpZGVyT3B0cyk7XG4gICAgfVxuXG4gICAgc2xpZGVyR3JvdXBzLmVhY2goZnVuY3Rpb24oc2xpZGVyT3B0cykge1xuICAgICAgICB2YXIgZ1NsaWRlciA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBjb21wdXRlTGFiZWxTdGVwcyhzbGlkZXJPcHRzKTtcblxuICAgICAgICBQbG90cy5tYW5hZ2VDb21tYW5kT2JzZXJ2ZXIoZ2QsIHNsaWRlck9wdHMsIHNsaWRlck9wdHMuX3Zpc2libGVTdGVwcywgZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgLy8gTkI6IFNhbWUgYXMgYmVsb3cuIFRoaXMgaXMgKm5vdCogYWx3YXlzIHRoZSBzYW1lIGFzIHNsaWRlck9wdHMgc2luY2VcbiAgICAgICAgICAgIC8vIGlmIGEgbmV3IHNldCBvZiBzdGVwcyBjb21lcyBpbiwgdGhlIHJlZmVyZW5jZSBpbiB0aGlzIGNhbGxiYWNrIHdvdWxkXG4gICAgICAgICAgICAvLyBiZSBpbnZhbGlkLiBXZSBuZWVkIHRvIHJlZmV0Y2ggaXQgZnJvbSB0aGUgc2xpZGVyIGdyb3VwLCB3aGljaCBpc1xuICAgICAgICAgICAgLy8gdGhlIGpvaW4gZGF0YSB0aGF0IGNyZWF0ZXMgdGhpcyBzbGlkZXIuIFNvIGlmIHRoaXMgc2xpZGVyIHN0aWxsIGV4aXN0cyxcbiAgICAgICAgICAgIC8vIHRoZSBncm91cCBzaG91bGQgYmUgdmFsaWQsICp0byB0aGUgYmVzdCBvZiBteSBrbm93bGVkZ2UuKiBJZiBub3QsXG4gICAgICAgICAgICAvLyB3ZSdkIGhhdmUgdG8gbG9vayBpdCB1cCBieSBkMyBkYXRhIGpvaW4gaW5kZXgva2V5LlxuICAgICAgICAgICAgdmFyIG9wdHMgPSBnU2xpZGVyLmRhdGEoKVswXTtcblxuICAgICAgICAgICAgaWYob3B0cy5hY3RpdmUgPT09IGRhdGEuaW5kZXgpIHJldHVybjtcbiAgICAgICAgICAgIGlmKG9wdHMuX2RyYWdnaW5nKSByZXR1cm47XG5cbiAgICAgICAgICAgIHNldEFjdGl2ZShnZCwgZ1NsaWRlciwgb3B0cywgZGF0YS5pbmRleCwgZmFsc2UsIHRydWUpO1xuICAgICAgICB9KTtcblxuICAgICAgICBkcmF3U2xpZGVyKGdkLCBkMy5zZWxlY3QodGhpcyksIHNsaWRlck9wdHMpO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gYXV0b01hcmdpbklkKHNsaWRlck9wdHMpIHtcbiAgICByZXR1cm4gY29uc3RhbnRzLmF1dG9NYXJnaW5JZFJvb3QgKyBzbGlkZXJPcHRzLl9pbmRleDtcbn1cblxuLy8gVGhpcyByZWFsbHkgb25seSBqdXN0IGZpbHRlcnMgYnkgdmlzaWJpbGl0eTpcbmZ1bmN0aW9uIG1ha2VTbGlkZXJEYXRhKGZ1bGxMYXlvdXQsIGdkKSB7XG4gICAgdmFyIGNvbnRPcHRzID0gZnVsbExheW91dFtjb25zdGFudHMubmFtZV07XG4gICAgdmFyIHNsaWRlckRhdGEgPSBbXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjb250T3B0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaXRlbSA9IGNvbnRPcHRzW2ldO1xuICAgICAgICBpZighaXRlbS52aXNpYmxlKSBjb250aW51ZTtcbiAgICAgICAgaXRlbS5fZ2QgPSBnZDtcbiAgICAgICAgc2xpZGVyRGF0YS5wdXNoKGl0ZW0pO1xuICAgIH1cblxuICAgIHJldHVybiBzbGlkZXJEYXRhO1xufVxuXG4vLyBUaGlzIGlzIHNldCBpbiB0aGUgZGVmYXVsdHMgc3RlcDpcbmZ1bmN0aW9uIGtleUZ1bmN0aW9uKG9wdHMpIHtcbiAgICByZXR1cm4gb3B0cy5faW5kZXg7XG59XG5cbi8vIENvbXB1dGUgdGhlIGRpbWVuc2lvbnMgKG11dGF0ZXMgc2xpZGVyT3B0cyk6XG5mdW5jdGlvbiBmaW5kRGltZW5zaW9ucyhnZCwgc2xpZGVyT3B0cykge1xuICAgIHZhciBzbGlkZXJMYWJlbHMgPSBEcmF3aW5nLnRlc3Rlci5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5sYWJlbEdyb3VwQ2xhc3MpXG4gICAgICAgIC5kYXRhKHNsaWRlck9wdHMuX3Zpc2libGVTdGVwcyk7XG5cbiAgICBzbGlkZXJMYWJlbHMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjb25zdGFudHMubGFiZWxHcm91cENsYXNzLCB0cnVlKTtcblxuICAgIC8vIGxvb3Agb3ZlciBmYWtlIGJ1dHRvbnMgdG8gZmluZCB3aWR0aCAvIGhlaWdodFxuICAgIHZhciBtYXhMYWJlbFdpZHRoID0gMDtcbiAgICB2YXIgbGFiZWxIZWlnaHQgPSAwO1xuICAgIHNsaWRlckxhYmVscy5lYWNoKGZ1bmN0aW9uKHN0ZXBPcHRzKSB7XG4gICAgICAgIHZhciBsYWJlbEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIHZhciB0ZXh0ID0gZHJhd0xhYmVsKGxhYmVsR3JvdXAsIHtzdGVwOiBzdGVwT3B0c30sIHNsaWRlck9wdHMpO1xuXG4gICAgICAgIHZhciB0ZXh0Tm9kZSA9IHRleHQubm9kZSgpO1xuICAgICAgICBpZih0ZXh0Tm9kZSkge1xuICAgICAgICAgICAgdmFyIGJCb3ggPSBEcmF3aW5nLmJCb3godGV4dE5vZGUpO1xuICAgICAgICAgICAgbGFiZWxIZWlnaHQgPSBNYXRoLm1heChsYWJlbEhlaWdodCwgYkJveC5oZWlnaHQpO1xuICAgICAgICAgICAgbWF4TGFiZWxXaWR0aCA9IE1hdGgubWF4KG1heExhYmVsV2lkdGgsIGJCb3gud2lkdGgpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBzbGlkZXJMYWJlbHMucmVtb3ZlKCk7XG5cbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXMgPSB7fTtcblxuICAgIGRpbXMuaW5wdXRBcmVhV2lkdGggPSBNYXRoLm1heChcbiAgICAgICAgY29uc3RhbnRzLnJhaWxXaWR0aCxcbiAgICAgICAgY29uc3RhbnRzLmdyaXBIZWlnaHRcbiAgICApO1xuXG4gICAgLy8gY2FsY3VsYXRlIHNvbWUgb3ZlcmFsbCBkaW1lbnNpb25zIC0gc29tZSBvZiB0aGVzZSBhcmUgbmVlZGVkIGZvclxuICAgIC8vIGNhbGN1bGF0aW5nIHRoZSBjdXJyZW50VmFsdWUgZGltZW5zaW9uc1xuICAgIHZhciBncmFwaFNpemUgPSBnZC5fZnVsbExheW91dC5fc2l6ZTtcbiAgICBkaW1zLmx4ID0gZ3JhcGhTaXplLmwgKyBncmFwaFNpemUudyAqIHNsaWRlck9wdHMueDtcbiAgICBkaW1zLmx5ID0gZ3JhcGhTaXplLnQgKyBncmFwaFNpemUuaCAqICgxIC0gc2xpZGVyT3B0cy55KTtcblxuICAgIGlmKHNsaWRlck9wdHMubGVubW9kZSA9PT0gJ2ZyYWN0aW9uJykge1xuICAgICAgICAvLyBmcmFjdGlvbjpcbiAgICAgICAgZGltcy5vdXRlckxlbmd0aCA9IE1hdGgucm91bmQoZ3JhcGhTaXplLncgKiBzbGlkZXJPcHRzLmxlbik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcGl4ZWxzOlxuICAgICAgICBkaW1zLm91dGVyTGVuZ3RoID0gc2xpZGVyT3B0cy5sZW47XG4gICAgfVxuXG4gICAgLy8gVGhlIGxlbmd0aCBvZiB0aGUgcmFpbCwgKmV4Y2x1ZGluZyogcGFkZGluZyBvbiBlaXRoZXIgZW5kOlxuICAgIGRpbXMuaW5wdXRBcmVhU3RhcnQgPSAwO1xuICAgIGRpbXMuaW5wdXRBcmVhTGVuZ3RoID0gTWF0aC5yb3VuZChkaW1zLm91dGVyTGVuZ3RoIC0gc2xpZGVyT3B0cy5wYWQubCAtIHNsaWRlck9wdHMucGFkLnIpO1xuXG4gICAgdmFyIHRleHRhYmxlSW5wdXRMZW5ndGggPSBkaW1zLmlucHV0QXJlYUxlbmd0aCAtIDIgKiBjb25zdGFudHMuc3RlcEluc2V0O1xuICAgIHZhciBhdmFpbGFibGVTcGFjZVBlckxhYmVsID0gdGV4dGFibGVJbnB1dExlbmd0aCAvIChzbGlkZXJPcHRzLl9zdGVwQ291bnQgLSAxKTtcbiAgICB2YXIgY29tcHV0ZWRTcGFjZVBlckxhYmVsID0gbWF4TGFiZWxXaWR0aCArIGNvbnN0YW50cy5sYWJlbFBhZGRpbmc7XG4gICAgZGltcy5sYWJlbFN0cmlkZSA9IE1hdGgubWF4KDEsIE1hdGguY2VpbChjb21wdXRlZFNwYWNlUGVyTGFiZWwgLyBhdmFpbGFibGVTcGFjZVBlckxhYmVsKSk7XG4gICAgZGltcy5sYWJlbEhlaWdodCA9IGxhYmVsSGVpZ2h0O1xuXG4gICAgLy8gbG9vcCBvdmVyIGFsbCBwb3NzaWJsZSB2YWx1ZXMgZm9yIGN1cnJlbnRWYWx1ZSB0byBmaW5kIHRoZVxuICAgIC8vIGFyZWEgd2UgbmVlZCBmb3IgaXRcbiAgICBkaW1zLmN1cnJlbnRWYWx1ZU1heFdpZHRoID0gMDtcbiAgICBkaW1zLmN1cnJlbnRWYWx1ZUhlaWdodCA9IDA7XG4gICAgZGltcy5jdXJyZW50VmFsdWVUb3RhbEhlaWdodCA9IDA7XG4gICAgZGltcy5jdXJyZW50VmFsdWVNYXhMaW5lcyA9IDE7XG5cbiAgICBpZihzbGlkZXJPcHRzLmN1cnJlbnR2YWx1ZS52aXNpYmxlKSB7XG4gICAgICAgIC8vIEdldCB0aGUgZGltZW5zaW9ucyBvZiB0aGUgY3VycmVudCB2YWx1ZSBsYWJlbDpcbiAgICAgICAgdmFyIGR1bW15R3JvdXAgPSBEcmF3aW5nLnRlc3Rlci5hcHBlbmQoJ2cnKTtcblxuICAgICAgICBzbGlkZXJMYWJlbHMuZWFjaChmdW5jdGlvbihzdGVwT3B0cykge1xuICAgICAgICAgICAgdmFyIGN1clZhbFByZWZpeCA9IGRyYXdDdXJyZW50VmFsdWUoZHVtbXlHcm91cCwgc2xpZGVyT3B0cywgc3RlcE9wdHMubGFiZWwpO1xuICAgICAgICAgICAgdmFyIGN1clZhbFNpemUgPSAoY3VyVmFsUHJlZml4Lm5vZGUoKSAmJiBEcmF3aW5nLmJCb3goY3VyVmFsUHJlZml4Lm5vZGUoKSkpIHx8IHt3aWR0aDogMCwgaGVpZ2h0OiAwfTtcbiAgICAgICAgICAgIHZhciBsaW5lcyA9IHN2Z1RleHRVdGlscy5saW5lQ291bnQoY3VyVmFsUHJlZml4KTtcbiAgICAgICAgICAgIGRpbXMuY3VycmVudFZhbHVlTWF4V2lkdGggPSBNYXRoLm1heChkaW1zLmN1cnJlbnRWYWx1ZU1heFdpZHRoLCBNYXRoLmNlaWwoY3VyVmFsU2l6ZS53aWR0aCkpO1xuICAgICAgICAgICAgZGltcy5jdXJyZW50VmFsdWVIZWlnaHQgPSBNYXRoLm1heChkaW1zLmN1cnJlbnRWYWx1ZUhlaWdodCwgTWF0aC5jZWlsKGN1clZhbFNpemUuaGVpZ2h0KSk7XG4gICAgICAgICAgICBkaW1zLmN1cnJlbnRWYWx1ZU1heExpbmVzID0gTWF0aC5tYXgoZGltcy5jdXJyZW50VmFsdWVNYXhMaW5lcywgbGluZXMpO1xuICAgICAgICB9KTtcblxuICAgICAgICBkaW1zLmN1cnJlbnRWYWx1ZVRvdGFsSGVpZ2h0ID0gZGltcy5jdXJyZW50VmFsdWVIZWlnaHQgKyBzbGlkZXJPcHRzLmN1cnJlbnR2YWx1ZS5vZmZzZXQ7XG5cbiAgICAgICAgZHVtbXlHcm91cC5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICBkaW1zLmhlaWdodCA9IGRpbXMuY3VycmVudFZhbHVlVG90YWxIZWlnaHQgKyBjb25zdGFudHMudGlja09mZnNldCArIHNsaWRlck9wdHMudGlja2xlbiArIGNvbnN0YW50cy5sYWJlbE9mZnNldCArIGRpbXMubGFiZWxIZWlnaHQgKyBzbGlkZXJPcHRzLnBhZC50ICsgc2xpZGVyT3B0cy5wYWQuYjtcblxuICAgIHZhciB4YW5jaG9yID0gJ2xlZnQnO1xuICAgIGlmKExpYi5pc1JpZ2h0QW5jaG9yKHNsaWRlck9wdHMpKSB7XG4gICAgICAgIGRpbXMubHggLT0gZGltcy5vdXRlckxlbmd0aDtcbiAgICAgICAgeGFuY2hvciA9ICdyaWdodCc7XG4gICAgfVxuICAgIGlmKExpYi5pc0NlbnRlckFuY2hvcihzbGlkZXJPcHRzKSkge1xuICAgICAgICBkaW1zLmx4IC09IGRpbXMub3V0ZXJMZW5ndGggLyAyO1xuICAgICAgICB4YW5jaG9yID0gJ2NlbnRlcic7XG4gICAgfVxuXG4gICAgdmFyIHlhbmNob3IgPSAndG9wJztcbiAgICBpZihMaWIuaXNCb3R0b21BbmNob3Ioc2xpZGVyT3B0cykpIHtcbiAgICAgICAgZGltcy5seSAtPSBkaW1zLmhlaWdodDtcbiAgICAgICAgeWFuY2hvciA9ICdib3R0b20nO1xuICAgIH1cbiAgICBpZihMaWIuaXNNaWRkbGVBbmNob3Ioc2xpZGVyT3B0cykpIHtcbiAgICAgICAgZGltcy5seSAtPSBkaW1zLmhlaWdodCAvIDI7XG4gICAgICAgIHlhbmNob3IgPSAnbWlkZGxlJztcbiAgICB9XG5cbiAgICBkaW1zLm91dGVyTGVuZ3RoID0gTWF0aC5jZWlsKGRpbXMub3V0ZXJMZW5ndGgpO1xuICAgIGRpbXMuaGVpZ2h0ID0gTWF0aC5jZWlsKGRpbXMuaGVpZ2h0KTtcbiAgICBkaW1zLmx4ID0gTWF0aC5yb3VuZChkaW1zLmx4KTtcbiAgICBkaW1zLmx5ID0gTWF0aC5yb3VuZChkaW1zLmx5KTtcblxuICAgIHZhciBtYXJnaW5PcHRzID0ge1xuICAgICAgICB5OiBzbGlkZXJPcHRzLnksXG4gICAgICAgIGI6IGRpbXMuaGVpZ2h0ICogRlJPTV9CUlt5YW5jaG9yXSxcbiAgICAgICAgdDogZGltcy5oZWlnaHQgKiBGUk9NX1RMW3lhbmNob3JdXG4gICAgfTtcblxuICAgIGlmKHNsaWRlck9wdHMubGVubW9kZSA9PT0gJ2ZyYWN0aW9uJykge1xuICAgICAgICBtYXJnaW5PcHRzLmwgPSAwO1xuICAgICAgICBtYXJnaW5PcHRzLnhsID0gc2xpZGVyT3B0cy54IC0gc2xpZGVyT3B0cy5sZW4gKiBGUk9NX1RMW3hhbmNob3JdO1xuICAgICAgICBtYXJnaW5PcHRzLnIgPSAwO1xuICAgICAgICBtYXJnaW5PcHRzLnhyID0gc2xpZGVyT3B0cy54ICsgc2xpZGVyT3B0cy5sZW4gKiBGUk9NX0JSW3hhbmNob3JdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1hcmdpbk9wdHMueCA9IHNsaWRlck9wdHMueDtcbiAgICAgICAgbWFyZ2luT3B0cy5sID0gZGltcy5vdXRlckxlbmd0aCAqIEZST01fVExbeGFuY2hvcl07XG4gICAgICAgIG1hcmdpbk9wdHMuciA9IGRpbXMub3V0ZXJMZW5ndGggKiBGUk9NX0JSW3hhbmNob3JdO1xuICAgIH1cblxuICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsIGF1dG9NYXJnaW5JZChzbGlkZXJPcHRzKSwgbWFyZ2luT3B0cyk7XG59XG5cbmZ1bmN0aW9uIGRyYXdTbGlkZXIoZ2QsIHNsaWRlckdyb3VwLCBzbGlkZXJPcHRzKSB7XG4gICAgLy8gVGhpcyBpcyByZWxhdGVkIHRvIHRoZSBvdGhlciBsb25nIG5vdGVzIGluIHRoaXMgZmlsZSByZWdhcmRpbmcgd2hhdCBoYXBwZW5zXG4gICAgLy8gd2hlbiBzbGlkZXIgc3RlcHMgZGlzYXBwZWFyLiBUaGlzIHBhcnRpY3VsYXIgZml4IGhhbmRsZXMgd2hhdCBoYXBwZW5zIHdoZW5cbiAgICAvLyB0aGUgKmN1cnJlbnQqIHNsaWRlciBzdGVwIGlzIHJlbW92ZWQuIFRoZSBkcmF3aW5nIGZ1bmN0aW9ucyB3aWxsIGVycm9yIG91dFxuICAgIC8vIHdoZW4gdGhleSBmYWlsIHRvIGZpbmQgaXQsIHNvIHRoZSBmaXggZm9yIG5vdyBpcyB0aGF0IGl0IHdpbGwganVzdCBkcmF3IHRoZVxuICAgIC8vIHNsaWRlciBpbiB0aGUgZmlyc3QgcG9zaXRpb24gYnV0IHdpbGwgbm90IGV4ZWN1dGUgdGhlIGNvbW1hbmQuXG4gICAgaWYoISgoc2xpZGVyT3B0cy5zdGVwc1tzbGlkZXJPcHRzLmFjdGl2ZV0gfHwge30pLnZpc2libGUpKSB7XG4gICAgICAgIHNsaWRlck9wdHMuYWN0aXZlID0gc2xpZGVyT3B0cy5fdmlzaWJsZVN0ZXBzWzBdLl9pbmRleDtcbiAgICB9XG5cbiAgICAvLyBUaGVzZSBhcmUgY2FyZWZ1bGx5IG9yZGVyZWQgZm9yIHByb3BlciB6LW9yZGVyaW5nOlxuICAgIHNsaWRlckdyb3VwXG4gICAgICAgIC5jYWxsKGRyYXdDdXJyZW50VmFsdWUsIHNsaWRlck9wdHMpXG4gICAgICAgIC5jYWxsKGRyYXdSYWlsLCBzbGlkZXJPcHRzKVxuICAgICAgICAuY2FsbChkcmF3TGFiZWxHcm91cCwgc2xpZGVyT3B0cylcbiAgICAgICAgLmNhbGwoZHJhd1RpY2tzLCBzbGlkZXJPcHRzKVxuICAgICAgICAuY2FsbChkcmF3VG91Y2hSZWN0LCBnZCwgc2xpZGVyT3B0cylcbiAgICAgICAgLmNhbGwoZHJhd0dyaXAsIGdkLCBzbGlkZXJPcHRzKTtcblxuICAgIHZhciBkaW1zID0gc2xpZGVyT3B0cy5fZGltcztcblxuICAgIC8vIFBvc2l0aW9uIHRoZSByZWN0YW5nbGU6XG4gICAgRHJhd2luZy5zZXRUcmFuc2xhdGUoc2xpZGVyR3JvdXAsIGRpbXMubHggKyBzbGlkZXJPcHRzLnBhZC5sLCBkaW1zLmx5ICsgc2xpZGVyT3B0cy5wYWQudCk7XG5cbiAgICBzbGlkZXJHcm91cC5jYWxsKHNldEdyaXBQb3NpdGlvbiwgc2xpZGVyT3B0cywgZmFsc2UpO1xuICAgIHNsaWRlckdyb3VwLmNhbGwoZHJhd0N1cnJlbnRWYWx1ZSwgc2xpZGVyT3B0cyk7XG59XG5cbmZ1bmN0aW9uIGRyYXdDdXJyZW50VmFsdWUoc2xpZGVyR3JvdXAsIHNsaWRlck9wdHMsIHZhbHVlT3ZlcnJpZGUpIHtcbiAgICBpZighc2xpZGVyT3B0cy5jdXJyZW50dmFsdWUudmlzaWJsZSkgcmV0dXJuO1xuXG4gICAgdmFyIGRpbXMgPSBzbGlkZXJPcHRzLl9kaW1zO1xuICAgIHZhciB4MCwgdGV4dEFuY2hvcjtcblxuICAgIHN3aXRjaChzbGlkZXJPcHRzLmN1cnJlbnR2YWx1ZS54YW5jaG9yKSB7XG4gICAgICAgIGNhc2UgJ3JpZ2h0JzpcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgYW5jaG9yZWQgbGVmdCBhbmQgYWRqdXN0ZWQgYnkgdGhlIHdpZHRoIG9mIHRoZSBsb25nZXN0IGxhYmVsXG4gICAgICAgICAgICAvLyBzbyB0aGF0IHRoZSBwcmVmaXggZG9lc24ndCBtb3ZlLiBUaGUgZ29hbCBvZiB0aGlzIGlzIHRvIGVtcGhhc2l6ZVxuICAgICAgICAgICAgLy8gd2hhdCdzIGFjdHVhbGx5IGNoYW5naW5nIGFuZCBtYWtlIHRoZSB1cGRhdGUgbGVzcyBkaXN0cmFjdGluZy5cbiAgICAgICAgICAgIHgwID0gZGltcy5pbnB1dEFyZWFMZW5ndGggLSBjb25zdGFudHMuY3VycmVudFZhbHVlSW5zZXQgLSBkaW1zLmN1cnJlbnRWYWx1ZU1heFdpZHRoO1xuICAgICAgICAgICAgdGV4dEFuY2hvciA9ICdsZWZ0JztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdjZW50ZXInOlxuICAgICAgICAgICAgeDAgPSBkaW1zLmlucHV0QXJlYUxlbmd0aCAqIDAuNTtcbiAgICAgICAgICAgIHRleHRBbmNob3IgPSAnbWlkZGxlJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgeDAgPSBjb25zdGFudHMuY3VycmVudFZhbHVlSW5zZXQ7XG4gICAgICAgICAgICB0ZXh0QW5jaG9yID0gJ2xlZnQnO1xuICAgIH1cblxuICAgIHZhciB0ZXh0ID0gTGliLmVuc3VyZVNpbmdsZShzbGlkZXJHcm91cCwgJ3RleHQnLCBjb25zdGFudHMubGFiZWxDbGFzcywgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmNsYXNzZWQoJ3VzZXItc2VsZWN0LW5vbmUnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6IHRleHRBbmNob3IsXG4gICAgICAgICAgICAgICAgJ2RhdGEtbm90ZXgnOiAxXG4gICAgICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIHZhciBzdHIgPSBzbGlkZXJPcHRzLmN1cnJlbnR2YWx1ZS5wcmVmaXggPyBzbGlkZXJPcHRzLmN1cnJlbnR2YWx1ZS5wcmVmaXggOiAnJztcblxuICAgIGlmKHR5cGVvZiB2YWx1ZU92ZXJyaWRlID09PSAnc3RyaW5nJykge1xuICAgICAgICBzdHIgKz0gdmFsdWVPdmVycmlkZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgY3VyVmFsID0gc2xpZGVyT3B0cy5zdGVwc1tzbGlkZXJPcHRzLmFjdGl2ZV0ubGFiZWw7XG4gICAgICAgIHZhciBfbWV0YSA9IHNsaWRlck9wdHMuX2dkLl9mdWxsTGF5b3V0Ll9tZXRhO1xuICAgICAgICBpZihfbWV0YSkgY3VyVmFsID0gTGliLnRlbXBsYXRlU3RyaW5nKGN1clZhbCwgX21ldGEpO1xuICAgICAgICBzdHIgKz0gY3VyVmFsO1xuICAgIH1cblxuICAgIGlmKHNsaWRlck9wdHMuY3VycmVudHZhbHVlLnN1ZmZpeCkge1xuICAgICAgICBzdHIgKz0gc2xpZGVyT3B0cy5jdXJyZW50dmFsdWUuc3VmZml4O1xuICAgIH1cblxuICAgIHRleHQuY2FsbChEcmF3aW5nLmZvbnQsIHNsaWRlck9wdHMuY3VycmVudHZhbHVlLmZvbnQpXG4gICAgICAgIC50ZXh0KHN0cilcbiAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgc2xpZGVyT3B0cy5fZ2QpO1xuXG4gICAgdmFyIGxpbmVzID0gc3ZnVGV4dFV0aWxzLmxpbmVDb3VudCh0ZXh0KTtcblxuICAgIHZhciB5MCA9IChkaW1zLmN1cnJlbnRWYWx1ZU1heExpbmVzICsgMSAtIGxpbmVzKSAqXG4gICAgICAgIHNsaWRlck9wdHMuY3VycmVudHZhbHVlLmZvbnQuc2l6ZSAqIExJTkVfU1BBQ0lORztcblxuICAgIHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQodGV4dCwgeDAsIHkwKTtcblxuICAgIHJldHVybiB0ZXh0O1xufVxuXG5mdW5jdGlvbiBkcmF3R3JpcChzbGlkZXJHcm91cCwgZ2QsIHNsaWRlck9wdHMpIHtcbiAgICB2YXIgZ3JpcCA9IExpYi5lbnN1cmVTaW5nbGUoc2xpZGVyR3JvdXAsICdyZWN0JywgY29uc3RhbnRzLmdyaXBSZWN0Q2xhc3MsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5jYWxsKGF0dGFjaEdyaXBFdmVudHMsIGdkLCBzbGlkZXJHcm91cCwgc2xpZGVyT3B0cylcbiAgICAgICAgICAgIC5zdHlsZSgncG9pbnRlci1ldmVudHMnLCAnYWxsJyk7XG4gICAgfSk7XG5cbiAgICBncmlwLmF0dHIoe1xuICAgICAgICB3aWR0aDogY29uc3RhbnRzLmdyaXBXaWR0aCxcbiAgICAgICAgaGVpZ2h0OiBjb25zdGFudHMuZ3JpcEhlaWdodCxcbiAgICAgICAgcng6IGNvbnN0YW50cy5ncmlwUmFkaXVzLFxuICAgICAgICByeTogY29uc3RhbnRzLmdyaXBSYWRpdXMsXG4gICAgfSlcbiAgICAuY2FsbChDb2xvci5zdHJva2UsIHNsaWRlck9wdHMuYm9yZGVyY29sb3IpXG4gICAgLmNhbGwoQ29sb3IuZmlsbCwgc2xpZGVyT3B0cy5iZ2NvbG9yKVxuICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgc2xpZGVyT3B0cy5ib3JkZXJ3aWR0aCArICdweCcpO1xufVxuXG5mdW5jdGlvbiBkcmF3TGFiZWwoaXRlbSwgZGF0YSwgc2xpZGVyT3B0cykge1xuICAgIHZhciB0ZXh0ID0gTGliLmVuc3VyZVNpbmdsZShpdGVtLCAndGV4dCcsIGNvbnN0YW50cy5sYWJlbENsYXNzLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuY2xhc3NlZCgndXNlci1zZWxlY3Qtbm9uZScsIHRydWUpXG4gICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZScsXG4gICAgICAgICAgICAgICAgJ2RhdGEtbm90ZXgnOiAxXG4gICAgICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIHZhciB0eCA9IGRhdGEuc3RlcC5sYWJlbDtcbiAgICB2YXIgX21ldGEgPSBzbGlkZXJPcHRzLl9nZC5fZnVsbExheW91dC5fbWV0YTtcbiAgICBpZihfbWV0YSkgdHggPSBMaWIudGVtcGxhdGVTdHJpbmcodHgsIF9tZXRhKTtcblxuICAgIHRleHQuY2FsbChEcmF3aW5nLmZvbnQsIHNsaWRlck9wdHMuZm9udClcbiAgICAgICAgLnRleHQodHgpXG4gICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIHNsaWRlck9wdHMuX2dkKTtcblxuICAgIHJldHVybiB0ZXh0O1xufVxuXG5mdW5jdGlvbiBkcmF3TGFiZWxHcm91cChzbGlkZXJHcm91cCwgc2xpZGVyT3B0cykge1xuICAgIHZhciBsYWJlbHMgPSBMaWIuZW5zdXJlU2luZ2xlKHNsaWRlckdyb3VwLCAnZycsIGNvbnN0YW50cy5sYWJlbHNDbGFzcyk7XG4gICAgdmFyIGRpbXMgPSBzbGlkZXJPcHRzLl9kaW1zO1xuXG4gICAgdmFyIGxhYmVsSXRlbXMgPSBsYWJlbHMuc2VsZWN0QWxsKCdnLicgKyBjb25zdGFudHMubGFiZWxHcm91cENsYXNzKVxuICAgICAgICAuZGF0YShkaW1zLmxhYmVsU3RlcHMpO1xuXG4gICAgbGFiZWxJdGVtcy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGNvbnN0YW50cy5sYWJlbEdyb3VwQ2xhc3MsIHRydWUpO1xuXG4gICAgbGFiZWxJdGVtcy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBsYWJlbEl0ZW1zLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgaXRlbSA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBpdGVtLmNhbGwoZHJhd0xhYmVsLCBkLCBzbGlkZXJPcHRzKTtcblxuICAgICAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShpdGVtLFxuICAgICAgICAgICAgbm9ybWFsaXplZFZhbHVlVG9Qb3NpdGlvbihzbGlkZXJPcHRzLCBkLmZyYWN0aW9uKSxcbiAgICAgICAgICAgIGNvbnN0YW50cy50aWNrT2Zmc2V0ICtcbiAgICAgICAgICAgICAgICBzbGlkZXJPcHRzLnRpY2tsZW4gK1xuICAgICAgICAgICAgICAgIC8vIHBvc2l0aW9uIGlzIHRoZSBiYXNlbGluZSBvZiB0aGUgdG9wIGxpbmUgb2YgdGV4dCBvbmx5LCBldmVuXG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGxhYmVsIHNwYW5zIG11bHRpcGxlIGxpbmVzXG4gICAgICAgICAgICAgICAgc2xpZGVyT3B0cy5mb250LnNpemUgKiBMSU5FX1NQQUNJTkcgK1xuICAgICAgICAgICAgICAgIGNvbnN0YW50cy5sYWJlbE9mZnNldCArXG4gICAgICAgICAgICAgICAgZGltcy5jdXJyZW50VmFsdWVUb3RhbEhlaWdodFxuICAgICAgICApO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVJbnB1dChnZCwgc2xpZGVyR3JvdXAsIHNsaWRlck9wdHMsIG5vcm1hbGl6ZWRQb3NpdGlvbiwgZG9UcmFuc2l0aW9uKSB7XG4gICAgdmFyIHF1YW50aXplZFBvc2l0aW9uID0gTWF0aC5yb3VuZChub3JtYWxpemVkUG9zaXRpb24gKiAoc2xpZGVyT3B0cy5fc3RlcENvdW50IC0gMSkpO1xuICAgIHZhciBxdWFudGl6ZWRJbmRleCA9IHNsaWRlck9wdHMuX3Zpc2libGVTdGVwc1txdWFudGl6ZWRQb3NpdGlvbl0uX2luZGV4O1xuXG4gICAgaWYocXVhbnRpemVkSW5kZXggIT09IHNsaWRlck9wdHMuYWN0aXZlKSB7XG4gICAgICAgIHNldEFjdGl2ZShnZCwgc2xpZGVyR3JvdXAsIHNsaWRlck9wdHMsIHF1YW50aXplZEluZGV4LCB0cnVlLCBkb1RyYW5zaXRpb24pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc2V0QWN0aXZlKGdkLCBzbGlkZXJHcm91cCwgc2xpZGVyT3B0cywgaW5kZXgsIGRvQ2FsbGJhY2ssIGRvVHJhbnNpdGlvbikge1xuICAgIHZhciBwcmV2aW91c0FjdGl2ZSA9IHNsaWRlck9wdHMuYWN0aXZlO1xuICAgIHNsaWRlck9wdHMuYWN0aXZlID0gaW5kZXg7XG5cbiAgICAvLyBkdWUgdG8gdGVtcGxhdGluZywgaXQncyBwb3NzaWJsZSB0aGlzIHNsaWRlciBkb2Vzbid0IGV2ZW4gZXhpc3QgeWV0XG4gICAgYXJyYXlFZGl0b3IoZ2QubGF5b3V0LCBjb25zdGFudHMubmFtZSwgc2xpZGVyT3B0cylcbiAgICAgICAgLmFwcGx5VXBkYXRlKCdhY3RpdmUnLCBpbmRleCk7XG5cbiAgICB2YXIgc3RlcCA9IHNsaWRlck9wdHMuc3RlcHNbc2xpZGVyT3B0cy5hY3RpdmVdO1xuXG4gICAgc2xpZGVyR3JvdXAuY2FsbChzZXRHcmlwUG9zaXRpb24sIHNsaWRlck9wdHMsIGRvVHJhbnNpdGlvbik7XG4gICAgc2xpZGVyR3JvdXAuY2FsbChkcmF3Q3VycmVudFZhbHVlLCBzbGlkZXJPcHRzKTtcblxuICAgIGdkLmVtaXQoJ3Bsb3RseV9zbGlkZXJjaGFuZ2UnLCB7XG4gICAgICAgIHNsaWRlcjogc2xpZGVyT3B0cyxcbiAgICAgICAgc3RlcDogc2xpZGVyT3B0cy5zdGVwc1tzbGlkZXJPcHRzLmFjdGl2ZV0sXG4gICAgICAgIGludGVyYWN0aW9uOiBkb0NhbGxiYWNrLFxuICAgICAgICBwcmV2aW91c0FjdGl2ZTogcHJldmlvdXNBY3RpdmVcbiAgICB9KTtcblxuICAgIGlmKHN0ZXAgJiYgc3RlcC5tZXRob2QgJiYgZG9DYWxsYmFjaykge1xuICAgICAgICBpZihzbGlkZXJHcm91cC5fbmV4dE1ldGhvZCkge1xuICAgICAgICAgICAgLy8gSWYgd2UndmUgYWxyZWFkeSBxdWV1ZWQgdXAgYW4gdXBkYXRlLCBqdXN0IG92ZXJ3cml0ZSBpdCB3aXRoIHRoZSBtb3N0IHJlY2VudDpcbiAgICAgICAgICAgIHNsaWRlckdyb3VwLl9uZXh0TWV0aG9kLnN0ZXAgPSBzdGVwO1xuICAgICAgICAgICAgc2xpZGVyR3JvdXAuX25leHRNZXRob2QuZG9DYWxsYmFjayA9IGRvQ2FsbGJhY2s7XG4gICAgICAgICAgICBzbGlkZXJHcm91cC5fbmV4dE1ldGhvZC5kb1RyYW5zaXRpb24gPSBkb1RyYW5zaXRpb247XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzbGlkZXJHcm91cC5fbmV4dE1ldGhvZCA9IHtzdGVwOiBzdGVwLCBkb0NhbGxiYWNrOiBkb0NhbGxiYWNrLCBkb1RyYW5zaXRpb246IGRvVHJhbnNpdGlvbn07XG4gICAgICAgICAgICBzbGlkZXJHcm91cC5fbmV4dE1ldGhvZFJhZiA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgdmFyIF9zdGVwID0gc2xpZGVyR3JvdXAuX25leHRNZXRob2Quc3RlcDtcbiAgICAgICAgICAgICAgICBpZighX3N0ZXAubWV0aG9kKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICBpZihfc3RlcC5leGVjdXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIFBsb3RzLmV4ZWN1dGVBUElDb21tYW5kKGdkLCBfc3RlcC5tZXRob2QsIF9zdGVwLmFyZ3MpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHNsaWRlckdyb3VwLl9uZXh0TWV0aG9kID0gbnVsbDtcbiAgICAgICAgICAgICAgICBzbGlkZXJHcm91cC5fbmV4dE1ldGhvZFJhZiA9IG51bGw7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gYXR0YWNoR3JpcEV2ZW50cyhpdGVtLCBnZCwgc2xpZGVyR3JvdXApIHtcbiAgICB2YXIgbm9kZSA9IHNsaWRlckdyb3VwLm5vZGUoKTtcbiAgICB2YXIgJGdkID0gZDMuc2VsZWN0KGdkKTtcblxuICAgIC8vIE5COiBUaGlzIGlzICpub3QqIHRoZSBzYW1lIGFzIHNsaWRlck9wdHMgaXRzZWxmISBUaGVzZSBjYWxsYmFja3NcbiAgICAvLyBhcmUgaW4gYSBjbG9zdXJlIHNvIHRoaXMgYXJyYXkgd29uJ3QgYWN0dWFsbHkgYmUgY29ycmVjdCBpZiB0aGVcbiAgICAvLyBzdGVwcyBoYXZlIGNoYW5nZWQgc2luY2UgdGhpcyB3YXMgaW5pdGlhbGl6ZWQuIFRoZSBzbGlkZXJHcm91cCxcbiAgICAvLyBob3dldmVyLCBoYXMgbm90IGNoYW5nZWQgc2luY2UgdGhhdCAqaXMqIHRoZSBzbGlkZXIsIHNvIGl0IG11c3RcbiAgICAvLyBiZSBwcmVzZW50IHRvIHJlY2VpdmUgbW91c2UgZXZlbnRzLlxuICAgIGZ1bmN0aW9uIGdldFNsaWRlck9wdHMoKSB7XG4gICAgICAgIHJldHVybiBzbGlkZXJHcm91cC5kYXRhKClbMF07XG4gICAgfVxuXG4gICAgaXRlbS5vbignbW91c2Vkb3duJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBzbGlkZXJPcHRzID0gZ2V0U2xpZGVyT3B0cygpO1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfc2xpZGVyc3RhcnQnLCB7c2xpZGVyOiBzbGlkZXJPcHRzfSk7XG5cbiAgICAgICAgdmFyIGdyaXAgPSBzbGlkZXJHcm91cC5zZWxlY3QoJy4nICsgY29uc3RhbnRzLmdyaXBSZWN0Q2xhc3MpO1xuXG4gICAgICAgIGQzLmV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBkMy5ldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBncmlwLmNhbGwoQ29sb3IuZmlsbCwgc2xpZGVyT3B0cy5hY3RpdmViZ2NvbG9yKTtcblxuICAgICAgICB2YXIgbm9ybWFsaXplZFBvc2l0aW9uID0gcG9zaXRpb25Ub05vcm1hbGl6ZWRWYWx1ZShzbGlkZXJPcHRzLCBkMy5tb3VzZShub2RlKVswXSk7XG4gICAgICAgIGhhbmRsZUlucHV0KGdkLCBzbGlkZXJHcm91cCwgc2xpZGVyT3B0cywgbm9ybWFsaXplZFBvc2l0aW9uLCB0cnVlKTtcbiAgICAgICAgc2xpZGVyT3B0cy5fZHJhZ2dpbmcgPSB0cnVlO1xuXG4gICAgICAgICRnZC5vbignbW91c2Vtb3ZlJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgc2xpZGVyT3B0cyA9IGdldFNsaWRlck9wdHMoKTtcbiAgICAgICAgICAgIHZhciBub3JtYWxpemVkUG9zaXRpb24gPSBwb3NpdGlvblRvTm9ybWFsaXplZFZhbHVlKHNsaWRlck9wdHMsIGQzLm1vdXNlKG5vZGUpWzBdKTtcbiAgICAgICAgICAgIGhhbmRsZUlucHV0KGdkLCBzbGlkZXJHcm91cCwgc2xpZGVyT3B0cywgbm9ybWFsaXplZFBvc2l0aW9uLCBmYWxzZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgICRnZC5vbignbW91c2V1cCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHNsaWRlck9wdHMgPSBnZXRTbGlkZXJPcHRzKCk7XG4gICAgICAgICAgICBzbGlkZXJPcHRzLl9kcmFnZ2luZyA9IGZhbHNlO1xuICAgICAgICAgICAgZ3JpcC5jYWxsKENvbG9yLmZpbGwsIHNsaWRlck9wdHMuYmdjb2xvcik7XG4gICAgICAgICAgICAkZ2Qub24oJ21vdXNldXAnLCBudWxsKTtcbiAgICAgICAgICAgICRnZC5vbignbW91c2Vtb3ZlJywgbnVsbCk7XG5cbiAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9zbGlkZXJlbmQnLCB7XG4gICAgICAgICAgICAgICAgc2xpZGVyOiBzbGlkZXJPcHRzLFxuICAgICAgICAgICAgICAgIHN0ZXA6IHNsaWRlck9wdHMuc3RlcHNbc2xpZGVyT3B0cy5hY3RpdmVdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGRyYXdUaWNrcyhzbGlkZXJHcm91cCwgc2xpZGVyT3B0cykge1xuICAgIHZhciB0aWNrID0gc2xpZGVyR3JvdXAuc2VsZWN0QWxsKCdyZWN0LicgKyBjb25zdGFudHMudGlja1JlY3RDbGFzcylcbiAgICAgICAgLmRhdGEoc2xpZGVyT3B0cy5fdmlzaWJsZVN0ZXBzKTtcbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXM7XG5cbiAgICB0aWNrLmVudGVyKCkuYXBwZW5kKCdyZWN0JylcbiAgICAgICAgLmNsYXNzZWQoY29uc3RhbnRzLnRpY2tSZWN0Q2xhc3MsIHRydWUpO1xuXG4gICAgdGljay5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICB0aWNrLmF0dHIoe1xuICAgICAgICB3aWR0aDogc2xpZGVyT3B0cy50aWNrd2lkdGggKyAncHgnLFxuICAgICAgICAnc2hhcGUtcmVuZGVyaW5nJzogJ2NyaXNwRWRnZXMnXG4gICAgfSk7XG5cbiAgICB0aWNrLmVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICB2YXIgaXNNYWpvciA9IGkgJSBkaW1zLmxhYmVsU3RyaWRlID09PSAwO1xuICAgICAgICB2YXIgaXRlbSA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBpdGVtXG4gICAgICAgICAgICAuYXR0cih7aGVpZ2h0OiBpc01ham9yID8gc2xpZGVyT3B0cy50aWNrbGVuIDogc2xpZGVyT3B0cy5taW5vcnRpY2tsZW59KVxuICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgaXNNYWpvciA/IHNsaWRlck9wdHMudGlja2NvbG9yIDogc2xpZGVyT3B0cy50aWNrY29sb3IpO1xuXG4gICAgICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKGl0ZW0sXG4gICAgICAgICAgICBub3JtYWxpemVkVmFsdWVUb1Bvc2l0aW9uKHNsaWRlck9wdHMsIGkgLyAoc2xpZGVyT3B0cy5fc3RlcENvdW50IC0gMSkpIC0gMC41ICogc2xpZGVyT3B0cy50aWNrd2lkdGgsXG4gICAgICAgICAgICAoaXNNYWpvciA/IGNvbnN0YW50cy50aWNrT2Zmc2V0IDogY29uc3RhbnRzLm1pbm9yVGlja09mZnNldCkgKyBkaW1zLmN1cnJlbnRWYWx1ZVRvdGFsSGVpZ2h0XG4gICAgICAgICk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVMYWJlbFN0ZXBzKHNsaWRlck9wdHMpIHtcbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXM7XG4gICAgZGltcy5sYWJlbFN0ZXBzID0gW107XG4gICAgdmFyIG5zdGVwcyA9IHNsaWRlck9wdHMuX3N0ZXBDb3VudDtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBuc3RlcHM7IGkgKz0gZGltcy5sYWJlbFN0cmlkZSkge1xuICAgICAgICBkaW1zLmxhYmVsU3RlcHMucHVzaCh7XG4gICAgICAgICAgICBmcmFjdGlvbjogaSAvIChuc3RlcHMgLSAxKSxcbiAgICAgICAgICAgIHN0ZXA6IHNsaWRlck9wdHMuX3Zpc2libGVTdGVwc1tpXVxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldEdyaXBQb3NpdGlvbihzbGlkZXJHcm91cCwgc2xpZGVyT3B0cywgZG9UcmFuc2l0aW9uKSB7XG4gICAgdmFyIGdyaXAgPSBzbGlkZXJHcm91cC5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5ncmlwUmVjdENsYXNzKTtcblxuICAgIHZhciBxdWFudGl6ZWRJbmRleCA9IDA7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNsaWRlck9wdHMuX3N0ZXBDb3VudDsgaSsrKSB7XG4gICAgICAgIGlmKHNsaWRlck9wdHMuX3Zpc2libGVTdGVwc1tpXS5faW5kZXggPT09IHNsaWRlck9wdHMuYWN0aXZlKSB7XG4gICAgICAgICAgICBxdWFudGl6ZWRJbmRleCA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB4ID0gbm9ybWFsaXplZFZhbHVlVG9Qb3NpdGlvbihzbGlkZXJPcHRzLCBxdWFudGl6ZWRJbmRleCAvIChzbGlkZXJPcHRzLl9zdGVwQ291bnQgLSAxKSk7XG5cbiAgICAvLyBJZiB0aGlzIGlzIHRydWUsIHRoZW4gKnRoaXMgY29tcG9uZW50KiBpcyBhbHJlYWR5IGludm9raW5nIGl0cyBvd24gY29tbWFuZFxuICAgIC8vIGFuZCBoYXMgdHJpZ2dlcmVkIGl0cyBvd24gYW5pbWF0aW9uLlxuICAgIGlmKHNsaWRlck9wdHMuX2ludm9raW5nQ29tbWFuZCkgcmV0dXJuO1xuXG4gICAgdmFyIGVsID0gZ3JpcDtcbiAgICBpZihkb1RyYW5zaXRpb24gJiYgc2xpZGVyT3B0cy50cmFuc2l0aW9uLmR1cmF0aW9uID4gMCkge1xuICAgICAgICBlbCA9IGVsLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgLmR1cmF0aW9uKHNsaWRlck9wdHMudHJhbnNpdGlvbi5kdXJhdGlvbilcbiAgICAgICAgICAgIC5lYXNlKHNsaWRlck9wdHMudHJhbnNpdGlvbi5lYXNpbmcpO1xuICAgIH1cblxuICAgIC8vIERyYXdpbmcuc2V0VHJhbnNsYXRlIGRvZXNuJ3Qgd29yayBoZXJlIGJlY2FzdWUgb2YgdGhlIHRyYW5zaXRpb24gZHVjay10eXBpbmcuXG4gICAgLy8gSXQncyBhbHNvIG5vdCBuZWNlc3NhcnkgYmVjYXVzZSB0aGVyZSBhcmUgbm8gb3RoZXIgdHJhbnNpdGlvbnMgdG8gcHJlc2VydmUuXG4gICAgZWwuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgKHggLSBjb25zdGFudHMuZ3JpcFdpZHRoICogMC41KSArICcsJyArIChzbGlkZXJPcHRzLl9kaW1zLmN1cnJlbnRWYWx1ZVRvdGFsSGVpZ2h0KSArICcpJyk7XG59XG5cbi8vIENvbnZlcnQgYSBudW1iZXIgZnJvbSBbMC0xXSB0byBhIHBpeGVsIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBzbGlkZXIgZ3JvdXAgY29udGFpbmVyOlxuZnVuY3Rpb24gbm9ybWFsaXplZFZhbHVlVG9Qb3NpdGlvbihzbGlkZXJPcHRzLCBub3JtYWxpemVkUG9zaXRpb24pIHtcbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXM7XG4gICAgcmV0dXJuIGRpbXMuaW5wdXRBcmVhU3RhcnQgKyBjb25zdGFudHMuc3RlcEluc2V0ICtcbiAgICAgICAgKGRpbXMuaW5wdXRBcmVhTGVuZ3RoIC0gMiAqIGNvbnN0YW50cy5zdGVwSW5zZXQpICogTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgbm9ybWFsaXplZFBvc2l0aW9uKSk7XG59XG5cbi8vIENvbnZlcnQgYSBwb3NpdGlvbiByZWxhdGl2ZSB0byB0aGUgc2xpZGVyIGdyb3VwIHRvIGEgbnVibWVyIGluIFswLCAxXVxuZnVuY3Rpb24gcG9zaXRpb25Ub05vcm1hbGl6ZWRWYWx1ZShzbGlkZXJPcHRzLCBwb3NpdGlvbikge1xuICAgIHZhciBkaW1zID0gc2xpZGVyT3B0cy5fZGltcztcbiAgICByZXR1cm4gTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgKHBvc2l0aW9uIC0gY29uc3RhbnRzLnN0ZXBJbnNldCAtIGRpbXMuaW5wdXRBcmVhU3RhcnQpIC8gKGRpbXMuaW5wdXRBcmVhTGVuZ3RoIC0gMiAqIGNvbnN0YW50cy5zdGVwSW5zZXQgLSAyICogZGltcy5pbnB1dEFyZWFTdGFydCkpKTtcbn1cblxuZnVuY3Rpb24gZHJhd1RvdWNoUmVjdChzbGlkZXJHcm91cCwgZ2QsIHNsaWRlck9wdHMpIHtcbiAgICB2YXIgZGltcyA9IHNsaWRlck9wdHMuX2RpbXM7XG4gICAgdmFyIHJlY3QgPSBMaWIuZW5zdXJlU2luZ2xlKHNsaWRlckdyb3VwLCAncmVjdCcsIGNvbnN0YW50cy5yYWlsVG91Y2hSZWN0Q2xhc3MsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5jYWxsKGF0dGFjaEdyaXBFdmVudHMsIGdkLCBzbGlkZXJHcm91cCwgc2xpZGVyT3B0cylcbiAgICAgICAgICAgIC5zdHlsZSgncG9pbnRlci1ldmVudHMnLCAnYWxsJyk7XG4gICAgfSk7XG5cbiAgICByZWN0LmF0dHIoe1xuICAgICAgICB3aWR0aDogZGltcy5pbnB1dEFyZWFMZW5ndGgsXG4gICAgICAgIGhlaWdodDogTWF0aC5tYXgoZGltcy5pbnB1dEFyZWFXaWR0aCwgY29uc3RhbnRzLnRpY2tPZmZzZXQgKyBzbGlkZXJPcHRzLnRpY2tsZW4gKyBkaW1zLmxhYmVsSGVpZ2h0KVxuICAgIH0pXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIHNsaWRlck9wdHMuYmdjb2xvcilcbiAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAwKTtcblxuICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKHJlY3QsIDAsIGRpbXMuY3VycmVudFZhbHVlVG90YWxIZWlnaHQpO1xufVxuXG5mdW5jdGlvbiBkcmF3UmFpbChzbGlkZXJHcm91cCwgc2xpZGVyT3B0cykge1xuICAgIHZhciBkaW1zID0gc2xpZGVyT3B0cy5fZGltcztcbiAgICB2YXIgY29tcHV0ZWRMZW5ndGggPSBkaW1zLmlucHV0QXJlYUxlbmd0aCAtIGNvbnN0YW50cy5yYWlsSW5zZXQgKiAyO1xuICAgIHZhciByZWN0ID0gTGliLmVuc3VyZVNpbmdsZShzbGlkZXJHcm91cCwgJ3JlY3QnLCBjb25zdGFudHMucmFpbFJlY3RDbGFzcyk7XG5cbiAgICByZWN0LmF0dHIoe1xuICAgICAgICB3aWR0aDogY29tcHV0ZWRMZW5ndGgsXG4gICAgICAgIGhlaWdodDogY29uc3RhbnRzLnJhaWxXaWR0aCxcbiAgICAgICAgcng6IGNvbnN0YW50cy5yYWlsUmFkaXVzLFxuICAgICAgICByeTogY29uc3RhbnRzLnJhaWxSYWRpdXMsXG4gICAgICAgICdzaGFwZS1yZW5kZXJpbmcnOiAnY3Jpc3BFZGdlcydcbiAgICB9KVxuICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgc2xpZGVyT3B0cy5ib3JkZXJjb2xvcilcbiAgICAuY2FsbChDb2xvci5maWxsLCBzbGlkZXJPcHRzLmJnY29sb3IpXG4gICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBzbGlkZXJPcHRzLmJvcmRlcndpZHRoICsgJ3B4Jyk7XG5cbiAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShyZWN0LFxuICAgICAgICBjb25zdGFudHMucmFpbEluc2V0LFxuICAgICAgICAoZGltcy5pbnB1dEFyZWFXaWR0aCAtIGNvbnN0YW50cy5yYWlsV2lkdGgpICogMC41ICsgZGltcy5jdXJyZW50VmFsdWVUb3RhbEhlaWdodFxuICAgICk7XG59XG5cbn0se1wiLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudFwiOjY4OCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9wbG90cy9wbG90c1wiOjgyOCxcIi4uL2NvbG9yXCI6NTkzLFwiLi4vZHJhd2luZ1wiOjYxNCxcIi4vY29uc3RhbnRzXCI6Njc3LFwiZDNcIjoxNjN9XSw2ODA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2NvbXBvbmVudCcsXG4gICAgbmFtZTogY29uc3RhbnRzLm5hbWUsXG5cbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlMYXlvdXREZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuXG4gICAgZHJhdzogX2RlcmVxXygnLi9kcmF3Jylcbn07XG5cbn0se1wiLi9hdHRyaWJ1dGVzXCI6Njc2LFwiLi9jb25zdGFudHNcIjo2NzcsXCIuL2RlZmF1bHRzXCI6Njc4LFwiLi9kcmF3XCI6Njc5fV0sNjgxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBQbG90cyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL3Bsb3RzJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi9kcmF3aW5nJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb2xvcicpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIGludGVyYWN0Q29uc3RhbnRzID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2ludGVyYWN0aW9ucycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBkcmF3OiBkcmF3XG59O1xuXG52YXIgbnVtU3RyaXBSRSA9IC8gW1hZXVswLTldKiAvO1xuXG4vKipcbiAqIFRpdGxlcyAtIChyZSlkcmF3IHRpdGxlcyBvbiB0aGUgYXhlcyBhbmQgcGxvdDpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkIC0gdGhlIGdyYXBoRGl2XG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVDbGFzcyAtIHRoZSBjc3MgY2xhc3Mgb2YgdGhpcyB0aXRsZVxuICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgLSBob3cgYW5kIHdoYXQgdG8gZHJhd1xuICogICAgICBwcm9wQ29udGFpbmVyIC0gdGhlIGxheW91dCBvYmplY3QgY29udGFpbmluZyBgdGl0bGVgIGFuZCBgdGl0bGVmb250YFxuICogICAgICAgICAgYXR0cmlidXRlcyB0aGF0IGFwcGx5IHRvIHRoaXMgdGl0bGVcbiAqICAgICAgcHJvcE5hbWUgLSB0aGUgZnVsbCBuYW1lIG9mIHRoZSB0aXRsZSBwcm9wZXJ0eSAoZm9yIFBsb3RseS5yZWxheW91dClcbiAqICAgICAgW3RyYWNlSW5kZXhdIC0gaW5jbHVkZSBvbmx5IGlmIHRoaXMgcHJvcGVydHkgYXBwbGllcyB0byBvbmUgdHJhY2VcbiAqICAgICAgICAgIChzdWNoIGFzIGEgY29sb3JiYXIgdGl0bGUpIC0gdGhlbiBlZGl0aW5nIHBpcGVzIHRvIFBsb3RseS5yZXN0eWxlXG4gKiAgICAgICAgICBpbnN0ZWFkIG9mIFBsb3RseS5yZWxheW91dFxuICogICAgICBwbGFjZWhvbGRlciAtIHBsYWNlaG9sZGVyIHRleHQgZm9yIGFuIGVtcHR5IGVkaXRhYmxlIHRpdGxlXG4gKiAgICAgIFthdm9pZF0ge29iamVjdH0gLSBpbmNsdWRlIGlmIHRoaXMgdGl0bGUgc2hvdWxkIG1vdmUgdG8gYXZvaWQgb3RoZXIgZWxlbWVudHNcbiAqICAgICAgICAgIHNlbGVjdGlvbiAtIGQzIHNlbGVjdGlvbiBvZiBlbGVtZW50cyB0byBhdm9pZFxuICogICAgICAgICAgc2lkZSAtIHdoaWNoIGRpcmVjdGlvbiB0byBtb3ZlIGlmIHRoZXJlIGlzIGEgY29uZmxpY3RcbiAqICAgICAgICAgIFtvZmZzZXRMZWZ0XSAtIGlmIHRoZXNlIGVsZW1lbnRzIGFyZSBzdWJqZWN0IHRvIGEgdHJhbnNsYXRpb25cbiAqICAgICAgICAgICAgICB3cnQgdGhlIHRpdGxlIGVsZW1lbnRcbiAqICAgICAgICAgIFtvZmZzZXRUb3BdXG4gKiAgICAgIGF0dHJpYnV0ZXMge29iamVjdH0gLSBwb3NpdGlvbiBhbmQgYWxpZ25tZW50IGF0dHJpYnV0ZXNcbiAqICAgICAgICAgIHggLSBwaXhlbHNcbiAqICAgICAgICAgIHkgLSBwaXhlbHNcbiAqICAgICAgICAgIHRleHQtYW5jaG9yIC0gc3RhcnR8bWlkZGxlfGVuZFxuICogICAgICB0cmFuc2Zvcm0ge29iamVjdH0gLSBob3cgdG8gdHJhbnNmb3JtIHRoZSB0aXRsZSBhZnRlciBwb3NpdGlvbmluZ1xuICogICAgICAgICAgcm90YXRlIC0gZGVncmVlc1xuICogICAgICAgICAgb2Zmc2V0IC0gc2hpZnQgdXAvZG93biBpbiB0aGUgcm90YXRlZCBmcmFtZSAodW51c2VkPylcbiAqICAgICAgY29udGFpbmVyR3JvdXAgLSBpZiBhbiBzdmcgPGc+IGVsZW1lbnQgYWxyZWFkeSBleGlzdHMgdG8gaG9sZCB0aGlzXG4gKiAgICAgICAgICB0aXRsZSwgaW5jbHVkZSBoZXJlLiBPdGhlcndpc2UgaXQgd2lsbCBnbyBpbiBmdWxsTGF5b3V0Ll9pbmZvbGF5ZXJcbiAqICAgICAgX21ldGEge29iamVjdCAob3B0aW9uYWx9IC0gbWV0YSBrZXktdmFsdWUgdG8gZm9yIHRpdGxlIHdpdGhcbiAqICAgICAgICAgIExpYi50ZW1wbGF0ZVN0cmluZywgZGVmYXVsdCB0byBmdWxsTGF5b3V0Ll9tZXRhLCBpZiBub3QgcHJvdmlkZWRcbiAqXG4gKiAgQHJldHVybiB7c2VsZWN0aW9ufSBkMyBzZWxlY3Rpb24gb2YgdGl0bGUgY29udGFpbmVyIGdyb3VwXG4gKi9cbmZ1bmN0aW9uIGRyYXcoZ2QsIHRpdGxlQ2xhc3MsIG9wdGlvbnMpIHtcbiAgICB2YXIgY29udCA9IG9wdGlvbnMucHJvcENvbnRhaW5lcjtcbiAgICB2YXIgcHJvcCA9IG9wdGlvbnMucHJvcE5hbWU7XG4gICAgdmFyIHBsYWNlaG9sZGVyID0gb3B0aW9ucy5wbGFjZWhvbGRlcjtcbiAgICB2YXIgdHJhY2VJbmRleCA9IG9wdGlvbnMudHJhY2VJbmRleDtcbiAgICB2YXIgYXZvaWQgPSBvcHRpb25zLmF2b2lkIHx8IHt9O1xuICAgIHZhciBhdHRyaWJ1dGVzID0gb3B0aW9ucy5hdHRyaWJ1dGVzO1xuICAgIHZhciB0cmFuc2Zvcm0gPSBvcHRpb25zLnRyYW5zZm9ybTtcbiAgICB2YXIgZ3JvdXAgPSBvcHRpb25zLmNvbnRhaW5lckdyb3VwO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciBvcGFjaXR5ID0gMTtcbiAgICB2YXIgaXNwbGFjZWhvbGRlciA9IGZhbHNlO1xuICAgIHZhciB0aXRsZSA9IGNvbnQudGl0bGU7XG4gICAgdmFyIHR4dCA9ICh0aXRsZSAmJiB0aXRsZS50ZXh0ID8gdGl0bGUudGV4dCA6ICcnKS50cmltKCk7XG5cbiAgICB2YXIgZm9udCA9IHRpdGxlICYmIHRpdGxlLmZvbnQgPyB0aXRsZS5mb250IDoge307XG4gICAgdmFyIGZvbnRGYW1pbHkgPSBmb250LmZhbWlseTtcbiAgICB2YXIgZm9udFNpemUgPSBmb250LnNpemU7XG4gICAgdmFyIGZvbnRDb2xvciA9IGZvbnQuY29sb3I7XG5cbiAgICAvLyBvbmx5IG1ha2UgdGhpcyB0aXRsZSBlZGl0YWJsZSBpZiB3ZSBwb3NpdGl2ZWx5IGlkZW50aWZ5IGl0cyBwcm9wZXJ0eVxuICAgIC8vIGFzIG9uZSB0aGF0IGhhcyBlZGl0aW5nIGVuYWJsZWQuXG4gICAgdmFyIGVkaXRBdHRyO1xuICAgIGlmKHByb3AgPT09ICd0aXRsZS50ZXh0JykgZWRpdEF0dHIgPSAndGl0bGVUZXh0JztcbiAgICBlbHNlIGlmKHByb3AuaW5kZXhPZignYXhpcycpICE9PSAtMSkgZWRpdEF0dHIgPSAnYXhpc1RpdGxlVGV4dCc7XG4gICAgZWxzZSBpZihwcm9wLmluZGV4T2YoJ2NvbG9yYmFyJyAhPT0gLTEpKSBlZGl0QXR0ciA9ICdjb2xvcmJhclRpdGxlVGV4dCc7XG4gICAgdmFyIGVkaXRhYmxlID0gZ2QuX2NvbnRleHQuZWRpdHNbZWRpdEF0dHJdO1xuXG4gICAgaWYodHh0ID09PSAnJykgb3BhY2l0eSA9IDA7XG4gICAgLy8gbG9vayBmb3IgcGxhY2Vob2xkZXIgdGV4dCB3aGlsZSBzdHJpcHBpbmcgb3V0IG51bWJlcnMgZnJvbSBlZyBYMiwgWTNcbiAgICAvLyB0aGlzIGlzIGp1c3QgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgd2l0aCB0aGUgb2xkIHZlcnNpb24gdGhhdCBoYWRcbiAgICAvLyBcIkNsaWNrIHRvIGVudGVyIFgyIHRpdGxlXCIgYW5kIG1heSBoYXZlIGdvdHRlbiBzYXZlZCBpbiBzb21lIG9sZCBwbG90cyxcbiAgICAvLyB3ZSBkb24ndCB3YW50IHRoaXMgdG8gc2hvdyB1cCB3aGVuIHRoZXNlIGFyZSBkaXNwbGF5ZWQuXG4gICAgZWxzZSBpZih0eHQucmVwbGFjZShudW1TdHJpcFJFLCAnICUgJykgPT09IHBsYWNlaG9sZGVyLnJlcGxhY2UobnVtU3RyaXBSRSwgJyAlICcpKSB7XG4gICAgICAgIG9wYWNpdHkgPSAwLjI7XG4gICAgICAgIGlzcGxhY2Vob2xkZXIgPSB0cnVlO1xuICAgICAgICBpZighZWRpdGFibGUpIHR4dCA9ICcnO1xuICAgIH1cblxuICAgIGlmKG9wdGlvbnMuX21ldGEpIHtcbiAgICAgICAgdHh0ID0gTGliLnRlbXBsYXRlU3RyaW5nKHR4dCwgb3B0aW9ucy5fbWV0YSk7XG4gICAgfSBlbHNlIGlmKGZ1bGxMYXlvdXQuX21ldGEpIHtcbiAgICAgICAgdHh0ID0gTGliLnRlbXBsYXRlU3RyaW5nKHR4dCwgZnVsbExheW91dC5fbWV0YSk7XG4gICAgfVxuXG4gICAgdmFyIGVsU2hvdWxkRXhpc3QgPSB0eHQgfHwgZWRpdGFibGU7XG5cbiAgICBpZighZ3JvdXApIHtcbiAgICAgICAgZ3JvdXAgPSBMaWIuZW5zdXJlU2luZ2xlKGZ1bGxMYXlvdXQuX2luZm9sYXllciwgJ2cnLCAnZy0nICsgdGl0bGVDbGFzcyk7XG4gICAgfVxuXG4gICAgdmFyIGVsID0gZ3JvdXAuc2VsZWN0QWxsKCd0ZXh0JylcbiAgICAgICAgLmRhdGEoZWxTaG91bGRFeGlzdCA/IFswXSA6IFtdKTtcbiAgICBlbC5lbnRlcigpLmFwcGVuZCgndGV4dCcpO1xuICAgIGVsLnRleHQodHh0KVxuICAgICAgICAvLyB0aGlzIGlzIGhhY2t5LCBidXQgY29udmVydFRvVHNwYW5zIHVzZXMgdGhlIGNsYXNzXG4gICAgICAgIC8vIHRvIGRldGVybWluZSB3aGV0aGVyIHRvIHJvdGF0ZSBtYXRoSmF4Li4uXG4gICAgICAgIC8vIHNvIHdlIG5lZWQgdG8gY2xlYXIgb3V0IGFueSBvbGQgY2xhc3MgYW5kIHB1dCB0aGVcbiAgICAgICAgLy8gY29ycmVjdCBvbmUgKG9ubHkgcmVsZXZhbnQgZm9yIGNvbG9yYmFycywgYXQgbGVhc3RcbiAgICAgICAgLy8gZm9yIG5vdykgLSBpZSBkb24ndCB1c2UgLmNsYXNzZWRcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgdGl0bGVDbGFzcyk7XG4gICAgZWwuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgaWYoIWVsU2hvdWxkRXhpc3QpIHJldHVybiBncm91cDtcblxuICAgIGZ1bmN0aW9uIHRpdGxlTGF5b3V0KHRpdGxlRWwpIHtcbiAgICAgICAgTGliLnN5bmNPckFzeW5jKFtkcmF3VGl0bGUsIHNjb290VGl0bGVdLCB0aXRsZUVsKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3VGl0bGUodGl0bGVFbCkge1xuICAgICAgICB2YXIgdHJhbnNmb3JtVmFsO1xuXG4gICAgICAgIGlmKHRyYW5zZm9ybSkge1xuICAgICAgICAgICAgdHJhbnNmb3JtVmFsID0gJyc7XG4gICAgICAgICAgICBpZih0cmFuc2Zvcm0ucm90YXRlKSB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtVmFsICs9ICdyb3RhdGUoJyArIFt0cmFuc2Zvcm0ucm90YXRlLCBhdHRyaWJ1dGVzLngsIGF0dHJpYnV0ZXMueV0gKyAnKSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih0cmFuc2Zvcm0ub2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtVmFsICs9ICd0cmFuc2xhdGUoMCwgJyArIHRyYW5zZm9ybS5vZmZzZXQgKyAnKSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0cmFuc2Zvcm1WYWwgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGl0bGVFbC5hdHRyKCd0cmFuc2Zvcm0nLCB0cmFuc2Zvcm1WYWwpO1xuXG4gICAgICAgIHRpdGxlRWwuc3R5bGUoe1xuICAgICAgICAgICAgJ2ZvbnQtZmFtaWx5JzogZm9udEZhbWlseSxcbiAgICAgICAgICAgICdmb250LXNpemUnOiBkMy5yb3VuZChmb250U2l6ZSwgMikgKyAncHgnLFxuICAgICAgICAgICAgZmlsbDogQ29sb3IucmdiKGZvbnRDb2xvciksXG4gICAgICAgICAgICBvcGFjaXR5OiBvcGFjaXR5ICogQ29sb3Iub3BhY2l0eShmb250Q29sb3IpLFxuICAgICAgICAgICAgJ2ZvbnQtd2VpZ2h0JzogUGxvdHMuZm9udFdlaWdodFxuICAgICAgICB9KVxuICAgICAgICAuYXR0cihhdHRyaWJ1dGVzKVxuICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG5cbiAgICAgICAgcmV0dXJuIFBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNjb290VGl0bGUodGl0bGVFbEluKSB7XG4gICAgICAgIHZhciB0aXRsZUdyb3VwID0gZDMuc2VsZWN0KHRpdGxlRWxJbi5ub2RlKCkucGFyZW50Tm9kZSk7XG5cbiAgICAgICAgaWYoYXZvaWQgJiYgYXZvaWQuc2VsZWN0aW9uICYmIGF2b2lkLnNpZGUgJiYgdHh0KSB7XG4gICAgICAgICAgICB0aXRsZUdyb3VwLmF0dHIoJ3RyYW5zZm9ybScsIG51bGwpO1xuXG4gICAgICAgICAgICAvLyBtb3ZlIHRvd2FyZCBhdm9pZC5zaWRlICg9IGxlZnQsIHJpZ2h0LCB0b3AsIGJvdHRvbSkgaWYgbmVlZGVkXG4gICAgICAgICAgICAvLyBjYW4gaW5jbHVkZSBwYWQgKHBpeGVscywgZGVmYXVsdCAyKVxuICAgICAgICAgICAgdmFyIHNoaWZ0ID0gMDtcbiAgICAgICAgICAgIHZhciBiYWNrc2lkZSA9IHtcbiAgICAgICAgICAgICAgICBsZWZ0OiAncmlnaHQnLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiAnbGVmdCcsXG4gICAgICAgICAgICAgICAgdG9wOiAnYm90dG9tJyxcbiAgICAgICAgICAgICAgICBib3R0b206ICd0b3AnXG4gICAgICAgICAgICB9W2F2b2lkLnNpZGVdO1xuICAgICAgICAgICAgdmFyIHNoaWZ0U2lnbiA9IChbJ2xlZnQnLCAndG9wJ10uaW5kZXhPZihhdm9pZC5zaWRlKSAhPT0gLTEpID9cbiAgICAgICAgICAgICAgICAgICAgLTEgOiAxO1xuICAgICAgICAgICAgdmFyIHBhZCA9IGlzTnVtZXJpYyhhdm9pZC5wYWQpID8gYXZvaWQucGFkIDogMjtcbiAgICAgICAgICAgIHZhciB0aXRsZWJiID0gRHJhd2luZy5iQm94KHRpdGxlR3JvdXAubm9kZSgpKTtcbiAgICAgICAgICAgIHZhciBwYXBlcmJiID0ge1xuICAgICAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICAgICAgdG9wOiAwLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiBmdWxsTGF5b3V0LndpZHRoLFxuICAgICAgICAgICAgICAgIGJvdHRvbTogZnVsbExheW91dC5oZWlnaHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgbWF4c2hpZnQgPSBhdm9pZC5tYXhTaGlmdCB8fCAoXG4gICAgICAgICAgICAgICAgKHBhcGVyYmJbYXZvaWQuc2lkZV0gLSB0aXRsZWJiW2F2b2lkLnNpZGVdKSAqXG4gICAgICAgICAgICAgICAgKChhdm9pZC5zaWRlID09PSAnbGVmdCcgfHwgYXZvaWQuc2lkZSA9PT0gJ3RvcCcpID8gLTEgOiAxKSk7XG4gICAgICAgICAgICAvLyBQcmV2ZW50IHRoZSB0aXRsZSBnb2luZyBvZmYgdGhlIHBhcGVyXG4gICAgICAgICAgICBpZihtYXhzaGlmdCA8IDApIHNoaWZ0ID0gbWF4c2hpZnQ7XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBzbyB3ZSBkb24ndCBoYXZlIHRvIG9mZnNldCBlYWNoIGF2b2lkZWQgZWxlbWVudCxcbiAgICAgICAgICAgICAgICAvLyBnaXZlIHRoZSB0aXRsZSB0aGUgb3Bwb3NpdGUgb2Zmc2V0XG4gICAgICAgICAgICAgICAgdmFyIG9mZnNldExlZnQgPSBhdm9pZC5vZmZzZXRMZWZ0IHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIG9mZnNldFRvcCA9IGF2b2lkLm9mZnNldFRvcCB8fCAwO1xuICAgICAgICAgICAgICAgIHRpdGxlYmIubGVmdCAtPSBvZmZzZXRMZWZ0O1xuICAgICAgICAgICAgICAgIHRpdGxlYmIucmlnaHQgLT0gb2Zmc2V0TGVmdDtcbiAgICAgICAgICAgICAgICB0aXRsZWJiLnRvcCAtPSBvZmZzZXRUb3A7XG4gICAgICAgICAgICAgICAgdGl0bGViYi5ib3R0b20gLT0gb2Zmc2V0VG9wO1xuXG4gICAgICAgICAgICAgICAgLy8gaXRlcmF0ZSBvdmVyIGEgc2V0IG9mIGVsZW1lbnRzIChhdm9pZC5zZWxlY3Rpb24pXG4gICAgICAgICAgICAgICAgLy8gdG8gYXZvaWQgY29sbGlzaW9ucyB3aXRoXG4gICAgICAgICAgICAgICAgYXZvaWQuc2VsZWN0aW9uLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhdm9pZGJiID0gRHJhd2luZy5iQm94KHRoaXMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKExpYi5iQm94SW50ZXJzZWN0KHRpdGxlYmIsIGF2b2lkYmIsIHBhZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNoaWZ0ID0gTWF0aC5tYXgoc2hpZnQsIHNoaWZ0U2lnbiAqIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdm9pZGJiW2F2b2lkLnNpZGVdIC0gdGl0bGViYltiYWNrc2lkZV0pICsgcGFkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHNoaWZ0ID0gTWF0aC5taW4obWF4c2hpZnQsIHNoaWZ0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHNoaWZ0ID4gMCB8fCBtYXhzaGlmdCA8IDApIHtcbiAgICAgICAgICAgICAgICB2YXIgc2hpZnRUZW1wbGF0ZSA9IHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogWy1zaGlmdCwgMF0sXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiBbc2hpZnQsIDBdLFxuICAgICAgICAgICAgICAgICAgICB0b3A6IFswLCAtc2hpZnRdLFxuICAgICAgICAgICAgICAgICAgICBib3R0b206IFswLCBzaGlmdF1cbiAgICAgICAgICAgICAgICB9W2F2b2lkLnNpZGVdO1xuICAgICAgICAgICAgICAgIHRpdGxlR3JvdXAuYXR0cigndHJhbnNmb3JtJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgc2hpZnRUZW1wbGF0ZSArICcpJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBlbC5jYWxsKHRpdGxlTGF5b3V0KTtcblxuICAgIGZ1bmN0aW9uIHNldFBsYWNlaG9sZGVyKCkge1xuICAgICAgICBvcGFjaXR5ID0gMDtcbiAgICAgICAgaXNwbGFjZWhvbGRlciA9IHRydWU7XG4gICAgICAgIGVsLnRleHQocGxhY2Vob2xkZXIpXG4gICAgICAgICAgICAub24oJ21vdXNlb3Zlci5vcGFjaXR5JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgICAgICAuZHVyYXRpb24oaW50ZXJhY3RDb25zdGFudHMuU0hPV19QTEFDRUhPTERFUikuc3R5bGUoJ29wYWNpdHknLCAxKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAub24oJ21vdXNlb3V0Lm9wYWNpdHknLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgICAgIC5kdXJhdGlvbihpbnRlcmFjdENvbnN0YW50cy5ISURFX1BMQUNFSE9MREVSKS5zdHlsZSgnb3BhY2l0eScsIDApO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYoZWRpdGFibGUpIHtcbiAgICAgICAgaWYoIXR4dCkgc2V0UGxhY2Vob2xkZXIoKTtcbiAgICAgICAgZWxzZSBlbC5vbignLm9wYWNpdHknLCBudWxsKTtcblxuICAgICAgICBlbC5jYWxsKHN2Z1RleHRVdGlscy5tYWtlRWRpdGFibGUsIHtnZDogZ2R9KVxuICAgICAgICAgICAgLm9uKCdlZGl0JywgZnVuY3Rpb24odGV4dCkge1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlSW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVzdHlsZScsIGdkLCBwcm9wLCB0ZXh0LCB0cmFjZUluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVsYXlvdXQnLCBnZCwgcHJvcCwgdGV4dCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5vbignY2FuY2VsJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0KHRoaXMuYXR0cignZGF0YS11bmZvcm1hdHRlZCcpKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbCh0aXRsZUxheW91dCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdpbnB1dCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQoZCB8fCAnICcpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQsIGF0dHJpYnV0ZXMueCwgYXR0cmlidXRlcy55KTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cbiAgICBlbC5jbGFzc2VkKCdqcy1wbGFjZWhvbGRlcicsIGlzcGxhY2Vob2xkZXIpO1xuXG4gICAgcmV0dXJuIGdyb3VwO1xufVxuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9pbnRlcmFjdGlvbnNcIjo2OTQsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHNcIjo3NDMsXCIuLi8uLi9wbG90cy9wbG90c1wiOjgyOCxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vY29sb3JcIjo1OTMsXCIuLi9kcmF3aW5nXCI6NjE0LFwiZDNcIjoxNjMsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDY4MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBmb250QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gX2RlcmVxXygnLi4vY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcbnZhciBwYWRBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL3BhZF9hdHRyaWJ1dGVzJyk7XG52YXIgdGVtcGxhdGVkQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykudGVtcGxhdGVkQXJyYXk7XG5cbnZhciBidXR0b25zQXR0cnMgPSB0ZW1wbGF0ZWRBcnJheSgnYnV0dG9uJywge1xuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBtZXRob2Q6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsncmVzdHlsZScsICdyZWxheW91dCcsICdhbmltYXRlJywgJ3VwZGF0ZScsICdza2lwJ10sXG4gICAgICAgIGRmbHQ6ICdyZXN0eWxlJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXJnczoge1xuICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgIFxuICAgICAgICBmcmVlTGVuZ3RoOiB0cnVlLFxuICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknfSxcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55J30sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueSd9XG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGFiZWw6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBleGVjdXRlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHRlbXBsYXRlZEFycmF5KCd1cGRhdGVtZW51Jywge1xuICAgIF9hcnJheUF0dHJSZWdleHBzOiBbL151cGRhdGVtZW51c1xcWygwfFsxLTldWzAtOV0rKVxcXVxcLmJ1dHRvbnMvXSxcblxuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHR5cGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZHJvcGRvd24nLCAnYnV0dG9ucyddLFxuICAgICAgICBkZmx0OiAnZHJvcGRvd24nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGRpcmVjdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydsZWZ0JywgJ3JpZ2h0JywgJ3VwJywgJ2Rvd24nXSxcbiAgICAgICAgZGZsdDogJ2Rvd24nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGFjdGl2ZToge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IC0xLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2hvd2FjdGl2ZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgYnV0dG9uczogYnV0dG9uc0F0dHJzLFxuXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAtMixcbiAgICAgICAgbWF4OiAzLFxuICAgICAgICBkZmx0OiAtMC4wNSxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhdXRvJywgJ2xlZnQnLCAnY2VudGVyJywgJ3JpZ2h0J10sXG4gICAgICAgIGRmbHQ6ICdyaWdodCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogLTIsXG4gICAgICAgIG1heDogMyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgeWFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhdXRvJywgJ3RvcCcsICdtaWRkbGUnLCAnYm90dG9tJ10sXG4gICAgICAgIGRmbHQ6ICd0b3AnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHBhZDogZXh0ZW5kRmxhdChwYWRBdHRycyh7ZWRpdFR5cGU6ICdhcnJheWRyYXcnfSksIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBmb250OiBmb250QXR0cnMoe1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIGJnY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm9yZGVyY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5ib3JkZXJMaW5lLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3JkZXJ3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdhcnJheWRyYXcnLFxuICAgICAgICBcbiAgICB9XG59KSwgJ2FycmF5ZHJhdycsICdmcm9tLXJvb3QnKTtcblxufSx7XCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlc1wiOjc1MCxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTMsXCIuLi8uLi9wbG90cy9wYWRfYXR0cmlidXRlc1wiOjgyNyxcIi4uL2NvbG9yL2F0dHJpYnV0ZXNcIjo1OTJ9XSw2ODM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cbiAgICAvLyBsYXlvdXQgYXR0cmlidXRlIG5hbWVcbiAgICBuYW1lOiAndXBkYXRlbWVudXMnLFxuXG4gICAgLy8gY2xhc3MgbmFtZXNcbiAgICBjb250YWluZXJDbGFzc05hbWU6ICd1cGRhdGVtZW51LWNvbnRhaW5lcicsXG4gICAgaGVhZGVyR3JvdXBDbGFzc05hbWU6ICd1cGRhdGVtZW51LWhlYWRlci1ncm91cCcsXG4gICAgaGVhZGVyQ2xhc3NOYW1lOiAndXBkYXRlbWVudS1oZWFkZXInLFxuICAgIGhlYWRlckFycm93Q2xhc3NOYW1lOiAndXBkYXRlbWVudS1oZWFkZXItYXJyb3cnLFxuICAgIGRyb3Bkb3duQnV0dG9uR3JvdXBDbGFzc05hbWU6ICd1cGRhdGVtZW51LWRyb3Bkb3duLWJ1dHRvbi1ncm91cCcsXG4gICAgZHJvcGRvd25CdXR0b25DbGFzc05hbWU6ICd1cGRhdGVtZW51LWRyb3Bkb3duLWJ1dHRvbicsXG4gICAgYnV0dG9uQ2xhc3NOYW1lOiAndXBkYXRlbWVudS1idXR0b24nLFxuICAgIGl0ZW1SZWN0Q2xhc3NOYW1lOiAndXBkYXRlbWVudS1pdGVtLXJlY3QnLFxuICAgIGl0ZW1UZXh0Q2xhc3NOYW1lOiAndXBkYXRlbWVudS1pdGVtLXRleHQnLFxuXG4gICAgLy8gRE9NIGF0dHJpYnV0ZSBuYW1lIGluIGJ1dHRvbiBncm91cCBrZWVwaW5nIHRyYWNrXG4gICAgLy8gb2YgYWN0aXZlIHVwZGF0ZSBtZW51XG4gICAgbWVudUluZGV4QXR0ck5hbWU6ICd1cGRhdGVtZW51LWFjdGl2ZS1pbmRleCcsXG5cbiAgICAvLyBpZCByb290IHBhc3MgdG8gUGxvdHMuYXV0b01hcmdpblxuICAgIGF1dG9NYXJnaW5JZFJvb3Q6ICd1cGRhdGVtZW51LScsXG5cbiAgICAvLyBvcHRpb25zIHdoZW4gJ2FjdGl2ZTogLTEnXG4gICAgYmxhbmtIZWFkZXJPcHRzOiB7IGxhYmVsOiAnICAnIH0sXG5cbiAgICAvLyBtaW4gaXRlbSB3aWR0aCAvIGhlaWdodFxuICAgIG1pbldpZHRoOiAzMCxcbiAgICBtaW5IZWlnaHQ6IDMwLFxuXG4gICAgLy8gcGFkZGluZyBhcm91bmQgaXRlbSB0ZXh0XG4gICAgdGV4dFBhZFg6IDI0LFxuICAgIGFycm93UGFkWDogMTYsXG5cbiAgICAvLyBpdGVtIHJlY3QgcmFkaWlcbiAgICByeDogMixcbiAgICByeTogMixcblxuICAgIC8vIGl0ZW0gIHRleHQgeCBvZmZzZXQgb2ZmIGxlZnQgZWRnZVxuICAgIHRleHRPZmZzZXRYOiAxMixcblxuICAgIC8vIGl0ZW0gIHRleHQgeSBvZmZzZXQgKHcuci50LiBtaWRkbGUpXG4gICAgdGV4dE9mZnNldFk6IDMsXG5cbiAgICAvLyBhcnJvdyBvZmZzZXQgb2ZmIHJpZ2h0IGVkZ2VcbiAgICBhcnJvd09mZnNldFg6IDQsXG5cbiAgICAvLyBnYXAgYmV0d2VlbiBoZWFkZXIgYW5kIGJ1dHRvbnNcbiAgICBnYXBCdXR0b25IZWFkZXI6IDUsXG5cbiAgICAvLyBnYXAgYmV0d2VlbiBiZXR3ZWVuIGJ1dHRvbnNcbiAgICBnYXBCdXR0b246IDIsXG5cbiAgICAvLyBjb2xvciBnaXZlbiB0byBhY3RpdmUgYnV0dG9uc1xuICAgIGFjdGl2ZUNvbG9yOiAnI0Y0RkFGRicsXG5cbiAgICAvLyBjb2xvciBnaXZlbiB0byBob3ZlcmVkIGJ1dHRvbnNcbiAgICBob3ZlckNvbG9yOiAnI0Y0RkFGRicsXG5cbiAgICAvLyBzeW1ib2wgZm9yIG1lbnUgb3BlbiBhcnJvd1xuICAgIGFycm93U3ltYm9sOiB7XG4gICAgICAgIGxlZnQ6ICfil4QnLFxuICAgICAgICByaWdodDogJ+KWuicsXG4gICAgICAgIHVwOiAn4payJyxcbiAgICAgICAgZG93bjogJ+KWvCdcbiAgICB9XG59O1xuXG59LHt9XSw2ODQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0cycpO1xuXG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG5cbnZhciBuYW1lID0gY29uc3RhbnRzLm5hbWU7XG52YXIgYnV0dG9uQXR0cnMgPSBhdHRyaWJ1dGVzLmJ1dHRvbnM7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB1cGRhdGVNZW51c0RlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQpIHtcbiAgICB2YXIgb3B0cyA9IHtcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgaGFuZGxlSXRlbURlZmF1bHRzOiBtZW51RGVmYXVsdHNcbiAgICB9O1xuXG4gICAgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBvcHRzKTtcbn07XG5cbmZ1bmN0aW9uIG1lbnVEZWZhdWx0cyhtZW51SW4sIG1lbnVPdXQsIGxheW91dE91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKG1lbnVJbiwgbWVudU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGJ1dHRvbnMgPSBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzKG1lbnVJbiwgbWVudU91dCwge1xuICAgICAgICBuYW1lOiAnYnV0dG9ucycsXG4gICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogYnV0dG9uRGVmYXVsdHNcbiAgICB9KTtcblxuICAgIHZhciB2aXNpYmxlID0gY29lcmNlKCd2aXNpYmxlJywgYnV0dG9ucy5sZW5ndGggPiAwKTtcbiAgICBpZighdmlzaWJsZSkgcmV0dXJuO1xuXG4gICAgY29lcmNlKCdhY3RpdmUnKTtcbiAgICBjb2VyY2UoJ2RpcmVjdGlvbicpO1xuICAgIGNvZXJjZSgndHlwZScpO1xuICAgIGNvZXJjZSgnc2hvd2FjdGl2ZScpO1xuXG4gICAgY29lcmNlKCd4Jyk7XG4gICAgY29lcmNlKCd5Jyk7XG4gICAgTGliLm5vbmVPckFsbChtZW51SW4sIG1lbnVPdXQsIFsneCcsICd5J10pO1xuXG4gICAgY29lcmNlKCd4YW5jaG9yJyk7XG4gICAgY29lcmNlKCd5YW5jaG9yJyk7XG5cbiAgICBjb2VyY2UoJ3BhZC50Jyk7XG4gICAgY29lcmNlKCdwYWQucicpO1xuICAgIGNvZXJjZSgncGFkLmInKTtcbiAgICBjb2VyY2UoJ3BhZC5sJyk7XG5cbiAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICdmb250JywgbGF5b3V0T3V0LmZvbnQpO1xuXG4gICAgY29lcmNlKCdiZ2NvbG9yJywgbGF5b3V0T3V0LnBhcGVyX2JnY29sb3IpO1xuICAgIGNvZXJjZSgnYm9yZGVyY29sb3InKTtcbiAgICBjb2VyY2UoJ2JvcmRlcndpZHRoJyk7XG59XG5cbmZ1bmN0aW9uIGJ1dHRvbkRlZmF1bHRzKGJ1dHRvbkluLCBidXR0b25PdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShidXR0b25JbiwgYnV0dG9uT3V0LCBidXR0b25BdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnLFxuICAgICAgICAoYnV0dG9uSW4ubWV0aG9kID09PSAnc2tpcCcgfHwgQXJyYXkuaXNBcnJheShidXR0b25Jbi5hcmdzKSkpO1xuICAgIGlmKHZpc2libGUpIHtcbiAgICAgICAgY29lcmNlKCdtZXRob2QnKTtcbiAgICAgICAgY29lcmNlKCdhcmdzJyk7XG4gICAgICAgIGNvZXJjZSgnbGFiZWwnKTtcbiAgICAgICAgY29lcmNlKCdleGVjdXRlJyk7XG4gICAgfVxufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0c1wiOjc2MyxcIi4vYXR0cmlidXRlc1wiOjY4MixcIi4vY29uc3RhbnRzXCI6NjgzfV0sNjg1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgUGxvdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9wbG90cycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vY29sb3InKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vZHJhd2luZycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIGFycmF5RWRpdG9yID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLmFycmF5RWRpdG9yO1xuXG52YXIgTElORV9TUEFDSU5HID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudCcpLkxJTkVfU1BBQ0lORztcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgU2Nyb2xsQm94ID0gX2RlcmVxXygnLi9zY3JvbGxib3gnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkcmF3KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgbWVudURhdGEgPSBMaWIuZmlsdGVyVmlzaWJsZShmdWxsTGF5b3V0W2NvbnN0YW50cy5uYW1lXSk7XG5cbiAgICAvKiBVcGRhdGUgbWVudSBkYXRhIGlzIGJvdW5kIHRvIHRoZSBoZWFkZXItZ3JvdXAuXG4gICAgICogVGhlIGl0ZW1zIGluIHRoZSBoZWFkZXIgZ3JvdXAgYXJlIGFsd2F5cyBwcmVzZW50LlxuICAgICAqXG4gICAgICogVXBvbiBjbGlja2luZyBvbiBhIGhlYWRlciBpdHMgY29ycmVzcG9uZGluZyBidXR0b25cbiAgICAgKiBkYXRhIGlzIGJvdW5kIHRvIHRoZSBidXR0b24tZ3JvdXAuXG4gICAgICpcbiAgICAgKiBXZSBkcmF3IGFsbCBoZWFkZXJzIGluIG9uZSBncm91cCBiZWZvcmUgYWxsIGJ1dHRvbnNcbiAgICAgKiBzbyB0aGF0IHRoZSBidXR0b25zICphbHdheXMqIGFwcGVhciBhYm92ZSB0aGUgaGVhZGVycy5cbiAgICAgKlxuICAgICAqIE5vdGUgdGhhdCBvbmx5IG9uZSBzZXQgb2YgYnV0dG9ucyBhcmUgdmlzaWJsZSBhdCBvbmNlLlxuICAgICAqXG4gICAgICogPGcgY29udGFpbmVyIC8+XG4gICAgICpcbiAgICAgKiAgICAgPGcgaGVhZGVyLWdyb3VwIC8+XG4gICAgICogICAgICAgICA8ZyBpdGVtIGhlYWRlciAvPlxuICAgICAqICAgICAgICAgPHRleHQgaXRlbSBoZWFkZXItYXJyb3cgLz5cbiAgICAgKiAgICAgPGcgaGVhZGVyLWdyb3VwIC8+XG4gICAgICogICAgICAgICA8ZyBpdGVtIGhlYWRlciAvPlxuICAgICAqICAgICAgICAgPHRleHQgaXRlbSBoZWFkZXItYXJyb3cgLz5cbiAgICAgKiAgICAgLi4uXG4gICAgICpcbiAgICAgKiAgICAgPGcgYnV0dG9uLWdyb3VwIC8+XG4gICAgICogICAgICAgICA8ZyBpdGVtIGJ1dHRvbiAvPlxuICAgICAqICAgICAgICAgPGcgaXRlbSBidXR0b24gLz5cbiAgICAgKiAgICAgICAgIC4uLlxuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gY2xlYXJBdXRvTWFyZ2luKG1lbnVPcHRzKSB7XG4gICAgICAgIFBsb3RzLmF1dG9NYXJnaW4oZ2QsIGF1dG9NYXJnaW5JZChtZW51T3B0cykpO1xuICAgIH1cblxuICAgIC8vIGRyYXcgdXBkYXRlIG1lbnUgY29udGFpbmVyXG4gICAgdmFyIG1lbnVzID0gZnVsbExheW91dC5fbWVudWxheWVyXG4gICAgICAgIC5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5jb250YWluZXJDbGFzc05hbWUpXG4gICAgICAgIC5kYXRhKG1lbnVEYXRhLmxlbmd0aCA+IDAgPyBbMF0gOiBbXSk7XG5cbiAgICBtZW51cy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGNvbnN0YW50cy5jb250YWluZXJDbGFzc05hbWUsIHRydWUpXG4gICAgICAgIC5zdHlsZSgnY3Vyc29yJywgJ3BvaW50ZXInKTtcblxuICAgIG1lbnVzLmV4aXQoKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBNb3N0IGNvbXBvbmVudHMgZG9uJ3QgbmVlZCB0byBleHBsaWNpdGx5IHJlbW92ZSBhdXRvTWFyZ2luLCBiZWNhdXNlXG4gICAgICAgIC8vIG1hcmdpblB1c2hlcnMgZG9lcyB0aGlzIC0gYnV0IHVwZGF0ZW1lbnUgdXBkYXRlcyBkb24ndCBnbyB0aHJvdWdoXG4gICAgICAgIC8vIGEgZnVsbCByZXBsb3Qgc28gd2UgbmVlZCB0byBleHBsaWNpdGx5IHJlbW92ZSBpdC5cbiAgICAgICAgLy8gVGhpcyBpcyBmb3IgcmVtb3ZpbmcgKmFsbCogdXBkYXRlbWVudXMsIHJlbW92aW5nIGluZGl2aWR1YWxzIGlzXG4gICAgICAgIC8vIGhhbmRsZWQgYmVsb3csIGluIGhlYWRlckdyb3Vwcy5leGl0XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5oZWFkZXJHcm91cENsYXNzTmFtZSlcbiAgICAgICAgICAgIC5lYWNoKGNsZWFyQXV0b01hcmdpbik7XG4gICAgfSkucmVtb3ZlKCk7XG5cbiAgICAvLyByZXR1cm4gZWFybHkgaWYgbm8gdXBkYXRlIG1lbnVzIGFyZSB2aXNpYmxlXG4gICAgaWYobWVudURhdGEubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICAvLyBqb2luIGhlYWRlciBncm91cFxuICAgIHZhciBoZWFkZXJHcm91cHMgPSBtZW51cy5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5oZWFkZXJHcm91cENsYXNzTmFtZSlcbiAgICAgICAgLmRhdGEobWVudURhdGEsIGtleUZ1bmN0aW9uKTtcblxuICAgIGhlYWRlckdyb3Vwcy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGNvbnN0YW50cy5oZWFkZXJHcm91cENsYXNzTmFtZSwgdHJ1ZSk7XG5cbiAgICAvLyBkcmF3IGRyb3Bkb3duIGJ1dHRvbiBjb250YWluZXJcbiAgICB2YXIgZ0J1dHRvbiA9IExpYi5lbnN1cmVTaW5nbGUobWVudXMsICdnJywgY29uc3RhbnRzLmRyb3Bkb3duQnV0dG9uR3JvdXBDbGFzc05hbWUsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5zdHlsZSgncG9pbnRlci1ldmVudHMnLCAnYWxsJyk7XG4gICAgfSk7XG5cbiAgICAvLyBmaW5kIGRpbWVuc2lvbnMgYmVmb3JlIHBsb3R0aW5nIGFueXRoaW5nICh0aGlzIG11dGF0ZXMgbWVudU9wdHMpXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG1lbnVEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBtZW51T3B0cyA9IG1lbnVEYXRhW2ldO1xuICAgICAgICBmaW5kRGltZW5zaW9ucyhnZCwgbWVudU9wdHMpO1xuICAgIH1cblxuICAgIC8vIHNldHVwIHNjcm9sbGJveFxuICAgIHZhciBzY3JvbGxCb3hJZCA9ICd1cGRhdGVtZW51cycgKyBmdWxsTGF5b3V0Ll91aWQ7XG4gICAgdmFyIHNjcm9sbEJveCA9IG5ldyBTY3JvbGxCb3goZ2QsIGdCdXR0b24sIHNjcm9sbEJveElkKTtcblxuICAgIC8vIHJlbW92ZSBleGl0aW5nIGhlYWRlciwgcmVtb3ZlIGRyb3BwZWQgYnV0dG9ucyBhbmQgcmVzZXQgbWFyZ2luc1xuICAgIGlmKGhlYWRlckdyb3Vwcy5lbnRlcigpLnNpemUoKSkge1xuICAgICAgICAvLyBtYWtlIHN1cmUgZ0J1dHRvbiBpcyBvbiB0b3Agb2YgYWxsIGhlYWRlcnNcbiAgICAgICAgZ0J1dHRvbi5ub2RlKCkucGFyZW50Tm9kZS5hcHBlbmRDaGlsZChnQnV0dG9uLm5vZGUoKSk7XG4gICAgICAgIGdCdXR0b24uY2FsbChyZW1vdmVBbGxCdXR0b25zKTtcbiAgICB9XG5cbiAgICBoZWFkZXJHcm91cHMuZXhpdCgpLmVhY2goZnVuY3Rpb24obWVudU9wdHMpIHtcbiAgICAgICAgZ0J1dHRvbi5jYWxsKHJlbW92ZUFsbEJ1dHRvbnMpO1xuICAgICAgICBjbGVhckF1dG9NYXJnaW4obWVudU9wdHMpO1xuICAgIH0pLnJlbW92ZSgpO1xuXG4gICAgLy8gZHJhdyBoZWFkZXJzIVxuICAgIGhlYWRlckdyb3Vwcy5lYWNoKGZ1bmN0aW9uKG1lbnVPcHRzKSB7XG4gICAgICAgIHZhciBnSGVhZGVyID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIHZhciBfZ0J1dHRvbiA9IG1lbnVPcHRzLnR5cGUgPT09ICdkcm9wZG93bicgPyBnQnV0dG9uIDogbnVsbDtcbiAgICAgICAgUGxvdHMubWFuYWdlQ29tbWFuZE9ic2VydmVyKGdkLCBtZW51T3B0cywgbWVudU9wdHMuYnV0dG9ucywgZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgc2V0QWN0aXZlKGdkLCBtZW51T3B0cywgbWVudU9wdHMuYnV0dG9uc1tkYXRhLmluZGV4XSwgZ0hlYWRlciwgX2dCdXR0b24sIHNjcm9sbEJveCwgZGF0YS5pbmRleCwgdHJ1ZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKG1lbnVPcHRzLnR5cGUgPT09ICdkcm9wZG93bicpIHtcbiAgICAgICAgICAgIGRyYXdIZWFkZXIoZ2QsIGdIZWFkZXIsIGdCdXR0b24sIHNjcm9sbEJveCwgbWVudU9wdHMpO1xuXG4gICAgICAgICAgICAvLyBpZiB0aGlzIG1lbnUgaXMgYWN0aXZlLCB1cGRhdGUgdGhlIGRyb3Bkb3duIGNvbnRhaW5lclxuICAgICAgICAgICAgaWYoaXNBY3RpdmUoZ0J1dHRvbiwgbWVudU9wdHMpKSB7XG4gICAgICAgICAgICAgICAgZHJhd0J1dHRvbnMoZ2QsIGdIZWFkZXIsIGdCdXR0b24sIHNjcm9sbEJveCwgbWVudU9wdHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZHJhd0J1dHRvbnMoZ2QsIGdIZWFkZXIsIG51bGwsIG51bGwsIG1lbnVPcHRzKTtcbiAgICAgICAgfVxuICAgIH0pO1xufTtcblxuLy8gTm90ZSB0aGF0ICdfaW5kZXgnIGlzIHNldCBhdCB0aGUgZGVmYXVsdCBzdGVwLFxuLy8gaXQgY29ycmVzcG9uZHMgdG8gdGhlIG1lbnUgaW5kZXggaW4gdGhlIHVzZXIgbGF5b3V0IHVwZGF0ZSBtZW51IGNvbnRhaW5lci5cbi8vIEJlY2F1c2UgYSBtZW51IGNhbiBiZSBzZXQgaW52aXNpYmxlLFxuLy8gdGhpcyBpcyBhIG1vcmUgJ2NvbnNpc3RlbnQnIGZpZWxkIHRoYW4gdGhlIGluZGV4IGluIHRoZSBtZW51RGF0YS5cbmZ1bmN0aW9uIGtleUZ1bmN0aW9uKG1lbnVPcHRzKSB7XG4gICAgcmV0dXJuIG1lbnVPcHRzLl9pbmRleDtcbn1cblxuZnVuY3Rpb24gaXNGb2xkZWQoZ0J1dHRvbikge1xuICAgIHJldHVybiArZ0J1dHRvbi5hdHRyKGNvbnN0YW50cy5tZW51SW5kZXhBdHRyTmFtZSkgPT09IC0xO1xufVxuXG5mdW5jdGlvbiBpc0FjdGl2ZShnQnV0dG9uLCBtZW51T3B0cykge1xuICAgIHJldHVybiArZ0J1dHRvbi5hdHRyKGNvbnN0YW50cy5tZW51SW5kZXhBdHRyTmFtZSkgPT09IG1lbnVPcHRzLl9pbmRleDtcbn1cblxuZnVuY3Rpb24gc2V0QWN0aXZlKGdkLCBtZW51T3B0cywgYnV0dG9uT3B0cywgZ0hlYWRlciwgZ0J1dHRvbiwgc2Nyb2xsQm94LCBidXR0b25JbmRleCwgaXNTaWxlbnRVcGRhdGUpIHtcbiAgICAvLyB1cGRhdGUgJ2FjdGl2ZScgYXR0cmlidXRlIGluIG1lbnVPcHRzXG4gICAgbWVudU9wdHMuYWN0aXZlID0gYnV0dG9uSW5kZXg7XG5cbiAgICAvLyBkdWUgdG8gdGVtcGxhdGluZywgaXQncyBwb3NzaWJsZSB0aGlzIHNsaWRlciBkb2Vzbid0IGV2ZW4gZXhpc3QgeWV0XG4gICAgYXJyYXlFZGl0b3IoZ2QubGF5b3V0LCBjb25zdGFudHMubmFtZSwgbWVudU9wdHMpXG4gICAgICAgIC5hcHBseVVwZGF0ZSgnYWN0aXZlJywgYnV0dG9uSW5kZXgpO1xuXG4gICAgaWYobWVudU9wdHMudHlwZSA9PT0gJ2J1dHRvbnMnKSB7XG4gICAgICAgIGRyYXdCdXR0b25zKGdkLCBnSGVhZGVyLCBudWxsLCBudWxsLCBtZW51T3B0cyk7XG4gICAgfSBlbHNlIGlmKG1lbnVPcHRzLnR5cGUgPT09ICdkcm9wZG93bicpIHtcbiAgICAgICAgLy8gZm9sZCB1cCBidXR0b25zIGFuZCByZWRyYXcgaGVhZGVyXG4gICAgICAgIGdCdXR0b24uYXR0cihjb25zdGFudHMubWVudUluZGV4QXR0ck5hbWUsICctMScpO1xuXG4gICAgICAgIGRyYXdIZWFkZXIoZ2QsIGdIZWFkZXIsIGdCdXR0b24sIHNjcm9sbEJveCwgbWVudU9wdHMpO1xuXG4gICAgICAgIGlmKCFpc1NpbGVudFVwZGF0ZSkge1xuICAgICAgICAgICAgZHJhd0J1dHRvbnMoZ2QsIGdIZWFkZXIsIGdCdXR0b24sIHNjcm9sbEJveCwgbWVudU9wdHMpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmF3SGVhZGVyKGdkLCBnSGVhZGVyLCBnQnV0dG9uLCBzY3JvbGxCb3gsIG1lbnVPcHRzKSB7XG4gICAgdmFyIGhlYWRlciA9IExpYi5lbnN1cmVTaW5nbGUoZ0hlYWRlciwgJ2cnLCBjb25zdGFudHMuaGVhZGVyQ2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpO1xuICAgIH0pO1xuXG4gICAgdmFyIGRpbXMgPSBtZW51T3B0cy5fZGltcztcbiAgICB2YXIgYWN0aXZlID0gbWVudU9wdHMuYWN0aXZlO1xuICAgIHZhciBoZWFkZXJPcHRzID0gbWVudU9wdHMuYnV0dG9uc1thY3RpdmVdIHx8IGNvbnN0YW50cy5ibGFua0hlYWRlck9wdHM7XG4gICAgdmFyIHBvc09wdHMgPSB7IHk6IG1lbnVPcHRzLnBhZC50LCB5UGFkOiAwLCB4OiBtZW51T3B0cy5wYWQubCwgeFBhZDogMCwgaW5kZXg6IDAgfTtcbiAgICB2YXIgcG9zaXRpb25PdmVycmlkZXMgPSB7XG4gICAgICAgIHdpZHRoOiBkaW1zLmhlYWRlcldpZHRoLFxuICAgICAgICBoZWlnaHQ6IGRpbXMuaGVhZGVySGVpZ2h0XG4gICAgfTtcblxuICAgIGhlYWRlclxuICAgICAgICAuY2FsbChkcmF3SXRlbSwgbWVudU9wdHMsIGhlYWRlck9wdHMsIGdkKVxuICAgICAgICAuY2FsbChzZXRJdGVtUG9zaXRpb24sIG1lbnVPcHRzLCBwb3NPcHRzLCBwb3NpdGlvbk92ZXJyaWRlcyk7XG5cbiAgICAvLyBkcmF3IGRyb3AgYXJyb3cgYXQgdGhlIHJpZ2h0IGVkZ2VcbiAgICB2YXIgYXJyb3cgPSBMaWIuZW5zdXJlU2luZ2xlKGdIZWFkZXIsICd0ZXh0JywgY29uc3RhbnRzLmhlYWRlckFycm93Q2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuY2xhc3NlZCgndXNlci1zZWxlY3Qtbm9uZScsIHRydWUpXG4gICAgICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLCAnZW5kJylcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZm9udCwgbWVudU9wdHMuZm9udClcbiAgICAgICAgICAgIC50ZXh0KGNvbnN0YW50cy5hcnJvd1N5bWJvbFttZW51T3B0cy5kaXJlY3Rpb25dKTtcbiAgICB9KTtcblxuICAgIGFycm93LmF0dHIoe1xuICAgICAgICB4OiBkaW1zLmhlYWRlcldpZHRoIC0gY29uc3RhbnRzLmFycm93T2Zmc2V0WCArIG1lbnVPcHRzLnBhZC5sLFxuICAgICAgICB5OiBkaW1zLmhlYWRlckhlaWdodCAvIDIgKyBjb25zdGFudHMudGV4dE9mZnNldFkgKyBtZW51T3B0cy5wYWQudFxuICAgIH0pO1xuXG4gICAgaGVhZGVyLm9uKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICBnQnV0dG9uLmNhbGwocmVtb3ZlQWxsQnV0dG9ucyxcbiAgICAgICAgICAgIFN0cmluZyhpc0FjdGl2ZShnQnV0dG9uLCBtZW51T3B0cykgPyAtMSA6IG1lbnVPcHRzLl9pbmRleClcbiAgICAgICAgKTtcblxuICAgICAgICBkcmF3QnV0dG9ucyhnZCwgZ0hlYWRlciwgZ0J1dHRvbiwgc2Nyb2xsQm94LCBtZW51T3B0cyk7XG4gICAgfSk7XG5cbiAgICBoZWFkZXIub24oJ21vdXNlb3ZlcicsIGZ1bmN0aW9uKCkge1xuICAgICAgICBoZWFkZXIuY2FsbChzdHlsZU9uTW91c2VPdmVyKTtcbiAgICB9KTtcblxuICAgIGhlYWRlci5vbignbW91c2VvdXQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgaGVhZGVyLmNhbGwoc3R5bGVPbk1vdXNlT3V0LCBtZW51T3B0cyk7XG4gICAgfSk7XG5cbiAgICAvLyB0cmFuc2xhdGUgaGVhZGVyIGdyb3VwXG4gICAgRHJhd2luZy5zZXRUcmFuc2xhdGUoZ0hlYWRlciwgZGltcy5seCwgZGltcy5seSk7XG59XG5cbmZ1bmN0aW9uIGRyYXdCdXR0b25zKGdkLCBnSGVhZGVyLCBnQnV0dG9uLCBzY3JvbGxCb3gsIG1lbnVPcHRzKSB7XG4gICAgLy8gSWYgdGhpcyBpcyBhIHNldCBvZiBidXR0b25zLCBzZXQgcG9pbnRlciBldmVudHMgPSBhbGwgc2luY2Ugd2UgcGxheVxuICAgIC8vIHNvbWUgbWlub3IgZ2FtZXMgd2l0aCB3aGljaCBjb250YWluZXIgaXMgd2hpY2ggaW4gb3JkZXIgdG8gc2ltcGxpZnlcbiAgICAvLyB0aGUgZHJhd2luZyBvZiAqZWl0aGVyKiBidXR0b25zIG9yIG1lbnVzXG4gICAgaWYoIWdCdXR0b24pIHtcbiAgICAgICAgZ0J1dHRvbiA9IGdIZWFkZXI7XG4gICAgICAgIGdCdXR0b24uYXR0cigncG9pbnRlci1ldmVudHMnLCAnYWxsJyk7XG4gICAgfVxuXG4gICAgdmFyIGJ1dHRvbkRhdGEgPSAoIWlzRm9sZGVkKGdCdXR0b24pIHx8IG1lbnVPcHRzLnR5cGUgPT09ICdidXR0b25zJykgP1xuICAgICAgICBtZW51T3B0cy5idXR0b25zIDpcbiAgICAgICAgW107XG5cbiAgICB2YXIga2xhc3MgPSBtZW51T3B0cy50eXBlID09PSAnZHJvcGRvd24nID8gY29uc3RhbnRzLmRyb3Bkb3duQnV0dG9uQ2xhc3NOYW1lIDogY29uc3RhbnRzLmJ1dHRvbkNsYXNzTmFtZTtcblxuICAgIHZhciBidXR0b25zID0gZ0J1dHRvbi5zZWxlY3RBbGwoJ2cuJyArIGtsYXNzKVxuICAgICAgICAuZGF0YShMaWIuZmlsdGVyVmlzaWJsZShidXR0b25EYXRhKSk7XG5cbiAgICB2YXIgZW50ZXIgPSBidXR0b25zLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoa2xhc3MsIHRydWUpO1xuXG4gICAgdmFyIGV4aXQgPSBidXR0b25zLmV4aXQoKTtcblxuICAgIGlmKG1lbnVPcHRzLnR5cGUgPT09ICdkcm9wZG93bicpIHtcbiAgICAgICAgZW50ZXIuYXR0cignb3BhY2l0eScsICcwJylcbiAgICAgICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgICAgIC5hdHRyKCdvcGFjaXR5JywgJzEnKTtcblxuICAgICAgICBleGl0LnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAnMCcpXG4gICAgICAgICAgICAucmVtb3ZlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZXhpdC5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICB2YXIgeDAgPSAwO1xuICAgIHZhciB5MCA9IDA7XG4gICAgdmFyIGRpbXMgPSBtZW51T3B0cy5fZGltcztcblxuICAgIHZhciBpc1ZlcnRpY2FsID0gWyd1cCcsICdkb3duJ10uaW5kZXhPZihtZW51T3B0cy5kaXJlY3Rpb24pICE9PSAtMTtcblxuICAgIGlmKG1lbnVPcHRzLnR5cGUgPT09ICdkcm9wZG93bicpIHtcbiAgICAgICAgaWYoaXNWZXJ0aWNhbCkge1xuICAgICAgICAgICAgeTAgPSBkaW1zLmhlYWRlckhlaWdodCArIGNvbnN0YW50cy5nYXBCdXR0b25IZWFkZXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB4MCA9IGRpbXMuaGVhZGVyV2lkdGggKyBjb25zdGFudHMuZ2FwQnV0dG9uSGVhZGVyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYobWVudU9wdHMudHlwZSA9PT0gJ2Ryb3Bkb3duJyAmJiBtZW51T3B0cy5kaXJlY3Rpb24gPT09ICd1cCcpIHtcbiAgICAgICAgeTAgPSAtY29uc3RhbnRzLmdhcEJ1dHRvbkhlYWRlciArIGNvbnN0YW50cy5nYXBCdXR0b24gLSBkaW1zLm9wZW5IZWlnaHQ7XG4gICAgfVxuXG4gICAgaWYobWVudU9wdHMudHlwZSA9PT0gJ2Ryb3Bkb3duJyAmJiBtZW51T3B0cy5kaXJlY3Rpb24gPT09ICdsZWZ0Jykge1xuICAgICAgICB4MCA9IC1jb25zdGFudHMuZ2FwQnV0dG9uSGVhZGVyICsgY29uc3RhbnRzLmdhcEJ1dHRvbiAtIGRpbXMub3BlbldpZHRoO1xuICAgIH1cblxuICAgIHZhciBwb3NPcHRzID0ge1xuICAgICAgICB4OiBkaW1zLmx4ICsgeDAgKyBtZW51T3B0cy5wYWQubCxcbiAgICAgICAgeTogZGltcy5seSArIHkwICsgbWVudU9wdHMucGFkLnQsXG4gICAgICAgIHlQYWQ6IGNvbnN0YW50cy5nYXBCdXR0b24sXG4gICAgICAgIHhQYWQ6IGNvbnN0YW50cy5nYXBCdXR0b24sXG4gICAgICAgIGluZGV4OiAwLFxuICAgIH07XG5cbiAgICB2YXIgc2Nyb2xsQm94UG9zaXRpb24gPSB7XG4gICAgICAgIGw6IHBvc09wdHMueCArIG1lbnVPcHRzLmJvcmRlcndpZHRoLFxuICAgICAgICB0OiBwb3NPcHRzLnkgKyBtZW51T3B0cy5ib3JkZXJ3aWR0aFxuICAgIH07XG5cbiAgICBidXR0b25zLmVhY2goZnVuY3Rpb24oYnV0dG9uT3B0cywgYnV0dG9uSW5kZXgpIHtcbiAgICAgICAgdmFyIGJ1dHRvbiA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBidXR0b25cbiAgICAgICAgICAgIC5jYWxsKGRyYXdJdGVtLCBtZW51T3B0cywgYnV0dG9uT3B0cywgZ2QpXG4gICAgICAgICAgICAuY2FsbChzZXRJdGVtUG9zaXRpb24sIG1lbnVPcHRzLCBwb3NPcHRzKTtcblxuICAgICAgICBidXR0b24ub24oJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBza2lwIGBkcmFnZW5kYCBldmVudHNcbiAgICAgICAgICAgIGlmKGQzLmV2ZW50LmRlZmF1bHRQcmV2ZW50ZWQpIHJldHVybjtcblxuICAgICAgICAgICAgc2V0QWN0aXZlKGdkLCBtZW51T3B0cywgYnV0dG9uT3B0cywgZ0hlYWRlciwgZ0J1dHRvbiwgc2Nyb2xsQm94LCBidXR0b25JbmRleCk7XG5cbiAgICAgICAgICAgIGlmKGJ1dHRvbk9wdHMuZXhlY3V0ZSkge1xuICAgICAgICAgICAgICAgIFBsb3RzLmV4ZWN1dGVBUElDb21tYW5kKGdkLCBidXR0b25PcHRzLm1ldGhvZCwgYnV0dG9uT3B0cy5hcmdzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2J1dHRvbmNsaWNrZWQnLCB7bWVudTogbWVudU9wdHMsIGJ1dHRvbjogYnV0dG9uT3B0cywgYWN0aXZlOiBtZW51T3B0cy5hY3RpdmV9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYnV0dG9uLm9uKCdtb3VzZW92ZXInLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGJ1dHRvbi5jYWxsKHN0eWxlT25Nb3VzZU92ZXIpO1xuICAgICAgICB9KTtcblxuICAgICAgICBidXR0b24ub24oJ21vdXNlb3V0JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBidXR0b24uY2FsbChzdHlsZU9uTW91c2VPdXQsIG1lbnVPcHRzKTtcbiAgICAgICAgICAgIGJ1dHRvbnMuY2FsbChzdHlsZUJ1dHRvbnMsIG1lbnVPcHRzKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBidXR0b25zLmNhbGwoc3R5bGVCdXR0b25zLCBtZW51T3B0cyk7XG5cbiAgICBpZihpc1ZlcnRpY2FsKSB7XG4gICAgICAgIHNjcm9sbEJveFBvc2l0aW9uLncgPSBNYXRoLm1heChkaW1zLm9wZW5XaWR0aCwgZGltcy5oZWFkZXJXaWR0aCk7XG4gICAgICAgIHNjcm9sbEJveFBvc2l0aW9uLmggPSBwb3NPcHRzLnkgLSBzY3JvbGxCb3hQb3NpdGlvbi50O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNjcm9sbEJveFBvc2l0aW9uLncgPSBwb3NPcHRzLnggLSBzY3JvbGxCb3hQb3NpdGlvbi5sO1xuICAgICAgICBzY3JvbGxCb3hQb3NpdGlvbi5oID0gTWF0aC5tYXgoZGltcy5vcGVuSGVpZ2h0LCBkaW1zLmhlYWRlckhlaWdodCk7XG4gICAgfVxuXG4gICAgc2Nyb2xsQm94UG9zaXRpb24uZGlyZWN0aW9uID0gbWVudU9wdHMuZGlyZWN0aW9uO1xuXG4gICAgaWYoc2Nyb2xsQm94KSB7XG4gICAgICAgIGlmKGJ1dHRvbnMuc2l6ZSgpKSB7XG4gICAgICAgICAgICBkcmF3U2Nyb2xsQm94KGdkLCBnSGVhZGVyLCBnQnV0dG9uLCBzY3JvbGxCb3gsIG1lbnVPcHRzLCBzY3JvbGxCb3hQb3NpdGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBoaWRlU2Nyb2xsQm94KHNjcm9sbEJveCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYXdTY3JvbGxCb3goZ2QsIGdIZWFkZXIsIGdCdXR0b24sIHNjcm9sbEJveCwgbWVudU9wdHMsIHBvc2l0aW9uKSB7XG4gICAgLy8gZW5hYmxlIHRoZSBzY3JvbGxib3hcbiAgICB2YXIgZGlyZWN0aW9uID0gbWVudU9wdHMuZGlyZWN0aW9uO1xuICAgIHZhciBpc1ZlcnRpY2FsID0gKGRpcmVjdGlvbiA9PT0gJ3VwJyB8fCBkaXJlY3Rpb24gPT09ICdkb3duJyk7XG4gICAgdmFyIGRpbXMgPSBtZW51T3B0cy5fZGltcztcblxuICAgIHZhciBhY3RpdmUgPSBtZW51T3B0cy5hY3RpdmU7XG4gICAgdmFyIHRyYW5zbGF0ZVgsIHRyYW5zbGF0ZVk7XG4gICAgdmFyIGk7XG4gICAgaWYoaXNWZXJ0aWNhbCkge1xuICAgICAgICB0cmFuc2xhdGVZID0gMDtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYWN0aXZlOyBpKyspIHtcbiAgICAgICAgICAgIHRyYW5zbGF0ZVkgKz0gZGltcy5oZWlnaHRzW2ldICsgY29uc3RhbnRzLmdhcEJ1dHRvbjtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYW5zbGF0ZVggPSAwO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBhY3RpdmU7IGkrKykge1xuICAgICAgICAgICAgdHJhbnNsYXRlWCArPSBkaW1zLndpZHRoc1tpXSArIGNvbnN0YW50cy5nYXBCdXR0b247XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzY3JvbGxCb3guZW5hYmxlKHBvc2l0aW9uLCB0cmFuc2xhdGVYLCB0cmFuc2xhdGVZKTtcblxuICAgIGlmKHNjcm9sbEJveC5oYmFyKSB7XG4gICAgICAgIHNjcm9sbEJveC5oYmFyXG4gICAgICAgICAgICAuYXR0cignb3BhY2l0eScsICcwJylcbiAgICAgICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgICAgIC5hdHRyKCdvcGFjaXR5JywgJzEnKTtcbiAgICB9XG5cbiAgICBpZihzY3JvbGxCb3gudmJhcikge1xuICAgICAgICBzY3JvbGxCb3gudmJhclxuICAgICAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAnMCcpXG4gICAgICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAuYXR0cignb3BhY2l0eScsICcxJyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBoaWRlU2Nyb2xsQm94KHNjcm9sbEJveCkge1xuICAgIHZhciBoYXNIQmFyID0gISFzY3JvbGxCb3guaGJhcjtcbiAgICB2YXIgaGFzVkJhciA9ICEhc2Nyb2xsQm94LnZiYXI7XG5cbiAgICBpZihoYXNIQmFyKSB7XG4gICAgICAgIHNjcm9sbEJveC5oYmFyXG4gICAgICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAuYXR0cignb3BhY2l0eScsICcwJylcbiAgICAgICAgICAgIC5lYWNoKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBoYXNIQmFyID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYoIWhhc1ZCYXIpIHNjcm9sbEJveC5kaXNhYmxlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihoYXNWQmFyKSB7XG4gICAgICAgIHNjcm9sbEJveC52YmFyXG4gICAgICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAuYXR0cignb3BhY2l0eScsICcwJylcbiAgICAgICAgICAgIC5lYWNoKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBoYXNWQmFyID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYoIWhhc0hCYXIpIHNjcm9sbEJveC5kaXNhYmxlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYXdJdGVtKGl0ZW0sIG1lbnVPcHRzLCBpdGVtT3B0cywgZ2QpIHtcbiAgICBpdGVtLmNhbGwoZHJhd0l0ZW1SZWN0LCBtZW51T3B0cylcbiAgICAgICAgLmNhbGwoZHJhd0l0ZW1UZXh0LCBtZW51T3B0cywgaXRlbU9wdHMsIGdkKTtcbn1cblxuZnVuY3Rpb24gZHJhd0l0ZW1SZWN0KGl0ZW0sIG1lbnVPcHRzKSB7XG4gICAgdmFyIHJlY3QgPSBMaWIuZW5zdXJlU2luZ2xlKGl0ZW0sICdyZWN0JywgY29uc3RhbnRzLml0ZW1SZWN0Q2xhc3NOYW1lLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXR0cih7XG4gICAgICAgICAgICByeDogY29uc3RhbnRzLnJ4LFxuICAgICAgICAgICAgcnk6IGNvbnN0YW50cy5yeSxcbiAgICAgICAgICAgICdzaGFwZS1yZW5kZXJpbmcnOiAnY3Jpc3BFZGdlcydcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZWN0LmNhbGwoQ29sb3Iuc3Ryb2tlLCBtZW51T3B0cy5ib3JkZXJjb2xvcilcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgbWVudU9wdHMuYmdjb2xvcilcbiAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBtZW51T3B0cy5ib3JkZXJ3aWR0aCArICdweCcpO1xufVxuXG5mdW5jdGlvbiBkcmF3SXRlbVRleHQoaXRlbSwgbWVudU9wdHMsIGl0ZW1PcHRzLCBnZCkge1xuICAgIHZhciB0ZXh0ID0gTGliLmVuc3VyZVNpbmdsZShpdGVtLCAndGV4dCcsIGNvbnN0YW50cy5pdGVtVGV4dENsYXNzTmFtZSwgZnVuY3Rpb24ocykge1xuICAgICAgICBzLmNsYXNzZWQoJ3VzZXItc2VsZWN0LW5vbmUnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6ICdzdGFydCcsXG4gICAgICAgICAgICAgICAgJ2RhdGEtbm90ZXgnOiAxXG4gICAgICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIHZhciB0eCA9IGl0ZW1PcHRzLmxhYmVsO1xuICAgIHZhciBfbWV0YSA9IGdkLl9mdWxsTGF5b3V0Ll9tZXRhO1xuICAgIGlmKF9tZXRhKSB0eCA9IExpYi50ZW1wbGF0ZVN0cmluZyh0eCwgX21ldGEpO1xuXG4gICAgdGV4dC5jYWxsKERyYXdpbmcuZm9udCwgbWVudU9wdHMuZm9udClcbiAgICAgICAgLnRleHQodHgpXG4gICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKTtcbn1cblxuZnVuY3Rpb24gc3R5bGVCdXR0b25zKGJ1dHRvbnMsIG1lbnVPcHRzKSB7XG4gICAgdmFyIGFjdGl2ZSA9IG1lbnVPcHRzLmFjdGl2ZTtcblxuICAgIGJ1dHRvbnMuZWFjaChmdW5jdGlvbihidXR0b25PcHRzLCBpKSB7XG4gICAgICAgIHZhciBidXR0b24gPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgaWYoaSA9PT0gYWN0aXZlICYmIG1lbnVPcHRzLnNob3dhY3RpdmUpIHtcbiAgICAgICAgICAgIGJ1dHRvbi5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5pdGVtUmVjdENsYXNzTmFtZSlcbiAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBjb25zdGFudHMuYWN0aXZlQ29sb3IpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlT25Nb3VzZU92ZXIoaXRlbSkge1xuICAgIGl0ZW0uc2VsZWN0KCdyZWN0LicgKyBjb25zdGFudHMuaXRlbVJlY3RDbGFzc05hbWUpXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGNvbnN0YW50cy5ob3ZlckNvbG9yKTtcbn1cblxuZnVuY3Rpb24gc3R5bGVPbk1vdXNlT3V0KGl0ZW0sIG1lbnVPcHRzKSB7XG4gICAgaXRlbS5zZWxlY3QoJ3JlY3QuJyArIGNvbnN0YW50cy5pdGVtUmVjdENsYXNzTmFtZSlcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgbWVudU9wdHMuYmdjb2xvcik7XG59XG5cbi8vIGZpbmQgaXRlbSBkaW1lbnNpb25zICh0aGlzIG11dGF0ZXMgbWVudU9wdHMpXG5mdW5jdGlvbiBmaW5kRGltZW5zaW9ucyhnZCwgbWVudU9wdHMpIHtcbiAgICB2YXIgZGltcyA9IG1lbnVPcHRzLl9kaW1zID0ge1xuICAgICAgICB3aWR0aDE6IDAsXG4gICAgICAgIGhlaWdodDE6IDAsXG4gICAgICAgIGhlaWdodHM6IFtdLFxuICAgICAgICB3aWR0aHM6IFtdLFxuICAgICAgICB0b3RhbFdpZHRoOiAwLFxuICAgICAgICB0b3RhbEhlaWdodDogMCxcbiAgICAgICAgb3BlbldpZHRoOiAwLFxuICAgICAgICBvcGVuSGVpZ2h0OiAwLFxuICAgICAgICBseDogMCxcbiAgICAgICAgbHk6IDBcbiAgICB9O1xuXG4gICAgdmFyIGZha2VCdXR0b25zID0gRHJhd2luZy50ZXN0ZXIuc2VsZWN0QWxsKCdnLicgKyBjb25zdGFudHMuZHJvcGRvd25CdXR0b25DbGFzc05hbWUpXG4gICAgICAgIC5kYXRhKExpYi5maWx0ZXJWaXNpYmxlKG1lbnVPcHRzLmJ1dHRvbnMpKTtcblxuICAgIGZha2VCdXR0b25zLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY29uc3RhbnRzLmRyb3Bkb3duQnV0dG9uQ2xhc3NOYW1lLCB0cnVlKTtcblxuICAgIHZhciBpc1ZlcnRpY2FsID0gWyd1cCcsICdkb3duJ10uaW5kZXhPZihtZW51T3B0cy5kaXJlY3Rpb24pICE9PSAtMTtcblxuICAgIC8vIGxvb3Agb3ZlciBmYWtlIGJ1dHRvbnMgdG8gZmluZCB3aWR0aCAvIGhlaWdodFxuICAgIGZha2VCdXR0b25zLmVhY2goZnVuY3Rpb24oYnV0dG9uT3B0cywgaSkge1xuICAgICAgICB2YXIgYnV0dG9uID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIGJ1dHRvbi5jYWxsKGRyYXdJdGVtLCBtZW51T3B0cywgYnV0dG9uT3B0cywgZ2QpO1xuXG4gICAgICAgIHZhciB0ZXh0ID0gYnV0dG9uLnNlbGVjdCgnLicgKyBjb25zdGFudHMuaXRlbVRleHRDbGFzc05hbWUpO1xuXG4gICAgICAgIC8vIHdpZHRoIGlzIGdpdmVuIGJ5IG1heCB3aWR0aCBvZiBhbGwgYnV0dG9uc1xuICAgICAgICB2YXIgdFdpZHRoID0gdGV4dC5ub2RlKCkgJiYgRHJhd2luZy5iQm94KHRleHQubm9kZSgpKS53aWR0aDtcbiAgICAgICAgdmFyIHdFZmYgPSBNYXRoLm1heCh0V2lkdGggKyBjb25zdGFudHMudGV4dFBhZFgsIGNvbnN0YW50cy5taW5XaWR0aCk7XG5cbiAgICAgICAgLy8gaGVpZ2h0IGlzIGRldGVybWluZWQgYnkgaXRlbSB0ZXh0XG4gICAgICAgIHZhciB0SGVpZ2h0ID0gbWVudU9wdHMuZm9udC5zaXplICogTElORV9TUEFDSU5HO1xuICAgICAgICB2YXIgdExpbmVzID0gc3ZnVGV4dFV0aWxzLmxpbmVDb3VudCh0ZXh0KTtcbiAgICAgICAgdmFyIGhFZmYgPSBNYXRoLm1heCh0SGVpZ2h0ICogdExpbmVzLCBjb25zdGFudHMubWluSGVpZ2h0KSArIGNvbnN0YW50cy50ZXh0T2Zmc2V0WTtcblxuICAgICAgICBoRWZmID0gTWF0aC5jZWlsKGhFZmYpO1xuICAgICAgICB3RWZmID0gTWF0aC5jZWlsKHdFZmYpO1xuXG4gICAgICAgIC8vIFN0b3JlIHBlci1pdGVtIHNpemVzIHNpbmNlIGEgcm93IG9mIGhvcml6b250YWwgYnV0dG9ucywgZm9yIGV4YW1wbGUsXG4gICAgICAgIC8vIGRvbid0IGFsbCBuZWVkIHRvIGJlIHRoZSBzYW1lIHdpZHRoOlxuICAgICAgICBkaW1zLndpZHRoc1tpXSA9IHdFZmY7XG4gICAgICAgIGRpbXMuaGVpZ2h0c1tpXSA9IGhFZmY7XG5cbiAgICAgICAgLy8gSGVpZ2h0IGFuZCB3aWR0aCBvZiBpbmRpdmlkdWFsIGVsZW1lbnQ6XG4gICAgICAgIGRpbXMuaGVpZ2h0MSA9IE1hdGgubWF4KGRpbXMuaGVpZ2h0MSwgaEVmZik7XG4gICAgICAgIGRpbXMud2lkdGgxID0gTWF0aC5tYXgoZGltcy53aWR0aDEsIHdFZmYpO1xuXG4gICAgICAgIGlmKGlzVmVydGljYWwpIHtcbiAgICAgICAgICAgIGRpbXMudG90YWxXaWR0aCA9IE1hdGgubWF4KGRpbXMudG90YWxXaWR0aCwgd0VmZik7XG4gICAgICAgICAgICBkaW1zLm9wZW5XaWR0aCA9IGRpbXMudG90YWxXaWR0aDtcbiAgICAgICAgICAgIGRpbXMudG90YWxIZWlnaHQgKz0gaEVmZiArIGNvbnN0YW50cy5nYXBCdXR0b247XG4gICAgICAgICAgICBkaW1zLm9wZW5IZWlnaHQgKz0gaEVmZiArIGNvbnN0YW50cy5nYXBCdXR0b247XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkaW1zLnRvdGFsV2lkdGggKz0gd0VmZiArIGNvbnN0YW50cy5nYXBCdXR0b247XG4gICAgICAgICAgICBkaW1zLm9wZW5XaWR0aCArPSB3RWZmICsgY29uc3RhbnRzLmdhcEJ1dHRvbjtcbiAgICAgICAgICAgIGRpbXMudG90YWxIZWlnaHQgPSBNYXRoLm1heChkaW1zLnRvdGFsSGVpZ2h0LCBoRWZmKTtcbiAgICAgICAgICAgIGRpbXMub3BlbkhlaWdodCA9IGRpbXMudG90YWxIZWlnaHQ7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmKGlzVmVydGljYWwpIHtcbiAgICAgICAgZGltcy50b3RhbEhlaWdodCAtPSBjb25zdGFudHMuZ2FwQnV0dG9uO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRpbXMudG90YWxXaWR0aCAtPSBjb25zdGFudHMuZ2FwQnV0dG9uO1xuICAgIH1cblxuXG4gICAgZGltcy5oZWFkZXJXaWR0aCA9IGRpbXMud2lkdGgxICsgY29uc3RhbnRzLmFycm93UGFkWDtcbiAgICBkaW1zLmhlYWRlckhlaWdodCA9IGRpbXMuaGVpZ2h0MTtcblxuICAgIGlmKG1lbnVPcHRzLnR5cGUgPT09ICdkcm9wZG93bicpIHtcbiAgICAgICAgaWYoaXNWZXJ0aWNhbCkge1xuICAgICAgICAgICAgZGltcy53aWR0aDEgKz0gY29uc3RhbnRzLmFycm93UGFkWDtcbiAgICAgICAgICAgIGRpbXMudG90YWxIZWlnaHQgPSBkaW1zLmhlaWdodDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkaW1zLnRvdGFsV2lkdGggPSBkaW1zLndpZHRoMTtcbiAgICAgICAgfVxuICAgICAgICBkaW1zLnRvdGFsV2lkdGggKz0gY29uc3RhbnRzLmFycm93UGFkWDtcbiAgICB9XG5cbiAgICBmYWtlQnV0dG9ucy5yZW1vdmUoKTtcblxuICAgIHZhciBwYWRkZWRXaWR0aCA9IGRpbXMudG90YWxXaWR0aCArIG1lbnVPcHRzLnBhZC5sICsgbWVudU9wdHMucGFkLnI7XG4gICAgdmFyIHBhZGRlZEhlaWdodCA9IGRpbXMudG90YWxIZWlnaHQgKyBtZW51T3B0cy5wYWQudCArIG1lbnVPcHRzLnBhZC5iO1xuXG4gICAgdmFyIGdyYXBoU2l6ZSA9IGdkLl9mdWxsTGF5b3V0Ll9zaXplO1xuICAgIGRpbXMubHggPSBncmFwaFNpemUubCArIGdyYXBoU2l6ZS53ICogbWVudU9wdHMueDtcbiAgICBkaW1zLmx5ID0gZ3JhcGhTaXplLnQgKyBncmFwaFNpemUuaCAqICgxIC0gbWVudU9wdHMueSk7XG5cbiAgICB2YXIgeGFuY2hvciA9ICdsZWZ0JztcbiAgICBpZihMaWIuaXNSaWdodEFuY2hvcihtZW51T3B0cykpIHtcbiAgICAgICAgZGltcy5seCAtPSBwYWRkZWRXaWR0aDtcbiAgICAgICAgeGFuY2hvciA9ICdyaWdodCc7XG4gICAgfVxuICAgIGlmKExpYi5pc0NlbnRlckFuY2hvcihtZW51T3B0cykpIHtcbiAgICAgICAgZGltcy5seCAtPSBwYWRkZWRXaWR0aCAvIDI7XG4gICAgICAgIHhhbmNob3IgPSAnY2VudGVyJztcbiAgICB9XG5cbiAgICB2YXIgeWFuY2hvciA9ICd0b3AnO1xuICAgIGlmKExpYi5pc0JvdHRvbUFuY2hvcihtZW51T3B0cykpIHtcbiAgICAgICAgZGltcy5seSAtPSBwYWRkZWRIZWlnaHQ7XG4gICAgICAgIHlhbmNob3IgPSAnYm90dG9tJztcbiAgICB9XG4gICAgaWYoTGliLmlzTWlkZGxlQW5jaG9yKG1lbnVPcHRzKSkge1xuICAgICAgICBkaW1zLmx5IC09IHBhZGRlZEhlaWdodCAvIDI7XG4gICAgICAgIHlhbmNob3IgPSAnbWlkZGxlJztcbiAgICB9XG5cbiAgICBkaW1zLnRvdGFsV2lkdGggPSBNYXRoLmNlaWwoZGltcy50b3RhbFdpZHRoKTtcbiAgICBkaW1zLnRvdGFsSGVpZ2h0ID0gTWF0aC5jZWlsKGRpbXMudG90YWxIZWlnaHQpO1xuICAgIGRpbXMubHggPSBNYXRoLnJvdW5kKGRpbXMubHgpO1xuICAgIGRpbXMubHkgPSBNYXRoLnJvdW5kKGRpbXMubHkpO1xuXG4gICAgUGxvdHMuYXV0b01hcmdpbihnZCwgYXV0b01hcmdpbklkKG1lbnVPcHRzKSwge1xuICAgICAgICB4OiBtZW51T3B0cy54LFxuICAgICAgICB5OiBtZW51T3B0cy55LFxuICAgICAgICBsOiBwYWRkZWRXaWR0aCAqICh7cmlnaHQ6IDEsIGNlbnRlcjogMC41fVt4YW5jaG9yXSB8fCAwKSxcbiAgICAgICAgcjogcGFkZGVkV2lkdGggKiAoe2xlZnQ6IDEsIGNlbnRlcjogMC41fVt4YW5jaG9yXSB8fCAwKSxcbiAgICAgICAgYjogcGFkZGVkSGVpZ2h0ICogKHt0b3A6IDEsIG1pZGRsZTogMC41fVt5YW5jaG9yXSB8fCAwKSxcbiAgICAgICAgdDogcGFkZGVkSGVpZ2h0ICogKHtib3R0b206IDEsIG1pZGRsZTogMC41fVt5YW5jaG9yXSB8fCAwKVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBhdXRvTWFyZ2luSWQobWVudU9wdHMpIHtcbiAgICByZXR1cm4gY29uc3RhbnRzLmF1dG9NYXJnaW5JZFJvb3QgKyBtZW51T3B0cy5faW5kZXg7XG59XG5cbi8vIHNldCBpdGVtIHBvc2l0aW9ucyAobXV0YXRlcyBwb3NPcHRzKVxuZnVuY3Rpb24gc2V0SXRlbVBvc2l0aW9uKGl0ZW0sIG1lbnVPcHRzLCBwb3NPcHRzLCBvdmVycmlkZU9wdHMpIHtcbiAgICBvdmVycmlkZU9wdHMgPSBvdmVycmlkZU9wdHMgfHwge307XG4gICAgdmFyIHJlY3QgPSBpdGVtLnNlbGVjdCgnLicgKyBjb25zdGFudHMuaXRlbVJlY3RDbGFzc05hbWUpO1xuICAgIHZhciB0ZXh0ID0gaXRlbS5zZWxlY3QoJy4nICsgY29uc3RhbnRzLml0ZW1UZXh0Q2xhc3NOYW1lKTtcbiAgICB2YXIgYm9yZGVyV2lkdGggPSBtZW51T3B0cy5ib3JkZXJ3aWR0aDtcbiAgICB2YXIgaW5kZXggPSBwb3NPcHRzLmluZGV4O1xuICAgIHZhciBkaW1zID0gbWVudU9wdHMuX2RpbXM7XG5cbiAgICBEcmF3aW5nLnNldFRyYW5zbGF0ZShpdGVtLCBib3JkZXJXaWR0aCArIHBvc09wdHMueCwgYm9yZGVyV2lkdGggKyBwb3NPcHRzLnkpO1xuXG4gICAgdmFyIGlzVmVydGljYWwgPSBbJ3VwJywgJ2Rvd24nXS5pbmRleE9mKG1lbnVPcHRzLmRpcmVjdGlvbikgIT09IC0xO1xuICAgIHZhciBmaW5hbEhlaWdodCA9IG92ZXJyaWRlT3B0cy5oZWlnaHQgfHwgKGlzVmVydGljYWwgPyBkaW1zLmhlaWdodHNbaW5kZXhdIDogZGltcy5oZWlnaHQxKTtcblxuICAgIHJlY3QuYXR0cih7XG4gICAgICAgIHg6IDAsXG4gICAgICAgIHk6IDAsXG4gICAgICAgIHdpZHRoOiBvdmVycmlkZU9wdHMud2lkdGggfHwgKGlzVmVydGljYWwgPyBkaW1zLndpZHRoMSA6IGRpbXMud2lkdGhzW2luZGV4XSksXG4gICAgICAgIGhlaWdodDogZmluYWxIZWlnaHRcbiAgICB9KTtcblxuICAgIHZhciB0SGVpZ2h0ID0gbWVudU9wdHMuZm9udC5zaXplICogTElORV9TUEFDSU5HO1xuICAgIHZhciB0TGluZXMgPSBzdmdUZXh0VXRpbHMubGluZUNvdW50KHRleHQpO1xuICAgIHZhciBzcGFuT2Zmc2V0ID0gKCh0TGluZXMgLSAxKSAqIHRIZWlnaHQgLyAyKTtcblxuICAgIHN2Z1RleHRVdGlscy5wb3NpdGlvblRleHQodGV4dCwgY29uc3RhbnRzLnRleHRPZmZzZXRYLFxuICAgICAgICBmaW5hbEhlaWdodCAvIDIgLSBzcGFuT2Zmc2V0ICsgY29uc3RhbnRzLnRleHRPZmZzZXRZKTtcblxuICAgIGlmKGlzVmVydGljYWwpIHtcbiAgICAgICAgcG9zT3B0cy55ICs9IGRpbXMuaGVpZ2h0c1tpbmRleF0gKyBwb3NPcHRzLnlQYWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcG9zT3B0cy54ICs9IGRpbXMud2lkdGhzW2luZGV4XSArIHBvc09wdHMueFBhZDtcbiAgICB9XG5cbiAgICBwb3NPcHRzLmluZGV4Kys7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZUFsbEJ1dHRvbnMoZ0J1dHRvbiwgbmV3TWVudUluZGV4QXR0cikge1xuICAgIGdCdXR0b25cbiAgICAgICAgLmF0dHIoY29uc3RhbnRzLm1lbnVJbmRleEF0dHJOYW1lLCBuZXdNZW51SW5kZXhBdHRyIHx8ICctMScpXG4gICAgICAgIC5zZWxlY3RBbGwoJ2cuJyArIGNvbnN0YW50cy5kcm9wZG93bkJ1dHRvbkNsYXNzTmFtZSkucmVtb3ZlKCk7XG59XG5cbn0se1wiLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudFwiOjY4OCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9wbG90cy9wbG90c1wiOjgyOCxcIi4uL2NvbG9yXCI6NTkzLFwiLi4vZHJhd2luZ1wiOjYxNCxcIi4vY29uc3RhbnRzXCI6NjgzLFwiLi9zY3JvbGxib3hcIjo2ODcsXCJkM1wiOjE2M31dLDY4NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG5hcmd1bWVudHNbNF1bNjgwXVswXS5hcHBseShleHBvcnRzLGFyZ3VtZW50cylcbn0se1wiLi9hdHRyaWJ1dGVzXCI6NjgyLFwiLi9jb25zdGFudHNcIjo2ODMsXCIuL2RlZmF1bHRzXCI6Njg0LFwiLi9kcmF3XCI6Njg1LFwiZHVwXCI6NjgwfV0sNjg3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBTY3JvbGxCb3g7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG5cbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uL2RyYXdpbmcnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG4vKipcbiAqIEhlbHBlciBjbGFzcyB0byBzZXR1cCBhIHNjcm9sbCBib3hcbiAqXG4gKiBAY2xhc3NcbiAqIEBwYXJhbSAgICAgICAgICAgZ2QgICAgICAgICAgUGxvdGx5J3MgZ3JhcGggZGl2XG4gKiBAcGFyYW0gICAgICAgICAgIGNvbnRhaW5lciAgIENvbnRhaW5lciB0byBiZSBzY3JvbGwtYm94ZWQgKGFzIGEgRDMgc2VsZWN0aW9uKVxuICogQHBhcmFtIHtzdHJpbmd9ICBpZCAgICAgICAgICBJZCBmb3IgdGhlIGNsaXAgcGF0aCB0byBpbXBsZW1lbnQgdGhlIHNjcm9sbCBib3hcbiAqL1xuZnVuY3Rpb24gU2Nyb2xsQm94KGdkLCBjb250YWluZXIsIGlkKSB7XG4gICAgdGhpcy5nZCA9IGdkO1xuICAgIHRoaXMuY29udGFpbmVyID0gY29udGFpbmVyO1xuICAgIHRoaXMuaWQgPSBpZDtcblxuICAgIC8vIFNlZSBTY3JvbGxCb3gucHJvdG90eXBlLmVuYWJsZSBmb3IgZnVydGhlciBkZWZpbml0aW9uXG4gICAgdGhpcy5wb3NpdGlvbiA9IG51bGw7ICAvLyBzY3JvbGxib3ggcG9zaXRpb25cbiAgICB0aGlzLnRyYW5zbGF0ZVggPSBudWxsOyAgLy8gc2Nyb2xsYm94IGhvcml6b250YWwgdHJhbnNsYXRpb25cbiAgICB0aGlzLnRyYW5zbGF0ZVkgPSBudWxsOyAgLy8gc2Nyb2xsYm94IHZlcnRpY2FsIHRyYW5zbGF0aW9uXG4gICAgdGhpcy5oYmFyID0gbnVsbDsgIC8vIGhvcml6b250YWwgc2Nyb2xsYmFyIEQzIHNlbGVjdGlvblxuICAgIHRoaXMudmJhciA9IG51bGw7ICAvLyB2ZXJ0aWNhbCBzY3JvbGxiYXIgRDMgc2VsZWN0aW9uXG5cbiAgICAvLyA8cmVjdD4gZWxlbWVudCB0byBjYXB0dXJlIHBvaW50ZXIgZXZlbnRzXG4gICAgdGhpcy5iZyA9IHRoaXMuY29udGFpbmVyLnNlbGVjdEFsbCgncmVjdC5zY3JvbGxib3gtYmcnKS5kYXRhKFswXSk7XG5cbiAgICB0aGlzLmJnLmV4aXQoKVxuICAgICAgICAub24oJy5kcmFnJywgbnVsbClcbiAgICAgICAgLm9uKCd3aGVlbCcsIG51bGwpXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIHRoaXMuYmcuZW50ZXIoKS5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZCgnc2Nyb2xsYm94LWJnJywgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhbGwnKVxuICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICBvcGFjaXR5OiAwLFxuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICB3aWR0aDogMCxcbiAgICAgICAgICAgIGhlaWdodDogMFxuICAgICAgICB9KTtcbn1cblxuLy8gc2Nyb2xsIGJhciBkaW1lbnNpb25zXG5TY3JvbGxCb3guYmFyV2lkdGggPSAyO1xuU2Nyb2xsQm94LmJhckxlbmd0aCA9IDIwO1xuU2Nyb2xsQm94LmJhclJhZGl1cyA9IDI7XG5TY3JvbGxCb3guYmFyUGFkID0gMTtcblNjcm9sbEJveC5iYXJDb2xvciA9ICcjODA4QkE0JztcblxuLyoqXG4gKiBJZiBuZWVkZWQsIHNldHVwIGEgY2xpcCBwYXRoIGFuZCBzY3JvbGxiYXJzXG4gKlxuICogQG1ldGhvZFxuICogQHBhcmFtIHtPYmplY3R9ICBwb3NpdGlvblxuICogQHBhcmFtIHtudW1iZXJ9ICBwb3NpdGlvbi5sICBMZWZ0IHNpZGUgcG9zaXRpb24gKGluIHBpeGVscylcbiAqIEBwYXJhbSB7bnVtYmVyfSAgcG9zaXRpb24udCAgVG9wIHNpZGUgKGluIHBpeGVscylcbiAqIEBwYXJhbSB7bnVtYmVyfSAgcG9zaXRpb24udyAgV2lkdGggKGluIHBpeGVscylcbiAqIEBwYXJhbSB7bnVtYmVyfSAgcG9zaXRpb24uaCAgSGVpZ2h0IChpbiBwaXhlbHMpXG4gKiBAcGFyYW0ge3N0cmluZ30gIFtwb3NpdGlvbi5kaXJlY3Rpb249J2Rvd24nXVxuICogICAgICAgICAgICAgICAgICBFaXRoZXIgJ2Rvd24nLCAnbGVmdCcsICdyaWdodCcgb3IgJ3VwJ1xuICogQHBhcmFtIHtudW1iZXJ9ICBbdHJhbnNsYXRlWD0wXSAgSG9yaXpvbnRhbCBvZmZzZXQgKGluIHBpeGVscylcbiAqIEBwYXJhbSB7bnVtYmVyfSAgW3RyYW5zbGF0ZVk9MF0gIFZlcnRpY2FsIG9mZnNldCAoaW4gcGl4ZWxzKVxuICovXG5TY3JvbGxCb3gucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uIGVuYWJsZShwb3NpdGlvbiwgdHJhbnNsYXRlWCwgdHJhbnNsYXRlWSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gdGhpcy5nZC5fZnVsbExheW91dDtcbiAgICB2YXIgZnVsbFdpZHRoID0gZnVsbExheW91dC53aWR0aDtcbiAgICB2YXIgZnVsbEhlaWdodCA9IGZ1bGxMYXlvdXQuaGVpZ2h0O1xuXG4gICAgLy8gY29tcHV0ZSBwb3NpdGlvbiBvZiBzY3JvbGxib3hcbiAgICB0aGlzLnBvc2l0aW9uID0gcG9zaXRpb247XG5cbiAgICB2YXIgbCA9IHRoaXMucG9zaXRpb24ubDtcbiAgICB2YXIgdyA9IHRoaXMucG9zaXRpb24udztcbiAgICB2YXIgdCA9IHRoaXMucG9zaXRpb24udDtcbiAgICB2YXIgaCA9IHRoaXMucG9zaXRpb24uaDtcbiAgICB2YXIgZGlyZWN0aW9uID0gdGhpcy5wb3NpdGlvbi5kaXJlY3Rpb247XG4gICAgdmFyIGlzRG93biA9IChkaXJlY3Rpb24gPT09ICdkb3duJyk7XG4gICAgdmFyIGlzTGVmdCA9IChkaXJlY3Rpb24gPT09ICdsZWZ0Jyk7XG4gICAgdmFyIGlzUmlnaHQgPSAoZGlyZWN0aW9uID09PSAncmlnaHQnKTtcbiAgICB2YXIgaXNVcCA9IChkaXJlY3Rpb24gPT09ICd1cCcpO1xuICAgIHZhciBib3hXID0gdztcbiAgICB2YXIgYm94SCA9IGg7XG4gICAgdmFyIGJveEwsIGJveFI7XG4gICAgdmFyIGJveFQsIGJveEI7XG5cbiAgICBpZighaXNEb3duICYmICFpc0xlZnQgJiYgIWlzUmlnaHQgJiYgIWlzVXApIHtcbiAgICAgICAgdGhpcy5wb3NpdGlvbi5kaXJlY3Rpb24gPSAnZG93bic7XG4gICAgICAgIGlzRG93biA9IHRydWU7XG4gICAgfVxuXG4gICAgdmFyIGlzVmVydGljYWwgPSBpc0Rvd24gfHwgaXNVcDtcbiAgICBpZihpc1ZlcnRpY2FsKSB7XG4gICAgICAgIGJveEwgPSBsO1xuICAgICAgICBib3hSID0gYm94TCArIGJveFc7XG5cbiAgICAgICAgaWYoaXNEb3duKSB7XG4gICAgICAgICAgICAvLyBhbmNob3IgdG8gdG9wIHNpZGVcbiAgICAgICAgICAgIGJveFQgPSB0O1xuICAgICAgICAgICAgYm94QiA9IE1hdGgubWluKGJveFQgKyBib3hILCBmdWxsSGVpZ2h0KTtcbiAgICAgICAgICAgIGJveEggPSBib3hCIC0gYm94VDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGFuY2hvciB0byBib3R0b20gc2lkZVxuICAgICAgICAgICAgYm94QiA9IHQgKyBib3hIO1xuICAgICAgICAgICAgYm94VCA9IE1hdGgubWF4KGJveEIgLSBib3hILCAwKTtcbiAgICAgICAgICAgIGJveEggPSBib3hCIC0gYm94VDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGJveFQgPSB0O1xuICAgICAgICBib3hCID0gYm94VCArIGJveEg7XG5cbiAgICAgICAgaWYoaXNMZWZ0KSB7XG4gICAgICAgICAgICAvLyBhbmNob3IgdG8gcmlnaHQgc2lkZVxuICAgICAgICAgICAgYm94UiA9IGwgKyBib3hXO1xuICAgICAgICAgICAgYm94TCA9IE1hdGgubWF4KGJveFIgLSBib3hXLCAwKTtcbiAgICAgICAgICAgIGJveFcgPSBib3hSIC0gYm94TDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGFuY2hvciB0byBsZWZ0IHNpZGVcbiAgICAgICAgICAgIGJveEwgPSBsO1xuICAgICAgICAgICAgYm94UiA9IE1hdGgubWluKGJveEwgKyBib3hXLCBmdWxsV2lkdGgpO1xuICAgICAgICAgICAgYm94VyA9IGJveFIgLSBib3hMO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5fYm94ID0ge1xuICAgICAgICBsOiBib3hMLFxuICAgICAgICB0OiBib3hULFxuICAgICAgICB3OiBib3hXLFxuICAgICAgICBoOiBib3hIXG4gICAgfTtcblxuICAgIC8vIGNvbXB1dGUgcG9zaXRpb24gb2YgaG9yaXpvbnRhbCBzY3JvbGwgYmFyXG4gICAgdmFyIG5lZWRzSG9yaXpvbnRhbFNjcm9sbEJhciA9ICh3ID4gYm94Vyk7XG4gICAgdmFyIGhiYXJXID0gU2Nyb2xsQm94LmJhckxlbmd0aCArIDIgKiBTY3JvbGxCb3guYmFyUGFkO1xuICAgIHZhciBoYmFySCA9IFNjcm9sbEJveC5iYXJXaWR0aCArIDIgKiBTY3JvbGxCb3guYmFyUGFkO1xuICAgIC8vIGRyYXcgaG9yaXpvbnRhbCBzY3JvbGxiYXIgb24gdGhlIGJvdHRvbSBzaWRlXG4gICAgdmFyIGhiYXJMID0gbDtcbiAgICB2YXIgaGJhclQgPSB0ICsgaDtcblxuICAgIGlmKGhiYXJUICsgaGJhckggPiBmdWxsSGVpZ2h0KSBoYmFyVCA9IGZ1bGxIZWlnaHQgLSBoYmFySDtcblxuICAgIHZhciBoYmFyID0gdGhpcy5jb250YWluZXIuc2VsZWN0QWxsKCdyZWN0LnNjcm9sbGJhci1ob3Jpem9udGFsJykuZGF0YShcbiAgICAgICAgICAgIChuZWVkc0hvcml6b250YWxTY3JvbGxCYXIpID8gWzBdIDogW10pO1xuXG4gICAgaGJhci5leGl0KClcbiAgICAgICAgLm9uKCcuZHJhZycsIG51bGwpXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIGhiYXIuZW50ZXIoKS5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZCgnc2Nyb2xsYmFyLWhvcml6b250YWwnLCB0cnVlKVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBTY3JvbGxCb3guYmFyQ29sb3IpO1xuXG4gICAgaWYobmVlZHNIb3Jpem9udGFsU2Nyb2xsQmFyKSB7XG4gICAgICAgIHRoaXMuaGJhciA9IGhiYXIuYXR0cih7XG4gICAgICAgICAgICAncngnOiBTY3JvbGxCb3guYmFyUmFkaXVzLFxuICAgICAgICAgICAgJ3J5JzogU2Nyb2xsQm94LmJhclJhZGl1cyxcbiAgICAgICAgICAgICd4JzogaGJhckwsXG4gICAgICAgICAgICAneSc6IGhiYXJULFxuICAgICAgICAgICAgJ3dpZHRoJzogaGJhclcsXG4gICAgICAgICAgICAnaGVpZ2h0JzogaGJhckhcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gaGJhciBjZW50ZXIgbW92ZXMgYmV0d2VlbiBoYmFyWE1pbiBhbmQgaGJhclhNaW4gKyBoYmFyVHJhbnNsYXRlTWF4XG4gICAgICAgIHRoaXMuX2hiYXJYTWluID0gaGJhckwgKyBoYmFyVyAvIDI7XG4gICAgICAgIHRoaXMuX2hiYXJUcmFuc2xhdGVNYXggPSBib3hXIC0gaGJhclc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuaGJhcjtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2hiYXJYTWluO1xuICAgICAgICBkZWxldGUgdGhpcy5faGJhclRyYW5zbGF0ZU1heDtcbiAgICB9XG5cbiAgICAvLyBjb21wdXRlIHBvc2l0aW9uIG9mIHZlcnRpY2FsIHNjcm9sbCBiYXJcbiAgICB2YXIgbmVlZHNWZXJ0aWNhbFNjcm9sbEJhciA9IChoID4gYm94SCk7XG4gICAgdmFyIHZiYXJXID0gU2Nyb2xsQm94LmJhcldpZHRoICsgMiAqIFNjcm9sbEJveC5iYXJQYWQ7XG4gICAgdmFyIHZiYXJIID0gU2Nyb2xsQm94LmJhckxlbmd0aCArIDIgKiBTY3JvbGxCb3guYmFyUGFkO1xuICAgIC8vIGRyYXcgdmVydGljYWwgc2Nyb2xsYmFyIG9uIHRoZSByaWdodCBzaWRlXG4gICAgdmFyIHZiYXJMID0gbCArIHc7XG4gICAgdmFyIHZiYXJUID0gdDtcblxuICAgIGlmKHZiYXJMICsgdmJhclcgPiBmdWxsV2lkdGgpIHZiYXJMID0gZnVsbFdpZHRoIC0gdmJhclc7XG5cbiAgICB2YXIgdmJhciA9IHRoaXMuY29udGFpbmVyLnNlbGVjdEFsbCgncmVjdC5zY3JvbGxiYXItdmVydGljYWwnKS5kYXRhKFxuICAgICAgICAgICAgKG5lZWRzVmVydGljYWxTY3JvbGxCYXIpID8gWzBdIDogW10pO1xuXG4gICAgdmJhci5leGl0KClcbiAgICAgICAgLm9uKCcuZHJhZycsIG51bGwpXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIHZiYXIuZW50ZXIoKS5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZCgnc2Nyb2xsYmFyLXZlcnRpY2FsJywgdHJ1ZSlcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgU2Nyb2xsQm94LmJhckNvbG9yKTtcblxuICAgIGlmKG5lZWRzVmVydGljYWxTY3JvbGxCYXIpIHtcbiAgICAgICAgdGhpcy52YmFyID0gdmJhci5hdHRyKHtcbiAgICAgICAgICAgICdyeCc6IFNjcm9sbEJveC5iYXJSYWRpdXMsXG4gICAgICAgICAgICAncnknOiBTY3JvbGxCb3guYmFyUmFkaXVzLFxuICAgICAgICAgICAgJ3gnOiB2YmFyTCxcbiAgICAgICAgICAgICd5JzogdmJhclQsXG4gICAgICAgICAgICAnd2lkdGgnOiB2YmFyVyxcbiAgICAgICAgICAgICdoZWlnaHQnOiB2YmFySFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyB2YmFyIGNlbnRlciBtb3ZlcyBiZXR3ZWVuIHZiYXJZTWluIGFuZCB2YmFyWU1pbiArIHZiYXJUcmFuc2xhdGVNYXhcbiAgICAgICAgdGhpcy5fdmJhcllNaW4gPSB2YmFyVCArIHZiYXJIIC8gMjtcbiAgICAgICAgdGhpcy5fdmJhclRyYW5zbGF0ZU1heCA9IGJveEggLSB2YmFySDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkZWxldGUgdGhpcy52YmFyO1xuICAgICAgICBkZWxldGUgdGhpcy5fdmJhcllNaW47XG4gICAgICAgIGRlbGV0ZSB0aGlzLl92YmFyVHJhbnNsYXRlTWF4O1xuICAgIH1cblxuICAgIC8vIHNldHVwIGEgY2xpcCBwYXRoIChpZiBzY3JvbGwgYmFycyBhcmUgbmVlZGVkKVxuICAgIHZhciBjbGlwSWQgPSB0aGlzLmlkO1xuICAgIHZhciBjbGlwTCA9IGJveEwgLSAwLjU7XG4gICAgdmFyIGNsaXBSID0gKG5lZWRzVmVydGljYWxTY3JvbGxCYXIpID8gYm94UiArIHZiYXJXICsgMC41IDogYm94UiArIDAuNTtcbiAgICB2YXIgY2xpcFQgPSBib3hUIC0gMC41O1xuICAgIHZhciBjbGlwQiA9IChuZWVkc0hvcml6b250YWxTY3JvbGxCYXIpID8gYm94QiArIGhiYXJIICsgMC41IDogYm94QiArIDAuNTtcblxuICAgIHZhciBjbGlwUGF0aCA9IGZ1bGxMYXlvdXQuX3RvcGRlZnMuc2VsZWN0QWxsKCcjJyArIGNsaXBJZClcbiAgICAgICAgLmRhdGEoKG5lZWRzSG9yaXpvbnRhbFNjcm9sbEJhciB8fCBuZWVkc1ZlcnRpY2FsU2Nyb2xsQmFyKSA/IFswXSA6IFtdKTtcblxuICAgIGNsaXBQYXRoLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGNsaXBQYXRoLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnY2xpcFBhdGgnKS5hdHRyKCdpZCcsIGNsaXBJZClcbiAgICAgICAgLmFwcGVuZCgncmVjdCcpO1xuXG4gICAgaWYobmVlZHNIb3Jpem9udGFsU2Nyb2xsQmFyIHx8IG5lZWRzVmVydGljYWxTY3JvbGxCYXIpIHtcbiAgICAgICAgdGhpcy5fY2xpcFJlY3QgPSBjbGlwUGF0aC5zZWxlY3QoJ3JlY3QnKS5hdHRyKHtcbiAgICAgICAgICAgIHg6IE1hdGguZmxvb3IoY2xpcEwpLFxuICAgICAgICAgICAgeTogTWF0aC5mbG9vcihjbGlwVCksXG4gICAgICAgICAgICB3aWR0aDogTWF0aC5jZWlsKGNsaXBSKSAtIE1hdGguZmxvb3IoY2xpcEwpLFxuICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLmNlaWwoY2xpcEIpIC0gTWF0aC5mbG9vcihjbGlwVClcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5jb250YWluZXIuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIGNsaXBJZCwgdGhpcy5nZCk7XG5cbiAgICAgICAgdGhpcy5iZy5hdHRyKHtcbiAgICAgICAgICAgIHg6IGwsXG4gICAgICAgICAgICB5OiB0LFxuICAgICAgICAgICAgd2lkdGg6IHcsXG4gICAgICAgICAgICBoZWlnaHQ6IGhcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5iZy5hdHRyKHtcbiAgICAgICAgICAgIHdpZHRoOiAwLFxuICAgICAgICAgICAgaGVpZ2h0OiAwXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmNvbnRhaW5lclxuICAgICAgICAgICAgLm9uKCd3aGVlbCcsIG51bGwpXG4gICAgICAgICAgICAub24oJy5kcmFnJywgbnVsbClcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0Q2xpcFVybCwgbnVsbCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9jbGlwUmVjdDtcbiAgICB9XG5cbiAgICAvLyBzZXQgdXAgZHJhZyBsaXN0ZW5lcnMgKGlmIHNjcm9sbCBiYXJzIGFyZSBuZWVkZWQpXG4gICAgaWYobmVlZHNIb3Jpem9udGFsU2Nyb2xsQmFyIHx8IG5lZWRzVmVydGljYWxTY3JvbGxCYXIpIHtcbiAgICAgICAgdmFyIG9uQm94RHJhZyA9IGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAgICAgLm9uKCdkcmFnc3RhcnQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBkMy5ldmVudC5zb3VyY2VFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5vbignZHJhZycsIHRoaXMuX29uQm94RHJhZy5iaW5kKHRoaXMpKTtcblxuICAgICAgICB0aGlzLmNvbnRhaW5lclxuICAgICAgICAgICAgLm9uKCd3aGVlbCcsIG51bGwpXG4gICAgICAgICAgICAub24oJ3doZWVsJywgdGhpcy5fb25Cb3hXaGVlbC5iaW5kKHRoaXMpKVxuICAgICAgICAgICAgLm9uKCcuZHJhZycsIG51bGwpXG4gICAgICAgICAgICAuY2FsbChvbkJveERyYWcpO1xuXG4gICAgICAgIHZhciBvbkJhckRyYWcgPSBkMy5iZWhhdmlvci5kcmFnKClcbiAgICAgICAgICAgIC5vbignZHJhZ3N0YXJ0JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgZDMuZXZlbnQuc291cmNlRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBkMy5ldmVudC5zb3VyY2VFdmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAub24oJ2RyYWcnLCB0aGlzLl9vbkJhckRyYWcuYmluZCh0aGlzKSk7XG5cbiAgICAgICAgaWYobmVlZHNIb3Jpem9udGFsU2Nyb2xsQmFyKSB7XG4gICAgICAgICAgICB0aGlzLmhiYXJcbiAgICAgICAgICAgICAgICAub24oJy5kcmFnJywgbnVsbClcbiAgICAgICAgICAgICAgICAuY2FsbChvbkJhckRyYWcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobmVlZHNWZXJ0aWNhbFNjcm9sbEJhcikge1xuICAgICAgICAgICAgdGhpcy52YmFyXG4gICAgICAgICAgICAgICAgLm9uKCcuZHJhZycsIG51bGwpXG4gICAgICAgICAgICAgICAgLmNhbGwob25CYXJEcmFnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNldCBzY3JvbGxib3ggdHJhbnNsYXRpb25cbiAgICB0aGlzLnNldFRyYW5zbGF0ZSh0cmFuc2xhdGVYLCB0cmFuc2xhdGVZKTtcbn07XG5cbi8qKlxuICogSWYgcHJlc2VudCwgcmVtb3ZlIGNsaXAtcGF0aCBhbmQgc2Nyb2xsYmFyc1xuICpcbiAqIEBtZXRob2RcbiAqL1xuU2Nyb2xsQm94LnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gZGlzYWJsZSgpIHtcbiAgICBpZih0aGlzLmhiYXIgfHwgdGhpcy52YmFyKSB7XG4gICAgICAgIHRoaXMuYmcuYXR0cih7XG4gICAgICAgICAgICB3aWR0aDogMCxcbiAgICAgICAgICAgIGhlaWdodDogMFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5jb250YWluZXJcbiAgICAgICAgICAgIC5vbignd2hlZWwnLCBudWxsKVxuICAgICAgICAgICAgLm9uKCcuZHJhZycsIG51bGwpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIG51bGwpO1xuICAgICAgICBkZWxldGUgdGhpcy5fY2xpcFJlY3Q7XG4gICAgfVxuXG4gICAgaWYodGhpcy5oYmFyKSB7XG4gICAgICAgIHRoaXMuaGJhci5vbignLmRyYWcnLCBudWxsKTtcbiAgICAgICAgdGhpcy5oYmFyLnJlbW92ZSgpO1xuICAgICAgICBkZWxldGUgdGhpcy5oYmFyO1xuICAgICAgICBkZWxldGUgdGhpcy5faGJhclhNaW47XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9oYmFyVHJhbnNsYXRlTWF4O1xuICAgIH1cblxuICAgIGlmKHRoaXMudmJhcikge1xuICAgICAgICB0aGlzLnZiYXIub24oJy5kcmFnJywgbnVsbCk7XG4gICAgICAgIHRoaXMudmJhci5yZW1vdmUoKTtcbiAgICAgICAgZGVsZXRlIHRoaXMudmJhcjtcbiAgICAgICAgZGVsZXRlIHRoaXMuX3ZiYXJZTWluO1xuICAgICAgICBkZWxldGUgdGhpcy5fdmJhclRyYW5zbGF0ZU1heDtcbiAgICB9XG59O1xuXG4vKipcbiAqIEhhbmRsZXMgc2Nyb2xsIGJveCBkcmFnIGV2ZW50c1xuICpcbiAqIEBtZXRob2RcbiAqL1xuU2Nyb2xsQm94LnByb3RvdHlwZS5fb25Cb3hEcmFnID0gZnVuY3Rpb24gX29uQm94RHJhZygpIHtcbiAgICB2YXIgdHJhbnNsYXRlWCA9IHRoaXMudHJhbnNsYXRlWDtcbiAgICB2YXIgdHJhbnNsYXRlWSA9IHRoaXMudHJhbnNsYXRlWTtcblxuICAgIGlmKHRoaXMuaGJhcikge1xuICAgICAgICB0cmFuc2xhdGVYIC09IGQzLmV2ZW50LmR4O1xuICAgIH1cblxuICAgIGlmKHRoaXMudmJhcikge1xuICAgICAgICB0cmFuc2xhdGVZIC09IGQzLmV2ZW50LmR5O1xuICAgIH1cblxuICAgIHRoaXMuc2V0VHJhbnNsYXRlKHRyYW5zbGF0ZVgsIHRyYW5zbGF0ZVkpO1xufTtcblxuLyoqXG4gKiBIYW5kbGVzIHNjcm9sbCBib3ggd2hlZWwgZXZlbnRzXG4gKlxuICogQG1ldGhvZFxuICovXG5TY3JvbGxCb3gucHJvdG90eXBlLl9vbkJveFdoZWVsID0gZnVuY3Rpb24gX29uQm94V2hlZWwoKSB7XG4gICAgdmFyIHRyYW5zbGF0ZVggPSB0aGlzLnRyYW5zbGF0ZVg7XG4gICAgdmFyIHRyYW5zbGF0ZVkgPSB0aGlzLnRyYW5zbGF0ZVk7XG5cbiAgICBpZih0aGlzLmhiYXIpIHtcbiAgICAgICAgdHJhbnNsYXRlWCArPSBkMy5ldmVudC5kZWx0YVk7XG4gICAgfVxuXG4gICAgaWYodGhpcy52YmFyKSB7XG4gICAgICAgIHRyYW5zbGF0ZVkgKz0gZDMuZXZlbnQuZGVsdGFZO1xuICAgIH1cblxuICAgIHRoaXMuc2V0VHJhbnNsYXRlKHRyYW5zbGF0ZVgsIHRyYW5zbGF0ZVkpO1xufTtcblxuLyoqXG4gKiBIYW5kbGVzIHNjcm9sbCBiYXIgZHJhZyBldmVudHNcbiAqXG4gKiBAbWV0aG9kXG4gKi9cblNjcm9sbEJveC5wcm90b3R5cGUuX29uQmFyRHJhZyA9IGZ1bmN0aW9uIF9vbkJhckRyYWcoKSB7XG4gICAgdmFyIHRyYW5zbGF0ZVggPSB0aGlzLnRyYW5zbGF0ZVg7XG4gICAgdmFyIHRyYW5zbGF0ZVkgPSB0aGlzLnRyYW5zbGF0ZVk7XG5cbiAgICBpZih0aGlzLmhiYXIpIHtcbiAgICAgICAgdmFyIHhNaW4gPSB0cmFuc2xhdGVYICsgdGhpcy5faGJhclhNaW47XG4gICAgICAgIHZhciB4TWF4ID0geE1pbiArIHRoaXMuX2hiYXJUcmFuc2xhdGVNYXg7XG4gICAgICAgIHZhciB4ID0gTGliLmNvbnN0cmFpbihkMy5ldmVudC54LCB4TWluLCB4TWF4KTtcbiAgICAgICAgdmFyIHhmID0gKHggLSB4TWluKSAvICh4TWF4IC0geE1pbik7XG5cbiAgICAgICAgdmFyIHRyYW5zbGF0ZVhNYXggPSB0aGlzLnBvc2l0aW9uLncgLSB0aGlzLl9ib3gudztcblxuICAgICAgICB0cmFuc2xhdGVYID0geGYgKiB0cmFuc2xhdGVYTWF4O1xuICAgIH1cblxuICAgIGlmKHRoaXMudmJhcikge1xuICAgICAgICB2YXIgeU1pbiA9IHRyYW5zbGF0ZVkgKyB0aGlzLl92YmFyWU1pbjtcbiAgICAgICAgdmFyIHlNYXggPSB5TWluICsgdGhpcy5fdmJhclRyYW5zbGF0ZU1heDtcbiAgICAgICAgdmFyIHkgPSBMaWIuY29uc3RyYWluKGQzLmV2ZW50LnksIHlNaW4sIHlNYXgpO1xuICAgICAgICB2YXIgeWYgPSAoeSAtIHlNaW4pIC8gKHlNYXggLSB5TWluKTtcblxuICAgICAgICB2YXIgdHJhbnNsYXRlWU1heCA9IHRoaXMucG9zaXRpb24uaCAtIHRoaXMuX2JveC5oO1xuXG4gICAgICAgIHRyYW5zbGF0ZVkgPSB5ZiAqIHRyYW5zbGF0ZVlNYXg7XG4gICAgfVxuXG4gICAgdGhpcy5zZXRUcmFuc2xhdGUodHJhbnNsYXRlWCwgdHJhbnNsYXRlWSk7XG59O1xuXG4vKipcbiAqIFNldCBjbGlwIHBhdGggYW5kIHNjcm9sbCBiYXIgdHJhbnNsYXRlIHRyYW5zZm9ybVxuICpcbiAqIEBtZXRob2RcbiAqIEBwYXJhbSB7bnVtYmVyfSAgW3RyYW5zbGF0ZVg9MF0gIEhvcml6b250YWwgb2Zmc2V0IChpbiBwaXhlbHMpXG4gKiBAcGFyYW0ge251bWJlcn0gIFt0cmFuc2xhdGVZPTBdICBWZXJ0aWNhbCBvZmZzZXQgKGluIHBpeGVscylcbiAqL1xuU2Nyb2xsQm94LnByb3RvdHlwZS5zZXRUcmFuc2xhdGUgPSBmdW5jdGlvbiBzZXRUcmFuc2xhdGUodHJhbnNsYXRlWCwgdHJhbnNsYXRlWSkge1xuICAgIC8vIHN0b3JlIHRyYW5zbGF0ZVggYW5kIHRyYW5zbGF0ZVkgKG5lZWRlZCBieSBtb3VzZSBldmVudCBoYW5kbGVycylcbiAgICB2YXIgdHJhbnNsYXRlWE1heCA9IHRoaXMucG9zaXRpb24udyAtIHRoaXMuX2JveC53O1xuICAgIHZhciB0cmFuc2xhdGVZTWF4ID0gdGhpcy5wb3NpdGlvbi5oIC0gdGhpcy5fYm94Lmg7XG5cbiAgICB0cmFuc2xhdGVYID0gTGliLmNvbnN0cmFpbih0cmFuc2xhdGVYIHx8IDAsIDAsIHRyYW5zbGF0ZVhNYXgpO1xuICAgIHRyYW5zbGF0ZVkgPSBMaWIuY29uc3RyYWluKHRyYW5zbGF0ZVkgfHwgMCwgMCwgdHJhbnNsYXRlWU1heCk7XG5cbiAgICB0aGlzLnRyYW5zbGF0ZVggPSB0cmFuc2xhdGVYO1xuICAgIHRoaXMudHJhbnNsYXRlWSA9IHRyYW5zbGF0ZVk7XG5cbiAgICB0aGlzLmNvbnRhaW5lci5jYWxsKERyYXdpbmcuc2V0VHJhbnNsYXRlLFxuICAgICAgICB0aGlzLl9ib3gubCAtIHRoaXMucG9zaXRpb24ubCAtIHRyYW5zbGF0ZVgsXG4gICAgICAgIHRoaXMuX2JveC50IC0gdGhpcy5wb3NpdGlvbi50IC0gdHJhbnNsYXRlWSk7XG5cbiAgICBpZih0aGlzLl9jbGlwUmVjdCkge1xuICAgICAgICB0aGlzLl9jbGlwUmVjdC5hdHRyKHtcbiAgICAgICAgICAgIHg6IE1hdGguZmxvb3IodGhpcy5wb3NpdGlvbi5sICsgdHJhbnNsYXRlWCAtIDAuNSksXG4gICAgICAgICAgICB5OiBNYXRoLmZsb29yKHRoaXMucG9zaXRpb24udCArIHRyYW5zbGF0ZVkgLSAwLjUpXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKHRoaXMuaGJhcikge1xuICAgICAgICB2YXIgeGYgPSB0cmFuc2xhdGVYIC8gdHJhbnNsYXRlWE1heDtcblxuICAgICAgICB0aGlzLmhiYXIuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSxcbiAgICAgICAgICAgIHRyYW5zbGF0ZVggKyB4ZiAqIHRoaXMuX2hiYXJUcmFuc2xhdGVNYXgsXG4gICAgICAgICAgICB0cmFuc2xhdGVZKTtcbiAgICB9XG5cbiAgICBpZih0aGlzLnZiYXIpIHtcbiAgICAgICAgdmFyIHlmID0gdHJhbnNsYXRlWSAvIHRyYW5zbGF0ZVlNYXg7XG5cbiAgICAgICAgdGhpcy52YmFyLmNhbGwoRHJhd2luZy5zZXRUcmFuc2xhdGUsXG4gICAgICAgICAgICB0cmFuc2xhdGVYLFxuICAgICAgICAgICAgdHJhbnNsYXRlWSArIHlmICogdGhpcy5fdmJhclRyYW5zbGF0ZU1heCk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi9jb2xvclwiOjU5MyxcIi4uL2RyYXdpbmdcIjo2MTQsXCJkM1wiOjE2M31dLDY4ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8vIGZyYWN0aW9uIG9mIHNvbWUgc2l6ZSB0byBnZXQgdG8gYSBuYW1lZCBwb3NpdGlvblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgLy8gZnJvbSBib3R0b20gbGVmdDogdGhpcyBpcyB0aGUgb3JpZ2luIG9mIG91ciBwYXBlci1yZWZlcmVuY2VcbiAgICAvLyBwb3NpdGlvbmluZyBzeXN0ZW1cbiAgICBGUk9NX0JMOiB7XG4gICAgICAgIGxlZnQ6IDAsXG4gICAgICAgIGNlbnRlcjogMC41LFxuICAgICAgICByaWdodDogMSxcbiAgICAgICAgYm90dG9tOiAwLFxuICAgICAgICBtaWRkbGU6IDAuNSxcbiAgICAgICAgdG9wOiAxXG4gICAgfSxcbiAgICAvLyBmcm9tIHRvcCBsZWZ0OiB0aGlzIGlzIHRoZSBzY3JlZW4gcGl4ZWwgcG9zaXRpb25pbmcgb3JpZ2luXG4gICAgRlJPTV9UTDoge1xuICAgICAgICBsZWZ0OiAwLFxuICAgICAgICBjZW50ZXI6IDAuNSxcbiAgICAgICAgcmlnaHQ6IDEsXG4gICAgICAgIGJvdHRvbTogMSxcbiAgICAgICAgbWlkZGxlOiAwLjUsXG4gICAgICAgIHRvcDogMFxuICAgIH0sXG4gICAgLy8gZnJvbSBib3R0b20gcmlnaHQ6IHNvbWV0aW1lcyB5b3UganVzdCBuZWVkIHRoZSBvcHBvc2l0ZSBvZiBeXlxuICAgIEZST01fQlI6IHtcbiAgICAgICAgbGVmdDogMSxcbiAgICAgICAgY2VudGVyOiAwLjUsXG4gICAgICAgIHJpZ2h0OiAwLFxuICAgICAgICBib3R0b206IDAsXG4gICAgICAgIG1pZGRsZTogMC41LFxuICAgICAgICB0b3A6IDFcbiAgICB9LFxuICAgIC8vIG11bHRpcGxlIG9mIGZvbnRTaXplIHRvIGdldCB0aGUgdmVydGljYWwgb2Zmc2V0IGJldHdlZW4gbGluZXNcbiAgICBMSU5FX1NQQUNJTkc6IDEuMyxcblxuICAgIC8vIG11bHRpcGxlIG9mIGZvbnRTaXplIHRvIHNoaWZ0IGZyb20gdGhlIGJhc2VsaW5lXG4gICAgLy8gdG8gdGhlIGNhcCAoY2FwdGljYWwgbGV0dGVyKSBsaW5lXG4gICAgLy8gKHRvIHVzZSB3aGVuIHdlIGRvbid0IGNhbGN1bGF0ZSB0aGlzIHNoaWZ0IGZyb20gRHJhd2luZy5iQm94KVxuICAgIC8vIFRoaXMgaXMgYW4gYXBwcm94aW1hdGlvbiBzaW5jZSBpbiByZWFsaXR5IGNhcCBoZWlnaHQgY2FuIGRpZmZlclxuICAgIC8vIGZyb20gZm9udCB0byBmb250LiBIb3dldmVyLCBhY2NvcmRpbmcgdG8gV2lraXBlZGlhXG4gICAgLy8gICBhbiBcImF2ZXJhZ2VcIiBmb250IG1pZ2h0IGhhdmUgYSBjYXAgaGVpZ2h0IG9mIDcwJSBvZiB0aGUgZW1cbiAgICAvLyBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9FbV8odHlwb2dyYXBoeSkjSGlzdG9yeVxuICAgIENBUF9TSElGVDogMC43MCxcblxuICAgIC8vIGhhbGYgdGhlIGNhcCBoZWlnaHQgKGRpc3RhbmNlIGJldHdlZW4gYmFzZWxpbmUgYW5kIGNhcCBsaW5lKVxuICAgIC8vIG9mIGFuIFwiYXZlcmFnZVwiIGZvbnQgKGZvciBtb3JlIGluZm8gc2VlIGFib3ZlKS5cbiAgICBNSURfU0hJRlQ6IDAuMzUsXG5cbiAgICBPUFBPU0lURV9TSURFOiB7XG4gICAgICAgIGxlZnQ6ICdyaWdodCcsXG4gICAgICAgIHJpZ2h0OiAnbGVmdCcsXG4gICAgICAgIHRvcDogJ2JvdHRvbScsXG4gICAgICAgIGJvdHRvbTogJ3RvcCdcbiAgICB9XG59O1xuXG59LHt9XSw2ODk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBJTkNSRUFTSU5HOiB7XG4gICAgICAgIENPTE9SOiAnIzNEOTk3MCcsXG4gICAgICAgIFNZTUJPTDogJ+KWsidcbiAgICB9LFxuICAgIERFQ1JFQVNJTkc6IHtcbiAgICAgICAgQ09MT1I6ICcjRkY0MTM2JyxcbiAgICAgICAgU1lNQk9MOiAn4pa8J1xuICAgIH1cbn07XG5cbn0se31dLDY5MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIEZPUk1BVF9MSU5LOiAnaHR0cHM6Ly9naXRodWIuY29tL2QzL2QzLTMueC1hcGktcmVmZXJlbmNlL2Jsb2IvbWFzdGVyL0Zvcm1hdHRpbmcubWQjZDNfZm9ybWF0JyxcbiAgICBEQVRFX0ZPUk1BVF9MSU5LOiAnaHR0cHM6Ly9naXRodWIuY29tL2QzL2QzLTMueC1hcGktcmVmZXJlbmNlL2Jsb2IvbWFzdGVyL1RpbWUtRm9ybWF0dGluZy5tZCNmb3JtYXQnXG59O1xuXG59LHt9XSw2OTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBDT01QQVJJU09OX09QUzogWyc9JywgJyE9JywgJzwnLCAnPj0nLCAnPicsICc8PSddLFxuICAgIENPTVBBUklTT05fT1BTMjogWyc9JywgJzwnLCAnPj0nLCAnPicsICc8PSddLFxuICAgIElOVEVSVkFMX09QUzogWydbXScsICcoKScsICdbKScsICcoXScsICddWycsICcpKCcsICddKCcsICcpWyddLFxuICAgIFNFVF9PUFM6IFsne30nLCAnfXsnXSxcbiAgICBDT05TVFJBSU5UX1JFRFVDVElPTjoge1xuICAgICAgICAvLyBmb3IgY29udG91ciBjb25zdHJhaW50cywgb3Blbi9jbG9zZWQgZW5kcG9pbnRzIGFyZSBlcXVpdmFsZW50XG4gICAgICAgICc9JzogJz0nLFxuXG4gICAgICAgICc8JzogJzwnLFxuICAgICAgICAnPD0nOiAnPCcsXG5cbiAgICAgICAgJz4nOiAnPicsXG4gICAgICAgICc+PSc6ICc+JyxcblxuICAgICAgICAnW10nOiAnW10nLFxuICAgICAgICAnKCknOiAnW10nLFxuICAgICAgICAnWyknOiAnW10nLFxuICAgICAgICAnKF0nOiAnW10nLFxuXG4gICAgICAgICddWyc6ICddWycsXG4gICAgICAgICcpKCc6ICddWycsXG4gICAgICAgICddKCc6ICddWycsXG4gICAgICAgICcpWyc6ICddWydcbiAgICB9XG59O1xuXG59LHt9XSw2OTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHNvbGlkOiBbW10sIDBdLFxuICAgIGRvdDogW1swLjUsIDFdLCAyMDBdLFxuICAgIGRhc2g6IFtbMC41LCAxXSwgNTBdLFxuICAgIGxvbmdkYXNoOiBbWzAuNSwgMV0sIDEwXSxcbiAgICBkYXNoZG90OiBbWzAuNSwgMC42MjUsIDAuODc1LCAxXSwgNTBdLFxuICAgIGxvbmdkYXNoZG90OiBbWzAuNSwgMC43LCAwLjgsIDFdLCAxMF1cbn07XG5cbn0se31dLDY5MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY2lyY2xlOiAn4pePJyxcbiAgICAnY2lyY2xlLW9wZW4nOiAn4peLJyxcbiAgICBzcXVhcmU6ICfilqAnLFxuICAgICdzcXVhcmUtb3Blbic6ICfilqEnLFxuICAgIGRpYW1vbmQ6ICfil4YnLFxuICAgICdkaWFtb25kLW9wZW4nOiAn4peHJyxcbiAgICBjcm9zczogJysnLFxuICAgIHg6ICfinYwnXG59O1xuXG59LHt9XSw2OTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIC8qKlxuICAgICAqIFRpbWluZyBpbmZvcm1hdGlvbiBmb3IgaW50ZXJhY3RpdmUgZWxlbWVudHNcbiAgICAgKi9cbiAgICBTSE9XX1BMQUNFSE9MREVSOiAxMDAsXG4gICAgSElERV9QTEFDRUhPTERFUjogMTAwMCxcblxuICAgIC8vIG9wYWNpdHkgZGltbWluZyBmcmFjdGlvbiBmb3IgcG9pbnRzIHRoYXQgYXJlIG5vdCBpbiBzZWxlY3Rpb25cbiAgICBERVNFTEVDVERJTTogMC4yXG59O1xuXG59LHt9XSw2OTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIC8qKlxuICAgICAqIFN0YW5kYXJkaXplIGFsbCBtaXNzaW5nIGRhdGEgaW4gY2FsY2RhdGEgdG8gdXNlIHVuZGVmaW5lZFxuICAgICAqIG5ldmVyIG51bGwgb3IgTmFOLlxuICAgICAqIFRoYXQgd2F5IHdlIGNhbiB1c2UgIT09dW5kZWZpbmVkLCBvciAhPT0gQkFETlVNLFxuICAgICAqIHRvIHRlc3QgZm9yIHJlYWwgZGF0YVxuICAgICAqL1xuICAgIEJBRE5VTTogdW5kZWZpbmVkLFxuXG4gICAgLypcbiAgICAgKiBMaW1pdCBjZXJ0YWluIG9wZXJhdGlvbnMgdG8gd2VsbCBiZWxvdyBmbG9hdGluZyBwb2ludCBtYXggdmFsdWVcbiAgICAgKiB0byBhdm9pZCBnbGl0Y2hlczogTWFrZSBzdXJlIHRoYXQgZXZlbiB3aGVuIHlvdSBtdWx0aXBseSBpdCBieSB0aGVcbiAgICAgKiBudW1iZXIgb2YgcGl4ZWxzIG9uIGEgZ2lhbnQgc2NyZWVuIGl0IHN0aWxsIHdvcmtzXG4gICAgICovXG4gICAgRlBfU0FGRTogTnVtYmVyLk1BWF9WQUxVRSAvIDEwMDAwLFxuXG4gICAgLypcbiAgICAgKiBjb252ZXJzaW9uIG9mIGRhdGUgdW5pdHMgdG8gbWlsbGlzZWNvbmRzXG4gICAgICogeWVhciBhbmQgbW9udGggY29uc3RhbnRzIGFyZSBtYXJrZWQgXCJBVkdcIlxuICAgICAqIHRvIHJlbWluZCB1cyB0aGF0IG5vdCBhbGwgeWVhcnMgYW5kIG1vbnRoc1xuICAgICAqIGhhdmUgdGhlIHNhbWUgbGVuZ3RoXG4gICAgICovXG4gICAgT05FQVZHWUVBUjogMzE1NTc2MDAwMDAsIC8vIDM2NS4yNSBkYXlzXG4gICAgT05FQVZHTU9OVEg6IDI2Mjk4MDAwMDAsIC8vIDEvMTIgb2YgT05FQVZHWUVBUlxuICAgIE9ORURBWTogODY0MDAwMDAsXG4gICAgT05FSE9VUjogMzYwMDAwMCxcbiAgICBPTkVNSU46IDYwMDAwLFxuICAgIE9ORVNFQzogMTAwMCxcblxuICAgIC8qXG4gICAgICogRm9yIGZhc3QgY29udmVyc2lvbiBidHduIHdvcmxkIGNhbGVuZGFycyBhbmQgZXBvY2ggbXMsIHRoZSBKdWxpYW4gRGF5IE51bWJlclxuICAgICAqIG9mIHRoZSB1bml4IGVwb2NoLiBGcm9tIGNhbGVuZGFycy5pbnN0YW5jZSgpLm5ld0RhdGUoMTk3MCwgMSwgMSkudG9KRCgpXG4gICAgICovXG4gICAgRVBPQ0hKRDogMjQ0MDU4Ny41LFxuXG4gICAgLypcbiAgICAgKiBBcmUgdHdvIHZhbHVlcyBuZWFybHkgZXF1YWw/IENvbXBhcmUgdG8gMVBQTVxuICAgICAqL1xuICAgIEFMTU9TVF9FUVVBTDogMSAtIDFlLTYsXG5cbiAgICAvKlxuICAgICAqIElmIHdlJ3JlIGFza2VkIHRvIGNsaXAgYSBub24tcG9zaXRpdmUgbG9nIHZhbHVlLCBob3cgZmFyIG9mZi1zY3JlZW5cbiAgICAgKiBkbyB3ZSBwdXQgaXQ/XG4gICAgICovXG4gICAgTE9HX0NMSVA6IDEwLFxuXG4gICAgLypcbiAgICAgKiBub3QgYSBudW1iZXIsIGJ1dCBmb3IgZGlzcGxheWluZyBudW1iZXJzOiB0aGUgXCJtaW51cyBzaWduXCIgc3ltYm9sIGlzXG4gICAgICogd2lkZXIgdGhhbiB0aGUgcmVndWxhciBhc2NpaSBkYXNoIFwiLVwiXG4gICAgICovXG4gICAgTUlOVVNfU0lHTjogJ1xcdTIyMTInXG59O1xuXG59LHt9XSw2OTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxuZXhwb3J0cy54bWxucyA9ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3htbG5zLyc7XG5leHBvcnRzLnN2ZyA9ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Zyc7XG5leHBvcnRzLnhsaW5rID0gJ2h0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsnO1xuXG4vLyB0aGUgJ29sZCcgZDMgcXVpcmsgZ290IGZpeCBpbiB2My41Ljdcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tYm9zdG9jay9kMy9jb21taXQvYTZmNjZlOWRkMzdmNzY0NDAzZmM3YzFmMjZiZTA5YWI0YWYyNGZlZFxuZXhwb3J0cy5zdmdBdHRycyA9IHtcbiAgICB4bWxuczogZXhwb3J0cy5zdmcsXG4gICAgJ3htbG5zOnhsaW5rJzogZXhwb3J0cy54bGlua1xufTtcblxufSx7fV0sNjk3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gcGFja2FnZSB2ZXJzaW9uIGluamVjdGVkIGJ5IGBucG0gcnVuIHByZXByb2Nlc3NgXG5leHBvcnRzLnZlcnNpb24gPSAnMS40OS4xJztcblxuLy8gaW5qZWN0IHByb21pc2UgcG9seWZpbGxcbl9kZXJlcV8oJ2VzNi1wcm9taXNlJykucG9seWZpbGwoKTtcblxuLy8gaW5qZWN0IHBsb3QgY3NzXG5fZGVyZXFfKCcuLi9idWlsZC9wbG90Y3NzJyk7XG5cbi8vIGluamVjdCBkZWZhdWx0IE1hdGhKYXggY29uZmlnXG5fZGVyZXFfKCcuL2ZvbnRzL21hdGhqYXhfY29uZmlnJykoKTtcblxuLy8gaW5jbHVkZSByZWdpc3RyeSBtb2R1bGUgYW5kIGV4cG9zZSByZWdpc3RlciBtZXRob2RcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4vcmVnaXN0cnknKTtcbnZhciByZWdpc3RlciA9IGV4cG9ydHMucmVnaXN0ZXIgPSBSZWdpc3RyeS5yZWdpc3RlcjtcblxuLy8gZXhwb3NlIHBsb3QgYXBpIG1ldGhvZHNcbnZhciBwbG90QXBpID0gX2RlcmVxXygnLi9wbG90X2FwaScpO1xudmFyIG1ldGhvZE5hbWVzID0gT2JqZWN0LmtleXMocGxvdEFwaSk7XG5mb3IodmFyIGkgPSAwOyBpIDwgbWV0aG9kTmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgbmFtZSA9IG1ldGhvZE5hbWVzW2ldO1xuICAgIC8vIF8gLT4gcHJpdmF0ZSBBUEkgbWV0aG9kcywgYnV0IHN0aWxsIHJlZ2lzdGVyZWQgZm9yIGludGVybmFsIHVzZVxuICAgIGlmKG5hbWUuY2hhckF0KDApICE9PSAnXycpIGV4cG9ydHNbbmFtZV0gPSBwbG90QXBpW25hbWVdO1xuICAgIHJlZ2lzdGVyKHtcbiAgICAgICAgbW9kdWxlVHlwZTogJ2FwaU1ldGhvZCcsXG4gICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgIGZuOiBwbG90QXBpW25hbWVdXG4gICAgfSk7XG59XG5cbi8vIHNjYXR0ZXIgaXMgdGhlIG9ubHkgdHJhY2UgaW5jbHVkZWQgYnkgZGVmYXVsdFxucmVnaXN0ZXIoX2RlcmVxXygnLi90cmFjZXMvc2NhdHRlcicpKTtcblxuLy8gcmVnaXN0ZXIgYWxsIHJlZ2lzdHJhYmxlIGNvbXBvbmVudHMgbW9kdWxlc1xucmVnaXN0ZXIoW1xuICAgIF9kZXJlcV8oJy4vY29tcG9uZW50cy9meCcpLFxuICAgIF9kZXJlcV8oJy4vY29tcG9uZW50cy9sZWdlbmQnKSxcbiAgICBfZGVyZXFfKCcuL2NvbXBvbmVudHMvYW5ub3RhdGlvbnMnKSxcbiAgICBfZGVyZXFfKCcuL2NvbXBvbmVudHMvYW5ub3RhdGlvbnMzZCcpLFxuICAgIF9kZXJlcV8oJy4vY29tcG9uZW50cy9zaGFwZXMnKSxcbiAgICBfZGVyZXFfKCcuL2NvbXBvbmVudHMvaW1hZ2VzJyksXG4gICAgX2RlcmVxXygnLi9jb21wb25lbnRzL3VwZGF0ZW1lbnVzJyksXG4gICAgX2RlcmVxXygnLi9jb21wb25lbnRzL3NsaWRlcnMnKSxcbiAgICBfZGVyZXFfKCcuL2NvbXBvbmVudHMvcmFuZ2VzbGlkZXInKSxcbiAgICBfZGVyZXFfKCcuL2NvbXBvbmVudHMvcmFuZ2VzZWxlY3RvcicpLFxuICAgIF9kZXJlcV8oJy4vY29tcG9uZW50cy9ncmlkJyksXG4gICAgX2RlcmVxXygnLi9jb21wb25lbnRzL2Vycm9yYmFycycpLFxuICAgIF9kZXJlcV8oJy4vY29tcG9uZW50cy9jb2xvcnNjYWxlJyksXG4gICAgX2RlcmVxXygnLi9jb21wb25lbnRzL2NvbG9yYmFyJylcbl0pO1xuXG4vLyBsb2NhbGVzIGVuIGFuZCBlbi1VUyBhcmUgcmVxdWlyZWQgZm9yIGRlZmF1bHQgYmVoYXZpb3JcbnJlZ2lzdGVyKFtcbiAgICBfZGVyZXFfKCcuL2xvY2FsZS1lbicpLFxuICAgIF9kZXJlcV8oJy4vbG9jYWxlLWVuLXVzJylcbl0pO1xuXG4vLyBwbG90IGljb25zXG5leHBvcnRzLkljb25zID0gX2RlcmVxXygnLi9mb250cy9wbG90aWNvbicpO1xuXG4vLyB1bm9mZmljaWFsICdiZXRhJyBwbG90IG1ldGhvZHMsIHVzZSBhdCB5b3VyIG93biByaXNrXG5leHBvcnRzLlBsb3RzID0gX2RlcmVxXygnLi9wbG90cy9wbG90cycpO1xuZXhwb3J0cy5GeCA9IF9kZXJlcV8oJy4vY29tcG9uZW50cy9meCcpO1xuZXhwb3J0cy5TbmFwc2hvdCA9IF9kZXJlcV8oJy4vc25hcHNob3QnKTtcbmV4cG9ydHMuUGxvdFNjaGVtYSA9IF9kZXJlcV8oJy4vcGxvdF9hcGkvcGxvdF9zY2hlbWEnKTtcbmV4cG9ydHMuUXVldWUgPSBfZGVyZXFfKCcuL2xpYi9xdWV1ZScpO1xuXG4vLyBleHBvcnQgZDMgdXNlZCBpbiB0aGUgYnVuZGxlXG5leHBvcnRzLmQzID0gX2RlcmVxXygnZDMnKTtcblxufSx7XCIuLi9idWlsZC9wbG90Y3NzXCI6MSxcIi4vY29tcG9uZW50cy9hbm5vdGF0aW9uc1wiOjU4NCxcIi4vY29tcG9uZW50cy9hbm5vdGF0aW9uczNkXCI6NTg5LFwiLi9jb21wb25lbnRzL2NvbG9yYmFyXCI6NTk5LFwiLi9jb21wb25lbnRzL2NvbG9yc2NhbGVcIjo2MDUsXCIuL2NvbXBvbmVudHMvZXJyb3JiYXJzXCI6NjIwLFwiLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi9jb21wb25lbnRzL2dyaWRcIjo2MzYsXCIuL2NvbXBvbmVudHMvaW1hZ2VzXCI6NjQxLFwiLi9jb21wb25lbnRzL2xlZ2VuZFwiOjY0OSxcIi4vY29tcG9uZW50cy9yYW5nZXNlbGVjdG9yXCI6NjYwLFwiLi9jb21wb25lbnRzL3Jhbmdlc2xpZGVyXCI6NjY3LFwiLi9jb21wb25lbnRzL3NoYXBlc1wiOjY3NSxcIi4vY29tcG9uZW50cy9zbGlkZXJzXCI6NjgwLFwiLi9jb21wb25lbnRzL3VwZGF0ZW1lbnVzXCI6Njg2LFwiLi9mb250cy9tYXRoamF4X2NvbmZpZ1wiOjY5OCxcIi4vZm9udHMvcGxvdGljb25cIjo2OTksXCIuL2xpYi9xdWV1ZVwiOjczNCxcIi4vbG9jYWxlLWVuXCI6NzQ4LFwiLi9sb2NhbGUtZW4tdXNcIjo3NDcsXCIuL3Bsb3RfYXBpXCI6NzUyLFwiLi9wbG90X2FwaS9wbG90X3NjaGVtYVwiOjc1NixcIi4vcGxvdHMvcGxvdHNcIjo4MjgsXCIuL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9zbmFwc2hvdFwiOjg1MixcIi4vdHJhY2VzL3NjYXR0ZXJcIjoxMTIzLFwiZDNcIjoxNjMsXCJlczYtcHJvbWlzZVwiOjIxOH1dLDY5ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qIGdsb2JhbCBNYXRoSmF4OmZhbHNlICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oKSB7XG4gICAgaWYodHlwZW9mIE1hdGhKYXggIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHZhciBnbG9iYWxDb25maWcgPSAod2luZG93LlBsb3RseUNvbmZpZyB8fCB7fSkuTWF0aEpheENvbmZpZyAhPT0gJ2xvY2FsJztcblxuICAgICAgICBpZihnbG9iYWxDb25maWcpIHtcbiAgICAgICAgICAgIE1hdGhKYXguSHViLkNvbmZpZyh7XG4gICAgICAgICAgICAgICAgbWVzc2FnZVN0eWxlOiAnbm9uZScsXG4gICAgICAgICAgICAgICAgc2tpcFN0YXJ0dXBUeXBlc2V0OiB0cnVlLFxuICAgICAgICAgICAgICAgIGRpc3BsYXlBbGlnbjogJ2xlZnQnLFxuICAgICAgICAgICAgICAgIHRleDJqYXg6IHtcbiAgICAgICAgICAgICAgICAgICAgaW5saW5lTWF0aDogW1snJCcsICckJ10sIFsnXFxcXCgnLCAnXFxcXCknXV1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIE1hdGhKYXguSHViLkNvbmZpZ3VyZWQoKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se31dLDY5OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgICd1bmRvJzoge1xuICAgICAgICAnd2lkdGgnOiA4NTcuMSxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ204NTcgMzUwcTAtODctMzQtMTY2dC05MS0xMzctMTM3LTkyLTE2Ni0zNHEtOTYgMC0xODMgNDF0LTE0NyAxMTRxLTQgNi00IDEzdDUgMTFsNzYgNzdxNiA1IDE0IDUgOS0xIDEzLTcgNDEtNTMgMTAwLTgydDEyNi0yOXE1OCAwIDExMCAyM3Q5MiA2MSA2MSA5MSAyMiAxMTEtMjIgMTExLTYxIDkxLTkyIDYxLTExMCAyM3EtNTUgMC0xMDUtMjB0LTkwLTU3bDc3LTc3cTE3LTE2IDgtMzgtMTAtMjMtMzMtMjNoLTI1MHEtMTUgMC0yNSAxMXQtMTEgMjV2MjUwcTAgMjQgMjIgMzMgMjIgMTAgMzktOGw3Mi03MnE2MCA1NyAxMzcgODh0MTU5IDMxcTg3IDAgMTY2LTM0dDEzNy05MiA5MS0xMzcgMzQtMTY2eicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICdob21lJzoge1xuICAgICAgICAnd2lkdGgnOiA5MjguNixcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ203ODYgMjk2di0yNjdxMC0xNS0xMS0yNnQtMjUtMTBoLTIxNHYyMTRoLTE0M3YtMjE0aC0yMTRxLTE1IDAtMjUgMTB0LTExIDI2djI2N3EwIDEgMCAydDAgMmwzMjEgMjY0IDMyMS0yNjRxMS0xIDEtNHogbTEyNCAzOWwtMzQtNDFxLTUtNS0xMi02aC0ycS03IDAtMTIgM2wtMzg2IDMyMi0zODYtMzIycS03LTQtMTMtNC03IDItMTIgN2wtMzUgNDFxLTQgNS0zIDEzdDYgMTJsNDAxIDMzNHExOCAxNSA0MiAxNXQ0My0xNWwxMzYtMTE0djEwOXEwIDggNSAxM3QxMyA1aDEwN3E4IDAgMTMtNXQ1LTEzdi0yMjdsMTIyLTEwMnE1LTUgNi0xMnQtNC0xM3onLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAnY2FtZXJhLXJldHJvJzoge1xuICAgICAgICAnd2lkdGgnOiAxMDAwLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTUxOCAzODZxMCA4LTUgMTN0LTEzIDVxLTM3IDAtNjMtMjd0LTI2LTYzcTAtOCA1LTEzdDEzLTUgMTIgNSA1IDEzcTAgMjMgMTYgMzh0MzggMTZxOCAwIDEzIDV0NSAxM3ogbTEyNS03M3EwLTU5LTQyLTEwMXQtMTAxLTQyLTEwMSA0Mi00MiAxMDEgNDIgMTAxIDEwMSA0MiAxMDEtNDIgNDItMTAxeiBtLTU3Mi0zMjBoODU4djcxaC04NTh2LTcxeiBtNjQzIDMyMHEwIDg5LTYyIDE1MnQtMTUyIDYyLTE1MS02Mi02My0xNTIgNjMtMTUxIDE1MS02MyAxNTIgNjMgNjIgMTUxeiBtLTU3MSAzNThoMjE0djcyaC0yMTR2LTcyeiBtLTcyLTEwN2g4NTh2MTQzaC00NjJsLTM2LTcxaC0zNjB2LTcyeiBtOTI5IDE0M3YtNzE0cTAtMzAtMjEtNTF0LTUwLTIxaC04NThxLTI5IDAtNTAgMjF0LTIxIDUxdjcxNHEwIDMwIDIxIDUxdDUwIDIxaDg1OHEyOSAwIDUwLTIxdDIxLTUxeicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICd6b29tYm94Jzoge1xuICAgICAgICAnd2lkdGgnOiAxMDAwLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTEwMDAtMjVsLTI1MCAyNTFjNDAgNjMgNjMgMTM4IDYzIDIxOCAwIDIyNC0xODIgNDA2LTQwNyA0MDYtMjI0IDAtNDA2LTE4Mi00MDYtNDA2czE4My00MDYgNDA3LTQwNmM4MCAwIDE1NSAyMiAyMTggNjJsMjUwLTI1MCAxMjUgMTI1eiBtLTgxMiAyNTBsMCA0MzggNDM3IDAgMC00MzgtNDM3IDB6IG02MiAzNzVsMzEzIDAgMC0zMTItMzEzIDAgMCAzMTJ6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ3Bhbic6IHtcbiAgICAgICAgJ3dpZHRoJzogMTAwMCxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ20xMDAwIDM1MGwtMTg3IDE4OCAwLTEyNS0yNTAgMCAwIDI1MCAxMjUgMC0xODggMTg3LTE4Ny0xODcgMTI1IDAgMC0yNTAtMjUwIDAgMCAxMjUtMTg4LTE4OCAxODYtMTg3IDAgMTI1IDI1MiAwIDAtMjUwLTEyNSAwIDE4Ny0xODggMTg4IDE4OC0xMjUgMCAwIDI1MCAyNTAgMCAwLTEyNiAxODcgMTg4eicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICd6b29tX3BsdXMnOiB7XG4gICAgICAgICd3aWR0aCc6IDg3NSxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ20xIDc4N2wwLTg3NSA4NzUgMCAwIDg3NS04NzUgMHogbTY4Ny01MDBsLTE4NyAwIDAtMTg3LTEyNSAwIDAgMTg3LTE4OCAwIDAgMTI1IDE4OCAwIDAgMTg3IDEyNSAwIDAtMTg3IDE4NyAwIDAtMTI1eicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICd6b29tX21pbnVzJzoge1xuICAgICAgICAnd2lkdGgnOiA4NzUsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtMCA3ODhsMC04NzYgODc1IDAgMCA4NzYtODc1IDB6IG02ODgtNTAwbC01MDAgMCAwIDEyNSA1MDAgMCAwLTEyNXonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAnYXV0b3NjYWxlJzoge1xuICAgICAgICAnd2lkdGgnOiAxMDAwLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTI1MCA4NTBsLTE4NyAwLTYzIDAgMC02MiAwLTE4OCA2MyAwIDAgMTg4IDE4NyAwIDAgNjJ6IG02ODggMGwtMTg4IDAgMC02MiAxODggMCAwLTE4OCA2MiAwIDAgMTg4IDAgNjItNjIgMHogbS04NzUtOTM4bDAgMTg4LTYzIDAgMC0xODggMC02MiA2MyAwIDE4NyAwIDAgNjItMTg3IDB6IG04NzUgMTg4bDAtMTg4LTE4OCAwIDAtNjIgMTg4IDAgNjIgMCAwIDYyIDAgMTg4LTYyIDB6IG0tMTI1IDE4OGwtMSAwLTkzLTk0LTE1NiAxNTYgMTU2IDE1NiA5Mi05MyAyIDAgMCAyNTAtMjUwIDAgMC0yIDkzLTkyLTE1Ni0xNTYtMTU2IDE1NiA5NCA5MiAwIDItMjUwIDAgMC0yNTAgMCAwIDkzIDkzIDE1Ny0xNTYtMTU3LTE1Ni05MyA5NCAwIDAgMC0yNTAgMjUwIDAgMCAwLTk0IDkzIDE1NiAxNTcgMTU2LTE1Ny05My05MyAwIDAgMjUwIDAgMCAyNTB6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ3Rvb2x0aXBfYmFzaWMnOiB7XG4gICAgICAgICd3aWR0aCc6IDE1MDAsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtMzc1IDcyNWwwIDAtMzc1LTM3NSAzNzUtMzc0IDAtMSAxMTI1IDAgMCA3NTAtMTEyNSAweicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICd0b29sdGlwX2NvbXBhcmUnOiB7XG4gICAgICAgICd3aWR0aCc6IDExMjUsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtMTg3IDc4NmwwIDItMTg3LTE4OCAxODgtMTg3IDAgMCA5MzcgMCAwIDM3My05MzggMHogbTAtNDk5bDAgMS0xODctMTg4IDE4OC0xODggMCAwIDkzNyAwIDAgMzc2LTkzOC0xeicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICdwbG90bHlsb2dvJzoge1xuICAgICAgICAnd2lkdGgnOiAxNTQyLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTAtMTBoMTgydi0xNDBoLTE4MnYxNDB6IG0yMjggMTQ2aDE4M3YtMjg2aC0xODN2Mjg2eiBtMjI1IDcxNGgxODJ2LTEwMDBoLTE4MnYxMDAweiBtMjI1LTI4NWgxODJ2LTcxNWgtMTgydjcxNXogbTIyNSAxNDJoMTgzdi04NTdoLTE4M3Y4NTd6IG0yMzEtNDI4aDE4MnYtNDI5aC0xODJ2NDI5eiBtMjI1LTI5MWgxODN2LTEzOGgtMTgzdjEzOHonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAnei1heGlzJzoge1xuICAgICAgICAnd2lkdGgnOiAxMDAwLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTgzMyA1bC0xNyAxMDh2NDFsLTEzMC02NSAxMzAtNjZjMCAwIDAgMzggMCAzOSAwLTEgMzYtMTQgMzktMjUgNC0xNS02LTIyLTE2LTMwLTE1LTEyLTM5LTE2LTU2LTIwLTkwLTIyLTE4Ny0yMy0yNzktMjMtMjYxIDAtMzQxIDM0LTM1MyA1OSAzIDYwIDIyOCAxMTAgMjI4IDExMC0xNDAtOC0zNTEtMzUtMzUxLTExNiAwLTEyMCAyOTMtMTQyIDQ3NC0xNDIgMTU1IDAgNDc3IDIyIDQ3NyAxNDIgMCA1MC03NCA3OS0xNjMgOTZ6IG0tMzc0IDk0Yy01OC01LTk5LTIxLTk5LTQwIDAtMjQgNjUtNDMgMTQ0LTQzIDc5IDAgMTQzIDE5IDE0MyA0MyAwIDE5LTQyIDM0LTk4IDQwdjIxNmg4N2wtMTMyIDEzNS0xMzMtMTM1aDg4di0yMTZ6IG0xNjcgNTE1aC0xMzZ2MWMxNiAxNiAzMSAzNCA0NiA1Mmw4NCAxMDl2NTRoLTIzMHYtNzFoMTI0di0xYy0xNi0xNy0yOC0zMi00NC01MWwtODktMTE0di01MWgyNDV2NzJ6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJzNkX3JvdGF0ZSc6IHtcbiAgICAgICAgJ3dpZHRoJzogMTAwMCxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ205MjIgNjYwYy01IDQtOSA3LTE0IDExLTM1OSAyNjMtNTgwLTMxLTU4MC0zMWwtMTAyIDI4IDU4LTQwMGMwIDEgMSAxIDIgMiAxMTggMTA4IDM1MSAyNDkgMzUxIDI0OXMtNjIgMjctMTAwIDQyYzg4IDgzIDIyMiAxODMgMzQ3IDEyMiAxNi04IDMwLTE3IDQ0LTI3LTIgMS00IDItNiA0eiBtMzYtMzI5YzAgMCA2NCAyMjktODggMjk2LTYyIDI3LTEyNCAxNC0xNzUtMTEgMTU3LTc4IDIyNS0yMDggMjQ5LTI2NiA4LTE5IDExLTMxIDExLTMxIDIgNSA2IDE1IDExIDMyLTUtMTMtOC0yMC04LTIweiBtLTc3NS0yMzljNzAtMzEgMTE3LTUwIDE5OC0zMi0xMjEgODAtMTk5IDM0Ni0xOTkgMzQ2bC05Ni0xNS01OC0xMmMwIDAgNTUtMjI2IDE1NS0yODd6IG02MDMgMTMzbC0zMTctMTM5YzAgMCA0LTQgMTktMTQgNy01IDI0LTE1IDI0LTE1cy0xNzctMTQ3LTM4OSA0YzIzNS0yODcgNTM2LTExMiA1MzYtMTEybDMxLTIyIDEwMCAyOTktNC0xeiBtLTI5OC0xNTNjNi00IDE0LTkgMjQtMTUgMCAwLTE3IDEwLTI0IDE1eicsXG4gICAgICAgICd0cmFuc2Zvcm0nOiAnbWF0cml4KDEgMCAwIC0xIDAgODUwKSdcbiAgICB9LFxuICAgICdjYW1lcmEnOiB7XG4gICAgICAgICd3aWR0aCc6IDEwMDAsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtNTAwIDQ1MGMtODMgMC0xNTAtNjctMTUwLTE1MCAwLTgzIDY3LTE1MCAxNTAtMTUwIDgzIDAgMTUwIDY3IDE1MCAxNTAgMCA4My02NyAxNTAtMTUwIDE1MHogbTQwMCAxNTBoLTEyMGMtMTYgMC0zNCAxMy0zOSAyOWwtMzEgOTNjLTYgMTUtMjMgMjgtNDAgMjhoLTM0MGMtMTYgMC0zNC0xMy0zOS0yOGwtMzEtOTRjLTYtMTUtMjMtMjgtNDAtMjhoLTEyMGMtNTUgMC0xMDAtNDUtMTAwLTEwMHYtNDUwYzAtNTUgNDUtMTAwIDEwMC0xMDBoODAwYzU1IDAgMTAwIDQ1IDEwMCAxMDB2NDUwYzAgNTUtNDUgMTAwLTEwMCAxMDB6IG0tNDAwLTU1MGMtMTM4IDAtMjUwIDExMi0yNTAgMjUwIDAgMTM4IDExMiAyNTAgMjUwIDI1MCAxMzggMCAyNTAtMTEyIDI1MC0yNTAgMC0xMzgtMTEyLTI1MC0yNTAtMjUweiBtMzY1IDM4MGMtMTkgMC0zNSAxNi0zNSAzNSAwIDE5IDE2IDM1IDM1IDM1IDE5IDAgMzUtMTYgMzUtMzUgMC0xOS0xNi0zNS0zNS0zNXonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAnbW92aWUnOiB7XG4gICAgICAgICd3aWR0aCc6IDEwMDAsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtOTM4IDQxM2wtMTg4LTEyNWMwIDM3LTE3IDcxLTQ0IDk0IDY0IDM4IDEwNyAxMDcgMTA3IDE4NyAwIDEyMS05OCAyMTktMjE5IDIxOS0xMjEgMC0yMTktOTgtMjE5LTIxOSAwLTYxIDI1LTExNyA2Ni0xNTZoLTExNWMzMCAzMyA0OSA3NiA0OSAxMjUgMCAxMDMtODQgMTg3LTE4NyAxODdzLTE4OC04NC0xODgtMTg3YzAtNTcgMjYtMTA3IDY1LTE0MS0zOC0yMi02NS02Mi02NS0xMDl2LTI1MGMwLTcwIDU2LTEyNiAxMjUtMTI2aDUwMGM2OSAwIDEyNSA1NiAxMjUgMTI2bDE4OC0xMjZjMzQgMCA2MiAyOCA2MiA2M3YzNzVjMCAzNS0yOCA2My02MiA2M3ogbS03NTAgMGMtNjkgMC0xMjUgNTYtMTI1IDEyNXM1NiAxMjUgMTI1IDEyNSAxMjUtNTYgMTI1LTEyNS01Ni0xMjUtMTI1LTEyNXogbTQwNi0xYy04NyAwLTE1NyA3MC0xNTcgMTU3IDAgODYgNzAgMTU2IDE1NyAxNTZzMTU2LTcwIDE1Ni0xNTYtNzAtMTU3LTE1Ni0xNTd6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ3F1ZXN0aW9uJzoge1xuICAgICAgICAnd2lkdGgnOiA4NTcuMSxcbiAgICAgICAgJ2hlaWdodCc6IDEwMDAsXG4gICAgICAgICdwYXRoJzogJ201MDAgODJ2MTA3cTAgOC01IDEzdC0xMyA1aC0xMDdxLTggMC0xMy01dC01LTEzdi0xMDdxMC04IDUtMTN0MTMtNWgxMDdxOCAwIDEzIDV0NSAxM3ogbTE0MyAzNzVxMCA0OS0zMSA5MXQtNzcgNjUtOTUgMjNxLTEzNiAwLTIwNy0xMTktOS0xNCA0LTI0bDc0LTU1cTQtNCAxMC00IDkgMCAxNCA3IDMwIDM4IDQ4IDUxIDE5IDE0IDQ4IDE0IDI3IDAgNDgtMTV0MjEtMzNxMC0yMS0xMS0zNHQtMzgtMjVxLTM1LTE2LTY1LTQ4dC0yOS03MHYtMjBxMC04IDUtMTN0MTMtNWgxMDdxOCAwIDEzIDV0NSAxM3EwIDEwIDEyIDI3dDMwIDI4cTE4IDEwIDI4IDE2dDI1IDE5IDI1IDI3IDE2IDM0IDcgNDV6IG0yMTQtMTA3cTAtMTE3LTU3LTIxNXQtMTU2LTE1Ni0yMTUtNTgtMjE2IDU4LTE1NSAxNTYtNTggMjE1IDU4IDIxNSAxNTUgMTU2IDIxNiA1OCAyMTUtNTggMTU2LTE1NiA1Ny0yMTV6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMSAwIDAgLTEgMCA4NTApJ1xuICAgIH0sXG4gICAgJ2Rpc2snOiB7XG4gICAgICAgICd3aWR0aCc6IDg1Ny4xLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTIxNC03aDQyOXYyMTRoLTQyOXYtMjE0eiBtNTAwIDBoNzJ2NTAwcTAgOC02IDIxdC0xMSAyMGwtMTU3IDE1NnEtNSA2LTE5IDEydC0yMiA1di0yMzJxMC0yMi0xNS0zOHQtMzgtMTZoLTMyMnEtMjIgMC0zNyAxNnQtMTYgMzh2MjMyaC03MnYtNzE0aDcydjIzMnEwIDIyIDE2IDM4dDM3IDE2aDQ2NXEyMiAwIDM4LTE2dDE1LTM4di0yMzJ6IG0tMjE0IDUxOHYxNzhxMCA4LTUgMTN0LTEzIDVoLTEwN3EtNyAwLTEzLTV0LTUtMTN2LTE3OHEwLTggNS0xM3QxMy01aDEwN3E3IDAgMTMgNXQ1IDEzeiBtMzU3LTE4di01MThxMC0yMi0xNS0zOHQtMzgtMTZoLTc1MHEtMjMgMC0zOCAxNnQtMTYgMzh2NzUwcTAgMjIgMTYgMzh0MzggMTZoNTE3cTIzIDAgNTAtMTJ0NDItMjZsMTU2LTE1N3ExNi0xNSAyNy00MnQxMS00OXonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAnbGFzc28nOiB7XG4gICAgICAgICd3aWR0aCc6IDEwMzEsXG4gICAgICAgICdoZWlnaHQnOiAxMDAwLFxuICAgICAgICAncGF0aCc6ICdtMTAxOCA1MzhjLTM2IDIwNy0yOTAgMzM2LTU2OCAyODYtMjc3LTQ4LTQ3My0yNTYtNDM2LTQ2MyAxMC01NyAzNi0xMDggNzYtMTUxLTEzLTY2IDExLTEzNyA2OC0xODMgMzQtMjggNzUtNDEgMTE0LTQybC01NS03MCAwIDBjLTItMS0zLTItNC0zLTEwLTE0LTgtMzQgNS00NSAxNC0xMSAzNC04IDQ1IDQgMSAxIDIgMyAyIDVsMCAwIDExMyAxNDBjMTYgMTEgMzEgMjQgNDUgNDAgNCAzIDYgNyA4IDExIDQ4LTMgMTAwIDAgMTUxIDkgMjc4IDQ4IDQ3MyAyNTUgNDM2IDQ2MnogbS02MjQtMzc5Yy04MCAxNC0xNDkgNDgtMTk3IDk2IDQyIDQyIDEwOSA0NyAxNTYgOSAzMy0yNiA0Ny02NiA0MS0xMDV6IG0tMTg3LTc0Yy0xOSAxNi0zMyAzNy0zOSA2MCA1MC0zMiAxMDktNTUgMTc0LTY4LTQyLTI1LTk1LTI0LTEzNSA4eiBtMzYwIDc1Yy0zNC03LTY5LTktMTAyLTggOCA2Mi0xNiAxMjgtNjggMTcwLTczIDU5LTE3NSA1NC0yNDQtNS05IDIwLTE2IDQwLTIwIDYxLTI4IDE1OSAxMjEgMzE3IDMzMyAzNTRzNDA3LTYwIDQzNC0yMTdjMjgtMTU5LTEyMS0zMTgtMzMzLTM1NXonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAnc2VsZWN0Ym94Jzoge1xuICAgICAgICAnd2lkdGgnOiAxMDAwLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnbTAgODUwbDAtMTQzIDE0MyAwIDAgMTQzLTE0MyAweiBtMjg2IDBsMC0xNDMgMTQzIDAgMCAxNDMtMTQzIDB6IG0yODUgMGwwLTE0MyAxNDMgMCAwIDE0My0xNDMgMHogbTI4NiAwbDAtMTQzIDE0MyAwIDAgMTQzLTE0MyAweiBtLTg1Ny0yODZsMC0xNDMgMTQzIDAgMCAxNDMtMTQzIDB6IG04NTcgMGwwLTE0MyAxNDMgMCAwIDE0My0xNDMgMHogbS04NTctMjg1bDAtMTQzIDE0MyAwIDAgMTQzLTE0MyAweiBtODU3IDBsMC0xNDMgMTQzIDAgMCAxNDMtMTQzIDB6IG0tODU3LTI4NmwwLTE0MyAxNDMgMCAwIDE0My0xNDMgMHogbTI4NiAwbDAtMTQzIDE0MyAwIDAgMTQzLTE0MyAweiBtMjg1IDBsMC0xNDMgMTQzIDAgMCAxNDMtMTQzIDB6IG0yODYgMGwwLTE0MyAxNDMgMCAwIDE0My0xNDMgMHonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAtMSAwIDg1MCknXG4gICAgfSxcbiAgICAnc3Bpa2VsaW5lJzoge1xuICAgICAgICAnd2lkdGgnOiAxMDAwLFxuICAgICAgICAnaGVpZ2h0JzogMTAwMCxcbiAgICAgICAgJ3BhdGgnOiAnTTUxMiA0MDljMC01Ny00Ni0xMDQtMTAzLTEwNC01NyAwLTEwNCA0Ny0xMDQgMTA0IDAgNTcgNDcgMTAzIDEwNCAxMDMgNTcgMCAxMDMtNDYgMTAzLTEwM3ogbS0zMjctMzlsOTIgMCAwIDkyLTkyIDB6IG0tMTg1IDBsOTIgMCAwIDkyLTkyIDB6IG0zNzAtMTg2bDkyIDAgMCA5My05MiAweiBtMC0xODRsOTIgMCAwIDkyLTkyIDB6JyxcbiAgICAgICAgJ3RyYW5zZm9ybSc6ICdtYXRyaXgoMS41IDAgMCAtMS41IDAgODUwKSdcbiAgICB9LFxuICAgICdwZW5jaWwnOiB7XG4gICAgICAgICd3aWR0aCc6IDE3OTIsXG4gICAgICAgICdoZWlnaHQnOiAxNzkyLFxuICAgICAgICAncGF0aCc6ICdNNDkxIDE1MzZsOTEtOTEtMjM1LTIzNS05MSA5MXYxMDdoMTI4djEyOGgxMDd6bTUyMy05MjhxMC0yMi0yMi0yMi0xMCAwLTE3IDdsLTU0MiA1NDJxLTcgNy03IDE3IDAgMjIgMjIgMjIgMTAgMCAxNy03bDU0Mi01NDJxNy03IDctMTd6bS01NC0xOTJsNDE2IDQxNi04MzIgODMyaC00MTZ2LTQxNnptNjgzIDk2cTAgNTMtMzcgOTBsLTE2NiAxNjYtNDE2LTQxNiAxNjYtMTY1cTM2LTM4IDkwLTM4IDUzIDAgOTEgMzhsMjM1IDIzNHEzNyAzOSAzNyA5MXonLFxuICAgICAgICAndHJhbnNmb3JtJzogJ21hdHJpeCgxIDAgMCAxIDAgMSknXG4gICAgfSxcbiAgICAnbmV3cGxvdGx5bG9nbyc6IHtcbiAgICAgICAgJ25hbWUnOiAnbmV3cGxvdGx5bG9nbycsXG4gICAgICAgICdzdmcnOiAnPHN2ZyB4bWxucz1cXCdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1xcJyB2aWV3Qm94PVxcJzAgMCAxMzIgMTMyXFwnPjxkZWZzPjxzdHlsZT4uY2xzLTEge2ZpbGw6ICMxMTlkZmY7fSAuY2xzLTIge2ZpbGw6ICMyNWZlZmQ7fSAuY2xzLTMge2ZpbGw6ICNmZmY7fTwvc3R5bGU+PC9kZWZzPjx0aXRsZT5wbG90bHktbG9nb21hcms8L3RpdGxlPjxnIGlkPVxcJ3N5bWJvbFxcJz48cmVjdCBjbGFzcz1cXCdjbHMtMVxcJyB3aWR0aD1cXCcxMzJcXCcgaGVpZ2h0PVxcJzEzMlxcJyByeD1cXCc2XFwnIHJ5PVxcJzZcXCcvPjxjaXJjbGUgY2xhc3M9XFwnY2xzLTJcXCcgY3g9XFwnNzhcXCcgY3k9XFwnNTRcXCcgcj1cXCc2XFwnLz48Y2lyY2xlIGNsYXNzPVxcJ2Nscy0yXFwnIGN4PVxcJzEwMlxcJyBjeT1cXCczMFxcJyByPVxcJzZcXCcvPjxjaXJjbGUgY2xhc3M9XFwnY2xzLTJcXCcgY3g9XFwnNzhcXCcgY3k9XFwnMzBcXCcgcj1cXCc2XFwnLz48Y2lyY2xlIGNsYXNzPVxcJ2Nscy0yXFwnIGN4PVxcJzU0XFwnIGN5PVxcJzMwXFwnIHI9XFwnNlxcJy8+PGNpcmNsZSBjbGFzcz1cXCdjbHMtMlxcJyBjeD1cXCczMFxcJyBjeT1cXCczMFxcJyByPVxcJzZcXCcvPjxjaXJjbGUgY2xhc3M9XFwnY2xzLTJcXCcgY3g9XFwnMzBcXCcgY3k9XFwnNTRcXCcgcj1cXCc2XFwnLz48cGF0aCBjbGFzcz1cXCdjbHMtM1xcJyBkPVxcJ00zMCw3MmE2LDYsMCwwLDAtNiw2djI0YTYsNiwwLDAsMCwxMiwwVjc4QTYsNiwwLDAsMCwzMCw3MlpcXCcvPjxwYXRoIGNsYXNzPVxcJ2Nscy0zXFwnIGQ9XFwnTTc4LDcyYTYsNiwwLDAsMC02LDZ2MjRhNiw2LDAsMCwwLDEyLDBWNzhBNiw2LDAsMCwwLDc4LDcyWlxcJy8+PHBhdGggY2xhc3M9XFwnY2xzLTNcXCcgZD1cXCdNNTQsNDhhNiw2LDAsMCwwLTYsNnY0OGE2LDYsMCwwLDAsMTIsMFY1NEE2LDYsMCwwLDAsNTQsNDhaXFwnLz48cGF0aCBjbGFzcz1cXCdjbHMtM1xcJyBkPVxcJ00xMDIsNDhhNiw2LDAsMCwwLTYsNnY0OGE2LDYsMCwwLDAsMTIsMFY1NEE2LDYsMCwwLDAsMTAyLDQ4WlxcJy8+PC9nPjwvc3ZnPidcbiAgICB9XG59O1xuXG59LHt9XSw3MDA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxuLyoqXG4gKiBEZXRlcm1pbmUgdGhlIHBvc2l0aW9uIGFuY2hvciBwcm9wZXJ0eSBvZiB4L3kgeGFuY2hvci95YW5jaG9yIGNvbXBvbmVudHMuXG4gKlxuICogLSB2YWx1ZXMgPCAxLzMgYWxpZ24gdGhlIGxvdyBzaWRlIGF0IHRoYXQgZnJhY3Rpb24sXG4gKiAtIHZhbHVlcyBbMS8zLCAyLzNdIGFsaWduIHRoZSBjZW50ZXIgYXQgdGhhdCBmcmFjdGlvbixcbiAqIC0gdmFsdWVzID4gMi8zIGFsaWduIHRoZSByaWdodCBhdCB0aGF0IGZyYWN0aW9uLlxuICovXG5cblxuZXhwb3J0cy5pc0xlZnRBbmNob3IgPSBmdW5jdGlvbiBpc0xlZnRBbmNob3Iob3B0cykge1xuICAgIHJldHVybiAoXG4gICAgICBvcHRzLnhhbmNob3IgPT09ICdsZWZ0JyB8fFxuICAgICAgKG9wdHMueGFuY2hvciA9PT0gJ2F1dG8nICYmIG9wdHMueCA8PSAxIC8gMylcbiAgICApO1xufTtcblxuZXhwb3J0cy5pc0NlbnRlckFuY2hvciA9IGZ1bmN0aW9uIGlzQ2VudGVyQW5jaG9yKG9wdHMpIHtcbiAgICByZXR1cm4gKFxuICAgICAgICBvcHRzLnhhbmNob3IgPT09ICdjZW50ZXInIHx8XG4gICAgICAgIChvcHRzLnhhbmNob3IgPT09ICdhdXRvJyAmJiBvcHRzLnggPiAxIC8gMyAmJiBvcHRzLnggPCAyIC8gMylcbiAgICApO1xufTtcblxuZXhwb3J0cy5pc1JpZ2h0QW5jaG9yID0gZnVuY3Rpb24gaXNSaWdodEFuY2hvcihvcHRzKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIG9wdHMueGFuY2hvciA9PT0gJ3JpZ2h0JyB8fFxuICAgICAgKG9wdHMueGFuY2hvciA9PT0gJ2F1dG8nICYmIG9wdHMueCA+PSAyIC8gMylcbiAgICApO1xufTtcblxuZXhwb3J0cy5pc1RvcEFuY2hvciA9IGZ1bmN0aW9uIGlzVG9wQW5jaG9yKG9wdHMpIHtcbiAgICByZXR1cm4gKFxuICAgICAgICBvcHRzLnlhbmNob3IgPT09ICd0b3AnIHx8XG4gICAgICAgIChvcHRzLnlhbmNob3IgPT09ICdhdXRvJyAmJiBvcHRzLnkgPj0gMiAvIDMpXG4gICAgKTtcbn07XG5cbmV4cG9ydHMuaXNNaWRkbGVBbmNob3IgPSBmdW5jdGlvbiBpc01pZGRsZUFuY2hvcihvcHRzKSB7XG4gICAgcmV0dXJuIChcbiAgICAgICAgb3B0cy55YW5jaG9yID09PSAnbWlkZGxlJyB8fFxuICAgICAgICAob3B0cy55YW5jaG9yID09PSAnYXV0bycgJiYgb3B0cy55ID4gMSAvIDMgJiYgb3B0cy55IDwgMiAvIDMpXG4gICAgKTtcbn07XG5cbmV4cG9ydHMuaXNCb3R0b21BbmNob3IgPSBmdW5jdGlvbiBpc0JvdHRvbUFuY2hvcihvcHRzKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIG9wdHMueWFuY2hvciA9PT0gJ2JvdHRvbScgfHxcbiAgICAgIChvcHRzLnlhbmNob3IgPT09ICdhdXRvJyAmJiBvcHRzLnkgPD0gMSAvIDMpXG4gICAgKTtcbn07XG5cbn0se31dLDcwMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBtb2RNb2R1bGUgPSBfZGVyZXFfKCcuL21vZCcpO1xudmFyIG1vZCA9IG1vZE1vZHVsZS5tb2Q7XG52YXIgbW9kSGFsZiA9IG1vZE1vZHVsZS5tb2RIYWxmO1xuXG52YXIgUEkgPSBNYXRoLlBJO1xudmFyIHR3b1BJID0gMiAqIFBJO1xuXG5mdW5jdGlvbiBkZWcycmFkKGRlZykgeyByZXR1cm4gZGVnIC8gMTgwICogUEk7IH1cblxuZnVuY3Rpb24gcmFkMmRlZyhyYWQpIHsgcmV0dXJuIHJhZCAvIFBJICogMTgwOyB9XG5cbi8qKlxuICogaXMgc2VjdG9yIGEgZnVsbCBjaXJjbGU/XG4gKiAuLi4gdGhpcyBjb21lcyB1cCBhIGxvdCBpbiBTVkcgcGF0aC1kcmF3aW5nIHJvdXRpbmVzXG4gKlxuICogTi5CLiB3ZSBjb25zaWRlciBhbGwgc2VjdG9ycyB0aGF0IHNwYW4gbW9yZSB0aGF0IDJwaSAnZnVsbCcgY2lyY2xlc1xuICpcbiAqIEBwYXJhbSB7Mi1pdGVtIGFycmF5fSBhQm5kcyA6IGFuZ3VsYXIgYm91bmRzIGluICpyYWRpYW5zKlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNGdWxsQ2lyY2xlKGFCbmRzKSB7XG4gICAgcmV0dXJuIE1hdGguYWJzKGFCbmRzWzFdIC0gYUJuZHNbMF0pID4gdHdvUEkgLSAxZS0xNDtcbn1cblxuLyoqXG4gKiBhbmd1bGFyIGRlbHRhIGJldHdlZW4gYW5nbGUgJ2EnIGFuZCAnYidcbiAqIHNvbHV0aW9uIHRha2VuIGZyb206IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMDA3Mjc5XG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGEgOiBmaXJzdCBhbmdsZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIDogc2Vjb25kIGFuZ2xlIGluICpyYWRpYW5zKlxuICogQHJldHVybiB7bnVtYmVyfSBhbmd1bGFyIGRlbHRhIGluICpyYWRpYW5zKlxuICovXG5mdW5jdGlvbiBhbmdsZURlbHRhKGEsIGIpIHtcbiAgICByZXR1cm4gbW9kSGFsZihiIC0gYSwgdHdvUEkpO1xufVxuXG4vKipcbiAqIGFuZ3VsYXIgZGlzdGFuY2UgYmV0d2VlbiBhbmdsZSAnYScgYW5kICdiJ1xuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIDogZmlyc3QgYW5nbGUgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge251bWJlcn0gYiA6IHNlY29uZCBhbmdsZSBpbiAqcmFkaWFucypcbiAqIEByZXR1cm4ge251bWJlcn0gYW5ndWxhciBkaXN0YW5jZSBpbiAqcmFkaWFucypcbiAqL1xuZnVuY3Rpb24gYW5nbGVEaXN0KGEsIGIpIHtcbiAgICByZXR1cm4gTWF0aC5hYnMoYW5nbGVEZWx0YShhLCBiKSk7XG59XG5cbi8qKlxuICogaXMgYW5nbGUgaW5zaWRlIHNlY3Rvcj9cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gYSA6IGFuZ2xlIHRvIHRlc3QgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0gezItaXRlbSBhcnJheX0gYUJuZHMgOiBzZWN0b3IncyBhbmd1bGFyIGJvdW5kcyBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNBbmdsZUluc2lkZVNlY3RvcihhLCBhQm5kcykge1xuICAgIGlmKGlzRnVsbENpcmNsZShhQm5kcykpIHJldHVybiB0cnVlO1xuXG4gICAgdmFyIHMwLCBzMTtcblxuICAgIGlmKGFCbmRzWzBdIDwgYUJuZHNbMV0pIHtcbiAgICAgICAgczAgPSBhQm5kc1swXTtcbiAgICAgICAgczEgPSBhQm5kc1sxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzMCA9IGFCbmRzWzFdO1xuICAgICAgICBzMSA9IGFCbmRzWzBdO1xuICAgIH1cblxuICAgIHMwID0gbW9kKHMwLCB0d29QSSk7XG4gICAgczEgPSBtb2QoczEsIHR3b1BJKTtcbiAgICBpZihzMCA+IHMxKSBzMSArPSB0d29QSTtcblxuICAgIHZhciBhMCA9IG1vZChhLCB0d29QSSk7XG4gICAgdmFyIGExID0gYTAgKyB0d29QSTtcblxuICAgIHJldHVybiAoYTAgPj0gczAgJiYgYTAgPD0gczEpIHx8IChhMSA+PSBzMCAmJiBhMSA8PSBzMSk7XG59XG5cbi8qKlxuICogaXMgcHQgKHIsYSkgaW5zaWRlIHNlY3Rvcj9cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gciA6IHB0J3MgcmFkaWFsIGNvb3JkaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIDogcHQncyBhbmd1bGFyIGNvb3JkaW5hdGUgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0gezItaXRlbSBhcnJheX0gckJuZHMgOiBzZWN0b3IncyByYWRpYWwgYm91bmRzXG4gKiBAcGFyYW0gezItaXRlbSBhcnJheX0gYUJuZHMgOiBzZWN0b3IncyBhbmd1bGFyIGJvdW5kcyBpbiAqcmFkaWFucypcbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzUHRJbnNpZGVTZWN0b3IociwgYSwgckJuZHMsIGFCbmRzKSB7XG4gICAgaWYoIWlzQW5nbGVJbnNpZGVTZWN0b3IoYSwgYUJuZHMpKSByZXR1cm4gZmFsc2U7XG5cbiAgICB2YXIgcjAsIHIxO1xuXG4gICAgaWYockJuZHNbMF0gPCByQm5kc1sxXSkge1xuICAgICAgICByMCA9IHJCbmRzWzBdO1xuICAgICAgICByMSA9IHJCbmRzWzFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHIwID0gckJuZHNbMV07XG4gICAgICAgIHIxID0gckJuZHNbMF07XG4gICAgfVxuXG4gICAgcmV0dXJuIHIgPj0gcjAgJiYgciA8PSByMTtcbn1cblxuLy8gY29tbW9uIHRvIHBhdGhBcmMsIHBhdGhTZWN0b3IgYW5kIHBhdGhBbm51bHVzXG5mdW5jdGlvbiBfcGF0aChyMCwgcjEsIGEwLCBhMSwgY3gsIGN5LCBpc0Nsb3NlZCkge1xuICAgIGN4ID0gY3ggfHwgMDtcbiAgICBjeSA9IGN5IHx8IDA7XG5cbiAgICB2YXIgaXNDaXJjbGUgPSBpc0Z1bGxDaXJjbGUoW2EwLCBhMV0pO1xuICAgIHZhciBhU3RhcnQsIGFNaWQsIGFFbmQ7XG4gICAgdmFyIHJTdGFydCwgckVuZDtcblxuICAgIGlmKGlzQ2lyY2xlKSB7XG4gICAgICAgIGFTdGFydCA9IDA7XG4gICAgICAgIGFNaWQgPSBQSTtcbiAgICAgICAgYUVuZCA9IHR3b1BJO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKGEwIDwgYTEpIHtcbiAgICAgICAgICAgIGFTdGFydCA9IGEwO1xuICAgICAgICAgICAgYUVuZCA9IGExO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYVN0YXJ0ID0gYTE7XG4gICAgICAgICAgICBhRW5kID0gYTA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihyMCA8IHIxKSB7XG4gICAgICAgIHJTdGFydCA9IHIwO1xuICAgICAgICByRW5kID0gcjE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgclN0YXJ0ID0gcjE7XG4gICAgICAgIHJFbmQgPSByMDtcbiAgICB9XG5cbiAgICAvLyBOLkIuIHN2ZyBjb29yZGluYXRlcyBoZXJlLCB3aGVyZSB5IGluY3JlYXNlcyBkb3dud2FyZFxuICAgIGZ1bmN0aW9uIHB0KHIsIGEpIHtcbiAgICAgICAgcmV0dXJuIFtyICogTWF0aC5jb3MoYSkgKyBjeCwgY3kgLSByICogTWF0aC5zaW4oYSldO1xuICAgIH1cblxuICAgIHZhciBsYXJnZUFyYyA9IE1hdGguYWJzKGFFbmQgLSBhU3RhcnQpIDw9IFBJID8gMCA6IDE7XG4gICAgZnVuY3Rpb24gYXJjKHIsIGEsIGN3KSB7XG4gICAgICAgIHJldHVybiAnQScgKyBbciwgcl0gKyAnICcgKyBbMCwgbGFyZ2VBcmMsIGN3XSArICcgJyArIHB0KHIsIGEpO1xuICAgIH1cblxuICAgIHZhciBwO1xuXG4gICAgaWYoaXNDaXJjbGUpIHtcbiAgICAgICAgaWYoclN0YXJ0ID09PSBudWxsKSB7XG4gICAgICAgICAgICBwID0gJ00nICsgcHQockVuZCwgYVN0YXJ0KSArXG4gICAgICAgICAgICAgICAgYXJjKHJFbmQsIGFNaWQsIDApICtcbiAgICAgICAgICAgICAgICBhcmMockVuZCwgYUVuZCwgMCkgKyAnWic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwID0gJ00nICsgcHQoclN0YXJ0LCBhU3RhcnQpICtcbiAgICAgICAgICAgICAgICBhcmMoclN0YXJ0LCBhTWlkLCAwKSArXG4gICAgICAgICAgICAgICAgYXJjKHJTdGFydCwgYUVuZCwgMCkgKyAnWicgK1xuICAgICAgICAgICAgICAgICdNJyArIHB0KHJFbmQsIGFTdGFydCkgK1xuICAgICAgICAgICAgICAgIGFyYyhyRW5kLCBhTWlkLCAxKSArXG4gICAgICAgICAgICAgICAgYXJjKHJFbmQsIGFFbmQsIDEpICsgJ1onO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYoclN0YXJ0ID09PSBudWxsKSB7XG4gICAgICAgICAgICBwID0gJ00nICsgcHQockVuZCwgYVN0YXJ0KSArIGFyYyhyRW5kLCBhRW5kLCAwKTtcbiAgICAgICAgICAgIGlmKGlzQ2xvc2VkKSBwICs9ICdMMCwwWic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwID0gJ00nICsgcHQoclN0YXJ0LCBhU3RhcnQpICtcbiAgICAgICAgICAgICAgICAnTCcgKyBwdChyRW5kLCBhU3RhcnQpICtcbiAgICAgICAgICAgICAgICBhcmMockVuZCwgYUVuZCwgMCkgK1xuICAgICAgICAgICAgICAgICdMJyArIHB0KHJTdGFydCwgYUVuZCkgK1xuICAgICAgICAgICAgICAgIGFyYyhyU3RhcnQsIGFTdGFydCwgMSkgKyAnWic7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcDtcbn1cblxuLyoqXG4gKiBwYXRoIGFuIGFyY1xuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSByIDogcmFkaXVzXG4gKiBAcGFyYW0ge251bWJlcn0gYTAgOiBmaXJzdCBhbmd1bGFyIGNvb3JkaW5hdGUgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge251bWJlcn0gYTEgOiBzZWNvbmQgYW5ndWxhciBjb29yZGluYXRlIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHtudW1iZXIgKG9wdGlvbmFsKX0gY3ggOiB4IGNvb3JkaW5hdGUgb2YgY2VudGVyXG4gKiBAcGFyYW0ge251bWJlciAob3B0aW9uYWwpfSBjeSA6IHkgY29vcmRpbmF0ZSBvZiBjZW50ZXJcbiAqIEByZXR1cm4ge3N0cmluZ30gc3ZnIHBhdGhcbiAqL1xuZnVuY3Rpb24gcGF0aEFyYyhyLCBhMCwgYTEsIGN4LCBjeSkge1xuICAgIHJldHVybiBfcGF0aChudWxsLCByLCBhMCwgYTEsIGN4LCBjeSwgMCk7XG59XG5cbi8qKlxuICogcGF0aCBhIHNlY3RvclxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSByIDogcmFkaXVzXG4gKiBAcGFyYW0ge251bWJlcn0gYTAgOiBmaXJzdCBhbmd1bGFyIGNvb3JkaW5hdGUgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge251bWJlcn0gYTEgOiBzZWNvbmQgYW5ndWxhciBjb29yZGluYXRlIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHtudW1iZXIgKG9wdGlvbmFsKX0gY3ggOiB4IGNvb3JkaW5hdGUgb2YgY2VudGVyXG4gKiBAcGFyYW0ge251bWJlciAob3B0aW9uYWwpfSBjeSA6IHkgY29vcmRpbmF0ZSBvZiBjZW50ZXJcbiAqIEByZXR1cm4ge3N0cmluZ30gc3ZnIHBhdGhcbiAqL1xuZnVuY3Rpb24gcGF0aFNlY3RvcihyLCBhMCwgYTEsIGN4LCBjeSkge1xuICAgIHJldHVybiBfcGF0aChudWxsLCByLCBhMCwgYTEsIGN4LCBjeSwgMSk7XG59XG5cbi8qKlxuICogcGF0aCBhbiBhbm51bHVzXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHIwIDogZmlyc3QgcmFkaWFsIGNvb3JkaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByMSA6IHNlY29uZCByYWRpYWwgY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IGEwIDogZmlyc3QgYW5ndWxhciBjb29yZGluYXRlIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHtudW1iZXJ9IGExIDogc2Vjb25kIGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7bnVtYmVyIChvcHRpb25hbCl9IGN4IDogeCBjb29yZGluYXRlIG9mIGNlbnRlclxuICogQHBhcmFtIHtudW1iZXIgKG9wdGlvbmFsKX0gY3kgOiB5IGNvb3JkaW5hdGUgb2YgY2VudGVyXG4gKiBAcmV0dXJuIHtzdHJpbmd9IHN2ZyBwYXRoXG4gKi9cbmZ1bmN0aW9uIHBhdGhBbm51bHVzKHIwLCByMSwgYTAsIGExLCBjeCwgY3kpIHtcbiAgICByZXR1cm4gX3BhdGgocjAsIHIxLCBhMCwgYTEsIGN4LCBjeSwgMSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGRlZzJyYWQ6IGRlZzJyYWQsXG4gICAgcmFkMmRlZzogcmFkMmRlZyxcbiAgICBhbmdsZURlbHRhOiBhbmdsZURlbHRhLFxuICAgIGFuZ2xlRGlzdDogYW5nbGVEaXN0LFxuICAgIGlzRnVsbENpcmNsZTogaXNGdWxsQ2lyY2xlLFxuICAgIGlzQW5nbGVJbnNpZGVTZWN0b3I6IGlzQW5nbGVJbnNpZGVTZWN0b3IsXG4gICAgaXNQdEluc2lkZVNlY3RvcjogaXNQdEluc2lkZVNlY3RvcixcbiAgICBwYXRoQXJjOiBwYXRoQXJjLFxuICAgIHBhdGhTZWN0b3I6IHBhdGhTZWN0b3IsXG4gICAgcGF0aEFubnVsdXM6IHBhdGhBbm51bHVzXG59O1xuXG59LHtcIi4vbW9kXCI6NzI2fV0sNzAyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuXG4vLyBJRTkgZmFsbGJhY2tzXG5cbnZhciBhYiA9ICh0eXBlb2YgQXJyYXlCdWZmZXIgPT09ICd1bmRlZmluZWQnIHx8ICFBcnJheUJ1ZmZlci5pc1ZpZXcpID9cbiAgICB7aXNWaWV3OiBmdW5jdGlvbigpIHsgcmV0dXJuIGZhbHNlOyB9fSA6XG4gICAgQXJyYXlCdWZmZXI7XG5cbnZhciBkdiA9ICh0eXBlb2YgRGF0YVZpZXcgPT09ICd1bmRlZmluZWQnKSA/XG4gICAgZnVuY3Rpb24oKSB7fSA6XG4gICAgRGF0YVZpZXc7XG5cbmZ1bmN0aW9uIGlzVHlwZWRBcnJheShhKSB7XG4gICAgcmV0dXJuIGFiLmlzVmlldyhhKSAmJiAhKGEgaW5zdGFuY2VvZiBkdik7XG59XG5leHBvcnRzLmlzVHlwZWRBcnJheSA9IGlzVHlwZWRBcnJheTtcblxuZnVuY3Rpb24gaXNBcnJheU9yVHlwZWRBcnJheShhKSB7XG4gICAgcmV0dXJuIGlzQXJyYXkoYSkgfHwgaXNUeXBlZEFycmF5KGEpO1xufVxuZXhwb3J0cy5pc0FycmF5T3JUeXBlZEFycmF5ID0gaXNBcnJheU9yVHlwZWRBcnJheTtcblxuLypcbiAqIFRlc3Qgd2hldGhlciBhbiBpbnB1dCBvYmplY3QgaXMgMUQuXG4gKlxuICogQXNzdW1lcyB3ZSBhbHJlYWR5IGtub3cgdGhlIG9iamVjdCBpcyBhbiBhcnJheS5cbiAqXG4gKiBMb29rcyBvbmx5IGF0IHRoZSBmaXJzdCBlbGVtZW50LCBpZiB0aGUgZGltZW5zaW9uYWxpdHkgaXNcbiAqIG5vdCBjb25zaXN0ZW50IHdlIHdvbid0IGZpZ3VyZSB0aGF0IG91dCBoZXJlLlxuICovXG5mdW5jdGlvbiBpc0FycmF5MUQoYSkge1xuICAgIHJldHVybiAhaXNBcnJheU9yVHlwZWRBcnJheShhWzBdKTtcbn1cbmV4cG9ydHMuaXNBcnJheTFEID0gaXNBcnJheTFEO1xuXG4vKlxuICogRW5zdXJlcyBhbiBhcnJheSBoYXMgdGhlIHJpZ2h0IGFtb3VudCBvZiBzdG9yYWdlIHNwYWNlLiBJZiBpdCBkb2Vzbid0XG4gKiBleGlzdCwgaXQgY3JlYXRlcyBhbiBhcnJheS4gSWYgaXQgZG9lcyBleGlzdCwgaXQgcmV0dXJucyBpdCBpZiB0b29cbiAqIHNob3J0IG9yIHRydW5jYXRlcyBpdCBpbi1wbGFjZS5cbiAqXG4gKiBUaGUgZ29hbCBpcyB0byBqdXN0IHJldXNlIG1lbW9yeSB0byBhdm9pZCBhIGJpdCBvZiBleGNlc3NpdmUgZ2FyYmFnZVxuICogY29sbGVjdGlvbi5cbiAqL1xuZXhwb3J0cy5lbnN1cmVBcnJheSA9IGZ1bmN0aW9uKG91dCwgbikge1xuICAgIC8vIFRPRE86IHR5cGVkIGFycmF5IHN1cHBvcnQgaGVyZT8gVGhpcyBpcyBvbmx5IHVzZWQgaW5cbiAgICAvLyB0cmFjZXMvY2FycGV0L2NvbXB1dGVfY29udHJvbF9wb2ludHNcbiAgICBpZighaXNBcnJheShvdXQpKSBvdXQgPSBbXTtcblxuICAgIC8vIElmIHRvbyBsb25nLCB0cnVuY2F0ZS4gKElmIHRvbyBzaG9ydCwgaXQgd2lsbCBncm93XG4gICAgLy8gYXV0b21hdGljYWxseSBzbyB3ZSBkb24ndCBjYXJlIGFib3V0IHRoYXQgY2FzZSlcbiAgICBvdXQubGVuZ3RoID0gbjtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKlxuICogVHlwZWRBcnJheS1jb21wYXRpYmxlIGNvbmNhdGVuYXRpb24gb2YgbiBhcnJheXNcbiAqIGlmIGFsbCBhcnJheXMgYXJlIHRoZSBzYW1lIHR5cGUgaXQgd2lsbCBwcmVzZXJ2ZSB0aGF0IHR5cGUsXG4gKiBvdGhlcndpc2UgaXQgZmFsbHMgYmFjayBvbiBBcnJheS5cbiAqIEFsc28gdHJpZXMgdG8gYXZvaWQgY29weWluZywgaW4gY2FzZSBvbmUgYXJyYXkgaGFzIHplcm8gbGVuZ3RoXG4gKiBCdXQgbmV2ZXIgbXV0YXRlcyBhbiBleGlzdGluZyBhcnJheVxuICovXG5leHBvcnRzLmNvbmNhdCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBhcmdzID0gW107XG4gICAgdmFyIGFsbEFycmF5ID0gdHJ1ZTtcbiAgICB2YXIgdG90YWxMZW4gPSAwO1xuXG4gICAgdmFyIF9jb25zdHJ1Y3RvciwgYXJnMCwgaSwgYXJnaSwgcG9zaSwgbGVuaSwgb3V0LCBqO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFyZ2kgPSBhcmd1bWVudHNbaV07XG4gICAgICAgIGxlbmkgPSBhcmdpLmxlbmd0aDtcbiAgICAgICAgaWYobGVuaSkge1xuICAgICAgICAgICAgaWYoYXJnMCkgYXJncy5wdXNoKGFyZ2kpO1xuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYXJnMCA9IGFyZ2k7XG4gICAgICAgICAgICAgICAgcG9zaSA9IGxlbmk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGlzQXJyYXkoYXJnaSkpIHtcbiAgICAgICAgICAgICAgICBfY29uc3RydWN0b3IgPSBmYWxzZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYWxsQXJyYXkgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZighdG90YWxMZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgX2NvbnN0cnVjdG9yID0gYXJnaS5jb25zdHJ1Y3RvcjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoX2NvbnN0cnVjdG9yICE9PSBhcmdpLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IGluIHByaW5jaXBsZSB3ZSBjb3VsZCB1cGdyYWRlIGhlcmUsXG4gICAgICAgICAgICAgICAgICAgIC8vIGllIGtlZXAgdHlwZWQgYXJyYXkgYnV0IGNvbnZlcnQgYWxsIHRvIEZsb2F0NjRBcnJheT9cbiAgICAgICAgICAgICAgICAgICAgX2NvbnN0cnVjdG9yID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0b3RhbExlbiArPSBsZW5pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoIXRvdGFsTGVuKSByZXR1cm4gW107XG4gICAgaWYoIWFyZ3MubGVuZ3RoKSByZXR1cm4gYXJnMDtcblxuICAgIGlmKGFsbEFycmF5KSByZXR1cm4gYXJnMC5jb25jYXQuYXBwbHkoYXJnMCwgYXJncyk7XG4gICAgaWYoX2NvbnN0cnVjdG9yKSB7XG4gICAgICAgIC8vIG1hdGNoaW5nIHR5cGVkIGFycmF5c1xuICAgICAgICBvdXQgPSBuZXcgX2NvbnN0cnVjdG9yKHRvdGFsTGVuKTtcbiAgICAgICAgb3V0LnNldChhcmcwKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnaSA9IGFyZ3NbaV07XG4gICAgICAgICAgICBvdXQuc2V0KGFyZ2ksIHBvc2kpO1xuICAgICAgICAgICAgcG9zaSArPSBhcmdpLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIC8vIG1pc21hdGNoZWQgdHlwZXMgb3IgQXJyYXkgKyB0eXBlZFxuICAgIG91dCA9IG5ldyBBcnJheSh0b3RhbExlbik7XG4gICAgZm9yKGogPSAwOyBqIDwgYXJnMC5sZW5ndGg7IGorKykgb3V0W2pdID0gYXJnMFtqXTtcbiAgICBmb3IoaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFyZ2kgPSBhcmdzW2ldO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBhcmdpLmxlbmd0aDsgaisrKSBvdXRbcG9zaSArIGpdID0gYXJnaVtqXTtcbiAgICAgICAgcG9zaSArPSBqO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZXhwb3J0cy5tYXhSb3dMZW5ndGggPSBmdW5jdGlvbih6KSB7XG4gICAgcmV0dXJuIF9yb3dMZW5ndGgoeiwgTWF0aC5tYXgsIDApO1xufTtcblxuZXhwb3J0cy5taW5Sb3dMZW5ndGggPSBmdW5jdGlvbih6KSB7XG4gICAgcmV0dXJuIF9yb3dMZW5ndGgoeiwgTWF0aC5taW4sIEluZmluaXR5KTtcbn07XG5cbmZ1bmN0aW9uIF9yb3dMZW5ndGgoeiwgZm4sIGxlbjApIHtcbiAgICBpZihpc0FycmF5T3JUeXBlZEFycmF5KHopKSB7XG4gICAgICAgIGlmKGlzQXJyYXlPclR5cGVkQXJyYXkoelswXSkpIHtcbiAgICAgICAgICAgIHZhciBsZW4gPSBsZW4wO1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHoubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBsZW4gPSBmbihsZW4sIHpbaV0ubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBsZW47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gei5sZW5ndGg7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIDA7XG59XG5cbn0se31dLDcwMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG4vLyBwcmVjb21waWxlIGZvciBzcGVlZFxudmFyIEpVTksgPSAvXlsnXCIlLCQjXFxzJ10rfFssIF18WydcIiUsJCNcXHMnXSskL2c7XG5cbi8qKlxuICogY2xlYW5OdW1iZXI6IHJlbW92ZSBjb21tb24gbGVhZGluZyBhbmQgdHJhaWxpbmcgY3J1ZnRcbiAqIEFsd2F5cyByZXR1cm5zIGVpdGhlciBhIG51bWJlciBvciBCQUROVU0uXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2xlYW5OdW1iZXIodikge1xuICAgIGlmKHR5cGVvZiB2ID09PSAnc3RyaW5nJykge1xuICAgICAgICB2ID0gdi5yZXBsYWNlKEpVTkssICcnKTtcbiAgICB9XG5cbiAgICBpZihpc051bWVyaWModikpIHJldHVybiBOdW1iZXIodik7XG5cbiAgICByZXR1cm4gQkFETlVNO1xufTtcblxufSx7XCIuLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSw3MDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIENsZWFyIGdsIGZyYW1lIChpZiBhbnkpLiBUaGlzIGlzIGEgY29tbW9uIHBhdHRlcm4gYXNcbiAqIHdlIHVzdWFsbHkgc2V0IGBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHRydWVgIGR1cmluZ1xuICogZ2wgY29udGV4dCBjcmVhdGlvbiAoZS5nLiB2aWEgYHJlZ2xVdGlscy5wcmVwYXJlYCkuXG4gKlxuICogQHBhcmFtIHtET00gbm9kZSBvciBvYmplY3R9IGdkIDogZ3JhcGggZGl2IG9iamVjdFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNsZWFyR2xDYW52YXNlcyhnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBpZihmdWxsTGF5b3V0Ll9nbGNhbnZhcyAmJiBmdWxsTGF5b3V0Ll9nbGNhbnZhcy5zaXplKCkpIHtcbiAgICAgICAgZnVsbExheW91dC5fZ2xjYW52YXMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBpZihkLnJlZ2wpIGQucmVnbC5jbGVhcih7Y29sb3I6IHRydWUsIGRlcHRoOiB0cnVlfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5cbn0se31dLDcwNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQ2xlYXIgcmVzcG9uc2l2ZSBoYW5kbGVycyAoaWYgYW55KS5cbiAqXG4gKiBAcGFyYW0ge0RPTSBub2RlIG9yIG9iamVjdH0gZ2QgOiBncmFwaCBkaXYgb2JqZWN0XG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2xlYXJSZXNwb25zaXZlKGdkKSB7XG4gICAgaWYoZ2QuX3Jlc3BvbnNpdmVDaGFydEhhbmRsZXIpIHtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIGdkLl9yZXNwb25zaXZlQ2hhcnRIYW5kbGVyKTtcbiAgICAgICAgZGVsZXRlIGdkLl9yZXNwb25zaXZlQ2hhcnRIYW5kbGVyO1xuICAgIH1cbn07XG5cbn0se31dLDcwNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIHRpbnljb2xvciA9IF9kZXJlcV8oJ3Rpbnljb2xvcjInKTtcblxudmFyIGJhc2VUcmFjZUF0dHJzID0gX2RlcmVxXygnLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yc2NhbGVzID0gX2RlcmVxXygnLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL3NjYWxlcycpO1xudmFyIERFU0VMRUNURElNID0gX2RlcmVxXygnLi4vY29uc3RhbnRzL2ludGVyYWN0aW9ucycpLkRFU0VMRUNURElNO1xuXG52YXIgbmVzdGVkUHJvcGVydHkgPSBfZGVyZXFfKCcuL25lc3RlZF9wcm9wZXJ0eScpO1xudmFyIGNvdW50ZXJSZWdleCA9IF9kZXJlcV8oJy4vcmVnZXgnKS5jb3VudGVyO1xudmFyIG1vZEhhbGYgPSBfZGVyZXFfKCcuL21vZCcpLm1vZEhhbGY7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IF9kZXJlcV8oJy4vYXJyYXknKS5pc0FycmF5T3JUeXBlZEFycmF5O1xuXG5leHBvcnRzLnZhbE9iamVjdE1ldGEgPSB7XG4gICAgZGF0YV9hcnJheToge1xuICAgICAgICAvLyBZb3UgY2FuIHVzZSAqZGZsdD1bXSB0byBmb3JjZSBzYWlkIGFycmF5IHRvIGV4aXN0IHRob3VnaC5cbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgY29lcmNlRnVuY3Rpb246IGZ1bmN0aW9uKHYsIHByb3BPdXQsIGRmbHQpIHtcbiAgICAgICAgICAgIC8vIFRPRE8gbWF5YmUgYHY6IHt0eXBlOiAnZmxvYXQzMicsIHZhbHM6IFsvKiAuLi4gKi9dfWAgYWxzb1xuICAgICAgICAgICAgaWYoaXNBcnJheU9yVHlwZWRBcnJheSh2KSkgcHJvcE91dC5zZXQodik7XG4gICAgICAgICAgICBlbHNlIGlmKGRmbHQgIT09IHVuZGVmaW5lZCkgcHJvcE91dC5zZXQoZGZsdCk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGVudW1lcmF0ZWQ6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgY29lcmNlRnVuY3Rpb246IGZ1bmN0aW9uKHYsIHByb3BPdXQsIGRmbHQsIG9wdHMpIHtcbiAgICAgICAgICAgIGlmKG9wdHMuY29lcmNlTnVtYmVyKSB2ID0gK3Y7XG4gICAgICAgICAgICBpZihvcHRzLnZhbHVlcy5pbmRleE9mKHYpID09PSAtMSkgcHJvcE91dC5zZXQoZGZsdCk7XG4gICAgICAgICAgICBlbHNlIHByb3BPdXQuc2V0KHYpO1xuICAgICAgICB9LFxuICAgICAgICB2YWxpZGF0ZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBvcHRzKSB7XG4gICAgICAgICAgICBpZihvcHRzLmNvZXJjZU51bWJlcikgdiA9ICt2O1xuXG4gICAgICAgICAgICB2YXIgdmFsdWVzID0gb3B0cy52YWx1ZXM7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgdmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGsgPSBTdHJpbmcodmFsdWVzW2ldKTtcblxuICAgICAgICAgICAgICAgIGlmKChrLmNoYXJBdCgwKSA9PT0gJy8nICYmIGsuY2hhckF0KGsubGVuZ3RoIC0gMSkgPT09ICcvJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlZ2V4ID0gbmV3IFJlZ0V4cChrLnN1YnN0cigxLCBrLmxlbmd0aCAtIDIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYocmVnZXgudGVzdCh2KSkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHYgPT09IHZhbHVlc1tpXSkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9LFxuICAgICdib29sZWFuJzoge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCkge1xuICAgICAgICAgICAgaWYodiA9PT0gdHJ1ZSB8fCB2ID09PSBmYWxzZSkgcHJvcE91dC5zZXQodik7XG4gICAgICAgICAgICBlbHNlIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBudW1iZXI6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgY29lcmNlRnVuY3Rpb246IGZ1bmN0aW9uKHYsIHByb3BPdXQsIGRmbHQsIG9wdHMpIHtcbiAgICAgICAgICAgIGlmKCFpc051bWVyaWModikgfHxcbiAgICAgICAgICAgICAgICAgICAgKG9wdHMubWluICE9PSB1bmRlZmluZWQgJiYgdiA8IG9wdHMubWluKSB8fFxuICAgICAgICAgICAgICAgICAgICAob3B0cy5tYXggIT09IHVuZGVmaW5lZCAmJiB2ID4gb3B0cy5tYXgpKSB7XG4gICAgICAgICAgICAgICAgcHJvcE91dC5zZXQoZGZsdCk7XG4gICAgICAgICAgICB9IGVsc2UgcHJvcE91dC5zZXQoK3YpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBpbnRlZ2VyOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIGNvZXJjZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBwcm9wT3V0LCBkZmx0LCBvcHRzKSB7XG4gICAgICAgICAgICBpZih2ICUgMSB8fCAhaXNOdW1lcmljKHYpIHx8XG4gICAgICAgICAgICAgICAgICAgIChvcHRzLm1pbiAhPT0gdW5kZWZpbmVkICYmIHYgPCBvcHRzLm1pbikgfHxcbiAgICAgICAgICAgICAgICAgICAgKG9wdHMubWF4ICE9PSB1bmRlZmluZWQgJiYgdiA+IG9wdHMubWF4KSkge1xuICAgICAgICAgICAgICAgIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICAgICAgfSBlbHNlIHByb3BPdXQuc2V0KCt2KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgc3RyaW5nOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgLy8gVE9ETyAndmFsdWVzIHNob3VsZG4ndCBiZSBpbiB0aGVyZSAoZWRnZSBjYXNlOiAnZGFzaCcgaW4gU2NhdHRlcilcbiAgICAgICAgXG4gICAgICAgIGNvZXJjZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBwcm9wT3V0LCBkZmx0LCBvcHRzKSB7XG4gICAgICAgICAgICBpZih0eXBlb2YgdiAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICB2YXIgb2tUb0NvZXJjZSA9ICh0eXBlb2YgdiA9PT0gJ251bWJlcicpO1xuXG4gICAgICAgICAgICAgICAgaWYob3B0cy5zdHJpY3QgPT09IHRydWUgfHwgIW9rVG9Db2VyY2UpIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICAgICAgICAgIGVsc2UgcHJvcE91dC5zZXQoU3RyaW5nKHYpKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihvcHRzLm5vQmxhbmsgJiYgIXYpIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICAgICAgZWxzZSBwcm9wT3V0LnNldCh2KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY29sb3I6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgY29lcmNlRnVuY3Rpb246IGZ1bmN0aW9uKHYsIHByb3BPdXQsIGRmbHQpIHtcbiAgICAgICAgICAgIGlmKHRpbnljb2xvcih2KS5pc1ZhbGlkKCkpIHByb3BPdXQuc2V0KHYpO1xuICAgICAgICAgICAgZWxzZSBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY29sb3JsaXN0OiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIGNvZXJjZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBwcm9wT3V0LCBkZmx0KSB7XG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NvbG9yKGNvbG9yKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRpbnljb2xvcihjb2xvcikuaXNWYWxpZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkodikgfHwgIXYubGVuZ3RoKSBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgICAgIGVsc2UgaWYodi5ldmVyeShpc0NvbG9yKSkgcHJvcE91dC5zZXQodik7XG4gICAgICAgICAgICBlbHNlIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjb2xvcnNjYWxlOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIGNvZXJjZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBwcm9wT3V0LCBkZmx0KSB7XG4gICAgICAgICAgICBwcm9wT3V0LnNldChjb2xvcnNjYWxlcy5nZXQodiwgZGZsdCkpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBhbmdsZToge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCkge1xuICAgICAgICAgICAgaWYodiA9PT0gJ2F1dG8nKSBwcm9wT3V0LnNldCgnYXV0bycpO1xuICAgICAgICAgICAgZWxzZSBpZighaXNOdW1lcmljKHYpKSBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgICAgIGVsc2UgcHJvcE91dC5zZXQobW9kSGFsZigrdiwgMzYwKSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHN1YnBsb3RpZDoge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCwgb3B0cykge1xuICAgICAgICAgICAgdmFyIHJlZ2V4ID0gb3B0cy5yZWdleCB8fCBjb3VudGVyUmVnZXgoZGZsdCk7XG4gICAgICAgICAgICBpZih0eXBlb2YgdiA9PT0gJ3N0cmluZycgJiYgcmVnZXgudGVzdCh2KSkge1xuICAgICAgICAgICAgICAgIHByb3BPdXQuc2V0KHYpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICB9LFxuICAgICAgICB2YWxpZGF0ZUZ1bmN0aW9uOiBmdW5jdGlvbih2LCBvcHRzKSB7XG4gICAgICAgICAgICB2YXIgZGZsdCA9IG9wdHMuZGZsdDtcblxuICAgICAgICAgICAgaWYodiA9PT0gZGZsdCkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICBpZih0eXBlb2YgdiAhPT0gJ3N0cmluZycpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIGlmKGNvdW50ZXJSZWdleChkZmx0KS50ZXN0KHYpKSByZXR1cm4gdHJ1ZTtcblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBmbGFnbGlzdDoge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCwgb3B0cykge1xuICAgICAgICAgICAgaWYodHlwZW9mIHYgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgcHJvcE91dC5zZXQoZGZsdCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoKG9wdHMuZXh0cmFzIHx8IFtdKS5pbmRleE9mKHYpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHByb3BPdXQuc2V0KHYpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB2UGFydHMgPSB2LnNwbGl0KCcrJyk7XG4gICAgICAgICAgICB2YXIgaSA9IDA7XG4gICAgICAgICAgICB3aGlsZShpIDwgdlBhcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHZhciB2aSA9IHZQYXJ0c1tpXTtcbiAgICAgICAgICAgICAgICBpZihvcHRzLmZsYWdzLmluZGV4T2YodmkpID09PSAtMSB8fCB2UGFydHMuaW5kZXhPZih2aSkgPCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZQYXJ0cy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKCF2UGFydHMubGVuZ3RoKSBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgICAgIGVsc2UgcHJvcE91dC5zZXQodlBhcnRzLmpvaW4oJysnKSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGFueToge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBjb2VyY2VGdW5jdGlvbjogZnVuY3Rpb24odiwgcHJvcE91dCwgZGZsdCkge1xuICAgICAgICAgICAgaWYodiA9PT0gdW5kZWZpbmVkKSBwcm9wT3V0LnNldChkZmx0KTtcbiAgICAgICAgICAgIGVsc2UgcHJvcE91dC5zZXQodik7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGluZm9fYXJyYXk6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICAvLyBzZXQgYGRpbWVuc2lvbnM9MmAgZm9yIGEgMkQgYXJyYXkgb3IgJzEtMicgZm9yIGVpdGhlclxuICAgICAgICAvLyBgaXRlbXNgIG1heSBiZSBhIHNpbmdsZSBvYmplY3QgaW5zdGVhZCBvZiBhbiBhcnJheSwgaW4gd2hpY2ggY2FzZVxuICAgICAgICAvLyBgZnJlZUxlbmd0aGAgbXVzdCBiZSB0cnVlLlxuICAgICAgICAvLyBpZiBgZGltZW5zaW9ucz0nMS0yJ2AgYW5kIGl0ZW1zIGlzIGEgMUQgYXJyYXksIHRoZW4gdGhlIHZhbHVlIGNhblxuICAgICAgICAvLyBlaXRoZXIgYmUgYSBtYXRjaGluZyAxRCBhcnJheSBvciBhbiBhcnJheSBvZiBzdWNoIG1hdGNoaW5nIDFEIGFycmF5c1xuICAgICAgICBcbiAgICAgICAgY29lcmNlRnVuY3Rpb246IGZ1bmN0aW9uKHYsIHByb3BPdXQsIGRmbHQsIG9wdHMpIHtcbiAgICAgICAgICAgIC8vIHNpbXBsaWZpZWQgY29lcmNlIGZ1bmN0aW9uIGp1c3QgZm9yIGFycmF5IGl0ZW1zXG4gICAgICAgICAgICBmdW5jdGlvbiBjb2VyY2VQYXJ0KHYsIG9wdHMsIGRmbHQpIHtcbiAgICAgICAgICAgICAgICB2YXIgb3V0O1xuICAgICAgICAgICAgICAgIHZhciBwcm9wUGFydCA9IHtzZXQ6IGZ1bmN0aW9uKHYpIHsgb3V0ID0gdjsgfX07XG5cbiAgICAgICAgICAgICAgICBpZihkZmx0ID09PSB1bmRlZmluZWQpIGRmbHQgPSBvcHRzLmRmbHQ7XG5cbiAgICAgICAgICAgICAgICBleHBvcnRzLnZhbE9iamVjdE1ldGFbb3B0cy52YWxUeXBlXS5jb2VyY2VGdW5jdGlvbih2LCBwcm9wUGFydCwgZGZsdCwgb3B0cyk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgdHdvRCA9IG9wdHMuZGltZW5zaW9ucyA9PT0gMiB8fCAob3B0cy5kaW1lbnNpb25zID09PSAnMS0yJyAmJiBBcnJheS5pc0FycmF5KHYpICYmIEFycmF5LmlzQXJyYXkodlswXSkpO1xuXG4gICAgICAgICAgICBpZighQXJyYXkuaXNBcnJheSh2KSkge1xuICAgICAgICAgICAgICAgIHByb3BPdXQuc2V0KGRmbHQpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGl0ZW1zID0gb3B0cy5pdGVtcztcbiAgICAgICAgICAgIHZhciB2T3V0ID0gW107XG4gICAgICAgICAgICB2YXIgYXJyYXlJdGVtcyA9IEFycmF5LmlzQXJyYXkoaXRlbXMpO1xuICAgICAgICAgICAgdmFyIGFycmF5SXRlbXMyRCA9IGFycmF5SXRlbXMgJiYgdHdvRCAmJiBBcnJheS5pc0FycmF5KGl0ZW1zWzBdKTtcbiAgICAgICAgICAgIHZhciBpbm5lckl0ZW1zT25seSA9IHR3b0QgJiYgYXJyYXlJdGVtcyAmJiAhYXJyYXlJdGVtczJEO1xuICAgICAgICAgICAgdmFyIGxlbiA9IChhcnJheUl0ZW1zICYmICFpbm5lckl0ZW1zT25seSkgPyBpdGVtcy5sZW5ndGggOiB2Lmxlbmd0aDtcblxuICAgICAgICAgICAgdmFyIGksIGosIHJvdywgaXRlbSwgbGVuMiwgdk5ldztcblxuICAgICAgICAgICAgZGZsdCA9IEFycmF5LmlzQXJyYXkoZGZsdCkgPyBkZmx0IDogW107XG5cbiAgICAgICAgICAgIGlmKHR3b0QpIHtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2T3V0W2ldID0gW107XG4gICAgICAgICAgICAgICAgICAgIHJvdyA9IEFycmF5LmlzQXJyYXkodltpXSkgPyB2W2ldIDogW107XG4gICAgICAgICAgICAgICAgICAgIGlmKGlubmVySXRlbXNPbmx5KSBsZW4yID0gaXRlbXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKGFycmF5SXRlbXMpIGxlbjIgPSBpdGVtc1tpXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgbGVuMiA9IHJvdy5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbGVuMjsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihpbm5lckl0ZW1zT25seSkgaXRlbSA9IGl0ZW1zW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZihhcnJheUl0ZW1zKSBpdGVtID0gaXRlbXNbaV1bal07XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGl0ZW0gPSBpdGVtcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgdk5ldyA9IGNvZXJjZVBhcnQocm93W2pdLCBpdGVtLCAoZGZsdFtpXSB8fCBbXSlbal0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYodk5ldyAhPT0gdW5kZWZpbmVkKSB2T3V0W2ldW2pdID0gdk5ldztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdk5ldyA9IGNvZXJjZVBhcnQodltpXSwgYXJyYXlJdGVtcyA/IGl0ZW1zW2ldIDogaXRlbXMsIGRmbHRbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih2TmV3ICE9PSB1bmRlZmluZWQpIHZPdXRbaV0gPSB2TmV3O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcHJvcE91dC5zZXQodk91dCk7XG4gICAgICAgIH0sXG4gICAgICAgIHZhbGlkYXRlRnVuY3Rpb246IGZ1bmN0aW9uKHYsIG9wdHMpIHtcbiAgICAgICAgICAgIGlmKCFBcnJheS5pc0FycmF5KHYpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgICAgIHZhciBpdGVtcyA9IG9wdHMuaXRlbXM7XG4gICAgICAgICAgICB2YXIgYXJyYXlJdGVtcyA9IEFycmF5LmlzQXJyYXkoaXRlbXMpO1xuICAgICAgICAgICAgdmFyIHR3b0QgPSBvcHRzLmRpbWVuc2lvbnMgPT09IDI7XG5cbiAgICAgICAgICAgIC8vIHdoZW4gZnJlZSBsZW5ndGggaXMgb2ZmLCBpbnB1dCBhbmQgZGVjbGFyZWQgbGVuZ3RocyBtdXN0IG1hdGNoXG4gICAgICAgICAgICBpZighb3B0cy5mcmVlTGVuZ3RoICYmIHYubGVuZ3RoICE9PSBpdGVtcy5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgICAgICAgICAgLy8gdmFsaWQgd2hlbiBhbGwgaW5wdXQgaXRlbXMgYXJlIHZhbGlkXG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgdi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKHR3b0QpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkodltpXSkgfHwgKCFvcHRzLmZyZWVMZW5ndGggJiYgdltpXS5sZW5ndGggIT09IGl0ZW1zW2ldLmxlbmd0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgdltpXS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIXZhbGlkYXRlKHZbaV1bal0sIGFycmF5SXRlbXMgPyBpdGVtc1tpXVtqXSA6IGl0ZW1zKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZighdmFsaWRhdGUodltpXSwgYXJyYXlJdGVtcyA/IGl0ZW1zW2ldIDogaXRlbXMpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuLyoqXG4gKiBFbnN1cmVzIHRoYXQgY29udGFpbmVyW2F0dHJpYnV0ZV0gaGFzIGEgdmFsaWQgdmFsdWUuXG4gKlxuICogYXR0cmlidXRlc1thdHRyaWJ1dGVdIGlzIGFuIG9iamVjdCB3aXRoIHBvc3NpYmxlIGtleXM6XG4gKiAtIHZhbFR5cGU6IGRhdGFfYXJyYXksIGVudW1lcmF0ZWQsIGJvb2xlYW4sIC4uLiBhcyBpbiB2YWxPYmplY3RNZXRhXG4gKiAtIHZhbHVlczogKGVudW1lcmF0ZWQgb25seSkgYXJyYXkgb2YgYWxsb3dlZCB2YWxzXG4gKiAtIG1pbiwgbWF4OiAobnVtYmVyLCBpbnRlZ2VyIG9ubHkpIGluY2x1c2l2ZSBib3VuZHMgb24gYWxsb3dlZCB2YWxzXG4gKiAgICAgIGVpdGhlciBvciBib3RoIG1heSBiZSBvbWl0dGVkXG4gKiAtIGRmbHQ6IGlmIGF0dHJpYnV0ZSBpcyBpbnZhbGlkIG9yIG1pc3NpbmcsIHVzZSB0aGlzIGRlZmF1bHRcbiAqICAgICAgaWYgZGZsdCBpcyBwcm92aWRlZCBhcyBhbiBhcmd1bWVudCB0byBsaWIuY29lcmNlIGl0IHRha2VzIHByZWNlZGVuY2VcbiAqICAgICAgYXMgYSBjb252ZW5pZW5jZSwgcmV0dXJucyB0aGUgdmFsdWUgaXQgZmluYWxseSBzZXRcbiAqL1xuZXhwb3J0cy5jb2VyY2UgPSBmdW5jdGlvbihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBhdHRyaWJ1dGVzLCBhdHRyaWJ1dGUsIGRmbHQpIHtcbiAgICB2YXIgb3B0cyA9IG5lc3RlZFByb3BlcnR5KGF0dHJpYnV0ZXMsIGF0dHJpYnV0ZSkuZ2V0KCk7XG4gICAgdmFyIHByb3BJbiA9IG5lc3RlZFByb3BlcnR5KGNvbnRhaW5lckluLCBhdHRyaWJ1dGUpO1xuICAgIHZhciBwcm9wT3V0ID0gbmVzdGVkUHJvcGVydHkoY29udGFpbmVyT3V0LCBhdHRyaWJ1dGUpO1xuICAgIHZhciB2ID0gcHJvcEluLmdldCgpO1xuXG4gICAgdmFyIHRlbXBsYXRlID0gY29udGFpbmVyT3V0Ll90ZW1wbGF0ZTtcbiAgICBpZih2ID09PSB1bmRlZmluZWQgJiYgdGVtcGxhdGUpIHtcbiAgICAgICAgdiA9IG5lc3RlZFByb3BlcnR5KHRlbXBsYXRlLCBhdHRyaWJ1dGUpLmdldCgpO1xuICAgICAgICAvLyBhbHJlYWR5IHVzZWQgdGhlIHRlbXBsYXRlIHZhbHVlLCBzbyBzaG9ydC1jaXJjdWl0IHRoZSBzZWNvbmQgY2hlY2tcbiAgICAgICAgdGVtcGxhdGUgPSAwO1xuICAgIH1cblxuICAgIGlmKGRmbHQgPT09IHVuZGVmaW5lZCkgZGZsdCA9IG9wdHMuZGZsdDtcblxuICAgIC8qKlxuICAgICAqIGFycmF5T2s6IHZhbHVlIE1BWSBiZSBhbiBhcnJheSwgdGhlbiB3ZSBkbyBubyB2YWx1ZSBjaGVja2luZ1xuICAgICAqIGF0IHRoaXMgcG9pbnQsIGJlY2F1c2UgaXQgY2FuIGJlIG1vcmUgY29tcGxpY2F0ZWQgdGhhbiB0aGVcbiAgICAgKiBpbmRpdmlkdWFsIGZvcm0gKGVnLiBzb21lIGFycmF5IHZhbHMgY2FuIGJlIG51bWJlcnMsIGV2ZW4gaWYgdGhlXG4gICAgICogc2luZ2xlIHZhbHVlcyBtdXN0IGJlIGNvbG9yIHN0cmluZ3MpXG4gICAgICovXG4gICAgaWYob3B0cy5hcnJheU9rICYmIGlzQXJyYXlPclR5cGVkQXJyYXkodikpIHtcbiAgICAgICAgcHJvcE91dC5zZXQodik7XG4gICAgICAgIHJldHVybiB2O1xuICAgIH1cblxuICAgIHZhciBjb2VyY2VGdW5jdGlvbiA9IGV4cG9ydHMudmFsT2JqZWN0TWV0YVtvcHRzLnZhbFR5cGVdLmNvZXJjZUZ1bmN0aW9uO1xuICAgIGNvZXJjZUZ1bmN0aW9uKHYsIHByb3BPdXQsIGRmbHQsIG9wdHMpO1xuXG4gICAgdmFyIG91dCA9IHByb3BPdXQuZ2V0KCk7XG4gICAgLy8gaW4gY2FzZSB2IHdhcyBwcm92aWRlZCBidXQgaW52YWxpZCwgdHJ5IHRoZSB0ZW1wbGF0ZSBhZ2FpbiBzbyBpdCBzdGlsbFxuICAgIC8vIG92ZXJyaWRlcyB0aGUgcmVndWxhciBkZWZhdWx0XG4gICAgaWYodGVtcGxhdGUgJiYgb3V0ID09PSBkZmx0ICYmICF2YWxpZGF0ZSh2LCBvcHRzKSkge1xuICAgICAgICB2ID0gbmVzdGVkUHJvcGVydHkodGVtcGxhdGUsIGF0dHJpYnV0ZSkuZ2V0KCk7XG4gICAgICAgIGNvZXJjZUZ1bmN0aW9uKHYsIHByb3BPdXQsIGRmbHQsIG9wdHMpO1xuICAgICAgICBvdXQgPSBwcm9wT3V0LmdldCgpO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBWYXJpYXRpb24gb24gY29lcmNlXG4gKlxuICogVXNlcyBjb2VyY2UgdG8gZ2V0IGF0dHJpYnV0ZSB2YWx1ZSBpZiB1c2VyIGlucHV0IGlzIHZhbGlkLFxuICogcmV0dXJucyBhdHRyaWJ1dGUgZGVmYXVsdCBpZiB1c2VyIGlucHV0IGl0IG5vdCB2YWxpZCBvclxuICogcmV0dXJucyBmYWxzZSBpZiB0aGVyZSBpcyBubyB1c2VyIGlucHV0LlxuICovXG5leHBvcnRzLmNvZXJjZTIgPSBmdW5jdGlvbihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBhdHRyaWJ1dGVzLCBhdHRyaWJ1dGUsIGRmbHQpIHtcbiAgICB2YXIgcHJvcEluID0gbmVzdGVkUHJvcGVydHkoY29udGFpbmVySW4sIGF0dHJpYnV0ZSk7XG4gICAgdmFyIHByb3BPdXQgPSBleHBvcnRzLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBhdHRyaWJ1dGVzLCBhdHRyaWJ1dGUsIGRmbHQpO1xuICAgIHZhciB2YWxJbiA9IHByb3BJbi5nZXQoKTtcblxuICAgIHJldHVybiAodmFsSW4gIT09IHVuZGVmaW5lZCAmJiB2YWxJbiAhPT0gbnVsbCkgPyBwcm9wT3V0IDogZmFsc2U7XG59O1xuXG4vKlxuICogU2hvcnRjdXQgdG8gY29lcmNlIHRoZSB0aHJlZSBmb250IGF0dHJpYnV0ZXNcbiAqXG4gKiAnY29lcmNlJyBpcyBhIGxpYi5jb2VyY2Ugd3JhcHBlciB3aXRoIGltcGxpZWQgZmlyc3QgdGhyZWUgYXJndW1lbnRzXG4gKi9cbmV4cG9ydHMuY29lcmNlRm9udCA9IGZ1bmN0aW9uKGNvZXJjZSwgYXR0ciwgZGZsdE9iaikge1xuICAgIHZhciBvdXQgPSB7fTtcblxuICAgIGRmbHRPYmogPSBkZmx0T2JqIHx8IHt9O1xuXG4gICAgb3V0LmZhbWlseSA9IGNvZXJjZShhdHRyICsgJy5mYW1pbHknLCBkZmx0T2JqLmZhbWlseSk7XG4gICAgb3V0LnNpemUgPSBjb2VyY2UoYXR0ciArICcuc2l6ZScsIGRmbHRPYmouc2l6ZSk7XG4gICAgb3V0LmNvbG9yID0gY29lcmNlKGF0dHIgKyAnLmNvbG9yJywgZGZsdE9iai5jb2xvcik7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqIENvZXJjZSBzaG9ydGN1dCBmb3IgJ2hvdmVyaW5mbydcbiAqIGhhbmRsaW5nIDEtdnMtbXVsdGktdHJhY2UgZGZsdCBsb2dpY1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFjZUluIDogdXNlciB0cmFjZSBvYmplY3RcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFjZU91dCA6IGZ1bGwgdHJhY2Ugb2JqZWN0IChyZXF1aXJlcyBfbW9kdWxlIHJlZilcbiAqIEBwYXJhbSB7b2JqZWN0fSBsYXlvdXRPdXQgOiBmdWxsIGxheW91dCBvYmplY3QgKHJlcXVpcmUgX2RhdGFMZW5ndGggcmVmKVxuICogQHJldHVybiB7YW55fSA6IHRoZSBjb2VyY2VkIHZhbHVlXG4gKi9cbmV4cG9ydHMuY29lcmNlSG92ZXJpbmZvID0gZnVuY3Rpb24odHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dE91dCkge1xuICAgIHZhciBtb2R1bGVBdHRycyA9IHRyYWNlT3V0Ll9tb2R1bGUuYXR0cmlidXRlcztcbiAgICB2YXIgYXR0cnMgPSBtb2R1bGVBdHRycy5ob3ZlcmluZm8gPyBtb2R1bGVBdHRycyA6IGJhc2VUcmFjZUF0dHJzO1xuXG4gICAgdmFyIHZhbE9iaiA9IGF0dHJzLmhvdmVyaW5mbztcbiAgICB2YXIgZGZsdDtcblxuICAgIGlmKGxheW91dE91dC5fZGF0YUxlbmd0aCA9PT0gMSkge1xuICAgICAgICB2YXIgZmxhZ3MgPSB2YWxPYmouZGZsdCA9PT0gJ2FsbCcgP1xuICAgICAgICAgICAgdmFsT2JqLmZsYWdzLnNsaWNlKCkgOlxuICAgICAgICAgICAgdmFsT2JqLmRmbHQuc3BsaXQoJysnKTtcblxuICAgICAgICBmbGFncy5zcGxpY2UoZmxhZ3MuaW5kZXhPZignbmFtZScpLCAxKTtcbiAgICAgICAgZGZsdCA9IGZsYWdzLmpvaW4oJysnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZXhwb3J0cy5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJzLCAnaG92ZXJpbmZvJywgZGZsdCk7XG59O1xuXG4vKiogQ29lcmNlIHNob3J0Y3V0IGZvciBbdW5dc2VsZWN0ZWQubWFya2VyLm9wYWNpdHksXG4gKiAgd2hpY2ggaGFzIHNwZWNpYWwgZGVmYXVsdCBsb2dpYywgdG8gZW5zdXJlIHRoYXQgaXQgY29ycmVzcG9uZHMgdG8gdGhlXG4gKiAgZGVmYXVsdCBzZWxlY3Rpb24gYmVoYXZpb3Igd2hpbGUgYWxsb3dpbmcgdG8gYmUgb3ZlcnRha2VuIGJ5IGFueSBvdGhlclxuICogIFt1bl1zZWxlY3RlZCBhdHRyaWJ1dGUuXG4gKlxuICogIE4uQi4gVGhpcyBtdXN0IGJlIGNhbGxlZCAqYWZ0ZXIqIGNvZXJjaW5nIGFsbCB0aGUgb3RoZXIgW3VuXXNlbGVjdGVkIGF0dHJzLFxuICogIHRvIGdpdmUgdGhlIGludGVuZGVkIHJlc3VsdC5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2VPdXQgOiBmdWxsRGF0YSBpdGVtXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjb2VyY2UgOiBsaWIuY29lcmNlIHdyYXBwZXIgd2l0aCBpbXBsaWVkIGZpcnN0IHRocmVlIGFyZ3VtZW50c1xuICovXG5leHBvcnRzLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkgPSBmdW5jdGlvbih0cmFjZU91dCwgY29lcmNlKSB7XG4gICAgaWYoIXRyYWNlT3V0Lm1hcmtlcikgcmV0dXJuO1xuXG4gICAgdmFyIG1vID0gdHJhY2VPdXQubWFya2VyLm9wYWNpdHk7XG4gICAgLy8geW91IGNhbiBzdGlsbCBoYXZlIGEgYG1hcmtlcmAgY29udGFpbmVyIHdpdGggbm8gbWFya2VycyBpZiB0aGVyZSdzIHRleHRcbiAgICBpZihtbyA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgICB2YXIgc21vRGZsdDtcbiAgICB2YXIgdXNtb0RmbHQ7XG5cbiAgICAvLyBEb24ndCBnaXZlIFt1bl1zZWxlY3RlZC5tYXJrZXIub3BhY2l0eSBhIGRlZmF1bHQgdmFsdWUgaWZcbiAgICAvLyBtYXJrZXIub3BhY2l0eSBpcyBhbiBhcnJheTogaGFuZGxlIHRoaXMgZHVyaW5nIHN0eWxlIHN0ZXAuXG4gICAgLy9cbiAgICAvLyBPbmx5IGdpdmUgW3VuXXNlbGVjdGVkLm1hcmtlci5vcGFjaXR5IGEgZGVmYXVsdCB2YWx1ZSBpZiB5b3UgZG9uJ3RcbiAgICAvLyBzZXQgYW55IG90aGVyIFt1bl1zZWxlY3RlZCBhdHRyaWJ1dGVzLlxuICAgIGlmKCFpc0FycmF5T3JUeXBlZEFycmF5KG1vKSAmJiAhdHJhY2VPdXQuc2VsZWN0ZWQgJiYgIXRyYWNlT3V0LnVuc2VsZWN0ZWQpIHtcbiAgICAgICAgc21vRGZsdCA9IG1vO1xuICAgICAgICB1c21vRGZsdCA9IERFU0VMRUNURElNICogbW87XG4gICAgfVxuXG4gICAgY29lcmNlKCdzZWxlY3RlZC5tYXJrZXIub3BhY2l0eScsIHNtb0RmbHQpO1xuICAgIGNvZXJjZSgndW5zZWxlY3RlZC5tYXJrZXIub3BhY2l0eScsIHVzbW9EZmx0KTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkYXRlKHZhbHVlLCBvcHRzKSB7XG4gICAgdmFyIHZhbE9iamVjdERlZiA9IGV4cG9ydHMudmFsT2JqZWN0TWV0YVtvcHRzLnZhbFR5cGVdO1xuXG4gICAgaWYob3B0cy5hcnJheU9rICYmIGlzQXJyYXlPclR5cGVkQXJyYXkodmFsdWUpKSByZXR1cm4gdHJ1ZTtcblxuICAgIGlmKHZhbE9iamVjdERlZi52YWxpZGF0ZUZ1bmN0aW9uKSB7XG4gICAgICAgIHJldHVybiB2YWxPYmplY3REZWYudmFsaWRhdGVGdW5jdGlvbih2YWx1ZSwgb3B0cyk7XG4gICAgfVxuXG4gICAgdmFyIGZhaWxlZCA9IHt9O1xuICAgIHZhciBvdXQgPSBmYWlsZWQ7XG4gICAgdmFyIHByb3BNb2NrID0geyBzZXQ6IGZ1bmN0aW9uKHYpIHsgb3V0ID0gdjsgfSB9O1xuXG4gICAgLy8gJ2ZhaWxlZCcganVzdCBzb21ldGhpbmcgbXV0YWJsZSB0aGF0IHdvbid0IGJlID09PSBhbnl0aGluZyBlbHNlXG5cbiAgICB2YWxPYmplY3REZWYuY29lcmNlRnVuY3Rpb24odmFsdWUsIHByb3BNb2NrLCBmYWlsZWQsIG9wdHMpO1xuICAgIHJldHVybiBvdXQgIT09IGZhaWxlZDtcbn1cbmV4cG9ydHMudmFsaWRhdGUgPSB2YWxpZGF0ZTtcblxufSx7XCIuLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvc2NhbGVzXCI6NjA4LFwiLi4vY29uc3RhbnRzL2ludGVyYWN0aW9uc1wiOjY5NCxcIi4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuL2FycmF5XCI6NzAyLFwiLi9tb2RcIjo3MjYsXCIuL25lc3RlZF9wcm9wZXJ0eVwiOjcyNyxcIi4vcmVnZXhcIjo3MzUsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNSxcInRpbnljb2xvcjJcIjo1Mzd9XSw3MDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExvZ2dlcnMgPSBfZGVyZXFfKCcuL2xvZ2dlcnMnKTtcbnZhciBtb2QgPSBfZGVyZXFfKCcuL21vZCcpLm1vZDtcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4uL2NvbnN0YW50cy9udW1lcmljYWwnKTtcbnZhciBCQUROVU0gPSBjb25zdGFudHMuQkFETlVNO1xudmFyIE9ORURBWSA9IGNvbnN0YW50cy5PTkVEQVk7XG52YXIgT05FSE9VUiA9IGNvbnN0YW50cy5PTkVIT1VSO1xudmFyIE9ORU1JTiA9IGNvbnN0YW50cy5PTkVNSU47XG52YXIgT05FU0VDID0gY29uc3RhbnRzLk9ORVNFQztcbnZhciBFUE9DSEpEID0gY29uc3RhbnRzLkVQT0NISkQ7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uL3JlZ2lzdHJ5Jyk7XG5cbnZhciB1dGNGb3JtYXQgPSBkMy50aW1lLmZvcm1hdC51dGM7XG5cbnZhciBEQVRFVElNRV9SRUdFWFAgPSAvXlxccyooLT9cXGRcXGRcXGRcXGR8XFxkXFxkKSgtKFxcZD9cXGQpKC0oXFxkP1xcZCkoWyBUdF0oWzAxXT9cXGR8MlswLTNdKSg6KFswLTVdXFxkKSg6KFswLTVdXFxkKFxcLlxcZCspPykpPyhafHp8WytcXC1dXFxkXFxkOj9cXGRcXGQpPyk/KT8pPyk/XFxzKiQvbTtcbi8vIHNwZWNpYWwgcmVnZXggZm9yIGNoaW5lc2UgY2FsZW5kYXJzIHRvIHN1cHBvcnQgeXl5eS1tbWktZGQgZXRjIGZvciBpbnRlcmNhbGFyeSBtb250aHNcbnZhciBEQVRFVElNRV9SRUdFWFBfQ04gPSAvXlxccyooLT9cXGRcXGRcXGRcXGR8XFxkXFxkKSgtKFxcZD9cXGRpPykoLShcXGQ/XFxkKShbIFR0XShbMDFdP1xcZHwyWzAtM10pKDooWzAtNV1cXGQpKDooWzAtNV1cXGQoXFwuXFxkKyk/KSk/KFp8enxbK1xcLV1cXGRcXGQ6P1xcZFxcZCk/KT8pPyk/KT9cXHMqJC9tO1xuXG4vLyBmb3IgMi1kaWdpdCB5ZWFycywgdGhlIGZpcnN0IHllYXIgd2UgbWFwIHRoZW0gb250b1xudmFyIFlGSVJTVCA9IG5ldyBEYXRlKCkuZ2V0RnVsbFllYXIoKSAtIDcwO1xuXG5mdW5jdGlvbiBpc1dvcmxkQ2FsZW5kYXIoY2FsZW5kYXIpIHtcbiAgICByZXR1cm4gKFxuICAgICAgICBjYWxlbmRhciAmJlxuICAgICAgICBSZWdpc3RyeS5jb21wb25lbnRzUmVnaXN0cnkuY2FsZW5kYXJzICYmXG4gICAgICAgIHR5cGVvZiBjYWxlbmRhciA9PT0gJ3N0cmluZycgJiYgY2FsZW5kYXIgIT09ICdncmVnb3JpYW4nXG4gICAgKTtcbn1cblxuLypcbiAqIGRhdGVUaWNrMDogZ2V0IHRoZSBjYW5vbmljYWwgdGljayBmb3IgdGhpcyBjYWxlbmRhclxuICpcbiAqIGJvb2wgc3VuZGF5IGlzIGZvciB3ZWVrIHRpY2tzLCBzaGlmdCBpdCB0byBhIFN1bmRheS5cbiAqL1xuZXhwb3J0cy5kYXRlVGljazAgPSBmdW5jdGlvbihjYWxlbmRhciwgc3VuZGF5KSB7XG4gICAgaWYoaXNXb3JsZENhbGVuZGFyKGNhbGVuZGFyKSkge1xuICAgICAgICByZXR1cm4gc3VuZGF5ID9cbiAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ0NBTk9OSUNBTF9TVU5EQVknKVtjYWxlbmRhcl0gOlxuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnQ0FOT05JQ0FMX1RJQ0snKVtjYWxlbmRhcl07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHN1bmRheSA/ICcyMDAwLTAxLTAyJyA6ICcyMDAwLTAxLTAxJztcbiAgICB9XG59O1xuXG4vKlxuICogZGZsdFJhbmdlOiBmb3IgZWFjaCBjYWxlbmRhciwgZ2l2ZSBhIHZhbGlkIGRlZmF1bHQgcmFuZ2VcbiAqL1xuZXhwb3J0cy5kZmx0UmFuZ2UgPSBmdW5jdGlvbihjYWxlbmRhcikge1xuICAgIGlmKGlzV29ybGRDYWxlbmRhcihjYWxlbmRhcikpIHtcbiAgICAgICAgcmV0dXJuIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ0RGTFRSQU5HRScpW2NhbGVuZGFyXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gWycyMDAwLTAxLTAxJywgJzIwMDEtMDEtMDEnXTtcbiAgICB9XG59O1xuXG4vLyBpcyBhbiBvYmplY3QgYSBqYXZhc2NyaXB0IGRhdGU/XG5leHBvcnRzLmlzSlNEYXRlID0gZnVuY3Rpb24odikge1xuICAgIHJldHVybiB0eXBlb2YgdiA9PT0gJ29iamVjdCcgJiYgdiAhPT0gbnVsbCAmJiB0eXBlb2Ygdi5nZXRUaW1lID09PSAnZnVuY3Rpb24nO1xufTtcblxuLy8gVGhlIGFic29sdXRlIGxpbWl0cyBvZiBvdXIgZGF0ZS10aW1lIHN5c3RlbVxuLy8gVGhpcyBpcyBhIGxpdHRsZSB3ZWlyZDogd2UgdXNlIE1JTl9NUyBhbmQgTUFYX01TIGluIGRhdGVUaW1lMm1zXG4vLyBidXQgd2UgdXNlIGRhdGVUaW1lMm1zIHRvIGNhbGN1bGF0ZSB0aGVtIChhZnRlciBkZWZpbmluZyBpdCEpXG52YXIgTUlOX01TLCBNQVhfTVM7XG5cbi8qKlxuICogZGF0ZVRpbWUybXMgLSB0dXJuIGEgZGF0ZSBvYmplY3Qgb3Igc3RyaW5nIHMgaW50byBtaWxsaXNlY29uZHNcbiAqIChyZWxhdGl2ZSB0byAxOTcwLTAxLTAxLCBwZXIgamF2YXNjcmlwdCBzdGFuZGFyZClcbiAqIG9wdGlvbmFsIGNhbGVuZGFyIChzdHJpbmcpIHRvIHVzZSBhIG5vbi1ncmVnb3JpYW4gY2FsZW5kYXJcbiAqXG4gKiBSZXR1cm5zIEJBRE5VTSBpZiBpdCBkb2Vzbid0IGZpbmQgYSBkYXRlXG4gKlxuICogc3RyaW5ncyBzaG91bGQgaGF2ZSB0aGUgZm9ybTpcbiAqXG4gKiAgICAtP1lZWVktbW0tZGQ8c2VwPkhIOk1NOlNTLnNzczx0ekluZm8+P1xuICpcbiAqIDxzZXA+OiBzcGFjZSAob3VyIG5vcm1hbCBzdGFuZGFyZCkgb3IgVCBvciB0IChJU08tODYwMSlcbiAqIDx0ekluZm8+OiBaLCB6LCBvciBbK1xcLV1ISDo/TU0gYW5kIHdlIFRIUk9XIElUIEFXQVlcbiAqIHRoaXMgZm9ybWF0IGNvbWVzIGZyb20gaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzMzMzkjc2VjdGlvbi01LjZcbiAqIGJ1dCB3ZSBhbGxvdyBpdCBldmVuIHdpdGggYSBzcGFjZSBhcyB0aGUgc2VwYXJhdG9yXG4gKlxuICogTWF5IHRydW5jYXRlIGFmdGVyIGFueSBmdWxsIGZpZWxkLCBhbmQgc3NzIGNhbiBiZSBhbnkgbGVuZ3RoXG4gKiBldmVuID4zIGRpZ2l0cywgdGhvdWdoIGphdmFzY3JpcHQgZGF0ZXMgdHJ1bmNhdGUgdG8gbWlsbGlzZWNvbmRzLFxuICogd2Uga2VlcCBhcyBtdWNoIGFzIGphdmFzY3JpcHQgbnVtZXJpYyBwcmVjaXNpb24gY2FuIGhvbGQsIGJ1dCB3ZSBvbmx5XG4gKiByZXBvcnQgYmFjayB1cCB0byAxMDAgbWljcm9zZWNvbmQgcHJlY2lzaW9uLCBiZWNhdXNlIG1vc3QgZGF0ZXMgc3VwcG9ydFxuICogdGhpcyBwcmVjaXNpb24gKGNsb3NlIHRvIDE5NzAgc3VwcG9ydCBtb3JlLCB2ZXJ5IGZhciBhd2F5IHN1cHBvcnQgbGVzcylcbiAqXG4gKiBFeHBhbmRlZCB0byBzdXBwb3J0IG5lZ2F0aXZlIHllYXJzIHRvIC05OTk5IGJ1dCB5b3UgbXVzdCBhbHdheXNcbiAqIGdpdmUgNCBkaWdpdHMsIGV4Y2VwdCBmb3IgMi1kaWdpdCBwb3NpdGl2ZSB5ZWFycyB3aGljaCB3ZSBhc3N1bWUgYXJlXG4gKiBuZWFyIHRoZSBwcmVzZW50IHRpbWUuXG4gKiBOb3RlIHRoYXQgd2UgZm9sbG93IElTTyA4NjAxOjIwMDQ6IHRoZXJlICppcyogYSB5ZWFyIDAsIHdoaWNoXG4gKiBpcyAxQkMvQkNFLCBhbmQgLTE9PT0yQkMgZXRjLlxuICpcbiAqIFdvcmxkIGNhbGVuZGFyczogbm90IGFsbCBvZiB0aGVzZSAqaGF2ZSogYWdyZWVkIGV4dGVuc2lvbnMgdG8gdGhpcyBmdWxsIHJhbmdlLFxuICogaWYgeW91IGhhdmUgYW5vdGhlciBjYWxlbmRhciBzeXN0ZW0gYnV0IHdhbnQgYSBkYXRlIHJhbmdlIG91dHNpZGUgaXRzIHZhbGlkaXR5LFxuICogeW91IGNhbiB1c2UgYSBncmVnb3JpYW4gZGF0ZSBzdHJpbmcgcHJlZml4ZWQgd2l0aCAnRycgb3IgJ2cnLlxuICpcbiAqIFdoZXJlIHRvIGN1dCBvZmYgMi1kaWdpdCB5ZWFycyBiZXR3ZWVuIDE5MDBzIGFuZCAyMDAwcz9cbiAqIGZyb20gaHR0cDovL3N1cHBvcnQubWljcm9zb2Z0LmNvbS9rYi8yNDQ2NjQ6XG4gKiAgIDE5MzAtMjAyOSAodGhlIG1vc3QgcmV0cm8gb2YgYWxsLi4uKVxuICogYnV0IGluIG15IG1hYyBjaHJvbWUgZnJvbSBlZy4gZD1uZXcgRGF0ZShEYXRlLnBhcnNlKCc4LzE5LzUwJykpOlxuICogICAxOTUwLTIwNDlcbiAqIGJ5IEphdmEsIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDI0MjczLzpcbiAqICAgbm93LTgwIC0gbm93KzE5XG4gKiBvciBGaWxlTWFrZXIgUHJvLCBmcm9tXG4gKiAgICAgIGh0dHA6Ly93d3cuZmlsZW1ha2VyLmNvbS8xMmhlbHAvaHRtbC9hZGRfdmlld19kYXRhLjQuMjEuaHRtbDpcbiAqICAgbm93LTcwIC0gbm93KzI5XG4gKiBidXQgcHl0aG9uIHN0cnB0aW1lIGV0YywgdmlhXG4gKiAgICAgIGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvcHkzay9saWJyYXJ5L3RpbWUuaHRtbDpcbiAqICAgMTk2OS0yMDY4IChzdXBlciBmb3J3YXJkLWxvb2tpbmcsIGJ1dCBzdGF0aWMsIG5vdCBzbGlkaW5nISlcbiAqXG4gKiBsZXRzIGdvIHdpdGggbm93LTcwIHRvIG5vdysyOSwgYW5kIGlmIGFueW9uZSBydW5zIGludG8gdGhpcyBwcm9ibGVtXG4gKiB0aGV5IGNhbiBsZWFybiB0aGUgaGFyZCB3YXkgbm90IHRvIHVzZSAyLWRpZ2l0IHllYXJzLCBhcyBubyBjaG9pY2Ugd2VcbiAqIG1ha2Ugbm93IHdpbGwgY292ZXIgYWxsIHBvc3NpYmlsaXRpZXMuIG1vc3RseSB0aGlzIHdpbGwgYWxsIGJlIHRha2VuXG4gKiBjYXJlIG9mIGluIGluaXRpYWwgcGFyc2luZywgc2hvdWxkIG9ubHkgYmUgYW4gaXNzdWUgZm9yIGhhbmQtZW50ZXJlZCBkYXRhXG4gKiBjdXJyZW50bHkgKDIwMTYpIHRoaXMgcmFuZ2UgaXM6XG4gKiAgIDE5NDYtMjA0NVxuICovXG5leHBvcnRzLmRhdGVUaW1lMm1zID0gZnVuY3Rpb24ocywgY2FsZW5kYXIpIHtcbiAgICAvLyBmaXJzdCBjaGVjayBpZiBzIGlzIGEgZGF0ZSBvYmplY3RcbiAgICBpZihleHBvcnRzLmlzSlNEYXRlKHMpKSB7XG4gICAgICAgIC8vIENvbnZlcnQgdG8gdGhlIFVUQyBtaWxsaXNlY29uZHMgdGhhdCBnaXZlIHRoZSBzYW1lXG4gICAgICAgIC8vIGhvdXJzIGFzIHRoaXMgZGF0ZSBoYXMgaW4gdGhlIGxvY2FsIHRpbWV6b25lXG4gICAgICAgIHZhciB0ek9mZnNldCA9IHMuZ2V0VGltZXpvbmVPZmZzZXQoKSAqIE9ORU1JTjtcbiAgICAgICAgdmFyIG9mZnNldFR3ZWFrID0gKHMuZ2V0VVRDTWludXRlcygpIC0gcy5nZXRNaW51dGVzKCkpICogT05FTUlOICtcbiAgICAgICAgICAgIChzLmdldFVUQ1NlY29uZHMoKSAtIHMuZ2V0U2Vjb25kcygpKSAqIE9ORVNFQyArXG4gICAgICAgICAgICAocy5nZXRVVENNaWxsaXNlY29uZHMoKSAtIHMuZ2V0TWlsbGlzZWNvbmRzKCkpO1xuXG4gICAgICAgIGlmKG9mZnNldFR3ZWFrKSB7XG4gICAgICAgICAgICB2YXIgY29tYiA9IDMgKiBPTkVNSU47XG4gICAgICAgICAgICB0ek9mZnNldCA9IHR6T2Zmc2V0IC0gY29tYiAvIDIgKyBtb2Qob2Zmc2V0VHdlYWsgLSB0ek9mZnNldCArIGNvbWIgLyAyLCBjb21iKTtcbiAgICAgICAgfVxuICAgICAgICBzID0gTnVtYmVyKHMpIC0gdHpPZmZzZXQ7XG4gICAgICAgIGlmKHMgPj0gTUlOX01TICYmIHMgPD0gTUFYX01TKSByZXR1cm4gcztcbiAgICAgICAgcmV0dXJuIEJBRE5VTTtcbiAgICB9XG4gICAgLy8gb3RoZXJ3aXNlIG9ubHkgYWNjZXB0IHN0cmluZ3MgYW5kIG51bWJlcnNcbiAgICBpZih0eXBlb2YgcyAhPT0gJ3N0cmluZycgJiYgdHlwZW9mIHMgIT09ICdudW1iZXInKSByZXR1cm4gQkFETlVNO1xuXG4gICAgcyA9IFN0cmluZyhzKTtcblxuICAgIHZhciBpc1dvcmxkID0gaXNXb3JsZENhbGVuZGFyKGNhbGVuZGFyKTtcblxuICAgIC8vIHRvIGhhbmRsZSBvdXQtb2YtcmFuZ2UgZGF0ZXMgaW4gaW50ZXJuYXRpb25hbCBjYWxlbmRhcnMsIGFjY2VwdFxuICAgIC8vICdHJyBhcyBhIHByZWZpeCB0byBmb3JjZSB0aGUgYnVpbHQtaW4gZ3JlZ29yaWFuIGNhbGVuZGFyLlxuICAgIHZhciBzMCA9IHMuY2hhckF0KDApO1xuICAgIGlmKGlzV29ybGQgJiYgKHMwID09PSAnRycgfHwgczAgPT09ICdnJykpIHtcbiAgICAgICAgcyA9IHMuc3Vic3RyKDEpO1xuICAgICAgICBjYWxlbmRhciA9ICcnO1xuICAgIH1cblxuICAgIHZhciBpc0NoaW5lc2UgPSBpc1dvcmxkICYmIGNhbGVuZGFyLnN1YnN0cigwLCA3KSA9PT0gJ2NoaW5lc2UnO1xuXG4gICAgdmFyIG1hdGNoID0gcy5tYXRjaChpc0NoaW5lc2UgPyBEQVRFVElNRV9SRUdFWFBfQ04gOiBEQVRFVElNRV9SRUdFWFApO1xuICAgIGlmKCFtYXRjaCkgcmV0dXJuIEJBRE5VTTtcbiAgICB2YXIgeSA9IG1hdGNoWzFdO1xuICAgIHZhciBtID0gbWF0Y2hbM10gfHwgJzEnO1xuICAgIHZhciBkID0gTnVtYmVyKG1hdGNoWzVdIHx8IDEpO1xuICAgIHZhciBIID0gTnVtYmVyKG1hdGNoWzddIHx8IDApO1xuICAgIHZhciBNID0gTnVtYmVyKG1hdGNoWzldIHx8IDApO1xuICAgIHZhciBTID0gTnVtYmVyKG1hdGNoWzExXSB8fCAwKTtcblxuICAgIGlmKGlzV29ybGQpIHtcbiAgICAgICAgLy8gZGlzYWxsb3cgMi1kaWdpdCB5ZWFycyBmb3Igd29ybGQgY2FsZW5kYXJzXG4gICAgICAgIGlmKHkubGVuZ3RoID09PSAyKSByZXR1cm4gQkFETlVNO1xuICAgICAgICB5ID0gTnVtYmVyKHkpO1xuXG4gICAgICAgIHZhciBjRGF0ZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZhciBjYWxJbnN0YW5jZSA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2dldENhbCcpKGNhbGVuZGFyKTtcbiAgICAgICAgICAgIGlmKGlzQ2hpbmVzZSkge1xuICAgICAgICAgICAgICAgIHZhciBpc0ludGVyY2FsYXJ5ID0gbS5jaGFyQXQobS5sZW5ndGggLSAxKSA9PT0gJ2knO1xuICAgICAgICAgICAgICAgIG0gPSBwYXJzZUludChtLCAxMCk7XG4gICAgICAgICAgICAgICAgY0RhdGUgPSBjYWxJbnN0YW5jZS5uZXdEYXRlKHksIGNhbEluc3RhbmNlLnRvTW9udGhJbmRleCh5LCBtLCBpc0ludGVyY2FsYXJ5KSwgZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNEYXRlID0gY2FsSW5zdGFuY2UubmV3RGF0ZSh5LCBOdW1iZXIobSksIGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoKGUpIHsgcmV0dXJuIEJBRE5VTTsgfSAvLyBJbnZhbGlkIC4uLiBkYXRlXG5cbiAgICAgICAgaWYoIWNEYXRlKSByZXR1cm4gQkFETlVNO1xuXG4gICAgICAgIHJldHVybiAoKGNEYXRlLnRvSkQoKSAtIEVQT0NISkQpICogT05FREFZKSArXG4gICAgICAgICAgICAoSCAqIE9ORUhPVVIpICsgKE0gKiBPTkVNSU4pICsgKFMgKiBPTkVTRUMpO1xuICAgIH1cblxuICAgIGlmKHkubGVuZ3RoID09PSAyKSB7XG4gICAgICAgIHkgPSAoTnVtYmVyKHkpICsgMjAwMCAtIFlGSVJTVCkgJSAxMDAgKyBZRklSU1Q7XG4gICAgfSBlbHNlIHkgPSBOdW1iZXIoeSk7XG5cbiAgICAvLyBuZXcgRGF0ZSB1c2VzIG1vbnRocyBmcm9tIDA7IHN1YnRyYWN0IDEgaGVyZSBqdXN0IHNvIHdlXG4gICAgLy8gZG9uJ3QgaGF2ZSB0byBkbyBpdCBhZ2FpbiBkdXJpbmcgdGhlIHZhbGlkaXR5IHRlc3QgYmVsb3dcbiAgICBtIC09IDE7XG5cbiAgICAvLyBqYXZhc2NyaXB0IHRha2VzIG5ldyBEYXRlKDAuLjk5LG0sZCkgdG8gbWVhbiAxOTAwLTE5OTksIHNvXG4gICAgLy8gdG8gc3VwcG9ydCB5ZWFycyAwLTk5IHdlIG5lZWQgdG8gdXNlIHNldEZ1bGxZZWFyIGV4cGxpY2l0bHlcbiAgICAvLyBOb3RlIHRoYXQgMjAwMCBpcyBhIGxlYXAgeWVhci5cbiAgICB2YXIgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDKDIwMDAsIG0sIGQsIEgsIE0pKTtcbiAgICBkYXRlLnNldFVUQ0Z1bGxZZWFyKHkpO1xuXG4gICAgaWYoZGF0ZS5nZXRVVENNb250aCgpICE9PSBtKSByZXR1cm4gQkFETlVNO1xuICAgIGlmKGRhdGUuZ2V0VVRDRGF0ZSgpICE9PSBkKSByZXR1cm4gQkFETlVNO1xuXG4gICAgcmV0dXJuIGRhdGUuZ2V0VGltZSgpICsgUyAqIE9ORVNFQztcbn07XG5cbk1JTl9NUyA9IGV4cG9ydHMuTUlOX01TID0gZXhwb3J0cy5kYXRlVGltZTJtcygnLTk5OTknKTtcbk1BWF9NUyA9IGV4cG9ydHMuTUFYX01TID0gZXhwb3J0cy5kYXRlVGltZTJtcygnOTk5OS0xMi0zMSAyMzo1OTo1OS45OTk5Jyk7XG5cbi8vIGlzIHN0cmluZyBzIGEgZGF0ZT8gKHNlZSBhYm92ZSlcbmV4cG9ydHMuaXNEYXRlVGltZSA9IGZ1bmN0aW9uKHMsIGNhbGVuZGFyKSB7XG4gICAgcmV0dXJuIChleHBvcnRzLmRhdGVUaW1lMm1zKHMsIGNhbGVuZGFyKSAhPT0gQkFETlVNKTtcbn07XG5cbi8vIHBhZCBhIG51bWJlciB3aXRoIHplcm9lcywgdG8gZ2l2ZW4gIyBvZiBkaWdpdHMgYmVmb3JlIHRoZSBkZWNpbWFsIHBvaW50XG5mdW5jdGlvbiBscGFkKHZhbCwgZGlnaXRzKSB7XG4gICAgcmV0dXJuIFN0cmluZyh2YWwgKyBNYXRoLnBvdygxMCwgZGlnaXRzKSkuc3Vic3RyKDEpO1xufVxuXG4vKipcbiAqIFR1cm4gbXMgaW50byBzdHJpbmcgb2YgdGhlIGZvcm0gWVlZWS1tbS1kZCBISDpNTTpTUy5zc3NzXG4gKiBDcm9wIGFueSB0cmFpbGluZyB6ZXJvcyBpbiB0aW1lLCBleGNlcHQgbmV2ZXIgc3RvcCByaWdodCBhZnRlciBob3Vyc1xuICogKHdlIGNvdWxkIGNob29zZSB0byBjcm9wICctMDEnIGZyb20gZGF0ZSB0b28gYnV0IGZvciBub3cgd2UgYWx3YXlzXG4gKiBzaG93IHRoZSB3aG9sZSBkYXRlKVxuICogT3B0aW9uYWwgcmFuZ2UgciBpcyB0aGUgZGF0YSByYW5nZSB0aGF0IGFwcGxpZXMsIGFsc28gaW4gbXMuXG4gKiBJZiBybmcgaXMgYmlnLCB0aGUgbGF0ZXIgcGFydHMgb2YgdGltZSB3aWxsIGJlIG9taXR0ZWRcbiAqL1xudmFyIE5JTkVUWURBWVMgPSA5MCAqIE9ORURBWTtcbnZhciBUSFJFRUhPVVJTID0gMyAqIE9ORUhPVVI7XG52YXIgRklWRU1JTiA9IDUgKiBPTkVNSU47XG5leHBvcnRzLm1zMkRhdGVUaW1lID0gZnVuY3Rpb24obXMsIHIsIGNhbGVuZGFyKSB7XG4gICAgaWYodHlwZW9mIG1zICE9PSAnbnVtYmVyJyB8fCAhKG1zID49IE1JTl9NUyAmJiBtcyA8PSBNQVhfTVMpKSByZXR1cm4gQkFETlVNO1xuXG4gICAgaWYoIXIpIHIgPSAwO1xuXG4gICAgdmFyIG1zZWNUZW50aHMgPSBNYXRoLmZsb29yKG1vZChtcyArIDAuMDUsIDEpICogMTApO1xuICAgIHZhciBtc1JvdW5kZWQgPSBNYXRoLnJvdW5kKG1zIC0gbXNlY1RlbnRocyAvIDEwKTtcbiAgICB2YXIgZGF0ZVN0ciwgaCwgbSwgcywgbXNlYzEwLCBkO1xuXG4gICAgaWYoaXNXb3JsZENhbGVuZGFyKGNhbGVuZGFyKSkge1xuICAgICAgICB2YXIgZGF0ZUpEID0gTWF0aC5mbG9vcihtc1JvdW5kZWQgLyBPTkVEQVkpICsgRVBPQ0hKRDtcbiAgICAgICAgdmFyIHRpbWVNcyA9IE1hdGguZmxvb3IobW9kKG1zLCBPTkVEQVkpKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGRhdGVTdHIgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdnZXRDYWwnKShjYWxlbmRhcilcbiAgICAgICAgICAgICAgICAuZnJvbUpEKGRhdGVKRCkuZm9ybWF0RGF0ZSgneXl5eS1tbS1kZCcpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICAgIC8vIGludmFsaWQgZGF0ZSBpbiB0aGlzIGNhbGVuZGFyIC0gZmFsbCBiYWNrIHRvIEd5eXl5LW1tLWRkXG4gICAgICAgICAgICBkYXRlU3RyID0gdXRjRm9ybWF0KCdHJVktJW0tJWQnKShuZXcgRGF0ZShtc1JvdW5kZWQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHl5eXkgZG9lcyBOT1QgZ3VhcmFudGVlIDQtZGlnaXQgeWVhcnMuIFlZWVkgbW9zdGx5IGRvZXMsIGJ1dCBkb2VzXG4gICAgICAgIC8vIG90aGVyIHRoaW5ncyBmb3IgYSBmZXcgY2FsZW5kYXJzLCBzbyB3ZSBjYW4ndCB0cnVzdCBpdC4gSnVzdCBwYWRcbiAgICAgICAgLy8gaXQgbWFudWFsbHkgKGFmdGVyIHRoZSAnLScgaWYgdGhlcmUgaXMgb25lKVxuICAgICAgICBpZihkYXRlU3RyLmNoYXJBdCgwKSA9PT0gJy0nKSB7XG4gICAgICAgICAgICB3aGlsZShkYXRlU3RyLmxlbmd0aCA8IDExKSBkYXRlU3RyID0gJy0wJyArIGRhdGVTdHIuc3Vic3RyKDEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2hpbGUoZGF0ZVN0ci5sZW5ndGggPCAxMCkgZGF0ZVN0ciA9ICcwJyArIGRhdGVTdHI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPOiBpZiB0aGlzIGlzIGZhc3Rlciwgd2UgY291bGQgdXNlIHRoaXMgYmxvY2sgZm9yIGV4dHJhY3RpbmdcbiAgICAgICAgLy8gdGhlIHRpbWUgY29tcG9uZW50cyBvZiByZWd1bGFyIGdyZWdvcmlhbiB0b29cbiAgICAgICAgaCA9IChyIDwgTklORVRZREFZUykgPyBNYXRoLmZsb29yKHRpbWVNcyAvIE9ORUhPVVIpIDogMDtcbiAgICAgICAgbSA9IChyIDwgTklORVRZREFZUykgPyBNYXRoLmZsb29yKCh0aW1lTXMgJSBPTkVIT1VSKSAvIE9ORU1JTikgOiAwO1xuICAgICAgICBzID0gKHIgPCBUSFJFRUhPVVJTKSA/IE1hdGguZmxvb3IoKHRpbWVNcyAlIE9ORU1JTikgLyBPTkVTRUMpIDogMDtcbiAgICAgICAgbXNlYzEwID0gKHIgPCBGSVZFTUlOKSA/ICh0aW1lTXMgJSBPTkVTRUMpICogMTAgKyBtc2VjVGVudGhzIDogMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkID0gbmV3IERhdGUobXNSb3VuZGVkKTtcblxuICAgICAgICBkYXRlU3RyID0gdXRjRm9ybWF0KCclWS0lbS0lZCcpKGQpO1xuXG4gICAgICAgIC8vIDw5MCBkYXlzOiBhZGQgaG91cnMgYW5kIG1pbnV0ZXMgLSBuZXZlciAqb25seSogYWRkIGhvdXJzXG4gICAgICAgIGggPSAociA8IE5JTkVUWURBWVMpID8gZC5nZXRVVENIb3VycygpIDogMDtcbiAgICAgICAgbSA9IChyIDwgTklORVRZREFZUykgPyBkLmdldFVUQ01pbnV0ZXMoKSA6IDA7XG4gICAgICAgIC8vIDwzIGhvdXJzOiBhZGQgc2Vjb25kc1xuICAgICAgICBzID0gKHIgPCBUSFJFRUhPVVJTKSA/IGQuZ2V0VVRDU2Vjb25kcygpIDogMDtcbiAgICAgICAgLy8gPDUgbWludXRlczogYWRkIG1zIChwbHVzIG9uZSBleHRyYSBkaWdpdCwgdGhpcyBpcyBtc2VjKjEwKVxuICAgICAgICBtc2VjMTAgPSAociA8IEZJVkVNSU4pID8gZC5nZXRVVENNaWxsaXNlY29uZHMoKSAqIDEwICsgbXNlY1RlbnRocyA6IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGluY2x1ZGVUaW1lKGRhdGVTdHIsIGgsIG0sIHMsIG1zZWMxMCk7XG59O1xuXG4vLyBGb3IgY29udmVydGluZyBvbGQtc3R5bGUgbWlsbGlzZWNvbmRzIHRvIGRhdGUgc3RyaW5ncyxcbi8vIHdlIHVzZSB0aGUgbG9jYWwgdGltZXpvbmUgcmF0aGVyIHRoYW4gVVRDIGxpa2Ugd2UgdXNlXG4vLyBldmVyeXdoZXJlIGVsc2UsIGJvdGggZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgYW5kXG4vLyBiZWNhdXNlIHRoYXQncyBob3cgcGVvcGxlIG1vc3RseSB1c2UgamF2YXNyaXB0IGRhdGUgb2JqZWN0cy5cbi8vIENsaXAgb25lIGV4dHJhIGRheSBvZmYgb3VyIGRhdGUgcmFuZ2UgdGhvdWdoIHNvIHdlIGNhbid0IGdldFxuLy8gdGhyb3duIGJleW9uZCB0aGUgcmFuZ2UgYnkgdGhlIHRpbWV6b25lIHNoaWZ0LlxuZXhwb3J0cy5tczJEYXRlVGltZUxvY2FsID0gZnVuY3Rpb24obXMpIHtcbiAgICBpZighKG1zID49IE1JTl9NUyArIE9ORURBWSAmJiBtcyA8PSBNQVhfTVMgLSBPTkVEQVkpKSByZXR1cm4gQkFETlVNO1xuXG4gICAgdmFyIG1zZWNUZW50aHMgPSBNYXRoLmZsb29yKG1vZChtcyArIDAuMDUsIDEpICogMTApO1xuICAgIHZhciBkID0gbmV3IERhdGUoTWF0aC5yb3VuZChtcyAtIG1zZWNUZW50aHMgLyAxMCkpO1xuICAgIHZhciBkYXRlU3RyID0gZDMudGltZS5mb3JtYXQoJyVZLSVtLSVkJykoZCk7XG4gICAgdmFyIGggPSBkLmdldEhvdXJzKCk7XG4gICAgdmFyIG0gPSBkLmdldE1pbnV0ZXMoKTtcbiAgICB2YXIgcyA9IGQuZ2V0U2Vjb25kcygpO1xuICAgIHZhciBtc2VjMTAgPSBkLmdldFVUQ01pbGxpc2Vjb25kcygpICogMTAgKyBtc2VjVGVudGhzO1xuXG4gICAgcmV0dXJuIGluY2x1ZGVUaW1lKGRhdGVTdHIsIGgsIG0sIHMsIG1zZWMxMCk7XG59O1xuXG5mdW5jdGlvbiBpbmNsdWRlVGltZShkYXRlU3RyLCBoLCBtLCBzLCBtc2VjMTApIHtcbiAgICAvLyBpbmNsdWRlIGVhY2ggcGFydCB0aGF0IGhhcyBub256ZXJvIGRhdGEgaW4gb3IgYWZ0ZXIgaXRcbiAgICBpZihoIHx8IG0gfHwgcyB8fCBtc2VjMTApIHtcbiAgICAgICAgZGF0ZVN0ciArPSAnICcgKyBscGFkKGgsIDIpICsgJzonICsgbHBhZChtLCAyKTtcbiAgICAgICAgaWYocyB8fCBtc2VjMTApIHtcbiAgICAgICAgICAgIGRhdGVTdHIgKz0gJzonICsgbHBhZChzLCAyKTtcbiAgICAgICAgICAgIGlmKG1zZWMxMCkge1xuICAgICAgICAgICAgICAgIHZhciBkaWdpdHMgPSA0O1xuICAgICAgICAgICAgICAgIHdoaWxlKG1zZWMxMCAlIDEwID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGRpZ2l0cyAtPSAxO1xuICAgICAgICAgICAgICAgICAgICBtc2VjMTAgLz0gMTA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRhdGVTdHIgKz0gJy4nICsgbHBhZChtc2VjMTAsIGRpZ2l0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRhdGVTdHI7XG59XG5cbi8vIG5vcm1hbGl6ZSBkYXRlIGZvcm1hdCB0byBkYXRlIHN0cmluZywgaW4gY2FzZSBpdCBzdGFydHMgYXNcbi8vIGEgRGF0ZSBvYmplY3Qgb3IgbWlsbGlzZWNvbmRzXG4vLyBvcHRpb25hbCBkZmx0IGlzIHRoZSByZXR1cm4gdmFsdWUgaWYgY2xlYW5pbmcgZmFpbHNcbmV4cG9ydHMuY2xlYW5EYXRlID0gZnVuY3Rpb24odiwgZGZsdCwgY2FsZW5kYXIpIHtcbiAgICAvLyBsZXQgdXMgdXNlIGNsZWFuRGF0ZSB0byBwcm92aWRlIGEgbWlzc2luZyBkZWZhdWx0IHdpdGhvdXQgYW4gZXJyb3JcbiAgICBpZih2ID09PSBCQUROVU0pIHJldHVybiBkZmx0O1xuICAgIGlmKGV4cG9ydHMuaXNKU0RhdGUodikgfHwgKHR5cGVvZiB2ID09PSAnbnVtYmVyJyAmJiBpc0Zpbml0ZSh2KSkpIHtcbiAgICAgICAgLy8gZG8gbm90IGFsbG93IG1pbGxpc2Vjb25kcyAob2xkKSBvciBqc2RhdGUgb2JqZWN0cyAoaW5oZXJlbnRseVxuICAgICAgICAvLyBkZXNjcmliZWQgYXMgZ3JlZ29yaWFuIGRhdGVzKSB3aXRoIHdvcmxkIGNhbGVuZGFyc1xuICAgICAgICBpZihpc1dvcmxkQ2FsZW5kYXIoY2FsZW5kYXIpKSB7XG4gICAgICAgICAgICBMb2dnZXJzLmVycm9yKCdKUyBEYXRlcyBhbmQgbWlsbGlzZWNvbmRzIGFyZSBpbmNvbXBhdGlibGUgd2l0aCB3b3JsZCBjYWxlbmRhcnMnLCB2KTtcbiAgICAgICAgICAgIHJldHVybiBkZmx0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTk9URTogaWYgc29tZW9uZSBwdXRzIGluIGEgeWVhciBhcyBhIG51bWJlciByYXRoZXIgdGhhbiBhIHN0cmluZyxcbiAgICAgICAgLy8gdGhpcyB3aWxsIG1pc3Rha2VubHkgY29udmVydCBpdCB0aGlua2luZyBpdCdzIG1pbGxpc2Vjb25kcyBmcm9tIDE5NzBcbiAgICAgICAgLy8gdGhhdCBpczogJzIwMTInIC0+IEphbi4gMSwgMjAxMiwgYnV0IDIwMTIgLT4gMjAxMiBlcG9jaCBtaWxsaXNlY29uZHNcbiAgICAgICAgdiA9IGV4cG9ydHMubXMyRGF0ZVRpbWVMb2NhbCgrdik7XG4gICAgICAgIGlmKCF2ICYmIGRmbHQgIT09IHVuZGVmaW5lZCkgcmV0dXJuIGRmbHQ7XG4gICAgfSBlbHNlIGlmKCFleHBvcnRzLmlzRGF0ZVRpbWUodiwgY2FsZW5kYXIpKSB7XG4gICAgICAgIExvZ2dlcnMuZXJyb3IoJ3VucmVjb2duaXplZCBkYXRlJywgdik7XG4gICAgICAgIHJldHVybiBkZmx0O1xuICAgIH1cbiAgICByZXR1cm4gdjtcbn07XG5cbi8qXG4gKiAgRGF0ZSBmb3JtYXR0aW5nIGZvciB0aWNrcyBhbmQgaG92ZXJ0ZXh0XG4gKi9cblxuLypcbiAqIG1vZERhdGVGb3JtYXQ6IFN1cHBvcnQgd29ybGQgY2FsZW5kYXJzLCBhbmQgYWRkIG9uZSBpdGVtIHRvXG4gKiBkMydzIHZvY2FidWxhcnk6XG4gKiAle259ZiB3aGVyZSBuIGlzIHRoZSBtYXggbnVtYmVyIG9mIGRpZ2l0cyBvZiBmcmFjdGlvbmFsIHNlY29uZHNcbiAqL1xudmFyIGZyYWNNYXRjaCA9IC8lXFxkP2YvZztcbmZ1bmN0aW9uIG1vZERhdGVGb3JtYXQoZm10LCB4LCBmb3JtYXR0ZXIsIGNhbGVuZGFyKSB7XG4gICAgZm10ID0gZm10LnJlcGxhY2UoZnJhY01hdGNoLCBmdW5jdGlvbihtYXRjaCkge1xuICAgICAgICB2YXIgZGlnaXRzID0gTWF0aC5taW4oKyhtYXRjaC5jaGFyQXQoMSkpIHx8IDYsIDYpO1xuICAgICAgICB2YXIgZnJhY1NlY3MgPSAoKHggLyAxMDAwICUgMSkgKyAyKVxuICAgICAgICAgICAgLnRvRml4ZWQoZGlnaXRzKVxuICAgICAgICAgICAgLnN1YnN0cigyKS5yZXBsYWNlKC8wKyQvLCAnJykgfHwgJzAnO1xuICAgICAgICByZXR1cm4gZnJhY1NlY3M7XG4gICAgfSk7XG5cbiAgICB2YXIgZCA9IG5ldyBEYXRlKE1hdGguZmxvb3IoeCArIDAuMDUpKTtcblxuICAgIGlmKGlzV29ybGRDYWxlbmRhcihjYWxlbmRhcikpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGZtdCA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ3dvcmxkQ2FsRm10JykoZm10LCB4LCBjYWxlbmRhcik7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgcmV0dXJuICdJbnZhbGlkJztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZm9ybWF0dGVyKGZtdCkoZCk7XG59XG5cbi8qXG4gKiBmb3JtYXRUaW1lOiBjcmVhdGUgYSB0aW1lIHN0cmluZyBmcm9tOlxuICogICB4OiBtaWxsaXNlY29uZHNcbiAqICAgdHI6IHRpY2tyb3VuZCAoJ00nLCAnUycsIG9yICMgZGlnaXRzKVxuICogb25seSBzdXBwb3J0cyBVVEMgdGltZXMgKHdoZXJlIGV2ZXJ5IGRheSBpcyAyNCBob3VycyBhbmQgMCBpcyBhdCBtaWRuaWdodClcbiAqL1xudmFyIE1BWFNFQ09ORFMgPSBbNTksIDU5LjksIDU5Ljk5LCA1OS45OTksIDU5Ljk5OTldO1xuZnVuY3Rpb24gZm9ybWF0VGltZSh4LCB0cikge1xuICAgIHZhciB0aW1lUGFydCA9IG1vZCh4ICsgMC4wNSwgT05FREFZKTtcblxuICAgIHZhciB0aW1lU3RyID0gbHBhZChNYXRoLmZsb29yKHRpbWVQYXJ0IC8gT05FSE9VUiksIDIpICsgJzonICtcbiAgICAgICAgbHBhZChtb2QoTWF0aC5mbG9vcih0aW1lUGFydCAvIE9ORU1JTiksIDYwKSwgMik7XG5cbiAgICBpZih0ciAhPT0gJ00nKSB7XG4gICAgICAgIGlmKCFpc051bWVyaWModHIpKSB0ciA9IDA7IC8vIHNob3VsZCBvbmx5IGJlICdTJ1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIHRoaXMgaXMgYSB3ZWlyZCBvbmUgLSBhbmQgc2hvdWxkbid0IGNvbWUgdXAgdW5sZXNzIHBlb3BsZVxuICAgICAgICAgKiBtb25rZXkgd2l0aCB0aWNrMCBpbiB3ZWlyZCB3YXlzLCBidXQgd2UgbmVlZCB0byBkbyBzb21ldGhpbmchXG4gICAgICAgICAqIElOIFBBUlRJQ1VMQVIgd2UgaGFkIGJldHRlciBub3QgZGlzcGxheSBnYXJiYWdlIChzZWUgYmVsb3cpXG4gICAgICAgICAqIGZvciBudW1iZXJzIHdlIGFsd2F5cyByb3VuZCB0byB0aGUgbmVhcmVzdCBpbmNyZW1lbnQgb2YgdGhlXG4gICAgICAgICAqIHByZWNpc2lvbiB3ZSdyZSBzaG93aW5nLCBhbmQgdGhpcyBzZWVtcyBsaWtlIHRoZSByaWdodCB3YXkgdG9cbiAgICAgICAgICogaGFuZGxlIHNlY29uZHMgYW5kIG1pbGxpc2Vjb25kcywgYXMgdGhleSBoYXZlIGEgZGVjaW1hbCBwb2ludFxuICAgICAgICAgKiBhbmQgcGVvcGxlIHdpbGwgaW50ZXJwcmV0IHRoYXQgdG8gbWVhbiByb3VuZGluZyBsaWtlIG51bWJlcnMuXG4gICAgICAgICAqIGJ1dCBmb3IgbGFyZ2VyIGluY3JlbWVudHMgd2UgZmxvb3IgdGhlIHZhbHVlOiBpdCdzIGFsd2F5c1xuICAgICAgICAgKiAyMDEzIHVudGlsIHRoZSBiYWxsIGRyb3BzIG9uIHRoZSBuZXcgeWVhci4gV2UgY291bGQgYXJndWUgYWJvdXRcbiAgICAgICAgICogd2hpY2ggZmllbGQgaXQgaXMgd2hlcmUgd2Ugc3RhcnQgcm91bmRpbmcgKHNob3VsZCAxMjowODo1OVxuICAgICAgICAgKiByb3VuZCB0byAxMjowOSBpZiB3ZSdyZSBzdG9wcGluZyBhdCBtaW51dGVzPykgYnV0IGZvciBub3cgSSdsbFxuICAgICAgICAgKiBzYXkgd2Ugcm91bmQgc2Vjb25kcyBidXQgZmxvb3IgZXZlcnl0aGluZyBlbHNlLiBCVVQgdGhhdCBtZWFuc1xuICAgICAgICAgKiB3ZSBuZWVkIHRvIG5ldmVyIHJvdW5kIHVwIHRvIDYwIHNlY29uZHMsIGllIDIzOjU5OjYwXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgc2VjID0gTWF0aC5taW4obW9kKHggLyBPTkVTRUMsIDYwKSwgTUFYU0VDT05EU1t0cl0pO1xuXG4gICAgICAgIHZhciBzZWNTdHIgPSAoMTAwICsgc2VjKS50b0ZpeGVkKHRyKS5zdWJzdHIoMSk7XG4gICAgICAgIGlmKHRyID4gMCkge1xuICAgICAgICAgICAgc2VjU3RyID0gc2VjU3RyLnJlcGxhY2UoLzArJC8sICcnKS5yZXBsYWNlKC9bXFwuXSQvLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aW1lU3RyICs9ICc6JyArIHNlY1N0cjtcbiAgICB9XG4gICAgcmV0dXJuIHRpbWVTdHI7XG59XG5cbi8qXG4gKiBmb3JtYXREYXRlOiB0dXJuIGEgZGF0ZSBpbnRvIHRpY2sgb3IgaG92ZXIgbGFiZWwgdGV4dC5cbiAqXG4gKiAgIHg6IG1pbGxpc2Vjb25kcywgdGhlIHZhbHVlIHRvIGNvbnZlcnRcbiAqICAgZm10OiBvcHRpb25hbCwgYW4gZXhwbGljaXQgZm9ybWF0IHN0cmluZyAoZDMgZm9ybWF0LCBldmVuIGZvciB3b3JsZCBjYWxlbmRhcnMpXG4gKiAgIHRyOiB0aWNrcm91bmQgKCd5JywgJ20nLCAnZCcsICdNJywgJ1MnLCBvciAjIGRpZ2l0cylcbiAqICAgICAgdXNlZCBpZiBubyBleHBsaWNpdCBmbXQgaXMgcHJvdmlkZWRcbiAqICAgZm9ybWF0dGVyOiBsb2NhbGUtYXdhcmUgZDMgZGF0ZSBmb3JtYXR0ZXIgZm9yIHN0YW5kYXJkIGdyZWdvcmlhbiBjYWxlbmRhcnNcbiAqICAgICAgc2hvdWxkIGJlIHRoZSByZXN1bHQgb2YgZXhwb3J0cy5nZXREM0RhdGVGb3JtYXQoZ2QpXG4gKiAgIGNhbGVuZGFyOiBvcHRpb25hbCBzdHJpbmcsIHRoZSB3b3JsZCBjYWxlbmRhciBzeXN0ZW0gdG8gdXNlXG4gKlxuICogcmV0dXJucyB0aGUgZGF0ZS90aW1lIGFzIGEgc3RyaW5nLCBwb3RlbnRpYWxseSB3aXRoIHRoZSBsZWFkaW5nIHBvcnRpb25cbiAqIG9uIGEgc2VwYXJhdGUgbGluZSAoYWZ0ZXIgJ1xcbicpXG4gKiBOb3RlIHRoYXQgdGhpcyBtZWFucyBpZiB5b3UgcHJvdmlkZSBhbiBleHBsaWNpdCBmb3JtYXQgd2hpY2ggaW5jbHVkZXMgJ1xcbidcbiAqIHRoZSBheGlzIG1heSBjaG9vc2UgdG8gc3RyaXAgdGhpbmdzIGFmdGVyIGl0IHdoZW4gdGhleSBkb24ndCBjaGFuZ2UgZnJvbVxuICogb25lIHRpY2sgdG8gdGhlIG5leHQgKGFzIGl0IGRvZXMgd2l0aCBhdXRvbWF0aWMgZm9ybWF0dGluZylcbiAqL1xuZXhwb3J0cy5mb3JtYXREYXRlID0gZnVuY3Rpb24oeCwgZm10LCB0ciwgZm9ybWF0dGVyLCBjYWxlbmRhciwgZXh0cmFGb3JtYXQpIHtcbiAgICBjYWxlbmRhciA9IGlzV29ybGRDYWxlbmRhcihjYWxlbmRhcikgJiYgY2FsZW5kYXI7XG5cbiAgICBpZighZm10KSB7XG4gICAgICAgIGlmKHRyID09PSAneScpIGZtdCA9IGV4dHJhRm9ybWF0LnllYXI7XG4gICAgICAgIGVsc2UgaWYodHIgPT09ICdtJykgZm10ID0gZXh0cmFGb3JtYXQubW9udGg7XG4gICAgICAgIGVsc2UgaWYodHIgPT09ICdkJykge1xuICAgICAgICAgICAgZm10ID0gZXh0cmFGb3JtYXQuZGF5TW9udGggKyAnXFxuJyArIGV4dHJhRm9ybWF0LnllYXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0VGltZSh4LCB0cikgKyAnXFxuJyArIG1vZERhdGVGb3JtYXQoZXh0cmFGb3JtYXQuZGF5TW9udGhZZWFyLCB4LCBmb3JtYXR0ZXIsIGNhbGVuZGFyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBtb2REYXRlRm9ybWF0KGZtdCwgeCwgZm9ybWF0dGVyLCBjYWxlbmRhcik7XG59O1xuXG4vKlxuICogaW5jcmVtZW50TW9udGg6IG1ha2UgYSBuZXcgbWlsbGlzZWNvbmRzIHZhbHVlIGZyb20gdGhlIGdpdmVuIG9uZSxcbiAqIGhhdmluZyBjaGFuZ2VkIHRoZSBtb250aFxuICpcbiAqIHNwZWNpYWwgY2FzZSBmb3Igd29ybGQgY2FsZW5kYXJzOiBtdWx0aXBsZXMgb2YgMTIgYXJlIHRyZWF0ZWQgYXMgeWVhcnMsXG4gKiBldmVuIGZvciBjYWxlbmRhciBzeXN0ZW1zIHRoYXQgZG9uJ3QgaGF2ZSAoYWx3YXlzIG9yIGV2ZXIpIDEyIG1vbnRocy95ZWFyXG4gKiBUT0RPOiBwZXJoYXBzIHdlIG5lZWQgYSBkaWZmZXJlbnQgY29kZSBmb3IgeWVhciBpbmNyZW1lbnRzIHRvIHN1cHBvcnQgdGhpcz9cbiAqXG4gKiBtcyAobnVtYmVyKTogdGhlIGluaXRpYWwgbWlsbGlzZWNvbmQgdmFsdWVcbiAqIGRNb250aCAoaW50KTogdGhlIChzaWduZWQpIG51bWJlciBvZiBtb250aHMgdG8gc2hpZnRcbiAqIGNhbGVuZGFyIChzdHJpbmcpOiB0aGUgY2FsZW5kYXIgc3lzdGVtIHRvIHVzZVxuICpcbiAqIGNoYW5naW5nIG1vbnRoIGRvZXMgbm90IChhbmQgQ0FOTk9UKSBhbHdheXMgcHJlc2VydmUgZGF5LCBzaW5jZVxuICogbW9udGhzIGhhdmUgZGlmZmVyZW50IGxlbmd0aHMuIFRoZSB3b3JzdCBleGFtcGxlIG9mIHRoaXMgaXM6XG4gKiAgIGQgPSBuZXcgRGF0ZSgxOTcwLDAsMzEpOyBkLnNldE1vbnRoKDEpIC0+IEZlYiAzMSB0dXJucyBpbnRvIE1hciAzXG4gKlxuICogQnV0IHdlIHdhbnQgdG8gYmUgYWJsZSB0byBpdGVyYXRlIG92ZXIgdGhlIGxhc3QgZGF5IG9mIGVhY2ggbW9udGgsXG4gKiByZWdhcmRsZXNzIG9mIHdoYXQgaXRzIG51bWJlciBpcy5cbiAqIFNvIHNoaWZ0IDMgZGF5cyBmb3J3YXJkLCBUSEVOIHNldCB0aGUgbmV3IG1vbnRoLCB0aGVuIHVuc2hpZnQ6XG4gKiAgIDEvMzEgLT4gMi8yOCAob3IgMjkpIC0+IDMvMzEgLT4gNC8zMCAtPiAuLi5cbiAqXG4gKiBOb3RlIHRoYXQgb2RkIGJlaGF2aW9yIHN0aWxsIGV4aXN0cyBpZiB5b3Ugc3RhcnQgZnJvbSB0aGUgMjZ0aC0yOHRoOlxuICogICAxLzI4IC0+IDIvMjggLT4gMy8zMVxuICogYnV0IGF0IGxlYXN0IHlvdSBjYW4ndCBzaGlmdCBhbnkgZGF0ZXMgaW50byB0aGUgd3JvbmcgbW9udGgsXG4gKiBhbmQgdGlja3Mgb24gdGhlc2UgZGF5cyBpbmNyZW1lbnRpbmcgYnkgbW9udGggd291bGQgYmUgdmVyeSB1bnVzdWFsXG4gKi9cbnZhciBUSFJFRURBWVMgPSAzICogT05FREFZO1xuZXhwb3J0cy5pbmNyZW1lbnRNb250aCA9IGZ1bmN0aW9uKG1zLCBkTW9udGgsIGNhbGVuZGFyKSB7XG4gICAgY2FsZW5kYXIgPSBpc1dvcmxkQ2FsZW5kYXIoY2FsZW5kYXIpICYmIGNhbGVuZGFyO1xuXG4gICAgLy8gcHVsbCB0aW1lIG91dCBhbmQgb3BlcmF0ZSBvbiBwdXJlIGRhdGVzLCB0aGVuIGFkZCB0aW1lIGJhY2sgYXQgdGhlIGVuZFxuICAgIC8vIHRoaXMgZ2l2ZXMgbWF4aW11bSBwcmVjaXNpb24gLSBub3QgdGhhdCB3ZSAqbm9ybWFsbHkqIGNhcmUgaWYgd2UncmVcbiAgICAvLyBpbmNyZW1lbnRpbmcgYnkgbW9udGgsIGJ1dCBiZXR0ZXIgdG8gYmUgc2FmZSFcbiAgICB2YXIgdGltZU1zID0gbW9kKG1zLCBPTkVEQVkpO1xuICAgIG1zID0gTWF0aC5yb3VuZChtcyAtIHRpbWVNcyk7XG5cbiAgICBpZihjYWxlbmRhcikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmFyIGRhdGVKRCA9IE1hdGgucm91bmQobXMgLyBPTkVEQVkpICsgRVBPQ0hKRDtcbiAgICAgICAgICAgIHZhciBjYWxJbnN0YW5jZSA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2dldENhbCcpKGNhbGVuZGFyKTtcbiAgICAgICAgICAgIHZhciBjRGF0ZSA9IGNhbEluc3RhbmNlLmZyb21KRChkYXRlSkQpO1xuXG4gICAgICAgICAgICBpZihkTW9udGggJSAxMikgY2FsSW5zdGFuY2UuYWRkKGNEYXRlLCBkTW9udGgsICdtJyk7XG4gICAgICAgICAgICBlbHNlIGNhbEluc3RhbmNlLmFkZChjRGF0ZSwgZE1vbnRoIC8gMTIsICd5Jyk7XG5cbiAgICAgICAgICAgIHJldHVybiAoY0RhdGUudG9KRCgpIC0gRVBPQ0hKRCkgKiBPTkVEQVkgKyB0aW1lTXM7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgTG9nZ2Vycy5lcnJvcignaW52YWxpZCBtcyAnICsgbXMgKyAnIGluIGNhbGVuZGFyICcgKyBjYWxlbmRhcik7XG4gICAgICAgICAgICAvLyB0aGVuIGtlZXAgZ29pbmcgaW4gZ3JlZ29yaWFuIGV2ZW4gdGhvdWdoIHRoZSByZXN1bHQgd2lsbCBiZSAnSW52YWxpZCdcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB5ID0gbmV3IERhdGUobXMgKyBUSFJFRURBWVMpO1xuICAgIHJldHVybiB5LnNldFVUQ01vbnRoKHkuZ2V0VVRDTW9udGgoKSArIGRNb250aCkgKyB0aW1lTXMgLSBUSFJFRURBWVM7XG59O1xuXG4vKlxuICogZmluZEV4YWN0RGF0ZXM6IHdoYXQgZnJhY3Rpb24gb2YgZGF0YSBpcyBleGFjdCBkYXlzLCBtb250aHMsIG9yIHllYXJzP1xuICpcbiAqIGRhdGE6IGFycmF5IG9mIG1pbGxpc2Vjb25kIHZhbHVlc1xuICogY2FsZW5kYXIgKHN0cmluZykgdGhlIGNhbGVuZGFyIHRvIHRlc3QgYWdhaW5zdFxuICovXG5leHBvcnRzLmZpbmRFeGFjdERhdGVzID0gZnVuY3Rpb24oZGF0YSwgY2FsZW5kYXIpIHtcbiAgICB2YXIgZXhhY3RZZWFycyA9IDA7XG4gICAgdmFyIGV4YWN0TW9udGhzID0gMDtcbiAgICB2YXIgZXhhY3REYXlzID0gMDtcbiAgICB2YXIgYmxhbmtDb3VudCA9IDA7XG4gICAgdmFyIGQ7XG4gICAgdmFyIGRpO1xuXG4gICAgdmFyIGNhbEluc3RhbmNlID0gKFxuICAgICAgICBpc1dvcmxkQ2FsZW5kYXIoY2FsZW5kYXIpICYmXG4gICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2dldENhbCcpKGNhbGVuZGFyKVxuICAgICk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBkaSA9IGRhdGFbaV07XG5cbiAgICAgICAgLy8gbm90IGRhdGUgZGF0YSBhdCBhbGxcbiAgICAgICAgaWYoIWlzTnVtZXJpYyhkaSkpIHtcbiAgICAgICAgICAgIGJsYW5rQ291bnQgKys7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG5vdCBhbiBleGFjdCBkYXRlXG4gICAgICAgIGlmKGRpICUgT05FREFZKSBjb250aW51ZTtcblxuICAgICAgICBpZihjYWxJbnN0YW5jZSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBkID0gY2FsSW5zdGFuY2UuZnJvbUpEKGRpIC8gT05FREFZICsgRVBPQ0hKRCk7XG4gICAgICAgICAgICAgICAgaWYoZC5kYXkoKSA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICBpZihkLm1vbnRoKCkgPT09IDEpIGV4YWN0WWVhcnMrKztcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBleGFjdE1vbnRocysrO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBleGFjdERheXMrKztcbiAgICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgICAgIC8vIGludmFsaWQgZGF0ZSBpbiB0aGlzIGNhbGVuZGFyIC0gaWdub3JlIGl0IGhlcmUuXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkID0gbmV3IERhdGUoZGkpO1xuICAgICAgICAgICAgaWYoZC5nZXRVVENEYXRlKCkgPT09IDEpIHtcbiAgICAgICAgICAgICAgICBpZihkLmdldFVUQ01vbnRoKCkgPT09IDApIGV4YWN0WWVhcnMrKztcbiAgICAgICAgICAgICAgICBlbHNlIGV4YWN0TW9udGhzKys7XG4gICAgICAgICAgICB9IGVsc2UgZXhhY3REYXlzKys7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZXhhY3RNb250aHMgKz0gZXhhY3RZZWFycztcbiAgICBleGFjdERheXMgKz0gZXhhY3RNb250aHM7XG5cbiAgICB2YXIgZGF0YUNvdW50ID0gZGF0YS5sZW5ndGggLSBibGFua0NvdW50O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgZXhhY3RZZWFyczogZXhhY3RZZWFycyAvIGRhdGFDb3VudCxcbiAgICAgICAgZXhhY3RNb250aHM6IGV4YWN0TW9udGhzIC8gZGF0YUNvdW50LFxuICAgICAgICBleGFjdERheXM6IGV4YWN0RGF5cyAvIGRhdGFDb3VudFxuICAgIH07XG59O1xuXG59LHtcIi4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi9yZWdpc3RyeVwiOjg0NyxcIi4vbG9nZ2Vyc1wiOjcyMyxcIi4vbW9kXCI6NzI2LFwiZDNcIjoxNjMsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDcwODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgbG9nZ2VycyA9IF9kZXJlcV8oJy4vbG9nZ2VycycpO1xuXG4vKipcbiAqIEFsbG93IHJlZmVyZW5jaW5nIGEgZ3JhcGggRE9NIGVsZW1lbnQgZWl0aGVyIGRpcmVjdGx5XG4gKiBvciBieSBpdHMgaWQgc3RyaW5nXG4gKlxuICogQHBhcmFtIHtIVE1MRGl2RWxlbWVudHxzdHJpbmd9IGdkOiBhIGdyYXBoIGVsZW1lbnQgb3IgaXRzIGlkXG4gKlxuICogQHJldHVybnMge0hUTUxEaXZFbGVtZW50fSB0aGUgRE9NIGVsZW1lbnQgb2YgdGhlIGdyYXBoXG4gKi9cbmZ1bmN0aW9uIGdldEdyYXBoRGl2KGdkKSB7XG4gICAgdmFyIGdkRWxlbWVudDtcblxuICAgIGlmKHR5cGVvZiBnZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZ2RFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZ2QpO1xuXG4gICAgICAgIGlmKGdkRWxlbWVudCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBET00gZWxlbWVudCB3aXRoIGlkIFxcJycgKyBnZCArICdcXCcgZXhpc3RzIG9uIHRoZSBwYWdlLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGdkRWxlbWVudDtcbiAgICB9IGVsc2UgaWYoZ2QgPT09IG51bGwgfHwgZ2QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RPTSBlbGVtZW50IHByb3ZpZGVkIGlzIG51bGwgb3IgdW5kZWZpbmVkJyk7XG4gICAgfVxuXG4gICAgLy8gb3RoZXJ3aXNlIGFzc3VtZSB0aGF0IGdkIGlzIGEgRE9NIGVsZW1lbnRcbiAgICByZXR1cm4gZ2Q7XG59XG5cbmZ1bmN0aW9uIGlzUGxvdERpdihlbCkge1xuICAgIHZhciBlbDMgPSBkMy5zZWxlY3QoZWwpO1xuICAgIHJldHVybiBlbDMubm9kZSgpIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQgJiZcbiAgICAgICAgZWwzLnNpemUoKSAmJlxuICAgICAgICBlbDMuY2xhc3NlZCgnanMtcGxvdGx5LXBsb3QnKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlRWxlbWVudChlbCkge1xuICAgIHZhciBlbFBhcmVudCA9IGVsICYmIGVsLnBhcmVudE5vZGU7XG4gICAgaWYoZWxQYXJlbnQpIGVsUGFyZW50LnJlbW92ZUNoaWxkKGVsKTtcbn1cblxuLyoqXG4gKiBmb3IgZHluYW1pY2FsbHkgYWRkaW5nIHN0eWxlIHJ1bGVzXG4gKiBtYWtlcyBvbmUgc3R5bGVzaGVldCB0aGF0IGNvbnRhaW5zIGFsbCBydWxlcyBhZGRlZFxuICogYnkgYWxsIGNhbGxzIHRvIHRoaXMgZnVuY3Rpb25cbiAqL1xuZnVuY3Rpb24gYWRkU3R5bGVSdWxlKHNlbGVjdG9yLCBzdHlsZVN0cmluZykge1xuICAgIGFkZFJlbGF0ZWRTdHlsZVJ1bGUoJ2dsb2JhbCcsIHNlbGVjdG9yLCBzdHlsZVN0cmluZyk7XG59XG5cbi8qKlxuICogZm9yIGR5bmFtaWNhbGx5IGFkZGluZyBzdHlsZSBydWxlc1xuICogdG8gYSBzdHlsZXNoZWV0IHVuaXF1ZWx5IGlkZW50aWZpZWQgYnkgYSB1aWRcbiAqL1xuZnVuY3Rpb24gYWRkUmVsYXRlZFN0eWxlUnVsZSh1aWQsIHNlbGVjdG9yLCBzdHlsZVN0cmluZykge1xuICAgIHZhciBpZCA9ICdwbG90bHkuanMtc3R5bGUtJyArIHVpZDtcbiAgICB2YXIgc3R5bGUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCk7XG4gICAgaWYoIXN0eWxlKSB7XG4gICAgICAgIHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcbiAgICAgICAgc3R5bGUuc2V0QXR0cmlidXRlKCdpZCcsIGlkKTtcbiAgICAgICAgLy8gV2ViS2l0IGhhY2sgOihcbiAgICAgICAgc3R5bGUuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpKTtcbiAgICAgICAgZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzdHlsZSk7XG4gICAgfVxuICAgIHZhciBzdHlsZVNoZWV0ID0gc3R5bGUuc2hlZXQ7XG5cbiAgICBpZihzdHlsZVNoZWV0Lmluc2VydFJ1bGUpIHtcbiAgICAgICAgc3R5bGVTaGVldC5pbnNlcnRSdWxlKHNlbGVjdG9yICsgJ3snICsgc3R5bGVTdHJpbmcgKyAnfScsIDApO1xuICAgIH0gZWxzZSBpZihzdHlsZVNoZWV0LmFkZFJ1bGUpIHtcbiAgICAgICAgc3R5bGVTaGVldC5hZGRSdWxlKHNlbGVjdG9yLCBzdHlsZVN0cmluZywgMCk7XG4gICAgfSBlbHNlIGxvZ2dlcnMud2FybignYWRkU3R5bGVSdWxlIGZhaWxlZCcpO1xufVxuXG4vKipcbiAqIHRvIHJlbW92ZSBmcm9tIHRoZSBwYWdlIGEgc3R5bGVzaGVldCBpZGVudGlmaWVkIGJ5IGEgZ2l2ZW4gdWlkXG4gKi9cbmZ1bmN0aW9uIGRlbGV0ZVJlbGF0ZWRTdHlsZVJ1bGUodWlkKSB7XG4gICAgdmFyIGlkID0gJ3Bsb3RseS5qcy1zdHlsZS0nICsgdWlkO1xuICAgIHZhciBzdHlsZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKTtcbiAgICBpZihzdHlsZSkgcmVtb3ZlRWxlbWVudChzdHlsZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGdldEdyYXBoRGl2OiBnZXRHcmFwaERpdixcbiAgICBpc1Bsb3REaXY6IGlzUGxvdERpdixcbiAgICByZW1vdmVFbGVtZW50OiByZW1vdmVFbGVtZW50LFxuICAgIGFkZFN0eWxlUnVsZTogYWRkU3R5bGVSdWxlLFxuICAgIGFkZFJlbGF0ZWRTdHlsZVJ1bGU6IGFkZFJlbGF0ZWRTdHlsZVJ1bGUsXG4gICAgZGVsZXRlUmVsYXRlZFN0eWxlUnVsZTogZGVsZXRlUmVsYXRlZFN0eWxlUnVsZVxufTtcblxufSx7XCIuL2xvZ2dlcnNcIjo3MjMsXCJkM1wiOjE2M31dLDcwOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuLyogZ2xvYmFsIGpRdWVyeTpmYWxzZSAqL1xuXG52YXIgRXZlbnRFbWl0dGVyID0gX2RlcmVxXygnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuXG52YXIgRXZlbnRzID0ge1xuXG4gICAgaW5pdDogZnVuY3Rpb24ocGxvdE9iaikge1xuICAgICAgICAvKlxuICAgICAgICAgKiBJZiB3ZSBoYXZlIGFscmVhZHkgaW5zdGFudGlhdGVkIGFuIGVtaXR0ZXIgZm9yIHRoaXMgcGxvdFxuICAgICAgICAgKiByZXR1cm4gZWFybHkuXG4gICAgICAgICAqL1xuICAgICAgICBpZihwbG90T2JqLl9ldiBpbnN0YW5jZW9mIEV2ZW50RW1pdHRlcikgcmV0dXJuIHBsb3RPYmo7XG5cbiAgICAgICAgdmFyIGV2ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgICAgICB2YXIgaW50ZXJuYWxFdiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgICAgICAvKlxuICAgICAgICAgKiBBc3NpZ24gdG8gcGxvdC5fZXYgd2hpbGUgd2Ugc3RpbGwgbGl2ZSBpbiBhIGxhbmRcbiAgICAgICAgICogd2hlcmUgcGxvdCBpcyBhIERPTSBlbGVtZW50IHdpdGggc3R1ZmYgYXR0YWNoZWQgdG8gaXQuXG4gICAgICAgICAqIEluIHRoZSBmdXR1cmUgd2UgY2FuIG1ha2UgcGxvdCB0aGUgZXZlbnQgZW1pdHRlciBpdHNlbGYuXG4gICAgICAgICAqL1xuICAgICAgICBwbG90T2JqLl9ldiA9IGV2O1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIENyZWF0ZSBhIHNlY29uZCBldmVudCBoYW5kbGVyIHRoYXQgd2lsbCBtYW5hZ2UgZXZlbnRzICppbnRlcm5hbGx5Ki5cbiAgICAgICAgICogVGhpcyBhbGxvd3MgcGFydHMgb2YgcGxvdGx5IHRvIHJlc3BvbmQgdG8gdGhpbmcgbGlrZSByZWxheW91dCB3aXRob3V0XG4gICAgICAgICAqIGhhdmluZyB0byB1c2UgdGhlIHVzZXItZmFjaW5nIGV2ZW50IGhhbmRsZXIuIFRoZXkgY2Fubm90IHBlYWNlZnVsbHlcbiAgICAgICAgICogY29leGlzdCBvbiB0aGUgc2FtZSBoYW5kbGVyIGJlY2F1c2UgYSB1c2VyIGludm9raW5nXG4gICAgICAgICAqIHBsb3RPYmoucmVtb3ZlQWxsTGlzdGVuZXJzKCkgd291bGQgZGV0YWNoIGludGVybmFsIGV2ZW50cywgYnJlYWtpbmdcbiAgICAgICAgICogcGxvdGx5LlxuICAgICAgICAgKi9cbiAgICAgICAgcGxvdE9iai5faW50ZXJuYWxFdiA9IGludGVybmFsRXY7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogQXNzaWduIGJvdW5kIG1ldGhvZHMgZnJvbSB0aGUgZXYgdG8gdGhlIHBsb3Qgb2JqZWN0LiBUaGVzZSBtZXRob2RzXG4gICAgICAgICAqIHdpbGwgcmVmZXJlbmNlIHRoZSAndGhpcycgb2YgcGxvdC5fZXYgZXZlbiB0aG91Z2ggdGhleSBhcmUgbWV0aG9kc1xuICAgICAgICAgKiBvZiBwbG90LiBUaGlzIHdpbGwga2VlcCB0aGUgZXZlbnQgbWFjaGluZXJ5IGF3YXkgZnJvbSB0aGUgcGxvdCBvYmplY3RcbiAgICAgICAgICogd2hpY2ggY3VycmVudGx5IGlzIG9mdGVuIGEgRE9NIGVsZW1lbnQgYnV0IHByZXNlbnRzIGFuIEFQSSB0aGF0IHdpbGxcbiAgICAgICAgICogY29udGludWUgdG8gZnVuY3Rpb24gd2hlbiBwbG90IGJlY29tZXMgYW4gZW1pdHRlci4gTm90IGFsbCBFdmVudEVtaXR0ZXJcbiAgICAgICAgICogbWV0aG9kcyBoYXZlIGJlZW4gYm91bmQgdG8gYHBsb3RgIGFzIHNvbWUgZG8gbm90IGN1cnJlbnRseSBhZGQgdmFsdWUgdG9cbiAgICAgICAgICogdGhlIFBsb3RseSBldmVudCBBUEkuXG4gICAgICAgICAqL1xuICAgICAgICBwbG90T2JqLm9uID0gZXYub24uYmluZChldik7XG4gICAgICAgIHBsb3RPYmoub25jZSA9IGV2Lm9uY2UuYmluZChldik7XG4gICAgICAgIHBsb3RPYmoucmVtb3ZlTGlzdGVuZXIgPSBldi5yZW1vdmVMaXN0ZW5lci5iaW5kKGV2KTtcbiAgICAgICAgcGxvdE9iai5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBldi5yZW1vdmVBbGxMaXN0ZW5lcnMuYmluZChldik7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogQ3JlYXRlIGZ1bmN0aW9ucyBmb3IgbWFuYWdpbmcgaW50ZXJuYWwgZXZlbnRzLiBUaGVzZSBhcmUgKm9ubHkqIHRyaWdnZXJlZFxuICAgICAgICAgKiBieSB0aGUgbWlycm9yaW5nIG9mIGV4dGVybmFsIGV2ZW50cyB2aWEgdGhlIGVtaXQgZnVuY3Rpb24uXG4gICAgICAgICAqL1xuICAgICAgICBwbG90T2JqLl9pbnRlcm5hbE9uID0gaW50ZXJuYWxFdi5vbi5iaW5kKGludGVybmFsRXYpO1xuICAgICAgICBwbG90T2JqLl9pbnRlcm5hbE9uY2UgPSBpbnRlcm5hbEV2Lm9uY2UuYmluZChpbnRlcm5hbEV2KTtcbiAgICAgICAgcGxvdE9iai5fcmVtb3ZlSW50ZXJuYWxMaXN0ZW5lciA9IGludGVybmFsRXYucmVtb3ZlTGlzdGVuZXIuYmluZChpbnRlcm5hbEV2KTtcbiAgICAgICAgcGxvdE9iai5fcmVtb3ZlQWxsSW50ZXJuYWxMaXN0ZW5lcnMgPSBpbnRlcm5hbEV2LnJlbW92ZUFsbExpc3RlbmVycy5iaW5kKGludGVybmFsRXYpO1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIFdlIG11c3Qgd3JhcCBlbWl0IHRvIGNvbnRpbnVlIHRvIHN1cHBvcnQgSlF1ZXJ5IGV2ZW50cy4gVGhlIGlkZWFcbiAgICAgICAgICogaXMgdG8gY2hlY2sgdG8gc2VlIGlmIHRoZSB1c2VyIGlzIHVzaW5nIEpRdWVyeSBldmVudHMsIGlmIHRoZXkgYXJlXG4gICAgICAgICAqIHdlIGVtaXQgSlF1ZXJ5IGV2ZW50cyB0byB0cmlnZ2VyIHVzZXIgaGFuZGxlcnMgYXMgd2VsbCBhcyB0aGUgRXZlbnRFbWl0dGVyXG4gICAgICAgICAqIGV2ZW50cy5cbiAgICAgICAgICovXG4gICAgICAgIHBsb3RPYmouZW1pdCA9IGZ1bmN0aW9uKGV2ZW50LCBkYXRhKSB7XG4gICAgICAgICAgICBpZih0eXBlb2YgalF1ZXJ5ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGpRdWVyeShwbG90T2JqKS50cmlnZ2VyKGV2ZW50LCBkYXRhKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZXYuZW1pdChldmVudCwgZGF0YSk7XG4gICAgICAgICAgICBpbnRlcm5hbEV2LmVtaXQoZXZlbnQsIGRhdGEpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBwbG90T2JqO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gYmVoYXZlcyBsaWtlIGpRdWVyeSdzIHRyaWdnZXJIYW5kbGVyLiBJdCBjYWxsc1xuICAgICAqIGFsbCBoYW5kbGVycyBmb3IgYSBwYXJ0aWN1bGFyIGV2ZW50IGFuZCByZXR1cm5zIHRoZSByZXR1cm4gdmFsdWVcbiAgICAgKiBvZiB0aGUgTEFTVCBoYW5kbGVyLiBUaGlzIGZ1bmN0aW9uIGFsc28gdHJpZ2dlcnMgalF1ZXJ5J3NcbiAgICAgKiB0cmlnZ2VySGFuZGxlciBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuXG4gICAgICovXG4gICAgdHJpZ2dlckhhbmRsZXI6IGZ1bmN0aW9uKHBsb3RPYmosIGV2ZW50LCBkYXRhKSB7XG4gICAgICAgIHZhciBqUXVlcnlIYW5kbGVyVmFsdWU7XG4gICAgICAgIHZhciBub2RlRXZlbnRIYW5kbGVyVmFsdWU7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogSWYgalF1ZXJ5IGV4aXN0cyBydW4gYWxsIGl0cyBoYW5kbGVycyBmb3IgdGhpcyBldmVudCBhbmRcbiAgICAgICAgICogY29sbGVjdCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBMQVNUIGhhbmRsZXIgZnVuY3Rpb25cbiAgICAgICAgICovXG4gICAgICAgIGlmKHR5cGVvZiBqUXVlcnkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBqUXVlcnlIYW5kbGVyVmFsdWUgPSBqUXVlcnkocGxvdE9iaikudHJpZ2dlckhhbmRsZXIoZXZlbnQsIGRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgLypcbiAgICAgICAgICogTm93IHJ1biBhbGwgdGhlIG5vZGUgc3R5bGUgZXZlbnQgaGFuZGxlcnNcbiAgICAgICAgICovXG4gICAgICAgIHZhciBldiA9IHBsb3RPYmouX2V2O1xuICAgICAgICBpZighZXYpIHJldHVybiBqUXVlcnlIYW5kbGVyVmFsdWU7XG5cbiAgICAgICAgdmFyIGhhbmRsZXJzID0gZXYuX2V2ZW50c1tldmVudF07XG4gICAgICAgIGlmKCFoYW5kbGVycykgcmV0dXJuIGpRdWVyeUhhbmRsZXJWYWx1ZTtcblxuICAgICAgICAvLyBtYWtpbmcgc3VyZSAndGhpcycgaXMgdGhlIEV2ZW50RW1pdHRlciBpbnN0YW5jZVxuICAgICAgICBmdW5jdGlvbiBhcHBseShoYW5kbGVyKSB7XG4gICAgICAgICAgICAvLyBUaGUgJ29uY2UnIGNhc2UsIHdlIGNhbid0IGp1c3QgY2FsbCBoYW5kbGVyKCkgYXMgd2UgbmVlZFxuICAgICAgICAgICAgLy8gdGhlIHJldHVybiB2YWx1ZSBoZXJlLiBTbyxcbiAgICAgICAgICAgIC8vIC0gcmVtb3ZlIGhhbmRsZXJcbiAgICAgICAgICAgIC8vIC0gY2FsbCBsaXN0ZW5lciBhbmQgZ3JhYiByZXR1cm4gdmFsdWUhXG4gICAgICAgICAgICAvLyAtIHN0YXNoICdmaXJlZCcga2V5IHRvIG5vdCBjYWxsIGhhbmRsZXIgdHdpY2VcbiAgICAgICAgICAgIGlmKGhhbmRsZXIubGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICBldi5yZW1vdmVMaXN0ZW5lcihldmVudCwgaGFuZGxlci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgaWYoIWhhbmRsZXIuZmlyZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlci5maXJlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBoYW5kbGVyLmxpc3RlbmVyLmFwcGx5KGV2LCBbZGF0YV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZXIuYXBwbHkoZXYsIFtkYXRhXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBoYW5kbGVycyBjYW4gYmUgZnVuY3Rpb24gb3IgYW4gYXJyYXkgb2YgZnVuY3Rpb25zXG4gICAgICAgIGhhbmRsZXJzID0gQXJyYXkuaXNBcnJheShoYW5kbGVycykgPyBoYW5kbGVycyA6IFtoYW5kbGVyc107XG5cbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGhhbmRsZXJzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgYXBwbHkoaGFuZGxlcnNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIG5vdyBjYWxsIHRoZSBmaW5hbCBoYW5kbGVyIGFuZCBjb2xsZWN0IGl0cyB2YWx1ZVxuICAgICAgICBub2RlRXZlbnRIYW5kbGVyVmFsdWUgPSBhcHBseShoYW5kbGVyc1tpXSk7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogUmV0dXJuIGVpdGhlciB0aGUgalF1ZXJ5IGhhbmRsZXIgdmFsdWUgaWYgaXQgZXhpc3RzIG9yIHRoZVxuICAgICAgICAgKiBub2RlRXZlbnRIYW5kbGVyIHZhbHVlLiBqUXVlcnkgZXZlbnQgdmFsdWUgc3VwZXJzZWRlcyBub2RlanNcbiAgICAgICAgICogZXZlbnRzIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSByZWFzb25zLlxuICAgICAgICAgKi9cbiAgICAgICAgcmV0dXJuIGpRdWVyeUhhbmRsZXJWYWx1ZSAhPT0gdW5kZWZpbmVkID9cbiAgICAgICAgICAgIGpRdWVyeUhhbmRsZXJWYWx1ZSA6XG4gICAgICAgICAgICBub2RlRXZlbnRIYW5kbGVyVmFsdWU7XG4gICAgfSxcblxuICAgIHB1cmdlOiBmdW5jdGlvbihwbG90T2JqKSB7XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLl9ldjtcbiAgICAgICAgZGVsZXRlIHBsb3RPYmoub247XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLm9uY2U7XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLnJlbW92ZUxpc3RlbmVyO1xuICAgICAgICBkZWxldGUgcGxvdE9iai5yZW1vdmVBbGxMaXN0ZW5lcnM7XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLmVtaXQ7XG5cbiAgICAgICAgZGVsZXRlIHBsb3RPYmouX2V2O1xuICAgICAgICBkZWxldGUgcGxvdE9iai5faW50ZXJuYWxFdjtcbiAgICAgICAgZGVsZXRlIHBsb3RPYmouX2ludGVybmFsT247XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLl9pbnRlcm5hbE9uY2U7XG4gICAgICAgIGRlbGV0ZSBwbG90T2JqLl9yZW1vdmVJbnRlcm5hbExpc3RlbmVyO1xuICAgICAgICBkZWxldGUgcGxvdE9iai5fcmVtb3ZlQWxsSW50ZXJuYWxMaXN0ZW5lcnM7XG5cbiAgICAgICAgcmV0dXJuIHBsb3RPYmo7XG4gICAgfVxuXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50cztcblxufSx7XCJldmVudHNcIjoxMDR9XSw3MTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc1BsYWluT2JqZWN0ID0gX2RlcmVxXygnLi9pc19wbGFpbl9vYmplY3QuanMnKTtcbnZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcblxuZnVuY3Rpb24gcHJpbWl0aXZlc0xvb3BTcGxpY2Uoc291cmNlLCB0YXJnZXQpIHtcbiAgICB2YXIgaSwgdmFsdWU7XG4gICAgZm9yKGkgPSAwOyBpIDwgc291cmNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhbHVlID0gc291cmNlW2ldO1xuICAgICAgICBpZih2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YodmFsdWUpID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmKHZhbHVlICE9PSB2b2lkKDApKSB7XG4gICAgICAgICAgICB0YXJnZXRbaV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0cy5leHRlbmRGbGF0ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF9leHRlbmQoYXJndW1lbnRzLCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcbn07XG5cbmV4cG9ydHMuZXh0ZW5kRGVlcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfZXh0ZW5kKGFyZ3VtZW50cywgdHJ1ZSwgZmFsc2UsIGZhbHNlKTtcbn07XG5cbmV4cG9ydHMuZXh0ZW5kRGVlcEFsbCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfZXh0ZW5kKGFyZ3VtZW50cywgdHJ1ZSwgdHJ1ZSwgZmFsc2UpO1xufTtcblxuZXhwb3J0cy5leHRlbmREZWVwTm9BcnJheXMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gX2V4dGVuZChhcmd1bWVudHMsIHRydWUsIGZhbHNlLCB0cnVlKTtcbn07XG5cbi8qXG4gKiBJbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vanVzdG1vb24vbm9kZS1leHRlbmQvYmxvYi9tYXN0ZXIvaW5kZXguanNcbiAqIEFsbCBjcmVkaXQgdG8gdGhlIGpRdWVyeSBhdXRob3JzIGZvciBwZXJmZWN0aW5nIHRoaXMgYW1hemluZyB1dGlsaXR5LlxuICpcbiAqIEFQSSBkaWZmZXJlbmNlIHdpdGggalF1ZXJ5IHZlcnNpb246XG4gKiAtIE5vIG9wdGlvbmFsIGJvb2xlYW4gKHRydWUgLT4gZGVlcCBleHRlbmQpIGZpcnN0IGFyZ3VtZW50LFxuICogICB1c2UgYGV4dGVuZEZsYXRgIGZvciBmaXJzdC1sZXZlbCBvbmx5IGV4dGVuZCBhbmRcbiAqICAgdXNlIGBleHRlbmREZWVwYCBmb3IgYSBkZWVwIGV4dGVuZC5cbiAqXG4gKiBPdGhlciBkaWZmZXJlbmNlcyB3aXRoIGpRdWVyeSB2ZXJzaW9uOlxuICogLSBVc2VzIGEgbW9kZXJuIChhbmQgZmFzdGVyKSBpc1BsYWluT2JqZWN0IHJvdXRpbmUuXG4gKiAtIEV4cGVjdGVkIHRvIHdvcmsgd2l0aCBvYmplY3Qge30gYW5kIGFycmF5IFtdIGFyZ3VtZW50cyBvbmx5LlxuICogLSBEb2VzIG5vdCBjaGVjayBmb3IgY2lyY3VsYXIgc3RydWN0dXJlLlxuICogICBGWUk6IGpRdWVyeSBvbmx5IGRvZXMgYSBjaGVjayBhY3Jvc3Mgb25lIGxldmVsLlxuICogICBXYXJuaW5nOiB0aGlzIG1pZ2h0IHJlc3VsdCBpbiBpbmZpbml0ZSBsb29wcy5cbiAqXG4gKi9cbmZ1bmN0aW9uIF9leHRlbmQoaW5wdXRzLCBpc0RlZXAsIGtlZXBBbGxLZXlzLCBub0FycmF5Q29waWVzKSB7XG4gICAgdmFyIHRhcmdldCA9IGlucHV0c1swXTtcbiAgICB2YXIgbGVuZ3RoID0gaW5wdXRzLmxlbmd0aDtcblxuICAgIHZhciBpbnB1dCwga2V5LCBzcmMsIGNvcHksIGNvcHlJc0FycmF5LCBjbG9uZSwgYWxsUHJpbWl0aXZlcztcblxuICAgIC8vIFRPRE8gZG9lcyB0aGlzIGRvIHRoZSByaWdodCB0aGluZyBmb3IgdHlwZWQgYXJyYXlzP1xuXG4gICAgaWYobGVuZ3RoID09PSAyICYmIGlzQXJyYXkodGFyZ2V0KSAmJiBpc0FycmF5KGlucHV0c1sxXSkgJiYgdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBhbGxQcmltaXRpdmVzID0gcHJpbWl0aXZlc0xvb3BTcGxpY2UoaW5wdXRzWzFdLCB0YXJnZXQpO1xuXG4gICAgICAgIGlmKGFsbFByaW1pdGl2ZXMpIHtcbiAgICAgICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0YXJnZXQuc3BsaWNlKDAsIHRhcmdldC5sZW5ndGgpOyAvLyByZXNldCB0YXJnZXQgYW5kIGNvbnRpbnVlIHRvIG5leHQgYmxvY2tcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDE7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBpbnB1dCA9IGlucHV0c1tpXTtcblxuICAgICAgICBmb3Ioa2V5IGluIGlucHV0KSB7XG4gICAgICAgICAgICBzcmMgPSB0YXJnZXRba2V5XTtcbiAgICAgICAgICAgIGNvcHkgPSBpbnB1dFtrZXldO1xuXG4gICAgICAgICAgICBpZihub0FycmF5Q29waWVzICYmIGlzQXJyYXkoY29weSkpIHtcbiAgICAgICAgICAgICAgICAvLyBTdG9wIGVhcmx5IGFuZCBqdXN0IHRyYW5zZmVyIHRoZSBhcnJheSBpZiBhcnJheSBjb3BpZXMgYXJlIGRpc2FsbG93ZWQ6XG5cbiAgICAgICAgICAgICAgICB0YXJnZXRba2V5XSA9IGNvcHk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoaXNEZWVwICYmIGNvcHkgJiYgKGlzUGxhaW5PYmplY3QoY29weSkgfHwgKGNvcHlJc0FycmF5ID0gaXNBcnJheShjb3B5KSkpKSB7XG4gICAgICAgICAgICAgICAgLy8gcmVjdXJzZSBpZiB3ZSdyZSBtZXJnaW5nIHBsYWluIG9iamVjdHMgb3IgYXJyYXlzXG5cbiAgICAgICAgICAgICAgICBpZihjb3B5SXNBcnJheSkge1xuICAgICAgICAgICAgICAgICAgICBjb3B5SXNBcnJheSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBjbG9uZSA9IHNyYyAmJiBpc0FycmF5KHNyYykgPyBzcmMgOiBbXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjbG9uZSA9IHNyYyAmJiBpc1BsYWluT2JqZWN0KHNyYykgPyBzcmMgOiB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBuZXZlciBtb3ZlIG9yaWdpbmFsIG9iamVjdHMsIGNsb25lIHRoZW1cbiAgICAgICAgICAgICAgICB0YXJnZXRba2V5XSA9IF9leHRlbmQoW2Nsb25lLCBjb3B5XSwgaXNEZWVwLCBrZWVwQWxsS2V5cywgbm9BcnJheUNvcGllcyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYodHlwZW9mIGNvcHkgIT09ICd1bmRlZmluZWQnIHx8IGtlZXBBbGxLZXlzKSB7XG4gICAgICAgICAgICAgICAgLy8gZG9uJ3QgYnJpbmcgaW4gdW5kZWZpbmVkIHZhbHVlcywgZXhjZXB0IGZvciBleHRlbmREZWVwQWxsXG5cbiAgICAgICAgICAgICAgICB0YXJnZXRba2V5XSA9IGNvcHk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGFyZ2V0O1xufVxuXG59LHtcIi4vaXNfcGxhaW5fb2JqZWN0LmpzXCI6NzIwfV0sNzExOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbi8qKlxuICogUmV0dXJuIG5ld3MgYXJyYXkgY29udGFpbmluZyBvbmx5IHRoZSB1bmlxdWUgaXRlbXNcbiAqIGZvdW5kIGluIGlucHV0IGFycmF5LlxuICpcbiAqIElNUE9SVEFOVDogTm90ZSB0aGF0IGl0ZW1zIGFyZSBjb25zaWRlcmVkIHVuaXF1ZVxuICogaWYgYFN0cmluZyh7fSlgIGlzIHVuaXF1ZS4gRm9yIGV4YW1wbGU7XG4gKlxuICogIExpYi5maWx0ZXJVbmlxdWUoWyB7IGE6IDEgfSwgeyBiOiAyIH0gXSlcbiAqXG4gKiAgcmV0dXJucyBbeyBhOiAxIH1dXG4gKlxuICogYW5kXG4gKlxuICogIExpYi5maWx0ZXJVbmlxdWUoWyAnMScsIDEgXSlcbiAqXG4gKiAgcmV0dXJucyBbJzEnXVxuICpcbiAqXG4gKiBAcGFyYW0ge2FycmF5fSBhcnJheSBiYXNlIGFycmF5XG4gKiBAcmV0dXJuIHthcnJheX0gbmV3IGZpbHRlcmVkIGFycmF5XG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZmlsdGVyVW5pcXVlKGFycmF5KSB7XG4gICAgdmFyIHNlZW4gPSB7fTtcbiAgICB2YXIgb3V0ID0gW107XG4gICAgdmFyIGogPSAwO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpdGVtID0gYXJyYXlbaV07XG5cbiAgICAgICAgaWYoc2VlbltpdGVtXSAhPT0gMSkge1xuICAgICAgICAgICAgc2VlbltpdGVtXSA9IDE7XG4gICAgICAgICAgICBvdXRbaisrXSA9IGl0ZW07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxufSx7fV0sNzEyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLyoqIEZpbHRlciBvdXQgb2JqZWN0IGl0ZW1zIHdpdGggdmlzaWJsZSAhPT0gdHJ1ZVxuICogIGluc2lkZXIgYXJyYXkgY29udGFpbmVyLlxuICpcbiAqICBAcGFyYW0ge2FycmF5IG9mIG9iamVjdHN9IGNvbnRhaW5lclxuICogIEByZXR1cm4ge2FycmF5IG9mIG9iamVjdHN9IG9mIGxlbmd0aCA8PSBjb250YWluZXJcbiAqXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZmlsdGVyVmlzaWJsZShjb250YWluZXIpIHtcbiAgICB2YXIgZmlsdGVyRm4gPSBpc0NhbGNEYXRhKGNvbnRhaW5lcikgPyBjYWxjRGF0YUZpbHRlciA6IGJhc2VGaWx0ZXI7XG4gICAgdmFyIG91dCA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNvbnRhaW5lci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaXRlbSA9IGNvbnRhaW5lcltpXTtcbiAgICAgICAgaWYoZmlsdGVyRm4oaXRlbSkpIG91dC5wdXNoKGl0ZW0pO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG5mdW5jdGlvbiBiYXNlRmlsdGVyKGl0ZW0pIHtcbiAgICByZXR1cm4gaXRlbS52aXNpYmxlID09PSB0cnVlO1xufVxuXG5mdW5jdGlvbiBjYWxjRGF0YUZpbHRlcihpdGVtKSB7XG4gICAgdmFyIHRyYWNlID0gaXRlbVswXS50cmFjZTtcbiAgICByZXR1cm4gdHJhY2UudmlzaWJsZSA9PT0gdHJ1ZSAmJiB0cmFjZS5fbGVuZ3RoICE9PSAwO1xufVxuXG5mdW5jdGlvbiBpc0NhbGNEYXRhKGNvbnQpIHtcbiAgICByZXR1cm4gKFxuICAgICAgICBBcnJheS5pc0FycmF5KGNvbnQpICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkoY29udFswXSkgJiZcbiAgICAgICAgY29udFswXVswXSAmJlxuICAgICAgICBjb250WzBdWzBdLnRyYWNlXG4gICAgKTtcbn1cblxufSx7fV0sNzEzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvdW50cnlSZWdleCA9IF9kZXJlcV8oJ2NvdW50cnktcmVnZXgnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcblxuLy8gbWFrZSBsaXN0IG9mIGFsbCBjb3VudHJ5IGlzbzMgaWRzIGZyb20gYXQgcnVudGltZVxudmFyIGNvdW50cnlJZHMgPSBPYmplY3Qua2V5cyhjb3VudHJ5UmVnZXgpO1xuXG52YXIgbG9jYXRpb25tb2RlVG9JZEZpbmRlciA9IHtcbiAgICAnSVNPLTMnOiBMaWIuaWRlbnRpdHksXG4gICAgJ1VTQS1zdGF0ZXMnOiBMaWIuaWRlbnRpdHksXG4gICAgJ2NvdW50cnkgbmFtZXMnOiBjb3VudHJ5TmFtZVRvSVNPM1xufTtcblxuZnVuY3Rpb24gY291bnRyeU5hbWVUb0lTTzMoY291bnRyeU5hbWUpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY291bnRyeUlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaXNvMyA9IGNvdW50cnlJZHNbaV07XG4gICAgICAgIHZhciByZWdleCA9IG5ldyBSZWdFeHAoY291bnRyeVJlZ2V4W2lzbzNdKTtcblxuICAgICAgICBpZihyZWdleC50ZXN0KGNvdW50cnlOYW1lLnRyaW0oKS50b0xvd2VyQ2FzZSgpKSkgcmV0dXJuIGlzbzM7XG4gICAgfVxuXG4gICAgTGliLmxvZygnVW5yZWNvZ25pemVkIGNvdW50cnkgbmFtZTogJyArIGNvdW50cnlOYW1lICsgJy4nKTtcblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gbG9jYXRpb25Ub0ZlYXR1cmUobG9jYXRpb25tb2RlLCBsb2NhdGlvbiwgZmVhdHVyZXMpIHtcbiAgICBpZighbG9jYXRpb24gfHwgdHlwZW9mIGxvY2F0aW9uICE9PSAnc3RyaW5nJykgcmV0dXJuIGZhbHNlO1xuXG4gICAgdmFyIGxvY2F0aW9uSWQgPSBsb2NhdGlvbm1vZGVUb0lkRmluZGVyW2xvY2F0aW9ubW9kZV0obG9jYXRpb24pO1xuICAgIHZhciBmaWx0ZXJlZEZlYXR1cmVzO1xuICAgIHZhciBmLCBpO1xuXG4gICAgaWYobG9jYXRpb25JZCkge1xuICAgICAgICBpZihsb2NhdGlvbm1vZGUgPT09ICdVU0Etc3RhdGVzJykge1xuICAgICAgICAgICAgLy8gRmlsdGVyIG91dCBmZWF0dXJlcyBvdXQgaW4gVVNBXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBpbXBvcnRhbnQgYXMgdGhlIE5hdHVyYWwgRWFydGggZmlsZXNcbiAgICAgICAgICAgIC8vIGluY2x1ZGUgc3RhdGUvcHJvdmluY2VzIGZyb20gVVNBLCBDYW5hZGEsIEF1c3RyYWxpYSBhbmQgQnJhemlsXG4gICAgICAgICAgICAvLyB3aGljaCBoYXZlIHNvbWUgb3ZlcmxheSBpbiB0aGVpciB0d28tbGV0dGVyIGlkcy4gRm9yIGV4YW1wbGUsXG4gICAgICAgICAgICAvLyAnV0EnIGlzIHVzZWQgZm9yIGJvdGggV2FzaGluZ3RvbiBzdGF0ZSBhbmQgV2VzdGVybiBBdXN0cmFsaWEuXG4gICAgICAgICAgICBmaWx0ZXJlZEZlYXR1cmVzID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBmZWF0dXJlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGYgPSBmZWF0dXJlc1tpXTtcbiAgICAgICAgICAgICAgICBpZihmLnByb3BlcnRpZXMgJiYgZi5wcm9wZXJ0aWVzLmd1ICYmIGYucHJvcGVydGllcy5ndSA9PT0gJ1VTQScpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyZWRGZWF0dXJlcy5wdXNoKGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZpbHRlcmVkRmVhdHVyZXMgPSBmZWF0dXJlcztcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGZpbHRlcmVkRmVhdHVyZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGYgPSBmaWx0ZXJlZEZlYXR1cmVzW2ldO1xuICAgICAgICAgICAgaWYoZi5pZCA9PT0gbG9jYXRpb25JZCkgcmV0dXJuIGY7XG4gICAgICAgIH1cblxuICAgICAgICBMaWIubG9nKFtcbiAgICAgICAgICAgICdMb2NhdGlvbiB3aXRoIGlkJywgbG9jYXRpb25JZCxcbiAgICAgICAgICAgICdkb2VzIG5vdCBoYXZlIGEgbWF0Y2hpbmcgdG9wb2pzb24gZmVhdHVyZSBhdCB0aGlzIHJlc29sdXRpb24uJ1xuICAgICAgICBdLmpvaW4oJyAnKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBsb2NhdGlvblRvRmVhdHVyZTogbG9jYXRpb25Ub0ZlYXR1cmVcbn07XG5cbn0se1wiLi4vbGliXCI6NzE5LFwiY291bnRyeS1yZWdleFwiOjEzNH1dLDcxNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEJBRE5VTSA9IF9kZXJlcV8oJy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbi8qKlxuICogQ29udmVydCBjYWxjVHJhY2UgdG8gR2VvSlNPTiAnTXVsdGlMaW5lU3RyaW5nJyBjb29yZGluYXRlIGFycmF5c1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBjYWxjVHJhY2VcbiAqICBnZC5jYWxjZGF0YSBpdGVtLlxuICogIE5vdGUgdGhhdCBjYWxjVHJhY2VbaV0ubG9ubGF0IGlzIGFzc3VtZWQgdG8gYmUgZGVmaW5lZFxuICpcbiAqIEByZXR1cm4ge2FycmF5fVxuICogIHJldHVybiBsaW5lIGNvb3JkcyBhcnJheSAob3IgYXJyYXkgb2YgYXJyYXlzKVxuICpcbiAqL1xuZXhwb3J0cy5jYWxjVHJhY2VUb0xpbmVDb29yZHMgPSBmdW5jdGlvbihjYWxjVHJhY2UpIHtcbiAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG4gICAgdmFyIGNvbm5lY3RnYXBzID0gdHJhY2UuY29ubmVjdGdhcHM7XG5cbiAgICB2YXIgY29vcmRzID0gW107XG4gICAgdmFyIGxpbmVTdHJpbmcgPSBbXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjVHJhY2UubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNQdCA9IGNhbGNUcmFjZVtpXTtcbiAgICAgICAgdmFyIGxvbmxhdCA9IGNhbGNQdC5sb25sYXQ7XG5cbiAgICAgICAgaWYobG9ubGF0WzBdICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgIGxpbmVTdHJpbmcucHVzaChsb25sYXQpO1xuICAgICAgICB9IGVsc2UgaWYoIWNvbm5lY3RnYXBzICYmIGxpbmVTdHJpbmcubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29vcmRzLnB1c2gobGluZVN0cmluZyk7XG4gICAgICAgICAgICBsaW5lU3RyaW5nID0gW107XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihsaW5lU3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29vcmRzLnB1c2gobGluZVN0cmluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvb3Jkcztcbn07XG5cblxuLyoqXG4gKiBNYWtlIGxpbmUgKCdMaW5lU3RyaW5nJyBvciAnTXVsdGlMaW5lU3RyaW5nJykgR2VvSlNPTlxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGNvb3Jkc1xuICogIHJlc3VsdHMgZm9ybSBjYWxjVHJhY2VUb0xpbmVDb29yZHNcbiAqIEByZXR1cm4ge29iamVjdH0gb3V0XG4gKiAgR2VvSlNPTiBvYmplY3RcbiAqXG4gKi9cbmV4cG9ydHMubWFrZUxpbmUgPSBmdW5jdGlvbihjb29yZHMpIHtcbiAgICBpZihjb29yZHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0eXBlOiAnTGluZVN0cmluZycsXG4gICAgICAgICAgICBjb29yZGluYXRlczogY29vcmRzWzBdXG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6ICdNdWx0aUxpbmVTdHJpbmcnLFxuICAgICAgICAgICAgY29vcmRpbmF0ZXM6IGNvb3Jkc1xuICAgICAgICB9O1xuICAgIH1cbn07XG5cbi8qKlxuICogTWFrZSBwb2x5Z29uICgnUG9seWdvbicgb3IgJ011bHRpUG9seWdvbicpIEdlb0pTT05cbiAqXG4gKiBAcGFyYW0ge2FycmF5fSBjb29yZHNcbiAqICByZXN1bHRzIGZvcm0gY2FsY1RyYWNlVG9MaW5lQ29vcmRzXG4gKiBAcmV0dXJuIHtvYmplY3R9IG91dFxuICogIEdlb0pTT04gb2JqZWN0XG4gKi9cbmV4cG9ydHMubWFrZVBvbHlnb24gPSBmdW5jdGlvbihjb29yZHMpIHtcbiAgICBpZihjb29yZHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0eXBlOiAnUG9seWdvbicsXG4gICAgICAgICAgICBjb29yZGluYXRlczogY29vcmRzXG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIF9jb29yZHMgPSBuZXcgQXJyYXkoY29vcmRzLmxlbmd0aCk7XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgX2Nvb3Jkc1tpXSA9IFtjb29yZHNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6ICdNdWx0aVBvbHlnb24nLFxuICAgICAgICAgICAgY29vcmRpbmF0ZXM6IF9jb29yZHNcbiAgICAgICAgfTtcbiAgICB9XG59O1xuXG4vKipcbiAqIE1ha2UgYmxhbmsgR2VvSlNPTlxuICpcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqICBCbGFuayBHZW9KU09OIG9iamVjdFxuICpcbiAqL1xuZXhwb3J0cy5tYWtlQmxhbmsgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiAnUG9pbnQnLFxuICAgICAgICBjb29yZGluYXRlczogW11cbiAgICB9O1xufTtcblxufSx7XCIuLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1fV0sNzE1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG1vZCA9IF9kZXJlcV8oJy4vbW9kJykubW9kO1xuXG4vKlxuICogbG9vayBmb3IgaW50ZXJzZWN0aW9uIG9mIHR3byBsaW5lIHNlZ21lbnRzXG4gKiAgICgxLT4yIGFuZCAzLT40KSAtIHJldHVybnMgYXJyYXkgW3gseV0gaWYgdGhleSBkbywgbnVsbCBpZiBub3RcbiAqL1xuZXhwb3J0cy5zZWdtZW50c0ludGVyc2VjdCA9IHNlZ21lbnRzSW50ZXJzZWN0O1xuZnVuY3Rpb24gc2VnbWVudHNJbnRlcnNlY3QoeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgeDQsIHk0KSB7XG4gICAgdmFyIGEgPSB4MiAtIHgxO1xuICAgIHZhciBiID0geDMgLSB4MTtcbiAgICB2YXIgYyA9IHg0IC0geDM7XG4gICAgdmFyIGQgPSB5MiAtIHkxO1xuICAgIHZhciBlID0geTMgLSB5MTtcbiAgICB2YXIgZiA9IHk0IC0geTM7XG4gICAgdmFyIGRldCA9IGEgKiBmIC0gYyAqIGQ7XG4gICAgLy8gcGFyYWxsZWwgbGluZXM/IGludGVyc2VjdGlvbiBpcyB1bmRlZmluZWRcbiAgICAvLyBpZ25vcmUgdGhlIGNhc2Ugd2hlcmUgdGhleSBhcmUgY29saW5lYXJcbiAgICBpZihkZXQgPT09IDApIHJldHVybiBudWxsO1xuICAgIHZhciB0ID0gKGIgKiBmIC0gYyAqIGUpIC8gZGV0O1xuICAgIHZhciB1ID0gKGIgKiBkIC0gYSAqIGUpIC8gZGV0O1xuICAgIC8vIHNlZ21lbnRzIGRvIG5vdCBpbnRlcnNlY3Q/XG4gICAgaWYodSA8IDAgfHwgdSA+IDEgfHwgdCA8IDAgfHwgdCA+IDEpIHJldHVybiBudWxsO1xuXG4gICAgcmV0dXJuIHt4OiB4MSArIGEgKiB0LCB5OiB5MSArIGQgKiB0fTtcbn1cblxuLypcbiAqIGZpbmQgdGhlIG1pbmltdW0gZGlzdGFuY2UgYmV0d2VlbiB0d28gbGluZSBzZWdtZW50cyAoMS0+MiBhbmQgMy0+NClcbiAqL1xuZXhwb3J0cy5zZWdtZW50RGlzdGFuY2UgPSBmdW5jdGlvbiBzZWdtZW50RGlzdGFuY2UoeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgeDQsIHk0KSB7XG4gICAgaWYoc2VnbWVudHNJbnRlcnNlY3QoeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgeDQsIHk0KSkgcmV0dXJuIDA7XG5cbiAgICAvLyB0aGUgdHdvIHNlZ21lbnRzIGFuZCB0aGVpciBsZW5ndGhzIHNxdWFyZWRcbiAgICB2YXIgeDEyID0geDIgLSB4MTtcbiAgICB2YXIgeTEyID0geTIgLSB5MTtcbiAgICB2YXIgeDM0ID0geDQgLSB4MztcbiAgICB2YXIgeTM0ID0geTQgLSB5MztcbiAgICB2YXIgbGwxMiA9IHgxMiAqIHgxMiArIHkxMiAqIHkxMjtcbiAgICB2YXIgbGwzNCA9IHgzNCAqIHgzNCArIHkzNCAqIHkzNDtcblxuICAgIC8vIGNhbGN1bGF0ZSBkaXN0YW5jZSBzcXVhcmVkLCB0aGVuIHRha2UgdGhlIHNxcnQgYXQgdGhlIHZlcnkgZW5kXG4gICAgdmFyIGRpc3QyID0gTWF0aC5taW4oXG4gICAgICAgIHBlcnBEaXN0YW5jZTIoeDEyLCB5MTIsIGxsMTIsIHgzIC0geDEsIHkzIC0geTEpLFxuICAgICAgICBwZXJwRGlzdGFuY2UyKHgxMiwgeTEyLCBsbDEyLCB4NCAtIHgxLCB5NCAtIHkxKSxcbiAgICAgICAgcGVycERpc3RhbmNlMih4MzQsIHkzNCwgbGwzNCwgeDEgLSB4MywgeTEgLSB5MyksXG4gICAgICAgIHBlcnBEaXN0YW5jZTIoeDM0LCB5MzQsIGxsMzQsIHgyIC0geDMsIHkyIC0geTMpXG4gICAgKTtcblxuICAgIHJldHVybiBNYXRoLnNxcnQoZGlzdDIpO1xufTtcblxuLypcbiAqIGRpc3RhbmNlIHNxdWFyZWQgZnJvbSBzZWdtZW50IGFiIHRvIHBvaW50IGNcbiAqIFt4YWIsIHlhYl0gaXMgdGhlIHZlY3RvciBiLWFcbiAqIFt4YWMsIHlhY10gaXMgdGhlIHZlY3RvciBjLWFcbiAqIGxsYWIgaXMgdGhlIGxlbmd0aCBzcXVhcmVkIG9mIChiLWEpLCBqdXN0IHRvIHNpbXBsaWZ5IGNhbGN1bGF0aW9uXG4gKi9cbmZ1bmN0aW9uIHBlcnBEaXN0YW5jZTIoeGFiLCB5YWIsIGxsYWIsIHhhYywgeWFjKSB7XG4gICAgdmFyIGZjQUIgPSAoeGFjICogeGFiICsgeWFjICogeWFiKTtcbiAgICBpZihmY0FCIDwgMCkge1xuICAgICAgICAvLyBwb2ludCBjIGlzIGNsb3NlciB0byBwb2ludCBhXG4gICAgICAgIHJldHVybiB4YWMgKiB4YWMgKyB5YWMgKiB5YWM7XG4gICAgfSBlbHNlIGlmKGZjQUIgPiBsbGFiKSB7XG4gICAgICAgIC8vIHBvaW50IGMgaXMgY2xvc2VyIHRvIHBvaW50IGJcbiAgICAgICAgdmFyIHhiYyA9IHhhYyAtIHhhYjtcbiAgICAgICAgdmFyIHliYyA9IHlhYyAtIHlhYjtcbiAgICAgICAgcmV0dXJuIHhiYyAqIHhiYyArIHliYyAqIHliYztcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBwZXJwZW5kaWN1bGFyIGRpc3RhbmNlIGlzIHRoZSBzaG9ydGVzdFxuICAgICAgICB2YXIgY3Jvc3NQcm9kdWN0ID0geGFjICogeWFiIC0geWFjICogeGFiO1xuICAgICAgICByZXR1cm4gY3Jvc3NQcm9kdWN0ICogY3Jvc3NQcm9kdWN0IC8gbGxhYjtcbiAgICB9XG59XG5cbi8vIGEgdmVyeSBzaG9ydC10ZXJtIGNhY2hlIGZvciBnZXRUZXh0TG9jYXRpb24sIGp1c3QgYmVjYXVzZVxuLy8gd2UncmUgb2Z0ZW4gbG9vcGluZyBvdmVyIHRoZSBzYW1lIGxvY2F0aW9ucyBtdWx0aXBsZSB0aW1lc1xuLy8gaW52YWxpZGF0ZWQgYXMgc29vbiBhcyB3ZSBsb29rIGF0IGEgZGlmZmVyZW50IHBhdGhcbnZhciBsb2NhdGlvbkNhY2hlLCB3b3JraW5nUGF0aCwgd29ya2luZ1RleHRXaWR0aDtcblxuLy8gdHVybiBhIHBhdGggYW5kIHBvc2l0aW9uIGFsb25nIGl0IGludG8geCwgeSwgYW5kIGFuZ2xlIGZvciB0aGUgZ2l2ZW4gdGV4dFxuZXhwb3J0cy5nZXRUZXh0TG9jYXRpb24gPSBmdW5jdGlvbiBnZXRUZXh0TG9jYXRpb24ocGF0aCwgdG90YWxQYXRoTGVuLCBwb3NpdGlvbk9uUGF0aCwgdGV4dFdpZHRoKSB7XG4gICAgaWYocGF0aCAhPT0gd29ya2luZ1BhdGggfHwgdGV4dFdpZHRoICE9PSB3b3JraW5nVGV4dFdpZHRoKSB7XG4gICAgICAgIGxvY2F0aW9uQ2FjaGUgPSB7fTtcbiAgICAgICAgd29ya2luZ1BhdGggPSBwYXRoO1xuICAgICAgICB3b3JraW5nVGV4dFdpZHRoID0gdGV4dFdpZHRoO1xuICAgIH1cbiAgICBpZihsb2NhdGlvbkNhY2hlW3Bvc2l0aW9uT25QYXRoXSkge1xuICAgICAgICByZXR1cm4gbG9jYXRpb25DYWNoZVtwb3NpdGlvbk9uUGF0aF07XG4gICAgfVxuXG4gICAgLy8gZm9yIHRoZSBhbmdsZSwgdXNlIHBvaW50cyBvbiB0aGUgcGF0aCBzZXBhcmF0ZWQgYnkgdGhlIHRleHQgd2lkdGhcbiAgICAvLyBldmVuIHRob3VnaCBkdWUgdG8gY3VydmF0dXJlLCB0aGUgdGV4dCB3aWxsIGNvdmVyIGEgYml0IG1vcmUgdGhhbiB0aGF0XG4gICAgdmFyIHAwID0gcGF0aC5nZXRQb2ludEF0TGVuZ3RoKG1vZChwb3NpdGlvbk9uUGF0aCAtIHRleHRXaWR0aCAvIDIsIHRvdGFsUGF0aExlbikpO1xuICAgIHZhciBwMSA9IHBhdGguZ2V0UG9pbnRBdExlbmd0aChtb2QocG9zaXRpb25PblBhdGggKyB0ZXh0V2lkdGggLyAyLCB0b3RhbFBhdGhMZW4pKTtcbiAgICAvLyBub3RlOiBhdGFuIGhhbmRsZXMgMS8wIG5pY2VseVxuICAgIHZhciB0aGV0YSA9IE1hdGguYXRhbigocDEueSAtIHAwLnkpIC8gKHAxLnggLSBwMC54KSk7XG4gICAgLy8gY2VudGVyIHRoZSB0ZXh0IGF0IDIvMyBvZiB0aGUgY2VudGVyIHBvc2l0aW9uIHBsdXMgMS8zIHRoZSBwMC9wMSBtaWRwb2ludFxuICAgIC8vIHRoYXQncyB0aGUgYXZlcmFnZSBwb3NpdGlvbiBvZiB0aGlzIHNlZ21lbnQsIGFzc3VtaW5nIGl0J3Mgcm91Z2hseSBxdWFkcmF0aWNcbiAgICB2YXIgcENlbnRlciA9IHBhdGguZ2V0UG9pbnRBdExlbmd0aChtb2QocG9zaXRpb25PblBhdGgsIHRvdGFsUGF0aExlbikpO1xuICAgIHZhciB4ID0gKHBDZW50ZXIueCAqIDQgKyBwMC54ICsgcDEueCkgLyA2O1xuICAgIHZhciB5ID0gKHBDZW50ZXIueSAqIDQgKyBwMC55ICsgcDEueSkgLyA2O1xuXG4gICAgdmFyIG91dCA9IHt4OiB4LCB5OiB5LCB0aGV0YTogdGhldGF9O1xuICAgIGxvY2F0aW9uQ2FjaGVbcG9zaXRpb25PblBhdGhdID0gb3V0O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG5leHBvcnRzLmNsZWFyTG9jYXRpb25DYWNoZSA9IGZ1bmN0aW9uKCkge1xuICAgIHdvcmtpbmdQYXRoID0gbnVsbDtcbn07XG5cbi8qXG4gKiBGaW5kIHRoZSBzZWdtZW50IG9mIGBwYXRoYCB0aGF0J3Mgd2l0aGluIHRoZSB2aXNpYmxlIGFyZWFcbiAqIGdpdmVuIGJ5IGBib3VuZHNgIHtsZWZ0LCByaWdodCwgdG9wLCBib3R0b219LCB0byB3aXRoaW4gYVxuICogcHJlY2lzaW9uIG9mIGBidWZmZXJgIHB4XG4gKlxuICogcmV0dXJuczogdW5kZWZpbmVkIGlmIG5vdGhpbmcgaXMgdmlzaWJsZSwgZWxzZSBvYmplY3Q6XG4gKiB7XG4gKiAgIG1pbjogcG9zaXRpb24gd2hlcmUgdGhlIHBhdGggZmlyc3QgZW50ZXJzIGJvdW5kcywgb3IgMCBpZiBpdFxuICogICAgICAgIHN0YXJ0cyB3aXRoaW4gYm91bmRzXG4gKiAgIG1heDogcG9zaXRpb24gd2hlcmUgdGhlIHBhdGggbGFzdCBleGl0cyBib3VuZHMsIG9yIHRoZSBwYXRoIGxlbmd0aFxuICogICAgICAgIGlmIGl0IGZpbmlzaGVzIHdpdGhpbiBib3VuZHNcbiAqICAgbGVuOiBtYXggLSBtaW4sIGllIHRoZSBsZW5ndGggb2YgdmlzaWJsZSBwYXRoXG4gKiAgIHRvdGFsOiB0aGUgdG90YWwgcGF0aCBsZW5ndGggLSBqdXN0IGluY2x1ZGVkIHNvIHRoZSBjYWxsZXIgZG9lc24ndFxuICogICAgICAgIG5lZWQgdG8gY2FsbCBwYXRoLmdldFRvdGFsTGVuZ3RoKCkgYWdhaW5cbiAqICAgaXNDbG9zZWQ6IHRydWUgaWZmIHRoZSBzdGFydCBhbmQgZW5kIHBvaW50cyBvZiB0aGUgcGF0aCBhcmUgYm90aCB2aXNpYmxlXG4gKiAgICAgICAgYW5kIGFyZSBhdCB0aGUgc2FtZSBwb2ludFxuICogfVxuICpcbiAqIFdvcmtzIGJ5IHN0YXJ0aW5nIGZyb20gZWl0aGVyIGVuZCBhbmQgcmVwZWF0ZWRseSBmaW5kaW5nIHRoZSBkaXN0YW5jZSBmcm9tXG4gKiB0aGF0IHBvaW50IHRvIHRoZSBwbG90IGFyZWEsIGFuZCBpZiBpdCdzIG91dHNpZGUgdGhlIHBsb3QsIG1vdmluZyBhbG9uZyB0aGVcbiAqIHBhdGggYnkgdGhhdCBkaXN0YW5jZSAoYmVjYXVzZSB0aGUgcGxvdCBtdXN0IGJlIGF0IGxlYXN0IHRoYXQgZmFyIGF3YXkgb25cbiAqIHRoZSBwYXRoKS4gTm90ZSB0aGF0IGlmIGEgcGF0aCBlbnRlcnMsIGV4aXRzLCBhbmQgcmUtZW50ZXJzIHRoZSBwbG90LCB3ZVxuICogd2lsbCBub3QgY2FwdHVyZSB0aGlzIGJlaGF2aW9yLlxuICovXG5leHBvcnRzLmdldFZpc2libGVTZWdtZW50ID0gZnVuY3Rpb24gZ2V0VmlzaWJsZVNlZ21lbnQocGF0aCwgYm91bmRzLCBidWZmZXIpIHtcbiAgICB2YXIgbGVmdCA9IGJvdW5kcy5sZWZ0O1xuICAgIHZhciByaWdodCA9IGJvdW5kcy5yaWdodDtcbiAgICB2YXIgdG9wID0gYm91bmRzLnRvcDtcbiAgICB2YXIgYm90dG9tID0gYm91bmRzLmJvdHRvbTtcblxuICAgIHZhciBwTWluID0gMDtcbiAgICB2YXIgcFRvdGFsID0gcGF0aC5nZXRUb3RhbExlbmd0aCgpO1xuICAgIHZhciBwTWF4ID0gcFRvdGFsO1xuXG4gICAgdmFyIHB0MCwgcHRUb3RhbDtcblxuICAgIGZ1bmN0aW9uIGdldERpc3RUb1Bsb3QobGVuKSB7XG4gICAgICAgIHZhciBwdCA9IHBhdGguZ2V0UG9pbnRBdExlbmd0aChsZW4pO1xuXG4gICAgICAgIC8vIGhvbGQgb24gdG8gdGhlIHN0YXJ0IGFuZCBlbmQgcG9pbnRzIGZvciBgY2xvc2VkYFxuICAgICAgICBpZihsZW4gPT09IDApIHB0MCA9IHB0O1xuICAgICAgICBlbHNlIGlmKGxlbiA9PT0gcFRvdGFsKSBwdFRvdGFsID0gcHQ7XG5cbiAgICAgICAgdmFyIGR4ID0gKHB0LnggPCBsZWZ0KSA/IGxlZnQgLSBwdC54IDogKHB0LnggPiByaWdodCA/IHB0LnggLSByaWdodCA6IDApO1xuICAgICAgICB2YXIgZHkgPSAocHQueSA8IHRvcCkgPyB0b3AgLSBwdC55IDogKHB0LnkgPiBib3R0b20gPyBwdC55IC0gYm90dG9tIDogMCk7XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuICAgIH1cblxuICAgIHZhciBkaXN0VG9QbG90ID0gZ2V0RGlzdFRvUGxvdChwTWluKTtcbiAgICB3aGlsZShkaXN0VG9QbG90KSB7XG4gICAgICAgIHBNaW4gKz0gZGlzdFRvUGxvdCArIGJ1ZmZlcjtcbiAgICAgICAgaWYocE1pbiA+IHBNYXgpIHJldHVybjtcbiAgICAgICAgZGlzdFRvUGxvdCA9IGdldERpc3RUb1Bsb3QocE1pbik7XG4gICAgfVxuXG4gICAgZGlzdFRvUGxvdCA9IGdldERpc3RUb1Bsb3QocE1heCk7XG4gICAgd2hpbGUoZGlzdFRvUGxvdCkge1xuICAgICAgICBwTWF4IC09IGRpc3RUb1Bsb3QgKyBidWZmZXI7XG4gICAgICAgIGlmKHBNaW4gPiBwTWF4KSByZXR1cm47XG4gICAgICAgIGRpc3RUb1Bsb3QgPSBnZXREaXN0VG9QbG90KHBNYXgpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIG1pbjogcE1pbixcbiAgICAgICAgbWF4OiBwTWF4LFxuICAgICAgICBsZW46IHBNYXggLSBwTWluLFxuICAgICAgICB0b3RhbDogcFRvdGFsLFxuICAgICAgICBpc0Nsb3NlZDogcE1pbiA9PT0gMCAmJiBwTWF4ID09PSBwVG90YWwgJiZcbiAgICAgICAgICAgIE1hdGguYWJzKHB0MC54IC0gcHRUb3RhbC54KSA8IDAuMSAmJlxuICAgICAgICAgICAgTWF0aC5hYnMocHQwLnkgLSBwdFRvdGFsLnkpIDwgMC4xXG4gICAgfTtcbn07XG5cbi8qKlxuICogRmluZCBwb2ludCBvbiBTVkcgcGF0aCBjb3JyZXNwb25kaW5nIHRvIGEgZ2l2ZW4gY29uc3RyYWludCBjb29yZGluYXRlXG4gKlxuICogQHBhcmFtIHtTVkdQYXRoRWxlbWVudH0gcGF0aFxuICogQHBhcmFtIHtOdW1iZXJ9IHZhbCA6IGNvbnN0cmFpbnQgY29vcmRpbmF0ZSB2YWx1ZVxuICogQHBhcmFtIHtTdHJpbmd9IGNvb3JkIDogJ3gnIG9yICd5JyB0aGUgY29uc3RyYWludCBjb29yZGluYXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0cyA6XG4gKiAgLSB7TnVtYmVyfSBwYXRoTGVuZ3RoIDogc3VwcGx5IHRvdGFsIHBhdGggbGVuZ3RoIGJlZm9yZSBoYW5kXG4gKiAgLSB7TnVtYmVyfSB0b2xlcmFuY2VcbiAqICAtIHtOdW1iZXJ9IGl0ZXJhdGlvbkxpbWl0XG4gKiBAcmV0dXJuIHtTVkdQb2ludH1cbiAqL1xuZXhwb3J0cy5maW5kUG9pbnRPblBhdGggPSBmdW5jdGlvbiBmaW5kUG9pbnRPblBhdGgocGF0aCwgdmFsLCBjb29yZCwgb3B0cykge1xuICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gICAgdmFyIHBhdGhMZW5ndGggPSBvcHRzLnBhdGhMZW5ndGggfHwgcGF0aC5nZXRUb3RhbExlbmd0aCgpO1xuICAgIHZhciB0b2xlcmFuY2UgPSBvcHRzLnRvbGVyYW5jZSB8fCAxZS0zO1xuICAgIHZhciBpdGVyYXRpb25MaW1pdCA9IG9wdHMuaXRlcmF0aW9uTGltaXQgfHwgMzA7XG5cbiAgICAvLyBpZiBwYXRoIHN0YXJ0cyBhdCBhIHZhbCBncmVhdGVyIHRoYW4gdGhlIHBhdGggdGFpbCAobGlrZSBvbiB2ZXJ0aWNhbCB2aW9saW5zKSxcbiAgICAvLyB3ZSBtdXN0IGZsaXAgdGhlIHNpZ24gb2YgdGhlIGNvbXB1dGVkIGRpZmYuXG4gICAgdmFyIG11bCA9IHBhdGguZ2V0UG9pbnRBdExlbmd0aCgwKVtjb29yZF0gPiBwYXRoLmdldFBvaW50QXRMZW5ndGgocGF0aExlbmd0aClbY29vcmRdID8gLTEgOiAxO1xuXG4gICAgdmFyIGkgPSAwO1xuICAgIHZhciBiMCA9IDA7XG4gICAgdmFyIGIxID0gcGF0aExlbmd0aDtcbiAgICB2YXIgbWlkO1xuICAgIHZhciBwdDtcbiAgICB2YXIgZGlmZjtcblxuICAgIHdoaWxlKGkgPCBpdGVyYXRpb25MaW1pdCkge1xuICAgICAgICBtaWQgPSAoYjAgKyBiMSkgLyAyO1xuICAgICAgICBwdCA9IHBhdGguZ2V0UG9pbnRBdExlbmd0aChtaWQpO1xuICAgICAgICBkaWZmID0gcHRbY29vcmRdIC0gdmFsO1xuXG4gICAgICAgIGlmKE1hdGguYWJzKGRpZmYpIDwgdG9sZXJhbmNlKSB7XG4gICAgICAgICAgICByZXR1cm4gcHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZihtdWwgKiBkaWZmID4gMCkge1xuICAgICAgICAgICAgICAgIGIxID0gbWlkO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBiMCA9IG1pZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcHQ7XG59O1xuXG59LHtcIi4vbW9kXCI6NzI2fV0sNzE2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgdGlueWNvbG9yID0gX2RlcmVxXygndGlueWNvbG9yMicpO1xudmFyIHJnYmEgPSBfZGVyZXFfKCdjb2xvci1ub3JtYWxpemUnKTtcblxudmFyIENvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKTtcbnZhciBjb2xvckRmbHQgPSBfZGVyZXFfKCcuLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXMnKS5kZWZhdWx0TGluZTtcbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi9hcnJheScpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG5cbnZhciBjb2xvckRmbHRSZ2JhID0gcmdiYShjb2xvckRmbHQpO1xudmFyIG9wYWNpdHlEZmx0ID0gMTtcblxuZnVuY3Rpb24gY2FsY3VsYXRlQ29sb3IoY29sb3JJbiwgb3BhY2l0eUluKSB7XG4gICAgdmFyIGNvbG9yT3V0ID0gY29sb3JJbjtcbiAgICBjb2xvck91dFszXSAqPSBvcGFjaXR5SW47XG4gICAgcmV0dXJuIGNvbG9yT3V0O1xufVxuXG5mdW5jdGlvbiB2YWxpZGF0ZUNvbG9yKGNvbG9ySW4pIHtcbiAgICBpZihpc051bWVyaWMoY29sb3JJbikpIHJldHVybiBjb2xvckRmbHRSZ2JhO1xuXG4gICAgdmFyIGNvbG9yT3V0ID0gcmdiYShjb2xvckluKTtcblxuICAgIHJldHVybiBjb2xvck91dC5sZW5ndGggPyBjb2xvck91dCA6IGNvbG9yRGZsdFJnYmE7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlT3BhY2l0eShvcGFjaXR5SW4pIHtcbiAgICByZXR1cm4gaXNOdW1lcmljKG9wYWNpdHlJbikgPyBvcGFjaXR5SW4gOiBvcGFjaXR5RGZsdDtcbn1cblxuZnVuY3Rpb24gZm9ybWF0Q29sb3IoY29udGFpbmVySW4sIG9wYWNpdHlJbiwgbGVuKSB7XG4gICAgdmFyIGNvbG9ySW4gPSBjb250YWluZXJJbi5jb2xvcjtcbiAgICB2YXIgaXNBcnJheUNvbG9ySW4gPSBpc0FycmF5T3JUeXBlZEFycmF5KGNvbG9ySW4pO1xuICAgIHZhciBpc0FycmF5T3BhY2l0eUluID0gaXNBcnJheU9yVHlwZWRBcnJheShvcGFjaXR5SW4pO1xuICAgIHZhciBjT3B0cyA9IENvbG9yc2NhbGUuZXh0cmFjdE9wdHMoY29udGFpbmVySW4pO1xuICAgIHZhciBjb2xvck91dCA9IFtdO1xuXG4gICAgdmFyIHNjbEZ1bmMsIGdldENvbG9yLCBnZXRPcGFjaXR5LCBjb2xvcmksIG9wYWNpdHlpO1xuXG4gICAgaWYoY09wdHMuY29sb3JzY2FsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHNjbEZ1bmMgPSBDb2xvcnNjYWxlLm1ha2VDb2xvclNjYWxlRnVuY0Zyb21UcmFjZShjb250YWluZXJJbik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc2NsRnVuYyA9IHZhbGlkYXRlQ29sb3I7XG4gICAgfVxuXG4gICAgaWYoaXNBcnJheUNvbG9ySW4pIHtcbiAgICAgICAgZ2V0Q29sb3IgPSBmdW5jdGlvbihjLCBpKSB7XG4gICAgICAgICAgICAvLyBGSVhNRTogdGhlcmUgaXMgZG91YmxlIHdvcmssIGNvbnNpZGVyaW5nIHRoYXQgc2NsRnVuYyBkb2VzIHRoZSBvcHBvc2l0ZVxuICAgICAgICAgICAgcmV0dXJuIGNbaV0gPT09IHVuZGVmaW5lZCA/IGNvbG9yRGZsdFJnYmEgOiByZ2JhKHNjbEZ1bmMoY1tpXSkpO1xuICAgICAgICB9O1xuICAgIH0gZWxzZSBnZXRDb2xvciA9IHZhbGlkYXRlQ29sb3I7XG5cbiAgICBpZihpc0FycmF5T3BhY2l0eUluKSB7XG4gICAgICAgIGdldE9wYWNpdHkgPSBmdW5jdGlvbihvLCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gb1tpXSA9PT0gdW5kZWZpbmVkID8gb3BhY2l0eURmbHQgOiB2YWxpZGF0ZU9wYWNpdHkob1tpXSk7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIGdldE9wYWNpdHkgPSB2YWxpZGF0ZU9wYWNpdHk7XG5cbiAgICBpZihpc0FycmF5Q29sb3JJbiB8fCBpc0FycmF5T3BhY2l0eUluKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgY29sb3JpID0gZ2V0Q29sb3IoY29sb3JJbiwgaSk7XG4gICAgICAgICAgICBvcGFjaXR5aSA9IGdldE9wYWNpdHkob3BhY2l0eUluLCBpKTtcbiAgICAgICAgICAgIGNvbG9yT3V0W2ldID0gY2FsY3VsYXRlQ29sb3IoY29sb3JpLCBvcGFjaXR5aSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgY29sb3JPdXQgPSBjYWxjdWxhdGVDb2xvcihyZ2JhKGNvbG9ySW4pLCBvcGFjaXR5SW4pO1xuXG4gICAgcmV0dXJuIGNvbG9yT3V0O1xufVxuXG5mdW5jdGlvbiBwYXJzZUNvbG9yU2NhbGUoY29udCwgYWxwaGEpIHtcbiAgICBpZihhbHBoYSA9PT0gdW5kZWZpbmVkKSBhbHBoYSA9IDE7XG5cbiAgICB2YXIgY09wdHMgPSBDb2xvcnNjYWxlLmV4dHJhY3RPcHRzKGNvbnQpO1xuXG4gICAgdmFyIGNvbG9yc2NhbGUgPSBjT3B0cy5yZXZlcnNlc2NhbGUgP1xuICAgICAgICBDb2xvcnNjYWxlLmZsaXBTY2FsZShjT3B0cy5jb2xvcnNjYWxlKSA6XG4gICAgICAgIGNPcHRzLmNvbG9yc2NhbGU7XG5cbiAgICByZXR1cm4gY29sb3JzY2FsZS5tYXAoZnVuY3Rpb24oZWxlbSkge1xuICAgICAgICB2YXIgaW5kZXggPSBlbGVtWzBdO1xuICAgICAgICB2YXIgY29sb3IgPSB0aW55Y29sb3IoZWxlbVsxXSk7XG4gICAgICAgIHZhciByZ2IgPSBjb2xvci50b1JnYigpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaW5kZXg6IGluZGV4LFxuICAgICAgICAgICAgcmdiOiBbcmdiLnIsIHJnYi5nLCByZ2IuYiwgYWxwaGFdXG4gICAgICAgIH07XG4gICAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGZvcm1hdENvbG9yOiBmb3JtYXRDb2xvcixcbiAgICBwYXJzZUNvbG9yU2NhbGU6IHBhcnNlQ29sb3JTY2FsZVxufTtcblxufSx7XCIuLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXNcIjo1OTIsXCIuLi9jb21wb25lbnRzL2NvbG9yc2NhbGVcIjo2MDUsXCIuL2FycmF5XCI6NzAyLFwiY29sb3Itbm9ybWFsaXplXCI6MTIwLFwiZmFzdC1pc251bWVyaWNcIjoyMjUsXCJ0aW55Y29sb3IyXCI6NTM3fV0sNzE3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlkZW50aXR5ID0gX2RlcmVxXygnLi9pZGVudGl0eScpO1xuXG5mdW5jdGlvbiB3cmFwKGQpIHtyZXR1cm4gW2RdO31cblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cbiAgICAvLyBUaGUgRDMgZGF0YSBiaW5kaW5nIGNvbmNlcHQgYW5kIHRoZSBHZW5lcmFsIFVwZGF0ZSBQYXR0ZXJuIHByb21vdGVzIHRoZSBpZGVhIG9mXG4gICAgLy8gdHJhdmVyc2luZyBpbnRvIHRoZSBzY2VuZWdyYXBoIGJ5IHVzaW5nIHRoZSBgLmRhdGEoZnVuLCBrZXlGdW4pYCBjYWxsLlxuICAgIC8vIFRoZSBgZnVuYCBpcyBtb3N0IG9mdGVuIGEgYHJlcGVhdGAsIGllLiB0aGUgZWxlbWVudHMgYmVuZWF0aCBhIGA8Zz5gIGVsZW1lbnQgbmVlZFxuICAgIC8vIGFjY2VzcyB0byB0aGUgc2FtZSBkYXRhLCBvciBhIGBkZXNjZW5kYCwgd2hpY2ggZmFucyBhIHNjZW5lZ3JhcGggbm9kZSBpbnRvIGEgYnVuY2ggb2ZcbiAgICAvLyBvZiBlbGVtZW50cywgZS5nLiBwb2ludHMsIGxpbmVzLCByb3dzLCByZXF1aXJpbmcgYW4gYXJyYXkgYXMgaW5wdXQuXG4gICAgLy8gVGhlIHJvbGUgb2YgdGhlIGBrZXlGdW5gIGlzIHRvIGlkZW50aWZ5IHdoYXQgZWxlbWVudHMgYXJlIGJlaW5nIGVudGVyZWQvZXhpdGVkL3VwZGF0ZWQsXG4gICAgLy8gb3RoZXJ3aXNlIEQzIHJldmVydHMgdG8gdXNpbmcgYSBwbGFpbiBpbmRleCB3aGljaCB3b3VsZCBzY3JldyB1cCBgdHJhbnNpdGlvbmBzLlxuICAgIGtleUZ1bjogZnVuY3Rpb24oZCkge3JldHVybiBkLmtleTt9LFxuICAgIHJlcGVhdDogd3JhcCxcbiAgICBkZXNjZW5kOiBpZGVudGl0eSxcblxuICAgIC8vIFBsb3RseS5qcyB1c2VzIGEgY29udmVudGlvbiBvZiBzdG9yaW5nIHRoZSBhY3R1YWwgY29udGVudHMgb2YgdGhlIGBjYWxjRGF0YWAgYXMgdGhlXG4gICAgLy8gZWxlbWVudCB6ZXJvIG9mIGEgY29udGFpbmVyIGFycmF5LiBUaGVzZSBoZWxwZXJzIGFyZSBqdXN0IHVzZWQgZm9yIGNsYXJpdHkgYXMgYVxuICAgIC8vIG5ld2NvbWVyIHRvIHRoZSBjb2RlYmFzZSBtYXkgbm90IGtub3cgd2hhdCB0aGUgYFswXWAgaXMsIGFuZCB3aGV0aGVyIHRoZXJlIGNhbiBiZSBmdXJ0aGVyXG4gICAgLy8gZWxlbWVudHMgKG5vdCBhdG0pLlxuICAgIHdyYXA6IHdyYXAsXG4gICAgdW53cmFwOiBmdW5jdGlvbihkKSB7cmV0dXJuIGRbMF07fVxufTtcblxufSx7XCIuL2lkZW50aXR5XCI6NzE4fV0sNzE4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gU2ltcGxlIGhlbHBlciBmdW5jdGlvbnNcbi8vIG5vbmUgb2YgdGhlc2UgbmVlZCBhbnkgZXh0ZXJuYWwgZGVwc1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlkZW50aXR5KGQpIHsgcmV0dXJuIGQ7IH07XG5cbn0se31dLDcxOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIG51bUNvbnN0YW50cyA9IF9kZXJlcV8oJy4uL2NvbnN0YW50cy9udW1lcmljYWwnKTtcbnZhciBGUF9TQUZFID0gbnVtQ29uc3RhbnRzLkZQX1NBRkU7XG52YXIgQkFETlVNID0gbnVtQ29uc3RhbnRzLkJBRE5VTTtcblxudmFyIGxpYiA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbmxpYi5uZXN0ZWRQcm9wZXJ0eSA9IF9kZXJlcV8oJy4vbmVzdGVkX3Byb3BlcnR5Jyk7XG5saWIua2V5ZWRDb250YWluZXIgPSBfZGVyZXFfKCcuL2tleWVkX2NvbnRhaW5lcicpO1xubGliLnJlbGF0aXZlQXR0ciA9IF9kZXJlcV8oJy4vcmVsYXRpdmVfYXR0cicpO1xubGliLmlzUGxhaW5PYmplY3QgPSBfZGVyZXFfKCcuL2lzX3BsYWluX29iamVjdCcpO1xubGliLnRvTG9nUmFuZ2UgPSBfZGVyZXFfKCcuL3RvX2xvZ19yYW5nZScpO1xubGliLnJlbGlua1ByaXZhdGVLZXlzID0gX2RlcmVxXygnLi9yZWxpbmtfcHJpdmF0ZScpO1xuXG52YXIgYXJyYXlNb2R1bGUgPSBfZGVyZXFfKCcuL2FycmF5Jyk7XG5saWIuaXNUeXBlZEFycmF5ID0gYXJyYXlNb2R1bGUuaXNUeXBlZEFycmF5O1xubGliLmlzQXJyYXlPclR5cGVkQXJyYXkgPSBhcnJheU1vZHVsZS5pc0FycmF5T3JUeXBlZEFycmF5O1xubGliLmlzQXJyYXkxRCA9IGFycmF5TW9kdWxlLmlzQXJyYXkxRDtcbmxpYi5lbnN1cmVBcnJheSA9IGFycmF5TW9kdWxlLmVuc3VyZUFycmF5O1xubGliLmNvbmNhdCA9IGFycmF5TW9kdWxlLmNvbmNhdDtcbmxpYi5tYXhSb3dMZW5ndGggPSBhcnJheU1vZHVsZS5tYXhSb3dMZW5ndGg7XG5saWIubWluUm93TGVuZ3RoID0gYXJyYXlNb2R1bGUubWluUm93TGVuZ3RoO1xuXG52YXIgbW9kTW9kdWxlID0gX2RlcmVxXygnLi9tb2QnKTtcbmxpYi5tb2QgPSBtb2RNb2R1bGUubW9kO1xubGliLm1vZEhhbGYgPSBtb2RNb2R1bGUubW9kSGFsZjtcblxudmFyIGNvZXJjZU1vZHVsZSA9IF9kZXJlcV8oJy4vY29lcmNlJyk7XG5saWIudmFsT2JqZWN0TWV0YSA9IGNvZXJjZU1vZHVsZS52YWxPYmplY3RNZXRhO1xubGliLmNvZXJjZSA9IGNvZXJjZU1vZHVsZS5jb2VyY2U7XG5saWIuY29lcmNlMiA9IGNvZXJjZU1vZHVsZS5jb2VyY2UyO1xubGliLmNvZXJjZUZvbnQgPSBjb2VyY2VNb2R1bGUuY29lcmNlRm9udDtcbmxpYi5jb2VyY2VIb3ZlcmluZm8gPSBjb2VyY2VNb2R1bGUuY29lcmNlSG92ZXJpbmZvO1xubGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkgPSBjb2VyY2VNb2R1bGUuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eTtcbmxpYi52YWxpZGF0ZSA9IGNvZXJjZU1vZHVsZS52YWxpZGF0ZTtcblxudmFyIGRhdGVzTW9kdWxlID0gX2RlcmVxXygnLi9kYXRlcycpO1xubGliLmRhdGVUaW1lMm1zID0gZGF0ZXNNb2R1bGUuZGF0ZVRpbWUybXM7XG5saWIuaXNEYXRlVGltZSA9IGRhdGVzTW9kdWxlLmlzRGF0ZVRpbWU7XG5saWIubXMyRGF0ZVRpbWUgPSBkYXRlc01vZHVsZS5tczJEYXRlVGltZTtcbmxpYi5tczJEYXRlVGltZUxvY2FsID0gZGF0ZXNNb2R1bGUubXMyRGF0ZVRpbWVMb2NhbDtcbmxpYi5jbGVhbkRhdGUgPSBkYXRlc01vZHVsZS5jbGVhbkRhdGU7XG5saWIuaXNKU0RhdGUgPSBkYXRlc01vZHVsZS5pc0pTRGF0ZTtcbmxpYi5mb3JtYXREYXRlID0gZGF0ZXNNb2R1bGUuZm9ybWF0RGF0ZTtcbmxpYi5pbmNyZW1lbnRNb250aCA9IGRhdGVzTW9kdWxlLmluY3JlbWVudE1vbnRoO1xubGliLmRhdGVUaWNrMCA9IGRhdGVzTW9kdWxlLmRhdGVUaWNrMDtcbmxpYi5kZmx0UmFuZ2UgPSBkYXRlc01vZHVsZS5kZmx0UmFuZ2U7XG5saWIuZmluZEV4YWN0RGF0ZXMgPSBkYXRlc01vZHVsZS5maW5kRXhhY3REYXRlcztcbmxpYi5NSU5fTVMgPSBkYXRlc01vZHVsZS5NSU5fTVM7XG5saWIuTUFYX01TID0gZGF0ZXNNb2R1bGUuTUFYX01TO1xuXG52YXIgc2VhcmNoTW9kdWxlID0gX2RlcmVxXygnLi9zZWFyY2gnKTtcbmxpYi5maW5kQmluID0gc2VhcmNoTW9kdWxlLmZpbmRCaW47XG5saWIuc29ydGVyQXNjID0gc2VhcmNoTW9kdWxlLnNvcnRlckFzYztcbmxpYi5zb3J0ZXJEZXMgPSBzZWFyY2hNb2R1bGUuc29ydGVyRGVzO1xubGliLmRpc3RpbmN0VmFscyA9IHNlYXJjaE1vZHVsZS5kaXN0aW5jdFZhbHM7XG5saWIucm91bmRVcCA9IHNlYXJjaE1vZHVsZS5yb3VuZFVwO1xubGliLnNvcnQgPSBzZWFyY2hNb2R1bGUuc29ydDtcbmxpYi5maW5kSW5kZXhPZk1pbiA9IHNlYXJjaE1vZHVsZS5maW5kSW5kZXhPZk1pbjtcblxudmFyIHN0YXRzTW9kdWxlID0gX2RlcmVxXygnLi9zdGF0cycpO1xubGliLmFnZ051bXMgPSBzdGF0c01vZHVsZS5hZ2dOdW1zO1xubGliLmxlbiA9IHN0YXRzTW9kdWxlLmxlbjtcbmxpYi5tZWFuID0gc3RhdHNNb2R1bGUubWVhbjtcbmxpYi5tZWRpYW4gPSBzdGF0c01vZHVsZS5tZWRpYW47XG5saWIubWlkUmFuZ2UgPSBzdGF0c01vZHVsZS5taWRSYW5nZTtcbmxpYi52YXJpYW5jZSA9IHN0YXRzTW9kdWxlLnZhcmlhbmNlO1xubGliLnN0ZGV2ID0gc3RhdHNNb2R1bGUuc3RkZXY7XG5saWIuaW50ZXJwID0gc3RhdHNNb2R1bGUuaW50ZXJwO1xuXG52YXIgbWF0cml4TW9kdWxlID0gX2RlcmVxXygnLi9tYXRyaXgnKTtcbmxpYi5pbml0MmRBcnJheSA9IG1hdHJpeE1vZHVsZS5pbml0MmRBcnJheTtcbmxpYi50cmFuc3Bvc2VSYWdnZWQgPSBtYXRyaXhNb2R1bGUudHJhbnNwb3NlUmFnZ2VkO1xubGliLmRvdCA9IG1hdHJpeE1vZHVsZS5kb3Q7XG5saWIudHJhbnNsYXRpb25NYXRyaXggPSBtYXRyaXhNb2R1bGUudHJhbnNsYXRpb25NYXRyaXg7XG5saWIucm90YXRpb25NYXRyaXggPSBtYXRyaXhNb2R1bGUucm90YXRpb25NYXRyaXg7XG5saWIucm90YXRpb25YWU1hdHJpeCA9IG1hdHJpeE1vZHVsZS5yb3RhdGlvblhZTWF0cml4O1xubGliLmFwcGx5MkRUcmFuc2Zvcm0gPSBtYXRyaXhNb2R1bGUuYXBwbHkyRFRyYW5zZm9ybTtcbmxpYi5hcHBseTJEVHJhbnNmb3JtMiA9IG1hdHJpeE1vZHVsZS5hcHBseTJEVHJhbnNmb3JtMjtcblxudmFyIGFuZ2xlc01vZHVsZSA9IF9kZXJlcV8oJy4vYW5nbGVzJyk7XG5saWIuZGVnMnJhZCA9IGFuZ2xlc01vZHVsZS5kZWcycmFkO1xubGliLnJhZDJkZWcgPSBhbmdsZXNNb2R1bGUucmFkMmRlZztcbmxpYi5hbmdsZURlbHRhID0gYW5nbGVzTW9kdWxlLmFuZ2xlRGVsdGE7XG5saWIuYW5nbGVEaXN0ID0gYW5nbGVzTW9kdWxlLmFuZ2xlRGlzdDtcbmxpYi5pc0Z1bGxDaXJjbGUgPSBhbmdsZXNNb2R1bGUuaXNGdWxsQ2lyY2xlO1xubGliLmlzQW5nbGVJbnNpZGVTZWN0b3IgPSBhbmdsZXNNb2R1bGUuaXNBbmdsZUluc2lkZVNlY3RvcjtcbmxpYi5pc1B0SW5zaWRlU2VjdG9yID0gYW5nbGVzTW9kdWxlLmlzUHRJbnNpZGVTZWN0b3I7XG5saWIucGF0aEFyYyA9IGFuZ2xlc01vZHVsZS5wYXRoQXJjO1xubGliLnBhdGhTZWN0b3IgPSBhbmdsZXNNb2R1bGUucGF0aFNlY3RvcjtcbmxpYi5wYXRoQW5udWx1cyA9IGFuZ2xlc01vZHVsZS5wYXRoQW5udWx1cztcblxudmFyIGFuY2hvclV0aWxzID0gX2RlcmVxXygnLi9hbmNob3JfdXRpbHMnKTtcbmxpYi5pc0xlZnRBbmNob3IgPSBhbmNob3JVdGlscy5pc0xlZnRBbmNob3I7XG5saWIuaXNDZW50ZXJBbmNob3IgPSBhbmNob3JVdGlscy5pc0NlbnRlckFuY2hvcjtcbmxpYi5pc1JpZ2h0QW5jaG9yID0gYW5jaG9yVXRpbHMuaXNSaWdodEFuY2hvcjtcbmxpYi5pc1RvcEFuY2hvciA9IGFuY2hvclV0aWxzLmlzVG9wQW5jaG9yO1xubGliLmlzTWlkZGxlQW5jaG9yID0gYW5jaG9yVXRpbHMuaXNNaWRkbGVBbmNob3I7XG5saWIuaXNCb3R0b21BbmNob3IgPSBhbmNob3JVdGlscy5pc0JvdHRvbUFuY2hvcjtcblxudmFyIGdlb20yZE1vZHVsZSA9IF9kZXJlcV8oJy4vZ2VvbWV0cnkyZCcpO1xubGliLnNlZ21lbnRzSW50ZXJzZWN0ID0gZ2VvbTJkTW9kdWxlLnNlZ21lbnRzSW50ZXJzZWN0O1xubGliLnNlZ21lbnREaXN0YW5jZSA9IGdlb20yZE1vZHVsZS5zZWdtZW50RGlzdGFuY2U7XG5saWIuZ2V0VGV4dExvY2F0aW9uID0gZ2VvbTJkTW9kdWxlLmdldFRleHRMb2NhdGlvbjtcbmxpYi5jbGVhckxvY2F0aW9uQ2FjaGUgPSBnZW9tMmRNb2R1bGUuY2xlYXJMb2NhdGlvbkNhY2hlO1xubGliLmdldFZpc2libGVTZWdtZW50ID0gZ2VvbTJkTW9kdWxlLmdldFZpc2libGVTZWdtZW50O1xubGliLmZpbmRQb2ludE9uUGF0aCA9IGdlb20yZE1vZHVsZS5maW5kUG9pbnRPblBhdGg7XG5cbnZhciBleHRlbmRNb2R1bGUgPSBfZGVyZXFfKCcuL2V4dGVuZCcpO1xubGliLmV4dGVuZEZsYXQgPSBleHRlbmRNb2R1bGUuZXh0ZW5kRmxhdDtcbmxpYi5leHRlbmREZWVwID0gZXh0ZW5kTW9kdWxlLmV4dGVuZERlZXA7XG5saWIuZXh0ZW5kRGVlcEFsbCA9IGV4dGVuZE1vZHVsZS5leHRlbmREZWVwQWxsO1xubGliLmV4dGVuZERlZXBOb0FycmF5cyA9IGV4dGVuZE1vZHVsZS5leHRlbmREZWVwTm9BcnJheXM7XG5cbnZhciBsb2dnZXJzTW9kdWxlID0gX2RlcmVxXygnLi9sb2dnZXJzJyk7XG5saWIubG9nID0gbG9nZ2Vyc01vZHVsZS5sb2c7XG5saWIud2FybiA9IGxvZ2dlcnNNb2R1bGUud2FybjtcbmxpYi5lcnJvciA9IGxvZ2dlcnNNb2R1bGUuZXJyb3I7XG5cbnZhciByZWdleE1vZHVsZSA9IF9kZXJlcV8oJy4vcmVnZXgnKTtcbmxpYi5jb3VudGVyUmVnZXggPSByZWdleE1vZHVsZS5jb3VudGVyO1xuXG52YXIgdGhyb3R0bGVNb2R1bGUgPSBfZGVyZXFfKCcuL3Rocm90dGxlJyk7XG5saWIudGhyb3R0bGUgPSB0aHJvdHRsZU1vZHVsZS50aHJvdHRsZTtcbmxpYi50aHJvdHRsZURvbmUgPSB0aHJvdHRsZU1vZHVsZS5kb25lO1xubGliLmNsZWFyVGhyb3R0bGUgPSB0aHJvdHRsZU1vZHVsZS5jbGVhcjtcblxudmFyIGRvbU1vZHVsZSA9IF9kZXJlcV8oJy4vZG9tJyk7XG5saWIuZ2V0R3JhcGhEaXYgPSBkb21Nb2R1bGUuZ2V0R3JhcGhEaXY7XG5saWIuaXNQbG90RGl2ID0gZG9tTW9kdWxlLmlzUGxvdERpdjtcbmxpYi5yZW1vdmVFbGVtZW50ID0gZG9tTW9kdWxlLnJlbW92ZUVsZW1lbnQ7XG5saWIuYWRkU3R5bGVSdWxlID0gZG9tTW9kdWxlLmFkZFN0eWxlUnVsZTtcbmxpYi5hZGRSZWxhdGVkU3R5bGVSdWxlID0gZG9tTW9kdWxlLmFkZFJlbGF0ZWRTdHlsZVJ1bGU7XG5saWIuZGVsZXRlUmVsYXRlZFN0eWxlUnVsZSA9IGRvbU1vZHVsZS5kZWxldGVSZWxhdGVkU3R5bGVSdWxlO1xuXG5saWIuY2xlYXJSZXNwb25zaXZlID0gX2RlcmVxXygnLi9jbGVhcl9yZXNwb25zaXZlJyk7XG5cbmxpYi5tYWtlVHJhY2VHcm91cHMgPSBfZGVyZXFfKCcuL21ha2VfdHJhY2VfZ3JvdXBzJyk7XG5cbmxpYi5fID0gX2RlcmVxXygnLi9sb2NhbGl6ZScpO1xuXG5saWIubm90aWZpZXIgPSBfZGVyZXFfKCcuL25vdGlmaWVyJyk7XG5cbmxpYi5maWx0ZXJVbmlxdWUgPSBfZGVyZXFfKCcuL2ZpbHRlcl91bmlxdWUnKTtcbmxpYi5maWx0ZXJWaXNpYmxlID0gX2RlcmVxXygnLi9maWx0ZXJfdmlzaWJsZScpO1xubGliLnB1c2hVbmlxdWUgPSBfZGVyZXFfKCcuL3B1c2hfdW5pcXVlJyk7XG5cbmxpYi5jbGVhbk51bWJlciA9IF9kZXJlcV8oJy4vY2xlYW5fbnVtYmVyJyk7XG5cbmxpYi5lbnN1cmVOdW1iZXIgPSBmdW5jdGlvbiBlbnN1cmVOdW1iZXIodikge1xuICAgIGlmKCFpc051bWVyaWModikpIHJldHVybiBCQUROVU07XG4gICAgdiA9IE51bWJlcih2KTtcbiAgICBpZih2IDwgLUZQX1NBRkUgfHwgdiA+IEZQX1NBRkUpIHJldHVybiBCQUROVU07XG4gICAgcmV0dXJuIGlzTnVtZXJpYyh2KSA/IE51bWJlcih2KSA6IEJBRE5VTTtcbn07XG5cbi8qKlxuICogSXMgdiBhIHZhbGlkIGFycmF5IGluZGV4PyBBY2NlcHRzIG51bWVyaWMgc3RyaW5ncyBhcyB3ZWxsIGFzIG51bWJlcnMuXG4gKlxuICogQHBhcmFtIHthbnl9IHY6IHRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcGFyYW0ge09wdGlvbmFsW2ludGVnZXJdfSBsZW46IHRoZSBhcnJheSBsZW5ndGggd2UgYXJlIGluZGV4aW5nXG4gKlxuICogQHJldHVybiB7Ym9vbH06IHYgaXMgYSB2YWxpZCBhcnJheSBpbmRleFxuICovXG5saWIuaXNJbmRleCA9IGZ1bmN0aW9uKHYsIGxlbikge1xuICAgIGlmKGxlbiAhPT0gdW5kZWZpbmVkICYmIHYgPj0gbGVuKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIGlzTnVtZXJpYyh2KSAmJiAodiA+PSAwKSAmJiAodiAlIDEgPT09IDApO1xufTtcblxubGliLm5vb3AgPSBfZGVyZXFfKCcuL25vb3AnKTtcbmxpYi5pZGVudGl0eSA9IF9kZXJlcV8oJy4vaWRlbnRpdHknKTtcblxuLyoqXG4gKiBjcmVhdGUgYW4gYXJyYXkgb2YgbGVuZ3RoICdjbnQnIGZpbGxlZCB3aXRoICd2JyBhdCBhbGwgaW5kaWNlc1xuICpcbiAqIEBwYXJhbSB7YW55fSB2XG4gKiBAcGFyYW0ge251bWJlcn0gY250XG4gKiBAcmV0dXJuIHthcnJheX1cbiAqL1xubGliLnJlcGVhdCA9IGZ1bmN0aW9uKHYsIGNudCkge1xuICAgIHZhciBvdXQgPSBuZXcgQXJyYXkoY250KTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY250OyBpKyspIHtcbiAgICAgICAgb3V0W2ldID0gdjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogc3dhcCB4IGFuZCB5IG9mIHRoZSBzYW1lIGF0dHJpYnV0ZSBpbiBjb250YWluZXIgY29udFxuICogc3BlY2lmeSBhdHRyIHdpdGggYSA/IGluIHBsYWNlIG9mIHgveVxuICogeW91IGNhbiBhbHNvIHN3YXAgb3RoZXIgdGhpbmdzIHRoYW4geC95IGJ5IHByb3ZpZGluZyBwYXJ0MSBhbmQgcGFydDJcbiAqL1xubGliLnN3YXBBdHRycyA9IGZ1bmN0aW9uKGNvbnQsIGF0dHJMaXN0LCBwYXJ0MSwgcGFydDIpIHtcbiAgICBpZighcGFydDEpIHBhcnQxID0gJ3gnO1xuICAgIGlmKCFwYXJ0MikgcGFydDIgPSAneSc7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF0dHJMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhdHRyID0gYXR0ckxpc3RbaV07XG4gICAgICAgIHZhciB4cCA9IGxpYi5uZXN0ZWRQcm9wZXJ0eShjb250LCBhdHRyLnJlcGxhY2UoJz8nLCBwYXJ0MSkpO1xuICAgICAgICB2YXIgeXAgPSBsaWIubmVzdGVkUHJvcGVydHkoY29udCwgYXR0ci5yZXBsYWNlKCc/JywgcGFydDIpKTtcbiAgICAgICAgdmFyIHRlbXAgPSB4cC5nZXQoKTtcbiAgICAgICAgeHAuc2V0KHlwLmdldCgpKTtcbiAgICAgICAgeXAuc2V0KHRlbXApO1xuICAgIH1cbn07XG5cbi8qKlxuICogU1ZHIHBhaW50ZXIncyBhbGdvIHdvcmtlZCBhcm91bmQgd2l0aCByZWluc2VydGlvblxuICovXG5saWIucmFpc2VUb1RvcCA9IGZ1bmN0aW9uIHJhaXNlVG9Ub3AoZWxlbSkge1xuICAgIGVsZW0ucGFyZW50Tm9kZS5hcHBlbmRDaGlsZChlbGVtKTtcbn07XG5cbi8qKlxuICogY2FuY2VsIGEgcG9zc2libHkgcGVuZGluZyB0cmFuc2l0aW9uOyByZXR1cm5lZCBzZWxlY3Rpb24gbWF5IGJlIHVzZWQgYnkgY2FsbGVyXG4gKi9cbmxpYi5jYW5jZWxUcmFuc2l0aW9uID0gZnVuY3Rpb24oc2VsZWN0aW9uKSB7XG4gICAgcmV0dXJuIHNlbGVjdGlvbi50cmFuc2l0aW9uKCkuZHVyYXRpb24oMCk7XG59O1xuXG4vLyBjb25zdHJhaW4gLSByZXN0cmljdCBhIG51bWJlciB2IHRvIGJlIGJldHdlZW4gdjAgYW5kIHYxXG5saWIuY29uc3RyYWluID0gZnVuY3Rpb24odiwgdjAsIHYxKSB7XG4gICAgaWYodjAgPiB2MSkgcmV0dXJuIE1hdGgubWF4KHYxLCBNYXRoLm1pbih2MCwgdikpO1xuICAgIHJldHVybiBNYXRoLm1heCh2MCwgTWF0aC5taW4odjEsIHYpKTtcbn07XG5cbi8qKlxuICogZG8gdHdvIGJvdW5kaW5nIGJveGVzIGZyb20gZ2V0Qm91bmRpbmdDbGllbnRSZWN0LFxuICogaWUge2xlZnQscmlnaHQsdG9wLGJvdHRvbSx3aWR0aCxoZWlnaHR9LCBvdmVybGFwP1xuICogdGFrZXMgb3B0aW9uYWwgcGFkZGluZyBwaXhlbHNcbiAqL1xubGliLmJCb3hJbnRlcnNlY3QgPSBmdW5jdGlvbihhLCBiLCBwYWQpIHtcbiAgICBwYWQgPSBwYWQgfHwgMDtcbiAgICByZXR1cm4gKGEubGVmdCA8PSBiLnJpZ2h0ICsgcGFkICYmXG4gICAgICAgICAgICBiLmxlZnQgPD0gYS5yaWdodCArIHBhZCAmJlxuICAgICAgICAgICAgYS50b3AgPD0gYi5ib3R0b20gKyBwYWQgJiZcbiAgICAgICAgICAgIGIudG9wIDw9IGEuYm90dG9tICsgcGFkKTtcbn07XG5cbi8qXG4gKiBzaW1wbGVNYXA6IGFsdGVybmF0aXZlIHRvIEFycmF5Lm1hcCB0aGF0IG9ubHlcbiAqIHBhc3NlcyBvbiB0aGUgZWxlbWVudCBhbmQgdXAgdG8gMiBleHRyYSBhcmdzIHlvdVxuICogcHJvdmlkZSAoYnV0IG5vdCB0aGUgYXJyYXkgaW5kZXggb3IgdGhlIHdob2xlIGFycmF5KVxuICpcbiAqIGFycmF5OiB0aGUgYXJyYXkgdG8gbWFwIGl0IHRvXG4gKiBmdW5jOiB0aGUgZnVuY3Rpb24gdG8gYXBwbHlcbiAqIHgxLCB4Mjogb3B0aW9uYWwgZXh0cmEgYXJnc1xuICovXG5saWIuc2ltcGxlTWFwID0gZnVuY3Rpb24oYXJyYXksIGZ1bmMsIHgxLCB4Mikge1xuICAgIHZhciBsZW4gPSBhcnJheS5sZW5ndGg7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykgb3V0W2ldID0gZnVuYyhhcnJheVtpXSwgeDEsIHgyKTtcbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBSYW5kb20gc3RyaW5nIGdlbmVyYXRvclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBleGlzdGluZ1xuICogICAgIHBhc3MgaW4gc3RyaW5ncyB0byBhdm9pZCBhcyBrZXlzIHdpdGggdHJ1dGh5IHZhbHVlc1xuICogQHBhcmFtIHtpbnR9IGJpdHNcbiAqICAgICBiaXRzIG9mIGluZm9ybWF0aW9uIGluIHRoZSBvdXRwdXQgc3RyaW5nLCBkZWZhdWx0IDI0XG4gKiBAcGFyYW0ge2ludH0gYmFzZVxuICogICAgIGJhc2Ugb2Ygc3RyaW5nIHJlcHJlc2VudGF0aW9uLCBkZWZhdWx0IDE2LiBTaG91bGQgYmUgYSBwb3dlciBvZiAyLlxuICovXG5saWIucmFuZHN0ciA9IGZ1bmN0aW9uIHJhbmRzdHIoZXhpc3RpbmcsIGJpdHMsIGJhc2UsIF9yZWN1cnNpb24pIHtcbiAgICBpZighYmFzZSkgYmFzZSA9IDE2O1xuICAgIGlmKGJpdHMgPT09IHVuZGVmaW5lZCkgYml0cyA9IDI0O1xuICAgIGlmKGJpdHMgPD0gMCkgcmV0dXJuICcwJztcblxuICAgIHZhciBkaWdpdHMgPSBNYXRoLmxvZyhNYXRoLnBvdygyLCBiaXRzKSkgLyBNYXRoLmxvZyhiYXNlKTtcbiAgICB2YXIgcmVzID0gJyc7XG4gICAgdmFyIGksIGIsIHg7XG5cbiAgICBmb3IoaSA9IDI7IGRpZ2l0cyA9PT0gSW5maW5pdHk7IGkgKj0gMikge1xuICAgICAgICBkaWdpdHMgPSBNYXRoLmxvZyhNYXRoLnBvdygyLCBiaXRzIC8gaSkpIC8gTWF0aC5sb2coYmFzZSkgKiBpO1xuICAgIH1cblxuICAgIHZhciByZW0gPSBkaWdpdHMgLSBNYXRoLmZsb29yKGRpZ2l0cyk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBNYXRoLmZsb29yKGRpZ2l0cyk7IGkrKykge1xuICAgICAgICB4ID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYmFzZSkudG9TdHJpbmcoYmFzZSk7XG4gICAgICAgIHJlcyA9IHggKyByZXM7XG4gICAgfVxuXG4gICAgaWYocmVtKSB7XG4gICAgICAgIGIgPSBNYXRoLnBvdyhiYXNlLCByZW0pO1xuICAgICAgICB4ID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYikudG9TdHJpbmcoYmFzZSk7XG4gICAgICAgIHJlcyA9IHggKyByZXM7XG4gICAgfVxuXG4gICAgdmFyIHBhcnNlZCA9IHBhcnNlSW50KHJlcywgYmFzZSk7XG4gICAgaWYoKGV4aXN0aW5nICYmIGV4aXN0aW5nW3Jlc10pIHx8XG4gICAgICAgICAocGFyc2VkICE9PSBJbmZpbml0eSAmJiBwYXJzZWQgPj0gTWF0aC5wb3coMiwgYml0cykpKSB7XG4gICAgICAgIGlmKF9yZWN1cnNpb24gPiAxMCkge1xuICAgICAgICAgICAgbGliLndhcm4oJ3JhbmRzdHIgZmFpbGVkIHVuaXF1ZW5lc3MnKTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJhbmRzdHIoZXhpc3RpbmcsIGJpdHMsIGJhc2UsIChfcmVjdXJzaW9uIHx8IDApICsgMSk7XG4gICAgfSBlbHNlIHJldHVybiByZXM7XG59O1xuXG5saWIuT3B0aW9uQ29udHJvbCA9IGZ1bmN0aW9uKG9wdCwgb3B0bmFtZSkge1xuICAgIC8qXG4gICAgICogQW4gZW52aXJvbm1lbnQgdG8gY29udGFpbiBhbGwgb3B0aW9uIHNldHRlcnMgYW5kXG4gICAgICogZ2V0dGVycyB0aGF0IGNvbGxlY3RpdmVseSBtb2RpZnkgb3B0cy5cbiAgICAgKlxuICAgICAqIFlvdSBjYW4gY2FsbCB1cCBvcHRzIGZyb20gYW55IGZ1bmN0aW9uIGluIG5ldyBvYmplY3RcbiAgICAgKiBhcyB0aGlzLm9wdG5hbWUgfHwgdGhpcy5vcHRcbiAgICAgKlxuICAgICAqIFNlZSBGaXRPcHRzIGZvciBleGFtcGxlIG9mIHVzYWdlXG4gICAgICovXG4gICAgaWYoIW9wdCkgb3B0ID0ge307XG4gICAgaWYoIW9wdG5hbWUpIG9wdG5hbWUgPSAnb3B0JztcblxuICAgIHZhciBzZWxmID0ge307XG4gICAgc2VsZi5vcHRpb25MaXN0ID0gW107XG5cbiAgICBzZWxmLl9uZXdvcHRpb24gPSBmdW5jdGlvbihvcHRPYmopIHtcbiAgICAgICAgb3B0T2JqW29wdG5hbWVdID0gb3B0O1xuICAgICAgICBzZWxmW29wdE9iai5uYW1lXSA9IG9wdE9iajtcbiAgICAgICAgc2VsZi5vcHRpb25MaXN0LnB1c2gob3B0T2JqKTtcbiAgICB9O1xuXG4gICAgc2VsZlsnXycgKyBvcHRuYW1lXSA9IG9wdDtcbiAgICByZXR1cm4gc2VsZjtcbn07XG5cbi8qKlxuICogbGliLnNtb290aDogc21vb3RoIGFycmF5SW4gYnkgY29udm9sdmluZyB3aXRoXG4gKiBhIGhhbm4gd2luZG93IHdpdGggZ2l2ZW4gZnVsbCB3aWR0aCBhdCBoYWxmIG1heFxuICogYm91bmNlIHRoZSBlbmRzIGluLCBzbyB0aGUgb3V0cHV0IGhhcyB0aGUgc2FtZSBsZW5ndGggYXMgdGhlIGlucHV0XG4gKi9cbmxpYi5zbW9vdGggPSBmdW5jdGlvbihhcnJheUluLCBGV0hNKSB7XG4gICAgRldITSA9IE1hdGgucm91bmQoRldITSkgfHwgMDsgLy8gb25seSBtYWtlcyBzZW5zZSBmb3IgaW50ZWdlcnNcbiAgICBpZihGV0hNIDwgMikgcmV0dXJuIGFycmF5SW47XG5cbiAgICB2YXIgYWxlbiA9IGFycmF5SW4ubGVuZ3RoO1xuICAgIHZhciBhbGVuMiA9IDIgKiBhbGVuO1xuICAgIHZhciB3bGVuID0gMiAqIEZXSE0gLSAxO1xuICAgIHZhciB3ID0gbmV3IEFycmF5KHdsZW4pO1xuICAgIHZhciBhcnJheU91dCA9IG5ldyBBcnJheShhbGVuKTtcbiAgICB2YXIgaTtcbiAgICB2YXIgajtcbiAgICB2YXIgaztcbiAgICB2YXIgdjtcblxuICAgIC8vIGZpcnN0IG1ha2UgdGhlIHdpbmRvdyBhcnJheVxuICAgIGZvcihpID0gMDsgaSA8IHdsZW47IGkrKykge1xuICAgICAgICB3W2ldID0gKDEgLSBNYXRoLmNvcyhNYXRoLlBJICogKGkgKyAxKSAvIEZXSE0pKSAvICgyICogRldITSk7XG4gICAgfVxuXG4gICAgLy8gbm93IGRvIHRoZSBjb252b2x1dGlvblxuICAgIGZvcihpID0gMDsgaSA8IGFsZW47IGkrKykge1xuICAgICAgICB2ID0gMDtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgd2xlbjsgaisrKSB7XG4gICAgICAgICAgICBrID0gaSArIGogKyAxIC0gRldITTtcblxuICAgICAgICAgICAgLy8gbXVsdGlib3VuY2VcbiAgICAgICAgICAgIGlmKGsgPCAtYWxlbikgayAtPSBhbGVuMiAqIE1hdGgucm91bmQoayAvIGFsZW4yKTtcbiAgICAgICAgICAgIGVsc2UgaWYoayA+PSBhbGVuMikgayAtPSBhbGVuMiAqIE1hdGguZmxvb3IoayAvIGFsZW4yKTtcblxuICAgICAgICAgICAgLy8gc2luZ2xlIGJvdW5jZVxuICAgICAgICAgICAgaWYoayA8IDApIGsgPSAtIDEgLSBrO1xuICAgICAgICAgICAgZWxzZSBpZihrID49IGFsZW4pIGsgPSBhbGVuMiAtIDEgLSBrO1xuXG4gICAgICAgICAgICB2ICs9IGFycmF5SW5ba10gKiB3W2pdO1xuICAgICAgICB9XG4gICAgICAgIGFycmF5T3V0W2ldID0gdjtcbiAgICB9XG5cbiAgICByZXR1cm4gYXJyYXlPdXQ7XG59O1xuXG4vKipcbiAqIHN5bmNPckFzeW5jOiBydW4gYSBzZXF1ZW5jZSBvZiBmdW5jdGlvbnMgc3luY2hyb25vdXNseVxuICogYXMgbG9uZyBhcyBpdHMgcmV0dXJucyBhcmUgbm90IHByb21pc2VzIChpZSBoYXZlIG5vIC50aGVuKVxuICogaW5jbHVkZXMgb25lIGFyZ3VtZW50IGFyZyB0byBzZW5kIHRvIGFsbCBmdW5jdGlvbnMuLi5cbiAqIHRoaXMgaXMgbWFpbmx5IGp1c3QgdG8gcHJldmVudCB1cyBoYXZpbmcgdG8gbWFrZSB3cmFwcGVyIGZ1bmN0aW9uc1xuICogd2hlbiB0aGUgb25seSBwdXJwb3NlIG9mIHRoZSB3cmFwcGVyIGlzIHRvIHJlZmVyZW5jZSBnZFxuICogYW5kIGEgZmluYWwgc3RlcCB0byBiZSBleGVjdXRlZCBhdCB0aGUgZW5kXG4gKiBUT0RPOiBpZiB0aGVyZSdzIGFuIGVycm9yIGFuZCBldmVyeXRoaW5nIGlzIHN5bmMsXG4gKiB0aGlzIGRvZXNuJ3QgaGFwcGVuIHlldCBiZWNhdXNlIHdlIHdhbnQgdG8gbWFrZSBzdXJlXG4gKiB0aGF0IGl0IGdldHMgcmVwb3J0ZWRcbiAqL1xubGliLnN5bmNPckFzeW5jID0gZnVuY3Rpb24oc2VxdWVuY2UsIGFyZywgZmluYWxTdGVwKSB7XG4gICAgdmFyIHJldCwgZm5pO1xuXG4gICAgZnVuY3Rpb24gY29udGludWVBc3luYygpIHtcbiAgICAgICAgcmV0dXJuIGxpYi5zeW5jT3JBc3luYyhzZXF1ZW5jZSwgYXJnLCBmaW5hbFN0ZXApO1xuICAgIH1cblxuICAgIHdoaWxlKHNlcXVlbmNlLmxlbmd0aCkge1xuICAgICAgICBmbmkgPSBzZXF1ZW5jZS5zcGxpY2UoMCwgMSlbMF07XG4gICAgICAgIHJldCA9IGZuaShhcmcpO1xuXG4gICAgICAgIGlmKHJldCAmJiByZXQudGhlbikge1xuICAgICAgICAgICAgcmV0dXJuIHJldC50aGVuKGNvbnRpbnVlQXN5bmMpXG4gICAgICAgICAgICAgICAgLnRoZW4odW5kZWZpbmVkLCBsaWIucHJvbWlzZUVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmaW5hbFN0ZXAgJiYgZmluYWxTdGVwKGFyZyk7XG59O1xuXG5cbi8qKlxuICogSGVscGVyIHRvIHN0cmlwIHRyYWlsaW5nIHNsYXNoLCBmcm9tXG4gKiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY2ODA4MjUvcmV0dXJuLXN0cmluZy13aXRob3V0LXRyYWlsaW5nLXNsYXNoXG4gKi9cbmxpYi5zdHJpcFRyYWlsaW5nU2xhc2ggPSBmdW5jdGlvbihzdHIpIHtcbiAgICBpZihzdHIuc3Vic3RyKC0xKSA9PT0gJy8nKSByZXR1cm4gc3RyLnN1YnN0cigwLCBzdHIubGVuZ3RoIC0gMSk7XG4gICAgcmV0dXJuIHN0cjtcbn07XG5cbmxpYi5ub25lT3JBbGwgPSBmdW5jdGlvbihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBhdHRyTGlzdCkge1xuICAgIC8qKlxuICAgICAqIHNvbWUgYXR0cmlidXRlcyBjb21lIHRvZ2V0aGVyLCBzbyBpZiB5b3UgaGF2ZSBvbmUgb2YgdGhlbVxuICAgICAqIGluIHRoZSBpbnB1dCwgeW91IHNob3VsZCBjb3B5IHRoZSBkZWZhdWx0IHZhbHVlcyBvZiB0aGUgb3RoZXJzXG4gICAgICogdG8gdGhlIGlucHV0IGFzIHdlbGwuXG4gICAgICovXG4gICAgaWYoIWNvbnRhaW5lckluKSByZXR1cm47XG5cbiAgICB2YXIgaGFzQW55ID0gZmFsc2U7XG4gICAgdmFyIGhhc0FsbCA9IHRydWU7XG4gICAgdmFyIGk7XG4gICAgdmFyIHZhbDtcblxuICAgIGZvcihpID0gMDsgaSA8IGF0dHJMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhbCA9IGNvbnRhaW5lckluW2F0dHJMaXN0W2ldXTtcbiAgICAgICAgaWYodmFsICE9PSB1bmRlZmluZWQgJiYgdmFsICE9PSBudWxsKSBoYXNBbnkgPSB0cnVlO1xuICAgICAgICBlbHNlIGhhc0FsbCA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmKGhhc0FueSAmJiAhaGFzQWxsKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGF0dHJMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb250YWluZXJJblthdHRyTGlzdFtpXV0gPSBjb250YWluZXJPdXRbYXR0ckxpc3RbaV1dO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuLyoqIG1lcmdlcyBjYWxjZGF0YSBmaWVsZCAoZ2l2ZW4gYnkgY2RBdHRyKSB3aXRoIHRyYWNlQXR0ciB2YWx1ZXNcbiAqXG4gKiBOLkIuIExvb3Agb3ZlciBtaW5pbXVtIG9mIGNkLmxlbmd0aCBhbmQgdHJhY2VBdHRyLmxlbmd0aFxuICogaS5lLiBpdCBkb2VzIG5vdCB0cnkgdG8gZmlsbCBpbiBiZXlvbmQgdHJhY2VBdHRyLmxlbmd0aC0xXG4gKlxuICogQHBhcmFtIHthcnJheX0gdHJhY2VBdHRyIDogdHJhY2UgYXR0cmlidXRlXG4gKiBAcGFyYW0ge29iamVjdH0gY2QgOiBjYWxjZGF0YSB0cmFjZVxuICogQHBhcmFtIHtzdHJpbmd9IGNkQXR0ciA6IGNhbGNkYXRhIGtleVxuICovXG5saWIubWVyZ2VBcnJheSA9IGZ1bmN0aW9uKHRyYWNlQXR0ciwgY2QsIGNkQXR0ciwgZm4pIHtcbiAgICB2YXIgaGFzRm4gPSB0eXBlb2YgZm4gPT09ICdmdW5jdGlvbic7XG4gICAgaWYobGliLmlzQXJyYXlPclR5cGVkQXJyYXkodHJhY2VBdHRyKSkge1xuICAgICAgICB2YXIgaW1heCA9IE1hdGgubWluKHRyYWNlQXR0ci5sZW5ndGgsIGNkLmxlbmd0aCk7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBpbWF4OyBpKyspIHtcbiAgICAgICAgICAgIHZhciB2ID0gdHJhY2VBdHRyW2ldO1xuICAgICAgICAgICAgY2RbaV1bY2RBdHRyXSA9IGhhc0ZuID8gZm4odikgOiB2O1xuICAgICAgICB9XG4gICAgfVxufTtcblxuLy8gY2FzdCBudW1iZXJzIHRvIHBvc2l0aXZlIG51bWJlcnMsIHJldHVybnMgMCBpZiBub3QgZ3JlYXRlciB0aGFuIDBcbmxpYi5tZXJnZUFycmF5Q2FzdFBvc2l0aXZlID0gZnVuY3Rpb24odHJhY2VBdHRyLCBjZCwgY2RBdHRyKSB7XG4gICAgcmV0dXJuIGxpYi5tZXJnZUFycmF5KHRyYWNlQXR0ciwgY2QsIGNkQXR0ciwgZnVuY3Rpb24odikge1xuICAgICAgICB2YXIgdyA9ICt2O1xuICAgICAgICByZXR1cm4gIWlzRmluaXRlKHcpID8gMCA6IHcgPiAwID8gdyA6IDA7XG4gICAgfSk7XG59O1xuXG4vKiogZmlsbHMgY2FsY2RhdGEgZmllbGQgKGdpdmVuIGJ5IGNkQXR0cikgd2l0aCB0cmFjZUF0dHIgdmFsdWVzXG4gKiAgb3IgZnVuY3Rpb24gb2YgdHJhY2VBdHRyIHZhbHVlcyAoZS5nLiBzb21lIGZhbGxiYWNrKVxuICpcbiAqIE4uQi4gTG9vcHMgb3ZlciBhbGwgY2QgaXRlbXMuXG4gKlxuICogQHBhcmFtIHthcnJheX0gdHJhY2VBdHRyIDogdHJhY2UgYXR0cmlidXRlXG4gKiBAcGFyYW0ge29iamVjdH0gY2QgOiBjYWxjZGF0YSB0cmFjZVxuICogQHBhcmFtIHtzdHJpbmd9IGNkQXR0ciA6IGNhbGNkYXRhIGtleVxuICogQHBhcmFtIHtmdW5jdGlvbn0gW2ZuXSA6IG9wdGlvbmFsIGZ1bmN0aW9uIHRvIGFwcGx5IHRvIGVhY2ggYXJyYXkgaXRlbVxuICovXG5saWIuZmlsbEFycmF5ID0gZnVuY3Rpb24odHJhY2VBdHRyLCBjZCwgY2RBdHRyLCBmbikge1xuICAgIGZuID0gZm4gfHwgbGliLmlkZW50aXR5O1xuXG4gICAgaWYobGliLmlzQXJyYXlPclR5cGVkQXJyYXkodHJhY2VBdHRyKSkge1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNkW2ldW2NkQXR0cl0gPSBmbih0cmFjZUF0dHJbaV0pO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuLyoqIEhhbmRsZXIgZm9yIHRyYWNlLXdpZGUgdnMgcGVyLXBvaW50IG9wdGlvbnNcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2UgOiAoZnVsbCkgdHJhY2Ugb2JqZWN0XG4gKiBAcGFyYW0ge251bWJlcn0gcHROdW1iZXIgOiBpbmRleCBvZiB0aGUgcG9pbnQgaW4gcXVlc3Rpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBhc3RyIDogYXR0cmlidXRlIHN0cmluZ1xuICogQHBhcmFtIHtmdW5jdGlvbn0gW2ZuXSA6IG9wdGlvbmFsIGZ1bmN0aW9uIHRvIGFwcGx5IHRvIGVhY2ggYXJyYXkgaXRlbVxuICpcbiAqIEByZXR1cm4ge2FueX1cbiAqL1xubGliLmNhc3RPcHRpb24gPSBmdW5jdGlvbih0cmFjZSwgcHROdW1iZXIsIGFzdHIsIGZuKSB7XG4gICAgZm4gPSBmbiB8fCBsaWIuaWRlbnRpdHk7XG5cbiAgICB2YXIgdmFsID0gbGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBhc3RyKS5nZXQoKTtcblxuICAgIGlmKGxpYi5pc0FycmF5T3JUeXBlZEFycmF5KHZhbCkpIHtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShwdE51bWJlcikgJiYgbGliLmlzQXJyYXlPclR5cGVkQXJyYXkodmFsW3B0TnVtYmVyWzBdXSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmbih2YWxbcHROdW1iZXJbMF1dW3B0TnVtYmVyWzFdXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZm4odmFsW3B0TnVtYmVyXSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdmFsO1xuICAgIH1cbn07XG5cbi8qKiBFeHRyYWN0IG9wdGlvbiBmcm9tIGNhbGNkYXRhIGl0ZW0sIGNvcnJlY3RseSBmYWxsaW5nIGJhY2sgdG9cbiAqICB0cmFjZSB2YWx1ZSBpZiBub3QgZm91bmQuXG4gKlxuICogIEBwYXJhbSB7b2JqZWN0fSBjYWxjUHQgOiBjYWxjZGF0YVtpXVtqXSBpdGVtXG4gKiAgQHBhcmFtIHtvYmplY3R9IHRyYWNlIDogKGZ1bGwpIHRyYWNlIG9iamVjdFxuICogIEBwYXJhbSB7c3RyaW5nfSBjYWxjS2V5IDogY2FsY2RhdGEga2V5XG4gKiAgQHBhcmFtIHtzdHJpbmd9IHRyYWNlS2V5IDogYWthIHRyYWNlIGF0dHJpYnV0ZSBzdHJpbmdcbiAqICBAcmV0dXJuIHthbnl9XG4gKi9cbmxpYi5leHRyYWN0T3B0aW9uID0gZnVuY3Rpb24oY2FsY1B0LCB0cmFjZSwgY2FsY0tleSwgdHJhY2VLZXkpIHtcbiAgICBpZihjYWxjS2V5IGluIGNhbGNQdCkgcmV0dXJuIGNhbGNQdFtjYWxjS2V5XTtcblxuICAgIC8vIGZhbGxiYWNrIHRvIHRyYWNlIHZhbHVlLFxuICAgIC8vICAgbXVzdCBjaGVjayBpZiB2YWx1ZSBpc24ndCBpdHNlbGYgYW4gYXJyYXlcbiAgICAvLyAgIHdoaWNoIG1lYW5zIHRoZSB0cmFjZSBhdHRyaWJ1dGUgaGFzIGEgY29ycmVzcG9uZGluZ1xuICAgIC8vICAgY2FsY2RhdGEga2V5LCBidXQgaXRzIHZhbHVlIGlzIGZhbHN5XG4gICAgdmFyIHRyYWNlVmFsID0gbGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCB0cmFjZUtleSkuZ2V0KCk7XG4gICAgaWYoIUFycmF5LmlzQXJyYXkodHJhY2VWYWwpKSByZXR1cm4gdHJhY2VWYWw7XG59O1xuXG5mdW5jdGlvbiBtYWtlUHRJbmRleDJQdE51bWJlcihpbmRleFRvUG9pbnRzKSB7XG4gICAgdmFyIHB0SW5kZXgycHROdW1iZXIgPSB7fTtcbiAgICBmb3IodmFyIGsgaW4gaW5kZXhUb1BvaW50cykge1xuICAgICAgICB2YXIgcHRzID0gaW5kZXhUb1BvaW50c1trXTtcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IHB0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgcHRJbmRleDJwdE51bWJlcltwdHNbal1dID0gK2s7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHB0SW5kZXgycHROdW1iZXI7XG59XG5cbi8qKiBUYWcgc2VsZWN0ZWQgY2FsY2RhdGEgaXRlbXNcbiAqXG4gKiBOLkIuIG5vdGUgdGhhdCBwb2ludCAnaW5kZXgnIGNvcnJlc3BvbmRzIHRvIGlucHV0IGRhdGEgYXJyYXkgaW5kZXhcbiAqICB3aGVyZWFzICdudW1iZXInIGlzIGl0cyBwb3N0LXRyYW5zZm9ybSB2ZXJzaW9uLlxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGNhbGNUcmFjZVxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlXG4gKiAgLSBzZWxlY3RlZHBvaW50cyB7YXJyYXl9XG4gKiAgLSBfaW5kZXhUb1BvaW50cyB7b2JqZWN0fVxuICogQHBhcmFtIHtwdE51bWJlcjJjZEluZGV4fSBwdE51bWJlcjJjZEluZGV4IChvcHRpb25hbClcbiAqICBvcHRpb25hbCBtYXAgb2JqZWN0IGZvciB0cmFjZSB0eXBlcyB0aGF0IGRvIG5vdCBoYXZlIDEtdG8tMSBwb2ludCBudW1iZXIgdG9cbiAqICBjYWxjZGF0YSBpdGVtIGluZGV4IGNvcnJlc3BvbmRlbmNlIChlLmcuIGhpc3RvZ3JhbSlcbiAqL1xubGliLnRhZ1NlbGVjdGVkID0gZnVuY3Rpb24oY2FsY1RyYWNlLCB0cmFjZSwgcHROdW1iZXIyY2RJbmRleCkge1xuICAgIHZhciBzZWxlY3RlZHBvaW50cyA9IHRyYWNlLnNlbGVjdGVkcG9pbnRzO1xuICAgIHZhciBpbmRleFRvUG9pbnRzID0gdHJhY2UuX2luZGV4VG9Qb2ludHM7XG4gICAgdmFyIHB0SW5kZXgycHROdW1iZXI7XG5cbiAgICAvLyBtYWtlIHB0IGluZGV4LXRvLW51bWJlciBtYXAgb2JqZWN0LCB3aGljaCB0YWtlcyBjYXJlIG9mIHRyYW5zZm9ybWVkIHRyYWNlc1xuICAgIGlmKGluZGV4VG9Qb2ludHMpIHtcbiAgICAgICAgcHRJbmRleDJwdE51bWJlciA9IG1ha2VQdEluZGV4MlB0TnVtYmVyKGluZGV4VG9Qb2ludHMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzQ2RJbmRleFZhbGlkKHYpIHtcbiAgICAgICAgcmV0dXJuIHYgIT09IHVuZGVmaW5lZCAmJiB2IDwgY2FsY1RyYWNlLmxlbmd0aDtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2VsZWN0ZWRwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHB0SW5kZXggPSBzZWxlY3RlZHBvaW50c1tpXTtcblxuICAgICAgICBpZihsaWIuaXNJbmRleChwdEluZGV4KSkge1xuICAgICAgICAgICAgdmFyIHB0TnVtYmVyID0gcHRJbmRleDJwdE51bWJlciA/IHB0SW5kZXgycHROdW1iZXJbcHRJbmRleF0gOiBwdEluZGV4O1xuICAgICAgICAgICAgdmFyIGNkSW5kZXggPSBwdE51bWJlcjJjZEluZGV4ID8gcHROdW1iZXIyY2RJbmRleFtwdE51bWJlcl0gOiBwdE51bWJlcjtcblxuICAgICAgICAgICAgaWYoaXNDZEluZGV4VmFsaWQoY2RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICBjYWxjVHJhY2VbY2RJbmRleF0uc2VsZWN0ZWQgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxubGliLnNlbEluZGljZXMyc2VsUG9pbnRzID0gZnVuY3Rpb24odHJhY2UpIHtcbiAgICB2YXIgc2VsZWN0ZWRwb2ludHMgPSB0cmFjZS5zZWxlY3RlZHBvaW50cztcbiAgICB2YXIgaW5kZXhUb1BvaW50cyA9IHRyYWNlLl9pbmRleFRvUG9pbnRzO1xuXG4gICAgaWYoaW5kZXhUb1BvaW50cykge1xuICAgICAgICB2YXIgcHRJbmRleDJwdE51bWJlciA9IG1ha2VQdEluZGV4MlB0TnVtYmVyKGluZGV4VG9Qb2ludHMpO1xuICAgICAgICB2YXIgb3V0ID0gW107XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHNlbGVjdGVkcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcHRJbmRleCA9IHNlbGVjdGVkcG9pbnRzW2ldO1xuICAgICAgICAgICAgaWYobGliLmlzSW5kZXgocHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHROdW1iZXIgPSBwdEluZGV4MnB0TnVtYmVyW3B0SW5kZXhdO1xuICAgICAgICAgICAgICAgIGlmKGxpYi5pc0luZGV4KHB0TnVtYmVyKSkge1xuICAgICAgICAgICAgICAgICAgICBvdXQucHVzaChwdE51bWJlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gc2VsZWN0ZWRwb2ludHM7XG4gICAgfVxufTtcblxuLyoqIFJldHVybnMgdGFyZ2V0IGFzIHNldCBieSAndGFyZ2V0JyB0cmFuc2Zvcm0gYXR0cmlidXRlXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlIDogZnVsbCB0cmFjZSBvYmplY3RcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFuc2Zvcm1PcHRzIDogdHJhbnNmb3JtIG9wdGlvbiBvYmplY3RcbiAqICAtIHRhcmdldCAoc3RyaW5nfSA6XG4gKiAgICAgIGVpdGhlciBhbiBhdHRyaWJ1dGUgc3RyaW5nIHJlZmVyZW5jaW5nIGFuIGFycmF5IGluIHRoZSB0cmFjZSBvYmplY3QsIG9yXG4gKiAgICAgIGEgc2V0IGFycmF5LlxuICpcbiAqIEByZXR1cm4ge2FycmF5IG9yIGZhbHNlfSA6IHRoZSB0YXJnZXQgYXJyYXkgKE5PVCBhIGNvcHkhISkgb3IgZmFsc2UgaWYgaW52YWxpZFxuICovXG5saWIuZ2V0VGFyZ2V0QXJyYXkgPSBmdW5jdGlvbih0cmFjZSwgdHJhbnNmb3JtT3B0cykge1xuICAgIHZhciB0YXJnZXQgPSB0cmFuc2Zvcm1PcHRzLnRhcmdldDtcblxuICAgIGlmKHR5cGVvZiB0YXJnZXQgPT09ICdzdHJpbmcnICYmIHRhcmdldCkge1xuICAgICAgICB2YXIgYXJyYXkgPSBsaWIubmVzdGVkUHJvcGVydHkodHJhY2UsIHRhcmdldCkuZ2V0KCk7XG4gICAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KGFycmF5KSA/IGFycmF5IDogZmFsc2U7XG4gICAgfSBlbHNlIGlmKEFycmF5LmlzQXJyYXkodGFyZ2V0KSkge1xuICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn07XG5cbi8qKlxuICogbW9kaWZpZWQgdmVyc2lvbiBvZiBqUXVlcnkncyBleHRlbmQgdG8gc3RyaXAgb3V0IHByaXZhdGUgb2JqcyBhbmQgZnVuY3Rpb25zLFxuICogYW5kIGN1dCBhcnJheXMgZG93biB0byBmaXJzdCA8YXJyYXlsZW4+IG9yIDEgZWxlbWVudHNcbiAqIGJlY2F1c2UgZXh0ZW5kLWxpa2UgYWxnb3JpdGhtcyBhcmUgaGVsbGEgc2xvd1xuICogb2JqMiBpcyBhc3N1bWVkIHRvIGFscmVhZHkgYmUgY2xlYW4gb2YgdGhlc2UgdGhpbmdzIChpbmNsdWRpbmcgbm8gYXJyYXlzKVxuICovXG5saWIubWluRXh0ZW5kID0gZnVuY3Rpb24ob2JqMSwgb2JqMikge1xuICAgIHZhciBvYmpPdXQgPSB7fTtcbiAgICBpZih0eXBlb2Ygb2JqMiAhPT0gJ29iamVjdCcpIG9iajIgPSB7fTtcbiAgICB2YXIgYXJyYXlMZW4gPSAzO1xuICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMob2JqMSk7XG4gICAgdmFyIGksIGssIHY7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGsgPSBrZXlzW2ldO1xuICAgICAgICB2ID0gb2JqMVtrXTtcbiAgICAgICAgaWYoay5jaGFyQXQoMCkgPT09ICdfJyB8fCB0eXBlb2YgdiA9PT0gJ2Z1bmN0aW9uJykgY29udGludWU7XG4gICAgICAgIGVsc2UgaWYoayA9PT0gJ21vZHVsZScpIG9iak91dFtrXSA9IHY7XG4gICAgICAgIGVsc2UgaWYoQXJyYXkuaXNBcnJheSh2KSkge1xuICAgICAgICAgICAgaWYoayA9PT0gJ2NvbG9yc2NhbGUnKSB7XG4gICAgICAgICAgICAgICAgb2JqT3V0W2tdID0gdi5zbGljZSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBvYmpPdXRba10gPSB2LnNsaWNlKDAsIGFycmF5TGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKHYgJiYgKHR5cGVvZiB2ID09PSAnb2JqZWN0JykpIG9iak91dFtrXSA9IGxpYi5taW5FeHRlbmQob2JqMVtrXSwgb2JqMltrXSk7XG4gICAgICAgIGVsc2Ugb2JqT3V0W2tdID0gdjtcbiAgICB9XG5cbiAgICBrZXlzID0gT2JqZWN0LmtleXMob2JqMik7XG4gICAgZm9yKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBrID0ga2V5c1tpXTtcbiAgICAgICAgdiA9IG9iajJba107XG4gICAgICAgIGlmKHR5cGVvZiB2ICE9PSAnb2JqZWN0JyB8fCAhKGsgaW4gb2JqT3V0KSB8fCB0eXBlb2Ygb2JqT3V0W2tdICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgb2JqT3V0W2tdID0gdjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvYmpPdXQ7XG59O1xuXG5saWIudGl0bGVDYXNlID0gZnVuY3Rpb24ocykge1xuICAgIHJldHVybiBzLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgcy5zdWJzdHIoMSk7XG59O1xuXG5saWIuY29udGFpbnNBbnkgPSBmdW5jdGlvbihzLCBmcmFnbWVudHMpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnJhZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKHMuaW5kZXhPZihmcmFnbWVudHNbaV0pICE9PSAtMSkgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn07XG5cbmxpYi5pc0lFID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB3aW5kb3cubmF2aWdhdG9yLm1zU2F2ZUJsb2IgIT09ICd1bmRlZmluZWQnO1xufTtcblxudmFyIElTX0lFOV9PUl9CRUxPV19SRUdFWCA9IC9NU0lFIFsxLTldXFwuLztcbmxpYi5pc0lFOW9yQmVsb3cgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbGliLmlzSUUoKSAmJiBJU19JRTlfT1JfQkVMT1dfUkVHRVgudGVzdCh3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudCk7XG59O1xuXG52YXIgSVNfU0FGQVJJX1JFR0VYID0gL1ZlcnNpb25cXC9bXFxkXFwuXSsuKlNhZmFyaS87XG5saWIuaXNTYWZhcmkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gSVNfU0FGQVJJX1JFR0VYLnRlc3Qod2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQpO1xufTtcblxuLyoqXG4gKiBEdWNrIHR5cGluZyB0byByZWNvZ25pemUgYSBkMyBzZWxlY3Rpb24sIG1vc3RseSBmb3IgSUU5J3MgYmVuZWZpdFxuICogYmVjYXVzZSBpdCBkb2Vzbid0IGhhbmRsZSBpbnN0YW5jZW9mIGxpa2UgbW9kZXJuIGJyb3dzZXJzXG4gKi9cbmxpYi5pc0QzU2VsZWN0aW9uID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiAmJiAodHlwZW9mIG9iai5jbGFzc2VkID09PSAnZnVuY3Rpb24nKTtcbn07XG5cbi8qKlxuICogQXBwZW5kIGVsZW1lbnQgdG8gRE9NIG9ubHkgaWYgbm90IHByZXNlbnQuXG4gKlxuICogQHBhcmFtIHtkMyBzZWxlY3Rpb259IHBhcmVudCA6IHBhcmVudCBzZWxlY3Rpb24gb2YgdGhlIGVsZW1lbnQgaW4gcXVlc3Rpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBub2RlVHlwZSA6IG5vZGUgdHlwZSBvZiBlbGVtZW50IHRvIGFwcGVuZFxuICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzTmFtZSAob3B0aW9uYWwpIDogY2xhc3MgbmFtZSBvZiBlbGVtZW50IGluIHF1ZXN0aW9uXG4gKiBAcGFyYW0ge2ZufSBlbnRlckZuIChvcHRpb25hbCkgOiBvcHRpb25hbCBmbiBhcHBsaWVkIHRvIGVudGVyaW5nIGVsZW1lbnRzIG9ubHlcbiAqIEByZXR1cm4ge2QzIHNlbGVjdGlvbn0gc2VsZWN0aW9uIG9mIG5ldyBsYXllclxuICpcbiAqIFByZXZpb3VzbHksIHdlIHdlcmUgdXNpbmcgdGhlIGZvbGxvd2luZyBwYXR0ZXJuOlxuICpcbiAqIGBgYFxuICogdmFyIHNlbCA9IHBhcmVudC5zZWxlY3RBbGwoJy4nICsgY2xhc3NOYW1lKVxuICogICAgIC5kYXRhKFswXSk7XG4gKlxuICogc2VsLmVudGVyKCkuYXBwZW5kKG5vZGVUeXBlKVxuICogICAgIC5jbGFzc2VkKGNsYXNzTmFtZSwgdHJ1ZSk7XG4gKlxuICogcmV0dXJuIHNlbDtcbiAqIGBgYFxuICpcbiAqIGluIG51bWVyb3VzIHBsYWNlcyBpbiBvdXIgY29kZWJhc2UgdG8gYWNoaWV2ZSB0aGUgc2FtZSBiZWhhdmlvci5cbiAqXG4gKiBUaGUgbG9naWMgYmVsb3cgcGVyZm9ybXMgbXVjaCBiZXR0ZXIsIG1vc3RseSBhcyB3ZSBhcmUgdXNpbmdcbiAqIGAuc2VsZWN0YCBpbnN0ZWFkIGAuc2VsZWN0QWxsYCB0aGF0IGlzIGBxdWVyeVNlbGVjdG9yYCBpbnN0ZWFkIG9mXG4gKiBgcXVlcnlTZWxlY3RvckFsbGAuXG4gKlxuICovXG5saWIuZW5zdXJlU2luZ2xlID0gZnVuY3Rpb24ocGFyZW50LCBub2RlVHlwZSwgY2xhc3NOYW1lLCBlbnRlckZuKSB7XG4gICAgdmFyIHNlbCA9IHBhcmVudC5zZWxlY3Qobm9kZVR5cGUgKyAoY2xhc3NOYW1lID8gJy4nICsgY2xhc3NOYW1lIDogJycpKTtcbiAgICBpZihzZWwuc2l6ZSgpKSByZXR1cm4gc2VsO1xuXG4gICAgdmFyIGxheWVyID0gcGFyZW50LmFwcGVuZChub2RlVHlwZSk7XG4gICAgaWYoY2xhc3NOYW1lKSBsYXllci5jbGFzc2VkKGNsYXNzTmFtZSwgdHJ1ZSk7XG4gICAgaWYoZW50ZXJGbikgbGF5ZXIuY2FsbChlbnRlckZuKTtcblxuICAgIHJldHVybiBsYXllcjtcbn07XG5cbi8qKlxuICogU2FtZSBhcyBMaWIuZW5zdXJlU2luZ2xlLCBidXQgdXNpbmcgaWQgYXMgc2VsZWN0b3IuXG4gKiBUaGlzIHZlcnNpb24gaXMgbW9zdGx5IHVzZWQgZm9yIGNsaXBQYXRoIG5vZGVzLlxuICpcbiAqIEBwYXJhbSB7ZDMgc2VsZWN0aW9ufSBwYXJlbnQgOiBwYXJlbnQgc2VsZWN0aW9uIG9mIHRoZSBlbGVtZW50IGluIHF1ZXN0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ30gbm9kZVR5cGUgOiBub2RlIHR5cGUgb2YgZWxlbWVudCB0byBhcHBlbmRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCA6IGlkIG9mIGVsZW1lbnQgaW4gcXVlc3Rpb25cbiAqIEBwYXJhbSB7Zm59IGVudGVyRm4gKG9wdGlvbmFsKSA6IG9wdGlvbmFsIGZuIGFwcGxpZWQgdG8gZW50ZXJpbmcgZWxlbWVudHMgb25seVxuICogQHJldHVybiB7ZDMgc2VsZWN0aW9ufSBzZWxlY3Rpb24gb2YgbmV3IGxheWVyXG4gKi9cbmxpYi5lbnN1cmVTaW5nbGVCeUlkID0gZnVuY3Rpb24ocGFyZW50LCBub2RlVHlwZSwgaWQsIGVudGVyRm4pIHtcbiAgICB2YXIgc2VsID0gcGFyZW50LnNlbGVjdChub2RlVHlwZSArICcjJyArIGlkKTtcbiAgICBpZihzZWwuc2l6ZSgpKSByZXR1cm4gc2VsO1xuXG4gICAgdmFyIGxheWVyID0gcGFyZW50LmFwcGVuZChub2RlVHlwZSkuYXR0cignaWQnLCBpZCk7XG4gICAgaWYoZW50ZXJGbikgbGF5ZXIuY2FsbChlbnRlckZuKTtcblxuICAgIHJldHVybiBsYXllcjtcbn07XG5cbi8qKlxuICogQ29udmVydHMgYSBzdHJpbmcgcGF0aCB0byBhbiBvYmplY3QuXG4gKlxuICogV2hlbiBnaXZlbiBhIHN0cmluZyBjb250YWluaW5nIGFuIGFycmF5IGVsZW1lbnQsIGl0IHdpbGwgY3JlYXRlIGEgYG51bGxgXG4gKiBmaWxsZWQgYXJyYXkgb2YgdGhlIGdpdmVuIHNpemUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGxpYi5vYmplY3RGcm9tUGF0aCgnbmVzdGVkLnRlc3RbMl0ucGF0aCcsICd2YWx1ZScpO1xuICogLy8gcmV0dXJucyB7IG5lc3RlZDogeyB0ZXN0OiBbbnVsbCwgbnVsbCwgeyBwYXRoOiAndmFsdWUnIH1dfVxuICpcbiAqIEBwYXJhbSAgIHtzdHJpbmd9ICAgIHBhdGggdG8gbmVzdGVkIHZhbHVlXG4gKiBAcGFyYW0gICB7Kn0gICAgICAgICBhbnkgdmFsdWUgdG8gYmUgc2V0XG4gKlxuICogQHJldHVybiB7T2JqZWN0fSB0aGUgY29uc3RydWN0ZWQgb2JqZWN0IHdpdGggYSBmdWxsIG5lc3RlZCBwYXRoXG4gKi9cbmxpYi5vYmplY3RGcm9tUGF0aCA9IGZ1bmN0aW9uKHBhdGgsIHZhbHVlKSB7XG4gICAgdmFyIGtleXMgPSBwYXRoLnNwbGl0KCcuJyk7XG4gICAgdmFyIHRtcE9iajtcbiAgICB2YXIgb2JqID0gdG1wT2JqID0ge307XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgdmFyIGVsID0gbnVsbDtcblxuICAgICAgICB2YXIgcGFydHMgPSBrZXlzW2ldLm1hdGNoKC8oLiopXFxbKFswLTldKylcXF0vKTtcblxuICAgICAgICBpZihwYXJ0cykge1xuICAgICAgICAgICAga2V5ID0gcGFydHNbMV07XG4gICAgICAgICAgICBlbCA9IHBhcnRzWzJdO1xuXG4gICAgICAgICAgICB0bXBPYmogPSB0bXBPYmpba2V5XSA9IFtdO1xuXG4gICAgICAgICAgICBpZihpID09PSBrZXlzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICB0bXBPYmpbZWxdID0gdmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRtcE9ialtlbF0gPSB7fTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdG1wT2JqID0gdG1wT2JqW2VsXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKGkgPT09IGtleXMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgICAgIHRtcE9ialtrZXldID0gdmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRtcE9ialtrZXldID0ge307XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRtcE9iaiA9IHRtcE9ialtrZXldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9iajtcbn07XG5cbi8qKlxuICogSXRlcmF0ZSB0aHJvdWdoIGFuIG9iamVjdCBpbi1wbGFjZSwgY29udmVydGluZyBkb3R0ZWQgcHJvcGVydGllcyB0byBvYmplY3RzLlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgbGliLmV4cGFuZE9iamVjdFBhdGhzKHsnbmVzdGVkLnRlc3QucGF0aCc6ICd2YWx1ZSd9KTtcbiAqICAgICA9PiB7IG5lc3RlZDogeyB0ZXN0OiB7cGF0aDogJ3ZhbHVlJ319fVxuICpcbiAqIEl0IGFsc28gaGFuZGxlcyBhcnJheSBub3RhdGlvbiwgZS5nLjpcbiAqXG4gKiAgIGxpYi5leHBhbmRPYmplY3RQYXRocyh7J2Zvb1sxXS5iYXInOiAndmFsdWUnfSk7XG4gKiAgICAgPT4geyBmb286IFtudWxsLCB7YmFyOiB2YWx1ZX1dIH1cbiAqXG4gKiBJdCBoYW5kbGVzIG1lcmdlcyB0aGUgcmVzdWx0cyB3aGVuIHR3byBwcm9wZXJ0aWVzIGFyZSBzcGVjaWZpZWQgaW4gcGFyYWxsZWw6XG4gKlxuICogICBsaWIuZXhwYW5kT2JqZWN0UGF0aHMoeydmb29bMV0uYmFyJzogMTAsICdmb29bMF0uYmFyJzogMjB9KTtcbiAqICAgICA9PiB7IGZvbzogW3tiYXI6IDEwfSwge2JhcjogMjB9XSB9XG4gKlxuICogSXQgZG9lcyBOT1QsIGhvd2V2ZXIsIG1lcmdlIG11bGl0cGxlIG11dGxpcGx5LW5lc3RlZCBhcnJheXM6OlxuICpcbiAqICAgbGliLmV4cGFuZE9iamVjdFBhdGhzKHsnbWFya2VyWzFdLnJhbmdlWzFdJzogNSwgJ21hcmtlclsxXS5yYW5nZVswXSc6IDR9KVxuICogICAgID0+IHsgbWFya2VyOiBbbnVsbCwge3JhbmdlOiA0fV0gfVxuICovXG5cbi8vIFN0b3JlIHRoaXMgdG8gYXZvaWQgcmVjb21waWxpbmcgcmVnZXggb24gKmV2ZXJ5KiBwcm9wIHNpbmNlIHRoaXMgbWF5IGhhcHBlbiBtYW55XG4vLyBtYW55IHRpbWVzIGZvciBhbmltYXRpb25zLiBDb3VsZCBtYXliZSBiZSBpbnNpZGUgdGhlIGZ1bmN0aW9uLiBOb3Qgc3VyZSBhYm91dFxuLy8gc2NvcGluZyB2cy4gcmVjb21waWxhdGlvbiB0cmFkZW9mZiwgYnV0IGF0IGxlYXN0IGl0J3Mgbm90IGp1c3QgaW5saW5pbmcgaXQgaW50b1xuLy8gdGhlIGlubmVyIGxvb3AuXG52YXIgZG90dGVkUHJvcGVydHlSZWdleCA9IC9eKFteXFxbXFwuXSspXFwuKC4rKT8vO1xudmFyIGluZGV4ZWRQcm9wZXJ0eVJlZ2V4ID0gL14oW15cXC5dKylcXFsoWzAtOV0rKVxcXShcXC4pPyguKyk/LztcblxubGliLmV4cGFuZE9iamVjdFBhdGhzID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIHZhciBtYXRjaCwga2V5LCBwcm9wLCBkYXR1bSwgaWR4LCBkZXN0LCB0cmFpbGluZ1BhdGg7XG4gICAgaWYodHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgICAgIGZvcihrZXkgaW4gZGF0YSkge1xuICAgICAgICAgICAgaWYoZGF0YS5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgaWYoKG1hdGNoID0ga2V5Lm1hdGNoKGRvdHRlZFByb3BlcnR5UmVnZXgpKSkge1xuICAgICAgICAgICAgICAgICAgICBkYXR1bSA9IGRhdGFba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcCA9IG1hdGNoWzFdO1xuXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBkYXRhW2tleV07XG5cbiAgICAgICAgICAgICAgICAgICAgZGF0YVtwcm9wXSA9IGxpYi5leHRlbmREZWVwTm9BcnJheXMoZGF0YVtwcm9wXSB8fCB7fSwgbGliLm9iamVjdEZyb21QYXRoKGtleSwgbGliLmV4cGFuZE9iamVjdFBhdGhzKGRhdHVtKSlbcHJvcF0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZigobWF0Y2ggPSBrZXkubWF0Y2goaW5kZXhlZFByb3BlcnR5UmVnZXgpKSkge1xuICAgICAgICAgICAgICAgICAgICBkYXR1bSA9IGRhdGFba2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBwcm9wID0gbWF0Y2hbMV07XG4gICAgICAgICAgICAgICAgICAgIGlkeCA9IHBhcnNlSW50KG1hdGNoWzJdKTtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZGF0YVtrZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGRhdGFbcHJvcF0gPSBkYXRhW3Byb3BdIHx8IFtdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKG1hdGNoWzNdID09PSAnLicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGNhc2Ugd2hlcmUgdGhlZXJlIGFyZSBzdWJzZXF1ZW50IHByb3BlcnRpZXMgaW50byB3aGljaFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UgbXVzdCByZWN1cnNlLCBlLmcuIHRyYW5zZm9ybXNbMF0udmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYWlsaW5nUGF0aCA9IG1hdGNoWzRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdCA9IGRhdGFbcHJvcF1baWR4XSA9IGRhdGFbcHJvcF1baWR4XSB8fCB7fTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTkI6IEV4dGVuZCBkZWVwIG5vIGFycmF5cyBwcmV2ZW50cyB0aGlzIGZyb20gd29ya2luZyBvbiBtdWx0aXBsZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbmVzdGVkIHByb3BlcnRpZXMgaW4gdGhlIHNhbWUgb2JqZWN0LCBlLmcuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICBmb29bMF0uYmFyWzFdLnJhbmdlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgIGZvb1swXS5iYXJbMF0ucmFuZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJbiB0aGlzIGNhc2UsIHRoZSBleHRlbmREZWVwTm9BcnJheXMgd2lsbCBvdmVyd3JpdGUgb25lIGFycmF5IHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBvdGhlciwgc28gdGhhdCBib3RoIHByb3BlcnRpZXMgKndpbGwgbm90KiBiZSBwcmVzZW50IGluIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVzdWx0LiBGaXhpbmcgdGhpcyB3b3VsZCByZXF1aXJlIGEgbW9yZSBpbnRlbGxpZ2VudCB0cmFja2luZ1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb2YgY2hhbmdlcyBhbmQgbWVyZ2luZyB0aGFuIGV4dGVuZERlZXBOb0FycmF5cyBjdXJyZW50bHkgYWNjb21wbGlzaGVzLlxuICAgICAgICAgICAgICAgICAgICAgICAgbGliLmV4dGVuZERlZXBOb0FycmF5cyhkZXN0LCBsaWIub2JqZWN0RnJvbVBhdGgodHJhaWxpbmdQYXRoLCBsaWIuZXhwYW5kT2JqZWN0UGF0aHMoZGF0dW0pKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIHRoZSBjYXNlIHdoZXJlIHRoaXMgcHJvcGVydHkgaXMgdGhlIGVuZCBvZiB0aGUgbGluZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGUuZy4geGF4aXMucmFuZ2VbMF1cbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFbcHJvcF1baWR4XSA9IGxpYi5leHBhbmRPYmplY3RQYXRocyhkYXR1bSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkYXRhW2tleV0gPSBsaWIuZXhwYW5kT2JqZWN0UGF0aHMoZGF0YVtrZXldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YTtcbn07XG5cbi8qKlxuICogQ29udmVydHMgdmFsdWUgdG8gc3RyaW5nIHNlcGFyYXRlZCBieSB0aGUgcHJvdmlkZWQgc2VwYXJhdG9ycy5cbiAqXG4gKiBAZXhhbXBsZVxuICogbGliLm51bVNlcGFyYXRlKDIwMTYsICcuLCcpO1xuICogLy8gcmV0dXJucyAnMjAxNidcbiAqXG4gKiBAZXhhbXBsZVxuICogbGliLm51bVNlcGFyYXRlKDMwMDAsICcuLCcsIHRydWUpO1xuICogLy8gcmV0dXJucyAnMywwMDAnXG4gKlxuICogQGV4YW1wbGVcbiAqIGxpYi5udW1TZXBhcmF0ZSgxMjM0LjU2LCAnfCwnKVxuICogLy8gcmV0dXJucyAnMSwyMzR8NTYnXG4gKlxuICogQHBhcmFtICAge3N0cmluZ3xudW1iZXJ9IHZhbHVlICAgICAgIHRoZSB2YWx1ZSB0byBiZSBjb252ZXJ0ZWRcbiAqIEBwYXJhbSAgIHtzdHJpbmd9ICAgIHNlcGFyYXRvcnMgIHN0cmluZyBvZiBkZWNpbWFsLCB0aGVuIHRob3VzYW5kcyBzZXBhcmF0b3JzXG4gKiBAcGFyYW0gICB7Ym9vbGVhbn0gICAgc2VwYXJhdGV0aG91c2FuZHMgIGJvb2xlYW4sIDQtZGlnaXQgaW50ZWdlcnMgYXJlIHNlcGFyYXRlZCBpZiB0cnVlXG4gKlxuICogQHJldHVybiAge3N0cmluZ30gICAgdGhlIHZhbHVlIHRoYXQgaGFzIGJlZW4gc2VwYXJhdGVkXG4gKi9cbmxpYi5udW1TZXBhcmF0ZSA9IGZ1bmN0aW9uKHZhbHVlLCBzZXBhcmF0b3JzLCBzZXBhcmF0ZXRob3VzYW5kcykge1xuICAgIGlmKCFzZXBhcmF0ZXRob3VzYW5kcykgc2VwYXJhdGV0aG91c2FuZHMgPSBmYWxzZTtcblxuICAgIGlmKHR5cGVvZiBzZXBhcmF0b3JzICE9PSAnc3RyaW5nJyB8fCBzZXBhcmF0b3JzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1NlcGFyYXRvciBzdHJpbmcgcmVxdWlyZWQgZm9yIGZvcm1hdHRpbmchJyk7XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICB2YWx1ZSA9IFN0cmluZyh2YWx1ZSk7XG4gICAgfVxuXG4gICAgdmFyIHRob3VzYW5kc1JlID0gLyhcXGQrKShcXGR7M30pLztcbiAgICB2YXIgZGVjaW1hbFNlcCA9IHNlcGFyYXRvcnMuY2hhckF0KDApO1xuICAgIHZhciB0aG91U2VwID0gc2VwYXJhdG9ycy5jaGFyQXQoMSk7XG5cbiAgICB2YXIgeCA9IHZhbHVlLnNwbGl0KCcuJyk7XG4gICAgdmFyIHgxID0geFswXTtcbiAgICB2YXIgeDIgPSB4Lmxlbmd0aCA+IDEgPyBkZWNpbWFsU2VwICsgeFsxXSA6ICcnO1xuXG4gICAgLy8gWWVhcnMgYXJlIGlnbm9yZWQgZm9yIHRob3VzYW5kcyBzZXBhcmF0b3JzXG4gICAgaWYodGhvdVNlcCAmJiAoeC5sZW5ndGggPiAxIHx8IHgxLmxlbmd0aCA+IDQgfHwgc2VwYXJhdGV0aG91c2FuZHMpKSB7XG4gICAgICAgIHdoaWxlKHRob3VzYW5kc1JlLnRlc3QoeDEpKSB7XG4gICAgICAgICAgICB4MSA9IHgxLnJlcGxhY2UodGhvdXNhbmRzUmUsICckMScgKyB0aG91U2VwICsgJyQyJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geDEgKyB4Mjtcbn07XG5cbmxpYi5URU1QTEFURV9TVFJJTkdfUkVHRVggPSAvJXsoW15cXHMle306XSopKDpbXn1dKik/fS9nO1xudmFyIFNJTVBMRV9QUk9QRVJUWV9SRUdFWCA9IC9eXFx3KiQvO1xuXG4vKipcbiAqIFN1YnN0aXR1dGUgdmFsdWVzIGZyb20gYW4gb2JqZWN0IGludG8gYSBzdHJpbmdcbiAqXG4gKiBFeGFtcGxlczpcbiAqICBMaWIudGVtcGxhdGVTdHJpbmcoJ25hbWU6ICV7dHJhY2V9Jywge3RyYWNlOiAnYXNkZid9KSAtLT4gJ25hbWU6IGFzZGYnXG4gKiAgTGliLnRlbXBsYXRlU3RyaW5nKCduYW1lOiAle3RyYWNlWzBdLm5hbWV9Jywge3RyYWNlOiBbe25hbWU6ICdhc2RmJ31dfSkgLS0+ICduYW1lOiBhc2RmJ1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSAgaW5wdXQgc3RyaW5nIGNvbnRhaW5pbmcgJXsuLi59IHRlbXBsYXRlIHN0cmluZ3NcbiAqIEBwYXJhbSB7b2JqfSAgICAgZGF0YSBvYmplY3QgY29udGFpbmluZyBzdWJzdGl0dXRpb24gdmFsdWVzXG4gKlxuICogQHJldHVybiB7c3RyaW5nfSB0ZW1wbGF0ZWQgc3RyaW5nXG4gKi9cbmxpYi50ZW1wbGF0ZVN0cmluZyA9IGZ1bmN0aW9uKHN0cmluZywgb2JqKSB7XG4gICAgLy8gTm90IGFsbCB0aGF0IHVzZWZ1bCwgYnV0IGNhY2hlIG5lc3RlZFByb3BlcnR5IGluc3RhbnRpYXRpb25cbiAgICAvLyBqdXN0IGluIGNhc2UgaXQgc3BlZWRzIHRoaW5ncyB1cCAqc2xpZ2h0bHkqOlxuICAgIHZhciBnZXR0ZXJDYWNoZSA9IHt9O1xuXG4gICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKGxpYi5URU1QTEFURV9TVFJJTkdfUkVHRVgsIGZ1bmN0aW9uKGR1bW15LCBrZXkpIHtcbiAgICAgICAgaWYoU0lNUExFX1BST1BFUlRZX1JFR0VYLnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgcmV0dXJuIG9ialtrZXldIHx8ICcnO1xuICAgICAgICB9XG4gICAgICAgIGdldHRlckNhY2hlW2tleV0gPSBnZXR0ZXJDYWNoZVtrZXldIHx8IGxpYi5uZXN0ZWRQcm9wZXJ0eShvYmosIGtleSkuZ2V0O1xuICAgICAgICByZXR1cm4gZ2V0dGVyQ2FjaGVba2V5XSgpIHx8ICcnO1xuICAgIH0pO1xufTtcblxudmFyIFRFTVBMQVRFX1NUUklOR19GT1JNQVRfU0VQQVJBVE9SID0gL146LztcbnZhciBudW1iZXJPZkhvdmVyVGVtcGxhdGVXYXJuaW5ncyA9IDA7XG52YXIgbWF4aW11bU51bWJlck9mSG92ZXJUZW1wbGF0ZVdhcm5pbmdzID0gMTA7XG4vKipcbiAqIFN1YnN0aXR1dGUgdmFsdWVzIGZyb20gYW4gb2JqZWN0IGludG8gYSBzdHJpbmcgYW5kIG9wdGlvbmFsbHkgZm9ybWF0cyB0aGVtIHVzaW5nIGQzLWZvcm1hdCxcbiAqIG9yIGZhbGxiYWNrIHRvIGFzc29jaWF0ZWQgbGFiZWxzLlxuICpcbiAqIEV4YW1wbGVzOlxuICogIExpYi5ob3ZlcnRlbXBsYXRlU3RyaW5nKCduYW1lOiAle3RyYWNlfScsIHt0cmFjZTogJ2FzZGYnfSkgLS0+ICduYW1lOiBhc2RmJ1xuICogIExpYi5ob3ZlcnRlbXBsYXRlU3RyaW5nKCduYW1lOiAle3RyYWNlWzBdLm5hbWV9Jywge3RyYWNlOiBbe25hbWU6ICdhc2RmJ31dfSkgLS0+ICduYW1lOiBhc2RmJ1xuICogIExpYi5ob3ZlcnRlbXBsYXRlU3RyaW5nKCdwcmljZTogJXt5OiQuMmZ9Jywge3k6IDF9KSAtLT4gJ3ByaWNlOiAkMS4wMCdcbiAqXG4gKiBAcGFyYW0ge29ian0gICAgIGQzIGxvY2FsZVxuICogQHBhcmFtIHtzdHJpbmd9ICBpbnB1dCBzdHJpbmcgY29udGFpbmluZyAley4uLjouLi59IHRlbXBsYXRlIHN0cmluZ3NcbiAqIEBwYXJhbSB7b2JqfSAgICAgZGF0YSBvYmplY3QgY29udGFpbmluZyBmYWxsYmFjayB0ZXh0IHdoZW4gbm8gZm9ybWF0dGluZyBpcyBzcGVjaWZpZWQsIGV4Ljoge3lMYWJlbDogJ2Zvcm1hdHRlZFlWYWx1ZSd9XG4gKiBAcGFyYW0ge29ian0gICAgIGRhdGEgb2JqZWN0cyBjb250YWluaW5nIHN1YnN0aXR1dGlvbiB2YWx1ZXNcbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IHRlbXBsYXRlZCBzdHJpbmdcbiAqL1xubGliLmhvdmVydGVtcGxhdGVTdHJpbmcgPSBmdW5jdGlvbihzdHJpbmcsIGxhYmVscywgZDNsb2NhbGUpIHtcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAvLyBOb3QgYWxsIHRoYXQgdXNlZnVsLCBidXQgY2FjaGUgbmVzdGVkUHJvcGVydHkgaW5zdGFudGlhdGlvblxuICAgIC8vIGp1c3QgaW4gY2FzZSBpdCBzcGVlZHMgdGhpbmdzIHVwICpzbGlnaHRseSo6XG4gICAgdmFyIGdldHRlckNhY2hlID0ge307XG5cbiAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UobGliLlRFTVBMQVRFX1NUUklOR19SRUdFWCwgZnVuY3Rpb24obWF0Y2gsIGtleSwgZm9ybWF0KSB7XG4gICAgICAgIHZhciBvYmosIHZhbHVlLCBpO1xuICAgICAgICBmb3IoaSA9IDM7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBvYmogPSBhcmdzW2ldO1xuICAgICAgICAgICAgaWYob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IG9ialtrZXldO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZighU0lNUExFX1BST1BFUlRZX1JFR0VYLnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gZ2V0dGVyQ2FjaGVba2V5XSB8fCBsaWIubmVzdGVkUHJvcGVydHkob2JqLCBrZXkpLmdldCgpO1xuICAgICAgICAgICAgICAgIGlmKHZhbHVlKSBnZXR0ZXJDYWNoZVtrZXldID0gdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih2YWx1ZSAhPT0gdW5kZWZpbmVkKSBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmKG51bWJlck9mSG92ZXJUZW1wbGF0ZVdhcm5pbmdzIDwgbWF4aW11bU51bWJlck9mSG92ZXJUZW1wbGF0ZVdhcm5pbmdzKSB7XG4gICAgICAgICAgICAgICAgbGliLndhcm4oJ1ZhcmlhYmxlIFxcJycgKyBrZXkgKyAnXFwnIGluIGhvdmVydGVtcGxhdGUgY291bGQgbm90IGJlIGZvdW5kIScpO1xuICAgICAgICAgICAgICAgIHZhbHVlID0gbWF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKG51bWJlck9mSG92ZXJUZW1wbGF0ZVdhcm5pbmdzID09PSBtYXhpbXVtTnVtYmVyT2ZIb3ZlclRlbXBsYXRlV2FybmluZ3MpIHtcbiAgICAgICAgICAgICAgICBsaWIud2FybignVG9vIG1hbnkgaG92ZXJ0ZW1wbGF0ZSB3YXJuaW5ncyAtIGFkZGl0aW9uYWwgd2FybmluZ3Mgd2lsbCBiZSBzdXBwcmVzc2VkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBudW1iZXJPZkhvdmVyVGVtcGxhdGVXYXJuaW5ncysrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZm9ybWF0KSB7XG4gICAgICAgICAgICB2YXIgZm10O1xuICAgICAgICAgICAgaWYoZDNsb2NhbGUpIHtcbiAgICAgICAgICAgICAgICBmbXQgPSBkM2xvY2FsZS5udW1iZXJGb3JtYXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZtdCA9IGQzLmZvcm1hdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhbHVlID0gZm10KGZvcm1hdC5yZXBsYWNlKFRFTVBMQVRFX1NUUklOR19GT1JNQVRfU0VQQVJBVE9SLCAnJykpKHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKGxhYmVscy5oYXNPd25Qcm9wZXJ0eShrZXkgKyAnTGFiZWwnKSkgdmFsdWUgPSBsYWJlbHNba2V5ICsgJ0xhYmVsJ107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0pO1xufTtcblxuLypcbiAqIGFscGhhbnVtZXJpYyBzdHJpbmcgc29ydCwgdGFpbG9yZWQgZm9yIHN1YnBsb3QgSURzIGxpa2Ugc2NlbmUyLCBzY2VuZTEwLCB4MTB5MTMgZXRjXG4gKi9cbnZhciBjaGFyMCA9IDQ4O1xudmFyIGNoYXI5ID0gNTc7XG5saWIuc3VicGxvdFNvcnQgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIGwgPSBNYXRoLm1pbihhLmxlbmd0aCwgYi5sZW5ndGgpICsgMTtcbiAgICB2YXIgbnVtQSA9IDA7XG4gICAgdmFyIG51bUIgPSAwO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgdmFyIGNoYXJBID0gYS5jaGFyQ29kZUF0KGkpIHx8IDA7XG4gICAgICAgIHZhciBjaGFyQiA9IGIuY2hhckNvZGVBdChpKSB8fCAwO1xuICAgICAgICB2YXIgaXNOdW1BID0gY2hhckEgPj0gY2hhcjAgJiYgY2hhckEgPD0gY2hhcjk7XG4gICAgICAgIHZhciBpc051bUIgPSBjaGFyQiA+PSBjaGFyMCAmJiBjaGFyQiA8PSBjaGFyOTtcblxuICAgICAgICBpZihpc051bUEpIG51bUEgPSAxMCAqIG51bUEgKyBjaGFyQSAtIGNoYXIwO1xuICAgICAgICBpZihpc051bUIpIG51bUIgPSAxMCAqIG51bUIgKyBjaGFyQiAtIGNoYXIwO1xuXG4gICAgICAgIGlmKCFpc051bUEgfHwgIWlzTnVtQikge1xuICAgICAgICAgICAgaWYobnVtQSAhPT0gbnVtQikgcmV0dXJuIG51bUEgLSBudW1CO1xuICAgICAgICAgICAgaWYoY2hhckEgIT09IGNoYXJCKSByZXR1cm4gY2hhckEgLSBjaGFyQjtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVtQiAtIG51bUE7XG59O1xuXG4vLyByZXBlYXRhYmxlIHBzZXVkb3JhbmRvbSBnZW5lcmF0b3JcbnZhciByYW5kU2VlZCA9IDIwMDAwMDAwMDA7XG5cbmxpYi5zZWVkUHNldWRvUmFuZG9tID0gZnVuY3Rpb24oKSB7XG4gICAgcmFuZFNlZWQgPSAyMDAwMDAwMDAwO1xufTtcblxubGliLnBzZXVkb1JhbmRvbSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBsYXN0VmFsID0gcmFuZFNlZWQ7XG4gICAgcmFuZFNlZWQgPSAoNjkwNjkgKiByYW5kU2VlZCArIDEpICUgNDI5NDk2NzI5NjtcbiAgICAvLyBkb24ndCBsZXQgY29uc2VjdXRpdmUgdmFscyBiZSB0b28gY2xvc2UgdG9nZXRoZXJcbiAgICAvLyBnZXRzIGF3YXkgZnJvbSByZWFsbHkgdHJ5aW5nIHRvIGJlIHJhbmRvbSwgaW4gZmF2b3Igb2YgYmV0dGVyIGxvY2FsIHVuaWZvcm1pdHlcbiAgICBpZihNYXRoLmFicyhyYW5kU2VlZCAtIGxhc3RWYWwpIDwgNDI5NDk2NzI5KSByZXR1cm4gbGliLnBzZXVkb1JhbmRvbSgpO1xuICAgIHJldHVybiByYW5kU2VlZCAvIDQyOTQ5NjcyOTY7XG59O1xuXG5cbi8qKiBGaWxsIGhvdmVyICdwb2ludERhdGEnIGNvbnRhaW5lciB3aXRoICdjb3JyZWN0JyBob3ZlciB0ZXh0IHZhbHVlXG4gKlxuICogLSBJZiB0cmFjZSBob3ZlcmluZm8gY29udGFpbnMgYSAndGV4dCcgZmxhZyBhbmQgaG92ZXJ0ZXh0IGlzIG5vdCBzZXQsXG4gKiAgIHRoZSB0ZXh0IGVsZW1lbnRzIHdpbGwgYmUgc2VlbiBpbiB0aGUgaG92ZXIgbGFiZWxzLlxuICpcbiAqIC0gSWYgdHJhY2UgaG92ZXJpbmZvIGNvbnRhaW5zIGEgJ3RleHQnIGZsYWcgYW5kIGhvdmVydGV4dCBpcyBzZXQsXG4gKiAgIGhvdmVydGV4dCB0YWtlcyBwcmVjZWRlbmNlIG92ZXIgdGV4dFxuICogICBpLmUuIHRoZSBob3ZlcmluZm8gZWxlbWVudHMgd2lsbCBiZSBzZWVuIGluIHRoZSBob3ZlciBsYWJlbHNcbiAqXG4gKiAgQHBhcmFtIHtvYmplY3R9IGNhbGNQdFxuICogIEBwYXJhbSB7b2JqZWN0fSB0cmFjZVxuICogIEBwYXJhbSB7b2JqZWN0IHx8IGFycmF5fSBjb250T3V0IChtdXRhdGVkIGhlcmUpXG4gKi9cbmxpYi5maWxsVGV4dCA9IGZ1bmN0aW9uKGNhbGNQdCwgdHJhY2UsIGNvbnRPdXQpIHtcbiAgICB2YXIgZmlsbCA9IEFycmF5LmlzQXJyYXkoY29udE91dCkgP1xuICAgICAgICBmdW5jdGlvbih2KSB7IGNvbnRPdXQucHVzaCh2KTsgfSA6XG4gICAgICAgIGZ1bmN0aW9uKHYpIHsgY29udE91dC50ZXh0ID0gdjsgfTtcblxuICAgIHZhciBodHggPSBsaWIuZXh0cmFjdE9wdGlvbihjYWxjUHQsIHRyYWNlLCAnaHR4JywgJ2hvdmVydGV4dCcpO1xuICAgIGlmKGxpYi5pc1ZhbGlkVGV4dFZhbHVlKGh0eCkpIHJldHVybiBmaWxsKGh0eCk7XG5cbiAgICB2YXIgdHggPSBsaWIuZXh0cmFjdE9wdGlvbihjYWxjUHQsIHRyYWNlLCAndHgnLCAndGV4dCcpO1xuICAgIGlmKGxpYi5pc1ZhbGlkVGV4dFZhbHVlKHR4KSkgcmV0dXJuIGZpbGwodHgpO1xufTtcblxuLy8gYWNjZXB0IGFsbCB0cnV0aHkgdmFsdWVzIGFuZCAwICh3aGljaCBnZXRzIGNhc3QgdG8gJzAnIGluIHRoZSBob3ZlciBsYWJlbHMpXG5saWIuaXNWYWxpZFRleHRWYWx1ZSA9IGZ1bmN0aW9uKHYpIHtcbiAgICByZXR1cm4gdiB8fCB2ID09PSAwO1xufTtcblxubGliLmZvcm1hdFBlcmNlbnQgPSBmdW5jdGlvbihyYXRpbywgbikge1xuICAgIG4gPSBuIHx8IDA7XG4gICAgdmFyIHN0ciA9IChNYXRoLnJvdW5kKDEwMCAqIHJhdGlvICogTWF0aC5wb3coMTAsIG4pKSAqIE1hdGgucG93KDAuMSwgbikpLnRvRml4ZWQobikgKyAnJSc7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICBpZihzdHIuaW5kZXhPZignLicpICE9PSAtMSkge1xuICAgICAgICAgICAgc3RyID0gc3RyLnJlcGxhY2UoJzAlJywgJyUnKTtcbiAgICAgICAgICAgIHN0ciA9IHN0ci5yZXBsYWNlKCcuJScsICclJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHN0cjtcbn07XG5cbmxpYi5pc0hpZGRlbiA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGRpc3BsYXkgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShnZCkuZGlzcGxheTtcbiAgICByZXR1cm4gIWRpc3BsYXkgfHwgZGlzcGxheSA9PT0gJ25vbmUnO1xufTtcblxufSx7XCIuLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi9hbmNob3JfdXRpbHNcIjo3MDAsXCIuL2FuZ2xlc1wiOjcwMSxcIi4vYXJyYXlcIjo3MDIsXCIuL2NsZWFuX251bWJlclwiOjcwMyxcIi4vY2xlYXJfcmVzcG9uc2l2ZVwiOjcwNSxcIi4vY29lcmNlXCI6NzA2LFwiLi9kYXRlc1wiOjcwNyxcIi4vZG9tXCI6NzA4LFwiLi9leHRlbmRcIjo3MTAsXCIuL2ZpbHRlcl91bmlxdWVcIjo3MTEsXCIuL2ZpbHRlcl92aXNpYmxlXCI6NzEyLFwiLi9nZW9tZXRyeTJkXCI6NzE1LFwiLi9pZGVudGl0eVwiOjcxOCxcIi4vaXNfcGxhaW5fb2JqZWN0XCI6NzIwLFwiLi9rZXllZF9jb250YWluZXJcIjo3MjEsXCIuL2xvY2FsaXplXCI6NzIyLFwiLi9sb2dnZXJzXCI6NzIzLFwiLi9tYWtlX3RyYWNlX2dyb3Vwc1wiOjcyNCxcIi4vbWF0cml4XCI6NzI1LFwiLi9tb2RcIjo3MjYsXCIuL25lc3RlZF9wcm9wZXJ0eVwiOjcyNyxcIi4vbm9vcFwiOjcyOCxcIi4vbm90aWZpZXJcIjo3MjksXCIuL3B1c2hfdW5pcXVlXCI6NzMzLFwiLi9yZWdleFwiOjczNSxcIi4vcmVsYXRpdmVfYXR0clwiOjczNixcIi4vcmVsaW5rX3ByaXZhdGVcIjo3MzcsXCIuL3NlYXJjaFwiOjczOCxcIi4vc3RhdHNcIjo3NDEsXCIuL3Rocm90dGxlXCI6NzQ0LFwiLi90b19sb2dfcmFuZ2VcIjo3NDUsXCJkM1wiOjE2MyxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sNzIwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG4vLyBtb3JlIGluZm86IGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTg1MzE2MjQvaXNwbGFpbm9iamVjdC10aGluZ1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc1BsYWluT2JqZWN0KG9iaikge1xuICAgIC8vIFdlIG5lZWQgdG8gYmUgYSBsaXR0bGUgbGVzcyBzdHJpY3QgaW4gdGhlIGBpbWFnZXRlc3RgIGNvbnRhaW5lciBiZWNhdXNlXG4gICAgLy8gb2YgaG93IGFzeW5jIGltYWdlIHJlcXVlc3RzIGFyZSBoYW5kbGVkLlxuICAgIC8vXG4gICAgLy8gTi5CLiBpc1BsYWluT2JqZWN0KG5ldyBDb25zdHJ1Y3RvcigpKSB3aWxsIHJldHVybiB0cnVlIGluIGBpbWFnZXRlc3RgXG4gICAgaWYod2luZG93ICYmIHdpbmRvdy5wcm9jZXNzICYmIHdpbmRvdy5wcm9jZXNzLnZlcnNpb25zKSB7XG4gICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgT2JqZWN0XSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIChcbiAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IE9iamVjdF0nICYmXG4gICAgICAgIE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmopID09PSBPYmplY3QucHJvdG90eXBlXG4gICAgKTtcbn07XG5cbn0se31dLDcyMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBuZXN0ZWRQcm9wZXJ0eSA9IF9kZXJlcV8oJy4vbmVzdGVkX3Byb3BlcnR5Jyk7XG5cbnZhciBTSU1QTEVfUFJPUEVSVFlfUkVHRVggPSAvXlxcdyokLztcblxuLy8gYml0bWFzayBmb3IgZGVjaWRpbmcgd2hhdCdzIHVwZGF0ZWQuIFNvbWV0aW1lcyB0aGUgbmFtZSBuZWVkcyB0byBiZSB1cGRhdGVkLFxuLy8gc29tZXRpbWVzIHRoZSB2YWx1ZSBuZWVkcyB0byBiZSB1cGRhdGVkLCBhbmQgc29tZXRpbWVzIGJvdGggZG8uIFRoaXMgaXMganVzdFxuLy8gYSBzaW1wbGUgd2F5IHRvIHRyYWNrIHdoYXQncyB1cGRhdGVkIHN1Y2ggdGhhdCBpdCdzIGEgc2ltcGxlIE9SIG9wZXJhdGlvbiB0b1xuLy8gYXNzaW1pbGF0ZSBuZXcgdXBkYXRlcy5cbi8vXG4vLyBUaGUgb25seSBleGNlcHRpb24gaXMgdGhlIFVOU0VUIGJpdCB0aGF0IHRyYWNrcyB3aGVuIHdlIG5lZWQgdG8gZXhwbGljaXRseVxuLy8gdW5zZXQgYW5kIHJlbW92ZSB0aGUgcHJvcGVydHkuIFRoaXMgY29uY3JuIGFyaXNlcyBiZWNhdXNlIG9mIHRoZSBzcGVjaWFsXG4vLyB3YXkgaW4gd2hpY2ggbmVzdGVkUHJvcGVydHkgaGFuZGxlcyBudWxsL3VuZGVmaW5lZC4gV2hlbiB5b3Ugc3BlY2lmeSBgbnVsbGAsXG4vLyBpdCBwcnVuZXMgYW55IHVudXNlZCBpdGVtcyBpbiB0aGUgdHJlZS4gSSByYW4gaW50byBzb21lIGlzc3VlcyB3aXRoIGl0IGdldHRpbmdcbi8vIG51bGwgdnMgdW5kZWZpbmVkIGNvbmZ1c2VkLCBzbyBVTlNFVCBpcyBqdXN0IGEgYml0IHRoYXQgZm9yY2VzIHRoZSBwcm9wZXJ0eVxuLy8gdXBkYXRlIHRvIHNlbmQgYG51bGxgLCByZW1vdmluZyB0aGUgcHJvcGVydHkgZXhwbGljaXRseSByYXRoZXIgdGhhbiBzZXR0aW5nXG4vLyBpdCB0byB1bmRlZmluZWQuXG52YXIgTk9ORSA9IDA7XG52YXIgTkFNRSA9IDE7XG52YXIgVkFMVUUgPSAyO1xudmFyIEJPVEggPSAzO1xudmFyIFVOU0VUID0gNDtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBrZXllZENvbnRhaW5lcihiYXNlT2JqLCBwYXRoLCBrZXlOYW1lLCB2YWx1ZU5hbWUpIHtcbiAgICBrZXlOYW1lID0ga2V5TmFtZSB8fCAnbmFtZSc7XG4gICAgdmFsdWVOYW1lID0gdmFsdWVOYW1lIHx8ICd2YWx1ZSc7XG4gICAgdmFyIGksIGFyciwgYmFzZVByb3A7XG4gICAgdmFyIGNoYW5nZVR5cGVzID0ge307XG5cbiAgICBpZihwYXRoICYmIHBhdGgubGVuZ3RoKSB7XG4gICAgICAgIGJhc2VQcm9wID0gbmVzdGVkUHJvcGVydHkoYmFzZU9iaiwgcGF0aCk7XG4gICAgICAgIGFyciA9IGJhc2VQcm9wLmdldCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGFyciA9IGJhc2VPYmo7XG4gICAgfVxuXG4gICAgcGF0aCA9IHBhdGggfHwgJyc7XG5cbiAgICAvLyBDb25zdHJ1Y3QgYW4gaW5kZXg6XG4gICAgdmFyIGluZGV4TG9va3VwID0ge307XG4gICAgaWYoYXJyKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaW5kZXhMb29rdXBbYXJyW2ldW2tleU5hbWVdXSA9IGk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaXNTaW1wbGVWYWx1ZVByb3AgPSBTSU1QTEVfUFJPUEVSVFlfUkVHRVgudGVzdCh2YWx1ZU5hbWUpO1xuXG4gICAgdmFyIG9iaiA9IHtcbiAgICAgICAgc2V0OiBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgICAgICAgICAgdmFyIGNoYW5nZVR5cGUgPSB2YWx1ZSA9PT0gbnVsbCA/IFVOU0VUIDogTk9ORTtcblxuICAgICAgICAgICAgLy8gY3JlYXRlIHRoZSBiYXNlIGFycmF5IGlmIG5lY2Vzc2FyeVxuICAgICAgICAgICAgaWYoIWFycikge1xuICAgICAgICAgICAgICAgIGlmKCFiYXNlUHJvcCB8fCBjaGFuZ2VUeXBlID09PSBVTlNFVCkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgYXJyID0gW107XG4gICAgICAgICAgICAgICAgYmFzZVByb3Auc2V0KGFycik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBpZHggPSBpbmRleExvb2t1cFtuYW1lXTtcbiAgICAgICAgICAgIGlmKGlkeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgaWYoY2hhbmdlVHlwZSA9PT0gVU5TRVQpIHJldHVybjtcblxuICAgICAgICAgICAgICAgIGNoYW5nZVR5cGUgPSBjaGFuZ2VUeXBlIHwgQk9USDtcbiAgICAgICAgICAgICAgICBpZHggPSBhcnIubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGluZGV4TG9va3VwW25hbWVdID0gaWR4O1xuICAgICAgICAgICAgfSBlbHNlIGlmKHZhbHVlICE9PSAoaXNTaW1wbGVWYWx1ZVByb3AgPyBhcnJbaWR4XVt2YWx1ZU5hbWVdIDogbmVzdGVkUHJvcGVydHkoYXJyW2lkeF0sIHZhbHVlTmFtZSkuZ2V0KCkpKSB7XG4gICAgICAgICAgICAgICAgY2hhbmdlVHlwZSA9IGNoYW5nZVR5cGUgfCBWQUxVRTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIG5ld1ZhbHVlID0gYXJyW2lkeF0gPSBhcnJbaWR4XSB8fCB7fTtcbiAgICAgICAgICAgIG5ld1ZhbHVlW2tleU5hbWVdID0gbmFtZTtcblxuICAgICAgICAgICAgaWYoaXNTaW1wbGVWYWx1ZVByb3ApIHtcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZVt2YWx1ZU5hbWVdID0gdmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG5lc3RlZFByb3BlcnR5KG5ld1ZhbHVlLCB2YWx1ZU5hbWUpLnNldCh2YWx1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElmIGl0J3Mgbm90IGFuIHVuc2V0LCBmb3JjZSB0aGF0IGJpdCB0byBiZSB1bnNldC4gVGhpcyBpcyBhbGwgcmVsYXRlZCB0byB0aGUgZmFjdFxuICAgICAgICAgICAgLy8gdGhhdCB1bmRlZmluZWQgYW5kIG51bGwgYXJlIGEgYml0IHNwZWNpYWxseSBpbXBsZW1lbnRlZCBpbiBuZXN0ZWRQcm9wZXJ0aWVzLlxuICAgICAgICAgICAgaWYodmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjaGFuZ2VUeXBlID0gY2hhbmdlVHlwZSAmIH5VTlNFVDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2hhbmdlVHlwZXNbaWR4XSA9IGNoYW5nZVR5cGVzW2lkeF0gfCBjaGFuZ2VUeXBlO1xuXG4gICAgICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgICB9LFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgICAgIGlmKCFhcnIpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIGlkeCA9IGluZGV4TG9va3VwW25hbWVdO1xuXG4gICAgICAgICAgICBpZihpZHggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYoaXNTaW1wbGVWYWx1ZVByb3ApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJyW2lkeF1bdmFsdWVOYW1lXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5lc3RlZFByb3BlcnR5KGFycltpZHhdLCB2YWx1ZU5hbWUpLmdldCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICByZW5hbWU6IGZ1bmN0aW9uKG5hbWUsIG5ld05hbWUpIHtcbiAgICAgICAgICAgIHZhciBpZHggPSBpbmRleExvb2t1cFtuYW1lXTtcblxuICAgICAgICAgICAgaWYoaWR4ID09PSB1bmRlZmluZWQpIHJldHVybiBvYmo7XG4gICAgICAgICAgICBjaGFuZ2VUeXBlc1tpZHhdID0gY2hhbmdlVHlwZXNbaWR4XSB8IE5BTUU7XG5cbiAgICAgICAgICAgIGluZGV4TG9va3VwW25ld05hbWVdID0gaWR4O1xuICAgICAgICAgICAgZGVsZXRlIGluZGV4TG9va3VwW25hbWVdO1xuXG4gICAgICAgICAgICBhcnJbaWR4XVtrZXlOYW1lXSA9IG5ld05hbWU7XG5cbiAgICAgICAgICAgIHJldHVybiBvYmo7XG4gICAgICAgIH0sXG4gICAgICAgIHJlbW92ZTogZnVuY3Rpb24obmFtZSkge1xuICAgICAgICAgICAgdmFyIGlkeCA9IGluZGV4TG9va3VwW25hbWVdO1xuXG4gICAgICAgICAgICBpZihpZHggPT09IHVuZGVmaW5lZCkgcmV0dXJuIG9iajtcblxuICAgICAgICAgICAgdmFyIG9iamVjdCA9IGFycltpZHhdO1xuICAgICAgICAgICAgaWYoT2JqZWN0LmtleXMob2JqZWN0KS5sZW5ndGggPiAyKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhpcyBvYmplY3QgY29udGFpbnMgbW9yZSB0aGFuIGp1c3QgdGhlIGtleS92YWx1ZSwgc28gdW5zZXRcbiAgICAgICAgICAgICAgICAvLyB0aGUgdmFsdWUgd2l0aG91dCBtb2RpZnlpbmcgdGhlIGVudHJ5IG90aGVyd2lzZTpcbiAgICAgICAgICAgICAgICBjaGFuZ2VUeXBlc1tpZHhdID0gY2hhbmdlVHlwZXNbaWR4XSB8IFZBTFVFO1xuICAgICAgICAgICAgICAgIHJldHVybiBvYmouc2V0KG5hbWUsIG51bGwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihpc1NpbXBsZVZhbHVlUHJvcCkge1xuICAgICAgICAgICAgICAgIGZvcihpID0gaWR4OyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZVR5cGVzW2ldID0gY2hhbmdlVHlwZXNbaV0gfCBCT1RIO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IoaSA9IGlkeDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpbmRleExvb2t1cFthcnJbaV1ba2V5TmFtZV1dLS07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgICBkZWxldGUoaW5kZXhMb29rdXBbbmFtZV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBQZXJmb3JtIHRoaXMgdXBkYXRlICpzdHJpY3RseSogc28gd2UgY2FuIGNoZWNrIHdoZXRoZXIgdGhlIHJlc3VsdCdzXG4gICAgICAgICAgICAgICAgLy8gYmVlbiBwcnVuZWQuIElmIHNvLCBpdCdzIGEgcmVtb3ZhbC4gSWYgbm90LCBpdCdzIGEgdmFsdWUgdW5zZXQgb25seS5cbiAgICAgICAgICAgICAgICBuZXN0ZWRQcm9wZXJ0eShvYmplY3QsIHZhbHVlTmFtZSkuc2V0KG51bGwpO1xuXG4gICAgICAgICAgICAgICAgLy8gTm93IGNoZWNrIGlmIHRoZSB0b3AgbGV2ZWwgbmVzdGVkIHByb3BlcnR5IGhhcyBhbnkga2V5cyBsZWZ0LiBJZiBzbyxcbiAgICAgICAgICAgICAgICAvLyB0aGUgb2JqZWN0IHN0aWxsIGhhcyB2YWx1ZXMgc28gd2Ugb25seSB3YW50IHRvIHVuc2V0IHRoZSBrZXkuIElmIG5vdCxcbiAgICAgICAgICAgICAgICAvLyB0aGUgZW50aXJlIG9iamVjdCBjYW4gYmUgcmVtb3ZlZCBzaW5jZSB0aGVyZSdzIG5vIG90aGVyIGRhdGEuXG4gICAgICAgICAgICAgICAgLy8gdmFyIHRvcExldmVsS2V5cyA9IE9iamVjdC5rZXlzKG9iamVjdFt2YWx1ZU5hbWUuc3BsaXQoJy4nKVswXV0gfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgY2hhbmdlVHlwZXNbaWR4XSA9IGNoYW5nZVR5cGVzW2lkeF0gfCBWQUxVRSB8IFVOU0VUO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgICB9LFxuICAgICAgICBjb25zdHJ1Y3RVcGRhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGFzdHIsIGlkeDtcbiAgICAgICAgICAgIHZhciB1cGRhdGUgPSB7fTtcbiAgICAgICAgICAgIHZhciBjaGFuZ2VkID0gT2JqZWN0LmtleXMoY2hhbmdlVHlwZXMpO1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNoYW5nZWQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZHggPSBjaGFuZ2VkW2ldO1xuICAgICAgICAgICAgICAgIGFzdHIgPSBwYXRoICsgJ1snICsgaWR4ICsgJ10nO1xuICAgICAgICAgICAgICAgIGlmKGFycltpZHhdKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGNoYW5nZVR5cGVzW2lkeF0gJiBOQU1FKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVbYXN0ciArICcuJyArIGtleU5hbWVdID0gYXJyW2lkeF1ba2V5TmFtZV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYoY2hhbmdlVHlwZXNbaWR4XSAmIFZBTFVFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihpc1NpbXBsZVZhbHVlUHJvcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZVthc3RyICsgJy4nICsgdmFsdWVOYW1lXSA9IChjaGFuZ2VUeXBlc1tpZHhdICYgVU5TRVQpID8gbnVsbCA6IGFycltpZHhdW3ZhbHVlTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZVthc3RyICsgJy4nICsgdmFsdWVOYW1lXSA9IChjaGFuZ2VUeXBlc1tpZHhdICYgVU5TRVQpID8gbnVsbCA6IG5lc3RlZFByb3BlcnR5KGFycltpZHhdLCB2YWx1ZU5hbWUpLmdldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlW2FzdHJdID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB1cGRhdGU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIG9iajtcbn07XG5cbn0se1wiLi9uZXN0ZWRfcHJvcGVydHlcIjo3Mjd9XSw3MjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uL3JlZ2lzdHJ5Jyk7XG5cbi8qKlxuICogbG9jYWxpemU6IHRyYW5zbGF0ZSBhIHN0cmluZyBmb3IgdGhlIGN1cnJlbnQgbG9jYWxlXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGdkOiB0aGUgZ3JhcGhEaXYgZm9yIGNvbnRleHRcbiAqICBnZC5fY29udGV4dC5sb2NhbGUgZGV0ZXJtaW5lcyB0aGUgbGFuZ3VhZ2UgKCYgb3B0aW9uYWwgcmVnaW9uL2NvdW50cnkpXG4gKiAgdGhlIGRpY3Rpb25hcnkgZm9yIGVhY2ggbG9jYWxlIG1heSBlaXRoZXIgYmUgc3VwcGxpZWQgaW5cbiAqICBnZC5fY29udGV4dC5sb2NhbGVzIG9yIGdsb2JhbGx5IHZpYSBQbG90bHkucmVnaXN0ZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBzOiB0aGUgc3RyaW5nIHRvIHRyYW5zbGF0ZVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGxvY2FsaXplKGdkLCBzKSB7XG4gICAgdmFyIGxvY2FsZSA9IGdkLl9jb250ZXh0LmxvY2FsZTtcblxuICAgIC8qXG4gICAgICogUHJpb3JpdHkgb2YgbG9va3VwOlxuICAgICAqICAgICBjb250ZXh0RGljdHNbbG9jYWxlXSxcbiAgICAgKiAgICAgcmVnaXN0ZXJlZERpY3RzW2xvY2FsZV0sXG4gICAgICogICAgIGNvbnRleHREaWN0c1tiYXNlTG9jYWxlXSwgKGlmIGJhc2VMb2NhbGUgaXMgZGlzdGluY3QpXG4gICAgICogICAgIHJlZ2lzdGVyZWREaWN0c1tiYXNlTG9jYWxlXVxuICAgICAqIFJldHVybiB0aGUgZmlyc3QgdHJhbnNsYXRpb24gd2UgZmluZC5cbiAgICAgKiBUaGlzIHdheSBpZiB5b3UgaGF2ZSBhIHJlZ2lvbmFsaXphdGlvbiB5b3UgYXJlIGFsbG93ZWQgdG8gc3BlY2lmeVxuICAgICAqIG9ubHkgd2hhdCdzIGRpZmZlcmVudCBmcm9tIHRoZSBiYXNlIGxvY2FsZSwgZXZlcnl0aGluZyBlbHNlIHdpbGxcbiAgICAgKiBmYWxsIGJhY2sgb24gdGhlIGJhc2UuXG4gICAgICovXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDI7IGkrKykge1xuICAgICAgICB2YXIgbG9jYWxlcyA9IGdkLl9jb250ZXh0LmxvY2FsZXM7XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCAyOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBkaWN0ID0gKGxvY2FsZXNbbG9jYWxlXSB8fCB7fSkuZGljdGlvbmFyeTtcbiAgICAgICAgICAgIGlmKGRpY3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgb3V0ID0gZGljdFtzXTtcbiAgICAgICAgICAgICAgICBpZihvdXQpIHJldHVybiBvdXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsb2NhbGVzID0gUmVnaXN0cnkubG9jYWxlUmVnaXN0cnk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYmFzZUxvY2FsZSA9IGxvY2FsZS5zcGxpdCgnLScpWzBdO1xuICAgICAgICBpZihiYXNlTG9jYWxlID09PSBsb2NhbGUpIGJyZWFrO1xuICAgICAgICBsb2NhbGUgPSBiYXNlTG9jYWxlO1xuICAgIH1cblxuICAgIHJldHVybiBzO1xufTtcblxufSx7XCIuLi9yZWdpc3RyeVwiOjg0N31dLDcyMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxudmFyIGRmbHRDb25maWcgPSBfZGVyZXFfKCcuLi9wbG90X2FwaS9wbG90X2NvbmZpZycpLmRmbHRDb25maWc7XG5cbnZhciBsb2dnZXJzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLyoqXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIGRlYnVnZ2luZyB0b29sc1xuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxubG9nZ2Vycy5sb2cgPSBmdW5jdGlvbigpIHtcbiAgICBpZihkZmx0Q29uZmlnLmxvZ2dpbmcgPiAxKSB7XG4gICAgICAgIHZhciBtZXNzYWdlcyA9IFsnTE9HOiddO1xuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG1lc3NhZ2VzLnB1c2goYXJndW1lbnRzW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFwcGx5KGNvbnNvbGUudHJhY2UgfHwgY29uc29sZS5sb2csIG1lc3NhZ2VzKTtcbiAgICB9XG59O1xuXG5sb2dnZXJzLndhcm4gPSBmdW5jdGlvbigpIHtcbiAgICBpZihkZmx0Q29uZmlnLmxvZ2dpbmcgPiAwKSB7XG4gICAgICAgIHZhciBtZXNzYWdlcyA9IFsnV0FSTjonXTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBtZXNzYWdlcy5wdXNoKGFyZ3VtZW50c1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICBhcHBseShjb25zb2xlLnRyYWNlIHx8IGNvbnNvbGUubG9nLCBtZXNzYWdlcyk7XG4gICAgfVxufTtcblxubG9nZ2Vycy5lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgIGlmKGRmbHRDb25maWcubG9nZ2luZyA+IDApIHtcbiAgICAgICAgdmFyIG1lc3NhZ2VzID0gWydFUlJPUjonXTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBtZXNzYWdlcy5wdXNoKGFyZ3VtZW50c1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICBhcHBseShjb25zb2xlLmVycm9yLCBtZXNzYWdlcyk7XG4gICAgfVxufTtcblxuLypcbiAqIFJvYnVzdCBhcHBseSwgZm9yIElFOSB3aGVyZSBjb25zb2xlLmxvZyBkb2Vzbid0IHN1cHBvcnRcbiAqIGFwcGx5IGxpa2Ugb3RoZXIgZnVuY3Rpb25zIGRvXG4gKi9cbmZ1bmN0aW9uIGFwcGx5KGYsIGFyZ3MpIHtcbiAgICBpZihmICYmIGYuYXBwbHkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIGB0aGlzYCBzaG91bGQgYWx3YXlzIGJlIGNvbnNvbGUsIHNpbmNlIGhlcmUgd2UncmUgYWx3YXlzXG4gICAgICAgICAgICAvLyBhcHBseWluZyBhIG1ldGhvZCBvZiB0aGUgY29uc29sZSBvYmplY3QuXG4gICAgICAgICAgICBmLmFwcGx5KGNvbnNvbGUsIGFyZ3MpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGNhdGNoKGUpIHsgLyogaW4gY2FzZSBhcHBseSBmYWlsZWQsIGZhbGwgYmFjayBvbiB0aGUgY29kZSBiZWxvdyAqLyB9XG4gICAgfVxuXG4gICAgLy8gbm8gYXBwbHkgLSBqdXN0IHRyeSBjYWxsaW5nIHRoZSBmdW5jdGlvbiBvbiBlYWNoIGFyZyBpbmRlcGVuZGVudGx5XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGYoYXJnc1tpXSk7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgLy8gc3RpbGwgZmFpbHMgLSBsYXN0IHJlc29ydCBzaW1wbGUgY29uc29sZS5sb2dcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGFyZ3NbaV0pO1xuICAgICAgICB9XG4gICAgfVxufVxuXG59LHtcIi4uL3Bsb3RfYXBpL3Bsb3RfY29uZmlnXCI6NzU1fV0sNzI0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxuLyoqXG4gKiBHZW5lcmFsIGhlbHBlciB0byBtYW5hZ2UgdHJhY2UgZ3JvdXBzIGJhc2VkIG9uIGNhbGNkYXRhXG4gKlxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IHRyYWNlTGF5ZXI6IGEgc2VsZWN0aW9uIGNvbnRhaW5pbmcgYSBzaW5nbGUgZ3JvdXBcbiAqICAgICB0byBkcmF3IHRoZXNlIHRyYWNlcyBpbnRvXG4gKiBAcGFyYW0ge2FycmF5fSBjZE1vZHVsZTogYXJyYXkgb2YgY2FsY2RhdGEgaXRlbXMgZm9yIHRoaXNcbiAqICAgICBtb2R1bGUgYW5kIHN1YnBsb3QgY29tYmluYXRpb24uIEFzc3VtZXMgdGhlIGNhbGNkYXRhIGl0ZW0gZm9yIGVhY2hcbiAqICAgICB0cmFjZSBpcyBhbiBhcnJheSB3aXRoIHRoZSBmdWxsRGF0YSB0cmFjZSBhdHRhY2hlZCB0byB0aGUgZmlyc3QgaXRlbS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjbHM6IHRoZSBjbGFzcyBhdHRyaWJ1dGUgdG8gZ2l2ZSBlYWNoIHRyYWNlIGdyb3VwXG4gKiAgICAgc28geW91IGNhbiBnaXZlIG11bHRpcGxlIGNsYXNzZXMgc2VwYXJhdGVkIGJ5IHNwYWNlc1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1ha2VUcmFjZUdyb3Vwcyh0cmFjZUxheWVyLCBjZE1vZHVsZSwgY2xzKSB7XG4gICAgdmFyIHRyYWNlcyA9IHRyYWNlTGF5ZXIuc2VsZWN0QWxsKCdnLicgKyBjbHMucmVwbGFjZSgvXFxzL2csICcuJykpXG4gICAgICAgIC5kYXRhKGNkTW9kdWxlLCBmdW5jdGlvbihjZCkgeyByZXR1cm4gY2RbMF0udHJhY2UudWlkOyB9KTtcblxuICAgIHRyYWNlcy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICB0cmFjZXMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCBjbHMpO1xuXG4gICAgdHJhY2VzLm9yZGVyKCk7XG5cbiAgICAvLyBzdGFzaCByZWYgbm9kZSB0byB0cmFjZSBncm91cCBpbiBjYWxjZGF0YSxcbiAgICAvLyB1c2VmdWwgZm9yIChmYXN0KSBzdHlsZU9uU2VsZWN0XG4gICAgdmFyIGsgPSB0cmFjZUxheWVyLmNsYXNzZWQoJ3JhbmdlcGxvdCcpID8gJ25vZGVSYW5nZVBsb3QzJyA6ICdub2RlMyc7XG4gICAgdHJhY2VzLmVhY2goZnVuY3Rpb24oY2QpIHsgY2RbMF1ba10gPSBkMy5zZWxlY3QodGhpcyk7IH0pO1xuXG4gICAgcmV0dXJuIHRyYWNlcztcbn07XG5cbn0se1wiZDNcIjoxNjN9XSw3MjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxuZXhwb3J0cy5pbml0MmRBcnJheSA9IGZ1bmN0aW9uKHJvd0xlbmd0aCwgY29sTGVuZ3RoKSB7XG4gICAgdmFyIGFycmF5ID0gbmV3IEFycmF5KHJvd0xlbmd0aCk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHJvd0xlbmd0aDsgaSsrKSBhcnJheVtpXSA9IG5ldyBBcnJheShjb2xMZW5ndGgpO1xuICAgIHJldHVybiBhcnJheTtcbn07XG5cbi8qKlxuICogdHJhbnNwb3NlIGEgKHBvc3NpYmx5IHJhZ2dlZCkgMmQgYXJyYXkgei4gaW5zcGlyZWQgYnlcbiAqIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTc0Mjg1ODcvXG4gKiB0cmFuc3Bvc2luZy1hLTJkLWFycmF5LWluLWphdmFzY3JpcHRcbiAqL1xuZXhwb3J0cy50cmFuc3Bvc2VSYWdnZWQgPSBmdW5jdGlvbih6KSB7XG4gICAgdmFyIG1heGxlbiA9IDA7XG4gICAgdmFyIHpsZW4gPSB6Lmxlbmd0aDtcbiAgICB2YXIgaSwgajtcbiAgICAvLyBNYXhpbXVtIHJvdyBsZW5ndGg6XG4gICAgZm9yKGkgPSAwOyBpIDwgemxlbjsgaSsrKSBtYXhsZW4gPSBNYXRoLm1heChtYXhsZW4sIHpbaV0ubGVuZ3RoKTtcblxuICAgIHZhciB0ID0gbmV3IEFycmF5KG1heGxlbik7XG4gICAgZm9yKGkgPSAwOyBpIDwgbWF4bGVuOyBpKyspIHtcbiAgICAgICAgdFtpXSA9IG5ldyBBcnJheSh6bGVuKTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgemxlbjsgaisrKSB0W2ldW2pdID0geltqXVtpXTtcbiAgICB9XG5cbiAgICByZXR1cm4gdDtcbn07XG5cbi8vIG91ciBvd24gZG90IGZ1bmN0aW9uIHNvIHRoYXQgd2UgZG9uJ3QgbmVlZCB0byBpbmNsdWRlIG51bWVyaWNcbmV4cG9ydHMuZG90ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIGlmKCEoeC5sZW5ndGggJiYgeS5sZW5ndGgpIHx8IHgubGVuZ3RoICE9PSB5Lmxlbmd0aCkgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgbGVuID0geC5sZW5ndGg7XG4gICAgdmFyIG91dDtcbiAgICB2YXIgaTtcblxuICAgIGlmKHhbMF0ubGVuZ3RoKSB7XG4gICAgICAgIC8vIG1hdC12ZWMgb3IgbWF0LW1hdFxuICAgICAgICBvdXQgPSBuZXcgQXJyYXkobGVuKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIG91dFtpXSA9IGV4cG9ydHMuZG90KHhbaV0sIHkpO1xuICAgIH0gZWxzZSBpZih5WzBdLmxlbmd0aCkge1xuICAgICAgICAvLyB2ZWMtbWF0XG4gICAgICAgIHZhciB5VHJhbnNwb3NlID0gZXhwb3J0cy50cmFuc3Bvc2VSYWdnZWQoeSk7XG4gICAgICAgIG91dCA9IG5ldyBBcnJheSh5VHJhbnNwb3NlLmxlbmd0aCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHlUcmFuc3Bvc2UubGVuZ3RoOyBpKyspIG91dFtpXSA9IGV4cG9ydHMuZG90KHgsIHlUcmFuc3Bvc2VbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHZlYy12ZWNcbiAgICAgICAgb3V0ID0gMDtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIG91dCArPSB4W2ldICogeVtpXTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLy8gdHJhbnNsYXRlIGJ5ICh4LHkpXG5leHBvcnRzLnRyYW5zbGF0aW9uTWF0cml4ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHJldHVybiBbWzEsIDAsIHhdLCBbMCwgMSwgeV0sIFswLCAwLCAxXV07XG59O1xuXG4vLyByb3RhdGUgYnkgYWxwaGEgYXJvdW5kICgwLDApXG5leHBvcnRzLnJvdGF0aW9uTWF0cml4ID0gZnVuY3Rpb24oYWxwaGEpIHtcbiAgICB2YXIgYSA9IGFscGhhICogTWF0aC5QSSAvIDE4MDtcbiAgICByZXR1cm4gW1tNYXRoLmNvcyhhKSwgLU1hdGguc2luKGEpLCAwXSxcbiAgICAgICAgICAgIFtNYXRoLnNpbihhKSwgTWF0aC5jb3MoYSksIDBdLFxuICAgICAgICAgICAgWzAsIDAsIDFdXTtcbn07XG5cbi8vIHJvdGF0ZSBieSBhbHBoYSBhcm91bmQgKHgseSlcbmV4cG9ydHMucm90YXRpb25YWU1hdHJpeCA9IGZ1bmN0aW9uKGEsIHgsIHkpIHtcbiAgICByZXR1cm4gZXhwb3J0cy5kb3QoXG4gICAgICAgIGV4cG9ydHMuZG90KGV4cG9ydHMudHJhbnNsYXRpb25NYXRyaXgoeCwgeSksXG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHMucm90YXRpb25NYXRyaXgoYSkpLFxuICAgICAgICBleHBvcnRzLnRyYW5zbGF0aW9uTWF0cml4KC14LCAteSkpO1xufTtcblxuLy8gYXBwbGllcyBhIDJEIHRyYW5zZm9ybWF0aW9uIG1hdHJpeCB0byBlaXRoZXIgeCBhbmQgeSBwYXJhbXMgb3IgYW4gW3gseV0gYXJyYXlcbmV4cG9ydHMuYXBwbHkyRFRyYW5zZm9ybSA9IGZ1bmN0aW9uKHRyYW5zZm9ybSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIGlmKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgICBhcmdzID0gYXJnc1swXTtcbiAgICAgICAgfS8vIGZyb20gbWFwXG4gICAgICAgIHZhciB4eSA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyBhcmdzWzBdIDogW2FyZ3NbMF0sIGFyZ3NbMV1dO1xuICAgICAgICByZXR1cm4gZXhwb3J0cy5kb3QodHJhbnNmb3JtLCBbeHlbMF0sIHh5WzFdLCAxXSkuc2xpY2UoMCwgMik7XG4gICAgfTtcbn07XG5cbi8vIGFwcGxpZXMgYSAyRCB0cmFuc2Zvcm1hdGlvbiBtYXRyaXggdG8gYW4gW3gxLHkxLHgyLHkyXSBhcnJheSAodG8gdHJhbnNmb3JtIGEgc2VnbWVudClcbmV4cG9ydHMuYXBwbHkyRFRyYW5zZm9ybTIgPSBmdW5jdGlvbih0cmFuc2Zvcm0pIHtcbiAgICB2YXIgYXQgPSBleHBvcnRzLmFwcGx5MkRUcmFuc2Zvcm0odHJhbnNmb3JtKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oeHlzKSB7XG4gICAgICAgIHJldHVybiBhdCh4eXMuc2xpY2UoMCwgMikpLmNvbmNhdChhdCh4eXMuc2xpY2UoMiwgNCkpKTtcbiAgICB9O1xufTtcblxufSx7fV0sNzI2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBzYW5pdGl6ZWQgbW9kdWx1cyBmdW5jdGlvbiB0aGF0IGFsd2F5cyByZXR1cm5zIGluIHRoZSByYW5nZSBbMCwgZClcbiAqIHJhdGhlciB0aGFuICgtZCwgMF0gaWYgdiBpcyBuZWdhdGl2ZVxuICovXG5mdW5jdGlvbiBtb2QodiwgZCkge1xuICAgIHZhciBvdXQgPSB2ICUgZDtcbiAgICByZXR1cm4gb3V0IDwgMCA/IG91dCArIGQgOiBvdXQ7XG59XG5cbi8qKlxuICogc2FuaXRpemVkIG1vZHVsdXMgZnVuY3Rpb24gdGhhdCBhbHdheXMgcmV0dXJucyBpbiB0aGUgcmFuZ2UgWy1kLzIsIGQvMl1cbiAqIHJhdGhlciB0aGFuICgtZCwgMF0gaWYgdiBpcyBuZWdhdGl2ZVxuICovXG5mdW5jdGlvbiBtb2RIYWxmKHYsIGQpIHtcbiAgICByZXR1cm4gTWF0aC5hYnModikgPiAoZCAvIDIpID9cbiAgICAgICAgdiAtIE1hdGgucm91bmQodiAvIGQpICogZCA6XG4gICAgICAgIHY7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZDogbW9kLFxuICAgIG1vZEhhbGY6IG1vZEhhbGZcbn07XG5cbn0se31dLDcyNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IF9kZXJlcV8oJy4vYXJyYXknKS5pc0FycmF5T3JUeXBlZEFycmF5O1xuXG4vKipcbiAqIGNvbnZlcnQgYSBzdHJpbmcgcyAoc3VjaCBhcyAneGF4aXMucmFuZ2VbMF0nKVxuICogcmVwcmVzZW50aW5nIGEgcHJvcGVydHkgb2YgbmVzdGVkIG9iamVjdCBpbnRvIHNldCBhbmQgZ2V0IG1ldGhvZHNcbiAqIGFsc28gcmV0dXJuIHRoZSBzdHJpbmcgYW5kIG9iamVjdCBzbyB3ZSBkb24ndCBoYXZlIHRvIGtlZXAgdHJhY2sgb2YgdGhlbVxuICogYWxsb3dzIFstMV0gZm9yIGFuIGFycmF5IGluZGV4LCB0byBzZXQgYSBwcm9wZXJ0eSBpbnNpZGUgYWxsIGVsZW1lbnRzXG4gKiBvZiBhbiBhcnJheVxuICogZWcgaWYgb2JqID0ge2FycjogW3thOiAxfSwge2E6IDJ9XX1cbiAqIHlvdSBjYW4gZG8gcCA9IG5lc3RlZFByb3BlcnR5KG9iaiwgJ2FyclstMV0uYScpXG4gKiBidXQgeW91IGNhbm5vdCBzZXQgdGhlIGFycmF5IGl0c2VsZiB0aGlzIHdheSwgdG8gZG8gdGhhdFxuICoganVzdCBzZXQgdGhlIHdob2xlIGFycmF5LlxuICogZWcgaWYgb2JqID0ge2FycjogWzEsIDIsIDNdfVxuICogeW91IGNhbid0IGRvIG5lc3RlZFByb3BlcnR5KG9iaiwgJ2FyclstMV0nKS5zZXQoNSlcbiAqIGJ1dCB5b3UgY2FuIGRvIG5lc3RlZFByb3BlcnR5KG9iaiwgJ2FycicpLnNldChbNSwgNSwgNV0pXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbmVzdGVkUHJvcGVydHkoY29udGFpbmVyLCBwcm9wU3RyKSB7XG4gICAgaWYoaXNOdW1lcmljKHByb3BTdHIpKSBwcm9wU3RyID0gU3RyaW5nKHByb3BTdHIpO1xuICAgIGVsc2UgaWYodHlwZW9mIHByb3BTdHIgIT09ICdzdHJpbmcnIHx8XG4gICAgICAgICAgICBwcm9wU3RyLnN1YnN0cihwcm9wU3RyLmxlbmd0aCAtIDQpID09PSAnWy0xXScpIHtcbiAgICAgICAgdGhyb3cgJ2JhZCBwcm9wZXJ0eSBzdHJpbmcnO1xuICAgIH1cblxuICAgIHZhciBqID0gMDtcbiAgICB2YXIgcHJvcFBhcnRzID0gcHJvcFN0ci5zcGxpdCgnLicpO1xuICAgIHZhciBpbmRleGVkO1xuICAgIHZhciBpbmRpY2VzO1xuICAgIHZhciBpO1xuXG4gICAgLy8gY2hlY2sgZm9yIHBhcnRzIG9mIHRoZSBuZXN0aW5nIGhpZXJhcmNoeSB0aGF0IGFyZSBudW1iZXJzIChpZSBhcnJheSBlbGVtZW50cylcbiAgICB3aGlsZShqIDwgcHJvcFBhcnRzLmxlbmd0aCkge1xuICAgICAgICAvLyBsb29rIGZvciBub24tYnJhY2tldCBjaGFycywgdGhlbiBhbnkgbnVtYmVyIG9mIFsjI10gYmxvY2tzXG4gICAgICAgIGluZGV4ZWQgPSBTdHJpbmcocHJvcFBhcnRzW2pdKS5tYXRjaCgvXihbXlxcW1xcXV0qKSgoXFxbXFwtP1swLTldKlxcXSkrKSQvKTtcbiAgICAgICAgaWYoaW5kZXhlZCkge1xuICAgICAgICAgICAgaWYoaW5kZXhlZFsxXSkgcHJvcFBhcnRzW2pdID0gaW5kZXhlZFsxXTtcbiAgICAgICAgICAgIC8vIGFsbG93IHByb3BTdHIgdG8gc3RhcnQgd2l0aCBicmFja2V0ZWQgYXJyYXkgaW5kaWNlc1xuICAgICAgICAgICAgZWxzZSBpZihqID09PSAwKSBwcm9wUGFydHMuc3BsaWNlKDAsIDEpO1xuICAgICAgICAgICAgZWxzZSB0aHJvdyAnYmFkIHByb3BlcnR5IHN0cmluZyc7XG5cbiAgICAgICAgICAgIGluZGljZXMgPSBpbmRleGVkWzJdXG4gICAgICAgICAgICAgICAgLnN1YnN0cigxLCBpbmRleGVkWzJdLmxlbmd0aCAtIDIpXG4gICAgICAgICAgICAgICAgLnNwbGl0KCddWycpO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaisrO1xuICAgICAgICAgICAgICAgIHByb3BQYXJ0cy5zcGxpY2UoaiwgMCwgTnVtYmVyKGluZGljZXNbaV0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBqKys7XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIGNvbnRhaW5lciAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgcmV0dXJuIGJhZENvbnRhaW5lcihjb250YWluZXIsIHByb3BTdHIsIHByb3BQYXJ0cyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgc2V0OiBucFNldChjb250YWluZXIsIHByb3BQYXJ0cywgcHJvcFN0ciksXG4gICAgICAgIGdldDogbnBHZXQoY29udGFpbmVyLCBwcm9wUGFydHMpLFxuICAgICAgICBhc3RyOiBwcm9wU3RyLFxuICAgICAgICBwYXJ0czogcHJvcFBhcnRzLFxuICAgICAgICBvYmo6IGNvbnRhaW5lclxuICAgIH07XG59O1xuXG5mdW5jdGlvbiBucEdldChjb250LCBwYXJ0cykge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGN1ckNvbnQgPSBjb250O1xuICAgICAgICB2YXIgY3VyUGFydDtcbiAgICAgICAgdmFyIGFsbFNhbWU7XG4gICAgICAgIHZhciBvdXQ7XG4gICAgICAgIHZhciBpO1xuICAgICAgICB2YXIgajtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgIGN1clBhcnQgPSBwYXJ0c1tpXTtcbiAgICAgICAgICAgIGlmKGN1clBhcnQgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgYWxsU2FtZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgb3V0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY3VyQ29udC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBvdXRbal0gPSBucEdldChjdXJDb250W2pdLCBwYXJ0cy5zbGljZShpICsgMSkpKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmKG91dFtqXSAhPT0gb3V0WzBdKSBhbGxTYW1lID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBhbGxTYW1lID8gb3V0WzBdIDogb3V0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYodHlwZW9mIGN1clBhcnQgPT09ICdudW1iZXInICYmICFpc0FycmF5T3JUeXBlZEFycmF5KGN1ckNvbnQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN1ckNvbnQgPSBjdXJDb250W2N1clBhcnRdO1xuICAgICAgICAgICAgaWYodHlwZW9mIGN1ckNvbnQgIT09ICdvYmplY3QnIHx8IGN1ckNvbnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gb25seSBoaXQgdGhpcyBpZiBwYXJ0cy5sZW5ndGggPT09IDFcbiAgICAgICAgaWYodHlwZW9mIGN1ckNvbnQgIT09ICdvYmplY3QnIHx8IGN1ckNvbnQgPT09IG51bGwpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgICAgb3V0ID0gY3VyQ29udFtwYXJ0c1tpXV07XG4gICAgICAgIGlmKG91dCA9PT0gbnVsbCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9O1xufVxuXG4vKlxuICogQ2FuIHRoaXMgdmFsdWUgYmUgZGVsZXRlZD8gV2UgY2FuIGRlbGV0ZSBgdW5kZWZpbmVkYCwgYW5kIGBudWxsYCBleGNlcHQgSU5TSURFIGFuXG4gKiAqYXJncyogYXJyYXkuXG4gKlxuICogUHJldmlvdXNseSB3ZSBhbHNvIGRlbGV0ZWQgc29tZSBge31gIGFuZCBgW11gLCBpbiBvcmRlciB0byB0cnkgYW5kIG1ha2Ugc2V0L3Vuc2V0XG4gKiBhIG5ldCBub29wOyBidXQgdGhpcyBjYXVzZXMgZmFyIG1vcmUgY29tcGxpY2F0aW9uIHRoYW4gaXQncyB3b3J0aCwgYW5kIHN0aWxsIGhhZFxuICogbG90cyBvZiBleGNlcHRpb25zLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzE0MTBcbiAqXG4gKiAqYXJncyogYXJyYXlzIGdldCBwYXNzZWQgZGlyZWN0bHkgdG8gQVBJIG1ldGhvZHMgYW5kIHdlIHNob3VsZCByZXNwZWN0IG51bGwgaWZcbiAqIHRoZSB1c2VyIHB1dCBpdCB0aGVyZSwgYnV0IG90aGVyd2lzZSBudWxsIGlzIGRlbGV0ZWQgYXMgd2UgdXNlIGl0IGFzIGNvZGVcbiAqIGluIHJlc3R5bGUvcmVsYXlvdXQvdXBkYXRlIGZvciBcImRlbGV0ZSB0aGlzIHZhbHVlXCIgd2hlcmVhcyB1bmRlZmluZWQgbWVhbnNcbiAqIFwiaWdub3JlIHRoaXMgZWRpdFwiXG4gKi9cbnZhciBBUkdTX1BBVFRFUk4gPSAvKF58XFwuKWFyZ3NcXFsvO1xuZnVuY3Rpb24gaXNEZWxldGFibGUodmFsLCBwcm9wU3RyKSB7XG4gICAgcmV0dXJuICh2YWwgPT09IHVuZGVmaW5lZCkgfHwgKHZhbCA9PT0gbnVsbCAmJiAhcHJvcFN0ci5tYXRjaChBUkdTX1BBVFRFUk4pKTtcbn1cblxuZnVuY3Rpb24gbnBTZXQoY29udCwgcGFydHMsIHByb3BTdHIpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odmFsKSB7XG4gICAgICAgIHZhciBjdXJDb250ID0gY29udDtcbiAgICAgICAgdmFyIHByb3BQYXJ0ID0gJyc7XG4gICAgICAgIHZhciBjb250YWluZXJMZXZlbHMgPSBbW2NvbnQsIHByb3BQYXJ0XV07XG4gICAgICAgIHZhciB0b0RlbGV0ZSA9IGlzRGVsZXRhYmxlKHZhbCwgcHJvcFN0cik7XG4gICAgICAgIHZhciBjdXJQYXJ0O1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgIGN1clBhcnQgPSBwYXJ0c1tpXTtcblxuICAgICAgICAgICAgaWYodHlwZW9mIGN1clBhcnQgPT09ICdudW1iZXInICYmICFpc0FycmF5T3JUeXBlZEFycmF5KGN1ckNvbnQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgJ2FycmF5IGluZGV4IGJ1dCBjb250YWluZXIgaXMgbm90IGFuIGFycmF5JztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gaGFuZGxlIHNwZWNpYWwgLTEgYXJyYXkgaW5kZXhcbiAgICAgICAgICAgIGlmKGN1clBhcnQgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdG9EZWxldGUgPSAhc2V0QXJyYXlBbGwoY3VyQ29udCwgcGFydHMuc2xpY2UoaSArIDEpLCB2YWwsIHByb3BTdHIpO1xuICAgICAgICAgICAgICAgIGlmKHRvRGVsZXRlKSBicmVhaztcbiAgICAgICAgICAgICAgICBlbHNlIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIWNoZWNrTmV3Q29udGFpbmVyKGN1ckNvbnQsIGN1clBhcnQsIHBhcnRzW2kgKyAxXSwgdG9EZWxldGUpKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGN1ckNvbnQgPSBjdXJDb250W2N1clBhcnRdO1xuXG4gICAgICAgICAgICBpZih0eXBlb2YgY3VyQ29udCAhPT0gJ29iamVjdCcgfHwgY3VyQ29udCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93ICdjb250YWluZXIgaXMgbm90IGFuIG9iamVjdCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHByb3BQYXJ0ID0gam9pblByb3BTdHIocHJvcFBhcnQsIGN1clBhcnQpO1xuXG4gICAgICAgICAgICBjb250YWluZXJMZXZlbHMucHVzaChbY3VyQ29udCwgcHJvcFBhcnRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRvRGVsZXRlKSB7XG4gICAgICAgICAgICBpZihpID09PSBwYXJ0cy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGN1ckNvbnRbcGFydHNbaV1dO1xuXG4gICAgICAgICAgICAgICAgLy8gVGhlIG9uZSBiaXQgb2YgcHJ1bmluZyB3ZSBzdGlsbCBkbzogZHJvcCBgdW5kZWZpbmVkYCBmcm9tIHRoZSBlbmQgb2YgYXJyYXlzLlxuICAgICAgICAgICAgICAgIC8vIEluIGNhc2Ugc29tZW9uZSBoYXMgYWxyZWFkeSB1bnNldCBwcmV2aW91cyBpdGVtcywgY29udGludWUgdW50aWwgd2UgaGl0IGFcbiAgICAgICAgICAgICAgICAvLyBub24tdW5kZWZpbmVkIHZhbHVlLlxuICAgICAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoY3VyQ29udCkgJiYgK3BhcnRzW2ldID09PSBjdXJDb250Lmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUoY3VyQ29udC5sZW5ndGggJiYgY3VyQ29udFtjdXJDb250Lmxlbmd0aCAtIDFdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1ckNvbnQucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBjdXJDb250W3BhcnRzW2ldXSA9IHZhbDtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBqb2luUHJvcFN0cihwcm9wU3RyLCBuZXdQYXJ0KSB7XG4gICAgdmFyIHRvQWRkID0gbmV3UGFydDtcbiAgICBpZihpc051bWVyaWMobmV3UGFydCkpIHRvQWRkID0gJ1snICsgbmV3UGFydCArICddJztcbiAgICBlbHNlIGlmKHByb3BTdHIpIHRvQWRkID0gJy4nICsgbmV3UGFydDtcblxuICAgIHJldHVybiBwcm9wU3RyICsgdG9BZGQ7XG59XG5cbi8vIGhhbmRsZSBzcGVjaWFsIC0xIGFycmF5IGluZGV4XG5mdW5jdGlvbiBzZXRBcnJheUFsbChjb250YWluZXJBcnJheSwgaW5uZXJQYXJ0cywgdmFsLCBwcm9wU3RyKSB7XG4gICAgdmFyIGFycmF5VmFsID0gaXNBcnJheU9yVHlwZWRBcnJheSh2YWwpO1xuICAgIHZhciBhbGxTZXQgPSB0cnVlO1xuICAgIHZhciB0aGlzVmFsID0gdmFsO1xuICAgIHZhciB0aGlzUHJvcFN0ciA9IHByb3BTdHIucmVwbGFjZSgnLTEnLCAwKTtcbiAgICB2YXIgZGVsZXRlVGhpcyA9IGFycmF5VmFsID8gZmFsc2UgOiBpc0RlbGV0YWJsZSh2YWwsIHRoaXNQcm9wU3RyKTtcbiAgICB2YXIgZmlyc3RQYXJ0ID0gaW5uZXJQYXJ0c1swXTtcbiAgICB2YXIgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNvbnRhaW5lckFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXNQcm9wU3RyID0gcHJvcFN0ci5yZXBsYWNlKCctMScsIGkpO1xuICAgICAgICBpZihhcnJheVZhbCkge1xuICAgICAgICAgICAgdGhpc1ZhbCA9IHZhbFtpICUgdmFsLmxlbmd0aF07XG4gICAgICAgICAgICBkZWxldGVUaGlzID0gaXNEZWxldGFibGUodGhpc1ZhbCwgdGhpc1Byb3BTdHIpO1xuICAgICAgICB9XG4gICAgICAgIGlmKGRlbGV0ZVRoaXMpIGFsbFNldCA9IGZhbHNlO1xuICAgICAgICBpZighY2hlY2tOZXdDb250YWluZXIoY29udGFpbmVyQXJyYXksIGksIGZpcnN0UGFydCwgZGVsZXRlVGhpcykpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIG5wU2V0KGNvbnRhaW5lckFycmF5W2ldLCBpbm5lclBhcnRzLCBwcm9wU3RyLnJlcGxhY2UoJy0xJywgaSkpKHRoaXNWYWwpO1xuICAgIH1cbiAgICByZXR1cm4gYWxsU2V0O1xufVxuXG4vKipcbiAqIG1ha2UgbmV3IHN1Yi1jb250YWluZXIgYXMgbmVlZGVkLlxuICogcmV0dXJucyBmYWxzZSBpZiB0aGVyZSdzIG5vIGNvbnRhaW5lciBhbmQgbm9uZSBpcyBuZWVkZWRcbiAqIGJlY2F1c2Ugd2UncmUgb25seSBkZWxldGluZyBhbiBhdHRyaWJ1dGVcbiAqL1xuZnVuY3Rpb24gY2hlY2tOZXdDb250YWluZXIoY29udGFpbmVyLCBwYXJ0LCBuZXh0UGFydCwgdG9EZWxldGUpIHtcbiAgICBpZihjb250YWluZXJbcGFydF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZih0b0RlbGV0ZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIGlmKHR5cGVvZiBuZXh0UGFydCA9PT0gJ251bWJlcicpIGNvbnRhaW5lcltwYXJ0XSA9IFtdO1xuICAgICAgICBlbHNlIGNvbnRhaW5lcltwYXJ0XSA9IHt9O1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gYmFkQ29udGFpbmVyKGNvbnRhaW5lciwgcHJvcFN0ciwgcHJvcFBhcnRzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc2V0OiBmdW5jdGlvbigpIHsgdGhyb3cgJ2JhZCBjb250YWluZXInOyB9LFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIGFzdHI6IHByb3BTdHIsXG4gICAgICAgIHBhcnRzOiBwcm9wUGFydHMsXG4gICAgICAgIG9iajogY29udGFpbmVyXG4gICAgfTtcbn1cblxufSx7XCIuL2FycmF5XCI6NzAyLFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSw3Mjg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vLyBTaW1wbGUgaGVscGVyIGZ1bmN0aW9uc1xuLy8gbm9uZSBvZiB0aGVzZSBuZWVkIGFueSBleHRlcm5hbCBkZXBzXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbm9vcCgpIHt9O1xuXG59LHt9XSw3Mjk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIE5PVEVEQVRBID0gW107XG5cbi8qKlxuICogbm90aWZpZXJcbiAqIEBwYXJhbSB7U3RyaW5nfSB0ZXh0IFRoZSBwZXJzb24ncyB1c2VyIG5hbWVcbiAqIEBwYXJhbSB7TnVtYmVyfSBbZGVsYXk9MTAwMF0gVGhlIGRlbGF5IHRpbWUgaW4gbWlsbGlzZWNvbmRzXG4gKiAgICAgICAgICBvciAnbG9uZycgd2hpY2ggcHJvdmlkZXMgMjAwMCBtcyBkZWxheSB0aW1lLlxuICogQHJldHVybiB7dW5kZWZpbmVkfSB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IHJldHVybiBhIHZhbHVlXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24odGV4dCwgZGlzcGxheUxlbmd0aCkge1xuICAgIGlmKE5PVEVEQVRBLmluZGV4T2YodGV4dCkgIT09IC0xKSByZXR1cm47XG5cbiAgICBOT1RFREFUQS5wdXNoKHRleHQpO1xuXG4gICAgdmFyIHRzID0gMTAwMDtcbiAgICBpZihpc051bWVyaWMoZGlzcGxheUxlbmd0aCkpIHRzID0gZGlzcGxheUxlbmd0aDtcbiAgICBlbHNlIGlmKGRpc3BsYXlMZW5ndGggPT09ICdsb25nJykgdHMgPSAzMDAwO1xuXG4gICAgdmFyIG5vdGlmaWVyQ29udGFpbmVyID0gZDMuc2VsZWN0KCdib2R5JylcbiAgICAgICAgLnNlbGVjdEFsbCgnLnBsb3RseS1ub3RpZmllcicpXG4gICAgICAgIC5kYXRhKFswXSk7XG4gICAgbm90aWZpZXJDb250YWluZXIuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdkaXYnKVxuICAgICAgICAuY2xhc3NlZCgncGxvdGx5LW5vdGlmaWVyJywgdHJ1ZSk7XG5cbiAgICB2YXIgbm90ZXMgPSBub3RpZmllckNvbnRhaW5lci5zZWxlY3RBbGwoJy5ub3RpZmllci1ub3RlJykuZGF0YShOT1RFREFUQSk7XG5cbiAgICBmdW5jdGlvbiBraWxsTm90ZSh0cmFuc2l0aW9uKSB7XG4gICAgICAgIHRyYW5zaXRpb25cbiAgICAgICAgICAgIC5kdXJhdGlvbig3MDApXG4gICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAwKVxuICAgICAgICAgICAgLmVhY2goJ2VuZCcsIGZ1bmN0aW9uKHRoaXNUZXh0KSB7XG4gICAgICAgICAgICAgICAgdmFyIHRoaXNJbmRleCA9IE5PVEVEQVRBLmluZGV4T2YodGhpc1RleHQpO1xuICAgICAgICAgICAgICAgIGlmKHRoaXNJbmRleCAhPT0gLTEpIE5PVEVEQVRBLnNwbGljZSh0aGlzSW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIG5vdGVzLmVudGVyKCkuYXBwZW5kKCdkaXYnKVxuICAgICAgICAuY2xhc3NlZCgnbm90aWZpZXItbm90ZScsIHRydWUpXG4gICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDApXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKHRoaXNUZXh0KSB7XG4gICAgICAgICAgICB2YXIgbm90ZSA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICAgICAgbm90ZS5hcHBlbmQoJ2J1dHRvbicpXG4gICAgICAgICAgICAgICAgLmNsYXNzZWQoJ25vdGlmaWVyLWNsb3NlJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAuaHRtbCgnJnRpbWVzOycpXG4gICAgICAgICAgICAgICAgLm9uKCdjbGljaycsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBub3RlLnRyYW5zaXRpb24oKS5jYWxsKGtpbGxOb3RlKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIHAgPSBub3RlLmFwcGVuZCgncCcpO1xuICAgICAgICAgICAgdmFyIGxpbmVzID0gdGhpc1RleHQuc3BsaXQoLzxiclxccypcXC8/Pi9nKTtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKGkpIHAuYXBwZW5kKCdicicpO1xuICAgICAgICAgICAgICAgIHAuYXBwZW5kKCdzcGFuJykudGV4dChsaW5lc1tpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG5vdGUudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgICAgIC5kdXJhdGlvbig3MDApXG4gICAgICAgICAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDEpXG4gICAgICAgICAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgICAgICAuZGVsYXkodHMpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKGtpbGxOb3RlKTtcbiAgICAgICAgfSk7XG59O1xuXG59LHtcImQzXCI6MTYzLFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSw3MzA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzZXRDdXJzb3IgPSBfZGVyZXFfKCcuL3NldGN1cnNvcicpO1xuXG52YXIgU1RBU0hBVFRSID0gJ2RhdGEtc2F2ZWRjdXJzb3InO1xudmFyIE5PX0NVUlNPUiA9ICchISc7XG5cbi8qXG4gKiB3b3JrcyB3aXRoIG91ciBDU1MgY3Vyc29yIGNsYXNzZXMgKHNlZSBjc3MvX2N1cnNvci5zY3NzKVxuICogdG8gb3ZlcnJpZGUgYSBwcmV2aW91cyBjdXJzb3Igc2V0IG9uIGQzIHNpbmdsZS1lbGVtZW50IHNlbGVjdGlvbnMsXG4gKiBieSBtb3ZpbmcgdGhlIG5hbWUgb2YgdGhlIG9yaWdpbmFsIGN1cnNvciB0byB0aGUgZGF0YS1zYXZlZGN1cnNvciBhdHRyLlxuICogb21pdCBjdXJzb3IgdG8gcmV2ZXJ0IHRvIHRoZSBwcmV2aW91c2x5IHNldCB2YWx1ZS5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBvdmVycmlkZUN1cnNvcihlbDMsIGNzcikge1xuICAgIHZhciBzYXZlZEN1cnNvciA9IGVsMy5hdHRyKFNUQVNIQVRUUik7XG4gICAgaWYoY3NyKSB7XG4gICAgICAgIGlmKCFzYXZlZEN1cnNvcikge1xuICAgICAgICAgICAgdmFyIGNsYXNzZXMgPSAoZWwzLmF0dHIoJ2NsYXNzJykgfHwgJycpLnNwbGl0KCcgJyk7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2xhc3Nlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBjbHMgPSBjbGFzc2VzW2ldO1xuICAgICAgICAgICAgICAgIGlmKGNscy5pbmRleE9mKCdjdXJzb3ItJykgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZWwzLmF0dHIoU1RBU0hBVFRSLCBjbHMuc3Vic3RyKDcpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoY2xzLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoIWVsMy5hdHRyKFNUQVNIQVRUUikpIHtcbiAgICAgICAgICAgICAgICBlbDMuYXR0cihTVEFTSEFUVFIsIE5PX0NVUlNPUik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgc2V0Q3Vyc29yKGVsMywgY3NyKTtcbiAgICB9IGVsc2UgaWYoc2F2ZWRDdXJzb3IpIHtcbiAgICAgICAgZWwzLmF0dHIoU1RBU0hBVFRSLCBudWxsKTtcblxuICAgICAgICBpZihzYXZlZEN1cnNvciA9PT0gTk9fQ1VSU09SKSBzZXRDdXJzb3IoZWwzKTtcbiAgICAgICAgZWxzZSBzZXRDdXJzb3IoZWwzLCBzYXZlZEN1cnNvcik7XG4gICAgfVxufTtcblxufSx7XCIuL3NldGN1cnNvclwiOjczOX1dLDczMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGRvdCA9IF9kZXJlcV8oJy4vbWF0cml4JykuZG90O1xudmFyIEJBRE5VTSA9IF9kZXJlcV8oJy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbnZhciBwb2x5Z29uID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLyoqXG4gKiBUdXJuIGFuIGFycmF5IG9mIFt4LCB5XSBwYWlycyBpbnRvIGEgcG9seWdvbiBvYmplY3RcbiAqIHRoYXQgY2FuIHRlc3QgaWYgcG9pbnRzIGFyZSBpbnNpZGUgaXRcbiAqXG4gKiBAcGFyYW0gcHRzSW4gQXJyYXkgb2YgW3gsIHldIHBhaXJzXG4gKlxuICogQHJldHVybnMgcG9seWdvbiBPYmplY3Qge3htaW4sIHhtYXgsIHltaW4sIHltYXgsIHB0cywgY29udGFpbnN9XG4gKiAgICAgICh4fHkpKG1pbnxtYXgpIGFyZSB0aGUgYm91bmRpbmcgcmVjdCBvZiB0aGUgcG9seWdvblxuICogICAgICBwdHMgaXMgdGhlIG9yaWdpbmFsIGFycmF5LCB3aXRoIHRoZSBmaXJzdCBwYWlyIHJlcGVhdGVkIGF0IHRoZSBlbmRcbiAqICAgICAgY29udGFpbnMgaXMgYSBmdW5jdGlvbjogKHB0LCBvbWl0Rmlyc3RFZGdlKVxuICogICAgICAgICAgcHQgaXMgdGhlIFt4LCB5XSBwYWlyIHRvIHRlc3RcbiAqICAgICAgICAgIG9taXRGaXJzdEVkZ2UgdHJ1dGh5IG1lYW5zIHBvaW50cyBleGFjdGx5IG9uIHRoZSBmaXJzdCBlZGdlIGRvbid0XG4gKiAgICAgICAgICAgICAgY291bnQuIFRoaXMgaXMgZm9yIHVzZSBhZGRpbmcgb25lIHBvbHlnb24gdG8gYW5vdGhlciBzbyB3ZVxuICogICAgICAgICAgICAgIGRvbid0IGRvdWJsZS1jb3VudCB0aGUgZWRnZSB3aGVyZSB0aGV5IG1lZXQuXG4gKiAgICAgICAgICByZXR1cm5zIGJvb2xlYW46IGlzIHB0IGluc2lkZSB0aGUgcG9seWdvbiAoaW5jbHVkaW5nIG9uIGl0cyBlZGdlcylcbiAqL1xucG9seWdvbi50ZXN0ZXIgPSBmdW5jdGlvbiB0ZXN0ZXIocHRzSW4pIHtcbiAgICB2YXIgcHRzID0gcHRzSW4uc2xpY2UoKTtcbiAgICB2YXIgeG1pbiA9IHB0c1swXVswXTtcbiAgICB2YXIgeG1heCA9IHhtaW47XG4gICAgdmFyIHltaW4gPSBwdHNbMF1bMV07XG4gICAgdmFyIHltYXggPSB5bWluO1xuICAgIHZhciBpO1xuXG4gICAgcHRzLnB1c2gocHRzWzBdKTtcbiAgICBmb3IoaSA9IDE7IGkgPCBwdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgeG1pbiA9IE1hdGgubWluKHhtaW4sIHB0c1tpXVswXSk7XG4gICAgICAgIHhtYXggPSBNYXRoLm1heCh4bWF4LCBwdHNbaV1bMF0pO1xuICAgICAgICB5bWluID0gTWF0aC5taW4oeW1pbiwgcHRzW2ldWzFdKTtcbiAgICAgICAgeW1heCA9IE1hdGgubWF4KHltYXgsIHB0c1tpXVsxXSk7XG4gICAgfVxuXG4gICAgLy8gZG8gd2UgaGF2ZSBhIHJlY3RhbmdsZT8gSGFuZGxlIHRoaXMgaGVyZSwgc28gd2UgY2FuIHVzZSB0aGUgc2FtZVxuICAgIC8vIHRlc3RlciBmb3IgdGhlIHJlY3Rhbmd1bGFyIGNhc2Ugd2l0aG91dCBzYWNyaWZpY2luZyBzcGVlZFxuXG4gICAgdmFyIGlzUmVjdCA9IGZhbHNlO1xuICAgIHZhciByZWN0Rmlyc3RFZGdlVGVzdDtcblxuICAgIGlmKHB0cy5sZW5ndGggPT09IDUpIHtcbiAgICAgICAgaWYocHRzWzBdWzBdID09PSBwdHNbMV1bMF0pIHsgLy8gdmVydCwgaG9yeiwgdmVydCwgaG9yelxuICAgICAgICAgICAgaWYocHRzWzJdWzBdID09PSBwdHNbM11bMF0gJiZcbiAgICAgICAgICAgICAgICAgICAgcHRzWzBdWzFdID09PSBwdHNbM11bMV0gJiZcbiAgICAgICAgICAgICAgICAgICAgcHRzWzFdWzFdID09PSBwdHNbMl1bMV0pIHtcbiAgICAgICAgICAgICAgICBpc1JlY3QgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJlY3RGaXJzdEVkZ2VUZXN0ID0gZnVuY3Rpb24ocHQpIHsgcmV0dXJuIHB0WzBdID09PSBwdHNbMF1bMF07IH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihwdHNbMF1bMV0gPT09IHB0c1sxXVsxXSkgeyAvLyBob3J6LCB2ZXJ0LCBob3J6LCB2ZXJ0XG4gICAgICAgICAgICBpZihwdHNbMl1bMV0gPT09IHB0c1szXVsxXSAmJlxuICAgICAgICAgICAgICAgICAgICBwdHNbMF1bMF0gPT09IHB0c1szXVswXSAmJlxuICAgICAgICAgICAgICAgICAgICBwdHNbMV1bMF0gPT09IHB0c1syXVswXSkge1xuICAgICAgICAgICAgICAgIGlzUmVjdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmVjdEZpcnN0RWRnZVRlc3QgPSBmdW5jdGlvbihwdCkgeyByZXR1cm4gcHRbMV0gPT09IHB0c1swXVsxXTsgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlY3RDb250YWlucyhwdCwgb21pdEZpcnN0RWRnZSkge1xuICAgICAgICB2YXIgeCA9IHB0WzBdO1xuICAgICAgICB2YXIgeSA9IHB0WzFdO1xuXG4gICAgICAgIGlmKHggPT09IEJBRE5VTSB8fCB4IDwgeG1pbiB8fCB4ID4geG1heCB8fCB5ID09PSBCQUROVU0gfHwgeSA8IHltaW4gfHwgeSA+IHltYXgpIHtcbiAgICAgICAgICAgIC8vIHB0IGlzIG91dHNpZGUgdGhlIGJvdW5kaW5nIGJveCBvZiBwb2x5Z29uXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYob21pdEZpcnN0RWRnZSAmJiByZWN0Rmlyc3RFZGdlVGVzdChwdCkpIHJldHVybiBmYWxzZTtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb250YWlucyhwdCwgb21pdEZpcnN0RWRnZSkge1xuICAgICAgICB2YXIgeCA9IHB0WzBdO1xuICAgICAgICB2YXIgeSA9IHB0WzFdO1xuXG4gICAgICAgIGlmKHggPT09IEJBRE5VTSB8fCB4IDwgeG1pbiB8fCB4ID4geG1heCB8fCB5ID09PSBCQUROVU0gfHwgeSA8IHltaW4gfHwgeSA+IHltYXgpIHtcbiAgICAgICAgICAgIC8vIHB0IGlzIG91dHNpZGUgdGhlIGJvdW5kaW5nIGJveCBvZiBwb2x5Z29uXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaW1heCA9IHB0cy5sZW5ndGg7XG4gICAgICAgIHZhciB4MSA9IHB0c1swXVswXTtcbiAgICAgICAgdmFyIHkxID0gcHRzWzBdWzFdO1xuICAgICAgICB2YXIgY3Jvc3NpbmdzID0gMDtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB4MDtcbiAgICAgICAgdmFyIHkwO1xuICAgICAgICB2YXIgeG1pbmk7XG4gICAgICAgIHZhciB5Y3Jvc3M7XG5cbiAgICAgICAgZm9yKGkgPSAxOyBpIDwgaW1heDsgaSsrKSB7XG4gICAgICAgICAgICAvLyBmaW5kIGFsbCBjcm9zc2luZ3Mgb2YgYSB2ZXJ0aWNhbCBsaW5lIHVwd2FyZCBmcm9tIHB0IHdpdGhcbiAgICAgICAgICAgIC8vIHBvbHlnb24gc2VnbWVudHNcbiAgICAgICAgICAgIC8vIGNyb3NzaW5ncyBleGFjdGx5IGF0IHhtYXggZG9uJ3QgY291bnQsIHVubGVzcyB0aGUgcG9pbnQgaXNcbiAgICAgICAgICAgIC8vIGV4YWN0bHkgb24gdGhlIHNlZ21lbnQsIHRoZW4gaXQgY291bnRzIGFzIGluc2lkZS5cbiAgICAgICAgICAgIHgwID0geDE7XG4gICAgICAgICAgICB5MCA9IHkxO1xuICAgICAgICAgICAgeDEgPSBwdHNbaV1bMF07XG4gICAgICAgICAgICB5MSA9IHB0c1tpXVsxXTtcbiAgICAgICAgICAgIHhtaW5pID0gTWF0aC5taW4oeDAsIHgxKTtcblxuICAgICAgICAgICAgaWYoeCA8IHhtaW5pIHx8IHggPiBNYXRoLm1heCh4MCwgeDEpIHx8IHkgPiBNYXRoLm1heCh5MCwgeTEpKSB7XG4gICAgICAgICAgICAgICAgLy8gb3V0c2lkZSB0aGUgYm91bmRpbmcgYm94IG9mIHRoaXMgc2VnbWVudCwgaXQncyBvbmx5IGEgY3Jvc3NpbmdcbiAgICAgICAgICAgICAgICAvLyBpZiBpdCdzIGJlbG93IHRoZSBib3guXG5cbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZih5IDwgTWF0aC5taW4oeTAsIHkxKSkge1xuICAgICAgICAgICAgICAgIC8vIGRvbid0IGNvdW50IHRoZSBsZWZ0LW1vc3QgcG9pbnQgb2YgdGhlIHNlZ21lbnQgYXMgYSBjcm9zc2luZ1xuICAgICAgICAgICAgICAgIC8vIGJlY2F1c2Ugd2UgZG9uJ3Qgd2FudCB0byBkb3VibGUtY291bnQgYWRqYWNlbnQgY3Jvc3NpbmdzXG4gICAgICAgICAgICAgICAgLy8gVU5MRVNTIHRoZSBwb2x5Z29uIHR1cm5zIHBhc3QgdmVydGljYWwgYXQgZXhhY3RseSB0aGlzIHhcbiAgICAgICAgICAgICAgICAvLyBOb3RlIHRoYXQgdGhpcyBpcyByZXBlYXRlZCBiZWxvdywgYnV0IHdlIGNhbid0IGZhY3RvciBpdCBvdXRcbiAgICAgICAgICAgICAgICAvLyBiZWNhdXNlXG4gICAgICAgICAgICAgICAgaWYoeCAhPT0geG1pbmkpIGNyb3NzaW5ncysrO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBpbnNpZGUgdGhlIGJvdW5kaW5nIGJveCwgY2hlY2sgdGhlIGFjdHVhbCBsaW5lIGludGVyY2VwdFxuXG4gICAgICAgICAgICAgICAgLy8gdmVydGljYWwgc2VnbWVudCAtIHdlIGtub3cgYWxyZWFkeSB0aGF0IHRoZSBwb2ludCBpcyBleGFjdGx5XG4gICAgICAgICAgICAgICAgLy8gb24gdGhlIHNlZ21lbnQsIHNvIG1hcmsgdGhlIGNyb3NzaW5nIGFzIGV4YWN0bHkgYXQgdGhlIHBvaW50LlxuICAgICAgICAgICAgICAgIGlmKHgxID09PSB4MCkgeWNyb3NzID0geTtcbiAgICAgICAgICAgICAgICAvLyBhbnkgb3RoZXIgYW5nbGVcbiAgICAgICAgICAgICAgICBlbHNlIHljcm9zcyA9IHkwICsgKHggLSB4MCkgKiAoeTEgLSB5MCkgLyAoeDEgLSB4MCk7XG5cbiAgICAgICAgICAgICAgICAvLyBleGFjdGx5IG9uIHRoZSBlZGdlOiBjb3VudHMgYXMgaW5zaWRlIHRoZSBwb2x5Z29uLCB1bmxlc3MgaXQncyB0aGVcbiAgICAgICAgICAgICAgICAvLyBmaXJzdCBlZGdlIGFuZCB3ZSdyZSBvbWl0dGluZyBpdC5cbiAgICAgICAgICAgICAgICBpZih5ID09PSB5Y3Jvc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoaSA9PT0gMSAmJiBvbWl0Rmlyc3RFZGdlKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKHkgPD0geWNyb3NzICYmIHggIT09IHhtaW5pKSBjcm9zc2luZ3MrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGlmIHdlJ3ZlIGdvdHRlbiB0aGlzIGZhciwgb2RkIGNyb3NzaW5ncyBtZWFucyBpbnNpZGUsIGV2ZW4gaXMgb3V0c2lkZVxuICAgICAgICByZXR1cm4gY3Jvc3NpbmdzICUgMiA9PT0gMTtcbiAgICB9XG5cbiAgICAvLyBkZXRlY3QgaWYgcG9seSBpcyBkZWdlbmVyYXRlXG4gICAgdmFyIGRlZ2VuZXJhdGUgPSB0cnVlO1xuICAgIHZhciBsYXN0UHQgPSBwdHNbMF07XG4gICAgZm9yKGkgPSAxOyBpIDwgcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGxhc3RQdFswXSAhPT0gcHRzW2ldWzBdIHx8IGxhc3RQdFsxXSAhPT0gcHRzW2ldWzFdKSB7XG4gICAgICAgICAgICBkZWdlbmVyYXRlID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHhtaW46IHhtaW4sXG4gICAgICAgIHhtYXg6IHhtYXgsXG4gICAgICAgIHltaW46IHltaW4sXG4gICAgICAgIHltYXg6IHltYXgsXG4gICAgICAgIHB0czogcHRzLFxuICAgICAgICBjb250YWluczogaXNSZWN0ID8gcmVjdENvbnRhaW5zIDogY29udGFpbnMsXG4gICAgICAgIGlzUmVjdDogaXNSZWN0LFxuICAgICAgICBkZWdlbmVyYXRlOiBkZWdlbmVyYXRlXG4gICAgfTtcbn07XG5cbi8qKlxuICogVGVzdCBpZiBhIHNlZ21lbnQgb2YgYSBwb2ludHMgYXJyYXkgaXMgYmVudCBvciBzdHJhaWdodFxuICpcbiAqIEBwYXJhbSBwdHMgQXJyYXkgb2YgW3gsIHldIHBhaXJzXG4gKiBAcGFyYW0gc3RhcnQgdGhlIGluZGV4IG9mIHRoZSBwcm9wb3NlZCBzdGFydCBvZiB0aGUgc3RyYWlnaHQgc2VjdGlvblxuICogQHBhcmFtIGVuZCB0aGUgaW5kZXggb2YgdGhlIHByb3Bvc2VkIGVuZCBwb2ludFxuICogQHBhcmFtIHRvbGVyYW5jZSB0aGUgbWF4IGRpc3RhbmNlIG9mZiB0aGUgbGluZSBjb25uZWN0aW5nIHN0YXJ0IGFuZCBlbmRcbiAqICAgICAgYmVmb3JlIHRoZSBsaW5lIGNvdW50cyBhcyBiZW50XG4gKiBAcmV0dXJucyBib29sZWFuOiB0cnVlIG1lYW5zIHRoaXMgc2VnbWVudCBpcyBiZW50LCBmYWxzZSBtZWFucyBzdHJhaWdodFxuICovXG5wb2x5Z29uLmlzU2VnbWVudEJlbnQgPSBmdW5jdGlvbiBpc1NlZ21lbnRCZW50KHB0cywgc3RhcnQsIGVuZCwgdG9sZXJhbmNlKSB7XG4gICAgdmFyIHN0YXJ0UHQgPSBwdHNbc3RhcnRdO1xuICAgIHZhciBzZWdtZW50ID0gW3B0c1tlbmRdWzBdIC0gc3RhcnRQdFswXSwgcHRzW2VuZF1bMV0gLSBzdGFydFB0WzFdXTtcbiAgICB2YXIgc2VnbWVudFNxdWFyZWQgPSBkb3Qoc2VnbWVudCwgc2VnbWVudCk7XG4gICAgdmFyIHNlZ21lbnRMZW4gPSBNYXRoLnNxcnQoc2VnbWVudFNxdWFyZWQpO1xuICAgIHZhciB1bml0UGVycCA9IFstc2VnbWVudFsxXSAvIHNlZ21lbnRMZW4sIHNlZ21lbnRbMF0gLyBzZWdtZW50TGVuXTtcbiAgICB2YXIgaTtcbiAgICB2YXIgcGFydDtcbiAgICB2YXIgcGFydFBhcmFsbGVsO1xuXG4gICAgZm9yKGkgPSBzdGFydCArIDE7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgICBwYXJ0ID0gW3B0c1tpXVswXSAtIHN0YXJ0UHRbMF0sIHB0c1tpXVsxXSAtIHN0YXJ0UHRbMV1dO1xuICAgICAgICBwYXJ0UGFyYWxsZWwgPSBkb3QocGFydCwgc2VnbWVudCk7XG5cbiAgICAgICAgaWYocGFydFBhcmFsbGVsIDwgMCB8fCBwYXJ0UGFyYWxsZWwgPiBzZWdtZW50U3F1YXJlZCB8fFxuICAgICAgICAgICAgTWF0aC5hYnMoZG90KHBhcnQsIHVuaXRQZXJwKSkgPiB0b2xlcmFuY2UpIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59O1xuXG4vKipcbiAqIE1ha2UgYSBmaWx0ZXJpbmcgcG9seWdvbiwgdG8gbWluaW1pemUgdGhlIG51bWJlciBvZiBzZWdtZW50c1xuICpcbiAqIEBwYXJhbSBwdHMgQXJyYXkgb2YgW3gsIHldIHBhaXJzIChtdXN0IHN0YXJ0IHdpdGggYXQgbGVhc3QgMSBwYWlyKVxuICogQHBhcmFtIHRvbGVyYW5jZSB0aGUgbWF4aW11bSBkZXZpYXRpb24gZnJvbSBzdHJhaWdodCBhbGxvd2VkIGZvclxuICogICAgICByZW1vdmluZyBwb2ludHMgdG8gc2ltcGxpZnkgdGhlIHBvbHlnb25cbiAqXG4gKiBAcmV0dXJucyBPYmplY3Qge2FkZFB0LCByYXcsIGZpbHRlcmVkfVxuICogICAgICBhZGRQdCBpcyBhIGZ1bmN0aW9uKHB0OiBbeCwgeV0gcGFpcikgdG8gYWRkIGEgcmF3IHBvaW50IGFuZFxuICogICAgICAgICAgY29udGludWUgZmlsdGVyaW5nXG4gKiAgICAgIHJhdyBpcyBhbGwgdGhlIGlucHV0IHBvaW50c1xuICogICAgICBmaWx0ZXJlZCBpcyB0aGUgcmVzdWx0aW5nIGZpbHRlcmVkIEFycmF5IG9mIFt4LCB5XSBwYWlyc1xuICovXG5wb2x5Z29uLmZpbHRlciA9IGZ1bmN0aW9uIGZpbHRlcihwdHMsIHRvbGVyYW5jZSkge1xuICAgIHZhciBwdHNGaWx0ZXJlZCA9IFtwdHNbMF1dO1xuICAgIHZhciBkb25lUmF3SW5kZXggPSAwO1xuICAgIHZhciBkb25lRmlsdGVyZWRJbmRleCA9IDA7XG5cbiAgICBmdW5jdGlvbiBhZGRQdChwdCkge1xuICAgICAgICBwdHMucHVzaChwdCk7XG4gICAgICAgIHZhciBwcmV2RmlsdGVyTGVuID0gcHRzRmlsdGVyZWQubGVuZ3RoO1xuICAgICAgICB2YXIgaUxhc3QgPSBkb25lUmF3SW5kZXg7XG4gICAgICAgIHB0c0ZpbHRlcmVkLnNwbGljZShkb25lRmlsdGVyZWRJbmRleCArIDEpO1xuXG4gICAgICAgIGZvcih2YXIgaSA9IGlMYXN0ICsgMTsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoaSA9PT0gcHRzLmxlbmd0aCAtIDEgfHwgcG9seWdvbi5pc1NlZ21lbnRCZW50KHB0cywgaUxhc3QsIGkgKyAxLCB0b2xlcmFuY2UpKSB7XG4gICAgICAgICAgICAgICAgcHRzRmlsdGVyZWQucHVzaChwdHNbaV0pO1xuICAgICAgICAgICAgICAgIGlmKHB0c0ZpbHRlcmVkLmxlbmd0aCA8IHByZXZGaWx0ZXJMZW4gLSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbmVSYXdJbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgICAgIGRvbmVGaWx0ZXJlZEluZGV4ID0gcHRzRmlsdGVyZWQubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaUxhc3QgPSBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYocHRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdmFyIGxhc3RQdCA9IHB0cy5wb3AoKTtcbiAgICAgICAgYWRkUHQobGFzdFB0KTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBhZGRQdDogYWRkUHQsXG4gICAgICAgIHJhdzogcHRzLFxuICAgICAgICBmaWx0ZXJlZDogcHRzRmlsdGVyZWRcbiAgICB9O1xufTtcblxufSx7XCIuLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi9tYXRyaXhcIjo3MjV9XSw3MzI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuKGZ1bmN0aW9uIChnbG9iYWwpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2hvd05vV2ViR2xNc2cgPSBfZGVyZXFfKCcuL3Nob3dfbm9fd2ViZ2xfbXNnJyk7XG5cbi8vIE5vdGUgdGhhdCB0aGlzIG1vZHVsZSBzaG91bGQgYmUgT05MWSByZXF1aXJlZCBpbnRvXG4vLyBmaWxlcyBjb3JyZXNwb25kaW5nIHRvIHJlZ2wgdHJhY2UgbW9kdWxlc1xuLy8gc28gdGhhdCBidW5kbGVzIHdpdGggbm9uLXJlZ2wgb25seSBkb24ndCBpbmNsdWRlXG4vLyByZWdsIGFuZCBhbGwgaXRzIGJ5dGVzLlxudmFyIGNyZWF0ZVJlZ2wgPSBfZGVyZXFfKCdyZWdsJyk7XG5cbi8qKlxuICogSWRlbXBvdGVudCB2ZXJzaW9uIG9mIGNyZWF0ZVJlZ2wuIENyZWF0ZSByZWdsIGluc3RhbmNlc1xuICogaW4gdGhlIGNvcnJlY3QgY2FudmFzZXMgd2l0aCB0aGUgY29ycmVjdCBhdHRyaWJ1dGVzIGFuZFxuICogb3B0aW9uc1xuICpcbiAqIEBwYXJhbSB7RE9NIG5vZGUgb3Igb2JqZWN0fSBnZCA6IGdyYXBoIGRpdiBvYmplY3RcbiAqIEBwYXJhbSB7YXJyYXl9IGV4dGVuc2lvbnMgOiBsaXN0IG9mIGV4dGVuc2lvbiB0byBwYXNzIHRvIGNyZWF0ZVJlZ2xcbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSB0cnVlIGlmIGFsbCBjcmVhdGVSZWdsIGNhbGxzIHN1Y2NlZWRlZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcHJlcGFyZVJlZ2woZ2QsIGV4dGVuc2lvbnMpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzdWNjZXNzID0gdHJ1ZTtcblxuICAgIGZ1bGxMYXlvdXQuX2dsY2FudmFzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICBpZihkLnJlZ2wpIHJldHVybjtcbiAgICAgICAgLy8gb25seSBwYXJjb29yZHMgbmVlZHMgcGljayBsYXllclxuICAgICAgICBpZihkLnBpY2sgJiYgIWZ1bGxMYXlvdXQuX2hhcygncGFyY29vcmRzJykpIHJldHVybjtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZC5yZWdsID0gY3JlYXRlUmVnbCh7XG4gICAgICAgICAgICAgICAgY2FudmFzOiB0aGlzLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgYW50aWFsaWFzOiAhZC5waWNrLFxuICAgICAgICAgICAgICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHRydWVcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBpeGVsUmF0aW86IGdkLl9jb250ZXh0LnBsb3RHbFBpeGVsUmF0aW8gfHwgZ2xvYmFsLmRldmljZVBpeGVsUmF0aW8sXG4gICAgICAgICAgICAgICAgZXh0ZW5zaW9uczogZXh0ZW5zaW9ucyB8fCBbXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgc3VjY2VzcyA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoc3VjY2Vzcykge1xuICAgICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCd3ZWJnbGNvbnRleHRsb3N0JywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBpZihnZCAmJiBnZC5lbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV93ZWJnbGNvbnRleHRsb3N0Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQ6IGV2ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXI6IGQua2V5XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYoIXN1Y2Nlc3MpIHtcbiAgICAgICAgc2hvd05vV2ViR2xNc2coe2NvbnRhaW5lcjogZnVsbExheW91dC5fZ2xjb250YWluZXIubm9kZSgpfSk7XG4gICAgfVxuICAgIHJldHVybiBzdWNjZXNzO1xufTtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pXG59LHtcIi4vc2hvd19ub193ZWJnbF9tc2dcIjo3NDAsXCJyZWdsXCI6NTAyfV0sNzMzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBQdXNoIGFycmF5IHdpdGggdW5pcXVlIGl0ZW1zXG4gKlxuICogSWdub3JlcyBmYWxzeSBpdGVtcywgZXhjZXB0IDAgc28gd2UgY2FuIHVzZSBpdCB0byBjb25zdHJ1Y3QgYXJyYXlzIG9mIGluZGljZXMuXG4gKlxuICogQHBhcmFtIHthcnJheX0gYXJyYXlcbiAqICBhcnJheSB0byBiZSBmaWxsZWRcbiAqIEBwYXJhbSB7YW55fSBpdGVtXG4gKiAgaXRlbSB0byBiZSBvciBub3QgdG8gYmUgaW5zZXJ0ZWRcbiAqIEByZXR1cm4ge2FycmF5fVxuICogIHJlZiB0byBhcnJheSAobm93IHBvc3NpYmx5IGNvbnRhaW5pbmcgb25lIG1vcmUgaXRlbSlcbiAqXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcHVzaFVuaXF1ZShhcnJheSwgaXRlbSkge1xuICAgIGlmKGl0ZW0gaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgdmFyIGl0ZW1TdHIgPSBpdGVtLnRvU3RyaW5nKCk7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoYXJyYXlbaV0gaW5zdGFuY2VvZiBSZWdFeHAgJiYgYXJyYXlbaV0udG9TdHJpbmcoKSA9PT0gaXRlbVN0cikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhcnJheTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhcnJheS5wdXNoKGl0ZW0pO1xuICAgIH0gZWxzZSBpZigoaXRlbSB8fCBpdGVtID09PSAwKSAmJiBhcnJheS5pbmRleE9mKGl0ZW0pID09PSAtMSkgYXJyYXkucHVzaChpdGVtKTtcblxuICAgIHJldHVybiBhcnJheTtcbn07XG5cbn0se31dLDczNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcbnZhciBkZmx0Q29uZmlnID0gX2RlcmVxXygnLi4vcGxvdF9hcGkvcGxvdF9jb25maWcnKS5kZmx0Q29uZmlnO1xuXG4vKipcbiAqIENvcHkgYXJnIGFycmF5ICp3aXRob3V0KiByZW1vdmluZyBgdW5kZWZpbmVkYCB2YWx1ZXMgZnJvbSBvYmplY3RzLlxuICpcbiAqIEBwYXJhbSBnZFxuICogQHBhcmFtIGFyZ3NcbiAqIEByZXR1cm5zIHtBcnJheX1cbiAqL1xuZnVuY3Rpb24gY29weUFyZ0FycmF5KGdkLCBhcmdzKSB7XG4gICAgdmFyIGNvcHkgPSBbXTtcbiAgICB2YXIgYXJnO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXJnID0gYXJnc1tpXTtcblxuICAgICAgICBpZihhcmcgPT09IGdkKSBjb3B5W2ldID0gYXJnO1xuICAgICAgICBlbHNlIGlmKHR5cGVvZiBhcmcgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBjb3B5W2ldID0gQXJyYXkuaXNBcnJheShhcmcpID9cbiAgICAgICAgICAgICAgICBMaWIuZXh0ZW5kRGVlcChbXSwgYXJnKSA6XG4gICAgICAgICAgICAgICAgTGliLmV4dGVuZERlZXBBbGwoe30sIGFyZyk7XG4gICAgICAgIH0gZWxzZSBjb3B5W2ldID0gYXJnO1xuICAgIH1cblxuICAgIHJldHVybiBjb3B5O1xufVxuXG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBVbmRvL1JlZG8gcXVldWUgZm9yIHBsb3RzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbnZhciBxdWV1ZSA9IHt9O1xuXG4vLyBUT0RPOiBkaXNhYmxlL2VuYWJsZSB1bmRvIGFuZCByZWRvIGJ1dHRvbnMgYXBwcm9wcmlhdGVseVxuXG4vKipcbiAqIEFkZCBhbiBpdGVtIHRvIHRoZSB1bmRvUXVldWUgZm9yIGEgZ3JhcGhEaXZcbiAqXG4gKiBAcGFyYW0gZ2RcbiAqIEBwYXJhbSB1bmRvRnVuYyBGdW5jdGlvbiB1bmRvIHRoaXMgb3BlcmF0aW9uXG4gKiBAcGFyYW0gdW5kb0FyZ3MgQXJncyB0byBzdXBwbHkgdW5kb0Z1bmMgd2l0aFxuICogQHBhcmFtIHJlZG9GdW5jIEZ1bmN0aW9uIHRvIHJlZG8gdGhpcyBvcGVyYXRpb25cbiAqIEBwYXJhbSByZWRvQXJncyBBcmdzIHRvIHN1cHBseSByZWRvRnVuYyB3aXRoXG4gKi9cbnF1ZXVlLmFkZCA9IGZ1bmN0aW9uKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncykge1xuICAgIHZhciBxdWV1ZU9iaixcbiAgICAgICAgcXVldWVJbmRleDtcblxuICAgIC8vIG1ha2Ugc3VyZSB3ZSBoYXZlIHRoZSBxdWV1ZSBhbmQgb3VyIHBvc2l0aW9uIGluIGl0XG4gICAgZ2QudW5kb1F1ZXVlID0gZ2QudW5kb1F1ZXVlIHx8IHtpbmRleDogMCwgcXVldWU6IFtdLCBzZXF1ZW5jZTogZmFsc2V9O1xuICAgIHF1ZXVlSW5kZXggPSBnZC51bmRvUXVldWUuaW5kZXg7XG5cbiAgICAvLyBpZiB3ZSdyZSBhbHJlYWR5IHBsYXlpbmcgYW4gdW5kbyBvciByZWRvLCBvciBpZiB0aGlzIGlzIGFuIGF1dG8gb3BlcmF0aW9uXG4gICAgLy8gKGxpa2UgcGFuZSByZXNpemUuLi4gYW55IG90aGVycz8pIHRoZW4gd2UgZG9uJ3Qgc2F2ZSB0aGlzIHRvIHRoZSB1bmRvIHF1ZXVlXG4gICAgaWYoZ2QuYXV0b3BsYXkpIHtcbiAgICAgICAgaWYoIWdkLnVuZG9RdWV1ZS5pblNlcXVlbmNlKSBnZC5hdXRvcGxheSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gaWYgd2UncmUgbm90IGluIGEgc2VxdWVuY2Ugb3IgYXJlIGp1c3Qgc3RhcnRpbmcsIHdlIG5lZWQgYSBuZXcgcXVldWUgaXRlbVxuICAgIGlmKCFnZC51bmRvUXVldWUuc2VxdWVuY2UgfHwgZ2QudW5kb1F1ZXVlLmJlZ2luU2VxdWVuY2UpIHtcbiAgICAgICAgcXVldWVPYmogPSB7dW5kbzoge2NhbGxzOiBbXSwgYXJnczogW119LCByZWRvOiB7Y2FsbHM6IFtdLCBhcmdzOiBbXX19O1xuICAgICAgICBnZC51bmRvUXVldWUucXVldWUuc3BsaWNlKHF1ZXVlSW5kZXgsIGdkLnVuZG9RdWV1ZS5xdWV1ZS5sZW5ndGggLSBxdWV1ZUluZGV4LCBxdWV1ZU9iaik7XG4gICAgICAgIGdkLnVuZG9RdWV1ZS5pbmRleCArPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlT2JqID0gZ2QudW5kb1F1ZXVlLnF1ZXVlW3F1ZXVlSW5kZXggLSAxXTtcbiAgICB9XG4gICAgZ2QudW5kb1F1ZXVlLmJlZ2luU2VxdWVuY2UgPSBmYWxzZTtcblxuICAgIC8vIHdlIHVuc2hpZnQgdG8gaGFuZGxlIGNhbGxzIGZvciB1bmRvIGluIGEgZm9yd2FyZCBmb3IgbG9vcCBsYXRlclxuICAgIGlmKHF1ZXVlT2JqKSB7XG4gICAgICAgIHF1ZXVlT2JqLnVuZG8uY2FsbHMudW5zaGlmdCh1bmRvRnVuYyk7XG4gICAgICAgIHF1ZXVlT2JqLnVuZG8uYXJncy51bnNoaWZ0KHVuZG9BcmdzKTtcbiAgICAgICAgcXVldWVPYmoucmVkby5jYWxscy5wdXNoKHJlZG9GdW5jKTtcbiAgICAgICAgcXVldWVPYmoucmVkby5hcmdzLnB1c2gocmVkb0FyZ3MpO1xuICAgIH1cblxuICAgIGlmKGdkLnVuZG9RdWV1ZS5xdWV1ZS5sZW5ndGggPiBkZmx0Q29uZmlnLnF1ZXVlTGVuZ3RoKSB7XG4gICAgICAgIGdkLnVuZG9RdWV1ZS5xdWV1ZS5zaGlmdCgpO1xuICAgICAgICBnZC51bmRvUXVldWUuaW5kZXgtLTtcbiAgICB9XG59O1xuXG4vKipcbiAqIEJlZ2luIGEgc2VxdWVuY2Ugb2YgdW5kb1F1ZXVlIGNoYW5nZXNcbiAqXG4gKiBAcGFyYW0gZ2RcbiAqL1xucXVldWUuc3RhcnRTZXF1ZW5jZSA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgZ2QudW5kb1F1ZXVlID0gZ2QudW5kb1F1ZXVlIHx8IHtpbmRleDogMCwgcXVldWU6IFtdLCBzZXF1ZW5jZTogZmFsc2V9O1xuICAgIGdkLnVuZG9RdWV1ZS5zZXF1ZW5jZSA9IHRydWU7XG4gICAgZ2QudW5kb1F1ZXVlLmJlZ2luU2VxdWVuY2UgPSB0cnVlO1xufTtcblxuLyoqXG4gKiBTdG9wIGEgc2VxdWVuY2Ugb2YgdW5kb1F1ZXVlIGNoYW5nZXNcbiAqXG4gKiBDYWxsIHRoaXMgKmFmdGVyKiB5b3UncmUgc3VyZSB5b3VyIHVuZG8gY2hhaW4gaGFzIGVuZGVkXG4gKlxuICogQHBhcmFtIGdkXG4gKi9cbnF1ZXVlLnN0b3BTZXF1ZW5jZSA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgZ2QudW5kb1F1ZXVlID0gZ2QudW5kb1F1ZXVlIHx8IHtpbmRleDogMCwgcXVldWU6IFtdLCBzZXF1ZW5jZTogZmFsc2V9O1xuICAgIGdkLnVuZG9RdWV1ZS5zZXF1ZW5jZSA9IGZhbHNlO1xuICAgIGdkLnVuZG9RdWV1ZS5iZWdpblNlcXVlbmNlID0gZmFsc2U7XG59O1xuXG4vKipcbiAqIE1vdmUgb25lIHN0ZXAgYmFjayBpbiB0aGUgdW5kbyBxdWV1ZSwgYW5kIHVuZG8gdGhlIG9iamVjdCB0aGVyZS5cbiAqXG4gKiBAcGFyYW0gZ2RcbiAqL1xucXVldWUudW5kbyA9IGZ1bmN0aW9uIHVuZG8oZ2QpIHtcbiAgICB2YXIgcXVldWVPYmosIGk7XG5cbiAgICBpZihnZC5mcmFtZXdvcmsgJiYgZ2QuZnJhbWV3b3JrLmlzUG9sYXIpIHtcbiAgICAgICAgZ2QuZnJhbWV3b3JrLnVuZG8oKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZihnZC51bmRvUXVldWUgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgICAgaXNOYU4oZ2QudW5kb1F1ZXVlLmluZGV4KSB8fFxuICAgICAgICAgICAgZ2QudW5kb1F1ZXVlLmluZGV4IDw9IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGluZGV4IGlzIHBvaW50aW5nIHRvIG5leHQgKmZvcndhcmQqIHF1ZXVlT2JqLCBwb2ludCB0byB0aGUgb25lIHdlJ3JlIHVuZG9pbmdcbiAgICBnZC51bmRvUXVldWUuaW5kZXgtLTtcblxuICAgIC8vIGdldCB0aGUgcXVldWVPYmogZm9yIGluc3RydWN0aW9ucyBvbiBob3cgdG8gdW5kb1xuICAgIHF1ZXVlT2JqID0gZ2QudW5kb1F1ZXVlLnF1ZXVlW2dkLnVuZG9RdWV1ZS5pbmRleF07XG5cbiAgICAvLyB0aGlzIHNlcXVlbmNlIGtlZXBzIHRoaW5ncyBmcm9tIGFkZGluZyB0byB0aGUgcXVldWUgZHVyaW5nIHVuZG8vcmVkb1xuICAgIGdkLnVuZG9RdWV1ZS5pblNlcXVlbmNlID0gdHJ1ZTtcbiAgICBmb3IoaSA9IDA7IGkgPCBxdWV1ZU9iai51bmRvLmNhbGxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHF1ZXVlLnBsb3REbyhnZCwgcXVldWVPYmoudW5kby5jYWxsc1tpXSwgcXVldWVPYmoudW5kby5hcmdzW2ldKTtcbiAgICB9XG4gICAgZ2QudW5kb1F1ZXVlLmluU2VxdWVuY2UgPSBmYWxzZTtcbiAgICBnZC5hdXRvcGxheSA9IGZhbHNlO1xufTtcblxuLyoqXG4gKiBSZWRvIHRoZSBjdXJyZW50IG9iamVjdCBpbiB0aGUgdW5kbywgdGhlbiBtb3ZlIGZvcndhcmQgaW4gdGhlIHF1ZXVlLlxuICpcbiAqIEBwYXJhbSBnZFxuICovXG5xdWV1ZS5yZWRvID0gZnVuY3Rpb24gcmVkbyhnZCkge1xuICAgIHZhciBxdWV1ZU9iaiwgaTtcblxuICAgIGlmKGdkLmZyYW1ld29yayAmJiBnZC5mcmFtZXdvcmsuaXNQb2xhcikge1xuICAgICAgICBnZC5mcmFtZXdvcmsucmVkbygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmKGdkLnVuZG9RdWV1ZSA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgICBpc05hTihnZC51bmRvUXVldWUuaW5kZXgpIHx8XG4gICAgICAgICAgICBnZC51bmRvUXVldWUuaW5kZXggPj0gZ2QudW5kb1F1ZXVlLnF1ZXVlLmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZ2V0IHRoZSBxdWV1ZU9iaiBmb3IgaW5zdHJ1Y3Rpb25zIG9uIGhvdyB0byB1bmRvXG4gICAgcXVldWVPYmogPSBnZC51bmRvUXVldWUucXVldWVbZ2QudW5kb1F1ZXVlLmluZGV4XTtcblxuICAgIC8vIHRoaXMgc2VxdWVuY2Uga2VlcHMgdGhpbmdzIGZyb20gYWRkaW5nIHRvIHRoZSBxdWV1ZSBkdXJpbmcgdW5kby9yZWRvXG4gICAgZ2QudW5kb1F1ZXVlLmluU2VxdWVuY2UgPSB0cnVlO1xuICAgIGZvcihpID0gMDsgaSA8IHF1ZXVlT2JqLnJlZG8uY2FsbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcXVldWUucGxvdERvKGdkLCBxdWV1ZU9iai5yZWRvLmNhbGxzW2ldLCBxdWV1ZU9iai5yZWRvLmFyZ3NbaV0pO1xuICAgIH1cbiAgICBnZC51bmRvUXVldWUuaW5TZXF1ZW5jZSA9IGZhbHNlO1xuICAgIGdkLmF1dG9wbGF5ID0gZmFsc2U7XG5cbiAgICAvLyBpbmRleCBpcyBwb2ludGluZyB0byB0aGUgdGhpbmcgd2UganVzdCByZWRpZCwgbW92ZSBpdFxuICAgIGdkLnVuZG9RdWV1ZS5pbmRleCsrO1xufTtcblxuLyoqXG4gKiBDYWxsZWQgYnkgdW5kby9yZWRvIHRvIG1ha2UgdGhlIGFjdHVhbCBjaGFuZ2VzLlxuICpcbiAqIE5vdCBtZWFudCB0byBiZSBjYWxsZWQgcHVibGljYWxseSwgYnV0IGluY2x1ZGVkIGZvciBtb2NraW5nIG91dCBpbiB0ZXN0cy5cbiAqXG4gKiBAcGFyYW0gZ2RcbiAqIEBwYXJhbSBmdW5jXG4gKiBAcGFyYW0gYXJnc1xuICovXG5xdWV1ZS5wbG90RG8gPSBmdW5jdGlvbihnZCwgZnVuYywgYXJncykge1xuICAgIGdkLmF1dG9wbGF5ID0gdHJ1ZTtcblxuICAgIC8vIHRoaXMgKndvbid0KiBjb3B5IGdkIGFuZCBpdCBwcmVzZXJ2ZXMgYHVuZGVmaW5lZGAgcHJvcGVydGllcyFcbiAgICBhcmdzID0gY29weUFyZ0FycmF5KGdkLCBhcmdzKTtcblxuICAgIC8vIGNhbGwgdGhlIHN1cHBsaWVkIGZ1bmN0aW9uXG4gICAgZnVuYy5hcHBseShudWxsLCBhcmdzKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gcXVldWU7XG5cbn0se1wiLi4vbGliXCI6NzE5LFwiLi4vcGxvdF9hcGkvcGxvdF9jb25maWdcIjo3NTV9XSw3MzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogbWFrZSBhIHJlZ2V4IGZvciBtYXRjaGluZyBjb3VudGVyIGlkcy9uYW1lcyBpZSB4YXhpcywgeGF4aXMyLCB4YXhpczEwLi4uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGhlYWQ6IHRoZSBoZWFkIG9mIHRoZSBwYXR0ZXJuLCBlZyAneCcgbWF0Y2hlcyAneCcsICd4MicsICd4MTAnIGV0Yy5cbiAqICAgICAgJ3h5JyBpcyBhIHNwZWNpYWwgY2FzZSBmb3IgY2FydGVzaWFuIHN1YnBsb3RzOiBpdCBtYXRjaGVzICd4MnkzJyBldGNcbiAqIEBwYXJhbSB7T3B0aW9uYWwoc3RyaW5nKX0gdGFpbDogYSBmaXhlZCBwaWVjZSBhZnRlciB0aGUgaWRcbiAqICAgICAgZWcgY291bnRlclJlZ2V4KCdzY2VuZScsICcuYW5ub3RhdGlvbnMnKSBmb3Igc2NlbmUyLmFubm90YXRpb25zIGV0Yy5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb3BlbkVuZGVkOiBpZiB0cnVlLCB0aGUgc3RyaW5nIG1heSBjb250aW51ZSBwYXN0IHRoZSBtYXRjaC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gbWF0Y2hCZWdpbm5pbmc6IGlmIGZhbHNlLCB0aGUgc3RyaW5nIG1heSBzdGFydCBiZWZvcmUgdGhlIG1hdGNoLlxuICovXG5leHBvcnRzLmNvdW50ZXIgPSBmdW5jdGlvbihoZWFkLCB0YWlsLCBvcGVuRW5kZWQsIG1hdGNoQmVnaW5uaW5nKSB7XG4gICAgdmFyIGZ1bGxUYWlsID0gKHRhaWwgfHwgJycpICsgKG9wZW5FbmRlZCA/ICcnIDogJyQnKTtcbiAgICB2YXIgc3RhcnRXaXRoUHJlZml4ID0gbWF0Y2hCZWdpbm5pbmcgPT09IGZhbHNlID8gJycgOiAnXic7XG4gICAgaWYoaGVhZCA9PT0gJ3h5Jykge1xuICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cChzdGFydFdpdGhQcmVmaXggKyAneChbMi05XXxbMS05XVswLTldKyk/eShbMi05XXxbMS05XVswLTldKyk/JyArIGZ1bGxUYWlsKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoc3RhcnRXaXRoUHJlZml4ICsgaGVhZCArICcoWzItOV18WzEtOV1bMC05XSspPycgKyBmdWxsVGFpbCk7XG59O1xuXG59LHt9XSw3MzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbi8vIEFTQ0VORDogY2hvcCBvZmYgdGhlIGxhc3QgbmVzdGluZyBsZXZlbCAtIGVpdGhlciBbPG4+XSBvciAuPGtleT4gLSB0byBhc2NlbmRcbi8vIHRoZSBhdHRyaWJ1dGUgdHJlZS4gdGhlIHJlbWFpbmluZyBhdHRyU3RyaW5nIGlzIGluIG1hdGNoWzFdXG52YXIgQVNDRU5EID0gL14oLiopKFxcLlteXFwuXFxbXFxdXSt8XFxbXFxkXFxdKSQvO1xuXG4vLyBTSU1QTEVBVFRSOiBpcyB0aGlzIGFuIHVuLW5lc3RlZCBhdHRyaWJ1dGU/IChubyBkb3RzIG9yIGJyYWNrZXRzKVxudmFyIFNJTVBMRUFUVFIgPSAvXlteXFwuXFxbXFxdXSskLztcblxuLypcbiAqIGNhbGN1bGF0ZSBhIHJlbGF0aXZlIGF0dHJpYnV0ZSBzdHJpbmcsIHNpbWlsYXIgdG8gYSByZWxhdGl2ZSBwYXRoXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2VBdHRyOlxuICogICBhbiBhdHRyaWJ1dGUgc3RyaW5nLCBzdWNoIGFzICdhbm5vdGF0aW9uc1szXS54Jy4gVGhlIFwiY3VycmVudCBsb2NhdGlvblwiXG4gKiAgIGlzIHRoZSBhdHRyaWJ1dGUgc3RyaW5nIG1pbnVzIHRoZSBsYXN0IGNvbXBvbmVudCAoJ2Fubm90YXRpb25zWzNdJylcbiAqIEBwYXJhbSB7c3RyaW5nfSByZWxhdGl2ZUF0dHI6XG4gKiAgIGEgcm91dGUgdG8gdGhlIGRlc2lyZWQgYXR0cmlidXRlIHN0cmluZywgdXNpbmcgJ14nIHRvIGFzY2VuZFxuICpcbiAqIEByZXR1cm4ge3N0cmluZ30gYXR0clN0cmluZzpcbiAqICAgZm9yIGV4YW1wbGU6XG4gKiAgICAgcmVsYXRpdmVBdHRyKCdhbm5vdGF0aW9uc1szXS54JywgJ3knKSA9ICdhbm5vdGF0aW9uc1szXS55J1xuICogICAgIHJlbGF0aXZlQXR0cignYW5ub3RhdGlvbnNbM10ueCcsICdeWzJdLnonKSA9ICdhbm5vdGF0aW9uc1syXS56J1xuICogICAgIHJlbGF0aXZlQXR0cignYW5ub3RhdGlvbnNbM10ueCcsICdeXm1hcmdpbicpID0gJ21hcmdpbidcbiAqICAgICByZWxhdGl2ZUF0dHIoJ2Fubm90YXRpb25zWzNdLngnLCAnXl5tYXJnaW4ucicpID0gJ21hcmdpbi5yJ1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGJhc2VBdHRyLCByZWxhdGl2ZUF0dHIpIHtcbiAgICB3aGlsZShyZWxhdGl2ZUF0dHIpIHtcbiAgICAgICAgdmFyIG1hdGNoID0gYmFzZUF0dHIubWF0Y2goQVNDRU5EKTtcblxuICAgICAgICBpZihtYXRjaCkgYmFzZUF0dHIgPSBtYXRjaFsxXTtcbiAgICAgICAgZWxzZSBpZihiYXNlQXR0ci5tYXRjaChTSU1QTEVBVFRSKSkgYmFzZUF0dHIgPSAnJztcbiAgICAgICAgZWxzZSB0aHJvdyBuZXcgRXJyb3IoJ2JhZCByZWxhdGl2ZUF0dHIgY2FsbDonICsgW2Jhc2VBdHRyLCByZWxhdGl2ZUF0dHJdKTtcblxuICAgICAgICBpZihyZWxhdGl2ZUF0dHIuY2hhckF0KDApID09PSAnXicpIHJlbGF0aXZlQXR0ciA9IHJlbGF0aXZlQXR0ci5zbGljZSgxKTtcbiAgICAgICAgZWxzZSBicmVhaztcbiAgICB9XG5cbiAgICBpZihiYXNlQXR0ciAmJiByZWxhdGl2ZUF0dHIuY2hhckF0KDApICE9PSAnWycpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VBdHRyICsgJy4nICsgcmVsYXRpdmVBdHRyO1xuICAgIH1cbiAgICByZXR1cm4gYmFzZUF0dHIgKyByZWxhdGl2ZUF0dHI7XG59O1xuXG59LHt9XSw3Mzc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi9hcnJheScpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG52YXIgaXNQbGFpbk9iamVjdCA9IF9kZXJlcV8oJy4vaXNfcGxhaW5fb2JqZWN0Jyk7XG5cbi8qKlxuICogUmVsaW5rIHByaXZhdGUgX2tleXMgYW5kIGtleXMgd2l0aCBhIGZ1bmN0aW9uIHZhbHVlIGZyb20gb25lIGNvbnRhaW5lclxuICogdG8gdGhlIG5ldyBjb250YWluZXIuXG4gKiBSZWxpbmsgbWVhbnMgY29weWluZyBpZiBvYmplY3QgaXMgcGFzcy1ieS12YWx1ZSBhbmQgYWRkaW5nIGEgcmVmZXJlbmNlXG4gKiBpZiBvYmplY3QgaXMgcGFzcy1ieS1yZWYuXG4gKiBUaGlzIHByZXZlbnRzIGRlZXBDb3B5aW5nIG1hc3NpdmUgc3RydWN0dXJlcyBsaWtlIGEgd2ViZ2wgY29udGV4dC5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiByZWxpbmtQcml2YXRlS2V5cyh0b0NvbnRhaW5lciwgZnJvbUNvbnRhaW5lcikge1xuICAgIGZvcih2YXIgayBpbiBmcm9tQ29udGFpbmVyKSB7XG4gICAgICAgIHZhciBmcm9tVmFsID0gZnJvbUNvbnRhaW5lcltrXTtcbiAgICAgICAgdmFyIHRvVmFsID0gdG9Db250YWluZXJba107XG5cbiAgICAgICAgaWYodG9WYWwgPT09IGZyb21WYWwpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmKGsuY2hhckF0KDApID09PSAnXycgfHwgdHlwZW9mIGZyb21WYWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIC8vIGlmIGl0IGFscmVhZHkgZXhpc3RzIGF0IHRoaXMgcG9pbnQsIGl0J3Mgc29tZXRoaW5nXG4gICAgICAgICAgICAvLyB0aGF0IHdlIHJlY3JlYXRlIGVhY2ggdGltZSBhcm91bmQsIHNvIGlnbm9yZSBpdFxuICAgICAgICAgICAgaWYoayBpbiB0b0NvbnRhaW5lcikgY29udGludWU7XG5cbiAgICAgICAgICAgIHRvQ29udGFpbmVyW2tdID0gZnJvbVZhbDtcbiAgICAgICAgfSBlbHNlIGlmKGlzQXJyYXlPclR5cGVkQXJyYXkoZnJvbVZhbCkgJiYgaXNBcnJheU9yVHlwZWRBcnJheSh0b1ZhbCkgJiYgaXNQbGFpbk9iamVjdChmcm9tVmFsWzBdKSkge1xuICAgICAgICAgICAgLy8gZmlsdGVyIG91dCBkYXRhX2FycmF5IGl0ZW1zIHRoYXQgY2FuIGNvbnRhaW4gdXNlciBvYmplY3RzXG4gICAgICAgICAgICAvLyBtb3N0IG9mIHRoZSB0aW1lIHRoZSB0b1ZhbCA9PT0gZnJvbVZhbCBjaGVjayB3aWxsIGNhdGNoIHRoZXNlIGVhcmx5XG4gICAgICAgICAgICAvLyBidXQgaWYgdGhlIHVzZXIgbWFrZXMgbmV3IG9uZXMgd2UgYWxzbyBkb24ndCB3YW50IHRvIHJlY3Vyc2UgaW4uXG4gICAgICAgICAgICBpZihrID09PSAnY3VzdG9tZGF0YScgfHwgayA9PT0gJ2lkcycpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAvLyByZWN1cnNlIGludG8gYXJyYXlzIGNvbnRhaW5lcnNcbiAgICAgICAgICAgIHZhciBtaW5MZW4gPSBNYXRoLm1pbihmcm9tVmFsLmxlbmd0aCwgdG9WYWwubGVuZ3RoKTtcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBtaW5MZW47IGorKykge1xuICAgICAgICAgICAgICAgIGlmKCh0b1ZhbFtqXSAhPT0gZnJvbVZhbFtqXSkgJiYgaXNQbGFpbk9iamVjdChmcm9tVmFsW2pdKSAmJiBpc1BsYWluT2JqZWN0KHRvVmFsW2pdKSkge1xuICAgICAgICAgICAgICAgICAgICByZWxpbmtQcml2YXRlS2V5cyh0b1ZhbFtqXSwgZnJvbVZhbFtqXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoaXNQbGFpbk9iamVjdChmcm9tVmFsKSAmJiBpc1BsYWluT2JqZWN0KHRvVmFsKSkge1xuICAgICAgICAgICAgLy8gcmVjdXJzZSBpbnRvIG9iamVjdHMsIGJ1dCBvbmx5IGlmIHRoZXkgc3RpbGwgZXhpc3RcbiAgICAgICAgICAgIHJlbGlua1ByaXZhdGVLZXlzKHRvVmFsLCBmcm9tVmFsKTtcblxuICAgICAgICAgICAgaWYoIU9iamVjdC5rZXlzKHRvVmFsKS5sZW5ndGgpIGRlbGV0ZSB0b0NvbnRhaW5lcltrXTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi9hcnJheVwiOjcwMixcIi4vaXNfcGxhaW5fb2JqZWN0XCI6NzIwfV0sNzM4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcbnZhciBsb2dnZXJzID0gX2RlcmVxXygnLi9sb2dnZXJzJyk7XG52YXIgaWRlbnRpdHkgPSBfZGVyZXFfKCcuL2lkZW50aXR5Jyk7XG5cbi8vIGRvbid0IHRydXN0IGZsb2F0aW5nIHBvaW50IGVxdWFsaXR5IC0gZnJhY3Rpb24gb2YgYmluIHNpemUgdG8gY2FsbFxuLy8gXCJvbiB0aGUgbGluZVwiIGFuZCBlbnN1cmUgdGhhdCB0aGV5IGdvIHRoZSByaWdodCB3YXkgc3BlY2lmaWVkIGJ5XG4vLyBsaW5lbG93XG52YXIgcm91bmRpbmdFcnJvciA9IDFlLTk7XG5cblxuLyoqXG4gKiBmaW5kQmluIC0gZmluZCB0aGUgYmluIGZvciB2YWwgLSBub3RlIHRoYXQgaXQgY2FuIHJldHVybiBvdXRzaWRlIHRoZVxuICogYmluIHJhbmdlIGFueSBwb3MuIG9yIG5lZy4gaW50ZWdlciBmb3IgbGluZWFyIGJpbnMsIG9yIC0xIG9yXG4gKiBiaW5zLmxlbmd0aC0xIGZvciBleHBsaWNpdC5cbiAqIGJpbnMgaXMgZWl0aGVyIGFuIG9iamVjdCB7c3RhcnQsc2l6ZSxlbmR9IG9yIGFuIGFycmF5IGxlbmd0aCAjYmlucysxXG4gKiBiaW5zIGNhbiBiZSBlaXRoZXIgaW5jcmVhc2luZyBvciBkZWNyZWFzaW5nIGJ1dCBtdXN0IGJlIG1vbm90b25pY1xuICogZm9yIGxpbmVhciBiaW5zLCB3ZSBjYW4ganVzdCBjYWxjdWxhdGUuIEZvciBsaXN0ZWQgYmlucywgcnVuIGEgYmluYXJ5XG4gKiBzZWFyY2ggbGluZWxvdyAodHJ1dGh5KSBzYXlzIHRoZSBiaW4gYm91bmRhcnkgc2hvdWxkIGJlIGF0dHJpYnV0ZWQgdG9cbiAqIHRoZSBsb3dlciBiaW4gcmF0aGVyIHRoYW4gdGhlIGRlZmF1bHQgdXBwZXIgYmluXG4gKi9cbmV4cG9ydHMuZmluZEJpbiA9IGZ1bmN0aW9uKHZhbCwgYmlucywgbGluZWxvdykge1xuICAgIGlmKGlzTnVtZXJpYyhiaW5zLnN0YXJ0KSkge1xuICAgICAgICByZXR1cm4gbGluZWxvdyA/XG4gICAgICAgICAgICBNYXRoLmNlaWwoKHZhbCAtIGJpbnMuc3RhcnQpIC8gYmlucy5zaXplIC0gcm91bmRpbmdFcnJvcikgLSAxIDpcbiAgICAgICAgICAgIE1hdGguZmxvb3IoKHZhbCAtIGJpbnMuc3RhcnQpIC8gYmlucy5zaXplICsgcm91bmRpbmdFcnJvcik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG4xID0gMDtcbiAgICAgICAgdmFyIG4yID0gYmlucy5sZW5ndGg7XG4gICAgICAgIHZhciBjID0gMDtcbiAgICAgICAgdmFyIGJpblNpemUgPSAobjIgPiAxKSA/IChiaW5zW24yIC0gMV0gLSBiaW5zWzBdKSAvIChuMiAtIDEpIDogMTtcbiAgICAgICAgdmFyIG4sIHRlc3Q7XG4gICAgICAgIGlmKGJpblNpemUgPj0gMCkge1xuICAgICAgICAgICAgdGVzdCA9IGxpbmVsb3cgPyBsZXNzVGhhbiA6IGxlc3NPckVxdWFsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGVzdCA9IGxpbmVsb3cgPyBncmVhdGVyT3JFcXVhbCA6IGdyZWF0ZXJUaGFuO1xuICAgICAgICB9XG4gICAgICAgIHZhbCArPSBiaW5TaXplICogcm91bmRpbmdFcnJvciAqIChsaW5lbG93ID8gLTEgOiAxKSAqIChiaW5TaXplID49IDAgPyAxIDogLTEpO1xuICAgICAgICAvLyBjIGlzIGp1c3QgdG8gYXZvaWQgaW5maW5pdGUgbG9vcHMgaWYgdGhlcmUncyBhbiBlcnJvclxuICAgICAgICB3aGlsZShuMSA8IG4yICYmIGMrKyA8IDEwMCkge1xuICAgICAgICAgICAgbiA9IE1hdGguZmxvb3IoKG4xICsgbjIpIC8gMik7XG4gICAgICAgICAgICBpZih0ZXN0KGJpbnNbbl0sIHZhbCkpIG4xID0gbiArIDE7XG4gICAgICAgICAgICBlbHNlIG4yID0gbjtcbiAgICAgICAgfVxuICAgICAgICBpZihjID4gOTApIGxvZ2dlcnMubG9nKCdMb25nIGJpbmFyeSBzZWFyY2guLi4nKTtcbiAgICAgICAgcmV0dXJuIG4xIC0gMTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBsZXNzVGhhbihhLCBiKSB7IHJldHVybiBhIDwgYjsgfVxuZnVuY3Rpb24gbGVzc09yRXF1YWwoYSwgYikgeyByZXR1cm4gYSA8PSBiOyB9XG5mdW5jdGlvbiBncmVhdGVyVGhhbihhLCBiKSB7IHJldHVybiBhID4gYjsgfVxuZnVuY3Rpb24gZ3JlYXRlck9yRXF1YWwoYSwgYikgeyByZXR1cm4gYSA+PSBiOyB9XG5cbmV4cG9ydHMuc29ydGVyQXNjID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYSAtIGI7IH07XG5leHBvcnRzLnNvcnRlckRlcyA9IGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGIgLSBhOyB9O1xuXG4vKipcbiAqIGZpbmQgZGlzdGluY3QgdmFsdWVzIGluIGFuIGFycmF5LCBsdW1waW5nIHRvZ2V0aGVyIG9uZXMgdGhhdCBhcHBlYXIgdG9cbiAqIGp1c3QgYmUgb2ZmIGJ5IGEgcm91bmRpbmcgZXJyb3JcbiAqIHJldHVybiB0aGUgZGlzdGluY3QgdmFsdWVzIGFuZCB0aGUgbWluaW11bSBkaWZmZXJlbmNlIGJldHdlZW4gYW55IHR3b1xuICovXG5leHBvcnRzLmRpc3RpbmN0VmFscyA9IGZ1bmN0aW9uKHZhbHNJbikge1xuICAgIHZhciB2YWxzID0gdmFsc0luLnNsaWNlKCk7ICAvLyBvdGhlcndpc2Ugd2Ugc29ydCB0aGUgb3JpZ2luYWwgYXJyYXkuLi5cbiAgICB2YWxzLnNvcnQoZXhwb3J0cy5zb3J0ZXJBc2MpO1xuXG4gICAgdmFyIGwgPSB2YWxzLmxlbmd0aCAtIDE7XG4gICAgdmFyIG1pbkRpZmYgPSAodmFsc1tsXSAtIHZhbHNbMF0pIHx8IDE7XG4gICAgdmFyIGVyckRpZmYgPSBtaW5EaWZmIC8gKGwgfHwgMSkgLyAxMDAwMDtcbiAgICB2YXIgdjIgPSBbdmFsc1swXV07XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIC8vIG1ha2Ugc3VyZSB2YWx1ZXMgYXJlbid0IGp1c3Qgb2ZmIGJ5IGEgcm91bmRpbmcgZXJyb3JcbiAgICAgICAgaWYodmFsc1tpICsgMV0gPiB2YWxzW2ldICsgZXJyRGlmZikge1xuICAgICAgICAgICAgbWluRGlmZiA9IE1hdGgubWluKG1pbkRpZmYsIHZhbHNbaSArIDFdIC0gdmFsc1tpXSk7XG4gICAgICAgICAgICB2Mi5wdXNoKHZhbHNbaSArIDFdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7dmFsczogdjIsIG1pbkRpZmY6IG1pbkRpZmZ9O1xufTtcblxuLyoqXG4gKiByZXR1cm4gdGhlIHNtYWxsZXN0IGVsZW1lbnQgZnJvbSAoc29ydGVkKSBhcnJheSBhcnJheUluIHRoYXQncyBiaWdnZXIgdGhhbiB2YWwsXG4gKiBvciAocmV2ZXJzZSkgdGhlIGxhcmdlc3QgZWxlbWVudCBzbWFsbGVyIHRoYW4gdmFsXG4gKiB1c2VkIHRvIGZpbmQgdGhlIGJlc3QgdGljayBnaXZlbiB0aGUgbWluaW11bSAobm9uLXJvdW5kZWQpIHRpY2tcbiAqIHBhcnRpY3VsYXJseSB1c2VmdWwgZm9yIGRhdGUvdGltZSB3aGVyZSB0aGluZ3MgYXJlIG5vdCBwb3dlcnMgb2YgMTBcbiAqIGJpbmFyeSBzZWFyY2ggaXMgcHJvYmFibHkgb3ZlcmtpbGwgaGVyZS4uLlxuICovXG5leHBvcnRzLnJvdW5kVXAgPSBmdW5jdGlvbih2YWwsIGFycmF5SW4sIHJldmVyc2UpIHtcbiAgICB2YXIgbG93ID0gMDtcbiAgICB2YXIgaGlnaCA9IGFycmF5SW4ubGVuZ3RoIC0gMTtcbiAgICB2YXIgbWlkO1xuICAgIHZhciBjID0gMDtcbiAgICB2YXIgZGxvdyA9IHJldmVyc2UgPyAwIDogMTtcbiAgICB2YXIgZGhpZ2ggPSByZXZlcnNlID8gMSA6IDA7XG4gICAgdmFyIHJvdW5kZWQgPSByZXZlcnNlID8gTWF0aC5jZWlsIDogTWF0aC5mbG9vcjtcbiAgICAvLyBjIGlzIGp1c3QgdG8gYXZvaWQgaW5maW5pdGUgbG9vcHMgaWYgdGhlcmUncyBhbiBlcnJvclxuICAgIHdoaWxlKGxvdyA8IGhpZ2ggJiYgYysrIDwgMTAwKSB7XG4gICAgICAgIG1pZCA9IHJvdW5kZWQoKGxvdyArIGhpZ2gpIC8gMik7XG4gICAgICAgIGlmKGFycmF5SW5bbWlkXSA8PSB2YWwpIGxvdyA9IG1pZCArIGRsb3c7XG4gICAgICAgIGVsc2UgaGlnaCA9IG1pZCAtIGRoaWdoO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXlJbltsb3ddO1xufTtcblxuLyoqXG4gKiBUd2VhayB0byBBcnJheS5zb3J0KHNvcnRGbikgdGhhdCBpbXByb3ZlcyBwZXJmb3JtYW5jZSBmb3IgcHJlLXNvcnRlZCBhcnJheXNcbiAqXG4gKiBOb3RlIHRoYXQgbmV3ZXIgYnJvd3NlcnMgKHN1Y2ggYXMgQ2hyb21lIHY3MCspIGFyZSBzdGFydGluZyB0byBwaWNrIHVwXG4gKiBvbiBwcmUtc29ydGVkIGFycmF5cyB3aGljaCBtYXkgcmVuZGVyIHRoZSBmb2xsb3dpbmcgb3B0aW1pemF0aW9uIHVubmVjZXNzYXJ5XG4gKiBpbiB0aGUgZnV0dXJlLlxuICpcbiAqIE1vdGl2YXRpb246IHNvbWV0aW1lcyB3ZSBuZWVkIHRvIHNvcnQgYXJyYXlzIGJ1dCB0aGUgaW5wdXQgaXMgbGlrZWx5IHRvXG4gKiBhbHJlYWR5IGJlIHNvcnRlZC4gQnJvd3NlcnMgZG9uJ3Qgc2VlbSB0byBwaWNrIHVwIG9uIHByZS1zb3J0ZWQgYXJyYXlzLFxuICogYW5kIGluIGZhY3QgQ2hyb21lIGlzIGFjdHVhbGx5ICpzbG93ZXIqIHNvcnRpbmcgcHJlLXNvcnRlZCBhcnJheXMgdGhhbiBwdXJlbHlcbiAqIHJhbmRvbSBhcnJheXMuIEZGIGlzIGF0IGxlYXN0IGZhc3RlciBpZiB0aGUgYXJyYXkgaXMgcHJlLXNvcnRlZCwgYnV0IHN0aWxsXG4gKiBub3QgYXMgZmFzdCBhcyBpdCBjb3VsZCBiZS5cbiAqIEhlcmUncyBob3cgdGhpcyBwbGF5cyBvdXQgc29ydGluZyBhIGxlbmd0aC0xZTYgYXJyYXk6XG4gKlxuICogQ2FsbHMgdG8gU29ydCBGTiAgfCAgQ2hyb21lIGJhcmUgIHwgIEZGIGJhcmUgIHwgIENocm9tZSB0d2VhayAgfCAgRkYgdHdlYWtcbiAqICAgICAgICAgICAgICAgICAgIHwgIHY2OC4wIE1hYyAgICB8ICB2NjEuMCBNYWN8ICAgICAgICAgICAgICAgIHxcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS1cbiAqIG9yZGVyZWQgICAgICAgICAgIHwgIDMwLjRlNiAgICAgICB8ICAxMC4xZTYgICB8ICAxZTYgICAgICAgICAgIHwgIDFlNlxuICogcmV2ZXJzZWQgICAgICAgICAgfCAgMjkuNGU2ICAgICAgIHwgIDkuOWU2ICAgIHwgIDFlNiArIHJldmVyc2UgfCAgMWU2ICsgcmV2ZXJzZVxuICogcmFuZG9tICAgICAgICAgICAgfCAgfjIxZTYgICAgICAgIHwgIH4xOC43ZTYgIHwgIH4yMWU2ICAgICAgICAgfCAgfjE4LjdlNlxuICpcbiAqIFNvIHRoaXMgaXMgYSBzdWJzdGFudGlhbCB3aW4gZm9yIHByZS1zb3J0ZWQgKG9yZGVyZWQgb3IgZXhhY3RseSByZXZlcnNlZClcbiAqIGFycmF5cy4gSW5jbHVkaW5nIHRoaXMgd3JhcHBlciBvbiBhbiB1bnNvcnRlZCBhcnJheSBhZGRzIGEgcGVuYWx0eSB0aGF0IHdpbGxcbiAqIGluIGdlbmVyYWwgYmUgb25seSBhIGZldyBjYWxscyB0byB0aGUgc29ydCBmdW5jdGlvbi4gVGhlIG9ubHkgY2FzZSB0aGlzXG4gKiBwZW5hbHR5IHdpbGwgYmUgc2lnbmlmaWNhbnQgaXMgaWYgdGhlIGFycmF5IGlzIG1vc3RseSBzb3J0ZWQgYnV0IHRoZXJlIGFyZVxuICogYSBmZXcgdW5zb3J0ZWQgaXRlbXMgbmVhciB0aGUgZW5kLCBidXQgdGhlIHBlbmFsdHkgaXMgc3RpbGwgYXQgbW9zdCBOIGNhbGxzXG4gKiBvdXQgb2YgKGZvciBOPTFlNikgfjIwTiB0b3RhbCBjYWxsc1xuICpcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5OiB0aGUgYXJyYXksIHRvIGJlIHNvcnRlZCBpbiBwbGFjZVxuICogQHBhcmFtIHtmdW5jdGlvbn0gc29ydEZuOiBBcyBpbiBBcnJheS5zb3J0LCBmdW5jdGlvbihhLCBiKSB0aGF0IHB1dHNcbiAqICAgICBpdGVtIGEgYmVmb3JlIGl0ZW0gYiBpZiB0aGUgcmV0dXJuIGlzIG5lZ2F0aXZlLCBhIGFmdGVyIGIgaWYgcG9zaXRpdmUsXG4gKiAgICAgYW5kIG5vIGNoYW5nZSBpZiB6ZXJvLlxuICogQHJldHVybiB7QXJyYXl9OiB0aGUgb3JpZ2luYWwgYXJyYXksIHNvcnRlZCBpbiBwbGFjZS5cbiAqL1xuZXhwb3J0cy5zb3J0ID0gZnVuY3Rpb24oYXJyYXksIHNvcnRGbikge1xuICAgIHZhciBub3RPcmRlcmVkID0gMDtcbiAgICB2YXIgbm90UmV2ZXJzZWQgPSAwO1xuICAgIGZvcih2YXIgaSA9IDE7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcGFpck9yZGVyID0gc29ydEZuKGFycmF5W2ldLCBhcnJheVtpIC0gMV0pO1xuICAgICAgICBpZihwYWlyT3JkZXIgPCAwKSBub3RPcmRlcmVkID0gMTtcbiAgICAgICAgZWxzZSBpZihwYWlyT3JkZXIgPiAwKSBub3RSZXZlcnNlZCA9IDE7XG4gICAgICAgIGlmKG5vdE9yZGVyZWQgJiYgbm90UmV2ZXJzZWQpIHJldHVybiBhcnJheS5zb3J0KHNvcnRGbik7XG4gICAgfVxuICAgIHJldHVybiBub3RSZXZlcnNlZCA/IGFycmF5IDogYXJyYXkucmV2ZXJzZSgpO1xufTtcblxuLyoqXG4gKiBmaW5kIGluZGV4IGluIGFycmF5ICdhcnInIHRoYXQgbWluaW1pemVzICdmbidcbiAqXG4gKiBAcGFyYW0ge2FycmF5fSBhcnIgOiBhcnJheSB3aGVyZSB0byBzZWFyY2hcbiAqIEBwYXJhbSB7Zm4gKG9wdGlvbmFsKX0gZm4gOiBmdW5jdGlvbiB0byBtaW5pbWl6ZSxcbiAqICAgaWYgbm90IGdpdmVuLCBmbiBpcyB0aGUgaWRlbnRpdHkgZnVuY3Rpb25cbiAqIEByZXR1cm4ge2ludGVnZXJ9XG4gKi9cbmV4cG9ydHMuZmluZEluZGV4T2ZNaW4gPSBmdW5jdGlvbihhcnIsIGZuKSB7XG4gICAgZm4gPSBmbiB8fCBpZGVudGl0eTtcblxuICAgIHZhciBtaW4gPSBJbmZpbml0eTtcbiAgICB2YXIgaW5kO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdiA9IGZuKGFycltpXSk7XG4gICAgICAgIGlmKHYgPCBtaW4pIHtcbiAgICAgICAgICAgIG1pbiA9IHY7XG4gICAgICAgICAgICBpbmQgPSBpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBpbmQ7XG59O1xuXG59LHtcIi4vaWRlbnRpdHlcIjo3MTgsXCIuL2xvZ2dlcnNcIjo3MjMsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDczOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gd29ya3Mgd2l0aCBvdXIgQ1NTIGN1cnNvciBjbGFzc2VzIChzZWUgY3NzL19jdXJzb3Iuc2Nzcylcbi8vIHRvIGFwcGx5IGN1cnNvcnMgdG8gZDMgc2luZ2xlLWVsZW1lbnQgc2VsZWN0aW9ucy5cbi8vIG9taXQgY3Vyc29yIHRvIHJldmVydCB0byB0aGUgZGVmYXVsdC5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2V0Q3Vyc29yKGVsMywgY3NyKSB7XG4gICAgKGVsMy5hdHRyKCdjbGFzcycpIHx8ICcnKS5zcGxpdCgnICcpLmZvckVhY2goZnVuY3Rpb24oY2xzKSB7XG4gICAgICAgIGlmKGNscy5pbmRleE9mKCdjdXJzb3ItJykgPT09IDApIGVsMy5jbGFzc2VkKGNscywgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaWYoY3NyKSBlbDMuY2xhc3NlZCgnY3Vyc29yLScgKyBjc3IsIHRydWUpO1xufTtcblxufSx7fV0sNzQwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb21wb25lbnRzL2NvbG9yJyk7XG5cbnZhciBub29wID0gZnVuY3Rpb24oKSB7fTtcblxuXG4vKipcbiAqIFByaW50cyBhIG5vIHdlYmdsIGVycm9yIG1lc3NhZ2UgaW50byB0aGUgc2NlbmUgY29udGFpbmVyXG4gKiBAcGFyYW0ge3NjZW5lIGluc3RhbmNlfSBzY2VuZVxuICpcbiAqIEV4cGVjdHMgJ3NjZW5lJyB0byBoYXZlIHByb3BlcnR5ICdjb250YWluZXInXG4gKlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNob3dOb1dlYkdsTXNnKHNjZW5lKSB7XG4gICAgZm9yKHZhciBwcm9wIGluIHNjZW5lKSB7XG4gICAgICAgIGlmKHR5cGVvZiBzY2VuZVtwcm9wXSA9PT0gJ2Z1bmN0aW9uJykgc2NlbmVbcHJvcF0gPSBub29wO1xuICAgIH1cblxuICAgIHNjZW5lLmRlc3Ryb3kgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgc2NlbmUuY29udGFpbmVyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc2NlbmUuY29udGFpbmVyKTtcbiAgICB9O1xuXG4gICAgdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGRpdi5jbGFzc05hbWUgPSAnbm8td2ViZ2wnO1xuICAgIGRpdi5zdHlsZS5jdXJzb3IgPSAncG9pbnRlcic7XG4gICAgZGl2LnN0eWxlLmZvbnRTaXplID0gJzI0cHgnO1xuICAgIGRpdi5zdHlsZS5jb2xvciA9IENvbG9yLmRlZmF1bHRzWzBdO1xuICAgIGRpdi5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgZGl2LnN0eWxlLmxlZnQgPSBkaXYuc3R5bGUudG9wID0gJzBweCc7XG4gICAgZGl2LnN0eWxlLndpZHRoID0gZGl2LnN0eWxlLmhlaWdodCA9ICcxMDAlJztcbiAgICBkaXYuc3R5bGVbJ2JhY2tncm91bmQtY29sb3InXSA9IENvbG9yLmxpZ2h0TGluZTtcbiAgICBkaXYuc3R5bGVbJ3otaW5kZXgnXSA9IDMwO1xuXG4gICAgdmFyIHAgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwJyk7XG4gICAgcC50ZXh0Q29udGVudCA9ICdXZWJHTCBpcyBub3Qgc3VwcG9ydGVkIGJ5IHlvdXIgYnJvd3NlciAtIHZpc2l0IGh0dHBzOi8vZ2V0LndlYmdsLm9yZyBmb3IgbW9yZSBpbmZvJztcbiAgICBwLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICBwLnN0eWxlLnRvcCA9ICc1MCUnO1xuICAgIHAuc3R5bGUubGVmdCA9ICc1MCUnO1xuICAgIHAuc3R5bGUuaGVpZ2h0ID0gJzMwJSc7XG4gICAgcC5zdHlsZS53aWR0aCA9ICc1MCUnO1xuICAgIHAuc3R5bGUubWFyZ2luID0gJy0xNSUgMCAwIC0yNSUnO1xuXG4gICAgZGl2LmFwcGVuZENoaWxkKHApO1xuICAgIHNjZW5lLmNvbnRhaW5lci5hcHBlbmRDaGlsZChkaXYpO1xuICAgIHNjZW5lLmNvbnRhaW5lci5zdHlsZS5iYWNrZ3JvdW5kID0gJyNGRkZGRkYnO1xuICAgIHNjZW5lLmNvbnRhaW5lci5vbmNsaWNrID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHdpbmRvdy5vcGVuKCdodHRwczovL2dldC53ZWJnbC5vcmcnKTtcbiAgICB9O1xuXG4gICAgLy8gcmV0dXJuIGJlZm9yZSBzZXR0aW5nIHVwIGNhbWVyYSBhbmQgb25yZW5kZXIgbWV0aG9kc1xuICAgIHJldHVybiBmYWxzZTtcbn07XG5cbn0se1wiLi4vY29tcG9uZW50cy9jb2xvclwiOjU5M31dLDc0MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IF9kZXJlcV8oJy4vYXJyYXknKS5pc0FycmF5T3JUeXBlZEFycmF5O1xuXG4vKipcbiAqIGFnZ051bXMoKSByZXR1cm5zIHRoZSByZXN1bHQgb2YgYW4gYWdncmVnYXRlIGZ1bmN0aW9uIGFwcGxpZWQgdG8gYW4gYXJyYXkgb2ZcbiAqIHZhbHVlcywgd2hlcmUgbm9uLW51bWVyaWNhbCB2YWx1ZXMgaGF2ZSBiZWVuIHRvc3NlZCBvdXQuXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbn0gZiAtIGFnZ3JlZ2F0aW9uIGZ1bmN0aW9uIChlLmcuLCBNYXRoLm1pbilcbiAqIEBwYXJhbSB7TnVtYmVyfSB2IC0gaW5pdGlhbCB2YWx1ZSAoY29udGludWluZyBmcm9tIHByZXZpb3VzIGNhbGxzKVxuICogICAgICBpZiB0aGVyZSdzIG5vIGNvbnRpbnVpbmcgdmFsdWUsIHVzZSBudWxsIGZvciBzZWxlY3Rvci10eXBlXG4gKiAgICAgIGZ1bmN0aW9ucyAobWF4LG1pbiksIG9yIDAgZm9yIHN1bW1hdGlvbnNcbiAqIEBwYXJhbSB7QXJyYXl9IGEgLSBhcnJheSB0byBhZ2dyZWdhdGUgKG1heSBiZSBuZXN0ZWQsIHdlIHdpbGwgcmVjdXJzZSxcbiAqICAgICAgICAgICAgICAgICAgICBidXQgYWxsIGVsZW1lbnRzIG11c3QgaGF2ZSB0aGUgc2FtZSBkaW1lbnNpb24pXG4gKiBAcGFyYW0ge051bWJlcn0gbGVuIC0gbWF4aW11bSBsZW5ndGggb2YgYSB0byBhZ2dyZWdhdGVcbiAqIEByZXR1cm4ge051bWJlcn0gLSByZXN1bHQgb2YgZiBhcHBsaWVkIHRvIGEgc3RhcnRpbmcgZnJvbSB2XG4gKi9cbmV4cG9ydHMuYWdnTnVtcyA9IGZ1bmN0aW9uKGYsIHYsIGEsIGxlbikge1xuICAgIHZhciBpLFxuICAgICAgICBiO1xuICAgIGlmKCFsZW4gfHwgbGVuID4gYS5sZW5ndGgpIGxlbiA9IGEubGVuZ3RoO1xuICAgIGlmKCFpc051bWVyaWModikpIHYgPSBmYWxzZTtcbiAgICBpZihpc0FycmF5T3JUeXBlZEFycmF5KGFbMF0pKSB7XG4gICAgICAgIGIgPSBuZXcgQXJyYXkobGVuKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIGJbaV0gPSBleHBvcnRzLmFnZ051bXMoZiwgdiwgYVtpXSk7XG4gICAgICAgIGEgPSBiO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmKCFpc051bWVyaWModikpIHYgPSBhW2ldO1xuICAgICAgICBlbHNlIGlmKGlzTnVtZXJpYyhhW2ldKSkgdiA9IGYoK3YsICthW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIHY7XG59O1xuXG4vKipcbiAqIG1lYW4gJiBzdGQgZGV2IGZ1bmN0aW9ucyB1c2luZyBhZ2dOdW1zLCBzbyBpdCBoYW5kbGVzIG5vbi1udW1lcmljcyBuaWNlbHlcbiAqIGV2ZW4gbmVlZCB0byB1c2UgYWdnTnVtcyBpbnN0ZWFkIG9mIC5sZW5ndGgsIHRvIHRvc3Mgb3V0IG5vbi1udW1lcmljc1xuICovXG5leHBvcnRzLmxlbiA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICByZXR1cm4gZXhwb3J0cy5hZ2dOdW1zKGZ1bmN0aW9uKGEpIHsgcmV0dXJuIGEgKyAxOyB9LCAwLCBkYXRhKTtcbn07XG5cbmV4cG9ydHMubWVhbiA9IGZ1bmN0aW9uKGRhdGEsIGxlbikge1xuICAgIGlmKCFsZW4pIGxlbiA9IGV4cG9ydHMubGVuKGRhdGEpO1xuICAgIHJldHVybiBleHBvcnRzLmFnZ051bXMoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYSArIGI7IH0sIDAsIGRhdGEpIC8gbGVuO1xufTtcblxuZXhwb3J0cy5taWRSYW5nZSA9IGZ1bmN0aW9uKG51bUFycikge1xuICAgIGlmKG51bUFyciA9PT0gdW5kZWZpbmVkIHx8IG51bUFyci5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIChleHBvcnRzLmFnZ051bXMoTWF0aC5tYXgsIG51bGwsIG51bUFycikgKyBleHBvcnRzLmFnZ051bXMoTWF0aC5taW4sIG51bGwsIG51bUFycikpIC8gMjtcbn07XG5cbmV4cG9ydHMudmFyaWFuY2UgPSBmdW5jdGlvbihkYXRhLCBsZW4sIG1lYW4pIHtcbiAgICBpZighbGVuKSBsZW4gPSBleHBvcnRzLmxlbihkYXRhKTtcbiAgICBpZighaXNOdW1lcmljKG1lYW4pKSBtZWFuID0gZXhwb3J0cy5tZWFuKGRhdGEsIGxlbik7XG5cbiAgICByZXR1cm4gZXhwb3J0cy5hZ2dOdW1zKGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEgKyBNYXRoLnBvdyhiIC0gbWVhbiwgMik7XG4gICAgfSwgMCwgZGF0YSkgLyBsZW47XG59O1xuXG5leHBvcnRzLnN0ZGV2ID0gZnVuY3Rpb24oZGF0YSwgbGVuLCBtZWFuKSB7XG4gICAgcmV0dXJuIE1hdGguc3FydChleHBvcnRzLnZhcmlhbmNlKGRhdGEsIGxlbiwgbWVhbikpO1xufTtcblxuLyoqXG4gKiBtZWRpYW4gb2YgYSBmaW5pdGUgc2V0IG9mIG51bWJlcnNcbiAqIHJlZmVyZW5jZSBwYWdlOiBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NZWRpYW4jRmluaXRlX3NldF9vZl9udW1iZXJzXG4qKi9cbmV4cG9ydHMubWVkaWFuID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIHZhciBiID0gZGF0YS5zbGljZSgpLnNvcnQoKTtcbiAgICByZXR1cm4gZXhwb3J0cy5pbnRlcnAoYiwgMC41KTtcbn07XG5cbi8qKlxuICogaW50ZXJwKCkgY29tcHV0ZXMgYSBwZXJjZW50aWxlIChxdWFudGlsZSkgZm9yIGEgZ2l2ZW4gZGlzdHJpYnV0aW9uLlxuICogV2UgaW50ZXJwb2xhdGUgdGhlIGRpc3RyaWJ1dGlvbiAodG8gY29tcHV0ZSBxdWFudGlsZXMsIHdlIGZvbGxvdyBtZXRob2QgIzEwIGhlcmU6XG4gKiBodHRwOi8vd3d3LmFtc3RhdC5vcmcvcHVibGljYXRpb25zL2pzZS92MTRuMy9sYW5nZm9yZC5odG1sKS5cbiAqIFR5cGljYWxseSB0aGUgaW5kZXggb3IgcmFuayAobiAqIGFyci5sZW5ndGgpIG1heSBiZSBub24taW50ZWdlci5cbiAqIEZvciByZWZlcmVuY2U6IGVuZHMgYXJlIGNsaXBwZWQgdG8gdGhlIGV4dHJlbWUgdmFsdWVzIGluIHRoZSBhcnJheTtcbiAqIEZvciBib3ggcGxvdHM6IGluZGV4IHlvdSBnZXQgaXMgaGFsZiBhIHBvaW50IHRvbyBoaWdoIChzZWVcbiAqIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGVyY2VudGlsZSNOZWFyZXN0X3JhbmspIGJ1dCBub3RlIHRoYXQgdGhpcyBkZWZpbml0aW9uXG4gKiBpbmRleGVzIGZyb20gMSByYXRoZXIgdGhhbiAwLCBzbyB3ZSBzdWJ0cmFjdCAxLzIgKGluc3RlYWQgb2YgYWRkKS5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBhcnIgLSBUaGlzIGFycmF5IGNvbnRhaW5zIHRoZSB2YWx1ZXMgdGhhdCBtYWtlIHVwIHRoZSBkaXN0cmlidXRpb24uXG4gKiBAcGFyYW0ge051bWJlcn0gbiAtIEJldHdlZW4gMCBhbmQgMSwgbiA9IHAvMTAwIGlzIHN1Y2ggdGhhdCB3ZSBjb21wdXRlIHRoZSBwXnRoIHBlcmNlbnRpbGUuXG4gKiBGb3IgZXhhbXBsZSwgdGhlIDUwdGggcGVyY2VudGlsZSAob3IgbWVkaWFuKSBjb3JyZXNwb25kcyB0byBuID0gMC41XG4gKiBAcmV0dXJuIHtOdW1iZXJ9IC0gcGVyY2VudGlsZVxuICovXG5leHBvcnRzLmludGVycCA9IGZ1bmN0aW9uKGFyciwgbikge1xuICAgIGlmKCFpc051bWVyaWMobikpIHRocm93ICduIHNob3VsZCBiZSBhIGZpbml0ZSBudW1iZXInO1xuICAgIG4gPSBuICogYXJyLmxlbmd0aCAtIDAuNTtcbiAgICBpZihuIDwgMCkgcmV0dXJuIGFyclswXTtcbiAgICBpZihuID4gYXJyLmxlbmd0aCAtIDEpIHJldHVybiBhcnJbYXJyLmxlbmd0aCAtIDFdO1xuICAgIHZhciBmcmFjID0gbiAlIDE7XG4gICAgcmV0dXJuIGZyYWMgKiBhcnJbTWF0aC5jZWlsKG4pXSArICgxIC0gZnJhYykgKiBhcnJbTWF0aC5mbG9vcihuKV07XG59O1xuXG59LHtcIi4vYXJyYXlcIjo3MDIsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDc0MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHJnYmEgPSBfZGVyZXFfKCdjb2xvci1ub3JtYWxpemUnKTtcblxuZnVuY3Rpb24gc3RyMlJnYmFBcnJheShjb2xvcikge1xuICAgIGlmKCFjb2xvcikgcmV0dXJuIFswLCAwLCAwLCAxXTtcbiAgICByZXR1cm4gcmdiYShjb2xvcik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc3RyMlJnYmFBcnJheTtcblxufSx7XCJjb2xvci1ub3JtYWxpemVcIjoxMjB9XSw3NDM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbi8qIGdsb2JhbCBNYXRoSmF4OmZhbHNlICovXG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcbnZhciB4bWxuc05hbWVzcGFjZXMgPSBfZGVyZXFfKCcuLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlcycpO1xudmFyIExJTkVfU1BBQ0lORyA9IF9kZXJlcV8oJy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKS5MSU5FX1NQQUNJTkc7XG5cbi8vIHRleHQgY29udmVydGVyXG5cbmZ1bmN0aW9uIGdldFNpemUoX3NlbGVjdGlvbiwgX2RpbWVuc2lvbikge1xuICAgIHJldHVybiBfc2VsZWN0aW9uLm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVtfZGltZW5zaW9uXTtcbn1cblxudmFyIEZJTkRfVEVYID0gLyhbXiRdKikoWyRdK1teJF0qWyRdKykoW14kXSopLztcblxuZXhwb3J0cy5jb252ZXJ0VG9Uc3BhbnMgPSBmdW5jdGlvbihfY29udGV4dCwgZ2QsIF9jYWxsYmFjaykge1xuICAgIHZhciBzdHIgPSBfY29udGV4dC50ZXh0KCk7XG5cbiAgICAvLyBVbnRpbCB3ZSBnZXQgdGV4IGludGVncmF0ZWQgbW9yZSBmdWxseSAoc28gaXQgY2FuIGJlIHVzZWQgYWxvbmcgd2l0aCBub24tdGV4KVxuICAgIC8vIGFsbG93IHNvbWUgZWxlbWVudHMgdG8gcHJvaGliaXQgaXQgYnkgYXR0YWNoaW5nICdkYXRhLW5vdGV4JyB0byB0aGUgb3JpZ2luYWxcbiAgICB2YXIgdGV4ID0gKCFfY29udGV4dC5hdHRyKCdkYXRhLW5vdGV4JykpICYmXG4gICAgICAgICh0eXBlb2YgTWF0aEpheCAhPT0gJ3VuZGVmaW5lZCcpICYmXG4gICAgICAgIHN0ci5tYXRjaChGSU5EX1RFWCk7XG5cbiAgICB2YXIgcGFyZW50ID0gZDMuc2VsZWN0KF9jb250ZXh0Lm5vZGUoKS5wYXJlbnROb2RlKTtcbiAgICBpZihwYXJlbnQuZW1wdHkoKSkgcmV0dXJuO1xuICAgIHZhciBzdmdDbGFzcyA9IChfY29udGV4dC5hdHRyKCdjbGFzcycpKSA/IF9jb250ZXh0LmF0dHIoJ2NsYXNzJykuc3BsaXQoJyAnKVswXSA6ICd0ZXh0JztcbiAgICBzdmdDbGFzcyArPSAnLW1hdGgnO1xuICAgIHBhcmVudC5zZWxlY3RBbGwoJ3N2Zy4nICsgc3ZnQ2xhc3MpLnJlbW92ZSgpO1xuICAgIHBhcmVudC5zZWxlY3RBbGwoJ2cuJyArIHN2Z0NsYXNzICsgJy1ncm91cCcpLnJlbW92ZSgpO1xuICAgIF9jb250ZXh0LnN0eWxlKCdkaXNwbGF5JywgbnVsbClcbiAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgLy8gc29tZSBjYWxsZXJzIHVzZSBkYXRhLXVuZm9ybWF0dGVkICpmcm9tIHRoZSA8dGV4dD4gZWxlbWVudCogaW4gJ2NhbmNlbCdcbiAgICAgICAgICAgIC8vIHNvIHdlIG5lZWQgaXQgaGVyZSBldmVuIGlmIHdlJ3JlIGdvaW5nIHRvIHR1cm4gaXQgaW50byBtYXRoXG4gICAgICAgICAgICAvLyB0aGVzZSB0d28gKHBsdXMgc3R5bGUgYW5kIHRleHQtYW5jaG9yIGF0dHJpYnV0ZXMpIGZvcm0gdGhlIGtleSB3ZSdyZVxuICAgICAgICAgICAgLy8gZ29pbmcgdG8gdXNlIGZvciBEcmF3aW5nLmJCb3hcbiAgICAgICAgICAgICdkYXRhLXVuZm9ybWF0dGVkJzogc3RyLFxuICAgICAgICAgICAgJ2RhdGEtbWF0aCc6ICdOJ1xuICAgICAgICB9KTtcblxuICAgIGZ1bmN0aW9uIHNob3dUZXh0KCkge1xuICAgICAgICBpZighcGFyZW50LmVtcHR5KCkpIHtcbiAgICAgICAgICAgIHN2Z0NsYXNzID0gX2NvbnRleHQuYXR0cignY2xhc3MnKSArICctbWF0aCc7XG4gICAgICAgICAgICBwYXJlbnQuc2VsZWN0KCdzdmcuJyArIHN2Z0NsYXNzKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgICAgICBfY29udGV4dC50ZXh0KCcnKVxuICAgICAgICAgICAgLnN0eWxlKCd3aGl0ZS1zcGFjZScsICdwcmUnKTtcblxuICAgICAgICB2YXIgaGFzTGluayA9IGJ1aWxkU1ZHVGV4dChfY29udGV4dC5ub2RlKCksIHN0cik7XG5cbiAgICAgICAgaWYoaGFzTGluaykge1xuICAgICAgICAgICAgLy8gYXQgbGVhc3QgaW4gQ2hyb21lLCBwb2ludGVyLWV2ZW50cyBkb2VzIG5vdCBzZWVtXG4gICAgICAgICAgICAvLyB0byBiZSBob25vcmVkIGluIGNoaWxkcmVuIG9mIDx0ZXh0PiBlbGVtZW50c1xuICAgICAgICAgICAgLy8gc28gaWYgd2UgaGF2ZSBhbiBhbmNob3IsIHdlIGhhdmUgdG8gbWFrZSB0aGVcbiAgICAgICAgICAgIC8vIHdob2xlIGVsZW1lbnQgcmVzcG9uZFxuICAgICAgICAgICAgX2NvbnRleHQuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgZXhwb3J0cy5wb3NpdGlvblRleHQoX2NvbnRleHQpO1xuXG4gICAgICAgIGlmKF9jYWxsYmFjaykgX2NhbGxiYWNrLmNhbGwoX2NvbnRleHQpO1xuICAgIH1cblxuICAgIGlmKHRleCkge1xuICAgICAgICAoKGdkICYmIGdkLl9wcm9taXNlcykgfHwgW10pLnB1c2gobmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgICAgICAgX2NvbnRleHQuc3R5bGUoJ2Rpc3BsYXknLCAnbm9uZScpO1xuICAgICAgICAgICAgdmFyIGZvbnRTaXplID0gcGFyc2VJbnQoX2NvbnRleHQubm9kZSgpLnN0eWxlLmZvbnRTaXplLCAxMCk7XG4gICAgICAgICAgICB2YXIgY29uZmlnID0ge2ZvbnRTaXplOiBmb250U2l6ZX07XG5cbiAgICAgICAgICAgIHRleFRvU1ZHKHRleFsyXSwgY29uZmlnLCBmdW5jdGlvbihfc3ZnRWwsIF9nbHlwaERlZnMsIF9zdmdCQm94KSB7XG4gICAgICAgICAgICAgICAgcGFyZW50LnNlbGVjdEFsbCgnc3ZnLicgKyBzdmdDbGFzcykucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgcGFyZW50LnNlbGVjdEFsbCgnZy4nICsgc3ZnQ2xhc3MgKyAnLWdyb3VwJykucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3U3ZnID0gX3N2Z0VsICYmIF9zdmdFbC5zZWxlY3QoJ3N2ZycpO1xuICAgICAgICAgICAgICAgIGlmKCFuZXdTdmcgfHwgIW5ld1N2Zy5ub2RlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2hvd1RleHQoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1hdGhqYXhHcm91cCA9IHBhcmVudC5hcHBlbmQoJ2cnKVxuICAgICAgICAgICAgICAgICAgICAuY2xhc3NlZChzdmdDbGFzcyArICctZ3JvdXAnLCB0cnVlKVxuICAgICAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICAncG9pbnRlci1ldmVudHMnOiAnbm9uZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAnZGF0YS11bmZvcm1hdHRlZCc6IHN0cixcbiAgICAgICAgICAgICAgICAgICAgICAgICdkYXRhLW1hdGgnOiAnWSdcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBtYXRoamF4R3JvdXAubm9kZSgpLmFwcGVuZENoaWxkKG5ld1N2Zy5ub2RlKCkpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3RpdGNoIHRoZSBnbHlwaCBkZWZzXG4gICAgICAgICAgICAgICAgaWYoX2dseXBoRGVmcyAmJiBfZ2x5cGhEZWZzLm5vZGUoKSkge1xuICAgICAgICAgICAgICAgICAgICBuZXdTdmcubm9kZSgpLmluc2VydEJlZm9yZShfZ2x5cGhEZWZzLm5vZGUoKS5jbG9uZU5vZGUodHJ1ZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1N2Zy5ub2RlKCkuZmlyc3RDaGlsZCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbmV3U3ZnLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiBzdmdDbGFzcyxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBfc3ZnQkJveC5oZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIHByZXNlcnZlQXNwZWN0UmF0aW86ICd4TWluWU1pbiBtZWV0J1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLnN0eWxlKHtvdmVyZmxvdzogJ3Zpc2libGUnLCAncG9pbnRlci1ldmVudHMnOiAnbm9uZSd9KTtcblxuICAgICAgICAgICAgICAgIHZhciBmaWxsID0gX2NvbnRleHQubm9kZSgpLnN0eWxlLmZpbGwgfHwgJ2JsYWNrJztcbiAgICAgICAgICAgICAgICB2YXIgZyA9IG5ld1N2Zy5zZWxlY3QoJ2cnKTtcbiAgICAgICAgICAgICAgICBnLmF0dHIoe2ZpbGw6IGZpbGwsIHN0cm9rZTogZmlsbH0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIG5ld1N2Z1cgPSBnZXRTaXplKGcsICd3aWR0aCcpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdTdmdIID0gZ2V0U2l6ZShnLCAnaGVpZ2h0Jyk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld1ggPSArX2NvbnRleHQuYXR0cigneCcpIC0gbmV3U3ZnVyAqXG4gICAgICAgICAgICAgICAgICAgIHtzdGFydDogMCwgbWlkZGxlOiAwLjUsIGVuZDogMX1bX2NvbnRleHQuYXR0cigndGV4dC1hbmNob3InKSB8fCAnc3RhcnQnXTtcbiAgICAgICAgICAgICAgICAvLyBmb250IGJhc2VsaW5lIGlzIGFib3V0IDEvNCBmb250U2l6ZSBiZWxvdyBjZW50ZXJsaW5lXG4gICAgICAgICAgICAgICAgdmFyIHRleHRIZWlnaHQgPSBmb250U2l6ZSB8fCBnZXRTaXplKF9jb250ZXh0LCAnaGVpZ2h0Jyk7XG4gICAgICAgICAgICAgICAgdmFyIGR5ID0gLXRleHRIZWlnaHQgLyA0O1xuXG4gICAgICAgICAgICAgICAgaWYoc3ZnQ2xhc3NbMF0gPT09ICd5Jykge1xuICAgICAgICAgICAgICAgICAgICBtYXRoamF4R3JvdXAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICdyb3RhdGUoJyArIFstOTAsICtfY29udGV4dC5hdHRyKCd4JyksICtfY29udGV4dC5hdHRyKCd5JyldICtcbiAgICAgICAgICAgICAgICAgICAgICAgICcpIHRyYW5zbGF0ZSgnICsgWy1uZXdTdmdXIC8gMiwgZHkgLSBuZXdTdmdIIC8gMl0gKyAnKSdcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIG5ld1N2Zy5hdHRyKHt4OiArX2NvbnRleHQuYXR0cigneCcpLCB5OiArX2NvbnRleHQuYXR0cigneScpfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHN2Z0NsYXNzWzBdID09PSAnbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3U3ZnLmF0dHIoe3g6IF9jb250ZXh0LmF0dHIoJ3gnKSwgeTogZHkgLSAobmV3U3ZnSCAvIDIpfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHN2Z0NsYXNzWzBdID09PSAnYScgJiYgc3ZnQ2xhc3MuaW5kZXhPZignYXRpdGxlJykgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3U3ZnLmF0dHIoe3g6IDAsIHk6IGR5fSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3U3ZnLmF0dHIoe3g6IG5ld1gsIHk6ICgrX2NvbnRleHQuYXR0cigneScpICsgZHkgLSBuZXdTdmdIIC8gMil9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihfY2FsbGJhY2spIF9jYWxsYmFjay5jYWxsKF9jb250ZXh0LCBtYXRoamF4R3JvdXApO1xuICAgICAgICAgICAgICAgIHJlc29sdmUobWF0aGpheEdyb3VwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KSk7XG4gICAgfSBlbHNlIHNob3dUZXh0KCk7XG5cbiAgICByZXR1cm4gX2NvbnRleHQ7XG59O1xuXG5cbi8vIE1hdGhKYXhcblxudmFyIExUX01BVENIID0gLyg8fCZsdDt8JiM2MDspL2c7XG52YXIgR1RfTUFUQ0ggPSAvKD58Jmd0O3wmIzYyOykvZztcblxuZnVuY3Rpb24gY2xlYW5Fc2NhcGVzRm9yVGV4KHMpIHtcbiAgICByZXR1cm4gcy5yZXBsYWNlKExUX01BVENILCAnXFxcXGx0ICcpXG4gICAgICAgIC5yZXBsYWNlKEdUX01BVENILCAnXFxcXGd0ICcpO1xufVxuXG5mdW5jdGlvbiB0ZXhUb1NWRyhfdGV4U3RyaW5nLCBfY29uZmlnLCBfY2FsbGJhY2spIHtcbiAgICB2YXIgb3JpZ2luYWxSZW5kZXJlcixcbiAgICAgICAgb3JpZ2luYWxDb25maWcsXG4gICAgICAgIG9yaWdpbmFsUHJvY2Vzc1NlY3Rpb25EZWxheSxcbiAgICAgICAgdG1wRGl2O1xuXG4gICAgTWF0aEpheC5IdWIuUXVldWUoXG4gICAgZnVuY3Rpb24oKSB7XG4gICAgICAgIG9yaWdpbmFsQ29uZmlnID0gTGliLmV4dGVuZERlZXBBbGwoe30sIE1hdGhKYXguSHViLmNvbmZpZyk7XG5cbiAgICAgICAgb3JpZ2luYWxQcm9jZXNzU2VjdGlvbkRlbGF5ID0gTWF0aEpheC5IdWIucHJvY2Vzc1NlY3Rpb25EZWxheTtcbiAgICAgICAgaWYoTWF0aEpheC5IdWIucHJvY2Vzc1NlY3Rpb25EZWxheSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyBNYXRoSmF4IDIuNStcbiAgICAgICAgICAgIE1hdGhKYXguSHViLnByb2Nlc3NTZWN0aW9uRGVsYXkgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIE1hdGhKYXguSHViLkNvbmZpZyh7XG4gICAgICAgICAgICBtZXNzYWdlU3R5bGU6ICdub25lJyxcbiAgICAgICAgICAgIHRleDJqYXg6IHtcbiAgICAgICAgICAgICAgICBpbmxpbmVNYXRoOiBbWyckJywgJyQnXSwgWydcXFxcKCcsICdcXFxcKSddXVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRpc3BsYXlBbGlnbjogJ2xlZnQnLFxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBHZXQgb3JpZ2luYWwgcmVuZGVyZXJcbiAgICAgICAgb3JpZ2luYWxSZW5kZXJlciA9IE1hdGhKYXguSHViLmNvbmZpZy5tZW51U2V0dGluZ3MucmVuZGVyZXI7XG4gICAgICAgIGlmKG9yaWdpbmFsUmVuZGVyZXIgIT09ICdTVkcnKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aEpheC5IdWIuc2V0UmVuZGVyZXIoJ1NWRycpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHJhbmRvbUlEID0gJ21hdGgtb3V0cHV0LScgKyBMaWIucmFuZHN0cih7fSwgNjQpO1xuICAgICAgICB0bXBEaXYgPSBkMy5zZWxlY3QoJ2JvZHknKS5hcHBlbmQoJ2RpdicpXG4gICAgICAgICAgICAuYXR0cih7aWQ6IHJhbmRvbUlEfSlcbiAgICAgICAgICAgIC5zdHlsZSh7dmlzaWJpbGl0eTogJ2hpZGRlbicsIHBvc2l0aW9uOiAnYWJzb2x1dGUnfSlcbiAgICAgICAgICAgIC5zdHlsZSh7J2ZvbnQtc2l6ZSc6IF9jb25maWcuZm9udFNpemUgKyAncHgnfSlcbiAgICAgICAgICAgIC50ZXh0KGNsZWFuRXNjYXBlc0ZvclRleChfdGV4U3RyaW5nKSk7XG5cbiAgICAgICAgcmV0dXJuIE1hdGhKYXguSHViLlR5cGVzZXQodG1wRGl2Lm5vZGUoKSk7XG4gICAgfSxcbiAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGdseXBoRGVmcyA9IGQzLnNlbGVjdCgnYm9keScpLnNlbGVjdCgnI01hdGhKYXhfU1ZHX2dseXBocycpO1xuXG4gICAgICAgIGlmKHRtcERpdi5zZWxlY3QoJy5NYXRoSmF4X1NWRycpLmVtcHR5KCkgfHwgIXRtcERpdi5zZWxlY3QoJ3N2ZycpLm5vZGUoKSkge1xuICAgICAgICAgICAgTGliLmxvZygnVGhlcmUgd2FzIGFuIGVycm9yIGluIHRoZSB0ZXggc3ludGF4LicsIF90ZXhTdHJpbmcpO1xuICAgICAgICAgICAgX2NhbGxiYWNrKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgc3ZnQkJveCA9IHRtcERpdi5zZWxlY3QoJ3N2ZycpLm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIF9jYWxsYmFjayh0bXBEaXYuc2VsZWN0KCcuTWF0aEpheF9TVkcnKSwgZ2x5cGhEZWZzLCBzdmdCQm94KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRtcERpdi5yZW1vdmUoKTtcblxuICAgICAgICBpZihvcmlnaW5hbFJlbmRlcmVyICE9PSAnU1ZHJykge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGhKYXguSHViLnNldFJlbmRlcmVyKG9yaWdpbmFsUmVuZGVyZXIpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYob3JpZ2luYWxQcm9jZXNzU2VjdGlvbkRlbGF5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIE1hdGhKYXguSHViLnByb2Nlc3NTZWN0aW9uRGVsYXkgPSBvcmlnaW5hbFByb2Nlc3NTZWN0aW9uRGVsYXk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIE1hdGhKYXguSHViLkNvbmZpZyhvcmlnaW5hbENvbmZpZyk7XG4gICAgfSk7XG59XG5cbnZhciBUQUdfU1RZTEVTID0ge1xuICAgIC8vIHdvdWxkIGxpa2UgdG8gdXNlIGJhc2VsaW5lLXNoaWZ0IGZvciBzdWIvc3VwIGJ1dCBGRiBkb2Vzbid0IHN1cHBvcnQgaXRcbiAgICAvLyBzbyB3ZSBuZWVkIHRvIHVzZSBkeSBhbG9uZyB3aXRoIHRoZSB1YmVyIGhhY2t5IHNoaWZ0LWJhY2stdG9cbiAgICAvLyBiYXNlbGluZSBiZWxvd1xuICAgIHN1cDogJ2ZvbnQtc2l6ZTo3MCUnLFxuICAgIHN1YjogJ2ZvbnQtc2l6ZTo3MCUnLFxuICAgIGI6ICdmb250LXdlaWdodDpib2xkJyxcbiAgICBpOiAnZm9udC1zdHlsZTppdGFsaWMnLFxuICAgIGE6ICdjdXJzb3I6cG9pbnRlcicsXG4gICAgc3BhbjogJycsXG4gICAgZW06ICdmb250LXN0eWxlOml0YWxpYztmb250LXdlaWdodDpib2xkJ1xufTtcblxuLy8gYmFzZWxpbmUgc2hpZnRzIGZvciBzdWIgYW5kIHN1cFxudmFyIFNISUZUX0RZID0ge1xuICAgIHN1YjogJzAuM2VtJyxcbiAgICBzdXA6ICctMC42ZW0nXG59O1xuLy8gcmVzZXQgYmFzZWxpbmUgYnkgYWRkaW5nIGEgdHNwYW4gKGVtcHR5IGV4Y2VwdCBmb3IgYSB6ZXJvLXdpZHRoIHNwYWNlKVxuLy8gd2l0aCBkeSBvZiAtNzAlICogU0hJRlRfRFkgKGJlY2F1c2UgZm9udC1zaXplPTcwJSlcbnZhciBSRVNFVF9EWSA9IHtcbiAgICBzdWI6ICctMC4yMWVtJyxcbiAgICBzdXA6ICcwLjQyZW0nXG59O1xudmFyIFpFUk9fV0lEVEhfU1BBQ0UgPSAnXFx1MjAwYic7XG5cbi8qXG4gKiBXaGl0ZWxpc3Qgb2YgcHJvdG9jb2xzIGluIHVzZXItc3VwcGxpZWQgdXJscy4gTW9zdGx5IHdlIHdhbnQgdG8gYXZvaWQgamF2YXNjcmlwdFxuICogYW5kIHJlbGF0ZWQgYXR0YWNrIHZlY3RvcnMuIFRoZSBlbXB0eSBpdGVtcyBhcmUgdGhlcmUgZm9yIElFLCB0aGF0IGluIHZhcmlvdXNcbiAqIHZlcnNpb25zIHRyZWF0cyByZWxhdGl2ZSBwYXRocyBhcyBoYXZpbmcgZGlmZmVyZW50IGZsYXZvcnMgb2Ygbm8gcHJvdG9jb2wsIHdoaWxlXG4gKiBvdGhlciBicm93c2VycyBoYXZlIHRoZXNlIGV4cGxpY2l0bHkgaW5oZXJpdCB0aGUgcHJvdG9jb2wgb2YgdGhlIHBhZ2UgdGhleSdyZSBpbi5cbiAqL1xudmFyIFBST1RPQ09MUyA9IFsnaHR0cDonLCAnaHR0cHM6JywgJ21haWx0bzonLCAnJywgdW5kZWZpbmVkLCAnOiddO1xuXG52YXIgTkVXTElORVMgPSAvKFxcclxcbj98XFxuKS9nO1xuXG52YXIgU1BMSVRfVEFHUyA9IC8oPFtePD5dKj4pLztcblxudmFyIE9ORV9UQUcgPSAvPChcXC8/KShbXiA+XSopKFxccysoLiopKT8+L2k7XG5cbnZhciBCUl9UQUcgPSAvPGJyKFxccysuKik/Pi9pO1xuXG4vKlxuICogc3R5bGUgYW5kIGhyZWY6IHB1bGwgdGhlbSBvdXQgb2YgZWl0aGVyIHNpbmdsZSBvciBkb3VibGUgcXVvdGVzLiBBbHNvXG4gKiAtIHRhcmdldDogKF9ibGFua3xfc2VsZnxfcGFyZW50fF90b3B8ZnJhbWVuYW1lKVxuICogICAgIG5vdGUgdGhhdCB5b3UgY2FuJ3QgdXNlIHRhcmdldCB0byBnZXQgYSBwb3B1cCBidXQgaWYgeW91IHVzZSBwb3B1cCxcbiAqICAgICBhIGBmcmFtZW5hbWVgIHdpbGwgYmUgcGFzc2VkIGFsb25nIGFzIHRoZSBuYW1lIG9mIHRoZSBwb3B1cCB3aW5kb3cuXG4gKiAgICAgcGVyIHRoZSBzcGVjLCBjYW5ub3QgY29udGFpbiB3aGl0ZXNwYWNlLlxuICogICAgIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IHdlIGRlZmF1bHQgdG8gJ19ibGFuaydcbiAqIC0gcG9wdXA6IGEgY3VzdG9tIG9uZSBmb3IgdXMgdG8gZW5hYmxlIHBvcHVwIChuZXcgd2luZG93KSBsaW5rcy4gU3RyaW5nXG4gKiAgICAgZm9yIHdpbmRvdy5vcGVuIC0+IHN0cldpbmRvd0ZlYXR1cmVzLCBsaWtlICdtZW51YmFyPXllcyx3aWR0aD01MDAsaGVpZ2h0PTU1MCdcbiAqICAgICBub3RlIHRoYXQgYXQgbGVhc3QgaW4gQ2hyb21lLCB5b3UgbmVlZCB0byBnaXZlIGF0IGxlYXN0IG9uZSBwcm9wZXJ0eVxuICogICAgIGluIHRoaXMgc3RyaW5nIG9yIHRoZSBwYWdlIHdpbGwgb3BlbiBpbiBhIG5ldyB0YWIgYW55d2F5LiBXZSBmb2xsb3cgdGhpc1xuICogICAgIGNvbnZlbnRpb24gYW5kIHdpbGwgbm90IG1ha2UgYSBwb3B1cCBpZiB0aGlzIHN0cmluZyBpcyBlbXB0eS5cbiAqICAgICBwZXIgdGhlIHNwZWMsIGNhbm5vdCBjb250YWluIHdoaXRlc3BhY2UuXG4gKlxuICogQmVjYXVzZSB3ZSBoYWNrIGluIG90aGVyIGF0dHJpYnV0ZXMgd2l0aCBzdHlsZSAoc3ViICYgc3VwKSwgZHJvcCBhbnkgdHJhaWxpbmdcbiAqIHNlbWljb2xvbiBpbiB1c2VyLXN1cHBsaWVkIHN0eWxlcyBzbyB3ZSBjYW4gY29uc2lzdGVudGx5IGFwcGVuZCB0aGUgdGFnLWRlcGVuZGVudCBzdHlsZVxuICpcbiAqIFRoZXNlIGFyZSBmb3IgdGFnIGF0dHJpYnV0ZXM7IENocm9tZSBhbnl3YXkgd2lsbCBjb252ZXJ0IGVudGl0aWVzIGluXG4gKiBhdHRyaWJ1dGUgdmFsdWVzLCBidXQgbm90IGluIGF0dHJpYnV0ZSBuYW1lc1xuICogeW91IGNhbiB0ZXN0IHRoaXMgYnkgZm9yIGV4YW1wbGU6XG4gKiA+IHAgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwJylcbiAqID4gcC5pbm5lckhUTUwgPSAnPHNwYW4gc3R5bCYjeDY1Oz1cImZvbnQtY29sb3I6ciYjeDY1O2Q7XCI+SGk8L3NwYW4+J1xuICogPiBwLmlubmVySFRNTFxuICogPC0gJzxzcGFuIHN0eWwmI3g2NTs9XCJmb250LWNvbG9yOnJlZDtcIj5IaTwvc3Bhbj4nXG4gKi9cbnZhciBTVFlMRU1BVENIID0gLyhefFtcXHNcIiddKXN0eWxlXFxzKj1cXHMqKFwiKFteXCJdKik7P1wifCcoW14nXSopOz8nKS9pO1xudmFyIEhSRUZNQVRDSCA9IC8oXnxbXFxzXCInXSlocmVmXFxzKj1cXHMqKFwiKFteXCJdKilcInwnKFteJ10qKScpL2k7XG52YXIgVEFSR0VUTUFUQ0ggPSAvKF58W1xcc1wiJ10pdGFyZ2V0XFxzKj1cXHMqKFwiKFteXCJcXHNdKilcInwnKFteJ1xcc10qKScpL2k7XG52YXIgUE9QVVBNQVRDSCA9IC8oXnxbXFxzXCInXSlwb3B1cFxccyo9XFxzKihcIihbXFx3PSxdKilcInwnKFtcXHc9LF0qKScpL2k7XG5cbi8vIGRlZGljYXRlZCBtYXRjaGVyIGZvciB0aGVzZSBxdW90ZWQgcmVnZXhlcywgdGhhdCBjYW4gcmV0dXJuIHRoZWlyIHJlc3VsdHNcbi8vIGluIHR3byBkaWZmZXJlbnQgcGxhY2VzXG5mdW5jdGlvbiBnZXRRdW90ZWRNYXRjaChfc3RyLCByZSkge1xuICAgIGlmKCFfc3RyKSByZXR1cm4gbnVsbDtcbiAgICB2YXIgbWF0Y2ggPSBfc3RyLm1hdGNoKHJlKTtcbiAgICB2YXIgcmVzdWx0ID0gbWF0Y2ggJiYgKG1hdGNoWzNdIHx8IG1hdGNoWzRdKTtcbiAgICByZXR1cm4gcmVzdWx0ICYmIGNvbnZlcnRFbnRpdGllcyhyZXN1bHQpO1xufVxuXG52YXIgQ09MT1JNQVRDSCA9IC8oXnw7KVxccypjb2xvcjovO1xuXG4vKipcbiAqIFN0cmlwIHN0cmluZyBvZiB0YWdzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IF9zdHIgOiBpbnB1dCBzdHJpbmdcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzIDpcbiAqIC0gbGVuIHtudW1iZXJ9IG1heCBsZW5ndGggb2Ygb3V0cHV0IHN0cmluZ1xuICogLSBhbGxvd2VkVGFncyB7YXJyYXl9IGxpc3Qgb2YgcHNldWRvLWh0bWwgdGFncyB0byBOT1Qgc3RyaXBcbiAqIEByZXR1cm4ge3N0cmluZ31cbiAqL1xuZXhwb3J0cy5wbGFpblRleHQgPSBmdW5jdGlvbihfc3RyLCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICB2YXIgbGVuID0gKG9wdHMubGVuICE9PSB1bmRlZmluZWQgJiYgb3B0cy5sZW4gIT09IC0xKSA/IG9wdHMubGVuIDogSW5maW5pdHk7XG4gICAgdmFyIGFsbG93ZWRUYWdzID0gb3B0cy5hbGxvd2VkVGFncyAhPT0gdW5kZWZpbmVkID8gb3B0cy5hbGxvd2VkVGFncyA6IFsnYnInXTtcblxuICAgIHZhciBlbGxpcHNpcyA9ICcuLi4nO1xuICAgIHZhciBlTGVuID0gZWxsaXBzaXMubGVuZ3RoO1xuXG4gICAgdmFyIG9sZFBhcnRzID0gX3N0ci5zcGxpdChTUExJVF9UQUdTKTtcbiAgICB2YXIgbmV3UGFydHMgPSBbXTtcbiAgICB2YXIgcHJldlRhZyA9ICcnO1xuICAgIHZhciBsID0gMDtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBvbGRQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcCA9IG9sZFBhcnRzW2ldO1xuICAgICAgICB2YXIgbWF0Y2ggPSBwLm1hdGNoKE9ORV9UQUcpO1xuICAgICAgICB2YXIgdGFnVHlwZSA9IG1hdGNoICYmIG1hdGNoWzJdLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgICAgaWYodGFnVHlwZSkge1xuICAgICAgICAgICAgLy8gTi5CLiB0YWdzIGRvIG5vdCBjb3VudCB0b3dhcmRzIHN0cmluZyBsZW5ndGhcbiAgICAgICAgICAgIGlmKGFsbG93ZWRUYWdzLmluZGV4T2YodGFnVHlwZSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgbmV3UGFydHMucHVzaChwKTtcbiAgICAgICAgICAgICAgICBwcmV2VGFnID0gdGFnVHlwZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBwTGVuID0gcC5sZW5ndGg7XG5cbiAgICAgICAgICAgIGlmKChsICsgcExlbikgPCBsZW4pIHtcbiAgICAgICAgICAgICAgICBuZXdQYXJ0cy5wdXNoKHApO1xuICAgICAgICAgICAgICAgIGwgKz0gcExlbjtcbiAgICAgICAgICAgIH0gZWxzZSBpZihsIDwgbGVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBMZW4yID0gbGVuIC0gbDtcblxuICAgICAgICAgICAgICAgIGlmKHByZXZUYWcgJiYgKHByZXZUYWcgIT09ICdicicgfHwgcExlbjIgPD0gZUxlbiB8fCBwTGVuIDw9IGVMZW4pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1BhcnRzLnBvcCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGxlbiA+IGVMZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3UGFydHMucHVzaChwLnN1YnN0cigwLCBwTGVuMiAtIGVMZW4pICsgZWxsaXBzaXMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1BhcnRzLnB1c2gocC5zdWJzdHIoMCwgcExlbjIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHByZXZUYWcgPSAnJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXdQYXJ0cy5qb2luKCcnKTtcbn07XG5cbi8qXG4gKiBOLkIuIEhUTUwgZW50aXRpZXMgYXJlIGxpc3RlZCB3aXRob3V0IHRoZSBsZWFkaW5nICcmJyBhbmQgdHJhaWxpbmcgJzsnXG4gKiBodHRwczovL3d3dy5mcmVlZm9ybWF0dGVyLmNvbS9odG1sLWVudGl0aWVzLmh0bWxcbiAqXG4gKiBGV0lXIGlmIHdlIHdhbnRlZCB0byBzdXBwb3J0IHRoZSBmdWxsIHNldCwgaXQgaGFzIDIyNjEgZW50cmllczpcbiAqIGh0dHBzOi8vd3d3LnczLm9yZy9UUi9odG1sNS9lbnRpdGllcy5qc29uXG4gKiB0aG91Z2ggSSBub3RpY2UgdGhhdCBzb21lIG9mIHRoZXNlIGFyZSBkdXBsaWNhdGVzIGFuZC9vciBhcmUgbWlzc2luZyBcIjtcIlxuICogZWc6IFwiJmFtcDtcIiwgXCImYW1wXCIsIFwiJkFNUDtcIiwgYW5kIFwiJkFNUFwiIGFsbCBtYXAgdG8gXCImXCJcbiAqIFdlIG5vIGxvbmdlciBuZWVkIHRvIGluY2x1ZGUgbnVtZXJpYyBlbnRpdGllcyBoZXJlLCB0aGVzZSBhcmUgbm93IGhhbmRsZWRcbiAqIGJ5IFN0cmluZy5mcm9tQ29kZVBvaW50L2Zyb21DaGFyQ29kZVxuICpcbiAqIEFueXdheSB0aGUgb25seSBvbmVzIHRoYXQgYXJlIHJlYWxseSBpbXBvcnRhbnQgdG8gYWxsb3cgYXJlIHRoZSBIVE1MIHNwZWNpYWxcbiAqIGNoYXJzIDwsID4sIGFuZCAmLCBiZWNhdXNlIHRoZXNlIG9uZXMgY2FuIHRyaWdnZXIgc3BlY2lhbCBwcm9jZXNzaW5nIGlmIG5vdFxuICogcmVwbGFjZWQgYnkgdGhlIGNvcnJlc3BvbmRpbmcgZW50aXR5LlxuICovXG52YXIgZW50aXR5VG9Vbmljb2RlID0ge1xuICAgIG11OiAnzrwnLFxuICAgIGFtcDogJyYnLFxuICAgIGx0OiAnPCcsXG4gICAgZ3Q6ICc+JyxcbiAgICBuYnNwOiAnwqAnLFxuICAgIHRpbWVzOiAnw5cnLFxuICAgIHBsdXNtbjogJ8KxJyxcbiAgICBkZWc6ICfCsCdcbn07XG5cbi8vIE5PVEU6IGluIGdlbmVyYWwgZW50aXRpZXMgY2FuIGNvbnRhaW4gdXBwZXJjYXNlIHRvbyAoc28gW2EtekEtWl0pIGJ1dCBhbGwgdGhlXG4vLyBvbmVzIHdlIHN1cHBvcnQgdXNlIG9ubHkgbG93ZXJjYXNlLiBJZiB3ZSBldmVyIGNoYW5nZSB0aGF0LCB1cGRhdGUgdGhlIHJlZ2V4LlxudmFyIEVOVElUWV9NQVRDSCA9IC8mKCNcXGQrfCN4W1xcZGEtZkEtRl0rfFthLXpdKyk7L2c7XG5mdW5jdGlvbiBjb252ZXJ0RW50aXRpZXMoX3N0cikge1xuICAgIHJldHVybiBfc3RyLnJlcGxhY2UoRU5USVRZX01BVENILCBmdW5jdGlvbihmdWxsTWF0Y2gsIGlubmVyTWF0Y2gpIHtcbiAgICAgICAgdmFyIG91dENoYXI7XG4gICAgICAgIGlmKGlubmVyTWF0Y2guY2hhckF0KDApID09PSAnIycpIHtcbiAgICAgICAgICAgIC8vIGNhbm5vdCB1c2UgU3RyaW5nLmZyb21Db2RlUG9pbnQgaW4gSUVcbiAgICAgICAgICAgIG91dENoYXIgPSBmcm9tQ29kZVBvaW50KFxuICAgICAgICAgICAgICAgIGlubmVyTWF0Y2guY2hhckF0KDEpID09PSAneCcgP1xuICAgICAgICAgICAgICAgICAgICBwYXJzZUludChpbm5lck1hdGNoLnN1YnN0cigyKSwgMTYpIDpcbiAgICAgICAgICAgICAgICAgICAgcGFyc2VJbnQoaW5uZXJNYXRjaC5zdWJzdHIoMSksIDEwKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIG91dENoYXIgPSBlbnRpdHlUb1VuaWNvZGVbaW5uZXJNYXRjaF07XG5cbiAgICAgICAgLy8gYXMgaW4gcmVndWxhciBIVE1MLCBpZiB3ZSBkaWRuJ3QgZGVjb2RlIHRoZSBlbnRpdHkganVzdFxuICAgICAgICAvLyBsZWF2ZSB0aGUgcmF3IHRleHQgaW4gcGxhY2UuXG4gICAgICAgIHJldHVybiBvdXRDaGFyIHx8IGZ1bGxNYXRjaDtcbiAgICB9KTtcbn1cbmV4cG9ydHMuY29udmVydEVudGl0aWVzID0gY29udmVydEVudGl0aWVzO1xuXG5mdW5jdGlvbiBmcm9tQ29kZVBvaW50KGNvZGUpIHtcbiAgICAvLyBEb24ndCBhbGxvdyBvdmVyZmxvdy4gSW4gQ2hyb21lIHRoaXMgdHVybnMgaW50byDvv70gYnV0IEkgZmVlbCBsaWtlIGl0J3NcbiAgICAvLyBtb3JlIHVzZWZ1bCB0byBqdXN0IG5vdCBjb252ZXJ0IGl0IGF0IGFsbC5cbiAgICBpZihjb2RlID4gMHgxMEZGRkYpIHJldHVybjtcbiAgICB2YXIgc3RyaW5nRnJvbUNvZGVQb2ludCA9IFN0cmluZy5mcm9tQ29kZVBvaW50O1xuICAgIGlmKHN0cmluZ0Zyb21Db2RlUG9pbnQpIHJldHVybiBzdHJpbmdGcm9tQ29kZVBvaW50KGNvZGUpO1xuXG4gICAgLy8gSUUgZG9lc24ndCBoYXZlIFN0cmluZy5mcm9tQ29kZVBvaW50XG4gICAgLy8gc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL1N0cmluZy9mcm9tQ29kZVBvaW50XG4gICAgdmFyIHN0cmluZ0Zyb21DaGFyQ29kZSA9IFN0cmluZy5mcm9tQ2hhckNvZGU7XG4gICAgaWYoY29kZSA8PSAweEZGRkYpIHJldHVybiBzdHJpbmdGcm9tQ2hhckNvZGUoY29kZSk7XG4gICAgcmV0dXJuIHN0cmluZ0Zyb21DaGFyQ29kZShcbiAgICAgICAgKGNvZGUgPj4gMTApICsgMHhEN0MwLFxuICAgICAgICAoY29kZSAlIDB4NDAwKSArIDB4REMwMFxuICAgICk7XG59XG5cbi8qXG4gKiBidWlsZFNWR1RleHQ6IGNvbnZlcnQgb3VyIHBzZXVkby1odG1sIGludG8gU1ZHIHRzcGFuIGVsZW1lbnRzLCBhbmQgYXR0YWNoIHRoZXNlXG4gKiB0byBjb250YWluZXJOb2RlXG4gKlxuICogQHBhcmFtIHtzdmcgdGV4dCBlbGVtZW50fSBjb250YWluZXJOb2RlOiB0aGUgPHRleHQ+IG5vZGUgdG8gaW5zZXJ0IHRoaXMgdGV4dCBpbnRvXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyOiB0aGUgcHNldWRvLWh0bWwgc3RyaW5nIHRvIGNvbnZlcnQgdG8gc3ZnXG4gKlxuICogQHJldHVybnMge2Jvb2x9OiBkb2VzIHRoZSByZXN1bHQgY29udGFpbiBhbnkgbGlua3M/IFdlIG5lZWQgdG8gaGFuZGxlIHRoZSB0ZXh0IGVsZW1lbnRcbiAqICAgc29tZXdoYXQgZGlmZmVyZW50bHkgaWYgaXQgZG9lcywgc28ganVzdCBrZWVwIHRyYWNrIG9mIHRoaXMgd2hlbiBpdCBoYXBwZW5zLlxuICovXG5mdW5jdGlvbiBidWlsZFNWR1RleHQoY29udGFpbmVyTm9kZSwgc3RyKSB7XG4gICAgLypcbiAgICAgKiBOb3JtYWxpemUgYmVoYXZpb3IgYmV0d2VlbiBJRSBhbmQgb3RoZXJzIHdydCBuZXdsaW5lcyBhbmQgd2hpdGVzcGFjZTpwcmVcbiAgICAgKiB0aGlzIGNvbWJpbmF0aW9uIG1ha2VzIElFIGJhcmYgaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzc0NlxuICAgICAqIENocm9tZSBhbmQgRkYgZGlzcGxheSBcXG4sIFxcciwgb3IgXFxyXFxuIGFzIGEgc3BhY2UgaW4gdGhpcyBtb2RlLlxuICAgICAqIEkgZmVlbCBsaWtlIGF0IHNvbWUgcG9pbnQgd2UgdHVybmVkIHRoZXNlIGludG8gPGJyPiBidXQgY3VycmVudGx5IHdlIGRvbid0IHNvXG4gICAgICogSSdtIGp1c3QgZ29pbmcgdG8gY2VtZW50IHdoYXQgd2UgZG8gbm93IGluIENocm9tZSBhbmQgRkZcbiAgICAgKi9cbiAgICBzdHIgPSBzdHIucmVwbGFjZShORVdMSU5FUywgJyAnKTtcblxuICAgIHZhciBoYXNMaW5rID0gZmFsc2U7XG5cbiAgICAvLyBhcyB3ZSdyZSBidWlsZGluZyB0aGUgdGV4dCwga2VlcCB0cmFjayBvZiB3aGF0IGVsZW1lbnRzIHdlJ3JlIG5lc3RlZCBpbnNpZGVcbiAgICAvLyBub2RlU3RhY2sgd2lsbCBiZSBhbiBhcnJheSBvZiB7bm9kZSwgdHlwZSwgc3R5bGUsIGhyZWYsIHRhcmdldCwgcG9wdXB9XG4gICAgLy8gd2hlcmUgb25seSB0eXBlOiAnYScgZ2V0cyB0aGUgbGFzdCAzIGFuZCBub2RlIGlzIG9ubHkgYWRkZWQgd2hlbiBpdCdzIGNyZWF0ZWRcbiAgICB2YXIgbm9kZVN0YWNrID0gW107XG4gICAgdmFyIGN1cnJlbnROb2RlO1xuICAgIHZhciBjdXJyZW50TGluZSA9IC0xO1xuXG4gICAgZnVuY3Rpb24gbmV3TGluZSgpIHtcbiAgICAgICAgY3VycmVudExpbmUrKztcblxuICAgICAgICB2YXIgbGluZU5vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoeG1sbnNOYW1lc3BhY2VzLnN2ZywgJ3RzcGFuJyk7XG4gICAgICAgIGQzLnNlbGVjdChsaW5lTm9kZSkuYXR0cih7XG4gICAgICAgICAgICBjbGFzczogJ2xpbmUnLFxuICAgICAgICAgICAgZHk6IChjdXJyZW50TGluZSAqIExJTkVfU1BBQ0lORykgKyAnZW0nXG4gICAgICAgIH0pO1xuICAgICAgICBjb250YWluZXJOb2RlLmFwcGVuZENoaWxkKGxpbmVOb2RlKTtcblxuICAgICAgICBjdXJyZW50Tm9kZSA9IGxpbmVOb2RlO1xuXG4gICAgICAgIHZhciBvbGROb2RlU3RhY2sgPSBub2RlU3RhY2s7XG4gICAgICAgIG5vZGVTdGFjayA9IFt7bm9kZTogbGluZU5vZGV9XTtcblxuICAgICAgICBpZihvbGROb2RlU3RhY2subGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMTsgaSA8IG9sZE5vZGVTdGFjay5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGVudGVyTm9kZShvbGROb2RlU3RhY2tbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW50ZXJOb2RlKG5vZGVTcGVjKSB7XG4gICAgICAgIHZhciB0eXBlID0gbm9kZVNwZWMudHlwZTtcbiAgICAgICAgdmFyIG5vZGVBdHRycyA9IHt9O1xuICAgICAgICB2YXIgbm9kZVR5cGU7XG5cbiAgICAgICAgaWYodHlwZSA9PT0gJ2EnKSB7XG4gICAgICAgICAgICBub2RlVHlwZSA9ICdhJztcbiAgICAgICAgICAgIHZhciB0YXJnZXQgPSBub2RlU3BlYy50YXJnZXQ7XG4gICAgICAgICAgICB2YXIgaHJlZiA9IG5vZGVTcGVjLmhyZWY7XG4gICAgICAgICAgICB2YXIgcG9wdXAgPSBub2RlU3BlYy5wb3B1cDtcbiAgICAgICAgICAgIGlmKGhyZWYpIHtcbiAgICAgICAgICAgICAgICBub2RlQXR0cnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICd4bGluazp4bGluazpzaG93JzogKHRhcmdldCA9PT0gJ19ibGFuaycgfHwgdGFyZ2V0LmNoYXJBdCgwKSAhPT0gJ18nKSA/ICduZXcnIDogJ3JlcGxhY2UnLFxuICAgICAgICAgICAgICAgICAgICB0YXJnZXQ6IHRhcmdldCxcbiAgICAgICAgICAgICAgICAgICAgJ3hsaW5rOnhsaW5rOmhyZWYnOiBocmVmXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZihwb3B1cCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBzZWN1cml0eTogaHJlZiBhbmQgdGFyZ2V0IGFyZSBub3QgaW5zZXJ0ZWQgYXMgY29kZSBidXRcbiAgICAgICAgICAgICAgICAgICAgLy8gYXMgYXR0cmlidXRlcy4gcG9wdXAgaXMsIGJ1dCBsaW1pdGVkIHRvIC9bQS1aYS16MC05Xz0sXS9cbiAgICAgICAgICAgICAgICAgICAgbm9kZUF0dHJzLm9uY2xpY2sgPSAnd2luZG93Lm9wZW4odGhpcy5ocmVmLmJhc2VWYWwsdGhpcy50YXJnZXQuYmFzZVZhbCxcIicgK1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXAgKyAnXCIpO3JldHVybiBmYWxzZTsnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIG5vZGVUeXBlID0gJ3RzcGFuJztcblxuICAgICAgICBpZihub2RlU3BlYy5zdHlsZSkgbm9kZUF0dHJzLnN0eWxlID0gbm9kZVNwZWMuc3R5bGU7XG5cbiAgICAgICAgdmFyIG5ld05vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoeG1sbnNOYW1lc3BhY2VzLnN2Zywgbm9kZVR5cGUpO1xuXG4gICAgICAgIGlmKHR5cGUgPT09ICdzdXAnIHx8IHR5cGUgPT09ICdzdWInKSB7XG4gICAgICAgICAgICBhZGRUZXh0Tm9kZShjdXJyZW50Tm9kZSwgWkVST19XSURUSF9TUEFDRSk7XG4gICAgICAgICAgICBjdXJyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcblxuICAgICAgICAgICAgdmFyIHJlc2V0dGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKHhtbG5zTmFtZXNwYWNlcy5zdmcsICd0c3BhbicpO1xuICAgICAgICAgICAgYWRkVGV4dE5vZGUocmVzZXR0ZXIsIFpFUk9fV0lEVEhfU1BBQ0UpO1xuICAgICAgICAgICAgZDMuc2VsZWN0KHJlc2V0dGVyKS5hdHRyKCdkeScsIFJFU0VUX0RZW3R5cGVdKTtcbiAgICAgICAgICAgIG5vZGVBdHRycy5keSA9IFNISUZUX0RZW3R5cGVdO1xuXG4gICAgICAgICAgICBjdXJyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgIGN1cnJlbnROb2RlLmFwcGVuZENoaWxkKHJlc2V0dGVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGN1cnJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgZDMuc2VsZWN0KG5ld05vZGUpLmF0dHIobm9kZUF0dHJzKTtcblxuICAgICAgICBjdXJyZW50Tm9kZSA9IG5vZGVTcGVjLm5vZGUgPSBuZXdOb2RlO1xuICAgICAgICBub2RlU3RhY2sucHVzaChub2RlU3BlYyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkVGV4dE5vZGUobm9kZSwgdGV4dCkge1xuICAgICAgICBub2RlLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRleHQpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleGl0Tm9kZSh0eXBlKSB7XG4gICAgICAgIC8vIEEgYmFyZSBjbG9zaW5nIHRhZyBjYW4ndCBjbG9zZSB0aGUgcm9vdCBub2RlLiBJZiB3ZSBlbmNvdW50ZXIgdGhpcyBpdFxuICAgICAgICAvLyBtZWFucyB0aGVyZSdzIGFuIGV4dHJhIGNsb3NpbmcgdGFnIHRoYXQgY2FuIGp1c3QgYmUgaWdub3JlZDpcbiAgICAgICAgaWYobm9kZVN0YWNrLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgTGliLmxvZygnSWdub3JpbmcgdW5leHBlY3RlZCBlbmQgdGFnIDwvJyArIHR5cGUgKyAnPi4nLCBzdHIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlubmVyTm9kZSA9IG5vZGVTdGFjay5wb3AoKTtcblxuICAgICAgICBpZih0eXBlICE9PSBpbm5lck5vZGUudHlwZSkge1xuICAgICAgICAgICAgTGliLmxvZygnU3RhcnQgdGFnIDwnICsgaW5uZXJOb2RlLnR5cGUgKyAnPiBkb2VzbnQgbWF0Y2ggZW5kIHRhZyA8JyArXG4gICAgICAgICAgICAgICAgdHlwZSArICc+LiBQcmV0ZW5kaW5nIGl0IGRpZCBtYXRjaC4nLCBzdHIpO1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnROb2RlID0gbm9kZVN0YWNrW25vZGVTdGFjay5sZW5ndGggLSAxXS5ub2RlO1xuICAgIH1cblxuICAgIHZhciBoYXNMaW5lcyA9IEJSX1RBRy50ZXN0KHN0cik7XG5cbiAgICBpZihoYXNMaW5lcykgbmV3TGluZSgpO1xuICAgIGVsc2Uge1xuICAgICAgICBjdXJyZW50Tm9kZSA9IGNvbnRhaW5lck5vZGU7XG4gICAgICAgIG5vZGVTdGFjayA9IFt7bm9kZTogY29udGFpbmVyTm9kZX1dO1xuICAgIH1cblxuICAgIHZhciBwYXJ0cyA9IHN0ci5zcGxpdChTUExJVF9UQUdTKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHBhcnRpID0gcGFydHNbaV07XG4gICAgICAgIHZhciBtYXRjaCA9IHBhcnRpLm1hdGNoKE9ORV9UQUcpO1xuICAgICAgICB2YXIgdGFnVHlwZSA9IG1hdGNoICYmIG1hdGNoWzJdLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHZhciB0YWdTdHlsZSA9IFRBR19TVFlMRVNbdGFnVHlwZV07XG5cbiAgICAgICAgaWYodGFnVHlwZSA9PT0gJ2JyJykge1xuICAgICAgICAgICAgbmV3TGluZSgpO1xuICAgICAgICB9IGVsc2UgaWYodGFnU3R5bGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgYWRkVGV4dE5vZGUoY3VycmVudE5vZGUsIGNvbnZlcnRFbnRpdGllcyhwYXJ0aSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdGFnIC0gb3BlbiBvciBjbG9zZVxuICAgICAgICAgICAgaWYobWF0Y2hbMV0pIHtcbiAgICAgICAgICAgICAgICBleGl0Tm9kZSh0YWdUeXBlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4dHJhID0gbWF0Y2hbNF07XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZVNwZWMgPSB7dHlwZTogdGFnVHlwZX07XG5cbiAgICAgICAgICAgICAgICAvLyBub3cgYWRkIHN0eWxlLCBmcm9tIGJvdGggdGhlIHRhZyBuYW1lIGFuZCBhbnkgZXh0cmEgY3NzXG4gICAgICAgICAgICAgICAgLy8gTW9zdCBvZiB0aGUgc3ZnIGNzcyB0aGF0IHVzZXJzIHdpbGwgY2FyZSBhYm91dCBpcyBqdXN0IGxpa2UgaHRtbCxcbiAgICAgICAgICAgICAgICAvLyBidXQgZm9udCBjb2xvciBpcyBkaWZmZXJlbnQgKHVzZXMgZmlsbCkuIExldCBvdXIgdXNlcnMgaWdub3JlIHRoaXMuXG4gICAgICAgICAgICAgICAgdmFyIGNzcyA9IGdldFF1b3RlZE1hdGNoKGV4dHJhLCBTVFlMRU1BVENIKTtcbiAgICAgICAgICAgICAgICBpZihjc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgY3NzID0gY3NzLnJlcGxhY2UoQ09MT1JNQVRDSCwgJyQxIGZpbGw6Jyk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHRhZ1N0eWxlKSBjc3MgKz0gJzsnICsgdGFnU3R5bGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHRhZ1N0eWxlKSBjc3MgPSB0YWdTdHlsZTtcblxuICAgICAgICAgICAgICAgIGlmKGNzcykgbm9kZVNwZWMuc3R5bGUgPSBjc3M7XG5cbiAgICAgICAgICAgICAgICBpZih0YWdUeXBlID09PSAnYScpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzTGluayA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGhyZWYgPSBnZXRRdW90ZWRNYXRjaChleHRyYSwgSFJFRk1BVENIKTtcblxuICAgICAgICAgICAgICAgICAgICBpZihocmVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayBzYWZlIHByb3RvY29sc1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGR1bW15QW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZHVtbXlBbmNob3IuaHJlZiA9IGhyZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihQUk9UT0NPTFMuaW5kZXhPZihkdW1teUFuY2hvci5wcm90b2NvbCkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRGVjb2RlIGhyZWYgdG8gYWxsb3cgYm90aCBhbHJlYWR5IGVuY29kZWQgYW5kIG5vdCBlbmNvZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVVJJcy4gV2l0aG91dCBkZWNvZGluZyBwcmlvciBlbmNvZGluZywgYW4gYWxyZWFkeSBlbmNvZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVVJJIHdvdWxkIGJlIGVuY29kZWQgdHdpY2UgcHJvZHVjaW5nIGEgc2VtYW50aWNhbGx5IGRpZmZlcmVudCBVUkkuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVNwZWMuaHJlZiA9IGVuY29kZVVSSShkZWNvZGVVUkkoaHJlZikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVTcGVjLnRhcmdldCA9IGdldFF1b3RlZE1hdGNoKGV4dHJhLCBUQVJHRVRNQVRDSCkgfHwgJ19ibGFuayc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVNwZWMucG9wdXAgPSBnZXRRdW90ZWRNYXRjaChleHRyYSwgUE9QVVBNQVRDSCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBlbnRlck5vZGUobm9kZVNwZWMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGhhc0xpbms7XG59XG5cbmV4cG9ydHMubGluZUNvdW50ID0gZnVuY3Rpb24gbGluZUNvdW50KHMpIHtcbiAgICByZXR1cm4gcy5zZWxlY3RBbGwoJ3RzcGFuLmxpbmUnKS5zaXplKCkgfHwgMTtcbn07XG5cbmV4cG9ydHMucG9zaXRpb25UZXh0ID0gZnVuY3Rpb24gcG9zaXRpb25UZXh0KHMsIHgsIHkpIHtcbiAgICByZXR1cm4gcy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdGV4dCA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICBmdW5jdGlvbiBzZXRPckdldChhdHRyLCB2YWwpIHtcbiAgICAgICAgICAgIGlmKHZhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdmFsID0gdGV4dC5hdHRyKGF0dHIpO1xuICAgICAgICAgICAgICAgIGlmKHZhbCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB0ZXh0LmF0dHIoYXR0ciwgMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhbCA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHRleHQuYXR0cihhdHRyLCB2YWwpO1xuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0aGlzWCA9IHNldE9yR2V0KCd4JywgeCk7XG4gICAgICAgIHZhciB0aGlzWSA9IHNldE9yR2V0KCd5JywgeSk7XG5cbiAgICAgICAgaWYodGhpcy5ub2RlTmFtZSA9PT0gJ3RleHQnKSB7XG4gICAgICAgICAgICB0ZXh0LnNlbGVjdEFsbCgndHNwYW4ubGluZScpLmF0dHIoe3g6IHRoaXNYLCB5OiB0aGlzWX0pO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBhbGlnbkhUTUxXaXRoKF9iYXNlLCBjb250YWluZXIsIG9wdGlvbnMpIHtcbiAgICB2YXIgYWxpZ25IID0gb3B0aW9ucy5ob3Jpem9udGFsQWxpZ247XG4gICAgdmFyIGFsaWduViA9IG9wdGlvbnMudmVydGljYWxBbGlnbiB8fCAndG9wJztcbiAgICB2YXIgYlJlY3QgPSBfYmFzZS5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgdmFyIGNSZWN0ID0gY29udGFpbmVyLm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgdGhpc1JlY3Q7XG4gICAgdmFyIGdldFRvcDtcbiAgICB2YXIgZ2V0TGVmdDtcblxuICAgIGlmKGFsaWduViA9PT0gJ2JvdHRvbScpIHtcbiAgICAgICAgZ2V0VG9wID0gZnVuY3Rpb24oKSB7IHJldHVybiBiUmVjdC5ib3R0b20gLSB0aGlzUmVjdC5oZWlnaHQ7IH07XG4gICAgfSBlbHNlIGlmKGFsaWduViA9PT0gJ21pZGRsZScpIHtcbiAgICAgICAgZ2V0VG9wID0gZnVuY3Rpb24oKSB7IHJldHVybiBiUmVjdC50b3AgKyAoYlJlY3QuaGVpZ2h0IC0gdGhpc1JlY3QuaGVpZ2h0KSAvIDI7IH07XG4gICAgfSBlbHNlIHsgLy8gZGVmYXVsdDogdG9wXG4gICAgICAgIGdldFRvcCA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gYlJlY3QudG9wOyB9O1xuICAgIH1cblxuICAgIGlmKGFsaWduSCA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICBnZXRMZWZ0ID0gZnVuY3Rpb24oKSB7IHJldHVybiBiUmVjdC5yaWdodCAtIHRoaXNSZWN0LndpZHRoOyB9O1xuICAgIH0gZWxzZSBpZihhbGlnbkggPT09ICdjZW50ZXInKSB7XG4gICAgICAgIGdldExlZnQgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGJSZWN0LmxlZnQgKyAoYlJlY3Qud2lkdGggLSB0aGlzUmVjdC53aWR0aCkgLyAyOyB9O1xuICAgIH0gZWxzZSB7IC8vIGRlZmF1bHQ6IGxlZnRcbiAgICAgICAgZ2V0TGVmdCA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gYlJlY3QubGVmdDsgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXNSZWN0ID0gdGhpcy5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHRoaXMuc3R5bGUoe1xuICAgICAgICAgICAgdG9wOiAoZ2V0VG9wKCkgLSBjUmVjdC50b3ApICsgJ3B4JyxcbiAgICAgICAgICAgIGxlZnQ6IChnZXRMZWZ0KCkgLSBjUmVjdC5sZWZ0KSArICdweCcsXG4gICAgICAgICAgICAnei1pbmRleCc6IDEwMDBcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG59XG5cbi8qXG4gKiBFZGl0YWJsZSB0aXRsZVxuICogQHBhcmFtIHtkMy5zZWxlY3Rpb259IGNvbnRleHQ6IHRoZSBlbGVtZW50IGJlaW5nIGVkaXRlZC4gTm9ybWFsbHkgdGV4dCxcbiAqICAgYnV0IGlmIGl0IGlzbid0LCB5b3Ugc2hvdWxkIHByb3ZpZGUgdGhlIHN0eWxpbmcgb3B0aW9uc1xuICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnM6XG4gKiAgIEBwYXJhbSB7ZGl2fSBvcHRpb25zLmdkOiBncmFwaERpdlxuICogICBAcGFyYW0ge2QzLnNlbGVjdGlvbn0gb3B0aW9ucy5kZWxlZ2F0ZTogaXRlbSB0byBiaW5kIGV2ZW50cyB0byBpZiBub3QgdGhpc1xuICogICBAcGFyYW0ge2Jvb2xlYW59IG9wdGlvbnMuaW1tZWRpYXRlOiBzdGFydCBlZGl0aW5nIG5vdyAodHJ1ZSkgb3Igb24gY2xpY2sgKGZhbHNlLCBkZWZhdWx0KVxuICogICBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5maWxsOiBmb250IGNvbG9yIGlmIG5vdCBhcyBzaG93blxuICogICBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5iYWNrZ3JvdW5kOiBiYWNrZ3JvdW5kIGNvbG9yIGlmIG5vdCBhcyBzaG93blxuICogICBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy50ZXh0OiBpbml0aWFsIHRleHQsIGlmIG5vdCBhcyBzaG93blxuICogICBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5ob3Jpem9udGFsQWxpZ246IGFsaWdubWVudCBvZiB0aGUgZWRpdCBib3ggd3J0LiB0aGUgYm91bmQgZWxlbWVudFxuICogICBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy52ZXJ0aWNhbEFsaWduOiBhbGlnbm1lbnQgb2YgdGhlIGVkaXQgYm94IHdydC4gdGhlIGJvdW5kIGVsZW1lbnRcbiAqL1xuXG5leHBvcnRzLm1ha2VFZGl0YWJsZSA9IGZ1bmN0aW9uKGNvbnRleHQsIG9wdGlvbnMpIHtcbiAgICB2YXIgZ2QgPSBvcHRpb25zLmdkO1xuICAgIHZhciBfZGVsZWdhdGUgPSBvcHRpb25zLmRlbGVnYXRlO1xuICAgIHZhciBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoKCdlZGl0JywgJ2lucHV0JywgJ2NhbmNlbCcpO1xuICAgIHZhciBoYW5kbGVyRWxlbWVudCA9IF9kZWxlZ2F0ZSB8fCBjb250ZXh0O1xuXG4gICAgY29udGV4dC5zdHlsZSh7J3BvaW50ZXItZXZlbnRzJzogX2RlbGVnYXRlID8gJ25vbmUnIDogJ2FsbCd9KTtcblxuICAgIGlmKGNvbnRleHQuc2l6ZSgpICE9PSAxKSB0aHJvdyBuZXcgRXJyb3IoJ2JvbycpO1xuXG4gICAgZnVuY3Rpb24gaGFuZGxlQ2xpY2soKSB7XG4gICAgICAgIGFwcGVuZEVkaXRhYmxlKCk7XG4gICAgICAgIGNvbnRleHQuc3R5bGUoe29wYWNpdHk6IDB9KTtcbiAgICAgICAgLy8gYWxzbyBoaWRlIGFueSBtYXRoamF4IHN2Z1xuICAgICAgICB2YXIgc3ZnQ2xhc3MgPSBoYW5kbGVyRWxlbWVudC5hdHRyKCdjbGFzcycpO1xuICAgICAgICB2YXIgbWF0aGpheENsYXNzO1xuICAgICAgICBpZihzdmdDbGFzcykgbWF0aGpheENsYXNzID0gJy4nICsgc3ZnQ2xhc3Muc3BsaXQoJyAnKVswXSArICctbWF0aC1ncm91cCc7XG4gICAgICAgIGVsc2UgbWF0aGpheENsYXNzID0gJ1tjbGFzcyo9LW1hdGgtZ3JvdXBdJztcbiAgICAgICAgaWYobWF0aGpheENsYXNzKSB7XG4gICAgICAgICAgICBkMy5zZWxlY3QoY29udGV4dC5ub2RlKCkucGFyZW50Tm9kZSkuc2VsZWN0KG1hdGhqYXhDbGFzcykuc3R5bGUoe29wYWNpdHk6IDB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNlbGVjdEVsZW1lbnRDb250ZW50cyhfZWwpIHtcbiAgICAgICAgdmFyIGVsID0gX2VsLm5vZGUoKTtcbiAgICAgICAgdmFyIHJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICAgICAgcmFuZ2Uuc2VsZWN0Tm9kZUNvbnRlbnRzKGVsKTtcbiAgICAgICAgdmFyIHNlbCA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgc2VsLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgICAgICBzZWwuYWRkUmFuZ2UocmFuZ2UpO1xuICAgICAgICBlbC5mb2N1cygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFwcGVuZEVkaXRhYmxlKCkge1xuICAgICAgICB2YXIgcGxvdERpdiA9IGQzLnNlbGVjdChnZCk7XG4gICAgICAgIHZhciBjb250YWluZXIgPSBwbG90RGl2LnNlbGVjdCgnLnN2Zy1jb250YWluZXInKTtcbiAgICAgICAgdmFyIGRpdiA9IGNvbnRhaW5lci5hcHBlbmQoJ2RpdicpO1xuICAgICAgICB2YXIgY1N0eWxlID0gY29udGV4dC5ub2RlKCkuc3R5bGU7XG4gICAgICAgIHZhciBmb250U2l6ZSA9IHBhcnNlRmxvYXQoY1N0eWxlLmZvbnRTaXplIHx8IDEyKTtcblxuICAgICAgICB2YXIgaW5pdGlhbFRleHQgPSBvcHRpb25zLnRleHQ7XG4gICAgICAgIGlmKGluaXRpYWxUZXh0ID09PSB1bmRlZmluZWQpIGluaXRpYWxUZXh0ID0gY29udGV4dC5hdHRyKCdkYXRhLXVuZm9ybWF0dGVkJyk7XG5cbiAgICAgICAgZGl2LmNsYXNzZWQoJ3BsdWdpbi1lZGl0YWJsZSBlZGl0YWJsZScsIHRydWUpXG4gICAgICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgICAgICAgICAgICAgICdmb250LWZhbWlseSc6IGNTdHlsZS5mb250RmFtaWx5IHx8ICdBcmlhbCcsXG4gICAgICAgICAgICAgICAgJ2ZvbnQtc2l6ZSc6IGZvbnRTaXplLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBvcHRpb25zLmZpbGwgfHwgY1N0eWxlLmZpbGwgfHwgJ2JsYWNrJyxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICAgICAgICAgICdiYWNrZ3JvdW5kLWNvbG9yJzogb3B0aW9ucy5iYWNrZ3JvdW5kIHx8ICd0cmFuc3BhcmVudCcsXG4gICAgICAgICAgICAgICAgb3V0bGluZTogJyNmZmZmZmYzMyAxcHggc29saWQnLFxuICAgICAgICAgICAgICAgIG1hcmdpbjogWy1mb250U2l6ZSAvIDggKyAxLCAwLCAwLCAtMV0uam9pbigncHggJykgKyAncHgnLFxuICAgICAgICAgICAgICAgIHBhZGRpbmc6ICcwJyxcbiAgICAgICAgICAgICAgICAnYm94LXNpemluZyc6ICdib3JkZXItYm94J1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hdHRyKHtjb250ZW50ZWRpdGFibGU6IHRydWV9KVxuICAgICAgICAgICAgLnRleHQoaW5pdGlhbFRleHQpXG4gICAgICAgICAgICAuY2FsbChhbGlnbkhUTUxXaXRoKGNvbnRleHQsIGNvbnRhaW5lciwgb3B0aW9ucykpXG4gICAgICAgICAgICAub24oJ2JsdXInLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBnZC5fZWRpdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGNvbnRleHQudGV4dCh0aGlzLnRleHRDb250ZW50KVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoe29wYWNpdHk6IDF9KTtcbiAgICAgICAgICAgICAgICB2YXIgc3ZnQ2xhc3MgPSBkMy5zZWxlY3QodGhpcykuYXR0cignY2xhc3MnKTtcbiAgICAgICAgICAgICAgICB2YXIgbWF0aGpheENsYXNzO1xuICAgICAgICAgICAgICAgIGlmKHN2Z0NsYXNzKSBtYXRoamF4Q2xhc3MgPSAnLicgKyBzdmdDbGFzcy5zcGxpdCgnICcpWzBdICsgJy1tYXRoLWdyb3VwJztcbiAgICAgICAgICAgICAgICBlbHNlIG1hdGhqYXhDbGFzcyA9ICdbY2xhc3MqPS1tYXRoLWdyb3VwXSc7XG4gICAgICAgICAgICAgICAgaWYobWF0aGpheENsYXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIGQzLnNlbGVjdChjb250ZXh0Lm5vZGUoKS5wYXJlbnROb2RlKS5zZWxlY3QobWF0aGpheENsYXNzKS5zdHlsZSh7b3BhY2l0eTogMH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IHRoaXMudGV4dENvbnRlbnQ7XG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnRyYW5zaXRpb24oKS5kdXJhdGlvbigwKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QoZG9jdW1lbnQpLm9uKCdtb3VzZXVwJywgbnVsbCk7XG4gICAgICAgICAgICAgICAgZGlzcGF0Y2guZWRpdC5jYWxsKGNvbnRleHQsIHRleHQpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5vbignZm9jdXMnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB2YXIgZWRpdERpdiA9IHRoaXM7XG4gICAgICAgICAgICAgICAgZ2QuX2VkaXRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGQzLnNlbGVjdChkb2N1bWVudCkub24oJ21vdXNldXAnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoZDMuZXZlbnQudGFyZ2V0ID09PSBlZGl0RGl2KSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGlmKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGRpdi5ub2RlKCkpIGRpdi5ub2RlKCkuYmx1cigpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5vbigna2V5dXAnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBpZihkMy5ldmVudC53aGljaCA9PT0gMjcpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2QuX2VkaXRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC5zdHlsZSh7b3BhY2l0eTogMX0pO1xuICAgICAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5zdHlsZSh7b3BhY2l0eTogMH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAub24oJ2JsdXInLCBmdW5jdGlvbigpIHsgcmV0dXJuIGZhbHNlOyB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRyYW5zaXRpb24oKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgZGlzcGF0Y2guY2FuY2VsLmNhbGwoY29udGV4dCwgdGhpcy50ZXh0Q29udGVudCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGlzcGF0Y2guaW5wdXQuY2FsbChjb250ZXh0LCB0aGlzLnRleHRDb250ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmNhbGwoYWxpZ25IVE1MV2l0aChjb250ZXh0LCBjb250YWluZXIsIG9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdrZXlkb3duJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgaWYoZDMuZXZlbnQud2hpY2ggPT09IDEzKSB0aGlzLmJsdXIoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2FsbChzZWxlY3RFbGVtZW50Q29udGVudHMpO1xuICAgIH1cblxuICAgIGlmKG9wdGlvbnMuaW1tZWRpYXRlKSBoYW5kbGVDbGljaygpO1xuICAgIGVsc2UgaGFuZGxlckVsZW1lbnQub24oJ2NsaWNrJywgaGFuZGxlQ2xpY2spO1xuXG4gICAgcmV0dXJuIGQzLnJlYmluZChjb250ZXh0LCBkaXNwYXRjaCwgJ29uJyk7XG59O1xuXG59LHtcIi4uL2NvbnN0YW50cy9hbGlnbm1lbnRcIjo2ODgsXCIuLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlc1wiOjY5NixcIi4uL2xpYlwiOjcxOSxcImQzXCI6MTYzfV0sNzQ0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHRpbWVyQ2FjaGUgPSB7fTtcblxuLyoqXG4gKiBUaHJvdHRsZSBhIGNhbGxiYWNrLiBgY2FsbGJhY2tgIGV4ZWN1dGVzIHN5bmNocm9ub3VzbHkgb25seSBpZlxuICogbW9yZSB0aGFuIGBtaW5JbnRlcnZhbGAgbWlsbGlzZWNvbmRzIGhhdmUgYWxyZWFkeSBlbGFwc2VkIHNpbmNlIHRoZSBsYXRlc3RcbiAqIGNhbGwgKGlmIGFueSkuIE90aGVyd2lzZSB3ZSB3YWl0IHVudGlsIGBtaW5JbnRlcnZhbGAgaXMgb3ZlciBhbmQgZXhlY3V0ZSB0aGVcbiAqIGxhc3QgY2FsbGJhY2sgcmVjZWl2ZWQgd2hpbGUgd2FpdGluZy5cbiAqIFNvIHRoZSBmaXJzdCBhbmQgbGFzdCBldmVudHMgaW4gYSB0cmFpbiBhcmUgYWx3YXlzIGV4ZWN1dGVkIChldmVudHVhbGx5KVxuICogYnV0IHNvbWUgb2YgdGhlIGV2ZW50cyBpbiB0aGUgbWlkZGxlIGNhbiBiZSBkcm9wcGVkLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZDogYW4gaWRlbnRpZmllciB0byBtYXJrIGV2ZW50cyB0byB0aHJvdHRsZSB0b2dldGhlclxuICogQHBhcmFtIHtudW1iZXJ9IG1pbkludGVydmFsOiBtaW5pbXVtIHRpbWUsIGluIG1pbGxpc2Vjb25kcywgYmV0d2VlblxuICogICBpbnZvY2F0aW9ucyBvZiBgY2FsbGJhY2tgXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjazogdGhlIGZ1bmN0aW9uIHRvIHRocm90dGxlLiBgY2FsbGJhY2tgIGl0c2VsZlxuICogICBzaG91bGQgYmUgYSBwdXJlbHkgc3luY2hyb25vdXMgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydHMudGhyb3R0bGUgPSBmdW5jdGlvbiB0aHJvdHRsZShpZCwgbWluSW50ZXJ2YWwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIGNhY2hlID0gdGltZXJDYWNoZVtpZF07XG4gICAgdmFyIG5vdyA9IERhdGUubm93KCk7XG5cbiAgICBpZighY2FjaGUpIHtcbiAgICAgICAgLypcbiAgICAgICAgICogVGhyb3cgb3V0IG9sZCBpdGVtcyBiZWZvcmUgbWFraW5nIGEgbmV3IG9uZSwgdG8gcHJldmVudCB0aGUgY2FjaGVcbiAgICAgICAgICogZ2V0dGluZyBvdmVyZ3Jvd24sIGZvciBleGFtcGxlIGZyb20gb2xkIHBsb3RzIHRoYXQgaGF2ZSBiZWVuIHJlcGxhY2VkLlxuICAgICAgICAgKiAxIG1pbnV0ZSBhZ2UgaXMgYXJiaXRyYXJ5LlxuICAgICAgICAgKi9cbiAgICAgICAgZm9yKHZhciBpZGkgaW4gdGltZXJDYWNoZSkge1xuICAgICAgICAgICAgaWYodGltZXJDYWNoZVtpZGldLnRzIDwgbm93IC0gNjAwMDApIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGltZXJDYWNoZVtpZGldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhY2hlID0gdGltZXJDYWNoZVtpZF0gPSB7dHM6IDAsIHRpbWVyOiBudWxsfTtcbiAgICB9XG5cbiAgICBfY2xlYXJUaW1lb3V0KGNhY2hlKTtcblxuICAgIGZ1bmN0aW9uIGV4ZWMoKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIGNhY2hlLnRzID0gRGF0ZS5ub3coKTtcbiAgICAgICAgaWYoY2FjaGUub25Eb25lKSB7XG4gICAgICAgICAgICBjYWNoZS5vbkRvbmUoKTtcbiAgICAgICAgICAgIGNhY2hlLm9uRG9uZSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihub3cgPiBjYWNoZS50cyArIG1pbkludGVydmFsKSB7XG4gICAgICAgIGV4ZWMoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNhY2hlLnRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgZXhlYygpO1xuICAgICAgICBjYWNoZS50aW1lciA9IG51bGw7XG4gICAgfSwgbWluSW50ZXJ2YWwpO1xufTtcblxuZXhwb3J0cy5kb25lID0gZnVuY3Rpb24oaWQpIHtcbiAgICB2YXIgY2FjaGUgPSB0aW1lckNhY2hlW2lkXTtcbiAgICBpZighY2FjaGUgfHwgIWNhY2hlLnRpbWVyKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgICB2YXIgcHJldmlvdXNPbkRvbmUgPSBjYWNoZS5vbkRvbmU7XG4gICAgICAgIGNhY2hlLm9uRG9uZSA9IGZ1bmN0aW9uIG9uRG9uZSgpIHtcbiAgICAgICAgICAgIGlmKHByZXZpb3VzT25Eb25lKSBwcmV2aW91c09uRG9uZSgpO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgY2FjaGUub25Eb25lID0gbnVsbDtcbiAgICAgICAgfTtcbiAgICB9KTtcbn07XG5cbi8qKlxuICogQ2xlYXIgdGhlIHRocm90dGxlIGNhY2hlIGZvciBvbmUgb3IgYWxsIHRpbWVyc1xuICogQHBhcmFtIHtvcHRpb25hbCBzdHJpbmd9IGlkOlxuICogICBpZiBwcm92aWRlZCwgY2xlYXIganVzdCB0aGlzIHRpbWVyXG4gKiAgIGlmIG9taXR0ZWQsIGNsZWFyIGFsbCB0aW1lcnMgKG1haW5seSB1c2VmdWwgZm9yIHRlc3RpbmcpXG4gKi9cbmV4cG9ydHMuY2xlYXIgPSBmdW5jdGlvbihpZCkge1xuICAgIGlmKGlkKSB7XG4gICAgICAgIF9jbGVhclRpbWVvdXQodGltZXJDYWNoZVtpZF0pO1xuICAgICAgICBkZWxldGUgdGltZXJDYWNoZVtpZF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKHZhciBpZGkgaW4gdGltZXJDYWNoZSkgZXhwb3J0cy5jbGVhcihpZGkpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIF9jbGVhclRpbWVvdXQoY2FjaGUpIHtcbiAgICBpZihjYWNoZSAmJiBjYWNoZS50aW1lciAhPT0gbnVsbCkge1xuICAgICAgICBjbGVhclRpbWVvdXQoY2FjaGUudGltZXIpO1xuICAgICAgICBjYWNoZS50aW1lciA9IG51bGw7XG4gICAgfVxufVxuXG59LHt9XSw3NDU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxuLyoqXG4gKiBjb252ZXJ0IGEgbGluZWFyIHZhbHVlIGludG8gYSBsb2dnZWQgdmFsdWUsIGZvbGRpbmcgbmVnYXRpdmUgbnVtYmVycyBpbnRvXG4gKiB0aGUgZ2l2ZW4gcmFuZ2VcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB0b0xvZ1JhbmdlKHZhbCwgcmFuZ2UpIHtcbiAgICBpZih2YWwgPiAwKSByZXR1cm4gTWF0aC5sb2codmFsKSAvIE1hdGguTE4xMDtcblxuICAgIC8vIG1vdmUgYSBuZWdhdGl2ZSB2YWx1ZSByZWZlcmVuY2UgdG8gYSBsb2cgYXhpcyAtIGp1c3QgcHV0IHRoZVxuICAgIC8vIHJlc3VsdCBhdCB0aGUgbG93ZXN0IHJhbmdlIHZhbHVlIG9uIHRoZSBwbG90IChvciBpZiB0aGUgcmFuZ2UgYWxzbyB3ZW50IG5lZ2F0aXZlLFxuICAgIC8vIG9uZSBtaWxsaW9udGggb2YgdGhlIHRvcCBvZiB0aGUgcmFuZ2UpXG4gICAgdmFyIG5ld1ZhbCA9IE1hdGgubG9nKE1hdGgubWluKHJhbmdlWzBdLCByYW5nZVsxXSkpIC8gTWF0aC5MTjEwO1xuICAgIGlmKCFpc051bWVyaWMobmV3VmFsKSkgbmV3VmFsID0gTWF0aC5sb2coTWF0aC5tYXgocmFuZ2VbMF0sIHJhbmdlWzFdKSkgLyBNYXRoLkxOMTAgLSA2O1xuICAgIHJldHVybiBuZXdWYWw7XG59O1xuXG59LHtcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sNzQ2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHRvcG9qc29uVXRpbHMgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG52YXIgbG9jYXRpb25tb2RlVG9MYXllciA9IF9kZXJlcV8oJy4uL3Bsb3RzL2dlby9jb25zdGFudHMnKS5sb2NhdGlvbm1vZGVUb0xheWVyO1xudmFyIHRvcG9qc29uRmVhdHVyZSA9IF9kZXJlcV8oJ3RvcG9qc29uLWNsaWVudCcpLmZlYXR1cmU7XG5cbnRvcG9qc29uVXRpbHMuZ2V0VG9wb2pzb25OYW1lID0gZnVuY3Rpb24oZ2VvTGF5b3V0KSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgZ2VvTGF5b3V0LnNjb3BlLnJlcGxhY2UoLyAvZywgJy0nKSwgJ18nLFxuICAgICAgICBnZW9MYXlvdXQucmVzb2x1dGlvbi50b1N0cmluZygpLCAnbSdcbiAgICBdLmpvaW4oJycpO1xufTtcblxudG9wb2pzb25VdGlscy5nZXRUb3BvanNvblBhdGggPSBmdW5jdGlvbih0b3BvanNvblVSTCwgdG9wb2pzb25OYW1lKSB7XG4gICAgcmV0dXJuIHRvcG9qc29uVVJMICsgdG9wb2pzb25OYW1lICsgJy5qc29uJztcbn07XG5cbnRvcG9qc29uVXRpbHMuZ2V0VG9wb2pzb25GZWF0dXJlcyA9IGZ1bmN0aW9uKHRyYWNlLCB0b3BvanNvbikge1xuICAgIHZhciBsYXllciA9IGxvY2F0aW9ubW9kZVRvTGF5ZXJbdHJhY2UubG9jYXRpb25tb2RlXTtcbiAgICB2YXIgb2JqID0gdG9wb2pzb24ub2JqZWN0c1tsYXllcl07XG5cbiAgICByZXR1cm4gdG9wb2pzb25GZWF0dXJlKHRvcG9qc29uLCBvYmopLmZlYXR1cmVzO1xufTtcblxufSx7XCIuLi9wbG90cy9nZW8vY29uc3RhbnRzXCI6Nzk1LFwidG9wb2pzb24tY2xpZW50XCI6NTQwfV0sNzQ3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ2xvY2FsZScsXG4gICAgbmFtZTogJ2VuLVVTJyxcbiAgICBkaWN0aW9uYXJ5OiB7XG4gICAgICAgICdDbGljayB0byBlbnRlciBDb2xvcnNjYWxlIHRpdGxlJzogJ0NsaWNrIHRvIGVudGVyIENvbG9yc2NhbGUgdGl0bGUnXG4gICAgfSxcbiAgICBmb3JtYXQ6IHtcbiAgICAgICAgZGF0ZTogJyVtLyVkLyVZJ1xuICAgIH1cbn07XG5cbn0se31dLDc0ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICdsb2NhbGUnLFxuICAgIG5hbWU6ICdlbicsXG4gICAgZGljdGlvbmFyeToge1xuICAgICAgICAnQ2xpY2sgdG8gZW50ZXIgQ29sb3JzY2FsZSB0aXRsZSc6ICdDbGljayB0byBlbnRlciBDb2xvdXJzY2FsZSB0aXRsZSdcbiAgICB9LFxuICAgIGZvcm1hdDoge1xuICAgICAgICBkYXlzOiBbJ1N1bmRheScsICdNb25kYXknLCAnVHVlc2RheScsICdXZWRuZXNkYXknLCAnVGh1cnNkYXknLCAnRnJpZGF5JywgJ1NhdHVyZGF5J10sXG4gICAgICAgIHNob3J0RGF5czogWydTdW4nLCAnTW9uJywgJ1R1ZScsICdXZWQnLCAnVGh1JywgJ0ZyaScsICdTYXQnXSxcbiAgICAgICAgbW9udGhzOiBbXG4gICAgICAgICAgICAnSmFudWFyeScsICdGZWJydWFyeScsICdNYXJjaCcsICdBcHJpbCcsICdNYXknLCAnSnVuZScsXG4gICAgICAgICAgICAnSnVseScsICdBdWd1c3QnLCAnU2VwdGVtYmVyJywgJ09jdG9iZXInLCAnTm92ZW1iZXInLCAnRGVjZW1iZXInXG4gICAgICAgIF0sXG4gICAgICAgIHNob3J0TW9udGhzOiBbXG4gICAgICAgICAgICAnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLFxuICAgICAgICAgICAgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ1xuICAgICAgICBdLFxuICAgICAgICBwZXJpb2RzOiBbJ0FNJywgJ1BNJ10sXG4gICAgICAgIGRhdGVUaW1lOiAnJWEgJWIgJWUgJVggJVknLFxuICAgICAgICBkYXRlOiAnJWQvJW0vJVknLFxuICAgICAgICB0aW1lOiAnJUg6JU06JVMnLFxuICAgICAgICBkZWNpbWFsOiAnLicsXG4gICAgICAgIHRob3VzYW5kczogJywnLFxuICAgICAgICBncm91cGluZzogWzNdLFxuICAgICAgICBjdXJyZW5jeTogWyckJywgJyddLFxuICAgICAgICB5ZWFyOiAnJVknLFxuICAgICAgICBtb250aDogJyViICVZJyxcbiAgICAgICAgZGF5TW9udGg6ICclYiAlLWQnLFxuICAgICAgICBkYXlNb250aFllYXI6ICclYiAlLWQsICVZJ1xuICAgIH1cbn07XG5cbn0se31dLDc0OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vcmVnaXN0cnknKTtcblxuLypcbiAqIGNvbnRhaW5lckFycmF5TWF0Y2g6IGRvZXMgdGhpcyBhdHRyaWJ1dGUgc3RyaW5nIHBvaW50IGludG8gYVxuICogbGF5b3V0IGNvbnRhaW5lciBhcnJheT9cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gYXN0cjogYW4gYXR0cmlidXRlIHN0cmluZywgbGlrZSAqYW5ub3RhdGlvbnNbMl0udGV4dCpcbiAqXG4gKiBAcmV0dXJucyB7T2JqZWN0IHwgZmFsc2V9IFJldHVybnMgZmFsc2UgaWYgYGFzdHJgIGRvZXNuJ3QgbWF0Y2ggYSBjb250YWluZXJcbiAqICBhcnJheS4gSWYgaXQgZG9lcywgcmV0dXJuczpcbiAqICAgICB7YXJyYXk6IHtTdHJpbmd9LCBpbmRleDoge051bWJlcn0sIHByb3BlcnR5OiB7U3RyaW5nfX1cbiAqICBpZSB0aGUgYXR0cmlidXRlIHN0cmluZyBmb3IgdGhlIGFycmF5LCB0aGUgaW5kZXggd2l0aGluIHRoZSBhcnJheSAob3IgJydcbiAqICBpZiB0aGUgd2hvbGUgYXJyYXkpIGFuZCB0aGUgcHJvcGVydHkgd2l0aGluIHRoYXQgKG9yICcnIGlmIHRoZSB3aG9sZSBhcnJheVxuICogIG9yIHRoZSB3aG9sZSBvYmplY3QpXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29udGFpbmVyQXJyYXlNYXRjaChhc3RyKSB7XG4gICAgdmFyIHJvb3RDb250YWluZXJzID0gUmVnaXN0cnkubGF5b3V0QXJyYXlDb250YWluZXJzO1xuICAgIHZhciByZWdleHBDb250YWluZXJzID0gUmVnaXN0cnkubGF5b3V0QXJyYXlSZWdleGVzO1xuICAgIHZhciByb290UGFydCA9IGFzdHIuc3BsaXQoJ1snKVswXTtcbiAgICB2YXIgYXJyYXlTdHI7XG4gICAgdmFyIG1hdGNoO1xuXG4gICAgLy8gbG9vayBmb3IgcmVnZXhwIG1hdGNoZXMgZmlyc3QsIGJlY2F1c2UgdGhleSBtYXkgYmUgbmVzdGVkIGluc2lkZSByb290IG1hdGNoZXNcbiAgICAvLyBlZyB1cGRhdGVtZW51c1tpXS5idXR0b25zIGlzIG5lc3RlZCBpbnNpZGUgdXBkYXRlbWVudXNcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgcmVnZXhwQ29udGFpbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICBtYXRjaCA9IGFzdHIubWF0Y2gocmVnZXhwQ29udGFpbmVyc1tpXSk7XG4gICAgICAgIGlmKG1hdGNoICYmIG1hdGNoLmluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICBhcnJheVN0ciA9IG1hdGNoWzBdO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBub3cgbG9vayBmb3Igcm9vdCBtYXRjaGVzXG4gICAgaWYoIWFycmF5U3RyKSBhcnJheVN0ciA9IHJvb3RDb250YWluZXJzW3Jvb3RDb250YWluZXJzLmluZGV4T2Yocm9vdFBhcnQpXTtcblxuICAgIGlmKCFhcnJheVN0cikgcmV0dXJuIGZhbHNlO1xuXG4gICAgdmFyIHRhaWwgPSBhc3RyLnN1YnN0cihhcnJheVN0ci5sZW5ndGgpO1xuICAgIGlmKCF0YWlsKSByZXR1cm4ge2FycmF5OiBhcnJheVN0ciwgaW5kZXg6ICcnLCBwcm9wZXJ0eTogJyd9O1xuXG4gICAgbWF0Y2ggPSB0YWlsLm1hdGNoKC9eXFxbKDB8WzEtOV1bMC05XSopXFxdKFxcLiguKykpPyQvKTtcbiAgICBpZighbWF0Y2gpIHJldHVybiBmYWxzZTtcblxuICAgIHJldHVybiB7YXJyYXk6IGFycmF5U3RyLCBpbmRleDogTnVtYmVyKG1hdGNoWzFdKSwgcHJvcGVydHk6IG1hdGNoWzNdIHx8ICcnfTtcbn07XG5cbn0se1wiLi4vcmVnaXN0cnlcIjo4NDd9XSw3NTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG52YXIgZXh0ZW5kRmxhdCA9IExpYi5leHRlbmRGbGF0O1xudmFyIGlzUGxhaW5PYmplY3QgPSBMaWIuaXNQbGFpbk9iamVjdDtcblxudmFyIHRyYWNlT3B0cyA9IHtcbiAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgIGV4dHJhczogWydub25lJ10sXG4gICAgZmxhZ3M6IFsnY2FsYycsICdjbGVhckF4aXNUeXBlcycsICdwbG90JywgJ3N0eWxlJywgJ21hcmtlclNpemUnLCAnY29sb3JiYXJzJ10sXG4gICAgXG59O1xuXG52YXIgbGF5b3V0T3B0cyA9IHtcbiAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgIGV4dHJhczogWydub25lJ10sXG4gICAgZmxhZ3M6IFtcbiAgICAgICAgJ2NhbGMnLCAncGxvdCcsICdsZWdlbmQnLCAndGlja3MnLCAnYXhyYW5nZScsXG4gICAgICAgICdsYXlvdXRzdHlsZScsICdtb2RlYmFyJywgJ2NhbWVyYScsICdhcnJheWRyYXcnLCAnY29sb3JiYXJzJ1xuICAgIF0sXG4gICAgXG59O1xuXG4vLyBmbGFncyBmb3IgaW5zaWRlIHJlc3R5bGUvcmVsYXlvdXQgaW5jbHVkZSBhIGZldyBleHRyYXNcbi8vIHRoYXQgc2hvdWxkbid0IGJlIHVzZWQgaW4gYXR0cmlidXRlcywgdG8gZGVhbCB3aXRoIGNlcnRhaW5cbi8vIGNvbWJpbmF0aW9ucyBhbmQgY29uZGl0aW9uYWxzIGVmZmljaWVudGx5XG52YXIgdHJhY2VFZGl0VHlwZUZsYWdzID0gdHJhY2VPcHRzLmZsYWdzLnNsaWNlKClcbiAgICAuY29uY2F0KFsnZnVsbFJlcGxvdCddKTtcblxudmFyIGxheW91dEVkaXRUeXBlRmxhZ3MgPSBsYXlvdXRPcHRzLmZsYWdzLnNsaWNlKClcbiAgICAuY29uY2F0KCdsYXlvdXRSZXBsb3QnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgdHJhY2VzOiB0cmFjZU9wdHMsXG4gICAgbGF5b3V0OiBsYXlvdXRPcHRzLFxuICAgIC8qXG4gICAgICogZGVmYXVsdCAoYWxsIGZhbHNlKSBlZGl0IGZsYWdzIGZvciByZXN0eWxlICh0cmFjZXMpXG4gICAgICogY3JlYXRlcyBhIG5ldyBvYmplY3QgZWFjaCBjYWxsLCBzbyB0aGUgY2FsbGVyIGNhbiBtdXRhdGUgZnJlZWx5XG4gICAgICovXG4gICAgdHJhY2VGbGFnczogZnVuY3Rpb24oKSB7IHJldHVybiBmYWxzZU9iaih0cmFjZUVkaXRUeXBlRmxhZ3MpOyB9LFxuXG4gICAgLypcbiAgICAgKiBkZWZhdWx0IChhbGwgZmFsc2UpIGVkaXQgZmxhZ3MgZm9yIHJlbGF5b3V0XG4gICAgICogY3JlYXRlcyBhIG5ldyBvYmplY3QgZWFjaCBjYWxsLCBzbyB0aGUgY2FsbGVyIGNhbiBtdXRhdGUgZnJlZWx5XG4gICAgICovXG4gICAgbGF5b3V0RmxhZ3M6IGZ1bmN0aW9uKCkgeyByZXR1cm4gZmFsc2VPYmoobGF5b3V0RWRpdFR5cGVGbGFncyk7IH0sXG5cbiAgICAvKlxuICAgICAqIHVwZGF0ZSBgZmxhZ3NgIHdpdGggdGhlIGBlZGl0VHlwZWAgdmFsdWVzIGZvdW5kIGluIGBhdHRyYFxuICAgICAqL1xuICAgIHVwZGF0ZTogZnVuY3Rpb24oZmxhZ3MsIGF0dHIpIHtcbiAgICAgICAgdmFyIGVkaXRUeXBlID0gYXR0ci5lZGl0VHlwZTtcbiAgICAgICAgaWYoZWRpdFR5cGUgJiYgZWRpdFR5cGUgIT09ICdub25lJykge1xuICAgICAgICAgICAgdmFyIGVkaXRUeXBlUGFydHMgPSBlZGl0VHlwZS5zcGxpdCgnKycpO1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGVkaXRUeXBlUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmbGFnc1tlZGl0VHlwZVBhcnRzW2ldXSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgb3ZlcnJpZGVBbGw6IG92ZXJyaWRlQWxsXG59O1xuXG5mdW5jdGlvbiBmYWxzZU9iaihrZXlzKSB7XG4gICAgdmFyIG91dCA9IHt9O1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSBvdXRba2V5c1tpXV0gPSBmYWxzZTtcbiAgICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIEZvciBhdHRyaWJ1dGVzIHRoYXQgYXJlIGxhcmdlbHkgY29waWVkIGZyb20gZWxzZXdoZXJlIGludG8gYSBwbG90IHR5cGUgdGhhdCBkb2Vzbid0XG4gKiBzdXBwb3J0IHBhcnRpYWwgcmVkcmF3cyAtIG92ZXJyaWRlcyB0aGUgZWRpdFR5cGUgZmllbGQgb2YgYWxsIGF0dHJpYnV0ZXMgaW4gdGhlIG9iamVjdFxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBhdHRyczogdGhlIGF0dHJpYnV0ZXMgdG8gb3ZlcnJpZGUuIFdpbGwgbm90IGJlIG11dGF0ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZWRpdFR5cGVPdmVycmlkZTogdGhlIG5ldyBlZGl0VHlwZSB0byB1c2VcbiAqIEBwYXJhbSB7J25lc3RlZCd8J2Zyb20tcm9vdCd9IG92ZXJyaWRlQ29udGFpbmVyczpcbiAqICAgLSAnbmVzdGVkJyB3aWxsIG92ZXJyaWRlIGVkaXRUeXBlIGZvciBuZXN0ZWQgY29udGFpbmVycyBidXQgbm90IHRoZSByb290LlxuICogICAtICdmcm9tLXJvb3QnIHdpbGwgYWxzbyBvdmVycmlkZSBlZGl0VHlwZSBvZiB0aGUgcm9vdCBjb250YWluZXIuXG4gKiAgIENvbnRhaW5lcnMgYmVsb3cgdGhlIGFic29sdXRlIHRvcCBsZXZlbCAodHJhY2Ugb3IgbGF5b3V0IHJvb3QpIERPIG5lZWQgYW5cbiAqICAgZWRpdFR5cGUgZXZlbiBpZiB0aGV5IGFyZSBub3QgYHZhbE9iamVjdGBzIHRoZW1zZWx2ZXMgKGVnIGBzY2F0dGVyLm1hcmtlcmApXG4gKiAgIHRvIGhhbmRsZSB0aGUgY2FzZSB3aGVyZSB5b3UgZWRpdCB0aGUgd2hvbGUgY29udGFpbmVyLlxuICpcbiAqIEByZXR1cm4ge29iamVjdH0gYSBuZXcgYXR0cmlidXRlcyBvYmplY3Qgd2l0aCBgZWRpdFR5cGVgIG1vZGlmaWVkIGFzIGRpcmVjdGVkXG4gKi9cbmZ1bmN0aW9uIG92ZXJyaWRlQWxsKGF0dHJzLCBlZGl0VHlwZU92ZXJyaWRlLCBvdmVycmlkZUNvbnRhaW5lcnMpIHtcbiAgICB2YXIgb3V0ID0gZXh0ZW5kRmxhdCh7fSwgYXR0cnMpO1xuICAgIGZvcih2YXIga2V5IGluIG91dCkge1xuICAgICAgICB2YXIgYXR0ciA9IG91dFtrZXldO1xuICAgICAgICBpZihpc1BsYWluT2JqZWN0KGF0dHIpKSB7XG4gICAgICAgICAgICBvdXRba2V5XSA9IG92ZXJyaWRlT25lKGF0dHIsIGVkaXRUeXBlT3ZlcnJpZGUsIG92ZXJyaWRlQ29udGFpbmVycywga2V5KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZihvdmVycmlkZUNvbnRhaW5lcnMgPT09ICdmcm9tLXJvb3QnKSBvdXQuZWRpdFR5cGUgPSBlZGl0VHlwZU92ZXJyaWRlO1xuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gb3ZlcnJpZGVPbmUoYXR0ciwgZWRpdFR5cGVPdmVycmlkZSwgb3ZlcnJpZGVDb250YWluZXJzLCBrZXkpIHtcbiAgICBpZihhdHRyLnZhbFR5cGUpIHtcbiAgICAgICAgdmFyIG91dCA9IGV4dGVuZEZsYXQoe30sIGF0dHIpO1xuICAgICAgICBvdXQuZWRpdFR5cGUgPSBlZGl0VHlwZU92ZXJyaWRlO1xuXG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoYXR0ci5pdGVtcykpIHtcbiAgICAgICAgICAgIG91dC5pdGVtcyA9IG5ldyBBcnJheShhdHRyLml0ZW1zLmxlbmd0aCk7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXR0ci5pdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIG91dC5pdGVtc1tpXSA9IG92ZXJyaWRlT25lKGF0dHIuaXRlbXNbaV0sIGVkaXRUeXBlT3ZlcnJpZGUsICdmcm9tLXJvb3QnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGRvbid0IHByb3ZpZGUgYW4gZWRpdFR5cGUgZm9yIHRoZSBfZGVwcmVjYXRlZCBjb250YWluZXJcbiAgICAgICAgcmV0dXJuIG92ZXJyaWRlQWxsKGF0dHIsIGVkaXRUeXBlT3ZlcnJpZGUsXG4gICAgICAgICAgICAoa2V5LmNoYXJBdCgwKSA9PT0gJ18nKSA/ICduZXN0ZWQnIDogJ2Zyb20tcm9vdCcpO1xuICAgIH1cbn1cblxufSx7XCIuLi9saWJcIjo3MTl9XSw3NTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcbnZhciBtNEZyb21RdWF0ID0gX2RlcmVxXygnZ2wtbWF0NC9mcm9tUXVhdCcpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uL2xpYicpO1xudmFyIFBsb3RzID0gX2RlcmVxXygnLi4vcGxvdHMvcGxvdHMnKTtcbnZhciBBeGlzSWRzID0gX2RlcmVxXygnLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb21wb25lbnRzL2NvbG9yJyk7XG5cbnZhciBjbGVhbklkID0gQXhpc0lkcy5jbGVhbklkO1xudmFyIGdldEZyb21UcmFjZSA9IEF4aXNJZHMuZ2V0RnJvbVRyYWNlO1xudmFyIHRyYWNlSXMgPSBSZWdpc3RyeS50cmFjZUlzO1xuXG4vLyBjbGVhciB0aGUgcHJvbWlzZSBxdWV1ZSBpZiBvbmUgb2YgdGhlbSBnb3QgcmVqZWN0ZWRcbmV4cG9ydHMuY2xlYXJQcm9taXNlUXVldWUgPSBmdW5jdGlvbihnZCkge1xuICAgIGlmKEFycmF5LmlzQXJyYXkoZ2QuX3Byb21pc2VzKSAmJiBnZC5fcHJvbWlzZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBMaWIubG9nKCdDbGVhcmluZyBwcmV2aW91cyByZWplY3RlZCBwcm9taXNlcyBmcm9tIHF1ZXVlLicpO1xuICAgIH1cblxuICAgIGdkLl9wcm9taXNlcyA9IFtdO1xufTtcblxuLy8gbWFrZSBhIGZldyBjaGFuZ2VzIHRvIHRoZSBsYXlvdXQgcmlnaHQgYXdheVxuLy8gYmVmb3JlIGl0IGdldHMgdXNlZCBmb3IgYW55dGhpbmdcbi8vIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgYW5kIGNsZWFudXAgb2Ygbm9uc3RhbmRhcmQgb3B0aW9uc1xuZXhwb3J0cy5jbGVhbkxheW91dCA9IGZ1bmN0aW9uKGxheW91dCkge1xuICAgIHZhciBpLCBqO1xuXG4gICAgaWYoIWxheW91dCkgbGF5b3V0ID0ge307XG5cbiAgICAvLyBjYW5ub3QgaGF2ZSAoeHx5KWF4aXMxLCBudW1iZXJpbmcgZ29lcyBheGlzLCBheGlzMiwgYXhpczMuLi5cbiAgICBpZihsYXlvdXQueGF4aXMxKSB7XG4gICAgICAgIGlmKCFsYXlvdXQueGF4aXMpIGxheW91dC54YXhpcyA9IGxheW91dC54YXhpczE7XG4gICAgICAgIGRlbGV0ZSBsYXlvdXQueGF4aXMxO1xuICAgIH1cbiAgICBpZihsYXlvdXQueWF4aXMxKSB7XG4gICAgICAgIGlmKCFsYXlvdXQueWF4aXMpIGxheW91dC55YXhpcyA9IGxheW91dC55YXhpczE7XG4gICAgICAgIGRlbGV0ZSBsYXlvdXQueWF4aXMxO1xuICAgIH1cbiAgICBpZihsYXlvdXQuc2NlbmUxKSB7XG4gICAgICAgIGlmKCFsYXlvdXQuc2NlbmUpIGxheW91dC5zY2VuZSA9IGxheW91dC5zY2VuZTE7XG4gICAgICAgIGRlbGV0ZSBsYXlvdXQuc2NlbmUxO1xuICAgIH1cblxuICAgIHZhciBheGlzQXR0clJlZ2V4ID0gKFBsb3RzLnN1YnBsb3RzUmVnaXN0cnkuY2FydGVzaWFuIHx8IHt9KS5hdHRyUmVnZXg7XG4gICAgdmFyIHBvbGFyQXR0clJlZ2V4ID0gKFBsb3RzLnN1YnBsb3RzUmVnaXN0cnkucG9sYXIgfHwge30pLmF0dHJSZWdleDtcbiAgICB2YXIgdGVybmFyeUF0dHJSZWdleCA9IChQbG90cy5zdWJwbG90c1JlZ2lzdHJ5LnRlcm5hcnkgfHwge30pLmF0dHJSZWdleDtcbiAgICB2YXIgc2NlbmVBdHRyUmVnZXggPSAoUGxvdHMuc3VicGxvdHNSZWdpc3RyeS5nbDNkIHx8IHt9KS5hdHRyUmVnZXg7XG5cbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGxheW91dCk7XG4gICAgZm9yKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTtcblxuICAgICAgICBpZihheGlzQXR0clJlZ2V4ICYmIGF4aXNBdHRyUmVnZXgudGVzdChrZXkpKSB7XG4gICAgICAgICAgICAvLyBtb2RpZmljYXRpb25zIHRvIGNhcnRlc2lhbiBheGVzXG5cbiAgICAgICAgICAgIHZhciBheCA9IGxheW91dFtrZXldO1xuICAgICAgICAgICAgaWYoYXguYW5jaG9yICYmIGF4LmFuY2hvciAhPT0gJ2ZyZWUnKSB7XG4gICAgICAgICAgICAgICAgYXguYW5jaG9yID0gY2xlYW5JZChheC5hbmNob3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoYXgub3ZlcmxheWluZykgYXgub3ZlcmxheWluZyA9IGNsZWFuSWQoYXgub3ZlcmxheWluZyk7XG5cbiAgICAgICAgICAgIC8vIG9sZCBtZXRob2Qgb2YgYXhpcyB0eXBlIC0gaXNkYXRlIGFuZCBpc2xvZyAoYmVmb3JlIGNhdGVnb3J5IGV4aXN0ZWQpXG4gICAgICAgICAgICBpZighYXgudHlwZSkge1xuICAgICAgICAgICAgICAgIGlmKGF4LmlzZGF0ZSkgYXgudHlwZSA9ICdkYXRlJztcbiAgICAgICAgICAgICAgICBlbHNlIGlmKGF4LmlzbG9nKSBheC50eXBlID0gJ2xvZyc7XG4gICAgICAgICAgICAgICAgZWxzZSBpZihheC5pc2RhdGUgPT09IGZhbHNlICYmIGF4LmlzbG9nID09PSBmYWxzZSkgYXgudHlwZSA9ICdsaW5lYXInO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoYXguYXV0b3JhbmdlID09PSAnd2l0aHplcm8nIHx8IGF4LmF1dG9yYW5nZSA9PT0gJ3RvemVybycpIHtcbiAgICAgICAgICAgICAgICBheC5hdXRvcmFuZ2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGF4LnJhbmdlbW9kZSA9ICd0b3plcm8nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIGF4LmlzbG9nO1xuICAgICAgICAgICAgZGVsZXRlIGF4LmlzZGF0ZTtcbiAgICAgICAgICAgIGRlbGV0ZSBheC5jYXRlZ29yaWVzOyAvLyByZXBsYWNlZCBieSBfY2F0ZWdvcmllc1xuXG4gICAgICAgICAgICAvLyBwcnVuZSBlbXB0eSBkb21haW4gYXJyYXlzIG1hZGUgYmVmb3JlIHRoZSBuZXcgbmVzdGVkUHJvcGVydHlcbiAgICAgICAgICAgIGlmKGVtcHR5Q29udGFpbmVyKGF4LCAnZG9tYWluJykpIGRlbGV0ZSBheC5kb21haW47XG5cbiAgICAgICAgICAgIC8vIGF1dG90aWNrIC0+IHRpY2ttb2RlXG4gICAgICAgICAgICBpZihheC5hdXRvdGljayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgaWYoYXgudGlja21vZGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBheC50aWNrbW9kZSA9IGF4LmF1dG90aWNrID8gJ2F1dG8nIDogJ2xpbmVhcic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlbGV0ZSBheC5hdXRvdGljaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2xlYW5UaXRsZShheCk7XG4gICAgICAgIH0gZWxzZSBpZihwb2xhckF0dHJSZWdleCAmJiBwb2xhckF0dHJSZWdleC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgIC8vIG1vZGlmaWNhdGlvbnMgZm9yIHBvbGFyXG5cbiAgICAgICAgICAgIHZhciBwb2xhciA9IGxheW91dFtrZXldO1xuICAgICAgICAgICAgY2xlYW5UaXRsZShwb2xhci5yYWRpYWxheGlzKTtcbiAgICAgICAgfSBlbHNlIGlmKHRlcm5hcnlBdHRyUmVnZXggJiYgdGVybmFyeUF0dHJSZWdleC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgIC8vIG1vZGlmaWNhdGlvbnMgZm9yIHRlcm5hcnlcblxuICAgICAgICAgICAgdmFyIHRlcm5hcnkgPSBsYXlvdXRba2V5XTtcbiAgICAgICAgICAgIGNsZWFuVGl0bGUodGVybmFyeS5hYXhpcyk7XG4gICAgICAgICAgICBjbGVhblRpdGxlKHRlcm5hcnkuYmF4aXMpO1xuICAgICAgICAgICAgY2xlYW5UaXRsZSh0ZXJuYXJ5LmNheGlzKTtcbiAgICAgICAgfSBlbHNlIGlmKHNjZW5lQXR0clJlZ2V4ICYmIHNjZW5lQXR0clJlZ2V4LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgLy8gbW9kaWZpY2F0aW9ucyBmb3IgM0Qgc2NlbmVzXG5cbiAgICAgICAgICAgIHZhciBzY2VuZSA9IGxheW91dFtrZXldO1xuXG4gICAgICAgICAgICAvLyBjbGVhbiBvbGQgQ2FtZXJhIGNvb3Jkc1xuICAgICAgICAgICAgdmFyIGNhbWVyYXBvc2l0aW9uID0gc2NlbmUuY2FtZXJhcG9zaXRpb247XG5cbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoY2FtZXJhcG9zaXRpb24pICYmIGNhbWVyYXBvc2l0aW9uWzBdLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHZhciByb3RhdGlvbiA9IGNhbWVyYXBvc2l0aW9uWzBdO1xuICAgICAgICAgICAgICAgIHZhciBjZW50ZXIgPSBjYW1lcmFwb3NpdGlvblsxXTtcbiAgICAgICAgICAgICAgICB2YXIgcmFkaXVzID0gY2FtZXJhcG9zaXRpb25bMl07XG4gICAgICAgICAgICAgICAgdmFyIG1hdCA9IG00RnJvbVF1YXQoW10sIHJvdGF0aW9uKTtcbiAgICAgICAgICAgICAgICB2YXIgZXllID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCAzOyArK2opIHtcbiAgICAgICAgICAgICAgICAgICAgZXllW2pdID0gY2VudGVyW2pdICsgcmFkaXVzICogbWF0WzIgKyA0ICogal07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgc2NlbmUuY2FtZXJhID0ge1xuICAgICAgICAgICAgICAgICAgICBleWU6IHt4OiBleWVbMF0sIHk6IGV5ZVsxXSwgejogZXllWzJdfSxcbiAgICAgICAgICAgICAgICAgICAgY2VudGVyOiB7eDogY2VudGVyWzBdLCB5OiBjZW50ZXJbMV0sIHo6IGNlbnRlclsyXX0sXG4gICAgICAgICAgICAgICAgICAgIHVwOiB7eDogMCwgeTogMCwgejogMX0gLy8gd2UganVzdCBpZ25vcmUgY2FsY3VsYXRpbmcgY2FtZXJhIHogdXAgaW4gdGhpcyBjYXNlXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGRlbGV0ZSBzY2VuZS5jYW1lcmFwb3NpdGlvbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gY2xlYW4gYXhpcyB0aXRsZXNcbiAgICAgICAgICAgIGNsZWFuVGl0bGUoc2NlbmUueGF4aXMpO1xuICAgICAgICAgICAgY2xlYW5UaXRsZShzY2VuZS55YXhpcyk7XG4gICAgICAgICAgICBjbGVhblRpdGxlKHNjZW5lLnpheGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBhbm5vdGF0aW9uc0xlbiA9IEFycmF5LmlzQXJyYXkobGF5b3V0LmFubm90YXRpb25zKSA/IGxheW91dC5hbm5vdGF0aW9ucy5sZW5ndGggOiAwO1xuICAgIGZvcihpID0gMDsgaSA8IGFubm90YXRpb25zTGVuOyBpKyspIHtcbiAgICAgICAgdmFyIGFubiA9IGxheW91dC5hbm5vdGF0aW9uc1tpXTtcblxuICAgICAgICBpZighTGliLmlzUGxhaW5PYmplY3QoYW5uKSkgY29udGludWU7XG5cbiAgICAgICAgaWYoYW5uLnJlZikge1xuICAgICAgICAgICAgaWYoYW5uLnJlZiA9PT0gJ3BhcGVyJykge1xuICAgICAgICAgICAgICAgIGFubi54cmVmID0gJ3BhcGVyJztcbiAgICAgICAgICAgICAgICBhbm4ueXJlZiA9ICdwYXBlcic7XG4gICAgICAgICAgICB9IGVsc2UgaWYoYW5uLnJlZiA9PT0gJ2RhdGEnKSB7XG4gICAgICAgICAgICAgICAgYW5uLnhyZWYgPSAneCc7XG4gICAgICAgICAgICAgICAgYW5uLnlyZWYgPSAneSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgYW5uLnJlZjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNsZWFuQXhSZWYoYW5uLCAneHJlZicpO1xuICAgICAgICBjbGVhbkF4UmVmKGFubiwgJ3lyZWYnKTtcbiAgICB9XG5cbiAgICB2YXIgc2hhcGVzTGVuID0gQXJyYXkuaXNBcnJheShsYXlvdXQuc2hhcGVzKSA/IGxheW91dC5zaGFwZXMubGVuZ3RoIDogMDtcbiAgICBmb3IoaSA9IDA7IGkgPCBzaGFwZXNMZW47IGkrKykge1xuICAgICAgICB2YXIgc2hhcGUgPSBsYXlvdXQuc2hhcGVzW2ldO1xuXG4gICAgICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChzaGFwZSkpIGNvbnRpbnVlO1xuXG4gICAgICAgIGNsZWFuQXhSZWYoc2hhcGUsICd4cmVmJyk7XG4gICAgICAgIGNsZWFuQXhSZWYoc2hhcGUsICd5cmVmJyk7XG4gICAgfVxuXG4gICAgdmFyIGxlZ2VuZCA9IGxheW91dC5sZWdlbmQ7XG4gICAgaWYobGVnZW5kKSB7XG4gICAgICAgIC8vIGNoZWNrIGZvciBvbGQtc3R5bGUgbGVnZW5kIHBvc2l0aW9uaW5nICh4IG9yIHkgaXMgKy8tIDEwMClcbiAgICAgICAgaWYobGVnZW5kLnggPiAzKSB7XG4gICAgICAgICAgICBsZWdlbmQueCA9IDEuMDI7XG4gICAgICAgICAgICBsZWdlbmQueGFuY2hvciA9ICdsZWZ0JztcbiAgICAgICAgfSBlbHNlIGlmKGxlZ2VuZC54IDwgLTIpIHtcbiAgICAgICAgICAgIGxlZ2VuZC54ID0gLTAuMDI7XG4gICAgICAgICAgICBsZWdlbmQueGFuY2hvciA9ICdyaWdodCc7XG4gICAgICAgIH1cblxuICAgICAgICBpZihsZWdlbmQueSA+IDMpIHtcbiAgICAgICAgICAgIGxlZ2VuZC55ID0gMS4wMjtcbiAgICAgICAgICAgIGxlZ2VuZC55YW5jaG9yID0gJ2JvdHRvbSc7XG4gICAgICAgIH0gZWxzZSBpZihsZWdlbmQueSA8IC0yKSB7XG4gICAgICAgICAgICBsZWdlbmQueSA9IC0wLjAyO1xuICAgICAgICAgICAgbGVnZW5kLnlhbmNob3IgPSAndG9wJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNsZWFuIHBsb3QgdGl0bGVcbiAgICBjbGVhblRpdGxlKGxheW91dCk7XG5cbiAgICAvKlxuICAgICAqIE1vdmVkIGZyb20gcm90YXRlIC0+IG9yYml0IGZvciBkcmFnbW9kZVxuICAgICAqL1xuICAgIGlmKGxheW91dC5kcmFnbW9kZSA9PT0gJ3JvdGF0ZScpIGxheW91dC5kcmFnbW9kZSA9ICdvcmJpdCc7XG5cbiAgICAvLyBzYW5pdGl6ZSByZ2IoZnJhY3Rpb25zKSBhbmQgcmdiYShmcmFjdGlvbnMpIHRoYXQgb2xkIHRpbnljb2xvclxuICAgIC8vIHN1cHBvcnRlZCwgYnV0IG5ldyB0aW55Y29sb3IgZG9lcyBub3QgYmVjYXVzZSB0aGV5J3JlIG5vdCB2YWxpZCBjc3NcbiAgICBDb2xvci5jbGVhbihsYXlvdXQpO1xuXG4gICAgLy8gY2xlYW4gdGhlIGxheW91dCBjb250YWluZXIgaW4gbGF5b3V0LnRlbXBsYXRlXG4gICAgaWYobGF5b3V0LnRlbXBsYXRlICYmIGxheW91dC50ZW1wbGF0ZS5sYXlvdXQpIHtcbiAgICAgICAgZXhwb3J0cy5jbGVhbkxheW91dChsYXlvdXQudGVtcGxhdGUubGF5b3V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbGF5b3V0O1xufTtcblxuZnVuY3Rpb24gY2xlYW5BeFJlZihjb250YWluZXIsIGF0dHIpIHtcbiAgICB2YXIgdmFsSW4gPSBjb250YWluZXJbYXR0cl07XG4gICAgdmFyIGF4TGV0dGVyID0gYXR0ci5jaGFyQXQoMCk7XG4gICAgaWYodmFsSW4gJiYgdmFsSW4gIT09ICdwYXBlcicpIHtcbiAgICAgICAgY29udGFpbmVyW2F0dHJdID0gY2xlYW5JZCh2YWxJbiwgYXhMZXR0ZXIpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDbGVhbnMgdXAgb2xkIHRpdGxlIGF0dHJpYnV0ZSBzdHJ1Y3R1cmUgKGZsYXQpIGluIGZhdm9yIG9mIHRoZSBuZXcgb25lIChuZXN0ZWQpLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB0aXRsZUNvbnRhaW5lciAtIGFuIG9iamVjdCBwb3RlbnRpYWxseSBpbmNsdWRpbmcgZGVwcmVjYXRlZCB0aXRsZSBhdHRyaWJ1dGVzXG4gKi9cbmZ1bmN0aW9uIGNsZWFuVGl0bGUodGl0bGVDb250YWluZXIpIHtcbiAgICBpZih0aXRsZUNvbnRhaW5lcikge1xuICAgICAgICAvLyB0aXRsZSAtPiB0aXRsZS50ZXh0XG4gICAgICAgIC8vIChhbHRob3VnaCB0aXRsZSB1c2VkIHRvIGJlIGEgc3RyaW5nIGF0dHJpYnV0ZSxcbiAgICAgICAgLy8gbnVtYmVycyBhcmUgYWNjZXB0ZWQgYXMgd2VsbClcbiAgICAgICAgaWYodHlwZW9mIHRpdGxlQ29udGFpbmVyLnRpdGxlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgdGl0bGVDb250YWluZXIudGl0bGUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICB0aXRsZUNvbnRhaW5lci50aXRsZSA9IHtcbiAgICAgICAgICAgICAgICB0ZXh0OiB0aXRsZUNvbnRhaW5lci50aXRsZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJld2lyZUF0dHIoJ3RpdGxlZm9udCcsICdmb250Jyk7XG4gICAgICAgIHJld2lyZUF0dHIoJ3RpdGxlcG9zaXRpb24nLCAncG9zaXRpb24nKTtcbiAgICAgICAgcmV3aXJlQXR0cigndGl0bGVzaWRlJywgJ3NpZGUnKTtcbiAgICAgICAgcmV3aXJlQXR0cigndGl0bGVvZmZzZXQnLCAnb2Zmc2V0Jyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmV3aXJlQXR0cihvbGRBdHRyTmFtZSwgbmV3QXR0ck5hbWUpIHtcbiAgICAgICAgdmFyIG9sZEF0dHJTZXQgPSB0aXRsZUNvbnRhaW5lcltvbGRBdHRyTmFtZV07XG4gICAgICAgIHZhciBuZXdBdHRyU2V0ID0gdGl0bGVDb250YWluZXIudGl0bGUgJiYgdGl0bGVDb250YWluZXIudGl0bGVbbmV3QXR0ck5hbWVdO1xuXG4gICAgICAgIGlmKG9sZEF0dHJTZXQgJiYgIW5ld0F0dHJTZXQpIHtcbiAgICAgICAgICAgIC8vIEVuc3VyZSB0aXRsZSBvYmplY3QgZXhpc3RzXG4gICAgICAgICAgICBpZighdGl0bGVDb250YWluZXIudGl0bGUpIHtcbiAgICAgICAgICAgICAgICB0aXRsZUNvbnRhaW5lci50aXRsZSA9IHt9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aXRsZUNvbnRhaW5lci50aXRsZVtuZXdBdHRyTmFtZV0gPSB0aXRsZUNvbnRhaW5lcltvbGRBdHRyTmFtZV07XG4gICAgICAgICAgICBkZWxldGUgdGl0bGVDb250YWluZXJbb2xkQXR0ck5hbWVdO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKlxuICogY2xlYW5EYXRhOiBNYWtlIGEgZmV3IGNoYW5nZXMgdG8gdGhlIGRhdGEgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbiAqIGJlZm9yZSBpdCBnZXRzIHVzZWQgZm9yIGFueXRoaW5nLiBNb2RpZmllcyB0aGUgZGF0YSB0cmFjZXMgdXNlcnMgcHJvdmlkZS5cbiAqXG4gKiBJbXBvcnRhbnQ6IGlmIHlvdSdyZSBnb2luZyB0byBhZGQgc29tZXRoaW5nIGhlcmUgdGhhdCBtb2RpZmllcyBhIGRhdGEgYXJyYXksXG4gKiB1cGRhdGUgaXQgaW4gcGxhY2Ugc28gdGhlIG5ldyBhcnJheSA9PT0gdGhlIG9sZCBvbmUuXG4gKi9cbmV4cG9ydHMuY2xlYW5EYXRhID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIGZvcih2YXIgdHJhY2VpID0gMDsgdHJhY2VpIDwgZGF0YS5sZW5ndGg7IHRyYWNlaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGRhdGFbdHJhY2VpXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgLy8gdXNlIHhiaW5zIHRvIGJpbiBkYXRhIGluIHgsIGFuZCB5YmlucyB0byBiaW4gZGF0YSBpbiB5XG4gICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdoaXN0b2dyYW15JyAmJiAneGJpbnMnIGluIHRyYWNlICYmICEoJ3liaW5zJyBpbiB0cmFjZSkpIHtcbiAgICAgICAgICAgIHRyYWNlLnliaW5zID0gdHJhY2UueGJpbnM7XG4gICAgICAgICAgICBkZWxldGUgdHJhY2UueGJpbnM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBlcnJvcl95Lm9wYWNpdHkgaXMgb2Jzb2xldGUgLSBtZXJnZSBpbnRvIGNvbG9yXG4gICAgICAgIGlmKHRyYWNlLmVycm9yX3kgJiYgJ29wYWNpdHknIGluIHRyYWNlLmVycm9yX3kpIHtcbiAgICAgICAgICAgIHZhciBkYyA9IENvbG9yLmRlZmF1bHRzO1xuICAgICAgICAgICAgdmFyIHllQ29sb3IgPSB0cmFjZS5lcnJvcl95LmNvbG9yIHx8ICh0cmFjZUlzKHRyYWNlLCAnYmFyJykgP1xuICAgICAgICAgICAgICAgIENvbG9yLmRlZmF1bHRMaW5lIDpcbiAgICAgICAgICAgICAgICBkY1t0cmFjZWkgJSBkYy5sZW5ndGhdKTtcbiAgICAgICAgICAgIHRyYWNlLmVycm9yX3kuY29sb3IgPSBDb2xvci5hZGRPcGFjaXR5KFxuICAgICAgICAgICAgICAgIENvbG9yLnJnYih5ZUNvbG9yKSxcbiAgICAgICAgICAgICAgICBDb2xvci5vcGFjaXR5KHllQ29sb3IpICogdHJhY2UuZXJyb3JfeS5vcGFjaXR5KTtcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5lcnJvcl95Lm9wYWNpdHk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjb252ZXJ0IGJhcmRpciB0byBvcmllbnRhdGlvbiwgYW5kIHB1dCB0aGUgZGF0YSBpbnRvXG4gICAgICAgIC8vIHRoZSBheGVzIGl0J3MgZXZlbnR1YWxseSBnb2luZyB0byBiZSB1c2VkIHdpdGhcbiAgICAgICAgaWYoJ2JhcmRpcicgaW4gdHJhY2UpIHtcbiAgICAgICAgICAgIGlmKHRyYWNlLmJhcmRpciA9PT0gJ2gnICYmICh0cmFjZUlzKHRyYWNlLCAnYmFyJykgfHxcbiAgICAgICAgICAgICAgICB0cmFjZS50eXBlLnN1YnN0cigwLCA5KSA9PT0gJ2hpc3RvZ3JhbScpKSB7XG4gICAgICAgICAgICAgICAgdHJhY2Uub3JpZW50YXRpb24gPSAnaCc7XG4gICAgICAgICAgICAgICAgZXhwb3J0cy5zd2FwWFlEYXRhKHRyYWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5iYXJkaXI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBub3cgd2UgaGF2ZSBvbmx5IG9uZSAxRCBoaXN0b2dyYW0gdHlwZSwgYW5kIHdoZXRoZXJcbiAgICAgICAgLy8gaXQgdXNlcyB4IG9yIHkgZGF0YSBkZXBlbmRzIG9uIHRyYWNlLm9yaWVudGF0aW9uXG4gICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdoaXN0b2dyYW15JykgZXhwb3J0cy5zd2FwWFlEYXRhKHRyYWNlKTtcbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2hpc3RvZ3JhbXgnIHx8IHRyYWNlLnR5cGUgPT09ICdoaXN0b2dyYW15Jykge1xuICAgICAgICAgICAgdHJhY2UudHlwZSA9ICdoaXN0b2dyYW0nO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc2NsLT5zY2FsZSwgcmV2ZXJzZXNjbC0+cmV2ZXJzZXNjYWxlXG4gICAgICAgIGlmKCdzY2wnIGluIHRyYWNlICYmICEoJ2NvbG9yc2NhbGUnIGluIHRyYWNlKSkge1xuICAgICAgICAgICAgdHJhY2UuY29sb3JzY2FsZSA9IHRyYWNlLnNjbDtcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5zY2w7XG4gICAgICAgIH1cbiAgICAgICAgaWYoJ3JldmVyc2VzY2wnIGluIHRyYWNlICYmICEoJ3JldmVyc2VzY2FsZScgaW4gdHJhY2UpKSB7XG4gICAgICAgICAgICB0cmFjZS5yZXZlcnNlc2NhbGUgPSB0cmFjZS5yZXZlcnNlc2NsO1xuICAgICAgICAgICAgZGVsZXRlIHRyYWNlLnJldmVyc2VzY2w7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBheGlzIGlkcyB4MSAtPiB4LCB5MS0+IHlcbiAgICAgICAgaWYodHJhY2UueGF4aXMpIHRyYWNlLnhheGlzID0gY2xlYW5JZCh0cmFjZS54YXhpcywgJ3gnKTtcbiAgICAgICAgaWYodHJhY2UueWF4aXMpIHRyYWNlLnlheGlzID0gY2xlYW5JZCh0cmFjZS55YXhpcywgJ3knKTtcblxuICAgICAgICAvLyBzY2VuZSBpZHMgc2NlbmUxIC0+IHNjZW5lXG4gICAgICAgIGlmKHRyYWNlSXModHJhY2UsICdnbDNkJykgJiYgdHJhY2Uuc2NlbmUpIHtcbiAgICAgICAgICAgIHRyYWNlLnNjZW5lID0gUGxvdHMuc3VicGxvdHNSZWdpc3RyeS5nbDNkLmNsZWFuSWQodHJhY2Uuc2NlbmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIXRyYWNlSXModHJhY2UsICdwaWUtbGlrZScpICYmICF0cmFjZUlzKHRyYWNlLCAnYmFyLWxpa2UnKSkge1xuICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh0cmFjZS50ZXh0cG9zaXRpb24pKSB7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgdHJhY2UudGV4dHBvc2l0aW9uLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNlLnRleHRwb3NpdGlvbltpXSA9IGNsZWFuVGV4dFBvc2l0aW9uKHRyYWNlLnRleHRwb3NpdGlvbltpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmKHRyYWNlLnRleHRwb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIHRyYWNlLnRleHRwb3NpdGlvbiA9IGNsZWFuVGV4dFBvc2l0aW9uKHRyYWNlLnRleHRwb3NpdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmaXggdHlwbyBpbiBjb2xvcnNjYWxlIGRlZmluaXRpb25cbiAgICAgICAgdmFyIF9tb2R1bGUgPSBSZWdpc3RyeS5nZXRNb2R1bGUodHJhY2UpO1xuICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuY29sb3JiYXIpIHtcbiAgICAgICAgICAgIHZhciBjb250YWluZXJOYW1lID0gX21vZHVsZS5jb2xvcmJhci5jb250YWluZXI7XG4gICAgICAgICAgICB2YXIgY29udGFpbmVyID0gY29udGFpbmVyTmFtZSA/IHRyYWNlW2NvbnRhaW5lck5hbWVdIDogdHJhY2U7XG4gICAgICAgICAgICBpZihjb250YWluZXIgJiYgY29udGFpbmVyLmNvbG9yc2NhbGUpIHtcbiAgICAgICAgICAgICAgICBpZihjb250YWluZXIuY29sb3JzY2FsZSA9PT0gJ1lJR25CdScpIGNvbnRhaW5lci5jb2xvcnNjYWxlID0gJ1lsR25CdSc7XG4gICAgICAgICAgICAgICAgaWYoY29udGFpbmVyLmNvbG9yc2NhbGUgPT09ICdZSU9yUmQnKSBjb250YWluZXIuY29sb3JzY2FsZSA9ICdZbE9yUmQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gZml4IHR5cG8gaW4gc3VyZmFjZSAnaGlnaGxpZ2h0KicgZGVmaW5pdGlvbnNcbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ3N1cmZhY2UnICYmIExpYi5pc1BsYWluT2JqZWN0KHRyYWNlLmNvbnRvdXJzKSkge1xuICAgICAgICAgICAgdmFyIGRpbXMgPSBbJ3gnLCAneScsICd6J107XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGRpbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgb3B0cyA9IHRyYWNlLmNvbnRvdXJzW2RpbXNbaV1dO1xuXG4gICAgICAgICAgICAgICAgaWYoIUxpYi5pc1BsYWluT2JqZWN0KG9wdHMpKSBjb250aW51ZTtcblxuICAgICAgICAgICAgICAgIGlmKG9wdHMuaGlnaGxpZ2h0Q29sb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5oaWdobGlnaHRjb2xvciA9IG9wdHMuaGlnaGxpZ2h0Q29sb3I7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBvcHRzLmhpZ2hsaWdodENvbG9yO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKG9wdHMuaGlnaGxpZ2h0V2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgb3B0cy5oaWdobGlnaHR3aWR0aCA9IG9wdHMuaGlnaGxpZ2h0V2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBvcHRzLmhpZ2hsaWdodFdpZHRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGZpeGVzIGZyb20gY29udmVydGluZyBmaW5hbmNlIGZyb20gdHJhbnNmb3JtcyB0byByZWFsIHRyYWNlIHR5cGVzXG4gICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdjYW5kbGVzdGljaycgfHwgdHJhY2UudHlwZSA9PT0gJ29obGMnKSB7XG4gICAgICAgICAgICB2YXIgaW5jcmVhc2luZ1Nob3dsZWdlbmQgPSAodHJhY2UuaW5jcmVhc2luZyB8fCB7fSkuc2hvd2xlZ2VuZCAhPT0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgZGVjcmVhc2luZ1Nob3dsZWdlbmQgPSAodHJhY2UuZGVjcmVhc2luZyB8fCB7fSkuc2hvd2xlZ2VuZCAhPT0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgaW5jcmVhc2luZ05hbWUgPSBjbGVhbkZpbmFuY2VEaXIodHJhY2UuaW5jcmVhc2luZyk7XG4gICAgICAgICAgICB2YXIgZGVjcmVhc2luZ05hbWUgPSBjbGVhbkZpbmFuY2VEaXIodHJhY2UuZGVjcmVhc2luZyk7XG5cbiAgICAgICAgICAgIC8vIG5vdyBmaWd1cmUgb3V0IHNvbWV0aGluZyBzbWFydCB0byBkbyB3aXRoIHRoZSBzZXBhcmF0ZSBkaXJlY3Rpb25cbiAgICAgICAgICAgIC8vIG5hbWVzIHdlIHJlbW92ZWRcbiAgICAgICAgICAgIGlmKChpbmNyZWFzaW5nTmFtZSAhPT0gZmFsc2UpICYmIChkZWNyZWFzaW5nTmFtZSAhPT0gZmFsc2UpKSB7XG4gICAgICAgICAgICAgICAgLy8gYm90aCBzdWItbmFtZXMgZXhpc3RlZDogYmFzZSBuYW1lIHByZXZpb3VzbHkgaGFkIG5vIGVmZmVjdFxuICAgICAgICAgICAgICAgIC8vIHNvIGlnbm9yZSBpdCBhbmQgdHJ5IHRvIGZpbmQgYSBzaGFyZWQgcGFydCBvZiB0aGUgc3ViLW5hbWVzXG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3TmFtZSA9IGNvbW1vblByZWZpeChcbiAgICAgICAgICAgICAgICAgICAgaW5jcmVhc2luZ05hbWUsIGRlY3JlYXNpbmdOYW1lLFxuICAgICAgICAgICAgICAgICAgICBpbmNyZWFzaW5nU2hvd2xlZ2VuZCwgZGVjcmVhc2luZ1Nob3dsZWdlbmRcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIC8vIGlmIG5vIGNvbW1vbiBwYXJ0LCBsZWF2ZSB3aGF0ZXZlciBuYW1lIHdhcyAob3Igd2Fzbid0KSB0aGVyZVxuICAgICAgICAgICAgICAgIGlmKG5ld05hbWUpIHRyYWNlLm5hbWUgPSBuZXdOYW1lO1xuICAgICAgICAgICAgfSBlbHNlIGlmKChpbmNyZWFzaW5nTmFtZSB8fCBkZWNyZWFzaW5nTmFtZSkgJiYgIXRyYWNlLm5hbWUpIHtcbiAgICAgICAgICAgICAgICAvLyBvbmUgc3ViLW5hbWUgZXhpc3RlZCBidXQgbm90IHRoZSBiYXNlIG5hbWUgLSBqdXN0IHVzZSB0aGUgc3ViLW5hbWVcbiAgICAgICAgICAgICAgICB0cmFjZS5uYW1lID0gaW5jcmVhc2luZ05hbWUgfHwgZGVjcmVhc2luZ05hbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmFuc2Zvcm1zIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgZml4ZXNcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh0cmFjZS50cmFuc2Zvcm1zKSkge1xuICAgICAgICAgICAgdmFyIHRyYW5zZm9ybXMgPSB0cmFjZS50cmFuc2Zvcm1zO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCB0cmFuc2Zvcm1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHRyYW5zZm9ybXNbaV07XG5cbiAgICAgICAgICAgICAgICBpZighTGliLmlzUGxhaW5PYmplY3QodHJhbnNmb3JtKSkgY29udGludWU7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2godHJhbnNmb3JtLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZmlsdGVyJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRyYW5zZm9ybS5maWx0ZXJzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0udGFyZ2V0ID0gdHJhbnNmb3JtLmZpbHRlcnNyYztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdHJhbnNmb3JtLmZpbHRlcnNyYztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodHJhbnNmb3JtLmNhbGVuZGFyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoIXRyYW5zZm9ybS52YWx1ZWNhbGVuZGFyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybS52YWx1ZWNhbGVuZGFyID0gdHJhbnNmb3JtLmNhbGVuZGFyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdHJhbnNmb3JtLmNhbGVuZGFyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZ3JvdXBieSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBOYW1lIGhhcyBjaGFuZ2VkIGZyb20gYHN0eWxlYCB0byBgc3R5bGVzYCwgc28gdXNlIGBzdHlsZWAgYnV0IHByZWZlciBgc3R5bGVzYDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybS5zdHlsZXMgPSB0cmFuc2Zvcm0uc3R5bGVzIHx8IHRyYW5zZm9ybS5zdHlsZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodHJhbnNmb3JtLnN0eWxlcyAmJiAhQXJyYXkuaXNBcnJheSh0cmFuc2Zvcm0uc3R5bGVzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcmV2U3R5bGVzID0gdHJhbnNmb3JtLnN0eWxlcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3R5bGVLZXlzID0gT2JqZWN0LmtleXMocHJldlN0eWxlcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0uc3R5bGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IHN0eWxlS2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0uc3R5bGVzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0OiBzdHlsZUtleXNbal0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogcHJldlN0eWxlc1tzdHlsZUtleXNbal1dXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHBydW5lIGVtcHR5IGNvbnRhaW5lcnMgbWFkZSBiZWZvcmUgdGhlIG5ldyBuZXN0ZWRQcm9wZXJ0eVxuICAgICAgICBpZihlbXB0eUNvbnRhaW5lcih0cmFjZSwgJ2xpbmUnKSkgZGVsZXRlIHRyYWNlLmxpbmU7XG4gICAgICAgIGlmKCdtYXJrZXInIGluIHRyYWNlKSB7XG4gICAgICAgICAgICBpZihlbXB0eUNvbnRhaW5lcih0cmFjZS5tYXJrZXIsICdsaW5lJykpIGRlbGV0ZSB0cmFjZS5tYXJrZXIubGluZTtcbiAgICAgICAgICAgIGlmKGVtcHR5Q29udGFpbmVyKHRyYWNlLCAnbWFya2VyJykpIGRlbGV0ZSB0cmFjZS5tYXJrZXI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzYW5pdGl6ZSByZ2IoZnJhY3Rpb25zKSBhbmQgcmdiYShmcmFjdGlvbnMpIHRoYXQgb2xkIHRpbnljb2xvclxuICAgICAgICAvLyBzdXBwb3J0ZWQsIGJ1dCBuZXcgdGlueWNvbG9yIGRvZXMgbm90IGJlY2F1c2UgdGhleSdyZSBub3QgdmFsaWQgY3NzXG4gICAgICAgIENvbG9yLmNsZWFuKHRyYWNlKTtcblxuICAgICAgICAvLyByZW1vdmUgb2Jzb2xldGUgYXV0b2Jpbih4fHkpIGF0dHJpYnV0ZXMsIGJ1dCBvbmx5IGlmIHRydWVcbiAgICAgICAgLy8gaWYgZmFsc2UsIHRoaXMgbmVlZHMgdG8gaGFwcGVuIGluIEhpc3RvZ3JhbS5jYWxjIGJlY2F1c2UgaXRcbiAgICAgICAgLy8gY2FuIGJlIGEgb25lLXRpbWUgYXV0b2JpbiBzbyB3ZSBuZWVkIHRvIGtub3cgdGhlIHJlc3VsdHMgYmVmb3JlXG4gICAgICAgIC8vIHdlIGNhbiBwdXNoIHRoZW0gYmFjayBpbnRvIHRoZSB0cmFjZS5cbiAgICAgICAgaWYodHJhY2UuYXV0b2JpbngpIHtcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5hdXRvYmlueDtcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS54YmlucztcbiAgICAgICAgfVxuICAgICAgICBpZih0cmFjZS5hdXRvYmlueSkge1xuICAgICAgICAgICAgZGVsZXRlIHRyYWNlLmF1dG9iaW55O1xuICAgICAgICAgICAgZGVsZXRlIHRyYWNlLnliaW5zO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xlYW5UaXRsZSh0cmFjZSk7XG4gICAgICAgIGlmKHRyYWNlLmNvbG9yYmFyKSBjbGVhblRpdGxlKHRyYWNlLmNvbG9yYmFyKTtcbiAgICAgICAgaWYodHJhY2UubWFya2VyICYmIHRyYWNlLm1hcmtlci5jb2xvcmJhcikgY2xlYW5UaXRsZSh0cmFjZS5tYXJrZXIuY29sb3JiYXIpO1xuICAgICAgICBpZih0cmFjZS5saW5lICYmIHRyYWNlLmxpbmUuY29sb3JiYXIpIGNsZWFuVGl0bGUodHJhY2UubGluZS5jb2xvcmJhcik7XG4gICAgICAgIGlmKHRyYWNlLmFheGlzKSBjbGVhblRpdGxlKHRyYWNlLmFheGlzKTtcbiAgICAgICAgaWYodHJhY2UuYmF4aXMpIGNsZWFuVGl0bGUodHJhY2UuYmF4aXMpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGNsZWFuRmluYW5jZURpcihkaXJDb250YWluZXIpIHtcbiAgICBpZighTGliLmlzUGxhaW5PYmplY3QoZGlyQ29udGFpbmVyKSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgdmFyIGRpck5hbWUgPSBkaXJDb250YWluZXIubmFtZTtcblxuICAgIGRlbGV0ZSBkaXJDb250YWluZXIubmFtZTtcbiAgICBkZWxldGUgZGlyQ29udGFpbmVyLnNob3dsZWdlbmQ7XG5cbiAgICByZXR1cm4gKHR5cGVvZiBkaXJOYW1lID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgZGlyTmFtZSA9PT0gJ251bWJlcicpICYmIFN0cmluZyhkaXJOYW1lKTtcbn1cblxuZnVuY3Rpb24gY29tbW9uUHJlZml4KG5hbWUxLCBuYW1lMiwgc2hvdzEsIHNob3cyKSB7XG4gICAgLy8gaWYgb25seSBvbmUgaXMgc2hvd24gaW4gdGhlIGxlZ2VuZCwgdXNlIHRoYXRcbiAgICBpZihzaG93MSAmJiAhc2hvdzIpIHJldHVybiBuYW1lMTtcbiAgICBpZihzaG93MiAmJiAhc2hvdzEpIHJldHVybiBuYW1lMjtcblxuICAgIC8vIGlmIGJvdGggb3IgbmVpdGhlciBhcmUgaW4gdGhlIGxlZ2VuZCwgY2hlY2sgaWYgb25lIGlzIGJsYW5rIChvciB3aGl0ZXNwYWNlKVxuICAgIC8vIGFuZCB1c2UgdGhlIG90aGVyIG9uZVxuICAgIC8vIG5vdGUgdGhhdCBob3ZlciBsYWJlbHMgY2FuIHN0aWxsIHVzZSB0aGUgbmFtZSBldmVuIGlmIHRoZSBsZWdlbmQgZG9lc24ndFxuICAgIGlmKCFuYW1lMS50cmltKCkpIHJldHVybiBuYW1lMjtcbiAgICBpZighbmFtZTIudHJpbSgpKSByZXR1cm4gbmFtZTE7XG5cbiAgICB2YXIgbWluTGVuID0gTWF0aC5taW4obmFtZTEubGVuZ3RoLCBuYW1lMi5sZW5ndGgpO1xuICAgIHZhciBpO1xuICAgIGZvcihpID0gMDsgaSA8IG1pbkxlbjsgaSsrKSB7XG4gICAgICAgIGlmKG5hbWUxLmNoYXJBdChpKSAhPT0gbmFtZTIuY2hhckF0KGkpKSBicmVhaztcbiAgICB9XG5cbiAgICB2YXIgb3V0ID0gbmFtZTEuc3Vic3RyKDAsIGkpO1xuICAgIHJldHVybiBvdXQudHJpbSgpO1xufVxuXG4vLyB0ZXh0cG9zaXRpb24gLSBzdXBwb3J0IHBhcnRpYWwgYXR0cmlidXRlcyAoaWUganVzdCAndG9wJylcbi8vIGFuZCBpbmNvcnJlY3QgdXNlIG9mIG1pZGRsZSAvIGNlbnRlciBldGMuXG5mdW5jdGlvbiBjbGVhblRleHRQb3NpdGlvbih0ZXh0cG9zaXRpb24pIHtcbiAgICB2YXIgcG9zWSA9ICdtaWRkbGUnO1xuICAgIHZhciBwb3NYID0gJ2NlbnRlcic7XG5cbiAgICBpZih0eXBlb2YgdGV4dHBvc2l0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgICBpZih0ZXh0cG9zaXRpb24uaW5kZXhPZigndG9wJykgIT09IC0xKSBwb3NZID0gJ3RvcCc7XG4gICAgICAgIGVsc2UgaWYodGV4dHBvc2l0aW9uLmluZGV4T2YoJ2JvdHRvbScpICE9PSAtMSkgcG9zWSA9ICdib3R0b20nO1xuXG4gICAgICAgIGlmKHRleHRwb3NpdGlvbi5pbmRleE9mKCdsZWZ0JykgIT09IC0xKSBwb3NYID0gJ2xlZnQnO1xuICAgICAgICBlbHNlIGlmKHRleHRwb3NpdGlvbi5pbmRleE9mKCdyaWdodCcpICE9PSAtMSkgcG9zWCA9ICdyaWdodCc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBvc1kgKyAnICcgKyBwb3NYO1xufVxuXG5mdW5jdGlvbiBlbXB0eUNvbnRhaW5lcihvdXRlciwgaW5uZXJTdHIpIHtcbiAgICByZXR1cm4gKGlubmVyU3RyIGluIG91dGVyKSAmJlxuICAgICAgICAodHlwZW9mIG91dGVyW2lubmVyU3RyXSA9PT0gJ29iamVjdCcpICYmXG4gICAgICAgIChPYmplY3Qua2V5cyhvdXRlcltpbm5lclN0cl0pLmxlbmd0aCA9PT0gMCk7XG59XG5cblxuLy8gc3dhcCBhbGwgdGhlIGRhdGEgYW5kIGRhdGEgYXR0cmlidXRlcyBhc3NvY2lhdGVkIHdpdGggeCBhbmQgeVxuZXhwb3J0cy5zd2FwWFlEYXRhID0gZnVuY3Rpb24odHJhY2UpIHtcbiAgICB2YXIgaTtcbiAgICBMaWIuc3dhcEF0dHJzKHRyYWNlLCBbJz8nLCAnPzAnLCAnZD8nLCAnP2JpbnMnLCAnbmJpbnM/JywgJ2F1dG9iaW4/JywgJz9zcmMnLCAnZXJyb3JfPyddKTtcbiAgICBpZihBcnJheS5pc0FycmF5KHRyYWNlLnopICYmIEFycmF5LmlzQXJyYXkodHJhY2UuelswXSkpIHtcbiAgICAgICAgaWYodHJhY2UudHJhbnNwb3NlKSBkZWxldGUgdHJhY2UudHJhbnNwb3NlO1xuICAgICAgICBlbHNlIHRyYWNlLnRyYW5zcG9zZSA9IHRydWU7XG4gICAgfVxuICAgIGlmKHRyYWNlLmVycm9yX3ggJiYgdHJhY2UuZXJyb3JfeSkge1xuICAgICAgICB2YXIgZXJyb3JZID0gdHJhY2UuZXJyb3JfeTtcbiAgICAgICAgdmFyIGNvcHlZc3R5bGUgPSAoJ2NvcHlfeXN0eWxlJyBpbiBlcnJvclkpID9cbiAgICAgICAgICAgIGVycm9yWS5jb3B5X3lzdHlsZSA6XG4gICAgICAgICAgICAhKGVycm9yWS5jb2xvciB8fCBlcnJvclkudGhpY2tuZXNzIHx8IGVycm9yWS53aWR0aCk7XG4gICAgICAgIExpYi5zd2FwQXR0cnModHJhY2UsIFsnZXJyb3JfPy5jb3B5X3lzdHlsZSddKTtcbiAgICAgICAgaWYoY29weVlzdHlsZSkge1xuICAgICAgICAgICAgTGliLnN3YXBBdHRycyh0cmFjZSwgWydlcnJvcl8/LmNvbG9yJywgJ2Vycm9yXz8udGhpY2tuZXNzJywgJ2Vycm9yXz8ud2lkdGgnXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYodHlwZW9mIHRyYWNlLmhvdmVyaW5mbyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIGhvdmVySW5mb1BhcnRzID0gdHJhY2UuaG92ZXJpbmZvLnNwbGl0KCcrJyk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGhvdmVySW5mb1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihob3ZlckluZm9QYXJ0c1tpXSA9PT0gJ3gnKSBob3ZlckluZm9QYXJ0c1tpXSA9ICd5JztcbiAgICAgICAgICAgIGVsc2UgaWYoaG92ZXJJbmZvUGFydHNbaV0gPT09ICd5JykgaG92ZXJJbmZvUGFydHNbaV0gPSAneCc7XG4gICAgICAgIH1cbiAgICAgICAgdHJhY2UuaG92ZXJpbmZvID0gaG92ZXJJbmZvUGFydHMuam9pbignKycpO1xuICAgIH1cbn07XG5cbi8vIGNvZXJjZSB0cmFjZUluZGljZXMgaW5wdXQgdG8gYXJyYXkgb2YgdHJhY2UgaW5kaWNlc1xuZXhwb3J0cy5jb2VyY2VUcmFjZUluZGljZXMgPSBmdW5jdGlvbihnZCwgdHJhY2VJbmRpY2VzKSB7XG4gICAgaWYoaXNOdW1lcmljKHRyYWNlSW5kaWNlcykpIHtcbiAgICAgICAgcmV0dXJuIFt0cmFjZUluZGljZXNdO1xuICAgIH0gZWxzZSBpZighQXJyYXkuaXNBcnJheSh0cmFjZUluZGljZXMpIHx8ICF0cmFjZUluZGljZXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBnZC5kYXRhLm1hcChmdW5jdGlvbihfLCBpKSB7IHJldHVybiBpOyB9KTtcbiAgICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheSh0cmFjZUluZGljZXMpKSB7XG4gICAgICAgIHZhciB0cmFjZUluZGljZXNPdXQgPSBbXTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYWNlSW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoTGliLmlzSW5kZXgodHJhY2VJbmRpY2VzW2ldLCBnZC5kYXRhLmxlbmd0aCkpIHtcbiAgICAgICAgICAgICAgICB0cmFjZUluZGljZXNPdXQucHVzaCh0cmFjZUluZGljZXNbaV0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMaWIud2FybigndHJhY2UgaW5kZXggKCcsIHRyYWNlSW5kaWNlc1tpXSwgJykgaXMgbm90IGEgbnVtYmVyIG9yIGlzIG91dCBvZiBib3VuZHMnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJhY2VJbmRpY2VzT3V0O1xuICAgIH1cblxuICAgIHJldHVybiB0cmFjZUluZGljZXM7XG59O1xuXG4vKipcbiAqIE1hbmFnZXMgbG9naWMgYXJvdW5kIGFycmF5IGNvbnRhaW5lciBpdGVtIGNyZWF0aW9uIC8gZGVsZXRpb24gLyB1cGRhdGVcbiAqIHRoYXQgbmVzdGVkIHByb3BlcnR5IGFsb25lIGNhbid0IGhhbmRsZS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gbnBcbiAqICBuZXN0ZWQgcHJvcGVydHkgb2YgdXBkYXRlIGF0dHJpYnV0ZSBzdHJpbmcgYWJvdXQgdHJhY2Ugb3IgbGF5b3V0IG9iamVjdFxuICogQHBhcmFtIHsqfSBuZXdWYWxcbiAqICB1cGRhdGUgdmFsdWUgcGFzc2VkIHRvIHJlc3R5bGUgLyByZWxheW91dCAvIHVwZGF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHVuZG9pdFxuICogIHVuZG8gaGFzaCAoTi5CLiB1bmRvaXQgbWF5IGJlIG11dGF0ZWQgaGVyZSkuXG4gKlxuICovXG5leHBvcnRzLm1hbmFnZUFycmF5Q29udGFpbmVycyA9IGZ1bmN0aW9uKG5wLCBuZXdWYWwsIHVuZG9pdCkge1xuICAgIHZhciBvYmogPSBucC5vYmo7XG4gICAgdmFyIHBhcnRzID0gbnAucGFydHM7XG4gICAgdmFyIHBMZW5ndGggPSBwYXJ0cy5sZW5ndGg7XG4gICAgdmFyIHBMYXN0ID0gcGFydHNbcExlbmd0aCAtIDFdO1xuXG4gICAgdmFyIHBMYXN0SXNOdW1iZXIgPSBpc051bWVyaWMocExhc3QpO1xuXG4gICAgaWYocExhc3RJc051bWJlciAmJiBuZXdWYWwgPT09IG51bGwpIHtcbiAgICAgICAgLy8gZGVsZXRlIGl0ZW1cblxuICAgICAgICAvLyBDbGVhciBpdGVtIGluIGFycmF5IGNvbnRhaW5lciB3aGVuIG5ldyB2YWx1ZSBpcyBudWxsXG4gICAgICAgIHZhciBjb250UGF0aCA9IHBhcnRzLnNsaWNlKDAsIHBMZW5ndGggLSAxKS5qb2luKCcuJyk7XG4gICAgICAgIHZhciBjb250ID0gTGliLm5lc3RlZFByb3BlcnR5KG9iaiwgY29udFBhdGgpLmdldCgpO1xuICAgICAgICBjb250LnNwbGljZShwTGFzdCwgMSk7XG5cbiAgICAgICAgLy8gTm90ZSB0aGF0IG5lc3RlZCBwcm9wZXJ0eSBjbGVhcnMgbnVsbCAvIHVuZGVmaW5lZCBhdCBlbmQgb2ZcbiAgICAgICAgLy8gYXJyYXkgY29udGFpbmVyLCBidXQgbm90IHdpdGhpbiB0aGVtLlxuICAgIH0gZWxzZSBpZihwTGFzdElzTnVtYmVyICYmIG5wLmdldCgpID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gY3JlYXRlIGl0ZW1cblxuICAgICAgICAvLyBXaGVuIGFkZGluZyBhIG5ldyBpdGVtLCBtYWtlIHN1cmUgdW5kbyBjb21tYW5kIHdpbGwgcmVtb3ZlIGl0XG4gICAgICAgIGlmKG5wLmdldCgpID09PSB1bmRlZmluZWQpIHVuZG9pdFtucC5hc3RyXSA9IG51bGw7XG5cbiAgICAgICAgbnAuc2V0KG5ld1ZhbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gdXBkYXRlIGl0ZW1cblxuICAgICAgICAvLyBJZiB0aGUgbGFzdCBwYXJ0IG9mIGF0dHJpYnV0ZSBzdHJpbmcgaXNuJ3QgYSBudW1iZXIsXG4gICAgICAgIC8vIG5wLnNldCBpcyBhbGwgd2UgbmVlZC5cbiAgICAgICAgbnAuc2V0KG5ld1ZhbCk7XG4gICAgfVxufTtcblxuLypcbiAqIE1hdGNoIHRoZSBwYXJ0IHRvIHN0cmlwIG9mZiB0byB0dXJuIGFuIGF0dHJpYnV0ZSBpbnRvIGl0cyBwYXJlbnRcbiAqIHJlYWxseSBpdCBzaG91bGQgYmUgZWl0aGVyICcuc29tZV9jaGFyYWN0ZXJzJyBvciAnW251bWJlcl0nXG4gKiBidXQgd2UncmUgYSBsaXR0bGUgbW9yZSBwZXJtaXNzaXZlIGhlcmUgYW5kIG1hdGNoIGVpdGhlclxuICogJy5ub3RfYnJhY2tldHNfb3JfZG90JyBvciAnW25vdF9icmFja2V0c19vcl9kb3RdJ1xuICovXG52YXIgQVRUUl9UQUlMX1JFID0gLyhcXC5bXlxcW1xcXVxcLl0rfFxcW1teXFxbXFxdXFwuXStcXF0pJC87XG5cbmZ1bmN0aW9uIGdldFBhcmVudChhdHRyKSB7XG4gICAgdmFyIHRhaWwgPSBhdHRyLnNlYXJjaChBVFRSX1RBSUxfUkUpO1xuICAgIGlmKHRhaWwgPiAwKSByZXR1cm4gYXR0ci5zdWJzdHIoMCwgdGFpbCk7XG59XG5cbi8qXG4gKiBoYXNQYXJlbnQ6IGRvZXMgYW4gYXR0cmlidXRlIG9iamVjdCBjb250YWluIGEgcGFyZW50IG9mIHRoZSBnaXZlbiBhdHRyaWJ1dGU/XG4gKiBmb3IgZXhhbXBsZSwgZ2l2ZW4gJ2ltYWdlc1syXS54JyBkbyB3ZSBhbHNvIGhhdmUgJ2ltYWdlcycgb3IgJ2ltYWdlc1syXSc/XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGFvYmpcbiAqICB1cGRhdGUgb2JqZWN0LCB3aG9zZSBrZXlzIGFyZSBhdHRyaWJ1dGUgc3RyaW5ncyBhbmQgdmFsdWVzIGFyZSB0aGVpciBuZXcgc2V0dGluZ3NcbiAqIEBwYXJhbSB7c3RyaW5nfSBhdHRyXG4gKiAgdGhlIGF0dHJpYnV0ZSBzdHJpbmcgdG8gdGVzdCBhZ2FpbnN0XG4gKiBAcmV0dXJucyB7Qm9vbGVhbn1cbiAqICBpcyBhIHBhcmVudCBvZiBhdHRyIHByZXNlbnQgaW4gYW9iaj9cbiAqL1xuZXhwb3J0cy5oYXNQYXJlbnQgPSBmdW5jdGlvbihhb2JqLCBhdHRyKSB7XG4gICAgdmFyIGF0dHJQYXJlbnQgPSBnZXRQYXJlbnQoYXR0cik7XG4gICAgd2hpbGUoYXR0clBhcmVudCkge1xuICAgICAgICBpZihhdHRyUGFyZW50IGluIGFvYmopIHJldHVybiB0cnVlO1xuICAgICAgICBhdHRyUGFyZW50ID0gZ2V0UGFyZW50KGF0dHJQYXJlbnQpO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59O1xuXG4vKipcbiAqIEVtcHR5IG91dCB0eXBlcyBmb3IgYWxsIGF4ZXMgY29udGFpbmluZyB0aGVzZSB0cmFjZXMgc28gd2UgYXV0by1zZXQgdGhlbSBhZ2FpblxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBnZFxuICogQHBhcmFtIHtbaW50ZWdlcl19IHRyYWNlczogdHJhY2UgaW5kaWNlcyB0byBzZWFyY2ggZm9yIGF4ZXMgdG8gY2xlYXIgdGhlIHR5cGVzIG9mXG4gKiBAcGFyYW0ge29iamVjdH0gbGF5b3V0VXBkYXRlOiBhbnkgdXBkYXRlIGJlaW5nIGRvbmUgY29uY3VycmVudGx5IHRvIHRoZSBsYXlvdXQsXG4gKiAgIHdoaWNoIG1heSBzdXBlcmNlZGUgY2xlYXJpbmcgdGhlIGF4aXMgdHlwZXNcbiAqL1xudmFyIGF4TGV0dGVycyA9IFsneCcsICd5JywgJ3onXTtcbmV4cG9ydHMuY2xlYXJBeGlzVHlwZXMgPSBmdW5jdGlvbihnZCwgdHJhY2VzLCBsYXlvdXRVcGRhdGUpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGdkLl9mdWxsRGF0YVtpXTtcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IDM7IGorKykge1xuICAgICAgICAgICAgdmFyIGF4ID0gZ2V0RnJvbVRyYWNlKGdkLCB0cmFjZSwgYXhMZXR0ZXJzW2pdKTtcblxuICAgICAgICAgICAgLy8gZG8gbm90IGNsZWFyIGxvZyB0eXBlIC0gdGhhdCdzIG5ldmVyIGFuIGF1dG8gcmVzdWx0IHNvIG11c3QgaGF2ZSBiZWVuIGludGVudGlvbmFsXG4gICAgICAgICAgICBpZihheCAmJiBheC50eXBlICE9PSAnbG9nJykge1xuICAgICAgICAgICAgICAgIHZhciBheEF0dHIgPSBheC5fbmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgc2NlbmVOYW1lID0gYXguX2lkLnN1YnN0cigxKTtcbiAgICAgICAgICAgICAgICBpZihzY2VuZU5hbWUuc3Vic3RyKDAsIDUpID09PSAnc2NlbmUnKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGxheW91dFVwZGF0ZVtzY2VuZU5hbWVdICE9PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICBheEF0dHIgPSBzY2VuZU5hbWUgKyAnLicgKyBheEF0dHI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciB0eXBlQXR0ciA9IGF4QXR0ciArICcudHlwZSc7XG5cbiAgICAgICAgICAgICAgICBpZihsYXlvdXRVcGRhdGVbYXhBdHRyXSA9PT0gdW5kZWZpbmVkICYmIGxheW91dFVwZGF0ZVt0eXBlQXR0cl0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoZ2QubGF5b3V0LCB0eXBlQXR0cikuc2V0KG51bGwpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uL2xpYlwiOjcxOSxcIi4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkc1wiOjc3MCxcIi4uL3Bsb3RzL3Bsb3RzXCI6ODI4LFwiLi4vcmVnaXN0cnlcIjo4NDcsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNSxcImdsLW1hdDQvZnJvbVF1YXRcIjoyNjJ9XSw3NTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbWFpbiA9IF9kZXJlcV8oJy4vcGxvdF9hcGknKTtcblxuZXhwb3J0cy5wbG90ID0gbWFpbi5wbG90O1xuZXhwb3J0cy5uZXdQbG90ID0gbWFpbi5uZXdQbG90O1xuZXhwb3J0cy5yZXN0eWxlID0gbWFpbi5yZXN0eWxlO1xuZXhwb3J0cy5yZWxheW91dCA9IG1haW4ucmVsYXlvdXQ7XG5leHBvcnRzLnJlZHJhdyA9IG1haW4ucmVkcmF3O1xuZXhwb3J0cy51cGRhdGUgPSBtYWluLnVwZGF0ZTtcbmV4cG9ydHMuX2d1aVJlc3R5bGUgPSBtYWluLl9ndWlSZXN0eWxlO1xuZXhwb3J0cy5fZ3VpUmVsYXlvdXQgPSBtYWluLl9ndWlSZWxheW91dDtcbmV4cG9ydHMuX2d1aVVwZGF0ZSA9IG1haW4uX2d1aVVwZGF0ZTtcbmV4cG9ydHMuX3N0b3JlRGlyZWN0R1VJRWRpdCA9IG1haW4uX3N0b3JlRGlyZWN0R1VJRWRpdDtcbmV4cG9ydHMucmVhY3QgPSBtYWluLnJlYWN0O1xuZXhwb3J0cy5leHRlbmRUcmFjZXMgPSBtYWluLmV4dGVuZFRyYWNlcztcbmV4cG9ydHMucHJlcGVuZFRyYWNlcyA9IG1haW4ucHJlcGVuZFRyYWNlcztcbmV4cG9ydHMuYWRkVHJhY2VzID0gbWFpbi5hZGRUcmFjZXM7XG5leHBvcnRzLmRlbGV0ZVRyYWNlcyA9IG1haW4uZGVsZXRlVHJhY2VzO1xuZXhwb3J0cy5tb3ZlVHJhY2VzID0gbWFpbi5tb3ZlVHJhY2VzO1xuZXhwb3J0cy5wdXJnZSA9IG1haW4ucHVyZ2U7XG5leHBvcnRzLmFkZEZyYW1lcyA9IG1haW4uYWRkRnJhbWVzO1xuZXhwb3J0cy5kZWxldGVGcmFtZXMgPSBtYWluLmRlbGV0ZUZyYW1lcztcbmV4cG9ydHMuYW5pbWF0ZSA9IG1haW4uYW5pbWF0ZTtcbmV4cG9ydHMuc2V0UGxvdENvbmZpZyA9IG1haW4uc2V0UGxvdENvbmZpZztcblxuZXhwb3J0cy50b0ltYWdlID0gX2RlcmVxXygnLi90b19pbWFnZScpO1xuZXhwb3J0cy52YWxpZGF0ZSA9IF9kZXJlcV8oJy4vdmFsaWRhdGUnKTtcbmV4cG9ydHMuZG93bmxvYWRJbWFnZSA9IF9kZXJlcV8oJy4uL3NuYXBzaG90L2Rvd25sb2FkJyk7XG5cbnZhciB0ZW1wbGF0ZUFwaSA9IF9kZXJlcV8oJy4vdGVtcGxhdGVfYXBpJyk7XG5leHBvcnRzLm1ha2VUZW1wbGF0ZSA9IHRlbXBsYXRlQXBpLm1ha2VUZW1wbGF0ZTtcbmV4cG9ydHMudmFsaWRhdGVUZW1wbGF0ZSA9IHRlbXBsYXRlQXBpLnZhbGlkYXRlVGVtcGxhdGU7XG5cbn0se1wiLi4vc25hcHNob3QvZG93bmxvYWRcIjo4NDksXCIuL3Bsb3RfYXBpXCI6NzU0LFwiLi90ZW1wbGF0ZV9hcGlcIjo3NTksXCIuL3RvX2ltYWdlXCI6NzYwLFwiLi92YWxpZGF0ZVwiOjc2MX1dLDc1MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzUGxhaW5PYmplY3QgPSBfZGVyZXFfKCcuLi9saWIvaXNfcGxhaW5fb2JqZWN0Jyk7XG52YXIgbm9vcCA9IF9kZXJlcV8oJy4uL2xpYi9ub29wJyk7XG52YXIgTG9nZ2VycyA9IF9kZXJlcV8oJy4uL2xpYi9sb2dnZXJzJyk7XG52YXIgc29ydGVyQXNjID0gX2RlcmVxXygnLi4vbGliL3NlYXJjaCcpLnNvcnRlckFzYztcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uL3JlZ2lzdHJ5Jyk7XG5cblxuZXhwb3J0cy5jb250YWluZXJBcnJheU1hdGNoID0gX2RlcmVxXygnLi9jb250YWluZXJfYXJyYXlfbWF0Y2gnKTtcblxudmFyIGlzQWRkVmFsID0gZXhwb3J0cy5pc0FkZFZhbCA9IGZ1bmN0aW9uIGlzQWRkVmFsKHZhbCkge1xuICAgIHJldHVybiB2YWwgPT09ICdhZGQnIHx8IGlzUGxhaW5PYmplY3QodmFsKTtcbn07XG5cbnZhciBpc1JlbW92ZVZhbCA9IGV4cG9ydHMuaXNSZW1vdmVWYWwgPSBmdW5jdGlvbiBpc1JlbW92ZVZhbCh2YWwpIHtcbiAgICByZXR1cm4gdmFsID09PSBudWxsIHx8IHZhbCA9PT0gJ3JlbW92ZSc7XG59O1xuXG4vKlxuICogYXBwbHlDb250YWluZXJBcnJheUNoYW5nZXM6IGZvciBtYW5hZ2luZyBhcnJheXMgb2YgbGF5b3V0IGNvbXBvbmVudHMgaW4gcmVsYXlvdXRcbiAqIGhhbmRsZXMgdGhlbSBhbGwgd2l0aCBhIGNvbnNpc3RlbnQgaW50ZXJmYWNlLlxuICpcbiAqIEhlcmUgYXJlIHRoZSBzdXBwb3J0ZWQgYWN0aW9ucyAtPiByZWxheW91dCBjYWxscyAtPiBlZGl0cyB3ZSBnZXQgaGVyZVxuICogKGFzIHByZXBhcmVkIGluIF9yZWxheW91dCk6XG4gKlxuICogYWRkIGFuIGVtcHR5IG9iaiAtPiB7J2Fubm90YXRpb25zWzJdJzogJ2FkZCd9IC0+IHsyOiB7Jyc6ICdhZGQnfX1cbiAqIGFkZCBhIHNwZWNpZmljIG9iaiAtPiB7J2Fubm90YXRpb25zWzJdJzoge2F0dHJzfX0gLT4gezI6IHsnJzoge2F0dHJzfX19XG4gKiBkZWxldGUgYW4gb2JqIC0+IHsnYW5ub3RhdGlvbnNbMl0nOiAncmVtb3ZlJ30gLT4gezI6IHsnJzogJ3JlbW92ZSd9fVxuICogICAgICAgICAgICAgICAtPiB7J2Fubm90YXRpb25zWzJdJzogbnVsbH0gLT4gezI6IHsnJzogbnVsbH19XG4gKiBkZWxldGUgdGhlIHdob2xlIGFycmF5IC0+IHsnYW5ub3RhdGlvbnMnOiAncmVtb3ZlJ30gLT4geycnOiB7Jyc6ICdyZW1vdmUnfX1cbiAqICAgICAgICAgICAgICAgICAgICAgICAgLT4geydhbm5vdGF0aW9ucyc6IG51bGx9IC0+IHsnJzogeycnOiBudWxsfX1cbiAqIGVkaXQgYW4gb2JqZWN0IC0+IHsnYW5ub3RhdGlvbnNbMl0udGV4dCc6ICdib28nfSAtPiB7Mjogeyd0ZXh0JzogJ2Jvbyd9fVxuICpcbiAqIFlvdSBjYW4gY29tYmluZSBtYW55IGVkaXRzIHRvIGRpZmZlcmVudCBvYmplY3RzLiBPYmplY3RzIGFyZSBhZGRlZCBhbmQgZWRpdGVkXG4gKiBpbiBhc2NlbmRpbmcgb3JkZXIsIHRoZW4gcmVtb3ZlZCBpbiBkZXNjZW5kaW5nIG9yZGVyLlxuICogRm9yIGV4YW1wbGUsIHN0YXJ0aW5nIHdpdGggW2EsIGIsIGNdLCBpZiB5b3Ugd2FudCB0bzpcbiAqIC0gcmVwbGFjZSBiIHdpdGggZDpcbiAqICAgeydhbm5vdGF0aW9uc1sxXSc6IGQsICdhbm5vdGF0aW9uc1syXSc6IG51bGx9IChiIGlzIGl0ZW0gMiBhZnRlciBhZGRpbmcgZClcbiAqIC0gYWRkIGEgbmV3IGl0ZW0gZCBiZXR3ZWVuIGEgYW5kIGIsIGFuZCBlZGl0IGI6XG4gKiAgICB7J2Fubm90YXRpb25zWzFdJzogZCwgJ2Fubm90YXRpb25zWzJdLngnOiBuZXdYfSAoYiBpcyBpdGVtIDIgYWZ0ZXIgYWRkaW5nIGQpXG4gKiAtIGRlbGV0ZSBiIGFuZCBlZGl0IGM6XG4gKiAgICB7J2Fubm90YXRpb25zWzFdJzogbnVsbCwgJ2Fubm90YXRpb25zWzJdLngnOiBuZXdYfSAoYyBpcyBlZGl0ZWQgYmVmb3JlIGIgaXMgcmVtb3ZlZClcbiAqXG4gKiBZb3UgQ0FOTk9UIGNvbWJpbmUgYWRkaW5nL2RlbGV0aW5nIGFuIGl0ZW0gYXQgaW5kZXggYGlgIHdpdGggZWRpdHMgdG8gdGhlIHNhbWUgaW5kZXggYGlgXG4gKiBZb3UgQ0FOTk9UIGNvbWJpbmUgcmVwbGFjaW5nL2RlbGV0aW5nIHRoZSB3aG9sZSBhcnJheSB3aXRoIGFueXRoaW5nIGVsc2UgKGZvciB0aGUgc2FtZSBhcnJheSkuXG4gKlxuICogQHBhcmFtIHtIVE1MRGl2RWxlbWVudH0gZ2RcbiAqICB0aGUgRE9NIGVsZW1lbnQgb2YgdGhlIGdyYXBoIGNvbnRhaW5lciBkaXZcbiAqIEBwYXJhbSB7TGliLm5lc3RlZFByb3BlcnR5fSBjb21wb25lbnRUeXBlOiB0aGUgYXJyYXkgd2UgYXJlIGVkaXRpbmdcbiAqIEBwYXJhbSB7T2JqZWN0fSBlZGl0c1xuICogIHRoZSBjaGFuZ2VzIHRvIG1ha2U7IGtleXMgYXJlIGluZGljZXMgdG8gZWRpdCwgdmFsdWVzIGFyZSB0aGVtc2VsdmVzIG9iamVjdHM6XG4gKiAge2F0dHI6IG5ld1ZhbHVlfSBvZiBjaGFuZ2VzIHRvIG1ha2UgdG8gdGhhdCBpbmRleCAod2l0aCBhZGQvcmVtb3ZlIGJlaGF2aW9yXG4gKiAgaW4gc3BlY2lhbCB2YWx1ZXMgb2YgdGhlIGVtcHR5IGF0dHIpXG4gKiBAcGFyYW0ge09iamVjdH0gZmxhZ3NcbiAqICB0aGUgZmxhZ3MgZm9yIHdoaWNoIGFjdGlvbnMgd2UncmUgZ29pbmcgdG8gcGVyZm9ybSB0byBkaXNwbGF5IHRoZXNlIChhbmRcbiAqICBhbnkgb3RoZXIpIGNoYW5nZXMuIElmIHdlJ3JlIGFscmVhZHkgYHJlY2FsY2BpbmcsIHdlIGRvbid0IG5lZWQgdG8gcmVkcmF3XG4gKiAgaW5kaXZpZHVhbCBpdGVtc1xuICogQHBhcmFtIHtmdW5jdGlvbn0gX25lc3RlZFByb3BlcnR5XG4gKiAgYSAocG9zc2libHkgbW9kaWZpZWQgZm9yIGd1aSBlZGl0cykgbmVzdGVkUHJvcGVydHkgY29uc3RydWN0b3JcbiAqICBUaGUgbW9kaWZpZWQgdmVyc2lvbiB0YWtlcyBhIDNyZCBhcmd1bWVudCwgZm9yIGEgcHJlZml4IHRvIHRoZSBhdHRyaWJ1dGVcbiAqICBzdHJpbmcgbmVjZXNzYXJ5IGZvciBzdG9yaW5nIEdVSSBlZGl0c1xuICpcbiAqIEByZXR1cm5zIHtib29sfSBgdHJ1ZWAgaWYgaXQgbWFuYWdlZCB0byBjb21wbGV0ZSBkcmF3aW5nIG9mIHRoZSBjaGFuZ2VzXG4gKiAgYGZhbHNlYCB3b3VsZCBtZWFuIHRoZSBwYXJlbnQgc2hvdWxkIHJlcGxvdC5cbiAqL1xuZXhwb3J0cy5hcHBseUNvbnRhaW5lckFycmF5Q2hhbmdlcyA9IGZ1bmN0aW9uIGFwcGx5Q29udGFpbmVyQXJyYXlDaGFuZ2VzKGdkLCBucCwgZWRpdHMsIGZsYWdzLCBfbmVzdGVkUHJvcGVydHkpIHtcbiAgICB2YXIgY29tcG9uZW50VHlwZSA9IG5wLmFzdHI7XG4gICAgdmFyIHN1cHBseUNvbXBvbmVudERlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKGNvbXBvbmVudFR5cGUsICdzdXBwbHlMYXlvdXREZWZhdWx0cycpO1xuICAgIHZhciBkcmF3ID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKGNvbXBvbmVudFR5cGUsICdkcmF3Jyk7XG4gICAgdmFyIGRyYXdPbmUgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoY29tcG9uZW50VHlwZSwgJ2RyYXdPbmUnKTtcbiAgICB2YXIgcmVwbG90TGF0ZXIgPSBmbGFncy5yZXBsb3QgfHwgZmxhZ3MucmVjYWxjIHx8IChzdXBwbHlDb21wb25lbnREZWZhdWx0cyA9PT0gbm9vcCkgfHwgKGRyYXcgPT09IG5vb3ApO1xuICAgIHZhciBsYXlvdXQgPSBnZC5sYXlvdXQ7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIGlmKGVkaXRzWycnXSkge1xuICAgICAgICBpZihPYmplY3Qua2V5cyhlZGl0cykubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgTG9nZ2Vycy53YXJuKCdGdWxsIGFycmF5IGVkaXRzIGFyZSBpbmNvbXBhdGlibGUgd2l0aCBvdGhlciBlZGl0cycsXG4gICAgICAgICAgICAgICAgY29tcG9uZW50VHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZnVsbFZhbCA9IGVkaXRzWycnXVsnJ107XG5cbiAgICAgICAgaWYoaXNSZW1vdmVWYWwoZnVsbFZhbCkpIG5wLnNldChudWxsKTtcbiAgICAgICAgZWxzZSBpZihBcnJheS5pc0FycmF5KGZ1bGxWYWwpKSBucC5zZXQoZnVsbFZhbCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgTG9nZ2Vycy53YXJuKCdVbnJlY29nbml6ZWQgZnVsbCBhcnJheSBlZGl0IHZhbHVlJywgY29tcG9uZW50VHlwZSwgZnVsbFZhbCk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHJlcGxvdExhdGVyKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgc3VwcGx5Q29tcG9uZW50RGVmYXVsdHMobGF5b3V0LCBmdWxsTGF5b3V0KTtcbiAgICAgICAgZHJhdyhnZCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHZhciBjb21wb25lbnROdW1zID0gT2JqZWN0LmtleXMoZWRpdHMpLm1hcChOdW1iZXIpLnNvcnQoc29ydGVyQXNjKTtcbiAgICB2YXIgY29tcG9uZW50QXJyYXlJbiA9IG5wLmdldCgpO1xuICAgIHZhciBjb21wb25lbnRBcnJheSA9IGNvbXBvbmVudEFycmF5SW4gfHwgW107XG4gICAgLy8gY29tcG9uZW50QXJyYXlGdWxsIGlzIHVzZWQganVzdCB0byBrZWVwIHNwbGljZXMgaW4gbGluZSBiZXR3ZWVuXG4gICAgLy8gZnVsbCBhbmQgaW5wdXQgYXJyYXlzLCBzbyBwcml2YXRlIGtleXMgY2FuIGJlIGNvcGllZCBvdmVyIGFmdGVyXG4gICAgLy8gcmVkb2luZyBzdXBwbHlEZWZhdWx0c1xuICAgIC8vIFRPRE86IHRoaXMgYXNzdW1lcyBjb21wb25lbnRBcnJheSBpcyBpbiBnZC5sYXlvdXQgLSB3aGljaCB3aWxsIG5vdCBiZVxuICAgIC8vIHRydWUgYWZ0ZXIgd2UgZXh0ZW5kIHRoaXMgdG8gcmVzdHlsZVxuICAgIHZhciBjb21wb25lbnRBcnJheUZ1bGwgPSBfbmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgY29tcG9uZW50VHlwZSkuZ2V0KCk7XG5cbiAgICB2YXIgZGVsZXRlcyA9IFtdO1xuICAgIHZhciBmaXJzdEluZGV4Q2hhbmdlID0gLTE7XG4gICAgdmFyIG1heEluZGV4ID0gY29tcG9uZW50QXJyYXkubGVuZ3RoO1xuICAgIHZhciBpO1xuICAgIHZhciBqO1xuICAgIHZhciBjb21wb25lbnROdW07XG4gICAgdmFyIG9iakVkaXRzO1xuICAgIHZhciBvYmpLZXlzO1xuICAgIHZhciBvYmpWYWw7XG4gICAgdmFyIGFkZGluZywgcHJlZml4O1xuXG4gICAgLy8gZmlyc3QgbWFrZSB0aGUgYWRkIGFuZCBlZGl0IGNoYW5nZXNcbiAgICBmb3IoaSA9IDA7IGkgPCBjb21wb25lbnROdW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbXBvbmVudE51bSA9IGNvbXBvbmVudE51bXNbaV07XG4gICAgICAgIG9iakVkaXRzID0gZWRpdHNbY29tcG9uZW50TnVtXTtcbiAgICAgICAgb2JqS2V5cyA9IE9iamVjdC5rZXlzKG9iakVkaXRzKTtcbiAgICAgICAgb2JqVmFsID0gb2JqRWRpdHNbJyddLFxuICAgICAgICBhZGRpbmcgPSBpc0FkZFZhbChvYmpWYWwpO1xuXG4gICAgICAgIGlmKGNvbXBvbmVudE51bSA8IDAgfHwgY29tcG9uZW50TnVtID4gY29tcG9uZW50QXJyYXkubGVuZ3RoIC0gKGFkZGluZyA/IDAgOiAxKSkge1xuICAgICAgICAgICAgTG9nZ2Vycy53YXJuKCdpbmRleCBvdXQgb2YgcmFuZ2UnLCBjb21wb25lbnRUeXBlLCBjb21wb25lbnROdW0pO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZihvYmpWYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYob2JqS2V5cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2Vycy53YXJuKFxuICAgICAgICAgICAgICAgICAgICAnSW5zZXJ0aW9uICYgcmVtb3ZhbCBhcmUgaW5jb21wYXRpYmxlIHdpdGggZWRpdHMgdG8gdGhlIHNhbWUgaW5kZXguJyxcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50VHlwZSwgY29tcG9uZW50TnVtKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaXNSZW1vdmVWYWwob2JqVmFsKSkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZXMucHVzaChjb21wb25lbnROdW0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGFkZGluZykge1xuICAgICAgICAgICAgICAgIGlmKG9ialZhbCA9PT0gJ2FkZCcpIG9ialZhbCA9IHt9O1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudEFycmF5LnNwbGljZShjb21wb25lbnROdW0sIDAsIG9ialZhbCk7XG4gICAgICAgICAgICAgICAgaWYoY29tcG9uZW50QXJyYXlGdWxsKSBjb21wb25lbnRBcnJheUZ1bGwuc3BsaWNlKGNvbXBvbmVudE51bSwgMCwge30pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMb2dnZXJzLndhcm4oJ1VucmVjb2duaXplZCBmdWxsIG9iamVjdCBlZGl0IHZhbHVlJyxcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50VHlwZSwgY29tcG9uZW50TnVtLCBvYmpWYWwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihmaXJzdEluZGV4Q2hhbmdlID09PSAtMSkgZmlyc3RJbmRleENoYW5nZSA9IGNvbXBvbmVudE51bTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG9iaktleXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBwcmVmaXggPSBjb21wb25lbnRUeXBlICsgJ1snICsgY29tcG9uZW50TnVtICsgJ10uJztcbiAgICAgICAgICAgICAgICBfbmVzdGVkUHJvcGVydHkoY29tcG9uZW50QXJyYXlbY29tcG9uZW50TnVtXSwgb2JqS2V5c1tqXSwgcHJlZml4KVxuICAgICAgICAgICAgICAgICAgICAuc2V0KG9iakVkaXRzW29iaktleXNbal1dKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG5vdyBkbyBkZWxldGVzXG4gICAgZm9yKGkgPSBkZWxldGVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGNvbXBvbmVudEFycmF5LnNwbGljZShkZWxldGVzW2ldLCAxKTtcbiAgICAgICAgLy8gVE9ETzogdGhpcyBkcm9wcyBwcml2YXRlIGtleXMgdGhhdCBoYWQgYmVlbiBzdG9yZWQgaW4gY29tcG9uZW50QXJyYXlGdWxsXG4gICAgICAgIC8vIGRvZXMgdGhpcyBoYXZlIGFueSBpbGwgZWZmZWN0cz9cbiAgICAgICAgaWYoY29tcG9uZW50QXJyYXlGdWxsKSBjb21wb25lbnRBcnJheUZ1bGwuc3BsaWNlKGRlbGV0ZXNbaV0sIDEpO1xuICAgIH1cblxuICAgIGlmKCFjb21wb25lbnRBcnJheS5sZW5ndGgpIG5wLnNldChudWxsKTtcbiAgICBlbHNlIGlmKCFjb21wb25lbnRBcnJheUluKSBucC5zZXQoY29tcG9uZW50QXJyYXkpO1xuXG4gICAgaWYocmVwbG90TGF0ZXIpIHJldHVybiBmYWxzZTtcblxuICAgIHN1cHBseUNvbXBvbmVudERlZmF1bHRzKGxheW91dCwgZnVsbExheW91dCk7XG5cbiAgICAvLyBmaW5hbGx5IGRyYXcgYWxsIHRoZSBjb21wb25lbnRzIHdlIG5lZWQgdG9cbiAgICAvLyBpZiB3ZSBhZGRlZCBvciByZW1vdmVkIGFueSwgcmVkcmF3IGFsbCBhZnRlciBpdFxuICAgIGlmKGRyYXdPbmUgIT09IG5vb3ApIHtcbiAgICAgICAgdmFyIGluZGljZXNUb0RyYXc7XG4gICAgICAgIGlmKGZpcnN0SW5kZXhDaGFuZ2UgPT09IC0xKSB7XG4gICAgICAgICAgICAvLyB0aGVyZSdzIG5vIHJlLWluZGV4aW5nIHRvIGRvLCBzbyBvbmx5IHJlZHJhdyBjb21wb25lbnRzIHRoYXQgY2hhbmdlZFxuICAgICAgICAgICAgaW5kaWNlc1RvRHJhdyA9IGNvbXBvbmVudE51bXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBpbiBjYXNlIHRoZSBjb21wb25lbnQgYXJyYXkgd2FzIHNob3J0ZW5lZCwgd2Ugc3RpbGwgbmVlZCBkbyBjYWxsXG4gICAgICAgICAgICAvLyBkcmF3T25lIG9uIHRoZSBsYXR0ZXIgaXRlbXMgc28gdGhleSBnZXQgcHJvcGVybHkgcmVtb3ZlZFxuICAgICAgICAgICAgbWF4SW5kZXggPSBNYXRoLm1heChjb21wb25lbnRBcnJheS5sZW5ndGgsIG1heEluZGV4KTtcbiAgICAgICAgICAgIGluZGljZXNUb0RyYXcgPSBbXTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNvbXBvbmVudE51bXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb21wb25lbnROdW0gPSBjb21wb25lbnROdW1zW2ldO1xuICAgICAgICAgICAgICAgIGlmKGNvbXBvbmVudE51bSA+PSBmaXJzdEluZGV4Q2hhbmdlKSBicmVhaztcbiAgICAgICAgICAgICAgICBpbmRpY2VzVG9EcmF3LnB1c2goY29tcG9uZW50TnVtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvcihpID0gZmlyc3RJbmRleENoYW5nZTsgaSA8IG1heEluZGV4OyBpKyspIHtcbiAgICAgICAgICAgICAgICBpbmRpY2VzVG9EcmF3LnB1c2goaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW5kaWNlc1RvRHJhdy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZHJhd09uZShnZCwgaW5kaWNlc1RvRHJhd1tpXSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgZHJhdyhnZCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbn0se1wiLi4vbGliL2lzX3BsYWluX29iamVjdFwiOjcyMCxcIi4uL2xpYi9sb2dnZXJzXCI6NzIzLFwiLi4vbGliL25vb3BcIjo3MjgsXCIuLi9saWIvc2VhcmNoXCI6NzM4LFwiLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2NvbnRhaW5lcl9hcnJheV9tYXRjaFwiOjc0OX1dLDc1NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcbnZhciBoYXNIb3ZlciA9IF9kZXJlcV8oJ2hhcy1ob3ZlcicpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG52YXIgbmVzdGVkUHJvcGVydHkgPSBMaWIubmVzdGVkUHJvcGVydHk7XG5cbnZhciBFdmVudHMgPSBfZGVyZXFfKCcuLi9saWIvZXZlbnRzJyk7XG52YXIgUXVldWUgPSBfZGVyZXFfKCcuLi9saWIvcXVldWUnKTtcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vcmVnaXN0cnknKTtcbnZhciBQbG90U2NoZW1hID0gX2RlcmVxXygnLi9wbG90X3NjaGVtYScpO1xudmFyIFBsb3RzID0gX2RlcmVxXygnLi4vcGxvdHMvcGxvdHMnKTtcbnZhciBQb2xhciA9IF9kZXJlcV8oJy4uL3Bsb3RzL3BvbGFyL2xlZ2FjeScpO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGluaXRJbnRlcmFjdGlvbnMgPSBfZGVyZXFfKCcuLi9wbG90cy9jYXJ0ZXNpYW4vZ3JhcGhfaW50ZXJhY3QnKS5pbml0SW50ZXJhY3Rpb25zO1xudmFyIHhtbG5zTmFtZXNwYWNlcyA9IF9kZXJlcV8oJy4uL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzJyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gX2RlcmVxXygnLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG52YXIgY2xlYXJTZWxlY3QgPSBfZGVyZXFfKCcuLi9wbG90cy9jYXJ0ZXNpYW4vc2VsZWN0JykuY2xlYXJTZWxlY3Q7XG5cbnZhciBkZmx0Q29uZmlnID0gX2RlcmVxXygnLi9wbG90X2NvbmZpZycpLmRmbHRDb25maWc7XG52YXIgbWFuYWdlQXJyYXlzID0gX2RlcmVxXygnLi9tYW5hZ2VfYXJyYXlzJyk7XG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xudmFyIHN1YnJvdXRpbmVzID0gX2RlcmVxXygnLi9zdWJyb3V0aW5lcycpO1xudmFyIGVkaXRUeXBlcyA9IF9kZXJlcV8oJy4vZWRpdF90eXBlcycpO1xuXG52YXIgQVhfTkFNRV9QQVRURVJOID0gX2RlcmVxXygnLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50cycpLkFYX05BTUVfUEFUVEVSTjtcblxudmFyIG51bWVyaWNOYW1lV2FybmluZ0NvdW50ID0gMDtcbnZhciBudW1lcmljTmFtZVdhcm5pbmdDb3VudExpbWl0ID0gNTtcblxuLyoqXG4gKiBNYWluIHBsb3QtY3JlYXRpb24gZnVuY3Rpb25cbiAqXG4gKiBAcGFyYW0ge3N0cmluZyBpZCBvciBET00gZWxlbWVudH0gZ2RcbiAqICAgICAgdGhlIGlkIG9yIERPTSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKiBAcGFyYW0ge2FycmF5IG9mIG9iamVjdHN9IGRhdGFcbiAqICAgICAgYXJyYXkgb2YgdHJhY2VzLCBjb250YWluaW5nIHRoZSBkYXRhIGFuZCBkaXNwbGF5IGluZm9ybWF0aW9uIGZvciBlYWNoIHRyYWNlXG4gKiBAcGFyYW0ge29iamVjdH0gbGF5b3V0XG4gKiAgICAgIG9iamVjdCBkZXNjcmliaW5nIHRoZSBvdmVyYWxsIGRpc3BsYXkgb2YgdGhlIHBsb3QsXG4gKiAgICAgIGFsbCB0aGUgc3R1ZmYgdGhhdCBkb2Vzbid0IHBlcnRhaW4gdG8gYW55IGluZGl2aWR1YWwgdHJhY2VcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb25maWdcbiAqICAgICAgY29uZmlndXJhdGlvbiBvcHRpb25zIChzZWUgLi9wbG90X2NvbmZpZy5qcyBmb3IgbW9yZSBpbmZvKVxuICpcbiAqIE9SXG4gKlxuICogQHBhcmFtIHtzdHJpbmcgaWQgb3IgRE9NIGVsZW1lbnR9IGdkXG4gKiAgICAgIHRoZSBpZCBvciBET00gZWxlbWVudCBvZiB0aGUgZ3JhcGggY29udGFpbmVyIGRpdlxuICogQHBhcmFtIHtvYmplY3R9IGZpZ3VyZVxuICogICAgICBvYmplY3QgY29udGFpbmluZyBgZGF0YWAsIGBsYXlvdXRgLCBgY29uZmlnYCwgYW5kIGBmcmFtZXNgIG1lbWJlcnNcbiAqXG4gKi9cbmZ1bmN0aW9uIHBsb3QoZ2QsIGRhdGEsIGxheW91dCwgY29uZmlnKSB7XG4gICAgdmFyIGZyYW1lcztcblxuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIC8vIEV2ZW50cy5pbml0IGlzIGlkZW1wb3RlbnQgYW5kIGJhaWxzIGVhcmx5IGlmIGdkIGhhcyBhbHJlYWR5IGJlZW4gaW5pdCdkXG4gICAgRXZlbnRzLmluaXQoZ2QpO1xuXG4gICAgaWYoTGliLmlzUGxhaW5PYmplY3QoZGF0YSkpIHtcbiAgICAgICAgdmFyIG9iaiA9IGRhdGE7XG4gICAgICAgIGRhdGEgPSBvYmouZGF0YTtcbiAgICAgICAgbGF5b3V0ID0gb2JqLmxheW91dDtcbiAgICAgICAgY29uZmlnID0gb2JqLmNvbmZpZztcbiAgICAgICAgZnJhbWVzID0gb2JqLmZyYW1lcztcbiAgICB9XG5cbiAgICB2YXIgb2tUb1Bsb3QgPSBFdmVudHMudHJpZ2dlckhhbmRsZXIoZ2QsICdwbG90bHlfYmVmb3JlcGxvdCcsIFtkYXRhLCBsYXlvdXQsIGNvbmZpZ10pO1xuICAgIGlmKG9rVG9QbG90ID09PSBmYWxzZSkgcmV0dXJuIFByb21pc2UucmVqZWN0KCk7XG5cbiAgICAvLyBpZiB0aGVyZSdzIG5vIGRhdGEgb3IgbGF5b3V0LCBhbmQgdGhpcyBpc24ndCB5ZXQgYSBwbG90bHkgcGxvdFxuICAgIC8vIGNvbnRhaW5lciwgbG9nIGEgd2FybmluZyB0byBoZWxwIHBsb3RseS5qcyB1c2VycyBkZWJ1Z1xuICAgIGlmKCFkYXRhICYmICFsYXlvdXQgJiYgIUxpYi5pc1Bsb3REaXYoZ2QpKSB7XG4gICAgICAgIExpYi53YXJuKCdDYWxsaW5nIFBsb3RseS5wbG90IGFzIGlmIHJlZHJhd2luZyAnICtcbiAgICAgICAgICAgICdidXQgdGhpcyBjb250YWluZXIgZG9lc25cXCd0IHlldCBoYXZlIGEgcGxvdC4nLCBnZCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkRnJhbWVzKCkge1xuICAgICAgICBpZihmcmFtZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBleHBvcnRzLmFkZEZyYW1lcyhnZCwgZnJhbWVzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRyYW5zZmVyIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byBnZCB1bnRpbCB3ZSBtb3ZlIG92ZXIgdG9cbiAgICAvLyBhIG1vcmUgT08gbGlrZSBtb2RlbFxuICAgIHNldFBsb3RDb250ZXh0KGdkLCBjb25maWcpO1xuXG4gICAgaWYoIWxheW91dCkgbGF5b3V0ID0ge307XG5cbiAgICAvLyBob29rIGNsYXNzIGZvciBwbG90cyBtYWluIGNvbnRhaW5lciAoaW4gY2FzZSBvZiBwbG90bHkuanNcbiAgICAvLyB0aGlzIHdvbid0IGJlICNlbWJlZGRlZC1ncmFwaCBvciAuanMtdGFiLWNvbnRlbnRzKVxuICAgIGQzLnNlbGVjdChnZCkuY2xhc3NlZCgnanMtcGxvdGx5LXBsb3QnLCB0cnVlKTtcblxuICAgIC8vIG9mZi1zY3JlZW4gZ2V0Qm91bmRpbmdDbGllbnRSZWN0IHRlc3Rpbmcgc3BhY2UsXG4gICAgLy8gaW4gI2pzLXBsb3RseS10ZXN0ZXIgKGFuZCBzdG9yZWQgYXMgRHJhd2luZy50ZXN0ZXIpXG4gICAgLy8gc28gd2UgY2FuIHNoYXJlIGNhY2hlZCB0ZXh0IGFjcm9zcyB0YWJzXG4gICAgRHJhd2luZy5tYWtlVGVzdGVyKCk7XG5cbiAgICAvLyBjb2xsZWN0IHByb21pc2VzIGZvciBhbnkgYXN5bmMgYWN0aW9ucyBkdXJpbmcgcGxvdHRpbmdcbiAgICAvLyBhbnkgcGFydCBvZiB0aGUgcGxvdHRpbmcgY29kZSBjYW4gcHVzaCB0byBnZC5fcHJvbWlzZXMsIHRoZW5cbiAgICAvLyBiZWZvcmUgd2UgbW92ZSB0byB0aGUgbmV4dCBzdGVwLCB3ZSBjaGVjayB0aGF0IHRoZXkncmUgYWxsXG4gICAgLy8gY29tcGxldGUsIGFuZCBlbXB0eSBvdXQgdGhlIHByb21pc2UgbGlzdCBhZ2Fpbi5cbiAgICBpZighQXJyYXkuaXNBcnJheShnZC5fcHJvbWlzZXMpKSBnZC5fcHJvbWlzZXMgPSBbXTtcblxuICAgIHZhciBncmFwaFdhc0VtcHR5ID0gKChnZC5kYXRhIHx8IFtdKS5sZW5ndGggPT09IDAgJiYgQXJyYXkuaXNBcnJheShkYXRhKSk7XG5cbiAgICAvLyBpZiB0aGVyZSBpcyBhbHJlYWR5IGRhdGEgb24gdGhlIGdyYXBoLCBhcHBlbmQgdGhlIG5ldyBkYXRhXG4gICAgLy8gaWYgeW91IG9ubHkgd2FudCB0byByZWRyYXcsIHBhc3MgYSBub24tYXJyYXkgZm9yIGRhdGFcbiAgICBpZihBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgICAgIGhlbHBlcnMuY2xlYW5EYXRhKGRhdGEpO1xuXG4gICAgICAgIGlmKGdyYXBoV2FzRW1wdHkpIGdkLmRhdGEgPSBkYXRhO1xuICAgICAgICBlbHNlIGdkLmRhdGEucHVzaC5hcHBseShnZC5kYXRhLCBkYXRhKTtcblxuICAgICAgICAvLyBmb3Igcm91dGluZXMgb3V0c2lkZSBncmFwaF9vYmogdGhhdCB3YW50IGEgY2xlYW4gdGFiXG4gICAgICAgIC8vIChyYXRoZXIgdGhhbiBhcHBlbmRpbmcgdG8gYW4gZXhpc3Rpbmcgb25lKSBnZC5lbXB0eVxuICAgICAgICAvLyBpcyB1c2VkIHRvIGRldGVybWluZSB3aGV0aGVyIHRvIG1ha2UgYSBuZXcgdGFiXG4gICAgICAgIGdkLmVtcHR5ID0gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYoIWdkLmxheW91dCB8fCBncmFwaFdhc0VtcHR5KSB7XG4gICAgICAgIGdkLmxheW91dCA9IGhlbHBlcnMuY2xlYW5MYXlvdXQobGF5b3V0KTtcbiAgICB9XG5cbiAgICBQbG90cy5zdXBwbHlEZWZhdWx0cyhnZCk7XG5cbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBoYXNDYXJ0ZXNpYW4gPSBmdWxsTGF5b3V0Ll9oYXMoJ2NhcnRlc2lhbicpO1xuXG4gICAgLy8gTGVnYWN5IHBvbGFyIHBsb3RzXG4gICAgaWYoIWZ1bGxMYXlvdXQuX2hhcygncG9sYXInKSAmJiBkYXRhICYmIGRhdGFbMF0gJiYgZGF0YVswXS5yKSB7XG4gICAgICAgIExpYi5sb2coJ0xlZ2FjeSBwb2xhciBjaGFydHMgYXJlIGRlcHJlY2F0ZWQhJyk7XG4gICAgICAgIHJldHVybiBwbG90TGVnYWN5UG9sYXIoZ2QsIGRhdGEsIGxheW91dCk7XG4gICAgfVxuXG4gICAgLy8gc28gd2UgZG9uJ3QgdHJ5IHRvIHJlLWNhbGwgUGxvdGx5LnBsb3QgZnJvbSBpbnNpZGVcbiAgICAvLyBsZWdlbmQgYW5kIGNvbG9yYmFyLCBpZiBtYXJnaW5zIGNoYW5nZWRcbiAgICBmdWxsTGF5b3V0Ll9yZXBsb3R0aW5nID0gdHJ1ZTtcblxuICAgIC8vIG1ha2Ugb3IgcmVtYWtlIHRoZSBmcmFtZXdvcmsgaWYgd2UgbmVlZCB0b1xuICAgIGlmKGdyYXBoV2FzRW1wdHkpIG1ha2VQbG90RnJhbWV3b3JrKGdkKTtcblxuICAgIC8vIHBvbGFyIG5lZWQgYSBkaWZmZXJlbnQgZnJhbWV3b3JrXG4gICAgaWYoZ2QuZnJhbWV3b3JrICE9PSBtYWtlUGxvdEZyYW1ld29yaykge1xuICAgICAgICBnZC5mcmFtZXdvcmsgPSBtYWtlUGxvdEZyYW1ld29yaztcbiAgICAgICAgbWFrZVBsb3RGcmFtZXdvcmsoZ2QpO1xuICAgIH1cblxuICAgIC8vIGNsZWFyIGdyYWRpZW50IGRlZnMgb24gZWFjaCAucGxvdCBjYWxsLCBiZWNhdXNlIHdlIGtub3cgd2UnbGwgbG9vcCB0aHJvdWdoIGFsbCB0cmFjZXNcbiAgICBEcmF3aW5nLmluaXRHcmFkaWVudHMoZ2QpO1xuXG4gICAgLy8gc2F2ZSBpbml0aWFsIHNob3cgc3Bpa2VzIG9uY2UgcGVyIGdyYXBoXG4gICAgaWYoZ3JhcGhXYXNFbXB0eSkgQXhlcy5zYXZlU2hvd1NwaWtlSW5pdGlhbChnZCk7XG5cbiAgICAvLyBwcmVwYXJlIHRoZSBkYXRhIGFuZCBmaW5kIHRoZSBhdXRvcmFuZ2VcblxuICAgIC8vIGdlbmVyYXRlIGNhbGNkYXRhLCBpZiB3ZSBuZWVkIHRvXG4gICAgLy8gdG8gZm9yY2UgcmVkb2luZyBjYWxjZGF0YSwganVzdCBkZWxldGUgaXQgYmVmb3JlIGNhbGxpbmcgUGxvdGx5LnBsb3RcbiAgICB2YXIgcmVjYWxjID0gIWdkLmNhbGNkYXRhIHx8IGdkLmNhbGNkYXRhLmxlbmd0aCAhPT0gKGdkLl9mdWxsRGF0YSB8fCBbXSkubGVuZ3RoO1xuICAgIGlmKHJlY2FsYykgUGxvdHMuZG9DYWxjZGF0YShnZCk7XG5cbiAgICAvLyBpbiBjYXNlIGl0IGhhcyBjaGFuZ2VkLCBhdHRhY2ggZnVsbERhdGEgdHJhY2VzIHRvIGNhbGNkYXRhXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGdkLmNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGdkLmNhbGNkYXRhW2ldWzBdLnRyYWNlID0gZ2QuX2Z1bGxEYXRhW2ldO1xuICAgIH1cblxuICAgIC8vIG1ha2UgdGhlIGZpZ3VyZSByZXNwb25zaXZlXG4gICAgaWYoZ2QuX2NvbnRleHQucmVzcG9uc2l2ZSkge1xuICAgICAgICBpZighZ2QuX3Jlc3BvbnNpdmVDaGFydEhhbmRsZXIpIHtcbiAgICAgICAgICAgIC8vIEtlZXAgYSByZWZlcmVuY2UgdG8gdGhlIHJlc2l6ZSBoYW5kbGVyIHRvIHB1cmdlIGl0IGRvd24gdGhlIHJvYWRcbiAgICAgICAgICAgIGdkLl9yZXNwb25zaXZlQ2hhcnRIYW5kbGVyID0gZnVuY3Rpb24oKSB7IGlmKCFMaWIuaXNIaWRkZW4oZ2QpKSBQbG90cy5yZXNpemUoZ2QpOyB9O1xuXG4gICAgICAgICAgICAvLyBMaXN0ZW4gdG8gd2luZG93IHJlc2l6ZVxuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIGdkLl9yZXNwb25zaXZlQ2hhcnRIYW5kbGVyKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIExpYi5jbGVhclJlc3BvbnNpdmUoZ2QpO1xuICAgIH1cblxuICAgIC8qXG4gICAgICogc3RhcnQgYXN5bmMtZnJpZW5kbHkgY29kZSAtIG5vdyB3ZSdyZSBhY3R1YWxseSBkcmF3aW5nIHRoaW5nc1xuICAgICAqL1xuXG4gICAgdmFyIG9sZE1hcmdpbnMgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgZnVsbExheW91dC5fc2l6ZSk7XG5cbiAgICAvLyBkcmF3IGZyYW1ld29yayBmaXJzdCBzbyB0aGF0IG1hcmdpbi1wdXNoaW5nXG4gICAgLy8gY29tcG9uZW50cyBjYW4gcG9zaXRpb24gdGhlbXNlbHZlcyBjb3JyZWN0bHlcbiAgICB2YXIgZHJhd0ZyYW1ld29ya0NhbGxzID0gMDtcbiAgICBmdW5jdGlvbiBkcmF3RnJhbWV3b3JrKCkge1xuICAgICAgICB2YXIgYmFzZVBsb3RNb2R1bGVzID0gZnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzO1xuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBiYXNlUGxvdE1vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGJhc2VQbG90TW9kdWxlc1tpXS5kcmF3RnJhbWV3b3JrKSB7XG4gICAgICAgICAgICAgICAgYmFzZVBsb3RNb2R1bGVzW2ldLmRyYXdGcmFtZXdvcmsoZ2QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWZ1bGxMYXlvdXQuX2dsY2FudmFzICYmIGZ1bGxMYXlvdXQuX2hhcygnZ2wnKSkge1xuICAgICAgICAgICAgZnVsbExheW91dC5fZ2xjYW52YXMgPSBmdWxsTGF5b3V0Ll9nbGNvbnRhaW5lci5zZWxlY3RBbGwoJy5nbC1jYW52YXMnKS5kYXRhKFt7XG4gICAgICAgICAgICAgICAga2V5OiAnY29udGV4dExheWVyJyxcbiAgICAgICAgICAgICAgICBjb250ZXh0OiB0cnVlLFxuICAgICAgICAgICAgICAgIHBpY2s6IGZhbHNlXG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAga2V5OiAnZm9jdXNMYXllcicsXG4gICAgICAgICAgICAgICAgY29udGV4dDogZmFsc2UsXG4gICAgICAgICAgICAgICAgcGljazogZmFsc2VcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICBrZXk6ICdwaWNrTGF5ZXInLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHBpY2s6IHRydWVcbiAgICAgICAgICAgIH1dLCBmdW5jdGlvbihkKSB7IHJldHVybiBkLmtleTsgfSk7XG5cbiAgICAgICAgICAgIGZ1bGxMYXlvdXQuX2dsY2FudmFzLmVudGVyKCkuYXBwZW5kKCdjYW52YXMnKVxuICAgICAgICAgICAgICAgIC5hdHRyKCdjbGFzcycsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdnbC1jYW52YXMgZ2wtY2FudmFzLScgKyBkLmtleS5yZXBsYWNlKCdMYXllcicsICcnKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgICAgICAgICAgICAgICAgICB0b3A6IDAsXG4gICAgICAgICAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICAgICAgICAgIG92ZXJmbG93OiAndmlzaWJsZScsXG4gICAgICAgICAgICAgICAgICAgICdwb2ludGVyLWV2ZW50cyc6ICdub25lJ1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZnVsbExheW91dC5fZ2xjYW52YXMpIHtcbiAgICAgICAgICAgIGZ1bGxMYXlvdXQuX2dsY2FudmFzXG4gICAgICAgICAgICAgICAgLmF0dHIoJ3dpZHRoJywgZnVsbExheW91dC53aWR0aClcbiAgICAgICAgICAgICAgICAuYXR0cignaGVpZ2h0JywgZnVsbExheW91dC5oZWlnaHQpO1xuXG4gICAgICAgICAgICB2YXIgcmVnbCA9IGZ1bGxMYXlvdXQuX2dsY2FudmFzLmRhdGEoKVswXS5yZWdsO1xuICAgICAgICAgICAgaWYocmVnbCkge1xuICAgICAgICAgICAgICAgIC8vIFVuZm9ydHVuYXRlbHksIHRoaXMgY2FuIGhhcHBlbiB3aGVuIHJlbGF5b3V0aW5nIHRvIGxhcmdlXG4gICAgICAgICAgICAgICAgLy8gd2lkdGgvaGVpZ2h0IG9uIHNvbWUgYnJvd3NlcnMuXG4gICAgICAgICAgICAgICAgaWYoTWF0aC5mbG9vcihmdWxsTGF5b3V0LndpZHRoKSAhPT0gcmVnbC5fZ2wuZHJhd2luZ0J1ZmZlcldpZHRoIHx8XG4gICAgICAgICAgICAgICAgICAgIE1hdGguZmxvb3IoZnVsbExheW91dC5oZWlnaHQpICE9PSByZWdsLl9nbC5kcmF3aW5nQnVmZmVySGVpZ2h0XG4gICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbXNnID0gJ1dlYkdMIGNvbnRleHQgYnVmZmVyIGFuZCBjYW52YXMgZGltZW5zaW9ucyBkbyBub3QgbWF0Y2ggZHVlIHRvIGJyb3dzZXIvV2ViR0wgYnVnLic7XG4gICAgICAgICAgICAgICAgICAgIGlmKGRyYXdGcmFtZXdvcmtDYWxscykge1xuICAgICAgICAgICAgICAgICAgICAgICAgTGliLmVycm9yKG1zZyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBMaWIubG9nKG1zZyArICcgQ2xlYXJpbmcgZ3JhcGggYW5kIHBsb3R0aW5nIGFnYWluLicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgUGxvdHMuY2xlYW5QbG90KFtdLCB7fSwgZ2QuX2Z1bGxEYXRhLCBmdWxsTGF5b3V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFBsb3RzLnN1cHBseURlZmF1bHRzKGdkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICAgICAgICAgICAgICAgICAgICAgIFBsb3RzLmRvQ2FsY2RhdGEoZ2QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZHJhd0ZyYW1ld29ya0NhbGxzKys7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZHJhd0ZyYW1ld29yaygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoZnVsbExheW91dC5tb2RlYmFyLm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgICAgIGZ1bGxMYXlvdXQuX21vZGViYXJkaXZcbiAgICAgICAgICAgICAgLnN0eWxlKCdoZWlnaHQnLCBudWxsKVxuICAgICAgICAgICAgICAuc3R5bGUoJ3dpZHRoJywgJzEwMCUnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZ1bGxMYXlvdXQuX21vZGViYXJkaXZcbiAgICAgICAgICAgICAgLnN0eWxlKCd3aWR0aCcsIG51bGwpXG4gICAgICAgICAgICAgIC5zdHlsZSgnaGVpZ2h0JywgZnVsbExheW91dC5oZWlnaHQgKyAncHgnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQbG90cy5wcmV2aW91c1Byb21pc2VzKGdkKTtcbiAgICB9XG5cbiAgICAvLyBkcmF3IGFueXRoaW5nIHRoYXQgY2FuIGFmZmVjdCBtYXJnaW5zLlxuICAgIGZ1bmN0aW9uIG1hcmdpblB1c2hlcnMoKSB7XG4gICAgICAgIC8vIEZpcnN0IHJlc2V0IHRoZSBsaXN0IG9mIHRoaW5ncyB0aGF0IGFyZSBhbGxvd2VkIHRvIGNoYW5nZSB0aGUgbWFyZ2luc1xuICAgICAgICAvLyBTbyBhbnkgZGVsZXRlZCB0cmFjZXMgb3IgY29tcG9uZW50cyB3aWxsIGJlIHdpcGVkIG91dCBvZiB0aGVcbiAgICAgICAgLy8gYXV0b21hcmdpbiBjYWxjdWxhdGlvbi5cbiAgICAgICAgLy8gVGhpcyBtZWFucyAqZXZlcnkqIG1hcmdpbiBwdXNoZXIgbXVzdCBiZSBsaXN0ZWQgaGVyZSwgZXZlbiBpZiBpdFxuICAgICAgICAvLyBkb2Vzbid0IGFjdHVhbGx5IHRyeSB0byBwdXNoIHRoZSBtYXJnaW5zIHVudGlsIGxhdGVyLlxuICAgICAgICBQbG90cy5jbGVhckF1dG9NYXJnaW5JZHMoZ2QpO1xuXG4gICAgICAgIHN1YnJvdXRpbmVzLmRyYXdNYXJnaW5QdXNoZXJzKGdkKTtcbiAgICAgICAgQXhlcy5hbGxvd0F1dG9NYXJnaW4oZ2QpO1xuXG4gICAgICAgIFBsb3RzLmRvQXV0b01hcmdpbihnZCk7XG4gICAgICAgIHJldHVybiBQbG90cy5wcmV2aW91c1Byb21pc2VzKGdkKTtcbiAgICB9XG5cbiAgICAvLyBpbiBjYXNlIHRoZSBtYXJnaW5zIGNoYW5nZWQsIGRyYXcgbWFyZ2luIHB1c2hlcnMgYWdhaW5cbiAgICBmdW5jdGlvbiBtYXJnaW5QdXNoZXJzQWdhaW4oKSB7XG4gICAgICAgIGlmKCFQbG90cy5kaWRNYXJnaW5DaGFuZ2Uob2xkTWFyZ2lucywgZnVsbExheW91dC5fc2l6ZSkpIHJldHVybjtcblxuICAgICAgICByZXR1cm4gTGliLnN5bmNPckFzeW5jKFtcbiAgICAgICAgICAgIG1hcmdpblB1c2hlcnMsXG4gICAgICAgICAgICBzdWJyb3V0aW5lcy5sYXlvdXRTdHlsZXNcbiAgICAgICAgXSwgZ2QpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBvc2l0aW9uQW5kQXV0b3JhbmdlKCkge1xuICAgICAgICBpZighcmVjYWxjKSB7XG4gICAgICAgICAgICBkb0F1dG9SYW5nZUFuZENvbnN0cmFpbnRzKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPOiBhdXRvc2l6ZSBleHRyYSBmb3IgdGV4dCBtYXJrZXJzIGFuZCBpbWFnZXNcbiAgICAgICAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy8xMTExXG4gICAgICAgIHJldHVybiBMaWIuc3luY09yQXN5bmMoW1xuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdzaGFwZXMnLCAnY2FsY0F1dG9yYW5nZScpLFxuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdhbm5vdGF0aW9ucycsICdjYWxjQXV0b3JhbmdlJyksXG4gICAgICAgICAgICBkb0F1dG9SYW5nZUFuZENvbnN0cmFpbnRzXG4gICAgICAgIF0sIGdkKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkb0F1dG9SYW5nZUFuZENvbnN0cmFpbnRzKCkge1xuICAgICAgICBpZihnZC5fdHJhbnNpdGlvbmluZykgcmV0dXJuO1xuXG4gICAgICAgIHN1YnJvdXRpbmVzLmRvQXV0b1JhbmdlQW5kQ29uc3RyYWludHMoZ2QpO1xuXG4gICAgICAgIC8vIHN0b3JlIGluaXRpYWwgcmFuZ2VzICphZnRlciogZW5mb3JjaW5nIGNvbnN0cmFpbnRzLCBvdGhlcndpc2VcbiAgICAgICAgLy8gd2Ugd2lsbCBuZXZlciBsb29rIGxpa2Ugd2UncmUgYXQgdGhlIGluaXRpYWwgcmFuZ2VzXG4gICAgICAgIGlmKGdyYXBoV2FzRW1wdHkpIEF4ZXMuc2F2ZVJhbmdlSW5pdGlhbChnZCk7XG5cbiAgICAgICAgLy8gdGhpcyBvbmUgaXMgZGlmZmVyZW50IGZyb20gc2hhcGVzL2Fubm90YXRpb25zIGNhbGNBdXRvcmFuZ2VcbiAgICAgICAgLy8gdGhlIG90aGVycyBpbmNvcnBvcmF0ZSB0aG9zZSBjb21wb25lbnRzIGludG8gYXguX2V4dHJlbWVzLFxuICAgICAgICAvLyB0aGlzIG9uZSBhY3R1YWxseSBzZXRzIHRoZSByYW5nZXMgaW4gcmFuZ2VzbGlkZXJzLlxuICAgICAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ3Jhbmdlc2xpZGVyJywgJ2NhbGNBdXRvcmFuZ2UnKShnZCk7XG4gICAgfVxuXG4gICAgLy8gZHJhdyB0aWNrcywgdGl0bGVzLCBhbmQgY2FsY3VsYXRlIGF4aXMgc2NhbGluZyAoLl9iLCAuX20pXG4gICAgZnVuY3Rpb24gZHJhd0F4ZXMoKSB7XG4gICAgICAgIHJldHVybiBBeGVzLmRyYXcoZ2QsIGdyYXBoV2FzRW1wdHkgPyAnJyA6ICdyZWRyYXcnKTtcbiAgICB9XG5cbiAgICB2YXIgc2VxID0gW1xuICAgICAgICBQbG90cy5wcmV2aW91c1Byb21pc2VzLFxuICAgICAgICBhZGRGcmFtZXMsXG4gICAgICAgIGRyYXdGcmFtZXdvcmssXG4gICAgICAgIG1hcmdpblB1c2hlcnMsXG4gICAgICAgIG1hcmdpblB1c2hlcnNBZ2FpblxuICAgIF07XG5cbiAgICBpZihoYXNDYXJ0ZXNpYW4pIHNlcS5wdXNoKHBvc2l0aW9uQW5kQXV0b3JhbmdlKTtcblxuICAgIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmxheW91dFN0eWxlcyk7XG4gICAgaWYoaGFzQ2FydGVzaWFuKSBzZXEucHVzaChkcmF3QXhlcyk7XG5cbiAgICBzZXEucHVzaChcbiAgICAgICAgc3Vicm91dGluZXMuZHJhd0RhdGEsXG4gICAgICAgIHN1YnJvdXRpbmVzLmZpbmFsRHJhdyxcbiAgICAgICAgaW5pdEludGVyYWN0aW9ucyxcbiAgICAgICAgUGxvdHMuYWRkTGlua3MsXG4gICAgICAgIFBsb3RzLnJlaG92ZXIsXG4gICAgICAgIFBsb3RzLnJlZHJhZyxcbiAgICAgICAgLy8gVE9ETzogZG9BdXRvTWFyZ2luIGlzIG9ubHkgbmVlZGVkIGhlcmUgZm9yIGF4aXMgYXV0b21hcmdpbiwgd2hpY2hcbiAgICAgICAgLy8gaGFwcGVucyBvdXRzaWRlIG9mIG1hcmdpblB1c2hlcnMgd2hlcmUgYWxsIHRoZSBvdGhlciBhdXRvbWFyZ2lucyBhcmVcbiAgICAgICAgLy8gY2FsY3VsYXRlZC4gV291bGQgYmUgbXVjaCBiZXR0ZXIgdG8gc2VwYXJhdGUgbWFyZ2luIGNhbGN1bGF0aW9ucyBmcm9tXG4gICAgICAgIC8vIGNvbXBvbmVudCBkcmF3aW5nIC0gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy8yNzA0XG4gICAgICAgIFBsb3RzLmRvQXV0b01hcmdpbixcbiAgICAgICAgUGxvdHMucHJldmlvdXNQcm9taXNlc1xuICAgICk7XG5cbiAgICAvLyBldmVuIGlmIGV2ZXJ5dGhpbmcgd2UgZGlkIHdhcyBzeW5jaHJvbm91cywgcmV0dXJuIGEgcHJvbWlzZVxuICAgIC8vIHNvIHRoYXQgdGhlIGNhbGxlciBkb2Vzbid0IGNhcmUgd2hpY2ggcm91dGUgd2UgdG9va1xuICAgIHZhciBwbG90RG9uZSA9IExpYi5zeW5jT3JBc3luYyhzZXEsIGdkKTtcbiAgICBpZighcGxvdERvbmUgfHwgIXBsb3REb25lLnRoZW4pIHBsb3REb25lID0gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgICByZXR1cm4gcGxvdERvbmUudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgZW1pdEFmdGVyUGxvdChnZCk7XG4gICAgICAgIHJldHVybiBnZDtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZW1pdEFmdGVyUGxvdChnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBpZihmdWxsTGF5b3V0Ll9yZWRyYXdGcm9tQXV0b01hcmdpbkNvdW50KSB7XG4gICAgICAgIGZ1bGxMYXlvdXQuX3JlZHJhd0Zyb21BdXRvTWFyZ2luQ291bnQtLTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfYWZ0ZXJwbG90Jyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzZXRQbG90Q29uZmlnKG9iaikge1xuICAgIHJldHVybiBMaWIuZXh0ZW5kRmxhdChkZmx0Q29uZmlnLCBvYmopO1xufVxuXG5mdW5jdGlvbiBzZXRCYWNrZ3JvdW5kKGdkLCBiZ0NvbG9yKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX3BhcGVyLnN0eWxlKCdiYWNrZ3JvdW5kJywgYmdDb2xvcik7XG4gICAgfSBjYXRjaChlKSB7XG4gICAgICAgIExpYi5lcnJvcihlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIG9wYXF1ZVNldEJhY2tncm91bmQoZ2QsIGJnQ29sb3IpIHtcbiAgICB2YXIgYmxlbmQgPSBDb2xvci5jb21iaW5lKGJnQ29sb3IsICd3aGl0ZScpO1xuICAgIHNldEJhY2tncm91bmQoZ2QsIGJsZW5kKTtcbn1cblxuZnVuY3Rpb24gc2V0UGxvdENvbnRleHQoZ2QsIGNvbmZpZykge1xuICAgIGlmKCFnZC5fY29udGV4dCkge1xuICAgICAgICBnZC5fY29udGV4dCA9IExpYi5leHRlbmREZWVwKHt9LCBkZmx0Q29uZmlnKTtcblxuICAgICAgICAvLyBzdGFzaCA8YmFzZT4gaHJlZiwgdXNlZCB0byBtYWtlIHJvYnVzdCBjbGlwUGF0aCBVUkxzXG4gICAgICAgIHZhciBiYXNlID0gZDMuc2VsZWN0KCdiYXNlJyk7XG4gICAgICAgIGdkLl9jb250ZXh0Ll9iYXNlVXJsID0gYmFzZS5zaXplKCkgJiYgYmFzZS5hdHRyKCdocmVmJykgP1xuICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYuc3BsaXQoJyMnKVswXSA6XG4gICAgICAgICAgICAnJztcbiAgICB9XG5cbiAgICB2YXIgY29udGV4dCA9IGdkLl9jb250ZXh0O1xuXG4gICAgdmFyIGksIGtleXMsIGtleTtcblxuICAgIGlmKGNvbmZpZykge1xuICAgICAgICBrZXlzID0gT2JqZWN0LmtleXMoY29uZmlnKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICAgIGlmKGtleSA9PT0gJ2VkaXRhYmxlJyB8fCBrZXkgPT09ICdlZGl0cycpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYoa2V5IGluIGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBpZihrZXkgPT09ICdzZXRCYWNrZ3JvdW5kJyAmJiBjb25maWdba2V5XSA9PT0gJ29wYXF1ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dFtrZXldID0gb3BhcXVlU2V0QmFja2dyb3VuZDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0W2tleV0gPSBjb25maWdba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBtYXAgcGxvdDNkUGl4ZWxSYXRpbyB0byBwbG90R2xQaXhlbFJhdGlvIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgICAgIGlmKGNvbmZpZy5wbG90M2RQaXhlbFJhdGlvICYmICFjb250ZXh0LnBsb3RHbFBpeGVsUmF0aW8pIHtcbiAgICAgICAgICAgIGNvbnRleHQucGxvdEdsUGl4ZWxSYXRpbyA9IGNvbnRleHQucGxvdDNkUGl4ZWxSYXRpbztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG5vdyBkZWFsIHdpdGggZWRpdGFibGUgYW5kIGVkaXRzIC0gZmlyc3QgZWRpdGFibGUgb3ZlcnJpZGVzXG4gICAgICAgIC8vIGV2ZXJ5dGhpbmcsIHRoZW4gZWRpdHMgcmVmaW5lc1xuICAgICAgICB2YXIgZWRpdGFibGUgPSBjb25maWcuZWRpdGFibGU7XG4gICAgICAgIGlmKGVkaXRhYmxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIHdlJ3JlIG5vdCBnb2luZyB0byAqdXNlKiBjb250ZXh0LmVkaXRhYmxlLCB3ZSdyZSBvbmx5IGdvaW5nIHRvXG4gICAgICAgICAgICAvLyB1c2UgY29udGV4dC5lZGl0cy4uLiBidXQga2VlcCBpdCBmb3IgdGhlIHJlY29yZFxuICAgICAgICAgICAgY29udGV4dC5lZGl0YWJsZSA9IGVkaXRhYmxlO1xuXG4gICAgICAgICAgICBrZXlzID0gT2JqZWN0LmtleXMoY29udGV4dC5lZGl0cyk7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29udGV4dC5lZGl0c1trZXlzW2ldXSA9IGVkaXRhYmxlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKGNvbmZpZy5lZGl0cykge1xuICAgICAgICAgICAga2V5cyA9IE9iamVjdC5rZXlzKGNvbmZpZy5lZGl0cyk7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICAgICAgICBpZihrZXkgaW4gY29udGV4dC5lZGl0cykge1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LmVkaXRzW2tleV0gPSBjb25maWcuZWRpdHNba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBub3QgcGFydCBvZiB0aGUgdXNlci1mYWNpbmcgY29uZmlnIG9wdGlvbnNcbiAgICAgICAgY29udGV4dC5fZXhwb3J0ZWRQbG90ID0gY29uZmlnLl9leHBvcnRlZFBsb3Q7XG4gICAgfVxuXG4gICAgLy8gc3RhdGljUGxvdCBmb3JjZXMgYSBidW5jaCBvZiBvdGhlcnM6XG4gICAgaWYoY29udGV4dC5zdGF0aWNQbG90KSB7XG4gICAgICAgIGNvbnRleHQuZWRpdGFibGUgPSBmYWxzZTtcbiAgICAgICAgY29udGV4dC5lZGl0cyA9IHt9O1xuICAgICAgICBjb250ZXh0LmF1dG9zaXphYmxlID0gZmFsc2U7XG4gICAgICAgIGNvbnRleHQuc2Nyb2xsWm9vbSA9IGZhbHNlO1xuICAgICAgICBjb250ZXh0LmRvdWJsZUNsaWNrID0gZmFsc2U7XG4gICAgICAgIGNvbnRleHQuc2hvd1RpcHMgPSBmYWxzZTtcbiAgICAgICAgY29udGV4dC5zaG93TGluayA9IGZhbHNlO1xuICAgICAgICBjb250ZXh0LmRpc3BsYXlNb2RlQmFyID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gbWFrZSBzdXJlIGhvdmVyLW9ubHkgZGV2aWNlcyBoYXZlIG1vZGUgYmFyIHZpc2libGVcbiAgICBpZihjb250ZXh0LmRpc3BsYXlNb2RlQmFyID09PSAnaG92ZXInICYmICFoYXNIb3Zlcikge1xuICAgICAgICBjb250ZXh0LmRpc3BsYXlNb2RlQmFyID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBkZWZhdWx0IGFuZCBmYWxsYmFjayBmb3Igc2V0QmFja2dyb3VuZFxuICAgIGlmKGNvbnRleHQuc2V0QmFja2dyb3VuZCA9PT0gJ3RyYW5zcGFyZW50JyB8fCB0eXBlb2YgY29udGV4dC5zZXRCYWNrZ3JvdW5kICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNvbnRleHQuc2V0QmFja2dyb3VuZCA9IHNldEJhY2tncm91bmQ7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgZ2QgaGFzIGEgc3BlY2lmaWVkIHdpZGh0L2hlaWdodCB0byBiZWdpbiB3aXRoXG4gICAgY29udGV4dC5faGFzWmVyb0hlaWdodCA9IGNvbnRleHQuX2hhc1plcm9IZWlnaHQgfHwgZ2QuY2xpZW50SGVpZ2h0ID09PSAwO1xuICAgIGNvbnRleHQuX2hhc1plcm9XaWR0aCA9IGNvbnRleHQuX2hhc1plcm9XaWR0aCB8fCBnZC5jbGllbnRXaWR0aCA9PT0gMDtcblxuICAgIC8vIGZpbGwgY29udGV4dC5fc2Nyb2xsWm9vbSBoZWxwZXIgdG8gaGVscCBtYW5hZ2Ugc2Nyb2xsWm9vbSBmbGFnbGlzdFxuICAgIHZhciBzekluID0gY29udGV4dC5zY3JvbGxab29tO1xuICAgIHZhciBzek91dCA9IGNvbnRleHQuX3Njcm9sbFpvb20gPSB7fTtcbiAgICBpZihzekluID09PSB0cnVlKSB7XG4gICAgICAgIHN6T3V0LmNhcnRlc2lhbiA9IDE7XG4gICAgICAgIHN6T3V0LmdsM2QgPSAxO1xuICAgICAgICBzek91dC5nZW8gPSAxO1xuICAgICAgICBzek91dC5tYXBib3ggPSAxO1xuICAgIH0gZWxzZSBpZih0eXBlb2Ygc3pJbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIHBhcnRzID0gc3pJbi5zcGxpdCgnKycpO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc3pPdXRbcGFydHNbaV1dID0gMTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZihzekluICE9PSBmYWxzZSkge1xuICAgICAgICBzek91dC5nbDNkID0gMTtcbiAgICAgICAgc3pPdXQuZ2VvID0gMTtcbiAgICAgICAgc3pPdXQubWFwYm94ID0gMTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHBsb3RMZWdhY3lQb2xhcihnZCwgZGF0YSwgbGF5b3V0KSB7XG4gICAgLy8gYnVpbGQgb3IgcmV1c2UgdGhlIGNvbnRhaW5lciBza2VsZXRvblxuICAgIHZhciBwbG90Q29udGFpbmVyID0gZDMuc2VsZWN0KGdkKS5zZWxlY3RBbGwoJy5wbG90LWNvbnRhaW5lcicpXG4gICAgICAgIC5kYXRhKFswXSk7XG4gICAgcGxvdENvbnRhaW5lci5lbnRlcigpXG4gICAgICAgIC5pbnNlcnQoJ2RpdicsICc6Zmlyc3QtY2hpbGQnKVxuICAgICAgICAuY2xhc3NlZCgncGxvdC1jb250YWluZXIgcGxvdGx5JywgdHJ1ZSk7XG4gICAgdmFyIHBhcGVyRGl2ID0gcGxvdENvbnRhaW5lci5zZWxlY3RBbGwoJy5zdmctY29udGFpbmVyJylcbiAgICAgICAgLmRhdGEoWzBdKTtcbiAgICBwYXBlckRpdi5lbnRlcigpLmFwcGVuZCgnZGl2JylcbiAgICAgICAgLmNsYXNzZWQoJ3N2Zy1jb250YWluZXInLCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ3Bvc2l0aW9uJywgJ3JlbGF0aXZlJyk7XG5cbiAgICAvLyBlbXB0eSBpdCBldmVyeXRpbWUgZm9yIG5vd1xuICAgIHBhcGVyRGl2Lmh0bWwoJycpO1xuXG4gICAgLy8gZnVsZmlsbCBnZCByZXF1aXJlbWVudHNcbiAgICBpZihkYXRhKSBnZC5kYXRhID0gZGF0YTtcbiAgICBpZihsYXlvdXQpIGdkLmxheW91dCA9IGxheW91dDtcbiAgICBQb2xhci5tYW5hZ2VyLmZpbGxMYXlvdXQoZ2QpO1xuXG4gICAgLy8gcmVzaXplIGNhbnZhc1xuICAgIHBhcGVyRGl2LnN0eWxlKHtcbiAgICAgICAgd2lkdGg6IGdkLl9mdWxsTGF5b3V0LndpZHRoICsgJ3B4JyxcbiAgICAgICAgaGVpZ2h0OiBnZC5fZnVsbExheW91dC5oZWlnaHQgKyAncHgnXG4gICAgfSk7XG5cbiAgICAvLyBpbnN0YW50aWF0ZSBmcmFtZXdvcmtcbiAgICBnZC5mcmFtZXdvcmsgPSBQb2xhci5tYW5hZ2VyLmZyYW1ld29yayhnZCk7XG5cbiAgICAvLyBwbG90XG4gICAgZ2QuZnJhbWV3b3JrKHtkYXRhOiBnZC5kYXRhLCBsYXlvdXQ6IGdkLmxheW91dH0sIHBhcGVyRGl2Lm5vZGUoKSk7XG5cbiAgICAvLyBzZXQgdW5kbyBwb2ludFxuICAgIGdkLmZyYW1ld29yay5zZXRVbmRvUG9pbnQoKTtcblxuICAgIC8vIGdldCB0aGUgcmVzdWx0aW5nIHN2ZyBmb3IgZXh0ZW5kaW5nIGl0XG4gICAgdmFyIHBvbGFyUGxvdFNWRyA9IGdkLmZyYW1ld29yay5zdmcoKTtcblxuICAgIC8vIGVkaXRhYmxlIHRpdGxlXG4gICAgdmFyIG9wYWNpdHkgPSAxO1xuICAgIHZhciB0eHQgPSBnZC5fZnVsbExheW91dC50aXRsZSA/IGdkLl9mdWxsTGF5b3V0LnRpdGxlLnRleHQgOiAnJztcbiAgICBpZih0eHQgPT09ICcnIHx8ICF0eHQpIG9wYWNpdHkgPSAwO1xuXG4gICAgdmFyIHRpdGxlTGF5b3V0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG4gICAgICAgIC8vIFRPRE86IGh0bWwvbWF0aGpheFxuICAgICAgICAvLyBUT0RPOiBjZW50ZXIgdGl0bGVcbiAgICB9O1xuXG4gICAgdmFyIHRpdGxlID0gcG9sYXJQbG90U1ZHLnNlbGVjdCgnLnRpdGxlLWdyb3VwIHRleHQnKVxuICAgICAgICAuY2FsbCh0aXRsZUxheW91dCk7XG5cbiAgICBpZihnZC5fY29udGV4dC5lZGl0cy50aXRsZVRleHQpIHtcbiAgICAgICAgdmFyIHBsYWNlaG9sZGVyVGV4dCA9IExpYi5fKGdkLCAnQ2xpY2sgdG8gZW50ZXIgUGxvdCB0aXRsZScpO1xuICAgICAgICBpZighdHh0IHx8IHR4dCA9PT0gcGxhY2Vob2xkZXJUZXh0KSB7XG4gICAgICAgICAgICBvcGFjaXR5ID0gMC4yO1xuICAgICAgICAgICAgLy8gcGxhY2Vob2xkZXIgaXMgbm90IGdvaW5nIHRocm91Z2ggY29udmVydFRvVHNwYW5zXG4gICAgICAgICAgICAvLyBzbyBuZWVkcyBleHBsaWNpdCBkYXRhLXVuZm9ybWF0dGVkXG4gICAgICAgICAgICB0aXRsZS5hdHRyKHsnZGF0YS11bmZvcm1hdHRlZCc6IHBsYWNlaG9sZGVyVGV4dH0pXG4gICAgICAgICAgICAgICAgLnRleHQocGxhY2Vob2xkZXJUZXh0KVxuICAgICAgICAgICAgICAgIC5zdHlsZSh7b3BhY2l0eTogb3BhY2l0eX0pXG4gICAgICAgICAgICAgICAgLm9uKCdtb3VzZW92ZXIub3BhY2l0eScsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykudHJhbnNpdGlvbigpLmR1cmF0aW9uKDEwMClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDEpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLm9uKCdtb3VzZW91dC5vcGFjaXR5JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS50cmFuc2l0aW9uKCkuZHVyYXRpb24oMTAwMClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNldENvbnRlbnRlZGl0YWJsZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5jYWxsKHN2Z1RleHRVdGlscy5tYWtlRWRpdGFibGUsIHtnZDogZ2R9KVxuICAgICAgICAgICAgICAgIC5vbignZWRpdCcsIGZ1bmN0aW9uKHRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2QuZnJhbWV3b3JrKHtsYXlvdXQ6IHt0aXRsZToge3RleHQ6IHRleHR9fX0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRleHQodGV4dClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYWxsKHRpdGxlTGF5b3V0KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWxsKHNldENvbnRlbnRlZGl0YWJsZSk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAub24oJ2NhbmNlbCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHh0ID0gdGhpcy5hdHRyKCdkYXRhLXVuZm9ybWF0dGVkJyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dCh0eHQpLmNhbGwodGl0bGVMYXlvdXQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICB0aXRsZS5jYWxsKHNldENvbnRlbnRlZGl0YWJsZSk7XG4gICAgfVxuXG4gICAgZ2QuX2NvbnRleHQuc2V0QmFja2dyb3VuZChnZCwgZ2QuX2Z1bGxMYXlvdXQucGFwZXJfYmdjb2xvcik7XG4gICAgUGxvdHMuYWRkTGlua3MoZ2QpO1xuXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBjb252ZW5pZW5jZSBmdW5jdGlvbiB0byBmb3JjZSBhIGZ1bGwgcmVkcmF3LCBtb3N0bHkgZm9yIHVzZSBieSBwbG90bHkuanNcbmZ1bmN0aW9uIHJlZHJhdyhnZCkge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIGlmKCFMaWIuaXNQbG90RGl2KGdkKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgZWxlbWVudCBpcyBub3QgYSBQbG90bHkgcGxvdDogJyArIGdkKTtcbiAgICB9XG5cbiAgICBoZWxwZXJzLmNsZWFuRGF0YShnZC5kYXRhKTtcbiAgICBoZWxwZXJzLmNsZWFuTGF5b3V0KGdkLmxheW91dCk7XG5cbiAgICBnZC5jYWxjZGF0YSA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gZXhwb3J0cy5wbG90KGdkKS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVkcmF3Jyk7XG4gICAgICAgIHJldHVybiBnZDtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDb252ZW5pZW5jZSBmdW5jdGlvbiB0byBtYWtlIGlkZW1wb3RlbnQgcGxvdCBvcHRpb24gb2J2aW91cyB0byB1c2Vycy5cbiAqXG4gKiBAcGFyYW0gZ2RcbiAqIEBwYXJhbSB7T2JqZWN0W119IGRhdGFcbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXlvdXRcbiAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWdcbiAqL1xuZnVuY3Rpb24gbmV3UGxvdChnZCwgZGF0YSwgbGF5b3V0LCBjb25maWcpIHtcbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICAvLyByZW1vdmUgZ2wgY29udGV4dHNcbiAgICBQbG90cy5jbGVhblBsb3QoW10sIHt9LCBnZC5fZnVsbERhdGEgfHwgW10sIGdkLl9mdWxsTGF5b3V0IHx8IHt9KTtcblxuICAgIFBsb3RzLnB1cmdlKGdkKTtcbiAgICByZXR1cm4gZXhwb3J0cy5wbG90KGdkLCBkYXRhLCBsYXlvdXQsIGNvbmZpZyk7XG59XG5cbi8qKlxuICogV3JhcCBuZWdhdGl2ZSBpbmRpY2llcyB0byB0aGVpciBwb3NpdGl2ZSBjb3VudGVycGFydHMuXG4gKlxuICogQHBhcmFtIHtOdW1iZXJbXX0gaW5kaWNlcyBBbiBhcnJheSBvZiBpbmRpY2VzXG4gKiBAcGFyYW0ge051bWJlcn0gbWF4SW5kZXggVGhlIG1heGltdW0gaW5kZXggYWxsb3dhYmxlIChhcnIubGVuZ3RoIC0gMSlcbiAqL1xuZnVuY3Rpb24gcG9zaXRpdmlmeUluZGljZXMoaW5kaWNlcywgbWF4SW5kZXgpIHtcbiAgICB2YXIgcGFyZW50TGVuZ3RoID0gbWF4SW5kZXggKyAxO1xuICAgIHZhciBwb3NpdGl2ZUluZGljZXMgPSBbXTtcbiAgICB2YXIgaTtcbiAgICB2YXIgaW5kZXg7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgaWYoaW5kZXggPCAwKSB7XG4gICAgICAgICAgICBwb3NpdGl2ZUluZGljZXMucHVzaChwYXJlbnRMZW5ndGggKyBpbmRleCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwb3NpdGl2ZUluZGljZXMucHVzaChpbmRleCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBvc2l0aXZlSW5kaWNlcztcbn1cblxuLyoqXG4gKiBFbnN1cmVzIHRoYXQgYW4gaW5kZXggYXJyYXkgZm9yIG1hbmlwdWxhdGluZyBnZC5kYXRhIGlzIHZhbGlkLlxuICpcbiAqIEludGVuZGVkIGZvciB1c2Ugd2l0aCBhZGRUcmFjZXMsIGRlbGV0ZVRyYWNlcywgYW5kIG1vdmVUcmFjZXMuXG4gKlxuICogQHBhcmFtIGdkXG4gKiBAcGFyYW0gaW5kaWNlc1xuICogQHBhcmFtIGFycmF5TmFtZVxuICovXG5mdW5jdGlvbiBhc3NlcnRJbmRleEFycmF5KGdkLCBpbmRpY2VzLCBhcnJheU5hbWUpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgaW5kZXg7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGluZGV4ID0gaW5kaWNlc1tpXTtcblxuICAgICAgICAvLyB2YWxpZGF0ZSB0aGF0IGluZGljZXMgYXJlIGluZGVlZCBpbnRlZ2Vyc1xuICAgICAgICBpZihpbmRleCAhPT0gcGFyc2VJbnQoaW5kZXgsIDEwKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhbGwgdmFsdWVzIGluICcgKyBhcnJheU5hbWUgKyAnIG11c3QgYmUgaW50ZWdlcnMnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIHRoYXQgYWxsIGluZGljZXMgYXJlIGluIGJvdW5kcyBmb3IgZ2l2ZW4gZ2QuZGF0YSBhcnJheSBsZW5ndGhcbiAgICAgICAgaWYoaW5kZXggPj0gZ2QuZGF0YS5sZW5ndGggfHwgaW5kZXggPCAtZ2QuZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihhcnJheU5hbWUgKyAnIG11c3QgYmUgdmFsaWQgaW5kaWNlcyBmb3IgZ2QuZGF0YS4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIHRoYXQgaW5kaWNlcyBhcmVuJ3QgcmVwZWF0ZWRcbiAgICAgICAgaWYoaW5kaWNlcy5pbmRleE9mKGluZGV4LCBpICsgMSkgPiAtMSB8fFxuICAgICAgICAgICAgICAgIGluZGV4ID49IDAgJiYgaW5kaWNlcy5pbmRleE9mKC1nZC5kYXRhLmxlbmd0aCArIGluZGV4KSA+IC0xIHx8XG4gICAgICAgICAgICAgICAgaW5kZXggPCAwICYmIGluZGljZXMuaW5kZXhPZihnZC5kYXRhLmxlbmd0aCArIGluZGV4KSA+IC0xKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2VhY2ggaW5kZXggaW4gJyArIGFycmF5TmFtZSArICcgbXVzdCBiZSB1bmlxdWUuJyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogUHJpdmF0ZSBmdW5jdGlvbiB1c2VkIGJ5IFBsb3RseS5tb3ZlVHJhY2VzIHRvIGNoZWNrIGlucHV0IGFyZ3NcbiAqXG4gKiBAcGFyYW0gZ2RcbiAqIEBwYXJhbSBjdXJyZW50SW5kaWNlc1xuICogQHBhcmFtIG5ld0luZGljZXNcbiAqL1xuZnVuY3Rpb24gY2hlY2tNb3ZlVHJhY2VzQXJncyhnZCwgY3VycmVudEluZGljZXMsIG5ld0luZGljZXMpIHtcbiAgICAvLyBjaGVjayB0aGF0IGdkIGhhcyBhdHRyaWJ1dGUgJ2RhdGEnIGFuZCAnZGF0YScgaXMgYXJyYXlcbiAgICBpZighQXJyYXkuaXNBcnJheShnZC5kYXRhKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dkLmRhdGEgbXVzdCBiZSBhbiBhcnJheS4nKTtcbiAgICB9XG5cbiAgICAvLyB2YWxpZGF0ZSBjdXJyZW50SW5kaWNlcyBhcnJheVxuICAgIGlmKHR5cGVvZiBjdXJyZW50SW5kaWNlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjdXJyZW50SW5kaWNlcyBpcyBhIHJlcXVpcmVkIGFyZ3VtZW50LicpO1xuICAgIH0gZWxzZSBpZighQXJyYXkuaXNBcnJheShjdXJyZW50SW5kaWNlcykpIHtcbiAgICAgICAgY3VycmVudEluZGljZXMgPSBbY3VycmVudEluZGljZXNdO1xuICAgIH1cbiAgICBhc3NlcnRJbmRleEFycmF5KGdkLCBjdXJyZW50SW5kaWNlcywgJ2N1cnJlbnRJbmRpY2VzJyk7XG5cbiAgICAvLyB2YWxpZGF0ZSBuZXdJbmRpY2VzIGFycmF5IGlmIGl0IGV4aXN0c1xuICAgIGlmKHR5cGVvZiBuZXdJbmRpY2VzICE9PSAndW5kZWZpbmVkJyAmJiAhQXJyYXkuaXNBcnJheShuZXdJbmRpY2VzKSkge1xuICAgICAgICBuZXdJbmRpY2VzID0gW25ld0luZGljZXNdO1xuICAgIH1cbiAgICBpZih0eXBlb2YgbmV3SW5kaWNlcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgYXNzZXJ0SW5kZXhBcnJheShnZCwgbmV3SW5kaWNlcywgJ25ld0luZGljZXMnKTtcbiAgICB9XG5cbiAgICAvLyBjaGVjayBjdXJyZW50SW5kaWNlcyBhbmQgbmV3SW5kaWNlcyBhcmUgdGhlIHNhbWUgbGVuZ3RoIGlmIG5ld0lkaWNlcyBleGlzdHNcbiAgICBpZih0eXBlb2YgbmV3SW5kaWNlcyAhPT0gJ3VuZGVmaW5lZCcgJiYgY3VycmVudEluZGljZXMubGVuZ3RoICE9PSBuZXdJbmRpY2VzLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnQgYW5kIG5ldyBpbmRpY2VzIG11c3QgYmUgb2YgZXF1YWwgbGVuZ3RoLicpO1xuICAgIH1cbn1cbi8qKlxuICogQSBwcml2YXRlIGZ1bmN0aW9uIHRvIHJlZHVjZSB0aGUgdHlwZSBjaGVja2luZyBjbHV0dGVyIGluIGFkZFRyYWNlcy5cbiAqXG4gKiBAcGFyYW0gZ2RcbiAqIEBwYXJhbSB0cmFjZXNcbiAqIEBwYXJhbSBuZXdJbmRpY2VzXG4gKi9cbmZ1bmN0aW9uIGNoZWNrQWRkVHJhY2VzQXJncyhnZCwgdHJhY2VzLCBuZXdJbmRpY2VzKSB7XG4gICAgdmFyIGksIHZhbHVlO1xuXG4gICAgLy8gY2hlY2sgdGhhdCBnZCBoYXMgYXR0cmlidXRlICdkYXRhJyBhbmQgJ2RhdGEnIGlzIGFycmF5XG4gICAgaWYoIUFycmF5LmlzQXJyYXkoZ2QuZGF0YSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdnZC5kYXRhIG11c3QgYmUgYW4gYXJyYXkuJyk7XG4gICAgfVxuXG4gICAgLy8gbWFrZSBzdXJlIHRyYWNlcyBleGlzdHNcbiAgICBpZih0eXBlb2YgdHJhY2VzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RyYWNlcyBtdXN0IGJlIGRlZmluZWQuJyk7XG4gICAgfVxuXG4gICAgLy8gbWFrZSBzdXJlIHRyYWNlcyBpcyBhbiBhcnJheVxuICAgIGlmKCFBcnJheS5pc0FycmF5KHRyYWNlcykpIHtcbiAgICAgICAgdHJhY2VzID0gW3RyYWNlc107XG4gICAgfVxuXG4gICAgLy8gbWFrZSBzdXJlIGVhY2ggdmFsdWUgaW4gdHJhY2VzIGlzIGFuIG9iamVjdFxuICAgIGZvcihpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YWx1ZSA9IHRyYWNlc1tpXTtcbiAgICAgICAgaWYodHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JyB8fCAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgfHwgdmFsdWUgPT09IG51bGwpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FsbCB2YWx1ZXMgaW4gdHJhY2VzIGFycmF5IG11c3QgYmUgbm9uLWFycmF5IG9iamVjdHMnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSB3ZSBoYXZlIGFuIGluZGV4IGZvciBlYWNoIHRyYWNlXG4gICAgaWYodHlwZW9mIG5ld0luZGljZXMgIT09ICd1bmRlZmluZWQnICYmICFBcnJheS5pc0FycmF5KG5ld0luZGljZXMpKSB7XG4gICAgICAgIG5ld0luZGljZXMgPSBbbmV3SW5kaWNlc107XG4gICAgfVxuICAgIGlmKHR5cGVvZiBuZXdJbmRpY2VzICE9PSAndW5kZWZpbmVkJyAmJiBuZXdJbmRpY2VzLmxlbmd0aCAhPT0gdHJhY2VzLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnaWYgaW5kaWNlcyBpcyBzcGVjaWZpZWQsIHRyYWNlcy5sZW5ndGggbXVzdCBlcXVhbCBpbmRpY2VzLmxlbmd0aCdcbiAgICAgICAgKTtcbiAgICB9XG59XG5cbi8qKlxuICogQSBwcml2YXRlIGZ1bmN0aW9uIHRvIHJlZHVjZSB0aGUgdHlwZSBjaGVja2luZyBjbHV0dGVyIGluIHNwbGljZVRyYWNlcy5cbiAqIEdldCBhbGwgdXBkYXRlIFByb3BlcnRpZXMgZnJvbSBnZC5kYXRhLiBWYWxpZGF0ZSBpbnB1dHMgYW5kIG91dHB1dHMuXG4gKiBVc2VkIGJ5IHByZXBlbmRUcmFjZSBhbmQgZXh0ZW5kVHJhY2VzXG4gKlxuICogQHBhcmFtIGdkXG4gKiBAcGFyYW0gdXBkYXRlXG4gKiBAcGFyYW0gaW5kaWNlc1xuICogQHBhcmFtIG1heFBvaW50c1xuICovXG5mdW5jdGlvbiBhc3NlcnRFeHRlbmRUcmFjZXNBcmdzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cykge1xuICAgIHZhciBtYXhQb2ludHNJc09iamVjdCA9IExpYi5pc1BsYWluT2JqZWN0KG1heFBvaW50cyk7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheShnZC5kYXRhKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dkLmRhdGEgbXVzdCBiZSBhbiBhcnJheScpO1xuICAgIH1cbiAgICBpZighTGliLmlzUGxhaW5PYmplY3QodXBkYXRlKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3VwZGF0ZSBtdXN0IGJlIGEga2V5OnZhbHVlIG9iamVjdCcpO1xuICAgIH1cblxuICAgIGlmKHR5cGVvZiBpbmRpY2VzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2luZGljZXMgbXVzdCBiZSBhbiBpbnRlZ2VyIG9yIGFycmF5IG9mIGludGVnZXJzJyk7XG4gICAgfVxuXG4gICAgYXNzZXJ0SW5kZXhBcnJheShnZCwgaW5kaWNlcywgJ2luZGljZXMnKTtcblxuICAgIGZvcih2YXIga2V5IGluIHVwZGF0ZSkge1xuICAgICAgICAvKlxuICAgICAgICAgKiBWZXJpZnkgdGhhdCB0aGUgYXR0cmlidXRlIHRvIGJlIHVwZGF0ZWQgY29udGFpbnMgYXMgbWFueSB0cmFjZSB1cGRhdGVzXG4gICAgICAgICAqIGFzIGluZGljZXMuIEZhaWx1cmUgbXVzdCByZXN1bHQgaW4gdGhyb3cgYW5kIG5vLW9wXG4gICAgICAgICAqL1xuICAgICAgICBpZighQXJyYXkuaXNBcnJheSh1cGRhdGVba2V5XSkgfHwgdXBkYXRlW2tleV0ubGVuZ3RoICE9PSBpbmRpY2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhdHRyaWJ1dGUgJyArIGtleSArICcgbXVzdCBiZSBhbiBhcnJheSBvZiBsZW5ndGggZXF1YWwgdG8gaW5kaWNlcyBhcnJheSBsZW5ndGgnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qXG4gICAgICAgICAqIGlmIG1heFBvaW50cyBpcyBhbiBvYmplY3QgaXQgbXVzdCBtYXRjaCBrZXlzIGFuZCBhcnJheSBsZW5ndGhzIG9mICd1cGRhdGUnIDE6MVxuICAgICAgICAgKi9cbiAgICAgICAgaWYobWF4UG9pbnRzSXNPYmplY3QgJiZcbiAgICAgICAgICAgICghKGtleSBpbiBtYXhQb2ludHMpIHx8ICFBcnJheS5pc0FycmF5KG1heFBvaW50c1trZXldKSB8fFxuICAgICAgICAgICAgbWF4UG9pbnRzW2tleV0ubGVuZ3RoICE9PSB1cGRhdGVba2V5XS5sZW5ndGgpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3doZW4gbWF4UG9pbnRzIGlzIHNldCBhcyBhIGtleTp2YWx1ZSBvYmplY3QgaXQgbXVzdCBjb250YWluIGEgMToxICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjb3JyaXNwb25kZW5jZSB3aXRoIHRoZSBrZXlzIGFuZCBudW1iZXIgb2YgdHJhY2VzIGluIHRoZSB1cGRhdGUgb2JqZWN0Jyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQSBwcml2YXRlIGZ1bmN0aW9uIHRvIHJlZHVjZSB0aGUgdHlwZSBjaGVja2luZyBjbHV0dGVyIGluIHNwbGljZVRyYWNlcy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdHxIVE1MRGl2RWxlbWVudH0gZ2RcbiAqIEBwYXJhbSB7T2JqZWN0fSB1cGRhdGVcbiAqIEBwYXJhbSB7TnVtYmVyW119IGluZGljZXNcbiAqIEBwYXJhbSB7TnVtYmVyfHxPYmplY3R9IG1heFBvaW50c1xuICogQHJldHVybiB7T2JqZWN0W119XG4gKi9cbmZ1bmN0aW9uIGdldEV4dGVuZFByb3BlcnRpZXMoZ2QsIHVwZGF0ZSwgaW5kaWNlcywgbWF4UG9pbnRzKSB7XG4gICAgdmFyIG1heFBvaW50c0lzT2JqZWN0ID0gTGliLmlzUGxhaW5PYmplY3QobWF4UG9pbnRzKTtcbiAgICB2YXIgdXBkYXRlUHJvcHMgPSBbXTtcbiAgICB2YXIgdHJhY2UsIHRhcmdldCwgcHJvcCwgaW5zZXJ0LCBtYXhwO1xuXG4gICAgLy8gYWxsb3cgc2NhbGFyIGluZGV4IHRvIHJlcHJlc2VudCBhIHNpbmdsZSB0cmFjZSBwb3NpdGlvblxuICAgIGlmKCFBcnJheS5pc0FycmF5KGluZGljZXMpKSBpbmRpY2VzID0gW2luZGljZXNdO1xuXG4gICAgLy8gbmVnYXRpdmUgaW5kaWNlcyBhcmUgd3JhcHBlZCBhcm91bmQgdG8gdGhlaXIgcG9zaXRpdmUgdmFsdWUuIEVxdWl2YWxlbnQgdG8gcHl0aG9uIGluZGV4aW5nLlxuICAgIGluZGljZXMgPSBwb3NpdGl2aWZ5SW5kaWNlcyhpbmRpY2VzLCBnZC5kYXRhLmxlbmd0aCAtIDEpO1xuXG4gICAgLy8gbG9vcCB0aHJvdWdoIGFsbCB1cGRhdGUga2V5cyBhbmQgdHJhY2VzIGFuZCBoYXJ2ZXN0IHZhbGlkYXRlZCBkYXRhLlxuICAgIGZvcih2YXIga2V5IGluIHVwZGF0ZSkge1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgaW5kaWNlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIENob29zZSB0aGUgdHJhY2UgaW5kZXhlZCBieSB0aGUgaW5kaWNlcyBtYXAgYXJndW1lbnQgYW5kIGdldCB0aGUgcHJvcCBzZXR0ZXItZ2V0dGVyXG4gICAgICAgICAgICAgKiBpbnN0YW5jZSB0aGF0IHJlZmVyZW5jZXMgdGhlIGtleSBhbmQgdmFsdWUgZm9yIHRoaXMgcGFydGljdWxhciB0cmFjZS5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdHJhY2UgPSBnZC5kYXRhW2luZGljZXNbal1dO1xuICAgICAgICAgICAgcHJvcCA9IG5lc3RlZFByb3BlcnR5KHRyYWNlLCBrZXkpO1xuXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogVGFyZ2V0IGlzIHRoZSBleGlzdGluZyBnZC5kYXRhLnRyYWNlLmRhdGFBcnJheSB2YWx1ZSBsaWtlIFwieFwiIG9yIFwibWFya2VyLnNpemVcIlxuICAgICAgICAgICAgICogVGFyZ2V0IG11c3QgZXhpc3QgYXMgYW4gQXJyYXkgdG8gYWxsb3cgdGhlIGV4dGVuZCBvcGVyYXRpb24gdG8gYmUgcGVyZm9ybWVkLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB0YXJnZXQgPSBwcm9wLmdldCgpO1xuICAgICAgICAgICAgaW5zZXJ0ID0gdXBkYXRlW2tleV1bal07XG5cbiAgICAgICAgICAgIGlmKCFMaWIuaXNBcnJheU9yVHlwZWRBcnJheShpbnNlcnQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhdHRyaWJ1dGU6ICcgKyBrZXkgKyAnIGluZGV4OiAnICsgaiArICcgbXVzdCBiZSBhbiBhcnJheScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoIUxpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRhcmdldCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBleHRlbmQgbWlzc2luZyBvciBub24tYXJyYXkgYXR0cmlidXRlOiAnICsga2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHRhcmdldC5jb25zdHJ1Y3RvciAhPT0gaW5zZXJ0LmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3QgZXh0ZW5kIGFycmF5IHdpdGggYW4gYXJyYXkgb2YgYSBkaWZmZXJlbnQgdHlwZTogJyArIGtleSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBtYXhQb2ludHMgbWF5IGJlIGFuIG9iamVjdCBtYXAgb3IgYSBzY2FsYXIuIElmIG9iamVjdCBzZWxlY3QgdGhlIGtleTp2YWx1ZSwgZWxzZVxuICAgICAgICAgICAgICogVXNlIHRoZSBzY2FsYXIgbWF4UG9pbnRzIGZvciBhbGwga2V5IGFuZCB0cmFjZSBjb21iaW5hdGlvbnMuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1heHAgPSBtYXhQb2ludHNJc09iamVjdCA/IG1heFBvaW50c1trZXldW2pdIDogbWF4UG9pbnRzO1xuXG4gICAgICAgICAgICAvLyBjb3VsZCBoYXZlIGNob3NlbiBudWxsIGhlcmUsIC0xIGp1c3QgdGVsbHMgdXMgdG8gbm90IHRha2UgYSB3aW5kb3dcbiAgICAgICAgICAgIGlmKCFpc051bWVyaWMobWF4cCkpIG1heHAgPSAtMTtcblxuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIFdyYXAgdGhlIG5lc3RlZFByb3BlcnR5IGluIGFuIG9iamVjdCBjb250YWluaW5nIHJlcXVpcmVkIGRhdGFcbiAgICAgICAgICAgICAqIGZvciBsZW5ndGhlbmluZyBhbmQgd2luZG93aW5nIHRoaXMgcGFydGljdWxhciB0cmFjZSAtIGtleSBjb21iaW5hdGlvbi5cbiAgICAgICAgICAgICAqIEZsb29yaW5nIG1heHAgbWlycm9ycyB0aGUgYmVoYXZpb3VyIG9mIGZsb2F0cyBpbiB0aGUgQXJyYXkuc2xpY2UgSlNuYXRpdmUgZnVuY3Rpb24uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHVwZGF0ZVByb3BzLnB1c2goe1xuICAgICAgICAgICAgICAgIHByb3A6IHByb3AsXG4gICAgICAgICAgICAgICAgdGFyZ2V0OiB0YXJnZXQsXG4gICAgICAgICAgICAgICAgaW5zZXJ0OiBpbnNlcnQsXG4gICAgICAgICAgICAgICAgbWF4cDogTWF0aC5mbG9vcihtYXhwKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhbGwgdGFyZ2V0IGFuZCBpbnNlcnRpb24gZGF0YSBub3cgdmFsaWRhdGVkXG4gICAgcmV0dXJuIHVwZGF0ZVByb3BzO1xufVxuXG4vKipcbiAqIEEgcHJpdmF0ZSBmdW5jdGlvbiB0byBrZXkgRXh0ZW5kIGFuZCBQcmVwZW5kIHRyYWNlcyBEUllcbiAqXG4gKiBAcGFyYW0ge09iamVjdHxIVE1MRGl2RWxlbWVudH0gZ2RcbiAqIEBwYXJhbSB7T2JqZWN0fSB1cGRhdGVcbiAqIEBwYXJhbSB7TnVtYmVyW119IGluZGljZXNcbiAqIEBwYXJhbSB7TnVtYmVyfHxPYmplY3R9IG1heFBvaW50c1xuICogQHBhcmFtIHtGdW5jdGlvbn0gdXBkYXRlQXJyYXlcbiAqIEByZXR1cm4ge09iamVjdH1cbiAqL1xuZnVuY3Rpb24gc3BsaWNlVHJhY2VzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cywgdXBkYXRlQXJyYXkpIHtcbiAgICBhc3NlcnRFeHRlbmRUcmFjZXNBcmdzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cyk7XG5cbiAgICB2YXIgdXBkYXRlUHJvcHMgPSBnZXRFeHRlbmRQcm9wZXJ0aWVzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cyk7XG4gICAgdmFyIHVuZG9VcGRhdGUgPSB7fTtcbiAgICB2YXIgdW5kb1BvaW50cyA9IHt9O1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHVwZGF0ZVByb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwcm9wID0gdXBkYXRlUHJvcHNbaV0ucHJvcDtcbiAgICAgICAgdmFyIG1heHAgPSB1cGRhdGVQcm9wc1tpXS5tYXhwO1xuXG4gICAgICAgIC8vIHJldHVybiBuZXcgYXJyYXkgYW5kIHJlbWFpbmRlclxuICAgICAgICB2YXIgb3V0ID0gdXBkYXRlQXJyYXkodXBkYXRlUHJvcHNbaV0udGFyZ2V0LCB1cGRhdGVQcm9wc1tpXS5pbnNlcnQsIG1heHApO1xuICAgICAgICBwcm9wLnNldChvdXRbMF0pO1xuXG4gICAgICAgIC8vIGJ1aWxkIHRoZSBpbnZlcnNlIHVwZGF0ZSBvYmplY3QgZm9yIHRoZSB1bmRvIG9wZXJhdGlvblxuICAgICAgICBpZighQXJyYXkuaXNBcnJheSh1bmRvVXBkYXRlW3Byb3AuYXN0cl0pKSB1bmRvVXBkYXRlW3Byb3AuYXN0cl0gPSBbXTtcbiAgICAgICAgdW5kb1VwZGF0ZVtwcm9wLmFzdHJdLnB1c2gob3V0WzFdKTtcblxuICAgICAgICAgLy8gYnVpbGQgdGhlIG1hdGNoaW5nIG1heFBvaW50cyB1bmRvIG9iamVjdCBjb250YWluaW5nIG9yaWdpbmFsIHRyYWNlIGxlbmd0aHNcbiAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkodW5kb1BvaW50c1twcm9wLmFzdHJdKSkgdW5kb1BvaW50c1twcm9wLmFzdHJdID0gW107XG4gICAgICAgIHVuZG9Qb2ludHNbcHJvcC5hc3RyXS5wdXNoKHVwZGF0ZVByb3BzW2ldLnRhcmdldC5sZW5ndGgpO1xuICAgIH1cblxuICAgIHJldHVybiB7dXBkYXRlOiB1bmRvVXBkYXRlLCBtYXhQb2ludHM6IHVuZG9Qb2ludHN9O1xufVxuXG5mdW5jdGlvbiBjb25jYXRUeXBlZEFycmF5KGFycjAsIGFycjEpIHtcbiAgICB2YXIgYXJyMiA9IG5ldyBhcnIwLmNvbnN0cnVjdG9yKGFycjAubGVuZ3RoICsgYXJyMS5sZW5ndGgpO1xuICAgIGFycjIuc2V0KGFycjApO1xuICAgIGFycjIuc2V0KGFycjEsIGFycjAubGVuZ3RoKTtcbiAgICByZXR1cm4gYXJyMjtcbn1cblxuLyoqXG4gKiBleHRlbmQgJiYgcHJlcGVuZCB0cmFjZXMgYXQgaW5kaWNlcyB3aXRoIHVwZGF0ZSBhcnJheXMsIHdpbmRvdyB0cmFjZSBsZW5ndGhzIHRvIG1heFBvaW50c1xuICpcbiAqIEV4dGVuZCBhbmQgUHJlcGVuZCBoYXZlIGlkZW50aWNhbCBBUElzLiBQcmVwZW5kIGluc2VydHMgYW4gYXJyYXkgYXQgdGhlIGhlYWQgd2hpbGUgRXh0ZW5kXG4gKiBpbnNlcnRzIGFuIGFycmF5IG9mZiB0aGUgdGFpbC4gUHJlcGVuZCB0cnVuY2F0ZXMgdGhlIHRhaWwgb2YgdGhlIGFycmF5IC0gY291bnRpbmcgbWF4UG9pbnRzXG4gKiBmcm9tIHRoZSBoZWFkLCB3aGVyZWFzIEV4dGVuZCB0cnVuY2F0ZXMgdGhlIGhlYWQgb2YgdGhlIGFycmF5LCBjb3VudGluZyBiYWNrd2FyZCBtYXhQb2ludHNcbiAqIGZyb20gdGhlIHRhaWwuXG4gKlxuICogSWYgbWF4UG9pbnRzIGlzIHVuZGVmaW5lZCwgbm9uTnVtZXJpYywgbmVnYXRpdmUgb3IgZ3JlYXRlciB0aGFuIGV4dGVuZGVkIHRyYWNlIGxlbmd0aCBub1xuICogdHJ1bmNhdGlvbiAvIHdpbmRvd2luZyB3aWxsIGJlIHBlcmZvcm1lZC4gSWYgaXRzIHplcm8sIHdlbGwgdGhlIHdob2xlIHRyYWNlIGlzIHRydW5jYXRlZC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdHxIVE1MRGl2RWxlbWVudH0gZ2QgVGhlIGdyYXBoIGRpdlxuICogQHBhcmFtIHtPYmplY3R9IHVwZGF0ZSBUaGUga2V5OmFycmF5IG1hcCBvZiB0YXJnZXQgYXR0cmlidXRlcyB0byBleHRlbmRcbiAqIEBwYXJhbSB7TnVtYmVyfE51bWJlcltdfSBpbmRpY2VzIFRoZSBsb2NhdGlvbnMgb2YgdHJhY2VzIHRvIGJlIGV4dGVuZGVkXG4gKiBAcGFyYW0ge051bWJlcnxPYmplY3R9IFttYXhQb2ludHNdIE51bWJlciBvZiBwb2ludHMgZm9yIHRyYWNlIHdpbmRvdyBhZnRlciBsZW5ndGhlbmluZy5cbiAqXG4gKi9cbmZ1bmN0aW9uIGV4dGVuZFRyYWNlcyhnZCwgdXBkYXRlLCBpbmRpY2VzLCBtYXhQb2ludHMpIHtcbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVBcnJheSh0YXJnZXQsIGluc2VydCwgbWF4cCkge1xuICAgICAgICB2YXIgbmV3QXJyYXksIHJlbWFpbmRlcjtcblxuICAgICAgICBpZihMaWIuaXNUeXBlZEFycmF5KHRhcmdldCkpIHtcbiAgICAgICAgICAgIGlmKG1heHAgPCAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vbmUgPSBuZXcgdGFyZ2V0LmNvbnN0cnVjdG9yKDApO1xuICAgICAgICAgICAgICAgIHZhciBib3RoID0gY29uY2F0VHlwZWRBcnJheSh0YXJnZXQsIGluc2VydCk7XG5cbiAgICAgICAgICAgICAgICBpZihtYXhwIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICBuZXdBcnJheSA9IGJvdGg7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlciA9IG5vbmU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkgPSBub25lO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5kZXIgPSBib3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV3QXJyYXkgPSBuZXcgdGFyZ2V0LmNvbnN0cnVjdG9yKG1heHApO1xuICAgICAgICAgICAgICAgIHJlbWFpbmRlciA9IG5ldyB0YXJnZXQuY29uc3RydWN0b3IodGFyZ2V0Lmxlbmd0aCArIGluc2VydC5sZW5ndGggLSBtYXhwKTtcblxuICAgICAgICAgICAgICAgIGlmKG1heHAgPT09IGluc2VydC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkuc2V0KGluc2VydCk7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlci5zZXQodGFyZ2V0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYobWF4cCA8IGluc2VydC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG51bWJlck9mSXRlbXNGcm9tSW5zZXJ0ID0gaW5zZXJ0Lmxlbmd0aCAtIG1heHA7XG5cbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkuc2V0KGluc2VydC5zdWJhcnJheShudW1iZXJPZkl0ZW1zRnJvbUluc2VydCkpO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5kZXIuc2V0KHRhcmdldCk7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlci5zZXQoaW5zZXJ0LnN1YmFycmF5KDAsIG51bWJlck9mSXRlbXNGcm9tSW5zZXJ0KSwgdGFyZ2V0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG51bWJlck9mSXRlbXNGcm9tVGFyZ2V0ID0gbWF4cCAtIGluc2VydC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0YXJnZXRCZWdpbiA9IHRhcmdldC5sZW5ndGggLSBudW1iZXJPZkl0ZW1zRnJvbVRhcmdldDtcblxuICAgICAgICAgICAgICAgICAgICBuZXdBcnJheS5zZXQodGFyZ2V0LnN1YmFycmF5KHRhcmdldEJlZ2luKSk7XG4gICAgICAgICAgICAgICAgICAgIG5ld0FycmF5LnNldChpbnNlcnQsIG51bWJlck9mSXRlbXNGcm9tVGFyZ2V0KTtcbiAgICAgICAgICAgICAgICAgICAgcmVtYWluZGVyLnNldCh0YXJnZXQuc3ViYXJyYXkoMCwgdGFyZ2V0QmVnaW4pKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZXdBcnJheSA9IHRhcmdldC5jb25jYXQoaW5zZXJ0KTtcbiAgICAgICAgICAgIHJlbWFpbmRlciA9IChtYXhwID49IDAgJiYgbWF4cCA8IG5ld0FycmF5Lmxlbmd0aCkgP1xuICAgICAgICAgICAgICAgIG5ld0FycmF5LnNwbGljZSgwLCBuZXdBcnJheS5sZW5ndGggLSBtYXhwKSA6XG4gICAgICAgICAgICAgICAgW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW25ld0FycmF5LCByZW1haW5kZXJdO1xuICAgIH1cblxuICAgIHZhciB1bmRvID0gc3BsaWNlVHJhY2VzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cywgdXBkYXRlQXJyYXkpO1xuICAgIHZhciBwcm9taXNlID0gZXhwb3J0cy5yZWRyYXcoZ2QpO1xuICAgIHZhciB1bmRvQXJncyA9IFtnZCwgdW5kby51cGRhdGUsIGluZGljZXMsIHVuZG8ubWF4UG9pbnRzXTtcbiAgICBRdWV1ZS5hZGQoZ2QsIGV4cG9ydHMucHJlcGVuZFRyYWNlcywgdW5kb0FyZ3MsIGV4dGVuZFRyYWNlcywgYXJndW1lbnRzKTtcblxuICAgIHJldHVybiBwcm9taXNlO1xufVxuXG5mdW5jdGlvbiBwcmVwZW5kVHJhY2VzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIGZ1bmN0aW9uIHVwZGF0ZUFycmF5KHRhcmdldCwgaW5zZXJ0LCBtYXhwKSB7XG4gICAgICAgIHZhciBuZXdBcnJheSwgcmVtYWluZGVyO1xuXG4gICAgICAgIGlmKExpYi5pc1R5cGVkQXJyYXkodGFyZ2V0KSkge1xuICAgICAgICAgICAgaWYobWF4cCA8PSAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vbmUgPSBuZXcgdGFyZ2V0LmNvbnN0cnVjdG9yKDApO1xuICAgICAgICAgICAgICAgIHZhciBib3RoID0gY29uY2F0VHlwZWRBcnJheShpbnNlcnQsIHRhcmdldCk7XG5cbiAgICAgICAgICAgICAgICBpZihtYXhwIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICBuZXdBcnJheSA9IGJvdGg7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlciA9IG5vbmU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkgPSBub25lO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5kZXIgPSBib3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV3QXJyYXkgPSBuZXcgdGFyZ2V0LmNvbnN0cnVjdG9yKG1heHApO1xuICAgICAgICAgICAgICAgIHJlbWFpbmRlciA9IG5ldyB0YXJnZXQuY29uc3RydWN0b3IodGFyZ2V0Lmxlbmd0aCArIGluc2VydC5sZW5ndGggLSBtYXhwKTtcblxuICAgICAgICAgICAgICAgIGlmKG1heHAgPT09IGluc2VydC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkuc2V0KGluc2VydCk7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlci5zZXQodGFyZ2V0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYobWF4cCA8IGluc2VydC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG51bWJlck9mSXRlbXNGcm9tSW5zZXJ0ID0gaW5zZXJ0Lmxlbmd0aCAtIG1heHA7XG5cbiAgICAgICAgICAgICAgICAgICAgbmV3QXJyYXkuc2V0KGluc2VydC5zdWJhcnJheSgwLCBudW1iZXJPZkl0ZW1zRnJvbUluc2VydCkpO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5kZXIuc2V0KGluc2VydC5zdWJhcnJheShudW1iZXJPZkl0ZW1zRnJvbUluc2VydCkpO1xuICAgICAgICAgICAgICAgICAgICByZW1haW5kZXIuc2V0KHRhcmdldCwgbnVtYmVyT2ZJdGVtc0Zyb21JbnNlcnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBudW1iZXJPZkl0ZW1zRnJvbVRhcmdldCA9IG1heHAgLSBpbnNlcnQubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgICAgIG5ld0FycmF5LnNldChpbnNlcnQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdBcnJheS5zZXQodGFyZ2V0LnN1YmFycmF5KDAsIG51bWJlck9mSXRlbXNGcm9tVGFyZ2V0KSwgaW5zZXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIHJlbWFpbmRlci5zZXQodGFyZ2V0LnN1YmFycmF5KG51bWJlck9mSXRlbXNGcm9tVGFyZ2V0KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3QXJyYXkgPSBpbnNlcnQuY29uY2F0KHRhcmdldCk7XG4gICAgICAgICAgICByZW1haW5kZXIgPSAobWF4cCA+PSAwICYmIG1heHAgPCBuZXdBcnJheS5sZW5ndGgpID9cbiAgICAgICAgICAgICAgICBuZXdBcnJheS5zcGxpY2UobWF4cCwgbmV3QXJyYXkubGVuZ3RoKSA6XG4gICAgICAgICAgICAgICAgW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW25ld0FycmF5LCByZW1haW5kZXJdO1xuICAgIH1cblxuICAgIHZhciB1bmRvID0gc3BsaWNlVHJhY2VzKGdkLCB1cGRhdGUsIGluZGljZXMsIG1heFBvaW50cywgdXBkYXRlQXJyYXkpO1xuICAgIHZhciBwcm9taXNlID0gZXhwb3J0cy5yZWRyYXcoZ2QpO1xuICAgIHZhciB1bmRvQXJncyA9IFtnZCwgdW5kby51cGRhdGUsIGluZGljZXMsIHVuZG8ubWF4UG9pbnRzXTtcbiAgICBRdWV1ZS5hZGQoZ2QsIGV4cG9ydHMuZXh0ZW5kVHJhY2VzLCB1bmRvQXJncywgcHJlcGVuZFRyYWNlcywgYXJndW1lbnRzKTtcblxuICAgIHJldHVybiBwcm9taXNlO1xufVxuXG4vKipcbiAqIEFkZCBkYXRhIHRyYWNlcyB0byBhbiBleGlzdGluZyBncmFwaCBkaXYuXG4gKlxuICogQHBhcmFtIHtPYmplY3R8SFRNTERpdkVsZW1lbnR9IGdkIFRoZSBncmFwaCBkaXZcbiAqIEBwYXJhbSB7T2JqZWN0W119IGdkLmRhdGEgVGhlIGFycmF5IG9mIHRyYWNlcyB3ZSdyZSBhZGRpbmcgdG9cbiAqIEBwYXJhbSB7T2JqZWN0W118T2JqZWN0fSB0cmFjZXMgVGhlIG9iamVjdCBvciBhcnJheSBvZiBvYmplY3RzIHRvIGFkZFxuICogQHBhcmFtIHtOdW1iZXJbXXxOdW1iZXJ9IFtuZXdJbmRpY2VzPVtnZC5kYXRhLmxlbmd0aF1dIExvY2F0aW9ucyB0byBhZGQgdHJhY2VzXG4gKlxuICovXG5mdW5jdGlvbiBhZGRUcmFjZXMoZ2QsIHRyYWNlcywgbmV3SW5kaWNlcykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIHZhciBjdXJyZW50SW5kaWNlcyA9IFtdO1xuICAgIHZhciB1bmRvRnVuYyA9IGV4cG9ydHMuZGVsZXRlVHJhY2VzO1xuICAgIHZhciByZWRvRnVuYyA9IGFkZFRyYWNlcztcbiAgICB2YXIgdW5kb0FyZ3MgPSBbZ2QsIGN1cnJlbnRJbmRpY2VzXTtcbiAgICB2YXIgcmVkb0FyZ3MgPSBbZ2QsIHRyYWNlc107ICAvLyBubyBuZXdJbmRpY2VzIGhlcmVcbiAgICB2YXIgaTtcbiAgICB2YXIgcHJvbWlzZTtcblxuICAgIC8vIGFsbCB2YWxpZGF0aW9uIGlzIGRvbmUgZWxzZXdoZXJlIHRvIHJlbW92ZSBjbHV0dGVyIGhlcmVcbiAgICBjaGVja0FkZFRyYWNlc0FyZ3MoZ2QsIHRyYWNlcywgbmV3SW5kaWNlcyk7XG5cbiAgICAvLyBtYWtlIHN1cmUgdHJhY2VzIGlzIGFuIGFycmF5XG4gICAgaWYoIUFycmF5LmlzQXJyYXkodHJhY2VzKSkge1xuICAgICAgICB0cmFjZXMgPSBbdHJhY2VzXTtcbiAgICB9XG5cbiAgICAvLyBtYWtlIHN1cmUgdHJhY2VzIGRvIG5vdCByZXBlYXQgZXhpc3Rpbmcgb25lc1xuICAgIHRyYWNlcyA9IHRyYWNlcy5tYXAoZnVuY3Rpb24odHJhY2UpIHtcbiAgICAgICAgcmV0dXJuIExpYi5leHRlbmRGbGF0KHt9LCB0cmFjZSk7XG4gICAgfSk7XG5cbiAgICBoZWxwZXJzLmNsZWFuRGF0YSh0cmFjZXMpO1xuXG4gICAgLy8gYWRkIHRoZSB0cmFjZXMgdG8gZ2QuZGF0YSAobm8gcmVkcmF3aW5nIHlldCEpXG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGdkLmRhdGEucHVzaCh0cmFjZXNbaV0pO1xuICAgIH1cblxuICAgIC8vIHRvIGNvbnRpbnVlLCB3ZSBuZWVkIHRvIGNhbGwgbW92ZVRyYWNlcyB3aGljaCByZXF1aXJlcyBjdXJyZW50SW5kaWNlc1xuICAgIGZvcihpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjdXJyZW50SW5kaWNlcy5wdXNoKC10cmFjZXMubGVuZ3RoICsgaSk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlIHVzZXIgZGlkbid0IGRlZmluZSBuZXdJbmRpY2VzLCB0aGV5IGp1c3Qgd2FudCB0aGUgdHJhY2VzIGFwcGVuZGVkXG4gICAgLy8gaS5lLiwgd2UgY2FuIHNpbXBseSByZWRyYXcgYW5kIGJlIGRvbmVcbiAgICBpZih0eXBlb2YgbmV3SW5kaWNlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcHJvbWlzZSA9IGV4cG9ydHMucmVkcmF3KGdkKTtcbiAgICAgICAgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSBpbmRpY2VzIGlzIHByb3BlcnR5IGRlZmluZWRcbiAgICBpZighQXJyYXkuaXNBcnJheShuZXdJbmRpY2VzKSkge1xuICAgICAgICBuZXdJbmRpY2VzID0gW25ld0luZGljZXNdO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAgIC8vIHRoaXMgaXMgcmVkdW5kYW50LCBidXQgbmVjZXNzYXJ5IHRvIG5vdCBjYXRjaCBsYXRlciBwb3NzaWJsZSBlcnJvcnMhXG4gICAgICAgIGNoZWNrTW92ZVRyYWNlc0FyZ3MoZ2QsIGN1cnJlbnRJbmRpY2VzLCBuZXdJbmRpY2VzKTtcbiAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nLCByZXNldCBnZCB0byBiZSBzYWZlIGFuZCByZXRocm93IGVycm9yXG4gICAgICAgIGdkLmRhdGEuc3BsaWNlKGdkLmRhdGEubGVuZ3RoIC0gdHJhY2VzLmxlbmd0aCwgdHJhY2VzLmxlbmd0aCk7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgIH1cblxuICAgIC8vIGlmIHdlJ3JlIGhlcmUsIHRoZSB1c2VyIGhhcyBkZWZpbmVkIHNwZWNpZmljIHBsYWNlcyB0byBwbGFjZSB0aGUgbmV3IHRyYWNlc1xuICAgIC8vIHRoaXMgcmVxdWlyZXMgc29tZSBleHRyYSB3b3JrIHRoYXQgbW92ZVRyYWNlcyB3aWxsIGRvXG4gICAgUXVldWUuc3RhcnRTZXF1ZW5jZShnZCk7XG4gICAgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG4gICAgcHJvbWlzZSA9IGV4cG9ydHMubW92ZVRyYWNlcyhnZCwgY3VycmVudEluZGljZXMsIG5ld0luZGljZXMpO1xuICAgIFF1ZXVlLnN0b3BTZXF1ZW5jZShnZCk7XG4gICAgcmV0dXJuIHByb21pc2U7XG59XG5cbi8qKlxuICogRGVsZXRlIHRyYWNlcyBhdCBgaW5kaWNlc2AgZnJvbSBnZC5kYXRhIGFycmF5LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fEhUTUxEaXZFbGVtZW50fSBnZCBUaGUgZ3JhcGggZGl2XG4gKiBAcGFyYW0ge09iamVjdFtdfSBnZC5kYXRhIFRoZSBhcnJheSBvZiB0cmFjZXMgd2UncmUgcmVtb3ZpbmcgZnJvbVxuICogQHBhcmFtIHtOdW1iZXJ8TnVtYmVyW119IGluZGljZXMgVGhlIGluZGljZXNcbiAqL1xuZnVuY3Rpb24gZGVsZXRlVHJhY2VzKGdkLCBpbmRpY2VzKSB7XG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuXG4gICAgdmFyIHRyYWNlcyA9IFtdO1xuICAgIHZhciB1bmRvRnVuYyA9IGV4cG9ydHMuYWRkVHJhY2VzO1xuICAgIHZhciByZWRvRnVuYyA9IGRlbGV0ZVRyYWNlcztcbiAgICB2YXIgdW5kb0FyZ3MgPSBbZ2QsIHRyYWNlcywgaW5kaWNlc107XG4gICAgdmFyIHJlZG9BcmdzID0gW2dkLCBpbmRpY2VzXTtcbiAgICB2YXIgaTtcbiAgICB2YXIgZGVsZXRlZFRyYWNlO1xuXG4gICAgLy8gbWFrZSBzdXJlIGluZGljZXMgYXJlIGRlZmluZWRcbiAgICBpZih0eXBlb2YgaW5kaWNlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbmRpY2VzIG11c3QgYmUgYW4gaW50ZWdlciBvciBhcnJheSBvZiBpbnRlZ2Vycy4nKTtcbiAgICB9IGVsc2UgaWYoIUFycmF5LmlzQXJyYXkoaW5kaWNlcykpIHtcbiAgICAgICAgaW5kaWNlcyA9IFtpbmRpY2VzXTtcbiAgICB9XG4gICAgYXNzZXJ0SW5kZXhBcnJheShnZCwgaW5kaWNlcywgJ2luZGljZXMnKTtcblxuICAgIC8vIGNvbnZlcnQgbmVnYXRpdmUgaW5kaWNlcyB0byBwb3NpdGl2ZSBpbmRpY2VzXG4gICAgaW5kaWNlcyA9IHBvc2l0aXZpZnlJbmRpY2VzKGluZGljZXMsIGdkLmRhdGEubGVuZ3RoIC0gMSk7XG5cbiAgICAvLyB3ZSB3YW50IGRlc2NlbmRpbmcgaGVyZSBzbyB0aGF0IHNwbGljaW5nIGxhdGVyIGRvZXNuJ3QgYWZmZWN0IGluZGV4aW5nXG4gICAgaW5kaWNlcy5zb3J0KExpYi5zb3J0ZXJEZXMpO1xuICAgIGZvcihpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgZGVsZXRlZFRyYWNlID0gZ2QuZGF0YS5zcGxpY2UoaW5kaWNlc1tpXSwgMSlbMF07XG4gICAgICAgIHRyYWNlcy5wdXNoKGRlbGV0ZWRUcmFjZSk7XG4gICAgfVxuXG4gICAgdmFyIHByb21pc2UgPSBleHBvcnRzLnJlZHJhdyhnZCk7XG4gICAgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG5cbiAgICByZXR1cm4gcHJvbWlzZTtcbn1cblxuLyoqXG4gKiBNb3ZlIHRyYWNlcyBhdCBjdXJyZW50SW5kaWNlcyBhcnJheSB0byBsb2NhdGlvbnMgaW4gbmV3SW5kaWNlcyBhcnJheS5cbiAqXG4gKiBJZiBuZXdJbmRpY2VzIGlzIG9taXR0ZWQsIGN1cnJlbnRJbmRpY2VzIHdpbGwgYmUgbW92ZWQgdG8gdGhlIGVuZC4gRS5nLixcbiAqIHRoZXNlIGFyZSBlcXVpdmFsZW50OlxuICpcbiAqIFBsb3RseS5tb3ZlVHJhY2VzKGdkLCBbMSwgMiwgM10sIFstMywgLTIsIC0xXSlcbiAqIFBsb3RseS5tb3ZlVHJhY2VzKGdkLCBbMSwgMiwgM10pXG4gKlxuICogQHBhcmFtIHtPYmplY3R8SFRNTERpdkVsZW1lbnR9IGdkIFRoZSBncmFwaCBkaXZcbiAqIEBwYXJhbSB7T2JqZWN0W119IGdkLmRhdGEgVGhlIGFycmF5IG9mIHRyYWNlcyB3ZSdyZSByZW1vdmluZyBmcm9tXG4gKiBAcGFyYW0ge051bWJlcnxOdW1iZXJbXX0gY3VycmVudEluZGljZXMgVGhlIGxvY2F0aW9ucyBvZiB0cmFjZXMgdG8gYmUgbW92ZWRcbiAqIEBwYXJhbSB7TnVtYmVyfE51bWJlcltdfSBbbmV3SW5kaWNlc10gVGhlIGxvY2F0aW9ucyB0byBtb3ZlIHRyYWNlcyB0b1xuICpcbiAqIEV4YW1wbGUgY2FsbHM6XG4gKlxuICogICAgICAvLyBtb3ZlIHRyYWNlIGkgdG8gbG9jYXRpb24geFxuICogICAgICBQbG90bHkubW92ZVRyYWNlcyhnZCwgaSwgeClcbiAqXG4gKiAgICAgIC8vIG1vdmUgdHJhY2UgaSB0byBlbmQgb2YgYXJyYXlcbiAqICAgICAgUGxvdGx5Lm1vdmVUcmFjZXMoZ2QsIGkpXG4gKlxuICogICAgICAvLyBtb3ZlIHRyYWNlcyBpLCBqLCBrIHRvIGVuZCBvZiBhcnJheSAoaSAhPSBqICE9IGspXG4gKiAgICAgIFBsb3RseS5tb3ZlVHJhY2VzKGdkLCBbaSwgaiwga10pXG4gKlxuICogICAgICAvLyBtb3ZlIHRyYWNlcyBbaSwgaiwga10gdG8gW3gsIHksIHpdIChpICE9IGogIT0gaykgKHggIT0geSAhPSB6KVxuICogICAgICBQbG90bHkubW92ZVRyYWNlcyhnZCwgW2ksIGosIGtdLCBbeCwgeSwgel0pXG4gKlxuICogICAgICAvLyByZW9yZGVyIGFsbCB0cmFjZXMgKGFzc3VtZSB0aGVyZSBhcmUgNS0tYSwgYiwgYywgZCwgZSlcbiAqICAgICAgUGxvdGx5Lm1vdmVUcmFjZXMoZ2QsIFtiLCBkLCBlLCBhLCBjXSkgIC8vIHNhbWUgYXMgJ21vdmUgdG8gZW5kJ1xuICovXG5mdW5jdGlvbiBtb3ZlVHJhY2VzKGdkLCBjdXJyZW50SW5kaWNlcywgbmV3SW5kaWNlcykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIHZhciBuZXdEYXRhID0gW107XG4gICAgdmFyIG1vdmluZ1RyYWNlTWFwID0gW107XG4gICAgdmFyIHVuZG9GdW5jID0gbW92ZVRyYWNlcztcbiAgICB2YXIgcmVkb0Z1bmMgPSBtb3ZlVHJhY2VzO1xuICAgIHZhciB1bmRvQXJncyA9IFtnZCwgbmV3SW5kaWNlcywgY3VycmVudEluZGljZXNdO1xuICAgIHZhciByZWRvQXJncyA9IFtnZCwgY3VycmVudEluZGljZXMsIG5ld0luZGljZXNdO1xuICAgIHZhciBpO1xuXG4gICAgLy8gdG8gcmVkdWNlIGNvbXBsZXhpdHkgaGVyZSwgY2hlY2sgYXJncyBlbHNld2hlcmVcbiAgICAvLyB0aGlzIHRocm93cyBlcnJvcnMgd2hlcmUgYXBwcm9wcmlhdGVcbiAgICBjaGVja01vdmVUcmFjZXNBcmdzKGdkLCBjdXJyZW50SW5kaWNlcywgbmV3SW5kaWNlcyk7XG5cbiAgICAvLyBtYWtlIHN1cmUgY3VycmVudEluZGljZXMgaXMgYW4gYXJyYXlcbiAgICBjdXJyZW50SW5kaWNlcyA9IEFycmF5LmlzQXJyYXkoY3VycmVudEluZGljZXMpID8gY3VycmVudEluZGljZXMgOiBbY3VycmVudEluZGljZXNdO1xuXG4gICAgLy8gaWYgdW5kZWZpbmVkLCBkZWZpbmUgbmV3SW5kaWNlcyB0byBwb2ludCB0byB0aGUgZW5kIG9mIGdkLmRhdGEgYXJyYXlcbiAgICBpZih0eXBlb2YgbmV3SW5kaWNlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgbmV3SW5kaWNlcyA9IFtdO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjdXJyZW50SW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbmV3SW5kaWNlcy5wdXNoKC1jdXJyZW50SW5kaWNlcy5sZW5ndGggKyBpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSBuZXdJbmRpY2VzIGlzIGFuIGFycmF5IGlmIGl0J3MgdXNlci1kZWZpbmVkXG4gICAgbmV3SW5kaWNlcyA9IEFycmF5LmlzQXJyYXkobmV3SW5kaWNlcykgPyBuZXdJbmRpY2VzIDogW25ld0luZGljZXNdO1xuXG4gICAgLy8gY29udmVydCBuZWdhdGl2ZSBpbmRpY2VzIHRvIHBvc2l0aXZlIGluZGljZXMgKHRoZXkncmUgdGhlIHNhbWUgbGVuZ3RoKVxuICAgIGN1cnJlbnRJbmRpY2VzID0gcG9zaXRpdmlmeUluZGljZXMoY3VycmVudEluZGljZXMsIGdkLmRhdGEubGVuZ3RoIC0gMSk7XG4gICAgbmV3SW5kaWNlcyA9IHBvc2l0aXZpZnlJbmRpY2VzKG5ld0luZGljZXMsIGdkLmRhdGEubGVuZ3RoIC0gMSk7XG5cbiAgICAvLyBhdCB0aGlzIHBvaW50LCB3ZSd2ZSBjb2VyY2VkIHRoZSBpbmRleCBhcnJheXMgaW50byBwcmVkaWN0YWJsZSBmb3Jtc1xuXG4gICAgLy8gZ2V0IHRoZSB0cmFjZXMgdGhhdCBhcmVuJ3QgYmVpbmcgbW92ZWQgYXJvdW5kXG4gICAgZm9yKGkgPSAwOyBpIDwgZ2QuZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAvLyBpZiBpbmRleCBpc24ndCBpbiBjdXJyZW50SW5kaWNlcywgaW5jbHVkZSBpdCBpbiBpZ25vcmVkIVxuICAgICAgICBpZihjdXJyZW50SW5kaWNlcy5pbmRleE9mKGkpID09PSAtMSkge1xuICAgICAgICAgICAgbmV3RGF0YS5wdXNoKGdkLmRhdGFbaV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZ2V0IGEgbWFwcGluZyBvZiBpbmRpY2VzIHRvIG1vdmluZyB0cmFjZXNcbiAgICBmb3IoaSA9IDA7IGkgPCBjdXJyZW50SW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBtb3ZpbmdUcmFjZU1hcC5wdXNoKHtuZXdJbmRleDogbmV3SW5kaWNlc1tpXSwgdHJhY2U6IGdkLmRhdGFbY3VycmVudEluZGljZXNbaV1dfSk7XG4gICAgfVxuXG4gICAgLy8gcmVvcmRlciB0aGlzIG1hcHBpbmcgYnkgbmV3SW5kZXgsIGFzY2VuZGluZ1xuICAgIG1vdmluZ1RyYWNlTWFwLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICByZXR1cm4gYS5uZXdJbmRleCAtIGIubmV3SW5kZXg7XG4gICAgfSk7XG5cbiAgICAvLyBub3csIGFkZCB0aGUgbW92aW5nIHRyYWNlcyBiYWNrIGluLCBpbiBvcmRlciFcbiAgICBmb3IoaSA9IDA7IGkgPCBtb3ZpbmdUcmFjZU1hcC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBuZXdEYXRhLnNwbGljZShtb3ZpbmdUcmFjZU1hcFtpXS5uZXdJbmRleCwgMCwgbW92aW5nVHJhY2VNYXBbaV0udHJhY2UpO1xuICAgIH1cblxuICAgIGdkLmRhdGEgPSBuZXdEYXRhO1xuXG4gICAgdmFyIHByb21pc2UgPSBleHBvcnRzLnJlZHJhdyhnZCk7XG4gICAgUXVldWUuYWRkKGdkLCB1bmRvRnVuYywgdW5kb0FyZ3MsIHJlZG9GdW5jLCByZWRvQXJncyk7XG5cbiAgICByZXR1cm4gcHJvbWlzZTtcbn1cblxuLyoqXG4gKiByZXN0eWxlOiB1cGRhdGUgdHJhY2UgYXR0cmlidXRlcyBvZiBhbiBleGlzdGluZyBwbG90XG4gKlxuICogQ2FuIGJlIGNhbGxlZCB0d28gd2F5cy5cbiAqXG4gKiBTaWduYXR1cmUgMTpcbiAqIEBwYXJhbSB7U3RyaW5nIHwgSFRNTERpdkVsZW1lbnR9IGdkXG4gKiAgdGhlIGlkIG9yIERPTSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKiBAcGFyYW0ge1N0cmluZ30gYXN0clxuICogIGF0dHJpYnV0ZSBzdHJpbmcgKGxpa2UgYCdtYXJrZXIuc3ltYm9sJ2ApIHRvIHVwZGF0ZVxuICogQHBhcmFtIHsqfSB2YWxcbiAqICB2YWx1ZSB0byBnaXZlIHRoaXMgYXR0cmlidXRlXG4gKiBAcGFyYW0ge051bWJlcltdIHwgTnVtYmVyfSBbdHJhY2VzXVxuICogIGludGVnZXIgb3IgYXJyYXkgb2YgaW50ZWdlcnMgZm9yIHRoZSB0cmFjZXMgdG8gYWx0ZXIgKGFsbCBpZiBvbWl0dGVkKVxuICpcbiAqIFNpZ25hdHVyZSAyOlxuICogQHBhcmFtIHtTdHJpbmcgfCBIVE1MRGl2RWxlbWVudH0gZ2RcbiAqICAoYXMgaW4gc2lnbmF0dXJlIDEpXG4gKiBAcGFyYW0ge09iamVjdH0gYW9ialxuICogIGF0dHJpYnV0ZSBvYmplY3QgYHthc3RyMTogdmFsMSwgYXN0cjI6IHZhbDIgLi4ufWBcbiAqICBhbGxvd3Mgc2V0dGluZyBtdWx0aXBsZSBhdHRyaWJ1dGVzIHNpbXVsdGFuZW91c2x5XG4gKiBAcGFyYW0ge051bWJlcltdIHwgTnVtYmVyfSBbdHJhY2VzXVxuICogIChhcyBpbiBzaWduYXR1cmUgMSlcbiAqXG4gKiBgdmFsYCAob3IgYHZhbDFgLCBgdmFsMmAgLi4uIGluIHRoZSBvYmplY3QgZm9ybSkgY2FuIGJlIGFuIGFycmF5LFxuICogdG8gYXBwbHkgZGlmZmVyZW50IHZhbHVlcyB0byBlYWNoIHRyYWNlLlxuICpcbiAqIElmIHRoZSBhcnJheSBpcyB0b28gc2hvcnQsIGl0IHdpbGwgd3JhcCBhcm91bmQgKHVzZWZ1bCBmb3JcbiAqIHN0eWxlIGZpbGVzIHRoYXQgd2FudCB0byBzcGVjaWZ5IGN5Y2xpY2FsIGRlZmF1bHQgdmFsdWVzKS5cbiAqL1xuZnVuY3Rpb24gcmVzdHlsZShnZCwgYXN0ciwgdmFsLCBfdHJhY2VzKSB7XG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuICAgIGhlbHBlcnMuY2xlYXJQcm9taXNlUXVldWUoZ2QpO1xuXG4gICAgdmFyIGFvYmogPSB7fTtcbiAgICBpZih0eXBlb2YgYXN0ciA9PT0gJ3N0cmluZycpIGFvYmpbYXN0cl0gPSB2YWw7XG4gICAgZWxzZSBpZihMaWIuaXNQbGFpbk9iamVjdChhc3RyKSkge1xuICAgICAgICAvLyB0aGUgMy1hcmcgZm9ybVxuICAgICAgICBhb2JqID0gTGliLmV4dGVuZEZsYXQoe30sIGFzdHIpO1xuICAgICAgICBpZihfdHJhY2VzID09PSB1bmRlZmluZWQpIF90cmFjZXMgPSB2YWw7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgTGliLndhcm4oJ1Jlc3R5bGUgZmFpbC4nLCBhc3RyLCB2YWwsIF90cmFjZXMpO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoKTtcbiAgICB9XG5cbiAgICBpZihPYmplY3Qua2V5cyhhb2JqKS5sZW5ndGgpIGdkLmNoYW5nZWQgPSB0cnVlO1xuXG4gICAgdmFyIHRyYWNlcyA9IGhlbHBlcnMuY29lcmNlVHJhY2VJbmRpY2VzKGdkLCBfdHJhY2VzKTtcblxuICAgIHZhciBzcGVjcyA9IF9yZXN0eWxlKGdkLCBhb2JqLCB0cmFjZXMpO1xuICAgIHZhciBmbGFncyA9IHNwZWNzLmZsYWdzO1xuXG4gICAgLy8gY2xlYXIgY2FsY2RhdGEgYW5kL29yIGF4aXMgdHlwZXMgaWYgcmVxdWlyZWQgc28gdGhleSBnZXQgcmVnZW5lcmF0ZWRcbiAgICBpZihmbGFncy5jYWxjKSBnZC5jYWxjZGF0YSA9IHVuZGVmaW5lZDtcbiAgICBpZihmbGFncy5jbGVhckF4aXNUeXBlcykgaGVscGVycy5jbGVhckF4aXNUeXBlcyhnZCwgdHJhY2VzLCB7fSk7XG5cbiAgICAvLyBmaWxsIGluIHJlZHJhdyBzZXF1ZW5jZVxuICAgIHZhciBzZXEgPSBbXTtcblxuICAgIGlmKGZsYWdzLmZ1bGxSZXBsb3QpIHtcbiAgICAgICAgc2VxLnB1c2goZXhwb3J0cy5wbG90KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzZXEucHVzaChQbG90cy5wcmV2aW91c1Byb21pc2VzKTtcblxuICAgICAgICAvLyBtYXliZSBvbmx5IGNhbGwgUGxvdHMuc3VwcGx5RGF0YURlZmF1bHRzIGluIHRoZSBzcGxvbSBjYXNlLFxuICAgICAgICAvLyB0byBza2lwIG92ZXIgbG9uZyBhbmQgc2xvdyBheGVzIGRlZmF1bHRzXG4gICAgICAgIFBsb3RzLnN1cHBseURlZmF1bHRzKGdkKTtcblxuICAgICAgICBpZihmbGFncy5tYXJrZXJTaXplKSB7XG4gICAgICAgICAgICBQbG90cy5kb0NhbGNkYXRhKGdkKTtcbiAgICAgICAgICAgIGFkZEF4UmFuZ2VTZXF1ZW5jZShzZXEpO1xuXG4gICAgICAgICAgICAvLyBUT0RPXG4gICAgICAgICAgICAvLyBpZiBhbGwgYXhlcyBoYXZlIGF1dG9yYW5nZTpmYWxzZSwgdGhlblxuICAgICAgICAgICAgLy8gcHJvY2VlZCB0byBzdWJyb3V0aW5lcy5kb1RyYWNlU3R5bGUoKSxcbiAgICAgICAgICAgIC8vIG90aGVyd2lzZSB3ZSBtdXN0IGdvIHRocm91Z2ggYWRkQXhSYW5nZVNlcXVlbmNlLFxuICAgICAgICAgICAgLy8gd2hpY2ggaW4gZ2VuZXJhbCBtdXN0IHJlZHJhd3MgJ2FsbCcgYXhlc1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZmxhZ3Muc3R5bGUpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmRvVHJhY2VTdHlsZSk7XG4gICAgICAgIGlmKGZsYWdzLmNvbG9yYmFycykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Db2xvckJhcnMpO1xuXG4gICAgICAgIHNlcS5wdXNoKGVtaXRBZnRlclBsb3QpO1xuICAgIH1cblxuICAgIHNlcS5wdXNoKFBsb3RzLnJlaG92ZXIsIFBsb3RzLnJlZHJhZyk7XG5cbiAgICBRdWV1ZS5hZGQoZ2QsXG4gICAgICAgIHJlc3R5bGUsIFtnZCwgc3BlY3MudW5kb2l0LCBzcGVjcy50cmFjZXNdLFxuICAgICAgICByZXN0eWxlLCBbZ2QsIHNwZWNzLnJlZG9pdCwgc3BlY3MudHJhY2VzXVxuICAgICk7XG5cbiAgICB2YXIgcGxvdERvbmUgPSBMaWIuc3luY09yQXN5bmMoc2VxLCBnZCk7XG4gICAgaWYoIXBsb3REb25lIHx8ICFwbG90RG9uZS50aGVuKSBwbG90RG9uZSA9IFByb21pc2UucmVzb2x2ZSgpO1xuXG4gICAgcmV0dXJuIHBsb3REb25lLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9yZXN0eWxlJywgc3BlY3MuZXZlbnREYXRhKTtcbiAgICAgICAgcmV0dXJuIGdkO1xuICAgIH0pO1xufVxuXG4vLyBmb3IgdW5kbzogdW5kZWZpbmVkIGluaXRpYWwgdmFscyBtdXN0IGJlIHR1cm5lZCBpbnRvIG51bGxzXG4vLyBzbyB0aGF0IHdlIHVuc2V0IHJhdGhlciB0aGFuIGlnbm9yZSB0aGVtXG5mdW5jdGlvbiB1bmRlZmluZWRUb051bGwodmFsKSB7XG4gICAgaWYodmFsID09PSB1bmRlZmluZWQpIHJldHVybiBudWxsO1xuICAgIHJldHVybiB2YWw7XG59XG5cbi8qKlxuICogRmFjdG9yeSBmdW5jdGlvbiB0byB3cmFwIG5lc3RlZFByb3BlcnR5IHdpdGggR1VJIGVkaXRzIGlmIG5lY2Vzc2FyeVxuICogd2l0aCBHVUkgZWRpdHMgd2UgYWRkIGFuIG9wdGlvbmFsIHByZWZpeCB0byB0aGUgbmVzdGVkUHJvcGVydHkgY29uc3RydWN0b3JcbiAqIHRvIHByZXBlbmQgdG8gdGhlIGF0dHJpYnV0ZSBzdHJpbmcgaW4gdGhlIHByZUdVSSBzdG9yZS5cbiAqL1xuZnVuY3Rpb24gbWFrZU5QKHByZUdVSSwgZ3VpRWRpdEZsYWcpIHtcbiAgICBpZighZ3VpRWRpdEZsYWcpIHJldHVybiBuZXN0ZWRQcm9wZXJ0eTtcblxuICAgIHJldHVybiBmdW5jdGlvbihjb250YWluZXIsIGF0dHIsIHByZWZpeCkge1xuICAgICAgICB2YXIgbnAgPSBuZXN0ZWRQcm9wZXJ0eShjb250YWluZXIsIGF0dHIpO1xuICAgICAgICB2YXIgbnBTZXQgPSBucC5zZXQ7XG4gICAgICAgIG5wLnNldCA9IGZ1bmN0aW9uKHZhbCkge1xuICAgICAgICAgICAgdmFyIGZ1bGxBdHRyID0gKHByZWZpeCB8fCAnJykgKyBhdHRyO1xuICAgICAgICAgICAgc3RvcmVDdXJyZW50KGZ1bGxBdHRyLCBucC5nZXQoKSwgdmFsLCBwcmVHVUkpO1xuICAgICAgICAgICAgbnBTZXQodmFsKTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIG5wO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIHN0b3JlQ3VycmVudChhdHRyLCB2YWwsIG5ld1ZhbCwgcHJlR1VJKSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheSh2YWwpIHx8IEFycmF5LmlzQXJyYXkobmV3VmFsKSkge1xuICAgICAgICB2YXIgYXJyYXlWYWwgPSBBcnJheS5pc0FycmF5KHZhbCkgPyB2YWwgOiBbXTtcbiAgICAgICAgdmFyIGFycmF5TmV3ID0gQXJyYXkuaXNBcnJheShuZXdWYWwpID8gbmV3VmFsIDogW107XG4gICAgICAgIHZhciBtYXhMZW4gPSBNYXRoLm1heChhcnJheVZhbC5sZW5ndGgsIGFycmF5TmV3Lmxlbmd0aCk7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBtYXhMZW47IGkrKykge1xuICAgICAgICAgICAgc3RvcmVDdXJyZW50KGF0dHIgKyAnWycgKyBpICsgJ10nLCBhcnJheVZhbFtpXSwgYXJyYXlOZXdbaV0sIHByZUdVSSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYoTGliLmlzUGxhaW5PYmplY3QodmFsKSB8fCBMaWIuaXNQbGFpbk9iamVjdChuZXdWYWwpKSB7XG4gICAgICAgIHZhciBvYmpWYWwgPSBMaWIuaXNQbGFpbk9iamVjdCh2YWwpID8gdmFsIDoge307XG4gICAgICAgIHZhciBvYmpOZXcgPSBMaWIuaXNQbGFpbk9iamVjdChuZXdWYWwpID8gbmV3VmFsIDoge307XG4gICAgICAgIHZhciBvYmpCb3RoID0gTGliLmV4dGVuZEZsYXQoe30sIG9ialZhbCwgb2JqTmV3KTtcbiAgICAgICAgZm9yKHZhciBrZXkgaW4gb2JqQm90aCkge1xuICAgICAgICAgICAgc3RvcmVDdXJyZW50KGF0dHIgKyAnLicgKyBrZXksIG9ialZhbFtrZXldLCBvYmpOZXdba2V5XSwgcHJlR1VJKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZihwcmVHVUlbYXR0cl0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBwcmVHVUlbYXR0cl0gPSB1bmRlZmluZWRUb051bGwodmFsKTtcbiAgICB9XG59XG5cbi8qKlxuICogc3RvcmVEaXJlY3RHVUlFZGl0OiBmb3Igcm91dGluZXMgdGhhdCBza2lwIHJlc3R5bGUvcmVsYXlvdXQgYW5kIG1vY2sgaXRcbiAqIGJ5IGVtaXR0aW5nIGEgcGxvdGx5X3Jlc3R5bGUgb3IgcGxvdGx5X3JlbGF5b3V0IGV2ZW50LCB0aGlzIHJvdXRpbmVcbiAqIGtlZXBzIHRyYWNrIG9mIHRoZSBpbml0aWFsIHN0YXRlIGluIF9wcmVHVUkgZm9yIHVzZSBieSB1aXJldmlzaW9uXG4gKiBEb2VzICpub3QqIGFwcGx5IHRoZXNlIGNoYW5nZXMgdG8gZGF0YS9sYXlvdXQgLSB0aGF0J3MgdGhlIHJlc3BvbnNpYmlsaXR5XG4gKiBvZiB0aGUgY2FsbGluZyByb3V0aW5lLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb250YWluZXI6IHRoZSBpbnB1dCBhdHRyaWJ1dGVzIGNvbnRhaW5lciAoZWcgYGxheW91dGAgb3IgYSBgdHJhY2VgKVxuICogQHBhcmFtIHtvYmplY3R9IHByZUdVSTogd2hlcmUgb3JpZ2luYWwgdmFsdWVzIHNob3VsZCBiZSBzdG9yZWQsIGVpdGhlclxuICogICAgIGBsYXlvdXQuX3ByZUdVSWAgb3IgYGxheW91dC5fdHJhY2VQcmVHVUlbdWlkXWBcbiAqIEBwYXJhbSB7b2JqZWN0fSBlZGl0czogdGhlIHthdHRyOiB2YWx9IG9iamVjdCBhcyBub3JtYWxseSBwYXNzZWQgdG8gYHJlbGF5b3V0YCBldGNcbiAqL1xuZnVuY3Rpb24gX3N0b3JlRGlyZWN0R1VJRWRpdChjb250YWluZXIsIHByZUdVSSwgZWRpdHMpIHtcbiAgICBmb3IodmFyIGF0dHIgaW4gZWRpdHMpIHtcbiAgICAgICAgdmFyIG5wID0gbmVzdGVkUHJvcGVydHkoY29udGFpbmVyLCBhdHRyKTtcbiAgICAgICAgc3RvcmVDdXJyZW50KGF0dHIsIG5wLmdldCgpLCBlZGl0c1thdHRyXSwgcHJlR1VJKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIF9yZXN0eWxlKGdkLCBhb2JqLCB0cmFjZXMpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBmdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICB2YXIgZGF0YSA9IGdkLmRhdGE7XG4gICAgdmFyIGd1aUVkaXRGbGFnID0gZnVsbExheW91dC5fZ3VpRWRpdGluZztcbiAgICB2YXIgbGF5b3V0TlAgPSBtYWtlTlAoZnVsbExheW91dC5fcHJlR1VJLCBndWlFZGl0RmxhZyk7XG4gICAgdmFyIGV2ZW50RGF0YSA9IExpYi5leHRlbmREZWVwQWxsKHt9LCBhb2JqKTtcbiAgICB2YXIgaTtcblxuICAgIGNsZWFuRGVwcmVjYXRlZEF0dHJpYnV0ZUtleXMoYW9iaik7XG5cbiAgICAvLyBpbml0aWFsaXplIGZsYWdzXG4gICAgdmFyIGZsYWdzID0gZWRpdFR5cGVzLnRyYWNlRmxhZ3MoKTtcblxuICAgIC8vIGNvcGllcyBvZiB0aGUgY2hhbmdlIChhbmQgcHJldmlvdXMgdmFsdWVzIG9mIGFueXRoaW5nIGFmZmVjdGVkKVxuICAgIC8vIGZvciB0aGUgdW5kbyAvIHJlZG8gcXVldWVcbiAgICB2YXIgcmVkb2l0ID0ge307XG4gICAgdmFyIHVuZG9pdCA9IHt9O1xuICAgIHZhciBheGxpc3Q7XG5cbiAgICAvLyBtYWtlIGEgbmV3IGVtcHR5IHZhbHMgYXJyYXkgZm9yIHVuZG9pdFxuICAgIGZ1bmN0aW9uIGEwKCkgeyByZXR1cm4gdHJhY2VzLm1hcChmdW5jdGlvbigpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfSk7IH1cblxuICAgIC8vIGZvciBhdXRvcmFuZ2luZyBtdWx0aXBsZSBheGVzXG4gICAgZnVuY3Rpb24gYWRkVG9BeGxpc3QoYXhpZCkge1xuICAgICAgICB2YXIgYXhOYW1lID0gQXhlcy5pZDJuYW1lKGF4aWQpO1xuICAgICAgICBpZihheGxpc3QuaW5kZXhPZihheE5hbWUpID09PSAtMSkgYXhsaXN0LnB1c2goYXhOYW1lKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhdXRvcmFuZ2VBdHRyKGF4TmFtZSkgeyByZXR1cm4gJ0xBWU9VVCcgKyBheE5hbWUgKyAnLmF1dG9yYW5nZSc7IH1cblxuICAgIGZ1bmN0aW9uIHJhbmdlQXR0cihheE5hbWUpIHsgcmV0dXJuICdMQVlPVVQnICsgYXhOYW1lICsgJy5yYW5nZSc7IH1cblxuICAgIGZ1bmN0aW9uIGdldEZ1bGxUcmFjZSh0cmFjZUluZGV4KSB7XG4gICAgICAgIC8vIHVzdWFsbHkgZnVsbERhdGEgbWFwcyAxOjEgb250byBkYXRhLCBidXQgd2l0aCBncm91cGJ5IHRyYW5zZm9ybXNcbiAgICAgICAgLy8gdGhlIGZ1bGxEYXRhIGluZGV4IGNhbiBiZSBncmVhdGVyLiBUYWtlIHRoZSAqZmlyc3QqIG1hdGNoaW5nIHRyYWNlLlxuICAgICAgICBmb3IodmFyIGogPSB0cmFjZUluZGV4OyBqIDwgZnVsbERhdGEubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKGZ1bGxEYXRhW2pdLl9pbnB1dCA9PT0gZGF0YVt0cmFjZUluZGV4XSkgcmV0dXJuIGZ1bGxEYXRhW2pdO1xuICAgICAgICB9XG4gICAgICAgIC8vIHNob3VsZCBuZXZlciBnZXQgaGVyZSAtIGFuZCBpZiB3ZSAqZG8qIGl0IHNob3VsZCBjYXVzZSBhbiBlcnJvclxuICAgICAgICAvLyBsYXRlciBvbiB1bmRlZmluZWQgZnVsbFRyYWNlIGlzIHBhc3NlZCB0byBuZXN0ZWRQcm9wZXJ0eS5cbiAgICB9XG5cbiAgICAvLyBmb3IgYXR0cnMgdGhhdCBpbnRlcmFjdCAobGlrZSBzY2FsZXMgJiBhdXRvc2NhbGVzKSwgc2F2ZSB0aGVcbiAgICAvLyBvbGQgdmFscyBiZWZvcmUgbWFraW5nIHRoZSBjaGFuZ2VcbiAgICAvLyB2YWw9dW5kZWZpbmVkIHdpbGwgbm90IHNldCBhIHZhbHVlLCBqdXN0IHJlY29yZCB3aGF0IHRoZSB2YWx1ZSB3YXMuXG4gICAgLy8gdmFsPW51bGwgd2lsbCBkZWxldGUgdGhlIGF0dHJpYnV0ZVxuICAgIC8vIGF0dHIgY2FuIGJlIGFuIGFycmF5IHRvIHNldCBzZXZlcmFsIGF0IG9uY2UgKGFsbCB0byB0aGUgc2FtZSB2YWwpXG4gICAgZnVuY3Rpb24gZG9leHRyYShhdHRyLCB2YWwsIGkpIHtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShhdHRyKSkge1xuICAgICAgICAgICAgYXR0ci5mb3JFYWNoKGZ1bmN0aW9uKGEpIHsgZG9leHRyYShhLCB2YWwsIGkpOyB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBxdWl0IGlmIGV4cGxpY2l0bHkgc2V0dGluZyB0aGlzIGVsc2V3aGVyZVxuICAgICAgICBpZihhdHRyIGluIGFvYmogfHwgaGVscGVycy5oYXNQYXJlbnQoYW9iaiwgYXR0cikpIHJldHVybjtcblxuICAgICAgICB2YXIgZXh0cmFwYXJhbTtcbiAgICAgICAgaWYoYXR0ci5zdWJzdHIoMCwgNikgPT09ICdMQVlPVVQnKSB7XG4gICAgICAgICAgICBleHRyYXBhcmFtID0gbGF5b3V0TlAoZ2QubGF5b3V0LCBhdHRyLnJlcGxhY2UoJ0xBWU9VVCcsICcnKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgdHJhY2VpID0gdHJhY2VzW2ldO1xuICAgICAgICAgICAgdmFyIHByZUdVSSA9IGZ1bGxMYXlvdXQuX3RyYWNlUHJlR1VJW2dldEZ1bGxUcmFjZSh0cmFjZWkpLl9mdWxsSW5wdXQudWlkXTtcbiAgICAgICAgICAgIGV4dHJhcGFyYW0gPSBtYWtlTlAocHJlR1VJLCBndWlFZGl0RmxhZykoZGF0YVt0cmFjZWldLCBhdHRyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCEoYXR0ciBpbiB1bmRvaXQpKSB7XG4gICAgICAgICAgICB1bmRvaXRbYXR0cl0gPSBhMCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHVuZG9pdFthdHRyXVtpXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB1bmRvaXRbYXR0cl1baV0gPSB1bmRlZmluZWRUb051bGwoZXh0cmFwYXJhbS5nZXQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYodmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGV4dHJhcGFyYW0uc2V0KHZhbCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhbGxCaW5zKGJpbkF0dHIpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGopIHtcbiAgICAgICAgICAgIHJldHVybiBmdWxsRGF0YVtqXVtiaW5BdHRyXTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhcnJheUJpbnMoYmluQXR0cikge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24odmlqLCBqKSB7XG4gICAgICAgICAgICByZXR1cm4gdmlqID09PSBmYWxzZSA/IGZ1bGxEYXRhW3RyYWNlc1tqXV1bYmluQXR0cl0gOiBudWxsO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIG5vdyBtYWtlIHRoZSBjaGFuZ2VzIHRvIGdkLmRhdGEgKGFuZCBvY2Nhc2lvbmFsbHkgZ2QubGF5b3V0KVxuICAgIC8vIGFuZCBmaWd1cmUgb3V0IHdoYXQga2luZCBvZiBncmFwaGljcyB1cGRhdGUgd2UgbmVlZCB0byBkb1xuICAgIGZvcih2YXIgYWkgaW4gYW9iaikge1xuICAgICAgICBpZihoZWxwZXJzLmhhc1BhcmVudChhb2JqLCBhaSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IHNldCAnICsgYWkgKyAnIGFuZCBhIHBhcmVudCBhdHRyaWJ1dGUgc2ltdWx0YW5lb3VzbHknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2aSA9IGFvYmpbYWldO1xuICAgICAgICB2YXIgY29udDtcbiAgICAgICAgdmFyIGNvbnRGdWxsO1xuICAgICAgICB2YXIgcGFyYW07XG4gICAgICAgIHZhciBvbGRWYWw7XG4gICAgICAgIHZhciBuZXdWYWw7XG4gICAgICAgIHZhciB2YWxPYmplY3Q7XG5cbiAgICAgICAgLy8gQmFja3dhcmQgY29tcGF0aWJpbGl0eSBzaGltIGZvciB0dXJuaW5nIGhpc3RvZ3JhbSBhdXRvYmluIG9uLFxuICAgICAgICAvLyBvciBmcmVlemluZyBwcmV2aW91cyBhdXRvYmlubmVkIHZhbHVlcy5cbiAgICAgICAgLy8gUmVwbGFjZSBvYnNvbGV0ZSBgYXV0b2Jpbih4fHkpOiB0cnVlYCB3aXRoIGAoeHx5KWJpbnM6IG51bGxgXG4gICAgICAgIC8vIGFuZCBgYXV0b2Jpbih4fHkpOiBmYWxzZWAgd2l0aCB0aGUgYCh4fHkpYmluc2AgaW4gYGZ1bGxEYXRhYFxuICAgICAgICBpZihhaSA9PT0gJ2F1dG9iaW54JyB8fCBhaSA9PT0gJ2F1dG9iaW55Jykge1xuICAgICAgICAgICAgYWkgPSBhaS5jaGFyQXQoYWkubGVuZ3RoIC0gMSkgKyAnYmlucyc7XG4gICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KHZpKSkgdmkgPSB2aS5tYXAoYXJyYXlCaW5zKGFpKSk7XG4gICAgICAgICAgICBlbHNlIGlmKHZpID09PSBmYWxzZSkgdmkgPSB0cmFjZXMubWFwKGFsbEJpbnMoYWkpKTtcbiAgICAgICAgICAgIGVsc2UgdmkgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVkb2l0W2FpXSA9IHZpO1xuXG4gICAgICAgIGlmKGFpLnN1YnN0cigwLCA2KSA9PT0gJ0xBWU9VVCcpIHtcbiAgICAgICAgICAgIHBhcmFtID0gbGF5b3V0TlAoZ2QubGF5b3V0LCBhaS5yZXBsYWNlKCdMQVlPVVQnLCAnJykpO1xuICAgICAgICAgICAgdW5kb2l0W2FpXSA9IFt1bmRlZmluZWRUb051bGwocGFyYW0uZ2V0KCkpXTtcbiAgICAgICAgICAgIC8vIHNpbmNlIHdlJ3JlIGFsbG93aW5nIHZhbCB0byBiZSBhbiBhcnJheSwgYWxsb3cgaXQgaGVyZSB0b28sXG4gICAgICAgICAgICAvLyBldmVuIHRob3VnaCB0aGF0J3MgbWVhbmluZ2xlc3NcbiAgICAgICAgICAgIHBhcmFtLnNldChBcnJheS5pc0FycmF5KHZpKSA/IHZpWzBdIDogdmkpO1xuICAgICAgICAgICAgLy8gaXJvbmljYWxseSwgdGhlIGxheW91dCBhdHRycyBpbiByZXN0eWxlIG9ubHkgcmVxdWlyZSByZXBsb3QsXG4gICAgICAgICAgICAvLyBub3QgcmVsYXlvdXRcbiAgICAgICAgICAgIGZsYWdzLmNhbGMgPSB0cnVlO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzZXQgYXR0cmlidXRlIGluIGdkLmRhdGFcbiAgICAgICAgdW5kb2l0W2FpXSA9IGEwKCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udCA9IGRhdGFbdHJhY2VzW2ldXTtcbiAgICAgICAgICAgIGNvbnRGdWxsID0gZ2V0RnVsbFRyYWNlKHRyYWNlc1tpXSk7XG4gICAgICAgICAgICB2YXIgcHJlR1VJID0gZnVsbExheW91dC5fdHJhY2VQcmVHVUlbY29udEZ1bGwuX2Z1bGxJbnB1dC51aWRdO1xuICAgICAgICAgICAgcGFyYW0gPSBtYWtlTlAocHJlR1VJLCBndWlFZGl0RmxhZykoY29udCwgYWkpO1xuICAgICAgICAgICAgb2xkVmFsID0gcGFyYW0uZ2V0KCk7XG4gICAgICAgICAgICBuZXdWYWwgPSBBcnJheS5pc0FycmF5KHZpKSA/IHZpW2kgJSB2aS5sZW5ndGhdIDogdmk7XG5cbiAgICAgICAgICAgIGlmKG5ld1ZhbCA9PT0gdW5kZWZpbmVkKSBjb250aW51ZTtcblxuICAgICAgICAgICAgdmFyIGZpbmFsUGFydCA9IHBhcmFtLnBhcnRzW3BhcmFtLnBhcnRzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgdmFyIHByZWZpeCA9IGFpLnN1YnN0cigwLCBhaS5sZW5ndGggLSBmaW5hbFBhcnQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICB2YXIgcHJlZml4RG90ID0gcHJlZml4ID8gcHJlZml4ICsgJy4nIDogJyc7XG4gICAgICAgICAgICB2YXIgaW5uZXJDb250RnVsbCA9IHByZWZpeCA/XG4gICAgICAgICAgICAgICAgbmVzdGVkUHJvcGVydHkoY29udEZ1bGwsIHByZWZpeCkuZ2V0KCkgOiBjb250RnVsbDtcblxuICAgICAgICAgICAgdmFsT2JqZWN0ID0gUGxvdFNjaGVtYS5nZXRUcmFjZVZhbE9iamVjdChjb250RnVsbCwgcGFyYW0ucGFydHMpO1xuXG4gICAgICAgICAgICBpZih2YWxPYmplY3QgJiYgdmFsT2JqZWN0LmltcGxpZWRFZGl0cyAmJiBuZXdWYWwgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGltcGxpZWRLZXkgaW4gdmFsT2JqZWN0LmltcGxpZWRFZGl0cykge1xuICAgICAgICAgICAgICAgICAgICBkb2V4dHJhKExpYi5yZWxhdGl2ZUF0dHIoYWksIGltcGxpZWRLZXkpLCB2YWxPYmplY3QuaW1wbGllZEVkaXRzW2ltcGxpZWRLZXldLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYoKGZpbmFsUGFydCA9PT0gJ3RoaWNrbmVzc21vZGUnIHx8IGZpbmFsUGFydCA9PT0gJ2xlbm1vZGUnKSAmJlxuICAgICAgICAgICAgICAgICAgICBvbGRWYWwgIT09IG5ld1ZhbCAmJlxuICAgICAgICAgICAgICAgICAgICAobmV3VmFsID09PSAnZnJhY3Rpb24nIHx8IG5ld1ZhbCA9PT0gJ3BpeGVscycpICYmXG4gICAgICAgICAgICAgICAgICAgIGlubmVyQ29udEZ1bGxcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIC8vIGNoYW5naW5nIGNvbG9yYmFyIHNpemUgbW9kZXMsXG4gICAgICAgICAgICAgICAgLy8gbWFrZSB0aGUgcmVzdWx0aW5nIHNpemUgbm90IGNoYW5nZVxuICAgICAgICAgICAgICAgIC8vIG5vdGUgdGhhdCBjb2xvcmJhciBmcmFjdGlvbmFsIHNpemluZyBpcyBiYXNlZCBvbiB0aGVcbiAgICAgICAgICAgICAgICAvLyBvcmlnaW5hbCBwbG90IHNpemUsIGJlZm9yZSBhbnl0aGluZyAobGlrZSBhIGNvbG9yYmFyKVxuICAgICAgICAgICAgICAgIC8vIGluY3JlYXNlcyB0aGUgbWFyZ2luc1xuXG4gICAgICAgICAgICAgICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICAgICAgICAgICAgICB2YXIgb3JpZW50ID0gaW5uZXJDb250RnVsbC5vcmllbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHRvcE9yQm90dG9tID0gKG9yaWVudCA9PT0gJ3RvcCcpIHx8IChvcmllbnQgPT09ICdib3R0b20nKTtcbiAgICAgICAgICAgICAgICBpZihmaW5hbFBhcnQgPT09ICd0aGlja25lc3Ntb2RlJykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGhpY2tub3JtID0gdG9wT3JCb3R0b20gPyBncy5oIDogZ3MudztcbiAgICAgICAgICAgICAgICAgICAgZG9leHRyYShwcmVmaXhEb3QgKyAndGhpY2tuZXNzJywgaW5uZXJDb250RnVsbC50aGlja25lc3MgKlxuICAgICAgICAgICAgICAgICAgICAgICAgKG5ld1ZhbCA9PT0gJ2ZyYWN0aW9uJyA/IDEgLyB0aGlja25vcm0gOiB0aGlja25vcm0pLCBpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVubm9ybSA9IHRvcE9yQm90dG9tID8gZ3MudyA6IGdzLmg7XG4gICAgICAgICAgICAgICAgICAgIGRvZXh0cmEocHJlZml4RG90ICsgJ2xlbicsIGlubmVyQ29udEZ1bGwubGVuICpcbiAgICAgICAgICAgICAgICAgICAgICAgIChuZXdWYWwgPT09ICdmcmFjdGlvbicgPyAxIC8gbGVubm9ybSA6IGxlbm5vcm0pLCBpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYoYWkgPT09ICd0eXBlJyAmJiAoXG4gICAgICAgICAgICAgICAgKG5ld1ZhbCA9PT0gJ3BpZScpICE9PSAob2xkVmFsID09PSAncGllJykgfHxcbiAgICAgICAgICAgICAgICAobmV3VmFsID09PSAnZnVubmVsYXJlYScpICE9PSAob2xkVmFsID09PSAnZnVubmVsYXJlYScpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxhYmVsc1RvID0gJ3gnO1xuICAgICAgICAgICAgICAgIHZhciB2YWx1ZXNUbyA9ICd5JztcbiAgICAgICAgICAgICAgICBpZigobmV3VmFsID09PSAnYmFyJyB8fCBvbGRWYWwgPT09ICdiYXInKSAmJiBjb250Lm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgICAgICAgICAgICAgbGFiZWxzVG8gPSAneSc7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlc1RvID0gJ3gnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBMaWIuc3dhcEF0dHJzKGNvbnQsIFsnPycsICc/c3JjJ10sICdsYWJlbHMnLCBsYWJlbHNUbyk7XG4gICAgICAgICAgICAgICAgTGliLnN3YXBBdHRycyhjb250LCBbJ2Q/JywgJz8wJ10sICdsYWJlbCcsIGxhYmVsc1RvKTtcbiAgICAgICAgICAgICAgICBMaWIuc3dhcEF0dHJzKGNvbnQsIFsnPycsICc/c3JjJ10sICd2YWx1ZXMnLCB2YWx1ZXNUbyk7XG5cbiAgICAgICAgICAgICAgICBpZihvbGRWYWwgPT09ICdwaWUnIHx8IG9sZFZhbCA9PT0gJ2Z1bm5lbGFyZWEnKSB7XG4gICAgICAgICAgICAgICAgICAgIG5lc3RlZFByb3BlcnR5KGNvbnQsICdtYXJrZXIuY29sb3InKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnNldChuZXN0ZWRQcm9wZXJ0eShjb250LCAnbWFya2VyLmNvbG9ycycpLmdldCgpKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBzdXBlciBrbHVkZ3kgLSBidXQgaWYgYWxsIHBpZXMgYXJlIGdvbmUgd2Ugd29uJ3QgcmVtb3ZlIHRoZW0gb3RoZXJ3aXNlXG4gICAgICAgICAgICAgICAgICAgIGZ1bGxMYXlvdXQuX3BpZWxheWVyLnNlbGVjdEFsbCgnZy50cmFjZScpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihSZWdpc3RyeS50cmFjZUlzKGNvbnQsICdjYXJ0ZXNpYW4nKSkge1xuICAgICAgICAgICAgICAgICAgICBuZXN0ZWRQcm9wZXJ0eShjb250LCAnbWFya2VyLmNvbG9ycycpXG4gICAgICAgICAgICAgICAgICAgICAgICAuc2V0KG5lc3RlZFByb3BlcnR5KGNvbnQsICdtYXJrZXIuY29sb3InKS5nZXQoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1bmRvaXRbYWldW2ldID0gdW5kZWZpbmVkVG9OdWxsKG9sZFZhbCk7XG4gICAgICAgICAgICAvLyBzZXQgdGhlIG5ldyB2YWx1ZSAtIGlmIHZhbCBpcyBhbiBhcnJheSwgaXQncyBvbmUgZWwgcGVyIHRyYWNlXG4gICAgICAgICAgICAvLyBmaXJzdCBjaGVjayBmb3IgYXR0cmlidXRlcyB0aGF0IGdldCBtb3JlIGNvbXBsZXggYWx0ZXJhdGlvbnNcbiAgICAgICAgICAgIHZhciBzd2FwQXR0cnMgPSBbXG4gICAgICAgICAgICAgICAgJ3N3YXB4eScsICdzd2FweHlheGVzJywgJ29yaWVudGF0aW9uJywgJ29yaWVudGF0aW9uYXhlcydcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBpZihzd2FwQXR0cnMuaW5kZXhPZihhaSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgLy8gc2V0dGluZyBhbiBvcmllbnRhdGlvbjogbWFrZSBzdXJlIGl0J3MgY2hhbmdpbmdcbiAgICAgICAgICAgICAgICAvLyBiZWZvcmUgd2Ugc3dhcCBldmVyeXRoaW5nIGVsc2VcbiAgICAgICAgICAgICAgICBpZihhaSA9PT0gJ29yaWVudGF0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICBwYXJhbS5zZXQobmV3VmFsKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gb2Jub3hpb3VzIHRoYXQgd2UgbmVlZCB0aGlzIGxldmVsIG9mIGNvdXBsaW5nLi4uIGJ1dCBpbiBvcmRlciB0b1xuICAgICAgICAgICAgICAgICAgICAvLyBwcm9wZXJseSBoYW5kbGUgc2V0dGluZyBvcmllbnRhdGlvbiB0byBgbnVsbGAgd2UgbmVlZCB0byBtaW1pY1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbG9naWMgaW5zaWRlIEJhcnMuc3VwcGx5RGVmYXVsdHMgZm9yIGRlZmF1bHQgb3JpZW50YXRpb25cbiAgICAgICAgICAgICAgICAgICAgdmFyIGRlZmF1bHRPcmllbnRhdGlvbiA9IChjb250LnggJiYgIWNvbnQueSkgPyAnaCcgOiAndic7XG4gICAgICAgICAgICAgICAgICAgIGlmKChwYXJhbS5nZXQoKSB8fCBkZWZhdWx0T3JpZW50YXRpb24pID09PSBjb250RnVsbC5vcmllbnRhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoYWkgPT09ICdvcmllbnRhdGlvbmF4ZXMnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIG9yaWVudGF0aW9uYXhlcyBoYXMgbm8gdmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIC8vIGl0IGZsaXBzIGV2ZXJ5dGhpbmcgYW5kIHRoZSBheGVzXG5cbiAgICAgICAgICAgICAgICAgICAgY29udC5vcmllbnRhdGlvbiA9XG4gICAgICAgICAgICAgICAgICAgICAgICB7djogJ2gnLCBoOiAndid9W2NvbnRGdWxsLm9yaWVudGF0aW9uXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaGVscGVycy5zd2FwWFlEYXRhKGNvbnQpO1xuICAgICAgICAgICAgICAgIGZsYWdzLmNhbGMgPSBmbGFncy5jbGVhckF4aXNUeXBlcyA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYoUGxvdHMuZGF0YUFycmF5Q29udGFpbmVycy5pbmRleE9mKHBhcmFtLnBhcnRzWzBdKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiB1c2UgbWFuYWdlQXJyYXlzLmFwcGx5Q29udGFpbmVyQXJyYXlDaGFuZ2VzIGhlcmUgdG9vXG4gICAgICAgICAgICAgICAgaGVscGVycy5tYW5hZ2VBcnJheUNvbnRhaW5lcnMocGFyYW0sIG5ld1ZhbCwgdW5kb2l0KTtcbiAgICAgICAgICAgICAgICBmbGFncy5jYWxjID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYodmFsT2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIG11c3QgcmVkbyBjYWxjZGF0YSB3aGVuIHJlc3R5bGluZyBhcnJheSB2YWx1ZXMgb2YgYXJyYXlPayBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgICAgIC8vIC4uLiBidXQgbm8gbmVlZCB0byB0aGlzIGZvciByZWdsLWJhc2VkIHRyYWNlc1xuICAgICAgICAgICAgICAgICAgICBpZih2YWxPYmplY3QuYXJyYXlPayAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgIVJlZ2lzdHJ5LnRyYWNlSXMoY29udEZ1bGwsICdyZWdsJykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChMaWIuaXNBcnJheU9yVHlwZWRBcnJheShuZXdWYWwpIHx8IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG9sZFZhbCkpXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MuY2FsYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBlZGl0VHlwZXMudXBkYXRlKGZsYWdzLCB2YWxPYmplY3QpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICAgICAqIGlmIHdlIGNvdWxkbid0IGZpbmQgdmFsT2JqZWN0LCAgYXNzdW1lIGEgZnVsbCByZWNhbGMuXG4gICAgICAgICAgICAgICAgICAgICAqIFRoaXMgY2FuIGhhcHBlbiBpZiB5b3UncmUgY2hhbmdpbmcgdHlwZSBhbmQgbWFraW5nXG4gICAgICAgICAgICAgICAgICAgICAqIHNvbWUgb3RoZXIgZWRpdHMgdG9vLCBzbyB0aGUgbW9kdWxlcyB3ZSdyZVxuICAgICAgICAgICAgICAgICAgICAgKiBsb29raW5nIGF0IGRvbid0IGhhdmUgdGhlc2UgYXR0cmlidXRlcyBpbiB0aGVtLlxuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgZmxhZ3MuY2FsYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gYWxsIHRoZSBvdGhlciBvbmVzLCBqdXN0IG1vZGlmeSB0aGF0IG9uZSBhdHRyaWJ1dGVcbiAgICAgICAgICAgICAgICBwYXJhbS5zZXQobmV3VmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHN3YXAgdGhlIGRhdGEgYXR0cmlidXRlcyBvZiB0aGUgcmVsZXZhbnQgeCBhbmQgeSBheGVzP1xuICAgICAgICBpZihbJ3N3YXB4eWF4ZXMnLCAnb3JpZW50YXRpb25heGVzJ10uaW5kZXhPZihhaSkgIT09IC0xKSB7XG4gICAgICAgICAgICBBeGVzLnN3YXAoZ2QsIHRyYWNlcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzd2FwIGhvdmVybW9kZSBpZiBzZXQgdG8gXCJjb21wYXJlIHgveSBkYXRhXCJcbiAgICAgICAgaWYoYWkgPT09ICdvcmllbnRhdGlvbmF4ZXMnKSB7XG4gICAgICAgICAgICB2YXIgaG92ZXJtb2RlID0gbmVzdGVkUHJvcGVydHkoZ2QubGF5b3V0LCAnaG92ZXJtb2RlJyk7XG4gICAgICAgICAgICBpZihob3Zlcm1vZGUuZ2V0KCkgPT09ICd4Jykge1xuICAgICAgICAgICAgICAgIGhvdmVybW9kZS5zZXQoJ3knKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihob3Zlcm1vZGUuZ2V0KCkgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgIGhvdmVybW9kZS5zZXQoJ3gnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1ham9yIGVub3VnaCBjaGFuZ2VzIGRlc2VydmUgYXV0b3NjYWxlIGFuZFxuICAgICAgICAvLyBub24tcmV2ZXJzZWQgYXhlcyBzbyBwZW9wbGUgZG9uJ3QgZ2V0IGNvbmZ1c2VkXG4gICAgICAgIC8vXG4gICAgICAgIC8vIE5vdGU6IGF1dG9iaW4gKG9yIGl0cyBuZXcgYW5hbG9nIGJpbiBjbGVhcmluZykgaXMgbm90IGluY2x1ZGVkIGhlcmVcbiAgICAgICAgLy8gc2luY2Ugd2UncmUgbm90IHB1c2hpbmcgYmlucyBiYWNrIHRvIGdkLmRhdGEsIHNvIGlmIHdlIGhhdmUgYmluXG4gICAgICAgIC8vIGluZm8gaXQgd2FzIGV4cGxpY2l0bHkgcHJvdmlkZWQgYnkgdGhlIHVzZXIuXG4gICAgICAgIGlmKFsnb3JpZW50YXRpb24nLCAndHlwZSddLmluZGV4T2YoYWkpICE9PSAtMSkge1xuICAgICAgICAgICAgYXhsaXN0ID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCB0cmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgdHJhY2UgPSBkYXRhW3RyYWNlc1tpXV07XG5cbiAgICAgICAgICAgICAgICBpZihSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnY2FydGVzaWFuJykpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkVG9BeGxpc3QodHJhY2UueGF4aXMgfHwgJ3gnKTtcbiAgICAgICAgICAgICAgICAgICAgYWRkVG9BeGxpc3QodHJhY2UueWF4aXMgfHwgJ3knKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRvZXh0cmEoYXhsaXN0Lm1hcChhdXRvcmFuZ2VBdHRyKSwgdHJ1ZSwgMCk7XG4gICAgICAgICAgICBkb2V4dHJhKGF4bGlzdC5tYXAocmFuZ2VBdHRyKSwgWzAsIDFdLCAwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGZsYWdzLmNhbGMgfHwgZmxhZ3MucGxvdCkge1xuICAgICAgICBmbGFncy5mdWxsUmVwbG90ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBmbGFnczogZmxhZ3MsXG4gICAgICAgIHVuZG9pdDogdW5kb2l0LFxuICAgICAgICByZWRvaXQ6IHJlZG9pdCxcbiAgICAgICAgdHJhY2VzOiB0cmFjZXMsXG4gICAgICAgIGV2ZW50RGF0YTogTGliLmV4dGVuZERlZXBOb0FycmF5cyhbXSwgW2V2ZW50RGF0YSwgdHJhY2VzXSlcbiAgICB9O1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGRlcHJlY2F0ZWQgYXR0cmlidXRlIGtleXMgdG9cbiAqIHRoZSBjdXJyZW50IEFQSSB0byBlbnN1cmUgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuXG4gKlxuICogVGhpcyBpcyBuZWVkZWQgZm9yIHRoZSB1cGRhdGUgbWVjaGFuaXNtIHRvIGRldGVybWluZSB3aGljaFxuICogc3Vicm91dGluZXMgdG8gcnVuIGJhc2VkIG9uIHRoZSBhY3R1YWwgYXR0cmlidXRlXG4gKiBkZWZpbml0aW9ucyAodGhhdCBkb24ndCBpbmNsdWRlIHRoZSBkZXByZWNhdGVkIG9uZXMpLlxuICpcbiAqIEUuZy4gTWFwcyB7J3hheGlzLnRpdGxlJzogJ0EgY2hhcnQnfSB0byB7J3hheGlzLnRpdGxlLnRleHQnOiAnQSBjaGFydCd9XG4gKiBhbmQge3RpdGxlZm9udDogey4uLn19IHRvIHsndGl0bGUuZm9udCc6IHsuLi59fS5cbiAqXG4gKiBAcGFyYW0gYW9ialxuICovXG5mdW5jdGlvbiBjbGVhbkRlcHJlY2F0ZWRBdHRyaWJ1dGVLZXlzKGFvYmopIHtcbiAgICB2YXIgb2xkQXhpc1RpdGxlUmVnZXggPSBMaWIuY291bnRlclJlZ2V4KCdheGlzJywgJ1xcLnRpdGxlJywgZmFsc2UsIGZhbHNlKTtcbiAgICB2YXIgY29sb3JiYXJSZWdleCA9IC9jb2xvcmJhclxcLnRpdGxlJC87XG4gICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhhb2JqKTtcbiAgICB2YXIgaSwga2V5LCB2YWx1ZTtcblxuICAgIGZvcihpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgdmFsdWUgPSBhb2JqW2tleV07XG5cbiAgICAgICAgaWYoKGtleSA9PT0gJ3RpdGxlJyB8fCBvbGRBeGlzVGl0bGVSZWdleC50ZXN0KGtleSkgfHwgY29sb3JiYXJSZWdleC50ZXN0KGtleSkpICYmXG4gICAgICAgICAgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykpIHtcbiAgICAgICAgICAgIHJlcGxhY2Uoa2V5LCBrZXkucmVwbGFjZSgndGl0bGUnLCAndGl0bGUudGV4dCcpKTtcbiAgICAgICAgfSBlbHNlIGlmKGtleS5pbmRleE9mKCd0aXRsZWZvbnQnKSA+IC0xKSB7XG4gICAgICAgICAgICByZXBsYWNlKGtleSwga2V5LnJlcGxhY2UoJ3RpdGxlZm9udCcsICd0aXRsZS5mb250JykpO1xuICAgICAgICB9IGVsc2UgaWYoa2V5LmluZGV4T2YoJ3RpdGxlcG9zaXRpb24nKSA+IC0xKSB7XG4gICAgICAgICAgICByZXBsYWNlKGtleSwga2V5LnJlcGxhY2UoJ3RpdGxlcG9zaXRpb24nLCAndGl0bGUucG9zaXRpb24nKSk7XG4gICAgICAgIH0gZWxzZSBpZihrZXkuaW5kZXhPZigndGl0bGVzaWRlJykgPiAtMSkge1xuICAgICAgICAgICAgcmVwbGFjZShrZXksIGtleS5yZXBsYWNlKCd0aXRsZXNpZGUnLCAndGl0bGUuc2lkZScpKTtcbiAgICAgICAgfSBlbHNlIGlmKGtleS5pbmRleE9mKCd0aXRsZW9mZnNldCcpID4gLTEpIHtcbiAgICAgICAgICAgIHJlcGxhY2Uoa2V5LCBrZXkucmVwbGFjZSgndGl0bGVvZmZzZXQnLCAndGl0bGUub2Zmc2V0JykpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVwbGFjZShvbGRBdHRyU3RyLCBuZXdBdHRyU3RyKSB7XG4gICAgICAgIGFvYmpbbmV3QXR0clN0cl0gPSBhb2JqW29sZEF0dHJTdHJdO1xuICAgICAgICBkZWxldGUgYW9ialtvbGRBdHRyU3RyXTtcbiAgICB9XG59XG5cbi8qKlxuICogcmVsYXlvdXQ6IHVwZGF0ZSBsYXlvdXQgYXR0cmlidXRlcyBvZiBhbiBleGlzdGluZyBwbG90XG4gKlxuICogQ2FuIGJlIGNhbGxlZCB0d28gd2F5czpcbiAqXG4gKiBTaWduYXR1cmUgMTpcbiAqIEBwYXJhbSB7U3RyaW5nIHwgSFRNTERpdkVsZW1lbnR9IGdkXG4gKiAgdGhlIGlkIG9yIGRvbSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKiBAcGFyYW0ge1N0cmluZ30gYXN0clxuICogIGF0dHJpYnV0ZSBzdHJpbmcgKGxpa2UgYCd4YXhpcy5yYW5nZVswXSdgKSB0byB1cGRhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsXG4gKiAgdmFsdWUgdG8gZ2l2ZSB0aGlzIGF0dHJpYnV0ZVxuICpcbiAqIFNpZ25hdHVyZSAyOlxuICogQHBhcmFtIHtTdHJpbmcgfCBIVE1MRGl2RWxlbWVudH0gZ2RcbiAqICAoYXMgaW4gc2lnbmF0dXJlIDEpXG4gKiBAcGFyYW0ge09iamVjdH0gYW9ialxuICogIGF0dHJpYnV0ZSBvYmplY3QgYHthc3RyMTogdmFsMSwgYXN0cjI6IHZhbDIgLi4ufWBcbiAqICBhbGxvd3Mgc2V0dGluZyBtdWx0aXBsZSBhdHRyaWJ1dGVzIHNpbXVsdGFuZW91c2x5XG4gKi9cbmZ1bmN0aW9uIHJlbGF5b3V0KGdkLCBhc3RyLCB2YWwpIHtcbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG4gICAgaGVscGVycy5jbGVhclByb21pc2VRdWV1ZShnZCk7XG5cbiAgICBpZihnZC5mcmFtZXdvcmsgJiYgZ2QuZnJhbWV3b3JrLmlzUG9sYXIpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShnZCk7XG4gICAgfVxuXG4gICAgdmFyIGFvYmogPSB7fTtcbiAgICBpZih0eXBlb2YgYXN0ciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgYW9ialthc3RyXSA9IHZhbDtcbiAgICB9IGVsc2UgaWYoTGliLmlzUGxhaW5PYmplY3QoYXN0cikpIHtcbiAgICAgICAgYW9iaiA9IExpYi5leHRlbmRGbGF0KHt9LCBhc3RyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBMaWIud2FybignUmVsYXlvdXQgZmFpbC4nLCBhc3RyLCB2YWwpO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoKTtcbiAgICB9XG5cbiAgICBpZihPYmplY3Qua2V5cyhhb2JqKS5sZW5ndGgpIGdkLmNoYW5nZWQgPSB0cnVlO1xuXG4gICAgdmFyIHNwZWNzID0gX3JlbGF5b3V0KGdkLCBhb2JqKTtcbiAgICB2YXIgZmxhZ3MgPSBzcGVjcy5mbGFncztcblxuICAgIC8vIGNsZWFyIGNhbGNkYXRhIGlmIHJlcXVpcmVkXG4gICAgaWYoZmxhZ3MuY2FsYykgZ2QuY2FsY2RhdGEgPSB1bmRlZmluZWQ7XG5cbiAgICAvLyBmaWxsIGluIHJlZHJhdyBzZXF1ZW5jZVxuXG4gICAgLy8gZXZlbiBpZiB3ZSBkb24ndCBoYXZlIGFueXRoaW5nIGxlZnQgaW4gYW9iaixcbiAgICAvLyBzb21ldGhpbmcgbWF5IGhhdmUgaGFwcGVuZWQgd2l0aGluIHJlbGF5b3V0IHRoYXQgd2VcbiAgICAvLyBuZWVkIHRvIHdhaXQgZm9yXG4gICAgdmFyIHNlcSA9IFtQbG90cy5wcmV2aW91c1Byb21pc2VzXTtcblxuICAgIGlmKGZsYWdzLmxheW91dFJlcGxvdCkge1xuICAgICAgICBzZXEucHVzaChzdWJyb3V0aW5lcy5sYXlvdXRSZXBsb3QpO1xuICAgIH0gZWxzZSBpZihPYmplY3Qua2V5cyhhb2JqKS5sZW5ndGgpIHtcbiAgICAgICAgYXhSYW5nZVN1cHBseURlZmF1bHRzQnlQYXNzKGdkLCBmbGFncywgc3BlY3MpIHx8IFBsb3RzLnN1cHBseURlZmF1bHRzKGdkKTtcblxuICAgICAgICBpZihmbGFncy5sZWdlbmQpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmRvTGVnZW5kKTtcbiAgICAgICAgaWYoZmxhZ3MubGF5b3V0c3R5bGUpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmxheW91dFN0eWxlcyk7XG4gICAgICAgIGlmKGZsYWdzLmF4cmFuZ2UpIGFkZEF4UmFuZ2VTZXF1ZW5jZShzZXEsIHNwZWNzLnJhbmdlc0FsdGVyZWQpO1xuICAgICAgICBpZihmbGFncy50aWNrcykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9UaWNrc1JlbGF5b3V0KTtcbiAgICAgICAgaWYoZmxhZ3MubW9kZWJhcikgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Nb2RlQmFyKTtcbiAgICAgICAgaWYoZmxhZ3MuY2FtZXJhKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb0NhbWVyYSk7XG4gICAgICAgIGlmKGZsYWdzLmNvbG9yYmFycykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Db2xvckJhcnMpO1xuXG4gICAgICAgIHNlcS5wdXNoKGVtaXRBZnRlclBsb3QpO1xuICAgIH1cblxuICAgIHNlcS5wdXNoKFBsb3RzLnJlaG92ZXIsIFBsb3RzLnJlZHJhZyk7XG5cbiAgICBRdWV1ZS5hZGQoZ2QsXG4gICAgICAgIHJlbGF5b3V0LCBbZ2QsIHNwZWNzLnVuZG9pdF0sXG4gICAgICAgIHJlbGF5b3V0LCBbZ2QsIHNwZWNzLnJlZG9pdF1cbiAgICApO1xuXG4gICAgdmFyIHBsb3REb25lID0gTGliLnN5bmNPckFzeW5jKHNlcSwgZ2QpO1xuICAgIGlmKCFwbG90RG9uZSB8fCAhcGxvdERvbmUudGhlbikgcGxvdERvbmUgPSBQcm9taXNlLnJlc29sdmUoZ2QpO1xuXG4gICAgcmV0dXJuIHBsb3REb25lLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9yZWxheW91dCcsIHNwZWNzLmV2ZW50RGF0YSk7XG4gICAgICAgIHJldHVybiBnZDtcbiAgICB9KTtcbn1cblxuLy8gT3B0aW1pemF0aW9uIG1vc3RseSBmb3IgbGFyZ2Ugc3Bsb20gdHJhY2VzIHdoZXJlXG4vLyBQbG90cy5zdXBwbHlEZWZhdWx0cyBjYW4gdGFrZSA+IDEwMG1zXG5mdW5jdGlvbiBheFJhbmdlU3VwcGx5RGVmYXVsdHNCeVBhc3MoZ2QsIGZsYWdzLCBzcGVjcykge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBpZighZmxhZ3MuYXhyYW5nZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yKHZhciBrIGluIGZsYWdzKSB7XG4gICAgICAgIGlmKGsgIT09ICdheHJhbmdlJyAmJiBmbGFnc1trXSkgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvcih2YXIgYXhJZCBpbiBzcGVjcy5yYW5nZXNBbHRlcmVkKSB7XG4gICAgICAgIHZhciBheE5hbWUgPSBBeGVzLmlkMm5hbWUoYXhJZCk7XG4gICAgICAgIHZhciBheEluID0gZ2QubGF5b3V0W2F4TmFtZV07XG4gICAgICAgIHZhciBheE91dCA9IGZ1bGxMYXlvdXRbYXhOYW1lXTtcbiAgICAgICAgYXhPdXQuYXV0b3JhbmdlID0gYXhJbi5hdXRvcmFuZ2U7XG4gICAgICAgIGF4T3V0LnJhbmdlID0gYXhJbi5yYW5nZS5zbGljZSgpO1xuICAgICAgICBheE91dC5jbGVhblJhbmdlKCk7XG5cbiAgICAgICAgaWYoYXhPdXQuX21hdGNoR3JvdXApIHtcbiAgICAgICAgICAgIGZvcih2YXIgYXhJZDIgaW4gYXhPdXQuX21hdGNoR3JvdXApIHtcbiAgICAgICAgICAgICAgICBpZihheElkMiAhPT0gYXhJZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYXgyID0gZnVsbExheW91dFtBeGVzLmlkMm5hbWUoYXhJZDIpXTtcbiAgICAgICAgICAgICAgICAgICAgYXgyLmF1dG9yYW5nZSA9IGF4T3V0LmF1dG9yYW5nZTtcbiAgICAgICAgICAgICAgICAgICAgYXgyLnJhbmdlID0gYXhPdXQucmFuZ2Uuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgYXgyLl9pbnB1dC5yYW5nZSA9IGF4T3V0LnJhbmdlLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGFkZEF4UmFuZ2VTZXF1ZW5jZShzZXEsIHJhbmdlc0FsdGVyZWQpIHtcbiAgICAvLyBOLkIuIGxlYXZlIGFzIHNlcXVlbmNlIG9mIHN1YnJvdXRpbmVzIChmb3Igbm93KSBpbnN0ZWFkIG9mXG4gICAgLy8gc3Vicm91dGluZSBvZiBpdHMgb3duIHNvIHRoYXQgZmluYWxEcmF3IGFsd2F5cyBnZXRzXG4gICAgLy8gZXhlY3V0ZWQgYWZ0ZXIgZHJhd0RhdGFcbiAgICB2YXIgZHJhd0F4ZXMgPSByYW5nZXNBbHRlcmVkID9cbiAgICAgICAgZnVuY3Rpb24oZ2QpIHtcbiAgICAgICAgICAgIHZhciBheElkcyA9IFtdO1xuICAgICAgICAgICAgdmFyIHNraXBUaXRsZSA9IHRydWU7XG5cbiAgICAgICAgICAgIGZvcih2YXIgaWQgaW4gcmFuZ2VzQWx0ZXJlZCkge1xuICAgICAgICAgICAgICAgIHZhciBheCA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBpZCk7XG4gICAgICAgICAgICAgICAgYXhJZHMucHVzaChpZCk7XG5cbiAgICAgICAgICAgICAgICBpZihheC5fbWF0Y2hHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGlkMiBpbiBheC5fbWF0Y2hHcm91cCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIXJhbmdlc0FsdGVyZWRbaWQyXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4SWRzLnB1c2goaWQyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGF4LmF1dG9tYXJnaW4pIHNraXBUaXRsZSA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gQXhlcy5kcmF3KGdkLCBheElkcywge3NraXBUaXRsZTogc2tpcFRpdGxlfSk7XG4gICAgICAgIH0gOlxuICAgICAgICBmdW5jdGlvbihnZCkge1xuICAgICAgICAgICAgcmV0dXJuIEF4ZXMuZHJhdyhnZCwgJ3JlZHJhdycpO1xuICAgICAgICB9O1xuXG4gICAgc2VxLnB1c2goXG4gICAgICAgIGNsZWFyU2VsZWN0LFxuICAgICAgICBzdWJyb3V0aW5lcy5kb0F1dG9SYW5nZUFuZENvbnN0cmFpbnRzLFxuICAgICAgICBkcmF3QXhlcyxcbiAgICAgICAgc3Vicm91dGluZXMuZHJhd0RhdGEsXG4gICAgICAgIHN1YnJvdXRpbmVzLmZpbmFsRHJhd1xuICAgICk7XG59XG5cbnZhciBBWF9SQU5HRV9SRSA9IC9eW3h5el1heGlzWzAtOV0qXFwucmFuZ2UoXFxbWzB8MV1cXF0pPyQvO1xudmFyIEFYX0FVVE9SQU5HRV9SRSA9IC9eW3h5el1heGlzWzAtOV0qXFwuYXV0b3JhbmdlJC87XG52YXIgQVhfRE9NQUlOX1JFID0gL15beHl6XWF4aXNbMC05XSpcXC5kb21haW4oXFxbWzB8MV1cXF0pPyQvO1xuXG5mdW5jdGlvbiBfcmVsYXlvdXQoZ2QsIGFvYmopIHtcbiAgICB2YXIgbGF5b3V0ID0gZ2QubGF5b3V0O1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGd1aUVkaXRGbGFnID0gZnVsbExheW91dC5fZ3VpRWRpdGluZztcbiAgICB2YXIgbGF5b3V0TlAgPSBtYWtlTlAoZnVsbExheW91dC5fcHJlR1VJLCBndWlFZGl0RmxhZyk7XG4gICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhhb2JqKTtcbiAgICB2YXIgYXhlcyA9IEF4ZXMubGlzdChnZCk7XG4gICAgdmFyIGV2ZW50RGF0YSA9IExpYi5leHRlbmREZWVwQWxsKHt9LCBhb2JqKTtcbiAgICB2YXIgYXJyYXlFZGl0cyA9IHt9O1xuXG4gICAgdmFyIGFycmF5U3RyLCBpLCBqO1xuXG4gICAgY2xlYW5EZXByZWNhdGVkQXR0cmlidXRlS2V5cyhhb2JqKTtcbiAgICBrZXlzID0gT2JqZWN0LmtleXMoYW9iaik7XG5cbiAgICAvLyBsb29rIGZvciAnYWxsYXhlcycsIHNwbGl0IG91dCBpbnRvIGFsbCBheGVzXG4gICAgLy8gaW4gY2FzZSBvZiAzRCB0aGUgYXhpcyBhcmUgbmVzdGVkIHdpdGhpbiBhIHNjZW5lIHdoaWNoIGlzIGhlbGQgaW4gX2lkXG4gICAgZm9yKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihrZXlzW2ldLmluZGV4T2YoJ2FsbGF4ZXMnKSA9PT0gMCkge1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgYXhlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBzY2VuZSA9IGF4ZXNbal0uX2lkLnN1YnN0cigxKTtcbiAgICAgICAgICAgICAgICB2YXIgYXhpc0F0dHIgPSAoc2NlbmUuaW5kZXhPZignc2NlbmUnKSAhPT0gLTEpID8gKHNjZW5lICsgJy4nKSA6ICcnO1xuICAgICAgICAgICAgICAgIHZhciBuZXdrZXkgPSBrZXlzW2ldLnJlcGxhY2UoJ2FsbGF4ZXMnLCBheGlzQXR0ciArIGF4ZXNbal0uX25hbWUpO1xuXG4gICAgICAgICAgICAgICAgaWYoIWFvYmpbbmV3a2V5XSkgYW9ialtuZXdrZXldID0gYW9ialtrZXlzW2ldXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGVsZXRlIGFvYmpba2V5c1tpXV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpbml0aWFsaXplIGZsYWdzXG4gICAgdmFyIGZsYWdzID0gZWRpdFR5cGVzLmxheW91dEZsYWdzKCk7XG5cbiAgICAvLyBjb3BpZXMgb2YgdGhlIGNoYW5nZSAoYW5kIHByZXZpb3VzIHZhbHVlcyBvZiBhbnl0aGluZyBhZmZlY3RlZClcbiAgICAvLyBmb3IgdGhlIHVuZG8gLyByZWRvIHF1ZXVlXG4gICAgdmFyIHJlZG9pdCA9IHt9O1xuICAgIHZhciB1bmRvaXQgPSB7fTtcblxuICAgIC8vIGZvciBhdHRycyB0aGF0IGludGVyYWN0IChsaWtlIHNjYWxlcyAmIGF1dG9zY2FsZXMpLCBzYXZlIHRoZVxuICAgIC8vIG9sZCB2YWxzIGJlZm9yZSBtYWtpbmcgdGhlIGNoYW5nZVxuICAgIC8vIHZhbD11bmRlZmluZWQgd2lsbCBub3Qgc2V0IGEgdmFsdWUsIGp1c3QgcmVjb3JkIHdoYXQgdGhlIHZhbHVlIHdhcy5cbiAgICAvLyBhdHRyIGNhbiBiZSBhbiBhcnJheSB0byBzZXQgc2V2ZXJhbCBhdCBvbmNlIChhbGwgdG8gdGhlIHNhbWUgdmFsKVxuICAgIGZ1bmN0aW9uIGRvZXh0cmEoYXR0ciwgdmFsKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoYXR0cikpIHtcbiAgICAgICAgICAgIGF0dHIuZm9yRWFjaChmdW5jdGlvbihhKSB7IGRvZXh0cmEoYSwgdmFsKTsgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiB3ZSBoYXZlIGFub3RoZXIgdmFsdWUgZm9yIHRoaXMgYXR0cmlidXRlIChleHBsaWNpdGx5IG9yXG4gICAgICAgIC8vIHZpYSBhIHBhcmVudCkgZG8gbm90IG92ZXJyaWRlIHdpdGggdGhpcyBhdXRvLWdlbmVyYXRlZCBleHRyYVxuICAgICAgICBpZihhdHRyIGluIGFvYmogfHwgaGVscGVycy5oYXNQYXJlbnQoYW9iaiwgYXR0cikpIHJldHVybjtcblxuICAgICAgICB2YXIgcCA9IGxheW91dE5QKGxheW91dCwgYXR0cik7XG4gICAgICAgIGlmKCEoYXR0ciBpbiB1bmRvaXQpKSB7XG4gICAgICAgICAgICB1bmRvaXRbYXR0cl0gPSB1bmRlZmluZWRUb051bGwocC5nZXQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYodmFsICE9PSB1bmRlZmluZWQpIHAuc2V0KHZhbCk7XG4gICAgfVxuXG4gICAgLy8gZm9yIGNvbnN0cmFpbnQgZW5mb3JjZW1lbnQ6IGtlZXAgdHJhY2sgb2YgYWxsIGF4ZXMgKGFzIHtpZDogbmFtZX0pXG4gICAgLy8gd2UncmUgZWRpdGluZyB0aGUgKGF1dG8pcmFuZ2Ugb2YsIHNvIHdlIGNhbiB0ZWxsIHRoZSBvdGhlcnMgY29uc3RyYWluZWRcbiAgICAvLyB0byBzY2FsZSB3aXRoIHRoZW0gdGhhdCBpdCdzIE9LIGZvciB0aGVtIHRvIHNocmlua1xuICAgIHZhciByYW5nZXNBbHRlcmVkID0ge307XG4gICAgdmFyIGF4SWQ7XG5cbiAgICBmdW5jdGlvbiByZWNvcmRBbHRlcmVkQXhpcyhwbGVhZlBsdXMpIHtcbiAgICAgICAgdmFyIGF4SWQgPSBBeGVzLm5hbWUyaWQocGxlYWZQbHVzLnNwbGl0KCcuJylbMF0pO1xuICAgICAgICByYW5nZXNBbHRlcmVkW2F4SWRdID0gMTtcbiAgICAgICAgcmV0dXJuIGF4SWQ7XG4gICAgfVxuXG4gICAgLy8gYWx0ZXIgZ2QubGF5b3V0XG4gICAgZm9yKHZhciBhaSBpbiBhb2JqKSB7XG4gICAgICAgIGlmKGhlbHBlcnMuaGFzUGFyZW50KGFvYmosIGFpKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3Qgc2V0ICcgKyBhaSArICcgYW5kIGEgcGFyZW50IGF0dHJpYnV0ZSBzaW11bHRhbmVvdXNseScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHAgPSBsYXlvdXROUChsYXlvdXQsIGFpKTtcbiAgICAgICAgdmFyIHZpID0gYW9ialthaV07XG4gICAgICAgIHZhciBwbGVuID0gcC5wYXJ0cy5sZW5ndGg7XG4gICAgICAgIC8vIHAucGFydHMgbWF5IGVuZCB3aXRoIGFuIGluZGV4IGludGVnZXIgaWYgdGhlIHByb3BlcnR5IGlzIGFuIGFycmF5XG4gICAgICAgIHZhciBwZW5kID0gcGxlbiAtIDE7XG4gICAgICAgIHdoaWxlKHBlbmQgPiAwICYmIHR5cGVvZiBwLnBhcnRzW3BlbmRdICE9PSAnc3RyaW5nJykgcGVuZC0tO1xuICAgICAgICAvLyBsYXN0IHByb3BlcnR5IGluIGNoYWluIChsZWFmIG5vZGUpXG4gICAgICAgIHZhciBwbGVhZiA9IHAucGFydHNbcGVuZF07XG4gICAgICAgIC8vIGxlYWYgcGx1cyBpbW1lZGlhdGUgcGFyZW50XG4gICAgICAgIHZhciBwbGVhZlBsdXMgPSBwLnBhcnRzW3BlbmQgLSAxXSArICcuJyArIHBsZWFmO1xuICAgICAgICAvLyB0cnVuayBub2RlcyAoZXZlcnl0aGluZyBleGNlcHQgdGhlIGxlYWYpXG4gICAgICAgIHZhciBwdHJ1bmsgPSBwLnBhcnRzLnNsaWNlKDAsIHBlbmQpLmpvaW4oJy4nKTtcbiAgICAgICAgdmFyIHBhcmVudEluID0gbmVzdGVkUHJvcGVydHkoZ2QubGF5b3V0LCBwdHJ1bmspLmdldCgpO1xuICAgICAgICB2YXIgcGFyZW50RnVsbCA9IG5lc3RlZFByb3BlcnR5KGZ1bGxMYXlvdXQsIHB0cnVuaykuZ2V0KCk7XG4gICAgICAgIHZhciB2T2xkID0gcC5nZXQoKTtcblxuICAgICAgICBpZih2aSA9PT0gdW5kZWZpbmVkKSBjb250aW51ZTtcblxuICAgICAgICByZWRvaXRbYWldID0gdmk7XG5cbiAgICAgICAgLy8gYXhpcyByZXZlcnNlIGlzIHNwZWNpYWwgLSBpdCBpcyBpdHMgb3duIGludmVyc2VcbiAgICAgICAgLy8gb3AgYW5kIGhhcyBubyBmbGFnLlxuICAgICAgICB1bmRvaXRbYWldID0gKHBsZWFmID09PSAncmV2ZXJzZScpID8gdmkgOiB1bmRlZmluZWRUb051bGwodk9sZCk7XG5cbiAgICAgICAgdmFyIHZhbE9iamVjdCA9IFBsb3RTY2hlbWEuZ2V0TGF5b3V0VmFsT2JqZWN0KGZ1bGxMYXlvdXQsIHAucGFydHMpO1xuXG4gICAgICAgIGlmKHZhbE9iamVjdCAmJiB2YWxPYmplY3QuaW1wbGllZEVkaXRzICYmIHZpICE9PSBudWxsKSB7XG4gICAgICAgICAgICBmb3IodmFyIGltcGxpZWRLZXkgaW4gdmFsT2JqZWN0LmltcGxpZWRFZGl0cykge1xuICAgICAgICAgICAgICAgIGRvZXh0cmEoTGliLnJlbGF0aXZlQXR0cihhaSwgaW1wbGllZEtleSksIHZhbE9iamVjdC5pbXBsaWVkRWRpdHNbaW1wbGllZEtleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2V0dGluZyB3aWR0aCBvciBoZWlnaHQgdG8gbnVsbCBtdXN0IHJlc2V0IHRoZSBncmFwaCdzIHdpZHRoIC8gaGVpZ2h0XG4gICAgICAgIC8vIGJhY2sgdG8gaXRzIGluaXRpYWwgdmFsdWUgYXMgY29tcHV0ZWQgZHVyaW5nIHRoZSBmaXJzdCBwYXNzIGluIFBsb3RzLnBsb3RBdXRvU2l6ZS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gVG8gZG8gc28sIHdlIG11c3QgbWFudWFsbHkgc2V0IHRoZW0gYmFjayBoZXJlIHVzaW5nIHRoZSBfaW5pdGlhbEF1dG9TaXplIGNhY2hlLlxuICAgICAgICAvLyBjYW4ndCB1c2UgaW1wbGllZEVkaXRzIGZvciB0aGlzIGJlY2F1c2UgYmVoYXZpb3IgZGVwZW5kcyBvbiB2aVxuICAgICAgICBpZihbJ3dpZHRoJywgJ2hlaWdodCddLmluZGV4T2YoYWkpICE9PSAtMSkge1xuICAgICAgICAgICAgaWYodmkpIHtcbiAgICAgICAgICAgICAgICBkb2V4dHJhKCdhdXRvc2l6ZScsIG51bGwpO1xuICAgICAgICAgICAgICAgIC8vIGN1cnJlbnRseSB3ZSBkb24ndCBzdXBwb3J0IGF1dG9zaXplIG9uZSBkaW0gb25seSAtIHNvXG4gICAgICAgICAgICAgICAgLy8gZXhwbGljaXRseSBzZXQgdGhlIG90aGVyIG9uZS4gTm90ZSB0aGF0IGRvZXh0cmEgd2lsbFxuICAgICAgICAgICAgICAgIC8vIGlnbm9yZSB0aGlzIGlmIHRoZSBzYW1lIHJlbGF5b3V0IGNhbGwgYWxzbyBwcm92aWRlcyBvcHBvc2l0ZUF0dHJcbiAgICAgICAgICAgICAgICB2YXIgb3Bwb3NpdGVBdHRyID0gYWkgPT09ICdoZWlnaHQnID8gJ3dpZHRoJyA6ICdoZWlnaHQnO1xuICAgICAgICAgICAgICAgIGRvZXh0cmEob3Bwb3NpdGVBdHRyLCBmdWxsTGF5b3V0W29wcG9zaXRlQXR0cl0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmdWxsTGF5b3V0W2FpXSA9IGdkLl9pbml0aWFsQXV0b1NpemVbYWldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoYWkgPT09ICdhdXRvc2l6ZScpIHtcbiAgICAgICAgICAgIC8vIGRlcGVuZHMgb24gdmkgaGVyZSB0b28sIHNvIGFnYWluIGNhbid0IHVzZSBpbXBsaWVkRWRpdHNcbiAgICAgICAgICAgIGRvZXh0cmEoJ3dpZHRoJywgdmkgPyBudWxsIDogZnVsbExheW91dC53aWR0aCk7XG4gICAgICAgICAgICBkb2V4dHJhKCdoZWlnaHQnLCB2aSA/IG51bGwgOiBmdWxsTGF5b3V0LmhlaWdodCk7XG4gICAgICAgIH0gZWxzZSBpZihwbGVhZlBsdXMubWF0Y2goQVhfUkFOR0VfUkUpKSB7XG4gICAgICAgICAgICAvLyBjaGVjayBhdXRvcmFuZ2UgdnMgcmFuZ2VcblxuICAgICAgICAgICAgcmVjb3JkQWx0ZXJlZEF4aXMocGxlYWZQbHVzKTtcbiAgICAgICAgICAgIG5lc3RlZFByb3BlcnR5KGZ1bGxMYXlvdXQsIHB0cnVuayArICcuX2lucHV0UmFuZ2UnKS5zZXQobnVsbCk7XG4gICAgICAgIH0gZWxzZSBpZihwbGVhZlBsdXMubWF0Y2goQVhfQVVUT1JBTkdFX1JFKSkge1xuICAgICAgICAgICAgcmVjb3JkQWx0ZXJlZEF4aXMocGxlYWZQbHVzKTtcbiAgICAgICAgICAgIG5lc3RlZFByb3BlcnR5KGZ1bGxMYXlvdXQsIHB0cnVuayArICcuX2lucHV0UmFuZ2UnKS5zZXQobnVsbCk7XG4gICAgICAgICAgICB2YXIgYXhGdWxsID0gbmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgcHRydW5rKS5nZXQoKTtcbiAgICAgICAgICAgIGlmKGF4RnVsbC5faW5wdXREb21haW4pIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB3ZSdyZSBhdXRvcmFuZ2luZyBhbmQgdGhpcyBheGlzIGhhcyBhIGNvbnN0cmFpbmVkIGRvbWFpbixcbiAgICAgICAgICAgICAgICAvLyByZXNldCBpdCBzbyB3ZSBkb24ndCBnZXQgbG9ja2VkIGludG8gYSBzaHJ1bmtlbiBzaXplXG4gICAgICAgICAgICAgICAgYXhGdWxsLl9pbnB1dC5kb21haW4gPSBheEZ1bGwuX2lucHV0RG9tYWluLnNsaWNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihwbGVhZlBsdXMubWF0Y2goQVhfRE9NQUlOX1JFKSkge1xuICAgICAgICAgICAgbmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgcHRydW5rICsgJy5faW5wdXREb21haW4nKS5zZXQobnVsbCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0b2dnbGluZyBheGlzIHR5cGUgYmV0d2VlbiBsb2cgYW5kIGxpbmVhcjogd2UgbmVlZCB0byBjb252ZXJ0XG4gICAgICAgIC8vIHBvc2l0aW9ucyBmb3IgY29tcG9uZW50cyB0aGF0IGFyZSBzdGlsbCB1c2luZyBsaW5lYXJpemVkIHZhbHVlcyxcbiAgICAgICAgLy8gbm90IGRhdGEgdmFsdWVzIGxpa2UgbmV3ZXIgY29tcG9uZW50cy5cbiAgICAgICAgLy8gcHJldmlvdXNseSB3ZSBkaWQgdGhpcyBmb3IgbG9nIDwtPiBub3QtbG9nLCBidXQgbm93IG9ubHkgZG8gaXRcbiAgICAgICAgLy8gZm9yIGxvZyA8LT4gbGluZWFyXG4gICAgICAgIGlmKHBsZWFmID09PSAndHlwZScpIHtcbiAgICAgICAgICAgIHZhciBheCA9IHBhcmVudEluO1xuICAgICAgICAgICAgdmFyIHRvTG9nID0gcGFyZW50RnVsbC50eXBlID09PSAnbGluZWFyJyAmJiB2aSA9PT0gJ2xvZyc7XG4gICAgICAgICAgICB2YXIgZnJvbUxvZyA9IHBhcmVudEZ1bGwudHlwZSA9PT0gJ2xvZycgJiYgdmkgPT09ICdsaW5lYXInO1xuXG4gICAgICAgICAgICBpZih0b0xvZyB8fCBmcm9tTG9nKSB7XG4gICAgICAgICAgICAgICAgaWYoIWF4IHx8ICFheC5yYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyAyRCBuZXZlciBnZXRzIGhlcmUsIGJ1dCAzRCBkb2VzXG4gICAgICAgICAgICAgICAgICAgIC8vIEkgZG9uJ3QgdGhpbmsgdGhpcyBpcyBuZWVkZWQsIGJ1dCBsZWZ0IGhlcmUgaW4gY2FzZSB0aGVyZVxuICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZWRnZSBjYXNlcyBJJ20gbm90IHRoaW5raW5nIG9mLlxuICAgICAgICAgICAgICAgICAgICBkb2V4dHJhKHB0cnVuayArICcuYXV0b3JhbmdlJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKCFwYXJlbnRGdWxsLmF1dG9yYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyB0b2dnbGluZyBsb2cgd2l0aG91dCBhdXRvcmFuZ2U6IG5lZWQgdG8gYWxzbyByZWNhbGN1bGF0ZSByYW5nZXNcbiAgICAgICAgICAgICAgICAgICAgLy8gYmVjYXVzZSBsb2cgYXhlcyB1c2UgbGluZWFyaXplZCB2YWx1ZXMgZm9yIHJhbmdlIGVuZHBvaW50c1xuICAgICAgICAgICAgICAgICAgICB2YXIgcjAgPSBheC5yYW5nZVswXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHIxID0gYXgucmFuZ2VbMV07XG4gICAgICAgICAgICAgICAgICAgIGlmKHRvTG9nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBib3RoIGxpbWl0cyBhcmUgbmVnYXRpdmUsIGF1dG9yYW5nZVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYocjAgPD0gMCAmJiByMSA8PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9leHRyYShwdHJ1bmsgKyAnLmF1dG9yYW5nZScsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgb25lIGlzIG5lZ2F0aXZlLCBzZXQgaXQgNiBvcmRlcnMgYmVsb3cgdGhlIG90aGVyLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYocjAgPD0gMCkgcjAgPSByMSAvIDFlNjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYocjEgPD0gMCkgcjEgPSByMCAvIDFlNjtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vdyBzZXQgdGhlIHJhbmdlIHZhbHVlcyBhcyBhcHByb3ByaWF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgZG9leHRyYShwdHJ1bmsgKyAnLnJhbmdlWzBdJywgTWF0aC5sb2cocjApIC8gTWF0aC5MTjEwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvZXh0cmEocHRydW5rICsgJy5yYW5nZVsxXScsIE1hdGgubG9nKHIxKSAvIE1hdGguTE4xMCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2V4dHJhKHB0cnVuayArICcucmFuZ2VbMF0nLCBNYXRoLnBvdygxMCwgcjApKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvZXh0cmEocHRydW5rICsgJy5yYW5nZVsxXScsIE1hdGgucG93KDEwLCByMSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHRvTG9nKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGp1c3QgbWFrZSBzdXJlIHRoZSByYW5nZSBpcyBwb3NpdGl2ZSBhbmQgaW4gdGhlIHJpZ2h0XG4gICAgICAgICAgICAgICAgICAgIC8vIG9yZGVyLCBpdCdsbCBnZXQgcmVjYWxjdWxhdGVkIGxhdGVyXG4gICAgICAgICAgICAgICAgICAgIGF4LnJhbmdlID0gKGF4LnJhbmdlWzFdID4gYXgucmFuZ2VbMF0pID8gWzEsIDJdIDogWzIsIDFdO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGNsZWFyIHBvbGFyIHZpZXcgaW5pdGlhbCBzdGFzaCBmb3IgcmFkaWFsIHJhbmdlIHNvIHRoYXRcbiAgICAgICAgICAgICAgICAvLyB2YWx1ZSBnZXQgcmVjb21wdXRlZCBpbiBjb3JyZWN0IHVuaXRzXG4gICAgICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShmdWxsTGF5b3V0Ll9zdWJwbG90cy5wb2xhcikgJiZcbiAgICAgICAgICAgICAgICAgICAgZnVsbExheW91dC5fc3VicGxvdHMucG9sYXIubGVuZ3RoICYmXG4gICAgICAgICAgICAgICAgICAgIGZ1bGxMYXlvdXRbcC5wYXJ0c1swXV0gJiZcbiAgICAgICAgICAgICAgICAgICAgcC5wYXJ0c1sxXSA9PT0gJ3JhZGlhbGF4aXMnXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBmdWxsTGF5b3V0W3AucGFydHNbMF1dLl9zdWJwbG90LnZpZXdJbml0aWFsWydyYWRpYWxheGlzLnJhbmdlJ107XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQW5ub3RhdGlvbnMgYW5kIGltYWdlcyBhbHNvIG5lZWQgdG8gY29udmVydCB0by9mcm9tIGxpbmVhcml6ZWQgY29vcmRzXG4gICAgICAgICAgICAgICAgLy8gU2hhcGVzIGRvIG5vdCBuZWVkIHRoaXMgOilcbiAgICAgICAgICAgICAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Fubm90YXRpb25zJywgJ2NvbnZlcnRDb29yZHMnKShnZCwgcGFyZW50RnVsbCwgdmksIGRvZXh0cmEpO1xuICAgICAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnaW1hZ2VzJywgJ2NvbnZlcnRDb29yZHMnKShnZCwgcGFyZW50RnVsbCwgdmksIGRvZXh0cmEpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBhbnkgb3RoZXIgdHlwZSBjaGFuZ2VzOiB0aGUgcmFuZ2UgZnJvbSB0aGUgcHJldmlvdXMgdHlwZVxuICAgICAgICAgICAgICAgIC8vIHdpbGwgbm90IG1ha2Ugc2Vuc2UsIHNvIGF1dG9yYW5nZSBpdC5cbiAgICAgICAgICAgICAgICBkb2V4dHJhKHB0cnVuayArICcuYXV0b3JhbmdlJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgZG9leHRyYShwdHJ1bmsgKyAnLnJhbmdlJywgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBuZXN0ZWRQcm9wZXJ0eShmdWxsTGF5b3V0LCBwdHJ1bmsgKyAnLl9pbnB1dFJhbmdlJykuc2V0KG51bGwpO1xuICAgICAgICB9IGVsc2UgaWYocGxlYWYubWF0Y2goQVhfTkFNRV9QQVRURVJOKSkge1xuICAgICAgICAgICAgdmFyIGZ1bGxQcm9wID0gbmVzdGVkUHJvcGVydHkoZnVsbExheW91dCwgYWkpLmdldCgpO1xuICAgICAgICAgICAgdmFyIG5ld1R5cGUgPSAodmkgfHwge30pLnR5cGU7XG5cbiAgICAgICAgICAgIC8vIFRoaXMgY2FuIHBvdGVudGlhbGx5IGNhdXNlIHN0cmFuZ2UgYmVoYXZpb3IgaWYgdGhlIGF1dG90eXBlIGlzIG5vdFxuICAgICAgICAgICAgLy8gbnVtZXJpYyAobGluZWFyLCBiZWNhdXNlIHdlIGRvbid0IGF1dG8tbG9nKSBidXQgdGhlIHByZXZpb3VzIHR5cGVcbiAgICAgICAgICAgIC8vIHdhcyBsb2cuIFRoYXQncyBhIHZlcnkgc3RyYW5nZSBlZGdlIGNhc2UgdGhvdWdoXG4gICAgICAgICAgICBpZighbmV3VHlwZSB8fCBuZXdUeXBlID09PSAnLScpIG5ld1R5cGUgPSAnbGluZWFyJztcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMnLCAnY29udmVydENvb3JkcycpKGdkLCBmdWxsUHJvcCwgbmV3VHlwZSwgZG9leHRyYSk7XG4gICAgICAgICAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2ltYWdlcycsICdjb252ZXJ0Q29vcmRzJykoZ2QsIGZ1bGxQcm9wLCBuZXdUeXBlLCBkb2V4dHJhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFsdGVyIGdkLmxheW91dFxuXG4gICAgICAgIC8vIGNvbGxlY3QgYXJyYXkgY29tcG9uZW50IGVkaXRzIGZvciBleGVjdXRpb24gYWxsIHRvZ2V0aGVyXG4gICAgICAgIC8vIHNvIHdlIGNhbiBlbnN1cmUgY29uc2lzdGVudCBiZWhhdmlvciBhZGRpbmcvcmVtb3ZpbmcgaXRlbXNcbiAgICAgICAgLy8gYW5kIG9yZGVyLWluZGVwZW5kZW5jZSBmb3IgYWRkL3JlbW92ZS9lZGl0IGFsbCB0b2dldGhlciBpblxuICAgICAgICAvLyBvbmUgcmVsYXlvdXQgY2FsbFxuICAgICAgICB2YXIgY29udGFpbmVyQXJyYXlNYXRjaCA9IG1hbmFnZUFycmF5cy5jb250YWluZXJBcnJheU1hdGNoKGFpKTtcbiAgICAgICAgaWYoY29udGFpbmVyQXJyYXlNYXRjaCkge1xuICAgICAgICAgICAgYXJyYXlTdHIgPSBjb250YWluZXJBcnJheU1hdGNoLmFycmF5O1xuICAgICAgICAgICAgaSA9IGNvbnRhaW5lckFycmF5TWF0Y2guaW5kZXg7XG4gICAgICAgICAgICB2YXIgcHJvcFN0ciA9IGNvbnRhaW5lckFycmF5TWF0Y2gucHJvcGVydHk7XG4gICAgICAgICAgICB2YXIgdXBkYXRlVmFsT2JqZWN0ID0gdmFsT2JqZWN0IHx8IHtlZGl0VHlwZTogJ2NhbGMnfTtcblxuICAgICAgICAgICAgaWYoaSAhPT0gJycgJiYgcHJvcFN0ciA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICAvLyBzcGVjaWFsIGhhbmRsaW5nIG9mIHVuZG9pdCBpZiB3ZSdyZSBhZGRpbmcgb3IgcmVtb3ZpbmcgYW4gZWxlbWVudFxuICAgICAgICAgICAgICAgIC8vIGllICdhbm5vdGF0aW9uc1syXScgd2hpY2ggY2FuIGJlIHsuLi59IChhZGQpIG9yIG51bGwsXG4gICAgICAgICAgICAgICAgLy8gZG9lcyBub3Qgd29yayB3aGVuIHJlcGxhY2luZyB0aGUgZW50aXJlIGFycmF5XG4gICAgICAgICAgICAgICAgaWYobWFuYWdlQXJyYXlzLmlzQWRkVmFsKHZpKSkge1xuICAgICAgICAgICAgICAgICAgICB1bmRvaXRbYWldID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYobWFuYWdlQXJyYXlzLmlzUmVtb3ZlVmFsKHZpKSkge1xuICAgICAgICAgICAgICAgICAgICB1bmRvaXRbYWldID0gKG5lc3RlZFByb3BlcnR5KGxheW91dCwgYXJyYXlTdHIpLmdldCgpIHx8IFtdKVtpXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBMaWIud2FybigndW5yZWNvZ25pemVkIGZ1bGwgb2JqZWN0IHZhbHVlJywgYW9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWRpdFR5cGVzLnVwZGF0ZShmbGFncywgdXBkYXRlVmFsT2JqZWN0KTtcblxuICAgICAgICAgICAgLy8gcHJlcGFyZSB0aGUgZWRpdHMgb2JqZWN0IHdlJ2xsIHNlbmQgdG8gYXBwbHlDb250YWluZXJBcnJheUNoYW5nZXNcbiAgICAgICAgICAgIGlmKCFhcnJheUVkaXRzW2FycmF5U3RyXSkgYXJyYXlFZGl0c1thcnJheVN0cl0gPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmpFZGl0cyA9IGFycmF5RWRpdHNbYXJyYXlTdHJdW2ldO1xuICAgICAgICAgICAgaWYoIW9iakVkaXRzKSBvYmpFZGl0cyA9IGFycmF5RWRpdHNbYXJyYXlTdHJdW2ldID0ge307XG4gICAgICAgICAgICBvYmpFZGl0c1twcm9wU3RyXSA9IHZpO1xuXG4gICAgICAgICAgICBkZWxldGUgYW9ialthaV07XG4gICAgICAgIH0gZWxzZSBpZihwbGVhZiA9PT0gJ3JldmVyc2UnKSB7XG4gICAgICAgICAgICAvLyBoYW5kbGUgYXhpcyByZXZlcnNhbCBleHBsaWNpdGx5LCBhcyB0aGVyZSdzIG5vICdyZXZlcnNlJyBhdHRyaWJ1dGVcblxuICAgICAgICAgICAgaWYocGFyZW50SW4ucmFuZ2UpIHBhcmVudEluLnJhbmdlLnJldmVyc2UoKTtcbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRvZXh0cmEocHRydW5rICsgJy5hdXRvcmFuZ2UnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBwYXJlbnRJbi5yYW5nZSA9IFsxLCAwXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYocGFyZW50RnVsbC5hdXRvcmFuZ2UpIGZsYWdzLmNhbGMgPSB0cnVlO1xuICAgICAgICAgICAgZWxzZSBmbGFncy5wbG90ID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKChmdWxsTGF5b3V0Ll9oYXMoJ3NjYXR0ZXItbGlrZScpICYmIGZ1bGxMYXlvdXQuX2hhcygncmVnbCcpKSAmJlxuICAgICAgICAgICAgICAgIChhaSA9PT0gJ2RyYWdtb2RlJyAmJlxuICAgICAgICAgICAgICAgICh2aSA9PT0gJ2xhc3NvJyB8fCB2aSA9PT0gJ3NlbGVjdCcpICYmXG4gICAgICAgICAgICAgICAgISh2T2xkID09PSAnbGFzc28nIHx8IHZPbGQgPT09ICdzZWxlY3QnKSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGZsYWdzLnBsb3QgPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGZ1bGxMYXlvdXQuX2hhcygnZ2wyZCcpKSB7XG4gICAgICAgICAgICAgICAgZmxhZ3MucGxvdCA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYodmFsT2JqZWN0KSBlZGl0VHlwZXMudXBkYXRlKGZsYWdzLCB2YWxPYmplY3QpO1xuICAgICAgICAgICAgZWxzZSBmbGFncy5jYWxjID0gdHJ1ZTtcblxuICAgICAgICAgICAgcC5zZXQodmkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gbm93IHdlJ3ZlIGNvbGxlY3RlZCBjb21wb25lbnQgZWRpdHMgLSBleGVjdXRlIHRoZW0gYWxsIHRvZ2V0aGVyXG4gICAgZm9yKGFycmF5U3RyIGluIGFycmF5RWRpdHMpIHtcbiAgICAgICAgdmFyIGZpbmlzaGVkID0gbWFuYWdlQXJyYXlzLmFwcGx5Q29udGFpbmVyQXJyYXlDaGFuZ2VzKGdkLFxuICAgICAgICAgICAgbGF5b3V0TlAobGF5b3V0LCBhcnJheVN0ciksIGFycmF5RWRpdHNbYXJyYXlTdHJdLCBmbGFncywgbGF5b3V0TlApO1xuICAgICAgICBpZighZmluaXNoZWQpIGZsYWdzLnBsb3QgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIGZpZ3VyZSBvdXQgaWYgd2UgbmVlZCB0byByZWNhbGN1bGF0ZSBheGlzIGNvbnN0cmFpbnRzXG4gICAgdmFyIGNvbnN0cmFpbnRzID0gZnVsbExheW91dC5fYXhpc0NvbnN0cmFpbnRHcm91cHMgfHwgW107XG4gICAgZm9yKGF4SWQgaW4gcmFuZ2VzQWx0ZXJlZCkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb25zdHJhaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGdyb3VwID0gY29uc3RyYWludHNbaV07XG4gICAgICAgICAgICBpZihncm91cFtheElkXSkge1xuICAgICAgICAgICAgICAgIC8vIEFsd2F5cyByZWNhbGMgaWYgd2UncmUgY2hhbmdpbmcgY29uc3RyYWluZWQgcmFuZ2VzLlxuICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBpdCdzIHBvc3NpYmxlIHRvIHZpb2xhdGUgdGhlIGNvbnN0cmFpbnRzIGJ5XG4gICAgICAgICAgICAgICAgLy8gc3BlY2lmeWluZyBhcmJpdHJhcnkgcmFuZ2VzIGZvciBhbGwgYXhlcyBpbiB0aGUgZ3JvdXAuXG4gICAgICAgICAgICAgICAgLy8gdGhpcyB3YXkgc29tZSByYW5nZXMgbWF5IGV4cGFuZCBiZXlvbmQgd2hhdCdzIHNwZWNpZmllZCxcbiAgICAgICAgICAgICAgICAvLyBhcyB0aGV5IGRvIGF0IGZpcnN0IGRyYXcsIHRvIHNhdGlzZnkgdGhlIGNvbnN0cmFpbnRzLlxuICAgICAgICAgICAgICAgIGZsYWdzLmNhbGMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGZvcih2YXIgZ3JvdXBBeElkIGluIGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCFyYW5nZXNBbHRlcmVkW2dyb3VwQXhJZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEF4ZXMuZ2V0RnJvbUlkKGdkLCBncm91cEF4SWQpLl9jb25zdHJhaW50U2hyaW5rYWJsZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBJZiB0aGUgYXV0b3NpemUgY2hhbmdlZCBvciBoZWlnaHQgb3Igd2lkdGggd2FzIGV4cGxpY2l0bHkgc3BlY2lmaWVkLFxuICAgIC8vIHRoaXMgdHJpZ2dlcnMgYSByZWRyYXdcbiAgICAvLyBUT0RPOiBkbyB3ZSByZWFsbHkgbmVlZCBzcGVjaWFsIGFvYmouaGVpZ2h0L3dpZHRoIGhhbmRsaW5nIGhlcmU/XG4gICAgLy8gY291bGRuJ3QgZWRpdFR5cGUgZG8gdGhpcz9cbiAgICBpZih1cGRhdGVBdXRvc2l6ZShnZCkgfHwgYW9iai5oZWlnaHQgfHwgYW9iai53aWR0aCkgZmxhZ3MucGxvdCA9IHRydWU7XG5cbiAgICBpZihmbGFncy5wbG90IHx8IGZsYWdzLmNhbGMpIHtcbiAgICAgICAgZmxhZ3MubGF5b3V0UmVwbG90ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBub3cgYWxsIGF0dHJpYnV0ZSBtb2RzIGFyZSBkb25lLCBhcyBhcmVcbiAgICAvLyByZWRvIGFuZCB1bmRvIHNvIHdlIGNhbiBzYXZlIHRoZW1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGZsYWdzOiBmbGFncyxcbiAgICAgICAgcmFuZ2VzQWx0ZXJlZDogcmFuZ2VzQWx0ZXJlZCxcbiAgICAgICAgdW5kb2l0OiB1bmRvaXQsXG4gICAgICAgIHJlZG9pdDogcmVkb2l0LFxuICAgICAgICBldmVudERhdGE6IGV2ZW50RGF0YVxuICAgIH07XG59XG5cbi8qXG4gKiB1cGRhdGVBdXRvc2l6ZTogd2UgbWFkZSBhIGNoYW5nZSwgZG9lcyBpdCBjaGFuZ2UgdGhlIGF1dG9zaXplIHJlc3VsdD9cbiAqIHB1dHMgdGhlIG5ldyBzaXplIGludG8gZnVsbExheW91dFxuICogcmV0dXJucyB0cnVlIGlmIGVpdGhlciBoZWlnaHQgb3Igd2lkdGggY2hhbmdlZFxuICovXG5mdW5jdGlvbiB1cGRhdGVBdXRvc2l6ZShnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIG9sZFdpZHRoID0gZnVsbExheW91dC53aWR0aDtcbiAgICB2YXIgb2xkSGVpZ2h0ID0gZnVsbExheW91dC5oZWlnaHQ7XG5cbiAgICAvLyBjYWxjdWxhdGUgYXV0b3NpemluZ1xuICAgIGlmKGdkLmxheW91dC5hdXRvc2l6ZSkgUGxvdHMucGxvdEF1dG9TaXplKGdkLCBnZC5sYXlvdXQsIGZ1bGxMYXlvdXQpO1xuXG4gICAgcmV0dXJuIChmdWxsTGF5b3V0LndpZHRoICE9PSBvbGRXaWR0aCkgfHwgKGZ1bGxMYXlvdXQuaGVpZ2h0ICE9PSBvbGRIZWlnaHQpO1xufVxuXG4vKipcbiAqIHVwZGF0ZTogdXBkYXRlIHRyYWNlIGFuZCBsYXlvdXQgYXR0cmlidXRlcyBvZiBhbiBleGlzdGluZyBwbG90XG4gKlxuICogQHBhcmFtIHtTdHJpbmcgfCBIVE1MRGl2RWxlbWVudH0gZ2RcbiAqICB0aGUgaWQgb3IgRE9NIGVsZW1lbnQgb2YgdGhlIGdyYXBoIGNvbnRhaW5lciBkaXZcbiAqIEBwYXJhbSB7T2JqZWN0fSB0cmFjZVVwZGF0ZVxuICogIGF0dHJpYnV0ZSBvYmplY3QgYHthc3RyMTogdmFsMSwgYXN0cjI6IHZhbDIgLi4ufWBcbiAqICBjb3JyZXNwb25kaW5nIHRvIHVwZGF0ZXMgaW4gdGhlIHBsb3QncyB0cmFjZXNcbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXlvdXRVcGRhdGVcbiAqICBhdHRyaWJ1dGUgb2JqZWN0IGB7YXN0cjE6IHZhbDEsIGFzdHIyOiB2YWwyIC4uLn1gXG4gKiAgY29ycmVzcG9uZGluZyB0byB1cGRhdGVzIGluIHRoZSBwbG90J3MgbGF5b3V0XG4gKiBAcGFyYW0ge051bWJlcltdIHwgTnVtYmVyfSBbdHJhY2VzXVxuICogIGludGVnZXIgb3IgYXJyYXkgb2YgaW50ZWdlcnMgZm9yIHRoZSB0cmFjZXMgdG8gYWx0ZXIgKGFsbCBpZiBvbWl0dGVkKVxuICpcbiAqL1xuZnVuY3Rpb24gdXBkYXRlKGdkLCB0cmFjZVVwZGF0ZSwgbGF5b3V0VXBkYXRlLCBfdHJhY2VzKSB7XG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuICAgIGhlbHBlcnMuY2xlYXJQcm9taXNlUXVldWUoZ2QpO1xuXG4gICAgaWYoZ2QuZnJhbWV3b3JrICYmIGdkLmZyYW1ld29yay5pc1BvbGFyKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZ2QpO1xuICAgIH1cblxuICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdCh0cmFjZVVwZGF0ZSkpIHRyYWNlVXBkYXRlID0ge307XG4gICAgaWYoIUxpYi5pc1BsYWluT2JqZWN0KGxheW91dFVwZGF0ZSkpIGxheW91dFVwZGF0ZSA9IHt9O1xuXG4gICAgaWYoT2JqZWN0LmtleXModHJhY2VVcGRhdGUpLmxlbmd0aCkgZ2QuY2hhbmdlZCA9IHRydWU7XG4gICAgaWYoT2JqZWN0LmtleXMobGF5b3V0VXBkYXRlKS5sZW5ndGgpIGdkLmNoYW5nZWQgPSB0cnVlO1xuXG4gICAgdmFyIHRyYWNlcyA9IGhlbHBlcnMuY29lcmNlVHJhY2VJbmRpY2VzKGdkLCBfdHJhY2VzKTtcblxuICAgIHZhciByZXN0eWxlU3BlY3MgPSBfcmVzdHlsZShnZCwgTGliLmV4dGVuZEZsYXQoe30sIHRyYWNlVXBkYXRlKSwgdHJhY2VzKTtcbiAgICB2YXIgcmVzdHlsZUZsYWdzID0gcmVzdHlsZVNwZWNzLmZsYWdzO1xuXG4gICAgdmFyIHJlbGF5b3V0U3BlY3MgPSBfcmVsYXlvdXQoZ2QsIExpYi5leHRlbmRGbGF0KHt9LCBsYXlvdXRVcGRhdGUpKTtcbiAgICB2YXIgcmVsYXlvdXRGbGFncyA9IHJlbGF5b3V0U3BlY3MuZmxhZ3M7XG5cbiAgICAvLyBjbGVhciBjYWxjZGF0YSBhbmQvb3IgYXhpcyB0eXBlcyBpZiByZXF1aXJlZFxuICAgIGlmKHJlc3R5bGVGbGFncy5jYWxjIHx8IHJlbGF5b3V0RmxhZ3MuY2FsYykgZ2QuY2FsY2RhdGEgPSB1bmRlZmluZWQ7XG4gICAgaWYocmVzdHlsZUZsYWdzLmNsZWFyQXhpc1R5cGVzKSBoZWxwZXJzLmNsZWFyQXhpc1R5cGVzKGdkLCB0cmFjZXMsIGxheW91dFVwZGF0ZSk7XG5cbiAgICAvLyBmaWxsIGluIHJlZHJhdyBzZXF1ZW5jZVxuICAgIHZhciBzZXEgPSBbXTtcblxuICAgIGlmKHJlbGF5b3V0RmxhZ3MubGF5b3V0UmVwbG90KSB7XG4gICAgICAgIC8vIE4uQi4gd29ya3MgZmluZSB3aGVuIGJvdGhcbiAgICAgICAgLy8gcmVsYXlvdXRGbGFncy5sYXlvdXRSZXBsb3QgYW5kIHJlc3R5bGVGbGFncy5mdWxsUmVwbG90IGFyZSB0cnVlXG4gICAgICAgIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmxheW91dFJlcGxvdCk7XG4gICAgfSBlbHNlIGlmKHJlc3R5bGVGbGFncy5mdWxsUmVwbG90KSB7XG4gICAgICAgIHNlcS5wdXNoKGV4cG9ydHMucGxvdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc2VxLnB1c2goUGxvdHMucHJldmlvdXNQcm9taXNlcyk7XG4gICAgICAgIGF4UmFuZ2VTdXBwbHlEZWZhdWx0c0J5UGFzcyhnZCwgcmVsYXlvdXRGbGFncywgcmVsYXlvdXRTcGVjcykgfHwgUGxvdHMuc3VwcGx5RGVmYXVsdHMoZ2QpO1xuXG4gICAgICAgIGlmKHJlc3R5bGVGbGFncy5zdHlsZSkgc2VxLnB1c2goc3Vicm91dGluZXMuZG9UcmFjZVN0eWxlKTtcbiAgICAgICAgaWYocmVzdHlsZUZsYWdzLmNvbG9yYmFycyB8fCByZWxheW91dEZsYWdzLmNvbG9yYmFycykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Db2xvckJhcnMpO1xuICAgICAgICBpZihyZWxheW91dEZsYWdzLmxlZ2VuZCkgc2VxLnB1c2goc3Vicm91dGluZXMuZG9MZWdlbmQpO1xuICAgICAgICBpZihyZWxheW91dEZsYWdzLmxheW91dHN0eWxlKSBzZXEucHVzaChzdWJyb3V0aW5lcy5sYXlvdXRTdHlsZXMpO1xuICAgICAgICBpZihyZWxheW91dEZsYWdzLmF4cmFuZ2UpIGFkZEF4UmFuZ2VTZXF1ZW5jZShzZXEsIHJlbGF5b3V0U3BlY3MucmFuZ2VzQWx0ZXJlZCk7XG4gICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MudGlja3MpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmRvVGlja3NSZWxheW91dCk7XG4gICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MubW9kZWJhcikgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Nb2RlQmFyKTtcbiAgICAgICAgaWYocmVsYXlvdXRGbGFncy5jYW1lcmEpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmRvQ2FtZXJhKTtcblxuICAgICAgICBzZXEucHVzaChlbWl0QWZ0ZXJQbG90KTtcbiAgICB9XG5cbiAgICBzZXEucHVzaChQbG90cy5yZWhvdmVyLCBQbG90cy5yZWRyYWcpO1xuXG4gICAgUXVldWUuYWRkKGdkLFxuICAgICAgICB1cGRhdGUsIFtnZCwgcmVzdHlsZVNwZWNzLnVuZG9pdCwgcmVsYXlvdXRTcGVjcy51bmRvaXQsIHJlc3R5bGVTcGVjcy50cmFjZXNdLFxuICAgICAgICB1cGRhdGUsIFtnZCwgcmVzdHlsZVNwZWNzLnJlZG9pdCwgcmVsYXlvdXRTcGVjcy5yZWRvaXQsIHJlc3R5bGVTcGVjcy50cmFjZXNdXG4gICAgKTtcblxuICAgIHZhciBwbG90RG9uZSA9IExpYi5zeW5jT3JBc3luYyhzZXEsIGdkKTtcbiAgICBpZighcGxvdERvbmUgfHwgIXBsb3REb25lLnRoZW4pIHBsb3REb25lID0gUHJvbWlzZS5yZXNvbHZlKGdkKTtcblxuICAgIHJldHVybiBwbG90RG9uZS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfdXBkYXRlJywge1xuICAgICAgICAgICAgZGF0YTogcmVzdHlsZVNwZWNzLmV2ZW50RGF0YSxcbiAgICAgICAgICAgIGxheW91dDogcmVsYXlvdXRTcGVjcy5ldmVudERhdGFcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGdkO1xuICAgIH0pO1xufVxuXG4vKlxuICogaW50ZXJuYWwtdXNlLW9ubHkgcmVzdHlsZS9yZWxheW91dC91cGRhdGUgdmFyaWFudHMgdGhhdCByZWNvcmQgdGhlIGluaXRpYWxcbiAqIHZhbHVlcyBpbiAoZnVsbExheW91dHxmdWxsVHJhY2UpLl9wcmVHVUkgc28gY2hhbmdlcyBjYW4gYmUgcGVyc2lzdGVkIGFjcm9zc1xuICogUGxvdGx5LnJlYWN0IGRhdGEgdXBkYXRlcywgZGVwZW5kZW50IG9uIHVpcmV2aXNpb24gYXR0cmlidXRlc1xuICovXG5mdW5jdGlvbiBndWlFZGl0KGZ1bmMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gd3JhcHBlZEVkaXQoZ2QpIHtcbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX2d1aUVkaXRpbmcgPSB0cnVlO1xuICAgICAgICB2YXIgcCA9IGZ1bmMuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX2d1aUVkaXRpbmcgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfTtcbn1cblxuLy8gRm9yIGNvbm5lY3RpbmcgZWRpdGVkIGxheW91dCBhdHRyaWJ1dGVzIHRvIHVpcmV2aXNpb24gYXR0cnNcbi8vIElmIG5vIGBhdHRyYCB3ZSB1c2UgYG1hdGNoWzFdICsgJy51aXJldmlzaW9uJ2Bcbi8vIE9yZGVyZWQgYnkgbW9zdCBjb21tb24gZWRpdHMgZmlyc3QsIHRvIG1pbmltaXplIG91ciBzZWFyY2ggdGltZVxudmFyIGxheW91dFVJQ29udHJvbFBhdHRlcm5zID0gW1xuICAgIHtwYXR0ZXJuOiAvXmhpZGRlbmxhYmVscy8sIGF0dHI6ICdsZWdlbmQudWlyZXZpc2lvbid9LFxuICAgIHtwYXR0ZXJuOiAvXigoeHx5KWF4aXNcXGQqKVxcLigoYXV0byk/cmFuZ2V8dGl0bGVcXC50ZXh0KS99LFxuXG4gICAgLy8gc2hvd3NwaWtlcyBhbmQgbW9kZXMgaW5jbHVkZSB0aG9zZSBuZXN0ZWQgaW5zaWRlIHNjZW5lc1xuICAgIHtwYXR0ZXJuOiAvYXhpc1xcZCpcXC5zaG93c3Bpa2VzJC8sIGF0dHI6ICdtb2RlYmFyLnVpcmV2aXNpb24nfSxcbiAgICB7cGF0dGVybjogLyhob3ZlcnxkcmFnKW1vZGUkLywgYXR0cjogJ21vZGViYXIudWlyZXZpc2lvbid9LFxuXG4gICAge3BhdHRlcm46IC9eKHNjZW5lXFxkKilcXC5jYW1lcmEvfSxcbiAgICB7cGF0dGVybjogL14oZ2VvXFxkKilcXC4ocHJvamVjdGlvbnxjZW50ZXIpL30sXG4gICAge3BhdHRlcm46IC9eKHRlcm5hcnlcXGQqXFwuW2FiY11heGlzKVxcLihtaW58dGl0bGVcXC50ZXh0KSQvfSxcbiAgICB7cGF0dGVybjogL14ocG9sYXJcXGQqXFwucmFkaWFsYXhpcylcXC4oKGF1dG8pP3JhbmdlfGFuZ2xlfHRpdGxlXFwudGV4dCkvfSxcbiAgICB7cGF0dGVybjogL14ocG9sYXJcXGQqXFwuYW5ndWxhcmF4aXMpXFwucm90YXRpb24vfSxcbiAgICB7cGF0dGVybjogL14obWFwYm94XFxkKilcXC4oY2VudGVyfHpvb218YmVhcmluZ3xwaXRjaCkvfSxcblxuICAgIHtwYXR0ZXJuOiAvXmxlZ2VuZFxcLih4fHkpJC8sIGF0dHI6ICdlZGl0cmV2aXNpb24nfSxcbiAgICB7cGF0dGVybjogL14oc2hhcGVzfGFubm90YXRpb25zKS8sIGF0dHI6ICdlZGl0cmV2aXNpb24nfSxcbiAgICB7cGF0dGVybjogL150aXRsZVxcLnRleHQkLywgYXR0cjogJ2VkaXRyZXZpc2lvbid9XG5dO1xuXG4vLyBzYW1lIGZvciB0cmFjZSBhdHRyaWJ1dGVzOiBpZiBgYXR0cmAgaXMgZ2l2ZW4gaXQncyBpbiBsYXlvdXQsXG4vLyBvciB3aXRoIG5vIGBhdHRyYCB3ZSB1c2UgYHRyYWNlLnVpcmV2aXNpb25gXG52YXIgdHJhY2VVSUNvbnRyb2xQYXR0ZXJucyA9IFtcbiAgICB7cGF0dGVybjogL15zZWxlY3RlZHBvaW50cyQvLCBhdHRyOiAnc2VsZWN0aW9ucmV2aXNpb24nfSxcbiAgICAvLyBcInZpc2libGVcIiBpbmNsdWRlcyB0cmFjZS50cmFuc2Zvcm1zW2ldLnN0eWxlc1tqXS52YWx1ZS52aXNpYmxlXG4gICAge3BhdHRlcm46IC8oXnx2YWx1ZVxcLil2aXNpYmxlJC8sIGF0dHI6ICdsZWdlbmQudWlyZXZpc2lvbid9LFxuICAgIHtwYXR0ZXJuOiAvXmRpbWVuc2lvbnNcXFtcXGQrXFxdXFwuY29uc3RyYWludHJhbmdlL30sXG4gICAge3BhdHRlcm46IC9ebm9kZVxcLih4fHl8Z3JvdXBzKS99LCAvLyBmb3IgU2Fua2V5IG5vZGVzXG4gICAge3BhdHRlcm46IC9ebGV2ZWwkL30sIC8vIGZvciBTdW5idXJzdCB0cmFjZXNcblxuICAgIC8vIGJlbG93IHRoaXMgeW91IG11c3QgYmUgaW4gZWRpdGFibGU6IHRydWUgbW9kZVxuICAgIC8vIFRPRE86IEkgc3RpbGwgcHV0IG5hbWUgYW5kIHRpdGxlIHdpdGggYHRyYWNlLnVpcmV2aXNpb25gXG4gICAgLy8gcmVhc29uYWJsZSBvciBzaG91bGQgdGhlc2UgYmUgYGVkaXRyZXZpc2lvbmA/XG4gICAgLy8gQWxzbyBhcHBsaWVzIHRvIGF4aXMgdGl0bGVzIHVwIGluIHRoZSBsYXlvdXQgc2VjdGlvblxuXG4gICAgLy8gXCJuYW1lXCIgYWxzbyBpbmNsdWRlcyB0cmFuc2Zvcm0uc3R5bGVzXG4gICAge3BhdHRlcm46IC8oXnx2YWx1ZVxcLiluYW1lJC99LFxuICAgIC8vIGluY2x1ZGluZyBuZXN0ZWQgY29sb3JiYXIgYXR0cmlidXRlcyAoaWUgbWFya2VyLmNvbG9yYmFyKVxuICAgIHtwYXR0ZXJuOiAvY29sb3JiYXJcXC50aXRsZVxcLnRleHQkL30sXG4gICAge3BhdHRlcm46IC9jb2xvcmJhclxcLih4fHkpJC8sIGF0dHI6ICdlZGl0cmV2aXNpb24nfVxuXTtcblxuZnVuY3Rpb24gZmluZFVJUGF0dGVybihrZXksIHBhdHRlcm5TcGVjcykge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBwYXR0ZXJuU3BlY3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNwZWMgPSBwYXR0ZXJuU3BlY3NbaV07XG4gICAgICAgIHZhciBtYXRjaCA9IGtleS5tYXRjaChzcGVjLnBhdHRlcm4pO1xuICAgICAgICBpZihtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIHtoZWFkOiBtYXRjaFsxXSwgYXR0cjogc3BlYy5hdHRyfTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLy8gV2UncmUgZmluZGluZyB0aGUgbmV3IHVpcmV2aXNpb24gYmVmb3JlIHN1cHBseURlZmF1bHRzLCBzbyBkbyB0aGVcbi8vIGluaGVyaXRhbmNlIG1hbnVhbGx5LiBOb3RlIHRoYXQgb25seSBgdW5kZWZpbmVkYCBpbmhlcml0cyAtIG90aGVyXG4vLyBmYWxzeSB2YWx1ZXMgYXJlIHJldHVybmVkLlxuZnVuY3Rpb24gZ2V0TmV3UmV2KHJldkF0dHIsIGNvbnRhaW5lcikge1xuICAgIHZhciBuZXdSZXYgPSBuZXN0ZWRQcm9wZXJ0eShjb250YWluZXIsIHJldkF0dHIpLmdldCgpO1xuICAgIGlmKG5ld1JldiAhPT0gdW5kZWZpbmVkKSByZXR1cm4gbmV3UmV2O1xuXG4gICAgdmFyIHBhcnRzID0gcmV2QXR0ci5zcGxpdCgnLicpO1xuICAgIHBhcnRzLnBvcCgpO1xuICAgIHdoaWxlKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgcGFydHMucG9wKCk7XG4gICAgICAgIG5ld1JldiA9IG5lc3RlZFByb3BlcnR5KGNvbnRhaW5lciwgcGFydHMuam9pbignLicpICsgJy51aXJldmlzaW9uJykuZ2V0KCk7XG4gICAgICAgIGlmKG5ld1JldiAhPT0gdW5kZWZpbmVkKSByZXR1cm4gbmV3UmV2O1xuICAgIH1cblxuICAgIHJldHVybiBjb250YWluZXIudWlyZXZpc2lvbjtcbn1cblxuZnVuY3Rpb24gZ2V0RnVsbFRyYWNlSW5kZXhGcm9tVWlkKHVpZCwgZnVsbERhdGEpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoZnVsbERhdGFbaV0uX2Z1bGxJbnB1dC51aWQgPT09IHVpZCkgcmV0dXJuIGk7XG4gICAgfVxuICAgIHJldHVybiAtMTtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhY2VJbmRleEZyb21VaWQodWlkLCBkYXRhLCB0cmFjZWkpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihkYXRhW2ldLnVpZCA9PT0gdWlkKSByZXR1cm4gaTtcbiAgICB9XG4gICAgLy8gZmFsbCBiYWNrIG9uIHRyYWNlIG9yZGVyLCBidXQgb25seSBpZiB1c2VyIGRpZG4ndCBwcm92aWRlIGEgdWlkIGZvciB0aGF0IHRyYWNlXG4gICAgcmV0dXJuICghZGF0YVt0cmFjZWldIHx8IGRhdGFbdHJhY2VpXS51aWQpID8gLTEgOiB0cmFjZWk7XG59XG5cbmZ1bmN0aW9uIHZhbHNNYXRjaCh2MSwgdjIpIHtcbiAgICB2YXIgdjFJc09iaiA9IExpYi5pc1BsYWluT2JqZWN0KHYxKTtcbiAgICB2YXIgdjFJc0FycmF5ID0gQXJyYXkuaXNBcnJheSh2MSk7XG4gICAgaWYodjFJc09iaiB8fCB2MUlzQXJyYXkpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICh2MUlzT2JqICYmIExpYi5pc1BsYWluT2JqZWN0KHYyKSkgfHxcbiAgICAgICAgICAgICh2MUlzQXJyYXkgJiYgQXJyYXkuaXNBcnJheSh2MikpXG4gICAgICAgICkgJiYgSlNPTi5zdHJpbmdpZnkodjEpID09PSBKU09OLnN0cmluZ2lmeSh2Mik7XG4gICAgfVxuICAgIHJldHVybiB2MSA9PT0gdjI7XG59XG5cbmZ1bmN0aW9uIGFwcGx5VUlSZXZpc2lvbnMoZGF0YSwgbGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBsYXlvdXRQcmVHVUkgPSBvbGRGdWxsTGF5b3V0Ll9wcmVHVUk7XG4gICAgdmFyIGtleSwgcmV2QXR0ciwgb2xkUmV2LCBuZXdSZXYsIG1hdGNoLCBwcmVHVUlWYWwsIG5ld05QLCBuZXdWYWw7XG4gICAgdmFyIGJvdGhJbmhlcml0QXV0b3JhbmdlID0gW107XG4gICAgdmFyIG5ld1JhbmdlQWNjZXB0ZWQgPSB7fTtcbiAgICBmb3Ioa2V5IGluIGxheW91dFByZUdVSSkge1xuICAgICAgICBtYXRjaCA9IGZpbmRVSVBhdHRlcm4oa2V5LCBsYXlvdXRVSUNvbnRyb2xQYXR0ZXJucyk7XG4gICAgICAgIGlmKG1hdGNoKSB7XG4gICAgICAgICAgICByZXZBdHRyID0gbWF0Y2guYXR0ciB8fCAobWF0Y2guaGVhZCArICcudWlyZXZpc2lvbicpO1xuICAgICAgICAgICAgb2xkUmV2ID0gbmVzdGVkUHJvcGVydHkob2xkRnVsbExheW91dCwgcmV2QXR0cikuZ2V0KCk7XG4gICAgICAgICAgICBuZXdSZXYgPSBvbGRSZXYgJiYgZ2V0TmV3UmV2KHJldkF0dHIsIGxheW91dCk7XG4gICAgICAgICAgICBpZihuZXdSZXYgJiYgKG5ld1JldiA9PT0gb2xkUmV2KSkge1xuICAgICAgICAgICAgICAgIHByZUdVSVZhbCA9IGxheW91dFByZUdVSVtrZXldO1xuICAgICAgICAgICAgICAgIGlmKHByZUdVSVZhbCA9PT0gbnVsbCkgcHJlR1VJVmFsID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIG5ld05QID0gbmVzdGVkUHJvcGVydHkobGF5b3V0LCBrZXkpO1xuICAgICAgICAgICAgICAgIG5ld1ZhbCA9IG5ld05QLmdldCgpO1xuICAgICAgICAgICAgICAgIGlmKHZhbHNNYXRjaChuZXdWYWwsIHByZUdVSVZhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYobmV3VmFsID09PSB1bmRlZmluZWQgJiYga2V5LnN1YnN0cihrZXkubGVuZ3RoIC0gOSkgPT09ICdhdXRvcmFuZ2UnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBib3RoSW5oZXJpdEF1dG9yYW5nZS5wdXNoKGtleS5zdWJzdHIoMCwga2V5Lmxlbmd0aCAtIDEwKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbmV3TlAuc2V0KHVuZGVmaW5lZFRvTnVsbChuZXN0ZWRQcm9wZXJ0eShvbGRGdWxsTGF5b3V0LCBrZXkpLmdldCgpKSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExpYi53YXJuKCd1bnJlY29nbml6ZWQgR1VJIGVkaXQ6ICcgKyBrZXkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGlmIHdlIGdvdCB0aGlzIGZhciwgdGhlIG5ldyB2YWx1ZSB3YXMgYWNjZXB0ZWQgYXMgdGhlIG5ldyBzdGFydGluZ1xuICAgICAgICAvLyBwb2ludCAoZWl0aGVyIGJlY2F1c2UgaXQgY2hhbmdlZCBvciByZXZpc2lvbiBjaGFuZ2VkKVxuICAgICAgICAvLyBzbyByZW1vdmUgaXQgZnJvbSBfcHJlR1VJIGZvciBuZXh0IHRpbWUuXG4gICAgICAgIGRlbGV0ZSBsYXlvdXRQcmVHVUlba2V5XTtcblxuICAgICAgICBpZihrZXkuc3Vic3RyKGtleS5sZW5ndGggLSA4LCA2KSA9PT0gJ3JhbmdlWycpIHtcbiAgICAgICAgICAgIG5ld1JhbmdlQWNjZXB0ZWRba2V5LnN1YnN0cigwLCBrZXkubGVuZ3RoIC0gOSldID0gMTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFNwZWNpYWwgbG9naWMgZm9yIGBhdXRvcmFuZ2VgLCBzaW5jZSBpdCBpbnRlcmFjdHMgd2l0aCBgcmFuZ2VgOlxuICAgIC8vIElmIHRoZSBuZXcgZmlndXJlJ3MgbWF0Y2hpbmcgYHJhbmdlYCB3YXMga2VwdCwgYW5kIGBhdXRvcmFuZ2VgXG4gICAgLy8gd2Fzbid0IHN1cHBsaWVkIGV4cGxpY2l0bHkgaW4gZWl0aGVyIHRoZSBvcmlnaW5hbCBvciB0aGUgbmV3IGZpZ3VyZSxcbiAgICAvLyB3ZSBzaG91bGRuJ3QgYWx0ZXIgdGhhdCAtIGJ1dCB3ZSBtYXkganVzdCBoYXZlIGRvbmUgdGhhdCwgc28gZml4IGl0LlxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBib3RoSW5oZXJpdEF1dG9yYW5nZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXhBdHRyID0gYm90aEluaGVyaXRBdXRvcmFuZ2VbaV07XG4gICAgICAgIGlmKG5ld1JhbmdlQWNjZXB0ZWRbYXhBdHRyXSkge1xuICAgICAgICAgICAgdmFyIG5ld0F4ID0gbmVzdGVkUHJvcGVydHkobGF5b3V0LCBheEF0dHIpLmdldCgpO1xuICAgICAgICAgICAgaWYobmV3QXgpIGRlbGV0ZSBuZXdBeC5hdXRvcmFuZ2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBOb3cgdHJhY2VzIC0gdHJ5IHRvIG1hdGNoIHRoZW0gdXAgYnkgdWlkIChpbiBjYXNlIHdlIGFkZGVkL2RlbGV0ZWQgaW5cbiAgICAvLyB0aGUgbWlkZGxlKSwgdGhlbiBmYWxsIGJhY2sgb24gaW5kZXguXG4gICAgdmFyIGFsbFRyYWNlUHJlR1VJID0gb2xkRnVsbExheW91dC5fdHJhY2VQcmVHVUk7XG4gICAgZm9yKHZhciB1aWQgaW4gYWxsVHJhY2VQcmVHVUkpIHtcbiAgICAgICAgdmFyIHRyYWNlUHJlR1VJID0gYWxsVHJhY2VQcmVHVUlbdWlkXTtcbiAgICAgICAgdmFyIG5ld1RyYWNlID0gbnVsbDtcbiAgICAgICAgdmFyIGZ1bGxJbnB1dDtcbiAgICAgICAgZm9yKGtleSBpbiB0cmFjZVByZUdVSSkge1xuICAgICAgICAgICAgLy8gd2FpdCB1bnRpbCB3ZSBrbm93IHdlIGhhdmUgcHJlR1VJIHZhbHVlcyB0byBsb29rIGZvciB0cmFjZXNcbiAgICAgICAgICAgIC8vIGJ1dCBpZiB3ZSBkb24ndCBmaW5kIGJvdGgsIHN0b3AgbG9va2luZyBhdCB0aGlzIHVpZFxuICAgICAgICAgICAgaWYoIW5ld1RyYWNlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bGxpID0gZ2V0RnVsbFRyYWNlSW5kZXhGcm9tVWlkKHVpZCwgb2xkRnVsbERhdGEpO1xuICAgICAgICAgICAgICAgIGlmKGZ1bGxpIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTb21laG93IHdlIGRpZG4ndCBldmVuIGhhdmUgdGhpcyB0cmFjZSBpbiBvbGRGdWxsRGF0YS4uLlxuICAgICAgICAgICAgICAgICAgICAvLyBJIGd1ZXNzIHRoaXMgY291bGQgaGFwcGVuIHdpdGggYGRlbGV0ZVRyYWNlc2Agb3Igc29tZXRoaW5nXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBhbGxUcmFjZVByZUdVSVt1aWRdO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGZ1bGxUcmFjZSA9IG9sZEZ1bGxEYXRhW2Z1bGxpXTtcbiAgICAgICAgICAgICAgICBmdWxsSW5wdXQgPSBmdWxsVHJhY2UuX2Z1bGxJbnB1dDtcblxuICAgICAgICAgICAgICAgIHZhciBuZXdUcmFjZWkgPSBnZXRUcmFjZUluZGV4RnJvbVVpZCh1aWQsIGRhdGEsIGZ1bGxJbnB1dC5pbmRleCk7XG4gICAgICAgICAgICAgICAgaWYobmV3VHJhY2VpIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBObyBtYXRjaCBpbiBuZXcgZGF0YVxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgYWxsVHJhY2VQcmVHVUlbdWlkXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG5ld1RyYWNlID0gZGF0YVtuZXdUcmFjZWldO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBtYXRjaCA9IGZpbmRVSVBhdHRlcm4oa2V5LCB0cmFjZVVJQ29udHJvbFBhdHRlcm5zKTtcbiAgICAgICAgICAgIGlmKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYobWF0Y2guYXR0cikge1xuICAgICAgICAgICAgICAgICAgICBvbGRSZXYgPSBuZXN0ZWRQcm9wZXJ0eShvbGRGdWxsTGF5b3V0LCBtYXRjaC5hdHRyKS5nZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgbmV3UmV2ID0gb2xkUmV2ICYmIGdldE5ld1JldihtYXRjaC5hdHRyLCBsYXlvdXQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJldiA9IGZ1bGxJbnB1dC51aXJldmlzaW9uO1xuICAgICAgICAgICAgICAgICAgICAvLyBpbmhlcml0YW5jZSBmb3IgdHJhY2UudWlyZXZpc2lvbiBpcyBzaW1wbGUsIGp1c3QgbGF5b3V0LnVpcmV2aXNpb25cbiAgICAgICAgICAgICAgICAgICAgbmV3UmV2ID0gbmV3VHJhY2UudWlyZXZpc2lvbjtcbiAgICAgICAgICAgICAgICAgICAgaWYobmV3UmV2ID09PSB1bmRlZmluZWQpIG5ld1JldiA9IGxheW91dC51aXJldmlzaW9uO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKG5ld1JldiAmJiBuZXdSZXYgPT09IG9sZFJldikge1xuICAgICAgICAgICAgICAgICAgICBwcmVHVUlWYWwgPSB0cmFjZVByZUdVSVtrZXldO1xuICAgICAgICAgICAgICAgICAgICBpZihwcmVHVUlWYWwgPT09IG51bGwpIHByZUdVSVZhbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgbmV3TlAgPSBuZXN0ZWRQcm9wZXJ0eShuZXdUcmFjZSwga2V5KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsID0gbmV3TlAuZ2V0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHZhbHNNYXRjaChuZXdWYWwsIHByZUdVSVZhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05QLnNldCh1bmRlZmluZWRUb051bGwobmVzdGVkUHJvcGVydHkoZnVsbElucHV0LCBrZXkpLmdldCgpKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTGliLndhcm4oJ3VucmVjb2duaXplZCBHVUkgZWRpdDogJyArIGtleSArICcgaW4gdHJhY2UgdWlkICcgKyB1aWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVsZXRlIHRyYWNlUHJlR1VJW2tleV07XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogUGxvdGx5LnJlYWN0OlxuICogQSBwbG90L3VwZGF0ZSBtZXRob2QgdGhhdCB0YWtlcyB0aGUgZnVsbCBwbG90IHN0YXRlIChzYW1lIEFQSSBhcyBwbG90L25ld1Bsb3QpXG4gKiBhbmQgZGlmZnMgdG8gZGV0ZXJtaW5lIHRoZSBtaW5pbWFsIHVwZGF0ZSBwYXRod2F5XG4gKlxuICogQHBhcmFtIHtzdHJpbmcgaWQgb3IgRE9NIGVsZW1lbnR9IGdkXG4gKiAgICAgIHRoZSBpZCBvciBET00gZWxlbWVudCBvZiB0aGUgZ3JhcGggY29udGFpbmVyIGRpdlxuICogQHBhcmFtIHthcnJheSBvZiBvYmplY3RzfSBkYXRhXG4gKiAgICAgIGFycmF5IG9mIHRyYWNlcywgY29udGFpbmluZyB0aGUgZGF0YSBhbmQgZGlzcGxheSBpbmZvcm1hdGlvbiBmb3IgZWFjaCB0cmFjZVxuICogQHBhcmFtIHtvYmplY3R9IGxheW91dFxuICogICAgICBvYmplY3QgZGVzY3JpYmluZyB0aGUgb3ZlcmFsbCBkaXNwbGF5IG9mIHRoZSBwbG90LFxuICogICAgICBhbGwgdGhlIHN0dWZmIHRoYXQgZG9lc24ndCBwZXJ0YWluIHRvIGFueSBpbmRpdmlkdWFsIHRyYWNlXG4gKiBAcGFyYW0ge29iamVjdH0gY29uZmlnXG4gKiAgICAgIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyAoc2VlIC4vcGxvdF9jb25maWcuanMgZm9yIG1vcmUgaW5mbylcbiAqXG4gKiBPUlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nIGlkIG9yIERPTSBlbGVtZW50fSBnZFxuICogICAgICB0aGUgaWQgb3IgRE9NIGVsZW1lbnQgb2YgdGhlIGdyYXBoIGNvbnRhaW5lciBkaXZcbiAqIEBwYXJhbSB7b2JqZWN0fSBmaWd1cmVcbiAqICAgICAgb2JqZWN0IGNvbnRhaW5pbmcgYGRhdGFgLCBgbGF5b3V0YCwgYGNvbmZpZ2AsIGFuZCBgZnJhbWVzYCBtZW1iZXJzXG4gKlxuICovXG5mdW5jdGlvbiByZWFjdChnZCwgZGF0YSwgbGF5b3V0LCBjb25maWcpIHtcbiAgICB2YXIgZnJhbWVzLCBwbG90RG9uZTtcblxuICAgIGZ1bmN0aW9uIGFkZEZyYW1lcygpIHsgcmV0dXJuIGV4cG9ydHMuYWRkRnJhbWVzKGdkLCBmcmFtZXMpOyB9XG5cbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICB2YXIgb2xkRnVsbERhdGEgPSBnZC5fZnVsbERhdGE7XG4gICAgdmFyIG9sZEZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIC8vIHlvdSBjYW4gdXNlIHRoaXMgYXMgdGhlIGluaXRpYWwgZHJhdyBhcyB3ZWxsIGFzIHRvIHVwZGF0ZVxuICAgIGlmKCFMaWIuaXNQbG90RGl2KGdkKSB8fCAhb2xkRnVsbERhdGEgfHwgIW9sZEZ1bGxMYXlvdXQpIHtcbiAgICAgICAgcGxvdERvbmUgPSBleHBvcnRzLm5ld1Bsb3QoZ2QsIGRhdGEsIGxheW91dCwgY29uZmlnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZihMaWIuaXNQbGFpbk9iamVjdChkYXRhKSkge1xuICAgICAgICAgICAgdmFyIG9iaiA9IGRhdGE7XG4gICAgICAgICAgICBkYXRhID0gb2JqLmRhdGE7XG4gICAgICAgICAgICBsYXlvdXQgPSBvYmoubGF5b3V0O1xuICAgICAgICAgICAgY29uZmlnID0gb2JqLmNvbmZpZztcbiAgICAgICAgICAgIGZyYW1lcyA9IG9iai5mcmFtZXM7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY29uZmlnQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgICAvLyBhc3N1bWUgdGhhdCBpZiB0aGVyZSdzIGEgY29uZmlnIGF0IGFsbCwgd2UncmUgcmVhY3RpbmcgdG8gaXQgdG9vLFxuICAgICAgICAvLyBhbmQgY29tcGxldGVseSByZXBsYWNlIHRoZSBwcmV2aW91cyBjb25maWdcbiAgICAgICAgaWYoY29uZmlnKSB7XG4gICAgICAgICAgICB2YXIgb2xkQ29uZmlnID0gTGliLmV4dGVuZERlZXAoe30sIGdkLl9jb250ZXh0KTtcbiAgICAgICAgICAgIGdkLl9jb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgc2V0UGxvdENvbnRleHQoZ2QsIGNvbmZpZyk7XG4gICAgICAgICAgICBjb25maWdDaGFuZ2VkID0gZGlmZkNvbmZpZyhvbGRDb25maWcsIGdkLl9jb250ZXh0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdkLmRhdGEgPSBkYXRhIHx8IFtdO1xuICAgICAgICBoZWxwZXJzLmNsZWFuRGF0YShnZC5kYXRhKTtcbiAgICAgICAgZ2QubGF5b3V0ID0gbGF5b3V0IHx8IHt9O1xuICAgICAgICBoZWxwZXJzLmNsZWFuTGF5b3V0KGdkLmxheW91dCk7XG5cbiAgICAgICAgYXBwbHlVSVJldmlzaW9ucyhnZC5kYXRhLCBnZC5sYXlvdXQsIG9sZEZ1bGxEYXRhLCBvbGRGdWxsTGF5b3V0KTtcblxuICAgICAgICAvLyBcInRydWVcIiBza2lwcyB1cGRhdGluZyBjYWxjZGF0YSBhbmQgcmVtYXBwaW5nIGFycmF5cyBmcm9tIGNhbGNUcmFuc2Zvcm1zLFxuICAgICAgICAvLyB3aGljaCBzdXBwbHlEZWZhdWx0cyB1c3VhbGx5IGRvZXMgYXQgdGhlIGVuZCwgYnV0IHdlIG1heSBuZWVkIHRvIE5PVCBkb1xuICAgICAgICAvLyBpZiB0aGUgZGlmZiAod2hpY2ggd2UgaGF2ZW4ndCBkZXRlcm1pbmVkIHlldCkgc2F5cyB3ZSdsbCByZWNhbGNcbiAgICAgICAgUGxvdHMuc3VwcGx5RGVmYXVsdHMoZ2QsIHtza2lwVXBkYXRlQ2FsYzogdHJ1ZX0pO1xuXG4gICAgICAgIHZhciBuZXdGdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICAgICAgdmFyIG5ld0Z1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICAgICAgdmFyIGltbXV0YWJsZSA9IG5ld0Z1bGxMYXlvdXQuZGF0YXJldmlzaW9uID09PSB1bmRlZmluZWQ7XG4gICAgICAgIHZhciB0cmFuc2l0aW9uID0gbmV3RnVsbExheW91dC50cmFuc2l0aW9uO1xuXG4gICAgICAgIHZhciByZWxheW91dEZsYWdzID0gZGlmZkxheW91dChnZCwgb2xkRnVsbExheW91dCwgbmV3RnVsbExheW91dCwgaW1tdXRhYmxlLCB0cmFuc2l0aW9uKTtcbiAgICAgICAgdmFyIG5ld0RhdGFSZXZpc2lvbiA9IHJlbGF5b3V0RmxhZ3MubmV3RGF0YVJldmlzaW9uO1xuICAgICAgICB2YXIgcmVzdHlsZUZsYWdzID0gZGlmZkRhdGEoZ2QsIG9sZEZ1bGxEYXRhLCBuZXdGdWxsRGF0YSwgaW1tdXRhYmxlLCB0cmFuc2l0aW9uLCBuZXdEYXRhUmV2aXNpb24pO1xuXG4gICAgICAgIC8vIFRPRE86IGhvdyB0byB0cmFuc2xhdGUgdGhpcyBwYXJ0IG9mIHJlbGF5b3V0IHRvIFBsb3RseS5yZWFjdD9cbiAgICAgICAgLy8gLy8gU2V0dGluZyB3aWR0aCBvciBoZWlnaHQgdG8gbnVsbCBtdXN0IHJlc2V0IHRoZSBncmFwaCdzIHdpZHRoIC8gaGVpZ2h0XG4gICAgICAgIC8vIC8vIGJhY2sgdG8gaXRzIGluaXRpYWwgdmFsdWUgYXMgY29tcHV0ZWQgZHVyaW5nIHRoZSBmaXJzdCBwYXNzIGluIFBsb3RzLnBsb3RBdXRvU2l6ZS5cbiAgICAgICAgLy8gLy9cbiAgICAgICAgLy8gLy8gVG8gZG8gc28sIHdlIG11c3QgbWFudWFsbHkgc2V0IHRoZW0gYmFjayBoZXJlIHVzaW5nIHRoZSBfaW5pdGlhbEF1dG9TaXplIGNhY2hlLlxuICAgICAgICAvLyBpZihbJ3dpZHRoJywgJ2hlaWdodCddLmluZGV4T2YoYWkpICE9PSAtMSAmJiB2aSA9PT0gbnVsbCkge1xuICAgICAgICAvLyAgICAgZnVsbExheW91dFthaV0gPSBnZC5faW5pdGlhbEF1dG9TaXplW2FpXTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIGlmKHVwZGF0ZUF1dG9zaXplKGdkKSkgcmVsYXlvdXRGbGFncy5sYXlvdXRSZXBsb3QgPSB0cnVlO1xuXG4gICAgICAgIC8vIGNsZWFyIGNhbGNkYXRhIGlmIHJlcXVpcmVkXG4gICAgICAgIGlmKHJlc3R5bGVGbGFncy5jYWxjIHx8IHJlbGF5b3V0RmxhZ3MuY2FsYykgZ2QuY2FsY2RhdGEgPSB1bmRlZmluZWQ7XG4gICAgICAgIC8vIG90aGVyd2lzZSBkbyB0aGUgY2FsY2RhdGEgdXBkYXRlcyBhbmQgY2FsY1RyYW5zZm9ybSBhcnJheSByZW1hcHMgdGhhdCB3ZSBza2lwcGVkIGVhcmxpZXJcbiAgICAgICAgZWxzZSBQbG90cy5zdXBwbHlEZWZhdWx0c1VwZGF0ZUNhbGMoZ2QuY2FsY2RhdGEsIG5ld0Z1bGxEYXRhKTtcblxuICAgICAgICAvLyBOb3RlOiB3aGF0IHJlc3R5bGUvcmVsYXlvdXQgdXNlIGltcGxpZWRFZGl0cyBhbmQgY2xlYXJBeGlzVHlwZXMgZm9yXG4gICAgICAgIC8vIG11c3QgYmUgaGFuZGxlZCBieSB0aGUgdXNlciB3aGVuIHVzaW5nIFBsb3RseS5yZWFjdC5cblxuICAgICAgICAvLyBmaWxsIGluIHJlZHJhdyBzZXF1ZW5jZVxuICAgICAgICB2YXIgc2VxID0gW107XG5cbiAgICAgICAgaWYoZnJhbWVzKSB7XG4gICAgICAgICAgICBnZC5fdHJhbnNpdGlvbkRhdGEgPSB7fTtcbiAgICAgICAgICAgIFBsb3RzLmNyZWF0ZVRyYW5zaXRpb25EYXRhKGdkKTtcbiAgICAgICAgICAgIHNlcS5wdXNoKGFkZEZyYW1lcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcmFuc2l0aW9uIHBhdGh3YXksXG4gICAgICAgIC8vIG9ubHkgdXNlZCB3aGVuICd0cmFuc2l0aW9uJyBpcyBzZXQgYnkgdXNlciBhbmRcbiAgICAgICAgLy8gd2hlbiBhdCBsZWFzdCBvbmUgYW5pbWF0YWJsZSBhdHRyaWJ1dGUgaGFzIGNoYW5nZWQsXG4gICAgICAgIC8vIE4uQi4gY29uZmlnIGNoYW5nZWQgYXJlbid0IGFuaW1hdGFibGVcbiAgICAgICAgaWYobmV3RnVsbExheW91dC50cmFuc2l0aW9uICYmICFjb25maWdDaGFuZ2VkICYmIChyZXN0eWxlRmxhZ3MuYW5pbSB8fCByZWxheW91dEZsYWdzLmFuaW0pKSB7XG4gICAgICAgICAgICBQbG90cy5kb0NhbGNkYXRhKGdkKTtcbiAgICAgICAgICAgIHN1YnJvdXRpbmVzLmRvQXV0b1JhbmdlQW5kQ29uc3RyYWludHMoZ2QpO1xuXG4gICAgICAgICAgICBzZXEucHVzaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUGxvdHMudHJhbnNpdGlvbkZyb21SZWFjdChnZCwgcmVzdHlsZUZsYWdzLCByZWxheW91dEZsYWdzLCBvbGRGdWxsTGF5b3V0KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYocmVzdHlsZUZsYWdzLmZ1bGxSZXBsb3QgfHwgcmVsYXlvdXRGbGFncy5sYXlvdXRSZXBsb3QgfHwgY29uZmlnQ2hhbmdlZCkge1xuICAgICAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX3NraXBEZWZhdWx0cyA9IHRydWU7XG4gICAgICAgICAgICBzZXEucHVzaChleHBvcnRzLnBsb3QpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9yKHZhciBjb21wb25lbnRUeXBlIGluIHJlbGF5b3V0RmxhZ3MuYXJyYXlzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSByZWxheW91dEZsYWdzLmFycmF5c1tjb21wb25lbnRUeXBlXTtcbiAgICAgICAgICAgICAgICBpZihpbmRpY2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZHJhd09uZSA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZChjb21wb25lbnRUeXBlLCAnZHJhd09uZScpO1xuICAgICAgICAgICAgICAgICAgICBpZihkcmF3T25lICE9PSBMaWIubm9vcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmF3T25lKGdkLCBpbmRpY2VzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkcmF3ID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKGNvbXBvbmVudFR5cGUsICdkcmF3Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihkcmF3ID09PSBMaWIubm9vcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IGRyYXcgY29tcG9uZW50czogJyArIGNvbXBvbmVudFR5cGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZHJhdyhnZCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNlcS5wdXNoKFBsb3RzLnByZXZpb3VzUHJvbWlzZXMpO1xuICAgICAgICAgICAgaWYocmVzdHlsZUZsYWdzLnN0eWxlKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb1RyYWNlU3R5bGUpO1xuICAgICAgICAgICAgaWYocmVzdHlsZUZsYWdzLmNvbG9yYmFycyB8fCByZWxheW91dEZsYWdzLmNvbG9yYmFycykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Db2xvckJhcnMpO1xuICAgICAgICAgICAgaWYocmVsYXlvdXRGbGFncy5sZWdlbmQpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmRvTGVnZW5kKTtcbiAgICAgICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MubGF5b3V0c3R5bGUpIHNlcS5wdXNoKHN1YnJvdXRpbmVzLmxheW91dFN0eWxlcyk7XG4gICAgICAgICAgICBpZihyZWxheW91dEZsYWdzLmF4cmFuZ2UpIGFkZEF4UmFuZ2VTZXF1ZW5jZShzZXEpO1xuICAgICAgICAgICAgaWYocmVsYXlvdXRGbGFncy50aWNrcykgc2VxLnB1c2goc3Vicm91dGluZXMuZG9UaWNrc1JlbGF5b3V0KTtcbiAgICAgICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MubW9kZWJhcikgc2VxLnB1c2goc3Vicm91dGluZXMuZG9Nb2RlQmFyKTtcbiAgICAgICAgICAgIGlmKHJlbGF5b3V0RmxhZ3MuY2FtZXJhKSBzZXEucHVzaChzdWJyb3V0aW5lcy5kb0NhbWVyYSk7XG4gICAgICAgICAgICBzZXEucHVzaChlbWl0QWZ0ZXJQbG90KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlcS5wdXNoKFBsb3RzLnJlaG92ZXIsIFBsb3RzLnJlZHJhZyk7XG5cbiAgICAgICAgcGxvdERvbmUgPSBMaWIuc3luY09yQXN5bmMoc2VxLCBnZCk7XG4gICAgICAgIGlmKCFwbG90RG9uZSB8fCAhcGxvdERvbmUudGhlbikgcGxvdERvbmUgPSBQcm9taXNlLnJlc29sdmUoZ2QpO1xuICAgIH1cblxuICAgIHJldHVybiBwbG90RG9uZS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVhY3QnLCB7XG4gICAgICAgICAgICBkYXRhOiBkYXRhLFxuICAgICAgICAgICAgbGF5b3V0OiBsYXlvdXRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGdkO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBkaWZmRGF0YShnZCwgb2xkRnVsbERhdGEsIG5ld0Z1bGxEYXRhLCBpbW11dGFibGUsIHRyYW5zaXRpb24sIG5ld0RhdGFSZXZpc2lvbikge1xuICAgIHZhciBzYW1lVHJhY2VMZW5ndGggPSBvbGRGdWxsRGF0YS5sZW5ndGggPT09IG5ld0Z1bGxEYXRhLmxlbmd0aDtcblxuICAgIGlmKCF0cmFuc2l0aW9uICYmICFzYW1lVHJhY2VMZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZ1bGxSZXBsb3Q6IHRydWUsXG4gICAgICAgICAgICBjYWxjOiB0cnVlXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGZsYWdzID0gZWRpdFR5cGVzLnRyYWNlRmxhZ3MoKTtcbiAgICBmbGFncy5hcnJheXMgPSB7fTtcbiAgICBmbGFncy5uQ2hhbmdlcyA9IDA7XG4gICAgZmxhZ3MubkNoYW5nZXNBbmltID0gMDtcblxuICAgIHZhciBpLCB0cmFjZTtcblxuICAgIGZ1bmN0aW9uIGdldFRyYWNlVmFsT2JqZWN0KHBhcnRzKSB7XG4gICAgICAgIHZhciBvdXQgPSBQbG90U2NoZW1hLmdldFRyYWNlVmFsT2JqZWN0KHRyYWNlLCBwYXJ0cyk7XG4gICAgICAgIGlmKCF0cmFjZS5fbW9kdWxlLmFuaW1hdGFibGUgJiYgb3V0LmFuaW0pIHtcbiAgICAgICAgICAgIG91dC5hbmltID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICB2YXIgZGlmZk9wdHMgPSB7XG4gICAgICAgIGdldFZhbE9iamVjdDogZ2V0VHJhY2VWYWxPYmplY3QsXG4gICAgICAgIGZsYWdzOiBmbGFncyxcbiAgICAgICAgaW1tdXRhYmxlOiBpbW11dGFibGUsXG4gICAgICAgIHRyYW5zaXRpb246IHRyYW5zaXRpb24sXG4gICAgICAgIG5ld0RhdGFSZXZpc2lvbjogbmV3RGF0YVJldmlzaW9uLFxuICAgICAgICBnZDogZ2RcbiAgICB9O1xuXG4gICAgdmFyIHNlZW5VSURzID0ge307XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBvbGRGdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihuZXdGdWxsRGF0YVtpXSkge1xuICAgICAgICAgICAgdHJhY2UgPSBuZXdGdWxsRGF0YVtpXS5fZnVsbElucHV0O1xuICAgICAgICAgICAgaWYoUGxvdHMuaGFzTWFrZXNEYXRhVHJhbnNmb3JtKHRyYWNlKSkgdHJhY2UgPSBuZXdGdWxsRGF0YVtpXTtcbiAgICAgICAgICAgIGlmKHNlZW5VSURzW3RyYWNlLnVpZF0pIGNvbnRpbnVlO1xuICAgICAgICAgICAgc2VlblVJRHNbdHJhY2UudWlkXSA9IDE7XG5cbiAgICAgICAgICAgIGdldERpZmZGbGFncyhvbGRGdWxsRGF0YVtpXS5fZnVsbElucHV0LCB0cmFjZSwgW10sIGRpZmZPcHRzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGZsYWdzLmNhbGMgfHwgZmxhZ3MucGxvdCkge1xuICAgICAgICBmbGFncy5mdWxsUmVwbG90ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZih0cmFuc2l0aW9uICYmIGZsYWdzLm5DaGFuZ2VzICYmIGZsYWdzLm5DaGFuZ2VzQW5pbSkge1xuICAgICAgICBmbGFncy5hbmltID0gKGZsYWdzLm5DaGFuZ2VzID09PSBmbGFncy5uQ2hhbmdlc0FuaW0pICYmIHNhbWVUcmFjZUxlbmd0aCA/ICdhbGwnIDogJ3NvbWUnO1xuICAgIH1cblxuICAgIHJldHVybiBmbGFncztcbn1cblxuZnVuY3Rpb24gZGlmZkxheW91dChnZCwgb2xkRnVsbExheW91dCwgbmV3RnVsbExheW91dCwgaW1tdXRhYmxlLCB0cmFuc2l0aW9uKSB7XG4gICAgdmFyIGZsYWdzID0gZWRpdFR5cGVzLmxheW91dEZsYWdzKCk7XG4gICAgZmxhZ3MuYXJyYXlzID0ge307XG4gICAgZmxhZ3MucmFuZ2VzQWx0ZXJlZCA9IHt9O1xuICAgIGZsYWdzLm5DaGFuZ2VzID0gMDtcbiAgICBmbGFncy5uQ2hhbmdlc0FuaW0gPSAwO1xuXG4gICAgZnVuY3Rpb24gZ2V0TGF5b3V0VmFsT2JqZWN0KHBhcnRzKSB7XG4gICAgICAgIHJldHVybiBQbG90U2NoZW1hLmdldExheW91dFZhbE9iamVjdChuZXdGdWxsTGF5b3V0LCBwYXJ0cyk7XG4gICAgfVxuXG4gICAgdmFyIGRpZmZPcHRzID0ge1xuICAgICAgICBnZXRWYWxPYmplY3Q6IGdldExheW91dFZhbE9iamVjdCxcbiAgICAgICAgZmxhZ3M6IGZsYWdzLFxuICAgICAgICBpbW11dGFibGU6IGltbXV0YWJsZSxcbiAgICAgICAgdHJhbnNpdGlvbjogdHJhbnNpdGlvbixcbiAgICAgICAgZ2Q6IGdkXG4gICAgfTtcblxuICAgIGdldERpZmZGbGFncyhvbGRGdWxsTGF5b3V0LCBuZXdGdWxsTGF5b3V0LCBbXSwgZGlmZk9wdHMpO1xuXG4gICAgaWYoZmxhZ3MucGxvdCB8fCBmbGFncy5jYWxjKSB7XG4gICAgICAgIGZsYWdzLmxheW91dFJlcGxvdCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYodHJhbnNpdGlvbiAmJiBmbGFncy5uQ2hhbmdlcyAmJiBmbGFncy5uQ2hhbmdlc0FuaW0pIHtcbiAgICAgICAgZmxhZ3MuYW5pbSA9IGZsYWdzLm5DaGFuZ2VzID09PSBmbGFncy5uQ2hhbmdlc0FuaW0gPyAnYWxsJyA6ICdzb21lJztcbiAgICB9XG5cbiAgICByZXR1cm4gZmxhZ3M7XG59XG5cbmZ1bmN0aW9uIGdldERpZmZGbGFncyhvbGRDb250YWluZXIsIG5ld0NvbnRhaW5lciwgb3V0ZXJwYXJ0cywgb3B0cykge1xuICAgIHZhciB2YWxPYmplY3QsIGtleSwgYXN0cjtcblxuICAgIHZhciBnZXRWYWxPYmplY3QgPSBvcHRzLmdldFZhbE9iamVjdDtcbiAgICB2YXIgZmxhZ3MgPSBvcHRzLmZsYWdzO1xuICAgIHZhciBpbW11dGFibGUgPSBvcHRzLmltbXV0YWJsZTtcbiAgICB2YXIgaW5BcnJheSA9IG9wdHMuaW5BcnJheTtcbiAgICB2YXIgYXJyYXlJbmRleCA9IG9wdHMuYXJyYXlJbmRleDtcblxuICAgIGZ1bmN0aW9uIGNoYW5nZWQoKSB7XG4gICAgICAgIHZhciBlZGl0VHlwZSA9IHZhbE9iamVjdC5lZGl0VHlwZTtcbiAgICAgICAgaWYoaW5BcnJheSAmJiBlZGl0VHlwZS5pbmRleE9mKCdhcnJheWRyYXcnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIExpYi5wdXNoVW5pcXVlKGZsYWdzLmFycmF5c1tpbkFycmF5XSwgYXJyYXlJbmRleCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZWRpdFR5cGVzLnVwZGF0ZShmbGFncywgdmFsT2JqZWN0KTtcblxuICAgICAgICBpZihlZGl0VHlwZSAhPT0gJ25vbmUnKSB7XG4gICAgICAgICAgICBmbGFncy5uQ2hhbmdlcysrO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHJhY2sgYW5pbWF0YWJsZSBjaGFuZ2VzXG4gICAgICAgIGlmKG9wdHMudHJhbnNpdGlvbiAmJiB2YWxPYmplY3QuYW5pbSkge1xuICAgICAgICAgICAgZmxhZ3MubkNoYW5nZXNBbmltKys7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmFjayBjYXJ0ZXNpYW4gYXhlcyB3aXRoIGFsdGVyZWQgcmFuZ2VzXG4gICAgICAgIGlmKEFYX1JBTkdFX1JFLnRlc3QoYXN0cikgfHwgQVhfQVVUT1JBTkdFX1JFLnRlc3QoYXN0cikpIHtcbiAgICAgICAgICAgIGZsYWdzLnJhbmdlc0FsdGVyZWRbb3V0ZXJwYXJ0c1swXV0gPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2xlYXIgX2lucHV0RG9tYWluIG9uIGNhcnRlc2lhbiBheGVzIHdpdGggYWx0ZXJlZCBkb21haW5zXG4gICAgICAgIGlmKEFYX0RPTUFJTl9SRS50ZXN0KGFzdHIpKSB7XG4gICAgICAgICAgICBuZXN0ZWRQcm9wZXJ0eShuZXdDb250YWluZXIsICdfaW5wdXREb21haW4nKS5zZXQobnVsbCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmFjayBkYXRhcmV2aXNpb24gY2hhbmdlc1xuICAgICAgICBpZihrZXkgPT09ICdkYXRhcmV2aXNpb24nKSB7XG4gICAgICAgICAgICBmbGFncy5uZXdEYXRhUmV2aXNpb24gPSAxO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmFsT2JqZWN0Q2FuQmVEYXRhQXJyYXkodmFsT2JqZWN0KSB7XG4gICAgICAgIHJldHVybiB2YWxPYmplY3QudmFsVHlwZSA9PT0gJ2RhdGFfYXJyYXknIHx8IHZhbE9iamVjdC5hcnJheU9rO1xuICAgIH1cblxuICAgIGZvcihrZXkgaW4gb2xkQ29udGFpbmVyKSB7XG4gICAgICAgIC8vIHNob3J0LWNpcmN1aXQgYmFzZWQgb24gcHJldmlvdXMgY2FsbHMgb3IgcHJldmlvdXMga2V5cyB0aGF0IGFscmVhZHkgbWF4aW1pemVkIHRoZSBwYXRod2F5XG4gICAgICAgIGlmKGZsYWdzLmNhbGMgJiYgIW9wdHMudHJhbnNpdGlvbikgcmV0dXJuO1xuXG4gICAgICAgIHZhciBvbGRWYWwgPSBvbGRDb250YWluZXJba2V5XTtcbiAgICAgICAgdmFyIG5ld1ZhbCA9IG5ld0NvbnRhaW5lcltrZXldO1xuICAgICAgICB2YXIgcGFydHMgPSBvdXRlcnBhcnRzLmNvbmNhdChrZXkpO1xuICAgICAgICBhc3RyID0gcGFydHMuam9pbignLicpO1xuXG4gICAgICAgIGlmKGtleS5jaGFyQXQoMCkgPT09ICdfJyB8fCB0eXBlb2Ygb2xkVmFsID09PSAnZnVuY3Rpb24nIHx8IG9sZFZhbCA9PT0gbmV3VmFsKSBjb250aW51ZTtcblxuICAgICAgICAvLyBGSVhNRTogYXgudGljazAgYW5kIGR0aWNrIGdldCBmaWxsZWQgaW4gZHVyaW5nIHBsb3R0aW5nIChleGNlcHQgZm9yIGdlbyBzdWJwbG90cyksXG4gICAgICAgIC8vIGFuZCB1bmxpa2Ugb3RoZXIgYXV0byB2YWx1ZXMgdGhleSBkb24ndCBtYWtlIGl0IGJhY2sgaW50byB0aGUgaW5wdXQsXG4gICAgICAgIC8vIHNvIG5ld0NvbnRhaW5lciB3b24ndCBoYXZlIHRoZW0uXG4gICAgICAgIGlmKChrZXkgPT09ICd0aWNrMCcgfHwga2V5ID09PSAnZHRpY2snKSAmJiBvdXRlcnBhcnRzWzBdICE9PSAnZ2VvJykge1xuICAgICAgICAgICAgdmFyIHRpY2tNb2RlID0gbmV3Q29udGFpbmVyLnRpY2ttb2RlO1xuICAgICAgICAgICAgaWYodGlja01vZGUgPT09ICdhdXRvJyB8fCB0aWNrTW9kZSA9PT0gJ2FycmF5JyB8fCAhdGlja01vZGUpIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZJWE1FOiBTaW1pbGFybHkgZm9yIGF4aXMgcmFuZ2VzIGZvciAzRFxuICAgICAgICAvLyBjb250b3VyY2FycGV0IGRvZXNuJ3QgSEFWRSB6bWluL3ptYXgsIHRoZXkncmUganVzdCBhdXRvLWFkZGVkLiBJdCBuZWVkcyB0aGVtLlxuICAgICAgICBpZihrZXkgPT09ICdyYW5nZScgJiYgbmV3Q29udGFpbmVyLmF1dG9yYW5nZSkgY29udGludWU7XG4gICAgICAgIGlmKChrZXkgPT09ICd6bWluJyB8fCBrZXkgPT09ICd6bWF4JykgJiYgbmV3Q29udGFpbmVyLnR5cGUgPT09ICdjb250b3VyY2FycGV0JykgY29udGludWU7XG5cbiAgICAgICAgdmFsT2JqZWN0ID0gZ2V0VmFsT2JqZWN0KHBhcnRzKTtcblxuICAgICAgICAvLyBpbiBjYXNlIHR5cGUgY2hhbmdlZCwgd2UgbWF5IG5vdCBldmVuICpoYXZlKiBhIHZhbE9iamVjdC5cbiAgICAgICAgaWYoIXZhbE9iamVjdCkgY29udGludWU7XG5cbiAgICAgICAgaWYodmFsT2JqZWN0Ll9jb21wYXJlQXNKU09OICYmIEpTT04uc3RyaW5naWZ5KG9sZFZhbCkgPT09IEpTT04uc3RyaW5naWZ5KG5ld1ZhbCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciB2YWxUeXBlID0gdmFsT2JqZWN0LnZhbFR5cGU7XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIHZhciBjYW5CZURhdGFBcnJheSA9IHZhbE9iamVjdENhbkJlRGF0YUFycmF5KHZhbE9iamVjdCk7XG4gICAgICAgIHZhciB3YXNBcnJheSA9IEFycmF5LmlzQXJyYXkob2xkVmFsKTtcbiAgICAgICAgdmFyIG5vd0FycmF5ID0gQXJyYXkuaXNBcnJheShuZXdWYWwpO1xuXG4gICAgICAgIC8vIGhhY2sgZm9yIHRyYWNlcyB0aGF0IG1vZGlmeSB0aGUgZGF0YSBpbiBzdXBwbHlEZWZhdWx0cywgbGlrZVxuICAgICAgICAvLyBjb252ZXJ0aW5nIDFEIHRvIDJEIGFycmF5cywgd2hpY2ggd2lsbCBhbHdheXMgY3JlYXRlIG5ldyBvYmplY3RzXG4gICAgICAgIGlmKHdhc0FycmF5ICYmIG5vd0FycmF5KSB7XG4gICAgICAgICAgICB2YXIgaW5wdXRLZXkgPSAnX2lucHV0XycgKyBrZXk7XG4gICAgICAgICAgICB2YXIgb2xkVmFsSW4gPSBvbGRDb250YWluZXJbaW5wdXRLZXldO1xuICAgICAgICAgICAgdmFyIG5ld1ZhbEluID0gbmV3Q29udGFpbmVyW2lucHV0S2V5XTtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkob2xkVmFsSW4pICYmIG9sZFZhbEluID09PSBuZXdWYWxJbikgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZihuZXdWYWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYoY2FuQmVEYXRhQXJyYXkgJiYgd2FzQXJyYXkpIGZsYWdzLmNhbGMgPSB0cnVlO1xuICAgICAgICAgICAgZWxzZSBjaGFuZ2VkKCk7XG4gICAgICAgIH0gZWxzZSBpZih2YWxPYmplY3QuX2lzTGlua2VkVG9BcnJheSkge1xuICAgICAgICAgICAgdmFyIGFycmF5RWRpdEluZGljZXMgPSBbXTtcbiAgICAgICAgICAgIHZhciBleHRyYUluZGljZXMgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmKCFpbkFycmF5KSBmbGFncy5hcnJheXNba2V5XSA9IGFycmF5RWRpdEluZGljZXM7XG5cbiAgICAgICAgICAgIHZhciBtaW5MZW4gPSBNYXRoLm1pbihvbGRWYWwubGVuZ3RoLCBuZXdWYWwubGVuZ3RoKTtcbiAgICAgICAgICAgIHZhciBtYXhMZW4gPSBNYXRoLm1heChvbGRWYWwubGVuZ3RoLCBuZXdWYWwubGVuZ3RoKTtcbiAgICAgICAgICAgIGlmKG1pbkxlbiAhPT0gbWF4TGVuKSB7XG4gICAgICAgICAgICAgICAgaWYodmFsT2JqZWN0LmVkaXRUeXBlID09PSAnYXJyYXlkcmF3Jykge1xuICAgICAgICAgICAgICAgICAgICBleHRyYUluZGljZXMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZWQoKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBtaW5MZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGdldERpZmZGbGFncyhvbGRWYWxbaV0sIG5ld1ZhbFtpXSwgcGFydHMuY29uY2F0KGkpLFxuICAgICAgICAgICAgICAgICAgICAvLyBhZGQgYXJyYXkgaW5kaWNlcywgYnV0IG5vdCBpZiB3ZSdyZSBhbHJlYWR5IGluIGFuIGFycmF5XG4gICAgICAgICAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KHtpbkFycmF5OiBrZXksIGFycmF5SW5kZXg6IGl9LCBvcHRzKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHB1dCB0aGlzIGF0IHRoZSBlbmQgc28gdGhhdCB3ZSBrbm93IG91ciBjb2xsZWN0ZWQgYXJyYXkgaW5kaWNlcyBhcmUgc29ydGVkXG4gICAgICAgICAgICAvLyBidXQgdGhlIGNoZWNrIGZvciBsZW5ndGggY2hhbmdlcyBoYXBwZW5zIHVwIGZyb250IHNvIHdlIGNhbiBzaG9ydC1jaXJjdWl0XG4gICAgICAgICAgICAvLyBkaWZmaW5nIGlmIGFwcHJvcHJpYXRlXG4gICAgICAgICAgICBpZihleHRyYUluZGljZXMpIHtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IG1pbkxlbjsgaSA8IG1heExlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGFycmF5RWRpdEluZGljZXMucHVzaChpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZighdmFsVHlwZSAmJiBMaWIuaXNQbGFpbk9iamVjdChvbGRWYWwpKSB7XG4gICAgICAgICAgICBnZXREaWZmRmxhZ3Mob2xkVmFsLCBuZXdWYWwsIHBhcnRzLCBvcHRzKTtcbiAgICAgICAgfSBlbHNlIGlmKGNhbkJlRGF0YUFycmF5KSB7XG4gICAgICAgICAgICBpZih3YXNBcnJheSAmJiBub3dBcnJheSkge1xuICAgICAgICAgICAgICAgIC8vIGRvbid0IHRyeSB0byBkaWZmIHR3byBkYXRhIGFycmF5cy4gSWYgaW1tdXRhYmxlIHdlIGtub3cgdGhlIGRhdGEgY2hhbmdlZCxcbiAgICAgICAgICAgICAgICAvLyBpZiBub3QsIGFzc3VtZSBpdCBkaWRuJ3QgYW5kIGxldCBgbGF5b3V0LmRhdGFyZXZpc2lvbmAgdGVsbCB1cyBpZiBpdCBkaWRcbiAgICAgICAgICAgICAgICBpZihpbW11dGFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZmxhZ3MuY2FsYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gbG9vayBmb3IgYW5pbWF0YWJsZSBhdHRyaWJ1dGVzIHdoZW4gdGhlIGRhdGEgY2hhbmdlZFxuICAgICAgICAgICAgICAgIGlmKGltbXV0YWJsZSB8fCBvcHRzLm5ld0RhdGFSZXZpc2lvbikge1xuICAgICAgICAgICAgICAgICAgICBjaGFuZ2VkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmKHdhc0FycmF5ICE9PSBub3dBcnJheSkge1xuICAgICAgICAgICAgICAgIGZsYWdzLmNhbGMgPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIGNoYW5nZWQoKTtcbiAgICAgICAgfSBlbHNlIGlmKHdhc0FycmF5ICYmIG5vd0FycmF5KSB7XG4gICAgICAgICAgICAvLyBpbmZvIGFycmF5LCBjb2xvcnNjYWxlLCAnYW55JyAtIHRoZXNlIGFyZSBzaG9ydCwganVzdCBzdHJpbmdpZnkuXG4gICAgICAgICAgICAvLyBJIGRvbid0ICp0aGluayogdGhhdCBjb3ZlcnMgdXAgYW55IHJlYWwgZGlmZmVyZW5jZXMgcG9zdC12YWxpZGF0aW9uLCBkb2VzIGl0P1xuICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIHdlIG5lZWQgdG8gZGl2ZSBpbiAxIChpbmZvX2FycmF5KSBvciAyIChjb2xvcnNjYWxlKSBsZXZlbHMgYW5kIGNvbXBhcmVcbiAgICAgICAgICAgIC8vIGFsbCBlbGVtZW50cy5cbiAgICAgICAgICAgIGlmKG9sZFZhbC5sZW5ndGggIT09IG5ld1ZhbC5sZW5ndGggfHwgU3RyaW5nKG9sZFZhbCkgIT09IFN0cmluZyhuZXdWYWwpKSB7XG4gICAgICAgICAgICAgICAgY2hhbmdlZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2hhbmdlZCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGtleSBpbiBuZXdDb250YWluZXIpIHtcbiAgICAgICAgaWYoIShrZXkgaW4gb2xkQ29udGFpbmVyIHx8IGtleS5jaGFyQXQoMCkgPT09ICdfJyB8fCB0eXBlb2YgbmV3Q29udGFpbmVyW2tleV0gPT09ICdmdW5jdGlvbicpKSB7XG4gICAgICAgICAgICB2YWxPYmplY3QgPSBnZXRWYWxPYmplY3Qob3V0ZXJwYXJ0cy5jb25jYXQoa2V5KSk7XG5cbiAgICAgICAgICAgIGlmKHZhbE9iamVjdENhbkJlRGF0YUFycmF5KHZhbE9iamVjdCkgJiYgQXJyYXkuaXNBcnJheShuZXdDb250YWluZXJba2V5XSkpIHtcbiAgICAgICAgICAgICAgICBmbGFncy5jYWxjID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2UgY2hhbmdlZCgpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKlxuICogc2ltcGxlIGRpZmYgZm9yIGNvbmZpZyAtIGZvciBub3csIGp1c3QgdHJlYXQgYWxsIGNoYW5nZXMgYXMgZXF1aXZhbGVudFxuICovXG5mdW5jdGlvbiBkaWZmQ29uZmlnKG9sZENvbmZpZywgbmV3Q29uZmlnKSB7XG4gICAgdmFyIGtleTtcblxuICAgIGZvcihrZXkgaW4gb2xkQ29uZmlnKSB7XG4gICAgICAgIGlmKGtleS5jaGFyQXQoMCkgPT09ICdfJykgY29udGludWU7XG4gICAgICAgIHZhciBvbGRWYWwgPSBvbGRDb25maWdba2V5XTtcbiAgICAgICAgdmFyIG5ld1ZhbCA9IG5ld0NvbmZpZ1trZXldO1xuICAgICAgICBpZihvbGRWYWwgIT09IG5ld1ZhbCkge1xuICAgICAgICAgICAgaWYoTGliLmlzUGxhaW5PYmplY3Qob2xkVmFsKSAmJiBMaWIuaXNQbGFpbk9iamVjdChuZXdWYWwpKSB7XG4gICAgICAgICAgICAgICAgaWYoZGlmZkNvbmZpZyhvbGRWYWwsIG5ld1ZhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmKEFycmF5LmlzQXJyYXkob2xkVmFsKSAmJiBBcnJheS5pc0FycmF5KG5ld1ZhbCkpIHtcbiAgICAgICAgICAgICAgICBpZihvbGRWYWwubGVuZ3RoICE9PSBuZXdWYWwubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgb2xkVmFsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKG9sZFZhbFtpXSAhPT0gbmV3VmFsW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihMaWIuaXNQbGFpbk9iamVjdChvbGRWYWxbaV0pICYmIExpYi5pc1BsYWluT2JqZWN0KG5ld1ZhbFtpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihkaWZmQ29uZmlnKG9sZFZhbFtpXSwgbmV3VmFsW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBBbmltYXRlIHRvIGEgZnJhbWUsIHNlcXVlbmNlIG9mIGZyYW1lLCBmcmFtZSBncm91cCwgb3IgZnJhbWUgZGVmaW5pdGlvblxuICpcbiAqIEBwYXJhbSB7c3RyaW5nIGlkIG9yIERPTSBlbGVtZW50fSBnZFxuICogICAgICB0aGUgaWQgb3IgRE9NIGVsZW1lbnQgb2YgdGhlIGdyYXBoIGNvbnRhaW5lciBkaXZcbiAqXG4gKiBAcGFyYW0ge3N0cmluZyBvciBvYmplY3Qgb3IgYXJyYXkgb2Ygc3RyaW5ncyBvciBhcnJheSBvZiBvYmplY3RzfSBmcmFtZU9yR3JvdXBOYW1lT3JGcmFtZUxpc3RcbiAqICAgICAgYSBzaW5nbGUgZnJhbWUsIGFycmF5IG9mIGZyYW1lcywgb3IgZ3JvdXAgdG8gd2hpY2ggdG8gYW5pbWF0ZS4gVGhlIGludGVudCBpc1xuICogICAgICBpbmZlcnJlZCBieSB0aGUgdHlwZSBvZiB0aGUgaW5wdXQuIFZhbGlkIGlucHV0cyBhcmU6XG4gKlxuICogICAgICAtIHN0cmluZywgZS5nLiAnZ3JvdXBuYW1lJzogYW5pbWF0ZSBhbGwgZnJhbWVzIG9mIGEgZ2l2ZW4gYGdyb3VwYCBpbiB0aGUgb3JkZXJcbiAqICAgICAgICAgICAgaW4gd2hpY2ggdGhleSBhcmUgZGVmaW5lZCB2aWEgYFBsb3RseS5hZGRGcmFtZXNgLlxuICpcbiAqICAgICAgLSBhcnJheSBvZiBzdHJpbmdzLCBlLmcuIFsnZnJhbWUxJywgZnJhbWUyJ106IGEgbGlzdCBvZiBmcmFtZXMgYnkgbmFtZSB0byB3aGljaFxuICogICAgICAgICAgICB0byBhbmltYXRlIGluIHNlcXVlbmNlXG4gKlxuICogICAgICAtIG9iamVjdDoge2RhdGE6IC4uLn06IGEgZnJhbWUgZGVmaW5pdGlvbiB0byB3aGljaCB0byBhbmltYXRlLiBUaGUgZnJhbWUgaXMgbm90XG4gKiAgICAgICAgICAgIGFuZCBkb2VzIG5vdCBuZWVkIHRvIGJlIGFkZGVkIHZpYSBgUGxvdGx5LmFkZEZyYW1lc2AuIEl0IG1heSBjb250YWluIGFueSBvZlxuICogICAgICAgICAgICB0aGUgcHJvcGVydGllcyBvZiBhIGZyYW1lLCBpbmNsdWRpbmcgYGRhdGFgLCBgbGF5b3V0YCwgYW5kIGB0cmFjZXNgLiBUaGVcbiAqICAgICAgICAgICAgZnJhbWUgaXMgdXNlZCBhcyBwcm92aWRlZCBhbmQgZG9lcyBub3QgdXNlIHRoZSBgYmFzZWZyYW1lYCBwcm9wZXJ0eS5cbiAqXG4gKiAgICAgIC0gYXJyYXkgb2Ygb2JqZWN0cywgZS5nLiBbe2RhdGE6IC4uLn0sIHtkYXRhOiAuLi59XTogYSBsaXN0IG9mIGZyYW1lIG9iamVjdHMsXG4gKiAgICAgICAgICAgIGVhY2ggZm9sbG93aW5nIHRoZSBzYW1lIHJ1bGVzIGFzIGEgc2luZ2xlIGBvYmplY3RgLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBhbmltYXRpb25PcHRzXG4gKiAgICAgIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBhbmltYXRpb25cbiAqL1xuZnVuY3Rpb24gYW5pbWF0ZShnZCwgZnJhbWVPckdyb3VwTmFtZU9yRnJhbWVMaXN0LCBhbmltYXRpb25PcHRzKSB7XG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuXG4gICAgaWYoIUxpYi5pc1Bsb3REaXYoZ2QpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICdUaGlzIGVsZW1lbnQgaXMgbm90IGEgUGxvdGx5IHBsb3Q6ICcgKyBnZCArICcuIEl0XFwncyBsaWtlbHkgdGhhdCB5b3VcXCd2ZSBmYWlsZWQgJyArXG4gICAgICAgICAgICAndG8gY3JlYXRlIGEgcGxvdCBiZWZvcmUgYW5pbWF0aW5nIGl0LiBGb3IgbW9yZSBkZXRhaWxzLCBzZWUgJyArXG4gICAgICAgICAgICAnaHR0cHM6Ly9wbG90Lmx5L2phdmFzY3JpcHQvYW5pbWF0aW9ucy8nXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgdmFyIHRyYW5zID0gZ2QuX3RyYW5zaXRpb25EYXRhO1xuXG4gICAgLy8gVGhpcyBpcyB0aGUgcXVldWUgb2YgZnJhbWVzIHRoYXQgd2lsbCBiZSBhbmltYXRlZCBhcyBzb29uIGFzIHBvc3NpYmxlLiBUaGV5XG4gICAgLy8gYXJlIHBvcHBlZCBpbW1lZGlhdGVseSB1cG9uIHRoZSAqc3RhcnQqIG9mIGEgdHJhbnNpdGlvbjpcbiAgICBpZighdHJhbnMuX2ZyYW1lUXVldWUpIHtcbiAgICAgICAgdHJhbnMuX2ZyYW1lUXVldWUgPSBbXTtcbiAgICB9XG5cbiAgICBhbmltYXRpb25PcHRzID0gUGxvdHMuc3VwcGx5QW5pbWF0aW9uRGVmYXVsdHMoYW5pbWF0aW9uT3B0cyk7XG4gICAgdmFyIHRyYW5zaXRpb25PcHRzID0gYW5pbWF0aW9uT3B0cy50cmFuc2l0aW9uO1xuICAgIHZhciBmcmFtZU9wdHMgPSBhbmltYXRpb25PcHRzLmZyYW1lO1xuXG4gICAgLy8gU2luY2UgZnJhbWVzIGFyZSBwb3BwZWQgaW1tZWRpYXRlbHksIGFuIGVtcHR5IHF1ZXVlIG9ubHkgbWVhbnMgYWxsIGZyYW1lcyBoYXZlXG4gICAgLy8gKnN0YXJ0ZWQqIHRvIHRyYW5zaXRpb24sIG5vdCB0aGF0IHRoZSBhbmltYXRpb24gaXMgY29tcGxldGUuIFRvIHNvbHZlIHRoYXQsXG4gICAgLy8gdHJhY2sgYSBzZXBhcmF0ZSBjb3VudGVyIHRoYXQgaW5jcmVtZW50cyBhdCB0aGUgc2FtZSB0aW1lIGFzIGZyYW1lcyBhcmUgYWRkZWRcbiAgICAvLyB0byB0aGUgcXVldWUsIGJ1dCBkZWNyZW1lbnRzIG9ubHkgd2hlbiB0aGUgdHJhbnNpdGlvbiBpcyBjb21wbGV0ZS5cbiAgICBpZih0cmFucy5fZnJhbWVXYWl0aW5nQ250ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdHJhbnMuX2ZyYW1lV2FpdGluZ0NudCA9IDA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0VHJhbnNpdGlvbk9wdHMoaSkge1xuICAgICAgICBpZihBcnJheS5pc0FycmF5KHRyYW5zaXRpb25PcHRzKSkge1xuICAgICAgICAgICAgaWYoaSA+PSB0cmFuc2l0aW9uT3B0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhbnNpdGlvbk9wdHNbMF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFuc2l0aW9uT3B0c1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2l0aW9uT3B0cztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEZyYW1lT3B0cyhpKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoZnJhbWVPcHRzKSkge1xuICAgICAgICAgICAgaWYoaSA+PSBmcmFtZU9wdHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZyYW1lT3B0c1swXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZyYW1lT3B0c1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmcmFtZU9wdHM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBFeGVjdXRlIGEgY2FsbGJhY2sgYWZ0ZXIgdGhlIHdyYXBwZXIgZnVuY3Rpb24gaGFzIGJlZW4gY2FsbGVkIG4gdGltZXMuXG4gICAgLy8gVGhpcyBpcyB1c2VkIHRvIGRlZmVyIHRoZSByZXNvbHV0aW9uIHVudGlsIGEgdHJhbnNpdGlvbiBoYXMgcmVzb3ZsZWQgKmFuZCpcbiAgICAvLyB0aGUgZnJhbWUgaGFzIGNvbXBsZXRlZC4gSWYgaXQncyBub3QgZG9uZSB0aGlzIHdheSwgdGhlbiB3ZSBnZXQgYSByYWNlXG4gICAgLy8gY29uZGl0aW9uIGluIHdoaWNoIHRoZSBhbmltYXRpb24gbWlnaHQgcmVzb2x2ZSBiZWZvcmUgYSB0cmFuc2l0aW9uIGlzIGNvbXBsZXRlXG4gICAgLy8gb3IgdmljZSB2ZXJzYS5cbiAgICBmdW5jdGlvbiBjYWxsYmFja09uTnRoVGltZShjYiwgbikge1xuICAgICAgICB2YXIgY250ID0gMDtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYoY2IgJiYgKytjbnQgPT09IG4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGRpc2NhcmRFeGlzdGluZ0ZyYW1lcygpIHtcbiAgICAgICAgICAgIGlmKHRyYW5zLl9mcmFtZVF1ZXVlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgd2hpbGUodHJhbnMuX2ZyYW1lUXVldWUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5leHQgPSB0cmFucy5fZnJhbWVRdWV1ZS5wb3AoKTtcbiAgICAgICAgICAgICAgICBpZihuZXh0Lm9uSW50ZXJydXB0KSB7XG4gICAgICAgICAgICAgICAgICAgIG5leHQub25JbnRlcnJ1cHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9hbmltYXRpb25pbnRlcnJ1cHRlZCcsIFtdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHF1ZXVlRnJhbWVzKGZyYW1lTGlzdCkge1xuICAgICAgICAgICAgaWYoZnJhbWVMaXN0Lmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnJhbWVMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbXB1dGVkRnJhbWU7XG5cbiAgICAgICAgICAgICAgICBpZihmcmFtZUxpc3RbaV0udHlwZSA9PT0gJ2J5bmFtZScpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgaXQncyBhIG5hbWVkIGZyYW1lLCBjb21wdXRlIGl0OlxuICAgICAgICAgICAgICAgICAgICBjb21wdXRlZEZyYW1lID0gUGxvdHMuY29tcHV0ZUZyYW1lKGdkLCBmcmFtZUxpc3RbaV0ubmFtZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHdlIG11c3QgaGF2ZSBiZWVuIGdpdmVuIGEgc2ltcGxlIG9iamVjdCwgc28gdHJlYXRcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGlucHV0IGl0c2VsZiBhcyB0aGUgY29tcHV0ZWQgZnJhbWUuXG4gICAgICAgICAgICAgICAgICAgIGNvbXB1dGVkRnJhbWUgPSBmcmFtZUxpc3RbaV0uZGF0YTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJhbWVPcHRzID0gZ2V0RnJhbWVPcHRzKGkpO1xuICAgICAgICAgICAgICAgIHZhciB0cmFuc2l0aW9uT3B0cyA9IGdldFRyYW5zaXRpb25PcHRzKGkpO1xuXG4gICAgICAgICAgICAgICAgLy8gSXQgZG9lc24ndCBtYWtlIG11Y2ggc2Vuc2UgZm9yIHRoZSB0cmFuc2l0aW9uIGR1cmF0aW9uIHRvIGJlIGdyZWF0ZXIgdGhhblxuICAgICAgICAgICAgICAgIC8vIHRoZSBmcmFtZSBkdXJhdGlvbiwgc28gbGltaXQgaXQ6XG4gICAgICAgICAgICAgICAgdHJhbnNpdGlvbk9wdHMuZHVyYXRpb24gPSBNYXRoLm1pbih0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbiwgZnJhbWVPcHRzLmR1cmF0aW9uKTtcblxuICAgICAgICAgICAgICAgIHZhciBuZXh0RnJhbWUgPSB7XG4gICAgICAgICAgICAgICAgICAgIGZyYW1lOiBjb21wdXRlZEZyYW1lLFxuICAgICAgICAgICAgICAgICAgICBuYW1lOiBmcmFtZUxpc3RbaV0ubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVPcHRzOiBmcmFtZU9wdHMsXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb25PcHRzOiB0cmFuc2l0aW9uT3B0cyxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGlmKGkgPT09IGZyYW1lTGlzdC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBsYXN0IGZyYW1lIGluIHRoaXMgLmFuaW1hdGUgY2FsbCBzdG9yZXMgdGhlIHByb21pc2UgcmVzb2x2ZVxuICAgICAgICAgICAgICAgICAgICAvLyBhbmQgcmVqZWN0IGNhbGxiYWNrcy4gVGhpcyBpcyBob3cgd2UgZW5zdXJlIHRoYXQgdGhlIGFuaW1hdGlvblxuICAgICAgICAgICAgICAgICAgICAvLyBsb29wICh3aGljaCBtYXkgZXhpc3QgYXMgYSByZXN1bHQgb2YgYSAqZGlmZmVyZW50KiAuYW5pbWF0ZSBjYWxsKVxuICAgICAgICAgICAgICAgICAgICAvLyBzdGlsbCByZXNvbHZlcyBvciByZWplY2R0cyB0aGlzIC5hbmltYXRlIGNhbGwncyBwcm9taXNlLiBvbmNlIGl0J3NcbiAgICAgICAgICAgICAgICAgICAgLy8gY29tcGxldGUuXG4gICAgICAgICAgICAgICAgICAgIG5leHRGcmFtZS5vbkNvbXBsZXRlID0gY2FsbGJhY2tPbk50aFRpbWUocmVzb2x2ZSwgMik7XG4gICAgICAgICAgICAgICAgICAgIG5leHRGcmFtZS5vbkludGVycnVwdCA9IHJlamVjdDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFucy5fZnJhbWVRdWV1ZS5wdXNoKG5leHRGcmFtZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNldCBpdCBhcyBuZXZlciBoYXZpbmcgdHJhbnNpdGlvbmVkIHRvIGEgZnJhbWUuIFRoaXMgd2lsbCBjYXVzZSB0aGUgYW5pbWF0aW9uXG4gICAgICAgICAgICAvLyBsb29wIHRvIGltbWVkaWF0ZWx5IHRyYW5zaXRpb24gdG8gdGhlIG5leHQgZnJhbWUgKHdoaWNoLCBmb3IgaW1tZWRpYXRlIG1vZGUsXG4gICAgICAgICAgICAvLyBpcyB0aGUgZmlyc3QgZnJhbWUgaW4gdGhlIGxpc3Qgc2luY2UgYWxsIG90aGVycyB3b3VsZCBoYXZlIGJlZW4gZGlzY2FyZGVkXG4gICAgICAgICAgICAvLyBiZWxvdylcbiAgICAgICAgICAgIGlmKGFuaW1hdGlvbk9wdHMubW9kZSA9PT0gJ2ltbWVkaWF0ZScpIHtcbiAgICAgICAgICAgICAgICB0cmFucy5fbGFzdEZyYW1lQXQgPSAtSW5maW5pdHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE9ubHkgaXQncyBub3QgYWxyZWFkeSBydW5uaW5nLCBzdGFydCBhIFJBRiBsb29wLiBUaGlzIGNvdWxkIGJlIGF2b2lkZWQgaW4gdGhlXG4gICAgICAgICAgICAvLyBjYXNlIHRoYXQgdGhlcmUncyBvbmx5IG9uZSBmcmFtZSwgYnV0IGl0IHNpZ25pZmljYW50bHkgY29tcGxpY2F0ZWQgdGhlIGxvZ2ljXG4gICAgICAgICAgICAvLyBhbmQgb25seSBzcGVkIHRoaW5ncyB1cCBieSBhYm91dCA1JSBvciBzbyBmb3IgYSBsb3JlbnogYXR0cmFjdG9yIHNpbXVsYXRpb24uXG4gICAgICAgICAgICAvLyBJdCB3b3VsZCBiZSBhIGZpbmUgdGhpbmcgdG8gaW1wbGVtZW50LCBidXQgdGhlIGJlbmVmaXQgb2YgdGhhdCBvcHRpbWl6YXRpb25cbiAgICAgICAgICAgIC8vIGRvZXNuJ3Qgc2VlbSB3b3J0aCB0aGUgZXh0cmEgY29tcGxleGl0eS5cbiAgICAgICAgICAgIGlmKCF0cmFucy5fYW5pbWF0aW9uUmFmKSB7XG4gICAgICAgICAgICAgICAgYmVnaW5BbmltYXRpb25Mb29wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzdG9wQW5pbWF0aW9uTG9vcCgpIHtcbiAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9hbmltYXRlZCcpO1xuXG4gICAgICAgICAgICAvLyBCZSBzdXJlIHRvIHVuc2V0IGFsc28gc2luY2UgaXQncyBob3cgd2Uga25vdyB3aGV0aGVyIGEgbG9vcCBpcyBhbHJlYWR5IHJ1bm5pbmc6XG4gICAgICAgICAgICB3aW5kb3cuY2FuY2VsQW5pbWF0aW9uRnJhbWUodHJhbnMuX2FuaW1hdGlvblJhZik7XG4gICAgICAgICAgICB0cmFucy5fYW5pbWF0aW9uUmFmID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIG5leHRGcmFtZSgpIHtcbiAgICAgICAgICAgIGlmKHRyYW5zLl9jdXJyZW50RnJhbWUgJiYgdHJhbnMuX2N1cnJlbnRGcmFtZS5vbkNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgLy8gRXhlY3V0ZSB0aGUgY2FsbGJhY2sgYW5kIHVuc2V0IGl0IHRvIGVuc3VyZSBpdCBkb2Vzbid0XG4gICAgICAgICAgICAgICAgLy8gYWNjaWRlbnRhbGx5IGdldCBjYWxsZWQgdHdpY2VcbiAgICAgICAgICAgICAgICB0cmFucy5fY3VycmVudEZyYW1lLm9uQ29tcGxldGUoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIG5ld0ZyYW1lID0gdHJhbnMuX2N1cnJlbnRGcmFtZSA9IHRyYW5zLl9mcmFtZVF1ZXVlLnNoaWZ0KCk7XG5cbiAgICAgICAgICAgIGlmKG5ld0ZyYW1lKSB7XG4gICAgICAgICAgICAgICAgLy8gU2luY2UgaXQncyBzb21ldGltZXMgbmVjZXNzYXJ5IHRvIGRvIGRlZXAgZGlnZ2luZyBpbnRvIGZyYW1lIGRhdGEsXG4gICAgICAgICAgICAgICAgLy8gd2UnbGwgY29uc2lkZXIgaXQgbm90IDEwMCUgaW1wb3NzaWJsZSBmb3IgbnVsbHMgb3IgbnVtYmVycyB0byBzbmVhayB0aHJvdWdoLFxuICAgICAgICAgICAgICAgIC8vIHNvIGNoZWNrIHdoZW4gY2FzdGluZyB0aGUgbmFtZSwganVzdCB0byBiZSBhYnNvbHV0ZWx5IGNlcnRhaW46XG4gICAgICAgICAgICAgICAgdmFyIHN0cmluZ05hbWUgPSBuZXdGcmFtZS5uYW1lID8gbmV3RnJhbWUubmFtZS50b1N0cmluZygpIDogbnVsbDtcbiAgICAgICAgICAgICAgICBnZC5fZnVsbExheW91dC5fY3VycmVudEZyYW1lID0gc3RyaW5nTmFtZTtcblxuICAgICAgICAgICAgICAgIHRyYW5zLl9sYXN0RnJhbWVBdCA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgdHJhbnMuX3RpbWVUb05leHQgPSBuZXdGcmFtZS5mcmFtZU9wdHMuZHVyYXRpb247XG5cbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIHNpbXBseSBjYWxsZWQgYW5kIGl0J3MgbGVmdCB0byAudHJhbnNpdGlvbiB0byBkZWNpZGUgaG93IHRvIG1hbmFnZVxuICAgICAgICAgICAgICAgIC8vIGludGVycnVwdGluZyBjdXJyZW50IHRyYW5zaXRpb25zLiBUaGF0IG1lYW5zIHdlIGRvbid0IG5lZWQgdG8gd29ycnkgYWJvdXRcbiAgICAgICAgICAgICAgICAvLyBob3cgaXQgcmVzb2x2ZXMgb3Igd2hhdCBoYXBwZW5zIGFmdGVyIHRoaXM6XG4gICAgICAgICAgICAgICAgUGxvdHMudHJhbnNpdGlvbihnZCxcbiAgICAgICAgICAgICAgICAgICAgbmV3RnJhbWUuZnJhbWUuZGF0YSxcbiAgICAgICAgICAgICAgICAgICAgbmV3RnJhbWUuZnJhbWUubGF5b3V0LFxuICAgICAgICAgICAgICAgICAgICBoZWxwZXJzLmNvZXJjZVRyYWNlSW5kaWNlcyhnZCwgbmV3RnJhbWUuZnJhbWUudHJhY2VzKSxcbiAgICAgICAgICAgICAgICAgICAgbmV3RnJhbWUuZnJhbWVPcHRzLFxuICAgICAgICAgICAgICAgICAgICBuZXdGcmFtZS50cmFuc2l0aW9uT3B0c1xuICAgICAgICAgICAgICAgICkudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYobmV3RnJhbWUub25Db21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3RnJhbWUub25Db21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfYW5pbWF0aW5nZnJhbWUnLCB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IHN0cmluZ05hbWUsXG4gICAgICAgICAgICAgICAgICAgIGZyYW1lOiBuZXdGcmFtZS5mcmFtZSxcbiAgICAgICAgICAgICAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmFtZTogbmV3RnJhbWUuZnJhbWVPcHRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbjogbmV3RnJhbWUudHJhbnNpdGlvbk9wdHMsXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIG5vIG1vcmUgZnJhbWVzLCB0aGVuIHN0b3AgdGhlIFJBRiBsb29wOlxuICAgICAgICAgICAgICAgIHN0b3BBbmltYXRpb25Mb29wKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBiZWdpbkFuaW1hdGlvbkxvb3AoKSB7XG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfYW5pbWF0aW5nJyk7XG5cbiAgICAgICAgICAgIC8vIElmIG5vIHRpbWVyIGlzIHJ1bm5pbmcsIHRoZW4gc2V0IGxhc3QgZnJhbWUgPSBsb25nIGFnbyBzbyB0aGF0IHRoZSBuZXh0XG4gICAgICAgICAgICAvLyBmcmFtZSBpcyBpbW1lZGlhdGVseSB0cmFuc2l0aW9uZWQ6XG4gICAgICAgICAgICB0cmFucy5fbGFzdEZyYW1lQXQgPSAtSW5maW5pdHk7XG4gICAgICAgICAgICB0cmFucy5fdGltZVRvTmV4dCA9IDA7XG4gICAgICAgICAgICB0cmFucy5fcnVubmluZ1RyYW5zaXRpb25zID0gMDtcbiAgICAgICAgICAgIHRyYW5zLl9jdXJyZW50RnJhbWUgPSBudWxsO1xuXG4gICAgICAgICAgICB2YXIgZG9GcmFtZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgKm11c3QqIGJlIHJlcXVlc3RlZCBiZWZvcmUgbmV4dEZyYW1lIHNpbmNlIG5leHRGcmFtZSBtYXkgZGVjaWRlXG4gICAgICAgICAgICAgICAgLy8gdG8gY2FuY2VsIGl0IGlmIHRoZXJlJ3Mgbm90aGluZyBtb3JlIHRvIGFuaW1hdGVkOlxuICAgICAgICAgICAgICAgIHRyYW5zLl9hbmltYXRpb25SYWYgPSB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGRvRnJhbWUpO1xuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2UncmUgcmVhZHkgZm9yIGEgbmV3IGZyYW1lOlxuICAgICAgICAgICAgICAgIGlmKERhdGUubm93KCkgLSB0cmFucy5fbGFzdEZyYW1lQXQgPiB0cmFucy5fdGltZVRvTmV4dCkge1xuICAgICAgICAgICAgICAgICAgICBuZXh0RnJhbWUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBkb0ZyYW1lKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGlzIGlzIGFuIGFuaW1hdGUtbG9jYWwgY291bnRlciB0aGF0IGhlbHBzIG1hdGNoIHVwIG9wdGlvbiBpbnB1dCBsaXN0XG4gICAgICAgIC8vIGl0ZW1zIHdpdGggdGhlIHBhcnRpY3VsYXIgZnJhbWUuXG4gICAgICAgIHZhciBjb25maWdDb3VudGVyID0gMDtcbiAgICAgICAgZnVuY3Rpb24gc2V0VHJhbnNpdGlvbkNvbmZpZyhmcmFtZSkge1xuICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh0cmFuc2l0aW9uT3B0cykpIHtcbiAgICAgICAgICAgICAgICBpZihjb25maWdDb3VudGVyID49IHRyYW5zaXRpb25PcHRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBmcmFtZS50cmFuc2l0aW9uT3B0cyA9IHRyYW5zaXRpb25PcHRzW2NvbmZpZ0NvdW50ZXJdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZyYW1lLnRyYW5zaXRpb25PcHRzID0gdHJhbnNpdGlvbk9wdHNbMF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmcmFtZS50cmFuc2l0aW9uT3B0cyA9IHRyYW5zaXRpb25PcHRzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uZmlnQ291bnRlcisrO1xuICAgICAgICAgICAgcmV0dXJuIGZyYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGlzYW1iaWd1YXRlIHdoYXQncyBzb3J0IG9mIGZyYW1lcyBoYXZlIGJlZW4gcmVjZWl2ZWRcbiAgICAgICAgdmFyIGksIGZyYW1lO1xuICAgICAgICB2YXIgZnJhbWVMaXN0ID0gW107XG4gICAgICAgIHZhciBhbGxGcmFtZXMgPSBmcmFtZU9yR3JvdXBOYW1lT3JGcmFtZUxpc3QgPT09IHVuZGVmaW5lZCB8fCBmcmFtZU9yR3JvdXBOYW1lT3JGcmFtZUxpc3QgPT09IG51bGw7XG4gICAgICAgIHZhciBpc0ZyYW1lQXJyYXkgPSBBcnJheS5pc0FycmF5KGZyYW1lT3JHcm91cE5hbWVPckZyYW1lTGlzdCk7XG4gICAgICAgIHZhciBpc1NpbmdsZUZyYW1lID0gIWFsbEZyYW1lcyAmJiAhaXNGcmFtZUFycmF5ICYmIExpYi5pc1BsYWluT2JqZWN0KGZyYW1lT3JHcm91cE5hbWVPckZyYW1lTGlzdCk7XG5cbiAgICAgICAgaWYoaXNTaW5nbGVGcmFtZSkge1xuICAgICAgICAgICAgLy8gSW4gdGhpcyBjYXNlLCBhIHNpbXBsZSBvYmplY3QgaGFzIGJlZW4gcGFzc2VkIHRvIGFuaW1hdGUuXG4gICAgICAgICAgICBmcmFtZUxpc3QucHVzaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgICAgZGF0YTogc2V0VHJhbnNpdGlvbkNvbmZpZyhMaWIuZXh0ZW5kRmxhdCh7fSwgZnJhbWVPckdyb3VwTmFtZU9yRnJhbWVMaXN0KSlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYoYWxsRnJhbWVzIHx8IFsnc3RyaW5nJywgJ251bWJlciddLmluZGV4T2YodHlwZW9mIGZyYW1lT3JHcm91cE5hbWVPckZyYW1lTGlzdCkgIT09IC0xKSB7XG4gICAgICAgICAgICAvLyBJbiB0aGlzIGNhc2UsIG51bGwgb3IgdW5kZWZpbmVkIGhhcyBiZWVuIHBhc3NlZCBzbyB0aGF0IHdlIHdhbnQgdG9cbiAgICAgICAgICAgIC8vIGFuaW1hdGUgKmFsbCogY3VycmVudGx5IGRlZmluZWQgZnJhbWVzXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCB0cmFucy5fZnJhbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZnJhbWUgPSB0cmFucy5fZnJhbWVzW2ldO1xuXG4gICAgICAgICAgICAgICAgaWYoIWZyYW1lKSBjb250aW51ZTtcblxuICAgICAgICAgICAgICAgIGlmKGFsbEZyYW1lcyB8fCBTdHJpbmcoZnJhbWUuZ3JvdXApID09PSBTdHJpbmcoZnJhbWVPckdyb3VwTmFtZU9yRnJhbWVMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmcmFtZUxpc3QucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnYnluYW1lJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IFN0cmluZyhmcmFtZS5uYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IHNldFRyYW5zaXRpb25Db25maWcoe25hbWU6IGZyYW1lLm5hbWV9KVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihpc0ZyYW1lQXJyYXkpIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGZyYW1lT3JHcm91cE5hbWVPckZyYW1lTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBmcmFtZU9yTmFtZSA9IGZyYW1lT3JHcm91cE5hbWVPckZyYW1lTGlzdFtpXTtcbiAgICAgICAgICAgICAgICBpZihbJ251bWJlcicsICdzdHJpbmcnXS5pbmRleE9mKHR5cGVvZiBmcmFtZU9yTmFtZSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyYW1lT3JOYW1lID0gU3RyaW5nKGZyYW1lT3JOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gSW4gdGhpcyBjYXNlLCB0aGVyZSdzIGFuIGFycmF5IGFuZCB0aGlzIGZyYW1lIGlzIGEgc3RyaW5nIG5hbWU6XG4gICAgICAgICAgICAgICAgICAgIGZyYW1lTGlzdC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdieW5hbWUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogZnJhbWVPck5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiBzZXRUcmFuc2l0aW9uQ29uZmlnKHtuYW1lOiBmcmFtZU9yTmFtZX0pXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihMaWIuaXNQbGFpbk9iamVjdChmcmFtZU9yTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVMaXN0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhOiBzZXRUcmFuc2l0aW9uQ29uZmlnKExpYi5leHRlbmRGbGF0KHt9LCBmcmFtZU9yTmFtZSkpXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFZlcmlmeSB0aGF0IGFsbCBvZiB0aGVzZSBmcmFtZXMgYWN0dWFsbHkgZXhpc3Q7IHJldHVybiBhbmQgcmVqZWN0IGlmIG5vdDpcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgZnJhbWVMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmcmFtZSA9IGZyYW1lTGlzdFtpXTtcbiAgICAgICAgICAgIGlmKGZyYW1lLnR5cGUgPT09ICdieW5hbWUnICYmICF0cmFucy5fZnJhbWVIYXNoW2ZyYW1lLmRhdGEubmFtZV0pIHtcbiAgICAgICAgICAgICAgICBMaWIud2FybignYW5pbWF0ZSBmYWlsdXJlOiBmcmFtZSBub3QgZm91bmQ6IFwiJyArIGZyYW1lLmRhdGEubmFtZSArICdcIicpO1xuICAgICAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHRoZSBtb2RlIGlzIGVpdGhlciBuZXh0IG9yIGltbWVkaWF0ZSwgdGhlbiBhbGwgY3VycmVudGx5IHF1ZXVlZCBmcmFtZXMgbXVzdFxuICAgICAgICAvLyBiZSBkdW1wZWQgYW5kIHRoZSBjb3JyZXNwb25kaW5nIC5hbmltYXRlIHByb21pc2VzIHJlamVjdGVkLlxuICAgICAgICBpZihbJ25leHQnLCAnaW1tZWRpYXRlJ10uaW5kZXhPZihhbmltYXRpb25PcHRzLm1vZGUpICE9PSAtMSkge1xuICAgICAgICAgICAgZGlzY2FyZEV4aXN0aW5nRnJhbWVzKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihhbmltYXRpb25PcHRzLmRpcmVjdGlvbiA9PT0gJ3JldmVyc2UnKSB7XG4gICAgICAgICAgICBmcmFtZUxpc3QucmV2ZXJzZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGN1cnJlbnRGcmFtZSA9IGdkLl9mdWxsTGF5b3V0Ll9jdXJyZW50RnJhbWU7XG4gICAgICAgIGlmKGN1cnJlbnRGcmFtZSAmJiBhbmltYXRpb25PcHRzLmZyb21jdXJyZW50KSB7XG4gICAgICAgICAgICB2YXIgaWR4ID0gLTE7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBmcmFtZUxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmcmFtZSA9IGZyYW1lTGlzdFtpXTtcbiAgICAgICAgICAgICAgICBpZihmcmFtZS50eXBlID09PSAnYnluYW1lJyAmJiBmcmFtZS5uYW1lID09PSBjdXJyZW50RnJhbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWR4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihpZHggPiAwICYmIGlkeCA8IGZyYW1lTGlzdC5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZpbHRlcmVkRnJhbWVMaXN0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgZnJhbWVMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyYW1lID0gZnJhbWVMaXN0W2ldO1xuICAgICAgICAgICAgICAgICAgICBpZihmcmFtZUxpc3RbaV0udHlwZSAhPT0gJ2J5bmFtZScgfHwgaSA+IGlkeCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyZWRGcmFtZUxpc3QucHVzaChmcmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnJhbWVMaXN0ID0gZmlsdGVyZWRGcmFtZUxpc3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihmcmFtZUxpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcXVldWVGcmFtZXMoZnJhbWVMaXN0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGNhc2Ugd2hlcmUgdGhlcmUgd2VyZSBzaW1wbHkgbm8gZnJhbWVzLiBJdCdzIGEgbGl0dGxlIHN0cmFuZ2VcbiAgICAgICAgICAgIC8vIHNpbmNlIHRoZXJlJ3Mgbm90IG11Y2ggdG8gZG86XG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfYW5pbWF0ZWQnKTtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIG5ldyBmcmFtZXNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZyBpZCBvciBET00gZWxlbWVudH0gZ2RcbiAqICAgICAgdGhlIGlkIG9yIERPTSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKlxuICogQHBhcmFtIHthcnJheSBvZiBvYmplY3RzfSBmcmFtZUxpc3RcbiAqICAgICAgbGlzdCBvZiBmcmFtZSBkZWZpbml0aW9ucywgaW4gd2hpY2ggZWFjaCBvYmplY3QgaW5jbHVkZXMgYW55IG9mOlxuICogICAgICAtIG5hbWU6IHtzdHJpbmd9IG5hbWUgb2YgZnJhbWUgdG8gYWRkXG4gKiAgICAgIC0gZGF0YToge2FycmF5IG9mIG9iamVjdHN9IHRyYWNlIGRhdGFcbiAqICAgICAgLSBsYXlvdXQge29iamVjdH0gbGF5b3V0IGRlZmluaXRpb25cbiAqICAgICAgLSB0cmFjZXMge2FycmF5fSB0cmFjZSBpbmRpY2VzXG4gKiAgICAgIC0gYmFzZWZyYW1lIHtzdHJpbmd9IG5hbWUgb2YgZnJhbWUgZnJvbSB3aGljaCB0aGlzIGZyYW1lIGdldHMgZGVmYXVsdHNcbiAqXG4gKiAgQHBhcmFtIHthcnJheSBvZiBpbnRlZ2Vyc30gaW5kaWNlc1xuICogICAgICBhbiBhcnJheSBvZiBpbnRlZ2VyIGluZGljZXMgbWF0Y2hpbmcgdGhlIHJlc3BlY3RpdmUgZnJhbWVzIGluIGBmcmFtZUxpc3RgLiBJZiBub3RcbiAqICAgICAgcHJvdmlkZWQsIGFuIGluZGV4IHdpbGwgYmUgcHJvdmlkZWQgaW4gc2VyaWFsIG9yZGVyLiBJZiBhbHJlYWR5IHVzZWQsIHRoZSBmcmFtZVxuICogICAgICB3aWxsIGJlIG92ZXJ3cml0dGVuLlxuICovXG5mdW5jdGlvbiBhZGRGcmFtZXMoZ2QsIGZyYW1lTGlzdCwgaW5kaWNlcykge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIGlmKGZyYW1lTGlzdCA9PT0gbnVsbCB8fCBmcmFtZUxpc3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgaWYoIUxpYi5pc1Bsb3REaXYoZ2QpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICdUaGlzIGVsZW1lbnQgaXMgbm90IGEgUGxvdGx5IHBsb3Q6ICcgKyBnZCArICcuIEl0XFwncyBsaWtlbHkgdGhhdCB5b3VcXCd2ZSBmYWlsZWQgJyArXG4gICAgICAgICAgICAndG8gY3JlYXRlIGEgcGxvdCBiZWZvcmUgYWRkaW5nIGZyYW1lcy4gRm9yIG1vcmUgZGV0YWlscywgc2VlICcgK1xuICAgICAgICAgICAgJ2h0dHBzOi8vcGxvdC5seS9qYXZhc2NyaXB0L2FuaW1hdGlvbnMvJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIHZhciBpLCBmcmFtZSwgaiwgaWR4O1xuICAgIHZhciBfZnJhbWVzID0gZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZXM7XG4gICAgdmFyIF9mcmFtZUhhc2ggPSBnZC5fdHJhbnNpdGlvbkRhdGEuX2ZyYW1lSGFzaDtcblxuXG4gICAgaWYoIUFycmF5LmlzQXJyYXkoZnJhbWVMaXN0KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FkZEZyYW1lcyBmYWlsdXJlOiBmcmFtZUxpc3QgbXVzdCBiZSBhbiBBcnJheSBvZiBmcmFtZSBkZWZpbml0aW9ucycgKyBmcmFtZUxpc3QpO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBhIHNvcnRlZCBsaXN0IG9mIGluc2VydGlvbnMgc2luY2Ugd2UgcnVuIGludG8gbG90cyBvZiBwcm9ibGVtcyBpZiB0aGVzZVxuICAgIC8vIGFyZW4ndCBpbiBhc2NlbmRpbmcgb3JkZXIgb2YgaW5kZXg6XG4gICAgLy9cbiAgICAvLyBTdHJpY3RseSBmb3Igc29ydGluZy4gTWFrZSBzdXJlIHRoaXMgaXMgZ3VhcmFudGVlZCB0byBuZXZlciBjb2xsaWRlIHdpdGggYW55XG4gICAgLy8gYWxyZWFkeS1leGlzaXN0aW5nIGluZGljZXM6XG4gICAgdmFyIGJpZ0luZGV4ID0gX2ZyYW1lcy5sZW5ndGggKyBmcmFtZUxpc3QubGVuZ3RoICogMjtcblxuICAgIHZhciBpbnNlcnRpb25zID0gW107XG4gICAgdmFyIF9mcmFtZUhhc2hMb2NhbCA9IHt9O1xuICAgIGZvcihpID0gZnJhbWVMaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChmcmFtZUxpc3RbaV0pKSBjb250aW51ZTtcblxuICAgICAgICAvLyBUaGUgZW50aXJlIGxvZ2ljIGZvciBjaGVja2luZyBmb3IgdGhpcyB0eXBlIG9mIG5hbWUgY29sbGlzaW9uIGNhbiBiZSByZW1vdmVkIG9uY2Ugd2UgbWlncmF0ZSB0byBFUzYgYW5kXG4gICAgICAgIC8vIHVzZSBhIE1hcCBpbnN0ZWFkIG9mIGFuIE9iamVjdCBpbnN0YW5jZSwgYXMgTWFwIGtleXMgYXJlbid0IGNvbnZlcnRlZCB0byBzdHJpbmdzLlxuICAgICAgICB2YXIgbG9va3VwTmFtZSA9IGZyYW1lTGlzdFtpXS5uYW1lO1xuICAgICAgICB2YXIgbmFtZSA9IChfZnJhbWVIYXNoW2xvb2t1cE5hbWVdIHx8IF9mcmFtZUhhc2hMb2NhbFtsb29rdXBOYW1lXSB8fCB7fSkubmFtZTtcbiAgICAgICAgdmFyIG5ld05hbWUgPSBmcmFtZUxpc3RbaV0ubmFtZTtcbiAgICAgICAgdmFyIGNvbGxpc2lvblByZXNlbnQgPSBfZnJhbWVIYXNoW25hbWVdIHx8IF9mcmFtZUhhc2hMb2NhbFtuYW1lXTtcblxuICAgICAgICBpZihuYW1lICYmIG5ld05hbWUgJiYgdHlwZW9mIG5ld05hbWUgPT09ICdudW1iZXInICYmIGNvbGxpc2lvblByZXNlbnQgJiYgbnVtZXJpY05hbWVXYXJuaW5nQ291bnQgPCBudW1lcmljTmFtZVdhcm5pbmdDb3VudExpbWl0KSB7XG4gICAgICAgICAgICBudW1lcmljTmFtZVdhcm5pbmdDb3VudCsrO1xuXG4gICAgICAgICAgICBMaWIud2FybignYWRkRnJhbWVzOiBvdmVyd3JpdGluZyBmcmFtZSBcIicgKyAoX2ZyYW1lSGFzaFtuYW1lXSB8fCBfZnJhbWVIYXNoTG9jYWxbbmFtZV0pLm5hbWUgK1xuICAgICAgICAgICAgICAgICdcIiB3aXRoIGEgZnJhbWUgd2hvc2UgbmFtZSBvZiB0eXBlIFwibnVtYmVyXCIgYWxzbyBlcXVhdGVzIHRvIFwiJyArXG4gICAgICAgICAgICAgICAgbmFtZSArICdcIi4gVGhpcyBpcyB2YWxpZCBidXQgbWF5IHBvdGVudGlhbGx5IGxlYWQgdG8gdW5leHBlY3RlZCAnICtcbiAgICAgICAgICAgICAgICAnYmVoYXZpb3Igc2luY2UgYWxsIHBsb3RseS5qcyBmcmFtZSBuYW1lcyBhcmUgc3RvcmVkIGludGVybmFsbHkgJyArXG4gICAgICAgICAgICAgICAgJ2FzIHN0cmluZ3MuJyk7XG5cbiAgICAgICAgICAgIGlmKG51bWVyaWNOYW1lV2FybmluZ0NvdW50ID09PSBudW1lcmljTmFtZVdhcm5pbmdDb3VudExpbWl0KSB7XG4gICAgICAgICAgICAgICAgTGliLndhcm4oJ2FkZEZyYW1lczogVGhpcyBBUEkgY2FsbCBoYXMgeWllbGRlZCB0b28gbWFueSBvZiB0aGVzZSB3YXJuaW5ncy4gJyArXG4gICAgICAgICAgICAgICAgICAgICdGb3IgdGhlIHJlc3Qgb2YgdGhpcyBjYWxsLCBmdXJ0aGVyIHdhcm5pbmdzIGFib3V0IG51bWVyaWMgZnJhbWUgJyArXG4gICAgICAgICAgICAgICAgICAgICduYW1lcyB3aWxsIGJlIHN1cHByZXNzZWQuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBfZnJhbWVIYXNoTG9jYWxbbG9va3VwTmFtZV0gPSB7bmFtZTogbG9va3VwTmFtZX07XG5cbiAgICAgICAgaW5zZXJ0aW9ucy5wdXNoKHtcbiAgICAgICAgICAgIGZyYW1lOiBQbG90cy5zdXBwbHlGcmFtZURlZmF1bHRzKGZyYW1lTGlzdFtpXSksXG4gICAgICAgICAgICBpbmRleDogKGluZGljZXMgJiYgaW5kaWNlc1tpXSAhPT0gdW5kZWZpbmVkICYmIGluZGljZXNbaV0gIT09IG51bGwpID8gaW5kaWNlc1tpXSA6IGJpZ0luZGV4ICsgaVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBTb3J0IHRoaXMsIHRha2luZyBub3RlIHRoYXQgdW5kZWZpbmVkIGluc2VydGlvbnMgZW5kIHVwIGF0IHRoZSBlbmQ6XG4gICAgaW5zZXJ0aW9ucy5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgaWYoYS5pbmRleCA+IGIuaW5kZXgpIHJldHVybiAtMTtcbiAgICAgICAgaWYoYS5pbmRleCA8IGIuaW5kZXgpIHJldHVybiAxO1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9KTtcblxuICAgIHZhciBvcHMgPSBbXTtcbiAgICB2YXIgcmV2b3BzID0gW107XG4gICAgdmFyIGZyYW1lQ291bnQgPSBfZnJhbWVzLmxlbmd0aDtcblxuICAgIGZvcihpID0gaW5zZXJ0aW9ucy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBmcmFtZSA9IGluc2VydGlvbnNbaV0uZnJhbWU7XG5cbiAgICAgICAgaWYodHlwZW9mIGZyYW1lLm5hbWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBMaWIud2FybignV2FybmluZzogYWRkRnJhbWVzIGFjY2VwdHMgZnJhbWVzIHdpdGggbnVtZXJpYyBuYW1lcywgYnV0IHRoZSBudW1iZXJzIGFyZScgK1xuICAgICAgICAgICAgICAgICdpbXBsaWNpdGx5IGNhc3QgdG8gc3RyaW5ncycpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWZyYW1lLm5hbWUpIHtcbiAgICAgICAgICAgIC8vIFJlcGVhdGVkbHkgYXNzaWduIGEgZGVmYXVsdCBuYW1lLCBpbmNyZW1lbnRpbmcgdGhlIGNvdW50ZXIgZWFjaCB0aW1lIHVudGlsXG4gICAgICAgICAgICAvLyB3ZSBnZXQgYSBuYW1lIHRoYXQncyBub3QgaW4gdGhlIGhhc2hlZCBsb29rdXAgdGFibGU6XG4gICAgICAgICAgICB3aGlsZShfZnJhbWVIYXNoWyhmcmFtZS5uYW1lID0gJ2ZyYW1lICcgKyBnZC5fdHJhbnNpdGlvbkRhdGEuX2NvdW50ZXIrKyldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKF9mcmFtZUhhc2hbZnJhbWUubmFtZV0pIHtcbiAgICAgICAgICAgIC8vIElmIGZyYW1lIGlzIHByZXNlbnQsIG92ZXJ3cml0ZSBpdHMgZGVmaW5pdGlvbjpcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IF9mcmFtZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZigoX2ZyYW1lc1tqXSB8fCB7fSkubmFtZSA9PT0gZnJhbWUubmFtZSkgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcHMucHVzaCh7dHlwZTogJ3JlcGxhY2UnLCBpbmRleDogaiwgdmFsdWU6IGZyYW1lfSk7XG4gICAgICAgICAgICByZXZvcHMudW5zaGlmdCh7dHlwZTogJ3JlcGxhY2UnLCBpbmRleDogaiwgdmFsdWU6IF9mcmFtZXNbal19KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE90aGVyd2lzZSBpbnNlcnQgaXQgYXQgdGhlIGVuZCBvZiB0aGUgbGlzdDpcbiAgICAgICAgICAgIGlkeCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGluc2VydGlvbnNbaV0uaW5kZXgsIGZyYW1lQ291bnQpKTtcblxuICAgICAgICAgICAgb3BzLnB1c2goe3R5cGU6ICdpbnNlcnQnLCBpbmRleDogaWR4LCB2YWx1ZTogZnJhbWV9KTtcbiAgICAgICAgICAgIHJldm9wcy51bnNoaWZ0KHt0eXBlOiAnZGVsZXRlJywgaW5kZXg6IGlkeH0pO1xuICAgICAgICAgICAgZnJhbWVDb3VudCsrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHVuZG9GdW5jID0gUGxvdHMubW9kaWZ5RnJhbWVzO1xuICAgIHZhciByZWRvRnVuYyA9IFBsb3RzLm1vZGlmeUZyYW1lcztcbiAgICB2YXIgdW5kb0FyZ3MgPSBbZ2QsIHJldm9wc107XG4gICAgdmFyIHJlZG9BcmdzID0gW2dkLCBvcHNdO1xuXG4gICAgaWYoUXVldWUpIFF1ZXVlLmFkZChnZCwgdW5kb0Z1bmMsIHVuZG9BcmdzLCByZWRvRnVuYywgcmVkb0FyZ3MpO1xuXG4gICAgcmV0dXJuIFBsb3RzLm1vZGlmeUZyYW1lcyhnZCwgb3BzKTtcbn1cblxuLyoqXG4gKiBEZWxldGUgZnJhbWVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZyBpZCBvciBET00gZWxlbWVudH0gZ2RcbiAqICAgICAgdGhlIGlkIG9yIERPTSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKlxuICogQHBhcmFtIHthcnJheSBvZiBpbnRlZ2Vyc30gZnJhbWVMaXN0XG4gKiAgICAgIGxpc3Qgb2YgaW50ZWdlciBpbmRpY2VzIG9mIGZyYW1lcyB0byBiZSBkZWxldGVkXG4gKi9cbmZ1bmN0aW9uIGRlbGV0ZUZyYW1lcyhnZCwgZnJhbWVMaXN0KSB7XG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuXG4gICAgaWYoIUxpYi5pc1Bsb3REaXYoZ2QpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGhpcyBlbGVtZW50IGlzIG5vdCBhIFBsb3RseSBwbG90OiAnICsgZ2QpO1xuICAgIH1cblxuICAgIHZhciBpLCBpZHg7XG4gICAgdmFyIF9mcmFtZXMgPSBnZC5fdHJhbnNpdGlvbkRhdGEuX2ZyYW1lcztcbiAgICB2YXIgb3BzID0gW107XG4gICAgdmFyIHJldm9wcyA9IFtdO1xuXG4gICAgaWYoIWZyYW1lTGlzdCkge1xuICAgICAgICBmcmFtZUxpc3QgPSBbXTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgX2ZyYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZnJhbWVMaXN0LnB1c2goaSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmcmFtZUxpc3QgPSBmcmFtZUxpc3Quc2xpY2UoKTtcbiAgICBmcmFtZUxpc3Quc29ydCgpO1xuXG4gICAgZm9yKGkgPSBmcmFtZUxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgaWR4ID0gZnJhbWVMaXN0W2ldO1xuICAgICAgICBvcHMucHVzaCh7dHlwZTogJ2RlbGV0ZScsIGluZGV4OiBpZHh9KTtcbiAgICAgICAgcmV2b3BzLnVuc2hpZnQoe3R5cGU6ICdpbnNlcnQnLCBpbmRleDogaWR4LCB2YWx1ZTogX2ZyYW1lc1tpZHhdfSk7XG4gICAgfVxuXG4gICAgdmFyIHVuZG9GdW5jID0gUGxvdHMubW9kaWZ5RnJhbWVzO1xuICAgIHZhciByZWRvRnVuYyA9IFBsb3RzLm1vZGlmeUZyYW1lcztcbiAgICB2YXIgdW5kb0FyZ3MgPSBbZ2QsIHJldm9wc107XG4gICAgdmFyIHJlZG9BcmdzID0gW2dkLCBvcHNdO1xuXG4gICAgaWYoUXVldWUpIFF1ZXVlLmFkZChnZCwgdW5kb0Z1bmMsIHVuZG9BcmdzLCByZWRvRnVuYywgcmVkb0FyZ3MpO1xuXG4gICAgcmV0dXJuIFBsb3RzLm1vZGlmeUZyYW1lcyhnZCwgb3BzKTtcbn1cblxuLyoqXG4gKiBQdXJnZSBhIGdyYXBoIGNvbnRhaW5lciBkaXYgYmFjayB0byBpdHMgaW5pdGlhbCBwcmUtUGxvdGx5LnBsb3Qgc3RhdGVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZyBpZCBvciBET00gZWxlbWVudH0gZ2RcbiAqICAgICAgdGhlIGlkIG9yIERPTSBlbGVtZW50IG9mIHRoZSBncmFwaCBjb250YWluZXIgZGl2XG4gKi9cbmZ1bmN0aW9uIHB1cmdlKGdkKSB7XG4gICAgZ2QgPSBMaWIuZ2V0R3JhcGhEaXYoZ2QpO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dCB8fCB7fTtcbiAgICB2YXIgZnVsbERhdGEgPSBnZC5fZnVsbERhdGEgfHwgW107XG5cbiAgICAvLyByZW1vdmUgZ2wgY29udGV4dHNcbiAgICBQbG90cy5jbGVhblBsb3QoW10sIHt9LCBmdWxsRGF0YSwgZnVsbExheW91dCk7XG5cbiAgICAvLyBwdXJnZSBwcm9wZXJ0aWVzXG4gICAgUGxvdHMucHVyZ2UoZ2QpO1xuXG4gICAgLy8gcHVyZ2UgZXZlbnQgZW1pdHRlciBtZXRob2RzXG4gICAgRXZlbnRzLnB1cmdlKGdkKTtcblxuICAgIC8vIHJlbW92ZSBwbG90IGNvbnRhaW5lclxuICAgIGlmKGZ1bGxMYXlvdXQuX2NvbnRhaW5lcikgZnVsbExheW91dC5fY29udGFpbmVyLnJlbW92ZSgpO1xuXG4gICAgLy8gaW4gY29udHJhc3QgdG8gUGxvdGx5LlBsb3RzLnB1cmdlIHdoaWNoIGRvZXMgTk9UIGNsZWFyIF9jb250ZXh0IVxuICAgIGRlbGV0ZSBnZC5fY29udGV4dDtcblxuICAgIHJldHVybiBnZDtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gbWFrZVBsb3RGcmFtZXdvcms6IENyZWF0ZSB0aGUgcGxvdCBjb250YWluZXIgYW5kIGF4ZXNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZ1bmN0aW9uIG1ha2VQbG90RnJhbWV3b3JrKGdkKSB7XG4gICAgdmFyIGdkMyA9IGQzLnNlbGVjdChnZCk7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIC8vIFBsb3QgY29udGFpbmVyXG4gICAgZnVsbExheW91dC5fY29udGFpbmVyID0gZ2QzLnNlbGVjdEFsbCgnLnBsb3QtY29udGFpbmVyJykuZGF0YShbMF0pO1xuICAgIGZ1bGxMYXlvdXQuX2NvbnRhaW5lci5lbnRlcigpLmluc2VydCgnZGl2JywgJzpmaXJzdC1jaGlsZCcpXG4gICAgICAgIC5jbGFzc2VkKCdwbG90LWNvbnRhaW5lcicsIHRydWUpXG4gICAgICAgIC5jbGFzc2VkKCdwbG90bHknLCB0cnVlKTtcblxuICAgIC8vIE1ha2UgdGhlIHN2ZyBjb250YWluZXJcbiAgICBmdWxsTGF5b3V0Ll9wYXBlcmRpdiA9IGZ1bGxMYXlvdXQuX2NvbnRhaW5lci5zZWxlY3RBbGwoJy5zdmctY29udGFpbmVyJykuZGF0YShbMF0pO1xuICAgIGZ1bGxMYXlvdXQuX3BhcGVyZGl2LmVudGVyKCkuYXBwZW5kKCdkaXYnKVxuICAgICAgICAuY2xhc3NlZCgnc3ZnLWNvbnRhaW5lcicsIHRydWUpXG4gICAgICAgIC5zdHlsZSgncG9zaXRpb24nLCAncmVsYXRpdmUnKTtcblxuICAgIC8vIE1ha2UgdGhlIGdyYXBoIGNvbnRhaW5lcnNcbiAgICAvLyBzdGFydCBmcmVzaCBlYWNoIHRpbWUgd2UgZ2V0IGhlcmUsIHNvIHdlIGtub3cgdGhlIG9yZGVyIGNvbWVzIG91dFxuICAgIC8vIHJpZ2h0LCByYXRoZXIgdGhhbiBlbnRlci9leGl0IHdoaWNoIGNhbiBtdWNrIHVwIHRoZSBvcmRlclxuICAgIC8vIFRPRE86IHNvcnQgb3V0IGFsbCB0aGUgb3JkZXJpbmcgc28gd2UgZG9uJ3QgaGF2ZSB0b1xuICAgIC8vIGV4cGxpY2l0bHkgZGVsZXRlIGFueXRoaW5nXG4gICAgLy8gRklYTUU6IHBhcmNvb3JkcyByZXVzZXMgdGhpcyBvYmplY3QsIG5vdCB0aGUgYmVzdCBwYXR0ZXJuXG4gICAgZnVsbExheW91dC5fZ2xjb250YWluZXIgPSBmdWxsTGF5b3V0Ll9wYXBlcmRpdi5zZWxlY3RBbGwoJy5nbC1jb250YWluZXInKVxuICAgICAgICAuZGF0YShbe31dKTtcblxuICAgIGZ1bGxMYXlvdXQuX2dsY29udGFpbmVyLmVudGVyKCkuYXBwZW5kKCdkaXYnKVxuICAgICAgICAuY2xhc3NlZCgnZ2wtY29udGFpbmVyJywgdHJ1ZSk7XG5cbiAgICBmdWxsTGF5b3V0Ll9wYXBlcmRpdi5zZWxlY3RBbGwoJy5tYWluLXN2ZycpLnJlbW92ZSgpO1xuICAgIGZ1bGxMYXlvdXQuX3BhcGVyZGl2LnNlbGVjdCgnLm1vZGViYXItY29udGFpbmVyJykucmVtb3ZlKCk7XG5cbiAgICBmdWxsTGF5b3V0Ll9wYXBlciA9IGZ1bGxMYXlvdXQuX3BhcGVyZGl2Lmluc2VydCgnc3ZnJywgJzpmaXJzdC1jaGlsZCcpXG4gICAgICAgIC5jbGFzc2VkKCdtYWluLXN2ZycsIHRydWUpO1xuXG4gICAgZnVsbExheW91dC5fdG9wcGFwZXIgPSBmdWxsTGF5b3V0Ll9wYXBlcmRpdi5hcHBlbmQoJ3N2ZycpXG4gICAgICAgIC5jbGFzc2VkKCdtYWluLXN2ZycsIHRydWUpO1xuXG4gICAgZnVsbExheW91dC5fbW9kZWJhcmRpdiA9IGZ1bGxMYXlvdXQuX3BhcGVyZGl2LmFwcGVuZCgnZGl2Jyk7XG5cbiAgICBmdWxsTGF5b3V0Ll9ob3ZlcnBhcGVyID0gZnVsbExheW91dC5fcGFwZXJkaXYuYXBwZW5kKCdzdmcnKVxuICAgICAgICAuY2xhc3NlZCgnbWFpbi1zdmcnLCB0cnVlKTtcblxuICAgIGlmKCFmdWxsTGF5b3V0Ll91aWQpIHtcbiAgICAgICAgdmFyIG90aGVyVWlkcyA9IHt9O1xuICAgICAgICBkMy5zZWxlY3RBbGwoJ2RlZnMnKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYodGhpcy5pZCkgb3RoZXJVaWRzW3RoaXMuaWQuc3BsaXQoJy0nKVsxXV0gPSAxO1xuICAgICAgICB9KTtcbiAgICAgICAgZnVsbExheW91dC5fdWlkID0gTGliLnJhbmRzdHIob3RoZXJVaWRzKTtcbiAgICB9XG5cbiAgICBmdWxsTGF5b3V0Ll9wYXBlcmRpdi5zZWxlY3RBbGwoJy5tYWluLXN2ZycpXG4gICAgICAgIC5hdHRyKHhtbG5zTmFtZXNwYWNlcy5zdmdBdHRycyk7XG5cbiAgICBmdWxsTGF5b3V0Ll9kZWZzID0gZnVsbExheW91dC5fcGFwZXIuYXBwZW5kKCdkZWZzJylcbiAgICAgICAgLmF0dHIoJ2lkJywgJ2RlZnMtJyArIGZ1bGxMYXlvdXQuX3VpZCk7XG5cbiAgICBmdWxsTGF5b3V0Ll9jbGlwcyA9IGZ1bGxMYXlvdXQuX2RlZnMuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2NsaXBzJywgdHJ1ZSk7XG5cbiAgICBmdWxsTGF5b3V0Ll90b3BkZWZzID0gZnVsbExheW91dC5fdG9wcGFwZXIuYXBwZW5kKCdkZWZzJylcbiAgICAgICAgLmF0dHIoJ2lkJywgJ3RvcGRlZnMtJyArIGZ1bGxMYXlvdXQuX3VpZCk7XG5cbiAgICBmdWxsTGF5b3V0Ll90b3BjbGlwcyA9IGZ1bGxMYXlvdXQuX3RvcGRlZnMuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2NsaXBzJywgdHJ1ZSk7XG5cbiAgICBmdWxsTGF5b3V0Ll9iZ0xheWVyID0gZnVsbExheW91dC5fcGFwZXIuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2JnbGF5ZXInLCB0cnVlKTtcblxuICAgIGZ1bGxMYXlvdXQuX2RyYWdnZXJzID0gZnVsbExheW91dC5fcGFwZXIuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2RyYWdsYXllcicsIHRydWUpO1xuXG4gICAgLy8gbG93ZXIgc2hhcGUvaW1hZ2UgbGF5ZXIgLSBub3RlIHRoYXQgdGhpcyBpcyBiZWhpbmRcbiAgICAvLyBhbGwgc3VicGxvdHMgZGF0YS9ncmlkcyBidXQgYWJvdmUgdGhlIGJhY2tncm91bmRzXG4gICAgLy8gZXhjZXB0IGluc2V0IHN1YnBsb3RzLCB3aG9zZSBiYWNrZ3JvdW5kcyBhcmUgZHJhd25cbiAgICAvLyBpbnNpZGUgdGhlaXIgb3duIGdyb3VwIHNvIHRoYXQgdGhleSBhcHBlYXIgYWJvdmVcbiAgICAvLyB0aGUgZGF0YSBmb3IgdGhlIG1haW4gc3VicGxvdFxuICAgIC8vIGxvd2VyIHNoYXBlcyBhbmQgaW1hZ2VzIHdoaWNoIGFyZSBmdWxseSByZWZlcmVuY2VkIHRvXG4gICAgLy8gYSBzdWJwbG90IHN0aWxsIGdldCBkcmF3biB3aXRoaW4gdGhlIHN1YnBsb3QncyBncm91cFxuICAgIC8vIHNvIHRoZXkgd2lsbCB3b3JrIGNvcnJlY3RseSBvbiBpbnNldHNcbiAgICB2YXIgbGF5ZXJCZWxvdyA9IGZ1bGxMYXlvdXQuX3BhcGVyLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdsYXllci1iZWxvdycsIHRydWUpO1xuICAgIGZ1bGxMYXlvdXQuX2ltYWdlTG93ZXJMYXllciA9IGxheWVyQmVsb3cuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2ltYWdlbGF5ZXInLCB0cnVlKTtcbiAgICBmdWxsTGF5b3V0Ll9zaGFwZUxvd2VyTGF5ZXIgPSBsYXllckJlbG93LmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdzaGFwZWxheWVyJywgdHJ1ZSk7XG5cbiAgICAvLyBzaW5nbGUgY2FydGVzaWFuIGxheWVyIGZvciB0aGUgd2hvbGUgcGxvdFxuICAgIGZ1bGxMYXlvdXQuX2NhcnRlc2lhbmxheWVyID0gZnVsbExheW91dC5fcGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnY2FydGVzaWFubGF5ZXInLCB0cnVlKTtcblxuICAgIC8vIHNpbmdsZSBwb2xhciBsYXllciBmb3IgdGhlIHdob2xlIHBsb3RcbiAgICBmdWxsTGF5b3V0Ll9wb2xhcmxheWVyID0gZnVsbExheW91dC5fcGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgncG9sYXJsYXllcicsIHRydWUpO1xuXG4gICAgLy8gc2luZ2xlIHRlcm5hcnkgbGF5ZXIgZm9yIHRoZSB3aG9sZSBwbG90XG4gICAgZnVsbExheW91dC5fdGVybmFyeWxheWVyID0gZnVsbExheW91dC5fcGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgndGVybmFyeWxheWVyJywgdHJ1ZSk7XG5cbiAgICAvLyBzaW5nbGUgZ2VvIGxheWVyIGZvciB0aGUgd2hvbGUgcGxvdFxuICAgIGZ1bGxMYXlvdXQuX2dlb2xheWVyID0gZnVsbExheW91dC5fcGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnZ2VvbGF5ZXInLCB0cnVlKTtcblxuICAgIC8vIHNpbmdsZSBmdW5uZWxhcmVhIGxheWVyIGZvciB0aGUgd2hvbGUgcGxvdFxuICAgIGZ1bGxMYXlvdXQuX2Z1bm5lbGFyZWFsYXllciA9IGZ1bGxMYXlvdXQuX3BhcGVyLmFwcGVuZCgnZycpLmNsYXNzZWQoJ2Z1bm5lbGFyZWFsYXllcicsIHRydWUpO1xuXG4gICAgLy8gc2luZ2xlIHBpZSBsYXllciBmb3IgdGhlIHdob2xlIHBsb3RcbiAgICBmdWxsTGF5b3V0Ll9waWVsYXllciA9IGZ1bGxMYXlvdXQuX3BhcGVyLmFwcGVuZCgnZycpLmNsYXNzZWQoJ3BpZWxheWVyJywgdHJ1ZSk7XG5cbiAgICAvLyBzaW5nbGUgc3VuYnVyc3QgbGF5ZXIgZm9yIHRoZSB3aG9sZSBwbG90XG4gICAgZnVsbExheW91dC5fc3VuYnVyc3RsYXllciA9IGZ1bGxMYXlvdXQuX3BhcGVyLmFwcGVuZCgnZycpLmNsYXNzZWQoJ3N1bmJ1cnN0bGF5ZXInLCB0cnVlKTtcblxuICAgIC8vIHNpbmdsZSBpbmRpY2F0b3IgbGF5ZXIgZm9yIHRoZSB3aG9sZSBwbG90XG4gICAgZnVsbExheW91dC5faW5kaWNhdG9ybGF5ZXIgPSBmdWxsTGF5b3V0Ll90b3BwYXBlci5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdpbmRpY2F0b3JsYXllcicsIHRydWUpO1xuXG4gICAgLy8gZmlsbCBpbiBpbWFnZSBzZXJ2ZXIgc2NyYXBlLXN2Z1xuICAgIGZ1bGxMYXlvdXQuX2dsaW1hZ2VzID0gZnVsbExheW91dC5fcGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnZ2xpbWFnZXMnLCB0cnVlKTtcblxuICAgIC8vIGxhc3RseSB1cHBlciBzaGFwZXMsIGluZm8gKGxlZ2VuZCwgYW5ub3RhdGlvbnMpIGFuZCBob3ZlciBsYXllcnMgZ28gb24gdG9wXG4gICAgLy8gdGhlc2UgYXJlIGluIGEgZGlmZmVyZW50IHN2ZyBlbGVtZW50IG5vcm1hbGx5LCBidXQgZ2V0IGNvbGxhcHNlZCBpbnRvIGEgc2luZ2xlXG4gICAgLy8gc3ZnIHdoZW4gZXhwb3J0aW5nIChhZnRlciBpbnNlcnRpbmcgM0QpXG4gICAgLy8gdXBwZXIgc2hhcGVzL2ltYWdlcyBhcmUgb25seSB0aG9zZSBkcmF3biBhYm92ZSB0aGUgd2hvbGUgcGxvdCwgaW5jbHVkaW5nIHN1YnBsb3RzXG4gICAgdmFyIGxheWVyQWJvdmUgPSBmdWxsTGF5b3V0Ll90b3BwYXBlci5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnbGF5ZXItYWJvdmUnLCB0cnVlKTtcbiAgICBmdWxsTGF5b3V0Ll9pbWFnZVVwcGVyTGF5ZXIgPSBsYXllckFib3ZlLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdpbWFnZWxheWVyJywgdHJ1ZSk7XG4gICAgZnVsbExheW91dC5fc2hhcGVVcHBlckxheWVyID0gbGF5ZXJBYm92ZS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnc2hhcGVsYXllcicsIHRydWUpO1xuXG4gICAgZnVsbExheW91dC5faW5mb2xheWVyID0gZnVsbExheW91dC5fdG9wcGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnaW5mb2xheWVyJywgdHJ1ZSk7XG4gICAgZnVsbExheW91dC5fbWVudWxheWVyID0gZnVsbExheW91dC5fdG9wcGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnbWVudWxheWVyJywgdHJ1ZSk7XG4gICAgZnVsbExheW91dC5fem9vbWxheWVyID0gZnVsbExheW91dC5fdG9wcGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnem9vbWxheWVyJywgdHJ1ZSk7XG4gICAgZnVsbExheW91dC5faG92ZXJsYXllciA9IGZ1bGxMYXlvdXQuX2hvdmVycGFwZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnaG92ZXJsYXllcicsIHRydWUpO1xuXG4gICAgLy8gTWFrZSB0aGUgbW9kZWJhciBjb250YWluZXJcbiAgICBmdWxsTGF5b3V0Ll9tb2RlYmFyZGl2XG4gICAgICAgIC5jbGFzc2VkKCdtb2RlYmFyLWNvbnRhaW5lcicsIHRydWUpXG4gICAgICAgIC5zdHlsZSgncG9zaXRpb24nLCAnYWJzb2x1dGUnKVxuICAgICAgICAuc3R5bGUoJ3RvcCcsICcwcHgnKVxuICAgICAgICAuc3R5bGUoJ3JpZ2h0JywgJzBweCcpO1xuXG4gICAgZ2QuZW1pdCgncGxvdGx5X2ZyYW1ld29yaycpO1xufVxuXG5leHBvcnRzLmFuaW1hdGUgPSBhbmltYXRlO1xuZXhwb3J0cy5hZGRGcmFtZXMgPSBhZGRGcmFtZXM7XG5leHBvcnRzLmRlbGV0ZUZyYW1lcyA9IGRlbGV0ZUZyYW1lcztcblxuZXhwb3J0cy5hZGRUcmFjZXMgPSBhZGRUcmFjZXM7XG5leHBvcnRzLmRlbGV0ZVRyYWNlcyA9IGRlbGV0ZVRyYWNlcztcbmV4cG9ydHMuZXh0ZW5kVHJhY2VzID0gZXh0ZW5kVHJhY2VzO1xuZXhwb3J0cy5tb3ZlVHJhY2VzID0gbW92ZVRyYWNlcztcbmV4cG9ydHMucHJlcGVuZFRyYWNlcyA9IHByZXBlbmRUcmFjZXM7XG5cbmV4cG9ydHMubmV3UGxvdCA9IG5ld1Bsb3Q7XG5leHBvcnRzLnBsb3QgPSBwbG90O1xuZXhwb3J0cy5wdXJnZSA9IHB1cmdlO1xuXG5leHBvcnRzLnJlYWN0ID0gcmVhY3Q7XG5leHBvcnRzLnJlZHJhdyA9IHJlZHJhdztcbmV4cG9ydHMucmVsYXlvdXQgPSByZWxheW91dDtcbmV4cG9ydHMucmVzdHlsZSA9IHJlc3R5bGU7XG5cbmV4cG9ydHMuc2V0UGxvdENvbmZpZyA9IHNldFBsb3RDb25maWc7XG5cbmV4cG9ydHMudXBkYXRlID0gdXBkYXRlO1xuXG5leHBvcnRzLl9ndWlSZWxheW91dCA9IGd1aUVkaXQocmVsYXlvdXQpO1xuZXhwb3J0cy5fZ3VpUmVzdHlsZSA9IGd1aUVkaXQocmVzdHlsZSk7XG5leHBvcnRzLl9ndWlVcGRhdGUgPSBndWlFZGl0KHVwZGF0ZSk7XG5cbmV4cG9ydHMuX3N0b3JlRGlyZWN0R1VJRWRpdCA9IF9zdG9yZURpcmVjdEdVSUVkaXQ7XG5cbn0se1wiLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzXCI6Njk2LFwiLi4vbGliXCI6NzE5LFwiLi4vbGliL2V2ZW50c1wiOjcwOSxcIi4uL2xpYi9xdWV1ZVwiOjczNCxcIi4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50c1wiOjc3MyxcIi4uL3Bsb3RzL2NhcnRlc2lhbi9ncmFwaF9pbnRlcmFjdFwiOjc3NixcIi4uL3Bsb3RzL2NhcnRlc2lhbi9zZWxlY3RcIjo3ODQsXCIuLi9wbG90cy9wbG90c1wiOjgyOCxcIi4uL3Bsb3RzL3BvbGFyL2xlZ2FjeVwiOjgzNixcIi4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9lZGl0X3R5cGVzXCI6NzUwLFwiLi9oZWxwZXJzXCI6NzUxLFwiLi9tYW5hZ2VfYXJyYXlzXCI6NzUzLFwiLi9wbG90X2NvbmZpZ1wiOjc1NSxcIi4vcGxvdF9zY2hlbWFcIjo3NTYsXCIuL3N1YnJvdXRpbmVzXCI6NzU4LFwiZDNcIjoxNjMsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNSxcImhhcy1ob3ZlclwiOjQxMH1dLDc1NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogVGhpcyB3aWxsIGJlIHRyYW5zZmVycmVkIG92ZXIgdG8gZ2QgYW5kIG92ZXJyaWRkZW4gYnlcbiAqIGNvbmZpZyBhcmdzIHRvIFBsb3RseS5wbG90LlxuICpcbiAqIFRoZSBkZWZhdWx0cyBhcmUgdGhlIGFwcHJvcHJpYXRlIHNldHRpbmdzIGZvciBwbG90bHkuanMsXG4gKiBzbyB3ZSBnZXQgdGhlIHJpZ2h0IGV4cGVyaWVuY2Ugd2l0aG91dCBhbnkgY29uZmlnIGFyZ3VtZW50LlxuICpcbiAqIE4uQi4gdGhlIGNvbmZpZyBvcHRpb25zIGFyZSBub3QgY29lcmNlZCB1c2luZyBMaWIuY29lcmNlIHNvIGtleXNcbiAqIGxpa2UgYHZhbFR5cGVgIGFuZCBgdmFsdWVzYCBhcmUgb25seSBzZXQgZm9yIGRvY3VtZW50YXRpb24gcHVycG9zZXNcbiAqIGF0IHRoZSBtb21lbnQuXG4gKi9cblxudmFyIGNvbmZpZ0F0dHJpYnV0ZXMgPSB7XG4gICAgc3RhdGljUGxvdDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgcGxvdGx5U2VydmVyVVJMOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBkZmx0OiAnaHR0cHM6Ly9wbG90Lmx5JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGVkaXRhYmxlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdHM6IHtcbiAgICAgICAgYW5ub3RhdGlvblBvc2l0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBhbm5vdGF0aW9uVGFpbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgYW5ub3RhdGlvblRleHQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGF4aXNUaXRsZVRleHQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yYmFyUG9zaXRpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yYmFyVGl0bGVUZXh0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBsZWdlbmRQb3NpdGlvbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbGVnZW5kVGV4dDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2hhcGVQb3NpdGlvbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdGl0bGVUZXh0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGF1dG9zaXphYmxlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcmVzcG9uc2l2ZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGZpbGxGcmFtZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGZyYW1lTWFyZ2luczoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDAuNSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHNjcm9sbFpvb206IHtcbiAgICAgICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICAgICAgZmxhZ3M6IFsnY2FydGVzaWFuJywgJ2dsM2QnLCAnZ2VvJywgJ21hcGJveCddLFxuICAgICAgICBleHRyYXM6IFt0cnVlLCBmYWxzZV0sXG4gICAgICAgIGRmbHQ6ICdnbDNkK2dlbyttYXBib3gnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRvdWJsZUNsaWNrOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbZmFsc2UsICdyZXNldCcsICdhdXRvc2l6ZScsICdyZXNldCthdXRvc2l6ZSddLFxuICAgICAgICBkZmx0OiAncmVzZXQrYXV0b3NpemUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRvdWJsZUNsaWNrRGVsYXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDMwMCxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2hvd0F4aXNEcmFnSGFuZGxlczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd0F4aXNSYW5nZUVudHJ5Qm94ZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2hvd1RpcHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2hvd0xpbms6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsaW5rVGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJ0VkaXQgY2hhcnQnLFxuICAgICAgICBub0JsYW5rOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNlbmREYXRhOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93U291cmNlczoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBkaXNwbGF5TW9kZUJhcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydob3ZlcicsIHRydWUsIGZhbHNlXSxcbiAgICAgICAgZGZsdDogJ2hvdmVyJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93U2VuZFRvQ2xvdWQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93RWRpdEluQ2hhcnRTdHVkaW86IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtb2RlQmFyQnV0dG9uc1RvUmVtb3ZlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtb2RlQmFyQnV0dG9uc1RvQWRkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtb2RlQmFyQnV0dG9uczoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdG9JbWFnZUJ1dHRvbk9wdGlvbnM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIGRmbHQ6IHt9LFxuICAgICAgICBcbiAgICB9LFxuICAgIGRpc3BsYXlsb2dvOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICB3YXRlcm1hcms6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHBsb3RHbFBpeGVsUmF0aW86IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDIsXG4gICAgICAgIG1pbjogMSxcbiAgICAgICAgbWF4OiA0LFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc2V0QmFja2dyb3VuZDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgZGZsdDogJ3RyYW5zcGFyZW50JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRvcG9qc29uVVJMOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBub0JsYW5rOiB0cnVlLFxuICAgICAgICBkZmx0OiAnaHR0cHM6Ly9jZG4ucGxvdC5seS8nLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbWFwYm94QWNjZXNzVG9rZW46IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsb2dnaW5nOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHF1ZXVlTGVuZ3RoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgZ2xvYmFsVHJhbnNmb3Jtczoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgZGZsdDogW10sXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsb2NhbGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIGRmbHQ6ICdlbi1VUycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsb2NhbGVzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBkZmx0OiB7fSxcbiAgICAgICAgXG4gICAgfVxufTtcblxudmFyIGRmbHRDb25maWcgPSB7fTtcblxuZnVuY3Rpb24gY3Jhd2woc3JjLCB0YXJnZXQpIHtcbiAgICBmb3IodmFyIGsgaW4gc3JjKSB7XG4gICAgICAgIHZhciBvYmogPSBzcmNba107XG4gICAgICAgIGlmKG9iai52YWxUeXBlKSB7XG4gICAgICAgICAgICB0YXJnZXRba10gPSBvYmouZGZsdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKCF0YXJnZXRba10pIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRba10gPSB7fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNyYXdsKG9iaiwgdGFyZ2V0W2tdKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuY3Jhd2woY29uZmlnQXR0cmlidXRlcywgZGZsdENvbmZpZyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNvbmZpZ0F0dHJpYnV0ZXM6IGNvbmZpZ0F0dHJpYnV0ZXMsXG4gICAgZGZsdENvbmZpZzogZGZsdENvbmZpZ1xufTtcblxufSx7fV0sNzU2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcblxudmFyIGJhc2VBdHRyaWJ1dGVzID0gX2RlcmVxXygnLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGJhc2VMYXlvdXRBdHRyaWJ1dGVzID0gX2RlcmVxXygnLi4vcGxvdHMvbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBmcmFtZUF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuLi9wbG90cy9mcmFtZV9hdHRyaWJ1dGVzJyk7XG52YXIgYW5pbWF0aW9uQXR0cmlidXRlcyA9IF9kZXJlcV8oJy4uL3Bsb3RzL2FuaW1hdGlvbl9hdHRyaWJ1dGVzJyk7XG52YXIgY29uZmlnQXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vcGxvdF9jb25maWcnKS5jb25maWdBdHRyaWJ1dGVzO1xuXG4vLyBwb2xhciBhdHRyaWJ1dGVzIGFyZSBub3QgcGFydCBvZiB0aGUgUmVnaXN0cnkgeWV0XG52YXIgcG9sYXJBcmVhQXR0cnMgPSBfZGVyZXFfKCcuLi9wbG90cy9wb2xhci9sZWdhY3kvYXJlYV9hdHRyaWJ1dGVzJyk7XG52YXIgcG9sYXJBeGlzQXR0cnMgPSBfZGVyZXFfKCcuLi9wbG90cy9wb2xhci9sZWdhY3kvYXhpc19hdHRyaWJ1dGVzJyk7XG5cbnZhciBlZGl0VHlwZXMgPSBfZGVyZXFfKCcuL2VkaXRfdHlwZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSBMaWIuZXh0ZW5kRmxhdDtcbnZhciBleHRlbmREZWVwQWxsID0gTGliLmV4dGVuZERlZXBBbGw7XG52YXIgaXNQbGFpbk9iamVjdCA9IExpYi5pc1BsYWluT2JqZWN0O1xudmFyIGlzQXJyYXlPclR5cGVkQXJyYXkgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheTtcbnZhciBuZXN0ZWRQcm9wZXJ0eSA9IExpYi5uZXN0ZWRQcm9wZXJ0eTtcbnZhciB2YWxPYmplY3RNZXRhID0gTGliLnZhbE9iamVjdE1ldGE7XG5cbnZhciBJU19TVUJQTE9UX09CSiA9ICdfaXNTdWJwbG90T2JqJztcbnZhciBJU19MSU5LRURfVE9fQVJSQVkgPSAnX2lzTGlua2VkVG9BcnJheSc7XG52YXIgQVJSQVlfQVRUUl9SRUdFWFBTID0gJ19hcnJheUF0dHJSZWdleHBzJztcbnZhciBERVBSRUNBVEVEID0gJ19kZXByZWNhdGVkJztcbnZhciBVTkRFUlNDT1JFX0FUVFJTID0gW0lTX1NVQlBMT1RfT0JKLCBJU19MSU5LRURfVE9fQVJSQVksIEFSUkFZX0FUVFJfUkVHRVhQUywgREVQUkVDQVRFRF07XG5cbmV4cG9ydHMuSVNfU1VCUExPVF9PQkogPSBJU19TVUJQTE9UX09CSjtcbmV4cG9ydHMuSVNfTElOS0VEX1RPX0FSUkFZID0gSVNfTElOS0VEX1RPX0FSUkFZO1xuZXhwb3J0cy5ERVBSRUNBVEVEID0gREVQUkVDQVRFRDtcbmV4cG9ydHMuVU5ERVJTQ09SRV9BVFRSUyA9IFVOREVSU0NPUkVfQVRUUlM7XG5cbi8qKiBPdXRwdXRzIHRoZSBmdWxsIHBsb3RseS5qcyBwbG90IHNjaGVtYVxuICpcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqICAtIGRlZnNcbiAqICAtIHRyYWNlc1xuICogIC0gbGF5b3V0XG4gKiAgLSB0cmFuc2Zvcm1zXG4gKiAgLSBmcmFtZXNcbiAqICAtIGFuaW1hdGlvbnNcbiAqICAtIGNvbmZpZ1xuICovXG5leHBvcnRzLmdldCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0cmFjZXMgPSB7fTtcblxuICAgIFJlZ2lzdHJ5LmFsbFR5cGVzLmNvbmNhdCgnYXJlYScpLmZvckVhY2goZnVuY3Rpb24odHlwZSkge1xuICAgICAgICB0cmFjZXNbdHlwZV0gPSBnZXRUcmFjZUF0dHJpYnV0ZXModHlwZSk7XG4gICAgfSk7XG5cbiAgICB2YXIgdHJhbnNmb3JtcyA9IHt9O1xuXG4gICAgT2JqZWN0LmtleXMoUmVnaXN0cnkudHJhbnNmb3Jtc1JlZ2lzdHJ5KS5mb3JFYWNoKGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgICAgdHJhbnNmb3Jtc1t0eXBlXSA9IGdldFRyYW5zZm9ybUF0dHJpYnV0ZXModHlwZSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBkZWZzOiB7XG4gICAgICAgICAgICB2YWxPYmplY3RzOiB2YWxPYmplY3RNZXRhLFxuICAgICAgICAgICAgbWV0YUtleXM6IFVOREVSU0NPUkVfQVRUUlMuY29uY2F0KFsnZGVzY3JpcHRpb24nLCAncm9sZScsICdlZGl0VHlwZScsICdpbXBsaWVkRWRpdHMnXSksXG4gICAgICAgICAgICBlZGl0VHlwZToge1xuICAgICAgICAgICAgICAgIHRyYWNlczogZWRpdFR5cGVzLnRyYWNlcyxcbiAgICAgICAgICAgICAgICBsYXlvdXQ6IGVkaXRUeXBlcy5sYXlvdXRcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbXBsaWVkRWRpdHM6IHtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICB0cmFjZXM6IHRyYWNlcyxcbiAgICAgICAgbGF5b3V0OiBnZXRMYXlvdXRBdHRyaWJ1dGVzKCksXG5cbiAgICAgICAgdHJhbnNmb3JtczogdHJhbnNmb3JtcyxcblxuICAgICAgICBmcmFtZXM6IGdldEZyYW1lc0F0dHJpYnV0ZXMoKSxcbiAgICAgICAgYW5pbWF0aW9uOiBmb3JtYXRBdHRyaWJ1dGVzKGFuaW1hdGlvbkF0dHJpYnV0ZXMpLFxuXG4gICAgICAgIGNvbmZpZzogZm9ybWF0QXR0cmlidXRlcyhjb25maWdBdHRyaWJ1dGVzKVxuICAgIH07XG59O1xuXG4vKipcbiAqIENyYXdsIHRoZSBhdHRyaWJ1dGUgdHJlZSwgcmVjdXJzaXZlbHkgY2FsbGluZyBhIGNhbGxiYWNrIGZ1bmN0aW9uXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGF0dHJzXG4gKiAgVGhlIG5vZGUgb2YgdGhlIGF0dHJpYnV0ZSB0cmVlIChlLmcuIHRoZSByb290KSBmcm9tIHdoaWNoIHJlY3Vyc2lvbiBvcmlnaW5hdGVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICogIEEgY2FsbGJhY2sgZnVuY3Rpb24gd2l0aCB0aGUgc2lnbmF0dXJlOlxuICogICAgICAgICAgQGNhbGxiYWNrIGNhbGxiYWNrXG4gKiAgICAgICAgICBAcGFyYW0ge29iamVjdH0gYXR0ciBhbiBhdHRyaWJ1dGVcbiAqICAgICAgICAgIEBwYXJhbSB7U3RyaW5nfSBhdHRyTmFtZSBuYW1lIHN0cmluZ1xuICogICAgICAgICAgQHBhcmFtIHtvYmplY3RbXX0gYXR0cnMgYWxsIHRoZSBhdHRyaWJ1dGVzXG4gKiAgICAgICAgICBAcGFyYW0ge051bWJlcn0gbGV2ZWwgdGhlIHJlY3Vyc2lvbiBsZXZlbCwgMCBhdCB0aGUgcm9vdFxuICogICAgICAgICAgQHBhcmFtIHtTdHJpbmd9IGZ1bGxBdHRyU3RyaW5nIGZ1bGwgYXR0cmlidXRlIG5hbWUgKGllICdtYXJrZXIubGluZScpXG4gKiBAcGFyYW0ge051bWJlcn0gW3NwZWNpZmllZExldmVsXVxuICogIFRoZSBsZXZlbCBpbiB0aGUgdHJlZSwgaW4gb3JkZXIgdG8gbGV0IHRoZSBjYWxsYmFjayBmdW5jdGlvbiBkZXRlY3QgZGVzY2VuZCBvciBiYWNrdHJhY2ssXG4gKiAgdHlwaWNhbGx5IHVuc3VwcGxpZWQgKGltcGxpZWQgMCksIGp1c3QgdXNlZCBieSB0aGUgc2VsZi1yZWN1cnNpdmUgY2FsbC5cbiAqICBUaGUgbmVjZXNzaXR5IGFyaXNlcyBiZWNhdXNlIHRoZSB0cmVlIHRyYXZlcnNhbCBpcyBub3QgY29udHJvbGxlZCBieSBjYWxsYmFjayByZXR1cm4gdmFsdWVzLlxuICogIFRoZSBkZWNpc2lvbiB0byBub3QgdXNlIGNhbGxiYWNrIHJldHVybiB2YWx1ZXMgZm9yIGNvbnRyb2xsaW5nIHRyZWUgcHJ1bmluZyBhcm9zZSBmcm9tXG4gKiAgdGhlIGdvYWwgb2Yga2VlcGluZyB0aGUgY3Jhd2xlciBiYWNrd2FyZHMgY29tcGF0aWJsZS4gT2JzZXJ2ZSB0aGF0IG9uZSBvZiB0aGUgcHJ1bmluZyBjb25kaXRpb25zXG4gKiAgcHJlY2VkZXMgdGhlIGNhbGxiYWNrIGNhbGwuXG4gKiBAcGFyYW0ge3N0cmluZ30gW2F0dHJTdHJpbmddXG4gKiAgdGhlIHBhdGggdG8gdGhlIGN1cnJlbnQgYXR0cmlidXRlLCBhcyBhbiBhdHRyaWJ1dGUgc3RyaW5nIChpZSAnbWFya2VyLmxpbmUnKVxuICogIHR5cGljYWxseSB1bnN1cHBsaWVkLCBidXQgeW91IG1heSBzdXBwbHkgaXQgaWYgeW91IHdhbnQgdG8gZGlzYW1iaWd1YXRlIHdoaWNoIGF0dHJzIHRyZWUgeW91XG4gKiAgYXJlIHN0YXJ0aW5nIGZyb21cbiAqXG4gKiBAcmV0dXJuIHtvYmplY3R9IHRyYW5zZm9ybU91dFxuICogIGNvcHkgb2YgdHJhbnNmb3JtSW4gdGhhdCBjb250YWlucyBhdHRyaWJ1dGUgZGVmYXVsdHNcbiAqL1xuZXhwb3J0cy5jcmF3bCA9IGZ1bmN0aW9uKGF0dHJzLCBjYWxsYmFjaywgc3BlY2lmaWVkTGV2ZWwsIGF0dHJTdHJpbmcpIHtcbiAgICB2YXIgbGV2ZWwgPSBzcGVjaWZpZWRMZXZlbCB8fCAwO1xuICAgIGF0dHJTdHJpbmcgPSBhdHRyU3RyaW5nIHx8ICcnO1xuXG4gICAgT2JqZWN0LmtleXMoYXR0cnMpLmZvckVhY2goZnVuY3Rpb24oYXR0ck5hbWUpIHtcbiAgICAgICAgdmFyIGF0dHIgPSBhdHRyc1thdHRyTmFtZV07XG5cbiAgICAgICAgaWYoVU5ERVJTQ09SRV9BVFRSUy5pbmRleE9mKGF0dHJOYW1lKSAhPT0gLTEpIHJldHVybjtcblxuICAgICAgICB2YXIgZnVsbEF0dHJTdHJpbmcgPSAoYXR0clN0cmluZyA/IGF0dHJTdHJpbmcgKyAnLicgOiAnJykgKyBhdHRyTmFtZTtcbiAgICAgICAgY2FsbGJhY2soYXR0ciwgYXR0ck5hbWUsIGF0dHJzLCBsZXZlbCwgZnVsbEF0dHJTdHJpbmcpO1xuXG4gICAgICAgIGlmKGV4cG9ydHMuaXNWYWxPYmplY3QoYXR0cikpIHJldHVybjtcblxuICAgICAgICBpZihpc1BsYWluT2JqZWN0KGF0dHIpICYmIGF0dHJOYW1lICE9PSAnaW1wbGllZEVkaXRzJykge1xuICAgICAgICAgICAgZXhwb3J0cy5jcmF3bChhdHRyLCBjYWxsYmFjaywgbGV2ZWwgKyAxLCBmdWxsQXR0clN0cmluZyk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbi8qKiBJcyBvYmplY3QgYSB2YWx1ZSBvYmplY3QgKG9yIGEgY29udGFpbmVyIG9iamVjdCk/XG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9ialxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqICByZXR1cm5zIHRydWUgZm9yIGEgdmFsaWQgdmFsdWUgb2JqZWN0IGFuZFxuICogIGZhbHNlIGZvciB0cmVlIG5vZGVzIGluIHRoZSBhdHRyaWJ1dGUgaGllcmFyY2h5XG4gKi9cbmV4cG9ydHMuaXNWYWxPYmplY3QgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqICYmIG9iai52YWxUeXBlICE9PSB1bmRlZmluZWQ7XG59O1xuXG4vKipcbiAqIEZpbmQgYWxsIGRhdGEgYXJyYXkgYXR0cmlidXRlcyBpbiBhIGdpdmVuIHRyYWNlIG9iamVjdCAtIGluY2x1ZGluZ1xuICogYGFycmF5T2tgIGF0dHJpYnV0ZXMuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlXG4gKiAgZnVsbCB0cmFjZSBvYmplY3QgdGhhdCBjb250YWlucyBhIHJlZmVyZW5jZSB0byBgX21vZHVsZS5hdHRyaWJ1dGVzYFxuICpcbiAqIEByZXR1cm4ge2FycmF5fSBhcnJheUF0dHJpYnV0ZXNcbiAqICBsaXN0IG9mIGFycmF5IGF0dHJpYnV0ZXMgZm9yIHRoZSBnaXZlbiB0cmFjZVxuICovXG5leHBvcnRzLmZpbmRBcnJheUF0dHJpYnV0ZXMgPSBmdW5jdGlvbih0cmFjZSkge1xuICAgIHZhciBhcnJheUF0dHJpYnV0ZXMgPSBbXTtcbiAgICB2YXIgc3RhY2sgPSBbXTtcbiAgICB2YXIgaXNBcnJheVN0YWNrID0gW107XG4gICAgdmFyIGJhc2VDb250YWluZXIsIGJhc2VBdHRyTmFtZTtcblxuICAgIGZ1bmN0aW9uIGNhbGxiYWNrKGF0dHIsIGF0dHJOYW1lLCBhdHRycywgbGV2ZWwpIHtcbiAgICAgICAgc3RhY2sgPSBzdGFjay5zbGljZSgwLCBsZXZlbCkuY29uY2F0KFthdHRyTmFtZV0pO1xuICAgICAgICBpc0FycmF5U3RhY2sgPSBpc0FycmF5U3RhY2suc2xpY2UoMCwgbGV2ZWwpLmNvbmNhdChbYXR0ciAmJiBhdHRyLl9pc0xpbmtlZFRvQXJyYXldKTtcblxuICAgICAgICB2YXIgc3BsaXR0YWJsZUF0dHIgPSAoXG4gICAgICAgICAgICBhdHRyICYmXG4gICAgICAgICAgICAoYXR0ci52YWxUeXBlID09PSAnZGF0YV9hcnJheScgfHwgYXR0ci5hcnJheU9rID09PSB0cnVlKSAmJlxuICAgICAgICAgICAgIShzdGFja1tsZXZlbCAtIDFdID09PSAnY29sb3JiYXInICYmIChhdHRyTmFtZSA9PT0gJ3RpY2t0ZXh0JyB8fCBhdHRyTmFtZSA9PT0gJ3RpY2t2YWxzJykpXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gTWFudWFsbHkgZXhjbHVkZSAnY29sb3JiYXIudGlja3ZhbHMnIGFuZCAnY29sb3JiYXIudGlja3RleHQnIGZvciBub3dcbiAgICAgICAgLy8gd2hpY2ggYXJlIGRlY2xhcmVkIGFzIGB2YWxUeXBlOiAnZGF0YV9hcnJheSdgIGJ1dCBzY2FsZSBpbmRlcGVuZGVudGx5IG9mXG4gICAgICAgIC8vIHRoZSBjb29yZGluYXRlIGFycmF5cy5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gRG93biB0aGUgcm9hZCwgd2UgbWlnaHQgd2FudCB0byBhZGQgYSBzY2hlbWEgZmllbGQgKGUuZyBgdW5jb3JyZWxhdGVkQXJyYXk6IHRydWVgKVxuICAgICAgICAvLyB0byBkaXN0aW5ndWlzaCBhdHRyaWJ1dGVzIG9mIHRoZSBsaWtlcy5cblxuICAgICAgICBpZighc3BsaXR0YWJsZUF0dHIpIHJldHVybjtcblxuICAgICAgICBjcmF3bEludG9UcmFjZShiYXNlQ29udGFpbmVyLCAwLCAnJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3Jhd2xJbnRvVHJhY2UoY29udGFpbmVyLCBpLCBhc3RyUGFydGlhbCkge1xuICAgICAgICB2YXIgaXRlbSA9IGNvbnRhaW5lcltzdGFja1tpXV07XG4gICAgICAgIHZhciBuZXdBc3RyUGFydGlhbCA9IGFzdHJQYXJ0aWFsICsgc3RhY2tbaV07XG4gICAgICAgIGlmKGkgPT09IHN0YWNrLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIGlmKGlzQXJyYXlPclR5cGVkQXJyYXkoaXRlbSkpIHtcbiAgICAgICAgICAgICAgICBhcnJheUF0dHJpYnV0ZXMucHVzaChiYXNlQXR0ck5hbWUgKyBuZXdBc3RyUGFydGlhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZihpc0FycmF5U3RhY2tbaV0pIHtcbiAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KGl0ZW0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBpdGVtLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihpc1BsYWluT2JqZWN0KGl0ZW1bal0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3Jhd2xJbnRvVHJhY2UoaXRlbVtqXSwgaSArIDEsIG5ld0FzdHJQYXJ0aWFsICsgJ1snICsgaiArICddLicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmKGlzUGxhaW5PYmplY3QoaXRlbSkpIHtcbiAgICAgICAgICAgICAgICBjcmF3bEludG9UcmFjZShpdGVtLCBpICsgMSwgbmV3QXN0clBhcnRpYWwgKyAnLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgYmFzZUNvbnRhaW5lciA9IHRyYWNlO1xuICAgIGJhc2VBdHRyTmFtZSA9ICcnO1xuICAgIGV4cG9ydHMuY3Jhd2woYmFzZUF0dHJpYnV0ZXMsIGNhbGxiYWNrKTtcbiAgICBpZih0cmFjZS5fbW9kdWxlICYmIHRyYWNlLl9tb2R1bGUuYXR0cmlidXRlcykge1xuICAgICAgICBleHBvcnRzLmNyYXdsKHRyYWNlLl9tb2R1bGUuYXR0cmlidXRlcywgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIHZhciB0cmFuc2Zvcm1zID0gdHJhY2UudHJhbnNmb3JtcztcbiAgICBpZih0cmFuc2Zvcm1zKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0cmFuc2Zvcm1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHJhbnNmb3JtID0gdHJhbnNmb3Jtc1tpXTtcbiAgICAgICAgICAgIHZhciBtb2R1bGUgPSB0cmFuc2Zvcm0uX21vZHVsZTtcblxuICAgICAgICAgICAgaWYobW9kdWxlKSB7XG4gICAgICAgICAgICAgICAgYmFzZUF0dHJOYW1lID0gJ3RyYW5zZm9ybXNbJyArIGkgKyAnXS4nO1xuICAgICAgICAgICAgICAgIGJhc2VDb250YWluZXIgPSB0cmFuc2Zvcm07XG5cbiAgICAgICAgICAgICAgICBleHBvcnRzLmNyYXdsKG1vZHVsZS5hdHRyaWJ1dGVzLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYXJyYXlBdHRyaWJ1dGVzO1xufTtcblxuLypcbiAqIEZpbmQgdGhlIHZhbE9iamVjdCBmb3Igb25lIGF0dHJpYnV0ZSBpbiBhbiBleGlzdGluZyB0cmFjZVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFjZVxuICogIGZ1bGwgdHJhY2Ugb2JqZWN0IHRoYXQgY29udGFpbnMgYSByZWZlcmVuY2UgdG8gYF9tb2R1bGUuYXR0cmlidXRlc2BcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYXJ0c1xuICogIGFuIGFycmF5IG9mIHBhcnRzLCBsaWtlIFsndHJhbnNmb3JtcycsIDEsICd2YWx1ZSddXG4gKiAgdHlwaWNhbGx5IGZyb20gbmVzdGVkUHJvcGVydHkoLi4uKS5wYXJ0c1xuICpcbiAqIEByZXR1cm4ge29iamVjdHxmYWxzZX1cbiAqICB0aGUgdmFsT2JqZWN0IGZvciB0aGlzIGF0dHJpYnV0ZSwgb3IgdGhlIGxhc3QgZm91bmQgcGFyZW50XG4gKiAgaW4gc29tZSBjYXNlcyB0aGUgaW5uZXJtb3N0IHZhbE9iamVjdCB3aWxsIG5vdCBleGlzdCwgZm9yIGV4YW1wbGVcbiAqICBgdmFsVHlwZTogJ2FueSdgIGF0dHJpYnV0ZXMgd2hlcmUgd2UgbWlnaHQgc2V0IGEgcGFydCBvZiB0aGUgYXR0cmlidXRlLlxuICogIEluIHRoYXQgY2FzZSwgc3RvcCBhdCB0aGUgZGVlcGVzdCB2YWxPYmplY3Qgd2UgKmRvKiBmaW5kLlxuICovXG5leHBvcnRzLmdldFRyYWNlVmFsT2JqZWN0ID0gZnVuY3Rpb24odHJhY2UsIHBhcnRzKSB7XG4gICAgdmFyIGhlYWQgPSBwYXJ0c1swXTtcbiAgICB2YXIgaSA9IDE7IC8vIGluZGV4IHRvIHN0YXJ0IHJlY3Vyc2luZyBmcm9tXG4gICAgdmFyIG1vZHVsZUF0dHJzLCB2YWxPYmplY3Q7XG5cbiAgICBpZihoZWFkID09PSAndHJhbnNmb3JtcycpIHtcbiAgICAgICAgaWYocGFydHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gYmFzZUF0dHJpYnV0ZXMudHJhbnNmb3JtcztcbiAgICAgICAgfVxuICAgICAgICB2YXIgdHJhbnNmb3JtcyA9IHRyYWNlLnRyYW5zZm9ybXM7XG4gICAgICAgIGlmKCFBcnJheS5pc0FycmF5KHRyYW5zZm9ybXMpIHx8ICF0cmFuc2Zvcm1zLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB2YXIgdE51bSA9IHBhcnRzWzFdO1xuICAgICAgICBpZighaXNJbmRleCh0TnVtKSB8fCB0TnVtID49IHRyYW5zZm9ybXMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgbW9kdWxlQXR0cnMgPSAoUmVnaXN0cnkudHJhbnNmb3Jtc1JlZ2lzdHJ5W3RyYW5zZm9ybXNbdE51bV0udHlwZV0gfHwge30pLmF0dHJpYnV0ZXM7XG4gICAgICAgIHZhbE9iamVjdCA9IG1vZHVsZUF0dHJzICYmIG1vZHVsZUF0dHJzW3BhcnRzWzJdXTtcbiAgICAgICAgaSA9IDM7IC8vIHN0YXJ0IHJlY3Vyc2luZyBvbmx5IGluc2lkZSB0aGUgdHJhbnNmb3JtXG4gICAgfSBlbHNlIGlmKHRyYWNlLnR5cGUgPT09ICdhcmVhJykge1xuICAgICAgICB2YWxPYmplY3QgPSBwb2xhckFyZWFBdHRyc1toZWFkXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBmaXJzdCBsb29rIGluIHRoZSBtb2R1bGUgZm9yIHRoaXMgdHJhY2VcbiAgICAgICAgLy8gY29tcG9uZW50cyBoYXZlIGFscmVhZHkgbWVyZ2VkIHRoZWlyIHRyYWNlIGF0dHJpYnV0ZXMgaW4gaGVyZVxuICAgICAgICB2YXIgX21vZHVsZSA9IHRyYWNlLl9tb2R1bGU7XG4gICAgICAgIGlmKCFfbW9kdWxlKSBfbW9kdWxlID0gKFJlZ2lzdHJ5Lm1vZHVsZXNbdHJhY2UudHlwZSB8fCBiYXNlQXR0cmlidXRlcy50eXBlLmRmbHRdIHx8IHt9KS5fbW9kdWxlO1xuICAgICAgICBpZighX21vZHVsZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIG1vZHVsZUF0dHJzID0gX21vZHVsZS5hdHRyaWJ1dGVzO1xuICAgICAgICB2YWxPYmplY3QgPSBtb2R1bGVBdHRycyAmJiBtb2R1bGVBdHRyc1toZWFkXTtcblxuICAgICAgICAvLyB0aGVuIGxvb2sgaW4gdGhlIHN1YnBsb3QgYXR0cmlidXRlc1xuICAgICAgICBpZighdmFsT2JqZWN0KSB7XG4gICAgICAgICAgICB2YXIgc3VicGxvdE1vZHVsZSA9IF9tb2R1bGUuYmFzZVBsb3RNb2R1bGU7XG4gICAgICAgICAgICBpZihzdWJwbG90TW9kdWxlICYmIHN1YnBsb3RNb2R1bGUuYXR0cmlidXRlcykge1xuICAgICAgICAgICAgICAgIHZhbE9iamVjdCA9IHN1YnBsb3RNb2R1bGUuYXR0cmlidXRlc1toZWFkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGZpbmFsbHkgbG9vayBpbiB0aGUgZ2xvYmFsIGF0dHJpYnV0ZXNcbiAgICAgICAgaWYoIXZhbE9iamVjdCkgdmFsT2JqZWN0ID0gYmFzZUF0dHJpYnV0ZXNbaGVhZF07XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlY3Vyc2VJbnRvVmFsT2JqZWN0KHZhbE9iamVjdCwgcGFydHMsIGkpO1xufTtcblxuLypcbiAqIEZpbmQgdGhlIHZhbE9iamVjdCBmb3Igb25lIGxheW91dCBhdHRyaWJ1dGVcbiAqXG4gKiBAcGFyYW0ge2FycmF5fSBwYXJ0c1xuICogIGFuIGFycmF5IG9mIHBhcnRzLCBsaWtlIFsnYW5ub3RhdGlvbnMnLCAxLCAneCddXG4gKiAgdHlwaWNhbGx5IGZyb20gbmVzdGVkUHJvcGVydHkoLi4uKS5wYXJ0c1xuICpcbiAqIEByZXR1cm4ge29iamVjdHxmYWxzZX1cbiAqICB0aGUgdmFsT2JqZWN0IGZvciB0aGlzIGF0dHJpYnV0ZSwgb3IgdGhlIGxhc3QgZm91bmQgcGFyZW50XG4gKiAgaW4gc29tZSBjYXNlcyB0aGUgaW5uZXJtb3N0IHZhbE9iamVjdCB3aWxsIG5vdCBleGlzdCwgZm9yIGV4YW1wbGVcbiAqICBgdmFsVHlwZTogJ2FueSdgIGF0dHJpYnV0ZXMgd2hlcmUgd2UgbWlnaHQgc2V0IGEgcGFydCBvZiB0aGUgYXR0cmlidXRlLlxuICogIEluIHRoYXQgY2FzZSwgc3RvcCBhdCB0aGUgZGVlcGVzdCB2YWxPYmplY3Qgd2UgKmRvKiBmaW5kLlxuICovXG5leHBvcnRzLmdldExheW91dFZhbE9iamVjdCA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBhcnRzKSB7XG4gICAgdmFyIHZhbE9iamVjdCA9IGxheW91dEhlYWRBdHRyKGZ1bGxMYXlvdXQsIHBhcnRzWzBdKTtcblxuICAgIHJldHVybiByZWN1cnNlSW50b1ZhbE9iamVjdCh2YWxPYmplY3QsIHBhcnRzLCAxKTtcbn07XG5cbmZ1bmN0aW9uIGxheW91dEhlYWRBdHRyKGZ1bGxMYXlvdXQsIGhlYWQpIHtcbiAgICB2YXIgaSwga2V5LCBfbW9kdWxlLCBhdHRyaWJ1dGVzO1xuXG4gICAgLy8gbG9vayBmb3IgYXR0cmlidXRlcyBvZiB0aGUgc3VicGxvdCB0eXBlcyB1c2VkIG9uIHRoZSBwbG90XG4gICAgdmFyIGJhc2VQbG90TW9kdWxlcyA9IGZ1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcztcbiAgICBpZihiYXNlUGxvdE1vZHVsZXMpIHtcbiAgICAgICAgdmFyIG91dDtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBfbW9kdWxlID0gYmFzZVBsb3RNb2R1bGVzW2ldO1xuICAgICAgICAgICAgaWYoX21vZHVsZS5hdHRyUmVnZXggJiYgX21vZHVsZS5hdHRyUmVnZXgudGVzdChoZWFkKSkge1xuICAgICAgICAgICAgICAgIC8vIGlmIGEgbW9kdWxlIGRlZmluZXMgb3ZlcnJpZGVzLCB0aGVzZSB0YWtlIHByZWNlZGVuY2VcbiAgICAgICAgICAgICAgICAvLyBpbml0aWFsbHkgdGhpcyBpcyB0byBhbGxvdyBnbDJkIGRpZmZlcmVudCBlZGl0VHlwZXMgZnJvbSBzdmcgY2FydGVzaWFuXG4gICAgICAgICAgICAgICAgaWYoX21vZHVsZS5sYXlvdXRBdHRyT3ZlcnJpZGVzKSByZXR1cm4gX21vZHVsZS5sYXlvdXRBdHRyT3ZlcnJpZGVzO1xuXG4gICAgICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIHRha2UgdGhlIGZpcnN0IGF0dHJpYnV0ZXMgd2UgZmluZFxuICAgICAgICAgICAgICAgIGlmKCFvdXQgJiYgX21vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzKSBvdXQgPSBfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGEgbW9kdWxlIGNhbiBhbHNvIG92ZXJyaWRlIHRoZSBiZWhhdmlvciBvZiBiYXNlIChhbmQgY29tcG9uZW50KSBtb2R1bGUgbGF5b3V0IGF0dHJzXG4gICAgICAgICAgICAvLyBhZ2FpbiBzZWUgZ2wyZCBmb3IgaW5pdGlhbCB1c2UgY2FzZVxuICAgICAgICAgICAgdmFyIGJhc2VPdmVycmlkZXMgPSBfbW9kdWxlLmJhc2VMYXlvdXRBdHRyT3ZlcnJpZGVzO1xuICAgICAgICAgICAgaWYoYmFzZU92ZXJyaWRlcyAmJiBoZWFkIGluIGJhc2VPdmVycmlkZXMpIHJldHVybiBiYXNlT3ZlcnJpZGVzW2hlYWRdO1xuICAgICAgICB9XG4gICAgICAgIGlmKG91dCkgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICAvLyBsb29rIGZvciBsYXlvdXQgYXR0cmlidXRlcyBjb250cmlidXRlZCBieSB0cmFjZXMgb24gdGhlIHBsb3RcbiAgICB2YXIgbW9kdWxlcyA9IGZ1bGxMYXlvdXQuX21vZHVsZXM7XG4gICAgaWYobW9kdWxlcykge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBtb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBhdHRyaWJ1dGVzID0gbW9kdWxlc1tpXS5sYXlvdXRBdHRyaWJ1dGVzO1xuICAgICAgICAgICAgaWYoYXR0cmlidXRlcyAmJiBoZWFkIGluIGF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXR0cmlidXRlc1toZWFkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qXG4gICAgICogTmV4dCBsb29rIGluIGNvbXBvbmVudHMuXG4gICAgICogQ29tcG9uZW50cyB0aGF0IGRlZmluZSBhIHNjaGVtYSBoYXZlIGFscmVhZHkgbWVyZ2VkIHRoaXMgaW50b1xuICAgICAqIGJhc2UgYW5kIHN1YnBsb3QgYXR0cmlidXRlIGRlZnMsIHNvIGlnbm9yZSB0aGVzZS5cbiAgICAgKiBPdGhlcnMgKG9sZGVyIHN0eWxlKSBhbGwgcHV0IGFsbCB0aGVpciBhdHRyaWJ1dGVzXG4gICAgICogaW5zaWRlIGEgY29udGFpbmVyIG1hdGNoaW5nIHRoZSBtb2R1bGUgYG5hbWVgXG4gICAgICogZWcgYGF0dHJpYnV0ZXNgIChhcnJheSkgb3IgYGxlZ2VuZGAgKG9iamVjdClcbiAgICAgKi9cbiAgICBmb3Ioa2V5IGluIFJlZ2lzdHJ5LmNvbXBvbmVudHNSZWdpc3RyeSkge1xuICAgICAgICBfbW9kdWxlID0gUmVnaXN0cnkuY29tcG9uZW50c1JlZ2lzdHJ5W2tleV07XG4gICAgICAgIGlmKF9tb2R1bGUubmFtZSA9PT0gJ2NvbG9yc2NhbGUnICYmIGhlYWQuaW5kZXhPZignY29sb3JheGlzJykgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXNbaGVhZF07XG4gICAgICAgIH0gZWxzZSBpZighX21vZHVsZS5zY2hlbWEgJiYgKGhlYWQgPT09IF9tb2R1bGUubmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihoZWFkIGluIGJhc2VMYXlvdXRBdHRyaWJ1dGVzKSByZXR1cm4gYmFzZUxheW91dEF0dHJpYnV0ZXNbaGVhZF07XG5cbiAgICAvLyBQb2xhciBkb2Vzbid0IHBvcHVsYXRlIF9tb2R1bGVzIG9yIF9iYXNlUGxvdE1vZHVsZXNcbiAgICAvLyBqdXN0IGZhbGwgYmFjayBvbiB0aGVzZSB3aGVuIHRoZSBvdGhlcnMgZmFpbFxuICAgIGlmKGhlYWQgPT09ICdyYWRpYWxheGlzJyB8fCBoZWFkID09PSAnYW5ndWxhcmF4aXMnKSB7XG4gICAgICAgIHJldHVybiBwb2xhckF4aXNBdHRyc1toZWFkXTtcbiAgICB9XG4gICAgcmV0dXJuIHBvbGFyQXhpc0F0dHJzLmxheW91dFtoZWFkXSB8fCBmYWxzZTtcbn1cblxuZnVuY3Rpb24gcmVjdXJzZUludG9WYWxPYmplY3QodmFsT2JqZWN0LCBwYXJ0cywgaSkge1xuICAgIGlmKCF2YWxPYmplY3QpIHJldHVybiBmYWxzZTtcblxuICAgIGlmKHZhbE9iamVjdC5faXNMaW5rZWRUb0FycmF5KSB7XG4gICAgICAgIC8vIHNraXAgYXJyYXkgaW5kZXgsIGFib3J0IGlmIHdlIHRyeSB0byBkaXZlIGludG8gYW4gYXJyYXkgd2l0aG91dCBhbiBpbmRleFxuICAgICAgICBpZihpc0luZGV4KHBhcnRzW2ldKSkgaSsrO1xuICAgICAgICBlbHNlIGlmKGkgPCBwYXJ0cy5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBub3cgcmVjdXJzZSBhcyBmYXIgYXMgd2UgY2FuLiBPY2Nhc2lvbmFsbHkgd2UgaGF2ZSBhbiBhdHRyaWJ1dGVcbiAgICAvLyBzZXR0aW5nIGFuIGludGVybmFsIHBhcnQgYmVsb3cgd2hhdCdzIGluIHRoZSBzY2hlbWE7IGp1c3QgcmV0dXJuXG4gICAgLy8gdGhlIGlubmVybW9zdCBzY2hlbWEgaXRlbSB3ZSBmaW5kLlxuICAgIGZvcig7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbmV3VmFsT2JqZWN0ID0gdmFsT2JqZWN0W3BhcnRzW2ldXTtcbiAgICAgICAgaWYoaXNQbGFpbk9iamVjdChuZXdWYWxPYmplY3QpKSB2YWxPYmplY3QgPSBuZXdWYWxPYmplY3Q7XG4gICAgICAgIGVsc2UgYnJlYWs7XG5cbiAgICAgICAgaWYoaSA9PT0gcGFydHMubGVuZ3RoIC0gMSkgYnJlYWs7XG5cbiAgICAgICAgaWYodmFsT2JqZWN0Ll9pc0xpbmtlZFRvQXJyYXkpIHtcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIGlmKCFpc0luZGV4KHBhcnRzW2ldKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGVsc2UgaWYodmFsT2JqZWN0LnZhbFR5cGUgPT09ICdpbmZvX2FycmF5Jykge1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gcGFydHNbaV07XG4gICAgICAgICAgICBpZighaXNJbmRleChpbmRleCkpIHJldHVybiBmYWxzZTtcblxuICAgICAgICAgICAgdmFyIGl0ZW1zID0gdmFsT2JqZWN0Lml0ZW1zO1xuICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShpdGVtcykpIHtcbiAgICAgICAgICAgICAgICBpZihpbmRleCA+PSBpdGVtcy5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZih2YWxPYmplY3QuZGltZW5zaW9ucyA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICAgICAgICAgIGlmKHBhcnRzLmxlbmd0aCA9PT0gaSkgcmV0dXJuIHZhbE9iamVjdDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGluZGV4MiA9IHBhcnRzW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZighaXNJbmRleChpbmRleDIpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHZhbE9iamVjdCA9IGl0ZW1zW2luZGV4XVtpbmRleDJdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB2YWxPYmplY3QgPSBpdGVtc1tpbmRleF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhbE9iamVjdCA9IGl0ZW1zO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbE9iamVjdDtcbn1cblxuLy8gbm90ZTogdGhpcyBpcyBkaWZmZXJlbnQgZnJvbSBMaWIuaXNJbmRleCwgdGhpcyBvbmUgZG9lc24ndCBhY2NlcHQgbnVtZXJpY1xuLy8gc3RyaW5ncywgb25seSBhY3R1YWwgbnVtYmVycy5cbmZ1bmN0aW9uIGlzSW5kZXgodmFsKSB7XG4gICAgcmV0dXJuIHZhbCA9PT0gTWF0aC5yb3VuZCh2YWwpICYmIHZhbCA+PSAwO1xufVxuXG5mdW5jdGlvbiBnZXRUcmFjZUF0dHJpYnV0ZXModHlwZSkge1xuICAgIHZhciBfbW9kdWxlLCBiYXNlUGxvdE1vZHVsZTtcblxuICAgIGlmKHR5cGUgPT09ICdhcmVhJykge1xuICAgICAgICBfbW9kdWxlID0geyBhdHRyaWJ1dGVzOiBwb2xhckFyZWFBdHRycyB9O1xuICAgICAgICBiYXNlUGxvdE1vZHVsZSA9IHt9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIF9tb2R1bGUgPSBSZWdpc3RyeS5tb2R1bGVzW3R5cGVdLl9tb2R1bGUsXG4gICAgICAgIGJhc2VQbG90TW9kdWxlID0gX21vZHVsZS5iYXNlUGxvdE1vZHVsZTtcbiAgICB9XG5cbiAgICB2YXIgYXR0cmlidXRlcyA9IHt9O1xuXG4gICAgLy8gbWFrZSAndHlwZScgdGhlIGZpcnN0IGF0dHJpYnV0ZSBpbiB0aGUgb2JqZWN0XG4gICAgYXR0cmlidXRlcy50eXBlID0gbnVsbDtcblxuICAgIHZhciBjb3B5QmFzZUF0dHJpYnV0ZXMgPSBleHRlbmREZWVwQWxsKHt9LCBiYXNlQXR0cmlidXRlcyk7XG4gICAgdmFyIGNvcHlNb2R1bGVBdHRyaWJ1dGVzID0gZXh0ZW5kRGVlcEFsbCh7fSwgX21vZHVsZS5hdHRyaWJ1dGVzKTtcblxuICAgIC8vIHBydW5lIGdsb2JhbC1sZXZlbCB0cmFjZSBhdHRyaWJ1dGVzIHRoYXQgYXJlIGFscmVhZHkgZGVmaW5lZCBpbiBhIHRyYWNlXG4gICAgZXhwb3J0cy5jcmF3bChjb3B5TW9kdWxlQXR0cmlidXRlcywgZnVuY3Rpb24oYXR0ciwgYXR0ck5hbWUsIGF0dHJzLCBsZXZlbCwgZnVsbEF0dHJTdHJpbmcpIHtcbiAgICAgICAgbmVzdGVkUHJvcGVydHkoY29weUJhc2VBdHRyaWJ1dGVzLCBmdWxsQXR0clN0cmluZykuc2V0KHVuZGVmaW5lZCk7XG4gICAgICAgIC8vIFBydW5lIHVuZGVmaW5lZCBhdHRyaWJ1dGVzXG4gICAgICAgIGlmKGF0dHIgPT09IHVuZGVmaW5lZCkgbmVzdGVkUHJvcGVydHkoY29weU1vZHVsZUF0dHJpYnV0ZXMsIGZ1bGxBdHRyU3RyaW5nKS5zZXQodW5kZWZpbmVkKTtcbiAgICB9KTtcblxuICAgIC8vIGJhc2UgYXR0cmlidXRlcyAoc2FtZSBmb3IgYWxsIHRyYWNlIHR5cGVzKVxuICAgIGV4dGVuZERlZXBBbGwoYXR0cmlidXRlcywgY29weUJhc2VBdHRyaWJ1dGVzKTtcblxuICAgIC8vIHBydW5lLW91dCBiYXNlIGF0dHJpYnV0ZXMgYmFzZWQgb24gdHJhY2UgbW9kdWxlIGNhdGVnb3JpZXNcbiAgICBpZihSZWdpc3RyeS50cmFjZUlzKHR5cGUsICdub09wYWNpdHknKSkge1xuICAgICAgICBkZWxldGUgYXR0cmlidXRlcy5vcGFjaXR5O1xuICAgIH1cbiAgICBpZighUmVnaXN0cnkudHJhY2VJcyh0eXBlLCAnc2hvd0xlZ2VuZCcpKSB7XG4gICAgICAgIGRlbGV0ZSBhdHRyaWJ1dGVzLnNob3dsZWdlbmQ7XG4gICAgICAgIGRlbGV0ZSBhdHRyaWJ1dGVzLmxlZ2VuZGdyb3VwO1xuICAgIH1cbiAgICBpZihSZWdpc3RyeS50cmFjZUlzKHR5cGUsICdub0hvdmVyJykpIHtcbiAgICAgICAgZGVsZXRlIGF0dHJpYnV0ZXMuaG92ZXJpbmZvO1xuICAgICAgICBkZWxldGUgYXR0cmlidXRlcy5ob3ZlcmxhYmVsO1xuICAgIH1cbiAgICBpZighX21vZHVsZS5zZWxlY3RQb2ludHMpIHtcbiAgICAgICAgZGVsZXRlIGF0dHJpYnV0ZXMuc2VsZWN0ZWRwb2ludHM7XG4gICAgfVxuXG4gICAgLy8gbW9kdWxlIGF0dHJpYnV0ZXNcbiAgICBleHRlbmREZWVwQWxsKGF0dHJpYnV0ZXMsIGNvcHlNb2R1bGVBdHRyaWJ1dGVzKTtcblxuICAgIC8vIHN1YnBsb3QgYXR0cmlidXRlc1xuICAgIGlmKGJhc2VQbG90TW9kdWxlLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgZXh0ZW5kRGVlcEFsbChhdHRyaWJ1dGVzLCBiYXNlUGxvdE1vZHVsZS5hdHRyaWJ1dGVzKTtcbiAgICB9XG5cbiAgICAvLyAndHlwZScgZ2V0cyBvdmVyd3JpdHRlbiBieSBiYXNlQXR0cmlidXRlczsgcmVzZXQgaXQgaGVyZVxuICAgIGF0dHJpYnV0ZXMudHlwZSA9IHR5cGU7XG5cbiAgICB2YXIgb3V0ID0ge1xuICAgICAgICBtZXRhOiBfbW9kdWxlLm1ldGEgfHwge30sXG4gICAgICAgIGNhdGVnb3JpZXM6IF9tb2R1bGUuY2F0ZWdvcmllcyB8fCB7fSxcbiAgICAgICAgYW5pbWF0YWJsZTogQm9vbGVhbihfbW9kdWxlLmFuaW1hdGFibGUpLFxuICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICBhdHRyaWJ1dGVzOiBmb3JtYXRBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpLFxuICAgIH07XG5cbiAgICAvLyB0cmFjZS1zcGVjaWZpYyBsYXlvdXQgYXR0cmlidXRlc1xuICAgIGlmKF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcykge1xuICAgICAgICB2YXIgbGF5b3V0QXR0cmlidXRlcyA9IHt9O1xuXG4gICAgICAgIGV4dGVuZERlZXBBbGwobGF5b3V0QXR0cmlidXRlcywgX21vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzKTtcbiAgICAgICAgb3V0LmxheW91dEF0dHJpYnV0ZXMgPSBmb3JtYXRBdHRyaWJ1dGVzKGxheW91dEF0dHJpYnV0ZXMpO1xuICAgIH1cblxuICAgIC8vIGRyb3AgYW5pbTp0cnVlIGluIG5vbi1hbmltYXRhYmxlIG1vZHVsZXNcbiAgICBpZighX21vZHVsZS5hbmltYXRhYmxlKSB7XG4gICAgICAgIGV4cG9ydHMuY3Jhd2wob3V0LCBmdW5jdGlvbihhdHRyKSB7XG4gICAgICAgICAgICBpZihleHBvcnRzLmlzVmFsT2JqZWN0KGF0dHIpICYmICdhbmltJyBpbiBhdHRyKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGF0dHIuYW5pbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gZ2V0TGF5b3V0QXR0cmlidXRlcygpIHtcbiAgICB2YXIgbGF5b3V0QXR0cmlidXRlcyA9IHt9O1xuICAgIHZhciBrZXksIF9tb2R1bGU7XG5cbiAgICAvLyBnbG9iYWwgbGF5b3V0IGF0dHJpYnV0ZXNcbiAgICBleHRlbmREZWVwQWxsKGxheW91dEF0dHJpYnV0ZXMsIGJhc2VMYXlvdXRBdHRyaWJ1dGVzKTtcblxuICAgIC8vIGFkZCBiYXNlIHBsb3QgbW9kdWxlIGxheW91dCBhdHRyaWJ1dGVzXG4gICAgZm9yKGtleSBpbiBSZWdpc3RyeS5zdWJwbG90c1JlZ2lzdHJ5KSB7XG4gICAgICAgIF9tb2R1bGUgPSBSZWdpc3RyeS5zdWJwbG90c1JlZ2lzdHJ5W2tleV07XG5cbiAgICAgICAgaWYoIV9tb2R1bGUubGF5b3V0QXR0cmlidXRlcykgY29udGludWU7XG5cbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShfbW9kdWxlLmF0dHIpKSB7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgX21vZHVsZS5hdHRyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlQmFzZVBsb3RNb2R1bGUobGF5b3V0QXR0cmlidXRlcywgX21vZHVsZSwgX21vZHVsZS5hdHRyW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBhc3RyID0gX21vZHVsZS5hdHRyID09PSAnc3VicGxvdCcgPyBfbW9kdWxlLm5hbWUgOiBfbW9kdWxlLmF0dHI7XG4gICAgICAgICAgICBoYW5kbGVCYXNlUGxvdE1vZHVsZShsYXlvdXRBdHRyaWJ1dGVzLCBfbW9kdWxlLCBhc3RyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHBvbGFyIGxheW91dCBhdHRyaWJ1dGVzXG4gICAgbGF5b3V0QXR0cmlidXRlcyA9IGFzc2lnblBvbGFyTGF5b3V0QXR0cnMobGF5b3V0QXR0cmlidXRlcyk7XG5cbiAgICAvLyBhZGQgcmVnaXN0ZXJlZCBjb21wb25lbnRzIGxheW91dCBhdHRyaWJ1dGVzXG4gICAgZm9yKGtleSBpbiBSZWdpc3RyeS5jb21wb25lbnRzUmVnaXN0cnkpIHtcbiAgICAgICAgX21vZHVsZSA9IFJlZ2lzdHJ5LmNvbXBvbmVudHNSZWdpc3RyeVtrZXldO1xuICAgICAgICB2YXIgc2NoZW1hID0gX21vZHVsZS5zY2hlbWE7XG5cbiAgICAgICAgaWYoc2NoZW1hICYmIChzY2hlbWEuc3VicGxvdHMgfHwgc2NoZW1hLmxheW91dCkpIHtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBDb21wb25lbnRzIHdpdGggZGVmaW5lZCBzY2hlbWEgaGF2ZSBhbHJlYWR5IGJlZW4gbWVyZ2VkIGluIGF0IHJlZ2lzdGVyIHRpbWVcbiAgICAgICAgICAgICAqIGJ1dCBhIGZldyBjb21wb25lbnRzIGRlZmluZSBhdHRyaWJ1dGVzIHRoYXQgYXBwbHkgb25seSB0byB4YXhpc1xuICAgICAgICAgICAgICogbm90IHlheGlzIChyYW5nZXNlbGVjdG9yLCByYW5nZXNsaWRlcikgLSBkZWxldGUgZnJvbSB5IHNjaGVtYS5cbiAgICAgICAgICAgICAqIE5vdGUgdGhhdCB0aGUgaW5wdXQgYXR0cmlidXRlcyBmb3IgeGF4aXMveWF4aXMgYXJlIHRoZSBzYW1lIG9iamVjdFxuICAgICAgICAgICAgICogc28gaXQncyBub3QgcG9zc2libGUgdG8gb25seSBhZGQgdGhlbSB0byB4YXhpcyBmcm9tIHRoZSBzdGFydC5cbiAgICAgICAgICAgICAqIElmIHdlIGV2ZXIgaGF2ZSBzdWNoIGFzeW1tZXRyeSB0aGUgb3RoZXIgd2F5LCBvciBhbnl3aGVyZSBlbHNlLFxuICAgICAgICAgICAgICogd2Ugd2lsbCBuZWVkIHRvIGV4dGVuZCBib3RoIHRoaXMgY29kZSBhbmQgbWVyZ2VDb21wb25lbnRBdHRyc1RvU3VicGxvdFxuICAgICAgICAgICAgICogKHdoaWNoIHdpbGwgbm90IGZpbmQgeWF4aXMgb25seSBmb3IgZXhhbXBsZSlcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdmFyIHN1YnBsb3RzID0gc2NoZW1hLnN1YnBsb3RzO1xuICAgICAgICAgICAgaWYoc3VicGxvdHMgJiYgc3VicGxvdHMueGF4aXMgJiYgIXN1YnBsb3RzLnlheGlzKSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciB4a2V5IGluIHN1YnBsb3RzLnhheGlzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBsYXlvdXRBdHRyaWJ1dGVzLnlheGlzW3hrZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKF9tb2R1bGUubmFtZSA9PT0gJ2NvbG9yc2NhbGUnKSB7XG4gICAgICAgICAgICBleHRlbmREZWVwQWxsKGxheW91dEF0dHJpYnV0ZXMsIF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcyk7XG4gICAgICAgIH0gZWxzZSBpZihfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICAgIC8vIG9sZGVyIHN0eWxlIHdpdGhvdXQgc2NoZW1hIG5lZWQgdG8gYmUgZXhwbGljaXRseSBtZXJnZWQgaW4gbm93XG4gICAgICAgICAgICBpbnNlcnRBdHRycyhsYXlvdXRBdHRyaWJ1dGVzLCBfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXMsIF9tb2R1bGUubmFtZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBsYXlvdXRBdHRyaWJ1dGVzOiBmb3JtYXRBdHRyaWJ1dGVzKGxheW91dEF0dHJpYnV0ZXMpXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhbnNmb3JtQXR0cmlidXRlcyh0eXBlKSB7XG4gICAgdmFyIF9tb2R1bGUgPSBSZWdpc3RyeS50cmFuc2Zvcm1zUmVnaXN0cnlbdHlwZV07XG4gICAgdmFyIGF0dHJpYnV0ZXMgPSBleHRlbmREZWVwQWxsKHt9LCBfbW9kdWxlLmF0dHJpYnV0ZXMpO1xuXG4gICAgLy8gYWRkIHJlZ2lzdGVyZWQgY29tcG9uZW50cyB0cmFuc2Zvcm0gYXR0cmlidXRlc1xuICAgIE9iamVjdC5rZXlzKFJlZ2lzdHJ5LmNvbXBvbmVudHNSZWdpc3RyeSkuZm9yRWFjaChmdW5jdGlvbihrKSB7XG4gICAgICAgIHZhciBfbW9kdWxlID0gUmVnaXN0cnkuY29tcG9uZW50c1JlZ2lzdHJ5W2tdO1xuXG4gICAgICAgIGlmKF9tb2R1bGUuc2NoZW1hICYmIF9tb2R1bGUuc2NoZW1hLnRyYW5zZm9ybXMgJiYgX21vZHVsZS5zY2hlbWEudHJhbnNmb3Jtc1t0eXBlXSkge1xuICAgICAgICAgICAgT2JqZWN0LmtleXMoX21vZHVsZS5zY2hlbWEudHJhbnNmb3Jtc1t0eXBlXSkuZm9yRWFjaChmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICAgICAgaW5zZXJ0QXR0cnMoYXR0cmlidXRlcywgX21vZHVsZS5zY2hlbWEudHJhbnNmb3Jtc1t0eXBlXVt2XSwgdik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgYXR0cmlidXRlczogZm9ybWF0QXR0cmlidXRlcyhhdHRyaWJ1dGVzKVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldEZyYW1lc0F0dHJpYnV0ZXMoKSB7XG4gICAgdmFyIGF0dHJzID0ge1xuICAgICAgICBmcmFtZXM6IGV4dGVuZERlZXBBbGwoe30sIGZyYW1lQXR0cmlidXRlcylcbiAgICB9O1xuXG4gICAgZm9ybWF0QXR0cmlidXRlcyhhdHRycyk7XG5cbiAgICByZXR1cm4gYXR0cnMuZnJhbWVzO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRBdHRyaWJ1dGVzKGF0dHJzKSB7XG4gICAgbWVyZ2VWYWxUeXBlQW5kUm9sZShhdHRycyk7XG4gICAgZm9ybWF0QXJyYXlDb250YWluZXJzKGF0dHJzKTtcbiAgICBzdHJpbmdpZnkoYXR0cnMpO1xuXG4gICAgcmV0dXJuIGF0dHJzO1xufVxuXG5mdW5jdGlvbiBtZXJnZVZhbFR5cGVBbmRSb2xlKGF0dHJzKSB7XG4gICAgZnVuY3Rpb24gbWFrZVNyY0F0dHIoYXR0ck5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnbm9uZSdcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjYWxsYmFjayhhdHRyLCBhdHRyTmFtZSwgYXR0cnMpIHtcbiAgICAgICAgaWYoZXhwb3J0cy5pc1ZhbE9iamVjdChhdHRyKSkge1xuICAgICAgICAgICAgaWYoYXR0ci52YWxUeXBlID09PSAnZGF0YV9hcnJheScpIHtcbiAgICAgICAgICAgICAgICAvLyBhbGwgJ2RhdGFfYXJyYXknIGF0dHJzIGhhdmUgcm9sZSAnZGF0YSdcbiAgICAgICAgICAgICAgICBhdHRyLnJvbGUgPSAnZGF0YSc7XG4gICAgICAgICAgICAgICAgLy8gYWxsICdkYXRhX2FycmF5JyBhdHRycyBoYXZlIGEgY29ycmVzcG9uZGluZyAnc3JjJyBhdHRyXG4gICAgICAgICAgICAgICAgYXR0cnNbYXR0ck5hbWUgKyAnc3JjJ10gPSBtYWtlU3JjQXR0cihhdHRyTmFtZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoYXR0ci5hcnJheU9rID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgLy8gYWxsICdhcnJheU9rJyBhdHRycyBoYXZlIGEgY29ycmVzcG9uZGluZyAnc3JjJyBhdHRyXG4gICAgICAgICAgICAgICAgYXR0cnNbYXR0ck5hbWUgKyAnc3JjJ10gPSBtYWtlU3JjQXR0cihhdHRyTmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihpc1BsYWluT2JqZWN0KGF0dHIpKSB7XG4gICAgICAgICAgICAvLyBhbGwgYXR0cnMgY29udGFpbmVyIG9iamVjdHMgZ2V0IHJvbGUgJ29iamVjdCdcbiAgICAgICAgICAgIGF0dHIucm9sZSA9ICdvYmplY3QnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZXhwb3J0cy5jcmF3bChhdHRycywgY2FsbGJhY2spO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRBcnJheUNvbnRhaW5lcnMoYXR0cnMpIHtcbiAgICBmdW5jdGlvbiBjYWxsYmFjayhhdHRyLCBhdHRyTmFtZSwgYXR0cnMpIHtcbiAgICAgICAgaWYoIWF0dHIpIHJldHVybjtcblxuICAgICAgICB2YXIgaXRlbU5hbWUgPSBhdHRyW0lTX0xJTktFRF9UT19BUlJBWV07XG5cbiAgICAgICAgaWYoIWl0ZW1OYW1lKSByZXR1cm47XG5cbiAgICAgICAgZGVsZXRlIGF0dHJbSVNfTElOS0VEX1RPX0FSUkFZXTtcblxuICAgICAgICBhdHRyc1thdHRyTmFtZV0gPSB7IGl0ZW1zOiB7fSB9O1xuICAgICAgICBhdHRyc1thdHRyTmFtZV0uaXRlbXNbaXRlbU5hbWVdID0gYXR0cjtcbiAgICAgICAgYXR0cnNbYXR0ck5hbWVdLnJvbGUgPSAnb2JqZWN0JztcbiAgICB9XG5cbiAgICBleHBvcnRzLmNyYXdsKGF0dHJzLCBjYWxsYmFjayk7XG59XG5cbi8vIHRoaXMgY2FuIHRha2UgYXJvdW5kIDEwbXMgYW5kIHNob3VsZCBvbmx5IGJlIHJ1biBmcm9tIFBsb3RTY2hlbWEuZ2V0KCksXG4vLyB0byBlbnN1cmUgSlNPTi5zdHJpbmdpZnkoUGxvdFNjaGVtYS5nZXQoKSkgZ2l2ZXMgdGhlIGludGVuZGVkIHJlc3VsdC5cbmZ1bmN0aW9uIHN0cmluZ2lmeShhdHRycykge1xuICAgIGZ1bmN0aW9uIHdhbGsoYXR0cikge1xuICAgICAgICBmb3IodmFyIGsgaW4gYXR0cikge1xuICAgICAgICAgICAgaWYoaXNQbGFpbk9iamVjdChhdHRyW2tdKSkge1xuICAgICAgICAgICAgICAgIHdhbGsoYXR0cltrXSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheShhdHRyW2tdKSkge1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhdHRyW2tdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHdhbGsoYXR0cltrXVtpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBhcyBKU09OLnN0cmluZ2lmeSgvdGVzdC8pIC8vID0+IHt9XG4gICAgICAgICAgICAgICAgaWYoYXR0cltrXSBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgICAgICAgICBhdHRyW2tdID0gYXR0cltrXS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdhbGsoYXR0cnMpO1xufVxuXG5mdW5jdGlvbiBhc3NpZ25Qb2xhckxheW91dEF0dHJzKGxheW91dEF0dHJpYnV0ZXMpIHtcbiAgICBleHRlbmRGbGF0KGxheW91dEF0dHJpYnV0ZXMsIHtcbiAgICAgICAgcmFkaWFsYXhpczogcG9sYXJBeGlzQXR0cnMucmFkaWFsYXhpcyxcbiAgICAgICAgYW5ndWxhcmF4aXM6IHBvbGFyQXhpc0F0dHJzLmFuZ3VsYXJheGlzXG4gICAgfSk7XG5cbiAgICBleHRlbmRGbGF0KGxheW91dEF0dHJpYnV0ZXMsIHBvbGFyQXhpc0F0dHJzLmxheW91dCk7XG5cbiAgICByZXR1cm4gbGF5b3V0QXR0cmlidXRlcztcbn1cblxuZnVuY3Rpb24gaGFuZGxlQmFzZVBsb3RNb2R1bGUobGF5b3V0QXR0cmlidXRlcywgX21vZHVsZSwgYXN0cikge1xuICAgIHZhciBucCA9IG5lc3RlZFByb3BlcnR5KGxheW91dEF0dHJpYnV0ZXMsIGFzdHIpO1xuICAgIHZhciBhdHRycyA9IGV4dGVuZERlZXBBbGwoe30sIF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcyk7XG5cbiAgICBhdHRyc1tJU19TVUJQTE9UX09CSl0gPSB0cnVlO1xuICAgIG5wLnNldChhdHRycyk7XG59XG5cbmZ1bmN0aW9uIGluc2VydEF0dHJzKGJhc2VBdHRycywgbmV3QXR0cnMsIGFzdHIpIHtcbiAgICB2YXIgbnAgPSBuZXN0ZWRQcm9wZXJ0eShiYXNlQXR0cnMsIGFzdHIpO1xuXG4gICAgbnAuc2V0KGV4dGVuZERlZXBBbGwobnAuZ2V0KCkgfHwge30sIG5ld0F0dHJzKSk7XG59XG5cbn0se1wiLi4vbGliXCI6NzE5LFwiLi4vcGxvdHMvYW5pbWF0aW9uX2F0dHJpYnV0ZXNcIjo3NjIsXCIuLi9wbG90cy9hdHRyaWJ1dGVzXCI6NzY0LFwiLi4vcGxvdHMvZnJhbWVfYXR0cmlidXRlc1wiOjc5NCxcIi4uL3Bsb3RzL2xheW91dF9hdHRyaWJ1dGVzXCI6ODE5LFwiLi4vcGxvdHMvcG9sYXIvbGVnYWN5L2FyZWFfYXR0cmlidXRlc1wiOjgzNCxcIi4uL3Bsb3RzL3BvbGFyL2xlZ2FjeS9heGlzX2F0dHJpYnV0ZXNcIjo4MzUsXCIuLi9yZWdpc3RyeVwiOjg0NyxcIi4vZWRpdF90eXBlc1wiOjc1MCxcIi4vcGxvdF9jb25maWdcIjo3NTV9XSw3NTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcbnZhciBwbG90QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcblxudmFyIFRFTVBMQVRFSVRFTU5BTUUgPSAndGVtcGxhdGVpdGVtbmFtZSc7XG5cbnZhciB0ZW1wbGF0ZUF0dHJzID0ge1xuICAgIG5hbWU6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9XG59O1xudGVtcGxhdGVBdHRyc1tURU1QTEFURUlURU1OQU1FXSA9IHtcbiAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICBcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIFxufTtcblxuLyoqXG4gKiB0ZW1wbGF0ZWRBcnJheTogZGVjb3JhdGUgYW4gYXR0cmlidXRlcyBvYmplY3Qgd2l0aCB0ZW1wbGF0aW5nIChhbmQgYXJyYXkpXG4gKiBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lOiB0aGUgc2luZ3VsYXIgZm9ybSBvZiB0aGUgYXJyYXkgbmFtZS4gU2V0c1xuICogICAgIGBfaXNMaW5rZWRUb0FycmF5YCB0byB0aGlzLCBzbyB0aGUgc2NoZW1hIGtub3dzIHRvIHRyZWF0IHRoaXMgYXMgYW4gYXJyYXkuXG4gKiBAcGFyYW0ge29iamVjdH0gYXR0cnM6IHRoZSBpdGVtIGF0dHJpYnV0ZXMuIFNpbmNlIGFsbCBjYWxsZXJzIGFyZSBleHBlY3RlZFxuICogICAgIHRvIGJlIGNvbnN0cnVjdGluZyB0aGlzIG9iamVjdCBvbiB0aGUgc3BvdCwgd2UgbXV0YXRlIGl0IGhlcmUgZm9yXG4gKiAgICAgcGVyZm9ybWFuY2UsIHJhdGhlciB0aGFuIGV4dGVuZGluZyBhIG5ldyBvYmplY3Qgd2l0aCBpdC5cbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fTogdGhlIGRlY29yYXRlZCBgYXR0cnNgIG9iamVjdFxuICovXG5leHBvcnRzLnRlbXBsYXRlZEFycmF5ID0gZnVuY3Rpb24obmFtZSwgYXR0cnMpIHtcbiAgICBhdHRycy5faXNMaW5rZWRUb0FycmF5ID0gbmFtZTtcbiAgICBhdHRycy5uYW1lID0gdGVtcGxhdGVBdHRycy5uYW1lO1xuICAgIGF0dHJzW1RFTVBMQVRFSVRFTU5BTUVdID0gdGVtcGxhdGVBdHRyc1tURU1QTEFURUlURU1OQU1FXTtcbiAgICByZXR1cm4gYXR0cnM7XG59O1xuXG4vKipcbiAqIHRyYWNlVGVtcGxhdGVyOiBsb2dpYyBmb3IgbWF0Y2hpbmcgdHJhY2VzIHRvIHRyYWNlIHRlbXBsYXRlc1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBkYXRhVGVtcGxhdGU6IGNvbGxlY3Rpb24gb2Yge3RyYWNlVHlwZTogW3t0ZW1wbGF0ZX0sIC4uLl19XG4gKiAgICAgaWUgZWFjaCB0eXBlIHRoZSB0ZW1wbGF0ZSBhcHBsaWVzIHRvIGNvbnRhaW5zIGEgbGlzdCBvZiB0ZW1wbGF0ZSBvYmplY3RzLFxuICogICAgIHRvIGJlIHByb3ZpZGVkIGN5Y2xpY2FsbHkgdG8gZGF0YSB0cmFjZXMgb2YgdGhhdCB0eXBlLlxuICpcbiAqIEByZXR1cm5zIHtvYmplY3R9OiB7bmV3VHJhY2V9LCBhIGZ1bmN0aW9uOlxuICogICAgIG5ld1RyYWNlKHRyYWNlSW4pOiB0aGF0IHRha2VzIHRoZSBpbnB1dCB0cmFjZUluLCBjb2VyY2VzIGl0cyB0eXBlLCB0aGVuXG4gKiAgICAgICAgIHVzZXMgdGhhdCB0eXBlIHRvIGZpbmQgdGhlIG5leHQgdGVtcGxhdGUgdG8gYXBwbHkuIHJldHVybnMgdGhlIG91dHB1dFxuICogICAgICAgICB0cmFjZU91dCB3aXRoIHRlbXBsYXRlIGF0dGFjaGVkLCByZWFkeSB0byBjb250aW51ZSBzdXBwbHlEZWZhdWx0cy5cbiAqL1xuZXhwb3J0cy50cmFjZVRlbXBsYXRlciA9IGZ1bmN0aW9uKGRhdGFUZW1wbGF0ZSkge1xuICAgIHZhciB0cmFjZUNvdW50cyA9IHt9O1xuICAgIHZhciB0cmFjZVR5cGUsIHR5cGVUZW1wbGF0ZXM7XG5cbiAgICBmb3IodHJhY2VUeXBlIGluIGRhdGFUZW1wbGF0ZSkge1xuICAgICAgICB0eXBlVGVtcGxhdGVzID0gZGF0YVRlbXBsYXRlW3RyYWNlVHlwZV07XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodHlwZVRlbXBsYXRlcykgJiYgdHlwZVRlbXBsYXRlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRyYWNlQ291bnRzW3RyYWNlVHlwZV0gPSAwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbmV3VHJhY2UodHJhY2VJbikge1xuICAgICAgICB0cmFjZVR5cGUgPSBMaWIuY29lcmNlKHRyYWNlSW4sIHt9LCBwbG90QXR0cmlidXRlcywgJ3R5cGUnKTtcbiAgICAgICAgdmFyIHRyYWNlT3V0ID0ge3R5cGU6IHRyYWNlVHlwZSwgX3RlbXBsYXRlOiBudWxsfTtcbiAgICAgICAgaWYodHJhY2VUeXBlIGluIHRyYWNlQ291bnRzKSB7XG4gICAgICAgICAgICB0eXBlVGVtcGxhdGVzID0gZGF0YVRlbXBsYXRlW3RyYWNlVHlwZV07XG4gICAgICAgICAgICAvLyBjeWNsZSB0aHJvdWdoIHRyYWNlcyBpbiB0aGUgdGVtcGxhdGUgc2V0IGZvciB0aGlzIHR5cGVcbiAgICAgICAgICAgIHZhciB0eXBlaSA9IHRyYWNlQ291bnRzW3RyYWNlVHlwZV0gJSB0eXBlVGVtcGxhdGVzLmxlbmd0aDtcbiAgICAgICAgICAgIHRyYWNlQ291bnRzW3RyYWNlVHlwZV0rKztcbiAgICAgICAgICAgIHRyYWNlT3V0Ll90ZW1wbGF0ZSA9IHR5cGVUZW1wbGF0ZXNbdHlwZWldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVE9ETzogYW55dGhpbmcgd2Ugc2hvdWxkIGRvIGZvciB0eXBlcyBtaXNzaW5nIGZyb20gdGhlIHRlbXBsYXRlP1xuICAgICAgICAgICAgLy8gdHJ5IHRvIGFwcGx5IHNvbWUgb3RoZXIgdHlwZT8gT3IganVzdCBiYWlsIGFzIHdlIGRvIGhlcmU/XG4gICAgICAgICAgICAvLyBBY3R1YWxseSBJIHRoaW5rIHllcywgd2Ugc2hvdWxkIGFwcGx5IG90aGVyIHR5cGVzOyB3b3VsZCBiZSBuaWNlXG4gICAgICAgICAgICAvLyBpZiBhbGwgc2NhdHRlciogY291bGQgaW5oZXJpdCBmcm9tIGVhY2ggb3RoZXIsIGFuZCBpZiBoaXN0b2dyYW1cbiAgICAgICAgICAgIC8vIGNvdWxkIGluaGVyaXQgZnJvbSBiYXIsIGV0Yy4uLiBidXQgaG93IHRvIHNwZWNpZnkgdGhpcz8gQW5kIGRvIHdlXG4gICAgICAgICAgICAvLyBjb21wb3NlIHRoZW0sIG9yIGlmIGEgdHlwZSBpcyBwcmVzZW50IHJlcXVpcmUgaXQgdG8gYmUgY29tcGxldGU/XG4gICAgICAgICAgICAvLyBBY3R1YWxseSB0aGlzIGNvdWxkIGFwcGx5IHRvIGxheW91dCB0b28gLSAzRCBhbm5vdGF0aW9uc1xuICAgICAgICAgICAgLy8gaW5oZXJpdGluZyBmcm9tIDJELCBheGVzIG9mIGRpZmZlcmVudCB0eXBlcyBpbmhlcml0aW5nIGZyb20gZWFjaFxuICAgICAgICAgICAgLy8gb3RoZXIuLi5cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJhY2VPdXQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgbmV3VHJhY2U6IG5ld1RyYWNlXG4gICAgICAgIC8vIFRPRE86IGZ1bmN0aW9uIHRvIGZpZ3VyZSBvdXQgd2hhdCdzIGxlZnQgJiB3aGF0IGRpZG4ndCB3b3JrXG4gICAgfTtcbn07XG5cbi8qKlxuICogbmV3Q29udGFpbmVyOiBDcmVhdGUgYSBuZXcgc3ViLWNvbnRhaW5lciBpbnNpZGUgYGNvbnRhaW5lcmAgYW5kIHByb3BhZ2F0ZSBhbnlcbiAqIGFwcGxpY2FibGUgdGVtcGxhdGUgdG8gaXQuIElmIHRoZXJlJ3Mgbm8gdGVtcGxhdGUsIHN0aWxsIHByb3BhZ2F0ZXNcbiAqIGB1bmRlZmluZWRgIHNvIHJlbGlua1ByaXZhdGUgd2lsbCBub3QgcmV0YWluIGFuIG9sZCB0ZW1wbGF0ZSFcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gY29udGFpbmVyOiB0aGUgb3V0ZXIgY29udGFpbmVyLCBzaG91bGQgYWxyZWFkeSBoYXZlIF90ZW1wbGF0ZVxuICogICAgIGlmIHRoZXJlICppcyogYSB0ZW1wbGF0ZSBmb3IgdGhpcyBwbG90XG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZTogdGhlIGtleSBvZiB0aGUgbmV3IGNvbnRhaW5lciB0byBtYWtlXG4gKiBAcGFyYW0ge3N0cmluZ30gYmFzZU5hbWU6IGlmIGFwcGxpY2FibGUsIGEgYmFzZSBhdHRyaWJ1dGUgdG8gdGFrZSB0aGVcbiAqICAgICB0ZW1wbGF0ZSBmcm9tLCBpZSBmb3IgeGF4aXMzIHRoZSBiYXNlIHdvdWxkIGJlIHhheGlzXG4gKlxuICogQHJldHVybnMge29iamVjdH06IGFuIG9iamVjdCBmb3IgaW5jbHVzaW9uIF9mdWxsKiwgZW1wdHkgZXhjZXB0IGZvciB0aGVcbiAqICAgICBhcHByb3ByaWF0ZSB0ZW1wbGF0ZSBwaWVjZVxuICovXG5leHBvcnRzLm5ld0NvbnRhaW5lciA9IGZ1bmN0aW9uKGNvbnRhaW5lciwgbmFtZSwgYmFzZU5hbWUpIHtcbiAgICB2YXIgdGVtcGxhdGUgPSBjb250YWluZXIuX3RlbXBsYXRlO1xuICAgIHZhciBwYXJ0ID0gdGVtcGxhdGUgJiYgKHRlbXBsYXRlW25hbWVdIHx8IChiYXNlTmFtZSAmJiB0ZW1wbGF0ZVtiYXNlTmFtZV0pKTtcbiAgICBpZighTGliLmlzUGxhaW5PYmplY3QocGFydCkpIHBhcnQgPSBudWxsO1xuXG4gICAgdmFyIG91dCA9IGNvbnRhaW5lcltuYW1lXSA9IHtfdGVtcGxhdGU6IHBhcnR9O1xuICAgIHJldHVybiBvdXQ7XG59O1xuXG4vKipcbiAqIGFycmF5VGVtcGxhdGVyOiBzcGVjaWFsIGxvZ2ljIGZvciB0ZW1wbGF0aW5nIGJvdGggZGVmYXVsdHMgYW5kIHNwZWNpZmljIGl0ZW1zXG4gKiBpbiBhIGNvbnRhaW5lciBhcnJheSAoYW5ub3RhdGlvbnMgZXRjKVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb250YWluZXI6IHRoZSBvdXRlciBjb250YWluZXIsIHNob3VsZCBhbHJlYWR5IGhhdmUgX3RlbXBsYXRlXG4gKiAgICAgaWYgdGhlcmUgKmlzKiBhIHRlbXBsYXRlIGZvciB0aGlzIHBsb3RcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lOiB0aGUgbmFtZSBvZiB0aGUgYXJyYXkgdG8gdGVtcGxhdGUgKGllICdhbm5vdGF0aW9ucycpXG4gKiAgICAgd2lsbCBiZSB1c2VkIHRvIGZpbmQgZGVmYXVsdCAoJ2Fubm90YXRpb25kZWZhdWx0cycgb2JqZWN0KSBhbmQgc3BlY2lmaWNcbiAqICAgICAoJ2Fubm90YXRpb25zJyBhcnJheSkgdGVtcGxhdGUgc3BlY3MuXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5jbHVzaW9uQXR0cjogdGhlIGF0dHJpYnV0ZSBkZXRlcm1pbmluZyB0aGlzIGl0ZW0nc1xuICogICAgIGluY2x1c2lvbiBpbiB0aGUgb3V0cHV0LCB1c3VhbGx5ICd2aXNpYmxlJyBvciAnZW5hYmxlZCdcbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fToge25ld0l0ZW0sIGRlZmF1bHRJdGVtc30sIGJvdGggZnVuY3Rpb25zOlxuICogICAgIG5ld0l0ZW0oaXRlbUluKTogY3JlYXRlIGFuIG91dHB1dCBpdGVtLCBiYXJlIGV4Y2VwdCBmb3IgdGhlIGNvcnJlY3RcbiAqICAgICAgICAgdGVtcGxhdGUgYW5kIG5hbWUocyksIGFzIHRoZSBiYXNlIGZvciBzdXBwbHlEZWZhdWx0c1xuICogICAgIGRlZmF1bHRJdGVtcygpOiB0byBiZSBjYWxsZWQgYWZ0ZXIgYWxsIG5ld0l0ZW0gY2FsbHMsIHJldHVybiBhbnlcbiAqICAgICAgICAgc3BlY2lmaWMgdGVtcGxhdGUgaXRlbXMgdGhhdCBoYXZlIG5vdCBhbHJlYWR5IGJlZWVuIGluY2x1ZGVkLFxuICogICAgICAgICBhbHNvIGFzIGJhcmUgb3V0cHV0IGl0ZW1zIHJlYWR5IGZvciBzdXBwbHlEZWZhdWx0cy5cbiAqL1xuZXhwb3J0cy5hcnJheVRlbXBsYXRlciA9IGZ1bmN0aW9uKGNvbnRhaW5lciwgbmFtZSwgaW5jbHVzaW9uQXR0cikge1xuICAgIHZhciB0ZW1wbGF0ZSA9IGNvbnRhaW5lci5fdGVtcGxhdGU7XG4gICAgdmFyIGRlZmF1bHRzVGVtcGxhdGUgPSB0ZW1wbGF0ZSAmJiB0ZW1wbGF0ZVthcnJheURlZmF1bHRLZXkobmFtZSldO1xuICAgIHZhciB0ZW1wbGF0ZUl0ZW1zID0gdGVtcGxhdGUgJiYgdGVtcGxhdGVbbmFtZV07XG4gICAgaWYoIUFycmF5LmlzQXJyYXkodGVtcGxhdGVJdGVtcykgfHwgIXRlbXBsYXRlSXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHRlbXBsYXRlSXRlbXMgPSBbXTtcbiAgICB9XG5cbiAgICB2YXIgdXNlZE5hbWVzID0ge307XG5cbiAgICBmdW5jdGlvbiBuZXdJdGVtKGl0ZW1Jbikge1xuICAgICAgICAvLyBpbmNsdWRlIG5hbWUgYW5kIHRlbXBsYXRlaXRlbW5hbWUgaW4gdGhlIG91dHB1dCBvYmplY3QgZm9yIEFMTFxuICAgICAgICAvLyBjb250YWluZXIgYXJyYXkgaXRlbXMuIE5vdGU6IHlvdSBjb3VsZCBwb3RlbnRpYWxseSB1c2UgZGlmZmVyZW50XG4gICAgICAgIC8vIG5hbWUgYW5kIHRlbXBsYXRlaXRlbW5hbWUsIGlmIHlvdSdyZSB1c2luZyBvbmUgdGVtcGxhdGUgdG8gbWFrZVxuICAgICAgICAvLyBhbm90aGVyIHRlbXBsYXRlLiB0ZW1wbGF0ZWl0ZW1uYW1lIHdvdWxkIGJlIHRoZSBuYW1lIGluIHRoZSBvcmlnaW5hbFxuICAgICAgICAvLyB0ZW1wbGF0ZSwgYW5kIG5hbWUgaXMgdGhlIG5ldyBcInN1YmNsYXNzZWRcIiBpdGVtIG5hbWUuXG4gICAgICAgIHZhciBvdXQgPSB7bmFtZTogaXRlbUluLm5hbWUsIF9pbnB1dDogaXRlbUlufTtcbiAgICAgICAgdmFyIHRlbXBsYXRlSXRlbU5hbWUgPSBvdXRbVEVNUExBVEVJVEVNTkFNRV0gPSBpdGVtSW5bVEVNUExBVEVJVEVNTkFNRV07XG5cbiAgICAgICAgLy8gbm8gaXRlbW5hbWU6IHVzZSB0aGUgZGVmYXVsdCB0ZW1wbGF0ZVxuICAgICAgICBpZighdmFsaWRJdGVtTmFtZSh0ZW1wbGF0ZUl0ZW1OYW1lKSkge1xuICAgICAgICAgICAgb3V0Ll90ZW1wbGF0ZSA9IGRlZmF1bHRzVGVtcGxhdGU7XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbG9vayBmb3IgYW4gaXRlbSBtYXRjaGluZyB0aGlzIGl0ZW1uYW1lXG4gICAgICAgIC8vIG5vdGUgdGhlc2UgZG8gbm90IGluaGVyaXQgZnJvbSB0aGUgZGVmYXVsdCB0ZW1wbGF0ZSwgb25seSB0aGUgaXRlbS5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHRlbXBsYXRlSXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0ZW1wbGF0ZUl0ZW0gPSB0ZW1wbGF0ZUl0ZW1zW2ldO1xuICAgICAgICAgICAgaWYodGVtcGxhdGVJdGVtLm5hbWUgPT09IHRlbXBsYXRlSXRlbU5hbWUpIHtcbiAgICAgICAgICAgICAgICAvLyBOb3RlOiBpdCdzIE9LIHRvIHVzZSBhIHRlbXBsYXRlIGl0ZW0gbW9yZSB0aGFuIG9uY2VcbiAgICAgICAgICAgICAgICAvLyBidXQgdXNpbmcgaXQgYXQgbGVhc3Qgb25jZSB3aWxsIHN0b3AgaXQgZnJvbSBnZW5lcmF0aW5nXG4gICAgICAgICAgICAgICAgLy8gYSBkZWZhdWx0IGl0ZW0gYXQgdGhlIGVuZC5cbiAgICAgICAgICAgICAgICB1c2VkTmFtZXNbdGVtcGxhdGVJdGVtTmFtZV0gPSAxO1xuICAgICAgICAgICAgICAgIG91dC5fdGVtcGxhdGUgPSB0ZW1wbGF0ZUl0ZW07XG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERpZG4ndCBmaW5kIGEgbWF0Y2hpbmcgdGVtcGxhdGUgaXRlbSwgc28gc2luY2UgdGhpcyBpdGVtIGlzIGludGVuZGVkXG4gICAgICAgIC8vIHRvIG9ubHkgYmUgbW9kaWZpY2F0aW9ucyBpdCdzIG1vc3QgbGlrZWx5IGJyb2tlbi4gSGlkZSBpdCB1bmxlc3NcbiAgICAgICAgLy8gaXQncyBleHBsaWNpdGx5IG1hcmtlZCB2aXNpYmxlIC0gaW4gd2hpY2ggY2FzZSBpdCBnZXRzIE5PIHRlbXBsYXRlLFxuICAgICAgICAvLyBub3QgZXZlbiB0aGUgZGVmYXVsdC5cbiAgICAgICAgb3V0W2luY2x1c2lvbkF0dHJdID0gaXRlbUluW2luY2x1c2lvbkF0dHJdIHx8IGZhbHNlO1xuICAgICAgICAvLyBzcGVjaWFsIGZhbHN5IHZhbHVlIHdlIGNhbiBsb29rIGZvciBpbiB2YWxpZGF0ZVRlbXBsYXRlXG4gICAgICAgIG91dC5fdGVtcGxhdGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkZWZhdWx0SXRlbXMoKSB7XG4gICAgICAgIHZhciBvdXQgPSBbXTtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHRlbXBsYXRlSXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0ZW1wbGF0ZUl0ZW0gPSB0ZW1wbGF0ZUl0ZW1zW2ldO1xuICAgICAgICAgICAgdmFyIG5hbWUgPSB0ZW1wbGF0ZUl0ZW0ubmFtZTtcbiAgICAgICAgICAgIC8vIG9ubHkgYWxsb3cgbmFtZWQgaXRlbXMgdG8gYmUgYWRkZWQgYXMgZGVmYXVsdHMsXG4gICAgICAgICAgICAvLyBhbmQgb25seSBhbGxvdyBlYWNoIG5hbWUgb25jZVxuICAgICAgICAgICAgaWYodmFsaWRJdGVtTmFtZShuYW1lKSAmJiAhdXNlZE5hbWVzW25hbWVdKSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dGkgPSB7XG4gICAgICAgICAgICAgICAgICAgIF90ZW1wbGF0ZTogdGVtcGxhdGVJdGVtLFxuICAgICAgICAgICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICAgICAgICAgICAgICBfaW5wdXQ6IHtfdGVtcGxhdGVpdGVtbmFtZTogbmFtZX1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIG91dGlbVEVNUExBVEVJVEVNTkFNRV0gPSB0ZW1wbGF0ZUl0ZW1bVEVNUExBVEVJVEVNTkFNRV07XG4gICAgICAgICAgICAgICAgb3V0LnB1c2gob3V0aSk7XG4gICAgICAgICAgICAgICAgdXNlZE5hbWVzW25hbWVdID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIG5ld0l0ZW06IG5ld0l0ZW0sXG4gICAgICAgIGRlZmF1bHRJdGVtczogZGVmYXVsdEl0ZW1zXG4gICAgfTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkSXRlbU5hbWUobmFtZSkge1xuICAgIHJldHVybiBuYW1lICYmIHR5cGVvZiBuYW1lID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gYXJyYXlEZWZhdWx0S2V5KG5hbWUpIHtcbiAgICB2YXIgbGFzdENoYXIgPSBuYW1lLmxlbmd0aCAtIDE7XG4gICAgaWYobmFtZS5jaGFyQXQobGFzdENoYXIpICE9PSAncycpIHtcbiAgICAgICAgTGliLndhcm4oJ2JhZCBhcmd1bWVudCB0byBhcnJheURlZmF1bHRLZXk6ICcgKyBuYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIG5hbWUuc3Vic3RyKDAsIG5hbWUubGVuZ3RoIC0gMSkgKyAnZGVmYXVsdHMnO1xufVxuZXhwb3J0cy5hcnJheURlZmF1bHRLZXkgPSBhcnJheURlZmF1bHRLZXk7XG5cbi8qKlxuICogYXJyYXlFZGl0b3I6IGhlbHBlciBmb3IgZWRpdGluZyBhcnJheSBpdGVtcyB0aGF0IG1heSBoYXZlIGNvbWUgZnJvbVxuICogICAgIHRlbXBsYXRlIGRlZmF1bHRzIChpbiB3aGljaCBjYXNlIHRoZXkgd2lsbCBub3QgZXhpc3QgaW4gdGhlIGlucHV0IHlldClcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFyZW50SW46IHRoZSBpbnB1dCBjb250YWluZXIgKGVnIGdkLmxheW91dClcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250YWluZXJTdHI6IHRoZSBhdHRyaWJ1dGUgc3RyaW5nIGZvciB0aGUgY29udGFpbmVyIGluc2lkZVxuICogICAgIGBwYXJlbnRJbmAuXG4gKiBAcGFyYW0ge29iamVjdH0gaXRlbU91dDogdGhlIF9mdWxsKiBpdGVtIChlZyBnZC5fZnVsbExheW91dC5hbm5vdGF0aW9uc1swXSlcbiAqICAgICB0aGF0IHdlJ2xsIGJlIGVkaXRpbmcuIEFzc3VtZWQgdG8gaGF2ZSBiZWVuIGNyZWF0ZWQgYnkgYGFycmF5VGVtcGxhdGVyYC5cbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fToge21vZGlmeUJhc2UsIG1vZGlmeUl0ZW0sIGdldFVwZGF0ZU9iaiwgYXBwbHlVcGRhdGV9LCBhbGwgZnVuY3Rpb25zOlxuICogICAgIG1vZGlmeUJhc2UoYXR0ciwgdmFsdWUpOiBBZGQgYW4gdXBkYXRlIHRoYXQncyAqbm90KiByZWxhdGVkIHRvIHRoZSBpdGVtLlxuICogICAgICAgICBgYXR0cmAgaXMgdGhlIGZ1bGwgYXR0cmlidXRlIHN0cmluZy5cbiAqICAgICBtb2RpZnlJdGVtKGF0dHIsIHZhbHVlKTogQWRkIGFuIHVwZGF0ZSB0byB0aGUgaXRlbS4gYGF0dHJgIGlzIGp1c3QgdGhlXG4gKiAgICAgICAgIHBvcnRpb24gb2YgdGhlIGF0dHJpYnV0ZSBzdHJpbmcgaW5zaWRlIHRoZSBpdGVtLlxuICogICAgIGdldFVwZGF0ZU9iaigpOiBHZXQgdGhlIGZpbmFsIGNvbnN0cnVjdGVkIHVwZGF0ZSBvYmplY3QsIHRvIHVzZSBpblxuICogICAgICAgICBgcmVzdHlsZWAgb3IgYHJlbGF5b3V0YC4gQWxzbyByZXNldHMgdGhlIHVwZGF0ZSBvYmplY3QgaW4gY2FzZSB0aGlzXG4gKiAgICAgICAgIHVwZGF0ZSB3YXMgY2FuY2VsZWQuXG4gKiAgICAgYXBwbHlVcGRhdGUoYXR0ciwgdmFsdWUpOiBvcHRpb25hbGx5IGFkZCBhbiB1cGRhdGUgYGF0dHI6IHZhbHVlYCxcbiAqICAgICAgICAgdGhlbiBhcHBseSBpdCB0byBgcGFyZW50YCB3aGljaCBzaG91bGQgYmUgdGhlIHBhcmVudCBvZiBgY29udGFpbmVySW5gLFxuICogICAgICAgICBpZSB0aGUgb2JqZWN0IHRvIHdoaWNoIGBjb250YWluZXJTdHJgIGlzIHRoZSBhdHRyaWJ1dGUgc3RyaW5nLlxuICovXG5leHBvcnRzLmFycmF5RWRpdG9yID0gZnVuY3Rpb24ocGFyZW50SW4sIGNvbnRhaW5lclN0ciwgaXRlbU91dCkge1xuICAgIHZhciBsZW5ndGhJbiA9IChMaWIubmVzdGVkUHJvcGVydHkocGFyZW50SW4sIGNvbnRhaW5lclN0cikuZ2V0KCkgfHwgW10pLmxlbmd0aDtcbiAgICB2YXIgaW5kZXggPSBpdGVtT3V0Ll9pbmRleDtcbiAgICAvLyBDaGVjayB0aGF0IHdlIGFyZSBpbmRlZWQgb2ZmIHRoZSBlbmQgb2YgdGhpcyBjb250YWluZXIuXG4gICAgLy8gT3RoZXJ3aXNlIGEgZGV2aW91cyB1c2VyIGNvdWxkIHB1dCBhIGtleSBgX3RlbXBsYXRlaXRlbW5hbWVgIGluIHRoZWlyXG4gICAgLy8gb3duIGlucHV0IGFuZCBicmVhayBsb3RzIG9mIHRoaW5ncy5cbiAgICB2YXIgdGVtcGxhdGVJdGVtTmFtZSA9IChpbmRleCA+PSBsZW5ndGhJbikgJiYgKGl0ZW1PdXQuX2lucHV0IHx8IHt9KS5fdGVtcGxhdGVpdGVtbmFtZTtcbiAgICBpZih0ZW1wbGF0ZUl0ZW1OYW1lKSBpbmRleCA9IGxlbmd0aEluO1xuICAgIHZhciBpdGVtU3RyID0gY29udGFpbmVyU3RyICsgJ1snICsgaW5kZXggKyAnXSc7XG5cbiAgICB2YXIgdXBkYXRlO1xuICAgIGZ1bmN0aW9uIHJlc2V0VXBkYXRlKCkge1xuICAgICAgICB1cGRhdGUgPSB7fTtcbiAgICAgICAgaWYodGVtcGxhdGVJdGVtTmFtZSkge1xuICAgICAgICAgICAgdXBkYXRlW2l0ZW1TdHJdID0ge307XG4gICAgICAgICAgICB1cGRhdGVbaXRlbVN0cl1bVEVNUExBVEVJVEVNTkFNRV0gPSB0ZW1wbGF0ZUl0ZW1OYW1lO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJlc2V0VXBkYXRlKCk7XG5cbiAgICBmdW5jdGlvbiBtb2RpZnlCYXNlKGF0dHIsIHZhbHVlKSB7XG4gICAgICAgIHVwZGF0ZVthdHRyXSA9IHZhbHVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vZGlmeUl0ZW0oYXR0ciwgdmFsdWUpIHtcbiAgICAgICAgaWYodGVtcGxhdGVJdGVtTmFtZSkge1xuICAgICAgICAgICAgLy8gd2UncmUgbWFraW5nIGEgbmV3IG9iamVjdDogZWRpdCB0aGF0IG9iamVjdFxuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KHVwZGF0ZVtpdGVtU3RyXSwgYXR0cikuc2V0KHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHdlJ3JlIGVkaXRpbmcgYW4gZXhpc3Rpbmcgb2JqZWN0OiBpbmNsdWRlICpqdXN0KiB0aGUgZWRpdFxuICAgICAgICAgICAgdXBkYXRlW2l0ZW1TdHIgKyAnLicgKyBhdHRyXSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0VXBkYXRlT2JqKCkge1xuICAgICAgICB2YXIgdXBkYXRlT3V0ID0gdXBkYXRlO1xuICAgICAgICByZXNldFVwZGF0ZSgpO1xuICAgICAgICByZXR1cm4gdXBkYXRlT3V0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFwcGx5VXBkYXRlKGF0dHIsIHZhbHVlKSB7XG4gICAgICAgIGlmKGF0dHIpIG1vZGlmeUl0ZW0oYXR0ciwgdmFsdWUpO1xuICAgICAgICB2YXIgdXBkYXRlVG9BcHBseSA9IGdldFVwZGF0ZU9iaigpO1xuICAgICAgICBmb3IodmFyIGtleSBpbiB1cGRhdGVUb0FwcGx5KSB7XG4gICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkocGFyZW50SW4sIGtleSkuc2V0KHVwZGF0ZVRvQXBwbHlba2V5XSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBtb2RpZnlCYXNlOiBtb2RpZnlCYXNlLFxuICAgICAgICBtb2RpZnlJdGVtOiBtb2RpZnlJdGVtLFxuICAgICAgICBnZXRVcGRhdGVPYmo6IGdldFVwZGF0ZU9iaixcbiAgICAgICAgYXBwbHlVcGRhdGU6IGFwcGx5VXBkYXRlXG4gICAgfTtcbn07XG5cbn0se1wiLi4vbGliXCI6NzE5LFwiLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NH1dLDc1ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi9yZWdpc3RyeScpO1xudmFyIFBsb3RzID0gX2RlcmVxXygnLi4vcGxvdHMvcGxvdHMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uL2xpYicpO1xudmFyIGNsZWFyR2xDYW52YXNlcyA9IF9kZXJlcV8oJy4uL2xpYi9jbGVhcl9nbF9jYW52YXNlcycpO1xuXG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIFRpdGxlcyA9IF9kZXJlcV8oJy4uL2NvbXBvbmVudHMvdGl0bGVzJyk7XG52YXIgTW9kZUJhciA9IF9kZXJlcV8oJy4uL2NvbXBvbmVudHMvbW9kZWJhcicpO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgYWxpZ25tZW50Q29uc3RhbnRzID0gX2RlcmVxXygnLi4vY29uc3RhbnRzL2FsaWdubWVudCcpO1xudmFyIGF4aXNDb25zdHJhaW50cyA9IF9kZXJlcV8oJy4uL3Bsb3RzL2NhcnRlc2lhbi9jb25zdHJhaW50cycpO1xudmFyIGVuZm9yY2VBeGlzQ29uc3RyYWludHMgPSBheGlzQ29uc3RyYWludHMuZW5mb3JjZTtcbnZhciBjbGVhbkF4aXNDb25zdHJhaW50cyA9IGF4aXNDb25zdHJhaW50cy5jbGVhbjtcbnZhciBkb0F1dG9SYW5nZSA9IF9kZXJlcV8oJy4uL3Bsb3RzL2NhcnRlc2lhbi9hdXRvcmFuZ2UnKS5kb0F1dG9SYW5nZTtcblxudmFyIFNWR19URVhUX0FOQ0hPUl9TVEFSVCA9ICdzdGFydCc7XG52YXIgU1ZHX1RFWFRfQU5DSE9SX01JRERMRSA9ICdtaWRkbGUnO1xudmFyIFNWR19URVhUX0FOQ0hPUl9FTkQgPSAnZW5kJztcblxuZXhwb3J0cy5sYXlvdXRTdHlsZXMgPSBmdW5jdGlvbihnZCkge1xuICAgIHJldHVybiBMaWIuc3luY09yQXN5bmMoW1Bsb3RzLmRvQXV0b01hcmdpbiwgbHNJbm5lcl0sIGdkKTtcbn07XG5cbmZ1bmN0aW9uIG92ZXJsYXBwaW5nRG9tYWluKHhEb21haW4sIHlEb21haW4sIGRvbWFpbnMpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZG9tYWlucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZXhpc3RpbmdYID0gZG9tYWluc1tpXVswXTtcbiAgICAgICAgdmFyIGV4aXN0aW5nWSA9IGRvbWFpbnNbaV1bMV07XG5cbiAgICAgICAgaWYoZXhpc3RpbmdYWzBdID49IHhEb21haW5bMV0gfHwgZXhpc3RpbmdYWzFdIDw9IHhEb21haW5bMF0pIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmKGV4aXN0aW5nWVswXSA8IHlEb21haW5bMV0gJiYgZXhpc3RpbmdZWzFdID4geURvbWFpblswXSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBsc0lubmVyKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZ3MgPSBmdWxsTGF5b3V0Ll9zaXplO1xuICAgIHZhciBwYWQgPSBncy5wO1xuICAgIHZhciBheExpc3QgPSBBeGVzLmxpc3QoZ2QsICcnLCB0cnVlKTtcbiAgICB2YXIgaSwgc3VicGxvdCwgcGxvdGluZm8sIGF4LCB4YSwgeWE7XG5cbiAgICBmdWxsTGF5b3V0Ll9wYXBlcmRpdi5zdHlsZSh7XG4gICAgICAgIHdpZHRoOiAoZ2QuX2NvbnRleHQucmVzcG9uc2l2ZSAmJiBmdWxsTGF5b3V0LmF1dG9zaXplICYmICFnZC5fY29udGV4dC5faGFzWmVyb1dpZHRoICYmICFnZC5sYXlvdXQud2lkdGgpID8gJzEwMCUnIDogZnVsbExheW91dC53aWR0aCArICdweCcsXG4gICAgICAgIGhlaWdodDogKGdkLl9jb250ZXh0LnJlc3BvbnNpdmUgJiYgZnVsbExheW91dC5hdXRvc2l6ZSAmJiAhZ2QuX2NvbnRleHQuX2hhc1plcm9IZWlnaHQgJiYgIWdkLmxheW91dC5oZWlnaHQpID8gJzEwMCUnIDogZnVsbExheW91dC5oZWlnaHQgKyAncHgnXG4gICAgfSlcbiAgICAuc2VsZWN0QWxsKCcubWFpbi1zdmcnKVxuICAgIC5jYWxsKERyYXdpbmcuc2V0U2l6ZSwgZnVsbExheW91dC53aWR0aCwgZnVsbExheW91dC5oZWlnaHQpO1xuICAgIGdkLl9jb250ZXh0LnNldEJhY2tncm91bmQoZ2QsIGZ1bGxMYXlvdXQucGFwZXJfYmdjb2xvcik7XG5cbiAgICBleHBvcnRzLmRyYXdNYWluVGl0bGUoZ2QpO1xuICAgIE1vZGVCYXIubWFuYWdlKGdkKTtcblxuICAgIC8vIF9oYXMoJ2NhcnRlc2lhbicpIG1lYW5zIFNWRyBzcGVjaWZpY2FsbHksIG5vdCBHTDJEIC0gYnV0IEdMMkRcbiAgICAvLyBjYW4gc3RpbGwgZ2V0IGhlcmUgYmVjYXVzZSBpdCBtYWtlcyBzb21lIG9mIHRoZSBTVkcgc3RydWN0dXJlXG4gICAgLy8gZm9yIHNoYXJlZCBmZWF0dXJlcyBsaWtlIHNlbGVjdGlvbnMuXG4gICAgaWYoIWZ1bGxMYXlvdXQuX2hhcygnY2FydGVzaWFuJykpIHtcbiAgICAgICAgcmV0dXJuIGdkLl9wcm9taXNlcy5sZW5ndGggJiYgUHJvbWlzZS5hbGwoZ2QuX3Byb21pc2VzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRMaW5lUG9zaXRpb24oYXgsIGNvdW50ZXJBeCwgc2lkZSkge1xuICAgICAgICB2YXIgbHdIYWxmID0gYXguX2x3IC8gMjtcblxuICAgICAgICBpZihheC5faWQuY2hhckF0KDApID09PSAneCcpIHtcbiAgICAgICAgICAgIGlmKCFjb3VudGVyQXgpIHJldHVybiBncy50ICsgZ3MuaCAqICgxIC0gKGF4LnBvc2l0aW9uIHx8IDApKSArIChsd0hhbGYgJSAxKTtcbiAgICAgICAgICAgIGVsc2UgaWYoc2lkZSA9PT0gJ3RvcCcpIHJldHVybiBjb3VudGVyQXguX29mZnNldCAtIHBhZCAtIGx3SGFsZjtcbiAgICAgICAgICAgIHJldHVybiBjb3VudGVyQXguX29mZnNldCArIGNvdW50ZXJBeC5fbGVuZ3RoICsgcGFkICsgbHdIYWxmO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWNvdW50ZXJBeCkgcmV0dXJuIGdzLmwgKyBncy53ICogKGF4LnBvc2l0aW9uIHx8IDApICsgKGx3SGFsZiAlIDEpO1xuICAgICAgICBlbHNlIGlmKHNpZGUgPT09ICdyaWdodCcpIHJldHVybiBjb3VudGVyQXguX29mZnNldCArIGNvdW50ZXJBeC5fbGVuZ3RoICsgcGFkICsgbHdIYWxmO1xuICAgICAgICByZXR1cm4gY291bnRlckF4Ll9vZmZzZXQgLSBwYWQgLSBsd0hhbGY7XG4gICAgfVxuXG4gICAgLy8gc29tZSBwcmVwYXJhdGlvbiBvZiBheGlzIHBvc2l0aW9uIGluZm9cbiAgICBmb3IoaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXggPSBheExpc3RbaV07XG5cbiAgICAgICAgdmFyIGNvdW50ZXJBeCA9IGF4Ll9hbmNob3JBeGlzO1xuXG4gICAgICAgIC8vIGNsZWFyIGF4aXMgbGluZSBwb3NpdGlvbnMsIHRvIGJlIHNldCBpbiB0aGUgc3VicGxvdCBsb29wIGJlbG93XG4gICAgICAgIGF4Ll9saW5lcG9zaXRpb25zID0ge307XG5cbiAgICAgICAgLy8gc3Rhc2ggY3Jpc3BSb3VuZGVkIGxpbmV3aWR0aCBzbyB3ZSBkb24ndCBuZWVkIHRvIHBhc3MgZ2QgYWxsIG92ZXIgdGhlIHBsYWNlXG4gICAgICAgIGF4Ll9sdyA9IERyYXdpbmcuY3Jpc3BSb3VuZChnZCwgYXgubGluZXdpZHRoLCAxKTtcblxuICAgICAgICAvLyBmaWd1cmUgb3V0IHRoZSBtYWluIGF4aXMgbGluZSBhbmQgbWFpbiBtaXJyb3IgbGluZSBwb3NpdGlvbi5cbiAgICAgICAgLy8gaXQncyBlYXNpZXIgdG8gZm9sbG93IHRoZSBsb2dpYyBpZiB3ZSBoYW5kbGUgdGhlc2Ugc2VwYXJhdGVseSBmcm9tXG4gICAgICAgIC8vIGF4Ll9saW5lcG9zaXRpb25zLCB3aGljaCBhcmUgb25seSB1c2VkIGJ5IG1pcnJvcj1hbGx0aWNrc1xuICAgICAgICAvLyBmb3Igbm9uLW1haW4tc3VicGxvdCB0aWNrcywgYW5kIG1pcnJvcj1hbGwodGlja3MpPyBmb3IgemVybyBsaW5lXG4gICAgICAgIC8vIGhpZGluZyBsb2dpY1xuICAgICAgICBheC5fbWFpbkxpbmVQb3NpdGlvbiA9IGdldExpbmVQb3NpdGlvbihheCwgY291bnRlckF4LCBheC5zaWRlKTtcbiAgICAgICAgYXguX21haW5NaXJyb3JQb3NpdGlvbiA9IChheC5taXJyb3IgJiYgY291bnRlckF4KSA/XG4gICAgICAgICAgICBnZXRMaW5lUG9zaXRpb24oYXgsIGNvdW50ZXJBeCxcbiAgICAgICAgICAgICAgICBhbGlnbm1lbnRDb25zdGFudHMuT1BQT1NJVEVfU0lERVtheC5zaWRlXSkgOiBudWxsO1xuICAgIH1cblxuICAgIC8vIGZpZ3VyZSBvdXQgd2hpY2ggYmFja2dyb3VuZHMgd2UgbmVlZCB0byBkcmF3LFxuICAgIC8vIGFuZCBpbiB3aGljaCBsYXllcnMgdG8gcHV0IHRoZW1cbiAgICB2YXIgbG93ZXJCYWNrZ3JvdW5kSURzID0gW107XG4gICAgdmFyIGJhY2tncm91bmRJZHMgPSBbXTtcbiAgICB2YXIgbG93ZXJEb21haW5zID0gW107XG4gICAgLy8gbm8gbmVlZCB0byBkcmF3IGJhY2tncm91bmQgd2hlbiBwYXBlciBhbmQgcGxvdCBjb2xvciBhcmUgdGhlIHNhbWUgY29sb3IsXG4gICAgLy8gYWN0aXZhdGUgbW9kZSBqdXN0IGZvciBsYXJnZSBzcGxvbSAod2hpY2ggYmVuZWZpdCB0aGUgbW9zdCBmcm9tIHRoaXNcbiAgICAvLyBvcHRpbWl6YXRpb24pLCBidXQgdGhpcyBjb3VsZCBhcHBseSB0byBhbGwgY2FydGVzaWFuIHN1YnBsb3RzLlxuICAgIHZhciBub05lZWRGb3JCZyA9IChcbiAgICAgICAgQ29sb3Iub3BhY2l0eShmdWxsTGF5b3V0LnBhcGVyX2JnY29sb3IpID09PSAxICYmXG4gICAgICAgIENvbG9yLm9wYWNpdHkoZnVsbExheW91dC5wbG90X2JnY29sb3IpID09PSAxICYmXG4gICAgICAgIGZ1bGxMYXlvdXQucGFwZXJfYmdjb2xvciA9PT0gZnVsbExheW91dC5wbG90X2JnY29sb3JcbiAgICApO1xuXG4gICAgZm9yKHN1YnBsb3QgaW4gZnVsbExheW91dC5fcGxvdHMpIHtcbiAgICAgICAgcGxvdGluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90XTtcblxuICAgICAgICBpZihwbG90aW5mby5tYWlucGxvdCkge1xuICAgICAgICAgICAgLy8gbWFpbnBsb3QgaXMgYSByZWZlcmVuY2UgdG8gdGhlIG1haW4gcGxvdCB0aGlzIG9uZSBpcyBvdmVybGFpZCBvblxuICAgICAgICAgICAgLy8gc28gaWYgaXQgZXhpc3RzLCB0aGlzIGlzIGFuIG92ZXJsYWlkIHBsb3QgYW5kIHdlIGRvbid0IG5lZWQgdG9cbiAgICAgICAgICAgIC8vIGdpdmUgaXQgaXRzIG93biBiYWNrZ3JvdW5kXG4gICAgICAgICAgICBpZihwbG90aW5mby5iZykge1xuICAgICAgICAgICAgICAgIHBsb3RpbmZvLmJnLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGxvdGluZm8uYmcgPSB1bmRlZmluZWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgeERvbWFpbiA9IHBsb3RpbmZvLnhheGlzLmRvbWFpbjtcbiAgICAgICAgICAgIHZhciB5RG9tYWluID0gcGxvdGluZm8ueWF4aXMuZG9tYWluO1xuICAgICAgICAgICAgdmFyIHBsb3Rncm91cCA9IHBsb3RpbmZvLnBsb3Rncm91cDtcblxuICAgICAgICAgICAgaWYob3ZlcmxhcHBpbmdEb21haW4oeERvbWFpbiwgeURvbWFpbiwgbG93ZXJEb21haW5zKSkge1xuICAgICAgICAgICAgICAgIHZhciBwZ05vZGUgPSBwbG90Z3JvdXAubm9kZSgpO1xuICAgICAgICAgICAgICAgIHZhciBwbG90Z3JvdXBCZyA9IHBsb3RpbmZvLmJnID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdyZWN0JywgJ2JnJyk7XG4gICAgICAgICAgICAgICAgcGdOb2RlLmluc2VydEJlZm9yZShwbG90Z3JvdXBCZy5ub2RlKCksIHBnTm9kZS5jaGlsZE5vZGVzWzBdKTtcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kSWRzLnB1c2goc3VicGxvdCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBsb3Rncm91cC5zZWxlY3QoJ3JlY3QuYmcnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICBsb3dlckRvbWFpbnMucHVzaChbeERvbWFpbiwgeURvbWFpbl0pO1xuICAgICAgICAgICAgICAgIGlmKCFub05lZWRGb3JCZykge1xuICAgICAgICAgICAgICAgICAgICBsb3dlckJhY2tncm91bmRJRHMucHVzaChzdWJwbG90KTtcbiAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZElkcy5wdXNoKHN1YnBsb3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG5vdyBjcmVhdGUgYWxsIHRoZSBsb3dlci1sYXllciBiYWNrZ3JvdW5kcyBhdCBvbmNlIG5vdyB0aGF0XG4gICAgLy8gd2UgaGF2ZSB0aGUgbGlzdCBvZiBzdWJwbG90cyB0aGF0IG5lZWQgdGhlbVxuICAgIHZhciBsb3dlckJhY2tncm91bmRzID0gZnVsbExheW91dC5fYmdMYXllci5zZWxlY3RBbGwoJy5iZycpXG4gICAgICAgIC5kYXRhKGxvd2VyQmFja2dyb3VuZElEcyk7XG5cbiAgICBsb3dlckJhY2tncm91bmRzLmVudGVyKCkuYXBwZW5kKCdyZWN0JylcbiAgICAgICAgLmNsYXNzZWQoJ2JnJywgdHJ1ZSk7XG5cbiAgICBsb3dlckJhY2tncm91bmRzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGxvd2VyQmFja2dyb3VuZHMuZWFjaChmdW5jdGlvbihzdWJwbG90KSB7XG4gICAgICAgIGZ1bGxMYXlvdXQuX3Bsb3RzW3N1YnBsb3RdLmJnID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgIH0pO1xuXG4gICAgLy8gc3R5bGUgYWxsIGJhY2tncm91bmRzXG4gICAgZm9yKGkgPSAwOyBpIDwgYmFja2dyb3VuZElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW2JhY2tncm91bmRJZHNbaV1dO1xuICAgICAgICB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgICAgICB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgICAgIGlmKHBsb3RpbmZvLmJnKSB7XG4gICAgICAgICAgICBwbG90aW5mby5iZ1xuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0UmVjdCxcbiAgICAgICAgICAgICAgICAgICAgeGEuX29mZnNldCAtIHBhZCwgeWEuX29mZnNldCAtIHBhZCxcbiAgICAgICAgICAgICAgICAgICAgeGEuX2xlbmd0aCArIDIgKiBwYWQsIHlhLl9sZW5ndGggKyAyICogcGFkKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGZ1bGxMYXlvdXQucGxvdF9iZ2NvbG9yKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZighZnVsbExheW91dC5faGFzT25seUxhcmdlU3Bsb21zKSB7XG4gICAgICAgIGZvcihzdWJwbG90IGluIGZ1bGxMYXlvdXQuX3Bsb3RzKSB7XG4gICAgICAgICAgICBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW3N1YnBsb3RdO1xuICAgICAgICAgICAgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICAgICAgICAgIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICAgICAgICAgIC8vIENsaXAgc28gdGhhdCBkYXRhIG9ubHkgc2hvd3MgdXAgb24gdGhlIHBsb3QgYXJlYS5cbiAgICAgICAgICAgIHZhciBjbGlwSWQgPSBwbG90aW5mby5jbGlwSWQgPSAnY2xpcCcgKyBmdWxsTGF5b3V0Ll91aWQgKyBzdWJwbG90ICsgJ3Bsb3QnO1xuXG4gICAgICAgICAgICB2YXIgcGxvdENsaXAgPSBMaWIuZW5zdXJlU2luZ2xlQnlJZChmdWxsTGF5b3V0Ll9jbGlwcywgJ2NsaXBQYXRoJywgY2xpcElkLCBmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICAgICAgcy5jbGFzc2VkKCdwbG90Y2xpcCcsIHRydWUpXG4gICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJ3JlY3QnKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBwbG90aW5mby5jbGlwUmVjdCA9IHBsb3RDbGlwLnNlbGVjdCgncmVjdCcpLmF0dHIoe1xuICAgICAgICAgICAgICAgIHdpZHRoOiB4YS5fbGVuZ3RoLFxuICAgICAgICAgICAgICAgIGhlaWdodDogeWEuX2xlbmd0aFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIERyYXdpbmcuc2V0VHJhbnNsYXRlKHBsb3RpbmZvLnBsb3QsIHhhLl9vZmZzZXQsIHlhLl9vZmZzZXQpO1xuXG4gICAgICAgICAgICB2YXIgcGxvdENsaXBJZDtcbiAgICAgICAgICAgIHZhciBsYXllckNsaXBJZDtcblxuICAgICAgICAgICAgaWYocGxvdGluZm8uX2hhc0NsaXBPbkF4aXNGYWxzZSkge1xuICAgICAgICAgICAgICAgIHBsb3RDbGlwSWQgPSBudWxsO1xuICAgICAgICAgICAgICAgIGxheWVyQ2xpcElkID0gY2xpcElkO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwbG90Q2xpcElkID0gY2xpcElkO1xuICAgICAgICAgICAgICAgIGxheWVyQ2xpcElkID0gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKHBsb3RpbmZvLnBsb3QsIHBsb3RDbGlwSWQsIGdkKTtcblxuICAgICAgICAgICAgLy8gc3Rhc2ggbGF5ZXIgY2xpcElkIHZhbHVlIChudWxsIG9yIHNhbWUgYXMgY2xpcElkKVxuICAgICAgICAgICAgLy8gdG8gRFJZIHVwIERyYXdpbmcuc2V0Q2xpcFVybCBjYWxscyBvbiB0cmFjZS1tb2R1bGUgYW5kIHRyYWNlIGxheWVyc1xuICAgICAgICAgICAgLy8gZG93bnN0cmVhbVxuICAgICAgICAgICAgcGxvdGluZm8ubGF5ZXJDbGlwSWQgPSBsYXllckNsaXBJZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB4TGluZXNYTGVmdCwgeExpbmVzWFJpZ2h0LCB4TGluZXNZQm90dG9tLCB4TGluZXNZVG9wLFxuICAgICAgICBsZWZ0WUxpbmVXaWR0aCwgcmlnaHRZTGluZVdpZHRoO1xuICAgIHZhciB5TGluZXNZQm90dG9tLCB5TGluZXNZVG9wLCB5TGluZXNYTGVmdCwgeUxpbmVzWFJpZ2h0LFxuICAgICAgICBjb25uZWN0WUJvdHRvbSwgY29ubmVjdFlUb3A7XG4gICAgdmFyIGV4dHJhU3VicGxvdDtcblxuICAgIGZ1bmN0aW9uIHhMaW5lUGF0aCh5KSB7XG4gICAgICAgIHJldHVybiAnTScgKyB4TGluZXNYTGVmdCArICcsJyArIHkgKyAnSCcgKyB4TGluZXNYUmlnaHQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24geExpbmVQYXRoRnJlZSh5KSB7XG4gICAgICAgIHJldHVybiAnTScgKyB4YS5fb2Zmc2V0ICsgJywnICsgeSArICdoJyArIHhhLl9sZW5ndGg7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24geUxpbmVQYXRoKHgpIHtcbiAgICAgICAgcmV0dXJuICdNJyArIHggKyAnLCcgKyB5TGluZXNZVG9wICsgJ1YnICsgeUxpbmVzWUJvdHRvbTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB5TGluZVBhdGhGcmVlKHgpIHtcbiAgICAgICAgcmV0dXJuICdNJyArIHggKyAnLCcgKyB5YS5fb2Zmc2V0ICsgJ3YnICsgeWEuX2xlbmd0aDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWluUGF0aChheCwgcGF0aEZuLCBwYXRoRm5GcmVlKSB7XG4gICAgICAgIGlmKCFheC5zaG93bGluZSB8fCBzdWJwbG90ICE9PSBheC5fbWFpblN1YnBsb3QpIHJldHVybiAnJztcbiAgICAgICAgaWYoIWF4Ll9hbmNob3JBeGlzKSByZXR1cm4gcGF0aEZuRnJlZShheC5fbWFpbkxpbmVQb3NpdGlvbik7XG4gICAgICAgIHZhciBvdXQgPSBwYXRoRm4oYXguX21haW5MaW5lUG9zaXRpb24pO1xuICAgICAgICBpZihheC5taXJyb3IpIG91dCArPSBwYXRoRm4oYXguX21haW5NaXJyb3JQb3NpdGlvbik7XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuXG4gICAgZm9yKHN1YnBsb3QgaW4gZnVsbExheW91dC5fcGxvdHMpIHtcbiAgICAgICAgcGxvdGluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90XTtcbiAgICAgICAgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICAgICAgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgICAgICAvKlxuICAgICAgICAgKiB4IGxpbmVzIGdldCBsb25nZXIgd2hlcmUgdGhleSBtZWV0IHkgbGluZXMsIHRvIG1ha2UgYSBjcmlzcCBjb3JuZXIuXG4gICAgICAgICAqIFRoZSB4IGxpbmVzIGdldCB0aGUgcGFkZGluZyAobWFyZ2luLnBhZCkgcGx1cyB0aGUgeSBsaW5lIHdpZHRoIHRvXG4gICAgICAgICAqIGZpbGwgdXAgdGhlIGNvcm5lciBuaWNlbHkuIEZyZWUgeCBsaW5lcyBhcmUgZXhjbHVkZWQgLSB0aGV5IGFsd2F5c1xuICAgICAgICAgKiBzcGFuIGV4YWN0bHkgdGhlIGRhdGEgYXJlYSBvZiB0aGUgcGxvdFxuICAgICAgICAgKlxuICAgICAgICAgKiAgfCBYWFhYWFxuICAgICAgICAgKiAgfCBYWFhYWFxuICAgICAgICAgKiAgfFxuICAgICAgICAgKiAgKy0tLS0tLVxuICAgICAgICAgKiAgICAgeDFcbiAgICAgICAgICogICAgLS0tLS1cbiAgICAgICAgICogICAgIHgyXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgeFBhdGggPSAnTTAsMCc7XG4gICAgICAgIGlmKHNob3VsZFNob3dMaW5lc09yVGlja3MoeGEsIHN1YnBsb3QpKSB7XG4gICAgICAgICAgICBsZWZ0WUxpbmVXaWR0aCA9IGZpbmRDb3VudGVyQXhpc0xpbmVXaWR0aCh4YSwgJ2xlZnQnLCB5YSwgYXhMaXN0KTtcbiAgICAgICAgICAgIHhMaW5lc1hMZWZ0ID0geGEuX29mZnNldCAtIChsZWZ0WUxpbmVXaWR0aCA/IChwYWQgKyBsZWZ0WUxpbmVXaWR0aCkgOiAwKTtcbiAgICAgICAgICAgIHJpZ2h0WUxpbmVXaWR0aCA9IGZpbmRDb3VudGVyQXhpc0xpbmVXaWR0aCh4YSwgJ3JpZ2h0JywgeWEsIGF4TGlzdCk7XG4gICAgICAgICAgICB4TGluZXNYUmlnaHQgPSB4YS5fb2Zmc2V0ICsgeGEuX2xlbmd0aCArIChyaWdodFlMaW5lV2lkdGggPyAocGFkICsgcmlnaHRZTGluZVdpZHRoKSA6IDApO1xuICAgICAgICAgICAgeExpbmVzWUJvdHRvbSA9IGdldExpbmVQb3NpdGlvbih4YSwgeWEsICdib3R0b20nKTtcbiAgICAgICAgICAgIHhMaW5lc1lUb3AgPSBnZXRMaW5lUG9zaXRpb24oeGEsIHlhLCAndG9wJyk7XG5cbiAgICAgICAgICAgIC8vIHNhdmUgYXhpcyBsaW5lIHBvc2l0aW9ucyBmb3IgZXh0cmEgdGlja3MgdG8gcmVmZXJlbmNlXG4gICAgICAgICAgICAvLyBlYWNoIHN1YnBsb3QgdGhhdCBnZXRzIHRpY2tzIGZyb20gXCJhbGx0aWNrc1wiIGdldHMgYW4gZW50cnk6XG4gICAgICAgICAgICAvLyAgICBbbGVmdCBvciBib3R0b20sIHJpZ2h0IG9yIHRvcF1cbiAgICAgICAgICAgIGV4dHJhU3VicGxvdCA9ICgheGEuX2FuY2hvckF4aXMgfHwgc3VicGxvdCAhPT0geGEuX21haW5TdWJwbG90KTtcbiAgICAgICAgICAgIGlmKGV4dHJhU3VicGxvdCAmJiAoeGEubWlycm9yID09PSAnYWxsdGlja3MnIHx8IHhhLm1pcnJvciA9PT0gJ2FsbCcpKSB7XG4gICAgICAgICAgICAgICAgeGEuX2xpbmVwb3NpdGlvbnNbc3VicGxvdF0gPSBbeExpbmVzWUJvdHRvbSwgeExpbmVzWVRvcF07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHhQYXRoID0gbWFpblBhdGgoeGEsIHhMaW5lUGF0aCwgeExpbmVQYXRoRnJlZSk7XG4gICAgICAgICAgICBpZihleHRyYVN1YnBsb3QgJiYgeGEuc2hvd2xpbmUgJiYgKHhhLm1pcnJvciA9PT0gJ2FsbCcgfHwgeGEubWlycm9yID09PSAnYWxsdGlja3MnKSkge1xuICAgICAgICAgICAgICAgIHhQYXRoICs9IHhMaW5lUGF0aCh4TGluZXNZQm90dG9tKSArIHhMaW5lUGF0aCh4TGluZXNZVG9wKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcGxvdGluZm8ueGxpbmVzXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCB4YS5fbHcgKyAncHgnKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgeGEuc2hvd2xpbmUgP1xuICAgICAgICAgICAgICAgICAgICB4YS5saW5lY29sb3IgOiAncmdiYSgwLDAsMCwwKScpO1xuICAgICAgICB9XG4gICAgICAgIHBsb3RpbmZvLnhsaW5lcy5hdHRyKCdkJywgeFBhdGgpO1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIHkgbGluZXMgdGhhdCBtZWV0IHggYXhlcyBnZXQgbG9uZ2VyIG9ubHkgYnkgbWFyZ2luLnBhZCwgYmVjYXVzZVxuICAgICAgICAgKiB0aGUgeCBheGVzIGZpbGwgaW4gdGhlIGNvcm5lciBzcGFjZS4gRnJlZSB5IGF4ZXMsIGxpa2UgZnJlZSB4IGF4ZXMsXG4gICAgICAgICAqIGFsd2F5cyBzcGFuIGV4YWN0bHkgdGhlIGRhdGEgYXJlYSBvZiB0aGUgcGxvdFxuICAgICAgICAgKlxuICAgICAgICAgKiAgIHwgICB8IFhYWFhcbiAgICAgICAgICogeTJ8IHkxfCBYWFhYXG4gICAgICAgICAqICAgfCAgIHwgWFhYWFxuICAgICAgICAgKiAgICAgICB8XG4gICAgICAgICAqICAgICAgICstLS0tLVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIHlQYXRoID0gJ00wLDAnO1xuICAgICAgICBpZihzaG91bGRTaG93TGluZXNPclRpY2tzKHlhLCBzdWJwbG90KSkge1xuICAgICAgICAgICAgY29ubmVjdFlCb3R0b20gPSBmaW5kQ291bnRlckF4aXNMaW5lV2lkdGgoeWEsICdib3R0b20nLCB4YSwgYXhMaXN0KTtcbiAgICAgICAgICAgIHlMaW5lc1lCb3R0b20gPSB5YS5fb2Zmc2V0ICsgeWEuX2xlbmd0aCArIChjb25uZWN0WUJvdHRvbSA/IHBhZCA6IDApO1xuICAgICAgICAgICAgY29ubmVjdFlUb3AgPSBmaW5kQ291bnRlckF4aXNMaW5lV2lkdGgoeWEsICd0b3AnLCB4YSwgYXhMaXN0KTtcbiAgICAgICAgICAgIHlMaW5lc1lUb3AgPSB5YS5fb2Zmc2V0IC0gKGNvbm5lY3RZVG9wID8gcGFkIDogMCk7XG4gICAgICAgICAgICB5TGluZXNYTGVmdCA9IGdldExpbmVQb3NpdGlvbih5YSwgeGEsICdsZWZ0Jyk7XG4gICAgICAgICAgICB5TGluZXNYUmlnaHQgPSBnZXRMaW5lUG9zaXRpb24oeWEsIHhhLCAncmlnaHQnKTtcblxuICAgICAgICAgICAgZXh0cmFTdWJwbG90ID0gKCF5YS5fYW5jaG9yQXhpcyB8fCBzdWJwbG90ICE9PSB5YS5fbWFpblN1YnBsb3QpO1xuICAgICAgICAgICAgaWYoZXh0cmFTdWJwbG90ICYmICh5YS5taXJyb3IgPT09ICdhbGx0aWNrcycgfHwgeWEubWlycm9yID09PSAnYWxsJykpIHtcbiAgICAgICAgICAgICAgICB5YS5fbGluZXBvc2l0aW9uc1tzdWJwbG90XSA9IFt5TGluZXNYTGVmdCwgeUxpbmVzWFJpZ2h0XTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgeVBhdGggPSBtYWluUGF0aCh5YSwgeUxpbmVQYXRoLCB5TGluZVBhdGhGcmVlKTtcbiAgICAgICAgICAgIGlmKGV4dHJhU3VicGxvdCAmJiB5YS5zaG93bGluZSAmJiAoeWEubWlycm9yID09PSAnYWxsJyB8fCB5YS5taXJyb3IgPT09ICdhbGx0aWNrcycpKSB7XG4gICAgICAgICAgICAgICAgeVBhdGggKz0geUxpbmVQYXRoKHlMaW5lc1hMZWZ0KSArIHlMaW5lUGF0aCh5TGluZXNYUmlnaHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwbG90aW5mby55bGluZXNcbiAgICAgICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIHlhLl9sdyArICdweCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCB5YS5zaG93bGluZSA/XG4gICAgICAgICAgICAgICAgICAgIHlhLmxpbmVjb2xvciA6ICdyZ2JhKDAsMCwwLDApJyk7XG4gICAgICAgIH1cbiAgICAgICAgcGxvdGluZm8ueWxpbmVzLmF0dHIoJ2QnLCB5UGF0aCk7XG4gICAgfVxuXG4gICAgQXhlcy5tYWtlQ2xpcFBhdGhzKGdkKTtcblxuICAgIHJldHVybiBnZC5fcHJvbWlzZXMubGVuZ3RoICYmIFByb21pc2UuYWxsKGdkLl9wcm9taXNlcyk7XG59XG5cbmZ1bmN0aW9uIHNob3VsZFNob3dMaW5lc09yVGlja3MoYXgsIHN1YnBsb3QpIHtcbiAgICByZXR1cm4gKGF4LnRpY2tzIHx8IGF4LnNob3dsaW5lKSAmJlxuICAgICAgICAoc3VicGxvdCA9PT0gYXguX21haW5TdWJwbG90IHx8IGF4Lm1pcnJvciA9PT0gJ2FsbCcgfHwgYXgubWlycm9yID09PSAnYWxsdGlja3MnKTtcbn1cblxuLypcbiAqIHNob3VsZCB3ZSBkcmF3IGEgbGluZSBvbiBjb3VudGVyQXggYXQgdGhpcyBzaWRlIG9mIGF4P1xuICogSXQncyBhc3N1bWVkIHRoYXQgY291bnRlckF4IGlzIGtub3duIHRvIG92ZXJsYXkgdGhlIHN1YnBsb3Qgd2UncmUgd29ya2luZyBvblxuICogYnV0IGl0IG1heSBub3QgYmUgaXRzIG1haW4gYXhpcy5cbiAqL1xuZnVuY3Rpb24gc2hvdWxkU2hvd0xpbmVUaGlzU2lkZShheCwgc2lkZSwgY291bnRlckF4KSB7XG4gICAgLy8gZG9lcyBjb3VudGVyQXggZ2V0IGEgbGluZSBhdCBhbGw/XG4gICAgaWYoIWNvdW50ZXJBeC5zaG93bGluZSB8fCAhY291bnRlckF4Ll9sdykgcmV0dXJuIGZhbHNlO1xuXG4gICAgLy8gYXJlIHdlIGRyYXdpbmcgKmFsbCogbGluZXMgZm9yIGNvdW50ZXJBeD9cbiAgICBpZihjb3VudGVyQXgubWlycm9yID09PSAnYWxsJyB8fCBjb3VudGVyQXgubWlycm9yID09PSAnYWxsdGlja3MnKSByZXR1cm4gdHJ1ZTtcblxuICAgIHZhciBhbmNob3JBeCA9IGNvdW50ZXJBeC5fYW5jaG9yQXhpcztcblxuICAgIC8vIGlzIHRoaXMgYSBmcmVlIGF4aXM/IGZyZWUgYXhlcyBjYW4gb25seSBoYXZlIGEgc3VicGxvdCBzaWRlLWxpbmUgd2l0aCBhbGwodGlja3MpPyBtaXJyb3JpbmdcbiAgICBpZighYW5jaG9yQXgpIHJldHVybiBmYWxzZTtcblxuICAgIC8vIGluIG9yZGVyIHRvIGhhbmRsZSBjYXNlcyB3aGVyZSB0aGUgdXNlciBmb3Jnb3QgdG8gYW5jaG9yIHRoaXMgYXhpcyBjb3JyZWN0bHlcbiAgICAvLyAoYmVjYXVzZSBpdHMgZGVmYXVsdCBhbmNob3IgaGFzIHRoZSBzYW1lIGRvbWFpbiBvbiB0aGUgcmVsZXZhbnQgZW5kKVxuICAgIC8vIGNoZWNrIHdoZXRoZXIgdGhlIHJlbGV2YW50IHBvc2l0aW9uIGlzIHRoZSBzYW1lLlxuICAgIHZhciBzaWRlSW5kZXggPSBhbGlnbm1lbnRDb25zdGFudHMuRlJPTV9CTFtzaWRlXTtcbiAgICBpZihjb3VudGVyQXguc2lkZSA9PT0gc2lkZSkge1xuICAgICAgICByZXR1cm4gYW5jaG9yQXguZG9tYWluW3NpZGVJbmRleF0gPT09IGF4LmRvbWFpbltzaWRlSW5kZXhdO1xuICAgIH1cbiAgICByZXR1cm4gY291bnRlckF4Lm1pcnJvciAmJiBhbmNob3JBeC5kb21haW5bMSAtIHNpZGVJbmRleF0gPT09IGF4LmRvbWFpblsxIC0gc2lkZUluZGV4XTtcbn1cblxuLypcbiAqIElzIHRoZXJlIGFub3RoZXIgYXhpcyBpbnRlcnNlY3RpbmcgYHNpZGVgIGVuZCBvZiBgYXhgP1xuICogRmlyc3QgbG9vayBhdCBgY291bnRlckF4YCAodGhlIGF4aXMgZm9yIHRoaXMgc3VicGxvdCksXG4gKiB0aGVuIGF0IGFsbCBvdGhlciBwb3RlbnRpYWwgY291bnRlcmF4ZXMgb24gb3Igb3ZlcmxheWluZyB0aGlzIHN1YnBsb3QuXG4gKiBUYWtlIHRoZSBsaW5lIHdpZHRoIGZyb20gdGhlIGZpcnN0IG9uZSB0aGF0IGhhcyBhIGxpbmUuXG4gKi9cbmZ1bmN0aW9uIGZpbmRDb3VudGVyQXhpc0xpbmVXaWR0aChheCwgc2lkZSwgY291bnRlckF4LCBheExpc3QpIHtcbiAgICBpZihzaG91bGRTaG93TGluZVRoaXNTaWRlKGF4LCBzaWRlLCBjb3VudGVyQXgpKSB7XG4gICAgICAgIHJldHVybiBjb3VudGVyQXguX2x3O1xuICAgIH1cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBheGkgPSBheExpc3RbaV07XG4gICAgICAgIGlmKGF4aS5fbWFpbkF4aXMgPT09IGNvdW50ZXJBeC5fbWFpbkF4aXMgJiYgc2hvdWxkU2hvd0xpbmVUaGlzU2lkZShheCwgc2lkZSwgYXhpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGF4aS5fbHc7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIDA7XG59XG5cbmV4cG9ydHMuZHJhd01haW5UaXRsZSA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciB0ZXh0QW5jaG9yID0gZ2V0TWFpblRpdGxlVGV4dEFuY2hvcihmdWxsTGF5b3V0KTtcbiAgICB2YXIgZHkgPSBnZXRNYWluVGl0bGVEeShmdWxsTGF5b3V0KTtcblxuICAgIFRpdGxlcy5kcmF3KGdkLCAnZ3RpdGxlJywge1xuICAgICAgICBwcm9wQ29udGFpbmVyOiBmdWxsTGF5b3V0LFxuICAgICAgICBwcm9wTmFtZTogJ3RpdGxlLnRleHQnLFxuICAgICAgICBwbGFjZWhvbGRlcjogZnVsbExheW91dC5fZGZsdFRpdGxlLnBsb3QsXG4gICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgIHg6IGdldE1haW5UaXRsZVgoZnVsbExheW91dCwgdGV4dEFuY2hvciksXG4gICAgICAgICAgICB5OiBnZXRNYWluVGl0bGVZKGZ1bGxMYXlvdXQsIGR5KSxcbiAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6IHRleHRBbmNob3IsXG4gICAgICAgICAgICBkeTogZHlcbiAgICAgICAgfVxuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gZ2V0TWFpblRpdGxlWChmdWxsTGF5b3V0LCB0ZXh0QW5jaG9yKSB7XG4gICAgdmFyIHRpdGxlID0gZnVsbExheW91dC50aXRsZTtcbiAgICB2YXIgZ3MgPSBmdWxsTGF5b3V0Ll9zaXplO1xuICAgIHZhciBoUGFkU2hpZnQgPSAwO1xuXG4gICAgaWYodGV4dEFuY2hvciA9PT0gU1ZHX1RFWFRfQU5DSE9SX1NUQVJUKSB7XG4gICAgICAgIGhQYWRTaGlmdCA9IHRpdGxlLnBhZC5sO1xuICAgIH0gZWxzZSBpZih0ZXh0QW5jaG9yID09PSBTVkdfVEVYVF9BTkNIT1JfRU5EKSB7XG4gICAgICAgIGhQYWRTaGlmdCA9IC10aXRsZS5wYWQucjtcbiAgICB9XG5cbiAgICBzd2l0Y2godGl0bGUueHJlZikge1xuICAgICAgICBjYXNlICdwYXBlcic6XG4gICAgICAgICAgICByZXR1cm4gZ3MubCArIGdzLncgKiB0aXRsZS54ICsgaFBhZFNoaWZ0O1xuICAgICAgICBjYXNlICdjb250YWluZXInOlxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGZ1bGxMYXlvdXQud2lkdGggKiB0aXRsZS54ICsgaFBhZFNoaWZ0O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0TWFpblRpdGxlWShmdWxsTGF5b3V0LCBkeSkge1xuICAgIHZhciB0aXRsZSA9IGZ1bGxMYXlvdXQudGl0bGU7XG4gICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICB2YXIgdlBhZFNoaWZ0ID0gMDtcblxuICAgIGlmKGR5ID09PSAnMGVtJyB8fCAhZHkpIHtcbiAgICAgICAgdlBhZFNoaWZ0ID0gLXRpdGxlLnBhZC5iO1xuICAgIH0gZWxzZSBpZihkeSA9PT0gYWxpZ25tZW50Q29uc3RhbnRzLkNBUF9TSElGVCArICdlbScpIHtcbiAgICAgICAgdlBhZFNoaWZ0ID0gdGl0bGUucGFkLnQ7XG4gICAgfVxuXG4gICAgaWYodGl0bGUueSA9PT0gJ2F1dG8nKSB7XG4gICAgICAgIHJldHVybiBncy50IC8gMjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzd2l0Y2godGl0bGUueXJlZikge1xuICAgICAgICAgICAgY2FzZSAncGFwZXInOlxuICAgICAgICAgICAgICAgIHJldHVybiBncy50ICsgZ3MuaCAtIGdzLmggKiB0aXRsZS55ICsgdlBhZFNoaWZ0O1xuICAgICAgICAgICAgY2FzZSAnY29udGFpbmVyJzpcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bGxMYXlvdXQuaGVpZ2h0IC0gZnVsbExheW91dC5oZWlnaHQgKiB0aXRsZS55ICsgdlBhZFNoaWZ0O1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRNYWluVGl0bGVUZXh0QW5jaG9yKGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgdGl0bGUgPSBmdWxsTGF5b3V0LnRpdGxlO1xuXG4gICAgdmFyIHRleHRBbmNob3IgPSBTVkdfVEVYVF9BTkNIT1JfTUlERExFO1xuICAgIGlmKExpYi5pc1JpZ2h0QW5jaG9yKHRpdGxlKSkge1xuICAgICAgICB0ZXh0QW5jaG9yID0gU1ZHX1RFWFRfQU5DSE9SX0VORDtcbiAgICB9IGVsc2UgaWYoTGliLmlzTGVmdEFuY2hvcih0aXRsZSkpIHtcbiAgICAgICAgdGV4dEFuY2hvciA9IFNWR19URVhUX0FOQ0hPUl9TVEFSVDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGV4dEFuY2hvcjtcbn1cblxuZnVuY3Rpb24gZ2V0TWFpblRpdGxlRHkoZnVsbExheW91dCkge1xuICAgIHZhciB0aXRsZSA9IGZ1bGxMYXlvdXQudGl0bGU7XG5cbiAgICB2YXIgZHkgPSAnMGVtJztcbiAgICBpZihMaWIuaXNUb3BBbmNob3IodGl0bGUpKSB7XG4gICAgICAgIGR5ID0gYWxpZ25tZW50Q29uc3RhbnRzLkNBUF9TSElGVCArICdlbSc7XG4gICAgfSBlbHNlIGlmKExpYi5pc01pZGRsZUFuY2hvcih0aXRsZSkpIHtcbiAgICAgICAgZHkgPSBhbGlnbm1lbnRDb25zdGFudHMuTUlEX1NISUZUICsgJ2VtJztcbiAgICB9XG5cbiAgICByZXR1cm4gZHk7XG59XG5cbmV4cG9ydHMuZG9UcmFjZVN0eWxlID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgY2FsY2RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgZWRpdFN0eWxlQ2FsbHMgPSBbXTtcbiAgICB2YXIgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjZCA9IGNhbGNkYXRhW2ldO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF0gfHwge307XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZSB8fCB7fTtcbiAgICAgICAgdmFyIF9tb2R1bGUgPSB0cmFjZS5fbW9kdWxlIHx8IHt9O1xuXG4gICAgICAgIC8vIFNlZSBpZiB3ZSBuZWVkIHRvIGRvIGFycmF5c1RvQ2FsY2RhdGFcbiAgICAgICAgLy8gY2FsbCBpdCByZWdhcmRsZXNzIG9mIHdoYXQgY2hhbmdlIHdlIG1hZGUsIGluIGNhc2VcbiAgICAgICAgLy8gc3VwcGx5RGVmYXVsdHMgYnJvdWdodCBpbiBhbiBhcnJheSB0aGF0IHdhcyBhbHJlYWR5XG4gICAgICAgIC8vIGluIGdkLmRhdGEgYnV0IG5vdCBpbiBnZC5fZnVsbERhdGEgcHJldmlvdXNseVxuICAgICAgICB2YXIgYXJyYXlzVG9DYWxjZGF0YSA9IF9tb2R1bGUuYXJyYXlzVG9DYWxjZGF0YTtcbiAgICAgICAgaWYoYXJyYXlzVG9DYWxjZGF0YSkgYXJyYXlzVG9DYWxjZGF0YShjZCwgdHJhY2UpO1xuXG4gICAgICAgIHZhciBlZGl0U3R5bGUgPSBfbW9kdWxlLmVkaXRTdHlsZTtcbiAgICAgICAgaWYoZWRpdFN0eWxlKSBlZGl0U3R5bGVDYWxscy5wdXNoKHtmbjogZWRpdFN0eWxlLCBjZDA6IGNkMH0pO1xuICAgIH1cblxuICAgIGlmKGVkaXRTdHlsZUNhbGxzLmxlbmd0aCkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBlZGl0U3R5bGVDYWxscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGVkaXQgPSBlZGl0U3R5bGVDYWxsc1tpXTtcbiAgICAgICAgICAgIGVkaXQuZm4oZ2QsIGVkaXQuY2QwKTtcbiAgICAgICAgfVxuICAgICAgICBjbGVhckdsQ2FudmFzZXMoZ2QpO1xuICAgICAgICBleHBvcnRzLnJlZHJhd1JlZ2xUcmFjZXMoZ2QpO1xuICAgIH1cblxuICAgIFBsb3RzLnN0eWxlKGdkKTtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2xlZ2VuZCcsICdkcmF3JykoZ2QpO1xuXG4gICAgcmV0dXJuIFBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpO1xufTtcblxuZXhwb3J0cy5kb0NvbG9yQmFycyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjb2xvcmJhcicsICdkcmF3JykoZ2QpO1xuICAgIHJldHVybiBQbG90cy5wcmV2aW91c1Byb21pc2VzKGdkKTtcbn07XG5cbi8vIGZvcmNlIHBsb3QoKSB0byByZWRvIHRoZSBsYXlvdXQgYW5kIHJlcGxvdCB3aXRoIHRoZSBtb2RpZmllZCBsYXlvdXRcbmV4cG9ydHMubGF5b3V0UmVwbG90ID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgbGF5b3V0ID0gZ2QubGF5b3V0O1xuICAgIGdkLmxheW91dCA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gUmVnaXN0cnkuY2FsbCgncGxvdCcsIGdkLCAnJywgbGF5b3V0KTtcbn07XG5cbmV4cG9ydHMuZG9MZWdlbmQgPSBmdW5jdGlvbihnZCkge1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnbGVnZW5kJywgJ2RyYXcnKShnZCk7XG4gICAgcmV0dXJuIFBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpO1xufTtcblxuZXhwb3J0cy5kb1RpY2tzUmVsYXlvdXQgPSBmdW5jdGlvbihnZCkge1xuICAgIEF4ZXMuZHJhdyhnZCwgJ3JlZHJhdycpO1xuXG4gICAgaWYoZ2QuX2Z1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcykge1xuICAgICAgICBSZWdpc3RyeS5zdWJwbG90c1JlZ2lzdHJ5LnNwbG9tLnVwZGF0ZUdyaWQoZ2QpO1xuICAgICAgICBjbGVhckdsQ2FudmFzZXMoZ2QpO1xuICAgICAgICBleHBvcnRzLnJlZHJhd1JlZ2xUcmFjZXMoZ2QpO1xuICAgIH1cblxuICAgIGV4cG9ydHMuZHJhd01haW5UaXRsZShnZCk7XG4gICAgcmV0dXJuIFBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpO1xufTtcblxuZXhwb3J0cy5kb01vZGVCYXIgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBNb2RlQmFyLm1hbmFnZShnZCk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB1cGRhdGVGeCA9IGZ1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlc1tpXS51cGRhdGVGeDtcbiAgICAgICAgaWYodXBkYXRlRngpIHVwZGF0ZUZ4KGdkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gUGxvdHMucHJldmlvdXNQcm9taXNlcyhnZCk7XG59O1xuXG5leHBvcnRzLmRvQ2FtZXJhID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzY2VuZUlkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzLmdsM2Q7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2NlbmVJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNjZW5lTGF5b3V0ID0gZnVsbExheW91dFtzY2VuZUlkc1tpXV07XG4gICAgICAgIHZhciBzY2VuZSA9IHNjZW5lTGF5b3V0Ll9zY2VuZTtcblxuICAgICAgICB2YXIgY2FtZXJhRGF0YSA9IHNjZW5lTGF5b3V0LmNhbWVyYTtcbiAgICAgICAgc2NlbmUuc2V0Q2FtZXJhKGNhbWVyYURhdGEpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMuZHJhd0RhdGEgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBjbGVhckdsQ2FudmFzZXMoZ2QpO1xuXG4gICAgLy8gbG9vcCBvdmVyIHRoZSBiYXNlIHBsb3QgbW9kdWxlcyBwcmVzZW50IG9uIGdyYXBoXG4gICAgdmFyIGJhc2VQbG90TW9kdWxlcyA9IGZ1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcztcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGJhc2VQbG90TW9kdWxlc1tpXS5wbG90KGdkKTtcbiAgICB9XG5cbiAgICBleHBvcnRzLnJlZHJhd1JlZ2xUcmFjZXMoZ2QpO1xuXG4gICAgLy8gc3R5bGluZyBzZXBhcmF0ZSBmcm9tIGRyYXdpbmdcbiAgICBQbG90cy5zdHlsZShnZCk7XG5cbiAgICAvLyBzaG93IGFubm90YXRpb25zIGFuZCBzaGFwZXNcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ3NoYXBlcycsICdkcmF3JykoZ2QpO1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMnLCAnZHJhdycpKGdkKTtcblxuICAgIC8vIE1hcmsgdGhlIGZpcnN0IHJlbmRlciBhcyBjb21wbGV0ZVxuICAgIGZ1bGxMYXlvdXQuX3JlcGxvdHRpbmcgPSBmYWxzZTtcblxuICAgIHJldHVybiBQbG90cy5wcmV2aW91c1Byb21pc2VzKGdkKTtcbn07XG5cbi8vIERyYXcgKG9yIHJlZHJhdykgYWxsIHJlZ2wtYmFzZWQgdHJhY2VzIGluIG9uZSBnbyxcbi8vIHVzZWZ1bCBkdXJpbmcgZHJhZyBhbmQgc2VsZWN0aW9uIHdoZXJlIGJ1ZmZlcnMgb2YgdGFyZ2V0ZWQgdHJhY2VzIGFyZSB1cGRhdGVkLFxuLy8gYnV0IGFsbCB0cmFjZXMgbmVlZCB0byBiZSByZWRyYXduIGZvbGxvd2luZyBjbGVhckdsQ2FudmFzZXMuXG4vL1xuLy8gTm90ZSB0aGF0IF9tb2R1bGUucGxvdCBmb3IgcmVnbCB0cmFjZSBkb2VzIE5PVCBkcmF3IHRoaW5nc1xuLy8gb24gdGhlIGNhbnZhcywgdGhleSBvbmx5IHVwZGF0ZSB0aGUgYnVmZmVycy5cbi8vIERyYXdpbmcgaXMgcGVyZm9ybSBoZXJlLlxuLy9cbi8vIFRPRE8gdHJ5IGFkZGluZyBwZXItc3VicGxvdCBvcHRpb24gdXNpbmcgZ2wuU0NJU1NPUl9URVNUIGZvclxuLy8gbm9uLW92ZXJsYXlpbmcsIGRpc2pvaW50IHN1YnBsb3RzLlxuLy9cbi8vIFRPRE8gdHJ5IHRvIGluY2x1ZGUgcGFyY29vcmRzIGluIGhlcmUuXG4vLyBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvMzA2OVxuZXhwb3J0cy5yZWRyYXdSZWdsVHJhY2VzID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgaWYoZnVsbExheW91dC5faGFzKCdyZWdsJykpIHtcbiAgICAgICAgdmFyIGZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhO1xuICAgICAgICB2YXIgY2FydGVzaWFuSWRzID0gW107XG4gICAgICAgIHZhciBwb2xhcklkcyA9IFtdO1xuICAgICAgICB2YXIgaSwgc3A7XG5cbiAgICAgICAgaWYoZnVsbExheW91dC5faGFzT25seUxhcmdlU3Bsb21zKSB7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9zcGxvbUdyaWQuZHJhdygpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTi5CLlxuICAgICAgICAvLyAtIExvb3Agb3ZlciBmdWxsRGF0YSAobm90IF9zcGxvbVNjZW5lcykgdG8gcHJlc2VydmUgc3Bsb20gdHJhY2UtdG8tdHJhY2Ugb3JkZXJpbmdcbiAgICAgICAgLy8gLSBGaWxsIGxpc3QgaWYgc3VicGxvdCBpZHMgKGluc3RlYWQgb2YgZnVsbExheW91dC5fc3VicGxvdHMpIHRvIGhhbmRsZSBjYXNlcyB3aGVyZSBhbGwgdHJhY2VzXG4gICAgICAgIC8vICAgb2YgYSBnaXZlbiBtb2R1bGUgYXJlIGB2aXNpYmxlICE9PSB0cnVlYFxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgICAgIGlmKHRyYWNlLnZpc2libGUgPT09IHRydWUgJiYgdHJhY2UuX2xlbmd0aCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdzcGxvbScpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVsbExheW91dC5fc3Bsb21TY2VuZXNbdHJhY2UudWlkXS5kcmF3KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHRyYWNlLnR5cGUgPT09ICdzY2F0dGVyZ2wnKSB7XG4gICAgICAgICAgICAgICAgICAgIExpYi5wdXNoVW5pcXVlKGNhcnRlc2lhbklkcywgdHJhY2UueGF4aXMgKyB0cmFjZS55YXhpcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHRyYWNlLnR5cGUgPT09ICdzY2F0dGVycG9sYXJnbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUocG9sYXJJZHMsIHRyYWNlLnN1YnBsb3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNhcnRlc2lhbklkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc3AgPSBmdWxsTGF5b3V0Ll9wbG90c1tjYXJ0ZXNpYW5JZHNbaV1dO1xuICAgICAgICAgICAgaWYoc3AuX3NjZW5lKSBzcC5fc2NlbmUuZHJhdygpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgcG9sYXJJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHNwID0gZnVsbExheW91dFtwb2xhcklkc1tpXV0uX3N1YnBsb3Q7XG4gICAgICAgICAgICBpZihzcC5fc2NlbmUpIHNwLl9zY2VuZS5kcmF3KCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5leHBvcnRzLmRvQXV0b1JhbmdlQW5kQ29uc3RyYWludHMgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGF4TGlzdCA9IEF4ZXMubGlzdChnZCwgJycsIHRydWUpO1xuICAgIHZhciBtYXRjaEdyb3VwcyA9IGZ1bGxMYXlvdXQuX2F4aXNNYXRjaEdyb3VwcyB8fCBbXTtcbiAgICB2YXIgYXg7XG4gICAgdmFyIGF4Um5nO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBheCA9IGF4TGlzdFtpXTtcbiAgICAgICAgY2xlYW5BeGlzQ29uc3RyYWludHMoZ2QsIGF4KTtcbiAgICAgICAgZG9BdXRvUmFuZ2UoZ2QsIGF4KTtcbiAgICB9XG5cbiAgICBlbmZvcmNlQXhpc0NvbnN0cmFpbnRzKGdkKTtcblxuICAgIGdyb3VwTG9vcDpcbiAgICBmb3IodmFyIGogPSAwOyBqIDwgbWF0Y2hHcm91cHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIGdyb3VwID0gbWF0Y2hHcm91cHNbal07XG4gICAgICAgIHZhciBybmcgPSBudWxsO1xuICAgICAgICB2YXIgaWQ7XG5cbiAgICAgICAgZm9yKGlkIGluIGdyb3VwKSB7XG4gICAgICAgICAgICBheCA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCBpZCk7XG4gICAgICAgICAgICBpZihheC5hdXRvcmFuZ2UgPT09IGZhbHNlKSBjb250aW51ZSBncm91cExvb3A7XG5cbiAgICAgICAgICAgIGF4Um5nID0gTGliLnNpbXBsZU1hcChheC5yYW5nZSwgYXgucjJsKTtcbiAgICAgICAgICAgIGlmKHJuZykge1xuICAgICAgICAgICAgICAgIGlmKHJuZ1swXSA8IHJuZ1sxXSkge1xuICAgICAgICAgICAgICAgICAgICBybmdbMF0gPSBNYXRoLm1pbihybmdbMF0sIGF4Um5nWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgcm5nWzFdID0gTWF0aC5tYXgocm5nWzFdLCBheFJuZ1sxXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcm5nWzBdID0gTWF0aC5tYXgocm5nWzBdLCBheFJuZ1swXSk7XG4gICAgICAgICAgICAgICAgICAgIHJuZ1sxXSA9IE1hdGgubWluKHJuZ1sxXSwgYXhSbmdbMV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcm5nID0gYXhSbmc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaWQgaW4gZ3JvdXApIHtcbiAgICAgICAgICAgIGF4ID0gQXhlcy5nZXRGcm9tSWQoZ2QsIGlkKTtcbiAgICAgICAgICAgIGF4LnJhbmdlID0gTGliLnNpbXBsZU1hcChybmcsIGF4Lmwycik7XG4gICAgICAgICAgICBheC5faW5wdXQucmFuZ2UgPSBheC5yYW5nZS5zbGljZSgpO1xuICAgICAgICAgICAgYXguc2V0U2NhbGUoKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8vIEFuIGluaXRpYWwgcGFpbnQgbXVzdCBiZSBjb21wbGV0ZWQgYmVmb3JlIHRoZXNlIGNvbXBvbmVudHMgY2FuIGJlXG4vLyBjb3JyZWN0bHkgc2l6ZWQgYW5kIHRoZSB3aG9sZSBwbG90IHJlLW1hcmdpbmVkLiBmdWxsTGF5b3V0Ll9yZXBsb3R0aW5nIG11c3Rcbi8vIGJlIHNldCB0byBmYWxzZSBiZWZvcmUgdGhlc2Ugd2lsbCB3b3JrIHByb3Blcmx5LlxuZXhwb3J0cy5maW5hbERyYXcgPSBmdW5jdGlvbihnZCkge1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnc2hhcGVzJywgJ2RyYXcnKShnZCk7XG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdpbWFnZXMnLCAnZHJhdycpKGdkKTtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Fubm90YXRpb25zJywgJ2RyYXcnKShnZCk7XG4gICAgLy8gVE9ETzogcmFuZ2VzbGlkZXJzIHJlYWxseSBiZWxvbmcgaW4gbWFyZ2luUHVzaGVycyBidXQgdGhleSBuZWVkIHRvIGJlXG4gICAgLy8gZHJhd24gYWZ0ZXIgZGF0YSAtIGNhbiB3ZSBhdCBsZWFzdCBnZXQgdGhlIG1hcmdpbiBwdXNoaW5nIHBhcnQgc2VwYXJhdGVkXG4gICAgLy8gb3V0IGFuZCBkb25lIGVhcmxpZXI/XG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdyYW5nZXNsaWRlcicsICdkcmF3JykoZ2QpO1xuICAgIC8vIFRPRE86IHJhbmdlc2VsZWN0b3Igb25seSBuZWVkcyB0byBiZSBoZXJlIChpbiBhZGRpdGlvbiB0byBkcmF3TWFyZ2luUHVzaGVycylcbiAgICAvLyBiZWNhdXNlIHRoZSBtYXJnaW5zIG5lZWQgdG8gYmUgZnVsbHkgZGV0ZXJtaW5lZCBiZWZvcmUgd2UgY2FuIGNhbGxcbiAgICAvLyBhdXRvcmFuZ2UgYW5kIHVwZGF0ZSBheGlzIHJhbmdlcyAod2hpY2ggcmFuZ2VzZWxlY3RvciBuZWVkcyB0byBrbm93IHdoaWNoXG4gICAgLy8gYnV0dG9uIGlzIGFjdGl2ZSkuIENhbiB3ZSBicmVhayBvdXQgaXRzIGF1dG9tYXJnaW4gc3RlcCBmcm9tIGl0cyBkcmF3IHN0ZXA/XG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdyYW5nZXNlbGVjdG9yJywgJ2RyYXcnKShnZCk7XG59O1xuXG5leHBvcnRzLmRyYXdNYXJnaW5QdXNoZXJzID0gZnVuY3Rpb24oZ2QpIHtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2xlZ2VuZCcsICdkcmF3JykoZ2QpO1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgncmFuZ2VzZWxlY3RvcicsICdkcmF3JykoZ2QpO1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnc2xpZGVycycsICdkcmF3JykoZ2QpO1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgndXBkYXRlbWVudXMnLCAnZHJhdycpKGdkKTtcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NvbG9yYmFyJywgJ2RyYXcnKShnZCk7XG59O1xuXG59LHtcIi4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi9jb21wb25lbnRzL21vZGViYXJcIjo2NTIsXCIuLi9jb21wb25lbnRzL3RpdGxlc1wiOjY4MSxcIi4uL2NvbnN0YW50cy9hbGlnbm1lbnRcIjo2ODgsXCIuLi9saWJcIjo3MTksXCIuLi9saWIvY2xlYXJfZ2xfY2FudmFzZXNcIjo3MDQsXCIuLi9wbG90cy9jYXJ0ZXNpYW4vYXV0b3JhbmdlXCI6NzY2LFwiLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi9wbG90cy9jYXJ0ZXNpYW4vY29uc3RyYWludHNcIjo3NzQsXCIuLi9wbG90cy9wbG90c1wiOjgyOCxcIi4uL3JlZ2lzdHJ5XCI6ODQ3LFwiZDNcIjoxNjN9XSw3NTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcbnZhciBpc1BsYWluT2JqZWN0ID0gTGliLmlzUGxhaW5PYmplY3Q7XG52YXIgUGxvdFNjaGVtYSA9IF9kZXJlcV8oJy4vcGxvdF9zY2hlbWEnKTtcbnZhciBQbG90cyA9IF9kZXJlcV8oJy4uL3Bsb3RzL3Bsb3RzJyk7XG52YXIgcGxvdEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgVGVtcGxhdGUgPSBfZGVyZXFfKCcuL3Bsb3RfdGVtcGxhdGUnKTtcbnZhciBkZmx0Q29uZmlnID0gX2RlcmVxXygnLi9wbG90X2NvbmZpZycpLmRmbHRDb25maWc7XG5cbi8qKlxuICogUGxvdGx5Lm1ha2VUZW1wbGF0ZTogY3JlYXRlIGEgdGVtcGxhdGUgb2ZmIGFuIGV4aXN0aW5nIGZpZ3VyZSB0byByZXVzZVxuICogc3R5bGUgYXR0cmlidXRlcyBvbiBvdGhlciBmaWd1cmVzLlxuICpcbiAqIE5vdGU6IHNlcGFyYXRlZCBmcm9tIHRoZSByZXN0IG9mIHRlbXBsYXRlcyBiZWNhdXNlIG90aGVyd2lzZSB3ZSBnZXQgY2lyY3VsYXJcbiAqIHJlZmVyZW5jZXMgZHVlIHRvIFBsb3RTY2hlbWEuXG4gKlxuICogQHBhcmFtIHtvYmplY3R8RE9NIGVsZW1lbnR8c3RyaW5nfSBmaWd1cmU6IFRoZSBmaWd1cmUgdG8gYmFzZSB0aGUgdGVtcGxhdGUgb25cbiAqICAgICBzaG91bGQgY29udGFpbiBhIHRyYWNlIGFycmF5IGBmaWd1cmUuZGF0YWBcbiAqICAgICBhbmQgYSBsYXlvdXQgb2JqZWN0IGBmaWd1cmUubGF5b3V0YFxuICogQHJldHVybnMge29iamVjdH0gdGVtcGxhdGU6IHRoZSBleHRyYWN0ZWQgdGVtcGxhdGUgLSBjYW4gdGhlbiBiZSB1c2VkIGFzXG4gKiAgICAgYGxheW91dC50ZW1wbGF0ZWAgaW4gYW5vdGhlciBmaWd1cmUuXG4gKi9cbmV4cG9ydHMubWFrZVRlbXBsYXRlID0gZnVuY3Rpb24oZmlndXJlKSB7XG4gICAgZmlndXJlID0gTGliLmlzUGxhaW5PYmplY3QoZmlndXJlKSA/IGZpZ3VyZSA6IExpYi5nZXRHcmFwaERpdihmaWd1cmUpO1xuICAgIGZpZ3VyZSA9IExpYi5leHRlbmREZWVwKHtfY29udGV4dDogZGZsdENvbmZpZ30sIHtkYXRhOiBmaWd1cmUuZGF0YSwgbGF5b3V0OiBmaWd1cmUubGF5b3V0fSk7XG4gICAgUGxvdHMuc3VwcGx5RGVmYXVsdHMoZmlndXJlKTtcbiAgICB2YXIgZGF0YSA9IGZpZ3VyZS5kYXRhIHx8IFtdO1xuICAgIHZhciBsYXlvdXQgPSBmaWd1cmUubGF5b3V0IHx8IHt9O1xuICAgIC8vIGNvcHkgb3ZlciBhIGZldyBpdGVtcyB0byBoZWxwIGZvbGxvdyB0aGUgc2NoZW1hXG4gICAgbGF5b3V0Ll9iYXNlUGxvdE1vZHVsZXMgPSBmaWd1cmUuX2Z1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcztcbiAgICBsYXlvdXQuX21vZHVsZXMgPSBmaWd1cmUuX2Z1bGxMYXlvdXQuX21vZHVsZXM7XG5cbiAgICB2YXIgdGVtcGxhdGUgPSB7XG4gICAgICAgIGRhdGE6IHt9LFxuICAgICAgICBsYXlvdXQ6IHt9XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogTm90ZTogd2UgZG8gTk9UIHZhbGlkYXRlIHRlbXBsYXRlIHZhbHVlcywgd2UganVzdCB0YWtlIHdoYXQncyBpbiB0aGVcbiAgICAgKiB1c2VyIGlucHV0cyBkYXRhIGFuZCBsYXlvdXQsIG5vdCB0aGUgdmFsaWRhdGVkIHZhbHVlcyBpbiBmdWxsRGF0YSBhbmRcbiAgICAgKiBmdWxsTGF5b3V0LiBFdmVuIGlmIHdlIHdlcmUgdG8gdmFsaWRhdGUgaGVyZSwgdGhlcmUncyBubyBndWFyYW50ZWUgdGhhdFxuICAgICAqIHRoZXNlIHZhbHVlcyB3b3VsZCBzdGlsbCBiZSB2YWxpZCB3aGVuIGFwcGxpZWQgdG8gYSBuZXcgZmlndXJlLCB3aGljaFxuICAgICAqIG1heSBjb250YWluIGRpZmZlcmVudCB0cmFjZSBtb2RlcywgZGlmZmVyZW50IGF4ZXMsIGV0Yy4gU28gaXQnc1xuICAgICAqIGltcG9ydGFudCB0aGF0IHdoZW4gYXBwbHlpbmcgYSB0ZW1wbGF0ZSB3ZSBzdGlsbCB2YWxpZGF0ZSB0aGUgdGVtcGxhdGVcbiAgICAgKiB2YWx1ZXMsIHJhdGhlciB0aGFuIGp1c3QgdXNpbmcgdGhlbSBhcyBkZWZhdWx0cy5cbiAgICAgKi9cblxuICAgIGRhdGEuZm9yRWFjaChmdW5jdGlvbih0cmFjZSkge1xuICAgICAgICAvLyBUT0RPOiBXaGF0IGlmIG5vIHN0eWxlIGluZm8gaXMgZXh0cmFjdGVkIGZvciB0aGlzIHRyYWNlLiBXZSBtYXlcbiAgICAgICAgLy8gbm90IHdhbnQgYW4gZW1wdHkgb2JqZWN0IGFzIHRoZSBudWxsIHZhbHVlLlxuICAgICAgICAvLyBUT0RPOiBhbGxvdyB0cmFuc2Zvcm1zIHRvIGNvbnRyaWJ1dGUgdG8gdGVtcGxhdGVzP1xuICAgICAgICAvLyBhcyBpdCBzdGFuZHMgdGhleSBhcmUgaWdub3JlZCwgd2hpY2ggbWF5IGJlIGZvciB0aGUgYmVzdC4uLlxuXG4gICAgICAgIHZhciB0cmFjZVRlbXBsYXRlID0ge307XG4gICAgICAgIHdhbGtTdHlsZUtleXModHJhY2UsIHRyYWNlVGVtcGxhdGUsIGdldFRyYWNlSW5mby5iaW5kKG51bGwsIHRyYWNlKSk7XG5cbiAgICAgICAgdmFyIHRyYWNlVHlwZSA9IExpYi5jb2VyY2UodHJhY2UsIHt9LCBwbG90QXR0cmlidXRlcywgJ3R5cGUnKTtcbiAgICAgICAgdmFyIHR5cGVUZW1wbGF0ZXMgPSB0ZW1wbGF0ZS5kYXRhW3RyYWNlVHlwZV07XG4gICAgICAgIGlmKCF0eXBlVGVtcGxhdGVzKSB0eXBlVGVtcGxhdGVzID0gdGVtcGxhdGUuZGF0YVt0cmFjZVR5cGVdID0gW107XG4gICAgICAgIHR5cGVUZW1wbGF0ZXMucHVzaCh0cmFjZVRlbXBsYXRlKTtcbiAgICB9KTtcblxuICAgIHdhbGtTdHlsZUtleXMobGF5b3V0LCB0ZW1wbGF0ZS5sYXlvdXQsIGdldExheW91dEluZm8uYmluZChudWxsLCBsYXlvdXQpKTtcblxuICAgIC8qXG4gICAgICogQ29tcG9zZSB0aGUgbmV3IHRlbXBsYXRlIHdpdGggYW4gZXhpc3Rpbmcgb25lIHRvIHRoZSBzYW1lIGVmZmVjdFxuICAgICAqXG4gICAgICogTk9URTogdGhlcmUncyBhIHBvc3NpYmlsaXR5IG9mIHNsaWdodGx5IGRpZmZlcmVudCBiZWhhdmlvcjogaWYgdGhlIHBsb3RcbiAgICAgKiBoYXMgYW4gaW52YWxpZCB2YWx1ZSBhbmQgdGhlIG9sZCB0ZW1wbGF0ZSBoYXMgYSB2YWxpZCB2YWx1ZSBmb3IgdGhlIHNhbWVcbiAgICAgKiBhdHRyaWJ1dGUsIHRoZSBwbG90IHdpbGwgdXNlIHRoZSBvbGQgdGVtcGxhdGUgdmFsdWUgYnV0IHRoaXMgcm91dGluZVxuICAgICAqIHdpbGwgcHVsbCB0aGUgaW52YWxpZCB2YWx1ZSAocmVzdWx0aW5nIGluIHRoZSBvcmlnaW5hbCBkZWZhdWx0KS5cbiAgICAgKiBJbiB0aGUgZ2VuZXJhbCBjYXNlIGl0J3Mgbm90IHBvc3NpYmxlIHRvIHNvbHZlIHRoaXMgd2l0aCBhIHNpbmdsZSB2YWx1ZSxcbiAgICAgKiBzaW5jZSB2YWxpZCBvcHRpb25zIGNhbiBiZSBjb250ZXh0LWRlcGVuZGVudC4gSXQgY291bGQgYmUgc29sdmVkIHdpdGhcbiAgICAgKiBhICpsaXN0KiBvZiB2YWx1ZXMsIGJ1dCB0aGF0IHdvdWxkIGJlIGh1Z2UgY29tcGxleGl0eSBmb3IgbGl0dGxlIGdhaW4uXG4gICAgICovXG4gICAgZGVsZXRlIHRlbXBsYXRlLmxheW91dC50ZW1wbGF0ZTtcbiAgICB2YXIgb2xkVGVtcGxhdGUgPSBsYXlvdXQudGVtcGxhdGU7XG4gICAgaWYoaXNQbGFpbk9iamVjdChvbGRUZW1wbGF0ZSkpIHtcbiAgICAgICAgdmFyIG9sZExheW91dFRlbXBsYXRlID0gb2xkVGVtcGxhdGUubGF5b3V0O1xuXG4gICAgICAgIHZhciBpLCB0cmFjZVR5cGUsIG9sZFR5cGVUZW1wbGF0ZXMsIG9sZFR5cGVMZW4sIHR5cGVUZW1wbGF0ZXMsIHR5cGVMZW47XG5cbiAgICAgICAgaWYoaXNQbGFpbk9iamVjdChvbGRMYXlvdXRUZW1wbGF0ZSkpIHtcbiAgICAgICAgICAgIG1lcmdlVGVtcGxhdGVzKG9sZExheW91dFRlbXBsYXRlLCB0ZW1wbGF0ZS5sYXlvdXQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvbGREYXRhVGVtcGxhdGUgPSBvbGRUZW1wbGF0ZS5kYXRhO1xuICAgICAgICBpZihpc1BsYWluT2JqZWN0KG9sZERhdGFUZW1wbGF0ZSkpIHtcbiAgICAgICAgICAgIGZvcih0cmFjZVR5cGUgaW4gdGVtcGxhdGUuZGF0YSkge1xuICAgICAgICAgICAgICAgIG9sZFR5cGVUZW1wbGF0ZXMgPSBvbGREYXRhVGVtcGxhdGVbdHJhY2VUeXBlXTtcbiAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KG9sZFR5cGVUZW1wbGF0ZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGVUZW1wbGF0ZXMgPSB0ZW1wbGF0ZS5kYXRhW3RyYWNlVHlwZV07XG4gICAgICAgICAgICAgICAgICAgIHR5cGVMZW4gPSB0eXBlVGVtcGxhdGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgb2xkVHlwZUxlbiA9IG9sZFR5cGVUZW1wbGF0ZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCB0eXBlTGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lcmdlVGVtcGxhdGVzKG9sZFR5cGVUZW1wbGF0ZXNbaSAlIG9sZFR5cGVMZW5dLCB0eXBlVGVtcGxhdGVzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmb3IoaSA9IHR5cGVMZW47IGkgPCBvbGRUeXBlTGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVUZW1wbGF0ZXMucHVzaChMaWIuZXh0ZW5kRGVlcCh7fSwgb2xkVHlwZVRlbXBsYXRlc1tpXSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yKHRyYWNlVHlwZSBpbiBvbGREYXRhVGVtcGxhdGUpIHtcbiAgICAgICAgICAgICAgICBpZighKHRyYWNlVHlwZSBpbiB0ZW1wbGF0ZS5kYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5kYXRhW3RyYWNlVHlwZV0gPSBMaWIuZXh0ZW5kRGVlcChbXSwgb2xkRGF0YVRlbXBsYXRlW3RyYWNlVHlwZV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0ZW1wbGF0ZTtcbn07XG5cbmZ1bmN0aW9uIG1lcmdlVGVtcGxhdGVzKG9sZFRlbXBsYXRlLCBuZXdUZW1wbGF0ZSkge1xuICAgIC8vIHdlIGRvbid0IGNhcmUgYWJvdXQgc3BlZWQgaGVyZSwganVzdCBtYWtlIHN1cmUgd2UgaGF2ZSBhIHRvdGFsbHlcbiAgICAvLyBkaXN0aW5jdCBvYmplY3QgZnJvbSB0aGUgcHJldmlvdXMgdGVtcGxhdGVcbiAgICBvbGRUZW1wbGF0ZSA9IExpYi5leHRlbmREZWVwKHt9LCBvbGRUZW1wbGF0ZSk7XG5cbiAgICAvLyBzb3J0IGtleXMgc28gd2UgYWx3YXlzIGdldCBhbm5vdGF0aW9uZGVmYXVsdHMgYmVmb3JlIGFubm90YXRpb25zIGV0Y1xuICAgIC8vIHNvIGFycmF5VGVtcGxhdGVyIHdpbGwgd29yayByaWdodFxuICAgIHZhciBvbGRLZXlzID0gT2JqZWN0LmtleXMob2xkVGVtcGxhdGUpLnNvcnQoKTtcbiAgICB2YXIgaSwgajtcblxuICAgIGZ1bmN0aW9uIG1lcmdlT25lKG9sZFZhbCwgbmV3VmFsLCBrZXkpIHtcbiAgICAgICAgaWYoaXNQbGFpbk9iamVjdChuZXdWYWwpICYmIGlzUGxhaW5PYmplY3Qob2xkVmFsKSkge1xuICAgICAgICAgICAgbWVyZ2VUZW1wbGF0ZXMob2xkVmFsLCBuZXdWYWwpO1xuICAgICAgICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheShuZXdWYWwpICYmIEFycmF5LmlzQXJyYXkob2xkVmFsKSkge1xuICAgICAgICAgICAgLy8gTm90ZTogb21pdHRlZCBgaW5jbHVzaW9uQXR0cmAgZnJvbSBhcnJheVRlbXBsYXRlciBoZXJlLFxuICAgICAgICAgICAgLy8gaXQncyBpcnJlbGV2YW50IGFzIHdlIG9ubHkgd2FudCB0aGUgcmVzdWx0aW5nIGBfdGVtcGxhdGVgLlxuICAgICAgICAgICAgdmFyIHRlbXBsYXRlciA9IFRlbXBsYXRlLmFycmF5VGVtcGxhdGVyKHtfdGVtcGxhdGU6IG9sZFRlbXBsYXRlfSwga2V5KTtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5ld1ZhbC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBpdGVtID0gbmV3VmFsW2pdO1xuICAgICAgICAgICAgICAgIHZhciBvbGRJdGVtID0gdGVtcGxhdGVyLm5ld0l0ZW0oaXRlbSkuX3RlbXBsYXRlO1xuICAgICAgICAgICAgICAgIGlmKG9sZEl0ZW0pIG1lcmdlVGVtcGxhdGVzKG9sZEl0ZW0sIGl0ZW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRlZmF1bHRJdGVtcyA9IHRlbXBsYXRlci5kZWZhdWx0SXRlbXMoKTtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGRlZmF1bHRJdGVtcy5sZW5ndGg7IGorKykgbmV3VmFsLnB1c2goZGVmYXVsdEl0ZW1zW2pdLl90ZW1wbGF0ZSk7XG5cbiAgICAgICAgICAgIC8vIHRlbXBsYXRlaXRlbW5hbWUgb25seSBhcHBsaWVzIHRvIHJlY2VpdmluZyBwbG90c1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbmV3VmFsLmxlbmd0aDsgaisrKSBkZWxldGUgbmV3VmFsW2pdLnRlbXBsYXRlaXRlbW5hbWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBvbGRLZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBrZXkgPSBvbGRLZXlzW2ldO1xuICAgICAgICB2YXIgb2xkVmFsID0gb2xkVGVtcGxhdGVba2V5XTtcbiAgICAgICAgaWYoa2V5IGluIG5ld1RlbXBsYXRlKSB7XG4gICAgICAgICAgICBtZXJnZU9uZShvbGRWYWwsIG5ld1RlbXBsYXRlW2tleV0sIGtleSk7XG4gICAgICAgIH0gZWxzZSBuZXdUZW1wbGF0ZVtrZXldID0gb2xkVmFsO1xuXG4gICAgICAgIC8vIGlmIHRoaXMgaXMgYSBiYXNlIGtleSBmcm9tIHRoZSBvbGQgdGVtcGxhdGUgKGVnIHhheGlzKSwgbG9vayBmb3JcbiAgICAgICAgLy8gZXh0ZW5kZWQga2V5cyAoZWcgeGF4aXMyKSBpbiB0aGUgbmV3IHRlbXBsYXRlIHRvIG1lcmdlIGludG9cbiAgICAgICAgaWYoZ2V0QmFzZUtleShrZXkpID09PSBrZXkpIHtcbiAgICAgICAgICAgIGZvcih2YXIga2V5MiBpbiBuZXdUZW1wbGF0ZSkge1xuICAgICAgICAgICAgICAgIHZhciBiYXNlS2V5MiA9IGdldEJhc2VLZXkoa2V5Mik7XG4gICAgICAgICAgICAgICAgaWYoa2V5MiAhPT0gYmFzZUtleTIgJiYgYmFzZUtleTIgPT09IGtleSAmJiAhKGtleTIgaW4gb2xkVGVtcGxhdGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lcmdlT25lKG9sZFZhbCwgbmV3VGVtcGxhdGVba2V5Ml0sIGtleSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRCYXNlS2V5KGtleSkge1xuICAgIHJldHVybiBrZXkucmVwbGFjZSgvWzAtOV0rJC8sICcnKTtcbn1cblxuZnVuY3Rpb24gd2Fsa1N0eWxlS2V5cyhwYXJlbnQsIHRlbXBsYXRlT3V0LCBnZXRBdHRyaWJ1dGVJbmZvLCBwYXRoLCBiYXNlUGF0aCkge1xuICAgIHZhciBwYXRoQXR0ciA9IGJhc2VQYXRoICYmIGdldEF0dHJpYnV0ZUluZm8oYmFzZVBhdGgpO1xuICAgIGZvcih2YXIga2V5IGluIHBhcmVudCkge1xuICAgICAgICB2YXIgY2hpbGQgPSBwYXJlbnRba2V5XTtcbiAgICAgICAgdmFyIG5leHRQYXRoID0gZ2V0TmV4dFBhdGgocGFyZW50LCBrZXksIHBhdGgpO1xuICAgICAgICB2YXIgbmV4dEJhc2VQYXRoID0gZ2V0TmV4dFBhdGgocGFyZW50LCBrZXksIGJhc2VQYXRoKTtcbiAgICAgICAgdmFyIGF0dHIgPSBnZXRBdHRyaWJ1dGVJbmZvKG5leHRCYXNlUGF0aCk7XG4gICAgICAgIGlmKCFhdHRyKSB7XG4gICAgICAgICAgICB2YXIgYmFzZUtleSA9IGdldEJhc2VLZXkoa2V5KTtcbiAgICAgICAgICAgIGlmKGJhc2VLZXkgIT09IGtleSkge1xuICAgICAgICAgICAgICAgIG5leHRCYXNlUGF0aCA9IGdldE5leHRQYXRoKHBhcmVudCwgYmFzZUtleSwgYmFzZVBhdGgpO1xuICAgICAgICAgICAgICAgIGF0dHIgPSBnZXRBdHRyaWJ1dGVJbmZvKG5leHRCYXNlUGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyB3ZSdsbCBnZXQgYW4gYXR0ciBpZiBwYXRoIHN0YXJ0cyB3aXRoIGEgdmFsaWQgcGFydCwgdGhlbiBoYXMgYW5cbiAgICAgICAgLy8gaW52YWxpZCBlbmRpbmcuIE1ha2Ugc3VyZSB3ZSBnb3QgYWxsIHRoZSB3YXkgdG8gdGhlIGVuZC5cbiAgICAgICAgaWYocGF0aEF0dHIgJiYgKHBhdGhBdHRyID09PSBhdHRyKSkgY29udGludWU7XG5cbiAgICAgICAgaWYoIWF0dHIgfHwgYXR0ci5fbm9UZW1wbGF0aW5nIHx8XG4gICAgICAgICAgICBhdHRyLnZhbFR5cGUgPT09ICdkYXRhX2FycmF5JyB8fFxuICAgICAgICAgICAgKGF0dHIuYXJyYXlPayAmJiBBcnJheS5pc0FycmF5KGNoaWxkKSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFhdHRyLnZhbFR5cGUgJiYgaXNQbGFpbk9iamVjdChjaGlsZCkpIHtcbiAgICAgICAgICAgIHdhbGtTdHlsZUtleXMoY2hpbGQsIHRlbXBsYXRlT3V0LCBnZXRBdHRyaWJ1dGVJbmZvLCBuZXh0UGF0aCwgbmV4dEJhc2VQYXRoKTtcbiAgICAgICAgfSBlbHNlIGlmKGF0dHIuX2lzTGlua2VkVG9BcnJheSAmJiBBcnJheS5pc0FycmF5KGNoaWxkKSkge1xuICAgICAgICAgICAgdmFyIGRmbHREb25lID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgbmFtZWRJbmRleCA9IDA7XG4gICAgICAgICAgICB2YXIgdXNlZE5hbWVzID0ge307XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2hpbGQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgaXRlbSA9IGNoaWxkW2ldO1xuICAgICAgICAgICAgICAgIGlmKGlzUGxhaW5PYmplY3QoaXRlbSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5hbWUgPSBpdGVtLm5hbWU7XG4gICAgICAgICAgICAgICAgICAgIGlmKG5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCF1c2VkTmFtZXNbbmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBuYW1lZCBhcnJheSBpdGVtczogYWxsb3cgYWxsIGF0dHJpYnV0ZXMgZXhjZXB0IGRhdGEgYXJyYXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2Fsa1N0eWxlS2V5cyhpdGVtLCB0ZW1wbGF0ZU91dCwgZ2V0QXR0cmlidXRlSW5mbyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TmV4dFBhdGgoY2hpbGQsIG5hbWVkSW5kZXgsIG5leHRQYXRoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0TmV4dFBhdGgoY2hpbGQsIG5hbWVkSW5kZXgsIG5leHRCYXNlUGF0aCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVkSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VkTmFtZXNbbmFtZV0gPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoIWRmbHREb25lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGZsdEtleSA9IFRlbXBsYXRlLmFycmF5RGVmYXVsdEtleShrZXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRmbHRQYXRoID0gZ2V0TmV4dFBhdGgocGFyZW50LCBkZmx0S2V5LCBwYXRoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZ2V0QXR0cmlidXRlSW5mbyB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVzZSBkZmx0S2V5IGRpcmVjdGx5LlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSW5zdGVhZCBwdXQgdGhpcyBpdGVtIGludG8gdGhlIG5leHQgYXJyYXkgZWxlbWVudCwgdGhlblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcHVsbCBpdCBvdXQgYW5kIG1vdmUgaXQgdG8gZGZsdEtleS5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwYXRoSW5BcnJheSA9IGdldE5leHRQYXRoKGNoaWxkLCBuYW1lZEluZGV4LCBuZXh0UGF0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrU3R5bGVLZXlzKGl0ZW0sIHRlbXBsYXRlT3V0LCBnZXRBdHRyaWJ1dGVJbmZvLCBwYXRoSW5BcnJheSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXROZXh0UGF0aChjaGlsZCwgbmFtZWRJbmRleCwgbmV4dEJhc2VQYXRoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbVByb3BJbkFycmF5ID0gTGliLm5lc3RlZFByb3BlcnR5KHRlbXBsYXRlT3V0LCBwYXRoSW5BcnJheSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGZsdFByb3AgPSBMaWIubmVzdGVkUHJvcGVydHkodGVtcGxhdGVPdXQsIGRmbHRQYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRmbHRQcm9wLnNldChpdGVtUHJvcEluQXJyYXkuZ2V0KCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlbVByb3BJbkFycmF5LnNldChudWxsKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGZsdERvbmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHRlbXBsYXRlUHJvcCA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0ZW1wbGF0ZU91dCwgbmV4dFBhdGgpO1xuICAgICAgICAgICAgdGVtcGxhdGVQcm9wLnNldChjaGlsZCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldExheW91dEluZm8obGF5b3V0LCBwYXRoKSB7XG4gICAgcmV0dXJuIFBsb3RTY2hlbWEuZ2V0TGF5b3V0VmFsT2JqZWN0KFxuICAgICAgICBsYXlvdXQsIExpYi5uZXN0ZWRQcm9wZXJ0eSh7fSwgcGF0aCkucGFydHNcbiAgICApO1xufVxuXG5mdW5jdGlvbiBnZXRUcmFjZUluZm8odHJhY2UsIHBhdGgpIHtcbiAgICByZXR1cm4gUGxvdFNjaGVtYS5nZXRUcmFjZVZhbE9iamVjdChcbiAgICAgICAgdHJhY2UsIExpYi5uZXN0ZWRQcm9wZXJ0eSh7fSwgcGF0aCkucGFydHNcbiAgICApO1xufVxuXG5mdW5jdGlvbiBnZXROZXh0UGF0aChwYXJlbnQsIGtleSwgcGF0aCkge1xuICAgIHZhciBuZXh0UGF0aDtcbiAgICBpZighcGF0aCkgbmV4dFBhdGggPSBrZXk7XG4gICAgZWxzZSBpZihBcnJheS5pc0FycmF5KHBhcmVudCkpIG5leHRQYXRoID0gcGF0aCArICdbJyArIGtleSArICddJztcbiAgICBlbHNlIG5leHRQYXRoID0gcGF0aCArICcuJyArIGtleTtcblxuICAgIHJldHVybiBuZXh0UGF0aDtcbn1cblxuLyoqXG4gKiB2YWxpZGF0ZVRlbXBsYXRlOiBUZXN0IGZvciBjb25zaXN0ZW5jeSBiZXR3ZWVuIHRoZSBnaXZlbiBmaWd1cmUgYW5kXG4gKiBhIHRlbXBsYXRlLCBlaXRoZXIgYWxyZWFkeSBpbmNsdWRlZCBpbiB0aGUgZmlndXJlIG9yIGdpdmVuIHNlcGFyYXRlbHkuXG4gKiBOb3RlIHRoYXQgbm90IGV2ZXJ5IGlzc3VlIHdlIGlkZW50aWZ5IGhlcmUgaXMgbmVjZXNzYXJpbHkgYSBwcm9ibGVtLFxuICogaXQgZGVwZW5kcyBvbiB3aGF0IHlvdSdyZSB1c2luZyB0aGUgdGVtcGxhdGUgZm9yLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fERPTSBlbGVtZW50fSBmaWd1cmU6IHRoZSBwbG90LCB3aXRoIHtkYXRhLCBsYXlvdXR9IG1lbWJlcnMsXG4gKiAgICAgdG8gdGVzdCB0aGUgdGVtcGxhdGUgYWdhaW5zdFxuICogQHBhcmFtIHtPcHRpb25hbChvYmplY3QpfSB0ZW1wbGF0ZTogdGhlIHRlbXBsYXRlLCB3aXRoIGl0cyBvd24ge2RhdGEsIGxheW91dH0sXG4gKiAgICAgdG8gdGVzdC4gSWYgb21pdHRlZCwgd2Ugd2lsbCBsb29rIGZvciBhIHRlbXBsYXRlIGFscmVhZHkgYXR0YWNoZWQgYXMgdGhlXG4gKiAgICAgcGxvdCdzIGBsYXlvdXQudGVtcGxhdGVgIGF0dHJpYnV0ZS5cbiAqXG4gKiBAcmV0dXJucyB7YXJyYXl9IGFycmF5IG9mIGVycm9yIG9iamVjdHMgZWFjaCBjb250YWluaW5nOlxuICogIC0ge3N0cmluZ30gY29kZVxuICogICAgICBlcnJvciBjb2RlICgnbWlzc2luZycsICd1bnVzZWQnLCAncmV1c2VkJywgJ25vTGF5b3V0JywgJ25vRGF0YScpXG4gKiAgLSB7c3RyaW5nfSBtc2dcbiAqICAgICAgYSBmdWxsIHJlYWRhYmxlIGRlc2NyaXB0aW9uIG9mIHRoZSBpc3N1ZS5cbiAqL1xuZXhwb3J0cy52YWxpZGF0ZVRlbXBsYXRlID0gZnVuY3Rpb24oZmlndXJlSW4sIHRlbXBsYXRlKSB7XG4gICAgdmFyIGZpZ3VyZSA9IExpYi5leHRlbmREZWVwKHt9LCB7XG4gICAgICAgIF9jb250ZXh0OiBkZmx0Q29uZmlnLFxuICAgICAgICBkYXRhOiBmaWd1cmVJbi5kYXRhLFxuICAgICAgICBsYXlvdXQ6IGZpZ3VyZUluLmxheW91dFxuICAgIH0pO1xuICAgIHZhciBsYXlvdXQgPSBmaWd1cmUubGF5b3V0IHx8IHt9O1xuICAgIGlmKCFpc1BsYWluT2JqZWN0KHRlbXBsYXRlKSkgdGVtcGxhdGUgPSBsYXlvdXQudGVtcGxhdGUgfHwge307XG4gICAgdmFyIGxheW91dFRlbXBsYXRlID0gdGVtcGxhdGUubGF5b3V0O1xuICAgIHZhciBkYXRhVGVtcGxhdGUgPSB0ZW1wbGF0ZS5kYXRhO1xuICAgIHZhciBlcnJvckxpc3QgPSBbXTtcblxuICAgIGZpZ3VyZS5sYXlvdXQgPSBsYXlvdXQ7XG4gICAgZmlndXJlLmxheW91dC50ZW1wbGF0ZSA9IHRlbXBsYXRlO1xuICAgIFBsb3RzLnN1cHBseURlZmF1bHRzKGZpZ3VyZSk7XG5cbiAgICB2YXIgZnVsbExheW91dCA9IGZpZ3VyZS5fZnVsbExheW91dDtcbiAgICB2YXIgZnVsbERhdGEgPSBmaWd1cmUuX2Z1bGxEYXRhO1xuXG4gICAgdmFyIGxheW91dFBhdGhzID0ge307XG4gICAgZnVuY3Rpb24gY3Jhd2xMYXlvdXRGb3JDb250YWluZXJzKG9iaiwgcGF0aHMpIHtcbiAgICAgICAgZm9yKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICBpZihrZXkuY2hhckF0KDApICE9PSAnXycgJiYgaXNQbGFpbk9iamVjdChvYmpba2V5XSkpIHtcbiAgICAgICAgICAgICAgICB2YXIgYmFzZUtleSA9IGdldEJhc2VLZXkoa2V5KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV4dFBhdGhzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGk7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGF0aHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbmV4dFBhdGhzLnB1c2goZ2V0TmV4dFBhdGgob2JqLCBrZXksIHBhdGhzW2ldKSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGJhc2VLZXkgIT09IGtleSkgbmV4dFBhdGhzLnB1c2goZ2V0TmV4dFBhdGgob2JqLCBiYXNlS2V5LCBwYXRoc1tpXSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBuZXh0UGF0aHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbGF5b3V0UGF0aHNbbmV4dFBhdGhzW2ldXSA9IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNyYXdsTGF5b3V0Rm9yQ29udGFpbmVycyhvYmpba2V5XSwgbmV4dFBhdGhzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyYXdsTGF5b3V0VGVtcGxhdGVGb3JDb250YWluZXJzKG9iaiwgcGF0aCkge1xuICAgICAgICBmb3IodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmKGtleS5pbmRleE9mKCdkZWZhdWx0cycpID09PSAtMSAmJiBpc1BsYWluT2JqZWN0KG9ialtrZXldKSkge1xuICAgICAgICAgICAgICAgIHZhciBuZXh0UGF0aCA9IGdldE5leHRQYXRoKG9iaiwga2V5LCBwYXRoKTtcbiAgICAgICAgICAgICAgICBpZihsYXlvdXRQYXRoc1tuZXh0UGF0aF0pIHtcbiAgICAgICAgICAgICAgICAgICAgY3Jhd2xMYXlvdXRUZW1wbGF0ZUZvckNvbnRhaW5lcnMob2JqW2tleV0sIG5leHRQYXRoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckxpc3QucHVzaCh7Y29kZTogJ3VudXNlZCcsIHBhdGg6IG5leHRQYXRofSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoIWlzUGxhaW5PYmplY3QobGF5b3V0VGVtcGxhdGUpKSB7XG4gICAgICAgIGVycm9yTGlzdC5wdXNoKHtjb2RlOiAnbGF5b3V0J30pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNyYXdsTGF5b3V0Rm9yQ29udGFpbmVycyhmdWxsTGF5b3V0LCBbJ2xheW91dCddKTtcbiAgICAgICAgY3Jhd2xMYXlvdXRUZW1wbGF0ZUZvckNvbnRhaW5lcnMobGF5b3V0VGVtcGxhdGUsICdsYXlvdXQnKTtcbiAgICB9XG5cbiAgICBpZighaXNQbGFpbk9iamVjdChkYXRhVGVtcGxhdGUpKSB7XG4gICAgICAgIGVycm9yTGlzdC5wdXNoKHtjb2RlOiAnZGF0YSd9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgdHlwZUNvdW50ID0ge307XG4gICAgICAgIHZhciB0cmFjZVR5cGU7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGZ1bGxUcmFjZSA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICAgICAgdHJhY2VUeXBlID0gZnVsbFRyYWNlLnR5cGU7XG4gICAgICAgICAgICB0eXBlQ291bnRbdHJhY2VUeXBlXSA9ICh0eXBlQ291bnRbdHJhY2VUeXBlXSB8fCAwKSArIDE7XG4gICAgICAgICAgICBpZighZnVsbFRyYWNlLl9mdWxsSW5wdXQuX3RlbXBsYXRlKSB7XG4gICAgICAgICAgICAgICAgLy8gdGhpcyB0YWtlcyBjYXJlIG9mIHRoZSBjYXNlIG9mIHRyYWNlVHlwZSBpbiB0aGUgZGF0YSBidXQgbm90XG4gICAgICAgICAgICAgICAgLy8gdGhlIHRlbXBsYXRlXG4gICAgICAgICAgICAgICAgZXJyb3JMaXN0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjb2RlOiAnbWlzc2luZycsXG4gICAgICAgICAgICAgICAgICAgIGluZGV4OiBmdWxsVHJhY2UuX2Z1bGxJbnB1dC5pbmRleCxcbiAgICAgICAgICAgICAgICAgICAgdHJhY2VUeXBlOiB0cmFjZVR5cGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IodHJhY2VUeXBlIGluIGRhdGFUZW1wbGF0ZSkge1xuICAgICAgICAgICAgdmFyIHRlbXBsYXRlQ291bnQgPSBkYXRhVGVtcGxhdGVbdHJhY2VUeXBlXS5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgZGF0YUNvdW50ID0gdHlwZUNvdW50W3RyYWNlVHlwZV0gfHwgMDtcbiAgICAgICAgICAgIGlmKHRlbXBsYXRlQ291bnQgPiBkYXRhQ291bnQpIHtcbiAgICAgICAgICAgICAgICBlcnJvckxpc3QucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGNvZGU6ICd1bnVzZWQnLFxuICAgICAgICAgICAgICAgICAgICB0cmFjZVR5cGU6IHRyYWNlVHlwZSxcbiAgICAgICAgICAgICAgICAgICAgdGVtcGxhdGVDb3VudDogdGVtcGxhdGVDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgZGF0YUNvdW50OiBkYXRhQ291bnRcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihkYXRhQ291bnQgPiB0ZW1wbGF0ZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgZXJyb3JMaXN0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjb2RlOiAncmV1c2VkJyxcbiAgICAgICAgICAgICAgICAgICAgdHJhY2VUeXBlOiB0cmFjZVR5cGUsXG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlQ291bnQ6IHRlbXBsYXRlQ291bnQsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFDb3VudDogZGF0YUNvdW50XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBfdGVtcGxhdGU6IGZhbHNlIGlzIHdoZW4gc29tZW9uZSB0cmllZCB0byBtb2RpZnkgYW4gYXJyYXkgaXRlbVxuICAgIC8vIGJ1dCB0aGVyZSB3YXMgbm8gdGVtcGxhdGUgd2l0aCBtYXRjaGluZyBuYW1lXG4gICAgZnVuY3Rpb24gY3Jhd2xGb3JNaXNzaW5nVGVtcGxhdGVzKG9iaiwgcGF0aCkge1xuICAgICAgICBmb3IodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmKGtleS5jaGFyQXQoMCkgPT09ICdfJykgY29udGludWU7XG4gICAgICAgICAgICB2YXIgdmFsID0gb2JqW2tleV07XG4gICAgICAgICAgICB2YXIgbmV4dFBhdGggPSBnZXROZXh0UGF0aChvYmosIGtleSwgcGF0aCk7XG4gICAgICAgICAgICBpZihpc1BsYWluT2JqZWN0KHZhbCkpIHtcbiAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KG9iaikgJiYgdmFsLl90ZW1wbGF0ZSA9PT0gZmFsc2UgJiYgdmFsLnRlbXBsYXRlaXRlbW5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JMaXN0LnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogJ21pc3NpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGF0aDogbmV4dFBhdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZWl0ZW1uYW1lOiB2YWwudGVtcGxhdGVpdGVtbmFtZVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY3Jhd2xGb3JNaXNzaW5nVGVtcGxhdGVzKHZhbCwgbmV4dFBhdGgpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKEFycmF5LmlzQXJyYXkodmFsKSAmJiBoYXNQbGFpbk9iamVjdCh2YWwpKSB7XG4gICAgICAgICAgICAgICAgY3Jhd2xGb3JNaXNzaW5nVGVtcGxhdGVzKHZhbCwgbmV4dFBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGNyYXdsRm9yTWlzc2luZ1RlbXBsYXRlcyh7ZGF0YTogZnVsbERhdGEsIGxheW91dDogZnVsbExheW91dH0sICcnKTtcblxuICAgIGlmKGVycm9yTGlzdC5sZW5ndGgpIHJldHVybiBlcnJvckxpc3QubWFwKGZvcm1hdCk7XG59O1xuXG5mdW5jdGlvbiBoYXNQbGFpbk9iamVjdChhcnIpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGlzUGxhaW5PYmplY3QoYXJyW2ldKSkgcmV0dXJuIHRydWU7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmb3JtYXQob3B0cykge1xuICAgIHZhciBtc2c7XG4gICAgc3dpdGNoKG9wdHMuY29kZSkge1xuICAgICAgICBjYXNlICdkYXRhJzpcbiAgICAgICAgICAgIG1zZyA9ICdUaGUgdGVtcGxhdGUgaGFzIG5vIGtleSBkYXRhLic7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbGF5b3V0JzpcbiAgICAgICAgICAgIG1zZyA9ICdUaGUgdGVtcGxhdGUgaGFzIG5vIGtleSBsYXlvdXQuJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdtaXNzaW5nJzpcbiAgICAgICAgICAgIGlmKG9wdHMucGF0aCkge1xuICAgICAgICAgICAgICAgIG1zZyA9ICdUaGVyZSBhcmUgbm8gdGVtcGxhdGVzIGZvciBpdGVtICcgKyBvcHRzLnBhdGggK1xuICAgICAgICAgICAgICAgICAgICAnIHdpdGggbmFtZSAnICsgb3B0cy50ZW1wbGF0ZWl0ZW1uYW1lO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtc2cgPSAnVGhlcmUgYXJlIG5vIHRlbXBsYXRlcyBmb3IgdHJhY2UgJyArIG9wdHMuaW5kZXggK1xuICAgICAgICAgICAgICAgICAgICAnLCBvZiB0eXBlICcgKyBvcHRzLnRyYWNlVHlwZSArICcuJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd1bnVzZWQnOlxuICAgICAgICAgICAgaWYob3B0cy5wYXRoKSB7XG4gICAgICAgICAgICAgICAgbXNnID0gJ1RoZSB0ZW1wbGF0ZSBpdGVtIGF0ICcgKyBvcHRzLnBhdGggK1xuICAgICAgICAgICAgICAgICAgICAnIHdhcyBub3QgdXNlZCBpbiBjb25zdHJ1Y3RpbmcgdGhlIHBsb3QuJztcbiAgICAgICAgICAgIH0gZWxzZSBpZihvcHRzLmRhdGFDb3VudCkge1xuICAgICAgICAgICAgICAgIG1zZyA9ICdTb21lIG9mIHRoZSB0ZW1wbGF0ZXMgb2YgdHlwZSAnICsgb3B0cy50cmFjZVR5cGUgK1xuICAgICAgICAgICAgICAgICAgICAnIHdlcmUgbm90IHVzZWQuIFRoZSB0ZW1wbGF0ZSBoYXMgJyArIG9wdHMudGVtcGxhdGVDb3VudCArXG4gICAgICAgICAgICAgICAgICAgICcgdHJhY2VzLCB0aGUgZGF0YSBvbmx5IGhhcyAnICsgb3B0cy5kYXRhQ291bnQgK1xuICAgICAgICAgICAgICAgICAgICAnIG9mIHRoaXMgdHlwZS4nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtc2cgPSAnVGhlIHRlbXBsYXRlIGhhcyAnICsgb3B0cy50ZW1wbGF0ZUNvdW50ICtcbiAgICAgICAgICAgICAgICAgICAgJyB0cmFjZXMgb2YgdHlwZSAnICsgb3B0cy50cmFjZVR5cGUgK1xuICAgICAgICAgICAgICAgICAgICAnIGJ1dCB0aGVyZSBhcmUgbm9uZSBpbiB0aGUgZGF0YS4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3JldXNlZCc6XG4gICAgICAgICAgICBtc2cgPSAnU29tZSBvZiB0aGUgdGVtcGxhdGVzIG9mIHR5cGUgJyArIG9wdHMudHJhY2VUeXBlICtcbiAgICAgICAgICAgICAgICAnIHdlcmUgdXNlZCBtb3JlIHRoYW4gb25jZS4gVGhlIHRlbXBsYXRlIGhhcyAnICtcbiAgICAgICAgICAgICAgICBvcHRzLnRlbXBsYXRlQ291bnQgKyAnIHRyYWNlcywgdGhlIGRhdGEgaGFzICcgK1xuICAgICAgICAgICAgICAgIG9wdHMuZGF0YUNvdW50ICsgJyBvZiB0aGlzIHR5cGUuJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBvcHRzLm1zZyA9IG1zZztcblxuICAgIHJldHVybiBvcHRzO1xufVxuXG59LHtcIi4uL2xpYlwiOjcxOSxcIi4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9wbG90cy9wbG90c1wiOjgyOCxcIi4vcGxvdF9jb25maWdcIjo3NTUsXCIuL3Bsb3Rfc2NoZW1hXCI6NzU2LFwiLi9wbG90X3RlbXBsYXRlXCI6NzU3fV0sNzYwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBwbG90QXBpID0gX2RlcmVxXygnLi9wbG90X2FwaScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uL2xpYicpO1xuXG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4uL3NuYXBzaG90L2hlbHBlcnMnKTtcbnZhciB0b1NWRyA9IF9kZXJlcV8oJy4uL3NuYXBzaG90L3Rvc3ZnJyk7XG52YXIgc3ZnVG9JbWcgPSBfZGVyZXFfKCcuLi9zbmFwc2hvdC9zdmd0b2ltZycpO1xuXG52YXIgYXR0cnMgPSB7XG4gICAgZm9ybWF0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3BuZycsICdqcGVnJywgJ3dlYnAnLCAnc3ZnJ10sXG4gICAgICAgIGRmbHQ6ICdwbmcnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDEsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaGVpZ2h0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDEsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2NhbGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzZXRCYWNrZ3JvdW5kOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBpbWFnZURhdGFPbmx5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH1cbn07XG5cbi8qKiBQbG90bHkudG9JbWFnZVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0IHwgc3RyaW5nIHwgSFRNTCBkaXZ9IGdkXG4gKiAgIGNhbiBlaXRoZXIgYmUgYSBkYXRhL2xheW91dC9jb25maWcgb2JqZWN0XG4gKiAgIG9yIGFuIGV4aXN0aW5nIGdyYXBoIDxkaXY+XG4gKiAgIG9yIGFuIGlkIHRvIGFuIGV4aXN0aW5nIGdyYXBoIDxkaXY+XG4gKiBAcGFyYW0ge29iamVjdH0gb3B0cyAoc2VlIGFib3ZlKVxuICogQHJldHVybiB7cHJvbWlzZX1cbiAqL1xuZnVuY3Rpb24gdG9JbWFnZShnZCwgb3B0cykge1xuICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gICAgdmFyIGRhdGE7XG4gICAgdmFyIGxheW91dDtcbiAgICB2YXIgY29uZmlnO1xuICAgIHZhciBmdWxsTGF5b3V0O1xuXG4gICAgaWYoTGliLmlzUGxhaW5PYmplY3QoZ2QpKSB7XG4gICAgICAgIGRhdGEgPSBnZC5kYXRhIHx8IFtdO1xuICAgICAgICBsYXlvdXQgPSBnZC5sYXlvdXQgfHwge307XG4gICAgICAgIGNvbmZpZyA9IGdkLmNvbmZpZyB8fCB7fTtcbiAgICAgICAgZnVsbExheW91dCA9IHt9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcbiAgICAgICAgZGF0YSA9IExpYi5leHRlbmREZWVwKFtdLCBnZC5kYXRhKTtcbiAgICAgICAgbGF5b3V0ID0gTGliLmV4dGVuZERlZXAoe30sIGdkLmxheW91dCk7XG4gICAgICAgIGNvbmZpZyA9IGdkLl9jb250ZXh0O1xuICAgICAgICBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQgfHwge307XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNJbXBsaWVkT3JWYWxpZChhdHRyKSB7XG4gICAgICAgIHJldHVybiAhKGF0dHIgaW4gb3B0cykgfHwgTGliLnZhbGlkYXRlKG9wdHNbYXR0cl0sIGF0dHJzW2F0dHJdKTtcbiAgICB9XG5cbiAgICBpZigoIWlzSW1wbGllZE9yVmFsaWQoJ3dpZHRoJykgJiYgb3B0cy53aWR0aCAhPT0gbnVsbCkgfHxcbiAgICAgICAgKCFpc0ltcGxpZWRPclZhbGlkKCdoZWlnaHQnKSAmJiBvcHRzLmhlaWdodCAhPT0gbnVsbCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdIZWlnaHQgYW5kIHdpZHRoIHNob3VsZCBiZSBwaXhlbCB2YWx1ZXMuJyk7XG4gICAgfVxuXG4gICAgaWYoIWlzSW1wbGllZE9yVmFsaWQoJ2Zvcm1hdCcpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgZm9ybWF0IGlzIG5vdCBqcGVnLCBwbmcsIHN2ZyBvciB3ZWJwLicpO1xuICAgIH1cblxuICAgIHZhciBmdWxsT3B0cyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2Uob3B0cywgZnVsbE9wdHMsIGF0dHJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgZm9ybWF0ID0gY29lcmNlKCdmb3JtYXQnKTtcbiAgICB2YXIgd2lkdGggPSBjb2VyY2UoJ3dpZHRoJyk7XG4gICAgdmFyIGhlaWdodCA9IGNvZXJjZSgnaGVpZ2h0Jyk7XG4gICAgdmFyIHNjYWxlID0gY29lcmNlKCdzY2FsZScpO1xuICAgIHZhciBzZXRCYWNrZ3JvdW5kID0gY29lcmNlKCdzZXRCYWNrZ3JvdW5kJyk7XG4gICAgdmFyIGltYWdlRGF0YU9ubHkgPSBjb2VyY2UoJ2ltYWdlRGF0YU9ubHknKTtcblxuICAgIC8vIHB1dCB0aGUgY2xvbmVkIGRpdiBzb21ld2hlcmUgb2ZmIHNjcmVlbiBiZWZvcmUgYXR0YWNoaW5nIHRvIERPTVxuICAgIHZhciBjbG9uZWRHZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGNsb25lZEdkLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBjbG9uZWRHZC5zdHlsZS5sZWZ0ID0gJy01MDAwcHgnO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoY2xvbmVkR2QpO1xuXG4gICAgLy8gZXh0ZW5kIGxheW91dCB3aXRoIGltYWdlIG9wdGlvbnNcbiAgICB2YXIgbGF5b3V0SW1hZ2UgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgbGF5b3V0KTtcbiAgICBpZih3aWR0aCkge1xuICAgICAgICBsYXlvdXRJbWFnZS53aWR0aCA9IHdpZHRoO1xuICAgIH0gZWxzZSBpZihvcHRzLndpZHRoID09PSBudWxsICYmIGlzTnVtZXJpYyhmdWxsTGF5b3V0LndpZHRoKSkge1xuICAgICAgICBsYXlvdXRJbWFnZS53aWR0aCA9IGZ1bGxMYXlvdXQud2lkdGg7XG4gICAgfVxuICAgIGlmKGhlaWdodCkge1xuICAgICAgICBsYXlvdXRJbWFnZS5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgfSBlbHNlIGlmKG9wdHMuaGVpZ2h0ID09PSBudWxsICYmIGlzTnVtZXJpYyhmdWxsTGF5b3V0LmhlaWdodCkpIHtcbiAgICAgICAgbGF5b3V0SW1hZ2UuaGVpZ2h0ID0gZnVsbExheW91dC5oZWlnaHQ7XG4gICAgfVxuXG4gICAgLy8gZXh0ZW5kIGNvbmZpZyBmb3Igc3RhdGljIHBsb3RcbiAgICB2YXIgY29uZmlnSW1hZ2UgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgY29uZmlnLCB7XG4gICAgICAgIF9leHBvcnRlZFBsb3Q6IHRydWUsXG4gICAgICAgIHN0YXRpY1Bsb3Q6IHRydWUsXG4gICAgICAgIHNldEJhY2tncm91bmQ6IHNldEJhY2tncm91bmRcbiAgICB9KTtcblxuICAgIHZhciByZWRyYXdGdW5jID0gaGVscGVycy5nZXRSZWRyYXdGdW5jKGNsb25lZEdkKTtcblxuICAgIGZ1bmN0aW9uIHdhaXQoKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KHJlc29sdmUsIGhlbHBlcnMuZ2V0RGVsYXkoY2xvbmVkR2QuX2Z1bGxMYXlvdXQpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29udmVydCgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgdmFyIHN2ZyA9IHRvU1ZHKGNsb25lZEdkLCBmb3JtYXQsIHNjYWxlKTtcbiAgICAgICAgICAgIHZhciB3aWR0aCA9IGNsb25lZEdkLl9mdWxsTGF5b3V0LndpZHRoO1xuICAgICAgICAgICAgdmFyIGhlaWdodCA9IGNsb25lZEdkLl9mdWxsTGF5b3V0LmhlaWdodDtcblxuICAgICAgICAgICAgcGxvdEFwaS5wdXJnZShjbG9uZWRHZCk7XG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGNsb25lZEdkKTtcblxuICAgICAgICAgICAgaWYoZm9ybWF0ID09PSAnc3ZnJykge1xuICAgICAgICAgICAgICAgIGlmKGltYWdlRGF0YU9ubHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoc3ZnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShoZWxwZXJzLmVuY29kZVNWRyhzdmcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgIGNhbnZhcy5pZCA9IExpYi5yYW5kc3RyKCk7XG5cbiAgICAgICAgICAgIHN2Z1RvSW1nKHtcbiAgICAgICAgICAgICAgICBmb3JtYXQ6IGZvcm1hdCxcbiAgICAgICAgICAgICAgICB3aWR0aDogd2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgICAgICAgc2NhbGU6IHNjYWxlLFxuICAgICAgICAgICAgICAgIGNhbnZhczogY2FudmFzLFxuICAgICAgICAgICAgICAgIHN2Zzogc3ZnLFxuICAgICAgICAgICAgICAgIC8vIGFzayBzdmdUb0ltZyB0byByZXR1cm4gYSBQcm9taXNlXG4gICAgICAgICAgICAgICAgLy8gIHJhdGhlciB0aGFuIEV2ZW50RW1pdHRlclxuICAgICAgICAgICAgICAgIC8vICBsZWF2ZSBFdmVudEVtaXR0ZXIgZm9yIGJhY2t3YXJkXG4gICAgICAgICAgICAgICAgLy8gIGNvbXBhdGliaWxpdHlcbiAgICAgICAgICAgICAgICBwcm9taXNlOiB0cnVlXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSlcbiAgICAgICAgICAgIC5jYXRjaChyZWplY3QpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cmxUb0ltYWdlRGF0YSh1cmwpIHtcbiAgICAgICAgaWYoaW1hZ2VEYXRhT25seSkge1xuICAgICAgICAgICAgcmV0dXJuIHVybC5yZXBsYWNlKGhlbHBlcnMuSU1BR0VfVVJMX1BSRUZJWCwgJycpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHVybDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgcGxvdEFwaS5wbG90KGNsb25lZEdkLCBkYXRhLCBsYXlvdXRJbWFnZSwgY29uZmlnSW1hZ2UpXG4gICAgICAgICAgICAudGhlbihyZWRyYXdGdW5jKVxuICAgICAgICAgICAgLnRoZW4od2FpdClcbiAgICAgICAgICAgIC50aGVuKGNvbnZlcnQpXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbih1cmwpIHsgcmVzb2x2ZSh1cmxUb0ltYWdlRGF0YSh1cmwpKTsgfSlcbiAgICAgICAgICAgIC5jYXRjaChmdW5jdGlvbihlcnIpIHsgcmVqZWN0KGVycik7IH0pO1xuICAgIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRvSW1hZ2U7XG5cbn0se1wiLi4vbGliXCI6NzE5LFwiLi4vc25hcHNob3QvaGVscGVyc1wiOjg1MSxcIi4uL3NuYXBzaG90L3N2Z3RvaW1nXCI6ODUzLFwiLi4vc25hcHNob3QvdG9zdmdcIjo4NTUsXCIuL3Bsb3RfYXBpXCI6NzU0LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSw3NjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG52YXIgUGxvdHMgPSBfZGVyZXFfKCcuLi9wbG90cy9wbG90cycpO1xudmFyIFBsb3RTY2hlbWEgPSBfZGVyZXFfKCcuL3Bsb3Rfc2NoZW1hJyk7XG52YXIgZGZsdENvbmZpZyA9IF9kZXJlcV8oJy4vcGxvdF9jb25maWcnKS5kZmx0Q29uZmlnO1xuXG52YXIgaXNQbGFpbk9iamVjdCA9IExpYi5pc1BsYWluT2JqZWN0O1xudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xudmFyIGlzQXJyYXlPclR5cGVkQXJyYXkgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheTtcblxuLyoqXG4gKiBWYWxpZGF0ZSBhIGRhdGEgYXJyYXkgYW5kIGxheW91dCBvYmplY3QuXG4gKlxuICogQHBhcmFtIHthcnJheX0gZGF0YVxuICogQHBhcmFtIHtvYmplY3R9IGxheW91dFxuICpcbiAqIEByZXR1cm4ge2FycmF5fSBhcnJheSBvZiBlcnJvciBvYmplY3RzIGVhY2ggY29udGFpbmluZzpcbiAqICAtIHtzdHJpbmd9IGNvZGVcbiAqICAgICAgZXJyb3IgY29kZSAoJ29iamVjdCcsICdhcnJheScsICdzY2hlbWEnLCAndW51c2VkJywgJ2ludmlzaWJsZScgb3IgJ3ZhbHVlJylcbiAqICAtIHtzdHJpbmd9IGNvbnRhaW5lclxuICogICAgICBjb250YWluZXIgd2hlcmUgdGhlIGVycm9yIG9jY3VycyAoJ2RhdGEnIG9yICdsYXlvdXQnKVxuICogIC0ge251bWJlcn0gdHJhY2VcbiAqICAgICAgdHJhY2UgaW5kZXggb2YgdGhlICdkYXRhJyBjb250YWluZXIgd2hlcmUgdGhlIGVycm9yIG9jY3Vyc1xuICogIC0ge2FycmF5fSBwYXRoXG4gKiAgICAgIG5lc3RlZCBwYXRoIHRvIHRoZSBrZXkgdGhhdCBjYXVzZXMgdGhlIGVycm9yXG4gKiAgLSB7c3RyaW5nfSBhc3RyXG4gKiAgICAgIGF0dHJpYnV0ZSBzdHJpbmcgdmFyaWFudCBvZiAncGF0aCcgY29tcGF0aWJsZSB3aXRoIFBsb3RseS5yZXN0eWxlIGFuZFxuICogICAgICBQbG90bHkucmVsYXlvdXQuXG4gKiAgLSB7c3RyaW5nfSBtc2dcbiAqICAgICAgZXJyb3IgbWVzc2FnZSAoc2hvd24gaW4gY29uc29sZSBpbiBsb2dnZXIgY29uZmlnIGFyZ3VtZW50IGlzIGVuYWJsZSlcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB2YWxpZGF0ZShkYXRhLCBsYXlvdXQpIHtcbiAgICB2YXIgc2NoZW1hID0gUGxvdFNjaGVtYS5nZXQoKTtcbiAgICB2YXIgZXJyb3JMaXN0ID0gW107XG4gICAgdmFyIGdkID0ge19jb250ZXh0OiBMaWIuZXh0ZW5kRmxhdCh7fSwgZGZsdENvbmZpZyl9O1xuXG4gICAgdmFyIGRhdGFJbiwgbGF5b3V0SW47XG5cbiAgICBpZihpc0FycmF5KGRhdGEpKSB7XG4gICAgICAgIGdkLmRhdGEgPSBMaWIuZXh0ZW5kRGVlcChbXSwgZGF0YSk7XG4gICAgICAgIGRhdGFJbiA9IGRhdGE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2QuZGF0YSA9IFtdO1xuICAgICAgICBkYXRhSW4gPSBbXTtcbiAgICAgICAgZXJyb3JMaXN0LnB1c2goZm9ybWF0KCdhcnJheScsICdkYXRhJykpO1xuICAgIH1cblxuICAgIGlmKGlzUGxhaW5PYmplY3QobGF5b3V0KSkge1xuICAgICAgICBnZC5sYXlvdXQgPSBMaWIuZXh0ZW5kRGVlcCh7fSwgbGF5b3V0KTtcbiAgICAgICAgbGF5b3V0SW4gPSBsYXlvdXQ7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2QubGF5b3V0ID0ge307XG4gICAgICAgIGxheW91dEluID0ge307XG4gICAgICAgIGlmKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBlcnJvckxpc3QucHVzaChmb3JtYXQoJ29iamVjdCcsICdsYXlvdXQnKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBOLkIuIGRhdGFJbiBhbmQgbGF5b3V0SW4gYXJlIGluIGdlbmVyYWwgbm90IHRoZSBzYW1lIGFzXG4gICAgLy8gZ2QuZGF0YSBhbmQgZ2QubGF5b3V0IGFmdGVyIHN1cHBseURlZmF1bHRzIGFzIHNvbWUgYXR0cmlidXRlc1xuICAgIC8vIGluIGdkLmRhdGEgYW5kIGdkLmxheW91dCAoc3RpbGwpIGdldCBtdXRhdGVkIGR1cmluZyB0aGlzIHN0ZXAuXG5cbiAgICBQbG90cy5zdXBwbHlEZWZhdWx0cyhnZCk7XG5cbiAgICB2YXIgZGF0YU91dCA9IGdkLl9mdWxsRGF0YTtcbiAgICB2YXIgbGVuID0gZGF0YUluLmxlbmd0aDtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgdHJhY2VJbiA9IGRhdGFJbltpXTtcbiAgICAgICAgdmFyIGJhc2UgPSBbJ2RhdGEnLCBpXTtcblxuICAgICAgICBpZighaXNQbGFpbk9iamVjdCh0cmFjZUluKSkge1xuICAgICAgICAgICAgZXJyb3JMaXN0LnB1c2goZm9ybWF0KCdvYmplY3QnLCBiYXNlKSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0cmFjZU91dCA9IGRhdGFPdXRbaV07XG4gICAgICAgIHZhciB0cmFjZVR5cGUgPSB0cmFjZU91dC50eXBlO1xuICAgICAgICB2YXIgdHJhY2VTY2hlbWEgPSBzY2hlbWEudHJhY2VzW3RyYWNlVHlwZV0uYXR0cmlidXRlcztcblxuICAgICAgICAvLyBQbG90U2NoZW1hIGRvZXMgc29tZXRoaW5nIGZhbmN5IHdpdGggdHJhY2UgJ3R5cGUnLCByZXNldCBpdCBoZXJlXG4gICAgICAgIC8vIHRvIG1ha2UgdGhlIHRyYWNlIHNjaGVtYSBjb21wYXRpYmxlIHdpdGggTGliLnZhbGlkYXRlLlxuICAgICAgICB0cmFjZVNjaGVtYS50eXBlID0ge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbdHJhY2VUeXBlXVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmKHRyYWNlT3V0LnZpc2libGUgPT09IGZhbHNlICYmIHRyYWNlSW4udmlzaWJsZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGVycm9yTGlzdC5wdXNoKGZvcm1hdCgnaW52aXNpYmxlJywgYmFzZSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY3Jhd2wodHJhY2VJbiwgdHJhY2VPdXQsIHRyYWNlU2NoZW1hLCBlcnJvckxpc3QsIGJhc2UpO1xuXG4gICAgICAgIHZhciB0cmFuc2Zvcm1zSW4gPSB0cmFjZUluLnRyYW5zZm9ybXM7XG4gICAgICAgIHZhciB0cmFuc2Zvcm1zT3V0ID0gdHJhY2VPdXQudHJhbnNmb3JtcztcblxuICAgICAgICBpZih0cmFuc2Zvcm1zSW4pIHtcbiAgICAgICAgICAgIGlmKCFpc0FycmF5KHRyYW5zZm9ybXNJbikpIHtcbiAgICAgICAgICAgICAgICBlcnJvckxpc3QucHVzaChmb3JtYXQoJ2FycmF5JywgYmFzZSwgWyd0cmFuc2Zvcm1zJ10pKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYmFzZS5wdXNoKCd0cmFuc2Zvcm1zJyk7XG5cbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB0cmFuc2Zvcm1zSW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0aCA9IFsndHJhbnNmb3JtcycsIGpdO1xuICAgICAgICAgICAgICAgIHZhciB0cmFuc2Zvcm1UeXBlID0gdHJhbnNmb3Jtc0luW2pdLnR5cGU7XG5cbiAgICAgICAgICAgICAgICBpZighaXNQbGFpbk9iamVjdCh0cmFuc2Zvcm1zSW5bal0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yTGlzdC5wdXNoKGZvcm1hdCgnb2JqZWN0JywgYmFzZSwgcGF0aCkpO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgdHJhbnNmb3JtU2NoZW1hID0gc2NoZW1hLnRyYW5zZm9ybXNbdHJhbnNmb3JtVHlwZV0gP1xuICAgICAgICAgICAgICAgICAgICBzY2hlbWEudHJhbnNmb3Jtc1t0cmFuc2Zvcm1UeXBlXS5hdHRyaWJ1dGVzIDpcbiAgICAgICAgICAgICAgICAgICAge307XG5cbiAgICAgICAgICAgICAgICAvLyBhZGQgJ3R5cGUnIHRvIHRyYW5zZm9ybSBzY2hlbWEgdG8gdmFsaWRhdGUgdGhlIHRyYW5zZm9ybSB0eXBlXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtU2NoZW1hLnR5cGUgPSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVzOiBPYmplY3Qua2V5cyhzY2hlbWEudHJhbnNmb3JtcylcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgY3Jhd2wodHJhbnNmb3Jtc0luW2pdLCB0cmFuc2Zvcm1zT3V0W2pdLCB0cmFuc2Zvcm1TY2hlbWEsIGVycm9yTGlzdCwgYmFzZSwgcGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbGF5b3V0T3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGxheW91dFNjaGVtYSA9IGZpbGxMYXlvdXRTY2hlbWEoc2NoZW1hLCBkYXRhT3V0KTtcblxuICAgIGNyYXdsKGxheW91dEluLCBsYXlvdXRPdXQsIGxheW91dFNjaGVtYSwgZXJyb3JMaXN0LCAnbGF5b3V0Jyk7XG5cbiAgICAvLyByZXR1cm4gdW5kZWZpbmVkIGlmIG5vIHZhbGlkYXRpb24gZXJyb3JzIHdlcmUgZm91bmRcbiAgICByZXR1cm4gKGVycm9yTGlzdC5sZW5ndGggPT09IDApID8gdm9pZCgwKSA6IGVycm9yTGlzdDtcbn07XG5cbmZ1bmN0aW9uIGNyYXdsKG9iakluLCBvYmpPdXQsIHNjaGVtYSwgbGlzdCwgYmFzZSwgcGF0aCkge1xuICAgIHBhdGggPSBwYXRoIHx8IFtdO1xuXG4gICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmpJbik7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgayA9IGtleXNbaV07XG5cbiAgICAgICAgLy8gdHJhbnNmb3JtcyBhcmUgaGFuZGxlZCBzZXBhcmF0ZWx5XG4gICAgICAgIGlmKGsgPT09ICd0cmFuc2Zvcm1zJykgY29udGludWU7XG5cbiAgICAgICAgdmFyIHAgPSBwYXRoLnNsaWNlKCk7XG4gICAgICAgIHAucHVzaChrKTtcblxuICAgICAgICB2YXIgdmFsSW4gPSBvYmpJbltrXTtcbiAgICAgICAgdmFyIHZhbE91dCA9IG9iak91dFtrXTtcblxuICAgICAgICB2YXIgbmVzdGVkU2NoZW1hID0gZ2V0TmVzdGVkU2NoZW1hKHNjaGVtYSwgayk7XG4gICAgICAgIHZhciBpc0luZm9BcnJheSA9IChuZXN0ZWRTY2hlbWEgfHwge30pLnZhbFR5cGUgPT09ICdpbmZvX2FycmF5JztcbiAgICAgICAgdmFyIGlzQ29sb3JzY2FsZSA9IChuZXN0ZWRTY2hlbWEgfHwge30pLnZhbFR5cGUgPT09ICdjb2xvcnNjYWxlJztcbiAgICAgICAgdmFyIGl0ZW1zID0gKG5lc3RlZFNjaGVtYSB8fCB7fSkuaXRlbXM7XG5cbiAgICAgICAgaWYoIWlzSW5TY2hlbWEoc2NoZW1hLCBrKSkge1xuICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgnc2NoZW1hJywgYmFzZSwgcCkpO1xuICAgICAgICB9IGVsc2UgaWYoaXNQbGFpbk9iamVjdCh2YWxJbikgJiYgaXNQbGFpbk9iamVjdCh2YWxPdXQpKSB7XG4gICAgICAgICAgICBjcmF3bCh2YWxJbiwgdmFsT3V0LCBuZXN0ZWRTY2hlbWEsIGxpc3QsIGJhc2UsIHApO1xuICAgICAgICB9IGVsc2UgaWYoaXNJbmZvQXJyYXkgJiYgaXNBcnJheSh2YWxJbikpIHtcbiAgICAgICAgICAgIGlmKHZhbEluLmxlbmd0aCA+IHZhbE91dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCd1bnVzZWQnLCBiYXNlLCBwLmNvbmNhdCh2YWxPdXQubGVuZ3RoKSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGxlbiA9IHZhbE91dC5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgYXJyYXlJdGVtcyA9IEFycmF5LmlzQXJyYXkoaXRlbXMpO1xuICAgICAgICAgICAgaWYoYXJyYXlJdGVtcykgbGVuID0gTWF0aC5taW4obGVuLCBpdGVtcy5sZW5ndGgpO1xuICAgICAgICAgICAgdmFyIG0sIG4sIGl0ZW0sIHZhbEluUGFydCwgdmFsT3V0UGFydDtcbiAgICAgICAgICAgIGlmKG5lc3RlZFNjaGVtYS5kaW1lbnNpb25zID09PSAyKSB7XG4gICAgICAgICAgICAgICAgZm9yKG4gPSAwOyBuIDwgbGVuOyBuKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoaXNBcnJheSh2YWxJbltuXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHZhbEluW25dLmxlbmd0aCA+IHZhbE91dFtuXS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCd1bnVzZWQnLCBiYXNlLCBwLmNvbmNhdChuLCB2YWxPdXRbbl0ubGVuZ3RoKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbjIgPSB2YWxPdXRbbl0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKG0gPSAwOyBtIDwgKGFycmF5SXRlbXMgPyBNYXRoLm1pbihsZW4yLCBpdGVtc1tuXS5sZW5ndGgpIDogbGVuMik7IG0rKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0gPSBhcnJheUl0ZW1zID8gaXRlbXNbbl1bbV0gOiBpdGVtcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxJblBhcnQgPSB2YWxJbltuXVttXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxPdXRQYXJ0ID0gdmFsT3V0W25dW21dO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKCFMaWIudmFsaWRhdGUodmFsSW5QYXJ0LCBpdGVtKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCd2YWx1ZScsIGJhc2UsIHAuY29uY2F0KG4sIG0pLCB2YWxJblBhcnQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYodmFsT3V0UGFydCAhPT0gdmFsSW5QYXJ0ICYmIHZhbE91dFBhcnQgIT09ICt2YWxJblBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgnZHluYW1pYycsIGJhc2UsIHAuY29uY2F0KG4sIG0pLCB2YWxJblBhcnQsIHZhbE91dFBhcnQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCdhcnJheScsIGJhc2UsIHAuY29uY2F0KG4pLCB2YWxJbltuXSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb3IobiA9IDA7IG4gPCBsZW47IG4rKykge1xuICAgICAgICAgICAgICAgICAgICBpdGVtID0gYXJyYXlJdGVtcyA/IGl0ZW1zW25dIDogaXRlbXM7XG4gICAgICAgICAgICAgICAgICAgIHZhbEluUGFydCA9IHZhbEluW25dO1xuICAgICAgICAgICAgICAgICAgICB2YWxPdXRQYXJ0ID0gdmFsT3V0W25dO1xuICAgICAgICAgICAgICAgICAgICBpZighTGliLnZhbGlkYXRlKHZhbEluUGFydCwgaXRlbSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QucHVzaChmb3JtYXQoJ3ZhbHVlJywgYmFzZSwgcC5jb25jYXQobiksIHZhbEluUGFydCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYodmFsT3V0UGFydCAhPT0gdmFsSW5QYXJ0ICYmIHZhbE91dFBhcnQgIT09ICt2YWxJblBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QucHVzaChmb3JtYXQoJ2R5bmFtaWMnLCBiYXNlLCBwLmNvbmNhdChuKSwgdmFsSW5QYXJ0LCB2YWxPdXRQYXJ0KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihuZXN0ZWRTY2hlbWEuaXRlbXMgJiYgIWlzSW5mb0FycmF5ICYmIGlzQXJyYXkodmFsSW4pKSB7XG4gICAgICAgICAgICB2YXIgX25lc3RlZFNjaGVtYSA9IGl0ZW1zW09iamVjdC5rZXlzKGl0ZW1zKVswXV07XG4gICAgICAgICAgICB2YXIgaW5kZXhMaXN0ID0gW107XG5cbiAgICAgICAgICAgIHZhciBqLCBfcDtcblxuICAgICAgICAgICAgLy8gbG9vcCBvdmVyIHZhbE91dCBpdGVtcyB3aGlsZSBrZWVwaW5nIHRyYWNrIG9mIHRoZWlyXG4gICAgICAgICAgICAvLyBjb3JyZXNwb25kaW5nIGlucHV0IGNvbnRhaW5lciBpbmRleCAoZ2l2ZW4gYnkgX2luZGV4KVxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgdmFsT3V0Lmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIF9pbmRleCA9IHZhbE91dFtqXS5faW5kZXggfHwgajtcblxuICAgICAgICAgICAgICAgIF9wID0gcC5zbGljZSgpO1xuICAgICAgICAgICAgICAgIF9wLnB1c2goX2luZGV4KTtcblxuICAgICAgICAgICAgICAgIGlmKGlzUGxhaW5PYmplY3QodmFsSW5bX2luZGV4XSkgJiYgaXNQbGFpbk9iamVjdCh2YWxPdXRbal0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4TGlzdC5wdXNoKF9pbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWxJbmogPSB2YWxJbltfaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsT3V0aiA9IHZhbE91dFtqXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoaXNQbGFpbk9iamVjdCh2YWxJbmopICYmIHZhbEluai52aXNpYmxlICE9PSBmYWxzZSAmJiB2YWxPdXRqLnZpc2libGUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCdpbnZpc2libGUnLCBiYXNlLCBfcCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgY3Jhd2wodmFsSW5qLCB2YWxPdXRqLCBfbmVzdGVkU2NoZW1hLCBsaXN0LCBiYXNlLCBfcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBsb29wIG92ZXIgdmFsSW4gdG8gZGV0ZXJtaW5lIHdoZXJlIGl0IHdlbnQgd3JvbmcgZm9yIHNvbWUgaXRlbXNcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHZhbEluLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgX3AgPSBwLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgX3AucHVzaChqKTtcblxuICAgICAgICAgICAgICAgIGlmKCFpc1BsYWluT2JqZWN0KHZhbEluW2pdKSkge1xuICAgICAgICAgICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCdvYmplY3QnLCBiYXNlLCBfcCwgdmFsSW5bal0pKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoaW5kZXhMaXN0LmluZGV4T2YoaikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3QucHVzaChmb3JtYXQoJ3VudXNlZCcsIGJhc2UsIF9wKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoIWlzUGxhaW5PYmplY3QodmFsSW4pICYmIGlzUGxhaW5PYmplY3QodmFsT3V0KSkge1xuICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgnb2JqZWN0JywgYmFzZSwgcCwgdmFsSW4pKTtcbiAgICAgICAgfSBlbHNlIGlmKCFpc0FycmF5T3JUeXBlZEFycmF5KHZhbEluKSAmJiBpc0FycmF5T3JUeXBlZEFycmF5KHZhbE91dCkgJiYgIWlzSW5mb0FycmF5ICYmICFpc0NvbG9yc2NhbGUpIHtcbiAgICAgICAgICAgIGxpc3QucHVzaChmb3JtYXQoJ2FycmF5JywgYmFzZSwgcCwgdmFsSW4pKTtcbiAgICAgICAgfSBlbHNlIGlmKCEoayBpbiBvYmpPdXQpKSB7XG4gICAgICAgICAgICBsaXN0LnB1c2goZm9ybWF0KCd1bnVzZWQnLCBiYXNlLCBwLCB2YWxJbikpO1xuICAgICAgICB9IGVsc2UgaWYoIUxpYi52YWxpZGF0ZSh2YWxJbiwgbmVzdGVkU2NoZW1hKSkge1xuICAgICAgICAgICAgbGlzdC5wdXNoKGZvcm1hdCgndmFsdWUnLCBiYXNlLCBwLCB2YWxJbikpO1xuICAgICAgICB9IGVsc2UgaWYobmVzdGVkU2NoZW1hLnZhbFR5cGUgPT09ICdlbnVtZXJhdGVkJyAmJlxuICAgICAgICAgICAgKChuZXN0ZWRTY2hlbWEuY29lcmNlTnVtYmVyICYmIHZhbEluICE9PSArdmFsT3V0KSB8fCB2YWxJbiAhPT0gdmFsT3V0KVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGxpc3QucHVzaChmb3JtYXQoJ2R5bmFtaWMnLCBiYXNlLCBwLCB2YWxJbiwgdmFsT3V0KSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGlzdDtcbn1cblxuLy8gdGhlICdmdWxsJyBsYXlvdXQgc2NoZW1hIGRlcGVuZHMgb24gdGhlIHRyYWNlcyB0eXBlcyBwcmVzZW50c1xuZnVuY3Rpb24gZmlsbExheW91dFNjaGVtYShzY2hlbWEsIGRhdGFPdXQpIHtcbiAgICB2YXIgbGF5b3V0U2NoZW1hID0gc2NoZW1hLmxheW91dC5sYXlvdXRBdHRyaWJ1dGVzO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGRhdGFPdXQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlT3V0ID0gZGF0YU91dFtpXTtcbiAgICAgICAgdmFyIHRyYWNlU2NoZW1hID0gc2NoZW1hLnRyYWNlc1t0cmFjZU91dC50eXBlXTtcbiAgICAgICAgdmFyIHRyYWNlTGF5b3V0QXR0ciA9IHRyYWNlU2NoZW1hLmxheW91dEF0dHJpYnV0ZXM7XG5cbiAgICAgICAgaWYodHJhY2VMYXlvdXRBdHRyKSB7XG4gICAgICAgICAgICBpZih0cmFjZU91dC5zdWJwbG90KSB7XG4gICAgICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQobGF5b3V0U2NoZW1hW3RyYWNlU2NoZW1hLmF0dHJpYnV0ZXMuc3VicGxvdC5kZmx0XSwgdHJhY2VMYXlvdXRBdHRyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQobGF5b3V0U2NoZW1hLCB0cmFjZUxheW91dEF0dHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGxheW91dFNjaGVtYTtcbn1cblxuLy8gdmFsaWRhdGlvbiBlcnJvciBjb2Rlc1xudmFyIGNvZGUybXNnRnVuYyA9IHtcbiAgICBvYmplY3Q6IGZ1bmN0aW9uKGJhc2UsIGFzdHIpIHtcbiAgICAgICAgdmFyIHByZWZpeDtcblxuICAgICAgICBpZihiYXNlID09PSAnbGF5b3V0JyAmJiBhc3RyID09PSAnJykgcHJlZml4ID0gJ1RoZSBsYXlvdXQgYXJndW1lbnQnO1xuICAgICAgICBlbHNlIGlmKGJhc2VbMF0gPT09ICdkYXRhJyAmJiBhc3RyID09PSAnJykge1xuICAgICAgICAgICAgcHJlZml4ID0gJ1RyYWNlICcgKyBiYXNlWzFdICsgJyBpbiB0aGUgZGF0YSBhcmd1bWVudCc7XG4gICAgICAgIH0gZWxzZSBwcmVmaXggPSBpbkJhc2UoYmFzZSkgKyAna2V5ICcgKyBhc3RyO1xuXG4gICAgICAgIHJldHVybiBwcmVmaXggKyAnIG11c3QgYmUgbGlua2VkIHRvIGFuIG9iamVjdCBjb250YWluZXInO1xuICAgIH0sXG4gICAgYXJyYXk6IGZ1bmN0aW9uKGJhc2UsIGFzdHIpIHtcbiAgICAgICAgdmFyIHByZWZpeDtcblxuICAgICAgICBpZihiYXNlID09PSAnZGF0YScpIHByZWZpeCA9ICdUaGUgZGF0YSBhcmd1bWVudCc7XG4gICAgICAgIGVsc2UgcHJlZml4ID0gaW5CYXNlKGJhc2UpICsgJ2tleSAnICsgYXN0cjtcblxuICAgICAgICByZXR1cm4gcHJlZml4ICsgJyBtdXN0IGJlIGxpbmtlZCB0byBhbiBhcnJheSBjb250YWluZXInO1xuICAgIH0sXG4gICAgc2NoZW1hOiBmdW5jdGlvbihiYXNlLCBhc3RyKSB7XG4gICAgICAgIHJldHVybiBpbkJhc2UoYmFzZSkgKyAna2V5ICcgKyBhc3RyICsgJyBpcyBub3QgcGFydCBvZiB0aGUgc2NoZW1hJztcbiAgICB9LFxuICAgIHVudXNlZDogZnVuY3Rpb24oYmFzZSwgYXN0ciwgdmFsSW4pIHtcbiAgICAgICAgdmFyIHRhcmdldCA9IGlzUGxhaW5PYmplY3QodmFsSW4pID8gJ2NvbnRhaW5lcicgOiAna2V5JztcblxuICAgICAgICByZXR1cm4gaW5CYXNlKGJhc2UpICsgdGFyZ2V0ICsgJyAnICsgYXN0ciArICcgZGlkIG5vdCBnZXQgY29lcmNlZCc7XG4gICAgfSxcbiAgICBkeW5hbWljOiBmdW5jdGlvbihiYXNlLCBhc3RyLCB2YWxJbiwgdmFsT3V0KSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBpbkJhc2UoYmFzZSkgKyAna2V5JyxcbiAgICAgICAgICAgIGFzdHIsXG4gICAgICAgICAgICAnKHNldCB0byBcXCcnICsgdmFsSW4gKyAnXFwnKScsXG4gICAgICAgICAgICAnZ290IHJlc2V0IHRvJyxcbiAgICAgICAgICAgICdcXCcnICsgdmFsT3V0ICsgJ1xcJycsXG4gICAgICAgICAgICAnZHVyaW5nIGRlZmF1bHRzLidcbiAgICAgICAgXS5qb2luKCcgJyk7XG4gICAgfSxcbiAgICBpbnZpc2libGU6IGZ1bmN0aW9uKGJhc2UsIGFzdHIpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGFzdHIgPyAoaW5CYXNlKGJhc2UpICsgJ2l0ZW0gJyArIGFzdHIpIDogKCdUcmFjZSAnICsgYmFzZVsxXSlcbiAgICAgICAgKSArICcgZ290IGRlZmF1bHRlZCB0byBiZSBub3QgdmlzaWJsZSc7XG4gICAgfSxcbiAgICB2YWx1ZTogZnVuY3Rpb24oYmFzZSwgYXN0ciwgdmFsSW4pIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIGluQmFzZShiYXNlKSArICdrZXkgJyArIGFzdHIsXG4gICAgICAgICAgICAnaXMgc2V0IHRvIGFuIGludmFsaWQgdmFsdWUgKCcgKyB2YWxJbiArICcpJ1xuICAgICAgICBdLmpvaW4oJyAnKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBpbkJhc2UoYmFzZSkge1xuICAgIGlmKGlzQXJyYXkoYmFzZSkpIHJldHVybiAnSW4gZGF0YSB0cmFjZSAnICsgYmFzZVsxXSArICcsICc7XG5cbiAgICByZXR1cm4gJ0luICcgKyBiYXNlICsgJywgJztcbn1cblxuZnVuY3Rpb24gZm9ybWF0KGNvZGUsIGJhc2UsIHBhdGgsIHZhbEluLCB2YWxPdXQpIHtcbiAgICBwYXRoID0gcGF0aCB8fCAnJztcblxuICAgIHZhciBjb250YWluZXIsIHRyYWNlO1xuXG4gICAgLy8gY29udGFpbmVyIGlzIGVpdGhlciAnZGF0YScgb3IgJ2xheW91dFxuICAgIC8vIHRyYWNlIGlzIHRoZSB0cmFjZSBpbmRleCBpZiAnZGF0YScsIG51bGwgb3RoZXJ3aXNlXG5cbiAgICBpZihpc0FycmF5KGJhc2UpKSB7XG4gICAgICAgIGNvbnRhaW5lciA9IGJhc2VbMF07XG4gICAgICAgIHRyYWNlID0gYmFzZVsxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb250YWluZXIgPSBiYXNlO1xuICAgICAgICB0cmFjZSA9IG51bGw7XG4gICAgfVxuXG4gICAgdmFyIGFzdHIgPSBjb252ZXJ0UGF0aFRvQXR0cmlidXRlU3RyaW5nKHBhdGgpO1xuICAgIHZhciBtc2cgPSBjb2RlMm1zZ0Z1bmNbY29kZV0oYmFzZSwgYXN0ciwgdmFsSW4sIHZhbE91dCk7XG5cbiAgICAvLyBsb2cgdG8gY29uc29sZSBpZiBsb2dnZXIgY29uZmlnIG9wdGlvbiBpcyBlbmFibGVkXG4gICAgTGliLmxvZyhtc2cpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29kZTogY29kZSxcbiAgICAgICAgY29udGFpbmVyOiBjb250YWluZXIsXG4gICAgICAgIHRyYWNlOiB0cmFjZSxcbiAgICAgICAgcGF0aDogcGF0aCxcbiAgICAgICAgYXN0cjogYXN0cixcbiAgICAgICAgbXNnOiBtc2dcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBpc0luU2NoZW1hKHNjaGVtYSwga2V5KSB7XG4gICAgdmFyIHBhcnRzID0gc3BsaXRLZXkoa2V5KTtcbiAgICB2YXIga2V5TWludXNJZCA9IHBhcnRzLmtleU1pbnVzSWQ7XG4gICAgdmFyIGlkID0gcGFydHMuaWQ7XG5cbiAgICBpZigoa2V5TWludXNJZCBpbiBzY2hlbWEpICYmIHNjaGVtYVtrZXlNaW51c0lkXS5faXNTdWJwbG90T2JqICYmIGlkKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiAoa2V5IGluIHNjaGVtYSk7XG59XG5cbmZ1bmN0aW9uIGdldE5lc3RlZFNjaGVtYShzY2hlbWEsIGtleSkge1xuICAgIGlmKGtleSBpbiBzY2hlbWEpIHJldHVybiBzY2hlbWFba2V5XTtcblxuICAgIHZhciBwYXJ0cyA9IHNwbGl0S2V5KGtleSk7XG5cbiAgICByZXR1cm4gc2NoZW1hW3BhcnRzLmtleU1pbnVzSWRdO1xufVxuXG52YXIgaWRSZWdleCA9IExpYi5jb3VudGVyUmVnZXgoJyhbYS16XSspJyk7XG5cbmZ1bmN0aW9uIHNwbGl0S2V5KGtleSkge1xuICAgIHZhciBpZE1hdGNoID0ga2V5Lm1hdGNoKGlkUmVnZXgpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAga2V5TWludXNJZDogaWRNYXRjaCAmJiBpZE1hdGNoWzFdLFxuICAgICAgICBpZDogaWRNYXRjaCAmJiBpZE1hdGNoWzJdXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY29udmVydFBhdGhUb0F0dHJpYnV0ZVN0cmluZyhwYXRoKSB7XG4gICAgaWYoIWlzQXJyYXkocGF0aCkpIHJldHVybiBTdHJpbmcocGF0aCk7XG5cbiAgICB2YXIgYXN0ciA9ICcnO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHAgPSBwYXRoW2ldO1xuXG4gICAgICAgIGlmKHR5cGVvZiBwID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgYXN0ciA9IGFzdHIuc3Vic3RyKDAsIGFzdHIubGVuZ3RoIC0gMSkgKyAnWycgKyBwICsgJ10nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXN0ciArPSBwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaSA8IHBhdGgubGVuZ3RoIC0gMSkgYXN0ciArPSAnLic7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFzdHI7XG59XG5cbn0se1wiLi4vbGliXCI6NzE5LFwiLi4vcGxvdHMvcGxvdHNcIjo4MjgsXCIuL3Bsb3RfY29uZmlnXCI6NzU1LFwiLi9wbG90X3NjaGVtYVwiOjc1Nn1dLDc2MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBkZmx0OiAnYWZ0ZXJhbGwnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ2ltbWVkaWF0ZScsICduZXh0JywgJ2FmdGVyYWxsJ10sXG4gICAgICAgIFxuICAgIH0sXG4gICAgZGlyZWN0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWydmb3J3YXJkJywgJ3JldmVyc2UnXSxcbiAgICAgICAgZGZsdDogJ2ZvcndhcmQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGZyb21jdXJyZW50OiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGZyYW1lOiB7XG4gICAgICAgIGR1cmF0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogNTAwLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHJlZHJhdzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgfSxcbiAgICB0cmFuc2l0aW9uOiB7XG4gICAgICAgIGR1cmF0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogNTAwLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlYXNpbmc6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIGRmbHQ6ICdjdWJpYy1pbi1vdXQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAgICAgJ2xpbmVhcicsXG4gICAgICAgICAgICAgICAgJ3F1YWQnLFxuICAgICAgICAgICAgICAgICdjdWJpYycsXG4gICAgICAgICAgICAgICAgJ3NpbicsXG4gICAgICAgICAgICAgICAgJ2V4cCcsXG4gICAgICAgICAgICAgICAgJ2NpcmNsZScsXG4gICAgICAgICAgICAgICAgJ2VsYXN0aWMnLFxuICAgICAgICAgICAgICAgICdiYWNrJyxcbiAgICAgICAgICAgICAgICAnYm91bmNlJyxcbiAgICAgICAgICAgICAgICAnbGluZWFyLWluJyxcbiAgICAgICAgICAgICAgICAncXVhZC1pbicsXG4gICAgICAgICAgICAgICAgJ2N1YmljLWluJyxcbiAgICAgICAgICAgICAgICAnc2luLWluJyxcbiAgICAgICAgICAgICAgICAnZXhwLWluJyxcbiAgICAgICAgICAgICAgICAnY2lyY2xlLWluJyxcbiAgICAgICAgICAgICAgICAnZWxhc3RpYy1pbicsXG4gICAgICAgICAgICAgICAgJ2JhY2staW4nLFxuICAgICAgICAgICAgICAgICdib3VuY2UtaW4nLFxuICAgICAgICAgICAgICAgICdsaW5lYXItb3V0JyxcbiAgICAgICAgICAgICAgICAncXVhZC1vdXQnLFxuICAgICAgICAgICAgICAgICdjdWJpYy1vdXQnLFxuICAgICAgICAgICAgICAgICdzaW4tb3V0JyxcbiAgICAgICAgICAgICAgICAnZXhwLW91dCcsXG4gICAgICAgICAgICAgICAgJ2NpcmNsZS1vdXQnLFxuICAgICAgICAgICAgICAgICdlbGFzdGljLW91dCcsXG4gICAgICAgICAgICAgICAgJ2JhY2stb3V0JyxcbiAgICAgICAgICAgICAgICAnYm91bmNlLW91dCcsXG4gICAgICAgICAgICAgICAgJ2xpbmVhci1pbi1vdXQnLFxuICAgICAgICAgICAgICAgICdxdWFkLWluLW91dCcsXG4gICAgICAgICAgICAgICAgJ2N1YmljLWluLW91dCcsXG4gICAgICAgICAgICAgICAgJ3Npbi1pbi1vdXQnLFxuICAgICAgICAgICAgICAgICdleHAtaW4tb3V0JyxcbiAgICAgICAgICAgICAgICAnY2lyY2xlLWluLW91dCcsXG4gICAgICAgICAgICAgICAgJ2VsYXN0aWMtaW4tb3V0JyxcbiAgICAgICAgICAgICAgICAnYmFjay1pbi1vdXQnLFxuICAgICAgICAgICAgICAgICdib3VuY2UtaW4tb3V0J1xuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBvcmRlcmluZzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2xheW91dCBmaXJzdCcsICd0cmFjZXMgZmlyc3QnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdsYXlvdXQgZmlyc3QnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHt9XSw3NjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG52YXIgVGVtcGxhdGUgPSBfZGVyZXFfKCcuLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJyk7XG5cbi8qKiBDb252ZW5pZW5jZSB3cmFwcGVyIGZvciBtYWtpbmcgYXJyYXkgY29udGFpbmVyIGxvZ2ljIERSWSBhbmQgY29uc2lzdGVudFxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBwYXJlbnRPYmpJblxuICogIHVzZXIgaW5wdXQgb2JqZWN0IHdoZXJlIHRoZSBjb250YWluZXIgaW4gcXVlc3Rpb24gaXMgbGlua2VkXG4gKiAgKGkuZS4gZWl0aGVyIGEgdXNlciB0cmFjZSBvYmplY3Qgb3IgdGhlIHVzZXIgbGF5b3V0IG9iamVjdClcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGFyZW50T2JqT3V0XG4gKiAgZnVsbCBvYmplY3Qgd2hlcmUgdGhlIGNvZXJjZWQgY29udGFpbmVyIHdpbGwgYmUgbGlua2VkXG4gKiAgKGkuZS4gZWl0aGVyIGEgZnVsbCB0cmFjZSBvYmplY3Qgb3IgdGhlIGZ1bGwgbGF5b3V0IG9iamVjdClcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0c1xuICogIG9wdGlvbnMgb2JqZWN0OlxuICogICAtIG5hbWUge3N0cmluZ31cbiAqICAgICAgbmFtZSBvZiB0aGUga2V5IGxpbmtpbmcgdGhlIGNvbnRhaW5lciBpbiBxdWVzdGlvblxuICogICAtIGluY2x1c2lvbkF0dHIge3N0cmluZ31cbiAqICAgICAgbmFtZSBvZiB0aGUgaXRlbSBhdHRyaWJ1dGUgZm9yIGluY2x1c2lvbi9leGNsdXNpb24uIERlZmF1bHQgaXMgJ3Zpc2libGUnLlxuICogICAgICBTaW5jZSBpbmNsdXNpb24gaXMgdHJ1ZSwgdXNlIGVnICdlbmFibGVkJyBpbnN0ZWFkIG9mICdkaXNhYmxlZCcuXG4gKiAgIC0gaGFuZGxlSXRlbURlZmF1bHRzIHtmdW5jdGlvbn1cbiAqICAgICAgZGVmYXVsdHMgbWV0aG9kIHRvIGJlIGNhbGxlZCBvbiBlYWNoIGl0ZW0gaW4gdGhlIGFycmF5IGNvbnRhaW5lciBpbiBxdWVzdGlvblxuICpcbiAqICAgICAgSXRzIGFyZ3VtZW50cyBhcmU6XG4gKiAgICAgICAgICAtIGl0ZW1JbiB7b2JqZWN0fSBpdGVtIGluIHVzZXIgbGF5b3V0XG4gKiAgICAgICAgICAtIGl0ZW1PdXQge29iamVjdH0gaXRlbSBpbiBmdWxsIGxheW91dFxuICogICAgICAgICAgLSBwYXJlbnRPYmoge29iamVjdH0gKGFzIGluIGNsb3N1cmUpXG4gKiAgICAgICAgICAtIG9wdHMge29iamVjdH0gKGFzIGluIGNsb3N1cmUpXG4gKiBOLkIuXG4gKlxuICogIC0gb3B0cyBpcyBwYXNzZWQgdG8gaGFuZGxlSXRlbURlZmF1bHRzIHNvIGl0IGNhbiBhbHNvIHN0b3JlXG4gKiAgICBsaW5rcyB0byBzdXBwbGVtZW50YXJ5IGRhdGEgKGUuZy4gZnVsbERhdGEgZm9yIGxheW91dCBjb21wb25lbnRzKVxuICpcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzKHBhcmVudE9iakluLCBwYXJlbnRPYmpPdXQsIG9wdHMpIHtcbiAgICB2YXIgbmFtZSA9IG9wdHMubmFtZTtcbiAgICB2YXIgaW5jbHVzaW9uQXR0ciA9IG9wdHMuaW5jbHVzaW9uQXR0ciB8fCAndmlzaWJsZSc7XG5cbiAgICB2YXIgcHJldmlvdXNDb250T3V0ID0gcGFyZW50T2JqT3V0W25hbWVdO1xuXG4gICAgdmFyIGNvbnRJbiA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHBhcmVudE9iakluW25hbWVdKSA/IHBhcmVudE9iakluW25hbWVdIDogW107XG4gICAgdmFyIGNvbnRPdXQgPSBwYXJlbnRPYmpPdXRbbmFtZV0gPSBbXTtcbiAgICB2YXIgdGVtcGxhdGVyID0gVGVtcGxhdGUuYXJyYXlUZW1wbGF0ZXIocGFyZW50T2JqT3V0LCBuYW1lLCBpbmNsdXNpb25BdHRyKTtcbiAgICB2YXIgaSwgaXRlbU91dDtcblxuICAgIGZvcihpID0gMDsgaSA8IGNvbnRJbi5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaXRlbUluID0gY29udEluW2ldO1xuXG4gICAgICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChpdGVtSW4pKSB7XG4gICAgICAgICAgICBpdGVtT3V0ID0gdGVtcGxhdGVyLm5ld0l0ZW0oe30pO1xuICAgICAgICAgICAgaXRlbU91dFtpbmNsdXNpb25BdHRyXSA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaXRlbU91dCA9IHRlbXBsYXRlci5uZXdJdGVtKGl0ZW1Jbik7XG4gICAgICAgIH1cblxuICAgICAgICBpdGVtT3V0Ll9pbmRleCA9IGk7XG5cbiAgICAgICAgaWYoaXRlbU91dFtpbmNsdXNpb25BdHRyXSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgIG9wdHMuaGFuZGxlSXRlbURlZmF1bHRzKGl0ZW1JbiwgaXRlbU91dCwgcGFyZW50T2JqT3V0LCBvcHRzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRPdXQucHVzaChpdGVtT3V0KTtcbiAgICB9XG5cbiAgICB2YXIgZGVmYXVsdEl0ZW1zID0gdGVtcGxhdGVyLmRlZmF1bHRJdGVtcygpO1xuICAgIGZvcihpID0gMDsgaSA8IGRlZmF1bHRJdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpdGVtT3V0ID0gZGVmYXVsdEl0ZW1zW2ldO1xuICAgICAgICBpdGVtT3V0Ll9pbmRleCA9IGNvbnRPdXQubGVuZ3RoO1xuICAgICAgICBvcHRzLmhhbmRsZUl0ZW1EZWZhdWx0cyh7fSwgaXRlbU91dCwgcGFyZW50T2JqT3V0LCBvcHRzLCB7fSk7XG4gICAgICAgIGNvbnRPdXQucHVzaChpdGVtT3V0KTtcbiAgICB9XG5cbiAgICAvLyBpbiBjYXNlIHRoaXMgYXJyYXkgZ2V0cyBpdHMgZGVmYXVsdHMgcmVidWlsdCBpbmRlcGVuZGVudCBvZiB0aGUgd2hvbGUgbGF5b3V0LFxuICAgIC8vIHJlbGluayB0aGUgcHJpdmF0ZSBrZXlzIGp1c3QgZm9yIHRoaXMgYXJyYXkuXG4gICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkocHJldmlvdXNDb250T3V0KSkge1xuICAgICAgICB2YXIgbGVuID0gTWF0aC5taW4ocHJldmlvdXNDb250T3V0Lmxlbmd0aCwgY29udE91dC5sZW5ndGgpO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgTGliLnJlbGlua1ByaXZhdGVLZXlzKGNvbnRPdXRbaV0sIHByZXZpb3VzQ29udE91dFtpXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29udE91dDtcbn07XG5cbn0se1wiLi4vbGliXCI6NzE5LFwiLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1N31dLDc2NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBmeEF0dHJzID0gX2RlcmVxXygnLi4vY29tcG9uZW50cy9meC9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHR5cGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbXSwgICAgIC8vIGxpc3RlZCBkeW5hbWljYWxseVxuICAgICAgICBkZmx0OiAnc2NhdHRlcicsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIF9ub1RlbXBsYXRpbmc6IHRydWUgLy8gd2UgaGFuZGxlIHRoaXMgYXQgYSBoaWdoZXIgbGV2ZWxcbiAgICB9LFxuICAgIHZpc2libGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFt0cnVlLCBmYWxzZSwgJ2xlZ2VuZG9ubHknXSxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd2xlZ2VuZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsZWdlbmRncm91cDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBvcGFjaXR5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG5hbWU6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB1aWQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGlkczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGFuaW06IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY3VzdG9tZGF0YToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbWV0YToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICAvLyBOLkIuIHRoZXNlIGNhbm5vdCBiZSAnZGF0YV9hcnJheScgYXMgdGhleSBkbyBub3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGggYXNcbiAgICAvLyBvdGhlciBkYXRhIGFycmF5cyBhbmQgYXJyYXlPayBhdHRyaWJ1dGVzIGluIGdlbmVyYWxcbiAgICAvL1xuICAgIC8vIE1heWJlIGFkZCBhbm90aGVyIHZhbFR5cGU6XG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzE4OTRcbiAgICBzZWxlY3RlZHBvaW50czoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBob3ZlcmluZm86IHtcbiAgICAgICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICAgICAgXG4gICAgICAgIGZsYWdzOiBbJ3gnLCAneScsICd6JywgJ3RleHQnLCAnbmFtZSddLFxuICAgICAgICBleHRyYXM6IFsnYWxsJywgJ25vbmUnLCAnc2tpcCddLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBkZmx0OiAnYWxsJyxcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBob3ZlcmxhYmVsOiBmeEF0dHJzLmhvdmVybGFiZWwsXG4gICAgc3RyZWFtOiB7XG4gICAgICAgIHRva2VuOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIG5vQmxhbms6IHRydWUsXG4gICAgICAgICAgICBzdHJpY3Q6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbWF4cG9pbnRzOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMTAwMDAsXG4gICAgICAgICAgICBkZmx0OiA1MDAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgdHJhbnNmb3Jtczoge1xuICAgICAgICBfaXNMaW5rZWRUb0FycmF5OiAndHJhbnNmb3JtJyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB1aXJldmlzaW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi9jb21wb25lbnRzL2Z4L2F0dHJpYnV0ZXNcIjo2MjN9XSw3NjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHhheGlzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ3gnLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHlheGlzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ3knLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHt9XSw3NjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEZQX1NBRkUgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuRlBfU0FGRTtcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGdldEF1dG9SYW5nZTogZ2V0QXV0b1JhbmdlLFxuICAgIG1ha2VQYWRGbjogbWFrZVBhZEZuLFxuICAgIGRvQXV0b1JhbmdlOiBkb0F1dG9SYW5nZSxcbiAgICBmaW5kRXh0cmVtZXM6IGZpbmRFeHRyZW1lcyxcbiAgICBjb25jYXRFeHRyZW1lczogY29uY2F0RXh0cmVtZXNcbn07XG5cbi8qKlxuICogZ2V0QXV0b1JhbmdlXG4gKlxuICogQ29sbGVjdHMgYWxsIF9leHRyZW1lcyB2YWx1ZXMgY29ycmVzcG9uZGluZyB0byBhIGdpdmVuIGF4aXNcbiAqIGFuZCBjb21wdXRlcyBpdHMgYXV0byByYW5nZS5cbiAqXG4gKiBOb3RlIHRoYXQgZ2V0QXV0b1JhbmdlIHVzZXMgcmV0dXJuIHZhbHVlcyBmcm9tIGZpbmRFeHRyZW1lcy5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gZ2Q6XG4gKiAgIGdyYXBoIGRpdiBvYmplY3Qgd2l0aCBmaWxsZWQtaW4gZnVsbERhdGEgYW5kIGZ1bGxMYXlvdXQsIGluIHBhcnRpY3VsYXJcbiAqICAgd2l0aCBmaWxsZWQtaW4gJ19leHRyZW1lcycgY29udGFpbmVyczpcbiAqICAge1xuICogICAgICB2YWw6IGNhbGNkYXRhIHZhbHVlLFxuICogICAgICBwYWQ6IGV4dHJhIHBpeGVscyBiZXlvbmQgdGhpcyB2YWx1ZSxcbiAqICAgICAgZXh0cmFwYWQ6IGJvb2wsIGRvZXMgdGhpcyBwb2ludCB3YW50IDUlIGV4dHJhIHBhZGRpbmdcbiAqICAgfVxuICogQHBhcmFtIHtvYmplY3R9IGF4OlxuICogICBmdWxsIGF4aXMgb2JqZWN0LCBpbiBwYXJ0aWN1bGFyIHdpdGggZmlsbGVkLWluICdfdHJhY2VJbmRpY2VzJ1xuICogICBhbmQgJ19hbm5JbmRpY2VzJyAvICdfc2hhcGVJbmRpY2VzJyBpZiBhcHBsaWNhYmxlXG4gKiBAcmV0dXJuIHthcnJheX1cbiAqICAgYW4gYXJyYXkgb2YgW21pbiwgbWF4XS4gVGhlc2UgYXJlIGNhbGNkYXRhIGZvciBsb2cgYW5kIGNhdGVnb3J5IGF4ZXNcbiAqICAgYW5kIGRhdGEgZm9yIGxpbmVhciBhbmQgZGF0ZSBheGVzLlxuICpcbiAqIFRPRE86IHdlIHdhbnQgdG8gY2hhbmdlIGxvZyB0byBkYXRhIGFzIHdlbGwsIGJ1dCBpdCdzIGhhcmQgdG8gZG8gdGhpc1xuICogbWFpbnRhaW5pbmcgYmFja3dhcmQgY29tcGF0aWJpbGl0eS4gY2F0ZWdvcnkgd2lsbCBhbHdheXMgaGF2ZSB0byB1c2UgY2FsY2RhdGFcbiAqIHRob3VnaCwgYmVjYXVzZSBvdGhlcndpc2UgdmFsdWVzIGJldHdlZW4gY2F0ZWdvcmllcyAob3Igb3V0c2lkZSBhbGwgY2F0ZWdvcmllcylcbiAqIHdvdWxkIGJlIGltcG9zc2libGUuXG4gKi9cbmZ1bmN0aW9uIGdldEF1dG9SYW5nZShnZCwgYXgpIHtcbiAgICB2YXIgaSwgajtcbiAgICB2YXIgbmV3UmFuZ2UgPSBbXTtcblxuICAgIHZhciBnZXRQYWQgPSBtYWtlUGFkRm4oYXgpO1xuICAgIHZhciBleHRyZW1lcyA9IGNvbmNhdEV4dHJlbWVzKGdkLCBheCk7XG4gICAgdmFyIG1pbkFycmF5ID0gZXh0cmVtZXMubWluO1xuICAgIHZhciBtYXhBcnJheSA9IGV4dHJlbWVzLm1heDtcblxuICAgIGlmKG1pbkFycmF5Lmxlbmd0aCA9PT0gMCB8fCBtYXhBcnJheS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIExpYi5zaW1wbGVNYXAoYXgucmFuZ2UsIGF4LnIybCk7XG4gICAgfVxuXG4gICAgdmFyIG1pbm1pbiA9IG1pbkFycmF5WzBdLnZhbDtcbiAgICB2YXIgbWF4bWF4ID0gbWF4QXJyYXlbMF0udmFsO1xuXG4gICAgZm9yKGkgPSAxOyBpIDwgbWluQXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYobWlubWluICE9PSBtYXhtYXgpIGJyZWFrO1xuICAgICAgICBtaW5taW4gPSBNYXRoLm1pbihtaW5taW4sIG1pbkFycmF5W2ldLnZhbCk7XG4gICAgfVxuICAgIGZvcihpID0gMTsgaSA8IG1heEFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKG1pbm1pbiAhPT0gbWF4bWF4KSBicmVhaztcbiAgICAgICAgbWF4bWF4ID0gTWF0aC5tYXgobWF4bWF4LCBtYXhBcnJheVtpXS52YWwpO1xuICAgIH1cblxuICAgIHZhciBheFJldmVyc2UgPSBmYWxzZTtcblxuICAgIGlmKGF4LnJhbmdlKSB7XG4gICAgICAgIHZhciBybmcgPSBMaWIuc2ltcGxlTWFwKGF4LnJhbmdlLCBheC5yMmwpO1xuICAgICAgICBheFJldmVyc2UgPSBybmdbMV0gPCBybmdbMF07XG4gICAgfVxuICAgIC8vIG9uZS10aW1lIHNldHRpbmcgdG8gZWFzaWx5IHJldmVyc2UgdGhlIGF4aXNcbiAgICAvLyB3aGVuIHBsb3R0aW5nIGZyb20gY29kZVxuICAgIGlmKGF4LmF1dG9yYW5nZSA9PT0gJ3JldmVyc2VkJykge1xuICAgICAgICBheFJldmVyc2UgPSB0cnVlO1xuICAgICAgICBheC5hdXRvcmFuZ2UgPSB0cnVlO1xuICAgIH1cblxuICAgIHZhciByYW5nZU1vZGUgPSBheC5yYW5nZW1vZGU7XG4gICAgdmFyIHRvWmVybyA9IHJhbmdlTW9kZSA9PT0gJ3RvemVybyc7XG4gICAgdmFyIG5vbk5lZ2F0aXZlID0gcmFuZ2VNb2RlID09PSAnbm9ubmVnYXRpdmUnO1xuICAgIHZhciBheExlbiA9IGF4Ll9sZW5ndGg7XG4gICAgLy8gZG9uJ3QgYWxsb3cgcGFkZGluZyB0byByZWR1Y2UgdGhlIGRhdGEgdG8gPCAxMCUgb2YgdGhlIGxlbmd0aFxuICAgIHZhciBtaW5TcGFuID0gYXhMZW4gLyAxMDtcblxuICAgIHZhciBtYmVzdCA9IDA7XG4gICAgdmFyIG1pbnB0LCBtYXhwdCwgbWluYmVzdCwgbWF4YmVzdCwgZHAsIGR2O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgbWluQXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbWlucHQgPSBtaW5BcnJheVtpXTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgbWF4QXJyYXkubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIG1heHB0ID0gbWF4QXJyYXlbal07XG4gICAgICAgICAgICBkdiA9IG1heHB0LnZhbCAtIG1pbnB0LnZhbDtcbiAgICAgICAgICAgIGlmKGR2ID4gMCkge1xuICAgICAgICAgICAgICAgIGRwID0gYXhMZW4gLSBnZXRQYWQobWlucHQpIC0gZ2V0UGFkKG1heHB0KTtcbiAgICAgICAgICAgICAgICBpZihkcCA+IG1pblNwYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoZHYgLyBkcCA+IG1iZXN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5iZXN0ID0gbWlucHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhiZXN0ID0gbWF4cHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYmVzdCA9IGR2IC8gZHA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoZHYgLyBheExlbiA+IG1iZXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGluIGNhc2Ugb2YgcGFkZGluZyBsb25nZXIgdGhhbiB0aGUgYXhpc1xuICAgICAgICAgICAgICAgICAgICAvLyBhdCBsZWFzdCBpbmNsdWRlIHRoZSB1bnBhZGRlZCBkYXRhIHZhbHVlcy5cbiAgICAgICAgICAgICAgICAgICAgbWluYmVzdCA9IHt2YWw6IG1pbnB0LnZhbCwgcGFkOiAwfTtcbiAgICAgICAgICAgICAgICAgICAgbWF4YmVzdCA9IHt2YWw6IG1heHB0LnZhbCwgcGFkOiAwfTtcbiAgICAgICAgICAgICAgICAgICAgbWJlc3QgPSBkdiAvIGF4TGVuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldE1heFBhZChwcmV2LCBwdCkge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgocHJldiwgZ2V0UGFkKHB0KSk7XG4gICAgfVxuXG4gICAgaWYobWlubWluID09PSBtYXhtYXgpIHtcbiAgICAgICAgdmFyIGxvd2VyID0gbWlubWluIC0gMTtcbiAgICAgICAgdmFyIHVwcGVyID0gbWlubWluICsgMTtcbiAgICAgICAgaWYodG9aZXJvKSB7XG4gICAgICAgICAgICBpZihtaW5taW4gPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgb25seSB2YWx1ZSB3ZSBoYXZlIG9uIHRoaXMgYXhpcyBpcyAwLCBhbmQgd2Ugd2FudCB0b1xuICAgICAgICAgICAgICAgIC8vIGF1dG9yYW5nZSBzbyB6ZXJvIGlzIG9uZSBlbmQuXG4gICAgICAgICAgICAgICAgLy8gSW4gcHJpbmNpcGxlIHRoaXMgY291bGQgYmUgWzAsIDFdIG9yIFstMSwgMF0gYnV0IHVzdWFsbHlcbiAgICAgICAgICAgICAgICAvLyAndG96ZXJvJyBwaW5zIDAgdG8gdGhlIGxvdyBlbmQsIHNvIGZvbGxvdyB0aGF0LlxuICAgICAgICAgICAgICAgIG5ld1JhbmdlID0gWzAsIDFdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgbWF4UGFkID0gKG1pbm1pbiA+IDAgPyBtYXhBcnJheSA6IG1pbkFycmF5KS5yZWR1Y2UoZ2V0TWF4UGFkLCAwKTtcbiAgICAgICAgICAgICAgICAvLyB3ZSdyZSBwdXNoaW5nIGEgc2luZ2xlIHZhbHVlIGF3YXkgZnJvbSB0aGUgZWRnZSBkdWUgdG8gaXRzXG4gICAgICAgICAgICAgICAgLy8gcGFkZGluZywgd2l0aCB0aGUgb3RoZXIgZW5kIGNsYW1wZWQgYXQgemVyb1xuICAgICAgICAgICAgICAgIC8vIDAuNSBtZWFucyBkb24ndCBwdXNoIGl0IGZhcnRoZXIgdGhhbiB0aGUgY2VudGVyLlxuICAgICAgICAgICAgICAgIHZhciByYW5nZUVuZCA9IG1pbm1pbiAvICgxIC0gTWF0aC5taW4oMC41LCBtYXhQYWQgLyBheExlbikpO1xuICAgICAgICAgICAgICAgIG5ld1JhbmdlID0gbWlubWluID4gMCA/IFswLCByYW5nZUVuZF0gOiBbcmFuZ2VFbmQsIDBdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYobm9uTmVnYXRpdmUpIHtcbiAgICAgICAgICAgIG5ld1JhbmdlID0gW01hdGgubWF4KDAsIGxvd2VyKSwgTWF0aC5tYXgoMSwgdXBwZXIpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld1JhbmdlID0gW2xvd2VyLCB1cHBlcl07XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBpZih0b1plcm8pIHtcbiAgICAgICAgICAgIGlmKG1pbmJlc3QudmFsID49IDApIHtcbiAgICAgICAgICAgICAgICBtaW5iZXN0ID0ge3ZhbDogMCwgcGFkOiAwfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKG1heGJlc3QudmFsIDw9IDApIHtcbiAgICAgICAgICAgICAgICBtYXhiZXN0ID0ge3ZhbDogMCwgcGFkOiAwfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKG5vbk5lZ2F0aXZlKSB7XG4gICAgICAgICAgICBpZihtaW5iZXN0LnZhbCAtIG1iZXN0ICogZ2V0UGFkKG1pbmJlc3QpIDwgMCkge1xuICAgICAgICAgICAgICAgIG1pbmJlc3QgPSB7dmFsOiAwLCBwYWQ6IDB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYobWF4YmVzdC52YWwgPD0gMCkge1xuICAgICAgICAgICAgICAgIG1heGJlc3QgPSB7dmFsOiAxLCBwYWQ6IDB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gaW4gY2FzZSBpdCBjaGFuZ2VkIGFnYWluLi4uXG4gICAgICAgIG1iZXN0ID0gKG1heGJlc3QudmFsIC0gbWluYmVzdC52YWwpIC9cbiAgICAgICAgICAgIChheExlbiAtIGdldFBhZChtaW5iZXN0KSAtIGdldFBhZChtYXhiZXN0KSk7XG5cbiAgICAgICAgbmV3UmFuZ2UgPSBbXG4gICAgICAgICAgICBtaW5iZXN0LnZhbCAtIG1iZXN0ICogZ2V0UGFkKG1pbmJlc3QpLFxuICAgICAgICAgICAgbWF4YmVzdC52YWwgKyBtYmVzdCAqIGdldFBhZChtYXhiZXN0KVxuICAgICAgICBdO1xuICAgIH1cblxuICAgIC8vIG1haW50YWluIHJldmVyc2FsXG4gICAgaWYoYXhSZXZlcnNlKSBuZXdSYW5nZS5yZXZlcnNlKCk7XG5cbiAgICByZXR1cm4gTGliLnNpbXBsZU1hcChuZXdSYW5nZSwgYXgubDJyIHx8IE51bWJlcik7XG59XG5cbi8qXG4gKiBjYWxjdWxhdGUgdGhlIHBpeGVsIHBhZGRpbmcgZm9yIGF4Ll9taW4gYW5kIGF4Ll9tYXggZW50cmllcyB3aXRoXG4gKiBvcHRpb25hbCBleHRyYXBhZCBhcyA1JSBvZiB0aGUgdG90YWwgYXhpcyBsZW5ndGhcbiAqL1xuZnVuY3Rpb24gbWFrZVBhZEZuKGF4KSB7XG4gICAgLy8gNSUgcGFkZGluZyBmb3IgcG9pbnRzIHRoYXQgc3BlY2lmeSBleHRyYXBhZDogdHJ1ZVxuICAgIHZhciBleHRyYXBwYWQgPSBheC5fbGVuZ3RoIC8gMjA7XG5cbiAgICAvLyBkb21haW4tY29uc3RyYWluZWQgYXhlczogYmFzZSBleHRyYXBwYWQgb24gdGhlIHVuY29uc3RyYWluZWRcbiAgICAvLyBkb21haW4gc28gaXQncyBjb25zaXN0ZW50IGFzIHRoZSBkb21haW4gY2hhbmdlc1xuICAgIGlmKChheC5jb25zdHJhaW4gPT09ICdkb21haW4nKSAmJiBheC5faW5wdXREb21haW4pIHtcbiAgICAgICAgZXh0cmFwcGFkICo9IChheC5faW5wdXREb21haW5bMV0gLSBheC5faW5wdXREb21haW5bMF0pIC9cbiAgICAgICAgICAgIChheC5kb21haW5bMV0gLSBheC5kb21haW5bMF0pO1xuICAgIH1cblxuICAgIHJldHVybiBmdW5jdGlvbiBnZXRQYWQocHQpIHsgcmV0dXJuIHB0LnBhZCArIChwdC5leHRyYXBhZCA/IGV4dHJhcHBhZCA6IDApOyB9O1xufVxuXG5mdW5jdGlvbiBjb25jYXRFeHRyZW1lcyhnZCwgYXgpIHtcbiAgICB2YXIgYXhJZCA9IGF4Ll9pZDtcbiAgICB2YXIgZnVsbERhdGEgPSBnZC5fZnVsbERhdGE7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgbWluQXJyYXkgPSBbXTtcbiAgICB2YXIgbWF4QXJyYXkgPSBbXTtcbiAgICB2YXIgaSwgaiwgZDtcblxuICAgIGZ1bmN0aW9uIF9jb25jYXQoY29udCwgaW5kaWNlcykge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgaXRlbSA9IGNvbnRbaW5kaWNlc1tpXV07XG4gICAgICAgICAgICB2YXIgZXh0cmVtZXMgPSAoaXRlbS5fZXh0cmVtZXMgfHwge30pW2F4SWRdO1xuICAgICAgICAgICAgaWYoaXRlbS52aXNpYmxlID09PSB0cnVlICYmIGV4dHJlbWVzKSB7XG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgZXh0cmVtZXMubWluLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGQgPSBleHRyZW1lcy5taW5bal07XG4gICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlTWluQXJyYXkobWluQXJyYXksIGQudmFsLCBkLnBhZCwge2V4dHJhcGFkOiBkLmV4dHJhcGFkfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGV4dHJlbWVzLm1heC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBkID0gZXh0cmVtZXMubWF4W2pdO1xuICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZU1heEFycmF5KG1heEFycmF5LCBkLnZhbCwgZC5wYWQsIHtleHRyYXBhZDogZC5leHRyYXBhZH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIF9jb25jYXQoZnVsbERhdGEsIGF4Ll90cmFjZUluZGljZXMpO1xuICAgIF9jb25jYXQoZnVsbExheW91dC5hbm5vdGF0aW9ucyB8fCBbXSwgYXguX2FubkluZGljZXMgfHwgW10pO1xuICAgIF9jb25jYXQoZnVsbExheW91dC5zaGFwZXMgfHwgW10sIGF4Ll9zaGFwZUluZGljZXMgfHwgW10pO1xuXG4gICAgcmV0dXJuIHttaW46IG1pbkFycmF5LCBtYXg6IG1heEFycmF5fTtcbn1cblxuZnVuY3Rpb24gZG9BdXRvUmFuZ2UoZ2QsIGF4KSB7XG4gICAgYXguc2V0U2NhbGUoKTtcblxuICAgIGlmKGF4LmF1dG9yYW5nZSkge1xuICAgICAgICBheC5yYW5nZSA9IGdldEF1dG9SYW5nZShnZCwgYXgpO1xuXG4gICAgICAgIGF4Ll9yID0gYXgucmFuZ2Uuc2xpY2UoKTtcbiAgICAgICAgYXguX3JsID0gTGliLnNpbXBsZU1hcChheC5fciwgYXgucjJsKTtcblxuICAgICAgICAvLyBkb0F1dG9SYW5nZSB3aWxsIGdldCBjYWxsZWQgb24gZnVsbExheW91dCxcbiAgICAgICAgLy8gYnV0IHdlIHdhbnQgdG8gcmVwb3J0IGl0cyByZXN1bHRzIGJhY2sgdG8gbGF5b3V0XG5cbiAgICAgICAgdmFyIGF4SW4gPSBheC5faW5wdXQ7XG5cbiAgICAgICAgLy8gYmVmb3JlIHdlIGVkaXQgX2lucHV0LCBzdG9yZSBwcmVHVUkgdmFsdWVzXG4gICAgICAgIHZhciBlZGl0cyA9IHt9O1xuICAgICAgICBlZGl0c1theC5fYXR0ciArICcucmFuZ2UnXSA9IGF4LnJhbmdlO1xuICAgICAgICBlZGl0c1theC5fYXR0ciArICcuYXV0b3JhbmdlJ10gPSBheC5hdXRvcmFuZ2U7XG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19zdG9yZURpcmVjdEdVSUVkaXQnLCBnZC5sYXlvdXQsIGdkLl9mdWxsTGF5b3V0Ll9wcmVHVUksIGVkaXRzKTtcblxuICAgICAgICBheEluLnJhbmdlID0gYXgucmFuZ2Uuc2xpY2UoKTtcbiAgICAgICAgYXhJbi5hdXRvcmFuZ2UgPSBheC5hdXRvcmFuZ2U7XG4gICAgfVxuXG4gICAgdmFyIGFuY2hvckF4ID0gYXguX2FuY2hvckF4aXM7XG5cbiAgICBpZihhbmNob3JBeCAmJiBhbmNob3JBeC5yYW5nZXNsaWRlcikge1xuICAgICAgICB2YXIgYXhlUmFuZ2VPcHRzID0gYW5jaG9yQXgucmFuZ2VzbGlkZXJbYXguX25hbWVdO1xuICAgICAgICBpZihheGVSYW5nZU9wdHMpIHtcbiAgICAgICAgICAgIGlmKGF4ZVJhbmdlT3B0cy5yYW5nZW1vZGUgPT09ICdhdXRvJykge1xuICAgICAgICAgICAgICAgIGF4ZVJhbmdlT3B0cy5yYW5nZSA9IGdldEF1dG9SYW5nZShnZCwgYXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGFuY2hvckF4Ll9pbnB1dC5yYW5nZXNsaWRlcltheC5fbmFtZV0gPSBMaWIuZXh0ZW5kRmxhdCh7fSwgYXhlUmFuZ2VPcHRzKTtcbiAgICB9XG59XG5cbi8qKlxuICogZmluZEV4dHJlbWVzXG4gKlxuICogRmluZCBtaW4vbWF4IGV4dHJlbWVzIG9mIGFuIGFycmF5IG9mIGNvb3JkaW5hdGVzIG9uIGEgZ2l2ZW4gYXhpcy5cbiAqXG4gKiBOb3RlIHRoYXQgZmluZEV4dHJlbWVzIGlzIGNhbGxlZCBkdXJpbmcgYGNhbGNgLCB3aGVuIHdlIGRvbid0IHlldCBrbm93IHRoZSBheGlzXG4gKiBsZW5ndGg7IGFsbCB0aGUgaW5wdXRzIHNob3VsZCBiZSBiYXNlZCBzb2xlbHkgb24gdGhlIHRyYWNlIGRhdGEsIG5vdGhpbmdcbiAqIGFib3V0IHRoZSBheGlzIGxheW91dC5cbiAqXG4gKiBOb3RlIHRoYXQgYHBwYWRgIGFuZCBgdnBhZGAgYXMgd2VsbCBhcyB0aGVpciBhc3ltbWV0cmljIHZhcmlhbnRzIHJlZmVyIHRvXG4gKiB0aGUgYmVmb3JlIGFuZCBhZnRlciBwYWRkaW5nIG9mIHRoZSBwYXNzZWQgYGRhdGFgIGFycmF5LCBub3QgdG8gdGhlIHdob2xlIGF4aXMuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGF4OiBmdWxsIGF4aXMgb2JqZWN0XG4gKiAgIHJlbGllcyBvblxuICogICAtIGF4LnR5cGVcbiAqICAgLSBheC5fbSAoanVzdCBpdHMgc2lnbilcbiAqICAgLSBheC5kMmxcbiAqIEBwYXJhbSB7YXJyYXl9IGRhdGE6XG4gKiAgYXJyYXkgb2YgbnVtYmVycyAoaS5lLiBhbHJlYWR5IHJ1biB0aG91Z2ggYXguZDJjKVxuICogQHBhcmFtIHtvYmplY3R9IG9wdHM6XG4gKiAgYXZhaWxhYmxlIGtleXMgYXJlOlxuICogICAgICB2cGFkOiAobnVtYmVyIG9yIG51bWJlciBhcnJheSkgcGFkIHZhbHVlcyAoZGF0YSB2YWx1ZSArLXZwYWQpXG4gKiAgICAgIHBwYWQ6IChudW1iZXIgb3IgbnVtYmVyIGFycmF5KSBwYWQgcGl4ZWxzIChwaXhlbCBsb2NhdGlvbiArLXBwYWQpXG4gKiAgICAgIHBwYWRwbHVzLCBwcGFkbWludXMsIHZwYWRwbHVzLCB2cGFkbWludXM6XG4gKiAgICAgICAgICBzZXBhcmF0ZSBwYWRkaW5nIGZvciBlYWNoIHNpZGUsIG92ZXJyaWRlcyBzeW1tZXRyaWNcbiAqICAgICAgcGFkZGVkOiAoYm9vbGVhbikgYWRkIDUlIHBhZGRpbmcgdG8gYm90aCBlbmRzXG4gKiAgICAgICAgICAodW5sZXNzIG9uZSBlbmQgaXMgb3ZlcnJpZGRlbiBieSB0b3plcm8pXG4gKiAgICAgIHRvemVybzogKGJvb2xlYW4pIG1ha2Ugc3VyZSB0byBpbmNsdWRlIHplcm8gaWYgYXhpcyBpcyBsaW5lYXIsXG4gKiAgICAgICAgICBhbmQgbWFrZSBpdCBhIHRpZ2h0IGJvdW5kIGlmIHBvc3NpYmxlXG4gKlxuICogQHJldHVybiB7b2JqZWN0fVxuICogIC0gbWluIHthcnJheSBvZiBvYmplY3RzfVxuICogIC0gbWF4IHthcnJheSBvZiBvYmplY3RzfVxuICogIGVhY2ggb2JqZWN0IGl0ZW0gaGFzIGZpZWxkczpcbiAqICAgIC0gdmFsIHtudW1iZXJ9XG4gKiAgICAtIHBhZCB7bnVtYmVyfVxuICogICAgLSBleHRyYXBwYWQge251bWJlcn1cbiAqICAtIG9wdHMge29iamVjdH06IGEgcmVmIHRvIHRoZSBwYXNzZWQgXCJvcHRpb25zXCIgb2JqZWN0XG4gKi9cbmZ1bmN0aW9uIGZpbmRFeHRyZW1lcyhheCwgZGF0YSwgb3B0cykge1xuICAgIGlmKCFvcHRzKSBvcHRzID0ge307XG4gICAgaWYoIWF4Ll9tKSBheC5zZXRTY2FsZSgpO1xuXG4gICAgdmFyIG1pbkFycmF5ID0gW107XG4gICAgdmFyIG1heEFycmF5ID0gW107XG5cbiAgICB2YXIgbGVuID0gZGF0YS5sZW5ndGg7XG4gICAgdmFyIGV4dHJhcGFkID0gb3B0cy5wYWRkZWQgfHwgZmFsc2U7XG4gICAgdmFyIHRvemVybyA9IG9wdHMudG96ZXJvICYmIChheC50eXBlID09PSAnbGluZWFyJyB8fCBheC50eXBlID09PSAnLScpO1xuICAgIHZhciBpc0xvZyA9IGF4LnR5cGUgPT09ICdsb2cnO1xuICAgIHZhciBoYXNBcnJheU9wdGlvbiA9IGZhbHNlO1xuICAgIHZhciBpLCB2LCBkaSwgZG1pbiwgZG1heCwgcHBhZGlwbHVzLCBwcGFkaW1pbnVzLCB2bWluLCB2bWF4O1xuXG4gICAgZnVuY3Rpb24gbWFrZVBhZEFjY2Vzc29yKGl0ZW0pIHtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShpdGVtKSkge1xuICAgICAgICAgICAgaGFzQXJyYXlPcHRpb24gPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGkpIHsgcmV0dXJuIE1hdGgubWF4KE51bWJlcihpdGVtW2ldfHwwKSwgMCk7IH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgdiA9IE1hdGgubWF4KE51bWJlcihpdGVtfHwwKSwgMCk7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7IHJldHVybiB2OyB9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHBwYWRwbHVzID0gbWFrZVBhZEFjY2Vzc29yKChheC5fbSA+IDAgP1xuICAgICAgICBvcHRzLnBwYWRwbHVzIDogb3B0cy5wcGFkbWludXMpIHx8IG9wdHMucHBhZCB8fCAwKTtcbiAgICB2YXIgcHBhZG1pbnVzID0gbWFrZVBhZEFjY2Vzc29yKChheC5fbSA+IDAgP1xuICAgICAgICBvcHRzLnBwYWRtaW51cyA6IG9wdHMucHBhZHBsdXMpIHx8IG9wdHMucHBhZCB8fCAwKTtcbiAgICB2YXIgdnBhZHBsdXMgPSBtYWtlUGFkQWNjZXNzb3Iob3B0cy52cGFkcGx1cyB8fCBvcHRzLnZwYWQpO1xuICAgIHZhciB2cGFkbWludXMgPSBtYWtlUGFkQWNjZXNzb3Iob3B0cy52cGFkbWludXMgfHwgb3B0cy52cGFkKTtcblxuICAgIGlmKCFoYXNBcnJheU9wdGlvbikge1xuICAgICAgICAvLyB3aXRoIG5vIGFycmF5cyBvdGhlciB0aGFuIGBkYXRhYCB3ZSBkb24ndCBuZWVkIHRvIGNvbnNpZGVyXG4gICAgICAgIC8vIGV2ZXJ5IHBvaW50LCBvbmx5IHRoZSBleHRyZW1lIGRhdGEgcG9pbnRzXG4gICAgICAgIHZtaW4gPSBJbmZpbml0eTtcbiAgICAgICAgdm1heCA9IC1JbmZpbml0eTtcblxuICAgICAgICBpZihpc0xvZykge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2ID0gZGF0YVtpXTtcbiAgICAgICAgICAgICAgICAvLyBkYXRhIGlzIG5vdCBsaW5lYXJpemVkIHlldCBzbyB3ZSBzdGlsbCBoYXZlIHRvIGZpbHRlciBvdXQgbmVnYXRpdmUgbG9nc1xuICAgICAgICAgICAgICAgIGlmKHYgPCB2bWluICYmIHYgPiAwKSB2bWluID0gdjtcbiAgICAgICAgICAgICAgICBpZih2ID4gdm1heCAmJiB2IDwgRlBfU0FGRSkgdm1heCA9IHY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIHYgPSBkYXRhW2ldO1xuICAgICAgICAgICAgICAgIGlmKHYgPCB2bWluICYmIHYgPiAtRlBfU0FGRSkgdm1pbiA9IHY7XG4gICAgICAgICAgICAgICAgaWYodiA+IHZtYXggJiYgdiA8IEZQX1NBRkUpIHZtYXggPSB2O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZGF0YSA9IFt2bWluLCB2bWF4XTtcbiAgICAgICAgbGVuID0gMjtcbiAgICB9XG5cbiAgICB2YXIgY29sbGFwc2VPcHRzID0ge3RvemVybzogdG96ZXJvLCBleHRyYXBhZDogZXh0cmFwYWR9O1xuXG4gICAgZnVuY3Rpb24gYWRkSXRlbShpKSB7XG4gICAgICAgIGRpID0gZGF0YVtpXTtcbiAgICAgICAgaWYoIWlzTnVtZXJpYyhkaSkpIHJldHVybjtcbiAgICAgICAgcHBhZGlwbHVzID0gcHBhZHBsdXMoaSk7XG4gICAgICAgIHBwYWRpbWludXMgPSBwcGFkbWludXMoaSk7XG4gICAgICAgIHZtaW4gPSBkaSAtIHZwYWRtaW51cyhpKTtcbiAgICAgICAgdm1heCA9IGRpICsgdnBhZHBsdXMoaSk7XG4gICAgICAgIC8vIHNwZWNpYWwgY2FzZSBmb3IgbG9nIGF4ZXM6IGlmIHZwYWQgbWFrZXMgdGhpcyBvYmplY3Qgc3BhblxuICAgICAgICAvLyBtb3JlIHRoYW4gYW4gb3JkZXIgb2YgbWFnLCBjbGlwIGl0IHRvIG9uZSBvcmRlci4gVGhpcyBpcyBzb1xuICAgICAgICAvLyB3ZSBkb24ndCBoYXZlIG5vbi1wb3NpdGl2ZSBlcnJvcnMgb3IgYWJzdXJkbHkgbGFyZ2UgbG93ZXJcbiAgICAgICAgLy8gcmFuZ2UgZHVlIHRvIHJvdW5kaW5nIGVycm9yc1xuICAgICAgICBpZihpc0xvZyAmJiB2bWluIDwgdm1heCAvIDEwKSB2bWluID0gdm1heCAvIDEwO1xuXG4gICAgICAgIGRtaW4gPSBheC5jMmwodm1pbik7XG4gICAgICAgIGRtYXggPSBheC5jMmwodm1heCk7XG5cbiAgICAgICAgaWYodG96ZXJvKSB7XG4gICAgICAgICAgICBkbWluID0gTWF0aC5taW4oMCwgZG1pbik7XG4gICAgICAgICAgICBkbWF4ID0gTWF0aC5tYXgoMCwgZG1heCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoZ29vZE51bWJlcihkbWluKSkge1xuICAgICAgICAgICAgY29sbGFwc2VNaW5BcnJheShtaW5BcnJheSwgZG1pbiwgcHBhZGltaW51cywgY29sbGFwc2VPcHRzKTtcbiAgICAgICAgfVxuICAgICAgICBpZihnb29kTnVtYmVyKGRtYXgpKSB7XG4gICAgICAgICAgICBjb2xsYXBzZU1heEFycmF5KG1heEFycmF5LCBkbWF4LCBwcGFkaXBsdXMsIGNvbGxhcHNlT3B0cyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBGb3IgZWZmaWNpZW5jeSBjb3ZlcmluZyBtb25vdG9uaWMgb3IgbmVhci1tb25vdG9uaWMgZGF0YSxcbiAgICAvLyBjaGVjayBhIGZldyBwb2ludHMgYXQgYm90aCBlbmRzIGZpcnN0IGFuZCB0aGVuIHN3ZWVwXG4gICAgLy8gdGhyb3VnaCB0aGUgbWlkZGxlXG4gICAgdmFyIGlNYXggPSBNYXRoLm1pbig2LCBsZW4pO1xuICAgIGZvcihpID0gMDsgaSA8IGlNYXg7IGkrKykgYWRkSXRlbShpKTtcbiAgICBmb3IoaSA9IGxlbiAtIDE7IGkgPj0gaU1heDsgaS0tKSBhZGRJdGVtKGkpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgbWluOiBtaW5BcnJheSxcbiAgICAgICAgbWF4OiBtYXhBcnJheSxcbiAgICAgICAgb3B0czogb3B0c1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGNvbGxhcHNlTWluQXJyYXkoYXJyYXksIG5ld1ZhbCwgbmV3UGFkLCBvcHRzKSB7XG4gICAgY29sbGFwc2VBcnJheShhcnJheSwgbmV3VmFsLCBuZXdQYWQsIG9wdHMsIGxlc3NPckVxdWFsKTtcbn1cblxuZnVuY3Rpb24gY29sbGFwc2VNYXhBcnJheShhcnJheSwgbmV3VmFsLCBuZXdQYWQsIG9wdHMpIHtcbiAgICBjb2xsYXBzZUFycmF5KGFycmF5LCBuZXdWYWwsIG5ld1BhZCwgb3B0cywgZ3JlYXRlck9yRXF1YWwpO1xufVxuXG4vKipcbiAqIGNvbGxhcHNlQXJyYXlcbiAqXG4gKiBUYWtlcyBpdGVtcyBmcm9tICdhcnJheScgYW5kIGNvbXBhcmVzIHRoZW0gdG8gJ25ld1ZhbCcsICduZXdQYWQnLlxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGFycmF5OlxuICogIGN1cnJlbnQgc2V0IG9mIG1pbiBvciBtYXggZXh0cmVtZXNcbiAqIEBwYXJhbSB7bnVtYmVyfSBuZXdWYWw6XG4gKiAgbmV3IHZhbHVlIHRvIGNvbXBhcmUgYWdhaW5zdFxuICogQHBhcmFtIHtudW1iZXJ9IG5ld1BhZDpcbiAqICBwYWQgdmFsdWUgYXNzb2NpYXRlZCB3aXRoICduZXdWYWwnXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0czpcbiAqICAtIHRvemVybyB7Ym9vbGVhbn1cbiAqICAtIGV4dHJhcGFkIHtudW1iZXJ9XG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBhdExlYXN0QXNFeHRyZW1lOlxuICogIGNvbXBhcmlzb24gZnVuY3Rpb24sIHVzZVxuICogIC0gbGVzc09yRXF1YWwgZm9yIG1pbiAnYXJyYXknIGFuZFxuICogIC0gZ3JlYXRlck9yRXF1YWwgZm9yIG1heCAnYXJyYXknXG4gKlxuICogSW4gcHJhY3RpY2UsICdhcnJheScgaXMgZWl0aGVyXG4gKiAgLSAnZXh0cmVtZXNbYXguX2lkXS5taW4nIG9yXG4gKiAgLSAnZXh0cmVtZXNbYXguX2lkXS5tYXhcbiAqICBmb3VuZCBpbiB0cmFjZXMgYW5kIGxheW91dCBpdGVtcyB0aGF0IGFmZmVjdCBhdXRvcmFuZ2UuXG4gKlxuICogU2luY2Ugd2UgZG9uJ3QgeWV0IGtub3cgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHBpeGVscyBhbmQgdmFsdWVzXG4gKiAodGhhdCdzIHdoYXQgd2UncmUgdHJ5aW5nIHRvIGZpZ3VyZSBvdXQhKSBBTkQgd2UgZG9uJ3QgeWV0IGtub3cgaG93XG4gKiBtYW55IHBpeGVscyBgZXh0cmFwYWRgIHJlcHJlc2VudHMgKGl0J3MgZ29pbmcgdG8gYmUgNSUgb2YgdGhlIGxlbmd0aCxcbiAqIGJ1dCB3ZSBkb24ndCB3YW50IHRvIGhhdmUgdG8gcmVkbyBjYWxjIGp1c3QgYmVjYXVzZSBsZW5ndGggY2hhbmdlZClcbiAqIHR3byBwb2ludCBtdXN0IHNhdGlzZnkgdGhyZWUgY3JpdGVyaWEgc2ltdWx0YW5lb3VzbHkgZm9yIG9uZSB0byBzdXBlcnNlZGUgdGhlIG90aGVyOlxuICogIC0gYXQgbGVhc3QgYXMgZXh0cmVtZSBhIGB2YWxgXG4gKiAgLSBhdCBsZWFzdCBhcyBiaWcgYSBgcGFkYFxuICogIC0gYW4gdW5wYWRkZWQgcG9pbnQgY2Fubm90IHN1cGVyc2VkZSBhIHBhZGRlZCBwb2ludCwgYnV0IGFueSBvdGhlciBjb21iaW5hdGlvbiBjYW5cbiAqXG4gKiBUaGVuOlxuICogLSBJZiB0aGUgaXRlbSBzdXBlcnNlZGVzIHRoZSBuZXcgcG9pbnQsIHNldCBpbmNsdWRlVGhpcyBmYWxzZVxuICogLSBJZiB0aGUgbmV3IHB0IHN1cGVyc2VkZXMgdGhlIGl0ZW0sIGRlbGV0ZSBpdCBmcm9tICdhcnJheSdcbiAqL1xuZnVuY3Rpb24gY29sbGFwc2VBcnJheShhcnJheSwgbmV3VmFsLCBuZXdQYWQsIG9wdHMsIGF0TGVhc3RBc0V4dHJlbWUpIHtcbiAgICB2YXIgdG96ZXJvID0gb3B0cy50b3plcm87XG4gICAgdmFyIGV4dHJhcGFkID0gb3B0cy5leHRyYXBhZDtcbiAgICB2YXIgaW5jbHVkZVRoaXMgPSB0cnVlO1xuXG4gICAgZm9yKHZhciBqID0gMDsgaiA8IGFycmF5Lmxlbmd0aCAmJiBpbmNsdWRlVGhpczsgaisrKSB7XG4gICAgICAgIHZhciB2ID0gYXJyYXlbal07XG4gICAgICAgIGlmKGF0TGVhc3RBc0V4dHJlbWUodi52YWwsIG5ld1ZhbCkgJiYgdi5wYWQgPj0gbmV3UGFkICYmICh2LmV4dHJhcGFkIHx8ICFleHRyYXBhZCkpIHtcbiAgICAgICAgICAgIGluY2x1ZGVUaGlzID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfSBlbHNlIGlmKGF0TGVhc3RBc0V4dHJlbWUobmV3VmFsLCB2LnZhbCkgJiYgdi5wYWQgPD0gbmV3UGFkICYmIChleHRyYXBhZCB8fCAhdi5leHRyYXBhZCkpIHtcbiAgICAgICAgICAgIGFycmF5LnNwbGljZShqLCAxKTtcbiAgICAgICAgICAgIGotLTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZihpbmNsdWRlVGhpcykge1xuICAgICAgICB2YXIgY2xpcEF0WmVybyA9ICh0b3plcm8gJiYgbmV3VmFsID09PSAwKTtcbiAgICAgICAgYXJyYXkucHVzaCh7XG4gICAgICAgICAgICB2YWw6IG5ld1ZhbCxcbiAgICAgICAgICAgIHBhZDogY2xpcEF0WmVybyA/IDAgOiBuZXdQYWQsXG4gICAgICAgICAgICBleHRyYXBhZDogY2xpcEF0WmVybyA/IGZhbHNlIDogZXh0cmFwYWRcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG4vLyBJbiBvcmRlciB0byBzdG9wIG92ZXJmbG93IGVycm9ycywgZG9uJ3QgY29uc2lkZXIgcG9pbnRzXG4vLyB0b28gY2xvc2UgdG8gdGhlIGxpbWl0cyBvZiBqcyBmbG9hdGluZyBwb2ludFxuZnVuY3Rpb24gZ29vZE51bWJlcih2KSB7XG4gICAgcmV0dXJuIGlzTnVtZXJpYyh2KSAmJiBNYXRoLmFicyh2KSA8IEZQX1NBRkU7XG59XG5cbmZ1bmN0aW9uIGxlc3NPckVxdWFsKHYwLCB2MSkgeyByZXR1cm4gdjAgPD0gdjE7IH1cbmZ1bmN0aW9uIGdyZWF0ZXJPckVxdWFsKHYwLCB2MSkgeyByZXR1cm4gdjAgPj0gdjE7IH1cblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDc2NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIFBsb3RzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvcGxvdHMnKTtcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBzdmdUZXh0VXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcbnZhciBUaXRsZXMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL3RpdGxlcycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcblxudmFyIGF4QXR0cnMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgY2xlYW5UaWNrcyA9IF9kZXJlcV8oJy4vY2xlYW5fdGlja3MnKTtcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKTtcbnZhciBPTkVBVkdZRUFSID0gY29uc3RhbnRzLk9ORUFWR1lFQVI7XG52YXIgT05FQVZHTU9OVEggPSBjb25zdGFudHMuT05FQVZHTU9OVEg7XG52YXIgT05FREFZID0gY29uc3RhbnRzLk9ORURBWTtcbnZhciBPTkVIT1VSID0gY29uc3RhbnRzLk9ORUhPVVI7XG52YXIgT05FTUlOID0gY29uc3RhbnRzLk9ORU1JTjtcbnZhciBPTkVTRUMgPSBjb25zdGFudHMuT05FU0VDO1xudmFyIE1JTlVTX1NJR04gPSBjb25zdGFudHMuTUlOVVNfU0lHTjtcbnZhciBCQUROVU0gPSBjb25zdGFudHMuQkFETlVNO1xuXG52YXIgTUlEX1NISUZUID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudCcpLk1JRF9TSElGVDtcbnZhciBMSU5FX1NQQUNJTkcgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50JykuTElORV9TUEFDSU5HO1xuXG52YXIgYXhlcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbmF4ZXMuc2V0Q29udmVydCA9IF9kZXJlcV8oJy4vc2V0X2NvbnZlcnQnKTtcbnZhciBhdXRvVHlwZSA9IF9kZXJlcV8oJy4vYXhpc19hdXRvdHlwZScpO1xuXG52YXIgYXhpc0lkcyA9IF9kZXJlcV8oJy4vYXhpc19pZHMnKTtcbmF4ZXMuaWQybmFtZSA9IGF4aXNJZHMuaWQybmFtZTtcbmF4ZXMubmFtZTJpZCA9IGF4aXNJZHMubmFtZTJpZDtcbmF4ZXMuY2xlYW5JZCA9IGF4aXNJZHMuY2xlYW5JZDtcbmF4ZXMubGlzdCA9IGF4aXNJZHMubGlzdDtcbmF4ZXMubGlzdElkcyA9IGF4aXNJZHMubGlzdElkcztcbmF4ZXMuZ2V0RnJvbUlkID0gYXhpc0lkcy5nZXRGcm9tSWQ7XG5heGVzLmdldEZyb21UcmFjZSA9IGF4aXNJZHMuZ2V0RnJvbVRyYWNlO1xuXG52YXIgYXV0b3JhbmdlID0gX2RlcmVxXygnLi9hdXRvcmFuZ2UnKTtcbmF4ZXMuZ2V0QXV0b1JhbmdlID0gYXV0b3JhbmdlLmdldEF1dG9SYW5nZTtcbmF4ZXMuZmluZEV4dHJlbWVzID0gYXV0b3JhbmdlLmZpbmRFeHRyZW1lcztcblxuLypcbiAqIGZpbmQgdGhlIGxpc3Qgb2YgcG9zc2libGUgYXhlcyB0byByZWZlcmVuY2Ugd2l0aCBhbiB4cmVmIG9yIHlyZWYgYXR0cmlidXRlXG4gKiBhbmQgY29lcmNlIGl0IHRvIHRoYXQgbGlzdFxuICpcbiAqIGF0dHI6IHRoZSBhdHRyaWJ1dGUgd2UncmUgZ2VuZXJhdGluZyBhIHJlZmVyZW5jZSBmb3IuIFNob3VsZCBlbmQgaW4gJ3gnIG9yICd5J1xuICogICAgIGJ1dCBjYW4gYmUgcHJlZml4ZWQsIGxpa2UgJ2F4JyBmb3IgYW5ub3RhdGlvbidzIGFycm93IHhcbiAqIGRmbHQ6IHRoZSBkZWZhdWx0IHRvIGNvZXJjZSB0bywgb3IgYmxhbmsgdG8gdXNlIHRoZSBmaXJzdCBheGlzIChmYWxsaW5nIGJhY2sgb25cbiAqICAgICBleHRyYU9wdGlvbiBpZiB0aGVyZSBpcyBubyBheGlzKVxuICogZXh0cmFPcHRpb246IGFzaWRlIGZyb20gZXhpc3RpbmcgYXhlcyB3aXRoIHRoaXMgbGV0dGVyLCB3aGF0IG5vbi1heGlzIHZhbHVlIGlzIGFsbG93ZWQ/XG4gKiAgICAgT25seSByZXF1aXJlZCBpZiBpdCdzIGRpZmZlcmVudCBmcm9tIGBkZmx0YFxuICovXG5heGVzLmNvZXJjZVJlZiA9IGZ1bmN0aW9uKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGdkLCBhdHRyLCBkZmx0LCBleHRyYU9wdGlvbikge1xuICAgIHZhciBheExldHRlciA9IGF0dHIuY2hhckF0KGF0dHIubGVuZ3RoIC0gMSk7XG4gICAgdmFyIGF4bGlzdCA9IGdkLl9mdWxsTGF5b3V0Ll9zdWJwbG90c1theExldHRlciArICdheGlzJ107XG4gICAgdmFyIHJlZkF0dHIgPSBhdHRyICsgJ3JlZic7XG4gICAgdmFyIGF0dHJEZWYgPSB7fTtcblxuICAgIGlmKCFkZmx0KSBkZmx0ID0gYXhsaXN0WzBdIHx8IGV4dHJhT3B0aW9uO1xuICAgIGlmKCFleHRyYU9wdGlvbikgZXh0cmFPcHRpb24gPSBkZmx0O1xuXG4gICAgLy8gZGF0YS1yZWYgYW5ub3RhdGlvbnMgYXJlIG5vdCBzdXBwb3J0ZWQgaW4gZ2wyZCB5ZXRcblxuICAgIGF0dHJEZWZbcmVmQXR0cl0gPSB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBheGxpc3QuY29uY2F0KGV4dHJhT3B0aW9uID8gW2V4dHJhT3B0aW9uXSA6IFtdKSxcbiAgICAgICAgZGZsdDogZGZsdFxuICAgIH07XG5cbiAgICAvLyB4cmVmLCB5cmVmXG4gICAgcmV0dXJuIExpYi5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgYXR0ckRlZiwgcmVmQXR0cik7XG59O1xuXG4vKlxuICogY29lcmNlIHBvc2l0aW9uIGF0dHJpYnV0ZXMgKHJhbmdlLXR5cGUpIHRoYXQgY2FuIGJlIGVpdGhlciBvbiBheGVzIG9yIGFic29sdXRlXG4gKiAocGFwZXIgb3IgcGl4ZWwpIHJlZmVyZW5jZWQuIFRoZSBiaWdnZXN0IGNvbXBsaWNhdGlvbiBoZXJlIGlzIHRoYXQgd2UgZG9uJ3Qga25vd1xuICogYmVmb3JlIGxvb2tpbmcgYXQgdGhlIGF4aXMgd2hldGhlciB0aGUgdmFsdWUgbXVzdCBiZSBhIG51bWJlciBvciBub3QgKGl0IG1heSBiZVxuICogYSBkYXRlIHN0cmluZyksIHNvIHdlIGNhbid0IHVzZSB0aGUgcmVndWxhciB2YWxUeXBlPSdudW1iZXInIG1hY2hpbmVyeVxuICpcbiAqIGF4UmVmIChzdHJpbmcpOiB0aGUgYXhpcyB0aGlzIHBvc2l0aW9uIGlzIHJlZmVyZW5jZWQgdG8sIG9yOlxuICogICAgIHBhcGVyOiBmcmFjdGlvbiBvZiB0aGUgcGxvdCBhcmVhXG4gKiAgICAgcGl4ZWw6IHBpeGVscyByZWxhdGl2ZSB0byBzb21lIHN0YXJ0aW5nIHBvc2l0aW9uXG4gKiBhdHRyIChzdHJpbmcpOiB0aGUgYXR0cmlidXRlIGluIGNvbnRhaW5lck91dCB3ZSBhcmUgY29lcmNpbmdcbiAqIGRmbHQgKG51bWJlcik6IHRoZSBkZWZhdWx0IHBvc2l0aW9uLCBhcyBhIGZyYWN0aW9uIG9yIHBpeGVscy4gSWYgdGhlIGF0dHJpYnV0ZVxuICogICAgIGlzIHRvIGJlIGF4aXMtcmVmZXJlbmNlZCwgdGhpcyB3aWxsIGJlIGNvbnZlcnRlZCB0byBhbiBheGlzIGRhdGEgdmFsdWVcbiAqXG4gKiBBbHNvIGNsZWFucyB0aGUgdmFsdWVzLCBzaW5jZSB0aGUgYXR0cmlidXRlIGRlZmluaXRpb24gaXRzZWxmIGhhcyB0byBzYXlcbiAqIHZhbFR5cGU6ICdhbnknIHRvIGhhbmRsZSBkYXRlIGF4ZXMuIFRoaXMgYWxsb3dzIHVzIHRvIGFjY2VwdDpcbiAqIC0gZm9yIGNhdGVnb3J5IGF4ZXM6IGNhdGVnb3J5IG5hbWVzLCBhbmQgY29udmVydCB0aGVtIGhlcmUgaW50byBzZXJpYWwgbnVtYmVycy5cbiAqICAgTm90ZSB0aGF0IHRoaXMgd2lsbCBOT1Qgd29yayBmb3IgYXhpcyByYW5nZSBlbmRwb2ludHMsIGJlY2F1c2Ugd2UgZG9uJ3Qga25vd1xuICogICB0aGUgY2F0ZWdvcnkgbGlzdCB5ZXQgKGl0J3Mgc2V0IGJ5IGF4Lm1ha2VDYWxjZGF0YSBkdXJpbmcgY2FsYylcbiAqICAgYnV0IGl0IHdvcmtzIGZvciBjb21wb25lbnQgKG5vdGUsIHNoYXBlLCBpbWFnZXMpIHBvc2l0aW9ucy5cbiAqIC0gZm9yIGRhdGUgYXhlczogSlMgRGF0ZXMgb3IgbWlsbGlzZWNvbmRzLCBhbmQgY29udmVydCB0byBkYXRlIHN0cmluZ3NcbiAqIC0gZm9yIG90aGVyIHR5cGVzOiBjb2VyY2UgdGhlbSB0byBudW1iZXJzXG4gKi9cbmF4ZXMuY29lcmNlUG9zaXRpb24gPSBmdW5jdGlvbihjb250YWluZXJPdXQsIGdkLCBjb2VyY2UsIGF4UmVmLCBhdHRyLCBkZmx0KSB7XG4gICAgdmFyIGNsZWFuUG9zLCBwb3M7XG5cbiAgICBpZihheFJlZiA9PT0gJ3BhcGVyJyB8fCBheFJlZiA9PT0gJ3BpeGVsJykge1xuICAgICAgICBjbGVhblBvcyA9IExpYi5lbnN1cmVOdW1iZXI7XG4gICAgICAgIHBvcyA9IGNvZXJjZShhdHRyLCBkZmx0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgYXggPSBheGVzLmdldEZyb21JZChnZCwgYXhSZWYpO1xuICAgICAgICBkZmx0ID0gYXguZnJhY3Rpb24ycihkZmx0KTtcbiAgICAgICAgcG9zID0gY29lcmNlKGF0dHIsIGRmbHQpO1xuICAgICAgICBjbGVhblBvcyA9IGF4LmNsZWFuUG9zO1xuICAgIH1cblxuICAgIGNvbnRhaW5lck91dFthdHRyXSA9IGNsZWFuUG9zKHBvcyk7XG59O1xuXG5heGVzLmNsZWFuUG9zaXRpb24gPSBmdW5jdGlvbihwb3MsIGdkLCBheFJlZikge1xuICAgIHZhciBjbGVhblBvcyA9IChheFJlZiA9PT0gJ3BhcGVyJyB8fCBheFJlZiA9PT0gJ3BpeGVsJykgP1xuICAgICAgICBMaWIuZW5zdXJlTnVtYmVyIDpcbiAgICAgICAgYXhlcy5nZXRGcm9tSWQoZ2QsIGF4UmVmKS5jbGVhblBvcztcblxuICAgIHJldHVybiBjbGVhblBvcyhwb3MpO1xufTtcblxuYXhlcy5yZWRyYXdDb21wb25lbnRzID0gZnVuY3Rpb24oZ2QsIGF4SWRzKSB7XG4gICAgYXhJZHMgPSBheElkcyA/IGF4SWRzIDogYXhlcy5saXN0SWRzKGdkKTtcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBmdW5jdGlvbiBfcmVkcmF3T25lQ29tcChtb2R1bGVOYW1lLCBtZXRob2ROYW1lLCBzdGFzaE5hbWUsIHNob3J0Q2lyY3VpdCkge1xuICAgICAgICB2YXIgbWV0aG9kID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKG1vZHVsZU5hbWUsIG1ldGhvZE5hbWUpO1xuICAgICAgICB2YXIgc3Rhc2ggPSB7fTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBheCA9IGZ1bGxMYXlvdXRbYXhlcy5pZDJuYW1lKGF4SWRzW2ldKV07XG4gICAgICAgICAgICB2YXIgaW5kaWNlcyA9IGF4W3N0YXNoTmFtZV07XG5cbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBpbmRpY2VzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZCA9IGluZGljZXNbal07XG5cbiAgICAgICAgICAgICAgICBpZighc3Rhc2hbaW5kXSkge1xuICAgICAgICAgICAgICAgICAgICBtZXRob2QoZ2QsIGluZCk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXNoW2luZF0gPSAxO1xuICAgICAgICAgICAgICAgICAgICAvLyBvbmNlIGlzIGVub3VnaCBmb3IgaW1hZ2VzICh3aGljaCBkb2Vzbid0IHVzZSB0aGUgYGlgIGFyZyBhbnl3YXkpXG4gICAgICAgICAgICAgICAgICAgIGlmKHNob3J0Q2lyY3VpdCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFubm90YXRpb25zIGFuZCBzaGFwZXMgJ2RyYXcnIG1ldGhvZCBpcyBzbG93LFxuICAgIC8vIHVzZSB0aGUgZmluZXItZ3JhaW5lZCAnZHJhd09uZScgbWV0aG9kIGluc3RlYWRcbiAgICBfcmVkcmF3T25lQ29tcCgnYW5ub3RhdGlvbnMnLCAnZHJhd09uZScsICdfYW5uSW5kaWNlcycpO1xuICAgIF9yZWRyYXdPbmVDb21wKCdzaGFwZXMnLCAnZHJhd09uZScsICdfc2hhcGVJbmRpY2VzJyk7XG4gICAgX3JlZHJhd09uZUNvbXAoJ2ltYWdlcycsICdkcmF3JywgJ19pbWdJbmRpY2VzJywgdHJ1ZSk7XG59O1xuXG52YXIgZ2V0RGF0YUNvbnZlcnNpb25zID0gYXhlcy5nZXREYXRhQ29udmVyc2lvbnMgPSBmdW5jdGlvbihnZCwgdHJhY2UsIHRhcmdldCwgdGFyZ2V0QXJyYXkpIHtcbiAgICB2YXIgYXg7XG5cbiAgICAvLyBJZiB0YXJnZXQgcG9pbnRzIHRvIGFuIGF4aXMsIHVzZSB0aGUgdHlwZSB3ZSBhbHJlYWR5IGhhdmUgZm9yIHRoYXRcbiAgICAvLyBheGlzIHRvIGZpbmQgdGhlIGRhdGEgdHlwZS4gT3RoZXJ3aXNlIHVzZSB0aGUgdmFsdWVzIHRvIGF1dG90eXBlLlxuICAgIHZhciBkMmNUYXJnZXQgPSAodGFyZ2V0ID09PSAneCcgfHwgdGFyZ2V0ID09PSAneScgfHwgdGFyZ2V0ID09PSAneicpID9cbiAgICAgICAgdGFyZ2V0IDpcbiAgICAgICAgdGFyZ2V0QXJyYXk7XG5cbiAgICAvLyBJbiB0aGUgY2FzZSBvZiBhbiBhcnJheSB0YXJnZXQsIG1ha2UgYSBtb2NrIGRhdGEgYXJyYXlcbiAgICAvLyBhbmQgY2FsbCBzdXBwbHlEZWZhdWx0cyB0byB0aGUgZGF0YSB0eXBlIGFuZFxuICAgIC8vIHNldHVwIHRoZSBkYXRhLXRvLWNhbGMgbWV0aG9kLlxuICAgIGlmKEFycmF5LmlzQXJyYXkoZDJjVGFyZ2V0KSkge1xuICAgICAgICBheCA9IHtcbiAgICAgICAgICAgIHR5cGU6IGF1dG9UeXBlKHRhcmdldEFycmF5KSxcbiAgICAgICAgICAgIF9jYXRlZ29yaWVzOiBbXVxuICAgICAgICB9O1xuICAgICAgICBheGVzLnNldENvbnZlcnQoYXgpO1xuXG4gICAgICAgIC8vIGJ1aWxkIHVwIGF4Ll9jYXRlZ29yaWVzICh1c3VhbGx5IGRvbmUgZHVyaW5nIGF4Lm1ha2VDYWxjZGF0YSgpXG4gICAgICAgIGlmKGF4LnR5cGUgPT09ICdjYXRlZ29yeScpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0YXJnZXRBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGF4LmQyYyh0YXJnZXRBcnJheVtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETyB3aGF0IHRvIGRvIGZvciB0cmFuc2Zvcm1zP1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGF4ID0gYXhlcy5nZXRGcm9tVHJhY2UoZ2QsIHRyYWNlLCBkMmNUYXJnZXQpO1xuICAgIH1cblxuICAgIC8vIGlmICd0YXJnZXQnIGhhcyBjb3JyZXNwb25kaW5nIGF4aXNcbiAgICAvLyAtPiB1c2Ugc2V0Q29udmVydCBtZXRob2RcbiAgICBpZihheCkgcmV0dXJuIHtkMmM6IGF4LmQyYywgYzJkOiBheC5jMmR9O1xuXG4gICAgLy8gc3BlY2lhbCBjYXNlIGZvciAnaWRzJ1xuICAgIC8vIC0+IGNhc3QgdG8gU3RyaW5nXG4gICAgaWYoZDJjVGFyZ2V0ID09PSAnaWRzJykgcmV0dXJuIHtkMmM6IHRvU3RyaW5nLCBjMmQ6IHRvU3RyaW5nfTtcblxuICAgIC8vIG90aGVyd2lzZSAoZS5nLiBudW1lcmljLWFycmF5IG9mICdtYXJrZXIuY29sb3InIG9yICdtYXJrZXIuc2l6ZScpXG4gICAgLy8gLT4gY2FzdCB0byBOdW1iZXJcblxuICAgIHJldHVybiB7ZDJjOiB0b051bSwgYzJkOiB0b051bX07XG59O1xuXG5mdW5jdGlvbiB0b051bSh2KSB7IHJldHVybiArdjsgfVxuZnVuY3Rpb24gdG9TdHJpbmcodikgeyByZXR1cm4gU3RyaW5nKHYpOyB9XG5cbmF4ZXMuZ2V0RGF0YVRvQ29vcmRGdW5jID0gZnVuY3Rpb24oZ2QsIHRyYWNlLCB0YXJnZXQsIHRhcmdldEFycmF5KSB7XG4gICAgcmV0dXJuIGdldERhdGFDb252ZXJzaW9ucyhnZCwgdHJhY2UsIHRhcmdldCwgdGFyZ2V0QXJyYXkpLmQyYztcbn07XG5cbi8vIGdldCBjb3VudGVyYXhpcyBsZXR0ZXIgZm9yIHRoaXMgYXhpcyAobmFtZSBvciBpZClcbi8vIHRoaXMgY2FuIGFsc28gYmUgdXNlZCBhcyB0aGUgaWQgZm9yIGRlZmF1bHQgY291bnRlciBheGlzXG5heGVzLmNvdW50ZXJMZXR0ZXIgPSBmdW5jdGlvbihpZCkge1xuICAgIHZhciBheExldHRlciA9IGlkLmNoYXJBdCgwKTtcbiAgICBpZihheExldHRlciA9PT0gJ3gnKSByZXR1cm4gJ3knO1xuICAgIGlmKGF4TGV0dGVyID09PSAneScpIHJldHVybiAneCc7XG59O1xuXG4vLyBpbmNvcnBvcmF0ZSBhIG5ldyBtaW5pbXVtIGRpZmZlcmVuY2UgYW5kIGZpcnN0IHRpY2sgaW50b1xuLy8gZm9yY2VkXG4vLyBub3RlIHRoYXQgX2ZvcmNlVGljazAgaXMgbGluZWFyaXplZCwgc28gbmVlZHMgdG8gYmUgdHVybmVkIGludG9cbi8vIGEgcmFuZ2UgdmFsdWUgZm9yIHNldHRpbmcgdGljazBcbmF4ZXMubWluRHRpY2sgPSBmdW5jdGlvbihheCwgbmV3RGlmZiwgbmV3Rmlyc3QsIGFsbG93KSB7XG4gICAgLy8gZG9lc24ndCBtYWtlIHNlbnNlIHRvIGRvIGZvcmNlZCBtaW4gZFRpY2sgb24gbG9nIG9yIGNhdGVnb3J5IGF4ZXMsXG4gICAgLy8gYW5kIHRoZSBwbG90IGl0c2VsZiBtYXkgZGVjaWRlIHRvIGNhbmNlbCAoaWUgbm9uLWdyb3VwZWQgYmFycylcbiAgICBpZihbJ2xvZycsICdjYXRlZ29yeScsICdtdWx0aWNhdGVnb3J5J10uaW5kZXhPZihheC50eXBlKSAhPT0gLTEgfHwgIWFsbG93KSB7XG4gICAgICAgIGF4Ll9taW5EdGljayA9IDA7XG4gICAgfSBlbHNlIGlmKGF4Ll9taW5EdGljayA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIHVuZGVmaW5lZCBtZWFucyB0aGVyZSdzIG5vdGhpbmcgdGhlcmUgeWV0XG5cbiAgICAgICAgYXguX21pbkR0aWNrID0gbmV3RGlmZjtcbiAgICAgICAgYXguX2ZvcmNlVGljazAgPSBuZXdGaXJzdDtcbiAgICB9IGVsc2UgaWYoYXguX21pbkR0aWNrKSB7XG4gICAgICAgIGlmKChheC5fbWluRHRpY2sgLyBuZXdEaWZmICsgMWUtNikgJSAxIDwgMmUtNiAmJlxuICAgICAgICAgICAgLy8gZXhpc3RpbmcgbWluRHRpY2sgaXMgYW4gaW50ZWdlciBtdWx0aXBsZSBvZiBuZXdEaWZmXG4gICAgICAgICAgICAvLyAod2l0aGluIHJvdW5kaW5nIGVycilcbiAgICAgICAgICAgIC8vIGFuZCBmb3JjZVRpY2swIGNhbiBiZSBzaGlmdGVkIHRvIG5ld0ZpcnN0XG5cbiAgICAgICAgICAgICAgICAoKChuZXdGaXJzdCAtIGF4Ll9mb3JjZVRpY2swKSAvIG5ld0RpZmYgJSAxKSArXG4gICAgICAgICAgICAgICAgICAgIDEuMDAwMDAxKSAlIDEgPCAyZS02KSB7XG4gICAgICAgICAgICBheC5fbWluRHRpY2sgPSBuZXdEaWZmO1xuICAgICAgICAgICAgYXguX2ZvcmNlVGljazAgPSBuZXdGaXJzdDtcbiAgICAgICAgfSBlbHNlIGlmKChuZXdEaWZmIC8gYXguX21pbkR0aWNrICsgMWUtNikgJSAxID4gMmUtNiB8fFxuICAgICAgICAgICAgLy8gaWYgdGhlIGNvbnZlcnNlIGlzIHRydWUgKG5ld0RpZmYgaXMgYSBtdWx0aXBsZSBvZiBtaW5EdGljayBhbmRcbiAgICAgICAgICAgIC8vIG5ld0ZpcnN0IGNhbiBiZSBzaGlmdGVkIHRvIGZvcmNlVGljazApIHRoZW4gZG8gbm90aGluZyAtIHNhbWVcbiAgICAgICAgICAgIC8vIGZvcmNpbmcgc3RhbmRzLiBPdGhlcndpc2UsIGNhbmNlbCBmb3JjZWQgbWluaW11bVxuXG4gICAgICAgICAgICAgICAgKCgobmV3Rmlyc3QgLSBheC5fZm9yY2VUaWNrMCkgLyBheC5fbWluRHRpY2sgJSAxKSArXG4gICAgICAgICAgICAgICAgICAgIDEuMDAwMDAxKSAlIDEgPiAyZS02KSB7XG4gICAgICAgICAgICBheC5fbWluRHRpY2sgPSAwO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuLy8gc2F2ZSBhIGNvcHkgb2YgdGhlIGluaXRpYWwgYXhpcyByYW5nZXMgaW4gZnVsbExheW91dFxuLy8gdXNlIHRoZW0gaW4gbW9kZSBiYXIgYW5kIGRibGNsaWNrIGV2ZW50c1xuYXhlcy5zYXZlUmFuZ2VJbml0aWFsID0gZnVuY3Rpb24oZ2QsIG92ZXJ3cml0ZSkge1xuICAgIHZhciBheExpc3QgPSBheGVzLmxpc3QoZ2QsICcnLCB0cnVlKTtcbiAgICB2YXIgaGFzT25lQXhpc0NoYW5nZWQgPSBmYWxzZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF4ID0gYXhMaXN0W2ldO1xuICAgICAgICB2YXIgaXNOZXcgPSAoYXguX3JhbmdlSW5pdGlhbCA9PT0gdW5kZWZpbmVkKTtcbiAgICAgICAgdmFyIGhhc0NoYW5nZWQgPSBpc05ldyB8fCAhKFxuICAgICAgICAgICAgYXgucmFuZ2VbMF0gPT09IGF4Ll9yYW5nZUluaXRpYWxbMF0gJiZcbiAgICAgICAgICAgIGF4LnJhbmdlWzFdID09PSBheC5fcmFuZ2VJbml0aWFsWzFdXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYoKGlzTmV3ICYmIGF4LmF1dG9yYW5nZSA9PT0gZmFsc2UpIHx8IChvdmVyd3JpdGUgJiYgaGFzQ2hhbmdlZCkpIHtcbiAgICAgICAgICAgIGF4Ll9yYW5nZUluaXRpYWwgPSBheC5yYW5nZS5zbGljZSgpO1xuICAgICAgICAgICAgaGFzT25lQXhpc0NoYW5nZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGhhc09uZUF4aXNDaGFuZ2VkO1xufTtcblxuLy8gc2F2ZSBhIGNvcHkgb2YgdGhlIGluaXRpYWwgc3Bpa2UgdmlzaWJpbGl0eVxuYXhlcy5zYXZlU2hvd1NwaWtlSW5pdGlhbCA9IGZ1bmN0aW9uKGdkLCBvdmVyd3JpdGUpIHtcbiAgICB2YXIgYXhMaXN0ID0gYXhlcy5saXN0KGdkLCAnJywgdHJ1ZSk7XG4gICAgdmFyIGhhc09uZUF4aXNDaGFuZ2VkID0gZmFsc2U7XG4gICAgdmFyIGFsbFNwaWtlc0VuYWJsZWQgPSAnb24nO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXggPSBheExpc3RbaV07XG4gICAgICAgIHZhciBpc05ldyA9IChheC5fc2hvd1NwaWtlSW5pdGlhbCA9PT0gdW5kZWZpbmVkKTtcbiAgICAgICAgdmFyIGhhc0NoYW5nZWQgPSBpc05ldyB8fCAhKGF4LnNob3dzcGlrZXMgPT09IGF4Ll9zaG93c3Bpa2VzKTtcblxuICAgICAgICBpZihpc05ldyB8fCAob3ZlcndyaXRlICYmIGhhc0NoYW5nZWQpKSB7XG4gICAgICAgICAgICBheC5fc2hvd1NwaWtlSW5pdGlhbCA9IGF4LnNob3dzcGlrZXM7XG4gICAgICAgICAgICBoYXNPbmVBeGlzQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZihhbGxTcGlrZXNFbmFibGVkID09PSAnb24nICYmICFheC5zaG93c3Bpa2VzKSB7XG4gICAgICAgICAgICBhbGxTcGlrZXNFbmFibGVkID0gJ29mZic7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZ2QuX2Z1bGxMYXlvdXQuX2NhcnRlc2lhblNwaWtlc0VuYWJsZWQgPSBhbGxTcGlrZXNFbmFibGVkO1xuICAgIHJldHVybiBoYXNPbmVBeGlzQ2hhbmdlZDtcbn07XG5cbmF4ZXMuYXV0b0JpbiA9IGZ1bmN0aW9uKGRhdGEsIGF4LCBuYmlucywgaXMyZCwgY2FsZW5kYXIsIHNpemUpIHtcbiAgICB2YXIgZGF0YU1pbiA9IExpYi5hZ2dOdW1zKE1hdGgubWluLCBudWxsLCBkYXRhKTtcbiAgICB2YXIgZGF0YU1heCA9IExpYi5hZ2dOdW1zKE1hdGgubWF4LCBudWxsLCBkYXRhKTtcblxuICAgIGlmKGF4LnR5cGUgPT09ICdjYXRlZ29yeScgfHwgYXgudHlwZSA9PT0gJ211bHRpY2F0ZWdvcnknKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdGFydDogZGF0YU1pbiAtIDAuNSxcbiAgICAgICAgICAgIGVuZDogZGF0YU1heCArIDAuNSxcbiAgICAgICAgICAgIHNpemU6IE1hdGgubWF4KDEsIE1hdGgucm91bmQoc2l6ZSkgfHwgMSksXG4gICAgICAgICAgICBfZGF0YVNwYW46IGRhdGFNYXggLSBkYXRhTWluLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmKCFjYWxlbmRhcikgY2FsZW5kYXIgPSBheC5jYWxlbmRhcjtcblxuICAgIC8vIHBpZ2d5YmFjayBvZmYgdGljayBjb2RlIHRvIG1ha2UgXCJuaWNlXCIgYmluIHNpemVzIGFuZCBlZGdlc1xuICAgIHZhciBkdW1teUF4O1xuICAgIGlmKGF4LnR5cGUgPT09ICdsb2cnKSB7XG4gICAgICAgIGR1bW15QXggPSB7XG4gICAgICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgICAgIHJhbmdlOiBbZGF0YU1pbiwgZGF0YU1heF1cbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkdW1teUF4ID0ge1xuICAgICAgICAgICAgdHlwZTogYXgudHlwZSxcbiAgICAgICAgICAgIHJhbmdlOiBMaWIuc2ltcGxlTWFwKFtkYXRhTWluLCBkYXRhTWF4XSwgYXguYzJyLCAwLCBjYWxlbmRhciksXG4gICAgICAgICAgICBjYWxlbmRhcjogY2FsZW5kYXJcbiAgICAgICAgfTtcbiAgICB9XG4gICAgYXhlcy5zZXRDb252ZXJ0KGR1bW15QXgpO1xuXG4gICAgc2l6ZSA9IHNpemUgJiYgY2xlYW5UaWNrcy5kdGljayhzaXplLCBkdW1teUF4LnR5cGUpO1xuXG4gICAgaWYoc2l6ZSkge1xuICAgICAgICBkdW1teUF4LmR0aWNrID0gc2l6ZTtcbiAgICAgICAgZHVtbXlBeC50aWNrMCA9IGNsZWFuVGlja3MudGljazAodW5kZWZpbmVkLCBkdW1teUF4LnR5cGUsIGNhbGVuZGFyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgc2l6ZTA7XG4gICAgICAgIGlmKG5iaW5zKSBzaXplMCA9ICgoZGF0YU1heCAtIGRhdGFNaW4pIC8gbmJpbnMpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRvdGFsbHkgYXV0bzogc2NhbGUgb2ZmIHN0ZCBkZXZpYXRpb24gc28gdGhlIGhpZ2hlc3QgYmluIGlzXG4gICAgICAgICAgICAvLyBzb21ld2hhdCB0YWxsZXIgdGhhbiB0aGUgdG90YWwgbnVtYmVyIG9mIGJpbnMsIGJ1dCBkb24ndCBsZXRcbiAgICAgICAgICAgIC8vIHRoZSBzaXplIGdldCBzbWFsbGVyIHRoYW4gdGhlICduaWNlJyByb3VuZGVkIGRvd24gbWluaW11bVxuICAgICAgICAgICAgLy8gZGlmZmVyZW5jZSBiZXR3ZWVuIHZhbHVlc1xuICAgICAgICAgICAgdmFyIGRpc3RpbmN0RGF0YSA9IExpYi5kaXN0aW5jdFZhbHMoZGF0YSk7XG4gICAgICAgICAgICB2YXIgbXNleHAgPSBNYXRoLnBvdygxMCwgTWF0aC5mbG9vcihcbiAgICAgICAgICAgICAgICBNYXRoLmxvZyhkaXN0aW5jdERhdGEubWluRGlmZikgLyBNYXRoLkxOMTApKTtcbiAgICAgICAgICAgIHZhciBtaW5TaXplID0gbXNleHAgKiBMaWIucm91bmRVcChcbiAgICAgICAgICAgICAgICBkaXN0aW5jdERhdGEubWluRGlmZiAvIG1zZXhwLCBbMC45LCAxLjksIDQuOSwgOS45XSwgdHJ1ZSk7XG4gICAgICAgICAgICBzaXplMCA9IE1hdGgubWF4KG1pblNpemUsIDIgKiBMaWIuc3RkZXYoZGF0YSkgL1xuICAgICAgICAgICAgICAgIE1hdGgucG93KGRhdGEubGVuZ3RoLCBpczJkID8gMC4yNSA6IDAuNCkpO1xuXG4gICAgICAgICAgICAvLyBmYWxsYmFjayBpZiBheC5kMmMgb3V0cHV0IEJBRE5VTXNcbiAgICAgICAgICAgIC8vIGUuZy4gd2hlbiB1c2VyIHRyeSB0byBwbG90IGNhdGVnb3JpY2FsIGJpbnNcbiAgICAgICAgICAgIC8vIG9uIGEgbGF5b3V0LnhheGlzLnR5cGU6ICdsaW5lYXInXG4gICAgICAgICAgICBpZighaXNOdW1lcmljKHNpemUwKSkgc2l6ZTAgPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgYXhlcy5hdXRvVGlja3MoZHVtbXlBeCwgc2l6ZTApO1xuICAgIH1cblxuICAgIHZhciBmaW5hbFNpemUgPSBkdW1teUF4LmR0aWNrO1xuICAgIHZhciBiaW5TdGFydCA9IGF4ZXMudGlja0luY3JlbWVudChcbiAgICAgICAgICAgIGF4ZXMudGlja0ZpcnN0KGR1bW15QXgpLCBmaW5hbFNpemUsICdyZXZlcnNlJywgY2FsZW5kYXIpO1xuICAgIHZhciBiaW5FbmQsIGJpbmNvdW50O1xuXG4gICAgLy8gY2hlY2sgZm9yIHRvbyBtYW55IGRhdGEgcG9pbnRzIHJpZ2h0IGF0IHRoZSBlZGdlcyBvZiBiaW5zXG4gICAgLy8gKD41MCUgd2l0aGluIDElIG9mIGJpbiBlZGdlcykgb3IgYWxsIGRhdGEgcG9pbnRzIGludGVncmFsXG4gICAgLy8gYW5kIG9mZnNldCB0aGUgYmlucyBhY2NvcmRpbmdseVxuICAgIGlmKHR5cGVvZiBmaW5hbFNpemUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGJpblN0YXJ0ID0gYXV0b1NoaWZ0TnVtZXJpY0JpbnMoYmluU3RhcnQsIGRhdGEsIGR1bW15QXgsIGRhdGFNaW4sIGRhdGFNYXgpO1xuXG4gICAgICAgIGJpbmNvdW50ID0gMSArIE1hdGguZmxvb3IoKGRhdGFNYXggLSBiaW5TdGFydCkgLyBmaW5hbFNpemUpO1xuICAgICAgICBiaW5FbmQgPSBiaW5TdGFydCArIGJpbmNvdW50ICogZmluYWxTaXplO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIG1vbnRoIHRpY2tzIC0gc2hvdWxkIGJlIHRoZSBvbmx5IG5vbmxpbmVhciBraW5kIHdlIGhhdmUgYXQgdGhpcyBwb2ludC5cbiAgICAgICAgLy8gZHRpY2sgKGFzIHN1cHBsaWVkIGJ5IGF4ZXMuYXV0b1RpY2spIG9ubHkgaGFzIG5vbmxpbmVhciB2YWx1ZXMgb25cbiAgICAgICAgLy8gZGF0ZSBhbmQgbG9nIGF4ZXMsIGJ1dCBldmVuIGlmIHlvdSBkaXNwbGF5IGEgaGlzdG9ncmFtIG9uIGEgbG9nIGF4aXNcbiAgICAgICAgLy8gd2UgYmluIGl0IG9uIGEgbGluZWFyIGF4aXMgKHdoaWNoIG9uZSBjb3VsZCBhcmd1ZSBhZ2FpbnN0LCBidXQgdGhhdCdzXG4gICAgICAgIC8vIGEgc2VwYXJhdGUgaXNzdWUpXG4gICAgICAgIGlmKGR1bW15QXguZHRpY2suY2hhckF0KDApID09PSAnTScpIHtcbiAgICAgICAgICAgIGJpblN0YXJ0ID0gYXV0b1NoaWZ0TW9udGhCaW5zKGJpblN0YXJ0LCBkYXRhLCBmaW5hbFNpemUsIGRhdGFNaW4sIGNhbGVuZGFyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgZW5kcG9pbnQgZm9yIG5vbmxpbmVhciB0aWNrcyAtIHlvdSBoYXZlIHRvXG4gICAgICAgIC8vIGp1c3QgaW5jcmVtZW50IHVudGlsIHlvdSdyZSBkb25lXG4gICAgICAgIGJpbkVuZCA9IGJpblN0YXJ0O1xuICAgICAgICBiaW5jb3VudCA9IDA7XG4gICAgICAgIHdoaWxlKGJpbkVuZCA8PSBkYXRhTWF4KSB7XG4gICAgICAgICAgICBiaW5FbmQgPSBheGVzLnRpY2tJbmNyZW1lbnQoYmluRW5kLCBmaW5hbFNpemUsIGZhbHNlLCBjYWxlbmRhcik7XG4gICAgICAgICAgICBiaW5jb3VudCsrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IGF4LmMycihiaW5TdGFydCwgMCwgY2FsZW5kYXIpLFxuICAgICAgICBlbmQ6IGF4LmMycihiaW5FbmQsIDAsIGNhbGVuZGFyKSxcbiAgICAgICAgc2l6ZTogZmluYWxTaXplLFxuICAgICAgICBfZGF0YVNwYW46IGRhdGFNYXggLSBkYXRhTWluXG4gICAgfTtcbn07XG5cblxuZnVuY3Rpb24gYXV0b1NoaWZ0TnVtZXJpY0JpbnMoYmluU3RhcnQsIGRhdGEsIGF4LCBkYXRhTWluLCBkYXRhTWF4KSB7XG4gICAgdmFyIGVkZ2Vjb3VudCA9IDA7XG4gICAgdmFyIG1pZGNvdW50ID0gMDtcbiAgICB2YXIgaW50Y291bnQgPSAwO1xuICAgIHZhciBibGFua0NvdW50ID0gMDtcblxuICAgIGZ1bmN0aW9uIG5lYXJFZGdlKHYpIHtcbiAgICAgICAgLy8gaXMgYSB2YWx1ZSB3aXRoaW4gMSUgb2YgYSBiaW4gZWRnZT9cbiAgICAgICAgcmV0dXJuICgxICsgKHYgLSBiaW5TdGFydCkgKiAxMDAgLyBheC5kdGljaykgJSAxMDAgPCAyO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGRhdGFbaV0gJSAxID09PSAwKSBpbnRjb3VudCsrO1xuICAgICAgICBlbHNlIGlmKCFpc051bWVyaWMoZGF0YVtpXSkpIGJsYW5rQ291bnQrKztcblxuICAgICAgICBpZihuZWFyRWRnZShkYXRhW2ldKSkgZWRnZWNvdW50Kys7XG4gICAgICAgIGlmKG5lYXJFZGdlKGRhdGFbaV0gKyBheC5kdGljayAvIDIpKSBtaWRjb3VudCsrO1xuICAgIH1cbiAgICB2YXIgZGF0YUNvdW50ID0gZGF0YS5sZW5ndGggLSBibGFua0NvdW50O1xuXG4gICAgaWYoaW50Y291bnQgPT09IGRhdGFDb3VudCAmJiBheC50eXBlICE9PSAnZGF0ZScpIHtcbiAgICAgICAgaWYoYXguZHRpY2sgPCAxKSB7XG4gICAgICAgICAgICAvLyBhbGwgaW50ZWdlcnM6IGlmIGJpbiBzaXplIGlzIDwxLCBpdCdzIGJlY2F1c2VcbiAgICAgICAgICAgIC8vIHRoYXQgd2FzIHNwZWNpZmljYWxseSByZXF1ZXN0ZWQgKGxhcmdlIG5iaW5zKVxuICAgICAgICAgICAgLy8gc28gcmVzcGVjdCB0aGF0Li4uIGJ1dCBjZW50ZXIgdGhlIGJpbnMgY29udGFpbmluZ1xuICAgICAgICAgICAgLy8gaW50ZWdlcnMgb24gdGhvc2UgaW50ZWdlcnNcblxuICAgICAgICAgICAgYmluU3RhcnQgPSBkYXRhTWluIC0gMC41ICogYXguZHRpY2s7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBvdGhlcndpc2Ugc3RhcnQgaGFsZiBhbiBpbnRlZ2VyIGRvd24gcmVnYXJkbGVzcyBvZlxuICAgICAgICAgICAgLy8gdGhlIGJpbiBzaXplLCBqdXN0IGVub3VnaCB0byBjbGVhciB1cCBlbmRwb2ludFxuICAgICAgICAgICAgLy8gYW1iaWd1aXR5IGFib3V0IHdoaWNoIGludGVnZXJzIGFyZSBpbiB3aGljaCBiaW5zLlxuXG4gICAgICAgICAgICBiaW5TdGFydCAtPSAwLjU7XG4gICAgICAgICAgICBpZihiaW5TdGFydCArIGF4LmR0aWNrIDwgZGF0YU1pbikgYmluU3RhcnQgKz0gYXguZHRpY2s7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYobWlkY291bnQgPCBkYXRhQ291bnQgKiAwLjEpIHtcbiAgICAgICAgaWYoZWRnZWNvdW50ID4gZGF0YUNvdW50ICogMC4zIHx8XG4gICAgICAgICAgICAgICAgbmVhckVkZ2UoZGF0YU1pbikgfHwgbmVhckVkZ2UoZGF0YU1heCkpIHtcbiAgICAgICAgICAgIC8vIGxvdHMgb2YgcG9pbnRzIGF0IHRoZSBlZGdlLCBub3QgbWFueSBpbiB0aGUgbWlkZGxlXG4gICAgICAgICAgICAvLyBzaGlmdCBoYWxmIGEgYmluXG4gICAgICAgICAgICB2YXIgYmluc2hpZnQgPSBheC5kdGljayAvIDI7XG4gICAgICAgICAgICBiaW5TdGFydCArPSAoYmluU3RhcnQgKyBiaW5zaGlmdCA8IGRhdGFNaW4pID8gYmluc2hpZnQgOiAtYmluc2hpZnQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGJpblN0YXJ0O1xufVxuXG5cbmZ1bmN0aW9uIGF1dG9TaGlmdE1vbnRoQmlucyhiaW5TdGFydCwgZGF0YSwgZHRpY2ssIGRhdGFNaW4sIGNhbGVuZGFyKSB7XG4gICAgdmFyIHN0YXRzID0gTGliLmZpbmRFeGFjdERhdGVzKGRhdGEsIGNhbGVuZGFyKTtcbiAgICAvLyBudW1iZXIgb2YgZGF0YSBwb2ludHMgdGhhdCBuZWVkcyB0byBiZSBhbiBleGFjdCB2YWx1ZVxuICAgIC8vIHRvIHNoaWZ0IHRoYXQgaW5jcmVtZW50IHRvIChuZWFyKSB0aGUgYmluIGNlbnRlclxuICAgIHZhciB0aHJlc2hvbGQgPSAwLjg7XG5cbiAgICBpZihzdGF0cy5leGFjdERheXMgPiB0aHJlc2hvbGQpIHtcbiAgICAgICAgdmFyIG51bU1vbnRocyA9IE51bWJlcihkdGljay5zdWJzdHIoMSkpO1xuXG4gICAgICAgIGlmKChzdGF0cy5leGFjdFllYXJzID4gdGhyZXNob2xkKSAmJiAobnVtTW9udGhzICUgMTIgPT09IDApKSB7XG4gICAgICAgICAgICAvLyBUaGUgZXhhY3QgbWlkZGxlIG9mIGEgbm9uLWxlYXAteWVhciBpcyAxLjUgZGF5cyBpbnRvIEp1bHlcbiAgICAgICAgICAgIC8vIHNvIGlmIHdlIHN0YXJ0IHRoZSBiaW5zIGhlcmUsIGFsbCBidXQgbGVhcCB5ZWFycyB3aWxsXG4gICAgICAgICAgICAvLyBnZXQgaG92ZXItbGFiZWxlZCBhcyBleGFjdCB5ZWFycy5cbiAgICAgICAgICAgIGJpblN0YXJ0ID0gYXhlcy50aWNrSW5jcmVtZW50KGJpblN0YXJ0LCAnTTYnLCAncmV2ZXJzZScpICsgT05FREFZICogMS41O1xuICAgICAgICB9IGVsc2UgaWYoc3RhdHMuZXhhY3RNb250aHMgPiB0aHJlc2hvbGQpIHtcbiAgICAgICAgICAgIC8vIE1vbnRocyBhcmUgbm90IGFzIGNsZWFuLCBidXQgaWYgd2Ugc2hpZnQgaGFsZiB0aGUgKmxvbmdlc3QqXG4gICAgICAgICAgICAvLyBtb250aCAoMzEvMiBkYXlzKSB0aGVuIDMxLWRheSBtb250aHMgd2lsbCBnZXQgbGFiZWxlZCBleGFjdGx5XG4gICAgICAgICAgICAvLyBhbmQgc2hvcnRlciBtb250aHMgd2lsbCBnZXQgbGFiZWxlZCB3aXRoIHRoZSBjb3JyZWN0IG1vbnRoXG4gICAgICAgICAgICAvLyBidXQgc2hpZnRlZCAxMi0zNiBob3VycyBpbnRvIGl0LlxuICAgICAgICAgICAgYmluU3RhcnQgPSBheGVzLnRpY2tJbmNyZW1lbnQoYmluU3RhcnQsICdNMScsICdyZXZlcnNlJykgKyBPTkVEQVkgKiAxNS41O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gU2hpZnRpbmcgaGFsZiBhIGRheSBpcyBleGFjdCwgYnV0IHNpbmNlIHRoZXNlIGFyZSBtb250aCBiaW5zIGl0XG4gICAgICAgICAgICAvLyB3aWxsIGFsd2F5cyBnaXZlIGEgc29tZXdoYXQgb2RkLWxvb2tpbmcgbGFiZWwsIHVudGlsIHdlIGRvIHNvbWV0aGluZ1xuICAgICAgICAgICAgLy8gc21hcnRlciBsaWtlIHNob3dpbmcgdGhlIGJpbiBib3VuZGFyaWVzIChvciB0aGUgYm91bmRzIG9mIHRoZSBhY3R1YWxcbiAgICAgICAgICAgIC8vIGRhdGEgaW4gZWFjaCBiaW4pXG4gICAgICAgICAgICBiaW5TdGFydCAtPSBPTkVEQVkgLyAyO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuZXh0QmluU3RhcnQgPSBheGVzLnRpY2tJbmNyZW1lbnQoYmluU3RhcnQsIGR0aWNrKTtcblxuICAgICAgICBpZihuZXh0QmluU3RhcnQgPD0gZGF0YU1pbikgcmV0dXJuIG5leHRCaW5TdGFydDtcbiAgICB9XG4gICAgcmV0dXJuIGJpblN0YXJ0O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBUaWNrcyBhbmQgZ3JpZHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLy8gZW5zdXJlIHdlIGhhdmUgdGljazAsIGR0aWNrLCBhbmQgdGljayByb3VuZGluZyBjYWxjdWxhdGVkXG5heGVzLnByZXBUaWNrcyA9IGZ1bmN0aW9uKGF4KSB7XG4gICAgdmFyIHJuZyA9IExpYi5zaW1wbGVNYXAoYXgucmFuZ2UsIGF4LnIybCk7XG5cbiAgICAvLyBjYWxjdWxhdGUgbWF4IG51bWJlciBvZiAoYXV0bykgdGlja3MgdG8gZGlzcGxheSBiYXNlZCBvbiBwbG90IHNpemVcbiAgICBpZihheC50aWNrbW9kZSA9PT0gJ2F1dG8nIHx8ICFheC5kdGljaykge1xuICAgICAgICB2YXIgbnQgPSBheC5udGlja3M7XG4gICAgICAgIHZhciBtaW5QeDtcblxuICAgICAgICBpZighbnQpIHtcbiAgICAgICAgICAgIGlmKGF4LnR5cGUgPT09ICdjYXRlZ29yeScgfHwgYXgudHlwZSA9PT0gJ211bHRpY2F0ZWdvcnknKSB7XG4gICAgICAgICAgICAgICAgbWluUHggPSBheC50aWNrZm9udCA/IChheC50aWNrZm9udC5zaXplIHx8IDEyKSAqIDEuMiA6IDE1O1xuICAgICAgICAgICAgICAgIG50ID0gYXguX2xlbmd0aCAvIG1pblB4O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtaW5QeCA9IGF4Ll9pZC5jaGFyQXQoMCkgPT09ICd5JyA/IDQwIDogODA7XG4gICAgICAgICAgICAgICAgbnQgPSBMaWIuY29uc3RyYWluKGF4Ll9sZW5ndGggLyBtaW5QeCwgNCwgOSkgKyAxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyByYWRpYWwgYXhlcyBzcGFuIGhhbGYgdGhlaXIgZG9tYWluLFxuICAgICAgICAgICAgLy8gbXVsdGlwbHkgbnRpY2tzIHZhbHVlIGJ5IHR3byB0byBnZXQgY29ycmVjdCBudW1iZXIgb2YgYXV0byB0aWNrcy5cbiAgICAgICAgICAgIGlmKGF4Ll9uYW1lID09PSAncmFkaWFsYXhpcycpIG50ICo9IDI7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGQgYSBjb3VwbGUgb2YgZXh0cmEgZGlnaXRzIGZvciBmaWxsaW5nIGluIHRpY2tzIHdoZW4gd2VcbiAgICAgICAgLy8gaGF2ZSBleHBsaWNpdCB0aWNrdmFscyB3aXRob3V0IHRpY2sgdGV4dFxuICAgICAgICBpZihheC50aWNrbW9kZSA9PT0gJ2FycmF5JykgbnQgKj0gMTAwO1xuXG4gICAgICAgIGF4ZXMuYXV0b1RpY2tzKGF4LCBNYXRoLmFicyhybmdbMV0gLSBybmdbMF0pIC8gbnQpO1xuICAgICAgICAvLyBjaGVjayBmb3IgYSBmb3JjZWQgbWluaW11bSBkdGlja1xuICAgICAgICBpZihheC5fbWluRHRpY2sgPiAwICYmIGF4LmR0aWNrIDwgYXguX21pbkR0aWNrICogMikge1xuICAgICAgICAgICAgYXguZHRpY2sgPSBheC5fbWluRHRpY2s7XG4gICAgICAgICAgICBheC50aWNrMCA9IGF4LmwycihheC5fZm9yY2VUaWNrMCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBjaGVjayBmb3IgbWlzc2luZyB0aWNrMFxuICAgIGlmKCFheC50aWNrMCkge1xuICAgICAgICBheC50aWNrMCA9IChheC50eXBlID09PSAnZGF0ZScpID8gJzIwMDAtMDEtMDEnIDogMDtcbiAgICB9XG5cbiAgICAvLyBlbnN1cmUgd2UgZG9uJ3QgdHJ5IHRvIG1ha2UgdGlja3MgYmVsb3cgb3VyIG1pbmltdW0gcHJlY2lzaW9uXG4gICAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy8yODkyXG4gICAgaWYoYXgudHlwZSA9PT0gJ2RhdGUnICYmIGF4LmR0aWNrIDwgMC4xKSBheC5kdGljayA9IDAuMTtcblxuICAgIC8vIG5vdyBmaWd1cmUgb3V0IHJvdW5kaW5nIG9mIHRpY2sgdmFsdWVzXG4gICAgYXV0b1RpY2tSb3VuZChheCk7XG59O1xuXG4vLyBjYWxjdWxhdGUgdGhlIHRpY2tzOiB0ZXh0LCB2YWx1ZXMsIHBvc2l0aW9uaW5nXG4vLyBpZiB0aWNrcyBhcmUgc2V0IHRvIGF1dG9tYXRpYywgZGV0ZXJtaW5lIHRoZSByaWdodCB2YWx1ZXMgKHRpY2swLGR0aWNrKVxuLy8gaW4gYW55IGNhc2UsIHNldCB0aWNrcm91bmQgdG8gIyBvZiBkaWdpdHMgdG8gcm91bmQgdGljayBsYWJlbHMgdG8sXG4vLyBvciBjb2RlcyB0byB0aGlzIGVmZmVjdCBmb3IgbG9nIGFuZCBkYXRlIHNjYWxlc1xuYXhlcy5jYWxjVGlja3MgPSBmdW5jdGlvbiBjYWxjVGlja3MoYXgpIHtcbiAgICBheGVzLnByZXBUaWNrcyhheCk7XG4gICAgdmFyIHJuZyA9IExpYi5zaW1wbGVNYXAoYXgucmFuZ2UsIGF4LnIybCk7XG5cbiAgICAvLyBub3cgdGhhdCB3ZSd2ZSBmaWd1cmVkIG91dCB0aGUgYXV0byB2YWx1ZXMgZm9yIGZvcm1hdHRpbmdcbiAgICAvLyBpbiBjYXNlIHdlJ3JlIG1pc3Npbmcgc29tZSB0aWNrdGV4dCwgd2UgY2FuIGJyZWFrIG91dCBmb3IgYXJyYXkgdGlja3NcbiAgICBpZihheC50aWNrbW9kZSA9PT0gJ2FycmF5JykgcmV0dXJuIGFycmF5VGlja3MoYXgpO1xuXG4gICAgLy8gZmluZCB0aGUgZmlyc3QgdGlja1xuICAgIGF4Ll90bWluID0gYXhlcy50aWNrRmlyc3QoYXgpO1xuXG4gICAgLy8gYWRkIGEgdGlueSBiaXQgc28gd2UgZ2V0IHRpY2tzIHdoaWNoIG1heSBoYXZlIHJvdW5kZWQgb3V0XG4gICAgdmFyIHN0YXJ0VGljayA9IHJuZ1swXSAqIDEuMDAwMSAtIHJuZ1sxXSAqIDAuMDAwMTtcbiAgICB2YXIgZW5kVGljayA9IHJuZ1sxXSAqIDEuMDAwMSAtIHJuZ1swXSAqIDAuMDAwMTtcbiAgICAvLyBjaGVjayBmb3IgcmV2ZXJzZWQgYXhpc1xuICAgIHZhciBheHJldiA9IChybmdbMV0gPCBybmdbMF0pO1xuXG4gICAgLy8gTm8gdmlzaWJsZSB0aWNrcz8gUXVpdC5cbiAgICAvLyBJJ3ZlIG9ubHkgc2VlbiB0aGlzIG9uIGNhdGVnb3J5IGF4ZXMgd2l0aCBhbGwgY2F0ZWdvcmllcyBvZmYgdGhlIGVkZ2UuXG4gICAgaWYoKGF4Ll90bWluIDwgc3RhcnRUaWNrKSAhPT0gYXhyZXYpIHJldHVybiBbXTtcblxuICAgIC8vIHJldHVybiB0aGUgZnVsbCBzZXQgb2YgdGljayB2YWxzXG4gICAgdmFyIHRpY2tWYWxzID0gW107XG4gICAgaWYoYXgudHlwZSA9PT0gJ2NhdGVnb3J5JyB8fCBheC50eXBlID09PSAnbXVsdGljYXRlZ29yeScpIHtcbiAgICAgICAgZW5kVGljayA9IChheHJldikgPyBNYXRoLm1heCgtMC41LCBlbmRUaWNrKSA6XG4gICAgICAgICAgICBNYXRoLm1pbihheC5fY2F0ZWdvcmllcy5sZW5ndGggLSAwLjUsIGVuZFRpY2spO1xuICAgIH1cblxuICAgIHZhciBpc0RMb2cgPSAoYXgudHlwZSA9PT0gJ2xvZycpICYmICEoaXNOdW1lcmljKGF4LmR0aWNrKSB8fCBheC5kdGljay5jaGFyQXQoMCkgPT09ICdMJyk7XG5cbiAgICB2YXIgeFByZXZpb3VzID0gbnVsbDtcbiAgICB2YXIgbWF4VGlja3MgPSBNYXRoLm1heCgxMDAwLCBheC5fbGVuZ3RoIHx8IDApO1xuICAgIGZvcih2YXIgeCA9IGF4Ll90bWluO1xuICAgICAgICAgICAgKGF4cmV2KSA/ICh4ID49IGVuZFRpY2spIDogKHggPD0gZW5kVGljayk7XG4gICAgICAgICAgICB4ID0gYXhlcy50aWNrSW5jcmVtZW50KHgsIGF4LmR0aWNrLCBheHJldiwgYXguY2FsZW5kYXIpKSB7XG4gICAgICAgIC8vIHByZXZlbnQgaW5maW5pdGUgbG9vcHMgLSBubyBtb3JlIHRoYW4gb25lIHRpY2sgcGVyIHBpeGVsLFxuICAgICAgICAvLyBhbmQgbWFrZSBzdXJlIGVhY2ggdmFsdWUgaXMgZGlmZmVyZW50IGZyb20gdGhlIHByZXZpb3VzXG4gICAgICAgIGlmKHRpY2tWYWxzLmxlbmd0aCA+IG1heFRpY2tzIHx8IHggPT09IHhQcmV2aW91cykgYnJlYWs7XG4gICAgICAgIHhQcmV2aW91cyA9IHg7XG5cbiAgICAgICAgdmFyIG1pbm9yID0gZmFsc2U7XG4gICAgICAgIGlmKGlzRExvZyAmJiAoeCAhPT0gKHggfCAwKSkpIHtcbiAgICAgICAgICAgIG1pbm9yID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRpY2tWYWxzLnB1c2goe1xuICAgICAgICAgICAgbWlub3I6IG1pbm9yLFxuICAgICAgICAgICAgdmFsdWU6IHhcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gSWYgc2FtZSBhbmdsZSBvdmVyIGEgZnVsbCBjaXJjbGUsIHRoZSBsYXN0IHRpY2sgdmFscyBpcyBhIGR1cGxpY2F0ZS5cbiAgICAvLyBUT0RPIG11c3QgZG8gc29tZXRoaW5nIHNpbWlsYXIgZm9yIGFuZ3VsYXIgZGF0ZSBheGVzLlxuICAgIGlmKGlzQW5ndWxhcihheCkgJiYgTWF0aC5hYnMocm5nWzFdIC0gcm5nWzBdKSA9PT0gMzYwKSB7XG4gICAgICAgIHRpY2tWYWxzLnBvcCgpO1xuICAgIH1cblxuICAgIC8vIHNhdmUgdGhlIGxhc3QgdGljayBhcyB3ZWxsIGFzIGZpcnN0LCBzbyB3ZSBjYW5cbiAgICAvLyBzaG93IHRoZSBleHBvbmVudCBvbmx5IG9uIHRoZSBsYXN0IG9uZVxuICAgIGF4Ll90bWF4ID0gKHRpY2tWYWxzW3RpY2tWYWxzLmxlbmd0aCAtIDFdIHx8IHt9KS52YWx1ZTtcblxuICAgIC8vIGZvciBzaG93aW5nIHRoZSByZXN0IG9mIGEgZGF0ZSB3aGVuIHRoZSBtYWluIHRpY2sgbGFiZWwgaXMgb25seSB0aGVcbiAgICAvLyBsYXR0ZXIgcGFydDogYXguX3ByZXZEYXRlSGVhZCBob2xkcyB3aGF0IHdlIHNob3dlZCBtb3N0IHJlY2VudGx5LlxuICAgIC8vIFN0YXJ0IHdpdGggaXQgY2xlYXJlZCBhbmQgbWFyayB0aGF0IHdlJ3JlIGluIGNhbGNUaWNrcyAoaWUgY2FsY3VsYXRpbmcgYVxuICAgIC8vIHdob2xlIHN0cmluZyBvZiB0aGVzZSBzbyB3ZSBzaG91bGQgY2FyZSB3aGF0IHRoZSBwcmV2aW91cyBkYXRlIGhlYWQgd2FzISlcbiAgICBheC5fcHJldkRhdGVIZWFkID0gJyc7XG4gICAgYXguX2luQ2FsY1RpY2tzID0gdHJ1ZTtcblxuICAgIHZhciB0aWNrc091dCA9IG5ldyBBcnJheSh0aWNrVmFscy5sZW5ndGgpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0aWNrVmFscy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aWNrc091dFtpXSA9IGF4ZXMudGlja1RleHQoXG4gICAgICAgICAgICBheCxcbiAgICAgICAgICAgIHRpY2tWYWxzW2ldLnZhbHVlLFxuICAgICAgICAgICAgZmFsc2UsIC8vIGhvdmVyXG4gICAgICAgICAgICB0aWNrVmFsc1tpXS5taW5vciAvLyBub1N1ZmZpeFByZWZpeFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGF4Ll9pbkNhbGNUaWNrcyA9IGZhbHNlO1xuXG4gICAgcmV0dXJuIHRpY2tzT3V0O1xufTtcblxuZnVuY3Rpb24gYXJyYXlUaWNrcyhheCkge1xuICAgIHZhciB2YWxzID0gYXgudGlja3ZhbHM7XG4gICAgdmFyIHRleHQgPSBheC50aWNrdGV4dDtcbiAgICB2YXIgdGlja3NPdXQgPSBuZXcgQXJyYXkodmFscy5sZW5ndGgpO1xuICAgIHZhciBybmcgPSBMaWIuc2ltcGxlTWFwKGF4LnJhbmdlLCBheC5yMmwpO1xuICAgIHZhciByMGV4cGFuZGVkID0gcm5nWzBdICogMS4wMDAxIC0gcm5nWzFdICogMC4wMDAxO1xuICAgIHZhciByMWV4cGFuZGVkID0gcm5nWzFdICogMS4wMDAxIC0gcm5nWzBdICogMC4wMDAxO1xuICAgIHZhciB0aWNrTWluID0gTWF0aC5taW4ocjBleHBhbmRlZCwgcjFleHBhbmRlZCk7XG4gICAgdmFyIHRpY2tNYXggPSBNYXRoLm1heChyMGV4cGFuZGVkLCByMWV4cGFuZGVkKTtcbiAgICB2YXIgaiA9IDA7XG5cbiAgICAvLyB3aXRob3V0IGEgdGV4dCBhcnJheSwganVzdCBmb3JtYXQgdGhlIGdpdmVuIHZhbHVlcyBhcyBhbnkgb3RoZXIgdGlja3NcbiAgICAvLyBleGNlcHQgd2l0aCBtb3JlIHByZWNpc2lvbiB0byB0aGUgbnVtYmVyc1xuICAgIGlmKCFBcnJheS5pc0FycmF5KHRleHQpKSB0ZXh0ID0gW107XG5cbiAgICAvLyBtYWtlIHN1cmUgc2hvd2luZyB0aWNrcyBkb2Vzbid0IGFjY2lkZW50YWxseSBhZGQgbmV3IGNhdGVnb3JpZXNcbiAgICAvLyBUT0RPIG11bHRpY2F0ZWdvcnksIGlmIHdlIGFsbG93IHRpY2t0ZXh0IC8gdGlja3ZhbHNcbiAgICB2YXIgdGlja1ZhbDJsID0gYXgudHlwZSA9PT0gJ2NhdGVnb3J5JyA/IGF4LmQybF9ub2FkZCA6IGF4LmQybDtcblxuICAgIC8vIGFycmF5IHRpY2tzIG9uIGxvZyBheGVzIGFsd2F5cyBzaG93IHRoZSBmdWxsIG51bWJlclxuICAgIC8vIChpZiBubyBleHBsaWNpdCB0aWNrdGV4dCBvdmVycmlkZXMgaXQpXG4gICAgaWYoYXgudHlwZSA9PT0gJ2xvZycgJiYgU3RyaW5nKGF4LmR0aWNrKS5jaGFyQXQoMCkgIT09ICdMJykge1xuICAgICAgICBheC5kdGljayA9ICdMJyArIE1hdGgucG93KDEwLCBNYXRoLmZsb29yKE1hdGgubWluKGF4LnJhbmdlWzBdLCBheC5yYW5nZVsxXSkpIC0gMSk7XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHZhbHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHZhbGkgPSB0aWNrVmFsMmwodmFsc1tpXSk7XG4gICAgICAgIGlmKHZhbGkgPiB0aWNrTWluICYmIHZhbGkgPCB0aWNrTWF4KSB7XG4gICAgICAgICAgICBpZih0ZXh0W2ldID09PSB1bmRlZmluZWQpIHRpY2tzT3V0W2pdID0gYXhlcy50aWNrVGV4dChheCwgdmFsaSk7XG4gICAgICAgICAgICBlbHNlIHRpY2tzT3V0W2pdID0gdGlja1RleHRPYmooYXgsIHZhbGksIFN0cmluZyh0ZXh0W2ldKSk7XG4gICAgICAgICAgICBqKys7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihqIDwgdmFscy5sZW5ndGgpIHRpY2tzT3V0LnNwbGljZShqLCB2YWxzLmxlbmd0aCAtIGopO1xuXG4gICAgcmV0dXJuIHRpY2tzT3V0O1xufVxuXG52YXIgcm91bmRCYXNlMTAgPSBbMiwgNSwgMTBdO1xudmFyIHJvdW5kQmFzZTI0ID0gWzEsIDIsIDMsIDYsIDEyXTtcbnZhciByb3VuZEJhc2U2MCA9IFsxLCAyLCA1LCAxMCwgMTUsIDMwXTtcbi8vIDImMyBkYXkgdGlja3MgYXJlIHdlaXJkLCBidXQgbmVlZCBzb21ldGhpbmcgYnR3biAxJjdcbnZhciByb3VuZERheXMgPSBbMSwgMiwgMywgNywgMTRdO1xuLy8gYXBwcm94LiB0aWNrIHBvc2l0aW9ucyBmb3IgbG9nIGF4ZXMsIHNob3dpbmcgYWxsICgxKSBhbmQganVzdCAxLCAyLCA1ICgyKVxuLy8gdGhlc2UgZG9uJ3QgaGF2ZSB0byBiZSBleGFjdCwganVzdCBjbG9zZSBlbm91Z2ggdG8gcm91bmQgdG8gdGhlIHJpZ2h0IHZhbHVlXG52YXIgcm91bmRMb2cxID0gWy0wLjA0NiwgMCwgMC4zMDEsIDAuNDc3LCAwLjYwMiwgMC42OTksIDAuNzc4LCAwLjg0NSwgMC45MDMsIDAuOTU0LCAxXTtcbnZhciByb3VuZExvZzIgPSBbLTAuMzAxLCAwLCAwLjMwMSwgMC42OTksIDFdO1xuLy8gTi5CLiBgdGhldGF1bml0OyAncmFkaWFucycgYW5ndWxhciBheGVzIG11c3QgYmUgY29udmVydGVkIHRvIGRlZ3JlZXNcbnZhciByb3VuZEFuZ2xlcyA9IFsxNSwgMzAsIDQ1LCA5MCwgMTgwXTtcblxuZnVuY3Rpb24gcm91bmREVGljayhyb3VnaERUaWNrLCBiYXNlLCByb3VuZGluZ1NldCkge1xuICAgIHJldHVybiBiYXNlICogTGliLnJvdW5kVXAocm91Z2hEVGljayAvIGJhc2UsIHJvdW5kaW5nU2V0KTtcbn1cblxuLy8gYXV0b1RpY2tzOiBjYWxjdWxhdGUgYmVzdCBndWVzcyBhdCBwbGVhc2FudCB0aWNrcyBmb3IgdGhpcyBheGlzXG4vLyBpbnB1dHM6XG4vLyAgICAgIGF4IC0gYW4gYXhpcyBvYmplY3Rcbi8vICAgICAgcm91Z2hEVGljayAtIHJvdWdoIHRpY2sgc3BhY2luZyAodG8gYmUgdHVybmVkIGludG8gYSBuaWNlIHJvdW5kIG51bWJlcilcbi8vIG91dHB1dHMgKGludG8gYXgpOlxuLy8gICB0aWNrMDogc3RhcnRpbmcgcG9pbnQgZm9yIHRpY2tzIChub3QgbmVjZXNzYXJpbHkgb24gdGhlIGdyYXBoKVxuLy8gICAgICB1c3VhbGx5IDAgZm9yIG51bWVyaWMgKD0xMF4wPTEgZm9yIGxvZykgb3IgamFuIDEsIDIwMDAgZm9yIGRhdGVzXG4vLyAgIGR0aWNrOiB0aGUgYWN0dWFsLCBuaWNlIHJvdW5kIHRpY2sgc3BhY2luZywgdXN1YWxseSBhIGxpdHRsZSBsYXJnZXIgdGhhbiByb3VnaERUaWNrXG4vLyAgICAgIGlmIHRoZSB0aWNrcyBhcmUgc3BhY2VkIGxpbmVhcmx5IChsaW5lYXIgc2NhbGUsIGNhdGVnb3JpZXMsXG4vLyAgICAgICAgICBsb2cgd2l0aCBvbmx5IGZ1bGwgcG93ZXJzLCBkYXRlIHRpY2tzIDwgbW9udGgpLFxuLy8gICAgICAgICAgdGhpcyB3aWxsIGp1c3QgYmUgYSBudW1iZXJcbi8vICAgICAgbW9udGhzOiBNI1xuLy8gICAgICB5ZWFyczogTSMgd2hlcmUgIyBpcyAxMipudW1iZXIgb2YgeWVhcnNcbi8vICAgICAgbG9nIHdpdGggbGluZWFyIHRpY2tzOiBMIyB3aGVyZSAjIGlzIHRoZSBsaW5lYXIgdGljayBzcGFjaW5nXG4vLyAgICAgIGxvZyBzaG93aW5nIHBvd2VycyBwbHVzIHNvbWUgaW50ZXJtZWRpYXRlczpcbi8vICAgICAgICAgIEQxIHNob3dzIGFsbCBkaWdpdHMsIEQyIHNob3dzIDIgYW5kIDVcbmF4ZXMuYXV0b1RpY2tzID0gZnVuY3Rpb24oYXgsIHJvdWdoRFRpY2spIHtcbiAgICB2YXIgYmFzZTtcblxuICAgIGZ1bmN0aW9uIGdldEJhc2Uodikge1xuICAgICAgICByZXR1cm4gTWF0aC5wb3codiwgTWF0aC5mbG9vcihNYXRoLmxvZyhyb3VnaERUaWNrKSAvIE1hdGguTE4xMCkpO1xuICAgIH1cblxuICAgIGlmKGF4LnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICBheC50aWNrMCA9IExpYi5kYXRlVGljazAoYXguY2FsZW5kYXIpO1xuICAgICAgICAvLyB0aGUgY3JpdGVyaWEgYmVsb3cgYXJlIGFsbCBiYXNlZCBvbiB0aGUgcm91Z2ggc3BhY2luZyB3ZSBjYWxjdWxhdGVcbiAgICAgICAgLy8gYmVpbmcgPiBoYWxmIG9mIHRoZSBmaW5hbCB1bml0IC0gc28gcHJlY2FsY3VsYXRlIHR3aWNlIHRoZSByb3VnaCB2YWxcbiAgICAgICAgdmFyIHJvdWdoWDIgPSAyICogcm91Z2hEVGljaztcblxuICAgICAgICBpZihyb3VnaFgyID4gT05FQVZHWUVBUikge1xuICAgICAgICAgICAgcm91Z2hEVGljayAvPSBPTkVBVkdZRUFSO1xuICAgICAgICAgICAgYmFzZSA9IGdldEJhc2UoMTApO1xuICAgICAgICAgICAgYXguZHRpY2sgPSAnTScgKyAoMTIgKiByb3VuZERUaWNrKHJvdWdoRFRpY2ssIGJhc2UsIHJvdW5kQmFzZTEwKSk7XG4gICAgICAgIH0gZWxzZSBpZihyb3VnaFgyID4gT05FQVZHTU9OVEgpIHtcbiAgICAgICAgICAgIHJvdWdoRFRpY2sgLz0gT05FQVZHTU9OVEg7XG4gICAgICAgICAgICBheC5kdGljayA9ICdNJyArIHJvdW5kRFRpY2socm91Z2hEVGljaywgMSwgcm91bmRCYXNlMjQpO1xuICAgICAgICB9IGVsc2UgaWYocm91Z2hYMiA+IE9ORURBWSkge1xuICAgICAgICAgICAgYXguZHRpY2sgPSByb3VuZERUaWNrKHJvdWdoRFRpY2ssIE9ORURBWSwgcm91bmREYXlzKTtcbiAgICAgICAgICAgIC8vIGdldCB3ZWVrIHRpY2tzIG9uIHN1bmRheVxuICAgICAgICAgICAgLy8gdGhpcyB3aWxsIGFsc28gbW92ZSB0aGUgYmFzZSB0aWNrIG9mZiAyMDAwLTAxLTAxIGlmIGR0aWNrIGlzXG4gICAgICAgICAgICAvLyAyIG9yIDMgZGF5cy4uLiBidXQgdGhhdCdzIGEgd2VpcmQgZW5vdWdoIGNhc2UgdGhhdCB3ZSdsbCBpZ25vcmUgaXQuXG4gICAgICAgICAgICBheC50aWNrMCA9IExpYi5kYXRlVGljazAoYXguY2FsZW5kYXIsIHRydWUpO1xuICAgICAgICB9IGVsc2UgaWYocm91Z2hYMiA+IE9ORUhPVVIpIHtcbiAgICAgICAgICAgIGF4LmR0aWNrID0gcm91bmREVGljayhyb3VnaERUaWNrLCBPTkVIT1VSLCByb3VuZEJhc2UyNCk7XG4gICAgICAgIH0gZWxzZSBpZihyb3VnaFgyID4gT05FTUlOKSB7XG4gICAgICAgICAgICBheC5kdGljayA9IHJvdW5kRFRpY2socm91Z2hEVGljaywgT05FTUlOLCByb3VuZEJhc2U2MCk7XG4gICAgICAgIH0gZWxzZSBpZihyb3VnaFgyID4gT05FU0VDKSB7XG4gICAgICAgICAgICBheC5kdGljayA9IHJvdW5kRFRpY2socm91Z2hEVGljaywgT05FU0VDLCByb3VuZEJhc2U2MCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBtaWxsaXNlY29uZHNcbiAgICAgICAgICAgIGJhc2UgPSBnZXRCYXNlKDEwKTtcbiAgICAgICAgICAgIGF4LmR0aWNrID0gcm91bmREVGljayhyb3VnaERUaWNrLCBiYXNlLCByb3VuZEJhc2UxMCk7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYoYXgudHlwZSA9PT0gJ2xvZycpIHtcbiAgICAgICAgYXgudGljazAgPSAwO1xuICAgICAgICB2YXIgcm5nID0gTGliLnNpbXBsZU1hcChheC5yYW5nZSwgYXgucjJsKTtcblxuICAgICAgICBpZihyb3VnaERUaWNrID4gMC43KSB7XG4gICAgICAgICAgICAvLyBvbmx5IHNob3cgcG93ZXJzIG9mIDEwXG4gICAgICAgICAgICBheC5kdGljayA9IE1hdGguY2VpbChyb3VnaERUaWNrKTtcbiAgICAgICAgfSBlbHNlIGlmKE1hdGguYWJzKHJuZ1sxXSAtIHJuZ1swXSkgPCAxKSB7XG4gICAgICAgICAgICAvLyBzcGFuIGlzIGxlc3MgdGhhbiBvbmUgcG93ZXIgb2YgMTBcbiAgICAgICAgICAgIHZhciBudCA9IDEuNSAqIE1hdGguYWJzKChybmdbMV0gLSBybmdbMF0pIC8gcm91Z2hEVGljayk7XG5cbiAgICAgICAgICAgIC8vIHRpY2tzIG9uIGEgbGluZWFyIHNjYWxlLCBsYWJlbGVkIGZ1bGx5XG4gICAgICAgICAgICByb3VnaERUaWNrID0gTWF0aC5hYnMoTWF0aC5wb3coMTAsIHJuZ1sxXSkgLVxuICAgICAgICAgICAgICAgIE1hdGgucG93KDEwLCBybmdbMF0pKSAvIG50O1xuICAgICAgICAgICAgYmFzZSA9IGdldEJhc2UoMTApO1xuICAgICAgICAgICAgYXguZHRpY2sgPSAnTCcgKyByb3VuZERUaWNrKHJvdWdoRFRpY2ssIGJhc2UsIHJvdW5kQmFzZTEwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGluY2x1ZGUgaW50ZXJtZWRpYXRlcyBiZXR3ZWVuIHBvd2VycyBvZiAxMCxcbiAgICAgICAgICAgIC8vIGxhYmVsZWQgd2l0aCBzbWFsbCBkaWdpdHNcbiAgICAgICAgICAgIC8vIGF4LmR0aWNrID0gXCJEMlwiIChzaG93IDIgYW5kIDUpIG9yIFwiRDFcIiAoc2hvdyBhbGwgZGlnaXRzKVxuICAgICAgICAgICAgYXguZHRpY2sgPSAocm91Z2hEVGljayA+IDAuMykgPyAnRDInIDogJ0QxJztcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZihheC50eXBlID09PSAnY2F0ZWdvcnknIHx8IGF4LnR5cGUgPT09ICdtdWx0aWNhdGVnb3J5Jykge1xuICAgICAgICBheC50aWNrMCA9IDA7XG4gICAgICAgIGF4LmR0aWNrID0gTWF0aC5jZWlsKE1hdGgubWF4KHJvdWdoRFRpY2ssIDEpKTtcbiAgICB9IGVsc2UgaWYoaXNBbmd1bGFyKGF4KSkge1xuICAgICAgICBheC50aWNrMCA9IDA7XG4gICAgICAgIGJhc2UgPSAxO1xuICAgICAgICBheC5kdGljayA9IHJvdW5kRFRpY2socm91Z2hEVGljaywgYmFzZSwgcm91bmRBbmdsZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGF1dG8gdGlja3MgYWx3YXlzIHN0YXJ0IGF0IDBcbiAgICAgICAgYXgudGljazAgPSAwO1xuICAgICAgICBiYXNlID0gZ2V0QmFzZSgxMCk7XG4gICAgICAgIGF4LmR0aWNrID0gcm91bmREVGljayhyb3VnaERUaWNrLCBiYXNlLCByb3VuZEJhc2UxMCk7XG4gICAgfVxuXG4gICAgLy8gcHJldmVudCBpbmZpbml0ZSBsb29wc1xuICAgIGlmKGF4LmR0aWNrID09PSAwKSBheC5kdGljayA9IDE7XG5cbiAgICAvLyBUT0RPOiB0aGlzIGlzIGZyb20gbG9nIGF4aXMgaGlzdG9ncmFtcyB3aXRoIGF1dG9yYW5nZSBvZmZcbiAgICBpZighaXNOdW1lcmljKGF4LmR0aWNrKSAmJiB0eXBlb2YgYXguZHRpY2sgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHZhciBvbGRkdGljayA9IGF4LmR0aWNrO1xuICAgICAgICBheC5kdGljayA9IDE7XG4gICAgICAgIHRocm93ICdheC5kdGljayBlcnJvcjogJyArIFN0cmluZyhvbGRkdGljayk7XG4gICAgfVxufTtcblxuLy8gYWZ0ZXIgZHRpY2sgaXMgYWxyZWFkeSBrbm93biwgZmluZCB0aWNrcm91bmQgPSBwcmVjaXNpb25cbi8vIHRvIGRpc3BsYXkgaW4gdGljayBsYWJlbHNcbi8vICAgZm9yIG51bWVyaWMgdGlja3MsIGludGVnZXIgIyBkaWdpdHMgYWZ0ZXIgLiB0byByb3VuZCB0b1xuLy8gICBmb3IgZGF0ZSB0aWNrcywgdGhlIGxhc3QgZGF0ZSBwYXJ0IHRvIHNob3cgKHksbSxkLEgsTSxTKVxuLy8gICAgICBvciBhbiBpbnRlZ2VyICMgZGlnaXRzIHBhc3Qgc2Vjb25kc1xuZnVuY3Rpb24gYXV0b1RpY2tSb3VuZChheCkge1xuICAgIHZhciBkdGljayA9IGF4LmR0aWNrO1xuXG4gICAgYXguX3RpY2tleHBvbmVudCA9IDA7XG4gICAgaWYoIWlzTnVtZXJpYyhkdGljaykgJiYgdHlwZW9mIGR0aWNrICE9PSAnc3RyaW5nJykge1xuICAgICAgICBkdGljayA9IDE7XG4gICAgfVxuXG4gICAgaWYoYXgudHlwZSA9PT0gJ2NhdGVnb3J5JyB8fCBheC50eXBlID09PSAnbXVsdGljYXRlZ29yeScpIHtcbiAgICAgICAgYXguX3RpY2tyb3VuZCA9IG51bGw7XG4gICAgfVxuICAgIGlmKGF4LnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICAvLyBJZiB0aWNrMCBpcyB1bnVzdWFsLCBnaXZlIHRpY2tyb3VuZCBhIGJpdCBtb3JlIGluZm9ybWF0aW9uXG4gICAgICAgIC8vIG5vdCBuZWNlc3NhcmlseSAqYWxsKiB0aGUgaW5mb3JtYXRpb24gaW4gdGljazAgdGhvdWdoLCBpZiBpdCdzIHJlYWxseSBvZGRcbiAgICAgICAgLy8gbWluaW1hbCBzdHJpbmcgbGVuZ3RoIGZvciB0aWNrMDogJ2QnIGlzIDEwLCAnTScgaXMgMTYsICdTJyBpcyAxOVxuICAgICAgICAvLyB0YWtlIG9mZiBhIGxlYWRpbmcgbWludXMgKHllYXIgPCAwKSBhbmQgaSAoaW50ZXJjYWxhcnkgbW9udGgpIHNvIGxlbmd0aCBpcyBjb25zaXN0ZW50XG4gICAgICAgIHZhciB0aWNrMG1zID0gYXgucjJsKGF4LnRpY2swKTtcbiAgICAgICAgdmFyIHRpY2swc3RyID0gYXgubDJyKHRpY2swbXMpLnJlcGxhY2UoLyheLXxpKS9nLCAnJyk7XG4gICAgICAgIHZhciB0aWNrMGxlbiA9IHRpY2swc3RyLmxlbmd0aDtcblxuICAgICAgICBpZihTdHJpbmcoZHRpY2spLmNoYXJBdCgwKSA9PT0gJ00nKSB7XG4gICAgICAgICAgICAvLyBhbnkgdGljazAgbW9yZSBzcGVjaWZpYyB0aGFuIGEgeWVhcjogYWx3YXkgc2hvdyB0aGUgZnVsbCBkYXRlXG4gICAgICAgICAgICBpZih0aWNrMGxlbiA+IDEwIHx8IHRpY2swc3RyLnN1YnN0cig1KSAhPT0gJzAxLTAxJykgYXguX3RpY2tyb3VuZCA9ICdkJztcbiAgICAgICAgICAgIC8vIHNob3cgdGhlIG1vbnRoIHVubGVzcyB0aWNrcyBhcmUgZnVsbCBtdWx0aXBsZXMgb2YgYSB5ZWFyXG4gICAgICAgICAgICBlbHNlIGF4Ll90aWNrcm91bmQgPSAoKyhkdGljay5zdWJzdHIoMSkpICUgMTIgPT09IDApID8gJ3knIDogJ20nO1xuICAgICAgICB9IGVsc2UgaWYoKGR0aWNrID49IE9ORURBWSAmJiB0aWNrMGxlbiA8PSAxMCkgfHwgKGR0aWNrID49IE9ORURBWSAqIDE1KSkgYXguX3RpY2tyb3VuZCA9ICdkJztcbiAgICAgICAgZWxzZSBpZigoZHRpY2sgPj0gT05FTUlOICYmIHRpY2swbGVuIDw9IDE2KSB8fCAoZHRpY2sgPj0gT05FSE9VUikpIGF4Ll90aWNrcm91bmQgPSAnTSc7XG4gICAgICAgIGVsc2UgaWYoKGR0aWNrID49IE9ORVNFQyAmJiB0aWNrMGxlbiA8PSAxOSkgfHwgKGR0aWNrID49IE9ORU1JTikpIGF4Ll90aWNrcm91bmQgPSAnUyc7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gdGlja3JvdW5kIGlzIGEgbnVtYmVyIG9mIGRpZ2l0cyBvZiBmcmFjdGlvbmFsIHNlY29uZHNcbiAgICAgICAgICAgIC8vIG9mIGFueSB0d28gYWRqYWNlbnQgdGlja3MsIGF0IGxlYXN0IG9uZSB3aWxsIGhhdmUgdGhlIG1heGltdW0gZnJhY3Rpb25hbCBkaWdpdHNcbiAgICAgICAgICAgIC8vIG9mIGFsbCBwb3NzaWJsZSB0aWNrcyAtIHNvIHRha2UgdGhlIG1heC4gbGVuZ3RoIG9mIHRpY2swIGFuZCB0aGUgbmV4dCBvbmVcbiAgICAgICAgICAgIHZhciB0aWNrMWxlbiA9IGF4Lmwycih0aWNrMG1zICsgZHRpY2spLnJlcGxhY2UoL14tLywgJycpLmxlbmd0aDtcbiAgICAgICAgICAgIGF4Ll90aWNrcm91bmQgPSBNYXRoLm1heCh0aWNrMGxlbiwgdGljazFsZW4pIC0gMjA7XG5cbiAgICAgICAgICAgIC8vIFdlIHNob3VsZG4ndCBnZXQgaGVyZS4uLiBidXQgaW4gY2FzZSB0aGVyZSdzIGEgc2l0dWF0aW9uIEknbVxuICAgICAgICAgICAgLy8gbm90IHRoaW5raW5nIG9mIHdoZXJlIHRpY2swc3RyIGFuZCB0aWNrMXN0ciBhcmUgaWRlbnRpY2FsIG9yXG4gICAgICAgICAgICAvLyBzb21ldGhpbmcsIGZhbGwgYmFjayBvbiBtYXhpbXVtIHByZWNpc2lvblxuICAgICAgICAgICAgaWYoYXguX3RpY2tyb3VuZCA8IDApIGF4Ll90aWNrcm91bmQgPSA0O1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKGlzTnVtZXJpYyhkdGljaykgfHwgZHRpY2suY2hhckF0KDApID09PSAnTCcpIHtcbiAgICAgICAgLy8gbGluZWFyIG9yIGxvZyAoZXhjZXB0IEQxLCBEMilcbiAgICAgICAgdmFyIHJuZyA9IGF4LnJhbmdlLm1hcChheC5yMmQgfHwgTnVtYmVyKTtcbiAgICAgICAgaWYoIWlzTnVtZXJpYyhkdGljaykpIGR0aWNrID0gTnVtYmVyKGR0aWNrLnN1YnN0cigxKSk7XG4gICAgICAgIC8vIDIgZGlnaXRzIHBhc3QgbGFyZ2VzdCBkaWdpdCBvZiBkdGlja1xuICAgICAgICBheC5fdGlja3JvdW5kID0gMiAtIE1hdGguZmxvb3IoTWF0aC5sb2coZHRpY2spIC8gTWF0aC5MTjEwICsgMC4wMSk7XG5cbiAgICAgICAgdmFyIG1heGVuZCA9IE1hdGgubWF4KE1hdGguYWJzKHJuZ1swXSksIE1hdGguYWJzKHJuZ1sxXSkpO1xuICAgICAgICB2YXIgcmFuZ2VleHAgPSBNYXRoLmZsb29yKE1hdGgubG9nKG1heGVuZCkgLyBNYXRoLkxOMTAgKyAwLjAxKTtcbiAgICAgICAgaWYoTWF0aC5hYnMocmFuZ2VleHApID4gMykge1xuICAgICAgICAgICAgaWYoaXNTSUZvcm1hdChheC5leHBvbmVudGZvcm1hdCkgJiYgIWJleW9uZFNJKHJhbmdlZXhwKSkge1xuICAgICAgICAgICAgICAgIGF4Ll90aWNrZXhwb25lbnQgPSAzICogTWF0aC5yb3VuZCgocmFuZ2VleHAgLSAxKSAvIDMpO1xuICAgICAgICAgICAgfSBlbHNlIGF4Ll90aWNrZXhwb25lbnQgPSByYW5nZWV4cDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEQxIG9yIEQyIChsb2cpXG4gICAgICAgIGF4Ll90aWNrcm91bmQgPSBudWxsO1xuICAgIH1cbn1cblxuLy8gbW9udGhzIGFuZCB5ZWFycyBkb24ndCBoYXZlIGNvbnN0YW50IG1pbGxpc2Vjb25kIHZhbHVlc1xuLy8gKGJ1dCBhIHllYXIgaXMgYWx3YXlzIDEyIG1vbnRocyBzbyB3ZSBvbmx5IG5lZWQgbW9udGhzKVxuLy8gbG9nLXNjYWxlIHRpY2tzIGFyZSBhbHNvIG5vdCBjb25zaXN0ZW50bHkgc3BhY2VkLCBleGNlcHRcbi8vIGZvciBwdXJlIHBvd2VycyBvZiAxMFxuLy8gbnVtZXJpYyB0aWNrcyBhbHdheXMgaGF2ZSBjb25zdGFudCBkaWZmZXJlbmNlcywgb3RoZXIgZGF0ZXRpbWUgdGlja3Ncbi8vIGNhbiBhbGwgYmUgY2FsY3VsYXRlZCBhcyBjb25zdGFudCBudW1iZXIgb2YgbWlsbGlzZWNvbmRzXG5heGVzLnRpY2tJbmNyZW1lbnQgPSBmdW5jdGlvbih4LCBkdGljaywgYXhyZXYsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGF4U2lnbiA9IGF4cmV2ID8gLTEgOiAxO1xuXG4gICAgLy8gaW5jbHVkZXMgbGluZWFyLCBhbGwgZGF0ZXMgc21hbGxlciB0aGFuIG1vbnRoLCBhbmQgcHVyZSAxMF5uIGluIGxvZ1xuICAgIGlmKGlzTnVtZXJpYyhkdGljaykpIHJldHVybiB4ICsgYXhTaWduICogZHRpY2s7XG5cbiAgICAvLyBldmVyeXRoaW5nIGVsc2UgaXMgYSBzdHJpbmcsIG9uZSBjaGFyYWN0ZXIgcGx1cyBhIG51bWJlclxuICAgIHZhciB0VHlwZSA9IGR0aWNrLmNoYXJBdCgwKTtcbiAgICB2YXIgZHRTaWduZWQgPSBheFNpZ24gKiBOdW1iZXIoZHRpY2suc3Vic3RyKDEpKTtcblxuICAgIC8vIERhdGVzOiBtb250aHMgKG9yIHllYXJzIC0gc2VlIExpYi5pbmNyZW1lbnRNb250aClcbiAgICBpZih0VHlwZSA9PT0gJ00nKSByZXR1cm4gTGliLmluY3JlbWVudE1vbnRoKHgsIGR0U2lnbmVkLCBjYWxlbmRhcik7XG5cbiAgICAvLyBMb2cgc2NhbGVzOiBMaW5lYXIsIERpZ2l0c1xuICAgIGVsc2UgaWYodFR5cGUgPT09ICdMJykgcmV0dXJuIE1hdGgubG9nKE1hdGgucG93KDEwLCB4KSArIGR0U2lnbmVkKSAvIE1hdGguTE4xMDtcblxuICAgIC8vIGxvZzEwIG9mIDIsNSwxMCwgb3IgYWxsIGRpZ2l0cyAobG9ncyBqdXN0IGhhdmUgdG8gYmVcbiAgICAvLyBjbG9zZSBlbm91Z2ggdG8gcm91bmQpXG4gICAgZWxzZSBpZih0VHlwZSA9PT0gJ0QnKSB7XG4gICAgICAgIHZhciB0aWNrc2V0ID0gKGR0aWNrID09PSAnRDInKSA/IHJvdW5kTG9nMiA6IHJvdW5kTG9nMTtcbiAgICAgICAgdmFyIHgyID0geCArIGF4U2lnbiAqIDAuMDE7XG4gICAgICAgIHZhciBmcmFjID0gTGliLnJvdW5kVXAoTGliLm1vZCh4MiwgMSksIHRpY2tzZXQsIGF4cmV2KTtcblxuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcih4MikgK1xuICAgICAgICAgICAgTWF0aC5sb2coZDMucm91bmQoTWF0aC5wb3coMTAsIGZyYWMpLCAxKSkgLyBNYXRoLkxOMTA7XG4gICAgfSBlbHNlIHRocm93ICd1bnJlY29nbml6ZWQgZHRpY2sgJyArIFN0cmluZyhkdGljayk7XG59O1xuXG4vLyBjYWxjdWxhdGUgdGhlIGZpcnN0IHRpY2sgb24gYW4gYXhpc1xuYXhlcy50aWNrRmlyc3QgPSBmdW5jdGlvbihheCkge1xuICAgIHZhciByMmwgPSBheC5yMmwgfHwgTnVtYmVyO1xuICAgIHZhciBybmcgPSBMaWIuc2ltcGxlTWFwKGF4LnJhbmdlLCByMmwpO1xuICAgIHZhciBheHJldiA9IHJuZ1sxXSA8IHJuZ1swXTtcbiAgICB2YXIgc1JvdW5kID0gYXhyZXYgPyBNYXRoLmZsb29yIDogTWF0aC5jZWlsO1xuICAgIC8vIGFkZCBhIHRpbnkgZXh0cmEgYml0IHRvIG1ha2Ugc3VyZSB3ZSBnZXQgdGlja3NcbiAgICAvLyB0aGF0IG1heSBoYXZlIGJlZW4gcm91bmRlZCBvdXRcbiAgICB2YXIgcjAgPSBybmdbMF0gKiAxLjAwMDEgLSBybmdbMV0gKiAwLjAwMDE7XG4gICAgdmFyIGR0aWNrID0gYXguZHRpY2s7XG4gICAgdmFyIHRpY2swID0gcjJsKGF4LnRpY2swKTtcblxuICAgIGlmKGlzTnVtZXJpYyhkdGljaykpIHtcbiAgICAgICAgdmFyIHRtaW4gPSBzUm91bmQoKHIwIC0gdGljazApIC8gZHRpY2spICogZHRpY2sgKyB0aWNrMDtcblxuICAgICAgICAvLyBtYWtlIHN1cmUgbm8gdGlja3Mgb3V0c2lkZSB0aGUgY2F0ZWdvcnkgbGlzdFxuICAgICAgICBpZihheC50eXBlID09PSAnY2F0ZWdvcnknIHx8IGF4LnR5cGUgPT09ICdtdWx0aWNhdGVnb3J5Jykge1xuICAgICAgICAgICAgdG1pbiA9IExpYi5jb25zdHJhaW4odG1pbiwgMCwgYXguX2NhdGVnb3JpZXMubGVuZ3RoIC0gMSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRtaW47XG4gICAgfVxuXG4gICAgdmFyIHRUeXBlID0gZHRpY2suY2hhckF0KDApO1xuICAgIHZhciBkdE51bSA9IE51bWJlcihkdGljay5zdWJzdHIoMSkpO1xuXG4gICAgLy8gRGF0ZXM6IG1vbnRocyAob3IgeWVhcnMpXG4gICAgaWYodFR5cGUgPT09ICdNJykge1xuICAgICAgICB2YXIgY250ID0gMDtcbiAgICAgICAgdmFyIHQwID0gdGljazA7XG4gICAgICAgIHZhciB0MSwgbXVsdCwgbmV3RFRpY2s7XG5cbiAgICAgICAgLy8gVGhpcyBhbGdvcml0aG0gc2hvdWxkIHdvcmsgZm9yICphbnkqIG5vbmxpbmVhciAoYnV0IGNsb3NlIHRvIGxpbmVhciEpXG4gICAgICAgIC8vIHRpY2sgc3BhY2luZy4gTGltaXQgdG8gMTAgaXRlcmF0aW9ucywgZm9yIGdyZWdvcmlhbiBtb250aHMgaXQncyBub3JtYWxseSA8PTMuXG4gICAgICAgIHdoaWxlKGNudCA8IDEwKSB7XG4gICAgICAgICAgICB0MSA9IGF4ZXMudGlja0luY3JlbWVudCh0MCwgZHRpY2ssIGF4cmV2LCBheC5jYWxlbmRhcik7XG4gICAgICAgICAgICBpZigodDEgLSByMCkgKiAodDAgLSByMCkgPD0gMCkge1xuICAgICAgICAgICAgICAgIC8vIHQxIGFuZCB0MCBhcmUgb24gb3Bwb3NpdGUgc2lkZXMgb2YgcjAhIHdlJ3ZlIHN1Y2NlZWRlZCFcbiAgICAgICAgICAgICAgICBpZihheHJldikgcmV0dXJuIE1hdGgubWluKHQwLCB0MSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE1hdGgubWF4KHQwLCB0MSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtdWx0ID0gKHIwIC0gKCh0MCArIHQxKSAvIDIpKSAvICh0MSAtIHQwKTtcbiAgICAgICAgICAgIG5ld0RUaWNrID0gdFR5cGUgKyAoKE1hdGguYWJzKE1hdGgucm91bmQobXVsdCkpIHx8IDEpICogZHROdW0pO1xuICAgICAgICAgICAgdDAgPSBheGVzLnRpY2tJbmNyZW1lbnQodDAsIG5ld0RUaWNrLCBtdWx0IDwgMCA/ICFheHJldiA6IGF4cmV2LCBheC5jYWxlbmRhcik7XG4gICAgICAgICAgICBjbnQrKztcbiAgICAgICAgfVxuICAgICAgICBMaWIuZXJyb3IoJ3RpY2tGaXJzdCBkaWQgbm90IGNvbnZlcmdlJywgYXgpO1xuICAgICAgICByZXR1cm4gdDA7XG4gICAgfSBlbHNlIGlmKHRUeXBlID09PSAnTCcpIHtcbiAgICAgICAgLy8gTG9nIHNjYWxlczogTGluZWFyLCBEaWdpdHNcblxuICAgICAgICByZXR1cm4gTWF0aC5sb2coc1JvdW5kKFxuICAgICAgICAgICAgKE1hdGgucG93KDEwLCByMCkgLSB0aWNrMCkgLyBkdE51bSkgKiBkdE51bSArIHRpY2swKSAvIE1hdGguTE4xMDtcbiAgICB9IGVsc2UgaWYodFR5cGUgPT09ICdEJykge1xuICAgICAgICB2YXIgdGlja3NldCA9IChkdGljayA9PT0gJ0QyJykgPyByb3VuZExvZzIgOiByb3VuZExvZzE7XG4gICAgICAgIHZhciBmcmFjID0gTGliLnJvdW5kVXAoTGliLm1vZChyMCwgMSksIHRpY2tzZXQsIGF4cmV2KTtcblxuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihyMCkgK1xuICAgICAgICAgICAgTWF0aC5sb2coZDMucm91bmQoTWF0aC5wb3coMTAsIGZyYWMpLCAxKSkgLyBNYXRoLkxOMTA7XG4gICAgfSBlbHNlIHRocm93ICd1bnJlY29nbml6ZWQgZHRpY2sgJyArIFN0cmluZyhkdGljayk7XG59O1xuXG4vLyBkcmF3IHRoZSB0ZXh0IGZvciBvbmUgdGljay5cbi8vIHB4LHB5IGFyZSB0aGUgbG9jYXRpb24gb24gZ2QucGFwZXJcbi8vIHByZWZpeCBpcyB0aGVyZSBzbyB0aGUgeCBheGlzIHRpY2tzIGNhbiBiZSBkcm9wcGVkIGEgbGluZVxuLy8gYXggaXMgdGhlIGF4aXMgbGF5b3V0LCB4IGlzIHRoZSB0aWNrIHZhbHVlXG4vLyBob3ZlciBpcyBhICh0cnV0aHkpIGZsYWcgZm9yIHdoZXRoZXIgdG8gc2hvdyBudW1iZXJzIHdpdGggYSBiaXRcbi8vIG1vcmUgcHJlY2lzaW9uIGZvciBob3ZlcnRleHRcbmF4ZXMudGlja1RleHQgPSBmdW5jdGlvbihheCwgeCwgaG92ZXIsIG5vU3VmZml4UHJlZml4KSB7XG4gICAgdmFyIG91dCA9IHRpY2tUZXh0T2JqKGF4LCB4KTtcbiAgICB2YXIgYXJyYXlNb2RlID0gYXgudGlja21vZGUgPT09ICdhcnJheSc7XG4gICAgdmFyIGV4dHJhUHJlY2lzaW9uID0gaG92ZXIgfHwgYXJyYXlNb2RlO1xuICAgIHZhciBheFR5cGUgPSBheC50eXBlO1xuICAgIC8vIFRPRE8gbXVsdGljYXRlZ29yeSwgaWYgd2UgYWxsb3cgdGlja3RleHQgLyB0aWNrdmFsc1xuICAgIHZhciB0aWNrVmFsMmwgPSBheFR5cGUgPT09ICdjYXRlZ29yeScgPyBheC5kMmxfbm9hZGQgOiBheC5kMmw7XG4gICAgdmFyIGk7XG5cbiAgICBpZihhcnJheU1vZGUgJiYgQXJyYXkuaXNBcnJheShheC50aWNrdGV4dCkpIHtcbiAgICAgICAgdmFyIHJuZyA9IExpYi5zaW1wbGVNYXAoYXgucmFuZ2UsIGF4LnIybCk7XG4gICAgICAgIHZhciBtaW5EaWZmID0gTWF0aC5hYnMocm5nWzFdIC0gcm5nWzBdKSAvIDEwMDAwO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGF4LnRpY2t0ZXh0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihNYXRoLmFicyh4IC0gdGlja1ZhbDJsKGF4LnRpY2t2YWxzW2ldKSkgPCBtaW5EaWZmKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZihpIDwgYXgudGlja3RleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICBvdXQudGV4dCA9IFN0cmluZyhheC50aWNrdGV4dFtpXSk7XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNIaWRkZW4oc2hvd0F0dHIpIHtcbiAgICAgICAgaWYoc2hvd0F0dHIgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRydWU7XG4gICAgICAgIGlmKGhvdmVyKSByZXR1cm4gc2hvd0F0dHIgPT09ICdub25lJztcblxuICAgICAgICB2YXIgZmlyc3RPckxhc3QgPSB7XG4gICAgICAgICAgICBmaXJzdDogYXguX3RtaW4sXG4gICAgICAgICAgICBsYXN0OiBheC5fdG1heFxuICAgICAgICB9W3Nob3dBdHRyXTtcblxuICAgICAgICByZXR1cm4gc2hvd0F0dHIgIT09ICdhbGwnICYmIHggIT09IGZpcnN0T3JMYXN0O1xuICAgIH1cblxuICAgIHZhciBoaWRlZXhwID0gaG92ZXIgP1xuICAgICAgICAnbmV2ZXInIDpcbiAgICAgICAgYXguZXhwb25lbnRmb3JtYXQgIT09ICdub25lJyAmJiBpc0hpZGRlbihheC5zaG93ZXhwb25lbnQpID8gJ2hpZGUnIDogJyc7XG5cbiAgICBpZihheFR5cGUgPT09ICdkYXRlJykgZm9ybWF0RGF0ZShheCwgb3V0LCBob3ZlciwgZXh0cmFQcmVjaXNpb24pO1xuICAgIGVsc2UgaWYoYXhUeXBlID09PSAnbG9nJykgZm9ybWF0TG9nKGF4LCBvdXQsIGhvdmVyLCBleHRyYVByZWNpc2lvbiwgaGlkZWV4cCk7XG4gICAgZWxzZSBpZihheFR5cGUgPT09ICdjYXRlZ29yeScpIGZvcm1hdENhdGVnb3J5KGF4LCBvdXQpO1xuICAgIGVsc2UgaWYoYXhUeXBlID09PSAnbXVsdGljYXRlZ29yeScpIGZvcm1hdE11bHRpQ2F0ZWdvcnkoYXgsIG91dCwgaG92ZXIpO1xuICAgIGVsc2UgaWYoaXNBbmd1bGFyKGF4KSkgZm9ybWF0QW5nbGUoYXgsIG91dCwgaG92ZXIsIGV4dHJhUHJlY2lzaW9uLCBoaWRlZXhwKTtcbiAgICBlbHNlIGZvcm1hdExpbmVhcihheCwgb3V0LCBob3ZlciwgZXh0cmFQcmVjaXNpb24sIGhpZGVleHApO1xuXG4gICAgLy8gYWRkIHByZWZpeCBhbmQgc3VmZml4XG4gICAgaWYoIW5vU3VmZml4UHJlZml4KSB7XG4gICAgICAgIGlmKGF4LnRpY2twcmVmaXggJiYgIWlzSGlkZGVuKGF4LnNob3d0aWNrcHJlZml4KSkgb3V0LnRleHQgPSBheC50aWNrcHJlZml4ICsgb3V0LnRleHQ7XG4gICAgICAgIGlmKGF4LnRpY2tzdWZmaXggJiYgIWlzSGlkZGVuKGF4LnNob3d0aWNrc3VmZml4KSkgb3V0LnRleHQgKz0gYXgudGlja3N1ZmZpeDtcbiAgICB9XG5cbiAgICAvLyBTZXR1cCB0aWNrcyBhbmQgZ3JpZCBsaW5lcyBib3VuZGFyaWVzXG4gICAgLy8gYXQgMS8yIGEgJ2NhdGVnb3J5JyB0byB0aGUgbGVmdC9ib3R0b21cbiAgICBpZihheC50aWNrc29uID09PSAnYm91bmRhcmllcycgfHwgYXguc2hvd2RpdmlkZXJzKSB7XG4gICAgICAgIHZhciBpbmJvdW5kcyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHZhciBwID0gYXgubDJwKHYpO1xuICAgICAgICAgICAgcmV0dXJuIHAgPj0gMCAmJiBwIDw9IGF4Ll9sZW5ndGggPyB2IDogbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICBvdXQueGJuZCA9IFtcbiAgICAgICAgICAgIGluYm91bmRzKG91dC54IC0gMC41KSxcbiAgICAgICAgICAgIGluYm91bmRzKG91dC54ICsgYXguZHRpY2sgLSAwLjUpXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogY3JlYXRlIHRleHQgZm9yIGEgaG92ZXIgbGFiZWwgb24gdGhpcyBheGlzLCB3aXRoIHNwZWNpYWwgaGFuZGxpbmcgb2ZcbiAqIGxvZyBheGVzICh3aGVyZSBuZWdhdGl2ZSB2YWx1ZXMgY2FuJ3QgYmUgZGlzcGxheWVkIGJ1dCBjYW4gYXBwZWFyIGluIGhvdmVyIHRleHQpXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGF4OiB0aGUgYXhpcyB0byBmb3JtYXQgdGV4dCBmb3JcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWw6IGNhbGNkYXRhIHZhbHVlIHRvIGZvcm1hdFxuICogQHBhcmFtIHtPcHRpb25hbChudW1iZXIpfSB2YWwyOiBhIHNlY29uZCB2YWx1ZSB0byBkaXNwbGF5XG4gKlxuICogQHJldHVybnMge3N0cmluZ30gYHZhbGAgZm9ybWF0dGVkIGFzIGEgc3RyaW5nIGFwcHJvcHJpYXRlIHRvIHRoaXMgYXhpcywgb3JcbiAqICAgICBgdmFsYCBhbmQgYHZhbDJgIGFzIGEgcmFuZ2UgKGllICc8dmFsPiAtIDx2YWwyPicpIGlmIGB2YWwyYCBpcyBwcm92aWRlZCBhbmRcbiAqICAgICBpdCdzIGRpZmZlcmVudCBmcm9tIGB2YWxgLlxuICovXG5heGVzLmhvdmVyTGFiZWxUZXh0ID0gZnVuY3Rpb24oYXgsIHZhbCwgdmFsMikge1xuICAgIGlmKHZhbDIgIT09IEJBRE5VTSAmJiB2YWwyICE9PSB2YWwpIHtcbiAgICAgICAgcmV0dXJuIGF4ZXMuaG92ZXJMYWJlbFRleHQoYXgsIHZhbCkgKyAnIC0gJyArIGF4ZXMuaG92ZXJMYWJlbFRleHQoYXgsIHZhbDIpO1xuICAgIH1cblxuICAgIHZhciBsb2dPZmZTY2FsZSA9IChheC50eXBlID09PSAnbG9nJyAmJiB2YWwgPD0gMCk7XG4gICAgdmFyIHR4ID0gYXhlcy50aWNrVGV4dChheCwgYXguYzJsKGxvZ09mZlNjYWxlID8gLXZhbCA6IHZhbCksICdob3ZlcicpLnRleHQ7XG5cbiAgICBpZihsb2dPZmZTY2FsZSkge1xuICAgICAgICByZXR1cm4gdmFsID09PSAwID8gJzAnIDogTUlOVVNfU0lHTiArIHR4O1xuICAgIH1cblxuICAgIC8vIFRPRE86IHNob3VsZCB3ZSBkbyBzb21ldGhpbmcgc3BlY2lhbCBpZiB0aGUgYXhpcyBjYWxlbmRhciBhbmRcbiAgICAvLyB0aGUgZGF0YSBjYWxlbmRhciBhcmUgZGlmZmVyZW50PyBTb21laG93IGRpc3BsYXkgYm90aCBkYXRlcyB3aXRoXG4gICAgLy8gdGhlaXIgc3lzdGVtIG5hbWVzPyBSaWdodCBub3cgaXQgd2lsbCBqdXN0IGRpc3BsYXkgaW4gdGhlIGF4aXMgY2FsZW5kYXJcbiAgICAvLyBidXQgdXNlcnMgY291bGQgYWRkIHRoZSBvdGhlciBvbmUgYXMgdGV4dC5cbiAgICByZXR1cm4gdHg7XG59O1xuXG5mdW5jdGlvbiB0aWNrVGV4dE9iaihheCwgeCwgdGV4dCkge1xuICAgIHZhciB0ZiA9IGF4LnRpY2tmb250IHx8IHt9O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogeCxcbiAgICAgICAgZHg6IDAsXG4gICAgICAgIGR5OiAwLFxuICAgICAgICB0ZXh0OiB0ZXh0IHx8ICcnLFxuICAgICAgICBmb250U2l6ZTogdGYuc2l6ZSxcbiAgICAgICAgZm9udDogdGYuZmFtaWx5LFxuICAgICAgICBmb250Q29sb3I6IHRmLmNvbG9yXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0RGF0ZShheCwgb3V0LCBob3ZlciwgZXh0cmFQcmVjaXNpb24pIHtcbiAgICB2YXIgdHIgPSBheC5fdGlja3JvdW5kO1xuICAgIHZhciBmbXQgPSAoaG92ZXIgJiYgYXguaG92ZXJmb3JtYXQpIHx8IGF4ZXMuZ2V0VGlja0Zvcm1hdChheCk7XG5cbiAgICBpZihleHRyYVByZWNpc2lvbikge1xuICAgICAgICAvLyBzZWNvbmQgb3Igc3ViLXNlY29uZCBwcmVjaXNpb246IGV4dHJhIGFsd2F5cyBzaG93cyBtYXggZGlnaXRzLlxuICAgICAgICAvLyBmb3Igb3RoZXIgZmllbGRzLCBleHRyYSBwcmVjaXNpb24ganVzdCBhZGRzIG9uZSBmaWVsZC5cbiAgICAgICAgaWYoaXNOdW1lcmljKHRyKSkgdHIgPSA0O1xuICAgICAgICBlbHNlIHRyID0ge3k6ICdtJywgbTogJ2QnLCBkOiAnTScsIE06ICdTJywgUzogNH1bdHJdO1xuICAgIH1cblxuICAgIHZhciBkYXRlU3RyID0gTGliLmZvcm1hdERhdGUob3V0LngsIGZtdCwgdHIsIGF4Ll9kYXRlRm9ybWF0LCBheC5jYWxlbmRhciwgYXguX2V4dHJhRm9ybWF0KTtcbiAgICB2YXIgaGVhZFN0cjtcblxuICAgIHZhciBzcGxpdEluZGV4ID0gZGF0ZVN0ci5pbmRleE9mKCdcXG4nKTtcbiAgICBpZihzcGxpdEluZGV4ICE9PSAtMSkge1xuICAgICAgICBoZWFkU3RyID0gZGF0ZVN0ci5zdWJzdHIoc3BsaXRJbmRleCArIDEpO1xuICAgICAgICBkYXRlU3RyID0gZGF0ZVN0ci5zdWJzdHIoMCwgc3BsaXRJbmRleCk7XG4gICAgfVxuXG4gICAgaWYoZXh0cmFQcmVjaXNpb24pIHtcbiAgICAgICAgLy8gaWYgZXh0cmFQcmVjaXNpb24gbGVkIHRvIHRyYWlsaW5nIHplcm9zLCBzdHJpcCB0aGVtIG9mZlxuICAgICAgICAvLyBhY3R1YWxseSwgdGhpcyBjYW4gbGVhZCB0byByZW1vdmluZyBldmVuIG1vcmUgemVyb3MgdGhhblxuICAgICAgICAvLyBpbiB0aGUgb3JpZ2luYWwgcm91bmRpbmcsIGJ1dCB0aGF0J3MgZmluZSBiZWNhdXNlIGluIHRoZXNlXG4gICAgICAgIC8vIGNvbnRleHRzIHVuaWZvcm1pdHkgaXMgbm90IHNvIGltcG9ydGFudCAoaWYgdGhlcmUncyBldmVuXG4gICAgICAgIC8vIGFueXRoaW5nIHRvIGJlIHVuaWZvcm0gd2l0aCEpXG5cbiAgICAgICAgLy8gY2FuIHdlIHJlbW92ZSB0aGUgd2hvbGUgdGltZSBwYXJ0P1xuICAgICAgICBpZihkYXRlU3RyID09PSAnMDA6MDA6MDAnIHx8IGRhdGVTdHIgPT09ICcwMDowMCcpIHtcbiAgICAgICAgICAgIGRhdGVTdHIgPSBoZWFkU3RyO1xuICAgICAgICAgICAgaGVhZFN0ciA9ICcnO1xuICAgICAgICB9IGVsc2UgaWYoZGF0ZVN0ci5sZW5ndGggPT09IDgpIHtcbiAgICAgICAgICAgIC8vIHN0cmlwIG9mZiBzZWNvbmRzIGlmIHRoZXkncmUgemVybyAoemVybyBmcmFjdGlvbmFsIHNlY29uZHNcbiAgICAgICAgICAgIC8vIGFyZSBhbHJlYWR5IG9taXR0ZWQpXG4gICAgICAgICAgICAvLyBidXQgd2UgbmV2ZXIgcmVtb3ZlIG1pbnV0ZXMgYW5kIGxlYXZlIGp1c3QgaG91cnNcbiAgICAgICAgICAgIGRhdGVTdHIgPSBkYXRlU3RyLnJlcGxhY2UoLzowMCQvLCAnJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihoZWFkU3RyKSB7XG4gICAgICAgIGlmKGhvdmVyKSB7XG4gICAgICAgICAgICAvLyBob3ZlciBwdXRzIGl0IGFsbCBvbiBvbmUgbGluZSwgc28gaGVhZFBhcnQgd29ya3MgYmVzdCB1cCBmcm9udFxuICAgICAgICAgICAgLy8gZXhjZXB0IGZvciB5ZWFyIGhlYWRQYXJ0OiB0dXJuIHRoaXMgaW50byBcIkphbiAxLCAyMDAwXCIgZXRjLlxuICAgICAgICAgICAgaWYodHIgPT09ICdkJykgZGF0ZVN0ciArPSAnLCAnICsgaGVhZFN0cjtcbiAgICAgICAgICAgIGVsc2UgZGF0ZVN0ciA9IGhlYWRTdHIgKyAoZGF0ZVN0ciA/ICcsICcgKyBkYXRlU3RyIDogJycpO1xuICAgICAgICB9IGVsc2UgaWYoIWF4Ll9pbkNhbGNUaWNrcyB8fCAoaGVhZFN0ciAhPT0gYXguX3ByZXZEYXRlSGVhZCkpIHtcbiAgICAgICAgICAgIGRhdGVTdHIgKz0gJzxicj4nICsgaGVhZFN0cjtcbiAgICAgICAgICAgIGF4Ll9wcmV2RGF0ZUhlYWQgPSBoZWFkU3RyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb3V0LnRleHQgPSBkYXRlU3RyO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRMb2coYXgsIG91dCwgaG92ZXIsIGV4dHJhUHJlY2lzaW9uLCBoaWRlZXhwKSB7XG4gICAgdmFyIGR0aWNrID0gYXguZHRpY2s7XG4gICAgdmFyIHggPSBvdXQueDtcbiAgICB2YXIgdGlja2Zvcm1hdCA9IGF4LnRpY2tmb3JtYXQ7XG4gICAgdmFyIGR0Q2hhcjAgPSB0eXBlb2YgZHRpY2sgPT09ICdzdHJpbmcnICYmIGR0aWNrLmNoYXJBdCgwKTtcblxuICAgIGlmKGhpZGVleHAgPT09ICduZXZlcicpIHtcbiAgICAgICAgLy8gSWYgdGhpcyBpcyBhIGhvdmVyIGxhYmVsLCB0aGVuIHdlIG11c3QgKm5ldmVyKiBoaWRlIHRoZSBleHBvbmVudFxuICAgICAgICAvLyBmb3IgdGhlIHNha2Ugb2YgZGlzcGxheSwgd2hpY2ggY291bGQgZ2l2ZSB0aGUgd3JvbmcgdmFsdWUgYnlcbiAgICAgICAgLy8gcG90ZW50aWFsbHkgbWFueSBvcmRlcnMgb2YgbWFnbml0dWRlLiBJZiBoaWRlZXhwIHdhcyAnbmV2ZXInLCB0aGVuXG4gICAgICAgIC8vIGl0J3Mgbm93IHN1Y2NlZWRlZCBieSBwcmV2ZW50aW5nIHRoZSBvdGhlciBjb25kaXRpb24gZnJvbSBhdXRvbWF0aW5nXG4gICAgICAgIC8vIHRoaXMgY2hvaWNlLiBUaHVzIHdlIGNhbiB1bnNldCBpdCBzbyB0aGF0IHRoZSBheGlzIGZvcm1hdHRpbmcgdGFrZXNcbiAgICAgICAgLy8gcHJlY2VkZW5jZS5cbiAgICAgICAgaGlkZWV4cCA9ICcnO1xuICAgIH1cblxuICAgIGlmKGV4dHJhUHJlY2lzaW9uICYmIChkdENoYXIwICE9PSAnTCcpKSB7XG4gICAgICAgIGR0aWNrID0gJ0wzJztcbiAgICAgICAgZHRDaGFyMCA9ICdMJztcbiAgICB9XG5cbiAgICBpZih0aWNrZm9ybWF0IHx8IChkdENoYXIwID09PSAnTCcpKSB7XG4gICAgICAgIG91dC50ZXh0ID0gbnVtRm9ybWF0KE1hdGgucG93KDEwLCB4KSwgYXgsIGhpZGVleHAsIGV4dHJhUHJlY2lzaW9uKTtcbiAgICB9IGVsc2UgaWYoaXNOdW1lcmljKGR0aWNrKSB8fCAoKGR0Q2hhcjAgPT09ICdEJykgJiYgKExpYi5tb2QoeCArIDAuMDEsIDEpIDwgMC4xKSkpIHtcbiAgICAgICAgdmFyIHAgPSBNYXRoLnJvdW5kKHgpO1xuICAgICAgICB2YXIgYWJzUCA9IE1hdGguYWJzKHApO1xuICAgICAgICB2YXIgZXhwb25lbnRGb3JtYXQgPSBheC5leHBvbmVudGZvcm1hdDtcbiAgICAgICAgaWYoZXhwb25lbnRGb3JtYXQgPT09ICdwb3dlcicgfHwgKGlzU0lGb3JtYXQoZXhwb25lbnRGb3JtYXQpICYmIGJleW9uZFNJKHApKSkge1xuICAgICAgICAgICAgaWYocCA9PT0gMCkgb3V0LnRleHQgPSAxO1xuICAgICAgICAgICAgZWxzZSBpZihwID09PSAxKSBvdXQudGV4dCA9ICcxMCc7XG4gICAgICAgICAgICBlbHNlIG91dC50ZXh0ID0gJzEwPHN1cD4nICsgKHAgPiAxID8gJycgOiBNSU5VU19TSUdOKSArIGFic1AgKyAnPC9zdXA+JztcblxuICAgICAgICAgICAgb3V0LmZvbnRTaXplICo9IDEuMjU7XG4gICAgICAgIH0gZWxzZSBpZigoZXhwb25lbnRGb3JtYXQgPT09ICdlJyB8fCBleHBvbmVudEZvcm1hdCA9PT0gJ0UnKSAmJiBhYnNQID4gMikge1xuICAgICAgICAgICAgb3V0LnRleHQgPSAnMScgKyBleHBvbmVudEZvcm1hdCArIChwID4gMCA/ICcrJyA6IE1JTlVTX1NJR04pICsgYWJzUDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG91dC50ZXh0ID0gbnVtRm9ybWF0KE1hdGgucG93KDEwLCB4KSwgYXgsICcnLCAnZmFrZWhvdmVyJyk7XG4gICAgICAgICAgICBpZihkdGljayA9PT0gJ0QxJyAmJiBheC5faWQuY2hhckF0KDApID09PSAneScpIHtcbiAgICAgICAgICAgICAgICBvdXQuZHkgLT0gb3V0LmZvbnRTaXplIC8gNjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZihkdENoYXIwID09PSAnRCcpIHtcbiAgICAgICAgb3V0LnRleHQgPSBTdHJpbmcoTWF0aC5yb3VuZChNYXRoLnBvdygxMCwgTGliLm1vZCh4LCAxKSkpKTtcbiAgICAgICAgb3V0LmZvbnRTaXplICo9IDAuNzU7XG4gICAgfSBlbHNlIHRocm93ICd1bnJlY29nbml6ZWQgZHRpY2sgJyArIFN0cmluZyhkdGljayk7XG5cbiAgICAvLyBpZiA5J3MgYXJlIHByaW50ZWQgb24gbG9nIHNjYWxlLCBtb3ZlIHRoZSAxMCdzIGF3YXkgYSBiaXRcbiAgICBpZihheC5kdGljayA9PT0gJ0QxJykge1xuICAgICAgICB2YXIgZmlyc3RDaGFyID0gU3RyaW5nKG91dC50ZXh0KS5jaGFyQXQoMCk7XG4gICAgICAgIGlmKGZpcnN0Q2hhciA9PT0gJzAnIHx8IGZpcnN0Q2hhciA9PT0gJzEnKSB7XG4gICAgICAgICAgICBpZihheC5faWQuY2hhckF0KDApID09PSAneScpIHtcbiAgICAgICAgICAgICAgICBvdXQuZHggLT0gb3V0LmZvbnRTaXplIC8gNDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb3V0LmR5ICs9IG91dC5mb250U2l6ZSAvIDI7XG4gICAgICAgICAgICAgICAgb3V0LmR4ICs9IChheC5yYW5nZVsxXSA+IGF4LnJhbmdlWzBdID8gMSA6IC0xKSAqXG4gICAgICAgICAgICAgICAgICAgIG91dC5mb250U2l6ZSAqICh4IDwgMCA/IDAuNSA6IDAuMjUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmb3JtYXRDYXRlZ29yeShheCwgb3V0KSB7XG4gICAgdmFyIHR0ID0gYXguX2NhdGVnb3JpZXNbTWF0aC5yb3VuZChvdXQueCldO1xuICAgIGlmKHR0ID09PSB1bmRlZmluZWQpIHR0ID0gJyc7XG4gICAgb3V0LnRleHQgPSBTdHJpbmcodHQpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRNdWx0aUNhdGVnb3J5KGF4LCBvdXQsIGhvdmVyKSB7XG4gICAgdmFyIHYgPSBNYXRoLnJvdW5kKG91dC54KTtcbiAgICB2YXIgY2F0cyA9IGF4Ll9jYXRlZ29yaWVzW3ZdIHx8IFtdO1xuICAgIHZhciB0dCA9IGNhdHNbMV0gPT09IHVuZGVmaW5lZCA/ICcnIDogU3RyaW5nKGNhdHNbMV0pO1xuICAgIHZhciB0dDIgPSBjYXRzWzBdID09PSB1bmRlZmluZWQgPyAnJyA6IFN0cmluZyhjYXRzWzBdKTtcblxuICAgIGlmKGhvdmVyKSB7XG4gICAgICAgIC8vIFRPRE8gaXMgdGhpcyB3aGF0IHdlIHdhbnQ/XG4gICAgICAgIG91dC50ZXh0ID0gdHQyICsgJyAtICcgKyB0dDtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBzZXR1cCBmb3Igc2Vjb25kYXJ5IGxhYmVsc1xuICAgICAgICBvdXQudGV4dCA9IHR0O1xuICAgICAgICBvdXQudGV4dDIgPSB0dDI7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmb3JtYXRMaW5lYXIoYXgsIG91dCwgaG92ZXIsIGV4dHJhUHJlY2lzaW9uLCBoaWRlZXhwKSB7XG4gICAgaWYoaGlkZWV4cCA9PT0gJ25ldmVyJykge1xuICAgICAgICAvLyBJZiB0aGlzIGlzIGEgaG92ZXIgbGFiZWwsIHRoZW4gd2UgbXVzdCAqbmV2ZXIqIGhpZGUgdGhlIGV4cG9uZW50XG4gICAgICAgIC8vIGZvciB0aGUgc2FrZSBvZiBkaXNwbGF5LCB3aGljaCBjb3VsZCBnaXZlIHRoZSB3cm9uZyB2YWx1ZSBieVxuICAgICAgICAvLyBwb3RlbnRpYWxseSBtYW55IG9yZGVycyBvZiBtYWduaXR1ZGUuIElmIGhpZGVleHAgd2FzICduZXZlcicsIHRoZW5cbiAgICAgICAgLy8gaXQncyBub3cgc3VjY2VlZGVkIGJ5IHByZXZlbnRpbmcgdGhlIG90aGVyIGNvbmRpdGlvbiBmcm9tIGF1dG9tYXRpbmdcbiAgICAgICAgLy8gdGhpcyBjaG9pY2UuIFRodXMgd2UgY2FuIHVuc2V0IGl0IHNvIHRoYXQgdGhlIGF4aXMgZm9ybWF0dGluZyB0YWtlc1xuICAgICAgICAvLyBwcmVjZWRlbmNlLlxuICAgICAgICBoaWRlZXhwID0gJyc7XG4gICAgfSBlbHNlIGlmKGF4LnNob3dleHBvbmVudCA9PT0gJ2FsbCcgJiYgTWF0aC5hYnMob3V0LnggLyBheC5kdGljaykgPCAxZS02KSB7XG4gICAgICAgIC8vIGRvbid0IGFkZCBhbiBleHBvbmVudCB0byB6ZXJvIGlmIHdlJ3JlIHNob3dpbmcgYWxsIGV4cG9uZW50c1xuICAgICAgICAvLyBzbyB0aGUgb25seSByZWFzb24geW91J2Qgc2hvdyBhbiBleHBvbmVudCBvbiB6ZXJvIGlzIGlmIGl0J3MgdGhlXG4gICAgICAgIC8vIE9OTFkgdGljayB0byBnZXQgYW4gZXhwb25lbnQgKGZpcnN0IG9yIGxhc3QpXG4gICAgICAgIGhpZGVleHAgPSAnaGlkZSc7XG4gICAgfVxuICAgIG91dC50ZXh0ID0gbnVtRm9ybWF0KG91dC54LCBheCwgaGlkZWV4cCwgZXh0cmFQcmVjaXNpb24pO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRBbmdsZShheCwgb3V0LCBob3ZlciwgZXh0cmFQcmVjaXNpb24sIGhpZGVleHApIHtcbiAgICBpZihheC50aGV0YXVuaXQgPT09ICdyYWRpYW5zJyAmJiAhaG92ZXIpIHtcbiAgICAgICAgdmFyIG51bSA9IG91dC54IC8gMTgwO1xuXG4gICAgICAgIGlmKG51bSA9PT0gMCkge1xuICAgICAgICAgICAgb3V0LnRleHQgPSAnMCc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgZnJhYyA9IG51bTJmcmFjKG51bSk7XG5cbiAgICAgICAgICAgIGlmKGZyYWNbMV0gPj0gMTAwKSB7XG4gICAgICAgICAgICAgICAgb3V0LnRleHQgPSBudW1Gb3JtYXQoTGliLmRlZzJyYWQob3V0LngpLCBheCwgaGlkZWV4cCwgZXh0cmFQcmVjaXNpb24pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgaXNOZWcgPSBvdXQueCA8IDA7XG5cbiAgICAgICAgICAgICAgICBpZihmcmFjWzFdID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGZyYWNbMF0gPT09IDEpIG91dC50ZXh0ID0gJ8+AJztcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBvdXQudGV4dCA9IGZyYWNbMF0gKyAnz4AnO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG91dC50ZXh0ID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgJzxzdXA+JywgZnJhY1swXSwgJzwvc3VwPicsXG4gICAgICAgICAgICAgICAgICAgICAgICAn4oGEJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICc8c3ViPicsIGZyYWNbMV0sICc8L3N1Yj4nLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ8+AJ1xuICAgICAgICAgICAgICAgICAgICBdLmpvaW4oJycpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGlzTmVnKSBvdXQudGV4dCA9IE1JTlVTX1NJR04gKyBvdXQudGV4dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIG91dC50ZXh0ID0gbnVtRm9ybWF0KG91dC54LCBheCwgaGlkZWV4cCwgZXh0cmFQcmVjaXNpb24pO1xuICAgIH1cbn1cblxuLy8gaW5zcGlyZWQgYnlcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS95aXNpYmwvbnVtMmZyYWN0aW9uL2Jsb2IvbWFzdGVyL2luZGV4LmpzXG5mdW5jdGlvbiBudW0yZnJhYyhudW0pIHtcbiAgICBmdW5jdGlvbiBhbG1vc3RFcShhLCBiKSB7XG4gICAgICAgIHJldHVybiBNYXRoLmFicyhhIC0gYikgPD0gMWUtNjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmaW5kR0NEKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGFsbW9zdEVxKGIsIDApID8gYSA6IGZpbmRHQ0QoYiwgYSAlIGIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpbmRQcmVjaXNpb24obikge1xuICAgICAgICB2YXIgZSA9IDE7XG4gICAgICAgIHdoaWxlKCFhbG1vc3RFcShNYXRoLnJvdW5kKG4gKiBlKSAvIGUsIG4pKSB7XG4gICAgICAgICAgICBlICo9IDEwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlO1xuICAgIH1cblxuICAgIHZhciBwcmVjaXNpb24gPSBmaW5kUHJlY2lzaW9uKG51bSk7XG4gICAgdmFyIG51bWJlciA9IG51bSAqIHByZWNpc2lvbjtcbiAgICB2YXIgZ2NkID0gTWF0aC5hYnMoZmluZEdDRChudW1iZXIsIHByZWNpc2lvbikpO1xuXG4gICAgcmV0dXJuIFtcbiAgICAgICAgLy8gbnVtZXJhdG9yXG4gICAgICAgIE1hdGgucm91bmQobnVtYmVyIC8gZ2NkKSxcbiAgICAgICAgLy8gZGVub21pbmF0b3JcbiAgICAgICAgTWF0aC5yb3VuZChwcmVjaXNpb24gLyBnY2QpXG4gICAgXTtcbn1cblxuLy8gZm9ybWF0IGEgbnVtYmVyICh0aWNrIHZhbHVlKSBhY2NvcmRpbmcgdG8gdGhlIGF4aXMgc2V0dGluZ3Ncbi8vIG5ldywgbW9yZSByZWxpYWJsZSBwcm9jZWR1cmUgdGhhbiBkMy5yb3VuZCBvciBzaW1pbGFyOlxuLy8gYWRkIGhhbGYgdGhlIHJvdW5kaW5nIGluY3JlbWVudCwgdGhlbiBzdHJpbmdpZnkgYW5kIHRydW5jYXRlXG4vLyBhbHNvIGF1dG9tYXRpY2FsbHkgc3dpdGNoIHRvIHNjaS4gbm90YXRpb25cbnZhciBTSVBSRUZJWEVTID0gWydmJywgJ3AnLCAnbicsICfOvCcsICdtJywgJycsICdrJywgJ00nLCAnRycsICdUJ107XG5cbmZ1bmN0aW9uIGlzU0lGb3JtYXQoZXhwb25lbnRGb3JtYXQpIHtcbiAgICByZXR1cm4gZXhwb25lbnRGb3JtYXQgPT09ICdTSScgfHwgZXhwb25lbnRGb3JtYXQgPT09ICdCJztcbn1cblxuLy8gYXJlIHdlIGJleW9uZCB0aGUgcmFuZ2Ugb2YgY29tbW9uIFNJIHByZWZpeGVzP1xuLy8gMTBeLTE2IC0+IDF4MTBeLTE2XG4vLyAxMF4tMTUgLT4gMWZcbi8vIC4uLlxuLy8gMTBeMTQgLT4gMTAwVFxuLy8gMTBeMTUgLT4gMXgxMF4xNVxuLy8gMTBeMTYgLT4gMXgxMF4xNlxuZnVuY3Rpb24gYmV5b25kU0koZXhwb25lbnQpIHtcbiAgICByZXR1cm4gZXhwb25lbnQgPiAxNCB8fCBleHBvbmVudCA8IC0xNTtcbn1cblxuZnVuY3Rpb24gbnVtRm9ybWF0KHYsIGF4LCBmbXRvdmVycmlkZSwgaG92ZXIpIHtcbiAgICB2YXIgaXNOZWcgPSB2IDwgMDtcbiAgICAvLyBtYXggbnVtYmVyIG9mIGRpZ2l0cyBwYXN0IGRlY2ltYWwgcG9pbnQgdG8gc2hvd1xuICAgIHZhciB0aWNrUm91bmQgPSBheC5fdGlja3JvdW5kO1xuICAgIHZhciBleHBvbmVudEZvcm1hdCA9IGZtdG92ZXJyaWRlIHx8IGF4LmV4cG9uZW50Zm9ybWF0IHx8ICdCJztcbiAgICB2YXIgZXhwb25lbnQgPSBheC5fdGlja2V4cG9uZW50O1xuICAgIHZhciB0aWNrZm9ybWF0ID0gYXhlcy5nZXRUaWNrRm9ybWF0KGF4KTtcbiAgICB2YXIgc2VwYXJhdGV0aG91c2FuZHMgPSBheC5zZXBhcmF0ZXRob3VzYW5kcztcblxuICAgIC8vIHNwZWNpYWwgY2FzZSBmb3IgaG92ZXI6IHNldCBleHBvbmVudCBqdXN0IGZvciB0aGlzIHZhbHVlLCBhbmRcbiAgICAvLyBhZGQgYSBjb3VwbGUgbW9yZSBkaWdpdHMgb2YgcHJlY2lzaW9uIG92ZXIgdGljayBsYWJlbHNcbiAgICBpZihob3Zlcikge1xuICAgICAgICAvLyBtYWtlIGEgZHVtbXkgYXhpcyBvYmogdG8gZ2V0IHRoZSBhdXRvIHJvdW5kaW5nIGFuZCBleHBvbmVudFxuICAgICAgICB2YXIgYWggPSB7XG4gICAgICAgICAgICBleHBvbmVudGZvcm1hdDogZXhwb25lbnRGb3JtYXQsXG4gICAgICAgICAgICBkdGljazogYXguc2hvd2V4cG9uZW50ID09PSAnbm9uZScgPyBheC5kdGljayA6XG4gICAgICAgICAgICAgICAgKGlzTnVtZXJpYyh2KSA/IE1hdGguYWJzKHYpIHx8IDEgOiAxKSxcbiAgICAgICAgICAgIC8vIGlmIG5vdCBzaG93aW5nIGFueSBleHBvbmVudHMsIGRvbid0IGNoYW5nZSB0aGUgZXhwb25lbnRcbiAgICAgICAgICAgIC8vIGZyb20gd2hhdCB3ZSBjYWxjdWxhdGVcbiAgICAgICAgICAgIHJhbmdlOiBheC5zaG93ZXhwb25lbnQgPT09ICdub25lJyA/IGF4LnJhbmdlLm1hcChheC5yMmQpIDogWzAsIHYgfHwgMV1cbiAgICAgICAgfTtcbiAgICAgICAgYXV0b1RpY2tSb3VuZChhaCk7XG4gICAgICAgIHRpY2tSb3VuZCA9IChOdW1iZXIoYWguX3RpY2tyb3VuZCkgfHwgMCkgKyA0O1xuICAgICAgICBleHBvbmVudCA9IGFoLl90aWNrZXhwb25lbnQ7XG4gICAgICAgIGlmKGF4LmhvdmVyZm9ybWF0KSB0aWNrZm9ybWF0ID0gYXguaG92ZXJmb3JtYXQ7XG4gICAgfVxuXG4gICAgaWYodGlja2Zvcm1hdCkgcmV0dXJuIGF4Ll9udW1Gb3JtYXQodGlja2Zvcm1hdCkodikucmVwbGFjZSgvLS9nLCBNSU5VU19TSUdOKTtcblxuICAgIC8vICdlcHNpbG9uJyAtIHJvdW5kaW5nIGluY3JlbWVudFxuICAgIHZhciBlID0gTWF0aC5wb3coMTAsIC10aWNrUm91bmQpIC8gMjtcblxuICAgIC8vIGV4cG9uZW50Rm9ybWF0IGNvZGVzOlxuICAgIC8vICdlJyAoMS4yZSs2LCBkZWZhdWx0KVxuICAgIC8vICdFJyAoMS4yRSs2KVxuICAgIC8vICdTSScgKDEuMk0pXG4gICAgLy8gJ0InIChzYW1lIGFzIFNJIGV4Y2VwdCAxMF45PUIgbm90IEcpXG4gICAgLy8gJ25vbmUnICgxMjAwMDAwKVxuICAgIC8vICdwb3dlcicgKDEuMngxMF42KVxuICAgIC8vICdoaWRlJyAoMS4yLCB1c2UgM3JkIGFyZ3VtZW50PT0naGlkZScgdG8gZWdcbiAgICAvLyAgICAgIG9ubHkgc2hvdyBleHBvbmVudCBvbiBsYXN0IHRpY2spXG4gICAgaWYoZXhwb25lbnRGb3JtYXQgPT09ICdub25lJykgZXhwb25lbnQgPSAwO1xuXG4gICAgLy8gdGFrZSB0aGUgc2lnbiBvdXQsIHB1dCBpdCBiYWNrIG1hbnVhbGx5IGF0IHRoZSBlbmRcbiAgICAvLyAtIG1ha2VzIGNhc2VzIGVhc2llclxuICAgIHYgPSBNYXRoLmFicyh2KTtcbiAgICBpZih2IDwgZSkge1xuICAgICAgICAvLyAwIGlzIGp1c3QgMCwgYnV0IG1heSBnZXQgZXhwb25lbnQgaWYgaXQncyB0aGUgbGFzdCB0aWNrXG4gICAgICAgIHYgPSAnMCc7XG4gICAgICAgIGlzTmVnID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdiArPSBlO1xuICAgICAgICAvLyB0YWtlIG91dCBhIGNvbW1vbiBleHBvbmVudCwgaWYgYW55XG4gICAgICAgIGlmKGV4cG9uZW50KSB7XG4gICAgICAgICAgICB2ICo9IE1hdGgucG93KDEwLCAtZXhwb25lbnQpO1xuICAgICAgICAgICAgdGlja1JvdW5kICs9IGV4cG9uZW50O1xuICAgICAgICB9XG4gICAgICAgIC8vIHJvdW5kIHRoZSBtYW50aXNzYVxuICAgICAgICBpZih0aWNrUm91bmQgPT09IDApIHYgPSBTdHJpbmcoTWF0aC5mbG9vcih2KSk7XG4gICAgICAgIGVsc2UgaWYodGlja1JvdW5kIDwgMCkge1xuICAgICAgICAgICAgdiA9IFN0cmluZyhNYXRoLnJvdW5kKHYpKTtcbiAgICAgICAgICAgIHYgPSB2LnN1YnN0cigwLCB2Lmxlbmd0aCArIHRpY2tSb3VuZCk7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSB0aWNrUm91bmQ7IGkgPCAwOyBpKyspIHYgKz0gJzAnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdiA9IFN0cmluZyh2KTtcbiAgICAgICAgICAgIHZhciBkcCA9IHYuaW5kZXhPZignLicpICsgMTtcbiAgICAgICAgICAgIGlmKGRwKSB2ID0gdi5zdWJzdHIoMCwgZHAgKyB0aWNrUm91bmQpLnJlcGxhY2UoL1xcLj8wKyQvLCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaW5zZXJ0IGFwcHJvcHJpYXRlIGRlY2ltYWwgcG9pbnQgYW5kIHRob3VzYW5kcyBzZXBhcmF0b3JcbiAgICAgICAgdiA9IExpYi5udW1TZXBhcmF0ZSh2LCBheC5fc2VwYXJhdG9ycywgc2VwYXJhdGV0aG91c2FuZHMpO1xuICAgIH1cblxuICAgIC8vIGFkZCBleHBvbmVudFxuICAgIGlmKGV4cG9uZW50ICYmIGV4cG9uZW50Rm9ybWF0ICE9PSAnaGlkZScpIHtcbiAgICAgICAgaWYoaXNTSUZvcm1hdChleHBvbmVudEZvcm1hdCkgJiYgYmV5b25kU0koZXhwb25lbnQpKSBleHBvbmVudEZvcm1hdCA9ICdwb3dlcic7XG5cbiAgICAgICAgdmFyIHNpZ25lZEV4cG9uZW50O1xuICAgICAgICBpZihleHBvbmVudCA8IDApIHNpZ25lZEV4cG9uZW50ID0gTUlOVVNfU0lHTiArIC1leHBvbmVudDtcbiAgICAgICAgZWxzZSBpZihleHBvbmVudEZvcm1hdCAhPT0gJ3Bvd2VyJykgc2lnbmVkRXhwb25lbnQgPSAnKycgKyBleHBvbmVudDtcbiAgICAgICAgZWxzZSBzaWduZWRFeHBvbmVudCA9IFN0cmluZyhleHBvbmVudCk7XG5cbiAgICAgICAgaWYoZXhwb25lbnRGb3JtYXQgPT09ICdlJyB8fCBleHBvbmVudEZvcm1hdCA9PT0gJ0UnKSB7XG4gICAgICAgICAgICB2ICs9IGV4cG9uZW50Rm9ybWF0ICsgc2lnbmVkRXhwb25lbnQ7XG4gICAgICAgIH0gZWxzZSBpZihleHBvbmVudEZvcm1hdCA9PT0gJ3Bvd2VyJykge1xuICAgICAgICAgICAgdiArPSAnw5cxMDxzdXA+JyArIHNpZ25lZEV4cG9uZW50ICsgJzwvc3VwPic7XG4gICAgICAgIH0gZWxzZSBpZihleHBvbmVudEZvcm1hdCA9PT0gJ0InICYmIGV4cG9uZW50ID09PSA5KSB7XG4gICAgICAgICAgICB2ICs9ICdCJztcbiAgICAgICAgfSBlbHNlIGlmKGlzU0lGb3JtYXQoZXhwb25lbnRGb3JtYXQpKSB7XG4gICAgICAgICAgICB2ICs9IFNJUFJFRklYRVNbZXhwb25lbnQgLyAzICsgNV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBwdXQgc2lnbiBiYWNrIGluIGFuZCByZXR1cm5cbiAgICAvLyByZXBsYWNlIHN0YW5kYXJkIG1pbnVzIGNoYXJhY3RlciAod2hpY2ggaXMgdGVjaG5pY2FsbHkgYSBoeXBoZW4pXG4gICAgLy8gd2l0aCBhIHRydWUgbWludXMgc2lnblxuICAgIGlmKGlzTmVnKSByZXR1cm4gTUlOVVNfU0lHTiArIHY7XG4gICAgcmV0dXJuIHY7XG59XG5cbmF4ZXMuZ2V0VGlja0Zvcm1hdCA9IGZ1bmN0aW9uKGF4KSB7XG4gICAgdmFyIGk7XG5cbiAgICBmdW5jdGlvbiBjb252ZXJ0VG9NcyhkdGljaykge1xuICAgICAgICByZXR1cm4gdHlwZW9mIGR0aWNrICE9PSAnc3RyaW5nJyA/IGR0aWNrIDogTnVtYmVyKGR0aWNrLnJlcGxhY2UoJ00nLCAnJykpICogT05FQVZHTU9OVEg7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcGFyZUxvZ1RpY2tzKGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgIHZhciBwcmlvcml0eSA9IFsnTCcsICdEJ107XG4gICAgICAgIGlmKHR5cGVvZiBsZWZ0ID09PSB0eXBlb2YgcmlnaHQpIHtcbiAgICAgICAgICAgIGlmKHR5cGVvZiBsZWZ0ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBsZWZ0IC0gcmlnaHQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBsZWZ0UHJpb3JpdHkgPSBwcmlvcml0eS5pbmRleE9mKGxlZnQuY2hhckF0KDApKTtcbiAgICAgICAgICAgICAgICB2YXIgcmlnaHRQcmlvcml0eSA9IHByaW9yaXR5LmluZGV4T2YocmlnaHQuY2hhckF0KDApKTtcbiAgICAgICAgICAgICAgICBpZihsZWZ0UHJpb3JpdHkgPT09IHJpZ2h0UHJpb3JpdHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE51bWJlcihsZWZ0LnJlcGxhY2UoLyhMfEQpL2csICcnKSkgLSBOdW1iZXIocmlnaHQucmVwbGFjZSgvKEx8RCkvZywgJycpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFByaW9yaXR5IC0gcmlnaHRQcmlvcml0eTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdHlwZW9mIGxlZnQgPT09ICdudW1iZXInID8gMSA6IC0xO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNQcm9wZXJTdG9wKGR0aWNrLCByYW5nZSwgY29udmVydCkge1xuICAgICAgICB2YXIgY29udmVydEZuID0gY29udmVydCB8fCBmdW5jdGlvbih4KSB7IHJldHVybiB4O307XG4gICAgICAgIHZhciBsZWZ0RHRpY2sgPSByYW5nZVswXTtcbiAgICAgICAgdmFyIHJpZ2h0RHRpY2sgPSByYW5nZVsxXTtcbiAgICAgICAgcmV0dXJuICgoIWxlZnREdGljayAmJiB0eXBlb2YgbGVmdER0aWNrICE9PSAnbnVtYmVyJykgfHwgY29udmVydEZuKGxlZnREdGljaykgPD0gY29udmVydEZuKGR0aWNrKSkgJiZcbiAgICAgICAgICAgICAgICgoIXJpZ2h0RHRpY2sgJiYgdHlwZW9mIHJpZ2h0RHRpY2sgIT09ICdudW1iZXInKSB8fCBjb252ZXJ0Rm4ocmlnaHREdGljaykgPj0gY29udmVydEZuKGR0aWNrKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNQcm9wZXJMb2dTdG9wKGR0aWNrLCByYW5nZSkge1xuICAgICAgICB2YXIgaXNMZWZ0RHRpY2tOdWxsID0gcmFuZ2VbMF0gPT09IG51bGw7XG4gICAgICAgIHZhciBpc1JpZ2h0RHRpY2tOdWxsID0gcmFuZ2VbMV0gPT09IG51bGw7XG4gICAgICAgIHZhciBpc0R0aWNrSW5SYW5nZUxlZnQgPSBjb21wYXJlTG9nVGlja3MoZHRpY2ssIHJhbmdlWzBdKSA+PSAwO1xuICAgICAgICB2YXIgaXNEdGlja0luUmFuZ2VSaWdodCA9IGNvbXBhcmVMb2dUaWNrcyhkdGljaywgcmFuZ2VbMV0pIDw9IDA7XG4gICAgICAgIHJldHVybiAoaXNMZWZ0RHRpY2tOdWxsIHx8IGlzRHRpY2tJblJhbmdlTGVmdCkgJiYgKGlzUmlnaHREdGlja051bGwgfHwgaXNEdGlja0luUmFuZ2VSaWdodCk7XG4gICAgfVxuXG4gICAgdmFyIHRpY2tzdG9wLCBzdG9waTtcbiAgICBpZihheC50aWNrZm9ybWF0c3RvcHMgJiYgYXgudGlja2Zvcm1hdHN0b3BzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgc3dpdGNoKGF4LnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2RhdGUnOlxuICAgICAgICAgICAgY2FzZSAnbGluZWFyJzoge1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGF4LnRpY2tmb3JtYXRzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBzdG9waSA9IGF4LnRpY2tmb3JtYXRzdG9wc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc3RvcGkuZW5hYmxlZCAmJiBpc1Byb3BlclN0b3AoYXguZHRpY2ssIHN0b3BpLmR0aWNrcmFuZ2UsIGNvbnZlcnRUb01zKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGlja3N0b3AgPSBzdG9waTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSAnbG9nJzoge1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGF4LnRpY2tmb3JtYXRzdG9wcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBzdG9waSA9IGF4LnRpY2tmb3JtYXRzdG9wc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc3RvcGkuZW5hYmxlZCAmJiBpc1Byb3BlckxvZ1N0b3AoYXguZHRpY2ssIHN0b3BpLmR0aWNrcmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aWNrc3RvcCA9IHN0b3BpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aWNrc3RvcCA/IHRpY2tzdG9wLnZhbHVlIDogYXgudGlja2Zvcm1hdDtcbn07XG5cbi8vIGdldFN1YnBsb3RzIC0gZXh0cmFjdCBhbGwgc3VicGxvdCBJRHMgd2UgbmVlZFxuLy8gYXMgYW4gYXJyYXkgb2YgaXRlbXMgbGlrZSAneHknLCAneDJ5JywgJ3gyeTInLi4uXG4vLyBzb3J0ZWQgYnkgeCAoeCx4Mix4My4uLikgdGhlbiB5XG4vLyBvcHRpb25hbGx5IHJlc3RyaWN0IHRvIG9ubHkgc3VicGxvdHMgY29udGFpbmluZyBheGlzIG9iamVjdCBheFxuLy9cbi8vIE5PVEU6IHRoaXMgaXMgY3VycmVudGx5IG9ubHkgdXNlZCBPVVRTSURFIHBsb3RseS5qcyAodG9vbHBhbmVsLCB3ZWJhcHApXG4vLyBpZGVhbGx5IHdlIGdldCByaWQgb2YgaXQgdGhlcmUgKG9yIGp1c3QgY29weSB0aGlzIHRoZXJlKSBhbmQgcmVtb3ZlIGl0IGhlcmVcbmF4ZXMuZ2V0U3VicGxvdHMgPSBmdW5jdGlvbihnZCwgYXgpIHtcbiAgICB2YXIgc3VicGxvdE9iaiA9IGdkLl9mdWxsTGF5b3V0Ll9zdWJwbG90cztcbiAgICB2YXIgYWxsU3VicGxvdHMgPSBzdWJwbG90T2JqLmNhcnRlc2lhbi5jb25jYXQoc3VicGxvdE9iai5nbDJkIHx8IFtdKTtcblxuICAgIHZhciBvdXQgPSBheCA/IGF4ZXMuZmluZFN1YnBsb3RzV2l0aEF4aXMoYWxsU3VicGxvdHMsIGF4KSA6IGFsbFN1YnBsb3RzO1xuXG4gICAgb3V0LnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICB2YXIgYVBhcnRzID0gYS5zdWJzdHIoMSkuc3BsaXQoJ3knKTtcbiAgICAgICAgdmFyIGJQYXJ0cyA9IGIuc3Vic3RyKDEpLnNwbGl0KCd5Jyk7XG5cbiAgICAgICAgaWYoYVBhcnRzWzBdID09PSBiUGFydHNbMF0pIHJldHVybiArYVBhcnRzWzFdIC0gK2JQYXJ0c1sxXTtcbiAgICAgICAgcmV0dXJuICthUGFydHNbMF0gLSArYlBhcnRzWzBdO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8vIGZpbmQgYWxsIHN1YnBsb3RzIHdpdGggYXhpcyAnYXgnXG4vLyBOT1RFOiB0aGlzIGlzIG9ubHkgdXNlZCBpbiBheGVzLmdldFN1YnBsb3RzIChvbmx5IHVzZWQgb3V0c2lkZSBwbG90bHkuanMpIGFuZFxuLy8gZ2wyZC9jb252ZXJ0ICh3aGVyZSBpdCByZXN0cmljdHMgYXhpcyBzdWJwbG90cyB0byBvbmx5IHRob3NlIHdpdGggZ2wyZClcbmF4ZXMuZmluZFN1YnBsb3RzV2l0aEF4aXMgPSBmdW5jdGlvbihzdWJwbG90cywgYXgpIHtcbiAgICB2YXIgYXhNYXRjaCA9IG5ldyBSZWdFeHAoXG4gICAgICAgIChheC5faWQuY2hhckF0KDApID09PSAneCcpID8gKCdeJyArIGF4Ll9pZCArICd5JykgOiAoYXguX2lkICsgJyQnKVxuICAgICk7XG4gICAgdmFyIHN1YnBsb3RzV2l0aEF4ID0gW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNwID0gc3VicGxvdHNbaV07XG4gICAgICAgIGlmKGF4TWF0Y2gudGVzdChzcCkpIHN1YnBsb3RzV2l0aEF4LnB1c2goc3ApO1xuICAgIH1cblxuICAgIHJldHVybiBzdWJwbG90c1dpdGhBeDtcbn07XG5cbi8vIG1ha2VDbGlwUGF0aHM6IHByZXBhcmUgY2xpcFBhdGhzIGZvciBhbGwgc2luZ2xlIGF4ZXMgYW5kIGFsbCBwb3NzaWJsZSB4eSBwYWlyaW5nc1xuYXhlcy5tYWtlQ2xpcFBhdGhzID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgLy8gZm9yIG1vcmUgaW5mbzogaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzI1OTVcbiAgICBpZihmdWxsTGF5b3V0Ll9oYXNPbmx5TGFyZ2VTcGxvbXMpIHJldHVybjtcblxuICAgIHZhciBmdWxsV2lkdGggPSB7X29mZnNldDogMCwgX2xlbmd0aDogZnVsbExheW91dC53aWR0aCwgX2lkOiAnJ307XG4gICAgdmFyIGZ1bGxIZWlnaHQgPSB7X29mZnNldDogMCwgX2xlbmd0aDogZnVsbExheW91dC5oZWlnaHQsIF9pZDogJyd9O1xuICAgIHZhciB4YUxpc3QgPSBheGVzLmxpc3QoZ2QsICd4JywgdHJ1ZSk7XG4gICAgdmFyIHlhTGlzdCA9IGF4ZXMubGlzdChnZCwgJ3knLCB0cnVlKTtcbiAgICB2YXIgY2xpcExpc3QgPSBbXTtcbiAgICB2YXIgaSwgajtcblxuICAgIGZvcihpID0gMDsgaSA8IHhhTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjbGlwTGlzdC5wdXNoKHt4OiB4YUxpc3RbaV0sIHk6IGZ1bGxIZWlnaHR9KTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgeWFMaXN0Lmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZihpID09PSAwKSBjbGlwTGlzdC5wdXNoKHt4OiBmdWxsV2lkdGgsIHk6IHlhTGlzdFtqXX0pO1xuICAgICAgICAgICAgY2xpcExpc3QucHVzaCh7eDogeGFMaXN0W2ldLCB5OiB5YUxpc3Rbal19KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNlbGVjdG9ycyBkb24ndCB3b3JrIHJpZ2h0IHdpdGggY2FtZWxDYXNlIHRhZ3MsXG4gICAgLy8gaGF2ZSB0byB1c2UgY2xhc3MgaW5zdGVhZFxuICAgIC8vIGh0dHBzOi8vZ3JvdXBzLmdvb2dsZS5jb20vZm9ydW0vIyF0b3BpYy9kMy1qcy82RXBBelEyZ1U5SVxuICAgIHZhciBheENsaXBzID0gZnVsbExheW91dC5fY2xpcHMuc2VsZWN0QWxsKCcuYXhlc2NsaXAnKVxuICAgICAgICAuZGF0YShjbGlwTGlzdCwgZnVuY3Rpb24oZCkgeyByZXR1cm4gZC54Ll9pZCArIGQueS5faWQ7IH0pO1xuXG4gICAgYXhDbGlwcy5lbnRlcigpLmFwcGVuZCgnY2xpcFBhdGgnKVxuICAgICAgICAuY2xhc3NlZCgnYXhlc2NsaXAnLCB0cnVlKVxuICAgICAgICAuYXR0cignaWQnLCBmdW5jdGlvbihkKSB7IHJldHVybiAnY2xpcCcgKyBmdWxsTGF5b3V0Ll91aWQgKyBkLnguX2lkICsgZC55Ll9pZDsgfSlcbiAgICAgIC5hcHBlbmQoJ3JlY3QnKTtcblxuICAgIGF4Q2xpcHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgYXhDbGlwcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnNlbGVjdCgncmVjdCcpLmF0dHIoe1xuICAgICAgICAgICAgeDogZC54Ll9vZmZzZXQgfHwgMCxcbiAgICAgICAgICAgIHk6IGQueS5fb2Zmc2V0IHx8IDAsXG4gICAgICAgICAgICB3aWR0aDogZC54Ll9sZW5ndGggfHwgMSxcbiAgICAgICAgICAgIGhlaWdodDogZC55Ll9sZW5ndGggfHwgMVxuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG5cbi8qKlxuICogTWFpbiBtdWx0aS1heGlzIGRyYXdpbmcgcm91dGluZSFcbiAqXG4gKiBAcGFyYW0ge0RPTSBlbGVtZW50fSBnZCA6IGdyYXBoIGRpdlxuICogQHBhcmFtIHtzdHJpbmcgb3IgYXJyYXkgb2Ygc3RyaW5nc30gYXJnIDogcG9seW1vcnBoaWMgYXJndW1lbnRcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzOlxuICogLSBAcGFyYW0ge2Jvb2xlYW59IHNraXBUaXRsZSA6IG9wdGlvbmFsIGZsYWcgdG8gc2tpcCBheGlzIHRpdGxlIGRyYXcvdXBkYXRlXG4gKlxuICogU2lnbmF0dXJlIDE6IEF4ZXMuZHJhdyhnZCwgJ3JlZHJhdycpXG4gKiAgIHVzZSB0aGlzIHRvIGNsZWFyIGFuZCByZWRyYXcgYWxsIGF4ZXMgb24gZ3JhcGhcbiAqXG4gKiBTaWduYXR1cmUgMjogQXhlcy5kcmF3KGdkLCAnJylcbiAqICAgdXNlIHRoaXMgdG8gZHJhdyBhbGwgYXhlcyBvbiBncmFwaCB3L28gdGhlIHNlbGVjdEFsbCgpLnJlbW92ZSgpXG4gKiAgIG9mIHRoZSAncmVkcmF3JyBzaWduYXR1cmVcbiAqXG4gKiBTaWduYXR1cmUgMzogQXhlcy5kcmF3KGdkLCBbYXhJZCwgYXhJZDIsIC4uLl0pXG4gKiAgIHdoZXJlIHRoZSBpdGVtcyBhcmUgYXhpcyBpZCBzdHJpbmcsXG4gKiAgIHVzZSB0aGlzIHRvIHVwZGF0ZSBtdWx0aXBsZSBheGVzIGluIG9uZSBjYWxsXG4gKlxuICogTi5CIGRyYXcgdXBkYXRlczpcbiAqIC0gYXguX3IgKHN0b3JlZCByYW5nZSBmb3IgdXNlIGJ5IHpvb20vcGFuKVxuICogLSBheC5fcmwgKHN0b3JlZCBsaW5lYXJpemVkIHJhbmdlIGZvciB1c2UgYnkgem9vbS9wYW4pXG4gKi9cbmF4ZXMuZHJhdyA9IGZ1bmN0aW9uKGdkLCBhcmcsIG9wdHMpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgaWYoYXJnID09PSAncmVkcmF3Jykge1xuICAgICAgICBmdWxsTGF5b3V0Ll9wYXBlci5zZWxlY3RBbGwoJ2cuc3VicGxvdCcpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGlkID0gZFswXTtcbiAgICAgICAgICAgIHZhciBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW2lkXTtcbiAgICAgICAgICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgICAgICAgICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICAgICAgICAgIHBsb3RpbmZvLnhheGlzbGF5ZXIuc2VsZWN0QWxsKCcuJyArIHhhLl9pZCArICd0aWNrJykucmVtb3ZlKCk7XG4gICAgICAgICAgICBwbG90aW5mby55YXhpc2xheWVyLnNlbGVjdEFsbCgnLicgKyB5YS5faWQgKyAndGljaycpLnJlbW92ZSgpO1xuICAgICAgICAgICAgcGxvdGluZm8ueGF4aXNsYXllci5zZWxlY3RBbGwoJy4nICsgeGEuX2lkICsgJ3RpY2syJykucmVtb3ZlKCk7XG4gICAgICAgICAgICBwbG90aW5mby55YXhpc2xheWVyLnNlbGVjdEFsbCgnLicgKyB5YS5faWQgKyAndGljazInKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLnhheGlzbGF5ZXIuc2VsZWN0QWxsKCcuJyArIHhhLl9pZCArICdkaXZpZGVyJykucmVtb3ZlKCk7XG4gICAgICAgICAgICBwbG90aW5mby55YXhpc2xheWVyLnNlbGVjdEFsbCgnLicgKyB5YS5faWQgKyAnZGl2aWRlcicpLnJlbW92ZSgpO1xuXG4gICAgICAgICAgICBpZihwbG90aW5mby5ncmlkbGF5ZXIpIHBsb3RpbmZvLmdyaWRsYXllci5zZWxlY3RBbGwoJ3BhdGgnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIGlmKHBsb3RpbmZvLnplcm9saW5lbGF5ZXIpIHBsb3RpbmZvLnplcm9saW5lbGF5ZXIuc2VsZWN0QWxsKCdwYXRoJykucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgIGZ1bGxMYXlvdXQuX2luZm9sYXllci5zZWxlY3QoJy5nLScgKyB4YS5faWQgKyAndGl0bGUnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIGZ1bGxMYXlvdXQuX2luZm9sYXllci5zZWxlY3QoJy5nLScgKyB5YS5faWQgKyAndGl0bGUnKS5yZW1vdmUoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIGF4TGlzdCA9ICghYXJnIHx8IGFyZyA9PT0gJ3JlZHJhdycpID8gYXhlcy5saXN0SWRzKGdkKSA6IGFyZztcblxuICAgIHJldHVybiBMaWIuc3luY09yQXN5bmMoYXhMaXN0Lm1hcChmdW5jdGlvbihheElkKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmKCFheElkKSByZXR1cm47XG5cbiAgICAgICAgICAgIHZhciBheCA9IGF4ZXMuZ2V0RnJvbUlkKGdkLCBheElkKTtcbiAgICAgICAgICAgIHZhciBheERvbmUgPSBheGVzLmRyYXdPbmUoZ2QsIGF4LCBvcHRzKTtcblxuICAgICAgICAgICAgYXguX3IgPSBheC5yYW5nZS5zbGljZSgpO1xuICAgICAgICAgICAgYXguX3JsID0gTGliLnNpbXBsZU1hcChheC5fciwgYXgucjJsKTtcblxuICAgICAgICAgICAgcmV0dXJuIGF4RG9uZTtcbiAgICAgICAgfTtcbiAgICB9KSk7XG59O1xuXG4vKipcbiAqIERyYXcgb25lIGNhcnRlc2lhbiBheGlzXG4gKlxuICogQHBhcmFtIHtET00gZWxlbWVudH0gZ2RcbiAqIEBwYXJhbSB7b2JqZWN0fSBheCAoZnVsbCkgYXhpcyBvYmplY3RcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzXG4gKiAtIEBwYXJhbSB7Ym9vbGVhbn0gc2tpcFRpdGxlIChzZXQgdG8gdHJ1ZSB0byBza2lwIGF4aXMgdGl0bGUgZHJhdyBjYWxsKVxuICovXG5heGVzLmRyYXdPbmUgPSBmdW5jdGlvbihnZCwgYXgsIG9wdHMpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgIHZhciBpLCBzcCwgcGxvdGluZm87XG5cbiAgICBheC5zZXRTY2FsZSgpO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgYXhJZCA9IGF4Ll9pZDtcbiAgICB2YXIgYXhMZXR0ZXIgPSBheElkLmNoYXJBdCgwKTtcbiAgICB2YXIgY291bnRlckxldHRlciA9IGF4ZXMuY291bnRlckxldHRlcihheElkKTtcbiAgICB2YXIgbWFpblN1YnBsb3QgPSBheC5fbWFpblN1YnBsb3Q7XG4gICAgdmFyIG1haW5MaW5lUG9zaXRpb24gPSBheC5fbWFpbkxpbmVQb3NpdGlvbjtcbiAgICB2YXIgbWFpbk1pcnJvclBvc2l0aW9uID0gYXguX21haW5NaXJyb3JQb3NpdGlvbjtcbiAgICB2YXIgbWFpblBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbbWFpblN1YnBsb3RdO1xuICAgIHZhciBtYWluQXhMYXllciA9IG1haW5QbG90aW5mb1theExldHRlciArICdheGlzbGF5ZXInXTtcbiAgICB2YXIgc3VicGxvdHNXaXRoQXggPSBheC5fc3VicGxvdHNXaXRoO1xuXG4gICAgdmFyIHZhbHMgPSBheC5fdmFscyA9IGF4ZXMuY2FsY1RpY2tzKGF4KTtcblxuICAgIC8vIEFkZCBhIGNvdXBsZSBvZiBheGlzIHByb3BlcnRpZXMgdGhhdCBzaG91bGQgY2F1c2UgdXMgdG8gcmVjcmVhdGVcbiAgICAvLyBlbGVtZW50cy4gVXNlZCBpbiBkMyBkYXRhIGZ1bmN0aW9uLlxuICAgIHZhciBheEluZm8gPSBbYXgubWlycm9yLCBtYWluTGluZVBvc2l0aW9uLCBtYWluTWlycm9yUG9zaXRpb25dLmpvaW4oJ18nKTtcbiAgICBmb3IoaSA9IDA7IGkgPCB2YWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhbHNbaV0uYXhJbmZvID0gYXhJbmZvO1xuICAgIH1cblxuICAgIGlmKCFheC52aXNpYmxlKSByZXR1cm47XG5cbiAgICAvLyBzdGFzaCBzZWxlY3Rpb25zIHRvIGF2b2lkIERPTSBxdWVyaWVzIGUuZy5cbiAgICAvLyAtIHN0YXNoIHRpY2tMYWJlbHMgc2VsZWN0aW9uLCBzbyB0aGF0IGRyYXdUaXRsZSBjYW4gdXNlIGl0IHRvIHNjb290IHRpdGxlXG4gICAgYXguX3NlbGVjdGlvbnMgPSB7fTtcbiAgICAvLyBzdGFzaCB0aWNrIGFuZ2xlIChpbmNsdWRpbmcgdGhlIGNvbXB1dGVkICdhdXRvJyB2YWx1ZXMpIHBlciB0aWNrLWxhYmVsIGNsYXNzXG4gICAgYXguX3RpY2tBbmdsZXMgPSB7fTtcblxuICAgIHZhciB0cmFuc0ZuID0gYXhlcy5tYWtlVHJhbnNGbihheCk7XG4gICAgdmFyIHRpY2tWYWxzO1xuICAgIC8vIFdlIHJlbW92ZSB6ZXJvIGxpbmVzLCBncmlkIGxpbmVzLCBhbmQgaW5zaWRlIHRpY2tzIGlmIHRoZXkncmUgd2l0aGluIDFweCBvZiB0aGUgZW5kXG4gICAgLy8gVGhlIGtleSBjYXNlIGhlcmUgaXMgcmVtb3ZpbmcgemVybyBsaW5lcyB3aGVuIHRoZSBheGlzIGJvdW5kIGlzIHplcm9cbiAgICB2YXIgdmFsc0NsaXBwZWQ7XG5cbiAgICBpZihheC50aWNrc29uID09PSAnYm91bmRhcmllcycpIHtcbiAgICAgICAgdmFyIGJvdW5kYXJ5VmFscyA9IGdldEJvdW5kYXJ5VmFscyhheCwgdmFscyk7XG4gICAgICAgIHZhbHNDbGlwcGVkID0gYXhlcy5jbGlwRW5kcyhheCwgYm91bmRhcnlWYWxzKTtcbiAgICAgICAgdGlja1ZhbHMgPSBheC50aWNrcyA9PT0gJ2luc2lkZScgPyB2YWxzQ2xpcHBlZCA6IGJvdW5kYXJ5VmFscztcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YWxzQ2xpcHBlZCA9IGF4ZXMuY2xpcEVuZHMoYXgsIHZhbHMpO1xuICAgICAgICB0aWNrVmFscyA9IGF4LnRpY2tzID09PSAnaW5zaWRlJyA/IHZhbHNDbGlwcGVkIDogdmFscztcbiAgICB9XG5cbiAgICB2YXIgZ3JpZFZhbHMgPSBheC5fZ3JpZFZhbHMgPSB2YWxzQ2xpcHBlZDtcbiAgICB2YXIgZGl2aWRlclZhbHMgPSBnZXREaXZpZGVyVmFscyhheCwgdmFscyk7XG5cbiAgICBpZighZnVsbExheW91dC5faGFzT25seUxhcmdlU3Bsb21zKSB7XG4gICAgICAgIC8vIGtlZXAgdHJhY2sgb2Ygd2hpY2ggc3VicGxvdHMgKGJ5IG1haW4gY29udGVyYXhpcykgd2UndmUgYWxyZWFkeVxuICAgICAgICAvLyBkcmF3biBncmlkcyBmb3IsIHNvIHdlIGRvbid0IG92ZXJkcmF3IG92ZXJsYXlpbmcgc3VicGxvdHNcbiAgICAgICAgdmFyIGZpbmlzaGVkR3JpZHMgPSB7fTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBzdWJwbG90c1dpdGhBeC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc3AgPSBzdWJwbG90c1dpdGhBeFtpXTtcbiAgICAgICAgICAgIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbc3BdO1xuXG4gICAgICAgICAgICB2YXIgY291bnRlckF4aXMgPSBwbG90aW5mb1tjb3VudGVyTGV0dGVyICsgJ2F4aXMnXTtcbiAgICAgICAgICAgIHZhciBtYWluQ291bnRlcklEID0gY291bnRlckF4aXMuX21haW5BeGlzLl9pZDtcbiAgICAgICAgICAgIGlmKGZpbmlzaGVkR3JpZHNbbWFpbkNvdW50ZXJJRF0pIGNvbnRpbnVlO1xuICAgICAgICAgICAgZmluaXNoZWRHcmlkc1ttYWluQ291bnRlcklEXSA9IDE7XG5cbiAgICAgICAgICAgIHZhciBncmlkUGF0aCA9IGF4TGV0dGVyID09PSAneCcgP1xuICAgICAgICAgICAgICAgICdNMCwnICsgY291bnRlckF4aXMuX29mZnNldCArICd2JyArIGNvdW50ZXJBeGlzLl9sZW5ndGggOlxuICAgICAgICAgICAgICAgICdNJyArIGNvdW50ZXJBeGlzLl9vZmZzZXQgKyAnLDBoJyArIGNvdW50ZXJBeGlzLl9sZW5ndGg7XG5cbiAgICAgICAgICAgIGF4ZXMuZHJhd0dyaWQoZ2QsIGF4LCB7XG4gICAgICAgICAgICAgICAgdmFsczogZ3JpZFZhbHMsXG4gICAgICAgICAgICAgICAgY291bnRlckF4aXM6IGNvdW50ZXJBeGlzLFxuICAgICAgICAgICAgICAgIGxheWVyOiBwbG90aW5mby5ncmlkbGF5ZXIuc2VsZWN0KCcuJyArIGF4SWQpLFxuICAgICAgICAgICAgICAgIHBhdGg6IGdyaWRQYXRoLFxuICAgICAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYXhlcy5kcmF3WmVyb0xpbmUoZ2QsIGF4LCB7XG4gICAgICAgICAgICAgICAgY291bnRlckF4aXM6IGNvdW50ZXJBeGlzLFxuICAgICAgICAgICAgICAgIGxheWVyOiBwbG90aW5mby56ZXJvbGluZWxheWVyLFxuICAgICAgICAgICAgICAgIHBhdGg6IGdyaWRQYXRoLFxuICAgICAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHRpY2tTaWducyA9IGF4ZXMuZ2V0VGlja1NpZ25zKGF4KTtcbiAgICB2YXIgdGlja1N1YnBsb3RzID0gW107XG5cbiAgICBpZihheC50aWNrcykge1xuICAgICAgICB2YXIgbWFpblRpY2tQYXRoID0gYXhlcy5tYWtlVGlja1BhdGgoYXgsIG1haW5MaW5lUG9zaXRpb24sIHRpY2tTaWduc1syXSk7XG4gICAgICAgIHZhciBtaXJyb3JUaWNrUGF0aDtcbiAgICAgICAgdmFyIGZ1bGxUaWNrUGF0aDtcbiAgICAgICAgaWYoYXguX2FuY2hvckF4aXMgJiYgYXgubWlycm9yICYmIGF4Lm1pcnJvciAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgbWlycm9yVGlja1BhdGggPSBheGVzLm1ha2VUaWNrUGF0aChheCwgbWFpbk1pcnJvclBvc2l0aW9uLCB0aWNrU2lnbnNbM10pO1xuICAgICAgICAgICAgZnVsbFRpY2tQYXRoID0gbWFpblRpY2tQYXRoICsgbWlycm9yVGlja1BhdGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtaXJyb3JUaWNrUGF0aCA9ICcnO1xuICAgICAgICAgICAgZnVsbFRpY2tQYXRoID0gbWFpblRpY2tQYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRpY2tQYXRoO1xuICAgICAgICBpZihheC5zaG93ZGl2aWRlcnMgJiYgYXgudGlja3MgPT09ICdvdXRzaWRlJyAmJiBheC50aWNrc29uID09PSAnYm91bmRhcmllcycpIHtcbiAgICAgICAgICAgIHZhciBkaXZpZGVyTG9va3VwID0ge307XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBkaXZpZGVyVmFscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGRpdmlkZXJMb29rdXBbZGl2aWRlclZhbHNbaV0ueF0gPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGlja1BhdGggPSBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpdmlkZXJMb29rdXBbZC54XSA/IG1pcnJvclRpY2tQYXRoIDogZnVsbFRpY2tQYXRoO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRpY2tQYXRoID0gZnVsbFRpY2tQYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgYXhlcy5kcmF3VGlja3MoZ2QsIGF4LCB7XG4gICAgICAgICAgICB2YWxzOiB0aWNrVmFscyxcbiAgICAgICAgICAgIGxheWVyOiBtYWluQXhMYXllcixcbiAgICAgICAgICAgIHBhdGg6IHRpY2tQYXRoLFxuICAgICAgICAgICAgdHJhbnNGbjogdHJhbnNGblxuICAgICAgICB9KTtcblxuICAgICAgICB0aWNrU3VicGxvdHMgPSBPYmplY3Qua2V5cyhheC5fbGluZXBvc2l0aW9ucyB8fCB7fSk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgdGlja1N1YnBsb3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHNwID0gdGlja1N1YnBsb3RzW2ldO1xuICAgICAgICBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW3NwXTtcbiAgICAgICAgLy8gW2JvdHRvbSBvciBsZWZ0LCB0b3Agb3IgcmlnaHRdLCBmcmVlIGFuZCBtYWluIGFyZSBoYW5kbGVkIGFib3ZlXG4gICAgICAgIHZhciBsaW5lcG9zaXRpb25zID0gYXguX2xpbmVwb3NpdGlvbnNbc3BdIHx8IFtdO1xuICAgICAgICB2YXIgc3BUaWNrUGF0aCA9IGF4ZXMubWFrZVRpY2tQYXRoKGF4LCBsaW5lcG9zaXRpb25zWzBdLCB0aWNrU2lnbnNbMF0pICtcbiAgICAgICAgICAgIGF4ZXMubWFrZVRpY2tQYXRoKGF4LCBsaW5lcG9zaXRpb25zWzFdLCB0aWNrU2lnbnNbMV0pO1xuXG4gICAgICAgIGF4ZXMuZHJhd1RpY2tzKGdkLCBheCwge1xuICAgICAgICAgICAgdmFsczogdGlja1ZhbHMsXG4gICAgICAgICAgICBsYXllcjogcGxvdGluZm9bYXhMZXR0ZXIgKyAnYXhpc2xheWVyJ10sXG4gICAgICAgICAgICBwYXRoOiBzcFRpY2tQYXRoLFxuICAgICAgICAgICAgdHJhbnNGbjogdHJhbnNGblxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgc2VxID0gW107XG5cbiAgICAvLyB0aWNrIGxhYmVscyAtIGZvciBub3cganVzdCB0aGUgbWFpbiBsYWJlbHMuXG4gICAgLy8gVE9ETzogbWlycm9yIGxhYmVscywgZXNwIGZvciBzdWJwbG90c1xuXG4gICAgc2VxLnB1c2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBheGVzLmRyYXdMYWJlbHMoZ2QsIGF4LCB7XG4gICAgICAgICAgICB2YWxzOiB2YWxzLFxuICAgICAgICAgICAgbGF5ZXI6IG1haW5BeExheWVyLFxuICAgICAgICAgICAgdHJhbnNGbjogdHJhbnNGbixcbiAgICAgICAgICAgIGxhYmVsRm5zOiBheGVzLm1ha2VMYWJlbEZucyhheCwgbWFpbkxpbmVQb3NpdGlvbilcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpZihheC50eXBlID09PSAnbXVsdGljYXRlZ29yeScpIHtcbiAgICAgICAgdmFyIGxhYmVsTGVuZ3RoID0gMDtcbiAgICAgICAgdmFyIHBhZCA9IHt4OiAyLCB5OiAxMH1bYXhMZXR0ZXJdO1xuICAgICAgICB2YXIgc2duID0gdGlja1NpZ25zWzJdICogKGF4LnRpY2tzID09PSAnaW5zaWRlJyA/IC0xIDogMSk7XG5cbiAgICAgICAgc2VxLnB1c2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBsYWJlbExlbmd0aCArPSBnZXRMYWJlbExldmVsU3BhbihheCwgYXhJZCArICd0aWNrJykgKyBwYWQ7XG4gICAgICAgICAgICBsYWJlbExlbmd0aCArPSBheC5fdGlja0FuZ2xlc1theElkICsgJ3RpY2snXSA/IGF4LnRpY2tmb250LnNpemUgKiBMSU5FX1NQQUNJTkcgOiAwO1xuXG4gICAgICAgICAgICByZXR1cm4gYXhlcy5kcmF3TGFiZWxzKGdkLCBheCwge1xuICAgICAgICAgICAgICAgIHZhbHM6IGdldFNlY29uZGFyeUxhYmVsVmFscyhheCwgdmFscyksXG4gICAgICAgICAgICAgICAgbGF5ZXI6IG1haW5BeExheWVyLFxuICAgICAgICAgICAgICAgIGNsczogYXhJZCArICd0aWNrMicsXG4gICAgICAgICAgICAgICAgcmVwb3NpdGlvbk9uVXBkYXRlOiB0cnVlLFxuICAgICAgICAgICAgICAgIHNlY29uZGFyeTogdHJ1ZSxcbiAgICAgICAgICAgICAgICB0cmFuc0ZuOiB0cmFuc0ZuLFxuICAgICAgICAgICAgICAgIGxhYmVsRm5zOiBheGVzLm1ha2VMYWJlbEZucyhheCwgbWFpbkxpbmVQb3NpdGlvbiArIGxhYmVsTGVuZ3RoICogc2duKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNlcS5wdXNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgbGFiZWxMZW5ndGggKz0gZ2V0TGFiZWxMZXZlbFNwYW4oYXgsIGF4SWQgKyAndGljazInKTtcbiAgICAgICAgICAgIGF4Ll9sYWJlbExlbmd0aCA9IGxhYmVsTGVuZ3RoO1xuXG4gICAgICAgICAgICByZXR1cm4gZHJhd0RpdmlkZXJzKGdkLCBheCwge1xuICAgICAgICAgICAgICAgIHZhbHM6IGRpdmlkZXJWYWxzLFxuICAgICAgICAgICAgICAgIGxheWVyOiBtYWluQXhMYXllcixcbiAgICAgICAgICAgICAgICBwYXRoOiBheGVzLm1ha2VUaWNrUGF0aChheCwgbWFpbkxpbmVQb3NpdGlvbiwgc2duLCBsYWJlbExlbmd0aCksXG4gICAgICAgICAgICAgICAgdHJhbnNGbjogdHJhbnNGblxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4dGVuZFJhbmdlKHJhbmdlLCBuZXdSYW5nZSkge1xuICAgICAgICByYW5nZVswXSA9IE1hdGgubWluKHJhbmdlWzBdLCBuZXdSYW5nZVswXSk7XG4gICAgICAgIHJhbmdlWzFdID0gTWF0aC5tYXgocmFuZ2VbMV0sIG5ld1JhbmdlWzFdKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjYWxjQm91bmRpbmdCb3goKSB7XG4gICAgICAgIGlmKGF4LnNob3d0aWNrbGFiZWxzKSB7XG4gICAgICAgICAgICB2YXIgZ2RCQiA9IGdkLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgdmFyIGJCb3ggPSBtYWluQXhMYXllci5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiB0aGUgd2F5IHdlJ3JlIGdvaW5nIHRvIHVzZSB0aGlzLCB0aGUgcG9zaXRpb25pbmcgdGhhdCBtYXR0ZXJzXG4gICAgICAgICAgICAgKiBpcyByZWxhdGl2ZSB0byB0aGUgb3JpZ2luIG9mIGdkLiBUaGlzIGlzIGltcG9ydGFudCBwYXJ0aWN1bGFybHlcbiAgICAgICAgICAgICAqIGlmIGdkIGlzIHNjcm9sbGFibGUsIGFuZCBtYXkgaGF2ZSBiZWVuIHNjcm9sbGVkIGJldHdlZW4gdGhlIHRpbWVcbiAgICAgICAgICAgICAqIHdlIGNhbGN1bGF0ZSB0aGlzIGFuZCB0aGUgdGltZSB3ZSB1c2UgaXRcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICBheC5fYm91bmRpbmdCb3ggPSB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IGJCb3gud2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBiQm94LmhlaWdodCxcbiAgICAgICAgICAgICAgICBsZWZ0OiBiQm94LmxlZnQgLSBnZEJCLmxlZnQsXG4gICAgICAgICAgICAgICAgcmlnaHQ6IGJCb3gucmlnaHQgLSBnZEJCLmxlZnQsXG4gICAgICAgICAgICAgICAgdG9wOiBiQm94LnRvcCAtIGdkQkIudG9wLFxuICAgICAgICAgICAgICAgIGJvdHRvbTogYkJveC5ib3R0b20gLSBnZEJCLnRvcFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBncyA9IGZ1bGxMYXlvdXQuX3NpemU7XG4gICAgICAgICAgICB2YXIgcG9zO1xuXG4gICAgICAgICAgICAvLyBzZXQgZHVtbXkgYmJveCBmb3IgdGlja2xhYmVsLWxlc3MgYXhlc1xuXG4gICAgICAgICAgICBpZihheExldHRlciA9PT0gJ3gnKSB7XG4gICAgICAgICAgICAgICAgcG9zID0gYXguYW5jaG9yID09PSAnZnJlZScgP1xuICAgICAgICAgICAgICAgICAgICBncy50ICsgZ3MuaCAqICgxIC0gYXgucG9zaXRpb24pIDpcbiAgICAgICAgICAgICAgICAgICAgZ3MudCArIGdzLmggKiAoMSAtIGF4Ll9hbmNob3JBeGlzLmRvbWFpblt7Ym90dG9tOiAwLCB0b3A6IDF9W2F4LnNpZGVdXSk7XG5cbiAgICAgICAgICAgICAgICBheC5fYm91bmRpbmdCb3ggPSB7XG4gICAgICAgICAgICAgICAgICAgIHRvcDogcG9zLFxuICAgICAgICAgICAgICAgICAgICBib3R0b206IHBvcyxcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogYXguX29mZnNldCxcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IGF4Ll9vZmZzZXQgKyBheC5fbGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICB3aWR0aDogYXguX2xlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAwXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcG9zID0gYXguYW5jaG9yID09PSAnZnJlZScgP1xuICAgICAgICAgICAgICAgICAgICBncy5sICsgZ3MudyAqIGF4LnBvc2l0aW9uIDpcbiAgICAgICAgICAgICAgICAgICAgZ3MubCArIGdzLncgKiBheC5fYW5jaG9yQXhpcy5kb21haW5be2xlZnQ6IDAsIHJpZ2h0OiAxfVtheC5zaWRlXV07XG5cbiAgICAgICAgICAgICAgICBheC5fYm91bmRpbmdCb3ggPSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQ6IHBvcyxcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IHBvcyxcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tOiBheC5fb2Zmc2V0ICsgYXguX2xlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgdG9wOiBheC5fb2Zmc2V0LFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGF4Ll9sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiAwXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8qXG4gICAgICAgICAqIGZvciBzcGlrZWxpbmVzOiB3aGF0J3MgdGhlIGZ1bGwgZG9tYWluIG9mIHBvc2l0aW9ucyBpbiB0aGVcbiAgICAgICAgICogb3Bwb3NpdGUgZGlyZWN0aW9uIHRoYXQgYXJlIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGF4aXM/XG4gICAgICAgICAqIFRoaXMgbWVhbnMgYW55IGF4ZXMgdGhhdCB3ZSBtYWtlIGEgc3VicGxvdCB3aXRoLCBwbHVzIHRoZVxuICAgICAgICAgKiBwb3NpdGlvbiBvZiB0aGUgYXhpcyBpdHNlbGYgaWYgaXQncyBmcmVlLlxuICAgICAgICAgKi9cbiAgICAgICAgaWYoc3VicGxvdHNXaXRoQXgpIHtcbiAgICAgICAgICAgIHZhciBmdWxsUmFuZ2UgPSBheC5fY291bnRlclNwYW4gPSBbSW5maW5pdHksIC1JbmZpbml0eV07XG5cbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzdWJwbG90c1dpdGhBeC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW3N1YnBsb3RzV2l0aEF4W2ldXTtcbiAgICAgICAgICAgICAgICB2YXIgY291bnRlckF4aXMgPSBwbG90aW5mb1soYXhMZXR0ZXIgPT09ICd4JykgPyAneWF4aXMnIDogJ3hheGlzJ107XG5cbiAgICAgICAgICAgICAgICBleHRlbmRSYW5nZShmdWxsUmFuZ2UsIFtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlckF4aXMuX29mZnNldCxcbiAgICAgICAgICAgICAgICAgICAgY291bnRlckF4aXMuX29mZnNldCArIGNvdW50ZXJBeGlzLl9sZW5ndGhcbiAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoYXguYW5jaG9yID09PSAnZnJlZScpIHtcbiAgICAgICAgICAgICAgICBleHRlbmRSYW5nZShmdWxsUmFuZ2UsIChheExldHRlciA9PT0gJ3gnKSA/XG4gICAgICAgICAgICAgICAgICAgIFtheC5fYm91bmRpbmdCb3guYm90dG9tLCBheC5fYm91bmRpbmdCb3gudG9wXSA6XG4gICAgICAgICAgICAgICAgICAgIFtheC5fYm91bmRpbmdCb3gucmlnaHQsIGF4Ll9ib3VuZGluZ0JveC5sZWZ0XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaGFzUmFuZ2VTbGlkZXIgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ3Jhbmdlc2xpZGVyJywgJ2lzVmlzaWJsZScpKGF4KTtcblxuICAgIGZ1bmN0aW9uIGRvQXV0b01hcmdpbnMoKSB7XG4gICAgICAgIHZhciBzID0gYXguc2lkZS5jaGFyQXQoMCk7XG4gICAgICAgIHZhciBwdXNoO1xuICAgICAgICB2YXIgcmFuZ2VTbGlkZXJQdXNoO1xuXG4gICAgICAgIGlmKGhhc1JhbmdlU2xpZGVyKSB7XG4gICAgICAgICAgICByYW5nZVNsaWRlclB1c2ggPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ3Jhbmdlc2xpZGVyJywgJ2F1dG9NYXJnaW5PcHRzJykoZ2QsIGF4KTtcbiAgICAgICAgfVxuICAgICAgICBQbG90cy5hdXRvTWFyZ2luKGdkLCByYW5nZVNsaWRlckF1dG9NYXJnaW5JRChheCksIHJhbmdlU2xpZGVyUHVzaCk7XG5cbiAgICAgICAgaWYoYXguYXV0b21hcmdpbiAmJiAoIWhhc1JhbmdlU2xpZGVyIHx8IHMgIT09ICdiJykpIHtcbiAgICAgICAgICAgIHB1c2ggPSB7eDogMCwgeTogMCwgcjogMCwgbDogMCwgdDogMCwgYjogMH07XG5cbiAgICAgICAgICAgIHZhciBiYm94ID0gYXguX2JvdW5kaW5nQm94O1xuICAgICAgICAgICAgdmFyIHRpdGxlT2Zmc2V0ID0gZ2V0VGl0bGVPZmZzZXQoZ2QsIGF4KTtcbiAgICAgICAgICAgIHZhciBhbmNob3JBeERvbWFpbkluZGV4O1xuICAgICAgICAgICAgdmFyIG9mZnNldDtcblxuICAgICAgICAgICAgc3dpdGNoKGF4TGV0dGVyICsgcykge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3hiJzpcbiAgICAgICAgICAgICAgICAgICAgYW5jaG9yQXhEb21haW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIG9mZnNldCA9IGJib3gudG9wIC0gdGl0bGVPZmZzZXQ7XG4gICAgICAgICAgICAgICAgICAgIHB1c2hbc10gPSBiYm94LmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAneHQnOlxuICAgICAgICAgICAgICAgICAgICBhbmNob3JBeERvbWFpbkluZGV4ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ID0gdGl0bGVPZmZzZXQgLSBiYm94LmJvdHRvbTtcbiAgICAgICAgICAgICAgICAgICAgcHVzaFtzXSA9IGJib3guaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd5bCc6XG4gICAgICAgICAgICAgICAgICAgIGFuY2hvckF4RG9tYWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXQgPSB0aXRsZU9mZnNldCAtIGJib3gucmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIHB1c2hbc10gPSBiYm94LndpZHRoO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd5cic6XG4gICAgICAgICAgICAgICAgICAgIGFuY2hvckF4RG9tYWluSW5kZXggPSAxO1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXQgPSBiYm94LmxlZnQgLSB0aXRsZU9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgcHVzaFtzXSA9IGJib3gud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwdXNoW2NvdW50ZXJMZXR0ZXJdID0gYXguYW5jaG9yID09PSAnZnJlZScgP1xuICAgICAgICAgICAgICAgIGF4LnBvc2l0aW9uIDpcbiAgICAgICAgICAgICAgICBheC5fYW5jaG9yQXhpcy5kb21haW5bYW5jaG9yQXhEb21haW5JbmRleF07XG5cbiAgICAgICAgICAgIGlmKHB1c2hbc10gPiAwKSB7XG4gICAgICAgICAgICAgICAgcHVzaFtzXSArPSBvZmZzZXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGF4LnRpdGxlLnRleHQgIT09IGZ1bGxMYXlvdXQuX2RmbHRUaXRsZVtheExldHRlcl0pIHtcbiAgICAgICAgICAgICAgICBwdXNoW3NdICs9IGF4LnRpdGxlLmZvbnQuc2l6ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoYXhMZXR0ZXIgPT09ICd4JyAmJiBiYm94LndpZHRoID4gMCkge1xuICAgICAgICAgICAgICAgIHZhciByRXh0cmEgPSBiYm94LnJpZ2h0IC0gKGF4Ll9vZmZzZXQgKyBheC5fbGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBpZihyRXh0cmEgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHB1c2gueCA9IDE7XG4gICAgICAgICAgICAgICAgICAgIHB1c2guciA9IHJFeHRyYTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGxFeHRyYSA9IGF4Ll9vZmZzZXQgLSBiYm94LmxlZnQ7XG4gICAgICAgICAgICAgICAgaWYobEV4dHJhID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBwdXNoLnggPSAwO1xuICAgICAgICAgICAgICAgICAgICBwdXNoLmwgPSBsRXh0cmE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmKGF4TGV0dGVyID09PSAneScgJiYgYmJveC5oZWlnaHQgPiAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJFeHRyYSA9IGJib3guYm90dG9tIC0gKGF4Ll9vZmZzZXQgKyBheC5fbGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBpZihiRXh0cmEgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHB1c2gueSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHB1c2guYiA9IGJFeHRyYTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHRFeHRyYSA9IGF4Ll9vZmZzZXQgLSBiYm94LnRvcDtcbiAgICAgICAgICAgICAgICBpZih0RXh0cmEgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHB1c2gueSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIHB1c2gudCA9IHRFeHRyYTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBQbG90cy5hdXRvTWFyZ2luKGdkLCBheEF1dG9NYXJnaW5JRChheCksIHB1c2gpO1xuICAgIH1cblxuICAgIHNlcS5wdXNoKGNhbGNCb3VuZGluZ0JveCwgZG9BdXRvTWFyZ2lucyk7XG5cbiAgICBpZighb3B0cy5za2lwVGl0bGUgJiZcbiAgICAgICAgIShoYXNSYW5nZVNsaWRlciAmJiBheC5fYm91bmRpbmdCb3ggJiYgYXguc2lkZSA9PT0gJ2JvdHRvbScpXG4gICAgKSB7XG4gICAgICAgIHNlcS5wdXNoKGZ1bmN0aW9uKCkgeyByZXR1cm4gZHJhd1RpdGxlKGdkLCBheCk7IH0pO1xuICAgIH1cblxuICAgIHJldHVybiBMaWIuc3luY09yQXN5bmMoc2VxKTtcbn07XG5cbmZ1bmN0aW9uIGdldEJvdW5kYXJ5VmFscyhheCwgdmFscykge1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICB2YXIgaTtcblxuICAgIC8vIGJvdW5kYXJ5VmFscyBhcmUgbmV2ZXIgdXNlZCBmb3IgbGFiZWxzO1xuICAgIC8vIG5vIG5lZWQgdG8gd29ycnkgYWJvdXQgdGhlIG90aGVyIHRpY2tUZXh0T2JqIGtleXNcbiAgICB2YXIgX3B1c2ggPSBmdW5jdGlvbihkLCBibmRJbmRleCkge1xuICAgICAgICB2YXIgeGIgPSBkLnhibmRbYm5kSW5kZXhdO1xuICAgICAgICBpZih4YiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgb3V0LnB1c2goTGliLmV4dGVuZEZsYXQoe30sIGQsIHt4OiB4Yn0pKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZih2YWxzLmxlbmd0aCkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCB2YWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBfcHVzaCh2YWxzW2ldLCAwKTtcbiAgICAgICAgfVxuICAgICAgICBfcHVzaCh2YWxzW2kgLSAxXSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gZ2V0U2Vjb25kYXJ5TGFiZWxWYWxzKGF4LCB2YWxzKSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBsb29rdXAgPSB7fTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB2YWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBkID0gdmFsc1tpXTtcbiAgICAgICAgaWYobG9va3VwW2QudGV4dDJdKSB7XG4gICAgICAgICAgICBsb29rdXBbZC50ZXh0Ml0ucHVzaChkLngpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9va3VwW2QudGV4dDJdID0gW2QueF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IodmFyIGsgaW4gbG9va3VwKSB7XG4gICAgICAgIG91dC5wdXNoKHRpY2tUZXh0T2JqKGF4LCBMaWIuaW50ZXJwKGxvb2t1cFtrXSwgMC41KSwgaykpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGdldERpdmlkZXJWYWxzKGF4LCB2YWxzKSB7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIHZhciBpLCBjdXJyZW50O1xuXG4gICAgLy8gbmV2ZXIgdXNlZCBmb3IgbGFiZWxzO1xuICAgIC8vIG5vIG5lZWQgdG8gd29ycnkgYWJvdXQgdGhlIG90aGVyIHRpY2tUZXh0T2JqIGtleXNcbiAgICB2YXIgX3B1c2ggPSBmdW5jdGlvbihkLCBibmRJbmRleCkge1xuICAgICAgICB2YXIgeGIgPSBkLnhibmRbYm5kSW5kZXhdO1xuICAgICAgICBpZih4YiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgb3V0LnB1c2goTGliLmV4dGVuZEZsYXQoe30sIGQsIHt4OiB4Yn0pKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZihheC5zaG93ZGl2aWRlcnMgJiYgdmFscy5sZW5ndGgpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgdmFscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGQgPSB2YWxzW2ldO1xuICAgICAgICAgICAgaWYoZC50ZXh0MiAhPT0gY3VycmVudCkge1xuICAgICAgICAgICAgICAgIF9wdXNoKGQsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudCA9IGQudGV4dDI7XG4gICAgICAgIH1cbiAgICAgICAgX3B1c2godmFsc1tpIC0gMV0sIDEpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGdldExhYmVsTGV2ZWxTcGFuKGF4LCBjbHMpIHtcbiAgICB2YXIgYXhMZXR0ZXIgPSBheC5faWQuY2hhckF0KDApO1xuICAgIHZhciBhbmdsZSA9IGF4Ll90aWNrQW5nbGVzW2Nsc10gfHwgMDtcbiAgICB2YXIgcmFkID0gTGliLmRlZzJyYWQoYW5nbGUpO1xuICAgIHZhciBzaW5BID0gTWF0aC5zaW4ocmFkKTtcbiAgICB2YXIgY29zQSA9IE1hdGguY29zKHJhZCk7XG4gICAgdmFyIG1heFggPSAwO1xuICAgIHZhciBtYXhZID0gMDtcblxuICAgIC8vIE4uQi4gRHJhd2luZy5iQm94IGRvZXMgbm90IHRha2UgaW50byBhY2NvdW50IHJvdGF0ZSB0cmFuc2Zvcm1zXG5cbiAgICBheC5fc2VsZWN0aW9uc1tjbHNdLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB0aGlzTGFiZWwgPSBzZWxlY3RUaWNrTGFiZWwodGhpcyk7XG4gICAgICAgIHZhciBiYiA9IERyYXdpbmcuYkJveCh0aGlzTGFiZWwubm9kZSgpKTtcbiAgICAgICAgdmFyIHcgPSBiYi53aWR0aDtcbiAgICAgICAgdmFyIGggPSBiYi5oZWlnaHQ7XG4gICAgICAgIG1heFggPSBNYXRoLm1heChtYXhYLCBjb3NBICogdywgc2luQSAqIGgpO1xuICAgICAgICBtYXhZID0gTWF0aC5tYXgobWF4WSwgc2luQSAqIHcsIGNvc0EgKiBoKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB7eDogbWF4WSwgeTogbWF4WH1bYXhMZXR0ZXJdO1xufVxuXG4vKipcbiAqIFdoaWNoIGRpcmVjdGlvbiBkbyB0aGUgJ2F4LnNpZGUnIHZhbHVlcywgYW5kIGZyZWUgdGlja3MgZ28/XG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGF4IChmdWxsKSBheGlzIG9iamVjdFxuICogIC0ge3N0cmluZ30gX2lkIChzdGFydGluZyB3aXRoICd4JyBvciAneScpXG4gKiAgLSB7c3RyaW5nfSBzaWRlXG4gKiAgLSB7c3RyaW5nfSB0aWNrc1xuICogQHJldHVybiB7YXJyYXl9IGFsbCBlbnRyaWVzIGFyZSBlaXRoZXIgLTEgb3IgMVxuICogIC0gWzBdOiBzaWduIGZvciB0b3AvcmlnaHQgdGlja3MgKGkuZS4gbmVnYXRpdmUgU1ZHIGRpcmVjdGlvbilcbiAqICAtIFsxXTogc2lnbiBmb3IgYm90dG9tL2xlZnQgdGlja3MgKGkuZS4gcG9zaXRpdmUgU1ZHIGRpcmVjdGlvbilcbiAqICAtIFsyXTogc2lnbiBmb3IgdGlja3MgY29ycmVzcG9uZGluZyB0byAnYXguc2lkZSdcbiAqICAtIFszXTogc2lnbiBmb3IgdGlja3MgbWlycm9yaW5nICdheC5zaWRlJ1xuICovXG5heGVzLmdldFRpY2tTaWducyA9IGZ1bmN0aW9uKGF4KSB7XG4gICAgdmFyIGF4TGV0dGVyID0gYXguX2lkLmNoYXJBdCgwKTtcbiAgICB2YXIgc2lkZU9wcG9zaXRlID0ge3g6ICd0b3AnLCB5OiAncmlnaHQnfVtheExldHRlcl07XG4gICAgdmFyIG1haW4gPSBheC5zaWRlID09PSBzaWRlT3Bwb3NpdGUgPyAxIDogLTE7XG4gICAgdmFyIG91dCA9IFstMSwgMSwgbWFpbiwgLW1haW5dO1xuICAgIC8vIHRoZW4gd2UgZmxpcCBpZiBvdXRzaWRlIFhPUiB5IGF4aXNcbiAgICBpZigoYXgudGlja3MgIT09ICdpbnNpZGUnKSA9PT0gKGF4TGV0dGVyID09PSAneCcpKSB7XG4gICAgICAgIG91dCA9IG91dC5tYXAoZnVuY3Rpb24odikgeyByZXR1cm4gLXY7IH0pO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xufTtcblxuLyoqXG4gKiBNYWtlIGF4aXMgdHJhbnNsYXRlIHRyYW5zZm9ybSBmdW5jdGlvblxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBheCAoZnVsbCkgYXhpcyBvYmplY3RcbiAqICAtIHtzdHJpbmd9IF9pZFxuICogIC0ge251bWJlcn0gX29mZnNldFxuICogIC0ge2ZufSBsMnBcbiAqIEByZXR1cm4ge2ZufSBmdW5jdGlvbiBvZiBjYWxjVGlja3MgaXRlbXNcbiAqL1xuYXhlcy5tYWtlVHJhbnNGbiA9IGZ1bmN0aW9uKGF4KSB7XG4gICAgdmFyIGF4TGV0dGVyID0gYXguX2lkLmNoYXJBdCgwKTtcbiAgICB2YXIgb2Zmc2V0ID0gYXguX29mZnNldDtcbiAgICByZXR1cm4gYXhMZXR0ZXIgPT09ICd4JyA/XG4gICAgICAgIGZ1bmN0aW9uKGQpIHsgcmV0dXJuICd0cmFuc2xhdGUoJyArIChvZmZzZXQgKyBheC5sMnAoZC54KSkgKyAnLDApJzsgfSA6XG4gICAgICAgIGZ1bmN0aW9uKGQpIHsgcmV0dXJuICd0cmFuc2xhdGUoMCwnICsgKG9mZnNldCArIGF4LmwycChkLngpKSArICcpJzsgfTtcbn07XG5cbi8qKlxuICogTWFrZSBheGlzIHRpY2sgcGF0aCBzdHJpbmdcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gYXggKGZ1bGwpIGF4aXMgb2JqZWN0XG4gKiAgLSB7c3RyaW5nfSBfaWRcbiAqICAtIHtudW1iZXJ9IHRpY2tsZW5cbiAqICAtIHtudW1iZXJ9IGxpbmV3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IHNoaWZ0IGFsb25nIGRpcmVjdGlvbiBvZiB0aWNrbGVuXG4gKiBAcGFyYW0gezEgb3IgLTF9IHNuZyB0aWNrIHNpZ25cbiAqIEBwYXJhbSB7bnVtYmVyIChvcHRpb25hbCl9IGxlbiB0aWNrIGxlbmd0aFxuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5heGVzLm1ha2VUaWNrUGF0aCA9IGZ1bmN0aW9uKGF4LCBzaGlmdCwgc2duLCBsZW4pIHtcbiAgICBsZW4gPSBsZW4gIT09IHVuZGVmaW5lZCA/IGxlbiA6IGF4LnRpY2tsZW47XG5cbiAgICB2YXIgYXhMZXR0ZXIgPSBheC5faWQuY2hhckF0KDApO1xuICAgIHZhciBwYWQgPSAoYXgubGluZXdpZHRoIHx8IDEpIC8gMjtcblxuICAgIHJldHVybiBheExldHRlciA9PT0gJ3gnID9cbiAgICAgICAgJ00wLCcgKyAoc2hpZnQgKyBwYWQgKiBzZ24pICsgJ3YnICsgKGxlbiAqIHNnbikgOlxuICAgICAgICAnTScgKyAoc2hpZnQgKyBwYWQgKiBzZ24pICsgJywwaCcgKyAobGVuICogc2duKTtcbn07XG5cbi8qKlxuICogTWFrZSBheGlzIHRpY2sgbGFiZWwgeCwgeSBhbmQgYW5jaG9yIGZ1bmN0aW9uc1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBheCAoZnVsbCkgYXhpcyBvYmplY3RcbiAqICAtIHtzdHJpbmd9IF9pZFxuICogIC0ge3N0cmluZ30gdGlja3NcbiAqICAtIHtudW1iZXJ9IHRpY2tsZW5cbiAqICAtIHtzdHJpbmd9IHNpZGVcbiAqICAtIHtudW1iZXJ9IGxpbmV3aWR0aFxuICogIC0ge251bWJlcn0gdGlja2ZvbnQuc2l6ZVxuICogIC0ge2Jvb2xlYW59IHNob3dsaW5lXG4gKiBAcGFyYW0ge251bWJlcn0gc2hpZnRcbiAqIEBwYXJhbSB7bnVtYmVyfSBhbmdsZSBbaW4gZGVncmVlc10gLi4uXG4gKiBAcmV0dXJuIHtvYmplY3R9XG4gKiAgLSB7Zm59IHhGblxuICogIC0ge2ZufSB5Rm5cbiAqICAtIHtmbn0gYW5jaG9yRm5cbiAqICAtIHtmbn0gaGVpZ2h0Rm5cbiAqICAtIHtudW1iZXJ9IGxhYmVsU3RhbmRvZmYgKGdhcCBwYXJhbGxlbCB0byB0aWNrcylcbiAqICAtIHtudW1iZXJ9IGxhYmVsU2hpZnQgKGdhcCBwZXJwZW5kaWN1bGFyIHRvIHRpY2tzKVxuICovXG5heGVzLm1ha2VMYWJlbEZucyA9IGZ1bmN0aW9uKGF4LCBzaGlmdCwgYW5nbGUpIHtcbiAgICB2YXIgYXhMZXR0ZXIgPSBheC5faWQuY2hhckF0KDApO1xuICAgIHZhciB0aWNrc09uT3V0c2lkZUxhYmVscyA9IGF4LnRpY2tzb24gIT09ICdib3VuZGFyaWVzJyAmJiBheC50aWNrcyA9PT0gJ291dHNpZGUnO1xuXG4gICAgdmFyIGxhYmVsU3RhbmRvZmYgPSAwO1xuICAgIHZhciBsYWJlbFNoaWZ0ID0gMDtcblxuICAgIGlmKHRpY2tzT25PdXRzaWRlTGFiZWxzKSB7XG4gICAgICAgIGxhYmVsU3RhbmRvZmYgKz0gYXgudGlja2xlbjtcbiAgICB9XG4gICAgaWYoYW5nbGUgJiYgYXgudGlja3MgPT09ICdvdXRzaWRlJykge1xuICAgICAgICB2YXIgcmFkID0gTGliLmRlZzJyYWQoYW5nbGUpO1xuICAgICAgICBsYWJlbFN0YW5kb2ZmID0gYXgudGlja2xlbiAqIE1hdGguY29zKHJhZCkgKyAxO1xuICAgICAgICBsYWJlbFNoaWZ0ID0gYXgudGlja2xlbiAqIE1hdGguc2luKHJhZCk7XG4gICAgfVxuICAgIGlmKGF4LnNob3d0aWNrbGFiZWxzICYmICh0aWNrc09uT3V0c2lkZUxhYmVscyB8fCBheC5zaG93bGluZSkpIHtcbiAgICAgICAgbGFiZWxTdGFuZG9mZiArPSAwLjIgKiBheC50aWNrZm9udC5zaXplO1xuICAgIH1cbiAgICBsYWJlbFN0YW5kb2ZmICs9IChheC5saW5ld2lkdGggfHwgMSkgLyAyO1xuXG4gICAgdmFyIG91dCA9IHtcbiAgICAgICAgbGFiZWxTdGFuZG9mZjogbGFiZWxTdGFuZG9mZixcbiAgICAgICAgbGFiZWxTaGlmdDogbGFiZWxTaGlmdFxuICAgIH07XG5cbiAgICB2YXIgeDAsIHkwLCBmZiwgZmxpcEl0O1xuXG4gICAgaWYoYXhMZXR0ZXIgPT09ICd4Jykge1xuICAgICAgICBmbGlwSXQgPSBheC5zaWRlID09PSAnYm90dG9tJyA/IDEgOiAtMTtcbiAgICAgICAgeDAgPSBsYWJlbFNoaWZ0ICogZmxpcEl0O1xuICAgICAgICB5MCA9IHNoaWZ0ICsgbGFiZWxTdGFuZG9mZiAqIGZsaXBJdDtcbiAgICAgICAgZmYgPSBheC5zaWRlID09PSAnYm90dG9tJyA/IDEgOiAtMC4yO1xuXG4gICAgICAgIG91dC54Rm4gPSBmdW5jdGlvbihkKSB7IHJldHVybiBkLmR4ICsgeDA7IH07XG4gICAgICAgIG91dC55Rm4gPSBmdW5jdGlvbihkKSB7IHJldHVybiBkLmR5ICsgeTAgKyBkLmZvbnRTaXplICogZmY7IH07XG4gICAgICAgIG91dC5hbmNob3JGbiA9IGZ1bmN0aW9uKGQsIGEpIHtcbiAgICAgICAgICAgIGlmKCFpc051bWVyaWMoYSkgfHwgYSA9PT0gMCB8fCBhID09PSAxODApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ21pZGRsZSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gKGEgKiBmbGlwSXQgPCAwKSA/ICdlbmQnIDogJ3N0YXJ0JztcbiAgICAgICAgfTtcbiAgICAgICAgb3V0LmhlaWdodEZuID0gZnVuY3Rpb24oZCwgYSwgaCkge1xuICAgICAgICAgICAgcmV0dXJuIChhIDwgLTYwIHx8IGEgPiA2MCkgPyAtMC41ICogaCA6XG4gICAgICAgICAgICAgICAgYXguc2lkZSA9PT0gJ3RvcCcgPyAtaCA6XG4gICAgICAgICAgICAgICAgMDtcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYoYXhMZXR0ZXIgPT09ICd5Jykge1xuICAgICAgICBmbGlwSXQgPSBheC5zaWRlID09PSAncmlnaHQnID8gMSA6IC0xO1xuICAgICAgICB4MCA9IGxhYmVsU3RhbmRvZmY7XG4gICAgICAgIHkwID0gLWxhYmVsU2hpZnQgKiBmbGlwSXQ7XG4gICAgICAgIGZmID0gTWF0aC5hYnMoYXgudGlja2FuZ2xlKSA9PT0gOTAgPyAwLjUgOiAwO1xuXG4gICAgICAgIG91dC54Rm4gPSBmdW5jdGlvbihkKSB7IHJldHVybiBkLmR4ICsgc2hpZnQgKyAoeDAgKyBkLmZvbnRTaXplICogZmYpICogZmxpcEl0OyB9O1xuICAgICAgICBvdXQueUZuID0gZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5keSArIHkwICsgZC5mb250U2l6ZSAqIE1JRF9TSElGVDsgfTtcbiAgICAgICAgb3V0LmFuY2hvckZuID0gZnVuY3Rpb24oZCwgYSkge1xuICAgICAgICAgICAgaWYoaXNOdW1lcmljKGEpICYmIE1hdGguYWJzKGEpID09PSA5MCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnbWlkZGxlJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBheC5zaWRlID09PSAncmlnaHQnID8gJ3N0YXJ0JyA6ICdlbmQnO1xuICAgICAgICB9O1xuICAgICAgICBvdXQuaGVpZ2h0Rm4gPSBmdW5jdGlvbihkLCBhLCBoKSB7XG4gICAgICAgICAgICBhICo9IGF4LnNpZGUgPT09ICdsZWZ0JyA/IDEgOiAtMTtcbiAgICAgICAgICAgIHJldHVybiBhIDwgLTMwID8gLWggOlxuICAgICAgICAgICAgICAgIGEgPCAzMCA/IC0wLjUgKiBoIDpcbiAgICAgICAgICAgICAgICAwO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG5mdW5jdGlvbiB0aWNrRGF0YUZuKGQpIHtcbiAgICByZXR1cm4gW2QudGV4dCwgZC54LCBkLmF4SW5mbywgZC5mb250LCBkLmZvbnRTaXplLCBkLmZvbnRDb2xvcl0uam9pbignXycpO1xufVxuXG4vKipcbiAqIERyYXcgYXhpcyB0aWNrc1xuICpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkXG4gKiBAcGFyYW0ge29iamVjdH0gYXggKGZ1bGwpIGF4aXMgb2JqZWN0XG4gKiAgLSB7c3RyaW5nfSBfaWRcbiAqICAtIHtzdHJpbmd9IHRpY2tzXG4gKiAgLSB7bnVtYmVyfSBsaW5ld2lkdGhcbiAqICAtIHtzdHJpbmd9IHRpY2tjb2xvclxuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqIC0ge2FycmF5IG9mIG9iamVjdH0gdmFscyAoY2FsY1RpY2tzIG91dHB1dC1saWtlKVxuICogLSB7ZDMgc2VsZWN0aW9ufSBsYXllclxuICogLSB7c3RyaW5nIG9yIGZufSBwYXRoXG4gKiAtIHtmbn0gdHJhbnNGblxuICogLSB7Ym9vbGVhbn0gY3Jpc3AgKHNldCB0byBmYWxzZSB0byB1bnNldCBjcmlzcC1lZGdlIFNWRyByZW5kZXJpbmcpXG4gKi9cbmF4ZXMuZHJhd1RpY2tzID0gZnVuY3Rpb24oZ2QsIGF4LCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICB2YXIgY2xzID0gYXguX2lkICsgJ3RpY2snO1xuXG4gICAgdmFyIHRpY2tzID0gb3B0cy5sYXllci5zZWxlY3RBbGwoJ3BhdGguJyArIGNscylcbiAgICAgICAgLmRhdGEoYXgudGlja3MgPyBvcHRzLnZhbHMgOiBbXSwgdGlja0RhdGFGbik7XG5cbiAgICB0aWNrcy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICB0aWNrcy5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5jbGFzc2VkKGNscywgMSlcbiAgICAgICAgLmNsYXNzZWQoJ3RpY2tzJywgMSlcbiAgICAgICAgLmNsYXNzZWQoJ2NyaXNwJywgb3B0cy5jcmlzcCAhPT0gZmFsc2UpXG4gICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgYXgudGlja2NvbG9yKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIERyYXdpbmcuY3Jpc3BSb3VuZChnZCwgYXgudGlja3dpZHRoLCAxKSArICdweCcpXG4gICAgICAgIC5hdHRyKCdkJywgb3B0cy5wYXRoKTtcblxuICAgIHRpY2tzLmF0dHIoJ3RyYW5zZm9ybScsIG9wdHMudHJhbnNGbik7XG59O1xuXG4vKipcbiAqIERyYXcgYXhpcyBncmlkXG4gKlxuICogQHBhcmFtIHtET00gZWxlbWVudH0gZ2RcbiAqIEBwYXJhbSB7b2JqZWN0fSBheCAoZnVsbCkgYXhpcyBvYmplY3RcbiAqICAtIHtzdHJpbmd9IF9pZFxuICogIC0ge2Jvb2xlYW59IHNob3dncmlkXG4gKiAgLSB7c3RyaW5nfSBncmlkY29sb3JcbiAqICAtIHtzdHJpbmd9IGdyaWR3aWR0aFxuICogIC0ge2Jvb2xlYW59IHplcm9saW5lXG4gKiAgLSB7c3RyaW5nfSB0eXBlXG4gKiAgLSB7c3RyaW5nfSBkdGlja1xuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqIC0ge2FycmF5IG9mIG9iamVjdH0gdmFscyAoY2FsY1RpY2tzIG91dHB1dC1saWtlKVxuICogLSB7ZDMgc2VsZWN0aW9ufSBsYXllclxuICogLSB7b2JqZWN0fSBjb3VudGVyQXhpcyAoZnVsbCBheGlzIG9iamVjdCBjb3JyZXNwb25kaW5nIHRvIGNvdW50ZXIgYXhpcylcbiAqICAgICBvcHRpb25hbCAtIG9ubHkgcmVxdWlyZWQgaWYgdGhpcyBheGlzIHN1cHBvcnRzIHplcm8gbGluZXNcbiAqIC0ge3N0cmluZyBvciBmbn0gcGF0aFxuICogLSB7Zm59IHRyYW5zRm5cbiAqIC0ge2Jvb2xlYW59IGNyaXNwIChzZXQgdG8gZmFsc2UgdG8gdW5zZXQgY3Jpc3AtZWRnZSBTVkcgcmVuZGVyaW5nKVxuICovXG5heGVzLmRyYXdHcmlkID0gZnVuY3Rpb24oZ2QsIGF4LCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICB2YXIgY2xzID0gYXguX2lkICsgJ2dyaWQnO1xuICAgIHZhciB2YWxzID0gb3B0cy52YWxzO1xuICAgIHZhciBjb3VudGVyQXggPSBvcHRzLmNvdW50ZXJBeGlzO1xuICAgIGlmKGF4LnNob3dncmlkID09PSBmYWxzZSkge1xuICAgICAgICB2YWxzID0gW107XG4gICAgfSBlbHNlIGlmKGNvdW50ZXJBeCAmJiBheGVzLnNob3VsZFNob3daZXJvTGluZShnZCwgYXgsIGNvdW50ZXJBeCkpIHtcbiAgICAgICAgdmFyIGlzQXJyYXlNb2RlID0gYXgudGlja21vZGUgPT09ICdhcnJheSc7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB2YWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgeGkgPSB2YWxzW2ldLng7XG4gICAgICAgICAgICBpZihpc0FycmF5TW9kZSA/ICF4aSA6IChNYXRoLmFicyh4aSkgPCBheC5kdGljayAvIDEwMCkpIHtcbiAgICAgICAgICAgICAgICB2YWxzID0gdmFscy5zbGljZSgwLCBpKS5jb25jYXQodmFscy5zbGljZShpICsgMSkpO1xuICAgICAgICAgICAgICAgIC8vIEluIGFycmF5IG1vZGUgeW91IGNhbiBpbiBwcmluY2lwbGUgaGF2ZSBtdWx0aXBsZVxuICAgICAgICAgICAgICAgIC8vIHRpY2tzIGF0IDAsIHNvIHRlc3QgdGhlbSBhbGwuIE90aGVyd2lzZSBvbmNlIHdlIGZvdW5kXG4gICAgICAgICAgICAgICAgLy8gb25lIHdlIGNhbiBzdG9wLlxuICAgICAgICAgICAgICAgIGlmKGlzQXJyYXlNb2RlKSBpLS07XG4gICAgICAgICAgICAgICAgZWxzZSBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBncmlkID0gb3B0cy5sYXllci5zZWxlY3RBbGwoJ3BhdGguJyArIGNscylcbiAgICAgICAgLmRhdGEodmFscywgdGlja0RhdGFGbik7XG5cbiAgICBncmlkLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGdyaWQuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAuY2xhc3NlZChjbHMsIDEpXG4gICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIG9wdHMuY3Jpc3AgIT09IGZhbHNlKTtcblxuICAgIGF4Ll9ndyA9IERyYXdpbmcuY3Jpc3BSb3VuZChnZCwgYXguZ3JpZHdpZHRoLCAxKTtcblxuICAgIGdyaWQuYXR0cigndHJhbnNmb3JtJywgb3B0cy50cmFuc0ZuKVxuICAgICAgICAuYXR0cignZCcsIG9wdHMucGF0aClcbiAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBheC5ncmlkY29sb3IgfHwgJyNkZGQnKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIGF4Ll9ndyArICdweCcpO1xuXG4gICAgaWYodHlwZW9mIG9wdHMucGF0aCA9PT0gJ2Z1bmN0aW9uJykgZ3JpZC5hdHRyKCdkJywgb3B0cy5wYXRoKTtcbn07XG5cbi8qKlxuICogRHJhdyBheGlzIHplcm8tbGluZVxuICpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkXG4gKiBAcGFyYW0ge29iamVjdH0gYXggKGZ1bGwpIGF4aXMgb2JqZWN0XG4gKiAgLSB7c3RyaW5nfSBfaWRcbiAqICAtIHtib29sZWFufSB6ZXJvbGluZVxuICogIC0ge251bWJlcn0gemVyb2xpbmV3aWR0aFxuICogIC0ge3N0cmluZ30gemVyb2xpbmVjb2xvclxuICogIC0ge251bWJlciAob3B0aW9uYWwpfSBfZ3JpZFdpZHRoQ3Jpc3BSb3VuZFxuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqIC0ge2QzIHNlbGVjdGlvbn0gbGF5ZXJcbiAqIC0ge29iamVjdH0gY291bnRlckF4aXMgKGZ1bGwgYXhpcyBvYmplY3QgY29ycmVzcG9uZGluZyB0byBjb3VudGVyIGF4aXMpXG4gKiAtIHtzdHJpbmcgb3IgZm59IHBhdGhcbiAqIC0ge2ZufSB0cmFuc0ZuXG4gKiAtIHtib29sZWFufSBjcmlzcCAoc2V0IHRvIGZhbHNlIHRvIHVuc2V0IGNyaXNwLWVkZ2UgU1ZHIHJlbmRlcmluZylcbiAqL1xuYXhlcy5kcmF3WmVyb0xpbmUgPSBmdW5jdGlvbihnZCwgYXgsIG9wdHMpIHtcbiAgICBvcHRzID0gb3B0cyB8fCBvcHRzO1xuXG4gICAgdmFyIGNscyA9IGF4Ll9pZCArICd6bCc7XG4gICAgdmFyIHNob3cgPSBheGVzLnNob3VsZFNob3daZXJvTGluZShnZCwgYXgsIG9wdHMuY291bnRlckF4aXMpO1xuXG4gICAgdmFyIHpsID0gb3B0cy5sYXllci5zZWxlY3RBbGwoJ3BhdGguJyArIGNscylcbiAgICAgICAgLmRhdGEoc2hvdyA/IFt7eDogMCwgaWQ6IGF4Ll9pZH1dIDogW10pO1xuXG4gICAgemwuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgemwuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAuY2xhc3NlZChjbHMsIDEpXG4gICAgICAgIC5jbGFzc2VkKCd6bCcsIDEpXG4gICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIG9wdHMuY3Jpc3AgIT09IGZhbHNlKVxuICAgICAgICAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIC8vIHVzZSB0aGUgZmFjdCB0aGF0IG9ubHkgb25lIGVsZW1lbnQgY2FuIGVudGVyIHRvIHRyaWdnZXIgYSBzb3J0LlxuICAgICAgICAgICAgLy8gSWYgc2V2ZXJhbCB6ZXJvbGluZXMgZW50ZXIgYXQgdGhlIHNhbWUgdGltZSB3ZSB3aWxsIHNvcnQgb25jZSBwZXIsXG4gICAgICAgICAgICAvLyBidXQgZ2VuZXJhbGx5IHRoaXMgc2hvdWxkIGJlIGEgbWluaW1hbCBvdmVyaGVhZC5cbiAgICAgICAgICAgIG9wdHMubGF5ZXIuc2VsZWN0QWxsKCdwYXRoJykuc29ydChmdW5jdGlvbihkYSwgZGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXhpc0lkcy5pZFNvcnQoZGEuaWQsIGRiLmlkKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgIHpsLmF0dHIoJ3RyYW5zZm9ybScsIG9wdHMudHJhbnNGbilcbiAgICAgICAgLmF0dHIoJ2QnLCBvcHRzLnBhdGgpXG4gICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgYXguemVyb2xpbmVjb2xvciB8fCBDb2xvci5kZWZhdWx0TGluZSlcbiAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBEcmF3aW5nLmNyaXNwUm91bmQoZ2QsIGF4Lnplcm9saW5ld2lkdGgsIGF4Ll9ndyB8fCAxKSArICdweCcpO1xufTtcblxuLyoqXG4gKiBEcmF3IGF4aXMgdGljayBsYWJlbHNcbiAqXG4gKiBAcGFyYW0ge0RPTSBlbGVtZW50fSBnZFxuICogQHBhcmFtIHtvYmplY3R9IGF4IChmdWxsKSBheGlzIG9iamVjdFxuICogIC0ge3N0cmluZ30gX2lkXG4gKiAgLSB7Ym9vbGVhbn0gc2hvd3RpY2tsYWJlbHNcbiAqICAtIHtudW1iZXJ9IHRpY2thbmdsZVxuICogIC0ge29iamVjdCAob3B0aW9uYWwpfSBfc2VsZWN0aW9uc1xuICogIC0ge29iamVjdH0gKG9wdGlvbmFsKX0gX3RpY2tBbmdsZXNcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzXG4gKiAtIHthcnJheSBvZiBvYmplY3R9IHZhbHMgKGNhbGNUaWNrcyBvdXRwdXQtbGlrZSlcbiAqIC0ge2QzIHNlbGVjdGlvbn0gbGF5ZXJcbiAqIC0ge3N0cmluZyAob3B0aW9uYWwpfSBjbHMgKG5vZGUgY2xhc3NOYW1lKVxuICogLSB7Ym9vbGVhbn0gcmVwb3NpdGlvbk9uVXBkYXRlIChzZXQgdG8gdHJ1ZSB0byByZXBvc2l0aW9uIHVwZGF0ZSBzZWxlY3Rpb24pXG4gKiAtIHtib29sZWFufSBzZWNvbmRhcnlcbiAqIC0ge2ZufSB0cmFuc0ZuXG4gKiAtIHtvYmplY3R9IGxhYmVsRm5zXG4gKiAgKyB7Zm59IHhGblxuICogICsge2ZufSB5Rm5cbiAqICArIHtmbn0gYW5jaG9yRm5cbiAqICArIHtmbn0gaGVpZ2h0Rm5cbiAqL1xuYXhlcy5kcmF3TGFiZWxzID0gZnVuY3Rpb24oZ2QsIGF4LCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICB2YXIgYXhJZCA9IGF4Ll9pZDtcbiAgICB2YXIgYXhMZXR0ZXIgPSBheElkLmNoYXJBdCgwKTtcbiAgICB2YXIgY2xzID0gb3B0cy5jbHMgfHwgYXhJZCArICd0aWNrJztcbiAgICB2YXIgdmFscyA9IG9wdHMudmFscztcbiAgICB2YXIgbGFiZWxGbnMgPSBvcHRzLmxhYmVsRm5zO1xuICAgIHZhciB0aWNrQW5nbGUgPSBvcHRzLnNlY29uZGFyeSA/IDAgOiBheC50aWNrYW5nbGU7XG4gICAgdmFyIGxhc3RBbmdsZSA9IChheC5fdGlja0FuZ2xlcyB8fCB7fSlbY2xzXTtcblxuICAgIHZhciB0aWNrTGFiZWxzID0gb3B0cy5sYXllci5zZWxlY3RBbGwoJ2cuJyArIGNscylcbiAgICAgICAgLmRhdGEoYXguc2hvd3RpY2tsYWJlbHMgPyB2YWxzIDogW10sIHRpY2tEYXRhRm4pO1xuXG4gICAgdmFyIGxhYmVsc1JlYWR5ID0gW107XG5cbiAgICB0aWNrTGFiZWxzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoY2xzLCAxKVxuICAgICAgICAuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgICAgIC8vIG9ubHkgc28gdGV4IGhhcyBwcmVkaWN0YWJsZSBhbGlnbm1lbnQgdGhhdCB3ZSBjYW5cbiAgICAgICAgICAgIC8vIGFsdGVyIGxhdGVyXG4gICAgICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLCAnbWlkZGxlJylcbiAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhpc0xhYmVsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdQcm9taXNlID0gZ2QuX3Byb21pc2VzLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIHRoaXNMYWJlbFxuICAgICAgICAgICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0LCBsYWJlbEZucy54Rm4oZCksIGxhYmVsRm5zLnlGbihkKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBkLmZvbnQsIGQuZm9udFNpemUsIGQuZm9udENvbG9yKVxuICAgICAgICAgICAgICAgICAgICAudGV4dChkLnRleHQpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKTtcblxuICAgICAgICAgICAgICAgIGlmKGdkLl9wcm9taXNlc1tuZXdQcm9taXNlXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBoYXZlIGFuIGFzeW5jIGxhYmVsLCB3ZSdsbCBkZWFsIHdpdGggdGhhdFxuICAgICAgICAgICAgICAgICAgICAvLyBhbGwgaGVyZSBzbyB0YWtlIGl0IG91dCBvZiBnZC5fcHJvbWlzZXMgYW5kXG4gICAgICAgICAgICAgICAgICAgIC8vIGluc3RlYWQgcG9zaXRpb24gdGhlIGxhYmVsIGFuZCBwcm9taXNlIHRoaXMgaW5cbiAgICAgICAgICAgICAgICAgICAgLy8gbGFiZWxzUmVhZHlcbiAgICAgICAgICAgICAgICAgICAgbGFiZWxzUmVhZHkucHVzaChnZC5fcHJvbWlzZXMucG9wKCkudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uTGFiZWxzKHRoaXNMYWJlbCwgdGlja0FuZ2xlKTtcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHN5bmMgbGFiZWw6IGp1c3QgcG9zaXRpb24gaXQgbm93LlxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbkxhYmVscyh0aGlzTGFiZWwsIHRpY2tBbmdsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICB0aWNrTGFiZWxzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGlmKG9wdHMucmVwb3NpdGlvbk9uVXBkYXRlKSB7XG4gICAgICAgIHRpY2tMYWJlbHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuc2VsZWN0KCd0ZXh0JylcbiAgICAgICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMucG9zaXRpb25UZXh0LCBsYWJlbEZucy54Rm4oZCksIGxhYmVsRm5zLnlGbihkKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBvc2l0aW9uTGFiZWxzKHMsIGFuZ2xlKSB7XG4gICAgICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgdGhpc0xhYmVsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIG1hdGhqYXhHcm91cCA9IHRoaXNMYWJlbC5zZWxlY3QoJy50ZXh0LW1hdGgtZ3JvdXAnKTtcbiAgICAgICAgICAgIHZhciBhbmNob3IgPSBsYWJlbEZucy5hbmNob3JGbihkLCBhbmdsZSk7XG5cbiAgICAgICAgICAgIHZhciB0cmFuc2Zvcm0gPSBvcHRzLnRyYW5zRm4uY2FsbCh0aGlzTGFiZWwubm9kZSgpLCBkKSArXG4gICAgICAgICAgICAgICAgKChpc051bWVyaWMoYW5nbGUpICYmICthbmdsZSAhPT0gMCkgP1xuICAgICAgICAgICAgICAgICgnIHJvdGF0ZSgnICsgYW5nbGUgKyAnLCcgKyBsYWJlbEZucy54Rm4oZCkgKyAnLCcgK1xuICAgICAgICAgICAgICAgICAgICAobGFiZWxGbnMueUZuKGQpIC0gZC5mb250U2l6ZSAvIDIpICsgJyknKSA6XG4gICAgICAgICAgICAgICAgJycpO1xuXG4gICAgICAgICAgICAvLyBob3cgbXVjaCB0byBzaGlmdCBhIG11bHRpLWxpbmUgbGFiZWwgdG8gY2VudGVyIGl0IHZlcnRpY2FsbHkuXG4gICAgICAgICAgICB2YXIgbkxpbmVzID0gc3ZnVGV4dFV0aWxzLmxpbmVDb3VudCh0aGlzTGFiZWwpO1xuICAgICAgICAgICAgdmFyIGxpbmVIZWlnaHQgPSBMSU5FX1NQQUNJTkcgKiBkLmZvbnRTaXplO1xuICAgICAgICAgICAgdmFyIGFuY2hvckhlaWdodCA9IGxhYmVsRm5zLmhlaWdodEZuKGQsIGlzTnVtZXJpYyhhbmdsZSkgPyArYW5nbGUgOiAwLCAobkxpbmVzIC0gMSkgKiBsaW5lSGVpZ2h0KTtcblxuICAgICAgICAgICAgaWYoYW5jaG9ySGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtICs9ICcgdHJhbnNsYXRlKDAsICcgKyBhbmNob3JIZWlnaHQgKyAnKSc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKG1hdGhqYXhHcm91cC5lbXB0eSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpc0xhYmVsLnNlbGVjdCgndGV4dCcpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zZm9ybSxcbiAgICAgICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogYW5jaG9yXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBtaldpZHRoID0gRHJhd2luZy5iQm94KG1hdGhqYXhHcm91cC5ub2RlKCkpLndpZHRoO1xuICAgICAgICAgICAgICAgIHZhciBtalNoaWZ0ID0gbWpXaWR0aCAqIHtlbmQ6IC0wLjUsIHN0YXJ0OiAwLjV9W2FuY2hvcl07XG4gICAgICAgICAgICAgICAgbWF0aGpheEdyb3VwLmF0dHIoJ3RyYW5zZm9ybScsIHRyYW5zZm9ybSArIChtalNoaWZ0ID8gJ3RyYW5zbGF0ZSgnICsgbWpTaGlmdCArICcsMCknIDogJycpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gbWFrZSBzdXJlIGFsbCBsYWJlbHMgYXJlIGNvcnJlY3RseSBwb3NpdGlvbmVkIGF0IHRoZWlyIGJhc2UgYW5nbGVcbiAgICAvLyB0aGUgcG9zaXRpb25MYWJlbHMgY2FsbCBhYm92ZSBpcyBvbmx5IGZvciBuZXdseSBkcmF3biBsYWJlbHMuXG4gICAgLy8gZG8gdGhpcyB3aXRob3V0IHdhaXRpbmcsIHVzaW5nIHRoZSBsYXN0IGNhbGN1bGF0ZWQgYW5nbGUgdG9cbiAgICAvLyBtaW5pbWl6ZSBmbGlja2VyLCB0aGVuIGRvIGl0IGFnYWluIHdoZW4gd2Uga25vdyBhbGwgbGFiZWxzIGFyZVxuICAgIC8vIHRoZXJlLCBwdXR0aW5nIGJhY2sgdGhlIHByZXNjcmliZWQgYW5nbGUgdG8gY2hlY2sgZm9yIG92ZXJsYXBzLlxuICAgIHBvc2l0aW9uTGFiZWxzKHRpY2tMYWJlbHMsIGxhc3RBbmdsZSB8fCB0aWNrQW5nbGUpO1xuXG4gICAgZnVuY3Rpb24gYWxsTGFiZWxzUmVhZHkoKSB7XG4gICAgICAgIHJldHVybiBsYWJlbHNSZWFkeS5sZW5ndGggJiYgUHJvbWlzZS5hbGwobGFiZWxzUmVhZHkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpeExhYmVsT3ZlcmxhcHMoKSB7XG4gICAgICAgIHBvc2l0aW9uTGFiZWxzKHRpY2tMYWJlbHMsIHRpY2tBbmdsZSk7XG5cbiAgICAgICAgdmFyIGF1dG9hbmdsZSA9IG51bGw7XG5cbiAgICAgICAgLy8gY2hlY2sgZm9yIGF1dG8tYW5nbGluZyBpZiB4IGxhYmVscyBvdmVybGFwXG4gICAgICAgIC8vIGRvbid0IGF1dG8tYW5nbGUgYXQgYWxsIGZvciBsb2cgYXhlcyB3aXRoXG4gICAgICAgIC8vIGJhc2UgYW5kIGRpZ2l0IGZvcm1hdFxuICAgICAgICBpZih2YWxzLmxlbmd0aCAmJiBheExldHRlciA9PT0gJ3gnICYmICFpc051bWVyaWModGlja0FuZ2xlKSAmJlxuICAgICAgICAgICAgKGF4LnR5cGUgIT09ICdsb2cnIHx8IFN0cmluZyhheC5kdGljaykuY2hhckF0KDApICE9PSAnRCcpXG4gICAgICAgICkge1xuICAgICAgICAgICAgYXV0b2FuZ2xlID0gMDtcblxuICAgICAgICAgICAgdmFyIG1heEZvbnRTaXplID0gMDtcbiAgICAgICAgICAgIHZhciBsYmJBcnJheSA9IFtdO1xuICAgICAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgICAgIHRpY2tMYWJlbHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgbWF4Rm9udFNpemUgPSBNYXRoLm1heChtYXhGb250U2l6ZSwgZC5mb250U2l6ZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgeCA9IGF4LmwycChkLngpO1xuICAgICAgICAgICAgICAgIHZhciB0aGlzTGFiZWwgPSBzZWxlY3RUaWNrTGFiZWwodGhpcyk7XG4gICAgICAgICAgICAgICAgdmFyIGJiID0gRHJhd2luZy5iQm94KHRoaXNMYWJlbC5ub2RlKCkpO1xuXG4gICAgICAgICAgICAgICAgbGJiQXJyYXkucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlnbm9yZSBhYm91dCB5LCBqdXN0IGRlYWwgd2l0aCB4IG92ZXJsYXBzXG4gICAgICAgICAgICAgICAgICAgIHRvcDogMCxcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tOiAxMCxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMCxcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogeCAtIGJiLndpZHRoIC8gMixcbiAgICAgICAgICAgICAgICAgICAgLy8gaW1wb3NlIGEgMnB4IGdhcFxuICAgICAgICAgICAgICAgICAgICByaWdodDogeCArIGJiLndpZHRoIC8gMiArIDIsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiBiYi53aWR0aCArIDJcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZigoYXgudGlja3NvbiA9PT0gJ2JvdW5kYXJpZXMnIHx8IGF4LnNob3dkaXZpZGVycykgJiYgIW9wdHMuc2Vjb25kYXJ5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGdhcCA9IDI7XG4gICAgICAgICAgICAgICAgaWYoYXgudGlja3MpIGdhcCArPSBheC50aWNrd2lkdGggLyAyO1xuXG4gICAgICAgICAgICAgICAgLy8gVE9ETyBzaG91bGQgc2Vjb25kYXJ5IGxhYmVscyBhbHNvIGZhbGwgaW50byB0aGlzIGZpeC1vdmVybGFwIHJlZ2ltZT9cblxuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxiYkFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB4Ym5kID0gdmFsc1tpXS54Ym5kO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGJiID0gbGJiQXJyYXlbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmKFxuICAgICAgICAgICAgICAgICAgICAgICAgKHhibmRbMF0gIT09IG51bGwgJiYgKGxiYi5sZWZ0IC0gYXgubDJwKHhibmRbMF0pKSA8IGdhcCkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICh4Ym5kWzFdICE9PSBudWxsICYmIChheC5sMnAoeGJuZFsxXSkgLSBsYmIucmlnaHQpIDwgZ2FwKVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9hbmdsZSA9IDkwO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciB2TGVuID0gdmFscy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIHRpY2tTcGFjaW5nID0gTWF0aC5hYnMoKHZhbHNbdkxlbiAtIDFdLnggLSB2YWxzWzBdLngpICogYXguX20pIC8gKHZMZW4gLSAxKTtcbiAgICAgICAgICAgICAgICB2YXIgcm90YXRlOTAgPSAodGlja1NwYWNpbmcgPCBtYXhGb250U2l6ZSAqIDIuNSkgfHwgYXgudHlwZSA9PT0gJ211bHRpY2F0ZWdvcnknO1xuXG4gICAgICAgICAgICAgICAgLy8gYW55IG92ZXJsYXAgYXQgYWxsIC0gc2V0IDMwIGRlZ3JlZXMgb3IgOTAgZGVncmVlc1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxiYkFycmF5Lmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZihMaWIuYkJveEludGVyc2VjdChsYmJBcnJheVtpXSwgbGJiQXJyYXlbaSArIDFdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXV0b2FuZ2xlID0gcm90YXRlOTAgPyA5MCA6IDMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGF1dG9hbmdsZSkge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uTGFiZWxzKHRpY2tMYWJlbHMsIGF1dG9hbmdsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihheC5fdGlja0FuZ2xlcykge1xuICAgICAgICAgICAgYXguX3RpY2tBbmdsZXNbY2xzXSA9IGF1dG9hbmdsZSA9PT0gbnVsbCA/XG4gICAgICAgICAgICAgICAgKGlzTnVtZXJpYyh0aWNrQW5nbGUpID8gdGlja0FuZ2xlIDogMCkgOlxuICAgICAgICAgICAgICAgIGF1dG9hbmdsZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGF4Ll9zZWxlY3Rpb25zKSB7XG4gICAgICAgIGF4Ll9zZWxlY3Rpb25zW2Nsc10gPSB0aWNrTGFiZWxzO1xuICAgIH1cblxuICAgIHZhciBkb25lID0gTGliLnN5bmNPckFzeW5jKFthbGxMYWJlbHNSZWFkeSwgZml4TGFiZWxPdmVybGFwc10pO1xuICAgIGlmKGRvbmUgJiYgZG9uZS50aGVuKSBnZC5fcHJvbWlzZXMucHVzaChkb25lKTtcbiAgICByZXR1cm4gZG9uZTtcbn07XG5cbi8qKlxuICogRHJhdyBheGlzIGRpdmlkZXJzXG4gKlxuICogQHBhcmFtIHtET00gZWxlbWVudH0gZ2RcbiAqIEBwYXJhbSB7b2JqZWN0fSBheCAoZnVsbCkgYXhpcyBvYmplY3RcbiAqICAtIHtzdHJpbmd9IF9pZFxuICogIC0ge3N0cmluZ30gc2hvd2RpdmlkZXJzXG4gKiAgLSB7bnVtYmVyfSBkaXZpZGVyd2lkdGhcbiAqICAtIHtzdHJpbmd9IGRpdmlkZXJjb2xvclxuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqIC0ge2FycmF5IG9mIG9iamVjdH0gdmFscyAoY2FsY1RpY2tzIG91dHB1dC1saWtlKVxuICogLSB7ZDMgc2VsZWN0aW9ufSBsYXllclxuICogLSB7Zm59IHBhdGhcbiAqIC0ge2ZufSB0cmFuc0ZuXG4gKi9cbmZ1bmN0aW9uIGRyYXdEaXZpZGVycyhnZCwgYXgsIG9wdHMpIHtcbiAgICB2YXIgY2xzID0gYXguX2lkICsgJ2RpdmlkZXInO1xuICAgIHZhciB2YWxzID0gb3B0cy52YWxzO1xuXG4gICAgdmFyIGRpdmlkZXJzID0gb3B0cy5sYXllci5zZWxlY3RBbGwoJ3BhdGguJyArIGNscylcbiAgICAgICAgLmRhdGEodmFscywgdGlja0RhdGFGbik7XG5cbiAgICBkaXZpZGVycy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBkaXZpZGVycy5lbnRlcigpLmluc2VydCgncGF0aCcsICc6Zmlyc3QtY2hpbGQnKVxuICAgICAgICAuY2xhc3NlZChjbHMsIDEpXG4gICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIDEpXG4gICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgYXguZGl2aWRlcmNvbG9yKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIERyYXdpbmcuY3Jpc3BSb3VuZChnZCwgYXguZGl2aWRlcndpZHRoLCAxKSArICdweCcpO1xuXG4gICAgZGl2aWRlcnNcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIG9wdHMudHJhbnNGbilcbiAgICAgICAgLmF0dHIoJ2QnLCBvcHRzLnBhdGgpO1xufVxuXG5mdW5jdGlvbiBnZXRUaXRsZU9mZnNldChnZCwgYXgpIHtcbiAgICB2YXIgZ3MgPSBnZC5fZnVsbExheW91dC5fc2l6ZTtcbiAgICB2YXIgYXhMZXR0ZXIgPSBheC5faWQuY2hhckF0KDApO1xuICAgIHZhciBzaWRlID0gYXguc2lkZTtcbiAgICB2YXIgYW5jaG9yQXhpcztcblxuICAgIGlmKGF4LmFuY2hvciAhPT0gJ2ZyZWUnKSB7XG4gICAgICAgIGFuY2hvckF4aXMgPSBheGlzSWRzLmdldEZyb21JZChnZCwgYXguYW5jaG9yKTtcbiAgICB9IGVsc2UgaWYoYXhMZXR0ZXIgPT09ICd4Jykge1xuICAgICAgICBhbmNob3JBeGlzID0ge1xuICAgICAgICAgICAgX29mZnNldDogZ3MudCArICgxIC0gKGF4LnBvc2l0aW9uIHx8IDApKSAqIGdzLmgsXG4gICAgICAgICAgICBfbGVuZ3RoOiAwXG4gICAgICAgIH07XG4gICAgfSBlbHNlIGlmKGF4TGV0dGVyID09PSAneScpIHtcbiAgICAgICAgYW5jaG9yQXhpcyA9IHtcbiAgICAgICAgICAgIF9vZmZzZXQ6IGdzLmwgKyAoYXgucG9zaXRpb24gfHwgMCkgKiBncy53LFxuICAgICAgICAgICAgX2xlbmd0aDogMFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmKHNpZGUgPT09ICd0b3AnIHx8IHNpZGUgPT09ICdsZWZ0Jykge1xuICAgICAgICByZXR1cm4gYW5jaG9yQXhpcy5fb2Zmc2V0O1xuICAgIH0gZWxzZSBpZihzaWRlID09PSAnYm90dG9tJyB8fCBzaWRlID09PSAncmlnaHQnKSB7XG4gICAgICAgIHJldHVybiBhbmNob3JBeGlzLl9vZmZzZXQgKyBhbmNob3JBeGlzLl9sZW5ndGg7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmF3VGl0bGUoZ2QsIGF4KSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgYXhJZCA9IGF4Ll9pZDtcbiAgICB2YXIgYXhMZXR0ZXIgPSBheElkLmNoYXJBdCgwKTtcbiAgICB2YXIgZm9udFNpemUgPSBheC50aXRsZS5mb250LnNpemU7XG5cbiAgICB2YXIgdGl0bGVTdGFuZG9mZjtcbiAgICBpZihheC50eXBlID09PSAnbXVsdGljYXRlZ29yeScpIHtcbiAgICAgICAgdGl0bGVTdGFuZG9mZiA9IGF4Ll9sYWJlbExlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgb2Zmc2V0QmFzZSA9IDEuNTtcbiAgICAgICAgdGl0bGVTdGFuZG9mZiA9IDEwICsgZm9udFNpemUgKiBvZmZzZXRCYXNlICsgKGF4LmxpbmV3aWR0aCA/IGF4LmxpbmV3aWR0aCAtIDEgOiAwKTtcbiAgICB9XG5cbiAgICB2YXIgdGl0bGVPZmZzZXQgPSBnZXRUaXRsZU9mZnNldChnZCwgYXgpO1xuXG4gICAgdmFyIHRyYW5zZm9ybSwgeCwgeTtcblxuICAgIGlmKGF4TGV0dGVyID09PSAneCcpIHtcbiAgICAgICAgeCA9IGF4Ll9vZmZzZXQgKyBheC5fbGVuZ3RoIC8gMjtcblxuICAgICAgICBpZihheC5zaWRlID09PSAndG9wJykge1xuICAgICAgICAgICAgeSA9IC10aXRsZVN0YW5kb2ZmIC0gZm9udFNpemUgKiAoYXguc2hvd3RpY2tsYWJlbHMgPyAxIDogMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB5ID0gdGl0bGVTdGFuZG9mZiArIGZvbnRTaXplICogKGF4LnNob3d0aWNrbGFiZWxzID8gMS41IDogMC41KTtcbiAgICAgICAgfVxuICAgICAgICB5ICs9IHRpdGxlT2Zmc2V0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHkgPSBheC5fb2Zmc2V0ICsgYXguX2xlbmd0aCAvIDI7XG5cbiAgICAgICAgaWYoYXguc2lkZSA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgeCA9IHRpdGxlU3RhbmRvZmYgKyBmb250U2l6ZSAqIChheC5zaG93dGlja2xhYmVscyA/IDEgOiAwLjUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgeCA9IC10aXRsZVN0YW5kb2ZmIC0gZm9udFNpemUgKiAoYXguc2hvd3RpY2tsYWJlbHMgPyAwLjUgOiAwKTtcbiAgICAgICAgfVxuICAgICAgICB4ICs9IHRpdGxlT2Zmc2V0O1xuXG4gICAgICAgIHRyYW5zZm9ybSA9IHtyb3RhdGU6ICctOTAnLCBvZmZzZXQ6IDB9O1xuICAgIH1cblxuICAgIHZhciBhdm9pZDtcblxuICAgIGlmKGF4LnR5cGUgIT09ICdtdWx0aWNhdGVnb3J5Jykge1xuICAgICAgICB2YXIgdGlja0xhYmVscyA9IGF4Ll9zZWxlY3Rpb25zW2F4Ll9pZCArICd0aWNrJ107XG5cbiAgICAgICAgYXZvaWQgPSB7XG4gICAgICAgICAgICBzZWxlY3Rpb246IHRpY2tMYWJlbHMsXG4gICAgICAgICAgICBzaWRlOiBheC5zaWRlXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYodGlja0xhYmVscyAmJiB0aWNrTGFiZWxzLm5vZGUoKSAmJiB0aWNrTGFiZWxzLm5vZGUoKS5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICB2YXIgdHJhbnNsYXRpb24gPSBEcmF3aW5nLmdldFRyYW5zbGF0ZSh0aWNrTGFiZWxzLm5vZGUoKS5wYXJlbnROb2RlKTtcbiAgICAgICAgICAgIGF2b2lkLm9mZnNldExlZnQgPSB0cmFuc2xhdGlvbi54O1xuICAgICAgICAgICAgYXZvaWQub2Zmc2V0VG9wID0gdHJhbnNsYXRpb24ueTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBUaXRsZXMuZHJhdyhnZCwgYXhJZCArICd0aXRsZScsIHtcbiAgICAgICAgcHJvcENvbnRhaW5lcjogYXgsXG4gICAgICAgIHByb3BOYW1lOiBheC5fbmFtZSArICcudGl0bGUudGV4dCcsXG4gICAgICAgIHBsYWNlaG9sZGVyOiBmdWxsTGF5b3V0Ll9kZmx0VGl0bGVbYXhMZXR0ZXJdLFxuICAgICAgICBhdm9pZDogYXZvaWQsXG4gICAgICAgIHRyYW5zZm9ybTogdHJhbnNmb3JtLFxuICAgICAgICBhdHRyaWJ1dGVzOiB7eDogeCwgeTogeSwgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSd9XG4gICAgfSk7XG59XG5cbmF4ZXMuc2hvdWxkU2hvd1plcm9MaW5lID0gZnVuY3Rpb24oZ2QsIGF4LCBjb3VudGVyQXhpcykge1xuICAgIHZhciBybmcgPSBMaWIuc2ltcGxlTWFwKGF4LnJhbmdlLCBheC5yMmwpO1xuICAgIHJldHVybiAoXG4gICAgICAgIChybmdbMF0gKiBybmdbMV0gPD0gMCkgJiZcbiAgICAgICAgYXguemVyb2xpbmUgJiZcbiAgICAgICAgKGF4LnR5cGUgPT09ICdsaW5lYXInIHx8IGF4LnR5cGUgPT09ICctJykgJiZcbiAgICAgICAgYXguX2dyaWRWYWxzLmxlbmd0aCAmJlxuICAgICAgICAoXG4gICAgICAgICAgICBjbGlwRW5kcyhheCwgMCkgfHxcbiAgICAgICAgICAgICFhbnlDb3VudGVyQXhMaW5lQXRaZXJvKGdkLCBheCwgY291bnRlckF4aXMsIHJuZykgfHxcbiAgICAgICAgICAgIGhhc0JhcnNPckZpbGwoZ2QsIGF4KVxuICAgICAgICApXG4gICAgKTtcbn07XG5cbmF4ZXMuY2xpcEVuZHMgPSBmdW5jdGlvbihheCwgdmFscykge1xuICAgIHJldHVybiB2YWxzLmZpbHRlcihmdW5jdGlvbihkKSB7IHJldHVybiBjbGlwRW5kcyhheCwgZC54KTsgfSk7XG59O1xuXG5mdW5jdGlvbiBjbGlwRW5kcyhheCwgbCkge1xuICAgIHZhciBwID0gYXgubDJwKGwpO1xuICAgIHJldHVybiAocCA+IDEgJiYgcCA8IGF4Ll9sZW5ndGggLSAxKTtcbn1cblxuZnVuY3Rpb24gYW55Q291bnRlckF4TGluZUF0WmVybyhnZCwgYXgsIGNvdW50ZXJBeGlzLCBybmcpIHtcbiAgICB2YXIgbWFpbkNvdW50ZXJBeGlzID0gY291bnRlckF4aXMuX21haW5BeGlzO1xuICAgIGlmKCFtYWluQ291bnRlckF4aXMpIHJldHVybjtcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGF4TGV0dGVyID0gYXguX2lkLmNoYXJBdCgwKTtcbiAgICB2YXIgY291bnRlckxldHRlciA9IGF4ZXMuY291bnRlckxldHRlcihheC5faWQpO1xuXG4gICAgdmFyIHplcm9Qb3NpdGlvbiA9IGF4Ll9vZmZzZXQgKyAoXG4gICAgICAgICgoTWF0aC5hYnMocm5nWzBdKSA8IE1hdGguYWJzKHJuZ1sxXSkpID09PSAoYXhMZXR0ZXIgPT09ICd4JykpID9cbiAgICAgICAgMCA6IGF4Ll9sZW5ndGhcbiAgICApO1xuXG4gICAgZnVuY3Rpb24gbGluZU5lYXJaZXJvKGF4Mikge1xuICAgICAgICBpZighYXgyLnNob3dsaW5lIHx8ICFheDIubGluZXdpZHRoKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHZhciB0b2xlcmFuY2UgPSBNYXRoLm1heCgoYXgyLmxpbmV3aWR0aCArIGF4Lnplcm9saW5ld2lkdGgpIC8gMiwgMSk7XG5cbiAgICAgICAgZnVuY3Rpb24gY2xvc2VFbm91Z2gocG9zMikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBwb3MyID09PSAnbnVtYmVyJyAmJiBNYXRoLmFicyhwb3MyIC0gemVyb1Bvc2l0aW9uKSA8IHRvbGVyYW5jZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNsb3NlRW5vdWdoKGF4Mi5fbWFpbkxpbmVQb3NpdGlvbikgfHwgY2xvc2VFbm91Z2goYXgyLl9tYWluTWlycm9yUG9zaXRpb24pKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbGluZVBvc2l0aW9ucyA9IGF4Mi5fbGluZXBvc2l0aW9ucyB8fCB7fTtcbiAgICAgICAgZm9yKHZhciBrIGluIGxpbmVQb3NpdGlvbnMpIHtcbiAgICAgICAgICAgIGlmKGNsb3NlRW5vdWdoKGxpbmVQb3NpdGlvbnNba11bMF0pIHx8IGNsb3NlRW5vdWdoKGxpbmVQb3NpdGlvbnNba11bMV0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcGxvdGluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1tjb3VudGVyQXhpcy5fbWFpblN1YnBsb3RdO1xuICAgIGlmKCEocGxvdGluZm8ubWFpbnBsb3RpbmZvIHx8IHBsb3RpbmZvKS5vdmVybGF5cy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGxpbmVOZWFyWmVybyhjb3VudGVyQXhpcywgemVyb1Bvc2l0aW9uKTtcbiAgICB9XG5cbiAgICB2YXIgY291bnRlckxldHRlckF4ZXMgPSBheGVzLmxpc3QoZ2QsIGNvdW50ZXJMZXR0ZXIpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjb3VudGVyTGV0dGVyQXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY291bnRlckF4aXMyID0gY291bnRlckxldHRlckF4ZXNbaV07XG4gICAgICAgIGlmKFxuICAgICAgICAgICAgY291bnRlckF4aXMyLl9tYWluQXhpcyA9PT0gbWFpbkNvdW50ZXJBeGlzICYmXG4gICAgICAgICAgICBsaW5lTmVhclplcm8oY291bnRlckF4aXMyLCB6ZXJvUG9zaXRpb24pXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGhhc0JhcnNPckZpbGwoZ2QsIGF4KSB7XG4gICAgdmFyIGZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhO1xuICAgIHZhciBzdWJwbG90ID0gYXguX21haW5TdWJwbG90O1xuICAgIHZhciBheExldHRlciA9IGF4Ll9pZC5jaGFyQXQoMCk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSA9PT0gdHJ1ZSAmJiAodHJhY2UueGF4aXMgKyB0cmFjZS55YXhpcykgPT09IHN1YnBsb3QpIHtcbiAgICAgICAgICAgIGlmKFxuICAgICAgICAgICAgICAgIFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdiYXItbGlrZScpICYmXG4gICAgICAgICAgICAgICAgdHJhY2Uub3JpZW50YXRpb24gPT09IHt4OiAnaCcsIHk6ICd2J31bYXhMZXR0ZXJdXG4gICAgICAgICAgICApIHJldHVybiB0cnVlO1xuXG4gICAgICAgICAgICBpZihcbiAgICAgICAgICAgICAgICB0cmFjZS5maWxsICYmXG4gICAgICAgICAgICAgICAgdHJhY2UuZmlsbC5jaGFyQXQodHJhY2UuZmlsbC5sZW5ndGggLSAxKSA9PT0gYXhMZXR0ZXJcbiAgICAgICAgICAgICkgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBzZWxlY3RUaWNrTGFiZWwoZ1RpY2spIHtcbiAgICB2YXIgcyA9IGQzLnNlbGVjdChnVGljayk7XG4gICAgdmFyIG1qID0gcy5zZWxlY3QoJy50ZXh0LW1hdGgtZ3JvdXAnKTtcbiAgICByZXR1cm4gbWouZW1wdHkoKSA/IHMuc2VsZWN0KCd0ZXh0JykgOiBtajtcbn1cblxuLyoqXG4gKiBGaW5kIGFsbCBtYXJnaW4gcHVzaGVycyBmb3IgMkQgYXhlcyBhbmQgcmVzZXJ2ZSB0aGVtIGZvciBsYXRlciB1c2VcbiAqIEJvdGggbGFiZWwgYW5kIHJhbmdlc2xpZGVyIGF1dG9tYXJnaW4gY2FsY3VsYXRpb25zIGhhcHBlbiBsYXRlciBzb1xuICogd2UgbmVlZCB0byBleHBsaWNpdGx5IGFsbG93IHRoZWlyIGlkcyBpbiBvcmRlciB0byBub3QgZGVsZXRlIHRoZW0uXG4gKlxuICogVE9ETzogY2FuIHdlIHB1bGwgdGhlIGFjdHVhbCBhdXRvbWFyZ2luIGNhbGxzIGZvcndhcmQgdG8gYXZvaWQgdGhpcyBoYWNrP1xuICogV2UncmUgcHJvYmFibHkgYWxzbyBkb2luZyBtdWx0aXBsZSByZWRyYXdzIGluIHRoaXMgY2FzZSwgd291bGQgYmUgZmFzdGVyXG4gKiBpZiB3ZSBjYW4ganVzdCBkbyB0aGUgd2hvbGUgY2FsY3VsYXRpb24gYWhlYWQgb2YgdGltZSBhbmQgZHJhdyBvbmNlLlxuICovXG5heGVzLmFsbG93QXV0b01hcmdpbiA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGF4TGlzdCA9IGF4ZXMubGlzdChnZCwgJycsIHRydWUpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF4ID0gYXhMaXN0W2ldO1xuICAgICAgICBpZihheC5hdXRvbWFyZ2luKSB7XG4gICAgICAgICAgICBQbG90cy5hbGxvd0F1dG9NYXJnaW4oZ2QsIGF4QXV0b01hcmdpbklEKGF4KSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdyYW5nZXNsaWRlcicsICdpc1Zpc2libGUnKShheCkpIHtcbiAgICAgICAgICAgIFBsb3RzLmFsbG93QXV0b01hcmdpbihnZCwgcmFuZ2VTbGlkZXJBdXRvTWFyZ2luSUQoYXgpKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGF4QXV0b01hcmdpbklEKGF4KSB7IHJldHVybiBheC5faWQgKyAnLmF1dG9tYXJnaW4nOyB9XG5mdW5jdGlvbiByYW5nZVNsaWRlckF1dG9NYXJnaW5JRChheCkgeyByZXR1cm4gYXguX2lkICsgJy5yYW5nZXNsaWRlcic7IH1cblxuLy8gc3dhcCBhbGwgdGhlIHByZXNlbnRhdGlvbiBhdHRyaWJ1dGVzIG9mIHRoZSBheGVzIHNob3dpbmcgdGhlc2UgdHJhY2VzXG5heGVzLnN3YXAgPSBmdW5jdGlvbihnZCwgdHJhY2VzKSB7XG4gICAgdmFyIGF4R3JvdXBzID0gbWFrZUF4aXNHcm91cHMoZ2QsIHRyYWNlcyk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhHcm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc3dhcEF4aXNHcm91cChnZCwgYXhHcm91cHNbaV0ueCwgYXhHcm91cHNbaV0ueSk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gbWFrZUF4aXNHcm91cHMoZ2QsIHRyYWNlcykge1xuICAgIHZhciBncm91cHMgPSBbXTtcbiAgICB2YXIgaSwgajtcblxuICAgIGZvcihpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZ3JvdXBzaSA9IFtdO1xuICAgICAgICB2YXIgeGkgPSBnZC5fZnVsbERhdGFbdHJhY2VzW2ldXS54YXhpcztcbiAgICAgICAgdmFyIHlpID0gZ2QuX2Z1bGxEYXRhW3RyYWNlc1tpXV0ueWF4aXM7XG4gICAgICAgIGlmKCF4aSB8fCAheWkpIGNvbnRpbnVlOyAvLyBub3QgYSAyRCBjYXJ0ZXNpYW4gdHJhY2U/XG5cbiAgICAgICAgZm9yKGogPSAwOyBqIDwgZ3JvdXBzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZihncm91cHNbal0ueC5pbmRleE9mKHhpKSAhPT0gLTEgfHwgZ3JvdXBzW2pdLnkuaW5kZXhPZih5aSkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBzaS5wdXNoKGopO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWdyb3Vwc2kubGVuZ3RoKSB7XG4gICAgICAgICAgICBncm91cHMucHVzaCh7eDogW3hpXSwgeTogW3lpXX0pO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZ3JvdXAwID0gZ3JvdXBzW2dyb3Vwc2lbMF1dO1xuICAgICAgICB2YXIgZ3JvdXBqO1xuXG4gICAgICAgIGlmKGdyb3Vwc2kubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgZm9yKGogPSAxOyBqIDwgZ3JvdXBzaS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGdyb3VwaiA9IGdyb3Vwc1tncm91cHNpW2pdXTtcbiAgICAgICAgICAgICAgICBtZXJnZUF4aXNHcm91cHMoZ3JvdXAwLngsIGdyb3Vwai54KTtcbiAgICAgICAgICAgICAgICBtZXJnZUF4aXNHcm91cHMoZ3JvdXAwLnksIGdyb3Vwai55KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBtZXJnZUF4aXNHcm91cHMoZ3JvdXAwLngsIFt4aV0pO1xuICAgICAgICBtZXJnZUF4aXNHcm91cHMoZ3JvdXAwLnksIFt5aV0pO1xuICAgIH1cblxuICAgIHJldHVybiBncm91cHM7XG59XG5cbmZ1bmN0aW9uIG1lcmdlQXhpc0dyb3VwcyhpbnRvU2V0LCBmcm9tU2V0KSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZyb21TZXQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoaW50b1NldC5pbmRleE9mKGZyb21TZXRbaV0pID09PSAtMSkgaW50b1NldC5wdXNoKGZyb21TZXRbaV0pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc3dhcEF4aXNHcm91cChnZCwgeElkcywgeUlkcykge1xuICAgIHZhciB4RnVsbEF4ZXMgPSBbXTtcbiAgICB2YXIgeUZ1bGxBeGVzID0gW107XG4gICAgdmFyIGxheW91dCA9IGdkLmxheW91dDtcbiAgICB2YXIgaSwgajtcblxuICAgIGZvcihpID0gMDsgaSA8IHhJZHMubGVuZ3RoOyBpKyspIHhGdWxsQXhlcy5wdXNoKGF4ZXMuZ2V0RnJvbUlkKGdkLCB4SWRzW2ldKSk7XG4gICAgZm9yKGkgPSAwOyBpIDwgeUlkcy5sZW5ndGg7IGkrKykgeUZ1bGxBeGVzLnB1c2goYXhlcy5nZXRGcm9tSWQoZ2QsIHlJZHNbaV0pKTtcblxuICAgIHZhciBhbGxBeEtleXMgPSBPYmplY3Qua2V5cyhheEF0dHJzKTtcblxuICAgIHZhciBub1N3YXBBdHRycyA9IFtcbiAgICAgICAgJ2FuY2hvcicsICdkb21haW4nLCAnb3ZlcmxheWluZycsICdwb3NpdGlvbicsICdzaWRlJywgJ3RpY2thbmdsZScsICdlZGl0VHlwZSdcbiAgICBdO1xuICAgIHZhciBudW1lcmljVHlwZXMgPSBbJ2xpbmVhcicsICdsb2cnXTtcblxuICAgIGZvcihpID0gMDsgaSA8IGFsbEF4S2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIga2V5aSA9IGFsbEF4S2V5c1tpXTtcbiAgICAgICAgdmFyIHhWYWwgPSB4RnVsbEF4ZXNbMF1ba2V5aV07XG4gICAgICAgIHZhciB5VmFsID0geUZ1bGxBeGVzWzBdW2tleWldO1xuICAgICAgICB2YXIgYWxsRXF1YWwgPSB0cnVlO1xuICAgICAgICB2YXIgY29lcmNlTGluZWFyWCA9IGZhbHNlO1xuICAgICAgICB2YXIgY29lcmNlTGluZWFyWSA9IGZhbHNlO1xuICAgICAgICBpZihrZXlpLmNoYXJBdCgwKSA9PT0gJ18nIHx8IHR5cGVvZiB4VmFsID09PSAnZnVuY3Rpb24nIHx8XG4gICAgICAgICAgICAgICAgbm9Td2FwQXR0cnMuaW5kZXhPZihrZXlpKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGZvcihqID0gMTsgaiA8IHhGdWxsQXhlcy5sZW5ndGggJiYgYWxsRXF1YWw7IGorKykge1xuICAgICAgICAgICAgdmFyIHhWYWxpID0geEZ1bGxBeGVzW2pdW2tleWldO1xuICAgICAgICAgICAgaWYoa2V5aSA9PT0gJ3R5cGUnICYmIG51bWVyaWNUeXBlcy5pbmRleE9mKHhWYWwpICE9PSAtMSAmJlxuICAgICAgICAgICAgICAgICAgICBudW1lcmljVHlwZXMuaW5kZXhPZih4VmFsaSkgIT09IC0xICYmIHhWYWwgIT09IHhWYWxpKSB7XG4gICAgICAgICAgICAgICAgLy8gdHlwZSBpcyBzcGVjaWFsIC0gaWYgd2UgZmluZCBhIG1peHR1cmUgb2YgbGluZWFyIGFuZCBsb2csXG4gICAgICAgICAgICAgICAgLy8gY29lcmNlIHRoZW0gYWxsIHRvIGxpbmVhciBvbiBmbGlwcGluZ1xuICAgICAgICAgICAgICAgIGNvZXJjZUxpbmVhclggPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIGlmKHhWYWxpICE9PSB4VmFsKSBhbGxFcXVhbCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGZvcihqID0gMTsgaiA8IHlGdWxsQXhlcy5sZW5ndGggJiYgYWxsRXF1YWw7IGorKykge1xuICAgICAgICAgICAgdmFyIHlWYWxpID0geUZ1bGxBeGVzW2pdW2tleWldO1xuICAgICAgICAgICAgaWYoa2V5aSA9PT0gJ3R5cGUnICYmIG51bWVyaWNUeXBlcy5pbmRleE9mKHlWYWwpICE9PSAtMSAmJlxuICAgICAgICAgICAgICAgICAgICBudW1lcmljVHlwZXMuaW5kZXhPZih5VmFsaSkgIT09IC0xICYmIHlWYWwgIT09IHlWYWxpKSB7XG4gICAgICAgICAgICAgICAgLy8gdHlwZSBpcyBzcGVjaWFsIC0gaWYgd2UgZmluZCBhIG1peHR1cmUgb2YgbGluZWFyIGFuZCBsb2csXG4gICAgICAgICAgICAgICAgLy8gY29lcmNlIHRoZW0gYWxsIHRvIGxpbmVhciBvbiBmbGlwcGluZ1xuICAgICAgICAgICAgICAgIGNvZXJjZUxpbmVhclkgPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIGlmKHlGdWxsQXhlc1tqXVtrZXlpXSAhPT0geVZhbCkgYWxsRXF1YWwgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZihhbGxFcXVhbCkge1xuICAgICAgICAgICAgaWYoY29lcmNlTGluZWFyWCkgbGF5b3V0W3hGdWxsQXhlc1swXS5fbmFtZV0udHlwZSA9ICdsaW5lYXInO1xuICAgICAgICAgICAgaWYoY29lcmNlTGluZWFyWSkgbGF5b3V0W3lGdWxsQXhlc1swXS5fbmFtZV0udHlwZSA9ICdsaW5lYXInO1xuICAgICAgICAgICAgc3dhcEF4aXNBdHRycyhsYXlvdXQsIGtleWksIHhGdWxsQXhlcywgeUZ1bGxBeGVzLCBnZC5fZnVsbExheW91dC5fZGZsdFRpdGxlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG5vdyBzd2FwIHgmeSBmb3IgYW55IGFubm90YXRpb25zIGFuY2hvcmVkIHRvIHRoZXNlIHggJiB5XG4gICAgZm9yKGkgPSAwOyBpIDwgZ2QuX2Z1bGxMYXlvdXQuYW5ub3RhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGFubiA9IGdkLl9mdWxsTGF5b3V0LmFubm90YXRpb25zW2ldO1xuICAgICAgICBpZih4SWRzLmluZGV4T2YoYW5uLnhyZWYpICE9PSAtMSAmJlxuICAgICAgICAgICAgICAgIHlJZHMuaW5kZXhPZihhbm4ueXJlZikgIT09IC0xKSB7XG4gICAgICAgICAgICBMaWIuc3dhcEF0dHJzKGxheW91dC5hbm5vdGF0aW9uc1tpXSwgWyc/J10pO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzd2FwQXhpc0F0dHJzKGxheW91dCwga2V5LCB4RnVsbEF4ZXMsIHlGdWxsQXhlcywgZGZsdFRpdGxlKSB7XG4gICAgLy8gaW4gY2FzZSB0aGUgdmFsdWUgaXMgdGhlIGRlZmF1bHQgZm9yIGVpdGhlciBheGlzLFxuICAgIC8vIGxvb2sgYXQgdGhlIGZpcnN0IGF4aXMgaW4gZWFjaCBsaXN0IGFuZCBzZWUgaWZcbiAgICAvLyB0aGlzIGtleSdzIHZhbHVlIGlzIHVuZGVmaW5lZFxuICAgIHZhciBucCA9IExpYi5uZXN0ZWRQcm9wZXJ0eTtcbiAgICB2YXIgeFZhbCA9IG5wKGxheW91dFt4RnVsbEF4ZXNbMF0uX25hbWVdLCBrZXkpLmdldCgpO1xuICAgIHZhciB5VmFsID0gbnAobGF5b3V0W3lGdWxsQXhlc1swXS5fbmFtZV0sIGtleSkuZ2V0KCk7XG4gICAgdmFyIGk7XG5cbiAgICBpZihrZXkgPT09ICd0aXRsZScpIHtcbiAgICAgICAgLy8gc3BlY2lhbCBoYW5kbGluZyBvZiBwbGFjZWhvbGRlciB0aXRsZXNcbiAgICAgICAgaWYoeFZhbCAmJiB4VmFsLnRleHQgPT09IGRmbHRUaXRsZS54KSB7XG4gICAgICAgICAgICB4VmFsLnRleHQgPSBkZmx0VGl0bGUueTtcbiAgICAgICAgfVxuICAgICAgICBpZih5VmFsICYmIHlWYWwudGV4dCA9PT0gZGZsdFRpdGxlLnkpIHtcbiAgICAgICAgICAgIHlWYWwudGV4dCA9IGRmbHRUaXRsZS54O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgeEZ1bGxBeGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG5wKGxheW91dCwgeEZ1bGxBeGVzW2ldLl9uYW1lICsgJy4nICsga2V5KS5zZXQoeVZhbCk7XG4gICAgfVxuICAgIGZvcihpID0gMDsgaSA8IHlGdWxsQXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBucChsYXlvdXQsIHlGdWxsQXhlc1tpXS5fbmFtZSArICcuJyArIGtleSkuc2V0KHhWYWwpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaXNBbmd1bGFyKGF4KSB7XG4gICAgcmV0dXJuIGF4Ll9pZCA9PT0gJ2FuZ3VsYXJheGlzJztcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vY29tcG9uZW50cy90aXRsZXNcIjo2ODEsXCIuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50XCI6Njg4LFwiLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbFwiOjY5NSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3Bsb3RzL3Bsb3RzXCI6ODI4LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2F1dG9yYW5nZVwiOjc2NixcIi4vYXhpc19hdXRvdHlwZVwiOjc2OCxcIi4vYXhpc19pZHNcIjo3NzAsXCIuL2NsZWFuX3RpY2tzXCI6NzcyLFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjc3OSxcIi4vc2V0X2NvbnZlcnRcIjo3ODUsXCJkM1wiOjE2MyxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sNzY4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEJBRE5VTSA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gYXV0b1R5cGUoYXJyYXksIGNhbGVuZGFyLCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICBpZighb3B0cy5ub011bHRpQ2F0ZWdvcnkgJiYgbXVsdGlDYXRlZ29yeShhcnJheSkpIHJldHVybiAnbXVsdGljYXRlZ29yeSc7XG4gICAgaWYobW9yZURhdGVzKGFycmF5LCBjYWxlbmRhcikpIHJldHVybiAnZGF0ZSc7XG4gICAgaWYoY2F0ZWdvcnkoYXJyYXkpKSByZXR1cm4gJ2NhdGVnb3J5JztcbiAgICBpZihsaW5lYXJPSyhhcnJheSkpIHJldHVybiAnbGluZWFyJztcbiAgICBlbHNlIHJldHVybiAnLSc7XG59O1xuXG4vLyBpcyB0aGVyZSBhdCBsZWFzdCBvbmUgbnVtYmVyIGluIGFycmF5PyBJZiBub3QsIHdlIHNob3VsZCBsZWF2ZVxuLy8gYXgudHlwZSBlbXB0eSBzbyBpdCBjYW4gYmUgYXV0b3NldCBsYXRlclxuZnVuY3Rpb24gbGluZWFyT0soYXJyYXkpIHtcbiAgICBpZighYXJyYXkpIHJldHVybiBmYWxzZTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihpc051bWVyaWMoYXJyYXlbaV0pKSByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIGRvZXMgdGhlIGFycmF5IGEgaGF2ZSBtb3N0bHkgZGF0ZXMgcmF0aGVyIHRoYW4gbnVtYmVycz9cbi8vIG5vdGU6IHNvbWUgdmFsdWVzIGNhbiBiZSBuZWl0aGVyIChzdWNoIGFzIGJsYW5rcywgdGV4dClcbi8vIDItIG9yIDQtZGlnaXQgaW50ZWdlcnMgY2FuIGJlIGJvdGgsIHNvIHJlcXVpcmUgdHdpY2UgYXMgbWFueVxuLy8gZGF0ZXMgYXMgbm9uLWRhdGVzLCB0byBleGNsdWRlIGNhc2VzIHdpdGggbW9zdGx5IDIgJiA0IGRpZ2l0XG4vLyBudW1iZXJzIGFuZCBhIGZldyBkYXRlc1xuLy8gYXMgd2l0aCBjYXRlZ29yaWVzLCBjb25zaWRlciBESVNUSU5DVCB2YWx1ZXMgb25seS5cbmZ1bmN0aW9uIG1vcmVEYXRlcyhhLCBjYWxlbmRhcikge1xuICAgIC8vIHRlc3QgYXQgbW9zdCAxMDAwIHBvaW50cywgZXZlbmx5IHNwYWNlZFxuICAgIHZhciBpbmMgPSBNYXRoLm1heCgxLCAoYS5sZW5ndGggLSAxKSAvIDEwMDApO1xuICAgIHZhciBkY250ID0gMDtcbiAgICB2YXIgbmNudCA9IDA7XG4gICAgdmFyIHNlZW4gPSB7fTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSArPSBpbmMpIHtcbiAgICAgICAgdmFyIGFpID0gYVtNYXRoLnJvdW5kKGkpXTtcbiAgICAgICAgdmFyIHN0cmkgPSBTdHJpbmcoYWkpO1xuICAgICAgICBpZihzZWVuW3N0cmldKSBjb250aW51ZTtcbiAgICAgICAgc2VlbltzdHJpXSA9IDE7XG5cbiAgICAgICAgaWYoTGliLmlzRGF0ZVRpbWUoYWksIGNhbGVuZGFyKSkgZGNudCArPSAxO1xuICAgICAgICBpZihpc051bWVyaWMoYWkpKSBuY250ICs9IDE7XG4gICAgfVxuXG4gICAgcmV0dXJuIChkY250ID4gbmNudCAqIDIpO1xufVxuXG4vLyBhcmUgdGhlICh4LHkpLXZhbHVlcyBpbiBnZC5kYXRhIG1vc3RseSB0ZXh0P1xuLy8gcmVxdWlyZSB0d2ljZSBhcyBtYW55IERJU1RJTkNUIGNhdGVnb3JpZXMgYXMgZGlzdGluY3QgbnVtYmVyc1xuZnVuY3Rpb24gY2F0ZWdvcnkoYSkge1xuICAgIC8vIHRlc3QgYXQgbW9zdCAxMDAwIHBvaW50c1xuICAgIHZhciBpbmMgPSBNYXRoLm1heCgxLCAoYS5sZW5ndGggLSAxKSAvIDEwMDApO1xuICAgIHZhciBjdXJ2ZW51bXMgPSAwO1xuICAgIHZhciBjdXJ2ZWNhdHMgPSAwO1xuICAgIHZhciBzZWVuID0ge307XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkgKz0gaW5jKSB7XG4gICAgICAgIHZhciBhaSA9IGFbTWF0aC5yb3VuZChpKV07XG4gICAgICAgIHZhciBzdHJpID0gU3RyaW5nKGFpKTtcbiAgICAgICAgaWYoc2VlbltzdHJpXSkgY29udGludWU7XG4gICAgICAgIHNlZW5bc3RyaV0gPSAxO1xuXG4gICAgICAgIGlmKHR5cGVvZiBhaSA9PT0gJ2Jvb2xlYW4nKSBjdXJ2ZWNhdHMrKztcbiAgICAgICAgZWxzZSBpZihMaWIuY2xlYW5OdW1iZXIoYWkpICE9PSBCQUROVU0pIGN1cnZlbnVtcysrO1xuICAgICAgICBlbHNlIGlmKHR5cGVvZiBhaSA9PT0gJ3N0cmluZycpIGN1cnZlY2F0cysrO1xuICAgIH1cblxuICAgIHJldHVybiBjdXJ2ZWNhdHMgPiBjdXJ2ZW51bXMgKiAyO1xufVxuXG4vLyB2ZXJ5LWxvb3NlIHJlcXVpcmVtZW50cyBmb3IgbXVsdGljYXRlZ29yeSxcbi8vIHRyYWNlIG1vZHVsZXMgdGhhdCBzaG91bGQgbmV2ZXIgYXV0by10eXBlIHRvIG11bHRpY2F0ZWdvcnlcbi8vIHNob3VsZCBiZSBkZWNsYXJlZCB3aXRoICdub011bHRpQ2F0ZWdvcnknXG5mdW5jdGlvbiBtdWx0aUNhdGVnb3J5KGEpIHtcbiAgICByZXR1cm4gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkoYVswXSkgJiYgTGliLmlzQXJyYXlPclR5cGVkQXJyYXkoYVsxXSk7XG59XG5cbn0se1wiLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbFwiOjY5NSxcIi4uLy4uL2xpYlwiOjcxOSxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sNzY5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIGxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgaGFuZGxlVGlja1ZhbHVlRGVmYXVsdHMgPSBfZGVyZXFfKCcuL3RpY2tfdmFsdWVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrTWFya0RlZmF1bHRzID0gX2RlcmVxXygnLi90aWNrX21hcmtfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrTGFiZWxEZWZhdWx0cyA9IF9kZXJlcV8oJy4vdGlja19sYWJlbF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNhdGVnb3J5T3JkZXJEZWZhdWx0cyA9IF9kZXJlcV8oJy4vY2F0ZWdvcnlfb3JkZXJfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVMaW5lR3JpZERlZmF1bHRzID0gX2RlcmVxXygnLi9saW5lX2dyaWRfZGVmYXVsdHMnKTtcbnZhciBzZXRDb252ZXJ0ID0gX2RlcmVxXygnLi9zZXRfY29udmVydCcpO1xuXG4vKipcbiAqIG9wdGlvbnM6IG9iamVjdCBjb250YWluaW5nOlxuICpcbiAqICBsZXR0ZXI6ICd4JyBvciAneSdcbiAqICB0aXRsZTogbmFtZSBvZiB0aGUgYXhpcyAoaWUgJ0NvbG9yYmFyJykgdG8gZ28gaW4gZGVmYXVsdCB0aXRsZVxuICogIGZvbnQ6IHRoZSBkZWZhdWx0IGZvbnQgdG8gaW5oZXJpdFxuICogIG91dGVyVGlja3M6IGJvb2xlYW4sIHNob3VsZCB0aWNrcyBkZWZhdWx0IHRvIG91dHNpZGU/XG4gKiAgc2hvd0dyaWQ6IGJvb2xlYW4sIHNob3VsZCBncmlkbGluZXMgYmUgc2hvd24gYnkgZGVmYXVsdD9cbiAqICBub0hvdmVyOiBib29sZWFuLCB0aGlzIGF4aXMgZG9lc24ndCBzdXBwb3J0IGhvdmVyIGVmZmVjdHM/XG4gKiAgbm9UaWNrc29uOiBib29sZWFuLCB0aGlzIGF4aXMgZG9lc24ndCBzdXBwb3J0ICd0aWNrc29uJ1xuICogIGRhdGE6IHRoZSBwbG90IGRhdGEsIHVzZWQgdG8gbWFuYWdlIGNhdGVnb3JpZXNcbiAqICBiZ0NvbG9yOiB0aGUgcGxvdCBiYWNrZ3JvdW5kIGNvbG9yLCB0byBjYWxjdWxhdGUgZGVmYXVsdCBncmlkbGluZSBjb2xvcnNcbiAqICBjYWxlbmRhcjpcbiAqICBzcGxvbVN0YXNoOlxuICogIHZpc2libGVEZmx0OiBib29sZWFuXG4gKiAgcmV2ZXJzZURmbHQ6IGJvb2xlYW5cbiAqICBhdXRvbWFyZ2luOiBib29sZWFuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlQXhpc0RlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgb3B0aW9ucywgbGF5b3V0T3V0KSB7XG4gICAgdmFyIGxldHRlciA9IG9wdGlvbnMubGV0dGVyO1xuICAgIHZhciBmb250ID0gb3B0aW9ucy5mb250IHx8IHt9O1xuICAgIHZhciBzcGxvbVN0YXNoID0gb3B0aW9ucy5zcGxvbVN0YXNoIHx8IHt9O1xuXG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnLCAhb3B0aW9ucy52aXNpYmxlRGZsdCk7XG5cbiAgICB2YXIgYXhUeXBlID0gY29udGFpbmVyT3V0LnR5cGU7XG5cbiAgICBpZihheFR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICB2YXIgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2hhbmRsZURlZmF1bHRzJyk7XG4gICAgICAgIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgJ2NhbGVuZGFyJywgb3B0aW9ucy5jYWxlbmRhcik7XG4gICAgfVxuXG4gICAgc2V0Q29udmVydChjb250YWluZXJPdXQsIGxheW91dE91dCk7XG5cbiAgICB2YXIgYXV0b3JhbmdlRGZsdCA9ICFjb250YWluZXJPdXQuaXNWYWxpZFJhbmdlKGNvbnRhaW5lckluLnJhbmdlKTtcbiAgICBpZihhdXRvcmFuZ2VEZmx0ICYmIG9wdGlvbnMucmV2ZXJzZURmbHQpIGF1dG9yYW5nZURmbHQgPSAncmV2ZXJzZWQnO1xuICAgIHZhciBhdXRvUmFuZ2UgPSBjb2VyY2UoJ2F1dG9yYW5nZScsIGF1dG9yYW5nZURmbHQpO1xuICAgIGlmKGF1dG9SYW5nZSAmJiAoYXhUeXBlID09PSAnbGluZWFyJyB8fCBheFR5cGUgPT09ICctJykpIGNvZXJjZSgncmFuZ2Vtb2RlJyk7XG5cbiAgICBjb2VyY2UoJ3JhbmdlJyk7XG4gICAgY29udGFpbmVyT3V0LmNsZWFuUmFuZ2UoKTtcblxuICAgIGhhbmRsZUNhdGVnb3J5T3JkZXJEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIG9wdGlvbnMpO1xuXG4gICAgaWYoYXhUeXBlICE9PSAnY2F0ZWdvcnknICYmICFvcHRpb25zLm5vSG92ZXIpIGNvZXJjZSgnaG92ZXJmb3JtYXQnKTtcblxuICAgIHZhciBkZmx0Q29sb3IgPSBjb2VyY2UoJ2NvbG9yJyk7XG4gICAgLy8gaWYgYXhpcy5jb2xvciB3YXMgcHJvdmlkZWQsIHVzZSBpdCBmb3IgZm9udHMgdG9vOyBvdGhlcndpc2UsXG4gICAgLy8gaW5oZXJpdCBmcm9tIGdsb2JhbCBmb250IGNvbG9yIGluIGNhc2UgdGhhdCB3YXMgcHJvdmlkZWQuXG4gICAgLy8gQ29tcGFyZSB0byBkZmx0IHJhdGhlciB0aGFuIHRvIGNvbnRhaW5lckluLCBzbyB3ZSBjYW4gcHJvdmlkZSBjb2xvciB2aWFcbiAgICAvLyB0ZW1wbGF0ZSB0b28uXG4gICAgdmFyIGRmbHRGb250Q29sb3IgPSAoZGZsdENvbG9yICE9PSBsYXlvdXRBdHRyaWJ1dGVzLmNvbG9yLmRmbHQpID8gZGZsdENvbG9yIDogZm9udC5jb2xvcjtcbiAgICAvLyB0cnkgdG8gZ2V0IGRlZmF1bHQgdGl0bGUgZnJvbSBzcGxvbSB0cmFjZSwgZmFsbGJhY2sgdG8gZ3JhcGgtd2lkZSB2YWx1ZVxuICAgIHZhciBkZmx0VGl0bGUgPSBzcGxvbVN0YXNoLmxhYmVsIHx8IGxheW91dE91dC5fZGZsdFRpdGxlW2xldHRlcl07XG5cbiAgICBoYW5kbGVUaWNrTGFiZWxEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIGF4VHlwZSwgb3B0aW9ucywge3Bhc3M6IDF9KTtcbiAgICBpZighdmlzaWJsZSkgcmV0dXJuIGNvbnRhaW5lck91dDtcblxuICAgIGNvZXJjZSgndGl0bGUudGV4dCcsIGRmbHRUaXRsZSk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAndGl0bGUuZm9udCcsIHtcbiAgICAgICAgZmFtaWx5OiBmb250LmZhbWlseSxcbiAgICAgICAgc2l6ZTogTWF0aC5yb3VuZChmb250LnNpemUgKiAxLjIpLFxuICAgICAgICBjb2xvcjogZGZsdEZvbnRDb2xvclxuICAgIH0pO1xuXG4gICAgaGFuZGxlVGlja1ZhbHVlRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBheFR5cGUpO1xuICAgIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgYXhUeXBlLCBvcHRpb25zLCB7cGFzczogMn0pO1xuICAgIGhhbmRsZVRpY2tNYXJrRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBvcHRpb25zKTtcbiAgICBoYW5kbGVMaW5lR3JpZERlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwge1xuICAgICAgICBkZmx0Q29sb3I6IGRmbHRDb2xvcixcbiAgICAgICAgYmdDb2xvcjogb3B0aW9ucy5iZ0NvbG9yLFxuICAgICAgICBzaG93R3JpZDogb3B0aW9ucy5zaG93R3JpZCxcbiAgICAgICAgYXR0cmlidXRlczogbGF5b3V0QXR0cmlidXRlc1xuICAgIH0pO1xuXG4gICAgaWYoY29udGFpbmVyT3V0LnNob3dsaW5lIHx8IGNvbnRhaW5lck91dC50aWNrcykgY29lcmNlKCdtaXJyb3InKTtcblxuICAgIGlmKG9wdGlvbnMuYXV0b21hcmdpbikgY29lcmNlKCdhdXRvbWFyZ2luJyk7XG5cbiAgICB2YXIgaXNNdWx0aUNhdGVnb3J5ID0gY29udGFpbmVyT3V0LnR5cGUgPT09ICdtdWx0aWNhdGVnb3J5JztcblxuICAgIGlmKCFvcHRpb25zLm5vVGlja3NvbiAmJlxuICAgICAgICAoY29udGFpbmVyT3V0LnR5cGUgPT09ICdjYXRlZ29yeScgfHwgaXNNdWx0aUNhdGVnb3J5KSAmJlxuICAgICAgICAoY29udGFpbmVyT3V0LnRpY2tzIHx8IGNvbnRhaW5lck91dC5zaG93Z3JpZClcbiAgICApIHtcbiAgICAgICAgdmFyIHRpY2tzb25EZmx0O1xuICAgICAgICBpZihpc011bHRpQ2F0ZWdvcnkpIHRpY2tzb25EZmx0ID0gJ2JvdW5kYXJpZXMnO1xuICAgICAgICBjb2VyY2UoJ3RpY2tzb24nLCB0aWNrc29uRGZsdCk7XG4gICAgfVxuXG4gICAgaWYoaXNNdWx0aUNhdGVnb3J5KSB7XG4gICAgICAgIHZhciBzaG93RGl2aWRlcnMgPSBjb2VyY2UoJ3Nob3dkaXZpZGVycycpO1xuICAgICAgICBpZihzaG93RGl2aWRlcnMpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnZGl2aWRlcmNvbG9yJyk7XG4gICAgICAgICAgICBjb2VyY2UoJ2RpdmlkZXJ3aWR0aCcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRhaW5lck91dDtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2NhdGVnb3J5X29yZGVyX2RlZmF1bHRzXCI6NzcxLFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjc3OSxcIi4vbGluZV9ncmlkX2RlZmF1bHRzXCI6NzgxLFwiLi9zZXRfY29udmVydFwiOjc4NSxcIi4vdGlja19sYWJlbF9kZWZhdWx0c1wiOjc4NixcIi4vdGlja19tYXJrX2RlZmF1bHRzXCI6Nzg3LFwiLi90aWNrX3ZhbHVlX2RlZmF1bHRzXCI6Nzg4fV0sNzcwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG5cblxuLy8gY29udmVydCBiZXR3ZWVuIGF4aXMgbmFtZXMgKHhheGlzLCB4YXhpczIsIGV0YywgZWxlbWVudHMgb2YgZ2QubGF5b3V0KVxuLy8gYW5kIGF4aXMgaWQncyAoeCwgeDIsIGV0YykuIFdvdWxkIHByb2JhYmx5IGhhdmUgZGl0Y2hlZCAneGF4aXMnXG4vLyBjb21wbGV0ZWx5IGluIGZhdm9yIG9mIGp1c3QgJ3gnIGlmIGl0IHdlcmVuJ3QgaW5ncmFpbmVkIGluIHRoZSBBUEkgZXRjLlxuZXhwb3J0cy5pZDJuYW1lID0gZnVuY3Rpb24gaWQybmFtZShpZCkge1xuICAgIGlmKHR5cGVvZiBpZCAhPT0gJ3N0cmluZycgfHwgIWlkLm1hdGNoKGNvbnN0YW50cy5BWF9JRF9QQVRURVJOKSkgcmV0dXJuO1xuICAgIHZhciBheE51bSA9IGlkLnN1YnN0cigxKTtcbiAgICBpZihheE51bSA9PT0gJzEnKSBheE51bSA9ICcnO1xuICAgIHJldHVybiBpZC5jaGFyQXQoMCkgKyAnYXhpcycgKyBheE51bTtcbn07XG5cbmV4cG9ydHMubmFtZTJpZCA9IGZ1bmN0aW9uIG5hbWUyaWQobmFtZSkge1xuICAgIGlmKCFuYW1lLm1hdGNoKGNvbnN0YW50cy5BWF9OQU1FX1BBVFRFUk4pKSByZXR1cm47XG4gICAgdmFyIGF4TnVtID0gbmFtZS5zdWJzdHIoNSk7XG4gICAgaWYoYXhOdW0gPT09ICcxJykgYXhOdW0gPSAnJztcbiAgICByZXR1cm4gbmFtZS5jaGFyQXQoMCkgKyBheE51bTtcbn07XG5cbmV4cG9ydHMuY2xlYW5JZCA9IGZ1bmN0aW9uIGNsZWFuSWQoaWQsIGF4TGV0dGVyKSB7XG4gICAgaWYoIWlkLm1hdGNoKGNvbnN0YW50cy5BWF9JRF9QQVRURVJOKSkgcmV0dXJuO1xuICAgIGlmKGF4TGV0dGVyICYmIGlkLmNoYXJBdCgwKSAhPT0gYXhMZXR0ZXIpIHJldHVybjtcblxuICAgIHZhciBheE51bSA9IGlkLnN1YnN0cigxKS5yZXBsYWNlKC9eMCsvLCAnJyk7XG4gICAgaWYoYXhOdW0gPT09ICcxJykgYXhOdW0gPSAnJztcbiAgICByZXR1cm4gaWQuY2hhckF0KDApICsgYXhOdW07XG59O1xuXG4vLyBnZXQgYWxsIGF4aXMgb2JqZWN0cywgYXMgcmVzdHJpY3RlZCBpbiBsaXN0TmFtZXNcbmV4cG9ydHMubGlzdCA9IGZ1bmN0aW9uKGdkLCBheExldHRlciwgb25seTJkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICBpZighZnVsbExheW91dCkgcmV0dXJuIFtdO1xuXG4gICAgdmFyIGlkTGlzdCA9IGV4cG9ydHMubGlzdElkcyhnZCwgYXhMZXR0ZXIpO1xuICAgIHZhciBvdXQgPSBuZXcgQXJyYXkoaWRMaXN0Lmxlbmd0aCk7XG4gICAgdmFyIGk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBpZExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkaSA9IGlkTGlzdFtpXTtcbiAgICAgICAgb3V0W2ldID0gZnVsbExheW91dFtpZGkuY2hhckF0KDApICsgJ2F4aXMnICsgaWRpLnN1YnN0cigxKV07XG4gICAgfVxuXG4gICAgaWYoIW9ubHkyZCkge1xuICAgICAgICB2YXIgc2NlbmVJZHMzRCA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzLmdsM2QgfHwgW107XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2NlbmVJZHMzRC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHNjZW5lID0gZnVsbExheW91dFtzY2VuZUlkczNEW2ldXTtcblxuICAgICAgICAgICAgaWYoYXhMZXR0ZXIpIG91dC5wdXNoKHNjZW5lW2F4TGV0dGVyICsgJ2F4aXMnXSk7XG4gICAgICAgICAgICBlbHNlIG91dC5wdXNoKHNjZW5lLnhheGlzLCBzY2VuZS55YXhpcywgc2NlbmUuemF4aXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbi8vIGdldCBhbGwgYXhpcyBpZHMsIG9wdGlvbmFsbHkgcmVzdHJpY3RlZCBieSBsZXR0ZXJcbi8vIHRoaXMgb25seSBtYWtlcyBzZW5zZSBmb3IgMmQgYXhlc1xuZXhwb3J0cy5saXN0SWRzID0gZnVuY3Rpb24oZ2QsIGF4TGV0dGVyKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICBpZighZnVsbExheW91dCkgcmV0dXJuIFtdO1xuXG4gICAgdmFyIHN1YnBsb3RMaXN0cyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzO1xuICAgIGlmKGF4TGV0dGVyKSByZXR1cm4gc3VicGxvdExpc3RzW2F4TGV0dGVyICsgJ2F4aXMnXTtcbiAgICByZXR1cm4gc3VicGxvdExpc3RzLnhheGlzLmNvbmNhdChzdWJwbG90TGlzdHMueWF4aXMpO1xufTtcblxuLy8gZ2V0IGFuIGF4aXMgb2JqZWN0IGZyb20gaXRzIGlkICd4JywneDInIGV0Y1xuLy8gb3B0aW9uYWxseSwgaWQgY2FuIGJlIGEgc3VicGxvdCAoaWUgJ3gyeTMnKSBhbmQgdHlwZSBnZXRzIHggb3IgeSBmcm9tIGl0XG5leHBvcnRzLmdldEZyb21JZCA9IGZ1bmN0aW9uKGdkLCBpZCwgdHlwZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBpZih0eXBlID09PSAneCcpIGlkID0gaWQucmVwbGFjZSgveVswLTldKi8sICcnKTtcbiAgICBlbHNlIGlmKHR5cGUgPT09ICd5JykgaWQgPSBpZC5yZXBsYWNlKC94WzAtOV0qLywgJycpO1xuXG4gICAgcmV0dXJuIGZ1bGxMYXlvdXRbZXhwb3J0cy5pZDJuYW1lKGlkKV07XG59O1xuXG4vLyBnZXQgYW4gYXhpcyBvYmplY3Qgb2Ygc3BlY2lmaWVkIHR5cGUgZnJvbSB0aGUgY29udGFpbmluZyB0cmFjZVxuZXhwb3J0cy5nZXRGcm9tVHJhY2UgPSBmdW5jdGlvbihnZCwgZnVsbFRyYWNlLCB0eXBlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgYXggPSBudWxsO1xuXG4gICAgaWYoUmVnaXN0cnkudHJhY2VJcyhmdWxsVHJhY2UsICdnbDNkJykpIHtcbiAgICAgICAgdmFyIHNjZW5lID0gZnVsbFRyYWNlLnNjZW5lO1xuICAgICAgICBpZihzY2VuZS5zdWJzdHIoMCwgNSkgPT09ICdzY2VuZScpIHtcbiAgICAgICAgICAgIGF4ID0gZnVsbExheW91dFtzY2VuZV1bdHlwZSArICdheGlzJ107XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBheCA9IGV4cG9ydHMuZ2V0RnJvbUlkKGdkLCBmdWxsVHJhY2VbdHlwZSArICdheGlzJ10gfHwgdHlwZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGF4O1xufTtcblxuLy8gc29ydCB4LCB4MiwgeDEwLCB5LCB5MiwgeTEwLi4uXG5leHBvcnRzLmlkU29ydCA9IGZ1bmN0aW9uKGlkMSwgaWQyKSB7XG4gICAgdmFyIGxldHRlcjEgPSBpZDEuY2hhckF0KDApO1xuICAgIHZhciBsZXR0ZXIyID0gaWQyLmNoYXJBdCgwKTtcbiAgICBpZihsZXR0ZXIxICE9PSBsZXR0ZXIyKSByZXR1cm4gbGV0dGVyMSA+IGxldHRlcjIgPyAxIDogLTE7XG4gICAgcmV0dXJuICsoaWQxLnN1YnN0cigxKSB8fCAxKSAtICsoaWQyLnN1YnN0cigxKSB8fCAxKTtcbn07XG5cbmV4cG9ydHMuZ2V0QXhpc0dyb3VwID0gZnVuY3Rpb24gZ2V0QXhpc0dyb3VwKGZ1bGxMYXlvdXQsIGF4SWQpIHtcbiAgICB2YXIgbWF0Y2hHcm91cHMgPSBmdWxsTGF5b3V0Ll9heGlzTWF0Y2hHcm91cHM7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbWF0Y2hHcm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGdyb3VwID0gbWF0Y2hHcm91cHNbaV07XG4gICAgICAgIGlmKGdyb3VwW2F4SWRdKSByZXR1cm4gJ2cnICsgaTtcbiAgICB9XG4gICAgcmV0dXJuIGF4SWQ7XG59O1xuXG59LHtcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9jb25zdGFudHNcIjo3NzN9XSw3NzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBmaW5kQ2F0ZWdvcmllcyhheCwgb3B0cykge1xuICAgIHZhciBkYXRhQXR0ciA9IG9wdHMuZGF0YUF0dHIgfHwgYXguX2lkLmNoYXJBdCgwKTtcbiAgICB2YXIgbG9va3VwID0ge307XG4gICAgdmFyIGF4RGF0YTtcbiAgICB2YXIgaSwgajtcblxuICAgIGlmKG9wdHMuYXhEYXRhKSB7XG4gICAgICAgIC8vIG5vbi14L3kgY2FzZVxuICAgICAgICBheERhdGEgPSBvcHRzLmF4RGF0YTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB4L3kgY2FzZVxuICAgICAgICBheERhdGEgPSBbXTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgb3B0cy5kYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSBvcHRzLmRhdGFbaV07XG4gICAgICAgICAgICBpZih0cmFjZVtkYXRhQXR0ciArICdheGlzJ10gPT09IGF4Ll9pZCkge1xuICAgICAgICAgICAgICAgIGF4RGF0YS5wdXNoKHRyYWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGF4RGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdmFscyA9IGF4RGF0YVtpXVtkYXRhQXR0cl07XG4gICAgICAgIGZvcihqID0gMDsgaiA8IHZhbHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciB2ID0gdmFsc1tqXTtcbiAgICAgICAgICAgIGlmKHYgIT09IG51bGwgJiYgdiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbG9va3VwW3ZdID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhsb29rdXApO1xufVxuXG4vKipcbiAqIEZpbGxzIGluIGNhdGVnb3J5KiBkZWZhdWx0IGFuZCBpbml0aWFsIGNhdGVnb3JpZXMuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGNvbnRhaW5lckluIDogaW5wdXQgYXhpcyBvYmplY3RcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb250YWluZXJPdXQgOiBmdWxsIGF4aXMgb2JqZWN0XG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjb2VyY2UgOiBMaWIuY29lcmNlIGZuIHdyYXBwZXJcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzIDpcbiAqICAgLSBkYXRhIHthcnJheX0gOiAoZnVsbCkgZGF0YSB0cmFjZVxuICogT1JcbiAqICAgLSBheERhdGEge2FycmF5fSA6IChmdWxsKSBkYXRhIGFzc29jaWF0ZWQgd2l0aCBheGlzIGJlaW5nIGNvZXJjZWQgaGVyZVxuICogICAtIGRhdGFBdHRyIHtzdHJpbmd9IDogYXR0cmlidXRlIG5hbWUgY29ycmVzcG9uZGluZyB0byBjb29yZGluYXRlIGFycmF5XG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlQ2F0ZWdvcnlPcmRlckRlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgb3B0cykge1xuICAgIGlmKGNvbnRhaW5lck91dC50eXBlICE9PSAnY2F0ZWdvcnknKSByZXR1cm47XG5cbiAgICB2YXIgYXJyYXlJbiA9IGNvbnRhaW5lckluLmNhdGVnb3J5YXJyYXk7XG4gICAgdmFyIGlzVmFsaWRBcnJheSA9IChBcnJheS5pc0FycmF5KGFycmF5SW4pICYmIGFycmF5SW4ubGVuZ3RoID4gMCk7XG5cbiAgICAvLyBvdmVycmlkZSBkZWZhdWx0ICdjYXRlZ29yeW9yZGVyJyB2YWx1ZSB3aGVuIG5vbi1lbXB0eSBhcnJheSBpcyBzdXBwbGllZFxuICAgIHZhciBvcmRlckRlZmF1bHQ7XG4gICAgaWYoaXNWYWxpZEFycmF5KSBvcmRlckRlZmF1bHQgPSAnYXJyYXknO1xuXG4gICAgdmFyIG9yZGVyID0gY29lcmNlKCdjYXRlZ29yeW9yZGVyJywgb3JkZXJEZWZhdWx0KTtcbiAgICB2YXIgYXJyYXk7XG5cbiAgICAvLyBjb2VyY2UgJ2NhdGVnb3J5YXJyYXknIG9ubHkgaW4gYXJyYXkgb3JkZXIgY2FzZVxuICAgIGlmKG9yZGVyID09PSAnYXJyYXknKSB7XG4gICAgICAgIGFycmF5ID0gY29lcmNlKCdjYXRlZ29yeWFycmF5Jyk7XG4gICAgfVxuXG4gICAgLy8gY2Fubm90IHNldCAnY2F0ZWdvcnlvcmRlcicgdG8gJ2FycmF5JyB3aXRoIGFuIGludmFsaWQgJ2NhdGVnb3J5YXJyYXknXG4gICAgaWYoIWlzVmFsaWRBcnJheSAmJiBvcmRlciA9PT0gJ2FycmF5Jykge1xuICAgICAgICBvcmRlciA9IGNvbnRhaW5lck91dC5jYXRlZ29yeW9yZGVyID0gJ3RyYWNlJztcbiAgICB9XG5cbiAgICAvLyBzZXQgdXAgdGhpbmdzIGZvciBtYWtlQ2FsY2RhdGFcbiAgICBpZihvcmRlciA9PT0gJ3RyYWNlJykge1xuICAgICAgICBjb250YWluZXJPdXQuX2luaXRpYWxDYXRlZ29yaWVzID0gW107XG4gICAgfSBlbHNlIGlmKG9yZGVyID09PSAnYXJyYXknKSB7XG4gICAgICAgIGNvbnRhaW5lck91dC5faW5pdGlhbENhdGVnb3JpZXMgPSBhcnJheS5zbGljZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGFycmF5ID0gZmluZENhdGVnb3JpZXMoY29udGFpbmVyT3V0LCBvcHRzKS5zb3J0KCk7XG4gICAgICAgIGlmKG9yZGVyID09PSAnY2F0ZWdvcnkgYXNjZW5kaW5nJykge1xuICAgICAgICAgICAgY29udGFpbmVyT3V0Ll9pbml0aWFsQ2F0ZWdvcmllcyA9IGFycmF5O1xuICAgICAgICB9IGVsc2UgaWYob3JkZXIgPT09ICdjYXRlZ29yeSBkZXNjZW5kaW5nJykge1xuICAgICAgICAgICAgY29udGFpbmVyT3V0Ll9pbml0aWFsQ2F0ZWdvcmllcyA9IGFycmF5LnJldmVyc2UoKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se31dLDc3MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIE9ORURBWSA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5PTkVEQVk7XG5cbi8qKlxuICogUmV0dXJuIGEgdmFsaWRhdGVkIGR0aWNrIHZhbHVlIGZvciB0aGlzIGF4aXNcbiAqXG4gKiBAcGFyYW0ge2FueX0gZHRpY2s6IHRoZSBjYW5kaWRhdGUgZHRpY2suIHZhbGlkIHZhbHVlcyBhcmUgbnVtYmVycyBhbmQgc3RyaW5ncyxcbiAqICAgICBhbmQgZnVydGhlciBjb25zdHJhaW5lZCBkZXBlbmRpbmcgb24gdGhlIGF4aXMgdHlwZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBheFR5cGU6IHRoZSBheGlzIHR5cGVcbiAqL1xuZXhwb3J0cy5kdGljayA9IGZ1bmN0aW9uKGR0aWNrLCBheFR5cGUpIHtcbiAgICB2YXIgaXNMb2cgPSBheFR5cGUgPT09ICdsb2cnO1xuICAgIHZhciBpc0RhdGUgPSBheFR5cGUgPT09ICdkYXRlJztcbiAgICB2YXIgaXNDYXQgPSBheFR5cGUgPT09ICdjYXRlZ29yeSc7XG4gICAgdmFyIGR0aWNrRGZsdCA9IGlzRGF0ZSA/IE9ORURBWSA6IDE7XG5cbiAgICBpZighZHRpY2spIHJldHVybiBkdGlja0RmbHQ7XG5cbiAgICBpZihpc051bWVyaWMoZHRpY2spKSB7XG4gICAgICAgIGR0aWNrID0gTnVtYmVyKGR0aWNrKTtcbiAgICAgICAgaWYoZHRpY2sgPD0gMCkgcmV0dXJuIGR0aWNrRGZsdDtcbiAgICAgICAgaWYoaXNDYXQpIHtcbiAgICAgICAgICAgIC8vIGNhdGVnb3J5IGR0aWNrIG11c3QgYmUgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICAgICAgICAgIHJldHVybiBNYXRoLm1heCgxLCBNYXRoLnJvdW5kKGR0aWNrKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaXNEYXRlKSB7XG4gICAgICAgICAgICAvLyBkYXRlIGR0aWNrIG11c3QgYmUgYXQgbGVhc3QgMC4xbXMgKG91ciBjdXJyZW50IHByZWNpc2lvbilcbiAgICAgICAgICAgIHJldHVybiBNYXRoLm1heCgwLjEsIGR0aWNrKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZHRpY2s7XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIGR0aWNrICE9PSAnc3RyaW5nJyB8fCAhKGlzRGF0ZSB8fCBpc0xvZykpIHtcbiAgICAgICAgcmV0dXJuIGR0aWNrRGZsdDtcbiAgICB9XG5cbiAgICB2YXIgcHJlZml4ID0gZHRpY2suY2hhckF0KDApO1xuICAgIHZhciBkdGlja051bSA9IGR0aWNrLnN1YnN0cigxKTtcbiAgICBkdGlja051bSA9IGlzTnVtZXJpYyhkdGlja051bSkgPyBOdW1iZXIoZHRpY2tOdW0pIDogMDtcblxuICAgIGlmKChkdGlja051bSA8PSAwKSB8fCAhKFxuICAgICAgICAgICAgLy8gXCJNPG4+XCIgZ2l2ZXMgdGlja3MgZXZlcnkgKGludGVnZXIpIG4gbW9udGhzXG4gICAgICAgICAgICAoaXNEYXRlICYmIHByZWZpeCA9PT0gJ00nICYmIGR0aWNrTnVtID09PSBNYXRoLnJvdW5kKGR0aWNrTnVtKSkgfHxcbiAgICAgICAgICAgIC8vIFwiTDxmPlwiIGdpdmVzIHRpY2tzIGxpbmVhcmx5IHNwYWNlZCBpbiBkYXRhIChub3QgaW4gcG9zaXRpb24pIGV2ZXJ5IChmbG9hdCkgZlxuICAgICAgICAgICAgKGlzTG9nICYmIHByZWZpeCA9PT0gJ0wnKSB8fFxuICAgICAgICAgICAgLy8gXCJEMVwiIGdpdmVzIHBvd2VycyBvZiAxMCB3aXRoIGFsbCBzbWFsbCBkaWdpdHMgYmV0d2VlbiwgXCJEMlwiIGdpdmVzIG9ubHkgMiBhbmQgNVxuICAgICAgICAgICAgKGlzTG9nICYmIHByZWZpeCA9PT0gJ0QnICYmIChkdGlja051bSA9PT0gMSB8fCBkdGlja051bSA9PT0gMikpXG4gICAgICAgICkpIHtcbiAgICAgICAgcmV0dXJuIGR0aWNrRGZsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gZHRpY2s7XG59O1xuXG4vKipcbiAqIFJldHVybiBhIHZhbGlkYXRlZCB0aWNrMCBmb3IgdGhpcyBheGlzXG4gKlxuICogQHBhcmFtIHthbnl9IHRpY2swOiB0aGUgY2FuZGlkYXRlIHRpY2swLiBWYWxpZCB2YWx1ZXMgYXJlIG51bWJlcnMgYW5kIHN0cmluZ3MsXG4gKiAgICAgZnVydGhlciBjb25zdHJhaW5lZCBkZXBlbmRpbmcgb24gdGhlIGF4aXMgdHlwZVxuICogQHBhcmFtIHtzdHJpbmd9IGF4VHlwZTogdGhlIGF4aXMgdHlwZVxuICogQHBhcmFtIHtzdHJpbmd9IGNhbGVuZGFyOiBmb3IgZGF0ZSBheGVzLCB0aGUgY2FsZW5kYXIgdG8gdmFsaWRhdGUvY29udmVydCB3aXRoXG4gKiBAcGFyYW0ge2FueX0gZHRpY2s6IGFuIGFscmVhZHkgdmFsaWQgZHRpY2suIE9ubHkgdXNlZCBmb3IgRDEgYW5kIEQyIGxvZyBkdGlja3MsXG4gKiAgICAgd2hpY2ggZG8gbm90IHN1cHBvcnQgdGljazAgYXQgYWxsLlxuICovXG5leHBvcnRzLnRpY2swID0gZnVuY3Rpb24odGljazAsIGF4VHlwZSwgY2FsZW5kYXIsIGR0aWNrKSB7XG4gICAgaWYoYXhUeXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jbGVhbkRhdGUodGljazAsIExpYi5kYXRlVGljazAoY2FsZW5kYXIpKTtcbiAgICB9XG4gICAgaWYoZHRpY2sgPT09ICdEMScgfHwgZHRpY2sgPT09ICdEMicpIHtcbiAgICAgICAgLy8gRDEgYW5kIEQyIG1vZGVzIGlnbm9yZSB0aWNrMCBlbnRpcmVseVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICAvLyBBc2lkZSBmcm9tIGRhdGUgYXhlcywgdGljazAgbXVzdCBiZSBudW1lcmljXG4gICAgcmV0dXJuIGlzTnVtZXJpYyh0aWNrMCkgPyBOdW1iZXIodGljazApIDogMDtcbn07XG5cbn0se1wiLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbFwiOjY5NSxcIi4uLy4uL2xpYlwiOjcxOSxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sNzczOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcbnZhciBjb3VudGVyUmVnZXggPSBfZGVyZXFfKCcuLi8uLi9saWIvcmVnZXgnKS5jb3VudGVyO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXG4gICAgaWRSZWdleDoge1xuICAgICAgICB4OiBjb3VudGVyUmVnZXgoJ3gnKSxcbiAgICAgICAgeTogY291bnRlclJlZ2V4KCd5JylcbiAgICB9LFxuXG4gICAgYXR0clJlZ2V4OiBjb3VudGVyUmVnZXgoJ1t4eV1heGlzJyksXG5cbiAgICAvLyBheGlzIG1hdGNoIHJlZ3VsYXIgZXhwcmVzc2lvblxuICAgIHhBeGlzTWF0Y2g6IGNvdW50ZXJSZWdleCgneGF4aXMnKSxcbiAgICB5QXhpc01hdGNoOiBjb3VudGVyUmVnZXgoJ3lheGlzJyksXG5cbiAgICAvLyBwYXR0ZXJuIG1hdGNoaW5nIGF4aXMgaWRzIGFuZCBuYW1lc1xuICAgIC8vIG5vdGUgdGhhdCB0aGlzIGlzIG1vcmUgcGVybWlzc2l2ZSB0aGFuIGNvdW50ZXJSZWdleCwgYXNcbiAgICAvLyBpZDJuYW1lLCBuYW1lMmlkLCBhbmQgY2xlYW5JZCBhY2NlcHQgXCJ4MVwiIGV0Y1xuICAgIEFYX0lEX1BBVFRFUk46IC9eW3h5el1bMC05XSokLyxcbiAgICBBWF9OQU1FX1BBVFRFUk46IC9eW3h5el1heGlzWzAtOV0qJC8sXG5cbiAgICAvLyBhbmQgZm9yIDJEIHN1YnBsb3RzXG4gICAgU1VCUExPVF9QQVRURVJOOiAvXngoWzAtOV0qKXkoWzAtOV0qKSQvLFxuXG4gICAgLy8gcGl4ZWxzIHRvIG1vdmUgbW91c2UgYmVmb3JlIHlvdSBzdG9wIGNsYW1waW5nIHRvIHN0YXJ0aW5nIHBvaW50XG4gICAgTUlORFJBRzogOCxcblxuICAgIC8vIHNtYWxsZXN0IGRpbWVuc2lvbiBhbGxvd2VkIGZvciBhIHNlbGVjdCBib3hcbiAgICBNSU5TRUxFQ1Q6IDEyLFxuXG4gICAgLy8gc21hbGxlc3QgZGltZW5zaW9uIGFsbG93ZWQgZm9yIGEgem9vbWJveFxuICAgIE1JTlpPT006IDIwLFxuXG4gICAgLy8gd2lkdGggb2YgYXhpcyBkcmFnIHJlZ2lvbnNcbiAgICBEUkFHR0VSU0laRTogMjAsXG5cbiAgICAvLyBtYXggcGl4ZWxzIG9mZiBzdHJhaWdodCBiZWZvcmUgYSBsYXNzbyBzZWxlY3QgbGluZSBjb3VudHMgYXMgYmVudFxuICAgIEJFTkRQWDogMS41LFxuXG4gICAgLy8gZGVsYXkgYmVmb3JlIGEgcmVkcmF3IChyZWxheW91dCkgYWZ0ZXIgc21vb3RoIHBhbm5pbmcgYW5kIHpvb21pbmdcbiAgICBSRURSQVdERUxBWTogNTAsXG5cbiAgICAvLyB0aHJvdHRsaW5nIGxpbWl0IChtcykgZm9yIHNlbGVjdFBvaW50cyBjYWxsc1xuICAgIFNFTEVDVERFTEFZOiAxMDAsXG5cbiAgICAvLyBjYWNoZSBJRCBzdWZmaXggZm9yIHRocm90dGxlXG4gICAgU0VMRUNUSUQ6ICctc2VsZWN0JyxcblxuICAgIC8vIGxhc3QgcmVzb3J0IGF4aXMgcmFuZ2VzIGZvciB4IGFuZCB5IGF4ZXMgaWYgd2UgaGF2ZSBubyBkYXRhXG4gICAgREZMVFJBTkdFWDogWy0xLCA2XSxcbiAgICBERkxUUkFOR0VZOiBbLTEsIDRdLFxuXG4gICAgLy8gTGF5ZXJzIHRvIGtlZXAgdHJhY2UgdHlwZXMgaW4gdGhlIHJpZ2h0IG9yZGVyXG4gICAgLy8gTi5CLiBlYWNoICAndW5pcXVlJyBwbG90IG1ldGhvZCBtdXN0IGhhdmUgaXRzIG93biBsYXllclxuICAgIHRyYWNlTGF5ZXJDbGFzc2VzOiBbXG4gICAgICAgICdoZWF0bWFwbGF5ZXInLFxuICAgICAgICAnY29udG91cmNhcnBldGxheWVyJywgJ2NvbnRvdXJsYXllcicsXG4gICAgICAgICdmdW5uZWxsYXllcicsICd3YXRlcmZhbGxsYXllcicsICdiYXJsYXllcicsXG4gICAgICAgICdjYXJwZXRsYXllcicsXG4gICAgICAgICd2aW9saW5sYXllcicsXG4gICAgICAgICdib3hsYXllcicsXG4gICAgICAgICdvaGxjbGF5ZXInLFxuICAgICAgICAnc2NhdHRlcmNhcnBldGxheWVyJywgJ3NjYXR0ZXJsYXllcidcbiAgICBdLFxuXG4gICAgY2xpcE9uQXhpc0ZhbHNlUXVlcnk6IFtcbiAgICAgICAgJy5zY2F0dGVybGF5ZXInLFxuICAgICAgICAnLmJhcmxheWVyJyxcbiAgICAgICAgJy5mdW5uZWxsYXllcicsXG4gICAgICAgICcud2F0ZXJmYWxsbGF5ZXInXG4gICAgXSxcblxuICAgIGxheWVyVmFsdWUybGF5ZXJDbGFzczoge1xuICAgICAgICAnYWJvdmUgdHJhY2VzJzogJ2Fib3ZlJyxcbiAgICAgICAgJ2JlbG93IHRyYWNlcyc6ICdiZWxvdydcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYi9yZWdleFwiOjczNX1dLDc3NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBpZDJuYW1lID0gX2RlcmVxXygnLi9heGlzX2lkcycpLmlkMm5hbWU7XG52YXIgc2NhbGVab29tID0gX2RlcmVxXygnLi9zY2FsZV96b29tJyk7XG52YXIgbWFrZVBhZEZuID0gX2RlcmVxXygnLi9hdXRvcmFuZ2UnKS5tYWtlUGFkRm47XG52YXIgY29uY2F0RXh0cmVtZXMgPSBfZGVyZXFfKCcuL2F1dG9yYW5nZScpLmNvbmNhdEV4dHJlbWVzO1xuXG52YXIgQUxNT1NUX0VRVUFMID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkFMTU9TVF9FUVVBTDtcbnZhciBGUk9NX0JMID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudCcpLkZST01fQkw7XG5cbmV4cG9ydHMuaGFuZGxlQ29uc3RyYWludERlZmF1bHRzID0gZnVuY3Rpb24oY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBhbGxBeGlzSWRzLCBsYXlvdXRPdXQpIHtcbiAgICB2YXIgY29uc3RyYWludEdyb3VwcyA9IGxheW91dE91dC5fYXhpc0NvbnN0cmFpbnRHcm91cHM7XG4gICAgdmFyIG1hdGNoR3JvdXBzID0gbGF5b3V0T3V0Ll9heGlzTWF0Y2hHcm91cHM7XG4gICAgdmFyIGF4SWQgPSBjb250YWluZXJPdXQuX2lkO1xuICAgIHZhciBheExldHRlciA9IGF4SWQuY2hhckF0KDApO1xuICAgIHZhciBzcGxvbVN0YXNoID0gKChsYXlvdXRPdXQuX3NwbG9tQXhlcyB8fCB7fSlbYXhMZXR0ZXJdIHx8IHt9KVtheElkXSB8fCB7fTtcbiAgICB2YXIgdGhpc0lEID0gY29udGFpbmVyT3V0Ll9pZDtcbiAgICB2YXIgbGV0dGVyID0gdGhpc0lELmNoYXJBdCgwKTtcblxuICAgIC8vIGNvZXJjZSB0aGUgY29uc3RyYWludCBtZWNoYW5pY3MgZXZlbiBpZiB0aGlzIGF4aXMgaGFzIG5vIHNjYWxlYW5jaG9yXG4gICAgLy8gYmVjYXVzZSBpdCBtYXkgYmUgdGhlIGFuY2hvciBvZiBhbm90aGVyIGF4aXMuXG4gICAgdmFyIGNvbnN0cmFpbiA9IGNvZXJjZSgnY29uc3RyYWluJyk7XG4gICAgTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCB7XG4gICAgICAgIGNvbnN0cmFpbnRvd2FyZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBsZXR0ZXIgPT09ICd4JyA/IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSA6IFsnYm90dG9tJywgJ21pZGRsZScsICd0b3AnXSxcbiAgICAgICAgICAgIGRmbHQ6IGxldHRlciA9PT0gJ3gnID8gJ2NlbnRlcicgOiAnbWlkZGxlJ1xuICAgICAgICB9XG4gICAgfSwgJ2NvbnN0cmFpbnRvd2FyZCcpO1xuXG4gICAgdmFyIG1hdGNoZXMsIG1hdGNoT3B0cztcblxuICAgIGlmKChjb250YWluZXJJbi5tYXRjaGVzIHx8IHNwbG9tU3Rhc2gubWF0Y2hlcykgJiYgIWNvbnRhaW5lck91dC5maXhlZHJhbmdlKSB7XG4gICAgICAgIG1hdGNoT3B0cyA9IGdldENvbnN0cmFpbnRPcHRzKG1hdGNoR3JvdXBzLCB0aGlzSUQsIGFsbEF4aXNJZHMsIGxheW91dE91dCk7XG4gICAgICAgIG1hdGNoZXMgPSBMaWIuY29lcmNlKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIHtcbiAgICAgICAgICAgIG1hdGNoZXM6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICAgICAgdmFsdWVzOiBtYXRjaE9wdHMubGlua2FibGVBeGVzIHx8IFtdLFxuICAgICAgICAgICAgICAgIGRmbHQ6IHNwbG9tU3Rhc2gubWF0Y2hlc1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCAnbWF0Y2hlcycpO1xuICAgIH1cblxuICAgIC8vICdtYXRjaGVzJyB3aW5zIG92ZXIgJ3NjYWxlYW5jaG9yJyAoZm9yIG5vdylcbiAgICB2YXIgc2NhbGVhbmNob3IsIHNjYWxlT3B0cztcblxuICAgIGlmKCFtYXRjaGVzICYmIGNvbnRhaW5lckluLnNjYWxlYW5jaG9yICYmICEoY29udGFpbmVyT3V0LmZpeGVkcmFuZ2UgJiYgY29uc3RyYWluICE9PSAnZG9tYWluJykpIHtcbiAgICAgICAgc2NhbGVPcHRzID0gZ2V0Q29uc3RyYWludE9wdHMoY29uc3RyYWludEdyb3VwcywgdGhpc0lELCBhbGxBeGlzSWRzLCBsYXlvdXRPdXQsIGNvbnN0cmFpbik7XG4gICAgICAgIHNjYWxlYW5jaG9yID0gTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCB7XG4gICAgICAgICAgICBzY2FsZWFuY2hvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgICAgICB2YWx1ZXM6IHNjYWxlT3B0cy5saW5rYWJsZUF4ZXMgfHwgW11cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgJ3NjYWxlYW5jaG9yJyk7XG4gICAgfVxuXG4gICAgaWYobWF0Y2hlcykge1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LmNvbnN0cmFpbjtcbiAgICAgICAgdXBkYXRlQ29uc3RyYWludEdyb3VwcyhtYXRjaEdyb3VwcywgbWF0Y2hPcHRzLnRoaXNHcm91cCwgdGhpc0lELCBtYXRjaGVzLCAxKTtcbiAgICB9IGVsc2UgaWYoYWxsQXhpc0lkcy5pbmRleE9mKGNvbnRhaW5lckluLm1hdGNoZXMpICE9PSAtMSkge1xuICAgICAgICBMaWIud2FybignaWdub3JlZCAnICsgY29udGFpbmVyT3V0Ll9uYW1lICsgJy5tYXRjaGVzOiBcIicgK1xuICAgICAgICAgICAgY29udGFpbmVySW4ubWF0Y2hlcyArICdcIiB0byBhdm9pZCBlaXRoZXIgYW4gaW5maW5pdGUgbG9vcCAnICtcbiAgICAgICAgICAgICdvciBiZWNhdXNlIHRoZSB0YXJnZXQgYXhpcyBoYXMgZml4ZWQgcmFuZ2UuJyk7XG4gICAgfVxuXG4gICAgaWYoc2NhbGVhbmNob3IpIHtcbiAgICAgICAgdmFyIHNjYWxlcmF0aW8gPSBjb2VyY2UoJ3NjYWxlcmF0aW8nKTtcblxuICAgICAgICAvLyBUT0RPOiBJIHN1cHBvc2UgSSBjb3VsZCBkbyBhdHRyaWJ1dGUubWluOiBOdW1iZXIuTUlOX1ZBTFVFIHRvIGF2b2lkIHplcm8sXG4gICAgICAgIC8vIGJ1dCB0aGF0IHNlZW1zIGhhY2t5LiBCZXR0ZXIgd2F5IHRvIHNheSBcIm11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXJcIj9cbiAgICAgICAgLy8gT2YgY291cnNlIGlmIHlvdSB1c2Ugc2V2ZXJhbCBzdXBlci10aW55IHZhbHVlcyB5b3UgY291bGQgZXZlbnR1YWxseVxuICAgICAgICAvLyBmb3JjZSBhIHByb2R1Y3Qgb2YgdGhlc2UgdG8gemVybyBhbmQgYWxsIGhlbGwgd291bGQgYnJlYWsgbG9vc2UuLi5cbiAgICAgICAgLy8gTGlrZXdpc2Ugd2l0aCBzdXBlci1odWdlIHZhbHVlcy5cbiAgICAgICAgaWYoIXNjYWxlcmF0aW8pIHNjYWxlcmF0aW8gPSBjb250YWluZXJPdXQuc2NhbGVyYXRpbyA9IDE7XG5cbiAgICAgICAgdXBkYXRlQ29uc3RyYWludEdyb3Vwcyhjb25zdHJhaW50R3JvdXBzLCBzY2FsZU9wdHMudGhpc0dyb3VwLCB0aGlzSUQsIHNjYWxlYW5jaG9yLCBzY2FsZXJhdGlvKTtcbiAgICB9IGVsc2UgaWYoYWxsQXhpc0lkcy5pbmRleE9mKGNvbnRhaW5lckluLnNjYWxlYW5jaG9yKSAhPT0gLTEpIHtcbiAgICAgICAgTGliLndhcm4oJ2lnbm9yZWQgJyArIGNvbnRhaW5lck91dC5fbmFtZSArICcuc2NhbGVhbmNob3I6IFwiJyArXG4gICAgICAgICAgICBjb250YWluZXJJbi5zY2FsZWFuY2hvciArICdcIiB0byBhdm9pZCBlaXRoZXIgYW4gaW5maW5pdGUgbG9vcCAnICtcbiAgICAgICAgICAgICdhbmQgcG9zc2libHkgaW5jb25zaXN0ZW50IHNjYWxlcmF0aW9zLCBvciBiZWNhdXNlIHRoZSB0YXJnZXQgJyArXG4gICAgICAgICAgICAnYXhpcyBoYXMgZml4ZWQgcmFuZ2Ugb3IgdGhpcyBheGlzIGRlY2xhcmVzIGEgKm1hdGNoZXMqIGNvbnN0cmFpbnQuJyk7XG4gICAgfVxufTtcblxuLy8gSWYgdGhpcyBheGlzIGlzIGFscmVhZHkgcGFydCBvZiBhIGNvbnN0cmFpbnQgZ3JvdXAsIHdlIGNhbid0XG4vLyBzY2FsZWFuY2hvciBhbnkgb3RoZXIgYXhpcyBpbiB0aGF0IGdyb3VwLCBvciB3ZSdkIG1ha2UgYSBsb29wLlxuLy8gRmlsdGVyIGFsbEF4aXNJZHMgdG8gZW5mb3JjZSB0aGlzLCBhbHNvIG1hdGNoaW5nIGF4aXMgdHlwZXMuXG5mdW5jdGlvbiBnZXRDb25zdHJhaW50T3B0cyhncm91cHMsIHRoaXNJRCwgYWxsQXhpc0lkcywgbGF5b3V0T3V0LCBjb25zdHJhaW4pIHtcbiAgICB2YXIgZG9lc05vdENvbnN0cmFpblJhbmdlID0gY29uc3RyYWluICE9PSAncmFuZ2UnO1xuICAgIHZhciB0aGlzVHlwZSA9IGxheW91dE91dFtpZDJuYW1lKHRoaXNJRCldLnR5cGU7XG4gICAgdmFyIGksIGosIGlkaiwgYXhqO1xuXG4gICAgdmFyIGxpbmthYmxlQXhlcyA9IFtdO1xuICAgIGZvcihqID0gMDsgaiA8IGFsbEF4aXNJZHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWRqID0gYWxsQXhpc0lkc1tqXTtcbiAgICAgICAgaWYoaWRqID09PSB0aGlzSUQpIGNvbnRpbnVlO1xuXG4gICAgICAgIGF4aiA9IGxheW91dE91dFtpZDJuYW1lKGlkaildO1xuICAgICAgICBpZihheGoudHlwZSA9PT0gdGhpc1R5cGUpIHtcbiAgICAgICAgICAgIGlmKCFheGouZml4ZWRyYW5nZSkge1xuICAgICAgICAgICAgICAgIGxpbmthYmxlQXhlcy5wdXNoKGlkaik7XG4gICAgICAgICAgICB9IGVsc2UgaWYoZG9lc05vdENvbnN0cmFpblJhbmdlICYmIGF4ai5hbmNob3IpIHtcbiAgICAgICAgICAgICAgICAvLyBhbGxvdyBkb21haW4gY29uc3RyYWludHMgb24gc3VicGxvdHMgd2hlcmVcbiAgICAgICAgICAgICAgICAvLyBCT1RIIGF4ZXMgaGF2ZSBmaXhlZHJhbmdlOnRydWUgYW5kIGNvbnN0cmFpbjpkb21haW5cbiAgICAgICAgICAgICAgICB2YXIgY291bnRlckF4aiA9IGxheW91dE91dFtpZDJuYW1lKGF4ai5hbmNob3IpXTtcbiAgICAgICAgICAgICAgICBpZihjb3VudGVyQXhqLmZpeGVkcmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlua2FibGVBeGVzLnB1c2goaWRqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBncm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoZ3JvdXBzW2ldW3RoaXNJRF0pIHtcbiAgICAgICAgICAgIHZhciB0aGlzR3JvdXAgPSBncm91cHNbaV07XG5cbiAgICAgICAgICAgIHZhciBsaW5rYWJsZUF4ZXNOb0xvb3BzID0gW107XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBsaW5rYWJsZUF4ZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZGogPSBsaW5rYWJsZUF4ZXNbal07XG4gICAgICAgICAgICAgICAgaWYoIXRoaXNHcm91cFtpZGpdKSBsaW5rYWJsZUF4ZXNOb0xvb3BzLnB1c2goaWRqKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB7bGlua2FibGVBeGVzOiBsaW5rYWJsZUF4ZXNOb0xvb3BzLCB0aGlzR3JvdXA6IHRoaXNHcm91cH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge2xpbmthYmxlQXhlczogbGlua2FibGVBeGVzLCB0aGlzR3JvdXA6IG51bGx9O1xufVxuXG4vKlxuICogQWRkIHRoaXMgYXhpcyB0byB0aGUgYXhpcyBjb25zdHJhaW50IGdyb3Vwcywgd2hpY2ggaXMgdGhlIGNvbGxlY3Rpb25cbiAqIG9mIGF4ZXMgdGhhdCBhcmUgYWxsIGNvbnN0cmFpbmVkIHRvZ2V0aGVyIG9uIHNjYWxlLlxuICpcbiAqIGNvbnN0cmFpbnRHcm91cHM6IGEgbGlzdCBvZiBvYmplY3RzLiBlYWNoIG9iamVjdCBpc1xuICoge2F4aXNfaWQ6IHNjYWxlX3dpdGhpbl9ncm91cH0sIHdoZXJlIHNjYWxlX3dpdGhpbl9ncm91cCBpc1xuICogb25seSBpbXBvcnRhbnQgcmVsYXRpdmUgdG8gdGhlIHJlc3Qgb2YgdGhlIGdyb3VwLCBhbmQgZGVmaW5lc1xuICogdGhlIHJlbGF0aXZlIHNjYWxlcyBiZXR3ZWVuIGFsbCBheGVzIGluIHRoZSBncm91cFxuICpcbiAqIHRoaXNHcm91cDogdGhlIGdyb3VwIHRoZSBjdXJyZW50IGF4aXMgaXMgYWxyZWFkeSBpblxuICogdGhpc0lEOiB0aGUgaWQgaWYgdGhlIGN1cnJlbnQgYXhpc1xuICogc2NhbGVhbmNob3I6IHRoZSBpZCBvZiB0aGUgYXhpcyB0byBzY2FsZSBpdCB3aXRoXG4gKiBzY2FsZXJhdGlvOiB0aGUgcmF0aW8gb2YgdGhpcyBheGlzIHRvIHRoZSBzY2FsZWFuY2hvciBheGlzXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZUNvbnN0cmFpbnRHcm91cHMoY29uc3RyYWludEdyb3VwcywgdGhpc0dyb3VwLCB0aGlzSUQsIHNjYWxlYW5jaG9yLCBzY2FsZXJhdGlvKSB7XG4gICAgdmFyIGksIGosIGdyb3VwaSwga2V5aiwgdGhpc0dyb3VwSW5kZXg7XG5cbiAgICBpZih0aGlzR3JvdXAgPT09IG51bGwpIHtcbiAgICAgICAgdGhpc0dyb3VwID0ge307XG4gICAgICAgIHRoaXNHcm91cFt0aGlzSURdID0gMTtcbiAgICAgICAgdGhpc0dyb3VwSW5kZXggPSBjb25zdHJhaW50R3JvdXBzLmxlbmd0aDtcbiAgICAgICAgY29uc3RyYWludEdyb3Vwcy5wdXNoKHRoaXNHcm91cCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpc0dyb3VwSW5kZXggPSBjb25zdHJhaW50R3JvdXBzLmluZGV4T2YodGhpc0dyb3VwKTtcbiAgICB9XG5cbiAgICB2YXIgdGhpc0dyb3VwS2V5cyA9IE9iamVjdC5rZXlzKHRoaXNHcm91cCk7XG5cbiAgICAvLyB3ZSBrbm93IHRoYXQgdGhpcyBheGlzIGlzbid0IGluIGFueSBvdGhlciBncm91cHMsIGJ1dCB3ZSBkb24ndCBrbm93XG4gICAgLy8gYWJvdXQgdGhlIHNjYWxlYW5jaG9yIGF4aXMuIElmIGl0IGlzLCB3ZSBuZWVkIHRvIG1lcmdlIHRoZSBncm91cHMuXG4gICAgZm9yKGkgPSAwOyBpIDwgY29uc3RyYWludEdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBncm91cGkgPSBjb25zdHJhaW50R3JvdXBzW2ldO1xuICAgICAgICBpZihpICE9PSB0aGlzR3JvdXBJbmRleCAmJiBncm91cGlbc2NhbGVhbmNob3JdKSB7XG4gICAgICAgICAgICB2YXIgYmFzZVNjYWxlID0gZ3JvdXBpW3NjYWxlYW5jaG9yXTtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHRoaXNHcm91cEtleXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBrZXlqID0gdGhpc0dyb3VwS2V5c1tqXTtcbiAgICAgICAgICAgICAgICBncm91cGlba2V5al0gPSBiYXNlU2NhbGUgKiBzY2FsZXJhdGlvICogdGhpc0dyb3VwW2tleWpdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3RyYWludEdyb3Vwcy5zcGxpY2UodGhpc0dyb3VwSW5kZXgsIDEpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gb3RoZXJ3aXNlLCB3ZSBpbnNlcnQgdGhlIG5ldyBzY2FsZWFuY2hvciBheGlzIGFzIHRoZSBiYXNlIHNjYWxlICgxKVxuICAgIC8vIGluIGl0cyBncm91cCwgYW5kIHNjYWxlIHRoZSByZXN0IG9mIHRoZSBncm91cCB0byBpdFxuICAgIGlmKHNjYWxlcmF0aW8gIT09IDEpIHtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgdGhpc0dyb3VwS2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdGhpc0dyb3VwW3RoaXNHcm91cEtleXNbal1dICo9IHNjYWxlcmF0aW87XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhpc0dyb3VwW3NjYWxlYW5jaG9yXSA9IDE7XG59XG5cbmV4cG9ydHMuZW5mb3JjZSA9IGZ1bmN0aW9uIGVuZm9yY2UoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBjb25zdHJhaW50R3JvdXBzID0gZnVsbExheW91dC5fYXhpc0NvbnN0cmFpbnRHcm91cHMgfHwgW107XG5cbiAgICB2YXIgaSwgaiwgYXhpc0lELCBheCwgbm9ybVNjYWxlLCBtb2RlLCBmYWN0b3I7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBjb25zdHJhaW50R3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBncm91cCA9IGNvbnN0cmFpbnRHcm91cHNbaV07XG4gICAgICAgIHZhciBheGlzSURzID0gT2JqZWN0LmtleXMoZ3JvdXApO1xuXG4gICAgICAgIHZhciBtaW5TY2FsZSA9IEluZmluaXR5O1xuICAgICAgICB2YXIgbWF4U2NhbGUgPSAwO1xuICAgICAgICAvLyBtb3N0bHkgbWF0Y2hTY2FsZSB3aWxsIGJlIHRoZSBzYW1lIGFzIG1pblNjYWxlXG4gICAgICAgIC8vIGllIHdlIGV4cGFuZCBheGlzIHJhbmdlcyB0byBlbmNvbXBhc3MgKmV2ZXJ5dGhpbmcqXG4gICAgICAgIC8vIHRoYXQncyBjdXJyZW50bHkgaW4gYW55IG9mIHRoZWlyIHJhbmdlcywgYnV0IGR1cmluZ1xuICAgICAgICAvLyBhdXRvcmFuZ2Ugb2YgYSBzdWJzZXQgb2YgYXhlcyB3ZSB3aWxsIGlnbm9yZSBvdGhlclxuICAgICAgICAvLyBheGVzIGZvciB0aGlzIHB1cnBvc2UuXG4gICAgICAgIHZhciBtYXRjaFNjYWxlID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBub3JtU2NhbGVzID0ge307XG4gICAgICAgIHZhciBheGVzID0ge307XG4gICAgICAgIHZhciBoYXNBbnlEb21haW5Db25zdHJhaW50ID0gZmFsc2U7XG5cbiAgICAgICAgLy8gZmluZCB0aGUgKG5vcm1hbGl6ZWQpIHNjYWxlIG9mIGVhY2ggYXhpcyBpbiB0aGUgZ3JvdXBcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgYXhpc0lEcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgYXhpc0lEID0gYXhpc0lEc1tqXTtcbiAgICAgICAgICAgIGF4ZXNbYXhpc0lEXSA9IGF4ID0gZnVsbExheW91dFtpZDJuYW1lKGF4aXNJRCldO1xuXG4gICAgICAgICAgICBpZihheC5faW5wdXREb21haW4pIGF4LmRvbWFpbiA9IGF4Ll9pbnB1dERvbWFpbi5zbGljZSgpO1xuICAgICAgICAgICAgZWxzZSBheC5faW5wdXREb21haW4gPSBheC5kb21haW4uc2xpY2UoKTtcblxuICAgICAgICAgICAgaWYoIWF4Ll9pbnB1dFJhbmdlKSBheC5faW5wdXRSYW5nZSA9IGF4LnJhbmdlLnNsaWNlKCk7XG5cbiAgICAgICAgICAgIC8vIHNldCBheGlzIHNjYWxlIGhlcmUgc28gd2UgY2FuIHVzZSBfbSByYXRoZXIgdGhhblxuICAgICAgICAgICAgLy8gaGF2aW5nIHRvIGNhbGN1bGF0ZSBpdCBmcm9tIGxlbmd0aCBhbmQgcmFuZ2VcbiAgICAgICAgICAgIGF4LnNldFNjYWxlKCk7XG5cbiAgICAgICAgICAgIC8vIGFiczogaW52ZXJ0ZWQgc2NhbGVzIHN0aWxsIHNhdGlzZnkgdGhlIGNvbnN0cmFpbnRcbiAgICAgICAgICAgIG5vcm1TY2FsZXNbYXhpc0lEXSA9IG5vcm1TY2FsZSA9IE1hdGguYWJzKGF4Ll9tKSAvIGdyb3VwW2F4aXNJRF07XG4gICAgICAgICAgICBtaW5TY2FsZSA9IE1hdGgubWluKG1pblNjYWxlLCBub3JtU2NhbGUpO1xuICAgICAgICAgICAgaWYoYXguY29uc3RyYWluID09PSAnZG9tYWluJyB8fCAhYXguX2NvbnN0cmFpbnRTaHJpbmthYmxlKSB7XG4gICAgICAgICAgICAgICAgbWF0Y2hTY2FsZSA9IE1hdGgubWluKG1hdGNoU2NhbGUsIG5vcm1TY2FsZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHRoaXMgaGFzIHNlcnZlZCBpdHMgcHVycG9zZSwgc28gcmVtb3ZlIGl0XG4gICAgICAgICAgICBkZWxldGUgYXguX2NvbnN0cmFpbnRTaHJpbmthYmxlO1xuICAgICAgICAgICAgbWF4U2NhbGUgPSBNYXRoLm1heChtYXhTY2FsZSwgbm9ybVNjYWxlKTtcblxuICAgICAgICAgICAgaWYoYXguY29uc3RyYWluID09PSAnZG9tYWluJykgaGFzQW55RG9tYWluQ29uc3RyYWludCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEbyB3ZSBoYXZlIGEgY29uc3RyYWludCBtaXNtYXRjaD8gR2l2ZSBhIHNtYWxsIGJ1ZmZlciBmb3Igcm91bmRpbmcgZXJyb3JzXG4gICAgICAgIGlmKG1pblNjYWxlID4gQUxNT1NUX0VRVUFMICogbWF4U2NhbGUgJiYgIWhhc0FueURvbWFpbkNvbnN0cmFpbnQpIGNvbnRpbnVlO1xuXG4gICAgICAgIC8vIG5vdyBpbmNyZWFzZSBhbnkgcmFuZ2VzIHdlIG5lZWQgdG8gdW50aWwgYWxsIG5vcm1hbGl6ZWQgc2NhbGVzIGFyZSBlcXVhbFxuICAgICAgICBmb3IoaiA9IDA7IGogPCBheGlzSURzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBheGlzSUQgPSBheGlzSURzW2pdO1xuICAgICAgICAgICAgbm9ybVNjYWxlID0gbm9ybVNjYWxlc1theGlzSURdO1xuICAgICAgICAgICAgYXggPSBheGVzW2F4aXNJRF07XG4gICAgICAgICAgICBtb2RlID0gYXguY29uc3RyYWluO1xuXG4gICAgICAgICAgICAvLyBldmVuIGlmIHRoZSBzY2FsZSBkaWRuJ3QgY2hhbmdlLCBpZiB3ZSdyZSBzaHJpbmtpbmcgZG9tYWluXG4gICAgICAgICAgICAvLyB3ZSBuZWVkIHRvIHJlY2FsY3VsYXRlIGluIGNhc2UgYGNvbnN0cmFpbnRvd2FyZGAgY2hhbmdlZFxuICAgICAgICAgICAgaWYobm9ybVNjYWxlICE9PSBtYXRjaFNjYWxlIHx8IG1vZGUgPT09ICdkb21haW4nKSB7XG4gICAgICAgICAgICAgICAgZmFjdG9yID0gbm9ybVNjYWxlIC8gbWF0Y2hTY2FsZTtcblxuICAgICAgICAgICAgICAgIGlmKG1vZGUgPT09ICdyYW5nZScpIHtcbiAgICAgICAgICAgICAgICAgICAgc2NhbGVab29tKGF4LCBmYWN0b3IpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIG1vZGUgPT09ICdkb21haW4nXG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0RG9tYWluID0gYXguX2lucHV0RG9tYWluO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9tYWluU2hydW5rID0gKGF4LmRvbWFpblsxXSAtIGF4LmRvbWFpblswXSkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgKGlucHV0RG9tYWluWzFdIC0gaW5wdXREb21haW5bMF0pO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmFuZ2VTaHJ1bmsgPSAoYXgucjJsKGF4LnJhbmdlWzFdKSAtIGF4LnIybChheC5yYW5nZVswXSkpIC9cbiAgICAgICAgICAgICAgICAgICAgICAgIChheC5yMmwoYXguX2lucHV0UmFuZ2VbMV0pIC0gYXgucjJsKGF4Ll9pbnB1dFJhbmdlWzBdKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgZmFjdG9yIC89IGRvbWFpblNocnVuaztcblxuICAgICAgICAgICAgICAgICAgICBpZihmYWN0b3IgKiByYW5nZVNocnVuayA8IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlJ3ZlIGFza2VkIHRvIG1hZ25pZnkgdGhlIGF4aXMgbW9yZSB0aGFuIHdlIGNhbiBqdXN0IGJ5XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBlbmxhcmdpbmcgdGhlIGRvbWFpbiAtIHNvIHdlIG5lZWQgdG8gY29uc3RyaWN0IHJhbmdlXG4gICAgICAgICAgICAgICAgICAgICAgICBheC5kb21haW4gPSBheC5faW5wdXQuZG9tYWluID0gaW5wdXREb21haW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWm9vbShheCwgZmFjdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYocmFuZ2VTaHJ1bmsgPCAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgcmFuZ2UgaGFzIHByZXZpb3VzbHkgYmVlbiBjb25zdHJpY3RlZCBieSBeXiwgYnV0IHdlJ3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzd2l0Y2hlZCB0byB0aGUgZG9tYWluLWNvbnN0cmljdGVkIHJlZ2ltZSwgc28gcmVzZXQgcmFuZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgIGF4LnJhbmdlID0gYXguX2lucHV0LnJhbmdlID0gYXguX2lucHV0UmFuZ2Uuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZhY3RvciAqPSByYW5nZVNocnVuaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmKGF4LmF1dG9yYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgICAgICAgICAgICAqIHJhbmdlICYgZmFjdG9yIG1heSBuZWVkIHRvIGNoYW5nZSBiZWNhdXNlIHJhbmdlIHdhc1xuICAgICAgICAgICAgICAgICAgICAgICAgICogY2FsY3VsYXRlZCBmb3IgdGhlIGxhcmdlciBzY2FsaW5nLCBzbyBzb21lIHBpeGVsXG4gICAgICAgICAgICAgICAgICAgICAgICAgKiBwYWRkaW5ncyBtYXkgZ2V0IGN1dCBvZmYgd2hlbiB3ZSByZWR1Y2UgdGhlIGRvbWFpbi5cbiAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgKiBUaGlzIGlzIGVhc2llciB0aGFuIHRoZSByZWd1bGFyIGF1dG9yYW5nZSBjYWxjdWxhdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICogYmVjYXVzZSB3ZSBhbHJlYWR5IGtub3cgdGhlIHNjYWxpbmcgYG1gLCBidXQgd2Ugc3RpbGxcbiAgICAgICAgICAgICAgICAgICAgICAgICAqIG5lZWQgdG8gY3V0IG91dCBpbXBvc3NpYmxlIGNvbnN0cmFpbnRzIChsaWtlXG4gICAgICAgICAgICAgICAgICAgICAgICAgKiBhbm5vdGF0aW9ucyB3aXRoIHN1cGVyLWxvbmcgYXJyb3dzKS4gVGhhdCdzIHdoYXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAqIG91dGVyTWluL01heCBhcmUgZm9yIC0gaWYgdGhlIGV4cGFuc2lvbiB3YXMgZ29pbmcgdG9cbiAgICAgICAgICAgICAgICAgICAgICAgICAqIGdvIGJleW9uZCB0aGUgb3JpZ2luYWwgZG9tYWluLCBpdCBtdXN0IGJlIGltcG9zc2libGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJsMCA9IGF4LnIybChheC5yYW5nZVswXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmwxID0gYXgucjJsKGF4LnJhbmdlWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYW5nZUNlbnRlciA9IChybDAgKyBybDEpIC8gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByYW5nZU1pbiA9IHJhbmdlQ2VudGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJhbmdlTWF4ID0gcmFuZ2VDZW50ZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaGFsZlJhbmdlID0gTWF0aC5hYnMocmwxIC0gcmFuZ2VDZW50ZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXh0cmEgdGlueSBiaXQgZm9yIHJvdW5kaW5nIGVycm9ycywgaW4gY2FzZSB3ZSBhY3R1YWxseVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gKmFyZSogZXhwYW5kaW5nIHRvIHRoZSBmdWxsIGRvbWFpblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG91dGVyTWluID0gcmFuZ2VDZW50ZXIgLSBoYWxmUmFuZ2UgKiBmYWN0b3IgKiAxLjAwMDE7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgb3V0ZXJNYXggPSByYW5nZUNlbnRlciArIGhhbGZSYW5nZSAqIGZhY3RvciAqIDEuMDAwMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBnZXRQYWQgPSBtYWtlUGFkRm4oYXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVEb21haW4oYXgsIGZhY3Rvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbSA9IE1hdGguYWJzKGF4Ll9tKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBleHRyZW1lcyA9IGNvbmNhdEV4dHJlbWVzKGdkLCBheCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWluQXJyYXkgPSBleHRyZW1lcy5taW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWF4QXJyYXkgPSBleHRyZW1lcy5tYXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV3VmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcihrID0gMDsgayA8IG1pbkFycmF5Lmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VmFsID0gbWluQXJyYXlba10udmFsIC0gZ2V0UGFkKG1pbkFycmF5W2tdKSAvIG07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYobmV3VmFsID4gb3V0ZXJNaW4gJiYgbmV3VmFsIDwgcmFuZ2VNaW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2VNaW4gPSBuZXdWYWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IoayA9IDA7IGsgPCBtYXhBcnJheS5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ZhbCA9IG1heEFycmF5W2tdLnZhbCArIGdldFBhZChtYXhBcnJheVtrXSkgLyBtO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKG5ld1ZhbCA8IG91dGVyTWF4ICYmIG5ld1ZhbCA+IHJhbmdlTWF4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlTWF4ID0gbmV3VmFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRvbWFpbkV4cGFuZCA9IChyYW5nZU1heCAtIHJhbmdlTWluKSAvICgyICogaGFsZlJhbmdlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZhY3RvciAvPSBkb21haW5FeHBhbmQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlTWluID0gYXgubDJyKHJhbmdlTWluKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlTWF4ID0gYXgubDJyKHJhbmdlTWF4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF4LnJhbmdlID0gYXguX2lucHV0LnJhbmdlID0gKHJsMCA8IHJsMSkgP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtyYW5nZU1pbiwgcmFuZ2VNYXhdIDogW3JhbmdlTWF4LCByYW5nZU1pbl07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB1cGRhdGVEb21haW4oYXgsIGZhY3Rvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuLy8gRm9yIHVzZSBiZWZvcmUgYXV0b3JhbmdpbmcsIGNoZWNrIGlmIHRoaXMgYXhpcyB3YXMgcHJldmlvdXNseSBjb25zdHJhaW5lZFxuLy8gYnkgZG9tYWluIGJ1dCBubyBsb25nZXIgaXNcbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbiBjbGVhbihnZCwgYXgpIHtcbiAgICBpZihheC5faW5wdXREb21haW4pIHtcbiAgICAgICAgdmFyIGlzQ29uc3RyYWluZWQgPSBmYWxzZTtcbiAgICAgICAgdmFyIGF4SWQgPSBheC5faWQ7XG4gICAgICAgIHZhciBjb25zdHJhaW50R3JvdXBzID0gZ2QuX2Z1bGxMYXlvdXQuX2F4aXNDb25zdHJhaW50R3JvdXBzO1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY29uc3RyYWludEdyb3Vwcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgaWYoY29uc3RyYWludEdyb3Vwc1tqXVtheElkXSkge1xuICAgICAgICAgICAgICAgIGlzQ29uc3RyYWluZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKCFpc0NvbnN0cmFpbmVkIHx8IGF4LmNvbnN0cmFpbiAhPT0gJ2RvbWFpbicpIHtcbiAgICAgICAgICAgIGF4Ll9pbnB1dC5kb21haW4gPSBheC5kb21haW4gPSBheC5faW5wdXREb21haW47XG4gICAgICAgICAgICBkZWxldGUgYXguX2lucHV0RG9tYWluO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuZnVuY3Rpb24gdXBkYXRlRG9tYWluKGF4LCBmYWN0b3IpIHtcbiAgICB2YXIgaW5wdXREb21haW4gPSBheC5faW5wdXREb21haW47XG4gICAgdmFyIGNlbnRlckZyYWN0aW9uID0gRlJPTV9CTFtheC5jb25zdHJhaW50b3dhcmRdO1xuICAgIHZhciBjZW50ZXIgPSBpbnB1dERvbWFpblswXSArIChpbnB1dERvbWFpblsxXSAtIGlucHV0RG9tYWluWzBdKSAqIGNlbnRlckZyYWN0aW9uO1xuXG4gICAgYXguZG9tYWluID0gYXguX2lucHV0LmRvbWFpbiA9IFtcbiAgICAgICAgY2VudGVyICsgKGlucHV0RG9tYWluWzBdIC0gY2VudGVyKSAvIGZhY3RvcixcbiAgICAgICAgY2VudGVyICsgKGlucHV0RG9tYWluWzFdIC0gY2VudGVyKSAvIGZhY3RvclxuICAgIF07XG4gICAgYXguc2V0U2NhbGUoKTtcbn1cblxufSx7XCIuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50XCI6Njg4LFwiLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbFwiOjY5NSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4vYXV0b3JhbmdlXCI6NzY2LFwiLi9heGlzX2lkc1wiOjc3MCxcIi4vc2NhbGVfem9vbVwiOjc4M31dLDc3NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgdGlueWNvbG9yID0gX2RlcmVxXygndGlueWNvbG9yMicpO1xudmFyIHN1cHBvcnRzUGFzc2l2ZSA9IF9kZXJlcV8oJ2hhcy1wYXNzaXZlLWV2ZW50cycpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBGeCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi9heGVzJyk7XG52YXIgc2V0Q3Vyc29yID0gX2RlcmVxXygnLi4vLi4vbGliL3NldGN1cnNvcicpO1xudmFyIGRyYWdFbGVtZW50ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmFnZWxlbWVudCcpO1xudmFyIEZST01fVEwgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50JykuRlJPTV9UTDtcbnZhciBjbGVhckdsQ2FudmFzZXMgPSBfZGVyZXFfKCcuLi8uLi9saWIvY2xlYXJfZ2xfY2FudmFzZXMnKTtcbnZhciByZWRyYXdSZWdsVHJhY2VzID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvc3Vicm91dGluZXMnKS5yZWRyYXdSZWdsVHJhY2VzO1xuXG52YXIgUGxvdHMgPSBfZGVyZXFfKCcuLi9wbG90cycpO1xuXG52YXIgZ2V0RnJvbUlkID0gX2RlcmVxXygnLi9heGlzX2lkcycpLmdldEZyb21JZDtcbnZhciBwcmVwU2VsZWN0ID0gX2RlcmVxXygnLi9zZWxlY3QnKS5wcmVwU2VsZWN0O1xudmFyIGNsZWFyU2VsZWN0ID0gX2RlcmVxXygnLi9zZWxlY3QnKS5jbGVhclNlbGVjdDtcbnZhciBzZWxlY3RPbkNsaWNrID0gX2RlcmVxXygnLi9zZWxlY3QnKS5zZWxlY3RPbkNsaWNrO1xudmFyIHNjYWxlWm9vbSA9IF9kZXJlcV8oJy4vc2NhbGVfem9vbScpO1xuXG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcbnZhciBNSU5EUkFHID0gY29uc3RhbnRzLk1JTkRSQUc7XG52YXIgTUlOWk9PTSA9IGNvbnN0YW50cy5NSU5aT09NO1xuXG4vLyBmbGFnIGZvciBzaG93aW5nIFwiZG91YmxlY2xpY2sgdG8gem9vbSBvdXRcIiBvbmx5IGF0IHRoZSBiZWdpbm5pbmdcbnZhciBTSE9XWk9PTU9VVFRJUCA9IHRydWU7XG5cbi8vIGRyYWdCb3g6IGNyZWF0ZSBhbiBlbGVtZW50IHRvIGRyYWcgb25lIG9yIG1vcmUgYXhpcyBlbmRzXG4vLyBpbnB1dHM6XG4vLyAgICAgIHBsb3RpbmZvIC0gd2hpY2ggc3VicGxvdCBhcmUgd2UgbWFraW5nIGRyYWdib3hlcyBvbj9cbi8vICAgICAgeCx5LHcsaCAtIGxlZnQsIHRvcCwgd2lkdGgsIGhlaWdodCBvZiB0aGUgYm94XG4vLyAgICAgIG5zIC0gaG93IGRvZXMgdGhpcyBkcmFnIHRoZSB2ZXJ0aWNhbCBheGlzP1xuLy8gICAgICAgICAgJ24nIC0gdG9wIG9ubHlcbi8vICAgICAgICAgICdzJyAtIGJvdHRvbSBvbmx5XG4vLyAgICAgICAgICAnbnMnIC0gdG9wIGFuZCBib3R0b20gdG9nZXRoZXIsIGRpZmZlcmVuY2UgdW5jaGFuZ2VkXG4vLyAgICAgIGV3IC0gc2FtZSBmb3IgaG9yaXpvbnRhbCBheGlzXG5mdW5jdGlvbiBtYWtlRHJhZ0JveChnZCwgcGxvdGluZm8sIHgsIHksIHcsIGgsIG5zLCBldykge1xuICAgIC8vIG1vdXNlRG93biBzdG9yZXMgbXMgb2YgZmlyc3QgbW91c2Vkb3duIGV2ZW50IGluIHRoZSBsYXN0XG4gICAgLy8gYGdkLl9jb250ZXh0LmRvdWJsZUNsaWNrRGVsYXlgIG1zIG9uIHRoZSBkcmFnIGJhcnNcbiAgICAvLyBudW1DbGlja3Mgc3RvcmVzIGhvdyBtYW55IG1vdXNlZG93bnMgaGF2ZSBiZWVuIHNlZW5cbiAgICAvLyB3aXRoaW4gYGdkLl9jb250ZXh0LmRvdWJsZUNsaWNrRGVsYXlgIHNvIHdlIGNhbiBjaGVjayBmb3IgY2xpY2sgb3IgZG91YmxlY2xpY2sgZXZlbnRzXG4gICAgLy8gZHJhZ2dlZCBzdG9yZXMgd2hldGhlciBhIGRyYWcgaGFzIG9jY3VycmVkLCBzbyB3ZSBkb24ndCBoYXZlIHRvXG4gICAgLy8gcmVkcmF3IHVubmVjZXNzYXJpbHksIGllIGlmIG5vIG1vdmUgYmlnZ2VyIHRoYW4gTUlORFJBRyBvciBNSU5aT09NIHB4XG4gICAgdmFyIHpvb21sYXllciA9IGdkLl9mdWxsTGF5b3V0Ll96b29tbGF5ZXI7XG4gICAgdmFyIGlzTWFpbkRyYWcgPSAobnMgKyBldyA9PT0gJ25zZXcnKTtcbiAgICB2YXIgc2luZ2xlRW5kID0gKG5zICsgZXcpLmxlbmd0aCA9PT0gMTtcblxuICAgIC8vIG1haW4gc3VicGxvdCB4IGFuZCB5IChpLmUuIGZvdW5kIGluIHBsb3RpbmZvIC0gdGhlIG1haW4gb25lcylcbiAgICB2YXIgeGEwLCB5YTA7XG4gICAgLy8ge2F4Ll9pZDogYXh9IGhhc2ggb2JqZWN0c1xuICAgIHZhciB4YUhhc2gsIHlhSGFzaDtcbiAgICAvLyB4YUhhc2gveWFIYXNoIHZhbHVlcyAoYXJyYXlzKVxuICAgIHZhciB4YXhlcywgeWF4ZXM7XG4gICAgLy8gbWFpbiBheGlzIG9mZnNldHNcbiAgICB2YXIgeHMsIHlzO1xuICAgIC8vIG1haW4gYXhpcyBsZW5ndGhzXG4gICAgdmFyIHB3LCBwaDtcbiAgICAvLyBjb250YWlucyBrZXlzICd4YUhhc2gnLCAneWFIYXNoJywgJ3hheGVzJywgYW5kICd5YXhlcydcbiAgICAvLyB3aGljaCBhcmUgdGhlIHgveSB7YXguX2lkOiBheH0gaGFzaCBvYmplY3RzIGFuZCB0aGVpciB2YWx1ZXNcbiAgICAvLyBmb3IgbGlua2VkIGF4aXMgcmVsYXRpdmUgdG8gdGhpcyBzdWJwbG90XG4gICAgdmFyIGxpbmtzO1xuICAgIC8vIHNpbWlsYXIgdG8gYGxpbmtzYCBidXQgZm9yIG1hdGNoaW5nIGF4ZXNcbiAgICB2YXIgbWF0Y2hlcztcbiAgICAvLyBzZXQgdG8gZXcvbnMgdmFsIHdoZW4gYWN0aXZlLCBzZXQgdG8gJycgd2hlbiBpbmFjdGl2ZVxuICAgIHZhciB4QWN0aXZlLCB5QWN0aXZlO1xuICAgIC8vIGFyZSBhbGwgYXhlcyBpbiB0aGlzIHN1YnBsb3QgYXJlIGZpeGVkP1xuICAgIHZhciBhbGxGaXhlZFJhbmdlcztcbiAgICAvLyBkbyB3ZSBuZWVkIHRvIGVkaXQgeC95IHJhbmdlcz9cbiAgICB2YXIgZWRpdFgsIGVkaXRZO1xuICAgIC8vIGdyYXBoLXdpZGUgb3B0aW1pemF0aW9uIGZsYWdzXG4gICAgdmFyIGhhc1NjYXR0ZXJHbCwgaGFzU3Bsb20sIGhhc1NWRztcbiAgICAvLyBjb2xsZWN0ZWQgY2hhbmdlcyB0byBiZSBtYWRlIHRvIHRoZSBwbG90IGJ5IHJlbGF5b3V0IGF0IHRoZSBlbmRcbiAgICB2YXIgdXBkYXRlcztcblxuICAgIGZ1bmN0aW9uIHJlY29tcHV0ZUF4aXNMaXN0cygpIHtcbiAgICAgICAgeGEwID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgIHlhMCA9IHBsb3RpbmZvLnlheGlzO1xuICAgICAgICBwdyA9IHhhMC5fbGVuZ3RoO1xuICAgICAgICBwaCA9IHlhMC5fbGVuZ3RoO1xuICAgICAgICB4cyA9IHhhMC5fb2Zmc2V0O1xuICAgICAgICB5cyA9IHlhMC5fb2Zmc2V0O1xuXG4gICAgICAgIHhhSGFzaCA9IHt9O1xuICAgICAgICB4YUhhc2hbeGEwLl9pZF0gPSB4YTA7XG4gICAgICAgIHlhSGFzaCA9IHt9O1xuICAgICAgICB5YUhhc2hbeWEwLl9pZF0gPSB5YTA7XG5cbiAgICAgICAgLy8gaWYgd2UncmUgZHJhZ2dpbmcgdHdvIGF4ZXMgYXQgb25jZSwgYWxzbyBkcmFnIG92ZXJsYXlzXG4gICAgICAgIGlmKG5zICYmIGV3KSB7XG4gICAgICAgICAgICB2YXIgb3ZlcmxheXMgPSBwbG90aW5mby5vdmVybGF5cztcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBvdmVybGF5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciB4YSA9IG92ZXJsYXlzW2ldLnhheGlzO1xuICAgICAgICAgICAgICAgIHhhSGFzaFt4YS5faWRdID0geGE7XG4gICAgICAgICAgICAgICAgdmFyIHlhID0gb3ZlcmxheXNbaV0ueWF4aXM7XG4gICAgICAgICAgICAgICAgeWFIYXNoW3lhLl9pZF0gPSB5YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHhheGVzID0gaGFzaFZhbHVlcyh4YUhhc2gpO1xuICAgICAgICB5YXhlcyA9IGhhc2hWYWx1ZXMoeWFIYXNoKTtcbiAgICAgICAgeEFjdGl2ZSA9IGlzRGlyZWN0aW9uQWN0aXZlKHhheGVzLCBldyk7XG4gICAgICAgIHlBY3RpdmUgPSBpc0RpcmVjdGlvbkFjdGl2ZSh5YXhlcywgbnMpO1xuICAgICAgICBhbGxGaXhlZFJhbmdlcyA9ICF5QWN0aXZlICYmICF4QWN0aXZlO1xuXG4gICAgICAgIGxpbmtzID0gY2FsY0xpbmtzKGdkLCBnZC5fZnVsbExheW91dC5fYXhpc0NvbnN0cmFpbnRHcm91cHMsIHhhSGFzaCwgeWFIYXNoKTtcbiAgICAgICAgbWF0Y2hlcyA9IGNhbGNMaW5rcyhnZCwgZ2QuX2Z1bGxMYXlvdXQuX2F4aXNNYXRjaEdyb3VwcywgeGFIYXNoLCB5YUhhc2gpO1xuICAgICAgICBlZGl0WCA9IGV3IHx8IGxpbmtzLmlzU3VicGxvdENvbnN0cmFpbmVkIHx8IG1hdGNoZXMuaXNTdWJwbG90Q29uc3RyYWluZWQ7XG4gICAgICAgIGVkaXRZID0gbnMgfHwgbGlua3MuaXNTdWJwbG90Q29uc3RyYWluZWQgfHwgbWF0Y2hlcy5pc1N1YnBsb3RDb25zdHJhaW5lZDtcblxuICAgICAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgICAgICBoYXNTY2F0dGVyR2wgPSBmdWxsTGF5b3V0Ll9oYXMoJ3NjYXR0ZXJnbCcpO1xuICAgICAgICBoYXNTcGxvbSA9IGZ1bGxMYXlvdXQuX2hhcygnc3Bsb20nKTtcbiAgICAgICAgaGFzU1ZHID0gZnVsbExheW91dC5faGFzKCdzdmcnKTtcbiAgICB9XG5cbiAgICByZWNvbXB1dGVBeGlzTGlzdHMoKTtcblxuICAgIHZhciBjdXJzb3IgPSBnZXREcmFnQ3Vyc29yKHlBY3RpdmUgKyB4QWN0aXZlLCBnZC5fZnVsbExheW91dC5kcmFnbW9kZSwgaXNNYWluRHJhZyk7XG4gICAgdmFyIGRyYWdnZXIgPSBtYWtlUmVjdERyYWdnZXIocGxvdGluZm8sIG5zICsgZXcgKyAnZHJhZycsIGN1cnNvciwgeCwgeSwgdywgaCk7XG5cbiAgICAvLyBzdGlsbCBuZWVkIHRvIG1ha2UgdGhlIGVsZW1lbnQgaWYgdGhlIGF4ZXMgYXJlIGRpc2FibGVkXG4gICAgLy8gYnV0IG51a2UgaXRzIGV2ZW50cyAoZXhjZXB0IGZvciBtYWluZHJhZyB3aGljaCBuZWVkcyB0aGVtIGZvciBob3ZlcilcbiAgICAvLyBhbmQgc3RvcCB0aGVyZVxuICAgIGlmKGFsbEZpeGVkUmFuZ2VzICYmICFpc01haW5EcmFnKSB7XG4gICAgICAgIGRyYWdnZXIub25tb3VzZWRvd24gPSBudWxsO1xuICAgICAgICBkcmFnZ2VyLnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7XG4gICAgICAgIHJldHVybiBkcmFnZ2VyO1xuICAgIH1cblxuICAgIHZhciBkcmFnT3B0aW9ucyA9IHtcbiAgICAgICAgZWxlbWVudDogZHJhZ2dlcixcbiAgICAgICAgZ2Q6IGdkLFxuICAgICAgICBwbG90aW5mbzogcGxvdGluZm9cbiAgICB9O1xuXG4gICAgZHJhZ09wdGlvbnMucHJlcEZuID0gZnVuY3Rpb24oZSwgc3RhcnRYLCBzdGFydFkpIHtcbiAgICAgICAgdmFyIGRyYWdNb2RlUHJldiA9IGRyYWdPcHRpb25zLmRyYWdtb2RlO1xuICAgICAgICB2YXIgZHJhZ01vZGVOb3cgPSBnZC5fZnVsbExheW91dC5kcmFnbW9kZTtcbiAgICAgICAgaWYoZHJhZ01vZGVOb3cgIT09IGRyYWdNb2RlUHJldikge1xuICAgICAgICAgICAgZHJhZ09wdGlvbnMuZHJhZ21vZGUgPSBkcmFnTW9kZU5vdztcbiAgICAgICAgfVxuXG4gICAgICAgIHJlY29tcHV0ZUF4aXNMaXN0cygpO1xuXG4gICAgICAgIGlmKCFhbGxGaXhlZFJhbmdlcykge1xuICAgICAgICAgICAgaWYoaXNNYWluRHJhZykge1xuICAgICAgICAgICAgICAgIC8vIG1haW4gZHJhZ2dlciBoYW5kbGVzIGFsbCBkcmFnIG1vZGVzLCBhbmQgY2hhbmdlc1xuICAgICAgICAgICAgICAgIC8vIHRvIHBhbiAob3IgdG8gem9vbSBpZiBpdCBhbHJlYWR5IGlzIHBhbikgb24gc2hpZnRcbiAgICAgICAgICAgICAgICBpZihlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGRyYWdNb2RlTm93ID09PSAncGFuJykgZHJhZ01vZGVOb3cgPSAnem9vbSc7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoIWlzU2VsZWN0T3JMYXNzbyhkcmFnTW9kZU5vdykpIGRyYWdNb2RlTm93ID0gJ3Bhbic7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKGUuY3RybEtleSkge1xuICAgICAgICAgICAgICAgICAgICBkcmFnTW9kZU5vdyA9ICdwYW4nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gYWxsIG90aGVyIGRyYWdnZXJzIGp1c3QgcGFuXG4gICAgICAgICAgICAgICAgZHJhZ01vZGVOb3cgPSAncGFuJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGRyYWdNb2RlTm93ID09PSAnbGFzc28nKSBkcmFnT3B0aW9ucy5taW5EcmFnID0gMTtcbiAgICAgICAgZWxzZSBkcmFnT3B0aW9ucy5taW5EcmFnID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmKGlzU2VsZWN0T3JMYXNzbyhkcmFnTW9kZU5vdykpIHtcbiAgICAgICAgICAgIGRyYWdPcHRpb25zLnhheGVzID0geGF4ZXM7XG4gICAgICAgICAgICBkcmFnT3B0aW9ucy55YXhlcyA9IHlheGVzO1xuICAgICAgICAgICAgLy8gdGhpcyBhdHRhY2hlcyBtb3ZlRm4sIGNsaWNrRm4sIGRvbmVGbiBvbiBkcmFnT3B0aW9uc1xuICAgICAgICAgICAgcHJlcFNlbGVjdChlLCBzdGFydFgsIHN0YXJ0WSwgZHJhZ09wdGlvbnMsIGRyYWdNb2RlTm93KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRyYWdPcHRpb25zLmNsaWNrRm4gPSBjbGlja0ZuO1xuICAgICAgICAgICAgaWYoaXNTZWxlY3RPckxhc3NvKGRyYWdNb2RlUHJldikpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPIEZpeCBwb3RlbnRpYWwgYnVnXG4gICAgICAgICAgICAgICAgLy8gTm90ZTogY2xlYXJpbmcgLyByZXNldHRpbmcgc2VsZWN0aW9uIHN0YXRlIG9ubHkgaGFwcGVucywgd2hlbiB1c2VyXG4gICAgICAgICAgICAgICAgLy8gdHJpZ2dlcnMgYXQgbGVhc3Qgb25lIGludGVyYWN0aW9uIGluIHBhbi96b29tIG1vZGUuIE90aGVyd2lzZSwgdGhlXG4gICAgICAgICAgICAgICAgLy8gc2VsZWN0L2xhc3NvIG91dGxpbmVzIGFyZSBkZWxldGVkIChpbiBwbG90cy5qcy5jbGVhblBsb3QpIGJ1dCB0aGUgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgLy8gY2FjaGUgaXNuJ3QgY2xlYXJlZC4gU28gd2hlbiB0aGUgdXNlciBzd2l0Y2hlcyBiYWNrIHRvIHNlbGVjdC9sYXNzbyBhbmRcbiAgICAgICAgICAgICAgICAvLyAnYWRkcyB0byBhIHNlbGVjdGlvbicgd2l0aCBTaGlmdCwgdGhlIFwib2xkXCIsIHNlZW1pbmdseSByZW1vdmVkIG91dGxpbmVzXG4gICAgICAgICAgICAgICAgLy8gYXJlIHJlZHJhd24gYWdhaW4gYmVjYXVzZSB0aGUgc2VsZWN0aW9uIGNhY2hlIHN0aWxsIGhvbGRzIHRoZWlyIGNvb3JkaW5hdGVzLlxuICAgICAgICAgICAgICAgIC8vIEhvd2V2ZXIsIHRoaXMgaXNuJ3QgZWFzaWx5IHNvbHZlZCwgc2luY2UgcGxvdHMuanMgd291bGQgbmVlZFxuICAgICAgICAgICAgICAgIC8vIHRvIGhhdmUgYSByZWZlcmVuY2UgdG8gdGhlIGRyYWdPcHRpb25zIG9iamVjdCAod2hpY2ggaG9sZHMgdGhlXG4gICAgICAgICAgICAgICAgLy8gc2VsZWN0aW9uIGNhY2hlKS5cbiAgICAgICAgICAgICAgICBjbGVhckFuZFJlc2V0U2VsZWN0KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKCFhbGxGaXhlZFJhbmdlcykge1xuICAgICAgICAgICAgICAgIGlmKGRyYWdNb2RlTm93ID09PSAnem9vbScpIHtcbiAgICAgICAgICAgICAgICAgICAgZHJhZ09wdGlvbnMubW92ZUZuID0gem9vbU1vdmU7XG4gICAgICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLmRvbmVGbiA9IHpvb21Eb25lO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHpvb21Nb3ZlIHRha2VzIGNhcmUgb2YgdGhlIHRocmVzaG9sZCwgYnV0IHdlIG5lZWQgdG9cbiAgICAgICAgICAgICAgICAgICAgLy8gbWluaW1pemUgdGhpcyBzbyB0aGF0IGNvbnN0cmFpbmVkIHpvb20gYm94ZXMgd2lsbCBmbGlwXG4gICAgICAgICAgICAgICAgICAgIC8vIG9yaWVudGF0aW9uIGF0IHRoZSByaWdodCBwbGFjZVxuICAgICAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5taW5EcmFnID0gMTtcblxuICAgICAgICAgICAgICAgICAgICB6b29tUHJlcChlLCBzdGFydFgsIHN0YXJ0WSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKGRyYWdNb2RlTm93ID09PSAncGFuJykge1xuICAgICAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5tb3ZlRm4gPSBwbG90RHJhZztcbiAgICAgICAgICAgICAgICAgICAgZHJhZ09wdGlvbnMuZG9uZUZuID0gZHJhZ1RhaWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX3JlZHJhZyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGRyYWdEYXRhTm93ID0gZ2QuX2RyYWdkYXRhO1xuXG4gICAgICAgICAgICBpZihkcmFnRGF0YU5vdyAmJiBkcmFnRGF0YU5vdy5lbGVtZW50ID09PSBkcmFnZ2VyKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRyYWdNb2RlTm93ID0gZ2QuX2Z1bGxMYXlvdXQuZHJhZ21vZGU7XG5cbiAgICAgICAgICAgICAgICBpZighaXNTZWxlY3RPckxhc3NvKGRyYWdNb2RlTm93KSkge1xuICAgICAgICAgICAgICAgICAgICByZWNvbXB1dGVBeGlzTGlzdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlU3VicGxvdHMoWzAsIDAsIHB3LCBwaF0pO1xuICAgICAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5tb3ZlRm4oZHJhZ0RhdGFOb3cuZHgsIGRyYWdEYXRhTm93LmR5KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPIHNob3VsZCB3ZSB0cnkgdG8gXCJyZS1zZWxlY3RcIiB1bmRlciBzZWxlY3QvbGFzc28gbW9kZXM/XG4gICAgICAgICAgICAgICAgLy8gcHJvYmFibHkgYmVzdCB0byB3YWl0IGZvciBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvMTg1MVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBjbGVhckFuZFJlc2V0U2VsZWN0KCkge1xuICAgICAgICAvLyBjbGVhciBzZWxlY3Rpb24gcG9seWdvbiBjYWNoZSAoaWYgYW55KVxuICAgICAgICBkcmFnT3B0aW9ucy5wbG90aW5mby5zZWxlY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgLy8gY2xlYXIgc2VsZWN0aW9uIG91dGxpbmVzXG4gICAgICAgIGNsZWFyU2VsZWN0KGdkKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjbGlja0ZuKG51bUNsaWNrcywgZXZ0KSB7XG4gICAgICAgIHZhciBjbGlja21vZGUgPSBnZC5fZnVsbExheW91dC5jbGlja21vZGU7XG5cbiAgICAgICAgcmVtb3ZlWm9vbWJveChnZCk7XG5cbiAgICAgICAgaWYobnVtQ2xpY2tzID09PSAyICYmICFzaW5nbGVFbmQpIGRvdWJsZUNsaWNrKCk7XG5cbiAgICAgICAgaWYoaXNNYWluRHJhZykge1xuICAgICAgICAgICAgaWYoY2xpY2ttb2RlLmluZGV4T2YoJ3NlbGVjdCcpID4gLTEpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3RPbkNsaWNrKGV2dCwgZ2QsIHhheGVzLCB5YXhlcywgcGxvdGluZm8uaWQsIGRyYWdPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoY2xpY2ttb2RlLmluZGV4T2YoJ2V2ZW50JykgPiAtMSkge1xuICAgICAgICAgICAgICAgIEZ4LmNsaWNrKGdkLCBldnQsIHBsb3RpbmZvLmlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKG51bUNsaWNrcyA9PT0gMSAmJiBzaW5nbGVFbmQpIHtcbiAgICAgICAgICAgIHZhciBheCA9IG5zID8geWEwIDogeGEwO1xuICAgICAgICAgICAgdmFyIGVuZCA9IChucyA9PT0gJ3MnIHx8IGV3ID09PSAndycpID8gMCA6IDE7XG4gICAgICAgICAgICB2YXIgYXR0clN0ciA9IGF4Ll9uYW1lICsgJy5yYW5nZVsnICsgZW5kICsgJ10nO1xuICAgICAgICAgICAgdmFyIGluaXRpYWxUZXh0ID0gZ2V0RW5kVGV4dChheCwgZW5kKTtcbiAgICAgICAgICAgIHZhciBoQWxpZ24gPSAnbGVmdCc7XG4gICAgICAgICAgICB2YXIgdkFsaWduID0gJ21pZGRsZSc7XG5cbiAgICAgICAgICAgIGlmKGF4LmZpeGVkcmFuZ2UpIHJldHVybjtcblxuICAgICAgICAgICAgaWYobnMpIHtcbiAgICAgICAgICAgICAgICB2QWxpZ24gPSAobnMgPT09ICduJykgPyAndG9wJyA6ICdib3R0b20nO1xuICAgICAgICAgICAgICAgIGlmKGF4LnNpZGUgPT09ICdyaWdodCcpIGhBbGlnbiA9ICdyaWdodCc7XG4gICAgICAgICAgICB9IGVsc2UgaWYoZXcgPT09ICdlJykgaEFsaWduID0gJ3JpZ2h0JztcblxuICAgICAgICAgICAgaWYoZ2QuX2NvbnRleHQuc2hvd0F4aXNSYW5nZUVudHJ5Qm94ZXMpIHtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QoZHJhZ2dlcilcbiAgICAgICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLm1ha2VFZGl0YWJsZSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgZ2Q6IGdkLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW1tZWRpYXRlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZDogZ2QuX2Z1bGxMYXlvdXQucGFwZXJfYmdjb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IFN0cmluZyhpbml0aWFsVGV4dCksXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxsOiBheC50aWNrZm9udCA/IGF4LnRpY2tmb250LmNvbG9yIDogJyM0NDQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG9yaXpvbnRhbEFsaWduOiBoQWxpZ24sXG4gICAgICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNhbEFsaWduOiB2QWxpZ25cbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLm9uKCdlZGl0JywgZnVuY3Rpb24odGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHYgPSBheC5kMnIodGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih2ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVsYXlvdXQnLCBnZCwgYXR0clN0ciwgdik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZHJhZ0VsZW1lbnQuaW5pdChkcmFnT3B0aW9ucyk7XG5cbiAgICAvLyB4L3kgcHggcG9zaXRpb24gYXQgc3RhcnQgb2YgZHJhZ1xuICAgIHZhciB4MCwgeTA7XG4gICAgLy8gYmJveCBvYmplY3Qgb2YgdGhlIHpvb21ib3hcbiAgICB2YXIgYm94O1xuICAgIC8vIGx1bWluYW5jZSBvZiBiZyBiZWhpbmQgem9vbWJveFxuICAgIHZhciBsdW07XG4gICAgLy8gem9vbWJveCBwYXRoIG91dGxpbmVcbiAgICB2YXIgcGF0aDA7XG4gICAgLy8gaXMgem9vbWJveCBkaW1tZWQgKGR1cmluZyBkcmFnKVxuICAgIHZhciBkaW1tZWQ7XG4gICAgLy8gJ3gnLW9ubHksICd5JyBvciAneHknIHpvb21pbmdcbiAgICB2YXIgem9vbU1vZGU7XG4gICAgLy8gem9vbWJveCBkMyBzZWxlY3Rpb25cbiAgICB2YXIgemI7XG4gICAgLy8gem9vbWJveCBjb3JuZXIgZDMgc2VsZWN0aW9uXG4gICAgdmFyIGNvcm5lcnM7XG4gICAgLy8gem9vbSB0YWtlcyBvdmVyIG1pbkRyYWcsIHNvIGl0IGFsc28gaGFzIHRvIHRha2Ugb3ZlciBnZC5fZHJhZ2dlZFxuICAgIHZhciB6b29tRHJhZ2dlZDtcblxuICAgIGZ1bmN0aW9uIHpvb21QcmVwKGUsIHN0YXJ0WCwgc3RhcnRZKSB7XG4gICAgICAgIHZhciBkcmFnQkJveCA9IGRyYWdnZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHgwID0gc3RhcnRYIC0gZHJhZ0JCb3gubGVmdDtcbiAgICAgICAgeTAgPSBzdGFydFkgLSBkcmFnQkJveC50b3A7XG4gICAgICAgIGJveCA9IHtsOiB4MCwgcjogeDAsIHc6IDAsIHQ6IHkwLCBiOiB5MCwgaDogMH07XG4gICAgICAgIGx1bSA9IGdkLl9obXBpeGNvdW50ID9cbiAgICAgICAgICAgIChnZC5faG1sdW1jb3VudCAvIGdkLl9obXBpeGNvdW50KSA6XG4gICAgICAgICAgICB0aW55Y29sb3IoZ2QuX2Z1bGxMYXlvdXQucGxvdF9iZ2NvbG9yKS5nZXRMdW1pbmFuY2UoKTtcbiAgICAgICAgcGF0aDAgPSAnTTAsMEgnICsgcHcgKyAnVicgKyBwaCArICdIMFYwJztcbiAgICAgICAgZGltbWVkID0gZmFsc2U7XG4gICAgICAgIHpvb21Nb2RlID0gJ3h5JztcbiAgICAgICAgem9vbURyYWdnZWQgPSBmYWxzZTtcbiAgICAgICAgemIgPSBtYWtlWm9vbWJveCh6b29tbGF5ZXIsIGx1bSwgeHMsIHlzLCBwYXRoMCk7XG4gICAgICAgIGNvcm5lcnMgPSBtYWtlQ29ybmVycyh6b29tbGF5ZXIsIHhzLCB5cyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gem9vbU1vdmUoZHgwLCBkeTApIHtcbiAgICAgICAgaWYoZ2QuX3RyYW5zaXRpb25pbmdXaXRoRHVyYXRpb24pIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB4MSA9IE1hdGgubWF4KDAsIE1hdGgubWluKHB3LCBkeDAgKyB4MCkpO1xuICAgICAgICB2YXIgeTEgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihwaCwgZHkwICsgeTApKTtcbiAgICAgICAgdmFyIGR4ID0gTWF0aC5hYnMoeDEgLSB4MCk7XG4gICAgICAgIHZhciBkeSA9IE1hdGguYWJzKHkxIC0geTApO1xuXG4gICAgICAgIGJveC5sID0gTWF0aC5taW4oeDAsIHgxKTtcbiAgICAgICAgYm94LnIgPSBNYXRoLm1heCh4MCwgeDEpO1xuICAgICAgICBib3gudCA9IE1hdGgubWluKHkwLCB5MSk7XG4gICAgICAgIGJveC5iID0gTWF0aC5tYXgoeTAsIHkxKTtcblxuICAgICAgICBmdW5jdGlvbiBub1pvb20oKSB7XG4gICAgICAgICAgICB6b29tTW9kZSA9ICcnO1xuICAgICAgICAgICAgYm94LnIgPSBib3gubDtcbiAgICAgICAgICAgIGJveC50ID0gYm94LmI7XG4gICAgICAgICAgICBjb3JuZXJzLmF0dHIoJ2QnLCAnTTAsMFonKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGxpbmtzLmlzU3VicGxvdENvbnN0cmFpbmVkKSB7XG4gICAgICAgICAgICBpZihkeCA+IE1JTlpPT00gfHwgZHkgPiBNSU5aT09NKSB7XG4gICAgICAgICAgICAgICAgem9vbU1vZGUgPSAneHknO1xuICAgICAgICAgICAgICAgIGlmKGR4IC8gcHcgPiBkeSAvIHBoKSB7XG4gICAgICAgICAgICAgICAgICAgIGR5ID0gZHggKiBwaCAvIHB3O1xuICAgICAgICAgICAgICAgICAgICBpZih5MCA+IHkxKSBib3gudCA9IHkwIC0gZHk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgYm94LmIgPSB5MCArIGR5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGR4ID0gZHkgKiBwdyAvIHBoO1xuICAgICAgICAgICAgICAgICAgICBpZih4MCA+IHgxKSBib3gubCA9IHgwIC0gZHg7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgYm94LnIgPSB4MCArIGR4O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb3JuZXJzLmF0dHIoJ2QnLCB4eUNvcm5lcnMoYm94KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG5vWm9vbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYobWF0Y2hlcy5pc1N1YnBsb3RDb25zdHJhaW5lZCkge1xuICAgICAgICAgICAgaWYoZHggPiBNSU5aT09NIHx8IGR5ID4gTUlOWk9PTSkge1xuICAgICAgICAgICAgICAgIHpvb21Nb2RlID0gJ3h5JztcblxuICAgICAgICAgICAgICAgIHZhciByMCA9IE1hdGgubWluKGJveC5sIC8gcHcsIChwaCAtIGJveC5iKSAvIHBoKTtcbiAgICAgICAgICAgICAgICB2YXIgcjEgPSBNYXRoLm1heChib3guciAvIHB3LCAocGggLSBib3gudCkgLyBwaCk7XG5cbiAgICAgICAgICAgICAgICBib3gubCA9IHIwICogcHc7XG4gICAgICAgICAgICAgICAgYm94LnIgPSByMSAqIHB3O1xuICAgICAgICAgICAgICAgIGJveC5iID0gKDEgLSByMCkgKiBwaDtcbiAgICAgICAgICAgICAgICBib3gudCA9ICgxIC0gcjEpICogcGg7XG4gICAgICAgICAgICAgICAgY29ybmVycy5hdHRyKCdkJywgeHlDb3JuZXJzKGJveCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBub1pvb20oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKCF5QWN0aXZlIHx8IGR5IDwgTWF0aC5taW4oTWF0aC5tYXgoZHggKiAwLjYsIE1JTkRSQUcpLCBNSU5aT09NKSkge1xuICAgICAgICAgICAgLy8gbG9vayBmb3Igc21hbGwgZHJhZ3MgaW4gb25lIGRpcmVjdGlvbiBvciB0aGUgb3RoZXIsXG4gICAgICAgICAgICAvLyBhbmQgb25seSBkcmFnIHRoZSBvdGhlciBheGlzXG5cbiAgICAgICAgICAgIGlmKGR4IDwgTUlORFJBRyB8fCAheEFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIG5vWm9vbSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBib3gudCA9IDA7XG4gICAgICAgICAgICAgICAgYm94LmIgPSBwaDtcbiAgICAgICAgICAgICAgICB6b29tTW9kZSA9ICd4JztcbiAgICAgICAgICAgICAgICBjb3JuZXJzLmF0dHIoJ2QnLCB4Q29ybmVycyhib3gsIHkwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZigheEFjdGl2ZSB8fCBkeCA8IE1hdGgubWluKGR5ICogMC42LCBNSU5aT09NKSkge1xuICAgICAgICAgICAgYm94LmwgPSAwO1xuICAgICAgICAgICAgYm94LnIgPSBwdztcbiAgICAgICAgICAgIHpvb21Nb2RlID0gJ3knO1xuICAgICAgICAgICAgY29ybmVycy5hdHRyKCdkJywgeUNvcm5lcnMoYm94LCB4MCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgem9vbU1vZGUgPSAneHknO1xuICAgICAgICAgICAgY29ybmVycy5hdHRyKCdkJywgeHlDb3JuZXJzKGJveCkpO1xuICAgICAgICB9XG4gICAgICAgIGJveC53ID0gYm94LnIgLSBib3gubDtcbiAgICAgICAgYm94LmggPSBib3guYiAtIGJveC50O1xuXG4gICAgICAgIGlmKHpvb21Nb2RlKSB6b29tRHJhZ2dlZCA9IHRydWU7XG4gICAgICAgIGdkLl9kcmFnZ2VkID0gem9vbURyYWdnZWQ7XG5cbiAgICAgICAgdXBkYXRlWm9vbWJveCh6YiwgY29ybmVycywgYm94LCBwYXRoMCwgZGltbWVkLCBsdW0pO1xuICAgICAgICBjb21wdXRlWm9vbVVwZGF0ZXMoKTtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3JlbGF5b3V0aW5nJywgdXBkYXRlcyk7XG4gICAgICAgIGRpbW1lZCA9IHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZVpvb21VcGRhdGVzKCkge1xuICAgICAgICB1cGRhdGVzID0ge307XG5cbiAgICAgICAgLy8gVE9ETzogZWRpdCBsaW5rZWQgYXhlcyBpbiB6b29tQXhSYW5nZXMgYW5kIGluIGRyYWdUYWlsXG4gICAgICAgIGlmKHpvb21Nb2RlID09PSAneHknIHx8IHpvb21Nb2RlID09PSAneCcpIHtcbiAgICAgICAgICAgIHpvb21BeFJhbmdlcyh4YXhlcywgYm94LmwgLyBwdywgYm94LnIgLyBwdywgdXBkYXRlcywgbGlua3MueGF4ZXMpO1xuICAgICAgICAgICAgdXBkYXRlTWF0Y2hlZEF4UmFuZ2UoJ3gnLCB1cGRhdGVzKTtcbiAgICAgICAgfVxuICAgICAgICBpZih6b29tTW9kZSA9PT0gJ3h5JyB8fCB6b29tTW9kZSA9PT0gJ3knKSB7XG4gICAgICAgICAgICB6b29tQXhSYW5nZXMoeWF4ZXMsIChwaCAtIGJveC5iKSAvIHBoLCAocGggLSBib3gudCkgLyBwaCwgdXBkYXRlcywgbGlua3MueWF4ZXMpO1xuICAgICAgICAgICAgdXBkYXRlTWF0Y2hlZEF4UmFuZ2UoJ3knLCB1cGRhdGVzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHpvb21Eb25lKCkge1xuICAgICAgICAvLyBtb3JlIHN0cmljdCB0aGFuIGRyYWdnZWQsIHdoaWNoIGFsbG93cyB5b3UgdG8gY29tZSBiYWNrIHRvIHdoZXJlIHlvdSBzdGFydGVkXG4gICAgICAgIC8vIGFuZCBzdGlsbCBjb3VudCBhcyBkcmFnZ2VkXG4gICAgICAgIGlmKE1hdGgubWluKGJveC5oLCBib3gudykgPCBNSU5EUkFHICogMikge1xuICAgICAgICAgICAgcmV0dXJuIHJlbW92ZVpvb21ib3goZ2QpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29tcHV0ZVpvb21VcGRhdGVzKCk7XG5cbiAgICAgICAgcmVtb3ZlWm9vbWJveChnZCk7XG4gICAgICAgIGRyYWdUYWlsKCk7XG4gICAgICAgIHNob3dEb3VibGVDbGlja05vdGlmaWVyKGdkKTtcbiAgICB9XG5cbiAgICAvLyBzY3JvbGwgem9vbSwgb24gYWxsIGRyYWdnZXJzIGV4Y2VwdCBjb3JuZXJzXG4gICAgdmFyIHNjcm9sbFZpZXdCb3ggPSBbMCwgMCwgcHcsIHBoXTtcbiAgICAvLyB3YWl0IGEgbGl0dGxlIGFmdGVyIHNjcm9sbGluZyBiZWZvcmUgcmVkcmF3aW5nXG4gICAgdmFyIHJlZHJhd1RpbWVyID0gbnVsbDtcbiAgICB2YXIgUkVEUkFXREVMQVkgPSBjb25zdGFudHMuUkVEUkFXREVMQVk7XG4gICAgdmFyIG1haW5wbG90ID0gcGxvdGluZm8ubWFpbnBsb3QgPyBnZC5fZnVsbExheW91dC5fcGxvdHNbcGxvdGluZm8ubWFpbnBsb3RdIDogcGxvdGluZm87XG5cbiAgICBmdW5jdGlvbiB6b29tV2hlZWwoZSkge1xuICAgICAgICAvLyBkZWFjdGl2YXRlIG1vdXNld2hlZWwgc2Nyb2xsaW5nIG9uIGVtYmVkZGVkIGdyYXBoc1xuICAgICAgICAvLyBkZXZzIGNhbiBvdmVycmlkZSB0aGlzIHdpdGggbGF5b3V0Ll9lbmFibGVzY3JvbGx6b29tLFxuICAgICAgICAvLyBidXQgXyBlbnN1cmVzIHRoaXMgc2V0dGluZyB3b24ndCBsZWF2ZSB0aGVpciBwYWdlXG4gICAgICAgIGlmKCFnZC5fY29udGV4dC5fc2Nyb2xsWm9vbS5jYXJ0ZXNpYW4gJiYgIWdkLl9mdWxsTGF5b3V0Ll9lbmFibGVzY3JvbGx6b29tKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjbGVhckFuZFJlc2V0U2VsZWN0KCk7XG5cbiAgICAgICAgLy8gSWYgYSB0cmFuc2l0aW9uIGlzIGluIHByb2dyZXNzLCB0aGVuIGRpc2FibGUgYW55IGJlaGF2aW9yOlxuICAgICAgICBpZihnZC5fdHJhbnNpdGlvbmluZ1dpdGhEdXJhdGlvbikge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlY29tcHV0ZUF4aXNMaXN0cygpO1xuXG4gICAgICAgIGNsZWFyVGltZW91dChyZWRyYXdUaW1lcik7XG5cbiAgICAgICAgdmFyIHdoZWVsRGVsdGEgPSAtZS5kZWx0YVk7XG4gICAgICAgIGlmKCFpc0Zpbml0ZSh3aGVlbERlbHRhKSkgd2hlZWxEZWx0YSA9IGUud2hlZWxEZWx0YSAvIDEwO1xuICAgICAgICBpZighaXNGaW5pdGUod2hlZWxEZWx0YSkpIHtcbiAgICAgICAgICAgIExpYi5sb2coJ0RpZCBub3QgZmluZCB3aGVlbCBtb3Rpb24gYXR0cmlidXRlczogJywgZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgem9vbSA9IE1hdGguZXhwKC1NYXRoLm1pbihNYXRoLm1heCh3aGVlbERlbHRhLCAtMjApLCAyMCkgLyAyMDApO1xuICAgICAgICB2YXIgZ2JiID0gbWFpbnBsb3QuZHJhZ2xheWVyLnNlbGVjdCgnLm5zZXdkcmFnJykubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB2YXIgeGZyYWMgPSAoZS5jbGllbnRYIC0gZ2JiLmxlZnQpIC8gZ2JiLndpZHRoO1xuICAgICAgICB2YXIgeWZyYWMgPSAoZ2JiLmJvdHRvbSAtIGUuY2xpZW50WSkgLyBnYmIuaGVpZ2h0O1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmdW5jdGlvbiB6b29tV2hlZWxPbmVBeGlzKGF4LCBjZW50ZXJGcmFjdGlvbiwgem9vbSkge1xuICAgICAgICAgICAgaWYoYXguZml4ZWRyYW5nZSkgcmV0dXJuO1xuXG4gICAgICAgICAgICB2YXIgYXhSYW5nZSA9IExpYi5zaW1wbGVNYXAoYXgucmFuZ2UsIGF4LnIybCk7XG4gICAgICAgICAgICB2YXIgdjAgPSBheFJhbmdlWzBdICsgKGF4UmFuZ2VbMV0gLSBheFJhbmdlWzBdKSAqIGNlbnRlckZyYWN0aW9uO1xuICAgICAgICAgICAgZnVuY3Rpb24gZG9ab29tKHYpIHsgcmV0dXJuIGF4Lmwycih2MCArICh2IC0gdjApICogem9vbSk7IH1cbiAgICAgICAgICAgIGF4LnJhbmdlID0gYXhSYW5nZS5tYXAoZG9ab29tKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGVkaXRYKSB7XG4gICAgICAgICAgICAvLyBpZiB3ZSdyZSBvbmx5IHpvb21pbmcgdGhpcyBheGlzIGJlY2F1c2Ugb2YgY29uc3RyYWludHMsXG4gICAgICAgICAgICAvLyB6b29tIGl0IGFib3V0IHRoZSBjZW50ZXJcbiAgICAgICAgICAgIGlmKCFldykgeGZyYWMgPSAwLjU7XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHhheGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgem9vbVdoZWVsT25lQXhpcyh4YXhlc1tpXSwgeGZyYWMsIHpvb20pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdXBkYXRlTWF0Y2hlZEF4UmFuZ2UoJ3gnKTtcblxuICAgICAgICAgICAgc2Nyb2xsVmlld0JveFsyXSAqPSB6b29tO1xuICAgICAgICAgICAgc2Nyb2xsVmlld0JveFswXSArPSBzY3JvbGxWaWV3Qm94WzJdICogeGZyYWMgKiAoMSAvIHpvb20gLSAxKTtcbiAgICAgICAgfVxuICAgICAgICBpZihlZGl0WSkge1xuICAgICAgICAgICAgaWYoIW5zKSB5ZnJhYyA9IDAuNTtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgeWF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB6b29tV2hlZWxPbmVBeGlzKHlheGVzW2ldLCB5ZnJhYywgem9vbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB1cGRhdGVNYXRjaGVkQXhSYW5nZSgneScpO1xuXG4gICAgICAgICAgICBzY3JvbGxWaWV3Qm94WzNdICo9IHpvb207XG4gICAgICAgICAgICBzY3JvbGxWaWV3Qm94WzFdICs9IHNjcm9sbFZpZXdCb3hbM10gKiAoMSAtIHlmcmFjKSAqICgxIC8gem9vbSAtIDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdmlld2JveCByZWRyYXcgYXQgZmlyc3RcbiAgICAgICAgdXBkYXRlU3VicGxvdHMoc2Nyb2xsVmlld0JveCk7XG4gICAgICAgIHRpY2tzQW5kQW5ub3RhdGlvbnMoKTtcblxuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVsYXlvdXRpbmcnLCB1cGRhdGVzKTtcblxuICAgICAgICAvLyB0aGVuIHJlcGxvdCBhZnRlciBhIGRlbGF5IHRvIG1ha2Ugc3VyZVxuICAgICAgICAvLyBubyBtb3JlIHNjcm9sbGluZyBpcyBjb21pbmdcbiAgICAgICAgcmVkcmF3VGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgc2Nyb2xsVmlld0JveCA9IFswLCAwLCBwdywgcGhdO1xuICAgICAgICAgICAgZHJhZ1RhaWwoKTtcbiAgICAgICAgfSwgUkVEUkFXREVMQVkpO1xuXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGV2ZXJ5dGhpbmcgYnV0IHRoZSBjb3JuZXJzIGdldHMgd2hlZWwgem9vbVxuICAgIGlmKG5zLmxlbmd0aCAqIGV3Lmxlbmd0aCAhPT0gMSkge1xuICAgICAgICBhdHRhY2hXaGVlbEV2ZW50SGFuZGxlcihkcmFnZ2VyLCB6b29tV2hlZWwpO1xuICAgIH1cblxuICAgIC8vIHBsb3REcmFnOiBtb3ZlIHRoZSBwbG90IGluIHJlc3BvbnNlIHRvIGEgZHJhZ1xuICAgIGZ1bmN0aW9uIHBsb3REcmFnKGR4LCBkeSkge1xuICAgICAgICAvLyBJZiBhIHRyYW5zaXRpb24gaXMgaW4gcHJvZ3Jlc3MsIHRoZW4gZGlzYWJsZSBhbnkgYmVoYXZpb3I6XG4gICAgICAgIGlmKGdkLl90cmFuc2l0aW9uaW5nV2l0aER1cmF0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwcmV2ZW50IGF4aXMgZHJhd2luZyBmcm9tIG1vbmtleWluZyB3aXRoIG1hcmdpbnMgdW50aWwgd2UncmUgZG9uZVxuICAgICAgICBnZC5fZnVsbExheW91dC5fcmVwbG90dGluZyA9IHRydWU7XG5cbiAgICAgICAgaWYoeEFjdGl2ZSA9PT0gJ2V3JyB8fCB5QWN0aXZlID09PSAnbnMnKSB7XG4gICAgICAgICAgICBpZih4QWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgZHJhZ0F4TGlzdCh4YXhlcywgZHgpO1xuICAgICAgICAgICAgICAgIHVwZGF0ZU1hdGNoZWRBeFJhbmdlKCd4Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih5QWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgZHJhZ0F4TGlzdCh5YXhlcywgZHkpO1xuICAgICAgICAgICAgICAgIHVwZGF0ZU1hdGNoZWRBeFJhbmdlKCd5Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB1cGRhdGVTdWJwbG90cyhbeEFjdGl2ZSA/IC1keCA6IDAsIHlBY3RpdmUgPyAtZHkgOiAwLCBwdywgcGhdKTtcbiAgICAgICAgICAgIHRpY2tzQW5kQW5ub3RhdGlvbnMoKTtcbiAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9yZWxheW91dGluZycsIHVwZGF0ZXMpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZHo6IHNldCBhIG5ldyB2YWx1ZSBmb3Igb25lIGVuZCAoMCBvciAxKSBvZiBhbiBheGlzIGFycmF5IGF4QXJyYXksXG4gICAgICAgIC8vIGFuZCByZXR1cm4gYSBwaXhlbCBzaGlmdCBmb3IgdGhhdCBlbmQgZm9yIHRoZSB2aWV3Ym94XG4gICAgICAgIC8vIGJhc2VkIG9uIHBpeGVsIGRyYWcgZGlzdGFuY2UgZFxuICAgICAgICAvLyBUT0RPOiB0aGlzIG1ha2VzIChnZW5lcmFsbHkgbm9uLWZhdGFsKSBlcnJvcnMgd2hlbiB5b3UgZ2V0XG4gICAgICAgIC8vIG5lYXIgZmxvYXRpbmcgcG9pbnQgbGltaXRzXG4gICAgICAgIGZ1bmN0aW9uIGR6KGF4QXJyYXksIGVuZCwgZCkge1xuICAgICAgICAgICAgdmFyIG90aGVyRW5kID0gMSAtIGVuZDtcbiAgICAgICAgICAgIHZhciBtb3ZlZEF4O1xuICAgICAgICAgICAgdmFyIG5ld0xpbmVhcml6ZWRFbmQ7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXhBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBheGkgPSBheEFycmF5W2ldO1xuICAgICAgICAgICAgICAgIGlmKGF4aS5maXhlZHJhbmdlKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBtb3ZlZEF4ID0gYXhpO1xuICAgICAgICAgICAgICAgIG5ld0xpbmVhcml6ZWRFbmQgPSBheGkuX3JsW290aGVyRW5kXSArXG4gICAgICAgICAgICAgICAgICAgIChheGkuX3JsW2VuZF0gLSBheGkuX3JsW290aGVyRW5kXSkgLyBkWm9vbShkIC8gYXhpLl9sZW5ndGgpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdFbmQgPSBheGkubDJyKG5ld0xpbmVhcml6ZWRFbmQpO1xuXG4gICAgICAgICAgICAgICAgLy8gaWYgbDJyIGNvbWVzIGJhY2sgZmFsc2Ugb3IgdW5kZWZpbmVkLCBpdCBtZWFucyB3ZSd2ZSBkcmFnZ2VkIG9mZlxuICAgICAgICAgICAgICAgIC8vIHRoZSBlbmQgb2YgdmFsaWQgcmFuZ2VzIC0gc28gc3RvcC5cbiAgICAgICAgICAgICAgICBpZihuZXdFbmQgIT09IGZhbHNlICYmIG5ld0VuZCAhPT0gdW5kZWZpbmVkKSBheGkucmFuZ2VbZW5kXSA9IG5ld0VuZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtb3ZlZEF4Ll9sZW5ndGggKiAobW92ZWRBeC5fcmxbZW5kXSAtIG5ld0xpbmVhcml6ZWRFbmQpIC9cbiAgICAgICAgICAgICAgICAobW92ZWRBeC5fcmxbZW5kXSAtIG1vdmVkQXguX3JsW290aGVyRW5kXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihsaW5rcy5pc1N1YnBsb3RDb25zdHJhaW5lZCAmJiB4QWN0aXZlICYmIHlBY3RpdmUpIHtcbiAgICAgICAgICAgIC8vIGRyYWdnaW5nIGEgY29ybmVyIG9mIGEgY29uc3RyYWluZWQgc3VicGxvdDpcbiAgICAgICAgICAgIC8vIHJlc3BlY3QgdGhlIGZpeGVkIGNvcm5lciwgYnV0IGhhcm1vbml6ZSBkeCBhbmQgZHlcbiAgICAgICAgICAgIHZhciBkeHlTaWduID0gKCh4QWN0aXZlID09PSAndycpID09PSAoeUFjdGl2ZSA9PT0gJ24nKSkgPyAxIDogLTE7XG4gICAgICAgICAgICB2YXIgZHh5RnJhY3Rpb24gPSAoZHggLyBwdyArIGR4eVNpZ24gKiBkeSAvIHBoKSAvIDI7XG4gICAgICAgICAgICBkeCA9IGR4eUZyYWN0aW9uICogcHc7XG4gICAgICAgICAgICBkeSA9IGR4eVNpZ24gKiBkeHlGcmFjdGlvbiAqIHBoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoeEFjdGl2ZSA9PT0gJ3cnKSBkeCA9IGR6KHhheGVzLCAwLCBkeCk7XG4gICAgICAgIGVsc2UgaWYoeEFjdGl2ZSA9PT0gJ2UnKSBkeCA9IGR6KHhheGVzLCAxLCAtZHgpO1xuICAgICAgICBlbHNlIGlmKCF4QWN0aXZlKSBkeCA9IDA7XG5cbiAgICAgICAgaWYoeUFjdGl2ZSA9PT0gJ24nKSBkeSA9IGR6KHlheGVzLCAxLCBkeSk7XG4gICAgICAgIGVsc2UgaWYoeUFjdGl2ZSA9PT0gJ3MnKSBkeSA9IGR6KHlheGVzLCAwLCAtZHkpO1xuICAgICAgICBlbHNlIGlmKCF5QWN0aXZlKSBkeSA9IDA7XG5cbiAgICAgICAgdmFyIHhTdGFydCA9ICh4QWN0aXZlID09PSAndycpID8gZHggOiAwO1xuICAgICAgICB2YXIgeVN0YXJ0ID0gKHlBY3RpdmUgPT09ICduJykgPyBkeSA6IDA7XG5cbiAgICAgICAgaWYobGlua3MuaXNTdWJwbG90Q29uc3RyYWluZWQpIHtcbiAgICAgICAgICAgIHZhciBpO1xuICAgICAgICAgICAgaWYoIXhBY3RpdmUgJiYgeUFjdGl2ZS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBkcmFnZ2luZyBvbmUgZW5kIG9mIHRoZSB5IGF4aXMgb2YgYSBjb25zdHJhaW5lZCBzdWJwbG90XG4gICAgICAgICAgICAgICAgLy8gc2NhbGUgdGhlIG90aGVyIGF4aXMgdGhlIHNhbWUgYWJvdXQgaXRzIG1pZGRsZVxuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHhheGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHhheGVzW2ldLnJhbmdlID0geGF4ZXNbaV0uX3Iuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICAgICAgc2NhbGVab29tKHhheGVzW2ldLCAxIC0gZHkgLyBwaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGR4ID0gZHkgKiBwdyAvIHBoO1xuICAgICAgICAgICAgICAgIHhTdGFydCA9IGR4IC8gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKCF5QWN0aXZlICYmIHhBY3RpdmUubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgeWF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgeWF4ZXNbaV0ucmFuZ2UgPSB5YXhlc1tpXS5fci5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICBzY2FsZVpvb20oeWF4ZXNbaV0sIDEgLSBkeCAvIHB3KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZHkgPSBkeCAqIHBoIC8gcHc7XG4gICAgICAgICAgICAgICAgeVN0YXJ0ID0gZHkgLyAyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdXBkYXRlTWF0Y2hlZEF4UmFuZ2UoJ3gnKTtcbiAgICAgICAgdXBkYXRlTWF0Y2hlZEF4UmFuZ2UoJ3knKTtcbiAgICAgICAgdXBkYXRlU3VicGxvdHMoW3hTdGFydCwgeVN0YXJ0LCBwdyAtIGR4LCBwaCAtIGR5XSk7XG4gICAgICAgIHRpY2tzQW5kQW5ub3RhdGlvbnMoKTtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3JlbGF5b3V0aW5nJywgdXBkYXRlcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlTWF0Y2hlZEF4UmFuZ2UoYXhMZXR0ZXIsIG91dCkge1xuICAgICAgICB2YXIgbWF0Y2hlZEF4ZXMgPSBtYXRjaGVzLmlzU3VicGxvdENvbnN0cmFpbmVkID9cbiAgICAgICAgICAgIHt4OiB5YXhlcywgeTogeGF4ZXN9W2F4TGV0dGVyXSA6XG4gICAgICAgICAgICBtYXRjaGVzW2F4TGV0dGVyICsgJ2F4ZXMnXTtcblxuICAgICAgICB2YXIgY29uc3RyYWluZWRBeGVzID0gbWF0Y2hlcy5pc1N1YnBsb3RDb25zdHJhaW5lZCA/XG4gICAgICAgICAgICB7eDogeGF4ZXMsIHk6IHlheGVzfVtheExldHRlcl0gOlxuICAgICAgICAgICAgW107XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG1hdGNoZWRBeGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgYXggPSBtYXRjaGVkQXhlc1tpXTtcbiAgICAgICAgICAgIHZhciBheElkID0gYXguX2lkO1xuICAgICAgICAgICAgdmFyIGF4SWQyID0gbWF0Y2hlcy54TGlua3NbYXhJZF0gfHwgbWF0Y2hlcy55TGlua3NbYXhJZF07XG4gICAgICAgICAgICB2YXIgYXgyID0gY29uc3RyYWluZWRBeGVzWzBdIHx8IHhhSGFzaFtheElkMl0gfHwgeWFIYXNoW2F4SWQyXTtcblxuICAgICAgICAgICAgaWYoYXgyKSB7XG4gICAgICAgICAgICAgICAgaWYob3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHpvb21ib3ggY2FzZSAtIGRvbid0IG11dGF0ZSAncmFuZ2UnLCBqdXN0IGFkZCBrZXlzIGluICd1cGRhdGVzJ1xuICAgICAgICAgICAgICAgICAgICBvdXRbYXguX25hbWUgKyAnLnJhbmdlWzBdJ10gPSBvdXRbYXgyLl9uYW1lICsgJy5yYW5nZVswXSddO1xuICAgICAgICAgICAgICAgICAgICBvdXRbYXguX25hbWUgKyAnLnJhbmdlWzFdJ10gPSBvdXRbYXgyLl9uYW1lICsgJy5yYW5nZVsxXSddO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGF4LnJhbmdlID0gYXgyLnJhbmdlLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gRHJhdyB0aWNrcyBhbmQgYW5ub3RhdGlvbnMgKGFuZCBvdGhlciBjb21wb25lbnRzKSB3aGVuIHJhbmdlcyBjaGFuZ2UuXG4gICAgLy8gQWxzbyByZWNvcmRzIHRoZSByYW5nZXMgdGhhdCBoYXZlIGNoYW5nZWQgZm9yIHVzZSBieSB1cGRhdGUgYXQgdGhlIGVuZC5cbiAgICBmdW5jdGlvbiB0aWNrc0FuZEFubm90YXRpb25zKCkge1xuICAgICAgICB2YXIgYWN0aXZlQXhJZHMgPSBbXTtcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgZnVuY3Rpb24gcHVzaEFjdGl2ZUF4SWRzKGF4TGlzdCkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYoIWF4TGlzdFtpXS5maXhlZHJhbmdlKSBhY3RpdmVBeElkcy5wdXNoKGF4TGlzdFtpXS5faWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoZWRpdFgpIHtcbiAgICAgICAgICAgIHB1c2hBY3RpdmVBeElkcyh4YXhlcyk7XG4gICAgICAgICAgICBwdXNoQWN0aXZlQXhJZHMobGlua3MueGF4ZXMpO1xuICAgICAgICAgICAgcHVzaEFjdGl2ZUF4SWRzKG1hdGNoZXMueGF4ZXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmKGVkaXRZKSB7XG4gICAgICAgICAgICBwdXNoQWN0aXZlQXhJZHMoeWF4ZXMpO1xuICAgICAgICAgICAgcHVzaEFjdGl2ZUF4SWRzKGxpbmtzLnlheGVzKTtcbiAgICAgICAgICAgIHB1c2hBY3RpdmVBeElkcyhtYXRjaGVzLnlheGVzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHVwZGF0ZXMgPSB7fTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYWN0aXZlQXhJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBheElkID0gYWN0aXZlQXhJZHNbaV07XG4gICAgICAgICAgICB2YXIgYXggPSBnZXRGcm9tSWQoZ2QsIGF4SWQpO1xuICAgICAgICAgICAgQXhlcy5kcmF3T25lKGdkLCBheCwge3NraXBUaXRsZTogdHJ1ZX0pO1xuICAgICAgICAgICAgdXBkYXRlc1theC5fbmFtZSArICcucmFuZ2VbMF0nXSA9IGF4LnJhbmdlWzBdO1xuICAgICAgICAgICAgdXBkYXRlc1theC5fbmFtZSArICcucmFuZ2VbMV0nXSA9IGF4LnJhbmdlWzFdO1xuICAgICAgICB9XG5cbiAgICAgICAgQXhlcy5yZWRyYXdDb21wb25lbnRzKGdkLCBhY3RpdmVBeElkcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZG91YmxlQ2xpY2soKSB7XG4gICAgICAgIGlmKGdkLl90cmFuc2l0aW9uaW5nV2l0aER1cmF0aW9uKSByZXR1cm47XG5cbiAgICAgICAgdmFyIGRvdWJsZUNsaWNrQ29uZmlnID0gZ2QuX2NvbnRleHQuZG91YmxlQ2xpY2s7XG5cbiAgICAgICAgdmFyIGF4TGlzdCA9IFtdO1xuICAgICAgICBpZih4QWN0aXZlKSBheExpc3QgPSBheExpc3QuY29uY2F0KHhheGVzKTtcbiAgICAgICAgaWYoeUFjdGl2ZSkgYXhMaXN0ID0gYXhMaXN0LmNvbmNhdCh5YXhlcyk7XG4gICAgICAgIGlmKG1hdGNoZXMueGF4ZXMpIGF4TGlzdCA9IGF4TGlzdC5jb25jYXQobWF0Y2hlcy54YXhlcyk7XG4gICAgICAgIGlmKG1hdGNoZXMueWF4ZXMpIGF4TGlzdCA9IGF4TGlzdC5jb25jYXQobWF0Y2hlcy55YXhlcyk7XG5cbiAgICAgICAgdmFyIGF0dHJzID0ge307XG4gICAgICAgIHZhciBheCwgaSwgcmFuZ2VJbml0aWFsO1xuXG4gICAgICAgIC8vIEZvciByZXNldCthdXRvc2l6ZSBtb2RlOlxuICAgICAgICAvLyBJZiAqYW55KiBvZiB0aGUgbWFpbiBheGVzIGlzIG5vdCBhdCBpdHMgaW5pdGlhbCByYW5nZVxuICAgICAgICAvLyAob3IgYXV0b3JhbmdlZCwgaWYgd2UgaGF2ZSBubyBpbml0aWFsIHJhbmdlLCB0byBtYXRjaCB0aGUgbG9naWMgaW5cbiAgICAgICAgLy8gZG91YmxlQ2xpY2tDb25maWcgPT09ICdyZXNldCcgYmVsb3cpLCB3ZSByZXNldC5cbiAgICAgICAgLy8gSWYgdGhleSBhcmUgKmFsbCogYXQgdGhlaXIgaW5pdGlhbCByYW5nZXMsIHRoZW4gd2UgYXV0b3NpemUuXG4gICAgICAgIGlmKGRvdWJsZUNsaWNrQ29uZmlnID09PSAncmVzZXQrYXV0b3NpemUnKSB7XG4gICAgICAgICAgICBkb3VibGVDbGlja0NvbmZpZyA9ICdhdXRvc2l6ZSc7XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGF4ID0gYXhMaXN0W2ldO1xuICAgICAgICAgICAgICAgIGlmKChheC5fcmFuZ2VJbml0aWFsICYmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIGF4LnJhbmdlWzBdICE9PSBheC5fcmFuZ2VJbml0aWFsWzBdIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBheC5yYW5nZVsxXSAhPT0gYXguX3JhbmdlSW5pdGlhbFsxXVxuICAgICAgICAgICAgICAgICAgICApKSB8fFxuICAgICAgICAgICAgICAgICAgICAoIWF4Ll9yYW5nZUluaXRpYWwgJiYgIWF4LmF1dG9yYW5nZSlcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgZG91YmxlQ2xpY2tDb25maWcgPSAncmVzZXQnO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihkb3VibGVDbGlja0NvbmZpZyA9PT0gJ2F1dG9zaXplJykge1xuICAgICAgICAgICAgLy8gZG9uJ3Qgc2V0IHRoZSBsaW5rZWQgYXhlcyBoZXJlLCBzbyByZWxheW91dCBtYXJrcyB0aGVtIGFzIHNocmlua2FibGVcbiAgICAgICAgICAgIC8vIGFuZCB3ZSBhdXRvc2l6ZSBqdXN0IHRvIHRoZSByZXF1ZXN0ZWQgYXhpcy9heGVzXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBheCA9IGF4TGlzdFtpXTtcbiAgICAgICAgICAgICAgICBpZighYXguZml4ZWRyYW5nZSkgYXR0cnNbYXguX25hbWUgKyAnLmF1dG9yYW5nZSddID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKGRvdWJsZUNsaWNrQ29uZmlnID09PSAncmVzZXQnKSB7XG4gICAgICAgICAgICAvLyB3aGVuIHdlJ3JlIHJlc2V0dGluZywgcmVzZXQgYWxsIGxpbmtlZCBheGVzIHRvbywgc28gd2UgZ2V0IGJhY2tcbiAgICAgICAgICAgIC8vIHRvIHRoZSBmdWxseS1hdXRvLXdpdGgtY29uc3RyYWludHMgc2l0dWF0aW9uXG4gICAgICAgICAgICBpZih4QWN0aXZlIHx8IGxpbmtzLmlzU3VicGxvdENvbnN0cmFpbmVkKSBheExpc3QgPSBheExpc3QuY29uY2F0KGxpbmtzLnhheGVzKTtcbiAgICAgICAgICAgIGlmKHlBY3RpdmUgJiYgIWxpbmtzLmlzU3VicGxvdENvbnN0cmFpbmVkKSBheExpc3QgPSBheExpc3QuY29uY2F0KGxpbmtzLnlheGVzKTtcblxuICAgICAgICAgICAgaWYobGlua3MuaXNTdWJwbG90Q29uc3RyYWluZWQpIHtcbiAgICAgICAgICAgICAgICBpZigheEFjdGl2ZSkgYXhMaXN0ID0gYXhMaXN0LmNvbmNhdCh4YXhlcyk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZigheUFjdGl2ZSkgYXhMaXN0ID0gYXhMaXN0LmNvbmNhdCh5YXhlcyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGF4ID0gYXhMaXN0W2ldO1xuXG4gICAgICAgICAgICAgICAgaWYoIWF4LmZpeGVkcmFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoIWF4Ll9yYW5nZUluaXRpYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHJzW2F4Ll9uYW1lICsgJy5hdXRvcmFuZ2UnXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByYW5nZUluaXRpYWwgPSBheC5fcmFuZ2VJbml0aWFsO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXR0cnNbYXguX25hbWUgKyAnLnJhbmdlWzBdJ10gPSByYW5nZUluaXRpYWxbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyc1theC5fbmFtZSArICcucmFuZ2VbMV0nXSA9IHJhbmdlSW5pdGlhbFsxXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9kb3VibGVjbGljaycsIG51bGwpO1xuICAgICAgICBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVsYXlvdXQnLCBnZCwgYXR0cnMpO1xuICAgIH1cblxuICAgIC8vIGRyYWdUYWlsIC0gZmluaXNoIGEgZHJhZyBldmVudCB3aXRoIGEgcmVkcmF3XG4gICAgZnVuY3Rpb24gZHJhZ1RhaWwoKSB7XG4gICAgICAgIC8vIHB1dCB0aGUgc3VicGxvdCB2aWV3Ym94ZXMgYmFjayB0byBkZWZhdWx0IChCZWNhdXNlIHdlJ3JlIGdvaW5nIHRvKVxuICAgICAgICAvLyBiZSByZXBvc2l0aW9uaW5nIHRoZSBkYXRhIGluIHRoZSByZWxheW91dC4gQnV0IERPTidUIGNhbGxcbiAgICAgICAgLy8gdGlja3NBbmRBbm5vdGF0aW9ucyBhZ2FpbiAtIGl0J3MgdW5uZWNlc3NhcnkgYW5kIHdvdWxkIG92ZXJ3cml0ZSBgdXBkYXRlc2BcbiAgICAgICAgdXBkYXRlU3VicGxvdHMoWzAsIDAsIHB3LCBwaF0pO1xuXG4gICAgICAgIC8vIHNpbmNlIHdlIG1heSBoYXZlIGJlZW4gcmVkcmF3aW5nIHNvbWUgdGhpbmdzIGR1cmluZyB0aGUgZHJhZywgd2UgbWF5IGhhdmVcbiAgICAgICAgLy8gYWNjdW11bGF0ZWQgTWF0aEpheCBwcm9taXNlcyAtIHdhaXQgZm9yIHRoZW0gYmVmb3JlIHdlIHJlbGF5b3V0LlxuICAgICAgICBMaWIuc3luY09yQXN5bmMoW1xuICAgICAgICAgICAgUGxvdHMucHJldmlvdXNQcm9taXNlcyxcbiAgICAgICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGdkLl9mdWxsTGF5b3V0Ll9yZXBsb3R0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIHVwZGF0ZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICBdLCBnZCk7XG4gICAgfVxuXG4gICAgLy8gdXBkYXRlU3VicGxvdHMgLSBmaW5kIGFsbCBwbG90IHZpZXdib3hlcyB0aGF0IHNob3VsZCBiZVxuICAgIC8vIGFmZmVjdGVkIGJ5IHRoaXMgZHJhZywgYW5kIHVwZGF0ZSB0aGVtLiBsb29rIGZvciBhbGwgcGxvdHNcbiAgICAvLyBzaGFyaW5nIGFuIGFmZmVjdGVkIGF4aXMgKGluY2x1ZGluZyB0aGUgb25lIGJlaW5nIGRyYWdnZWQpLFxuICAgIC8vIGluY2x1ZGVzIGFsc28gc2NhdHRlcmdsIGFuZCBzcGxvbSBsb2dpYy5cbiAgICBmdW5jdGlvbiB1cGRhdGVTdWJwbG90cyh2aWV3Qm94KSB7XG4gICAgICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgIHZhciBwbG90aW5mb3MgPSBmdWxsTGF5b3V0Ll9wbG90cztcbiAgICAgICAgdmFyIHN1YnBsb3RzID0gZnVsbExheW91dC5fc3VicGxvdHMuY2FydGVzaWFuO1xuICAgICAgICB2YXIgaSwgc3AsIHhhLCB5YTtcblxuICAgICAgICBpZihoYXNTcGxvbSkge1xuICAgICAgICAgICAgUmVnaXN0cnkuc3VicGxvdHNSZWdpc3RyeS5zcGxvbS5kcmFnKGdkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGhhc1NjYXR0ZXJHbCkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc3VicGxvdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzcCA9IHBsb3RpbmZvc1tzdWJwbG90c1tpXV07XG4gICAgICAgICAgICAgICAgeGEgPSBzcC54YXhpcztcbiAgICAgICAgICAgICAgICB5YSA9IHNwLnlheGlzO1xuXG4gICAgICAgICAgICAgICAgaWYoc3AuX3NjZW5lKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB4cm5nID0gTGliLnNpbXBsZU1hcCh4YS5yYW5nZSwgeGEucjJsKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHlybmcgPSBMaWIuc2ltcGxlTWFwKHlhLnJhbmdlLCB5YS5yMmwpO1xuICAgICAgICAgICAgICAgICAgICBzcC5fc2NlbmUudXBkYXRlKHtyYW5nZTogW3hybmdbMF0sIHlybmdbMF0sIHhybmdbMV0sIHlybmdbMV1dfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoaGFzU3Bsb20gfHwgaGFzU2NhdHRlckdsKSB7XG4gICAgICAgICAgICBjbGVhckdsQ2FudmFzZXMoZ2QpO1xuICAgICAgICAgICAgcmVkcmF3UmVnbFRyYWNlcyhnZCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihoYXNTVkcpIHtcbiAgICAgICAgICAgIHZhciB4U2NhbGVGYWN0b3IgPSB2aWV3Qm94WzJdIC8geGEwLl9sZW5ndGg7XG4gICAgICAgICAgICB2YXIgeVNjYWxlRmFjdG9yID0gdmlld0JveFszXSAvIHlhMC5fbGVuZ3RoO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBzdWJwbG90cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHNwID0gcGxvdGluZm9zW3N1YnBsb3RzW2ldXTtcbiAgICAgICAgICAgICAgICB4YSA9IHNwLnhheGlzO1xuICAgICAgICAgICAgICAgIHlhID0gc3AueWF4aXM7XG5cbiAgICAgICAgICAgICAgICB2YXIgZWRpdFgyID0gZWRpdFggJiYgIXhhLmZpeGVkcmFuZ2UgJiYgeGFIYXNoW3hhLl9pZF07XG4gICAgICAgICAgICAgICAgdmFyIGVkaXRZMiA9IGVkaXRZICYmICF5YS5maXhlZHJhbmdlICYmIHlhSGFzaFt5YS5faWRdO1xuXG4gICAgICAgICAgICAgICAgdmFyIHhTY2FsZUZhY3RvcjIsIHlTY2FsZUZhY3RvcjI7XG4gICAgICAgICAgICAgICAgdmFyIGNsaXBEeCwgY2xpcER5O1xuXG4gICAgICAgICAgICAgICAgaWYoZWRpdFgyKSB7XG4gICAgICAgICAgICAgICAgICAgIHhTY2FsZUZhY3RvcjIgPSB4U2NhbGVGYWN0b3I7XG4gICAgICAgICAgICAgICAgICAgIGNsaXBEeCA9IGV3ID8gdmlld0JveFswXSA6IGdldFNoaWZ0KHhhLCB4U2NhbGVGYWN0b3IyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYobWF0Y2hlcy54YUhhc2hbeGEuX2lkXSkge1xuICAgICAgICAgICAgICAgICAgICB4U2NhbGVGYWN0b3IyID0geFNjYWxlRmFjdG9yO1xuICAgICAgICAgICAgICAgICAgICBjbGlwRHggPSB2aWV3Qm94WzBdICogeGEuX2xlbmd0aCAvIHhhMC5fbGVuZ3RoO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihtYXRjaGVzLnlhSGFzaFt4YS5faWRdKSB7XG4gICAgICAgICAgICAgICAgICAgIHhTY2FsZUZhY3RvcjIgPSB5U2NhbGVGYWN0b3I7XG4gICAgICAgICAgICAgICAgICAgIGNsaXBEeCA9IHlBY3RpdmUgPT09ICducycgP1xuICAgICAgICAgICAgICAgICAgICAgICAgLXZpZXdCb3hbMV0gKiB4YS5fbGVuZ3RoIC8geWEwLl9sZW5ndGggOlxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0U2hpZnQoeGEsIHhTY2FsZUZhY3RvcjIsIHtuOiAndG9wJywgczogJ2JvdHRvbSd9W3lBY3RpdmVdKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB4U2NhbGVGYWN0b3IyID0gZ2V0TGlua2VkU2NhbGVGYWN0b3IoeGEsIHhTY2FsZUZhY3RvciwgeVNjYWxlRmFjdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgY2xpcER4ID0gc2NhbGVBbmRHZXRTaGlmdCh4YSwgeFNjYWxlRmFjdG9yMik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoZWRpdFkyKSB7XG4gICAgICAgICAgICAgICAgICAgIHlTY2FsZUZhY3RvcjIgPSB5U2NhbGVGYWN0b3I7XG4gICAgICAgICAgICAgICAgICAgIGNsaXBEeSA9IG5zID8gdmlld0JveFsxXSA6IGdldFNoaWZ0KHlhLCB5U2NhbGVGYWN0b3IyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYobWF0Y2hlcy55YUhhc2hbeWEuX2lkXSkge1xuICAgICAgICAgICAgICAgICAgICB5U2NhbGVGYWN0b3IyID0geVNjYWxlRmFjdG9yO1xuICAgICAgICAgICAgICAgICAgICBjbGlwRHkgPSB2aWV3Qm94WzFdICogeWEuX2xlbmd0aCAvIHlhMC5fbGVuZ3RoO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihtYXRjaGVzLnhhSGFzaFt5YS5faWRdKSB7XG4gICAgICAgICAgICAgICAgICAgIHlTY2FsZUZhY3RvcjIgPSB4U2NhbGVGYWN0b3I7XG4gICAgICAgICAgICAgICAgICAgIGNsaXBEeSA9IHhBY3RpdmUgPT09ICdldycgP1xuICAgICAgICAgICAgICAgICAgICAgICAgLXZpZXdCb3hbMF0gKiB5YS5fbGVuZ3RoIC8geGEwLl9sZW5ndGggOlxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0U2hpZnQoeWEsIHlTY2FsZUZhY3RvcjIsIHtlOiAncmlnaHQnLCB3OiAnbGVmdCd9W3hBY3RpdmVdKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB5U2NhbGVGYWN0b3IyID0gZ2V0TGlua2VkU2NhbGVGYWN0b3IoeWEsIHhTY2FsZUZhY3RvciwgeVNjYWxlRmFjdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgY2xpcER5ID0gc2NhbGVBbmRHZXRTaGlmdCh5YSwgeVNjYWxlRmFjdG9yMik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZG9uJ3Qgc2NhbGUgYXQgYWxsIGlmIG5laXRoZXIgYXhpcyBpcyBzY2FsYWJsZSBoZXJlXG4gICAgICAgICAgICAgICAgaWYoIXhTY2FsZUZhY3RvcjIgJiYgIXlTY2FsZUZhY3RvcjIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gYnV0IGlmIG9ubHkgb25lIGlzLCByZXNldCB0aGUgb3RoZXIgYXhpcyBzY2FsaW5nXG4gICAgICAgICAgICAgICAgaWYoIXhTY2FsZUZhY3RvcjIpIHhTY2FsZUZhY3RvcjIgPSAxO1xuICAgICAgICAgICAgICAgIGlmKCF5U2NhbGVGYWN0b3IyKSB5U2NhbGVGYWN0b3IyID0gMTtcblxuICAgICAgICAgICAgICAgIHZhciBwbG90RHggPSB4YS5fb2Zmc2V0IC0gY2xpcER4IC8geFNjYWxlRmFjdG9yMjtcbiAgICAgICAgICAgICAgICB2YXIgcGxvdER5ID0geWEuX29mZnNldCAtIGNsaXBEeSAvIHlTY2FsZUZhY3RvcjI7XG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPIGNvdWxkIGJlIG1vcmUgZWZmaWNpZW50IGhlcmU6XG4gICAgICAgICAgICAgICAgLy8gc2V0VHJhbnNsYXRlIGFuZCBzZXRTY2FsZSBkbyBhIGxvdCBvZiBleHRyYSB3b3JrXG4gICAgICAgICAgICAgICAgLy8gd2hlbiB3b3JraW5nIGluZGVwZW5kZW50bHksIHNob3VsZCBwZXJoYXBzIGNvbWJpbmVcbiAgICAgICAgICAgICAgICAvLyB0aGVtIGludG8gYSBzaW5nbGUgcm91dGluZS5cbiAgICAgICAgICAgICAgICBzcC5jbGlwUmVjdFxuICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSwgY2xpcER4LCBjbGlwRHkpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0U2NhbGUsIHhTY2FsZUZhY3RvcjIsIHlTY2FsZUZhY3RvcjIpO1xuXG4gICAgICAgICAgICAgICAgc3AucGxvdFxuICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSwgcGxvdER4LCBwbG90RHkpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0U2NhbGUsIDEgLyB4U2NhbGVGYWN0b3IyLCAxIC8geVNjYWxlRmFjdG9yMik7XG5cbiAgICAgICAgICAgICAgICAvLyBhcHBseSBhbiBpbnZlcnNlIHNjYWxlIHRvIGluZGl2aWR1YWwgcG9pbnRzIHRvIGNvdW50ZXJhY3RcbiAgICAgICAgICAgICAgICAvLyB0aGUgc2NhbGUgb2YgdGhlIHRyYWNlIGdyb3VwLlxuICAgICAgICAgICAgICAgIC8vIGFwcGx5IG9ubHkgd2hlbiBzY2FsZSBjaGFuZ2VzLCBhcyBhZGp1c3RpbmcgdGhlIHNjYWxlIG9mXG4gICAgICAgICAgICAgICAgLy8gYWxsIHRoZSBwb2ludHMgY2FuIGJlIGV4cGFuc2l2ZS5cbiAgICAgICAgICAgICAgICBpZih4U2NhbGVGYWN0b3IyICE9PSBzcC54U2NhbGVGYWN0b3IgfHwgeVNjYWxlRmFjdG9yMiAhPT0gc3AueVNjYWxlRmFjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0UG9pbnRHcm91cFNjYWxlKHNwLnpvb21TY2FsZVB0cywgeFNjYWxlRmFjdG9yMiwgeVNjYWxlRmFjdG9yMik7XG4gICAgICAgICAgICAgICAgICAgIERyYXdpbmcuc2V0VGV4dFBvaW50c1NjYWxlKHNwLnpvb21TY2FsZVR4dCwgeFNjYWxlRmFjdG9yMiwgeVNjYWxlRmFjdG9yMik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgRHJhd2luZy5oaWRlT3V0c2lkZVJhbmdlUG9pbnRzKHNwLmNsaXBPbkF4aXNGYWxzZVRyYWNlcywgc3ApO1xuXG4gICAgICAgICAgICAgICAgLy8gdXBkYXRlIHgveSBzY2FsZUZhY3RvciBzdGFzaFxuICAgICAgICAgICAgICAgIHNwLnhTY2FsZUZhY3RvciA9IHhTY2FsZUZhY3RvcjI7XG4gICAgICAgICAgICAgICAgc3AueVNjYWxlRmFjdG9yID0geVNjYWxlRmFjdG9yMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEZpbmQgdGhlIGFwcHJvcHJpYXRlIHNjYWxpbmcgZm9yIHRoaXMgYXhpcywgaWYgaXQncyBsaW5rZWQgdG8gdGhlXG4gICAgLy8gZHJhZ2dlZCBheGVzIGJ5IGNvbnN0cmFpbnRzLiAwIGlzIHNwZWNpYWwsIGl0IG1lYW5zIHRoaXMgYXhpcyBzaG91bGRuJ3RcbiAgICAvLyBldmVyIGJlIHNjYWxlZCAod2lsbCBiZSBjb252ZXJ0ZWQgdG8gMSBpZiB0aGUgb3RoZXIgYXhpcyBpcyBzY2FsZWQpXG4gICAgZnVuY3Rpb24gZ2V0TGlua2VkU2NhbGVGYWN0b3IoYXgsIHhTY2FsZUZhY3RvciwgeVNjYWxlRmFjdG9yKSB7XG4gICAgICAgIGlmKGF4LmZpeGVkcmFuZ2UpIHJldHVybiAwO1xuXG4gICAgICAgIGlmKGVkaXRYICYmIGxpbmtzLnhhSGFzaFtheC5faWRdKSB7XG4gICAgICAgICAgICByZXR1cm4geFNjYWxlRmFjdG9yO1xuICAgICAgICB9XG4gICAgICAgIGlmKGVkaXRZICYmIChsaW5rcy5pc1N1YnBsb3RDb25zdHJhaW5lZCA/IGxpbmtzLnhhSGFzaCA6IGxpbmtzLnlhSGFzaClbYXguX2lkXSkge1xuICAgICAgICAgICAgcmV0dXJuIHlTY2FsZUZhY3RvcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzY2FsZUFuZEdldFNoaWZ0KGF4LCBzY2FsZUZhY3Rvcikge1xuICAgICAgICBpZihzY2FsZUZhY3Rvcikge1xuICAgICAgICAgICAgYXgucmFuZ2UgPSBheC5fci5zbGljZSgpO1xuICAgICAgICAgICAgc2NhbGVab29tKGF4LCBzY2FsZUZhY3Rvcik7XG4gICAgICAgICAgICByZXR1cm4gZ2V0U2hpZnQoYXgsIHNjYWxlRmFjdG9yKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTaGlmdChheCwgc2NhbGVGYWN0b3IsIGZyb20pIHtcbiAgICAgICAgcmV0dXJuIGF4Ll9sZW5ndGggKiAoMSAtIHNjYWxlRmFjdG9yKSAqIEZST01fVExbZnJvbSB8fCBheC5jb25zdHJhaW50b3dhcmQgfHwgJ21pZGRsZSddO1xuICAgIH1cblxuICAgIHJldHVybiBkcmFnZ2VyO1xufVxuXG5mdW5jdGlvbiBtYWtlRHJhZ2dlcihwbG90aW5mbywgbm9kZU5hbWUsIGRyYWdDbGFzcywgY3Vyc29yKSB7XG4gICAgdmFyIGRyYWdnZXIzID0gTGliLmVuc3VyZVNpbmdsZShwbG90aW5mby5kcmFnbGF5ZXIsIG5vZGVOYW1lLCBkcmFnQ2xhc3MsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5jbGFzc2VkKCdkcmFnJywgdHJ1ZSlcbiAgICAgICAgICAgIC5zdHlsZSh7ZmlsbDogJ3RyYW5zcGFyZW50JywgJ3N0cm9rZS13aWR0aCc6IDB9KVxuICAgICAgICAgICAgLmF0dHIoJ2RhdGEtc3VicGxvdCcsIHBsb3RpbmZvLmlkKTtcbiAgICB9KTtcblxuICAgIGRyYWdnZXIzLmNhbGwoc2V0Q3Vyc29yLCBjdXJzb3IpO1xuXG4gICAgcmV0dXJuIGRyYWdnZXIzLm5vZGUoKTtcbn1cblxuZnVuY3Rpb24gbWFrZVJlY3REcmFnZ2VyKHBsb3RpbmZvLCBkcmFnQ2xhc3MsIGN1cnNvciwgeCwgeSwgdywgaCkge1xuICAgIHZhciBkcmFnZ2VyID0gbWFrZURyYWdnZXIocGxvdGluZm8sICdyZWN0JywgZHJhZ0NsYXNzLCBjdXJzb3IpO1xuICAgIGQzLnNlbGVjdChkcmFnZ2VyKS5jYWxsKERyYXdpbmcuc2V0UmVjdCwgeCwgeSwgdywgaCk7XG4gICAgcmV0dXJuIGRyYWdnZXI7XG59XG5cbmZ1bmN0aW9uIGlzRGlyZWN0aW9uQWN0aXZlKGF4TGlzdCwgYWN0aXZlVmFsKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZighYXhMaXN0W2ldLmZpeGVkcmFuZ2UpIHJldHVybiBhY3RpdmVWYWw7XG4gICAgfVxuICAgIHJldHVybiAnJztcbn1cblxuZnVuY3Rpb24gZ2V0RW5kVGV4dChheCwgZW5kKSB7XG4gICAgdmFyIGluaXRpYWxWYWwgPSBheC5yYW5nZVtlbmRdO1xuICAgIHZhciBkaWZmID0gTWF0aC5hYnMoaW5pdGlhbFZhbCAtIGF4LnJhbmdlWzEgLSBlbmRdKTtcbiAgICB2YXIgZGlnO1xuXG4gICAgLy8gVE9ETzogdGhpcyBzaG91bGQgYmFzaWNhbGx5IGJlIGF4LnIyZCBidXQgd2UncmUgZG9pbmcgZXh0cmFcbiAgICAvLyByb3VuZGluZyBoZXJlLi4uIGNhbiB3ZSBjbGVhbiB1cCBhdCBhbGw/XG4gICAgaWYoYXgudHlwZSA9PT0gJ2RhdGUnKSB7XG4gICAgICAgIHJldHVybiBpbml0aWFsVmFsO1xuICAgIH0gZWxzZSBpZihheC50eXBlID09PSAnbG9nJykge1xuICAgICAgICBkaWcgPSBNYXRoLmNlaWwoTWF0aC5tYXgoMCwgLU1hdGgubG9nKGRpZmYpIC8gTWF0aC5MTjEwKSkgKyAzO1xuICAgICAgICByZXR1cm4gZDMuZm9ybWF0KCcuJyArIGRpZyArICdnJykoTWF0aC5wb3coMTAsIGluaXRpYWxWYWwpKTtcbiAgICB9IGVsc2UgeyAvLyBsaW5lYXIgbnVtZXJpYyAob3IgY2F0ZWdvcnkuLi4gYnV0IGp1c3Qgc2hvdyBudW1iZXJzIGhlcmUpXG4gICAgICAgIGRpZyA9IE1hdGguZmxvb3IoTWF0aC5sb2coTWF0aC5hYnMoaW5pdGlhbFZhbCkpIC8gTWF0aC5MTjEwKSAtXG4gICAgICAgICAgICBNYXRoLmZsb29yKE1hdGgubG9nKGRpZmYpIC8gTWF0aC5MTjEwKSArIDQ7XG4gICAgICAgIHJldHVybiBkMy5mb3JtYXQoJy4nICsgU3RyaW5nKGRpZykgKyAnZycpKGluaXRpYWxWYWwpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gem9vbUF4UmFuZ2VzKGF4TGlzdCwgcjBGcmFjdGlvbiwgcjFGcmFjdGlvbiwgdXBkYXRlcywgbGlua2VkQXhlcykge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF4aSA9IGF4TGlzdFtpXTtcbiAgICAgICAgaWYoYXhpLmZpeGVkcmFuZ2UpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBheFJhbmdlTGluZWFyMCA9IGF4aS5fcmxbMF07XG4gICAgICAgIHZhciBheFJhbmdlTGluZWFyU3BhbiA9IGF4aS5fcmxbMV0gLSBheFJhbmdlTGluZWFyMDtcbiAgICAgICAgdXBkYXRlc1theGkuX25hbWUgKyAnLnJhbmdlWzBdJ10gPSBheGkubDJyKGF4UmFuZ2VMaW5lYXIwICsgYXhSYW5nZUxpbmVhclNwYW4gKiByMEZyYWN0aW9uKTtcbiAgICAgICAgdXBkYXRlc1theGkuX25hbWUgKyAnLnJhbmdlWzFdJ10gPSBheGkubDJyKGF4UmFuZ2VMaW5lYXIwICsgYXhSYW5nZUxpbmVhclNwYW4gKiByMUZyYWN0aW9uKTtcbiAgICB9XG5cbiAgICAvLyB6b29tIGxpbmtlZCBheGVzIGFib3V0IHRoZWlyIGNlbnRlcnNcbiAgICBpZihsaW5rZWRBeGVzICYmIGxpbmtlZEF4ZXMubGVuZ3RoKSB7XG4gICAgICAgIHZhciBsaW5rZWRSMEZyYWN0aW9uID0gKHIwRnJhY3Rpb24gKyAoMSAtIHIxRnJhY3Rpb24pKSAvIDI7XG4gICAgICAgIHpvb21BeFJhbmdlcyhsaW5rZWRBeGVzLCBsaW5rZWRSMEZyYWN0aW9uLCAxIC0gbGlua2VkUjBGcmFjdGlvbiwgdXBkYXRlcywgW10pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZHJhZ0F4TGlzdChheExpc3QsIHBpeCkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF4aSA9IGF4TGlzdFtpXTtcbiAgICAgICAgaWYoIWF4aS5maXhlZHJhbmdlKSB7XG4gICAgICAgICAgICBheGkucmFuZ2UgPSBbXG4gICAgICAgICAgICAgICAgYXhpLmwycihheGkuX3JsWzBdIC0gcGl4IC8gYXhpLl9tKSxcbiAgICAgICAgICAgICAgICBheGkubDJyKGF4aS5fcmxbMV0gLSBwaXggLyBheGkuX20pXG4gICAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyBjb21tb24gdHJhbnNmb3JtIGZvciBkcmFnZ2luZyBvbmUgZW5kIG9mIGFuIGF4aXNcbi8vIGQ+MCBpcyBjb21wcmVzc2luZyBzY2FsZSAoY3Vyc29yIGlzIG92ZXIgdGhlIHBsb3QsXG4vLyAgdGhlIGF4aXMgZW5kIHNob3VsZCBtb3ZlIHdpdGggdGhlIGN1cnNvcilcbi8vIGQ8MCBpcyBleHBhbmRpbmcgKGN1cnNvciBpcyBvZmYgdGhlIHBsb3QsIGF4aXMgZW5kIG1vdmVzXG4vLyAgbm9ubGluZWFybHkgc28geW91IGNhbiBleHBhbmQgZmFyKVxuZnVuY3Rpb24gZFpvb20oZCkge1xuICAgIHJldHVybiAxIC0gKChkID49IDApID8gTWF0aC5taW4oZCwgMC45KSA6XG4gICAgICAgIDEgLyAoMSAvIE1hdGgubWF4KGQsIC0wLjMpICsgMy4yMjIpKTtcbn1cblxuZnVuY3Rpb24gZ2V0RHJhZ0N1cnNvcihuc2V3LCBkcmFnbW9kZSwgaXNNYWluRHJhZykge1xuICAgIGlmKCFuc2V3KSByZXR1cm4gJ3BvaW50ZXInO1xuICAgIGlmKG5zZXcgPT09ICduc2V3Jykge1xuICAgICAgICAvLyBpbiB0aGlzIGNhc2UgaGVyZSwgY2xlYXIgY3Vyc29yIGFuZFxuICAgICAgICAvLyB1c2UgdGhlIGN1cnNvciBzdHlsZSBzZXQgb24gPGcgLmRyYWdsYXllcj5cbiAgICAgICAgaWYoaXNNYWluRHJhZykgcmV0dXJuICcnO1xuICAgICAgICBpZihkcmFnbW9kZSA9PT0gJ3BhbicpIHJldHVybiAnbW92ZSc7XG4gICAgICAgIHJldHVybiAnY3Jvc3NoYWlyJztcbiAgICB9XG4gICAgcmV0dXJuIG5zZXcudG9Mb3dlckNhc2UoKSArICctcmVzaXplJztcbn1cblxuZnVuY3Rpb24gbWFrZVpvb21ib3goem9vbWxheWVyLCBsdW0sIHhzLCB5cywgcGF0aDApIHtcbiAgICByZXR1cm4gem9vbWxheWVyLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICd6b29tYm94JylcbiAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICdmaWxsJzogbHVtID4gMC4yID8gJ3JnYmEoMCwwLDAsMCknIDogJ3JnYmEoMjU1LDI1NSwyNTUsMCknLFxuICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IDBcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIHhzICsgJywgJyArIHlzICsgJyknKVxuICAgICAgICAuYXR0cignZCcsIHBhdGgwICsgJ1onKTtcbn1cblxuZnVuY3Rpb24gbWFrZUNvcm5lcnMoem9vbWxheWVyLCB4cywgeXMpIHtcbiAgICByZXR1cm4gem9vbWxheWVyLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICd6b29tYm94LWNvcm5lcnMnKVxuICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgZmlsbDogQ29sb3IuYmFja2dyb3VuZCxcbiAgICAgICAgICAgIHN0cm9rZTogQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogMSxcbiAgICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIHhzICsgJywgJyArIHlzICsgJyknKVxuICAgICAgICAuYXR0cignZCcsICdNMCwwWicpO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVab29tYm94KHpiLCBjb3JuZXJzLCBib3gsIHBhdGgwLCBkaW1tZWQsIGx1bSkge1xuICAgIHpiLmF0dHIoJ2QnLFxuICAgICAgICBwYXRoMCArICdNJyArIChib3gubCkgKyAnLCcgKyAoYm94LnQpICsgJ3YnICsgKGJveC5oKSArXG4gICAgICAgICdoJyArIChib3gudykgKyAndi0nICsgKGJveC5oKSArICdoLScgKyAoYm94LncpICsgJ1onKTtcbiAgICB0cmFuc2l0aW9uWm9vbWJveCh6YiwgY29ybmVycywgZGltbWVkLCBsdW0pO1xufVxuXG5mdW5jdGlvbiB0cmFuc2l0aW9uWm9vbWJveCh6YiwgY29ybmVycywgZGltbWVkLCBsdW0pIHtcbiAgICBpZighZGltbWVkKSB7XG4gICAgICAgIHpiLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgbHVtID4gMC4yID8gJ3JnYmEoMCwwLDAsMC40KScgOlxuICAgICAgICAgICAgICAgICdyZ2JhKDI1NSwyNTUsMjU1LDAuMyknKVxuICAgICAgICAgICAgLmR1cmF0aW9uKDIwMCk7XG4gICAgICAgIGNvcm5lcnMudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAxKVxuICAgICAgICAgICAgLmR1cmF0aW9uKDIwMCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVab29tYm94KGdkKSB7XG4gICAgZDMuc2VsZWN0KGdkKVxuICAgICAgICAuc2VsZWN0QWxsKCcuem9vbWJveCwuanMtem9vbWJveC1iYWNrZHJvcCwuanMtem9vbWJveC1tZW51LC56b29tYm94LWNvcm5lcnMnKVxuICAgICAgICAucmVtb3ZlKCk7XG59XG5cbmZ1bmN0aW9uIHNob3dEb3VibGVDbGlja05vdGlmaWVyKGdkKSB7XG4gICAgaWYoU0hPV1pPT01PVVRUSVAgJiYgZ2QuZGF0YSAmJiBnZC5fY29udGV4dC5zaG93VGlwcykge1xuICAgICAgICBMaWIubm90aWZpZXIoTGliLl8oZ2QsICdEb3VibGUtY2xpY2sgdG8gem9vbSBiYWNrIG91dCcpLCAnbG9uZycpO1xuICAgICAgICBTSE9XWk9PTU9VVFRJUCA9IGZhbHNlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaXNTZWxlY3RPckxhc3NvKGRyYWdtb2RlKSB7XG4gICAgcmV0dXJuIGRyYWdtb2RlID09PSAnbGFzc28nIHx8IGRyYWdtb2RlID09PSAnc2VsZWN0Jztcbn1cblxuZnVuY3Rpb24geENvcm5lcnMoYm94LCB5MCkge1xuICAgIHJldHVybiAnTScgK1xuICAgICAgICAoYm94LmwgLSAwLjUpICsgJywnICsgKHkwIC0gTUlOWk9PTSAtIDAuNSkgK1xuICAgICAgICAnaC0zdicgKyAoMiAqIE1JTlpPT00gKyAxKSArICdoM1pNJyArXG4gICAgICAgIChib3guciArIDAuNSkgKyAnLCcgKyAoeTAgLSBNSU5aT09NIC0gMC41KSArXG4gICAgICAgICdoM3YnICsgKDIgKiBNSU5aT09NICsgMSkgKyAnaC0zWic7XG59XG5cbmZ1bmN0aW9uIHlDb3JuZXJzKGJveCwgeDApIHtcbiAgICByZXR1cm4gJ00nICtcbiAgICAgICAgKHgwIC0gTUlOWk9PTSAtIDAuNSkgKyAnLCcgKyAoYm94LnQgLSAwLjUpICtcbiAgICAgICAgJ3YtM2gnICsgKDIgKiBNSU5aT09NICsgMSkgKyAndjNaTScgK1xuICAgICAgICAoeDAgLSBNSU5aT09NIC0gMC41KSArICcsJyArIChib3guYiArIDAuNSkgK1xuICAgICAgICAndjNoJyArICgyICogTUlOWk9PTSArIDEpICsgJ3YtM1onO1xufVxuXG5mdW5jdGlvbiB4eUNvcm5lcnMoYm94KSB7XG4gICAgdmFyIGNsZW4gPSBNYXRoLmZsb29yKE1hdGgubWluKGJveC5iIC0gYm94LnQsIGJveC5yIC0gYm94LmwsIE1JTlpPT00pIC8gMik7XG4gICAgcmV0dXJuICdNJyArXG4gICAgICAgIChib3gubCAtIDMuNSkgKyAnLCcgKyAoYm94LnQgLSAwLjUgKyBjbGVuKSArICdoM3YnICsgKC1jbGVuKSArXG4gICAgICAgICAgICAnaCcgKyBjbGVuICsgJ3YtM2gtJyArIChjbGVuICsgMykgKyAnWk0nICtcbiAgICAgICAgKGJveC5yICsgMy41KSArICcsJyArIChib3gudCAtIDAuNSArIGNsZW4pICsgJ2gtM3YnICsgKC1jbGVuKSArXG4gICAgICAgICAgICAnaCcgKyAoLWNsZW4pICsgJ3YtM2gnICsgKGNsZW4gKyAzKSArICdaTScgK1xuICAgICAgICAoYm94LnIgKyAzLjUpICsgJywnICsgKGJveC5iICsgMC41IC0gY2xlbikgKyAnaC0zdicgKyBjbGVuICtcbiAgICAgICAgICAgICdoJyArICgtY2xlbikgKyAndjNoJyArIChjbGVuICsgMykgKyAnWk0nICtcbiAgICAgICAgKGJveC5sIC0gMy41KSArICcsJyArIChib3guYiArIDAuNSAtIGNsZW4pICsgJ2gzdicgKyBjbGVuICtcbiAgICAgICAgICAgICdoJyArIGNsZW4gKyAndjNoLScgKyAoY2xlbiArIDMpICsgJ1onO1xufVxuXG5mdW5jdGlvbiBjYWxjTGlua3MoZ2QsIGdyb3VwcywgeGFIYXNoLCB5YUhhc2gpIHtcbiAgICB2YXIgaXNTdWJwbG90Q29uc3RyYWluZWQgPSBmYWxzZTtcbiAgICB2YXIgeExpbmtzID0ge307XG4gICAgdmFyIHlMaW5rcyA9IHt9O1xuICAgIHZhciB4SUQsIHlJRCwgeExpbmtJRCwgeUxpbmtJRDtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBncm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGdyb3VwID0gZ3JvdXBzW2ldO1xuICAgICAgICAvLyBjaGVjayBpZiBhbnkgb2YgdGhlIHggYXhlcyB3ZSdyZSBkcmFnZ2luZyBpcyBpbiB0aGlzIGNvbnN0cmFpbnQgZ3JvdXBcbiAgICAgICAgZm9yKHhJRCBpbiB4YUhhc2gpIHtcbiAgICAgICAgICAgIGlmKGdyb3VwW3hJRF0pIHtcbiAgICAgICAgICAgICAgICAvLyBwdXQgdGhlIHJlc3Qgb2YgdGhlc2UgYXhlcyBpbnRvIHhMaW5rcywgaWYgd2UncmUgbm90IGFscmVhZHlcbiAgICAgICAgICAgICAgICAvLyBkcmFnZ2luZyB0aGVtLCBzbyB3ZSBrbm93IHRvIHNjYWxlIHRoZXNlIGF4ZXMgYXV0b21hdGljYWxseSB0b29cbiAgICAgICAgICAgICAgICAvLyB0byBtYXRjaCB0aGUgY2hhbmdlcyBpbiB0aGUgZHJhZ2dlZCB4IGF4ZXNcbiAgICAgICAgICAgICAgICBmb3IoeExpbmtJRCBpbiBncm91cCkge1xuICAgICAgICAgICAgICAgICAgICBpZighKHhMaW5rSUQuY2hhckF0KDApID09PSAneCcgPyB4YUhhc2ggOiB5YUhhc2gpW3hMaW5rSURdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4TGlua3NbeExpbmtJRF0gPSB4SUQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiB0aGUgeCBhbmQgeSBheGVzIG9mIFRISVMgZHJhZyBhcmUgbGlua2VkXG4gICAgICAgICAgICAgICAgZm9yKHlJRCBpbiB5YUhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoZ3JvdXBbeUlEXSkgaXNTdWJwbG90Q29uc3RyYWluZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG5vdyBjaGVjayBpZiBhbnkgb2YgdGhlIHkgYXhlcyB3ZSdyZSBkcmFnZ2luZyBpcyBpbiB0aGlzIGNvbnN0cmFpbnQgZ3JvdXBcbiAgICAgICAgLy8gb25seSBsb29rIGZvciBvdXRzaWRlIGxpbmtzLCBhcyB3ZSd2ZSBhbHJlYWR5IGNoZWNrZWQgZm9yIGxpbmtzIHdpdGhpbiB0aGUgZHJhZ2dlclxuICAgICAgICBmb3IoeUlEIGluIHlhSGFzaCkge1xuICAgICAgICAgICAgaWYoZ3JvdXBbeUlEXSkge1xuICAgICAgICAgICAgICAgIGZvcih5TGlua0lEIGluIGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCEoeUxpbmtJRC5jaGFyQXQoMCkgPT09ICd4JyA/IHhhSGFzaCA6IHlhSGFzaClbeUxpbmtJRF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHlMaW5rc1t5TGlua0lEXSA9IHlJRDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGlzU3VicGxvdENvbnN0cmFpbmVkKSB7XG4gICAgICAgIC8vIG1lcmdlIHhMaW5rcyBhbmQgeUxpbmtzIGlmIHRoZSBzdWJwbG90IGlzIGNvbnN0cmFpbmVkLFxuICAgICAgICAvLyBzaW5jZSB3ZSdsbCBhbHdheXMgYXBwbHkgYm90aCBhbnl3YXkgYW5kIHRoZSB0d28gd2lsbCBjb250YWluXG4gICAgICAgIC8vIGR1cGxpY2F0ZXNcbiAgICAgICAgTGliLmV4dGVuZEZsYXQoeExpbmtzLCB5TGlua3MpO1xuICAgICAgICB5TGlua3MgPSB7fTtcbiAgICB9XG5cbiAgICB2YXIgeGFIYXNoTGlua2VkID0ge307XG4gICAgdmFyIHhheGVzTGlua2VkID0gW107XG4gICAgZm9yKHhMaW5rSUQgaW4geExpbmtzKSB7XG4gICAgICAgIHZhciB4YSA9IGdldEZyb21JZChnZCwgeExpbmtJRCk7XG4gICAgICAgIHhheGVzTGlua2VkLnB1c2goeGEpO1xuICAgICAgICB4YUhhc2hMaW5rZWRbeGEuX2lkXSA9IHhhO1xuICAgIH1cblxuICAgIHZhciB5YUhhc2hMaW5rZWQgPSB7fTtcbiAgICB2YXIgeWF4ZXNMaW5rZWQgPSBbXTtcbiAgICBmb3IoeUxpbmtJRCBpbiB5TGlua3MpIHtcbiAgICAgICAgdmFyIHlhID0gZ2V0RnJvbUlkKGdkLCB5TGlua0lEKTtcbiAgICAgICAgeWF4ZXNMaW5rZWQucHVzaCh5YSk7XG4gICAgICAgIHlhSGFzaExpbmtlZFt5YS5faWRdID0geWE7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgeGFIYXNoOiB4YUhhc2hMaW5rZWQsXG4gICAgICAgIHlhSGFzaDogeWFIYXNoTGlua2VkLFxuICAgICAgICB4YXhlczogeGF4ZXNMaW5rZWQsXG4gICAgICAgIHlheGVzOiB5YXhlc0xpbmtlZCxcbiAgICAgICAgeExpbmtzOiB4TGlua3MsXG4gICAgICAgIHlMaW5rczogeUxpbmtzLFxuICAgICAgICBpc1N1YnBsb3RDb25zdHJhaW5lZDogaXNTdWJwbG90Q29uc3RyYWluZWRcbiAgICB9O1xufVxuXG4vLyBzdGlsbCBzZWVtcyB0byBiZSBzb21lIGNvbmZ1c2lvbiBhYm91dCBvbndoZWVsIHZzIG9ubW91c2V3aGVlbC4uLlxuZnVuY3Rpb24gYXR0YWNoV2hlZWxFdmVudEhhbmRsZXIoZWxlbWVudCwgaGFuZGxlcikge1xuICAgIGlmKCFzdXBwb3J0c1Bhc3NpdmUpIHtcbiAgICAgICAgaWYoZWxlbWVudC5vbndoZWVsICE9PSB1bmRlZmluZWQpIGVsZW1lbnQub253aGVlbCA9IGhhbmRsZXI7XG4gICAgICAgIGVsc2UgaWYoZWxlbWVudC5vbm1vdXNld2hlZWwgIT09IHVuZGVmaW5lZCkgZWxlbWVudC5vbm1vdXNld2hlZWwgPSBoYW5kbGVyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB3aGVlbEV2ZW50TmFtZSA9IGVsZW1lbnQub253aGVlbCAhPT0gdW5kZWZpbmVkID8gJ3doZWVsJyA6ICdtb3VzZXdoZWVsJztcblxuICAgICAgICBpZihlbGVtZW50Ll9vbndoZWVsKSB7XG4gICAgICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIod2hlZWxFdmVudE5hbWUsIGVsZW1lbnQuX29ud2hlZWwpO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQuX29ud2hlZWwgPSBoYW5kbGVyO1xuXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih3aGVlbEV2ZW50TmFtZSwgaGFuZGxlciwge3Bhc3NpdmU6IGZhbHNlfSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBoYXNoVmFsdWVzKGhhc2gpIHtcbiAgICB2YXIgb3V0ID0gW107XG4gICAgZm9yKHZhciBrIGluIGhhc2gpIG91dC5wdXNoKGhhc2hba10pO1xuICAgIHJldHVybiBvdXQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1ha2VEcmFnQm94OiBtYWtlRHJhZ0JveCxcblxuICAgIG1ha2VEcmFnZ2VyOiBtYWtlRHJhZ2dlcixcbiAgICBtYWtlUmVjdERyYWdnZXI6IG1ha2VSZWN0RHJhZ2dlcixcbiAgICBtYWtlWm9vbWJveDogbWFrZVpvb21ib3gsXG4gICAgbWFrZUNvcm5lcnM6IG1ha2VDb3JuZXJzLFxuXG4gICAgdXBkYXRlWm9vbWJveDogdXBkYXRlWm9vbWJveCxcbiAgICB4eUNvcm5lcnM6IHh5Q29ybmVycyxcbiAgICB0cmFuc2l0aW9uWm9vbWJveDogdHJhbnNpdGlvblpvb21ib3gsXG4gICAgcmVtb3ZlWm9vbWJveDogcmVtb3ZlWm9vbWJveCxcbiAgICBzaG93RG91YmxlQ2xpY2tOb3RpZmllcjogc2hvd0RvdWJsZUNsaWNrTm90aWZpZXIsXG5cbiAgICBhdHRhY2hXaGVlbEV2ZW50SGFuZGxlcjogYXR0YWNoV2hlZWxFdmVudEhhbmRsZXJcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZHJhZ2VsZW1lbnRcIjo2MTEsXCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudFwiOjY4OCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9jbGVhcl9nbF9jYW52YXNlc1wiOjcwNCxcIi4uLy4uL2xpYi9zZXRjdXJzb3JcIjo3MzksXCIuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHNcIjo3NDMsXCIuLi8uLi9wbG90X2FwaS9zdWJyb3V0aW5lc1wiOjc1OCxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vcGxvdHNcIjo4MjgsXCIuL2F4ZXNcIjo3NjcsXCIuL2F4aXNfaWRzXCI6NzcwLFwiLi9jb25zdGFudHNcIjo3NzMsXCIuL3NjYWxlX3pvb21cIjo3ODMsXCIuL3NlbGVjdFwiOjc4NCxcImQzXCI6MTYzLFwiaGFzLXBhc3NpdmUtZXZlbnRzXCI6NDExLFwidGlueWNvbG9yMlwiOjUzN31dLDc3NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIEZ4ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIGRyYWdFbGVtZW50ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmFnZWxlbWVudCcpO1xudmFyIHNldEN1cnNvciA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zZXRjdXJzb3InKTtcblxudmFyIG1ha2VEcmFnQm94ID0gX2RlcmVxXygnLi9kcmFnYm94JykubWFrZURyYWdCb3g7XG52YXIgRFJBR0dFUlNJWkUgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpLkRSQUdHRVJTSVpFO1xuXG5leHBvcnRzLmluaXRJbnRlcmFjdGlvbnMgPSBmdW5jdGlvbiBpbml0SW50ZXJhY3Rpb25zKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIGlmKGdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgLy8gdGhpcyBzd2VlcHMgdXAgbW9yZSB0aGFuIGp1c3QgY2FydGVzaWFuIGRyYWcgZWxlbWVudHMuLi5cbiAgICAgICAgZDMuc2VsZWN0KGdkKS5zZWxlY3RBbGwoJy5kcmFnJykucmVtb3ZlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZighZnVsbExheW91dC5faGFzKCdjYXJ0ZXNpYW4nKSAmJiAhZnVsbExheW91dC5faGFzKCdzcGxvbScpKSByZXR1cm47XG5cbiAgICB2YXIgc3VicGxvdHMgPSBPYmplY3Qua2V5cyhmdWxsTGF5b3V0Ll9wbG90cyB8fCB7fSkuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIC8vIHNvcnQgb3ZlcmxheXMgbGFzdCwgdGhlbiBieSB4IGF4aXMgbnVtYmVyLCB0aGVuIHkgYXhpcyBudW1iZXJcbiAgICAgICAgaWYoKGZ1bGxMYXlvdXQuX3Bsb3RzW2FdLm1haW5wbG90ICYmIHRydWUpID09PVxuICAgICAgICAgICAgKGZ1bGxMYXlvdXQuX3Bsb3RzW2JdLm1haW5wbG90ICYmIHRydWUpKSB7XG4gICAgICAgICAgICB2YXIgYVBhcnRzID0gYS5zcGxpdCgneScpO1xuICAgICAgICAgICAgdmFyIGJQYXJ0cyA9IGIuc3BsaXQoJ3knKTtcbiAgICAgICAgICAgIHJldHVybiAoYVBhcnRzWzBdID09PSBiUGFydHNbMF0pID9cbiAgICAgICAgICAgICAgICAoTnVtYmVyKGFQYXJ0c1sxXSB8fCAxKSAtIE51bWJlcihiUGFydHNbMV0gfHwgMSkpIDpcbiAgICAgICAgICAgICAgICAoTnVtYmVyKGFQYXJ0c1swXSB8fCAxKSAtIE51bWJlcihiUGFydHNbMF0gfHwgMSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdWxsTGF5b3V0Ll9wbG90c1thXS5tYWlucGxvdCA/IDEgOiAtMTtcbiAgICB9KTtcblxuICAgIHN1YnBsb3RzLmZvckVhY2goZnVuY3Rpb24oc3VicGxvdCkge1xuICAgICAgICB2YXIgcGxvdGluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90XTtcbiAgICAgICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgICAgIC8vIG1haW4gYW5kIGNvcm5lciBkcmFnZ2VycyBuZWVkIG5vdCBiZSByZXBlYXRlZCBmb3JcbiAgICAgICAgLy8gb3ZlcmxhaWQgc3VicGxvdHMgLSB0aGVzZSBkcmFnZ2VycyBkcmFnIHRoZW0gYWxsXG4gICAgICAgIGlmKCFwbG90aW5mby5tYWlucGxvdCkge1xuICAgICAgICAgICAgLy8gbWFpbiBkcmFnZ2VyIGdvZXMgb3ZlciB0aGUgZ3JpZHMgYW5kIGRhdGEsIHNvIHdlIHVzZSBpdHNcbiAgICAgICAgICAgIC8vIG1vdXNlbW92ZSBldmVudHMgZm9yIGFsbCBkYXRhIGhvdmVyIGVmZmVjdHNcbiAgICAgICAgICAgIHZhciBtYWluZHJhZyA9IG1ha2VEcmFnQm94KGdkLCBwbG90aW5mbywgeGEuX29mZnNldCwgeWEuX29mZnNldCxcbiAgICAgICAgICAgICAgICB4YS5fbGVuZ3RoLCB5YS5fbGVuZ3RoLCAnbnMnLCAnZXcnKTtcblxuICAgICAgICAgICAgbWFpbmRyYWcub25tb3VzZW1vdmUgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIG9uIGBnZC5fZnVsbExheW91dGAsICpub3QqIGZ1bGxMYXlvdXQgYmVjYXVzZSB0aGUgcmVmZXJlbmNlXG4gICAgICAgICAgICAgICAgLy8gY2hhbmdlcyBieSB0aGUgdGltZSB0aGlzIGlzIGNhbGxlZCBhZ2Fpbi5cbiAgICAgICAgICAgICAgICBnZC5fZnVsbExheW91dC5fcmVob3ZlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBpZihnZC5fZnVsbExheW91dC5faG92ZXJzdWJwbG90ID09PSBzdWJwbG90KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBGeC5ob3ZlcihnZCwgZXZ0LCBzdWJwbG90KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBGeC5ob3ZlcihnZCwgZXZ0LCBzdWJwbG90KTtcblxuICAgICAgICAgICAgICAgIC8vIE5vdGUgdGhhdCB3ZSBoYXZlICpub3QqIHVzZWQgdGhlIGNhY2hlZCBmdWxsTGF5b3V0IHZhcmlhYmxlIGhlcmVcbiAgICAgICAgICAgICAgICAvLyBzaW5jZSB0aGF0IG1heSBiZSBvdXRkYXRlZCB3aGVuIHRoaXMgaXMgY2FsbGVkIGFzIGEgY2FsbGJhY2sgbGF0ZXIgb25cbiAgICAgICAgICAgICAgICBnZC5fZnVsbExheW91dC5fbGFzdGhvdmVyID0gbWFpbmRyYWc7XG4gICAgICAgICAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX2hvdmVyc3VicGxvdCA9IHN1YnBsb3Q7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogSU1QT1JUQU5UOlxuICAgICAgICAgICAgICogV2UgbXVzdCBjaGVjayBmb3IgdGhlIHByZXNlbmNlIG9mIHRoZSBkcmFnIGNvdmVyIGhlcmUuXG4gICAgICAgICAgICAgKiBJZiB3ZSBkb24ndCwgYSAnbW91c2VvdXQnIGV2ZW50IGlzIHRyaWdnZXJlZCBvbiB0aGVcbiAgICAgICAgICAgICAqIG1haW5kcmFnIGJlZm9yZSBlYWNoICdjbGljaycgZXZlbnQsIHdoaWNoIGhhcyB0aGUgZWZmZWN0XG4gICAgICAgICAgICAgKiBvZiBjbGVhcmluZyB0aGUgaG92ZXJkYXRhOyB0aHVzLCBjYW5jZWxsaW5nIHRoZSBjbGljayBldmVudC5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbWFpbmRyYWcub25tb3VzZW91dCA9IGZ1bmN0aW9uKGV2dCkge1xuICAgICAgICAgICAgICAgIGlmKGdkLl9kcmFnZ2luZykgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgLy8gV2hlbiB0aGUgbW91c2UgbGVhdmVzIHRoaXMgbWFpbmRyYWcsIHVuc2V0IHRoZSBob3ZlcmVkIHN1YnBsb3QuXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBtYXkgY2F1c2UgcHJvYmxlbXMgaWYgaXQgbGVhdmVzIHRoZSBzdWJwbG90IGRpcmVjdGx5ICpvbnRvKlxuICAgICAgICAgICAgICAgIC8vIGFub3RoZXIgc3VicGxvdCwgYnV0IHRoYXQncyBhIHRpbnkgY29ybmVyIGNhc2UgYXQgdGhlIG1vbWVudC5cbiAgICAgICAgICAgICAgICBnZC5fZnVsbExheW91dC5faG92ZXJzdWJwbG90ID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGRyYWdFbGVtZW50LnVuaG92ZXIoZ2QsIGV2dCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBjb3JuZXIgZHJhZ2dlcnNcbiAgICAgICAgICAgIGlmKGdkLl9jb250ZXh0LnNob3dBeGlzRHJhZ0hhbmRsZXMpIHtcbiAgICAgICAgICAgICAgICBtYWtlRHJhZ0JveChnZCwgcGxvdGluZm8sIHhhLl9vZmZzZXQgLSBEUkFHR0VSU0laRSwgeWEuX29mZnNldCAtIERSQUdHRVJTSVpFLFxuICAgICAgICAgICAgICAgICAgICBEUkFHR0VSU0laRSwgRFJBR0dFUlNJWkUsICduJywgJ3cnKTtcbiAgICAgICAgICAgICAgICBtYWtlRHJhZ0JveChnZCwgcGxvdGluZm8sIHhhLl9vZmZzZXQgKyB4YS5fbGVuZ3RoLCB5YS5fb2Zmc2V0IC0gRFJBR0dFUlNJWkUsXG4gICAgICAgICAgICAgICAgICAgIERSQUdHRVJTSVpFLCBEUkFHR0VSU0laRSwgJ24nLCAnZScpO1xuICAgICAgICAgICAgICAgIG1ha2VEcmFnQm94KGdkLCBwbG90aW5mbywgeGEuX29mZnNldCAtIERSQUdHRVJTSVpFLCB5YS5fb2Zmc2V0ICsgeWEuX2xlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgRFJBR0dFUlNJWkUsIERSQUdHRVJTSVpFLCAncycsICd3Jyk7XG4gICAgICAgICAgICAgICAgbWFrZURyYWdCb3goZ2QsIHBsb3RpbmZvLCB4YS5fb2Zmc2V0ICsgeGEuX2xlbmd0aCwgeWEuX29mZnNldCArIHlhLl9sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgIERSQUdHRVJTSVpFLCBEUkFHR0VSU0laRSwgJ3MnLCAnZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKGdkLl9jb250ZXh0LnNob3dBeGlzRHJhZ0hhbmRsZXMpIHtcbiAgICAgICAgICAgIC8vIHggYXhpcyBkcmFnZ2VycyAtIGlmIHlvdSBoYXZlIG92ZXJsYWlkIHBsb3RzLFxuICAgICAgICAgICAgLy8gdGhlc2UgZHJhZyBlYWNoIGF4aXMgc2VwYXJhdGVseVxuICAgICAgICAgICAgaWYoc3VicGxvdCA9PT0geGEuX21haW5TdWJwbG90KSB7XG4gICAgICAgICAgICAgICAgLy8gdGhlIHkgcG9zaXRpb24gb2YgdGhlIG1haW4geCBheGlzIGxpbmVcbiAgICAgICAgICAgICAgICB2YXIgeTAgPSB4YS5fbWFpbkxpbmVQb3NpdGlvbjtcbiAgICAgICAgICAgICAgICBpZih4YS5zaWRlID09PSAndG9wJykgeTAgLT0gRFJBR0dFUlNJWkU7XG4gICAgICAgICAgICAgICAgbWFrZURyYWdCb3goZ2QsIHBsb3RpbmZvLCB4YS5fb2Zmc2V0ICsgeGEuX2xlbmd0aCAqIDAuMSwgeTAsXG4gICAgICAgICAgICAgICAgICAgIHhhLl9sZW5ndGggKiAwLjgsIERSQUdHRVJTSVpFLCAnJywgJ2V3Jyk7XG4gICAgICAgICAgICAgICAgbWFrZURyYWdCb3goZ2QsIHBsb3RpbmZvLCB4YS5fb2Zmc2V0LCB5MCxcbiAgICAgICAgICAgICAgICAgICAgeGEuX2xlbmd0aCAqIDAuMSwgRFJBR0dFUlNJWkUsICcnLCAndycpO1xuICAgICAgICAgICAgICAgIG1ha2VEcmFnQm94KGdkLCBwbG90aW5mbywgeGEuX29mZnNldCArIHhhLl9sZW5ndGggKiAwLjksIHkwLFxuICAgICAgICAgICAgICAgICAgICB4YS5fbGVuZ3RoICogMC4xLCBEUkFHR0VSU0laRSwgJycsICdlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyB5IGF4aXMgZHJhZ2dlcnNcbiAgICAgICAgICAgIGlmKHN1YnBsb3QgPT09IHlhLl9tYWluU3VicGxvdCkge1xuICAgICAgICAgICAgICAgIC8vIHRoZSB4IHBvc2l0aW9uIG9mIHRoZSBtYWluIHkgYXhpcyBsaW5lXG4gICAgICAgICAgICAgICAgdmFyIHgwID0geWEuX21haW5MaW5lUG9zaXRpb247XG4gICAgICAgICAgICAgICAgaWYoeWEuc2lkZSAhPT0gJ3JpZ2h0JykgeDAgLT0gRFJBR0dFUlNJWkU7XG4gICAgICAgICAgICAgICAgbWFrZURyYWdCb3goZ2QsIHBsb3RpbmZvLCB4MCwgeWEuX29mZnNldCArIHlhLl9sZW5ndGggKiAwLjEsXG4gICAgICAgICAgICAgICAgICAgIERSQUdHRVJTSVpFLCB5YS5fbGVuZ3RoICogMC44LCAnbnMnLCAnJyk7XG4gICAgICAgICAgICAgICAgbWFrZURyYWdCb3goZ2QsIHBsb3RpbmZvLCB4MCwgeWEuX29mZnNldCArIHlhLl9sZW5ndGggKiAwLjksXG4gICAgICAgICAgICAgICAgICAgIERSQUdHRVJTSVpFLCB5YS5fbGVuZ3RoICogMC4xLCAncycsICcnKTtcbiAgICAgICAgICAgICAgICBtYWtlRHJhZ0JveChnZCwgcGxvdGluZm8sIHgwLCB5YS5fb2Zmc2V0LFxuICAgICAgICAgICAgICAgICAgICBEUkFHR0VSU0laRSwgeWEuX2xlbmd0aCAqIDAuMSwgJ24nLCAnJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIEluIGNhc2UgeW91IG1vdXNlbW92ZSBvdmVyIHNvbWUgaG92ZXJ0ZXh0LCBzZW5kIGl0IHRvIEZ4LmhvdmVyIHRvb1xuICAgIC8vIHdlIGRvIHRoaXMgc28gdGhhdCB3ZSBjYW4gcHV0IHRoZSBob3ZlciB0ZXh0IGluIGZyb250IG9mIGV2ZXJ5dGhpbmcsXG4gICAgLy8gYnV0IHN0aWxsIGJlIGFibGUgdG8gaW50ZXJhY3Qgd2l0aCBldmVyeXRoaW5nIGFzIGlmIGl0IGlzbid0IHRoZXJlXG4gICAgdmFyIGhvdmVyTGF5ZXIgPSBmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLm5vZGUoKTtcblxuICAgIGhvdmVyTGF5ZXIub25tb3VzZW1vdmUgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgZXZ0LnRhcmdldCA9IGdkLl9mdWxsTGF5b3V0Ll9sYXN0aG92ZXI7XG4gICAgICAgIEZ4LmhvdmVyKGdkLCBldnQsIGZ1bGxMYXlvdXQuX2hvdmVyc3VicGxvdCk7XG4gICAgfTtcblxuICAgIGhvdmVyTGF5ZXIub25jbGljayA9IGZ1bmN0aW9uKGV2dCkge1xuICAgICAgICBldnQudGFyZ2V0ID0gZ2QuX2Z1bGxMYXlvdXQuX2xhc3Rob3ZlcjtcbiAgICAgICAgRnguY2xpY2soZ2QsIGV2dCk7XG4gICAgfTtcblxuICAgIC8vIGFsc28gZGVsZWdhdGUgbW91c2Vkb3ducy4uLiBUT0RPOiBkb2VzIHRoaXMgYWN0dWFsbHkgd29yaz9cbiAgICBob3ZlckxheWVyLm9ubW91c2Vkb3duID0gZnVuY3Rpb24oZXZ0KSB7XG4gICAgICAgIGdkLl9mdWxsTGF5b3V0Ll9sYXN0aG92ZXIub25tb3VzZWRvd24oZXZ0KTtcbiAgICB9O1xuXG4gICAgZXhwb3J0cy51cGRhdGVGeChnZCk7XG59O1xuXG4vLyBNaW5pbWFsIHNldCBvZiB1cGRhdGUgbmVlZGVkIG9uICdtb2RlYmFyJyBlZGl0cy5cbi8vIFdlIG9ubHkgbmVlZCB0byB1cGRhdGUgdGhlIDxnIC5kcmFnbGF5ZXI+IGN1cnNvciBzdHlsZS5cbi8vXG4vLyBOb3RlIHRoYXQgY2hhbmdpbmcgdGhlIGF4aXMgY29uZmlndXJhdGlvbiBhbmQvb3IgdGhlIGZpeGVkcmFuZ2UgYXR0cmlidXRlXG4vLyBzaG91bGQgdHJpZ2dlciBhIGZ1bGwgaW5pdEludGVyYWN0aW9ucy5cbmV4cG9ydHMudXBkYXRlRnggPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGN1cnNvciA9IGZ1bGxMYXlvdXQuZHJhZ21vZGUgPT09ICdwYW4nID8gJ21vdmUnIDogJ2Nyb3NzaGFpcic7XG4gICAgc2V0Q3Vyc29yKGZ1bGxMYXlvdXQuX2RyYWdnZXJzLCBjdXJzb3IpO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYWdlbGVtZW50XCI6NjExLFwiLi4vLi4vY29tcG9uZW50cy9meFwiOjYzMixcIi4uLy4uL2xpYi9zZXRjdXJzb3JcIjo3MzksXCIuL2NvbnN0YW50c1wiOjc3MyxcIi4vZHJhZ2JveFwiOjc3NSxcImQzXCI6MTYzfV0sNzc3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG4vKipcbiAqIEZhY3RvcnkgZnVuY3Rpb24gZm9yIGNoZWNraW5nIGNvbXBvbmVudCBhcnJheXMgZm9yIHN1YnBsb3QgcmVmZXJlbmNlcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udGFpbmVyQXJyYXlOYW1lOiB0aGUgdG9wLWxldmVsIGFycmF5IGluIGdkLmxheW91dCB0byBjaGVja1xuICogICBJZiBhbiBpdGVtIGluIHRoaXMgY29udGFpbmVyIGlzIGZvdW5kIHRoYXQgcmVmZXJlbmNlcyBhIGNhcnRlc2lhbiB4IGFuZC9vciB5IGF4aXMsXG4gKiAgIGVuc3VyZSBjYXJ0ZXNpYW4gaXMgbWFya2VkIGFzIGEgYmFzZSBwbG90IG1vZHVsZSBhbmQgcmVjb3JkIHRoZSBheGVzIChhbmQgc3VicGxvdFxuICogICBpZiBib3RoIHJlZnMgYXJlIGF4ZXMpIGluIGdkLl9mdWxsTGF5b3V0XG4gKlxuICogQHJldHVybiB7ZnVuY3Rpb259OiB3aXRoIGFyZ3MgbGF5b3V0SW4gKGdkLmxheW91dCkgYW5kIGxheW91dE91dCAoZ2QuX2Z1bGxMYXlvdXQpXG4gKiBhcyBleHBlY3RlZCBvZiBhIGNvbXBvbmVudCBpbmNsdWRlQmFzZVBsb3QgbWV0aG9kXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWFrZUluY2x1ZGVDb21wb25lbnRzKGNvbnRhaW5lckFycmF5TmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiBpbmNsdWRlQ29tcG9uZW50cyhsYXlvdXRJbiwgbGF5b3V0T3V0KSB7XG4gICAgICAgIHZhciBhcnJheSA9IGxheW91dEluW2NvbnRhaW5lckFycmF5TmFtZV07XG4gICAgICAgIGlmKCFBcnJheS5pc0FycmF5KGFycmF5KSkgcmV0dXJuO1xuXG4gICAgICAgIHZhciBDYXJ0ZXNpYW4gPSBSZWdpc3RyeS5zdWJwbG90c1JlZ2lzdHJ5LmNhcnRlc2lhbjtcbiAgICAgICAgdmFyIGlkUmVnZXggPSBDYXJ0ZXNpYW4uaWRSZWdleDtcbiAgICAgICAgdmFyIHN1YnBsb3RzID0gbGF5b3V0T3V0Ll9zdWJwbG90cztcbiAgICAgICAgdmFyIHhhTGlzdCA9IHN1YnBsb3RzLnhheGlzO1xuICAgICAgICB2YXIgeWFMaXN0ID0gc3VicGxvdHMueWF4aXM7XG4gICAgICAgIHZhciBjYXJ0ZXNpYW5MaXN0ID0gc3VicGxvdHMuY2FydGVzaWFuO1xuICAgICAgICB2YXIgaGFzQ2FydGVzaWFuT3JHTDJEID0gbGF5b3V0T3V0Ll9oYXMoJ2NhcnRlc2lhbicpIHx8IGxheW91dE91dC5faGFzKCdnbDJkJyk7XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgaXRlbWkgPSBhcnJheVtpXTtcbiAgICAgICAgICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChpdGVtaSkpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB2YXIgeHJlZiA9IGl0ZW1pLnhyZWY7XG4gICAgICAgICAgICB2YXIgeXJlZiA9IGl0ZW1pLnlyZWY7XG5cbiAgICAgICAgICAgIHZhciBoYXNYcmVmID0gaWRSZWdleC54LnRlc3QoeHJlZik7XG4gICAgICAgICAgICB2YXIgaGFzWXJlZiA9IGlkUmVnZXgueS50ZXN0KHlyZWYpO1xuICAgICAgICAgICAgaWYoaGFzWHJlZiB8fCBoYXNZcmVmKSB7XG4gICAgICAgICAgICAgICAgaWYoIWhhc0NhcnRlc2lhbk9yR0wyRCkgTGliLnB1c2hVbmlxdWUobGF5b3V0T3V0Ll9iYXNlUGxvdE1vZHVsZXMsIENhcnRlc2lhbik7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3QXhpcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmKGhhc1hyZWYgJiYgeGFMaXN0LmluZGV4T2YoeHJlZikgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHhhTGlzdC5wdXNoKHhyZWYpO1xuICAgICAgICAgICAgICAgICAgICBuZXdBeGlzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYoaGFzWXJlZiAmJiB5YUxpc3QuaW5kZXhPZih5cmVmKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgeWFMaXN0LnB1c2goeXJlZik7XG4gICAgICAgICAgICAgICAgICAgIG5ld0F4aXMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICogTm90aWNlIHRoZSBsb2dpYyBoZXJlOiBvbmx5IGFkZCBhIHN1YnBsb3QgZm9yIGEgY29tcG9uZW50IGlmXG4gICAgICAgICAgICAgICAgICogaXQncyByZWZlcmVuY2luZyBib3RoIHggYW5kIHkgYXhlcyBBTkQgaXQncyBjcmVhdGluZyBhIG5ldyBheGlzXG4gICAgICAgICAgICAgICAgICogc28gZm9yIGV4YW1wbGUgaWYgeW91ciBwbG90IGFscmVhZHkgaGFzIHh5IGFuZCB4MnkyLCBhbiBhbm5vdGF0aW9uXG4gICAgICAgICAgICAgICAgICogb24geDJ5IG9yIHh5MiB3aWxsIG5vdCBjcmVhdGUgYSBuZXcgc3VicGxvdC5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBpZihuZXdBeGlzICYmIGhhc1hyZWYgJiYgaGFzWXJlZikge1xuICAgICAgICAgICAgICAgICAgICBjYXJ0ZXNpYW5MaXN0LnB1c2goeHJlZiArIHlyZWYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3fV0sNzc4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIFBsb3RzID0gX2RlcmVxXygnLi4vcGxvdHMnKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG5cbnZhciBnZXRNb2R1bGVDYWxjRGF0YSA9IF9kZXJlcV8oJy4uL2dldF9kYXRhJykuZ2V0TW9kdWxlQ2FsY0RhdGE7XG52YXIgYXhpc0lkcyA9IF9kZXJlcV8oJy4vYXhpc19pZHMnKTtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIHhtbG5zTmFtZXNwYWNlcyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzJyk7XG5cbnZhciBlbnN1cmVTaW5nbGUgPSBMaWIuZW5zdXJlU2luZ2xlO1xuXG5mdW5jdGlvbiBlbnN1cmVTaW5nbGVBbmRBZGREYXR1bShwYXJlbnQsIG5vZGVUeXBlLCBjbGFzc05hbWUpIHtcbiAgICByZXR1cm4gTGliLmVuc3VyZVNpbmdsZShwYXJlbnQsIG5vZGVUeXBlLCBjbGFzc05hbWUsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5kYXR1bShjbGFzc05hbWUpO1xuICAgIH0pO1xufVxuXG5leHBvcnRzLm5hbWUgPSAnY2FydGVzaWFuJztcblxuZXhwb3J0cy5hdHRyID0gWyd4YXhpcycsICd5YXhpcyddO1xuXG5leHBvcnRzLmlkUm9vdCA9IFsneCcsICd5J107XG5cbmV4cG9ydHMuaWRSZWdleCA9IGNvbnN0YW50cy5pZFJlZ2V4O1xuXG5leHBvcnRzLmF0dHJSZWdleCA9IGNvbnN0YW50cy5hdHRyUmVnZXg7XG5cbmV4cG9ydHMuYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG5leHBvcnRzLmxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMuc3VwcGx5TGF5b3V0RGVmYXVsdHMgPSBfZGVyZXFfKCcuL2xheW91dF9kZWZhdWx0cycpO1xuXG5leHBvcnRzLnRyYW5zaXRpb25BeGVzID0gX2RlcmVxXygnLi90cmFuc2l0aW9uX2F4ZXMnKTtcblxuZXhwb3J0cy5maW5hbGl6ZVN1YnBsb3RzID0gZnVuY3Rpb24obGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgIHZhciBzdWJwbG90cyA9IGxheW91dE91dC5fc3VicGxvdHM7XG4gICAgdmFyIHhMaXN0ID0gc3VicGxvdHMueGF4aXM7XG4gICAgdmFyIHlMaXN0ID0gc3VicGxvdHMueWF4aXM7XG4gICAgdmFyIHNwU1ZHID0gc3VicGxvdHMuY2FydGVzaWFuO1xuICAgIHZhciBzcEFsbCA9IHNwU1ZHLmNvbmNhdChzdWJwbG90cy5nbDJkIHx8IFtdKTtcbiAgICB2YXIgYWxsWCA9IHt9O1xuICAgIHZhciBhbGxZID0ge307XG4gICAgdmFyIGksIHhpLCB5aTtcblxuICAgIGZvcihpID0gMDsgaSA8IHNwQWxsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IHNwQWxsW2ldLnNwbGl0KCd5Jyk7XG4gICAgICAgIGFsbFhbcGFydHNbMF1dID0gMTtcbiAgICAgICAgYWxsWVsneScgKyBwYXJ0c1sxXV0gPSAxO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGZvciB4IGF4ZXMgd2l0aCBubyBzdWJwbG90LCBhbmQgbWFrZSBvbmUgZnJvbSB0aGUgYW5jaG9yIG9mIHRoYXQgeCBheGlzXG4gICAgZm9yKGkgPSAwOyBpIDwgeExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgeGkgPSB4TGlzdFtpXTtcbiAgICAgICAgaWYoIWFsbFhbeGldKSB7XG4gICAgICAgICAgICB5aSA9IChsYXlvdXRJbltheGlzSWRzLmlkMm5hbWUoeGkpXSB8fCB7fSkuYW5jaG9yO1xuICAgICAgICAgICAgaWYoIWNvbnN0YW50cy5pZFJlZ2V4LnkudGVzdCh5aSkpIHlpID0gJ3knO1xuICAgICAgICAgICAgc3BTVkcucHVzaCh4aSArIHlpKTtcbiAgICAgICAgICAgIHNwQWxsLnB1c2goeGkgKyB5aSk7XG5cbiAgICAgICAgICAgIGlmKCFhbGxZW3lpXSkge1xuICAgICAgICAgICAgICAgIGFsbFlbeWldID0gMTtcbiAgICAgICAgICAgICAgICBMaWIucHVzaFVuaXF1ZSh5TGlzdCwgeWkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gc2FtZSBmb3IgeSBheGVzIHdpdGggbm8gc3VicGxvdFxuICAgIGZvcihpID0gMDsgaSA8IHlMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHlpID0geUxpc3RbaV07XG4gICAgICAgIGlmKCFhbGxZW3lpXSkge1xuICAgICAgICAgICAgeGkgPSAobGF5b3V0SW5bYXhpc0lkcy5pZDJuYW1lKHlpKV0gfHwge30pLmFuY2hvcjtcbiAgICAgICAgICAgIGlmKCFjb25zdGFudHMuaWRSZWdleC54LnRlc3QoeGkpKSB4aSA9ICd4JztcbiAgICAgICAgICAgIHNwU1ZHLnB1c2goeGkgKyB5aSk7XG4gICAgICAgICAgICBzcEFsbC5wdXNoKHhpICsgeWkpO1xuXG4gICAgICAgICAgICBpZighYWxsWFt4aV0pIHtcbiAgICAgICAgICAgICAgICBhbGxYW3hpXSA9IDE7XG4gICAgICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUoeExpc3QsIHhpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGZpbmFsbHksIGlmIHdlJ3ZlIGdvdHRlbiBoZXJlIHdlJ3JlIHN1cHBvc2VkIHRvIHNob3cgY2FydGVzaWFuLi4uXG4gICAgLy8gc28gaWYgdGhlcmUgYXJlIE5PIHN1YnBsb3RzIGF0IGFsbCwgbWFrZSBvbmUgZnJvbSB0aGUgZmlyc3RcbiAgICAvLyB4ICYgeSBheGVzIGluIHRoZSBpbnB1dCBsYXlvdXRcbiAgICBpZighc3BBbGwubGVuZ3RoKSB7XG4gICAgICAgIHhpID0gJyc7XG4gICAgICAgIHlpID0gJyc7XG4gICAgICAgIGZvcih2YXIga2kgaW4gbGF5b3V0SW4pIHtcbiAgICAgICAgICAgIGlmKGNvbnN0YW50cy5hdHRyUmVnZXgudGVzdChraSkpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXhMZXR0ZXIgPSBraS5jaGFyQXQoMCk7XG4gICAgICAgICAgICAgICAgaWYoYXhMZXR0ZXIgPT09ICd4Jykge1xuICAgICAgICAgICAgICAgICAgICBpZigheGkgfHwgKCtraS5zdWJzdHIoNSkgPCAreGkuc3Vic3RyKDUpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgeGkgPSBraTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZigheWkgfHwgKCtraS5zdWJzdHIoNSkgPCAreWkuc3Vic3RyKDUpKSkge1xuICAgICAgICAgICAgICAgICAgICB5aSA9IGtpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB4aSA9IHhpID8gYXhpc0lkcy5uYW1lMmlkKHhpKSA6ICd4JztcbiAgICAgICAgeWkgPSB5aSA/IGF4aXNJZHMubmFtZTJpZCh5aSkgOiAneSc7XG4gICAgICAgIHhMaXN0LnB1c2goeGkpO1xuICAgICAgICB5TGlzdC5wdXNoKHlpKTtcbiAgICAgICAgc3BTVkcucHVzaCh4aSArIHlpKTtcbiAgICB9XG59O1xuXG4vKipcbiAqIENhcnRlc2lhbi5wbG90XG4gKlxuICogQHBhcmFtIHtET00gZGl2IHwgb2JqZWN0fSBnZFxuICogQHBhcmFtIHthcnJheSAob3B0aW9uYWwpfSB0cmFjZXNcbiAqICBhcnJheSBvZiB0cmFjZXMgaW5kaWNlcyB0byBwbG90XG4gKiAgaWYgdW5kZWZpbmVkLCBwbG90cyBhbGwgY2FydGVzaWFuIHRyYWNlcyxcbiAqIEBwYXJhbSB7b2JqZWN0fSAob3B0aW9uYWwpIHRyYW5zaXRpb25PcHRzXG4gKiAgdHJhbnNpdGlvbiBvcHRpb24gb2JqZWN0XG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSAob3B0aW9uYWwpIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2tcbiAqICB0cmFuc2l0aW9uIG1ha2UgY2FsbGJhY2sgZnVuY3Rpb24gZnJvbSBQbG90cy50cmFuc2l0aW9uXG4gKi9cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uKGdkLCB0cmFjZXMsIHRyYW5zaXRpb25PcHRzLCBtYWtlT25Db21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VicGxvdHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90cy5jYXJ0ZXNpYW47XG4gICAgdmFyIGNhbGNkYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIGk7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheSh0cmFjZXMpKSB7XG4gICAgICAgIC8vIElmIHRyYWNlcyBpcyBub3QgcHJvdmlkZWQsIHRoZW4gaXQncyBhIGNvbXBsZXRlIHJlcGxvdCBhbmQgbWlzc2luZ1xuICAgICAgICAvLyB0cmFjZXMgYXJlIHJlbW92ZWRcbiAgICAgICAgdHJhY2VzID0gW107XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNhbGNkYXRhLmxlbmd0aDsgaSsrKSB0cmFjZXMucHVzaChpKTtcbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzdWJwbG90cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3VicGxvdCA9IHN1YnBsb3RzW2ldO1xuICAgICAgICB2YXIgc3VicGxvdEluZm8gPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90XTtcblxuICAgICAgICAvLyBHZXQgYWxsIGNhbGNkYXRhIGZvciB0aGlzIHN1YnBsb3Q6XG4gICAgICAgIHZhciBjZFN1YnBsb3QgPSBbXTtcbiAgICAgICAgdmFyIHBjZDtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2FsY2RhdGEubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBjZCA9IGNhbGNkYXRhW2pdO1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICAgICAgICAgIC8vIFNraXAgdHJhY2UgaWYgd2hpdGVsaXN0IHByb3ZpZGVkIGFuZCBpdCdzIG5vdCB3aGl0ZWxpc3RlZDpcbiAgICAgICAgICAgIC8vIGlmIChBcnJheS5pc0FycmF5KHRyYWNlcykgJiYgdHJhY2VzLmluZGV4T2YoaSkgPT09IC0xKSBjb250aW51ZTtcbiAgICAgICAgICAgIGlmKHRyYWNlLnhheGlzICsgdHJhY2UueWF4aXMgPT09IHN1YnBsb3QpIHtcbiAgICAgICAgICAgICAgICAvLyBYWFg6IFNob3VsZCB0cmFjZSBjYXJwZXQgZGVwZW5kZW5jaWVzLiBPbmx5IHJlcGxvdCBhbGwgY2FycGV0IHBsb3RzIGlmIHRoZSBjYXJwZXRcbiAgICAgICAgICAgICAgICAvLyBheGlzIGhhcyBhY3R1YWxseSBjaGFuZ2VkOlxuICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyB0cmFjZSBpcyBzcGVjaWZpY2FsbHkgcmVxdWVzdGVkLCBhZGQgaXQgdG8gdGhlIGxpc3Q6XG4gICAgICAgICAgICAgICAgaWYodHJhY2VzLmluZGV4T2YodHJhY2UuaW5kZXgpICE9PSAtMSB8fCB0cmFjZS5jYXJwZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gT2theSwgc28gZXhhbXBsZTogdHJhY2VzIDAsIDEsIGFuZCAyIGhhdmUgZmlsbCA9IHRvbmV4dC4gWW91IGFuaW1hdGVcbiAgICAgICAgICAgICAgICAgICAgLy8gdHJhY2VzIDAgYW5kIDIuIFRyYWNlIDEgYWxzbyBuZWVkcyB0byBiZSB1cGRhdGVkLCBvdGhlcndpc2UgaXRzIGZpbGxcbiAgICAgICAgICAgICAgICAgICAgLy8gaXMgb3V0ZGF0ZWQuIFNvIHRoaXMgcmV0cm9hY3RpdmVseSBhZGRzIHRoZSBwcmV2aW91cyB0cmFjZSBpZiB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gdHJhY2VzIGFyZSBpbnRlcmRlcGVuZGVudC5cbiAgICAgICAgICAgICAgICAgICAgaWYoXG4gICAgICAgICAgICAgICAgICAgICAgICBwY2QgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHBjZFswXS50cmFjZS54YXhpcyArIHBjZFswXS50cmFjZS55YXhpcyA9PT0gc3VicGxvdCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgWyd0b25leHR4JywgJ3RvbmV4dHknLCAndG9uZXh0J10uaW5kZXhPZih0cmFjZS5maWxsKSAhPT0gLTEgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGNkU3VicGxvdC5pbmRleE9mKHBjZCkgPT09IC0xXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2RTdWJwbG90LnB1c2gocGNkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNkU3VicGxvdC5wdXNoKGNkKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBUcmFjayB0aGUgcHJldmlvdXMgdHJhY2Ugb24gdGhpcyBzdWJwbG90IGZvciB0aGUgcmV0cm9hY3RpdmUtYWRkIHN0ZXBcbiAgICAgICAgICAgICAgICAvLyBhYm92ZTpcbiAgICAgICAgICAgICAgICBwY2QgPSBjZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHBsb3RPbmUoZ2QsIHN1YnBsb3RJbmZvLCBjZFN1YnBsb3QsIHRyYW5zaXRpb25PcHRzLCBtYWtlT25Db21wbGV0ZUNhbGxiYWNrKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBwbG90T25lKGdkLCBwbG90aW5mbywgY2RTdWJwbG90LCB0cmFuc2l0aW9uT3B0cywgbWFrZU9uQ29tcGxldGVDYWxsYmFjaykge1xuICAgIHZhciB0cmFjZUxheWVyQ2xhc3NlcyA9IGNvbnN0YW50cy50cmFjZUxheWVyQ2xhc3NlcztcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBtb2R1bGVzID0gZnVsbExheW91dC5fbW9kdWxlcztcbiAgICB2YXIgX21vZHVsZSwgY2RNb2R1bGVBbmRPdGhlcnMsIGNkTW9kdWxlO1xuXG4gICAgdmFyIGxheWVyRGF0YSA9IFtdO1xuICAgIHZhciB6b29tU2NhbGVRdWVyeVBhcnRzID0gW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbW9kdWxlID0gbW9kdWxlc1tpXTtcbiAgICAgICAgdmFyIG5hbWUgPSBfbW9kdWxlLm5hbWU7XG4gICAgICAgIHZhciBjYXRlZ29yaWVzID0gUmVnaXN0cnkubW9kdWxlc1tuYW1lXS5jYXRlZ29yaWVzO1xuXG4gICAgICAgIGlmKGNhdGVnb3JpZXMuc3ZnKSB7XG4gICAgICAgICAgICB2YXIgY2xhc3NOYW1lID0gKF9tb2R1bGUubGF5ZXJOYW1lIHx8IG5hbWUgKyAnbGF5ZXInKTtcbiAgICAgICAgICAgIHZhciBwbG90TWV0aG9kID0gX21vZHVsZS5wbG90O1xuXG4gICAgICAgICAgICAvLyBwbG90IGFsbCB2aXNpYmxlIHRyYWNlcyBvZiB0aGlzIHR5cGUgb24gdGhpcyBzdWJwbG90IGF0IG9uY2VcbiAgICAgICAgICAgIGNkTW9kdWxlQW5kT3RoZXJzID0gZ2V0TW9kdWxlQ2FsY0RhdGEoY2RTdWJwbG90LCBwbG90TWV0aG9kKTtcbiAgICAgICAgICAgIGNkTW9kdWxlID0gY2RNb2R1bGVBbmRPdGhlcnNbMF07XG4gICAgICAgICAgICAvLyBkb24ndCBuZWVkIHRvIHNlYXJjaCB0aGUgZm91bmQgdHJhY2VzIGFnYWluIC0gaW4gZmFjdCB3ZSBuZWVkIHRvIE5PVFxuICAgICAgICAgICAgLy8gc28gdGhhdCBpZiB0d28gbW9kdWxlcyBzaGFyZSB0aGUgc2FtZSBwbG90dGVyIHdlIGRvbid0IGRvdWJsZS1wbG90XG4gICAgICAgICAgICBjZFN1YnBsb3QgPSBjZE1vZHVsZUFuZE90aGVyc1sxXTtcblxuICAgICAgICAgICAgaWYoY2RNb2R1bGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgbGF5ZXJEYXRhLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBpOiB0cmFjZUxheWVyQ2xhc3Nlcy5pbmRleE9mKGNsYXNzTmFtZSksXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgICAgICBwbG90TWV0aG9kOiBwbG90TWV0aG9kLFxuICAgICAgICAgICAgICAgICAgICBjZE1vZHVsZTogY2RNb2R1bGVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoY2F0ZWdvcmllcy56b29tU2NhbGUpIHtcbiAgICAgICAgICAgICAgICB6b29tU2NhbGVRdWVyeVBhcnRzLnB1c2goJy4nICsgY2xhc3NOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGxheWVyRGF0YS5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGEuaSAtIGIuaTsgfSk7XG5cbiAgICB2YXIgbGF5ZXJzID0gcGxvdGluZm8ucGxvdC5zZWxlY3RBbGwoJ2cubWxheWVyJylcbiAgICAgICAgLmRhdGEobGF5ZXJEYXRhLCBmdW5jdGlvbihkKSB7IHJldHVybiBkLmNsYXNzTmFtZTsgfSk7XG5cbiAgICBsYXllcnMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCBmdW5jdGlvbihkKSB7IHJldHVybiBkLmNsYXNzTmFtZTsgfSlcbiAgICAgICAgLmNsYXNzZWQoJ21sYXllcicsIHRydWUpXG4gICAgICAgIC5jbGFzc2VkKCdyYW5nZXBsb3QnLCBwbG90aW5mby5pc1JhbmdlUGxvdCk7XG5cbiAgICBsYXllcnMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgbGF5ZXJzLm9yZGVyKCk7XG5cbiAgICBsYXllcnMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBzZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBkLmNsYXNzTmFtZTtcblxuICAgICAgICBkLnBsb3RNZXRob2QoXG4gICAgICAgICAgICBnZCwgcGxvdGluZm8sIGQuY2RNb2R1bGUsIHNlbCxcbiAgICAgICAgICAgIHRyYW5zaXRpb25PcHRzLCBtYWtlT25Db21wbGV0ZUNhbGxiYWNrXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gbGF5ZXJzIHRoYXQgYWxsb3cgYGNsaXBvbmF4aXM6IGZhbHNlYFxuICAgICAgICBpZihjb25zdGFudHMuY2xpcE9uQXhpc0ZhbHNlUXVlcnkuaW5kZXhPZignLicgKyBjbGFzc05hbWUpID09PSAtMSkge1xuICAgICAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKHNlbCwgcGxvdGluZm8ubGF5ZXJDbGlwSWQsIGdkKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gY2FsbCBTY2F0dGVyZ2wucGxvdCBzZXBhcmF0ZWx5XG4gICAgaWYoZnVsbExheW91dC5faGFzKCdzY2F0dGVyZ2wnKSkge1xuICAgICAgICBfbW9kdWxlID0gUmVnaXN0cnkuZ2V0TW9kdWxlKCdzY2F0dGVyZ2wnKTtcbiAgICAgICAgY2RNb2R1bGUgPSBnZXRNb2R1bGVDYWxjRGF0YShjZFN1YnBsb3QsIF9tb2R1bGUpWzBdO1xuICAgICAgICBfbW9kdWxlLnBsb3QoZ2QsIHBsb3RpbmZvLCBjZE1vZHVsZSk7XG4gICAgfVxuXG4gICAgLy8gc3Rhc2ggXCJob3RcIiBzZWxlY3Rpb25zIGZvciBmYXN0ZXIgaW50ZXJhY3Rpb24gb24gZHJhZyBhbmQgc2Nyb2xsXG4gICAgaWYoIWdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgaWYocGxvdGluZm8uX2hhc0NsaXBPbkF4aXNGYWxzZSkge1xuICAgICAgICAgICAgcGxvdGluZm8uY2xpcE9uQXhpc0ZhbHNlVHJhY2VzID0gcGxvdGluZm8ucGxvdFxuICAgICAgICAgICAgICAgIC5zZWxlY3RBbGwoY29uc3RhbnRzLmNsaXBPbkF4aXNGYWxzZVF1ZXJ5LmpvaW4oJywnKSlcbiAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCcudHJhY2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHpvb21TY2FsZVF1ZXJ5UGFydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2VzID0gcGxvdGluZm8ucGxvdFxuICAgICAgICAgICAgICAgIC5zZWxlY3RBbGwoem9vbVNjYWxlUXVlcnlQYXJ0cy5qb2luKCcsJykpXG4gICAgICAgICAgICAgICAgLnNlbGVjdEFsbCgnLnRyYWNlJyk7XG5cbiAgICAgICAgICAgIHBsb3RpbmZvLnpvb21TY2FsZVB0cyA9IHRyYWNlcy5zZWxlY3RBbGwoJ3BhdGgucG9pbnQnKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLnpvb21TY2FsZVR4dCA9IHRyYWNlcy5zZWxlY3RBbGwoJy50ZXh0cG9pbnQnKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBvbGRQbG90cyA9IG9sZEZ1bGxMYXlvdXQuX3Bsb3RzIHx8IHt9O1xuICAgIHZhciBuZXdQbG90cyA9IG5ld0Z1bGxMYXlvdXQuX3Bsb3RzIHx8IHt9O1xuICAgIHZhciBvbGRTdWJwbG90TGlzdCA9IG9sZEZ1bGxMYXlvdXQuX3N1YnBsb3RzIHx8IHt9O1xuICAgIHZhciBwbG90aW5mbztcbiAgICB2YXIgaSwgaztcblxuICAgIC8vIHdoZW4gZ29pbmcgZnJvbSBhIGxhcmdlIHNwbG9tIGdyYXBoIHRvIHNvbWV0aGluZyBlbHNlLFxuICAgIC8vIHdlIG5lZWQgdG8gY2xlYXIgPGcgc3VicGxvdD4gc28gdGhhdCB0aGUgbmV3IGNhcnRlc2lhbiBzdWJwbG90XG4gICAgLy8gY2FuIGhhdmUgdGhlIGNvcnJlY3QgbGF5ZXIgb3JkZXJpbmdcbiAgICBpZihvbGRGdWxsTGF5b3V0Ll9oYXNPbmx5TGFyZ2VTcGxvbXMgJiYgIW5ld0Z1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcykge1xuICAgICAgICBmb3IoayBpbiBvbGRQbG90cykge1xuICAgICAgICAgICAgcGxvdGluZm8gPSBvbGRQbG90c1trXTtcbiAgICAgICAgICAgIGlmKHBsb3RpbmZvLnBsb3Rncm91cCkgcGxvdGluZm8ucGxvdGdyb3VwLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGhhZEdsID0gKG9sZEZ1bGxMYXlvdXQuX2hhcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXMoJ2dsJykpO1xuICAgIHZhciBoYXNHbCA9IChuZXdGdWxsTGF5b3V0Ll9oYXMgJiYgbmV3RnVsbExheW91dC5faGFzKCdnbCcpKTtcblxuICAgIGlmKGhhZEdsICYmICFoYXNHbCkge1xuICAgICAgICBmb3IoayBpbiBvbGRQbG90cykge1xuICAgICAgICAgICAgcGxvdGluZm8gPSBvbGRQbG90c1trXTtcbiAgICAgICAgICAgIGlmKHBsb3RpbmZvLl9zY2VuZSkgcGxvdGluZm8uX3NjZW5lLmRlc3Ryb3koKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGRlbGV0ZSBhbnkgdGl0bGVzIHdlIGRvbid0IG5lZWQgYW55bW9yZVxuICAgIC8vIGNoZWNrIGlmIGF4aXMgbGlzdCBoYXMgY2hhbmdlZCwgYW5kIGlmIHNvIGNsZWFyIG9sZCB0aXRsZXNcbiAgICBpZihvbGRTdWJwbG90TGlzdC54YXhpcyAmJiBvbGRTdWJwbG90TGlzdC55YXhpcykge1xuICAgICAgICB2YXIgb2xkQXhJRHMgPSBheGlzSWRzLmxpc3RJZHMoe19mdWxsTGF5b3V0OiBvbGRGdWxsTGF5b3V0fSk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG9sZEF4SURzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgb2xkQXhJZCA9IG9sZEF4SURzW2ldO1xuICAgICAgICAgICAgaWYoIW5ld0Z1bGxMYXlvdXRbYXhpc0lkcy5pZDJuYW1lKG9sZEF4SWQpXSkge1xuICAgICAgICAgICAgICAgIG9sZEZ1bGxMYXlvdXQuX2luZm9sYXllci5zZWxlY3RBbGwoJy5nLScgKyBvbGRBeElkICsgJ3RpdGxlJykucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaGFkQ2FydGVzaWFuID0gKG9sZEZ1bGxMYXlvdXQuX2hhcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXMoJ2NhcnRlc2lhbicpKTtcbiAgICB2YXIgaGFzQ2FydGVzaWFuID0gKG5ld0Z1bGxMYXlvdXQuX2hhcyAmJiBuZXdGdWxsTGF5b3V0Ll9oYXMoJ2NhcnRlc2lhbicpKTtcblxuICAgIGlmKGhhZENhcnRlc2lhbiAmJiAhaGFzQ2FydGVzaWFuKSB7XG4gICAgICAgIC8vIGlmIHdlJ3ZlIGdvdHRlbiByaWQgb2YgYWxsIGNhcnRlc2lhbiB0cmFjZXMsIHJlbW92ZSBhbGwgdGhlIHN1YnBsb3Qgc3ZnIGl0ZW1zXG5cbiAgICAgICAgcHVyZ2VTdWJwbG90TGF5ZXJzKG9sZEZ1bGxMYXlvdXQuX2NhcnRlc2lhbmxheWVyLnNlbGVjdEFsbCgnLnN1YnBsb3QnKSwgb2xkRnVsbExheW91dCk7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX2RlZnMuc2VsZWN0QWxsKCcuYXhlc2NsaXAnKS5yZW1vdmUoKTtcbiAgICAgICAgZGVsZXRlIG9sZEZ1bGxMYXlvdXQuX2F4aXNDb25zdHJhaW50R3JvdXBzO1xuICAgIH0gZWxzZSBpZihvbGRTdWJwbG90TGlzdC5jYXJ0ZXNpYW4pIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlIGxvb2sgZm9yIHN1YnBsb3RzIHdlIG5lZWQgdG8gcmVtb3ZlXG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgb2xkU3VicGxvdExpc3QuY2FydGVzaWFuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgb2xkU3VicGxvdElkID0gb2xkU3VicGxvdExpc3QuY2FydGVzaWFuW2ldO1xuICAgICAgICAgICAgaWYoIW5ld1Bsb3RzW29sZFN1YnBsb3RJZF0pIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0b3IgPSAnLicgKyBvbGRTdWJwbG90SWQgKyAnLC4nICsgb2xkU3VicGxvdElkICsgJy14LC4nICsgb2xkU3VicGxvdElkICsgJy15JztcbiAgICAgICAgICAgICAgICBvbGRGdWxsTGF5b3V0Ll9jYXJ0ZXNpYW5sYXllci5zZWxlY3RBbGwoc2VsZWN0b3IpLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIHJlbW92ZVN1YnBsb3RFeHRyYXMob2xkU3VicGxvdElkLCBvbGRGdWxsTGF5b3V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmV4cG9ydHMuZHJhd0ZyYW1ld29yayA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VicGxvdERhdGEgPSBtYWtlU3VicGxvdERhdGEoZ2QpO1xuXG4gICAgdmFyIHN1YnBsb3RMYXllcnMgPSBmdWxsTGF5b3V0Ll9jYXJ0ZXNpYW5sYXllci5zZWxlY3RBbGwoJy5zdWJwbG90JylcbiAgICAgICAgLmRhdGEoc3VicGxvdERhdGEsIFN0cmluZyk7XG5cbiAgICBzdWJwbG90TGF5ZXJzLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgZnVuY3Rpb24oZCkgeyByZXR1cm4gJ3N1YnBsb3QgJyArIGRbMF07IH0pO1xuXG4gICAgc3VicGxvdExheWVycy5vcmRlcigpO1xuXG4gICAgc3VicGxvdExheWVycy5leGl0KClcbiAgICAgICAgLmNhbGwocHVyZ2VTdWJwbG90TGF5ZXJzLCBmdWxsTGF5b3V0KTtcblxuICAgIHN1YnBsb3RMYXllcnMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBpZCA9IGRbMF07XG4gICAgICAgIHZhciBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW2lkXTtcblxuICAgICAgICBwbG90aW5mby5wbG90Z3JvdXAgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIG1ha2VTdWJwbG90TGF5ZXIoZ2QsIHBsb3RpbmZvKTtcblxuICAgICAgICAvLyBtYWtlIHNlcGFyYXRlIGRyYWcgbGF5ZXJzIGZvciBlYWNoIHN1YnBsb3QsXG4gICAgICAgIC8vIGJ1dCBhcHBlbmQgdGhlbSB0byBwYXBlciByYXRoZXIgdGhhbiB0aGUgcGxvdCBncm91cHMsXG4gICAgICAgIC8vIHNvIHRoZXkgZW5kIHVwIG9uIHRvcCBvZiB0aGUgcmVzdFxuICAgICAgICBwbG90aW5mby5kcmFnbGF5ZXIgPSBlbnN1cmVTaW5nbGUoZnVsbExheW91dC5fZHJhZ2dlcnMsICdnJywgaWQpO1xuICAgIH0pO1xufTtcblxuZXhwb3J0cy5yYW5nZVBsb3QgPSBmdW5jdGlvbihnZCwgcGxvdGluZm8sIGNkU3VicGxvdCkge1xuICAgIG1ha2VTdWJwbG90TGF5ZXIoZ2QsIHBsb3RpbmZvKTtcbiAgICBwbG90T25lKGdkLCBwbG90aW5mbywgY2RTdWJwbG90KTtcbiAgICBQbG90cy5zdHlsZShnZCk7XG59O1xuXG5mdW5jdGlvbiBtYWtlU3VicGxvdERhdGEoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBpZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90cy5jYXJ0ZXNpYW47XG4gICAgdmFyIGxlbiA9IGlkcy5sZW5ndGg7XG4gICAgdmFyIGksIGosIGlkLCBwbG90aW5mbywgeGEsIHlhO1xuXG4gICAgLy8gc3BsaXQgJ3JlZ3VsYXInIGFuZCAnb3ZlcmxheWluZycgc3VicGxvdHNcbiAgICB2YXIgcmVndWxhcnMgPSBbXTtcbiAgICB2YXIgb3ZlcmxheXMgPSBbXTtcblxuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlkID0gaWRzW2ldO1xuICAgICAgICBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW2lkXTtcbiAgICAgICAgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICAgICAgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgICAgICB2YXIgeGEyID0geGEuX21haW5BeGlzO1xuICAgICAgICB2YXIgeWEyID0geWEuX21haW5BeGlzO1xuICAgICAgICB2YXIgbWFpbnBsb3QgPSB4YTIuX2lkICsgeWEyLl9pZDtcbiAgICAgICAgdmFyIG1haW5wbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW21haW5wbG90XTtcbiAgICAgICAgcGxvdGluZm8ub3ZlcmxheXMgPSBbXTtcblxuICAgICAgICBpZihtYWlucGxvdCAhPT0gaWQgJiYgbWFpbnBsb3RpbmZvKSB7XG4gICAgICAgICAgICBwbG90aW5mby5tYWlucGxvdCA9IG1haW5wbG90O1xuICAgICAgICAgICAgcGxvdGluZm8ubWFpbnBsb3RpbmZvID0gbWFpbnBsb3RpbmZvO1xuICAgICAgICAgICAgb3ZlcmxheXMucHVzaChpZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwbG90aW5mby5tYWlucGxvdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHBsb3RpbmZvLm1haW5QbG90aW5mbyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHJlZ3VsYXJzLnB1c2goaWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZmlsbCBpbiBsaXN0IG9mIG92ZXJsYXlpbmcgc3VicGxvdHMgaW4gJ21haW4gcGxvdCdcbiAgICBmb3IoaSA9IDA7IGkgPCBvdmVybGF5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZCA9IG92ZXJsYXlzW2ldO1xuICAgICAgICBwbG90aW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW2lkXTtcbiAgICAgICAgcGxvdGluZm8ubWFpbnBsb3RpbmZvLm92ZXJsYXlzLnB1c2gocGxvdGluZm8pO1xuICAgIH1cblxuICAgIC8vIHB1dCAncmVndWxhcicgc3VicGxvdCBkYXRhIGJlZm9yZSAnb3ZlcmxheWluZydcbiAgICB2YXIgc3VicGxvdElkcyA9IHJlZ3VsYXJzLmNvbmNhdChvdmVybGF5cyk7XG4gICAgdmFyIHN1YnBsb3REYXRhID0gbmV3IEFycmF5KGxlbik7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBpZCA9IHN1YnBsb3RJZHNbaV07XG4gICAgICAgIHBsb3RpbmZvID0gZnVsbExheW91dC5fcGxvdHNbaWRdO1xuICAgICAgICB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgICAgICB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgICAgIC8vIHVzZSBpbmZvIGFib3V0IGF4aXMgbGF5ZXIgYW5kIG92ZXJsYXlpbmcgcGF0dGVyblxuICAgICAgICAvLyB0byBjbGVhbiB3aGF0IG5lZWQgdG8gYmUgY2xlYW5lZCB1cCBpbiBleGl0IHNlbGVjdGlvblxuICAgICAgICB2YXIgZCA9IFtpZCwgeGEubGF5ZXIsIHlhLmxheWVyLCB4YS5vdmVybGF5aW5nIHx8ICcnLCB5YS5vdmVybGF5aW5nIHx8ICcnXTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgcGxvdGluZm8ub3ZlcmxheXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGQucHVzaChwbG90aW5mby5vdmVybGF5c1tqXS5pZCk7XG4gICAgICAgIH1cbiAgICAgICAgc3VicGxvdERhdGFbaV0gPSBkO1xuICAgIH1cblxuICAgIHJldHVybiBzdWJwbG90RGF0YTtcbn1cblxuZnVuY3Rpb24gbWFrZVN1YnBsb3RMYXllcihnZCwgcGxvdGluZm8pIHtcbiAgICB2YXIgcGxvdGdyb3VwID0gcGxvdGluZm8ucGxvdGdyb3VwO1xuICAgIHZhciBpZCA9IHBsb3RpbmZvLmlkO1xuICAgIHZhciB4TGF5ZXIgPSBjb25zdGFudHMubGF5ZXJWYWx1ZTJsYXllckNsYXNzW3Bsb3RpbmZvLnhheGlzLmxheWVyXTtcbiAgICB2YXIgeUxheWVyID0gY29uc3RhbnRzLmxheWVyVmFsdWUybGF5ZXJDbGFzc1twbG90aW5mby55YXhpcy5sYXllcl07XG4gICAgdmFyIGhhc09ubHlMYXJnZVNwbG9tcyA9IGdkLl9mdWxsTGF5b3V0Ll9oYXNPbmx5TGFyZ2VTcGxvbXM7XG5cbiAgICBpZighcGxvdGluZm8ubWFpbnBsb3QpIHtcbiAgICAgICAgaWYoaGFzT25seUxhcmdlU3Bsb21zKSB7XG4gICAgICAgICAgICAvLyBUT0RPIGNvdWxkIGRvIGV2ZW4gYmV0dGVyXG4gICAgICAgICAgICAvLyAtIHdlIGRvbid0IG5lZWQgcGxvdCAoYnV0IHdlIHdvdWxkIGhhdmUgdG8gbW9jayBpdCBpbiBsc0lubmVyXG4gICAgICAgICAgICAvLyAgIGFuZCBvdGhlciBwbGFjZXNcbiAgICAgICAgICAgIC8vIC0gd2UgZG9uJ3QgKHh8eSlsaW5lcyBhbmQgKHh8eSlheGlzbGF5ZXIgZm9yIG1vc3Qgc3VicGxvdHNcbiAgICAgICAgICAgIC8vICAgdXN1YWxseSBqdXN0IHRoZSBib3R0b20geCBhbmQgbGVmdCB5IGF4ZXMuXG4gICAgICAgICAgICBwbG90aW5mby54bGluZXMgPSBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAncGF0aCcsICd4bGluZXMtYWJvdmUnKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLnlsaW5lcyA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdwYXRoJywgJ3lsaW5lcy1hYm92ZScpO1xuICAgICAgICAgICAgcGxvdGluZm8ueGF4aXNsYXllciA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ3hheGlzbGF5ZXItYWJvdmUnKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLnlheGlzbGF5ZXIgPSBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICd5YXhpc2xheWVyLWFib3ZlJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgYmFja0xheWVyID0gZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAnbGF5ZXItc3VicGxvdCcpO1xuICAgICAgICAgICAgcGxvdGluZm8uc2hhcGVsYXllciA9IGVuc3VyZVNpbmdsZShiYWNrTGF5ZXIsICdnJywgJ3NoYXBlbGF5ZXInKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLmltYWdlbGF5ZXIgPSBlbnN1cmVTaW5nbGUoYmFja0xheWVyLCAnZycsICdpbWFnZWxheWVyJyk7XG5cbiAgICAgICAgICAgIHBsb3RpbmZvLmdyaWRsYXllciA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2dyaWRsYXllcicpO1xuICAgICAgICAgICAgcGxvdGluZm8uemVyb2xpbmVsYXllciA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ3plcm9saW5lbGF5ZXInKTtcblxuICAgICAgICAgICAgZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ3BhdGgnLCAneGxpbmVzLWJlbG93Jyk7XG4gICAgICAgICAgICBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAncGF0aCcsICd5bGluZXMtYmVsb3cnKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLm92ZXJsaW5lc0JlbG93ID0gZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAnb3ZlcmxpbmVzLWJlbG93Jyk7XG5cbiAgICAgICAgICAgIGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ3hheGlzbGF5ZXItYmVsb3cnKTtcbiAgICAgICAgICAgIGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ3lheGlzbGF5ZXItYmVsb3cnKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLm92ZXJheGVzQmVsb3cgPSBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICdvdmVyYXhlcy1iZWxvdycpO1xuXG4gICAgICAgICAgICBwbG90aW5mby5wbG90ID0gZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAncGxvdCcpO1xuICAgICAgICAgICAgcGxvdGluZm8ub3ZlcnBsb3QgPSBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICdvdmVycGxvdCcpO1xuXG4gICAgICAgICAgICBwbG90aW5mby54bGluZXMgPSBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAncGF0aCcsICd4bGluZXMtYWJvdmUnKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLnlsaW5lcyA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdwYXRoJywgJ3lsaW5lcy1hYm92ZScpO1xuICAgICAgICAgICAgcGxvdGluZm8ub3ZlcmxpbmVzQWJvdmUgPSBlbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICdvdmVybGluZXMtYWJvdmUnKTtcblxuICAgICAgICAgICAgZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAneGF4aXNsYXllci1hYm92ZScpO1xuICAgICAgICAgICAgZW5zdXJlU2luZ2xlKHBsb3Rncm91cCwgJ2cnLCAneWF4aXNsYXllci1hYm92ZScpO1xuICAgICAgICAgICAgcGxvdGluZm8ub3ZlcmF4ZXNBYm92ZSA9IGVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ292ZXJheGVzLWFib3ZlJyk7XG5cbiAgICAgICAgICAgIC8vIHNldCByZWZzIHRvIGNvcnJlY3QgbGF5ZXJzIGFzIGRldGVybWluZWQgYnkgJ2F4aXMubGF5ZXInXG4gICAgICAgICAgICBwbG90aW5mby54bGluZXMgPSBwbG90Z3JvdXAuc2VsZWN0KCcueGxpbmVzLScgKyB4TGF5ZXIpO1xuICAgICAgICAgICAgcGxvdGluZm8ueWxpbmVzID0gcGxvdGdyb3VwLnNlbGVjdCgnLnlsaW5lcy0nICsgeUxheWVyKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLnhheGlzbGF5ZXIgPSBwbG90Z3JvdXAuc2VsZWN0KCcueGF4aXNsYXllci0nICsgeExheWVyKTtcbiAgICAgICAgICAgIHBsb3RpbmZvLnlheGlzbGF5ZXIgPSBwbG90Z3JvdXAuc2VsZWN0KCcueWF4aXNsYXllci0nICsgeUxheWVyKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBtYWlucGxvdGluZm8gPSBwbG90aW5mby5tYWlucGxvdGluZm87XG4gICAgICAgIHZhciBtYWlucGxvdGdyb3VwID0gbWFpbnBsb3RpbmZvLnBsb3Rncm91cDtcbiAgICAgICAgdmFyIHhJZCA9IGlkICsgJy14JztcbiAgICAgICAgdmFyIHlJZCA9IGlkICsgJy15JztcblxuICAgICAgICAvLyBub3cgbWFrZSB0aGUgY29tcG9uZW50cyBvZiBvdmVybGFpZCBzdWJwbG90c1xuICAgICAgICAvLyBvdmVybGF5cyBkb24ndCBoYXZlIGJhY2tncm91bmRzLCBhbmQgYXBwZW5kIGFsbFxuICAgICAgICAvLyB0aGVpciBvdGhlciBjb21wb25lbnRzIHRvIHRoZSBjb3JyZXNwb25kaW5nXG4gICAgICAgIC8vIGV4dHJhIGdyb3VwcyBvZiB0aGVpciBtYWluIHBsb3RzLlxuXG4gICAgICAgIHBsb3RpbmZvLmdyaWRsYXllciA9IG1haW5wbG90aW5mby5ncmlkbGF5ZXI7XG4gICAgICAgIHBsb3RpbmZvLnplcm9saW5lbGF5ZXIgPSBtYWlucGxvdGluZm8uemVyb2xpbmVsYXllcjtcblxuICAgICAgICBlbnN1cmVTaW5nbGUobWFpbnBsb3RpbmZvLm92ZXJsaW5lc0JlbG93LCAncGF0aCcsIHhJZCk7XG4gICAgICAgIGVuc3VyZVNpbmdsZShtYWlucGxvdGluZm8ub3ZlcmxpbmVzQmVsb3csICdwYXRoJywgeUlkKTtcbiAgICAgICAgZW5zdXJlU2luZ2xlKG1haW5wbG90aW5mby5vdmVyYXhlc0JlbG93LCAnZycsIHhJZCk7XG4gICAgICAgIGVuc3VyZVNpbmdsZShtYWlucGxvdGluZm8ub3ZlcmF4ZXNCZWxvdywgJ2cnLCB5SWQpO1xuXG4gICAgICAgIHBsb3RpbmZvLnBsb3QgPSBlbnN1cmVTaW5nbGUobWFpbnBsb3RpbmZvLm92ZXJwbG90LCAnZycsIGlkKTtcblxuICAgICAgICBlbnN1cmVTaW5nbGUobWFpbnBsb3RpbmZvLm92ZXJsaW5lc0Fib3ZlLCAncGF0aCcsIHhJZCk7XG4gICAgICAgIGVuc3VyZVNpbmdsZShtYWlucGxvdGluZm8ub3ZlcmxpbmVzQWJvdmUsICdwYXRoJywgeUlkKTtcbiAgICAgICAgZW5zdXJlU2luZ2xlKG1haW5wbG90aW5mby5vdmVyYXhlc0Fib3ZlLCAnZycsIHhJZCk7XG4gICAgICAgIGVuc3VyZVNpbmdsZShtYWlucGxvdGluZm8ub3ZlcmF4ZXNBYm92ZSwgJ2cnLCB5SWQpO1xuXG4gICAgICAgIC8vIHNldCByZWZzIHRvIGNvcnJlY3QgbGF5ZXJzIGFzIGRldGVybWluZWQgYnkgJ2Fib3ZldHJhY2VzJ1xuICAgICAgICBwbG90aW5mby54bGluZXMgPSBtYWlucGxvdGdyb3VwLnNlbGVjdCgnLm92ZXJsaW5lcy0nICsgeExheWVyKS5zZWxlY3QoJy4nICsgeElkKTtcbiAgICAgICAgcGxvdGluZm8ueWxpbmVzID0gbWFpbnBsb3Rncm91cC5zZWxlY3QoJy5vdmVybGluZXMtJyArIHlMYXllcikuc2VsZWN0KCcuJyArIHlJZCk7XG4gICAgICAgIHBsb3RpbmZvLnhheGlzbGF5ZXIgPSBtYWlucGxvdGdyb3VwLnNlbGVjdCgnLm92ZXJheGVzLScgKyB4TGF5ZXIpLnNlbGVjdCgnLicgKyB4SWQpO1xuICAgICAgICBwbG90aW5mby55YXhpc2xheWVyID0gbWFpbnBsb3Rncm91cC5zZWxlY3QoJy5vdmVyYXhlcy0nICsgeUxheWVyKS5zZWxlY3QoJy4nICsgeUlkKTtcbiAgICB9XG5cbiAgICAvLyBjb21tb24gYXR0cmlidXRlcyBmb3IgYWxsIHN1YnBsb3RzLCBvdmVybGF5cyBvciBub3RcblxuICAgIGlmKCFoYXNPbmx5TGFyZ2VTcGxvbXMpIHtcbiAgICAgICAgZW5zdXJlU2luZ2xlQW5kQWRkRGF0dW0ocGxvdGluZm8uZ3JpZGxheWVyLCAnZycsIHBsb3RpbmZvLnhheGlzLl9pZCk7XG4gICAgICAgIGVuc3VyZVNpbmdsZUFuZEFkZERhdHVtKHBsb3RpbmZvLmdyaWRsYXllciwgJ2cnLCBwbG90aW5mby55YXhpcy5faWQpO1xuICAgICAgICBwbG90aW5mby5ncmlkbGF5ZXIuc2VsZWN0QWxsKCdnJylcbiAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24oZCkgeyByZXR1cm4gZFswXTsgfSlcbiAgICAgICAgICAgIC5zb3J0KGF4aXNJZHMuaWRTb3J0KTtcbiAgICB9XG5cbiAgICBwbG90aW5mby54bGluZXNcbiAgICAgICAgLnN0eWxlKCdmaWxsJywgJ25vbmUnKVxuICAgICAgICAuY2xhc3NlZCgnY3Jpc3AnLCB0cnVlKTtcblxuICAgIHBsb3RpbmZvLnlsaW5lc1xuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpXG4gICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIHRydWUpO1xufVxuXG5mdW5jdGlvbiBwdXJnZVN1YnBsb3RMYXllcnMobGF5ZXJzLCBmdWxsTGF5b3V0KSB7XG4gICAgaWYoIWxheWVycykgcmV0dXJuO1xuXG4gICAgdmFyIG92ZXJsYXlJZHNUb1JlbW92ZSA9IHt9O1xuXG4gICAgbGF5ZXJzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgaWQgPSBkWzBdO1xuICAgICAgICB2YXIgcGxvdGdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIHBsb3Rncm91cC5yZW1vdmUoKTtcbiAgICAgICAgcmVtb3ZlU3VicGxvdEV4dHJhcyhpZCwgZnVsbExheW91dCk7XG4gICAgICAgIG92ZXJsYXlJZHNUb1JlbW92ZVtpZF0gPSB0cnVlO1xuXG4gICAgICAgIC8vIGRvIG5vdCByZW1vdmUgaW5kaXZpZHVhbCBheGlzIDxjbGlwUGF0aD5zIGhlcmVcbiAgICAgICAgLy8gYXMgb3RoZXIgc3VicGxvdHMgbWF5IG5lZWQgdGhlbVxuICAgIH0pO1xuXG4gICAgLy8gbXVzdCByZW1vdmUgb3ZlcmxhaWQgc3VicGxvdCB0cmFjZSBsYXllcnMgJ21hbnVhbGx5J1xuXG4gICAgZm9yKHZhciBrIGluIGZ1bGxMYXlvdXQuX3Bsb3RzKSB7XG4gICAgICAgIHZhciBzdWJwbG90SW5mbyA9IGZ1bGxMYXlvdXQuX3Bsb3RzW2tdO1xuICAgICAgICB2YXIgb3ZlcmxheXMgPSBzdWJwbG90SW5mby5vdmVybGF5cyB8fCBbXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgb3ZlcmxheXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBvdmVybGF5SW5mbyA9IG92ZXJsYXlzW2pdO1xuXG4gICAgICAgICAgICBpZihvdmVybGF5SWRzVG9SZW1vdmVbb3ZlcmxheUluZm8uaWRdKSB7XG4gICAgICAgICAgICAgICAgb3ZlcmxheUluZm8ucGxvdC5zZWxlY3RBbGwoJy50cmFjZScpLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVTdWJwbG90RXh0cmFzKHN1YnBsb3RJZCwgZnVsbExheW91dCkge1xuICAgIGZ1bGxMYXlvdXQuX2RyYWdnZXJzLnNlbGVjdEFsbCgnZy4nICsgc3VicGxvdElkKS5yZW1vdmUoKTtcbiAgICBmdWxsTGF5b3V0Ll9kZWZzLnNlbGVjdCgnI2NsaXAnICsgZnVsbExheW91dC5fdWlkICsgc3VicGxvdElkICsgJ3Bsb3QnKS5yZW1vdmUoKTtcbn1cblxuZXhwb3J0cy50b1NWRyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGltYWdlUm9vdCA9IGdkLl9mdWxsTGF5b3V0Ll9nbGltYWdlcztcbiAgICB2YXIgcm9vdCA9IGQzLnNlbGVjdChnZCkuc2VsZWN0QWxsKCcuc3ZnLWNvbnRhaW5lcicpO1xuICAgIHZhciBjYW52YXNlcyA9IHJvb3QuZmlsdGVyKGZ1bmN0aW9uKGQsIGkpIHtyZXR1cm4gaSA9PT0gcm9vdC5zaXplKCkgLSAxO30pXG4gICAgICAgIC5zZWxlY3RBbGwoJy5nbC1jYW52YXMtY29udGV4dCwgLmdsLWNhbnZhcy1mb2N1cycpO1xuXG4gICAgZnVuY3Rpb24gY2FudmFzVG9JbWFnZSgpIHtcbiAgICAgICAgdmFyIGNhbnZhcyA9IHRoaXM7XG4gICAgICAgIHZhciBpbWFnZURhdGEgPSBjYW52YXMudG9EYXRhVVJMKCdpbWFnZS9wbmcnKTtcbiAgICAgICAgdmFyIGltYWdlID0gaW1hZ2VSb290LmFwcGVuZCgnc3ZnOmltYWdlJyk7XG5cbiAgICAgICAgaW1hZ2UuYXR0cih7XG4gICAgICAgICAgICB4bWxuczogeG1sbnNOYW1lc3BhY2VzLnN2ZyxcbiAgICAgICAgICAgICd4bGluazpocmVmJzogaW1hZ2VEYXRhLFxuICAgICAgICAgICAgcHJlc2VydmVBc3BlY3RSYXRpbzogJ25vbmUnLFxuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICB3aWR0aDogY2FudmFzLndpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0OiBjYW52YXMuaGVpZ2h0XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGNhbnZhc2VzLmVhY2goY2FudmFzVG9JbWFnZSk7XG59O1xuXG5leHBvcnRzLnVwZGF0ZUZ4ID0gX2RlcmVxXygnLi9ncmFwaF9pbnRlcmFjdCcpLnVwZGF0ZUZ4O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzXCI6Njk2LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9nZXRfZGF0YVwiOjgwMixcIi4uL3Bsb3RzXCI6ODI4LFwiLi9hdHRyaWJ1dGVzXCI6NzY1LFwiLi9heGlzX2lkc1wiOjc3MCxcIi4vY29uc3RhbnRzXCI6NzczLFwiLi9ncmFwaF9pbnRlcmFjdFwiOjc3NixcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo3NzksXCIuL2xheW91dF9kZWZhdWx0c1wiOjc4MCxcIi4vdHJhbnNpdGlvbl9heGVzXCI6Nzg5LFwiZDNcIjoxNjN9XSw3Nzk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZm9udEF0dHJzID0gX2RlcmVxXygnLi4vZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGRhc2ggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcvYXR0cmlidXRlcycpLmRhc2g7XG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIHRlbXBsYXRlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG52YXIgRk9STUFUX0xJTksgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvZG9jcycpLkZPUk1BVF9MSU5LO1xudmFyIERBVEVfRk9STUFUX0xJTksgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvZG9jcycpLkRBVEVfRk9STUFUX0xJTks7XG5cbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB2aXNpYmxlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpdGxlOiB7XG4gICAgICAgIHRleHQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBmb250OiBmb250QXR0cnMoe1xuICAgICAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnXG4gICAgfSxcbiAgICB0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgLy8gJy0nIG1lYW5zIHdlIGhhdmVuJ3QgeWV0IHJ1biBhdXRvdHlwZSBvciBjb3VsZG4ndCBmaW5kIGFueSBkYXRhXG4gICAgICAgIC8vIGl0IGdldHMgdHVybmVkIGludG8gbGluZWFyIGluIGdkLl9mdWxsTGF5b3V0IGJ1dCBub3QgY29waWVkIGJhY2tcbiAgICAgICAgLy8gdG8gZ2QuZGF0YSBsaWtlIHRoZSBvdGhlcnMgYXJlLlxuICAgICAgICB2YWx1ZXM6IFsnLScsICdsaW5lYXInLCAnbG9nJywgJ2RhdGUnLCAnY2F0ZWdvcnknLCAnbXVsdGljYXRlZ29yeSddLFxuICAgICAgICBkZmx0OiAnLScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAvLyB3ZSBmb3JnZXQgd2hlbiBhbiBheGlzIGhhcyBiZWVuIGF1dG90eXBlZCwganVzdCB3cml0aW5nIHRoZSBhdXRvXG4gICAgICAgIC8vIHZhbHVlIGJhY2sgdG8gdGhlIGlucHV0IC0gc28gaXQgZG9lc24ndCBtYWtlIHNlbnNlIHRvIHRlbXBsYXRlIHRoaXMuXG4gICAgICAgIC8vIE5vdGU6IHdlIGRvIE5PVCBwcm9oaWJpdCB0aGlzIGluIGBjb2VyY2VgLCBzbyBpZiBzb21lb25lIGVudGVycyBhXG4gICAgICAgIC8vIHR5cGUgaW4gdGhlIHRlbXBsYXRlIGV4cGxpY2l0bHkgaXQgd2lsbCBiZSBob25vcmVkIGFzIHRoZSBkZWZhdWx0LlxuICAgICAgICBfbm9UZW1wbGF0aW5nOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGF1dG9yYW5nZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW3RydWUsIGZhbHNlLCAncmV2ZXJzZWQnXSxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnYXhyYW5nZScsXG4gICAgICAgIGltcGxpZWRFZGl0czogeydyYW5nZVswXSc6IHVuZGVmaW5lZCwgJ3JhbmdlWzFdJzogdW5kZWZpbmVkfSxcbiAgICAgICAgXG4gICAgfSxcbiAgICByYW5nZW1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbm9ybWFsJywgJ3RvemVybycsICdub25uZWdhdGl2ZSddLFxuICAgICAgICBkZmx0OiAnbm9ybWFsJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcmFuZ2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdheHJhbmdlJywgaW1wbGllZEVkaXRzOiB7J15hdXRvcmFuZ2UnOiBmYWxzZX0sIGFuaW06IHRydWV9LFxuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ2F4cmFuZ2UnLCBpbXBsaWVkRWRpdHM6IHsnXmF1dG9yYW5nZSc6IGZhbHNlfSwgYW5pbTogdHJ1ZX1cbiAgICAgICAgXSxcbiAgICAgICAgZWRpdFR5cGU6ICdheHJhbmdlJyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiB7J2F1dG9yYW5nZSc6IGZhbHNlfSxcbiAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBmaXhlZHJhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIHNjYWxlYW5jaG9yOiBub3QgdXNlZCBkaXJlY3RseSwganVzdCBwdXQgaGVyZSBmb3IgcmVmZXJlbmNlXG4gICAgLy8gdmFsdWVzIGFyZSBhbnkgb3Bwb3NpdGUtbGV0dGVyIGF4aXMgaWRcbiAgICBzY2FsZWFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgY29uc3RhbnRzLmlkUmVnZXgueC50b1N0cmluZygpLFxuICAgICAgICAgICAgY29uc3RhbnRzLmlkUmVnZXgueS50b1N0cmluZygpXG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNjYWxlcmF0aW86IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY29uc3RyYWluOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3JhbmdlJywgJ2RvbWFpbiddLFxuICAgICAgICBkZmx0OiAncmFuZ2UnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBjb25zdHJhaW50b3dhcmQ6IG5vdCB1c2VkIGRpcmVjdGx5LCBqdXN0IHB1dCBoZXJlIGZvciByZWZlcmVuY2VcbiAgICBjb25zdHJhaW50b3dhcmQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnLCAndG9wJywgJ21pZGRsZScsICdib3R0b20nXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbWF0Y2hlczoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgY29uc3RhbnRzLmlkUmVnZXgueC50b1N0cmluZygpLFxuICAgICAgICAgICAgY29uc3RhbnRzLmlkUmVnZXgueS50b1N0cmluZygpXG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIHRpY2tzXG4gICAgdGlja21vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYXV0bycsICdsaW5lYXInLCAnYXJyYXknXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBpbXBsaWVkRWRpdHM6IHt0aWNrMDogdW5kZWZpbmVkLCBkdGljazogdW5kZWZpbmVkfSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBudGlja3M6IHtcbiAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrMDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBpbXBsaWVkRWRpdHM6IHt0aWNrbW9kZTogJ2xpbmVhcid9LFxuICAgICAgICBcbiAgICB9LFxuICAgIGR0aWNrOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIGltcGxpZWRFZGl0czoge3RpY2ttb2RlOiAnbGluZWFyJ30sXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3ZhbHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrdGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ291dHNpZGUnLCAnaW5zaWRlJywgJyddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3Nvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydsYWJlbHMnLCAnYm91bmRhcmllcyddLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ2xhYmVscycsXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG1pcnJvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW3RydWUsICd0aWNrcycsIGZhbHNlLCAnYWxsJywgJ2FsbHRpY2tzJ10sXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcytsYXlvdXRzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja2xlbjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiA1LFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3dpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3d0aWNrbGFiZWxzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGF1dG9tYXJnaW46IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dzcGlrZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbW9kZWJhcicsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3Bpa2Vjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzcGlrZXRoaWNrbmVzczoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3Bpa2VkYXNoOiBleHRlbmRGbGF0KHt9LCBkYXNoLCB7ZGZsdDogJ2Rhc2gnLCBlZGl0VHlwZTogJ25vbmUnfSksXG4gICAgc3Bpa2Vtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdmbGFnbGlzdCcsXG4gICAgICAgIGZsYWdzOiBbJ3RvYXhpcycsICdhY3Jvc3MnLCAnbWFya2VyJ10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAndG9heGlzJyxcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzcGlrZXNuYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZGF0YScsICdjdXJzb3InXSxcbiAgICAgICAgZGZsdDogJ2RhdGEnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0pLFxuICAgIHRpY2thbmdsZToge1xuICAgICAgICB2YWxUeXBlOiAnYW5nbGUnLFxuICAgICAgICBkZmx0OiAnYXV0bycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrcHJlZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3d0aWNrcHJlZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FsbCcsICdmaXJzdCcsICdsYXN0JywgJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ2FsbCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrc3VmZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3d0aWNrc3VmZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FsbCcsICdmaXJzdCcsICdsYXN0JywgJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ2FsbCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93ZXhwb25lbnQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYWxsJywgJ2ZpcnN0JywgJ2xhc3QnLCAnbm9uZSddLFxuICAgICAgICBkZmx0OiAnYWxsJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGV4cG9uZW50Zm9ybWF0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ25vbmUnLCAnZScsICdFJywgJ3Bvd2VyJywgJ1NJJywgJ0InXSxcbiAgICAgICAgZGZsdDogJ0InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2VwYXJhdGV0aG91c2FuZHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tmb3JtYXQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICd0aWNrcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja2Zvcm1hdHN0b3BzOiB0ZW1wbGF0ZWRBcnJheSgndGlja2Zvcm1hdHN0b3AnLCB7XG4gICAgICAgIGVuYWJsZWQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGR0aWNrcmFuZ2U6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAndGlja3MnfSxcbiAgICAgICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAndGlja3MnfVxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJ1xuICAgIH0pLFxuICAgIGhvdmVyZm9ybWF0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgLy8gbGluZXMgYW5kIGdyaWRzXG4gICAgc2hvd2xpbmU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MrbGF5b3V0c3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxpbmVjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdsYXlvdXRzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGluZXdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzK2xheW91dHN0eWxlJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93Z3JpZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBncmlkY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5saWdodExpbmUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBncmlkd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHplcm9saW5lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHplcm9saW5lY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHplcm9saW5ld2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHNob3dkaXZpZGVyczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkaXZpZGVyY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRpdmlkZXJ3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIFRPRE8gZGl2aWRlcmxlbjogdGhhdCB3b3VsZCBvdmVycmlkZSBcInRvIGxhYmVsIGJhc2VcIiBsZW5ndGg/XG5cbiAgICAvLyBwb3NpdGlvbmluZyBhdHRyaWJ1dGVzXG4gICAgLy8gYW5jaG9yOiBub3QgdXNlZCBkaXJlY3RseSwganVzdCBwdXQgaGVyZSBmb3IgcmVmZXJlbmNlXG4gICAgLy8gdmFsdWVzIGFyZSBhbnkgb3Bwb3NpdGUtbGV0dGVyIGF4aXMgaWRcbiAgICBhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICdmcmVlJyxcbiAgICAgICAgICAgIGNvbnN0YW50cy5pZFJlZ2V4LngudG9TdHJpbmcoKSxcbiAgICAgICAgICAgIGNvbnN0YW50cy5pZFJlZ2V4LnkudG9TdHJpbmcoKVxuICAgICAgICBdLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBzaWRlOiBub3QgdXNlZCBkaXJlY3RseSwgYXMgdmFsdWVzIGRlcGVuZCBvbiBkaXJlY3Rpb25cbiAgICAvLyB2YWx1ZXMgYXJlIHRvcCwgYm90dG9tIGZvciB4IGF4ZXMsIGFuZCBsZWZ0LCByaWdodCBmb3IgeVxuICAgIHNpZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsndG9wJywgJ2JvdHRvbScsICdsZWZ0JywgJ3JpZ2h0J10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIG92ZXJsYXlpbmc6IG5vdCB1c2VkIGRpcmVjdGx5LCBqdXN0IHB1dCBoZXJlIGZvciByZWZlcmVuY2VcbiAgICAvLyB2YWx1ZXMgYXJlIGZhbHNlIGFuZCBhbnkgb3RoZXIgc2FtZS1sZXR0ZXIgYXhpcyBpZCB0aGF0J3Mgbm90XG4gICAgLy8gaXRzZWxmIG92ZXJsYXlpbmcgYW55dGhpbmdcbiAgICBvdmVybGF5aW5nOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAnZnJlZScsXG4gICAgICAgICAgICBjb25zdGFudHMuaWRSZWdleC54LnRvU3RyaW5nKCksXG4gICAgICAgICAgICBjb25zdGFudHMuaWRSZWdleC55LnRvU3RyaW5nKClcbiAgICAgICAgXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGF5ZXI6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYWJvdmUgdHJhY2VzJywgJ2JlbG93IHRyYWNlcyddLFxuICAgICAgICBkZmx0OiAnYWJvdmUgdHJhY2VzJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZG9tYWluOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIG1pbjogMCwgbWF4OiAxLCBlZGl0VHlwZTogJ3Bsb3QnfSxcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnbnVtYmVyJywgbWluOiAwLCBtYXg6IDEsIGVkaXRUeXBlOiAncGxvdCd9XG4gICAgICAgIF0sXG4gICAgICAgIGRmbHQ6IFswLCAxXSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBwb3NpdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNhdGVnb3J5b3JkZXI6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICd0cmFjZScsICdjYXRlZ29yeSBhc2NlbmRpbmcnLCAnY2F0ZWdvcnkgZGVzY2VuZGluZycsICdhcnJheScsXG4gICAgICAgICAgICAndG90YWwgYXNjZW5kaW5nJywgJ3RvdGFsIGRlc2NlbmRpbmcnLFxuICAgICAgICAgICAgJ21pbiBhc2NlbmRpbmcnLCAnbWluIGRlc2NlbmRpbmcnLFxuICAgICAgICAgICAgJ21heCBhc2NlbmRpbmcnLCAnbWF4IGRlc2NlbmRpbmcnLFxuICAgICAgICAgICAgJ3N1bSBhc2NlbmRpbmcnLCAnc3VtIGRlc2NlbmRpbmcnLFxuICAgICAgICAgICAgJ21lYW4gYXNjZW5kaW5nJywgJ21lYW4gZGVzY2VuZGluZycsXG4gICAgICAgICAgICAnbWVkaWFuIGFzY2VuZGluZycsICdtZWRpYW4gZGVzY2VuZGluZydcbiAgICAgICAgXSxcbiAgICAgICAgZGZsdDogJ3RyYWNlJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY2F0ZWdvcnlhcnJheToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHVpcmV2aXNpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVkaXRUeXBlOiAnY2FsYycsXG5cbiAgICBfZGVwcmVjYXRlZDoge1xuICAgICAgICBhdXRvdGljazoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3RpY2tzJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB0aXRsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHRpdGxlZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgICAgIGVkaXRUeXBlOiAndGlja3MnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXNcIjo1OTIsXCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcvYXR0cmlidXRlc1wiOjYxMyxcIi4uLy4uL2NvbnN0YW50cy9kb2NzXCI6NjkwLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi9mb250X2F0dHJpYnV0ZXNcIjo3OTMsXCIuL2NvbnN0YW50c1wiOjc3M31dLDc4MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIFRlbXBsYXRlID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xudmFyIGJhc2VQbG90TGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4uL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZVR5cGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4vdHlwZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUF4aXNEZWZhdWx0cyA9IF9kZXJlcV8oJy4vYXhpc19kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNvbnN0cmFpbnREZWZhdWx0cyA9IF9kZXJlcV8oJy4vY29uc3RyYWludHMnKS5oYW5kbGVDb25zdHJhaW50RGVmYXVsdHM7XG52YXIgaGFuZGxlUG9zaXRpb25EZWZhdWx0cyA9IF9kZXJlcV8oJy4vcG9zaXRpb25fZGVmYXVsdHMnKTtcblxudmFyIGF4aXNJZHMgPSBfZGVyZXFfKCcuL2F4aXNfaWRzJyk7XG52YXIgaWQybmFtZSA9IGF4aXNJZHMuaWQybmFtZTtcbnZhciBuYW1lMmlkID0gYXhpc0lkcy5uYW1lMmlkO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIHRyYWNlSXMgPSBSZWdpc3RyeS50cmFjZUlzO1xudmFyIGdldENvbXBvbmVudE1ldGhvZCA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZDtcblxuZnVuY3Rpb24gYXBwZW5kTGlzdChjb250LCBrLCBpdGVtKSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheShjb250W2tdKSkgY29udFtrXS5wdXNoKGl0ZW0pO1xuICAgIGVsc2UgY29udFtrXSA9IFtpdGVtXTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSkge1xuICAgIHZhciBheDJ0cmFjZXMgPSB7fTtcbiAgICB2YXIgeGFNYXlIaWRlID0ge307XG4gICAgdmFyIHlhTWF5SGlkZSA9IHt9O1xuICAgIHZhciB4YU11c3REaXNwbGF5ID0ge307XG4gICAgdmFyIHlhTXVzdERpc3BsYXkgPSB7fTtcbiAgICB2YXIgeWFNdXN0Rm9yd2FyZCA9IHt9O1xuICAgIHZhciB5YU1heUJhY2t3YXJkID0ge307XG4gICAgdmFyIG91dGVyVGlja3MgPSB7fTtcbiAgICB2YXIgbm9HcmlkcyA9IHt9O1xuICAgIHZhciBpLCBqO1xuXG4gICAgLy8gbG9vayBmb3IgYXhlcyBpbiB0aGUgZGF0YVxuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICBpZighdHJhY2VJcyh0cmFjZSwgJ2NhcnRlc2lhbicpICYmICF0cmFjZUlzKHRyYWNlLCAnZ2wyZCcpKSBjb250aW51ZTtcblxuICAgICAgICB2YXIgeGFOYW1lO1xuICAgICAgICBpZih0cmFjZS54YXhpcykge1xuICAgICAgICAgICAgeGFOYW1lID0gaWQybmFtZSh0cmFjZS54YXhpcyk7XG4gICAgICAgICAgICBhcHBlbmRMaXN0KGF4MnRyYWNlcywgeGFOYW1lLCB0cmFjZSk7XG4gICAgICAgIH0gZWxzZSBpZih0cmFjZS54YXhlcykge1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgdHJhY2UueGF4ZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBhcHBlbmRMaXN0KGF4MnRyYWNlcywgaWQybmFtZSh0cmFjZS54YXhlc1tqXSksIHRyYWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB5YU5hbWU7XG4gICAgICAgIGlmKHRyYWNlLnlheGlzKSB7XG4gICAgICAgICAgICB5YU5hbWUgPSBpZDJuYW1lKHRyYWNlLnlheGlzKTtcbiAgICAgICAgICAgIGFwcGVuZExpc3QoYXgydHJhY2VzLCB5YU5hbWUsIHRyYWNlKTtcbiAgICAgICAgfSBlbHNlIGlmKHRyYWNlLnlheGVzKSB7XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCB0cmFjZS55YXhlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGFwcGVuZExpc3QoYXgydHJhY2VzLCBpZDJuYW1lKHRyYWNlLnlheGVzW2pdKSwgdHJhY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gbG9naWMgZm9yIGZ1bm5lbHNcbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2Z1bm5lbCcpIHtcbiAgICAgICAgICAgIGlmKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgICAgICAgICBpZih4YU5hbWUpIHhhTWF5SGlkZVt4YU5hbWVdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZih5YU5hbWUpIHlhTWF5QmFja3dhcmRbeWFOYW1lXSA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmKHlhTmFtZSkgeWFNYXlIaWRlW3lhTmFtZV0gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYoeWFOYW1lKSB7XG4gICAgICAgICAgICAgICAgeWFNdXN0RGlzcGxheVt5YU5hbWVdID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB5YU11c3RGb3J3YXJkW3lhTmFtZV0gPSB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZighdHJhY2VJcyh0cmFjZSwgJ2NhcnBldCcpIHx8ICh0cmFjZS50eXBlID09PSAnY2FycGV0JyAmJiAhdHJhY2UuX2NoZWF0ZXIpKSB7XG4gICAgICAgICAgICAgICAgaWYoeGFOYW1lKSB4YU11c3REaXNwbGF5W3hhTmFtZV0gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHdvIHRoaW5ncyB0cmlnZ2VyIGF4aXMgdmlzaWJpbGl0eTpcbiAgICAgICAgLy8gMS4gaXMgbm90IGNhcnBldFxuICAgICAgICAvLyAyLiBjYXJwZXQgdGhhdCdzIG5vdCBjaGVhdGVyXG5cbiAgICAgICAgLy8gVGhlIGFib3ZlIGNoZWNrIGZvciBkZWZpbml0ZWx5LW5vdC1jaGVhdGVyIGlzIG5vdCBhZGVxdWF0ZS4gVGhpc1xuICAgICAgICAvLyBzZWNvbmQgbGlzdCB0cmFja3Mgd2hpY2ggYXhlcyAqY291bGQqIGJlIGEgY2hlYXRlciBzbyB0aGF0IHRoZVxuICAgICAgICAvLyBmdWxsIGNvbmRpdGlvbiB0cmlnZ2VyaW5nIGhpZGluZyBpczpcbiAgICAgICAgLy8gICAqY291bGQqIGJlIGEgY2hlYXRlciBhbmQgKmlzIG5vdCBkZWZpbml0ZWx5IHZpc2libGUqXG4gICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdjYXJwZXQnICYmIHRyYWNlLl9jaGVhdGVyKSB7XG4gICAgICAgICAgICBpZih4YU5hbWUpIHhhTWF5SGlkZVt4YU5hbWVdID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNoZWNrIGZvciBkZWZhdWx0IGZvcm1hdHRpbmcgdHdlYWtzXG4gICAgICAgIGlmKHRyYWNlSXModHJhY2UsICcyZE1hcCcpKSB7XG4gICAgICAgICAgICBvdXRlclRpY2tzW3hhTmFtZV0gPSB0cnVlO1xuICAgICAgICAgICAgb3V0ZXJUaWNrc1t5YU5hbWVdID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRyYWNlSXModHJhY2UsICdvcmllbnRlZCcpKSB7XG4gICAgICAgICAgICB2YXIgcG9zaXRpb25BeGlzID0gdHJhY2Uub3JpZW50YXRpb24gPT09ICdoJyA/IHlhTmFtZSA6IHhhTmFtZTtcbiAgICAgICAgICAgIG5vR3JpZHNbcG9zaXRpb25BeGlzXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc3VicGxvdHMgPSBsYXlvdXRPdXQuX3N1YnBsb3RzO1xuICAgIHZhciB4SWRzID0gc3VicGxvdHMueGF4aXM7XG4gICAgdmFyIHlJZHMgPSBzdWJwbG90cy55YXhpcztcbiAgICB2YXIgeE5hbWVzID0gTGliLnNpbXBsZU1hcCh4SWRzLCBpZDJuYW1lKTtcbiAgICB2YXIgeU5hbWVzID0gTGliLnNpbXBsZU1hcCh5SWRzLCBpZDJuYW1lKTtcbiAgICB2YXIgYXhOYW1lcyA9IHhOYW1lcy5jb25jYXQoeU5hbWVzKTtcblxuICAgIC8vIHBsb3RfYmdjb2xvciBvbmx5IG1ha2VzIHNlbnNlIGlmIHRoZXJlJ3MgYSAoMkQpIHBsb3QhXG4gICAgLy8gVE9ETzogYmdjb2xvciBmb3IgZWFjaCBzdWJwbG90LCB0byBpbmhlcml0IGZyb20gdGhlIG1haW4gb25lXG4gICAgdmFyIHBsb3RCZ0NvbG9yID0gQ29sb3IuYmFja2dyb3VuZDtcbiAgICBpZih4SWRzLmxlbmd0aCAmJiB5SWRzLmxlbmd0aCkge1xuICAgICAgICBwbG90QmdDb2xvciA9IExpYi5jb2VyY2UobGF5b3V0SW4sIGxheW91dE91dCwgYmFzZVBsb3RMYXlvdXRBdHRyaWJ1dGVzLCAncGxvdF9iZ2NvbG9yJyk7XG4gICAgfVxuXG4gICAgdmFyIGJnQ29sb3IgPSBDb2xvci5jb21iaW5lKHBsb3RCZ0NvbG9yLCBsYXlvdXRPdXQucGFwZXJfYmdjb2xvcik7XG5cbiAgICB2YXIgYXhOYW1lLCBheExldHRlciwgYXhMYXlvdXRJbiwgYXhMYXlvdXRPdXQ7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShheExheW91dEluLCBheExheW91dE91dCwgbGF5b3V0QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29lcmNlMihhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlMihheExheW91dEluLCBheExheW91dE91dCwgbGF5b3V0QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q291bnRlckF4ZXMoYXhMZXR0ZXIpIHtcbiAgICAgICAgcmV0dXJuIChheExldHRlciA9PT0gJ3gnKSA/IHlJZHMgOiB4SWRzO1xuICAgIH1cblxuICAgIHZhciBjb3VudGVyQXhlcyA9IHt4OiBnZXRDb3VudGVyQXhlcygneCcpLCB5OiBnZXRDb3VudGVyQXhlcygneScpfTtcbiAgICB2YXIgYWxsQXhpc0lkcyA9IGNvdW50ZXJBeGVzLnguY29uY2F0KGNvdW50ZXJBeGVzLnkpO1xuXG4gICAgZnVuY3Rpb24gZ2V0T3ZlcmxheWFibGVBeGVzKGF4TGV0dGVyLCBheE5hbWUpIHtcbiAgICAgICAgdmFyIGxpc3QgPSAoYXhMZXR0ZXIgPT09ICd4JykgPyB4TmFtZXMgOiB5TmFtZXM7XG4gICAgICAgIHZhciBvdXQgPSBbXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgbGlzdC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGF4TmFtZTIgPSBsaXN0W2pdO1xuXG4gICAgICAgICAgICBpZihheE5hbWUyICE9PSBheE5hbWUgJiYgIShsYXlvdXRJbltheE5hbWUyXSB8fCB7fSkub3ZlcmxheWluZykge1xuICAgICAgICAgICAgICAgIG91dC5wdXNoKG5hbWUyaWQoYXhOYW1lMikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICAvLyBmaXJzdCBwYXNzIGNyZWF0ZXMgdGhlIGNvbnRhaW5lcnMsIGRldGVybWluZXMgdHlwZXMsIGFuZCBoYW5kbGVzIG1vc3Qgb2YgdGhlIHNldHRpbmdzXG4gICAgZm9yKGkgPSAwOyBpIDwgYXhOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBheE5hbWUgPSBheE5hbWVzW2ldO1xuICAgICAgICBheExldHRlciA9IGF4TmFtZS5jaGFyQXQoMCk7XG5cbiAgICAgICAgaWYoIUxpYi5pc1BsYWluT2JqZWN0KGxheW91dEluW2F4TmFtZV0pKSB7XG4gICAgICAgICAgICBsYXlvdXRJbltheE5hbWVdID0ge307XG4gICAgICAgIH1cblxuICAgICAgICBheExheW91dEluID0gbGF5b3V0SW5bYXhOYW1lXTtcbiAgICAgICAgYXhMYXlvdXRPdXQgPSBUZW1wbGF0ZS5uZXdDb250YWluZXIobGF5b3V0T3V0LCBheE5hbWUsIGF4TGV0dGVyICsgJ2F4aXMnKTtcblxuICAgICAgICB2YXIgdHJhY2VzID0gYXgydHJhY2VzW2F4TmFtZV0gfHwgW107XG4gICAgICAgIGF4TGF5b3V0T3V0Ll90cmFjZUluZGljZXMgPSB0cmFjZXMubWFwKGZ1bmN0aW9uKHQpIHsgcmV0dXJuIHQuX2V4cGFuZGVkSW5kZXg7IH0pO1xuICAgICAgICBheExheW91dE91dC5fYW5uSW5kaWNlcyA9IFtdO1xuICAgICAgICBheExheW91dE91dC5fc2hhcGVJbmRpY2VzID0gW107XG4gICAgICAgIGF4TGF5b3V0T3V0Ll9pbWdJbmRpY2VzID0gW107XG4gICAgICAgIGF4TGF5b3V0T3V0Ll9zdWJwbG90c1dpdGggPSBbXTtcbiAgICAgICAgYXhMYXlvdXRPdXQuX2NvdW50ZXJBeGVzID0gW107XG5cbiAgICAgICAgLy8gc2V0IHVwIHNvbWUgcHJpdmF0ZSBwcm9wZXJ0aWVzXG4gICAgICAgIGF4TGF5b3V0T3V0Ll9uYW1lID0gYXhMYXlvdXRPdXQuX2F0dHIgPSBheE5hbWU7XG4gICAgICAgIHZhciBpZCA9IGF4TGF5b3V0T3V0Ll9pZCA9IG5hbWUyaWQoYXhOYW1lKTtcblxuICAgICAgICB2YXIgb3ZlcmxheWFibGVBeGVzID0gZ2V0T3ZlcmxheWFibGVBeGVzKGF4TGV0dGVyLCBheE5hbWUpO1xuXG4gICAgICAgIHZhciB2aXNpYmxlRGZsdCA9XG4gICAgICAgICAgICAoYXhMZXR0ZXIgPT09ICd4JyAmJiAheGFNdXN0RGlzcGxheVtheE5hbWVdICYmIHhhTWF5SGlkZVtheE5hbWVdKSB8fFxuICAgICAgICAgICAgKGF4TGV0dGVyID09PSAneScgJiYgIXlhTXVzdERpc3BsYXlbYXhOYW1lXSAmJiB5YU1heUhpZGVbYXhOYW1lXSk7XG5cbiAgICAgICAgdmFyIHJldmVyc2VEZmx0ID1cbiAgICAgICAgICAgIChheExldHRlciA9PT0gJ3knICYmICF5YU11c3RGb3J3YXJkW2F4TmFtZV0gJiYgeWFNYXlCYWNrd2FyZFtheE5hbWVdKTtcblxuICAgICAgICB2YXIgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgICAgICAgICBsZXR0ZXI6IGF4TGV0dGVyLFxuICAgICAgICAgICAgZm9udDogbGF5b3V0T3V0LmZvbnQsXG4gICAgICAgICAgICBvdXRlclRpY2tzOiBvdXRlclRpY2tzW2F4TmFtZV0sXG4gICAgICAgICAgICBzaG93R3JpZDogIW5vR3JpZHNbYXhOYW1lXSxcbiAgICAgICAgICAgIGRhdGE6IHRyYWNlcyxcbiAgICAgICAgICAgIGJnQ29sb3I6IGJnQ29sb3IsXG4gICAgICAgICAgICBjYWxlbmRhcjogbGF5b3V0T3V0LmNhbGVuZGFyLFxuICAgICAgICAgICAgYXV0b21hcmdpbjogdHJ1ZSxcbiAgICAgICAgICAgIHZpc2libGVEZmx0OiB2aXNpYmxlRGZsdCxcbiAgICAgICAgICAgIHJldmVyc2VEZmx0OiByZXZlcnNlRGZsdCxcbiAgICAgICAgICAgIHNwbG9tU3Rhc2g6ICgobGF5b3V0T3V0Ll9zcGxvbUF4ZXMgfHwge30pW2F4TGV0dGVyXSB8fCB7fSlbaWRdXG4gICAgICAgIH07XG5cbiAgICAgICAgY29lcmNlKCd1aXJldmlzaW9uJywgbGF5b3V0T3V0LnVpcmV2aXNpb24pO1xuXG4gICAgICAgIGhhbmRsZVR5cGVEZWZhdWx0cyhheExheW91dEluLCBheExheW91dE91dCwgY29lcmNlLCBkZWZhdWx0T3B0aW9ucyk7XG4gICAgICAgIGhhbmRsZUF4aXNEZWZhdWx0cyhheExheW91dEluLCBheExheW91dE91dCwgY29lcmNlLCBkZWZhdWx0T3B0aW9ucywgbGF5b3V0T3V0KTtcblxuICAgICAgICB2YXIgc3Bpa2Vjb2xvciA9IGNvZXJjZTIoJ3NwaWtlY29sb3InKTtcbiAgICAgICAgdmFyIHNwaWtldGhpY2tuZXNzID0gY29lcmNlMignc3Bpa2V0aGlja25lc3MnKTtcbiAgICAgICAgdmFyIHNwaWtlZGFzaCA9IGNvZXJjZTIoJ3NwaWtlZGFzaCcpO1xuICAgICAgICB2YXIgc3Bpa2Vtb2RlID0gY29lcmNlMignc3Bpa2Vtb2RlJyk7XG4gICAgICAgIHZhciBzcGlrZXNuYXAgPSBjb2VyY2UyKCdzcGlrZXNuYXAnKTtcbiAgICAgICAgdmFyIHNob3dTcGlrZXMgPSBjb2VyY2UoJ3Nob3dzcGlrZXMnLCAhIXNwaWtlY29sb3IgfHwgISFzcGlrZXRoaWNrbmVzcyB8fCAhIXNwaWtlZGFzaCB8fCAhIXNwaWtlbW9kZSB8fCAhIXNwaWtlc25hcCk7XG5cbiAgICAgICAgaWYoIXNob3dTcGlrZXMpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBheExheW91dE91dC5zcGlrZWNvbG9yO1xuICAgICAgICAgICAgZGVsZXRlIGF4TGF5b3V0T3V0LnNwaWtldGhpY2tuZXNzO1xuICAgICAgICAgICAgZGVsZXRlIGF4TGF5b3V0T3V0LnNwaWtlZGFzaDtcbiAgICAgICAgICAgIGRlbGV0ZSBheExheW91dE91dC5zcGlrZW1vZGU7XG4gICAgICAgICAgICBkZWxldGUgYXhMYXlvdXRPdXQuc3Bpa2VzbmFwO1xuICAgICAgICB9XG5cbiAgICAgICAgaGFuZGxlUG9zaXRpb25EZWZhdWx0cyhheExheW91dEluLCBheExheW91dE91dCwgY29lcmNlLCB7XG4gICAgICAgICAgICBsZXR0ZXI6IGF4TGV0dGVyLFxuICAgICAgICAgICAgY291bnRlckF4ZXM6IGNvdW50ZXJBeGVzW2F4TGV0dGVyXSxcbiAgICAgICAgICAgIG92ZXJsYXlhYmxlQXhlczogb3ZlcmxheWFibGVBeGVzLFxuICAgICAgICAgICAgZ3JpZDogbGF5b3V0T3V0LmdyaWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXhMYXlvdXRPdXQuX2lucHV0ID0gYXhMYXlvdXRJbjtcbiAgICB9XG5cbiAgICAvLyBxdWljayBzZWNvbmQgcGFzcyBmb3IgcmFuZ2Ugc2xpZGVyIGFuZCBzZWxlY3RvciBkZWZhdWx0c1xuICAgIHZhciByYW5nZVNsaWRlckRlZmF1bHRzID0gZ2V0Q29tcG9uZW50TWV0aG9kKCdyYW5nZXNsaWRlcicsICdoYW5kbGVEZWZhdWx0cycpO1xuICAgIHZhciByYW5nZVNlbGVjdG9yRGVmYXVsdHMgPSBnZXRDb21wb25lbnRNZXRob2QoJ3Jhbmdlc2VsZWN0b3InLCAnaGFuZGxlRGVmYXVsdHMnKTtcblxuICAgIGZvcihpID0gMDsgaSA8IHhOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBheE5hbWUgPSB4TmFtZXNbaV07XG4gICAgICAgIGF4TGF5b3V0SW4gPSBsYXlvdXRJbltheE5hbWVdO1xuICAgICAgICBheExheW91dE91dCA9IGxheW91dE91dFtheE5hbWVdO1xuXG4gICAgICAgIHJhbmdlU2xpZGVyRGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgYXhOYW1lKTtcblxuICAgICAgICBpZihheExheW91dE91dC50eXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgICAgIHJhbmdlU2VsZWN0b3JEZWZhdWx0cyhcbiAgICAgICAgICAgICAgICBheExheW91dEluLFxuICAgICAgICAgICAgICAgIGF4TGF5b3V0T3V0LFxuICAgICAgICAgICAgICAgIGxheW91dE91dCxcbiAgICAgICAgICAgICAgICB5TmFtZXMsXG4gICAgICAgICAgICAgICAgYXhMYXlvdXRPdXQuY2FsZW5kYXJcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb2VyY2UoJ2ZpeGVkcmFuZ2UnKTtcbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCB5TmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXhOYW1lID0geU5hbWVzW2ldO1xuICAgICAgICBheExheW91dEluID0gbGF5b3V0SW5bYXhOYW1lXTtcbiAgICAgICAgYXhMYXlvdXRPdXQgPSBsYXlvdXRPdXRbYXhOYW1lXTtcblxuICAgICAgICB2YXIgYW5jaG9yZWRBeGlzID0gbGF5b3V0T3V0W2lkMm5hbWUoYXhMYXlvdXRPdXQuYW5jaG9yKV07XG5cbiAgICAgICAgdmFyIGZpeGVkUmFuZ2VEZmx0ID0gZ2V0Q29tcG9uZW50TWV0aG9kKCdyYW5nZXNsaWRlcicsICdpc1Zpc2libGUnKShhbmNob3JlZEF4aXMpO1xuXG4gICAgICAgIGNvZXJjZSgnZml4ZWRyYW5nZScsIGZpeGVkUmFuZ2VEZmx0KTtcbiAgICB9XG5cbiAgICAvLyBGaW5hbGx5LCBoYW5kbGUgc2NhbGUgY29uc3RyYWludHMgYW5kIG1hdGNoaW5nIGF4ZXMuXG4gICAgLy9cbiAgICAvLyBXZSBuZWVkIHRvIGRvIHRoaXMgYWZ0ZXIgYWxsIGF4ZXMgaGF2ZSBjb2VyY2VkIGJvdGggYHR5cGVgXG4gICAgLy8gKHNvIHdlIGxpbmsgb25seSBheGVzIG9mIHRoZSBzYW1lIHR5cGUpIGFuZFxuICAgIC8vIGBmaXhlZHJhbmdlYCAoc28gd2UgY2FuIGF2b2lkIGxpbmtpbmcgZnJvbSBPUiBUTyBhIGZpeGVkIGF4aXMpLlxuXG4gICAgLy8gc2V0cyBvZiBheGVzIGxpbmtlZCBieSBgc2NhbGVhbmNob3JgIGFsb25nIHdpdGggdGhlIHNjYWxlcmF0aW9zIGNvbXBvdW5kZWRcbiAgICAvLyB0b2dldGhlciwgcG9wdWxhdGVkIGluIGhhbmRsZUNvbnN0cmFpbnREZWZhdWx0c1xuICAgIHZhciBjb25zdHJhaW50R3JvdXBzID0gbGF5b3V0T3V0Ll9heGlzQ29uc3RyYWludEdyb3VwcyA9IFtdO1xuICAgIC8vIHNpbWlsYXIgdG8gX2F4aXNDb25zdHJhaW50R3JvdXBzLCBidXQgZm9yIG1hdGNoaW5nIGF4ZXNcbiAgICB2YXIgbWF0Y2hHcm91cHMgPSBsYXlvdXRPdXQuX2F4aXNNYXRjaEdyb3VwcyA9IFtdO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYXhOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBheE5hbWUgPSBheE5hbWVzW2ldO1xuICAgICAgICBheExldHRlciA9IGF4TmFtZS5jaGFyQXQoMCk7XG4gICAgICAgIGF4TGF5b3V0SW4gPSBsYXlvdXRJbltheE5hbWVdO1xuICAgICAgICBheExheW91dE91dCA9IGxheW91dE91dFtheE5hbWVdO1xuXG4gICAgICAgIGhhbmRsZUNvbnN0cmFpbnREZWZhdWx0cyhheExheW91dEluLCBheExheW91dE91dCwgY29lcmNlLCBhbGxBeGlzSWRzLCBsYXlvdXRPdXQpO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IG1hdGNoR3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBncm91cCA9IG1hdGNoR3JvdXBzW2ldO1xuICAgICAgICB2YXIgcm5nID0gbnVsbDtcbiAgICAgICAgdmFyIGF1dG9yYW5nZSA9IG51bGw7XG4gICAgICAgIHZhciBheElkO1xuXG4gICAgICAgIC8vIGZpbmQgJ21hdGNoaW5nJyByYW5nZSBhdHRyc1xuICAgICAgICBmb3IoYXhJZCBpbiBncm91cCkge1xuICAgICAgICAgICAgYXhMYXlvdXRPdXQgPSBsYXlvdXRPdXRbaWQybmFtZShheElkKV07XG4gICAgICAgICAgICBpZighYXhMYXlvdXRPdXQubWF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHJuZyA9IGF4TGF5b3V0T3V0LnJhbmdlO1xuICAgICAgICAgICAgICAgIGF1dG9yYW5nZSA9IGF4TGF5b3V0T3V0LmF1dG9yYW5nZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBgYXgubWF0Y2hlc2AgdmFsdWVzIGFyZSByZWNpcHJvY2FsLFxuICAgICAgICAvLyBwaWNrIHZhbHVlcyBvZiBmaXJzdCBheGlzIGluIGdyb3VwXG4gICAgICAgIGlmKHJuZyA9PT0gbnVsbCB8fCBhdXRvcmFuZ2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGZvcihheElkIGluIGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgYXhMYXlvdXRPdXQgPSBsYXlvdXRPdXRbaWQybmFtZShheElkKV07XG4gICAgICAgICAgICAgICAgcm5nID0gYXhMYXlvdXRPdXQucmFuZ2U7XG4gICAgICAgICAgICAgICAgYXV0b3JhbmdlID0gYXhMYXlvdXRPdXQuYXV0b3JhbmdlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIGFwcGx5IG1hdGNoaW5nIHJhbmdlIGF0dHJzXG4gICAgICAgIGZvcihheElkIGluIGdyb3VwKSB7XG4gICAgICAgICAgICBheExheW91dE91dCA9IGxheW91dE91dFtpZDJuYW1lKGF4SWQpXTtcbiAgICAgICAgICAgIGlmKGF4TGF5b3V0T3V0Lm1hdGNoZXMpIHtcbiAgICAgICAgICAgICAgICBheExheW91dE91dC5yYW5nZSA9IHJuZy5zbGljZSgpO1xuICAgICAgICAgICAgICAgIGF4TGF5b3V0T3V0LmF1dG9yYW5nZSA9IGF1dG9yYW5nZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF4TGF5b3V0T3V0Ll9tYXRjaEdyb3VwID0gZ3JvdXA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyByZW1vdmUgbWF0Y2hpbmcgYXhpcyBmcm9tIHNjYWxlYW5jaG9yIGNvbnN0cmFpbnQgZ3JvdXBzIChmb3Igbm93KVxuICAgICAgICBpZihjb25zdHJhaW50R3JvdXBzLmxlbmd0aCkge1xuICAgICAgICAgICAgZm9yKGF4SWQgaW4gZ3JvdXApIHtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBjb25zdHJhaW50R3JvdXBzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBncm91cDIgPSBjb25zdHJhaW50R3JvdXBzW2pdO1xuICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGF4SWQyIGluIGdyb3VwMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoYXhJZCA9PT0gYXhJZDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMaWIud2FybignQXhpcyAnICsgYXhJZDIgKyAnIGlzIHNldCB3aXRoIGJvdGggJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdhICpzY2FsZWFuY2hvciogYW5kICptYXRjaGVzKiBjb25zdHJhaW50OyAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2lnbm9yaW5nIHRoZSBzY2FsZSBjb25zdHJhaW50LicpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGdyb3VwMltheElkMl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoT2JqZWN0LmtleXMoZ3JvdXAyKS5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRHcm91cHMuc3BsaWNlKGosIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4uL2xheW91dF9hdHRyaWJ1dGVzXCI6ODE5LFwiLi9heGlzX2RlZmF1bHRzXCI6NzY5LFwiLi9heGlzX2lkc1wiOjc3MCxcIi4vY29uc3RyYWludHNcIjo3NzQsXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6Nzc5LFwiLi9wb3NpdGlvbl9kZWZhdWx0c1wiOjc4MixcIi4vdHlwZV9kZWZhdWx0c1wiOjc5MH1dLDc4MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvck1peCA9IF9kZXJlcV8oJ3Rpbnljb2xvcjInKS5taXg7XG52YXIgbGlnaHRGcmFjdGlvbiA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpLmxpZ2h0RnJhY3Rpb247XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbi8qKlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHMgOlxuICogICAtIGRmbHRDb2xvciB7c3RyaW5nfSA6IGRlZmF1bHQgYXhpcyBjb2xvclxuICogICAtIGJnQ29sb3Ige3N0cmluZ30gOiBjb21iaW5lZCBzdWJwbG90IGJnIGNvbG9yXG4gKiAgIC0gYmxlbmQge251bWJlciwgb3B0aW9uYWx9IDogYmxlbmQgcGVyY2VudGFnZSAodG8gY29tcHV0ZSBkZmx0IGdyaWQgY29sb3IpXG4gKiAgIC0gc2hvd0xpbmUge2Jvb2xlYW59IDogc2hvdyBsaW5lIGJ5IGRlZmF1bHRcbiAqICAgLSBzaG93R3JpZCB7Ym9vbGVhbn0gOiBzaG93IGdyaWQgYnkgZGVmYXVsdFxuICogICAtIG5vWmVyb0xpbmUge2Jvb2xlYW59IDogZG9uJ3QgY29lcmNlIHplcm9saW5lKiBhdHRyaWJ1dGVzXG4gKiAgIC0gYXR0cmlidXRlcyB7b2JqZWN0fSA6IGF0dHJpYnV0ZSBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIGlucHV0IGNvbnRhaW5lcnNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVMaW5lR3JpZERlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgb3B0cykge1xuICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gICAgdmFyIGRmbHRDb2xvciA9IG9wdHMuZGZsdENvbG9yO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlMihhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlMihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBvcHRzLmF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsaW5lQ29sb3IgPSBjb2VyY2UyKCdsaW5lY29sb3InLCBkZmx0Q29sb3IpO1xuICAgIHZhciBsaW5lV2lkdGggPSBjb2VyY2UyKCdsaW5ld2lkdGgnKTtcbiAgICB2YXIgc2hvd0xpbmUgPSBjb2VyY2UoJ3Nob3dsaW5lJywgb3B0cy5zaG93TGluZSB8fCAhIWxpbmVDb2xvciB8fCAhIWxpbmVXaWR0aCk7XG5cbiAgICBpZighc2hvd0xpbmUpIHtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC5saW5lY29sb3I7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQubGluZXdpZHRoO1xuICAgIH1cblxuICAgIHZhciBncmlkQ29sb3JEZmx0ID0gY29sb3JNaXgoZGZsdENvbG9yLCBvcHRzLmJnQ29sb3IsIG9wdHMuYmxlbmQgfHwgbGlnaHRGcmFjdGlvbikudG9SZ2JTdHJpbmcoKTtcbiAgICB2YXIgZ3JpZENvbG9yID0gY29lcmNlMignZ3JpZGNvbG9yJywgZ3JpZENvbG9yRGZsdCk7XG4gICAgdmFyIGdyaWRXaWR0aCA9IGNvZXJjZTIoJ2dyaWR3aWR0aCcpO1xuICAgIHZhciBzaG93R3JpZExpbmVzID0gY29lcmNlKCdzaG93Z3JpZCcsIG9wdHMuc2hvd0dyaWQgfHwgISFncmlkQ29sb3IgfHwgISFncmlkV2lkdGgpO1xuXG4gICAgaWYoIXNob3dHcmlkTGluZXMpIHtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC5ncmlkY29sb3I7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuZ3JpZHdpZHRoO1xuICAgIH1cblxuICAgIGlmKCFvcHRzLm5vWmVyb0xpbmUpIHtcbiAgICAgICAgdmFyIHplcm9MaW5lQ29sb3IgPSBjb2VyY2UyKCd6ZXJvbGluZWNvbG9yJywgZGZsdENvbG9yKTtcbiAgICAgICAgdmFyIHplcm9MaW5lV2lkdGggPSBjb2VyY2UyKCd6ZXJvbGluZXdpZHRoJyk7XG4gICAgICAgIHZhciBzaG93WmVyb0xpbmUgPSBjb2VyY2UoJ3plcm9saW5lJywgb3B0cy5zaG93R3JpZCB8fCAhIXplcm9MaW5lQ29sb3IgfHwgISF6ZXJvTGluZVdpZHRoKTtcblxuICAgICAgICBpZighc2hvd1plcm9MaW5lKSB7XG4gICAgICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0Lnplcm9saW5lY29sb3I7XG4gICAgICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0Lnplcm9saW5ld2lkdGg7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlc1wiOjU5MixcIi4uLy4uL2xpYlwiOjcxOSxcInRpbnljb2xvcjJcIjo1Mzd9XSw3ODI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVQb3NpdGlvbkRlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgb3B0aW9ucykge1xuICAgIHZhciBjb3VudGVyQXhlcyA9IG9wdGlvbnMuY291bnRlckF4ZXMgfHwgW107XG4gICAgdmFyIG92ZXJsYXlhYmxlQXhlcyA9IG9wdGlvbnMub3ZlcmxheWFibGVBeGVzIHx8IFtdO1xuICAgIHZhciBsZXR0ZXIgPSBvcHRpb25zLmxldHRlcjtcbiAgICB2YXIgZ3JpZCA9IG9wdGlvbnMuZ3JpZDtcblxuICAgIHZhciBkZmx0QW5jaG9yLCBkZmx0RG9tYWluLCBkZmx0U2lkZSwgZGZsdFBvc2l0aW9uO1xuXG4gICAgaWYoZ3JpZCkge1xuICAgICAgICBkZmx0RG9tYWluID0gZ3JpZC5fZG9tYWluc1tsZXR0ZXJdW2dyaWQuX2F4aXNNYXBbY29udGFpbmVyT3V0Ll9pZF1dO1xuICAgICAgICBkZmx0QW5jaG9yID0gZ3JpZC5fYW5jaG9yc1tjb250YWluZXJPdXQuX2lkXTtcbiAgICAgICAgaWYoZGZsdERvbWFpbikge1xuICAgICAgICAgICAgZGZsdFNpZGUgPSBncmlkW2xldHRlciArICdzaWRlJ10uc3BsaXQoJyAnKVswXTtcbiAgICAgICAgICAgIGRmbHRQb3NpdGlvbiA9IGdyaWQuZG9tYWluW2xldHRlcl1bZGZsdFNpZGUgPT09ICdyaWdodCcgfHwgZGZsdFNpZGUgPT09ICd0b3AnID8gMSA6IDBdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gRXZlbiBpZiB0aGVyZSdzIGEgZ3JpZCwgdGhpcyBheGlzIG1heSBub3QgYmUgaW4gaXQgLSBmYWxsIGJhY2sgb24gbm9uLWdyaWQgZGVmYXVsdHNcbiAgICBkZmx0RG9tYWluID0gZGZsdERvbWFpbiB8fCBbMCwgMV07XG4gICAgZGZsdEFuY2hvciA9IGRmbHRBbmNob3IgfHwgKGlzTnVtZXJpYyhjb250YWluZXJJbi5wb3NpdGlvbikgPyAnZnJlZScgOiAoY291bnRlckF4ZXNbMF0gfHwgJ2ZyZWUnKSk7XG4gICAgZGZsdFNpZGUgPSBkZmx0U2lkZSB8fCAobGV0dGVyID09PSAneCcgPyAnYm90dG9tJyA6ICdsZWZ0Jyk7XG4gICAgZGZsdFBvc2l0aW9uID0gZGZsdFBvc2l0aW9uIHx8IDA7XG5cbiAgICB2YXIgYW5jaG9yID0gTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCB7XG4gICAgICAgIGFuY2hvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2ZyZWUnXS5jb25jYXQoY291bnRlckF4ZXMpLFxuICAgICAgICAgICAgZGZsdDogZGZsdEFuY2hvclxuICAgICAgICB9XG4gICAgfSwgJ2FuY2hvcicpO1xuXG4gICAgaWYoYW5jaG9yID09PSAnZnJlZScpIGNvZXJjZSgncG9zaXRpb24nLCBkZmx0UG9zaXRpb24pO1xuXG4gICAgTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCB7XG4gICAgICAgIHNpZGU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogbGV0dGVyID09PSAneCcgPyBbJ2JvdHRvbScsICd0b3AnXSA6IFsnbGVmdCcsICdyaWdodCddLFxuICAgICAgICAgICAgZGZsdDogZGZsdFNpZGVcbiAgICAgICAgfVxuICAgIH0sICdzaWRlJyk7XG5cbiAgICB2YXIgb3ZlcmxheWluZyA9IGZhbHNlO1xuICAgIGlmKG92ZXJsYXlhYmxlQXhlcy5sZW5ndGgpIHtcbiAgICAgICAgb3ZlcmxheWluZyA9IExpYi5jb2VyY2UoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwge1xuICAgICAgICAgICAgb3ZlcmxheWluZzoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgICAgICB2YWx1ZXM6IFtmYWxzZV0uY29uY2F0KG92ZXJsYXlhYmxlQXhlcyksXG4gICAgICAgICAgICAgICAgZGZsdDogZmFsc2VcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgJ292ZXJsYXlpbmcnKTtcbiAgICB9XG5cbiAgICBpZighb3ZlcmxheWluZykge1xuICAgICAgICAvLyBUT0RPOiByaWdodCBub3cgSSdtIGNvcHlpbmcgdGhpcyBkb21haW4gb3ZlciB0byBvdmVybGF5aW5nIGF4ZXNcbiAgICAgICAgLy8gaW4gYXguc2V0c2NhbGUoKS4uLiBidXQgdGhpcyBtZWFucyB3ZSBzdGlsbCBuZWVkIChpbXBlcmZlY3QpIGxvZ2ljXG4gICAgICAgIC8vIGluIHRoZSBheGVzIHBvcG92ZXIgdG8gaGlkZSBkb21haW4gZm9yIHRoZSBvdmVybGF5aW5nIGF4aXMuXG4gICAgICAgIC8vIHBlcmhhcHMgSSBzaG91bGQgbWFrZSBhIHByaXZhdGUgdmVyc2lvbiBfZG9tYWluIHRoYXQgYWxsIGF4ZXMgZ2V0Pz8/XG4gICAgICAgIHZhciBkb21haW4gPSBjb2VyY2UoJ2RvbWFpbicsIGRmbHREb21haW4pO1xuXG4gICAgICAgIC8vIGFjY29yZGluZyB0byBodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9jYW52YXMtc2l6ZVxuICAgICAgICAvLyB0aGUgbWluaW11bSB2YWx1ZSBvZiBtYXggY2FudmFzIHdpZHRoIGFjcm9zcyBicm93c2VycyBhbmQgZGV2aWNlcyBpcyA0MDk2XG4gICAgICAgIC8vIHdoaWNoIGFwcGxpZWQgaW4gdGhlIGNhbGN1bGF0aW9uIGJlbG93OlxuICAgICAgICBpZihkb21haW5bMF0gPiBkb21haW5bMV0gLSAxIC8gNDA5NikgY29udGFpbmVyT3V0LmRvbWFpbiA9IGRmbHREb21haW47XG4gICAgICAgIExpYi5ub25lT3JBbGwoY29udGFpbmVySW4uZG9tYWluLCBjb250YWluZXJPdXQuZG9tYWluLCBkZmx0RG9tYWluKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2xheWVyJyk7XG5cbiAgICByZXR1cm4gY29udGFpbmVyT3V0O1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDc4MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEZST01fQkwgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50JykuRlJPTV9CTDtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzY2FsZVpvb20oYXgsIGZhY3RvciwgY2VudGVyRnJhY3Rpb24pIHtcbiAgICBpZihjZW50ZXJGcmFjdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNlbnRlckZyYWN0aW9uID0gRlJPTV9CTFtheC5jb25zdHJhaW50b3dhcmQgfHwgJ2NlbnRlciddO1xuICAgIH1cblxuICAgIHZhciByYW5nZUxpbmVhciA9IFtheC5yMmwoYXgucmFuZ2VbMF0pLCBheC5yMmwoYXgucmFuZ2VbMV0pXTtcbiAgICB2YXIgY2VudGVyID0gcmFuZ2VMaW5lYXJbMF0gKyAocmFuZ2VMaW5lYXJbMV0gLSByYW5nZUxpbmVhclswXSkgKiBjZW50ZXJGcmFjdGlvbjtcblxuICAgIGF4LnJhbmdlID0gYXguX2lucHV0LnJhbmdlID0gW1xuICAgICAgICBheC5sMnIoY2VudGVyICsgKHJhbmdlTGluZWFyWzBdIC0gY2VudGVyKSAqIGZhY3RvciksXG4gICAgICAgIGF4LmwycihjZW50ZXIgKyAocmFuZ2VMaW5lYXJbMV0gLSBjZW50ZXIpICogZmFjdG9yKVxuICAgIF07XG59O1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnRcIjo2ODh9XSw3ODQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBwb2x5Ym9vbCA9IF9kZXJlcV8oJ3BvbHlib29sanMnKTtcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBGeCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHBvbHlnb24gPSBfZGVyZXFfKCcuLi8uLi9saWIvcG9seWdvbicpO1xudmFyIHRocm90dGxlID0gX2RlcmVxXygnLi4vLi4vbGliL3Rocm90dGxlJyk7XG52YXIgbWFrZUV2ZW50RGF0YSA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngvaGVscGVycycpLm1ha2VFdmVudERhdGE7XG52YXIgZ2V0RnJvbUlkID0gX2RlcmVxXygnLi9heGlzX2lkcycpLmdldEZyb21JZDtcbnZhciBjbGVhckdsQ2FudmFzZXMgPSBfZGVyZXFfKCcuLi8uLi9saWIvY2xlYXJfZ2xfY2FudmFzZXMnKTtcblxudmFyIHJlZHJhd1JlZ2xUcmFjZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9zdWJyb3V0aW5lcycpLnJlZHJhd1JlZ2xUcmFjZXM7XG5cbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIE1JTlNFTEVDVCA9IGNvbnN0YW50cy5NSU5TRUxFQ1Q7XG5cbnZhciBmaWx0ZXJlZFBvbHlnb24gPSBwb2x5Z29uLmZpbHRlcjtcbnZhciBwb2x5Z29uVGVzdGVyID0gcG9seWdvbi50ZXN0ZXI7XG5cbmZ1bmN0aW9uIGdldEF4SWQoYXgpIHsgcmV0dXJuIGF4Ll9pZDsgfVxuXG5mdW5jdGlvbiBwcmVwU2VsZWN0KGUsIHN0YXJ0WCwgc3RhcnRZLCBkcmFnT3B0aW9ucywgbW9kZSkge1xuICAgIHZhciBnZCA9IGRyYWdPcHRpb25zLmdkO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHpvb21MYXllciA9IGZ1bGxMYXlvdXQuX3pvb21sYXllcjtcbiAgICB2YXIgZHJhZ0JCb3ggPSBkcmFnT3B0aW9ucy5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHZhciBwbG90aW5mbyA9IGRyYWdPcHRpb25zLnBsb3RpbmZvO1xuICAgIHZhciB4cyA9IHBsb3RpbmZvLnhheGlzLl9vZmZzZXQ7XG4gICAgdmFyIHlzID0gcGxvdGluZm8ueWF4aXMuX29mZnNldDtcbiAgICB2YXIgeDAgPSBzdGFydFggLSBkcmFnQkJveC5sZWZ0O1xuICAgIHZhciB5MCA9IHN0YXJ0WSAtIGRyYWdCQm94LnRvcDtcbiAgICB2YXIgeDEgPSB4MDtcbiAgICB2YXIgeTEgPSB5MDtcbiAgICB2YXIgcGF0aDAgPSAnTScgKyB4MCArICcsJyArIHkwO1xuICAgIHZhciBwdyA9IGRyYWdPcHRpb25zLnhheGVzWzBdLl9sZW5ndGg7XG4gICAgdmFyIHBoID0gZHJhZ09wdGlvbnMueWF4ZXNbMF0uX2xlbmd0aDtcbiAgICB2YXIgYWxsQXhlcyA9IGRyYWdPcHRpb25zLnhheGVzLmNvbmNhdChkcmFnT3B0aW9ucy55YXhlcyk7XG4gICAgdmFyIHN1YnRyYWN0ID0gZS5hbHRLZXk7XG5cbiAgICB2YXIgZmlsdGVyUG9seSwgc2VsZWN0aW9uVGVzdGVyLCBtZXJnZWRQb2x5Z29ucywgY3VycmVudFBvbHlnb247XG4gICAgdmFyIGksIHNlYXJjaEluZm8sIGV2ZW50RGF0YTtcblxuICAgIGNvZXJjZVNlbGVjdGlvbnNDYWNoZShlLCBnZCwgZHJhZ09wdGlvbnMpO1xuXG4gICAgaWYobW9kZSA9PT0gJ2xhc3NvJykge1xuICAgICAgICBmaWx0ZXJQb2x5ID0gZmlsdGVyZWRQb2x5Z29uKFtbeDAsIHkwXV0sIGNvbnN0YW50cy5CRU5EUFgpO1xuICAgIH1cblxuICAgIHZhciBvdXRsaW5lcyA9IHpvb21MYXllci5zZWxlY3RBbGwoJ3BhdGguc2VsZWN0LW91dGxpbmUtJyArIHBsb3RpbmZvLmlkKS5kYXRhKFsxLCAyXSk7XG5cbiAgICBvdXRsaW5lcy5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCBmdW5jdGlvbihkKSB7IHJldHVybiAnc2VsZWN0LW91dGxpbmUgc2VsZWN0LW91dGxpbmUtJyArIGQgKyAnIHNlbGVjdC1vdXRsaW5lLScgKyBwbG90aW5mby5pZDsgfSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIHhzICsgJywgJyArIHlzICsgJyknKVxuICAgICAgICAuYXR0cignZCcsIHBhdGgwICsgJ1onKTtcblxuICAgIHZhciBjb3JuZXJzID0gem9vbUxheWVyLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICd6b29tYm94LWNvcm5lcnMnKVxuICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgZmlsbDogQ29sb3IuYmFja2dyb3VuZCxcbiAgICAgICAgICAgIHN0cm9rZTogQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogMVxuICAgICAgICB9KVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgeHMgKyAnLCAnICsgeXMgKyAnKScpXG4gICAgICAgIC5hdHRyKCdkJywgJ00wLDBaJyk7XG5cblxuICAgIHZhciB0aHJvdHRsZUlEID0gZnVsbExheW91dC5fdWlkICsgY29uc3RhbnRzLlNFTEVDVElEO1xuICAgIHZhciBzZWxlY3Rpb24gPSBbXTtcblxuICAgIC8vIGZpbmQgdGhlIHRyYWNlcyB0byBzZWFyY2ggZm9yIHNlbGVjdGlvbiBwb2ludHNcbiAgICB2YXIgc2VhcmNoVHJhY2VzID0gZGV0ZXJtaW5lU2VhcmNoVHJhY2VzKGdkLCBkcmFnT3B0aW9ucy54YXhlcyxcbiAgICAgIGRyYWdPcHRpb25zLnlheGVzLCBkcmFnT3B0aW9ucy5zdWJwbG90KTtcblxuICAgIC8vIGluIHYyIChvbmNlIGxvZyByYW5nZXMgYXJlIGZpeGVkKSxcbiAgICAvLyB3ZSdsbCBiZSBhYmxlIHRvIHAyciBoZXJlIGZvciBhbGwgYXhpcyB0eXBlc1xuICAgIGZ1bmN0aW9uIHAycihheCwgdikge1xuICAgICAgICByZXR1cm4gYXgudHlwZSA9PT0gJ2xvZycgPyBheC5wMmQodikgOiBheC5wMnIodik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXhWYWx1ZShheCkge1xuICAgICAgICB2YXIgaW5kZXggPSAoYXguX2lkLmNoYXJBdCgwKSA9PT0gJ3knKSA/IDEgOiAwO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24odikgeyByZXR1cm4gcDJyKGF4LCB2W2luZGV4XSk7IH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHsgcmV0dXJuIGEgLSBiOyB9XG5cbiAgICAvLyBhbGxvdyBzdWJwbG90cyB0byBvdmVycmlkZSBmaWxsUmFuZ2VJdGVtcyByb3V0aW5lXG4gICAgdmFyIGZpbGxSYW5nZUl0ZW1zO1xuXG4gICAgaWYocGxvdGluZm8uZmlsbFJhbmdlSXRlbXMpIHtcbiAgICAgICAgZmlsbFJhbmdlSXRlbXMgPSBwbG90aW5mby5maWxsUmFuZ2VJdGVtcztcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZihtb2RlID09PSAnc2VsZWN0Jykge1xuICAgICAgICAgICAgZmlsbFJhbmdlSXRlbXMgPSBmdW5jdGlvbihldmVudERhdGEsIHBvbHkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmFuZ2VzID0gZXZlbnREYXRhLnJhbmdlID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBhbGxBeGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBheCA9IGFsbEF4ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBheExldHRlciA9IGF4Ll9pZC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgcmFuZ2VzW2F4Ll9pZF0gPSBbXG4gICAgICAgICAgICAgICAgICAgICAgICBwMnIoYXgsIHBvbHlbYXhMZXR0ZXIgKyAnbWluJ10pLFxuICAgICAgICAgICAgICAgICAgICAgICAgcDJyKGF4LCBwb2x5W2F4TGV0dGVyICsgJ21heCddKVxuICAgICAgICAgICAgICAgICAgICBdLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZmlsbFJhbmdlSXRlbXMgPSBmdW5jdGlvbihldmVudERhdGEsIHBvbHksIGZpbHRlclBvbHkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGF0YVB0cyA9IGV2ZW50RGF0YS5sYXNzb1BvaW50cyA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgYWxsQXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYXggPSBhbGxBeGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBkYXRhUHRzW2F4Ll9pZF0gPSBmaWx0ZXJQb2x5LmZpbHRlcmVkLm1hcChheFZhbHVlKGF4KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGRyYWdPcHRpb25zLm1vdmVGbiA9IGZ1bmN0aW9uKGR4MCwgZHkwKSB7XG4gICAgICAgIHgxID0gTWF0aC5tYXgoMCwgTWF0aC5taW4ocHcsIGR4MCArIHgwKSk7XG4gICAgICAgIHkxID0gTWF0aC5tYXgoMCwgTWF0aC5taW4ocGgsIGR5MCArIHkwKSk7XG5cbiAgICAgICAgdmFyIGR4ID0gTWF0aC5hYnMoeDEgLSB4MCk7XG4gICAgICAgIHZhciBkeSA9IE1hdGguYWJzKHkxIC0geTApO1xuXG4gICAgICAgIGlmKG1vZGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICAgICAgICB2YXIgZGlyZWN0aW9uID0gZnVsbExheW91dC5zZWxlY3RkaXJlY3Rpb247XG5cbiAgICAgICAgICAgIGlmKGZ1bGxMYXlvdXQuc2VsZWN0ZGlyZWN0aW9uID09PSAnYW55Jykge1xuICAgICAgICAgICAgICAgIGlmKGR5IDwgTWF0aC5taW4oZHggKiAwLjYsIE1JTlNFTEVDVCkpIGRpcmVjdGlvbiA9ICdoJztcbiAgICAgICAgICAgICAgICBlbHNlIGlmKGR4IDwgTWF0aC5taW4oZHkgKiAwLjYsIE1JTlNFTEVDVCkpIGRpcmVjdGlvbiA9ICd2JztcbiAgICAgICAgICAgICAgICBlbHNlIGRpcmVjdGlvbiA9ICdkJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gZnVsbExheW91dC5zZWxlY3RkaXJlY3Rpb247XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGRpcmVjdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICAgICAgLy8gaG9yaXpvbnRhbCBtb3Rpb246IG1ha2UgYSB2ZXJ0aWNhbCBib3hcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9seWdvbiA9IFtbeDAsIDBdLCBbeDAsIHBoXSwgW3gxLCBwaF0sIFt4MSwgMF1dO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnhtaW4gPSBNYXRoLm1pbih4MCwgeDEpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnhtYXggPSBNYXRoLm1heCh4MCwgeDEpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnltaW4gPSBNYXRoLm1pbigwLCBwaCk7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24ueW1heCA9IE1hdGgubWF4KDAsIHBoKTtcbiAgICAgICAgICAgICAgICAvLyBleHRyYXMgdG8gZ3VpZGUgdXNlcnMgaW4ga2VlcGluZyBhIHN0cmFpZ2h0IHNlbGVjdGlvblxuICAgICAgICAgICAgICAgIGNvcm5lcnMuYXR0cignZCcsICdNJyArIGN1cnJlbnRQb2x5Z29uLnhtaW4gKyAnLCcgKyAoeTAgLSBNSU5TRUxFQ1QpICtcbiAgICAgICAgICAgICAgICAgICAgJ2gtNHYnICsgKDIgKiBNSU5TRUxFQ1QpICsgJ2g0WicgK1xuICAgICAgICAgICAgICAgICAgICAnTScgKyAoY3VycmVudFBvbHlnb24ueG1heCAtIDEpICsgJywnICsgKHkwIC0gTUlOU0VMRUNUKSArXG4gICAgICAgICAgICAgICAgICAgICdoNHYnICsgKDIgKiBNSU5TRUxFQ1QpICsgJ2gtNFonKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihkaXJlY3Rpb24gPT09ICd2Jykge1xuICAgICAgICAgICAgICAgIC8vIHZlcnRpY2FsIG1vdGlvbjogbWFrZSBhIGhvcml6b250YWwgYm94XG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24gPSBbWzAsIHkwXSwgWzAsIHkxXSwgW3B3LCB5MV0sIFtwdywgeTBdXTtcbiAgICAgICAgICAgICAgICBjdXJyZW50UG9seWdvbi54bWluID0gTWF0aC5taW4oMCwgcHcpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnhtYXggPSBNYXRoLm1heCgwLCBwdyk7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24ueW1pbiA9IE1hdGgubWluKHkwLCB5MSk7XG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24ueW1heCA9IE1hdGgubWF4KHkwLCB5MSk7XG4gICAgICAgICAgICAgICAgY29ybmVycy5hdHRyKCdkJywgJ00nICsgKHgwIC0gTUlOU0VMRUNUKSArICcsJyArIGN1cnJlbnRQb2x5Z29uLnltaW4gK1xuICAgICAgICAgICAgICAgICAgICAndi00aCcgKyAoMiAqIE1JTlNFTEVDVCkgKyAndjRaJyArXG4gICAgICAgICAgICAgICAgICAgICdNJyArICh4MCAtIE1JTlNFTEVDVCkgKyAnLCcgKyAoY3VycmVudFBvbHlnb24ueW1heCAtIDEpICtcbiAgICAgICAgICAgICAgICAgICAgJ3Y0aCcgKyAoMiAqIE1JTlNFTEVDVCkgKyAndi00WicpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGRpcmVjdGlvbiA9PT0gJ2QnKSB7XG4gICAgICAgICAgICAgICAgLy8gZGlhZ29uYWwgbW90aW9uXG4gICAgICAgICAgICAgICAgY3VycmVudFBvbHlnb24gPSBbW3gwLCB5MF0sIFt4MCwgeTFdLCBbeDEsIHkxXSwgW3gxLCB5MF1dO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnhtaW4gPSBNYXRoLm1pbih4MCwgeDEpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnhtYXggPSBNYXRoLm1heCh4MCwgeDEpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnltaW4gPSBNYXRoLm1pbih5MCwgeTEpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnltYXggPSBNYXRoLm1heCh5MCwgeTEpO1xuICAgICAgICAgICAgICAgIGNvcm5lcnMuYXR0cignZCcsICdNMCwwWicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYobW9kZSA9PT0gJ2xhc3NvJykge1xuICAgICAgICAgICAgZmlsdGVyUG9seS5hZGRQdChbeDEsIHkxXSk7XG4gICAgICAgICAgICBjdXJyZW50UG9seWdvbiA9IGZpbHRlclBvbHkuZmlsdGVyZWQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjcmVhdGUgb3V0bGluZSAmIHRlc3RlclxuICAgICAgICBpZihkcmFnT3B0aW9ucy5zZWxlY3Rpb25EZWZzICYmIGRyYWdPcHRpb25zLnNlbGVjdGlvbkRlZnMubGVuZ3RoKSB7XG4gICAgICAgICAgICBtZXJnZWRQb2x5Z29ucyA9IG1lcmdlUG9seWdvbnMoZHJhZ09wdGlvbnMubWVyZ2VkUG9seWdvbnMsIGN1cnJlbnRQb2x5Z29uLCBzdWJ0cmFjdCk7XG4gICAgICAgICAgICBjdXJyZW50UG9seWdvbi5zdWJ0cmFjdCA9IHN1YnRyYWN0O1xuICAgICAgICAgICAgc2VsZWN0aW9uVGVzdGVyID0gbXVsdGlUZXN0ZXIoZHJhZ09wdGlvbnMuc2VsZWN0aW9uRGVmcy5jb25jYXQoW2N1cnJlbnRQb2x5Z29uXSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbWVyZ2VkUG9seWdvbnMgPSBbY3VycmVudFBvbHlnb25dO1xuICAgICAgICAgICAgc2VsZWN0aW9uVGVzdGVyID0gcG9seWdvblRlc3RlcihjdXJyZW50UG9seWdvbik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkcmF3IHNlbGVjdGlvblxuICAgICAgICBkcmF3U2VsZWN0aW9uKG1lcmdlZFBvbHlnb25zLCBvdXRsaW5lcyk7XG5cblxuICAgICAgICB0aHJvdHRsZS50aHJvdHRsZShcbiAgICAgICAgICAgIHRocm90dGxlSUQsXG4gICAgICAgICAgICBjb25zdGFudHMuU0VMRUNUREVMQVksXG4gICAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciB0aGlzU2VsZWN0aW9uO1xuICAgICAgICAgICAgICAgIHZhciB0cmFjZVNlbGVjdGlvbnMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdHJhY2VTZWxlY3Rpb247XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2VhcmNoVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlYXJjaEluZm8gPSBzZWFyY2hUcmFjZXNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgdHJhY2VTZWxlY3Rpb24gPSBzZWFyY2hJbmZvLl9tb2R1bGUuc2VsZWN0UG9pbnRzKHNlYXJjaEluZm8sIHNlbGVjdGlvblRlc3Rlcik7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNlU2VsZWN0aW9ucy5wdXNoKHRyYWNlU2VsZWN0aW9uKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzU2VsZWN0aW9uID0gZmlsbFNlbGVjdGlvbkl0ZW0odHJhY2VTZWxlY3Rpb24sIHNlYXJjaEluZm8pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKHNlbGVjdGlvbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB0aGlzU2VsZWN0aW9uLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2godGhpc1NlbGVjdGlvbltqXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBzZWxlY3Rpb24gPSB0aGlzU2VsZWN0aW9uO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YSA9IHtwb2ludHM6IHNlbGVjdGlvbn07XG4gICAgICAgICAgICAgICAgdXBkYXRlU2VsZWN0ZWRTdGF0ZShnZCwgc2VhcmNoVHJhY2VzLCBldmVudERhdGEpO1xuICAgICAgICAgICAgICAgIGZpbGxSYW5nZUl0ZW1zKGV2ZW50RGF0YSwgY3VycmVudFBvbHlnb24sIGZpbHRlclBvbHkpO1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLmdkLmVtaXQoJ3Bsb3RseV9zZWxlY3RpbmcnLCBldmVudERhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH07XG5cbiAgICBkcmFnT3B0aW9ucy5jbGlja0ZuID0gZnVuY3Rpb24obnVtQ2xpY2tzLCBldnQpIHtcbiAgICAgICAgdmFyIGNsaWNrbW9kZSA9IGZ1bGxMYXlvdXQuY2xpY2ttb2RlO1xuXG4gICAgICAgIGNvcm5lcnMucmVtb3ZlKCk7XG5cbiAgICAgICAgdGhyb3R0bGUuZG9uZSh0aHJvdHRsZUlEKS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhyb3R0bGUuY2xlYXIodGhyb3R0bGVJRCk7XG4gICAgICAgICAgICBpZihudW1DbGlja3MgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAvLyBjbGVhciBzZWxlY3Rpb24gb24gZG91YmxlY2xpY2tcbiAgICAgICAgICAgICAgICBvdXRsaW5lcy5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBzZWFyY2hUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgc2VhcmNoSW5mbyA9IHNlYXJjaFRyYWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgc2VhcmNoSW5mby5fbW9kdWxlLnNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdXBkYXRlU2VsZWN0ZWRTdGF0ZShnZCwgc2VhcmNoVHJhY2VzKTtcblxuICAgICAgICAgICAgICAgIGNsZWFyU2VsZWN0aW9uc0NhY2hlKGRyYWdPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9kZXNlbGVjdCcsIG51bGwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZihjbGlja21vZGUuaW5kZXhPZignc2VsZWN0JykgPiAtMSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxlY3RPbkNsaWNrKGV2dCwgZ2QsIGRyYWdPcHRpb25zLnhheGVzLCBkcmFnT3B0aW9ucy55YXhlcyxcbiAgICAgICAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5zdWJwbG90LCBkcmFnT3B0aW9ucywgb3V0bGluZXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGNsaWNrbW9kZSA9PT0gJ2V2ZW50Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiByZW1vdmUgaW4gdjIgLSB0aGlzIHdhcyBwcm9iYWJseSBuZXZlciBpbnRlbmRlZCB0byB3b3JrIGFzIGl0IGRvZXMsXG4gICAgICAgICAgICAgICAgICAgIC8vIGJ1dCBpbiBjYXNlIGFueW9uZSBkZXBlbmRzIG9uIGl0IHdlIGRvbid0IHdhbnQgdG8gYnJlYWsgaXQgbm93LlxuICAgICAgICAgICAgICAgICAgICAvLyBOb3RlIHRoYXQgY2xpY2stdG8tc2VsZWN0IGludHJvZHVjZWQgcHJlIHYyIGFsc28gZW1pdHRzIHByb3BlclxuICAgICAgICAgICAgICAgICAgICAvLyBldmVudCBkYXRhIHdoZW4gY2xpY2ttb2RlIGlzIGhhdmluZyAnc2VsZWN0JyBpbiBpdHMgZmxhZyBsaXN0LlxuICAgICAgICAgICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfc2VsZWN0ZWQnLCB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRnguY2xpY2soZ2QsIGV2dCk7XG4gICAgICAgIH0pLmNhdGNoKExpYi5lcnJvcik7XG4gICAgfTtcblxuICAgIGRyYWdPcHRpb25zLmRvbmVGbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjb3JuZXJzLnJlbW92ZSgpO1xuXG4gICAgICAgIHRocm90dGxlLmRvbmUodGhyb3R0bGVJRCkudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHRocm90dGxlLmNsZWFyKHRocm90dGxlSUQpO1xuICAgICAgICAgICAgZHJhZ09wdGlvbnMuZ2QuZW1pdCgncGxvdGx5X3NlbGVjdGVkJywgZXZlbnREYXRhKTtcblxuICAgICAgICAgICAgaWYoY3VycmVudFBvbHlnb24gJiYgZHJhZ09wdGlvbnMuc2VsZWN0aW9uRGVmcykge1xuICAgICAgICAgICAgICAgIC8vIHNhdmUgbGFzdCBwb2x5Z29uc1xuICAgICAgICAgICAgICAgIGN1cnJlbnRQb2x5Z29uLnN1YnRyYWN0ID0gc3VidHJhY3Q7XG4gICAgICAgICAgICAgICAgZHJhZ09wdGlvbnMuc2VsZWN0aW9uRGVmcy5wdXNoKGN1cnJlbnRQb2x5Z29uKTtcblxuICAgICAgICAgICAgICAgIC8vIHdlIGhhdmUgdG8ga2VlcCByZWZlcmVuY2UgdG8gYXJyYXlzIGNvbnRhaW5lclxuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLm1lcmdlZFBvbHlnb25zLmxlbmd0aCA9IDA7XG4gICAgICAgICAgICAgICAgW10ucHVzaC5hcHBseShkcmFnT3B0aW9ucy5tZXJnZWRQb2x5Z29ucywgbWVyZ2VkUG9seWdvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihkcmFnT3B0aW9ucy5kb25lRm5Db21wbGV0ZWQpIHtcbiAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5kb25lRm5Db21wbGV0ZWQoc2VsZWN0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuY2F0Y2goTGliLmVycm9yKTtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBzZWxlY3RPbkNsaWNrKGV2dCwgZ2QsIHhBeGVzLCB5QXhlcywgc3VicGxvdCwgZHJhZ09wdGlvbnMsIHBvbHlnb25PdXRsaW5lcykge1xuICAgIHZhciBob3ZlckRhdGEgPSBnZC5faG92ZXJkYXRhO1xuICAgIHZhciBjbGlja21vZGUgPSBnZC5fZnVsbExheW91dC5jbGlja21vZGU7XG4gICAgdmFyIHNlbmRFdmVudHMgPSBjbGlja21vZGUuaW5kZXhPZignZXZlbnQnKSA+IC0xO1xuICAgIHZhciBzZWxlY3Rpb24gPSBbXTtcbiAgICB2YXIgc2VhcmNoVHJhY2VzLCBzZWFyY2hJbmZvLCBjdXJyZW50U2VsZWN0aW9uRGVmLCBzZWxlY3Rpb25UZXN0ZXIsIHRyYWNlU2VsZWN0aW9uO1xuICAgIHZhciB0aGlzVHJhY2VzU2VsZWN0aW9uLCBwb2ludE9yQmluU2VsZWN0ZWQsIHN1YnRyYWN0LCBldmVudERhdGEsIGk7XG5cbiAgICBpZihpc0hvdmVyRGF0YVNldChob3ZlckRhdGEpKSB7XG4gICAgICAgIGNvZXJjZVNlbGVjdGlvbnNDYWNoZShldnQsIGdkLCBkcmFnT3B0aW9ucyk7XG4gICAgICAgIHNlYXJjaFRyYWNlcyA9IGRldGVybWluZVNlYXJjaFRyYWNlcyhnZCwgeEF4ZXMsIHlBeGVzLCBzdWJwbG90KTtcbiAgICAgICAgdmFyIGNsaWNrZWRQdEluZm8gPSBleHRyYWN0Q2xpY2tlZFB0SW5mbyhob3ZlckRhdGEsIHNlYXJjaFRyYWNlcyk7XG4gICAgICAgIHZhciBpc0Jpbm5lZFRyYWNlID0gY2xpY2tlZFB0SW5mby5wb2ludE51bWJlcnMubGVuZ3RoID4gMDtcblxuXG4gICAgICAgIC8vIE5vdGU6IHBvdGVudGlhbGx5IGNvc3RseSBvcGVyYXRpb24gaXNQb2ludE9yQmluU2VsZWN0ZWQgaXNcbiAgICAgICAgLy8gY2FsbGVkIGFzIGxhdGUgYXMgcG9zc2libGUgdGhyb3VnaCB0aGUgdXNlIG9mIGFuIGFzc2lnbm1lbnRcbiAgICAgICAgLy8gaW4gYW4gaWYgY29uZGl0aW9uLlxuICAgICAgICBpZihpc0Jpbm5lZFRyYWNlID9cbiAgICAgICAgICAgIGlzT25seVRoaXNCaW5TZWxlY3RlZChzZWFyY2hUcmFjZXMsIGNsaWNrZWRQdEluZm8pIDpcbiAgICAgICAgICAgIGlzT25seU9uZVBvaW50U2VsZWN0ZWQoc2VhcmNoVHJhY2VzKSAmJlxuICAgICAgICAgICAgICAgIChwb2ludE9yQmluU2VsZWN0ZWQgPSBpc1BvaW50T3JCaW5TZWxlY3RlZChjbGlja2VkUHRJbmZvKSkpIHtcbiAgICAgICAgICAgIGlmKHBvbHlnb25PdXRsaW5lcykgcG9seWdvbk91dGxpbmVzLnJlbW92ZSgpO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2VhcmNoVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgc2VhcmNoSW5mbyA9IHNlYXJjaFRyYWNlc1tpXTtcbiAgICAgICAgICAgICAgICBzZWFyY2hJbmZvLl9tb2R1bGUuc2VsZWN0UG9pbnRzKHNlYXJjaEluZm8sIGZhbHNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdXBkYXRlU2VsZWN0ZWRTdGF0ZShnZCwgc2VhcmNoVHJhY2VzKTtcblxuICAgICAgICAgICAgY2xlYXJTZWxlY3Rpb25zQ2FjaGUoZHJhZ09wdGlvbnMpO1xuXG4gICAgICAgICAgICBpZihzZW5kRXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2Rlc2VsZWN0JywgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdWJ0cmFjdCA9IGV2dC5zaGlmdEtleSAmJlxuICAgICAgICAgICAgICAocG9pbnRPckJpblNlbGVjdGVkICE9PSB1bmRlZmluZWQgP1xuICAgICAgICAgICAgICAgIHBvaW50T3JCaW5TZWxlY3RlZCA6XG4gICAgICAgICAgICAgICAgaXNQb2ludE9yQmluU2VsZWN0ZWQoY2xpY2tlZFB0SW5mbykpO1xuICAgICAgICAgICAgY3VycmVudFNlbGVjdGlvbkRlZiA9IG5ld1BvaW50U2VsZWN0aW9uRGVmKGNsaWNrZWRQdEluZm8ucG9pbnROdW1iZXIsIGNsaWNrZWRQdEluZm8uc2VhcmNoSW5mbywgc3VidHJhY3QpO1xuXG4gICAgICAgICAgICB2YXIgYWxsU2VsZWN0aW9uRGVmcyA9IGRyYWdPcHRpb25zLnNlbGVjdGlvbkRlZnMuY29uY2F0KFtjdXJyZW50U2VsZWN0aW9uRGVmXSk7XG4gICAgICAgICAgICBzZWxlY3Rpb25UZXN0ZXIgPSBtdWx0aVRlc3RlcihhbGxTZWxlY3Rpb25EZWZzKTtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2VhcmNoVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdHJhY2VTZWxlY3Rpb24gPSBzZWFyY2hUcmFjZXNbaV0uX21vZHVsZS5zZWxlY3RQb2ludHMoc2VhcmNoVHJhY2VzW2ldLCBzZWxlY3Rpb25UZXN0ZXIpO1xuICAgICAgICAgICAgICAgIHRoaXNUcmFjZXNTZWxlY3Rpb24gPSBmaWxsU2VsZWN0aW9uSXRlbSh0cmFjZVNlbGVjdGlvbiwgc2VhcmNoVHJhY2VzW2ldKTtcblxuICAgICAgICAgICAgICAgIGlmKHNlbGVjdGlvbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IHRoaXNUcmFjZXNTZWxlY3Rpb24ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5wdXNoKHRoaXNUcmFjZXNTZWxlY3Rpb25bal0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHNlbGVjdGlvbiA9IHRoaXNUcmFjZXNTZWxlY3Rpb247XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGV2ZW50RGF0YSA9IHtwb2ludHM6IHNlbGVjdGlvbn07XG4gICAgICAgICAgICB1cGRhdGVTZWxlY3RlZFN0YXRlKGdkLCBzZWFyY2hUcmFjZXMsIGV2ZW50RGF0YSk7XG5cbiAgICAgICAgICAgIGlmKGN1cnJlbnRTZWxlY3Rpb25EZWYgJiYgZHJhZ09wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBkcmFnT3B0aW9ucy5zZWxlY3Rpb25EZWZzLnB1c2goY3VycmVudFNlbGVjdGlvbkRlZik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHBvbHlnb25PdXRsaW5lcykgZHJhd1NlbGVjdGlvbihkcmFnT3B0aW9ucy5tZXJnZWRQb2x5Z29ucywgcG9seWdvbk91dGxpbmVzKTtcblxuICAgICAgICAgICAgaWYoc2VuZEV2ZW50cykge1xuICAgICAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9zZWxlY3RlZCcsIGV2ZW50RGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQ29uc3RydWN0cyBhIG5ldyBwb2ludCBzZWxlY3Rpb24gZGVmaW5pdGlvbiBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIG5ld1BvaW50U2VsZWN0aW9uRGVmKHBvaW50TnVtYmVyLCBzZWFyY2hJbmZvLCBzdWJ0cmFjdCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIHBvaW50TnVtYmVyOiBwb2ludE51bWJlcixcbiAgICAgICAgc2VhcmNoSW5mbzogc2VhcmNoSW5mbyxcbiAgICAgICAgc3VidHJhY3Q6IHN1YnRyYWN0XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gaXNQb2ludFNlbGVjdGlvbkRlZihvKSB7XG4gICAgcmV0dXJuICdwb2ludE51bWJlcicgaW4gbyAmJiAnc2VhcmNoSW5mbycgaW4gbztcbn1cblxuLypcbiAqIENvbnN0cnVjdHMgYSBuZXcgcG9pbnQgbnVtYmVyIHRlc3Rlci5cbiAqL1xuZnVuY3Rpb24gbmV3UG9pbnROdW1UZXN0ZXIocG9pbnRTZWxlY3Rpb25EZWYpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB4bWluOiAwLFxuICAgICAgICB4bWF4OiAwLFxuICAgICAgICB5bWluOiAwLFxuICAgICAgICB5bWF4OiAwLFxuICAgICAgICBwdHM6IFtdLFxuICAgICAgICBjb250YWluczogZnVuY3Rpb24ocHQsIG9taXRGaXJzdEVkZ2UsIHBvaW50TnVtYmVyLCBzZWFyY2hJbmZvKSB7XG4gICAgICAgICAgICB2YXIgaWR4V2FudGVkVHJhY2UgPSBwb2ludFNlbGVjdGlvbkRlZi5zZWFyY2hJbmZvLmNkWzBdLnRyYWNlLl9leHBhbmRlZEluZGV4O1xuICAgICAgICAgICAgdmFyIGlkeEFjdHVhbFRyYWNlID0gc2VhcmNoSW5mby5jZFswXS50cmFjZS5fZXhwYW5kZWRJbmRleDtcbiAgICAgICAgICAgIHJldHVybiBpZHhBY3R1YWxUcmFjZSA9PT0gaWR4V2FudGVkVHJhY2UgJiZcbiAgICAgICAgICAgICAgcG9pbnROdW1iZXIgPT09IHBvaW50U2VsZWN0aW9uRGVmLnBvaW50TnVtYmVyO1xuICAgICAgICB9LFxuICAgICAgICBpc1JlY3Q6IGZhbHNlLFxuICAgICAgICBkZWdlbmVyYXRlOiBmYWxzZSxcbiAgICAgICAgc3VidHJhY3Q6IHBvaW50U2VsZWN0aW9uRGVmLnN1YnRyYWN0XG4gICAgfTtcbn1cblxuLyoqXG4gKiBXcmFwcyBtdWx0aXBsZSBzZWxlY3Rpb24gdGVzdGVycy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fSBsaXN0IC0gQW4gYXJyYXkgb2Ygc2VsZWN0aW9uIHRlc3RlcnMuXG4gKlxuICogQHJldHVybiBhIHNlbGVjdGlvbiB0ZXN0ZXIgb2JqZWN0IHdpdGggYSBjb250YWlucyBmdW5jdGlvblxuICogdGhhdCBjYW4gYmUgY2FsbGVkIHRvIGV2YWx1YXRlIGEgcG9pbnQgYWdhaW5zdCBhbGwgd3JhcHBlZFxuICogc2VsZWN0aW9uIHRlc3RlcnMgdGhhdCB3ZXJlIHBhc3NlZCBpbiBsaXN0LlxuICovXG5mdW5jdGlvbiBtdWx0aVRlc3RlcihsaXN0KSB7XG4gICAgdmFyIHRlc3RlcnMgPSBbXTtcbiAgICB2YXIgeG1pbiA9IGlzUG9pbnRTZWxlY3Rpb25EZWYobGlzdFswXSkgPyAwIDogbGlzdFswXVswXVswXTtcbiAgICB2YXIgeG1heCA9IHhtaW47XG4gICAgdmFyIHltaW4gPSBpc1BvaW50U2VsZWN0aW9uRGVmKGxpc3RbMF0pID8gMCA6IGxpc3RbMF1bMF1bMV07XG4gICAgdmFyIHltYXggPSB5bWluO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoaXNQb2ludFNlbGVjdGlvbkRlZihsaXN0W2ldKSkge1xuICAgICAgICAgICAgdGVzdGVycy5wdXNoKG5ld1BvaW50TnVtVGVzdGVyKGxpc3RbaV0pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciB0ZXN0ZXIgPSBwb2x5Z29uLnRlc3RlcihsaXN0W2ldKTtcbiAgICAgICAgICAgIHRlc3Rlci5zdWJ0cmFjdCA9IGxpc3RbaV0uc3VidHJhY3Q7XG4gICAgICAgICAgICB0ZXN0ZXJzLnB1c2godGVzdGVyKTtcbiAgICAgICAgICAgIHhtaW4gPSBNYXRoLm1pbih4bWluLCB0ZXN0ZXIueG1pbik7XG4gICAgICAgICAgICB4bWF4ID0gTWF0aC5tYXgoeG1heCwgdGVzdGVyLnhtYXgpO1xuICAgICAgICAgICAgeW1pbiA9IE1hdGgubWluKHltaW4sIHRlc3Rlci55bWluKTtcbiAgICAgICAgICAgIHltYXggPSBNYXRoLm1heCh5bWF4LCB0ZXN0ZXIueW1heCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZXN0cyBpZiB0aGUgZ2l2ZW4gcG9pbnQgaXMgd2l0aGluIHRoaXMgdGVzdGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheX0gcHQgLSBbMF0gaXMgdGhlIHggY29vcmRpbmF0ZSwgWzFdIGlzIHRoZSB5IGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50LlxuICAgICAqIEBwYXJhbSB7Kn0gYXJnIC0gQW4gb3B0aW9uYWwgcGFyYW1ldGVyIHRvIHBhc3MgZG93biB0byB3cmFwcGVkIHRlc3RlcnMuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHBvaW50TnVtYmVyIC0gVGhlIHBvaW50IG51bWJlciBvZiB0aGUgcG9pbnQgd2l0aGluIHRoZSB1bmRlcmx5aW5nIGRhdGEgYXJyYXkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNlYXJjaEluZm8gLSBBbiBvYmplY3QgaWRlbnRpZnlpbmcgdGhlIHRyYWNlIHRoZSBwb2ludCBpcyBjb250YWluZWQgaW4uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtib29sZWFufSB0cnVlIGlmIHBvaW50IGlzIGNvbnNpZGVyZWQgdG8gYmUgc2VsZWN0ZWQsIGZhbHNlIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb250YWlucyhwdCwgYXJnLCBwb2ludE51bWJlciwgc2VhcmNoSW5mbykge1xuICAgICAgICB2YXIgY29udGFpbmVkID0gZmFsc2U7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0ZXN0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZih0ZXN0ZXJzW2ldLmNvbnRhaW5zKHB0LCBhcmcsIHBvaW50TnVtYmVyLCBzZWFyY2hJbmZvKSkge1xuICAgICAgICAgICAgICAgIC8vIGlmIGNvbnRhaW5lZCBieSBzdWJ0cmFjdCB0ZXN0ZXIgLSBleGNsdWRlIHRoZSBwb2ludFxuICAgICAgICAgICAgICAgIGNvbnRhaW5lZCA9IHRlc3RlcnNbaV0uc3VidHJhY3QgPT09IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbnRhaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB4bWluOiB4bWluLFxuICAgICAgICB4bWF4OiB4bWF4LFxuICAgICAgICB5bWluOiB5bWluLFxuICAgICAgICB5bWF4OiB5bWF4LFxuICAgICAgICBwdHM6IFtdLFxuICAgICAgICBjb250YWluczogY29udGFpbnMsXG4gICAgICAgIGlzUmVjdDogZmFsc2UsXG4gICAgICAgIGRlZ2VuZXJhdGU6IGZhbHNlXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY29lcmNlU2VsZWN0aW9uc0NhY2hlKGV2dCwgZ2QsIGRyYWdPcHRpb25zKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgcGxvdGluZm8gPSBkcmFnT3B0aW9ucy5wbG90aW5mbztcblxuICAgIHZhciBzZWxlY3RpbmdPblNhbWVTdWJwbG90ID0gKFxuICAgICAgICBmdWxsTGF5b3V0Ll9sYXN0U2VsZWN0ZWRTdWJwbG90ICYmXG4gICAgICAgIGZ1bGxMYXlvdXQuX2xhc3RTZWxlY3RlZFN1YnBsb3QgPT09IHBsb3RpbmZvLmlkXG4gICAgKTtcbiAgICB2YXIgaGFzTW9kaWZpZXJLZXkgPSBldnQuc2hpZnRLZXkgfHwgZXZ0LmFsdEtleTtcblxuICAgIGlmKHNlbGVjdGluZ09uU2FtZVN1YnBsb3QgJiYgaGFzTW9kaWZpZXJLZXkgJiZcbiAgICAgIChwbG90aW5mby5zZWxlY3Rpb24gJiYgcGxvdGluZm8uc2VsZWN0aW9uLnNlbGVjdGlvbkRlZnMpICYmICFkcmFnT3B0aW9ucy5zZWxlY3Rpb25EZWZzKSB7XG4gICAgICAgIC8vIHRha2Ugb3ZlciBzZWxlY3Rpb24gZGVmaW5pdGlvbnMgZnJvbSBwcmV2IG1vZGUsIGlmIGFueVxuICAgICAgICBkcmFnT3B0aW9ucy5zZWxlY3Rpb25EZWZzID0gcGxvdGluZm8uc2VsZWN0aW9uLnNlbGVjdGlvbkRlZnM7XG4gICAgICAgIGRyYWdPcHRpb25zLm1lcmdlZFBvbHlnb25zID0gcGxvdGluZm8uc2VsZWN0aW9uLm1lcmdlZFBvbHlnb25zO1xuICAgIH0gZWxzZSBpZighaGFzTW9kaWZpZXJLZXkgfHwgIXBsb3RpbmZvLnNlbGVjdGlvbikge1xuICAgICAgICBjbGVhclNlbGVjdGlvbnNDYWNoZShkcmFnT3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLy8gY2xlYXIgc2VsZWN0aW9uIG91dGxpbmUgd2hlbiBzZWxlY3RpbmcgYSBkaWZmZXJlbnQgc3VicGxvdFxuICAgIGlmKCFzZWxlY3RpbmdPblNhbWVTdWJwbG90KSB7XG4gICAgICAgIGNsZWFyU2VsZWN0KGdkKTtcbiAgICAgICAgZnVsbExheW91dC5fbGFzdFNlbGVjdGVkU3VicGxvdCA9IHBsb3RpbmZvLmlkO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gY2xlYXJTZWxlY3Rpb25zQ2FjaGUoZHJhZ09wdGlvbnMpIHtcbiAgICB2YXIgcGxvdGluZm8gPSBkcmFnT3B0aW9ucy5wbG90aW5mbztcblxuICAgIHBsb3RpbmZvLnNlbGVjdGlvbiA9IHt9O1xuICAgIHBsb3RpbmZvLnNlbGVjdGlvbi5zZWxlY3Rpb25EZWZzID0gZHJhZ09wdGlvbnMuc2VsZWN0aW9uRGVmcyA9IFtdO1xuICAgIHBsb3RpbmZvLnNlbGVjdGlvbi5tZXJnZWRQb2x5Z29ucyA9IGRyYWdPcHRpb25zLm1lcmdlZFBvbHlnb25zID0gW107XG59XG5cbmZ1bmN0aW9uIGRldGVybWluZVNlYXJjaFRyYWNlcyhnZCwgeEF4ZXMsIHlBeGVzLCBzdWJwbG90KSB7XG4gICAgdmFyIHNlYXJjaFRyYWNlcyA9IFtdO1xuICAgIHZhciB4QXhpc0lkcyA9IHhBeGVzLm1hcChnZXRBeElkKTtcbiAgICB2YXIgeUF4aXNJZHMgPSB5QXhlcy5tYXAoZ2V0QXhJZCk7XG4gICAgdmFyIGNkLCB0cmFjZSwgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IGdkLmNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNkID0gZ2QuY2FsY2RhdGFbaV07XG4gICAgICAgIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSAhPT0gdHJ1ZSB8fCAhdHJhY2UuX21vZHVsZSB8fCAhdHJhY2UuX21vZHVsZS5zZWxlY3RQb2ludHMpIGNvbnRpbnVlO1xuXG4gICAgICAgIGlmKHN1YnBsb3QgJiYgKHRyYWNlLnN1YnBsb3QgPT09IHN1YnBsb3QgfHwgdHJhY2UuZ2VvID09PSBzdWJwbG90KSkge1xuICAgICAgICAgICAgc2VhcmNoVHJhY2VzLnB1c2goY3JlYXRlU2VhcmNoSW5mbyh0cmFjZS5fbW9kdWxlLCBjZCwgeEF4ZXNbMF0sIHlBeGVzWzBdKSk7XG4gICAgICAgIH0gZWxzZSBpZihcbiAgICAgICAgICB0cmFjZS50eXBlID09PSAnc3Bsb20nICYmXG4gICAgICAgICAgLy8gRklYTUU6IG1ha2Ugc3VyZSB3ZSBkb24ndCBoYXZlIG1vcmUgdGhhbiBzaW5nbGUgYXhpcyBmb3Igc3Bsb21cbiAgICAgICAgICB0cmFjZS5feGF4ZXNbeEF4aXNJZHNbMF1dICYmIHRyYWNlLl95YXhlc1t5QXhpc0lkc1swXV1cbiAgICAgICAgKSB7XG4gICAgICAgICAgICB2YXIgaW5mbyA9IGNyZWF0ZVNlYXJjaEluZm8odHJhY2UuX21vZHVsZSwgY2QsIHhBeGVzWzBdLCB5QXhlc1swXSk7XG4gICAgICAgICAgICBpbmZvLnNjZW5lID0gZ2QuX2Z1bGxMYXlvdXQuX3NwbG9tU2NlbmVzW3RyYWNlLnVpZF07XG4gICAgICAgICAgICBzZWFyY2hUcmFjZXMucHVzaChpbmZvKTtcbiAgICAgICAgfSBlbHNlIGlmKFxuICAgICAgICAgIHRyYWNlLnR5cGUgPT09ICdzYW5rZXknXG4gICAgICAgICkge1xuICAgICAgICAgICAgdmFyIHNhbmtleUluZm8gPSBjcmVhdGVTZWFyY2hJbmZvKHRyYWNlLl9tb2R1bGUsIGNkLCB4QXhlc1swXSwgeUF4ZXNbMF0pO1xuICAgICAgICAgICAgc2VhcmNoVHJhY2VzLnB1c2goc2Fua2V5SW5mbyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZih4QXhpc0lkcy5pbmRleE9mKHRyYWNlLnhheGlzKSA9PT0gLTEpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYoeUF4aXNJZHMuaW5kZXhPZih0cmFjZS55YXhpcykgPT09IC0xKSBjb250aW51ZTtcblxuICAgICAgICAgICAgc2VhcmNoVHJhY2VzLnB1c2goY3JlYXRlU2VhcmNoSW5mbyh0cmFjZS5fbW9kdWxlLCBjZCxcbiAgICAgICAgICAgICAgZ2V0RnJvbUlkKGdkLCB0cmFjZS54YXhpcyksIGdldEZyb21JZChnZCwgdHJhY2UueWF4aXMpKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2VhcmNoVHJhY2VzO1xuXG4gICAgZnVuY3Rpb24gY3JlYXRlU2VhcmNoSW5mbyhtb2R1bGUsIGNhbGNEYXRhLCB4YXhpcywgeWF4aXMpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIF9tb2R1bGU6IG1vZHVsZSxcbiAgICAgICAgICAgIGNkOiBjYWxjRGF0YSxcbiAgICAgICAgICAgIHhheGlzOiB4YXhpcyxcbiAgICAgICAgICAgIHlheGlzOiB5YXhpc1xuICAgICAgICB9O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZHJhd1NlbGVjdGlvbihwb2x5Z29ucywgb3V0bGluZXMpIHtcbiAgICB2YXIgcGF0aHMgPSBbXTtcbiAgICB2YXIgaSwgZDtcblxuICAgIGZvcihpID0gMDsgaSA8IHBvbHlnb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwcHRzID0gcG9seWdvbnNbaV07XG4gICAgICAgIHBhdGhzLnB1c2gocHB0cy5qb2luKCdMJykgKyAnTCcgKyBwcHRzWzBdKTtcbiAgICB9XG5cbiAgICBkID0gcG9seWdvbnMubGVuZ3RoID4gMCA/XG4gICAgICAnTScgKyBwYXRocy5qb2luKCdNJykgKyAnWicgOlxuICAgICAgJ00wLDBaJztcbiAgICBvdXRsaW5lcy5hdHRyKCdkJywgZCk7XG59XG5cbmZ1bmN0aW9uIGlzSG92ZXJEYXRhU2V0KGhvdmVyRGF0YSkge1xuICAgIHJldHVybiBob3ZlckRhdGEgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkoaG92ZXJEYXRhKSAmJlxuICAgICAgaG92ZXJEYXRhWzBdLmhvdmVyT25Cb3ggIT09IHRydWU7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RDbGlja2VkUHRJbmZvKGhvdmVyRGF0YSwgc2VhcmNoVHJhY2VzKSB7XG4gICAgdmFyIGhvdmVyRGF0dW0gPSBob3ZlckRhdGFbMF07XG4gICAgdmFyIHBvaW50TnVtYmVyID0gLTE7XG4gICAgdmFyIHBvaW50TnVtYmVycyA9IFtdO1xuICAgIHZhciBzZWFyY2hJbmZvLCBpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgc2VhcmNoVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHNlYXJjaEluZm8gPSBzZWFyY2hUcmFjZXNbaV07XG4gICAgICAgIGlmKGhvdmVyRGF0dW0uZnVsbERhdGEuX2V4cGFuZGVkSW5kZXggPT09IHNlYXJjaEluZm8uY2RbMF0udHJhY2UuX2V4cGFuZGVkSW5kZXgpIHtcbiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgYm94IChhbmQgdmlvbGluKVxuICAgICAgICAgICAgaWYoaG92ZXJEYXR1bS5ob3Zlck9uQm94ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEhpbnQ6IGluIHNvbWUgdHJhY2VzIGxpa2UgaGlzdG9ncmFtLCBvbmUgZ3JhcGhpY2FsIGVsZW1lbnRcbiAgICAgICAgICAgIC8vIGRvZXNuJ3QgY29ycmVzcG9uZCB0byBvbmUgcGFydGljdWxhciBkYXRhIHBvaW50LCBidXQgdG9cbiAgICAgICAgICAgIC8vIGJpbnMgb2YgZGF0YSBwb2ludHMuIFRodXMsIGhvdmVyRGF0dW0gY2FuIGhhdmUgYSBiaW5OdW1iZXJcbiAgICAgICAgICAgIC8vIHByb3BlcnR5IGluc3RlYWQgb2YgcG9pbnROdW1iZXIuXG4gICAgICAgICAgICBpZihob3ZlckRhdHVtLnBvaW50TnVtYmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBwb2ludE51bWJlciA9IGhvdmVyRGF0dW0ucG9pbnROdW1iZXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYoaG92ZXJEYXR1bS5iaW5OdW1iZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHBvaW50TnVtYmVyID0gaG92ZXJEYXR1bS5iaW5OdW1iZXI7XG4gICAgICAgICAgICAgICAgcG9pbnROdW1iZXJzID0gaG92ZXJEYXR1bS5wb2ludE51bWJlcnM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgcG9pbnROdW1iZXI6IHBvaW50TnVtYmVyLFxuICAgICAgICBwb2ludE51bWJlcnM6IHBvaW50TnVtYmVycyxcbiAgICAgICAgc2VhcmNoSW5mbzogc2VhcmNoSW5mb1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGlzUG9pbnRPckJpblNlbGVjdGVkKGNsaWNrZWRQdEluZm8pIHtcbiAgICB2YXIgdHJhY2UgPSBjbGlja2VkUHRJbmZvLnNlYXJjaEluZm8uY2RbMF0udHJhY2U7XG4gICAgdmFyIHB0TnVtID0gY2xpY2tlZFB0SW5mby5wb2ludE51bWJlcjtcbiAgICB2YXIgcHROdW1zID0gY2xpY2tlZFB0SW5mby5wb2ludE51bWJlcnM7XG4gICAgdmFyIHB0TnVtc1NldCA9IHB0TnVtcy5sZW5ndGggPiAwO1xuXG4gICAgLy8gV2hlbiBwb2ludHNOdW1iZXJzIGlzIHNldCAoZS5nLiBoaXN0b2dyYW0ncyBiaW5uaW5nKSxcbiAgICAvLyBpdCBpcyBhc3N1bWVkIHRoYXQgd2hlbiB0aGUgZmlyc3QgcG9pbnQgb2ZcbiAgICAvLyBhIGJpbiBpcyBzZWxlY3RlZCwgYWxsIG90aGVycyBhcmUgYXMgd2VsbFxuICAgIHZhciBwdE51bVRvVGVzdCA9IHB0TnVtc1NldCA/IHB0TnVtc1swXSA6IHB0TnVtO1xuXG4gICAgLy8gVE9ETyBwb3RlbnRpYWwgcGVyZm9ybWFuY2UgaW1wcm92ZW1lbnRcbiAgICAvLyBQcmltYXJpbHkgd2UgbmVlZCB0aGlzIGZ1bmN0aW9uIHRvIGRldGVybWluZSBpZiBhIGNsaWNrIGFkZHNcbiAgICAvLyBvciBzdWJ0cmFjdHMgZnJvbSBhIHNlbGVjdGlvbi5cbiAgICAvLyBJbiBjYXNlcyBgdHJhY2Uuc2VsZWN0ZWRwb2ludHNgIGlzIGEgaHVnZSBhcnJheSwgaW5kZXhPZlxuICAgIC8vIG1pZ2h0IGJlIHNsb3cuIE9uZSByZW1lZHkgd291bGQgYmUgdG8gaW50cm9kdWNlIGEgaGFzaCBzb21ld2hlcmUuXG4gICAgcmV0dXJuIHRyYWNlLnNlbGVjdGVkcG9pbnRzID8gdHJhY2Uuc2VsZWN0ZWRwb2ludHMuaW5kZXhPZihwdE51bVRvVGVzdCkgPiAtMSA6IGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc09ubHlUaGlzQmluU2VsZWN0ZWQoc2VhcmNoVHJhY2VzLCBjbGlja2VkUHRJbmZvKSB7XG4gICAgdmFyIHRyYWNlc1dpdGhTZWxlY3RlZFB0cyA9IFtdO1xuICAgIHZhciBzZWFyY2hJbmZvLCB0cmFjZSwgaXNTYW1lVHJhY2UsIGk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzZWFyY2hUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc2VhcmNoSW5mbyA9IHNlYXJjaFRyYWNlc1tpXTtcbiAgICAgICAgaWYoc2VhcmNoSW5mby5jZFswXS50cmFjZS5zZWxlY3RlZHBvaW50cyAmJiBzZWFyY2hJbmZvLmNkWzBdLnRyYWNlLnNlbGVjdGVkcG9pbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHRyYWNlc1dpdGhTZWxlY3RlZFB0cy5wdXNoKHNlYXJjaEluZm8pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYodHJhY2VzV2l0aFNlbGVjdGVkUHRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBpc1NhbWVUcmFjZSA9IHRyYWNlc1dpdGhTZWxlY3RlZFB0c1swXSA9PT0gY2xpY2tlZFB0SW5mby5zZWFyY2hJbmZvO1xuICAgICAgICBpZihpc1NhbWVUcmFjZSkge1xuICAgICAgICAgICAgdHJhY2UgPSBjbGlja2VkUHRJbmZvLnNlYXJjaEluZm8uY2RbMF0udHJhY2U7XG4gICAgICAgICAgICBpZih0cmFjZS5zZWxlY3RlZHBvaW50cy5sZW5ndGggPT09IGNsaWNrZWRQdEluZm8ucG9pbnROdW1iZXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNsaWNrZWRQdEluZm8ucG9pbnROdW1iZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKHRyYWNlLnNlbGVjdGVkcG9pbnRzLmluZGV4T2YoY2xpY2tlZFB0SW5mby5wb2ludE51bWJlcnNbaV0pIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc09ubHlPbmVQb2ludFNlbGVjdGVkKHNlYXJjaFRyYWNlcykge1xuICAgIHZhciBsZW4gPSAwO1xuICAgIHZhciBzZWFyY2hJbmZvLCB0cmFjZSwgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IHNlYXJjaFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzZWFyY2hJbmZvID0gc2VhcmNoVHJhY2VzW2ldO1xuICAgICAgICB0cmFjZSA9IHNlYXJjaEluZm8uY2RbMF0udHJhY2U7XG4gICAgICAgIGlmKHRyYWNlLnNlbGVjdGVkcG9pbnRzKSB7XG4gICAgICAgICAgICBpZih0cmFjZS5zZWxlY3RlZHBvaW50cy5sZW5ndGggPiAxKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgICAgIGxlbiArPSB0cmFjZS5zZWxlY3RlZHBvaW50cy5sZW5ndGg7XG4gICAgICAgICAgICBpZihsZW4gPiAxKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGVuID09PSAxO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVTZWxlY3RlZFN0YXRlKGdkLCBzZWFyY2hUcmFjZXMsIGV2ZW50RGF0YSkge1xuICAgIHZhciBpLCBzZWFyY2hJbmZvLCBjZCwgdHJhY2U7XG5cbiAgICAvLyBiZWZvcmUgYW55dGhpbmcgZWxzZSwgdXBkYXRlIHByZUdVSSBpZiBuZWNlc3NhcnlcbiAgICBmb3IoaSA9IDA7IGkgPCBzZWFyY2hUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGZ1bGxJbnB1dFRyYWNlID0gc2VhcmNoVHJhY2VzW2ldLmNkWzBdLnRyYWNlLl9mdWxsSW5wdXQ7XG4gICAgICAgIHZhciB0cmFjZVByZUdVSSA9IGdkLl9mdWxsTGF5b3V0Ll90cmFjZVByZUdVSVtmdWxsSW5wdXRUcmFjZS51aWRdIHx8IHt9O1xuICAgICAgICBpZih0cmFjZVByZUdVSS5zZWxlY3RlZHBvaW50cyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0cmFjZVByZUdVSS5zZWxlY3RlZHBvaW50cyA9IGZ1bGxJbnB1dFRyYWNlLl9pbnB1dC5zZWxlY3RlZHBvaW50cyB8fCBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoZXZlbnREYXRhKSB7XG4gICAgICAgIHZhciBwdHMgPSBldmVudERhdGEucG9pbnRzIHx8IFtdO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHNlYXJjaFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdHJhY2UgPSBzZWFyY2hUcmFjZXNbaV0uY2RbMF0udHJhY2U7XG4gICAgICAgICAgICB0cmFjZS5faW5wdXQuc2VsZWN0ZWRwb2ludHMgPSB0cmFjZS5fZnVsbElucHV0LnNlbGVjdGVkcG9pbnRzID0gW107XG4gICAgICAgICAgICBpZih0cmFjZS5fZnVsbElucHV0ICE9PSB0cmFjZSkgdHJhY2Uuc2VsZWN0ZWRwb2ludHMgPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHB0ID0gcHRzW2ldO1xuICAgICAgICAgICAgdmFyIGRhdGEgPSBwdC5kYXRhO1xuICAgICAgICAgICAgdmFyIGZ1bGxEYXRhID0gcHQuZnVsbERhdGE7XG5cbiAgICAgICAgICAgIGlmKHB0LnBvaW50SW5kaWNlcykge1xuICAgICAgICAgICAgICAgIFtdLnB1c2guYXBwbHkoZGF0YS5zZWxlY3RlZHBvaW50cywgcHQucG9pbnRJbmRpY2VzKTtcbiAgICAgICAgICAgICAgICBpZih0cmFjZS5fZnVsbElucHV0ICE9PSB0cmFjZSkge1xuICAgICAgICAgICAgICAgICAgICBbXS5wdXNoLmFwcGx5KGZ1bGxEYXRhLnNlbGVjdGVkcG9pbnRzLCBwdC5wb2ludEluZGljZXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGF0YS5zZWxlY3RlZHBvaW50cy5wdXNoKHB0LnBvaW50SW5kZXgpO1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlLl9mdWxsSW5wdXQgIT09IHRyYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bGxEYXRhLnNlbGVjdGVkcG9pbnRzLnB1c2gocHQucG9pbnRJbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2VhcmNoVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0cmFjZSA9IHNlYXJjaFRyYWNlc1tpXS5jZFswXS50cmFjZTtcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5zZWxlY3RlZHBvaW50cztcbiAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5faW5wdXQuc2VsZWN0ZWRwb2ludHM7XG4gICAgICAgICAgICBpZih0cmFjZS5fZnVsbElucHV0ICE9PSB0cmFjZSkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0cmFjZS5fZnVsbElucHV0LnNlbGVjdGVkcG9pbnRzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGhhc1JlZ2wgPSBmYWxzZTtcblxuICAgIGZvcihpID0gMDsgaSA8IHNlYXJjaFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzZWFyY2hJbmZvID0gc2VhcmNoVHJhY2VzW2ldO1xuICAgICAgICBjZCA9IHNlYXJjaEluZm8uY2Q7XG4gICAgICAgIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3JlZ2wnKSkge1xuICAgICAgICAgICAgaGFzUmVnbCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgX21vZHVsZSA9IHNlYXJjaEluZm8uX21vZHVsZTtcbiAgICAgICAgdmFyIGZuID0gX21vZHVsZS5zdHlsZU9uU2VsZWN0IHx8IF9tb2R1bGUuc3R5bGU7XG4gICAgICAgIGlmKGZuKSB7XG4gICAgICAgICAgICBmbihnZCwgY2QsIGNkWzBdLm5vZGUzKTtcbiAgICAgICAgICAgIGlmKGNkWzBdLm5vZGVSYW5nZVBsb3QzKSBmbihnZCwgY2QsIGNkWzBdLm5vZGVSYW5nZVBsb3QzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGhhc1JlZ2wpIHtcbiAgICAgICAgY2xlYXJHbENhbnZhc2VzKGdkKTtcbiAgICAgICAgcmVkcmF3UmVnbFRyYWNlcyhnZCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBtZXJnZVBvbHlnb25zKGxpc3QsIHBvbHksIHN1YnRyYWN0KSB7XG4gICAgdmFyIHJlcztcblxuICAgIGlmKHN1YnRyYWN0KSB7XG4gICAgICAgIHJlcyA9IHBvbHlib29sLmRpZmZlcmVuY2Uoe1xuICAgICAgICAgICAgcmVnaW9uczogbGlzdCxcbiAgICAgICAgICAgIGludmVydGVkOiBmYWxzZVxuICAgICAgICB9LCB7XG4gICAgICAgICAgICByZWdpb25zOiBbcG9seV0sXG4gICAgICAgICAgICBpbnZlcnRlZDogZmFsc2VcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHJlcy5yZWdpb25zO1xuICAgIH1cblxuICAgIHJlcyA9IHBvbHlib29sLnVuaW9uKHtcbiAgICAgICAgcmVnaW9uczogbGlzdCxcbiAgICAgICAgaW52ZXJ0ZWQ6IGZhbHNlXG4gICAgfSwge1xuICAgICAgICByZWdpb25zOiBbcG9seV0sXG4gICAgICAgIGludmVydGVkOiBmYWxzZVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlcy5yZWdpb25zO1xufVxuXG5mdW5jdGlvbiBmaWxsU2VsZWN0aW9uSXRlbShzZWxlY3Rpb24sIHNlYXJjaEluZm8pIHtcbiAgICBpZihBcnJheS5pc0FycmF5KHNlbGVjdGlvbikpIHtcbiAgICAgICAgdmFyIGNkID0gc2VhcmNoSW5mby5jZDtcbiAgICAgICAgdmFyIHRyYWNlID0gc2VhcmNoSW5mby5jZFswXS50cmFjZTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2VsZWN0aW9uLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzZWxlY3Rpb25baV0gPSBtYWtlRXZlbnREYXRhKHNlbGVjdGlvbltpXSwgdHJhY2UsIGNkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzZWxlY3Rpb247XG59XG5cbi8vIHVudGlsIHdlIGdldCBhcm91bmQgdG8gcGVyc2lzdGVudCBzZWxlY3Rpb25zLCByZW1vdmUgdGhlIG91dGxpbmVcbi8vIGhlcmUuIFRoZSBzZWxlY3Rpb24gaXRzZWxmIHdpbGwgYmUgcmVtb3ZlZCB3aGVuIHRoZSBwbG90IHJlZHJhd3Ncbi8vIGF0IHRoZSBlbmQuXG5mdW5jdGlvbiBjbGVhclNlbGVjdChnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQgfHwge307XG4gICAgdmFyIHpvb21sYXllciA9IGZ1bGxMYXlvdXQuX3pvb21sYXllcjtcbiAgICBpZih6b29tbGF5ZXIpIHtcbiAgICAgICAgem9vbWxheWVyLnNlbGVjdEFsbCgnLnNlbGVjdC1vdXRsaW5lJykucmVtb3ZlKCk7XG4gICAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBwcmVwU2VsZWN0OiBwcmVwU2VsZWN0LFxuICAgIGNsZWFyU2VsZWN0OiBjbGVhclNlbGVjdCxcbiAgICBzZWxlY3RPbkNsaWNrOiBzZWxlY3RPbkNsaWNrXG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi4vLi4vY29tcG9uZW50cy9meC9oZWxwZXJzXCI6NjI4LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL2NsZWFyX2dsX2NhbnZhc2VzXCI6NzA0LFwiLi4vLi4vbGliL3BvbHlnb25cIjo3MzEsXCIuLi8uLi9saWIvdGhyb3R0bGVcIjo3NDQsXCIuLi8uLi9wbG90X2FwaS9zdWJyb3V0aW5lc1wiOjc1OCxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9heGlzX2lkc1wiOjc3MCxcIi4vY29uc3RhbnRzXCI6NzczLFwicG9seWJvb2xqc1wiOjQ3M31dLDc4NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGNsZWFuTnVtYmVyID0gTGliLmNsZWFuTnVtYmVyO1xudmFyIG1zMkRhdGVUaW1lID0gTGliLm1zMkRhdGVUaW1lO1xudmFyIGRhdGVUaW1lMm1zID0gTGliLmRhdGVUaW1lMm1zO1xudmFyIGVuc3VyZU51bWJlciA9IExpYi5lbnN1cmVOdW1iZXI7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5O1xuXG52YXIgbnVtQ29uc3RhbnRzID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpO1xudmFyIEZQX1NBRkUgPSBudW1Db25zdGFudHMuRlBfU0FGRTtcbnZhciBCQUROVU0gPSBudW1Db25zdGFudHMuQkFETlVNO1xudmFyIExPR19DTElQID0gbnVtQ29uc3RhbnRzLkxPR19DTElQO1xuXG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcbnZhciBheGlzSWRzID0gX2RlcmVxXygnLi9heGlzX2lkcycpO1xuXG5mdW5jdGlvbiBmcm9tTG9nKHYpIHtcbiAgICByZXR1cm4gTWF0aC5wb3coMTAsIHYpO1xufVxuXG5mdW5jdGlvbiBpc1ZhbGlkQ2F0ZWdvcnkodikge1xuICAgIHJldHVybiB2ICE9PSBudWxsICYmIHYgIT09IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBEZWZpbmUgdGhlIGNvbnZlcnNpb24gZnVuY3Rpb25zIGZvciBhbiBheGlzIGRhdGEgaXMgdXNlZCBpbiA1IHdheXM6XG4gKlxuICogIGQ6IGRhdGEsIGluIHdoYXRldmVyIGZvcm0gaXQncyBwcm92aWRlZFxuICogIGM6IGNhbGNkYXRhOiB0dXJuZWQgaW50byBudW1iZXJzLCBidXQgbm90IGxpbmVhcml6ZWRcbiAqICBsOiBsaW5lYXJpemVkIC0gc2FtZSBhcyBjIGV4Y2VwdCBmb3IgbG9nIGF4ZXMgKGFuZCBvdGhlciBub25saW5lYXJcbiAqICAgICAgbWFwcGluZ3MgbGF0ZXI/KSB0aGlzIGlzIHVzZWQgd2hlbiB3ZSBuZWVkIHRvIGtub3cgaWYgaXQnc1xuICogICAgICAqcG9zc2libGUqIHRvIHNob3cgc29tZSBkYXRhIG9uIHRoaXMgYXhpcywgd2l0aG91dCBjYXJpbmcgYWJvdXRcbiAqICAgICAgdGhlIGN1cnJlbnQgcmFuZ2VcbiAqICBwOiBwaXhlbCB2YWx1ZSAtIG1hcHBlZCB0byB0aGUgc2NyZWVuIHdpdGggY3VycmVudCBzaXplIGFuZCB6b29tXG4gKiAgcjogcmFuZ2VzLCB0aWNrMCwgYW5kIGFubm90YXRpb24gcG9zaXRpb25zIG1hdGNoIG9uZSBvZiB0aGUgYWJvdmVcbiAqICAgICBidXQgYXJlIGhhbmRsZWQgZGlmZmVyZW50bHkgZm9yIGRpZmZlcmVudCB0eXBlczpcbiAqICAgICAtIGxpbmVhciBhbmQgZGF0ZTogZGF0YSBmb3JtYXQgKGQpXG4gKiAgICAgLSBjYXRlZ29yeTogY2FsY2RhdGEgZm9ybWF0IChjKSwgYW5kIHdpbGwgc3RheSB0aGF0IHdheSBiZWNhdXNlXG4gKiAgICAgICB0aGUgZGF0YSBmb3JtYXQgaGFzIG5vIGNvbnRpbnVvdXMgbWFwcGluZ1xuICogICAgIC0gbG9nOiBsaW5lYXJpemVkIChsKSBmb3JtYXRcbiAqICAgICAgIFRPRE86IGluIHYyLjAgd2UgcGxhbiB0byBjaGFuZ2UgaXQgdG8gZGF0YSBmb3JtYXQuIEF0IHRoYXQgcG9pbnRcbiAqICAgICAgIHNoYXBlcyB3aWxsIHdvcmsgdGhlIHNhbWUgd2F5IGFzIHJhbmdlcywgdGljazAsIGFuZCBhbm5vdGF0aW9uc1xuICogICAgICAgc28gdGhleSBjYW4gdXNlIHRoaXMgY29udmVyc2lvbiB0b28uXG4gKlxuICogQ3JlYXRlcy91cGRhdGVzIHRoZXNlIGNvbnZlcnNpb24gZnVuY3Rpb25zLCBhbmQgYSBmZXcgbW9yZSB1dGlsaXRpZXNcbiAqIGxpa2UgY2xlYW5SYW5nZSwgYW5kIG1ha2VDYWxjZGF0YVxuICpcbiAqIGFsc28gY2xlYXJzIHRoZSBhdXRvdGljayBjb25zdHJhaW50cyAuX21pbkR0aWNrLCAuX2ZvcmNlVGljazBcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzZXRDb252ZXJ0KGF4LCBmdWxsTGF5b3V0KSB7XG4gICAgZnVsbExheW91dCA9IGZ1bGxMYXlvdXQgfHwge307XG5cbiAgICB2YXIgYXhJZCA9IChheC5faWQgfHwgJ3gnKTtcbiAgICB2YXIgYXhMZXR0ZXIgPSBheElkLmNoYXJBdCgwKTtcblxuICAgIGZ1bmN0aW9uIHRvTG9nKHYsIGNsaXApIHtcbiAgICAgICAgaWYodiA+IDApIHJldHVybiBNYXRoLmxvZyh2KSAvIE1hdGguTE4xMDtcblxuICAgICAgICBlbHNlIGlmKHYgPD0gMCAmJiBjbGlwICYmIGF4LnJhbmdlICYmIGF4LnJhbmdlLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgLy8gY2xpcCBOYU4gKGllIHBhc3QgbmVnYXRpdmUgaW5maW5pdHkpIHRvIExPR19DTElQIGF4aXNcbiAgICAgICAgICAgIC8vIGxlbmd0aCBwYXN0IHRoZSBuZWdhdGl2ZSBlZGdlXG4gICAgICAgICAgICB2YXIgcjAgPSBheC5yYW5nZVswXTtcbiAgICAgICAgICAgIHZhciByMSA9IGF4LnJhbmdlWzFdO1xuICAgICAgICAgICAgcmV0dXJuIDAuNSAqIChyMCArIHIxIC0gMiAqIExPR19DTElQICogTWF0aC5hYnMocjAgLSByMSkpO1xuICAgICAgICB9IGVsc2UgcmV0dXJuIEJBRE5VTTtcbiAgICB9XG5cbiAgICAvKlxuICAgICAqIHdyYXBwZWQgZGF0ZVRpbWUybXMgdGhhdDpcbiAgICAgKiAtIGFjY2VwdHMgbXMgbnVtYmVycyBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eVxuICAgICAqIC0gaW5zZXJ0cyBhIGR1bW15IGFyZyBzbyBjYWxlbmRhciBpcyB0aGUgM3JkIGFyZyAoc2VlIG5vdGVzIGJlbG93KS5cbiAgICAgKiAtIGRlZmF1bHRzIHRvIGF4LmNhbGVuZGFyXG4gICAgICovXG4gICAgZnVuY3Rpb24gZHQybXModiwgXywgY2FsZW5kYXIpIHtcbiAgICAgICAgLy8gTk9URTogQ2hhbmdlZCB0aGlzIGJlaGF2aW9yOiBwcmV2aW91c2x5IHdlIHRvb2sgYW55IG51bWVyaWMgdmFsdWVcbiAgICAgICAgLy8gdG8gYmUgYSBtcywgZXZlbiBpZiBpdCB3YXMgYSBzdHJpbmcgdGhhdCBjb3VsZCBiZSBhIGJhcmUgeWVhci5cbiAgICAgICAgLy8gTm93IHdlIGNvbnZlcnQgaXQgYXMgYSBkYXRlIGlmIGF0IGFsbCBwb3NzaWJsZSwgYW5kIG9ubHkgdHJ5XG4gICAgICAgIC8vIGFzIChsb2NhbCkgbXMgaWYgdGhhdCBmYWlscy5cbiAgICAgICAgdmFyIG1zID0gZGF0ZVRpbWUybXModiwgY2FsZW5kYXIgfHwgYXguY2FsZW5kYXIpO1xuICAgICAgICBpZihtcyA9PT0gQkFETlVNKSB7XG4gICAgICAgICAgICBpZihpc051bWVyaWModikpIHtcbiAgICAgICAgICAgICAgICB2ID0gK3Y7XG4gICAgICAgICAgICAgICAgLy8ga2VlcCB0cmFjayBvZiB0ZW50aHMgb2YgbXMsIHRoYXQgYG5ldyBEYXRlYCB3aWxsIGRyb3BcbiAgICAgICAgICAgICAgICAvLyBzYW1lIGxvZ2ljIGFzIGluIExpYi5tczJEYXRlVGltZVxuICAgICAgICAgICAgICAgIHZhciBtc2VjVGVudGhzID0gTWF0aC5mbG9vcihMaWIubW9kKHYgKyAwLjA1LCAxKSAqIDEwKTtcbiAgICAgICAgICAgICAgICB2YXIgbXNSb3VuZGVkID0gTWF0aC5yb3VuZCh2IC0gbXNlY1RlbnRocyAvIDEwKTtcbiAgICAgICAgICAgICAgICBtcyA9IGRhdGVUaW1lMm1zKG5ldyBEYXRlKG1zUm91bmRlZCkpICsgbXNlY1RlbnRocyAvIDEwO1xuICAgICAgICAgICAgfSBlbHNlIHJldHVybiBCQUROVU07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1zO1xuICAgIH1cblxuICAgIC8vIHdyYXBwZWQgbXMyRGF0ZVRpbWUgdG8gaW5zZXJ0IGRlZmF1bHQgYXguY2FsZW5kYXJcbiAgICBmdW5jdGlvbiBtczJkdCh2LCByLCBjYWxlbmRhcikge1xuICAgICAgICByZXR1cm4gbXMyRGF0ZVRpbWUodiwgciwgY2FsZW5kYXIgfHwgYXguY2FsZW5kYXIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldENhdGVnb3J5TmFtZSh2KSB7XG4gICAgICAgIHJldHVybiBheC5fY2F0ZWdvcmllc1tNYXRoLnJvdW5kKHYpXTtcbiAgICB9XG5cbiAgICAvKlxuICAgICAqIHNldENhdGVnb3J5SW5kZXg6IHJldHVybiB0aGUgaW5kZXggb2YgY2F0ZWdvcnkgdixcbiAgICAgKiBpbnNlcnRpbmcgaXQgaW4gdGhlIGxpc3QgaWYgaXQncyBub3QgYWxyZWFkeSB0aGVyZVxuICAgICAqXG4gICAgICogdGhpcyB3aWxsIGVudGVyIHRoZSBjYXRlZ29yaWVzIGluIHRoZSBvcmRlciBpdFxuICAgICAqIGVuY291bnRlcnMgdGhlbSwgaWUgYWxsIHRoZSBjYXRlZ29yaWVzIGZyb20gdGhlXG4gICAgICogZmlyc3QgZGF0YSBzZXQsIHRoZW4gYWxsIHRoZSBvbmVzIGZyb20gdGhlIHNlY29uZFxuICAgICAqIHRoYXQgYXJlbid0IGluIHRoZSBmaXJzdCBldGMuXG4gICAgICpcbiAgICAgKiBpdCBpcyBhc3N1bWVkIHRoYXQgdGhpcyBmdW5jdGlvbiBpcyBiZWluZyBpbnZva2VkIGluIHRoZVxuICAgICAqIGFscmVhZHkgc29ydGVkIGNhdGVnb3J5IG9yZGVyOyBvdGhlcndpc2UgdGhlcmUgd291bGQgYmVcbiAgICAgKiBhIGRpc2Nvbm5lY3QgYmV0d2VlbiB0aGUgYXJyYXkgYW5kIHRoZSBpbmRleCByZXR1cm5lZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldENhdGVnb3J5SW5kZXgodikge1xuICAgICAgICBpZihpc1ZhbGlkQ2F0ZWdvcnkodikpIHtcbiAgICAgICAgICAgIGlmKGF4Ll9jYXRlZ29yaWVzTWFwID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBheC5fY2F0ZWdvcmllc01hcCA9IHt9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihheC5fY2F0ZWdvcmllc01hcFt2XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGF4Ll9jYXRlZ29yaWVzTWFwW3ZdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBheC5fY2F0ZWdvcmllcy5wdXNoKHR5cGVvZiB2ID09PSAnbnVtYmVyJyA/IFN0cmluZyh2KSA6IHYpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGN1ckxlbmd0aCA9IGF4Ll9jYXRlZ29yaWVzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgYXguX2NhdGVnb3JpZXNNYXBbdl0gPSBjdXJMZW5ndGg7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gY3VyTGVuZ3RoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBCQUROVU07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0TXVsdGlDYXRlZ29yeUluZGV4KGFycmF5SW4sIGxlbikge1xuICAgICAgICB2YXIgYXJyYXlPdXQgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB2MCA9IChhcnJheUluWzBdIHx8IFtdKVtpXTtcbiAgICAgICAgICAgIHZhciB2MSA9IChhcnJheUluWzFdIHx8IFtdKVtpXTtcbiAgICAgICAgICAgIGFycmF5T3V0W2ldID0gZ2V0Q2F0ZWdvcnlJbmRleChbdjAsIHYxXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXJyYXlPdXQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q2F0ZWdvcnlJbmRleCh2KSB7XG4gICAgICAgIGlmKGF4Ll9jYXRlZ29yaWVzTWFwKSB7XG4gICAgICAgICAgICByZXR1cm4gYXguX2NhdGVnb3JpZXNNYXBbdl07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRDYXRlZ29yeVBvc2l0aW9uKHYpIHtcbiAgICAgICAgLy8gZDJsL2QyYyB2YXJpYW50IHRoYXQgdGhhdCB3b24ndCBhZGQgY2F0ZWdvcmllcyBidXQgd2lsbCBhbHNvXG4gICAgICAgIC8vIGFsbG93IG51bWJlcnMgdG8gYmUgbWFwcGVkIHRvIHRoZSBsaW5lYXJpemVkIGF4aXMgcG9zaXRpb25zXG4gICAgICAgIHZhciBpbmRleCA9IGdldENhdGVnb3J5SW5kZXgodik7XG4gICAgICAgIGlmKGluZGV4ICE9PSB1bmRlZmluZWQpIHJldHVybiBpbmRleDtcbiAgICAgICAgaWYoaXNOdW1lcmljKHYpKSByZXR1cm4gK3Y7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbDJwKHYpIHtcbiAgICAgICAgaWYoIWlzTnVtZXJpYyh2KSkgcmV0dXJuIEJBRE5VTTtcblxuICAgICAgICAvLyBpbmNsdWRlIDIgZnJhY3Rpb25hbCBkaWdpdHMgb24gcGl4ZWwsIGZvciBQREYgem9vbWluZyBldGNcbiAgICAgICAgcmV0dXJuIGQzLnJvdW5kKGF4Ll9iICsgYXguX20gKiB2LCAyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwMmwocHgpIHsgcmV0dXJuIChweCAtIGF4Ll9iKSAvIGF4Ll9tOyB9XG5cbiAgICAvLyBjb252ZXJzaW9ucyBhbW9uZyBjL2wvcCBhcmUgZmFpcmx5IHNpbXBsZSAtIGRvIHRoZW0gdG9nZXRoZXIgZm9yIGFsbCBheGlzIHR5cGVzXG4gICAgYXguYzJsID0gKGF4LnR5cGUgPT09ICdsb2cnKSA/IHRvTG9nIDogZW5zdXJlTnVtYmVyO1xuICAgIGF4LmwyYyA9IChheC50eXBlID09PSAnbG9nJykgPyBmcm9tTG9nIDogZW5zdXJlTnVtYmVyO1xuXG4gICAgYXgubDJwID0gbDJwO1xuICAgIGF4LnAybCA9IHAybDtcblxuICAgIGF4LmMycCA9IChheC50eXBlID09PSAnbG9nJykgPyBmdW5jdGlvbih2LCBjbGlwKSB7IHJldHVybiBsMnAodG9Mb2codiwgY2xpcCkpOyB9IDogbDJwO1xuICAgIGF4LnAyYyA9IChheC50eXBlID09PSAnbG9nJykgPyBmdW5jdGlvbihweCkgeyByZXR1cm4gZnJvbUxvZyhwMmwocHgpKTsgfSA6IHAybDtcblxuICAgIC8qXG4gICAgICogbm93IHR5cGUtc3BlY2lmaWMgY29udmVyc2lvbnMgZm9yICoqQUxMKiogb3RoZXIgY29tYmluYXRpb25zXG4gICAgICogdGhleSdyZSBhbGwgd3JpdHRlbiBvdXQsIGluc3RlYWQgb2YgYmVpbmcgY29tYmluYXRpb25zIG9mIGVhY2ggb3RoZXIsIGZvclxuICAgICAqIGJvdGggY2xhcml0eSBhbmQgc3BlZWQuXG4gICAgICovXG4gICAgaWYoWydsaW5lYXInLCAnLSddLmluZGV4T2YoYXgudHlwZSkgIT09IC0xKSB7XG4gICAgICAgIC8vIGFsbCBhcmUgZGF0YSB2YWxzLCBidXQgZCBhbmQgciBuZWVkIGNsZWFuaW5nXG4gICAgICAgIGF4LmQyciA9IGF4LnIyZCA9IGF4LmQyYyA9IGF4LnIyYyA9IGF4LmQybCA9IGF4LnIybCA9IGNsZWFuTnVtYmVyO1xuICAgICAgICBheC5jMmQgPSBheC5jMnIgPSBheC5sMmQgPSBheC5sMnIgPSBlbnN1cmVOdW1iZXI7XG5cbiAgICAgICAgYXguZDJwID0gYXgucjJwID0gZnVuY3Rpb24odikgeyByZXR1cm4gYXgubDJwKGNsZWFuTnVtYmVyKHYpKTsgfTtcbiAgICAgICAgYXgucDJkID0gYXgucDJyID0gcDJsO1xuXG4gICAgICAgIGF4LmNsZWFuUG9zID0gZW5zdXJlTnVtYmVyO1xuICAgIH0gZWxzZSBpZihheC50eXBlID09PSAnbG9nJykge1xuICAgICAgICAvLyBkIGFuZCBjIGFyZSBkYXRhIHZhbHMsIHIgYW5kIGwgYXJlIGxvZ2dlZCAoYnV0IGQgYW5kIHIgbmVlZCBjbGVhbmluZylcbiAgICAgICAgYXguZDJyID0gYXguZDJsID0gZnVuY3Rpb24odiwgY2xpcCkgeyByZXR1cm4gdG9Mb2coY2xlYW5OdW1iZXIodiksIGNsaXApOyB9O1xuICAgICAgICBheC5yMmQgPSBheC5yMmMgPSBmdW5jdGlvbih2KSB7IHJldHVybiBmcm9tTG9nKGNsZWFuTnVtYmVyKHYpKTsgfTtcblxuICAgICAgICBheC5kMmMgPSBheC5yMmwgPSBjbGVhbk51bWJlcjtcbiAgICAgICAgYXguYzJkID0gYXgubDJyID0gZW5zdXJlTnVtYmVyO1xuXG4gICAgICAgIGF4LmMyciA9IHRvTG9nO1xuICAgICAgICBheC5sMmQgPSBmcm9tTG9nO1xuXG4gICAgICAgIGF4LmQycCA9IGZ1bmN0aW9uKHYsIGNsaXApIHsgcmV0dXJuIGF4LmwycChheC5kMnIodiwgY2xpcCkpOyB9O1xuICAgICAgICBheC5wMmQgPSBmdW5jdGlvbihweCkgeyByZXR1cm4gZnJvbUxvZyhwMmwocHgpKTsgfTtcblxuICAgICAgICBheC5yMnAgPSBmdW5jdGlvbih2KSB7IHJldHVybiBheC5sMnAoY2xlYW5OdW1iZXIodikpOyB9O1xuICAgICAgICBheC5wMnIgPSBwMmw7XG5cbiAgICAgICAgYXguY2xlYW5Qb3MgPSBlbnN1cmVOdW1iZXI7XG4gICAgfSBlbHNlIGlmKGF4LnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICAvLyByIGFuZCBkIGFyZSBkYXRlIHN0cmluZ3MsIGwgYW5kIGMgYXJlIG1zXG5cbiAgICAgICAgLypcbiAgICAgICAgICogQW55IG9mIHRoZXNlIGZ1bmN0aW9ucyB3aXRoIHIgYW5kIGQgb24gZWl0aGVyIHNpZGUsIGNhbGVuZGFyIGlzIHRoZVxuICAgICAgICAgKiAqKjNyZCoqIGFyZ3VtZW50LiBsb2cgaGFzIHJlc2VydmVkIHRoZSBzZWNvbmQgYXJndW1lbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIFVubGVzcyB5b3UgbmVlZCB0aGUgc3BlY2lhbCBiZWhhdmlvciBvZiB0aGUgc2Vjb25kIGFyZyAobXMyRGF0ZVRpbWVcbiAgICAgICAgICogdXNlcyB0aGlzIHRvIGxpbWl0IHByZWNpc2lvbiwgdG9Mb2cgdXNlcyB0cnVlIHRvIGNsaXAgbmVnYXRpdmVzXG4gICAgICAgICAqIHRvIG9mZnNjcmVlbiBsb3cgcmF0aGVyIHRoYW4gdW5kZWZpbmVkKSwgaXQncyBzYWZlIHRvIHBhc3MgMC5cbiAgICAgICAgICovXG4gICAgICAgIGF4LmQyciA9IGF4LnIyZCA9IExpYi5pZGVudGl0eTtcblxuICAgICAgICBheC5kMmMgPSBheC5yMmMgPSBheC5kMmwgPSBheC5yMmwgPSBkdDJtcztcbiAgICAgICAgYXguYzJkID0gYXguYzJyID0gYXgubDJkID0gYXgubDJyID0gbXMyZHQ7XG5cbiAgICAgICAgYXguZDJwID0gYXgucjJwID0gZnVuY3Rpb24odiwgXywgY2FsZW5kYXIpIHsgcmV0dXJuIGF4LmwycChkdDJtcyh2LCAwLCBjYWxlbmRhcikpOyB9O1xuICAgICAgICBheC5wMmQgPSBheC5wMnIgPSBmdW5jdGlvbihweCwgciwgY2FsZW5kYXIpIHsgcmV0dXJuIG1zMmR0KHAybChweCksIHIsIGNhbGVuZGFyKTsgfTtcblxuICAgICAgICBheC5jbGVhblBvcyA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIExpYi5jbGVhbkRhdGUodiwgQkFETlVNLCBheC5jYWxlbmRhcik7IH07XG4gICAgfSBlbHNlIGlmKGF4LnR5cGUgPT09ICdjYXRlZ29yeScpIHtcbiAgICAgICAgLy8gZCBpcyBjYXRlZ29yaWVzIChzdHJpbmcpXG4gICAgICAgIC8vIGMgYW5kIGwgYXJlIGluZGljZXMgKG51bWJlcnMpXG4gICAgICAgIC8vIHIgaXMgY2F0ZWdvcmllcyBvciBudW1iZXJzXG5cbiAgICAgICAgYXguZDJjID0gYXguZDJsID0gc2V0Q2F0ZWdvcnlJbmRleDtcbiAgICAgICAgYXgucjJkID0gYXguYzJkID0gYXgubDJkID0gZ2V0Q2F0ZWdvcnlOYW1lO1xuXG4gICAgICAgIGF4LmQyciA9IGF4LmQybF9ub2FkZCA9IGdldENhdGVnb3J5UG9zaXRpb247XG5cbiAgICAgICAgYXgucjJjID0gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gZ2V0Q2F0ZWdvcnlQb3NpdGlvbih2KTtcbiAgICAgICAgICAgIHJldHVybiBpbmRleCAhPT0gdW5kZWZpbmVkID8gaW5kZXggOiBheC5mcmFjdGlvbjJyKDAuNSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgYXgubDJyID0gYXguYzJyID0gZW5zdXJlTnVtYmVyO1xuICAgICAgICBheC5yMmwgPSBnZXRDYXRlZ29yeVBvc2l0aW9uO1xuXG4gICAgICAgIGF4LmQycCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGF4LmwycChheC5yMmModikpOyB9O1xuICAgICAgICBheC5wMmQgPSBmdW5jdGlvbihweCkgeyByZXR1cm4gZ2V0Q2F0ZWdvcnlOYW1lKHAybChweCkpOyB9O1xuICAgICAgICBheC5yMnAgPSBheC5kMnA7XG4gICAgICAgIGF4LnAyciA9IHAybDtcblxuICAgICAgICBheC5jbGVhblBvcyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIGlmKHR5cGVvZiB2ID09PSAnc3RyaW5nJyAmJiB2ICE9PSAnJykgcmV0dXJuIHY7XG4gICAgICAgICAgICByZXR1cm4gZW5zdXJlTnVtYmVyKHYpO1xuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZihheC50eXBlID09PSAnbXVsdGljYXRlZ29yeScpIHtcbiAgICAgICAgLy8gTi5CLiBtdWx0aWNhdGVnb3J5IGF4ZXMgZG9uJ3QgZGVmaW5lIGQyYyBhbmQgZDJsLFxuICAgICAgICAvLyBhcyAnZGF0YS10by1jYWxjZGF0YScgY29udmVyc2lvbiBuZWVkcyB0byB0YWtlIGludG9cbiAgICAgICAgLy8gYWNjb3VudCBhbGwgZGF0YSBhcnJheSBpdGVtcyBhcyBpbiBheC5tYWtlQ2FsY2RhdGEuXG5cbiAgICAgICAgYXgucjJkID0gYXguYzJkID0gYXgubDJkID0gZ2V0Q2F0ZWdvcnlOYW1lO1xuICAgICAgICBheC5kMnIgPSBheC5kMmxfbm9hZGQgPSBnZXRDYXRlZ29yeVBvc2l0aW9uO1xuXG4gICAgICAgIGF4LnIyYyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHZhciBpbmRleCA9IGdldENhdGVnb3J5UG9zaXRpb24odik7XG4gICAgICAgICAgICByZXR1cm4gaW5kZXggIT09IHVuZGVmaW5lZCA/IGluZGV4IDogYXguZnJhY3Rpb24ycigwLjUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGF4LnIyY19qdXN0X2luZGljZXMgPSBnZXRDYXRlZ29yeUluZGV4O1xuXG4gICAgICAgIGF4LmwyciA9IGF4LmMyciA9IGVuc3VyZU51bWJlcjtcbiAgICAgICAgYXgucjJsID0gZ2V0Q2F0ZWdvcnlQb3NpdGlvbjtcblxuICAgICAgICBheC5kMnAgPSBmdW5jdGlvbih2KSB7IHJldHVybiBheC5sMnAoYXgucjJjKHYpKTsgfTtcbiAgICAgICAgYXgucDJkID0gZnVuY3Rpb24ocHgpIHsgcmV0dXJuIGdldENhdGVnb3J5TmFtZShwMmwocHgpKTsgfTtcbiAgICAgICAgYXgucjJwID0gYXguZDJwO1xuICAgICAgICBheC5wMnIgPSBwMmw7XG5cbiAgICAgICAgYXguY2xlYW5Qb3MgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KHYpIHx8ICh0eXBlb2YgdiA9PT0gJ3N0cmluZycgJiYgdiAhPT0gJycpKSByZXR1cm4gdjtcbiAgICAgICAgICAgIHJldHVybiBlbnN1cmVOdW1iZXIodik7XG4gICAgICAgIH07XG5cbiAgICAgICAgYXguc2V0dXBNdWx0aUNhdGVnb3J5ID0gZnVuY3Rpb24oZnVsbERhdGEpIHtcbiAgICAgICAgICAgIHZhciB0cmFjZUluZGljZXMgPSBheC5fdHJhY2VJbmRpY2VzO1xuICAgICAgICAgICAgdmFyIGksIGo7XG5cbiAgICAgICAgICAgIHZhciBtYXRjaEdyb3VwcyA9IGZ1bGxMYXlvdXQuX2F4aXNNYXRjaEdyb3VwcztcbiAgICAgICAgICAgIGlmKG1hdGNoR3JvdXBzICYmIG1hdGNoR3JvdXBzLmxlbmd0aCAmJiBheC5fY2F0ZWdvcmllcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBtYXRjaEdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZ3JvdXAgPSBtYXRjaEdyb3Vwc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoZ3JvdXBbYXhJZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcih2YXIgYXhJZDIgaW4gZ3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihheElkMiAhPT0gYXhJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXgyID0gZnVsbExheW91dFtheGlzSWRzLmlkMm5hbWUoYXhJZDIpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2VJbmRpY2VzID0gdHJhY2VJbmRpY2VzLmNvbmNhdChheDIuX3RyYWNlSW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBbIFtjbnQsIHskY2F0OiBpbmRleH1dLCBmb3IgMSwyIF1cbiAgICAgICAgICAgIHZhciBzZWVuID0gW1swLCB7fV0sIFswLCB7fV1dO1xuICAgICAgICAgICAgLy8gWyBbYXJyYXlJblswXVtpXSwgYXJyYXlJblsxXVtpXV0sIGZvciBpIC4uIE4gXVxuICAgICAgICAgICAgdmFyIGxpc3QgPSBbXTtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgdHJhY2VJbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbdHJhY2VJbmRpY2VzW2ldXTtcblxuICAgICAgICAgICAgICAgIGlmKGF4TGV0dGVyIGluIHRyYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhcnJheUluID0gdHJhY2VbYXhMZXR0ZXJdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gdHJhY2UuX2xlbmd0aCB8fCBMaWIubWluUm93TGVuZ3RoKGFycmF5SW4pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGlzQXJyYXlPclR5cGVkQXJyYXkoYXJyYXlJblswXSkgJiYgaXNBcnJheU9yVHlwZWRBcnJheShhcnJheUluWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbGVuOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdjAgPSBhcnJheUluWzBdW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2MSA9IGFycmF5SW5bMV1bal07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihpc1ZhbGlkQ2F0ZWdvcnkodjApICYmIGlzVmFsaWRDYXRlZ29yeSh2MSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdC5wdXNoKFt2MCwgdjFdKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZighKHYwIGluIHNlZW5bMF1bMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVuWzBdWzFdW3YwXSA9IHNlZW5bMF1bMF0rKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZighKHYxIGluIHNlZW5bMV1bMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVuWzFdWzFdW3YxXSA9IHNlZW5bMV1bMF0rKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGlzdC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kMCA9IHNlZW5bMF1bMV07XG4gICAgICAgICAgICAgICAgdmFyIGQgPSBpbmQwW2FbMF1dIC0gaW5kMFtiWzBdXTtcbiAgICAgICAgICAgICAgICBpZihkKSByZXR1cm4gZDtcblxuICAgICAgICAgICAgICAgIHZhciBpbmQxID0gc2VlblsxXVsxXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kMVthWzFdXSAtIGluZDFbYlsxXV07XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHNldENhdGVnb3J5SW5kZXgobGlzdFtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gZmluZCB0aGUgcmFuZ2UgdmFsdWUgYXQgdGhlIHNwZWNpZmllZCAobGluZWFyKSBmcmFjdGlvbiBvZiB0aGUgYXhpc1xuICAgIGF4LmZyYWN0aW9uMnIgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgIHZhciBybDAgPSBheC5yMmwoYXgucmFuZ2VbMF0pO1xuICAgICAgICB2YXIgcmwxID0gYXgucjJsKGF4LnJhbmdlWzFdKTtcbiAgICAgICAgcmV0dXJuIGF4LmwycihybDAgKyB2ICogKHJsMSAtIHJsMCkpO1xuICAgIH07XG5cbiAgICAvLyBmaW5kIHRoZSBmcmFjdGlvbiBvZiB0aGUgcmFuZ2UgYXQgdGhlIHNwZWNpZmllZCByYW5nZSB2YWx1ZVxuICAgIGF4LnIyZnJhY3Rpb24gPSBmdW5jdGlvbih2KSB7XG4gICAgICAgIHZhciBybDAgPSBheC5yMmwoYXgucmFuZ2VbMF0pO1xuICAgICAgICB2YXIgcmwxID0gYXgucjJsKGF4LnJhbmdlWzFdKTtcbiAgICAgICAgcmV0dXJuIChheC5yMmwodikgLSBybDApIC8gKHJsMSAtIHJsMCk7XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogY2xlYW5SYW5nZTogbWFrZSBzdXJlIHJhbmdlIGlzIGEgY291cGxldCBvZiB2YWxpZCAmIGRpc3RpbmN0IHZhbHVlc1xuICAgICAqIGtlZXAgbnVtYmVycyBhd2F5IGZyb20gdGhlIGxpbWl0cyBvZiBmbG9hdGluZyBwb2ludCBudW1iZXJzLFxuICAgICAqIGFuZCBkYXRlcyBhd2F5IGZyb20gdGhlIGVuZHMgb2Ygb3VyIGRhdGUgc3lzdGVtICgrLy0gOTk5OSB5ZWFycylcbiAgICAgKlxuICAgICAqIG9wdGlvbmFsIHBhcmFtIHJhbmdlQXR0cjogb3BlcmF0ZSBvbiBhIGRpZmZlcmVudCBhdHRyaWJ1dGUsIGxpa2VcbiAgICAgKiBheC5fciwgcmF0aGVyIHRoYW4gYXgucmFuZ2VcbiAgICAgKi9cbiAgICBheC5jbGVhblJhbmdlID0gZnVuY3Rpb24ocmFuZ2VBdHRyLCBvcHRzKSB7XG4gICAgICAgIGlmKCFvcHRzKSBvcHRzID0ge307XG4gICAgICAgIGlmKCFyYW5nZUF0dHIpIHJhbmdlQXR0ciA9ICdyYW5nZSc7XG5cbiAgICAgICAgdmFyIHJhbmdlID0gTGliLm5lc3RlZFByb3BlcnR5KGF4LCByYW5nZUF0dHIpLmdldCgpO1xuICAgICAgICB2YXIgaSwgZGZsdDtcblxuICAgICAgICBpZihheC50eXBlID09PSAnZGF0ZScpIGRmbHQgPSBMaWIuZGZsdFJhbmdlKGF4LmNhbGVuZGFyKTtcbiAgICAgICAgZWxzZSBpZihheExldHRlciA9PT0gJ3knKSBkZmx0ID0gY29uc3RhbnRzLkRGTFRSQU5HRVk7XG4gICAgICAgIGVsc2UgZGZsdCA9IG9wdHMuZGZsdFJhbmdlIHx8IGNvbnN0YW50cy5ERkxUUkFOR0VYO1xuXG4gICAgICAgIC8vIG1ha2Ugc3VyZSB3ZSBkb24ndCBsYXRlciBtdXRhdGUgdGhlIGRlZmF1bHRzXG4gICAgICAgIGRmbHQgPSBkZmx0LnNsaWNlKCk7XG5cbiAgICAgICAgaWYoIXJhbmdlIHx8IHJhbmdlLmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KGF4LCByYW5nZUF0dHIpLnNldChkZmx0KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF4LnR5cGUgPT09ICdkYXRlJyAmJiAhYXguYXV0b3JhbmdlKSB7XG4gICAgICAgICAgICAvLyBjaGVjayBpZiBtaWxsaXNlY29uZHMgb3IganMgZGF0ZSBvYmplY3RzIGFyZSBwcm92aWRlZCBmb3IgcmFuZ2VcbiAgICAgICAgICAgIC8vIGFuZCBjb252ZXJ0IHRvIGRhdGUgc3RyaW5nc1xuICAgICAgICAgICAgcmFuZ2VbMF0gPSBMaWIuY2xlYW5EYXRlKHJhbmdlWzBdLCBCQUROVU0sIGF4LmNhbGVuZGFyKTtcbiAgICAgICAgICAgIHJhbmdlWzFdID0gTGliLmNsZWFuRGF0ZShyYW5nZVsxXSwgQkFETlVNLCBheC5jYWxlbmRhcik7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGF4LnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICAgICAgICAgIGlmKCFMaWIuaXNEYXRlVGltZShyYW5nZVtpXSwgYXguY2FsZW5kYXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGF4W3JhbmdlQXR0cl0gPSBkZmx0O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihheC5yMmwocmFuZ2VbMF0pID09PSBheC5yMmwocmFuZ2VbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHNwbGl0IGJ5ICsvLSAxIHNlY29uZFxuICAgICAgICAgICAgICAgICAgICB2YXIgbGluQ2VudGVyID0gTGliLmNvbnN0cmFpbihheC5yMmwocmFuZ2VbMF0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgTGliLk1JTl9NUyArIDEwMDAsIExpYi5NQVhfTVMgLSAxMDAwKTtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2VbMF0gPSBheC5sMnIobGluQ2VudGVyIC0gMTAwMCk7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlWzFdID0gYXgubDJyKGxpbkNlbnRlciArIDEwMDApO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmKCFpc051bWVyaWMocmFuZ2VbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhyYW5nZVsxIC0gaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByYW5nZVtpXSA9IHJhbmdlWzEgLSBpXSAqIChpID8gMTAgOiAwLjEpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXhbcmFuZ2VBdHRyXSA9IGRmbHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKHJhbmdlW2ldIDwgLUZQX1NBRkUpIHJhbmdlW2ldID0gLUZQX1NBRkU7XG4gICAgICAgICAgICAgICAgZWxzZSBpZihyYW5nZVtpXSA+IEZQX1NBRkUpIHJhbmdlW2ldID0gRlBfU0FGRTtcblxuICAgICAgICAgICAgICAgIGlmKHJhbmdlWzBdID09PSByYW5nZVsxXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBzb21ld2hhdCBhcmJpdHJhcnk6IHNwbGl0IGJ5IDEgb3IgMXBwbSwgd2hpY2hldmVyIGlzIGJpZ2dlclxuICAgICAgICAgICAgICAgICAgICB2YXIgaW5jID0gTWF0aC5tYXgoMSwgTWF0aC5hYnMocmFuZ2VbMF0gKiAxZS02KSk7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlWzBdIC09IGluYztcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2VbMV0gKz0gaW5jO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBzZXQgc2NhbGluZyB0byBwaXhlbHNcbiAgICBheC5zZXRTY2FsZSA9IGZ1bmN0aW9uKHVzZVByaXZhdGVSYW5nZSkge1xuICAgICAgICB2YXIgZ3MgPSBmdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgICAgIC8vIG1ha2Ugc3VyZSB3ZSBoYXZlIGEgZG9tYWluIChwdWxsIGl0IGluIGZyb20gdGhlIGF4aXNcbiAgICAgICAgLy8gdGhpcyBvbmUgaXMgb3ZlcmxheWluZyBpZiBuZWNlc3NhcnkpXG4gICAgICAgIGlmKGF4Lm92ZXJsYXlpbmcpIHtcbiAgICAgICAgICAgIHZhciBheDIgPSBheGlzSWRzLmdldEZyb21JZCh7IF9mdWxsTGF5b3V0OiBmdWxsTGF5b3V0IH0sIGF4Lm92ZXJsYXlpbmcpO1xuICAgICAgICAgICAgYXguZG9tYWluID0gYXgyLmRvbWFpbjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFdoaWxlIHRyYW5zaXRpb25zIGFyZSBvY2N1cmluZywgb2NjdXJyaW5nLCB3ZSBnZXQgYSBkb3VibGUtdHJhbnNmb3JtXG4gICAgICAgIC8vIGlzc3VlIGlmIHdlIHRyYW5zZm9ybSB0aGUgZHJhd24gbGF5ZXIgKmFuZCogdXNlIHRoZSBuZXcgYXhpcyByYW5nZSB0b1xuICAgICAgICAvLyBkcmF3IHRoZSBkYXRhLiBUaGlzIGFsbG93cyB1cyB0byBjb25zdHJ1Y3Qgc2V0Q29udmVydCB1c2luZyB0aGUgcHJlLVxuICAgICAgICAvLyBpbnRlcmFjdGlvbiB2YWx1ZXMgb2YgdGhlIHJhbmdlOlxuICAgICAgICB2YXIgcmFuZ2VBdHRyID0gKHVzZVByaXZhdGVSYW5nZSAmJiBheC5fcikgPyAnX3InIDogJ3JhbmdlJztcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gYXguY2FsZW5kYXI7XG4gICAgICAgIGF4LmNsZWFuUmFuZ2UocmFuZ2VBdHRyKTtcblxuICAgICAgICB2YXIgcmwwID0gYXgucjJsKGF4W3JhbmdlQXR0cl1bMF0sIGNhbGVuZGFyKTtcbiAgICAgICAgdmFyIHJsMSA9IGF4LnIybChheFtyYW5nZUF0dHJdWzFdLCBjYWxlbmRhcik7XG5cbiAgICAgICAgaWYoYXhMZXR0ZXIgPT09ICd5Jykge1xuICAgICAgICAgICAgYXguX29mZnNldCA9IGdzLnQgKyAoMSAtIGF4LmRvbWFpblsxXSkgKiBncy5oO1xuICAgICAgICAgICAgYXguX2xlbmd0aCA9IGdzLmggKiAoYXguZG9tYWluWzFdIC0gYXguZG9tYWluWzBdKTtcbiAgICAgICAgICAgIGF4Ll9tID0gYXguX2xlbmd0aCAvIChybDAgLSBybDEpO1xuICAgICAgICAgICAgYXguX2IgPSAtYXguX20gKiBybDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBheC5fb2Zmc2V0ID0gZ3MubCArIGF4LmRvbWFpblswXSAqIGdzLnc7XG4gICAgICAgICAgICBheC5fbGVuZ3RoID0gZ3MudyAqIChheC5kb21haW5bMV0gLSBheC5kb21haW5bMF0pO1xuICAgICAgICAgICAgYXguX20gPSBheC5fbGVuZ3RoIC8gKHJsMSAtIHJsMCk7XG4gICAgICAgICAgICBheC5fYiA9IC1heC5fbSAqIHJsMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFpc0Zpbml0ZShheC5fbSkgfHwgIWlzRmluaXRlKGF4Ll9iKSB8fCBheC5fbGVuZ3RoIDwgMCkge1xuICAgICAgICAgICAgZnVsbExheW91dC5fcmVwbG90dGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTb21ldGhpbmcgd2VudCB3cm9uZyB3aXRoIGF4aXMgc2NhbGluZycpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8vIG1ha2VDYWxjZGF0YTogdGFrZXMgYW4geCBvciB5IGFycmF5IGFuZCBjb252ZXJ0cyBpdFxuICAgIC8vIHRvIGEgcG9zaXRpb24gb24gdGhlIGF4aXMgb2JqZWN0IFwiYXhcIlxuICAgIC8vIGlucHV0czpcbiAgICAvLyAgICAgIHRyYWNlIC0gYSBkYXRhIG9iamVjdCBmcm9tIGdkLmRhdGFcbiAgICAvLyAgICAgIGF4TGV0dGVyIC0gYSBzdHJpbmcsIGVpdGhlciAneCcgb3IgJ3knLCBmb3Igd2hpY2ggaXRlbVxuICAgIC8vICAgICAgICAgIHRvIGNvbnZlcnQgKFRPRE86IGlzIHRoaXMgbm93IGFsd2F5cyB0aGUgc2FtZSBhc1xuICAgIC8vICAgICAgICAgIHRoZSBmaXJzdCBsZXR0ZXIgb2YgYXguX2lkPylcbiAgICAvLyBpbiBjYXNlIHRoZSBleHBlY3RlZCBkYXRhIGlzbid0IHRoZXJlLCBtYWtlIGEgbGlzdCBvZlxuICAgIC8vIGludGVnZXJzIGJhc2VkIG9uIHRoZSBvcHBvc2l0ZSBkYXRhXG4gICAgYXgubWFrZUNhbGNkYXRhID0gZnVuY3Rpb24odHJhY2UsIGF4TGV0dGVyKSB7XG4gICAgICAgIHZhciBhcnJheUluLCBhcnJheU91dCwgaSwgbGVuO1xuXG4gICAgICAgIHZhciBheFR5cGUgPSBheC50eXBlO1xuICAgICAgICB2YXIgY2FsID0gYXhUeXBlID09PSAnZGF0ZScgJiYgdHJhY2VbYXhMZXR0ZXIgKyAnY2FsZW5kYXInXTtcblxuICAgICAgICBpZihheExldHRlciBpbiB0cmFjZSkge1xuICAgICAgICAgICAgYXJyYXlJbiA9IHRyYWNlW2F4TGV0dGVyXTtcbiAgICAgICAgICAgIGxlbiA9IHRyYWNlLl9sZW5ndGggfHwgTGliLm1pblJvd0xlbmd0aChhcnJheUluKTtcblxuICAgICAgICAgICAgaWYoTGliLmlzVHlwZWRBcnJheShhcnJheUluKSAmJiAoYXhUeXBlID09PSAnbGluZWFyJyB8fCBheFR5cGUgPT09ICdsb2cnKSkge1xuICAgICAgICAgICAgICAgIGlmKGxlbiA9PT0gYXJyYXlJbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFycmF5SW47XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKGFycmF5SW4uc3ViYXJyYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFycmF5SW4uc3ViYXJyYXkoMCwgbGVuKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGF4VHlwZSA9PT0gJ211bHRpY2F0ZWdvcnknKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNldE11bHRpQ2F0ZWdvcnlJbmRleChhcnJheUluLCBsZW4pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBhcnJheU91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcnJheU91dFtpXSA9IGF4LmQyYyhhcnJheUluW2ldLCAwLCBjYWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHYwID0gKChheExldHRlciArICcwJykgaW4gdHJhY2UpID8gYXguZDJjKHRyYWNlW2F4TGV0dGVyICsgJzAnXSwgMCwgY2FsKSA6IDA7XG4gICAgICAgICAgICB2YXIgZHYgPSAodHJhY2VbJ2QnICsgYXhMZXR0ZXJdKSA/IE51bWJlcih0cmFjZVsnZCcgKyBheExldHRlcl0pIDogMTtcblxuICAgICAgICAgICAgLy8gdGhlIG9wcG9zaW5nIGRhdGEsIGZvciBzaXplIGlmIHdlIGhhdmUgeCBhbmQgZHggZXRjXG4gICAgICAgICAgICBhcnJheUluID0gdHJhY2Vbe3g6ICd5JywgeTogJ3gnfVtheExldHRlcl1dO1xuICAgICAgICAgICAgbGVuID0gdHJhY2UuX2xlbmd0aCB8fCBhcnJheUluLmxlbmd0aDtcbiAgICAgICAgICAgIGFycmF5T3V0ID0gbmV3IEFycmF5KGxlbik7XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYXJyYXlPdXRbaV0gPSB2MCArIGkgKiBkdjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhcnJheU91dDtcbiAgICB9O1xuXG4gICAgYXguaXNWYWxpZFJhbmdlID0gZnVuY3Rpb24ocmFuZ2UpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIEFycmF5LmlzQXJyYXkocmFuZ2UpICYmXG4gICAgICAgICAgICByYW5nZS5sZW5ndGggPT09IDIgJiZcbiAgICAgICAgICAgIGlzTnVtZXJpYyhheC5yMmwocmFuZ2VbMF0pKSAmJlxuICAgICAgICAgICAgaXNOdW1lcmljKGF4LnIybChyYW5nZVsxXSkpXG4gICAgICAgICk7XG4gICAgfTtcblxuICAgIGF4LmlzUHRXaXRoaW5SYW5nZSA9IGZ1bmN0aW9uKGQsIGNhbGVuZGFyKSB7XG4gICAgICAgIHZhciBjb29yZCA9IGF4LmMybChkW2F4TGV0dGVyXSwgbnVsbCwgY2FsZW5kYXIpO1xuICAgICAgICB2YXIgcjAgPSBheC5yMmwoYXgucmFuZ2VbMF0pO1xuICAgICAgICB2YXIgcjEgPSBheC5yMmwoYXgucmFuZ2VbMV0pO1xuXG4gICAgICAgIGlmKHIwIDwgcjEpIHtcbiAgICAgICAgICAgIHJldHVybiByMCA8PSBjb29yZCAmJiBjb29yZCA8PSByMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJldmVyc2VkIGF4aXMgY2FzZS5cbiAgICAgICAgICAgIHJldHVybiByMSA8PSBjb29yZCAmJiBjb29yZCA8PSByMDtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBzaG91bGQgc2tpcCBpZiBub3QgY2F0ZWdvcnkgbm9yIG11bHRpY2F0ZWdvcnlcbiAgICBheC5jbGVhckNhbGMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGVtcHR5Q2F0ZWdvcmllcyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgYXguX2NhdGVnb3JpZXMgPSBbXTtcbiAgICAgICAgICAgIGF4Ll9jYXRlZ29yaWVzTWFwID0ge307XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIG1hdGNoR3JvdXBzID0gZnVsbExheW91dC5fYXhpc01hdGNoR3JvdXBzO1xuXG4gICAgICAgIGlmKG1hdGNoR3JvdXBzICYmIG1hdGNoR3JvdXBzLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGZvdW5kID0gZmFsc2U7XG5cbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBtYXRjaEdyb3Vwcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciBncm91cCA9IG1hdGNoR3JvdXBzW2ldO1xuXG4gICAgICAgICAgICAgICAgaWYoZ3JvdXBbYXhJZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2F0ZWdvcmllcyA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjYXRlZ29yaWVzTWFwID0gbnVsbDtcblxuICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGF4SWQyIGluIGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXgyID0gZnVsbExheW91dFtheGlzSWRzLmlkMm5hbWUoYXhJZDIpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGF4Mi5fY2F0ZWdvcmllcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGVnb3JpZXMgPSBheDIuX2NhdGVnb3JpZXM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcmllc01hcCA9IGF4Mi5fY2F0ZWdvcmllc01hcDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmKGNhdGVnb3JpZXMgJiYgY2F0ZWdvcmllc01hcCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXguX2NhdGVnb3JpZXMgPSBjYXRlZ29yaWVzO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXguX2NhdGVnb3JpZXNNYXAgPSBjYXRlZ29yaWVzTWFwO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZW1wdHlDYXRlZ29yaWVzKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoIWZvdW5kKSBlbXB0eUNhdGVnb3JpZXMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVtcHR5Q2F0ZWdvcmllcygpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYXguX2luaXRpYWxDYXRlZ29yaWVzKSB7XG4gICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgYXguX2luaXRpYWxDYXRlZ29yaWVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgc2V0Q2F0ZWdvcnlJbmRleChheC5faW5pdGlhbENhdGVnb3JpZXNbal0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIC8vIHNvcnQgdGhlIGF4aXMgKGFuZCBhbGwgdGhlIG1hdGNoaW5nIG9uZXMpIGJ5IF9pbml0aWFsQ2F0ZWdvcmllc1xuICAgIC8vIHJldHVybnMgdGhlIGluZGljZXMgb2YgdGhlIHRyYWNlcyBhZmZlY3RlZCBieSB0aGUgcmVvcmRlcmluZ1xuICAgIGF4LnNvcnRCeUluaXRpYWxDYXRlZ29yaWVzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhZmZlY3RlZFRyYWNlcyA9IFtdO1xuICAgICAgICB2YXIgZW1wdHlDYXRlZ29yaWVzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBheC5fY2F0ZWdvcmllcyA9IFtdO1xuICAgICAgICAgICAgYXguX2NhdGVnb3JpZXNNYXAgPSB7fTtcbiAgICAgICAgfTtcblxuICAgICAgICBlbXB0eUNhdGVnb3JpZXMoKTtcblxuICAgICAgICBpZihheC5faW5pdGlhbENhdGVnb3JpZXMpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBheC5faW5pdGlhbENhdGVnb3JpZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBzZXRDYXRlZ29yeUluZGV4KGF4Ll9pbml0aWFsQ2F0ZWdvcmllc1tqXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBhZmZlY3RlZFRyYWNlcyA9IGFmZmVjdGVkVHJhY2VzLmNvbmNhdChheC5fdHJhY2VJbmRpY2VzKTtcblxuICAgICAgICAvLyBQcm9wYWdhdGUgdG8gbWF0Y2hpbmcgYXhlc1xuICAgICAgICB2YXIgZ3JvdXAgPSBheC5fbWF0Y2hHcm91cDtcbiAgICAgICAgZm9yKHZhciBheElkMiBpbiBncm91cCkge1xuICAgICAgICAgICAgaWYoYXhJZCA9PT0gYXhJZDIpIGNvbnRpbnVlO1xuICAgICAgICAgICAgdmFyIGF4MiA9IGZ1bGxMYXlvdXRbYXhpc0lkcy5pZDJuYW1lKGF4SWQyKV07XG4gICAgICAgICAgICBheDIuX2NhdGVnb3JpZXMgPSBheC5fY2F0ZWdvcmllcztcbiAgICAgICAgICAgIGF4Mi5fY2F0ZWdvcmllc01hcCA9IGF4Ll9jYXRlZ29yaWVzTWFwO1xuICAgICAgICAgICAgYWZmZWN0ZWRUcmFjZXMgPSBhZmZlY3RlZFRyYWNlcy5jb25jYXQoYXgyLl90cmFjZUluZGljZXMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhZmZlY3RlZFRyYWNlcztcbiAgICB9O1xuXG4gICAgLy8gUHJvcGFnYXRlIGxvY2FsaXphdGlvbiBpbnRvIHRoZSBheGlzIHNvIHRoYXRcbiAgICAvLyBtZXRob2RzIGluIEF4ZXMgY2FuIHVzZSBpdCB3L28gaGF2aW5nIHRvIHBhc3MgZnVsbExheW91dFxuICAgIC8vIERlZmF1bHQgKG5vbi1kMykgbnVtYmVyIGZvcm1hdHRpbmcgdXNlcyBzZXBhcmF0b3JzIGRpcmVjdGx5XG4gICAgLy8gZGF0ZXMgYW5kIGQzLWZvcm1hdHRlZCBudW1iZXJzIHVzZSB0aGUgZDMgbG9jYWxlXG4gICAgLy8gRmFsbCBiYWNrIG9uIGRlZmF1bHQgZm9ybWF0IGZvciBkdW1teSBheGVzIHRoYXQgZG9uJ3QgY2FyZSBhYm91dCBmb3JtYXR0aW5nXG4gICAgdmFyIGxvY2FsZSA9IGZ1bGxMYXlvdXQuX2QzbG9jYWxlO1xuICAgIGlmKGF4LnR5cGUgPT09ICdkYXRlJykge1xuICAgICAgICBheC5fZGF0ZUZvcm1hdCA9IGxvY2FsZSA/IGxvY2FsZS50aW1lRm9ybWF0LnV0YyA6IGQzLnRpbWUuZm9ybWF0LnV0YztcbiAgICAgICAgYXguX2V4dHJhRm9ybWF0ID0gZnVsbExheW91dC5fZXh0cmFGb3JtYXQ7XG4gICAgfVxuICAgIC8vIG9jY2FzaW9uYWxseSB3ZSBuZWVkIF9udW1Gb3JtYXQgdG8gcGFzcyB0aHJvdWdoXG4gICAgLy8gZXZlbiB0aG91Z2ggaXQgd29uJ3QgYmUgbmVlZGVkIGJ5IHRoaXMgYXhpc1xuICAgIGF4Ll9zZXBhcmF0b3JzID0gZnVsbExheW91dC5zZXBhcmF0b3JzO1xuICAgIGF4Ll9udW1Gb3JtYXQgPSBsb2NhbGUgPyBsb2NhbGUubnVtYmVyRm9ybWF0IDogZDMuZm9ybWF0O1xuXG4gICAgLy8gYW5kIGZvciBiYXIgY2hhcnRzIGFuZCBib3ggcGxvdHM6IHJlc2V0IGZvcmNlZCBtaW5pbXVtIHRpY2sgc3BhY2luZ1xuICAgIGRlbGV0ZSBheC5fbWluRHRpY2s7XG4gICAgZGVsZXRlIGF4Ll9mb3JjZVRpY2swO1xufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vbGliXCI6NzE5LFwiLi9heGlzX2lkc1wiOjc3MCxcIi4vY29uc3RhbnRzXCI6NzczLFwiZDNcIjoxNjMsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDc4NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgYXhUeXBlLCBvcHRpb25zLCBjb25maWcpIHtcbiAgICBpZighY29uZmlnIHx8IGNvbmZpZy5wYXNzID09PSAxKSB7XG4gICAgICAgIGhhbmRsZVByZWZpeFN1ZmZpeChjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIGF4VHlwZSwgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgaWYoIWNvbmZpZyB8fCBjb25maWcucGFzcyA9PT0gMikge1xuICAgICAgICBoYW5kbGVPdGhlckRlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgYXhUeXBlLCBvcHRpb25zKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBoYW5kbGVQcmVmaXhTdWZmaXgoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBheFR5cGUsIG9wdGlvbnMpIHtcbiAgICB2YXIgc2hvd0F0dHJEZmx0ID0gZ2V0U2hvd0F0dHJEZmx0KGNvbnRhaW5lckluKTtcblxuICAgIHZhciB0aWNrUHJlZml4ID0gY29lcmNlKCd0aWNrcHJlZml4Jyk7XG4gICAgaWYodGlja1ByZWZpeCkgY29lcmNlKCdzaG93dGlja3ByZWZpeCcsIHNob3dBdHRyRGZsdCk7XG5cbiAgICB2YXIgdGlja1N1ZmZpeCA9IGNvZXJjZSgndGlja3N1ZmZpeCcsIG9wdGlvbnMudGlja1N1ZmZpeERmbHQpO1xuICAgIGlmKHRpY2tTdWZmaXgpIGNvZXJjZSgnc2hvd3RpY2tzdWZmaXgnLCBzaG93QXR0ckRmbHQpO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVPdGhlckRlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgYXhUeXBlLCBvcHRpb25zKSB7XG4gICAgdmFyIHNob3dBdHRyRGZsdCA9IGdldFNob3dBdHRyRGZsdChjb250YWluZXJJbik7XG5cbiAgICB2YXIgdGlja1ByZWZpeCA9IGNvZXJjZSgndGlja3ByZWZpeCcpO1xuICAgIGlmKHRpY2tQcmVmaXgpIGNvZXJjZSgnc2hvd3RpY2twcmVmaXgnLCBzaG93QXR0ckRmbHQpO1xuXG4gICAgdmFyIHRpY2tTdWZmaXggPSBjb2VyY2UoJ3RpY2tzdWZmaXgnLCBvcHRpb25zLnRpY2tTdWZmaXhEZmx0KTtcbiAgICBpZih0aWNrU3VmZml4KSBjb2VyY2UoJ3Nob3d0aWNrc3VmZml4Jywgc2hvd0F0dHJEZmx0KTtcblxuICAgIHZhciBzaG93VGlja0xhYmVscyA9IGNvZXJjZSgnc2hvd3RpY2tsYWJlbHMnKTtcbiAgICBpZihzaG93VGlja0xhYmVscykge1xuICAgICAgICB2YXIgZm9udCA9IG9wdGlvbnMuZm9udCB8fCB7fTtcbiAgICAgICAgdmFyIGNvbnRDb2xvciA9IGNvbnRhaW5lck91dC5jb2xvcjtcbiAgICAgICAgLy8gYXMgd2l0aCB0aXRsZWZvbnQuY29sb3IsIGluaGVyaXQgYXhpcy5jb2xvciBvbmx5IGlmIG9uZSB3YXNcbiAgICAgICAgLy8gZXhwbGljaXRseSBwcm92aWRlZFxuICAgICAgICB2YXIgZGZsdEZvbnRDb2xvciA9IChjb250Q29sb3IgJiYgY29udENvbG9yICE9PSBsYXlvdXRBdHRyaWJ1dGVzLmNvbG9yLmRmbHQpID9cbiAgICAgICAgICAgIGNvbnRDb2xvciA6IGZvbnQuY29sb3I7XG4gICAgICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3RpY2tmb250Jywge1xuICAgICAgICAgICAgZmFtaWx5OiBmb250LmZhbWlseSxcbiAgICAgICAgICAgIHNpemU6IGZvbnQuc2l6ZSxcbiAgICAgICAgICAgIGNvbG9yOiBkZmx0Rm9udENvbG9yXG4gICAgICAgIH0pO1xuICAgICAgICBjb2VyY2UoJ3RpY2thbmdsZScpO1xuXG4gICAgICAgIGlmKGF4VHlwZSAhPT0gJ2NhdGVnb3J5Jykge1xuICAgICAgICAgICAgdmFyIHRpY2tGb3JtYXQgPSBjb2VyY2UoJ3RpY2tmb3JtYXQnKTtcbiAgICAgICAgICAgIHZhciB0aWNrZm9ybWF0U3RvcHMgPSBjb250YWluZXJJbi50aWNrZm9ybWF0c3RvcHM7XG4gICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KHRpY2tmb3JtYXRTdG9wcykgJiYgdGlja2Zvcm1hdFN0b3BzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiAndGlja2Zvcm1hdHN0b3BzJyxcbiAgICAgICAgICAgICAgICAgICAgaW5jbHVzaW9uQXR0cjogJ2VuYWJsZWQnLFxuICAgICAgICAgICAgICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IHRpY2tmb3JtYXRzdG9wRGVmYXVsdHNcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKCF0aWNrRm9ybWF0ICYmIGF4VHlwZSAhPT0gJ2RhdGUnKSB7XG4gICAgICAgICAgICAgICAgY29lcmNlKCdzaG93ZXhwb25lbnQnLCBzaG93QXR0ckRmbHQpO1xuICAgICAgICAgICAgICAgIGNvZXJjZSgnZXhwb25lbnRmb3JtYXQnKTtcbiAgICAgICAgICAgICAgICBjb2VyY2UoJ3NlcGFyYXRldGhvdXNhbmRzJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qXG4gKiBBdHRyaWJ1dGVzICdzaG93ZXhwb25lbnQnLCAnc2hvd3RpY2twcmVmaXgnIGFuZCAnc2hvd3RpY2tzdWZmaXgnXG4gKiBzaGFyZSB2YWx1ZXMuXG4gKlxuICogSWYgb25seSAxIGF0dHJpYnV0ZSBpcyBzZXQsXG4gKiB0aGUgcmVtYWluaW5nIGF0dHJpYnV0ZXMgaW5oZXJpdCB0aGF0IHZhbHVlLlxuICpcbiAqIElmIDIgYXR0cmlidXRlcyBhcmUgc2V0IHRvIHRoZSBzYW1lIHZhbHVlLFxuICogdGhlIHJlbWFpbmluZyBhdHRyaWJ1dGUgaW5oZXJpdHMgdGhhdCB2YWx1ZS5cbiAqXG4gKiBJZiAyIGF0dHJpYnV0ZXMgYXJlIHNldCB0byBkaWZmZXJlbnQgdmFsdWVzLFxuICogdGhlIHJlbWFpbmluZyBpcyBzZXQgdG8gaXRzIGRmbHQgdmFsdWUuXG4gKlxuICovXG5mdW5jdGlvbiBnZXRTaG93QXR0ckRmbHQoY29udGFpbmVySW4pIHtcbiAgICB2YXIgc2hvd0F0dHJzQWxsID0gWydzaG93ZXhwb25lbnQnLCAnc2hvd3RpY2twcmVmaXgnLCAnc2hvd3RpY2tzdWZmaXgnXTtcbiAgICB2YXIgc2hvd0F0dHJzID0gc2hvd0F0dHJzQWxsLmZpbHRlcihmdW5jdGlvbihhKSB7XG4gICAgICAgIHJldHVybiBjb250YWluZXJJblthXSAhPT0gdW5kZWZpbmVkO1xuICAgIH0pO1xuICAgIHZhciBzYW1lVmFsID0gZnVuY3Rpb24oYSkge1xuICAgICAgICByZXR1cm4gY29udGFpbmVySW5bYV0gPT09IGNvbnRhaW5lckluW3Nob3dBdHRyc1swXV07XG4gICAgfTtcblxuICAgIGlmKHNob3dBdHRycy5ldmVyeShzYW1lVmFsKSB8fCBzaG93QXR0cnMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiBjb250YWluZXJJbltzaG93QXR0cnNbMF1dO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdGlja2Zvcm1hdHN0b3BEZWZhdWx0cyh2YWx1ZUluLCB2YWx1ZU91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHZhbHVlSW4sIHZhbHVlT3V0LCBsYXlvdXRBdHRyaWJ1dGVzLnRpY2tmb3JtYXRzdG9wcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGVuYWJsZWQgPSBjb2VyY2UoJ2VuYWJsZWQnKTtcbiAgICBpZihlbmFibGVkKSB7XG4gICAgICAgIGNvZXJjZSgnZHRpY2tyYW5nZScpO1xuICAgICAgICBjb2VyY2UoJ3ZhbHVlJyk7XG4gICAgfVxufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0c1wiOjc2MyxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo3Nzl9XSw3ODc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIGxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cblxuLyoqXG4gKiBvcHRpb25zOiBpbmhlcml0cyBvdXRlclRpY2tzIGZyb20gYXhlcy5oYW5kbGVBeGlzRGVmYXVsdHNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVUaWNrRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBvcHRpb25zKSB7XG4gICAgdmFyIHRpY2tMZW4gPSBMaWIuY29lcmNlMihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCAndGlja2xlbicpO1xuICAgIHZhciB0aWNrV2lkdGggPSBMaWIuY29lcmNlMihjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCAndGlja3dpZHRoJyk7XG4gICAgdmFyIHRpY2tDb2xvciA9IExpYi5jb2VyY2UyKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGxheW91dEF0dHJpYnV0ZXMsICd0aWNrY29sb3InLCBjb250YWluZXJPdXQuY29sb3IpO1xuICAgIHZhciBzaG93VGlja3MgPSBjb2VyY2UoJ3RpY2tzJywgKG9wdGlvbnMub3V0ZXJUaWNrcyB8fCB0aWNrTGVuIHx8IHRpY2tXaWR0aCB8fCB0aWNrQ29sb3IpID8gJ291dHNpZGUnIDogJycpO1xuXG4gICAgaWYoIXNob3dUaWNrcykge1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnRpY2tsZW47XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQudGlja3dpZHRoO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnRpY2tjb2xvcjtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo3Nzl9XSw3ODg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY2xlYW5UaWNrcyA9IF9kZXJlcV8oJy4vY2xlYW5fdGlja3MnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVUaWNrVmFsdWVEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIGF4VHlwZSkge1xuICAgIHZhciB0aWNrbW9kZTtcblxuICAgIGlmKGNvbnRhaW5lckluLnRpY2ttb2RlID09PSAnYXJyYXknICYmXG4gICAgICAgICAgICAoYXhUeXBlID09PSAnbG9nJyB8fCBheFR5cGUgPT09ICdkYXRlJykpIHtcbiAgICAgICAgdGlja21vZGUgPSBjb250YWluZXJPdXQudGlja21vZGUgPSAnYXV0byc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHRpY2ttb2RlRGVmYXVsdCA9IEFycmF5LmlzQXJyYXkoY29udGFpbmVySW4udGlja3ZhbHMpID8gJ2FycmF5JyA6XG4gICAgICAgICAgICBjb250YWluZXJJbi5kdGljayA/ICdsaW5lYXInIDpcbiAgICAgICAgICAgICdhdXRvJztcbiAgICAgICAgdGlja21vZGUgPSBjb2VyY2UoJ3RpY2ttb2RlJywgdGlja21vZGVEZWZhdWx0KTtcbiAgICB9XG5cbiAgICBpZih0aWNrbW9kZSA9PT0gJ2F1dG8nKSBjb2VyY2UoJ250aWNrcycpO1xuICAgIGVsc2UgaWYodGlja21vZGUgPT09ICdsaW5lYXInKSB7XG4gICAgICAgIC8vIGR0aWNrIGlzIHVzdWFsbHkgYSBwb3NpdGl2ZSBudW1iZXIsIGJ1dCB0aGVyZSBhcmUgc29tZVxuICAgICAgICAvLyBzcGVjaWFsIHN0cmluZ3MgYXZhaWxhYmxlIGZvciBsb2cgb3IgZGF0ZSBheGVzXG4gICAgICAgIC8vIHRpY2swIGFsc28gaGFzIHNwZWNpYWwgbG9naWNcbiAgICAgICAgdmFyIGR0aWNrID0gY29udGFpbmVyT3V0LmR0aWNrID0gY2xlYW5UaWNrcy5kdGljayhcbiAgICAgICAgICAgIGNvbnRhaW5lckluLmR0aWNrLCBheFR5cGUpO1xuICAgICAgICBjb250YWluZXJPdXQudGljazAgPSBjbGVhblRpY2tzLnRpY2swKFxuICAgICAgICAgICAgY29udGFpbmVySW4udGljazAsIGF4VHlwZSwgY29udGFpbmVyT3V0LmNhbGVuZGFyLCBkdGljayk7XG4gICAgfSBlbHNlIGlmKGF4VHlwZSAhPT0gJ211bHRpY2F0ZWdvcnknKSB7XG4gICAgICAgIHZhciB0aWNrdmFscyA9IGNvZXJjZSgndGlja3ZhbHMnKTtcbiAgICAgICAgaWYodGlja3ZhbHMgPT09IHVuZGVmaW5lZCkgY29udGFpbmVyT3V0LnRpY2ttb2RlID0gJ2F1dG8nO1xuICAgICAgICBlbHNlIGNvZXJjZSgndGlja3RleHQnKTtcbiAgICB9XG59O1xuXG59LHtcIi4vY2xlYW5fdGlja3NcIjo3NzJ9XSw3ODk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi9heGVzJyk7XG5cbi8qKlxuICogdHJhbnNpdGlvbkF4ZXNcbiAqXG4gKiB0cmFuc2l0aW9uIGF4ZXMgZnJvbSBvbmUgc2V0IG9mIHJhbmdlcyB0byBhbm90aGVyLCB1c2luZyBhIHN2Z1xuICogdHJhbnNmb3JtYXRpb25zLCBzaW1pbGFyIHRvIGR1cmluZyBwYW5uaW5nLlxuICpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnQgfCBvYmplY3R9IGdkXG4gKiBAcGFyYW0ge2FycmF5fSBlZGl0cyA6IGFycmF5IG9mICdlZGl0cycsIGVhY2ggaXRlbSB3aXRoXG4gKiAtIHBsb3RpbmZvIHtvYmplY3R9IHN1YnBsb3Qgb2JqZWN0XG4gKiAtIHhyMCB7YXJyYXl9IGluaXRpYWwgeC1yYW5nZVxuICogLSB4cjEge2FycmF5fSBlbmQgeC1yYW5nZVxuICogLSB5cjAge2FycmF5fSBpbml0aWFsIHktcmFuZ2VcbiAqIC0geXIxIHthcnJheX0gZW5kIHktcmFuZ2VcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFuc2l0aW9uT3B0c1xuICogQHBhcmFtIHtmdW5jdGlvbn0gbWFrZU9uQ29tcGxldGVDYWxsYmFja1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHRyYW5zaXRpb25BeGVzKGdkLCBlZGl0cywgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgLy8gc3BlY2lhbCBjYXNlIGZvciByZWRyYXc6ZmFsc2UgUGxvdGx5LmFuaW1hdGUgdGhhdCByZWxpZXMgb24gdGhpc1xuICAgIC8vIHRvIHVwZGF0ZSBheGlzLXJlZmVyZW5jZWQgbGF5b3V0IGNvbXBvbmVudHNcbiAgICBpZihlZGl0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgQXhlcy5yZWRyYXdDb21wb25lbnRzKGdkKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVuc2V0U3VicGxvdFRyYW5zZm9ybShzdWJwbG90KSB7XG4gICAgICAgIHZhciB4YSA9IHN1YnBsb3QueGF4aXM7XG4gICAgICAgIHZhciB5YSA9IHN1YnBsb3QueWF4aXM7XG5cbiAgICAgICAgZnVsbExheW91dC5fZGVmcy5zZWxlY3QoJyMnICsgc3VicGxvdC5jbGlwSWQgKyAnPiByZWN0JylcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0VHJhbnNsYXRlLCAwLCAwKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRTY2FsZSwgMSwgMSk7XG5cbiAgICAgICAgc3VicGxvdC5wbG90XG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSwgeGEuX29mZnNldCwgeWEuX29mZnNldClcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0U2NhbGUsIDEsIDEpO1xuXG4gICAgICAgIHZhciB0cmFjZUdyb3VwcyA9IHN1YnBsb3QucGxvdC5zZWxlY3RBbGwoJy5zY2F0dGVybGF5ZXIgLnRyYWNlJyk7XG5cbiAgICAgICAgLy8gVGhpcyBpcyBzcGVjaWZpY2FsbHkgZGlyZWN0ZWQgYXQgc2NhdHRlciB0cmFjZXMsIGFwcGx5aW5nIGFuIGludmVyc2VcbiAgICAgICAgLy8gc2NhbGUgdG8gaW5kaXZpZHVhbCBwb2ludHMgdG8gY291bnRlcmFjdCB0aGUgc2NhbGUgb2YgdGhlIHRyYWNlXG4gICAgICAgIC8vIGFzIGEgd2hvbGU6XG4gICAgICAgIHRyYWNlR3JvdXBzLnNlbGVjdEFsbCgnLnBvaW50JylcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0UG9pbnRHcm91cFNjYWxlLCAxLCAxKTtcbiAgICAgICAgdHJhY2VHcm91cHMuc2VsZWN0QWxsKCcudGV4dHBvaW50JylcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0VGV4dFBvaW50c1NjYWxlLCAxLCAxKTtcbiAgICAgICAgdHJhY2VHcm91cHNcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50cywgc3VicGxvdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlU3VicGxvdChlZGl0LCBwcm9ncmVzcykge1xuICAgICAgICB2YXIgcGxvdGluZm8gPSBlZGl0LnBsb3RpbmZvO1xuICAgICAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICAgICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICAgICAgdmFyIHhyMCA9IGVkaXQueHIwO1xuICAgICAgICB2YXIgeHIxID0gZWRpdC54cjE7XG4gICAgICAgIHZhciB4bGVuID0geGEuX2xlbmd0aDtcbiAgICAgICAgdmFyIHlyMCA9IGVkaXQueXIwO1xuICAgICAgICB2YXIgeXIxID0gZWRpdC55cjE7XG4gICAgICAgIHZhciB5bGVuID0geWEuX2xlbmd0aDtcblxuICAgICAgICB2YXIgZWRpdFggPSAhIXhyMTtcbiAgICAgICAgdmFyIGVkaXRZID0gISF5cjE7XG4gICAgICAgIHZhciB2aWV3Qm94ID0gW107XG5cbiAgICAgICAgaWYoZWRpdFgpIHtcbiAgICAgICAgICAgIHZhciBkeDAgPSB4cjBbMV0gLSB4cjBbMF07XG4gICAgICAgICAgICB2YXIgZHgxID0geHIxWzFdIC0geHIxWzBdO1xuICAgICAgICAgICAgdmlld0JveFswXSA9ICh4cjBbMF0gKiAoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogeHIxWzBdIC0geHIwWzBdKSAvICh4cjBbMV0gLSB4cjBbMF0pICogeGxlbjtcbiAgICAgICAgICAgIHZpZXdCb3hbMl0gPSB4bGVuICogKCgxIC0gcHJvZ3Jlc3MpICsgcHJvZ3Jlc3MgKiBkeDEgLyBkeDApO1xuICAgICAgICAgICAgeGEucmFuZ2VbMF0gPSB4cjBbMF0gKiAoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogeHIxWzBdO1xuICAgICAgICAgICAgeGEucmFuZ2VbMV0gPSB4cjBbMV0gKiAoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogeHIxWzFdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmlld0JveFswXSA9IDA7XG4gICAgICAgICAgICB2aWV3Qm94WzJdID0geGxlbjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGVkaXRZKSB7XG4gICAgICAgICAgICB2YXIgZHkwID0geXIwWzFdIC0geXIwWzBdO1xuICAgICAgICAgICAgdmFyIGR5MSA9IHlyMVsxXSAtIHlyMVswXTtcbiAgICAgICAgICAgIHZpZXdCb3hbMV0gPSAoeXIwWzFdICogKDEgLSBwcm9ncmVzcykgKyBwcm9ncmVzcyAqIHlyMVsxXSAtIHlyMFsxXSkgLyAoeXIwWzBdIC0geXIwWzFdKSAqIHlsZW47XG4gICAgICAgICAgICB2aWV3Qm94WzNdID0geWxlbiAqICgoMSAtIHByb2dyZXNzKSArIHByb2dyZXNzICogZHkxIC8gZHkwKTtcbiAgICAgICAgICAgIHlhLnJhbmdlWzBdID0geXIwWzBdICogKDEgLSBwcm9ncmVzcykgKyBwcm9ncmVzcyAqIHlyMVswXTtcbiAgICAgICAgICAgIHlhLnJhbmdlWzFdID0geXIwWzFdICogKDEgLSBwcm9ncmVzcykgKyBwcm9ncmVzcyAqIHlyMVsxXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZpZXdCb3hbMV0gPSAwO1xuICAgICAgICAgICAgdmlld0JveFszXSA9IHlsZW47XG4gICAgICAgIH1cblxuICAgICAgICBBeGVzLmRyYXdPbmUoZ2QsIHhhLCB7c2tpcFRpdGxlOiB0cnVlfSk7XG4gICAgICAgIEF4ZXMuZHJhd09uZShnZCwgeWEsIHtza2lwVGl0bGU6IHRydWV9KTtcbiAgICAgICAgQXhlcy5yZWRyYXdDb21wb25lbnRzKGdkLCBbeGEuX2lkLCB5YS5faWRdKTtcblxuICAgICAgICB2YXIgeFNjYWxlRmFjdG9yID0gZWRpdFggPyB4bGVuIC8gdmlld0JveFsyXSA6IDE7XG4gICAgICAgIHZhciB5U2NhbGVGYWN0b3IgPSBlZGl0WSA/IHlsZW4gLyB2aWV3Qm94WzNdIDogMTtcbiAgICAgICAgdmFyIGNsaXBEeCA9IGVkaXRYID8gdmlld0JveFswXSA6IDA7XG4gICAgICAgIHZhciBjbGlwRHkgPSBlZGl0WSA/IHZpZXdCb3hbMV0gOiAwO1xuICAgICAgICB2YXIgZnJhY0R4ID0gZWRpdFggPyAodmlld0JveFswXSAvIHZpZXdCb3hbMl0gKiB4bGVuKSA6IDA7XG4gICAgICAgIHZhciBmcmFjRHkgPSBlZGl0WSA/ICh2aWV3Qm94WzFdIC8gdmlld0JveFszXSAqIHlsZW4pIDogMDtcbiAgICAgICAgdmFyIHBsb3REeCA9IHhhLl9vZmZzZXQgLSBmcmFjRHg7XG4gICAgICAgIHZhciBwbG90RHkgPSB5YS5fb2Zmc2V0IC0gZnJhY0R5O1xuXG4gICAgICAgIHBsb3RpbmZvLmNsaXBSZWN0XG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSwgY2xpcER4LCBjbGlwRHkpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFNjYWxlLCAxIC8geFNjYWxlRmFjdG9yLCAxIC8geVNjYWxlRmFjdG9yKTtcblxuICAgICAgICBwbG90aW5mby5wbG90XG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFRyYW5zbGF0ZSwgcGxvdER4LCBwbG90RHkpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldFNjYWxlLCB4U2NhbGVGYWN0b3IsIHlTY2FsZUZhY3Rvcik7XG5cbiAgICAgICAgLy8gYXBwbHkgYW4gaW52ZXJzZSBzY2FsZSB0byBpbmRpdmlkdWFsIHBvaW50cyB0byBjb3VudGVyYWN0XG4gICAgICAgIC8vIHRoZSBzY2FsZSBvZiB0aGUgdHJhY2UgZ3JvdXAuXG4gICAgICAgIERyYXdpbmcuc2V0UG9pbnRHcm91cFNjYWxlKHBsb3RpbmZvLnpvb21TY2FsZVB0cywgMSAvIHhTY2FsZUZhY3RvciwgMSAvIHlTY2FsZUZhY3Rvcik7XG4gICAgICAgIERyYXdpbmcuc2V0VGV4dFBvaW50c1NjYWxlKHBsb3RpbmZvLnpvb21TY2FsZVR4dCwgMSAvIHhTY2FsZUZhY3RvciwgMSAvIHlTY2FsZUZhY3Rvcik7XG4gICAgfVxuXG4gICAgdmFyIG9uQ29tcGxldGU7XG4gICAgaWYobWFrZU9uQ29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICAvLyBUaGlzIG1vZHVsZSBtYWtlcyB0aGUgY2hvaWNlIHdoZXRoZXIgb3Igbm90IGl0IG5vdGlmaWVzIFBsb3RseS50cmFuc2l0aW9uXG4gICAgICAgIC8vIGFib3V0IGNvbXBsZXRpb246XG4gICAgICAgIG9uQ29tcGxldGUgPSBtYWtlT25Db21wbGV0ZUNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdHJhbnNpdGlvbkNvbXBsZXRlKCkge1xuICAgICAgICB2YXIgYW9iaiA9IHt9O1xuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBlZGl0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGVkaXQgPSBlZGl0c1tpXTtcbiAgICAgICAgICAgIGlmKGVkaXQueHIxKSBhb2JqW2VkaXQucGxvdGluZm8ueGF4aXMuX25hbWUgKyAnLnJhbmdlJ10gPSBlZGl0LnhyMS5zbGljZSgpO1xuICAgICAgICAgICAgaWYoZWRpdC55cjEpIGFvYmpbZWRpdC5wbG90aW5mby55YXhpcy5fbmFtZSArICcucmFuZ2UnXSA9IGVkaXQueXIxLnNsaWNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTaWduYWwgdGhhdCB0aGlzIHRyYW5zaXRpb24gaGFzIGNvbXBsZXRlZDpcbiAgICAgICAgb25Db21wbGV0ZSAmJiBvbkNvbXBsZXRlKCk7XG5cbiAgICAgICAgcmV0dXJuIFJlZ2lzdHJ5LmNhbGwoJ3JlbGF5b3V0JywgZ2QsIGFvYmopLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgZWRpdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB1bnNldFN1YnBsb3RUcmFuc2Zvcm0oZWRpdHNbaV0ucGxvdGluZm8pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0cmFuc2l0aW9uSW50ZXJydXB0KCkge1xuICAgICAgICB2YXIgYW9iaiA9IHt9O1xuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBlZGl0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGVkaXQgPSBlZGl0c1tpXTtcbiAgICAgICAgICAgIGlmKGVkaXQueHIwKSBhb2JqW2VkaXQucGxvdGluZm8ueGF4aXMuX25hbWUgKyAnLnJhbmdlJ10gPSBlZGl0LnhyMC5zbGljZSgpO1xuICAgICAgICAgICAgaWYoZWRpdC55cjApIGFvYmpbZWRpdC5wbG90aW5mby55YXhpcy5fbmFtZSArICcucmFuZ2UnXSA9IGVkaXQueXIwLnNsaWNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgYW9iaikudGhlbihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBlZGl0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHVuc2V0U3VicGxvdFRyYW5zZm9ybShlZGl0c1tpXS5wbG90aW5mbyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciB0MSwgdDIsIHJhZjtcbiAgICB2YXIgZWFzZUZuID0gZDMuZWFzZSh0cmFuc2l0aW9uT3B0cy5lYXNpbmcpO1xuXG4gICAgZ2QuX3RyYW5zaXRpb25EYXRhLl9pbnRlcnJ1cHRDYWxsYmFja3MucHVzaChmdW5jdGlvbigpIHtcbiAgICAgICAgd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lKHJhZik7XG4gICAgICAgIHJhZiA9IG51bGw7XG4gICAgICAgIHJldHVybiB0cmFuc2l0aW9uSW50ZXJydXB0KCk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBkb0ZyYW1lKCkge1xuICAgICAgICB0MiA9IERhdGUubm93KCk7XG5cbiAgICAgICAgdmFyIHRJbnRlcnAgPSBNYXRoLm1pbigxLCAodDIgLSB0MSkgLyB0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbik7XG4gICAgICAgIHZhciBwcm9ncmVzcyA9IGVhc2VGbih0SW50ZXJwKTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgZWRpdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHVwZGF0ZVN1YnBsb3QoZWRpdHNbaV0sIHByb2dyZXNzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHQyIC0gdDEgPiB0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbikge1xuICAgICAgICAgICAgdHJhbnNpdGlvbkNvbXBsZXRlKCk7XG4gICAgICAgICAgICByYWYgPSB3aW5kb3cuY2FuY2VsQW5pbWF0aW9uRnJhbWUoZG9GcmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByYWYgPSB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGRvRnJhbWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdDEgPSBEYXRlLm5vdygpO1xuICAgIHJhZiA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZG9GcmFtZSk7XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9heGVzXCI6NzY3LFwiZDNcIjoxNjN9XSw3OTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdHJhY2VJcyA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5JykudHJhY2VJcztcbnZhciBhdXRvVHlwZSA9IF9kZXJlcV8oJy4vYXhpc19hdXRvdHlwZScpO1xuXG4vKlxuICogIGRhdGE6IHRoZSBwbG90IGRhdGEgdG8gdXNlIGluIGNob29zaW5nIGF1dG8gdHlwZVxuICogIG5hbWU6IGF4aXMgb2JqZWN0IG5hbWUgKGllICd4YXhpcycpIGlmIG9uZSBzaG91bGQgYmUgc3RvcmVkXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlVHlwZURlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgb3B0aW9ucykge1xuICAgIHZhciBheFR5cGUgPSBjb2VyY2UoJ3R5cGUnLCAob3B0aW9ucy5zcGxvbVN0YXNoIHx8IHt9KS50eXBlKTtcblxuICAgIGlmKGF4VHlwZSA9PT0gJy0nKSB7XG4gICAgICAgIHNldEF1dG9UeXBlKGNvbnRhaW5lck91dCwgb3B0aW9ucy5kYXRhKTtcblxuICAgICAgICBpZihjb250YWluZXJPdXQudHlwZSA9PT0gJy0nKSB7XG4gICAgICAgICAgICBjb250YWluZXJPdXQudHlwZSA9ICdsaW5lYXInO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY29weSBhdXRvVHlwZSBiYWNrIHRvIGlucHV0IGF4aXNcbiAgICAgICAgICAgIC8vIG5vdGUgdGhhdCBpZiB0aGlzIG9iamVjdCBkaWRuJ3QgZXhpc3RcbiAgICAgICAgICAgIC8vIGluIHRoZSBpbnB1dCBsYXlvdXQsIHdlIGhhdmUgdG8gcHV0IGl0IGluXG4gICAgICAgICAgICAvLyB0aGlzIGhhcHBlbnMgaW4gdGhlIG1haW4gc3VwcGx5RGVmYXVsdHMgZnVuY3Rpb25cbiAgICAgICAgICAgIGNvbnRhaW5lckluLnR5cGUgPSBjb250YWluZXJPdXQudHlwZTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHNldEF1dG9UeXBlKGF4LCBkYXRhKSB7XG4gICAgLy8gbmV3IGxvZ2ljOiBsZXQgcGVvcGxlIHNwZWNpZnkgYW55IHR5cGUgdGhleSB3YW50LFxuICAgIC8vIG9ubHkgYXV0b3R5cGUgaWYgdHlwZSBpcyAnLSdcbiAgICBpZihheC50eXBlICE9PSAnLScpIHJldHVybjtcblxuICAgIHZhciBpZCA9IGF4Ll9pZDtcbiAgICB2YXIgYXhMZXR0ZXIgPSBpZC5jaGFyQXQoMCk7XG5cbiAgICAvLyBzdXBwb3J0IDNkXG4gICAgaWYoaWQuaW5kZXhPZignc2NlbmUnKSAhPT0gLTEpIGlkID0gYXhMZXR0ZXI7XG5cbiAgICB2YXIgZDAgPSBnZXRGaXJzdE5vbkVtcHR5VHJhY2UoZGF0YSwgaWQsIGF4TGV0dGVyKTtcbiAgICBpZighZDApIHJldHVybjtcblxuICAgIC8vIGZpcnN0IGNoZWNrIGZvciBoaXN0b2dyYW1zLCBhcyB0aGUgY291bnQgZGlyZWN0aW9uXG4gICAgLy8gc2hvdWxkIGFsd2F5cyBkZWZhdWx0IHRvIGEgbGluZWFyIGF4aXNcbiAgICBpZihkMC50eXBlID09PSAnaGlzdG9ncmFtJyAmJlxuICAgICAgICAgICAgYXhMZXR0ZXIgPT09IHt2OiAneScsIGg6ICd4J31bZDAub3JpZW50YXRpb24gfHwgJ3YnXSkge1xuICAgICAgICBheC50eXBlID0gJ2xpbmVhcic7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgY2FsQXR0ciA9IGF4TGV0dGVyICsgJ2NhbGVuZGFyJztcbiAgICB2YXIgY2FsZW5kYXIgPSBkMFtjYWxBdHRyXTtcbiAgICB2YXIgb3B0cyA9IHtub011bHRpQ2F0ZWdvcnk6ICF0cmFjZUlzKGQwLCAnY2FydGVzaWFuJykgfHwgdHJhY2VJcyhkMCwgJ25vTXVsdGlDYXRlZ29yeScpfTtcbiAgICB2YXIgaTtcblxuICAgIC8vIGNoZWNrIGFsbCBib3hlcyBvbiB0aGlzIHggYXhpcyB0byBzZWVcbiAgICAvLyBpZiB0aGV5J3JlIGRhdGVzLCBudW1iZXJzLCBvciBjYXRlZ29yaWVzXG4gICAgaWYoaXNCb3hXaXRob3V0UG9zaXRpb25Db29yZHMoZDAsIGF4TGV0dGVyKSkge1xuICAgICAgICB2YXIgcG9zTGV0dGVyID0gZ2V0Qm94UG9zTGV0dGVyKGQwKTtcbiAgICAgICAgdmFyIGJveFBvc2l0aW9ucyA9IFtdO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IGRhdGFbaV07XG4gICAgICAgICAgICBpZighdHJhY2VJcyh0cmFjZSwgJ2JveC12aW9saW4nKSB8fCAodHJhY2VbYXhMZXR0ZXIgKyAnYXhpcyddIHx8IGF4TGV0dGVyKSAhPT0gaWQpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICBpZih0cmFjZVtwb3NMZXR0ZXJdICE9PSB1bmRlZmluZWQpIGJveFBvc2l0aW9ucy5wdXNoKHRyYWNlW3Bvc0xldHRlcl1bMF0pO1xuICAgICAgICAgICAgZWxzZSBpZih0cmFjZS5uYW1lICE9PSB1bmRlZmluZWQpIGJveFBvc2l0aW9ucy5wdXNoKHRyYWNlLm5hbWUpO1xuICAgICAgICAgICAgZWxzZSBib3hQb3NpdGlvbnMucHVzaCgndGV4dCcpO1xuXG4gICAgICAgICAgICBpZih0cmFjZVtjYWxBdHRyXSAhPT0gY2FsZW5kYXIpIGNhbGVuZGFyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgYXgudHlwZSA9IGF1dG9UeXBlKGJveFBvc2l0aW9ucywgY2FsZW5kYXIsIG9wdHMpO1xuICAgIH0gZWxzZSBpZihkMC50eXBlID09PSAnc3Bsb20nKSB7XG4gICAgICAgIHZhciBkaW1lbnNpb25zID0gZDAuZGltZW5zaW9ucztcbiAgICAgICAgdmFyIGRpbSA9IGRpbWVuc2lvbnNbZDAuX2F4ZXNEaW1baWRdXTtcbiAgICAgICAgaWYoZGltLnZpc2libGUpIGF4LnR5cGUgPSBhdXRvVHlwZShkaW0udmFsdWVzLCBjYWxlbmRhciwgb3B0cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYXgudHlwZSA9IGF1dG9UeXBlKGQwW2F4TGV0dGVyXSB8fCBbZDBbYXhMZXR0ZXIgKyAnMCddXSwgY2FsZW5kYXIsIG9wdHMpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0Rmlyc3ROb25FbXB0eVRyYWNlKGRhdGEsIGlkLCBheExldHRlcikge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGRhdGFbaV07XG5cbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ3NwbG9tJyAmJlxuICAgICAgICAgICAgICAgIHRyYWNlLl9sZW5ndGggPiAwICYmXG4gICAgICAgICAgICAgICAgKHRyYWNlWydfJyArIGF4TGV0dGVyICsgJ2F4ZXMnXSB8fCB7fSlbaWRdXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIHRyYWNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoKHRyYWNlW2F4TGV0dGVyICsgJ2F4aXMnXSB8fCBheExldHRlcikgPT09IGlkKSB7XG4gICAgICAgICAgICBpZihpc0JveFdpdGhvdXRQb3NpdGlvbkNvb3Jkcyh0cmFjZSwgYXhMZXR0ZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyYWNlO1xuICAgICAgICAgICAgfSBlbHNlIGlmKCh0cmFjZVtheExldHRlcl0gfHwgW10pLmxlbmd0aCB8fCB0cmFjZVtheExldHRlciArICcwJ10pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldEJveFBvc0xldHRlcih0cmFjZSkge1xuICAgIHJldHVybiB7djogJ3gnLCBoOiAneSd9W3RyYWNlLm9yaWVudGF0aW9uIHx8ICd2J107XG59XG5cbmZ1bmN0aW9uIGlzQm94V2l0aG91dFBvc2l0aW9uQ29vcmRzKHRyYWNlLCBheExldHRlcikge1xuICAgIHZhciBwb3NMZXR0ZXIgPSBnZXRCb3hQb3NMZXR0ZXIodHJhY2UpO1xuICAgIHZhciBpc0JveCA9IHRyYWNlSXModHJhY2UsICdib3gtdmlvbGluJyk7XG4gICAgdmFyIGlzQ2FuZGxlc3RpY2sgPSB0cmFjZUlzKHRyYWNlLl9mdWxsSW5wdXQgfHwge30sICdjYW5kbGVzdGljaycpO1xuXG4gICAgcmV0dXJuIChcbiAgICAgICAgaXNCb3ggJiZcbiAgICAgICAgIWlzQ2FuZGxlc3RpY2sgJiZcbiAgICAgICAgYXhMZXR0ZXIgPT09IHBvc0xldHRlciAmJlxuICAgICAgICB0cmFjZVtwb3NMZXR0ZXJdID09PSB1bmRlZmluZWQgJiZcbiAgICAgICAgdHJhY2VbcG9zTGV0dGVyICsgJzAnXSA9PT0gdW5kZWZpbmVkXG4gICAgKTtcbn1cblxufSx7XCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4vYXhpc19hdXRvdHlwZVwiOjc2OH1dLDc5MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG5cbi8qXG4gKiBDcmVhdGUgb3IgdXBkYXRlIGFuIG9ic2VydmVyLiBUaGlzIGZ1bmN0aW9uIGlzIGRlc2lnbmVkIHRvIGJlXG4gKiBpZGVtcG90ZW50IHNvIHRoYXQgaXQgY2FuIGJlIGNhbGxlZCBvdmVyIGFuZCBvdmVyIGFzIHRoZSBjb21wb25lbnRcbiAqIHVwZGF0ZXMsIGFuZCB3aWxsIGF0dGFjaCBhbmQgZGV0YWNoIGxpc3RlbmVycyBhcyBuZWVkZWQuXG4gKlxuICogQHBhcmFtIHtvcHRpb25hbCBvYmplY3R9IGNvbnRhaW5lclxuICogICAgICBBbiBvYmplY3Qgb24gd2hpY2ggdGhlIG9ic2VydmVyIGlzIHN0b3JlZC4gVGhpcyBpcyB0aGUgbWVjaGFuaXNtXG4gKiAgICAgIGJ5IHdoaWNoIGl0IGlzIGlkZW1wb3RlbnQuIElmIGl0IGFscmVhZHkgZXhpc3RzLCBhbm90aGVyIHdvbid0IGJlXG4gKiAgICAgIGFkZGVkLiBFYWNoIHRpbWUgaXQncyBjYWxsZWQsIHRoZSB2YWx1ZSBsb29rdXAgdGFibGUgaXMgdXBkYXRlZC5cbiAqIEBwYXJhbSB7YXJyYXl9IGNvbW1hbmRMaXN0XG4gKiAgICAgIEFuIGFycmF5IG9mIGNvbW1hbmRzLCBmb2xsb3dpbmcgZWl0aGVyIGBidXR0b25zYCBvZiBgdXBkYXRlbWVudXNgXG4gKiAgICAgIG9yIGBzdGVwc2Agb2YgYHNsaWRlcnNgLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gb25jaGFuZ2VcbiAqICAgICAgQSBsaXN0ZW5lciBjYWxsZWQgd2hlbiB0aGUgdmFsdWUgaXMgY2hhbmdlZC4gUmVjZWl2ZXMgZGF0YSBvYmplY3RcbiAqICAgICAgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbmV3IHN0YXRlLlxuICovXG5leHBvcnRzLm1hbmFnZUNvbW1hbmRPYnNlcnZlciA9IGZ1bmN0aW9uKGdkLCBjb250YWluZXIsIGNvbW1hbmRMaXN0LCBvbmNoYW5nZSkge1xuICAgIHZhciByZXQgPSB7fTtcbiAgICB2YXIgZW5hYmxlZCA9IHRydWU7XG5cbiAgICBpZihjb250YWluZXIgJiYgY29udGFpbmVyLl9jb21tYW5kT2JzZXJ2ZXIpIHtcbiAgICAgICAgcmV0ID0gY29udGFpbmVyLl9jb21tYW5kT2JzZXJ2ZXI7XG4gICAgfVxuXG4gICAgaWYoIXJldC5jYWNoZSkge1xuICAgICAgICByZXQuY2FjaGUgPSB7fTtcbiAgICB9XG5cbiAgICAvLyBFaXRoZXIgY3JlYXRlIG9yIGp1c3QgcmVjb21wdXRlIHRoaXM6XG4gICAgcmV0Lmxvb2t1cFRhYmxlID0ge307XG5cbiAgICB2YXIgYmluZGluZyA9IGV4cG9ydHMuaGFzU2ltcGxlQVBJQ29tbWFuZEJpbmRpbmdzKGdkLCBjb21tYW5kTGlzdCwgcmV0Lmxvb2t1cFRhYmxlKTtcblxuICAgIGlmKGNvbnRhaW5lciAmJiBjb250YWluZXIuX2NvbW1hbmRPYnNlcnZlcikge1xuICAgICAgICBpZighYmluZGluZykge1xuICAgICAgICAgICAgLy8gSWYgY29udGFpbmVyIGV4aXN0cyBhbmQgdGhlcmUgYXJlIG5vIGxvbmdlciBhbnkgYmluZGluZ3MsXG4gICAgICAgICAgICAvLyByZW1vdmUgZXhpc3Rpbmc6XG4gICAgICAgICAgICBpZihjb250YWluZXIuX2NvbW1hbmRPYnNlcnZlci5yZW1vdmUpIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXIuX2NvbW1hbmRPYnNlcnZlci5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICBjb250YWluZXIuX2NvbW1hbmRPYnNlcnZlciA9IG51bGw7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIElmIGNvbnRhaW5lciBleGlzdHMgYW5kIHRoZXJlICphcmUqIGJpbmRpbmdzLCB0aGVuIHRoZSBsb29rdXBcbiAgICAgICAgICAgIC8vIHRhYmxlIHNob3VsZCBoYXZlIGJlZW4gdXBkYXRlZCBhbmQgY2hlY2sgaXMgYWxyZWFkeSBhdHRhY2hlZCxcbiAgICAgICAgICAgIC8vIHNvIHRoZXJlJ3Mgbm90aGluZyB0byBiZSBkb25lOlxuICAgICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIERldGVybWluZSB3aGV0aGVyIHRoZXJlJ3MgYW55dGhpbmcgdG8gZG8gZm9yIHRoaXMgYmluZGluZzpcblxuICAgIGlmKGJpbmRpbmcpIHtcbiAgICAgICAgLy8gQnVpbGQgdGhlIGNhY2hlOlxuICAgICAgICBiaW5kaW5nVmFsdWVIYXNDaGFuZ2VkKGdkLCBiaW5kaW5nLCByZXQuY2FjaGUpO1xuXG4gICAgICAgIHJldC5jaGVjayA9IGZ1bmN0aW9uIGNoZWNrKCkge1xuICAgICAgICAgICAgaWYoIWVuYWJsZWQpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZSA9IGJpbmRpbmdWYWx1ZUhhc0NoYW5nZWQoZ2QsIGJpbmRpbmcsIHJldC5jYWNoZSk7XG5cbiAgICAgICAgICAgIGlmKHVwZGF0ZS5jaGFuZ2VkICYmIG9uY2hhbmdlKSB7XG4gICAgICAgICAgICAgICAgLy8gRGlzYWJsZSBjaGVja3MgZm9yIHRoZSBkdXJhdGlvbiBvZiB0aGlzIGNvbW1hbmQgaW4gb3JkZXIgdG8gYXZvaWRcbiAgICAgICAgICAgICAgICAvLyBpbmZpbml0ZSBsb29wczpcbiAgICAgICAgICAgICAgICBpZihyZXQubG9va3VwVGFibGVbdXBkYXRlLnZhbHVlXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldC5kaXNhYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgIFByb21pc2UucmVzb2x2ZShvbmNoYW5nZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdXBkYXRlLnZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogYmluZGluZy50eXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcDogYmluZGluZy5wcm9wLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2VzOiBiaW5kaW5nLnRyYWNlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4OiByZXQubG9va3VwVGFibGVbdXBkYXRlLnZhbHVlXVxuICAgICAgICAgICAgICAgICAgICB9KSkudGhlbihyZXQuZW5hYmxlLCByZXQuZW5hYmxlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB1cGRhdGUuY2hhbmdlZDtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgY2hlY2tFdmVudHMgPSBbXG4gICAgICAgICAgICAncGxvdGx5X3JlbGF5b3V0JyxcbiAgICAgICAgICAgICdwbG90bHlfcmVkcmF3JyxcbiAgICAgICAgICAgICdwbG90bHlfcmVzdHlsZScsXG4gICAgICAgICAgICAncGxvdGx5X3VwZGF0ZScsXG4gICAgICAgICAgICAncGxvdGx5X2FuaW1hdGluZ2ZyYW1lJyxcbiAgICAgICAgICAgICdwbG90bHlfYWZ0ZXJwbG90J1xuICAgICAgICBdO1xuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjaGVja0V2ZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZ2QuX2ludGVybmFsT24oY2hlY2tFdmVudHNbaV0sIHJldC5jaGVjayk7XG4gICAgICAgIH1cblxuICAgICAgICByZXQucmVtb3ZlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2hlY2tFdmVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBnZC5fcmVtb3ZlSW50ZXJuYWxMaXN0ZW5lcihjaGVja0V2ZW50c1tpXSwgcmV0LmNoZWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBUT0RPOiBJdCdkIGJlIHJlYWxseSBuZWF0IHRvIGFjdHVhbGx5IGdpdmUgYSAqcmVhc29uKiBmb3IgdGhpcywgYnV0IGF0IGxlYXN0IGEgd2FybmluZ1xuICAgICAgICAvLyBpcyBhIHN0YXJ0XG4gICAgICAgIExpYi5sb2coJ1VuYWJsZSB0byBhdXRvbWF0aWNhbGx5IGJpbmQgcGxvdCB1cGRhdGVzIHRvIEFQSSBjb21tYW5kJyk7XG5cbiAgICAgICAgcmV0Lmxvb2t1cFRhYmxlID0ge307XG4gICAgICAgIHJldC5yZW1vdmUgPSBmdW5jdGlvbigpIHt9O1xuICAgIH1cblxuICAgIHJldC5kaXNhYmxlID0gZnVuY3Rpb24gZGlzYWJsZSgpIHtcbiAgICAgICAgZW5hYmxlZCA9IGZhbHNlO1xuICAgIH07XG5cbiAgICByZXQuZW5hYmxlID0gZnVuY3Rpb24gZW5hYmxlKCkge1xuICAgICAgICBlbmFibGVkID0gdHJ1ZTtcbiAgICB9O1xuXG4gICAgaWYoY29udGFpbmVyKSB7XG4gICAgICAgIGNvbnRhaW5lci5fY29tbWFuZE9ic2VydmVyID0gcmV0O1xuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG59O1xuXG4vKlxuICogVGhpcyBmdW5jdGlvbiBjaGVja3MgdG8gc2VlIGlmIGFuIGFycmF5IG9mIG9iamVjdHMgY29udGFpbmluZ1xuICogbWV0aG9kIGFuZCBhcmdzIHByb3BlcnRpZXMgaXMgY29tcGF0aWJsZSB3aXRoIGF1dG9tYXRpYyB0d28td2F5XG4gKiBiaW5kaW5nLiBUaGUgY3JpdGVyaWEgcmlnaHQgbm93IGFyZSB0aGF0XG4gKlxuICogICAxLiBtdWx0aXBsZSB0cmFjZXMgbWF5IGJlIGFmZmVjdGVkXG4gKiAgIDIuIG9ubHkgb25lIHByb3BlcnR5IG1heSBiZSBhZmZlY3RlZFxuICogICAzLiB0aGUgc2FtZSBwcm9wZXJ0eSBtdXN0IGJlIGFmZmVjdGVkIGJ5IGFsbCBjb21tYW5kc1xuICovXG5leHBvcnRzLmhhc1NpbXBsZUFQSUNvbW1hbmRCaW5kaW5ncyA9IGZ1bmN0aW9uKGdkLCBjb21tYW5kTGlzdCwgYmluZGluZ3NCeVZhbHVlKSB7XG4gICAgdmFyIGk7XG4gICAgdmFyIG4gPSBjb21tYW5kTGlzdC5sZW5ndGg7XG5cbiAgICB2YXIgcmVmQmluZGluZztcblxuICAgIGZvcihpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICB2YXIgYmluZGluZztcbiAgICAgICAgdmFyIGNvbW1hbmQgPSBjb21tYW5kTGlzdFtpXTtcbiAgICAgICAgdmFyIG1ldGhvZCA9IGNvbW1hbmQubWV0aG9kO1xuICAgICAgICB2YXIgYXJncyA9IGNvbW1hbmQuYXJncztcblxuICAgICAgICBpZighQXJyYXkuaXNBcnJheShhcmdzKSkgYXJncyA9IFtdO1xuXG4gICAgICAgIC8vIElmIGFueSBjb21tYW5kIGhhcyBubyBtZXRob2QsIHJlZnVzZSB0byBiaW5kOlxuICAgICAgICBpZighbWV0aG9kKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJpbmRpbmdzID0gZXhwb3J0cy5jb21wdXRlQVBJQ29tbWFuZEJpbmRpbmdzKGdkLCBtZXRob2QsIGFyZ3MpO1xuXG4gICAgICAgIC8vIFJpZ2h0IG5vdywgaGFuZGxlIG9uZSBhbmQgKm9ubHkqIG9uZSBwcm9wZXJ0eSBiZWluZyBzZXQ6XG4gICAgICAgIGlmKGJpbmRpbmdzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIXJlZkJpbmRpbmcpIHtcbiAgICAgICAgICAgIHJlZkJpbmRpbmcgPSBiaW5kaW5nc1swXTtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkocmVmQmluZGluZy50cmFjZXMpKSB7XG4gICAgICAgICAgICAgICAgcmVmQmluZGluZy50cmFjZXMuc29ydCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYmluZGluZyA9IGJpbmRpbmdzWzBdO1xuICAgICAgICAgICAgaWYoYmluZGluZy50eXBlICE9PSByZWZCaW5kaW5nLnR5cGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihiaW5kaW5nLnByb3AgIT09IHJlZkJpbmRpbmcucHJvcCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkocmVmQmluZGluZy50cmFjZXMpKSB7XG4gICAgICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShiaW5kaW5nLnRyYWNlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgYmluZGluZy50cmFjZXMuc29ydCgpO1xuICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgcmVmQmluZGluZy50cmFjZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHJlZkJpbmRpbmcudHJhY2VzW2pdICE9PSBiaW5kaW5nLnRyYWNlc1tqXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmKGJpbmRpbmcucHJvcCAhPT0gcmVmQmluZGluZy5wcm9wKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBiaW5kaW5nID0gYmluZGluZ3NbMF07XG4gICAgICAgIHZhciB2YWx1ZSA9IGJpbmRpbmcudmFsdWU7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgICBpZih2YWx1ZS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlWzBdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYoYmluZGluZ3NCeVZhbHVlKSB7XG4gICAgICAgICAgICBiaW5kaW5nc0J5VmFsdWVbdmFsdWVdID0gaTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZWZCaW5kaW5nO1xufTtcblxuZnVuY3Rpb24gYmluZGluZ1ZhbHVlSGFzQ2hhbmdlZChnZCwgYmluZGluZywgY2FjaGUpIHtcbiAgICB2YXIgY29udGFpbmVyLCB2YWx1ZSwgb2JqO1xuICAgIHZhciBjaGFuZ2VkID0gZmFsc2U7XG5cbiAgICBpZihiaW5kaW5nLnR5cGUgPT09ICdkYXRhJykge1xuICAgICAgICAvLyBJZiBpdCdzIGRhdGEsIHdlIG5lZWQgdG8gZ2V0IGEgdHJhY2UuIEJhc2VkIG9uIHRoZSBsaW1pdGVkIHNjb3BlXG4gICAgICAgIC8vIG9mIHdoYXQgd2UgY292ZXIsIHdlIGNhbiBqdXN0IHRha2UgdGhlIGZpcnN0IHRyYWNlIGZyb20gdGhlIGxpc3QsXG4gICAgICAgIC8vIG9yIG90aGVyd2lzZSBqdXN0IHRoZSBmaXJzdCB0cmFjZTpcbiAgICAgICAgY29udGFpbmVyID0gZ2QuX2Z1bGxEYXRhW2JpbmRpbmcudHJhY2VzICE9PSBudWxsID8gYmluZGluZy50cmFjZXNbMF0gOiAwXTtcbiAgICB9IGVsc2UgaWYoYmluZGluZy50eXBlID09PSAnbGF5b3V0Jykge1xuICAgICAgICBjb250YWluZXIgPSBnZC5fZnVsbExheW91dDtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFsdWUgPSBMaWIubmVzdGVkUHJvcGVydHkoY29udGFpbmVyLCBiaW5kaW5nLnByb3ApLmdldCgpO1xuXG4gICAgb2JqID0gY2FjaGVbYmluZGluZy50eXBlXSA9IGNhY2hlW2JpbmRpbmcudHlwZV0gfHwge307XG5cbiAgICBpZihvYmouaGFzT3duUHJvcGVydHkoYmluZGluZy5wcm9wKSkge1xuICAgICAgICBpZihvYmpbYmluZGluZy5wcm9wXSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIGNoYW5nZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb2JqW2JpbmRpbmcucHJvcF0gPSB2YWx1ZTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGNoYW5nZWQ6IGNoYW5nZWQsXG4gICAgICAgIHZhbHVlOiB2YWx1ZVxuICAgIH07XG59XG5cbi8qXG4gKiBFeGVjdXRlIGFuIEFQSSBjb21tYW5kLiBUaGVyZSdzIHJlYWxseSBub3QgbXVjaCB0byB0aGlzOyBpdCBqdXN0IHByb3ZpZGVzXG4gKiBhIGNvbW1vbiBob29rIHNvIHRoYXQgaW1wbGVtZW50YXRpb25zIGRvbid0IG5lZWQgdG8gYmUgc3luY2hyb25pemVkIGFjcm9zc1xuICogbXVsdGlwbGUgY29tcG9uZW50cyB3aXRoIHRoZSBhYmlsaXR5IHRvIGludm9rZSBBUEkgY29tbWFuZHMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZFxuICogICAgICBUaGUgbmFtZSBvZiB0aGUgcGxvdGx5IGNvbW1hbmQgdG8gZXhlY3V0ZS4gTXVzdCBiZSBvbmUgb2YgJ2FuaW1hdGUnLFxuICogICAgICAncmVzdHlsZScsICdyZWxheW91dCcsICd1cGRhdGUnLlxuICogQHBhcmFtIHthcnJheX0gYXJnc1xuICogICAgICBBIGxpc3Qgb2YgYXJndW1lbnRzIHBhc3NlZCB0byB0aGUgQVBJIGNvbW1hbmRcbiAqL1xuZXhwb3J0cy5leGVjdXRlQVBJQ29tbWFuZCA9IGZ1bmN0aW9uKGdkLCBtZXRob2QsIGFyZ3MpIHtcbiAgICBpZihtZXRob2QgPT09ICdza2lwJykgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuXG4gICAgdmFyIF9tZXRob2QgPSBSZWdpc3RyeS5hcGlNZXRob2RSZWdpc3RyeVttZXRob2RdO1xuICAgIHZhciBhbGxBcmdzID0gW2dkXTtcbiAgICBpZighQXJyYXkuaXNBcnJheShhcmdzKSkgYXJncyA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYWxsQXJncy5wdXNoKGFyZ3NbaV0pO1xuICAgIH1cblxuICAgIHJldHVybiBfbWV0aG9kLmFwcGx5KG51bGwsIGFsbEFyZ3MpLmNhdGNoKGZ1bmN0aW9uKGVycikge1xuICAgICAgICBMaWIud2FybignQVBJIGNhbGwgdG8gUGxvdGx5LicgKyBtZXRob2QgKyAnIHJlamVjdGVkLicsIGVycik7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnIpO1xuICAgIH0pO1xufTtcblxuZXhwb3J0cy5jb21wdXRlQVBJQ29tbWFuZEJpbmRpbmdzID0gZnVuY3Rpb24oZ2QsIG1ldGhvZCwgYXJncykge1xuICAgIHZhciBiaW5kaW5ncztcblxuICAgIGlmKCFBcnJheS5pc0FycmF5KGFyZ3MpKSBhcmdzID0gW107XG5cbiAgICBzd2l0Y2gobWV0aG9kKSB7XG4gICAgICAgIGNhc2UgJ3Jlc3R5bGUnOlxuICAgICAgICAgICAgYmluZGluZ3MgPSBjb21wdXRlRGF0YUJpbmRpbmdzKGdkLCBhcmdzKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdyZWxheW91dCc6XG4gICAgICAgICAgICBiaW5kaW5ncyA9IGNvbXB1dGVMYXlvdXRCaW5kaW5ncyhnZCwgYXJncyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndXBkYXRlJzpcbiAgICAgICAgICAgIGJpbmRpbmdzID0gY29tcHV0ZURhdGFCaW5kaW5ncyhnZCwgW2FyZ3NbMF0sIGFyZ3NbMl1dKVxuICAgICAgICAgICAgICAgIC5jb25jYXQoY29tcHV0ZUxheW91dEJpbmRpbmdzKGdkLCBbYXJnc1sxXV0pKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdhbmltYXRlJzpcbiAgICAgICAgICAgIGJpbmRpbmdzID0gY29tcHV0ZUFuaW1hdGVCaW5kaW5ncyhnZCwgYXJncyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgdGhlIGNhc2Ugd2hlcmUgaW50ZWxsaWdlbnQgbG9naWMgYWJvdXQgd2hhdCBhZmZlY3RzXG4gICAgICAgICAgICAvLyB0aGlzIGNvbW1hbmQgaXMgbm90IGltcGxlbWVudGVkLiBJdCBjYXVzZXMgbm8gaWxsIGVmZmVjdHMuXG4gICAgICAgICAgICAvLyBGb3IgZXhhbXBsZSwgYWRkRnJhbWVzIHNpbXBseSB3b24ndCBiaW5kIHRvIGEgY29udHJvbCBjb21wb25lbnQuXG4gICAgICAgICAgICBiaW5kaW5ncyA9IFtdO1xuICAgIH1cbiAgICByZXR1cm4gYmluZGluZ3M7XG59O1xuXG5mdW5jdGlvbiBjb21wdXRlQW5pbWF0ZUJpbmRpbmdzKGdkLCBhcmdzKSB7XG4gICAgLy8gV2UnbGwgYXNzdW1lIHRoYXQgdGhlIG9ubHkgcmVsZXZhbnQgbW9kaWZpY2F0aW9uIGFuIGFuaW1hdGlvblxuICAgIC8vIG1ha2VzIHRoYXQncyBtZWFuaW5nZnVsbHkgdHJhY2tlZCBpcyB0aGUgZnJhbWU6XG4gICAgaWYoQXJyYXkuaXNBcnJheShhcmdzWzBdKSAmJiBhcmdzWzBdLmxlbmd0aCA9PT0gMSAmJiBbJ3N0cmluZycsICdudW1iZXInXS5pbmRleE9mKHR5cGVvZiBhcmdzWzBdWzBdKSAhPT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIFt7dHlwZTogJ2xheW91dCcsIHByb3A6ICdfY3VycmVudEZyYW1lJywgdmFsdWU6IGFyZ3NbMF1bMF0udG9TdHJpbmcoKX1dO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVMYXlvdXRCaW5kaW5ncyhnZCwgYXJncykge1xuICAgIHZhciBiaW5kaW5ncyA9IFtdO1xuXG4gICAgdmFyIGFzdHIgPSBhcmdzWzBdO1xuICAgIHZhciBhb2JqID0ge307XG4gICAgaWYodHlwZW9mIGFzdHIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGFvYmpbYXN0cl0gPSBhcmdzWzFdO1xuICAgIH0gZWxzZSBpZihMaWIuaXNQbGFpbk9iamVjdChhc3RyKSkge1xuICAgICAgICBhb2JqID0gYXN0cjtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gYmluZGluZ3M7XG4gICAgfVxuXG4gICAgY3Jhd2woYW9iaiwgZnVuY3Rpb24ocGF0aCwgYXR0ck5hbWUsIGF0dHIpIHtcbiAgICAgICAgYmluZGluZ3MucHVzaCh7dHlwZTogJ2xheW91dCcsIHByb3A6IHBhdGgsIHZhbHVlOiBhdHRyfSk7XG4gICAgfSwgJycsIDApO1xuXG4gICAgcmV0dXJuIGJpbmRpbmdzO1xufVxuXG5mdW5jdGlvbiBjb21wdXRlRGF0YUJpbmRpbmdzKGdkLCBhcmdzKSB7XG4gICAgdmFyIHRyYWNlcywgYXN0ciwgdmFsLCBhb2JqO1xuICAgIHZhciBiaW5kaW5ncyA9IFtdO1xuXG4gICAgLy8gTG9naWMgY29waWVkIGZyb20gUGxvdGx5LnJlc3R5bGU6XG4gICAgYXN0ciA9IGFyZ3NbMF07XG4gICAgdmFsID0gYXJnc1sxXTtcbiAgICB0cmFjZXMgPSBhcmdzWzJdO1xuICAgIGFvYmogPSB7fTtcbiAgICBpZih0eXBlb2YgYXN0ciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgYW9ialthc3RyXSA9IHZhbDtcbiAgICB9IGVsc2UgaWYoTGliLmlzUGxhaW5PYmplY3QoYXN0cikpIHtcbiAgICAgICAgLy8gdGhlIDMtYXJnIGZvcm1cbiAgICAgICAgYW9iaiA9IGFzdHI7XG5cbiAgICAgICAgaWYodHJhY2VzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRyYWNlcyA9IHZhbDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBiaW5kaW5ncztcbiAgICB9XG5cbiAgICBpZih0cmFjZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyBFeHBsaWNpdGx5IGFzc2lnbiB0aGlzIHRvIG51bGwgaW5zdGVhZCBvZiB1bmRlZmluZWQ6XG4gICAgICAgIHRyYWNlcyA9IG51bGw7XG4gICAgfVxuXG4gICAgY3Jhd2woYW9iaiwgZnVuY3Rpb24ocGF0aCwgYXR0ck5hbWUsIF9hdHRyKSB7XG4gICAgICAgIHZhciB0aGlzVHJhY2VzO1xuICAgICAgICB2YXIgYXR0cjtcblxuICAgICAgICBpZihBcnJheS5pc0FycmF5KF9hdHRyKSkge1xuICAgICAgICAgICAgYXR0ciA9IF9hdHRyLnNsaWNlKCk7XG5cbiAgICAgICAgICAgIHZhciBuQXR0ciA9IE1hdGgubWluKGF0dHIubGVuZ3RoLCBnZC5kYXRhLmxlbmd0aCk7XG4gICAgICAgICAgICBpZih0cmFjZXMpIHtcbiAgICAgICAgICAgICAgICBuQXR0ciA9IE1hdGgubWluKG5BdHRyLCB0cmFjZXMubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXNUcmFjZXMgPSBbXTtcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBuQXR0cjsgaisrKSB7XG4gICAgICAgICAgICAgICAgdGhpc1RyYWNlc1tqXSA9IHRyYWNlcyA/IHRyYWNlc1tqXSA6IGo7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhdHRyID0gX2F0dHI7XG4gICAgICAgICAgICB0aGlzVHJhY2VzID0gdHJhY2VzID8gdHJhY2VzLnNsaWNlKCkgOiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29udmVydCBbN10gdG8ganVzdCA3IHdoZW4gdHJhY2VzIGlzIG51bGw6XG4gICAgICAgIGlmKHRoaXNUcmFjZXMgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoYXR0cikpIHtcbiAgICAgICAgICAgICAgICBhdHRyID0gYXR0clswXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKEFycmF5LmlzQXJyYXkodGhpc1RyYWNlcykpIHtcbiAgICAgICAgICAgIGlmKCFBcnJheS5pc0FycmF5KGF0dHIpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRtcCA9IGF0dHI7XG4gICAgICAgICAgICAgICAgYXR0ciA9IFtdO1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0aGlzVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGF0dHJbaV0gPSB0bXA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXR0ci5sZW5ndGggPSBNYXRoLm1pbih0aGlzVHJhY2VzLmxlbmd0aCwgYXR0ci5sZW5ndGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgYmluZGluZ3MucHVzaCh7XG4gICAgICAgICAgICB0eXBlOiAnZGF0YScsXG4gICAgICAgICAgICBwcm9wOiBwYXRoLFxuICAgICAgICAgICAgdHJhY2VzOiB0aGlzVHJhY2VzLFxuICAgICAgICAgICAgdmFsdWU6IGF0dHJcbiAgICAgICAgfSk7XG4gICAgfSwgJycsIDApO1xuXG4gICAgcmV0dXJuIGJpbmRpbmdzO1xufVxuXG5mdW5jdGlvbiBjcmF3bChhdHRycywgY2FsbGJhY2ssIHBhdGgsIGRlcHRoKSB7XG4gICAgT2JqZWN0LmtleXMoYXR0cnMpLmZvckVhY2goZnVuY3Rpb24oYXR0ck5hbWUpIHtcbiAgICAgICAgdmFyIGF0dHIgPSBhdHRyc1thdHRyTmFtZV07XG5cbiAgICAgICAgaWYoYXR0ck5hbWVbMF0gPT09ICdfJykgcmV0dXJuO1xuXG4gICAgICAgIHZhciB0aGlzUGF0aCA9IHBhdGggKyAoZGVwdGggPiAwID8gJy4nIDogJycpICsgYXR0ck5hbWU7XG5cbiAgICAgICAgaWYoTGliLmlzUGxhaW5PYmplY3QoYXR0cikpIHtcbiAgICAgICAgICAgIGNyYXdsKGF0dHIsIGNhbGxiYWNrLCB0aGlzUGF0aCwgZGVwdGggKyAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE9ubHkgZXhlY3V0ZSB0aGUgY2FsbGJhY2sgb24gbGVhZiBub2RlczpcbiAgICAgICAgICAgIGNhbGxiYWNrKHRoaXNQYXRoLCBhdHRyTmFtZSwgYXR0cik7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxufSx7XCIuLi9saWJcIjo3MTksXCIuLi9yZWdpc3RyeVwiOjg0N31dLDc5MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbi8qKlxuICogTWFrZSBhIHh5IGRvbWFpbiBhdHRyaWJ1dGUgZ3JvdXBcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0c1xuICogICBAcGFyYW0ge3N0cmluZ31cbiAqICAgICBvcHRzLm5hbWU6IG5hbWUgdG8gYmUgaW5zZXJ0ZWQgaW4gdGhlIGRlZmF1bHQgZGVzY3JpcHRpb25cbiAqICAgQHBhcmFtIHtib29sZWFufVxuICogICAgIG9wdHMudHJhY2U6IHNldCB0byB0cnVlIGZvciB0cmFjZSBjb250YWluZXJzXG4gKiAgIEBwYXJhbSB7c3RyaW5nfVxuICogICAgIG9wdHMuZWRpdFR5cGU6IGVkaXRUeXBlIGZvciBhbGwgcGllY2VzXG4gKiAgIEBwYXJhbSB7Ym9vbGVhbn1cbiAqICAgICBvcHRzLm5vR3JpZENlbGw6IHNldCB0byB0cnVlIHRvIG9taXQgYHJvd2AgYW5kIGBjb2x1bW5gXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGV4dHJhXG4gKiAgIEBwYXJhbSB7c3RyaW5nfVxuICogICAgIGV4dHJhLmRlc2NyaXB0aW9uOiBleHRyYSBkZXNjcmlwdGlvbi4gTi5CIHdlIHVzZVxuICogICAgIGEgc2VwYXJhdGUgZXh0cmEgY29udGFpbmVyIHRvIG1ha2UgaXQgY29tcGF0aWJsZSB3aXRoXG4gKiAgICAgdGhlIGNvbXByZXNzX2F0dHJpYnV0ZXMgdHJhbnNmb3JtLlxuICpcbiAqIEByZXR1cm4ge29iamVjdH0gYXR0cmlidXRlcyBvYmplY3QgY29udGFpbmluZyB7eCx5fSBhcyBzcGVjaWZpZWRcbiAqL1xuZXhwb3J0cy5hdHRyaWJ1dGVzID0gZnVuY3Rpb24ob3B0cywgZXh0cmEpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcbiAgICBleHRyYSA9IGV4dHJhIHx8IHt9O1xuXG4gICAgdmFyIGJhc2UgPSB7XG4gICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiBvcHRzLmVkaXRUeXBlLFxuICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInLCBtaW46IDAsIG1heDogMSwgZWRpdFR5cGU6IG9wdHMuZWRpdFR5cGV9LFxuICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInLCBtaW46IDAsIG1heDogMSwgZWRpdFR5cGU6IG9wdHMuZWRpdFR5cGV9XG4gICAgICAgIF0sXG4gICAgICAgIGRmbHQ6IFswLCAxXVxuICAgIH07XG5cbiAgICB2YXIgbmFtZVBhcnQgPSBvcHRzLm5hbWUgPyBvcHRzLm5hbWUgKyAnICcgOiAnJztcbiAgICB2YXIgY29udFBhcnQgPSBvcHRzLnRyYWNlID8gJ3RyYWNlICcgOiAnc3VicGxvdCAnO1xuICAgIHZhciBkZXNjUGFydCA9IGV4dHJhLmRlc2NyaXB0aW9uID8gJyAnICsgZXh0cmEuZGVzY3JpcHRpb24gOiAnJztcblxuICAgIHZhciBvdXQgPSB7XG4gICAgICAgIHg6IGV4dGVuZEZsYXQoe30sIGJhc2UsIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgeTogZXh0ZW5kRmxhdCh7fSwgYmFzZSwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBlZGl0VHlwZTogb3B0cy5lZGl0VHlwZVxuICAgIH07XG5cbiAgICBpZighb3B0cy5ub0dyaWRDZWxsKSB7XG4gICAgICAgIG91dC5yb3cgPSB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogb3B0cy5lZGl0VHlwZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9O1xuICAgICAgICBvdXQuY29sdW1uID0ge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6IG9wdHMuZWRpdFR5cGUsXG4gICAgICAgICAgICBcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxuZXhwb3J0cy5kZWZhdWx0cyA9IGZ1bmN0aW9uKGNvbnRhaW5lck91dCwgbGF5b3V0LCBjb2VyY2UsIGRmbHREb21haW5zKSB7XG4gICAgdmFyIGRmbHRYID0gKGRmbHREb21haW5zICYmIGRmbHREb21haW5zLngpIHx8IFswLCAxXTtcbiAgICB2YXIgZGZsdFkgPSAoZGZsdERvbWFpbnMgJiYgZGZsdERvbWFpbnMueSkgfHwgWzAsIDFdO1xuXG4gICAgdmFyIGdyaWQgPSBsYXlvdXQuZ3JpZDtcbiAgICBpZihncmlkKSB7XG4gICAgICAgIHZhciBjb2x1bW4gPSBjb2VyY2UoJ2RvbWFpbi5jb2x1bW4nKTtcbiAgICAgICAgaWYoY29sdW1uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmKGNvbHVtbiA8IGdyaWQuY29sdW1ucykgZGZsdFggPSBncmlkLl9kb21haW5zLnhbY29sdW1uXTtcbiAgICAgICAgICAgIGVsc2UgZGVsZXRlIGNvbnRhaW5lck91dC5kb21haW4uY29sdW1uO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJvdyA9IGNvZXJjZSgnZG9tYWluLnJvdycpO1xuICAgICAgICBpZihyb3cgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYocm93IDwgZ3JpZC5yb3dzKSBkZmx0WSA9IGdyaWQuX2RvbWFpbnMueVtyb3ddO1xuICAgICAgICAgICAgZWxzZSBkZWxldGUgY29udGFpbmVyT3V0LmRvbWFpbi5yb3c7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb2VyY2UoJ2RvbWFpbi54JywgZGZsdFgpO1xuICAgIGNvZXJjZSgnZG9tYWluLnknLCBkZmx0WSk7XG59O1xuXG59LHtcIi4uL2xpYi9leHRlbmRcIjo3MTB9XSw3OTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogbWFrZSBhIGZvbnQgYXR0cmlidXRlIGdyb3VwXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqICAgQHBhcmFtIHtzdHJpbmd9XG4gKiAgICAgb3B0cy5kZXNjcmlwdGlvbjogd2hlcmUgJiBob3cgdGhpcyBmb250IGlzIHVzZWRcbiAqICAgQHBhcmFtIHtvcHRpb25hbCBib29sfSBhcnJheU9rOlxuICogICAgIHNob3VsZCBlYWNoIHBhcnQgKGZhbWlseSwgc2l6ZSwgY29sb3IpIGJlIGFycmF5T2s/IGRlZmF1bHQgZmFsc2UuXG4gKiAgIEBwYXJhbSB7c3RyaW5nfSBlZGl0VHlwZTpcbiAqICAgICB0aGUgZWRpdFR5cGUgZm9yIGFsbCBwaWVjZXMgb2YgdGhpcyBmb250XG4gKiAgIEBwYXJhbSB7b3B0aW9uYWwgc3RyaW5nfSBjb2xvckVkaXRUeXBlOlxuICogICAgIGEgc2VwYXJhdGUgZWRpdFR5cGUganVzdCBmb3IgY29sb3JcbiAqXG4gKiBAcmV0dXJuIHtvYmplY3R9IGF0dHJpYnV0ZXMgb2JqZWN0IGNvbnRhaW5pbmcge2ZhbWlseSwgc2l6ZSwgY29sb3J9IGFzIHNwZWNpZmllZFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG9wdHMpIHtcbiAgICB2YXIgZWRpdFR5cGUgPSBvcHRzLmVkaXRUeXBlO1xuICAgIHZhciBjb2xvckVkaXRUeXBlID0gb3B0cy5jb2xvckVkaXRUeXBlO1xuICAgIGlmKGNvbG9yRWRpdFR5cGUgPT09IHVuZGVmaW5lZCkgY29sb3JFZGl0VHlwZSA9IGVkaXRUeXBlO1xuICAgIHZhciBhdHRycyA9IHtcbiAgICAgICAgZmFtaWx5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbm9CbGFuazogdHJ1ZSxcbiAgICAgICAgICAgIHN0cmljdDogdHJ1ZSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiBlZGl0VHlwZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaXplOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAxLFxuICAgICAgICAgICAgZWRpdFR5cGU6IGVkaXRUeXBlXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogY29sb3JFZGl0VHlwZVxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogZWRpdFR5cGUsXG4gICAgICAgIC8vIGJsYW5rIHN0cmluZ3Mgc28gY29tcHJlc3NfYXR0cmlidXRlcyBjYW4gcmVtb3ZlXG4gICAgICAgIC8vIFRPRE8gLSB0aGF0J3MgdWJlciBoYWNreS4uLiBiZXR0ZXIgc29sdXRpb24/XG4gICAgICAgIFxuICAgIH07XG5cbiAgICBpZihvcHRzLmFycmF5T2spIHtcbiAgICAgICAgYXR0cnMuZmFtaWx5LmFycmF5T2sgPSB0cnVlO1xuICAgICAgICBhdHRycy5zaXplLmFycmF5T2sgPSB0cnVlO1xuICAgICAgICBhdHRycy5jb2xvci5hcnJheU9rID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXR0cnM7XG59O1xuXG59LHt9XSw3OTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBfaXNMaW5rZWRUb0FycmF5OiAnZnJhbWVzX2VudHJ5JyxcblxuICAgIGdyb3VwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBuYW1lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB0cmFjZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGJhc2VmcmFtZToge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgZGF0YToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGF5b3V0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7fV0sNzk1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gcHJvamVjdGlvbiBuYW1lcyB0byBkMyBmdW5jdGlvbiBuYW1lXG5leHBvcnRzLnByb2pOYW1lcyA9IHtcbiAgICAvLyBkMy5nZW8ucHJvamVjdGlvblxuICAgICdlcXVpcmVjdGFuZ3VsYXInOiAnZXF1aXJlY3Rhbmd1bGFyJyxcbiAgICAnbWVyY2F0b3InOiAnbWVyY2F0b3InLFxuICAgICdvcnRob2dyYXBoaWMnOiAnb3J0aG9ncmFwaGljJyxcbiAgICAnbmF0dXJhbCBlYXJ0aCc6ICduYXR1cmFsRWFydGgnLFxuICAgICdrYXZyYXlza2l5Nyc6ICdrYXZyYXlza2l5NycsXG4gICAgJ21pbGxlcic6ICdtaWxsZXInLFxuICAgICdyb2JpbnNvbic6ICdyb2JpbnNvbicsXG4gICAgJ2Vja2VydDQnOiAnZWNrZXJ0NCcsXG4gICAgJ2F6aW11dGhhbCBlcXVhbCBhcmVhJzogJ2F6aW11dGhhbEVxdWFsQXJlYScsXG4gICAgJ2F6aW11dGhhbCBlcXVpZGlzdGFudCc6ICdhemltdXRoYWxFcXVpZGlzdGFudCcsXG4gICAgJ2NvbmljIGVxdWFsIGFyZWEnOiAnY29uaWNFcXVhbEFyZWEnLFxuICAgICdjb25pYyBjb25mb3JtYWwnOiAnY29uaWNDb25mb3JtYWwnLFxuICAgICdjb25pYyBlcXVpZGlzdGFudCc6ICdjb25pY0VxdWlkaXN0YW50JyxcbiAgICAnZ25vbW9uaWMnOiAnZ25vbW9uaWMnLFxuICAgICdzdGVyZW9ncmFwaGljJzogJ3N0ZXJlb2dyYXBoaWMnLFxuICAgICdtb2xsd2VpZGUnOiAnbW9sbHdlaWRlJyxcbiAgICAnaGFtbWVyJzogJ2hhbW1lcicsXG4gICAgJ3RyYW5zdmVyc2UgbWVyY2F0b3InOiAndHJhbnN2ZXJzZU1lcmNhdG9yJyxcbiAgICAnYWxiZXJzIHVzYSc6ICdhbGJlcnNVc2EnLFxuICAgICd3aW5rZWwgdHJpcGVsJzogJ3dpbmtlbDMnLFxuICAgICdhaXRvZmYnOiAnYWl0b2ZmJyxcbiAgICAnc2ludXNvaWRhbCc6ICdzaW51c29pZGFsJ1xufTtcblxuLy8gbmFtZSBvZiB0aGUgYXhlc1xuZXhwb3J0cy5heGVzTmFtZXMgPSBbJ2xvbmF4aXMnLCAnbGF0YXhpcyddO1xuXG4vLyBtYXggbG9uZ2l0dWRpbmFsIGFuZ3VsYXIgc3BhbiAoRVhQRVJJTUVOVEFMKVxuZXhwb3J0cy5sb25heGlzU3BhbiA9IHtcbiAgICAnb3J0aG9ncmFwaGljJzogMTgwLFxuICAgICdhemltdXRoYWwgZXF1YWwgYXJlYSc6IDM2MCxcbiAgICAnYXppbXV0aGFsIGVxdWlkaXN0YW50JzogMzYwLFxuICAgICdjb25pYyBjb25mb3JtYWwnOiAxODAsXG4gICAgJ2dub21vbmljJzogMTYwLFxuICAgICdzdGVyZW9ncmFwaGljJzogMTgwLFxuICAgICd0cmFuc3ZlcnNlIG1lcmNhdG9yJzogMTgwLFxuICAgICcqJzogMzYwXG59O1xuXG4vLyBtYXggbGF0aXR1ZGluYWwgYW5ndWxhciBzcGFuIChFWFBFUklNRU5UQUwpXG5leHBvcnRzLmxhdGF4aXNTcGFuID0ge1xuICAgICdjb25pYyBjb25mb3JtYWwnOiAxNTAsXG4gICAgJ3N0ZXJlb2dyYXBoaWMnOiAxNzkuNSxcbiAgICAnKic6IDE4MFxufTtcblxuLy8gZGVmYXVsdHMgZm9yIGVhY2ggc2NvcGVcbmV4cG9ydHMuc2NvcGVEZWZhdWx0cyA9IHtcbiAgICB3b3JsZDoge1xuICAgICAgICBsb25heGlzUmFuZ2U6IFstMTgwLCAxODBdLFxuICAgICAgICBsYXRheGlzUmFuZ2U6IFstOTAsIDkwXSxcbiAgICAgICAgcHJvalR5cGU6ICdlcXVpcmVjdGFuZ3VsYXInLFxuICAgICAgICBwcm9qUm90YXRlOiBbMCwgMCwgMF1cbiAgICB9LFxuICAgIHVzYToge1xuICAgICAgICBsb25heGlzUmFuZ2U6IFstMTgwLCAtNTBdLFxuICAgICAgICBsYXRheGlzUmFuZ2U6IFsxNSwgODBdLFxuICAgICAgICBwcm9qVHlwZTogJ2FsYmVycyB1c2EnXG4gICAgfSxcbiAgICBldXJvcGU6IHtcbiAgICAgICAgbG9uYXhpc1JhbmdlOiBbLTMwLCA2MF0sXG4gICAgICAgIGxhdGF4aXNSYW5nZTogWzMwLCA4NV0sXG4gICAgICAgIHByb2pUeXBlOiAnY29uaWMgY29uZm9ybWFsJyxcbiAgICAgICAgcHJvalJvdGF0ZTogWzE1LCAwLCAwXSxcbiAgICAgICAgcHJvalBhcmFsbGVsczogWzAsIDYwXVxuICAgIH0sXG4gICAgYXNpYToge1xuICAgICAgICBsb25heGlzUmFuZ2U6IFsyMiwgMTYwXSxcbiAgICAgICAgbGF0YXhpc1JhbmdlOiBbLTE1LCA1NV0sXG4gICAgICAgIHByb2pUeXBlOiAnbWVyY2F0b3InLFxuICAgICAgICBwcm9qUm90YXRlOiBbMCwgMCwgMF1cbiAgICB9LFxuICAgIGFmcmljYToge1xuICAgICAgICBsb25heGlzUmFuZ2U6IFstMzAsIDYwXSxcbiAgICAgICAgbGF0YXhpc1JhbmdlOiBbLTQwLCA0MF0sXG4gICAgICAgIHByb2pUeXBlOiAnbWVyY2F0b3InLFxuICAgICAgICBwcm9qUm90YXRlOiBbMCwgMCwgMF1cbiAgICB9LFxuICAgICdub3J0aCBhbWVyaWNhJzoge1xuICAgICAgICBsb25heGlzUmFuZ2U6IFstMTgwLCAtNDVdLFxuICAgICAgICBsYXRheGlzUmFuZ2U6IFs1LCA4NV0sXG4gICAgICAgIHByb2pUeXBlOiAnY29uaWMgY29uZm9ybWFsJyxcbiAgICAgICAgcHJvalJvdGF0ZTogWy0xMDAsIDAsIDBdLFxuICAgICAgICBwcm9qUGFyYWxsZWxzOiBbMjkuNSwgNDUuNV1cbiAgICB9LFxuICAgICdzb3V0aCBhbWVyaWNhJzoge1xuICAgICAgICBsb25heGlzUmFuZ2U6IFstMTAwLCAtMzBdLFxuICAgICAgICBsYXRheGlzUmFuZ2U6IFstNjAsIDE1XSxcbiAgICAgICAgcHJvalR5cGU6ICdtZXJjYXRvcicsXG4gICAgICAgIHByb2pSb3RhdGU6IFswLCAwLCAwXVxuICAgIH1cbn07XG5cbi8vIGFuZ3VsYXIgcGFkIHRvIGF2b2lkIHJvdW5kaW5nIGVycm9yIGFyb3VuZCBjbGlwIGFuZ2xlc1xuZXhwb3J0cy5jbGlwUGFkID0gMWUtMztcblxuLy8gbWFwIHByb2plY3Rpb24gcHJlY2lzaW9uXG5leHBvcnRzLnByZWNpc2lvbiA9IDAuMTtcblxuLy8gZGVmYXVsdCBsYW5kIGFuZCB3YXRlciBmaWxsIGNvbG9yc1xuZXhwb3J0cy5sYW5kQ29sb3IgPSAnI0YwREM4Mic7XG5leHBvcnRzLndhdGVyQ29sb3IgPSAnIzMzOTlGRic7XG5cbi8vIGxvY2F0aW9ubW9kZSB0byBsYXllciBuYW1lXG5leHBvcnRzLmxvY2F0aW9ubW9kZVRvTGF5ZXIgPSB7XG4gICAgJ0lTTy0zJzogJ2NvdW50cmllcycsXG4gICAgJ1VTQS1zdGF0ZXMnOiAnc3VidW5pdHMnLFxuICAgICdjb3VudHJ5IG5hbWVzJzogJ2NvdW50cmllcydcbn07XG5cbi8vIFNWRyBlbGVtZW50IGZvciBhIHNwaGVyZSAodXNlIHRvIGZyYW1lIG1hcHMpXG5leHBvcnRzLnNwaGVyZVNWRyA9IHt0eXBlOiAnU3BoZXJlJ307XG5cbi8vIE4uQi4gYmFzZSBsYXllciBuYW1lcyBtdXN0IGJlIHRoZSBzYW1lIGFzIGluIHRoZSB0b3BvanNvbiBmaWxlc1xuXG4vLyBiYXNlIGxheWVyIHdpdGggYSBmaWxsIGNvbG9yXG5leHBvcnRzLmZpbGxMYXllcnMgPSB7XG4gICAgb2NlYW46IDEsXG4gICAgbGFuZDogMSxcbiAgICBsYWtlczogMVxufTtcblxuLy8gYmFzZSBsYXllciB3aXRoIGEgb25seSBhIGxpbmUgY29sb3JcbmV4cG9ydHMubGluZUxheWVycyA9IHtcbiAgICBzdWJ1bml0czogMSxcbiAgICBjb3VudHJpZXM6IDEsXG4gICAgY29hc3RsaW5lczogMSxcbiAgICByaXZlcnM6IDEsXG4gICAgZnJhbWU6IDFcbn07XG5cbmV4cG9ydHMubGF5ZXJzID0gW1xuICAgICdiZycsXG4gICAgJ29jZWFuJywgJ2xhbmQnLCAnbGFrZXMnLFxuICAgICdzdWJ1bml0cycsICdjb3VudHJpZXMnLCAnY29hc3RsaW5lcycsICdyaXZlcnMnLFxuICAgICdsYXRheGlzJywgJ2xvbmF4aXMnLCAnZnJhbWUnLFxuICAgICdiYWNrcGxvdCcsXG4gICAgJ2Zyb250cGxvdCdcbl07XG5cbmV4cG9ydHMubGF5ZXJzRm9yQ2hvcm9wbGV0aCA9IFtcbiAgICAnYmcnLFxuICAgICdvY2VhbicsICdsYW5kJyxcbiAgICAnc3VidW5pdHMnLCAnY291bnRyaWVzJywgJ2NvYXN0bGluZXMnLFxuICAgICdsYXRheGlzJywgJ2xvbmF4aXMnLCAnZnJhbWUnLFxuICAgICdiYWNrcGxvdCcsXG4gICAgJ3JpdmVycycsICdsYWtlcycsXG4gICAgJ2Zyb250cGxvdCdcbl07XG5cbmV4cG9ydHMubGF5ZXJOYW1lVG9BZGplY3RpdmUgPSB7XG4gICAgb2NlYW46ICdvY2VhbicsXG4gICAgbGFuZDogJ2xhbmQnLFxuICAgIGxha2VzOiAnbGFrZScsXG4gICAgc3VidW5pdHM6ICdzdWJ1bml0JyxcbiAgICBjb3VudHJpZXM6ICdjb3VudHJ5JyxcbiAgICBjb2FzdGxpbmVzOiAnY29hc3RsaW5lJyxcbiAgICByaXZlcnM6ICdyaXZlcicsXG4gICAgZnJhbWU6ICdmcmFtZSdcbn07XG5cbn0se31dLDc5NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qIGdsb2JhbCBQbG90bHlHZW9Bc3NldHM6ZmFsc2UgKi9cblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgUGxvdHMgPSBfZGVyZXFfKCcuLi9wbG90cycpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGRyYWdFbGVtZW50ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmFnZWxlbWVudCcpO1xudmFyIHByZXBTZWxlY3QgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vc2VsZWN0JykucHJlcFNlbGVjdDtcbnZhciBzZWxlY3RPbkNsaWNrID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL3NlbGVjdCcpLnNlbGVjdE9uQ2xpY2s7XG5cbnZhciBjcmVhdGVHZW9ab29tID0gX2RlcmVxXygnLi96b29tJyk7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcblxudmFyIHRvcG9qc29uVXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvdG9wb2pzb25fdXRpbHMnKTtcbnZhciB0b3BvanNvbkZlYXR1cmUgPSBfZGVyZXFfKCd0b3BvanNvbi1jbGllbnQnKS5mZWF0dXJlO1xuXG5fZGVyZXFfKCcuL3Byb2plY3Rpb25zJykoZDMpO1xuXG5mdW5jdGlvbiBHZW8ob3B0cykge1xuICAgIHRoaXMuaWQgPSBvcHRzLmlkO1xuICAgIHRoaXMuZ3JhcGhEaXYgPSBvcHRzLmdyYXBoRGl2O1xuICAgIHRoaXMuY29udGFpbmVyID0gb3B0cy5jb250YWluZXI7XG4gICAgdGhpcy50b3BvanNvblVSTCA9IG9wdHMudG9wb2pzb25VUkw7XG4gICAgdGhpcy5pc1N0YXRpYyA9IG9wdHMuc3RhdGljUGxvdDtcblxuICAgIHRoaXMudG9wb2pzb25OYW1lID0gbnVsbDtcbiAgICB0aGlzLnRvcG9qc29uID0gbnVsbDtcblxuICAgIHRoaXMucHJvamVjdGlvbiA9IG51bGw7XG4gICAgdGhpcy5zY29wZSA9IG51bGw7XG4gICAgdGhpcy52aWV3SW5pdGlhbCA9IG51bGw7XG4gICAgdGhpcy5maXRTY2FsZSA9IG51bGw7XG4gICAgdGhpcy5ib3VuZHMgPSBudWxsO1xuICAgIHRoaXMubWlkUHQgPSBudWxsO1xuXG4gICAgdGhpcy5oYXNDaG9yb3BsZXRoID0gZmFsc2U7XG4gICAgdGhpcy50cmFjZUhhc2ggPSB7fTtcblxuICAgIHRoaXMubGF5ZXJzID0ge307XG4gICAgdGhpcy5iYXNlUGF0aHMgPSB7fTtcbiAgICB0aGlzLmRhdGFQYXRocyA9IHt9O1xuICAgIHRoaXMuZGF0YVBvaW50cyA9IHt9O1xuXG4gICAgdGhpcy5jbGlwRGVmID0gbnVsbDtcbiAgICB0aGlzLmNsaXBSZWN0ID0gbnVsbDtcbiAgICB0aGlzLmJnUmVjdCA9IG51bGw7XG5cbiAgICB0aGlzLm1ha2VGcmFtZXdvcmsoKTtcbn1cblxudmFyIHByb3RvID0gR2VvLnByb3RvdHlwZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGVHZW8ob3B0cykge1xuICAgIHJldHVybiBuZXcgR2VvKG9wdHMpO1xufTtcblxucHJvdG8ucGxvdCA9IGZ1bmN0aW9uKGdlb0NhbGNEYXRhLCBmdWxsTGF5b3V0LCBwcm9taXNlcykge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGdlb0xheW91dCA9IGZ1bGxMYXlvdXRbdGhpcy5pZF07XG5cbiAgICB2YXIgbmVlZHNUb3BvanNvbiA9IGZhbHNlO1xuICAgIGZvcih2YXIgayBpbiBjb25zdGFudHMubGF5ZXJOYW1lVG9BZGplY3RpdmUpIHtcbiAgICAgICAgaWYoayAhPT0gJ2ZyYW1lJyAmJiBnZW9MYXlvdXRbJ3Nob3cnICsga10pIHtcbiAgICAgICAgICAgIG5lZWRzVG9wb2pzb24gPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGdlb0NhbGNEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGdlb0NhbGNEYXRhWzBdWzBdLnRyYWNlLmxvY2F0aW9ubW9kZSkge1xuICAgICAgICAgICAgbmVlZHNUb3BvanNvbiA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZighbmVlZHNUb3BvanNvbikge1xuICAgICAgICByZXR1cm4gX3RoaXMudXBkYXRlKGdlb0NhbGNEYXRhLCBmdWxsTGF5b3V0KTtcbiAgICB9XG5cbiAgICB2YXIgdG9wb2pzb25OYW1lTmV3ID0gdG9wb2pzb25VdGlscy5nZXRUb3BvanNvbk5hbWUoZ2VvTGF5b3V0KTtcblxuICAgIGlmKF90aGlzLnRvcG9qc29uID09PSBudWxsIHx8IHRvcG9qc29uTmFtZU5ldyAhPT0gX3RoaXMudG9wb2pzb25OYW1lKSB7XG4gICAgICAgIF90aGlzLnRvcG9qc29uTmFtZSA9IHRvcG9qc29uTmFtZU5ldztcblxuICAgICAgICBpZihQbG90bHlHZW9Bc3NldHMudG9wb2pzb25bX3RoaXMudG9wb2pzb25OYW1lXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKF90aGlzLmZldGNoVG9wb2pzb24oKS50aGVuKGZ1bmN0aW9uKHRvcG9qc29uKSB7XG4gICAgICAgICAgICAgICAgUGxvdGx5R2VvQXNzZXRzLnRvcG9qc29uW190aGlzLnRvcG9qc29uTmFtZV0gPSB0b3BvanNvbjtcbiAgICAgICAgICAgICAgICBfdGhpcy50b3BvanNvbiA9IHRvcG9qc29uO1xuICAgICAgICAgICAgICAgIF90aGlzLnVwZGF0ZShnZW9DYWxjRGF0YSwgZnVsbExheW91dCk7XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBfdGhpcy50b3BvanNvbiA9IFBsb3RseUdlb0Fzc2V0cy50b3BvanNvbltfdGhpcy50b3BvanNvbk5hbWVdO1xuICAgICAgICAgICAgX3RoaXMudXBkYXRlKGdlb0NhbGNEYXRhLCBmdWxsTGF5b3V0KTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIF90aGlzLnVwZGF0ZShnZW9DYWxjRGF0YSwgZnVsbExheW91dCk7XG4gICAgfVxufTtcblxucHJvdG8uZmV0Y2hUb3BvanNvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0b3BvanNvblBhdGggPSB0b3BvanNvblV0aWxzLmdldFRvcG9qc29uUGF0aChcbiAgICAgICAgdGhpcy50b3BvanNvblVSTCxcbiAgICAgICAgdGhpcy50b3BvanNvbk5hbWVcbiAgICApO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZDMuanNvbih0b3BvanNvblBhdGgsIGZ1bmN0aW9uKGVyciwgdG9wb2pzb24pIHtcbiAgICAgICAgICAgIGlmKGVycikge1xuICAgICAgICAgICAgICAgIGlmKGVyci5zdGF0dXMgPT09IDQwNCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihbXG4gICAgICAgICAgICAgICAgICAgICAgICAncGxvdGx5LmpzIGNvdWxkIG5vdCBmaW5kIHRvcG9qc29uIGZpbGUgYXQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdG9wb2pzb25QYXRoLCAnLicsXG4gICAgICAgICAgICAgICAgICAgICAgICAnTWFrZSBzdXJlIHRoZSAqdG9wb2pzb25VUkwqIHBsb3QgY29uZmlnIG9wdGlvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICAnaXMgc2V0IHByb3Blcmx5LidcbiAgICAgICAgICAgICAgICAgICAgXS5qb2luKCcgJykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcihbXG4gICAgICAgICAgICAgICAgICAgICAgICAndW5leHBlY3RlZCBlcnJvciB3aGlsZSBmZXRjaGluZyB0b3BvanNvbiBmaWxlIGF0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcG9qc29uUGF0aFxuICAgICAgICAgICAgICAgICAgICBdLmpvaW4oJyAnKSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc29sdmUodG9wb2pzb24pO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGdlb0NhbGNEYXRhLCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIGdlb0xheW91dCA9IGZ1bGxMYXlvdXRbdGhpcy5pZF07XG5cbiAgICB2YXIgaGFzSW52YWxpZEJvdW5kcyA9IHRoaXMudXBkYXRlUHJvamVjdGlvbihmdWxsTGF5b3V0LCBnZW9MYXlvdXQpO1xuICAgIGlmKGhhc0ludmFsaWRCb3VuZHMpIHJldHVybjtcblxuICAgIC8vIGltcG9ydGFudDogbWFwcyB3aXRoIGNob3JvcGxldGggdHJhY2VzIGhhdmUgYSBkaWZmZXJlbnQgbGF5ZXIgb3JkZXJcbiAgICB0aGlzLmhhc0Nob3JvcGxldGggPSBmYWxzZTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZ2VvQ2FsY0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoZ2VvQ2FsY0RhdGFbaV1bMF0udHJhY2UudHlwZSA9PT0gJ2Nob3JvcGxldGgnKSB7XG4gICAgICAgICAgICB0aGlzLmhhc0Nob3JvcGxldGggPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZighdGhpcy52aWV3SW5pdGlhbCB8fCB0aGlzLnNjb3BlICE9PSBnZW9MYXlvdXQuc2NvcGUpIHtcbiAgICAgICAgdGhpcy5zYXZlVmlld0luaXRpYWwoZ2VvTGF5b3V0KTtcbiAgICB9XG4gICAgdGhpcy5zY29wZSA9IGdlb0xheW91dC5zY29wZTtcblxuICAgIHRoaXMudXBkYXRlQmFzZUxheWVycyhmdWxsTGF5b3V0LCBnZW9MYXlvdXQpO1xuICAgIHRoaXMudXBkYXRlRGltcyhmdWxsTGF5b3V0LCBnZW9MYXlvdXQpO1xuICAgIHRoaXMudXBkYXRlRngoZnVsbExheW91dCwgZ2VvTGF5b3V0KTtcblxuICAgIFBsb3RzLmdlbmVyYWxVcGRhdGVQZXJUcmFjZU1vZHVsZSh0aGlzLmdyYXBoRGl2LCB0aGlzLCBnZW9DYWxjRGF0YSwgZ2VvTGF5b3V0KTtcblxuICAgIHZhciBzY2F0dGVyTGF5ZXIgPSB0aGlzLmxheWVycy5mcm9udHBsb3Quc2VsZWN0KCcuc2NhdHRlcmxheWVyJyk7XG4gICAgdGhpcy5kYXRhUG9pbnRzLnBvaW50ID0gc2NhdHRlckxheWVyLnNlbGVjdEFsbCgnLnBvaW50Jyk7XG4gICAgdGhpcy5kYXRhUG9pbnRzLnRleHQgPSBzY2F0dGVyTGF5ZXIuc2VsZWN0QWxsKCd0ZXh0Jyk7XG4gICAgdGhpcy5kYXRhUGF0aHMubGluZSA9IHNjYXR0ZXJMYXllci5zZWxlY3RBbGwoJy5qcy1saW5lJyk7XG5cbiAgICB2YXIgY2hvcm9wbGV0aExheWVyID0gdGhpcy5sYXllcnMuYmFja3Bsb3Quc2VsZWN0KCcuY2hvcm9wbGV0aGxheWVyJyk7XG4gICAgdGhpcy5kYXRhUGF0aHMuY2hvcm9wbGV0aCA9IGNob3JvcGxldGhMYXllci5zZWxlY3RBbGwoJ3BhdGgnKTtcblxuICAgIHRoaXMucmVuZGVyKCk7XG59O1xuXG5wcm90by51cGRhdGVQcm9qZWN0aW9uID0gZnVuY3Rpb24oZnVsbExheW91dCwgZ2VvTGF5b3V0KSB7XG4gICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICB2YXIgZG9tYWluID0gZ2VvTGF5b3V0LmRvbWFpbjtcbiAgICB2YXIgcHJvakxheW91dCA9IGdlb0xheW91dC5wcm9qZWN0aW9uO1xuICAgIHZhciByb3RhdGlvbiA9IHByb2pMYXlvdXQucm90YXRpb24gfHwge307XG4gICAgdmFyIGNlbnRlciA9IGdlb0xheW91dC5jZW50ZXIgfHwge307XG5cbiAgICB2YXIgcHJvamVjdGlvbiA9IHRoaXMucHJvamVjdGlvbiA9IGdldFByb2plY3Rpb24oZ2VvTGF5b3V0KTtcblxuICAgIC8vIHNldCAncHJlLWZpdCcgcHJvamVjdGlvblxuICAgIHByb2plY3Rpb25cbiAgICAgICAgLmNlbnRlcihbY2VudGVyLmxvbiAtIHJvdGF0aW9uLmxvbiwgY2VudGVyLmxhdCAtIHJvdGF0aW9uLmxhdF0pXG4gICAgICAgIC5yb3RhdGUoWy1yb3RhdGlvbi5sb24sIC1yb3RhdGlvbi5sYXQsIHJvdGF0aW9uLnJvbGxdKVxuICAgICAgICAucGFyYWxsZWxzKHByb2pMYXlvdXQucGFyYWxsZWxzKTtcblxuICAgIC8vIHNldHVwIHN1YnBsb3QgZXh0ZW50IFtbeDAseTBdLCBbeDEseTFdXVxuICAgIHZhciBleHRlbnQgPSBbW1xuICAgICAgICBncy5sICsgZ3MudyAqIGRvbWFpbi54WzBdLFxuICAgICAgICBncy50ICsgZ3MuaCAqICgxIC0gZG9tYWluLnlbMV0pXG4gICAgXSwgW1xuICAgICAgICBncy5sICsgZ3MudyAqIGRvbWFpbi54WzFdLFxuICAgICAgICBncy50ICsgZ3MuaCAqICgxIC0gZG9tYWluLnlbMF0pXG4gICAgXV07XG5cbiAgICB2YXIgbG9uYXhpcyA9IGdlb0xheW91dC5sb25heGlzO1xuICAgIHZhciBsYXRheGlzID0gZ2VvTGF5b3V0LmxhdGF4aXM7XG4gICAgdmFyIHJhbmdlQm94ID0gbWFrZVJhbmdlQm94KGxvbmF4aXMucmFuZ2UsIGxhdGF4aXMucmFuZ2UpO1xuXG4gICAgLy8gZml0IHByb2plY3Rpb24gJ3NjYWxlJyBhbmQgJ3RyYW5zbGF0ZScgdG8gc2V0IGxvbi9sYXQgcmFuZ2VzXG4gICAgcHJvamVjdGlvbi5maXRFeHRlbnQoZXh0ZW50LCByYW5nZUJveCk7XG5cbiAgICB2YXIgYiA9IHRoaXMuYm91bmRzID0gcHJvamVjdGlvbi5nZXRCb3VuZHMocmFuZ2VCb3gpO1xuICAgIHZhciBzID0gdGhpcy5maXRTY2FsZSA9IHByb2plY3Rpb24uc2NhbGUoKTtcbiAgICB2YXIgdCA9IHByb2plY3Rpb24udHJhbnNsYXRlKCk7XG5cbiAgICBpZihcbiAgICAgICAgIWlzRmluaXRlKGJbMF1bMF0pIHx8ICFpc0Zpbml0ZShiWzBdWzFdKSB8fFxuICAgICAgICAhaXNGaW5pdGUoYlsxXVswXSkgfHwgIWlzRmluaXRlKGJbMV1bMV0pIHx8XG4gICAgICAgIGlzTmFOKHRbMF0pIHx8IGlzTmFOKHRbMF0pXG4gICAgKSB7XG4gICAgICAgIHZhciBnZCA9IHRoaXMuZ3JhcGhEaXY7XG4gICAgICAgIHZhciBhdHRyVG9VbnNldCA9IFsncHJvamVjdGlvbi5yb3RhdGlvbicsICdjZW50ZXInLCAnbG9uYXhpcy5yYW5nZScsICdsYXRheGlzLnJhbmdlJ107XG4gICAgICAgIHZhciBtc2cgPSAnSW52YWxpZCBnZW8gc2V0dGluZ3MsIHJlbGF5b3V0XFwnaW5nIHRvIGRlZmF1bHQgdmlldy4nO1xuICAgICAgICB2YXIgdXBkYXRlT2JqID0ge307XG5cbiAgICAgICAgLy8gY2xlYXIgYWxsIGF0dHJpYnV0ZSB0aGF0IGNvdWxkIGNhdXNlIGludmFsaWQgYm91bmRzLFxuICAgICAgICAvLyBjbGVhciB2aWV3SW5pdGlhbCB0byB1cGRhdGUgcmVzZXQtdmlldyBiZWhhdmlvclxuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhdHRyVG9VbnNldC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdXBkYXRlT2JqW3RoaXMuaWQgKyAnLicgKyBhdHRyVG9VbnNldFtpXV0gPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy52aWV3SW5pdGlhbCA9IG51bGw7XG5cbiAgICAgICAgTGliLndhcm4obXNnKTtcbiAgICAgICAgZ2QuX3Byb21pc2VzLnB1c2goUmVnaXN0cnkuY2FsbCgncmVsYXlvdXQnLCBnZCwgdXBkYXRlT2JqKSk7XG4gICAgICAgIHJldHVybiBtc2c7XG4gICAgfVxuXG4gICAgLy8gcHggY29vcmRpbmF0ZXMgb2YgdmlldyBtaWQtcG9pbnQsXG4gICAgLy8gdXNlZnVsIHRvIHVwZGF0ZSBgZ2VvLmNlbnRlcmAgYWZ0ZXIgaW50ZXJhY3Rpb25zXG4gICAgdmFyIG1pZFB0ID0gdGhpcy5taWRQdCA9IFtcbiAgICAgICAgKGJbMF1bMF0gKyBiWzFdWzBdKSAvIDIsXG4gICAgICAgIChiWzBdWzFdICsgYlsxXVsxXSkgLyAyXG4gICAgXTtcblxuICAgIC8vIGFkanVzdCBwcm9qZWN0aW9uIHRvIHVzZXIgc2V0dGluZ1xuICAgIHByb2plY3Rpb25cbiAgICAgICAgLnNjYWxlKHByb2pMYXlvdXQuc2NhbGUgKiBzKVxuICAgICAgICAudHJhbnNsYXRlKFt0WzBdICsgKG1pZFB0WzBdIC0gdFswXSksIHRbMV0gKyAobWlkUHRbMV0gLSB0WzFdKV0pXG4gICAgICAgIC5jbGlwRXh0ZW50KGIpO1xuXG4gICAgLy8gdGhlICdhbGJlcnMgdXNhJyBwcm9qZWN0aW9uIGRvZXMgbm90IGV4cG9zZSBhICdjZW50ZXInIG1ldGhvZFxuICAgIC8vIHNvIGhlcmUncyB0aGlzIGhhY2sgdG8gbWFrZSBpdCByZXNwb25kIHRvICdnZW9MYXlvdXQuY2VudGVyJ1xuICAgIGlmKGdlb0xheW91dC5faXNBbGJlcnNVc2EpIHtcbiAgICAgICAgdmFyIGNlbnRlclB4ID0gcHJvamVjdGlvbihbY2VudGVyLmxvbiwgY2VudGVyLmxhdF0pO1xuICAgICAgICB2YXIgdHQgPSBwcm9qZWN0aW9uLnRyYW5zbGF0ZSgpO1xuXG4gICAgICAgIHByb2plY3Rpb24udHJhbnNsYXRlKFtcbiAgICAgICAgICAgIHR0WzBdIC0gKGNlbnRlclB4WzBdIC0gdHRbMF0pLFxuICAgICAgICAgICAgdHRbMV0gLSAoY2VudGVyUHhbMV0gLSB0dFsxXSlcbiAgICAgICAgXSk7XG4gICAgfVxufTtcblxucHJvdG8udXBkYXRlQmFzZUxheWVycyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIGdlb0xheW91dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIHRvcG9qc29uID0gX3RoaXMudG9wb2pzb247XG4gICAgdmFyIGxheWVycyA9IF90aGlzLmxheWVycztcbiAgICB2YXIgYmFzZVBhdGhzID0gX3RoaXMuYmFzZVBhdGhzO1xuXG4gICAgZnVuY3Rpb24gaXNBeGlzTGF5ZXIoZCkge1xuICAgICAgICByZXR1cm4gKGQgPT09ICdsb25heGlzJyB8fCBkID09PSAnbGF0YXhpcycpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzTGluZUxheWVyKGQpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4oY29uc3RhbnRzLmxpbmVMYXllcnNbZF0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzRmlsbExheWVyKGQpIHtcbiAgICAgICAgcmV0dXJuIEJvb2xlYW4oY29uc3RhbnRzLmZpbGxMYXllcnNbZF0pO1xuICAgIH1cblxuICAgIHZhciBhbGxMYXllcnMgPSB0aGlzLmhhc0Nob3JvcGxldGggP1xuICAgICAgICBjb25zdGFudHMubGF5ZXJzRm9yQ2hvcm9wbGV0aCA6XG4gICAgICAgIGNvbnN0YW50cy5sYXllcnM7XG5cbiAgICB2YXIgbGF5ZXJEYXRhID0gYWxsTGF5ZXJzLmZpbHRlcihmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiAoaXNMaW5lTGF5ZXIoZCkgfHwgaXNGaWxsTGF5ZXIoZCkpID8gZ2VvTGF5b3V0WydzaG93JyArIGRdIDpcbiAgICAgICAgICAgIGlzQXhpc0xheWVyKGQpID8gZ2VvTGF5b3V0W2RdLnNob3dncmlkIDpcbiAgICAgICAgICAgIHRydWU7XG4gICAgfSk7XG5cbiAgICB2YXIgam9pbiA9IF90aGlzLmZyYW1ld29yay5zZWxlY3RBbGwoJy5sYXllcicpXG4gICAgICAgIC5kYXRhKGxheWVyRGF0YSwgU3RyaW5nKTtcblxuICAgIGpvaW4uZXhpdCgpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICBkZWxldGUgbGF5ZXJzW2RdO1xuICAgICAgICBkZWxldGUgYmFzZVBhdGhzW2RdO1xuICAgICAgICBkMy5zZWxlY3QodGhpcykucmVtb3ZlKCk7XG4gICAgfSk7XG5cbiAgICBqb2luLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgZnVuY3Rpb24oZCkgeyByZXR1cm4gJ2xheWVyICcgKyBkOyB9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgbGF5ZXIgPSBsYXllcnNbZF0gPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgICAgIGlmKGQgPT09ICdiZycpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5iZ1JlY3QgPSBsYXllci5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGlzQXhpc0xheWVyKGQpKSB7XG4gICAgICAgICAgICAgICAgYmFzZVBhdGhzW2RdID0gbGF5ZXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgJ25vbmUnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihkID09PSAnYmFja3Bsb3QnKSB7XG4gICAgICAgICAgICAgICAgbGF5ZXIuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ2Nob3JvcGxldGhsYXllcicsIHRydWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGQgPT09ICdmcm9udHBsb3QnKSB7XG4gICAgICAgICAgICAgICAgbGF5ZXIuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3NjYXR0ZXJsYXllcicsIHRydWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGlzTGluZUxheWVyKGQpKSB7XG4gICAgICAgICAgICAgICAgYmFzZVBhdGhzW2RdID0gbGF5ZXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgJ25vbmUnKVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMik7XG4gICAgICAgICAgICB9IGVsc2UgaWYoaXNGaWxsTGF5ZXIoZCkpIHtcbiAgICAgICAgICAgICAgICBiYXNlUGF0aHNbZF0gPSBsYXllci5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZScsICdub25lJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgam9pbi5vcmRlcigpO1xuXG4gICAgam9pbi5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHBhdGggPSBiYXNlUGF0aHNbZF07XG4gICAgICAgIHZhciBhZGogPSBjb25zdGFudHMubGF5ZXJOYW1lVG9BZGplY3RpdmVbZF07XG5cbiAgICAgICAgaWYoZCA9PT0gJ2ZyYW1lJykge1xuICAgICAgICAgICAgcGF0aC5kYXR1bShjb25zdGFudHMuc3BoZXJlU1ZHKTtcbiAgICAgICAgfSBlbHNlIGlmKGlzTGluZUxheWVyKGQpIHx8IGlzRmlsbExheWVyKGQpKSB7XG4gICAgICAgICAgICBwYXRoLmRhdHVtKHRvcG9qc29uRmVhdHVyZSh0b3BvanNvbiwgdG9wb2pzb24ub2JqZWN0c1tkXSkpO1xuICAgICAgICB9IGVsc2UgaWYoaXNBeGlzTGF5ZXIoZCkpIHtcbiAgICAgICAgICAgIHBhdGguZGF0dW0obWFrZUdyYXRpY3VsZShkLCBnZW9MYXlvdXQsIGZ1bGxMYXlvdXQpKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgZ2VvTGF5b3V0W2RdLmdyaWRjb2xvcilcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmRhc2hMaW5lLCAnJywgZ2VvTGF5b3V0W2RdLmdyaWR3aWR0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihpc0xpbmVMYXllcihkKSkge1xuICAgICAgICAgICAgcGF0aC5jYWxsKENvbG9yLnN0cm9rZSwgZ2VvTGF5b3V0W2FkaiArICdjb2xvciddKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZGFzaExpbmUsICcnLCBnZW9MYXlvdXRbYWRqICsgJ3dpZHRoJ10pO1xuICAgICAgICB9IGVsc2UgaWYoaXNGaWxsTGF5ZXIoZCkpIHtcbiAgICAgICAgICAgIHBhdGguY2FsbChDb2xvci5maWxsLCBnZW9MYXlvdXRbYWRqICsgJ2NvbG9yJ10pO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5wcm90by51cGRhdGVEaW1zID0gZnVuY3Rpb24oZnVsbExheW91dCwgZ2VvTGF5b3V0KSB7XG4gICAgdmFyIGIgPSB0aGlzLmJvdW5kcztcbiAgICB2YXIgaEZyYW1lV2lkdGggPSAoZ2VvTGF5b3V0LmZyYW1ld2lkdGggfHwgMCkgLyAyO1xuXG4gICAgdmFyIGwgPSBiWzBdWzBdIC0gaEZyYW1lV2lkdGg7XG4gICAgdmFyIHQgPSBiWzBdWzFdIC0gaEZyYW1lV2lkdGg7XG4gICAgdmFyIHcgPSBiWzFdWzBdIC0gbCArIGhGcmFtZVdpZHRoO1xuICAgIHZhciBoID0gYlsxXVsxXSAtIHQgKyBoRnJhbWVXaWR0aDtcblxuICAgIERyYXdpbmcuc2V0UmVjdCh0aGlzLmNsaXBSZWN0LCBsLCB0LCB3LCBoKTtcblxuICAgIHRoaXMuYmdSZWN0XG4gICAgICAgIC5jYWxsKERyYXdpbmcuc2V0UmVjdCwgbCwgdCwgdywgaClcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgZ2VvTGF5b3V0LmJnY29sb3IpO1xuXG4gICAgdGhpcy54YXhpcy5fb2Zmc2V0ID0gbDtcbiAgICB0aGlzLnhheGlzLl9sZW5ndGggPSB3O1xuXG4gICAgdGhpcy55YXhpcy5fb2Zmc2V0ID0gdDtcbiAgICB0aGlzLnlheGlzLl9sZW5ndGggPSBoO1xufTtcblxucHJvdG8udXBkYXRlRnggPSBmdW5jdGlvbihmdWxsTGF5b3V0LCBnZW9MYXlvdXQpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBnZCA9IF90aGlzLmdyYXBoRGl2O1xuICAgIHZhciBiZ1JlY3QgPSBfdGhpcy5iZ1JlY3Q7XG4gICAgdmFyIGRyYWdNb2RlID0gZnVsbExheW91dC5kcmFnbW9kZTtcbiAgICB2YXIgY2xpY2tNb2RlID0gZnVsbExheW91dC5jbGlja21vZGU7XG5cbiAgICBpZihfdGhpcy5pc1N0YXRpYykgcmV0dXJuO1xuXG4gICAgZnVuY3Rpb24gem9vbVJlc2V0KCkge1xuICAgICAgICB2YXIgdmlld0luaXRpYWwgPSBfdGhpcy52aWV3SW5pdGlhbDtcbiAgICAgICAgdmFyIHVwZGF0ZU9iaiA9IHt9O1xuXG4gICAgICAgIGZvcih2YXIgayBpbiB2aWV3SW5pdGlhbCkge1xuICAgICAgICAgICAgdXBkYXRlT2JqW190aGlzLmlkICsgJy4nICsga10gPSB2aWV3SW5pdGlhbFtrXTtcbiAgICAgICAgfVxuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCB1cGRhdGVPYmopO1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfZG91YmxlY2xpY2snLCBudWxsKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnZlcnQobG9ubGF0KSB7XG4gICAgICAgIHJldHVybiBfdGhpcy5wcm9qZWN0aW9uLmludmVydChbXG4gICAgICAgICAgICBsb25sYXRbMF0gKyBfdGhpcy54YXhpcy5fb2Zmc2V0LFxuICAgICAgICAgICAgbG9ubGF0WzFdICsgX3RoaXMueWF4aXMuX29mZnNldFxuICAgICAgICBdKTtcbiAgICB9XG5cbiAgICB2YXIgZmlsbFJhbmdlSXRlbXM7XG5cbiAgICBpZihkcmFnTW9kZSA9PT0gJ3NlbGVjdCcpIHtcbiAgICAgICAgZmlsbFJhbmdlSXRlbXMgPSBmdW5jdGlvbihldmVudERhdGEsIHBvbHkpIHtcbiAgICAgICAgICAgIHZhciByYW5nZXMgPSBldmVudERhdGEucmFuZ2UgPSB7fTtcbiAgICAgICAgICAgIHJhbmdlc1tfdGhpcy5pZF0gPSBbXG4gICAgICAgICAgICAgICAgaW52ZXJ0KFtwb2x5LnhtaW4sIHBvbHkueW1pbl0pLFxuICAgICAgICAgICAgICAgIGludmVydChbcG9seS54bWF4LCBwb2x5LnltYXhdKVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYoZHJhZ01vZGUgPT09ICdsYXNzbycpIHtcbiAgICAgICAgZmlsbFJhbmdlSXRlbXMgPSBmdW5jdGlvbihldmVudERhdGEsIHBvbHksIHB0cykge1xuICAgICAgICAgICAgdmFyIGRhdGFQdHMgPSBldmVudERhdGEubGFzc29Qb2ludHMgPSB7fTtcbiAgICAgICAgICAgIGRhdGFQdHNbX3RoaXMuaWRdID0gcHRzLmZpbHRlcmVkLm1hcChpbnZlcnQpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIE5vdGU6IGRyYWdPcHRpb25zIGlzIG5lZWRlZCB0byBiZSBkZWNsYXJlZCBmb3IgYWxsIGRyYWdtb2RlcyBiZWNhdXNlXG4gICAgLy8gaXQncyB0aGUgb2JqZWN0IHRoYXQgaG9sZHMgcGVyc2lzdGVudCBzZWxlY3Rpb24gc3RhdGUuXG4gICAgdmFyIGRyYWdPcHRpb25zID0ge1xuICAgICAgICBlbGVtZW50OiBfdGhpcy5iZ1JlY3Qubm9kZSgpLFxuICAgICAgICBnZDogZ2QsXG4gICAgICAgIHBsb3RpbmZvOiB7XG4gICAgICAgICAgICBpZDogX3RoaXMuaWQsXG4gICAgICAgICAgICB4YXhpczogX3RoaXMueGF4aXMsXG4gICAgICAgICAgICB5YXhpczogX3RoaXMueWF4aXMsXG4gICAgICAgICAgICBmaWxsUmFuZ2VJdGVtczogZmlsbFJhbmdlSXRlbXNcbiAgICAgICAgfSxcbiAgICAgICAgeGF4ZXM6IFtfdGhpcy54YXhpc10sXG4gICAgICAgIHlheGVzOiBbX3RoaXMueWF4aXNdLFxuICAgICAgICBzdWJwbG90OiBfdGhpcy5pZCxcbiAgICAgICAgY2xpY2tGbjogZnVuY3Rpb24obnVtQ2xpY2tzKSB7XG4gICAgICAgICAgICBpZihudW1DbGlja3MgPT09IDIpIHtcbiAgICAgICAgICAgICAgICBmdWxsTGF5b3V0Ll96b29tbGF5ZXIuc2VsZWN0QWxsKCcuc2VsZWN0LW91dGxpbmUnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZihkcmFnTW9kZSA9PT0gJ3BhbicpIHtcbiAgICAgICAgYmdSZWN0Lm5vZGUoKS5vbm1vdXNlZG93biA9IG51bGw7XG4gICAgICAgIGJnUmVjdC5jYWxsKGNyZWF0ZUdlb1pvb20oX3RoaXMsIGdlb0xheW91dCkpO1xuICAgICAgICBiZ1JlY3Qub24oJ2RibGNsaWNrLnpvb20nLCB6b29tUmVzZXQpO1xuICAgICAgICBpZighZ2QuX2NvbnRleHQuX3Njcm9sbFpvb20uZ2VvKSB7XG4gICAgICAgICAgICBiZ1JlY3Qub24oJ3doZWVsLnpvb20nLCBudWxsKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZihkcmFnTW9kZSA9PT0gJ3NlbGVjdCcgfHwgZHJhZ01vZGUgPT09ICdsYXNzbycpIHtcbiAgICAgICAgYmdSZWN0Lm9uKCcuem9vbScsIG51bGwpO1xuXG4gICAgICAgIGRyYWdPcHRpb25zLnByZXBGbiA9IGZ1bmN0aW9uKGUsIHN0YXJ0WCwgc3RhcnRZKSB7XG4gICAgICAgICAgICBwcmVwU2VsZWN0KGUsIHN0YXJ0WCwgc3RhcnRZLCBkcmFnT3B0aW9ucywgZHJhZ01vZGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGRyYWdFbGVtZW50LmluaXQoZHJhZ09wdGlvbnMpO1xuICAgIH1cblxuICAgIGJnUmVjdC5vbignbW91c2Vtb3ZlJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBsb25sYXQgPSBfdGhpcy5wcm9qZWN0aW9uLmludmVydChkMy5tb3VzZSh0aGlzKSk7XG5cbiAgICAgICAgaWYoIWxvbmxhdCB8fCBpc05hTihsb25sYXRbMF0pIHx8IGlzTmFOKGxvbmxhdFsxXSkpIHtcbiAgICAgICAgICAgIHJldHVybiBkcmFnRWxlbWVudC51bmhvdmVyKGdkLCBkMy5ldmVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBfdGhpcy54YXhpcy5wMmMgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGxvbmxhdFswXTsgfTtcbiAgICAgICAgX3RoaXMueWF4aXMucDJjID0gZnVuY3Rpb24oKSB7IHJldHVybiBsb25sYXRbMV07IH07XG5cbiAgICAgICAgRnguaG92ZXIoZ2QsIGQzLmV2ZW50LCBfdGhpcy5pZCk7XG4gICAgfSk7XG5cbiAgICBiZ1JlY3Qub24oJ21vdXNlb3V0JywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmKGdkLl9kcmFnZ2luZykgcmV0dXJuO1xuICAgICAgICBkcmFnRWxlbWVudC51bmhvdmVyKGdkLCBkMy5ldmVudCk7XG4gICAgfSk7XG5cbiAgICBiZ1JlY3Qub24oJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIC8vIEZvciBzZWxlY3QgYW5kIGxhc3NvIHRoZSBkcmFnRWxlbWVudCBpcyBoYW5kbGluZyBjbGlja3NcbiAgICAgICAgaWYoZHJhZ01vZGUgIT09ICdzZWxlY3QnICYmIGRyYWdNb2RlICE9PSAnbGFzc28nKSB7XG4gICAgICAgICAgICBpZihjbGlja01vZGUuaW5kZXhPZignc2VsZWN0JykgPiAtMSkge1xuICAgICAgICAgICAgICAgIHNlbGVjdE9uQ2xpY2soZDMuZXZlbnQsIGdkLCBbX3RoaXMueGF4aXNdLCBbX3RoaXMueWF4aXNdLFxuICAgICAgICAgICAgICAgICAgX3RoaXMuaWQsIGRyYWdPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoY2xpY2tNb2RlLmluZGV4T2YoJ2V2ZW50JykgPiAtMSkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IGxpa2UgcGllIGFuZCBtYXBib3gsIHRoaXMgZG9lc24ndCBzdXBwb3J0IHJpZ2h0LWNsaWNrXG4gICAgICAgICAgICAgICAgLy8gYWN0dWFsbHkgdGhpcyBvbmUgaXMgd29yc2UsIGFzIHJpZ2h0LWNsaWNrIHN0YXJ0cyBhIHBhbiwgb3IgbGVhdmVzXG4gICAgICAgICAgICAgICAgLy8gc2VsZWN0IGluIGEgd2VpcmQgc3RhdGUuXG4gICAgICAgICAgICAgICAgLy8gQWxzbywgb25seSB0YW5nZW50aWFsbHkgcmVsYXRlZCwgd2Ugc2hvdWxkIGNhbmNlbCBob3ZlciBkdXJpbmcgcGFuXG4gICAgICAgICAgICAgICAgRnguY2xpY2soZ2QsIGQzLmV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xufTtcblxucHJvdG8ubWFrZUZyYW1ld29yayA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGdkID0gX3RoaXMuZ3JhcGhEaXY7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2xpcElkID0gJ2NsaXAnICsgZnVsbExheW91dC5fdWlkICsgX3RoaXMuaWQ7XG5cbiAgICBfdGhpcy5jbGlwRGVmID0gZnVsbExheW91dC5fY2xpcHMuYXBwZW5kKCdjbGlwUGF0aCcpXG4gICAgICAgIC5hdHRyKCdpZCcsIGNsaXBJZCk7XG5cbiAgICBfdGhpcy5jbGlwUmVjdCA9IF90aGlzLmNsaXBEZWYuYXBwZW5kKCdyZWN0Jyk7XG5cbiAgICBfdGhpcy5mcmFtZXdvcmsgPSBkMy5zZWxlY3QoX3RoaXMuY29udGFpbmVyKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnZ2VvICcgKyBfdGhpcy5pZClcbiAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRDbGlwVXJsLCBjbGlwSWQsIGdkKTtcblxuICAgIC8vIHNhbmUgbG9ubGF0IHRvIHB4XG4gICAgX3RoaXMucHJvamVjdCA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgdmFyIHB4ID0gX3RoaXMucHJvamVjdGlvbih2KTtcbiAgICAgICAgcmV0dXJuIHB4ID9cbiAgICAgICAgICAgIFtweFswXSAtIF90aGlzLnhheGlzLl9vZmZzZXQsIHB4WzFdIC0gX3RoaXMueWF4aXMuX29mZnNldF0gOlxuICAgICAgICAgICAgW251bGwsIG51bGxdO1xuICAgIH07XG5cbiAgICBfdGhpcy54YXhpcyA9IHtcbiAgICAgICAgX2lkOiAneCcsXG4gICAgICAgIGMycDogZnVuY3Rpb24odikgeyByZXR1cm4gX3RoaXMucHJvamVjdCh2KVswXTsgfVxuICAgIH07XG5cbiAgICBfdGhpcy55YXhpcyA9IHtcbiAgICAgICAgX2lkOiAneScsXG4gICAgICAgIGMycDogZnVuY3Rpb24odikgeyByZXR1cm4gX3RoaXMucHJvamVjdCh2KVsxXTsgfVxuICAgIH07XG5cbiAgICAvLyBtb2NrIGF4aXMgZm9yIGhvdmVyIGZvcm1hdHRpbmdcbiAgICBfdGhpcy5tb2NrQXhpcyA9IHtcbiAgICAgICAgdHlwZTogJ2xpbmVhcicsXG4gICAgICAgIHNob3dleHBvbmVudDogJ2FsbCcsXG4gICAgICAgIGV4cG9uZW50Zm9ybWF0OiAnQidcbiAgICB9O1xuICAgIEF4ZXMuc2V0Q29udmVydChfdGhpcy5tb2NrQXhpcywgZnVsbExheW91dCk7XG59O1xuXG5wcm90by5zYXZlVmlld0luaXRpYWwgPSBmdW5jdGlvbihnZW9MYXlvdXQpIHtcbiAgICB2YXIgY2VudGVyID0gZ2VvTGF5b3V0LmNlbnRlciB8fCB7fTtcbiAgICB2YXIgcHJvakxheW91dCA9IGdlb0xheW91dC5wcm9qZWN0aW9uO1xuICAgIHZhciByb3RhdGlvbiA9IHByb2pMYXlvdXQucm90YXRpb24gfHwge307XG5cbiAgICBpZihnZW9MYXlvdXQuX2lzU2NvcGVkKSB7XG4gICAgICAgIHRoaXMudmlld0luaXRpYWwgPSB7XG4gICAgICAgICAgICAnY2VudGVyLmxvbic6IGNlbnRlci5sb24sXG4gICAgICAgICAgICAnY2VudGVyLmxhdCc6IGNlbnRlci5sYXQsXG4gICAgICAgICAgICAncHJvamVjdGlvbi5zY2FsZSc6IHByb2pMYXlvdXQuc2NhbGVcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYoZ2VvTGF5b3V0Ll9pc0NsaXBwZWQpIHtcbiAgICAgICAgdGhpcy52aWV3SW5pdGlhbCA9IHtcbiAgICAgICAgICAgICdwcm9qZWN0aW9uLnNjYWxlJzogcHJvakxheW91dC5zY2FsZSxcbiAgICAgICAgICAgICdwcm9qZWN0aW9uLnJvdGF0aW9uLmxvbic6IHJvdGF0aW9uLmxvbixcbiAgICAgICAgICAgICdwcm9qZWN0aW9uLnJvdGF0aW9uLmxhdCc6IHJvdGF0aW9uLmxhdFxuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMudmlld0luaXRpYWwgPSB7XG4gICAgICAgICAgICAnY2VudGVyLmxvbic6IGNlbnRlci5sb24sXG4gICAgICAgICAgICAnY2VudGVyLmxhdCc6IGNlbnRlci5sYXQsXG4gICAgICAgICAgICAncHJvamVjdGlvbi5zY2FsZSc6IHByb2pMYXlvdXQuc2NhbGUsXG4gICAgICAgICAgICAncHJvamVjdGlvbi5yb3RhdGlvbi5sb24nOiByb3RhdGlvbi5sb25cbiAgICAgICAgfTtcbiAgICB9XG59O1xuXG4vLyBbaG90IGNvZGUgcGF0aF0gKHJlKWRyYXcgYWxsIHBhdGhzIHdoaWNoIGRlcGVuZCBvbiB0aGUgcHJvamVjdGlvblxucHJvdG8ucmVuZGVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHByb2plY3Rpb24gPSB0aGlzLnByb2plY3Rpb247XG4gICAgdmFyIHBhdGhGbiA9IHByb2plY3Rpb24uZ2V0UGF0aCgpO1xuICAgIHZhciBrO1xuXG4gICAgZnVuY3Rpb24gdHJhbnNsYXRlUG9pbnRzKGQpIHtcbiAgICAgICAgdmFyIGxvbmxhdFB4ID0gcHJvamVjdGlvbihkLmxvbmxhdCk7XG4gICAgICAgIHJldHVybiBsb25sYXRQeCA/XG4gICAgICAgICAgICAndHJhbnNsYXRlKCcgKyBsb25sYXRQeFswXSArICcsJyArIGxvbmxhdFB4WzFdICsgJyknIDpcbiAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhpZGVTaG93UG9pbnRzKGQpIHtcbiAgICAgICAgcmV0dXJuIHByb2plY3Rpb24uaXNMb25MYXRPdmVyRWRnZXMoZC5sb25sYXQpID8gJ25vbmUnIDogbnVsbDtcbiAgICB9XG5cbiAgICBmb3IoayBpbiB0aGlzLmJhc2VQYXRocykge1xuICAgICAgICB0aGlzLmJhc2VQYXRoc1trXS5hdHRyKCdkJywgcGF0aEZuKTtcbiAgICB9XG5cbiAgICBmb3IoayBpbiB0aGlzLmRhdGFQYXRocykge1xuICAgICAgICB0aGlzLmRhdGFQYXRoc1trXS5hdHRyKCdkJywgZnVuY3Rpb24oZCkgeyByZXR1cm4gcGF0aEZuKGQuZ2VvanNvbik7IH0pO1xuICAgIH1cblxuICAgIGZvcihrIGluIHRoaXMuZGF0YVBvaW50cykge1xuICAgICAgICB0aGlzLmRhdGFQb2ludHNba11cbiAgICAgICAgICAgIC5hdHRyKCdkaXNwbGF5JywgaGlkZVNob3dQb2ludHMpXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgdHJhbnNsYXRlUG9pbnRzKTtcbiAgICB9XG59O1xuXG4vLyBIZWxwZXIgdGhhdCB3cmFwcyBkMy5nZW9bLyogcHJvamVjdGlvbiBuYW1lIC8qXSgpIHdoaWNoOlxuLy9cbi8vIC0gYWRkcyAnZml0RXh0ZW50JyAoYXZhaWxhYmxlIGluIGQzIHY0KVxuLy8gLSBhZGRzICdnZXRQYXRoJywgJ2dldEJvdW5kcycgY29udmVuaWVuY2UgbWV0aG9kc1xuLy8gLSBzY29wZXMgbG9naWMgcmVsYXRlZCB0byAnY2xpcEFuZ2xlJ1xuLy8gLSBhZGRzICdpc0xvbkxhdE92ZXJFZGdlcycgbWV0aG9kXG4vLyAtIHNldHMgcHJvamVjdGlvbiBwcmVjaXNpb25cbi8vIC0gc2V0cyBtZXRob2RzIHRoYXQgYXJlbid0IGFsd2F5cyBkZWZpbmVkIGRlcGVuZGluZ1xuLy8gICBvbiB0aGUgcHJvamVjdGlvbiB0eXBlIHRvIGEgZHVtbXkgJ2QzLWVzcXVlJyBmdW5jdGlvbixcbi8vXG4vLyBUaGlzIHdyYXBwZXIgYWxsZXZpYXRlcyBzdWJzZXF1ZW50IGNvZGUgb2YgKG1hbnkpIGFubm95aW5nIGlmLXN0YXRlbWVudHMuXG5mdW5jdGlvbiBnZXRQcm9qZWN0aW9uKGdlb0xheW91dCkge1xuICAgIHZhciBwcm9qTGF5b3V0ID0gZ2VvTGF5b3V0LnByb2plY3Rpb247XG4gICAgdmFyIHByb2pUeXBlID0gcHJvakxheW91dC50eXBlO1xuXG4gICAgdmFyIHByb2plY3Rpb24gPSBkMy5nZW9bY29uc3RhbnRzLnByb2pOYW1lc1twcm9qVHlwZV1dKCk7XG5cbiAgICB2YXIgY2xpcEFuZ2xlID0gZ2VvTGF5b3V0Ll9pc0NsaXBwZWQgP1xuICAgICAgICBjb25zdGFudHMubG9uYXhpc1NwYW5bcHJvalR5cGVdIC8gMiA6XG4gICAgICAgIG51bGw7XG5cbiAgICB2YXIgbWV0aG9kcyA9IFsnY2VudGVyJywgJ3JvdGF0ZScsICdwYXJhbGxlbHMnLCAnY2xpcEV4dGVudCddO1xuICAgIHZhciBkdW1teUZuID0gZnVuY3Rpb24oXykgeyByZXR1cm4gXyA/IHByb2plY3Rpb24gOiBbXTsgfTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBtZXRob2RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBtID0gbWV0aG9kc1tpXTtcbiAgICAgICAgaWYodHlwZW9mIHByb2plY3Rpb25bbV0gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHByb2plY3Rpb25bbV0gPSBkdW1teUZuO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJvamVjdGlvbi5pc0xvbkxhdE92ZXJFZGdlcyA9IGZ1bmN0aW9uKGxvbmxhdCkge1xuICAgICAgICBpZihwcm9qZWN0aW9uKGxvbmxhdCkgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY2xpcEFuZ2xlKSB7XG4gICAgICAgICAgICB2YXIgciA9IHByb2plY3Rpb24ucm90YXRlKCk7XG4gICAgICAgICAgICB2YXIgYW5nbGUgPSBkMy5nZW8uZGlzdGFuY2UobG9ubGF0LCBbLXJbMF0sIC1yWzFdXSk7XG4gICAgICAgICAgICB2YXIgbWF4QW5nbGUgPSBjbGlwQW5nbGUgKiBNYXRoLlBJIC8gMTgwO1xuICAgICAgICAgICAgcmV0dXJuIGFuZ2xlID4gbWF4QW5nbGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJvamVjdGlvbi5nZXRQYXRoID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBkMy5nZW8ucGF0aCgpLnByb2plY3Rpb24ocHJvamVjdGlvbik7XG4gICAgfTtcblxuICAgIHByb2plY3Rpb24uZ2V0Qm91bmRzID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBwcm9qZWN0aW9uLmdldFBhdGgoKS5ib3VuZHMob2JqZWN0KTtcbiAgICB9O1xuXG4gICAgLy8gYWRhcHRlZCBmcm9tIGQzIHY0OlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9kMy9kMy1nZW8vYmxvYi9tYXN0ZXIvc3JjL3Byb2plY3Rpb24vZml0LmpzXG4gICAgcHJvamVjdGlvbi5maXRFeHRlbnQgPSBmdW5jdGlvbihleHRlbnQsIG9iamVjdCkge1xuICAgICAgICB2YXIgdyA9IGV4dGVudFsxXVswXSAtIGV4dGVudFswXVswXTtcbiAgICAgICAgdmFyIGggPSBleHRlbnRbMV1bMV0gLSBleHRlbnRbMF1bMV07XG4gICAgICAgIHZhciBjbGlwID0gcHJvamVjdGlvbi5jbGlwRXh0ZW50ICYmIHByb2plY3Rpb24uY2xpcEV4dGVudCgpO1xuXG4gICAgICAgIHByb2plY3Rpb25cbiAgICAgICAgICAgIC5zY2FsZSgxNTApXG4gICAgICAgICAgICAudHJhbnNsYXRlKFswLCAwXSk7XG5cbiAgICAgICAgaWYoY2xpcCkgcHJvamVjdGlvbi5jbGlwRXh0ZW50KG51bGwpO1xuXG4gICAgICAgIHZhciBiID0gcHJvamVjdGlvbi5nZXRCb3VuZHMob2JqZWN0KTtcbiAgICAgICAgdmFyIGsgPSBNYXRoLm1pbih3IC8gKGJbMV1bMF0gLSBiWzBdWzBdKSwgaCAvIChiWzFdWzFdIC0gYlswXVsxXSkpO1xuICAgICAgICB2YXIgeCA9ICtleHRlbnRbMF1bMF0gKyAodyAtIGsgKiAoYlsxXVswXSArIGJbMF1bMF0pKSAvIDI7XG4gICAgICAgIHZhciB5ID0gK2V4dGVudFswXVsxXSArIChoIC0gayAqIChiWzFdWzFdICsgYlswXVsxXSkpIC8gMjtcblxuICAgICAgICBpZihjbGlwKSBwcm9qZWN0aW9uLmNsaXBFeHRlbnQoY2xpcCk7XG5cbiAgICAgICAgcmV0dXJuIHByb2plY3Rpb25cbiAgICAgICAgICAgIC5zY2FsZShrICogMTUwKVxuICAgICAgICAgICAgLnRyYW5zbGF0ZShbeCwgeV0pO1xuICAgIH07XG5cbiAgICBwcm9qZWN0aW9uLnByZWNpc2lvbihjb25zdGFudHMucHJlY2lzaW9uKTtcblxuICAgIGlmKGNsaXBBbmdsZSkge1xuICAgICAgICBwcm9qZWN0aW9uLmNsaXBBbmdsZShjbGlwQW5nbGUgLSBjb25zdGFudHMuY2xpcFBhZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2plY3Rpb247XG59XG5cbmZ1bmN0aW9uIG1ha2VHcmF0aWN1bGUoYXhpc05hbWUsIGdlb0xheW91dCwgZnVsbExheW91dCkge1xuICAgIC8vIGVxdWl2YWxlbnQgdG8gdGhlIGQzIFwizrVcIlxuICAgIHZhciBlcHNpbG9uID0gMWUtNjtcbiAgICAvLyBzYW1lIGFzIHRoZSBnZW9HcmF0aWN1bGUgZGVmYXVsdFxuICAgIHZhciBwcmVjaXNpb24gPSAyLjU7XG5cbiAgICB2YXIgYXhMYXlvdXQgPSBnZW9MYXlvdXRbYXhpc05hbWVdO1xuICAgIHZhciBzY29wZURlZmF1bHRzID0gY29uc3RhbnRzLnNjb3BlRGVmYXVsdHNbZ2VvTGF5b3V0LnNjb3BlXTtcbiAgICB2YXIgcm5nO1xuICAgIHZhciBvcHBSbmc7XG4gICAgdmFyIGNvb3JkRm47XG5cbiAgICBpZihheGlzTmFtZSA9PT0gJ2xvbmF4aXMnKSB7XG4gICAgICAgIHJuZyA9IHNjb3BlRGVmYXVsdHMubG9uYXhpc1JhbmdlO1xuICAgICAgICBvcHBSbmcgPSBzY29wZURlZmF1bHRzLmxhdGF4aXNSYW5nZTtcbiAgICAgICAgY29vcmRGbiA9IGZ1bmN0aW9uKHYsIGwpIHsgcmV0dXJuIFt2LCBsXTsgfTtcbiAgICB9IGVsc2UgaWYoYXhpc05hbWUgPT09ICdsYXRheGlzJykge1xuICAgICAgICBybmcgPSBzY29wZURlZmF1bHRzLmxhdGF4aXNSYW5nZTtcbiAgICAgICAgb3BwUm5nID0gc2NvcGVEZWZhdWx0cy5sb25heGlzUmFuZ2U7XG4gICAgICAgIGNvb3JkRm4gPSBmdW5jdGlvbih2LCBsKSB7IHJldHVybiBbbCwgdl07IH07XG4gICAgfVxuXG4gICAgdmFyIGR1bW15QXggPSB7XG4gICAgICAgIHR5cGU6ICdsaW5lYXInLFxuICAgICAgICByYW5nZTogW3JuZ1swXSwgcm5nWzFdIC0gZXBzaWxvbl0sXG4gICAgICAgIHRpY2swOiBheExheW91dC50aWNrMCxcbiAgICAgICAgZHRpY2s6IGF4TGF5b3V0LmR0aWNrXG4gICAgfTtcblxuICAgIEF4ZXMuc2V0Q29udmVydChkdW1teUF4LCBmdWxsTGF5b3V0KTtcbiAgICB2YXIgdmFscyA9IEF4ZXMuY2FsY1RpY2tzKGR1bW15QXgpO1xuXG4gICAgLy8gcmVtb3ZlIGR1cGxpY2F0ZSBvbiBhbnRpbWVyaWRpYW5cbiAgICBpZighZ2VvTGF5b3V0LmlzU2NvcGVkICYmIGF4aXNOYW1lID09PSAnbG9uYXhpcycpIHtcbiAgICAgICAgdmFscy5wb3AoKTtcbiAgICB9XG5cbiAgICB2YXIgbGVuID0gdmFscy5sZW5ndGg7XG4gICAgdmFyIGNvb3JkcyA9IG5ldyBBcnJheShsZW4pO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciB2ID0gdmFsc1tpXS54O1xuICAgICAgICB2YXIgbGluZSA9IGNvb3Jkc1tpXSA9IFtdO1xuICAgICAgICBmb3IodmFyIGwgPSBvcHBSbmdbMF07IGwgPCBvcHBSbmdbMV0gKyBwcmVjaXNpb247IGwgKz0gcHJlY2lzaW9uKSB7XG4gICAgICAgICAgICBsaW5lLnB1c2goY29vcmRGbih2LCBsKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiAnTXVsdGlMaW5lU3RyaW5nJyxcbiAgICAgICAgY29vcmRpbmF0ZXM6IGNvb3Jkc1xuICAgIH07XG59XG5cbi8vIFJldHVybnMgcG9seWdvbiBHZW9KU09OIGNvcnJlc3BvbmRpbmcgdG8gbG9uL2xhdCByYW5nZSBib3hcbi8vIHdpdGggd2VsbC1kZWZpbmVkIGRpcmVjdGlvblxuLy9cbi8vIE5vdGUgdGhhdCBjbGlwUGFkIHBhZGRpbmcgaXMgYWRkZWQgYXJvdW5kIHJhbmdlIHRvIGF2b2lkIGFsaWFzaW5nLlxuZnVuY3Rpb24gbWFrZVJhbmdlQm94KGxvbiwgbGF0KSB7XG4gICAgdmFyIGNsaXBQYWQgPSBjb25zdGFudHMuY2xpcFBhZDtcbiAgICB2YXIgbG9uMCA9IGxvblswXSArIGNsaXBQYWQ7XG4gICAgdmFyIGxvbjEgPSBsb25bMV0gLSBjbGlwUGFkO1xuICAgIHZhciBsYXQwID0gbGF0WzBdICsgY2xpcFBhZDtcbiAgICB2YXIgbGF0MSA9IGxhdFsxXSAtIGNsaXBQYWQ7XG5cbiAgICAvLyB0byBjcm9zcyBhbnRpbWVyaWRpYW4gdy9vIGFtYmlndWl0eVxuICAgIGlmKGxvbjAgPiAwICYmIGxvbjEgPCAwKSBsb24xICs9IDM2MDtcblxuICAgIHZhciBkbG9uNCA9IChsb24xIC0gbG9uMCkgLyA0O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogJ1BvbHlnb24nLFxuICAgICAgICBjb29yZGluYXRlczogW1tcbiAgICAgICAgICAgIFtsb24wLCBsYXQwXSxcbiAgICAgICAgICAgIFtsb24wLCBsYXQxXSxcbiAgICAgICAgICAgIFtsb24wICsgZGxvbjQsIGxhdDFdLFxuICAgICAgICAgICAgW2xvbjAgKyAyICogZGxvbjQsIGxhdDFdLFxuICAgICAgICAgICAgW2xvbjAgKyAzICogZGxvbjQsIGxhdDFdLFxuICAgICAgICAgICAgW2xvbjEsIGxhdDFdLFxuICAgICAgICAgICAgW2xvbjEsIGxhdDBdLFxuICAgICAgICAgICAgW2xvbjEgLSBkbG9uNCwgbGF0MF0sXG4gICAgICAgICAgICBbbG9uMSAtIDIgKiBkbG9uNCwgbGF0MF0sXG4gICAgICAgICAgICBbbG9uMSAtIDMgKiBkbG9uNCwgbGF0MF0sXG4gICAgICAgICAgICBbbG9uMCwgbGF0MF1cbiAgICAgICAgXV1cbiAgICB9O1xufVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9jb21wb25lbnRzL2RyYWdlbGVtZW50XCI6NjExLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vY29tcG9uZW50cy9meFwiOjYzMixcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi90b3BvanNvbl91dGlsc1wiOjc0NixcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi9jYXJ0ZXNpYW4vc2VsZWN0XCI6Nzg0LFwiLi4vcGxvdHNcIjo4MjgsXCIuL2NvbnN0YW50c1wiOjc5NSxcIi4vcHJvamVjdGlvbnNcIjo4MDAsXCIuL3pvb21cIjo4MDEsXCJkM1wiOjE2MyxcInRvcG9qc29uLWNsaWVudFwiOjU0MH1dLDc5NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBnZXRTdWJwbG90Q2FsY0RhdGEgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9nZXRfZGF0YScpLmdldFN1YnBsb3RDYWxjRGF0YTtcbnZhciBjb3VudGVyUmVnZXggPSBfZGVyZXFfKCcuLi8uLi9saWInKS5jb3VudGVyUmVnZXg7XG5cbnZhciBjcmVhdGVHZW8gPSBfZGVyZXFfKCcuL2dlbycpO1xuXG52YXIgR0VPID0gJ2dlbyc7XG52YXIgY291bnRlciA9IGNvdW50ZXJSZWdleChHRU8pO1xuXG52YXIgYXR0cmlidXRlcyA9IHt9O1xuYXR0cmlidXRlc1tHRU9dID0ge1xuICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgIFxuICAgIGRmbHQ6IEdFTyxcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIFxufTtcblxuZnVuY3Rpb24gcGxvdEdlbyhnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGNhbGNEYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIGdlb0lkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW0dFT107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZ2VvSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBnZW9JZCA9IGdlb0lkc1tpXTtcbiAgICAgICAgdmFyIGdlb0NhbGNEYXRhID0gZ2V0U3VicGxvdENhbGNEYXRhKGNhbGNEYXRhLCBHRU8sIGdlb0lkKTtcbiAgICAgICAgdmFyIGdlb0xheW91dCA9IGZ1bGxMYXlvdXRbZ2VvSWRdO1xuICAgICAgICB2YXIgZ2VvID0gZ2VvTGF5b3V0Ll9zdWJwbG90O1xuXG4gICAgICAgIGlmKCFnZW8pIHtcbiAgICAgICAgICAgIGdlbyA9IGNyZWF0ZUdlbyh7XG4gICAgICAgICAgICAgICAgaWQ6IGdlb0lkLFxuICAgICAgICAgICAgICAgIGdyYXBoRGl2OiBnZCxcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IGZ1bGxMYXlvdXQuX2dlb2xheWVyLm5vZGUoKSxcbiAgICAgICAgICAgICAgICB0b3BvanNvblVSTDogZ2QuX2NvbnRleHQudG9wb2pzb25VUkwsXG4gICAgICAgICAgICAgICAgc3RhdGljUGxvdDogZ2QuX2NvbnRleHQuc3RhdGljUGxvdFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGZ1bGxMYXlvdXRbZ2VvSWRdLl9zdWJwbG90ID0gZ2VvO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2VvLnBsb3QoZ2VvQ2FsY0RhdGEsIGZ1bGxMYXlvdXQsIGdkLl9wcm9taXNlcyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjbGVhbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgb2xkR2VvS2V5cyA9IG9sZEZ1bGxMYXlvdXQuX3N1YnBsb3RzW0dFT10gfHwgW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgb2xkR2VvS2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb2xkR2VvS2V5ID0gb2xkR2VvS2V5c1tpXTtcbiAgICAgICAgdmFyIG9sZEdlbyA9IG9sZEZ1bGxMYXlvdXRbb2xkR2VvS2V5XS5fc3VicGxvdDtcblxuICAgICAgICBpZighbmV3RnVsbExheW91dFtvbGRHZW9LZXldICYmICEhb2xkR2VvKSB7XG4gICAgICAgICAgICBvbGRHZW8uZnJhbWV3b3JrLnJlbW92ZSgpO1xuICAgICAgICAgICAgb2xkR2VvLmNsaXBEZWYucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZUZ4KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VicGxvdElkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW0dFT107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3VicGxvdExheW91dCA9IGZ1bGxMYXlvdXRbc3VicGxvdElkc1tpXV07XG4gICAgICAgIHZhciBzdWJwbG90T2JqID0gc3VicGxvdExheW91dC5fc3VicGxvdDtcbiAgICAgICAgc3VicGxvdE9iai51cGRhdGVGeChmdWxsTGF5b3V0LCBzdWJwbG90TGF5b3V0KTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHI6IEdFTyxcbiAgICBuYW1lOiBHRU8sXG4gICAgaWRSb290OiBHRU8sXG4gICAgaWRSZWdleDogY291bnRlcixcbiAgICBhdHRyUmVnZXg6IGNvdW50ZXIsXG4gICAgYXR0cmlidXRlczogYXR0cmlidXRlcyxcbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2RlZmF1bHRzJyksXG4gICAgcGxvdDogcGxvdEdlbyxcbiAgICB1cGRhdGVGeDogdXBkYXRlRngsXG4gICAgY2xlYW46IGNsZWFuXG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2dldF9kYXRhXCI6ODAyLFwiLi9nZW9cIjo3OTYsXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6Nzk4LFwiLi9sYXlvdXRfZGVmYXVsdHNcIjo3OTl9XSw3OTg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gX2RlcmVxXygnLi4vZG9tYWluJykuYXR0cmlidXRlcztcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIG92ZXJyaWRlQWxsID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xuXG52YXIgZ2VvQXhlc0F0dHJzID0ge1xuICAgIHJhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcid9LFxuICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInfVxuICAgICAgICBdLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dncmlkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2swOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkdGljazoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgZ3JpZGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmxpZ2h0TGluZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBncmlkd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgIH1cbn07XG5cbnZhciBhdHRycyA9IG1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoe1xuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICdnZW8nfSwge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIHJlc29sdXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsxMTAsIDUwXSxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDExMCxcbiAgICAgICAgY29lcmNlTnVtYmVyOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNjb3BlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogT2JqZWN0LmtleXMoY29uc3RhbnRzLnNjb3BlRGVmYXVsdHMpLFxuICAgICAgICBkZmx0OiAnd29ybGQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHByb2plY3Rpb246IHtcbiAgICAgICAgdHlwZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICB2YWx1ZXM6IE9iamVjdC5rZXlzKGNvbnN0YW50cy5wcm9qTmFtZXMpLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHJvdGF0aW9uOiB7XG4gICAgICAgICAgICBsb246IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYXQ6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByb2xsOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHBhcmFsbGVsczoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAgICAgIHt2YWxUeXBlOiAnbnVtYmVyJ30sXG4gICAgICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInfVxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzY2FsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICB9LFxuICAgIGNlbnRlcjoge1xuICAgICAgICBsb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbGF0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9LFxuICAgIHNob3djb2FzdGxpbmVzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgY29hc3RsaW5lY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY29hc3RsaW5ld2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd2xhbmQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGFuZGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb25zdGFudHMubGFuZENvbG9yLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dvY2Vhbjoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBvY2VhbmNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb25zdGFudHMud2F0ZXJDb2xvcixcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93bGFrZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGFrZWNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb25zdGFudHMud2F0ZXJDb2xvcixcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93cml2ZXJzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuICAgIHJpdmVyY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGNvbnN0YW50cy53YXRlckNvbG9yLFxuICAgICAgICBcbiAgICB9LFxuICAgIHJpdmVyd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd2NvdW50cmllczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGNvdW50cnljb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjb3VudHJ5d2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd3N1YnVuaXRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3VidW5pdGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN1YnVuaXR3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93ZnJhbWU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBmcmFtZWNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICBcbiAgICB9LFxuICAgIGZyYW1ld2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYmdjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5iYWNrZ3JvdW5kLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxvbmF4aXM6IGdlb0F4ZXNBdHRycyxcbiAgICBsYXRheGlzOiBnZW9BeGVzQXR0cnNcbn0sICdwbG90JywgJ2Zyb20tcm9vdCcpO1xuXG4vLyBzZXQgdWlyZXZpc2lvbiBvdXRzaWRlIG9mIG92ZXJyaWRlQWxsIHNvIGl0IGNhbiBiZSBgZWRpdFR5cGU6ICdub25lJ2BcbmF0dHJzLnVpcmV2aXNpb24gPSB7XG4gICAgdmFsVHlwZTogJ2FueScsXG4gICAgXG4gICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICBcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzXCI6NTkyLFwiLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlc1wiOjc1MCxcIi4uL2RvbWFpblwiOjc5MixcIi4vY29uc3RhbnRzXCI6Nzk1fV0sNzk5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGFuZGxlU3VicGxvdERlZmF1bHRzID0gX2RlcmVxXygnLi4vc3VicGxvdF9kZWZhdWx0cycpO1xudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxudmFyIGF4ZXNOYW1lcyA9IGNvbnN0YW50cy5heGVzTmFtZXM7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICBoYW5kbGVTdWJwbG90RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEsIHtcbiAgICAgICAgdHlwZTogJ2dlbycsXG4gICAgICAgIGF0dHJpYnV0ZXM6IGxheW91dEF0dHJpYnV0ZXMsXG4gICAgICAgIGhhbmRsZURlZmF1bHRzOiBoYW5kbGVHZW9EZWZhdWx0cyxcbiAgICAgICAgcGFydGl0aW9uOiAneSdcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZUdlb0RlZmF1bHRzKGdlb0xheW91dEluLCBnZW9MYXlvdXRPdXQsIGNvZXJjZSkge1xuICAgIHZhciBzaG93O1xuXG4gICAgdmFyIHJlc29sdXRpb24gPSBjb2VyY2UoJ3Jlc29sdXRpb24nKTtcbiAgICB2YXIgc2NvcGUgPSBjb2VyY2UoJ3Njb3BlJyk7XG4gICAgdmFyIHNjb3BlUGFyYW1zID0gY29uc3RhbnRzLnNjb3BlRGVmYXVsdHNbc2NvcGVdO1xuXG4gICAgdmFyIHByb2pUeXBlID0gY29lcmNlKCdwcm9qZWN0aW9uLnR5cGUnLCBzY29wZVBhcmFtcy5wcm9qVHlwZSk7XG4gICAgdmFyIGlzQWxiZXJzVXNhID0gZ2VvTGF5b3V0T3V0Ll9pc0FsYmVyc1VzYSA9IHByb2pUeXBlID09PSAnYWxiZXJzIHVzYSc7XG5cbiAgICAvLyBubyBvdGhlciBzY29wZXMgYXJlIGFsbG93ZWQgZm9yICdhbGJlcnMgdXNhJyBwcm9qZWN0aW9uXG4gICAgaWYoaXNBbGJlcnNVc2EpIHNjb3BlID0gZ2VvTGF5b3V0T3V0LnNjb3BlID0gJ3VzYSc7XG5cbiAgICB2YXIgaXNTY29wZWQgPSBnZW9MYXlvdXRPdXQuX2lzU2NvcGVkID0gKHNjb3BlICE9PSAnd29ybGQnKTtcbiAgICB2YXIgaXNDb25pYyA9IGdlb0xheW91dE91dC5faXNDb25pYyA9IHByb2pUeXBlLmluZGV4T2YoJ2NvbmljJykgIT09IC0xO1xuICAgIGdlb0xheW91dE91dC5faXNDbGlwcGVkID0gISFjb25zdGFudHMubG9uYXhpc1NwYW5bcHJvalR5cGVdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4ZXNOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXhpc05hbWUgPSBheGVzTmFtZXNbaV07XG4gICAgICAgIHZhciBkdGlja0RmbHQgPSBbMzAsIDEwXVtpXTtcbiAgICAgICAgdmFyIHJhbmdlRGZsdDtcblxuICAgICAgICBpZihpc1Njb3BlZCkge1xuICAgICAgICAgICAgcmFuZ2VEZmx0ID0gc2NvcGVQYXJhbXNbYXhpc05hbWUgKyAnUmFuZ2UnXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBkZmx0U3BhbnMgPSBjb25zdGFudHNbYXhpc05hbWUgKyAnU3BhbiddO1xuICAgICAgICAgICAgdmFyIGhTcGFuID0gKGRmbHRTcGFuc1twcm9qVHlwZV0gfHwgZGZsdFNwYW5zWycqJ10pIC8gMjtcbiAgICAgICAgICAgIHZhciByb3QgPSBjb2VyY2UoXG4gICAgICAgICAgICAgICAgJ3Byb2plY3Rpb24ucm90YXRpb24uJyArIGF4aXNOYW1lLnN1YnN0cigwLCAzKSxcbiAgICAgICAgICAgICAgICBzY29wZVBhcmFtcy5wcm9qUm90YXRlW2ldXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmFuZ2VEZmx0ID0gW3JvdCAtIGhTcGFuLCByb3QgKyBoU3Bhbl07XG4gICAgICAgIH1cblxuICAgICAgICBjb2VyY2UoYXhpc05hbWUgKyAnLnJhbmdlJywgcmFuZ2VEZmx0KTtcbiAgICAgICAgY29lcmNlKGF4aXNOYW1lICsgJy50aWNrMCcpO1xuICAgICAgICBjb2VyY2UoYXhpc05hbWUgKyAnLmR0aWNrJywgZHRpY2tEZmx0KTtcblxuICAgICAgICBzaG93ID0gY29lcmNlKGF4aXNOYW1lICsgJy5zaG93Z3JpZCcpO1xuICAgICAgICBpZihzaG93KSB7XG4gICAgICAgICAgICBjb2VyY2UoYXhpc05hbWUgKyAnLmdyaWRjb2xvcicpO1xuICAgICAgICAgICAgY29lcmNlKGF4aXNOYW1lICsgJy5ncmlkd2lkdGgnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsb25SYW5nZSA9IGdlb0xheW91dE91dC5sb25heGlzLnJhbmdlO1xuICAgIHZhciBsYXRSYW5nZSA9IGdlb0xheW91dE91dC5sYXRheGlzLnJhbmdlO1xuXG4gICAgLy8gdG8gY3Jvc3MgYW50aW1lcmlkaWFuIHcvbyBhbWJpZ3VpdHlcbiAgICB2YXIgbG9uMCA9IGxvblJhbmdlWzBdO1xuICAgIHZhciBsb24xID0gbG9uUmFuZ2VbMV07XG4gICAgaWYobG9uMCA+IDAgJiYgbG9uMSA8IDApIGxvbjEgKz0gMzYwO1xuXG4gICAgdmFyIGNlbnRlckxvbiA9IChsb24wICsgbG9uMSkgLyAyO1xuICAgIHZhciBwcm9qTG9uO1xuXG4gICAgaWYoIWlzQWxiZXJzVXNhKSB7XG4gICAgICAgIHZhciBkZmx0UHJvalJvdGF0ZSA9IGlzU2NvcGVkID8gc2NvcGVQYXJhbXMucHJvalJvdGF0ZSA6IFtjZW50ZXJMb24sIDAsIDBdO1xuXG4gICAgICAgIHByb2pMb24gPSBjb2VyY2UoJ3Byb2plY3Rpb24ucm90YXRpb24ubG9uJywgZGZsdFByb2pSb3RhdGVbMF0pO1xuICAgICAgICBjb2VyY2UoJ3Byb2plY3Rpb24ucm90YXRpb24ubGF0JywgZGZsdFByb2pSb3RhdGVbMV0pO1xuICAgICAgICBjb2VyY2UoJ3Byb2plY3Rpb24ucm90YXRpb24ucm9sbCcsIGRmbHRQcm9qUm90YXRlWzJdKTtcblxuICAgICAgICBzaG93ID0gY29lcmNlKCdzaG93Y29hc3RsaW5lcycsICFpc1Njb3BlZCk7XG4gICAgICAgIGlmKHNob3cpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnY29hc3RsaW5lY29sb3InKTtcbiAgICAgICAgICAgIGNvZXJjZSgnY29hc3RsaW5ld2lkdGgnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNob3cgPSBjb2VyY2UoJ3Nob3dvY2VhbicpO1xuICAgICAgICBpZihzaG93KSBjb2VyY2UoJ29jZWFuY29sb3InKTtcbiAgICB9XG5cbiAgICB2YXIgY2VudGVyTG9uRGZsdDtcbiAgICB2YXIgY2VudGVyTGF0RGZsdDtcblxuICAgIGlmKGlzQWxiZXJzVXNhKSB7XG4gICAgICAgIC8vICdhbGJlcnMgdXNhJyBkb2VzIG5vdCBoYXZlIGEgJ2NlbnRlcicsXG4gICAgICAgIC8vIHRoZXNlIHZhbHVlcyB3ZXJlIGZvdW5kIHVzaW5nIHZpYTpcbiAgICAgICAgLy8gICBwcm9qZWN0aW9uLmludmVydChbZ2VvTGF5b3V0LmNlbnRlci5sb24sIGdlb0xheW91dEluLmNlbnRlci5sYXRdKVxuICAgICAgICBjZW50ZXJMb25EZmx0ID0gLTk2LjY7XG4gICAgICAgIGNlbnRlckxhdERmbHQgPSAzOC43O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNlbnRlckxvbkRmbHQgPSBpc1Njb3BlZCA/IGNlbnRlckxvbiA6IHByb2pMb247XG4gICAgICAgIGNlbnRlckxhdERmbHQgPSAobGF0UmFuZ2VbMF0gKyBsYXRSYW5nZVsxXSkgLyAyO1xuICAgIH1cblxuICAgIGNvZXJjZSgnY2VudGVyLmxvbicsIGNlbnRlckxvbkRmbHQpO1xuICAgIGNvZXJjZSgnY2VudGVyLmxhdCcsIGNlbnRlckxhdERmbHQpO1xuXG4gICAgaWYoaXNDb25pYykge1xuICAgICAgICB2YXIgZGZsdFByb2pQYXJhbGxlbHMgPSBzY29wZVBhcmFtcy5wcm9qUGFyYWxsZWxzIHx8IFswLCA2MF07XG4gICAgICAgIGNvZXJjZSgncHJvamVjdGlvbi5wYXJhbGxlbHMnLCBkZmx0UHJvalBhcmFsbGVscyk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdwcm9qZWN0aW9uLnNjYWxlJyk7XG5cbiAgICBzaG93ID0gY29lcmNlKCdzaG93bGFuZCcpO1xuICAgIGlmKHNob3cpIGNvZXJjZSgnbGFuZGNvbG9yJyk7XG5cbiAgICBzaG93ID0gY29lcmNlKCdzaG93bGFrZXMnKTtcbiAgICBpZihzaG93KSBjb2VyY2UoJ2xha2Vjb2xvcicpO1xuXG4gICAgc2hvdyA9IGNvZXJjZSgnc2hvd3JpdmVycycpO1xuICAgIGlmKHNob3cpIHtcbiAgICAgICAgY29lcmNlKCdyaXZlcmNvbG9yJyk7XG4gICAgICAgIGNvZXJjZSgncml2ZXJ3aWR0aCcpO1xuICAgIH1cblxuICAgIHNob3cgPSBjb2VyY2UoJ3Nob3djb3VudHJpZXMnLCBpc1Njb3BlZCAmJiBzY29wZSAhPT0gJ3VzYScpO1xuICAgIGlmKHNob3cpIHtcbiAgICAgICAgY29lcmNlKCdjb3VudHJ5Y29sb3InKTtcbiAgICAgICAgY29lcmNlKCdjb3VudHJ5d2lkdGgnKTtcbiAgICB9XG5cbiAgICBpZihzY29wZSA9PT0gJ3VzYScgfHwgKHNjb3BlID09PSAnbm9ydGggYW1lcmljYScgJiYgcmVzb2x1dGlvbiA9PT0gNTApKSB7XG4gICAgICAgIC8vIE9ubHkgd29ya3MgZm9yOlxuICAgICAgICAvLyAgIFVTQSBzdGF0ZXMgYXQgMTEwbVxuICAgICAgICAvLyAgIFVTQSBzdGF0ZXMgKyBDYW5hZGEgcHJvdmluY2VzIGF0IDUwbVxuICAgICAgICBjb2VyY2UoJ3Nob3dzdWJ1bml0cycsIHRydWUpO1xuICAgICAgICBjb2VyY2UoJ3N1YnVuaXRjb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ3N1YnVuaXR3aWR0aCcpO1xuICAgIH1cblxuICAgIGlmKCFpc1Njb3BlZCkge1xuICAgICAgICAvLyBEb2VzIG5vdCB3b3JrIGluIG5vbi13b3JsZCBzY29wZXNcbiAgICAgICAgc2hvdyA9IGNvZXJjZSgnc2hvd2ZyYW1lJywgdHJ1ZSk7XG4gICAgICAgIGlmKHNob3cpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnZnJhbWVjb2xvcicpO1xuICAgICAgICAgICAgY29lcmNlKCdmcmFtZXdpZHRoJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb2VyY2UoJ2JnY29sb3InKTtcbn1cblxufSx7XCIuLi9zdWJwbG90X2RlZmF1bHRzXCI6ODQyLFwiLi9jb25zdGFudHNcIjo3OTUsXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6Nzk4fV0sODAwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbi8qXG4gKiBHZW5lcmF0ZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL2V0cGluYXJkL2QzLWdlby1wcm9qZWN0aW9uLXBpY2tlclxuICpcbiAqIHdoaWNoIGlzIGhhbmQtcGlja3MgcHJvamVjdGlvbiBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9kMy9kMy1nZW8tcHJvamVjdGlvblxuICpcbiAqIGludG8gYSBDb21tb25KUyByZXF1aXJlLWFibGUgbW9kdWxlLlxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuLyogZXNsaW50LWRpc2FibGUgKi9cblxuZnVuY3Rpb24gYWRkUHJvamVjdGlvbnNUb0QzKGQzKSB7XG4gIGQzLmdlby5wcm9qZWN0ID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9qZWN0aW9uKSB7XG4gICAgdmFyIHN0cmVhbSA9IHByb2plY3Rpb24uc3RyZWFtO1xuICAgIGlmICghc3RyZWFtKSB0aHJvdyBuZXcgRXJyb3IoXCJub3QgeWV0IHN1cHBvcnRlZFwiKTtcbiAgICByZXR1cm4gKG9iamVjdCAmJiBkM19nZW9fcHJvamVjdE9iamVjdFR5cGUuaGFzT3duUHJvcGVydHkob2JqZWN0LnR5cGUpID8gZDNfZ2VvX3Byb2plY3RPYmplY3RUeXBlW29iamVjdC50eXBlXSA6IGQzX2dlb19wcm9qZWN0R2VvbWV0cnkpKG9iamVjdCwgc3RyZWFtKTtcbiAgfTtcbiAgZnVuY3Rpb24gZDNfZ2VvX3Byb2plY3RGZWF0dXJlKG9iamVjdCwgc3RyZWFtKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IFwiRmVhdHVyZVwiLFxuICAgICAgaWQ6IG9iamVjdC5pZCxcbiAgICAgIHByb3BlcnRpZXM6IG9iamVjdC5wcm9wZXJ0aWVzLFxuICAgICAgZ2VvbWV0cnk6IGQzX2dlb19wcm9qZWN0R2VvbWV0cnkob2JqZWN0Lmdlb21ldHJ5LCBzdHJlYW0pXG4gICAgfTtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcHJvamVjdEdlb21ldHJ5KGdlb21ldHJ5LCBzdHJlYW0pIHtcbiAgICBpZiAoIWdlb21ldHJ5KSByZXR1cm4gbnVsbDtcbiAgICBpZiAoZ2VvbWV0cnkudHlwZSA9PT0gXCJHZW9tZXRyeUNvbGxlY3Rpb25cIikgcmV0dXJuIHtcbiAgICAgIHR5cGU6IFwiR2VvbWV0cnlDb2xsZWN0aW9uXCIsXG4gICAgICBnZW9tZXRyaWVzOiBvYmplY3QuZ2VvbWV0cmllcy5tYXAoZnVuY3Rpb24oZ2VvbWV0cnkpIHtcbiAgICAgICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0R2VvbWV0cnkoZ2VvbWV0cnksIHN0cmVhbSk7XG4gICAgICB9KVxuICAgIH07XG4gICAgaWYgKCFkM19nZW9fcHJvamVjdEdlb21ldHJ5VHlwZS5oYXNPd25Qcm9wZXJ0eShnZW9tZXRyeS50eXBlKSkgcmV0dXJuIG51bGw7XG4gICAgdmFyIHNpbmsgPSBkM19nZW9fcHJvamVjdEdlb21ldHJ5VHlwZVtnZW9tZXRyeS50eXBlXTtcbiAgICBkMy5nZW8uc3RyZWFtKGdlb21ldHJ5LCBzdHJlYW0oc2luaykpO1xuICAgIHJldHVybiBzaW5rLnJlc3VsdCgpO1xuICB9XG4gIHZhciBkM19nZW9fcHJvamVjdE9iamVjdFR5cGUgPSB7XG4gICAgRmVhdHVyZTogZDNfZ2VvX3Byb2plY3RGZWF0dXJlLFxuICAgIEZlYXR1cmVDb2xsZWN0aW9uOiBmdW5jdGlvbihvYmplY3QsIHN0cmVhbSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogXCJGZWF0dXJlQ29sbGVjdGlvblwiLFxuICAgICAgICBmZWF0dXJlczogb2JqZWN0LmZlYXR1cmVzLm1hcChmdW5jdGlvbihmZWF0dXJlKSB7XG4gICAgICAgICAgcmV0dXJuIGQzX2dlb19wcm9qZWN0RmVhdHVyZShmZWF0dXJlLCBzdHJlYW0pO1xuICAgICAgICB9KVxuICAgICAgfTtcbiAgICB9XG4gIH07XG4gIHZhciBkM19nZW9fcHJvamVjdFBvaW50cyA9IFtdLCBkM19nZW9fcHJvamVjdExpbmVzID0gW107XG4gIHZhciBkM19nZW9fcHJvamVjdFBvaW50ID0ge1xuICAgIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgICBkM19nZW9fcHJvamVjdFBvaW50cy5wdXNoKFsgeCwgeSBdKTtcbiAgICB9LFxuICAgIHJlc3VsdDogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gIWQzX2dlb19wcm9qZWN0UG9pbnRzLmxlbmd0aCA/IG51bGwgOiBkM19nZW9fcHJvamVjdFBvaW50cy5sZW5ndGggPCAyID8ge1xuICAgICAgICB0eXBlOiBcIlBvaW50XCIsXG4gICAgICAgIGNvb3JkaW5hdGVzOiBkM19nZW9fcHJvamVjdFBvaW50c1swXVxuICAgICAgfSA6IHtcbiAgICAgICAgdHlwZTogXCJNdWx0aVBvaW50XCIsXG4gICAgICAgIGNvb3JkaW5hdGVzOiBkM19nZW9fcHJvamVjdFBvaW50c1xuICAgICAgfTtcbiAgICAgIGQzX2dlb19wcm9qZWN0UG9pbnRzID0gW107XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfTtcbiAgdmFyIGQzX2dlb19wcm9qZWN0TGluZSA9IHtcbiAgICBsaW5lU3RhcnQ6IGQzX2dlb19wcm9qZWN0Tm9vcCxcbiAgICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgICAgZDNfZ2VvX3Byb2plY3RQb2ludHMucHVzaChbIHgsIHkgXSk7XG4gICAgfSxcbiAgICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgIGlmIChkM19nZW9fcHJvamVjdFBvaW50cy5sZW5ndGgpIGQzX2dlb19wcm9qZWN0TGluZXMucHVzaChkM19nZW9fcHJvamVjdFBvaW50cyksXG4gICAgICBkM19nZW9fcHJvamVjdFBvaW50cyA9IFtdO1xuICAgIH0sXG4gICAgcmVzdWx0OiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciByZXN1bHQgPSAhZDNfZ2VvX3Byb2plY3RMaW5lcy5sZW5ndGggPyBudWxsIDogZDNfZ2VvX3Byb2plY3RMaW5lcy5sZW5ndGggPCAyID8ge1xuICAgICAgICB0eXBlOiBcIkxpbmVTdHJpbmdcIixcbiAgICAgICAgY29vcmRpbmF0ZXM6IGQzX2dlb19wcm9qZWN0TGluZXNbMF1cbiAgICAgIH0gOiB7XG4gICAgICAgIHR5cGU6IFwiTXVsdGlMaW5lU3RyaW5nXCIsXG4gICAgICAgIGNvb3JkaW5hdGVzOiBkM19nZW9fcHJvamVjdExpbmVzXG4gICAgICB9O1xuICAgICAgZDNfZ2VvX3Byb2plY3RMaW5lcyA9IFtdO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH07XG4gIHZhciBkM19nZW9fcHJvamVjdFBvbHlnb24gPSB7XG4gICAgcG9seWdvblN0YXJ0OiBkM19nZW9fcHJvamVjdE5vb3AsXG4gICAgbGluZVN0YXJ0OiBkM19nZW9fcHJvamVjdE5vb3AsXG4gICAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIGQzX2dlb19wcm9qZWN0UG9pbnRzLnB1c2goWyB4LCB5IF0pO1xuICAgIH0sXG4gICAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbiA9IGQzX2dlb19wcm9qZWN0UG9pbnRzLmxlbmd0aDtcbiAgICAgIGlmIChuKSB7XG4gICAgICAgIGRvIGQzX2dlb19wcm9qZWN0UG9pbnRzLnB1c2goZDNfZ2VvX3Byb2plY3RQb2ludHNbMF0uc2xpY2UoKSk7IHdoaWxlICgrK24gPCA0KTtcbiAgICAgICAgZDNfZ2VvX3Byb2plY3RMaW5lcy5wdXNoKGQzX2dlb19wcm9qZWN0UG9pbnRzKSwgZDNfZ2VvX3Byb2plY3RQb2ludHMgPSBbXTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHBvbHlnb25FbmQ6IGQzX2dlb19wcm9qZWN0Tm9vcCxcbiAgICByZXN1bHQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCFkM19nZW9fcHJvamVjdExpbmVzLmxlbmd0aCkgcmV0dXJuIG51bGw7XG4gICAgICB2YXIgcG9seWdvbnMgPSBbXSwgaG9sZXMgPSBbXTtcbiAgICAgIGQzX2dlb19wcm9qZWN0TGluZXMuZm9yRWFjaChmdW5jdGlvbihyaW5nKSB7XG4gICAgICAgIGlmIChkM19nZW9fcHJvamVjdENsb2Nrd2lzZShyaW5nKSkgcG9seWdvbnMucHVzaChbIHJpbmcgXSk7IGVsc2UgaG9sZXMucHVzaChyaW5nKTtcbiAgICAgIH0pO1xuICAgICAgaG9sZXMuZm9yRWFjaChmdW5jdGlvbihob2xlKSB7XG4gICAgICAgIHZhciBwb2ludCA9IGhvbGVbMF07XG4gICAgICAgIHBvbHlnb25zLnNvbWUoZnVuY3Rpb24ocG9seWdvbikge1xuICAgICAgICAgIGlmIChkM19nZW9fcHJvamVjdENvbnRhaW5zKHBvbHlnb25bMF0sIHBvaW50KSkge1xuICAgICAgICAgICAgcG9seWdvbi5wdXNoKGhvbGUpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9KSB8fCBwb2x5Z29ucy5wdXNoKFsgaG9sZSBdKTtcbiAgICAgIH0pO1xuICAgICAgZDNfZ2VvX3Byb2plY3RMaW5lcyA9IFtdO1xuICAgICAgcmV0dXJuICFwb2x5Z29ucy5sZW5ndGggPyBudWxsIDogcG9seWdvbnMubGVuZ3RoID4gMSA/IHtcbiAgICAgICAgdHlwZTogXCJNdWx0aVBvbHlnb25cIixcbiAgICAgICAgY29vcmRpbmF0ZXM6IHBvbHlnb25zXG4gICAgICB9IDoge1xuICAgICAgICB0eXBlOiBcIlBvbHlnb25cIixcbiAgICAgICAgY29vcmRpbmF0ZXM6IHBvbHlnb25zWzBdXG4gICAgICB9O1xuICAgIH1cbiAgfTtcbiAgdmFyIGQzX2dlb19wcm9qZWN0R2VvbWV0cnlUeXBlID0ge1xuICAgIFBvaW50OiBkM19nZW9fcHJvamVjdFBvaW50LFxuICAgIE11bHRpUG9pbnQ6IGQzX2dlb19wcm9qZWN0UG9pbnQsXG4gICAgTGluZVN0cmluZzogZDNfZ2VvX3Byb2plY3RMaW5lLFxuICAgIE11bHRpTGluZVN0cmluZzogZDNfZ2VvX3Byb2plY3RMaW5lLFxuICAgIFBvbHlnb246IGQzX2dlb19wcm9qZWN0UG9seWdvbixcbiAgICBNdWx0aVBvbHlnb246IGQzX2dlb19wcm9qZWN0UG9seWdvbixcbiAgICBTcGhlcmU6IGQzX2dlb19wcm9qZWN0UG9seWdvblxuICB9O1xuICBmdW5jdGlvbiBkM19nZW9fcHJvamVjdE5vb3AoKSB7fVxuICBmdW5jdGlvbiBkM19nZW9fcHJvamVjdENsb2Nrd2lzZShyaW5nKSB7XG4gICAgaWYgKChuID0gcmluZy5sZW5ndGgpIDwgNCkgcmV0dXJuIGZhbHNlO1xuICAgIHZhciBpID0gMCwgbiwgYXJlYSA9IHJpbmdbbiAtIDFdWzFdICogcmluZ1swXVswXSAtIHJpbmdbbiAtIDFdWzBdICogcmluZ1swXVsxXTtcbiAgICB3aGlsZSAoKytpIDwgbikgYXJlYSArPSByaW5nW2kgLSAxXVsxXSAqIHJpbmdbaV1bMF0gLSByaW5nW2kgLSAxXVswXSAqIHJpbmdbaV1bMV07XG4gICAgcmV0dXJuIGFyZWEgPD0gMDtcbiAgfVxuICBmdW5jdGlvbiBkM19nZW9fcHJvamVjdENvbnRhaW5zKHJpbmcsIHBvaW50KSB7XG4gICAgdmFyIHggPSBwb2ludFswXSwgeSA9IHBvaW50WzFdLCBjb250YWlucyA9IGZhbHNlO1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gcmluZy5sZW5ndGgsIGogPSBuIC0gMTsgaSA8IG47IGogPSBpKyspIHtcbiAgICAgIHZhciBwaSA9IHJpbmdbaV0sIHhpID0gcGlbMF0sIHlpID0gcGlbMV0sIHBqID0gcmluZ1tqXSwgeGogPSBwalswXSwgeWogPSBwalsxXTtcbiAgICAgIGlmICh5aSA+IHkgXiB5aiA+IHkgJiYgeCA8ICh4aiAtIHhpKSAqICh5IC0geWkpIC8gKHlqIC0geWkpICsgeGkpIGNvbnRhaW5zID0gIWNvbnRhaW5zO1xuICAgIH1cbiAgICByZXR1cm4gY29udGFpbnM7XG4gIH1cbiAgdmFyIM61ID0gMWUtNiwgzrUyID0gzrUgKiDOtSwgz4AgPSBNYXRoLlBJLCBoYWxmz4AgPSDPgCAvIDIsIHNxcnTPgCA9IE1hdGguc3FydCjPgCksIHJhZGlhbnMgPSDPgCAvIDE4MCwgZGVncmVlcyA9IDE4MCAvIM+AO1xuICBmdW5jdGlvbiBzaW5jaSh4KSB7XG4gICAgcmV0dXJuIHggPyB4IC8gTWF0aC5zaW4oeCkgOiAxO1xuICB9XG4gIGZ1bmN0aW9uIHNnbih4KSB7XG4gICAgcmV0dXJuIHggPiAwID8gMSA6IHggPCAwID8gLTEgOiAwO1xuICB9XG4gIGZ1bmN0aW9uIGFzaW4oeCkge1xuICAgIHJldHVybiB4ID4gMSA/IGhhbGbPgCA6IHggPCAtMSA/IC1oYWxmz4AgOiBNYXRoLmFzaW4oeCk7XG4gIH1cbiAgZnVuY3Rpb24gYWNvcyh4KSB7XG4gICAgcmV0dXJuIHggPiAxID8gMCA6IHggPCAtMSA/IM+AIDogTWF0aC5hY29zKHgpO1xuICB9XG4gIGZ1bmN0aW9uIGFzcXJ0KHgpIHtcbiAgICByZXR1cm4geCA+IDAgPyBNYXRoLnNxcnQoeCkgOiAwO1xuICB9XG4gIHZhciBwcm9qZWN0aW9uID0gZDMuZ2VvLnByb2plY3Rpb24sIHByb2plY3Rpb25NdXRhdG9yID0gZDMuZ2VvLnByb2plY3Rpb25NdXRhdG9yO1xuICBkMy5nZW8uaW50ZXJydXB0ID0gZnVuY3Rpb24ocHJvamVjdCkge1xuICAgIHZhciBsb2JlcyA9IFsgWyBbIFsgLc+ALCAwIF0sIFsgMCwgaGFsZs+AIF0sIFsgz4AsIDAgXSBdIF0sIFsgWyBbIC3PgCwgMCBdLCBbIDAsIC1oYWxmz4AgXSwgWyDPgCwgMCBdIF0gXSBdO1xuICAgIHZhciBib3VuZHM7XG4gICAgZnVuY3Rpb24gZm9yd2FyZCjOuywgz4YpIHtcbiAgICAgIHZhciBzaWduID0gz4YgPCAwID8gLTEgOiArMSwgaGVtaWxvYmVzID0gbG9iZXNbKyjPhiA8IDApXTtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gaGVtaWxvYmVzLmxlbmd0aCAtIDE7IGkgPCBuICYmIM67ID4gaGVtaWxvYmVzW2ldWzJdWzBdOyArK2kpIDtcbiAgICAgIHZhciBjb29yZGluYXRlcyA9IHByb2plY3QozrsgLSBoZW1pbG9iZXNbaV1bMV1bMF0sIM+GKTtcbiAgICAgIGNvb3JkaW5hdGVzWzBdICs9IHByb2plY3QoaGVtaWxvYmVzW2ldWzFdWzBdLCBzaWduICogz4YgPiBzaWduICogaGVtaWxvYmVzW2ldWzBdWzFdID8gaGVtaWxvYmVzW2ldWzBdWzFdIDogz4YpWzBdO1xuICAgICAgcmV0dXJuIGNvb3JkaW5hdGVzO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNldCgpIHtcbiAgICAgIGJvdW5kcyA9IGxvYmVzLm1hcChmdW5jdGlvbihoZW1pbG9iZXMpIHtcbiAgICAgICAgcmV0dXJuIGhlbWlsb2Jlcy5tYXAoZnVuY3Rpb24obG9iZSkge1xuICAgICAgICAgIHZhciB4MCA9IHByb2plY3QobG9iZVswXVswXSwgbG9iZVswXVsxXSlbMF0sIHgxID0gcHJvamVjdChsb2JlWzJdWzBdLCBsb2JlWzJdWzFdKVswXSwgeTAgPSBwcm9qZWN0KGxvYmVbMV1bMF0sIGxvYmVbMF1bMV0pWzFdLCB5MSA9IHByb2plY3QobG9iZVsxXVswXSwgbG9iZVsxXVsxXSlbMV0sIHQ7XG4gICAgICAgICAgaWYgKHkwID4geTEpIHQgPSB5MCwgeTAgPSB5MSwgeTEgPSB0O1xuICAgICAgICAgIHJldHVybiBbIFsgeDAsIHkwIF0sIFsgeDEsIHkxIF0gXTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHByb2plY3QuaW52ZXJ0KSBmb3J3YXJkLmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciBoZW1pYm91bmRzID0gYm91bmRzWysoeSA8IDApXSwgaGVtaWxvYmVzID0gbG9iZXNbKyh5IDwgMCldO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIG4gPSBoZW1pYm91bmRzLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgICB2YXIgYiA9IGhlbWlib3VuZHNbaV07XG4gICAgICAgIGlmIChiWzBdWzBdIDw9IHggJiYgeCA8IGJbMV1bMF0gJiYgYlswXVsxXSA8PSB5ICYmIHkgPCBiWzFdWzFdKSB7XG4gICAgICAgICAgdmFyIGNvb3JkaW5hdGVzID0gcHJvamVjdC5pbnZlcnQoeCAtIHByb2plY3QoaGVtaWxvYmVzW2ldWzFdWzBdLCAwKVswXSwgeSk7XG4gICAgICAgICAgY29vcmRpbmF0ZXNbMF0gKz0gaGVtaWxvYmVzW2ldWzFdWzBdO1xuICAgICAgICAgIHJldHVybiBwb2ludEVxdWFsKGZvcndhcmQoY29vcmRpbmF0ZXNbMF0sIGNvb3JkaW5hdGVzWzFdKSwgWyB4LCB5IF0pID8gY29vcmRpbmF0ZXMgOiBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcbiAgICB2YXIgcHJvamVjdGlvbiA9IGQzLmdlby5wcm9qZWN0aW9uKGZvcndhcmQpLCBzdHJlYW1fID0gcHJvamVjdGlvbi5zdHJlYW07XG4gICAgcHJvamVjdGlvbi5zdHJlYW0gPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgIHZhciByb3RhdGUgPSBwcm9qZWN0aW9uLnJvdGF0ZSgpLCByb3RhdGVTdHJlYW0gPSBzdHJlYW1fKHN0cmVhbSksIHNwaGVyZVN0cmVhbSA9IChwcm9qZWN0aW9uLnJvdGF0ZShbIDAsIDAgXSksXG4gICAgICBzdHJlYW1fKHN0cmVhbSkpO1xuICAgICAgcHJvamVjdGlvbi5yb3RhdGUocm90YXRlKTtcbiAgICAgIHJvdGF0ZVN0cmVhbS5zcGhlcmUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgZDMuZ2VvLnN0cmVhbShzcGhlcmUoKSwgc3BoZXJlU3RyZWFtKTtcbiAgICAgIH07XG4gICAgICByZXR1cm4gcm90YXRlU3RyZWFtO1xuICAgIH07XG4gICAgcHJvamVjdGlvbi5sb2JlcyA9IGZ1bmN0aW9uKF8pIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGxvYmVzLm1hcChmdW5jdGlvbihsb2Jlcykge1xuICAgICAgICByZXR1cm4gbG9iZXMubWFwKGZ1bmN0aW9uKGxvYmUpIHtcbiAgICAgICAgICByZXR1cm4gWyBbIGxvYmVbMF1bMF0gKiAxODAgLyDPgCwgbG9iZVswXVsxXSAqIDE4MCAvIM+AIF0sIFsgbG9iZVsxXVswXSAqIDE4MCAvIM+ALCBsb2JlWzFdWzFdICogMTgwIC8gz4AgXSwgWyBsb2JlWzJdWzBdICogMTgwIC8gz4AsIGxvYmVbMl1bMV0gKiAxODAgLyDPgCBdIF07XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgICBsb2JlcyA9IF8ubWFwKGZ1bmN0aW9uKGxvYmVzKSB7XG4gICAgICAgIHJldHVybiBsb2Jlcy5tYXAoZnVuY3Rpb24obG9iZSkge1xuICAgICAgICAgIHJldHVybiBbIFsgbG9iZVswXVswXSAqIM+AIC8gMTgwLCBsb2JlWzBdWzFdICogz4AgLyAxODAgXSwgWyBsb2JlWzFdWzBdICogz4AgLyAxODAsIGxvYmVbMV1bMV0gKiDPgCAvIDE4MCBdLCBbIGxvYmVbMl1bMF0gKiDPgCAvIDE4MCwgbG9iZVsyXVsxXSAqIM+AIC8gMTgwIF0gXTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICAgIHJlc2V0KCk7XG4gICAgICByZXR1cm4gcHJvamVjdGlvbjtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIHNwaGVyZSgpIHtcbiAgICAgIHZhciDOtSA9IDFlLTYsIGNvb3JkaW5hdGVzID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMCwgbiA9IGxvYmVzWzBdLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgICB2YXIgbG9iZSA9IGxvYmVzWzBdW2ldLCDOuzAgPSBsb2JlWzBdWzBdICogMTgwIC8gz4AsIM+GMCA9IGxvYmVbMF1bMV0gKiAxODAgLyDPgCwgz4YxID0gbG9iZVsxXVsxXSAqIDE4MCAvIM+ALCDOuzIgPSBsb2JlWzJdWzBdICogMTgwIC8gz4AsIM+GMiA9IGxvYmVbMl1bMV0gKiAxODAgLyDPgDtcbiAgICAgICAgY29vcmRpbmF0ZXMucHVzaChyZXNhbXBsZShbIFsgzrswICsgzrUsIM+GMCArIM61IF0sIFsgzrswICsgzrUsIM+GMSAtIM61IF0sIFsgzrsyIC0gzrUsIM+GMSAtIM61IF0sIFsgzrsyIC0gzrUsIM+GMiArIM61IF0gXSwgMzApKTtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGkgPSBsb2Jlc1sxXS5sZW5ndGggLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgICB2YXIgbG9iZSA9IGxvYmVzWzFdW2ldLCDOuzAgPSBsb2JlWzBdWzBdICogMTgwIC8gz4AsIM+GMCA9IGxvYmVbMF1bMV0gKiAxODAgLyDPgCwgz4YxID0gbG9iZVsxXVsxXSAqIDE4MCAvIM+ALCDOuzIgPSBsb2JlWzJdWzBdICogMTgwIC8gz4AsIM+GMiA9IGxvYmVbMl1bMV0gKiAxODAgLyDPgDtcbiAgICAgICAgY29vcmRpbmF0ZXMucHVzaChyZXNhbXBsZShbIFsgzrsyIC0gzrUsIM+GMiAtIM61IF0sIFsgzrsyIC0gzrUsIM+GMSArIM61IF0sIFsgzrswICsgzrUsIM+GMSArIM61IF0sIFsgzrswICsgzrUsIM+GMCAtIM61IF0gXSwgMzApKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IFwiUG9seWdvblwiLFxuICAgICAgICBjb29yZGluYXRlczogWyBkMy5tZXJnZShjb29yZGluYXRlcykgXVxuICAgICAgfTtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVzYW1wbGUoY29vcmRpbmF0ZXMsIG0pIHtcbiAgICAgIHZhciBpID0gLTEsIG4gPSBjb29yZGluYXRlcy5sZW5ndGgsIHAwID0gY29vcmRpbmF0ZXNbMF0sIHAxLCBkeCwgZHksIHJlc2FtcGxlZCA9IFtdO1xuICAgICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgICAgcDEgPSBjb29yZGluYXRlc1tpXTtcbiAgICAgICAgZHggPSAocDFbMF0gLSBwMFswXSkgLyBtO1xuICAgICAgICBkeSA9IChwMVsxXSAtIHAwWzFdKSAvIG07XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbTsgKytqKSByZXNhbXBsZWQucHVzaChbIHAwWzBdICsgaiAqIGR4LCBwMFsxXSArIGogKiBkeSBdKTtcbiAgICAgICAgcDAgPSBwMTtcbiAgICAgIH1cbiAgICAgIHJlc2FtcGxlZC5wdXNoKHAxKTtcbiAgICAgIHJldHVybiByZXNhbXBsZWQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHBvaW50RXF1YWwoYSwgYikge1xuICAgICAgcmV0dXJuIE1hdGguYWJzKGFbMF0gLSBiWzBdKSA8IM61ICYmIE1hdGguYWJzKGFbMV0gLSBiWzFdKSA8IM61O1xuICAgIH1cbiAgICByZXR1cm4gcHJvamVjdGlvbjtcbiAgfTtcbiAgZnVuY3Rpb24gZWNrZXJ0NCjOuywgz4YpIHtcbiAgICB2YXIgayA9ICgyICsgaGFsZs+AKSAqIE1hdGguc2luKM+GKTtcbiAgICDPhiAvPSAyO1xuICAgIGZvciAodmFyIGkgPSAwLCDOtCA9IEluZmluaXR5OyBpIDwgMTAgJiYgTWF0aC5hYnMozrQpID4gzrU7IGkrKykge1xuICAgICAgdmFyIGNvc8+GID0gTWF0aC5jb3Moz4YpO1xuICAgICAgz4YgLT0gzrQgPSAoz4YgKyBNYXRoLnNpbijPhikgKiAoY29zz4YgKyAyKSAtIGspIC8gKDIgKiBjb3PPhiAqICgxICsgY29zz4YpKTtcbiAgICB9XG4gICAgcmV0dXJuIFsgMiAvIE1hdGguc3FydCjPgCAqICg0ICsgz4ApKSAqIM67ICogKDEgKyBNYXRoLmNvcyjPhikpLCAyICogTWF0aC5zcXJ0KM+AIC8gKDQgKyDPgCkpICogTWF0aC5zaW4oz4YpIF07XG4gIH1cbiAgZWNrZXJ0NC5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgdmFyIEEgPSAuNSAqIHkgKiBNYXRoLnNxcnQoKDQgKyDPgCkgLyDPgCksIGsgPSBhc2luKEEpLCBjID0gTWF0aC5jb3Moayk7XG4gICAgcmV0dXJuIFsgeCAvICgyIC8gTWF0aC5zcXJ0KM+AICogKDQgKyDPgCkpICogKDEgKyBjKSksIGFzaW4oKGsgKyBBICogKGMgKyAyKSkgLyAoMiArIGhhbGbPgCkpIF07XG4gIH07XG4gIChkMy5nZW8uZWNrZXJ0NCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBwcm9qZWN0aW9uKGVja2VydDQpO1xuICB9KS5yYXcgPSBlY2tlcnQ0O1xuICB2YXIgaGFtbWVyQXppbXV0aGFsRXF1YWxBcmVhID0gZDMuZ2VvLmF6aW11dGhhbEVxdWFsQXJlYS5yYXc7XG4gIGZ1bmN0aW9uIGhhbW1lcihBLCBCKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSBCID0gQTtcbiAgICBpZiAoQiA9PT0gMSkgcmV0dXJuIGhhbW1lckF6aW11dGhhbEVxdWFsQXJlYTtcbiAgICBpZiAoQiA9PT0gSW5maW5pdHkpIHJldHVybiBoYW1tZXJRdWFydGljQXV0aGFsaWM7XG4gICAgZnVuY3Rpb24gZm9yd2FyZCjOuywgz4YpIHtcbiAgICAgIHZhciBjb29yZGluYXRlcyA9IGhhbW1lckF6aW11dGhhbEVxdWFsQXJlYSjOuyAvIEIsIM+GKTtcbiAgICAgIGNvb3JkaW5hdGVzWzBdICo9IEE7XG4gICAgICByZXR1cm4gY29vcmRpbmF0ZXM7XG4gICAgfVxuICAgIGZvcndhcmQuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgICAgdmFyIGNvb3JkaW5hdGVzID0gaGFtbWVyQXppbXV0aGFsRXF1YWxBcmVhLmludmVydCh4IC8gQSwgeSk7XG4gICAgICBjb29yZGluYXRlc1swXSAqPSBCO1xuICAgICAgcmV0dXJuIGNvb3JkaW5hdGVzO1xuICAgIH07XG4gICAgcmV0dXJuIGZvcndhcmQ7XG4gIH1cbiAgZnVuY3Rpb24gaGFtbWVyUHJvamVjdGlvbigpIHtcbiAgICB2YXIgQiA9IDIsIG0gPSBwcm9qZWN0aW9uTXV0YXRvcihoYW1tZXIpLCBwID0gbShCKTtcbiAgICBwLmNvZWZmaWNpZW50ID0gZnVuY3Rpb24oXykge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gQjtcbiAgICAgIHJldHVybiBtKEIgPSArXyk7XG4gICAgfTtcbiAgICByZXR1cm4gcDtcbiAgfVxuICBmdW5jdGlvbiBoYW1tZXJRdWFydGljQXV0aGFsaWMozrssIM+GKSB7XG4gICAgcmV0dXJuIFsgzrsgKiBNYXRoLmNvcyjPhikgLyBNYXRoLmNvcyjPhiAvPSAyKSwgMiAqIE1hdGguc2luKM+GKSBdO1xuICB9XG4gIGhhbW1lclF1YXJ0aWNBdXRoYWxpYy5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgdmFyIM+GID0gMiAqIGFzaW4oeSAvIDIpO1xuICAgIHJldHVybiBbIHggKiBNYXRoLmNvcyjPhiAvIDIpIC8gTWF0aC5jb3Moz4YpLCDPhiBdO1xuICB9O1xuICAoZDMuZ2VvLmhhbW1lciA9IGhhbW1lclByb2plY3Rpb24pLnJhdyA9IGhhbW1lcjtcbiAgZnVuY3Rpb24ga2F2cmF5c2tpeTcozrssIM+GKSB7XG4gICAgcmV0dXJuIFsgMyAqIM67IC8gKDIgKiDPgCkgKiBNYXRoLnNxcnQoz4AgKiDPgCAvIDMgLSDPhiAqIM+GKSwgz4YgXTtcbiAgfVxuICBrYXZyYXlza2l5Ny5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgcmV0dXJuIFsgMiAvIDMgKiDPgCAqIHggLyBNYXRoLnNxcnQoz4AgKiDPgCAvIDMgLSB5ICogeSksIHkgXTtcbiAgfTtcbiAgKGQzLmdlby5rYXZyYXlza2l5NyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBwcm9qZWN0aW9uKGthdnJheXNraXk3KTtcbiAgfSkucmF3ID0ga2F2cmF5c2tpeTc7XG4gIGZ1bmN0aW9uIG1pbGxlcijOuywgz4YpIHtcbiAgICByZXR1cm4gWyDOuywgMS4yNSAqIE1hdGgubG9nKE1hdGgudGFuKM+AIC8gNCArIC40ICogz4YpKSBdO1xuICB9XG4gIG1pbGxlci5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgcmV0dXJuIFsgeCwgMi41ICogTWF0aC5hdGFuKE1hdGguZXhwKC44ICogeSkpIC0gLjYyNSAqIM+AIF07XG4gIH07XG4gIChkMy5nZW8ubWlsbGVyID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHByb2plY3Rpb24obWlsbGVyKTtcbiAgfSkucmF3ID0gbWlsbGVyO1xuICBmdW5jdGlvbiBtb2xsd2VpZGVCcm9tbGV5zrgoQ3ApIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ozrgpIHtcbiAgICAgIHZhciBDcHNpbs64ID0gQ3AgKiBNYXRoLnNpbijOuCksIGkgPSAzMCwgzrQ7XG4gICAgICBkbyDOuCAtPSDOtCA9ICjOuCArIE1hdGguc2luKM64KSAtIENwc2luzrgpIC8gKDEgKyBNYXRoLmNvcyjOuCkpOyB3aGlsZSAoTWF0aC5hYnMozrQpID4gzrUgJiYgLS1pID4gMCk7XG4gICAgICByZXR1cm4gzrggLyAyO1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gbW9sbHdlaWRlQnJvbWxleShDeCwgQ3ksIENwKSB7XG4gICAgdmFyIM64ID0gbW9sbHdlaWRlQnJvbWxlec64KENwKTtcbiAgICBmdW5jdGlvbiBmb3J3YXJkKM67LCDPhikge1xuICAgICAgcmV0dXJuIFsgQ3ggKiDOuyAqIE1hdGguY29zKM+GID0gzrgoz4YpKSwgQ3kgKiBNYXRoLnNpbijPhikgXTtcbiAgICB9XG4gICAgZm9yd2FyZC5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgICB2YXIgzrggPSBhc2luKHkgLyBDeSk7XG4gICAgICByZXR1cm4gWyB4IC8gKEN4ICogTWF0aC5jb3MozrgpKSwgYXNpbigoMiAqIM64ICsgTWF0aC5zaW4oMiAqIM64KSkgLyBDcCkgXTtcbiAgICB9O1xuICAgIHJldHVybiBmb3J3YXJkO1xuICB9XG4gIHZhciBtb2xsd2VpZGXOuCA9IG1vbGx3ZWlkZUJyb21sZXnOuCjPgCksIG1vbGx3ZWlkZSA9IG1vbGx3ZWlkZUJyb21sZXkoTWF0aC5TUVJUMiAvIGhhbGbPgCwgTWF0aC5TUVJUMiwgz4ApO1xuICAoZDMuZ2VvLm1vbGx3ZWlkZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBwcm9qZWN0aW9uKG1vbGx3ZWlkZSk7XG4gIH0pLnJhdyA9IG1vbGx3ZWlkZTtcbiAgZnVuY3Rpb24gbmF0dXJhbEVhcnRoKM67LCDPhikge1xuICAgIHZhciDPhjIgPSDPhiAqIM+GLCDPhjQgPSDPhjIgKiDPhjI7XG4gICAgcmV0dXJuIFsgzrsgKiAoLjg3MDcgLSAuMTMxOTc5ICogz4YyICsgz4Y0ICogKC0uMDEzNzkxICsgz4Y0ICogKC4wMDM5NzEgKiDPhjIgLSAuMDAxNTI5ICogz4Y0KSkpLCDPhiAqICgxLjAwNzIyNiArIM+GMiAqICguMDE1MDg1ICsgz4Y0ICogKC0uMDQ0NDc1ICsgLjAyODg3NCAqIM+GMiAtIC4wMDU5MTYgKiDPhjQpKSkgXTtcbiAgfVxuICBuYXR1cmFsRWFydGguaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHZhciDPhiA9IHksIGkgPSAyNSwgzrQ7XG4gICAgZG8ge1xuICAgICAgdmFyIM+GMiA9IM+GICogz4YsIM+GNCA9IM+GMiAqIM+GMjtcbiAgICAgIM+GIC09IM60ID0gKM+GICogKDEuMDA3MjI2ICsgz4YyICogKC4wMTUwODUgKyDPhjQgKiAoLS4wNDQ0NzUgKyAuMDI4ODc0ICogz4YyIC0gLjAwNTkxNiAqIM+GNCkpKSAtIHkpIC8gKDEuMDA3MjI2ICsgz4YyICogKC4wMTUwODUgKiAzICsgz4Y0ICogKC0uMDQ0NDc1ICogNyArIC4wMjg4NzQgKiA5ICogz4YyIC0gLjAwNTkxNiAqIDExICogz4Y0KSkpO1xuICAgIH0gd2hpbGUgKE1hdGguYWJzKM60KSA+IM61ICYmIC0taSA+IDApO1xuICAgIHJldHVybiBbIHggLyAoLjg3MDcgKyAoz4YyID0gz4YgKiDPhikgKiAoLS4xMzE5NzkgKyDPhjIgKiAoLS4wMTM3OTEgKyDPhjIgKiDPhjIgKiDPhjIgKiAoLjAwMzk3MSAtIC4wMDE1MjkgKiDPhjIpKSkpLCDPhiBdO1xuICB9O1xuICAoZDMuZ2VvLm5hdHVyYWxFYXJ0aCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBwcm9qZWN0aW9uKG5hdHVyYWxFYXJ0aCk7XG4gIH0pLnJhdyA9IG5hdHVyYWxFYXJ0aDtcbiAgdmFyIHJvYmluc29uQ29uc3RhbnRzID0gWyBbIC45OTg2LCAtLjA2MiBdLCBbIDEsIDAgXSwgWyAuOTk4NiwgLjA2MiBdLCBbIC45OTU0LCAuMTI0IF0sIFsgLjk5LCAuMTg2IF0sIFsgLjk4MjIsIC4yNDggXSwgWyAuOTczLCAuMzEgXSwgWyAuOTYsIC4zNzIgXSwgWyAuOTQyNywgLjQzNCBdLCBbIC45MjE2LCAuNDk1OCBdLCBbIC44OTYyLCAuNTU3MSBdLCBbIC44Njc5LCAuNjE3NiBdLCBbIC44MzUsIC42NzY5IF0sIFsgLjc5ODYsIC43MzQ2IF0sIFsgLjc1OTcsIC43OTAzIF0sIFsgLjcxODYsIC44NDM1IF0sIFsgLjY3MzIsIC44OTM2IF0sIFsgLjYyMTMsIC45Mzk0IF0sIFsgLjU3MjIsIC45NzYxIF0sIFsgLjUzMjIsIDEgXSBdO1xuICByb2JpbnNvbkNvbnN0YW50cy5mb3JFYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICBkWzFdICo9IDEuMDE0NDtcbiAgfSk7XG4gIGZ1bmN0aW9uIHJvYmluc29uKM67LCDPhikge1xuICAgIHZhciBpID0gTWF0aC5taW4oMTgsIE1hdGguYWJzKM+GKSAqIDM2IC8gz4ApLCBpMCA9IE1hdGguZmxvb3IoaSksIGRpID0gaSAtIGkwLCBheCA9IChrID0gcm9iaW5zb25Db25zdGFudHNbaTBdKVswXSwgYXkgPSBrWzFdLCBieCA9IChrID0gcm9iaW5zb25Db25zdGFudHNbKytpMF0pWzBdLCBieSA9IGtbMV0sIGN4ID0gKGsgPSByb2JpbnNvbkNvbnN0YW50c1tNYXRoLm1pbigxOSwgKytpMCldKVswXSwgY3kgPSBrWzFdLCBrO1xuICAgIHJldHVybiBbIM67ICogKGJ4ICsgZGkgKiAoY3ggLSBheCkgLyAyICsgZGkgKiBkaSAqIChjeCAtIDIgKiBieCArIGF4KSAvIDIpLCAoz4YgPiAwID8gaGFsZs+AIDogLWhhbGbPgCkgKiAoYnkgKyBkaSAqIChjeSAtIGF5KSAvIDIgKyBkaSAqIGRpICogKGN5IC0gMiAqIGJ5ICsgYXkpIC8gMikgXTtcbiAgfVxuICByb2JpbnNvbi5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgdmFyIHl5ID0geSAvIGhhbGbPgCwgz4YgPSB5eSAqIDkwLCBpID0gTWF0aC5taW4oMTgsIE1hdGguYWJzKM+GIC8gNSkpLCBpMCA9IE1hdGgubWF4KDAsIE1hdGguZmxvb3IoaSkpO1xuICAgIGRvIHtcbiAgICAgIHZhciBheSA9IHJvYmluc29uQ29uc3RhbnRzW2kwXVsxXSwgYnkgPSByb2JpbnNvbkNvbnN0YW50c1tpMCArIDFdWzFdLCBjeSA9IHJvYmluc29uQ29uc3RhbnRzW01hdGgubWluKDE5LCBpMCArIDIpXVsxXSwgdSA9IGN5IC0gYXksIHYgPSBjeSAtIDIgKiBieSArIGF5LCB0ID0gMiAqIChNYXRoLmFicyh5eSkgLSBieSkgLyB1LCBjID0gdiAvIHUsIGRpID0gdCAqICgxIC0gYyAqIHQgKiAoMSAtIDIgKiBjICogdCkpO1xuICAgICAgaWYgKGRpID49IDAgfHwgaTAgPT09IDEpIHtcbiAgICAgICAgz4YgPSAoeSA+PSAwID8gNSA6IC01KSAqIChkaSArIGkpO1xuICAgICAgICB2YXIgaiA9IDUwLCDOtDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgIGkgPSBNYXRoLm1pbigxOCwgTWF0aC5hYnMoz4YpIC8gNSk7XG4gICAgICAgICAgaTAgPSBNYXRoLmZsb29yKGkpO1xuICAgICAgICAgIGRpID0gaSAtIGkwO1xuICAgICAgICAgIGF5ID0gcm9iaW5zb25Db25zdGFudHNbaTBdWzFdO1xuICAgICAgICAgIGJ5ID0gcm9iaW5zb25Db25zdGFudHNbaTAgKyAxXVsxXTtcbiAgICAgICAgICBjeSA9IHJvYmluc29uQ29uc3RhbnRzW01hdGgubWluKDE5LCBpMCArIDIpXVsxXTtcbiAgICAgICAgICDPhiAtPSAozrQgPSAoeSA+PSAwID8gaGFsZs+AIDogLWhhbGbPgCkgKiAoYnkgKyBkaSAqIChjeSAtIGF5KSAvIDIgKyBkaSAqIGRpICogKGN5IC0gMiAqIGJ5ICsgYXkpIC8gMikgLSB5KSAqIGRlZ3JlZXM7XG4gICAgICAgIH0gd2hpbGUgKE1hdGguYWJzKM60KSA+IM61MiAmJiAtLWogPiAwKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfSB3aGlsZSAoLS1pMCA+PSAwKTtcbiAgICB2YXIgYXggPSByb2JpbnNvbkNvbnN0YW50c1tpMF1bMF0sIGJ4ID0gcm9iaW5zb25Db25zdGFudHNbaTAgKyAxXVswXSwgY3ggPSByb2JpbnNvbkNvbnN0YW50c1tNYXRoLm1pbigxOSwgaTAgKyAyKV1bMF07XG4gICAgcmV0dXJuIFsgeCAvIChieCArIGRpICogKGN4IC0gYXgpIC8gMiArIGRpICogZGkgKiAoY3ggLSAyICogYnggKyBheCkgLyAyKSwgz4YgKiByYWRpYW5zIF07XG4gIH07XG4gIChkMy5nZW8ucm9iaW5zb24gPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gcHJvamVjdGlvbihyb2JpbnNvbik7XG4gIH0pLnJhdyA9IHJvYmluc29uO1xuICBmdW5jdGlvbiBzaW51c29pZGFsKM67LCDPhikge1xuICAgIHJldHVybiBbIM67ICogTWF0aC5jb3Moz4YpLCDPhiBdO1xuICB9XG4gIHNpbnVzb2lkYWwuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHJldHVybiBbIHggLyBNYXRoLmNvcyh5KSwgeSBdO1xuICB9O1xuICAoZDMuZ2VvLnNpbnVzb2lkYWwgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gcHJvamVjdGlvbihzaW51c29pZGFsKTtcbiAgfSkucmF3ID0gc2ludXNvaWRhbDtcbiAgZnVuY3Rpb24gYWl0b2ZmKM67LCDPhikge1xuICAgIHZhciBjb3PPhiA9IE1hdGguY29zKM+GKSwgc2luY2nOsSA9IHNpbmNpKGFjb3MoY29zz4YgKiBNYXRoLmNvcyjOuyAvPSAyKSkpO1xuICAgIHJldHVybiBbIDIgKiBjb3PPhiAqIE1hdGguc2luKM67KSAqIHNpbmNpzrEsIE1hdGguc2luKM+GKSAqIHNpbmNpzrEgXTtcbiAgfVxuICBhaXRvZmYuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIGlmICh4ICogeCArIDQgKiB5ICogeSA+IM+AICogz4AgKyDOtSkgcmV0dXJuO1xuICAgIHZhciDOuyA9IHgsIM+GID0geSwgaSA9IDI1O1xuICAgIGRvIHtcbiAgICAgIHZhciBzaW7OuyA9IE1hdGguc2luKM67KSwgc2luzrtfMiA9IE1hdGguc2luKM67IC8gMiksIGNvc867XzIgPSBNYXRoLmNvcyjOuyAvIDIpLCBzaW7PhiA9IE1hdGguc2luKM+GKSwgY29zz4YgPSBNYXRoLmNvcyjPhiksIHNpbl8yz4YgPSBNYXRoLnNpbigyICogz4YpLCBzaW4yz4YgPSBzaW7PhiAqIHNpbs+GLCBjb3Myz4YgPSBjb3PPhiAqIGNvc8+GLCBzaW4yzrtfMiA9IHNpbs67XzIgKiBzaW7Ou18yLCBDID0gMSAtIGNvczLPhiAqIGNvc867XzIgKiBjb3POu18yLCBFID0gQyA/IGFjb3MoY29zz4YgKiBjb3POu18yKSAqIE1hdGguc3FydChGID0gMSAvIEMpIDogRiA9IDAsIEYsIGZ4ID0gMiAqIEUgKiBjb3PPhiAqIHNpbs67XzIgLSB4LCBmeSA9IEUgKiBzaW7PhiAtIHksIM60eM60zrsgPSBGICogKGNvczLPhiAqIHNpbjLOu18yICsgRSAqIGNvc8+GICogY29zzrtfMiAqIHNpbjLPhiksIM60eM60z4YgPSBGICogKC41ICogc2luzrsgKiBzaW5fMs+GIC0gRSAqIDIgKiBzaW7PhiAqIHNpbs67XzIpLCDOtHnOtM67ID0gRiAqIC4yNSAqIChzaW5fMs+GICogc2luzrtfMiAtIEUgKiBzaW7PhiAqIGNvczLPhiAqIHNpbs67KSwgzrR5zrTPhiA9IEYgKiAoc2luMs+GICogY29zzrtfMiArIEUgKiBzaW4yzrtfMiAqIGNvc8+GKSwgZGVub21pbmF0b3IgPSDOtHjOtM+GICogzrR5zrTOuyAtIM60ec60z4YgKiDOtHjOtM67O1xuICAgICAgaWYgKCFkZW5vbWluYXRvcikgYnJlYWs7XG4gICAgICB2YXIgzrTOuyA9IChmeSAqIM60eM60z4YgLSBmeCAqIM60ec60z4YpIC8gZGVub21pbmF0b3IsIM60z4YgPSAoZnggKiDOtHnOtM67IC0gZnkgKiDOtHjOtM67KSAvIGRlbm9taW5hdG9yO1xuICAgICAgzrsgLT0gzrTOuywgz4YgLT0gzrTPhjtcbiAgICB9IHdoaWxlICgoTWF0aC5hYnMozrTOuykgPiDOtSB8fCBNYXRoLmFicyjOtM+GKSA+IM61KSAmJiAtLWkgPiAwKTtcbiAgICByZXR1cm4gWyDOuywgz4YgXTtcbiAgfTtcbiAgKGQzLmdlby5haXRvZmYgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gcHJvamVjdGlvbihhaXRvZmYpO1xuICB9KS5yYXcgPSBhaXRvZmY7XG4gIGZ1bmN0aW9uIHdpbmtlbDMozrssIM+GKSB7XG4gICAgdmFyIGNvb3JkaW5hdGVzID0gYWl0b2ZmKM67LCDPhik7XG4gICAgcmV0dXJuIFsgKGNvb3JkaW5hdGVzWzBdICsgzrsgLyBoYWxmz4ApIC8gMiwgKGNvb3JkaW5hdGVzWzFdICsgz4YpIC8gMiBdO1xuICB9XG4gIHdpbmtlbDMuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHZhciDOuyA9IHgsIM+GID0geSwgaSA9IDI1O1xuICAgIGRvIHtcbiAgICAgIHZhciBjb3PPhiA9IE1hdGguY29zKM+GKSwgc2luz4YgPSBNYXRoLnNpbijPhiksIHNpbl8yz4YgPSBNYXRoLnNpbigyICogz4YpLCBzaW4yz4YgPSBzaW7PhiAqIHNpbs+GLCBjb3Myz4YgPSBjb3PPhiAqIGNvc8+GLCBzaW7OuyA9IE1hdGguc2luKM67KSwgY29zzrtfMiA9IE1hdGguY29zKM67IC8gMiksIHNpbs67XzIgPSBNYXRoLnNpbijOuyAvIDIpLCBzaW4yzrtfMiA9IHNpbs67XzIgKiBzaW7Ou18yLCBDID0gMSAtIGNvczLPhiAqIGNvc867XzIgKiBjb3POu18yLCBFID0gQyA/IGFjb3MoY29zz4YgKiBjb3POu18yKSAqIE1hdGguc3FydChGID0gMSAvIEMpIDogRiA9IDAsIEYsIGZ4ID0gLjUgKiAoMiAqIEUgKiBjb3PPhiAqIHNpbs67XzIgKyDOuyAvIGhhbGbPgCkgLSB4LCBmeSA9IC41ICogKEUgKiBzaW7PhiArIM+GKSAtIHksIM60eM60zrsgPSAuNSAqIEYgKiAoY29zMs+GICogc2luMs67XzIgKyBFICogY29zz4YgKiBjb3POu18yICogc2luMs+GKSArIC41IC8gaGFsZs+ALCDOtHjOtM+GID0gRiAqIChzaW7OuyAqIHNpbl8yz4YgLyA0IC0gRSAqIHNpbs+GICogc2luzrtfMiksIM60ec60zrsgPSAuMTI1ICogRiAqIChzaW5fMs+GICogc2luzrtfMiAtIEUgKiBzaW7PhiAqIGNvczLPhiAqIHNpbs67KSwgzrR5zrTPhiA9IC41ICogRiAqIChzaW4yz4YgKiBjb3POu18yICsgRSAqIHNpbjLOu18yICogY29zz4YpICsgLjUsIGRlbm9taW5hdG9yID0gzrR4zrTPhiAqIM60ec60zrsgLSDOtHnOtM+GICogzrR4zrTOuywgzrTOuyA9IChmeSAqIM60eM60z4YgLSBmeCAqIM60ec60z4YpIC8gZGVub21pbmF0b3IsIM60z4YgPSAoZnggKiDOtHnOtM67IC0gZnkgKiDOtHjOtM67KSAvIGRlbm9taW5hdG9yO1xuICAgICAgzrsgLT0gzrTOuywgz4YgLT0gzrTPhjtcbiAgICB9IHdoaWxlICgoTWF0aC5hYnMozrTOuykgPiDOtSB8fCBNYXRoLmFicyjOtM+GKSA+IM61KSAmJiAtLWkgPiAwKTtcbiAgICByZXR1cm4gWyDOuywgz4YgXTtcbiAgfTtcbiAgKGQzLmdlby53aW5rZWwzID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHByb2plY3Rpb24od2lua2VsMyk7XG4gIH0pLnJhdyA9IHdpbmtlbDM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYWRkUHJvamVjdGlvbnNUb0QzO1xuXG59LHt9XSw4MDE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xuXG52YXIgcmFkaWFucyA9IE1hdGguUEkgLyAxODA7XG52YXIgZGVncmVlcyA9IDE4MCAvIE1hdGguUEk7XG52YXIgem9vbXN0YXJ0U3R5bGUgPSB7Y3Vyc29yOiAncG9pbnRlcid9O1xudmFyIHpvb21lbmRTdHlsZSA9IHtjdXJzb3I6ICdhdXRvJ307XG5cbmZ1bmN0aW9uIGNyZWF0ZUdlb1pvb20oZ2VvLCBnZW9MYXlvdXQpIHtcbiAgICB2YXIgcHJvamVjdGlvbiA9IGdlby5wcm9qZWN0aW9uO1xuICAgIHZhciB6b29tQ29uc3RydWN0b3I7XG5cbiAgICBpZihnZW9MYXlvdXQuX2lzU2NvcGVkKSB7XG4gICAgICAgIHpvb21Db25zdHJ1Y3RvciA9IHpvb21TY29wZWQ7XG4gICAgfSBlbHNlIGlmKGdlb0xheW91dC5faXNDbGlwcGVkKSB7XG4gICAgICAgIHpvb21Db25zdHJ1Y3RvciA9IHpvb21DbGlwcGVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHpvb21Db25zdHJ1Y3RvciA9IHpvb21Ob25DbGlwcGVkO1xuICAgIH1cblxuICAgIC8vIFRPRE8gYWRkIGEgY29uaWMtc3BlY2lmaWMgem9vbVxuXG4gICAgcmV0dXJuIHpvb21Db25zdHJ1Y3RvcihnZW8sIHByb2plY3Rpb24pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUdlb1pvb207XG5cbi8vIGNvbW1vbiB0byBhbGwgem9vbSB0eXBlc1xuZnVuY3Rpb24gaW5pdFpvb20oZ2VvLCBwcm9qZWN0aW9uKSB7XG4gICAgcmV0dXJuIGQzLmJlaGF2aW9yLnpvb20oKVxuICAgICAgICAudHJhbnNsYXRlKHByb2plY3Rpb24udHJhbnNsYXRlKCkpXG4gICAgICAgIC5zY2FsZShwcm9qZWN0aW9uLnNjYWxlKCkpO1xufVxuXG4vLyBzeW5jIHpvb20gdXBkYXRlcyB3aXRoIHVzZXIgJiBmdWxsIGxheW91dFxuZnVuY3Rpb24gc3luYyhnZW8sIHByb2plY3Rpb24sIGNiKSB7XG4gICAgdmFyIGlkID0gZ2VvLmlkO1xuICAgIHZhciBnZCA9IGdlby5ncmFwaERpdjtcbiAgICB2YXIgbGF5b3V0ID0gZ2QubGF5b3V0O1xuICAgIHZhciB1c2VyT3B0cyA9IGxheW91dFtpZF07XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZnVsbE9wdHMgPSBmdWxsTGF5b3V0W2lkXTtcblxuICAgIHZhciBwcmVHVUkgPSB7fTtcbiAgICB2YXIgZXZlbnREYXRhID0ge307XG5cbiAgICBmdW5jdGlvbiBzZXQocHJvcFN0ciwgdmFsKSB7XG4gICAgICAgIHByZUdVSVtpZCArICcuJyArIHByb3BTdHJdID0gTGliLm5lc3RlZFByb3BlcnR5KHVzZXJPcHRzLCBwcm9wU3RyKS5nZXQoKTtcbiAgICAgICAgUmVnaXN0cnkuY2FsbCgnX3N0b3JlRGlyZWN0R1VJRWRpdCcsIGxheW91dCwgZnVsbExheW91dC5fcHJlR1VJLCBwcmVHVUkpO1xuXG4gICAgICAgIHZhciBmdWxsTnAgPSBMaWIubmVzdGVkUHJvcGVydHkoZnVsbE9wdHMsIHByb3BTdHIpO1xuICAgICAgICBpZihmdWxsTnAuZ2V0KCkgIT09IHZhbCkge1xuICAgICAgICAgICAgZnVsbE5wLnNldCh2YWwpO1xuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KHVzZXJPcHRzLCBwcm9wU3RyKS5zZXQodmFsKTtcbiAgICAgICAgICAgIGV2ZW50RGF0YVtpZCArICcuJyArIHByb3BTdHJdID0gdmFsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2Ioc2V0KTtcbiAgICBzZXQoJ3Byb2plY3Rpb24uc2NhbGUnLCBwcm9qZWN0aW9uLnNjYWxlKCkgLyBnZW8uZml0U2NhbGUpO1xuICAgIGdkLmVtaXQoJ3Bsb3RseV9yZWxheW91dCcsIGV2ZW50RGF0YSk7XG59XG5cbi8vIHpvb20gZm9yIHNjb3BlZCBwcm9qZWN0aW9uc1xuZnVuY3Rpb24gem9vbVNjb3BlZChnZW8sIHByb2plY3Rpb24pIHtcbiAgICB2YXIgem9vbSA9IGluaXRab29tKGdlbywgcHJvamVjdGlvbik7XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVab29tc3RhcnQoKSB7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zdHlsZSh6b29tc3RhcnRTdHlsZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGFuZGxlWm9vbSgpIHtcbiAgICAgICAgcHJvamVjdGlvblxuICAgICAgICAgICAgLnNjYWxlKGQzLmV2ZW50LnNjYWxlKVxuICAgICAgICAgICAgLnRyYW5zbGF0ZShkMy5ldmVudC50cmFuc2xhdGUpO1xuICAgICAgICBnZW8ucmVuZGVyKCk7XG5cbiAgICAgICAgdmFyIGNlbnRlciA9IHByb2plY3Rpb24uaW52ZXJ0KGdlby5taWRQdCk7XG4gICAgICAgIGdlby5ncmFwaERpdi5lbWl0KCdwbG90bHlfcmVsYXlvdXRpbmcnLCB7XG4gICAgICAgICAgICAnZ2VvLnByb2plY3Rpb24uc2NhbGUnOiBwcm9qZWN0aW9uLnNjYWxlKCkgLyBnZW8uZml0U2NhbGUsXG4gICAgICAgICAgICAnZ2VvLmNlbnRlci5sb24nOiBjZW50ZXJbMF0sXG4gICAgICAgICAgICAnZ2VvLmNlbnRlci5sYXQnOiBjZW50ZXJbMV1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3luY0NiKHNldCkge1xuICAgICAgICB2YXIgY2VudGVyID0gcHJvamVjdGlvbi5pbnZlcnQoZ2VvLm1pZFB0KTtcblxuICAgICAgICBzZXQoJ2NlbnRlci5sb24nLCBjZW50ZXJbMF0pO1xuICAgICAgICBzZXQoJ2NlbnRlci5sYXQnLCBjZW50ZXJbMV0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhbmRsZVpvb21lbmQoKSB7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zdHlsZSh6b29tZW5kU3R5bGUpO1xuICAgICAgICBzeW5jKGdlbywgcHJvamVjdGlvbiwgc3luY0NiKTtcbiAgICB9XG5cbiAgICB6b29tXG4gICAgICAgIC5vbignem9vbXN0YXJ0JywgaGFuZGxlWm9vbXN0YXJ0KVxuICAgICAgICAub24oJ3pvb20nLCBoYW5kbGVab29tKVxuICAgICAgICAub24oJ3pvb21lbmQnLCBoYW5kbGVab29tZW5kKTtcblxuICAgIHJldHVybiB6b29tO1xufVxuXG4vLyB6b29tIGZvciBub24tY2xpcHBlZCBwcm9qZWN0aW9uc1xuZnVuY3Rpb24gem9vbU5vbkNsaXBwZWQoZ2VvLCBwcm9qZWN0aW9uKSB7XG4gICAgdmFyIHpvb20gPSBpbml0Wm9vbShnZW8sIHByb2plY3Rpb24pO1xuXG4gICAgdmFyIElOU0lERVRPTE9SQU5DRVBYUyA9IDI7XG5cbiAgICB2YXIgbW91c2UwLCByb3RhdGUwLCB0cmFuc2xhdGUwLCBsYXN0Um90YXRlLCB6b29tUG9pbnQsXG4gICAgICAgIG1vdXNlMSwgcm90YXRlMSwgcG9pbnQxLCBkaWRab29tO1xuXG4gICAgZnVuY3Rpb24gcG9zaXRpb24oeCkgeyByZXR1cm4gcHJvamVjdGlvbi5pbnZlcnQoeCk7IH1cblxuICAgIGZ1bmN0aW9uIG91dHNpZGUoeCkge1xuICAgICAgICB2YXIgcG9zID0gcG9zaXRpb24oeCk7XG4gICAgICAgIGlmKCFwb3MpIHJldHVybiB0cnVlO1xuXG4gICAgICAgIHZhciBwdCA9IHByb2plY3Rpb24ocG9zKTtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIE1hdGguYWJzKHB0WzBdIC0geFswXSkgPiBJTlNJREVUT0xPUkFOQ0VQWFMgfHxcbiAgICAgICAgICAgIE1hdGguYWJzKHB0WzFdIC0geFsxXSkgPiBJTlNJREVUT0xPUkFOQ0VQWFNcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVab29tc3RhcnQoKSB7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zdHlsZSh6b29tc3RhcnRTdHlsZSk7XG5cbiAgICAgICAgbW91c2UwID0gZDMubW91c2UodGhpcyk7XG4gICAgICAgIHJvdGF0ZTAgPSBwcm9qZWN0aW9uLnJvdGF0ZSgpO1xuICAgICAgICB0cmFuc2xhdGUwID0gcHJvamVjdGlvbi50cmFuc2xhdGUoKTtcbiAgICAgICAgbGFzdFJvdGF0ZSA9IHJvdGF0ZTA7XG4gICAgICAgIHpvb21Qb2ludCA9IHBvc2l0aW9uKG1vdXNlMCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGFuZGxlWm9vbSgpIHtcbiAgICAgICAgbW91c2UxID0gZDMubW91c2UodGhpcyk7XG5cbiAgICAgICAgaWYob3V0c2lkZShtb3VzZTApKSB7XG4gICAgICAgICAgICB6b29tLnNjYWxlKHByb2plY3Rpb24uc2NhbGUoKSk7XG4gICAgICAgICAgICB6b29tLnRyYW5zbGF0ZShwcm9qZWN0aW9uLnRyYW5zbGF0ZSgpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHByb2plY3Rpb24uc2NhbGUoZDMuZXZlbnQuc2NhbGUpO1xuICAgICAgICBwcm9qZWN0aW9uLnRyYW5zbGF0ZShbdHJhbnNsYXRlMFswXSwgZDMuZXZlbnQudHJhbnNsYXRlWzFdXSk7XG5cbiAgICAgICAgaWYoIXpvb21Qb2ludCkge1xuICAgICAgICAgICAgbW91c2UwID0gbW91c2UxO1xuICAgICAgICAgICAgem9vbVBvaW50ID0gcG9zaXRpb24obW91c2UwKTtcbiAgICAgICAgfSBlbHNlIGlmKHBvc2l0aW9uKG1vdXNlMSkpIHtcbiAgICAgICAgICAgIHBvaW50MSA9IHBvc2l0aW9uKG1vdXNlMSk7XG4gICAgICAgICAgICByb3RhdGUxID0gW2xhc3RSb3RhdGVbMF0gKyAocG9pbnQxWzBdIC0gem9vbVBvaW50WzBdKSwgcm90YXRlMFsxXSwgcm90YXRlMFsyXV07XG4gICAgICAgICAgICBwcm9qZWN0aW9uLnJvdGF0ZShyb3RhdGUxKTtcbiAgICAgICAgICAgIGxhc3RSb3RhdGUgPSByb3RhdGUxO1xuICAgICAgICB9XG5cbiAgICAgICAgZGlkWm9vbSA9IHRydWU7XG4gICAgICAgIGdlby5yZW5kZXIoKTtcblxuICAgICAgICB2YXIgcm90YXRlID0gcHJvamVjdGlvbi5yb3RhdGUoKTtcbiAgICAgICAgdmFyIGNlbnRlciA9IHByb2plY3Rpb24uaW52ZXJ0KGdlby5taWRQdCk7XG4gICAgICAgIGdlby5ncmFwaERpdi5lbWl0KCdwbG90bHlfcmVsYXlvdXRpbmcnLCB7XG4gICAgICAgICAgICAnZ2VvLnByb2plY3Rpb24uc2NhbGUnOiBwcm9qZWN0aW9uLnNjYWxlKCkgLyBnZW8uZml0U2NhbGUsXG4gICAgICAgICAgICAnZ2VvLmNlbnRlci5sb24nOiBjZW50ZXJbMF0sXG4gICAgICAgICAgICAnZ2VvLmNlbnRlci5sYXQnOiBjZW50ZXJbMV0sXG4gICAgICAgICAgICAnZ2VvLnByb2plY3Rpb24ucm90YXRpb24ubG9uJzogLXJvdGF0ZVswXVxuXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhbmRsZVpvb21lbmQoKSB7XG4gICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zdHlsZSh6b29tZW5kU3R5bGUpO1xuICAgICAgICBpZihkaWRab29tKSBzeW5jKGdlbywgcHJvamVjdGlvbiwgc3luY0NiKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzeW5jQ2Ioc2V0KSB7XG4gICAgICAgIHZhciByb3RhdGUgPSBwcm9qZWN0aW9uLnJvdGF0ZSgpO1xuICAgICAgICB2YXIgY2VudGVyID0gcHJvamVjdGlvbi5pbnZlcnQoZ2VvLm1pZFB0KTtcblxuICAgICAgICBzZXQoJ3Byb2plY3Rpb24ucm90YXRpb24ubG9uJywgLXJvdGF0ZVswXSk7XG4gICAgICAgIHNldCgnY2VudGVyLmxvbicsIGNlbnRlclswXSk7XG4gICAgICAgIHNldCgnY2VudGVyLmxhdCcsIGNlbnRlclsxXSk7XG4gICAgfVxuXG4gICAgem9vbVxuICAgICAgICAub24oJ3pvb21zdGFydCcsIGhhbmRsZVpvb21zdGFydClcbiAgICAgICAgLm9uKCd6b29tJywgaGFuZGxlWm9vbSlcbiAgICAgICAgLm9uKCd6b29tZW5kJywgaGFuZGxlWm9vbWVuZCk7XG5cbiAgICByZXR1cm4gem9vbTtcbn1cblxuLy8gem9vbSBmb3IgY2xpcHBlZCBwcm9qZWN0aW9uc1xuLy8gaW5zcGlyZWQgYnkgaHR0cHM6Ly93d3cuamFzb25kYXZpZXMuY29tL21hcHMvZDMuZ2VvLnpvb20uanNcbmZ1bmN0aW9uIHpvb21DbGlwcGVkKGdlbywgcHJvamVjdGlvbikge1xuICAgIHZhciB2aWV3ID0ge3I6IHByb2plY3Rpb24ucm90YXRlKCksIGs6IHByb2plY3Rpb24uc2NhbGUoKX07XG4gICAgdmFyIHpvb20gPSBpbml0Wm9vbShnZW8sIHByb2plY3Rpb24pO1xuICAgIHZhciBldmVudCA9IGQzZXZlbnREaXNwYXRjaCh6b29tLCAnem9vbXN0YXJ0JywgJ3pvb20nLCAnem9vbWVuZCcpO1xuICAgIHZhciB6b29taW5nID0gMDtcbiAgICB2YXIgem9vbU9uID0gem9vbS5vbjtcblxuICAgIHZhciB6b29tUG9pbnQ7XG5cbiAgICB6b29tLm9uKCd6b29tc3RhcnQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnN0eWxlKHpvb21zdGFydFN0eWxlKTtcblxuICAgICAgICB2YXIgbW91c2UwID0gZDMubW91c2UodGhpcyk7XG4gICAgICAgIHZhciByb3RhdGUwID0gcHJvamVjdGlvbi5yb3RhdGUoKTtcbiAgICAgICAgdmFyIGxhc3RSb3RhdGUgPSByb3RhdGUwO1xuICAgICAgICB2YXIgdHJhbnNsYXRlMCA9IHByb2plY3Rpb24udHJhbnNsYXRlKCk7XG4gICAgICAgIHZhciBxID0gcXVhdGVybmlvbkZyb21FdWxlcihyb3RhdGUwKTtcblxuICAgICAgICB6b29tUG9pbnQgPSBwb3NpdGlvbihwcm9qZWN0aW9uLCBtb3VzZTApO1xuXG4gICAgICAgIHpvb21Pbi5jYWxsKHpvb20sICd6b29tJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgbW91c2UxID0gZDMubW91c2UodGhpcyk7XG5cbiAgICAgICAgICAgIHByb2plY3Rpb24uc2NhbGUodmlldy5rID0gZDMuZXZlbnQuc2NhbGUpO1xuXG4gICAgICAgICAgICBpZighem9vbVBvaW50KSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgbm8gem9vbVBvaW50LCB0aGUgbW91c2Ugd2Fzbid0IG92ZXIgdGhlIGFjdHVhbCBnZW9ncmFwaHkgeWV0XG4gICAgICAgICAgICAgICAgLy8gbWF5YmUgdGhpcyBwb2ludCBpcyB0aGUgc3RhcnQuLi4gd2UnbGwgZmluZCBvdXQgbmV4dCB0aW1lIVxuICAgICAgICAgICAgICAgIG1vdXNlMCA9IG1vdXNlMTtcbiAgICAgICAgICAgICAgICB6b29tUG9pbnQgPSBwb3NpdGlvbihwcm9qZWN0aW9uLCBtb3VzZTApO1xuICAgICAgICAgICAgfSBlbHNlIGlmKHBvc2l0aW9uKHByb2plY3Rpb24sIG1vdXNlMSkpIHtcbiAgICAgICAgICAgICAgICAvLyBjaGVjayBpZiB0aGUgcG9pbnQgaXMgb24gdGhlIG1hcFxuICAgICAgICAgICAgICAgIC8vIGlmIG5vdCwgZG9uJ3QgZG8gYW55dGhpbmcgbmV3IGJ1dCBzY2FsZVxuICAgICAgICAgICAgICAgIC8vIGlmIGl0IGlzLCB0aGVuIHdlIGNhbiBhc3N1bWUgYmV0d2VlbiB3aWxsIGV4aXN0IGJlbG93XG4gICAgICAgICAgICAgICAgLy8gc28gd2UgZG9uJ3QgbmVlZCB0aGUgJ2JhbmsnIGZ1bmN0aW9uLCB3aGF0ZXZlciB0aGF0IGlzLlxuXG4gICAgICAgICAgICAgICAgLy8gZ28gYmFjayB0byBvcmlnaW5hbCBwcm9qZWN0aW9uIHRlbXBvcmFyaWx5XG4gICAgICAgICAgICAgICAgLy8gZXhjZXB0IGZvciBzY2FsZS4uLiB0aGF0J3Mga2luZCBvZiBpbmRlcGVuZGVudD9cbiAgICAgICAgICAgICAgICBwcm9qZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIC5yb3RhdGUocm90YXRlMClcbiAgICAgICAgICAgICAgICAgICAgLnRyYW5zbGF0ZSh0cmFuc2xhdGUwKTtcblxuICAgICAgICAgICAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgbmV3IHBhcmFtc1xuICAgICAgICAgICAgICAgIHZhciBwb2ludDEgPSBwb3NpdGlvbihwcm9qZWN0aW9uLCBtb3VzZTEpO1xuICAgICAgICAgICAgICAgIHZhciBiZXR3ZWVuID0gcm90YXRlQmV0d2Vlbih6b29tUG9pbnQsIHBvaW50MSk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld0V1bGVyID0gZXVsZXJGcm9tUXVhdGVybmlvbihtdWx0aXBseShxLCBiZXR3ZWVuKSk7XG4gICAgICAgICAgICAgICAgdmFyIHJvdGF0ZUFuZ2xlcyA9IHZpZXcuciA9IHVuUm9sbChuZXdFdWxlciwgem9vbVBvaW50LCBsYXN0Um90YXRlKTtcblxuICAgICAgICAgICAgICAgIGlmKCFpc0Zpbml0ZShyb3RhdGVBbmdsZXNbMF0pIHx8ICFpc0Zpbml0ZShyb3RhdGVBbmdsZXNbMV0pIHx8XG4gICAgICAgICAgICAgICAgICAgIWlzRmluaXRlKHJvdGF0ZUFuZ2xlc1syXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcm90YXRlQW5nbGVzID0gbGFzdFJvdGF0ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyB1cGRhdGUgdGhlIHByb2plY3Rpb25cbiAgICAgICAgICAgICAgICBwcm9qZWN0aW9uLnJvdGF0ZShyb3RhdGVBbmdsZXMpO1xuICAgICAgICAgICAgICAgIGxhc3RSb3RhdGUgPSByb3RhdGVBbmdsZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHpvb21lZChldmVudC5vZih0aGlzLCBhcmd1bWVudHMpKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgem9vbXN0YXJ0ZWQoZXZlbnQub2YodGhpcywgYXJndW1lbnRzKSk7XG4gICAgfSlcbiAgICAub24oJ3pvb21lbmQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnN0eWxlKHpvb21lbmRTdHlsZSk7XG4gICAgICAgIHpvb21Pbi5jYWxsKHpvb20sICd6b29tJywgbnVsbCk7XG4gICAgICAgIHpvb21lbmRlZChldmVudC5vZih0aGlzLCBhcmd1bWVudHMpKTtcbiAgICAgICAgc3luYyhnZW8sIHByb2plY3Rpb24sIHN5bmNDYik7XG4gICAgfSlcbiAgICAub24oJ3pvb20ucmVkcmF3JywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGdlby5yZW5kZXIoKTtcblxuICAgICAgICB2YXIgX3JvdGF0ZSA9IHByb2plY3Rpb24ucm90YXRlKCk7XG4gICAgICAgIGdlby5ncmFwaERpdi5lbWl0KCdwbG90bHlfcmVsYXlvdXRpbmcnLCB7XG4gICAgICAgICAgICAnZ2VvLnByb2plY3Rpb24uc2NhbGUnOiBwcm9qZWN0aW9uLnNjYWxlKCkgLyBnZW8uZml0U2NhbGUsXG4gICAgICAgICAgICAnZ2VvLnByb2plY3Rpb24ucm90YXRpb24ubG9uJzogLV9yb3RhdGVbMF0sXG4gICAgICAgICAgICAnZ2VvLnByb2plY3Rpb24ucm90YXRpb24ubGF0JzogLV9yb3RhdGVbMV1cbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiB6b29tc3RhcnRlZChkaXNwYXRjaCkge1xuICAgICAgICBpZighem9vbWluZysrKSBkaXNwYXRjaCh7dHlwZTogJ3pvb21zdGFydCd9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tZWQoZGlzcGF0Y2gpIHtcbiAgICAgICAgZGlzcGF0Y2goe3R5cGU6ICd6b29tJ30pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHpvb21lbmRlZChkaXNwYXRjaCkge1xuICAgICAgICBpZighLS16b29taW5nKSBkaXNwYXRjaCh7dHlwZTogJ3pvb21lbmQnfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3luY0NiKHNldCkge1xuICAgICAgICB2YXIgX3JvdGF0ZSA9IHByb2plY3Rpb24ucm90YXRlKCk7XG4gICAgICAgIHNldCgncHJvamVjdGlvbi5yb3RhdGlvbi5sb24nLCAtX3JvdGF0ZVswXSk7XG4gICAgICAgIHNldCgncHJvamVjdGlvbi5yb3RhdGlvbi5sYXQnLCAtX3JvdGF0ZVsxXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGQzLnJlYmluZCh6b29tLCBldmVudCwgJ29uJyk7XG59XG5cbi8vIC0tIGhlbHBlciBmdW5jdGlvbnMgZm9yIHpvb21DbGlwcGVkXG5cbmZ1bmN0aW9uIHBvc2l0aW9uKHByb2plY3Rpb24sIHBvaW50KSB7XG4gICAgdmFyIHNwaGVyaWNhbCA9IHByb2plY3Rpb24uaW52ZXJ0KHBvaW50KTtcbiAgICByZXR1cm4gc3BoZXJpY2FsICYmIGlzRmluaXRlKHNwaGVyaWNhbFswXSkgJiYgaXNGaW5pdGUoc3BoZXJpY2FsWzFdKSAmJiBjYXJ0ZXNpYW4oc3BoZXJpY2FsKTtcbn1cblxuZnVuY3Rpb24gcXVhdGVybmlvbkZyb21FdWxlcihldWxlcikge1xuICAgIHZhciBsYW1iZGEgPSAwLjUgKiBldWxlclswXSAqIHJhZGlhbnM7XG4gICAgdmFyIHBoaSA9IDAuNSAqIGV1bGVyWzFdICogcmFkaWFucztcbiAgICB2YXIgZ2FtbWEgPSAwLjUgKiBldWxlclsyXSAqIHJhZGlhbnM7XG4gICAgdmFyIHNpbkxhbWJkYSA9IE1hdGguc2luKGxhbWJkYSk7XG4gICAgdmFyIGNvc0xhbWJkYSA9IE1hdGguY29zKGxhbWJkYSk7XG4gICAgdmFyIHNpblBoaSA9IE1hdGguc2luKHBoaSk7XG4gICAgdmFyIGNvc1BoaSA9IE1hdGguY29zKHBoaSk7XG4gICAgdmFyIHNpbkdhbW1hID0gTWF0aC5zaW4oZ2FtbWEpO1xuICAgIHZhciBjb3NHYW1tYSA9IE1hdGguY29zKGdhbW1hKTtcbiAgICByZXR1cm4gW1xuICAgICAgICBjb3NMYW1iZGEgKiBjb3NQaGkgKiBjb3NHYW1tYSArIHNpbkxhbWJkYSAqIHNpblBoaSAqIHNpbkdhbW1hLFxuICAgICAgICBzaW5MYW1iZGEgKiBjb3NQaGkgKiBjb3NHYW1tYSAtIGNvc0xhbWJkYSAqIHNpblBoaSAqIHNpbkdhbW1hLFxuICAgICAgICBjb3NMYW1iZGEgKiBzaW5QaGkgKiBjb3NHYW1tYSArIHNpbkxhbWJkYSAqIGNvc1BoaSAqIHNpbkdhbW1hLFxuICAgICAgICBjb3NMYW1iZGEgKiBjb3NQaGkgKiBzaW5HYW1tYSAtIHNpbkxhbWJkYSAqIHNpblBoaSAqIGNvc0dhbW1hXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gbXVsdGlwbHkoYSwgYikge1xuICAgIHZhciBhMCA9IGFbMF07XG4gICAgdmFyIGExID0gYVsxXTtcbiAgICB2YXIgYTIgPSBhWzJdO1xuICAgIHZhciBhMyA9IGFbM107XG4gICAgdmFyIGIwID0gYlswXTtcbiAgICB2YXIgYjEgPSBiWzFdO1xuICAgIHZhciBiMiA9IGJbMl07XG4gICAgdmFyIGIzID0gYlszXTtcbiAgICByZXR1cm4gW1xuICAgICAgICBhMCAqIGIwIC0gYTEgKiBiMSAtIGEyICogYjIgLSBhMyAqIGIzLFxuICAgICAgICBhMCAqIGIxICsgYTEgKiBiMCArIGEyICogYjMgLSBhMyAqIGIyLFxuICAgICAgICBhMCAqIGIyIC0gYTEgKiBiMyArIGEyICogYjAgKyBhMyAqIGIxLFxuICAgICAgICBhMCAqIGIzICsgYTEgKiBiMiAtIGEyICogYjEgKyBhMyAqIGIwXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gcm90YXRlQmV0d2VlbihhLCBiKSB7XG4gICAgaWYoIWEgfHwgIWIpIHJldHVybjtcbiAgICB2YXIgYXhpcyA9IGNyb3NzKGEsIGIpO1xuICAgIHZhciBub3JtID0gTWF0aC5zcXJ0KGRvdChheGlzLCBheGlzKSk7XG4gICAgdmFyIGhhbGZnYW1tYSA9IDAuNSAqIE1hdGguYWNvcyhNYXRoLm1heCgtMSwgTWF0aC5taW4oMSwgZG90KGEsIGIpKSkpO1xuICAgIHZhciBrID0gTWF0aC5zaW4oaGFsZmdhbW1hKSAvIG5vcm07XG4gICAgcmV0dXJuIG5vcm0gJiYgW01hdGguY29zKGhhbGZnYW1tYSksIGF4aXNbMl0gKiBrLCAtYXhpc1sxXSAqIGssIGF4aXNbMF0gKiBrXTtcbn1cblxuLy8gaW5wdXQ6XG4vLyAgIHJvdGF0ZUFuZ2xlczogYSBjYWxjdWxhdGVkIHNldCBvZiBFdWxlciBhbmdsZXNcbi8vICAgcHQ6IGEgcG9pbnQgKGNhcnRlc2lhbiBpbiAzLXNwYWNlKSB0byBrZWVwIGZpeGVkXG4vLyAgIHJvbGwwOiBhbiBpbml0aWFsIHJvbGwsIHRvIGJlIHByZXNlcnZlZFxuLy8gb3V0cHV0OlxuLy8gICBhIHNldCBvZiBFdWxlciBhbmdsZXMgdGhhdCBwcmVzZXJ2ZSB0aGUgcHJvamVjdGlvbiBvZiBwdFxuLy8gICAgIGJ1dCBzZXQgcm9sbCAob3V0cHV0WzJdKSBlcXVhbCB0byByb2xsMFxuLy8gICAgIG5vdGUgdGhhdCB0aGlzIGRvZXNuJ3QgZGVwZW5kIG9uIHRoZSBwYXJ0aWN1bGFyIHByb2plY3Rpb24sXG4vLyAgICAganVzdCBvbiB0aGUgcm90YXRpb24gYW5nbGVzXG5mdW5jdGlvbiB1blJvbGwocm90YXRlQW5nbGVzLCBwdCwgbGFzdFJvdGF0ZSkge1xuICAgIC8vIGNhbGN1bGF0ZSB0aGUgZml4ZWQgcG9pbnQgdHJhbnNmb3JtZWQgYnkgdGhlc2UgRXVsZXIgYW5nbGVzXG4gICAgLy8gYnV0IHdpdGggdGhlIGRlc2lyZWQgcm9sbCB1bmRvbmVcbiAgICB2YXIgcHRSb3RhdGVkID0gcm90YXRlQ2FydGVzaWFuKHB0LCAyLCByb3RhdGVBbmdsZXNbMF0pO1xuICAgIHB0Um90YXRlZCA9IHJvdGF0ZUNhcnRlc2lhbihwdFJvdGF0ZWQsIDEsIHJvdGF0ZUFuZ2xlc1sxXSk7XG4gICAgcHRSb3RhdGVkID0gcm90YXRlQ2FydGVzaWFuKHB0Um90YXRlZCwgMCwgcm90YXRlQW5nbGVzWzJdIC0gbGFzdFJvdGF0ZVsyXSk7XG5cbiAgICB2YXIgeCA9IHB0WzBdO1xuICAgIHZhciB5ID0gcHRbMV07XG4gICAgdmFyIHogPSBwdFsyXTtcbiAgICB2YXIgZiA9IHB0Um90YXRlZFswXTtcbiAgICB2YXIgZyA9IHB0Um90YXRlZFsxXTtcbiAgICB2YXIgaCA9IHB0Um90YXRlZFsyXTtcblxuICAgIC8vIHRoZSBmb2xsb3dpbmcgZXNzZW50aWFsbHkgc29sdmVzOlxuICAgIC8vIHB0Um90YXRlZCA9IHJvdGF0ZUNhcnRlc2lhbihyb3RhdGVDYXJ0ZXNpYW4ocHQsIDIsIG5ld1lhdyksIDEsIG5ld1BpdGNoKVxuICAgIC8vIGZvciBuZXdZYXcgYW5kIG5ld1BpdGNoLCBhcyBiZXN0IGl0IGNhblxuICAgIHZhciB0aGV0YSA9IE1hdGguYXRhbjIoeSwgeCkgKiBkZWdyZWVzO1xuICAgIHZhciBhID0gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkpO1xuICAgIHZhciBiO1xuICAgIHZhciBuZXdZYXcxO1xuXG4gICAgaWYoTWF0aC5hYnMoZykgPiBhKSB7XG4gICAgICAgIG5ld1lhdzEgPSAoZyA+IDAgPyA5MCA6IC05MCkgLSB0aGV0YTtcbiAgICAgICAgYiA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmV3WWF3MSA9IE1hdGguYXNpbihnIC8gYSkgKiBkZWdyZWVzIC0gdGhldGE7XG4gICAgICAgIGIgPSBNYXRoLnNxcnQoYSAqIGEgLSBnICogZyk7XG4gICAgfVxuXG4gICAgdmFyIG5ld1lhdzIgPSAxODAgLSBuZXdZYXcxIC0gMiAqIHRoZXRhO1xuICAgIHZhciBuZXdQaXRjaDEgPSAoTWF0aC5hdGFuMihoLCBmKSAtIE1hdGguYXRhbjIoeiwgYikpICogZGVncmVlcztcbiAgICB2YXIgbmV3UGl0Y2gyID0gKE1hdGguYXRhbjIoaCwgZikgLSBNYXRoLmF0YW4yKHosIC1iKSkgKiBkZWdyZWVzO1xuXG4gICAgLy8gd2hpY2ggaXMgY2xvc2VzdCB0byBsYXN0Um90YXRlWzAsMV06IG5ld1lhdy9QaXRjaCBvciBuZXdZYXcyL1BpdGNoMj9cbiAgICB2YXIgZGlzdDEgPSBhbmdsZURpc3RhbmNlKGxhc3RSb3RhdGVbMF0sIGxhc3RSb3RhdGVbMV0sIG5ld1lhdzEsIG5ld1BpdGNoMSk7XG4gICAgdmFyIGRpc3QyID0gYW5nbGVEaXN0YW5jZShsYXN0Um90YXRlWzBdLCBsYXN0Um90YXRlWzFdLCBuZXdZYXcyLCBuZXdQaXRjaDIpO1xuXG4gICAgaWYoZGlzdDEgPD0gZGlzdDIpIHJldHVybiBbbmV3WWF3MSwgbmV3UGl0Y2gxLCBsYXN0Um90YXRlWzJdXTtcbiAgICBlbHNlIHJldHVybiBbbmV3WWF3MiwgbmV3UGl0Y2gyLCBsYXN0Um90YXRlWzJdXTtcbn1cblxuZnVuY3Rpb24gYW5nbGVEaXN0YW5jZSh5YXcwLCBwaXRjaDAsIHlhdzEsIHBpdGNoMSkge1xuICAgIHZhciBkWWF3ID0gYW5nbGVNb2QoeWF3MSAtIHlhdzApO1xuICAgIHZhciBkUGl0Y2ggPSBhbmdsZU1vZChwaXRjaDEgLSBwaXRjaDApO1xuICAgIHJldHVybiBNYXRoLnNxcnQoZFlhdyAqIGRZYXcgKyBkUGl0Y2ggKiBkUGl0Y2gpO1xufVxuXG4vLyByZWR1Y2UgYW4gYW5nbGUgaW4gZGVncmVlcyB0byBbLTE4MCwxODBdXG5mdW5jdGlvbiBhbmdsZU1vZChhbmdsZSkge1xuICAgIHJldHVybiAoYW5nbGUgJSAzNjAgKyA1NDApICUgMzYwIC0gMTgwO1xufVxuXG4vLyByb3RhdGUgYSBjYXJ0ZXNpYW4gdmVjdG9yXG4vLyBheGlzIGlzIDAgKHgpLCAxICh5KSwgb3IgMiAoeilcbi8vIGFuZ2xlIGlzIGluIGRlZ3JlZXNcbmZ1bmN0aW9uIHJvdGF0ZUNhcnRlc2lhbih2ZWN0b3IsIGF4aXMsIGFuZ2xlKSB7XG4gICAgdmFyIGFuZ2xlUmFkcyA9IGFuZ2xlICogcmFkaWFucztcbiAgICB2YXIgdmVjdG9yT3V0ID0gdmVjdG9yLnNsaWNlKCk7XG4gICAgdmFyIGF4MSA9IChheGlzID09PSAwKSA/IDEgOiAwO1xuICAgIHZhciBheDIgPSAoYXhpcyA9PT0gMikgPyAxIDogMjtcbiAgICB2YXIgY29zYSA9IE1hdGguY29zKGFuZ2xlUmFkcyk7XG4gICAgdmFyIHNpbmEgPSBNYXRoLnNpbihhbmdsZVJhZHMpO1xuXG4gICAgdmVjdG9yT3V0W2F4MV0gPSB2ZWN0b3JbYXgxXSAqIGNvc2EgLSB2ZWN0b3JbYXgyXSAqIHNpbmE7XG4gICAgdmVjdG9yT3V0W2F4Ml0gPSB2ZWN0b3JbYXgyXSAqIGNvc2EgKyB2ZWN0b3JbYXgxXSAqIHNpbmE7XG5cbiAgICByZXR1cm4gdmVjdG9yT3V0O1xufVxuZnVuY3Rpb24gZXVsZXJGcm9tUXVhdGVybmlvbihxKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgTWF0aC5hdGFuMigyICogKHFbMF0gKiBxWzFdICsgcVsyXSAqIHFbM10pLCAxIC0gMiAqIChxWzFdICogcVsxXSArIHFbMl0gKiBxWzJdKSkgKiBkZWdyZWVzLFxuICAgICAgICBNYXRoLmFzaW4oTWF0aC5tYXgoLTEsIE1hdGgubWluKDEsIDIgKiAocVswXSAqIHFbMl0gLSBxWzNdICogcVsxXSkpKSkgKiBkZWdyZWVzLFxuICAgICAgICBNYXRoLmF0YW4yKDIgKiAocVswXSAqIHFbM10gKyBxWzFdICogcVsyXSksIDEgLSAyICogKHFbMl0gKiBxWzJdICsgcVszXSAqIHFbM10pKSAqIGRlZ3JlZXNcbiAgICBdO1xufVxuXG5mdW5jdGlvbiBjYXJ0ZXNpYW4oc3BoZXJpY2FsKSB7XG4gICAgdmFyIGxhbWJkYSA9IHNwaGVyaWNhbFswXSAqIHJhZGlhbnM7XG4gICAgdmFyIHBoaSA9IHNwaGVyaWNhbFsxXSAqIHJhZGlhbnM7XG4gICAgdmFyIGNvc1BoaSA9IE1hdGguY29zKHBoaSk7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgY29zUGhpICogTWF0aC5jb3MobGFtYmRhKSxcbiAgICAgICAgY29zUGhpICogTWF0aC5zaW4obGFtYmRhKSxcbiAgICAgICAgTWF0aC5zaW4ocGhpKVxuICAgIF07XG59XG5cbmZ1bmN0aW9uIGRvdChhLCBiKSB7XG4gICAgdmFyIHMgPSAwO1xuICAgIGZvcih2YXIgaSA9IDAsIG4gPSBhLmxlbmd0aDsgaSA8IG47ICsraSkgcyArPSBhW2ldICogYltpXTtcbiAgICByZXR1cm4gcztcbn1cblxuZnVuY3Rpb24gY3Jvc3MoYSwgYikge1xuICAgIHJldHVybiBbXG4gICAgICAgIGFbMV0gKiBiWzJdIC0gYVsyXSAqIGJbMV0sXG4gICAgICAgIGFbMl0gKiBiWzBdIC0gYVswXSAqIGJbMl0sXG4gICAgICAgIGFbMF0gKiBiWzFdIC0gYVsxXSAqIGJbMF1cbiAgICBdO1xufVxuXG4vLyBMaWtlIGQzLmRpc3BhdGNoLCBidXQgZm9yIGN1c3RvbSBldmVudHMgYWJzdHJhY3RpbmcgbmF0aXZlIFVJIGV2ZW50cy4gVGhlc2Vcbi8vIGV2ZW50cyBoYXZlIGEgdGFyZ2V0IGNvbXBvbmVudCAoc3VjaCBhcyBhIGJydXNoKSwgYSB0YXJnZXQgZWxlbWVudCAoc3VjaCBhc1xuLy8gdGhlIHN2ZzpnIGVsZW1lbnQgY29udGFpbmluZyB0aGUgYnJ1c2gpIGFuZCB0aGUgc3RhbmRhcmQgYXJndW1lbnRzIGBkYCAodGhlXG4vLyB0YXJnZXQgZWxlbWVudCdzIGRhdGEpIGFuZCBgaWAgKHRoZSBzZWxlY3Rpb24gaW5kZXggb2YgdGhlIHRhcmdldCBlbGVtZW50KS5cbmZ1bmN0aW9uIGQzZXZlbnREaXNwYXRjaCh0YXJnZXQpIHtcbiAgICB2YXIgaSA9IDA7XG4gICAgdmFyIG4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIHZhciBhcmd1bWVudHogPSBbXTtcblxuICAgIHdoaWxlKCsraSA8IG4pIGFyZ3VtZW50ei5wdXNoKGFyZ3VtZW50c1tpXSk7XG5cbiAgICB2YXIgZGlzcGF0Y2ggPSBkMy5kaXNwYXRjaC5hcHBseShudWxsLCBhcmd1bWVudHopO1xuXG4gICAgLy8gQ3JlYXRlcyBhIGRpc3BhdGNoIGNvbnRleHQgZm9yIHRoZSBzcGVjaWZpZWQgYHRoaXpgICh0eXBpY2FsbHksIHRoZSB0YXJnZXRcbiAgICAvLyBET00gZWxlbWVudCB0aGF0IHJlY2VpdmVkIHRoZSBzb3VyY2UgZXZlbnQpIGFuZCBgYXJndW1lbnR6YCAodHlwaWNhbGx5LCB0aGVcbiAgICAvLyBkYXRhIGBkYCBhbmQgaW5kZXggYGlgIG9mIHRoZSB0YXJnZXQgZWxlbWVudCkuIFRoZSByZXR1cm5lZCBmdW5jdGlvbiBjYW4gYmVcbiAgICAvLyB1c2VkIHRvIGRpc3BhdGNoIGFuIGV2ZW50IHRvIGFueSByZWdpc3RlcmVkIGxpc3RlbmVyczsgdGhlIGZ1bmN0aW9uIHRha2VzIGFcbiAgICAvLyBzaW5nbGUgYXJndW1lbnQgYXMgaW5wdXQsIGJlaW5nIHRoZSBldmVudCB0byBkaXNwYXRjaC4gVGhlIGV2ZW50IG11c3QgaGF2ZVxuICAgIC8vIGEgXCJ0eXBlXCIgYXR0cmlidXRlIHdoaWNoIGNvcnJlc3BvbmRzIHRvIGEgdHlwZSByZWdpc3RlcmVkIGluIHRoZVxuICAgIC8vIGNvbnN0cnVjdG9yLiBUaGlzIGNvbnRleHQgd2lsbCBhdXRvbWF0aWNhbGx5IHBvcHVsYXRlIHRoZSBcInNvdXJjZUV2ZW50XCIgYW5kXG4gICAgLy8gXCJ0YXJnZXRcIiBhdHRyaWJ1dGVzIG9mIHRoZSBldmVudCwgYXMgd2VsbCBhcyBzZXR0aW5nIHRoZSBgZDMuZXZlbnRgIGdsb2JhbFxuICAgIC8vIGZvciB0aGUgZHVyYXRpb24gb2YgdGhlIG5vdGlmaWNhdGlvbi5cbiAgICBkaXNwYXRjaC5vZiA9IGZ1bmN0aW9uKHRoaXosIGFyZ3VtZW50eikge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oZTEpIHtcbiAgICAgICAgICAgIHZhciBlMDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgZTAgPSBlMS5zb3VyY2VFdmVudCA9IGQzLmV2ZW50O1xuICAgICAgICAgICAgICAgIGUxLnRhcmdldCA9IHRhcmdldDtcbiAgICAgICAgICAgICAgICBkMy5ldmVudCA9IGUxO1xuICAgICAgICAgICAgICAgIGRpc3BhdGNoW2UxLnR5cGVdLmFwcGx5KHRoaXosIGFyZ3VtZW50eik7XG4gICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIGQzLmV2ZW50ID0gZTA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIHJldHVybiBkaXNwYXRjaDtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcImQzXCI6MTYzfV0sODAyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vcmVnaXN0cnknKTtcbnZhciBTVUJQTE9UX1BBVFRFUk4gPSBfZGVyZXFfKCcuL2NhcnRlc2lhbi9jb25zdGFudHMnKS5TVUJQTE9UX1BBVFRFUk47XG5cbi8qKlxuICogR2V0IGNhbGNkYXRhIHRyYWNlKHMpIGFzc29jaWF0ZWQgd2l0aCBhIGdpdmVuIHN1YnBsb3RcbiAqXG4gKiBAcGFyYW0ge2FycmF5fSBjYWxjRGF0YTogYXMgaW4gZ2QuY2FsY2RhdGFcbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlOiBzdWJwbG90IHR5cGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdWJwbG90SWQ6IHN1YnBsb3QgaWQgdG8gbG9vayBmb3JcbiAqXG4gKiBAcmV0dXJuIHthcnJheX0gYXJyYXkgb2YgY2FsY2RhdGEgdHJhY2VzXG4gKi9cbmV4cG9ydHMuZ2V0U3VicGxvdENhbGNEYXRhID0gZnVuY3Rpb24oY2FsY0RhdGEsIHR5cGUsIHN1YnBsb3RJZCkge1xuICAgIHZhciBiYXNlUGxvdE1vZHVsZSA9IFJlZ2lzdHJ5LnN1YnBsb3RzUmVnaXN0cnlbdHlwZV07XG4gICAgaWYoIWJhc2VQbG90TW9kdWxlKSByZXR1cm4gW107XG5cbiAgICB2YXIgYXR0ciA9IGJhc2VQbG90TW9kdWxlLmF0dHI7XG4gICAgdmFyIHN1YnBsb3RDYWxjRGF0YSA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjVHJhY2UgPSBjYWxjRGF0YVtpXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuXG4gICAgICAgIGlmKHRyYWNlW2F0dHJdID09PSBzdWJwbG90SWQpIHN1YnBsb3RDYWxjRGF0YS5wdXNoKGNhbGNUcmFjZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1YnBsb3RDYWxjRGF0YTtcbn07XG4vKipcbiAqIEdldCBjYWxjZGF0YSB0cmFjZShzKSB0aGF0IGNhbiBiZSBwbG90dGVkIHdpdGggYSBnaXZlbiBtb2R1bGVcbiAqIE5PVEU6IHRoaXMgaXNuJ3QgbmVjZXNzYXJpbHkganVzdCBleGFjdGx5IG1hdGNoaW5nIHRyYWNlIHR5cGUsXG4gKiBpZiBtdWx0aXBsZSB0cmFjZSB0eXBlcyB1c2UgdGhlIHNhbWUgcGxvdHRpbmcgcm91dGluZSwgdGhleSB3aWxsIGJlXG4gKiBjb2xsZWN0ZWQgaGVyZS5cbiAqIEluIG9yZGVyIHRvIG5vdCBwbG90IHRoZSBzYW1lIHRoaW5nIG11bHRpcGxlIHRpbWVzLCB3ZSByZXR1cm4gdHdvIGFycmF5cyxcbiAqIHRoZSBjYWxjZGF0YSB3ZSAqd2lsbCogcGxvdCB3aXRoIHRoaXMgbW9kdWxlLCBhbmQgdGhlIG9uZXMgd2UgKndvbid0KlxuICpcbiAqIEBwYXJhbSB7YXJyYXl9IGNhbGNkYXRhOiBhcyBpbiBnZC5jYWxjZGF0YVxuICogQHBhcmFtIHtvYmplY3R8c3RyaW5nfGZufSBhcmcxOlxuICogIHRoZSBwbG90dGluZyBtb2R1bGUsIG9yIGl0cyBuYW1lLCBvciBpdHMgcGxvdCBtZXRob2RcbiAqXG4gKiBAcmV0dXJuIHthcnJheVthcnJheV19IFtmb3VuZENhbGNkYXRhLCByZW1haW5pbmdDYWxjZGF0YV1cbiAqL1xuZXhwb3J0cy5nZXRNb2R1bGVDYWxjRGF0YSA9IGZ1bmN0aW9uKGNhbGNkYXRhLCBhcmcxKSB7XG4gICAgdmFyIG1vZHVsZUNhbGNEYXRhID0gW107XG4gICAgdmFyIHJlbWFpbmluZ0NhbGNEYXRhID0gW107XG5cbiAgICB2YXIgcGxvdE1ldGhvZDtcbiAgICBpZih0eXBlb2YgYXJnMSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcGxvdE1ldGhvZCA9IFJlZ2lzdHJ5LmdldE1vZHVsZShhcmcxKS5wbG90O1xuICAgIH0gZWxzZSBpZih0eXBlb2YgYXJnMSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwbG90TWV0aG9kID0gYXJnMTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwbG90TWV0aG9kID0gYXJnMS5wbG90O1xuICAgIH1cbiAgICBpZighcGxvdE1ldGhvZCkge1xuICAgICAgICByZXR1cm4gW21vZHVsZUNhbGNEYXRhLCBjYWxjZGF0YV07XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjZCA9IGNhbGNkYXRhW2ldO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICAgICAgLy8gTi5CLlxuICAgICAgICAvLyAtICdsZWdlbmRvbmx5JyB0cmFjZXMgZG8gbm90IG1ha2UgaXQgcGFzdCBoZXJlXG4gICAgICAgIC8vIC0gc2tpcCBvdmVyICd2aXNpYmxlJyB0cmFjZXMgdGhhdCBnb3QgdHJpbW1lZCBjb21wbGV0ZWx5IGR1cmluZyBjYWxjIHRyYW5zZm9ybXNcbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSAhPT0gdHJ1ZSB8fCB0cmFjZS5fbGVuZ3RoID09PSAwKSBjb250aW51ZTtcblxuICAgICAgICAvLyBncm91cCBjYWxjZGF0YSB0cmFjZSBub3QgYnkgJ21vZHVsZScgKGFzIHRoZSBuYW1lIG9mIHRoaXMgZnVuY3Rpb25cbiAgICAgICAgLy8gd291bGQgc3VnZ2VzdCksIGJ1dCBieSAnbW9kdWxlIHBsb3QgbWV0aG9kJyBzbyB0aGF0IGlmIHNvbWUgdHJhY2VzXG4gICAgICAgIC8vIHNoYXJlIHRoZSBzYW1lIG1vZHVsZSBwbG90IG1ldGhvZCAoZS5nLiBiYXIgYW5kIGhpc3RvZ3JhbSksIHdlXG4gICAgICAgIC8vIG9ubHkgY2FsbCBpdCBvbmUhXG4gICAgICAgIGlmKHRyYWNlLl9tb2R1bGUucGxvdCA9PT0gcGxvdE1ldGhvZCkge1xuICAgICAgICAgICAgbW9kdWxlQ2FsY0RhdGEucHVzaChjZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZW1haW5pbmdDYWxjRGF0YS5wdXNoKGNkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBbbW9kdWxlQ2FsY0RhdGEsIHJlbWFpbmluZ0NhbGNEYXRhXTtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBkYXRhIHRyYWNlKHMpIGFzc29jaWF0ZWQgd2l0aCBhIGdpdmVuIHN1YnBsb3QuXG4gKlxuICogQHBhcmFtIHthcnJheX0gZGF0YSAgcGxvdGx5IGZ1bGwgZGF0YSBhcnJheS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIHN1YnBsb3QgdHlwZSB0byBsb29rIGZvci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzdWJwbG90SWQgc3VicGxvdCBpZCB0byBsb29rIGZvci5cbiAqXG4gKiBAcmV0dXJuIHthcnJheX0gbGlzdCBvZiB0cmFjZSBvYmplY3RzLlxuICpcbiAqL1xuZXhwb3J0cy5nZXRTdWJwbG90RGF0YSA9IGZ1bmN0aW9uIGdldFN1YnBsb3REYXRhKGRhdGEsIHR5cGUsIHN1YnBsb3RJZCkge1xuICAgIGlmKCFSZWdpc3RyeS5zdWJwbG90c1JlZ2lzdHJ5W3R5cGVdKSByZXR1cm4gW107XG5cbiAgICB2YXIgYXR0ciA9IFJlZ2lzdHJ5LnN1YnBsb3RzUmVnaXN0cnlbdHlwZV0uYXR0cjtcbiAgICB2YXIgc3VicGxvdERhdGEgPSBbXTtcbiAgICB2YXIgdHJhY2UsIHN1YnBsb3RYLCBzdWJwbG90WTtcblxuICAgIGlmKHR5cGUgPT09ICdnbDJkJykge1xuICAgICAgICB2YXIgc3BtYXRjaCA9IHN1YnBsb3RJZC5tYXRjaChTVUJQTE9UX1BBVFRFUk4pO1xuICAgICAgICBzdWJwbG90WCA9ICd4JyArIHNwbWF0Y2hbMV07XG4gICAgICAgIHN1YnBsb3RZID0gJ3knICsgc3BtYXRjaFsyXTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB0cmFjZSA9IGRhdGFbaV07XG5cbiAgICAgICAgaWYodHlwZSA9PT0gJ2dsMmQnICYmIFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdnbDJkJykpIHtcbiAgICAgICAgICAgIGlmKHRyYWNlW2F0dHJbMF1dID09PSBzdWJwbG90WCAmJiB0cmFjZVthdHRyWzFdXSA9PT0gc3VicGxvdFkpIHtcbiAgICAgICAgICAgICAgICBzdWJwbG90RGF0YS5wdXNoKHRyYWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKHRyYWNlW2F0dHJdID09PSBzdWJwbG90SWQpIHN1YnBsb3REYXRhLnB1c2godHJhY2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1YnBsb3REYXRhO1xufTtcblxufSx7XCIuLi9yZWdpc3RyeVwiOjg0NyxcIi4vY2FydGVzaWFuL2NvbnN0YW50c1wiOjc3M31dLDgwMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG1vdXNlQ2hhbmdlID0gX2RlcmVxXygnbW91c2UtY2hhbmdlJyk7XG52YXIgbW91c2VXaGVlbCA9IF9kZXJlcV8oJ21vdXNlLXdoZWVsJyk7XG52YXIgbW91c2VPZmZzZXQgPSBfZGVyZXFfKCdtb3VzZS1ldmVudC1vZmZzZXQnKTtcbnZhciBjYXJ0ZXNpYW5Db25zdGFudHMgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vY29uc3RhbnRzJyk7XG52YXIgaGFzUGFzc2l2ZSA9IF9kZXJlcV8oJ2hhcy1wYXNzaXZlLWV2ZW50cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUNhbWVyYTtcblxuZnVuY3Rpb24gQ2FtZXJhMkQoZWxlbWVudCwgcGxvdCkge1xuICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgdGhpcy5wbG90ID0gcGxvdDtcbiAgICB0aGlzLm1vdXNlTGlzdGVuZXIgPSBudWxsO1xuICAgIHRoaXMud2hlZWxMaXN0ZW5lciA9IG51bGw7XG4gICAgdGhpcy5sYXN0SW5wdXRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICB0aGlzLmxhc3RQb3MgPSBbMCwgMF07XG4gICAgdGhpcy5ib3hFbmFibGVkID0gZmFsc2U7XG4gICAgdGhpcy5ib3hJbml0ZWQgPSBmYWxzZTtcbiAgICB0aGlzLmJveFN0YXJ0ID0gWzAsIDBdO1xuICAgIHRoaXMuYm94RW5kID0gWzAsIDBdO1xuICAgIHRoaXMuZHJhZ1N0YXJ0ID0gWzAsIDBdO1xufVxuXG5cbmZ1bmN0aW9uIGNyZWF0ZUNhbWVyYShzY2VuZSkge1xuICAgIHZhciBlbGVtZW50ID0gc2NlbmUubW91c2VDb250YWluZXI7XG4gICAgdmFyIHBsb3QgPSBzY2VuZS5nbHBsb3Q7XG4gICAgdmFyIHJlc3VsdCA9IG5ldyBDYW1lcmEyRChlbGVtZW50LCBwbG90KTtcblxuICAgIGZ1bmN0aW9uIHVuU2V0QXV0b1JhbmdlKCkge1xuICAgICAgICBzY2VuZS54YXhpcy5hdXRvcmFuZ2UgPSBmYWxzZTtcbiAgICAgICAgc2NlbmUueWF4aXMuYXV0b3JhbmdlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U3VicGxvdENvbnN0cmFpbnQoKSB7XG4gICAgICAgIC8vIG5vdGU6IHRoaXMgYXNzdW1lcyB3ZSBvbmx5IGhhdmUgb25lIHggYW5kIG9uZSB5IGF4aXMgb24gdGhpcyBzdWJwbG90XG4gICAgICAgIC8vIHdoZW4gdGhpcyBjb25zdHJhaW50IGlzIGxpZnRlZCB0aGlzIGJsb2NrIHdvbid0IG1ha2Ugc2Vuc2VcbiAgICAgICAgdmFyIGNvbnN0cmFpbnRzID0gc2NlbmUuZ3JhcGhEaXYuX2Z1bGxMYXlvdXQuX2F4aXNDb25zdHJhaW50R3JvdXBzO1xuICAgICAgICB2YXIgeGFJZCA9IHNjZW5lLnhheGlzLl9pZDtcbiAgICAgICAgdmFyIHlhSWQgPSBzY2VuZS55YXhpcy5faWQ7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjb25zdHJhaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoY29uc3RyYWludHNbaV1beGFJZF0gIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgaWYoY29uc3RyYWludHNbaV1beWFJZF0gIT09IC0xKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmVzdWx0Lm1vdXNlTGlzdGVuZXIgPSBtb3VzZUNoYW5nZShlbGVtZW50LCBoYW5kbGVJbnRlcmFjdGlvbik7XG5cbiAgICAvLyBlbmFibGUgc2ltcGxlIHRvdWNoIGludGVyYWN0aW9uc1xuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIHZhciB4eSA9IG1vdXNlT2Zmc2V0KGV2LmNoYW5nZWRUb3VjaGVzWzBdLCBlbGVtZW50KTtcbiAgICAgICAgaGFuZGxlSW50ZXJhY3Rpb24oMCwgeHlbMF0sIHh5WzFdKTtcbiAgICAgICAgaGFuZGxlSW50ZXJhY3Rpb24oMSwgeHlbMF0sIHh5WzFdKTtcblxuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0sIGhhc1Bhc3NpdmUgPyB7cGFzc2l2ZTogZmFsc2V9IDogZmFsc2UpO1xuICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdmFyIHh5ID0gbW91c2VPZmZzZXQoZXYuY2hhbmdlZFRvdWNoZXNbMF0sIGVsZW1lbnQpO1xuICAgICAgICBoYW5kbGVJbnRlcmFjdGlvbigxLCB4eVswXSwgeHlbMV0pO1xuXG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSwgaGFzUGFzc2l2ZSA/IHtwYXNzaXZlOiBmYWxzZX0gOiBmYWxzZSk7XG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGVuZCcsIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIGhhbmRsZUludGVyYWN0aW9uKDAsIHJlc3VsdC5sYXN0UG9zWzBdLCByZXN1bHQubGFzdFBvc1sxXSk7XG5cbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICB9LCBoYXNQYXNzaXZlID8ge3Bhc3NpdmU6IGZhbHNlfSA6IGZhbHNlKTtcblxuICAgIGZ1bmN0aW9uIGhhbmRsZUludGVyYWN0aW9uKGJ1dHRvbnMsIHgsIHkpIHtcbiAgICAgICAgdmFyIGRhdGFCb3ggPSBzY2VuZS5jYWxjRGF0YUJveCgpO1xuICAgICAgICB2YXIgdmlld0JveCA9IHBsb3Qudmlld0JveDtcblxuICAgICAgICB2YXIgbGFzdFggPSByZXN1bHQubGFzdFBvc1swXTtcbiAgICAgICAgdmFyIGxhc3RZID0gcmVzdWx0Lmxhc3RQb3NbMV07XG5cbiAgICAgICAgdmFyIE1JTkRSQUcgPSBjYXJ0ZXNpYW5Db25zdGFudHMuTUlORFJBRyAqIHBsb3QucGl4ZWxSYXRpbztcbiAgICAgICAgdmFyIE1JTlpPT00gPSBjYXJ0ZXNpYW5Db25zdGFudHMuTUlOWk9PTSAqIHBsb3QucGl4ZWxSYXRpbztcblxuICAgICAgICB2YXIgZHgsIGR5O1xuXG4gICAgICAgIHggKj0gcGxvdC5waXhlbFJhdGlvO1xuICAgICAgICB5ICo9IHBsb3QucGl4ZWxSYXRpbztcblxuICAgICAgICAvLyBtb3VzZUNoYW5nZSBnaXZlcyB5IGFib3V0IHRvcDsgY29udmVydCB0byBhYm91dCBib3R0b21cbiAgICAgICAgeSA9ICh2aWV3Qm94WzNdIC0gdmlld0JveFsxXSkgLSB5O1xuXG4gICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVJhbmdlKGkwLCBzdGFydCwgZW5kKSB7XG4gICAgICAgICAgICB2YXIgcmFuZ2UwID0gTWF0aC5taW4oc3RhcnQsIGVuZCk7XG4gICAgICAgICAgICB2YXIgcmFuZ2UxID0gTWF0aC5tYXgoc3RhcnQsIGVuZCk7XG5cbiAgICAgICAgICAgIGlmKHJhbmdlMCAhPT0gcmFuZ2UxKSB7XG4gICAgICAgICAgICAgICAgZGF0YUJveFtpMF0gPSByYW5nZTA7XG4gICAgICAgICAgICAgICAgZGF0YUJveFtpMCArIDJdID0gcmFuZ2UxO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5kYXRhQm94ID0gZGF0YUJveDtcbiAgICAgICAgICAgICAgICBzY2VuZS5zZXRSYW5nZXMoZGF0YUJveCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNjZW5lLnNlbGVjdEJveC5zZWxlY3RCb3ggPSBbMCwgMCwgMSwgMV07XG4gICAgICAgICAgICAgICAgc2NlbmUuZ2xwbG90LnNldERpcnR5KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2goc2NlbmUuZnVsbExheW91dC5kcmFnbW9kZSkge1xuICAgICAgICAgICAgY2FzZSAnem9vbSc6XG4gICAgICAgICAgICAgICAgaWYoYnV0dG9ucykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGF0YVggPSB4IC9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAodmlld0JveFsyXSAtIHZpZXdCb3hbMF0pICogKGRhdGFCb3hbMl0gLSBkYXRhQm94WzBdKSArXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhQm94WzBdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGF0YVkgPSB5IC9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAodmlld0JveFszXSAtIHZpZXdCb3hbMV0pICogKGRhdGFCb3hbM10gLSBkYXRhQm94WzFdKSArXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhQm94WzFdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKCFyZXN1bHQuYm94SW5pdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94U3RhcnRbMF0gPSBkYXRhWDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hTdGFydFsxXSA9IGRhdGFZO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmRyYWdTdGFydFswXSA9IHg7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZHJhZ1N0YXJ0WzFdID0geTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmRbMF0gPSBkYXRhWDtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuZFsxXSA9IGRhdGFZO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHdlIG5lZWQgdG8gbWFyayB0aGUgYm94IGFzIGluaXRpYWxpemVkIHJpZ2h0IGF3YXlcbiAgICAgICAgICAgICAgICAgICAgLy8gc28gdGhhdCB3ZSBjYW4gdGVsbCB0aGUgc3RhcnQgYW5kIGVuZCBwb2ludHMgYXBhcnRcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEluaXRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gYnV0IGRvbid0IGFjdHVhbGx5IGVuYWJsZSB0aGUgYm94IHVudGlsIHRoZSBjdXJzb3IgbW92ZXNcbiAgICAgICAgICAgICAgICAgICAgaWYoIXJlc3VsdC5ib3hFbmFibGVkICYmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hTdGFydFswXSAhPT0gcmVzdWx0LmJveEVuZFswXSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveFN0YXJ0WzFdICE9PSByZXN1bHQuYm94RW5kWzFdKVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnN0cmFpbiBhc3BlY3QgcmF0aW8gaWYgdGhlIGF4ZXMgcmVxdWlyZSBpdFxuICAgICAgICAgICAgICAgICAgICB2YXIgc21hbGxEeCA9IE1hdGguYWJzKHJlc3VsdC5kcmFnU3RhcnRbMF0gLSB4KSA8IE1JTlpPT007XG4gICAgICAgICAgICAgICAgICAgIHZhciBzbWFsbER5ID0gTWF0aC5hYnMocmVzdWx0LmRyYWdTdGFydFsxXSAtIHkpIDwgTUlOWk9PTTtcbiAgICAgICAgICAgICAgICAgICAgaWYoZ2V0U3VicGxvdENvbnN0cmFpbnQoKSAmJiAhKHNtYWxsRHggJiYgc21hbGxEeSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGR4ID0gcmVzdWx0LmJveEVuZFswXSAtIHJlc3VsdC5ib3hTdGFydFswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGR5ID0gcmVzdWx0LmJveEVuZFsxXSAtIHJlc3VsdC5ib3hTdGFydFsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkeWR4ID0gKGRhdGFCb3hbM10gLSBkYXRhQm94WzFdKSAvIChkYXRhQm94WzJdIC0gZGF0YUJveFswXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKE1hdGguYWJzKGR4ICogZHlkeCkgPiBNYXRoLmFicyhkeSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94RW5kWzFdID0gcmVzdWx0LmJveFN0YXJ0WzFdICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5hYnMoZHgpICogZHlkeCAqIChkeSA+PSAwID8gMSA6IC0xKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGdsLXNlbGVjdC1ib3ggY2xpcHMgdG8gdGhlIHBsb3QgYXJlYSBib3VuZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2hpY2ggYnJlYWtzIHRoZSBheGlzIGNvbnN0cmFpbnQsIHNvIGRvbid0IGFsbG93XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBib3ggdG8gZ28gb3V0IG9mIGJvdW5kc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKHJlc3VsdC5ib3hFbmRbMV0gPCBkYXRhQm94WzFdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmRbMV0gPSBkYXRhQm94WzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94RW5kWzBdID0gcmVzdWx0LmJveFN0YXJ0WzBdICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChkYXRhQm94WzFdIC0gcmVzdWx0LmJveFN0YXJ0WzFdKSAvIE1hdGguYWJzKGR5ZHgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihyZXN1bHQuYm94RW5kWzFdID4gZGF0YUJveFszXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94RW5kWzFdID0gZGF0YUJveFszXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuZFswXSA9IHJlc3VsdC5ib3hTdGFydFswXSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGF0YUJveFszXSAtIHJlc3VsdC5ib3hTdGFydFsxXSkgLyBNYXRoLmFicyhkeWR4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmRbMF0gPSByZXN1bHQuYm94U3RhcnRbMF0gK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYXRoLmFicyhkeSkgLyBkeWR4ICogKGR4ID49IDAgPyAxIDogLTEpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVzdWx0LmJveEVuZFswXSA8IGRhdGFCb3hbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuZFswXSA9IGRhdGFCb3hbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmRbMV0gPSByZXN1bHQuYm94U3RhcnRbMV0gK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGRhdGFCb3hbMF0gLSByZXN1bHQuYm94U3RhcnRbMF0pICogTWF0aC5hYnMoZHlkeCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHJlc3VsdC5ib3hFbmRbMF0gPiBkYXRhQm94WzJdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmRbMF0gPSBkYXRhQm94WzJdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94RW5kWzFdID0gcmVzdWx0LmJveFN0YXJ0WzFdICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChkYXRhQm94WzJdIC0gcmVzdWx0LmJveFN0YXJ0WzBdKSAqIE1hdGguYWJzKGR5ZHgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG90aGVyd2lzZSBjbGFtcCBzbWFsbCBjaGFuZ2VzIHRvIHRoZSBvcmlnaW4gc28gd2UgZ2V0IDFEIHpvb21cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoc21hbGxEeCkgcmVzdWx0LmJveEVuZFswXSA9IHJlc3VsdC5ib3hTdGFydFswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHNtYWxsRHkpIHJlc3VsdC5ib3hFbmRbMV0gPSByZXN1bHQuYm94U3RhcnRbMV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYocmVzdWx0LmJveEVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZHggPSByZXN1bHQuYm94U3RhcnRbMF0gIT09IHJlc3VsdC5ib3hFbmRbMF07XG4gICAgICAgICAgICAgICAgICAgIGR5ID0gcmVzdWx0LmJveFN0YXJ0WzFdICE9PSByZXN1bHQuYm94RW5kWzFdO1xuICAgICAgICAgICAgICAgICAgICBpZihkeCB8fCBkeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoZHgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVSYW5nZSgwLCByZXN1bHQuYm94U3RhcnRbMF0sIHJlc3VsdC5ib3hFbmRbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjZW5lLnhheGlzLmF1dG9yYW5nZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoZHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVSYW5nZSgxLCByZXN1bHQuYm94U3RhcnRbMV0sIHJlc3VsdC5ib3hFbmRbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjZW5lLnlheGlzLmF1dG9yYW5nZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgc2NlbmUucmVsYXlvdXRDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2NlbmUuZ2xwbG90LnNldERpcnR5KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmJveEluaXRlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihyZXN1bHQuYm94SW5pdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIGJveCB3YXMgaW5pdGVkIGJ1dCBidXR0b24gcmVsZWFzZWQgdGhlbiAtIHJlc2V0IHRoZSBib3hcblxuICAgICAgICAgICAgICAgICAgICByZXN1bHQuYm94SW5pdGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlICdwYW4nOlxuICAgICAgICAgICAgICAgIHJlc3VsdC5ib3hFbmFibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmVzdWx0LmJveEluaXRlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYoYnV0dG9ucykge1xuICAgICAgICAgICAgICAgICAgICBpZighcmVzdWx0LnBhbm5pbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5kcmFnU3RhcnRbMF0gPSB4O1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmRyYWdTdGFydFsxXSA9IHk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZihNYXRoLmFicyhyZXN1bHQuZHJhZ1N0YXJ0WzBdIC0geCkgPCBNSU5EUkFHKSB4ID0gcmVzdWx0LmRyYWdTdGFydFswXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMocmVzdWx0LmRyYWdTdGFydFsxXSAtIHkpIDwgTUlORFJBRykgeSA9IHJlc3VsdC5kcmFnU3RhcnRbMV07XG5cbiAgICAgICAgICAgICAgICAgICAgZHggPSAobGFzdFggLSB4KSAqIChkYXRhQm94WzJdIC0gZGF0YUJveFswXSkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgKHBsb3Qudmlld0JveFsyXSAtIHBsb3Qudmlld0JveFswXSk7XG4gICAgICAgICAgICAgICAgICAgIGR5ID0gKGxhc3RZIC0geSkgKiAoZGF0YUJveFszXSAtIGRhdGFCb3hbMV0pIC9cbiAgICAgICAgICAgICAgICAgICAgICAgIChwbG90LnZpZXdCb3hbM10gLSBwbG90LnZpZXdCb3hbMV0pO1xuXG4gICAgICAgICAgICAgICAgICAgIGRhdGFCb3hbMF0gKz0gZHg7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFCb3hbMl0gKz0gZHg7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFCb3hbMV0gKz0gZHk7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFCb3hbM10gKz0gZHk7XG5cbiAgICAgICAgICAgICAgICAgICAgc2NlbmUuc2V0UmFuZ2VzKGRhdGFCb3gpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wYW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0Lmxhc3RJbnB1dFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgICB1blNldEF1dG9SYW5nZSgpO1xuICAgICAgICAgICAgICAgICAgICBzY2VuZS5jYW1lcmFDaGFuZ2VkKCk7XG4gICAgICAgICAgICAgICAgICAgIHNjZW5lLmhhbmRsZUFubm90YXRpb25zKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHJlc3VsdC5wYW5uaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wYW5uaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHNjZW5lLnJlbGF5b3V0Q2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICByZXN1bHQubGFzdFBvc1swXSA9IHg7XG4gICAgICAgIHJlc3VsdC5sYXN0UG9zWzFdID0geTtcbiAgICB9XG5cbiAgICByZXN1bHQud2hlZWxMaXN0ZW5lciA9IG1vdXNlV2hlZWwoZWxlbWVudCwgZnVuY3Rpb24oZHgsIGR5KSB7XG4gICAgICAgIGlmKCFzY2VuZS5zY3JvbGxab29tKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgdmFyIGRhdGFCb3ggPSBzY2VuZS5jYWxjRGF0YUJveCgpO1xuICAgICAgICB2YXIgdmlld0JveCA9IHBsb3Qudmlld0JveDtcblxuICAgICAgICB2YXIgbGFzdFggPSByZXN1bHQubGFzdFBvc1swXTtcbiAgICAgICAgdmFyIGxhc3RZID0gcmVzdWx0Lmxhc3RQb3NbMV07XG5cbiAgICAgICAgdmFyIHNjYWxlID0gTWF0aC5leHAoNS4wICogZHkgLyAodmlld0JveFszXSAtIHZpZXdCb3hbMV0pKTtcblxuICAgICAgICB2YXIgY3ggPSBsYXN0WCAvXG4gICAgICAgICAgICAgICAgKHZpZXdCb3hbMl0gLSB2aWV3Qm94WzBdKSAqIChkYXRhQm94WzJdIC0gZGF0YUJveFswXSkgK1xuICAgICAgICAgICAgZGF0YUJveFswXTtcbiAgICAgICAgdmFyIGN5ID0gbGFzdFkgL1xuICAgICAgICAgICAgICAgICh2aWV3Qm94WzNdIC0gdmlld0JveFsxXSkgKiAoZGF0YUJveFszXSAtIGRhdGFCb3hbMV0pICtcbiAgICAgICAgICAgIGRhdGFCb3hbMV07XG5cbiAgICAgICAgZGF0YUJveFswXSA9IChkYXRhQm94WzBdIC0gY3gpICogc2NhbGUgKyBjeDtcbiAgICAgICAgZGF0YUJveFsyXSA9IChkYXRhQm94WzJdIC0gY3gpICogc2NhbGUgKyBjeDtcbiAgICAgICAgZGF0YUJveFsxXSA9IChkYXRhQm94WzFdIC0gY3kpICogc2NhbGUgKyBjeTtcbiAgICAgICAgZGF0YUJveFszXSA9IChkYXRhQm94WzNdIC0gY3kpICogc2NhbGUgKyBjeTtcblxuICAgICAgICBzY2VuZS5zZXRSYW5nZXMoZGF0YUJveCk7XG5cbiAgICAgICAgcmVzdWx0Lmxhc3RJbnB1dFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB1blNldEF1dG9SYW5nZSgpO1xuICAgICAgICBzY2VuZS5jYW1lcmFDaGFuZ2VkKCk7XG4gICAgICAgIHNjZW5lLmhhbmRsZUFubm90YXRpb25zKCk7XG4gICAgICAgIHNjZW5lLnJlbGF5b3V0Q2FsbGJhY2soKTtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9LCB0cnVlKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbn0se1wiLi4vY2FydGVzaWFuL2NvbnN0YW50c1wiOjc3MyxcImhhcy1wYXNzaXZlLWV2ZW50c1wiOjQxMSxcIm1vdXNlLWNoYW5nZVwiOjQzNSxcIm1vdXNlLWV2ZW50LW9mZnNldFwiOjQzNixcIm1vdXNlLXdoZWVsXCI6NDM4fV0sODA0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9heGVzJyk7XG5cbnZhciBzdHIyUkdCQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3RyMnJnYmFycmF5Jyk7XG5cbmZ1bmN0aW9uIEF4ZXMyRE9wdGlvbnMoc2NlbmUpIHtcbiAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgdGhpcy5nbCA9IHNjZW5lLmdsO1xuICAgIHRoaXMucGl4ZWxSYXRpbyA9IHNjZW5lLnBpeGVsUmF0aW87XG5cbiAgICB0aGlzLnNjcmVlbkJveCA9IFswLCAwLCAxLCAxXTtcbiAgICB0aGlzLnZpZXdCb3ggPSBbMCwgMCwgMSwgMV07XG4gICAgdGhpcy5kYXRhQm94ID0gWy0xLCAtMSwgMSwgMV07XG5cbiAgICB0aGlzLmJvcmRlckxpbmVFbmFibGUgPSBbZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2VdO1xuICAgIHRoaXMuYm9yZGVyTGluZVdpZHRoID0gWzEsIDEsIDEsIDFdO1xuICAgIHRoaXMuYm9yZGVyTGluZUNvbG9yID0gW1xuICAgICAgICBbMCwgMCwgMCwgMV0sXG4gICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgWzAsIDAsIDAsIDFdLFxuICAgICAgICBbMCwgMCwgMCwgMV1cbiAgICBdO1xuXG4gICAgdGhpcy50aWNrcyA9IFtbXSwgW11dO1xuICAgIHRoaXMudGlja0VuYWJsZSA9IFt0cnVlLCB0cnVlLCBmYWxzZSwgZmFsc2VdO1xuICAgIHRoaXMudGlja1BhZCA9IFsxNSwgMTUsIDE1LCAxNV07XG4gICAgdGhpcy50aWNrQW5nbGUgPSBbMCwgMCwgMCwgMF07XG4gICAgdGhpcy50aWNrQ29sb3IgPSBbXG4gICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgWzAsIDAsIDAsIDFdLFxuICAgICAgICBbMCwgMCwgMCwgMV0sXG4gICAgICAgIFswLCAwLCAwLCAxXVxuICAgIF07XG4gICAgdGhpcy50aWNrTWFya0xlbmd0aCA9IFswLCAwLCAwLCAwXTtcbiAgICB0aGlzLnRpY2tNYXJrV2lkdGggPSBbMCwgMCwgMCwgMF07XG4gICAgdGhpcy50aWNrTWFya0NvbG9yID0gW1xuICAgICAgICBbMCwgMCwgMCwgMV0sXG4gICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgWzAsIDAsIDAsIDFdLFxuICAgICAgICBbMCwgMCwgMCwgMV1cbiAgICBdO1xuXG4gICAgdGhpcy5sYWJlbHMgPSBbJ3gnLCAneSddO1xuICAgIHRoaXMubGFiZWxFbmFibGUgPSBbdHJ1ZSwgdHJ1ZSwgZmFsc2UsIGZhbHNlXTtcbiAgICB0aGlzLmxhYmVsQW5nbGUgPSBbMCwgTWF0aC5QSSAvIDIsIDAsIDMuMCAqIE1hdGguUEkgLyAyXTtcbiAgICB0aGlzLmxhYmVsUGFkID0gWzE1LCAxNSwgMTUsIDE1XTtcbiAgICB0aGlzLmxhYmVsU2l6ZSA9IFsxMiwgMTJdO1xuICAgIHRoaXMubGFiZWxGb250ID0gWydzYW5zLXNlcmlmJywgJ3NhbnMtc2VyaWYnXTtcbiAgICB0aGlzLmxhYmVsQ29sb3IgPSBbXG4gICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgWzAsIDAsIDAsIDFdLFxuICAgICAgICBbMCwgMCwgMCwgMV0sXG4gICAgICAgIFswLCAwLCAwLCAxXVxuICAgIF07XG5cbiAgICB0aGlzLnRpdGxlID0gJyc7XG4gICAgdGhpcy50aXRsZUVuYWJsZSA9IHRydWU7XG4gICAgdGhpcy50aXRsZUNlbnRlciA9IFswLCAwLCAwLCAwXTtcbiAgICB0aGlzLnRpdGxlQW5nbGUgPSAwO1xuICAgIHRoaXMudGl0bGVDb2xvciA9IFswLCAwLCAwLCAxXTtcbiAgICB0aGlzLnRpdGxlRm9udCA9ICdzYW5zLXNlcmlmJztcbiAgICB0aGlzLnRpdGxlU2l6ZSA9IDE4O1xuXG4gICAgdGhpcy5ncmlkTGluZUVuYWJsZSA9IFt0cnVlLCB0cnVlXTtcbiAgICB0aGlzLmdyaWRMaW5lQ29sb3IgPSBbXG4gICAgICAgIFswLCAwLCAwLCAwLjVdLFxuICAgICAgICBbMCwgMCwgMCwgMC41XVxuICAgIF07XG4gICAgdGhpcy5ncmlkTGluZVdpZHRoID0gWzEsIDFdO1xuXG4gICAgdGhpcy56ZXJvTGluZUVuYWJsZSA9IFt0cnVlLCB0cnVlXTtcbiAgICB0aGlzLnplcm9MaW5lV2lkdGggPSBbMSwgMV07XG4gICAgdGhpcy56ZXJvTGluZUNvbG9yID0gW1xuICAgICAgICBbMCwgMCwgMCwgMV0sXG4gICAgICAgIFswLCAwLCAwLCAxXVxuICAgIF07XG5cbiAgICB0aGlzLmJvcmRlckNvbG9yID0gWzAsIDAsIDAsIDBdO1xuICAgIHRoaXMuYmFja2dyb3VuZENvbG9yID0gWzAsIDAsIDAsIDBdO1xuXG4gICAgdGhpcy5zdGF0aWMgPSB0aGlzLnNjZW5lLnN0YXRpY1Bsb3Q7XG59XG5cbnZhciBwcm90byA9IEF4ZXMyRE9wdGlvbnMucHJvdG90eXBlO1xuXG52YXIgQVhFUyA9IFsneGF4aXMnLCAneWF4aXMnXTtcblxucHJvdG8ubWVyZ2UgPSBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgLy8gdGl0bGVzIGFyZSByZW5kZXJlZCBpbiBTVkdcbiAgICB0aGlzLnRpdGxlRW5hYmxlID0gZmFsc2U7XG4gICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBzdHIyUkdCQXJyYXkob3B0aW9ucy5wbG90X2JnY29sb3IpO1xuXG4gICAgdmFyIGF4aXNOYW1lLCBheCwgYXhUaXRsZSwgYXhNaXJyb3I7XG4gICAgdmFyIGhhc0F4aXNJbkRmbHRQb3MsIGhhc0F4aXNJbkFsdHJQb3MsIGhhc1NoYXJlZEF4aXMsIG1pcnJvckxpbmVzLCBtaXJyb3JUaWNrcztcbiAgICB2YXIgaSwgajtcblxuICAgIGZvcihpID0gMDsgaSA8IDI7ICsraSkge1xuICAgICAgICBheGlzTmFtZSA9IEFYRVNbaV07XG4gICAgICAgIHZhciBheGlzTGV0dGVyID0gYXhpc05hbWUuY2hhckF0KDApO1xuXG4gICAgICAgIC8vIGdldCBvcHRpb25zIHJlbGV2YW50IHRvIHRoaXMgc3VicGxvdCxcbiAgICAgICAgLy8gJ19uYW1lJyBpcyBlLmcuIHhheGlzLCB4YXhpczIsIHlheGlzLCB5YXhpczQgLi4uXG4gICAgICAgIGF4ID0gb3B0aW9uc1t0aGlzLnNjZW5lW2F4aXNOYW1lXS5fbmFtZV07XG5cbiAgICAgICAgYXhUaXRsZSA9IGF4LnRpdGxlLnRleHQgPT09IHRoaXMuc2NlbmUuZnVsbExheW91dC5fZGZsdFRpdGxlW2F4aXNMZXR0ZXJdID8gJycgOiBheC50aXRsZS50ZXh0O1xuXG4gICAgICAgIGZvcihqID0gMDsgaiA8PSAyOyBqICs9IDIpIHtcbiAgICAgICAgICAgIHRoaXMubGFiZWxFbmFibGVbaSArIGpdID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmxhYmVsc1tpICsgal0gPSBheFRpdGxlO1xuICAgICAgICAgICAgdGhpcy5sYWJlbENvbG9yW2kgKyBqXSA9IHN0cjJSR0JBcnJheShheC50aXRsZS5mb250LmNvbG9yKTtcbiAgICAgICAgICAgIHRoaXMubGFiZWxGb250W2kgKyBqXSA9IGF4LnRpdGxlLmZvbnQuZmFtaWx5O1xuICAgICAgICAgICAgdGhpcy5sYWJlbFNpemVbaSArIGpdID0gYXgudGl0bGUuZm9udC5zaXplO1xuICAgICAgICAgICAgdGhpcy5sYWJlbFBhZFtpICsgal0gPSB0aGlzLmdldExhYmVsUGFkKGF4aXNOYW1lLCBheCk7XG5cbiAgICAgICAgICAgIHRoaXMudGlja0VuYWJsZVtpICsgal0gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMudGlja0NvbG9yW2kgKyBqXSA9IHN0cjJSR0JBcnJheSgoYXgudGlja2ZvbnQgfHwge30pLmNvbG9yKTtcbiAgICAgICAgICAgIHRoaXMudGlja0FuZ2xlW2kgKyBqXSA9IChheC50aWNrYW5nbGUgPT09ICdhdXRvJykgP1xuICAgICAgICAgICAgICAgIDAgOlxuICAgICAgICAgICAgICAgIE1hdGguUEkgKiAtYXgudGlja2FuZ2xlIC8gMTgwO1xuICAgICAgICAgICAgdGhpcy50aWNrUGFkW2kgKyBqXSA9IHRoaXMuZ2V0VGlja1BhZChheCk7XG5cbiAgICAgICAgICAgIHRoaXMudGlja01hcmtMZW5ndGhbaSArIGpdID0gMDtcbiAgICAgICAgICAgIHRoaXMudGlja01hcmtXaWR0aFtpICsgal0gPSBheC50aWNrd2lkdGggfHwgMDtcbiAgICAgICAgICAgIHRoaXMudGlja01hcmtDb2xvcltpICsgal0gPSBzdHIyUkdCQXJyYXkoYXgudGlja2NvbG9yKTtcblxuICAgICAgICAgICAgdGhpcy5ib3JkZXJMaW5lRW5hYmxlW2kgKyBqXSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ib3JkZXJMaW5lQ29sb3JbaSArIGpdID0gc3RyMlJHQkFycmF5KGF4LmxpbmVjb2xvcik7XG4gICAgICAgICAgICB0aGlzLmJvcmRlckxpbmVXaWR0aFtpICsgal0gPSBheC5saW5ld2lkdGggfHwgMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGhhc1NoYXJlZEF4aXMgPSB0aGlzLmhhc1NoYXJlZEF4aXMoYXgpO1xuICAgICAgICBoYXNBeGlzSW5EZmx0UG9zID0gdGhpcy5oYXNBeGlzSW5EZmx0UG9zKGF4aXNOYW1lLCBheCkgJiYgIWhhc1NoYXJlZEF4aXM7XG4gICAgICAgIGhhc0F4aXNJbkFsdHJQb3MgPSB0aGlzLmhhc0F4aXNJbkFsdHJQb3MoYXhpc05hbWUsIGF4KSAmJiAhaGFzU2hhcmVkQXhpcztcblxuICAgICAgICBheE1pcnJvciA9IGF4Lm1pcnJvciB8fCBmYWxzZTtcbiAgICAgICAgbWlycm9yTGluZXMgPSBoYXNTaGFyZWRBeGlzID9cbiAgICAgICAgICAgIChTdHJpbmcoYXhNaXJyb3IpLmluZGV4T2YoJ2FsbCcpICE9PSAtMSkgOiAgLy8gJ2FsbCcgb3IgJ2FsbHRpY2tzJ1xuICAgICAgICAgICAgISFheE1pcnJvcjsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhbGwgYnV0IGZhbHNlXG4gICAgICAgIG1pcnJvclRpY2tzID0gaGFzU2hhcmVkQXhpcyA/XG4gICAgICAgICAgICAoYXhNaXJyb3IgPT09ICdhbGx0aWNrcycpIDpcbiAgICAgICAgICAgIChTdHJpbmcoYXhNaXJyb3IpLmluZGV4T2YoJ3RpY2tzJykgIT09IC0xKTsgLy8gJ3RpY2tzJyBvciAnYWxsdGlja3MnXG5cbiAgICAgICAgLy8gQXhpcyB0aXRsZXMgYW5kIHRpY2sgbGFiZWxzIGNhbiBvbmx5IGFwcGVhciBvZiBvbmUgc2lkZSBvZiB0aGUgc2NlbmVcbiAgICAgICAgLy8gIGFuZCBhcmUgbmV2ZXIgc2hvdyBvbiBzdWJwbG90cyB0aGF0IHNoYXJlIGV4aXN0aW5nIGF4ZXMuXG5cbiAgICAgICAgaWYoaGFzQXhpc0luRGZsdFBvcykgdGhpcy5sYWJlbEVuYWJsZVtpXSA9IHRydWU7XG4gICAgICAgIGVsc2UgaWYoaGFzQXhpc0luQWx0clBvcykgdGhpcy5sYWJlbEVuYWJsZVtpICsgMl0gPSB0cnVlO1xuXG4gICAgICAgIGlmKGhhc0F4aXNJbkRmbHRQb3MpIHRoaXMudGlja0VuYWJsZVtpXSA9IGF4LnNob3d0aWNrbGFiZWxzO1xuICAgICAgICBlbHNlIGlmKGhhc0F4aXNJbkFsdHJQb3MpIHRoaXMudGlja0VuYWJsZVtpICsgMl0gPSBheC5zaG93dGlja2xhYmVscztcblxuICAgICAgICAvLyBHcmlkIGxpbmVzIGFuZCB0aWNrcyBjYW4gYXBwZWFyIG9uIGJvdGggc2lkZXMgb2YgdGhlIHNjZW5lXG4gICAgICAgIC8vICBhbmQgY2FuIGFwcGVhciBvbiBzdWJwbG90IHRoYXQgc2hhcmUgZXhpc3RpbmcgYXhlcyB2aWEgYGF4Lm1pcnJvcmAuXG5cbiAgICAgICAgaWYoaGFzQXhpc0luRGZsdFBvcyB8fCBtaXJyb3JMaW5lcykgdGhpcy5ib3JkZXJMaW5lRW5hYmxlW2ldID0gYXguc2hvd2xpbmU7XG4gICAgICAgIGlmKGhhc0F4aXNJbkFsdHJQb3MgfHwgbWlycm9yTGluZXMpIHRoaXMuYm9yZGVyTGluZUVuYWJsZVtpICsgMl0gPSBheC5zaG93bGluZTtcblxuICAgICAgICBpZihoYXNBeGlzSW5EZmx0UG9zIHx8IG1pcnJvclRpY2tzKSB0aGlzLnRpY2tNYXJrTGVuZ3RoW2ldID0gdGhpcy5nZXRUaWNrTWFya0xlbmd0aChheCk7XG4gICAgICAgIGlmKGhhc0F4aXNJbkFsdHJQb3MgfHwgbWlycm9yVGlja3MpIHRoaXMudGlja01hcmtMZW5ndGhbaSArIDJdID0gdGhpcy5nZXRUaWNrTWFya0xlbmd0aChheCk7XG5cbiAgICAgICAgdGhpcy5ncmlkTGluZUVuYWJsZVtpXSA9IGF4LnNob3dncmlkO1xuICAgICAgICB0aGlzLmdyaWRMaW5lQ29sb3JbaV0gPSBzdHIyUkdCQXJyYXkoYXguZ3JpZGNvbG9yKTtcbiAgICAgICAgdGhpcy5ncmlkTGluZVdpZHRoW2ldID0gYXguZ3JpZHdpZHRoO1xuXG4gICAgICAgIHRoaXMuemVyb0xpbmVFbmFibGVbaV0gPSBheC56ZXJvbGluZTtcbiAgICAgICAgdGhpcy56ZXJvTGluZUNvbG9yW2ldID0gc3RyMlJHQkFycmF5KGF4Lnplcm9saW5lY29sb3IpO1xuICAgICAgICB0aGlzLnplcm9MaW5lV2lkdGhbaV0gPSBheC56ZXJvbGluZXdpZHRoO1xuICAgIH1cbn07XG5cbi8vIGlzIGFuIGF4aXMgc2hhcmVkIHdpdGggYW4gYWxyZWFkeS1kcmF3biBzdWJwbG90ID9cbnByb3RvLmhhc1NoYXJlZEF4aXMgPSBmdW5jdGlvbihheCkge1xuICAgIHZhciBzY2VuZSA9IHRoaXMuc2NlbmU7XG4gICAgdmFyIHN1YnBsb3RJZHMgPSBzY2VuZS5mdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkO1xuICAgIHZhciBsaXN0ID0gQXhlcy5maW5kU3VicGxvdHNXaXRoQXhpcyhzdWJwbG90SWRzLCBheCk7XG5cbiAgICAvLyBpZiBpbmRleCA9PT0gMCwgdGhlbiB0aGUgc3VicGxvdCBpcyBhbHJlYWR5IGRyYXduIGFzIHN1YnBsb3RzXG4gICAgLy8gYXJlIGRyYXduIGluIG9yZGVyLlxuICAgIHJldHVybiAobGlzdC5pbmRleE9mKHNjZW5lLmlkKSAhPT0gMCk7XG59O1xuXG4vLyBoYXMgYW4gYXhpcyBpbiBkZWZhdWx0IHBvc2l0aW9uIChpLmUuIGJvdHRvbS9sZWZ0KSA/XG5wcm90by5oYXNBeGlzSW5EZmx0UG9zID0gZnVuY3Rpb24oYXhpc05hbWUsIGF4KSB7XG4gICAgdmFyIGF4U2lkZSA9IGF4LnNpZGU7XG5cbiAgICBpZihheGlzTmFtZSA9PT0gJ3hheGlzJykgcmV0dXJuIChheFNpZGUgPT09ICdib3R0b20nKTtcbiAgICBlbHNlIGlmKGF4aXNOYW1lID09PSAneWF4aXMnKSByZXR1cm4gKGF4U2lkZSA9PT0gJ2xlZnQnKTtcbn07XG5cbi8vIGhhcyBhbiBheGlzIGluIGFsdGVybmF0ZSBwb3NpdGlvbiAoaS5lLiB0b3AvcmlnaHQpID9cbnByb3RvLmhhc0F4aXNJbkFsdHJQb3MgPSBmdW5jdGlvbihheGlzTmFtZSwgYXgpIHtcbiAgICB2YXIgYXhTaWRlID0gYXguc2lkZTtcblxuICAgIGlmKGF4aXNOYW1lID09PSAneGF4aXMnKSByZXR1cm4gKGF4U2lkZSA9PT0gJ3RvcCcpO1xuICAgIGVsc2UgaWYoYXhpc05hbWUgPT09ICd5YXhpcycpIHJldHVybiAoYXhTaWRlID09PSAncmlnaHQnKTtcbn07XG5cbnByb3RvLmdldExhYmVsUGFkID0gZnVuY3Rpb24oYXhpc05hbWUsIGF4KSB7XG4gICAgdmFyIG9mZnNldEJhc2UgPSAxLjU7XG4gICAgdmFyIGZvbnRTaXplID0gYXgudGl0bGUuZm9udC5zaXplO1xuICAgIHZhciBzaG93dGlja2xhYmVscyA9IGF4LnNob3d0aWNrbGFiZWxzO1xuXG4gICAgaWYoYXhpc05hbWUgPT09ICd4YXhpcycpIHtcbiAgICAgICAgcmV0dXJuIChheC5zaWRlID09PSAndG9wJykgP1xuICAgICAgICAgICAgLTEwICsgZm9udFNpemUgKiAob2Zmc2V0QmFzZSArIChzaG93dGlja2xhYmVscyA/IDEgOiAwKSkgOlxuICAgICAgICAgICAgLTEwICsgZm9udFNpemUgKiAob2Zmc2V0QmFzZSArIChzaG93dGlja2xhYmVscyA/IDAuNSA6IDApKTtcbiAgICB9IGVsc2UgaWYoYXhpc05hbWUgPT09ICd5YXhpcycpIHtcbiAgICAgICAgcmV0dXJuIChheC5zaWRlID09PSAncmlnaHQnKSA/XG4gICAgICAgICAgICAxMCArIGZvbnRTaXplICogKG9mZnNldEJhc2UgKyAoc2hvd3RpY2tsYWJlbHMgPyAxIDogMC41KSkgOlxuICAgICAgICAgICAgMTAgKyBmb250U2l6ZSAqIChvZmZzZXRCYXNlICsgKHNob3d0aWNrbGFiZWxzID8gMC41IDogMCkpO1xuICAgIH1cbn07XG5cbnByb3RvLmdldFRpY2tQYWQgPSBmdW5jdGlvbihheCkge1xuICAgIHJldHVybiAoYXgudGlja3MgPT09ICdvdXRzaWRlJykgPyAxMCArIGF4LnRpY2tsZW4gOiAxNTtcbn07XG5cbnByb3RvLmdldFRpY2tNYXJrTGVuZ3RoID0gZnVuY3Rpb24oYXgpIHtcbiAgICBpZighYXgudGlja3MpIHJldHVybiAwO1xuXG4gICAgdmFyIHRpY2tsZW4gPSBheC50aWNrbGVuO1xuXG4gICAgcmV0dXJuIChheC50aWNrcyA9PT0gJ2luc2lkZScpID8gLXRpY2tsZW4gOiB0aWNrbGVuO1xufTtcblxuXG5mdW5jdGlvbiBjcmVhdGVBeGVzMkQoc2NlbmUpIHtcbiAgICByZXR1cm4gbmV3IEF4ZXMyRE9wdGlvbnMoc2NlbmUpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUF4ZXMyRDtcblxufSx7XCIuLi8uLi9saWIvc3RyMnJnYmFycmF5XCI6NzQyLFwiLi4vY2FydGVzaWFuL2F4ZXNcIjo3Njd9XSw4MDU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxudmFyIFNjZW5lMkQgPSBfZGVyZXFfKCcuL3NjZW5lMmQnKTtcbnZhciBsYXlvdXRHbG9iYWxBdHRycyA9IF9kZXJlcV8oJy4uL2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgeG1sbnNOYW1lc3BhY2VzID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXMnKTtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vY29uc3RhbnRzJyk7XG52YXIgQ2FydGVzaWFuID0gX2RlcmVxXygnLi4vY2FydGVzaWFuJyk7XG52YXIgZnhBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngvbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBnZXRTdWJwbG90RGF0YSA9IF9kZXJlcV8oJy4uL2dldF9kYXRhJykuZ2V0U3VicGxvdERhdGE7XG5cbmV4cG9ydHMubmFtZSA9ICdnbDJkJztcblxuZXhwb3J0cy5hdHRyID0gWyd4YXhpcycsICd5YXhpcyddO1xuXG5leHBvcnRzLmlkUm9vdCA9IFsneCcsICd5J107XG5cbmV4cG9ydHMuaWRSZWdleCA9IGNvbnN0YW50cy5pZFJlZ2V4O1xuXG5leHBvcnRzLmF0dHJSZWdleCA9IGNvbnN0YW50cy5hdHRyUmVnZXg7XG5cbmV4cG9ydHMuYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMuc3VwcGx5TGF5b3V0RGVmYXVsdHMgPSBmdW5jdGlvbihsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSkge1xuICAgIGlmKCFsYXlvdXRPdXQuX2hhcygnY2FydGVzaWFuJykpIHtcbiAgICAgICAgQ2FydGVzaWFuLnN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKTtcbiAgICB9XG59O1xuXG4vLyBnbDJkIHVzZXMgc3ZnIGF4aXMgYXR0cmlidXRlcyB2ZXJiYXRpbSwgYnV0IG92ZXJyaWRlcyBlZGl0VHlwZVxuLy8gdGhpcyBjb3VsZCBwb3RlbnRpYWxseSBiZSBqdXN0IGBsYXlvdXRBdHRyaWJ1dGVzYCBidXQgaXQgd291bGRcbi8vIHN0aWxsIG5lZWQgc3BlY2lhbCBoYW5kbGluZyBzb21ld2hlcmUgdG8gZ2l2ZSBpdCBwcmVjZWRlbmNlIG92ZXJcbi8vIHRoZSBzdmcgdmVyc2lvbiB3aGVuIGJvdGggYXJlIGluIHVzZSBvbiBvbmUgcGxvdFxuZXhwb3J0cy5sYXlvdXRBdHRyT3ZlcnJpZGVzID0gb3ZlcnJpZGVBbGwoQ2FydGVzaWFuLmxheW91dEF0dHJpYnV0ZXMsICdwbG90JywgJ2Zyb20tcm9vdCcpO1xuXG4vLyBzaW1pbGFyIG92ZXJyaWRlcyBmb3IgYmFzZSBwbG90IGF0dHJpYnV0ZXMgKGFuZCB0aG9zZSBhZGRlZCBieSBjb21wb25lbnRzKVxuZXhwb3J0cy5iYXNlTGF5b3V0QXR0ck92ZXJyaWRlcyA9IG92ZXJyaWRlQWxsKHtcbiAgICBwbG90X2JnY29sb3I6IGxheW91dEdsb2JhbEF0dHJzLnBsb3RfYmdjb2xvcixcbiAgICBob3ZlcmxhYmVsOiBmeEF0dHJzLmhvdmVybGFiZWxcbiAgICAvLyBkcmFnbW9kZSBuZWVkcyBjYWxjIGJ1dCBvbmx5IHdoZW4gdHJhbnNpdGlvbmluZyBUTyBsYXNzbyBvciBzZWxlY3RcbiAgICAvLyBzbyBmb3Igbm93IGl0J3MgbGVmdCBpbnNpZGUgX3JlbGF5b3V0XG4gICAgLy8gZHJhZ21vZGU6IGZ4QXR0cnMuZHJhZ21vZGVcbn0sICdwbG90JywgJ25lc3RlZCcpO1xuXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbiBwbG90KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZnVsbERhdGEgPSBnZC5fZnVsbERhdGE7XG4gICAgdmFyIHN1YnBsb3RJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHN1YnBsb3RJZCA9IHN1YnBsb3RJZHNbaV07XG4gICAgICAgIHZhciBzdWJwbG90T2JqID0gZnVsbExheW91dC5fcGxvdHNbc3VicGxvdElkXTtcbiAgICAgICAgdmFyIGZ1bGxTdWJwbG90RGF0YSA9IGdldFN1YnBsb3REYXRhKGZ1bGxEYXRhLCAnZ2wyZCcsIHN1YnBsb3RJZCk7XG5cbiAgICAgICAgLy8gcmVmLiB0byBjb3JyZXNwLiBTY2VuZSBpbnN0YW5jZVxuICAgICAgICB2YXIgc2NlbmUgPSBzdWJwbG90T2JqLl9zY2VuZTJkO1xuXG4gICAgICAgIC8vIElmIFNjZW5lIGlzIG5vdCBpbnN0YW50aWF0ZWQsIGNyZWF0ZSBvbmUhXG4gICAgICAgIGlmKHNjZW5lID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHNjZW5lID0gbmV3IFNjZW5lMkQoe1xuICAgICAgICAgICAgICAgIGlkOiBzdWJwbG90SWQsXG4gICAgICAgICAgICAgICAgZ3JhcGhEaXY6IGdkLFxuICAgICAgICAgICAgICAgIGNvbnRhaW5lcjogZ2QucXVlcnlTZWxlY3RvcignLmdsLWNvbnRhaW5lcicpLFxuICAgICAgICAgICAgICAgIHN0YXRpY1Bsb3Q6IGdkLl9jb250ZXh0LnN0YXRpY1Bsb3QsXG4gICAgICAgICAgICAgICAgcGxvdEdsUGl4ZWxSYXRpbzogZ2QuX2NvbnRleHQucGxvdEdsUGl4ZWxSYXRpb1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmdWxsTGF5b3V0XG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBzZXQgcmVmIHRvIFNjZW5lIGluc3RhbmNlXG4gICAgICAgICAgICBzdWJwbG90T2JqLl9zY2VuZTJkID0gc2NlbmU7XG4gICAgICAgIH1cblxuICAgICAgICBzY2VuZS5wbG90KGZ1bGxTdWJwbG90RGF0YSwgZ2QuY2FsY2RhdGEsIGZ1bGxMYXlvdXQsIGdkLmxheW91dCk7XG4gICAgfVxufTtcblxuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBvbGRTY2VuZUtleXMgPSBvbGRGdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkIHx8IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG9sZFNjZW5lS2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBvbGRTY2VuZUtleXNbaV07XG4gICAgICAgIHZhciBvbGRTdWJwbG90ID0gb2xkRnVsbExheW91dC5fcGxvdHNbaWRdO1xuXG4gICAgICAgIC8vIG9sZCBzdWJwbG90IHdhc24ndCBnbDJkOyBub3RoaW5nIHRvIGRvXG4gICAgICAgIGlmKCFvbGRTdWJwbG90Ll9zY2VuZTJkKSBjb250aW51ZTtcblxuICAgICAgICAvLyBpZiBubyB0cmFjZXMgYXJlIHByZXNlbnQsIGRlbGV0ZSBnbDJkIHN1YnBsb3RcbiAgICAgICAgdmFyIHN1YnBsb3REYXRhID0gZ2V0U3VicGxvdERhdGEobmV3RnVsbERhdGEsICdnbDJkJywgaWQpO1xuICAgICAgICBpZihzdWJwbG90RGF0YS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIG9sZFN1YnBsb3QuX3NjZW5lMmQuZGVzdHJveSgpO1xuICAgICAgICAgICAgZGVsZXRlIG9sZEZ1bGxMYXlvdXQuX3Bsb3RzW2lkXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNpbmNlIHdlIHVzZSBjYXJ0ZXNpYW4gaW50ZXJhY3Rpb25zLCBkbyBjYXJ0ZXNpYW4gY2xlYW5cbiAgICBDYXJ0ZXNpYW4uY2xlYW4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn07XG5cbmV4cG9ydHMuZHJhd0ZyYW1ld29yayA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgaWYoIWdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgQ2FydGVzaWFuLmRyYXdGcmFtZXdvcmsoZ2QpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMudG9TVkcgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHN1YnBsb3RJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHN1YnBsb3QgPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90SWRzW2ldXTtcbiAgICAgICAgdmFyIHNjZW5lID0gc3VicGxvdC5fc2NlbmUyZDtcblxuICAgICAgICB2YXIgaW1hZ2VEYXRhID0gc2NlbmUudG9JbWFnZSgncG5nJyk7XG4gICAgICAgIHZhciBpbWFnZSA9IGZ1bGxMYXlvdXQuX2dsaW1hZ2VzLmFwcGVuZCgnc3ZnOmltYWdlJyk7XG5cbiAgICAgICAgaW1hZ2UuYXR0cih7XG4gICAgICAgICAgICB4bWxuczogeG1sbnNOYW1lc3BhY2VzLnN2ZyxcbiAgICAgICAgICAgICd4bGluazpocmVmJzogaW1hZ2VEYXRhLFxuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICB3aWR0aDogJzEwMCUnLFxuICAgICAgICAgICAgaGVpZ2h0OiAnMTAwJScsXG4gICAgICAgICAgICBwcmVzZXJ2ZUFzcGVjdFJhdGlvOiAnbm9uZSdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2NlbmUuZGVzdHJveSgpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMudXBkYXRlRnggPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHN1YnBsb3RJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90cy5nbDJkO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHN1YnBsb3RPYmogPSBmdWxsTGF5b3V0Ll9wbG90c1tzdWJwbG90SWRzW2ldXS5fc2NlbmUyZDtcbiAgICAgICAgc3VicGxvdE9iai51cGRhdGVGeChmdWxsTGF5b3V0LmRyYWdtb2RlKTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvZngvbGF5b3V0X2F0dHJpYnV0ZXNcIjo2MzMsXCIuLi8uLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlc1wiOjY5NixcIi4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXNcIjo3NTAsXCIuLi9jYXJ0ZXNpYW5cIjo3NzgsXCIuLi9jYXJ0ZXNpYW4vYXR0cmlidXRlc1wiOjc2NSxcIi4uL2NhcnRlc2lhbi9jb25zdGFudHNcIjo3NzMsXCIuLi9nZXRfZGF0YVwiOjgwMixcIi4uL2xheW91dF9hdHRyaWJ1dGVzXCI6ODE5LFwiLi9zY2VuZTJkXCI6ODA2fV0sODA2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIEZ4ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meCcpO1xuXG52YXIgY3JlYXRlUGxvdDJEID0gX2RlcmVxXygnZ2wtcGxvdDJkJyk7XG52YXIgY3JlYXRlU3Bpa2VzID0gX2RlcmVxXygnZ2wtc3Bpa2VzMmQnKTtcbnZhciBjcmVhdGVTZWxlY3RCb3ggPSBfZGVyZXFfKCdnbC1zZWxlY3QtYm94Jyk7XG52YXIgZ2V0Q29udGV4dCA9IF9kZXJlcV8oJ3dlYmdsLWNvbnRleHQnKTtcblxudmFyIGNyZWF0ZU9wdGlvbnMgPSBfZGVyZXFfKCcuL2NvbnZlcnQnKTtcbnZhciBjcmVhdGVDYW1lcmEgPSBfZGVyZXFfKCcuL2NhbWVyYScpO1xudmFyIHNob3dOb1dlYkdsTXNnID0gX2RlcmVxXygnLi4vLi4vbGliL3Nob3dfbm9fd2ViZ2xfbXNnJyk7XG52YXIgYXhpc0NvbnN0cmFpbnRzID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL2NvbnN0cmFpbnRzJyk7XG52YXIgZW5mb3JjZUF4aXNDb25zdHJhaW50cyA9IGF4aXNDb25zdHJhaW50cy5lbmZvcmNlO1xudmFyIGNsZWFuQXhpc0NvbnN0cmFpbnRzID0gYXhpc0NvbnN0cmFpbnRzLmNsZWFuO1xudmFyIGRvQXV0b1JhbmdlID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL2F1dG9yYW5nZScpLmRvQXV0b1JhbmdlO1xuXG52YXIgQVhFUyA9IFsneGF4aXMnLCAneWF4aXMnXTtcbnZhciBTVEFUSUNfQ0FOVkFTLCBTVEFUSUNfQ09OVEVYVDtcblxudmFyIFNVQlBMT1RfUEFUVEVSTiA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9jb25zdGFudHMnKS5TVUJQTE9UX1BBVFRFUk47XG5cblxuZnVuY3Rpb24gU2NlbmUyRChvcHRpb25zLCBmdWxsTGF5b3V0KSB7XG4gICAgdGhpcy5jb250YWluZXIgPSBvcHRpb25zLmNvbnRhaW5lcjtcbiAgICB0aGlzLmdyYXBoRGl2ID0gb3B0aW9ucy5ncmFwaERpdjtcbiAgICB0aGlzLnBpeGVsUmF0aW8gPSBvcHRpb25zLnBsb3RHbFBpeGVsUmF0aW8gfHwgd2luZG93LmRldmljZVBpeGVsUmF0aW87XG4gICAgdGhpcy5pZCA9IG9wdGlvbnMuaWQ7XG4gICAgdGhpcy5zdGF0aWNQbG90ID0gISFvcHRpb25zLnN0YXRpY1Bsb3Q7XG4gICAgdGhpcy5zY3JvbGxab29tID0gdGhpcy5ncmFwaERpdi5fY29udGV4dC5fc2Nyb2xsWm9vbS5jYXJ0ZXNpYW47XG5cbiAgICB0aGlzLmZ1bGxEYXRhID0gbnVsbDtcbiAgICB0aGlzLnVwZGF0ZVJlZnMoZnVsbExheW91dCk7XG5cbiAgICB0aGlzLm1ha2VGcmFtZXdvcmsoKTtcbiAgICBpZih0aGlzLnN0b3BwZWQpIHJldHVybjtcblxuICAgIC8vIHVwZGF0ZSBvcHRpb25zXG4gICAgdGhpcy5nbHBsb3RPcHRpb25zID0gY3JlYXRlT3B0aW9ucyh0aGlzKTtcbiAgICB0aGlzLmdscGxvdE9wdGlvbnMubWVyZ2UoZnVsbExheW91dCk7XG5cbiAgICAvLyBjcmVhdGUgdGhlIHBsb3RcbiAgICB0aGlzLmdscGxvdCA9IGNyZWF0ZVBsb3QyRCh0aGlzLmdscGxvdE9wdGlvbnMpO1xuXG4gICAgLy8gY3JlYXRlIGNhbWVyYVxuICAgIHRoaXMuY2FtZXJhID0gY3JlYXRlQ2FtZXJhKHRoaXMpO1xuXG4gICAgLy8gdHJhY2Ugc2V0XG4gICAgdGhpcy50cmFjZXMgPSB7fTtcblxuICAgIC8vIGNyZWF0ZSBheGVzIHNwaWtlc1xuICAgIHRoaXMuc3Bpa2VzID0gY3JlYXRlU3Bpa2VzKHRoaXMuZ2xwbG90KTtcblxuICAgIHRoaXMuc2VsZWN0Qm94ID0gY3JlYXRlU2VsZWN0Qm94KHRoaXMuZ2xwbG90LCB7XG4gICAgICAgIGlubmVyRmlsbDogZmFsc2UsXG4gICAgICAgIG91dGVyRmlsbDogdHJ1ZVxuICAgIH0pO1xuXG4gICAgLy8gbGFzdCBidXR0b24gc3RhdGVcbiAgICB0aGlzLmxhc3RCdXR0b25TdGF0ZSA9IDA7XG5cbiAgICAvLyBsYXN0IHBpY2sgcmVzdWx0XG4gICAgdGhpcy5waWNrUmVzdWx0ID0gbnVsbDtcblxuICAgIC8vIGlzIHRoZSBtb3VzZSBvdmVyIHRoZSBwbG90P1xuICAgIC8vIGl0J3MgT0sgaWYgdGhpcyBzYXlzIHRydWUgd2hlbiBpdCdzIG5vdCwgc28gbG9uZyBhc1xuICAgIC8vIHdoZW4gd2UgZ2V0IGEgbW91c2VvdXQgd2Ugc2V0IGl0IHRvIGZhbHNlIGJlZm9yZSBoYW5kbGluZ1xuICAgIHRoaXMuaXNNb3VzZU92ZXIgPSB0cnVlO1xuXG4gICAgLy8gZmxhZyB0byBzdG9wIHJlbmRlciBsb29wXG4gICAgdGhpcy5zdG9wcGVkID0gZmFsc2U7XG5cbiAgICAvLyByZWRyYXcgdGhlIHBsb3RcbiAgICB0aGlzLnJlZHJhdyA9IHRoaXMuZHJhdy5iaW5kKHRoaXMpO1xuICAgIHRoaXMucmVkcmF3KCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gU2NlbmUyRDtcblxudmFyIHByb3RvID0gU2NlbmUyRC5wcm90b3R5cGU7XG5cbnByb3RvLm1ha2VGcmFtZXdvcmsgPSBmdW5jdGlvbigpIHtcbiAgICAvLyBjcmVhdGUgY2FudmFzIGFuZCBnbCBjb250ZXh0XG4gICAgaWYodGhpcy5zdGF0aWNQbG90KSB7XG4gICAgICAgIGlmKCFTVEFUSUNfQ09OVEVYVCkge1xuICAgICAgICAgICAgU1RBVElDX0NBTlZBUyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuXG4gICAgICAgICAgICBTVEFUSUNfQ09OVEVYVCA9IGdldENvbnRleHQoe1xuICAgICAgICAgICAgICAgIGNhbnZhczogU1RBVElDX0NBTlZBUyxcbiAgICAgICAgICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHByZW11bHRpcGxpZWRBbHBoYTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhbnRpYWxpYXM6IHRydWVcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZighU1RBVElDX0NPTlRFWFQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIGNyZWF0aW5nIHN0YXRpYyBjYW52YXMvY29udGV4dCBmb3IgaW1hZ2Ugc2VydmVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNhbnZhcyA9IFNUQVRJQ19DQU5WQVM7XG4gICAgICAgIHRoaXMuZ2wgPSBTVEFUSUNfQ09OVEVYVDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbGl2ZUNhbnZhcyA9IHRoaXMuY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5nbC1jYW52YXMtZm9jdXMnKTtcblxuICAgICAgICB2YXIgZ2wgPSBnZXRDb250ZXh0KHtcbiAgICAgICAgICAgIGNhbnZhczogbGl2ZUNhbnZhcyxcbiAgICAgICAgICAgIHByZXNlcnZlRHJhd2luZ0J1ZmZlcjogdHJ1ZSxcbiAgICAgICAgICAgIHByZW11bHRpcGxpZWRBbHBoYTogdHJ1ZVxuICAgICAgICB9KTtcblxuICAgICAgICBpZighZ2wpIHtcbiAgICAgICAgICAgIHNob3dOb1dlYkdsTXNnKHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5zdG9wcGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY2FudmFzID0gbGl2ZUNhbnZhcztcbiAgICAgICAgdGhpcy5nbCA9IGdsO1xuICAgIH1cblxuICAgIC8vIHBvc2l0aW9uIHRoZSBjYW52YXNcbiAgICB2YXIgY2FudmFzID0gdGhpcy5jYW52YXM7XG5cbiAgICBjYW52YXMuc3R5bGUud2lkdGggPSAnMTAwJSc7XG4gICAgY2FudmFzLnN0eWxlLmhlaWdodCA9ICcxMDAlJztcbiAgICBjYW52YXMuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgIGNhbnZhcy5zdHlsZS50b3AgPSAnMHB4JztcbiAgICBjYW52YXMuc3R5bGUubGVmdCA9ICcwcHgnO1xuICAgIGNhbnZhcy5zdHlsZVsncG9pbnRlci1ldmVudHMnXSA9ICdub25lJztcblxuICAgIHRoaXMudXBkYXRlU2l6ZShjYW52YXMpO1xuXG4gICAgLy8gZGlzYWJsaW5nIHVzZXIgc2VsZWN0IG9uIHRoZSBjYW52YXNcbiAgICAvLyBzYW5pdGl6ZXMgZG91YmxlLWNsaWNrcyBpbnRlcmFjdGlvbnNcbiAgICAvLyByZWY6IGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy83NDRcbiAgICBjYW52YXMuY2xhc3NOYW1lICs9ICcgdXNlci1zZWxlY3Qtbm9uZSc7XG5cbiAgICAvLyBjcmVhdGUgU1ZHIGNvbnRhaW5lciBmb3IgaG92ZXIgdGV4dFxuICAgIHZhciBzdmdDb250YWluZXIgPSB0aGlzLnN2Z0NvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhcbiAgICAgICAgJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyxcbiAgICAgICAgJ3N2ZycpO1xuICAgIHN2Z0NvbnRhaW5lci5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgc3ZnQ29udGFpbmVyLnN0eWxlLnRvcCA9IHN2Z0NvbnRhaW5lci5zdHlsZS5sZWZ0ID0gJzBweCc7XG4gICAgc3ZnQ29udGFpbmVyLnN0eWxlLndpZHRoID0gc3ZnQ29udGFpbmVyLnN0eWxlLmhlaWdodCA9ICcxMDAlJztcbiAgICBzdmdDb250YWluZXIuc3R5bGVbJ3otaW5kZXgnXSA9IDIwO1xuICAgIHN2Z0NvbnRhaW5lci5zdHlsZVsncG9pbnRlci1ldmVudHMnXSA9ICdub25lJztcblxuICAgIC8vIGNyZWF0ZSBkaXYgdG8gY2F0Y2ggdGhlIG1vdXNlIGV2ZW50XG4gICAgdmFyIG1vdXNlQ29udGFpbmVyID0gdGhpcy5tb3VzZUNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIG1vdXNlQ29udGFpbmVyLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBtb3VzZUNvbnRhaW5lci5zdHlsZVsncG9pbnRlci1ldmVudHMnXSA9ICdhdXRvJztcblxuICAgIHRoaXMucGlja0NhbnZhcyA9IHRoaXMuY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoJy5nbC1jYW52YXMtcGljaycpO1xuXG5cbiAgICAvLyBhcHBlbmQgY2FudmFzLCBob3ZlciBzdmcgYW5kIG1vdXNlIGRpdiB0byBjb250YWluZXJcbiAgICB2YXIgY29udGFpbmVyID0gdGhpcy5jb250YWluZXI7XG4gICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHN2Z0NvbnRhaW5lcik7XG4gICAgY29udGFpbmVyLmFwcGVuZENoaWxkKG1vdXNlQ29udGFpbmVyKTtcblxuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICBtb3VzZUNvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW91dCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICBzZWxmLmlzTW91c2VPdmVyID0gZmFsc2U7XG4gICAgICAgIHNlbGYudW5ob3ZlcigpO1xuICAgIH0pO1xuICAgIG1vdXNlQ29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsIGZ1bmN0aW9uKCkge1xuICAgICAgICBzZWxmLmlzTW91c2VPdmVyID0gdHJ1ZTtcbiAgICB9KTtcbn07XG5cbnByb3RvLnRvSW1hZ2UgPSBmdW5jdGlvbihmb3JtYXQpIHtcbiAgICBpZighZm9ybWF0KSBmb3JtYXQgPSAncG5nJztcblxuICAgIHRoaXMuc3RvcHBlZCA9IHRydWU7XG5cbiAgICBpZih0aGlzLnN0YXRpY1Bsb3QpIHRoaXMuY29udGFpbmVyLmFwcGVuZENoaWxkKFNUQVRJQ19DQU5WQVMpO1xuXG4gICAgLy8gdXBkYXRlIGNhbnZhcyBzaXplXG4gICAgdGhpcy51cGRhdGVTaXplKHRoaXMuY2FudmFzKTtcblxuXG4gICAgLy8gZ3JhYiBjb250ZXh0IGFuZCB5YW5rIG91dCBwaXhlbHNcbiAgICB2YXIgZ2wgPSB0aGlzLmdscGxvdC5nbDtcbiAgICB2YXIgdyA9IGdsLmRyYXdpbmdCdWZmZXJXaWR0aDtcbiAgICB2YXIgaCA9IGdsLmRyYXdpbmdCdWZmZXJIZWlnaHQ7XG5cbiAgICAvLyBmb3JjZSByZWRyYXdcbiAgICBnbC5jbGVhckNvbG9yKDEsIDEsIDEsIDApO1xuICAgIGdsLmNsZWFyKGdsLkNPTE9SX0JVRkZFUl9CSVQgfCBnbC5ERVBUSF9CVUZGRVJfQklUKTtcbiAgICB0aGlzLmdscGxvdC5zZXREaXJ0eSgpO1xuICAgIHRoaXMuZ2xwbG90LmRyYXcoKTtcblxuICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgbnVsbCk7XG5cbiAgICB2YXIgcGl4ZWxzID0gbmV3IFVpbnQ4QXJyYXkodyAqIGggKiA0KTtcbiAgICBnbC5yZWFkUGl4ZWxzKDAsIDAsIHcsIGgsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIHBpeGVscyk7XG5cbiAgICAvLyBmbGlwIHBpeGVsc1xuICAgIGZvcih2YXIgaiA9IDAsIGsgPSBoIC0gMTsgaiA8IGs7ICsraiwgLS1rKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB3OyArK2kpIHtcbiAgICAgICAgICAgIGZvcih2YXIgbCA9IDA7IGwgPCA0OyArK2wpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG1wID0gcGl4ZWxzWzQgKiAodyAqIGogKyBpKSArIGxdO1xuICAgICAgICAgICAgICAgIHBpeGVsc1s0ICogKHcgKiBqICsgaSkgKyBsXSA9IHBpeGVsc1s0ICogKHcgKiBrICsgaSkgKyBsXTtcbiAgICAgICAgICAgICAgICBwaXhlbHNbNCAqICh3ICogayArIGkpICsgbF0gPSB0bXA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgY2FudmFzLndpZHRoID0gdztcbiAgICBjYW52YXMuaGVpZ2h0ID0gaDtcblxuICAgIHZhciBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgdmFyIGltYWdlRGF0YSA9IGNvbnRleHQuY3JlYXRlSW1hZ2VEYXRhKHcsIGgpO1xuICAgIGltYWdlRGF0YS5kYXRhLnNldChwaXhlbHMpO1xuICAgIGNvbnRleHQucHV0SW1hZ2VEYXRhKGltYWdlRGF0YSwgMCwgMCk7XG5cbiAgICB2YXIgZGF0YVVSTDtcblxuICAgIHN3aXRjaChmb3JtYXQpIHtcbiAgICAgICAgY2FzZSAnanBlZyc6XG4gICAgICAgICAgICBkYXRhVVJMID0gY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvanBlZycpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3dlYnAnOlxuICAgICAgICAgICAgZGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3dlYnAnKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgZGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuICAgIH1cblxuICAgIGlmKHRoaXMuc3RhdGljUGxvdCkgdGhpcy5jb250YWluZXIucmVtb3ZlQ2hpbGQoU1RBVElDX0NBTlZBUyk7XG5cbiAgICByZXR1cm4gZGF0YVVSTDtcbn07XG5cbnByb3RvLnVwZGF0ZVNpemUgPSBmdW5jdGlvbihjYW52YXMpIHtcbiAgICBpZighY2FudmFzKSBjYW52YXMgPSB0aGlzLmNhbnZhcztcblxuICAgIHZhciBwaXhlbFJhdGlvID0gdGhpcy5waXhlbFJhdGlvO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gdGhpcy5mdWxsTGF5b3V0O1xuXG4gICAgdmFyIHdpZHRoID0gZnVsbExheW91dC53aWR0aDtcbiAgICB2YXIgaGVpZ2h0ID0gZnVsbExheW91dC5oZWlnaHQ7XG4gICAgdmFyIHBpeGVsV2lkdGggPSBNYXRoLmNlaWwocGl4ZWxSYXRpbyAqIHdpZHRoKSB8MDtcbiAgICB2YXIgcGl4ZWxIZWlnaHQgPSBNYXRoLmNlaWwocGl4ZWxSYXRpbyAqIGhlaWdodCkgfDA7XG5cbiAgICAvLyBjaGVjayBmb3IgcmVzaXplXG4gICAgaWYoY2FudmFzLndpZHRoICE9PSBwaXhlbFdpZHRoIHx8IGNhbnZhcy5oZWlnaHQgIT09IHBpeGVsSGVpZ2h0KSB7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHBpeGVsV2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBwaXhlbEhlaWdodDtcbiAgICB9XG5cbiAgICByZXR1cm4gY2FudmFzO1xufTtcblxucHJvdG8uY29tcHV0ZVRpY2tNYXJrcyA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMueGF4aXMuc2V0U2NhbGUoKTtcbiAgICB0aGlzLnlheGlzLnNldFNjYWxlKCk7XG5cbiAgICB2YXIgbmV4dFRpY2tzID0gW1xuICAgICAgICBBeGVzLmNhbGNUaWNrcyh0aGlzLnhheGlzKSxcbiAgICAgICAgQXhlcy5jYWxjVGlja3ModGhpcy55YXhpcylcbiAgICBdO1xuXG4gICAgZm9yKHZhciBqID0gMDsgaiA8IDI7ICsraikge1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbmV4dFRpY2tzW2pdLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAvLyBjb2VyY2luZyB0aWNrIHZhbHVlIChtYXkgbm90IGJlIGEgc3RyaW5nKSB0byBhIHN0cmluZ1xuICAgICAgICAgICAgbmV4dFRpY2tzW2pdW2ldLnRleHQgPSBuZXh0VGlja3Nbal1baV0udGV4dCArICcnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG5leHRUaWNrcztcbn07XG5cbmZ1bmN0aW9uIGNvbXBhcmVUaWNrcyhhLCBiKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDI7ICsraSkge1xuICAgICAgICB2YXIgYXRpY2tzID0gYVtpXTtcbiAgICAgICAgdmFyIGJ0aWNrcyA9IGJbaV07XG5cbiAgICAgICAgaWYoYXRpY2tzLmxlbmd0aCAhPT0gYnRpY2tzLmxlbmd0aCkgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGF0aWNrcy5sZW5ndGg7ICsraikge1xuICAgICAgICAgICAgaWYoYXRpY2tzW2pdLnggIT09IGJ0aWNrc1tqXS54KSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxucHJvdG8udXBkYXRlUmVmcyA9IGZ1bmN0aW9uKG5ld0Z1bGxMYXlvdXQpIHtcbiAgICB0aGlzLmZ1bGxMYXlvdXQgPSBuZXdGdWxsTGF5b3V0O1xuXG4gICAgdmFyIHNwbWF0Y2ggPSB0aGlzLmlkLm1hdGNoKFNVQlBMT1RfUEFUVEVSTik7XG4gICAgdmFyIHhheGlzTmFtZSA9ICd4YXhpcycgKyBzcG1hdGNoWzFdO1xuICAgIHZhciB5YXhpc05hbWUgPSAneWF4aXMnICsgc3BtYXRjaFsyXTtcblxuICAgIHRoaXMueGF4aXMgPSB0aGlzLmZ1bGxMYXlvdXRbeGF4aXNOYW1lXTtcbiAgICB0aGlzLnlheGlzID0gdGhpcy5mdWxsTGF5b3V0W3lheGlzTmFtZV07XG59O1xuXG5wcm90by5yZWxheW91dENhbGxiYWNrID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGdyYXBoRGl2ID0gdGhpcy5ncmFwaERpdjtcbiAgICB2YXIgeGF4aXMgPSB0aGlzLnhheGlzO1xuICAgIHZhciB5YXhpcyA9IHRoaXMueWF4aXM7XG4gICAgdmFyIGxheW91dCA9IGdyYXBoRGl2LmxheW91dDtcblxuICAgIC8vIG1ha2UgYSBtZWFuaW5nZnVsIHZhbHVlIHRvIGJlIHBhc3NlZCBvbiB0byBwb3NzaWJsZSAncGxvdGx5X3JlbGF5b3V0JyBzdWJzY3JpYmVyKHMpXG4gICAgdmFyIHVwZGF0ZSA9IHt9O1xuICAgIHZhciB4cmFuZ2UgPSB1cGRhdGVbeGF4aXMuX25hbWUgKyAnLnJhbmdlJ10gPSB4YXhpcy5yYW5nZS5zbGljZSgpO1xuICAgIHZhciB5cmFuZ2UgPSB1cGRhdGVbeWF4aXMuX25hbWUgKyAnLnJhbmdlJ10gPSB5YXhpcy5yYW5nZS5zbGljZSgpO1xuICAgIHVwZGF0ZVt4YXhpcy5fbmFtZSArICcuYXV0b3JhbmdlJ10gPSB4YXhpcy5hdXRvcmFuZ2U7XG4gICAgdXBkYXRlW3lheGlzLl9uYW1lICsgJy5hdXRvcmFuZ2UnXSA9IHlheGlzLmF1dG9yYW5nZTtcblxuICAgIFJlZ2lzdHJ5LmNhbGwoJ19zdG9yZURpcmVjdEdVSUVkaXQnLCBncmFwaERpdi5sYXlvdXQsIGdyYXBoRGl2Ll9mdWxsTGF5b3V0Ll9wcmVHVUksIHVwZGF0ZSk7XG5cbiAgICAvLyB1cGRhdGUgdGhlIGlucHV0IGxheW91dFxuICAgIHZhciB4YUluID0gbGF5b3V0W3hheGlzLl9uYW1lXTtcbiAgICB4YUluLnJhbmdlID0geHJhbmdlO1xuICAgIHhhSW4uYXV0b3JhbmdlID0geGF4aXMuYXV0b3JhbmdlO1xuXG4gICAgdmFyIHlhSW4gPSBsYXlvdXRbeWF4aXMuX25hbWVdO1xuICAgIHlhSW4ucmFuZ2UgPSB5cmFuZ2U7XG4gICAgeWFJbi5hdXRvcmFuZ2UgPSB5YXhpcy5hdXRvcmFuZ2U7XG5cbiAgICAvLyBsYXN0SW5wdXRUaW1lIGhlbHBzIGRldGVybWluZSB3aGljaCBvbmUgaXMgdGhlIGxhdGVzdCBpbnB1dCAoaWYgYXN5bmMpXG4gICAgdXBkYXRlLmxhc3RJbnB1dFRpbWUgPSB0aGlzLmNhbWVyYS5sYXN0SW5wdXRUaW1lO1xuICAgIGdyYXBoRGl2LmVtaXQoJ3Bsb3RseV9yZWxheW91dCcsIHVwZGF0ZSk7XG59O1xuXG5wcm90by5jYW1lcmFDaGFuZ2VkID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNhbWVyYSA9IHRoaXMuY2FtZXJhO1xuXG4gICAgdGhpcy5nbHBsb3Quc2V0RGF0YUJveCh0aGlzLmNhbGNEYXRhQm94KCkpO1xuXG4gICAgdmFyIG5leHRUaWNrcyA9IHRoaXMuY29tcHV0ZVRpY2tNYXJrcygpO1xuICAgIHZhciBjdXJUaWNrcyA9IHRoaXMuZ2xwbG90T3B0aW9ucy50aWNrcztcblxuICAgIGlmKGNvbXBhcmVUaWNrcyhuZXh0VGlja3MsIGN1clRpY2tzKSkge1xuICAgICAgICB0aGlzLmdscGxvdE9wdGlvbnMudGlja3MgPSBuZXh0VGlja3M7XG4gICAgICAgIHRoaXMuZ2xwbG90T3B0aW9ucy5kYXRhQm94ID0gY2FtZXJhLmRhdGFCb3g7XG4gICAgICAgIHRoaXMuZ2xwbG90LnVwZGF0ZSh0aGlzLmdscGxvdE9wdGlvbnMpO1xuICAgICAgICB0aGlzLmhhbmRsZUFubm90YXRpb25zKCk7XG4gICAgfVxufTtcblxucHJvdG8uaGFuZGxlQW5ub3RhdGlvbnMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZ2QgPSB0aGlzLmdyYXBoRGl2O1xuICAgIHZhciBhbm5vdGF0aW9ucyA9IHRoaXMuZnVsbExheW91dC5hbm5vdGF0aW9ucztcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhbm5vdGF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYW5uID0gYW5ub3RhdGlvbnNbaV07XG5cbiAgICAgICAgaWYoYW5uLnhyZWYgPT09IHRoaXMueGF4aXMuX2lkICYmIGFubi55cmVmID09PSB0aGlzLnlheGlzLl9pZCkge1xuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdhbm5vdGF0aW9ucycsICdkcmF3T25lJykoZ2QsIGkpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxucHJvdG8uZGVzdHJveSA9IGZ1bmN0aW9uKCkge1xuICAgIGlmKCF0aGlzLmdscGxvdCkgcmV0dXJuO1xuXG4gICAgdmFyIHRyYWNlcyA9IHRoaXMudHJhY2VzO1xuXG4gICAgaWYodHJhY2VzKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKHRyYWNlcykubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgICAgICAgdHJhY2VzW2tleV0uZGlzcG9zZSgpO1xuICAgICAgICAgICAgZGVsZXRlIHRyYWNlc1trZXldO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLmdscGxvdC5kaXNwb3NlKCk7XG5cbiAgICB0aGlzLmNvbnRhaW5lci5yZW1vdmVDaGlsZCh0aGlzLnN2Z0NvbnRhaW5lcik7XG4gICAgdGhpcy5jb250YWluZXIucmVtb3ZlQ2hpbGQodGhpcy5tb3VzZUNvbnRhaW5lcik7XG5cbiAgICB0aGlzLmZ1bGxEYXRhID0gbnVsbDtcbiAgICB0aGlzLmdscGxvdCA9IG51bGw7XG4gICAgdGhpcy5zdG9wcGVkID0gdHJ1ZTtcbiAgICB0aGlzLmNhbWVyYS5tb3VzZUxpc3RlbmVyLmVuYWJsZWQgPSBmYWxzZTtcbiAgICB0aGlzLm1vdXNlQ29udGFpbmVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3doZWVsJywgdGhpcy5jYW1lcmEud2hlZWxMaXN0ZW5lcik7XG4gICAgdGhpcy5jYW1lcmEgPSBudWxsO1xufTtcblxucHJvdG8ucGxvdCA9IGZ1bmN0aW9uKGZ1bGxEYXRhLCBjYWxjRGF0YSwgZnVsbExheW91dCkge1xuICAgIHZhciBnbHBsb3QgPSB0aGlzLmdscGxvdDtcblxuICAgIHRoaXMudXBkYXRlUmVmcyhmdWxsTGF5b3V0KTtcbiAgICB0aGlzLnhheGlzLmNsZWFyQ2FsYygpO1xuICAgIHRoaXMueWF4aXMuY2xlYXJDYWxjKCk7XG4gICAgdGhpcy51cGRhdGVUcmFjZXMoZnVsbERhdGEsIGNhbGNEYXRhKTtcbiAgICB0aGlzLnVwZGF0ZUZ4KGZ1bGxMYXlvdXQuZHJhZ21vZGUpO1xuXG4gICAgdmFyIHdpZHRoID0gZnVsbExheW91dC53aWR0aDtcbiAgICB2YXIgaGVpZ2h0ID0gZnVsbExheW91dC5oZWlnaHQ7XG5cbiAgICB0aGlzLnVwZGF0ZVNpemUodGhpcy5jYW52YXMpO1xuXG4gICAgdmFyIG9wdGlvbnMgPSB0aGlzLmdscGxvdE9wdGlvbnM7XG4gICAgb3B0aW9ucy5tZXJnZShmdWxsTGF5b3V0KTtcbiAgICBvcHRpb25zLnNjcmVlbkJveCA9IFswLCAwLCB3aWR0aCwgaGVpZ2h0XTtcblxuICAgIHZhciBtb2NrR3JhcGhEaXYgPSB7X2Z1bGxMYXlvdXQ6IHtcbiAgICAgICAgX2F4aXNDb25zdHJhaW50R3JvdXBzOiB0aGlzLmdyYXBoRGl2Ll9mdWxsTGF5b3V0Ll9heGlzQ29uc3RyYWludEdyb3VwcyxcbiAgICAgICAgeGF4aXM6IHRoaXMueGF4aXMsXG4gICAgICAgIHlheGlzOiB0aGlzLnlheGlzXG4gICAgfX07XG5cbiAgICBjbGVhbkF4aXNDb25zdHJhaW50cyhtb2NrR3JhcGhEaXYsIHRoaXMueGF4aXMpO1xuICAgIGNsZWFuQXhpc0NvbnN0cmFpbnRzKG1vY2tHcmFwaERpdiwgdGhpcy55YXhpcyk7XG5cbiAgICB2YXIgc2l6ZSA9IGZ1bGxMYXlvdXQuX3NpemU7XG4gICAgdmFyIGRvbWFpblggPSB0aGlzLnhheGlzLmRvbWFpbjtcbiAgICB2YXIgZG9tYWluWSA9IHRoaXMueWF4aXMuZG9tYWluO1xuXG4gICAgb3B0aW9ucy52aWV3Qm94ID0gW1xuICAgICAgICBzaXplLmwgKyBkb21haW5YWzBdICogc2l6ZS53LFxuICAgICAgICBzaXplLmIgKyBkb21haW5ZWzBdICogc2l6ZS5oLFxuICAgICAgICAod2lkdGggLSBzaXplLnIpIC0gKDEgLSBkb21haW5YWzFdKSAqIHNpemUudyxcbiAgICAgICAgKGhlaWdodCAtIHNpemUudCkgLSAoMSAtIGRvbWFpbllbMV0pICogc2l6ZS5oXG4gICAgXTtcblxuICAgIHRoaXMubW91c2VDb250YWluZXIuc3R5bGUud2lkdGggPSBzaXplLncgKiAoZG9tYWluWFsxXSAtIGRvbWFpblhbMF0pICsgJ3B4JztcbiAgICB0aGlzLm1vdXNlQ29udGFpbmVyLnN0eWxlLmhlaWdodCA9IHNpemUuaCAqIChkb21haW5ZWzFdIC0gZG9tYWluWVswXSkgKyAncHgnO1xuICAgIHRoaXMubW91c2VDb250YWluZXIuaGVpZ2h0ID0gc2l6ZS5oICogKGRvbWFpbllbMV0gLSBkb21haW5ZWzBdKTtcbiAgICB0aGlzLm1vdXNlQ29udGFpbmVyLnN0eWxlLmxlZnQgPSBzaXplLmwgKyBkb21haW5YWzBdICogc2l6ZS53ICsgJ3B4JztcbiAgICB0aGlzLm1vdXNlQ29udGFpbmVyLnN0eWxlLnRvcCA9IHNpemUudCArICgxIC0gZG9tYWluWVsxXSkgKiBzaXplLmggKyAncHgnO1xuXG4gICAgdmFyIGF4LCBpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgMjsgKytpKSB7XG4gICAgICAgIGF4ID0gdGhpc1tBWEVTW2ldXTtcbiAgICAgICAgYXguX2xlbmd0aCA9IG9wdGlvbnMudmlld0JveFtpICsgMl0gLSBvcHRpb25zLnZpZXdCb3hbaV07XG5cbiAgICAgICAgZG9BdXRvUmFuZ2UodGhpcy5ncmFwaERpdiwgYXgpO1xuICAgICAgICBheC5zZXRTY2FsZSgpO1xuICAgIH1cblxuICAgIGVuZm9yY2VBeGlzQ29uc3RyYWludHMobW9ja0dyYXBoRGl2KTtcblxuICAgIG9wdGlvbnMudGlja3MgPSB0aGlzLmNvbXB1dGVUaWNrTWFya3MoKTtcblxuICAgIG9wdGlvbnMuZGF0YUJveCA9IHRoaXMuY2FsY0RhdGFCb3goKTtcblxuICAgIG9wdGlvbnMubWVyZ2UoZnVsbExheW91dCk7XG4gICAgZ2xwbG90LnVwZGF0ZShvcHRpb25zKTtcblxuICAgIC8vIGZvcmNlIHJlZHJhdyBzbyB0aGF0IHByb21pc2UgaXMgcmV0dXJuZWQgd2hlbiByZW5kZXJpbmcgaXMgY29tcGxldGVkXG4gICAgdGhpcy5nbHBsb3QuZHJhdygpO1xufTtcblxucHJvdG8uY2FsY0RhdGFCb3ggPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgeGF4aXMgPSB0aGlzLnhheGlzO1xuICAgIHZhciB5YXhpcyA9IHRoaXMueWF4aXM7XG4gICAgdmFyIHhyYW5nZSA9IHhheGlzLnJhbmdlO1xuICAgIHZhciB5cmFuZ2UgPSB5YXhpcy5yYW5nZTtcbiAgICB2YXIgeHIybCA9IHhheGlzLnIybDtcbiAgICB2YXIgeXIybCA9IHlheGlzLnIybDtcblxuICAgIHJldHVybiBbeHIybCh4cmFuZ2VbMF0pLCB5cjJsKHlyYW5nZVswXSksIHhyMmwoeHJhbmdlWzFdKSwgeXIybCh5cmFuZ2VbMV0pXTtcbn07XG5cbnByb3RvLnNldFJhbmdlcyA9IGZ1bmN0aW9uKGRhdGFCb3gpIHtcbiAgICB2YXIgeGF4aXMgPSB0aGlzLnhheGlzO1xuICAgIHZhciB5YXhpcyA9IHRoaXMueWF4aXM7XG4gICAgdmFyIHhsMnIgPSB4YXhpcy5sMnI7XG4gICAgdmFyIHlsMnIgPSB5YXhpcy5sMnI7XG5cbiAgICB4YXhpcy5yYW5nZSA9IFt4bDJyKGRhdGFCb3hbMF0pLCB4bDJyKGRhdGFCb3hbMl0pXTtcbiAgICB5YXhpcy5yYW5nZSA9IFt5bDJyKGRhdGFCb3hbMV0pLCB5bDJyKGRhdGFCb3hbM10pXTtcbn07XG5cbnByb3RvLnVwZGF0ZVRyYWNlcyA9IGZ1bmN0aW9uKGZ1bGxEYXRhLCBjYWxjRGF0YSkge1xuICAgIHZhciB0cmFjZUlkcyA9IE9iamVjdC5rZXlzKHRoaXMudHJhY2VzKTtcbiAgICB2YXIgaSwgaiwgZnVsbFRyYWNlO1xuXG4gICAgdGhpcy5mdWxsRGF0YSA9IGZ1bGxEYXRhO1xuXG4gICAgLy8gcmVtb3ZlIGVtcHR5IHRyYWNlc1xuICAgIHRyYWNlSWRMb29wOlxuICAgIGZvcihpID0gMDsgaSA8IHRyYWNlSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvbGRVaWQgPSB0cmFjZUlkc1tpXTtcbiAgICAgICAgdmFyIG9sZFRyYWNlID0gdGhpcy50cmFjZXNbb2xkVWlkXTtcblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBmdWxsRGF0YS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgZnVsbFRyYWNlID0gZnVsbERhdGFbal07XG5cbiAgICAgICAgICAgIGlmKGZ1bGxUcmFjZS51aWQgPT09IG9sZFVpZCAmJiBmdWxsVHJhY2UudHlwZSA9PT0gb2xkVHJhY2UudHlwZSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlIHRyYWNlSWRMb29wO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgb2xkVHJhY2UuZGlzcG9zZSgpO1xuICAgICAgICBkZWxldGUgdGhpcy50cmFjZXNbb2xkVWlkXTtcbiAgICB9XG5cbiAgICAvLyB1cGRhdGUgLyBjcmVhdGUgdHJhY2Ugb2JqZWN0c1xuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGZ1bGxUcmFjZSA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICB2YXIgY2FsY1RyYWNlID0gY2FsY0RhdGFbaV07XG4gICAgICAgIHZhciB0cmFjZU9iaiA9IHRoaXMudHJhY2VzW2Z1bGxUcmFjZS51aWRdO1xuXG4gICAgICAgIGlmKHRyYWNlT2JqKSB0cmFjZU9iai51cGRhdGUoZnVsbFRyYWNlLCBjYWxjVHJhY2UpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRyYWNlT2JqID0gZnVsbFRyYWNlLl9tb2R1bGUucGxvdCh0aGlzLCBmdWxsVHJhY2UsIGNhbGNUcmFjZSk7XG4gICAgICAgICAgICB0aGlzLnRyYWNlc1tmdWxsVHJhY2UudWlkXSA9IHRyYWNlT2JqO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gb3JkZXIgb2JqZWN0IHBlciB0cmFjZXNcbiAgICB0aGlzLmdscGxvdC5vYmplY3RzLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICByZXR1cm4gYS5fdHJhY2UuaW5kZXggLSBiLl90cmFjZS5pbmRleDtcbiAgICB9KTtcbn07XG5cbnByb3RvLnVwZGF0ZUZ4ID0gZnVuY3Rpb24oZHJhZ21vZGUpIHtcbiAgICAvLyBzd2l0Y2ggdG8gc3ZnIGludGVyYWN0aW9ucyBpbiBsYXNzby9zZWxlY3QgbW9kZVxuICAgIGlmKGRyYWdtb2RlID09PSAnbGFzc28nIHx8IGRyYWdtb2RlID09PSAnc2VsZWN0Jykge1xuICAgICAgICB0aGlzLnBpY2tDYW52YXMuc3R5bGVbJ3BvaW50ZXItZXZlbnRzJ10gPSAnbm9uZSc7XG4gICAgICAgIHRoaXMubW91c2VDb250YWluZXIuc3R5bGVbJ3BvaW50ZXItZXZlbnRzJ10gPSAnbm9uZSc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5waWNrQ2FudmFzLnN0eWxlWydwb2ludGVyLWV2ZW50cyddID0gJ2F1dG8nO1xuICAgICAgICB0aGlzLm1vdXNlQ29udGFpbmVyLnN0eWxlWydwb2ludGVyLWV2ZW50cyddID0gJ2F1dG8nO1xuICAgIH1cblxuICAgIC8vIHNldCBwcm9wZXIgY3Vyc29yXG4gICAgaWYoZHJhZ21vZGUgPT09ICdwYW4nKSB7XG4gICAgICAgIHRoaXMubW91c2VDb250YWluZXIuc3R5bGUuY3Vyc29yID0gJ21vdmUnO1xuICAgIH0gZWxzZSBpZihkcmFnbW9kZSA9PT0gJ3pvb20nKSB7XG4gICAgICAgIHRoaXMubW91c2VDb250YWluZXIuc3R5bGUuY3Vyc29yID0gJ2Nyb3NzaGFpcic7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5tb3VzZUNvbnRhaW5lci5zdHlsZS5jdXJzb3IgPSBudWxsO1xuICAgIH1cbn07XG5cbnByb3RvLmVtaXRQb2ludEFjdGlvbiA9IGZ1bmN0aW9uKG5leHRTZWxlY3Rpb24sIGV2ZW50VHlwZSkge1xuICAgIHZhciB1aWQgPSBuZXh0U2VsZWN0aW9uLnRyYWNlLnVpZDtcbiAgICB2YXIgcHROdW1iZXIgPSBuZXh0U2VsZWN0aW9uLnBvaW50SW5kZXg7XG4gICAgdmFyIHRyYWNlO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRoaXMuZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYodGhpcy5mdWxsRGF0YVtpXS51aWQgPT09IHVpZCkge1xuICAgICAgICAgICAgdHJhY2UgPSB0aGlzLmZ1bGxEYXRhW2ldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHBvaW50RGF0YSA9IHtcbiAgICAgICAgeDogbmV4dFNlbGVjdGlvbi50cmFjZUNvb3JkWzBdLFxuICAgICAgICB5OiBuZXh0U2VsZWN0aW9uLnRyYWNlQ29vcmRbMV0sXG4gICAgICAgIGN1cnZlTnVtYmVyOiB0cmFjZS5pbmRleCxcbiAgICAgICAgcG9pbnROdW1iZXI6IHB0TnVtYmVyLFxuICAgICAgICBkYXRhOiB0cmFjZS5faW5wdXQsXG4gICAgICAgIGZ1bGxEYXRhOiB0aGlzLmZ1bGxEYXRhLFxuICAgICAgICB4YXhpczogdGhpcy54YXhpcyxcbiAgICAgICAgeWF4aXM6IHRoaXMueWF4aXNcbiAgICB9O1xuXG4gICAgRnguYXBwZW5kQXJyYXlQb2ludFZhbHVlKHBvaW50RGF0YSwgdHJhY2UsIHB0TnVtYmVyKTtcblxuICAgIHRoaXMuZ3JhcGhEaXYuZW1pdChldmVudFR5cGUsIHtwb2ludHM6IFtwb2ludERhdGFdfSk7XG59O1xuXG5wcm90by5kcmF3ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5zdG9wcGVkKSByZXR1cm47XG5cbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5yZWRyYXcpO1xuXG4gICAgdmFyIGdscGxvdCA9IHRoaXMuZ2xwbG90O1xuICAgIHZhciBjYW1lcmEgPSB0aGlzLmNhbWVyYTtcbiAgICB2YXIgbW91c2VMaXN0ZW5lciA9IGNhbWVyYS5tb3VzZUxpc3RlbmVyO1xuICAgIHZhciBtb3VzZVVwID0gdGhpcy5sYXN0QnV0dG9uU3RhdGUgPT09IDEgJiYgbW91c2VMaXN0ZW5lci5idXR0b25zID09PSAwO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gdGhpcy5mdWxsTGF5b3V0O1xuXG4gICAgdGhpcy5sYXN0QnV0dG9uU3RhdGUgPSBtb3VzZUxpc3RlbmVyLmJ1dHRvbnM7XG5cbiAgICB0aGlzLmNhbWVyYUNoYW5nZWQoKTtcblxuICAgIHZhciB4ID0gbW91c2VMaXN0ZW5lci54ICogZ2xwbG90LnBpeGVsUmF0aW87XG4gICAgdmFyIHkgPSB0aGlzLmNhbnZhcy5oZWlnaHQgLSBnbHBsb3QucGl4ZWxSYXRpbyAqIG1vdXNlTGlzdGVuZXIueTtcblxuICAgIHZhciByZXN1bHQ7XG5cbiAgICBpZihjYW1lcmEuYm94RW5hYmxlZCAmJiBmdWxsTGF5b3V0LmRyYWdtb2RlID09PSAnem9vbScpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RCb3guZW5hYmxlZCA9IHRydWU7XG5cbiAgICAgICAgdmFyIHNlbGVjdEJveCA9IHRoaXMuc2VsZWN0Qm94LnNlbGVjdEJveCA9IFtcbiAgICAgICAgICAgIE1hdGgubWluKGNhbWVyYS5ib3hTdGFydFswXSwgY2FtZXJhLmJveEVuZFswXSksXG4gICAgICAgICAgICBNYXRoLm1pbihjYW1lcmEuYm94U3RhcnRbMV0sIGNhbWVyYS5ib3hFbmRbMV0pLFxuICAgICAgICAgICAgTWF0aC5tYXgoY2FtZXJhLmJveFN0YXJ0WzBdLCBjYW1lcmEuYm94RW5kWzBdKSxcbiAgICAgICAgICAgIE1hdGgubWF4KGNhbWVyYS5ib3hTdGFydFsxXSwgY2FtZXJhLmJveEVuZFsxXSlcbiAgICAgICAgXTtcblxuICAgICAgICAvLyAxRCB6b29tXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGNhbWVyYS5ib3hTdGFydFtpXSA9PT0gY2FtZXJhLmJveEVuZFtpXSkge1xuICAgICAgICAgICAgICAgIHNlbGVjdEJveFtpXSA9IGdscGxvdC5kYXRhQm94W2ldO1xuICAgICAgICAgICAgICAgIHNlbGVjdEJveFtpICsgMl0gPSBnbHBsb3QuZGF0YUJveFtpICsgMl07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBnbHBsb3Quc2V0RGlydHkoKTtcbiAgICB9IGVsc2UgaWYoIWNhbWVyYS5wYW5uaW5nICYmIHRoaXMuaXNNb3VzZU92ZXIpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RCb3guZW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgICAgIHZhciBzaXplID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICAgICAgdmFyIGRvbWFpblggPSB0aGlzLnhheGlzLmRvbWFpbjtcbiAgICAgICAgdmFyIGRvbWFpblkgPSB0aGlzLnlheGlzLmRvbWFpbjtcblxuICAgICAgICByZXN1bHQgPSBnbHBsb3QucGljayhcbiAgICAgICAgICAgICh4IC8gZ2xwbG90LnBpeGVsUmF0aW8pICsgc2l6ZS5sICsgZG9tYWluWFswXSAqIHNpemUudyxcbiAgICAgICAgICAgICh5IC8gZ2xwbG90LnBpeGVsUmF0aW8pIC0gKHNpemUudCArICgxIC0gZG9tYWluWVsxXSkgKiBzaXplLmgpXG4gICAgICAgICk7XG5cbiAgICAgICAgdmFyIG5leHRTZWxlY3Rpb24gPSByZXN1bHQgJiYgcmVzdWx0Lm9iamVjdC5fdHJhY2UuaGFuZGxlUGljayhyZXN1bHQpO1xuXG4gICAgICAgIGlmKG5leHRTZWxlY3Rpb24gJiYgbW91c2VVcCkge1xuICAgICAgICAgICAgdGhpcy5lbWl0UG9pbnRBY3Rpb24obmV4dFNlbGVjdGlvbiwgJ3Bsb3RseV9jbGljaycpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYocmVzdWx0ICYmIHJlc3VsdC5vYmplY3QuX3RyYWNlLmhvdmVyaW5mbyAhPT0gJ3NraXAnICYmIGZ1bGxMYXlvdXQuaG92ZXJtb2RlKSB7XG4gICAgICAgICAgICBpZihuZXh0U2VsZWN0aW9uICYmIChcbiAgICAgICAgICAgICAgICAhdGhpcy5sYXN0UGlja1Jlc3VsdCB8fFxuICAgICAgICAgICAgICAgIHRoaXMubGFzdFBpY2tSZXN1bHQudHJhY2VVaWQgIT09IG5leHRTZWxlY3Rpb24udHJhY2UudWlkIHx8XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UGlja1Jlc3VsdC5kYXRhQ29vcmRbMF0gIT09IG5leHRTZWxlY3Rpb24uZGF0YUNvb3JkWzBdIHx8XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UGlja1Jlc3VsdC5kYXRhQ29vcmRbMV0gIT09IG5leHRTZWxlY3Rpb24uZGF0YUNvb3JkWzFdKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlbGVjdGlvbiA9IG5leHRTZWxlY3Rpb247XG5cbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RQaWNrUmVzdWx0ID0ge1xuICAgICAgICAgICAgICAgICAgICB0cmFjZVVpZDogbmV4dFNlbGVjdGlvbi50cmFjZSA/IG5leHRTZWxlY3Rpb24udHJhY2UudWlkIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgZGF0YUNvb3JkOiBuZXh0U2VsZWN0aW9uLmRhdGFDb29yZC5zbGljZSgpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnNwaWtlcy51cGRhdGUoeyBjZW50ZXI6IHJlc3VsdC5kYXRhQ29vcmQgfSk7XG5cbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24uc2NyZWVuQ29vcmQgPSBbXG4gICAgICAgICAgICAgICAgICAgICgoZ2xwbG90LnZpZXdCb3hbMl0gLSBnbHBsb3Qudmlld0JveFswXSkgKlxuICAgICAgICAgICAgICAgICAgICAocmVzdWx0LmRhdGFDb29yZFswXSAtIGdscGxvdC5kYXRhQm94WzBdKSAvXG4gICAgICAgICAgICAgICAgICAgICAgICAoZ2xwbG90LmRhdGFCb3hbMl0gLSBnbHBsb3QuZGF0YUJveFswXSkgKyBnbHBsb3Qudmlld0JveFswXSkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdscGxvdC5waXhlbFJhdGlvLFxuICAgICAgICAgICAgICAgICAgICAodGhpcy5jYW52YXMuaGVpZ2h0IC0gKGdscGxvdC52aWV3Qm94WzNdIC0gZ2xwbG90LnZpZXdCb3hbMV0pICpcbiAgICAgICAgICAgICAgICAgICAgKHJlc3VsdC5kYXRhQ29vcmRbMV0gLSBnbHBsb3QuZGF0YUJveFsxXSkgL1xuICAgICAgICAgICAgICAgICAgICAgICAgKGdscGxvdC5kYXRhQm94WzNdIC0gZ2xwbG90LmRhdGFCb3hbMV0pIC0gZ2xwbG90LnZpZXdCb3hbMV0pIC9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnbHBsb3QucGl4ZWxSYXRpb1xuICAgICAgICAgICAgICAgIF07XG5cbiAgICAgICAgICAgICAgICAvLyB0aGlzIG5lZWRzIHRvIGhhcHBlbiBiZWZvcmUgdGhlIG5leHQgYmxvY2sgdGhhdCBkZWxldGVzIHRyYWNlQ29vcmQgZGF0YVxuICAgICAgICAgICAgICAgIC8vIGFsc28gaXQncyBpbXBvcnRhbnQgdG8gY29weSwgb3RoZXJ3aXNlIGRhdGEgaXMgbG9zdCBieSB0aGUgdGltZSBldmVudCBkYXRhIGlzIHJlYWRcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRQb2ludEFjdGlvbihuZXh0U2VsZWN0aW9uLCAncGxvdGx5X2hvdmVyJyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgdHJhY2UgPSB0aGlzLmZ1bGxEYXRhW3NlbGVjdGlvbi50cmFjZS5pbmRleF0gfHwge307XG4gICAgICAgICAgICAgICAgdmFyIHB0TnVtYmVyID0gc2VsZWN0aW9uLnBvaW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGhvdmVyaW5mbyA9IEZ4LmNhc3RIb3ZlcmluZm8odHJhY2UsIGZ1bGxMYXlvdXQsIHB0TnVtYmVyKTtcblxuICAgICAgICAgICAgICAgIGlmKGhvdmVyaW5mbyAmJiBob3ZlcmluZm8gIT09ICdhbGwnKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJ0cyA9IGhvdmVyaW5mby5zcGxpdCgnKycpO1xuICAgICAgICAgICAgICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCd4JykgPT09IC0xKSBzZWxlY3Rpb24udHJhY2VDb29yZFswXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgaWYocGFydHMuaW5kZXhPZigneScpID09PSAtMSkgc2VsZWN0aW9uLnRyYWNlQ29vcmRbMV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIGlmKHBhcnRzLmluZGV4T2YoJ3onKSA9PT0gLTEpIHNlbGVjdGlvbi50cmFjZUNvb3JkWzJdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCd0ZXh0JykgPT09IC0xKSBzZWxlY3Rpb24udGV4dExhYmVsID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCduYW1lJykgPT09IC0xKSBzZWxlY3Rpb24ubmFtZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBGeC5sb25lSG92ZXIoe1xuICAgICAgICAgICAgICAgICAgICB4OiBzZWxlY3Rpb24uc2NyZWVuQ29vcmRbMF0sXG4gICAgICAgICAgICAgICAgICAgIHk6IHNlbGVjdGlvbi5zY3JlZW5Db29yZFsxXSxcbiAgICAgICAgICAgICAgICAgICAgeExhYmVsOiB0aGlzLmhvdmVyRm9ybWF0dGVyKCd4YXhpcycsIHNlbGVjdGlvbi50cmFjZUNvb3JkWzBdKSxcbiAgICAgICAgICAgICAgICAgICAgeUxhYmVsOiB0aGlzLmhvdmVyRm9ybWF0dGVyKCd5YXhpcycsIHNlbGVjdGlvbi50cmFjZUNvb3JkWzFdKSxcbiAgICAgICAgICAgICAgICAgICAgekxhYmVsOiBzZWxlY3Rpb24udHJhY2VDb29yZFsyXSxcbiAgICAgICAgICAgICAgICAgICAgdGV4dDogc2VsZWN0aW9uLnRleHRMYWJlbCxcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogc2VsZWN0aW9uLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGNvbG9yOiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnYmdjb2xvcicpIHx8IHNlbGVjdGlvbi5jb2xvcixcbiAgICAgICAgICAgICAgICAgICAgYm9yZGVyQ29sb3I6IEZ4LmNhc3RIb3Zlck9wdGlvbih0cmFjZSwgcHROdW1iZXIsICdib3JkZXJjb2xvcicpLFxuICAgICAgICAgICAgICAgICAgICBmb250RmFtaWx5OiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnZm9udC5mYW1pbHknKSxcbiAgICAgICAgICAgICAgICAgICAgZm9udFNpemU6IEZ4LmNhc3RIb3Zlck9wdGlvbih0cmFjZSwgcHROdW1iZXIsICdmb250LnNpemUnKSxcbiAgICAgICAgICAgICAgICAgICAgZm9udENvbG9yOiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnZm9udC5jb2xvcicpLFxuICAgICAgICAgICAgICAgICAgICBuYW1lTGVuZ3RoOiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnbmFtZWxlbmd0aCcpLFxuICAgICAgICAgICAgICAgICAgICB0ZXh0QWxpZ246IEZ4LmNhc3RIb3Zlck9wdGlvbih0cmFjZSwgcHROdW1iZXIsICdhbGlnbicpXG4gICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICBjb250YWluZXI6IHRoaXMuc3ZnQ29udGFpbmVyLFxuICAgICAgICAgICAgICAgICAgICBnZDogdGhpcy5ncmFwaERpdlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIGhvdmVyIGVmZmVjdHMgaWYgd2UncmUgbm90IG92ZXIgYSBwb2ludCBPUlxuICAgIC8vIGlmIHdlJ3JlIHpvb21pbmcgb3IgcGFubmluZyAoaW4gd2hpY2ggY2FzZSByZXN1bHQgaXMgbm90IHNldClcbiAgICBpZighcmVzdWx0KSB7XG4gICAgICAgIHRoaXMudW5ob3ZlcigpO1xuICAgIH1cblxuICAgIGdscGxvdC5kcmF3KCk7XG59O1xuXG5wcm90by51bmhvdmVyID0gZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5sYXN0UGlja1Jlc3VsdCkge1xuICAgICAgICB0aGlzLnNwaWtlcy51cGRhdGUoe30pO1xuICAgICAgICB0aGlzLmxhc3RQaWNrUmVzdWx0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5ncmFwaERpdi5lbWl0KCdwbG90bHlfdW5ob3ZlcicpO1xuICAgICAgICBGeC5sb25lVW5ob3Zlcih0aGlzLnN2Z0NvbnRhaW5lcik7XG4gICAgfVxufTtcblxucHJvdG8uaG92ZXJGb3JtYXR0ZXIgPSBmdW5jdGlvbihheGlzTmFtZSwgdmFsKSB7XG4gICAgaWYodmFsID09PSB1bmRlZmluZWQpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICB2YXIgYXhpcyA9IHRoaXNbYXhpc05hbWVdO1xuICAgIHJldHVybiBBeGVzLnRpY2tUZXh0KGF4aXMsIGF4aXMuYzJsKHZhbCksICdob3ZlcicpLnRleHQ7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvZnhcIjo2MzIsXCIuLi8uLi9saWIvc2hvd19ub193ZWJnbF9tc2dcIjo3NDAsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vY2FydGVzaWFuL2F1dG9yYW5nZVwiOjc2NixcIi4uL2NhcnRlc2lhbi9jb25zdGFudHNcIjo3NzMsXCIuLi9jYXJ0ZXNpYW4vY29uc3RyYWludHNcIjo3NzQsXCIuL2NhbWVyYVwiOjgwMyxcIi4vY29udmVydFwiOjgwNCxcImdsLXBsb3QyZFwiOjI4NyxcImdsLXNlbGVjdC1ib3hcIjoyOTksXCJnbC1zcGlrZXMyZFwiOjMwOCxcIndlYmdsLWNvbnRleHRcIjo1NTZ9XSw4MDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcbnZhciBmeEF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG52YXIgU2NlbmUgPSBfZGVyZXFfKCcuL3NjZW5lJyk7XG52YXIgZ2V0U3VicGxvdERhdGEgPSBfZGVyZXFfKCcuLi9nZXRfZGF0YScpLmdldFN1YnBsb3REYXRhO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHhtbG5zTmFtZXNwYWNlcyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzJyk7XG5cbnZhciBHTDNEID0gJ2dsM2QnO1xudmFyIFNDRU5FID0gJ3NjZW5lJztcblxuXG5leHBvcnRzLm5hbWUgPSBHTDNEO1xuXG5leHBvcnRzLmF0dHIgPSBTQ0VORTtcblxuZXhwb3J0cy5pZFJvb3QgPSBTQ0VORTtcblxuZXhwb3J0cy5pZFJlZ2V4ID0gZXhwb3J0cy5hdHRyUmVnZXggPSBMaWIuY291bnRlclJlZ2V4KCdzY2VuZScpO1xuXG5leHBvcnRzLmF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dC9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMubGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vbGF5b3V0L2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMuYmFzZUxheW91dEF0dHJPdmVycmlkZXMgPSBvdmVycmlkZUFsbCh7XG4gICAgaG92ZXJsYWJlbDogZnhBdHRycy5ob3ZlcmxhYmVsXG59LCAncGxvdCcsICduZXN0ZWQnKTtcblxuZXhwb3J0cy5zdXBwbHlMYXlvdXREZWZhdWx0cyA9IF9kZXJlcV8oJy4vbGF5b3V0L2RlZmF1bHRzJyk7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uIHBsb3QoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBmdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICB2YXIgc2NlbmVJZHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90c1tHTDNEXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzY2VuZUlkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc2NlbmVJZCA9IHNjZW5lSWRzW2ldO1xuICAgICAgICB2YXIgZnVsbFNjZW5lRGF0YSA9IGdldFN1YnBsb3REYXRhKGZ1bGxEYXRhLCBHTDNELCBzY2VuZUlkKTtcbiAgICAgICAgdmFyIHNjZW5lTGF5b3V0ID0gZnVsbExheW91dFtzY2VuZUlkXTtcbiAgICAgICAgdmFyIGNhbWVyYSA9IHNjZW5lTGF5b3V0LmNhbWVyYTtcbiAgICAgICAgdmFyIHNjZW5lID0gc2NlbmVMYXlvdXQuX3NjZW5lO1xuXG4gICAgICAgIGlmKCFzY2VuZSkge1xuICAgICAgICAgICAgc2NlbmUgPSBuZXcgU2NlbmUoe1xuICAgICAgICAgICAgICAgIGlkOiBzY2VuZUlkLFxuICAgICAgICAgICAgICAgIGdyYXBoRGl2OiBnZCxcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IGdkLnF1ZXJ5U2VsZWN0b3IoJy5nbC1jb250YWluZXInKSxcbiAgICAgICAgICAgICAgICBzdGF0aWNQbG90OiBnZC5fY29udGV4dC5zdGF0aWNQbG90LFxuICAgICAgICAgICAgICAgIHBsb3RHbFBpeGVsUmF0aW86IGdkLl9jb250ZXh0LnBsb3RHbFBpeGVsUmF0aW8sXG4gICAgICAgICAgICAgICAgY2FtZXJhOiBjYW1lcmFcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZnVsbExheW91dFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgLy8gc2V0IHJlZiB0byBTY2VuZSBpbnN0YW5jZVxuICAgICAgICAgICAgc2NlbmVMYXlvdXQuX3NjZW5lID0gc2NlbmU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzYXZlICdpbml0aWFsJyBjYW1lcmEgdmlldyBzZXR0aW5ncyBmb3IgbW9kZWJhciBidXR0b25cbiAgICAgICAgaWYoIXNjZW5lLnZpZXdJbml0aWFsKSB7XG4gICAgICAgICAgICBzY2VuZS52aWV3SW5pdGlhbCA9IHtcbiAgICAgICAgICAgICAgICB1cDoge1xuICAgICAgICAgICAgICAgICAgICB4OiBjYW1lcmEudXAueCxcbiAgICAgICAgICAgICAgICAgICAgeTogY2FtZXJhLnVwLnksXG4gICAgICAgICAgICAgICAgICAgIHo6IGNhbWVyYS51cC56XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBleWU6IHtcbiAgICAgICAgICAgICAgICAgICAgeDogY2FtZXJhLmV5ZS54LFxuICAgICAgICAgICAgICAgICAgICB5OiBjYW1lcmEuZXllLnksXG4gICAgICAgICAgICAgICAgICAgIHo6IGNhbWVyYS5leWUuelxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY2VudGVyOiB7XG4gICAgICAgICAgICAgICAgICAgIHg6IGNhbWVyYS5jZW50ZXIueCxcbiAgICAgICAgICAgICAgICAgICAgeTogY2FtZXJhLmNlbnRlci55LFxuICAgICAgICAgICAgICAgICAgICB6OiBjYW1lcmEuY2VudGVyLnpcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgc2NlbmUucGxvdChmdWxsU2NlbmVEYXRhLCBmdWxsTGF5b3V0LCBnZC5sYXlvdXQpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgb2xkU2NlbmVLZXlzID0gb2xkRnVsbExheW91dC5fc3VicGxvdHNbR0wzRF0gfHwgW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgb2xkU2NlbmVLZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvbGRTY2VuZUtleSA9IG9sZFNjZW5lS2V5c1tpXTtcblxuICAgICAgICBpZighbmV3RnVsbExheW91dFtvbGRTY2VuZUtleV0gJiYgISFvbGRGdWxsTGF5b3V0W29sZFNjZW5lS2V5XS5fc2NlbmUpIHtcbiAgICAgICAgICAgIG9sZEZ1bGxMYXlvdXRbb2xkU2NlbmVLZXldLl9zY2VuZS5kZXN0cm95KCk7XG5cbiAgICAgICAgICAgIGlmKG9sZEZ1bGxMYXlvdXQuX2luZm9sYXllcikge1xuICAgICAgICAgICAgICAgIG9sZEZ1bGxMYXlvdXQuX2luZm9sYXllclxuICAgICAgICAgICAgICAgICAgICAuc2VsZWN0QWxsKCcuYW5ub3RhdGlvbi0nICsgb2xkU2NlbmVLZXkpXG4gICAgICAgICAgICAgICAgICAgIC5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmV4cG9ydHMudG9TVkcgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHNjZW5lSWRzID0gZnVsbExheW91dC5fc3VicGxvdHNbR0wzRF07XG4gICAgdmFyIHNpemUgPSBmdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNjZW5lSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBzY2VuZUxheW91dCA9IGZ1bGxMYXlvdXRbc2NlbmVJZHNbaV1dO1xuICAgICAgICB2YXIgZG9tYWluID0gc2NlbmVMYXlvdXQuZG9tYWluO1xuICAgICAgICB2YXIgc2NlbmUgPSBzY2VuZUxheW91dC5fc2NlbmU7XG5cbiAgICAgICAgdmFyIGltYWdlRGF0YSA9IHNjZW5lLnRvSW1hZ2UoJ3BuZycpO1xuICAgICAgICB2YXIgaW1hZ2UgPSBmdWxsTGF5b3V0Ll9nbGltYWdlcy5hcHBlbmQoJ3N2ZzppbWFnZScpO1xuXG4gICAgICAgIGltYWdlLmF0dHIoe1xuICAgICAgICAgICAgeG1sbnM6IHhtbG5zTmFtZXNwYWNlcy5zdmcsXG4gICAgICAgICAgICAneGxpbms6aHJlZic6IGltYWdlRGF0YSxcbiAgICAgICAgICAgIHg6IHNpemUubCArIHNpemUudyAqIGRvbWFpbi54WzBdLFxuICAgICAgICAgICAgeTogc2l6ZS50ICsgc2l6ZS5oICogKDEgLSBkb21haW4ueVsxXSksXG4gICAgICAgICAgICB3aWR0aDogc2l6ZS53ICogKGRvbWFpbi54WzFdIC0gZG9tYWluLnhbMF0pLFxuICAgICAgICAgICAgaGVpZ2h0OiBzaXplLmggKiAoZG9tYWluLnlbMV0gLSBkb21haW4ueVswXSksXG4gICAgICAgICAgICBwcmVzZXJ2ZUFzcGVjdFJhdGlvOiAnbm9uZSdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2NlbmUuZGVzdHJveSgpO1xuICAgIH1cbn07XG5cbi8vIGNsZWFuIHNjZW5lIGlkcywgJ3NjZW5lMScgLT4gJ3NjZW5lJ1xuZXhwb3J0cy5jbGVhbklkID0gZnVuY3Rpb24gY2xlYW5JZChpZCkge1xuICAgIGlmKCFpZC5tYXRjaCgvXnNjZW5lWzAtOV0qJC8pKSByZXR1cm47XG5cbiAgICB2YXIgc2NlbmVOdW0gPSBpZC5zdWJzdHIoNSk7XG4gICAgaWYoc2NlbmVOdW0gPT09ICcxJykgc2NlbmVOdW0gPSAnJztcblxuICAgIHJldHVybiBTQ0VORSArIHNjZW5lTnVtO1xufTtcblxuZXhwb3J0cy51cGRhdGVGeCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VicGxvdElkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW0dMM0RdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHN1YnBsb3RPYmogPSBmdWxsTGF5b3V0W3N1YnBsb3RJZHNbaV1dLl9zY2VuZTtcbiAgICAgICAgc3VicGxvdE9iai51cGRhdGVGeChmdWxsTGF5b3V0LmRyYWdtb2RlLCBmdWxsTGF5b3V0LmhvdmVybW9kZSk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2Z4L2xheW91dF9hdHRyaWJ1dGVzXCI6NjMzLFwiLi4vLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXNcIjo2OTYsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vZ2V0X2RhdGFcIjo4MDIsXCIuL2xheW91dC9hdHRyaWJ1dGVzXCI6ODA4LFwiLi9sYXlvdXQvZGVmYXVsdHNcIjo4MTIsXCIuL2xheW91dC9sYXlvdXRfYXR0cmlidXRlc1wiOjgxMyxcIi4vc2NlbmVcIjo4MTd9XSw4MDg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHNjZW5lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ3NjZW5lJyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7fV0sODA5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGF4ZXNBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxubW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4gICAgdmlzaWJsZTogYXhlc0F0dHJzLnZpc2libGUsXG4gICAgc2hvd3NwaWtlczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNwaWtlc2lkZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzcGlrZXRoaWNrbmVzczoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMixcbiAgICAgICAgXG4gICAgfSxcbiAgICBzcGlrZWNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBDb2xvci5kZWZhdWx0TGluZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93YmFja2dyb3VuZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiYWNrZ3JvdW5kY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICdyZ2JhKDIwNCwgMjA0LCAyMDQsIDAuNSknLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dheGVzbGFiZWxzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY29sb3I6IGF4ZXNBdHRycy5jb2xvcixcbiAgICBjYXRlZ29yeW9yZGVyOiBheGVzQXR0cnMuY2F0ZWdvcnlvcmRlcixcbiAgICBjYXRlZ29yeWFycmF5OiBheGVzQXR0cnMuY2F0ZWdvcnlhcnJheSxcbiAgICB0aXRsZTogYXhlc0F0dHJzLnRpdGxlLFxuICAgIHR5cGU6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy50eXBlLCB7XG4gICAgICAgIHZhbHVlczogWyctJywgJ2xpbmVhcicsICdsb2cnLCAnZGF0ZScsICdjYXRlZ29yeSddXG4gICAgfSksXG4gICAgYXV0b3JhbmdlOiBheGVzQXR0cnMuYXV0b3JhbmdlLFxuICAgIHJhbmdlbW9kZTogYXhlc0F0dHJzLnJhbmdlbW9kZSxcbiAgICByYW5nZTogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLnJhbmdlLCB7XG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAncGxvdCcsIGltcGxpZWRFZGl0czogeydeYXV0b3JhbmdlJzogZmFsc2V9fSxcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdwbG90JywgaW1wbGllZEVkaXRzOiB7J15hdXRvcmFuZ2UnOiBmYWxzZX19XG4gICAgICAgIF0sXG4gICAgICAgIGFuaW06IGZhbHNlXG4gICAgfSksXG4gICAgLy8gdGlja3NcbiAgICB0aWNrbW9kZTogYXhlc0F0dHJzLnRpY2ttb2RlLFxuICAgIG50aWNrczogYXhlc0F0dHJzLm50aWNrcyxcbiAgICB0aWNrMDogYXhlc0F0dHJzLnRpY2swLFxuICAgIGR0aWNrOiBheGVzQXR0cnMuZHRpY2ssXG4gICAgdGlja3ZhbHM6IGF4ZXNBdHRycy50aWNrdmFscyxcbiAgICB0aWNrdGV4dDogYXhlc0F0dHJzLnRpY2t0ZXh0LFxuICAgIHRpY2tzOiBheGVzQXR0cnMudGlja3MsXG4gICAgbWlycm9yOiBheGVzQXR0cnMubWlycm9yLFxuICAgIHRpY2tsZW46IGF4ZXNBdHRycy50aWNrbGVuLFxuICAgIHRpY2t3aWR0aDogYXhlc0F0dHJzLnRpY2t3aWR0aCxcbiAgICB0aWNrY29sb3I6IGF4ZXNBdHRycy50aWNrY29sb3IsXG4gICAgc2hvd3RpY2tsYWJlbHM6IGF4ZXNBdHRycy5zaG93dGlja2xhYmVscyxcbiAgICB0aWNrZm9udDogYXhlc0F0dHJzLnRpY2tmb250LFxuICAgIHRpY2thbmdsZTogYXhlc0F0dHJzLnRpY2thbmdsZSxcbiAgICB0aWNrcHJlZml4OiBheGVzQXR0cnMudGlja3ByZWZpeCxcbiAgICBzaG93dGlja3ByZWZpeDogYXhlc0F0dHJzLnNob3d0aWNrcHJlZml4LFxuICAgIHRpY2tzdWZmaXg6IGF4ZXNBdHRycy50aWNrc3VmZml4LFxuICAgIHNob3d0aWNrc3VmZml4OiBheGVzQXR0cnMuc2hvd3RpY2tzdWZmaXgsXG4gICAgc2hvd2V4cG9uZW50OiBheGVzQXR0cnMuc2hvd2V4cG9uZW50LFxuICAgIGV4cG9uZW50Zm9ybWF0OiBheGVzQXR0cnMuZXhwb25lbnRmb3JtYXQsXG4gICAgc2VwYXJhdGV0aG91c2FuZHM6IGF4ZXNBdHRycy5zZXBhcmF0ZXRob3VzYW5kcyxcbiAgICB0aWNrZm9ybWF0OiBheGVzQXR0cnMudGlja2Zvcm1hdCxcbiAgICB0aWNrZm9ybWF0c3RvcHM6IGF4ZXNBdHRycy50aWNrZm9ybWF0c3RvcHMsXG4gICAgaG92ZXJmb3JtYXQ6IGF4ZXNBdHRycy5ob3ZlcmZvcm1hdCxcbiAgICAvLyBsaW5lcyBhbmQgZ3JpZHNcbiAgICBzaG93bGluZTogYXhlc0F0dHJzLnNob3dsaW5lLFxuICAgIGxpbmVjb2xvcjogYXhlc0F0dHJzLmxpbmVjb2xvcixcbiAgICBsaW5ld2lkdGg6IGF4ZXNBdHRycy5saW5ld2lkdGgsXG4gICAgc2hvd2dyaWQ6IGF4ZXNBdHRycy5zaG93Z3JpZCxcbiAgICBncmlkY29sb3I6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy5ncmlkY29sb3IsICAvLyBzaG91bGRuJ3QgdGhpcyBiZSBvbi1wYXIgd2l0aCAyRD9cbiAgICAgICAge2RmbHQ6ICdyZ2IoMjA0LCAyMDQsIDIwNCknfSksXG4gICAgZ3JpZHdpZHRoOiBheGVzQXR0cnMuZ3JpZHdpZHRoLFxuICAgIHplcm9saW5lOiBheGVzQXR0cnMuemVyb2xpbmUsXG4gICAgemVyb2xpbmVjb2xvcjogYXhlc0F0dHJzLnplcm9saW5lY29sb3IsXG4gICAgemVyb2xpbmV3aWR0aDogYXhlc0F0dHJzLnplcm9saW5ld2lkdGgsXG4gICAgX2RlcHJlY2F0ZWQ6IHtcbiAgICAgICAgdGl0bGU6IGF4ZXNBdHRycy5fZGVwcmVjYXRlZC50aXRsZSxcbiAgICAgICAgdGl0bGVmb250OiBheGVzQXR0cnMuX2RlcHJlY2F0ZWQudGl0bGVmb250XG4gICAgfVxufSwgJ3Bsb3QnLCAnZnJvbS1yb290Jyk7XG5cbn0se1wiLi4vLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vY2FydGVzaWFuL2xheW91dF9hdHRyaWJ1dGVzXCI6Nzc5fV0sODEwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JNaXggPSBfZGVyZXFfKCd0aW55Y29sb3IyJykubWl4O1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vLi4vbGliJyk7XG52YXIgVGVtcGxhdGUgPSBfZGVyZXFfKCcuLi8uLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJyk7XG5cbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9heGlzX2F0dHJpYnV0ZXMnKTtcbnZhciBoYW5kbGVUeXBlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9jYXJ0ZXNpYW4vdHlwZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUF4aXNEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL2NhcnRlc2lhbi9heGlzX2RlZmF1bHRzJyk7XG5cbnZhciBheGVzTmFtZXMgPSBbJ3hheGlzJywgJ3lheGlzJywgJ3pheGlzJ107XG5cbi8vIFRPRE86IGhhcmQtY29kZWQgbGlnaHRuZXNzIGZyYWN0aW9uIGJhc2VkIG9uIGdyaWRsaW5lIGRlZmF1bHQgY29sb3JzXG4vLyB0aGF0IGRpZmZlciBmcm9tIG90aGVyIHN1YnBsb3QgdHlwZXMuXG52YXIgZ3JpZExpZ2h0bmVzcyA9IDEwMCAqICgyMDQgLSAweDQ0KSAvICgyNTUgLSAweDQ0KTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBvcHRpb25zKSB7XG4gICAgdmFyIGNvbnRhaW5lckluLCBjb250YWluZXJPdXQ7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBsYXlvdXRBdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGogPSAwOyBqIDwgYXhlc05hbWVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHZhciBheE5hbWUgPSBheGVzTmFtZXNbal07XG4gICAgICAgIGNvbnRhaW5lckluID0gbGF5b3V0SW5bYXhOYW1lXSB8fCB7fTtcblxuICAgICAgICBjb250YWluZXJPdXQgPSBUZW1wbGF0ZS5uZXdDb250YWluZXIobGF5b3V0T3V0LCBheE5hbWUpO1xuICAgICAgICBjb250YWluZXJPdXQuX2lkID0gYXhOYW1lWzBdICsgb3B0aW9ucy5zY2VuZTtcbiAgICAgICAgY29udGFpbmVyT3V0Ll9uYW1lID0gYXhOYW1lO1xuXG4gICAgICAgIGhhbmRsZVR5cGVEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIG9wdGlvbnMpO1xuXG4gICAgICAgIGhhbmRsZUF4aXNEZWZhdWx0cyhcbiAgICAgICAgICAgIGNvbnRhaW5lckluLFxuICAgICAgICAgICAgY29udGFpbmVyT3V0LFxuICAgICAgICAgICAgY29lcmNlLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGZvbnQ6IG9wdGlvbnMuZm9udCxcbiAgICAgICAgICAgICAgICBsZXR0ZXI6IGF4TmFtZVswXSxcbiAgICAgICAgICAgICAgICBkYXRhOiBvcHRpb25zLmRhdGEsXG4gICAgICAgICAgICAgICAgc2hvd0dyaWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgbm9UaWNrc29uOiB0cnVlLFxuICAgICAgICAgICAgICAgIGJnQ29sb3I6IG9wdGlvbnMuYmdDb2xvcixcbiAgICAgICAgICAgICAgICBjYWxlbmRhcjogb3B0aW9ucy5jYWxlbmRhclxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbnMuZnVsbExheW91dCk7XG5cbiAgICAgICAgY29lcmNlKCdncmlkY29sb3InLCBjb2xvck1peChjb250YWluZXJPdXQuY29sb3IsIG9wdGlvbnMuYmdDb2xvciwgZ3JpZExpZ2h0bmVzcykudG9SZ2JTdHJpbmcoKSk7XG4gICAgICAgIGNvZXJjZSgndGl0bGUudGV4dCcsIGF4TmFtZVswXSk7ICAvLyBzaG91bGRuJ3QgdGhpcyBiZSBvbi1wYXIgd2l0aCAyRD9cblxuICAgICAgICBjb250YWluZXJPdXQuc2V0U2NhbGUgPSBMaWIubm9vcDtcblxuICAgICAgICBpZihjb2VyY2UoJ3Nob3dzcGlrZXMnKSkge1xuICAgICAgICAgICAgY29lcmNlKCdzcGlrZXNpZGVzJyk7XG4gICAgICAgICAgICBjb2VyY2UoJ3NwaWtldGhpY2tuZXNzJyk7XG4gICAgICAgICAgICBjb2VyY2UoJ3NwaWtlY29sb3InLCBjb250YWluZXJPdXQuY29sb3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29lcmNlKCdzaG93YXhlc2xhYmVscycpO1xuICAgICAgICBpZihjb2VyY2UoJ3Nob3diYWNrZ3JvdW5kJykpIGNvZXJjZSgnYmFja2dyb3VuZGNvbG9yJyk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi8uLi9saWJcIjo3MTksXCIuLi8uLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi4vLi4vY2FydGVzaWFuL2F4aXNfZGVmYXVsdHNcIjo3NjksXCIuLi8uLi9jYXJ0ZXNpYW4vdHlwZV9kZWZhdWx0c1wiOjc5MCxcIi4vYXhpc19hdHRyaWJ1dGVzXCI6ODA5LFwidGlueWNvbG9yMlwiOjUzN31dLDgxMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzdHIyUmdiYUFycmF5ID0gX2RlcmVxXygnLi4vLi4vLi4vbGliL3N0cjJyZ2JhcnJheScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uLy4uL2xpYicpO1xuXG52YXIgQVhFU19OQU1FUyA9IFsneGF4aXMnLCAneWF4aXMnLCAnemF4aXMnXTtcblxuZnVuY3Rpb24gQXhlc09wdGlvbnMoKSB7XG4gICAgdGhpcy5ib3VuZHMgPSBbXG4gICAgICAgIFstMTAsIC0xMCwgLTEwXSxcbiAgICAgICAgWzEwLCAxMCwgMTBdXG4gICAgXTtcblxuICAgIHRoaXMudGlja3MgPSBbIFtdLCBbXSwgW10gXTtcbiAgICB0aGlzLnRpY2tFbmFibGUgPSBbIHRydWUsIHRydWUsIHRydWUgXTtcbiAgICB0aGlzLnRpY2tGb250ID0gWyAnc2Fucy1zZXJpZicsICdzYW5zLXNlcmlmJywgJ3NhbnMtc2VyaWYnIF07XG4gICAgdGhpcy50aWNrU2l6ZSA9IFsgMTIsIDEyLCAxMiBdO1xuICAgIHRoaXMudGlja0FuZ2xlID0gWyAwLCAwLCAwIF07XG4gICAgdGhpcy50aWNrQ29sb3IgPSBbIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0gXTtcbiAgICB0aGlzLnRpY2tQYWQgPSBbIDE4LCAxOCwgMTggXTtcblxuICAgIHRoaXMubGFiZWxzID0gWyAneCcsICd5JywgJ3onIF07XG4gICAgdGhpcy5sYWJlbEVuYWJsZSA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdO1xuICAgIHRoaXMubGFiZWxGb250ID0gWydPcGVuIFNhbnMnLCAnT3BlbiBTYW5zJywgJ09wZW4gU2FucyddO1xuICAgIHRoaXMubGFiZWxTaXplID0gWyAyMCwgMjAsIDIwIF07XG4gICAgdGhpcy5sYWJlbENvbG9yID0gWyBbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdIF07XG4gICAgdGhpcy5sYWJlbFBhZCA9IFsgMzAsIDMwLCAzMCBdO1xuXG4gICAgdGhpcy5saW5lRW5hYmxlID0gWyB0cnVlLCB0cnVlLCB0cnVlIF07XG4gICAgdGhpcy5saW5lTWlycm9yID0gWyBmYWxzZSwgZmFsc2UsIGZhbHNlIF07XG4gICAgdGhpcy5saW5lV2lkdGggPSBbIDEsIDEsIDEgXTtcbiAgICB0aGlzLmxpbmVDb2xvciA9IFsgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXSBdO1xuXG4gICAgdGhpcy5saW5lVGlja0VuYWJsZSA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdO1xuICAgIHRoaXMubGluZVRpY2tNaXJyb3IgPSBbIGZhbHNlLCBmYWxzZSwgZmFsc2UgXTtcbiAgICB0aGlzLmxpbmVUaWNrTGVuZ3RoID0gWyAxMCwgMTAsIDEwIF07XG4gICAgdGhpcy5saW5lVGlja1dpZHRoID0gWyAxLCAxLCAxIF07XG4gICAgdGhpcy5saW5lVGlja0NvbG9yID0gWyBbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdIF07XG5cbiAgICB0aGlzLmdyaWRFbmFibGUgPSBbIHRydWUsIHRydWUsIHRydWUgXTtcbiAgICB0aGlzLmdyaWRXaWR0aCA9IFsgMSwgMSwgMSBdO1xuICAgIHRoaXMuZ3JpZENvbG9yID0gWyBbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdIF07XG5cbiAgICB0aGlzLnplcm9FbmFibGUgPSBbIHRydWUsIHRydWUsIHRydWUgXTtcbiAgICB0aGlzLnplcm9MaW5lQ29sb3IgPSBbIFswLCAwLCAwLCAxXSwgWzAsIDAsIDAsIDFdLCBbMCwgMCwgMCwgMV0gXTtcbiAgICB0aGlzLnplcm9MaW5lV2lkdGggPSBbIDIsIDIsIDIgXTtcblxuICAgIHRoaXMuYmFja2dyb3VuZEVuYWJsZSA9IFsgdHJ1ZSwgdHJ1ZSwgdHJ1ZSBdO1xuICAgIHRoaXMuYmFja2dyb3VuZENvbG9yID0gWyBbMC44LCAwLjgsIDAuOCwgMC41XSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFswLjgsIDAuOCwgMC44LCAwLjVdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWzAuOCwgMC44LCAwLjgsIDAuNV0gXTtcblxuICAgIC8vIHNvbWUgZGVmYXVsdCB2YWx1ZXMgYXJlIHN0b3JlZCBmb3IgYXBwbHlpbmcgbW9kZWwgdHJhbnNmb3Jtc1xuICAgIHRoaXMuX2RlZmF1bHRUaWNrUGFkID0gdGhpcy50aWNrUGFkLnNsaWNlKCk7XG4gICAgdGhpcy5fZGVmYXVsdExhYmVsUGFkID0gdGhpcy5sYWJlbFBhZC5zbGljZSgpO1xuICAgIHRoaXMuX2RlZmF1bHRMaW5lVGlja0xlbmd0aCA9IHRoaXMubGluZVRpY2tMZW5ndGguc2xpY2UoKTtcbn1cblxudmFyIHByb3RvID0gQXhlc09wdGlvbnMucHJvdG90eXBlO1xuXG5wcm90by5tZXJnZSA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHNjZW5lTGF5b3V0KSB7XG4gICAgdmFyIG9wdHMgPSB0aGlzO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICAgICAgdmFyIGF4ZXMgPSBzY2VuZUxheW91dFtBWEVTX05BTUVTW2ldXTtcblxuICAgICAgICBpZighYXhlcy52aXNpYmxlKSB7XG4gICAgICAgICAgICBvcHRzLnRpY2tFbmFibGVbaV0gPSBmYWxzZTtcbiAgICAgICAgICAgIG9wdHMubGFiZWxFbmFibGVbaV0gPSBmYWxzZTtcbiAgICAgICAgICAgIG9wdHMubGluZUVuYWJsZVtpXSA9IGZhbHNlO1xuICAgICAgICAgICAgb3B0cy5saW5lVGlja0VuYWJsZVtpXSA9IGZhbHNlO1xuICAgICAgICAgICAgb3B0cy5ncmlkRW5hYmxlW2ldID0gZmFsc2U7XG4gICAgICAgICAgICBvcHRzLnplcm9FbmFibGVbaV0gPSBmYWxzZTtcbiAgICAgICAgICAgIG9wdHMuYmFja2dyb3VuZEVuYWJsZVtpXSA9IGZhbHNlO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBeGVzIGxhYmVsc1xuICAgICAgICBvcHRzLmxhYmVsc1tpXSA9IGZ1bGxMYXlvdXQuX21ldGEgP1xuICAgICAgICAgICAgTGliLnRlbXBsYXRlU3RyaW5nKGF4ZXMudGl0bGUudGV4dCwgZnVsbExheW91dC5fbWV0YSkgOlxuICAgICAgICAgICAgYXhlcy50aXRsZS50ZXh0O1xuXG4gICAgICAgIGlmKCdmb250JyBpbiBheGVzLnRpdGxlKSB7XG4gICAgICAgICAgICBpZihheGVzLnRpdGxlLmZvbnQuY29sb3IpIG9wdHMubGFiZWxDb2xvcltpXSA9IHN0cjJSZ2JhQXJyYXkoYXhlcy50aXRsZS5mb250LmNvbG9yKTtcbiAgICAgICAgICAgIGlmKGF4ZXMudGl0bGUuZm9udC5mYW1pbHkpIG9wdHMubGFiZWxGb250W2ldID0gYXhlcy50aXRsZS5mb250LmZhbWlseTtcbiAgICAgICAgICAgIGlmKGF4ZXMudGl0bGUuZm9udC5zaXplKSBvcHRzLmxhYmVsU2l6ZVtpXSA9IGF4ZXMudGl0bGUuZm9udC5zaXplO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTGluZXNcbiAgICAgICAgaWYoJ3Nob3dsaW5lJyBpbiBheGVzKSBvcHRzLmxpbmVFbmFibGVbaV0gPSBheGVzLnNob3dsaW5lO1xuICAgICAgICBpZignbGluZWNvbG9yJyBpbiBheGVzKSBvcHRzLmxpbmVDb2xvcltpXSA9IHN0cjJSZ2JhQXJyYXkoYXhlcy5saW5lY29sb3IpO1xuICAgICAgICBpZignbGluZXdpZHRoJyBpbiBheGVzKSBvcHRzLmxpbmVXaWR0aFtpXSA9IGF4ZXMubGluZXdpZHRoO1xuXG4gICAgICAgIGlmKCdzaG93Z3JpZCcgaW4gYXhlcykgb3B0cy5ncmlkRW5hYmxlW2ldID0gYXhlcy5zaG93Z3JpZDtcbiAgICAgICAgaWYoJ2dyaWRjb2xvcicgaW4gYXhlcykgb3B0cy5ncmlkQ29sb3JbaV0gPSBzdHIyUmdiYUFycmF5KGF4ZXMuZ3JpZGNvbG9yKTtcbiAgICAgICAgaWYoJ2dyaWR3aWR0aCcgaW4gYXhlcykgb3B0cy5ncmlkV2lkdGhbaV0gPSBheGVzLmdyaWR3aWR0aDtcblxuICAgICAgICAvLyBSZW1vdmUgemVyb2xpbmUgaWYgYXhpcyB0eXBlIGlzIGxvZ1xuICAgICAgICAvLyBvdGhlcndpc2UgdGhlIHplcm9saW5lIGlzIGluY29ycmVjdGx5IGRyYXduIGF0IDEgb24gbG9nIGF4ZXNcbiAgICAgICAgaWYoYXhlcy50eXBlID09PSAnbG9nJykgb3B0cy56ZXJvRW5hYmxlW2ldID0gZmFsc2U7XG4gICAgICAgIGVsc2UgaWYoJ3plcm9saW5lJyBpbiBheGVzKSBvcHRzLnplcm9FbmFibGVbaV0gPSBheGVzLnplcm9saW5lO1xuICAgICAgICBpZignemVyb2xpbmVjb2xvcicgaW4gYXhlcykgb3B0cy56ZXJvTGluZUNvbG9yW2ldID0gc3RyMlJnYmFBcnJheShheGVzLnplcm9saW5lY29sb3IpO1xuICAgICAgICBpZignemVyb2xpbmV3aWR0aCcgaW4gYXhlcykgb3B0cy56ZXJvTGluZVdpZHRoW2ldID0gYXhlcy56ZXJvbGluZXdpZHRoO1xuXG4gICAgICAgIC8vIHRpY2sgbGluZXNcbiAgICAgICAgaWYoJ3RpY2tzJyBpbiBheGVzICYmICEhYXhlcy50aWNrcykgb3B0cy5saW5lVGlja0VuYWJsZVtpXSA9IHRydWU7XG4gICAgICAgIGVsc2Ugb3B0cy5saW5lVGlja0VuYWJsZVtpXSA9IGZhbHNlO1xuXG4gICAgICAgIGlmKCd0aWNrbGVuJyBpbiBheGVzKSB7XG4gICAgICAgICAgICBvcHRzLmxpbmVUaWNrTGVuZ3RoW2ldID0gb3B0cy5fZGVmYXVsdExpbmVUaWNrTGVuZ3RoW2ldID0gYXhlcy50aWNrbGVuO1xuICAgICAgICB9XG4gICAgICAgIGlmKCd0aWNrY29sb3InIGluIGF4ZXMpIG9wdHMubGluZVRpY2tDb2xvcltpXSA9IHN0cjJSZ2JhQXJyYXkoYXhlcy50aWNrY29sb3IpO1xuICAgICAgICBpZigndGlja3dpZHRoJyBpbiBheGVzKSBvcHRzLmxpbmVUaWNrV2lkdGhbaV0gPSBheGVzLnRpY2t3aWR0aDtcbiAgICAgICAgaWYoJ3RpY2thbmdsZScgaW4gYXhlcykge1xuICAgICAgICAgICAgb3B0cy50aWNrQW5nbGVbaV0gPSAoYXhlcy50aWNrYW5nbGUgPT09ICdhdXRvJykgP1xuICAgICAgICAgICAgICAgIC0zNjAwIDogLy8gaS5lLiBzcGVjaWFsIG51bWJlciB0byBzZXQgYXV0byBvcHRpb25cbiAgICAgICAgICAgICAgICBNYXRoLlBJICogLWF4ZXMudGlja2FuZ2xlIC8gMTgwO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGljayBsYWJlbHNcbiAgICAgICAgaWYoJ3Nob3d0aWNrbGFiZWxzJyBpbiBheGVzKSBvcHRzLnRpY2tFbmFibGVbaV0gPSBheGVzLnNob3d0aWNrbGFiZWxzO1xuICAgICAgICBpZigndGlja2ZvbnQnIGluIGF4ZXMpIHtcbiAgICAgICAgICAgIGlmKGF4ZXMudGlja2ZvbnQuY29sb3IpIG9wdHMudGlja0NvbG9yW2ldID0gc3RyMlJnYmFBcnJheShheGVzLnRpY2tmb250LmNvbG9yKTtcbiAgICAgICAgICAgIGlmKGF4ZXMudGlja2ZvbnQuZmFtaWx5KSBvcHRzLnRpY2tGb250W2ldID0gYXhlcy50aWNrZm9udC5mYW1pbHk7XG4gICAgICAgICAgICBpZihheGVzLnRpY2tmb250LnNpemUpIG9wdHMudGlja1NpemVbaV0gPSBheGVzLnRpY2tmb250LnNpemU7XG4gICAgICAgIH1cblxuICAgICAgICBpZignbWlycm9yJyBpbiBheGVzKSB7XG4gICAgICAgICAgICBpZihbJ3RpY2tzJywgJ2FsbCcsICdhbGx0aWNrcyddLmluZGV4T2YoYXhlcy5taXJyb3IpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIG9wdHMubGluZVRpY2tNaXJyb3JbaV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIG9wdHMubGluZU1pcnJvcltpXSA9IHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYoYXhlcy5taXJyb3IgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBvcHRzLmxpbmVUaWNrTWlycm9yW2ldID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgb3B0cy5saW5lTWlycm9yW2ldID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb3B0cy5saW5lVGlja01pcnJvcltpXSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIG9wdHMubGluZU1pcnJvcltpXSA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Ugb3B0cy5saW5lTWlycm9yW2ldID0gZmFsc2U7XG5cbiAgICAgICAgLy8gZ3JpZCBiYWNrZ3JvdW5kXG4gICAgICAgIGlmKCdzaG93YmFja2dyb3VuZCcgaW4gYXhlcyAmJiBheGVzLnNob3diYWNrZ3JvdW5kICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgb3B0cy5iYWNrZ3JvdW5kRW5hYmxlW2ldID0gdHJ1ZTtcbiAgICAgICAgICAgIG9wdHMuYmFja2dyb3VuZENvbG9yW2ldID0gc3RyMlJnYmFBcnJheShheGVzLmJhY2tncm91bmRjb2xvcik7XG4gICAgICAgIH0gZWxzZSBvcHRzLmJhY2tncm91bmRFbmFibGVbaV0gPSBmYWxzZTtcbiAgICB9XG59O1xuXG5cbmZ1bmN0aW9uIGNyZWF0ZUF4ZXNPcHRpb25zKGZ1bGxMYXlvdXQsIHNjZW5lTGF5b3V0KSB7XG4gICAgdmFyIHJlc3VsdCA9IG5ldyBBeGVzT3B0aW9ucygpO1xuICAgIHJlc3VsdC5tZXJnZShmdWxsTGF5b3V0LCBzY2VuZUxheW91dCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVBeGVzT3B0aW9ucztcblxufSx7XCIuLi8uLi8uLi9saWJcIjo3MTksXCIuLi8uLi8uLi9saWIvc3RyMnJnYmFycmF5XCI6NzQyfV0sODEyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vLi4vbGliJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi8uLi9yZWdpc3RyeScpO1xuXG52YXIgaGFuZGxlU3VicGxvdERlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vc3VicGxvdF9kZWZhdWx0cycpO1xudmFyIHN1cHBseUdsM2RBeGlzTGF5b3V0RGVmYXVsdHMgPSBfZGVyZXFfKCcuL2F4aXNfZGVmYXVsdHMnKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGdldFN1YnBsb3REYXRhID0gX2RlcmVxXygnLi4vLi4vZ2V0X2RhdGEnKS5nZXRTdWJwbG90RGF0YTtcblxudmFyIEdMM0QgPSAnZ2wzZCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICB2YXIgaGFzTm9uM0QgPSBsYXlvdXRPdXQuX2Jhc2VQbG90TW9kdWxlcy5sZW5ndGggPiAxO1xuXG4gICAgLy8gc29tZSBsYXlvdXQtd2lkZSBhdHRyaWJ1dGUgYXJlIHVzZWQgaW4gYWxsIHNjZW5lc1xuICAgIC8vIGlmIDNEIGlzIHRoZSBvbmx5IHZpc2libGUgcGxvdCB0eXBlXG4gICAgZnVuY3Rpb24gZ2V0RGZsdEZyb21MYXlvdXQoYXR0cikge1xuICAgICAgICBpZihoYXNOb24zRCkgcmV0dXJuO1xuXG4gICAgICAgIHZhciBpc1ZhbGlkID0gTGliLnZhbGlkYXRlKGxheW91dEluW2F0dHJdLCBsYXlvdXRBdHRyaWJ1dGVzW2F0dHJdKTtcbiAgICAgICAgaWYoaXNWYWxpZCkgcmV0dXJuIGxheW91dEluW2F0dHJdO1xuICAgIH1cblxuICAgIGhhbmRsZVN1YnBsb3REZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSwge1xuICAgICAgICB0eXBlOiBHTDNELFxuICAgICAgICBhdHRyaWJ1dGVzOiBsYXlvdXRBdHRyaWJ1dGVzLFxuICAgICAgICBoYW5kbGVEZWZhdWx0czogaGFuZGxlR2wzZERlZmF1bHRzLFxuICAgICAgICBmdWxsTGF5b3V0OiBsYXlvdXRPdXQsXG4gICAgICAgIGZvbnQ6IGxheW91dE91dC5mb250LFxuICAgICAgICBmdWxsRGF0YTogZnVsbERhdGEsXG4gICAgICAgIGdldERmbHRGcm9tTGF5b3V0OiBnZXREZmx0RnJvbUxheW91dCxcbiAgICAgICAgcGFwZXJfYmdjb2xvcjogbGF5b3V0T3V0LnBhcGVyX2JnY29sb3IsXG4gICAgICAgIGNhbGVuZGFyOiBsYXlvdXRPdXQuY2FsZW5kYXJcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZUdsM2REZWZhdWx0cyhzY2VuZUxheW91dEluLCBzY2VuZUxheW91dE91dCwgY29lcmNlLCBvcHRzKSB7XG4gICAgLypcbiAgICAgKiBTY2VuZSBudW1iZXJpbmcgcHJvY2VlZHMgYXMgZm9sbG93c1xuICAgICAqIHNjZW5lXG4gICAgICogc2NlbmUyXG4gICAgICogc2NlbmUzXG4gICAgICpcbiAgICAgKiBhbmQgZC5zY2VuZSB3aWxsIGJlIHVuZGVmaW5lZCBvciBzb21lIG51bWJlciBvciBudW1iZXIgc3RyaW5nXG4gICAgICpcbiAgICAgKiBBbHNvIHdyaXRlIGJhY2sgYSBibGFuayBzY2VuZSBvYmplY3QgdG8gdXNlciBsYXlvdXQgc28gdGhhdCBzb21lXG4gICAgICogYXR0cmlidXRlcyBsaWtlIGFzcGVjdHJhdGlvIGNhbiBiZSB3cml0dGVuIGJhY2sgZHluYW1pY2FsbHkuXG4gICAgICovXG5cbiAgICB2YXIgYmdjb2xvciA9IGNvZXJjZSgnYmdjb2xvcicpO1xuICAgIHZhciBiZ0NvbG9yQ29tYmluZWQgPSBDb2xvci5jb21iaW5lKGJnY29sb3IsIG9wdHMucGFwZXJfYmdjb2xvcik7XG5cbiAgICB2YXIgY2FtZXJhS2V5cyA9IFsndXAnLCAnY2VudGVyJywgJ2V5ZSddO1xuXG4gICAgZm9yKHZhciBqID0gMDsgaiA8IGNhbWVyYUtleXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgY29lcmNlKCdjYW1lcmEuJyArIGNhbWVyYUtleXNbal0gKyAnLngnKTtcbiAgICAgICAgY29lcmNlKCdjYW1lcmEuJyArIGNhbWVyYUtleXNbal0gKyAnLnknKTtcbiAgICAgICAgY29lcmNlKCdjYW1lcmEuJyArIGNhbWVyYUtleXNbal0gKyAnLnonKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2NhbWVyYS5wcm9qZWN0aW9uLnR5cGUnKTtcblxuICAgIC8qXG4gICAgICogY29lcmNlIHRvIHBvc2l0aXZlIG51bWJlciAobWluIDApIGJ1dCBhbHNvIGRvIG5vdCBhY2NlcHQgMCAoPjAgbm90ID49MClcbiAgICAgKiBub3RlIHRoYXQgMCdzIGdvIGZhbHNlIHdpdGggdGhlICEhIGNhbGxcbiAgICAgKi9cbiAgICB2YXIgaGFzQXNwZWN0ID0gISFjb2VyY2UoJ2FzcGVjdHJhdGlvLngnKSAmJlxuICAgICAgICAgICAgICAgICAgICAhIWNvZXJjZSgnYXNwZWN0cmF0aW8ueScpICYmXG4gICAgICAgICAgICAgICAgICAgICEhY29lcmNlKCdhc3BlY3RyYXRpby56Jyk7XG5cbiAgICB2YXIgZGVmYXVsdEFzcGVjdE1vZGUgPSBoYXNBc3BlY3QgPyAnbWFudWFsJyA6ICdhdXRvJztcbiAgICB2YXIgYXNwZWN0TW9kZSA9IGNvZXJjZSgnYXNwZWN0bW9kZScsIGRlZmF1bHRBc3BlY3RNb2RlKTtcblxuICAgIC8qXG4gICAgICogV2UgbmVlZCBhc3BlY3RyYXRpbyBvYmplY3QgaW4gYWxsIHRoZSBMYXlvdXRzIGFzIGl0IGlzIGR5bmFtaWNhbGx5IHNldFxuICAgICAqIGluIHRoZSBjYWxjdWxhdGlvbiBzdGVwcywgaWUsIHdlIGNhbnQgc2V0IHRoZSBjb3JyZWN0IGRhdGEgbm93LCBpdCBoYXBwZW5zIGxhdGVyLlxuICAgICAqIFdlIG11c3QgYWxzbyBhY2NvdW50IGZvciB0aGUgY2FzZSB0aGUgdXNlciBzZW5kcyBiYWQgcmF0aW8gZGF0YSB3aXRoICdtYW51YWwnIHNldFxuICAgICAqIGZvciB0aGUgbW9kZS4gSW4gdGhpcyBjYXNlIHdlIG11c3QgZm9yY2UgY2hhbmdlIGl0IGhlcmUgYXMgdGhlIGRlZmF1bHQgY29lcmNlXG4gICAgICogbWlzc2VzIGl0IGFib3ZlLlxuICAgICAqL1xuICAgIGlmKCFoYXNBc3BlY3QpIHtcbiAgICAgICAgc2NlbmVMYXlvdXRJbi5hc3BlY3RyYXRpbyA9IHNjZW5lTGF5b3V0T3V0LmFzcGVjdHJhdGlvID0ge3g6IDEsIHk6IDEsIHo6IDF9O1xuXG4gICAgICAgIGlmKGFzcGVjdE1vZGUgPT09ICdtYW51YWwnKSBzY2VuZUxheW91dE91dC5hc3BlY3Rtb2RlID0gJ2F1dG8nO1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIGtpbmQgb2YgbGlrZSBhdXRvcmFuZ2UgLSB3ZSBuZWVkIHRoZSBjYWxjdWxhdGVkIGFzcGVjdG1vZGUgYmFjayBpblxuICAgICAgICAgKiB0aGUgaW5wdXQgbGF5b3V0IG9yIHJlbGF5b3V0IGNhbiBjYXVzZSBwcm9ibGVtcyBsYXRlclxuICAgICAgICAgKi9cbiAgICAgICAgc2NlbmVMYXlvdXRJbi5hc3BlY3Rtb2RlID0gc2NlbmVMYXlvdXRPdXQuYXNwZWN0bW9kZTtcbiAgICB9XG5cbiAgICB2YXIgZnVsbEdsM2REYXRhID0gZ2V0U3VicGxvdERhdGEob3B0cy5mdWxsRGF0YSwgR0wzRCwgb3B0cy5pZCk7XG5cbiAgICBzdXBwbHlHbDNkQXhpc0xheW91dERlZmF1bHRzKHNjZW5lTGF5b3V0SW4sIHNjZW5lTGF5b3V0T3V0LCB7XG4gICAgICAgIGZvbnQ6IG9wdHMuZm9udCxcbiAgICAgICAgc2NlbmU6IG9wdHMuaWQsXG4gICAgICAgIGRhdGE6IGZ1bGxHbDNkRGF0YSxcbiAgICAgICAgYmdDb2xvcjogYmdDb2xvckNvbWJpbmVkLFxuICAgICAgICBjYWxlbmRhcjogb3B0cy5jYWxlbmRhcixcbiAgICAgICAgZnVsbExheW91dDogb3B0cy5mdWxsTGF5b3V0XG4gICAgfSk7XG5cbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Fubm90YXRpb25zM2QnLCAnaGFuZGxlRGVmYXVsdHMnKShcbiAgICAgICAgc2NlbmVMYXlvdXRJbiwgc2NlbmVMYXlvdXRPdXQsIG9wdHNcbiAgICApO1xuXG4gICAgdmFyIGRyYWdtb2RlID0gb3B0cy5nZXREZmx0RnJvbUxheW91dCgnZHJhZ21vZGUnKTtcblxuICAgIGlmKGRyYWdtb2RlICE9PSBmYWxzZSkge1xuICAgICAgICBpZighZHJhZ21vZGUpIHtcbiAgICAgICAgICAgIGRyYWdtb2RlID0gJ29yYml0JztcblxuICAgICAgICAgICAgaWYoc2NlbmVMYXlvdXRJbi5jYW1lcmEgJiZcbiAgICAgICAgICAgICAgICBzY2VuZUxheW91dEluLmNhbWVyYS51cCkge1xuICAgICAgICAgICAgICAgIHZhciB4ID0gc2NlbmVMYXlvdXRJbi5jYW1lcmEudXAueDtcbiAgICAgICAgICAgICAgICB2YXIgeSA9IHNjZW5lTGF5b3V0SW4uY2FtZXJhLnVwLnk7XG4gICAgICAgICAgICAgICAgdmFyIHogPSBzY2VuZUxheW91dEluLmNhbWVyYS51cC56O1xuXG4gICAgICAgICAgICAgICAgaWYoeiAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBpZigheCB8fCAheSB8fCAheikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ21vZGUgPSAndHVybnRhYmxlJztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHogLyBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSArIHogKiB6KSA+IDAuOTk5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkcmFnbW9kZSA9ICd0dXJudGFibGUnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkcmFnbW9kZSA9ICd0dXJudGFibGUnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29lcmNlKCdkcmFnbW9kZScsIGRyYWdtb2RlKTtcbiAgICBjb2VyY2UoJ2hvdmVybW9kZScsIG9wdHMuZ2V0RGZsdEZyb21MYXlvdXQoJ2hvdmVybW9kZScpKTtcbn1cblxufSx7XCIuLi8uLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi8uLi9nZXRfZGF0YVwiOjgwMixcIi4uLy4uL3N1YnBsb3RfZGVmYXVsdHNcIjo4NDIsXCIuL2F4aXNfZGVmYXVsdHNcIjo4MTAsXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6ODEzfV0sODEzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2wzZEF4aXNBdHRycyA9IF9kZXJlcV8oJy4vYXhpc19hdHRyaWJ1dGVzJyk7XG52YXIgZG9tYWluQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9kb21haW4nKS5hdHRyaWJ1dGVzO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBjb3VudGVyUmVnZXggPSBfZGVyZXFfKCcuLi8uLi8uLi9saWInKS5jb3VudGVyUmVnZXg7XG5cbmZ1bmN0aW9uIG1ha2VDYW1lcmFWZWN0b3IoeCwgeSwgeikge1xuICAgIHJldHVybiB7XG4gICAgICAgIHg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB4LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYW1lcmEnXG4gICAgICAgIH0sXG4gICAgICAgIHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB5LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYW1lcmEnXG4gICAgICAgIH0sXG4gICAgICAgIHo6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB6LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYW1lcmEnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FtZXJhJ1xuICAgIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIF9hcnJheUF0dHJSZWdleHBzOiBbY291bnRlclJlZ2V4KCdzY2VuZScsICcuYW5ub3RhdGlvbnMnLCB0cnVlKV0sXG5cbiAgICBiZ2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAncmdiYSgwLDAsMCwwKScsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuICAgIGNhbWVyYToge1xuICAgICAgICB1cDogZXh0ZW5kRmxhdChtYWtlQ2FtZXJhVmVjdG9yKDAsIDAsIDEpLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGNlbnRlcjogZXh0ZW5kRmxhdChtYWtlQ2FtZXJhVmVjdG9yKDAsIDAsIDApLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGV5ZTogZXh0ZW5kRmxhdChtYWtlQ2FtZXJhVmVjdG9yKDEuMjUsIDEuMjUsIDEuMjUpLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIHByb2plY3Rpb246IHtcbiAgICAgICAgICAgIHR5cGU6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgdmFsdWVzOiBbJ3BlcnNwZWN0aXZlJywgJ29ydGhvZ3JhcGhpYyddLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICdwZXJzcGVjdGl2ZScsXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FtZXJhJ1xuICAgIH0sXG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ3NjZW5lJywgZWRpdFR5cGU6ICdwbG90J30pLFxuICAgIGFzcGVjdG1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAnY3ViZScsICdkYXRhJywgJ21hbnVhbCddLFxuICAgICAgICBkZmx0OiAnYXV0bycsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIGltcGxpZWRFZGl0czoge1xuICAgICAgICAgICAgJ2FzcGVjdHJhdGlvLngnOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAnYXNwZWN0cmF0aW8ueSc6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICdhc3BlY3RyYXRpby56JzogdW5kZWZpbmVkXG4gICAgICAgIH0sXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXNwZWN0cmF0aW86IHsgLy8gbXVzdCBiZSBwb3NpdGl2ZSAoMCdzIGFyZSBjb2VyY2VkIHRvIDEpXG4gICAgICAgIHg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7J15hc3BlY3Rtb2RlJzogJ21hbnVhbCd9XG4gICAgICAgIH0sXG4gICAgICAgIHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7J15hc3BlY3Rtb2RlJzogJ21hbnVhbCd9XG4gICAgICAgIH0sXG4gICAgICAgIHo6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7J15hc3BlY3Rtb2RlJzogJ21hbnVhbCd9XG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIGltcGxpZWRFZGl0czoge2FzcGVjdG1vZGU6ICdtYW51YWwnfSxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHhheGlzOiBnbDNkQXhpc0F0dHJzLFxuICAgIHlheGlzOiBnbDNkQXhpc0F0dHJzLFxuICAgIHpheGlzOiBnbDNkQXhpc0F0dHJzLFxuXG4gICAgZHJhZ21vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ29yYml0JywgJ3R1cm50YWJsZScsICd6b29tJywgJ3BhbicsIGZhbHNlXSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBob3Zlcm1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgdmFsdWVzOiBbJ2Nsb3Nlc3QnLCBmYWxzZV0sXG4gICAgICAgIGRmbHQ6ICdjbG9zZXN0JyxcbiAgICAgICAgZWRpdFR5cGU6ICdtb2RlYmFyJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB1aXJldmlzaW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuXG4gICAgX2RlcHJlY2F0ZWQ6IHtcbiAgICAgICAgY2FtZXJhcG9zaXRpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYW1lcmEnLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9kb21haW5cIjo3OTIsXCIuL2F4aXNfYXR0cmlidXRlc1wiOjgwOX1dLDgxNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHN0cjJSR0JBcnJheSA9IF9kZXJlcV8oJy4uLy4uLy4uL2xpYi9zdHIycmdiYXJyYXknKTtcblxudmFyIEFYRVNfTkFNRVMgPSBbJ3hheGlzJywgJ3lheGlzJywgJ3pheGlzJ107XG5cbmZ1bmN0aW9uIFNwaWtlT3B0aW9ucygpIHtcbiAgICB0aGlzLmVuYWJsZWQgPSBbdHJ1ZSwgdHJ1ZSwgdHJ1ZV07XG4gICAgdGhpcy5jb2xvcnMgPSBbWzAsIDAsIDAsIDFdLFxuICAgICAgICAgICAgICAgICAgIFswLCAwLCAwLCAxXSxcbiAgICAgICAgICAgICAgICAgICBbMCwgMCwgMCwgMV1dO1xuICAgIHRoaXMuZHJhd1NpZGVzID0gW3RydWUsIHRydWUsIHRydWVdO1xuICAgIHRoaXMubGluZVdpZHRoID0gWzEsIDEsIDFdO1xufVxuXG52YXIgcHJvdG8gPSBTcGlrZU9wdGlvbnMucHJvdG90eXBlO1xuXG5wcm90by5tZXJnZSA9IGZ1bmN0aW9uKHNjZW5lTGF5b3V0KSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICB2YXIgYXhlcyA9IHNjZW5lTGF5b3V0W0FYRVNfTkFNRVNbaV1dO1xuXG4gICAgICAgIGlmKCFheGVzLnZpc2libGUpIHtcbiAgICAgICAgICAgIHRoaXMuZW5hYmxlZFtpXSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5kcmF3U2lkZXNbaV0gPSBmYWxzZTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5lbmFibGVkW2ldID0gYXhlcy5zaG93c3Bpa2VzO1xuICAgICAgICB0aGlzLmNvbG9yc1tpXSA9IHN0cjJSR0JBcnJheShheGVzLnNwaWtlY29sb3IpO1xuICAgICAgICB0aGlzLmRyYXdTaWRlc1tpXSA9IGF4ZXMuc3Bpa2VzaWRlcztcbiAgICAgICAgdGhpcy5saW5lV2lkdGhbaV0gPSBheGVzLnNwaWtldGhpY2tuZXNzO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZVNwaWtlT3B0aW9ucyhsYXlvdXQpIHtcbiAgICB2YXIgcmVzdWx0ID0gbmV3IFNwaWtlT3B0aW9ucygpO1xuICAgIHJlc3VsdC5tZXJnZShsYXlvdXQpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU3Bpa2VPcHRpb25zO1xuXG59LHtcIi4uLy4uLy4uL2xpYi9zdHIycmdiYXJyYXlcIjo3NDJ9XSw4MTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuLyogZXNsaW50IGJsb2NrLXNjb3BlZC12YXI6IDAqL1xuLyogZXNsaW50IG5vLXJlZGVjbGFyZTogMCovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBjb21wdXRlVGlja01hcmtzO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vLi4vbGliJyk7XG5cbnZhciBBWEVTX05BTUVTID0gWyd4YXhpcycsICd5YXhpcycsICd6YXhpcyddO1xuXG52YXIgY2VudGVyUG9pbnQgPSBbMCwgMCwgMF07XG5cbmZ1bmN0aW9uIGNvbnRvdXJMZXZlbHNGcm9tVGlja3ModGlja3MpIHtcbiAgICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KDMpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICAgICAgdmFyIHRsZXZlbCA9IHRpY2tzW2ldO1xuICAgICAgICB2YXIgY2xldmVsID0gbmV3IEFycmF5KHRsZXZlbC5sZW5ndGgpO1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgdGxldmVsLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICBjbGV2ZWxbal0gPSB0bGV2ZWxbal0ueDtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHRbaV0gPSBjbGV2ZWw7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVUaWNrTWFya3Moc2NlbmUpIHtcbiAgICB2YXIgYXhlc09wdGlvbnMgPSBzY2VuZS5heGVzT3B0aW9ucztcbiAgICB2YXIgZ2xSYW5nZSA9IHNjZW5lLmdscGxvdC5heGVzUGl4ZWxzO1xuICAgIHZhciBzY2VuZUxheW91dCA9IHNjZW5lLmZ1bGxTY2VuZUxheW91dDtcblxuICAgIHZhciB0aWNrcyA9IFtbXSwgW10sIFtdXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICAgICAgdmFyIGF4ZXMgPSBzY2VuZUxheW91dFtBWEVTX05BTUVTW2ldXTtcblxuICAgICAgICBheGVzLl9sZW5ndGggPSAoZ2xSYW5nZVtpXS5oaSAtIGdsUmFuZ2VbaV0ubG8pICpcbiAgICAgICAgICAgIGdsUmFuZ2VbaV0ucGl4ZWxzUGVyRGF0YVVuaXQgLyBzY2VuZS5kYXRhU2NhbGVbaV07XG5cbiAgICAgICAgaWYoTWF0aC5hYnMoYXhlcy5fbGVuZ3RoKSA9PT0gSW5maW5pdHkgfHxcbiAgICAgICAgICAgaXNOYU4oYXhlcy5fbGVuZ3RoKSkge1xuICAgICAgICAgICAgdGlja3NbaV0gPSBbXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGF4ZXMuX2lucHV0X3JhbmdlID0gYXhlcy5yYW5nZS5zbGljZSgpO1xuICAgICAgICAgICAgYXhlcy5yYW5nZVswXSA9IChnbFJhbmdlW2ldLmxvKSAvIHNjZW5lLmRhdGFTY2FsZVtpXTtcbiAgICAgICAgICAgIGF4ZXMucmFuZ2VbMV0gPSAoZ2xSYW5nZVtpXS5oaSkgLyBzY2VuZS5kYXRhU2NhbGVbaV07XG4gICAgICAgICAgICBheGVzLl9tID0gMS4wIC8gKHNjZW5lLmRhdGFTY2FsZVtpXSAqIGdsUmFuZ2VbaV0ucGl4ZWxzUGVyRGF0YVVuaXQpO1xuXG4gICAgICAgICAgICBpZihheGVzLnJhbmdlWzBdID09PSBheGVzLnJhbmdlWzFdKSB7XG4gICAgICAgICAgICAgICAgYXhlcy5yYW5nZVswXSAtPSAxO1xuICAgICAgICAgICAgICAgIGF4ZXMucmFuZ2VbMV0gKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRoaXMgaXMgbmVjZXNzYXJ5IHRvIHNob3J0LWNpcmN1aXQgdGhlICd5JyBoYW5kbGluZ1xuICAgICAgICAgICAgLy8gaW4gYXV0b3RpY2sgcGFydCBvZiBjYWxjVGlja3MuLi4gVHJlYXRpbmcgYWxsIGF4ZXMgYXMgJ3knIGluIHRoaXMgY2FzZVxuICAgICAgICAgICAgLy8gcnVubmluZyB0aGUgYXV0b3RpY2tzIGhlcmUsIHRoZW4gc2V0dGluZ1xuICAgICAgICAgICAgLy8gYXV0b3RpY2tzIHRvIGZhbHNlIHRvIGdldCBhcm91bmQgdGhlIDJEIGhhbmRsaW5nIGluIGNhbGNUaWNrcy5cbiAgICAgICAgICAgIHZhciB0aWNrTW9kZUNhY2hlZCA9IGF4ZXMudGlja21vZGU7XG4gICAgICAgICAgICBpZihheGVzLnRpY2ttb2RlID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgICAgICBheGVzLnRpY2ttb2RlID0gJ2xpbmVhcic7XG4gICAgICAgICAgICAgICAgdmFyIG50aWNrcyA9IGF4ZXMubnRpY2tzIHx8IExpYi5jb25zdHJhaW4oKGF4ZXMuX2xlbmd0aCAvIDQwKSwgNCwgOSk7XG4gICAgICAgICAgICAgICAgQXhlcy5hdXRvVGlja3MoYXhlcywgTWF0aC5hYnMoYXhlcy5yYW5nZVsxXSAtIGF4ZXMucmFuZ2VbMF0pIC8gbnRpY2tzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBkYXRhVGlja3MgPSBBeGVzLmNhbGNUaWNrcyhheGVzKTtcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBkYXRhVGlja3MubGVuZ3RoOyArK2opIHtcbiAgICAgICAgICAgICAgICBkYXRhVGlja3Nbal0ueCA9IGRhdGFUaWNrc1tqXS54ICogc2NlbmUuZGF0YVNjYWxlW2ldO1xuXG4gICAgICAgICAgICAgICAgaWYoYXhlcy50eXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YVRpY2tzW2pdLnRleHQgPVxuICAgICAgICAgICAgICAgICAgICBkYXRhVGlja3Nbal0udGV4dC5yZXBsYWNlKC9cXDxiclxcPi9nLCAnICcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRpY2tzW2ldID0gZGF0YVRpY2tzO1xuXG5cbiAgICAgICAgICAgIGF4ZXMudGlja21vZGUgPSB0aWNrTW9kZUNhY2hlZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGF4ZXNPcHRpb25zLnRpY2tzID0gdGlja3M7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGljayBsZW5ndGhzIGR5bmFtaWNhbGx5XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICBjZW50ZXJQb2ludFtpXSA9IDAuNSAqIChzY2VuZS5nbHBsb3QuYm91bmRzWzBdW2ldICsgc2NlbmUuZ2xwbG90LmJvdW5kc1sxXVtpXSk7XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCAyOyArK2opIHtcbiAgICAgICAgICAgIGF4ZXNPcHRpb25zLmJvdW5kc1tqXVtpXSA9IHNjZW5lLmdscGxvdC5ib3VuZHNbal1baV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzY2VuZS5jb250b3VyTGV2ZWxzID0gY29udG91ckxldmVsc0Zyb21UaWNrcyh0aWNrcyk7XG59XG5cbn0se1wiLi4vLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vY2FydGVzaWFuL2F4ZXNcIjo3Njd9XSw4MTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIHhmb3JtTWF0cml4KG0sIHYpIHtcbiAgICB2YXIgb3V0ID0gWzAsIDAsIDAsIDBdO1xuICAgIHZhciBpLCBqO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgNDsgKytpKSB7XG4gICAgICAgIGZvcihqID0gMDsgaiA8IDQ7ICsraikge1xuICAgICAgICAgICAgb3V0W2pdICs9IG1bNCAqIGkgKyBqXSAqIHZbaV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufVxuXG5mdW5jdGlvbiBwcm9qZWN0KGNhbWVyYSwgdikge1xuICAgIHZhciBwID0geGZvcm1NYXRyaXgoY2FtZXJhLnByb2plY3Rpb24sXG4gICAgICAgIHhmb3JtTWF0cml4KGNhbWVyYS52aWV3LFxuICAgICAgICB4Zm9ybU1hdHJpeChjYW1lcmEubW9kZWwsIFt2WzBdLCB2WzFdLCB2WzJdLCAxXSkpKTtcbiAgICByZXR1cm4gcDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBwcm9qZWN0O1xuXG59LHt9XSw4MTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVDYW1lcmEgPSBfZGVyZXFfKCdnbC1wbG90M2QnKS5jcmVhdGVDYW1lcmE7XG52YXIgY3JlYXRlUGxvdCA9IF9kZXJlcV8oJ2dsLXBsb3QzZCcpLmNyZWF0ZVNjZW5lO1xudmFyIGdldENvbnRleHQgPSBfZGVyZXFfKCd3ZWJnbC1jb250ZXh0Jyk7XG52YXIgcGFzc2l2ZVN1cHBvcnRlZCA9IF9kZXJlcV8oJ2hhcy1wYXNzaXZlLWV2ZW50cycpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG5cbnZhciBzdHIyUkdCQWFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliL3N0cjJyZ2JhcnJheScpO1xudmFyIHNob3dOb1dlYkdsTXNnID0gX2RlcmVxXygnLi4vLi4vbGliL3Nob3dfbm9fd2ViZ2xfbXNnJyk7XG5cbnZhciBwcm9qZWN0ID0gX2RlcmVxXygnLi9wcm9qZWN0Jyk7XG52YXIgY3JlYXRlQXhlc09wdGlvbnMgPSBfZGVyZXFfKCcuL2xheW91dC9jb252ZXJ0Jyk7XG52YXIgY3JlYXRlU3Bpa2VPcHRpb25zID0gX2RlcmVxXygnLi9sYXlvdXQvc3Bpa2VzJyk7XG52YXIgY29tcHV0ZVRpY2tNYXJrcyA9IF9kZXJlcV8oJy4vbGF5b3V0L3RpY2tfbWFya3MnKTtcblxuXG52YXIgU1RBVElDX0NBTlZBUywgU1RBVElDX0NPTlRFWFQ7XG5cbmZ1bmN0aW9uIHJlbmRlcihzY2VuZSkge1xuICAgIHZhciBnZCA9IHNjZW5lLmdyYXBoRGl2O1xuICAgIHZhciB0cmFjZTtcblxuICAgIC8vIHVwZGF0ZSBzaXplIG9mIHN2ZyBjb250YWluZXJcbiAgICB2YXIgc3ZnQ29udGFpbmVyID0gc2NlbmUuc3ZnQ29udGFpbmVyO1xuICAgIHZhciBjbGllbnRSZWN0ID0gc2NlbmUuY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHZhciB3aWR0aCA9IGNsaWVudFJlY3Qud2lkdGg7XG4gICAgdmFyIGhlaWdodCA9IGNsaWVudFJlY3QuaGVpZ2h0O1xuICAgIHN2Z0NvbnRhaW5lci5zZXRBdHRyaWJ1dGVOUyhudWxsLCAndmlld0JveCcsICcwIDAgJyArIHdpZHRoICsgJyAnICsgaGVpZ2h0KTtcbiAgICBzdmdDb250YWluZXIuc2V0QXR0cmlidXRlTlMobnVsbCwgJ3dpZHRoJywgd2lkdGgpO1xuICAgIHN2Z0NvbnRhaW5lci5zZXRBdHRyaWJ1dGVOUyhudWxsLCAnaGVpZ2h0JywgaGVpZ2h0KTtcblxuICAgIGNvbXB1dGVUaWNrTWFya3Moc2NlbmUpO1xuICAgIHNjZW5lLmdscGxvdC5heGVzLnVwZGF0ZShzY2VuZS5heGVzT3B0aW9ucyk7XG5cbiAgICAvLyBjaGVjayBpZiBwaWNrIGhhcyBjaGFuZ2VkXG4gICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhzY2VuZS50cmFjZXMpO1xuICAgIHZhciBsYXN0UGlja2VkID0gbnVsbDtcbiAgICB2YXIgc2VsZWN0aW9uID0gc2NlbmUuZ2xwbG90LnNlbGVjdGlvbjtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICB0cmFjZSA9IHNjZW5lLnRyYWNlc1trZXlzW2ldXTtcbiAgICAgICAgaWYodHJhY2UuZGF0YS5ob3ZlcmluZm8gIT09ICdza2lwJyAmJiB0cmFjZS5oYW5kbGVQaWNrKHNlbGVjdGlvbikpIHtcbiAgICAgICAgICAgIGxhc3RQaWNrZWQgPSB0cmFjZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRyYWNlLnNldENvbnRvdXJMZXZlbHMpIHRyYWNlLnNldENvbnRvdXJMZXZlbHMoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmb3JtYXR0ZXIoYXhpc05hbWUsIHZhbCkge1xuICAgICAgICB2YXIgYXhpcyA9IHNjZW5lLmZ1bGxTY2VuZUxheW91dFtheGlzTmFtZV07XG5cbiAgICAgICAgcmV0dXJuIEF4ZXMudGlja1RleHQoYXhpcywgYXhpcy5kMmwodmFsKSwgJ2hvdmVyJykudGV4dDtcbiAgICB9XG5cbiAgICB2YXIgb2xkRXZlbnREYXRhO1xuXG4gICAgaWYobGFzdFBpY2tlZCAhPT0gbnVsbCkge1xuICAgICAgICB2YXIgcGRhdGEgPSBwcm9qZWN0KHNjZW5lLmdscGxvdC5jYW1lcmFQYXJhbXMsIHNlbGVjdGlvbi5kYXRhQ29vcmRpbmF0ZSk7XG4gICAgICAgIHRyYWNlID0gbGFzdFBpY2tlZC5kYXRhO1xuICAgICAgICB2YXIgdHJhY2VOb3cgPSBnZC5fZnVsbERhdGFbdHJhY2UuaW5kZXhdO1xuICAgICAgICB2YXIgcHROdW1iZXIgPSBzZWxlY3Rpb24uaW5kZXg7XG5cbiAgICAgICAgdmFyIGxhYmVscyA9IHtcbiAgICAgICAgICAgIHhMYWJlbDogZm9ybWF0dGVyKCd4YXhpcycsIHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGVbMF0pLFxuICAgICAgICAgICAgeUxhYmVsOiBmb3JtYXR0ZXIoJ3lheGlzJywgc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZVsxXSksXG4gICAgICAgICAgICB6TGFiZWw6IGZvcm1hdHRlcignemF4aXMnLCBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlWzJdKVxuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBob3ZlcmluZm8gPSBGeC5jYXN0SG92ZXJpbmZvKHRyYWNlTm93LCBzY2VuZS5mdWxsTGF5b3V0LCBwdE51bWJlcik7XG4gICAgICAgIHZhciBob3ZlcmluZm9QYXJ0cyA9IChob3ZlcmluZm8gfHwgJycpLnNwbGl0KCcrJyk7XG4gICAgICAgIHZhciBpc0hvdmVyaW5mb0FsbCA9IGhvdmVyaW5mbyAmJiBob3ZlcmluZm8gPT09ICdhbGwnO1xuXG4gICAgICAgIGlmKCF0cmFjZU5vdy5ob3ZlcnRlbXBsYXRlICYmICFpc0hvdmVyaW5mb0FsbCkge1xuICAgICAgICAgICAgaWYoaG92ZXJpbmZvUGFydHMuaW5kZXhPZigneCcpID09PSAtMSkgbGFiZWxzLnhMYWJlbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmKGhvdmVyaW5mb1BhcnRzLmluZGV4T2YoJ3knKSA9PT0gLTEpIGxhYmVscy55TGFiZWwgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZihob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCd6JykgPT09IC0xKSBsYWJlbHMuekxhYmVsID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYoaG92ZXJpbmZvUGFydHMuaW5kZXhPZigndGV4dCcpID09PSAtMSkgc2VsZWN0aW9uLnRleHRMYWJlbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmKGhvdmVyaW5mb1BhcnRzLmluZGV4T2YoJ25hbWUnKSA9PT0gLTEpIGxhc3RQaWNrZWQubmFtZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0eDtcbiAgICAgICAgdmFyIHZlY3RvclR4ID0gW107XG5cbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2NvbmUnIHx8IHRyYWNlLnR5cGUgPT09ICdzdHJlYW10dWJlJykge1xuICAgICAgICAgICAgbGFiZWxzLnVMYWJlbCA9IGZvcm1hdHRlcigneGF4aXMnLCBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlWzNdKTtcbiAgICAgICAgICAgIGlmKGlzSG92ZXJpbmZvQWxsIHx8IGhvdmVyaW5mb1BhcnRzLmluZGV4T2YoJ3UnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICB2ZWN0b3JUeC5wdXNoKCd1OiAnICsgbGFiZWxzLnVMYWJlbCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxhYmVscy52TGFiZWwgPSBmb3JtYXR0ZXIoJ3lheGlzJywgc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZVs0XSk7XG4gICAgICAgICAgICBpZihpc0hvdmVyaW5mb0FsbCB8fCBob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCd2JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdmVjdG9yVHgucHVzaCgndjogJyArIGxhYmVscy52TGFiZWwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsYWJlbHMud0xhYmVsID0gZm9ybWF0dGVyKCd6YXhpcycsIHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGVbNV0pO1xuICAgICAgICAgICAgaWYoaXNIb3ZlcmluZm9BbGwgfHwgaG92ZXJpbmZvUGFydHMuaW5kZXhPZigndycpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHZlY3RvclR4LnB1c2goJ3c6ICcgKyBsYWJlbHMud0xhYmVsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGFiZWxzLm5vcm1MYWJlbCA9IHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGVbNl0udG9QcmVjaXNpb24oMyk7XG4gICAgICAgICAgICBpZihpc0hvdmVyaW5mb0FsbCB8fCBob3ZlcmluZm9QYXJ0cy5pbmRleE9mKCdub3JtJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdmVjdG9yVHgucHVzaCgnbm9ybTogJyArIGxhYmVscy5ub3JtTGFiZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ3N0cmVhbXR1YmUnKSB7XG4gICAgICAgICAgICAgICAgbGFiZWxzLmRpdmVyZ2VuY2VMYWJlbCA9IHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGVbN10udG9QcmVjaXNpb24oMyk7XG4gICAgICAgICAgICAgICAgaWYoaXNIb3ZlcmluZm9BbGwgfHwgaG92ZXJpbmZvUGFydHMuaW5kZXhPZignZGl2ZXJnZW5jZScpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICB2ZWN0b3JUeC5wdXNoKCdkaXZlcmdlbmNlOiAnICsgbGFiZWxzLmRpdmVyZ2VuY2VMYWJlbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoc2VsZWN0aW9uLnRleHRMYWJlbCkge1xuICAgICAgICAgICAgICAgIHZlY3RvclR4LnB1c2goc2VsZWN0aW9uLnRleHRMYWJlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0eCA9IHZlY3RvclR4LmpvaW4oJzxicj4nKTtcbiAgICAgICAgfSBlbHNlIGlmKHRyYWNlLnR5cGUgPT09ICdpc29zdXJmYWNlJyB8fCB0cmFjZS50eXBlID09PSAndm9sdW1lJykge1xuICAgICAgICAgICAgbGFiZWxzLnZhbHVlTGFiZWwgPSBBeGVzLnRpY2tUZXh0KHNjZW5lLm1vY2tBeGlzLCBzY2VuZS5tb2NrQXhpcy5kMmwoc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZVszXSksICdob3ZlcicpLnRleHQ7XG4gICAgICAgICAgICB2ZWN0b3JUeC5wdXNoKCd2YWx1ZTogJyArIGxhYmVscy52YWx1ZUxhYmVsKTtcbiAgICAgICAgICAgIGlmKHNlbGVjdGlvbi50ZXh0TGFiZWwpIHtcbiAgICAgICAgICAgICAgICB2ZWN0b3JUeC5wdXNoKHNlbGVjdGlvbi50ZXh0TGFiZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHggPSB2ZWN0b3JUeC5qb2luKCc8YnI+Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0eCA9IHNlbGVjdGlvbi50ZXh0TGFiZWw7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcG9pbnREYXRhID0ge1xuICAgICAgICAgICAgeDogc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZVswXSxcbiAgICAgICAgICAgIHk6IHNlbGVjdGlvbi50cmFjZUNvb3JkaW5hdGVbMV0sXG4gICAgICAgICAgICB6OiBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlWzJdLFxuICAgICAgICAgICAgZGF0YTogdHJhY2VOb3cuX2lucHV0LFxuICAgICAgICAgICAgZnVsbERhdGE6IHRyYWNlTm93LFxuICAgICAgICAgICAgY3VydmVOdW1iZXI6IHRyYWNlTm93LmluZGV4LFxuICAgICAgICAgICAgcG9pbnROdW1iZXI6IHB0TnVtYmVyXG4gICAgICAgIH07XG5cbiAgICAgICAgRnguYXBwZW5kQXJyYXlQb2ludFZhbHVlKHBvaW50RGF0YSwgdHJhY2VOb3csIHB0TnVtYmVyKTtcblxuICAgICAgICBpZih0cmFjZS5fbW9kdWxlLmV2ZW50RGF0YSkge1xuICAgICAgICAgICAgcG9pbnREYXRhID0gdHJhY2VOb3cuX21vZHVsZS5ldmVudERhdGEocG9pbnREYXRhLCBzZWxlY3Rpb24sIHRyYWNlTm93LCB7fSwgcHROdW1iZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGV2ZW50RGF0YSA9IHtwb2ludHM6IFtwb2ludERhdGFdfTtcblxuICAgICAgICBpZihzY2VuZS5mdWxsU2NlbmVMYXlvdXQuaG92ZXJtb2RlKSB7XG4gICAgICAgICAgICBGeC5sb25lSG92ZXIoe1xuICAgICAgICAgICAgICAgIHRyYWNlOiB0cmFjZU5vdyxcbiAgICAgICAgICAgICAgICB4OiAoMC41ICsgMC41ICogcGRhdGFbMF0gLyBwZGF0YVszXSkgKiB3aWR0aCxcbiAgICAgICAgICAgICAgICB5OiAoMC41IC0gMC41ICogcGRhdGFbMV0gLyBwZGF0YVszXSkgKiBoZWlnaHQsXG4gICAgICAgICAgICAgICAgeExhYmVsOiBsYWJlbHMueExhYmVsLFxuICAgICAgICAgICAgICAgIHlMYWJlbDogbGFiZWxzLnlMYWJlbCxcbiAgICAgICAgICAgICAgICB6TGFiZWw6IGxhYmVscy56TGFiZWwsXG4gICAgICAgICAgICAgICAgdGV4dDogdHgsXG4gICAgICAgICAgICAgICAgbmFtZTogbGFzdFBpY2tlZC5uYW1lLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2VOb3csIHB0TnVtYmVyLCAnYmdjb2xvcicpIHx8IGxhc3RQaWNrZWQuY29sb3IsXG4gICAgICAgICAgICAgICAgYm9yZGVyQ29sb3I6IEZ4LmNhc3RIb3Zlck9wdGlvbih0cmFjZU5vdywgcHROdW1iZXIsICdib3JkZXJjb2xvcicpLFxuICAgICAgICAgICAgICAgIGZvbnRGYW1pbHk6IEZ4LmNhc3RIb3Zlck9wdGlvbih0cmFjZU5vdywgcHROdW1iZXIsICdmb250LmZhbWlseScpLFxuICAgICAgICAgICAgICAgIGZvbnRTaXplOiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2VOb3csIHB0TnVtYmVyLCAnZm9udC5zaXplJyksXG4gICAgICAgICAgICAgICAgZm9udENvbG9yOiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2VOb3csIHB0TnVtYmVyLCAnZm9udC5jb2xvcicpLFxuICAgICAgICAgICAgICAgIG5hbWVMZW5ndGg6IEZ4LmNhc3RIb3Zlck9wdGlvbih0cmFjZU5vdywgcHROdW1iZXIsICduYW1lbGVuZ3RoJyksXG4gICAgICAgICAgICAgICAgdGV4dEFsaWduOiBGeC5jYXN0SG92ZXJPcHRpb24odHJhY2VOb3csIHB0TnVtYmVyLCAnYWxpZ24nKSxcbiAgICAgICAgICAgICAgICBob3ZlcnRlbXBsYXRlOiBMaWIuY2FzdE9wdGlvbih0cmFjZU5vdywgcHROdW1iZXIsICdob3ZlcnRlbXBsYXRlJyksXG4gICAgICAgICAgICAgICAgaG92ZXJ0ZW1wbGF0ZUxhYmVsczogTGliLmV4dGVuZEZsYXQoe30sIHBvaW50RGF0YSwgbGFiZWxzKSxcbiAgICAgICAgICAgICAgICBldmVudERhdGE6IFtwb2ludERhdGFdXG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiBzdmdDb250YWluZXIsXG4gICAgICAgICAgICAgICAgZ2Q6IGdkXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHNlbGVjdGlvbi5idXR0b25zICYmIHNlbGVjdGlvbi5kaXN0YW5jZSA8IDUpIHtcbiAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9jbGljaycsIGV2ZW50RGF0YSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfaG92ZXInLCBldmVudERhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgb2xkRXZlbnREYXRhID0gZXZlbnREYXRhO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIEZ4LmxvbmVVbmhvdmVyKHN2Z0NvbnRhaW5lcik7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV91bmhvdmVyJywgb2xkRXZlbnREYXRhKTtcbiAgICB9XG5cbiAgICBzY2VuZS5kcmF3QW5ub3RhdGlvbnMoc2NlbmUpO1xufVxuXG5mdW5jdGlvbiB0cnlDcmVhdGVQbG90KHNjZW5lLCBjYW1lcmFPYmplY3QsIHBpeGVsUmF0aW8sIGNhbnZhcywgZ2wpIHtcbiAgICB2YXIgZ2xwbG90T3B0aW9ucyA9IHtcbiAgICAgICAgY2FudmFzOiBjYW52YXMsXG4gICAgICAgIGdsOiBnbCxcbiAgICAgICAgY29udGFpbmVyOiBzY2VuZS5jb250YWluZXIsXG4gICAgICAgIGF4ZXM6IHNjZW5lLmF4ZXNPcHRpb25zLFxuICAgICAgICBzcGlrZXM6IHNjZW5lLnNwaWtlT3B0aW9ucyxcbiAgICAgICAgcGlja1JhZGl1czogMTAsXG4gICAgICAgIHNuYXBUb0RhdGE6IHRydWUsXG4gICAgICAgIGF1dG9TY2FsZTogdHJ1ZSxcbiAgICAgICAgYXV0b0JvdW5kczogZmFsc2UsXG4gICAgICAgIGNhbWVyYU9iamVjdDogY2FtZXJhT2JqZWN0LFxuICAgICAgICBwaXhlbFJhdGlvOiBwaXhlbFJhdGlvXG4gICAgfTtcblxuICAgIC8vIGZvciBzdGF0aWMgcGxvdHMsIHdlIHJldXNlIHRoZSBXZWJHTCBjb250ZXh0XG4gICAgLy8gIGFzIFdlYktpdCBkb2Vzbid0IGNvbGxlY3QgdGhlbSByZWxpYWJseVxuICAgIGlmKHNjZW5lLnN0YXRpY01vZGUpIHtcbiAgICAgICAgaWYoIVNUQVRJQ19DT05URVhUKSB7XG4gICAgICAgICAgICBTVEFUSUNfQ0FOVkFTID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgICAgICBTVEFUSUNfQ09OVEVYVCA9IGdldENvbnRleHQoe1xuICAgICAgICAgICAgICAgIGNhbnZhczogU1RBVElDX0NBTlZBUyxcbiAgICAgICAgICAgICAgICBwcmVzZXJ2ZURyYXdpbmdCdWZmZXI6IHRydWUsXG4gICAgICAgICAgICAgICAgcHJlbXVsdGlwbGllZEFscGhhOiB0cnVlLFxuICAgICAgICAgICAgICAgIGFudGlhbGlhczogdHJ1ZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZighU1RBVElDX0NPTlRFWFQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Vycm9yIGNyZWF0aW5nIHN0YXRpYyBjYW52YXMvY29udGV4dCBmb3IgaW1hZ2Ugc2VydmVyJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZ2xwbG90T3B0aW9ucy5waXhlbFJhdGlvID0gc2NlbmUucGl4ZWxSYXRpbztcbiAgICAgICAgZ2xwbG90T3B0aW9ucy5nbCA9IFNUQVRJQ19DT05URVhUO1xuICAgICAgICBnbHBsb3RPcHRpb25zLmNhbnZhcyA9IFNUQVRJQ19DQU5WQVM7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgICAgc2NlbmUuZ2xwbG90ID0gY3JlYXRlUGxvdChnbHBsb3RPcHRpb25zKTtcbiAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBpbml0aWFsaXplR0xQbG90KHNjZW5lLCBwaXhlbFJhdGlvLCBjYW52YXMsIGdsKSB7XG4gICAgc2NlbmUuaW5pdGlhbGl6ZUdMQ2FtZXJhKCk7XG5cbiAgICB2YXIgc3VjY2VzcyA9IHRyeUNyZWF0ZVBsb3Qoc2NlbmUsIHNjZW5lLmNhbWVyYSwgcGl4ZWxSYXRpbywgY2FudmFzLCBnbCk7XG4gICAgLypcbiAgICAqIGNyZWF0ZVBsb3Qgd2lsbCB0aHJvdyB3aGVuIHdlYmdsIGlzIG5vdCBlbmFibGVkIGluIHRoZSBjbGllbnQuXG4gICAgKiBMZXRzIHJldHVybiBhbiBpbnN0YW5jZSBvZiB0aGUgbW9kdWxlIHdpdGggYWxsIGZ1bmN0aW9ucyBub29wJ2QuXG4gICAgKiBUaGUgZGVzdHJveSBtZXRob2QgLSB3aGljaCB3aWxsIHJlbW92ZSB0aGUgY29udGFpbmVyIGZyb20gdGhlIERPTVxuICAgICogaXMgb3ZlcnJpZGRlbiB3aXRoIGEgZnVuY3Rpb24gdGhhdCByZW1vdmVzIHRoZSBjb250YWluZXIgb25seS5cbiAgICAqL1xuICAgIGlmKCFzdWNjZXNzKSByZXR1cm4gc2hvd05vV2ViR2xNc2coc2NlbmUpO1xuXG4gICAgdmFyIGdkID0gc2NlbmUuZ3JhcGhEaXY7XG5cbiAgICB2YXIgcmVsYXlvdXRDYWxsYmFjayA9IGZ1bmN0aW9uKHNjZW5lKSB7XG4gICAgICAgIGlmKHNjZW5lLmZ1bGxTY2VuZUxheW91dC5kcmFnbW9kZSA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgICAgICB2YXIgdXBkYXRlID0ge307XG4gICAgICAgIHVwZGF0ZVtzY2VuZS5pZCArICcuY2FtZXJhJ10gPSBnZXRMYXlvdXRDYW1lcmEoc2NlbmUuY2FtZXJhKTtcbiAgICAgICAgc2NlbmUuc2F2ZUNhbWVyYShnZC5sYXlvdXQpO1xuICAgICAgICBzY2VuZS5ncmFwaERpdi5lbWl0KCdwbG90bHlfcmVsYXlvdXQnLCB1cGRhdGUpO1xuICAgIH07XG5cbiAgICBzY2VuZS5nbHBsb3QuY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgcmVsYXlvdXRDYWxsYmFjayhzY2VuZSk7XG4gICAgfSk7XG5cbiAgICBzY2VuZS5nbHBsb3QuY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ3doZWVsJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmKGdkLl9jb250ZXh0Ll9zY3JvbGxab29tLmdsM2QpIHtcbiAgICAgICAgICAgIHJlbGF5b3V0Q2FsbGJhY2soc2NlbmUpO1xuICAgICAgICB9XG4gICAgfSwgcGFzc2l2ZVN1cHBvcnRlZCA/IHtwYXNzaXZlOiBmYWxzZX0gOiBmYWxzZSk7XG5cbiAgICBzY2VuZS5nbHBsb3QuY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIGZ1bmN0aW9uKCkge1xuICAgICAgICBpZihzY2VuZS5mdWxsU2NlbmVMYXlvdXQuZHJhZ21vZGUgPT09IGZhbHNlKSByZXR1cm47XG4gICAgICAgIGlmKHNjZW5lLmNhbWVyYS5tb3VzZUxpc3RlbmVyLmJ1dHRvbnMgPT09IDApIHJldHVybjtcblxuICAgICAgICB2YXIgdXBkYXRlID0ge307XG4gICAgICAgIHVwZGF0ZVtzY2VuZS5pZCArICcuY2FtZXJhJ10gPSBnZXRMYXlvdXRDYW1lcmEoc2NlbmUuY2FtZXJhKTtcbiAgICAgICAgc2NlbmUuZ3JhcGhEaXYuZW1pdCgncGxvdGx5X3JlbGF5b3V0aW5nJywgdXBkYXRlKTtcbiAgICB9KTtcblxuICAgIGlmKCFzY2VuZS5zdGF0aWNNb2RlKSB7XG4gICAgICAgIHNjZW5lLmdscGxvdC5jYW52YXMuYWRkRXZlbnRMaXN0ZW5lcignd2ViZ2xjb250ZXh0bG9zdCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICBpZihnZCAmJiBnZC5lbWl0KSB7XG4gICAgICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3dlYmdsY29udGV4dGxvc3QnLCB7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50OiBldmVudCxcbiAgICAgICAgICAgICAgICAgICAgbGF5ZXI6IHNjZW5lLmlkXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIGZhbHNlKTtcbiAgICB9XG5cbiAgICBzY2VuZS5nbHBsb3QuY2FtZXJhID0gc2NlbmUuY2FtZXJhO1xuXG4gICAgc2NlbmUuZ2xwbG90Lm9uY29udGV4dGxvc3MgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgc2NlbmUucmVjb3ZlckNvbnRleHQoKTtcbiAgICB9O1xuXG4gICAgc2NlbmUuZ2xwbG90Lm9ucmVuZGVyID0gcmVuZGVyLmJpbmQobnVsbCwgc2NlbmUpO1xuXG4gICAgLy8gTGlzdCBvZiBzY2VuZSBvYmplY3RzXG4gICAgc2NlbmUudHJhY2VzID0ge307XG5cbiAgICBzY2VuZS5tYWtlNHRoRGltZW5zaW9uKCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gU2NlbmUob3B0aW9ucywgZnVsbExheW91dCkge1xuICAgIC8vIGNyZWF0ZSBzdWIgY29udGFpbmVyIGZvciBwbG90XG4gICAgdmFyIHNjZW5lQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgdmFyIHBsb3RDb250YWluZXIgPSBvcHRpb25zLmNvbnRhaW5lcjtcblxuICAgIC8vIGtlZXAgYSByZWYgdG8gdGhlIGdyYXBoIGRpdiB0byBmaXJlIGhvdmVyK2NsaWNrIGV2ZW50c1xuICAgIHRoaXMuZ3JhcGhEaXYgPSBvcHRpb25zLmdyYXBoRGl2O1xuXG4gICAgLy8gY3JlYXRlIFNWRyBjb250YWluZXIgZm9yIGhvdmVyIHRleHRcbiAgICB2YXIgc3ZnQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFxuICAgICAgICAnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnLFxuICAgICAgICAnc3ZnJyk7XG4gICAgc3ZnQ29udGFpbmVyLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBzdmdDb250YWluZXIuc3R5bGUudG9wID0gc3ZnQ29udGFpbmVyLnN0eWxlLmxlZnQgPSAnMHB4JztcbiAgICBzdmdDb250YWluZXIuc3R5bGUud2lkdGggPSBzdmdDb250YWluZXIuc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xuICAgIHN2Z0NvbnRhaW5lci5zdHlsZVsnei1pbmRleCddID0gMjA7XG4gICAgc3ZnQ29udGFpbmVyLnN0eWxlWydwb2ludGVyLWV2ZW50cyddID0gJ25vbmUnO1xuICAgIHNjZW5lQ29udGFpbmVyLmFwcGVuZENoaWxkKHN2Z0NvbnRhaW5lcik7XG4gICAgdGhpcy5zdmdDb250YWluZXIgPSBzdmdDb250YWluZXI7XG5cbiAgICAvLyBUYWcgdGhlIGNvbnRhaW5lciB3aXRoIHRoZSBzY2VuZUlEXG4gICAgc2NlbmVDb250YWluZXIuaWQgPSBvcHRpb25zLmlkO1xuICAgIHNjZW5lQ29udGFpbmVyLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBzY2VuZUNvbnRhaW5lci5zdHlsZS50b3AgPSBzY2VuZUNvbnRhaW5lci5zdHlsZS5sZWZ0ID0gJzBweCc7XG4gICAgc2NlbmVDb250YWluZXIuc3R5bGUud2lkdGggPSBzY2VuZUNvbnRhaW5lci5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7XG4gICAgcGxvdENvbnRhaW5lci5hcHBlbmRDaGlsZChzY2VuZUNvbnRhaW5lcik7XG5cbiAgICB0aGlzLmZ1bGxMYXlvdXQgPSBmdWxsTGF5b3V0O1xuICAgIHRoaXMuaWQgPSBvcHRpb25zLmlkIHx8ICdzY2VuZSc7XG4gICAgdGhpcy5mdWxsU2NlbmVMYXlvdXQgPSBmdWxsTGF5b3V0W3RoaXMuaWRdO1xuXG4gICAgLy8gU2F2ZWQgZnJvbSBsYXN0IGNhbGwgdG8gcGxvdCgpXG4gICAgdGhpcy5wbG90QXJncyA9IFsgW10sIHt9LCB7fSBdO1xuXG4gICAgLypcbiAgICAgKiBNb3ZlIHRoaXMgdG8gY2FsYyBzdGVwPyBXaHkgZG9lcyBpdCB3b3JrIGhlcmU/XG4gICAgICovXG4gICAgdGhpcy5heGVzT3B0aW9ucyA9IGNyZWF0ZUF4ZXNPcHRpb25zKGZ1bGxMYXlvdXQsIGZ1bGxMYXlvdXRbdGhpcy5pZF0pO1xuICAgIHRoaXMuc3Bpa2VPcHRpb25zID0gY3JlYXRlU3Bpa2VPcHRpb25zKGZ1bGxMYXlvdXRbdGhpcy5pZF0pO1xuICAgIHRoaXMuY29udGFpbmVyID0gc2NlbmVDb250YWluZXI7XG4gICAgdGhpcy5zdGF0aWNNb2RlID0gISFvcHRpb25zLnN0YXRpY1Bsb3Q7XG4gICAgdGhpcy5waXhlbFJhdGlvID0gdGhpcy5waXhlbFJhdGlvIHx8IG9wdGlvbnMucGxvdEdsUGl4ZWxSYXRpbyB8fCAyO1xuXG4gICAgLy8gQ29vcmRpbmF0ZSByZXNjYWxpbmdcbiAgICB0aGlzLmRhdGFTY2FsZSA9IFsxLCAxLCAxXTtcblxuICAgIHRoaXMuY29udG91ckxldmVscyA9IFsgW10sIFtdLCBbXSBdO1xuXG4gICAgdGhpcy5jb252ZXJ0QW5ub3RhdGlvbnMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Fubm90YXRpb25zM2QnLCAnY29udmVydCcpO1xuICAgIHRoaXMuZHJhd0Fubm90YXRpb25zID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdhbm5vdGF0aW9uczNkJywgJ2RyYXcnKTtcblxuICAgIGluaXRpYWxpemVHTFBsb3QodGhpcywgdGhpcy5waXhlbFJhdGlvKTtcbn1cblxudmFyIHByb3RvID0gU2NlbmUucHJvdG90eXBlO1xuXG5wcm90by5pbml0aWFsaXplR0xDYW1lcmEgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgY2FtZXJhRGF0YSA9IHRoaXMuZnVsbFNjZW5lTGF5b3V0LmNhbWVyYTtcbiAgICB2YXIgaXNPcnRobyA9IChjYW1lcmFEYXRhLnByb2plY3Rpb24udHlwZSA9PT0gJ29ydGhvZ3JhcGhpYycpO1xuXG4gICAgdGhpcy5jYW1lcmEgPSBjcmVhdGVDYW1lcmEodGhpcy5jb250YWluZXIsIHtcbiAgICAgICAgY2VudGVyOiBbY2FtZXJhRGF0YS5jZW50ZXIueCwgY2FtZXJhRGF0YS5jZW50ZXIueSwgY2FtZXJhRGF0YS5jZW50ZXIuel0sXG4gICAgICAgIGV5ZTogW2NhbWVyYURhdGEuZXllLngsIGNhbWVyYURhdGEuZXllLnksIGNhbWVyYURhdGEuZXllLnpdLFxuICAgICAgICB1cDogW2NhbWVyYURhdGEudXAueCwgY2FtZXJhRGF0YS51cC55LCBjYW1lcmFEYXRhLnVwLnpdLFxuICAgICAgICBfb3J0aG86IGlzT3J0aG8sXG4gICAgICAgIHpvb21NaW46IDAuMDEsXG4gICAgICAgIHpvb21NYXg6IDEwMCxcbiAgICAgICAgbW9kZTogJ29yYml0J1xuICAgIH0pO1xufTtcblxucHJvdG8ucmVjb3ZlckNvbnRleHQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc2NlbmUgPSB0aGlzO1xuICAgIHZhciBnbCA9IHRoaXMuZ2xwbG90LmdsO1xuICAgIHZhciBjYW52YXMgPSB0aGlzLmdscGxvdC5jYW52YXM7XG4gICAgdmFyIGNhbWVyYSA9IHRoaXMuZ2xwbG90LmNhbWVyYTtcbiAgICB2YXIgcGl4ZWxSYXRpbyA9IHRoaXMuZ2xwbG90LnBpeGVsUmF0aW87XG4gICAgdGhpcy5nbHBsb3QuZGlzcG9zZSgpO1xuXG4gICAgZnVuY3Rpb24gdHJ5UmVjb3ZlcigpIHtcbiAgICAgICAgaWYoZ2wuaXNDb250ZXh0TG9zdCgpKSB7XG4gICAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodHJ5UmVjb3Zlcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYoIWluaXRpYWxpemVHTFBsb3Qoc2NlbmUsIGNhbWVyYSwgcGl4ZWxSYXRpbywgY2FudmFzLCBnbCkpIHtcbiAgICAgICAgICAgIExpYi5lcnJvcignQ2F0YXN0cm9waGljIGFuZCB1bnJlY292ZXJhYmxlIFdlYkdMIGVycm9yLiBDb250ZXh0IGxvc3QuJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgc2NlbmUucGxvdC5hcHBseShzY2VuZSwgc2NlbmUucGxvdEFyZ3MpO1xuICAgIH1cbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodHJ5UmVjb3Zlcik7XG59O1xuXG52YXIgYXhpc1Byb3BlcnRpZXMgPSBbICd4YXhpcycsICd5YXhpcycsICd6YXhpcycgXTtcblxuZnVuY3Rpb24gY29tcHV0ZVRyYWNlQm91bmRzKHNjZW5lLCB0cmFjZSwgYm91bmRzKSB7XG4gICAgdmFyIHNjZW5lTGF5b3V0ID0gc2NlbmUuZnVsbFNjZW5lTGF5b3V0O1xuXG4gICAgZm9yKHZhciBkID0gMDsgZCA8IDM7IGQrKykge1xuICAgICAgICB2YXIgYXhpc05hbWUgPSBheGlzUHJvcGVydGllc1tkXTtcbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhpc05hbWUuY2hhckF0KDApO1xuICAgICAgICB2YXIgYXggPSBzY2VuZUxheW91dFtheGlzTmFtZV07XG4gICAgICAgIHZhciBjb29yZHMgPSB0cmFjZVtheExldHRlcl07XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRyYWNlW2F4TGV0dGVyICsgJ2NhbGVuZGFyJ107XG4gICAgICAgIHZhciBsZW4gPSB0cmFjZVsnXycgKyBheExldHRlciArICdsZW5ndGgnXTtcblxuICAgICAgICBpZighTGliLmlzQXJyYXlPclR5cGVkQXJyYXkoY29vcmRzKSkge1xuICAgICAgICAgICAgYm91bmRzWzBdW2RdID0gTWF0aC5taW4oYm91bmRzWzBdW2RdLCAwKTtcbiAgICAgICAgICAgIGJvdW5kc1sxXVtkXSA9IE1hdGgubWF4KGJvdW5kc1sxXVtkXSwgbGVuIC0gMSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgdjtcblxuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IChsZW4gfHwgY29vcmRzLmxlbmd0aCk7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGNvb3Jkc1tpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNvb3Jkc1tpXS5sZW5ndGg7ICsraikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdiA9IGF4LmQybChjb29yZHNbaV1bal0sIDAsIGNhbGVuZGFyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCFpc05hTih2KSAmJiBpc0Zpbml0ZSh2KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kc1swXVtkXSA9IE1hdGgubWluKGJvdW5kc1swXVtkXSwgdik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzWzFdW2RdID0gTWF0aC5tYXgoYm91bmRzWzFdW2RdLCB2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHYgPSBheC5kMmwoY29vcmRzW2ldLCAwLCBjYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgICAgIGlmKCFpc05hTih2KSAmJiBpc0Zpbml0ZSh2KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzWzBdW2RdID0gTWF0aC5taW4oYm91bmRzWzBdW2RdLCB2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kc1sxXVtkXSA9IE1hdGgubWF4KGJvdW5kc1sxXVtkXSwgdik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVBbm5vdGF0aW9uQm91bmRzKHNjZW5lLCBib3VuZHMpIHtcbiAgICB2YXIgc2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIGFubm90YXRpb25zID0gc2NlbmVMYXlvdXQuYW5ub3RhdGlvbnMgfHwgW107XG5cbiAgICBmb3IodmFyIGQgPSAwOyBkIDwgMzsgZCsrKSB7XG4gICAgICAgIHZhciBheGlzTmFtZSA9IGF4aXNQcm9wZXJ0aWVzW2RdO1xuICAgICAgICB2YXIgYXhMZXR0ZXIgPSBheGlzTmFtZS5jaGFyQXQoMCk7XG4gICAgICAgIHZhciBheCA9IHNjZW5lTGF5b3V0W2F4aXNOYW1lXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgYW5ub3RhdGlvbnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBhbm4gPSBhbm5vdGF0aW9uc1tqXTtcblxuICAgICAgICAgICAgaWYoYW5uLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcG9zID0gYXgucjJsKGFubltheExldHRlcl0pO1xuICAgICAgICAgICAgICAgIGlmKCFpc05hTihwb3MpICYmIGlzRmluaXRlKHBvcykpIHtcbiAgICAgICAgICAgICAgICAgICAgYm91bmRzWzBdW2RdID0gTWF0aC5taW4oYm91bmRzWzBdW2RdLCBwb3MpO1xuICAgICAgICAgICAgICAgICAgICBib3VuZHNbMV1bZF0gPSBNYXRoLm1heChib3VuZHNbMV1bZF0sIHBvcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5wcm90by5wbG90ID0gZnVuY3Rpb24oc2NlbmVEYXRhLCBmdWxsTGF5b3V0LCBsYXlvdXQpIHtcbiAgICAvLyBTYXZlIHBhcmFtZXRlcnNcbiAgICB0aGlzLnBsb3RBcmdzID0gW3NjZW5lRGF0YSwgZnVsbExheW91dCwgbGF5b3V0XTtcblxuICAgIGlmKHRoaXMuZ2xwbG90LmNvbnRleHRMb3N0KSByZXR1cm47XG5cbiAgICB2YXIgZGF0YSwgdHJhY2U7XG4gICAgdmFyIGksIGosIGF4aXMsIGF4aXNUeXBlO1xuICAgIHZhciBmdWxsU2NlbmVMYXlvdXQgPSBmdWxsTGF5b3V0W3RoaXMuaWRdO1xuICAgIHZhciBzY2VuZUxheW91dCA9IGxheW91dFt0aGlzLmlkXTtcblxuICAgIGlmKGZ1bGxTY2VuZUxheW91dC5iZ2NvbG9yKSB0aGlzLmdscGxvdC5jbGVhckNvbG9yID0gc3RyMlJHQkFhcnJheShmdWxsU2NlbmVMYXlvdXQuYmdjb2xvcik7XG4gICAgZWxzZSB0aGlzLmdscGxvdC5jbGVhckNvbG9yID0gWzAsIDAsIDAsIDBdO1xuXG4gICAgdGhpcy5nbHBsb3Quc25hcFRvRGF0YSA9IHRydWU7XG5cbiAgICAvLyBVcGRhdGUgbGF5b3V0XG4gICAgdGhpcy5mdWxsTGF5b3V0ID0gZnVsbExheW91dDtcbiAgICB0aGlzLmZ1bGxTY2VuZUxheW91dCA9IGZ1bGxTY2VuZUxheW91dDtcblxuICAgIHRoaXMuZ2xwbG90TGF5b3V0ID0gZnVsbFNjZW5lTGF5b3V0O1xuICAgIHRoaXMuYXhlc09wdGlvbnMubWVyZ2UoZnVsbExheW91dCwgZnVsbFNjZW5lTGF5b3V0KTtcbiAgICB0aGlzLnNwaWtlT3B0aW9ucy5tZXJnZShmdWxsU2NlbmVMYXlvdXQpO1xuXG4gICAgLy8gVXBkYXRlIGNhbWVyYSBhbmQgY2FtZXJhIG1vZGVcbiAgICB0aGlzLnNldENhbWVyYShmdWxsU2NlbmVMYXlvdXQuY2FtZXJhKTtcbiAgICB0aGlzLnVwZGF0ZUZ4KGZ1bGxTY2VuZUxheW91dC5kcmFnbW9kZSwgZnVsbFNjZW5lTGF5b3V0LmhvdmVybW9kZSk7XG4gICAgdGhpcy5jYW1lcmEuZW5hYmxlV2hlZWwgPSB0aGlzLmdyYXBoRGl2Ll9jb250ZXh0Ll9zY3JvbGxab29tLmdsM2Q7XG5cbiAgICAvLyBVcGRhdGUgc2NlbmVcbiAgICB0aGlzLmdscGxvdC51cGRhdGUoe30pO1xuXG4gICAgLy8gVXBkYXRlIGF4ZXMgZnVuY3Rpb25zIEJFRk9SRSB1cGRhdGluZyB0cmFjZXNcbiAgICB0aGlzLnNldENvbnZlcnQoYXhpcyk7XG5cbiAgICAvLyBDb252ZXJ0IHNjZW5lIGRhdGFcbiAgICBpZighc2NlbmVEYXRhKSBzY2VuZURhdGEgPSBbXTtcbiAgICBlbHNlIGlmKCFBcnJheS5pc0FycmF5KHNjZW5lRGF0YSkpIHNjZW5lRGF0YSA9IFtzY2VuZURhdGFdO1xuXG4gICAgLy8gQ29tcHV0ZSB0cmFjZSBib3VuZGluZyBib3hcbiAgICB2YXIgZGF0YUJvdW5kcyA9IFtcbiAgICAgICAgW0luZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldLFxuICAgICAgICBbLUluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV1cbiAgICBdO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgc2NlbmVEYXRhLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGRhdGEgPSBzY2VuZURhdGFbaV07XG4gICAgICAgIGlmKGRhdGEudmlzaWJsZSAhPT0gdHJ1ZSB8fCBkYXRhLl9sZW5ndGggPT09IDApIGNvbnRpbnVlO1xuXG4gICAgICAgIGNvbXB1dGVUcmFjZUJvdW5kcyh0aGlzLCBkYXRhLCBkYXRhQm91bmRzKTtcbiAgICB9XG4gICAgY29tcHV0ZUFubm90YXRpb25Cb3VuZHModGhpcywgZGF0YUJvdW5kcyk7XG5cbiAgICB2YXIgZGF0YVNjYWxlID0gWzEsIDEsIDFdO1xuICAgIGZvcihqID0gMDsgaiA8IDM7ICsraikge1xuICAgICAgICBpZihkYXRhQm91bmRzWzFdW2pdID09PSBkYXRhQm91bmRzWzBdW2pdKSB7XG4gICAgICAgICAgICBkYXRhU2NhbGVbal0gPSAxLjA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkYXRhU2NhbGVbal0gPSAxLjAgLyAoZGF0YUJvdW5kc1sxXVtqXSAtIGRhdGFCb3VuZHNbMF1bal0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gU2F2ZSBzY2FsZVxuICAgIHRoaXMuZGF0YVNjYWxlID0gZGF0YVNjYWxlO1xuXG4gICAgLy8gYWZ0ZXIgY29tcHV0ZVRyYWNlQm91bmRzIHdoZXJlIGF4Ll9jYXRlZ29yaWVzIGFyZSBmaWxsZWQgaW5cbiAgICB0aGlzLmNvbnZlcnRBbm5vdGF0aW9ucyh0aGlzKTtcblxuICAgIC8vIFVwZGF0ZSB0cmFjZXNcbiAgICBmb3IoaSA9IDA7IGkgPCBzY2VuZURhdGEubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgZGF0YSA9IHNjZW5lRGF0YVtpXTtcbiAgICAgICAgaWYoZGF0YS52aXNpYmxlICE9PSB0cnVlIHx8IGRhdGEuX2xlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdHJhY2UgPSB0aGlzLnRyYWNlc1tkYXRhLnVpZF07XG4gICAgICAgIGlmKHRyYWNlKSB7XG4gICAgICAgICAgICBpZih0cmFjZS5kYXRhLnR5cGUgPT09IGRhdGEudHlwZSkge1xuICAgICAgICAgICAgICAgIHRyYWNlLnVwZGF0ZShkYXRhKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdHJhY2UuZGlzcG9zZSgpO1xuICAgICAgICAgICAgICAgIHRyYWNlID0gZGF0YS5fbW9kdWxlLnBsb3QodGhpcywgZGF0YSk7XG4gICAgICAgICAgICAgICAgdGhpcy50cmFjZXNbZGF0YS51aWRdID0gdHJhY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0cmFjZSA9IGRhdGEuX21vZHVsZS5wbG90KHRoaXMsIGRhdGEpO1xuICAgICAgICAgICAgdGhpcy50cmFjZXNbZGF0YS51aWRdID0gdHJhY2U7XG4gICAgICAgIH1cbiAgICAgICAgdHJhY2UubmFtZSA9IGRhdGEubmFtZTtcbiAgICB9XG5cbiAgICAvLyBSZW1vdmUgZW1wdHkgdHJhY2VzXG4gICAgdmFyIHRyYWNlSWRzID0gT2JqZWN0LmtleXModGhpcy50cmFjZXMpO1xuXG4gICAgdHJhY2VJZExvb3A6XG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhY2VJZHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgc2NlbmVEYXRhLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICBpZihzY2VuZURhdGFbal0udWlkID09PSB0cmFjZUlkc1tpXSAmJlxuICAgICAgICAgICAgICAgIChzY2VuZURhdGFbal0udmlzaWJsZSA9PT0gdHJ1ZSAmJiBzY2VuZURhdGFbal0uX2xlbmd0aCAhPT0gMCkpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZSB0cmFjZUlkTG9vcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0cmFjZSA9IHRoaXMudHJhY2VzW3RyYWNlSWRzW2ldXTtcbiAgICAgICAgdHJhY2UuZGlzcG9zZSgpO1xuICAgICAgICBkZWxldGUgdGhpcy50cmFjZXNbdHJhY2VJZHNbaV1dO1xuICAgIH1cblxuICAgIC8vIG9yZGVyIG9iamVjdCBwZXIgdHJhY2UgaW5kZXhcbiAgICB0aGlzLmdscGxvdC5vYmplY3RzLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICByZXR1cm4gYS5fdHJhY2UuZGF0YS5pbmRleCAtIGIuX3RyYWNlLmRhdGEuaW5kZXg7XG4gICAgfSk7XG5cbiAgICAvLyBVcGRhdGUgcmFuZ2VzIChuZWVkcyB0byBiZSBjYWxsZWQgKmFmdGVyKiBvYmplY3RzIGFyZSBhZGRlZCBkdWUgdG8gdXBkYXRlcylcbiAgICB2YXIgc2NlbmVCb3VuZHMgPSBbWzAsIDAsIDBdLCBbMCwgMCwgMF1dO1xuICAgIHZhciBheGlzRGF0YVJhbmdlID0gW107XG4gICAgdmFyIGF4aXNUeXBlUmF0aW9zID0ge307XG5cbiAgICBmb3IoaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICAgICAgYXhpcyA9IGZ1bGxTY2VuZUxheW91dFtheGlzUHJvcGVydGllc1tpXV07XG4gICAgICAgIGF4aXNUeXBlID0gYXhpcy50eXBlO1xuXG4gICAgICAgIGlmKGF4aXNUeXBlIGluIGF4aXNUeXBlUmF0aW9zKSB7XG4gICAgICAgICAgICBheGlzVHlwZVJhdGlvc1theGlzVHlwZV0uYWNjICo9IGRhdGFTY2FsZVtpXTtcbiAgICAgICAgICAgIGF4aXNUeXBlUmF0aW9zW2F4aXNUeXBlXS5jb3VudCArPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXhpc1R5cGVSYXRpb3NbYXhpc1R5cGVdID0ge1xuICAgICAgICAgICAgICAgIGFjYzogZGF0YVNjYWxlW2ldLFxuICAgICAgICAgICAgICAgIGNvdW50OiAxXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYXhpcy5hdXRvcmFuZ2UpIHtcbiAgICAgICAgICAgIHNjZW5lQm91bmRzWzBdW2ldID0gSW5maW5pdHk7XG4gICAgICAgICAgICBzY2VuZUJvdW5kc1sxXVtpXSA9IC1JbmZpbml0eTtcblxuICAgICAgICAgICAgdmFyIG9iamVjdHMgPSB0aGlzLmdscGxvdC5vYmplY3RzO1xuICAgICAgICAgICAgdmFyIGFubm90YXRpb25zID0gdGhpcy5mdWxsU2NlbmVMYXlvdXQuYW5ub3RhdGlvbnMgfHwgW107XG4gICAgICAgICAgICB2YXIgYXhMZXR0ZXIgPSBheGlzLl9uYW1lLmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgb2JqZWN0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBvYmogPSBvYmplY3RzW2pdO1xuICAgICAgICAgICAgICAgIHZhciBvYmpCb3VuZHMgPSBvYmouYm91bmRzO1xuICAgICAgICAgICAgICAgIHZhciBwYWQgPSBvYmouX3RyYWNlLmRhdGEuX3BhZCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgaWYob2JqLmNvbnN0cnVjdG9yLm5hbWUgPT09ICdFcnJvckJhcnMnICYmIGF4aXMuX2xvd2VyTG9nRXJyb3JCb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSA9IE1hdGgubWluKHNjZW5lQm91bmRzWzBdW2ldLCBheGlzLl9sb3dlckxvZ0Vycm9yQm91bmQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNjZW5lQm91bmRzWzBdW2ldID0gTWF0aC5taW4oc2NlbmVCb3VuZHNbMF1baV0sIG9iakJvdW5kc1swXVtpXSAvIGRhdGFTY2FsZVtpXSAtIHBhZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNjZW5lQm91bmRzWzFdW2ldID0gTWF0aC5tYXgoc2NlbmVCb3VuZHNbMV1baV0sIG9iakJvdW5kc1sxXVtpXSAvIGRhdGFTY2FsZVtpXSArIHBhZCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGFubm90YXRpb25zLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFubiA9IGFubm90YXRpb25zW2pdO1xuXG4gICAgICAgICAgICAgICAgLy8gTi5CLiBub3QgdGFraW5nIGludG8gY29uc2lkZXJhdGlvbiB0aGUgYXJyb3doZWFkXG4gICAgICAgICAgICAgICAgaWYoYW5uLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvcyA9IGF4aXMucjJsKGFubltheExldHRlcl0pO1xuICAgICAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSA9IE1hdGgubWluKHNjZW5lQm91bmRzWzBdW2ldLCBwb3MpO1xuICAgICAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1sxXVtpXSA9IE1hdGgubWF4KHNjZW5lQm91bmRzWzFdW2ldLCBwb3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoJ3JhbmdlbW9kZScgaW4gYXhpcyAmJiBheGlzLnJhbmdlbW9kZSA9PT0gJ3RvemVybycpIHtcbiAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSA9IE1hdGgubWluKHNjZW5lQm91bmRzWzBdW2ldLCAwKTtcbiAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1sxXVtpXSA9IE1hdGgubWF4KHNjZW5lQm91bmRzWzFdW2ldLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHNjZW5lQm91bmRzWzBdW2ldID4gc2NlbmVCb3VuZHNbMV1baV0pIHtcbiAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSA9IC0xO1xuICAgICAgICAgICAgICAgIHNjZW5lQm91bmRzWzFdW2ldID0gMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGQgPSBzY2VuZUJvdW5kc1sxXVtpXSAtIHNjZW5lQm91bmRzWzBdW2ldO1xuICAgICAgICAgICAgICAgIHNjZW5lQm91bmRzWzBdW2ldIC09IGQgLyAzMi4wO1xuICAgICAgICAgICAgICAgIHNjZW5lQm91bmRzWzFdW2ldICs9IGQgLyAzMi4wO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihheGlzLmF1dG9yYW5nZSA9PT0gJ3JldmVyc2VkJykge1xuICAgICAgICAgICAgICAgIC8vIHN3YXAgYm91bmRzOlxuICAgICAgICAgICAgICAgIHZhciB0bXAgPSBzY2VuZUJvdW5kc1swXVtpXTtcbiAgICAgICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSA9IHNjZW5lQm91bmRzWzFdW2ldO1xuICAgICAgICAgICAgICAgIHNjZW5lQm91bmRzWzFdW2ldID0gdG1wO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHJhbmdlID0gYXhpcy5yYW5nZTtcbiAgICAgICAgICAgIHNjZW5lQm91bmRzWzBdW2ldID0gYXhpcy5yMmwocmFuZ2VbMF0pO1xuICAgICAgICAgICAgc2NlbmVCb3VuZHNbMV1baV0gPSBheGlzLnIybChyYW5nZVsxXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoc2NlbmVCb3VuZHNbMF1baV0gPT09IHNjZW5lQm91bmRzWzFdW2ldKSB7XG4gICAgICAgICAgICBzY2VuZUJvdW5kc1swXVtpXSAtPSAxO1xuICAgICAgICAgICAgc2NlbmVCb3VuZHNbMV1baV0gKz0gMTtcbiAgICAgICAgfVxuICAgICAgICBheGlzRGF0YVJhbmdlW2ldID0gc2NlbmVCb3VuZHNbMV1baV0gLSBzY2VuZUJvdW5kc1swXVtpXTtcblxuICAgICAgICAvLyBVcGRhdGUgcGxvdCBib3VuZHNcbiAgICAgICAgdGhpcy5nbHBsb3QuYm91bmRzWzBdW2ldID0gc2NlbmVCb3VuZHNbMF1baV0gKiBkYXRhU2NhbGVbaV07XG4gICAgICAgIHRoaXMuZ2xwbG90LmJvdW5kc1sxXVtpXSA9IHNjZW5lQm91bmRzWzFdW2ldICogZGF0YVNjYWxlW2ldO1xuICAgIH1cblxuICAgIHZhciBheGVzU2NhbGVSYXRpbyA9IFsxLCAxLCAxXTtcblxuICAgIC8vIENvbXB1dGUgYXhpcyBzY2FsZSBwZXIgY2F0ZWdvcnlcbiAgICBmb3IoaSA9IDA7IGkgPCAzOyArK2kpIHtcbiAgICAgICAgYXhpcyA9IGZ1bGxTY2VuZUxheW91dFtheGlzUHJvcGVydGllc1tpXV07XG4gICAgICAgIGF4aXNUeXBlID0gYXhpcy50eXBlO1xuICAgICAgICB2YXIgYXhpc1JhdGlvID0gYXhpc1R5cGVSYXRpb3NbYXhpc1R5cGVdO1xuICAgICAgICBheGVzU2NhbGVSYXRpb1tpXSA9IE1hdGgucG93KGF4aXNSYXRpby5hY2MsIDEuMCAvIGF4aXNSYXRpby5jb3VudCkgLyBkYXRhU2NhbGVbaV07XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBEeW5hbWljYWxseSBzZXQgdGhlIGFzcGVjdCByYXRpbyBkZXBlbmRpbmcgb24gdGhlIHVzZXJzIGFzcGVjdCBzZXR0aW5nc1xuICAgICAqL1xuICAgIHZhciBheGlzQXV0b1NjYWxlRmFjdG9yID0gNDtcbiAgICB2YXIgYXNwZWN0UmF0aW87XG5cbiAgICBpZihmdWxsU2NlbmVMYXlvdXQuYXNwZWN0bW9kZSA9PT0gJ2F1dG8nKSB7XG4gICAgICAgIGlmKE1hdGgubWF4LmFwcGx5KG51bGwsIGF4ZXNTY2FsZVJhdGlvKSAvIE1hdGgubWluLmFwcGx5KG51bGwsIGF4ZXNTY2FsZVJhdGlvKSA8PSBheGlzQXV0b1NjYWxlRmFjdG9yKSB7XG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogVVNFIERBVEEgTU9ERSBXSEVOIEFYSVMgUkFOR0UgRElNRU5TSU9OUyBBUkUgUkVMQVRJVkVMWSBFUVVBTFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIGFzcGVjdFJhdGlvID0gYXhlc1NjYWxlUmF0aW87XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogVVNFIEVRVUFMIE1PREUgV0hFTiBBWElTIFJBTkdFIERJTUVOU0lPTlMgQVJFIEhJR0hMWSBVTkVRVUFMXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGFzcGVjdFJhdGlvID0gWzEsIDEsIDFdO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKGZ1bGxTY2VuZUxheW91dC5hc3BlY3Rtb2RlID09PSAnY3ViZScpIHtcbiAgICAgICAgYXNwZWN0UmF0aW8gPSBbMSwgMSwgMV07XG4gICAgfSBlbHNlIGlmKGZ1bGxTY2VuZUxheW91dC5hc3BlY3Rtb2RlID09PSAnZGF0YScpIHtcbiAgICAgICAgYXNwZWN0UmF0aW8gPSBheGVzU2NhbGVSYXRpbztcbiAgICB9IGVsc2UgaWYoZnVsbFNjZW5lTGF5b3V0LmFzcGVjdG1vZGUgPT09ICdtYW51YWwnKSB7XG4gICAgICAgIHZhciB1c2VyUmF0aW8gPSBmdWxsU2NlbmVMYXlvdXQuYXNwZWN0cmF0aW87XG4gICAgICAgIGFzcGVjdFJhdGlvID0gW3VzZXJSYXRpby54LCB1c2VyUmF0aW8ueSwgdXNlclJhdGlvLnpdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignc2NlbmUuanMgYXNwZWN0UmF0aW8gd2FzIG5vdCBvbmUgb2YgdGhlIGVudW1lcmF0ZWQgdHlwZXMnKTtcbiAgICB9XG5cbiAgICAvKlxuICAgICAqIFdyaXRlIGFzcGVjdCBSYXRpbyBiYWNrIHRvIHVzZXIgZGF0YSBhbmQgZnVsbExheW91dCBzbyB0aGF0IGl0IGlzIG1vZGlmaWVzIGFzIHVzZXJcbiAgICAgKiBtYW5pcHVsYXRlcyB0aGUgYXNwZWN0bW9kZSBzZXR0aW5ncyBhbmQgdGhlIGZ1bGxMYXlvdXQgaXMgdXAtdG8tZGF0ZS5cbiAgICAgKi9cbiAgICBmdWxsU2NlbmVMYXlvdXQuYXNwZWN0cmF0aW8ueCA9IHNjZW5lTGF5b3V0LmFzcGVjdHJhdGlvLnggPSBhc3BlY3RSYXRpb1swXTtcbiAgICBmdWxsU2NlbmVMYXlvdXQuYXNwZWN0cmF0aW8ueSA9IHNjZW5lTGF5b3V0LmFzcGVjdHJhdGlvLnkgPSBhc3BlY3RSYXRpb1sxXTtcbiAgICBmdWxsU2NlbmVMYXlvdXQuYXNwZWN0cmF0aW8ueiA9IHNjZW5lTGF5b3V0LmFzcGVjdHJhdGlvLnogPSBhc3BlY3RSYXRpb1syXTtcblxuICAgIC8qXG4gICAgICogRmluYWxseSBhc3NpZ24gdGhlIGNvbXB1dGVkIGFzcGVjcmF0aW8gdG8gdGhlIGdscGxvdCBtb2R1bGUuIFRoaXMgd2lsbCBoYXZlIGFuIGVmZmVjdFxuICAgICAqIG9uIHRoZSBuZXh0IHJlbmRlciBjeWNsZS5cbiAgICAgKi9cbiAgICB0aGlzLmdscGxvdC5hc3BlY3QgPSBhc3BlY3RSYXRpbztcblxuXG4gICAgLy8gVXBkYXRlIGZyYW1lIHBvc2l0aW9uIGZvciBtdWx0aSBwbG90c1xuICAgIHZhciBkb21haW4gPSBmdWxsU2NlbmVMYXlvdXQuZG9tYWluIHx8IG51bGw7XG4gICAgdmFyIHNpemUgPSBmdWxsTGF5b3V0Ll9zaXplIHx8IG51bGw7XG5cbiAgICBpZihkb21haW4gJiYgc2l6ZSkge1xuICAgICAgICB2YXIgY29udGFpbmVyU3R5bGUgPSB0aGlzLmNvbnRhaW5lci5zdHlsZTtcbiAgICAgICAgY29udGFpbmVyU3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgICBjb250YWluZXJTdHlsZS5sZWZ0ID0gKHNpemUubCArIGRvbWFpbi54WzBdICogc2l6ZS53KSArICdweCc7XG4gICAgICAgIGNvbnRhaW5lclN0eWxlLnRvcCA9IChzaXplLnQgKyAoMSAtIGRvbWFpbi55WzFdKSAqIHNpemUuaCkgKyAncHgnO1xuICAgICAgICBjb250YWluZXJTdHlsZS53aWR0aCA9IChzaXplLncgKiAoZG9tYWluLnhbMV0gLSBkb21haW4ueFswXSkpICsgJ3B4JztcbiAgICAgICAgY29udGFpbmVyU3R5bGUuaGVpZ2h0ID0gKHNpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKSkgKyAncHgnO1xuICAgIH1cblxuICAgIC8vIGZvcmNlIHJlZHJhdyBzbyB0aGF0IHByb21pc2UgaXMgcmV0dXJuZWQgd2hlbiByZW5kZXJpbmcgaXMgY29tcGxldGVkXG4gICAgdGhpcy5nbHBsb3QucmVkcmF3KCk7XG59O1xuXG5wcm90by5kZXN0cm95ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYoIXRoaXMuZ2xwbG90KSByZXR1cm47XG5cbiAgICB0aGlzLmNhbWVyYS5tb3VzZUxpc3RlbmVyLmVuYWJsZWQgPSBmYWxzZTtcbiAgICB0aGlzLmNvbnRhaW5lci5yZW1vdmVFdmVudExpc3RlbmVyKCd3aGVlbCcsIHRoaXMuY2FtZXJhLndoZWVsTGlzdGVuZXIpO1xuICAgIHRoaXMuY2FtZXJhID0gdGhpcy5nbHBsb3QuY2FtZXJhID0gbnVsbDtcbiAgICB0aGlzLmdscGxvdC5kaXNwb3NlKCk7XG4gICAgdGhpcy5jb250YWluZXIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLmNvbnRhaW5lcik7XG4gICAgdGhpcy5nbHBsb3QgPSBudWxsO1xufTtcblxuLy8gZ2V0T3JiaXRDYW1lcmEgOjogcGxvdGx5X2Nvb3JkcyAtPiBvcmJpdF9jYW1lcmFfY29vcmRzXG4vLyBpbnZlcnNlIG9mIGdldExheW91dENhbWVyYVxuZnVuY3Rpb24gZ2V0T3JiaXRDYW1lcmEoY2FtZXJhKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgW2NhbWVyYS5leWUueCwgY2FtZXJhLmV5ZS55LCBjYW1lcmEuZXllLnpdLFxuICAgICAgICBbY2FtZXJhLmNlbnRlci54LCBjYW1lcmEuY2VudGVyLnksIGNhbWVyYS5jZW50ZXIuel0sXG4gICAgICAgIFtjYW1lcmEudXAueCwgY2FtZXJhLnVwLnksIGNhbWVyYS51cC56XVxuICAgIF07XG59XG5cbi8vIGdldExheW91dENhbWVyYSA6OiBvcmJpdF9jYW1lcmFfY29vcmRzIC0+IHBsb3RseV9jb29yZHNcbi8vIGludmVyc2Ugb2YgZ2V0T3JiaXRDYW1lcmFcbmZ1bmN0aW9uIGdldExheW91dENhbWVyYShjYW1lcmEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB1cDoge3g6IGNhbWVyYS51cFswXSwgeTogY2FtZXJhLnVwWzFdLCB6OiBjYW1lcmEudXBbMl19LFxuICAgICAgICBjZW50ZXI6IHt4OiBjYW1lcmEuY2VudGVyWzBdLCB5OiBjYW1lcmEuY2VudGVyWzFdLCB6OiBjYW1lcmEuY2VudGVyWzJdfSxcbiAgICAgICAgZXllOiB7eDogY2FtZXJhLmV5ZVswXSwgeTogY2FtZXJhLmV5ZVsxXSwgejogY2FtZXJhLmV5ZVsyXX0sXG4gICAgICAgIHByb2plY3Rpb246IHt0eXBlOiAoY2FtZXJhLl9vcnRobyA9PT0gdHJ1ZSkgPyAnb3J0aG9ncmFwaGljJyA6ICdwZXJzcGVjdGl2ZSd9XG4gICAgfTtcbn1cblxuLy8gZ2V0IGNhbWVyYSBwb3NpdGlvbiBpbiBwbG90bHkgY29vcmRzIGZyb20gJ29yYml0LWNhbWVyYScgY29vcmRzXG5wcm90by5nZXRDYW1lcmEgPSBmdW5jdGlvbiBnZXRDYW1lcmEoKSB7XG4gICAgdGhpcy5nbHBsb3QuY2FtZXJhLnZpZXcucmVjYWxjTWF0cml4KHRoaXMuY2FtZXJhLnZpZXcubGFzdFQoKSk7XG4gICAgcmV0dXJuIGdldExheW91dENhbWVyYSh0aGlzLmdscGxvdC5jYW1lcmEpO1xufTtcblxuLy8gc2V0IGNhbWVyYSBwb3NpdGlvbiB3aXRoIGEgc2V0IG9mIHBsb3RseSBjb29yZHNcbnByb3RvLnNldENhbWVyYSA9IGZ1bmN0aW9uIHNldENhbWVyYShjYW1lcmFEYXRhKSB7XG4gICAgdGhpcy5nbHBsb3QuY2FtZXJhLmxvb2tBdC5hcHBseSh0aGlzLCBnZXRPcmJpdENhbWVyYShjYW1lcmFEYXRhKSk7XG5cbiAgICB2YXIgbmV3T3J0aG8gPSAoY2FtZXJhRGF0YS5wcm9qZWN0aW9uLnR5cGUgPT09ICdvcnRob2dyYXBoaWMnKTtcbiAgICB2YXIgb2xkT3J0aG8gPSB0aGlzLmdscGxvdC5jYW1lcmEuX29ydGhvO1xuXG4gICAgaWYobmV3T3J0aG8gIT09IG9sZE9ydGhvKSB7XG4gICAgICAgIHRoaXMuZ2xwbG90LnJlZHJhdygpO1xuXG4gICAgICAgIHZhciBwaXhlbFJhdGlvID0gdGhpcy5nbHBsb3QucGl4ZWxSYXRpbztcblxuICAgICAgICB2YXIgUkdCQSA9IHRoaXMuZ2xwbG90LmNsZWFyQ29sb3I7XG4gICAgICAgIHRoaXMuZ2xwbG90LmdsLmNsZWFyQ29sb3IoXG4gICAgICAgICAgICBSR0JBWzBdLCBSR0JBWzFdLCBSR0JBWzJdLCBSR0JBWzNdXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZ2xwbG90LmdsLmNsZWFyKFxuICAgICAgICAgICAgdGhpcy5nbHBsb3QuZ2wuREVQVEhfQlVGRkVSX0JJVCB8XG4gICAgICAgICAgICB0aGlzLmdscGxvdC5nbC5DT0xPUl9CVUZGRVJfQklUXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5nbHBsb3QuZGlzcG9zZSgpO1xuXG4gICAgICAgIGluaXRpYWxpemVHTFBsb3QodGhpcywgcGl4ZWxSYXRpbyk7XG4gICAgICAgIHRoaXMuZ2xwbG90LmNhbWVyYS5fb3J0aG8gPSBuZXdPcnRobztcbiAgICB9XG59O1xuXG4vLyBzYXZlIGNhbWVyYSB0byB1c2VyIGxheW91dCAoaS5lLiBnZC5sYXlvdXQpXG5wcm90by5zYXZlQ2FtZXJhID0gZnVuY3Rpb24gc2F2ZUNhbWVyYShsYXlvdXQpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IHRoaXMuZnVsbExheW91dDtcbiAgICB2YXIgY2FtZXJhRGF0YSA9IHRoaXMuZ2V0Q2FtZXJhKCk7XG4gICAgdmFyIGNhbWVyYU5lc3RlZFByb3AgPSBMaWIubmVzdGVkUHJvcGVydHkobGF5b3V0LCB0aGlzLmlkICsgJy5jYW1lcmEnKTtcbiAgICB2YXIgY2FtZXJhRGF0YUxhc3RTYXZlID0gY2FtZXJhTmVzdGVkUHJvcC5nZXQoKTtcbiAgICB2YXIgaGFzQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gc2FtZSh4LCB5LCBpLCBqKSB7XG4gICAgICAgIHZhciB2ZWN0b3JzID0gWyd1cCcsICdjZW50ZXInLCAnZXllJ107XG4gICAgICAgIHZhciBjb21wb25lbnRzID0gWyd4JywgJ3knLCAneiddO1xuICAgICAgICByZXR1cm4geVt2ZWN0b3JzW2ldXSAmJiAoeFt2ZWN0b3JzW2ldXVtjb21wb25lbnRzW2pdXSA9PT0geVt2ZWN0b3JzW2ldXVtjb21wb25lbnRzW2pdXSk7XG4gICAgfVxuXG4gICAgaWYoY2FtZXJhRGF0YUxhc3RTYXZlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaGFzQ2hhbmdlZCA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IDM7IGorKykge1xuICAgICAgICAgICAgICAgIGlmKCFzYW1lKGNhbWVyYURhdGEsIGNhbWVyYURhdGFMYXN0U2F2ZSwgaSwgaikpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFjYW1lcmFEYXRhTGFzdFNhdmUucHJvamVjdGlvbiB8fCAoXG4gICAgICAgICAgICBjYW1lcmFEYXRhLnByb2plY3Rpb24gJiZcbiAgICAgICAgICAgIGNhbWVyYURhdGEucHJvamVjdGlvbi50eXBlICE9PSBjYW1lcmFEYXRhTGFzdFNhdmUucHJvamVjdGlvbi50eXBlKSkge1xuICAgICAgICAgICAgaGFzQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihoYXNDaGFuZ2VkKSB7XG4gICAgICAgIHZhciBwcmVHVUkgPSB7fTtcbiAgICAgICAgcHJlR1VJW3RoaXMuaWQgKyAnLmNhbWVyYSddID0gY2FtZXJhRGF0YUxhc3RTYXZlO1xuICAgICAgICBSZWdpc3RyeS5jYWxsKCdfc3RvcmVEaXJlY3RHVUlFZGl0JywgbGF5b3V0LCBmdWxsTGF5b3V0Ll9wcmVHVUksIHByZUdVSSk7XG5cbiAgICAgICAgY2FtZXJhTmVzdGVkUHJvcC5zZXQoY2FtZXJhRGF0YSk7XG5cbiAgICAgICAgdmFyIGNhbWVyYUZ1bGxOUCA9IExpYi5uZXN0ZWRQcm9wZXJ0eShmdWxsTGF5b3V0LCB0aGlzLmlkICsgJy5jYW1lcmEnKTtcbiAgICAgICAgY2FtZXJhRnVsbE5QLnNldChjYW1lcmFEYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaGFzQ2hhbmdlZDtcbn07XG5cbnByb3RvLnVwZGF0ZUZ4ID0gZnVuY3Rpb24oZHJhZ21vZGUsIGhvdmVybW9kZSkge1xuICAgIHZhciBjYW1lcmEgPSB0aGlzLmNhbWVyYTtcbiAgICBpZihjYW1lcmEpIHtcbiAgICAgICAgLy8gcm90YXRlIGFuZCBvcmJpdGFsIGFyZSBzeW5vbnltb3VzXG4gICAgICAgIGlmKGRyYWdtb2RlID09PSAnb3JiaXQnKSB7XG4gICAgICAgICAgICBjYW1lcmEubW9kZSA9ICdvcmJpdCc7XG4gICAgICAgICAgICBjYW1lcmEua2V5QmluZGluZ01vZGUgPSAncm90YXRlJztcbiAgICAgICAgfSBlbHNlIGlmKGRyYWdtb2RlID09PSAndHVybnRhYmxlJykge1xuICAgICAgICAgICAgY2FtZXJhLnVwID0gWzAsIDAsIDFdO1xuICAgICAgICAgICAgY2FtZXJhLm1vZGUgPSAndHVybnRhYmxlJztcbiAgICAgICAgICAgIGNhbWVyYS5rZXlCaW5kaW5nTW9kZSA9ICdyb3RhdGUnO1xuXG4gICAgICAgICAgICAvLyBUaGUgc2V0dGVyIGZvciBjYW1lcmEubW9kZSBhbmltYXRlcyB0aGUgdHJhbnNpdGlvbiB0byB6LXVwLFxuICAgICAgICAgICAgLy8gYnV0IG9ubHkgaWYgd2UgKmRvbid0KiBleHBsaWNpdGx5IHNldCB6LXVwIGVhcmxpZXIgdmlhIHRoZVxuICAgICAgICAgICAgLy8gcmVsYXlvdXQuIFNvIHB1c2ggYHVwYCBiYWNrIHRvIGxheW91dCAmIGZ1bGxMYXlvdXQgbWFudWFsbHkgbm93LlxuICAgICAgICAgICAgdmFyIGdkID0gdGhpcy5ncmFwaERpdjtcbiAgICAgICAgICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgICAgICB2YXIgZnVsbENhbWVyYSA9IHRoaXMuZnVsbFNjZW5lTGF5b3V0LmNhbWVyYTtcbiAgICAgICAgICAgIHZhciB4ID0gZnVsbENhbWVyYS51cC54O1xuICAgICAgICAgICAgdmFyIHkgPSBmdWxsQ2FtZXJhLnVwLnk7XG4gICAgICAgICAgICB2YXIgeiA9IGZ1bGxDYW1lcmEudXAuejtcbiAgICAgICAgICAgIC8vIG9ubHkgcHVzaCBgdXBgIGJhY2sgdG8gKGZ1bGwpbGF5b3V0IGlmIGl0J3MgZ29pbmcgdG8gY2hhbmdlXG4gICAgICAgICAgICBpZih6IC8gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkgKyB6ICogeikgPCAwLjk5OSkge1xuICAgICAgICAgICAgICAgIHZhciBhdHRyID0gdGhpcy5pZCArICcuY2FtZXJhLnVwJztcbiAgICAgICAgICAgICAgICB2YXIgelVwID0ge3g6IDAsIHk6IDAsIHo6IDF9O1xuICAgICAgICAgICAgICAgIHZhciBlZGl0cyA9IHt9O1xuICAgICAgICAgICAgICAgIGVkaXRzW2F0dHJdID0gelVwO1xuICAgICAgICAgICAgICAgIHZhciBsYXlvdXQgPSBnZC5sYXlvdXQ7XG4gICAgICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX3N0b3JlRGlyZWN0R1VJRWRpdCcsIGxheW91dCwgZnVsbExheW91dC5fcHJlR1VJLCBlZGl0cyk7XG4gICAgICAgICAgICAgICAgZnVsbENhbWVyYS51cCA9IHpVcDtcbiAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkobGF5b3V0LCBhdHRyKS5zZXQoelVwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG5vbmUgcm90YXRpb24gbW9kZXMgW3BhbiBvciB6b29tXVxuICAgICAgICAgICAgY2FtZXJhLmtleUJpbmRpbmdNb2RlID0gZHJhZ21vZGU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0byBwdXQgZHJhZ21vZGUgYW5kIGhvdmVybW9kZSBvbiB0aGUgc2FtZSBncm91bmRzIGZyb20gcmVsYXlvdXRcbiAgICB0aGlzLmZ1bGxTY2VuZUxheW91dC5ob3Zlcm1vZGUgPSBob3Zlcm1vZGU7XG59O1xuXG5wcm90by50b0ltYWdlID0gZnVuY3Rpb24oZm9ybWF0KSB7XG4gICAgaWYoIWZvcm1hdCkgZm9ybWF0ID0gJ3BuZyc7XG5cbiAgICBpZih0aGlzLnN0YXRpY01vZGUpIHRoaXMuY29udGFpbmVyLmFwcGVuZENoaWxkKFNUQVRJQ19DQU5WQVMpO1xuXG4gICAgLy8gRm9yY2UgcmVkcmF3XG4gICAgdGhpcy5nbHBsb3QucmVkcmF3KCk7XG5cbiAgICAvLyBHcmFiIGNvbnRleHQgYW5kIHlhbmsgb3V0IHBpeGVsc1xuICAgIHZhciBnbCA9IHRoaXMuZ2xwbG90LmdsO1xuICAgIHZhciB3ID0gZ2wuZHJhd2luZ0J1ZmZlcldpZHRoO1xuICAgIHZhciBoID0gZ2wuZHJhd2luZ0J1ZmZlckhlaWdodDtcblxuICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgbnVsbCk7XG5cbiAgICB2YXIgcGl4ZWxzID0gbmV3IFVpbnQ4QXJyYXkodyAqIGggKiA0KTtcbiAgICBnbC5yZWFkUGl4ZWxzKDAsIDAsIHcsIGgsIGdsLlJHQkEsIGdsLlVOU0lHTkVEX0JZVEUsIHBpeGVscyk7XG5cbiAgICAvLyBGbGlwIHBpeGVsc1xuICAgIGZvcih2YXIgaiA9IDAsIGsgPSBoIC0gMTsgaiA8IGs7ICsraiwgLS1rKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB3OyArK2kpIHtcbiAgICAgICAgICAgIGZvcih2YXIgbCA9IDA7IGwgPCA0OyArK2wpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG1wID0gcGl4ZWxzWzQgKiAodyAqIGogKyBpKSArIGxdO1xuICAgICAgICAgICAgICAgIHBpeGVsc1s0ICogKHcgKiBqICsgaSkgKyBsXSA9IHBpeGVsc1s0ICogKHcgKiBrICsgaSkgKyBsXTtcbiAgICAgICAgICAgICAgICBwaXhlbHNbNCAqICh3ICogayArIGkpICsgbF0gPSB0bXA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgY2FudmFzLndpZHRoID0gdztcbiAgICBjYW52YXMuaGVpZ2h0ID0gaDtcbiAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIHZhciBpbWFnZURhdGEgPSBjb250ZXh0LmNyZWF0ZUltYWdlRGF0YSh3LCBoKTtcbiAgICBpbWFnZURhdGEuZGF0YS5zZXQocGl4ZWxzKTtcbiAgICBjb250ZXh0LnB1dEltYWdlRGF0YShpbWFnZURhdGEsIDAsIDApO1xuXG4gICAgdmFyIGRhdGFVUkw7XG5cbiAgICBzd2l0Y2goZm9ybWF0KSB7XG4gICAgICAgIGNhc2UgJ2pwZWcnOlxuICAgICAgICAgICAgZGF0YVVSTCA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL2pwZWcnKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd3ZWJwJzpcbiAgICAgICAgICAgIGRhdGFVUkwgPSBjYW52YXMudG9EYXRhVVJMKCdpbWFnZS93ZWJwJyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGRhdGFVUkwgPSBjYW52YXMudG9EYXRhVVJMKCdpbWFnZS9wbmcnKTtcbiAgICB9XG5cbiAgICBpZih0aGlzLnN0YXRpY01vZGUpIHRoaXMuY29udGFpbmVyLnJlbW92ZUNoaWxkKFNUQVRJQ19DQU5WQVMpO1xuXG4gICAgcmV0dXJuIGRhdGFVUkw7XG59O1xuXG5wcm90by5zZXRDb252ZXJ0ID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICB2YXIgYXggPSB0aGlzLmZ1bGxTY2VuZUxheW91dFtheGlzUHJvcGVydGllc1tpXV07XG4gICAgICAgIEF4ZXMuc2V0Q29udmVydChheCwgdGhpcy5mdWxsTGF5b3V0KTtcbiAgICAgICAgYXguc2V0U2NhbGUgPSBMaWIubm9vcDtcbiAgICB9XG59O1xuXG5wcm90by5tYWtlNHRoRGltZW5zaW9uID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgZ2QgPSBfdGhpcy5ncmFwaERpdjtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgLy8gbW9jayBheGlzIGZvciBob3ZlciBmb3JtYXR0aW5nXG4gICAgX3RoaXMubW9ja0F4aXMgPSB7XG4gICAgICAgIHR5cGU6ICdsaW5lYXInLFxuICAgICAgICBzaG93ZXhwb25lbnQ6ICdhbGwnLFxuICAgICAgICBleHBvbmVudGZvcm1hdDogJ0InXG4gICAgfTtcbiAgICBBeGVzLnNldENvbnZlcnQoX3RoaXMubW9ja0F4aXMsIGZ1bGxMYXlvdXQpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBTY2VuZTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL3Nob3dfbm9fd2ViZ2xfbXNnXCI6NzQwLFwiLi4vLi4vbGliL3N0cjJyZ2JhcnJheVwiOjc0MixcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2xheW91dC9jb252ZXJ0XCI6ODExLFwiLi9sYXlvdXQvc3Bpa2VzXCI6ODE0LFwiLi9sYXlvdXQvdGlja19tYXJrc1wiOjgxNSxcIi4vcHJvamVjdFwiOjgxNixcImdsLXBsb3QzZFwiOjI5MCxcImhhcy1wYXNzaXZlLWV2ZW50c1wiOjQxMSxcIndlYmdsLWNvbnRleHRcIjo1NTZ9XSw4MTg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHppcDMoeCwgeSwgeiwgbGVuKSB7XG4gICAgbGVuID0gbGVuIHx8IHgubGVuZ3RoO1xuXG4gICAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheShsZW4pO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICByZXN1bHRbaV0gPSBbeFtpXSwgeVtpXSwgeltpXV07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59O1xuXG59LHt9XSw4MTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZm9udEF0dHJzID0gX2RlcmVxXygnLi9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBhbmltYXRpb25BdHRycyA9IF9kZXJlcV8oJy4vYW5pbWF0aW9uX2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gX2RlcmVxXygnLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzJyk7XG52YXIgcGFkQXR0cnMgPSBfZGVyZXFfKCcuL3BhZF9hdHRyaWJ1dGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG52YXIgZ2xvYmFsRm9udCA9IGZvbnRBdHRycyh7XG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICBcbn0pO1xuZ2xvYmFsRm9udC5mYW1pbHkuZGZsdCA9ICdcIk9wZW4gU2Fuc1wiLCB2ZXJkYW5hLCBhcmlhbCwgc2Fucy1zZXJpZic7XG5nbG9iYWxGb250LnNpemUuZGZsdCA9IDEyO1xuZ2xvYmFsRm9udC5jb2xvci5kZmx0ID0gY29sb3JBdHRycy5kZWZhdWx0TGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZm9udDogZ2xvYmFsRm9udCxcbiAgICB0aXRsZToge1xuICAgICAgICB0ZXh0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdsYXlvdXRzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnbGF5b3V0c3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICB4cmVmOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICBkZmx0OiAnY29udGFpbmVyJyxcbiAgICAgICAgICAgIHZhbHVlczogWydjb250YWluZXInLCAncGFwZXInXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdsYXlvdXRzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgeXJlZjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgZGZsdDogJ2NvbnRhaW5lcicsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnY29udGFpbmVyJywgJ3BhcGVyJ10sXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnbGF5b3V0c3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxLFxuICAgICAgICAgICAgZGZsdDogMC41LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2xheW91dHN0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMSxcbiAgICAgICAgICAgIGRmbHQ6ICdhdXRvJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdsYXlvdXRzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgeGFuY2hvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAnbGVmdCcsICdjZW50ZXInLCAncmlnaHQnXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdsYXlvdXRzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgeWFuY2hvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2F1dG8nLCAndG9wJywgJ21pZGRsZScsICdib3R0b20nXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdsYXlvdXRzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgcGFkOiBleHRlbmRGbGF0KHBhZEF0dHJzKHtlZGl0VHlwZTogJ2xheW91dHN0eWxlJ30pLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiAnbGF5b3V0c3R5bGUnXG4gICAgfSxcbiAgICBhdXRvc2l6ZToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgLy8gYXV0b3NpemUsIHdpZHRoLCBhbmQgaGVpZ2h0IGdldCBzcGVjaWFsIGVkaXRUeXBlIHRyZWF0bWVudCBpbiBfcmVsYXlvdXRcbiAgICAgICAgLy8gc28gd2UgY2FuIGhhbmRsZSBub29wIHJlc2l6ZXMgbW9yZSBlZmZpY2llbnRseVxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAxMCxcbiAgICAgICAgZGZsdDogNzAwLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhlaWdodDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMTAsXG4gICAgICAgIGRmbHQ6IDQ1MCxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtYXJnaW46IHtcbiAgICAgICAgbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDgwLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICByOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogODAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAxMDAsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGI6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiA4MCxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgcGFkOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgYXV0b2V4cGFuZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICBwYXBlcl9iZ2NvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmJhY2tncm91bmQsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcGxvdF9iZ2NvbG9yOiB7XG4gICAgICAgIC8vIGRlZmluZWQgaGVyZSwgYnV0IHNldCBpbiBjYXJ0ZXNpYW4uc3VwcGx5TGF5b3V0RGVmYXVsdHNcbiAgICAgICAgLy8gYmVjYXVzZSBpdCBuZWVkcyB0byBrbm93IGlmIHRoZXJlIGFyZSAoMkQpIGF4ZXMgb3Igbm90XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmJhY2tncm91bmQsXG4gICAgICAgIGVkaXRUeXBlOiAnbGF5b3V0c3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNlcGFyYXRvcnM6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhpZGVzb3VyY2VzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dsZWdlbmQ6IHtcbiAgICAgICAgLy8gaGFuZGxlZCBpbiBsZWdlbmQuc3VwcGx5TGF5b3V0RGVmYXVsdHNcbiAgICAgICAgLy8gYnV0IGluY2x1ZGVkIGhlcmUgYmVjYXVzZSBpdCdzIG5vdCBpbiB0aGUgbGVnZW5kIG9iamVjdFxuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2xlZ2VuZCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgY29sb3J3YXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9ybGlzdCcsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdHMsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRhdGFyZXZpc2lvbjoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdWlyZXZpc2lvbjoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdHJldmlzaW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzZWxlY3Rpb25yZXZpc2lvbjoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG1vZGViYXI6IHtcbiAgICAgICAgb3JpZW50YXRpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWyd2JywgJ2gnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdoJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdtb2RlYmFyJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBiZ2NvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ21vZGViYXInLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ21vZGViYXInLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGFjdGl2ZWNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ21vZGViYXInLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHVpcmV2aXNpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnbW9kZWJhcidcbiAgICB9LFxuXG4gICAgbWV0YToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0cmFuc2l0aW9uOiBleHRlbmRGbGF0KHt9LCBhbmltYXRpb25BdHRycy50cmFuc2l0aW9uLCB7XG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnXG4gICAgfSksXG4gICAgX2RlcHJlY2F0ZWQ6IHtcbiAgICAgICAgdGl0bGU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2xheW91dHN0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB0aXRsZWZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgICAgICBlZGl0VHlwZTogJ2xheW91dHN0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9KVxuICAgIH1cbn07XG5cbn0se1wiLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzXCI6NTkyLFwiLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4vYW5pbWF0aW9uX2F0dHJpYnV0ZXNcIjo3NjIsXCIuL2ZvbnRfYXR0cmlidXRlc1wiOjc5MyxcIi4vcGFkX2F0dHJpYnV0ZXNcIjo4Mjd9XSw4MjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgcmVxdWlyZWRWZXJzaW9uID0gJzEuMS4xJztcblxudmFyIHN0eWxlc05vbk1hcGJveCA9IHtcbiAgICAnb3Blbi1zdHJlZXQtbWFwJzoge1xuICAgICAgICBpZDogJ29zbScsXG4gICAgICAgIHZlcnNpb246IDgsXG4gICAgICAgIHNvdXJjZXM6IHtcbiAgICAgICAgICAgICdwbG90bHktb3NtLXRpbGVzJzoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdyYXN0ZXInLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0aW9uOiAnPGEgaHJlZj1cImh0dHA6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvYWJvdXQvXCIgdGFyZ2V0PVwiX2JsYW5rXCI+wqkgT3BlblN0cmVldE1hcDwvYT4nLFxuICAgICAgICAgICAgICAgIHRpbGVzOiBbXG4gICAgICAgICAgICAgICAgICAgICdodHRwczovL2EudGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLFxuICAgICAgICAgICAgICAgICAgICAnaHR0cHM6Ly9iLnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nJ1xuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgdGlsZVNpemU6IDI1NlxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXllcnM6IFt7XG4gICAgICAgICAgICBpZDogJ3Bsb3RseS1vc20tdGlsZXMnLFxuICAgICAgICAgICAgdHlwZTogJ3Jhc3RlcicsXG4gICAgICAgICAgICBzb3VyY2U6ICdwbG90bHktb3NtLXRpbGVzJyxcbiAgICAgICAgICAgIG1pbnpvb206IDAsXG4gICAgICAgICAgICBtYXh6b29tOiAyMlxuICAgICAgICB9XVxuICAgIH0sXG4gICAgJ3doaXRlLWJnJzoge1xuICAgICAgICBpZDogJ3doaXRlLWJnJyxcbiAgICAgICAgdmVyc2lvbjogOCxcbiAgICAgICAgc291cmNlczoge30sXG4gICAgICAgIGxheWVyczogW3tcbiAgICAgICAgICAgIGlkOiAnd2hpdGUtYmcnLFxuICAgICAgICAgICAgdHlwZTogJ2JhY2tncm91bmQnLFxuICAgICAgICAgICAgcGFpbnQ6IHsnYmFja2dyb3VuZC1jb2xvcic6ICcjRkZGRkZGJ30sXG4gICAgICAgICAgICBtaW56b29tOiAwLFxuICAgICAgICAgICAgbWF4em9vbTogMjJcbiAgICAgICAgfV1cbiAgICB9LFxuICAgICdjYXJ0by1wb3NpdHJvbic6IHtcbiAgICAgICAgaWQ6ICdjYXJ0by1wb3NpdHJvbicsXG4gICAgICAgIHZlcnNpb246IDgsXG4gICAgICAgIHNvdXJjZXM6IHtcbiAgICAgICAgICAgICdwbG90bHktY2FydG8tcG9zaXRyb24nOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ3Jhc3RlcicsXG4gICAgICAgICAgICAgICAgYXR0cmlidXRpb246ICc8YSBocmVmPVwiaHR0cHM6Ly9jYXJ0by5jb20vXCIgdGFyZ2V0PVwiX2JsYW5rXCI+wqkgQ0FSVE88L2E+JyxcbiAgICAgICAgICAgICAgICB0aWxlczogWydodHRwczovL2NhcnRvZGItYmFzZW1hcHMtYy5nbG9iYWwuc3NsLmZhc3RseS5uZXQvbGlnaHRfYWxsL3t6fS97eH0ve3l9LnBuZyddLFxuICAgICAgICAgICAgICAgIHRpbGVTaXplOiAyNTZcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGF5ZXJzOiBbe1xuICAgICAgICAgICAgaWQ6ICdwbG90bHktY2FydG8tcG9zaXRyb24nLFxuICAgICAgICAgICAgdHlwZTogJ3Jhc3RlcicsXG4gICAgICAgICAgICBzb3VyY2U6ICdwbG90bHktY2FydG8tcG9zaXRyb24nLFxuICAgICAgICAgICAgbWluem9vbTogMCxcbiAgICAgICAgICAgIG1heHpvb206IDIyXG4gICAgICAgIH1dXG4gICAgfSxcbiAgICAnY2FydG8tZGFya21hdHRlcic6IHtcbiAgICAgICAgaWQ6ICdjYXJ0by1kYXJrbWF0dGVyJyxcbiAgICAgICAgdmVyc2lvbjogOCxcbiAgICAgICAgc291cmNlczoge1xuICAgICAgICAgICAgJ3Bsb3RseS1jYXJ0by1kYXJrbWF0dGVyJzoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdyYXN0ZXInLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0aW9uOiAnPGEgaHJlZj1cImh0dHBzOi8vY2FydG8uY29tL1wiIHRhcmdldD1cIl9ibGFua1wiPsKpIENBUlRPPC9hPicsXG4gICAgICAgICAgICAgICAgdGlsZXM6IFsnaHR0cHM6Ly9jYXJ0b2RiLWJhc2VtYXBzLWMuZ2xvYmFsLnNzbC5mYXN0bHkubmV0L2RhcmtfYWxsL3t6fS97eH0ve3l9LnBuZyddLFxuICAgICAgICAgICAgICAgIHRpbGVTaXplOiAyNTZcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGF5ZXJzOiBbe1xuICAgICAgICAgICAgaWQ6ICdwbG90bHktY2FydG8tZGFya21hdHRlcicsXG4gICAgICAgICAgICB0eXBlOiAncmFzdGVyJyxcbiAgICAgICAgICAgIHNvdXJjZTogJ3Bsb3RseS1jYXJ0by1kYXJrbWF0dGVyJyxcbiAgICAgICAgICAgIG1pbnpvb206IDAsXG4gICAgICAgICAgICBtYXh6b29tOiAyMlxuICAgICAgICB9XVxuICAgIH0sXG4gICAgJ3N0YW1lbi10ZXJyYWluJzoge1xuICAgICAgICBpZDogJ3N0YW1lbi10ZXJyYWluJyxcbiAgICAgICAgdmVyc2lvbjogOCxcbiAgICAgICAgc291cmNlczoge1xuICAgICAgICAgICAgJ3Bsb3RseS1zdGFtZW4tdGVycmFpbic6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAncmFzdGVyJyxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGlvbjogJ01hcCB0aWxlcyBieSA8YSBocmVmPVwiaHR0cDovL3N0YW1lbi5jb21cIj5TdGFtZW4gRGVzaWduPC9hPiwgdW5kZXIgPGEgaHJlZj1cImh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LzMuMFwiPkNDIEJZIDMuMDwvYT4gfCBEYXRhIGJ5IDxhIGhyZWY9XCJodHRwOi8vb3BlbnN0cmVldG1hcC5vcmdcIj5PcGVuU3RyZWV0TWFwPC9hPiwgdW5kZXIgPGEgaHJlZj1cImh0dHA6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvY29weXJpZ2h0XCI+T0RiTDwvYT4uJyxcbiAgICAgICAgICAgICAgICB0aWxlczogWydodHRwczovL3N0YW1lbi10aWxlcy5hLnNzbC5mYXN0bHkubmV0L3RlcnJhaW4ve3p9L3t4fS97eX0ucG5nJ10sXG4gICAgICAgICAgICAgICAgdGlsZVNpemU6IDI1NlxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXllcnM6IFt7XG4gICAgICAgICAgICBpZDogJ3Bsb3RseS1zdGFtZW4tdGVycmFpbicsXG4gICAgICAgICAgICB0eXBlOiAncmFzdGVyJyxcbiAgICAgICAgICAgIHNvdXJjZTogJ3Bsb3RseS1zdGFtZW4tdGVycmFpbicsXG4gICAgICAgICAgICBtaW56b29tOiAwLFxuICAgICAgICAgICAgbWF4em9vbTogMjJcbiAgICAgICAgfV1cbiAgICB9LFxuICAgICdzdGFtZW4tdG9uZXInOiB7XG4gICAgICAgIGlkOiAnc3RhbWVuLXRvbmVyJyxcbiAgICAgICAgdmVyc2lvbjogOCxcbiAgICAgICAgc291cmNlczoge1xuICAgICAgICAgICAgJ3Bsb3RseS1zdGFtZW4tdG9uZXInOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ3Jhc3RlcicsXG4gICAgICAgICAgICAgICAgYXR0cmlidXRpb246ICdNYXAgdGlsZXMgYnkgPGEgaHJlZj1cImh0dHA6Ly9zdGFtZW4uY29tXCI+U3RhbWVuIERlc2lnbjwvYT4sIHVuZGVyIDxhIGhyZWY9XCJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS8zLjBcIj5DQyBCWSAzLjA8L2E+IHwgRGF0YSBieSA8YSBocmVmPVwiaHR0cDovL29wZW5zdHJlZXRtYXAub3JnXCI+T3BlblN0cmVldE1hcDwvYT4sIHVuZGVyIDxhIGhyZWY9XCJodHRwOi8vd3d3Lm9wZW5zdHJlZXRtYXAub3JnL2NvcHlyaWdodFwiPk9EYkw8L2E+LicsXG4gICAgICAgICAgICAgICAgdGlsZXM6IFsnaHR0cHM6Ly9zdGFtZW4tdGlsZXMuYS5zc2wuZmFzdGx5Lm5ldC90b25lci97en0ve3h9L3t5fS5wbmcnXSxcbiAgICAgICAgICAgICAgICB0aWxlU2l6ZTogMjU2XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxheWVyczogW3tcbiAgICAgICAgICAgIGlkOiAncGxvdGx5LXN0YW1lbi10b25lcicsXG4gICAgICAgICAgICB0eXBlOiAncmFzdGVyJyxcbiAgICAgICAgICAgIHNvdXJjZTogJ3Bsb3RseS1zdGFtZW4tdG9uZXInLFxuICAgICAgICAgICAgbWluem9vbTogMCxcbiAgICAgICAgICAgIG1heHpvb206IDIyXG4gICAgICAgIH1dXG4gICAgfSxcbiAgICAnc3RhbWVuLXdhdGVyY29sb3InOiB7XG4gICAgICAgIGlkOiAnc3RhbWVuLXdhdGVyY29sb3InLFxuICAgICAgICB2ZXJzaW9uOiA4LFxuICAgICAgICBzb3VyY2VzOiB7XG4gICAgICAgICAgICAncGxvdGx5LXN0YW1lbi13YXRlcmNvbG9yJzoge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdyYXN0ZXInLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0aW9uOiAnTWFwIHRpbGVzIGJ5IDxhIGhyZWY9XCJodHRwOi8vc3RhbWVuLmNvbVwiPlN0YW1lbiBEZXNpZ248L2E+LCB1bmRlciA8YSBocmVmPVwiaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnkvMy4wXCI+Q0MgQlkgMy4wPC9hPiB8IERhdGEgYnkgPGEgaHJlZj1cImh0dHA6Ly9vcGVuc3RyZWV0bWFwLm9yZ1wiPk9wZW5TdHJlZXRNYXA8L2E+LCB1bmRlciA8YSBocmVmPVwiaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvMy4wXCI+Q0MgQlkgU0E8L2E+LicsXG4gICAgICAgICAgICAgICAgdGlsZXM6IFsnaHR0cHM6Ly9zdGFtZW4tdGlsZXMuYS5zc2wuZmFzdGx5Lm5ldC93YXRlcmNvbG9yL3t6fS97eH0ve3l9LnBuZyddLFxuICAgICAgICAgICAgICAgIHRpbGVTaXplOiAyNTZcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGF5ZXJzOiBbe1xuICAgICAgICAgICAgaWQ6ICdwbG90bHktc3RhbWVuLXdhdGVyY29sb3InLFxuICAgICAgICAgICAgdHlwZTogJ3Jhc3RlcicsXG4gICAgICAgICAgICBzb3VyY2U6ICdwbG90bHktc3RhbWVuLXdhdGVyY29sb3InLFxuICAgICAgICAgICAgbWluem9vbTogMCxcbiAgICAgICAgICAgIG1heHpvb206IDIyXG4gICAgICAgIH1dXG4gICAgfVxufTtcblxudmFyIHN0eWxlVmFsdWVzTm9uTWFwYm94ID0gT2JqZWN0LmtleXMoc3R5bGVzTm9uTWFwYm94KTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgcmVxdWlyZWRWZXJzaW9uOiByZXF1aXJlZFZlcnNpb24sXG5cbiAgICBzdHlsZVVybFByZWZpeDogJ21hcGJveDovL3N0eWxlcy9tYXBib3gvJyxcbiAgICBzdHlsZVVybFN1ZmZpeDogJ3Y5JyxcblxuICAgIHN0eWxlVmFsdWVzTWFwYm94OiBbJ2Jhc2ljJywgJ3N0cmVldHMnLCAnb3V0ZG9vcnMnLCAnbGlnaHQnLCAnZGFyaycsICdzYXRlbGxpdGUnLCAnc2F0ZWxsaXRlLXN0cmVldHMnXSxcbiAgICBzdHlsZVZhbHVlRGZsdDogJ2Jhc2ljJyxcbiAgICBzdHlsZXNOb25NYXBib3g6IHN0eWxlc05vbk1hcGJveCxcbiAgICBzdHlsZVZhbHVlc05vbk1hcGJveDogc3R5bGVWYWx1ZXNOb25NYXBib3gsXG5cbiAgICB0cmFjZUxheWVyUHJlZml4OiAncGxvdGx5LXRyYWNlLWxheWVyLScsXG4gICAgbGF5b3V0TGF5ZXJQcmVmaXg6ICdwbG90bHktbGF5b3V0LWxheWVyLScsXG5cbiAgICB3cm9uZ1ZlcnNpb25FcnJvck1zZzogW1xuICAgICAgICAnWW91ciBjdXN0b20gcGxvdGx5LmpzIGJ1bmRsZSBpcyBub3QgdXNpbmcgdGhlIGNvcnJlY3QgbWFwYm94LWdsIHZlcnNpb24nLFxuICAgICAgICAnUGxlYXNlIGluc3RhbGwgbWFwYm94LWdsQCcgKyByZXF1aXJlZFZlcnNpb24gKyAnLidcbiAgICBdLmpvaW4oJ1xcbicpLFxuXG4gICAgbm9BY2Nlc3NUb2tlbkVycm9yTXNnOiBbXG4gICAgICAgICdNaXNzaW5nIE1hcGJveCBhY2Nlc3MgdG9rZW4uJyxcbiAgICAgICAgJ01hcGJveCB0cmFjZSB0eXBlIHJlcXVpcmUgYSBNYXBib3ggYWNjZXNzIHRva2VuIHRvIGJlIHJlZ2lzdGVyZWQuJyxcbiAgICAgICAgJ0ZvciBleGFtcGxlOicsXG4gICAgICAgICcgIFBsb3RseS5wbG90KGdkLCBkYXRhLCBsYXlvdXQsIHsgbWFwYm94QWNjZXNzVG9rZW46IFxcJ215LWFjY2Vzcy10b2tlblxcJyB9KTsnLFxuICAgICAgICAnTW9yZSBpbmZvIGhlcmU6IGh0dHBzOi8vd3d3Lm1hcGJveC5jb20vaGVscC9kZWZpbmUtYWNjZXNzLXRva2VuLydcbiAgICBdLmpvaW4oJ1xcbicpLFxuXG4gICAgbWlzc2luZ1N0eWxlRXJyb3JNc2c6IFtcbiAgICAgICAgJ05vIHZhbGlkIG1hcGJveCBzdHlsZSBmb3VuZCwgcGxlYXNlIHNldCBgbWFwYm94LnN0eWxlYCB0byBvbmUgb2Y6JyxcbiAgICAgICAgc3R5bGVWYWx1ZXNOb25NYXBib3guam9pbignLCAnKSxcbiAgICAgICAgJ29yIHJlZ2lzdGVyIGEgTWFwYm94IGFjY2VzcyB0b2tlbiB0byB1c2UgYSBNYXBib3gtc2VydmVkIHN0eWxlLidcbiAgICBdLmpvaW4oJ1xcbicpLFxuXG4gICAgbXVsdGlwbGVUb2tlbnNFcnJvck1zZzogW1xuICAgICAgICAnU2V0IG11bHRpcGxlIG1hcGJveCBhY2Nlc3MgdG9rZW4gYWNyb3NzIGRpZmZlcmVudCBtYXBib3ggc3VicGxvdCwnLFxuICAgICAgICAndXNpbmcgZmlyc3QgdG9rZW4gZm91bmQgYXMgbWFwYm94LWdsIGRvZXMgbm90IGFsbG93IG11bHRpcGxlJyArXG4gICAgICAgICdhY2Nlc3MgdG9rZW5zIG9uIHRoZSBzYW1lIHBhZ2UuJ1xuICAgIF0uam9pbignXFxuJyksXG5cbiAgICBtYXBPbkVycm9yTXNnOiAnTWFwYm94IGVycm9yLicsXG5cbiAgICAvLyBNYXBib3ggbG9nbyBmb3Igc3RhdGljIGV4cG9ydFxuICAgIG1hcGJveExvZ286IHtcbiAgICAgICAgcGF0aDA6ICdtIDEwLjUsMS4yNCBjIC01LjExLDAgLTkuMjUsNC4xNSAtOS4yNSw5LjI1IDAsNS4xIDQuMTUsOS4yNSA5LjI1LDkuMjUgNS4xLDAgOS4yNSwtNC4xNSA5LjI1LC05LjI1IDAsLTUuMTEgLTQuMTQsLTkuMjUgLTkuMjUsLTkuMjUgeiBtIDQuMzksMTEuNTMgYyAtMS45MywxLjkzIC00Ljc4LDIuMzEgLTYuNywyLjMxIC0wLjcsMCAtMS40MSwtMC4wNSAtMi4xLC0wLjE2IDAsMCAtMS4wMiwtNS42NCAyLjE0LC04LjgxIDAuODMsLTAuODMgMS45NSwtMS4yOCAzLjEzLC0xLjI4IDEuMjcsMCAyLjQ5LDAuNTEgMy4zOSwxLjQyIDEuODQsMS44NCAxLjg5LDQuNzUgMC4xNCw2LjUyIHonLFxuICAgICAgICBwYXRoMTogJ00gMTAuNSwtMC4wMSBDIDQuNywtMC4wMSAwLDQuNyAwLDEwLjQ5IGMgMCw1Ljc5IDQuNywxMC41IDEwLjUsMTAuNSA1LjgsMCAxMC41LC00LjcgMTAuNSwtMTAuNSBDIDIwLjk5LDQuNyAxNi4zLC0wLjAxIDEwLjUsLTAuMDEgWiBtIDAsMTkuNzUgYyAtNS4xMSwwIC05LjI1LC00LjE1IC05LjI1LC05LjI1IDAsLTUuMSA0LjE0LC05LjI2IDkuMjUsLTkuMjYgNS4xMSwwIDkuMjUsNC4xNSA5LjI1LDkuMjUgMCw1LjEzIC00LjE0LDkuMjYgLTkuMjUsOS4yNiB6JyxcbiAgICAgICAgcGF0aDI6ICdNIDE0Ljc0LDYuMjUgQyAxMi45LDQuNDEgOS45OCw0LjM1IDguMjMsNi4xIDUuMDcsOS4yNyA2LjA5LDE0LjkxIDYuMDksMTQuOTEgYyAwLDAgNS42NCwxLjAyIDguODEsLTIuMTQgQyAxNi42NCwxMSAxNi41OSw4LjA5IDE0Ljc0LDYuMjUgWiBtIC0yLjI3LDQuMDkgLTAuOTEsMS44NyAtMC45LC0xLjg3IC0xLjg2LC0wLjkxIDEuODYsLTAuOSAwLjksLTEuODcgMC45MSwxLjg3IDEuODYsMC45IHonLFxuICAgICAgICBwb2x5Z29uOiAnMTEuNTYsMTIuMjEgMTAuNjYsMTAuMzQgOC44LDkuNDMgMTAuNjYsOC41MyAxMS41Niw2LjY2IDEyLjQ3LDguNTMgMTQuMzMsOS40MyAxMi40NywxMC4zNCdcbiAgICB9LFxuXG4gICAgLy8gYSBzdWJzZXQgb2Ygbm9kZV9tb2R1bGVzL21hcGJveC1nbC9kaXN0L21hcGJveC1nbC5jc3NcbiAgICBzdHlsZVJ1bGVzOiB7XG4gICAgICAgIG1hcDogJ292ZXJmbG93OmhpZGRlbjtwb3NpdGlvbjpyZWxhdGl2ZTsnLFxuICAgICAgICAnbWlzc2luZy1jc3MnOiAnZGlzcGxheTpub25lOycsXG4gICAgICAgICdjYW5hcnknOiAnYmFja2dyb3VuZC1jb2xvcjpzYWxtb247JyxcblxuICAgICAgICAvLyBSZXVzaW5nIENTUyBkaXJlY3RpdmVzIGZyb206IGh0dHBzOi8vYXBpLnRpbGVzLm1hcGJveC5jb20vbWFwYm94LWdsLWpzL3YxLjEuMS9tYXBib3gtZ2wuY3NzXG4gICAgICAgICdjdHJsLWJvdHRvbS1sZWZ0JzogJ3Bvc2l0aW9uOiBhYnNvbHV0ZTsgcG9pbnRlci1ldmVudHM6IG5vbmU7IHotaW5kZXg6IDI7IGJvdHRvbTogMDsgbGVmdDogMDsnLFxuICAgICAgICAnY3RybC1ib3R0b20tcmlnaHQnOiAncG9zaXRpb246IGFic29sdXRlOyBwb2ludGVyLWV2ZW50czogbm9uZTsgei1pbmRleDogMjsgcmlnaHQ6IDA7IGJvdHRvbTogMDsnLFxuICAgICAgICAnY3RybCc6ICdjbGVhcjogYm90aDsgcG9pbnRlci1ldmVudHM6IGF1dG87IHRyYW5zZm9ybTogdHJhbnNsYXRlKDAsIDApOycsXG5cbiAgICAgICAgLy8gQ29tcGFjdCBjdHJsXG4gICAgICAgICdjdHJsLWF0dHJpYi5tYXBib3hnbC1jb21wYWN0IC5tYXBib3hnbC1jdHJsLWF0dHJpYi1pbm5lcic6ICdkaXNwbGF5OiBub25lOycsXG4gICAgICAgICdjdHJsLWF0dHJpYi5tYXBib3hnbC1jb21wYWN0OmhvdmVyIC5tYXBib3hnbC1jdHJsLWF0dHJpYi1pbm5lcic6ICdkaXNwbGF5OiBibG9jazsgbWFyZ2luLXRvcDoycHgnLFxuICAgICAgICAnY3RybC1hdHRyaWIubWFwYm94Z2wtY29tcGFjdDpob3Zlcic6ICdwYWRkaW5nOiAycHggMjRweCAycHggNHB4OyB2aXNpYmlsaXR5OiB2aXNpYmxlOyBtYXJnaW4tdG9wOiA2cHg7JyxcbiAgICAgICAgJ2N0cmwtYXR0cmliLm1hcGJveGdsLWNvbXBhY3Q6OmFmdGVyJzogJ2NvbnRlbnQ6IFwiXCI7IGN1cnNvcjogcG9pbnRlcjsgcG9zaXRpb246IGFic29sdXRlOyBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoXFwnZGF0YTppbWFnZS9zdmcreG1sO2NoYXJzZXQ9dXRmLTgsJTNDc3ZnIHZpZXdCb3g9XCIwIDAgMjAgMjBcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIlM0UgJTNDcGF0aCBmaWxsPVwiJTIzMzMzMzMzXCIgZmlsbC1ydWxlPVwiZXZlbm9kZFwiIGQ9XCJNNCwxMGE2LDYgMCAxLDAgMTIsMGE2LDYgMCAxLDAgLTEyLDAgTTksN2ExLDEgMCAxLDAgMiwwYTEsMSAwIDEsMCAtMiwwIE05LDEwYTEsMSAwIDEsMSAyLDBsMCwzYTEsMSAwIDEsMSAtMiwwXCIvJTNFICUzQy9zdmclM0VcXCcpOyBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSk7IHdpZHRoOiAyNHB4OyBoZWlnaHQ6IDI0cHg7IGJveC1zaXppbmc6IGJvcmRlci1ib3g7IGJvcmRlci1yYWRpdXM6IDEycHg7JyxcbiAgICAgICAgJ2N0cmwtYXR0cmliLm1hcGJveGdsLWNvbXBhY3QnOiAnbWluLWhlaWdodDogMjBweDsgcGFkZGluZzogMDsgbWFyZ2luOiAxMHB4OyBwb3NpdGlvbjogcmVsYXRpdmU7IGJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDNweCAxMnB4IDEycHggM3B4OycsXG4gICAgICAgICdjdHJsLWJvdHRvbS1yaWdodCA+IC5tYXBib3hnbC1jdHJsLWF0dHJpYi5tYXBib3hnbC1jb21wYWN0OjphZnRlcic6ICdib3R0b206IDA7IHJpZ2h0OiAwJyxcbiAgICAgICAgJ2N0cmwtYm90dG9tLWxlZnQgPiAubWFwYm94Z2wtY3RybC1hdHRyaWIubWFwYm94Z2wtY29tcGFjdDo6YWZ0ZXInOiAnYm90dG9tOiAwOyBsZWZ0OiAwJyxcblxuICAgICAgICAnY3RybC1ib3R0b20tbGVmdCAubWFwYm94Z2wtY3RybCc6ICdtYXJnaW46IDAgMCAxMHB4IDEwcHg7IGZsb2F0OiBsZWZ0OycsXG4gICAgICAgICdjdHJsLWJvdHRvbS1yaWdodCAubWFwYm94Z2wtY3RybCc6ICdtYXJnaW46IDAgMTBweCAxMHB4IDA7IGZsb2F0OiByaWdodDsnLFxuXG4gICAgICAgICdjdHJsLWF0dHJpYic6ICdjb2xvcjogcmdiYSgwLCAwLCAwLCAwLjc1KTsgdGV4dC1kZWNvcmF0aW9uOiBub25lOyBmb250LXNpemU6IDEycHgnLFxuICAgICAgICAnY3RybC1hdHRyaWIgYSc6ICdjb2xvcjogcmdiYSgwLCAwLCAwLCAwLjc1KTsgdGV4dC1kZWNvcmF0aW9uOiBub25lOyBmb250LXNpemU6IDEycHgnLFxuICAgICAgICAnY3RybC1hdHRyaWIgYTpob3Zlcic6ICdjb2xvcjogaW5oZXJpdDsgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7JyxcblxuICAgICAgICAnY3RybC1hdHRyaWIgLm1hcGJveC1pbXByb3ZlLW1hcCc6ICdmb250LXdlaWdodDogYm9sZDsgbWFyZ2luLWxlZnQ6IDJweDsnLFxuICAgICAgICAnYXR0cmliLWVtcHR5JzogJ2Rpc3BsYXk6IG5vbmU7JyxcblxuICAgICAgICAvLyBDb21wYWN0IE1hcGJveCBsb2dvIHdpdGhvdXQgdGV4dFxuICAgICAgICAnY3RybC1sb2dvJzogJ2Rpc3BsYXk6YmxvY2s7IHdpZHRoOiAyMXB4OyBoZWlnaHQ6IDIxcHg7IGJhY2tncm91bmQtaW1hZ2U6IHVybChcXCdkYXRhOmltYWdlL3N2Zyt4bWw7Y2hhcnNldD11dGYtOCwlM0M/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cInV0Zi04XCI/JTNFICUzQ3N2ZyB2ZXJzaW9uPVwiMS4xXCIgaWQ9XCJMYXllcl8xXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHhtbG5zOnhsaW5rPVwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlua1wiIHg9XCIwcHhcIiB5PVwiMHB4XCIgdmlld0JveD1cIjAgMCAyMSAyMVwiIHN0eWxlPVwiZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAyMSAyMTtcIiB4bWw6c3BhY2U9XCJwcmVzZXJ2ZVwiJTNFJTNDZyB0cmFuc2Zvcm09XCJ0cmFuc2xhdGUoMCwwLjAxKVwiJTNFJTNDcGF0aCBkPVwibSAxMC41LDEuMjQgYyAtNS4xMSwwIC05LjI1LDQuMTUgLTkuMjUsOS4yNSAwLDUuMSA0LjE1LDkuMjUgOS4yNSw5LjI1IDUuMSwwIDkuMjUsLTQuMTUgOS4yNSwtOS4yNSAwLC01LjExIC00LjE0LC05LjI1IC05LjI1LC05LjI1IHogbSA0LjM5LDExLjUzIGMgLTEuOTMsMS45MyAtNC43OCwyLjMxIC02LjcsMi4zMSAtMC43LDAgLTEuNDEsLTAuMDUgLTIuMSwtMC4xNiAwLDAgLTEuMDIsLTUuNjQgMi4xNCwtOC44MSAwLjgzLC0wLjgzIDEuOTUsLTEuMjggMy4xMywtMS4yOCAxLjI3LDAgMi40OSwwLjUxIDMuMzksMS40MiAxLjg0LDEuODQgMS44OSw0Ljc1IDAuMTQsNi41MiB6XCIgc3R5bGU9XCJvcGFjaXR5OjAuOTtmaWxsOiUyM2ZmZmZmZjtlbmFibGUtYmFja2dyb3VuZDpuZXdcIiBjbGFzcz1cInN0MFwiLyUzRSUzQ3BhdGggZD1cIk0gMTAuNSwtMC4wMSBDIDQuNywtMC4wMSAwLDQuNyAwLDEwLjQ5IGMgMCw1Ljc5IDQuNywxMC41IDEwLjUsMTAuNSA1LjgsMCAxMC41LC00LjcgMTAuNSwtMTAuNSBDIDIwLjk5LDQuNyAxNi4zLC0wLjAxIDEwLjUsLTAuMDEgWiBtIDAsMTkuNzUgYyAtNS4xMSwwIC05LjI1LC00LjE1IC05LjI1LC05LjI1IDAsLTUuMSA0LjE0LC05LjI2IDkuMjUsLTkuMjYgNS4xMSwwIDkuMjUsNC4xNSA5LjI1LDkuMjUgMCw1LjEzIC00LjE0LDkuMjYgLTkuMjUsOS4yNiB6XCIgc3R5bGU9XCJvcGFjaXR5OjAuMzU7ZW5hYmxlLWJhY2tncm91bmQ6bmV3XCIgY2xhc3M9XCJzdDFcIi8lM0UlM0NwYXRoIGQ9XCJNIDE0Ljc0LDYuMjUgQyAxMi45LDQuNDEgOS45OCw0LjM1IDguMjMsNi4xIDUuMDcsOS4yNyA2LjA5LDE0LjkxIDYuMDksMTQuOTEgYyAwLDAgNS42NCwxLjAyIDguODEsLTIuMTQgQyAxNi42NCwxMSAxNi41OSw4LjA5IDE0Ljc0LDYuMjUgWiBtIC0yLjI3LDQuMDkgLTAuOTEsMS44NyAtMC45LC0xLjg3IC0xLjg2LC0wLjkxIDEuODYsLTAuOSAwLjksLTEuODcgMC45MSwxLjg3IDEuODYsMC45IHpcIiBzdHlsZT1cIm9wYWNpdHk6MC4zNTtlbmFibGUtYmFja2dyb3VuZDpuZXdcIiBjbGFzcz1cInN0MVwiLyUzRSUzQ3BvbHlnb24gcG9pbnRzPVwiMTEuNTYsMTIuMjEgMTAuNjYsMTAuMzQgOC44LDkuNDMgMTAuNjYsOC41MyAxMS41Niw2LjY2IDEyLjQ3LDguNTMgMTQuMzMsOS40MyAxMi40NywxMC4zNCBcIiBzdHlsZT1cIm9wYWNpdHk6MC45O2ZpbGw6JTIzZmZmZmZmO2VuYWJsZS1iYWNrZ3JvdW5kOm5ld1wiIGNsYXNzPVwic3QwXCIvJTNFJTNDL2clM0UlM0Mvc3ZnJTNFXFwnKSdcblxuICAgICAgICAvLyBNYXBib3ggbG9nbyBXSVRIIHRleHQgYmVsb3cgKGNvbW1lbnRlZCBvdXQgZm9yIG5vdylcbiAgICAgICAgLy8gJ2N0cmwtbG9nbyc6ICd3aWR0aDogODVweDsgaGVpZ2h0OiAyMXB4OyBtYXJnaW46IDAgMCAtM3B4IC0zcHg7IGRpc3BsYXk6IGJsb2NrOyBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0OyBjdXJzb3I6IHBvaW50ZXI7IGJhY2tncm91bmQtaW1hZ2U6IHVybChcXCdkYXRhOmltYWdlL3N2Zyt4bWw7Y2hhcnNldD11dGYtOCwlM0M/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cInV0Zi04XCI/JTNFJTNDc3ZnIHZlcnNpb249XCIxLjFcIiBpZD1cIkxheWVyXzFcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgeG1sbnM6eGxpbms9XCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rXCIgeD1cIjBweFwiIHk9XCIwcHhcIiB2aWV3Qm94PVwiMCAwIDg0LjQ5IDIxXCIgc3R5bGU9XCJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDg0LjQ5IDIxO1wiIHhtbDpzcGFjZT1cInByZXNlcnZlXCIlM0UlM0NnJTNFICUzQ3BhdGggY2xhc3M9XCJzdDBcIiBzdHlsZT1cIm9wYWNpdHk6MC45OyBmaWxsOiAlMjNGRkZGRkY7IGVuYWJsZS1iYWNrZ3JvdW5kOiBuZXc7XCIgZD1cIk04My4yNSwxNC4yNmMwLDAuMTItMC4wOSwwLjIxLTAuMjEsMC4yMWgtMS42MWMtMC4xMywwLTAuMjQtMC4wNi0wLjMtMC4xN2wtMS40NC0yLjM5bC0xLjQ0LDIuMzkgYy0wLjA2LDAuMTEtMC4xOCwwLjE3LTAuMywwLjE3aC0xLjYxYy0wLjA0LDAtMC4wOC0wLjAxLTAuMTItMC4wM2MtMC4wOS0wLjA2LTAuMTMtMC4xOS0wLjA2LTAuMjhsMCwwbDIuNDMtMy42OEw3Ni4yLDYuODQgYy0wLjAyLTAuMDMtMC4wMy0wLjA3LTAuMDMtMC4xMmMwLTAuMTIsMC4wOS0wLjIxLDAuMjEtMC4yMWgxLjYxYzAuMTMsMCwwLjI0LDAuMDYsMC4zLDAuMTdsMS40MSwyLjM2bDEuNC0yLjM1IGMwLjA2LTAuMTEsMC4xOC0wLjE3LDAuMy0wLjE3SDgzYzAuMDQsMCwwLjA4LDAuMDEsMC4xMiwwLjAzYzAuMDksMC4wNiwwLjEzLDAuMTksMC4wNiwwLjI4bDAsMGwtMi4zNywzLjYzbDIuNDMsMy42NyBDODMuMjQsMTQuMTgsODMuMjUsMTQuMjIsODMuMjUsMTQuMjZ6XCIvJTNFICUzQ3BhdGggY2xhc3M9XCJzdDBcIiBzdHlsZT1cIm9wYWNpdHk6MC45OyBmaWxsOiAlMjNGRkZGRkY7IGVuYWJsZS1iYWNrZ3JvdW5kOiBuZXc7XCIgZD1cIk02Ni4yNCw5LjU5Yy0wLjM5LTEuODgtMS45Ni0zLjI4LTMuODQtMy4yOGMtMS4wMywwLTIuMDMsMC40Mi0yLjczLDEuMThWMy41MWMwLTAuMTMtMC4xLTAuMjMtMC4yMy0wLjIzaC0xLjQgYy0wLjEzLDAtMC4yMywwLjExLTAuMjMsMC4yM3YxMC43MmMwLDAuMTMsMC4xLDAuMjMsMC4yMywwLjIzaDEuNGMwLjEzLDAsMC4yMy0wLjExLDAuMjMtMC4yM1YxMy41YzAuNzEsMC43NSwxLjcsMS4xOCwyLjczLDEuMTggYzEuODgsMCwzLjQ1LTEuNDEsMy44NC0zLjI5QzY2LjM3LDEwLjc5LDY2LjM3LDEwLjE4LDY2LjI0LDkuNTlMNjYuMjQsOS41OXogTTYyLjA4LDEzYy0xLjMyLDAtMi4zOS0xLjExLTIuNDEtMi40OHYtMC4wNiBjMC4wMi0xLjM4LDEuMDktMi40OCwyLjQxLTIuNDhzMi40MiwxLjEyLDIuNDIsMi41MVM2My40MSwxMyw2Mi4wOCwxM3pcIi8lM0UgJTNDcGF0aCBjbGFzcz1cInN0MFwiIHN0eWxlPVwib3BhY2l0eTowLjk7IGZpbGw6ICUyM0ZGRkZGRjsgZW5hYmxlLWJhY2tncm91bmQ6IG5ldztcIiBkPVwiTTcxLjY3LDYuMzJjLTEuOTgtMC4wMS0zLjcyLDEuMzUtNC4xNiwzLjI5Yy0wLjEzLDAuNTktMC4xMywxLjE5LDAsMS43N2MwLjQ0LDEuOTQsMi4xNywzLjMyLDQuMTcsMy4zIGMyLjM1LDAsNC4yNi0xLjg3LDQuMjYtNC4xOVM3NC4wNCw2LjMyLDcxLjY3LDYuMzJ6IE03MS42NSwxMy4wMWMtMS4zMywwLTIuNDItMS4xMi0yLjQyLTIuNTFzMS4wOC0yLjUyLDIuNDItMi41MiBjMS4zMywwLDIuNDIsMS4xMiwyLjQyLDIuNTFTNzIuOTksMTMsNzEuNjUsMTMuMDFMNzEuNjUsMTMuMDF6XCIvJTNFICUzQ3BhdGggY2xhc3M9XCJzdDFcIiBzdHlsZT1cIm9wYWNpdHk6MC4zNTsgZW5hYmxlLWJhY2tncm91bmQ6bmV3O1wiIGQ9XCJNNjIuMDgsNy45OGMtMS4zMiwwLTIuMzksMS4xMS0yLjQxLDIuNDh2MC4wNkM1OS42OCwxMS45LDYwLjc1LDEzLDYyLjA4LDEzczIuNDItMS4xMiwyLjQyLTIuNTEgUzYzLjQxLDcuOTgsNjIuMDgsNy45OHogTTYyLjA4LDExLjc2Yy0wLjYzLDAtMS4xNC0wLjU2LTEuMTctMS4yNXYtMC4wNGMwLjAxLTAuNjksMC41NC0xLjI1LDEuMTctMS4yNSBjMC42MywwLDEuMTcsMC41NywxLjE3LDEuMjdDNjMuMjQsMTEuMiw2Mi43MywxMS43Niw2Mi4wOCwxMS43NnpcIi8lM0UgJTNDcGF0aCBjbGFzcz1cInN0MVwiIHN0eWxlPVwib3BhY2l0eTowLjM1OyBlbmFibGUtYmFja2dyb3VuZDpuZXc7XCIgZD1cIk03MS42NSw3Ljk4Yy0xLjMzLDAtMi40MiwxLjEyLTIuNDIsMi41MVM3MC4zMiwxMyw3MS42NSwxM3MyLjQyLTEuMTIsMi40Mi0yLjUxUzcyLjk5LDcuOTgsNzEuNjUsNy45OHogTTcxLjY1LDExLjc2Yy0wLjY0LDAtMS4xNy0wLjU3LTEuMTctMS4yN2MwLTAuNywwLjUzLTEuMjYsMS4xNy0xLjI2czEuMTcsMC41NywxLjE3LDEuMjdDNzIuODIsMTEuMjEsNzIuMjksMTEuNzYsNzEuNjUsMTEuNzZ6XCIvJTNFICUzQ3BhdGggY2xhc3M9XCJzdDBcIiBzdHlsZT1cIm9wYWNpdHk6MC45OyBmaWxsOiAlMjNGRkZGRkY7IGVuYWJsZS1iYWNrZ3JvdW5kOiBuZXc7XCIgZD1cIk00NS43NCw2LjUzaC0xLjRjLTAuMTMsMC0wLjIzLDAuMTEtMC4yMywwLjIzdjAuNzNjLTAuNzEtMC43NS0xLjctMS4xOC0yLjczLTEuMTggYy0yLjE3LDAtMy45NCwxLjg3LTMuOTQsNC4xOXMxLjc3LDQuMTksMy45NCw0LjE5YzEuMDQsMCwyLjAzLTAuNDMsMi43My0xLjE5djAuNzNjMCwwLjEzLDAuMSwwLjIzLDAuMjMsMC4yM2gxLjQgYzAuMTMsMCwwLjIzLTAuMTEsMC4yMy0wLjIzVjYuNzRjMC0wLjEyLTAuMDktMC4yMi0wLjIyLTAuMjJDNDUuNzUsNi41Myw0NS43NSw2LjUzLDQ1Ljc0LDYuNTN6IE00NC4xMiwxMC41MyBDNDQuMTEsMTEuOSw0My4wMywxMyw0MS43MSwxM3MtMi40Mi0xLjEyLTIuNDItMi41MXMxLjA4LTIuNTIsMi40LTIuNTJjMS4zMywwLDIuMzksMS4xMSwyLjQxLDIuNDhMNDQuMTIsMTAuNTN6XCIvJTNFICUzQ3BhdGggY2xhc3M9XCJzdDFcIiBzdHlsZT1cIm9wYWNpdHk6MC4zNTsgZW5hYmxlLWJhY2tncm91bmQ6bmV3O1wiIGQ9XCJNNDEuNzEsNy45OGMtMS4zMywwLTIuNDIsMS4xMi0yLjQyLDIuNTFTNDAuMzcsMTMsNDEuNzEsMTNzMi4zOS0xLjExLDIuNDEtMi40OHYtMC4wNiBDNDQuMSw5LjA5LDQzLjAzLDcuOTgsNDEuNzEsNy45OHogTTQwLjU1LDEwLjQ5YzAtMC43LDAuNTItMS4yNywxLjE3LTEuMjdjMC42NCwwLDEuMTQsMC41NiwxLjE3LDEuMjV2MC4wNCBjLTAuMDEsMC42OC0wLjUzLDEuMjQtMS4xNywxLjI0QzQxLjA4LDExLjc1LDQwLjU1LDExLjE5LDQwLjU1LDEwLjQ5elwiLyUzRSAlM0NwYXRoIGNsYXNzPVwic3QwXCIgc3R5bGU9XCJvcGFjaXR5OjAuOTsgZmlsbDogJTIzRkZGRkZGOyBlbmFibGUtYmFja2dyb3VuZDogbmV3O1wiIGQ9XCJNNTIuNDEsNi4zMmMtMS4wMywwLTIuMDMsMC40Mi0yLjczLDEuMThWNi43NWMwLTAuMTMtMC4xLTAuMjMtMC4yMy0wLjIzaC0xLjRjLTAuMTMsMC0wLjIzLDAuMTEtMC4yMywwLjIzIHYxMC43MmMwLDAuMTMsMC4xLDAuMjMsMC4yMywwLjIzaDEuNGMwLjEzLDAsMC4yMy0wLjEsMC4yMy0wLjIzVjEzLjVjMC43MSwwLjc1LDEuNywxLjE4LDIuNzQsMS4xOGMyLjE3LDAsMy45NC0xLjg3LDMuOTQtNC4xOSBTNTQuNTgsNi4zMiw1Mi40MSw2LjMyeiBNNTIuMDgsMTMuMDFjLTEuMzIsMC0yLjM5LTEuMTEtMi40Mi0yLjQ4di0wLjA3YzAuMDItMS4zOCwxLjA5LTIuNDksMi40LTIuNDljMS4zMiwwLDIuNDEsMS4xMiwyLjQxLDIuNTEgUzUzLjQsMTMsNTIuMDgsMTMuMDFMNTIuMDgsMTMuMDF6XCIvJTNFICUzQ3BhdGggY2xhc3M9XCJzdDFcIiBzdHlsZT1cIm9wYWNpdHk6MC4zNTsgZW5hYmxlLWJhY2tncm91bmQ6bmV3O1wiIGQ9XCJNNTIuMDgsNy45OGMtMS4zMiwwLTIuMzksMS4xMS0yLjQyLDIuNDh2MC4wNmMwLjAzLDEuMzgsMS4xLDIuNDgsMi40MiwyLjQ4czIuNDEtMS4xMiwyLjQxLTIuNTEgUzUzLjQsNy45OCw1Mi4wOCw3Ljk4eiBNNTIuMDgsMTEuNzZjLTAuNjMsMC0xLjE0LTAuNTYtMS4xNy0xLjI1di0wLjA0YzAuMDEtMC42OSwwLjU0LTEuMjUsMS4xNy0xLjI1YzAuNjMsMCwxLjE3LDAuNTgsMS4xNywxLjI3IFM1Mi43MiwxMS43Niw1Mi4wOCwxMS43NnpcIi8lM0UgJTNDcGF0aCBjbGFzcz1cInN0MFwiIHN0eWxlPVwib3BhY2l0eTowLjk7IGZpbGw6ICUyM0ZGRkZGRjsgZW5hYmxlLWJhY2tncm91bmQ6IG5ldztcIiBkPVwiTTM2LjA4LDE0LjI0YzAsMC4xMy0wLjEsMC4yMy0wLjIzLDAuMjNoLTEuNDFjLTAuMTMsMC0wLjIzLTAuMTEtMC4yMy0wLjIzVjkuNjhjMC0wLjk4LTAuNzQtMS43MS0xLjYyLTEuNzEgYy0wLjgsMC0xLjQ2LDAuNy0xLjU5LDEuNjJsMC4wMSw0LjY2YzAsMC4xMy0wLjExLDAuMjMtMC4yMywwLjIzaC0xLjQxYy0wLjEzLDAtMC4yMy0wLjExLTAuMjMtMC4yM1Y5LjY4IGMwLTAuOTgtMC43NC0xLjcxLTEuNjItMS43MWMtMC44NSwwLTEuNTQsMC43OS0xLjYsMS44djQuNDhjMCwwLjEzLTAuMSwwLjIzLTAuMjMsMC4yM2gtMS40Yy0wLjEzLDAtMC4yMy0wLjExLTAuMjMtMC4yM1Y2Ljc0IGMwLjAxLTAuMTMsMC4xLTAuMjIsMC4yMy0wLjIyaDEuNGMwLjEzLDAsMC4yMiwwLjExLDAuMjMsMC4yMlY3LjRjMC41LTAuNjgsMS4zLTEuMDksMi4xNi0xLjFoMC4wM2MxLjA5LDAsMi4wOSwwLjYsMi42LDEuNTUgYzAuNDUtMC45NSwxLjQtMS41NSwyLjQ0LTEuNTZjMS42MiwwLDIuOTMsMS4yNSwyLjksMi43OEwzNi4wOCwxNC4yNHpcIi8lM0UgJTNDcGF0aCBjbGFzcz1cInN0MVwiIHN0eWxlPVwib3BhY2l0eTowLjM1OyBlbmFibGUtYmFja2dyb3VuZDpuZXc7XCIgZD1cIk04NC4zNCwxMy41OWwtMC4wNy0wLjEzbC0xLjk2LTIuOTlsMS45NC0yLjk1YzAuNDQtMC42NywwLjI2LTEuNTYtMC40MS0yLjAyYy0wLjAyLDAtMC4wMywwLTAuMDQtMC4wMSBjLTAuMjMtMC4xNS0wLjUtMC4yMi0wLjc4LTAuMjJoLTEuNjFjLTAuNTYsMC0xLjA4LDAuMjktMS4zNywwLjc4TDc5LjcyLDYuNmwtMC4zNC0wLjU2Qzc5LjA5LDUuNTYsNzguNTcsNS4yNyw3OCw1LjI3aC0xLjYgYy0wLjYsMC0xLjEzLDAuMzctMS4zNSwwLjkyYy0yLjE5LTEuNjYtNS4yOC0xLjQ3LTcuMjYsMC40NWMtMC4zNSwwLjM0LTAuNjUsMC43Mi0wLjg5LDEuMTRjLTAuOS0xLjYyLTIuNTgtMi43Mi00LjUtMi43MiBjLTAuNSwwLTEuMDEsMC4wNy0xLjQ4LDAuMjNWMy41MWMwLTAuODItMC42Ni0xLjQ4LTEuNDctMS40OGgtMS40Yy0wLjgxLDAtMS40NywwLjY2LTEuNDcsMS40N3YzLjc1IGMtMC45NS0xLjM2LTIuNS0yLjE4LTQuMTctMi4xOWMtMC43NCwwLTEuNDYsMC4xNi0yLjEyLDAuNDdjLTAuMjQtMC4xNy0wLjU0LTAuMjYtMC44NC0wLjI2aC0xLjRjLTAuNDUsMC0wLjg3LDAuMjEtMS4xNSwwLjU2IGMtMC4wMi0wLjAzLTAuMDQtMC4wNS0wLjA3LTAuMDhjLTAuMjgtMC4zLTAuNjgtMC40Ny0xLjA5LTAuNDdoLTEuMzljLTAuMywwLTAuNiwwLjA5LTAuODQsMC4yNmMtMC42Ny0wLjMtMS4zOS0wLjQ2LTIuMTItMC40NiBjLTEuODMsMC0zLjQzLDEtNC4zNywyLjVjLTAuMi0wLjQ2LTAuNDgtMC44OS0wLjgzLTEuMjVjLTAuOC0wLjgxLTEuODktMS4yNS0zLjAyLTEuMjVoLTAuMDFjLTAuODksMC4wMS0xLjc1LDAuMzMtMi40NiwwLjg4IGMtMC43NC0wLjU3LTEuNjQtMC44OC0yLjU3LTAuODhIMjguMWMtMC4yOSwwLTAuNTgsMC4wMy0wLjg2LDAuMTFjLTAuMjgsMC4wNi0wLjU2LDAuMTYtMC44MiwwLjI4Yy0wLjIxLTAuMTItMC40NS0wLjE4LTAuNy0wLjE4IGgtMS40Yy0wLjgyLDAtMS40NywwLjY2LTEuNDcsMS40N3Y3LjVjMCwwLjgyLDAuNjYsMS40NywxLjQ3LDEuNDdoMS40YzAuODIsMCwxLjQ4LTAuNjYsMS40OC0xLjQ4bDAsMFY5Ljc5IGMwLjAzLTAuMzYsMC4yMy0wLjU5LDAuMzYtMC41OWMwLjE4LDAsMC4zOCwwLjE4LDAuMzgsMC40N3Y0LjU3YzAsMC44MiwwLjY2LDEuNDcsMS40NywxLjQ3aDEuNDFjMC44MiwwLDEuNDctMC42NiwxLjQ3LTEuNDcgbC0wLjAxLTQuNTdjMC4wNi0wLjMyLDAuMjUtMC40NywwLjM1LTAuNDdjMC4xOCwwLDAuMzgsMC4xOCwwLjM4LDAuNDd2NC41N2MwLDAuODIsMC42NiwxLjQ3LDEuNDcsMS40N2gxLjQxIGMwLjgyLDAsMS40Ny0wLjY2LDEuNDctMS40N3YtMC4zOGMwLjk2LDEuMjksMi40NiwyLjA2LDQuMDYsMi4wNmMwLjc0LDAsMS40Ni0wLjE2LDIuMTItMC40N2MwLjI0LDAuMTcsMC41NCwwLjI2LDAuODQsMC4yNmgxLjM5IGMwLjMsMCwwLjYtMC4wOSwwLjg0LTAuMjZ2Mi4wMWMwLDAuODIsMC42NiwxLjQ3LDEuNDcsMS40N2gxLjRjMC44MiwwLDEuNDctMC42NiwxLjQ3LTEuNDd2LTEuNzdjMC40OCwwLjE1LDAuOTksMC4yMywxLjQ5LDAuMjIgYzEuNywwLDMuMjItMC44Nyw0LjE3LTIuMnYwLjUyYzAsMC44MiwwLjY2LDEuNDcsMS40NywxLjQ3aDEuNGMwLjMsMCwwLjYtMC4wOSwwLjg0LTAuMjZjMC42NiwwLjMxLDEuMzksMC40NywyLjEyLDAuNDcgYzEuOTIsMCwzLjYtMS4xLDQuNDktMi43M2MxLjU0LDIuNjUsNC45NSwzLjUzLDcuNTgsMS45OGMwLjE4LTAuMTEsMC4zNi0wLjIyLDAuNTMtMC4zNmMwLjIyLDAuNTUsMC43NiwwLjkxLDEuMzUsMC45SDc4IGMwLjU2LDAsMS4wOC0wLjI5LDEuMzctMC43OGwwLjM3LTAuNjFsMC4zNywwLjYxYzAuMjksMC40OCwwLjgxLDAuNzgsMS4zOCwwLjc4aDEuNmMwLjgxLDAsMS40Ni0wLjY2LDEuNDUtMS40NiBDODQuNDksMTQuMDIsODQuNDQsMTMuOCw4NC4zNCwxMy41OUw4NC4zNCwxMy41OXogTTM1Ljg2LDE0LjQ3aC0xLjQxYy0wLjEzLDAtMC4yMy0wLjExLTAuMjMtMC4yM1Y5LjY4IGMwLTAuOTgtMC43NC0xLjcxLTEuNjItMS43MWMtMC44LDAtMS40NiwwLjctMS41OSwxLjYybDAuMDEsNC42NmMwLDAuMTMtMC4xLDAuMjMtMC4yMywwLjIzaC0xLjQxYy0wLjEzLDAtMC4yMy0wLjExLTAuMjMtMC4yMyBWOS42OGMwLTAuOTgtMC43NC0xLjcxLTEuNjItMS43MWMtMC44NSwwLTEuNTQsMC43OS0xLjYsMS44djQuNDhjMCwwLjEzLTAuMSwwLjIzLTAuMjMsMC4yM2gtMS40Yy0wLjEzLDAtMC4yMy0wLjExLTAuMjMtMC4yMyBWNi43NGMwLjAxLTAuMTMsMC4xMS0wLjIyLDAuMjMtMC4yMmgxLjRjMC4xMywwLDAuMjIsMC4xMSwwLjIzLDAuMjJWNy40YzAuNS0wLjY4LDEuMy0xLjA5LDIuMTYtMS4xaDAuMDMgYzEuMDksMCwyLjA5LDAuNiwyLjYsMS41NWMwLjQ1LTAuOTUsMS40LTEuNTUsMi40NC0xLjU2YzEuNjIsMCwyLjkzLDEuMjUsMi45LDIuNzhsMC4wMSw1LjE2QzM2LjA5LDE0LjM2LDM1Ljk4LDE0LjQ2LDM1Ljg2LDE0LjQ3IEwzNS44NiwxNC40N3ogTTQ1Ljk3LDE0LjI0YzAsMC4xMy0wLjEsMC4yMy0wLjIzLDAuMjNoLTEuNGMtMC4xMywwLTAuMjMtMC4xMS0wLjIzLTAuMjNWMTMuNWMtMC43LDAuNzYtMS42OSwxLjE4LTIuNzIsMS4xOCBjLTIuMTcsMC0zLjk0LTEuODctMy45NC00LjE5czEuNzctNC4xOSwzLjk0LTQuMTljMS4wMywwLDIuMDIsMC40MywyLjczLDEuMThWNi43NGMwLTAuMTMsMC4xLTAuMjMsMC4yMy0wLjIzaDEuNCBjMC4xMi0wLjAxLDAuMjIsMC4wOCwwLjIzLDAuMjFjMCwwLjAxLDAsMC4wMSwwLDAuMDJ2Ny41MWgtMC4wMVYxNC4yNHogTTUyLjQxLDE0LjY3Yy0xLjAzLDAtMi4wMi0wLjQzLTIuNzMtMS4xOHYzLjk3IGMwLDAuMTMtMC4xLDAuMjMtMC4yMywwLjIzaC0xLjRjLTAuMTMsMC0wLjIzLTAuMS0wLjIzLTAuMjNWNi43NWMwLTAuMTMsMC4xLTAuMjIsMC4yMy0wLjIyaDEuNGMwLjEzLDAsMC4yMywwLjExLDAuMjMsMC4yM3YwLjczIGMwLjcxLTAuNzYsMS43LTEuMTgsMi43My0xLjE4YzIuMTcsMCwzLjk0LDEuODYsMy45NCw0LjE4UzU0LjU4LDE0LjY3LDUyLjQxLDE0LjY3eiBNNjYuMjQsMTEuMzljLTAuMzksMS44Ny0xLjk2LDMuMjktMy44NCwzLjI5IGMtMS4wMywwLTIuMDItMC40My0yLjczLTEuMTh2MC43M2MwLDAuMTMtMC4xLDAuMjMtMC4yMywwLjIzaC0xLjRjLTAuMTMsMC0wLjIzLTAuMTEtMC4yMy0wLjIzVjMuNTFjMC0wLjEzLDAuMS0wLjIzLDAuMjMtMC4yMyBoMS40YzAuMTMsMCwwLjIzLDAuMTEsMC4yMywwLjIzdjMuOTdjMC43MS0wLjc1LDEuNy0xLjE4LDIuNzMtMS4xN2MxLjg4LDAsMy40NSwxLjQsMy44NCwzLjI4QzY2LjM3LDEwLjE5LDY2LjM3LDEwLjgsNjYuMjQsMTEuMzkgTDY2LjI0LDExLjM5TDY2LjI0LDExLjM5eiBNNzEuNjcsMTQuNjhjLTIsMC4wMS0zLjczLTEuMzUtNC4xNy0zLjNjLTAuMTMtMC41OS0wLjEzLTEuMTksMC0xLjc3YzAuNDQtMS45NCwyLjE3LTMuMzEsNC4xNy0zLjMgYzIuMzYsMCw0LjI2LDEuODcsNC4yNiw0LjE5Uzc0LjAzLDE0LjY4LDcxLjY3LDE0LjY4TDcxLjY3LDE0LjY4eiBNODMuMDQsMTQuNDdoLTEuNjFjLTAuMTMsMC0wLjI0LTAuMDYtMC4zLTAuMTdsLTEuNDQtMi4zOSBsLTEuNDQsMi4zOWMtMC4wNiwwLjExLTAuMTgsMC4xNy0wLjMsMC4xN2gtMS42MWMtMC4wNCwwLTAuMDgtMC4wMS0wLjEyLTAuMDNjLTAuMDktMC4wNi0wLjEzLTAuMTktMC4wNi0wLjI4bDAsMGwyLjQzLTMuNjggTDc2LjIsNi44NGMtMC4wMi0wLjAzLTAuMDMtMC4wNy0wLjAzLTAuMTJjMC0wLjEyLDAuMDktMC4yMSwwLjIxLTAuMjFoMS42MWMwLjEzLDAsMC4yNCwwLjA2LDAuMywwLjE3bDEuNDEsMi4zNmwxLjQxLTIuMzYgYzAuMDYtMC4xMSwwLjE4LTAuMTcsMC4zLTAuMTdoMS42MWMwLjA0LDAsMC4wOCwwLjAxLDAuMTIsMC4wM2MwLjA5LDAuMDYsMC4xMywwLjE5LDAuMDYsMC4yOGwwLDBsLTIuMzgsMy42NGwyLjQzLDMuNjcgYzAuMDIsMC4wMywwLjAzLDAuMDcsMC4wMywwLjEyQzgzLjI1LDE0LjM4LDgzLjE2LDE0LjQ3LDgzLjA0LDE0LjQ3TDgzLjA0LDE0LjQ3TDgzLjA0LDE0LjQ3elwiLyUzRSAlM0NwYXRoIGNsYXNzPVwic3QwXCIgc3R5bGU9XCJvcGFjaXR5OjAuOTsgZmlsbDogJTIzRkZGRkZGOyBlbmFibGUtYmFja2dyb3VuZDogbmV3O1wiIGQ9XCJNMTAuNSwxLjI0Yy01LjExLDAtOS4yNSw0LjE1LTkuMjUsOS4yNXM0LjE1LDkuMjUsOS4yNSw5LjI1czkuMjUtNC4xNSw5LjI1LTkuMjUgQzE5Ljc1LDUuMzgsMTUuNjEsMS4yNCwxMC41LDEuMjR6IE0xNC44OSwxMi43N2MtMS45MywxLjkzLTQuNzgsMi4zMS02LjcsMi4zMWMtMC43LDAtMS40MS0wLjA1LTIuMS0wLjE2YzAsMC0xLjAyLTUuNjQsMi4xNC04LjgxIGMwLjgzLTAuODMsMS45NS0xLjI4LDMuMTMtMS4yOGMxLjI3LDAsMi40OSwwLjUxLDMuMzksMS40MkMxNi41OSw4LjA5LDE2LjY0LDExLDE0Ljg5LDEyLjc3elwiLyUzRSAlM0NwYXRoIGNsYXNzPVwic3QxXCIgc3R5bGU9XCJvcGFjaXR5OjAuMzU7IGVuYWJsZS1iYWNrZ3JvdW5kOm5ldztcIiBkPVwiTTEwLjUtMC4wMUM0LjctMC4wMSwwLDQuNywwLDEwLjQ5czQuNywxMC41LDEwLjUsMTAuNVMyMSwxNi4yOSwyMSwxMC40OUMyMC45OSw0LjcsMTYuMy0wLjAxLDEwLjUtMC4wMXogTTEwLjUsMTkuNzRjLTUuMTEsMC05LjI1LTQuMTUtOS4yNS05LjI1czQuMTQtOS4yNiw5LjI1LTkuMjZzOS4yNSw0LjE1LDkuMjUsOS4yNUMxOS43NSwxNS42MSwxNS42MSwxOS43NCwxMC41LDE5Ljc0elwiLyUzRSAlM0NwYXRoIGNsYXNzPVwic3QxXCIgc3R5bGU9XCJvcGFjaXR5OjAuMzU7IGVuYWJsZS1iYWNrZ3JvdW5kOm5ldztcIiBkPVwiTTE0Ljc0LDYuMjVDMTIuOSw0LjQxLDkuOTgsNC4zNSw4LjIzLDYuMWMtMy4xNiwzLjE3LTIuMTQsOC44MS0yLjE0LDguODFzNS42NCwxLjAyLDguODEtMi4xNCBDMTYuNjQsMTEsMTYuNTksOC4wOSwxNC43NCw2LjI1eiBNMTIuNDcsMTAuMzRsLTAuOTEsMS44N2wtMC45LTEuODdMOC44LDkuNDNsMS44Ni0wLjlsMC45LTEuODdsMC45MSwxLjg3bDEuODYsMC45TDEyLjQ3LDEwLjM0elwiLyUzRSAlM0Nwb2x5Z29uIGNsYXNzPVwic3QwXCIgc3R5bGU9XCJvcGFjaXR5OjAuOTsgZmlsbDogJTIzRkZGRkZGOyBlbmFibGUtYmFja2dyb3VuZDogbmV3O1wiIHBvaW50cz1cIjE0LjMzLDkuNDMgMTIuNDcsMTAuMzQgMTEuNTYsMTIuMjEgMTAuNjYsMTAuMzQgOC44LDkuNDMgMTAuNjYsOC41MyAxMS41Niw2LjY2IDEyLjQ3LDguNTMgXCIvJTNFJTNDL2clM0UlM0Mvc3ZnJTNFXFwnKTsnXG4gICAgfVxufTtcblxufSx7fV0sODIxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbi8qKlxuICogQ29udmVydCBwbG90bHkuanMgJ3RleHRwb3NpdGlvbicgdG8gbWFwYm94LWdsICdhbmNob3InIGFuZCAnb2Zmc2V0J1xuICogKHdpdGggdGhlIGhlbHAgb2YgdGhlIGljb24gc2l6ZSkuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHRwb3N0aW9uIDogcGxvdGx5LmpzIHRleHRwb3NpdGlvbiB2YWx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IGljb25TaXplIDogcGxvdGx5LmpzIGljb24gc2l6ZSAoZS5nLiBtYXJrZXIuc2l6ZSBmb3IgdHJhY2VzKVxuICpcbiAqIEByZXR1cm4ge29iamVjdH1cbiAqICAgICAgLSBhbmNob3JcbiAqICAgICAgLSBvZmZzZXRcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb252ZXJ0VGV4dE9wdHModGV4dHBvc2l0aW9uLCBpY29uU2l6ZSkge1xuICAgIHZhciBwYXJ0cyA9IHRleHRwb3NpdGlvbi5zcGxpdCgnICcpO1xuICAgIHZhciB2UG9zID0gcGFydHNbMF07XG4gICAgdmFyIGhQb3MgPSBwYXJ0c1sxXTtcblxuICAgIC8vIGJhbGxwYWNrIHZhbHVlc1xuICAgIHZhciBmYWN0b3IgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShpY29uU2l6ZSkgPyBMaWIubWVhbihpY29uU2l6ZSkgOiBpY29uU2l6ZTtcbiAgICB2YXIgeEluYyA9IDAuNSArIChmYWN0b3IgLyAxMDApO1xuICAgIHZhciB5SW5jID0gMS41ICsgKGZhY3RvciAvIDEwMCk7XG5cbiAgICB2YXIgYW5jaG9yVmFscyA9IFsnJywgJyddO1xuICAgIHZhciBvZmZzZXQgPSBbMCwgMF07XG5cbiAgICBzd2l0Y2godlBvcykge1xuICAgICAgICBjYXNlICd0b3AnOlxuICAgICAgICAgICAgYW5jaG9yVmFsc1swXSA9ICd0b3AnO1xuICAgICAgICAgICAgb2Zmc2V0WzFdID0gLXlJbmM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnYm90dG9tJzpcbiAgICAgICAgICAgIGFuY2hvclZhbHNbMF0gPSAnYm90dG9tJztcbiAgICAgICAgICAgIG9mZnNldFsxXSA9IHlJbmM7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBzd2l0Y2goaFBvcykge1xuICAgICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgICAgIGFuY2hvclZhbHNbMV0gPSAncmlnaHQnO1xuICAgICAgICAgICAgb2Zmc2V0WzBdID0gLXhJbmM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICAgICAgYW5jaG9yVmFsc1sxXSA9ICdsZWZ0JztcbiAgICAgICAgICAgIG9mZnNldFswXSA9IHhJbmM7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICAvLyBNYXBib3ggdGV4dC1hbmNob3IgbXVzdCBiZSBvbmUgb2Y6XG4gICAgLy8gIGNlbnRlciwgbGVmdCwgcmlnaHQsIHRvcCwgYm90dG9tLFxuICAgIC8vICB0b3AtbGVmdCwgdG9wLXJpZ2h0LCBib3R0b20tbGVmdCwgYm90dG9tLXJpZ2h0XG5cbiAgICB2YXIgYW5jaG9yO1xuICAgIGlmKGFuY2hvclZhbHNbMF0gJiYgYW5jaG9yVmFsc1sxXSkgYW5jaG9yID0gYW5jaG9yVmFscy5qb2luKCctJyk7XG4gICAgZWxzZSBpZihhbmNob3JWYWxzWzBdKSBhbmNob3IgPSBhbmNob3JWYWxzWzBdO1xuICAgIGVsc2UgaWYoYW5jaG9yVmFsc1sxXSkgYW5jaG9yID0gYW5jaG9yVmFsc1sxXTtcbiAgICBlbHNlIGFuY2hvciA9ICdjZW50ZXInO1xuXG4gICAgcmV0dXJuIHsgYW5jaG9yOiBhbmNob3IsIG9mZnNldDogb2Zmc2V0IH07XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOX1dLDgyMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBtYXBib3hnbCA9IF9kZXJlcV8oJ21hcGJveC1nbCcpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgZ2V0U3VicGxvdENhbGNEYXRhID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRTdWJwbG90Q2FsY0RhdGE7XG52YXIgeG1sbnNOYW1lc3BhY2VzID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXMnKTtcbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xuXG52YXIgTWFwYm94ID0gX2RlcmVxXygnLi9tYXBib3gnKTtcblxudmFyIE1BUEJPWCA9ICdtYXBib3gnO1xuXG52YXIgY29uc3RhbnRzID0gZXhwb3J0cy5jb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xuXG5leHBvcnRzLm5hbWUgPSBNQVBCT1g7XG5cbmV4cG9ydHMuYXR0ciA9ICdzdWJwbG90JztcblxuZXhwb3J0cy5pZFJvb3QgPSBNQVBCT1g7XG5cbmV4cG9ydHMuaWRSZWdleCA9IGV4cG9ydHMuYXR0clJlZ2V4ID0gTGliLmNvdW50ZXJSZWdleChNQVBCT1gpO1xuXG5leHBvcnRzLmF0dHJpYnV0ZXMgPSB7XG4gICAgc3VicGxvdDoge1xuICAgICAgICB2YWxUeXBlOiAnc3VicGxvdGlkJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICdtYXBib3gnLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9XG59O1xuXG5leHBvcnRzLmxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMuc3VwcGx5TGF5b3V0RGVmYXVsdHMgPSBfZGVyZXFfKCcuL2xheW91dF9kZWZhdWx0cycpO1xuXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbiBwbG90KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2FsY0RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgbWFwYm94SWRzID0gZnVsbExheW91dC5fc3VicGxvdHNbTUFQQk9YXTtcblxuICAgIGlmKG1hcGJveGdsLnZlcnNpb24gIT09IGNvbnN0YW50cy5yZXF1aXJlZFZlcnNpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGNvbnN0YW50cy53cm9uZ1ZlcnNpb25FcnJvck1zZyk7XG4gICAgfVxuXG4gICAgdmFyIGFjY2Vzc1Rva2VuID0gZmluZEFjY2Vzc1Rva2VuKGdkLCBtYXBib3hJZHMpO1xuICAgIG1hcGJveGdsLmFjY2Vzc1Rva2VuID0gYWNjZXNzVG9rZW47XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbWFwYm94SWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpZCA9IG1hcGJveElkc1tpXTtcbiAgICAgICAgdmFyIHN1YnBsb3RDYWxjRGF0YSA9IGdldFN1YnBsb3RDYWxjRGF0YShjYWxjRGF0YSwgTUFQQk9YLCBpZCk7XG4gICAgICAgIHZhciBvcHRzID0gZnVsbExheW91dFtpZF07XG4gICAgICAgIHZhciBtYXBib3ggPSBvcHRzLl9zdWJwbG90O1xuXG4gICAgICAgIGlmKCFtYXBib3gpIHtcbiAgICAgICAgICAgIG1hcGJveCA9IG5ldyBNYXBib3goZ2QsIGlkKTtcbiAgICAgICAgICAgIGZ1bGxMYXlvdXRbaWRdLl9zdWJwbG90ID0gbWFwYm94O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW1hcGJveC52aWV3SW5pdGlhbCkge1xuICAgICAgICAgICAgbWFwYm94LnZpZXdJbml0aWFsID0ge1xuICAgICAgICAgICAgICAgIGNlbnRlcjogTGliLmV4dGVuZEZsYXQoe30sIG9wdHMuY2VudGVyKSxcbiAgICAgICAgICAgICAgICB6b29tOiBvcHRzLnpvb20sXG4gICAgICAgICAgICAgICAgYmVhcmluZzogb3B0cy5iZWFyaW5nLFxuICAgICAgICAgICAgICAgIHBpdGNoOiBvcHRzLnBpdGNoXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbWFwYm94LnBsb3Qoc3VicGxvdENhbGNEYXRhLCBmdWxsTGF5b3V0LCBnZC5fcHJvbWlzZXMpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgb2xkTWFwYm94S2V5cyA9IG9sZEZ1bGxMYXlvdXQuX3N1YnBsb3RzW01BUEJPWF0gfHwgW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgb2xkTWFwYm94S2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb2xkTWFwYm94S2V5ID0gb2xkTWFwYm94S2V5c1tpXTtcblxuICAgICAgICBpZighbmV3RnVsbExheW91dFtvbGRNYXBib3hLZXldICYmICEhb2xkRnVsbExheW91dFtvbGRNYXBib3hLZXldLl9zdWJwbG90KSB7XG4gICAgICAgICAgICBvbGRGdWxsTGF5b3V0W29sZE1hcGJveEtleV0uX3N1YnBsb3QuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuZXhwb3J0cy50b1NWRyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VicGxvdElkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW01BUEJPWF07XG4gICAgdmFyIHNpemUgPSBmdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG9wdHMgPSBmdWxsTGF5b3V0W3N1YnBsb3RJZHNbaV1dO1xuICAgICAgICB2YXIgZG9tYWluID0gb3B0cy5kb21haW47XG4gICAgICAgIHZhciBtYXBib3ggPSBvcHRzLl9zdWJwbG90O1xuXG4gICAgICAgIHZhciBpbWFnZURhdGEgPSBtYXBib3gudG9JbWFnZSgncG5nJyk7XG4gICAgICAgIHZhciBpbWFnZSA9IGZ1bGxMYXlvdXQuX2dsaW1hZ2VzLmFwcGVuZCgnc3ZnOmltYWdlJyk7XG5cbiAgICAgICAgaW1hZ2UuYXR0cih7XG4gICAgICAgICAgICB4bWxuczogeG1sbnNOYW1lc3BhY2VzLnN2ZyxcbiAgICAgICAgICAgICd4bGluazpocmVmJzogaW1hZ2VEYXRhLFxuICAgICAgICAgICAgeDogc2l6ZS5sICsgc2l6ZS53ICogZG9tYWluLnhbMF0sXG4gICAgICAgICAgICB5OiBzaXplLnQgKyBzaXplLmggKiAoMSAtIGRvbWFpbi55WzFdKSxcbiAgICAgICAgICAgIHdpZHRoOiBzaXplLncgKiAoZG9tYWluLnhbMV0gLSBkb21haW4ueFswXSksXG4gICAgICAgICAgICBoZWlnaHQ6IHNpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKSxcbiAgICAgICAgICAgIHByZXNlcnZlQXNwZWN0UmF0aW86ICdub25lJ1xuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgc3VicGxvdERpdiA9IGQzLnNlbGVjdChvcHRzLl9zdWJwbG90LmRpdik7XG5cbiAgICAgICAgLy8gQXBwZW5kIGxvZ28gaWYgdmlzaWJsZVxuICAgICAgICB2YXIgaGlkZGVuID0gc3VicGxvdERpdi5zZWxlY3QoJy5tYXBib3hnbC1jdHJsLWxvZ28nKS5ub2RlKCkub2Zmc2V0UGFyZW50ID09PSBudWxsO1xuICAgICAgICBpZighaGlkZGVuKSB7XG4gICAgICAgICAgICB2YXIgbG9nbyA9IGZ1bGxMYXlvdXQuX2dsaW1hZ2VzLmFwcGVuZCgnZycpO1xuICAgICAgICAgICAgbG9nby5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyAoc2l6ZS5sICsgc2l6ZS53ICogZG9tYWluLnhbMF0gKyAxMCkgKyAnLCAnICsgKHNpemUudCArIHNpemUuaCAqICgxIC0gZG9tYWluLnlbMF0pIC0gMzEpICsgJyknKTtcbiAgICAgICAgICAgIGxvZ28uYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgLmF0dHIoJ2QnLCBjb25zdGFudHMubWFwYm94TG9nby5wYXRoMClcbiAgICAgICAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IDAuOSxcbiAgICAgICAgICAgICAgICAgIGZpbGw6ICcjZmZmZmZmJyxcbiAgICAgICAgICAgICAgICAgICdlbmFibGUtYmFja2dyb3VuZCc6ICduZXcnXG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBsb2dvLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAgIC5hdHRyKCdkJywgY29uc3RhbnRzLm1hcGJveExvZ28ucGF0aDEpXG4gICAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDAuMzUpXG4gICAgICAgICAgICAgIC5zdHlsZSgnZW5hYmxlLWJhY2tncm91bmQnLCAnbmV3Jyk7XG5cbiAgICAgICAgICAgIGxvZ28uYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgLmF0dHIoJ2QnLCBjb25zdGFudHMubWFwYm94TG9nby5wYXRoMilcbiAgICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMC4zNSlcbiAgICAgICAgICAgICAgLnN0eWxlKCdlbmFibGUtYmFja2dyb3VuZCcsICduZXcnKTtcblxuICAgICAgICAgICAgbG9nby5hcHBlbmQoJ3BvbHlnb24nKVxuICAgICAgICAgICAgICAuYXR0cigncG9pbnRzJywgY29uc3RhbnRzLm1hcGJveExvZ28ucG9seWdvbilcbiAgICAgICAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IDAuOSxcbiAgICAgICAgICAgICAgICAgIGZpbGw6ICcjZmZmZmZmJyxcbiAgICAgICAgICAgICAgICAgICdlbmFibGUtYmFja2dyb3VuZCc6ICduZXcnXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIGF0dHJpYnV0aW9uc1xuICAgICAgICB2YXIgYXR0cmlidXRpb25zID0gc3VicGxvdERpdlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNlbGVjdCgnLm1hcGJveGdsLWN0cmwtYXR0cmliJykudGV4dCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgnSW1wcm92ZSB0aGlzIG1hcCcsICcnKTtcblxuICAgICAgICB2YXIgYXR0cmlidXRpb25Hcm91cCA9IGZ1bGxMYXlvdXQuX2dsaW1hZ2VzLmFwcGVuZCgnZycpO1xuXG4gICAgICAgIHZhciBhdHRyaWJ1dGlvblRleHQgPSBhdHRyaWJ1dGlvbkdyb3VwLmFwcGVuZCgndGV4dCcpO1xuICAgICAgICBhdHRyaWJ1dGlvblRleHRcbiAgICAgICAgICAudGV4dChhdHRyaWJ1dGlvbnMpXG4gICAgICAgICAgLmNsYXNzZWQoJ3N0YXRpYy1hdHRyaWJ1dGlvbicsIHRydWUpXG4gICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAnZm9udC1zaXplJzogMTIsXG4gICAgICAgICAgICAgICdmb250LWZhbWlseSc6ICdBcmlhbCcsXG4gICAgICAgICAgICAgICdjb2xvcic6ICdyZ2JhKDAsIDAsIDAsIDAuNzUpJyxcbiAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ2VuZCcsXG4gICAgICAgICAgICAgICdkYXRhLXVuZm9ybWF0dGVkJzogYXR0cmlidXRpb25zXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGJCb3ggPSBEcmF3aW5nLmJCb3goYXR0cmlidXRpb25UZXh0Lm5vZGUoKSk7XG5cbiAgICAgICAgLy8gQnJlYWsgaW50byBtdWx0aXBsZSBsaW5lcyB0d2ljZSBsYXJnZXIgdGhhbiBkb21haW5cbiAgICAgICAgdmFyIG1heFdpZHRoID0gc2l6ZS53ICogKGRvbWFpbi54WzFdIC0gZG9tYWluLnhbMF0pO1xuICAgICAgICBpZigoYkJveC53aWR0aCA+IG1heFdpZHRoIC8gMikpIHtcbiAgICAgICAgICAgIHZhciBtdWx0aWxpbmVBdHRyaWJ1dGlvbnMgPSBhdHRyaWJ1dGlvbnMuc3BsaXQoJ3wnKS5qb2luKCc8YnI+Jyk7XG4gICAgICAgICAgICBhdHRyaWJ1dGlvblRleHRcbiAgICAgICAgICAgICAgLnRleHQobXVsdGlsaW5lQXR0cmlidXRpb25zKVxuICAgICAgICAgICAgICAuYXR0cignZGF0YS11bmZvcm1hdHRlZCcsIG11bHRpbGluZUF0dHJpYnV0aW9ucylcbiAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgICAgICBiQm94ID0gRHJhd2luZy5iQm94KGF0dHJpYnV0aW9uVGV4dC5ub2RlKCkpO1xuICAgICAgICB9XG4gICAgICAgIGF0dHJpYnV0aW9uVGV4dC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKC0zLCAnICsgKC1iQm94LmhlaWdodCArIDgpICsgJyknKTtcblxuICAgICAgICAvLyBEcmF3IHdoaXRlIHJlY3RhbmdsZSBiZWhpbmQgdGV4dFxuICAgICAgICBhdHRyaWJ1dGlvbkdyb3VwXG4gICAgICAgICAgLmluc2VydCgncmVjdCcsICcuc3RhdGljLWF0dHJpYnV0aW9uJylcbiAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgIHg6IC1iQm94LndpZHRoIC0gNixcbiAgICAgICAgICAgICAgeTogLWJCb3guaGVpZ2h0IC0gMyxcbiAgICAgICAgICAgICAgd2lkdGg6IGJCb3gud2lkdGggKyA2LFxuICAgICAgICAgICAgICBoZWlnaHQ6IGJCb3guaGVpZ2h0ICsgMyxcbiAgICAgICAgICAgICAgZmlsbDogJ3JnYmEoMjU1LCAyNTUsIDI1NSwgMC43NSknXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU2NhbGUgZG93biBpZiBsYXJnZXIgdGhhbiBkb21haW5cbiAgICAgICAgdmFyIHNjYWxlUmF0aW8gPSAxO1xuICAgICAgICBpZigoYkJveC53aWR0aCArIDYpID4gbWF4V2lkdGgpIHNjYWxlUmF0aW8gPSBtYXhXaWR0aCAvIChiQm94LndpZHRoICsgNik7XG5cbiAgICAgICAgdmFyIG9mZnNldCA9IFsoc2l6ZS5sICsgc2l6ZS53ICogZG9tYWluLnhbMV0pLCAoc2l6ZS50ICsgc2l6ZS5oICogKDEgLSBkb21haW4ueVswXSkpXTtcbiAgICAgICAgYXR0cmlidXRpb25Hcm91cC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBvZmZzZXRbMF0gKyAnLCcgKyBvZmZzZXRbMV0gKyAnKSBzY2FsZSgnICsgc2NhbGVSYXRpbyArICcpJyk7XG4gICAgfVxufTtcblxuLy8gTi5CLiBtYXBib3gtZ2wgb25seSBhbGxvd3Mgb25lIGFjY2Vzc1Rva2VuIHRvIGJlIHNldCBwZXIgcGFnZTpcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXBib3gvbWFwYm94LWdsLWpzL2lzc3Vlcy82MzMxXG5mdW5jdGlvbiBmaW5kQWNjZXNzVG9rZW4oZ2QsIG1hcGJveElkcykge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGNvbnRleHQgPSBnZC5fY29udGV4dDtcblxuICAgIC8vIHNwZWNpYWwgY2FzZSBmb3IgTWFwYm94IEF0bGFzIHVzZXJzXG4gICAgaWYoY29udGV4dC5tYXBib3hBY2Nlc3NUb2tlbiA9PT0gJycpIHJldHVybiAnJztcblxuICAgIHZhciB0b2tlbnNVc2VmdWwgPSBbXTtcbiAgICB2YXIgdG9rZW5zTGlzdGVkID0gW107XG4gICAgdmFyIGhhc09uZVNldE1hcGJveFN0eWxlID0gZmFsc2U7XG4gICAgdmFyIHdvbnRXb3JrID0gZmFsc2U7XG5cbiAgICAvLyBUYWtlIHRoZSBmaXJzdCB0b2tlbiB3ZSBmaW5kIGluIGEgbWFwYm94IHN1YnBsb3QuXG4gICAgLy8gVGhlc2UgZGVmYXVsdCB0byB0aGUgY29udGV4dCB2YWx1ZSBidXQgbWF5IGJlIG92ZXJyaWRkZW4uXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG1hcGJveElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb3B0cyA9IGZ1bGxMYXlvdXRbbWFwYm94SWRzW2ldXTtcbiAgICAgICAgdmFyIHRva2VuID0gb3B0cy5hY2Nlc3N0b2tlbjtcblxuICAgICAgICBpZihpc01hcGJveFN0eWxlKG9wdHMuc3R5bGUpKSB7XG4gICAgICAgICAgICBpZih0b2tlbikge1xuICAgICAgICAgICAgICAgIExpYi5wdXNoVW5pcXVlKHRva2Vuc1VzZWZ1bCwgdG9rZW4pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZihpc01hcGJveFN0eWxlKG9wdHMuX2lucHV0LnN0eWxlKSkge1xuICAgICAgICAgICAgICAgICAgICBMaWIuZXJyb3IoJ1VzZXMgTWFwYm94IG1hcCBzdHlsZSwgYnV0IGRpZCBub3Qgc2V0IGFuIGFjY2VzcyB0b2tlbi4nKTtcbiAgICAgICAgICAgICAgICAgICAgaGFzT25lU2V0TWFwYm94U3R5bGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3b250V29yayA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZih0b2tlbikge1xuICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUodG9rZW5zTGlzdGVkLCB0b2tlbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZih3b250V29yaykge1xuICAgICAgICB2YXIgbXNnID0gaGFzT25lU2V0TWFwYm94U3R5bGUgP1xuICAgICAgICAgICAgY29uc3RhbnRzLm5vQWNjZXNzVG9rZW5FcnJvck1zZyA6XG4gICAgICAgICAgICBjb25zdGFudHMubWlzc2luZ1N0eWxlRXJyb3JNc2c7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgIH1cblxuICAgIGlmKHRva2Vuc1VzZWZ1bC5sZW5ndGgpIHtcbiAgICAgICAgaWYodG9rZW5zVXNlZnVsLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIExpYi53YXJuKGNvbnN0YW50cy5tdWx0aXBsZVRva2Vuc0Vycm9yTXNnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG9rZW5zVXNlZnVsWzBdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKHRva2Vuc0xpc3RlZC5sZW5ndGgpIHtcbiAgICAgICAgICAgIExpYi5sb2coW1xuICAgICAgICAgICAgICAgICdMaXN0ZWQgbWFwYm94IGFjY2VzcyB0b2tlbihzKScsIHRva2Vuc0xpc3RlZC5qb2luKCcsJyksXG4gICAgICAgICAgICAgICAgJ2J1dCBkaWQgbm90IHVzZSBhIE1hcGJveCBtYXAgc3R5bGUsIGlnbm9yaW5nIHRva2VuKHMpLidcbiAgICAgICAgICAgIF0uam9pbignICcpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc01hcGJveFN0eWxlKHMpIHtcbiAgICByZXR1cm4gdHlwZW9mIHMgPT09ICdzdHJpbmcnICYmIGNvbnN0YW50cy5zdHlsZVZhbHVlc01hcGJveC5pbmRleE9mKHMpICE9PSAtMTtcbn1cblxuZXhwb3J0cy51cGRhdGVGeCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3VicGxvdElkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW01BUEJPWF07XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc3VicGxvdElkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc3VicGxvdE9iaiA9IGZ1bGxMYXlvdXRbc3VicGxvdElkc1tpXV0uX3N1YnBsb3Q7XG4gICAgICAgIHN1YnBsb3RPYmoudXBkYXRlRngoZnVsbExheW91dCk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlc1wiOjY5NixcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3Bsb3RzL2dldF9kYXRhXCI6ODAyLFwiLi9jb25zdGFudHNcIjo4MjAsXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6ODI0LFwiLi9sYXlvdXRfZGVmYXVsdHNcIjo4MjUsXCIuL21hcGJveFwiOjgyNixcImQzXCI6MTYzLFwibWFwYm94LWdsXCI6NDI2fV0sODIzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGNvbnZlcnRUZXh0T3B0cyA9IF9kZXJlcV8oJy4vY29udmVydF90ZXh0X29wdHMnKTtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xuXG5mdW5jdGlvbiBNYXBib3hMYXllcihzdWJwbG90LCBpbmRleCkge1xuICAgIHRoaXMuc3VicGxvdCA9IHN1YnBsb3Q7XG5cbiAgICB0aGlzLnVpZCA9IHN1YnBsb3QudWlkICsgJy0nICsgaW5kZXg7XG4gICAgdGhpcy5pbmRleCA9IGluZGV4O1xuXG4gICAgdGhpcy5pZFNvdXJjZSA9ICdzb3VyY2UtJyArIHRoaXMudWlkO1xuICAgIHRoaXMuaWRMYXllciA9IGNvbnN0YW50cy5sYXlvdXRMYXllclByZWZpeCArIHRoaXMudWlkO1xuXG4gICAgLy8gc29tZSBzdGF0ZSB2YXJpYWJsZSB0byBjaGVjayBpZiBhIHJlbW92ZS9hZGQgc3RlcCBpcyBuZWVkZWRcbiAgICB0aGlzLnNvdXJjZVR5cGUgPSBudWxsO1xuICAgIHRoaXMuc291cmNlID0gbnVsbDtcbiAgICB0aGlzLmxheWVyVHlwZSA9IG51bGw7XG4gICAgdGhpcy5iZWxvdyA9IG51bGw7XG5cbiAgICAvLyBpcyBsYXllciBjdXJyZW50bHkgdmlzaWJsZVxuICAgIHRoaXMudmlzaWJsZSA9IGZhbHNlO1xufVxuXG52YXIgcHJvdG8gPSBNYXBib3hMYXllci5wcm90b3R5cGU7XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShvcHRzKSB7XG4gICAgaWYoIXRoaXMudmlzaWJsZSkge1xuICAgICAgICAvLyBJTVBPUlRBTlQ6IG11c3QgY3JlYXRlIHNvdXJjZSBiZWZvcmUgbGF5ZXIgdG8gbm90IGNhdXNlIGVycm9yc1xuICAgICAgICB0aGlzLnVwZGF0ZVNvdXJjZShvcHRzKTtcbiAgICAgICAgdGhpcy51cGRhdGVMYXllcihvcHRzKTtcbiAgICB9IGVsc2UgaWYodGhpcy5uZWVkc05ld1NvdXJjZShvcHRzKSkge1xuICAgICAgICAvLyBJTVBPUlRBTlQ6IG11c3QgZGVsZXRlIGxheWVyIGJlZm9yZSBzb3VyY2UgdG8gbm90IGNhdXNlIGVycm9yc1xuICAgICAgICB0aGlzLnJlbW92ZUxheWVyKCk7XG4gICAgICAgIHRoaXMudXBkYXRlU291cmNlKG9wdHMpO1xuICAgICAgICB0aGlzLnVwZGF0ZUxheWVyKG9wdHMpO1xuICAgIH0gZWxzZSBpZih0aGlzLm5lZWRzTmV3TGF5ZXIob3B0cykpIHtcbiAgICAgICAgdGhpcy51cGRhdGVMYXllcihvcHRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnVwZGF0ZVN0eWxlKG9wdHMpO1xuICAgIH1cblxuICAgIHRoaXMudmlzaWJsZSA9IGlzVmlzaWJsZShvcHRzKTtcbn07XG5cbnByb3RvLm5lZWRzTmV3U291cmNlID0gZnVuY3Rpb24ob3B0cykge1xuICAgIC8vIGZvciBzb21lIHJlYXNvbiBjaGFuZ2luZyBsYXllciB0byAnZmlsbCcgb3IgJ3N5bWJvbCdcbiAgICAvLyB3L28gY2hhbmdpbmcgdGhlIHNvdXJjZSB0aHJvd3MgYW4gZXhjZXB0aW9uIGluIG1hcGJveC1nbCAwLjE4IDtcbiAgICAvLyBzdGF5IHNhZmUgYW5kIG1ha2UgbmV3IHNvdXJjZSBvbiB0eXBlIGNoYW5nZXNcbiAgICByZXR1cm4gKFxuICAgICAgICB0aGlzLnNvdXJjZVR5cGUgIT09IG9wdHMuc291cmNldHlwZSB8fFxuICAgICAgICB0aGlzLnNvdXJjZSAhPT0gb3B0cy5zb3VyY2UgfHxcbiAgICAgICAgdGhpcy5sYXllclR5cGUgIT09IG9wdHMudHlwZVxuICAgICk7XG59O1xuXG5wcm90by5uZWVkc05ld0xheWVyID0gZnVuY3Rpb24ob3B0cykge1xuICAgIHJldHVybiAoXG4gICAgICAgIHRoaXMubGF5ZXJUeXBlICE9PSBvcHRzLnR5cGUgfHxcbiAgICAgICAgdGhpcy5iZWxvdyAhPT0gdGhpcy5zdWJwbG90LmJlbG93TG9va3VwWydsYXlvdXQtJyArIHRoaXMuaW5kZXhdXG4gICAgKTtcbn07XG5cbnByb3RvLnVwZGF0ZVNvdXJjZSA9IGZ1bmN0aW9uKG9wdHMpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5zdWJwbG90Lm1hcDtcblxuICAgIGlmKG1hcC5nZXRTb3VyY2UodGhpcy5pZFNvdXJjZSkpIG1hcC5yZW1vdmVTb3VyY2UodGhpcy5pZFNvdXJjZSk7XG5cbiAgICB0aGlzLnNvdXJjZVR5cGUgPSBvcHRzLnNvdXJjZXR5cGU7XG4gICAgdGhpcy5zb3VyY2UgPSBvcHRzLnNvdXJjZTtcblxuICAgIGlmKCFpc1Zpc2libGUob3B0cykpIHJldHVybjtcblxuICAgIHZhciBzb3VyY2VPcHRzID0gY29udmVydFNvdXJjZU9wdHMob3B0cyk7XG5cbiAgICBtYXAuYWRkU291cmNlKHRoaXMuaWRTb3VyY2UsIHNvdXJjZU9wdHMpO1xufTtcblxucHJvdG8udXBkYXRlTGF5ZXIgPSBmdW5jdGlvbihvcHRzKSB7XG4gICAgdmFyIHN1YnBsb3QgPSB0aGlzLnN1YnBsb3Q7XG4gICAgdmFyIGNvbnZlcnRlZE9wdHMgPSBjb252ZXJ0T3B0cyhvcHRzKTtcblxuICAgIHZhciBiZWxvdyA9IHRoaXMuc3VicGxvdC5iZWxvd0xvb2t1cFsnbGF5b3V0LScgKyB0aGlzLmluZGV4XTtcbiAgICB2YXIgX2JlbG93O1xuXG4gICAgaWYoYmVsb3cgPT09ICd0cmFjZXMnKSB7XG4gICAgICAgIHZhciBtYXBMYXllcnMgPSBzdWJwbG90LmdldE1hcExheWVycygpO1xuXG4gICAgICAgIC8vIGZpbmQgaWQgb2YgZmlyc3QgcGxvdGx5IHRyYWNlIGxheWVyXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBtYXBMYXllcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBsYXllcklkID0gbWFwTGF5ZXJzW2ldLmlkO1xuICAgICAgICAgICAgaWYodHlwZW9mIGxheWVySWQgPT09ICdzdHJpbmcnICYmXG4gICAgICAgICAgICAgICAgbGF5ZXJJZC5pbmRleE9mKGNvbnN0YW50cy50cmFjZUxheWVyUHJlZml4KSA9PT0gMFxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgX2JlbG93ID0gbGF5ZXJJZDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIF9iZWxvdyA9IGJlbG93O1xuICAgIH1cblxuICAgIHRoaXMucmVtb3ZlTGF5ZXIoKTtcblxuICAgIGlmKGlzVmlzaWJsZShvcHRzKSkge1xuICAgICAgICBzdWJwbG90LmFkZExheWVyKHtcbiAgICAgICAgICAgIGlkOiB0aGlzLmlkTGF5ZXIsXG4gICAgICAgICAgICBzb3VyY2U6IHRoaXMuaWRTb3VyY2UsXG4gICAgICAgICAgICAnc291cmNlLWxheWVyJzogb3B0cy5zb3VyY2VsYXllciB8fCAnJyxcbiAgICAgICAgICAgIHR5cGU6IG9wdHMudHlwZSxcbiAgICAgICAgICAgIG1pbnpvb206IG9wdHMubWluem9vbSxcbiAgICAgICAgICAgIG1heHpvb206IG9wdHMubWF4em9vbSxcbiAgICAgICAgICAgIGxheW91dDogY29udmVydGVkT3B0cy5sYXlvdXQsXG4gICAgICAgICAgICBwYWludDogY29udmVydGVkT3B0cy5wYWludFxuICAgICAgICB9LCBfYmVsb3cpO1xuICAgIH1cblxuICAgIHRoaXMubGF5ZXJUeXBlID0gb3B0cy50eXBlO1xuICAgIHRoaXMuYmVsb3cgPSBiZWxvdztcbn07XG5cbnByb3RvLnVwZGF0ZVN0eWxlID0gZnVuY3Rpb24ob3B0cykge1xuICAgIGlmKGlzVmlzaWJsZShvcHRzKSkge1xuICAgICAgICB2YXIgY29udmVydGVkT3B0cyA9IGNvbnZlcnRPcHRzKG9wdHMpO1xuICAgICAgICB0aGlzLnN1YnBsb3Quc2V0T3B0aW9ucyh0aGlzLmlkTGF5ZXIsICdzZXRMYXlvdXRQcm9wZXJ0eScsIGNvbnZlcnRlZE9wdHMubGF5b3V0KTtcbiAgICAgICAgdGhpcy5zdWJwbG90LnNldE9wdGlvbnModGhpcy5pZExheWVyLCAnc2V0UGFpbnRQcm9wZXJ0eScsIGNvbnZlcnRlZE9wdHMucGFpbnQpO1xuICAgIH1cbn07XG5cbnByb3RvLnJlbW92ZUxheWVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1hcCA9IHRoaXMuc3VicGxvdC5tYXA7XG4gICAgaWYobWFwLmdldExheWVyKHRoaXMuaWRMYXllcikpIHtcbiAgICAgICAgbWFwLnJlbW92ZUxheWVyKHRoaXMuaWRMYXllcik7XG4gICAgfVxufTtcblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBtYXAgPSB0aGlzLnN1YnBsb3QubWFwO1xuICAgIG1hcC5yZW1vdmVMYXllcih0aGlzLmlkTGF5ZXIpO1xuICAgIG1hcC5yZW1vdmVTb3VyY2UodGhpcy5pZFNvdXJjZSk7XG59O1xuXG5mdW5jdGlvbiBpc1Zpc2libGUob3B0cykge1xuICAgIHZhciBzb3VyY2UgPSBvcHRzLnNvdXJjZTtcblxuICAgIHJldHVybiBvcHRzLnZpc2libGUgJiYgKFxuICAgICAgICBMaWIuaXNQbGFpbk9iamVjdChzb3VyY2UpIHx8XG4gICAgICAgICgodHlwZW9mIHNvdXJjZSA9PT0gJ3N0cmluZycgfHwgQXJyYXkuaXNBcnJheShzb3VyY2UpKSAmJiBzb3VyY2UubGVuZ3RoID4gMClcbiAgICApO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0T3B0cyhvcHRzKSB7XG4gICAgdmFyIGxheW91dCA9IHt9O1xuICAgIHZhciBwYWludCA9IHt9O1xuXG4gICAgc3dpdGNoKG9wdHMudHlwZSkge1xuICAgICAgICBjYXNlICdjaXJjbGUnOlxuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQocGFpbnQsIHtcbiAgICAgICAgICAgICAgICAnY2lyY2xlLXJhZGl1cyc6IG9wdHMuY2lyY2xlLnJhZGl1cyxcbiAgICAgICAgICAgICAgICAnY2lyY2xlLWNvbG9yJzogb3B0cy5jb2xvcixcbiAgICAgICAgICAgICAgICAnY2lyY2xlLW9wYWNpdHknOiBvcHRzLm9wYWNpdHlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnbGluZSc6XG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChwYWludCwge1xuICAgICAgICAgICAgICAgICdsaW5lLXdpZHRoJzogb3B0cy5saW5lLndpZHRoLFxuICAgICAgICAgICAgICAgICdsaW5lLWNvbG9yJzogb3B0cy5jb2xvcixcbiAgICAgICAgICAgICAgICAnbGluZS1vcGFjaXR5Jzogb3B0cy5vcGFjaXR5LFxuICAgICAgICAgICAgICAgICdsaW5lLWRhc2hhcnJheSc6IG9wdHMubGluZS5kYXNoXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgJ2ZpbGwnOlxuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQocGFpbnQsIHtcbiAgICAgICAgICAgICAgICAnZmlsbC1jb2xvcic6IG9wdHMuY29sb3IsXG4gICAgICAgICAgICAgICAgJ2ZpbGwtb3V0bGluZS1jb2xvcic6IG9wdHMuZmlsbC5vdXRsaW5lY29sb3IsXG4gICAgICAgICAgICAgICAgJ2ZpbGwtb3BhY2l0eSc6IG9wdHMub3BhY2l0eVxuXG4gICAgICAgICAgICAgICAgLy8gbm8gd2F5IHRvIHBhc3Mgc3BlY2lmeSBvdXRsaW5lIHdpZHRoIGF0IHRoZSBtb21lbnRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnc3ltYm9sJzpcbiAgICAgICAgICAgIHZhciBzeW1ib2wgPSBvcHRzLnN5bWJvbDtcbiAgICAgICAgICAgIHZhciB0ZXh0T3B0cyA9IGNvbnZlcnRUZXh0T3B0cyhzeW1ib2wudGV4dHBvc2l0aW9uLCBzeW1ib2wuaWNvbnNpemUpO1xuXG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChsYXlvdXQsIHtcbiAgICAgICAgICAgICAgICAnaWNvbi1pbWFnZSc6IHN5bWJvbC5pY29uICsgJy0xNScsXG4gICAgICAgICAgICAgICAgJ2ljb24tc2l6ZSc6IHN5bWJvbC5pY29uc2l6ZSAvIDEwLFxuXG4gICAgICAgICAgICAgICAgJ3RleHQtZmllbGQnOiBzeW1ib2wudGV4dCxcbiAgICAgICAgICAgICAgICAndGV4dC1zaXplJzogc3ltYm9sLnRleHRmb250LnNpemUsXG4gICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogdGV4dE9wdHMuYW5jaG9yLFxuICAgICAgICAgICAgICAgICd0ZXh0LW9mZnNldCc6IHRleHRPcHRzLm9mZnNldCxcbiAgICAgICAgICAgICAgICAnc3ltYm9sLXBsYWNlbWVudCc6IHN5bWJvbC5wbGFjZW1lbnQsXG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPIGZvbnQgZmFtaWx5XG4gICAgICAgICAgICAgICAgLy8gJ3RleHQtZm9udCc6IHN5bWJvbC50ZXh0Zm9udC5mYW1pbHkuc3BsaXQoJywgJyksXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQocGFpbnQsIHtcbiAgICAgICAgICAgICAgICAnaWNvbi1jb2xvcic6IG9wdHMuY29sb3IsXG4gICAgICAgICAgICAgICAgJ3RleHQtY29sb3InOiBzeW1ib2wudGV4dGZvbnQuY29sb3IsXG4gICAgICAgICAgICAgICAgJ3RleHQtb3BhY2l0eSc6IG9wdHMub3BhY2l0eVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBsYXlvdXQ6IGxheW91dCxcbiAgICAgICAgcGFpbnQ6IHBhaW50XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY29udmVydFNvdXJjZU9wdHMob3B0cykge1xuICAgIHZhciBzb3VyY2VUeXBlID0gb3B0cy5zb3VyY2V0eXBlO1xuICAgIHZhciBzb3VyY2UgPSBvcHRzLnNvdXJjZTtcbiAgICB2YXIgc291cmNlT3B0cyA9IHt0eXBlOiBzb3VyY2VUeXBlfTtcbiAgICB2YXIgZmllbGQ7XG5cbiAgICBpZihzb3VyY2VUeXBlID09PSAnZ2VvanNvbicpIHtcbiAgICAgICAgZmllbGQgPSAnZGF0YSc7XG4gICAgfSBlbHNlIGlmKHNvdXJjZVR5cGUgPT09ICd2ZWN0b3InKSB7XG4gICAgICAgIGZpZWxkID0gdHlwZW9mIHNvdXJjZSA9PT0gJ3N0cmluZycgPyAndXJsJyA6ICd0aWxlcyc7XG4gICAgfSBlbHNlIGlmKHNvdXJjZVR5cGUgPT09ICdyYXN0ZXInKSB7XG4gICAgICAgIGZpZWxkID0gJ3RpbGVzJztcbiAgICAgICAgc291cmNlT3B0cy50aWxlU2l6ZSA9IDI1NjtcbiAgICB9IGVsc2UgaWYoc291cmNlVHlwZSA9PT0gJ2ltYWdlJykge1xuICAgICAgICBmaWVsZCA9ICd1cmwnO1xuICAgICAgICBzb3VyY2VPcHRzLmNvb3JkaW5hdGVzID0gb3B0cy5jb29yZGluYXRlcztcbiAgICB9XG5cbiAgICBzb3VyY2VPcHRzW2ZpZWxkXSA9IHNvdXJjZTtcblxuICAgIGlmKG9wdHMuc291cmNlYXR0cmlidXRpb24pIHNvdXJjZU9wdHMuYXR0cmlidXRpb24gPSBvcHRzLnNvdXJjZWF0dHJpYnV0aW9uO1xuXG4gICAgcmV0dXJuIHNvdXJjZU9wdHM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3JlYXRlTWFwYm94TGF5ZXIoc3VicGxvdCwgaW5kZXgsIG9wdHMpIHtcbiAgICB2YXIgbWFwYm94TGF5ZXIgPSBuZXcgTWFwYm94TGF5ZXIoc3VicGxvdCwgaW5kZXgpO1xuXG4gICAgbWFwYm94TGF5ZXIudXBkYXRlKG9wdHMpO1xuXG4gICAgcmV0dXJuIG1hcGJveExheWVyO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuL2NvbnN0YW50c1wiOjgyMCxcIi4vY29udmVydF90ZXh0X29wdHNcIjo4MjF9XSw4MjQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgZGVmYXVsdExpbmUgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJykuZGVmYXVsdExpbmU7XG52YXIgZG9tYWluQXR0cnMgPSBfZGVyZXFfKCcuLi9kb21haW4nKS5hdHRyaWJ1dGVzO1xudmFyIGZvbnRBdHRycyA9IF9kZXJlcV8oJy4uL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIHRleHRwb3NpdGlvbiA9IF9kZXJlcV8oJy4uLy4uL3RyYWNlcy9zY2F0dGVyL2F0dHJpYnV0ZXMnKS50ZXh0cG9zaXRpb247XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG52YXIgdGVtcGxhdGVkQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykudGVtcGxhdGVkQXJyYXk7XG5cbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xuXG52YXIgZm9udEF0dHIgPSBmb250QXR0cnMoe1xuICAgIFxufSk7XG5mb250QXR0ci5mYW1pbHkuZGZsdCA9ICdPcGVuIFNhbnMgUmVndWxhciwgQXJpYWwgVW5pY29kZSBNUyBSZWd1bGFyJztcblxudmFyIGF0dHJzID0gbW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4gICAgX2FycmF5QXR0clJlZ2V4cHM6IFtMaWIuY291bnRlclJlZ2V4KCdtYXBib3gnLCAnLmxheWVycycsIHRydWUpXSxcblxuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICdtYXBib3gnfSksXG5cbiAgICBhY2Nlc3N0b2tlbjoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgbm9CbGFuazogdHJ1ZSxcbiAgICAgICAgc3RyaWN0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBzdHlsZToge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgdmFsdWVzOiBjb25zdGFudHMuc3R5bGVWYWx1ZXNNYXBib3guY29uY2F0KGNvbnN0YW50cy5zdHlsZVZhbHVlc05vbk1hcGJveCksXG4gICAgICAgIGRmbHQ6IGNvbnN0YW50cy5zdHlsZVZhbHVlRGZsdCxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBjZW50ZXI6IHtcbiAgICAgICAgbG9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGRmbHQ6IDAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBsYXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9LFxuICAgIHpvb206IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGJlYXJpbmc6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHBpdGNoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGxheWVyczogdGVtcGxhdGVkQXJyYXkoJ2xheWVyJywge1xuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc291cmNldHlwZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2dlb2pzb24nLCAndmVjdG9yJywgJ3Jhc3RlcicsICdpbWFnZSddLFxuICAgICAgICAgICAgZGZsdDogJ2dlb2pzb24nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBzb3VyY2U6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBzb3VyY2VsYXllcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgc291cmNlYXR0cmlidXRpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICB0eXBlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnY2lyY2xlJywgJ2xpbmUnLCAnZmlsbCcsICdzeW1ib2wnLCAncmFzdGVyJ10sXG4gICAgICAgICAgICBkZmx0OiAnY2lyY2xlJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgY29vcmRpbmF0ZXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICAvLyBhdHRyaWJ1dGVzIHNoYXJlZCBiZXR3ZWVuIGFsbCB0eXBlc1xuICAgICAgICBiZWxvdzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIGRmbHQ6IGRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgb3BhY2l0eToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbWluem9vbToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDI0LFxuICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIG1heHpvb206IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAyNCxcbiAgICAgICAgICAgIGRmbHQ6IDI0LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICAvLyB0eXBlLXNwZWNpZmljIHN0eWxlIGF0dHJpYnV0ZXNcbiAgICAgICAgY2lyY2xlOiB7XG4gICAgICAgICAgICByYWRpdXM6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBkZmx0OiAxNSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBsaW5lOiB7XG4gICAgICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIGRmbHQ6IDIsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGFzaDoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBmaWxsOiB7XG4gICAgICAgICAgICBvdXRsaW5lY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIGRmbHQ6IGRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIHN5bWJvbDoge1xuICAgICAgICAgICAgaWNvbjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICdtYXJrZXInLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGljb25zaXplOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgZGZsdDogMTAsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGV4dDoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBsYWNlbWVudDoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgICAgICB2YWx1ZXM6IFsncG9pbnQnLCAnbGluZScsICdsaW5lLWNlbnRlciddLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICdwb2ludCcsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGV4dGZvbnQ6IGZvbnRBdHRyLFxuICAgICAgICAgICAgdGV4dHBvc2l0aW9uOiBMaWIuZXh0ZW5kRmxhdCh7fSwgdGV4dHBvc2l0aW9uLCB7IGFycmF5T2s6IGZhbHNlIH0pXG4gICAgICAgIH1cbiAgICB9KVxufSwgJ3Bsb3QnLCAnZnJvbS1yb290Jyk7XG5cbi8vIHNldCB1aXJldmlzaW9uIG91dHNpZGUgb2Ygb3ZlcnJpZGVBbGwgc28gaXQgY2FuIGJlIGBlZGl0VHlwZTogJ25vbmUnYFxuYXR0cnMudWlyZXZpc2lvbiA9IHtcbiAgICB2YWxUeXBlOiAnYW55JyxcbiAgICBcbiAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgIFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlc1wiOjc1MCxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi90cmFjZXMvc2NhdHRlci9hdHRyaWJ1dGVzXCI6MTExMixcIi4uL2RvbWFpblwiOjc5MixcIi4uL2ZvbnRfYXR0cmlidXRlc1wiOjc5MyxcIi4vY29uc3RhbnRzXCI6ODIwfV0sODI1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgaGFuZGxlU3VicGxvdERlZmF1bHRzID0gX2RlcmVxXygnLi4vc3VicGxvdF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICBoYW5kbGVTdWJwbG90RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEsIHtcbiAgICAgICAgdHlwZTogJ21hcGJveCcsXG4gICAgICAgIGF0dHJpYnV0ZXM6IGxheW91dEF0dHJpYnV0ZXMsXG4gICAgICAgIGhhbmRsZURlZmF1bHRzOiBoYW5kbGVEZWZhdWx0cyxcbiAgICAgICAgcGFydGl0aW9uOiAneScsXG4gICAgICAgIGFjY2Vzc1Rva2VuOiBsYXlvdXRPdXQuX21hcGJveEFjY2Vzc1Rva2VuXG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBoYW5kbGVEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsIG9wdHMpIHtcbiAgICBjb2VyY2UoJ2FjY2Vzc3Rva2VuJywgb3B0cy5hY2Nlc3NUb2tlbik7XG4gICAgY29lcmNlKCdzdHlsZScpO1xuICAgIGNvZXJjZSgnY2VudGVyLmxvbicpO1xuICAgIGNvZXJjZSgnY2VudGVyLmxhdCcpO1xuICAgIGNvZXJjZSgnem9vbScpO1xuICAgIGNvZXJjZSgnYmVhcmluZycpO1xuICAgIGNvZXJjZSgncGl0Y2gnKTtcblxuICAgIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwge1xuICAgICAgICBuYW1lOiAnbGF5ZXJzJyxcbiAgICAgICAgaGFuZGxlSXRlbURlZmF1bHRzOiBoYW5kbGVMYXllckRlZmF1bHRzXG4gICAgfSk7XG5cbiAgICAvLyBjb3B5IHJlZiB0byBpbnB1dCBjb250YWluZXIgdG8gdXBkYXRlICdjZW50ZXInIGFuZCAnem9vbScgb24gbWFwIG1vdmVcbiAgICBjb250YWluZXJPdXQuX2lucHV0ID0gY29udGFpbmVySW47XG59XG5cbmZ1bmN0aW9uIGhhbmRsZUxheWVyRGVmYXVsdHMobGF5ZXJJbiwgbGF5ZXJPdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShsYXllckluLCBsYXllck91dCwgbGF5b3V0QXR0cmlidXRlcy5sYXllcnMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciB2aXNpYmxlID0gY29lcmNlKCd2aXNpYmxlJyk7XG4gICAgaWYodmlzaWJsZSkge1xuICAgICAgICB2YXIgc291cmNlVHlwZSA9IGNvZXJjZSgnc291cmNldHlwZScpO1xuICAgICAgICB2YXIgbXVzdEJlUmFzdGVyTGF5ZXIgPSBzb3VyY2VUeXBlID09PSAncmFzdGVyJyB8fCBzb3VyY2VUeXBlID09PSAnaW1hZ2UnO1xuXG4gICAgICAgIGNvZXJjZSgnc291cmNlJyk7XG4gICAgICAgIGNvZXJjZSgnc291cmNlYXR0cmlidXRpb24nKTtcblxuICAgICAgICBpZihzb3VyY2VUeXBlID09PSAndmVjdG9yJykge1xuICAgICAgICAgICAgY29lcmNlKCdzb3VyY2VsYXllcicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoc291cmNlVHlwZSA9PT0gJ2ltYWdlJykge1xuICAgICAgICAgICAgY29lcmNlKCdjb29yZGluYXRlcycpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHR5cGVEZmx0O1xuICAgICAgICBpZihtdXN0QmVSYXN0ZXJMYXllcikgdHlwZURmbHQgPSAncmFzdGVyJztcblxuICAgICAgICB2YXIgdHlwZSA9IGNvZXJjZSgndHlwZScsIHR5cGVEZmx0KTtcblxuICAgICAgICBpZihtdXN0QmVSYXN0ZXJMYXllciAmJiB0eXBlICE9PSAncmFzdGVyJykge1xuICAgICAgICAgICAgdHlwZSA9IGxheWVyT3V0LnR5cGUgPSAncmFzdGVyJztcbiAgICAgICAgICAgIExpYi5sb2coJ1NvdXJjZSB0eXBlcyAqcmFzdGVyKiBhbmQgKmltYWdlKiBtdXN0IGRyYXduICpyYXN0ZXIqIGxheWVyIHR5cGUuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb2VyY2UoJ2JlbG93Jyk7XG4gICAgICAgIGNvZXJjZSgnY29sb3InKTtcbiAgICAgICAgY29lcmNlKCdvcGFjaXR5Jyk7XG4gICAgICAgIGNvZXJjZSgnbWluem9vbScpO1xuICAgICAgICBjb2VyY2UoJ21heHpvb20nKTtcblxuICAgICAgICBpZih0eXBlID09PSAnY2lyY2xlJykge1xuICAgICAgICAgICAgY29lcmNlKCdjaXJjbGUucmFkaXVzJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0eXBlID09PSAnbGluZScpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnbGluZS53aWR0aCcpO1xuICAgICAgICAgICAgY29lcmNlKCdsaW5lLmRhc2gnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHR5cGUgPT09ICdmaWxsJykge1xuICAgICAgICAgICAgY29lcmNlKCdmaWxsLm91dGxpbmVjb2xvcicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodHlwZSA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnc3ltYm9sLmljb24nKTtcbiAgICAgICAgICAgIGNvZXJjZSgnc3ltYm9sLmljb25zaXplJyk7XG5cbiAgICAgICAgICAgIGNvZXJjZSgnc3ltYm9sLnRleHQnKTtcbiAgICAgICAgICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3N5bWJvbC50ZXh0Zm9udCcpO1xuICAgICAgICAgICAgY29lcmNlKCdzeW1ib2wudGV4dHBvc2l0aW9uJyk7XG4gICAgICAgICAgICBjb2VyY2UoJ3N5bWJvbC5wbGFjZW1lbnQnKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi9hcnJheV9jb250YWluZXJfZGVmYXVsdHNcIjo3NjMsXCIuLi9zdWJwbG90X2RlZmF1bHRzXCI6ODQyLFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjgyNH1dLDgyNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qIGdsb2JhbCBQbG90bHlHZW9Bc3NldHM6ZmFsc2UgKi9cblxudmFyIG1hcGJveGdsID0gX2RlcmVxXygnbWFwYm94LWdsJyk7XG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGRyYWdFbGVtZW50ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmFnZWxlbWVudCcpO1xudmFyIHByZXBTZWxlY3QgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vc2VsZWN0JykucHJlcFNlbGVjdDtcbnZhciBzZWxlY3RPbkNsaWNrID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL3NlbGVjdCcpLnNlbGVjdE9uQ2xpY2s7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcbnZhciBjcmVhdGVNYXBib3hMYXllciA9IF9kZXJlcV8oJy4vbGF5ZXJzJyk7XG5cbmZ1bmN0aW9uIE1hcGJveChnZCwgaWQpIHtcbiAgICB0aGlzLmlkID0gaWQ7XG4gICAgdGhpcy5nZCA9IGdkO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY29udGV4dCA9IGdkLl9jb250ZXh0O1xuXG4gICAgdGhpcy5jb250YWluZXIgPSBmdWxsTGF5b3V0Ll9nbGNvbnRhaW5lci5ub2RlKCk7XG4gICAgdGhpcy5pc1N0YXRpYyA9IGNvbnRleHQuc3RhdGljUGxvdDtcblxuICAgIC8vIHVuaXF1ZSBpZCBmb3IgdGhpcyBNYXBib3ggaW5zdGFuY2VcbiAgICB0aGlzLnVpZCA9IGZ1bGxMYXlvdXQuX3VpZCArICctJyArIHRoaXMuaWQ7XG5cbiAgICAvLyBjcmVhdGUgZnJhbWV3b3JrIG9uIGluc3RhbnRpYXRpb24gZm9yIGEgc21vb3RoZXIgZmlyc3QgcGxvdCBjYWxsXG4gICAgdGhpcy5kaXYgPSBudWxsO1xuICAgIHRoaXMueGF4aXMgPSBudWxsO1xuICAgIHRoaXMueWF4aXMgPSBudWxsO1xuICAgIHRoaXMuY3JlYXRlRnJhbWV3b3JrKGZ1bGxMYXlvdXQpO1xuXG4gICAgLy8gc3RhdGUgdmFyaWFibGVzIHVzZWQgdG8gaW5mZXIgaG93IGFuZCB3aGF0IHRvIHVwZGF0ZVxuICAgIHRoaXMubWFwID0gbnVsbDtcbiAgICB0aGlzLmFjY2Vzc1Rva2VuID0gbnVsbDtcbiAgICB0aGlzLnN0eWxlT2JqID0gbnVsbDtcbiAgICB0aGlzLnRyYWNlSGFzaCA9IHt9O1xuICAgIHRoaXMubGF5ZXJMaXN0ID0gW107XG4gICAgdGhpcy5iZWxvd0xvb2t1cCA9IHt9O1xufVxuXG52YXIgcHJvdG8gPSBNYXBib3gucHJvdG90eXBlO1xuXG5wcm90by5wbG90ID0gZnVuY3Rpb24oY2FsY0RhdGEsIGZ1bGxMYXlvdXQsIHByb21pc2VzKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBvcHRzID0gZnVsbExheW91dFtzZWxmLmlkXTtcblxuICAgIC8vIHJlbW92ZSBtYXAgYW5kIGNyZWF0ZSBhIG5ldyBtYXAgaWYgYWNjZXNzIHRva2VuIGhhcyBjaGFuZ2VcbiAgICBpZihzZWxmLm1hcCAmJiAob3B0cy5hY2Nlc3N0b2tlbiAhPT0gc2VsZi5hY2Nlc3NUb2tlbikpIHtcbiAgICAgICAgc2VsZi5tYXAucmVtb3ZlKCk7XG4gICAgICAgIHNlbGYubWFwID0gbnVsbDtcbiAgICAgICAgc2VsZi5zdHlsZU9iaiA9IG51bGw7XG4gICAgICAgIHNlbGYudHJhY2VIYXNoID0gW107XG4gICAgICAgIHNlbGYubGF5ZXJMaXN0ID0ge307XG4gICAgfVxuXG4gICAgdmFyIHByb21pc2U7XG5cbiAgICBpZighc2VsZi5tYXApIHtcbiAgICAgICAgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgc2VsZi5jcmVhdGVNYXAoY2FsY0RhdGEsIGZ1bGxMYXlvdXQsIHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIHNlbGYudXBkYXRlTWFwKGNhbGNEYXRhLCBmdWxsTGF5b3V0LCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcm9taXNlcy5wdXNoKHByb21pc2UpO1xufTtcblxucHJvdG8uY3JlYXRlTWFwID0gZnVuY3Rpb24oY2FsY0RhdGEsIGZ1bGxMYXlvdXQsIHJlc29sdmUsIHJlamVjdCkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB2YXIgb3B0cyA9IGZ1bGxMYXlvdXRbc2VsZi5pZF07XG5cbiAgICAvLyBzdG9yZSBzdHlsZSBpZCBhbmQgVVJMIG9yIG9iamVjdFxuICAgIHZhciBzdHlsZU9iaiA9IHNlbGYuc3R5bGVPYmogPSBnZXRTdHlsZU9iaihvcHRzLnN0eWxlKTtcblxuICAgIC8vIHN0b3JlIGFjY2VzcyB0b2tlbiBhc3NvY2lhdGVkIHdpdGggdGhpcyBtYXBcbiAgICBzZWxmLmFjY2Vzc1Rva2VuID0gb3B0cy5hY2Nlc3N0b2tlbjtcblxuICAgIC8vIGNyZWF0ZSB0aGUgbWFwIVxuICAgIHZhciBtYXAgPSBzZWxmLm1hcCA9IG5ldyBtYXBib3hnbC5NYXAoe1xuICAgICAgICBjb250YWluZXI6IHNlbGYuZGl2LFxuXG4gICAgICAgIHN0eWxlOiBzdHlsZU9iai5zdHlsZSxcbiAgICAgICAgY2VudGVyOiBjb252ZXJ0Q2VudGVyKG9wdHMuY2VudGVyKSxcbiAgICAgICAgem9vbTogb3B0cy56b29tLFxuICAgICAgICBiZWFyaW5nOiBvcHRzLmJlYXJpbmcsXG4gICAgICAgIHBpdGNoOiBvcHRzLnBpdGNoLFxuXG4gICAgICAgIGludGVyYWN0aXZlOiAhc2VsZi5pc1N0YXRpYyxcbiAgICAgICAgcHJlc2VydmVEcmF3aW5nQnVmZmVyOiBzZWxmLmlzU3RhdGljLFxuXG4gICAgICAgIGRvdWJsZUNsaWNrWm9vbTogZmFsc2UsXG4gICAgICAgIGJveFpvb206IGZhbHNlLFxuXG4gICAgICAgIGF0dHJpYnV0aW9uQ29udHJvbDogZmFsc2VcbiAgICB9KVxuICAgIC5hZGRDb250cm9sKG5ldyBtYXBib3hnbC5BdHRyaWJ1dGlvbkNvbnRyb2woe1xuICAgICAgICBjb21wYWN0OiB0cnVlXG4gICAgfSkpO1xuXG5cbiAgICAvLyBtYWtlIHN1cmUgY2FudmFzIGRvZXMgbm90IGluaGVyaXQgbGVmdCBhbmQgdG9wIGNzc1xuICAgIG1hcC5fY2FudmFzLnN0eWxlLmxlZnQgPSAnMHB4JztcbiAgICBtYXAuX2NhbnZhcy5zdHlsZS50b3AgPSAnMHB4JztcblxuICAgIHNlbGYucmVqZWN0T25FcnJvcihyZWplY3QpO1xuXG4gICAgaWYoIXNlbGYuaXNTdGF0aWMpIHtcbiAgICAgICAgc2VsZi5pbml0RngoY2FsY0RhdGEsIGZ1bGxMYXlvdXQpO1xuICAgIH1cblxuICAgIHZhciBwcm9taXNlcyA9IFtdO1xuXG4gICAgcHJvbWlzZXMucHVzaChuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7XG4gICAgICAgIG1hcC5vbmNlKCdsb2FkJywgcmVzb2x2ZSk7XG4gICAgfSkpO1xuXG4gICAgcHJvbWlzZXMgPSBwcm9taXNlcy5jb25jYXQoc2VsZi5mZXRjaE1hcERhdGEoY2FsY0RhdGEsIGZ1bGxMYXlvdXQpKTtcblxuICAgIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICBzZWxmLmZpbGxCZWxvd0xvb2t1cChjYWxjRGF0YSwgZnVsbExheW91dCk7XG4gICAgICAgIHNlbGYudXBkYXRlRGF0YShjYWxjRGF0YSk7XG4gICAgICAgIHNlbGYudXBkYXRlTGF5b3V0KGZ1bGxMYXlvdXQpO1xuICAgICAgICBzZWxmLnJlc29sdmVPblJlbmRlcihyZXNvbHZlKTtcbiAgICB9KS5jYXRjaChyZWplY3QpO1xufTtcblxucHJvdG8uZmV0Y2hNYXBEYXRhID0gZnVuY3Rpb24oY2FsY0RhdGEpIHtcbiAgICB2YXIgcHJvbWlzZXMgPSBbXTtcblxuICAgIGZ1bmN0aW9uIGZldGNoKHVybCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICBkMy5qc29uKHVybCwgZnVuY3Rpb24oZXJyLCBkKSB7XG4gICAgICAgICAgICAgICAgaWYoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBQbG90bHlHZW9Bc3NldHNbdXJsXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1zZyA9IGVyci5zdGF0dXMgPT09IDQwNCA/XG4gICAgICAgICAgICAgICAgICAgICAgICAoJ0dlb0pTT04gYXQgVVJMIFwiJyArIHVybCArICdcIiBkb2VzIG5vdCBleGlzdC4nKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAoJ1VuZXhwZWN0ZWQgZXJyb3Igd2hpbGUgZmV0Y2hpbmcgZnJvbSAnICsgdXJsKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IobXNnKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgUGxvdGx5R2VvQXNzZXRzW3VybF0gPSBkO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGNhbGNEYXRhW2ldWzBdLnRyYWNlO1xuICAgICAgICB2YXIgdXJsID0gdHJhY2UuZ2VvanNvbjtcblxuICAgICAgICBpZih0eXBlb2YgdXJsID09PSAnc3RyaW5nJyAmJiAhUGxvdGx5R2VvQXNzZXRzW3VybF0pIHtcbiAgICAgICAgICAgIFBsb3RseUdlb0Fzc2V0c1t1cmxdID0gJ3BlbmRpbmcnO1xuICAgICAgICAgICAgcHJvbWlzZXMucHVzaChmZXRjaCh1cmwpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwcm9taXNlcztcbn07XG5cbnByb3RvLnVwZGF0ZU1hcCA9IGZ1bmN0aW9uKGNhbGNEYXRhLCBmdWxsTGF5b3V0LCByZXNvbHZlLCByZWplY3QpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIG1hcCA9IHNlbGYubWFwO1xuICAgIHZhciBvcHRzID0gZnVsbExheW91dFt0aGlzLmlkXTtcblxuICAgIHNlbGYucmVqZWN0T25FcnJvcihyZWplY3QpO1xuXG4gICAgdmFyIHByb21pc2VzID0gW107XG4gICAgdmFyIHN0eWxlT2JqID0gZ2V0U3R5bGVPYmoob3B0cy5zdHlsZSk7XG5cbiAgICBpZihzZWxmLnN0eWxlT2JqLmlkICE9PSBzdHlsZU9iai5pZCkge1xuICAgICAgICBzZWxmLnN0eWxlT2JqID0gc3R5bGVPYmo7XG4gICAgICAgIG1hcC5zZXRTdHlsZShzdHlsZU9iai5zdHlsZSk7XG5cbiAgICAgICAgLy8gbmVlZCB0byByZWJ1aWxkIHRyYWNlIGxheWVycyBvbiByZWxvYWRcbiAgICAgICAgLy8gdG8gYXZvaWQgJ2xvc3QgZXZlbnQnIGVycm9yc1xuICAgICAgICBzZWxmLnRyYWNlSGFzaCA9IHt9O1xuXG4gICAgICAgIHByb21pc2VzLnB1c2gobmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgICAgICAgICAgbWFwLm9uY2UoJ3N0eWxlZGF0YScsIHJlc29sdmUpO1xuICAgICAgICB9KSk7XG4gICAgfVxuXG4gICAgcHJvbWlzZXMgPSBwcm9taXNlcy5jb25jYXQoc2VsZi5mZXRjaE1hcERhdGEoY2FsY0RhdGEsIGZ1bGxMYXlvdXQpKTtcblxuICAgIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICBzZWxmLmZpbGxCZWxvd0xvb2t1cChjYWxjRGF0YSwgZnVsbExheW91dCk7XG4gICAgICAgIHNlbGYudXBkYXRlRGF0YShjYWxjRGF0YSk7XG4gICAgICAgIHNlbGYudXBkYXRlTGF5b3V0KGZ1bGxMYXlvdXQpO1xuICAgICAgICBzZWxmLnJlc29sdmVPblJlbmRlcihyZXNvbHZlKTtcbiAgICB9KS5jYXRjaChyZWplY3QpO1xufTtcblxucHJvdG8uZmlsbEJlbG93TG9va3VwID0gZnVuY3Rpb24oY2FsY0RhdGEsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgb3B0cyA9IGZ1bGxMYXlvdXRbdGhpcy5pZF07XG4gICAgdmFyIGxheWVycyA9IG9wdHMubGF5ZXJzO1xuICAgIHZhciBpLCB2YWw7XG5cbiAgICB2YXIgYmVsb3dMb29rdXAgPSB0aGlzLmJlbG93TG9va3VwID0ge307XG4gICAgdmFyIGhhc1RyYWNlQXRUb3AgPSBmYWxzZTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNhbGNEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGNhbGNEYXRhW2ldWzBdLnRyYWNlO1xuICAgICAgICB2YXIgX21vZHVsZSA9IHRyYWNlLl9tb2R1bGU7XG5cbiAgICAgICAgaWYodHlwZW9mIHRyYWNlLmJlbG93ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdmFsID0gdHJhY2UuYmVsb3c7XG4gICAgICAgIH0gZWxzZSBpZihfbW9kdWxlLmdldEJlbG93KSB7XG4gICAgICAgICAgICAvLyAnc21hcnQnIGRlZmF1bHQgdGhhdCBkZXBlbmQgdGhlIG1hcCdzIGJhc2UgbGF5ZXJzXG4gICAgICAgICAgICB2YWwgPSBfbW9kdWxlLmdldEJlbG93KHRyYWNlLCB0aGlzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHZhbCA9PT0gJycpIHtcbiAgICAgICAgICAgIGhhc1RyYWNlQXRUb3AgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgYmVsb3dMb29rdXBbJ3RyYWNlLScgKyB0cmFjZS51aWRdID0gdmFsIHx8ICcnO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGxheWVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaXRlbSA9IGxheWVyc1tpXTtcblxuICAgICAgICBpZih0eXBlb2YgaXRlbS5iZWxvdyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHZhbCA9IGl0ZW0uYmVsb3c7XG4gICAgICAgIH0gZWxzZSBpZihoYXNUcmFjZUF0VG9wKSB7XG4gICAgICAgICAgICAvLyBpZiBvbmUgb3IgbW9yZSB0cmFjZShzKSBzZXQgYGJlbG93OicnYCBhbmRcbiAgICAgICAgICAgIC8vIGxheWVyc1tpXS5iZWxvdyBpcyB1bnNldCxcbiAgICAgICAgICAgIC8vIHBsYWNlIGxheWVyIGJlbG93IHRyYWNlc1xuICAgICAgICAgICAgdmFsID0gJ3RyYWNlcyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWwgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIGJlbG93TG9va3VwWydsYXlvdXQtJyArIGldID0gdmFsO1xuICAgIH1cblxuICAgIC8vIE4uQi4gSWYgbXVsdGlwbGUgbGF5ZXJzIGhhdmUgdGhlICdiZWxvdycgdmFsdWUsXG4gICAgLy8gd2UgbXVzdCBjbGVhciB0aGUgc3Rhc2hlZCAnYmVsb3cnIGZpZWxkIGluIG9yZGVyXG4gICAgLy8gdG8gbWFrZSBgdHJhY2VIYXNoW2tdLnVwZGF0ZSgpYCBhbmQgYGxheWVyTGlzdFtpXS51cGRhdGUoKWBcbiAgICAvLyByZW1vdmUvYWRkIHRoZSBhbGwgdGhvc2UgbGF5ZXJzIHRvIGhhdmUgcHJlc2VydmVcbiAgICAvLyB0aGUgY29ycmVjdCBsYXllciBvcmRlcmluZ1xuICAgIHZhciB2YWwybGlzdCA9IHt9O1xuICAgIHZhciBrLCBpZDtcblxuICAgIGZvcihrIGluIGJlbG93TG9va3VwKSB7XG4gICAgICAgIHZhbCA9IGJlbG93TG9va3VwW2tdO1xuICAgICAgICBpZih2YWwybGlzdFt2YWxdKSB7XG4gICAgICAgICAgICB2YWwybGlzdFt2YWxdLnB1c2goayk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWwybGlzdFt2YWxdID0gW2tdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKHZhbCBpbiB2YWwybGlzdCkge1xuICAgICAgICB2YXIgbGlzdCA9IHZhbDJsaXN0W3ZhbF07XG4gICAgICAgIGlmKGxpc3QubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGsgPSBsaXN0W2ldO1xuICAgICAgICAgICAgICAgIGlmKGsuaW5kZXhPZigndHJhY2UtJykgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgaWQgPSBrLnNwbGl0KCd0cmFjZS0nKVsxXTtcbiAgICAgICAgICAgICAgICAgICAgaWYodGhpcy50cmFjZUhhc2hbaWRdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYWNlSGFzaFtpZF0uYmVsb3cgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKGsuaW5kZXhPZignbGF5b3V0LScpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlkID0gay5zcGxpdCgnbGF5b3V0LScpWzFdO1xuICAgICAgICAgICAgICAgICAgICBpZih0aGlzLmxheWVyTGlzdFtpZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGF5ZXJMaXN0W2lkXS5iZWxvdyA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG52YXIgdHJhY2VUeXBlMm9yZGVySW5kZXggPSB7XG4gICAgY2hvcm9wbGV0aG1hcGJveDogMCxcbiAgICBkZW5zaXR5bWFwYm94OiAxLFxuICAgIHNjYXR0ZXJtYXBib3g6IDJcbn07XG5cbnByb3RvLnVwZGF0ZURhdGEgPSBmdW5jdGlvbihjYWxjRGF0YSkge1xuICAgIHZhciB0cmFjZUhhc2ggPSB0aGlzLnRyYWNlSGFzaDtcbiAgICB2YXIgdHJhY2VPYmosIHRyYWNlLCBpLCBqO1xuXG4gICAgLy8gTmVlZCB0byBzb3J0IGhlcmUgYnkgdHJhY2UgdHlwZSBoZXJlLFxuICAgIC8vIGluIGNhc2UgdHJhY2VzIHdpdGggZGlmZmVyZW50IGB0eXBlYCBoYXZlIHRoZSBzYW1lXG4gICAgLy8gYmVsb3cgdmFsdWUsIGJ1dCBzb3J0aW5nIHdlIGVuc3VyZSB0aGF0XG4gICAgLy8gZS5nLiBjaG9yb3BsZXRobWFwYm94IHRyYWNlcyB3aWxsIGJlIGJlbG93IHNjYXR0ZXJtYXBib3ggdHJhY2VzXG4gICAgdmFyIGNhbGNEYXRhU29ydGVkID0gY2FsY0RhdGEuc2xpY2UoKS5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHRyYWNlVHlwZTJvcmRlckluZGV4W2FbMF0udHJhY2UudHlwZV0gLVxuICAgICAgICAgICAgdHJhY2VUeXBlMm9yZGVySW5kZXhbYlswXS50cmFjZS50eXBlXVxuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgLy8gdXBkYXRlIG9yIGNyZWF0ZSB0cmFjZSBvYmplY3RzXG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY0RhdGFTb3J0ZWQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNUcmFjZSA9IGNhbGNEYXRhU29ydGVkW2ldO1xuXG4gICAgICAgIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgICAgICB0cmFjZU9iaiA9IHRyYWNlSGFzaFt0cmFjZS51aWRdO1xuXG4gICAgICAgIGlmKHRyYWNlT2JqKSB7XG4gICAgICAgICAgICB0cmFjZU9iai51cGRhdGUoY2FsY1RyYWNlKTtcbiAgICAgICAgfSBlbHNlIGlmKHRyYWNlLl9tb2R1bGUpIHtcbiAgICAgICAgICAgIHRyYWNlSGFzaFt0cmFjZS51aWRdID0gdHJhY2UuX21vZHVsZS5wbG90KHRoaXMsIGNhbGNUcmFjZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyByZW1vdmUgZW1wdHkgdHJhY2Ugb2JqZWN0c1xuICAgIHZhciBpZHMgPSBPYmplY3Qua2V5cyh0cmFjZUhhc2gpO1xuICAgIGlkTG9vcDpcbiAgICBmb3IoaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkID0gaWRzW2ldO1xuXG4gICAgICAgIGZvcihqID0gMDsgaiA8IGNhbGNEYXRhLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB0cmFjZSA9IGNhbGNEYXRhW2pdWzBdLnRyYWNlO1xuICAgICAgICAgICAgaWYoaWQgPT09IHRyYWNlLnVpZCkgY29udGludWUgaWRMb29wO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJhY2VPYmogPSB0cmFjZUhhc2hbaWRdO1xuICAgICAgICB0cmFjZU9iai5kaXNwb3NlKCk7XG4gICAgICAgIGRlbGV0ZSB0cmFjZUhhc2hbaWRdO1xuICAgIH1cbn07XG5cbnByb3RvLnVwZGF0ZUxheW91dCA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5tYXA7XG4gICAgdmFyIG9wdHMgPSBmdWxsTGF5b3V0W3RoaXMuaWRdO1xuXG4gICAgbWFwLnNldENlbnRlcihjb252ZXJ0Q2VudGVyKG9wdHMuY2VudGVyKSk7XG4gICAgbWFwLnNldFpvb20ob3B0cy56b29tKTtcbiAgICBtYXAuc2V0QmVhcmluZyhvcHRzLmJlYXJpbmcpO1xuICAgIG1hcC5zZXRQaXRjaChvcHRzLnBpdGNoKTtcblxuICAgIHRoaXMudXBkYXRlTGF5ZXJzKGZ1bGxMYXlvdXQpO1xuICAgIHRoaXMudXBkYXRlRnJhbWV3b3JrKGZ1bGxMYXlvdXQpO1xuICAgIHRoaXMudXBkYXRlRngoZnVsbExheW91dCk7XG4gICAgdGhpcy5tYXAucmVzaXplKCk7XG5cbiAgICBpZih0aGlzLmdkLl9jb250ZXh0Ll9zY3JvbGxab29tLm1hcGJveCkge1xuICAgICAgICBtYXAuc2Nyb2xsWm9vbS5lbmFibGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYXAuc2Nyb2xsWm9vbS5kaXNhYmxlKCk7XG4gICAgfVxufTtcblxucHJvdG8ucmVzb2x2ZU9uUmVuZGVyID0gZnVuY3Rpb24ocmVzb2x2ZSkge1xuICAgIHZhciBtYXAgPSB0aGlzLm1hcDtcblxuICAgIG1hcC5vbigncmVuZGVyJywgZnVuY3Rpb24gb25SZW5kZXIoKSB7XG4gICAgICAgIGlmKG1hcC5sb2FkZWQoKSkge1xuICAgICAgICAgICAgbWFwLm9mZigncmVuZGVyJywgb25SZW5kZXIpO1xuICAgICAgICAgICAgLy8gcmVzb2x2ZSBhdCBlbmQgb2YgcmVuZGVyIGxvb3BcbiAgICAgICAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgMCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbnByb3RvLnJlamVjdE9uRXJyb3IgPSBmdW5jdGlvbihyZWplY3QpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5tYXA7XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVyKCkge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKGNvbnN0YW50cy5tYXBPbkVycm9yTXNnKSk7XG4gICAgfVxuXG4gICAgbWFwLm9uY2UoJ2Vycm9yJywgaGFuZGxlcik7XG4gICAgbWFwLm9uY2UoJ3N0eWxlLmVycm9yJywgaGFuZGxlcik7XG4gICAgbWFwLm9uY2UoJ3NvdXJjZS5lcnJvcicsIGhhbmRsZXIpO1xuICAgIG1hcC5vbmNlKCd0aWxlLmVycm9yJywgaGFuZGxlcik7XG4gICAgbWFwLm9uY2UoJ2xheWVyLmVycm9yJywgaGFuZGxlcik7XG59O1xuXG5wcm90by5jcmVhdGVGcmFtZXdvcmsgPSBmdW5jdGlvbihmdWxsTGF5b3V0KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIGRpdiA9IHNlbGYuZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZGl2LmlkID0gc2VsZi51aWQ7XG4gICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBzZWxmLmNvbnRhaW5lci5hcHBlbmRDaGlsZChkaXYpO1xuXG4gICAgLy8gY3JlYXRlIG1vY2sgeC95IGF4ZXMgZm9yIGhvdmVyIHJvdXRpbmVcbiAgICBzZWxmLnhheGlzID0ge1xuICAgICAgICBfaWQ6ICd4JyxcbiAgICAgICAgYzJwOiBmdW5jdGlvbih2KSB7IHJldHVybiBzZWxmLnByb2plY3QodikueDsgfVxuICAgIH07XG4gICAgc2VsZi55YXhpcyA9IHtcbiAgICAgICAgX2lkOiAneScsXG4gICAgICAgIGMycDogZnVuY3Rpb24odikgeyByZXR1cm4gc2VsZi5wcm9qZWN0KHYpLnk7IH1cbiAgICB9O1xuXG4gICAgc2VsZi51cGRhdGVGcmFtZXdvcmsoZnVsbExheW91dCk7XG5cbiAgICAvLyBtb2NrIGF4aXMgZm9yIGhvdmVyIGZvcm1hdHRpbmdcbiAgICBzZWxmLm1vY2tBeGlzID0ge1xuICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgc2hvd2V4cG9uZW50OiAnYWxsJyxcbiAgICAgICAgZXhwb25lbnRmb3JtYXQ6ICdCJ1xuICAgIH07XG4gICAgQXhlcy5zZXRDb252ZXJ0KHNlbGYubW9ja0F4aXMsIGZ1bGxMYXlvdXQpO1xufTtcblxucHJvdG8uaW5pdEZ4ID0gZnVuY3Rpb24oY2FsY0RhdGEsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIGdkID0gc2VsZi5nZDtcbiAgICB2YXIgbWFwID0gc2VsZi5tYXA7XG5cbiAgICB2YXIgd2hlZWxpbmcgPSBmYWxzZTtcblxuICAgIC8vIGtlZXAgdHJhY2sgb2YgcGFuIC8gem9vbSBpbiB1c2VyIGxheW91dCBhbmQgZW1pdCByZWxheW91dCBldmVudFxuICAgIG1hcC5vbignbW92ZWVuZCcsIGZ1bmN0aW9uKGV2dCkge1xuICAgICAgICBpZighc2VsZi5tYXApIHJldHVybjtcblxuICAgICAgICB2YXIgZnVsbExheW91dE5vdyA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgICAgIC8vICdtb3ZlZW5kJyBnZXRzIHRyaWdnZXJlZCBieSBtYXAuc2V0Q2VudGVyLCBtYXAuc2V0Wm9vbSxcbiAgICAgICAgLy8gbWFwLnNldEJlYXJpbmcgYW5kIG1hcC5zZXRQaXRjaC5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gSGVyZSwgd2UgbWFrZSBzdXJlIHRoYXQgc3RhdGUgdXBkYXRlcyBhbWQgJ3Bsb3RseV9yZWxheW91dCdcbiAgICAgICAgLy8gYXJlIHRyaWdnZXJlZCBvbmx5IHdoZW4gdGhlICdtb3ZlZW5kJyBvcmlnaW5hdGVzIGZyb20gYVxuICAgICAgICAvLyBtb3VzZSB0YXJnZXQgKGZpbHRlcmluZyBvdXQgQVBJIGNhbGxzKSB0byBub3RcbiAgICAgICAgLy8gZHVwbGljYXRlICdwbG90bHlfcmVsYXlvdXQnIGV2ZW50cy5cblxuICAgICAgICBpZihldnQub3JpZ2luYWxFdmVudCB8fCB3aGVlbGluZykge1xuICAgICAgICAgICAgdmFyIG9wdHNOb3cgPSBmdWxsTGF5b3V0Tm93W3NlbGYuaWRdO1xuICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX3N0b3JlRGlyZWN0R1VJRWRpdCcsIGdkLmxheW91dCwgZnVsbExheW91dE5vdy5fcHJlR1VJLCBzZWxmLmdldFZpZXdFZGl0cyhvcHRzTm93KSk7XG5cbiAgICAgICAgICAgIHZhciB2aWV3Tm93ID0gc2VsZi5nZXRWaWV3KCk7XG4gICAgICAgICAgICBvcHRzTm93Ll9pbnB1dC5jZW50ZXIgPSBvcHRzTm93LmNlbnRlciA9IHZpZXdOb3cuY2VudGVyO1xuICAgICAgICAgICAgb3B0c05vdy5faW5wdXQuem9vbSA9IG9wdHNOb3cuem9vbSA9IHZpZXdOb3cuem9vbTtcbiAgICAgICAgICAgIG9wdHNOb3cuX2lucHV0LmJlYXJpbmcgPSBvcHRzTm93LmJlYXJpbmcgPSB2aWV3Tm93LmJlYXJpbmc7XG4gICAgICAgICAgICBvcHRzTm93Ll9pbnB1dC5waXRjaCA9IG9wdHNOb3cucGl0Y2ggPSB2aWV3Tm93LnBpdGNoO1xuXG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVsYXlvdXQnLCBzZWxmLmdldFZpZXdFZGl0cyh2aWV3Tm93KSk7XG4gICAgICAgIH1cbiAgICAgICAgd2hlZWxpbmcgPSBmYWxzZTtcblxuICAgICAgICBpZihmdWxsTGF5b3V0Tm93Ll9yZWhvdmVyKSB7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Tm93Ll9yZWhvdmVyKCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIG1hcC5vbignd2hlZWwnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgd2hlZWxpbmcgPSB0cnVlO1xuICAgIH0pO1xuXG4gICAgbWFwLm9uKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgdmFyIGJiID0gc2VsZi5kaXYuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgLy8gc29tZSBoYWNrZXJ5IHRvIGdldCBGeC5ob3ZlciB0byB3b3JrXG4gICAgICAgIGV2dC5jbGllbnRYID0gZXZ0LnBvaW50LnggKyBiYi5sZWZ0O1xuICAgICAgICBldnQuY2xpZW50WSA9IGV2dC5wb2ludC55ICsgYmIudG9wO1xuXG4gICAgICAgIGV2dC50YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0ID0gZnVuY3Rpb24oKSB7IHJldHVybiBiYjsgfTtcblxuICAgICAgICBzZWxmLnhheGlzLnAyYyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gZXZ0LmxuZ0xhdC5sbmc7IH07XG4gICAgICAgIHNlbGYueWF4aXMucDJjID0gZnVuY3Rpb24oKSB7IHJldHVybiBldnQubG5nTGF0LmxhdDsgfTtcblxuICAgICAgICBnZC5fZnVsbExheW91dC5fcmVob3ZlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYoZ2QuX2Z1bGxMYXlvdXQuX2hvdmVyc3VicGxvdCA9PT0gc2VsZi5pZCkge1xuICAgICAgICAgICAgICAgIEZ4LmhvdmVyKGdkLCBldnQsIHNlbGYuaWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIEZ4LmhvdmVyKGdkLCBldnQsIHNlbGYuaWQpO1xuICAgICAgICBnZC5fZnVsbExheW91dC5faG92ZXJzdWJwbG90ID0gc2VsZi5pZDtcbiAgICB9KTtcblxuICAgIGZ1bmN0aW9uIHVuaG92ZXIoKSB7XG4gICAgICAgIEZ4LmxvbmVVbmhvdmVyKGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIpO1xuICAgIH1cblxuICAgIG1hcC5vbignZHJhZ3N0YXJ0JywgdW5ob3Zlcik7XG4gICAgbWFwLm9uKCd6b29tc3RhcnQnLCB1bmhvdmVyKTtcblxuICAgIG1hcC5vbignbW91c2VvdXQnLCBmdW5jdGlvbigpIHtcbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX2hvdmVyc3VicGxvdCA9IG51bGw7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBlbWl0VXBkYXRlKCkge1xuICAgICAgICB2YXIgdmlld05vdyA9IHNlbGYuZ2V0VmlldygpO1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVsYXlvdXRpbmcnLCBzZWxmLmdldFZpZXdFZGl0cyh2aWV3Tm93KSk7XG4gICAgfVxuXG4gICAgbWFwLm9uKCdkcmFnJywgZW1pdFVwZGF0ZSk7XG4gICAgbWFwLm9uKCd6b29tJywgZW1pdFVwZGF0ZSk7XG5cbiAgICBtYXAub24oJ2RibGNsaWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBvcHRzTm93ID0gZ2QuX2Z1bGxMYXlvdXRbc2VsZi5pZF07XG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19zdG9yZURpcmVjdEdVSUVkaXQnLCBnZC5sYXlvdXQsIGdkLl9mdWxsTGF5b3V0Ll9wcmVHVUksIHNlbGYuZ2V0Vmlld0VkaXRzKG9wdHNOb3cpKTtcblxuICAgICAgICB2YXIgdmlld0luaXRpYWwgPSBzZWxmLnZpZXdJbml0aWFsO1xuICAgICAgICBtYXAuc2V0Q2VudGVyKGNvbnZlcnRDZW50ZXIodmlld0luaXRpYWwuY2VudGVyKSk7XG4gICAgICAgIG1hcC5zZXRab29tKHZpZXdJbml0aWFsLnpvb20pO1xuICAgICAgICBtYXAuc2V0QmVhcmluZyh2aWV3SW5pdGlhbC5iZWFyaW5nKTtcbiAgICAgICAgbWFwLnNldFBpdGNoKHZpZXdJbml0aWFsLnBpdGNoKTtcblxuICAgICAgICB2YXIgdmlld05vdyA9IHNlbGYuZ2V0VmlldygpO1xuICAgICAgICBvcHRzTm93Ll9pbnB1dC5jZW50ZXIgPSBvcHRzTm93LmNlbnRlciA9IHZpZXdOb3cuY2VudGVyO1xuICAgICAgICBvcHRzTm93Ll9pbnB1dC56b29tID0gb3B0c05vdy56b29tID0gdmlld05vdy56b29tO1xuICAgICAgICBvcHRzTm93Ll9pbnB1dC5iZWFyaW5nID0gb3B0c05vdy5iZWFyaW5nID0gdmlld05vdy5iZWFyaW5nO1xuICAgICAgICBvcHRzTm93Ll9pbnB1dC5waXRjaCA9IG9wdHNOb3cucGl0Y2ggPSB2aWV3Tm93LnBpdGNoO1xuXG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9kb3VibGVjbGljaycsIG51bGwpO1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVsYXlvdXQnLCBzZWxmLmdldFZpZXdFZGl0cyh2aWV3Tm93KSk7XG4gICAgfSk7XG5cbiAgICAvLyBkZWZpbmUgZXZlbnQgaGFuZGxlcnMgb24gbWFwIGNyZWF0aW9uLCB0byBrZWVwIG9uZSByZWYgcGVyIG1hcCxcbiAgICAvLyBzbyB0aGF0IG1hcC5vbiAvIG1hcC5vZmYgaW4gdXBkYXRlRnggd29ya3MgYXMgZXhwZWN0ZWRcbiAgICBzZWxmLmNsZWFyU2VsZWN0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGdkLl9mdWxsTGF5b3V0Ll96b29tbGF5ZXIuc2VsZWN0QWxsKCcuc2VsZWN0LW91dGxpbmUnKS5yZW1vdmUoKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGNsaWNrIGhhbmRsZXIgZnVuY3Rpb24gdGhhdCBpcyBzdXBwb3NlZFxuICAgICAqIHRvIGhhbmRsZSBjbGlja3MgaW4gcGFuIG1vZGUuXG4gICAgICovXG4gICAgc2VsZi5vbkNsaWNrSW5QYW5GbiA9IGZ1bmN0aW9uKGRyYWdPcHRpb25zKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgICAgIHZhciBjbGlja01vZGUgPSBnZC5fZnVsbExheW91dC5jbGlja21vZGU7XG5cbiAgICAgICAgICAgIGlmKGNsaWNrTW9kZS5pbmRleE9mKCdzZWxlY3QnKSA+IC0xKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0T25DbGljayhldnQub3JpZ2luYWxFdmVudCwgZ2QsIFtzZWxmLnhheGlzXSwgW3NlbGYueWF4aXNdLCBzZWxmLmlkLCBkcmFnT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGNsaWNrTW9kZS5pbmRleE9mKCdldmVudCcpID4gLTEpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiB0aGlzIGRvZXMgbm90IHN1cHBvcnQgcmlnaHQtY2xpY2suIElmIHdlIHdhbnQgdG8gc3VwcG9ydCBpdCwgd2VcbiAgICAgICAgICAgICAgICAvLyB3b3VsZCBsaWtlbHkgbmVlZCB0byBjaGFuZ2UgbWFwYm94IHRvIHVzZSBkcmFnRWxlbWVudCBpbnN0ZWFkIG9mIHN0cmFpZ2h0XG4gICAgICAgICAgICAgICAgLy8gbWFwYm94IGV2ZW50IGJpbmRpbmcuIE9yIHBlcmhhcHMgYmV0dGVyLCBtYWtlIGEgc2ltcGxlIHdyYXBwZXIgd2l0aCB0aGVcbiAgICAgICAgICAgICAgICAvLyByaWdodCBtb3VzZWRvd24sIG1vdXNlbW92ZSwgYW5kIG1vdXNldXAgaGFuZGxlcnMganVzdCBmb3IgYSBsZWZ0L3JpZ2h0IGNsaWNrXG4gICAgICAgICAgICAgICAgLy8gcGllIHdvdWxkIHVzZSB0aGlzIHRvby5cbiAgICAgICAgICAgICAgICBGeC5jbGljayhnZCwgZXZ0Lm9yaWdpbmFsRXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH07XG59O1xuXG5wcm90by51cGRhdGVGeCA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIG1hcCA9IHNlbGYubWFwO1xuICAgIHZhciBnZCA9IHNlbGYuZ2Q7XG5cbiAgICBpZihzZWxmLmlzU3RhdGljKSByZXR1cm47XG5cbiAgICBmdW5jdGlvbiBpbnZlcnQocHhweSkge1xuICAgICAgICB2YXIgb2JqID0gc2VsZi5tYXAudW5wcm9qZWN0KHB4cHkpO1xuICAgICAgICByZXR1cm4gW29iai5sbmcsIG9iai5sYXRdO1xuICAgIH1cblxuICAgIHZhciBkcmFnTW9kZSA9IGZ1bGxMYXlvdXQuZHJhZ21vZGU7XG4gICAgdmFyIGZpbGxSYW5nZUl0ZW1zO1xuXG4gICAgaWYoZHJhZ01vZGUgPT09ICdzZWxlY3QnKSB7XG4gICAgICAgIGZpbGxSYW5nZUl0ZW1zID0gZnVuY3Rpb24oZXZlbnREYXRhLCBwb2x5KSB7XG4gICAgICAgICAgICB2YXIgcmFuZ2VzID0gZXZlbnREYXRhLnJhbmdlID0ge307XG4gICAgICAgICAgICByYW5nZXNbc2VsZi5pZF0gPSBbXG4gICAgICAgICAgICAgICAgaW52ZXJ0KFtwb2x5LnhtaW4sIHBvbHkueW1pbl0pLFxuICAgICAgICAgICAgICAgIGludmVydChbcG9seS54bWF4LCBwb2x5LnltYXhdKVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBmaWxsUmFuZ2VJdGVtcyA9IGZ1bmN0aW9uKGV2ZW50RGF0YSwgcG9seSwgcHRzKSB7XG4gICAgICAgICAgICB2YXIgZGF0YVB0cyA9IGV2ZW50RGF0YS5sYXNzb1BvaW50cyA9IHt9O1xuICAgICAgICAgICAgZGF0YVB0c1tzZWxmLmlkXSA9IHB0cy5maWx0ZXJlZC5tYXAoaW52ZXJ0KTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBOb3RlOiBkcmFnT3B0aW9ucyBpcyBuZWVkZWQgdG8gYmUgZGVjbGFyZWQgZm9yIGFsbCBkcmFnbW9kZXMgYmVjYXVzZVxuICAgIC8vIGl0J3MgdGhlIG9iamVjdCB0aGF0IGhvbGRzIHBlcnNpc3RlbnQgc2VsZWN0aW9uIHN0YXRlLlxuICAgIC8vIE1lcmdlIG9sZCBkcmFnT3B0aW9ucyB3aXRoIG5ldyB0byBrZWVwIHBvc3NpYmx5IGluaXRpYWxpemVkXG4gICAgLy8gcGVyc2lzdGVudCBzZWxlY3Rpb24gc3RhdGUuXG4gICAgdmFyIG9sZERyYWdPcHRpb25zID0gc2VsZi5kcmFnT3B0aW9ucztcbiAgICBzZWxmLmRyYWdPcHRpb25zID0gTGliLmV4dGVuZERlZXAob2xkRHJhZ09wdGlvbnMgfHwge30sIHtcbiAgICAgICAgZWxlbWVudDogc2VsZi5kaXYsXG4gICAgICAgIGdkOiBnZCxcbiAgICAgICAgcGxvdGluZm86IHtcbiAgICAgICAgICAgIGlkOiBzZWxmLmlkLFxuICAgICAgICAgICAgeGF4aXM6IHNlbGYueGF4aXMsXG4gICAgICAgICAgICB5YXhpczogc2VsZi55YXhpcyxcbiAgICAgICAgICAgIGZpbGxSYW5nZUl0ZW1zOiBmaWxsUmFuZ2VJdGVtc1xuICAgICAgICB9LFxuICAgICAgICB4YXhlczogW3NlbGYueGF4aXNdLFxuICAgICAgICB5YXhlczogW3NlbGYueWF4aXNdLFxuICAgICAgICBzdWJwbG90OiBzZWxmLmlkXG4gICAgfSk7XG5cbiAgICAvLyBVbnJlZ2lzdGVyIHRoZSBvbGQgaGFuZGxlciBiZWZvcmUgcG90ZW50aWFsbHkgcmVnaXN0ZXJpbmdcbiAgICAvLyBhIG5ldyBvbmUuIE90aGVyd2lzZSBtdWx0aXBsZSBjbGljayBoYW5kbGVycyBtaWdodFxuICAgIC8vIGJlIHJlZ2lzdGVyZWQgcmVzdWx0aW5nIGluIHVud2FudGVkIGJlaGF2aW9yLlxuICAgIG1hcC5vZmYoJ2NsaWNrJywgc2VsZi5vbkNsaWNrSW5QYW5IYW5kbGVyKTtcbiAgICBpZihkcmFnTW9kZSA9PT0gJ3NlbGVjdCcgfHwgZHJhZ01vZGUgPT09ICdsYXNzbycpIHtcbiAgICAgICAgbWFwLmRyYWdQYW4uZGlzYWJsZSgpO1xuICAgICAgICBtYXAub24oJ3pvb21zdGFydCcsIHNlbGYuY2xlYXJTZWxlY3QpO1xuXG4gICAgICAgIHNlbGYuZHJhZ09wdGlvbnMucHJlcEZuID0gZnVuY3Rpb24oZSwgc3RhcnRYLCBzdGFydFkpIHtcbiAgICAgICAgICAgIHByZXBTZWxlY3QoZSwgc3RhcnRYLCBzdGFydFksIHNlbGYuZHJhZ09wdGlvbnMsIGRyYWdNb2RlKTtcbiAgICAgICAgfTtcblxuICAgICAgICBkcmFnRWxlbWVudC5pbml0KHNlbGYuZHJhZ09wdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1hcC5kcmFnUGFuLmVuYWJsZSgpO1xuICAgICAgICBtYXAub2ZmKCd6b29tc3RhcnQnLCBzZWxmLmNsZWFyU2VsZWN0KTtcbiAgICAgICAgc2VsZi5kaXYub25tb3VzZWRvd24gPSBudWxsO1xuXG4gICAgICAgIC8vIFRPRE86IHRoaXMgZG9lcyBub3Qgc3VwcG9ydCByaWdodC1jbGljay4gSWYgd2Ugd2FudCB0byBzdXBwb3J0IGl0LCB3ZVxuICAgICAgICAvLyB3b3VsZCBsaWtlbHkgbmVlZCB0byBjaGFuZ2UgbWFwYm94IHRvIHVzZSBkcmFnRWxlbWVudCBpbnN0ZWFkIG9mIHN0cmFpZ2h0XG4gICAgICAgIC8vIG1hcGJveCBldmVudCBiaW5kaW5nLiBPciBwZXJoYXBzIGJldHRlciwgbWFrZSBhIHNpbXBsZSB3cmFwcGVyIHdpdGggdGhlXG4gICAgICAgIC8vIHJpZ2h0IG1vdXNlZG93biwgbW91c2Vtb3ZlLCBhbmQgbW91c2V1cCBoYW5kbGVycyBqdXN0IGZvciBhIGxlZnQvcmlnaHQgY2xpY2tcbiAgICAgICAgLy8gcGllIHdvdWxkIHVzZSB0aGlzIHRvby5cbiAgICAgICAgc2VsZi5vbkNsaWNrSW5QYW5IYW5kbGVyID0gc2VsZi5vbkNsaWNrSW5QYW5GbihzZWxmLmRyYWdPcHRpb25zKTtcbiAgICAgICAgbWFwLm9uKCdjbGljaycsIHNlbGYub25DbGlja0luUGFuSGFuZGxlcik7XG4gICAgfVxufTtcblxucHJvdG8udXBkYXRlRnJhbWV3b3JrID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIHZhciBkb21haW4gPSBmdWxsTGF5b3V0W3RoaXMuaWRdLmRvbWFpbjtcbiAgICB2YXIgc2l6ZSA9IGZ1bGxMYXlvdXQuX3NpemU7XG5cbiAgICB2YXIgc3R5bGUgPSB0aGlzLmRpdi5zdHlsZTtcbiAgICBzdHlsZS53aWR0aCA9IHNpemUudyAqIChkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdKSArICdweCc7XG4gICAgc3R5bGUuaGVpZ2h0ID0gc2l6ZS5oICogKGRvbWFpbi55WzFdIC0gZG9tYWluLnlbMF0pICsgJ3B4JztcbiAgICBzdHlsZS5sZWZ0ID0gc2l6ZS5sICsgZG9tYWluLnhbMF0gKiBzaXplLncgKyAncHgnO1xuICAgIHN0eWxlLnRvcCA9IHNpemUudCArICgxIC0gZG9tYWluLnlbMV0pICogc2l6ZS5oICsgJ3B4JztcblxuICAgIHRoaXMueGF4aXMuX29mZnNldCA9IHNpemUubCArIGRvbWFpbi54WzBdICogc2l6ZS53O1xuICAgIHRoaXMueGF4aXMuX2xlbmd0aCA9IHNpemUudyAqIChkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdKTtcblxuICAgIHRoaXMueWF4aXMuX29mZnNldCA9IHNpemUudCArICgxIC0gZG9tYWluLnlbMV0pICogc2l6ZS5oO1xuICAgIHRoaXMueWF4aXMuX2xlbmd0aCA9IHNpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKTtcbn07XG5cbnByb3RvLnVwZGF0ZUxheWVycyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgb3B0cyA9IGZ1bGxMYXlvdXRbdGhpcy5pZF07XG4gICAgdmFyIGxheWVycyA9IG9wdHMubGF5ZXJzO1xuICAgIHZhciBsYXllckxpc3QgPSB0aGlzLmxheWVyTGlzdDtcbiAgICB2YXIgaTtcblxuICAgIC8vIGlmIHRoZSBsYXllciBhcnJheXMgZG9uJ3QgbWF0Y2gsXG4gICAgLy8gZG9uJ3QgdHJ5IHRvIGJlIHNtYXJ0LFxuICAgIC8vIGRlbGV0ZSB0aGVtIGFsbCwgYW5kIHN0YXJ0IGFsbCBvdmVyLlxuXG4gICAgaWYobGF5ZXJzLmxlbmd0aCAhPT0gbGF5ZXJMaXN0Lmxlbmd0aCkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsYXllckxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxheWVyTGlzdFtpXS5kaXNwb3NlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBsYXllckxpc3QgPSB0aGlzLmxheWVyTGlzdCA9IFtdO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxheWVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGF5ZXJMaXN0LnB1c2goY3JlYXRlTWFwYm94TGF5ZXIodGhpcywgaSwgbGF5ZXJzW2ldKSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsYXllcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxheWVyTGlzdFtpXS51cGRhdGUobGF5ZXJzW2ldKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbnByb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbigpIHtcbiAgICBpZih0aGlzLm1hcCkge1xuICAgICAgICB0aGlzLm1hcC5yZW1vdmUoKTtcbiAgICAgICAgdGhpcy5tYXAgPSBudWxsO1xuICAgICAgICB0aGlzLmNvbnRhaW5lci5yZW1vdmVDaGlsZCh0aGlzLmRpdik7XG4gICAgfVxufTtcblxucHJvdG8udG9JbWFnZSA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMubWFwLnN0b3AoKTtcbiAgICByZXR1cm4gdGhpcy5tYXAuZ2V0Q2FudmFzKCkudG9EYXRhVVJMKCk7XG59O1xuXG4vLyBjb252ZW5pZW5jZSB3cmFwcGVyIHRvIGNyZWF0ZSBzZXQgbXVsdGlwbGUgbGF5ZXJcbi8vICdsYXlvdXQnIG9yICdwYWludCBvcHRpb25zIGF0IG9uY2UuXG5wcm90by5zZXRPcHRpb25zID0gZnVuY3Rpb24oaWQsIG1ldGhvZE5hbWUsIG9wdHMpIHtcbiAgICBmb3IodmFyIGsgaW4gb3B0cykge1xuICAgICAgICB0aGlzLm1hcFttZXRob2ROYW1lXShpZCwgaywgb3B0c1trXSk7XG4gICAgfVxufTtcblxucHJvdG8uZ2V0TWFwTGF5ZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMubWFwLmdldFN0eWxlKCkubGF5ZXJzO1xufTtcblxuLy8gY29udmVuaWVuY2Ugd3JhcHBlciB0aGF0IGZpcnN0IGNoZWNrIGluICdiZWxvdycgcmVmZXJlbmNlc1xuLy8gYSBsYXllciB0aGF0IGV4aXN0IGFuZCB0aGVuIGFkZCB0aGUgbGF5ZXIgdG8gdGhlIG1hcCxcbnByb3RvLmFkZExheWVyID0gZnVuY3Rpb24ob3B0cywgYmVsb3cpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5tYXA7XG5cbiAgICBpZih0eXBlb2YgYmVsb3cgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGlmKGJlbG93ID09PSAnJykge1xuICAgICAgICAgICAgbWFwLmFkZExheWVyKG9wdHMsIGJlbG93KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBtYXBMYXllcnMgPSB0aGlzLmdldE1hcExheWVycygpO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbWFwTGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihiZWxvdyA9PT0gbWFwTGF5ZXJzW2ldLmlkKSB7XG4gICAgICAgICAgICAgICAgbWFwLmFkZExheWVyKG9wdHMsIGJlbG93KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBMaWIud2FybihbXG4gICAgICAgICAgICAnVHJ5aW5nIHRvIGFkZCBsYXllciB3aXRoICpiZWxvdyogdmFsdWUnLFxuICAgICAgICAgICAgYmVsb3csXG4gICAgICAgICAgICAncmVmZXJlbmNpbmcgYSBsYXllciB0aGF0IGRvZXMgbm90IGV4aXN0JyxcbiAgICAgICAgICAgICdvciB0aGF0IGRvZXMgbm90IHlldCBleGlzdC4nXG4gICAgICAgIF0uam9pbignICcpKTtcbiAgICB9XG5cbiAgICBtYXAuYWRkTGF5ZXIob3B0cyk7XG59O1xuXG4vLyBjb252ZW5pZW5jZSBtZXRob2QgdG8gcHJvamVjdCBhIFtsb24sIGxhdF0gYXJyYXkgdG8gcGl4ZWwgY29vcmRzXG5wcm90by5wcm9qZWN0ID0gZnVuY3Rpb24odikge1xuICAgIHJldHVybiB0aGlzLm1hcC5wcm9qZWN0KG5ldyBtYXBib3hnbC5MbmdMYXQodlswXSwgdlsxXSkpO1xufTtcblxuLy8gZ2V0IG1hcCdzIGN1cnJlbnQgdmlldyB2YWx1ZXMgaW4gcGxvdGx5LmpzIG5vdGF0aW9uXG5wcm90by5nZXRWaWV3ID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1hcCA9IHRoaXMubWFwO1xuICAgIHZhciBtYXBDZW50ZXIgPSBtYXAuZ2V0Q2VudGVyKCk7XG4gICAgdmFyIGNlbnRlciA9IHsgbG9uOiBtYXBDZW50ZXIubG5nLCBsYXQ6IG1hcENlbnRlci5sYXQgfTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGNlbnRlcjogY2VudGVyLFxuICAgICAgICB6b29tOiBtYXAuZ2V0Wm9vbSgpLFxuICAgICAgICBiZWFyaW5nOiBtYXAuZ2V0QmVhcmluZygpLFxuICAgICAgICBwaXRjaDogbWFwLmdldFBpdGNoKClcbiAgICB9O1xufTtcblxucHJvdG8uZ2V0Vmlld0VkaXRzID0gZnVuY3Rpb24oY29udCkge1xuICAgIHZhciBpZCA9IHRoaXMuaWQ7XG4gICAgdmFyIGtleXMgPSBbJ2NlbnRlcicsICd6b29tJywgJ2JlYXJpbmcnLCAncGl0Y2gnXTtcbiAgICB2YXIgb2JqID0ge307XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgayA9IGtleXNbaV07XG4gICAgICAgIG9ialtpZCArICcuJyArIGtdID0gY29udFtrXTtcbiAgICB9XG5cbiAgICByZXR1cm4gb2JqO1xufTtcblxuZnVuY3Rpb24gZ2V0U3R5bGVPYmoodmFsKSB7XG4gICAgdmFyIHN0eWxlT2JqID0ge307XG5cbiAgICBpZihMaWIuaXNQbGFpbk9iamVjdCh2YWwpKSB7XG4gICAgICAgIHN0eWxlT2JqLmlkID0gdmFsLmlkO1xuICAgICAgICBzdHlsZU9iai5zdHlsZSA9IHZhbDtcbiAgICB9IGVsc2UgaWYodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgc3R5bGVPYmouaWQgPSB2YWw7XG5cbiAgICAgICAgaWYoY29uc3RhbnRzLnN0eWxlVmFsdWVzTWFwYm94LmluZGV4T2YodmFsKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHN0eWxlT2JqLnN0eWxlID0gY29udmVydFN0eWxlVmFsKHZhbCk7XG4gICAgICAgIH0gZWxzZSBpZihjb25zdGFudHMuc3R5bGVzTm9uTWFwYm94W3ZhbF0pIHtcbiAgICAgICAgICAgIHN0eWxlT2JqLnN0eWxlID0gY29uc3RhbnRzLnN0eWxlc05vbk1hcGJveFt2YWxdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3R5bGVPYmouc3R5bGUgPSB2YWw7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBzdHlsZU9iai5pZCA9IGNvbnN0YW50cy5zdHlsZVZhbHVlRGZsdDtcbiAgICAgICAgc3R5bGVPYmouc3R5bGUgPSBjb252ZXJ0U3R5bGVWYWwoY29uc3RhbnRzLnN0eWxlVmFsdWVEZmx0KTtcbiAgICB9XG5cbiAgICBzdHlsZU9iai50cmFuc2l0aW9uID0ge2R1cmF0aW9uOiAwLCBkZWxheTogMH07XG5cbiAgICByZXR1cm4gc3R5bGVPYmo7XG59XG5cbi8vIGlmIHN0eWxlIGlzIHBhcnQgb2YgdGhlICdvZmZpY2lhbCcgbWFwYm94IHZhbHVlcywgYWRkIFVSTCBwcmVmaXggYW5kIHN1ZmZpeFxuZnVuY3Rpb24gY29udmVydFN0eWxlVmFsKHZhbCkge1xuICAgIHJldHVybiBjb25zdGFudHMuc3R5bGVVcmxQcmVmaXggKyB2YWwgKyAnLScgKyBjb25zdGFudHMuc3R5bGVVcmxTdWZmaXg7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRDZW50ZXIoY2VudGVyKSB7XG4gICAgcmV0dXJuIFtjZW50ZXIubG9uLCBjZW50ZXIubGF0XTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBNYXBib3g7XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9kcmFnZWxlbWVudFwiOjYxMSxcIi4uLy4uL2NvbXBvbmVudHMvZnhcIjo2MzIsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4uL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vY2FydGVzaWFuL3NlbGVjdFwiOjc4NCxcIi4vY29uc3RhbnRzXCI6ODIwLFwiLi9sYXllcnNcIjo4MjMsXCJkM1wiOjE2MyxcIm1hcGJveC1nbFwiOjQyNn1dLDgyNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQ3JlYXRlcyBhIHNldCBvZiBwYWRkaW5nIGF0dHJpYnV0ZXMuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqICAgQHBhcmFtIHtzdHJpbmd9IGVkaXRUeXBlOlxuICogICAgIHRoZSBlZGl0VHlwZSBmb3IgYWxsIHBpZWNlcyBvZiB0aGlzIHBhZGRpbmcgZGVmaW5pdGlvblxuICpcbiAqIEByZXR1cm4ge29iamVjdH0gYXR0cmlidXRlcyBvYmplY3QgY29udGFpbmluZyB7dCwgciwgYiwgbH0gYXMgc3BlY2lmaWVkXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob3B0cykge1xuICAgIHZhciBlZGl0VHlwZSA9IG9wdHMuZWRpdFR5cGU7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogZWRpdFR5cGUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogZWRpdFR5cGUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgYjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogZWRpdFR5cGUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogZWRpdFR5cGUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6IGVkaXRUeXBlXG4gICAgfTtcbn07XG5cbn0se31dLDgyODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vcmVnaXN0cnknKTtcbnZhciBQbG90U2NoZW1hID0gX2RlcmVxXygnLi4vcGxvdF9hcGkvcGxvdF9zY2hlbWEnKTtcbnZhciBUZW1wbGF0ZSA9IF9kZXJlcV8oJy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG52YXIgYXhpc0lEcyA9IF9kZXJlcV8oJy4vY2FydGVzaWFuL2F4aXNfaWRzJyk7XG5cbnZhciBhbmltYXRpb25BdHRycyA9IF9kZXJlcV8oJy4vYW5pbWF0aW9uX2F0dHJpYnV0ZXMnKTtcbnZhciBmcmFtZUF0dHJzID0gX2RlcmVxXygnLi9mcmFtZV9hdHRyaWJ1dGVzJyk7XG5cbnZhciByZWxpbmtQcml2YXRlS2V5cyA9IExpYi5yZWxpbmtQcml2YXRlS2V5cztcbnZhciBfID0gTGliLl87XG5cbnZhciBwbG90cyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8vIEV4cG9zZSByZWdpc3RyeSBtZXRob2RzIG9uIFBsb3RzIGZvciBiYWNrd2FyZC1jb21wYXRpYmlsaXR5XG5MaWIuZXh0ZW5kRmxhdChwbG90cywgUmVnaXN0cnkpO1xuXG5wbG90cy5hdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5wbG90cy5hdHRyaWJ1dGVzLnR5cGUudmFsdWVzID0gcGxvdHMuYWxsVHlwZXM7XG5wbG90cy5mb250QXR0cnMgPSBfZGVyZXFfKCcuL2ZvbnRfYXR0cmlidXRlcycpO1xucGxvdHMubGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxuLy8gVE9ETyBtYWtlIHRoaXMgYSBwbG90IGF0dHJpYnV0ZT9cbnBsb3RzLmZvbnRXZWlnaHQgPSAnbm9ybWFsJztcblxudmFyIHRyYW5zZm9ybXNSZWdpc3RyeSA9IHBsb3RzLnRyYW5zZm9ybXNSZWdpc3RyeTtcblxudmFyIGNvbW1hbmRNb2R1bGUgPSBfZGVyZXFfKCcuL2NvbW1hbmQnKTtcbnBsb3RzLmV4ZWN1dGVBUElDb21tYW5kID0gY29tbWFuZE1vZHVsZS5leGVjdXRlQVBJQ29tbWFuZDtcbnBsb3RzLmNvbXB1dGVBUElDb21tYW5kQmluZGluZ3MgPSBjb21tYW5kTW9kdWxlLmNvbXB1dGVBUElDb21tYW5kQmluZGluZ3M7XG5wbG90cy5tYW5hZ2VDb21tYW5kT2JzZXJ2ZXIgPSBjb21tYW5kTW9kdWxlLm1hbmFnZUNvbW1hbmRPYnNlcnZlcjtcbnBsb3RzLmhhc1NpbXBsZUFQSUNvbW1hbmRCaW5kaW5ncyA9IGNvbW1hbmRNb2R1bGUuaGFzU2ltcGxlQVBJQ29tbWFuZEJpbmRpbmdzO1xuXG4vLyBpbiBzb21lIGNhc2VzIHRoZSBicm93c2VyIGRvZXNuJ3Qgc2VlbSB0byBrbm93IGhvdyBiaWdcbi8vIHRoZSB0ZXh0IGlzIGF0IGZpcnN0LCBzbyBpdCBuZWVkcyB0byBkcmF3IGl0LFxuLy8gdGhlbiB3YWl0IGEgbGl0dGxlLCB0aGVuIGRyYXcgaXQgYWdhaW5cbnBsb3RzLnJlZHJhd1RleHQgPSBmdW5jdGlvbihnZCkge1xuICAgIGdkID0gTGliLmdldEdyYXBoRGl2KGdkKTtcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQgfHwge307XG4gICAgdmFyIGhhc1BvbGFyID0gZnVsbExheW91dC5faGFzICYmIGZ1bGxMYXlvdXQuX2hhcygncG9sYXInKTtcbiAgICB2YXIgaGFzTGVnYWN5UG9sYXIgPSAhaGFzUG9sYXIgJiYgZ2QuZGF0YSAmJiBnZC5kYXRhWzBdICYmIGdkLmRhdGFbMF0ucjtcblxuICAgIC8vIGRvIG5vdCB3b3JrIGlmIHBvbGFyIGlzIHByZXNlbnRcbiAgICBpZihoYXNMZWdhY3lQb2xhcikgcmV0dXJuO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnYW5ub3RhdGlvbnMnLCAnZHJhdycpKGdkKTtcbiAgICAgICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnbGVnZW5kJywgJ2RyYXcnKShnZCk7XG4gICAgICAgICAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NvbG9yYmFyJywgJ2RyYXcnKShnZCk7XG4gICAgICAgICAgICByZXNvbHZlKHBsb3RzLnByZXZpb3VzUHJvbWlzZXMoZ2QpKTtcbiAgICAgICAgfSwgMzAwKTtcbiAgICB9KTtcbn07XG5cbi8vIHJlc2l6ZSBwbG90IGFib3V0IHRoZSBjb250YWluZXIgc2l6ZVxucGxvdHMucmVzaXplID0gZnVuY3Rpb24oZ2QpIHtcbiAgICBnZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGlmKCFnZCB8fCBMaWIuaXNIaWRkZW4oZ2QpKSB7XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdSZXNpemUgbXVzdCBiZSBwYXNzZWQgYSBkaXNwbGF5ZWQgcGxvdCBkaXYgZWxlbWVudC4nKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihnZC5fcmVkcmF3VGltZXIpIGNsZWFyVGltZW91dChnZC5fcmVkcmF3VGltZXIpO1xuXG4gICAgICAgIGdkLl9yZWRyYXdUaW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyByZXR1cm4gaWYgdGhlcmUgaXMgbm90aGluZyB0byByZXNpemUgb3IgaXMgaGlkZGVuXG4gICAgICAgICAgICBpZighZ2QubGF5b3V0IHx8IChnZC5sYXlvdXQud2lkdGggJiYgZ2QubGF5b3V0LmhlaWdodCkgfHwgTGliLmlzSGlkZGVuKGdkKSkge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZ2QpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGVsZXRlIGdkLmxheW91dC53aWR0aDtcbiAgICAgICAgICAgIGRlbGV0ZSBnZC5sYXlvdXQuaGVpZ2h0O1xuXG4gICAgICAgICAgICAvLyBhdXRvc2l6aW5nIGRvZXNuJ3QgY291bnQgYXMgYSBjaGFuZ2UgdGhhdCBuZWVkcyBzYXZpbmdcbiAgICAgICAgICAgIHZhciBvbGRjaGFuZ2VkID0gZ2QuY2hhbmdlZDtcblxuICAgICAgICAgICAgLy8gbm9yIHNob3VsZCBpdCBiZSBpbmNsdWRlZCBpbiB0aGUgdW5kbyBxdWV1ZVxuICAgICAgICAgICAgZ2QuYXV0b3BsYXkgPSB0cnVlO1xuXG4gICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdyZWxheW91dCcsIGdkLCB7YXV0b3NpemU6IHRydWV9KS50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGdkLmNoYW5nZWQgPSBvbGRjaGFuZ2VkO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZ2QpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIDEwMCk7XG4gICAgfSk7XG59O1xuXG5cbi8vIGZvciB1c2UgaW4gTGliLnN5bmNPckFzeW5jLCBjaGVjayBpZiB0aGVyZSBhcmUgYW55XG4vLyBwZW5kaW5nIHByb21pc2VzIGluIHRoaXMgcGxvdCBhbmQgd2FpdCBmb3IgdGhlbVxucGxvdHMucHJldmlvdXNQcm9taXNlcyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgaWYoKGdkLl9wcm9taXNlcyB8fCBbXSkubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChnZC5fcHJvbWlzZXMpXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbigpIHsgZ2QuX3Byb21pc2VzID0gW107IH0pO1xuICAgIH1cbn07XG5cbi8qKlxuICogQWRkcyB0aGUgJ0VkaXQgY2hhcnQnIGxpbmsuXG4gKiBOb3RlIHRoYXQgbm93IFBsb3RseS5wbG90KCkgY2FsbHMgdGhpcyBzbyBpdCBjYW4gcmVnZW5lcmF0ZSB3aGVuZXZlciBpdCByZXBsb3RzXG4gKlxuICogQWRkIHNvdXJjZSBsaW5rcyB0byB5b3VyIGdyYXBoIGluc2lkZSB0aGUgJ3Nob3dTb3VyY2VzJyBjb25maWcgYXJndW1lbnQuXG4gKi9cbnBsb3RzLmFkZExpbmtzID0gZnVuY3Rpb24oZ2QpIHtcbiAgICAvLyBEbyBub3QgZG8gYW55dGhpbmcgaWYgc2hvd0xpbmsgYW5kIHNob3dTb3VyY2VzIGFyZSBub3Qgc2V0IHRvIHRydWUgaW4gY29uZmlnXG4gICAgaWYoIWdkLl9jb250ZXh0LnNob3dMaW5rICYmICFnZC5fY29udGV4dC5zaG93U291cmNlcykgcmV0dXJuO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHZhciBsaW5rQ29udGFpbmVyID0gTGliLmVuc3VyZVNpbmdsZShmdWxsTGF5b3V0Ll9wYXBlciwgJ3RleHQnLCAnanMtcGxvdC1saW5rLWNvbnRhaW5lcicsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgcy5zdHlsZSh7XG4gICAgICAgICAgICAnZm9udC1mYW1pbHknOiAnXCJPcGVuIFNhbnNcIiwgQXJpYWwsIHNhbnMtc2VyaWYnLFxuICAgICAgICAgICAgJ2ZvbnQtc2l6ZSc6ICcxMnB4JyxcbiAgICAgICAgICAgICdmaWxsJzogQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgICAgICAncG9pbnRlci1ldmVudHMnOiAnYWxsJ1xuICAgICAgICB9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBsaW5rcyA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIGxpbmtzLmFwcGVuZCgndHNwYW4nKS5jbGFzc2VkKCdqcy1saW5rLXRvLXRvb2wnLCB0cnVlKTtcbiAgICAgICAgICAgIGxpbmtzLmFwcGVuZCgndHNwYW4nKS5jbGFzc2VkKCdqcy1saW5rLXNwYWNlcicsIHRydWUpO1xuICAgICAgICAgICAgbGlua3MuYXBwZW5kKCd0c3BhbicpLmNsYXNzZWQoJ2pzLXNvdXJjZWxpbmtzJywgdHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gVGhlIHRleHQgbm9kZSBpbnNpZGUgc3ZnXG4gICAgdmFyIHRleHQgPSBsaW5rQ29udGFpbmVyLm5vZGUoKTtcbiAgICB2YXIgYXR0cnMgPSB7eTogZnVsbExheW91dC5fcGFwZXIuYXR0cignaGVpZ2h0JykgLSA5fTtcblxuICAgIC8vIElmIHRleHQncyB3aWR0aCBpcyBiaWdnZXIgdGhhbiB0aGUgbGF5b3V0XG4gICAgLy8gQ2hlY2sgdGhhdCB0ZXh0IGlzIGEgY2hpbGQgbm9kZSBvciBkb2N1bWVudC5ib2R5XG4gICAgLy8gYmVjYXVzZSBvdGhlcndpc2UgSUUvRWRnZSBtaWdodCB0aHJvdyBhbiBleGNlcHRpb25cbiAgICAvLyB3aGVuIGNhbGxpbmcgZ2V0Q29tcHV0ZWRUZXh0TGVuZ3RoKCkuXG4gICAgLy8gQXBwYXJlbnRseSBvZmZzZXRQYXJlbnQgaXMgbnVsbCBmb3IgaW52aXNpYmxlcy5cbiAgICBpZihkb2N1bWVudC5ib2R5LmNvbnRhaW5zKHRleHQpICYmIHRleHQuZ2V0Q29tcHV0ZWRUZXh0TGVuZ3RoKCkgPj0gKGZ1bGxMYXlvdXQud2lkdGggLSAyMCkpIHtcbiAgICAgICAgLy8gQWxpZ24gdGhlIHRleHQgYXQgdGhlIGxlZnRcbiAgICAgICAgYXR0cnNbJ3RleHQtYW5jaG9yJ10gPSAnc3RhcnQnO1xuICAgICAgICBhdHRycy54ID0gNTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBBbGlnbiB0aGUgdGV4dCBhdCB0aGUgcmlnaHRcbiAgICAgICAgYXR0cnNbJ3RleHQtYW5jaG9yJ10gPSAnZW5kJztcbiAgICAgICAgYXR0cnMueCA9IGZ1bGxMYXlvdXQuX3BhcGVyLmF0dHIoJ3dpZHRoJykgLSA3O1xuICAgIH1cblxuICAgIGxpbmtDb250YWluZXIuYXR0cihhdHRycyk7XG5cbiAgICB2YXIgdG9vbHNwYW4gPSBsaW5rQ29udGFpbmVyLnNlbGVjdCgnLmpzLWxpbmstdG8tdG9vbCcpO1xuICAgIHZhciBzcGFjZXNwYW4gPSBsaW5rQ29udGFpbmVyLnNlbGVjdCgnLmpzLWxpbmstc3BhY2VyJyk7XG4gICAgdmFyIHNvdXJjZXNwYW4gPSBsaW5rQ29udGFpbmVyLnNlbGVjdCgnLmpzLXNvdXJjZWxpbmtzJyk7XG5cbiAgICBpZihnZC5fY29udGV4dC5zaG93U291cmNlcykgZ2QuX2NvbnRleHQuc2hvd1NvdXJjZXMoZ2QpO1xuXG4gICAgLy8gJ3ZpZXcgaW4gcGxvdGx5JyBsaW5rIGZvciBlbWJlZGRlZCBwbG90c1xuICAgIGlmKGdkLl9jb250ZXh0LnNob3dMaW5rKSBwb3NpdGlvblBsYXlXaXRoRGF0YShnZCwgdG9vbHNwYW4pO1xuXG4gICAgLy8gc2VwYXJhdG9yIGlmIHdlIGhhdmUgYm90aCBzb3VyY2VzIGFuZCB0b29sIGxpbmtcbiAgICBzcGFjZXNwYW4udGV4dCgodG9vbHNwYW4udGV4dCgpICYmIHNvdXJjZXNwYW4udGV4dCgpKSA/ICcgLSAnIDogJycpO1xufTtcblxuLy8gbm90ZSB0aGF0IG5vdyB0aGlzIGZ1bmN0aW9uIGlzIG9ubHkgYWRkaW5nIHRoZSBicmFuZCBpblxuLy8gaWZyYW1lcyBhbmQgM3JkLXBhcnR5IGFwcHNcbmZ1bmN0aW9uIHBvc2l0aW9uUGxheVdpdGhEYXRhKGdkLCBjb250YWluZXIpIHtcbiAgICBjb250YWluZXIudGV4dCgnJyk7XG4gICAgdmFyIGxpbmsgPSBjb250YWluZXIuYXBwZW5kKCdhJylcbiAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgJ3hsaW5rOnhsaW5rOmhyZWYnOiAnIycsXG4gICAgICAgICAgICAnY2xhc3MnOiAnbGluay0taW1wdCBsaW5rLS1lbWJlZHZpZXcnLFxuICAgICAgICAgICAgJ2ZvbnQtd2VpZ2h0JzogJ2JvbGQnXG4gICAgICAgIH0pXG4gICAgICAgIC50ZXh0KGdkLl9jb250ZXh0LmxpbmtUZXh0ICsgJyAnICsgU3RyaW5nLmZyb21DaGFyQ29kZSgxODcpKTtcblxuICAgIGlmKGdkLl9jb250ZXh0LnNlbmREYXRhKSB7XG4gICAgICAgIGxpbmsub24oJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBwbG90cy5zZW5kRGF0YVRvQ2xvdWQoZ2QpO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgcGF0aCA9IHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZS5zcGxpdCgnLycpO1xuICAgICAgICB2YXIgcXVlcnkgPSB3aW5kb3cubG9jYXRpb24uc2VhcmNoO1xuICAgICAgICBsaW5rLmF0dHIoe1xuICAgICAgICAgICAgJ3hsaW5rOnhsaW5rOnNob3cnOiAnbmV3JyxcbiAgICAgICAgICAgICd4bGluazp4bGluazpocmVmJzogJy8nICsgcGF0aFsyXS5zcGxpdCgnLicpWzBdICsgJy8nICsgcGF0aFsxXSArIHF1ZXJ5XG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxucGxvdHMuc2VuZERhdGFUb0Nsb3VkID0gZnVuY3Rpb24oZ2QpIHtcbiAgICBnZC5lbWl0KCdwbG90bHlfYmVmb3JlZXhwb3J0Jyk7XG5cbiAgICB2YXIgYmFzZVVybCA9ICh3aW5kb3cuUExPVExZRU5WIHx8IHt9KS5CQVNFX1VSTCB8fCBnZC5fY29udGV4dC5wbG90bHlTZXJ2ZXJVUkw7XG5cbiAgICB2YXIgaGlkZGVuZm9ybURpdiA9IGQzLnNlbGVjdChnZClcbiAgICAgICAgLmFwcGVuZCgnZGl2JylcbiAgICAgICAgLmF0dHIoJ2lkJywgJ2hpZGRlbmZvcm0nKVxuICAgICAgICAuc3R5bGUoJ2Rpc3BsYXknLCAnbm9uZScpO1xuXG4gICAgdmFyIGhpZGRlbmZvcm0gPSBoaWRkZW5mb3JtRGl2XG4gICAgICAgIC5hcHBlbmQoJ2Zvcm0nKVxuICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICBhY3Rpb246IGJhc2VVcmwgKyAnL2V4dGVybmFsJyxcbiAgICAgICAgICAgIG1ldGhvZDogJ3Bvc3QnLFxuICAgICAgICAgICAgdGFyZ2V0OiAnX2JsYW5rJ1xuICAgICAgICB9KTtcblxuICAgIHZhciBoaWRkZW5mb3JtSW5wdXQgPSBoaWRkZW5mb3JtXG4gICAgICAgIC5hcHBlbmQoJ2lucHV0JylcbiAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgdHlwZTogJ3RleHQnLFxuICAgICAgICAgICAgbmFtZTogJ2RhdGEnXG4gICAgICAgIH0pO1xuXG4gICAgaGlkZGVuZm9ybUlucHV0Lm5vZGUoKS52YWx1ZSA9IHBsb3RzLmdyYXBoSnNvbihnZCwgZmFsc2UsICdrZWVwZGF0YScpO1xuICAgIGhpZGRlbmZvcm0ubm9kZSgpLnN1Ym1pdCgpO1xuICAgIGhpZGRlbmZvcm1EaXYucmVtb3ZlKCk7XG5cbiAgICBnZC5lbWl0KCdwbG90bHlfYWZ0ZXJleHBvcnQnKTtcbiAgICByZXR1cm4gZmFsc2U7XG59O1xuXG52YXIgZDNGb3JtYXRLZXlzID0gW1xuICAgICdkYXlzJywgJ3Nob3J0RGF5cycsICdtb250aHMnLCAnc2hvcnRNb250aHMnLCAncGVyaW9kcycsXG4gICAgJ2RhdGVUaW1lJywgJ2RhdGUnLCAndGltZScsXG4gICAgJ2RlY2ltYWwnLCAndGhvdXNhbmRzJywgJ2dyb3VwaW5nJywgJ2N1cnJlbmN5J1xuXTtcblxudmFyIGV4dHJhRm9ybWF0S2V5cyA9IFtcbiAgICAneWVhcicsICdtb250aCcsICdkYXlNb250aCcsICdkYXlNb250aFllYXInXG5dO1xuXG4vKlxuICogRmlsbCBpbiBkZWZhdWx0IHZhbHVlc1xuICogQHBhcmFtIHtET00gZWxlbWVudH0gZ2RcbiAqIEBwYXJhbSB7b2JqZWN0fSBvcHRzXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG9wdHMuc2tpcFVwZGF0ZUNhbGM6IG5vcm1hbGx5IGlmIHRoZSBleGlzdGluZyBnZC5jYWxjZGF0YSBsb29rc1xuICogICBjb21wYXRpYmxlIHdpdGggdGhlIG5ldyBnZC5fZnVsbERhdGEgd2UgZmluaXNoIGJ5IGxpbmtpbmcgdGhlIG5ldyBfZnVsbERhdGEgdHJhY2VzXG4gKiAgIHRvIHRoZSBvbGQgZ2QuY2FsY2RhdGEsIHNvIGl0J3MgY29ycmVjdGx5IHNldCBpZiB3ZSdyZSBub3QgZ29pbmcgdG8gcmVjYWxjLiBCdXQgYWxzbyxcbiAqICAgaWYgdGhlcmUgYXJlIGNhbGNUcmFuc2Zvcm1zIG9uIHRoZSB0cmFjZSwgd2UgZmlyc3QgcmVtYXAgZGF0YSBhcnJheXMgZnJvbSB0aGUgb2xkIGZ1bGxcbiAqICAgdHJhY2UgaW50byB0aGUgbmV3IG9uZS4gVXNlIHNraXBVcGRhdGVDYWxjIHRvIGRlZmVyIHRoaXMgKG5lZWRlZCBieSBQbG90bHkucmVhY3QpXG4gKlxuICogZ2QuZGF0YSwgZ2QubGF5b3V0OlxuICogICBhcmUgcHJlY2lzZWx5IHdoYXQgdGhlIHVzZXIgc3BlY2lmaWVkIChleGNlcHQgYXMgbW9kaWZpZWQgYnkgY2xlYW5EYXRhL2NsZWFuTGF5b3V0KSxcbiAqICAgdGhlc2UgZmllbGRzIHNob3VsZG4ndCBiZSBtb2RpZmllZCAoZXhjZXB0IGZvciBmaWxsaW5nIGluIHNvbWUgYXV0byB2YWx1ZXMpXG4gKiAgIG5vciB1c2VkIGRpcmVjdGx5IGFmdGVyIHRoZSBzdXBwbHkgZGVmYXVsdHMgc3RlcC5cbiAqXG4gKiBnZC5fZnVsbERhdGEsIGdkLl9mdWxsTGF5b3V0OlxuICogICBhcmUgY29tcGxldGUgZGVzY3JpcHRpb25zIG9mIGhvdyB0byBkcmF3IHRoZSBwbG90LFxuICogICB1c2UgdGhlc2UgZmllbGRzIGluIGFsbCByZXF1aXJlZCBjb21wdXRhdGlvbnMuXG4gKlxuICogZ2QuX2Z1bGxMYXlvdXQuX21vZHVsZXNcbiAqICAgaXMgYSBsaXN0IG9mIGFsbCB0aGUgdHJhY2UgbW9kdWxlcyByZXF1aXJlZCB0byBkcmF3IHRoZSBwbG90LlxuICpcbiAqIGdkLl9mdWxsTGF5b3V0Ll92aXNpYmxlTW9kdWxlc1xuICogICBzdWJzZXQgb2YgX21vZHVsZXMsIGEgbGlzdCBvZiBtb2R1bGVzIGNvcnJlc3BvbmRpbmcgdG8gdmlzaWJsZTp0cnVlIHRyYWNlcy5cbiAqXG4gKiBnZC5fZnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzXG4gKiAgIGlzIGEgbGlzdCBvZiBhbGwgdGhlIHBsb3QgbW9kdWxlcyByZXF1aXJlZCB0byBkcmF3IHRoZSBwbG90LlxuICpcbiAqIGdkLl9mdWxsTGF5b3V0Ll90cmFuc2Zvcm1Nb2R1bGVzXG4gKiAgIGlzIGEgbGlzdCBvZiBhbGwgdGhlIHRyYW5zZm9ybSBtb2R1bGVzIGludm9rZWQuXG4gKlxuICovXG5wbG90cy5zdXBwbHlEZWZhdWx0cyA9IGZ1bmN0aW9uKGdkLCBvcHRzKSB7XG4gICAgdmFyIHNraXBVcGRhdGVDYWxjID0gb3B0cyAmJiBvcHRzLnNraXBVcGRhdGVDYWxjO1xuICAgIHZhciBvbGRGdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQgfHwge307XG5cbiAgICBpZihvbGRGdWxsTGF5b3V0Ll9za2lwRGVmYXVsdHMpIHtcbiAgICAgICAgZGVsZXRlIG9sZEZ1bGxMYXlvdXQuX3NraXBEZWZhdWx0cztcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBuZXdGdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQgPSB7fTtcbiAgICB2YXIgbmV3TGF5b3V0ID0gZ2QubGF5b3V0IHx8IHt9O1xuXG4gICAgdmFyIG9sZEZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhIHx8IFtdO1xuICAgIHZhciBuZXdGdWxsRGF0YSA9IGdkLl9mdWxsRGF0YSA9IFtdO1xuICAgIHZhciBuZXdEYXRhID0gZ2QuZGF0YSB8fCBbXTtcblxuICAgIHZhciBvbGRDYWxjZGF0YSA9IGdkLmNhbGNkYXRhIHx8IFtdO1xuXG4gICAgdmFyIGNvbnRleHQgPSBnZC5fY29udGV4dCB8fCB7fTtcblxuICAgIHZhciBpO1xuXG4gICAgLy8gQ3JlYXRlIGFsbCB0aGUgc3RvcmFnZSBzcGFjZSBmb3IgZnJhbWVzLCBidXQgb25seSBpZiBkb2Vzbid0IGFscmVhZHkgZXhpc3RcbiAgICBpZighZ2QuX3RyYW5zaXRpb25EYXRhKSBwbG90cy5jcmVhdGVUcmFuc2l0aW9uRGF0YShnZCk7XG5cbiAgICAvLyBTbyB3ZSBvbmx5IG5lZWQgdG8gZG8gdGhpcyBvbmNlIChhbmQgc2luY2Ugd2UgaGF2ZSBnZCBoZXJlKVxuICAgIC8vIGdldCB0aGUgdHJhbnNsYXRlZCBwbGFjZWhvbGRlciB0aXRsZXMuXG4gICAgLy8gVGhlc2Ugb25lcyBnZXQgdXNlZCBhcyBkZWZhdWx0IHZhbHVlcyBzbyBuZWVkIHRvIGJlIGtub3duIGF0IHN1cHBseURlZmF1bHRzXG4gICAgLy8gb3RoZXJzIGtlZXAgdGhlaXIgYmxhbmsgZGVmYXVsdHMgYnV0IHJlbmRlciB0aGUgcGxhY2Vob2xkZXIgYXMgZGVzaXJlZCBsYXRlclxuICAgIC8vIFRPRE86IG1ha2UgdGhlc2Ugd29yayB0aGUgc2FtZSB3YXksIG9ubHkgaW5zZXJ0aW5nIHRoZSBwbGFjZWhvbGRlciB0ZXh0IGF0IGRyYXcgdGltZT9cbiAgICAvLyBUaGUgY2hhbGxlbmdlIGlzIHRoYXQgdGhpcyBoYXMgc2xpZ2h0bHkgZGlmZmVyZW50IGJlaGF2aW9yIHJpZ2h0IG5vdyBpbiBlZGl0YWJsZSBtb2RlOlxuICAgIC8vIHVzaW5nIHRoZSBwbGFjZWhvbGRlciBhcyBkZWZhdWx0IG1ha2VzIHRoaXMgdGV4dCBwZXJtYW5lbnRseSAoYnV0IGxpZ2h0bHkpIHZpc2libGUsXG4gICAgLy8gYnV0IGV4cGxpY2l0ICcnIGZvciB0aGVzZSB0aXRsZXMgZ2l2ZXMgeW91IGEgcGxhY2Vob2xkZXIgdGhhdCdzIGhpZGRlbiB1bnRpbCB5b3UgbW91c2VcbiAgICAvLyBvdmVyIGl0IC0gc28geW91J3JlIG5vdCBkaXN0cmFjdGVkIGJ5IGl0IGlmIHlvdSByZWFsbHkgZG9uJ3Qgd2FudCBhIHRpdGxlLCBidXQgaWYgeW91IGRvXG4gICAgLy8gYW5kIHlvdSdyZSBuZXcgdG8gcGxvdGx5IHlvdSBtYXkgbm90IGJlIGFibGUgdG8gZmluZCBpdC5cbiAgICAvLyBXaGVuIGVkaXRhYmxlPWZhbHNlIHRoZSB0d28gYmVoYXZlIHRoZSBzYW1lLCBubyB0aXRsZSBpcyBkcmF3bi5cbiAgICBuZXdGdWxsTGF5b3V0Ll9kZmx0VGl0bGUgPSB7XG4gICAgICAgIHBsb3Q6IF8oZ2QsICdDbGljayB0byBlbnRlciBQbG90IHRpdGxlJyksXG4gICAgICAgIHg6IF8oZ2QsICdDbGljayB0byBlbnRlciBYIGF4aXMgdGl0bGUnKSxcbiAgICAgICAgeTogXyhnZCwgJ0NsaWNrIHRvIGVudGVyIFkgYXhpcyB0aXRsZScpLFxuICAgICAgICBjb2xvcmJhcjogXyhnZCwgJ0NsaWNrIHRvIGVudGVyIENvbG9yc2NhbGUgdGl0bGUnKSxcbiAgICAgICAgYW5ub3RhdGlvbjogXyhnZCwgJ25ldyB0ZXh0JylcbiAgICB9O1xuICAgIG5ld0Z1bGxMYXlvdXQuX3RyYWNlV29yZCA9IF8oZ2QsICd0cmFjZScpO1xuXG4gICAgdmFyIGZvcm1hdE9iaiA9IGdldEZvcm1hdE9iaihnZCwgZDNGb3JtYXRLZXlzKTtcblxuICAgIC8vIHN0YXNoIHRoZSB0b2tlbiBmcm9tIGNvbnRleHQgc28gbWFwYm94IHN1YnBsb3RzIGNhbiB1c2UgaXQgYXMgZGVmYXVsdFxuICAgIG5ld0Z1bGxMYXlvdXQuX21hcGJveEFjY2Vzc1Rva2VuID0gY29udGV4dC5tYXBib3hBY2Nlc3NUb2tlbjtcblxuICAgIC8vIGZpcnN0IGZpbGwgaW4gd2hhdCB3ZSBjYW4gb2YgbGF5b3V0IHdpdGhvdXQgbG9va2luZyBhdCBkYXRhXG4gICAgLy8gYmVjYXVzZSBmdWxsRGF0YSBuZWVkcyBhIGZldyB0aGluZ3MgZnJvbSBsYXlvdXRcbiAgICBpZihvbGRGdWxsTGF5b3V0Ll9pbml0aWFsQXV0b1NpemVJc0RvbmUpIHtcbiAgICAgICAgLy8gY29lcmNlIHRoZSB1cGRhdGVkIGxheW91dCB3aGlsZSBwcmVzZXJ2aW5nIHdpZHRoIGFuZCBoZWlnaHRcbiAgICAgICAgdmFyIG9sZFdpZHRoID0gb2xkRnVsbExheW91dC53aWR0aDtcbiAgICAgICAgdmFyIG9sZEhlaWdodCA9IG9sZEZ1bGxMYXlvdXQuaGVpZ2h0O1xuXG4gICAgICAgIHBsb3RzLnN1cHBseUxheW91dEdsb2JhbERlZmF1bHRzKG5ld0xheW91dCwgbmV3RnVsbExheW91dCwgZm9ybWF0T2JqKTtcblxuICAgICAgICBpZighbmV3TGF5b3V0LndpZHRoKSBuZXdGdWxsTGF5b3V0LndpZHRoID0gb2xkV2lkdGg7XG4gICAgICAgIGlmKCFuZXdMYXlvdXQuaGVpZ2h0KSBuZXdGdWxsTGF5b3V0LmhlaWdodCA9IG9sZEhlaWdodDtcbiAgICAgICAgcGxvdHMuc2FuaXRpemVNYXJnaW5zKG5ld0Z1bGxMYXlvdXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGNvZXJjZSB0aGUgdXBkYXRlZCBsYXlvdXQgYW5kIGF1dG9zaXplIGlmIG5lZWRlZFxuICAgICAgICBwbG90cy5zdXBwbHlMYXlvdXRHbG9iYWxEZWZhdWx0cyhuZXdMYXlvdXQsIG5ld0Z1bGxMYXlvdXQsIGZvcm1hdE9iaik7XG5cbiAgICAgICAgdmFyIG1pc3NpbmdXaWR0aE9ySGVpZ2h0ID0gKCFuZXdMYXlvdXQud2lkdGggfHwgIW5ld0xheW91dC5oZWlnaHQpO1xuICAgICAgICB2YXIgYXV0b3NpemUgPSBuZXdGdWxsTGF5b3V0LmF1dG9zaXplO1xuICAgICAgICB2YXIgYXV0b3NpemFibGUgPSBjb250ZXh0LmF1dG9zaXphYmxlO1xuICAgICAgICB2YXIgaW5pdGlhbEF1dG9TaXplID0gbWlzc2luZ1dpZHRoT3JIZWlnaHQgJiYgKGF1dG9zaXplIHx8IGF1dG9zaXphYmxlKTtcblxuICAgICAgICBpZihpbml0aWFsQXV0b1NpemUpIHBsb3RzLnBsb3RBdXRvU2l6ZShnZCwgbmV3TGF5b3V0LCBuZXdGdWxsTGF5b3V0KTtcbiAgICAgICAgZWxzZSBpZihtaXNzaW5nV2lkdGhPckhlaWdodCkgcGxvdHMuc2FuaXRpemVNYXJnaW5zKG5ld0Z1bGxMYXlvdXQpO1xuXG4gICAgICAgIC8vIGZvciBiYWNrd2FyZHMtY29tcGF0aWJpbGl0eSB3aXRoIFBsb3RseSB2MS54LnhcbiAgICAgICAgaWYoIWF1dG9zaXplICYmIG1pc3NpbmdXaWR0aE9ySGVpZ2h0KSB7XG4gICAgICAgICAgICBuZXdMYXlvdXQud2lkdGggPSBuZXdGdWxsTGF5b3V0LndpZHRoO1xuICAgICAgICAgICAgbmV3TGF5b3V0LmhlaWdodCA9IG5ld0Z1bGxMYXlvdXQuaGVpZ2h0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmV3RnVsbExheW91dC5fZDNsb2NhbGUgPSBnZXRGb3JtYXR0ZXIoZm9ybWF0T2JqLCBuZXdGdWxsTGF5b3V0LnNlcGFyYXRvcnMpO1xuICAgIG5ld0Z1bGxMYXlvdXQuX2V4dHJhRm9ybWF0ID0gZ2V0Rm9ybWF0T2JqKGdkLCBleHRyYUZvcm1hdEtleXMpO1xuXG4gICAgbmV3RnVsbExheW91dC5faW5pdGlhbEF1dG9TaXplSXNEb25lID0gdHJ1ZTtcblxuICAgIC8vIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkgdHJhY2VzIGFyZSBpbnB1dHRlZFxuICAgIG5ld0Z1bGxMYXlvdXQuX2RhdGFMZW5ndGggPSBuZXdEYXRhLmxlbmd0aDtcblxuICAgIC8vIGNsZWFyIHRoZSBsaXN0cyBvZiB0cmFjZSBhbmQgYmFzZXBsb3QgbW9kdWxlcywgYW5kIHN1YnBsb3RzXG4gICAgbmV3RnVsbExheW91dC5fbW9kdWxlcyA9IFtdO1xuICAgIG5ld0Z1bGxMYXlvdXQuX3Zpc2libGVNb2R1bGVzID0gW107XG4gICAgbmV3RnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzID0gW107XG4gICAgdmFyIHN1YnBsb3RzID0gbmV3RnVsbExheW91dC5fc3VicGxvdHMgPSBlbXB0eVN1YnBsb3RMaXN0cygpO1xuXG4gICAgLy8gaW5pdGlhbGl6ZSBheGlzIGFuZCBzdWJwbG90IGhhc2ggb2JqZWN0cyBmb3Igc3Bsb20tZ2VuZXJhdGVkIGdyaWRzXG4gICAgdmFyIHNwbG9tQXhlcyA9IG5ld0Z1bGxMYXlvdXQuX3NwbG9tQXhlcyA9IHt4OiB7fSwgeToge319O1xuICAgIHZhciBzcGxvbVN1YnBsb3RzID0gbmV3RnVsbExheW91dC5fc3Bsb21TdWJwbG90cyA9IHt9O1xuICAgIC8vIGluaXRpYWxpemUgc3Bsb20gZ3JpZCBkZWZhdWx0c1xuICAgIG5ld0Z1bGxMYXlvdXQuX3NwbG9tR3JpZERmbHQgPSB7fTtcblxuICAgIC8vIGZvciBzdGFja2VkIGFyZWEgdHJhY2VzIHRvIHNoYXJlIGNvbmZpZyBhY3Jvc3MgdHJhY2VzXG4gICAgbmV3RnVsbExheW91dC5fc2NhdHRlclN0YWNrT3B0cyA9IHt9O1xuICAgIC8vIGZvciB0aGUgZmlyc3Qgc2NhdHRlciB0cmFjZSBvbiBlYWNoIHN1YnBsb3QgKHNvIGl0IGtub3dzIHRvbmV4dC0+dG96ZXJvKVxuICAgIG5ld0Z1bGxMYXlvdXQuX2ZpcnN0U2NhdHRlciA9IHt9O1xuICAgIC8vIGZvciBncm91cGVkIGJhci9ib3gvdmlvbGluIHRyYWNlIHRvIHNoYXJlIGNvbmZpZyBhY3Jvc3MgdHJhY2VzXG4gICAgbmV3RnVsbExheW91dC5fYWxpZ25tZW50T3B0cyA9IHt9O1xuICAgIC8vIHRyYWNrIGNvbG9yIGF4ZXMgcmVmZXJlbmNlZCBpbiB0aGUgZGF0YVxuICAgIG5ld0Z1bGxMYXlvdXQuX2NvbG9yQXhlcyA9IHt9O1xuXG4gICAgLy8gZm9yIHRyYWNlcyB0byByZXF1ZXN0IGEgZGVmYXVsdCByYW5nZXNsaWRlciBvbiB0aGVpciB4IGF4ZXNcbiAgICAvLyBlZyBzZXQgYF9yZXF1ZXN0UmFuZ2VzbGlkZXIueDIgPSB0cnVlYCBmb3IgeGF4aXMyXG4gICAgbmV3RnVsbExheW91dC5fcmVxdWVzdFJhbmdlc2xpZGVyID0ge307XG5cbiAgICAvLyBwdWxsIHVpZHMgZnJvbSBvbGQgZGF0YSB0byB1c2UgYXMgbmV3IGRlZmF1bHRzXG4gICAgbmV3RnVsbExheW91dC5fdHJhY2VVaWRzID0gZ2V0VHJhY2VVaWRzKG9sZEZ1bGxEYXRhLCBuZXdEYXRhKTtcblxuICAgIC8vIHRoZW4gZG8gdGhlIGRhdGFcbiAgICBuZXdGdWxsTGF5b3V0Ll9nbG9iYWxUcmFuc2Zvcm1zID0gKGdkLl9jb250ZXh0IHx8IHt9KS5nbG9iYWxUcmFuc2Zvcm1zO1xuICAgIHBsb3RzLnN1cHBseURhdGFEZWZhdWx0cyhuZXdEYXRhLCBuZXdGdWxsRGF0YSwgbmV3TGF5b3V0LCBuZXdGdWxsTGF5b3V0KTtcblxuICAgIC8vIHJlZG8gZ3JpZCBzaXplIGRlZmF1bHRzIHdpdGggaW5mbyBhYm91dCBzcGxvbSB4L3kgYXhlcyxcbiAgICAvLyBhbmQgZmlsbCBpbiBnZW5lcmF0ZWQgY2FydGVzaWFuIGF4ZXMgYW5kIHN1YnBsb3RzXG4gICAgdmFyIHNwbG9tWGEgPSBPYmplY3Qua2V5cyhzcGxvbUF4ZXMueCk7XG4gICAgdmFyIHNwbG9tWWEgPSBPYmplY3Qua2V5cyhzcGxvbUF4ZXMueSk7XG4gICAgaWYoc3Bsb21YYS5sZW5ndGggPiAxICYmIHNwbG9tWWEubGVuZ3RoID4gMSkge1xuICAgICAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2dyaWQnLCAnc2l6ZURlZmF1bHRzJykobmV3TGF5b3V0LCBuZXdGdWxsTGF5b3V0KTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBzcGxvbVhhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBMaWIucHVzaFVuaXF1ZShzdWJwbG90cy54YXhpcywgc3Bsb21YYVtpXSk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc3Bsb21ZYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUoc3VicGxvdHMueWF4aXMsIHNwbG9tWWFbaV0pO1xuICAgICAgICB9XG4gICAgICAgIGZvcih2YXIgayBpbiBzcGxvbVN1YnBsb3RzKSB7XG4gICAgICAgICAgICBMaWIucHVzaFVuaXF1ZShzdWJwbG90cy5jYXJ0ZXNpYW4sIGspO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gYXR0YWNoIGhlbHBlciBtZXRob2QgdG8gY2hlY2sgd2hldGhlciBhIHBsb3QgdHlwZSBpcyBwcmVzZW50IG9uIGdyYXBoXG4gICAgbmV3RnVsbExheW91dC5faGFzID0gcGxvdHMuX2hhc1Bsb3RUeXBlLmJpbmQobmV3RnVsbExheW91dCk7XG5cbiAgICBpZihvbGRGdWxsRGF0YS5sZW5ndGggPT09IG5ld0Z1bGxEYXRhLmxlbmd0aCkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBuZXdGdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgcmVsaW5rUHJpdmF0ZUtleXMobmV3RnVsbERhdGFbaV0sIG9sZEZ1bGxEYXRhW2ldKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGZpbmFsbHksIGZpbGwgaW4gdGhlIHBpZWNlcyBvZiBsYXlvdXQgdGhhdCBtYXkgbmVlZCB0byBsb29rIGF0IGRhdGFcbiAgICBwbG90cy5zdXBwbHlMYXlvdXRNb2R1bGVEZWZhdWx0cyhuZXdMYXlvdXQsIG5ld0Z1bGxMYXlvdXQsIG5ld0Z1bGxEYXRhLCBnZC5fdHJhbnNpdGlvbkRhdGEpO1xuXG4gICAgLy8gU3BlY2lhbCBjYXNlcyB0aGF0IGludHJvZHVjZSBpbnRlcmFjdGlvbnMgYmV0d2VlbiB0cmFjZXMuXG4gICAgLy8gVGhpcyBpcyBhZnRlciByZWxpbmtQcml2YXRlS2V5cyBzbyB3ZSBjYW4gdXNlIHRob3NlIGluIGNyb3NzVHJhY2VEZWZhdWx0c1xuICAgIC8vIGFuZCBhZnRlciBsYXlvdXQgbW9kdWxlIGRlZmF1bHRzLCBzbyB3ZSBjYW4gdXNlIGVnIGJhcm1vZGVcbiAgICB2YXIgX21vZHVsZXMgPSBuZXdGdWxsTGF5b3V0Ll92aXNpYmxlTW9kdWxlcztcbiAgICB2YXIgY3Jvc3NUcmFjZURlZmF1bHRzRnVuY3MgPSBbXTtcbiAgICBmb3IoaSA9IDA7IGkgPCBfbW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZnVuY2kgPSBfbW9kdWxlc1tpXS5jcm9zc1RyYWNlRGVmYXVsdHM7XG4gICAgICAgIC8vIHNvbWUgdHJhY2UgdHlwZXMgc2hhcmUgY3Jvc3NUcmFjZURlZmF1bHRzIChpZSBoaXN0b2dyYW0yZCwgaGlzdG9ncmFtMmRjb250b3VyKVxuICAgICAgICBpZihmdW5jaSkgTGliLnB1c2hVbmlxdWUoY3Jvc3NUcmFjZURlZmF1bHRzRnVuY3MsIGZ1bmNpKTtcbiAgICB9XG4gICAgZm9yKGkgPSAwOyBpIDwgY3Jvc3NUcmFjZURlZmF1bHRzRnVuY3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY3Jvc3NUcmFjZURlZmF1bHRzRnVuY3NbaV0obmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQpO1xuICAgIH1cblxuICAgIC8vIHR1cm4gb24gZmxhZyB0byBvcHRpbWl6ZSBsYXJnZSBzcGxvbS1vbmx5IGdyYXBoc1xuICAgIC8vIG1vc3RseSBieSBvbWl0dGluZyBTVkcgbGF5ZXJzIGR1cmluZyBDYXJ0ZXNpYW4uZHJhd0ZyYW1ld29ya1xuICAgIG5ld0Z1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcyA9IChcbiAgICAgICAgbmV3RnVsbExheW91dC5fYmFzZVBsb3RNb2R1bGVzLmxlbmd0aCA9PT0gMSAmJlxuICAgICAgICBuZXdGdWxsTGF5b3V0Ll9iYXNlUGxvdE1vZHVsZXNbMF0ubmFtZSA9PT0gJ3NwbG9tJyAmJlxuICAgICAgICBzcGxvbVhhLmxlbmd0aCA+IDE1ICYmXG4gICAgICAgIHNwbG9tWWEubGVuZ3RoID4gMTUgJiZcbiAgICAgICAgbmV3RnVsbExheW91dC5zaGFwZXMubGVuZ3RoID09PSAwICYmXG4gICAgICAgIG5ld0Z1bGxMYXlvdXQuaW1hZ2VzLmxlbmd0aCA9PT0gMFxuICAgICk7XG5cbiAgICAvLyBUT0RPIHJlbW92ZSBpbiB2Mi4wLjBcbiAgICAvLyBhZGQgaGFzLXBsb3QtdHlwZSByZWZzIHRvIGZ1bGxMYXlvdXQgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbiAgICBuZXdGdWxsTGF5b3V0Ll9oYXNDYXJ0ZXNpYW4gPSBuZXdGdWxsTGF5b3V0Ll9oYXMoJ2NhcnRlc2lhbicpO1xuICAgIG5ld0Z1bGxMYXlvdXQuX2hhc0dlbyA9IG5ld0Z1bGxMYXlvdXQuX2hhcygnZ2VvJyk7XG4gICAgbmV3RnVsbExheW91dC5faGFzR0wzRCA9IG5ld0Z1bGxMYXlvdXQuX2hhcygnZ2wzZCcpO1xuICAgIG5ld0Z1bGxMYXlvdXQuX2hhc0dMMkQgPSBuZXdGdWxsTGF5b3V0Ll9oYXMoJ2dsMmQnKTtcbiAgICBuZXdGdWxsTGF5b3V0Ll9oYXNUZXJuYXJ5ID0gbmV3RnVsbExheW91dC5faGFzKCd0ZXJuYXJ5Jyk7XG4gICAgbmV3RnVsbExheW91dC5faGFzUGllID0gbmV3RnVsbExheW91dC5faGFzKCdwaWUnKTtcblxuICAgIC8vIHJlbGluayAvIGluaXRpYWxpemUgc3VicGxvdCBheGlzIG9iamVjdHNcbiAgICBwbG90cy5saW5rU3VicGxvdHMobmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxEYXRhLCBvbGRGdWxsTGF5b3V0KTtcblxuICAgIC8vIGNsZWFuIHN1YnBsb3RzIGFuZCBvdGhlciBhcnRpZmFjdHMgZnJvbSBwcmV2aW91cyBwbG90IGNhbGxzXG4gICAgcGxvdHMuY2xlYW5QbG90KG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCk7XG5cbiAgICAvLyBjbGVhciBzZWxlY3Rpb24gb3V0bGluZSB1bnRpbCB3ZSBpbXBsZW1lbnQgcGVyc2lzdGVudCBzZWxlY3Rpb24sXG4gICAgLy8gZG9uJ3QgY2xlYXIgdGhlbSB0aG91Z2ggd2hlbiBkcmFnIGhhbmRsZXJzIChlLmcuIGxpc3RlbmluZyB0b1xuICAgIC8vIGBwbG90bHlfc2VsZWN0aW5nYCkgdXBkYXRlIHRoZSBncmFwaC5cbiAgICAvLyB3ZSBzaG91bGQgdHJ5IHRvIGNvbWUgdXAgd2l0aCBhIGJldHRlciBzb2x1dGlvbiB3aGVuIGltcGxlbWVudGluZ1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2lzc3Vlcy8xODUxXG4gICAgaWYob2xkRnVsbExheW91dC5fem9vbWxheWVyICYmICFnZC5fZHJhZ2dpbmcpIHtcbiAgICAgICAgb2xkRnVsbExheW91dC5fem9vbWxheWVyLnNlbGVjdEFsbCgnLnNlbGVjdC1vdXRsaW5lJykucmVtb3ZlKCk7XG4gICAgfVxuXG5cbiAgICAvLyBmaWxsIGluIG1ldGEgaGVscGVyc1xuICAgIGZpbGxNZXRhVGV4dEhlbHBlcnMobmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQpO1xuXG4gICAgLy8gcmVsaW5rIGZ1bmN0aW9ucyBhbmQgXyBhdHRyaWJ1dGVzIHRvIHByb21vdGUgY29uc2lzdGVuY3kgYmV0d2VlbiBwbG90c1xuICAgIHJlbGlua1ByaXZhdGVLZXlzKG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxMYXlvdXQpO1xuXG4gICAgLy8gY29sb3JzY2FsZSBjcm9zc1RyYWNlRGVmYXVsdHMgbmVlZHMgbmV3RnVsbExheW91dCB3aXRoIHJlbGlua2VkIGtleXNcbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NvbG9yc2NhbGUnLCAnY3Jvc3NUcmFjZURlZmF1bHRzJykobmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQpO1xuXG4gICAgLy8gRm9yIHBlcnNpc3RpbmcgR1VJLWRyaXZlbiBjaGFuZ2VzIGluIGxheW91dFxuICAgIC8vIF9wcmVHVUkgYW5kIF90cmFjZVByZUdVSSB3ZXJlIGFscmVhZHkgY29waWVkIG92ZXIgaW4gcmVsaW5rUHJpdmF0ZUtleXNcbiAgICBpZighbmV3RnVsbExheW91dC5fcHJlR1VJKSBuZXdGdWxsTGF5b3V0Ll9wcmVHVUkgPSB7fTtcbiAgICAvLyB0cmFjayB0cmFjZSBHVUkgY2hhbmdlcyBieSB1aWQgcmF0aGVyIHRoYW4gYnkgdHJhY2UgaW5kZXhcbiAgICBpZighbmV3RnVsbExheW91dC5fdHJhY2VQcmVHVUkpIG5ld0Z1bGxMYXlvdXQuX3RyYWNlUHJlR1VJID0ge307XG4gICAgdmFyIHRyYWNlUHJlR1VJID0gbmV3RnVsbExheW91dC5fdHJhY2VQcmVHVUk7XG4gICAgdmFyIHVpZHMgPSB7fTtcbiAgICB2YXIgdWlkO1xuICAgIGZvcih1aWQgaW4gdHJhY2VQcmVHVUkpIHVpZHNbdWlkXSA9ICdvbGQnO1xuICAgIGZvcihpID0gMDsgaSA8IG5ld0Z1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHVpZCA9IG5ld0Z1bGxEYXRhW2ldLl9mdWxsSW5wdXQudWlkO1xuICAgICAgICBpZighdWlkc1t1aWRdKSB0cmFjZVByZUdVSVt1aWRdID0ge307XG4gICAgICAgIHVpZHNbdWlkXSA9ICduZXcnO1xuICAgIH1cbiAgICBmb3IodWlkIGluIHVpZHMpIHtcbiAgICAgICAgaWYodWlkc1t1aWRdID09PSAnb2xkJykgZGVsZXRlIHRyYWNlUHJlR1VJW3VpZF07XG4gICAgfVxuXG4gICAgLy8gc2V0IHVwIGNvbnRhaW5lcnMgZm9yIG1hcmdpbiBjYWxjdWxhdGlvbnNcbiAgICBpbml0TWFyZ2lucyhuZXdGdWxsTGF5b3V0KTtcblxuICAgIC8vIGNvbGxlY3QgYW5kIGRvIHNvbWUgaW5pdGlhbCBjYWxjdWxhdGlvbnMgZm9yIHJhbmdlc2xpZGVyc1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgncmFuZ2VzbGlkZXInLCAnbWFrZURhdGEnKShuZXdGdWxsTGF5b3V0KTtcblxuICAgIC8vIHVwZGF0ZSBvYmplY3QgcmVmZXJlbmNlcyBpbiBjYWxjZGF0YVxuICAgIGlmKCFza2lwVXBkYXRlQ2FsYyAmJiBvbGRDYWxjZGF0YS5sZW5ndGggPT09IG5ld0Z1bGxEYXRhLmxlbmd0aCkge1xuICAgICAgICBwbG90cy5zdXBwbHlEZWZhdWx0c1VwZGF0ZUNhbGMob2xkQ2FsY2RhdGEsIG5ld0Z1bGxEYXRhKTtcbiAgICB9XG59O1xuXG5wbG90cy5zdXBwbHlEZWZhdWx0c1VwZGF0ZUNhbGMgPSBmdW5jdGlvbihvbGRDYWxjZGF0YSwgbmV3RnVsbERhdGEpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbmV3RnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG5ld1RyYWNlID0gbmV3RnVsbERhdGFbaV07XG4gICAgICAgIHZhciBjZDAgPSAob2xkQ2FsY2RhdGFbaV0gfHwgW10pWzBdO1xuICAgICAgICBpZihjZDAgJiYgY2QwLnRyYWNlKSB7XG4gICAgICAgICAgICB2YXIgb2xkVHJhY2UgPSBjZDAudHJhY2U7XG4gICAgICAgICAgICBpZihvbGRUcmFjZS5faGFzQ2FsY1RyYW5zZm9ybSkge1xuICAgICAgICAgICAgICAgIHZhciBhcnJheUF0dHJzID0gb2xkVHJhY2UuX2FycmF5QXR0cnM7XG4gICAgICAgICAgICAgICAgdmFyIGosIGFzdHIsIG9sZEFycmF5VmFsO1xuXG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgYXJyYXlBdHRycy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBhc3RyID0gYXJyYXlBdHRyc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgb2xkQXJyYXlWYWwgPSBMaWIubmVzdGVkUHJvcGVydHkob2xkVHJhY2UsIGFzdHIpLmdldCgpLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgIExpYi5uZXN0ZWRQcm9wZXJ0eShuZXdUcmFjZSwgYXN0cikuc2V0KG9sZEFycmF5VmFsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjZDAudHJhY2UgPSBuZXdUcmFjZTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qKlxuICogQ3JlYXRlIGEgbGlzdCBvZiB1aWQgc3RyaW5ncyBzYXRpc2Z5aW5nIChpbiB0aGlzIG9yZGVyIG9mIGltcG9ydGFuY2UpOlxuICogMS4gYWxsIHVuaXF1ZSwgYWxsIHN0cmluZ3NcbiAqIDIuIG1hdGNoZXMgaW5wdXQgdWlkcyBpZiBwcm92aWRlZFxuICogMy4gbWF0Y2hlcyBwcmV2aW91cyBkYXRhIHVpZHNcbiAqL1xuZnVuY3Rpb24gZ2V0VHJhY2VVaWRzKG9sZEZ1bGxEYXRhLCBuZXdEYXRhKSB7XG4gICAgdmFyIGxlbiA9IG5ld0RhdGEubGVuZ3RoO1xuICAgIHZhciBvbGRGdWxsSW5wdXQgPSBbXTtcbiAgICB2YXIgaSwgcHJldkZ1bGxJbnB1dDtcbiAgICBmb3IoaSA9IDA7IGkgPCBvbGRGdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdGhpc0Z1bGxJbnB1dCA9IG9sZEZ1bGxEYXRhW2ldLl9mdWxsSW5wdXQ7XG4gICAgICAgIGlmKHRoaXNGdWxsSW5wdXQgIT09IHByZXZGdWxsSW5wdXQpIG9sZEZ1bGxJbnB1dC5wdXNoKHRoaXNGdWxsSW5wdXQpO1xuICAgICAgICBwcmV2RnVsbElucHV0ID0gdGhpc0Z1bGxJbnB1dDtcbiAgICB9XG4gICAgdmFyIG9sZExlbiA9IG9sZEZ1bGxJbnB1dC5sZW5ndGg7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgIHZhciBzZWVuVWlkcyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gc2V0VWlkKHVpZCwgaSkge1xuICAgICAgICBvdXRbaV0gPSB1aWQ7XG4gICAgICAgIHNlZW5VaWRzW3VpZF0gPSAxO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyeVVpZCh1aWQsIGkpIHtcbiAgICAgICAgaWYodWlkICYmIHR5cGVvZiB1aWQgPT09ICdzdHJpbmcnICYmICFzZWVuVWlkc1t1aWRdKSB7XG4gICAgICAgICAgICBzZXRVaWQodWlkLCBpKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIG5ld1VpZCA9IG5ld0RhdGFbaV0udWlkO1xuICAgICAgICBpZih0eXBlb2YgbmV3VWlkID09PSAnbnVtYmVyJykgbmV3VWlkID0gU3RyaW5nKG5ld1VpZCk7XG5cbiAgICAgICAgaWYodHJ5VWlkKG5ld1VpZCwgaSkpIGNvbnRpbnVlO1xuICAgICAgICBpZihpIDwgb2xkTGVuICYmIHRyeVVpZChvbGRGdWxsSW5wdXRbaV0udWlkLCBpKSkgY29udGludWU7XG4gICAgICAgIHNldFVpZChMaWIucmFuZHN0cihzZWVuVWlkcyksIGkpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogTWFrZSBhIGNvbnRhaW5lciBmb3IgY29sbGVjdGluZyBzdWJwbG90cyB3ZSBuZWVkIHRvIGRpc3BsYXkuXG4gKlxuICogRmluZHMgYWxsIHN1YnBsb3QgdHlwZXMgd2UgbmVlZCB0byBlbnVtZXJhdGUgb25jZSBhbmQgY2FjaGVzIGl0LFxuICogYnV0IG1ha2VzIGEgbmV3IG91dHB1dCBvYmplY3QgZWFjaCB0aW1lLlxuICogU2luZ2xlLXRyYWNlIHN1YnBsb3RzICh3aGljaCBoYXZlIG5vIGBpZGApIHN1Y2ggYXMgcGllLCB0YWJsZSwgZXRjXG4gKiBkbyBub3QgbmVlZCB0byBiZSBjb2xsZWN0ZWQgYmVjYXVzZSB3ZSBqdXN0IGRyYXcgYWxsIHZpc2libGUgdHJhY2VzLlxuICovXG5mdW5jdGlvbiBlbXB0eVN1YnBsb3RMaXN0cygpIHtcbiAgICB2YXIgY29sbGVjdGFibGVTdWJwbG90VHlwZXMgPSBSZWdpc3RyeS5jb2xsZWN0YWJsZVN1YnBsb3RUeXBlcztcbiAgICB2YXIgb3V0ID0ge307XG4gICAgdmFyIGksIGo7XG5cbiAgICBpZighY29sbGVjdGFibGVTdWJwbG90VHlwZXMpIHtcbiAgICAgICAgY29sbGVjdGFibGVTdWJwbG90VHlwZXMgPSBbXTtcblxuICAgICAgICB2YXIgc3VicGxvdHNSZWdpc3RyeSA9IFJlZ2lzdHJ5LnN1YnBsb3RzUmVnaXN0cnk7XG5cbiAgICAgICAgZm9yKHZhciBzdWJwbG90VHlwZSBpbiBzdWJwbG90c1JlZ2lzdHJ5KSB7XG4gICAgICAgICAgICB2YXIgc3VicGxvdE1vZHVsZSA9IHN1YnBsb3RzUmVnaXN0cnlbc3VicGxvdFR5cGVdO1xuICAgICAgICAgICAgdmFyIHN1YnBsb3RBdHRyID0gc3VicGxvdE1vZHVsZS5hdHRyO1xuXG4gICAgICAgICAgICBpZihzdWJwbG90QXR0cikge1xuICAgICAgICAgICAgICAgIGNvbGxlY3RhYmxlU3VicGxvdFR5cGVzLnB1c2goc3VicGxvdFR5cGUpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3BlY2lhbCBjYXNlLCBjdXJyZW50bHkganVzdCBmb3IgY2FydGVzaWFuOlxuICAgICAgICAgICAgICAgIC8vIHdlIG5lZWQgdG8gZW51bWVyYXRlIGF4ZXMsIG5vdCBqdXN0IHN1YnBsb3RzXG4gICAgICAgICAgICAgICAgaWYoQXJyYXkuaXNBcnJheShzdWJwbG90QXR0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgc3VicGxvdEF0dHIubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExpYi5wdXNoVW5pcXVlKGNvbGxlY3RhYmxlU3VicGxvdFR5cGVzLCBzdWJwbG90QXR0cltqXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBjb2xsZWN0YWJsZVN1YnBsb3RUeXBlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBvdXRbY29sbGVjdGFibGVTdWJwbG90VHlwZXNbaV1dID0gW107XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogZ2V0Rm9ybWF0T2JqOiB1c2UgX2NvbnRleHQgdG8gZ2V0IHRoZSBmb3JtYXQgb2JqZWN0IGZyb20gbG9jYWxlLlxuICogVXNlZCB0byBnZXQgZDMubG9jYWxlIGFyZ3VtZW50IG9iamVjdCBhbmQgZXh0cmFGb3JtYXQgYXJndW1lbnQgb2JqZWN0XG4gKlxuICogUmVnYXJkaW5nIGQzLmxvY2FsZSBhcmd1bWVudCA6XG4gKiBkZWNpbWFsIGFuZCB0aG91c2FuZHMgY2FuIGJlIG92ZXJyaWRkZW4gbGF0ZXIgYnkgbGF5b3V0LnNlcGFyYXRvcnNcbiAqIGdyb3VwaW5nIGFuZCBjdXJyZW5jeSBhcmUgbm90IHByZXNlbnRseSB1c2VkIGJ5IG91ciBhdXRvbWF0aWMgbnVtYmVyXG4gKiBmb3JtYXR0aW5nIHN5c3RlbSBidXQgY2FuIGJlIHVzZWQgYnkgY3VzdG9tIGZvcm1hdHMuXG4gKlxuICogQHJldHVybnMge29iamVjdH0gZDMubG9jYWxlIGZvcm1hdCBvYmplY3RcbiAqL1xuZnVuY3Rpb24gZ2V0Rm9ybWF0T2JqKGdkLCBmb3JtYXRLZXlzKSB7XG4gICAgdmFyIGxvY2FsZSA9IGdkLl9jb250ZXh0LmxvY2FsZTtcbiAgICBpZighbG9jYWxlKSBsb2NhbGUgPT09ICdlbi1VUyc7XG5cbiAgICB2YXIgZm9ybWF0RG9uZSA9IGZhbHNlO1xuICAgIHZhciBmb3JtYXRPYmogPSB7fTtcblxuICAgIGZ1bmN0aW9uIGluY2x1ZGVGb3JtYXQobmV3Rm9ybWF0KSB7XG4gICAgICAgIHZhciBmb3JtYXRGaW5pc2hlZCA9IHRydWU7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmb3JtYXRLZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZm9ybWF0S2V5ID0gZm9ybWF0S2V5c1tpXTtcbiAgICAgICAgICAgIGlmKCFmb3JtYXRPYmpbZm9ybWF0S2V5XSkge1xuICAgICAgICAgICAgICAgIGlmKG5ld0Zvcm1hdFtmb3JtYXRLZXldKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1hdE9ialtmb3JtYXRLZXldID0gbmV3Rm9ybWF0W2Zvcm1hdEtleV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGZvcm1hdEZpbmlzaGVkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYoZm9ybWF0RmluaXNoZWQpIGZvcm1hdERvbmUgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIHNhbWUgYXMgbG9jYWxpemUsIGxvb2sgZm9yIGZvcm1hdCBwYXJ0cyBpbiBlYWNoIGZvcm1hdCBzcGVjIGluIHRoZSBjaGFpblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICAgICAgdmFyIGxvY2FsZXMgPSBnZC5fY29udGV4dC5sb2NhbGVzO1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgMjsgaisrKSB7XG4gICAgICAgICAgICB2YXIgZm9ybWF0aiA9IChsb2NhbGVzW2xvY2FsZV0gfHwge30pLmZvcm1hdDtcbiAgICAgICAgICAgIGlmKGZvcm1hdGopIHtcbiAgICAgICAgICAgICAgICBpbmNsdWRlRm9ybWF0KGZvcm1hdGopO1xuICAgICAgICAgICAgICAgIGlmKGZvcm1hdERvbmUpIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbG9jYWxlcyA9IFJlZ2lzdHJ5LmxvY2FsZVJlZ2lzdHJ5O1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGJhc2VMb2NhbGUgPSBsb2NhbGUuc3BsaXQoJy0nKVswXTtcbiAgICAgICAgaWYoZm9ybWF0RG9uZSB8fCBiYXNlTG9jYWxlID09PSBsb2NhbGUpIGJyZWFrO1xuICAgICAgICBsb2NhbGUgPSBiYXNlTG9jYWxlO1xuICAgIH1cblxuICAgIC8vIGxhc3RseSBwaWNrIG91dCBkZWZhdWx0cyBmcm9tIGVuZ2xpc2ggKG5vbi1VUywgYXMgRE1ZIGlzIHNvIG11Y2ggbW9yZSBjb21tb24pXG4gICAgaWYoIWZvcm1hdERvbmUpIGluY2x1ZGVGb3JtYXQoUmVnaXN0cnkubG9jYWxlUmVnaXN0cnkuZW4uZm9ybWF0KTtcblxuICAgIHJldHVybiBmb3JtYXRPYmo7XG59XG5cbi8qKlxuICogZ2V0Rm9ybWF0dGVyOiBjb21iaW5lIHRoZSBmaW5hbCBzZXBhcmF0b3JzIHdpdGggdGhlIGxvY2FsZSBmb3JtYXR0aW5nIG9iamVjdFxuICogd2UgcHVsbGVkIGVhcmxpZXIgdG8gZ2VuZXJhdGUgbnVtYmVyIGFuZCB0aW1lIGZvcm1hdHRlcnNcbiAqIFRPRE86IHJlbW92ZSBzZXBhcmF0b3JzIGluIHYyLCBvbmx5IHVzZSBsb2NhbGUsIHNvIHdlIGRvbid0IG5lZWQgdGhpcyBzdGVwP1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBmb3JtYXRPYmo6IGQzLmxvY2FsZSBmb3JtYXQgb2JqZWN0XG4gKiBAcGFyYW0ge3N0cmluZ30gc2VwYXJhdG9yczogbGVuZ3RoLTIgc3RyaW5nIHRvIG92ZXJyaWRlIGRlY2ltYWwgYW5kIHRob3VzYW5kc1xuICogICBzZXBhcmF0b3JzIGluIG51bWJlciBmb3JtYXR0aW5nXG4gKlxuICogQHJldHVybnMge29iamVjdH0ge251bWJlckZvcm1hdCwgdGltZUZvcm1hdH0gZDMgZm9ybWF0dGVyIGZhY3RvcnkgZnVuY3Rpb25zXG4gKiAgIGZvciBudW1iZXJzIGFuZCB0aW1lXG4gKi9cbmZ1bmN0aW9uIGdldEZvcm1hdHRlcihmb3JtYXRPYmosIHNlcGFyYXRvcnMpIHtcbiAgICBmb3JtYXRPYmouZGVjaW1hbCA9IHNlcGFyYXRvcnMuY2hhckF0KDApO1xuICAgIGZvcm1hdE9iai50aG91c2FuZHMgPSBzZXBhcmF0b3JzLmNoYXJBdCgxKTtcblxuICAgIHJldHVybiBkMy5sb2NhbGUoZm9ybWF0T2JqKTtcbn1cblxuZnVuY3Rpb24gZmlsbE1ldGFUZXh0SGVscGVycyhuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCkge1xuICAgIHZhciBfbWV0YTtcbiAgICB2YXIgbWV0YTRkYXRhID0gW107XG5cbiAgICBpZihuZXdGdWxsTGF5b3V0Lm1ldGEpIHtcbiAgICAgICAgX21ldGEgPSBuZXdGdWxsTGF5b3V0Ll9tZXRhID0ge1xuICAgICAgICAgICAgbWV0YTogbmV3RnVsbExheW91dC5tZXRhLFxuICAgICAgICAgICAgbGF5b3V0OiB7bWV0YTogbmV3RnVsbExheW91dC5tZXRhfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBuZXdGdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2UgPSBuZXdGdWxsRGF0YVtpXTtcblxuICAgICAgICBpZih0cmFjZS5tZXRhKSB7XG4gICAgICAgICAgICBtZXRhNGRhdGFbdHJhY2UuaW5kZXhdID0gdHJhY2UuX21ldGEgPSB7bWV0YTogdHJhY2UubWV0YX07XG4gICAgICAgIH0gZWxzZSBpZihuZXdGdWxsTGF5b3V0Lm1ldGEpIHtcbiAgICAgICAgICAgIHRyYWNlLl9tZXRhID0ge21ldGE6IG5ld0Z1bGxMYXlvdXQubWV0YX07XG4gICAgICAgIH1cbiAgICAgICAgaWYobmV3RnVsbExheW91dC5tZXRhKSB7XG4gICAgICAgICAgICB0cmFjZS5fbWV0YS5sYXlvdXQgPSB7bWV0YTogbmV3RnVsbExheW91dC5tZXRhfTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKG1ldGE0ZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgaWYoIV9tZXRhKSB7XG4gICAgICAgICAgICBfbWV0YSA9IG5ld0Z1bGxMYXlvdXQuX21ldGEgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICBfbWV0YS5kYXRhID0gbWV0YTRkYXRhO1xuICAgIH1cbn1cblxuLy8gQ3JlYXRlIHN0b3JhZ2UgZm9yIGFsbCBvZiB0aGUgZGF0YSByZWxhdGVkIHRvIGZyYW1lcyBhbmQgdHJhbnNpdGlvbnM6XG5wbG90cy5jcmVhdGVUcmFuc2l0aW9uRGF0YSA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgLy8gU2V0IHVwIHRoZSBkZWZhdWx0IGtleWZyYW1lIGlmIGl0IGRvZXNuJ3QgZXhpc3Q6XG4gICAgaWYoIWdkLl90cmFuc2l0aW9uRGF0YSkge1xuICAgICAgICBnZC5fdHJhbnNpdGlvbkRhdGEgPSB7fTtcbiAgICB9XG5cbiAgICBpZighZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZXMpIHtcbiAgICAgICAgZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZXMgPSBbXTtcbiAgICB9XG5cbiAgICBpZighZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZUhhc2gpIHtcbiAgICAgICAgZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZUhhc2ggPSB7fTtcbiAgICB9XG5cbiAgICBpZighZ2QuX3RyYW5zaXRpb25EYXRhLl9jb3VudGVyKSB7XG4gICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5fY291bnRlciA9IDA7XG4gICAgfVxuXG4gICAgaWYoIWdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzKSB7XG4gICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzID0gW107XG4gICAgfVxufTtcblxuLy8gaGVscGVyIGZ1bmN0aW9uIHRvIGJlIGJvdW5kIHRvIGZ1bGxMYXlvdXQgdG8gY2hlY2tcbi8vIHdoZXRoZXIgYSBjZXJ0YWluIHBsb3QgdHlwZSBpcyBwcmVzZW50IG9uIHBsb3Rcbi8vIG9yIHRyYWNlIGhhcyBhIGNhdGVnb3J5XG5wbG90cy5faGFzUGxvdFR5cGUgPSBmdW5jdGlvbihjYXRlZ29yeSkge1xuICAgIHZhciBpO1xuXG4gICAgLy8gY2hlY2sgYmFzZSBwbG90IG1vZHVsZXNcbiAgICB2YXIgYmFzZVBsb3RNb2R1bGVzID0gdGhpcy5fYmFzZVBsb3RNb2R1bGVzIHx8IFtdO1xuICAgIGZvcihpID0gMDsgaSA8IGJhc2VQbG90TW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihiYXNlUGxvdE1vZHVsZXNbaV0ubmFtZSA9PT0gY2F0ZWdvcnkpIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIHRyYWNlIG1vZHVsZXMgKGluY2x1ZGluZyBub24tdmlzaWJsZTp0cnVlKVxuICAgIHZhciBtb2R1bGVzID0gdGhpcy5fbW9kdWxlcyB8fCBbXTtcbiAgICBmb3IoaSA9IDA7IGkgPCBtb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBuYW1lID0gbW9kdWxlc1tpXS5uYW1lO1xuICAgICAgICBpZihuYW1lID09PSBjYXRlZ29yeSkgcmV0dXJuIHRydWU7XG4gICAgICAgIC8vIE4uQi4gdGhpcyBpcyBtb2R1bGVzW2ldIGFsb25nIHdpdGggJ2NhdGVnb3JpZXMnIGFzIGEgaGFzaCBvYmplY3RcbiAgICAgICAgdmFyIF9tb2R1bGUgPSBSZWdpc3RyeS5tb2R1bGVzW25hbWVdO1xuICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuY2F0ZWdvcmllc1tjYXRlZ29yeV0pIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn07XG5cbnBsb3RzLmNsZWFuUGxvdCA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBpLCBqO1xuXG4gICAgdmFyIGJhc2VQbG90TW9kdWxlcyA9IG9sZEZ1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcyB8fCBbXTtcbiAgICBmb3IoaSA9IDA7IGkgPCBiYXNlUGxvdE1vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIF9tb2R1bGUgPSBiYXNlUGxvdE1vZHVsZXNbaV07XG5cbiAgICAgICAgaWYoX21vZHVsZS5jbGVhbikge1xuICAgICAgICAgICAgX21vZHVsZS5jbGVhbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGhhZEdsID0gb2xkRnVsbExheW91dC5faGFzICYmIG9sZEZ1bGxMYXlvdXQuX2hhcygnZ2wnKTtcbiAgICB2YXIgaGFzR2wgPSBuZXdGdWxsTGF5b3V0Ll9oYXMgJiYgbmV3RnVsbExheW91dC5faGFzKCdnbCcpO1xuXG4gICAgaWYoaGFkR2wgJiYgIWhhc0dsKSB7XG4gICAgICAgIGlmKG9sZEZ1bGxMYXlvdXQuX2dsY29udGFpbmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIG9sZEZ1bGxMYXlvdXQuX2dsY29udGFpbmVyLnNlbGVjdEFsbCgnLmdsLWNhbnZhcycpLnJlbW92ZSgpO1xuICAgICAgICAgICAgb2xkRnVsbExheW91dC5fZ2xjb250YWluZXIuc2VsZWN0QWxsKCcubm8td2ViZ2wnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIG9sZEZ1bGxMYXlvdXQuX2dsY2FudmFzID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBoYXNJbmZvTGF5ZXIgPSAhIW9sZEZ1bGxMYXlvdXQuX2luZm9sYXllcjtcblxuICAgIG9sZExvb3A6XG4gICAgZm9yKGkgPSAwOyBpIDwgb2xkRnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG9sZFRyYWNlID0gb2xkRnVsbERhdGFbaV07XG4gICAgICAgIHZhciBvbGRVaWQgPSBvbGRUcmFjZS51aWQ7XG5cbiAgICAgICAgZm9yKGogPSAwOyBqIDwgbmV3RnVsbERhdGEubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBuZXdUcmFjZSA9IG5ld0Z1bGxEYXRhW2pdO1xuXG4gICAgICAgICAgICBpZihvbGRVaWQgPT09IG5ld1RyYWNlLnVpZCkgY29udGludWUgb2xkTG9vcDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNsZWFuIG9sZCBjb2xvcmJhcnNcbiAgICAgICAgaWYoaGFzSW5mb0xheWVyKSB7XG4gICAgICAgICAgICBvbGRGdWxsTGF5b3V0Ll9pbmZvbGF5ZXIuc2VsZWN0KCcuY2InICsgb2xkVWlkKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbnBsb3RzLmxpbmtTdWJwbG90cyA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBpLCBqO1xuXG4gICAgdmFyIG9sZFN1YnBsb3RzID0gb2xkRnVsbExheW91dC5fcGxvdHMgfHwge307XG4gICAgdmFyIG5ld1N1YnBsb3RzID0gbmV3RnVsbExheW91dC5fcGxvdHMgPSB7fTtcbiAgICB2YXIgbmV3U3VicGxvdExpc3QgPSBuZXdGdWxsTGF5b3V0Ll9zdWJwbG90cztcblxuICAgIHZhciBtb2NrR2QgPSB7XG4gICAgICAgIF9mdWxsRGF0YTogbmV3RnVsbERhdGEsXG4gICAgICAgIF9mdWxsTGF5b3V0OiBuZXdGdWxsTGF5b3V0XG4gICAgfTtcblxuICAgIHZhciBpZHMgPSBuZXdTdWJwbG90TGlzdC5jYXJ0ZXNpYW4uY29uY2F0KG5ld1N1YnBsb3RMaXN0LmdsMmQgfHwgW10pO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgaWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpZCA9IGlkc1tpXTtcbiAgICAgICAgdmFyIG9sZFN1YnBsb3QgPSBvbGRTdWJwbG90c1tpZF07XG4gICAgICAgIHZhciB4YXhpcyA9IGF4aXNJRHMuZ2V0RnJvbUlkKG1vY2tHZCwgaWQsICd4Jyk7XG4gICAgICAgIHZhciB5YXhpcyA9IGF4aXNJRHMuZ2V0RnJvbUlkKG1vY2tHZCwgaWQsICd5Jyk7XG4gICAgICAgIHZhciBwbG90aW5mbztcblxuICAgICAgICAvLyBsaW5rIG9yIGNyZWF0ZSBzdWJwbG90IG9iamVjdFxuICAgICAgICBpZihvbGRTdWJwbG90KSB7XG4gICAgICAgICAgICBwbG90aW5mbyA9IG5ld1N1YnBsb3RzW2lkXSA9IG9sZFN1YnBsb3Q7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwbG90aW5mbyA9IG5ld1N1YnBsb3RzW2lkXSA9IHt9O1xuICAgICAgICAgICAgcGxvdGluZm8uaWQgPSBpZDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkZCB0aGVzZSBheGlzIGlkcyB0byBlYWNoIG90aGVycycgc3VicGxvdCBsaXN0c1xuICAgICAgICB4YXhpcy5fY291bnRlckF4ZXMucHVzaCh5YXhpcy5faWQpO1xuICAgICAgICB5YXhpcy5fY291bnRlckF4ZXMucHVzaCh4YXhpcy5faWQpO1xuICAgICAgICB4YXhpcy5fc3VicGxvdHNXaXRoLnB1c2goaWQpO1xuICAgICAgICB5YXhpcy5fc3VicGxvdHNXaXRoLnB1c2goaWQpO1xuXG4gICAgICAgIC8vIHVwZGF0ZSB4IGFuZCB5IGF4aXMgbGF5b3V0IG9iamVjdCByZWZzXG4gICAgICAgIHBsb3RpbmZvLnhheGlzID0geGF4aXM7XG4gICAgICAgIHBsb3RpbmZvLnlheGlzID0geWF4aXM7XG5cbiAgICAgICAgLy8gQnkgZGVmYXVsdCwgd2UgY2xpcCBhdCB0aGUgc3VicGxvdCBsZXZlbCxcbiAgICAgICAgLy8gYnV0IGlmIG9uZSB0cmFjZSBvbiBhIGdpdmVuIHN1YnBsb3QgaGFzICpjbGlwb25heGlzKiBzZXQgdG8gZmFsc2UsXG4gICAgICAgIC8vIHdlIG5lZWQgdG8gY2xpcCBhdCB0aGUgdHJhY2UgbW9kdWxlIGxheWVyIGxldmVsO1xuICAgICAgICAvLyBmaW5kIHRoaXMgb3V0IGhlcmUsIG9uY2Ugb2YgZm9yIGFsbC5cbiAgICAgICAgcGxvdGluZm8uX2hhc0NsaXBPbkF4aXNGYWxzZSA9IGZhbHNlO1xuXG4gICAgICAgIGZvcihqID0gMDsgaiA8IG5ld0Z1bGxEYXRhLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2UgPSBuZXdGdWxsRGF0YVtqXTtcblxuICAgICAgICAgICAgaWYoXG4gICAgICAgICAgICAgICAgdHJhY2UueGF4aXMgPT09IHBsb3RpbmZvLnhheGlzLl9pZCAmJlxuICAgICAgICAgICAgICAgIHRyYWNlLnlheGlzID09PSBwbG90aW5mby55YXhpcy5faWQgJiZcbiAgICAgICAgICAgICAgICB0cmFjZS5jbGlwb25heGlzID09PSBmYWxzZVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcGxvdGluZm8uX2hhc0NsaXBPbkF4aXNGYWxzZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB3aGlsZSB3ZSdyZSBhdCBpdCwgbGluayBvdmVybGF5aW5nIGF4ZXMgdG8gdGhlaXIgbWFpbiBheGVzIGFuZFxuICAgIC8vIGFuY2hvcmVkIGF4ZXMgdG8gdGhlIGF4ZXMgdGhleSdyZSBhbmNob3JlZCB0b1xuICAgIHZhciBheExpc3QgPSBheGlzSURzLmxpc3QobW9ja0dkLCBudWxsLCB0cnVlKTtcbiAgICB2YXIgYXg7XG4gICAgZm9yKGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGF4ID0gYXhMaXN0W2ldO1xuICAgICAgICB2YXIgbWFpbkF4ID0gbnVsbDtcblxuICAgICAgICBpZihheC5vdmVybGF5aW5nKSB7XG4gICAgICAgICAgICBtYWluQXggPSBheGlzSURzLmdldEZyb21JZChtb2NrR2QsIGF4Lm92ZXJsYXlpbmcpO1xuXG4gICAgICAgICAgICAvLyB5b3UgY2Fubm90IG92ZXJsYXkgYW4gYXhpcyB0aGF0J3MgYWxyZWFkeSBvdmVybGF5aW5nIGFub3RoZXJcbiAgICAgICAgICAgIGlmKG1haW5BeCAmJiBtYWluQXgub3ZlcmxheWluZykge1xuICAgICAgICAgICAgICAgIGF4Lm92ZXJsYXlpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBtYWluQXggPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGF4Ll9tYWluQXhpcyA9IG1haW5BeCB8fCBheDtcblxuICAgICAgICAvKlxuICAgICAgICAgKiBGb3Igbm93IGZvcmNlIG92ZXJsYXlzIHRvIG92ZXJsYXkgY29tcGxldGVseS4uLiBzbyB0aGV5XG4gICAgICAgICAqIGNhbiBkcmFnIHRvZ2V0aGVyIGNvcnJlY3RseSBhbmQgc2hhcmUgYmFja2dyb3VuZHMuXG4gICAgICAgICAqIExhdGVyIHBlcmhhcHMgd2UgbWFrZSBzZXBhcmF0ZSBheGlzIGRvbWFpbiBhbmRcbiAgICAgICAgICogdGljay9saW5lIGRvbWFpbiBvciBzb21ldGhpbmcsIHNvIHRoZXkgY2FuIHN0aWxsIHNoYXJlXG4gICAgICAgICAqIHRoZSAocG9zc2libHkgbGFyZ2VyKSBkcmFnZ2VyIGFuZCBiYWNrZ3JvdW5kIGJ1dCBkb24ndFxuICAgICAgICAgKiBoYXZlIHRvIGJvdGggYmUgZHJhd24gb3ZlciB0aGF0IHdob2xlIGRvbWFpblxuICAgICAgICAgKi9cbiAgICAgICAgaWYobWFpbkF4KSBheC5kb21haW4gPSBtYWluQXguZG9tYWluLnNsaWNlKCk7XG5cbiAgICAgICAgYXguX2FuY2hvckF4aXMgPSBheC5hbmNob3IgPT09ICdmcmVlJyA/XG4gICAgICAgICAgICBudWxsIDpcbiAgICAgICAgICAgIGF4aXNJRHMuZ2V0RnJvbUlkKG1vY2tHZCwgYXguYW5jaG9yKTtcbiAgICB9XG5cbiAgICAvLyBmaW5hbGx5LCB3ZSBjYW4gZmluZCB0aGUgbWFpbiBzdWJwbG90IGZvciBlYWNoIGF4aXNcbiAgICAvLyAob24gd2hpY2ggdGhlIHRpY2tzICYgbGFiZWxzIGFyZSBkcmF3bilcbiAgICBmb3IoaSA9IDA7IGkgPCBheExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXggPSBheExpc3RbaV07XG4gICAgICAgIGF4Ll9jb3VudGVyQXhlcy5zb3J0KGF4aXNJRHMuaWRTb3J0KTtcbiAgICAgICAgYXguX3N1YnBsb3RzV2l0aC5zb3J0KExpYi5zdWJwbG90U29ydCk7XG4gICAgICAgIGF4Ll9tYWluU3VicGxvdCA9IGZpbmRNYWluU3VicGxvdChheCwgbmV3RnVsbExheW91dCk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gZmluZE1haW5TdWJwbG90KGF4LCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIG1vY2tHZCA9IHtfZnVsbExheW91dDogZnVsbExheW91dH07XG5cbiAgICB2YXIgaXNYID0gYXguX2lkLmNoYXJBdCgwKSA9PT0gJ3gnO1xuICAgIHZhciBhbmNob3JBeCA9IGF4Ll9tYWluQXhpcy5fYW5jaG9yQXhpcztcbiAgICB2YXIgbWFpblN1YnBsb3RJRCA9ICcnO1xuICAgIHZhciBuZXh0QmVzdE1haW5TdWJwbG90SUQgPSAnJztcbiAgICB2YXIgYW5jaG9ySUQgPSAnJztcblxuICAgIC8vIEZpcnN0IHRyeSB0aGUgbWFpbiBJRCB3aXRoIHRoZSBhbmNob3JcbiAgICBpZihhbmNob3JBeCkge1xuICAgICAgICBhbmNob3JJRCA9IGFuY2hvckF4Ll9tYWluQXhpcy5faWQ7XG4gICAgICAgIG1haW5TdWJwbG90SUQgPSBpc1ggPyAoYXguX2lkICsgYW5jaG9ySUQpIDogKGFuY2hvcklEICsgYXguX2lkKTtcbiAgICB9XG5cbiAgICAvLyBUaGVuIGxvb2sgZm9yIGEgc3VicGxvdCB3aXRoIHRoZSBjb3VudGVyYXhpcyBvdmVybGF5aW5nIHRoZSBhbmNob3JcbiAgICAvLyBJZiB0aGF0IGZhaWxzIGp1c3QgdXNlIHRoZSBmaXJzdCBzdWJwbG90IGluY2x1ZGluZyB0aGlzIGF4aXNcbiAgICBpZighbWFpblN1YnBsb3RJRCB8fCAhZnVsbExheW91dC5fcGxvdHNbbWFpblN1YnBsb3RJRF0pIHtcbiAgICAgICAgbWFpblN1YnBsb3RJRCA9ICcnO1xuXG4gICAgICAgIHZhciBjb3VudGVySURzID0gYXguX2NvdW50ZXJBeGVzO1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY291bnRlcklEcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGNvdW50ZXJQYXJ0ID0gY291bnRlcklEc1tqXTtcbiAgICAgICAgICAgIHZhciBpZCA9IGlzWCA/IChheC5faWQgKyBjb3VudGVyUGFydCkgOiAoY291bnRlclBhcnQgKyBheC5faWQpO1xuICAgICAgICAgICAgaWYoIW5leHRCZXN0TWFpblN1YnBsb3RJRCkgbmV4dEJlc3RNYWluU3VicGxvdElEID0gaWQ7XG4gICAgICAgICAgICB2YXIgY291bnRlckF4ID0gYXhpc0lEcy5nZXRGcm9tSWQobW9ja0dkLCBjb3VudGVyUGFydCk7XG4gICAgICAgICAgICBpZihhbmNob3JJRCAmJiBjb3VudGVyQXgub3ZlcmxheWluZyA9PT0gYW5jaG9ySUQpIHtcbiAgICAgICAgICAgICAgICBtYWluU3VicGxvdElEID0gaWQ7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWFpblN1YnBsb3RJRCB8fCBuZXh0QmVzdE1haW5TdWJwbG90SUQ7XG59XG5cbi8vIFRoaXMgZnVuY3Rpb24gY2xlYXJzIGFueSB0cmFjZSBhdHRyaWJ1dGVzIHdpdGggdmFsVHlwZTogY29sb3IgYW5kXG4vLyBubyBzZXQgZGZsdCBmaWxlZCBpbiB0aGUgcGxvdCBzY2hlbWEuIFRoaXMgaXMgbmVlZGVkIGJlY2F1c2UgZ3JvdXBieSAod2hpY2hcbi8vIGlzIHRoZSBvbmx5IHRyYW5zZm9ybSBmb3Igd2hpY2ggdGhpcyBjdXJyZW50bHkgYXBwbGllcykgc3VwcGxpZXMgcGFyZW50XG4vLyB0cmFjZSBkZWZhdWx0cywgdGhlbiBleHBhbmRlZCB0cmFjZSBkZWZhdWx0cy4gVGhlIHJlc3VsdCBpcyB0aGF0IGBudWxsYFxuLy8gY29sb3JzIGFyZSBkZWZhdWx0LXN1cHBsaWVkIGFuZCBpbmhlcml0ZWQgYXMgYSBjb2xvciBpbnN0ZWFkIG9mIGEgbnVsbC5cbi8vIFRoZSByZXN1bHQgaXMgdGhhdCBleHBhbmRlZCB0cmFjZSBkZWZhdWx0IGNvbG9ycyBoYXZlIG5vIGVmZmVjdCwgd2l0aFxuLy8gdGhlIGZpbmFsIHJlc3VsdCB0aGF0IGdyb3VwcyBhcmUgaW5kaXN0aW5ndWlzaGFibGUuIFRoaXMgZnVuY3Rpb24gY2xlYXJzXG4vLyB0aG9zZSBjb2xvcnMgc28gdGhhdCBpbmRpdmlkdWFsIGdyb3VwYnkgZ3JvdXBzIGdldCB1bmlxdWUgY29sb3JzLlxucGxvdHMuY2xlYXJFeHBhbmRlZFRyYWNlRGVmYXVsdENvbG9ycyA9IGZ1bmN0aW9uKHRyYWNlKSB7XG4gICAgdmFyIGNvbG9yQXR0cnMsIHBhdGgsIGk7XG5cbiAgICAvLyBUaGlzIHVzZXMgd2VpcmQgY2xvc3VyZSBzdGF0ZSBpbiBvcmRlciB0byBzYXRpc2Z5IHRoZSBsaW50ZXIgcnVsZVxuICAgIC8vIHRoYXQgd2UgY2FuJ3QgY3JlYXRlIGZ1bmN0aW9ucyBpbiBhIGxvb3AuXG4gICAgZnVuY3Rpb24gbG9jYXRlQ29sb3JBdHRycyhhdHRyLCBhdHRyTmFtZSwgYXR0cnMsIGxldmVsKSB7XG4gICAgICAgIHBhdGhbbGV2ZWxdID0gYXR0ck5hbWU7XG4gICAgICAgIHBhdGgubGVuZ3RoID0gbGV2ZWwgKyAxO1xuICAgICAgICBpZihhdHRyLnZhbFR5cGUgPT09ICdjb2xvcicgJiYgYXR0ci5kZmx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbG9yQXR0cnMucHVzaChwYXRoLmpvaW4oJy4nKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwYXRoID0gW107XG5cbiAgICAvLyBHZXQgdGhlIGNhY2hlZCBjb2xvckF0dHJzOlxuICAgIGNvbG9yQXR0cnMgPSB0cmFjZS5fbW9kdWxlLl9jb2xvckF0dHJzO1xuXG4gICAgLy8gT3IgZWxzZSBjb21wdXRlIGFuZCBjYWNoZSB0aGUgY29sb3JBdHRycyBvbiB0aGUgbW9kdWxlOlxuICAgIGlmKCFjb2xvckF0dHJzKSB7XG4gICAgICAgIHRyYWNlLl9tb2R1bGUuX2NvbG9yQXR0cnMgPSBjb2xvckF0dHJzID0gW107XG4gICAgICAgIFBsb3RTY2hlbWEuY3Jhd2woXG4gICAgICAgICAgICB0cmFjZS5fbW9kdWxlLmF0dHJpYnV0ZXMsXG4gICAgICAgICAgICBsb2NhdGVDb2xvckF0dHJzXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgY29sb3JBdHRycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb3JpZ3Byb3AgPSBMaWIubmVzdGVkUHJvcGVydHkodHJhY2UsICdfaW5wdXQuJyArIGNvbG9yQXR0cnNbaV0pO1xuXG4gICAgICAgIGlmKCFvcmlncHJvcC5nZXQoKSkge1xuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBjb2xvckF0dHJzW2ldKS5zZXQobnVsbCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5cbnBsb3RzLnN1cHBseURhdGFEZWZhdWx0cyA9IGZ1bmN0aW9uKGRhdGFJbiwgZGF0YU91dCwgbGF5b3V0LCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIG1vZHVsZXMgPSBmdWxsTGF5b3V0Ll9tb2R1bGVzO1xuICAgIHZhciB2aXNpYmxlTW9kdWxlcyA9IGZ1bGxMYXlvdXQuX3Zpc2libGVNb2R1bGVzO1xuICAgIHZhciBiYXNlUGxvdE1vZHVsZXMgPSBmdWxsTGF5b3V0Ll9iYXNlUGxvdE1vZHVsZXM7XG4gICAgdmFyIGNudCA9IDA7XG4gICAgdmFyIGNvbG9yQ250ID0gMDtcblxuICAgIHZhciBpLCBmdWxsVHJhY2UsIHRyYWNlO1xuXG4gICAgZnVsbExheW91dC5fdHJhbnNmb3JtTW9kdWxlcyA9IFtdO1xuXG4gICAgZnVuY3Rpb24gcHVzaE1vZHVsZShmdWxsVHJhY2UpIHtcbiAgICAgICAgZGF0YU91dC5wdXNoKGZ1bGxUcmFjZSk7XG5cbiAgICAgICAgdmFyIF9tb2R1bGUgPSBmdWxsVHJhY2UuX21vZHVsZTtcbiAgICAgICAgaWYoIV9tb2R1bGUpIHJldHVybjtcblxuICAgICAgICBMaWIucHVzaFVuaXF1ZShtb2R1bGVzLCBfbW9kdWxlKTtcbiAgICAgICAgaWYoZnVsbFRyYWNlLnZpc2libGUgPT09IHRydWUpIExpYi5wdXNoVW5pcXVlKHZpc2libGVNb2R1bGVzLCBfbW9kdWxlKTtcbiAgICAgICAgTGliLnB1c2hVbmlxdWUoYmFzZVBsb3RNb2R1bGVzLCBmdWxsVHJhY2UuX21vZHVsZS5iYXNlUGxvdE1vZHVsZSk7XG4gICAgICAgIGNudCsrO1xuXG4gICAgICAgIC8vIFRPRE86IGRvIHdlIHJlYWxseSB3YW50IGNvbG9yIG5vdCB0byBpbmNyZW1lbnQgZm9yIGV4cGxpY2l0bHkgaW52aXNpYmxlIHRyYWNlcz9cbiAgICAgICAgLy8gVGhpcyBsb2dpYyBpcyB3ZWlyZCwgYnV0IG1hdGNoZXMgcHJldmlvdXMgYmVoYXZpb3I6IHRyYWNlcyB0aGF0IHlvdSBleHBsaWNpdGx5XG4gICAgICAgIC8vIHNldCB0byB2aXNpYmxlOmZhbHNlIGRvIG5vdCBpbmNyZW1lbnQgdGhlIGNvbG9yLCBidXQgdHJhY2VzIFdFIGRldGVybWluZSB0byBiZVxuICAgICAgICAvLyBlbXB0eSBvciBpbnZhbGlkIChhbmQgdGh1cyBzZXQgdG8gdmlzaWJsZTpmYWxzZSkgRE8gaW5jcmVtZW50IGNvbG9yLlxuICAgICAgICAvLyBJIGtpbmQgb2YgdGhpbmsgd2Ugc2hvdWxkIGp1c3QgbGV0IGFsbCB0cmFjZXMgaW5jcmVtZW50IGNvbG9yLCB2aXNpYmxlIG9yIG5vdC5cbiAgICAgICAgLy8gc2VlIG1vY2s6IGF4ZXMtYXV0b3R5cGUtZW1wdHkgdnMuIGEgdGVzdCBvZiByZXN0eWxpbmcgdmlzaWJsZTogZmFsc2UgdGhhdFxuICAgICAgICAvLyBJIGNhbid0IGZpbmQgcmlnaHQgbm93Li4uXG4gICAgICAgIGlmKGZ1bGxUcmFjZS5faW5wdXQudmlzaWJsZSAhPT0gZmFsc2UpIGNvbG9yQ250Kys7XG4gICAgfVxuXG4gICAgdmFyIGNhcnBldEluZGV4ID0ge307XG4gICAgdmFyIGNhcnBldERlcGVuZGVudHMgPSBbXTtcbiAgICB2YXIgZGF0YVRlbXBsYXRlID0gKGxheW91dC50ZW1wbGF0ZSB8fCB7fSkuZGF0YSB8fCB7fTtcbiAgICB2YXIgdGVtcGxhdGVyID0gVGVtcGxhdGUudHJhY2VUZW1wbGF0ZXIoZGF0YVRlbXBsYXRlKTtcblxuICAgIGZvcihpID0gMDsgaSA8IGRhdGFJbi5sZW5ndGg7IGkrKykge1xuICAgICAgICB0cmFjZSA9IGRhdGFJbltpXTtcblxuICAgICAgICAvLyByZXVzZSB1aWQgd2UgbWF5IGhhdmUgcHVsbGVkIG91dCBvZiBvbGRGdWxsRGF0YVxuICAgICAgICAvLyBOb3RlOiB0ZW1wbGF0ZXIgc3VwcGxpZXMgdHJhY2UgdHlwZVxuICAgICAgICBmdWxsVHJhY2UgPSB0ZW1wbGF0ZXIubmV3VHJhY2UodHJhY2UpO1xuICAgICAgICBmdWxsVHJhY2UudWlkID0gZnVsbExheW91dC5fdHJhY2VVaWRzW2ldO1xuICAgICAgICBwbG90cy5zdXBwbHlUcmFjZURlZmF1bHRzKHRyYWNlLCBmdWxsVHJhY2UsIGNvbG9yQ250LCBmdWxsTGF5b3V0LCBpKTtcblxuICAgICAgICBmdWxsVHJhY2UuaW5kZXggPSBpO1xuICAgICAgICBmdWxsVHJhY2UuX2lucHV0ID0gdHJhY2U7XG4gICAgICAgIGZ1bGxUcmFjZS5fZXhwYW5kZWRJbmRleCA9IGNudDtcblxuICAgICAgICBpZihmdWxsVHJhY2UudHJhbnNmb3JtcyAmJiBmdWxsVHJhY2UudHJhbnNmb3Jtcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciBzZEludmlzaWJsZSA9IHRyYWNlLnZpc2libGUgIT09IGZhbHNlICYmIGZ1bGxUcmFjZS52aXNpYmxlID09PSBmYWxzZTtcblxuICAgICAgICAgICAgdmFyIGV4cGFuZGVkVHJhY2VzID0gYXBwbHlUcmFuc2Zvcm1zKGZ1bGxUcmFjZSwgZGF0YU91dCwgbGF5b3V0LCBmdWxsTGF5b3V0KTtcblxuICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGV4cGFuZGVkVHJhY2VzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4cGFuZGVkVHJhY2UgPSBleHBhbmRlZFRyYWNlc1tqXTtcblxuICAgICAgICAgICAgICAgIC8vIE5vIGZ1cnRoZXIgdGVtcGxhdGluZyBkdXJpbmcgdHJhbnNmb3Jtcy5cbiAgICAgICAgICAgICAgICB2YXIgZnVsbEV4cGFuZGVkVHJhY2UgPSB7XG4gICAgICAgICAgICAgICAgICAgIF90ZW1wbGF0ZTogZnVsbFRyYWNlLl90ZW1wbGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogZnVsbFRyYWNlLnR5cGUsXG4gICAgICAgICAgICAgICAgICAgIC8vIHNldCB1aWQgdXNpbmcgcGFyZW50IHVpZCBhbmQgZXhwYW5kZWQgaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgLy8gdG8gcHJvbW90ZSBjb25zaXN0ZW5jeSBiZXR3ZWVuIHVwZGF0ZSBjYWxsc1xuICAgICAgICAgICAgICAgICAgICB1aWQ6IGZ1bGxUcmFjZS51aWQgKyBqXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBmaXJzdCBzdXBwbHlEZWZhdWx0cyBjcmVhdGVkIGB2aXNpYmxlOiBmYWxzZWAsXG4gICAgICAgICAgICAgICAgLy8gY2xlYXIgaXQgYmVmb3JlIHJ1bm5pbmcgc3VwcGx5RGVmYXVsdHMgYSBzZWNvbmQgdGltZSxcbiAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIHNvbWV0aW1lcyB0aGVyZSBhcmUgaXRlbXMgd2Ugc3RpbGwgd2FudCB0byBjb2VyY2VcbiAgICAgICAgICAgICAgICAvLyBpbnNpZGUgdHJhY2UgbW9kdWxlcyBiZWZvcmUgZGV0ZXJtaW5pbmcgdGhhdCB0aGUgdHJhY2UgaXNcbiAgICAgICAgICAgICAgICAvLyBhZ2FpbiBgdmlzaWJsZTogZmFsc2VgLCBmb3IgZXhhbXBsZSBwYXJ0aWFsIHZpc2liaWxpdGllc1xuICAgICAgICAgICAgICAgIC8vIGluIGBzcGxvbWAgdHJhY2VzLlxuICAgICAgICAgICAgICAgIGlmKHNkSW52aXNpYmxlICYmIGV4cGFuZGVkVHJhY2UudmlzaWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV4cGFuZGVkVHJhY2UudmlzaWJsZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwbG90cy5zdXBwbHlUcmFjZURlZmF1bHRzKGV4cGFuZGVkVHJhY2UsIGZ1bGxFeHBhbmRlZFRyYWNlLCBjbnQsIGZ1bGxMYXlvdXQsIGkpO1xuXG4gICAgICAgICAgICAgICAgLy8gcmVsaW5rIHByaXZhdGUgKGkuZS4gdW5kZXJzY29yZSkga2V5cyBleHBhbmRlZCB0cmFjZSB0byBmdWxsIGV4cGFuZGVkIHRyYWNlIHNvXG4gICAgICAgICAgICAgICAgLy8gdGhhdCB0cmFuc2Zvcm0gc3VwcGx5LWRlZmF1bHQgbWV0aG9kcyBjYW4gc2V0IF8ga2V5cyBmb3IgZnV0dXJlIHVzZS5cbiAgICAgICAgICAgICAgICByZWxpbmtQcml2YXRlS2V5cyhmdWxsRXhwYW5kZWRUcmFjZSwgZXhwYW5kZWRUcmFjZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBhZGQgaW5mbyBhYm91dCBwYXJlbnQgZGF0YSB0cmFjZVxuICAgICAgICAgICAgICAgIGZ1bGxFeHBhbmRlZFRyYWNlLmluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICBmdWxsRXhwYW5kZWRUcmFjZS5faW5wdXQgPSB0cmFjZTtcbiAgICAgICAgICAgICAgICBmdWxsRXhwYW5kZWRUcmFjZS5fZnVsbElucHV0ID0gZnVsbFRyYWNlO1xuXG4gICAgICAgICAgICAgICAgLy8gYWRkIGluZm8gYWJvdXQgdGhlIGV4cGFuZGVkIGRhdGFcbiAgICAgICAgICAgICAgICBmdWxsRXhwYW5kZWRUcmFjZS5fZXhwYW5kZWRJbmRleCA9IGNudDtcbiAgICAgICAgICAgICAgICBmdWxsRXhwYW5kZWRUcmFjZS5fZXhwYW5kZWRJbnB1dCA9IGV4cGFuZGVkVHJhY2U7XG5cbiAgICAgICAgICAgICAgICBwdXNoTW9kdWxlKGZ1bGxFeHBhbmRlZFRyYWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGFkZCBpZGVudGlmeSByZWZzIGZvciBjb25zaXN0ZW5jeSB3aXRoIHRyYW5zZm9ybWVkIHRyYWNlc1xuICAgICAgICAgICAgZnVsbFRyYWNlLl9mdWxsSW5wdXQgPSBmdWxsVHJhY2U7XG4gICAgICAgICAgICBmdWxsVHJhY2UuX2V4cGFuZGVkSW5wdXQgPSBmdWxsVHJhY2U7XG5cbiAgICAgICAgICAgIHB1c2hNb2R1bGUoZnVsbFRyYWNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXMoZnVsbFRyYWNlLCAnY2FycGV0QXhpcycpKSB7XG4gICAgICAgICAgICBjYXJwZXRJbmRleFtmdWxsVHJhY2UuY2FycGV0XSA9IGZ1bGxUcmFjZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXMoZnVsbFRyYWNlLCAnY2FycGV0RGVwZW5kZW50JykpIHtcbiAgICAgICAgICAgIGNhcnBldERlcGVuZGVudHMucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGNhcnBldERlcGVuZGVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZnVsbFRyYWNlID0gZGF0YU91dFtjYXJwZXREZXBlbmRlbnRzW2ldXTtcblxuICAgICAgICBpZighZnVsbFRyYWNlLnZpc2libGUpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBjYXJwZXRBeGlzID0gY2FycGV0SW5kZXhbZnVsbFRyYWNlLmNhcnBldF07XG4gICAgICAgIGZ1bGxUcmFjZS5fY2FycGV0ID0gY2FycGV0QXhpcztcblxuICAgICAgICBpZighY2FycGV0QXhpcyB8fCAhY2FycGV0QXhpcy52aXNpYmxlKSB7XG4gICAgICAgICAgICBmdWxsVHJhY2UudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBmdWxsVHJhY2UueGF4aXMgPSBjYXJwZXRBeGlzLnhheGlzO1xuICAgICAgICBmdWxsVHJhY2UueWF4aXMgPSBjYXJwZXRBeGlzLnlheGlzO1xuICAgIH1cbn07XG5cbnBsb3RzLnN1cHBseUFuaW1hdGlvbkRlZmF1bHRzID0gZnVuY3Rpb24ob3B0cykge1xuICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuICAgIHZhciBpO1xuICAgIHZhciBvcHRzT3V0ID0ge307XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShvcHRzIHx8IHt9LCBvcHRzT3V0LCBhbmltYXRpb25BdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdtb2RlJyk7XG4gICAgY29lcmNlKCdkaXJlY3Rpb24nKTtcbiAgICBjb2VyY2UoJ2Zyb21jdXJyZW50Jyk7XG5cbiAgICBpZihBcnJheS5pc0FycmF5KG9wdHMuZnJhbWUpKSB7XG4gICAgICAgIG9wdHNPdXQuZnJhbWUgPSBbXTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgb3B0cy5mcmFtZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgb3B0c091dC5mcmFtZVtpXSA9IHBsb3RzLnN1cHBseUFuaW1hdGlvbkZyYW1lRGVmYXVsdHMob3B0cy5mcmFtZVtpXSB8fCB7fSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBvcHRzT3V0LmZyYW1lID0gcGxvdHMuc3VwcGx5QW5pbWF0aW9uRnJhbWVEZWZhdWx0cyhvcHRzLmZyYW1lIHx8IHt9KTtcbiAgICB9XG5cbiAgICBpZihBcnJheS5pc0FycmF5KG9wdHMudHJhbnNpdGlvbikpIHtcbiAgICAgICAgb3B0c091dC50cmFuc2l0aW9uID0gW107XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG9wdHMudHJhbnNpdGlvbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgb3B0c091dC50cmFuc2l0aW9uW2ldID0gcGxvdHMuc3VwcGx5QW5pbWF0aW9uVHJhbnNpdGlvbkRlZmF1bHRzKG9wdHMudHJhbnNpdGlvbltpXSB8fCB7fSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBvcHRzT3V0LnRyYW5zaXRpb24gPSBwbG90cy5zdXBwbHlBbmltYXRpb25UcmFuc2l0aW9uRGVmYXVsdHMob3B0cy50cmFuc2l0aW9uIHx8IHt9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3B0c091dDtcbn07XG5cbnBsb3RzLnN1cHBseUFuaW1hdGlvbkZyYW1lRGVmYXVsdHMgPSBmdW5jdGlvbihvcHRzKSB7XG4gICAgdmFyIG9wdHNPdXQgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKG9wdHMgfHwge30sIG9wdHNPdXQsIGFuaW1hdGlvbkF0dHJzLmZyYW1lLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2R1cmF0aW9uJyk7XG4gICAgY29lcmNlKCdyZWRyYXcnKTtcblxuICAgIHJldHVybiBvcHRzT3V0O1xufTtcblxucGxvdHMuc3VwcGx5QW5pbWF0aW9uVHJhbnNpdGlvbkRlZmF1bHRzID0gZnVuY3Rpb24ob3B0cykge1xuICAgIHZhciBvcHRzT3V0ID0ge307XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShvcHRzIHx8IHt9LCBvcHRzT3V0LCBhbmltYXRpb25BdHRycy50cmFuc2l0aW9uLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2R1cmF0aW9uJyk7XG4gICAgY29lcmNlKCdlYXNpbmcnKTtcblxuICAgIHJldHVybiBvcHRzT3V0O1xufTtcblxucGxvdHMuc3VwcGx5RnJhbWVEZWZhdWx0cyA9IGZ1bmN0aW9uKGZyYW1lSW4pIHtcbiAgICB2YXIgZnJhbWVPdXQgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGZyYW1lSW4sIGZyYW1lT3V0LCBmcmFtZUF0dHJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2dyb3VwJyk7XG4gICAgY29lcmNlKCduYW1lJyk7XG4gICAgY29lcmNlKCd0cmFjZXMnKTtcbiAgICBjb2VyY2UoJ2Jhc2VmcmFtZScpO1xuICAgIGNvZXJjZSgnZGF0YScpO1xuICAgIGNvZXJjZSgnbGF5b3V0Jyk7XG5cbiAgICByZXR1cm4gZnJhbWVPdXQ7XG59O1xuXG5wbG90cy5zdXBwbHlUcmFjZURlZmF1bHRzID0gZnVuY3Rpb24odHJhY2VJbiwgdHJhY2VPdXQsIGNvbG9ySW5kZXgsIGxheW91dCwgdHJhY2VJbkluZGV4KSB7XG4gICAgdmFyIGNvbG9yd2F5ID0gbGF5b3V0LmNvbG9yd2F5IHx8IENvbG9yLmRlZmF1bHRzO1xuICAgIHZhciBkZWZhdWx0Q29sb3IgPSBjb2xvcndheVtjb2xvckluZGV4ICUgY29sb3J3YXkubGVuZ3RoXTtcblxuICAgIHZhciBpO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIHBsb3RzLmF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciB2aXNpYmxlID0gY29lcmNlKCd2aXNpYmxlJyk7XG5cbiAgICBjb2VyY2UoJ3R5cGUnKTtcbiAgICBjb2VyY2UoJ25hbWUnLCBsYXlvdXQuX3RyYWNlV29yZCArICcgJyArIHRyYWNlSW5JbmRleCk7XG5cbiAgICBjb2VyY2UoJ3VpcmV2aXNpb24nLCBsYXlvdXQudWlyZXZpc2lvbik7XG5cbiAgICAvLyB3ZSB3YW50IGV2ZW4gaW52aXNpYmxlIHRyYWNlcyB0byBtYWtlIHRoZWlyIHdvdWxkLWJlIHN1YnBsb3RzIHZpc2libGVcbiAgICAvLyBzbyBjb2VyY2UgdGhlIHN1YnBsb3QgaWQocykgbm93IG5vIG1hdHRlciB3aGF0XG4gICAgdmFyIF9tb2R1bGUgPSBwbG90cy5nZXRNb2R1bGUodHJhY2VPdXQpO1xuXG4gICAgdHJhY2VPdXQuX21vZHVsZSA9IF9tb2R1bGU7XG4gICAgaWYoX21vZHVsZSkge1xuICAgICAgICB2YXIgYmFzZVBsb3RNb2R1bGUgPSBfbW9kdWxlLmJhc2VQbG90TW9kdWxlO1xuICAgICAgICB2YXIgc3VicGxvdEF0dHIgPSBiYXNlUGxvdE1vZHVsZS5hdHRyO1xuICAgICAgICB2YXIgc3VicGxvdEF0dHJzID0gYmFzZVBsb3RNb2R1bGUuYXR0cmlidXRlcztcbiAgICAgICAgaWYoc3VicGxvdEF0dHIgJiYgc3VicGxvdEF0dHJzKSB7XG4gICAgICAgICAgICB2YXIgc3VicGxvdHMgPSBsYXlvdXQuX3N1YnBsb3RzO1xuICAgICAgICAgICAgdmFyIHN1YnBsb3RJZCA9ICcnO1xuXG4gICAgICAgICAgICAvLyBUT0RPIC0gY3VycmVudGx5IGlmIHdlIGRyYXcgYW4gZW1wdHkgZ2wyZCBzdWJwbG90LCBpdCBkcmF3c1xuICAgICAgICAgICAgLy8gbm90aGluZyB0aGVuIGdldHMgc3R1Y2sgYW5kIHlvdSBjYW4ndCBnZXQgaXQgYmFjayB3aXRob3V0IG5ld1Bsb3RcbiAgICAgICAgICAgIC8vIHNvcnQgdGhpcyBvdXQgaW4gdGhlIHJlZ2wgcmVmYWN0b3I/IGJ1dCBmb3Igbm93IGp1c3QgZHJvcCBlbXB0eSBnbDJkIHN1YnBsb3RzXG4gICAgICAgICAgICBpZihiYXNlUGxvdE1vZHVsZS5uYW1lICE9PSAnZ2wyZCcgfHwgdmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkoc3VicGxvdEF0dHIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHN1YnBsb3RBdHRyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0cmkgPSBzdWJwbG90QXR0cltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWxpID0gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgc3VicGxvdEF0dHJzLCBhdHRyaSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHN1YnBsb3RzW2F0dHJpXSkgTGliLnB1c2hVbmlxdWUoc3VicGxvdHNbYXR0cmldLCB2YWxpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YnBsb3RJZCArPSB2YWxpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc3VicGxvdElkID0gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgc3VicGxvdEF0dHJzLCBzdWJwbG90QXR0cik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoc3VicGxvdHNbYmFzZVBsb3RNb2R1bGUubmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgTGliLnB1c2hVbmlxdWUoc3VicGxvdHNbYmFzZVBsb3RNb2R1bGUubmFtZV0sIHN1YnBsb3RJZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYodmlzaWJsZSkge1xuICAgICAgICBjb2VyY2UoJ2N1c3RvbWRhdGEnKTtcbiAgICAgICAgY29lcmNlKCdpZHMnKTtcbiAgICAgICAgY29lcmNlKCdtZXRhJyk7XG5cbiAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZU91dCwgJ3Nob3dMZWdlbmQnKSkge1xuICAgICAgICAgICAgdHJhY2VPdXQuX2RmbHRTaG93TGVnZW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvZXJjZSgnc2hvd2xlZ2VuZCcpO1xuICAgICAgICAgICAgY29lcmNlKCdsZWdlbmRncm91cCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHJhY2VPdXQuX2RmbHRTaG93TGVnZW5kID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZihfbW9kdWxlKSB7XG4gICAgICAgICAgICBfbW9kdWxlLnN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZighUmVnaXN0cnkudHJhY2VJcyh0cmFjZU91dCwgJ25vT3BhY2l0eScpKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ29wYWNpdHknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2VPdXQsICdub3RMZWdlbmRJc29sYXRhYmxlJykpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgY2xlYXJzIG91dCB0aGUgbGVnZW5kb25seSBzdGF0ZSBmb3IgdHJhY2VzIGxpa2UgY2FycGV0IHRoYXRcbiAgICAgICAgICAgIC8vIGNhbm5vdCBiZSBpc29sYXRlZCBpbiB0aGUgbGVnZW5kXG4gICAgICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gISF0cmFjZU91dC52aXNpYmxlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIVJlZ2lzdHJ5LnRyYWNlSXModHJhY2VPdXQsICdub0hvdmVyJykpIHtcbiAgICAgICAgICAgIGlmKCF0cmFjZU91dC5ob3ZlcnRlbXBsYXRlKSBMaWIuY29lcmNlSG92ZXJpbmZvKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQpO1xuXG4gICAgICAgICAgICAvLyBwYXJjYXRzIHN1cHBvcnQgaG92ZXIsIGJ1dCBub3QgaG92ZXJsYWJlbCBzdHlsaW5ncyAoeWV0KVxuICAgICAgICAgICAgaWYodHJhY2VPdXQudHlwZSAhPT0gJ3BhcmNhdHMnKSB7XG4gICAgICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdmeCcsICdzdXBwbHlEZWZhdWx0cycpKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuc2VsZWN0UG9pbnRzKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ3NlbGVjdGVkcG9pbnRzJyk7XG4gICAgICAgIH1cblxuICAgICAgICBwbG90cy5zdXBwbHlUcmFuc2Zvcm1EZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJhY2VPdXQ7XG59O1xuXG4vKipcbiAqIGhhc01ha2VzRGF0YVRyYW5zZm9ybTogZG9lcyB0aGlzIHRyYWNlIGhhdmUgYSB0cmFuc2Zvcm0gdGhhdCBtYWtlcyBpdHMgb3duXG4gKiBkYXRhLCBlaXRoZXIgYnkgZ3JhYmJpbmcgaXQgZnJvbSBzb21ld2hlcmUgZWxzZSBvciBieSBjcmVhdGluZyBpdCBmcm9tIGlucHV0XG4gKiBwYXJhbWV0ZXJzPyBJZiBzbywgd2Ugc2hvdWxkIHN0aWxsIGtlZXAgZ29pbmcgd2l0aCBzdXBwbHlEZWZhdWx0c1xuICogZXZlbiBpZiB0aGUgdHJhY2UgaXMgaW52aXNpYmxlLCB3aGljaCBtYXkganVzdCBiZSBiZWNhdXNlIGl0IGhhcyBubyBkYXRhIHlldC5cbiAqL1xuZnVuY3Rpb24gaGFzTWFrZXNEYXRhVHJhbnNmb3JtKHRyYWNlKSB7XG4gICAgdmFyIHRyYW5zZm9ybXMgPSB0cmFjZS50cmFuc2Zvcm1zO1xuICAgIGlmKEFycmF5LmlzQXJyYXkodHJhbnNmb3JtcykgJiYgdHJhbnNmb3Jtcy5sZW5ndGgpIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYW5zZm9ybXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0aSA9IHRyYW5zZm9ybXNbaV07XG4gICAgICAgICAgICB2YXIgX21vZHVsZSA9IHRpLl9tb2R1bGUgfHwgdHJhbnNmb3Jtc1JlZ2lzdHJ5W3RpLnR5cGVdO1xuICAgICAgICAgICAgaWYoX21vZHVsZSAmJiBfbW9kdWxlLm1ha2VzRGF0YSkgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5wbG90cy5oYXNNYWtlc0RhdGFUcmFuc2Zvcm0gPSBoYXNNYWtlc0RhdGFUcmFuc2Zvcm07XG5cbnBsb3RzLnN1cHBseVRyYW5zZm9ybURlZmF1bHRzID0gZnVuY3Rpb24odHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCkge1xuICAgIC8vIEZvciBub3cgd2Ugb25seSBhbGxvdyB0cmFuc2Zvcm1zIG9uIDFEIHRyYWNlcywgaWUgdGhvc2UgdGhhdCBzcGVjaWZ5IGEgX2xlbmd0aC5cbiAgICAvLyBJZiB3ZSB3ZXJlIHRvIGltcGxlbWVudCAyRCB0cmFuc2Zvcm1zLCB3ZSdkIG5lZWQgdG8gaGF2ZSBlYWNoIHRyYW5zZm9ybVxuICAgIC8vIGRlc2NyaWJlIGl0cyBvd24gYXBwbGljYWJpbGl0eSBhbmQgZGlzYWJsZSBpdHNlbGYgd2hlbiBpdCBkb2Vzbid0IGFwcGx5LlxuICAgIC8vIEFsc28gYWxsb3cgdHJhbnNmb3JtcyB0aGF0IG1ha2UgdGhlaXIgb3duIGRhdGEsIGJ1dCBub3QgaW4gZ2xvYmFsVHJhbnNmb3Jtc1xuICAgIGlmKCEodHJhY2VPdXQuX2xlbmd0aCB8fCBoYXNNYWtlc0RhdGFUcmFuc2Zvcm0odHJhY2VJbikpKSByZXR1cm47XG5cbiAgICB2YXIgZ2xvYmFsVHJhbnNmb3JtcyA9IGxheW91dC5fZ2xvYmFsVHJhbnNmb3JtcyB8fCBbXTtcbiAgICB2YXIgdHJhbnNmb3JtTW9kdWxlcyA9IGxheW91dC5fdHJhbnNmb3JtTW9kdWxlcyB8fCBbXTtcblxuICAgIGlmKCFBcnJheS5pc0FycmF5KHRyYWNlSW4udHJhbnNmb3JtcykgJiYgZ2xvYmFsVHJhbnNmb3Jtcy5sZW5ndGggPT09IDApIHJldHVybjtcblxuICAgIHZhciBjb250YWluZXJJbiA9IHRyYWNlSW4udHJhbnNmb3JtcyB8fCBbXTtcbiAgICB2YXIgdHJhbnNmb3JtTGlzdCA9IGdsb2JhbFRyYW5zZm9ybXMuY29uY2F0KGNvbnRhaW5lckluKTtcbiAgICB2YXIgY29udGFpbmVyT3V0ID0gdHJhY2VPdXQudHJhbnNmb3JtcyA9IFtdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYW5zZm9ybUxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYW5zZm9ybUluID0gdHJhbnNmb3JtTGlzdFtpXTtcbiAgICAgICAgdmFyIHR5cGUgPSB0cmFuc2Zvcm1Jbi50eXBlO1xuICAgICAgICB2YXIgX21vZHVsZSA9IHRyYW5zZm9ybXNSZWdpc3RyeVt0eXBlXTtcbiAgICAgICAgdmFyIHRyYW5zZm9ybU91dDtcblxuICAgICAgICAvKlxuICAgICAgICAgKiBTdXBwbHkgZGVmYXVsdHMgbWF5IHJ1biB0d2ljZS4gRmlyc3QgcGFzcyBydW5zIGFsbCBzdXBwbHkgZGVmYXVsdHMgc3RlcHNcbiAgICAgICAgICogYW5kIGFkZHMgdGhlIF9tb2R1bGUgdG8gYW55IG91dHB1dCB0cmFuc2Zvcm1zLlxuICAgICAgICAgKiBJZiB0cmFuc2Zvcm1zIGV4aXN0IGFub3RoZXIgcGFzcyBpcyBydW4gc28gdGhhdCBhbnkgZ2VuZXJhdGVkIHRyYWNlcyBhbHNvXG4gICAgICAgICAqIGdvIHRocm91Z2ggc3VwcGx5IGRlZmF1bHRzLiBUaGlzIGhhcyB0aGUgZWZmZWN0IG9mIHJlcnVubmluZ1xuICAgICAgICAgKiBzdXBwbHlUcmFuc2Zvcm1EZWZhdWx0cy4gSWYgdGhlIHRyYW5zZm9ybSBkb2VzIG5vdCBoYXZlIGEgYHRyYW5zZm9ybWBcbiAgICAgICAgICogZnVuY3Rpb24gaXQgY291bGQgbm90IGhhdmUgZ2VuZXJhdGVkIGFueSBuZXcgdHJhY2VzIGFuZCB0aGUgc2Vjb25kIHN0YWdlXG4gICAgICAgICAqIGlzIHVubmVjZXNzYXJ5LiBXZSBkZXRlY3QgdGhpcyBjYXNlIHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMuXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgaXNGaXJzdFN0YWdlID0gISh0cmFuc2Zvcm1Jbi5fbW9kdWxlICYmIHRyYW5zZm9ybUluLl9tb2R1bGUgPT09IF9tb2R1bGUpO1xuICAgICAgICB2YXIgZG9MYXRlclN0YWdlcyA9IF9tb2R1bGUgJiYgdHlwZW9mIF9tb2R1bGUudHJhbnNmb3JtID09PSAnZnVuY3Rpb24nO1xuXG4gICAgICAgIGlmKCFfbW9kdWxlKSBMaWIud2FybignVW5yZWNvZ25pemVkIHRyYW5zZm9ybSB0eXBlICcgKyB0eXBlICsgJy4nKTtcblxuICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuc3VwcGx5RGVmYXVsdHMgJiYgKGlzRmlyc3RTdGFnZSB8fCBkb0xhdGVyU3RhZ2VzKSkge1xuICAgICAgICAgICAgdHJhbnNmb3JtT3V0ID0gX21vZHVsZS5zdXBwbHlEZWZhdWx0cyh0cmFuc2Zvcm1JbiwgdHJhY2VPdXQsIGxheW91dCwgdHJhY2VJbik7XG4gICAgICAgICAgICB0cmFuc2Zvcm1PdXQudHlwZSA9IHR5cGU7XG4gICAgICAgICAgICB0cmFuc2Zvcm1PdXQuX21vZHVsZSA9IF9tb2R1bGU7XG5cbiAgICAgICAgICAgIExpYi5wdXNoVW5pcXVlKHRyYW5zZm9ybU1vZHVsZXMsIF9tb2R1bGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHJhbnNmb3JtT3V0ID0gTGliLmV4dGVuZEZsYXQoe30sIHRyYW5zZm9ybUluKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRhaW5lck91dC5wdXNoKHRyYW5zZm9ybU91dCk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gYXBwbHlUcmFuc2Zvcm1zKGZ1bGxUcmFjZSwgZnVsbERhdGEsIGxheW91dCwgZnVsbExheW91dCkge1xuICAgIHZhciBjb250YWluZXIgPSBmdWxsVHJhY2UudHJhbnNmb3JtcztcbiAgICB2YXIgZGF0YU91dCA9IFtmdWxsVHJhY2VdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNvbnRhaW5lci5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhbnNmb3JtID0gY29udGFpbmVyW2ldO1xuICAgICAgICB2YXIgX21vZHVsZSA9IHRyYW5zZm9ybXNSZWdpc3RyeVt0cmFuc2Zvcm0udHlwZV07XG5cbiAgICAgICAgaWYoX21vZHVsZSAmJiBfbW9kdWxlLnRyYW5zZm9ybSkge1xuICAgICAgICAgICAgZGF0YU91dCA9IF9tb2R1bGUudHJhbnNmb3JtKGRhdGFPdXQsIHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zZm9ybSxcbiAgICAgICAgICAgICAgICBmdWxsVHJhY2U6IGZ1bGxUcmFjZSxcbiAgICAgICAgICAgICAgICBmdWxsRGF0YTogZnVsbERhdGEsXG4gICAgICAgICAgICAgICAgbGF5b3V0OiBsYXlvdXQsXG4gICAgICAgICAgICAgICAgZnVsbExheW91dDogZnVsbExheW91dCxcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1JbmRleDogaVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YU91dDtcbn1cblxucGxvdHMuc3VwcGx5TGF5b3V0R2xvYmFsRGVmYXVsdHMgPSBmdW5jdGlvbihsYXlvdXRJbiwgbGF5b3V0T3V0LCBmb3JtYXRPYmopIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShsYXlvdXRJbiwgbGF5b3V0T3V0LCBwbG90cy5sYXlvdXRBdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdGVtcGxhdGUgPSBsYXlvdXRJbi50ZW1wbGF0ZTtcbiAgICBpZihMaWIuaXNQbGFpbk9iamVjdCh0ZW1wbGF0ZSkpIHtcbiAgICAgICAgbGF5b3V0T3V0LnRlbXBsYXRlID0gdGVtcGxhdGU7XG4gICAgICAgIGxheW91dE91dC5fdGVtcGxhdGUgPSB0ZW1wbGF0ZS5sYXlvdXQ7XG4gICAgICAgIGxheW91dE91dC5fZGF0YVRlbXBsYXRlID0gdGVtcGxhdGUuZGF0YTtcbiAgICB9XG5cbiAgICB2YXIgZ2xvYmFsRm9udCA9IExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2ZvbnQnKTtcblxuICAgIGNvZXJjZSgndGl0bGUudGV4dCcsIGxheW91dE91dC5fZGZsdFRpdGxlLnBsb3QpO1xuXG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAndGl0bGUuZm9udCcsIHtcbiAgICAgICAgZmFtaWx5OiBnbG9iYWxGb250LmZhbWlseSxcbiAgICAgICAgc2l6ZTogTWF0aC5yb3VuZChnbG9iYWxGb250LnNpemUgKiAxLjQpLFxuICAgICAgICBjb2xvcjogZ2xvYmFsRm9udC5jb2xvclxuICAgIH0pO1xuXG4gICAgY29lcmNlKCd0aXRsZS54cmVmJyk7XG4gICAgY29lcmNlKCd0aXRsZS55cmVmJyk7XG4gICAgY29lcmNlKCd0aXRsZS54Jyk7XG4gICAgY29lcmNlKCd0aXRsZS55Jyk7XG4gICAgY29lcmNlKCd0aXRsZS54YW5jaG9yJyk7XG4gICAgY29lcmNlKCd0aXRsZS55YW5jaG9yJyk7XG4gICAgY29lcmNlKCd0aXRsZS5wYWQudCcpO1xuICAgIGNvZXJjZSgndGl0bGUucGFkLnInKTtcbiAgICBjb2VyY2UoJ3RpdGxlLnBhZC5iJyk7XG4gICAgY29lcmNlKCd0aXRsZS5wYWQubCcpO1xuXG4gICAgLy8gTWFrZSBzdXJlIHRoYXQgYXV0b3NpemUgaXMgZGVmYXVsdGVkIHRvICp0cnVlKlxuICAgIC8vIG9uIGxheW91dHMgd2l0aCBubyBzZXQgd2lkdGggYW5kIGhlaWdodCBmb3IgYmFja3dhcmQgY29tcGF0aWJseSxcbiAgICAvLyBpbiBwYXJ0aWN1bGFyIGh0dHBzOi8vcGxvdC5seS9qYXZhc2NyaXB0L3Jlc3BvbnNpdmUtZmx1aWQtbGF5b3V0L1xuICAgIC8vXG4gICAgLy8gQmVmb3JlIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL3B1bGwvNjM1ICxcbiAgICAvLyBsYXlvdXRzIHdpdGggbm8gc2V0IHdpZHRoIGFuZCBoZWlnaHQgd2VyZSBzZXQgdGVtcG9yYXJ5IHNldCB0byAnaW5pdGlhbCdcbiAgICAvLyB0byBwYXNzIHRocm91Z2ggdGhlIGF1dG9zaXplIHJvdXRpbmVcbiAgICAvL1xuICAgIC8vIFRoaXMgYmVoYXZpb3IgaXMgc3ViamVjdCB0byBjaGFuZ2UgaW4gdjIuXG4gICAgY29lcmNlKCdhdXRvc2l6ZScsICEobGF5b3V0SW4ud2lkdGggJiYgbGF5b3V0SW4uaGVpZ2h0KSk7XG5cbiAgICBjb2VyY2UoJ3dpZHRoJyk7XG4gICAgY29lcmNlKCdoZWlnaHQnKTtcbiAgICBjb2VyY2UoJ21hcmdpbi5sJyk7XG4gICAgY29lcmNlKCdtYXJnaW4ucicpO1xuICAgIGNvZXJjZSgnbWFyZ2luLnQnKTtcbiAgICBjb2VyY2UoJ21hcmdpbi5iJyk7XG4gICAgY29lcmNlKCdtYXJnaW4ucGFkJyk7XG4gICAgY29lcmNlKCdtYXJnaW4uYXV0b2V4cGFuZCcpO1xuXG4gICAgaWYobGF5b3V0SW4ud2lkdGggJiYgbGF5b3V0SW4uaGVpZ2h0KSBwbG90cy5zYW5pdGl6ZU1hcmdpbnMobGF5b3V0T3V0KTtcblxuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZ3JpZCcsICdzaXplRGVmYXVsdHMnKShsYXlvdXRJbiwgbGF5b3V0T3V0KTtcblxuICAgIGNvZXJjZSgncGFwZXJfYmdjb2xvcicpO1xuXG4gICAgY29lcmNlKCdzZXBhcmF0b3JzJywgZm9ybWF0T2JqLmRlY2ltYWwgKyBmb3JtYXRPYmoudGhvdXNhbmRzKTtcbiAgICBjb2VyY2UoJ2hpZGVzb3VyY2VzJyk7XG5cbiAgICBjb2VyY2UoJ2NvbG9yd2F5Jyk7XG5cbiAgICBjb2VyY2UoJ2RhdGFyZXZpc2lvbicpO1xuICAgIHZhciB1aXJldmlzaW9uID0gY29lcmNlKCd1aXJldmlzaW9uJyk7XG4gICAgY29lcmNlKCdlZGl0cmV2aXNpb24nLCB1aXJldmlzaW9uKTtcbiAgICBjb2VyY2UoJ3NlbGVjdGlvbnJldmlzaW9uJywgdWlyZXZpc2lvbik7XG5cbiAgICBjb2VyY2UoJ21vZGViYXIub3JpZW50YXRpb24nKTtcbiAgICBjb2VyY2UoJ21vZGViYXIuYmdjb2xvcicsIENvbG9yLmFkZE9wYWNpdHkobGF5b3V0T3V0LnBhcGVyX2JnY29sb3IsIDAuNSkpO1xuICAgIHZhciBtb2RlYmFyRGVmYXVsdENvbG9yID0gQ29sb3IuY29udHJhc3QoQ29sb3IucmdiKGxheW91dE91dC5tb2RlYmFyLmJnY29sb3IpKTtcbiAgICBjb2VyY2UoJ21vZGViYXIuY29sb3InLCBDb2xvci5hZGRPcGFjaXR5KG1vZGViYXJEZWZhdWx0Q29sb3IsIDAuMykpO1xuICAgIGNvZXJjZSgnbW9kZWJhci5hY3RpdmVjb2xvcicsIENvbG9yLmFkZE9wYWNpdHkobW9kZWJhckRlZmF1bHRDb2xvciwgMC43KSk7XG4gICAgY29lcmNlKCdtb2RlYmFyLnVpcmV2aXNpb24nLCB1aXJldmlzaW9uKTtcblxuICAgIGNvZXJjZSgnbWV0YScpO1xuXG4gICAgLy8gZG8gbm90IGluY2x1ZGUgZGVmYXVsdHMgaW4gZnVsbExheW91dCB3aGVuIHVzZXJzIGRvIG5vdCBzZXQgdHJhbnNpdGlvblxuICAgIGlmKExpYi5pc1BsYWluT2JqZWN0KGxheW91dEluLnRyYW5zaXRpb24pKSB7XG4gICAgICAgIGNvZXJjZSgndHJhbnNpdGlvbi5kdXJhdGlvbicpO1xuICAgICAgICBjb2VyY2UoJ3RyYW5zaXRpb24uZWFzaW5nJyk7XG4gICAgICAgIGNvZXJjZSgndHJhbnNpdGlvbi5vcmRlcmluZycpO1xuICAgIH1cblxuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZChcbiAgICAgICAgJ2NhbGVuZGFycycsXG4gICAgICAgICdoYW5kbGVEZWZhdWx0cydcbiAgICApKGxheW91dEluLCBsYXlvdXRPdXQsICdjYWxlbmRhcicpO1xuXG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKFxuICAgICAgICAnZngnLFxuICAgICAgICAnc3VwcGx5TGF5b3V0R2xvYmFsRGVmYXVsdHMnXG4gICAgKShsYXlvdXRJbiwgbGF5b3V0T3V0LCBjb2VyY2UpO1xufTtcblxucGxvdHMucGxvdEF1dG9TaXplID0gZnVuY3Rpb24gcGxvdEF1dG9TaXplKGdkLCBsYXlvdXQsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgY29udGV4dCA9IGdkLl9jb250ZXh0IHx8IHt9O1xuICAgIHZhciBmcmFtZU1hcmdpbnMgPSBjb250ZXh0LmZyYW1lTWFyZ2lucztcbiAgICB2YXIgbmV3V2lkdGg7XG4gICAgdmFyIG5ld0hlaWdodDtcblxuICAgIHZhciBpc1Bsb3REaXYgPSBMaWIuaXNQbG90RGl2KGdkKTtcblxuICAgIGlmKGlzUGxvdERpdikgZ2QuZW1pdCgncGxvdGx5X2F1dG9zaXplJyk7XG5cbiAgICAvLyBlbWJlZGRlZCBpbiBhbiBpZnJhbWUgLSBqdXN0IHRha2UgdGhlIGZ1bGwgaWZyYW1lIHNpemVcbiAgICAvLyBpZiB3ZSBnZXQgdG8gdGhpcyBwb2ludCwgd2l0aCBubyBhc3BlY3QgcmF0aW8gcmVzdHJpY3Rpb25zXG4gICAgaWYoY29udGV4dC5maWxsRnJhbWUpIHtcbiAgICAgICAgbmV3V2lkdGggPSB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICAgICAgbmV3SGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0O1xuXG4gICAgICAgIC8vIHNvbWVob3cgd2UgZ2V0IGEgZmV3IGV4dHJhIHB4IGhlaWdodCBzb21ldGltZXMuLi5cbiAgICAgICAgLy8ganVzdCBoaWRlIGl0XG4gICAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBwbG90bHkuanMgLSBsZXQgdGhlIGRldmVsb3BlcnMgZG8gd2hhdCB0aGV5IHdhbnQsIGVpdGhlclxuICAgICAgICAvLyBwcm92aWRlIGhlaWdodCBhbmQgd2lkdGggZm9yIHRoZSBjb250YWluZXIgZGl2LFxuICAgICAgICAvLyBzcGVjaWZ5IHNpemUgaW4gbGF5b3V0LCBvciB0YWtlIHRoZSBkZWZhdWx0cyxcbiAgICAgICAgLy8gYnV0IGRvbid0IGVuZm9yY2UgYW55IHJhdGlvIHJlc3RyaWN0aW9uc1xuICAgICAgICB2YXIgY29tcHV0ZWRTdHlsZSA9IGlzUGxvdERpdiA/IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGdkKSA6IHt9O1xuXG4gICAgICAgIG5ld1dpZHRoID0gcGFyc2VGbG9hdChjb21wdXRlZFN0eWxlLndpZHRoKSB8fCBwYXJzZUZsb2F0KGNvbXB1dGVkU3R5bGUubWF4V2lkdGgpIHx8IGZ1bGxMYXlvdXQud2lkdGg7XG4gICAgICAgIG5ld0hlaWdodCA9IHBhcnNlRmxvYXQoY29tcHV0ZWRTdHlsZS5oZWlnaHQpIHx8IHBhcnNlRmxvYXQoY29tcHV0ZWRTdHlsZS5tYXhIZWlnaHQpIHx8IGZ1bGxMYXlvdXQuaGVpZ2h0O1xuXG4gICAgICAgIGlmKGlzTnVtZXJpYyhmcmFtZU1hcmdpbnMpICYmIGZyYW1lTWFyZ2lucyA+IDApIHtcbiAgICAgICAgICAgIHZhciBmYWN0b3IgPSAxIC0gMiAqIGZyYW1lTWFyZ2lucztcbiAgICAgICAgICAgIG5ld1dpZHRoID0gTWF0aC5yb3VuZChmYWN0b3IgKiBuZXdXaWR0aCk7XG4gICAgICAgICAgICBuZXdIZWlnaHQgPSBNYXRoLnJvdW5kKGZhY3RvciAqIG5ld0hlaWdodCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbWluV2lkdGggPSBwbG90cy5sYXlvdXRBdHRyaWJ1dGVzLndpZHRoLm1pbjtcbiAgICB2YXIgbWluSGVpZ2h0ID0gcGxvdHMubGF5b3V0QXR0cmlidXRlcy5oZWlnaHQubWluO1xuICAgIGlmKG5ld1dpZHRoIDwgbWluV2lkdGgpIG5ld1dpZHRoID0gbWluV2lkdGg7XG4gICAgaWYobmV3SGVpZ2h0IDwgbWluSGVpZ2h0KSBuZXdIZWlnaHQgPSBtaW5IZWlnaHQ7XG5cbiAgICB2YXIgd2lkdGhIYXNDaGFuZ2VkID0gIWxheW91dC53aWR0aCAmJlxuICAgICAgICAoTWF0aC5hYnMoZnVsbExheW91dC53aWR0aCAtIG5ld1dpZHRoKSA+IDEpO1xuICAgIHZhciBoZWlnaHRIYXNDaGFuZ2VkID0gIWxheW91dC5oZWlnaHQgJiZcbiAgICAgICAgKE1hdGguYWJzKGZ1bGxMYXlvdXQuaGVpZ2h0IC0gbmV3SGVpZ2h0KSA+IDEpO1xuXG4gICAgaWYoaGVpZ2h0SGFzQ2hhbmdlZCB8fCB3aWR0aEhhc0NoYW5nZWQpIHtcbiAgICAgICAgaWYod2lkdGhIYXNDaGFuZ2VkKSBmdWxsTGF5b3V0LndpZHRoID0gbmV3V2lkdGg7XG4gICAgICAgIGlmKGhlaWdodEhhc0NoYW5nZWQpIGZ1bGxMYXlvdXQuaGVpZ2h0ID0gbmV3SGVpZ2h0O1xuICAgIH1cblxuICAgIC8vIGNhY2hlIGluaXRpYWwgYXV0b3NpemUgdmFsdWUsIHVzZWQgaW4gcmVsYXlvdXQgd2hlblxuICAgIC8vIHdpZHRoIG9yIGhlaWdodCB2YWx1ZXMgYXJlIHNldCB0byBudWxsXG4gICAgaWYoIWdkLl9pbml0aWFsQXV0b1NpemUpIHtcbiAgICAgICAgZ2QuX2luaXRpYWxBdXRvU2l6ZSA9IHsgd2lkdGg6IG5ld1dpZHRoLCBoZWlnaHQ6IG5ld0hlaWdodCB9O1xuICAgIH1cblxuICAgIHBsb3RzLnNhbml0aXplTWFyZ2lucyhmdWxsTGF5b3V0KTtcbn07XG5cbnBsb3RzLnN1cHBseUxheW91dE1vZHVsZURlZmF1bHRzID0gZnVuY3Rpb24obGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEsIHRyYW5zaXRpb25EYXRhKSB7XG4gICAgdmFyIGNvbXBvbmVudHNSZWdpc3RyeSA9IFJlZ2lzdHJ5LmNvbXBvbmVudHNSZWdpc3RyeTtcbiAgICB2YXIgYmFzZVBsb3RNb2R1bGVzID0gbGF5b3V0T3V0Ll9iYXNlUGxvdE1vZHVsZXM7XG4gICAgdmFyIGNvbXBvbmVudCwgaSwgX21vZHVsZTtcblxuICAgIHZhciBDYXJ0ZXNpYW4gPSBSZWdpc3RyeS5zdWJwbG90c1JlZ2lzdHJ5LmNhcnRlc2lhbjtcblxuICAgIC8vIGNoZWNrIGlmIGFueSBjb21wb25lbnRzIG5lZWQgdG8gYWRkIG1vcmUgYmFzZSBwbG90IG1vZHVsZXNcbiAgICAvLyB0aGF0IHdlcmVuJ3QgY2FwdHVyZWQgYnkgdHJhY2VzXG4gICAgZm9yKGNvbXBvbmVudCBpbiBjb21wb25lbnRzUmVnaXN0cnkpIHtcbiAgICAgICAgX21vZHVsZSA9IGNvbXBvbmVudHNSZWdpc3RyeVtjb21wb25lbnRdO1xuXG4gICAgICAgIGlmKF9tb2R1bGUuaW5jbHVkZUJhc2VQbG90KSB7XG4gICAgICAgICAgICBfbW9kdWxlLmluY2x1ZGVCYXNlUGxvdChsYXlvdXRJbiwgbGF5b3V0T3V0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSB3ZSAqYXQgbGVhc3QqIGhhdmUgc29tZSBjYXJ0ZXNpYW4gYXhlc1xuICAgIGlmKCFiYXNlUGxvdE1vZHVsZXMubGVuZ3RoKSB7XG4gICAgICAgIGJhc2VQbG90TW9kdWxlcy5wdXNoKENhcnRlc2lhbik7XG4gICAgfVxuXG4gICAgLy8gZW5zdXJlIGFsbCBjYXJ0ZXNpYW4gYXhlcyBoYXZlIGF0IGxlYXN0IG9uZSBzdWJwbG90XG4gICAgaWYobGF5b3V0T3V0Ll9oYXMoJ2NhcnRlc2lhbicpKSB7XG4gICAgICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZ3JpZCcsICdjb250ZW50RGVmYXVsdHMnKShsYXlvdXRJbiwgbGF5b3V0T3V0KTtcbiAgICAgICAgQ2FydGVzaWFuLmZpbmFsaXplU3VicGxvdHMobGF5b3V0SW4sIGxheW91dE91dCk7XG4gICAgfVxuXG4gICAgLy8gc29ydCBzdWJwbG90IGxpc3RzXG4gICAgZm9yKHZhciBzdWJwbG90VHlwZSBpbiBsYXlvdXRPdXQuX3N1YnBsb3RzKSB7XG4gICAgICAgIGxheW91dE91dC5fc3VicGxvdHNbc3VicGxvdFR5cGVdLnNvcnQoTGliLnN1YnBsb3RTb3J0KTtcbiAgICB9XG5cbiAgICAvLyBiYXNlIHBsb3QgbW9kdWxlIGxheW91dCBkZWZhdWx0c1xuICAgIGZvcihpID0gMDsgaSA8IGJhc2VQbG90TW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbW9kdWxlID0gYmFzZVBsb3RNb2R1bGVzW2ldO1xuXG4gICAgICAgIC8vIGUuZy4gcGllIGRvZXMgbm90IGhhdmUgYSBsYXlvdXQtZGVmYXVsdHMgc3RlcFxuICAgICAgICBpZihfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKSB7XG4gICAgICAgICAgICBfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRyYWNlIG1vZHVsZSBsYXlvdXQgZGVmYXVsdHNcbiAgICAvLyB1c2UgX21vZHVsZXMgcmF0aGVyIHRoYW4gX3Zpc2libGVNb2R1bGVzIHNvIHRoYXQgZXZlblxuICAgIC8vIGxlZ2VuZG9ubHkgdHJhY2VzIGNhbiBpbmNsdWRlIHNldHRpbmdzIC0gZWcgYmFybW9kZSwgd2hpY2ggYWZmZWN0c1xuICAgIC8vIGxlZ2VuZC50cmFjZW9yZGVyIGRlZmF1bHQgdmFsdWUuXG4gICAgdmFyIG1vZHVsZXMgPSBsYXlvdXRPdXQuX21vZHVsZXM7XG4gICAgZm9yKGkgPSAwOyBpIDwgbW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbW9kdWxlID0gbW9kdWxlc1tpXTtcblxuICAgICAgICBpZihfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKSB7XG4gICAgICAgICAgICBfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRyYW5zZm9ybSBtb2R1bGUgbGF5b3V0IGRlZmF1bHRzXG4gICAgdmFyIHRyYW5zZm9ybU1vZHVsZXMgPSBsYXlvdXRPdXQuX3RyYW5zZm9ybU1vZHVsZXM7XG4gICAgZm9yKGkgPSAwOyBpIDwgdHJhbnNmb3JtTW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbW9kdWxlID0gdHJhbnNmb3JtTW9kdWxlc1tpXTtcblxuICAgICAgICBpZihfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKSB7XG4gICAgICAgICAgICBfbW9kdWxlLnN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhLCB0cmFuc2l0aW9uRGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoY29tcG9uZW50IGluIGNvbXBvbmVudHNSZWdpc3RyeSkge1xuICAgICAgICBfbW9kdWxlID0gY29tcG9uZW50c1JlZ2lzdHJ5W2NvbXBvbmVudF07XG5cbiAgICAgICAgaWYoX21vZHVsZS5zdXBwbHlMYXlvdXREZWZhdWx0cykge1xuICAgICAgICAgICAgX21vZHVsZS5zdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBSZW1vdmUgYWxsIHBsb3RseSBhdHRyaWJ1dGVzIGZyb20gYSBkaXYgc28gaXQgY2FuIGJlIHJlcGxvdHRlZCBmcmVzaFxuLy8gVE9ETzogdGhlc2UgcmVhbGx5IG5lZWQgdG8gYmUgZW5jYXBzdWxhdGVkIGludG8gYSBtdWNoIHNtYWxsZXIgc2V0Li4uXG5wbG90cy5wdXJnZSA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgLy8gbm90ZTogd2UgRE8gTk9UIHJlbW92ZSBfY29udGV4dCBiZWNhdXNlIGl0IGRvZXNuJ3QgY2hhbmdlIHdoZW4gd2UgaW5zZXJ0XG4gICAgLy8gYSBuZXcgcGxvdCwgYW5kIG1heSBoYXZlIGJlZW4gc2V0IG91dHNpZGUgb2Ygb3VyIHNjb3BlLlxuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dCB8fCB7fTtcbiAgICBpZihmdWxsTGF5b3V0Ll9nbGNvbnRhaW5lciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGZ1bGxMYXlvdXQuX2dsY29udGFpbmVyLnNlbGVjdEFsbCgnLmdsLWNhbnZhcycpLnJlbW92ZSgpO1xuICAgICAgICBmdWxsTGF5b3V0Ll9nbGNvbnRhaW5lci5yZW1vdmUoKTtcbiAgICAgICAgZnVsbExheW91dC5fZ2xjYW52YXMgPSBudWxsO1xuICAgIH1cbiAgICBpZihmdWxsTGF5b3V0Ll9nZW9jb250YWluZXIgIT09IHVuZGVmaW5lZCkgZnVsbExheW91dC5fZ2VvY29udGFpbmVyLnJlbW92ZSgpO1xuXG4gICAgLy8gcmVtb3ZlIG1vZGViYXJcbiAgICBpZihmdWxsTGF5b3V0Ll9tb2RlQmFyKSBmdWxsTGF5b3V0Ll9tb2RlQmFyLmRlc3Ryb3koKTtcblxuICAgIGlmKGdkLl90cmFuc2l0aW9uRGF0YSkge1xuICAgICAgICAvLyBFbnN1cmUgYW55IGRhbmdsaW5nIGNhbGxiYWNrcyBhcmUgc2ltcGx5IGRyb3BwZWQgaWYgdGhlIHBsb3QgaXMgcHVyZ2VkLlxuICAgICAgICAvLyBUaGlzIGlzIG1vcmUgb3IgbGVzcyBvbmx5IGFjdHVhbGx5IGltcG9ydGFudCBmb3IgdGVzdGluZy5cbiAgICAgICAgaWYoZ2QuX3RyYW5zaXRpb25EYXRhLl9pbnRlcnJ1cHRDYWxsYmFja3MpIHtcbiAgICAgICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzLmxlbmd0aCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZihnZC5fdHJhbnNpdGlvbkRhdGEuX2FuaW1hdGlvblJhZikge1xuICAgICAgICAgICAgd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lKGdkLl90cmFuc2l0aW9uRGF0YS5fYW5pbWF0aW9uUmFmKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHJlbW92ZSBhbnkgcGxhbm5lZCB0aHJvdHRsZXNcbiAgICBMaWIuY2xlYXJUaHJvdHRsZSgpO1xuXG4gICAgLy8gcmVtb3ZlIHJlc3BvbnNpdmUgaGFuZGxlclxuICAgIExpYi5jbGVhclJlc3BvbnNpdmUoZ2QpO1xuXG4gICAgLy8gZGF0YSBhbmQgbGF5b3V0XG4gICAgZGVsZXRlIGdkLmRhdGE7XG4gICAgZGVsZXRlIGdkLmxheW91dDtcbiAgICBkZWxldGUgZ2QuX2Z1bGxEYXRhO1xuICAgIGRlbGV0ZSBnZC5fZnVsbExheW91dDtcbiAgICBkZWxldGUgZ2QuY2FsY2RhdGE7XG4gICAgZGVsZXRlIGdkLmZyYW1ld29yaztcbiAgICBkZWxldGUgZ2QuZW1wdHk7XG5cbiAgICBkZWxldGUgZ2QuZmlkO1xuXG4gICAgZGVsZXRlIGdkLnVuZG9xdWV1ZTsgLy8gYWN0aW9uIHF1ZXVlXG4gICAgZGVsZXRlIGdkLnVuZG9udW07XG4gICAgZGVsZXRlIGdkLmF1dG9wbGF5OyAvLyBhcmUgd2UgZG9pbmcgYW4gYWN0aW9uIHRoYXQgZG9lc24ndCBnbyBpbiB1bmRvIHF1ZXVlP1xuICAgIGRlbGV0ZSBnZC5jaGFuZ2VkO1xuXG4gICAgLy8gdGhlc2UgZ2V0IHJlY3JlYXRlZCBvbiBQbG90bHkucGxvdCBhbnl3YXksIGJ1dCBqdXN0IHRvIGJlIHNhZmVcbiAgICAvLyAoYW5kIHRvIGhhdmUgYSByZWNvcmQgb2YgdGhlbS4uLilcbiAgICBkZWxldGUgZ2QuX3Byb21pc2VzO1xuICAgIGRlbGV0ZSBnZC5fcmVkcmF3VGltZXI7XG4gICAgZGVsZXRlIGdkLl9obWx1bWNvdW50O1xuICAgIGRlbGV0ZSBnZC5faG1waXhjb3VudDtcbiAgICBkZWxldGUgZ2QuX3RyYW5zaXRpb25EYXRhO1xuICAgIGRlbGV0ZSBnZC5fdHJhbnNpdGlvbmluZztcbiAgICBkZWxldGUgZ2QuX2luaXRpYWxBdXRvU2l6ZTtcbiAgICBkZWxldGUgZ2QuX3RyYW5zaXRpb25pbmdXaXRoRHVyYXRpb247XG5cbiAgICAvLyBjcmVhdGVkIGR1cmluZyBjZXJ0YWluIGV2ZW50cywgdGhhdCAqc2hvdWxkKiBjbGVhbiB0aGVtIHVwXG4gICAgLy8gdGhlbXNlbHZlcywgYnV0IG1heSBub3QgaWYgdGhlcmUgd2FzIGFuIGVycm9yXG4gICAgZGVsZXRlIGdkLl9kcmFnZ2luZztcbiAgICBkZWxldGUgZ2QuX2RyYWdnZWQ7XG4gICAgZGVsZXRlIGdkLl9kcmFnZGF0YTtcbiAgICBkZWxldGUgZ2QuX2hvdmVyZGF0YTtcbiAgICBkZWxldGUgZ2QuX3NuYXBzaG90SW5Qcm9ncmVzcztcbiAgICBkZWxldGUgZ2QuX2VkaXRpbmc7XG4gICAgZGVsZXRlIGdkLl9tb3VzZURvd25UaW1lO1xuICAgIGRlbGV0ZSBnZC5fbGVnZW5kTW91c2VEb3duVGltZTtcblxuICAgIC8vIHJlbW92ZSBhbGwgZXZlbnQgbGlzdGVuZXJzXG4gICAgaWYoZ2QucmVtb3ZlQWxsTGlzdGVuZXJzKSBnZC5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbn07XG5cbnBsb3RzLnN0eWxlID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgX21vZHVsZXMgPSBnZC5fZnVsbExheW91dC5fdmlzaWJsZU1vZHVsZXM7XG4gICAgdmFyIHN0eWxlTW9kdWxlcyA9IFtdO1xuICAgIHZhciBpO1xuXG4gICAgLy8gc29tZSB0cmFjZSBtb2R1bGVzIHJldXNlIHRoZSBzYW1lIHN0eWxlIG1ldGhvZCxcbiAgICAvLyBtYWtlIHN1cmUgdG8gbm90IHVubmVjZXNzYXJ5IGNhbGwgdGhlbSBtdWx0aXBsZSB0aW1lcy5cblxuICAgIGZvcihpID0gMDsgaSA8IF9tb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBfbW9kdWxlID0gX21vZHVsZXNbaV07XG4gICAgICAgIGlmKF9tb2R1bGUuc3R5bGUpIHtcbiAgICAgICAgICAgIExpYi5wdXNoVW5pcXVlKHN0eWxlTW9kdWxlcywgX21vZHVsZS5zdHlsZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzdHlsZU1vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgc3R5bGVNb2R1bGVzW2ldKGdkKTtcbiAgICB9XG59O1xuXG5wbG90cy5zYW5pdGl6ZU1hcmdpbnMgPSBmdW5jdGlvbihmdWxsTGF5b3V0KSB7XG4gICAgLy8gcG9sYXIgZG9lc24ndCBkbyBtYXJnaW5zLi4uXG4gICAgaWYoIWZ1bGxMYXlvdXQgfHwgIWZ1bGxMYXlvdXQubWFyZ2luKSByZXR1cm47XG5cbiAgICB2YXIgd2lkdGggPSBmdWxsTGF5b3V0LndpZHRoO1xuICAgIHZhciBoZWlnaHQgPSBmdWxsTGF5b3V0LmhlaWdodDtcbiAgICB2YXIgbWFyZ2luID0gZnVsbExheW91dC5tYXJnaW47XG4gICAgdmFyIHBsb3RXaWR0aCA9IHdpZHRoIC0gKG1hcmdpbi5sICsgbWFyZ2luLnIpO1xuICAgIHZhciBwbG90SGVpZ2h0ID0gaGVpZ2h0IC0gKG1hcmdpbi50ICsgbWFyZ2luLmIpO1xuICAgIHZhciBjb3JyZWN0aW9uO1xuXG4gICAgLy8gaWYgbWFyZ2luLmwgKyBtYXJnaW4uciA9IDAgdGhlbiBwbG90V2lkdGggPiAwXG4gICAgLy8gYXMgd2lkdGggPj0gMTAgYnkgc3VwcGx5RGVmYXVsdHNcbiAgICAvLyBzaW1pbGFybHkgZm9yIG1hcmdpbi50ICsgbWFyZ2luLmJcblxuICAgIGlmKHBsb3RXaWR0aCA8IDApIHtcbiAgICAgICAgY29ycmVjdGlvbiA9ICh3aWR0aCAtIDEpIC8gKG1hcmdpbi5sICsgbWFyZ2luLnIpO1xuICAgICAgICBtYXJnaW4ubCA9IE1hdGguZmxvb3IoY29ycmVjdGlvbiAqIG1hcmdpbi5sKTtcbiAgICAgICAgbWFyZ2luLnIgPSBNYXRoLmZsb29yKGNvcnJlY3Rpb24gKiBtYXJnaW4ucik7XG4gICAgfVxuXG4gICAgaWYocGxvdEhlaWdodCA8IDApIHtcbiAgICAgICAgY29ycmVjdGlvbiA9IChoZWlnaHQgLSAxKSAvIChtYXJnaW4udCArIG1hcmdpbi5iKTtcbiAgICAgICAgbWFyZ2luLnQgPSBNYXRoLmZsb29yKGNvcnJlY3Rpb24gKiBtYXJnaW4udCk7XG4gICAgICAgIG1hcmdpbi5iID0gTWF0aC5mbG9vcihjb3JyZWN0aW9uICogbWFyZ2luLmIpO1xuICAgIH1cbn07XG5cbnBsb3RzLmNsZWFyQXV0b01hcmdpbklkcyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgZ2QuX2Z1bGxMYXlvdXQuX3B1c2htYXJnaW5JZHMgPSB7fTtcbn07XG5cbnBsb3RzLmFsbG93QXV0b01hcmdpbiA9IGZ1bmN0aW9uKGdkLCBpZCkge1xuICAgIGdkLl9mdWxsTGF5b3V0Ll9wdXNobWFyZ2luSWRzW2lkXSA9IDE7XG59O1xuXG5mdW5jdGlvbiBpbml0TWFyZ2lucyhmdWxsTGF5b3V0KSB7XG4gICAgdmFyIG1hcmdpbiA9IGZ1bGxMYXlvdXQubWFyZ2luO1xuXG4gICAgaWYoIWZ1bGxMYXlvdXQuX3NpemUpIHtcbiAgICAgICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZSA9IHtcbiAgICAgICAgICAgIGw6IE1hdGgucm91bmQobWFyZ2luLmwpLFxuICAgICAgICAgICAgcjogTWF0aC5yb3VuZChtYXJnaW4uciksXG4gICAgICAgICAgICB0OiBNYXRoLnJvdW5kKG1hcmdpbi50KSxcbiAgICAgICAgICAgIGI6IE1hdGgucm91bmQobWFyZ2luLmIpLFxuICAgICAgICAgICAgcDogTWF0aC5yb3VuZChtYXJnaW4ucGFkKVxuICAgICAgICB9O1xuICAgICAgICBncy53ID0gTWF0aC5yb3VuZChmdWxsTGF5b3V0LndpZHRoKSAtIGdzLmwgLSBncy5yO1xuICAgICAgICBncy5oID0gTWF0aC5yb3VuZChmdWxsTGF5b3V0LmhlaWdodCkgLSBncy50IC0gZ3MuYjtcbiAgICB9XG4gICAgaWYoIWZ1bGxMYXlvdXQuX3B1c2htYXJnaW4pIGZ1bGxMYXlvdXQuX3B1c2htYXJnaW4gPSB7fTtcbiAgICBpZighZnVsbExheW91dC5fcHVzaG1hcmdpbklkcykgZnVsbExheW91dC5fcHVzaG1hcmdpbklkcyA9IHt9O1xufVxuXG4vKipcbiAqIGF1dG9NYXJnaW46IGNhbGxlZCBieSBjb21wb25lbnRzIHRoYXQgbWF5IG5lZWQgdG8gZXhwYW5kIHRoZSBtYXJnaW5zIHRvXG4gKiBiZSByZW5kZXJlZCBvbi1wbG90LlxuICpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBhbiBpZGVudGlmaWVyIHVuaXF1ZSAod2l0aGluIHRoaXMgcGxvdCkgdG8gdGhpcyBvYmplY3QsXG4gKiAgICAgc28gd2UgY2FuIHJlbW92ZSBhIHByZXZpb3VzIG1hcmdpbiBleHBhbnNpb24gZnJvbSB0aGUgc2FtZSBvYmplY3QuXG4gKiBAcGFyYW0ge29iamVjdH0gbyAtIHRoZSBtYXJnaW4gcmVxdWlyZW1lbnRzIG9mIHRoaXMgb2JqZWN0LCBvciBvbWl0IHRvIGRlbGV0ZVxuICogICAgIHRoaXMgZW50cnkgKGxpa2UgaWYgaXQncyBoaWRkZW4pLiBLZXlzIGFyZTpcbiAqICAgICB4LCB5OiBwbG90IGZyYWN0aW9uIG9mIHRoZSBhbmNob3IgcG9pbnQuXG4gKiAgICAgeGwsIHhyLCB5dCwgeWI6IGlmIHRoZSBvYmplY3QgaGFzIGFuIGV4dGVudCBkZWZpbmVkIGluIHBsb3QgZnJhY3Rpb24sXG4gKiAgICAgICAgIHlvdSBjYW4gc3BlY2lmeSBib3RoIGVkZ2VzIGFzIHBsb3QgZnJhY3Rpb25zIGluIGVhY2ggZGltZW5zaW9uXG4gKiAgICAgbCwgciwgdCwgYjogdGhlIHBpeGVscyB0byBwYWQgcGFzdCB0aGUgcGxvdCBmcmFjdGlvbiB4W2x8cl0gYW5kIHlbdHxiXVxuICogICAgIHBhZDogZXh0cmEgcGl4ZWxzIHRvIGFkZCBpbiBhbGwgZGlyZWN0aW9ucywgZGVmYXVsdCAxMiAod2h5PylcbiAqL1xucGxvdHMuYXV0b01hcmdpbiA9IGZ1bmN0aW9uKGdkLCBpZCwgbykge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICB2YXIgcHVzaE1hcmdpbiA9IGZ1bGxMYXlvdXQuX3B1c2htYXJnaW47XG4gICAgdmFyIHB1c2hNYXJnaW5JZHMgPSBmdWxsTGF5b3V0Ll9wdXNobWFyZ2luSWRzO1xuXG4gICAgaWYoZnVsbExheW91dC5tYXJnaW4uYXV0b2V4cGFuZCAhPT0gZmFsc2UpIHtcbiAgICAgICAgaWYoIW8pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBwdXNoTWFyZ2luW2lkXTtcbiAgICAgICAgICAgIGRlbGV0ZSBwdXNoTWFyZ2luSWRzW2lkXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBwYWQgPSBvLnBhZDtcbiAgICAgICAgICAgIGlmKHBhZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hcmdpbiA9IGZ1bGxMYXlvdXQubWFyZ2luO1xuICAgICAgICAgICAgICAgIC8vIGlmIG5vIGV4cGxpY2l0IHBhZCBpcyBnaXZlbiwgdXNlIDEycHggdW5sZXNzIHRoZXJlJ3MgYVxuICAgICAgICAgICAgICAgIC8vIHNwZWNpZmllZCBtYXJnaW4gdGhhdCdzIHNtYWxsZXIgdGhhbiB0aGF0XG4gICAgICAgICAgICAgICAgcGFkID0gTWF0aC5taW4oMTIsIG1hcmdpbi5sLCBtYXJnaW4uciwgbWFyZ2luLnQsIG1hcmdpbi5iKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gaWYgdGhlIGl0ZW0gaXMgdG9vIGJpZywganVzdCBnaXZlIGl0IGVub3VnaCBhdXRvbWFyZ2luIHRvXG4gICAgICAgICAgICAvLyBtYWtlIHN1cmUgeW91IGNhbiBzdGlsbCBncmFiIGl0IGFuZCBicmluZyBpdCBiYWNrXG4gICAgICAgICAgICBpZihvLmwgKyBvLnIgPiBmdWxsTGF5b3V0LndpZHRoICogMC41KSBvLmwgPSBvLnIgPSAwO1xuICAgICAgICAgICAgaWYoby5iICsgby50ID4gZnVsbExheW91dC5oZWlnaHQgKiAwLjUpIG8uYiA9IG8udCA9IDA7XG5cbiAgICAgICAgICAgIHZhciB4bCA9IG8ueGwgIT09IHVuZGVmaW5lZCA/IG8ueGwgOiBvLng7XG4gICAgICAgICAgICB2YXIgeHIgPSBvLnhyICE9PSB1bmRlZmluZWQgPyBvLnhyIDogby54O1xuICAgICAgICAgICAgdmFyIHl0ID0gby55dCAhPT0gdW5kZWZpbmVkID8gby55dCA6IG8ueTtcbiAgICAgICAgICAgIHZhciB5YiA9IG8ueWIgIT09IHVuZGVmaW5lZCA/IG8ueWIgOiBvLnk7XG5cbiAgICAgICAgICAgIHB1c2hNYXJnaW5baWRdID0ge1xuICAgICAgICAgICAgICAgIGw6IHt2YWw6IHhsLCBzaXplOiBvLmwgKyBwYWR9LFxuICAgICAgICAgICAgICAgIHI6IHt2YWw6IHhyLCBzaXplOiBvLnIgKyBwYWR9LFxuICAgICAgICAgICAgICAgIGI6IHt2YWw6IHliLCBzaXplOiBvLmIgKyBwYWR9LFxuICAgICAgICAgICAgICAgIHQ6IHt2YWw6IHl0LCBzaXplOiBvLnQgKyBwYWR9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcHVzaE1hcmdpbklkc1tpZF0gPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIWZ1bGxMYXlvdXQuX3JlcGxvdHRpbmcpIHtcbiAgICAgICAgICAgIHBsb3RzLmRvQXV0b01hcmdpbihnZCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5wbG90cy5kb0F1dG9NYXJnaW4gPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgaWYoIWZ1bGxMYXlvdXQuX3NpemUpIGZ1bGxMYXlvdXQuX3NpemUgPSB7fTtcbiAgICBpbml0TWFyZ2lucyhmdWxsTGF5b3V0KTtcblxuICAgIHZhciBncyA9IGZ1bGxMYXlvdXQuX3NpemU7XG4gICAgdmFyIG1hcmdpbiA9IGZ1bGxMYXlvdXQubWFyZ2luO1xuICAgIHZhciBvbGRNYXJnaW5zID0gTGliLmV4dGVuZEZsYXQoe30sIGdzKTtcblxuICAgIC8vIGFkanVzdCBtYXJnaW5zIGZvciBvdXRzaWRlIGNvbXBvbmVudHNcbiAgICAvLyBmdWxsTGF5b3V0Lm1hcmdpbiBpcyB0aGUgcmVxdWVzdGVkIG1hcmdpbixcbiAgICAvLyBmdWxsTGF5b3V0Ll9zaXplIGhhcyBtYXJnaW5zIGFuZCBwbG90c2l6ZSBhZnRlciBhZGp1c3RtZW50XG4gICAgdmFyIG1sID0gbWFyZ2luLmw7XG4gICAgdmFyIG1yID0gbWFyZ2luLnI7XG4gICAgdmFyIG10ID0gbWFyZ2luLnQ7XG4gICAgdmFyIG1iID0gbWFyZ2luLmI7XG4gICAgdmFyIHdpZHRoID0gZnVsbExheW91dC53aWR0aDtcbiAgICB2YXIgaGVpZ2h0ID0gZnVsbExheW91dC5oZWlnaHQ7XG4gICAgdmFyIHB1c2hNYXJnaW4gPSBmdWxsTGF5b3V0Ll9wdXNobWFyZ2luO1xuICAgIHZhciBwdXNoTWFyZ2luSWRzID0gZnVsbExheW91dC5fcHVzaG1hcmdpbklkcztcblxuICAgIGlmKGZ1bGxMYXlvdXQubWFyZ2luLmF1dG9leHBhbmQgIT09IGZhbHNlKSB7XG4gICAgICAgIGZvcih2YXIgayBpbiBwdXNoTWFyZ2luKSB7XG4gICAgICAgICAgICBpZighcHVzaE1hcmdpbklkc1trXSkgZGVsZXRlIHB1c2hNYXJnaW5ba107XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmaWxsIGluIHRoZSByZXF1ZXN0ZWQgbWFyZ2luc1xuICAgICAgICBwdXNoTWFyZ2luLmJhc2UgPSB7XG4gICAgICAgICAgICBsOiB7dmFsOiAwLCBzaXplOiBtbH0sXG4gICAgICAgICAgICByOiB7dmFsOiAxLCBzaXplOiBtcn0sXG4gICAgICAgICAgICB0OiB7dmFsOiAxLCBzaXplOiBtdH0sXG4gICAgICAgICAgICBiOiB7dmFsOiAwLCBzaXplOiBtYn1cbiAgICAgICAgfTtcblxuICAgICAgICAvLyBub3cgY3ljbGUgdGhyb3VnaCBhbGwgdGhlIGNvbWJpbmF0aW9ucyBvZiBsIGFuZCByXG4gICAgICAgIC8vIChhbmQgdCBhbmQgYikgdG8gZmluZCB0aGUgcmVxdWlyZWQgbWFyZ2luc1xuXG4gICAgICAgIGZvcih2YXIgazEgaW4gcHVzaE1hcmdpbikge1xuICAgICAgICAgICAgdmFyIHB1c2hsZWZ0ID0gcHVzaE1hcmdpbltrMV0ubCB8fCB7fTtcbiAgICAgICAgICAgIHZhciBwdXNoYm90dG9tID0gcHVzaE1hcmdpbltrMV0uYiB8fCB7fTtcbiAgICAgICAgICAgIHZhciBmbCA9IHB1c2hsZWZ0LnZhbDtcbiAgICAgICAgICAgIHZhciBwbCA9IHB1c2hsZWZ0LnNpemU7XG4gICAgICAgICAgICB2YXIgZmIgPSBwdXNoYm90dG9tLnZhbDtcbiAgICAgICAgICAgIHZhciBwYiA9IHB1c2hib3R0b20uc2l6ZTtcblxuICAgICAgICAgICAgZm9yKHZhciBrMiBpbiBwdXNoTWFyZ2luKSB7XG4gICAgICAgICAgICAgICAgaWYoaXNOdW1lcmljKHBsKSAmJiBwdXNoTWFyZ2luW2syXS5yKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmciA9IHB1c2hNYXJnaW5bazJdLnIudmFsO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHIgPSBwdXNoTWFyZ2luW2syXS5yLnNpemU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoZnIgPiBmbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0wgPSAocGwgKiBmciArIChwciAtIHdpZHRoKSAqIGZsKSAvIChmciAtIGZsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdSID0gKHByICogKDEgLSBmbCkgKyAocGwgLSB3aWR0aCkgKiAoMSAtIGZyKSkgLyAoZnIgLSBmbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihuZXdMID49IDAgJiYgbmV3UiA+PSAwICYmIHdpZHRoIC0gKG5ld0wgKyBuZXdSKSA+IDAgJiYgbmV3TCArIG5ld1IgPiBtbCArIG1yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWwgPSBuZXdMO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1yID0gbmV3UjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhwYikgJiYgcHVzaE1hcmdpbltrMl0udCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZnQgPSBwdXNoTWFyZ2luW2syXS50LnZhbDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHB0ID0gcHVzaE1hcmdpbltrMl0udC5zaXplO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGZ0ID4gZmIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXdCID0gKHBiICogZnQgKyAocHQgLSBoZWlnaHQpICogZmIpIC8gKGZ0IC0gZmIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1QgPSAocHQgKiAoMSAtIGZiKSArIChwYiAtIGhlaWdodCkgKiAoMSAtIGZ0KSkgLyAoZnQgLSBmYik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihuZXdCID49IDAgJiYgbmV3VCA+PSAwICYmIGhlaWdodCAtIChuZXdUICsgbmV3QikgPiAwICYmIG5ld0IgKyBuZXdUID4gbWIgKyBtdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1iID0gbmV3QjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdCA9IG5ld1Q7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBncy5sID0gTWF0aC5yb3VuZChtbCk7XG4gICAgZ3MuciA9IE1hdGgucm91bmQobXIpO1xuICAgIGdzLnQgPSBNYXRoLnJvdW5kKG10KTtcbiAgICBncy5iID0gTWF0aC5yb3VuZChtYik7XG4gICAgZ3MucCA9IE1hdGgucm91bmQobWFyZ2luLnBhZCk7XG4gICAgZ3MudyA9IE1hdGgucm91bmQod2lkdGgpIC0gZ3MubCAtIGdzLnI7XG4gICAgZ3MuaCA9IE1hdGgucm91bmQoaGVpZ2h0KSAtIGdzLnQgLSBncy5iO1xuXG4gICAgLy8gaWYgdGhpbmdzIGNoYW5nZWQgYW5kIHdlJ3JlIG5vdCBhbHJlYWR5IHJlZHJhd2luZywgdHJpZ2dlciBhIHJlZHJhd1xuICAgIGlmKCFmdWxsTGF5b3V0Ll9yZXBsb3R0aW5nICYmIHBsb3RzLmRpZE1hcmdpbkNoYW5nZShvbGRNYXJnaW5zLCBncykpIHtcbiAgICAgICAgaWYoJ19yZWRyYXdGcm9tQXV0b01hcmdpbkNvdW50JyBpbiBmdWxsTGF5b3V0KSB7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9yZWRyYXdGcm9tQXV0b01hcmdpbkNvdW50Kys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmdWxsTGF5b3V0Ll9yZWRyYXdGcm9tQXV0b01hcmdpbkNvdW50ID0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUmVnaXN0cnkuY2FsbCgncGxvdCcsIGdkKTtcbiAgICB9XG59O1xuXG52YXIgbWFyZ2luS2V5cyA9IFsnbCcsICdyJywgJ3QnLCAnYicsICdwJywgJ3cnLCAnaCddO1xuXG5wbG90cy5kaWRNYXJnaW5DaGFuZ2UgPSBmdW5jdGlvbihtYXJnaW4wLCBtYXJnaW4xKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG1hcmdpbktleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGsgPSBtYXJnaW5LZXlzW2ldO1xuICAgICAgICB2YXIgbTAgPSBtYXJnaW4wW2tdO1xuICAgICAgICB2YXIgbTEgPSBtYXJnaW4xW2tdO1xuICAgICAgICAvLyB1c2UgMXB4IHRvbGVyYW5jZSBpbiBjYXNlIHdlIG9sZC9uZXcgZGlmZmVyIG9ubHlcbiAgICAgICAgLy8gYnkgcm91bmRpbmcgZXJyb3JzLCB3aGljaCBjYW4gbGVhZCB0byBpbmZpbml0ZSBsb29wc1xuICAgICAgICBpZighaXNOdW1lcmljKG0wKSB8fCBNYXRoLmFicyhtMSAtIG0wKSA+IDEpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn07XG5cbi8qKlxuICogSlNPTmlmeSB0aGUgZ3JhcGggZGF0YSBhbmQgbGF5b3V0XG4gKlxuICogVGhpcyBmdW5jdGlvbiBuZWVkcyB0byByZWN1cnNlIGJlY2F1c2Ugc29tZSBzcmMgY2FuIGJlIGluc2lkZVxuICogc3ViLW9iamVjdHMuXG4gKlxuICogSXQgYWxzbyBzdHJpcHMgb3V0IGZ1bmN0aW9ucyBhbmQgcHJpdmF0ZSAoc3RhcnRzIHdpdGggXykgZWxlbWVudHMuXG4gKiBUaGVyZWZvcmUsIHdlIGNhbiBhZGQgdGVtcG9yYXJ5IHRoaW5ncyB0byBkYXRhIGFuZCBsYXlvdXQgdGhhdCBkb24ndFxuICogZ2V0IHNhdmVkLlxuICpcbiAqIEBwYXJhbSBnZCBUaGUgZ3JhcGhEaXZcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gZGF0YW9ubHkgSWYgdHJ1ZSwgZG9uJ3QgcmV0dXJuIGxheW91dC5cbiAqIEBwYXJhbSB7J2tlZXByZWYnfCdrZWVwZGF0YSd8J2tlZXBhbGwnfSBbbW9kZT0na2VlcHJlZiddIEZpbHRlciB3aGF0J3Mga2VwdFxuICogICAgICBrZWVwcmVmOiByZW1vdmUgZGF0YSBmb3Igd2hpY2ggdGhlcmUncyBhIHNyYyBwcmVzZW50XG4gKiAgICAgICAgICBlZyBpZiB0aGVyZSdzIHhzcmMgcHJlc2VudCAoYW5kIHhzcmMgaXMgd2VsbC1mb3JtZWQsXG4gKiAgICAgICAgICBpZSBoYXMgOiBhbmQgc29tZSBjaGFycyBiZWZvcmUgaXQpLCBzdHJpcCBvdXQgeFxuICogICAgICBrZWVwZGF0YTogcmVtb3ZlIGFsbCBzcmMgdGFncywgZG9uJ3QgcmVtb3ZlIHRoZSBkYXRhIGl0c2VsZlxuICogICAgICBrZWVwYWxsOiBrZWVwIGRhdGEgYW5kIHNyY1xuICogQHBhcmFtIHtTdHJpbmd9IG91dHB1dCBJZiB5b3Ugc3BlY2lmeSAnb2JqZWN0JywgdGhlIHJlc3VsdCB3aWxsIG5vdCBiZSBzdHJpbmdpZmllZFxuICogQHBhcmFtIHtCb29sZWFufSB1c2VEZWZhdWx0cyBJZiB0cnV0aHksIHVzZSBfZnVsbExheW91dCBhbmQgX2Z1bGxEYXRhXG4gKiBAcmV0dXJucyB7T2JqZWN0fFN0cmluZ31cbiAqL1xucGxvdHMuZ3JhcGhKc29uID0gZnVuY3Rpb24oZ2QsIGRhdGFvbmx5LCBtb2RlLCBvdXRwdXQsIHVzZURlZmF1bHRzKSB7XG4gICAgLy8gaWYgdGhlIGRlZmF1bHRzIGFyZW4ndCBzdXBwbGllZCB5ZXQsIHdlIG5lZWQgdG8gZG8gdGhhdC4uLlxuICAgIGlmKCh1c2VEZWZhdWx0cyAmJiBkYXRhb25seSAmJiAhZ2QuX2Z1bGxEYXRhKSB8fFxuICAgICAgICAgICAgKHVzZURlZmF1bHRzICYmICFkYXRhb25seSAmJiAhZ2QuX2Z1bGxMYXlvdXQpKSB7XG4gICAgICAgIHBsb3RzLnN1cHBseURlZmF1bHRzKGdkKTtcbiAgICB9XG5cbiAgICB2YXIgZGF0YSA9ICh1c2VEZWZhdWx0cykgPyBnZC5fZnVsbERhdGEgOiBnZC5kYXRhO1xuICAgIHZhciBsYXlvdXQgPSAodXNlRGVmYXVsdHMpID8gZ2QuX2Z1bGxMYXlvdXQgOiBnZC5sYXlvdXQ7XG4gICAgdmFyIGZyYW1lcyA9IChnZC5fdHJhbnNpdGlvbkRhdGEgfHwge30pLl9mcmFtZXM7XG5cbiAgICBmdW5jdGlvbiBzdHJpcE9iaihkKSB7XG4gICAgICAgIGlmKHR5cGVvZiBkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZihMaWIuaXNQbGFpbk9iamVjdChkKSkge1xuICAgICAgICAgICAgdmFyIG8gPSB7fTtcbiAgICAgICAgICAgIHZhciB2LCBzcmM7XG4gICAgICAgICAgICBmb3IodiBpbiBkKSB7XG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIHByaXZhdGUgZWxlbWVudHMgYW5kIGZ1bmN0aW9uc1xuICAgICAgICAgICAgICAgIC8vIF8gaXMgZm9yIHByaXZhdGUsIFsgaXMgYSBtaXN0YWtlIGllIFtvYmplY3QgT2JqZWN0XVxuICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBkW3ZdID09PSAnZnVuY3Rpb24nIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICBbJ18nLCAnWyddLmluZGV4T2Yodi5jaGFyQXQoMCkpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBsb29rIGZvciBzcmMvZGF0YSBtYXRjaGVzIGFuZCByZW1vdmUgdGhlIGFwcHJvcHJpYXRlIG9uZVxuICAgICAgICAgICAgICAgIGlmKG1vZGUgPT09ICdrZWVwZGF0YScpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8ga2VlcGRhdGE6IHJlbW92ZSBhbGwgLi4uc3JjIHRhZ3NcbiAgICAgICAgICAgICAgICAgICAgaWYodi5zdWJzdHIodi5sZW5ndGggLSAzKSA9PT0gJ3NyYycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKG1vZGUgPT09ICdrZWVwc3RyZWFtJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBrZWVwIHNvdXJjZWQgZGF0YSBpZiBpdCdzIGJlaW5nIHN0cmVhbWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBzaW1pbGFyIHRvIGtlZXByZWYsIGJ1dCBpZiB0aGUgJ3N0cmVhbScgb2JqZWN0IGV4aXN0c1xuICAgICAgICAgICAgICAgICAgICAvLyBpbiBhIHRyYWNlLCB3ZSB3aWxsIGtlZXAgdGhlIGRhdGEgYXJyYXkuXG4gICAgICAgICAgICAgICAgICAgIHNyYyA9IGRbdiArICdzcmMnXTtcbiAgICAgICAgICAgICAgICAgICAgaWYodHlwZW9mIHNyYyA9PT0gJ3N0cmluZycgJiYgc3JjLmluZGV4T2YoJzonKSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChkLnN0cmVhbSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihtb2RlICE9PSAna2VlcGFsbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8ga2VlcHJlZjogcmVtb3ZlIHNvdXJjZWQgZGF0YSBidXQgb25seVxuICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgc291cmNlIHRhZyBpcyB3ZWxsLWZvcm1lZFxuICAgICAgICAgICAgICAgICAgICBzcmMgPSBkW3YgKyAnc3JjJ107XG4gICAgICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBzcmMgPT09ICdzdHJpbmcnICYmIHNyYy5pbmRleE9mKCc6JykgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE9LLCB3ZSdyZSBpbmNsdWRpbmcgdGhpcy4uLiByZWN1cnNlIGludG8gaXRcbiAgICAgICAgICAgICAgICBvW3ZdID0gc3RyaXBPYmooZFt2XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBkLm1hcChzdHJpcE9iaik7XG4gICAgICAgIH1cblxuICAgICAgICBpZihMaWIuaXNUeXBlZEFycmF5KGQpKSB7XG4gICAgICAgICAgICByZXR1cm4gTGliLnNpbXBsZU1hcChkLCBMaWIuaWRlbnRpdHkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29udmVydCBuYXRpdmUgZGF0ZXMgdG8gZGF0ZSBzdHJpbmdzLi4uXG4gICAgICAgIC8vIG1vc3RseSBmb3IgZXh0ZXJuYWwgdXNlcnMgZXhwb3J0aW5nIHRvIHBsb3RseVxuICAgICAgICBpZihMaWIuaXNKU0RhdGUoZCkpIHJldHVybiBMaWIubXMyRGF0ZVRpbWVMb2NhbCgrZCk7XG5cbiAgICAgICAgcmV0dXJuIGQ7XG4gICAgfVxuXG4gICAgdmFyIG9iaiA9IHtcbiAgICAgICAgZGF0YTogKGRhdGEgfHwgW10pLm1hcChmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICB2YXIgZCA9IHN0cmlwT2JqKHYpO1xuICAgICAgICAgICAgLy8gZml0IGhhcyBzb21lIGxpdHRsZSBhcnJheXMgaW4gaXQgdGhhdCBkb24ndCBjb250YWluIGRhdGEsXG4gICAgICAgICAgICAvLyBqdXN0IGZpdCBwYXJhbXMgYW5kIG1ldGFcbiAgICAgICAgICAgIGlmKGRhdGFvbmx5KSB7IGRlbGV0ZSBkLmZpdDsgfVxuICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgIH0pXG4gICAgfTtcbiAgICBpZighZGF0YW9ubHkpIHsgb2JqLmxheW91dCA9IHN0cmlwT2JqKGxheW91dCk7IH1cblxuICAgIGlmKGdkLmZyYW1ld29yayAmJiBnZC5mcmFtZXdvcmsuaXNQb2xhcikgb2JqID0gZ2QuZnJhbWV3b3JrLmdldENvbmZpZygpO1xuXG4gICAgaWYoZnJhbWVzKSBvYmouZnJhbWVzID0gc3RyaXBPYmooZnJhbWVzKTtcblxuICAgIHJldHVybiAob3V0cHV0ID09PSAnb2JqZWN0JykgPyBvYmogOiBKU09OLnN0cmluZ2lmeShvYmopO1xufTtcblxuLyoqXG4gKiBNb2RpZnkgYSBrZXlmcmFtZSB1c2luZyBhIGxpc3Qgb2Ygb3BlcmF0aW9uczpcbiAqXG4gKiBAcGFyYW0ge2FycmF5IG9mIG9iamVjdHN9IG9wZXJhdGlvbnNcbiAqICAgICAgU2VxdWVuY2Ugb2Ygb3BlcmF0aW9ucyB0byBiZSBwZXJmb3JtZWQgb24gdGhlIGtleWZyYW1lc1xuICovXG5wbG90cy5tb2RpZnlGcmFtZXMgPSBmdW5jdGlvbihnZCwgb3BlcmF0aW9ucykge1xuICAgIHZhciBpLCBvcCwgZnJhbWU7XG4gICAgdmFyIF9mcmFtZXMgPSBnZC5fdHJhbnNpdGlvbkRhdGEuX2ZyYW1lcztcbiAgICB2YXIgX2ZyYW1lSGFzaCA9IGdkLl90cmFuc2l0aW9uRGF0YS5fZnJhbWVIYXNoO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgb3BlcmF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBvcCA9IG9wZXJhdGlvbnNbaV07XG5cbiAgICAgICAgc3dpdGNoKG9wLnR5cGUpIHtcbiAgICAgICAgICAgIC8vIE5vIHJlYXNvbiB0aGlzIGNvdWxkbid0IGV4aXN0LCBidXQgaXMgY3VycmVudGx5IHVudXNlZC91bnRlc3RlZDpcbiAgICAgICAgICAgIC8qIGNhc2UgJ3JlbmFtZSc6XG4gICAgICAgICAgICAgICAgZnJhbWUgPSBfZnJhbWVzW29wLmluZGV4XTtcbiAgICAgICAgICAgICAgICBkZWxldGUgX2ZyYW1lSGFzaFtmcmFtZS5uYW1lXTtcbiAgICAgICAgICAgICAgICBfZnJhbWVIYXNoW29wLm5hbWVdID0gZnJhbWU7XG4gICAgICAgICAgICAgICAgZnJhbWUubmFtZSA9IG9wLm5hbWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7Ki9cbiAgICAgICAgICAgIGNhc2UgJ3JlcGxhY2UnOlxuICAgICAgICAgICAgICAgIGZyYW1lID0gb3AudmFsdWU7XG4gICAgICAgICAgICAgICAgdmFyIG9sZE5hbWUgPSAoX2ZyYW1lc1tvcC5pbmRleF0gfHwge30pLm5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05hbWUgPSBmcmFtZS5uYW1lO1xuICAgICAgICAgICAgICAgIF9mcmFtZXNbb3AuaW5kZXhdID0gX2ZyYW1lSGFzaFtuZXdOYW1lXSA9IGZyYW1lO1xuXG4gICAgICAgICAgICAgICAgaWYobmV3TmFtZSAhPT0gb2xkTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBuYW1lIGhhcyBjaGFuZ2VkIGluIGFkZGl0aW9uIHRvIHJlcGxhY2VtZW50LCB0aGVuIHVwZGF0ZVxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgbG9va3VwIHRhYmxlOlxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgX2ZyYW1lSGFzaFtvbGROYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgX2ZyYW1lSGFzaFtuZXdOYW1lXSA9IGZyYW1lO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaW5zZXJ0JzpcbiAgICAgICAgICAgICAgICBmcmFtZSA9IG9wLnZhbHVlO1xuICAgICAgICAgICAgICAgIF9mcmFtZUhhc2hbZnJhbWUubmFtZV0gPSBmcmFtZTtcbiAgICAgICAgICAgICAgICBfZnJhbWVzLnNwbGljZShvcC5pbmRleCwgMCwgZnJhbWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZGVsZXRlJzpcbiAgICAgICAgICAgICAgICBmcmFtZSA9IF9mcmFtZXNbb3AuaW5kZXhdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBfZnJhbWVIYXNoW2ZyYW1lLm5hbWVdO1xuICAgICAgICAgICAgICAgIF9mcmFtZXMuc3BsaWNlKG9wLmluZGV4LCAxKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn07XG5cbi8qXG4gKiBDb21wdXRlIGEga2V5ZnJhbWUuIE1lcmdlIGEga2V5ZnJhbWUgaW50byBpdHMgYmFzZSBmcmFtZShzKSBhbmRcbiAqIGV4cGFuZCBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBmcmFtZUxvb2t1cFxuICogICAgICBBbiBvYmplY3QgY29udGFpbmluZyBmcmFtZXMga2V5ZWQgYnkgbmFtZSAoaS5lLiBnZC5fdHJhbnNpdGlvbkRhdGEuX2ZyYW1lSGFzaClcbiAqIEBwYXJhbSB7c3RyaW5nfSBmcmFtZVxuICogICAgICBUaGUgbmFtZSBvZiB0aGUga2V5ZnJhbWUgdG8gYmUgY29tcHV0ZWRcbiAqXG4gKiBSZXR1cm5zOiBhIG5ldyBvYmplY3Qgd2l0aCB0aGUgbWVyZ2VkIGNvbnRlbnRcbiAqL1xucGxvdHMuY29tcHV0ZUZyYW1lID0gZnVuY3Rpb24oZ2QsIGZyYW1lTmFtZSkge1xuICAgIHZhciBmcmFtZUxvb2t1cCA9IGdkLl90cmFuc2l0aW9uRGF0YS5fZnJhbWVIYXNoO1xuICAgIHZhciBpLCB0cmFjZUluZGljZXMsIHRyYWNlSW5kZXgsIGRlc3RJbmRleDtcblxuICAgIC8vIE51bGwgb3IgdW5kZWZpbmVkIHdpbGwgZmFpbCBvbiAudG9TdHJpbmcoKS4gV2UnbGwgYWxsb3cgbnVtYmVycyBzaW5jZSB3ZVxuICAgIC8vIG1ha2UgaXQgY2xlYXIgZnJhbWVzIG11c3QgYmUgZ2l2ZW4gc3RyaW5nIG5hbWVzLCBidXQgd2UnbGwgYWxsb3cgbnVtYmVyc1xuICAgIC8vIGhlcmUgc2luY2UgdGhleSdyZSBvdGhlcndpc2UgZmluZSBmb3IgbG9va2luZyB1cCBmcmFtZXMgYXMgbG9uZyBhcyB0aGV5J3JlXG4gICAgLy8gcHJvcGVybHkgY2FzdCB0byBzdHJpbmdzLiBXZSByZWFsbHkganVzdCB3YW50IHRvIGVuc3VyZSBoZXJlIHRoYXQgdGhpc1xuICAgIC8vIDEpIGRvZXNuJ3QgZmFpbCwgYW5kXG4gICAgLy8gMikgZG9lbnMndCBnaXZlIGFuIGluY29ycmVjdCBhbnN3ZXIgKHdoaWNoIFN0cmluZyhmcmFtZU5hbWUpIHdvdWxkKVxuICAgIGlmKCFmcmFtZU5hbWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb21wdXRlRnJhbWUgbXVzdCBiZSBnaXZlbiBhIHN0cmluZyBmcmFtZSBuYW1lJyk7XG4gICAgfVxuXG4gICAgdmFyIGZyYW1lUHRyID0gZnJhbWVMb29rdXBbZnJhbWVOYW1lLnRvU3RyaW5nKCldO1xuXG4gICAgLy8gUmV0dXJuIGZhbHNlIGlmIHRoZSBuYW1lIGlzIGludmFsaWQ6XG4gICAgaWYoIWZyYW1lUHRyKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgZnJhbWVTdGFjayA9IFtmcmFtZVB0cl07XG4gICAgdmFyIGZyYW1lTmFtZVN0YWNrID0gW2ZyYW1lUHRyLm5hbWVdO1xuXG4gICAgLy8gRm9sbG93IGZyYW1lIHBvaW50ZXJzOlxuICAgIHdoaWxlKGZyYW1lUHRyLmJhc2VmcmFtZSAmJiAoZnJhbWVQdHIgPSBmcmFtZUxvb2t1cFtmcmFtZVB0ci5iYXNlZnJhbWUudG9TdHJpbmcoKV0pKSB7XG4gICAgICAgIC8vIEF2b2lkIGluZmluaXRlIGxvb3BzOlxuICAgICAgICBpZihmcmFtZU5hbWVTdGFjay5pbmRleE9mKGZyYW1lUHRyLm5hbWUpICE9PSAtMSkgYnJlYWs7XG5cbiAgICAgICAgZnJhbWVTdGFjay5wdXNoKGZyYW1lUHRyKTtcbiAgICAgICAgZnJhbWVOYW1lU3RhY2sucHVzaChmcmFtZVB0ci5uYW1lKTtcbiAgICB9XG5cbiAgICAvLyBBIG5ldyBvYmplY3QgZm9yIHRoZSBtZXJnZWQgcmVzdWx0OlxuICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgIC8vIE1lcmdlLCBzdGFydGluZyB3aXRoIHRoZSBsYXN0IGFuZCBlbmRpbmcgd2l0aCB0aGUgZGVzaXJlZCBmcmFtZTpcbiAgICB3aGlsZSgoZnJhbWVQdHIgPSBmcmFtZVN0YWNrLnBvcCgpKSkge1xuICAgICAgICBpZihmcmFtZVB0ci5sYXlvdXQpIHtcbiAgICAgICAgICAgIHJlc3VsdC5sYXlvdXQgPSBwbG90cy5leHRlbmRMYXlvdXQocmVzdWx0LmxheW91dCwgZnJhbWVQdHIubGF5b3V0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGZyYW1lUHRyLmRhdGEpIHtcbiAgICAgICAgICAgIGlmKCFyZXN1bHQuZGF0YSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5kYXRhID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cmFjZUluZGljZXMgPSBmcmFtZVB0ci50cmFjZXM7XG5cbiAgICAgICAgICAgIGlmKCF0cmFjZUluZGljZXMpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBub3QgZGVmaW5lZCwgYXNzdW1lIHNlcmlhbCBvcmRlciBzdGFydGluZyBhdCB6ZXJvXG4gICAgICAgICAgICAgICAgdHJhY2VJbmRpY2VzID0gW107XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgZnJhbWVQdHIuZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB0cmFjZUluZGljZXNbaV0gPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIXJlc3VsdC50cmFjZXMpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQudHJhY2VzID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGZyYW1lUHRyLmRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAvLyBMb29wIHRocm91Z2ggdGhpcyBmcmFtZXMgZGF0YSwgZmluZCBvdXQgd2hlcmUgaXQgc2hvdWxkIGdvLFxuICAgICAgICAgICAgICAgIC8vIGFuZCBtZXJnZSBpdCFcbiAgICAgICAgICAgICAgICB0cmFjZUluZGV4ID0gdHJhY2VJbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlSW5kZXggPT09IHVuZGVmaW5lZCB8fCB0cmFjZUluZGV4ID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3RJbmRleCA9IHJlc3VsdC50cmFjZXMuaW5kZXhPZih0cmFjZUluZGV4KTtcbiAgICAgICAgICAgICAgICBpZihkZXN0SW5kZXggPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3RJbmRleCA9IHJlc3VsdC5kYXRhLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnRyYWNlc1tkZXN0SW5kZXhdID0gdHJhY2VJbmRleDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXN1bHQuZGF0YVtkZXN0SW5kZXhdID0gcGxvdHMuZXh0ZW5kVHJhY2UocmVzdWx0LmRhdGFbZGVzdEluZGV4XSwgZnJhbWVQdHIuZGF0YVtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufTtcblxuLypcbiAqIFJlY29tcHV0ZSB0aGUgbG9va3VwIHRhYmxlIHRoYXQgbWFwcyBmcmFtZSBuYW1lIC0+IGZyYW1lIG9iamVjdC4gYWRkRnJhbWVzL1xuICogZGVsZXRlRnJhbWVzIGFscmVhZHkgbWFuYWdlcyB0aGlzIGRhdGEgb25lIGF0IGEgdGltZSwgc28gdGhlIG9ubHkgdGltZSB0aGlzXG4gKiBpcyBuZWNlc3NhcnkgaXMgaWYgeW91IHBva2UgYXJvdW5kIG1hbnVhbGx5IGluIGBnZC5fdHJhbnNpdGlvbkRhdGEuX2ZyYW1lc2BcbiAqIGFuZCBjcmVhdGUgYW5kIGhhdmVuJ3QgdXBkYXRlZCB0aGUgbG9va3VwIHRhYmxlLlxuICovXG5wbG90cy5yZWNvbXB1dGVGcmFtZUhhc2ggPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBoYXNoID0gZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZUhhc2ggPSB7fTtcbiAgICB2YXIgZnJhbWVzID0gZ2QuX3RyYW5zaXRpb25EYXRhLl9mcmFtZXM7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZyYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZnJhbWUgPSBmcmFtZXNbaV07XG4gICAgICAgIGlmKGZyYW1lICYmIGZyYW1lLm5hbWUpIHtcbiAgICAgICAgICAgIGhhc2hbZnJhbWUubmFtZV0gPSBmcmFtZTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qKlxuICogRXh0ZW5kIGFuIG9iamVjdCwgdHJlYXRpbmcgY29udGFpbmVyIGFycmF5cyB2ZXJ5IGRpZmZlcmVudGx5IGJ5IGV4dHJhY3RpbmdcbiAqIHRoZWlyIGNvbnRlbnRzIGFuZCBtZXJnaW5nIHRoZW0gc2VwYXJhdGVseS5cbiAqXG4gKiBUaGlzIGV4aXN0cyBzbyB0aGF0IHdlIGNhbiBleHRlbmREZWVwTm9BcnJheXMgYW5kIGF2b2lkIHN0ZXBwaW5nIGludG8gZGF0YVxuICogYXJyYXlzIHdpdGhvdXQga25vd2xlZGdlIG9mIHRoZSBwbG90IHNjaGVtYSwgYnV0IHNvIHRoYXQgd2UgbWF5IGFsc28gbWFudWFsbHlcbiAqIHJlY3Vyc2UgaW50byBrbm93biBjb250YWluZXIgYXJyYXlzLCBzdWNoIGFzIHRyYW5zZm9ybXMuXG4gKlxuICogU2VlIGV4dGVuZFRyYWNlIGFuZCBleHRlbmRMYXlvdXQgYmVsb3cgZm9yIHVzYWdlLlxuICovXG5wbG90cy5leHRlbmRPYmplY3RXaXRoQ29udGFpbmVycyA9IGZ1bmN0aW9uKGRlc3QsIHNyYywgY29udGFpbmVyUGF0aHMpIHtcbiAgICB2YXIgY29udGFpbmVyUHJvcCwgY29udGFpbmVyVmFsLCBpLCBqLCBzcmNQcm9wLCBkZXN0UHJvcCwgc3JjQ29udGFpbmVyLCBkZXN0Q29udGFpbmVyO1xuICAgIHZhciBjb3B5ID0gTGliLmV4dGVuZERlZXBOb0FycmF5cyh7fSwgc3JjIHx8IHt9KTtcbiAgICB2YXIgZXhwYW5kZWRPYmogPSBMaWIuZXhwYW5kT2JqZWN0UGF0aHMoY29weSk7XG4gICAgdmFyIGNvbnRhaW5lck9iaiA9IHt9O1xuXG4gICAgLy8gU3RlcCB0aHJvdWdoIGFuZCBleHRyYWN0IGFueSBjb250YWluZXIgcHJvcGVydGllcy4gT3RoZXJ3aXNlIGV4dGVuZERlZXBOb0FycmF5c1xuICAgIC8vIHdpbGwgY2xvYmJlciBhbnkgZXhpc3RpbmcgcHJvcGVydGllcyB3aXRoIGFuIGVtcHR5IGFycmF5IGFuZCB0aGVuIHN1cHBseURlZmF1bHRzXG4gICAgLy8gd2lsbCByZXNldCBldmVyeXRoaW5nIHRvIGRlZmF1bHRzLlxuICAgIGlmKGNvbnRhaW5lclBhdGhzICYmIGNvbnRhaW5lclBhdGhzLmxlbmd0aCkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb250YWluZXJQYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29udGFpbmVyUHJvcCA9IExpYi5uZXN0ZWRQcm9wZXJ0eShleHBhbmRlZE9iaiwgY29udGFpbmVyUGF0aHNbaV0pO1xuICAgICAgICAgICAgY29udGFpbmVyVmFsID0gY29udGFpbmVyUHJvcC5nZXQoKTtcblxuICAgICAgICAgICAgaWYoY29udGFpbmVyVmFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoY29udGFpbmVyT2JqLCBjb250YWluZXJQYXRoc1tpXSkuc2V0KG51bGwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXJQcm9wLnNldChudWxsKTtcbiAgICAgICAgICAgICAgICBMaWIubmVzdGVkUHJvcGVydHkoY29udGFpbmVyT2JqLCBjb250YWluZXJQYXRoc1tpXSkuc2V0KGNvbnRhaW5lclZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBkZXN0ID0gTGliLmV4dGVuZERlZXBOb0FycmF5cyhkZXN0IHx8IHt9LCBleHBhbmRlZE9iaik7XG5cbiAgICBpZihjb250YWluZXJQYXRocyAmJiBjb250YWluZXJQYXRocy5sZW5ndGgpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY29udGFpbmVyUGF0aHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHNyY1Byb3AgPSBMaWIubmVzdGVkUHJvcGVydHkoY29udGFpbmVyT2JqLCBjb250YWluZXJQYXRoc1tpXSk7XG4gICAgICAgICAgICBzcmNDb250YWluZXIgPSBzcmNQcm9wLmdldCgpO1xuXG4gICAgICAgICAgICBpZighc3JjQ29udGFpbmVyKSBjb250aW51ZTtcblxuICAgICAgICAgICAgZGVzdFByb3AgPSBMaWIubmVzdGVkUHJvcGVydHkoZGVzdCwgY29udGFpbmVyUGF0aHNbaV0pO1xuICAgICAgICAgICAgZGVzdENvbnRhaW5lciA9IGRlc3RQcm9wLmdldCgpO1xuXG4gICAgICAgICAgICBpZighQXJyYXkuaXNBcnJheShkZXN0Q29udGFpbmVyKSkge1xuICAgICAgICAgICAgICAgIGRlc3RDb250YWluZXIgPSBbXTtcbiAgICAgICAgICAgICAgICBkZXN0UHJvcC5zZXQoZGVzdENvbnRhaW5lcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHNyY0NvbnRhaW5lci5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBzcmNPYmogPSBzcmNDb250YWluZXJbal07XG5cbiAgICAgICAgICAgICAgICBpZihzcmNPYmogPT09IG51bGwpIGRlc3RDb250YWluZXJbal0gPSBudWxsO1xuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkZXN0Q29udGFpbmVyW2pdID0gcGxvdHMuZXh0ZW5kT2JqZWN0V2l0aENvbnRhaW5lcnMoZGVzdENvbnRhaW5lcltqXSwgc3JjT2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRlc3RQcm9wLnNldChkZXN0Q29udGFpbmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBkZXN0O1xufTtcblxucGxvdHMuZGF0YUFycmF5Q29udGFpbmVycyA9IFsndHJhbnNmb3JtcycsICdkaW1lbnNpb25zJ107XG5wbG90cy5sYXlvdXRBcnJheUNvbnRhaW5lcnMgPSBSZWdpc3RyeS5sYXlvdXRBcnJheUNvbnRhaW5lcnM7XG5cbi8qXG4gKiBFeHRlbmQgYSB0cmFjZSBkZWZpbml0aW9uLiBUaGlzIG1ldGhvZDpcbiAqXG4gKiAgMS4gZGlyZWN0bHkgdHJhbnNmZXJzIGFueSBhcnJheSByZWZlcmVuY2VzXG4gKiAgMi4gbWFudWFsbHkgcmVjdXJzZXMgaW50byBjb250YWluZXIgYXJyYXlzIGxpa2UgdHJhbnNmb3Jtc1xuICpcbiAqIFRoZSByZXN1bHQgaXMgdGhlIG9yaWdpbmFsIG9iamVjdCByZWZlcmVuY2Ugd2l0aCB0aGUgbmV3IGNvbnRlbnRzIG1lcmdlZCBpbi5cbiAqL1xucGxvdHMuZXh0ZW5kVHJhY2UgPSBmdW5jdGlvbihkZXN0VHJhY2UsIHNyY1RyYWNlKSB7XG4gICAgcmV0dXJuIHBsb3RzLmV4dGVuZE9iamVjdFdpdGhDb250YWluZXJzKGRlc3RUcmFjZSwgc3JjVHJhY2UsIHBsb3RzLmRhdGFBcnJheUNvbnRhaW5lcnMpO1xufTtcblxuLypcbiAqIEV4dGVuZCBhIGxheW91dCBkZWZpbml0aW9uLiBUaGlzIG1ldGhvZDpcbiAqXG4gKiAgMS4gZGlyZWN0bHkgdHJhbnNmZXJzIGFueSBhcnJheSByZWZlcmVuY2VzIChub3QgY3JpdGljYWxseSBpbXBvcnRhbnQgZm9yXG4gKiAgICAgbGF5b3V0IHNpbmNlIHRoZXJlIGFyZW4ndCByZWFsbHkgZGF0YSBhcnJheXMpXG4gKiAgMi4gbWFudWFsbHkgcmVjdXJzZXMgaW50byBjb250YWluZXIgYXJyYXlzIGxpa2UgYW5ub3RhdGlvbnNcbiAqXG4gKiBUaGUgcmVzdWx0IGlzIHRoZSBvcmlnaW5hbCBvYmplY3QgcmVmZXJlbmNlIHdpdGggdGhlIG5ldyBjb250ZW50cyBtZXJnZWQgaW4uXG4gKi9cbnBsb3RzLmV4dGVuZExheW91dCA9IGZ1bmN0aW9uKGRlc3RMYXlvdXQsIHNyY0xheW91dCkge1xuICAgIHJldHVybiBwbG90cy5leHRlbmRPYmplY3RXaXRoQ29udGFpbmVycyhkZXN0TGF5b3V0LCBzcmNMYXlvdXQsIHBsb3RzLmxheW91dEFycmF5Q29udGFpbmVycyk7XG59O1xuXG4vKipcbiAqIFRyYW5zaXRpb24gdG8gYSBzZXQgb2YgbmV3IGRhdGEgYW5kIGxheW91dCBwcm9wZXJ0aWVzIGZyb20gUGxvdGx5LmFuaW1hdGVcbiAqXG4gKiBAcGFyYW0ge0RPTSBlbGVtZW50fSBnZFxuICogQHBhcmFtIHtPYmplY3RbXX0gZGF0YVxuICogICAgICBhbiBhcnJheSBvZiBkYXRhIG9iamVjdHMgZm9sbG93aW5nIHRoZSBub3JtYWwgUGxvdGx5IGRhdGEgZGVmaW5pdGlvbiBmb3JtYXRcbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXlvdXRcbiAqICAgICAgYSBsYXlvdXQgb2JqZWN0LCBmb2xsb3dpbmcgbm9ybWFsIFBsb3RseSBsYXlvdXQgZm9ybWF0XG4gKiBAcGFyYW0ge051bWJlcltdfSB0cmFjZXNcbiAqICAgICAgaW5kaWNlcyBvZiB0aGUgY29ycmVzcG9uZGluZyB0cmFjZXMgc3BlY2lmaWVkIGluIGBkYXRhYFxuICogQHBhcmFtIHtPYmplY3R9IGZyYW1lT3B0c1xuICogICAgICBvcHRpb25zIGZvciB0aGUgZnJhbWUgKGkuZS4gd2hldGhlciB0byByZWRyYXcgcG9zdC10cmFuc2l0aW9uKVxuICogQHBhcmFtIHtPYmplY3R9IHRyYW5zaXRpb25PcHRzXG4gKiAgICAgIG9wdGlvbnMgZm9yIHRoZSB0cmFuc2l0aW9uXG4gKi9cbnBsb3RzLnRyYW5zaXRpb24gPSBmdW5jdGlvbihnZCwgZGF0YSwgbGF5b3V0LCB0cmFjZXMsIGZyYW1lT3B0cywgdHJhbnNpdGlvbk9wdHMpIHtcbiAgICB2YXIgb3B0cyA9IHtyZWRyYXc6IGZyYW1lT3B0cy5yZWRyYXd9O1xuICAgIHZhciB0cmFuc2l0aW9uZWRUcmFjZXMgPSB7fTtcbiAgICB2YXIgYXhFZGl0cyA9IFtdO1xuXG4gICAgb3B0cy5wcmVwYXJlRm4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGRhdGFMZW5ndGggPSBBcnJheS5pc0FycmF5KGRhdGEpID8gZGF0YS5sZW5ndGggOiAwO1xuICAgICAgICB2YXIgdHJhY2VJbmRpY2VzID0gdHJhY2VzLnNsaWNlKDAsIGRhdGFMZW5ndGgpO1xuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0cmFjZUluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0cmFjZUlkeCA9IHRyYWNlSW5kaWNlc1tpXTtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IGdkLl9mdWxsRGF0YVt0cmFjZUlkeF07XG4gICAgICAgICAgICB2YXIgX21vZHVsZSA9IHRyYWNlLl9tb2R1bGU7XG5cbiAgICAgICAgICAgIC8vIFRoZXJlJ3Mgbm90aGluZyB0byBkbyBpZiB0aGlzIG1vZHVsZSBpcyBub3QgZGVmaW5lZDpcbiAgICAgICAgICAgIGlmKCFfbW9kdWxlKSBjb250aW51ZTtcblxuICAgICAgICAgICAgLy8gRG9uJ3QgcmVnaXN0ZXIgdGhlIHRyYWNlIGFzIHRyYW5zaXRpb25lZCBpZiBpdCBkb2Vzbid0IGtub3cgd2hhdCB0byBkby5cbiAgICAgICAgICAgIC8vIElmIGl0ICppcyogcmVnaXN0ZXJlZCwgaXQgd2lsbCByZWNlaXZlIGEgY2FsbGJhY2sgdGhhdCBpdCdzIHJlc3BvbnNpYmxlXG4gICAgICAgICAgICAvLyBmb3IgY2FsbGluZyBpbiBvcmRlciB0byByZWdpc3RlciB0aGUgdHJhbnNpdGlvbiBhcyBoYXZpbmcgY29tcGxldGVkLlxuICAgICAgICAgICAgaWYoX21vZHVsZS5hbmltYXRhYmxlKSB7XG4gICAgICAgICAgICAgICAgdmFyIG4gPSBfbW9kdWxlLmJhc2VQbG90TW9kdWxlLm5hbWU7XG4gICAgICAgICAgICAgICAgaWYoIXRyYW5zaXRpb25lZFRyYWNlc1tuXSkgdHJhbnNpdGlvbmVkVHJhY2VzW25dID0gW107XG4gICAgICAgICAgICAgICAgdHJhbnNpdGlvbmVkVHJhY2VzW25dLnB1c2godHJhY2VJZHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBnZC5kYXRhW3RyYWNlSW5kaWNlc1tpXV0gPSBwbG90cy5leHRlbmRUcmFjZShnZC5kYXRhW3RyYWNlSW5kaWNlc1tpXV0sIGRhdGFbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRm9sbG93IHRoZSBzYW1lIHByb2NlZHVyZS4gQ2xvbmUgaXQgc28gd2UgZG9uJ3QgbWFuZ2xlIHRoZSBpbnB1dCwgdGhlblxuICAgICAgICAvLyBleHBhbmQgYW55IG9iamVjdCBwYXRocyBzbyB3ZSBjYW4gbWVyZ2UgZGVlcCBpbnRvIGdkLmxheW91dDpcbiAgICAgICAgdmFyIGxheW91dFVwZGF0ZSA9IExpYi5leHBhbmRPYmplY3RQYXRocyhMaWIuZXh0ZW5kRGVlcE5vQXJyYXlzKHt9LCBsYXlvdXQpKTtcblxuICAgICAgICAvLyBCZWZvcmUgbWVyZ2luZyB0aG91Z2gsIHdlIG5lZWQgdG8gbW9kaWZ5IHRoZSBpbmNvbWluZyBsYXlvdXQuIFdlIG9ubHlcbiAgICAgICAgLy8ga25vdyBob3cgdG8gKnRyYW5zaXRpb24qIGxheW91dCByYW5nZXMsIHNvIGl0J3MgaW1wZXJhdGl2ZSB0aGF0IGEgbmV3XG4gICAgICAgIC8vIHJhbmdlIG5vdCBiZSBzZW50IHRvIHRoZSBsYXlvdXQgYmVmb3JlIHRoZSB0cmFuc2l0aW9uIGhhcyBzdGFydGVkLiBTb1xuICAgICAgICAvLyB3ZSBtdXN0IHJlbW92ZSB0aGUgdGhpbmdzIHdlIGNhbiB0cmFuc2l0aW9uOlxuICAgICAgICB2YXIgYXhpc0F0dHJSZSA9IC9eW3h5XWF4aXNbMC05XSokLztcbiAgICAgICAgZm9yKHZhciBhdHRyIGluIGxheW91dFVwZGF0ZSkge1xuICAgICAgICAgICAgaWYoIWF4aXNBdHRyUmUudGVzdChhdHRyKSkgY29udGludWU7XG4gICAgICAgICAgICBkZWxldGUgbGF5b3V0VXBkYXRlW2F0dHJdLnJhbmdlO1xuICAgICAgICB9XG5cbiAgICAgICAgcGxvdHMuZXh0ZW5kTGF5b3V0KGdkLmxheW91dCwgbGF5b3V0VXBkYXRlKTtcblxuICAgICAgICAvLyBTdXBwbHkgZGVmYXVsdHMgYWZ0ZXIgYXBwbHlpbmcgdGhlIGluY29taW5nIHByb3BlcnRpZXMuIE5vdGUgdGhhdCBhbnkgYXR0ZW1wdFxuICAgICAgICAvLyB0byBzaW1wbGlmeSB0aGlzIHN0ZXAgYW5kIHJlZHVjZSB0aGUgYW1vdW50IG9mIHdvcmsgcmVzdWx0ZWQgaW4gdGhlIHJlY29uc3RydWN0aW9uXG4gICAgICAgIC8vIG9mIGVzc2VudGlhbGx5IHRoZSB3aG9sZSBzdXBwbHlEZWZhdWx0cyBzdGVwLCBzbyB0aGF0IGl0IHNlZW1zIHNlbnNpYmxlIHRvIGp1c3QgdXNlXG4gICAgICAgIC8vIHN1cHBseURlZmF1bHRzIGV2ZW4gdGhvdWdoIGl0J3MgaGVhdmllciB0aGFuIHdvdWxkIG90aGVyd2lzZSBiZSBkZXNpcmVkIGZvclxuICAgICAgICAvLyB0cmFuc2l0aW9uczpcblxuICAgICAgICAvLyBmaXJzdCBkZWxldGUgY2FsY2RhdGEgc28gc3VwcGx5RGVmYXVsdHMga25vd3MgYSBjYWxjIHN0ZXAgaXMgY29taW5nXG4gICAgICAgIGRlbGV0ZSBnZC5jYWxjZGF0YTtcblxuICAgICAgICBwbG90cy5zdXBwbHlEZWZhdWx0cyhnZCk7XG4gICAgICAgIHBsb3RzLmRvQ2FsY2RhdGEoZ2QpO1xuXG4gICAgICAgIHZhciBuZXdMYXlvdXQgPSBMaWIuZXhwYW5kT2JqZWN0UGF0aHMobGF5b3V0KTtcblxuICAgICAgICBpZihuZXdMYXlvdXQpIHtcbiAgICAgICAgICAgIHZhciBzdWJwbG90cyA9IGdkLl9mdWxsTGF5b3V0Ll9wbG90cztcblxuICAgICAgICAgICAgZm9yKHZhciBrIGluIHN1YnBsb3RzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBsb3RpbmZvID0gc3VicGxvdHNba107XG4gICAgICAgICAgICAgICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgICAgICAgICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG4gICAgICAgICAgICAgICAgdmFyIHhyMCA9IHhhLnJhbmdlLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHlyMCA9IHlhLnJhbmdlLnNsaWNlKCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgeHIxO1xuICAgICAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkobmV3TGF5b3V0W3hhLl9uYW1lICsgJy5yYW5nZSddKSkge1xuICAgICAgICAgICAgICAgICAgICB4cjEgPSBuZXdMYXlvdXRbeGEuX25hbWUgKyAnLnJhbmdlJ10uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheSgobmV3TGF5b3V0W3hhLl9uYW1lXSB8fCB7fSkucmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIHhyMSA9IG5ld0xheW91dFt4YS5fbmFtZV0ucmFuZ2Uuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgeXIxO1xuICAgICAgICAgICAgICAgIGlmKEFycmF5LmlzQXJyYXkobmV3TGF5b3V0W3lhLl9uYW1lICsgJy5yYW5nZSddKSkge1xuICAgICAgICAgICAgICAgICAgICB5cjEgPSBuZXdMYXlvdXRbeWEuX25hbWUgKyAnLnJhbmdlJ10uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheSgobmV3TGF5b3V0W3lhLl9uYW1lXSB8fCB7fSkucmFuZ2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIHlyMSA9IG5ld0xheW91dFt5YS5fbmFtZV0ucmFuZ2Uuc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgZWRpdFg7XG4gICAgICAgICAgICAgICAgaWYoeHIwICYmIHhyMSAmJiAoeHIwWzBdICE9PSB4cjFbMF0gfHwgeHIwWzFdICE9PSB4cjFbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGVkaXRYID0ge3hyMDogeHIwLCB4cjE6IHhyMX07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGVkaXRZO1xuICAgICAgICAgICAgICAgIGlmKHlyMCAmJiB5cjEgJiYgKHlyMFswXSAhPT0geXIxWzBdIHx8IHlyMFsxXSAhPT0geXIxWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICBlZGl0WSA9IHt5cjA6IHlyMCwgeXIxOiB5cjF9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKGVkaXRYIHx8IGVkaXRZKSB7XG4gICAgICAgICAgICAgICAgICAgIGF4RWRpdHMucHVzaChMaWIuZXh0ZW5kRmxhdCh7cGxvdGluZm86IHBsb3RpbmZvfSwgZWRpdFgsIGVkaXRZKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH07XG5cbiAgICBvcHRzLnJ1bkZuID0gZnVuY3Rpb24obWFrZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciB0cmFjZVRyYW5zaXRpb25PcHRzO1xuICAgICAgICB2YXIgYmFzZVBsb3RNb2R1bGVzID0gZ2QuX2Z1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcztcbiAgICAgICAgdmFyIGhhc0F4aXNUcmFuc2l0aW9uID0gYXhFZGl0cy5sZW5ndGg7XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIGlmKGxheW91dCkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYoYmFzZVBsb3RNb2R1bGVzW2ldLnRyYW5zaXRpb25BeGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhc2VQbG90TW9kdWxlc1tpXS50cmFuc2l0aW9uQXhlcyhnZCwgYXhFZGl0cywgdHJhbnNpdGlvbk9wdHMsIG1ha2VDYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGVyZSBoYW5kbGUgdGhlIGV4Y2VwdGlvbiB0aGF0IHdlIHJlZnVzZSB0byBhbmltYXRlIHNjYWxlcyBhbmQgYXhlcyBhdCB0aGUgc2FtZVxuICAgICAgICAvLyB0aW1lLiBJbiBvdGhlciB3b3JkcywgaWYgdGhlcmUncyBhbiBheGlzIHRyYW5zaXRpb24sIHRoZW4gc2V0IHRoZSBkYXRhIHRyYW5zaXRpb25cbiAgICAgICAgLy8gdG8gaW5zdGFudGFuZW91cy5cbiAgICAgICAgaWYoaGFzQXhpc1RyYW5zaXRpb24pIHtcbiAgICAgICAgICAgIHRyYWNlVHJhbnNpdGlvbk9wdHMgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgdHJhbnNpdGlvbk9wdHMpO1xuICAgICAgICAgICAgdHJhY2VUcmFuc2l0aW9uT3B0cy5kdXJhdGlvbiA9IDA7XG4gICAgICAgICAgICAvLyBUaGlzIG1lYW5zIGRvIG5vdCB0cmFuc2l0aW9uIGNhcnRlc2lhbiB0cmFjZXMsXG4gICAgICAgICAgICAvLyB0aGlzIGhhcHBlbnMgb24gbGF5b3V0LW9ubHkgKGUuZy4gYXhpcyByYW5nZSkgYW5pbWF0aW9uc1xuICAgICAgICAgICAgZGVsZXRlIHRyYW5zaXRpb25lZFRyYWNlcy5jYXJ0ZXNpYW47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0cmFjZVRyYW5zaXRpb25PcHRzID0gdHJhbnNpdGlvbk9wdHM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBOb3RlIHRoYXQgd2UgcGFzcyBhIGNhbGxiYWNrIHRvICpjcmVhdGUqIHRoZSBjYWxsYmFjayB0aGF0IG11c3QgYmUgaW52b2tlZCBvbiBjb21wbGV0aW9uLlxuICAgICAgICAvLyBUaGlzIGlzIHNpbmNlIG5vdCBhbGwgdHJhY2VzIGtub3cgYWJvdXQgdHJhbnNpdGlvbnMsIHNvIGl0IGdyZWF0bHkgc2ltcGxpZmllcyBtYXR0ZXJzIGlmXG4gICAgICAgIC8vIHRoZSB0cmFjZSBpcyByZXNwb25zaWJsZSBmb3IgY3JlYXRpbmcgYSBjYWxsYmFjaywgaWYgbmVlZGVkLCBhbmQgdGhlbiBleGVjdXRpbmcgaXQgd2hlblxuICAgICAgICAvLyB0aGUgdGltZSBpcyByaWdodC5cbiAgICAgICAgZm9yKHZhciBuIGluIHRyYW5zaXRpb25lZFRyYWNlcykge1xuICAgICAgICAgICAgdmFyIHRyYWNlSW5kaWNlcyA9IHRyYW5zaXRpb25lZFRyYWNlc1tuXTtcbiAgICAgICAgICAgIHZhciBfbW9kdWxlID0gZ2QuX2Z1bGxEYXRhW3RyYWNlSW5kaWNlc1swXV0uX21vZHVsZTtcbiAgICAgICAgICAgIF9tb2R1bGUuYmFzZVBsb3RNb2R1bGUucGxvdChnZCwgdHJhY2VJbmRpY2VzLCB0cmFjZVRyYW5zaXRpb25PcHRzLCBtYWtlQ2FsbGJhY2spO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfdHJhbnNpdGlvbihnZCwgdHJhbnNpdGlvbk9wdHMsIG9wdHMpO1xufTtcblxuLyoqXG4gKiBUcmFuc2l0aW9uIHRvIGEgc2V0IG9mIG5ldyBkYXRhIGFuZCBsYXlvdXQgcHJvcGVydGllcyBmcm9tIFBsb3RseS5yZWFjdFxuICpcbiAqIEBwYXJhbSB7RE9NIGVsZW1lbnR9IGdkXG4gKiBAcGFyYW0ge29iamVjdH0gcmVzdHlsZUZsYWdzXG4gKiAtIGFuaW0geydhbGwnfCdzb21lJ31cbiAqIEBwYXJhbSB7b2JqZWN0fSByZWxheW91dEZsYWdzXG4gKiAtIGFuaW0geydhbGwnfCdzb21lJ31cbiAqIEBwYXJhbSB7b2JqZWN0fSBvbGRGdWxsTGF5b3V0IDogb2xkIChwcmUgUGxvdGx5LnJlYWN0KSBmdWxsTGF5b3V0XG4gKi9cbnBsb3RzLnRyYW5zaXRpb25Gcm9tUmVhY3QgPSBmdW5jdGlvbihnZCwgcmVzdHlsZUZsYWdzLCByZWxheW91dEZsYWdzLCBvbGRGdWxsTGF5b3V0KSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgdHJhbnNpdGlvbk9wdHMgPSBmdWxsTGF5b3V0LnRyYW5zaXRpb247XG4gICAgdmFyIG9wdHMgPSB7fTtcbiAgICB2YXIgYXhFZGl0cyA9IFtdO1xuXG4gICAgb3B0cy5wcmVwYXJlRm4gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHN1YnBsb3RzID0gZnVsbExheW91dC5fcGxvdHM7XG5cbiAgICAgICAgLy8gbm8gbmVlZCB0byByZWRyYXcgYXQgZW5kIG9mIHRyYW5zaXRpb24sXG4gICAgICAgIC8vIGlmIGFsbCBjaGFuZ2VzIGFyZSBhbmltYXRhYmxlXG4gICAgICAgIG9wdHMucmVkcmF3ID0gZmFsc2U7XG4gICAgICAgIGlmKHJlc3R5bGVGbGFncy5hbmltID09PSAnc29tZScpIG9wdHMucmVkcmF3ID0gdHJ1ZTtcbiAgICAgICAgaWYocmVsYXlvdXRGbGFncy5hbmltID09PSAnc29tZScpIG9wdHMucmVkcmF3ID0gdHJ1ZTtcblxuICAgICAgICBmb3IodmFyIGsgaW4gc3VicGxvdHMpIHtcbiAgICAgICAgICAgIHZhciBwbG90aW5mbyA9IHN1YnBsb3RzW2tdO1xuICAgICAgICAgICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgICAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcbiAgICAgICAgICAgIHZhciB4cjAgPSBvbGRGdWxsTGF5b3V0W3hhLl9uYW1lXS5yYW5nZS5zbGljZSgpO1xuICAgICAgICAgICAgdmFyIHlyMCA9IG9sZEZ1bGxMYXlvdXRbeWEuX25hbWVdLnJhbmdlLnNsaWNlKCk7XG4gICAgICAgICAgICB2YXIgeHIxID0geGEucmFuZ2Uuc2xpY2UoKTtcbiAgICAgICAgICAgIHZhciB5cjEgPSB5YS5yYW5nZS5zbGljZSgpO1xuXG4gICAgICAgICAgICB4YS5zZXRTY2FsZSgpO1xuICAgICAgICAgICAgeWEuc2V0U2NhbGUoKTtcblxuICAgICAgICAgICAgdmFyIGVkaXRYO1xuICAgICAgICAgICAgaWYoeHIwWzBdICE9PSB4cjFbMF0gfHwgeHIwWzFdICE9PSB4cjFbMV0pIHtcbiAgICAgICAgICAgICAgICBlZGl0WCA9IHt4cjA6IHhyMCwgeHIxOiB4cjF9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZWRpdFk7XG4gICAgICAgICAgICBpZih5cjBbMF0gIT09IHlyMVswXSB8fCB5cjBbMV0gIT09IHlyMVsxXSkge1xuICAgICAgICAgICAgICAgIGVkaXRZID0ge3lyMDogeXIwLCB5cjE6IHlyMX07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGVkaXRYIHx8IGVkaXRZKSB7XG4gICAgICAgICAgICAgICAgYXhFZGl0cy5wdXNoKExpYi5leHRlbmRGbGF0KHtwbG90aW5mbzogcGxvdGluZm99LCBlZGl0WCwgZWRpdFkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9O1xuXG4gICAgb3B0cy5ydW5GbiA9IGZ1bmN0aW9uKG1ha2VDYWxsYmFjaykge1xuICAgICAgICB2YXIgZnVsbERhdGEgPSBnZC5fZnVsbERhdGE7XG4gICAgICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgIHZhciBiYXNlUGxvdE1vZHVsZXMgPSBmdWxsTGF5b3V0Ll9iYXNlUGxvdE1vZHVsZXM7XG5cbiAgICAgICAgdmFyIGF4aXNUcmFuc2l0aW9uT3B0cztcbiAgICAgICAgdmFyIHRyYWNlVHJhbnNpdGlvbk9wdHM7XG4gICAgICAgIHZhciB0cmFuc2l0aW9uZWRUcmFjZXM7XG5cbiAgICAgICAgdmFyIGFsbFRyYWNlSW5kaWNlcyA9IFtdO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFsbFRyYWNlSW5kaWNlcy5wdXNoKGkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gdHJhbnNpdGlvbkF4ZXMoKSB7XG4gICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYoYmFzZVBsb3RNb2R1bGVzW2pdLnRyYW5zaXRpb25BeGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhc2VQbG90TW9kdWxlc1tqXS50cmFuc2l0aW9uQXhlcyhnZCwgYXhFZGl0cywgYXhpc1RyYW5zaXRpb25PcHRzLCBtYWtlQ2FsbGJhY2spO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHRyYW5zaXRpb25UcmFjZXMoKSB7XG4gICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgYmFzZVBsb3RNb2R1bGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgYmFzZVBsb3RNb2R1bGVzW2pdLnBsb3QoZ2QsIHRyYW5zaXRpb25lZFRyYWNlcywgdHJhY2VUcmFuc2l0aW9uT3B0cywgbWFrZUNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF4RWRpdHMubGVuZ3RoICYmIHJlc3R5bGVGbGFncy5hbmltKSB7XG4gICAgICAgICAgICBpZih0cmFuc2l0aW9uT3B0cy5vcmRlcmluZyA9PT0gJ3RyYWNlcyBmaXJzdCcpIHtcbiAgICAgICAgICAgICAgICBheGlzVHJhbnNpdGlvbk9wdHMgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgdHJhbnNpdGlvbk9wdHMsIHtkdXJhdGlvbjogMH0pO1xuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25lZFRyYWNlcyA9IGFsbFRyYWNlSW5kaWNlcztcbiAgICAgICAgICAgICAgICB0cmFjZVRyYW5zaXRpb25PcHRzID0gdHJhbnNpdGlvbk9wdHM7XG4gICAgICAgICAgICAgICAgdHJhbnNpdGlvblRyYWNlcygpO1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQodHJhbnNpdGlvbkF4ZXMsIHRyYW5zaXRpb25PcHRzLmR1cmF0aW9uKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYXhpc1RyYW5zaXRpb25PcHRzID0gdHJhbnNpdGlvbk9wdHM7XG4gICAgICAgICAgICAgICAgdHJhbnNpdGlvbmVkVHJhY2VzID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0cmFjZVRyYW5zaXRpb25PcHRzID0gTGliLmV4dGVuZEZsYXQoe30sIHRyYW5zaXRpb25PcHRzLCB7ZHVyYXRpb246IDB9KTtcbiAgICAgICAgICAgICAgICB0cmFuc2l0aW9uQXhlcygpO1xuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25UcmFjZXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKGF4RWRpdHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBheGlzVHJhbnNpdGlvbk9wdHMgPSB0cmFuc2l0aW9uT3B0cztcbiAgICAgICAgICAgIHRyYW5zaXRpb25BeGVzKCk7XG4gICAgICAgIH0gZWxzZSBpZihyZXN0eWxlRmxhZ3MuYW5pbSkge1xuICAgICAgICAgICAgdHJhbnNpdGlvbmVkVHJhY2VzID0gYWxsVHJhY2VJbmRpY2VzO1xuICAgICAgICAgICAgdHJhY2VUcmFuc2l0aW9uT3B0cyA9IHRyYW5zaXRpb25PcHRzO1xuICAgICAgICAgICAgdHJhbnNpdGlvblRyYWNlcygpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfdHJhbnNpdGlvbihnZCwgdHJhbnNpdGlvbk9wdHMsIG9wdHMpO1xufTtcblxuLyoqXG4gKiB0cmFjZS9sYXlvdXQgdHJhbnNpdGlvbiB3cmFwcGVyIHRoYXQgd29ya3NcbiAqIGZvciB0cmFuc2l0aW9ucyBpbml0aWF0ZWQgYnkgUGxvdGx5LmFuaW1hdGUgYW5kIFBsb3RseS5yZWFjdC5cbiAqXG4gKiBAcGFyYW0ge0RPTSBlbGVtZW50fSBnZFxuICogQHBhcmFtIHtvYmplY3R9IHRyYW5zaXRpb25PcHRzXG4gKiBAcGFyYW0ge29iamVjdH0gb3B0c1xuICogLSByZWRyYXcge2Jvb2xlYW59XG4gKiAtIHByZXBhcmVGbiB7ZnVuY3Rpb259ICpzaG91bGQgcmV0dXJuIGEgUHJvbWlzZSpcbiAqIC0gcnVuRm4ge2Z1bmN0aW9ufSByYW4gaW5zaWRlIGV4ZWN1dGVUcmFuc2l0aW9uc1xuICovXG5mdW5jdGlvbiBfdHJhbnNpdGlvbihnZCwgdHJhbnNpdGlvbk9wdHMsIG9wdHMpIHtcbiAgICB2YXIgYWJvcnRlZCA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gZXhlY3V0ZUNhbGxiYWNrcyhsaXN0KSB7XG4gICAgICAgIHZhciBwID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIGlmKCFsaXN0KSByZXR1cm4gcDtcbiAgICAgICAgd2hpbGUobGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHAgPSBwLnRoZW4oKGxpc3Quc2hpZnQoKSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZsdXNoQ2FsbGJhY2tzKGxpc3QpIHtcbiAgICAgICAgaWYoIWxpc3QpIHJldHVybjtcbiAgICAgICAgd2hpbGUobGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGxpc3Quc2hpZnQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4ZWN1dGVUcmFuc2l0aW9ucygpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3RyYW5zaXRpb25pbmcnLCBbXSk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgZmxhZyBpcyB1c2VkIHRvIGRpc2FibGVkIHRoaW5ncyBsaWtlIGF1dG9yYW5nZTpcbiAgICAgICAgICAgIGdkLl90cmFuc2l0aW9uaW5nID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gV2hlbiBpbnN0YW50YW5lb3VzIHVwZGF0ZXMgYXJlIGNvbWluZyB0aHJvdWdoIHF1aWNrbHksIGl0J3MgdG9vIG11Y2ggdG8gc2ltcGx5IGRpc2FibGVcbiAgICAgICAgICAgIC8vIGFsbCBpbnRlcmFjdGlvbiwgc28gc3RvcmUgdGhpcyBmbGFnIHNvIHdlIGNhbiBkaXNhbWJpZ3VhdGUgd2hldGhlciBtb3VzZSBpbnRlcmFjdGlvbnNcbiAgICAgICAgICAgIC8vIHNob3VsZCBiZSBmdWxseSBkaXNhYmxlZCBvciBub3Q6XG4gICAgICAgICAgICBpZih0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbiA+IDApIHtcbiAgICAgICAgICAgICAgICBnZC5fdHJhbnNpdGlvbmluZ1dpdGhEdXJhdGlvbiA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElmIGFub3RoZXIgdHJhbnNpdGlvbiBpcyB0cmlnZ2VyZWQsIHRoaXMgY2FsbGJhY2sgd2lsbCBiZSBleGVjdXRlZCBzaW1wbHkgYmVjYXVzZSBpdCdzXG4gICAgICAgICAgICAvLyBpbiB0aGUgaW50ZXJydXB0Q2FsbGJhY2tzIHF1ZXVlLiBJZiB0aGlzIHRyYW5zaXRpb24gY29tcGxldGVzLCBpdCB3aWxsIGluc3RlYWQgZmx1c2hcbiAgICAgICAgICAgIC8vIHRoYXQgcXVldWUgYW5kIGZvcmdldCBhYm91dCB0aGlzIGNhbGxiYWNrLlxuICAgICAgICAgICAgZ2QuX3RyYW5zaXRpb25EYXRhLl9pbnRlcnJ1cHRDYWxsYmFja3MucHVzaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBhYm9ydGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZihvcHRzLnJlZHJhdykge1xuICAgICAgICAgICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzLnB1c2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBSZWdpc3RyeS5jYWxsKCdyZWRyYXcnLCBnZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVtaXQgdGhpcyBhbmQgbWFrZSBzdXJlIGl0IGhhcHBlbnMgbGFzdDpcbiAgICAgICAgICAgIGdkLl90cmFuc2l0aW9uRGF0YS5faW50ZXJydXB0Q2FsbGJhY2tzLnB1c2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3RyYW5zaXRpb25pbnRlcnJ1cHRlZCcsIFtdKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBDb25zdHJ1Y3QgY2FsbGJhY2tzIHRoYXQgYXJlIGV4ZWN1dGVkIG9uIHRyYW5zaXRpb24gZW5kLiBUaGlzIGVuc3VyZXMgdGhlIGQzIHRyYW5zaXRpb25zXG4gICAgICAgICAgICAvLyBhcmUgKmNvbXBsZXRlKiBiZWZvcmUgYW55dGhpbmcgZWxzZSBpcyBkb25lLlxuICAgICAgICAgICAgdmFyIG51bUNhbGxiYWNrcyA9IDA7XG4gICAgICAgICAgICB2YXIgbnVtQ29tcGxldGVkID0gMDtcbiAgICAgICAgICAgIGZ1bmN0aW9uIG1ha2VDYWxsYmFjaygpIHtcbiAgICAgICAgICAgICAgICBudW1DYWxsYmFja3MrKztcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIG51bUNvbXBsZXRlZCsrO1xuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGFsbCBhcmUgY29tcGxldGUsIHBlcmZvcm0gYSByZWRyYXc6XG4gICAgICAgICAgICAgICAgICAgIGlmKCFhYm9ydGVkICYmIG51bUNvbXBsZXRlZCA9PT0gbnVtQ2FsbGJhY2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZVRyYW5zaXRpb24ocmVzb2x2ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBvcHRzLnJ1bkZuKG1ha2VDYWxsYmFjayk7XG5cbiAgICAgICAgICAgIC8vIElmIG5vdGhpbmcgZWxzZSBjcmVhdGVzIGEgY2FsbGJhY2ssIHRoZW4gdGhpcyB3aWxsIHRyaWdnZXIgdGhlIGNvbXBsZXRpb24gaW4gdGhlIG5leHQgdGljazpcbiAgICAgICAgICAgIHNldFRpbWVvdXQobWFrZUNhbGxiYWNrKCkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb21wbGV0ZVRyYW5zaXRpb24oY2FsbGJhY2spIHtcbiAgICAgICAgLy8gVGhpcyBhIHNpbXBsZSB3b3JrYXJvdW5kIGZvciB0ZXN0cyB3aGljaCBwdXJnZSB0aGUgZ3JhcGggYmVmb3JlIGFuaW1hdGlvbnNcbiAgICAgICAgLy8gaGF2ZSBjb21wbGV0ZWQuIFRoYXQncyBub3QgYSB2ZXJ5IGNvbW1vbiBjYXNlLCBzbyB0aGlzIGlzIHRoZSBzaW1wbGVzdFxuICAgICAgICAvLyBmaXguXG4gICAgICAgIGlmKCFnZC5fdHJhbnNpdGlvbkRhdGEpIHJldHVybjtcblxuICAgICAgICBmbHVzaENhbGxiYWNrcyhnZC5fdHJhbnNpdGlvbkRhdGEuX2ludGVycnVwdENhbGxiYWNrcyk7XG5cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZihvcHRzLnJlZHJhdykge1xuICAgICAgICAgICAgICAgIHJldHVybiBSZWdpc3RyeS5jYWxsKCdyZWRyYXcnLCBnZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBTZXQgdHJhbnNpdGlvbmluZyBmYWxzZSBhZ2FpbiBvbmNlIHRoZSByZWRyYXcgaGFzIG9jY3VycmVkLiBUaGlzIGlzIHVzZWQsIGZvciBleGFtcGxlLFxuICAgICAgICAgICAgLy8gdG8gcHJldmVudCB0aGUgdHJhaWxpbmcgcmVkcmF3IGZyb20gYXV0b3Jhbmdpbmc6XG4gICAgICAgICAgICBnZC5fdHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgZ2QuX3RyYW5zaXRpb25pbmdXaXRoRHVyYXRpb24gPSBmYWxzZTtcblxuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3RyYW5zaXRpb25lZCcsIFtdKTtcbiAgICAgICAgfSkudGhlbihjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW50ZXJydXB0UHJldmlvdXNUcmFuc2l0aW9ucygpIHtcbiAgICAgICAgLy8gRmFpbC1zYWZlIGFnYWluc3QgcHVyZ2VkIHBsb3Q6XG4gICAgICAgIGlmKCFnZC5fdHJhbnNpdGlvbkRhdGEpIHJldHVybjtcblxuICAgICAgICAvLyBJZiBhIHRyYW5zaXRpb24gaXMgaW50ZXJydXB0ZWQsIHNldCB0aGlzIHRvIGZhbHNlLiBBdCB0aGUgbW9tZW50LCB0aGUgb25seSB0aGluZyB0aGF0IHdvdWxkXG4gICAgICAgIC8vIGludGVycnVwdCBhIHRyYW5zaXRpb24gaXMgYW5vdGhlciB0cmFuc2l0aW9uLCBzbyB0aGF0IGl0IHdpbGwgbW9tZW50YXJpbHkgYmUgc2V0IHRvIHRydWVcbiAgICAgICAgLy8gYWdhaW4sIGJ1dCB0aGlzIGRldGVybWluZXMgd2hldGhlciBhdXRvcmFuZ2Ugb3IgZHJhZ2JveCB3b3JrLCBzbyBpdCdzIGZvciB0aGUgc2FrZSBvZlxuICAgICAgICAvLyBjbGVhbmxpbmVzczpcbiAgICAgICAgZ2QuX3RyYW5zaXRpb25pbmcgPSBmYWxzZTtcblxuICAgICAgICByZXR1cm4gZXhlY3V0ZUNhbGxiYWNrcyhnZC5fdHJhbnNpdGlvbkRhdGEuX2ludGVycnVwdENhbGxiYWNrcyk7XG4gICAgfVxuXG4gICAgdmFyIHNlcSA9IFtcbiAgICAgICAgcGxvdHMucHJldmlvdXNQcm9taXNlcyxcbiAgICAgICAgaW50ZXJydXB0UHJldmlvdXNUcmFuc2l0aW9ucyxcbiAgICAgICAgb3B0cy5wcmVwYXJlRm4sXG4gICAgICAgIHBsb3RzLnJlaG92ZXIsXG4gICAgICAgIGV4ZWN1dGVUcmFuc2l0aW9uc1xuICAgIF07XG5cbiAgICB2YXIgdHJhbnNpdGlvblN0YXJ0aW5nID0gTGliLnN5bmNPckFzeW5jKHNlcSwgZ2QpO1xuXG4gICAgaWYoIXRyYW5zaXRpb25TdGFydGluZyB8fCAhdHJhbnNpdGlvblN0YXJ0aW5nLnRoZW4pIHtcbiAgICAgICAgdHJhbnNpdGlvblN0YXJ0aW5nID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyYW5zaXRpb25TdGFydGluZy50aGVuKGZ1bmN0aW9uKCkgeyByZXR1cm4gZ2Q7IH0pO1xufVxuXG5wbG90cy5kb0NhbGNkYXRhID0gZnVuY3Rpb24oZ2QsIHRyYWNlcykge1xuICAgIHZhciBheExpc3QgPSBheGlzSURzLmxpc3QoZ2QpO1xuICAgIHZhciBmdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgdmFyIHRyYWNlLCBfbW9kdWxlLCBpLCBqO1xuXG4gICAgLy8gWFhYOiBJcyB0aGlzIGNvcnJlY3Q/IE5lZWRzIGEgY2xvc2VyIGxvb2sgc28gdGhhdCAqc29tZSogdHJhY2VzIGNhbiBiZSByZWNvbXB1dGVkIHdpdGhvdXRcbiAgICAvLyAqYWxsKiBuZWVkaW5nIGRvQ2FsY2RhdGE6XG4gICAgdmFyIGNhbGNkYXRhID0gbmV3IEFycmF5KGZ1bGxEYXRhLmxlbmd0aCk7XG4gICAgdmFyIG9sZENhbGNkYXRhID0gKGdkLmNhbGNkYXRhIHx8IFtdKS5zbGljZSgpO1xuICAgIGdkLmNhbGNkYXRhID0gY2FsY2RhdGE7XG5cbiAgICAvLyBleHRyYSBoZWxwZXIgdmFyaWFibGVzXG5cbiAgICAvLyBob3cgbWFueSBib3gvdmlvbGlucyBwbG90cyBkbyB3ZSBoYXZlIChpbiBjYXNlIHRoZXkncmUgZ3JvdXBlZClcbiAgICBmdWxsTGF5b3V0Ll9udW1Cb3hlcyA9IDA7XG4gICAgZnVsbExheW91dC5fbnVtVmlvbGlucyA9IDA7XG5cbiAgICAvLyBpbml0aWFsaXplIHZpb2xpbiBwZXItc2NhbGUtZ3JvdXAgc3RhdHMgY29udGFpbmVyXG4gICAgZnVsbExheW91dC5fdmlvbGluU2NhbGVHcm91cFN0YXRzID0ge307XG5cbiAgICAvLyBmb3IgY2FsY3VsYXRpbmcgYXZnIGx1bWlub3NpdHkgb2YgaGVhdG1hcHNcbiAgICBnZC5faG1waXhjb3VudCA9IDA7XG4gICAgZ2QuX2htbHVtY291bnQgPSAwO1xuXG4gICAgLy8gZm9yIHNoYXJpbmcgY29sb3JzIGFjcm9zcyBwaWVzIC8gc3VuYnVyc3RzIC8gZnVubmVsYXJlYSAoYW5kIGZvciBsZWdlbmQpXG4gICAgZnVsbExheW91dC5fcGllY29sb3JtYXAgPSB7fTtcbiAgICBmdWxsTGF5b3V0Ll9zdW5idXJzdGNvbG9ybWFwID0ge307XG4gICAgZnVsbExheW91dC5fZnVubmVsYXJlYWNvbG9ybWFwID0ge307XG5cbiAgICAvLyBJZiB0cmFjZXMgd2VyZSBzcGVjaWZpZWQgYW5kIHRoaXMgdHJhY2Ugd2FzIG5vdCBpbmNsdWRlZCxcbiAgICAvLyB0aGVuIHRyYW5zZmVyIGl0IG92ZXIgZnJvbSB0aGUgb2xkIGNhbGNkYXRhOlxuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodHJhY2VzKSAmJiB0cmFjZXMuaW5kZXhPZihpKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIGNhbGNkYXRhW2ldID0gb2xkQ2FsY2RhdGFbaV07XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgdHJhY2UuX2FycmF5QXR0cnMgPSBQbG90U2NoZW1hLmZpbmRBcnJheUF0dHJpYnV0ZXModHJhY2UpO1xuXG4gICAgICAgIC8vIGtlZXAgdHJhY2sgb2YgdHJhY2UgZXh0cmVtZXMgKGZvciBhdXRvcmFuZ2UpIGluIGhlcmVcbiAgICAgICAgdHJhY2UuX2V4dHJlbWVzID0ge307XG4gICAgfVxuXG4gICAgLy8gYWRkIHBvbGFyIGF4ZXMgdG8gYXhpcyBsaXN0XG4gICAgdmFyIHBvbGFySWRzID0gZnVsbExheW91dC5fc3VicGxvdHMucG9sYXIgfHwgW107XG4gICAgZm9yKGkgPSAwOyBpIDwgcG9sYXJJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXhMaXN0LnB1c2goXG4gICAgICAgICAgICBmdWxsTGF5b3V0W3BvbGFySWRzW2ldXS5yYWRpYWxheGlzLFxuICAgICAgICAgICAgZnVsbExheW91dFtwb2xhcklkc1tpXV0uYW5ndWxhcmF4aXNcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICB2YXIgaGFzQ2FsY1RyYW5zZm9ybSA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtQ2FsY2koaSkge1xuICAgICAgICB0cmFjZSA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICBfbW9kdWxlID0gdHJhY2UuX21vZHVsZTtcblxuICAgICAgICBpZih0cmFjZS52aXNpYmxlID09PSB0cnVlICYmIHRyYWNlLnRyYW5zZm9ybXMpIHtcbiAgICAgICAgICAgIC8vIHdlIG5lZWQgb25lIHJvdW5kIG9mIHRyYWNlIG1vZHVsZSBjYWxjIGJlZm9yZVxuICAgICAgICAgICAgLy8gdGhlIGNhbGMgdHJhbnNmb3JtIHRvICdmaWxsIGluJyB0aGUgY2F0ZWdvcmllcyBsaXN0XG4gICAgICAgICAgICAvLyB1c2VkIGZvciBleGFtcGxlIGluIHRoZSBkYXRhLXRvLWNvb3JkaW5hdGUgbWV0aG9kXG4gICAgICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuY2FsYykge1xuICAgICAgICAgICAgICAgIHZhciBjZGkgPSBfbW9kdWxlLmNhbGMoZ2QsIHRyYWNlKTtcblxuICAgICAgICAgICAgICAgIC8vIG11c3QgY2xlYXIgc2NlbmUgJ2JhdGNoZXMnLCBzbyB0aGF0IDJuZFxuICAgICAgICAgICAgICAgIC8vIF9tb2R1bGUuY2FsYyBjYWxsIHN0YXJ0cyBmcm9tIHNjcmF0Y2hcbiAgICAgICAgICAgICAgICBpZihjZGlbMF0gJiYgY2RpWzBdLnQgJiYgY2RpWzBdLnQuX3NjZW5lKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBjZGlbMF0udC5fc2NlbmUuZGlydHk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCB0cmFjZS50cmFuc2Zvcm1zLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHRyYWNlLnRyYW5zZm9ybXNbal07XG5cbiAgICAgICAgICAgICAgICBfbW9kdWxlID0gdHJhbnNmb3Jtc1JlZ2lzdHJ5W3RyYW5zZm9ybS50eXBlXTtcbiAgICAgICAgICAgICAgICBpZihfbW9kdWxlICYmIF9tb2R1bGUuY2FsY1RyYW5zZm9ybSkge1xuICAgICAgICAgICAgICAgICAgICB0cmFjZS5faGFzQ2FsY1RyYW5zZm9ybSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGhhc0NhbGNUcmFuc2Zvcm0gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBfbW9kdWxlLmNhbGNUcmFuc2Zvcm0oZ2QsIHRyYWNlLCB0cmFuc2Zvcm0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNhbGNpKGksIGlzQ29udGFpbmVyKSB7XG4gICAgICAgIHRyYWNlID0gZnVsbERhdGFbaV07XG4gICAgICAgIF9tb2R1bGUgPSB0cmFjZS5fbW9kdWxlO1xuXG4gICAgICAgIGlmKCEhX21vZHVsZS5pc0NvbnRhaW5lciAhPT0gaXNDb250YWluZXIpIHJldHVybjtcblxuICAgICAgICB2YXIgY2QgPSBbXTtcblxuICAgICAgICBpZih0cmFjZS52aXNpYmxlID09PSB0cnVlICYmIHRyYWNlLl9sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgIC8vIGNsZWFyIGV4aXN0aW5nIHJlZiBpbiBjYXNlIGl0IGdvdCByZWxpbmtlZFxuICAgICAgICAgICAgZGVsZXRlIHRyYWNlLl9pbmRleFRvUG9pbnRzO1xuICAgICAgICAgICAgLy8ga2VlcCByZWYgb2YgaW5kZXgtdG8tcG9pbnRzIG1hcCBvYmplY3Qgb2YgdGhlICpsYXN0KiBlbmFibGVkIHRyYW5zZm9ybSxcbiAgICAgICAgICAgIC8vIHRoaXMgaW5kZXgtdG8tcG9pbnRzIG1hcCBvYmplY3QgaXMgcmVxdWlyZWQgdG8gZGV0ZXJtaW5lIHRoZSBjYWxjZGF0YSBpbmRpY2VzXG4gICAgICAgICAgICAvLyB0aGF0IGNvcnJlc3BvbmQgdG8gaW5wdXQgaW5kaWNlcyAoZS5nLiBmcm9tICdzZWxlY3RlZHBvaW50cycpXG4gICAgICAgICAgICB2YXIgdHJhbnNmb3JtcyA9IHRyYWNlLnRyYW5zZm9ybXMgfHwgW107XG4gICAgICAgICAgICBmb3IoaiA9IHRyYW5zZm9ybXMubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgICAgICBpZih0cmFuc2Zvcm1zW2pdLmVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2UuX2luZGV4VG9Qb2ludHMgPSB0cmFuc2Zvcm1zW2pdLl9pbmRleFRvUG9pbnRzO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKF9tb2R1bGUgJiYgX21vZHVsZS5jYWxjKSB7XG4gICAgICAgICAgICAgICAgY2QgPSBfbW9kdWxlLmNhbGMoZ2QsIHRyYWNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1ha2Ugc3VyZSB0aGVyZSBpcyBhIGZpcnN0IHBvaW50LlxuICAgICAgICAvL1xuICAgICAgICAvLyBUaGlzIGVuc3VyZXMgdGhlcmUgaXMgYSBjYWxjZGF0YSBpdGVtIGZvciBldmVyeSB0cmFjZSxcbiAgICAgICAgLy8gZXZlbiBpZiBjYXJ0ZXNpYW4gbG9naWMgZG9lc24ndCBoYW5kbGUgaXQgKGZvciB0aGluZ3MgbGlrZSBsZWdlbmRzKS5cbiAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkoY2QpIHx8ICFjZFswXSkge1xuICAgICAgICAgICAgY2QgPSBbe3g6IEJBRE5VTSwgeTogQkFETlVNfV07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGQgdGhlIHRyYWNlLXdpZGUgcHJvcGVydGllcyB0byB0aGUgZmlyc3QgcG9pbnQsXG4gICAgICAgIC8vIHBlciBwb2ludCBwcm9wZXJ0aWVzIHRvIGV2ZXJ5IHBvaW50XG4gICAgICAgIC8vIHQgaXMgdGhlIGhvbGRlciBmb3IgdHJhY2Utd2lkZSBwcm9wZXJ0aWVzXG4gICAgICAgIGlmKCFjZFswXS50KSBjZFswXS50ID0ge307XG4gICAgICAgIGNkWzBdLnRyYWNlID0gdHJhY2U7XG5cbiAgICAgICAgY2FsY2RhdGFbaV0gPSBjZDtcbiAgICB9XG5cbiAgICBzZXR1cEF4aXNDYXRlZ29yaWVzKGF4TGlzdCwgZnVsbERhdGEpO1xuXG4gICAgLy8gJ3RyYW5zZm9ybScgbG9vcCAtIG11c3QgY2FsYyBjb250YWluZXIgdHJhY2VzIGZpcnN0XG4gICAgLy8gc28gdGhhdCBpZiB0aGVpciBkZXBlbmRlbnQgdHJhY2VzIGNhbiBnZXQgdHJhbnNmb3JtIHByb3Blcmx5XG4gICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIGNhbGNpKGksIHRydWUpO1xuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB0cmFuc2Zvcm1DYWxjaShpKTtcblxuICAgIC8vIGNsZWFyIHN0dWZmIHRoYXQgc2hvdWxkIHJlY29tcHV0ZWQgaW4gJ3JlZ3VsYXInIGxvb3BcbiAgICBpZihoYXNDYWxjVHJhbnNmb3JtKSBzZXR1cEF4aXNDYXRlZ29yaWVzKGF4TGlzdCwgZnVsbERhdGEpO1xuXG4gICAgLy8gJ3JlZ3VsYXInIGxvb3AgLSBtYWtlIHN1cmUgY29udGFpbmVyIHRyYWNlcyAoZWcgY2FycGV0KSBjYWxjIGJlZm9yZVxuICAgIC8vIGNvbnRhaW5lZCB0cmFjZXMgKGVnIGNvbnRvdXJjYXJwZXQpXG4gICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIGNhbGNpKGksIHRydWUpO1xuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSBjYWxjaShpLCBmYWxzZSk7XG5cbiAgICBkb0Nyb3NzVHJhY2VDYWxjKGdkKTtcblxuICAgIC8vIFNvcnQgYXhpcyBjYXRlZ29yaWVzIHBlciB2YWx1ZSBpZiBzcGVjaWZpZWRcbiAgICB2YXIgc29ydGVkID0gc29ydEF4aXNDYXRlZ29yaWVzQnlWYWx1ZShheExpc3QsIGdkKTtcbiAgICBpZihzb3J0ZWQubGVuZ3RoKSB7XG4gICAgICAgIC8vIGhvdyBtYW55IGJveC92aW9saW5zIHBsb3RzIGRvIHdlIGhhdmUgKGluIGNhc2UgdGhleSdyZSBncm91cGVkKVxuICAgICAgICBmdWxsTGF5b3V0Ll9udW1Cb3hlcyA9IDA7XG4gICAgICAgIGZ1bGxMYXlvdXQuX251bVZpb2xpbnMgPSAwO1xuICAgICAgICAvLyBJZiBhIHNvcnQgb3BlcmF0aW9uIHdhcyBwZXJmb3JtZWQsIHJ1biBjYWxjKCkgYWdhaW5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc29ydGVkLmxlbmd0aDsgaSsrKSBjYWxjaShzb3J0ZWRbaV0sIHRydWUpO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBzb3J0ZWQubGVuZ3RoOyBpKyspIGNhbGNpKHNvcnRlZFtpXSwgZmFsc2UpO1xuICAgICAgICBkb0Nyb3NzVHJhY2VDYWxjKGdkKTtcbiAgICB9XG5cbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Z4JywgJ2NhbGMnKShnZCk7XG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnY2FsYycpKGdkKTtcbn07XG5cbnZhciBzb3J0QXhpc0NhdGVnb3JpZXNCeVZhbHVlUmVnZXggPSAvKHRvdGFsfHN1bXxtaW58bWF4fG1lYW58bWVkaWFuKSAoYXNjZW5kaW5nfGRlc2NlbmRpbmcpLztcblxuZnVuY3Rpb24gc29ydEF4aXNDYXRlZ29yaWVzQnlWYWx1ZShheExpc3QsIGdkKSB7XG4gICAgdmFyIGFmZmVjdGVkVHJhY2VzID0gW107XG4gICAgdmFyIGksIGosIGssIGwsIG87XG5cbiAgICBmdW5jdGlvbiB6TWFwQ2F0ZWdvcnkodHlwZSwgYXgsIHZhbHVlKSB7XG4gICAgICAgIHZhciBheExldHRlciA9IGF4Ll9pZC5jaGFyQXQoMCk7XG4gICAgICAgIGlmKHR5cGUgPT09ICdoaXN0b2dyYW0yZGNvbnRvdXInKSB7XG4gICAgICAgICAgICB2YXIgY291bnRlckF4TGV0dGVyID0gYXguX2NvdW50ZXJBeGVzWzBdO1xuICAgICAgICAgICAgdmFyIGNvdW50ZXJBeCA9IGF4aXNJRHMuZ2V0RnJvbUlkKGdkLCBjb3VudGVyQXhMZXR0ZXIpO1xuXG4gICAgICAgICAgICB2YXIgeENhdGVnb3JpY2FsID0gYXhMZXR0ZXIgPT09ICd4JyB8fCAoY291bnRlckF4TGV0dGVyID09PSAneCcgJiYgY291bnRlckF4LnR5cGUgPT09ICdjYXRlZ29yeScpO1xuICAgICAgICAgICAgdmFyIHlDYXRlZ29yaWNhbCA9IGF4TGV0dGVyID09PSAneScgfHwgKGNvdW50ZXJBeExldHRlciA9PT0gJ3knICYmIGNvdW50ZXJBeC50eXBlID09PSAnY2F0ZWdvcnknKTtcblxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG8sIGwpIHtcbiAgICAgICAgICAgICAgICBpZihvID09PSAwIHx8IGwgPT09IDApIHJldHVybiAtMTsgLy8gU2tpcCBmaXJzdCByb3cgYW5kIGNvbHVtblxuICAgICAgICAgICAgICAgIGlmKHhDYXRlZ29yaWNhbCAmJiBvID09PSB2YWx1ZVtsXS5sZW5ndGggLSAxKSByZXR1cm4gLTE7XG4gICAgICAgICAgICAgICAgaWYoeUNhdGVnb3JpY2FsICYmIGwgPT09IHZhbHVlLmxlbmd0aCAtIDEpIHJldHVybiAtMTtcblxuICAgICAgICAgICAgICAgIHJldHVybiAoYXhMZXR0ZXIgPT09ICd5JyA/IGwgOiBvKSAtIDE7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG8sIGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXhMZXR0ZXIgPT09ICd5JyA/IGwgOiBvO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBhZ2dGbiA9IHtcbiAgICAgICAgJ21pbic6IGZ1bmN0aW9uKHZhbHVlcykge3JldHVybiBMaWIuYWdnTnVtcyhNYXRoLm1pbiwgbnVsbCwgdmFsdWVzKTt9LFxuICAgICAgICAnbWF4JzogZnVuY3Rpb24odmFsdWVzKSB7cmV0dXJuIExpYi5hZ2dOdW1zKE1hdGgubWF4LCBudWxsLCB2YWx1ZXMpO30sXG4gICAgICAgICdzdW0nOiBmdW5jdGlvbih2YWx1ZXMpIHtyZXR1cm4gTGliLmFnZ051bXMoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYSArIGI7fSwgbnVsbCwgdmFsdWVzKTt9LFxuICAgICAgICAndG90YWwnOiBmdW5jdGlvbih2YWx1ZXMpIHtyZXR1cm4gTGliLmFnZ051bXMoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYSArIGI7fSwgbnVsbCwgdmFsdWVzKTt9LFxuICAgICAgICAnbWVhbic6IGZ1bmN0aW9uKHZhbHVlcykge3JldHVybiBMaWIubWVhbih2YWx1ZXMpO30sXG4gICAgICAgICdtZWRpYW4nOiBmdW5jdGlvbih2YWx1ZXMpIHtyZXR1cm4gTGliLm1lZGlhbih2YWx1ZXMpO31cbiAgICB9O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYXhMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBheCA9IGF4TGlzdFtpXTtcbiAgICAgICAgaWYoYXgudHlwZSAhPT0gJ2NhdGVnb3J5JykgY29udGludWU7XG5cbiAgICAgICAgLy8gT3JkZXIgYnkgdmFsdWVcbiAgICAgICAgdmFyIG1hdGNoID0gYXguY2F0ZWdvcnlvcmRlci5tYXRjaChzb3J0QXhpc0NhdGVnb3JpZXNCeVZhbHVlUmVnZXgpO1xuICAgICAgICBpZihtYXRjaCkge1xuICAgICAgICAgICAgdmFyIGFnZ3JlZ2F0b3IgPSBtYXRjaFsxXTtcbiAgICAgICAgICAgIHZhciBvcmRlciA9IG1hdGNoWzJdO1xuXG4gICAgICAgICAgICAvLyBTdG9yZSB2YWx1ZXMgYXNzb2NpYXRlZCB3aXRoIGVhY2ggY2F0ZWdvcnlcbiAgICAgICAgICAgIHZhciBjYXRlZ29yaWVzVmFsdWUgPSBbXTtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGF4Ll9jYXRlZ29yaWVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgY2F0ZWdvcmllc1ZhbHVlLnB1c2goW2F4Ll9jYXRlZ29yaWVzW2pdLCBbXV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDb2xsZWN0IHZhbHVlcyBhY3Jvc3MgdHJhY2VzXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBheC5fdHJhY2VJbmRpY2VzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRyYWNlSW5kZXggPSBheC5fdHJhY2VJbmRpY2VzW2pdO1xuICAgICAgICAgICAgICAgIHZhciBmdWxsVHJhY2UgPSBnZC5fZnVsbERhdGFbdHJhY2VJbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGF4TGV0dGVyID0gYXguX2lkLmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgIC8vIFNraXAgb3ZlciBpbnZpc2libGUgdHJhY2VzXG4gICAgICAgICAgICAgICAgaWYoZnVsbFRyYWNlLnZpc2libGUgIT09IHRydWUpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSBmdWxsVHJhY2UudHlwZTtcbiAgICAgICAgICAgICAgICBpZihSZWdpc3RyeS50cmFjZUlzKGZ1bGxUcmFjZSwgJ2hpc3RvZ3JhbScpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBmdWxsVHJhY2UuX3hhdXRvQmluRmluaXNoZWQ7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBmdWxsVHJhY2UuX3lhdXRvQmluRmluaXNoZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNkID0gZ2QuY2FsY2RhdGFbdHJhY2VJbmRleF07XG4gICAgICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgY2QubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNkaSA9IGNkW2tdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2F0LCBjYXRJbmRleCwgdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYodHlwZSA9PT0gJ3NwbG9tJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNwbG9tYCwgY29sbGVjdCB2YWx1ZXMgYWNyb3NzIGRpbWVuc2lvbnNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpbmQgd2hpY2ggZGltZW5zaW9uIHRoZSBjdXJyZW50IGF4aXMgaXMgcmVwcmVzZW50aW5nXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY3VycmVudERpbWVuc2lvbkluZGV4ID0gZnVsbFRyYWNlLl9heGVzRGltW2F4Ll9pZF07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFwcGx5IGxvZ2ljIHRvIGFzc29jaWF0ZWQgeCBheGlzIGlmIGl0J3MgZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoYXhMZXR0ZXIgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhc3NvY2lhdGVkWEF4aXNJRCA9IGZ1bGxUcmFjZS5fZGlhZ1tjdXJyZW50RGltZW5zaW9uSW5kZXhdWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGFzc29jaWF0ZWRYQXhpc0lEKSBheCA9IGdkLl9mdWxsTGF5b3V0W2F4aXNJRHMuaWQybmFtZShhc3NvY2lhdGVkWEF4aXNJRCldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2F0ZWdvcmllcyA9IGNkaS50cmFjZS5kaW1lbnNpb25zW2N1cnJlbnREaW1lbnNpb25JbmRleF0udmFsdWVzO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGwgPSAwOyBsIDwgY2F0ZWdvcmllcy5sZW5ndGg7IGwrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdCA9IGNhdGVnb3JpZXNbbF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0SW5kZXggPSBheC5fY2F0ZWdvcmllc01hcFtjYXRdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29sbGVjdCBhc3NvY2lhdGVkIHZhbHVlcyBhdCBpbmRleCBgbGAgb3ZlciBhbGwgb3RoZXIgZGltZW5zaW9uc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcihvID0gMDsgbyA8IGNkaS50cmFjZS5kaW1lbnNpb25zLmxlbmd0aDsgbysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKG8gPT09IGN1cnJlbnREaW1lbnNpb25JbmRleCkgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkaW1lbnNpb24gPSBjZGkudHJhY2UuZGltZW5zaW9uc1tvXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcmllc1ZhbHVlW2NhdEluZGV4XVsxXS5wdXNoKGRpbWVuc2lvbi52YWx1ZXNbbF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHR5cGUgPT09ICdzY2F0dGVyZ2wnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2NhdHRlcmdsYCwgY29sbGVjdCBhbGwgdmFsdWVzIHN0YXNoZWQgdW5kZXIgY2RpLnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcihsID0gMDsgbCA8IGNkaS50LngubGVuZ3RoOyBsKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihheExldHRlciA9PT0gJ3gnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdCA9IGNkaS50LnhbbF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdEluZGV4ID0gY2F0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGNkaS50LnlbbF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoYXhMZXR0ZXIgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXQgPSBjZGkudC55W2xdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXRJbmRleCA9IGNhdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBjZGkudC54W2xdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXRlZ29yaWVzVmFsdWVbY2F0SW5kZXhdWzFdLnB1c2godmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbXVzdCBjbGVhciBzY2VuZSAnYmF0Y2hlcycsIHNvIHRoYXQgMm5kXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBfbW9kdWxlLmNhbGMgY2FsbCBzdGFydHMgZnJvbSBzY3JhdGNoXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihjZGkudCAmJiBjZGkudC5fc2NlbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgY2RpLnQuX3NjZW5lLmRpcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoY2RpLmhhc093blByb3BlcnR5KCd6JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIDJkTWFwLCBjb2xsZWN0IHZhbHVlcyBpbiBgemBcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gY2RpLno7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWFwcGluZyA9IHpNYXBDYXRlZ29yeShmdWxsVHJhY2UudHlwZSwgYXgsIHZhbHVlKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGwgPSAwOyBsIDwgdmFsdWUubGVuZ3RoOyBsKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IobyA9IDA7IG8gPCB2YWx1ZVtsXS5sZW5ndGg7IG8rKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXRJbmRleCA9IG1hcHBpbmcobywgbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGNhdEluZGV4ICsgMSkgY2F0ZWdvcmllc1ZhbHVlW2NhdEluZGV4XVsxXS5wdXNoKHZhbHVlW2xdW29dKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBGb3IgYWxsIG90aGVyIDJkIGNhcnRlc2lhbiB0cmFjZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGF4TGV0dGVyID09PSAneCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXQgPSBjZGkucCArIDEgPyBjZGkucCA6IGNkaS54O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gY2RpLnMgfHwgY2RpLnYgfHwgY2RpLnk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoYXhMZXR0ZXIgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdCA9IGNkaS5wICsgMSA/IGNkaS5wIDogY2RpLnk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBjZGkucyB8fCBjZGkudiB8fCBjZGkueDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCFBcnJheS5pc0FycmF5KHZhbHVlKSkgdmFsdWUgPSBbdmFsdWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKGwgPSAwOyBsIDwgdmFsdWUubGVuZ3RoOyBsKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXRlZ29yaWVzVmFsdWVbY2F0XVsxXS5wdXNoKHZhbHVlW2xdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXguX2NhdGVnb3JpZXNWYWx1ZSA9IGNhdGVnb3JpZXNWYWx1ZTtcblxuICAgICAgICAgICAgdmFyIGNhdGVnb3JpZXNBZ2dyZWdhdGVkVmFsdWUgPSBbXTtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGNhdGVnb3JpZXNWYWx1ZS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGNhdGVnb3JpZXNBZ2dyZWdhdGVkVmFsdWUucHVzaChbXG4gICAgICAgICAgICAgICAgICAgIGNhdGVnb3JpZXNWYWx1ZVtqXVswXSxcbiAgICAgICAgICAgICAgICAgICAgYWdnRm5bYWdncmVnYXRvcl0oY2F0ZWdvcmllc1ZhbHVlW2pdWzFdKVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTb3J0IGJ5IGFnZ3JlZ2F0ZWQgdmFsdWVcbiAgICAgICAgICAgIGNhdGVnb3JpZXNBZ2dyZWdhdGVkVmFsdWUuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFbMV0gLSBiWzFdO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGF4Ll9jYXRlZ29yaWVzQWdncmVnYXRlZFZhbHVlID0gY2F0ZWdvcmllc0FnZ3JlZ2F0ZWRWYWx1ZTtcblxuICAgICAgICAgICAgLy8gU2V0IG5ldyBjYXRlZ29yeSBvcmRlclxuICAgICAgICAgICAgYXguX2luaXRpYWxDYXRlZ29yaWVzID0gY2F0ZWdvcmllc0FnZ3JlZ2F0ZWRWYWx1ZS5tYXAoZnVuY3Rpb24oYykge1xuICAgICAgICAgICAgICAgIHJldHVybiBjWzBdO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFJldmVyc2UgaWYgZGVzY2VuZGluZ1xuICAgICAgICAgICAgaWYob3JkZXIgPT09ICdkZXNjZW5kaW5nJykge1xuICAgICAgICAgICAgICAgIGF4Ll9pbml0aWFsQ2F0ZWdvcmllcy5yZXZlcnNlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNvcnQgYWxsIG1hdGNoaW5nIGF4ZXNcbiAgICAgICAgICAgIGFmZmVjdGVkVHJhY2VzID0gYWZmZWN0ZWRUcmFjZXMuY29uY2F0KGF4LnNvcnRCeUluaXRpYWxDYXRlZ29yaWVzKCkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhZmZlY3RlZFRyYWNlcztcbn1cblxuZnVuY3Rpb24gc2V0dXBBeGlzQ2F0ZWdvcmllcyhheExpc3QsIGZ1bGxEYXRhKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXggPSBheExpc3RbaV07XG4gICAgICAgIGF4LmNsZWFyQ2FsYygpO1xuICAgICAgICBpZihheC50eXBlID09PSAnbXVsdGljYXRlZ29yeScpIHtcbiAgICAgICAgICAgIGF4LnNldHVwTXVsdGlDYXRlZ29yeShmdWxsRGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRvQ3Jvc3NUcmFjZUNhbGMoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBtb2R1bGVzID0gZnVsbExheW91dC5fdmlzaWJsZU1vZHVsZXM7XG4gICAgdmFyIGhhc2ggPSB7fTtcbiAgICB2YXIgaSwgaiwgaztcblxuICAgIC8vIHBvc2l0aW9uIGFuZCByYW5nZSBjYWxjdWxhdGlvbnMgZm9yIHRyYWNlcyB0aGF0XG4gICAgLy8gZGVwZW5kIG9uIGVhY2ggb3RoZXIgaWUgYmFycyAoc3RhY2tlZCBvciBncm91cGVkKVxuICAgIC8vIGFuZCBib3hlcyAoZ3JvdXBlZCkgcHVzaCBlYWNoIG90aGVyIG91dCBvZiB0aGUgd2F5XG5cbiAgICBmb3IoaiA9IDA7IGogPCBtb2R1bGVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHZhciBfbW9kdWxlID0gbW9kdWxlc1tqXTtcbiAgICAgICAgdmFyIGZuID0gX21vZHVsZS5jcm9zc1RyYWNlQ2FsYztcbiAgICAgICAgaWYoZm4pIHtcbiAgICAgICAgICAgIHZhciBzcFR5cGUgPSBfbW9kdWxlLmJhc2VQbG90TW9kdWxlLm5hbWU7XG4gICAgICAgICAgICBpZihoYXNoW3NwVHlwZV0pIHtcbiAgICAgICAgICAgICAgICBMaWIucHVzaFVuaXF1ZShoYXNoW3NwVHlwZV0sIGZuKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaGFzaFtzcFR5cGVdID0gW2ZuXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihrIGluIGhhc2gpIHtcbiAgICAgICAgdmFyIG1ldGhvZHMgPSBoYXNoW2tdO1xuICAgICAgICB2YXIgc3VicGxvdHMgPSBmdWxsTGF5b3V0Ll9zdWJwbG90c1trXTtcblxuICAgICAgICBpZihBcnJheS5pc0FycmF5KHN1YnBsb3RzKSkge1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgc3VicGxvdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgc3AgPSBzdWJwbG90c1tpXTtcbiAgICAgICAgICAgICAgICB2YXIgc3BJbmZvID0gayA9PT0gJ2NhcnRlc2lhbicgP1xuICAgICAgICAgICAgICAgICAgICBmdWxsTGF5b3V0Ll9wbG90c1tzcF0gOlxuICAgICAgICAgICAgICAgICAgICBmdWxsTGF5b3V0W3NwXTtcblxuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG1ldGhvZHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kc1tqXShnZCwgc3BJbmZvLCBzcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbWV0aG9kcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIG1ldGhvZHNbal0oZ2QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5wbG90cy5yZWhvdmVyID0gZnVuY3Rpb24oZ2QpIHtcbiAgICBpZihnZC5fZnVsbExheW91dC5fcmVob3Zlcikge1xuICAgICAgICBnZC5fZnVsbExheW91dC5fcmVob3ZlcigpO1xuICAgIH1cbn07XG5cbnBsb3RzLnJlZHJhZyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgaWYoZ2QuX2Z1bGxMYXlvdXQuX3JlZHJhZykge1xuICAgICAgICBnZC5fZnVsbExheW91dC5fcmVkcmFnKCk7XG4gICAgfVxufTtcblxucGxvdHMuZ2VuZXJhbFVwZGF0ZVBlclRyYWNlTW9kdWxlID0gZnVuY3Rpb24oZ2QsIHN1YnBsb3QsIHN1YnBsb3RDYWxjRGF0YSwgc3VicGxvdExheW91dCkge1xuICAgIHZhciB0cmFjZUhhc2hPbGQgPSBzdWJwbG90LnRyYWNlSGFzaDtcbiAgICB2YXIgdHJhY2VIYXNoID0ge307XG4gICAgdmFyIGk7XG5cbiAgICAvLyBidWlsZCB1cCBtb2R1bGVOYW1lIC0+IGNhbGNEYXRhIGhhc2hcbiAgICBmb3IoaSA9IDA7IGkgPCBzdWJwbG90Q2FsY0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNUcmFjZXMgPSBzdWJwbG90Q2FsY0RhdGFbaV07XG4gICAgICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZXNbMF0udHJhY2U7XG5cbiAgICAgICAgLy8gc2tpcCBvdmVyIHZpc2libGUgPT09IGZhbHNlIHRyYWNlc1xuICAgICAgICAvLyBhcyB0aGV5IGRvbid0IGhhdmUgYF9tb2R1bGVgIHJlZlxuICAgICAgICBpZih0cmFjZS52aXNpYmxlKSB7XG4gICAgICAgICAgICB0cmFjZUhhc2hbdHJhY2UudHlwZV0gPSB0cmFjZUhhc2hbdHJhY2UudHlwZV0gfHwgW107XG4gICAgICAgICAgICB0cmFjZUhhc2hbdHJhY2UudHlwZV0ucHVzaChjYWxjVHJhY2VzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHdoZW4gYSB0cmFjZSBnZXRzIGRlbGV0ZWQsIG1ha2Ugc3VyZSB0aGF0IGl0cyBtb2R1bGUnc1xuICAgIC8vIHBsb3QgbWV0aG9kIGlzIGNhbGxlZCBzbyB0aGF0IGl0IGlzIHByb3Blcmx5XG4gICAgLy8gcmVtb3ZlZCBmcm9tIHRoZSBET00uXG4gICAgZm9yKHZhciBtb2R1bGVOYW1lT2xkIGluIHRyYWNlSGFzaE9sZCkge1xuICAgICAgICBpZighdHJhY2VIYXNoW21vZHVsZU5hbWVPbGRdKSB7XG4gICAgICAgICAgICB2YXIgZmFrZUNhbGNUcmFjZSA9IHRyYWNlSGFzaE9sZFttb2R1bGVOYW1lT2xkXVswXTtcbiAgICAgICAgICAgIHZhciBmYWtlVHJhY2UgPSBmYWtlQ2FsY1RyYWNlWzBdLnRyYWNlO1xuXG4gICAgICAgICAgICBmYWtlVHJhY2UudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgdHJhY2VIYXNoW21vZHVsZU5hbWVPbGRdID0gW2Zha2VDYWxjVHJhY2VdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gY2FsbCBtb2R1bGUgcGxvdCBtZXRob2RcbiAgICBmb3IodmFyIG1vZHVsZU5hbWUgaW4gdHJhY2VIYXNoKSB7XG4gICAgICAgIHZhciBtb2R1bGVDYWxjRGF0YSA9IHRyYWNlSGFzaFttb2R1bGVOYW1lXTtcbiAgICAgICAgdmFyIF9tb2R1bGUgPSBtb2R1bGVDYWxjRGF0YVswXVswXS50cmFjZS5fbW9kdWxlO1xuXG4gICAgICAgIF9tb2R1bGUucGxvdChnZCwgc3VicGxvdCwgTGliLmZpbHRlclZpc2libGUobW9kdWxlQ2FsY0RhdGEpLCBzdWJwbG90TGF5b3V0KTtcbiAgICB9XG5cbiAgICAvLyB1cGRhdGUgbW9kdWxlTmFtZSAtPiBjYWxjRGF0YSBoYXNoXG4gICAgc3VicGxvdC50cmFjZUhhc2ggPSB0cmFjZUhhc2g7XG59O1xuXG59LHtcIi4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vbGliXCI6NzE5LFwiLi4vcGxvdF9hcGkvcGxvdF9zY2hlbWFcIjo3NTYsXCIuLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2FuaW1hdGlvbl9hdHRyaWJ1dGVzXCI6NzYyLFwiLi9hdHRyaWJ1dGVzXCI6NzY0LFwiLi9jYXJ0ZXNpYW4vYXhpc19pZHNcIjo3NzAsXCIuL2NvbW1hbmRcIjo3OTEsXCIuL2ZvbnRfYXR0cmlidXRlc1wiOjc5MyxcIi4vZnJhbWVfYXR0cmlidXRlc1wiOjc5NCxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo4MTksXCJkM1wiOjE2MyxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sODI5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cjogJ3N1YnBsb3QnLFxuICAgIG5hbWU6ICdwb2xhcicsXG5cbiAgICBheGlzTmFtZXM6IFsnYW5ndWxhcmF4aXMnLCAncmFkaWFsYXhpcyddLFxuICAgIGF4aXNOYW1lMmRhdGFBcnJheToge2FuZ3VsYXJheGlzOiAndGhldGEnLCByYWRpYWxheGlzOiAncid9LFxuXG4gICAgbGF5ZXJOYW1lczogW1xuICAgICAgICAnZHJhZ2xheWVyJyxcbiAgICAgICAgJ3Bsb3RiZycsXG4gICAgICAgICdiYWNrcGxvdCcsXG4gICAgICAgICdhbmd1bGFyLWdyaWQnLFxuICAgICAgICAncmFkaWFsLWdyaWQnLFxuICAgICAgICAnZnJvbnRwbG90JyxcbiAgICAgICAgJ2FuZ3VsYXItbGluZScsXG4gICAgICAgICdyYWRpYWwtbGluZScsXG4gICAgICAgICdhbmd1bGFyLWF4aXMnLFxuICAgICAgICAncmFkaWFsLWF4aXMnXG4gICAgXSxcblxuICAgIHJhZGlhbERyYWdCb3hTaXplOiA1MCxcbiAgICBhbmd1bGFyRHJhZ0JveFNpemU6IDMwLFxuICAgIGNvcm5lckxlbjogMjUsXG4gICAgY29ybmVySGFsZldpZHRoOiAyLFxuXG4gICAgLy8gcGl4ZWxzIHRvIG1vdmUgbW91c2UgYmVmb3JlIHlvdSBzdG9wIGNsYW1waW5nIHRvIHN0YXJ0aW5nIHBvaW50XG4gICAgTUlORFJBRzogOCxcbiAgICAvLyBzbWFsbGVzdCByYWRpYWwgZGlzdGFuY2UgW3B4XSBhbGxvd2VkIGZvciBhIHpvb21ib3hcbiAgICBNSU5aT09NOiAyMCxcbiAgICAvLyBkaXN0YW5jZSBbcHhdIG9mZiAocj0wKSBvciAocj1yYWRpdXMpIHdoZXJlIHdlIHRyYW5zaXRpb25cbiAgICAvLyBmcm9tIHNpbmdsZS1zaWRlZCB0byB0d28tc2lkZWQgcmFkaWFsIHpvb21cbiAgICBPRkZFREdFOiAyMFxufTtcblxufSx7fV0sODMwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHBvbHlnb25UZXN0ZXIgPSBfZGVyZXFfKCcuLi8uLi9saWIvcG9seWdvbicpLnRlc3RlcjtcblxudmFyIGZpbmRJbmRleE9mTWluID0gTGliLmZpbmRJbmRleE9mTWluO1xudmFyIGlzQW5nbGVJbnNpZGVTZWN0b3IgPSBMaWIuaXNBbmdsZUluc2lkZVNlY3RvcjtcbnZhciBhbmdsZURlbHRhID0gTGliLmFuZ2xlRGVsdGE7XG52YXIgYW5nbGVEaXN0ID0gTGliLmFuZ2xlRGlzdDtcblxuLyoqXG4gKiBpcyBwdCAocixhKSBpbnNpZGUgcG9seWdvbiBtYWRlIHVwIHZlcnRpY2VzIGF0IGFuZ2xlcyAndmFuZ2xlcydcbiAqIGluc2lkZSBhIGdpdmVuIHBvbGFyIHNlY3RvclxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSByIDogcHQncyByYWRpYWwgY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IGEgOiBwdCdzIGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7Mi1pdGVtIGFycmF5fSByQm5kcyA6IHNlY3RvcidzIHJhZGlhbCBib3VuZHNcbiAqIEBwYXJhbSB7Mi1pdGVtIGFycmF5fSBhQm5kcyA6IHNlY3RvcidzIGFuZ3VsYXIgYm91bmRzICpyYWRpYW5zKlxuICogQHBhcmFtIHthcnJheX0gdmFuZ2xlcyA6IGFuZ2xlcyBvZiBwb2x5Z29uIHZlcnRpY2VzIGluICpyYWRpYW5zKlxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNQdEluc2lkZVBvbHlnb24ociwgYSwgckJuZHMsIGFCbmRzLCB2YW5nbGVzKSB7XG4gICAgaWYoIWlzQW5nbGVJbnNpZGVTZWN0b3IoYSwgYUJuZHMpKSByZXR1cm4gZmFsc2U7XG5cbiAgICB2YXIgcjAsIHIxO1xuXG4gICAgaWYockJuZHNbMF0gPCByQm5kc1sxXSkge1xuICAgICAgICByMCA9IHJCbmRzWzBdO1xuICAgICAgICByMSA9IHJCbmRzWzFdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHIwID0gckJuZHNbMV07XG4gICAgICAgIHIxID0gckJuZHNbMF07XG4gICAgfVxuXG4gICAgdmFyIHBvbHlnb25JbiA9IHBvbHlnb25UZXN0ZXIobWFrZVBvbHlnb24ocjAsIGFCbmRzWzBdLCBhQm5kc1sxXSwgdmFuZ2xlcykpO1xuICAgIHZhciBwb2x5Z29uT3V0ID0gcG9seWdvblRlc3RlcihtYWtlUG9seWdvbihyMSwgYUJuZHNbMF0sIGFCbmRzWzFdLCB2YW5nbGVzKSk7XG4gICAgdmFyIHh5ID0gW3IgKiBNYXRoLmNvcyhhKSwgciAqIE1hdGguc2luKGEpXTtcbiAgICByZXR1cm4gcG9seWdvbk91dC5jb250YWlucyh4eSkgJiYgIXBvbHlnb25Jbi5jb250YWlucyh4eSk7XG59XG5cbi8vIGZpbmQgaW50ZXJzZWN0aW9uIG9mICd2MCcgPC0+ICd2MScgZWRnZSB3aXRoIGEgcmF5IGF0IGFuZ2xlICdhJ1xuLy8gKGkuZS4gYSBsaW5lIHRoYXQgc3RhcnRzIGZyb20gdGhlIG9yaWdpbiBhdCBhbmdsZSAnYScpXG4vLyBnaXZlbiBhbiAoeHAseXApIHBhaXIgb24gdGhlICd2MCcgPC0+ICd2MScgbGluZVxuLy8gKE4uQi4gJ3YwJyBhbmQgJ3YxJyBhcmUgYW5nbGVzIGluIHJhZGlhbnMpXG5mdW5jdGlvbiBmaW5kSW50ZXJzZWN0aW9uWFkodjAsIHYxLCBhLCB4cHlwKSB7XG4gICAgdmFyIHhzdGFyLCB5c3RhcjtcblxuICAgIHZhciB4cCA9IHhweXBbMF07XG4gICAgdmFyIHlwID0geHB5cFsxXTtcbiAgICB2YXIgZHNpbiA9IGNsYW1wVGlueShNYXRoLnNpbih2MSkgLSBNYXRoLnNpbih2MCkpO1xuICAgIHZhciBkY29zID0gY2xhbXBUaW55KE1hdGguY29zKHYxKSAtIE1hdGguY29zKHYwKSk7XG4gICAgdmFyIHRhbkEgPSBNYXRoLnRhbihhKTtcbiAgICB2YXIgY290YW5BID0gY2xhbXBUaW55KDEgLyB0YW5BKTtcbiAgICB2YXIgbSA9IGRzaW4gLyBkY29zO1xuICAgIHZhciBiID0geXAgLSBtICogeHA7XG5cbiAgICBpZihjb3RhbkEpIHtcbiAgICAgICAgaWYoZHNpbiAmJiBkY29zKSB7XG4gICAgICAgICAgICAvLyBnaXZlblxuICAgICAgICAgICAgLy8gIGcoeCkgOj0gdjAgLT4gdjEgbGluZSA9IG0qeCArIGJcbiAgICAgICAgICAgIC8vICBoKHgpIDo9IHJheSBhdCBhbmdsZSAnYScgPSBtKnggPSB0YW5BKnhcbiAgICAgICAgICAgIC8vIHNvbHZlIGcoeHN0YXIpID0gaCh4c3RhcilcbiAgICAgICAgICAgIHhzdGFyID0gYiAvICh0YW5BIC0gbSk7XG4gICAgICAgICAgICB5c3RhciA9IHRhbkEgKiB4c3RhcjtcbiAgICAgICAgfSBlbHNlIGlmKGRjb3MpIHtcbiAgICAgICAgICAgIC8vIGhvcml6b250YWwgdjAgLT4gdjFcbiAgICAgICAgICAgIHhzdGFyID0geXAgKiBjb3RhbkE7XG4gICAgICAgICAgICB5c3RhciA9IHlwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdmVydGljYWwgdjAgLT4gdjFcbiAgICAgICAgICAgIHhzdGFyID0geHA7XG4gICAgICAgICAgICB5c3RhciA9IHhwICogdGFuQTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHZlcnRpY2FsIHJheVxuICAgICAgICBpZihkc2luICYmIGRjb3MpIHtcbiAgICAgICAgICAgIHhzdGFyID0gMDtcbiAgICAgICAgICAgIHlzdGFyID0gYjtcbiAgICAgICAgfSBlbHNlIGlmKGRjb3MpIHtcbiAgICAgICAgICAgIHhzdGFyID0gMDtcbiAgICAgICAgICAgIHlzdGFyID0geXA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBkb2VzIHRoaXMgY2FzZSBleGlzdHM/XG4gICAgICAgICAgICB4c3RhciA9IHlzdGFyID0gTmFOO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFt4c3RhciwgeXN0YXJdO1xufVxuXG4vLyBzb2x2ZXMgbF4yID0gKGYoeCleMiAtIHlwKV4yICsgKHggLSB4cCleMlxuLy8gcmVhcnJhbmdlZCBpbnRvIDAgPSBhKnheMiArIGIgKiB4ICsgY1xuLy9cbi8vIHdoZXJlIGYoeCkgPSBtKnggKyB0ICsgeXBcbi8vIGFuZCAgICh4MCwgeDEpID0gKC1iICsvLSBkZWwpIC8gKDIqYSlcbmZ1bmN0aW9uIGZpbmRYWWF0TGVuZ3RoKGwsIG0sIHhwLCB5cCkge1xuICAgIHZhciB0ID0gLW0gKiB4cDtcbiAgICB2YXIgYSA9IG0gKiBtICsgMTtcbiAgICB2YXIgYiA9IDIgKiAobSAqIHQgLSB4cCk7XG4gICAgdmFyIGMgPSB0ICogdCArIHhwICogeHAgLSBsICogbDtcbiAgICB2YXIgZGVsID0gTWF0aC5zcXJ0KGIgKiBiIC0gNCAqIGEgKiBjKTtcbiAgICB2YXIgeDAgPSAoLWIgKyBkZWwpIC8gKDIgKiBhKTtcbiAgICB2YXIgeDEgPSAoLWIgLSBkZWwpIC8gKDIgKiBhKTtcbiAgICByZXR1cm4gW1xuICAgICAgICBbeDAsIG0gKiB4MCArIHQgKyB5cF0sXG4gICAgICAgIFt4MSwgbSAqIHgxICsgdCArIHlwXVxuICAgIF07XG59XG5cbmZ1bmN0aW9uIG1ha2VSZWd1bGFyUG9seWdvbihyLCB2YW5nbGVzKSB7XG4gICAgdmFyIGxlbiA9IHZhbmdsZXMubGVuZ3RoO1xuICAgIHZhciB2ZXJ0aWNlcyA9IG5ldyBBcnJheShsZW4gKyAxKTtcbiAgICB2YXIgaTtcbiAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgdmEgPSB2YW5nbGVzW2ldO1xuICAgICAgICB2ZXJ0aWNlc1tpXSA9IFtyICogTWF0aC5jb3ModmEpLCByICogTWF0aC5zaW4odmEpXTtcbiAgICB9XG4gICAgdmVydGljZXNbaV0gPSB2ZXJ0aWNlc1swXS5zbGljZSgpO1xuICAgIHJldHVybiB2ZXJ0aWNlcztcbn1cblxuZnVuY3Rpb24gbWFrZUNsaXBwZWRQb2x5Z29uKHIsIGEwLCBhMSwgdmFuZ2xlcykge1xuICAgIHZhciBsZW4gPSB2YW5nbGVzLmxlbmd0aDtcbiAgICB2YXIgdmVydGljZXMgPSBbXTtcbiAgICB2YXIgaSwgajtcblxuICAgIGZ1bmN0aW9uIGEyeHkoYSkge1xuICAgICAgICByZXR1cm4gW3IgKiBNYXRoLmNvcyhhKSwgciAqIE1hdGguc2luKGEpXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmaW5kWFkodmEwLCB2YTEsIHMpIHtcbiAgICAgICAgcmV0dXJuIGZpbmRJbnRlcnNlY3Rpb25YWSh2YTAsIHZhMSwgcywgYTJ4eSh2YTApKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjeWNsZUluZGV4KGluZCkge1xuICAgICAgICByZXR1cm4gTGliLm1vZChpbmQsIGxlbik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNJbnNpZGUodikge1xuICAgICAgICByZXR1cm4gaXNBbmdsZUluc2lkZVNlY3Rvcih2LCBbYTAsIGExXSk7XG4gICAgfVxuXG4gICAgLy8gZmluZCBpbmRleCBpbiBzZWN0b3IgY2xvc2VzdCB0byBhMFxuICAgIC8vIHVzZSBpdCB0byBmaW5kIGludGVyc2VjdGlvbiBvZiB2W2kwXSA8LT4gdltpMC0xXSBlZGdlIHdpdGggc2VjdG9yIHJhZGl1c1xuICAgIHZhciBpMCA9IGZpbmRJbmRleE9mTWluKHZhbmdsZXMsIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgcmV0dXJuIGlzSW5zaWRlKHYpID8gYW5nbGVEaXN0KHYsIGEwKSA6IEluZmluaXR5O1xuICAgIH0pO1xuICAgIHZhciB4eTAgPSBmaW5kWFkodmFuZ2xlc1tpMF0sIHZhbmdsZXNbY3ljbGVJbmRleChpMCAtIDEpXSwgYTApO1xuICAgIHZlcnRpY2VzLnB1c2goeHkwKTtcblxuICAgIC8vIGZpbGwgaW4gaW4tc2VjdG9yIHZlcnRpY2VzXG4gICAgZm9yKGkgPSBpMCwgaiA9IDA7IGogPCBsZW47IGkrKywgaisrKSB7XG4gICAgICAgIHZhciB2YSA9IHZhbmdsZXNbY3ljbGVJbmRleChpKV07XG4gICAgICAgIGlmKCFpc0luc2lkZSh2YSkpIGJyZWFrO1xuICAgICAgICB2ZXJ0aWNlcy5wdXNoKGEyeHkodmEpKTtcbiAgICB9XG5cbiAgICAvLyBmaW5kIGluZGV4IGluIHNlY3RvciBjbG9zZXN0IHRvIGExLFxuICAgIC8vIHVzZSBpdCB0byBmaW5kIGludGVyc2VjdGlvbiBvZiB2W2lOXSA8LT4gdltpTisxXSBlZGdlIHdpdGggc2VjdG9yIHJhZGl1c1xuICAgIHZhciBpTiA9IGZpbmRJbmRleE9mTWluKHZhbmdsZXMsIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgcmV0dXJuIGlzSW5zaWRlKHYpID8gYW5nbGVEaXN0KHYsIGExKSA6IEluZmluaXR5O1xuICAgIH0pO1xuICAgIHZhciB4eU4gPSBmaW5kWFkodmFuZ2xlc1tpTl0sIHZhbmdsZXNbY3ljbGVJbmRleChpTiArIDEpXSwgYTEpO1xuICAgIHZlcnRpY2VzLnB1c2goeHlOKTtcblxuICAgIHZlcnRpY2VzLnB1c2goWzAsIDBdKTtcbiAgICB2ZXJ0aWNlcy5wdXNoKHZlcnRpY2VzWzBdLnNsaWNlKCkpO1xuXG4gICAgcmV0dXJuIHZlcnRpY2VzO1xufVxuXG5mdW5jdGlvbiBtYWtlUG9seWdvbihyLCBhMCwgYTEsIHZhbmdsZXMpIHtcbiAgICByZXR1cm4gTGliLmlzRnVsbENpcmNsZShbYTAsIGExXSkgP1xuICAgICAgICBtYWtlUmVndWxhclBvbHlnb24ociwgdmFuZ2xlcykgOlxuICAgICAgICBtYWtlQ2xpcHBlZFBvbHlnb24ociwgYTAsIGExLCB2YW5nbGVzKTtcbn1cblxuZnVuY3Rpb24gZmluZFBvbHlnb25PZmZzZXQociwgYTAsIGExLCB2YW5nbGVzKSB7XG4gICAgdmFyIG1pblggPSBJbmZpbml0eTtcbiAgICB2YXIgbWluWSA9IEluZmluaXR5O1xuICAgIHZhciB2ZXJ0aWNlcyA9IG1ha2VQb2x5Z29uKHIsIGEwLCBhMSwgdmFuZ2xlcyk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdmVydGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHYgPSB2ZXJ0aWNlc1tpXTtcbiAgICAgICAgbWluWCA9IE1hdGgubWluKG1pblgsIHZbMF0pO1xuICAgICAgICBtaW5ZID0gTWF0aC5taW4obWluWSwgLXZbMV0pO1xuICAgIH1cbiAgICByZXR1cm4gW21pblgsIG1pblldO1xufVxuXG4vKipcbiAqIGZpbmQgdmVydGV4IGFuZ2xlcyAoaW4gJ3ZhbmdsZXMnKSB0aGUgZW5jbG9zZSBhbmdsZSAnYSdcbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gYSA6IGFuZ2xlIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHthcnJheX0gdmFuZ2xlcyA6IGFuZ2xlcyBvZiBwb2x5Z29uIHZlcnRpY2VzIGluICpyYWRpYW5zKlxuICogQHJldHVybiB7Mi1pdGVtIGFycmF5fVxuICovXG5mdW5jdGlvbiBmaW5kRW5jbG9zaW5nVmVydGV4QW5nbGVzKGEsIHZhbmdsZXMpIHtcbiAgICB2YXIgbWluRm4gPSBmdW5jdGlvbih2KSB7XG4gICAgICAgIHZhciBhZGVsdGEgPSBhbmdsZURlbHRhKHYsIGEpO1xuICAgICAgICByZXR1cm4gYWRlbHRhID4gMCA/IGFkZWx0YSA6IEluZmluaXR5O1xuICAgIH07XG4gICAgdmFyIGkwID0gZmluZEluZGV4T2ZNaW4odmFuZ2xlcywgbWluRm4pO1xuICAgIHZhciBpMSA9IExpYi5tb2QoaTAgKyAxLCB2YW5nbGVzLmxlbmd0aCk7XG4gICAgcmV0dXJuIFt2YW5nbGVzW2kwXSwgdmFuZ2xlc1tpMV1dO1xufVxuXG4vLyB0byBtb3JlIGVhc2lseSBjYXRjaCAnYWxtb3N0IHplcm8nIG51bWJlcnMgaW4gaWYtZWxzZSBibG9ja3NcbmZ1bmN0aW9uIGNsYW1wVGlueSh2KSB7XG4gICAgcmV0dXJuIE1hdGguYWJzKHYpID4gMWUtMTAgPyB2IDogMDtcbn1cblxuZnVuY3Rpb24gdHJhbnNmb3JtRm9yU1ZHKHB0czAsIGN4LCBjeSkge1xuICAgIGN4ID0gY3ggfHwgMDtcbiAgICBjeSA9IGN5IHx8IDA7XG5cbiAgICB2YXIgbGVuID0gcHRzMC5sZW5ndGg7XG4gICAgdmFyIHB0czEgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgcHQgPSBwdHMwW2ldO1xuICAgICAgICBwdHMxW2ldID0gW2N4ICsgcHRbMF0sIGN5IC0gcHRbMV1dO1xuICAgIH1cbiAgICByZXR1cm4gcHRzMTtcbn1cblxuLyoqXG4gKiBwYXRoIHBvbHlnb25cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gciA6IHBvbHlnb24gJ3JhZGl1cydcbiAqIEBwYXJhbSB7bnVtYmVyfSBhMCA6IGZpcnN0IGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7bnVtYmVyfSBhMSA6IHNlY29uZCBhbmd1bGFyIGNvb3JkaW5hdGUgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge2FycmF5fSB2YW5nbGVzIDogYW5nbGVzIG9mIHBvbHlnb24gdmVydGljZXMgaW4gKnJhZGlhbnMqXG4gKiBAcGFyYW0ge251bWJlciAob3B0aW9uYWwpfSBjeCA6IHggY29vcmRpbmF0ZSBvZiBjZW50ZXJcbiAqIEBwYXJhbSB7bnVtYmVyIChvcHRpb25hbCl9IGN5IDogeSBjb29yZGluYXRlIG9mIGNlbnRlclxuICogQHJldHVybiB7c3RyaW5nfSBzdmcgcGF0aFxuICpcbiAqL1xuZnVuY3Rpb24gcGF0aFBvbHlnb24ociwgYTAsIGExLCB2YW5nbGVzLCBjeCwgY3kpIHtcbiAgICB2YXIgcG9seSA9IG1ha2VQb2x5Z29uKHIsIGEwLCBhMSwgdmFuZ2xlcyk7XG4gICAgcmV0dXJuICdNJyArIHRyYW5zZm9ybUZvclNWRyhwb2x5LCBjeCwgY3kpLmpvaW4oJ0wnKTtcbn1cblxuLyoqXG4gKiBwYXRoIGEgcG9seWdvbiAnYW5udWx1cydcbiAqIGkuZS4gYSBwb2x5Z29uIHdpdGggYSBjb25jZW50cmljIGhvbGVcbiAqXG4gKiBOLkIuIHRoaXMgcm91dGluZSB1c2VzIHRoZSBldmVub2RkIFNWRyBydWxlXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHIwIDogZmlyc3QgcmFkaWFsIGNvb3JkaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSByMSA6IHNlY29uZCByYWRpYWwgY29vcmRpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IGEwIDogZmlyc3QgYW5ndWxhciBjb29yZGluYXRlIGluICpyYWRpYW5zKlxuICogQHBhcmFtIHtudW1iZXJ9IGExIDogc2Vjb25kIGFuZ3VsYXIgY29vcmRpbmF0ZSBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7YXJyYXl9IHZhbmdsZXMgOiBhbmdsZXMgb2YgcG9seWdvbiB2ZXJ0aWNlcyBpbiAqcmFkaWFucypcbiAqIEBwYXJhbSB7bnVtYmVyIChvcHRpb25hbCl9IGN4IDogeCBjb29yZGluYXRlIG9mIGNlbnRlclxuICogQHBhcmFtIHtudW1iZXIgKG9wdGlvbmFsKX0gY3kgOiB5IGNvb3JkaW5hdGUgb2YgY2VudGVyXG4gKiBAcmV0dXJuIHtzdHJpbmd9IHN2ZyBwYXRoXG4gKlxuICovXG5mdW5jdGlvbiBwYXRoUG9seWdvbkFubnVsdXMocjAsIHIxLCBhMCwgYTEsIHZhbmdsZXMsIGN4LCBjeSkge1xuICAgIHZhciByU3RhcnQsIHJFbmQ7XG5cbiAgICBpZihyMCA8IHIxKSB7XG4gICAgICAgIHJTdGFydCA9IHIwO1xuICAgICAgICByRW5kID0gcjE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgclN0YXJ0ID0gcjE7XG4gICAgICAgIHJFbmQgPSByMDtcbiAgICB9XG5cbiAgICB2YXIgaW5uZXIgPSB0cmFuc2Zvcm1Gb3JTVkcobWFrZVBvbHlnb24oclN0YXJ0LCBhMCwgYTEsIHZhbmdsZXMpLCBjeCwgY3kpO1xuICAgIHZhciBvdXRlciA9IHRyYW5zZm9ybUZvclNWRyhtYWtlUG9seWdvbihyRW5kLCBhMCwgYTEsIHZhbmdsZXMpLCBjeCwgY3kpO1xuICAgIHJldHVybiAnTScgKyBvdXRlci5yZXZlcnNlKCkuam9pbignTCcpICsgJ00nICsgaW5uZXIuam9pbignTCcpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBpc1B0SW5zaWRlUG9seWdvbjogaXNQdEluc2lkZVBvbHlnb24sXG4gICAgZmluZFBvbHlnb25PZmZzZXQ6IGZpbmRQb2x5Z29uT2Zmc2V0LFxuICAgIGZpbmRFbmNsb3NpbmdWZXJ0ZXhBbmdsZXM6IGZpbmRFbmNsb3NpbmdWZXJ0ZXhBbmdsZXMsXG4gICAgZmluZEludGVyc2VjdGlvblhZOiBmaW5kSW50ZXJzZWN0aW9uWFksXG4gICAgZmluZFhZYXRMZW5ndGg6IGZpbmRYWWF0TGVuZ3RoLFxuICAgIGNsYW1wVGlueTogY2xhbXBUaW55LFxuICAgIHBhdGhQb2x5Z29uOiBwYXRoUG9seWdvbixcbiAgICBwYXRoUG9seWdvbkFubnVsdXM6IHBhdGhQb2x5Z29uQW5udWx1c1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvcG9seWdvblwiOjczMX1dLDgzMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBnZXRTdWJwbG90Q2FsY0RhdGEgPSBfZGVyZXFfKCcuLi9nZXRfZGF0YScpLmdldFN1YnBsb3RDYWxjRGF0YTtcbnZhciBjb3VudGVyUmVnZXggPSBfZGVyZXFfKCcuLi8uLi9saWInKS5jb3VudGVyUmVnZXg7XG5cbnZhciBjcmVhdGVQb2xhciA9IF9kZXJlcV8oJy4vcG9sYXInKTtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xuXG52YXIgYXR0ciA9IGNvbnN0YW50cy5hdHRyO1xudmFyIG5hbWUgPSBjb25zdGFudHMubmFtZTtcbnZhciBjb3VudGVyID0gY291bnRlclJlZ2V4KG5hbWUpO1xuXG52YXIgYXR0cmlidXRlcyA9IHt9O1xuYXR0cmlidXRlc1thdHRyXSA9IHtcbiAgICB2YWxUeXBlOiAnc3VicGxvdGlkJyxcbiAgICBcbiAgICBkZmx0OiBuYW1lLFxuICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgXG59O1xuXG5mdW5jdGlvbiBwbG90KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2FsY0RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgc3VicGxvdElkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW25hbWVdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3RJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGlkID0gc3VicGxvdElkc1tpXTtcbiAgICAgICAgdmFyIHN1YnBsb3RDYWxjRGF0YSA9IGdldFN1YnBsb3RDYWxjRGF0YShjYWxjRGF0YSwgbmFtZSwgaWQpO1xuICAgICAgICB2YXIgc3VicGxvdCA9IGZ1bGxMYXlvdXRbaWRdLl9zdWJwbG90O1xuXG4gICAgICAgIGlmKCFzdWJwbG90KSB7XG4gICAgICAgICAgICBzdWJwbG90ID0gY3JlYXRlUG9sYXIoZ2QsIGlkKTtcbiAgICAgICAgICAgIGZ1bGxMYXlvdXRbaWRdLl9zdWJwbG90ID0gc3VicGxvdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHN1YnBsb3QucGxvdChzdWJwbG90Q2FsY0RhdGEsIGZ1bGxMYXlvdXQsIGdkLl9wcm9taXNlcyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjbGVhbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgb2xkSWRzID0gb2xkRnVsbExheW91dC5fc3VicGxvdHNbbmFtZV0gfHwgW107XG4gICAgdmFyIGhhZEdsID0gKG9sZEZ1bGxMYXlvdXQuX2hhcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXMoJ2dsJykpO1xuICAgIHZhciBoYXNHbCA9IChuZXdGdWxsTGF5b3V0Ll9oYXMgJiYgbmV3RnVsbExheW91dC5faGFzKCdnbCcpKTtcbiAgICB2YXIgbXVzdENsZWFuU2NlbmUgPSBoYWRHbCAmJiAhaGFzR2w7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgb2xkSWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpZCA9IG9sZElkc1tpXTtcbiAgICAgICAgdmFyIG9sZFN1YnBsb3QgPSBvbGRGdWxsTGF5b3V0W2lkXS5fc3VicGxvdDtcblxuICAgICAgICBpZighbmV3RnVsbExheW91dFtpZF0gJiYgISFvbGRTdWJwbG90KSB7XG4gICAgICAgICAgICBvbGRTdWJwbG90LmZyYW1ld29yay5yZW1vdmUoKTtcbiAgICAgICAgICAgIG9sZFN1YnBsb3QubGF5ZXJzWydyYWRpYWwtYXhpcy10aXRsZSddLnJlbW92ZSgpO1xuXG4gICAgICAgICAgICBmb3IodmFyIGsgaW4gb2xkU3VicGxvdC5jbGlwUGF0aHMpIHtcbiAgICAgICAgICAgICAgICBvbGRTdWJwbG90LmNsaXBQYXRoc1trXS5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG11c3RDbGVhblNjZW5lICYmIG9sZFN1YnBsb3QuX3NjZW5lKSB7XG4gICAgICAgICAgICBvbGRTdWJwbG90Ll9zY2VuZS5kZXN0cm95KCk7XG4gICAgICAgICAgICBvbGRTdWJwbG90Ll9zY2VuZSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHI6IGF0dHIsXG4gICAgbmFtZTogbmFtZSxcbiAgICBpZFJvb3Q6IG5hbWUsXG4gICAgaWRSZWdleDogY291bnRlcixcbiAgICBhdHRyUmVnZXg6IGNvdW50ZXIsXG4gICAgYXR0cmlidXRlczogYXR0cmlidXRlcyxcbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2RlZmF1bHRzJyksXG4gICAgcGxvdDogcGxvdCxcbiAgICBjbGVhbjogY2xlYW4sXG4gICAgdG9TVkc6IF9kZXJlcV8oJy4uL2NhcnRlc2lhbicpLnRvU1ZHXG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2NhcnRlc2lhblwiOjc3OCxcIi4uL2dldF9kYXRhXCI6ODAyLFwiLi9jb25zdGFudHNcIjo4MjksXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6ODMyLFwiLi9sYXlvdXRfZGVmYXVsdHNcIjo4MzMsXCIuL3BvbGFyXCI6ODQwfV0sODMyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXMnKTtcbnZhciBheGVzQXR0cnMgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBkb21haW5BdHRycyA9IF9kZXJlcV8oJy4uL2RvbWFpbicpLmF0dHJpYnV0ZXM7XG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbnZhciBheGlzTGluZUdyaWRBdHRyID0gb3ZlcnJpZGVBbGwoe1xuICAgIGNvbG9yOiBheGVzQXR0cnMuY29sb3IsXG4gICAgc2hvd2xpbmU6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy5zaG93bGluZSwge2RmbHQ6IHRydWV9KSxcbiAgICBsaW5lY29sb3I6IGF4ZXNBdHRycy5saW5lY29sb3IsXG4gICAgbGluZXdpZHRoOiBheGVzQXR0cnMubGluZXdpZHRoLFxuICAgIHNob3dncmlkOiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMuc2hvd2dyaWQsIHtkZmx0OiB0cnVlfSksXG4gICAgZ3JpZGNvbG9yOiBheGVzQXR0cnMuZ3JpZGNvbG9yLFxuICAgIGdyaWR3aWR0aDogYXhlc0F0dHJzLmdyaWR3aWR0aFxuXG4gICAgLy8gVE9ETyBhZGQgc3Bpa2UqIGF0dHJpYnV0ZXMgZG93biB0aGUgcm9hZFxuXG4gICAgLy8gc2hvdWxkIHdlIGFkZCB6ZXJvbGluZSogYXR0cmlidXRlcz9cblxufSwgJ3Bsb3QnLCAnZnJvbS1yb290Jyk7XG5cbnZhciBheGlzVGlja0F0dHJzID0gb3ZlcnJpZGVBbGwoe1xuICAgIHRpY2ttb2RlOiBheGVzQXR0cnMudGlja21vZGUsXG4gICAgbnRpY2tzOiBheGVzQXR0cnMubnRpY2tzLFxuICAgIHRpY2swOiBheGVzQXR0cnMudGljazAsXG4gICAgZHRpY2s6IGF4ZXNBdHRycy5kdGljayxcbiAgICB0aWNrdmFsczogYXhlc0F0dHJzLnRpY2t2YWxzLFxuICAgIHRpY2t0ZXh0OiBheGVzQXR0cnMudGlja3RleHQsXG4gICAgdGlja3M6IGF4ZXNBdHRycy50aWNrcyxcbiAgICB0aWNrbGVuOiBheGVzQXR0cnMudGlja2xlbixcbiAgICB0aWNrd2lkdGg6IGF4ZXNBdHRycy50aWNrd2lkdGgsXG4gICAgdGlja2NvbG9yOiBheGVzQXR0cnMudGlja2NvbG9yLFxuICAgIHNob3d0aWNrbGFiZWxzOiBheGVzQXR0cnMuc2hvd3RpY2tsYWJlbHMsXG4gICAgc2hvd3RpY2twcmVmaXg6IGF4ZXNBdHRycy5zaG93dGlja3ByZWZpeCxcbiAgICB0aWNrcHJlZml4OiBheGVzQXR0cnMudGlja3ByZWZpeCxcbiAgICBzaG93dGlja3N1ZmZpeDogYXhlc0F0dHJzLnNob3d0aWNrc3VmZml4LFxuICAgIHRpY2tzdWZmaXg6IGF4ZXNBdHRycy50aWNrc3VmZml4LFxuICAgIHNob3dleHBvbmVudDogYXhlc0F0dHJzLnNob3dleHBvbmVudCxcbiAgICBleHBvbmVudGZvcm1hdDogYXhlc0F0dHJzLmV4cG9uZW50Zm9ybWF0LFxuICAgIHNlcGFyYXRldGhvdXNhbmRzOiBheGVzQXR0cnMuc2VwYXJhdGV0aG91c2FuZHMsXG4gICAgdGlja2ZvbnQ6IGF4ZXNBdHRycy50aWNrZm9udCxcbiAgICB0aWNrYW5nbGU6IGF4ZXNBdHRycy50aWNrYW5nbGUsXG4gICAgdGlja2Zvcm1hdDogYXhlc0F0dHJzLnRpY2tmb3JtYXQsXG4gICAgdGlja2Zvcm1hdHN0b3BzOiBheGVzQXR0cnMudGlja2Zvcm1hdHN0b3BzLFxuICAgIGxheWVyOiBheGVzQXR0cnMubGF5ZXJcbn0sICdwbG90JywgJ2Zyb20tcm9vdCcpO1xuXG52YXIgcmFkaWFsQXhpc0F0dHJzID0ge1xuICAgIHZpc2libGU6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy52aXNpYmxlLCB7ZGZsdDogdHJ1ZX0pLFxuICAgIHR5cGU6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy50eXBlLCB7XG4gICAgICAgIHZhbHVlczogWyctJywgJ2xpbmVhcicsICdsb2cnLCAnZGF0ZScsICdjYXRlZ29yeSddXG4gICAgfSksXG5cbiAgICBhdXRvcmFuZ2U6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy5hdXRvcmFuZ2UsIHtlZGl0VHlwZTogJ3Bsb3QnfSksXG4gICAgcmFuZ2Vtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3RvemVybycsICdub25uZWdhdGl2ZScsICdub3JtYWwnXSxcbiAgICAgICAgZGZsdDogJ3RvemVybycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHJhbmdlOiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMucmFuZ2UsIHtcbiAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdwbG90JywgaW1wbGllZEVkaXRzOiB7J15hdXRvcmFuZ2UnOiBmYWxzZX19LFxuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ3Bsb3QnLCBpbXBsaWVkRWRpdHM6IHsnXmF1dG9yYW5nZSc6IGZhbHNlfX1cbiAgICAgICAgXSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgIH0pLFxuXG4gICAgY2F0ZWdvcnlvcmRlcjogYXhlc0F0dHJzLmNhdGVnb3J5b3JkZXIsXG4gICAgY2F0ZWdvcnlhcnJheTogYXhlc0F0dHJzLmNhdGVnb3J5YXJyYXksXG5cbiAgICBhbmdsZToge1xuICAgICAgICB2YWxUeXBlOiAnYW5nbGUnLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHNpZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAvLyBUT0RPIGFkZCAnY2VudGVyJyBmb3IgYHNob3dsaW5lOiBmYWxzZWAgcmFkaWFsIGF4ZXNcbiAgICAgICAgdmFsdWVzOiBbJ2Nsb2Nrd2lzZScsICdjb3VudGVyY2xvY2t3aXNlJ10sXG4gICAgICAgIGRmbHQ6ICdjbG9ja3dpc2UnLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuXG4gICAgdGl0bGU6IG92ZXJyaWRlQWxsKGF4ZXNBdHRycy50aXRsZSwgJ3Bsb3QnLCAnZnJvbS1yb290JyksXG4gICAgLy8gbWlnaHQgbmVlZCBhICd0aXRsZXNpZGUnIGFuZCBldmVuICd0aXRsZWRpcmVjdGlvbicgZG93biB0aGUgcm9hZFxuXG4gICAgaG92ZXJmb3JtYXQ6IGF4ZXNBdHRycy5ob3ZlcmZvcm1hdCxcblxuICAgIHVpcmV2aXNpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcblxuICAgIF9kZXByZWNhdGVkOiB7XG4gICAgICAgIHRpdGxlOiBheGVzQXR0cnMuX2RlcHJlY2F0ZWQudGl0bGUsXG4gICAgICAgIHRpdGxlZm9udDogYXhlc0F0dHJzLl9kZXByZWNhdGVkLnRpdGxlZm9udFxuICAgIH1cbn07XG5cbi8vIHJhZGlhbCB0aXRsZSBpcyBub3QgZ3VpLWVkaXRhYmxlLCBzbyBpdCBuZWVkcyBkZmx0OiAnJywgc2ltaWxhciB0byBjYXJwZXQgYXhlcy5cbnJhZGlhbEF4aXNBdHRycy50aXRsZS50ZXh0LmRmbHQgPSAnJztcblxuZXh0ZW5kRmxhdChcbiAgICByYWRpYWxBeGlzQXR0cnMsXG5cbiAgICAvLyBOLkIuIHJhZGlhbGF4aXMgZ3JpZCBsaW5lcyBhcmUgY2lyY3VsYXIsXG4gICAgLy8gYnV0IHJhZGlhbGF4aXMgbGluZXMgYXJlIHN0cmFpZ2h0IGZyb20gY2lyY2xlIGNlbnRlciB0byBvdXRlciBib3VuZFxuICAgIGF4aXNMaW5lR3JpZEF0dHIsXG4gICAgYXhpc1RpY2tBdHRyc1xuKTtcblxudmFyIGFuZ3VsYXJBeGlzQXR0cnMgPSB7XG4gICAgdmlzaWJsZTogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLnZpc2libGUsIHtkZmx0OiB0cnVlfSksXG4gICAgdHlwZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIC8vICdsaW5lYXInIHNob3VsZCBtYXliZSBiZSBjYWxsZWQgJ2FuZ2xlJyBvciAnYW5ndWxhcicgaGVyZVxuICAgICAgICAvLyB0byBtYWtlIGNsZWFyIHRoYXQgYXhpcyBoZXJlIGlzIHBlcmlvZGljIGFuZCBtb3JlIHRpZ2h0bHkgbWF0Y2hcbiAgICAgICAgLy8gYHRoZXRhdW5pdGA/XG4gICAgICAgIC8vXG4gICAgICAgIC8vIHNraXAgJ2RhdGUnIGZvciBmaXJzdCBwdXNoXG4gICAgICAgIC8vIG5vICdsb2cnIGZvciBub3dcbiAgICAgICAgdmFsdWVzOiBbJy0nLCAnbGluZWFyJywgJ2NhdGVnb3J5J10sXG4gICAgICAgIGRmbHQ6ICctJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIF9ub1RlbXBsYXRpbmc6IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBjYXRlZ29yeW9yZGVyOiBheGVzQXR0cnMuY2F0ZWdvcnlvcmRlcixcbiAgICBjYXRlZ29yeWFycmF5OiBheGVzQXR0cnMuY2F0ZWdvcnlhcnJheSxcblxuICAgIHRoZXRhdW5pdDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydyYWRpYW5zJywgJ2RlZ3JlZXMnXSxcbiAgICAgICAgZGZsdDogJ2RlZ3JlZXMnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHBlcmlvZDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgICAgIC8vIEV4YW1wbGVzIGZvciBkYXRlIGF4ZXM6XG4gICAgICAgIC8vXG4gICAgICAgIC8vIC0gcGVyaW9kIHRoYXQgZXF1YWxzIHRoZSB0aW1lc2VyaWVzIGxlbmd0aFxuICAgICAgICAvLyAgaHR0cDovL2Zsb3dpbmdkYXRhLmNvbS8yMDE3LzAxLzI0L29uZS1kYXRhc2V0LXZpc3VhbGl6ZWQtMjUtd2F5cy8xOC1wb2xhci1jb29yZGluYXRlcy9cbiAgICAgICAgLy8gLSBhbmQgMS15ZWFyIHBlcmlvZHMgKGZvY3VzaW5nIG9uIHNlYXNvbmFsIGNoYW5nZTBcbiAgICAgICAgLy8gIGh0dHA6Ly9vdGV4dHMub3JnL2ZwcDIvc2Vhc29uYWwtcGxvdHMuaHRtbFxuICAgICAgICAvLyAgaHR0cHM6Ly9ibG9ncy5zY2llbnRpZmljYW1lcmljYW4uY29tL3NhLXZpc3VhbC93aHktYXJlLXNvLW1hbnktYmFiaWVzLWJvcm4tYXJvdW5kLTgtMDAtYS1tL1xuICAgICAgICAvLyAgaHR0cDovL3d3dy5zZWFzb25hbGFkanVzdG1lbnQuY29tLzIwMTIvMDkvMDUvY2xvY2stcGxvdC12aXN1YWxpc2luZy1zZWFzb25hbGl0eS11c2luZy1yLWFuZC1nZ3Bsb3QyLXBhcnQtMy9cbiAgICAgICAgLy8gIGh0dHBzOi8vaS5waW5pbWcuY29tLzczNngvNDkvYjkvNzIvNDliOTcyY2NiMzIwNmExYTZkNmY4NzBkYWM1NDMyODAuanBnXG4gICAgICAgIC8vICBodHRwczovL3d3dy5jbGltYXRlLWxhYi1ib29rLmFjLnVrL3NwaXJhbHMvXG4gICAgfSxcblxuICAgIGRpcmVjdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydjb3VudGVyY2xvY2t3aXNlJywgJ2Nsb2Nrd2lzZSddLFxuICAgICAgICBkZmx0OiAnY291bnRlcmNsb2Nrd2lzZScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgcm90YXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2FuZ2xlJyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBob3ZlcmZvcm1hdDogYXhlc0F0dHJzLmhvdmVyZm9ybWF0LFxuXG4gICAgdWlyZXZpc2lvbjoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuXG5leHRlbmRGbGF0KFxuICAgIGFuZ3VsYXJBeGlzQXR0cnMsXG5cbiAgICAvLyBOLkIuIGFuZ3VsYXIgZ3JpZCBsaW5lcyBhcmUgc3RyYWlnaHQgbGluZXMgZnJvbSBjaXJjbGUgY2VudGVyIHRvIG91dGVyIGJvdW5kXG4gICAgLy8gdGhlIGFuZ3VsYXIgbGluZSBpcyBjaXJjdWxhciBib3VuZGluZyB0aGUgcG9sYXIgcGxvdCBhcmVhLlxuICAgIGF4aXNMaW5lR3JpZEF0dHIsXG5cbiAgICAvLyBOLkIuIHRpY2tzdWZmaXggZGVmYXVsdHMgdG8gJ8KwJyBmb3IgYW5ndWxhciBheGVzIHdpdGggYHRoZXRhdW5pdDogJ2RlZ3JlZXMnYFxuICAgIGF4aXNUaWNrQXR0cnNcbik7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIC8vIFRPRE8gZm9yIHgveS96b29tIHN5c3RlbSBmb3IgcGFwZXItYmFzZWQgem9vbWluZzpcbiAgICAvLyB4OiB7fSxcbiAgICAvLyB5OiB7fSxcbiAgICAvLyB6b29tOiB7fSxcblxuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICdwb2xhcicsIGVkaXRUeXBlOiAncGxvdCd9KSxcblxuICAgIHNlY3Rvcjoge1xuICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIGVkaXRUeXBlOiAncGxvdCd9LFxuICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInLCBlZGl0VHlwZTogJ3Bsb3QnfVxuICAgICAgICBdLFxuICAgICAgICBkZmx0OiBbMCwgMzYwXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG9sZToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgYmdjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgZGZsdDogY29sb3JBdHRycy5iYWNrZ3JvdW5kLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgcmFkaWFsYXhpczogcmFkaWFsQXhpc0F0dHJzLFxuICAgIGFuZ3VsYXJheGlzOiBhbmd1bGFyQXhpc0F0dHJzLFxuXG4gICAgZ3JpZHNoYXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2NpcmN1bGFyJywgJ2xpbmVhciddLFxuICAgICAgICBkZmx0OiAnY2lyY3VsYXInLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIC8vIFRPRE8gbWF5YmU/XG4gICAgLy8gYW5ub3RhdGlvbnM6XG5cbiAgICB1aXJldmlzaW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdub25lJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGVkaXRUeXBlOiAnY2FsYydcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzXCI6NTkyLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlc1wiOjc1MCxcIi4uL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlc1wiOjc3OSxcIi4uL2RvbWFpblwiOjc5Mn1dLDgzMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBUZW1wbGF0ZSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcblxudmFyIGhhbmRsZVN1YnBsb3REZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3N1YnBsb3RfZGVmYXVsdHMnKTtcbnZhciBnZXRTdWJwbG90RGF0YSA9IF9kZXJlcV8oJy4uL2dldF9kYXRhJykuZ2V0U3VicGxvdERhdGE7XG5cbnZhciBoYW5kbGVUaWNrVmFsdWVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi90aWNrX3ZhbHVlX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlVGlja01hcmtEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi90aWNrX21hcmtfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrTGFiZWxEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi90aWNrX2xhYmVsX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlQ2F0ZWdvcnlPcmRlckRlZmF1bHRzID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL2NhdGVnb3J5X29yZGVyX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZUdyaWREZWZhdWx0cyA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9saW5lX2dyaWRfZGVmYXVsdHMnKTtcbnZhciBhdXRvVHlwZSA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9heGlzX2F1dG90eXBlJyk7XG5cbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIHNldENvbnZlcnQgPSBfZGVyZXFfKCcuL3NldF9jb252ZXJ0Jyk7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcbnZhciBheGlzTmFtZXMgPSBjb25zdGFudHMuYXhpc05hbWVzO1xuXG5mdW5jdGlvbiBoYW5kbGVEZWZhdWx0cyhjb250SW4sIGNvbnRPdXQsIGNvZXJjZSwgb3B0cykge1xuICAgIHZhciBiZ0NvbG9yID0gY29lcmNlKCdiZ2NvbG9yJyk7XG4gICAgb3B0cy5iZ0NvbG9yID0gQ29sb3IuY29tYmluZShiZ0NvbG9yLCBvcHRzLnBhcGVyX2JnY29sb3IpO1xuXG4gICAgdmFyIHNlY3RvciA9IGNvZXJjZSgnc2VjdG9yJyk7XG4gICAgY29lcmNlKCdob2xlJyk7XG5cbiAgICAvLyBjb3VsZCBvcHRpbWl6ZSwgc3VicGxvdERhdGEgaXMgbm90IGFsd2F5cyBuZWVkZWQhXG4gICAgdmFyIHN1YnBsb3REYXRhID0gZ2V0U3VicGxvdERhdGEob3B0cy5mdWxsRGF0YSwgY29uc3RhbnRzLm5hbWUsIG9wdHMuaWQpO1xuICAgIHZhciBsYXlvdXRPdXQgPSBvcHRzLmxheW91dE91dDtcbiAgICB2YXIgYXhOYW1lO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlQXhpcyhhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBjb2VyY2UoYXhOYW1lICsgJy4nICsgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGF4aXNOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBheE5hbWUgPSBheGlzTmFtZXNbaV07XG5cbiAgICAgICAgaWYoIUxpYi5pc1BsYWluT2JqZWN0KGNvbnRJbltheE5hbWVdKSkge1xuICAgICAgICAgICAgY29udEluW2F4TmFtZV0gPSB7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBheEluID0gY29udEluW2F4TmFtZV07XG4gICAgICAgIHZhciBheE91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcihjb250T3V0LCBheE5hbWUpO1xuICAgICAgICBheE91dC5faWQgPSBheE91dC5fbmFtZSA9IGF4TmFtZTtcbiAgICAgICAgYXhPdXQuX2F0dHIgPSBvcHRzLmlkICsgJy4nICsgYXhOYW1lO1xuICAgICAgICBheE91dC5fdHJhY2VJbmRpY2VzID0gc3VicGxvdERhdGEubWFwKGZ1bmN0aW9uKHQpIHsgcmV0dXJuIHQuX2V4cGFuZGVkSW5kZXg7IH0pO1xuXG4gICAgICAgIHZhciBkYXRhQXR0ciA9IGNvbnN0YW50cy5heGlzTmFtZTJkYXRhQXJyYXlbYXhOYW1lXTtcbiAgICAgICAgdmFyIGF4VHlwZSA9IGhhbmRsZUF4aXNUeXBlRGVmYXVsdHMoYXhJbiwgYXhPdXQsIGNvZXJjZUF4aXMsIHN1YnBsb3REYXRhLCBkYXRhQXR0cik7XG5cbiAgICAgICAgaGFuZGxlQ2F0ZWdvcnlPcmRlckRlZmF1bHRzKGF4SW4sIGF4T3V0LCBjb2VyY2VBeGlzLCB7XG4gICAgICAgICAgICBheERhdGE6IHN1YnBsb3REYXRhLFxuICAgICAgICAgICAgZGF0YUF0dHI6IGRhdGFBdHRyXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciB2aXNpYmxlID0gY29lcmNlQXhpcygndmlzaWJsZScpO1xuICAgICAgICBzZXRDb252ZXJ0KGF4T3V0LCBjb250T3V0LCBsYXlvdXRPdXQpO1xuXG4gICAgICAgIGNvZXJjZUF4aXMoJ3VpcmV2aXNpb24nLCBjb250T3V0LnVpcmV2aXNpb24pO1xuXG4gICAgICAgIHZhciBkZmx0Q29sb3I7XG4gICAgICAgIHZhciBkZmx0Rm9udENvbG9yO1xuXG4gICAgICAgIGlmKHZpc2libGUpIHtcbiAgICAgICAgICAgIGRmbHRDb2xvciA9IGNvZXJjZUF4aXMoJ2NvbG9yJyk7XG4gICAgICAgICAgICBkZmx0Rm9udENvbG9yID0gKGRmbHRDb2xvciA9PT0gYXhJbi5jb2xvcikgPyBkZmx0Q29sb3IgOiBvcHRzLmZvbnQuY29sb3I7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIG1ha2UgZG93bnN0cmVhbSBjb2RlIGNhbGwgYXguc2V0U2NhbGUsXG4gICAgICAgIC8vIGFzIGJvdGggcmFkaWFsIGFuZCBhbmd1bGFyIGF4ZXMgZG9uJ3QgaGF2ZSBhIHNldCBkb21haW4uXG4gICAgICAgIC8vIEZ1cnRoZXJtb3JlLCBhbmd1bGFyIGF4ZXMgZG9uJ3QgaGF2ZSBhIHNldCByYW5nZS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gTW9ja2VkIGRvbWFpbnMgYW5kIHJhbmdlcyBhcmUgc2V0IGJ5IHRoZSBwb2xhciBzdWJwbG90IGluc3RhbmNlcyxcbiAgICAgICAgLy8gYnV0IEF4ZXMuZmluZEV4dHJlbWVzIHVzZXMgdGhlIHNpZ24gb2YgX20gdG8gZGV0ZXJtaW5lIHdoaWNoIHBhZGRpbmcgdmFsdWVcbiAgICAgICAgLy8gdG8gdXNlLlxuICAgICAgICAvL1xuICAgICAgICAvLyBCeSBzZXR0aW5nLCBfbSB0byAxIGhlcmUsIHdlIG1ha2UgQXhlcy5maW5kRXh0cmVtZXMgdGhpbmsgdGhhdFxuICAgICAgICAvLyByYW5nZVsxXSA+IHJhbmdlWzBdLCBhbmQgdmljZS12ZXJzYSBmb3IgYGF1dG9yYW5nZTogJ3JldmVyc2VkJ2AgYmVsb3cuXG4gICAgICAgIGF4T3V0Ll9tID0gMTtcblxuICAgICAgICBzd2l0Y2goYXhOYW1lKSB7XG4gICAgICAgICAgICBjYXNlICdyYWRpYWxheGlzJzpcbiAgICAgICAgICAgICAgICB2YXIgYXV0b1JhbmdlID0gY29lcmNlQXhpcygnYXV0b3JhbmdlJywgIWF4T3V0LmlzVmFsaWRSYW5nZShheEluLnJhbmdlKSk7XG4gICAgICAgICAgICAgICAgYXhJbi5hdXRvcmFuZ2UgPSBhdXRvUmFuZ2U7XG4gICAgICAgICAgICAgICAgaWYoYXV0b1JhbmdlICYmIChheFR5cGUgPT09ICdsaW5lYXInIHx8IGF4VHlwZSA9PT0gJy0nKSkgY29lcmNlQXhpcygncmFuZ2Vtb2RlJyk7XG4gICAgICAgICAgICAgICAgaWYoYXV0b1JhbmdlID09PSAncmV2ZXJzZWQnKSBheE91dC5fbSA9IC0xO1xuXG4gICAgICAgICAgICAgICAgY29lcmNlQXhpcygncmFuZ2UnKTtcbiAgICAgICAgICAgICAgICBheE91dC5jbGVhblJhbmdlKCdyYW5nZScsIHtkZmx0UmFuZ2U6IFswLCAxXX0pO1xuXG4gICAgICAgICAgICAgICAgaWYodmlzaWJsZSkge1xuICAgICAgICAgICAgICAgICAgICBjb2VyY2VBeGlzKCdzaWRlJyk7XG4gICAgICAgICAgICAgICAgICAgIGNvZXJjZUF4aXMoJ2FuZ2xlJywgc2VjdG9yWzBdKTtcblxuICAgICAgICAgICAgICAgICAgICBjb2VyY2VBeGlzKCd0aXRsZS50ZXh0Jyk7XG4gICAgICAgICAgICAgICAgICAgIExpYi5jb2VyY2VGb250KGNvZXJjZUF4aXMsICd0aXRsZS5mb250Jywge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5OiBvcHRzLmZvbnQuZmFtaWx5LFxuICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogTWF0aC5yb3VuZChvcHRzLmZvbnQuc2l6ZSAqIDEuMiksXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xvcjogZGZsdEZvbnRDb2xvclxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ2FuZ3VsYXJheGlzJzpcbiAgICAgICAgICAgICAgICAvLyBXZSBkbyBub3Qgc3VwcG9ydCAndHJ1ZScgZGF0ZSBhbmd1bGFyIGF4ZXMgeWV0LFxuICAgICAgICAgICAgICAgIC8vIHVzZXJzIGNhbiBzdGlsbCBwbG90IGRhdGVzIG9uIGFuZ3VsYXIgYXhlcyBieSBzZXR0aW5nXG4gICAgICAgICAgICAgICAgLy8gYGFuZ3VsYXJheGlzLnR5cGU6ICdjYXRlZ29yeSdgLlxuICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgLy8gSGVyZSwgaWYgYSBkYXRlIGFuZ3VsYXIgYXhlcyBpcyBkZXRlY3RlZCwgd2UgbWFrZVxuICAgICAgICAgICAgICAgIC8vIGFsbCBpdHMgY29ycmVzcG9uZGluZyB0cmFjZXMgaW52aXNpYmxlLCBzbyB0aGF0XG4gICAgICAgICAgICAgICAgLy8gd2hlbiB3ZSBkbyBhZGQgc3VwcG9ydCBmb3IgZGF0YSBhbmd1bGFyIGF4ZXMsIHRoZSBuZXdcbiAgICAgICAgICAgICAgICAvLyBiZWhhdmlvciB3b24ndCBjb25mbGljdCB3aXRoIGV4aXN0aW5nIGJlaGF2aW9yXG4gICAgICAgICAgICAgICAgaWYoYXhUeXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgTGliLmxvZygnUG9sYXIgcGxvdHMgZG8gbm90IHN1cHBvcnQgZGF0ZSBhbmd1bGFyIGF4ZXMgeWV0LicpO1xuXG4gICAgICAgICAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBzdWJwbG90RGF0YS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3VicGxvdERhdGFbal0udmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gdHVybiB0aGlzIGludG8gYSAnZHVtbXknIGxpbmVhciBheGlzIHNvIHRoYXRcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHN1YnBsb3Qgc3RpbGwgcmVuZGVycyBva1xuICAgICAgICAgICAgICAgICAgICBheFR5cGUgPSBheEluLnR5cGUgPSBheE91dC50eXBlID0gJ2xpbmVhcic7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoYXhUeXBlID09PSAnbGluZWFyJykge1xuICAgICAgICAgICAgICAgICAgICBjb2VyY2VBeGlzKCd0aGV0YXVuaXQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb2VyY2VBeGlzKCdwZXJpb2QnKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgZGlyZWN0aW9uID0gY29lcmNlQXhpcygnZGlyZWN0aW9uJyk7XG4gICAgICAgICAgICAgICAgY29lcmNlQXhpcygncm90YXRpb24nLCB7Y291bnRlcmNsb2Nrd2lzZTogMCwgY2xvY2t3aXNlOiA5MH1bZGlyZWN0aW9uXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBpZih2aXNpYmxlKSB7XG4gICAgICAgICAgICBoYW5kbGVUaWNrVmFsdWVEZWZhdWx0cyhheEluLCBheE91dCwgY29lcmNlQXhpcywgYXhPdXQudHlwZSk7XG4gICAgICAgICAgICBoYW5kbGVUaWNrTGFiZWxEZWZhdWx0cyhheEluLCBheE91dCwgY29lcmNlQXhpcywgYXhPdXQudHlwZSwge1xuICAgICAgICAgICAgICAgIHRpY2tTdWZmaXhEZmx0OiBheE91dC50aGV0YXVuaXQgPT09ICdkZWdyZWVzJyA/ICfCsCcgOiB1bmRlZmluZWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaGFuZGxlVGlja01hcmtEZWZhdWx0cyhheEluLCBheE91dCwgY29lcmNlQXhpcywge291dGVyVGlja3M6IHRydWV9KTtcblxuICAgICAgICAgICAgdmFyIHNob3dUaWNrTGFiZWxzID0gY29lcmNlQXhpcygnc2hvd3RpY2tsYWJlbHMnKTtcbiAgICAgICAgICAgIGlmKHNob3dUaWNrTGFiZWxzKSB7XG4gICAgICAgICAgICAgICAgTGliLmNvZXJjZUZvbnQoY29lcmNlQXhpcywgJ3RpY2tmb250Jywge1xuICAgICAgICAgICAgICAgICAgICBmYW1pbHk6IG9wdHMuZm9udC5mYW1pbHksXG4gICAgICAgICAgICAgICAgICAgIHNpemU6IG9wdHMuZm9udC5zaXplLFxuICAgICAgICAgICAgICAgICAgICBjb2xvcjogZGZsdEZvbnRDb2xvclxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvZXJjZUF4aXMoJ3RpY2thbmdsZScpO1xuICAgICAgICAgICAgICAgIGNvZXJjZUF4aXMoJ3RpY2tmb3JtYXQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaGFuZGxlTGluZUdyaWREZWZhdWx0cyhheEluLCBheE91dCwgY29lcmNlQXhpcywge1xuICAgICAgICAgICAgICAgIGRmbHRDb2xvcjogZGZsdENvbG9yLFxuICAgICAgICAgICAgICAgIGJnQ29sb3I6IG9wdHMuYmdDb2xvcixcbiAgICAgICAgICAgICAgICAvLyBkZWZhdWx0IGdyaWQgY29sb3IgaXMgZGFya2VyIGhlcmUgKDYwJSwgdnMgY2FydGVzaWFuIGRlZmF1bHQgfjkxJSlcbiAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIHRoZSBncmlkIGlzIG5vdCBzcXVhcmUgc28gdGhlIGV5ZSBuZWVkcyBoZWF2aWVyIGN1ZXMgdG8gZm9sbG93XG4gICAgICAgICAgICAgICAgYmxlbmQ6IDYwLFxuICAgICAgICAgICAgICAgIHNob3dMaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIHNob3dHcmlkOiB0cnVlLFxuICAgICAgICAgICAgICAgIG5vWmVyb0xpbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgYXR0cmlidXRlczogbGF5b3V0QXR0cmlidXRlc1theE5hbWVdXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29lcmNlQXhpcygnbGF5ZXInKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF4VHlwZSAhPT0gJ2NhdGVnb3J5JykgY29lcmNlQXhpcygnaG92ZXJmb3JtYXQnKTtcblxuICAgICAgICBheE91dC5faW5wdXQgPSBheEluO1xuICAgIH1cblxuICAgIGlmKGNvbnRPdXQuYW5ndWxhcmF4aXMudHlwZSA9PT0gJ2NhdGVnb3J5Jykge1xuICAgICAgICBjb2VyY2UoJ2dyaWRzaGFwZScpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaGFuZGxlQXhpc1R5cGVEZWZhdWx0cyhheEluLCBheE91dCwgY29lcmNlLCBzdWJwbG90RGF0YSwgZGF0YUF0dHIpIHtcbiAgICB2YXIgYXhUeXBlID0gY29lcmNlKCd0eXBlJyk7XG5cbiAgICBpZihheFR5cGUgPT09ICctJykge1xuICAgICAgICB2YXIgdHJhY2U7XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHN1YnBsb3REYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihzdWJwbG90RGF0YVtpXS52aXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgdHJhY2UgPSBzdWJwbG90RGF0YVtpXTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRyYWNlICYmIHRyYWNlW2RhdGFBdHRyXSkge1xuICAgICAgICAgICAgYXhPdXQudHlwZSA9IGF1dG9UeXBlKHRyYWNlW2RhdGFBdHRyXSwgJ2dyZWdvcmlhbicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYXhPdXQudHlwZSA9PT0gJy0nKSB7XG4gICAgICAgICAgICBheE91dC50eXBlID0gJ2xpbmVhcic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBjb3B5IGF1dG9UeXBlIGJhY2sgdG8gaW5wdXQgYXhpc1xuICAgICAgICAgICAgLy8gbm90ZSB0aGF0IGlmIHRoaXMgb2JqZWN0IGRpZG4ndCBleGlzdFxuICAgICAgICAgICAgLy8gaW4gdGhlIGlucHV0IGxheW91dCwgd2UgaGF2ZSB0byBwdXQgaXQgaW5cbiAgICAgICAgICAgIC8vIHRoaXMgaGFwcGVucyBpbiB0aGUgbWFpbiBzdXBwbHlEZWZhdWx0cyBmdW5jdGlvblxuICAgICAgICAgICAgYXhJbi50eXBlID0gYXhPdXQudHlwZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBheE91dC50eXBlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgaGFuZGxlU3VicGxvdERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhLCB7XG4gICAgICAgIHR5cGU6IGNvbnN0YW50cy5uYW1lLFxuICAgICAgICBhdHRyaWJ1dGVzOiBsYXlvdXRBdHRyaWJ1dGVzLFxuICAgICAgICBoYW5kbGVEZWZhdWx0czogaGFuZGxlRGVmYXVsdHMsXG4gICAgICAgIGZvbnQ6IGxheW91dE91dC5mb250LFxuICAgICAgICBwYXBlcl9iZ2NvbG9yOiBsYXlvdXRPdXQucGFwZXJfYmdjb2xvcixcbiAgICAgICAgZnVsbERhdGE6IGZ1bGxEYXRhLFxuICAgICAgICBsYXlvdXRPdXQ6IGxheW91dE91dFxuICAgIH0pO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uL2NhcnRlc2lhbi9heGlzX2F1dG90eXBlXCI6NzY4LFwiLi4vY2FydGVzaWFuL2NhdGVnb3J5X29yZGVyX2RlZmF1bHRzXCI6NzcxLFwiLi4vY2FydGVzaWFuL2xpbmVfZ3JpZF9kZWZhdWx0c1wiOjc4MSxcIi4uL2NhcnRlc2lhbi90aWNrX2xhYmVsX2RlZmF1bHRzXCI6Nzg2LFwiLi4vY2FydGVzaWFuL3RpY2tfbWFya19kZWZhdWx0c1wiOjc4NyxcIi4uL2NhcnRlc2lhbi90aWNrX3ZhbHVlX2RlZmF1bHRzXCI6Nzg4LFwiLi4vZ2V0X2RhdGFcIjo4MDIsXCIuLi9zdWJwbG90X2RlZmF1bHRzXCI6ODQyLFwiLi9jb25zdGFudHNcIjo4MjksXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6ODMyLFwiLi9zZXRfY29udmVydFwiOjg0MX1dLDgzNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi8uLi90cmFjZXMvc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG52YXIgc2NhdHRlck1hcmtlckF0dHJzID0gc2NhdHRlckF0dHJzLm1hcmtlcjtcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciBkZXByZWNhdGlvbldhcm5pbmcgPSBbXG4gICAgJ0FyZWEgdHJhY2VzIGFyZSBkZXByZWNhdGVkIScsXG4gICAgJ1BsZWFzZSBzd2l0Y2ggdG8gdGhlICpiYXJwb2xhciogdHJhY2UgdHlwZS4nXG5dLmpvaW4oJyAnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgcjogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLnIsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgdDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLnQsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgbWFya2VyOiB7XG4gICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyQXR0cnMuY29sb3IsIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgc2l6ZTogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlck1hcmtlckF0dHJzLnNpemUsIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgc3ltYm9sOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyQXR0cnMuc3ltYm9sLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIG9wYWNpdHk6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJBdHRycy5vcGFjaXR5LCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi8uLi90cmFjZXMvc2NhdHRlci9hdHRyaWJ1dGVzXCI6MTExMn1dLDgzNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGF4ZXNBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxudmFyIGRlcHJlY2F0aW9uV2FybmluZyA9IFtcbiAgICAnTGVnYWN5IHBvbGFyIGNoYXJ0cyBhcmUgZGVwcmVjYXRlZCEnLFxuICAgICdQbGVhc2Ugc3dpdGNoIHRvICpwb2xhciogc3VicGxvdHMuJ1xuXS5qb2luKCcgJyk7XG5cbnZhciBkb21haW5BdHRyID0gZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLmRvbWFpbiwge1xuICAgIFxufSk7XG5cbmZ1bmN0aW9uIG1lcmdlQXR0cnMoYXhpc05hbWUsIG5vbkNvbW1vbkF0dHJzKSB7XG4gICAgdmFyIGNvbW1vbkF0dHJzID0ge1xuICAgICAgICBzaG93bGluZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2hvd3RpY2tsYWJlbHM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHRpY2tvcmllbnRhdGlvbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2hvcml6b250YWwnLCAndmVydGljYWwnXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHRpY2tsZW46IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdGlja2NvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdGlja3N1ZmZpeDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlbmRwYWRkaW5nOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IGRlcHJlY2F0aW9uV2FybmluZyxcbiAgICAgICAgfSxcbiAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gZXh0ZW5kRmxhdCh7fSwgbm9uQ29tbW9uQXR0cnMsIGNvbW1vbkF0dHJzKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4gICAgcmFkaWFsYXhpczogbWVyZ2VBdHRycygncmFkaWFsJywge1xuICAgICAgICByYW5nZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAgICAgIHsgdmFsVHlwZTogJ251bWJlcicgfSxcbiAgICAgICAgICAgICAgICB7IHZhbFR5cGU6ICdudW1iZXInIH1cbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZG9tYWluOiBkb21haW5BdHRyLFxuICAgICAgICBvcmllbnRhdGlvbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSksXG5cbiAgICBhbmd1bGFyYXhpczogbWVyZ2VBdHRycygnYW5ndWxhcicsIHtcbiAgICAgICAgcmFuZ2U6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgICAgICB7IHZhbFR5cGU6ICdudW1iZXInLCBkZmx0OiAwIH0sXG4gICAgICAgICAgICAgICAgeyB2YWxUeXBlOiAnbnVtYmVyJywgZGZsdDogMzYwIH1cbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZG9tYWluOiBkb21haW5BdHRyXG4gICAgfSksXG5cbiAgICAvLyBhdHRyaWJ1dGVzIHRoYXQgYXBwZWFyIGF0IGxheW91dCByb290XG4gICAgbGF5b3V0OiB7XG4gICAgICAgIGRpcmVjdGlvbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2Nsb2Nrd2lzZScsICdjb3VudGVyY2xvY2t3aXNlJ10sXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBvcmllbnRhdGlvbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2FuZ2xlJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9XG59LCAncGxvdCcsICduZXN0ZWQnKTtcblxufSx7XCIuLi8uLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlc1wiOjc1MCxcIi4uLy4uL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlc1wiOjc3OX1dLDgzNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBQb2xhciA9IG1vZHVsZS5leHBvcnRzID0gX2RlcmVxXygnLi9taWNyb3BvbGFyJyk7XG5cblBvbGFyLm1hbmFnZXIgPSBfZGVyZXFfKCcuL21pY3JvcG9sYXJfbWFuYWdlcicpO1xuXG59LHtcIi4vbWljcm9wb2xhclwiOjgzNyxcIi4vbWljcm9wb2xhcl9tYW5hZ2VyXCI6ODM4fV0sODM3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vLi4vbGliJyk7XG52YXIgZXh0ZW5kRGVlcEFsbCA9IExpYi5leHRlbmREZWVwQWxsO1xudmFyIE1JRF9TSElGVCA9IF9kZXJlcV8oJy4uLy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKS5NSURfU0hJRlQ7XG5cbnZhciDCtSA9IG1vZHVsZS5leHBvcnRzID0geyB2ZXJzaW9uOiAnMC4yLjInIH07XG5cbsK1LkF4aXMgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZGF0YTogW10sXG4gICAgICAgIGxheW91dDoge31cbiAgICB9LCBpbnB1dENvbmZpZyA9IHt9LCBsaXZlQ29uZmlnID0ge307XG4gICAgdmFyIHN2ZywgY29udGFpbmVyLCBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoKCdob3ZlcicpLCByYWRpYWxTY2FsZSwgYW5ndWxhclNjYWxlO1xuICAgIHZhciBleHBvcnRzID0ge307XG4gICAgZnVuY3Rpb24gcmVuZGVyKF9jb250YWluZXIpIHtcbiAgICAgICAgY29udGFpbmVyID0gX2NvbnRhaW5lciB8fCBjb250YWluZXI7XG4gICAgICAgIHZhciBkYXRhID0gY29uZmlnLmRhdGE7XG4gICAgICAgIHZhciBheGlzQ29uZmlnID0gY29uZmlnLmxheW91dDtcbiAgICAgICAgaWYgKHR5cGVvZiBjb250YWluZXIgPT0gJ3N0cmluZycgfHwgY29udGFpbmVyLm5vZGVOYW1lKSBjb250YWluZXIgPSBkMy5zZWxlY3QoY29udGFpbmVyKTtcbiAgICAgICAgY29udGFpbmVyLmRhdHVtKGRhdGEpLmVhY2goZnVuY3Rpb24oX2RhdGEsIF9pbmRleCkge1xuICAgICAgICAgICAgdmFyIGRhdGFPcmlnaW5hbCA9IF9kYXRhLnNsaWNlKCk7XG4gICAgICAgICAgICBsaXZlQ29uZmlnID0ge1xuICAgICAgICAgICAgICAgIGRhdGE6IMK1LnV0aWwuY2xvbmVKc29uKGRhdGFPcmlnaW5hbCksXG4gICAgICAgICAgICAgICAgbGF5b3V0OiDCtS51dGlsLmNsb25lSnNvbihheGlzQ29uZmlnKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBjb2xvckluZGV4ID0gMDtcbiAgICAgICAgICAgIGRhdGFPcmlnaW5hbC5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWQuY29sb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgZC5jb2xvciA9IGF4aXNDb25maWcuZGVmYXVsdENvbG9yUmFuZ2VbY29sb3JJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIGNvbG9ySW5kZXggPSAoY29sb3JJbmRleCArIDEpICUgYXhpc0NvbmZpZy5kZWZhdWx0Q29sb3JSYW5nZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghZC5zdHJva2VDb2xvcikge1xuICAgICAgICAgICAgICAgICAgICBkLnN0cm9rZUNvbG9yID0gZC5nZW9tZXRyeSA9PT0gJ0xpbmVQbG90JyA/IGQuY29sb3IgOiBkMy5yZ2IoZC5jb2xvcikuZGFya2VyKCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGl2ZUNvbmZpZy5kYXRhW2ldLmNvbG9yID0gZC5jb2xvcjtcbiAgICAgICAgICAgICAgICBsaXZlQ29uZmlnLmRhdGFbaV0uc3Ryb2tlQ29sb3IgPSBkLnN0cm9rZUNvbG9yO1xuICAgICAgICAgICAgICAgIGxpdmVDb25maWcuZGF0YVtpXS5zdHJva2VEYXNoID0gZC5zdHJva2VEYXNoO1xuICAgICAgICAgICAgICAgIGxpdmVDb25maWcuZGF0YVtpXS5zdHJva2VTaXplID0gZC5zdHJva2VTaXplO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgZGF0YSA9IGRhdGFPcmlnaW5hbC5maWx0ZXIoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHZhciB2aXNpYmxlID0gZC52aXNpYmxlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgdmlzaWJsZSA9PT0gJ3VuZGVmaW5lZCcgfHwgdmlzaWJsZSA9PT0gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGlzU3RhY2tlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdmFyIGRhdGFXaXRoR3JvdXBJZCA9IGRhdGEubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICBpc1N0YWNrZWQgPSBpc1N0YWNrZWQgfHwgdHlwZW9mIGQuZ3JvdXBJZCAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChpc1N0YWNrZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JvdXBlZCA9IGQzLm5lc3QoKS5rZXkoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIGQuZ3JvdXBJZCAhPSAndW5kZWZpbmVkJyA/IGQuZ3JvdXBJZCA6ICd1bnN0YWNrZWQnO1xuICAgICAgICAgICAgICAgIH0pLmVudHJpZXMoZGF0YVdpdGhHcm91cElkKTtcbiAgICAgICAgICAgICAgICB2YXIgZGF0YVlTdGFjayA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzdGFja2VkID0gZ3JvdXBlZC5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZC5rZXkgPT09ICd1bnN0YWNrZWQnKSByZXR1cm4gZC52YWx1ZXM7IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZBcnJheSA9IGQudmFsdWVzWzBdLnIubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgZC52YWx1ZXMuZm9yRWFjaChmdW5jdGlvbihkLCBpLCBhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZC55U3RhY2sgPSBbIHByZXZBcnJheSBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFZU3RhY2sucHVzaChwcmV2QXJyYXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZBcnJheSA9IMK1LnV0aWwuc3VtQXJyYXlzKGQuciwgcHJldkFycmF5KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGQudmFsdWVzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZGF0YSA9IGQzLm1lcmdlKHN0YWNrZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICBkLnQgPSBBcnJheS5pc0FycmF5KGQudFswXSkgPyBkLnQgOiBbIGQudCBdO1xuICAgICAgICAgICAgICAgIGQuciA9IEFycmF5LmlzQXJyYXkoZC5yWzBdKSA/IGQuciA6IFsgZC5yIF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciByYWRpdXMgPSBNYXRoLm1pbihheGlzQ29uZmlnLndpZHRoIC0gYXhpc0NvbmZpZy5tYXJnaW4ubGVmdCAtIGF4aXNDb25maWcubWFyZ2luLnJpZ2h0LCBheGlzQ29uZmlnLmhlaWdodCAtIGF4aXNDb25maWcubWFyZ2luLnRvcCAtIGF4aXNDb25maWcubWFyZ2luLmJvdHRvbSkgLyAyO1xuICAgICAgICAgICAgcmFkaXVzID0gTWF0aC5tYXgoMTAsIHJhZGl1cyk7XG4gICAgICAgICAgICB2YXIgY2hhcnRDZW50ZXIgPSBbIGF4aXNDb25maWcubWFyZ2luLmxlZnQgKyByYWRpdXMsIGF4aXNDb25maWcubWFyZ2luLnRvcCArIHJhZGl1cyBdO1xuICAgICAgICAgICAgdmFyIGV4dGVudDtcbiAgICAgICAgICAgIGlmIChpc1N0YWNrZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgaGlnaGVzdFN0YWNrZWRWYWx1ZSA9IGQzLm1heCjCtS51dGlsLnN1bUFycmF5cyjCtS51dGlsLmFycmF5TGFzdChkYXRhKS5yWzBdLCDCtS51dGlsLmFycmF5TGFzdChkYXRhWVN0YWNrKSkpO1xuICAgICAgICAgICAgICAgIGV4dGVudCA9IFsgMCwgaGlnaGVzdFN0YWNrZWRWYWx1ZSBdO1xuICAgICAgICAgICAgfSBlbHNlIGV4dGVudCA9IGQzLmV4dGVudCjCtS51dGlsLmZsYXR0ZW5BcnJheShkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQucjtcbiAgICAgICAgICAgIH0pKSk7XG4gICAgICAgICAgICBpZiAoYXhpc0NvbmZpZy5yYWRpYWxBeGlzLmRvbWFpbiAhPSDCtS5EQVRBRVhURU5UKSBleHRlbnRbMF0gPSAwO1xuICAgICAgICAgICAgcmFkaWFsU2NhbGUgPSBkMy5zY2FsZS5saW5lYXIoKS5kb21haW4oYXhpc0NvbmZpZy5yYWRpYWxBeGlzLmRvbWFpbiAhPSDCtS5EQVRBRVhURU5UICYmIGF4aXNDb25maWcucmFkaWFsQXhpcy5kb21haW4gPyBheGlzQ29uZmlnLnJhZGlhbEF4aXMuZG9tYWluIDogZXh0ZW50KS5yYW5nZShbIDAsIHJhZGl1cyBdKTtcbiAgICAgICAgICAgIGxpdmVDb25maWcubGF5b3V0LnJhZGlhbEF4aXMuZG9tYWluID0gcmFkaWFsU2NhbGUuZG9tYWluKCk7XG4gICAgICAgICAgICB2YXIgYW5ndWxhckRhdGFNZXJnZWQgPSDCtS51dGlsLmZsYXR0ZW5BcnJheShkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQudDtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIHZhciBpc09yZGluYWwgPSB0eXBlb2YgYW5ndWxhckRhdGFNZXJnZWRbMF0gPT09ICdzdHJpbmcnO1xuICAgICAgICAgICAgdmFyIHRpY2tzO1xuICAgICAgICAgICAgaWYgKGlzT3JkaW5hbCkge1xuICAgICAgICAgICAgICAgIGFuZ3VsYXJEYXRhTWVyZ2VkID0gwrUudXRpbC5kZWR1cGxpY2F0ZShhbmd1bGFyRGF0YU1lcmdlZCk7XG4gICAgICAgICAgICAgICAgdGlja3MgPSBhbmd1bGFyRGF0YU1lcmdlZC5zbGljZSgpO1xuICAgICAgICAgICAgICAgIGFuZ3VsYXJEYXRhTWVyZ2VkID0gZDMucmFuZ2UoYW5ndWxhckRhdGFNZXJnZWQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBkYXRhID0gZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gZDtcbiAgICAgICAgICAgICAgICAgICAgZC50ID0gWyBhbmd1bGFyRGF0YU1lcmdlZCBdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNTdGFja2VkKSByZXN1bHQueVN0YWNrID0gZC55U3RhY2s7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgaGFzT25seUxpbmVPckRvdFBsb3QgPSBkYXRhLmZpbHRlcihmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQuZ2VvbWV0cnkgPT09ICdMaW5lUGxvdCcgfHwgZC5nZW9tZXRyeSA9PT0gJ0RvdFBsb3QnO1xuICAgICAgICAgICAgfSkubGVuZ3RoID09PSBkYXRhLmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBuZWVkc0VuZFNwYWNpbmcgPSBheGlzQ29uZmlnLm5lZWRzRW5kU3BhY2luZyA9PT0gbnVsbCA/IGlzT3JkaW5hbCB8fCAhaGFzT25seUxpbmVPckRvdFBsb3QgOiBheGlzQ29uZmlnLm5lZWRzRW5kU3BhY2luZztcbiAgICAgICAgICAgIHZhciB1c2VQcm92aWRlZERvbWFpbiA9IGF4aXNDb25maWcuYW5ndWxhckF4aXMuZG9tYWluICYmIGF4aXNDb25maWcuYW5ndWxhckF4aXMuZG9tYWluICE9IMK1LkRBVEFFWFRFTlQgJiYgIWlzT3JkaW5hbCAmJiBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLmRvbWFpblswXSA+PSAwO1xuICAgICAgICAgICAgdmFyIGFuZ3VsYXJEb21haW4gPSB1c2VQcm92aWRlZERvbWFpbiA/IGF4aXNDb25maWcuYW5ndWxhckF4aXMuZG9tYWluIDogZDMuZXh0ZW50KGFuZ3VsYXJEYXRhTWVyZ2VkKTtcbiAgICAgICAgICAgIHZhciBhbmd1bGFyRG9tYWluU3RlcCA9IE1hdGguYWJzKGFuZ3VsYXJEYXRhTWVyZ2VkWzFdIC0gYW5ndWxhckRhdGFNZXJnZWRbMF0pO1xuICAgICAgICAgICAgaWYgKGhhc09ubHlMaW5lT3JEb3RQbG90ICYmICFpc09yZGluYWwpIGFuZ3VsYXJEb21haW5TdGVwID0gMDtcbiAgICAgICAgICAgIHZhciBhbmd1bGFyRG9tYWluV2l0aFBhZGRpbmcgPSBhbmd1bGFyRG9tYWluLnNsaWNlKCk7XG4gICAgICAgICAgICBpZiAobmVlZHNFbmRTcGFjaW5nICYmIGlzT3JkaW5hbCkgYW5ndWxhckRvbWFpbldpdGhQYWRkaW5nWzFdICs9IGFuZ3VsYXJEb21haW5TdGVwO1xuICAgICAgICAgICAgdmFyIHRpY2tDb3VudCA9IGF4aXNDb25maWcuYW5ndWxhckF4aXMudGlja3NDb3VudCB8fCA0O1xuICAgICAgICAgICAgaWYgKHRpY2tDb3VudCA+IDgpIHRpY2tDb3VudCA9IHRpY2tDb3VudCAvICh0aWNrQ291bnQgLyA4KSArIHRpY2tDb3VudCAlIDg7XG4gICAgICAgICAgICBpZiAoYXhpc0NvbmZpZy5hbmd1bGFyQXhpcy50aWNrc1N0ZXApIHtcbiAgICAgICAgICAgICAgICB0aWNrQ291bnQgPSAoYW5ndWxhckRvbWFpbldpdGhQYWRkaW5nWzFdIC0gYW5ndWxhckRvbWFpbldpdGhQYWRkaW5nWzBdKSAvIHRpY2tDb3VudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhbmd1bGFyVGlja3NTdGVwID0gYXhpc0NvbmZpZy5hbmd1bGFyQXhpcy50aWNrc1N0ZXAgfHwgKGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZ1sxXSAtIGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZ1swXSkgLyAodGlja0NvdW50ICogKGF4aXNDb25maWcubWlub3JUaWNrcyArIDEpKTtcbiAgICAgICAgICAgIGlmICh0aWNrcykgYW5ndWxhclRpY2tzU3RlcCA9IE1hdGgubWF4KE1hdGgucm91bmQoYW5ndWxhclRpY2tzU3RlcCksIDEpO1xuICAgICAgICAgICAgaWYgKCFhbmd1bGFyRG9tYWluV2l0aFBhZGRpbmdbMl0pIGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZ1syXSA9IGFuZ3VsYXJUaWNrc1N0ZXA7XG4gICAgICAgICAgICB2YXIgYW5ndWxhckF4aXNSYW5nZSA9IGQzLnJhbmdlLmFwcGx5KHRoaXMsIGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZyk7XG4gICAgICAgICAgICBhbmd1bGFyQXhpc1JhbmdlID0gYW5ndWxhckF4aXNSYW5nZS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZUZsb2F0KGQudG9QcmVjaXNpb24oMTIpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYW5ndWxhclNjYWxlID0gZDMuc2NhbGUubGluZWFyKCkuZG9tYWluKGFuZ3VsYXJEb21haW5XaXRoUGFkZGluZy5zbGljZSgwLCAyKSkucmFuZ2UoYXhpc0NvbmZpZy5kaXJlY3Rpb24gPT09ICdjbG9ja3dpc2UnID8gWyAwLCAzNjAgXSA6IFsgMzYwLCAwIF0pO1xuICAgICAgICAgICAgbGl2ZUNvbmZpZy5sYXlvdXQuYW5ndWxhckF4aXMuZG9tYWluID0gYW5ndWxhclNjYWxlLmRvbWFpbigpO1xuICAgICAgICAgICAgbGl2ZUNvbmZpZy5sYXlvdXQuYW5ndWxhckF4aXMuZW5kUGFkZGluZyA9IG5lZWRzRW5kU3BhY2luZyA/IGFuZ3VsYXJEb21haW5TdGVwIDogMDtcbiAgICAgICAgICAgIHN2ZyA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3QoJ3N2Zy5jaGFydC1yb290Jyk7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHN2ZyA9PT0gJ3VuZGVmaW5lZCcgfHwgc3ZnLmVtcHR5KCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2tlbGV0b24gPSBcIjxzdmcgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyBjbGFzcz0nY2hhcnQtcm9vdCc+JyArICc8ZyBjbGFzcz0nb3V0ZXItZ3JvdXAnPicgKyAnPGcgY2xhc3M9J2NoYXJ0LWdyb3VwJz4nICsgJzxjaXJjbGUgY2xhc3M9J2JhY2tncm91bmQtY2lyY2xlJz48L2NpcmNsZT4nICsgJzxnIGNsYXNzPSdnZW9tZXRyeS1ncm91cCc+PC9nPicgKyAnPGcgY2xhc3M9J3JhZGlhbCBheGlzLWdyb3VwJz4nICsgJzxjaXJjbGUgY2xhc3M9J291dHNpZGUtY2lyY2xlJz48L2NpcmNsZT4nICsgJzwvZz4nICsgJzxnIGNsYXNzPSdhbmd1bGFyIGF4aXMtZ3JvdXAnPjwvZz4nICsgJzxnIGNsYXNzPSdndWlkZXMtZ3JvdXAnPjxsaW5lPjwvbGluZT48Y2lyY2xlIHI9JzAnPjwvY2lyY2xlPjwvZz4nICsgJzwvZz4nICsgJzxnIGNsYXNzPSdsZWdlbmQtZ3JvdXAnPjwvZz4nICsgJzxnIGNsYXNzPSd0b29sdGlwcy1ncm91cCc+PC9nPicgKyAnPGcgY2xhc3M9J3RpdGxlLWdyb3VwJz48dGV4dD48L3RleHQ+PC9nPicgKyAnPC9nPicgKyAnPC9zdmc+XCI7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG5ldyBET01QYXJzZXIoKS5wYXJzZUZyb21TdHJpbmcoc2tlbGV0b24sICdhcHBsaWNhdGlvbi94bWwnKTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3U3ZnID0gdGhpcy5hcHBlbmRDaGlsZCh0aGlzLm93bmVyRG9jdW1lbnQuaW1wb3J0Tm9kZShkb2MuZG9jdW1lbnRFbGVtZW50LCB0cnVlKSk7XG4gICAgICAgICAgICAgICAgc3ZnID0gZDMuc2VsZWN0KG5ld1N2Zyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdmcuc2VsZWN0KCcuZ3VpZGVzLWdyb3VwJykuc3R5bGUoe1xuICAgICAgICAgICAgICAgICdwb2ludGVyLWV2ZW50cyc6ICdub25lJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdmcuc2VsZWN0KCcuYW5ndWxhci5heGlzLWdyb3VwJykuc3R5bGUoe1xuICAgICAgICAgICAgICAgICdwb2ludGVyLWV2ZW50cyc6ICdub25lJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdmcuc2VsZWN0KCcucmFkaWFsLmF4aXMtZ3JvdXAnKS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgJ3BvaW50ZXItZXZlbnRzJzogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBjaGFydEdyb3VwID0gc3ZnLnNlbGVjdCgnLmNoYXJ0LWdyb3VwJyk7XG4gICAgICAgICAgICB2YXIgbGluZVN0eWxlID0ge1xuICAgICAgICAgICAgICAgIGZpbGw6ICdub25lJyxcbiAgICAgICAgICAgICAgICBzdHJva2U6IGF4aXNDb25maWcudGlja0NvbG9yXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGZvbnRTdHlsZSA9IHtcbiAgICAgICAgICAgICAgICAnZm9udC1zaXplJzogYXhpc0NvbmZpZy5mb250LnNpemUsXG4gICAgICAgICAgICAgICAgJ2ZvbnQtZmFtaWx5JzogYXhpc0NvbmZpZy5mb250LmZhbWlseSxcbiAgICAgICAgICAgICAgICBmaWxsOiBheGlzQ29uZmlnLmZvbnQuY29sb3IsXG4gICAgICAgICAgICAgICAgJ3RleHQtc2hhZG93JzogWyAnLTFweCAwcHgnLCAnMXB4IC0xcHgnLCAnLTFweCAxcHgnLCAnMXB4IDFweCcgXS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJyAnICsgZCArICcgMCAnICsgYXhpc0NvbmZpZy5mb250Lm91dGxpbmVDb2xvcjtcbiAgICAgICAgICAgICAgICB9KS5qb2luKCcsJylcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgbGVnZW5kQ29udGFpbmVyO1xuICAgICAgICAgICAgaWYgKGF4aXNDb25maWcuc2hvd0xlZ2VuZCkge1xuICAgICAgICAgICAgICAgIGxlZ2VuZENvbnRhaW5lciA9IHN2Zy5zZWxlY3QoJy5sZWdlbmQtZ3JvdXAnKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlKCcgKyBbIHJhZGl1cywgYXhpc0NvbmZpZy5tYXJnaW4udG9wIF0gKyAnKSdcbiAgICAgICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6ICdibG9jaydcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB2YXIgZWxlbWVudHMgPSBkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXR1bUNsb25lID0gwrUudXRpbC5jbG9uZUpzb24oZCk7XG4gICAgICAgICAgICAgICAgICAgIGRhdHVtQ2xvbmUuc3ltYm9sID0gZC5nZW9tZXRyeSA9PT0gJ0RvdFBsb3QnID8gZC5kb3RUeXBlIHx8ICdjaXJjbGUnIDogZC5nZW9tZXRyeSAhPSAnTGluZVBsb3QnID8gJ3NxdWFyZScgOiAnbGluZSc7XG4gICAgICAgICAgICAgICAgICAgIGRhdHVtQ2xvbmUudmlzaWJsZUluTGVnZW5kID0gdHlwZW9mIGQudmlzaWJsZUluTGVnZW5kID09PSAndW5kZWZpbmVkJyB8fCBkLnZpc2libGVJbkxlZ2VuZDtcbiAgICAgICAgICAgICAgICAgICAgZGF0dW1DbG9uZS5jb2xvciA9IGQuZ2VvbWV0cnkgPT09ICdMaW5lUGxvdCcgPyBkLnN0cm9rZUNvbG9yIDogZC5jb2xvcjtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdHVtQ2xvbmU7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICDCtS5MZWdlbmQoKS5jb25maWcoe1xuICAgICAgICAgICAgICAgICAgICBkYXRhOiBkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZC5uYW1lIHx8ICdFbGVtZW50JyArIGk7XG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICBsZWdlbmRDb25maWc6IGV4dGVuZERlZXBBbGwoe30sXG4gICAgICAgICAgICAgICAgICAgICAgICDCtS5MZWdlbmQuZGVmYXVsdENvbmZpZygpLmxlZ2VuZENvbmZpZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXI6IGxlZ2VuZENvbnRhaW5lcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50czogZWxlbWVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV2ZXJzZU9yZGVyOiBheGlzQ29uZmlnLmxlZ2VuZC5yZXZlcnNlT3JkZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIH0pKCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVnZW5kQkJveCA9IGxlZ2VuZENvbnRhaW5lci5ub2RlKCkuZ2V0QkJveCgpO1xuICAgICAgICAgICAgICAgIHJhZGl1cyA9IE1hdGgubWluKGF4aXNDb25maWcud2lkdGggLSBsZWdlbmRCQm94LndpZHRoIC0gYXhpc0NvbmZpZy5tYXJnaW4ubGVmdCAtIGF4aXNDb25maWcubWFyZ2luLnJpZ2h0LCBheGlzQ29uZmlnLmhlaWdodCAtIGF4aXNDb25maWcubWFyZ2luLnRvcCAtIGF4aXNDb25maWcubWFyZ2luLmJvdHRvbSkgLyAyO1xuICAgICAgICAgICAgICAgIHJhZGl1cyA9IE1hdGgubWF4KDEwLCByYWRpdXMpO1xuICAgICAgICAgICAgICAgIGNoYXJ0Q2VudGVyID0gWyBheGlzQ29uZmlnLm1hcmdpbi5sZWZ0ICsgcmFkaXVzLCBheGlzQ29uZmlnLm1hcmdpbi50b3AgKyByYWRpdXMgXTtcbiAgICAgICAgICAgICAgICByYWRpYWxTY2FsZS5yYW5nZShbIDAsIHJhZGl1cyBdKTtcbiAgICAgICAgICAgICAgICBsaXZlQ29uZmlnLmxheW91dC5yYWRpYWxBeGlzLmRvbWFpbiA9IHJhZGlhbFNjYWxlLmRvbWFpbigpO1xuICAgICAgICAgICAgICAgIGxlZ2VuZENvbnRhaW5lci5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBbIGNoYXJ0Q2VudGVyWzBdICsgcmFkaXVzLCBjaGFydENlbnRlclsxXSAtIHJhZGl1cyBdICsgJyknKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbGVnZW5kQ29udGFpbmVyID0gc3ZnLnNlbGVjdCgnLmxlZ2VuZC1ncm91cCcpLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogJ25vbmUnXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdmcuYXR0cih7XG4gICAgICAgICAgICAgICAgd2lkdGg6IGF4aXNDb25maWcud2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBheGlzQ29uZmlnLmhlaWdodFxuICAgICAgICAgICAgfSkuc3R5bGUoe1xuICAgICAgICAgICAgICAgIG9wYWNpdHk6IGF4aXNDb25maWcub3BhY2l0eVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjaGFydEdyb3VwLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIGNoYXJ0Q2VudGVyICsgJyknKS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgY3Vyc29yOiAnY3Jvc3NoYWlyJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgY2VudGVyaW5nT2Zmc2V0ID0gWyAoYXhpc0NvbmZpZy53aWR0aCAtIChheGlzQ29uZmlnLm1hcmdpbi5sZWZ0ICsgYXhpc0NvbmZpZy5tYXJnaW4ucmlnaHQgKyByYWRpdXMgKiAyICsgKGxlZ2VuZEJCb3ggPyBsZWdlbmRCQm94LndpZHRoIDogMCkpKSAvIDIsIChheGlzQ29uZmlnLmhlaWdodCAtIChheGlzQ29uZmlnLm1hcmdpbi50b3AgKyBheGlzQ29uZmlnLm1hcmdpbi5ib3R0b20gKyByYWRpdXMgKiAyKSkgLyAyIF07XG4gICAgICAgICAgICBjZW50ZXJpbmdPZmZzZXRbMF0gPSBNYXRoLm1heCgwLCBjZW50ZXJpbmdPZmZzZXRbMF0pO1xuICAgICAgICAgICAgY2VudGVyaW5nT2Zmc2V0WzFdID0gTWF0aC5tYXgoMCwgY2VudGVyaW5nT2Zmc2V0WzFdKTtcbiAgICAgICAgICAgIHN2Zy5zZWxlY3QoJy5vdXRlci1ncm91cCcpLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIGNlbnRlcmluZ09mZnNldCArICcpJyk7XG4gICAgICAgICAgICBpZiAoYXhpc0NvbmZpZy50aXRsZSAmJiBheGlzQ29uZmlnLnRpdGxlLnRleHQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGl0bGUgPSBzdmcuc2VsZWN0KCdnLnRpdGxlLWdyb3VwIHRleHQnKS5zdHlsZShmb250U3R5bGUpLnRleHQoYXhpc0NvbmZpZy50aXRsZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGl0bGVCQm94ID0gdGl0bGUubm9kZSgpLmdldEJCb3goKTtcbiAgICAgICAgICAgICAgICB0aXRsZS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgeDogY2hhcnRDZW50ZXJbMF0gLSB0aXRsZUJCb3gud2lkdGggLyAyLFxuICAgICAgICAgICAgICAgICAgICB5OiBjaGFydENlbnRlclsxXSAtIHJhZGl1cyAtIDIwXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmFkaWFsQXhpcyA9IHN2Zy5zZWxlY3QoJy5yYWRpYWwuYXhpcy1ncm91cCcpO1xuICAgICAgICAgICAgaWYgKGF4aXNDb25maWcucmFkaWFsQXhpcy5ncmlkTGluZXNWaXNpYmxlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGdyaWRDaXJjbGVzID0gcmFkaWFsQXhpcy5zZWxlY3RBbGwoJ2NpcmNsZS5ncmlkLWNpcmNsZScpLmRhdGEocmFkaWFsU2NhbGUudGlja3MoNSkpO1xuICAgICAgICAgICAgICAgIGdyaWRDaXJjbGVzLmVudGVyKCkuYXBwZW5kKCdjaXJjbGUnKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ2dyaWQtY2lyY2xlJ1xuICAgICAgICAgICAgICAgIH0pLnN0eWxlKGxpbmVTdHlsZSk7XG4gICAgICAgICAgICAgICAgZ3JpZENpcmNsZXMuYXR0cigncicsIHJhZGlhbFNjYWxlKTtcbiAgICAgICAgICAgICAgICBncmlkQ2lyY2xlcy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByYWRpYWxBeGlzLnNlbGVjdCgnY2lyY2xlLm91dHNpZGUtY2lyY2xlJykuYXR0cih7XG4gICAgICAgICAgICAgICAgcjogcmFkaXVzXG4gICAgICAgICAgICB9KS5zdHlsZShsaW5lU3R5bGUpO1xuICAgICAgICAgICAgdmFyIGJhY2tncm91bmRDaXJjbGUgPSBzdmcuc2VsZWN0KCdjaXJjbGUuYmFja2dyb3VuZC1jaXJjbGUnKS5hdHRyKHtcbiAgICAgICAgICAgICAgICByOiByYWRpdXNcbiAgICAgICAgICAgIH0pLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBmaWxsOiBheGlzQ29uZmlnLmJhY2tncm91bmRDb2xvcixcbiAgICAgICAgICAgICAgICBzdHJva2U6IGF4aXNDb25maWcuc3Ryb2tlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGN1cnJlbnRBbmdsZShkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFuZ3VsYXJTY2FsZShkKSAlIDM2MCArIGF4aXNDb25maWcub3JpZW50YXRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYXhpc0NvbmZpZy5yYWRpYWxBeGlzLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXhpcyA9IGQzLnN2Zy5heGlzKCkuc2NhbGUocmFkaWFsU2NhbGUpLnRpY2tzKDUpLnRpY2tTaXplKDUpO1xuICAgICAgICAgICAgICAgIHJhZGlhbEF4aXMuY2FsbChheGlzKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAncm90YXRlKCcgKyBheGlzQ29uZmlnLnJhZGlhbEF4aXMub3JpZW50YXRpb24gKyAnKSdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByYWRpYWxBeGlzLnNlbGVjdEFsbCgnLmRvbWFpbicpLnN0eWxlKGxpbmVTdHlsZSk7XG4gICAgICAgICAgICAgICAgcmFkaWFsQXhpcy5zZWxlY3RBbGwoJ2c+dGV4dCcpLnRleHQoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50ZXh0Q29udGVudCArIGF4aXNDb25maWcucmFkaWFsQXhpcy50aWNrc1N1ZmZpeDtcbiAgICAgICAgICAgICAgICB9KS5zdHlsZShmb250U3R5bGUpLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ3N0YXJ0J1xuICAgICAgICAgICAgICAgIH0pLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgICAgICAgICBkeDogMCxcbiAgICAgICAgICAgICAgICAgICAgZHk6IDAsXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF4aXNDb25maWcucmFkaWFsQXhpcy50aWNrT3JpZW50YXRpb24gPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAncm90YXRlKCcgKyAtYXhpc0NvbmZpZy5yYWRpYWxBeGlzLm9yaWVudGF0aW9uICsgJykgdHJhbnNsYXRlKCcgKyBbIDAsIGZvbnRTdHlsZVsnZm9udC1zaXplJ10gXSArICcpJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgWyAwLCBmb250U3R5bGVbJ2ZvbnQtc2l6ZSddIF0gKyAnKSc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByYWRpYWxBeGlzLnNlbGVjdEFsbCgnZz5saW5lJykuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICBzdHJva2U6ICdibGFjaydcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhbmd1bGFyQXhpcyA9IHN2Zy5zZWxlY3QoJy5hbmd1bGFyLmF4aXMtZ3JvdXAnKS5zZWxlY3RBbGwoJ2cuYW5ndWxhci10aWNrJykuZGF0YShhbmd1bGFyQXhpc1JhbmdlKTtcbiAgICAgICAgICAgIHZhciBhbmd1bGFyQXhpc0VudGVyID0gYW5ndWxhckF4aXMuZW50ZXIoKS5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdhbmd1bGFyLXRpY2snLCB0cnVlKTtcbiAgICAgICAgICAgIGFuZ3VsYXJBeGlzLmF0dHIoe1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3JvdGF0ZSgnICsgY3VycmVudEFuZ2xlKGQsIGkpICsgJyknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLnZpc2libGUgPyAnYmxvY2snIDogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGFuZ3VsYXJBeGlzLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIGFuZ3VsYXJBeGlzRW50ZXIuYXBwZW5kKCdsaW5lJykuY2xhc3NlZCgnZ3JpZC1saW5lJywgdHJ1ZSkuY2xhc3NlZCgnbWFqb3InLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGkgJSAoYXhpc0NvbmZpZy5taW5vclRpY2tzICsgMSkgPT0gMDtcbiAgICAgICAgICAgIH0pLmNsYXNzZWQoJ21pbm9yJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAhKGkgJSAoYXhpc0NvbmZpZy5taW5vclRpY2tzICsgMSkgPT0gMCk7XG4gICAgICAgICAgICB9KS5zdHlsZShsaW5lU3R5bGUpO1xuICAgICAgICAgICAgYW5ndWxhckF4aXNFbnRlci5zZWxlY3RBbGwoJy5taW5vcicpLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBzdHJva2U6IGF4aXNDb25maWcubWlub3JUaWNrQ29sb3JcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYW5ndWxhckF4aXMuc2VsZWN0KCdsaW5lLmdyaWQtbGluZScpLmF0dHIoe1xuICAgICAgICAgICAgICAgIHgxOiBheGlzQ29uZmlnLnRpY2tMZW5ndGggPyByYWRpdXMgLSBheGlzQ29uZmlnLnRpY2tMZW5ndGggOiAwLFxuICAgICAgICAgICAgICAgIHgyOiByYWRpdXNcbiAgICAgICAgICAgIH0pLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBkaXNwbGF5OiBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLmdyaWRMaW5lc1Zpc2libGUgPyAnYmxvY2snIDogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGFuZ3VsYXJBeGlzRW50ZXIuYXBwZW5kKCd0ZXh0JykuY2xhc3NlZCgnYXhpcy10ZXh0JywgdHJ1ZSkuc3R5bGUoZm9udFN0eWxlKTtcbiAgICAgICAgICAgIHZhciB0aWNrc1RleHQgPSBhbmd1bGFyQXhpcy5zZWxlY3QoJ3RleHQuYXhpcy10ZXh0JykuYXR0cih7XG4gICAgICAgICAgICAgICAgeDogcmFkaXVzICsgYXhpc0NvbmZpZy5sYWJlbE9mZnNldCxcbiAgICAgICAgICAgICAgICBkeTogTUlEX1NISUZUICsgJ2VtJyxcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFuZ2xlID0gY3VycmVudEFuZ2xlKGQsIGkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmFkID0gcmFkaXVzICsgYXhpc0NvbmZpZy5sYWJlbE9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG9yaWVudCA9IGF4aXNDb25maWcuYW5ndWxhckF4aXMudGlja09yaWVudGF0aW9uO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3JpZW50ID09ICdob3Jpem9udGFsJykgcmV0dXJuICdyb3RhdGUoJyArIC1hbmdsZSArICcgJyArIHJhZCArICcgMCknOyBlbHNlIGlmIChvcmllbnQgPT0gJ3JhZGlhbCcpIHJldHVybiBhbmdsZSA8IDI3MCAmJiBhbmdsZSA+IDkwID8gJ3JvdGF0ZSgxODAgJyArIHJhZCArICcgMCknIDogbnVsbDsgZWxzZSByZXR1cm4gJ3JvdGF0ZSgnICsgKGFuZ2xlIDw9IDE4MCAmJiBhbmdsZSA+IDAgPyAtOTAgOiA5MCkgKyAnICcgKyByYWQgKyAnIDApJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZScsXG4gICAgICAgICAgICAgICAgZGlzcGxheTogYXhpc0NvbmZpZy5hbmd1bGFyQXhpcy5sYWJlbHNWaXNpYmxlID8gJ2Jsb2NrJyA6ICdub25lJ1xuICAgICAgICAgICAgfSkudGV4dChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgJSAoYXhpc0NvbmZpZy5taW5vclRpY2tzICsgMSkgIT0gMCkgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgIGlmICh0aWNrcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGlja3NbZF0gKyBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLnRpY2tzU3VmZml4O1xuICAgICAgICAgICAgICAgIH0gZWxzZSByZXR1cm4gZCArIGF4aXNDb25maWcuYW5ndWxhckF4aXMudGlja3NTdWZmaXg7XG4gICAgICAgICAgICB9KS5zdHlsZShmb250U3R5bGUpO1xuICAgICAgICAgICAgaWYgKGF4aXNDb25maWcuYW5ndWxhckF4aXMucmV3cml0ZVRpY2tzKSB0aWNrc1RleHQudGV4dChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgJSAoYXhpc0NvbmZpZy5taW5vclRpY2tzICsgMSkgIT0gMCkgcmV0dXJuICcnO1xuICAgICAgICAgICAgICAgIHJldHVybiBheGlzQ29uZmlnLmFuZ3VsYXJBeGlzLnJld3JpdGVUaWNrcyh0aGlzLnRleHRDb250ZW50LCBpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIHJpZ2h0bW9zdFRpY2tFbmRYID0gZDMubWF4KGNoYXJ0R3JvdXAuc2VsZWN0QWxsKCcuYW5ndWxhci10aWNrIHRleHQnKVswXS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBkLmdldENUTSgpLmUgKyBkLmdldEJCb3goKS53aWR0aDtcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIGxlZ2VuZENvbnRhaW5lci5hdHRyKHtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIFsgcmFkaXVzICsgcmlnaHRtb3N0VGlja0VuZFgsIGF4aXNDb25maWcubWFyZ2luLnRvcCBdICsgJyknXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBoYXNHZW9tZXRyeSA9IHN2Zy5zZWxlY3QoJ2cuZ2VvbWV0cnktZ3JvdXAnKS5zZWxlY3RBbGwoJ2cnKS5zaXplKCkgPiAwO1xuICAgICAgICAgICAgdmFyIGdlb21ldHJ5Q29udGFpbmVyID0gc3ZnLnNlbGVjdCgnZy5nZW9tZXRyeS1ncm91cCcpLnNlbGVjdEFsbCgnZy5nZW9tZXRyeScpLmRhdGEoZGF0YSk7XG4gICAgICAgICAgICBnZW9tZXRyeUNvbnRhaW5lci5lbnRlcigpLmFwcGVuZCgnZycpLmF0dHIoe1xuICAgICAgICAgICAgICAgICdjbGFzcyc6IGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdnZW9tZXRyeSBnZW9tZXRyeScgKyBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZ2VvbWV0cnlDb250YWluZXIuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICAgICAgaWYgKGRhdGFbMF0gfHwgaGFzR2VvbWV0cnkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZ2VvbWV0cnlDb25maWdzID0gW107XG4gICAgICAgICAgICAgICAgZGF0YS5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGdlb21ldHJ5Q29uZmlnID0ge307XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnLnJhZGlhbFNjYWxlID0gcmFkaWFsU2NhbGU7XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnLmFuZ3VsYXJTY2FsZSA9IGFuZ3VsYXJTY2FsZTtcbiAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cnlDb25maWcuY29udGFpbmVyID0gZ2VvbWV0cnlDb250YWluZXIuZmlsdGVyKGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlCID09IGk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBnZW9tZXRyeUNvbmZpZy5nZW9tZXRyeSA9IGQuZ2VvbWV0cnk7XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnLm9yaWVudGF0aW9uID0gYXhpc0NvbmZpZy5vcmllbnRhdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cnlDb25maWcuZGlyZWN0aW9uID0gYXhpc0NvbmZpZy5kaXJlY3Rpb247XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnLmluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cnlDb25maWdzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5Q29uZmlnOiBnZW9tZXRyeUNvbmZpZ1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB2YXIgZ2VvbWV0cnlDb25maWdzR3JvdXBlZCA9IGQzLm5lc3QoKS5rZXkoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIGQuZGF0YS5ncm91cElkICE9ICd1bmRlZmluZWQnIHx8ICd1bnN0YWNrZWQnO1xuICAgICAgICAgICAgICAgIH0pLmVudHJpZXMoZ2VvbWV0cnlDb25maWdzKTtcbiAgICAgICAgICAgICAgICB2YXIgZ2VvbWV0cnlDb25maWdzR3JvdXBlZDIgPSBbXTtcbiAgICAgICAgICAgICAgICBnZW9tZXRyeUNvbmZpZ3NHcm91cGVkLmZvckVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZC5rZXkgPT09ICd1bnN0YWNrZWQnKSBnZW9tZXRyeUNvbmZpZ3NHcm91cGVkMiA9IGdlb21ldHJ5Q29uZmlnc0dyb3VwZWQyLmNvbmNhdChkLnZhbHVlcy5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsgZCBdO1xuICAgICAgICAgICAgICAgICAgICB9KSk7IGVsc2UgZ2VvbWV0cnlDb25maWdzR3JvdXBlZDIucHVzaChkLnZhbHVlcyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZ2VvbWV0cnlDb25maWdzR3JvdXBlZDIuZm9yRWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBnZW9tZXRyeTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZCkpIGdlb21ldHJ5ID0gZFswXS5nZW9tZXRyeUNvbmZpZy5nZW9tZXRyeTsgZWxzZSBnZW9tZXRyeSA9IGQuZ2VvbWV0cnlDb25maWcuZ2VvbWV0cnk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmaW5hbEdlb21ldHJ5Q29uZmlnID0gZC5tYXAoZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXh0ZW5kRGVlcEFsbCjCtVtnZW9tZXRyeV0uZGVmYXVsdENvbmZpZygpLCBkQik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICDCtVtnZW9tZXRyeV0oKS5jb25maWcoZmluYWxHZW9tZXRyeUNvbmZpZykoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBndWlkZXMgPSBzdmcuc2VsZWN0KCcuZ3VpZGVzLWdyb3VwJyk7XG4gICAgICAgICAgICB2YXIgdG9vbHRpcENvbnRhaW5lciA9IHN2Zy5zZWxlY3QoJy50b29sdGlwcy1ncm91cCcpO1xuICAgICAgICAgICAgdmFyIGFuZ3VsYXJUb29sdGlwID0gwrUudG9vbHRpcFBhbmVsKCkuY29uZmlnKHtcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IHRvb2x0aXBDb250YWluZXIsXG4gICAgICAgICAgICAgICAgZm9udFNpemU6IDhcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgICAgICB2YXIgcmFkaWFsVG9vbHRpcCA9IMK1LnRvb2x0aXBQYW5lbCgpLmNvbmZpZyh7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiB0b29sdGlwQ29udGFpbmVyLFxuICAgICAgICAgICAgICAgIGZvbnRTaXplOiA4XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICAgICAgdmFyIGdlb21ldHJ5VG9vbHRpcCA9IMK1LnRvb2x0aXBQYW5lbCgpLmNvbmZpZyh7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiB0b29sdGlwQ29udGFpbmVyLFxuICAgICAgICAgICAgICAgIGhhc1RpY2s6IHRydWVcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgICAgICB2YXIgYW5ndWxhclZhbHVlLCByYWRpYWxWYWx1ZTtcbiAgICAgICAgICAgIGlmICghaXNPcmRpbmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFuZ3VsYXJHdWlkZUxpbmUgPSBndWlkZXMuc2VsZWN0KCdsaW5lJykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHgxOiAwLFxuICAgICAgICAgICAgICAgICAgICB5MTogMCxcbiAgICAgICAgICAgICAgICAgICAgeTI6IDBcbiAgICAgICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogJ2dyZXknLFxuICAgICAgICAgICAgICAgICAgICAncG9pbnRlci1ldmVudHMnOiAnbm9uZSdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBjaGFydEdyb3VwLm9uKCdtb3VzZW1vdmUuYW5ndWxhci1ndWlkZScsIGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1vdXNlQW5nbGUgPSDCtS51dGlsLmdldE1vdXNlUG9zKGJhY2tncm91bmRDaXJjbGUpLmFuZ2xlO1xuICAgICAgICAgICAgICAgICAgICBhbmd1bGFyR3VpZGVMaW5lLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgeDI6IC1yYWRpdXMsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICdyb3RhdGUoJyArIG1vdXNlQW5nbGUgKyAnKSdcbiAgICAgICAgICAgICAgICAgICAgfSkuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogLjVcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhbmdsZVdpdGhPcmlnaW5PZmZzZXQgPSAobW91c2VBbmdsZSArIDE4MCArIDM2MCAtIGF4aXNDb25maWcub3JpZW50YXRpb24pICUgMzYwO1xuICAgICAgICAgICAgICAgICAgICBhbmd1bGFyVmFsdWUgPSBhbmd1bGFyU2NhbGUuaW52ZXJ0KGFuZ2xlV2l0aE9yaWdpbk9mZnNldCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3MgPSDCtS51dGlsLmNvbnZlcnRUb0NhcnRlc2lhbihyYWRpdXMgKyAxMiwgbW91c2VBbmdsZSArIDE4MCk7XG4gICAgICAgICAgICAgICAgICAgIGFuZ3VsYXJUb29sdGlwLnRleHQowrUudXRpbC5yb3VuZChhbmd1bGFyVmFsdWUpKS5tb3ZlKFsgcG9zWzBdICsgY2hhcnRDZW50ZXJbMF0sIHBvc1sxXSArIGNoYXJ0Q2VudGVyWzFdIF0pO1xuICAgICAgICAgICAgICAgIH0pLm9uKCdtb3VzZW91dC5hbmd1bGFyLWd1aWRlJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICBndWlkZXMuc2VsZWN0KCdsaW5lJykuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhbmd1bGFyR3VpZGVDaXJjbGUgPSBndWlkZXMuc2VsZWN0KCdjaXJjbGUnKS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgc3Ryb2tlOiAnZ3JleScsXG4gICAgICAgICAgICAgICAgZmlsbDogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNoYXJ0R3JvdXAub24oJ21vdXNlbW92ZS5yYWRpYWwtZ3VpZGUnLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHIgPSDCtS51dGlsLmdldE1vdXNlUG9zKGJhY2tncm91bmRDaXJjbGUpLnJhZGl1cztcbiAgICAgICAgICAgICAgICBhbmd1bGFyR3VpZGVDaXJjbGUuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHI6IHJcbiAgICAgICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IC41XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmFkaWFsVmFsdWUgPSByYWRpYWxTY2FsZS5pbnZlcnQowrUudXRpbC5nZXRNb3VzZVBvcyhiYWNrZ3JvdW5kQ2lyY2xlKS5yYWRpdXMpO1xuICAgICAgICAgICAgICAgIHZhciBwb3MgPSDCtS51dGlsLmNvbnZlcnRUb0NhcnRlc2lhbihyLCBheGlzQ29uZmlnLnJhZGlhbEF4aXMub3JpZW50YXRpb24pO1xuICAgICAgICAgICAgICAgIHJhZGlhbFRvb2x0aXAudGV4dCjCtS51dGlsLnJvdW5kKHJhZGlhbFZhbHVlKSkubW92ZShbIHBvc1swXSArIGNoYXJ0Q2VudGVyWzBdLCBwb3NbMV0gKyBjaGFydENlbnRlclsxXSBdKTtcbiAgICAgICAgICAgIH0pLm9uKCdtb3VzZW91dC5yYWRpYWwtZ3VpZGUnLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgYW5ndWxhckd1aWRlQ2lyY2xlLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGdlb21ldHJ5VG9vbHRpcC5oaWRlKCk7XG4gICAgICAgICAgICAgICAgYW5ndWxhclRvb2x0aXAuaGlkZSgpO1xuICAgICAgICAgICAgICAgIHJhZGlhbFRvb2x0aXAuaGlkZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBzdmcuc2VsZWN0QWxsKCcuZ2VvbWV0cnktZ3JvdXAgLm1hcmsnKS5vbignbW91c2VvdmVyLnRvb2x0aXAnLCBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgIHZhciBjb2xvciA9IHRoaXMuc3R5bGUuZmlsbDtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q29sb3IgPSAnYmxhY2snO1xuICAgICAgICAgICAgICAgIHZhciBvcGFjaXR5ID0gdGhpcy5zdHlsZS5vcGFjaXR5IHx8IDE7XG4gICAgICAgICAgICAgICAgZWwuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdkYXRhLW9wYWNpdHknOiBvcGFjaXR5XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbG9yICYmIGNvbG9yICE9PSAnbm9uZScpIHtcbiAgICAgICAgICAgICAgICAgICAgZWwuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICAnZGF0YS1maWxsJzogY29sb3JcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIG5ld0NvbG9yID0gZDMuaHNsKGNvbG9yKS5kYXJrZXIoKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBlbC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxsOiBuZXdDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ZXh0RGF0YSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHQ6IMK1LnV0aWwucm91bmQoZFswXSksXG4gICAgICAgICAgICAgICAgICAgICAgICByOiDCtS51dGlsLnJvdW5kKGRbMV0pXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc09yZGluYWwpIHRleHREYXRhLnQgPSB0aWNrc1tkWzBdXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRleHQgPSAndDogJyArIHRleHREYXRhLnQgKyAnLCByOiAnICsgdGV4dERhdGEucjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJib3ggPSB0aGlzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3ZnQkJveCA9IHN2Zy5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwb3MgPSBbIGJib3gubGVmdCArIGJib3gud2lkdGggLyAyIC0gY2VudGVyaW5nT2Zmc2V0WzBdIC0gc3ZnQkJveC5sZWZ0LCBiYm94LnRvcCArIGJib3guaGVpZ2h0IC8gMiAtIGNlbnRlcmluZ09mZnNldFsxXSAtIHN2Z0JCb3gudG9wIF07XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5VG9vbHRpcC5jb25maWcoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I6IG5ld0NvbG9yXG4gICAgICAgICAgICAgICAgICAgIH0pLnRleHQodGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJ5VG9vbHRpcC5tb3ZlKHBvcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29sb3IgPSB0aGlzLnN0eWxlLnN0cm9rZSB8fCAnYmxhY2snO1xuICAgICAgICAgICAgICAgICAgICBlbC5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICdkYXRhLXN0cm9rZSc6IGNvbG9yXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBuZXdDb2xvciA9IGQzLmhzbChjb2xvcikuZGFya2VyKCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgZWwuc3R5bGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlOiBuZXdDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IDFcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkub24oJ21vdXNlbW92ZS50b29sdGlwJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIGlmIChkMy5ldmVudC53aGljaCAhPSAwKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKGQzLnNlbGVjdCh0aGlzKS5hdHRyKCdkYXRhLWZpbGwnKSkgZ2VvbWV0cnlUb29sdGlwLnNob3coKTtcbiAgICAgICAgICAgIH0pLm9uKCdtb3VzZW91dC50b29sdGlwJywgZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIGdlb21ldHJ5VG9vbHRpcC5oaWRlKCk7XG4gICAgICAgICAgICAgICAgdmFyIGVsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgIHZhciBmaWxsQ29sb3IgPSBlbC5hdHRyKCdkYXRhLWZpbGwnKTtcbiAgICAgICAgICAgICAgICBpZiAoZmlsbENvbG9yKSBlbC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIGZpbGw6IGZpbGxDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogZWwuYXR0cignZGF0YS1vcGFjaXR5JylcbiAgICAgICAgICAgICAgICB9KTsgZWxzZSBlbC5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogZWwuYXR0cignZGF0YS1zdHJva2UnKSxcbiAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogZWwuYXR0cignZGF0YS1vcGFjaXR5JylcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGV4cG9ydHM7XG4gICAgfVxuICAgIGV4cG9ydHMucmVuZGVyID0gZnVuY3Rpb24oX2NvbnRhaW5lcikge1xuICAgICAgICByZW5kZXIoX2NvbnRhaW5lcik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZXhwb3J0cy5jb25maWcgPSBmdW5jdGlvbihfeCkge1xuICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjb25maWc7XG4gICAgICAgIHZhciB4Q2xvbmUgPSDCtS51dGlsLmNsb25lSnNvbihfeCk7XG4gICAgICAgIHhDbG9uZS5kYXRhLmZvckVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgaWYgKCFjb25maWcuZGF0YVtpXSkgY29uZmlnLmRhdGFbaV0gPSB7fTtcbiAgICAgICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnLmRhdGFbaV0sIMK1LkF4aXMuZGVmYXVsdENvbmZpZygpLmRhdGFbMF0pO1xuICAgICAgICAgICAgZXh0ZW5kRGVlcEFsbChjb25maWcuZGF0YVtpXSwgZCk7XG4gICAgICAgIH0pO1xuICAgICAgICBleHRlbmREZWVwQWxsKGNvbmZpZy5sYXlvdXQsIMK1LkF4aXMuZGVmYXVsdENvbmZpZygpLmxheW91dCk7XG4gICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnLmxheW91dCwgeENsb25lLmxheW91dCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZXhwb3J0cy5nZXRMaXZlQ29uZmlnID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBsaXZlQ29uZmlnO1xuICAgIH07XG4gICAgZXhwb3J0cy5nZXRpbnB1dENvbmZpZyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gaW5wdXRDb25maWc7XG4gICAgfTtcbiAgICBleHBvcnRzLnJhZGlhbFNjYWxlID0gZnVuY3Rpb24oX3gpIHtcbiAgICAgICAgcmV0dXJuIHJhZGlhbFNjYWxlO1xuICAgIH07XG4gICAgZXhwb3J0cy5hbmd1bGFyU2NhbGUgPSBmdW5jdGlvbihfeCkge1xuICAgICAgICByZXR1cm4gYW5ndWxhclNjYWxlO1xuICAgIH07XG4gICAgZXhwb3J0cy5zdmcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHN2ZztcbiAgICB9O1xuICAgIGQzLnJlYmluZChleHBvcnRzLCBkaXNwYXRjaCwgJ29uJyk7XG4gICAgcmV0dXJuIGV4cG9ydHM7XG59O1xuXG7CtS5BeGlzLmRlZmF1bHRDb25maWcgPSBmdW5jdGlvbihkLCBpKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZGF0YTogWyB7XG4gICAgICAgICAgICB0OiBbIDEsIDIsIDMsIDQgXSxcbiAgICAgICAgICAgIHI6IFsgMTAsIDExLCAxMiwgMTMgXSxcbiAgICAgICAgICAgIG5hbWU6ICdMaW5lMScsXG4gICAgICAgICAgICBnZW9tZXRyeTogJ0xpbmVQbG90JyxcbiAgICAgICAgICAgIGNvbG9yOiBudWxsLFxuICAgICAgICAgICAgc3Ryb2tlRGFzaDogJ3NvbGlkJyxcbiAgICAgICAgICAgIHN0cm9rZUNvbG9yOiBudWxsLFxuICAgICAgICAgICAgc3Ryb2tlU2l6ZTogJzEnLFxuICAgICAgICAgICAgdmlzaWJsZUluTGVnZW5kOiB0cnVlLFxuICAgICAgICAgICAgb3BhY2l0eTogMVxuICAgICAgICB9IF0sXG4gICAgICAgIGxheW91dDoge1xuICAgICAgICAgICAgZGVmYXVsdENvbG9yUmFuZ2U6IGQzLnNjYWxlLmNhdGVnb3J5MTAoKS5yYW5nZSgpLFxuICAgICAgICAgICAgdGl0bGU6IG51bGwsXG4gICAgICAgICAgICBoZWlnaHQ6IDQ1MCxcbiAgICAgICAgICAgIHdpZHRoOiA1MDAsXG4gICAgICAgICAgICBtYXJnaW46IHtcbiAgICAgICAgICAgICAgICB0b3A6IDQwLFxuICAgICAgICAgICAgICAgIHJpZ2h0OiA0MCxcbiAgICAgICAgICAgICAgICBib3R0b206IDQwLFxuICAgICAgICAgICAgICAgIGxlZnQ6IDQwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZm9udDoge1xuICAgICAgICAgICAgICAgIHNpemU6IDEyLFxuICAgICAgICAgICAgICAgIGNvbG9yOiAnZ3JheScsXG4gICAgICAgICAgICAgICAgb3V0bGluZUNvbG9yOiAnd2hpdGUnLFxuICAgICAgICAgICAgICAgIGZhbWlseTogJ1RhaG9tYSwgc2Fucy1zZXJpZidcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkaXJlY3Rpb246ICdjbG9ja3dpc2UnLFxuICAgICAgICAgICAgb3JpZW50YXRpb246IDAsXG4gICAgICAgICAgICBsYWJlbE9mZnNldDogMTAsXG4gICAgICAgICAgICByYWRpYWxBeGlzOiB7XG4gICAgICAgICAgICAgICAgZG9tYWluOiBudWxsLFxuICAgICAgICAgICAgICAgIG9yaWVudGF0aW9uOiAtNDUsXG4gICAgICAgICAgICAgICAgdGlja3NTdWZmaXg6ICcnLFxuICAgICAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZ3JpZExpbmVzVmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICB0aWNrT3JpZW50YXRpb246ICdob3Jpem9udGFsJyxcbiAgICAgICAgICAgICAgICByZXdyaXRlVGlja3M6IG51bGxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhbmd1bGFyQXhpczoge1xuICAgICAgICAgICAgICAgIGRvbWFpbjogWyAwLCAzNjAgXSxcbiAgICAgICAgICAgICAgICB0aWNrc1N1ZmZpeDogJycsXG4gICAgICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBncmlkTGluZXNWaXNpYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGxhYmVsc1Zpc2libGU6IHRydWUsXG4gICAgICAgICAgICAgICAgdGlja09yaWVudGF0aW9uOiAnaG9yaXpvbnRhbCcsXG4gICAgICAgICAgICAgICAgcmV3cml0ZVRpY2tzOiBudWxsLFxuICAgICAgICAgICAgICAgIHRpY2tzQ291bnQ6IG51bGwsXG4gICAgICAgICAgICAgICAgdGlja3NTdGVwOiBudWxsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWlub3JUaWNrczogMCxcbiAgICAgICAgICAgIHRpY2tMZW5ndGg6IG51bGwsXG4gICAgICAgICAgICB0aWNrQ29sb3I6ICdzaWx2ZXInLFxuICAgICAgICAgICAgbWlub3JUaWNrQ29sb3I6ICcjZWVlJyxcbiAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogJ25vbmUnLFxuICAgICAgICAgICAgbmVlZHNFbmRTcGFjaW5nOiBudWxsLFxuICAgICAgICAgICAgc2hvd0xlZ2VuZDogdHJ1ZSxcbiAgICAgICAgICAgIGxlZ2VuZDoge1xuICAgICAgICAgICAgICAgIHJldmVyc2VPcmRlcjogZmFsc2VcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgIH1cbiAgICB9O1xuICAgIHJldHVybiBjb25maWc7XG59O1xuXG7CtS51dGlsID0ge307XG5cbsK1LkRBVEFFWFRFTlQgPSAnZGF0YUV4dGVudCc7XG5cbsK1LkFSRUEgPSAnQXJlYUNoYXJ0JztcblxuwrUuTElORSA9ICdMaW5lUGxvdCc7XG5cbsK1LkRPVCA9ICdEb3RQbG90JztcblxuwrUuQkFSID0gJ0JhckNoYXJ0JztcblxuwrUudXRpbC5fb3ZlcnJpZGUgPSBmdW5jdGlvbihfb2JqQSwgX29iakIpIHtcbiAgICBmb3IgKHZhciB4IGluIF9vYmpBKSBpZiAoeCBpbiBfb2JqQikgX29iakJbeF0gPSBfb2JqQVt4XTtcbn07XG5cbsK1LnV0aWwuX2V4dGVuZCA9IGZ1bmN0aW9uKF9vYmpBLCBfb2JqQikge1xuICAgIGZvciAodmFyIHggaW4gX29iakEpIF9vYmpCW3hdID0gX29iakFbeF07XG59O1xuXG7CtS51dGlsLl9ybmRTbmQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gTWF0aC5yYW5kb20oKSAqIDIgLSAxICsgKE1hdGgucmFuZG9tKCkgKiAyIC0gMSkgKyAoTWF0aC5yYW5kb20oKSAqIDIgLSAxKTtcbn07XG5cbsK1LnV0aWwuZGF0YUZyb21FcXVhdGlvbjIgPSBmdW5jdGlvbihfZXF1YXRpb24sIF9zdGVwKSB7XG4gICAgdmFyIHN0ZXAgPSBfc3RlcCB8fCA2O1xuICAgIHZhciBkYXRhID0gZDMucmFuZ2UoMCwgMzYwICsgc3RlcCwgc3RlcCkubWFwKGZ1bmN0aW9uKGRlZywgaW5kZXgpIHtcbiAgICAgICAgdmFyIHRoZXRhID0gZGVnICogTWF0aC5QSSAvIDE4MDtcbiAgICAgICAgdmFyIHJhZGl1cyA9IF9lcXVhdGlvbih0aGV0YSk7XG4gICAgICAgIHJldHVybiBbIGRlZywgcmFkaXVzIF07XG4gICAgfSk7XG4gICAgcmV0dXJuIGRhdGE7XG59O1xuXG7CtS51dGlsLmRhdGFGcm9tRXF1YXRpb24gPSBmdW5jdGlvbihfZXF1YXRpb24sIF9zdGVwLCBfbmFtZSkge1xuICAgIHZhciBzdGVwID0gX3N0ZXAgfHwgNjtcbiAgICB2YXIgdCA9IFtdLCByID0gW107XG4gICAgZDMucmFuZ2UoMCwgMzYwICsgc3RlcCwgc3RlcCkuZm9yRWFjaChmdW5jdGlvbihkZWcsIGluZGV4KSB7XG4gICAgICAgIHZhciB0aGV0YSA9IGRlZyAqIE1hdGguUEkgLyAxODA7XG4gICAgICAgIHZhciByYWRpdXMgPSBfZXF1YXRpb24odGhldGEpO1xuICAgICAgICB0LnB1c2goZGVnKTtcbiAgICAgICAgci5wdXNoKHJhZGl1cyk7XG4gICAgfSk7XG4gICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgICAgdDogdCxcbiAgICAgICAgcjogclxuICAgIH07XG4gICAgaWYgKF9uYW1lKSByZXN1bHQubmFtZSA9IF9uYW1lO1xuICAgIHJldHVybiByZXN1bHQ7XG59O1xuXG7CtS51dGlsLmVuc3VyZUFycmF5ID0gZnVuY3Rpb24oX3ZhbCwgX2NvdW50KSB7XG4gICAgaWYgKHR5cGVvZiBfdmFsID09PSAndW5kZWZpbmVkJykgcmV0dXJuIG51bGw7XG4gICAgdmFyIGFyciA9IFtdLmNvbmNhdChfdmFsKTtcbiAgICByZXR1cm4gZDMucmFuZ2UoX2NvdW50KS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICByZXR1cm4gYXJyW2ldIHx8IGFyclswXTtcbiAgICB9KTtcbn07XG5cbsK1LnV0aWwuZmlsbEFycmF5cyA9IGZ1bmN0aW9uKF9vYmosIF92YWx1ZU5hbWVzLCBfY291bnQpIHtcbiAgICBfdmFsdWVOYW1lcy5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgX29ialtkXSA9IMK1LnV0aWwuZW5zdXJlQXJyYXkoX29ialtkXSwgX2NvdW50KTtcbiAgICB9KTtcbiAgICByZXR1cm4gX29iajtcbn07XG5cbsK1LnV0aWwuY2xvbmVKc29uID0gZnVuY3Rpb24oanNvbikge1xuICAgIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGpzb24pKTtcbn07XG5cbsK1LnV0aWwudmFsaWRhdGVLZXlzID0gZnVuY3Rpb24ob2JqLCBrZXlzKSB7XG4gICAgaWYgKHR5cGVvZiBrZXlzID09PSAnc3RyaW5nJykga2V5cyA9IGtleXMuc3BsaXQoJy4nKTtcbiAgICB2YXIgbmV4dCA9IGtleXMuc2hpZnQoKTtcbiAgICByZXR1cm4gb2JqW25leHRdICYmICgha2V5cy5sZW5ndGggfHwgb2JqSGFzS2V5cyhvYmpbbmV4dF0sIGtleXMpKTtcbn07XG5cbsK1LnV0aWwuc3VtQXJyYXlzID0gZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBkMy56aXAoYSwgYikubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgcmV0dXJuIGQzLnN1bShkKTtcbiAgICB9KTtcbn07XG5cbsK1LnV0aWwuYXJyYXlMYXN0ID0gZnVuY3Rpb24oYSkge1xuICAgIHJldHVybiBhW2EubGVuZ3RoIC0gMV07XG59O1xuXG7CtS51dGlsLmFycmF5RXF1YWwgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIGkgPSBNYXRoLm1heChhLmxlbmd0aCwgYi5sZW5ndGgsIDEpO1xuICAgIHdoaWxlIChpLS0gPj0gMCAmJiBhW2ldID09PSBiW2ldKSA7XG4gICAgcmV0dXJuIGkgPT09IC0yO1xufTtcblxuwrUudXRpbC5mbGF0dGVuQXJyYXkgPSBmdW5jdGlvbihhcnIpIHtcbiAgICB2YXIgciA9IFtdO1xuICAgIHdoaWxlICghwrUudXRpbC5hcnJheUVxdWFsKHIsIGFycikpIHtcbiAgICAgICAgciA9IGFycjtcbiAgICAgICAgYXJyID0gW10uY29uY2F0LmFwcGx5KFtdLCBhcnIpO1xuICAgIH1cbiAgICByZXR1cm4gYXJyO1xufTtcblxuwrUudXRpbC5kZWR1cGxpY2F0ZSA9IGZ1bmN0aW9uKGFycikge1xuICAgIHJldHVybiBhcnIuZmlsdGVyKGZ1bmN0aW9uKHYsIGksIGEpIHtcbiAgICAgICAgcmV0dXJuIGEuaW5kZXhPZih2KSA9PSBpO1xuICAgIH0pO1xufTtcblxuwrUudXRpbC5jb252ZXJ0VG9DYXJ0ZXNpYW4gPSBmdW5jdGlvbihyYWRpdXMsIHRoZXRhKSB7XG4gICAgdmFyIHRoZXRhUmFkaWFucyA9IHRoZXRhICogTWF0aC5QSSAvIDE4MDtcbiAgICB2YXIgeCA9IHJhZGl1cyAqIE1hdGguY29zKHRoZXRhUmFkaWFucyk7XG4gICAgdmFyIHkgPSByYWRpdXMgKiBNYXRoLnNpbih0aGV0YVJhZGlhbnMpO1xuICAgIHJldHVybiBbIHgsIHkgXTtcbn07XG5cbsK1LnV0aWwucm91bmQgPSBmdW5jdGlvbihfdmFsdWUsIF9kaWdpdHMpIHtcbiAgICB2YXIgZGlnaXRzID0gX2RpZ2l0cyB8fCAyO1xuICAgIHZhciBtdWx0ID0gTWF0aC5wb3coMTAsIGRpZ2l0cyk7XG4gICAgcmV0dXJuIE1hdGgucm91bmQoX3ZhbHVlICogbXVsdCkgLyBtdWx0O1xufTtcblxuwrUudXRpbC5nZXRNb3VzZVBvcyA9IGZ1bmN0aW9uKF9yZWZlcmVuY2VFbGVtZW50KSB7XG4gICAgdmFyIG1vdXNlUG9zID0gZDMubW91c2UoX3JlZmVyZW5jZUVsZW1lbnQubm9kZSgpKTtcbiAgICB2YXIgbW91c2VYID0gbW91c2VQb3NbMF07XG4gICAgdmFyIG1vdXNlWSA9IG1vdXNlUG9zWzFdO1xuICAgIHZhciBtb3VzZSA9IHt9O1xuICAgIG1vdXNlLnggPSBtb3VzZVg7XG4gICAgbW91c2UueSA9IG1vdXNlWTtcbiAgICBtb3VzZS5wb3MgPSBtb3VzZVBvcztcbiAgICBtb3VzZS5hbmdsZSA9IChNYXRoLmF0YW4yKG1vdXNlWSwgbW91c2VYKSArIE1hdGguUEkpICogMTgwIC8gTWF0aC5QSTtcbiAgICBtb3VzZS5yYWRpdXMgPSBNYXRoLnNxcnQobW91c2VYICogbW91c2VYICsgbW91c2VZICogbW91c2VZKTtcbiAgICByZXR1cm4gbW91c2U7XG59O1xuXG7CtS51dGlsLmR1cGxpY2F0ZXNDb3VudCA9IGZ1bmN0aW9uKGFycikge1xuICAgIHZhciB1bmlxdWVzID0ge30sIHZhbDtcbiAgICB2YXIgZHVwcyA9IHt9O1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBhcnIubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFsID0gYXJyW2ldO1xuICAgICAgICBpZiAodmFsIGluIHVuaXF1ZXMpIHtcbiAgICAgICAgICAgIHVuaXF1ZXNbdmFsXSsrO1xuICAgICAgICAgICAgZHVwc1t2YWxdID0gdW5pcXVlc1t2YWxdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdW5pcXVlc1t2YWxdID0gMTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZHVwcztcbn07XG5cbsK1LnV0aWwuZHVwbGljYXRlcyA9IGZ1bmN0aW9uKGFycikge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyjCtS51dGlsLmR1cGxpY2F0ZXNDb3VudChhcnIpKTtcbn07XG5cbsK1LnV0aWwudHJhbnNsYXRvciA9IGZ1bmN0aW9uKG9iaiwgc291cmNlQnJhbmNoLCB0YXJnZXRCcmFuY2gsIHJldmVyc2UpIHtcbiAgICBpZiAocmV2ZXJzZSkge1xuICAgICAgICB2YXIgdGFyZ2V0QnJhbmNoQ29weSA9IHRhcmdldEJyYW5jaC5zbGljZSgpO1xuICAgICAgICB0YXJnZXRCcmFuY2ggPSBzb3VyY2VCcmFuY2g7XG4gICAgICAgIHNvdXJjZUJyYW5jaCA9IHRhcmdldEJyYW5jaENvcHk7XG4gICAgfVxuICAgIHZhciB2YWx1ZSA9IHNvdXJjZUJyYW5jaC5yZWR1Y2UoZnVuY3Rpb24ocHJldmlvdXNWYWx1ZSwgY3VycmVudFZhbHVlKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSAhPSAndW5kZWZpbmVkJykgcmV0dXJuIHByZXZpb3VzVmFsdWVbY3VycmVudFZhbHVlXTtcbiAgICB9LCBvYmopO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnKSByZXR1cm47XG4gICAgc291cmNlQnJhbmNoLnJlZHVjZShmdW5jdGlvbihwcmV2aW91c1ZhbHVlLCBjdXJyZW50VmFsdWUsIGluZGV4KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PSAndW5kZWZpbmVkJykgcmV0dXJuO1xuICAgICAgICBpZiAoaW5kZXggPT09IHNvdXJjZUJyYW5jaC5sZW5ndGggLSAxKSBkZWxldGUgcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdO1xuICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdO1xuICAgIH0sIG9iaik7XG4gICAgdGFyZ2V0QnJhbmNoLnJlZHVjZShmdW5jdGlvbihwcmV2aW91c1ZhbHVlLCBjdXJyZW50VmFsdWUsIGluZGV4KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdID09PSAndW5kZWZpbmVkJykgcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdID0ge307XG4gICAgICAgIGlmIChpbmRleCA9PT0gdGFyZ2V0QnJhbmNoLmxlbmd0aCAtIDEpIHByZXZpb3VzVmFsdWVbY3VycmVudFZhbHVlXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZVtjdXJyZW50VmFsdWVdO1xuICAgIH0sIG9iaik7XG59O1xuXG7CtS5Qb2x5Q2hhcnQgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgdmFyIGNvbmZpZyA9IFsgwrUuUG9seUNoYXJ0LmRlZmF1bHRDb25maWcoKSBdO1xuICAgIHZhciBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoKCdob3ZlcicpO1xuICAgIHZhciBkYXNoQXJyYXkgPSB7XG4gICAgICAgIHNvbGlkOiAnbm9uZScsXG4gICAgICAgIGRhc2g6IFsgNSwgMiBdLFxuICAgICAgICBkb3Q6IFsgMiwgNSBdXG4gICAgfTtcbiAgICB2YXIgY29sb3JTY2FsZTtcbiAgICBmdW5jdGlvbiBleHBvcnRzKCkge1xuICAgICAgICB2YXIgZ2VvbWV0cnlDb25maWcgPSBjb25maWdbMF0uZ2VvbWV0cnlDb25maWc7XG4gICAgICAgIHZhciBjb250YWluZXIgPSBnZW9tZXRyeUNvbmZpZy5jb250YWluZXI7XG4gICAgICAgIGlmICh0eXBlb2YgY29udGFpbmVyID09ICdzdHJpbmcnKSBjb250YWluZXIgPSBkMy5zZWxlY3QoY29udGFpbmVyKTtcbiAgICAgICAgY29udGFpbmVyLmRhdHVtKGNvbmZpZykuZWFjaChmdW5jdGlvbihfY29uZmlnLCBfaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBpc1N0YWNrID0gISFfY29uZmlnWzBdLmRhdGEueVN0YWNrO1xuICAgICAgICAgICAgdmFyIGRhdGEgPSBfY29uZmlnLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzU3RhY2spIHJldHVybiBkMy56aXAoZC5kYXRhLnRbMF0sIGQuZGF0YS5yWzBdLCBkLmRhdGEueVN0YWNrWzBdKTsgZWxzZSByZXR1cm4gZDMuemlwKGQuZGF0YS50WzBdLCBkLmRhdGEuclswXSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBhbmd1bGFyU2NhbGUgPSBnZW9tZXRyeUNvbmZpZy5hbmd1bGFyU2NhbGU7XG4gICAgICAgICAgICB2YXIgZG9tYWluTWluID0gZ2VvbWV0cnlDb25maWcucmFkaWFsU2NhbGUuZG9tYWluKClbMF07XG4gICAgICAgICAgICB2YXIgZ2VuZXJhdG9yID0ge307XG4gICAgICAgICAgICBnZW5lcmF0b3IuYmFyID0gZnVuY3Rpb24oZCwgaSwgcEkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGF0YUNvbmZpZyA9IF9jb25maWdbcEldLmRhdGE7XG4gICAgICAgICAgICAgICAgdmFyIGggPSBnZW9tZXRyeUNvbmZpZy5yYWRpYWxTY2FsZShkWzFdKSAtIGdlb21ldHJ5Q29uZmlnLnJhZGlhbFNjYWxlKDApO1xuICAgICAgICAgICAgICAgIHZhciBzdGFja1RvcCA9IGdlb21ldHJ5Q29uZmlnLnJhZGlhbFNjYWxlKGRbMl0gfHwgMCk7XG4gICAgICAgICAgICAgICAgdmFyIHcgPSBkYXRhQ29uZmlnLmJhcldpZHRoO1xuICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5hdHRyKHtcbiAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ21hcmsgYmFyJyxcbiAgICAgICAgICAgICAgICAgICAgZDogJ00nICsgWyBbIGggKyBzdGFja1RvcCwgLXcgLyAyIF0sIFsgaCArIHN0YWNrVG9wLCB3IC8gMiBdLCBbIHN0YWNrVG9wLCB3IC8gMiBdLCBbIHN0YWNrVG9wLCAtdyAvIDIgXSBdLmpvaW4oJ0wnKSArICdaJyxcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3JvdGF0ZSgnICsgKGdlb21ldHJ5Q29uZmlnLm9yaWVudGF0aW9uICsgYW5ndWxhclNjYWxlKGRbMF0pKSArICcpJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGdlbmVyYXRvci5kb3QgPSBmdW5jdGlvbihkLCBpLCBwSSkge1xuICAgICAgICAgICAgICAgIHZhciBzdGFja2VkRGF0YSA9IGRbMl0gPyBbIGRbMF0sIGRbMV0gKyBkWzJdIF0gOiBkO1xuICAgICAgICAgICAgICAgIHZhciBzeW1ib2wgPSBkMy5zdmcuc3ltYm9sKCkuc2l6ZShfY29uZmlnW3BJXS5kYXRhLmRvdFNpemUpLnR5cGUoX2NvbmZpZ1twSV0uZGF0YS5kb3RUeXBlKShkLCBpKTtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdtYXJrIGRvdCcsXG4gICAgICAgICAgICAgICAgICAgIGQ6IHN5bWJvbCxcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY29vcmQgPSBjb252ZXJ0VG9DYXJ0ZXNpYW4oZ2V0UG9sYXJDb29yZGluYXRlcyhzdGFja2VkRGF0YSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIFsgY29vcmQueCwgY29vcmQueSBdICsgJyknO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGxpbmUgPSBkMy5zdmcubGluZS5yYWRpYWwoKS5pbnRlcnBvbGF0ZShfY29uZmlnWzBdLmRhdGEubGluZUludGVycG9sYXRpb24pLnJhZGl1cyhmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdlb21ldHJ5Q29uZmlnLnJhZGlhbFNjYWxlKGRbMV0pO1xuICAgICAgICAgICAgfSkuYW5nbGUoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBnZW9tZXRyeUNvbmZpZy5hbmd1bGFyU2NhbGUoZFswXSkgKiBNYXRoLlBJIC8gMTgwO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBnZW5lcmF0b3IubGluZSA9IGZ1bmN0aW9uKGQsIGksIHBJKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxpbmVEYXRhID0gZFsyXSA/IGRhdGFbcEldLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbIGRbMF0sIGRbMV0gKyBkWzJdIF07XG4gICAgICAgICAgICAgICAgfSkgOiBkYXRhW3BJXTtcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuZWFjaChnZW5lcmF0b3JbJ2RvdCddKS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICtfY29uZmlnW3BJXS5kYXRhLmRvdFZpc2libGU7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGZpbGw6IG1hcmtTdHlsZS5zdHJva2UoZCwgaSwgcEkpXG4gICAgICAgICAgICAgICAgfSkuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdtYXJrIGRvdCdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBpZiAoaSA+IDApIHJldHVybjtcbiAgICAgICAgICAgICAgICB2YXIgbGluZVNlbGVjdGlvbiA9IGQzLnNlbGVjdCh0aGlzLnBhcmVudE5vZGUpLnNlbGVjdEFsbCgncGF0aC5saW5lJykuZGF0YShbIDAgXSk7XG4gICAgICAgICAgICAgICAgbGluZVNlbGVjdGlvbi5lbnRlcigpLmluc2VydCgncGF0aCcpO1xuICAgICAgICAgICAgICAgIGxpbmVTZWxlY3Rpb24uYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdsaW5lJyxcbiAgICAgICAgICAgICAgICAgICAgZDogbGluZShsaW5lRGF0YSksXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3JvdGF0ZSgnICsgKGdlb21ldHJ5Q29uZmlnLm9yaWVudGF0aW9uICsgOTApICsgJyknO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAncG9pbnRlci1ldmVudHMnOiAnbm9uZSdcbiAgICAgICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgICAgIGZpbGw6IGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hcmtTdHlsZS5maWxsKGQsIGksIHBJKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgJ2ZpbGwtb3BhY2l0eSc6IDAsXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZTogZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFya1N0eWxlLnN0cm9rZShkLCBpLCBwSSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiBmdW5jdGlvbihkQiwgaUIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXJrU3R5bGVbJ3N0cm9rZS13aWR0aCddKGQsIGksIHBJKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS1kYXNoYXJyYXknOiBmdW5jdGlvbihkQiwgaUIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXJrU3R5bGVbJ3N0cm9rZS1kYXNoYXJyYXknXShkLCBpLCBwSSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hcmtTdHlsZS5vcGFjaXR5KGQsIGksIHBJKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWFya1N0eWxlLmRpc3BsYXkoZCwgaSwgcEkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIGFuZ3VsYXJSYW5nZSA9IGdlb21ldHJ5Q29uZmlnLmFuZ3VsYXJTY2FsZS5yYW5nZSgpO1xuICAgICAgICAgICAgdmFyIHRyaWFuZ2xlQW5nbGUgPSBNYXRoLmFicyhhbmd1bGFyUmFuZ2VbMV0gLSBhbmd1bGFyUmFuZ2VbMF0pIC8gZGF0YVswXS5sZW5ndGggKiBNYXRoLlBJIC8gMTgwO1xuICAgICAgICAgICAgdmFyIGFyYyA9IGQzLnN2Zy5hcmMoKS5zdGFydEFuZ2xlKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gLXRyaWFuZ2xlQW5nbGUgLyAyO1xuICAgICAgICAgICAgfSkuZW5kQW5nbGUoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmlhbmdsZUFuZ2xlIC8gMjtcbiAgICAgICAgICAgIH0pLmlubmVyUmFkaXVzKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2VvbWV0cnlDb25maWcucmFkaWFsU2NhbGUoZG9tYWluTWluICsgKGRbMl0gfHwgMCkpO1xuICAgICAgICAgICAgfSkub3V0ZXJSYWRpdXMoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBnZW9tZXRyeUNvbmZpZy5yYWRpYWxTY2FsZShkb21haW5NaW4gKyAoZFsyXSB8fCAwKSkgKyBnZW9tZXRyeUNvbmZpZy5yYWRpYWxTY2FsZShkWzFdKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgZ2VuZXJhdG9yLmFyYyA9IGZ1bmN0aW9uKGQsIGksIHBJKSB7XG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAnbWFyayBhcmMnLFxuICAgICAgICAgICAgICAgICAgICBkOiBhcmMsXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdyb3RhdGUoJyArIChnZW9tZXRyeUNvbmZpZy5vcmllbnRhdGlvbiArIGFuZ3VsYXJTY2FsZShkWzBdKSArIDkwKSArICcpJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBtYXJrU3R5bGUgPSB7XG4gICAgICAgICAgICAgICAgZmlsbDogZnVuY3Rpb24oZCwgaSwgcEkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jb25maWdbcEldLmRhdGEuY29sb3I7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzdHJva2U6IGZ1bmN0aW9uKGQsIGksIHBJKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfY29uZmlnW3BJXS5kYXRhLnN0cm9rZUNvbG9yO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IGZ1bmN0aW9uKGQsIGksIHBJKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfY29uZmlnW3BJXS5kYXRhLnN0cm9rZVNpemUgKyAncHgnO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgJ3N0cm9rZS1kYXNoYXJyYXknOiBmdW5jdGlvbihkLCBpLCBwSSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGFzaEFycmF5W19jb25maWdbcEldLmRhdGEuc3Ryb2tlRGFzaF07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiBmdW5jdGlvbihkLCBpLCBwSSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NvbmZpZ1twSV0uZGF0YS5vcGFjaXR5O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGlzcGxheTogZnVuY3Rpb24oZCwgaSwgcEkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBfY29uZmlnW3BJXS5kYXRhLnZpc2libGUgPT09ICd1bmRlZmluZWQnIHx8IF9jb25maWdbcEldLmRhdGEudmlzaWJsZSA/ICdibG9jaycgOiAnbm9uZSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHZhciBnZW9tZXRyeUxheWVyID0gZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgnZy5sYXllcicpLmRhdGEoZGF0YSk7XG4gICAgICAgICAgICBnZW9tZXRyeUxheWVyLmVudGVyKCkuYXBwZW5kKCdnJykuYXR0cih7XG4gICAgICAgICAgICAgICAgJ2NsYXNzJzogJ2xheWVyJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgZ2VvbWV0cnkgPSBnZW9tZXRyeUxheWVyLnNlbGVjdEFsbCgncGF0aC5tYXJrJykuZGF0YShmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGdlb21ldHJ5LmVudGVyKCkuYXBwZW5kKCdwYXRoJykuYXR0cih7XG4gICAgICAgICAgICAgICAgJ2NsYXNzJzogJ21hcmsnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGdlb21ldHJ5LnN0eWxlKG1hcmtTdHlsZSkuZWFjaChnZW5lcmF0b3JbZ2VvbWV0cnlDb25maWcuZ2VvbWV0cnlUeXBlXSk7XG4gICAgICAgICAgICBnZW9tZXRyeS5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgICAgICBnZW9tZXRyeUxheWVyLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFBvbGFyQ29vcmRpbmF0ZXMoZCwgaSkge1xuICAgICAgICAgICAgICAgIHZhciByID0gZ2VvbWV0cnlDb25maWcucmFkaWFsU2NhbGUoZFsxXSk7XG4gICAgICAgICAgICAgICAgdmFyIHQgPSAoZ2VvbWV0cnlDb25maWcuYW5ndWxhclNjYWxlKGRbMF0pICsgZ2VvbWV0cnlDb25maWcub3JpZW50YXRpb24pICogTWF0aC5QSSAvIDE4MDtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICByOiByLFxuICAgICAgICAgICAgICAgICAgICB0OiB0XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNvbnZlcnRUb0NhcnRlc2lhbihwb2xhckNvb3JkaW5hdGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHggPSBwb2xhckNvb3JkaW5hdGVzLnIgKiBNYXRoLmNvcyhwb2xhckNvb3JkaW5hdGVzLnQpO1xuICAgICAgICAgICAgICAgIHZhciB5ID0gcG9sYXJDb29yZGluYXRlcy5yICogTWF0aC5zaW4ocG9sYXJDb29yZGluYXRlcy50KTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB4OiB4LFxuICAgICAgICAgICAgICAgICAgICB5OiB5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGV4cG9ydHMuY29uZmlnID0gZnVuY3Rpb24oX3gpIHtcbiAgICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY29uZmlnO1xuICAgICAgICBfeC5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgIGlmICghY29uZmlnW2ldKSBjb25maWdbaV0gPSB7fTtcbiAgICAgICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnW2ldLCDCtS5Qb2x5Q2hhcnQuZGVmYXVsdENvbmZpZygpKTtcbiAgICAgICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnW2ldLCBkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZXhwb3J0cy5nZXRDb2xvclNjYWxlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBjb2xvclNjYWxlO1xuICAgIH07XG4gICAgZDMucmViaW5kKGV4cG9ydHMsIGRpc3BhdGNoLCAnb24nKTtcbiAgICByZXR1cm4gZXhwb3J0cztcbn07XG5cbsK1LlBvbHlDaGFydC5kZWZhdWx0Q29uZmlnID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgbmFtZTogJ2dlb20xJyxcbiAgICAgICAgICAgIHQ6IFsgWyAxLCAyLCAzLCA0IF0gXSxcbiAgICAgICAgICAgIHI6IFsgWyAxLCAyLCAzLCA0IF0gXSxcbiAgICAgICAgICAgIGRvdFR5cGU6ICdjaXJjbGUnLFxuICAgICAgICAgICAgZG90U2l6ZTogNjQsXG4gICAgICAgICAgICBkb3RWaXNpYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIGJhcldpZHRoOiAyMCxcbiAgICAgICAgICAgIGNvbG9yOiAnI2ZmYTUwMCcsXG4gICAgICAgICAgICBzdHJva2VTaXplOiAxLFxuICAgICAgICAgICAgc3Ryb2tlQ29sb3I6ICdzaWx2ZXInLFxuICAgICAgICAgICAgc3Ryb2tlRGFzaDogJ3NvbGlkJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG4gICAgICAgICAgICB2aXNpYmxlSW5MZWdlbmQ6IHRydWVcbiAgICAgICAgfSxcbiAgICAgICAgZ2VvbWV0cnlDb25maWc6IHtcbiAgICAgICAgICAgIGdlb21ldHJ5OiAnTGluZVBsb3QnLFxuICAgICAgICAgICAgZ2VvbWV0cnlUeXBlOiAnYXJjJyxcbiAgICAgICAgICAgIGRpcmVjdGlvbjogJ2Nsb2Nrd2lzZScsXG4gICAgICAgICAgICBvcmllbnRhdGlvbjogMCxcbiAgICAgICAgICAgIGNvbnRhaW5lcjogJ2JvZHknLFxuICAgICAgICAgICAgcmFkaWFsU2NhbGU6IG51bGwsXG4gICAgICAgICAgICBhbmd1bGFyU2NhbGU6IG51bGwsXG4gICAgICAgICAgICBjb2xvclNjYWxlOiBkMy5zY2FsZS5jYXRlZ29yeTIwKClcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIGNvbmZpZztcbn07XG5cbsK1LkJhckNoYXJ0ID0gZnVuY3Rpb24gbW9kdWxlKCkge1xuICAgIHJldHVybiDCtS5Qb2x5Q2hhcnQoKTtcbn07XG5cbsK1LkJhckNoYXJ0LmRlZmF1bHRDb25maWcgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgY29uZmlnID0ge1xuICAgICAgICBnZW9tZXRyeUNvbmZpZzoge1xuICAgICAgICAgICAgZ2VvbWV0cnlUeXBlOiAnYmFyJ1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gY29uZmlnO1xufTtcblxuwrUuQXJlYUNoYXJ0ID0gZnVuY3Rpb24gbW9kdWxlKCkge1xuICAgIHJldHVybiDCtS5Qb2x5Q2hhcnQoKTtcbn07XG5cbsK1LkFyZWFDaGFydC5kZWZhdWx0Q29uZmlnID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZ2VvbWV0cnlDb25maWc6IHtcbiAgICAgICAgICAgIGdlb21ldHJ5VHlwZTogJ2FyYydcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIGNvbmZpZztcbn07XG5cbsK1LkRvdFBsb3QgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgcmV0dXJuIMK1LlBvbHlDaGFydCgpO1xufTtcblxuwrUuRG90UGxvdC5kZWZhdWx0Q29uZmlnID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgZ2VvbWV0cnlDb25maWc6IHtcbiAgICAgICAgICAgIGdlb21ldHJ5VHlwZTogJ2RvdCcsXG4gICAgICAgICAgICBkb3RUeXBlOiAnY2lyY2xlJ1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gY29uZmlnO1xufTtcblxuwrUuTGluZVBsb3QgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgcmV0dXJuIMK1LlBvbHlDaGFydCgpO1xufTtcblxuwrUuTGluZVBsb3QuZGVmYXVsdENvbmZpZyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBjb25maWcgPSB7XG4gICAgICAgIGdlb21ldHJ5Q29uZmlnOiB7XG4gICAgICAgICAgICBnZW9tZXRyeVR5cGU6ICdsaW5lJ1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gY29uZmlnO1xufTtcblxuwrUuTGVnZW5kID0gZnVuY3Rpb24gbW9kdWxlKCkge1xuICAgIHZhciBjb25maWcgPSDCtS5MZWdlbmQuZGVmYXVsdENvbmZpZygpO1xuICAgIHZhciBkaXNwYXRjaCA9IGQzLmRpc3BhdGNoKCdob3ZlcicpO1xuICAgIGZ1bmN0aW9uIGV4cG9ydHMoKSB7XG4gICAgICAgIHZhciBsZWdlbmRDb25maWcgPSBjb25maWcubGVnZW5kQ29uZmlnO1xuICAgICAgICB2YXIgZmxhdHRlbkRhdGEgPSBjb25maWcuZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIFtdLmNvbmNhdChkKS5tYXAoZnVuY3Rpb24oZEIsIGlCKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSBleHRlbmREZWVwQWxsKHt9LCBsZWdlbmRDb25maWcuZWxlbWVudHNbaV0pO1xuICAgICAgICAgICAgICAgIGVsZW1lbnQubmFtZSA9IGRCO1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuY29sb3IgPSBbXS5jb25jYXQobGVnZW5kQ29uZmlnLmVsZW1lbnRzW2ldLmNvbG9yKVtpQl07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBkYXRhID0gZDMubWVyZ2UoZmxhdHRlbkRhdGEpO1xuICAgICAgICBkYXRhID0gZGF0YS5maWx0ZXIoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIGxlZ2VuZENvbmZpZy5lbGVtZW50c1tpXSAmJiAobGVnZW5kQ29uZmlnLmVsZW1lbnRzW2ldLnZpc2libGVJbkxlZ2VuZCB8fCB0eXBlb2YgbGVnZW5kQ29uZmlnLmVsZW1lbnRzW2ldLnZpc2libGVJbkxlZ2VuZCA9PT0gJ3VuZGVmaW5lZCcpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGxlZ2VuZENvbmZpZy5yZXZlcnNlT3JkZXIpIGRhdGEgPSBkYXRhLnJldmVyc2UoKTtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IGxlZ2VuZENvbmZpZy5jb250YWluZXI7XG4gICAgICAgIGlmICh0eXBlb2YgY29udGFpbmVyID09ICdzdHJpbmcnIHx8IGNvbnRhaW5lci5ub2RlTmFtZSkgY29udGFpbmVyID0gZDMuc2VsZWN0KGNvbnRhaW5lcik7XG4gICAgICAgIHZhciBjb2xvcnMgPSBkYXRhLm1hcChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5jb2xvcjtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBsaW5lSGVpZ2h0ID0gbGVnZW5kQ29uZmlnLmZvbnRTaXplO1xuICAgICAgICB2YXIgaXNDb250aW51b3VzID0gbGVnZW5kQ29uZmlnLmlzQ29udGludW91cyA9PSBudWxsID8gdHlwZW9mIGRhdGFbMF0gPT09ICdudW1iZXInIDogbGVnZW5kQ29uZmlnLmlzQ29udGludW91cztcbiAgICAgICAgdmFyIGhlaWdodCA9IGlzQ29udGludW91cyA/IGxlZ2VuZENvbmZpZy5oZWlnaHQgOiBsaW5lSGVpZ2h0ICogZGF0YS5sZW5ndGg7XG4gICAgICAgIHZhciBsZWdlbmRDb250YWluZXJHcm91cCA9IGNvbnRhaW5lci5jbGFzc2VkKCdsZWdlbmQtZ3JvdXAnLCB0cnVlKTtcbiAgICAgICAgdmFyIHN2ZyA9IGxlZ2VuZENvbnRhaW5lckdyb3VwLnNlbGVjdEFsbCgnc3ZnJykuZGF0YShbIDAgXSk7XG4gICAgICAgIHZhciBzdmdFbnRlciA9IHN2Zy5lbnRlcigpLmFwcGVuZCgnc3ZnJykuYXR0cih7XG4gICAgICAgICAgICB3aWR0aDogMzAwLFxuICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgKyBsaW5lSGVpZ2h0LFxuICAgICAgICAgICAgeG1sbnM6ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsXG4gICAgICAgICAgICAneG1sbnM6eGxpbmsnOiAnaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluaycsXG4gICAgICAgICAgICB2ZXJzaW9uOiAnMS4xJ1xuICAgICAgICB9KTtcbiAgICAgICAgc3ZnRW50ZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnbGVnZW5kLWF4aXMnLCB0cnVlKTtcbiAgICAgICAgc3ZnRW50ZXIuYXBwZW5kKCdnJykuY2xhc3NlZCgnbGVnZW5kLW1hcmtzJywgdHJ1ZSk7XG4gICAgICAgIHZhciBkYXRhTnVtYmVyZWQgPSBkMy5yYW5nZShkYXRhLmxlbmd0aCk7XG4gICAgICAgIHZhciBjb2xvclNjYWxlID0gZDMuc2NhbGVbaXNDb250aW51b3VzID8gJ2xpbmVhcicgOiAnb3JkaW5hbCddKCkuZG9tYWluKGRhdGFOdW1iZXJlZCkucmFuZ2UoY29sb3JzKTtcbiAgICAgICAgdmFyIGRhdGFTY2FsZSA9IGQzLnNjYWxlW2lzQ29udGludW91cyA/ICdsaW5lYXInIDogJ29yZGluYWwnXSgpLmRvbWFpbihkYXRhTnVtYmVyZWQpW2lzQ29udGludW91cyA/ICdyYW5nZScgOiAncmFuZ2VQb2ludHMnXShbIDAsIGhlaWdodCBdKTtcbiAgICAgICAgdmFyIHNoYXBlR2VuZXJhdG9yID0gZnVuY3Rpb24oX3R5cGUsIF9zaXplKSB7XG4gICAgICAgICAgICB2YXIgc3F1YXJlU2l6ZSA9IF9zaXplICogMztcbiAgICAgICAgICAgIGlmIChfdHlwZSA9PT0gJ2xpbmUnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdNJyArIFsgWyAtX3NpemUgLyAyLCAtX3NpemUgLyAxMiBdLCBbIF9zaXplIC8gMiwgLV9zaXplIC8gMTIgXSwgWyBfc2l6ZSAvIDIsIF9zaXplIC8gMTIgXSwgWyAtX3NpemUgLyAyLCBfc2l6ZSAvIDEyIF0gXSArICdaJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZDMuc3ZnLnN5bWJvbFR5cGVzLmluZGV4T2YoX3R5cGUpICE9IC0xKSByZXR1cm4gZDMuc3ZnLnN5bWJvbCgpLnR5cGUoX3R5cGUpLnNpemUoc3F1YXJlU2l6ZSkoKTsgZWxzZSByZXR1cm4gZDMuc3ZnLnN5bWJvbCgpLnR5cGUoJ3NxdWFyZScpLnNpemUoc3F1YXJlU2l6ZSkoKTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGlzQ29udGludW91cykge1xuICAgICAgICAgICAgdmFyIGdyYWRpZW50ID0gc3ZnLnNlbGVjdCgnLmxlZ2VuZC1tYXJrcycpLmFwcGVuZCgnZGVmcycpLmFwcGVuZCgnbGluZWFyR3JhZGllbnQnKS5hdHRyKHtcbiAgICAgICAgICAgICAgICBpZDogJ2dyYWQxJyxcbiAgICAgICAgICAgICAgICB4MTogJzAlJyxcbiAgICAgICAgICAgICAgICB5MTogJzAlJyxcbiAgICAgICAgICAgICAgICB4MjogJzAlJyxcbiAgICAgICAgICAgICAgICB5MjogJzEwMCUnXG4gICAgICAgICAgICB9KS5zZWxlY3RBbGwoJ3N0b3AnKS5kYXRhKGNvbG9ycyk7XG4gICAgICAgICAgICBncmFkaWVudC5lbnRlcigpLmFwcGVuZCgnc3RvcCcpO1xuICAgICAgICAgICAgZ3JhZGllbnQuYXR0cih7XG4gICAgICAgICAgICAgICAgb2Zmc2V0OiBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpIC8gKGNvbG9ycy5sZW5ndGggLSAxKSAqIDEwMCArICclJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5zdHlsZSh7XG4gICAgICAgICAgICAgICAgJ3N0b3AtY29sb3InOiBmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgc3ZnLmFwcGVuZCgncmVjdCcpLmNsYXNzZWQoJ2xlZ2VuZC1tYXJrJywgdHJ1ZSkuYXR0cih7XG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBsZWdlbmRDb25maWcuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBsZWdlbmRDb25maWcuY29sb3JCYW5kV2lkdGgsXG4gICAgICAgICAgICAgICAgZmlsbDogJ3VybCgjZ3JhZDEpJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgbGVnZW5kRWxlbWVudCA9IHN2Zy5zZWxlY3QoJy5sZWdlbmQtbWFya3MnKS5zZWxlY3RBbGwoJ3BhdGgubGVnZW5kLW1hcmsnKS5kYXRhKGRhdGEpO1xuICAgICAgICAgICAgbGVnZW5kRWxlbWVudC5lbnRlcigpLmFwcGVuZCgncGF0aCcpLmNsYXNzZWQoJ2xlZ2VuZC1tYXJrJywgdHJ1ZSk7XG4gICAgICAgICAgICBsZWdlbmRFbGVtZW50LmF0dHIoe1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgWyBsaW5lSGVpZ2h0IC8gMiwgZGF0YVNjYWxlKGkpICsgbGluZUhlaWdodCAvIDIgXSArICcpJztcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGQ6IGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHN5bWJvbFR5cGUgPSBkLnN5bWJvbDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNoYXBlR2VuZXJhdG9yKHN5bWJvbFR5cGUsIGxpbmVIZWlnaHQpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZmlsbDogZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sb3JTY2FsZShpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGxlZ2VuZEVsZW1lbnQuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBsZWdlbmRBeGlzID0gZDMuc3ZnLmF4aXMoKS5zY2FsZShkYXRhU2NhbGUpLm9yaWVudCgncmlnaHQnKTtcbiAgICAgICAgdmFyIGF4aXMgPSBzdmcuc2VsZWN0KCdnLmxlZ2VuZC1heGlzJykuYXR0cih7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIFsgaXNDb250aW51b3VzID8gbGVnZW5kQ29uZmlnLmNvbG9yQmFuZFdpZHRoIDogbGluZUhlaWdodCwgbGluZUhlaWdodCAvIDIgXSArICcpJ1xuICAgICAgICB9KS5jYWxsKGxlZ2VuZEF4aXMpO1xuICAgICAgICBheGlzLnNlbGVjdEFsbCgnLmRvbWFpbicpLnN0eWxlKHtcbiAgICAgICAgICAgIGZpbGw6ICdub25lJyxcbiAgICAgICAgICAgIHN0cm9rZTogJ25vbmUnXG4gICAgICAgIH0pO1xuICAgICAgICBheGlzLnNlbGVjdEFsbCgnbGluZScpLnN0eWxlKHtcbiAgICAgICAgICAgIGZpbGw6ICdub25lJyxcbiAgICAgICAgICAgIHN0cm9rZTogaXNDb250aW51b3VzID8gbGVnZW5kQ29uZmlnLnRleHRDb2xvciA6ICdub25lJ1xuICAgICAgICB9KTtcbiAgICAgICAgYXhpcy5zZWxlY3RBbGwoJ3RleHQnKS5zdHlsZSh7XG4gICAgICAgICAgICBmaWxsOiBsZWdlbmRDb25maWcudGV4dENvbG9yLFxuICAgICAgICAgICAgJ2ZvbnQtc2l6ZSc6IGxlZ2VuZENvbmZpZy5mb250U2l6ZVxuICAgICAgICB9KS50ZXh0KGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRhW2ldLm5hbWU7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZXhwb3J0cztcbiAgICB9XG4gICAgZXhwb3J0cy5jb25maWcgPSBmdW5jdGlvbihfeCkge1xuICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBjb25maWc7XG4gICAgICAgIGV4dGVuZERlZXBBbGwoY29uZmlnLCBfeCk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG4gICAgZDMucmViaW5kKGV4cG9ydHMsIGRpc3BhdGNoLCAnb24nKTtcbiAgICByZXR1cm4gZXhwb3J0cztcbn07XG5cbsK1LkxlZ2VuZC5kZWZhdWx0Q29uZmlnID0gZnVuY3Rpb24oZCwgaSkge1xuICAgIHZhciBjb25maWcgPSB7XG4gICAgICAgIGRhdGE6IFsgJ2EnLCAnYicsICdjJyBdLFxuICAgICAgICBsZWdlbmRDb25maWc6IHtcbiAgICAgICAgICAgIGVsZW1lbnRzOiBbIHtcbiAgICAgICAgICAgICAgICBzeW1ib2w6ICdsaW5lJyxcbiAgICAgICAgICAgICAgICBjb2xvcjogJ3JlZCdcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICBzeW1ib2w6ICdzcXVhcmUnLFxuICAgICAgICAgICAgICAgIGNvbG9yOiAneWVsbG93J1xuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIHN5bWJvbDogJ2RpYW1vbmQnLFxuICAgICAgICAgICAgICAgIGNvbG9yOiAnbGltZWdyZWVuJ1xuICAgICAgICAgICAgfSBdLFxuICAgICAgICAgICAgaGVpZ2h0OiAxNTAsXG4gICAgICAgICAgICBjb2xvckJhbmRXaWR0aDogMzAsXG4gICAgICAgICAgICBmb250U2l6ZTogMTIsXG4gICAgICAgICAgICBjb250YWluZXI6ICdib2R5JyxcbiAgICAgICAgICAgIGlzQ29udGludW91czogbnVsbCxcbiAgICAgICAgICAgIHRleHRDb2xvcjogJ2dyZXknLFxuICAgICAgICAgICAgcmV2ZXJzZU9yZGVyOiBmYWxzZVxuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gY29uZmlnO1xufTtcblxuwrUudG9vbHRpcFBhbmVsID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHRvb2x0aXBFbCwgdG9vbHRpcFRleHRFbCwgYmFja2dyb3VuZEVsO1xuICAgIHZhciBjb25maWcgPSB7XG4gICAgICAgIGNvbnRhaW5lcjogbnVsbCxcbiAgICAgICAgaGFzVGljazogZmFsc2UsXG4gICAgICAgIGZvbnRTaXplOiAxMixcbiAgICAgICAgY29sb3I6ICd3aGl0ZScsXG4gICAgICAgIHBhZGRpbmc6IDVcbiAgICB9O1xuICAgIHZhciBpZCA9ICd0b29sdGlwLScgKyDCtS50b29sdGlwUGFuZWwudWlkKys7XG4gICAgdmFyIHRpY2tTaXplID0gMTA7XG4gICAgdmFyIGV4cG9ydHMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdG9vbHRpcEVsID0gY29uZmlnLmNvbnRhaW5lci5zZWxlY3RBbGwoJ2cuJyArIGlkKS5kYXRhKFsgMCBdKTtcbiAgICAgICAgdmFyIHRvb2x0aXBFbnRlciA9IHRvb2x0aXBFbC5lbnRlcigpLmFwcGVuZCgnZycpLmNsYXNzZWQoaWQsIHRydWUpLnN0eWxlKHtcbiAgICAgICAgICAgICdwb2ludGVyLWV2ZW50cyc6ICdub25lJyxcbiAgICAgICAgICAgIGRpc3BsYXk6ICdub25lJ1xuICAgICAgICB9KTtcbiAgICAgICAgYmFja2dyb3VuZEVsID0gdG9vbHRpcEVudGVyLmFwcGVuZCgncGF0aCcpLnN0eWxlKHtcbiAgICAgICAgICAgIGZpbGw6ICd3aGl0ZScsXG4gICAgICAgICAgICAnZmlsbC1vcGFjaXR5JzogLjlcbiAgICAgICAgfSkuYXR0cih7XG4gICAgICAgICAgICBkOiAnTTAgMCdcbiAgICAgICAgfSk7XG4gICAgICAgIHRvb2x0aXBUZXh0RWwgPSB0b29sdGlwRW50ZXIuYXBwZW5kKCd0ZXh0JykuYXR0cih7XG4gICAgICAgICAgICBkeDogY29uZmlnLnBhZGRpbmcgKyB0aWNrU2l6ZSxcbiAgICAgICAgICAgIGR5OiArY29uZmlnLmZvbnRTaXplICogLjNcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBleHBvcnRzO1xuICAgIH07XG4gICAgZXhwb3J0cy50ZXh0ID0gZnVuY3Rpb24oX3RleHQpIHtcbiAgICAgICAgdmFyIGwgPSBkMy5oc2woY29uZmlnLmNvbG9yKS5sO1xuICAgICAgICB2YXIgc3Ryb2tlQ29sb3IgPSBsID49IC41ID8gJyNhYWEnIDogJ3doaXRlJztcbiAgICAgICAgdmFyIGZpbGxDb2xvciA9IGwgPj0gLjUgPyAnYmxhY2snIDogJ3doaXRlJztcbiAgICAgICAgdmFyIHRleHQgPSBfdGV4dCB8fCAnJztcbiAgICAgICAgdG9vbHRpcFRleHRFbC5zdHlsZSh7XG4gICAgICAgICAgICBmaWxsOiBmaWxsQ29sb3IsXG4gICAgICAgICAgICAnZm9udC1zaXplJzogY29uZmlnLmZvbnRTaXplICsgJ3B4J1xuICAgICAgICB9KS50ZXh0KHRleHQpO1xuICAgICAgICB2YXIgcGFkZGluZyA9IGNvbmZpZy5wYWRkaW5nO1xuICAgICAgICB2YXIgYmJveCA9IHRvb2x0aXBUZXh0RWwubm9kZSgpLmdldEJCb3goKTtcbiAgICAgICAgdmFyIGJveFN0eWxlID0ge1xuICAgICAgICAgICAgZmlsbDogY29uZmlnLmNvbG9yLFxuICAgICAgICAgICAgc3Ryb2tlOiBzdHJva2VDb2xvcixcbiAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiAnMnB4J1xuICAgICAgICB9O1xuICAgICAgICB2YXIgYmFja0dyb3VuZFcgPSBiYm94LndpZHRoICsgcGFkZGluZyAqIDIgKyB0aWNrU2l6ZTtcbiAgICAgICAgdmFyIGJhY2tHcm91bmRIID0gYmJveC5oZWlnaHQgKyBwYWRkaW5nICogMjtcbiAgICAgICAgYmFja2dyb3VuZEVsLmF0dHIoe1xuICAgICAgICAgICAgZDogJ00nICsgWyBbIHRpY2tTaXplLCAtYmFja0dyb3VuZEggLyAyIF0sIFsgdGlja1NpemUsIC1iYWNrR3JvdW5kSCAvIDQgXSwgWyBjb25maWcuaGFzVGljayA/IDAgOiB0aWNrU2l6ZSwgMCBdLCBbIHRpY2tTaXplLCBiYWNrR3JvdW5kSCAvIDQgXSwgWyB0aWNrU2l6ZSwgYmFja0dyb3VuZEggLyAyIF0sIFsgYmFja0dyb3VuZFcsIGJhY2tHcm91bmRIIC8gMiBdLCBbIGJhY2tHcm91bmRXLCAtYmFja0dyb3VuZEggLyAyIF0gXS5qb2luKCdMJykgKyAnWidcbiAgICAgICAgfSkuc3R5bGUoYm94U3R5bGUpO1xuICAgICAgICB0b29sdGlwRWwuYXR0cih7XG4gICAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUoJyArIFsgdGlja1NpemUsIC1iYWNrR3JvdW5kSCAvIDIgKyBwYWRkaW5nICogMiBdICsgJyknXG4gICAgICAgIH0pO1xuICAgICAgICB0b29sdGlwRWwuc3R5bGUoe1xuICAgICAgICAgICAgZGlzcGxheTogJ2Jsb2NrJ1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGV4cG9ydHM7XG4gICAgfTtcbiAgICBleHBvcnRzLm1vdmUgPSBmdW5jdGlvbihfcG9zKSB7XG4gICAgICAgIGlmICghdG9vbHRpcEVsKSByZXR1cm47XG4gICAgICAgIHRvb2x0aXBFbC5hdHRyKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZSgnICsgWyBfcG9zWzBdLCBfcG9zWzFdIF0gKyAnKSdcbiAgICAgICAgfSkuc3R5bGUoe1xuICAgICAgICAgICAgZGlzcGxheTogJ2Jsb2NrJ1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGV4cG9ydHM7XG4gICAgfTtcbiAgICBleHBvcnRzLmhpZGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0b29sdGlwRWwpIHJldHVybjtcbiAgICAgICAgdG9vbHRpcEVsLnN0eWxlKHtcbiAgICAgICAgICAgIGRpc3BsYXk6ICdub25lJ1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGV4cG9ydHM7XG4gICAgfTtcbiAgICBleHBvcnRzLnNob3cgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCF0b29sdGlwRWwpIHJldHVybjtcbiAgICAgICAgdG9vbHRpcEVsLnN0eWxlKHtcbiAgICAgICAgICAgIGRpc3BsYXk6ICdibG9jaydcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBleHBvcnRzO1xuICAgIH07XG4gICAgZXhwb3J0cy5jb25maWcgPSBmdW5jdGlvbihfeCkge1xuICAgICAgICBleHRlbmREZWVwQWxsKGNvbmZpZywgX3gpO1xuICAgICAgICByZXR1cm4gZXhwb3J0cztcbiAgICB9O1xuICAgIHJldHVybiBleHBvcnRzO1xufTtcblxuwrUudG9vbHRpcFBhbmVsLnVpZCA9IDE7XG5cbsK1LmFkYXB0ZXIgPSB7fTtcblxuwrUuYWRhcHRlci5wbG90bHkgPSBmdW5jdGlvbiBtb2R1bGUoKSB7XG4gICAgdmFyIGV4cG9ydHMgPSB7fTtcbiAgICBleHBvcnRzLmNvbnZlcnQgPSBmdW5jdGlvbihfaW5wdXRDb25maWcsIHJldmVyc2UpIHtcbiAgICAgICAgdmFyIG91dHB1dENvbmZpZyA9IHt9O1xuICAgICAgICBpZiAoX2lucHV0Q29uZmlnLmRhdGEpIHtcbiAgICAgICAgICAgIG91dHB1dENvbmZpZy5kYXRhID0gX2lucHV0Q29uZmlnLmRhdGEubWFwKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgciA9IGV4dGVuZERlZXBBbGwoe30sIGQpO1xuICAgICAgICAgICAgICAgIHZhciB0b1RyYW5zbGF0ZSA9IFtcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnY29sb3InIF0sIFsgJ2NvbG9yJyBdIF0sXG4gICAgICAgICAgICAgICAgICAgIFsgciwgWyAnbWFya2VyJywgJ29wYWNpdHknIF0sIFsgJ29wYWNpdHknIF0gXSxcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnbGluZScsICdjb2xvcicgXSwgWyAnc3Ryb2tlQ29sb3InIF0gXSxcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnbGluZScsICdkYXNoJyBdLCBbICdzdHJva2VEYXNoJyBdIF0sXG4gICAgICAgICAgICAgICAgICAgIFsgciwgWyAnbWFya2VyJywgJ2xpbmUnLCAnd2lkdGgnIF0sIFsgJ3N0cm9rZVNpemUnIF0gXSxcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnc3ltYm9sJyBdLCBbICdkb3RUeXBlJyBdIF0sXG4gICAgICAgICAgICAgICAgICAgIFsgciwgWyAnbWFya2VyJywgJ3NpemUnIF0sIFsgJ2RvdFNpemUnIF0gXSxcbiAgICAgICAgICAgICAgICAgICAgWyByLCBbICdtYXJrZXInLCAnYmFyV2lkdGgnIF0sIFsgJ2JhcldpZHRoJyBdIF0sXG4gICAgICAgICAgICAgICAgICAgIFsgciwgWyAnbGluZScsICdpbnRlcnBvbGF0aW9uJyBdLCBbICdsaW5lSW50ZXJwb2xhdGlvbicgXSBdLFxuICAgICAgICAgICAgICAgICAgICBbIHIsIFsgJ3Nob3dsZWdlbmQnIF0sIFsgJ3Zpc2libGVJbkxlZ2VuZCcgXSBdXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICB0b1RyYW5zbGF0ZS5mb3JFYWNoKGZ1bmN0aW9uKGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgwrUudXRpbC50cmFuc2xhdG9yLmFwcGx5KG51bGwsIGQuY29uY2F0KHJldmVyc2UpKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICghcmV2ZXJzZSkgZGVsZXRlIHIubWFya2VyO1xuICAgICAgICAgICAgICAgIGlmIChyZXZlcnNlKSBkZWxldGUgci5ncm91cElkO1xuICAgICAgICAgICAgICAgIGlmICghcmV2ZXJzZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoci50eXBlID09PSAnc2NhdHRlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyLm1vZGUgPT09ICdsaW5lcycpIHIuZ2VvbWV0cnkgPSAnTGluZVBsb3QnOyBlbHNlIGlmIChyLm1vZGUgPT09ICdtYXJrZXJzJykgci5nZW9tZXRyeSA9ICdEb3RQbG90JzsgZWxzZSBpZiAoci5tb2RlID09PSAnbGluZXMrbWFya2VycycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByLmdlb21ldHJ5ID0gJ0xpbmVQbG90JztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByLmRvdFZpc2libGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHIudHlwZSA9PT0gJ2FyZWEnKSByLmdlb21ldHJ5ID0gJ0FyZWFDaGFydCc7IGVsc2UgaWYgKHIudHlwZSA9PT0gJ2JhcicpIHIuZ2VvbWV0cnkgPSAnQmFyQ2hhcnQnO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgci5tb2RlO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgci50eXBlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyLmdlb21ldHJ5ID09PSAnTGluZVBsb3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByLnR5cGUgPSAnc2NhdHRlcic7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoci5kb3RWaXNpYmxlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHIuZG90VmlzaWJsZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByLm1vZGUgPSAnbGluZXMrbWFya2Vycyc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugci5tb2RlID0gJ2xpbmVzJztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChyLmdlb21ldHJ5ID09PSAnRG90UGxvdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHIudHlwZSA9ICdzY2F0dGVyJztcbiAgICAgICAgICAgICAgICAgICAgICAgIHIubW9kZSA9ICdtYXJrZXJzJztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChyLmdlb21ldHJ5ID09PSAnQXJlYUNoYXJ0Jykgci50eXBlID0gJ2FyZWEnOyBlbHNlIGlmIChyLmdlb21ldHJ5ID09PSAnQmFyQ2hhcnQnKSByLnR5cGUgPSAnYmFyJztcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHIuZ2VvbWV0cnk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIXJldmVyc2UgJiYgX2lucHV0Q29uZmlnLmxheW91dCAmJiBfaW5wdXRDb25maWcubGF5b3V0LmJhcm1vZGUgPT09ICdzdGFjaycpIHtcbiAgICAgICAgICAgICAgICB2YXIgZHVwbGljYXRlcyA9IMK1LnV0aWwuZHVwbGljYXRlcyhvdXRwdXRDb25maWcuZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZC5nZW9tZXRyeTtcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgb3V0cHV0Q29uZmlnLmRhdGEuZm9yRWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpZHggPSBkdXBsaWNhdGVzLmluZGV4T2YoZC5nZW9tZXRyeSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpZHggIT0gLTEpIG91dHB1dENvbmZpZy5kYXRhW2ldLmdyb3VwSWQgPSBpZHg7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKF9pbnB1dENvbmZpZy5sYXlvdXQpIHtcbiAgICAgICAgICAgIHZhciByID0gZXh0ZW5kRGVlcEFsbCh7fSwgX2lucHV0Q29uZmlnLmxheW91dCk7XG4gICAgICAgICAgICB2YXIgdG9UcmFuc2xhdGUgPSBbXG4gICAgICAgICAgICAgICAgWyByLCBbICdwbG90X2JnY29sb3InIF0sIFsgJ2JhY2tncm91bmRDb2xvcicgXSBdLFxuICAgICAgICAgICAgICAgIFsgciwgWyAnc2hvd2xlZ2VuZCcgXSwgWyAnc2hvd0xlZ2VuZCcgXSBdLFxuICAgICAgICAgICAgICAgIFsgciwgWyAncmFkaWFsYXhpcycgXSwgWyAncmFkaWFsQXhpcycgXSBdLFxuICAgICAgICAgICAgICAgIFsgciwgWyAnYW5ndWxhcmF4aXMnIF0sIFsgJ2FuZ3VsYXJBeGlzJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJheGlzLCBbICdzaG93bGluZScgXSwgWyAnZ3JpZExpbmVzVmlzaWJsZScgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5hbmd1bGFyYXhpcywgWyAnc2hvd3RpY2tsYWJlbHMnIF0sIFsgJ2xhYmVsc1Zpc2libGUnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhcmF4aXMsIFsgJ250aWNrcycgXSwgWyAndGlja3NDb3VudCcgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5hbmd1bGFyYXhpcywgWyAndGlja29yaWVudGF0aW9uJyBdLCBbICd0aWNrT3JpZW50YXRpb24nIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhcmF4aXMsIFsgJ3RpY2tzdWZmaXgnIF0sIFsgJ3RpY2tzU3VmZml4JyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJheGlzLCBbICdyYW5nZScgXSwgWyAnZG9tYWluJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJheGlzLCBbICdlbmRwYWRkaW5nJyBdLCBbICdlbmRQYWRkaW5nJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLnJhZGlhbGF4aXMsIFsgJ3Nob3dsaW5lJyBdLCBbICdncmlkTGluZXNWaXNpYmxlJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLnJhZGlhbGF4aXMsIFsgJ3RpY2tvcmllbnRhdGlvbicgXSwgWyAndGlja09yaWVudGF0aW9uJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLnJhZGlhbGF4aXMsIFsgJ3RpY2tzdWZmaXgnIF0sIFsgJ3RpY2tzU3VmZml4JyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLnJhZGlhbGF4aXMsIFsgJ3JhbmdlJyBdLCBbICdkb21haW4nIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhckF4aXMsIFsgJ3Nob3dsaW5lJyBdLCBbICdncmlkTGluZXNWaXNpYmxlJyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJBeGlzLCBbICdzaG93dGlja2xhYmVscycgXSwgWyAnbGFiZWxzVmlzaWJsZScgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5hbmd1bGFyQXhpcywgWyAnbnRpY2tzJyBdLCBbICd0aWNrc0NvdW50JyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLmFuZ3VsYXJBeGlzLCBbICd0aWNrb3JpZW50YXRpb24nIF0sIFsgJ3RpY2tPcmllbnRhdGlvbicgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5hbmd1bGFyQXhpcywgWyAndGlja3N1ZmZpeCcgXSwgWyAndGlja3NTdWZmaXgnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhckF4aXMsIFsgJ3JhbmdlJyBdLCBbICdkb21haW4nIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIuYW5ndWxhckF4aXMsIFsgJ2VuZHBhZGRpbmcnIF0sIFsgJ2VuZFBhZGRpbmcnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIucmFkaWFsQXhpcywgWyAnc2hvd2xpbmUnIF0sIFsgJ2dyaWRMaW5lc1Zpc2libGUnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIucmFkaWFsQXhpcywgWyAndGlja29yaWVudGF0aW9uJyBdLCBbICd0aWNrT3JpZW50YXRpb24nIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIucmFkaWFsQXhpcywgWyAndGlja3N1ZmZpeCcgXSwgWyAndGlja3NTdWZmaXgnIF0gXSxcbiAgICAgICAgICAgICAgICBbIHIucmFkaWFsQXhpcywgWyAncmFuZ2UnIF0sIFsgJ2RvbWFpbicgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5mb250LCBbICdvdXRsaW5lY29sb3InIF0sIFsgJ291dGxpbmVDb2xvcicgXSBdLFxuICAgICAgICAgICAgICAgIFsgci5sZWdlbmQsIFsgJ3RyYWNlb3JkZXInIF0sIFsgJ3JldmVyc2VPcmRlcicgXSBdLFxuICAgICAgICAgICAgICAgIFsgciwgWyAnbGFiZWxvZmZzZXQnIF0sIFsgJ2xhYmVsT2Zmc2V0JyBdIF0sXG4gICAgICAgICAgICAgICAgWyByLCBbICdkZWZhdWx0Y29sb3JyYW5nZScgXSwgWyAnZGVmYXVsdENvbG9yUmFuZ2UnIF0gXVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHRvVHJhbnNsYXRlLmZvckVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIMK1LnV0aWwudHJhbnNsYXRvci5hcHBseShudWxsLCBkLmNvbmNhdChyZXZlcnNlKSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKCFyZXZlcnNlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHIuYW5ndWxhckF4aXMgJiYgdHlwZW9mIHIuYW5ndWxhckF4aXMudGlja2xlbiAhPT0gJ3VuZGVmaW5lZCcpIHIudGlja0xlbmd0aCA9IHIuYW5ndWxhckF4aXMudGlja2xlbjtcbiAgICAgICAgICAgICAgICBpZiAoci5hbmd1bGFyQXhpcyAmJiB0eXBlb2Ygci5hbmd1bGFyQXhpcy50aWNrY29sb3IgIT09ICd1bmRlZmluZWQnKSByLnRpY2tDb2xvciA9IHIuYW5ndWxhckF4aXMudGlja2NvbG9yO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHIudGlja0xlbmd0aCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgci5hbmd1bGFyYXhpcy50aWNrbGVuID0gci50aWNrTGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgci50aWNrTGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoci50aWNrQ29sb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgci5hbmd1bGFyYXhpcy50aWNrY29sb3IgPSByLnRpY2tDb2xvcjtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHIudGlja0NvbG9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyLmxlZ2VuZCAmJiB0eXBlb2Ygci5sZWdlbmQucmV2ZXJzZU9yZGVyICE9ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgIHIubGVnZW5kLnJldmVyc2VPcmRlciA9IHIubGVnZW5kLnJldmVyc2VPcmRlciAhPSAnbm9ybWFsJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChyLmxlZ2VuZCAmJiB0eXBlb2Ygci5sZWdlbmQudHJhY2VvcmRlciA9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICByLmxlZ2VuZC50cmFjZW9yZGVyID0gci5sZWdlbmQudHJhY2VvcmRlciA/ICdyZXZlcnNlZCcgOiAnbm9ybWFsJztcbiAgICAgICAgICAgICAgICBkZWxldGUgci5sZWdlbmQucmV2ZXJzZU9yZGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHIubWFyZ2luICYmIHR5cGVvZiByLm1hcmdpbi50ICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNvdXJjZSA9IFsgJ3QnLCAncicsICdiJywgJ2wnLCAncGFkJyBdO1xuICAgICAgICAgICAgICAgIHZhciB0YXJnZXQgPSBbICd0b3AnLCAncmlnaHQnLCAnYm90dG9tJywgJ2xlZnQnLCAncGFkJyBdO1xuICAgICAgICAgICAgICAgIHZhciBtYXJnaW4gPSB7fTtcbiAgICAgICAgICAgICAgICBkMy5lbnRyaWVzKHIubWFyZ2luKS5mb3JFYWNoKGZ1bmN0aW9uKGRCLCBpQikge1xuICAgICAgICAgICAgICAgICAgICBtYXJnaW5bdGFyZ2V0W3NvdXJjZS5pbmRleE9mKGRCLmtleSldXSA9IGRCLnZhbHVlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHIubWFyZ2luID0gbWFyZ2luO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJldmVyc2UpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgci5uZWVkc0VuZFNwYWNpbmc7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHIubWlub3JUaWNrQ29sb3I7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHIubWlub3JUaWNrcztcbiAgICAgICAgICAgICAgICBkZWxldGUgci5hbmd1bGFyYXhpcy50aWNrc0NvdW50O1xuICAgICAgICAgICAgICAgIGRlbGV0ZSByLmFuZ3VsYXJheGlzLnRpY2tzQ291bnQ7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHIuYW5ndWxhcmF4aXMudGlja3NTdGVwO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSByLmFuZ3VsYXJheGlzLnJld3JpdGVUaWNrcztcbiAgICAgICAgICAgICAgICBkZWxldGUgci5hbmd1bGFyYXhpcy5udGlja3M7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHIucmFkaWFsYXhpcy50aWNrc0NvdW50O1xuICAgICAgICAgICAgICAgIGRlbGV0ZSByLnJhZGlhbGF4aXMudGlja3NDb3VudDtcbiAgICAgICAgICAgICAgICBkZWxldGUgci5yYWRpYWxheGlzLnRpY2tzU3RlcDtcbiAgICAgICAgICAgICAgICBkZWxldGUgci5yYWRpYWxheGlzLnJld3JpdGVUaWNrcztcbiAgICAgICAgICAgICAgICBkZWxldGUgci5yYWRpYWxheGlzLm50aWNrcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG91dHB1dENvbmZpZy5sYXlvdXQgPSByO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXRwdXRDb25maWc7XG4gICAgfTtcbiAgICByZXR1cm4gZXhwb3J0cztcbn07XG5cbn0se1wiLi4vLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudFwiOjY4OCxcIi4uLy4uLy4uL2xpYlwiOjcxOSxcImQzXCI6MTYzfV0sODM4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbi8qIGVzbGludC1kaXNhYmxlIG5ldy1jYXAgKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG52YXIgbWljcm9wb2xhciA9IF9kZXJlcV8oJy4vbWljcm9wb2xhcicpO1xudmFyIFVuZG9NYW5hZ2VyID0gX2RlcmVxXygnLi91bmRvX21hbmFnZXInKTtcbnZhciBleHRlbmREZWVwQWxsID0gTGliLmV4dGVuZERlZXBBbGw7XG5cbnZhciBtYW5hZ2VyID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxubWFuYWdlci5mcmFtZXdvcmsgPSBmdW5jdGlvbihfZ2QpIHtcbiAgICB2YXIgY29uZmlnLCBwcmV2aW91c0NvbmZpZ0Nsb25lLCBwbG90LCBjb252ZXJ0ZWRJbnB1dCwgY29udGFpbmVyO1xuICAgIHZhciB1bmRvTWFuYWdlciA9IG5ldyBVbmRvTWFuYWdlcigpO1xuXG4gICAgZnVuY3Rpb24gZXhwb3J0cyhfaW5wdXRDb25maWcsIF9jb250YWluZXIpIHtcbiAgICAgICAgaWYoX2NvbnRhaW5lcikgY29udGFpbmVyID0gX2NvbnRhaW5lcjtcbiAgICAgICAgZDMuc2VsZWN0KGQzLnNlbGVjdChjb250YWluZXIpLm5vZGUoKS5wYXJlbnROb2RlKS5zZWxlY3RBbGwoJy5zdmctY29udGFpbmVyPio6bm90KC5jaGFydC1yb290KScpLnJlbW92ZSgpO1xuXG4gICAgICAgIGNvbmZpZyA9ICghY29uZmlnKSA/XG4gICAgICAgICAgICBfaW5wdXRDb25maWcgOlxuICAgICAgICAgICAgZXh0ZW5kRGVlcEFsbChjb25maWcsIF9pbnB1dENvbmZpZyk7XG5cbiAgICAgICAgaWYoIXBsb3QpIHBsb3QgPSBtaWNyb3BvbGFyLkF4aXMoKTtcbiAgICAgICAgY29udmVydGVkSW5wdXQgPSBtaWNyb3BvbGFyLmFkYXB0ZXIucGxvdGx5KCkuY29udmVydChjb25maWcpO1xuICAgICAgICBwbG90LmNvbmZpZyhjb252ZXJ0ZWRJbnB1dCkucmVuZGVyKGNvbnRhaW5lcik7XG4gICAgICAgIF9nZC5kYXRhID0gY29uZmlnLmRhdGE7XG4gICAgICAgIF9nZC5sYXlvdXQgPSBjb25maWcubGF5b3V0O1xuICAgICAgICBtYW5hZ2VyLmZpbGxMYXlvdXQoX2dkKTtcbiAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICB9XG4gICAgZXhwb3J0cy5pc1BvbGFyID0gdHJ1ZTtcbiAgICBleHBvcnRzLnN2ZyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gcGxvdC5zdmcoKTsgfTtcbiAgICBleHBvcnRzLmdldENvbmZpZyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gY29uZmlnOyB9O1xuICAgIGV4cG9ydHMuZ2V0TGl2ZUNvbmZpZyA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gbWljcm9wb2xhci5hZGFwdGVyLnBsb3RseSgpLmNvbnZlcnQocGxvdC5nZXRMaXZlQ29uZmlnKCksIHRydWUpO1xuICAgIH07XG4gICAgZXhwb3J0cy5nZXRMaXZlU2NhbGVzID0gZnVuY3Rpb24oKSB7IHJldHVybiB7dDogcGxvdC5hbmd1bGFyU2NhbGUoKSwgcjogcGxvdC5yYWRpYWxTY2FsZSgpfTsgfTtcbiAgICBleHBvcnRzLnNldFVuZG9Qb2ludCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgIHZhciBjb25maWdDbG9uZSA9IG1pY3JvcG9sYXIudXRpbC5jbG9uZUpzb24oY29uZmlnKTtcbiAgICAgICAgKGZ1bmN0aW9uKF9jb25maWdDbG9uZSwgX3ByZXZpb3VzQ29uZmlnQ2xvbmUpIHtcbiAgICAgICAgICAgIHVuZG9NYW5hZ2VyLmFkZCh7XG4gICAgICAgICAgICAgICAgdW5kbzogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKF9wcmV2aW91c0NvbmZpZ0Nsb25lKSB0aGF0KF9wcmV2aW91c0NvbmZpZ0Nsb25lKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHJlZG86IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB0aGF0KF9jb25maWdDbG9uZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pKGNvbmZpZ0Nsb25lLCBwcmV2aW91c0NvbmZpZ0Nsb25lKTtcbiAgICAgICAgcHJldmlvdXNDb25maWdDbG9uZSA9IG1pY3JvcG9sYXIudXRpbC5jbG9uZUpzb24oY29uZmlnQ2xvbmUpO1xuICAgIH07XG4gICAgZXhwb3J0cy51bmRvID0gZnVuY3Rpb24oKSB7IHVuZG9NYW5hZ2VyLnVuZG8oKTsgfTtcbiAgICBleHBvcnRzLnJlZG8gPSBmdW5jdGlvbigpIHsgdW5kb01hbmFnZXIucmVkbygpOyB9O1xuICAgIHJldHVybiBleHBvcnRzO1xufTtcblxubWFuYWdlci5maWxsTGF5b3V0ID0gZnVuY3Rpb24oX2dkKSB7XG4gICAgdmFyIGNvbnRhaW5lciA9IGQzLnNlbGVjdChfZ2QpLnNlbGVjdEFsbCgnLnBsb3QtY29udGFpbmVyJyk7XG4gICAgdmFyIHBhcGVyRGl2ID0gY29udGFpbmVyLnNlbGVjdEFsbCgnLnN2Zy1jb250YWluZXInKTtcbiAgICB2YXIgcGFwZXIgPSBfZ2QuZnJhbWV3b3JrICYmIF9nZC5mcmFtZXdvcmsuc3ZnICYmIF9nZC5mcmFtZXdvcmsuc3ZnKCk7XG4gICAgdmFyIGRmbHRzID0ge1xuICAgICAgICB3aWR0aDogODAwLFxuICAgICAgICBoZWlnaHQ6IDYwMCxcbiAgICAgICAgcGFwZXJfYmdjb2xvcjogQ29sb3IuYmFja2dyb3VuZCxcbiAgICAgICAgX2NvbnRhaW5lcjogY29udGFpbmVyLFxuICAgICAgICBfcGFwZXJkaXY6IHBhcGVyRGl2LFxuICAgICAgICBfcGFwZXI6IHBhcGVyXG4gICAgfTtcblxuICAgIF9nZC5fZnVsbExheW91dCA9IGV4dGVuZERlZXBBbGwoZGZsdHMsIF9nZC5sYXlvdXQpO1xufTtcblxufSx7XCIuLi8uLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vLi4vbGliXCI6NzE5LFwiLi9taWNyb3BvbGFyXCI6ODM3LFwiLi91bmRvX21hbmFnZXJcIjo4MzksXCJkM1wiOjE2M31dLDgzOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8vIE1vZGlmaWVkIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL0FydGh1ckNsZW1lbnMvSmF2YXNjcmlwdC1VbmRvLU1hbmFnZXJcbi8vIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIEFydGh1ciBDbGVtZW5zLCBhcnRodXJAdmlzaWJsZWFyZWEuY29tXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIFVuZG9NYW5hZ2VyKCkge1xuICAgIHZhciB1bmRvQ29tbWFuZHMgPSBbXTtcbiAgICB2YXIgaW5kZXggPSAtMTtcbiAgICB2YXIgaXNFeGVjdXRpbmcgPSBmYWxzZTtcbiAgICB2YXIgY2FsbGJhY2s7XG5cbiAgICBmdW5jdGlvbiBleGVjdXRlKGNvbW1hbmQsIGFjdGlvbikge1xuICAgICAgICBpZighY29tbWFuZCkgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaXNFeGVjdXRpbmcgPSB0cnVlO1xuICAgICAgICBjb21tYW5kW2FjdGlvbl0oKTtcbiAgICAgICAgaXNFeGVjdXRpbmcgPSBmYWxzZTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBhZGQ6IGZ1bmN0aW9uKGNvbW1hbmQpIHtcbiAgICAgICAgICAgIGlmKGlzRXhlY3V0aW5nKSByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIHVuZG9Db21tYW5kcy5zcGxpY2UoaW5kZXggKyAxLCB1bmRvQ29tbWFuZHMubGVuZ3RoIC0gaW5kZXgpO1xuICAgICAgICAgICAgdW5kb0NvbW1hbmRzLnB1c2goY29tbWFuZCk7XG4gICAgICAgICAgICBpbmRleCA9IHVuZG9Db21tYW5kcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG4gICAgICAgIHNldENhbGxiYWNrOiBmdW5jdGlvbihjYWxsYmFja0Z1bmMpIHsgY2FsbGJhY2sgPSBjYWxsYmFja0Z1bmM7IH0sXG4gICAgICAgIHVuZG86IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGNvbW1hbmQgPSB1bmRvQ29tbWFuZHNbaW5kZXhdO1xuICAgICAgICAgICAgaWYoIWNvbW1hbmQpIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgZXhlY3V0ZShjb21tYW5kLCAndW5kbycpO1xuICAgICAgICAgICAgaW5kZXggLT0gMTtcbiAgICAgICAgICAgIGlmKGNhbGxiYWNrKSBjYWxsYmFjayhjb21tYW5kLnVuZG8pO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG4gICAgICAgIHJlZG86IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGNvbW1hbmQgPSB1bmRvQ29tbWFuZHNbaW5kZXggKyAxXTtcbiAgICAgICAgICAgIGlmKCFjb21tYW5kKSByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIGV4ZWN1dGUoY29tbWFuZCwgJ3JlZG8nKTtcbiAgICAgICAgICAgIGluZGV4ICs9IDE7XG4gICAgICAgICAgICBpZihjYWxsYmFjaykgY2FsbGJhY2soY29tbWFuZC5yZWRvKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuICAgICAgICBjbGVhcjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB1bmRvQ29tbWFuZHMgPSBbXTtcbiAgICAgICAgICAgIGluZGV4ID0gLTE7XG4gICAgICAgIH0sXG4gICAgICAgIGhhc1VuZG86IGZ1bmN0aW9uKCkgeyByZXR1cm4gaW5kZXggIT09IC0xOyB9LFxuICAgICAgICBoYXNSZWRvOiBmdW5jdGlvbigpIHsgcmV0dXJuIGluZGV4IDwgKHVuZG9Db21tYW5kcy5sZW5ndGggLSAxKTsgfSxcbiAgICAgICAgZ2V0Q29tbWFuZHM6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdW5kb0NvbW1hbmRzOyB9LFxuICAgICAgICBnZXRQcmV2aW91c0NvbW1hbmQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gdW5kb0NvbW1hbmRzW2luZGV4IC0gMV07IH0sXG4gICAgICAgIGdldEluZGV4OiBmdW5jdGlvbigpIHsgcmV0dXJuIGluZGV4OyB9XG4gICAgfTtcbn07XG5cbn0se31dLDg0MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgdGlueWNvbG9yID0gX2RlcmVxXygndGlueWNvbG9yMicpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBQbG90cyA9IF9kZXJlcV8oJy4uL3Bsb3RzJyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgc2V0Q29udmVydENhcnRlc2lhbiA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9zZXRfY29udmVydCcpO1xudmFyIHNldENvbnZlcnRQb2xhciA9IF9kZXJlcV8oJy4vc2V0X2NvbnZlcnQnKTtcbnZhciBkb0F1dG9SYW5nZSA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9hdXRvcmFuZ2UnKS5kb0F1dG9SYW5nZTtcbnZhciBkcmFnQm94ID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL2RyYWdib3gnKTtcbnZhciBkcmFnRWxlbWVudCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhZ2VsZW1lbnQnKTtcbnZhciBGeCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBUaXRsZXMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL3RpdGxlcycpO1xudmFyIHByZXBTZWxlY3QgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vc2VsZWN0JykucHJlcFNlbGVjdDtcbnZhciBzZWxlY3RPbkNsaWNrID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL3NlbGVjdCcpLnNlbGVjdE9uQ2xpY2s7XG52YXIgY2xlYXJTZWxlY3QgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vc2VsZWN0JykuY2xlYXJTZWxlY3Q7XG52YXIgc2V0Q3Vyc29yID0gX2RlcmVxXygnLi4vLi4vbGliL3NldGN1cnNvcicpO1xudmFyIGNsZWFyR2xDYW52YXNlcyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9jbGVhcl9nbF9jYW52YXNlcycpO1xudmFyIHJlZHJhd1JlZ2xUcmFjZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9zdWJyb3V0aW5lcycpLnJlZHJhd1JlZ2xUcmFjZXM7XG5cbnZhciBNSURfU0hJRlQgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50JykuTUlEX1NISUZUO1xudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xuXG52YXIgXyA9IExpYi5fO1xudmFyIG1vZCA9IExpYi5tb2Q7XG52YXIgZGVnMnJhZCA9IExpYi5kZWcycmFkO1xudmFyIHJhZDJkZWcgPSBMaWIucmFkMmRlZztcblxuZnVuY3Rpb24gUG9sYXIoZ2QsIGlkKSB7XG4gICAgdGhpcy5pZCA9IGlkO1xuICAgIHRoaXMuZ2QgPSBnZDtcblxuICAgIHRoaXMuX2hhc0NsaXBPbkF4aXNGYWxzZSA9IG51bGw7XG4gICAgdGhpcy52YW5nbGVzID0gbnVsbDtcbiAgICB0aGlzLnJhZGlhbEF4aXNBbmdsZSA9IG51bGw7XG4gICAgdGhpcy50cmFjZUhhc2ggPSB7fTtcbiAgICB0aGlzLmxheWVycyA9IHt9O1xuICAgIHRoaXMuY2xpcFBhdGhzID0ge307XG4gICAgdGhpcy5jbGlwSWRzID0ge307XG4gICAgdGhpcy52aWV3SW5pdGlhbCA9IHt9O1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2xpcElkQmFzZSA9ICdjbGlwJyArIGZ1bGxMYXlvdXQuX3VpZCArIGlkO1xuXG4gICAgdGhpcy5jbGlwSWRzLmZvclRyYWNlcyA9IGNsaXBJZEJhc2UgKyAnLWZvci10cmFjZXMnO1xuICAgIHRoaXMuY2xpcFBhdGhzLmZvclRyYWNlcyA9IGZ1bGxMYXlvdXQuX2NsaXBzLmFwcGVuZCgnY2xpcFBhdGgnKVxuICAgICAgICAuYXR0cignaWQnLCB0aGlzLmNsaXBJZHMuZm9yVHJhY2VzKTtcbiAgICB0aGlzLmNsaXBQYXRocy5mb3JUcmFjZXMuYXBwZW5kKCdwYXRoJyk7XG5cbiAgICB0aGlzLmZyYW1ld29yayA9IGZ1bGxMYXlvdXQuX3BvbGFybGF5ZXIuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgaWQpO1xuXG4gICAgLy8gdW5mb3J0dW5hdGVseSwgd2UgaGF2ZSB0byBrZWVwIHRyYWNrIG9mIHNvbWUgYXhpcyB0aWNrIHNldHRpbmdzXG4gICAgLy8gYXMgcG9sYXIgc3VicGxvdHMgZG8gbm90IGltcGxlbWVudCB0aGUgJ3RpY2tzJyBlZGl0VHlwZVxuICAgIHRoaXMucmFkaWFsVGlja0xheW91dCA9IG51bGw7XG4gICAgdGhpcy5hbmd1bGFyVGlja0xheW91dCA9IG51bGw7XG59XG5cbnZhciBwcm90byA9IFBvbGFyLnByb3RvdHlwZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGVQb2xhcihnZCwgaWQpIHtcbiAgICByZXR1cm4gbmV3IFBvbGFyKGdkLCBpZCk7XG59O1xuXG5wcm90by5wbG90ID0gZnVuY3Rpb24ocG9sYXJDYWxjRGF0YSwgZnVsbExheW91dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIHBvbGFyTGF5b3V0ID0gZnVsbExheW91dFtfdGhpcy5pZF07XG5cbiAgICBfdGhpcy5faGFzQ2xpcE9uQXhpc0ZhbHNlID0gZmFsc2U7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHBvbGFyQ2FsY0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gcG9sYXJDYWxjRGF0YVtpXVswXS50cmFjZTtcbiAgICAgICAgaWYodHJhY2UuY2xpcG9uYXhpcyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIF90aGlzLl9oYXNDbGlwT25BeGlzRmFsc2UgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfdGhpcy51cGRhdGVMYXllcnMoZnVsbExheW91dCwgcG9sYXJMYXlvdXQpO1xuICAgIF90aGlzLnVwZGF0ZUxheW91dChmdWxsTGF5b3V0LCBwb2xhckxheW91dCk7XG4gICAgUGxvdHMuZ2VuZXJhbFVwZGF0ZVBlclRyYWNlTW9kdWxlKF90aGlzLmdkLCBfdGhpcywgcG9sYXJDYWxjRGF0YSwgcG9sYXJMYXlvdXQpO1xuICAgIF90aGlzLnVwZGF0ZUZ4KGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KTtcbn07XG5cbnByb3RvLnVwZGF0ZUxheWVycyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgbGF5ZXJzID0gX3RoaXMubGF5ZXJzO1xuICAgIHZhciByYWRpYWxMYXlvdXQgPSBwb2xhckxheW91dC5yYWRpYWxheGlzO1xuICAgIHZhciBhbmd1bGFyTGF5b3V0ID0gcG9sYXJMYXlvdXQuYW5ndWxhcmF4aXM7XG4gICAgdmFyIGxheWVyTmFtZXMgPSBjb25zdGFudHMubGF5ZXJOYW1lcztcblxuICAgIHZhciBmcm9udFBsb3RJbmRleCA9IGxheWVyTmFtZXMuaW5kZXhPZignZnJvbnRwbG90Jyk7XG4gICAgdmFyIGxheWVyRGF0YSA9IGxheWVyTmFtZXMuc2xpY2UoMCwgZnJvbnRQbG90SW5kZXgpO1xuICAgIHZhciBpc0FuZ3VsYXJBeGlzQmVsb3dUcmFjZXMgPSBhbmd1bGFyTGF5b3V0LmxheWVyID09PSAnYmVsb3cgdHJhY2VzJztcbiAgICB2YXIgaXNSYWRpYWxBeGlzQmVsb3dUcmFjZXMgPSByYWRpYWxMYXlvdXQubGF5ZXIgPT09ICdiZWxvdyB0cmFjZXMnO1xuXG4gICAgaWYoaXNBbmd1bGFyQXhpc0JlbG93VHJhY2VzKSBsYXllckRhdGEucHVzaCgnYW5ndWxhci1saW5lJyk7XG4gICAgaWYoaXNSYWRpYWxBeGlzQmVsb3dUcmFjZXMpIGxheWVyRGF0YS5wdXNoKCdyYWRpYWwtbGluZScpO1xuICAgIGlmKGlzQW5ndWxhckF4aXNCZWxvd1RyYWNlcykgbGF5ZXJEYXRhLnB1c2goJ2FuZ3VsYXItYXhpcycpO1xuICAgIGlmKGlzUmFkaWFsQXhpc0JlbG93VHJhY2VzKSBsYXllckRhdGEucHVzaCgncmFkaWFsLWF4aXMnKTtcblxuICAgIGxheWVyRGF0YS5wdXNoKCdmcm9udHBsb3QnKTtcblxuICAgIGlmKCFpc0FuZ3VsYXJBeGlzQmVsb3dUcmFjZXMpIGxheWVyRGF0YS5wdXNoKCdhbmd1bGFyLWxpbmUnKTtcbiAgICBpZighaXNSYWRpYWxBeGlzQmVsb3dUcmFjZXMpIGxheWVyRGF0YS5wdXNoKCdyYWRpYWwtbGluZScpO1xuICAgIGlmKCFpc0FuZ3VsYXJBeGlzQmVsb3dUcmFjZXMpIGxheWVyRGF0YS5wdXNoKCdhbmd1bGFyLWF4aXMnKTtcbiAgICBpZighaXNSYWRpYWxBeGlzQmVsb3dUcmFjZXMpIGxheWVyRGF0YS5wdXNoKCdyYWRpYWwtYXhpcycpO1xuXG4gICAgdmFyIGpvaW4gPSBfdGhpcy5mcmFtZXdvcmsuc2VsZWN0QWxsKCcucG9sYXJzdWJsYXllcicpXG4gICAgICAgIC5kYXRhKGxheWVyRGF0YSwgU3RyaW5nKTtcblxuICAgIGpvaW4uZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCBmdW5jdGlvbihkKSB7IHJldHVybiAncG9sYXJzdWJsYXllciAnICsgZDt9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgc2VsID0gbGF5ZXJzW2RdID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgICAgICBzd2l0Y2goZCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2Zyb250cGxvdCc6XG4gICAgICAgICAgICAgICAgICAgIC8vIFRPRE8gYWRkIG9wdGlvbiB0byBwbGFjZSBpbiAnYmFja3Bsb3QnIGxheWVyPz9cbiAgICAgICAgICAgICAgICAgICAgc2VsLmFwcGVuZCgnZycpLmNsYXNzZWQoJ2JhcmxheWVyJywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHNlbC5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdzY2F0dGVybGF5ZXInLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnYmFja3Bsb3QnOlxuICAgICAgICAgICAgICAgICAgICBzZWwuYXBwZW5kKCdnJykuY2xhc3NlZCgnbWFwbGF5ZXInLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAncGxvdGJnJzpcbiAgICAgICAgICAgICAgICAgICAgbGF5ZXJzLmJnID0gc2VsLmFwcGVuZCgncGF0aCcpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdyYWRpYWwtZ3JpZCc6XG4gICAgICAgICAgICAgICAgICAgIHNlbC5zdHlsZSgnZmlsbCcsICdub25lJyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2FuZ3VsYXItZ3JpZCc6XG4gICAgICAgICAgICAgICAgICAgIHNlbC5zdHlsZSgnZmlsbCcsICdub25lJyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3JhZGlhbC1saW5lJzpcbiAgICAgICAgICAgICAgICAgICAgc2VsLmFwcGVuZCgnbGluZScpLnN0eWxlKCdmaWxsJywgJ25vbmUnKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnYW5ndWxhci1saW5lJzpcbiAgICAgICAgICAgICAgICAgICAgc2VsLmFwcGVuZCgncGF0aCcpLnN0eWxlKCdmaWxsJywgJ25vbmUnKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgam9pbi5vcmRlcigpO1xufTtcblxuLyogUG9sYXIgc3VicGxvdHMganVnZ2xlIHdpdGggNiAnYXhpcyBvYmplY3RzJyAoISksIHRoZXNlIGFyZTpcbiAqXG4gKiAtIHBvbGFyTGF5b3V0LnJhZGlhbGF4aXMgKGFrYSByYWRpYWxMYXlvdXQgaW4gdGhpcyBmaWxlKTpcbiAqIC0gcG9sYXJMYXlvdXQuYW5ndWxhcmF4aXMgKGFrYSBhbmd1bGFyTGF5b3V0IGluIHRoaXMgZmlsZSk6XG4gKiAgIHVzZWQgZm9yIGRhdGEgLT4gY2FsY2RhdGEgY29udmVyc2lvbnMgKGFrYSBkMmMpIGR1cmluZyB0aGUgY2FsYyBzdGVwXG4gKlxuICogLSB0aGlzLnJhZGlhbEF4aXNcbiAqICAgZXh0ZW5kcyBwb2xhckxheW91dC5yYWRpYWxheGlzLCBhZGRzIG1vY2tlZCAnZG9tYWluJyBhbmRcbiAqICAgZmV3IG90aGVyIGtleXMgaW4gb3JkZXIgdG8gcmV1c2UgQ2FydGVzaWFuIGRvQXV0b1JhbmdlIGFuZCB0aGUgQXhlc1xuICogICBkcmF3aW5nIHJvdXRpbmVzLlxuICogICB1c2VkIGZvciBjYWxjZGF0YSAtPiBnZW9tZXRyaWMgY29udmVyc2lvbnMgKGFrYSBjMmcpIGR1cmluZyB0aGUgcGxvdCBzdGVwXG4gKiAgICsgc2V0R2VvbWV0cnkgc2V0dXBzIGF4LmMyZyBmb3IgZ2l2ZW4gYXgucmFuZ2VcbiAqICAgKyBzZXRTY2FsZSBzZXR1cHMgYXguX20sYXguX2IgZm9yIGdpdmVuIGF4LnJhbmdlXG4gKlxuICogLSB0aGlzLmFuZ3VsYXJBeGlzXG4gKiAgIGV4dGVuZHMgcG9sYXJMYXlvdXQuYW5ndWxhcmF4aXMsIGFkZHMgbW9ja2VkICdyYW5nZScgYW5kICdkb21haW4nIGFuZFxuICogICBhIGZldyBvdGhlciBrZXlzIGluIG9yZGVyIHRvIHJldXNlIHRoZSBBeGVzIGRyYXdpbmcgcm91dGluZXMuXG4gKiAgIHVzZWQgZm9yIGNhbGNkYXRhIC0+IGdlb21ldHJpYyBjb252ZXJzaW9ucyAoYWthIGMyZykgZHVyaW5nIHRoZSBwbG90IHN0ZXBcbiAqICAgKyBzZXRHZW9tZXRyeSBzZXR1cHMgYXguYzJnIGdpdmVuIGF4LnJvdGF0aW9uLCBheC5kaXJlY3Rpb24gJiBheC5fY2F0ZWdvcmllcyxcbiAqICAgICAgICAgICAgICAgICBhbmQgbW9ja3MgYXgucmFuZ2VcbiAqICAgKyBzZXRTY2FsZSBzZXR1cHMgYXguX20sYXguX2Igd2l0aCB0aGF0IG1vY2tlZCBheC5yYW5nZVxuICpcbiAqIC0gdGhpcy54YXhpc1xuICogLSB0aGlzLnlheGlzXG4gKiAgIHNldHVwIHNvIHRoYXQgcG9sYXIgdHJhY2VzIGNhbiByZXVzZSBwbG90IG1ldGhvZHMgb2YgQ2FydGVzaWFuIHRyYWNlc1xuICogICB3aGljaCBtb3N0bHkgcmVseSBvbiAycGl4ZWwgbWV0aG9kcyAoZS5nIGF4LmMycClcbiAqL1xucHJvdG8udXBkYXRlTGF5b3V0ID0gZnVuY3Rpb24oZnVsbExheW91dCwgcG9sYXJMYXlvdXQpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBsYXllcnMgPSBfdGhpcy5sYXllcnM7XG4gICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZTtcblxuICAgIC8vIGF4aXMgYXR0cmlidXRlc1xuICAgIHZhciByYWRpYWxMYXlvdXQgPSBwb2xhckxheW91dC5yYWRpYWxheGlzO1xuICAgIHZhciBhbmd1bGFyTGF5b3V0ID0gcG9sYXJMYXlvdXQuYW5ndWxhcmF4aXM7XG4gICAgLy8gbGF5b3V0IGRvbWFpbnNcbiAgICB2YXIgeERvbWFpbiA9IHBvbGFyTGF5b3V0LmRvbWFpbi54O1xuICAgIHZhciB5RG9tYWluID0gcG9sYXJMYXlvdXQuZG9tYWluLnk7XG4gICAgLy8gb2Zmc2V0cyBmcm9tIHBhcGVyIGVkZ2UgdG8gbGF5b3V0IGRvbWFpbiBib3hcbiAgICBfdGhpcy54T2Zmc2V0ID0gZ3MubCArIGdzLncgKiB4RG9tYWluWzBdO1xuICAgIF90aGlzLnlPZmZzZXQgPSBncy50ICsgZ3MuaCAqICgxIC0geURvbWFpblsxXSk7XG4gICAgLy8gbGVuZ3RocyBvZiB0aGUgbGF5b3V0IGRvbWFpbiBib3hcbiAgICB2YXIgeExlbmd0aCA9IF90aGlzLnhMZW5ndGggPSBncy53ICogKHhEb21haW5bMV0gLSB4RG9tYWluWzBdKTtcbiAgICB2YXIgeUxlbmd0aCA9IF90aGlzLnlMZW5ndGggPSBncy5oICogKHlEb21haW5bMV0gLSB5RG9tYWluWzBdKTtcbiAgICAvLyBzZWN0b3IgdG8gcGxvdFxuICAgIHZhciBzZWN0b3IgPSBwb2xhckxheW91dC5zZWN0b3I7XG4gICAgX3RoaXMuc2VjdG9ySW5SYWQgPSBzZWN0b3IubWFwKGRlZzJyYWQpO1xuICAgIHZhciBzZWN0b3JCQm94ID0gX3RoaXMuc2VjdG9yQkJveCA9IGNvbXB1dGVTZWN0b3JCQm94KHNlY3Rvcik7XG4gICAgdmFyIGR4U2VjdG9yQkJveCA9IHNlY3RvckJCb3hbMl0gLSBzZWN0b3JCQm94WzBdO1xuICAgIHZhciBkeVNlY3RvckJCb3ggPSBzZWN0b3JCQm94WzNdIC0gc2VjdG9yQkJveFsxXTtcbiAgICAvLyBhc3BlY3QgcmF0aW9zXG4gICAgdmFyIGFyRG9tYWluID0geUxlbmd0aCAvIHhMZW5ndGg7XG4gICAgdmFyIGFyU2VjdG9yID0gTWF0aC5hYnMoZHlTZWN0b3JCQm94IC8gZHhTZWN0b3JCQm94KTtcbiAgICAvLyBhY3R1YWwgbGVuZ3RocyBhbmQgZG9tYWlucyBvZiBzdWJwbG90IGJveFxuICAgIHZhciB4TGVuZ3RoMiwgeUxlbmd0aDI7XG4gICAgdmFyIHhEb21haW4yLCB5RG9tYWluMjtcbiAgICB2YXIgZ2FwO1xuICAgIGlmKGFyRG9tYWluID4gYXJTZWN0b3IpIHtcbiAgICAgICAgeExlbmd0aDIgPSB4TGVuZ3RoO1xuICAgICAgICB5TGVuZ3RoMiA9IHhMZW5ndGggKiBhclNlY3RvcjtcbiAgICAgICAgZ2FwID0gKHlMZW5ndGggLSB5TGVuZ3RoMikgLyBncy5oIC8gMjtcbiAgICAgICAgeERvbWFpbjIgPSBbeERvbWFpblswXSwgeERvbWFpblsxXV07XG4gICAgICAgIHlEb21haW4yID0gW3lEb21haW5bMF0gKyBnYXAsIHlEb21haW5bMV0gLSBnYXBdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHhMZW5ndGgyID0geUxlbmd0aCAvIGFyU2VjdG9yO1xuICAgICAgICB5TGVuZ3RoMiA9IHlMZW5ndGg7XG4gICAgICAgIGdhcCA9ICh4TGVuZ3RoIC0geExlbmd0aDIpIC8gZ3MudyAvIDI7XG4gICAgICAgIHhEb21haW4yID0gW3hEb21haW5bMF0gKyBnYXAsIHhEb21haW5bMV0gLSBnYXBdO1xuICAgICAgICB5RG9tYWluMiA9IFt5RG9tYWluWzBdLCB5RG9tYWluWzFdXTtcbiAgICB9XG4gICAgX3RoaXMueExlbmd0aDIgPSB4TGVuZ3RoMjtcbiAgICBfdGhpcy55TGVuZ3RoMiA9IHlMZW5ndGgyO1xuICAgIF90aGlzLnhEb21haW4yID0geERvbWFpbjI7XG4gICAgX3RoaXMueURvbWFpbjIgPSB5RG9tYWluMjtcbiAgICAvLyBhY3R1YWwgb2Zmc2V0cyBmcm9tIHBhcGVyIGVkZ2UgdG8gdGhlIHN1YnBsb3QgYm94IHRvcC1sZWZ0IGNvcm5lclxuICAgIHZhciB4T2Zmc2V0MiA9IF90aGlzLnhPZmZzZXQyID0gZ3MubCArIGdzLncgKiB4RG9tYWluMlswXTtcbiAgICB2YXIgeU9mZnNldDIgPSBfdGhpcy55T2Zmc2V0MiA9IGdzLnQgKyBncy5oICogKDEgLSB5RG9tYWluMlsxXSk7XG4gICAgLy8gY2lyY2xlIHJhZGl1cyBpbiBweFxuICAgIHZhciByYWRpdXMgPSBfdGhpcy5yYWRpdXMgPSB4TGVuZ3RoMiAvIGR4U2VjdG9yQkJveDtcbiAgICAvLyAnaW5uZXInIHJhZGl1cyBpbiBweCAod2hlbiBwb2xhci5ob2xlIGlzIHNldClcbiAgICB2YXIgaW5uZXJSYWRpdXMgPSBfdGhpcy5pbm5lclJhZGl1cyA9IHBvbGFyTGF5b3V0LmhvbGUgKiByYWRpdXM7XG4gICAgLy8gY2lyY2xlIGNlbnRlciBwb3NpdGlvbiBpbiBweFxuICAgIHZhciBjeCA9IF90aGlzLmN4ID0geE9mZnNldDIgLSByYWRpdXMgKiBzZWN0b3JCQm94WzBdO1xuICAgIHZhciBjeSA9IF90aGlzLmN5ID0geU9mZnNldDIgKyByYWRpdXMgKiBzZWN0b3JCQm94WzNdO1xuICAgIC8vIGNpcmNsZSBjZW50ZXIgaW4gdGhlIGNvb3JkaW5hdGUgc3lzdGVtIG9mIHBsb3QgYXJlYVxuICAgIHZhciBjeHggPSBfdGhpcy5jeHggPSBjeCAtIHhPZmZzZXQyO1xuICAgIHZhciBjeXkgPSBfdGhpcy5jeXkgPSBjeSAtIHlPZmZzZXQyO1xuXG4gICAgX3RoaXMucmFkaWFsQXhpcyA9IF90aGlzLm1vY2tBeGlzKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0LCByYWRpYWxMYXlvdXQsIHtcbiAgICAgICAgLy8gbWFrZSB0aGlzIGFuICd4JyBheGlzIHRvIG1ha2UgcG9zaXRpb25pbmcgKGVzcGVjaWFsbHkgcm90YXRpb24pIGVhc2llclxuICAgICAgICBfaWQ6ICd4JyxcbiAgICAgICAgLy8gY29udmVydCB0byAneCcgYXhpcyBlcXVpdmFsZW50XG4gICAgICAgIHNpZGU6IHtcbiAgICAgICAgICAgIGNvdW50ZXJjbG9ja3dpc2U6ICd0b3AnLFxuICAgICAgICAgICAgY2xvY2t3aXNlOiAnYm90dG9tJ1xuICAgICAgICB9W3JhZGlhbExheW91dC5zaWRlXSxcbiAgICAgICAgLy8gc3BhbnMgbGVuZ3RoIDEgcmFkaXVzXG4gICAgICAgIGRvbWFpbjogW2lubmVyUmFkaXVzIC8gZ3MudywgcmFkaXVzIC8gZ3Mud11cbiAgICB9KTtcblxuICAgIF90aGlzLmFuZ3VsYXJBeGlzID0gX3RoaXMubW9ja0F4aXMoZnVsbExheW91dCwgcG9sYXJMYXlvdXQsIGFuZ3VsYXJMYXlvdXQsIHtcbiAgICAgICAgc2lkZTogJ3JpZ2h0JyxcbiAgICAgICAgLy8gdG8gZ2V0IGF1dG8gbnRpY2tzIHJpZ2h0XG4gICAgICAgIGRvbWFpbjogWzAsIE1hdGguUEldLFxuICAgICAgICAvLyBkb24ndCBwYXNzIHRocm91Z2ggYXV0b3JhbmdlIGxvZ2ljXG4gICAgICAgIGF1dG9yYW5nZTogZmFsc2VcbiAgICB9KTtcblxuICAgIF90aGlzLmRvQXV0b1JhbmdlKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KTtcbiAgICAvLyBOLkIuIHRoaXMgc2V0cyBfdGhpcy52YW5nbGVzXG4gICAgX3RoaXMudXBkYXRlQW5ndWxhckF4aXMoZnVsbExheW91dCwgcG9sYXJMYXlvdXQpO1xuICAgIC8vIE4uQi4gdGhpcyBzZXRzIF90aGlzLnJhZGlhbEF4aXNBbmdsZVxuICAgIF90aGlzLnVwZGF0ZVJhZGlhbEF4aXMoZnVsbExheW91dCwgcG9sYXJMYXlvdXQpO1xuICAgIF90aGlzLnVwZGF0ZVJhZGlhbEF4aXNUaXRsZShmdWxsTGF5b3V0LCBwb2xhckxheW91dCk7XG5cbiAgICBfdGhpcy54YXhpcyA9IF90aGlzLm1vY2tDYXJ0ZXNpYW5BeGlzKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0LCB7XG4gICAgICAgIF9pZDogJ3gnLFxuICAgICAgICBkb21haW46IHhEb21haW4yXG4gICAgfSk7XG5cbiAgICBfdGhpcy55YXhpcyA9IF90aGlzLm1vY2tDYXJ0ZXNpYW5BeGlzKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0LCB7XG4gICAgICAgIF9pZDogJ3knLFxuICAgICAgICBkb21haW46IHlEb21haW4yXG4gICAgfSk7XG5cbiAgICB2YXIgZFBhdGggPSBfdGhpcy5wYXRoU3VicGxvdCgpO1xuXG4gICAgX3RoaXMuY2xpcFBhdGhzLmZvclRyYWNlcy5zZWxlY3QoJ3BhdGgnKVxuICAgICAgICAuYXR0cignZCcsIGRQYXRoKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgc3RyVHJhbnNsYXRlKGN4eCwgY3l5KSk7XG5cbiAgICBsYXllcnMuZnJvbnRwbG90XG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBzdHJUcmFuc2xhdGUoeE9mZnNldDIsIHlPZmZzZXQyKSlcbiAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRDbGlwVXJsLCBfdGhpcy5faGFzQ2xpcE9uQXhpc0ZhbHNlID8gbnVsbCA6IF90aGlzLmNsaXBJZHMuZm9yVHJhY2VzLCBfdGhpcy5nZCk7XG5cbiAgICBsYXllcnMuYmdcbiAgICAgICAgLmF0dHIoJ2QnLCBkUGF0aClcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHN0clRyYW5zbGF0ZShjeCwgY3kpKVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBwb2xhckxheW91dC5iZ2NvbG9yKTtcbn07XG5cbnByb3RvLm1vY2tBeGlzID0gZnVuY3Rpb24oZnVsbExheW91dCwgcG9sYXJMYXlvdXQsIGF4TGF5b3V0LCBvcHRzKSB7XG4gICAgdmFyIGNvbW1vbk9wdHMgPSB7XG4gICAgICAgIC8vIHRvIGdldCBfYm91bmRpbmdCb3ggY29tcHV0YXRpb24gcmlnaHQgd2hlbiBzaG93dGlja2xhYmVscyBpcyBmYWxzZVxuICAgICAgICBhbmNob3I6ICdmcmVlJyxcbiAgICAgICAgcG9zaXRpb246IDBcbiAgICB9O1xuXG4gICAgdmFyIGF4ID0gTGliLmV4dGVuZEZsYXQoY29tbW9uT3B0cywgYXhMYXlvdXQsIG9wdHMpO1xuICAgIHNldENvbnZlcnRQb2xhcihheCwgcG9sYXJMYXlvdXQsIGZ1bGxMYXlvdXQpO1xuICAgIHJldHVybiBheDtcbn07XG5cbnByb3RvLm1vY2tDYXJ0ZXNpYW5BeGlzID0gZnVuY3Rpb24oZnVsbExheW91dCwgcG9sYXJMYXlvdXQsIG9wdHMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBheElkID0gb3B0cy5faWQ7XG5cbiAgICB2YXIgYXggPSBMaWIuZXh0ZW5kRmxhdCh7dHlwZTogJ2xpbmVhcid9LCBvcHRzKTtcbiAgICBzZXRDb252ZXJ0Q2FydGVzaWFuKGF4LCBmdWxsTGF5b3V0KTtcblxuICAgIHZhciBiYm94SW5kaWNlcyA9IHtcbiAgICAgICAgeDogWzAsIDJdLFxuICAgICAgICB5OiBbMSwgM11cbiAgICB9O1xuXG4gICAgYXguc2V0UmFuZ2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHNlY3RvckJCb3ggPSBfdGhpcy5zZWN0b3JCQm94O1xuICAgICAgICB2YXIgaW5kID0gYmJveEluZGljZXNbYXhJZF07XG4gICAgICAgIHZhciBybCA9IF90aGlzLnJhZGlhbEF4aXMuX3JsO1xuICAgICAgICB2YXIgZHJsID0gKHJsWzFdIC0gcmxbMF0pIC8gKDEgLSBwb2xhckxheW91dC5ob2xlKTtcbiAgICAgICAgYXgucmFuZ2UgPSBbc2VjdG9yQkJveFtpbmRbMF1dICogZHJsLCBzZWN0b3JCQm94W2luZFsxXV0gKiBkcmxdO1xuICAgIH07XG5cbiAgICBheC5pc1B0V2l0aGluUmFuZ2UgPSBheElkID09PSAneCcgP1xuICAgICAgICBmdW5jdGlvbihkKSB7IHJldHVybiBfdGhpcy5pc1B0SW5zaWRlKGQpOyB9IDpcbiAgICAgICAgZnVuY3Rpb24oKSB7IHJldHVybiB0cnVlOyB9O1xuXG4gICAgYXguc2V0UmFuZ2UoKTtcbiAgICBheC5zZXRTY2FsZSgpO1xuICAgIHJldHVybiBheDtcbn07XG5cbnByb3RvLmRvQXV0b1JhbmdlID0gZnVuY3Rpb24oZnVsbExheW91dCwgcG9sYXJMYXlvdXQpIHtcbiAgICB2YXIgZ2QgPSB0aGlzLmdkO1xuICAgIHZhciByYWRpYWxBeGlzID0gdGhpcy5yYWRpYWxBeGlzO1xuICAgIHZhciByYWRpYWxMYXlvdXQgPSBwb2xhckxheW91dC5yYWRpYWxheGlzO1xuXG4gICAgcmFkaWFsQXhpcy5zZXRTY2FsZSgpO1xuICAgIGRvQXV0b1JhbmdlKGdkLCByYWRpYWxBeGlzKTtcblxuICAgIHZhciBybmcgPSByYWRpYWxBeGlzLnJhbmdlO1xuICAgIHJhZGlhbExheW91dC5yYW5nZSA9IHJuZy5zbGljZSgpO1xuICAgIHJhZGlhbExheW91dC5faW5wdXQucmFuZ2UgPSBybmcuc2xpY2UoKTtcblxuICAgIHJhZGlhbEF4aXMuX3JsID0gW1xuICAgICAgICByYWRpYWxBeGlzLnIybChybmdbMF0sIG51bGwsICdncmVnb3JpYW4nKSxcbiAgICAgICAgcmFkaWFsQXhpcy5yMmwocm5nWzFdLCBudWxsLCAnZ3JlZ29yaWFuJylcbiAgICBdO1xufTtcblxucHJvdG8udXBkYXRlUmFkaWFsQXhpcyA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgZ2QgPSBfdGhpcy5nZDtcbiAgICB2YXIgbGF5ZXJzID0gX3RoaXMubGF5ZXJzO1xuICAgIHZhciByYWRpdXMgPSBfdGhpcy5yYWRpdXM7XG4gICAgdmFyIGlubmVyUmFkaXVzID0gX3RoaXMuaW5uZXJSYWRpdXM7XG4gICAgdmFyIGN4ID0gX3RoaXMuY3g7XG4gICAgdmFyIGN5ID0gX3RoaXMuY3k7XG4gICAgdmFyIHJhZGlhbExheW91dCA9IHBvbGFyTGF5b3V0LnJhZGlhbGF4aXM7XG4gICAgdmFyIGEwID0gbW9kKHBvbGFyTGF5b3V0LnNlY3RvclswXSwgMzYwKTtcbiAgICB2YXIgYXggPSBfdGhpcy5yYWRpYWxBeGlzO1xuICAgIHZhciBoYXNSb29tRm9ySXQgPSBpbm5lclJhZGl1cyA8IHJhZGl1cztcblxuICAgIF90aGlzLmZpbGxWaWV3SW5pdGlhbEtleSgncmFkaWFsYXhpcy5hbmdsZScsIHJhZGlhbExheW91dC5hbmdsZSk7XG4gICAgX3RoaXMuZmlsbFZpZXdJbml0aWFsS2V5KCdyYWRpYWxheGlzLnJhbmdlJywgYXgucmFuZ2Uuc2xpY2UoKSk7XG5cbiAgICBheC5zZXRHZW9tZXRyeSgpO1xuXG4gICAgLy8gcm90YXRlIGF1dG8gdGljayBsYWJlbHMgYnkgMTgwIGlmIGluIHF1YWRyYW50IElJIGFuZCBJSUkgdG8gbWFrZSB0aGVtXG4gICAgLy8gcmVhZGFibGUgZnJvbSBsZWZ0LXRvLXJpZ2h0XG4gICAgLy9cbiAgICAvLyBUT0RPIHRyeSBtb3ZpbmcgZGVlcGVyIGluIEF4ZXMuZHJhd0xhYmVscyBmb3IgYmV0dGVyIHJlc3VsdHM/XG4gICAgaWYoYXgudGlja2FuZ2xlID09PSAnYXV0bycgJiYgKGEwID4gOTAgJiYgYTAgPD0gMjcwKSkge1xuICAgICAgICBheC50aWNrYW5nbGUgPSAxODA7XG4gICAgfVxuXG4gICAgLy8gZWFzaWVyIHRvIHNldCByb3RhdGUgYW5nbGUgd2l0aCBjdXN0b20gdHJhbnNsYXRlIGZ1bmN0aW9uXG4gICAgdmFyIHRyYW5zRm4gPSBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyAoYXgubDJwKGQueCkgKyBpbm5lclJhZGl1cykgKyAnLDApJztcbiAgICB9O1xuXG4gICAgLy8gc2V0IHNwZWNpYWwgZ3JpZCBwYXRoIGZ1bmN0aW9uXG4gICAgdmFyIGdyaWRQYXRoRm4gPSBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBfdGhpcy5wYXRoQXJjKGF4LnIycChkLngpICsgaW5uZXJSYWRpdXMpO1xuICAgIH07XG5cbiAgICB2YXIgbmV3VGlja0xheW91dCA9IHN0clRpY2tMYXlvdXQocmFkaWFsTGF5b3V0KTtcbiAgICBpZihfdGhpcy5yYWRpYWxUaWNrTGF5b3V0ICE9PSBuZXdUaWNrTGF5b3V0KSB7XG4gICAgICAgIGxheWVyc1sncmFkaWFsLWF4aXMnXS5zZWxlY3RBbGwoJy54dGljaycpLnJlbW92ZSgpO1xuICAgICAgICBfdGhpcy5yYWRpYWxUaWNrTGF5b3V0ID0gbmV3VGlja0xheW91dDtcbiAgICB9XG5cbiAgICBpZihoYXNSb29tRm9ySXQpIHtcbiAgICAgICAgYXguc2V0U2NhbGUoKTtcblxuICAgICAgICB2YXIgdmFscyA9IEF4ZXMuY2FsY1RpY2tzKGF4KTtcbiAgICAgICAgdmFyIHZhbHNDbGlwcGVkID0gQXhlcy5jbGlwRW5kcyhheCwgdmFscyk7XG4gICAgICAgIHZhciB0aWNrU2lnbiA9IEF4ZXMuZ2V0VGlja1NpZ25zKGF4KVsyXTtcblxuICAgICAgICBBeGVzLmRyYXdUaWNrcyhnZCwgYXgsIHtcbiAgICAgICAgICAgIHZhbHM6IHZhbHMsXG4gICAgICAgICAgICBsYXllcjogbGF5ZXJzWydyYWRpYWwtYXhpcyddLFxuICAgICAgICAgICAgcGF0aDogQXhlcy5tYWtlVGlja1BhdGgoYXgsIDAsIHRpY2tTaWduKSxcbiAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm4sXG4gICAgICAgICAgICBjcmlzcDogZmFsc2VcbiAgICAgICAgfSk7XG5cbiAgICAgICAgQXhlcy5kcmF3R3JpZChnZCwgYXgsIHtcbiAgICAgICAgICAgIHZhbHM6IHZhbHNDbGlwcGVkLFxuICAgICAgICAgICAgbGF5ZXI6IGxheWVyc1sncmFkaWFsLWdyaWQnXSxcbiAgICAgICAgICAgIHBhdGg6IGdyaWRQYXRoRm4sXG4gICAgICAgICAgICB0cmFuc0ZuOiBMaWIubm9vcCxcbiAgICAgICAgICAgIGNyaXNwOiBmYWxzZVxuICAgICAgICB9KTtcblxuICAgICAgICBBeGVzLmRyYXdMYWJlbHMoZ2QsIGF4LCB7XG4gICAgICAgICAgICB2YWxzOiB2YWxzLFxuICAgICAgICAgICAgbGF5ZXI6IGxheWVyc1sncmFkaWFsLWF4aXMnXSxcbiAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm4sXG4gICAgICAgICAgICBsYWJlbEZuczogQXhlcy5tYWtlTGFiZWxGbnMoYXgsIDApXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIHN0YXNoICdhY3R1YWwnIHJhZGlhbCBheGlzIGFuZ2xlIGZvciBkcmFnIGhhbmRsZXJzIChpbiBkZWdyZWVzKVxuICAgIHZhciBhbmdsZSA9IF90aGlzLnJhZGlhbEF4aXNBbmdsZSA9IF90aGlzLnZhbmdsZXMgP1xuICAgICAgICByYWQyZGVnKHNuYXBUb1ZlcnRleEFuZ2xlKGRlZzJyYWQocmFkaWFsTGF5b3V0LmFuZ2xlKSwgX3RoaXMudmFuZ2xlcykpIDpcbiAgICAgICAgcmFkaWFsTGF5b3V0LmFuZ2xlO1xuXG4gICAgdmFyIHRMYXllciA9IHN0clRyYW5zbGF0ZShjeCwgY3kpO1xuICAgIHZhciB0TGF5ZXIyID0gdExheWVyICsgc3RyUm90YXRlKC1hbmdsZSk7XG5cbiAgICB1cGRhdGVFbGVtZW50KFxuICAgICAgICBsYXllcnNbJ3JhZGlhbC1heGlzJ10sXG4gICAgICAgIGhhc1Jvb21Gb3JJdCAmJiAocmFkaWFsTGF5b3V0LnNob3d0aWNrbGFiZWxzIHx8IHJhZGlhbExheW91dC50aWNrcyksXG4gICAgICAgIHt0cmFuc2Zvcm06IHRMYXllcjJ9XG4gICAgKTtcblxuICAgIHVwZGF0ZUVsZW1lbnQoXG4gICAgICAgIGxheWVyc1sncmFkaWFsLWdyaWQnXSxcbiAgICAgICAgaGFzUm9vbUZvckl0ICYmIHJhZGlhbExheW91dC5zaG93Z3JpZCxcbiAgICAgICAge3RyYW5zZm9ybTogdExheWVyfVxuICAgICk7XG5cbiAgICB1cGRhdGVFbGVtZW50KFxuICAgICAgICBsYXllcnNbJ3JhZGlhbC1saW5lJ10uc2VsZWN0KCdsaW5lJyksXG4gICAgICAgIGhhc1Jvb21Gb3JJdCAmJiByYWRpYWxMYXlvdXQuc2hvd2xpbmUsXG4gICAgICAgIHtcbiAgICAgICAgICAgIHgxOiBpbm5lclJhZGl1cyxcbiAgICAgICAgICAgIHkxOiAwLFxuICAgICAgICAgICAgeDI6IHJhZGl1cyxcbiAgICAgICAgICAgIHkyOiAwLFxuICAgICAgICAgICAgdHJhbnNmb3JtOiB0TGF5ZXIyXG4gICAgICAgIH1cbiAgICApXG4gICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIHJhZGlhbExheW91dC5saW5ld2lkdGgpXG4gICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCByYWRpYWxMYXlvdXQubGluZWNvbG9yKTtcbn07XG5cbnByb3RvLnVwZGF0ZVJhZGlhbEF4aXNUaXRsZSA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0LCBfYW5nbGUpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBnZCA9IF90aGlzLmdkO1xuICAgIHZhciByYWRpdXMgPSBfdGhpcy5yYWRpdXM7XG4gICAgdmFyIGN4ID0gX3RoaXMuY3g7XG4gICAgdmFyIGN5ID0gX3RoaXMuY3k7XG4gICAgdmFyIHJhZGlhbExheW91dCA9IHBvbGFyTGF5b3V0LnJhZGlhbGF4aXM7XG4gICAgdmFyIHRpdGxlQ2xhc3MgPSBfdGhpcy5pZCArICd0aXRsZSc7XG5cbiAgICB2YXIgYW5nbGUgPSBfYW5nbGUgIT09IHVuZGVmaW5lZCA/IF9hbmdsZSA6IF90aGlzLnJhZGlhbEF4aXNBbmdsZTtcbiAgICB2YXIgYW5nbGVSYWQgPSBkZWcycmFkKGFuZ2xlKTtcbiAgICB2YXIgY29zYSA9IE1hdGguY29zKGFuZ2xlUmFkKTtcbiAgICB2YXIgc2luYSA9IE1hdGguc2luKGFuZ2xlUmFkKTtcblxuICAgIHZhciBwYWQgPSAwO1xuXG4gICAgLy8gSGludDogbm8gbmVlZCB0byBjaGVjayBpZiB0aGVyZSBpcyBpbiBmYWN0IGEgdGl0bGUudGV4dCBzZXRcbiAgICAvLyBiZWNhdXNlIGlmIHBsb3QgaXMgZWRpdGFibGUsIHBhZCBuZWVkcyB0byBiZSBjYWxjdWxhdGVkIGFueXdheXNcbiAgICAvLyB0byBwcm9wZXJseSBzaG93IHBsYWNlaG9sZGVyIHRleHQgd2hlbiB0aXRsZSBpcyBlbXB0eS5cbiAgICBpZihyYWRpYWxMYXlvdXQudGl0bGUpIHtcbiAgICAgICAgdmFyIGggPSBEcmF3aW5nLmJCb3goX3RoaXMubGF5ZXJzWydyYWRpYWwtYXhpcyddLm5vZGUoKSkuaGVpZ2h0O1xuICAgICAgICB2YXIgdHMgPSByYWRpYWxMYXlvdXQudGl0bGUuZm9udC5zaXplO1xuICAgICAgICBwYWQgPSByYWRpYWxMYXlvdXQuc2lkZSA9PT0gJ2NvdW50ZXJjbG9ja3dpc2UnID9cbiAgICAgICAgICAgIC1oIC0gdHMgKiAwLjQgOlxuICAgICAgICAgICAgaCArIHRzICogMC44O1xuICAgIH1cblxuICAgIF90aGlzLmxheWVyc1sncmFkaWFsLWF4aXMtdGl0bGUnXSA9IFRpdGxlcy5kcmF3KGdkLCB0aXRsZUNsYXNzLCB7XG4gICAgICAgIHByb3BDb250YWluZXI6IHJhZGlhbExheW91dCxcbiAgICAgICAgcHJvcE5hbWU6IF90aGlzLmlkICsgJy5yYWRpYWxheGlzLnRpdGxlJyxcbiAgICAgICAgcGxhY2Vob2xkZXI6IF8oZ2QsICdDbGljayB0byBlbnRlciByYWRpYWwgYXhpcyB0aXRsZScpLFxuICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICB4OiBjeCArIChyYWRpdXMgLyAyKSAqIGNvc2EgKyBwYWQgKiBzaW5hLFxuICAgICAgICAgICAgeTogY3kgLSAocmFkaXVzIC8gMikgKiBzaW5hICsgcGFkICogY29zYSxcbiAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6ICdtaWRkbGUnXG4gICAgICAgIH0sXG4gICAgICAgIHRyYW5zZm9ybToge3JvdGF0ZTogLWFuZ2xlfVxuICAgIH0pO1xufTtcblxucHJvdG8udXBkYXRlQW5ndWxhckF4aXMgPSBmdW5jdGlvbihmdWxsTGF5b3V0LCBwb2xhckxheW91dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGdkID0gX3RoaXMuZ2Q7XG4gICAgdmFyIGxheWVycyA9IF90aGlzLmxheWVycztcbiAgICB2YXIgcmFkaXVzID0gX3RoaXMucmFkaXVzO1xuICAgIHZhciBpbm5lclJhZGl1cyA9IF90aGlzLmlubmVyUmFkaXVzO1xuICAgIHZhciBjeCA9IF90aGlzLmN4O1xuICAgIHZhciBjeSA9IF90aGlzLmN5O1xuICAgIHZhciBhbmd1bGFyTGF5b3V0ID0gcG9sYXJMYXlvdXQuYW5ndWxhcmF4aXM7XG4gICAgdmFyIGF4ID0gX3RoaXMuYW5ndWxhckF4aXM7XG5cbiAgICBfdGhpcy5maWxsVmlld0luaXRpYWxLZXkoJ2FuZ3VsYXJheGlzLnJvdGF0aW9uJywgYW5ndWxhckxheW91dC5yb3RhdGlvbik7XG5cbiAgICBheC5zZXRHZW9tZXRyeSgpO1xuICAgIGF4LnNldFNjYWxlKCk7XG5cbiAgICAvLyAndCdpY2sgdG8gJ2cnZW9tZXRyaWMgcmFkaWFucyBpcyB1c2VkIGFsbCBvdmVyIHRoZSBwbGFjZSBoZXJlXG4gICAgdmFyIHQyZyA9IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGF4LnQyZyhkLngpOyB9O1xuXG4gICAgLy8gcnVuIHJhZDJkZWcgb24gdGljazAgYW5kIGRpdGNrIGZvciB0aGV0YXVuaXQ6ICdyYWRpYW5zJyBheGVzXG4gICAgaWYoYXgudHlwZSA9PT0gJ2xpbmVhcicgJiYgYXgudGhldGF1bml0ID09PSAncmFkaWFucycpIHtcbiAgICAgICAgYXgudGljazAgPSByYWQyZGVnKGF4LnRpY2swKTtcbiAgICAgICAgYXguZHRpY2sgPSByYWQyZGVnKGF4LmR0aWNrKTtcbiAgICB9XG5cbiAgICB2YXIgX3RyYW5zRm4gPSBmdW5jdGlvbihyYWQpIHtcbiAgICAgICAgcmV0dXJuIHN0clRyYW5zbGF0ZShjeCArIHJhZGl1cyAqIE1hdGguY29zKHJhZCksIGN5IC0gcmFkaXVzICogTWF0aC5zaW4ocmFkKSk7XG4gICAgfTtcblxuICAgIHZhciB0cmFuc0ZuID0gZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gX3RyYW5zRm4odDJnKGQpKTtcbiAgICB9O1xuXG4gICAgdmFyIHRyYW5zRm4yID0gZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgcmFkID0gdDJnKGQpO1xuICAgICAgICByZXR1cm4gX3RyYW5zRm4ocmFkKSArIHN0clJvdGF0ZSgtcmFkMmRlZyhyYWQpKTtcbiAgICB9O1xuXG4gICAgdmFyIGdyaWRQYXRoRm4gPSBmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciByYWQgPSB0MmcoZCk7XG4gICAgICAgIHZhciBjb3NSYWQgPSBNYXRoLmNvcyhyYWQpO1xuICAgICAgICB2YXIgc2luUmFkID0gTWF0aC5zaW4ocmFkKTtcbiAgICAgICAgcmV0dXJuICdNJyArIFtjeCArIGlubmVyUmFkaXVzICogY29zUmFkLCBjeSAtIGlubmVyUmFkaXVzICogc2luUmFkXSArXG4gICAgICAgICAgICAnTCcgKyBbY3ggKyByYWRpdXMgKiBjb3NSYWQsIGN5IC0gcmFkaXVzICogc2luUmFkXTtcbiAgICB9O1xuXG4gICAgdmFyIG91dCA9IEF4ZXMubWFrZUxhYmVsRm5zKGF4LCAwKTtcbiAgICB2YXIgbGFiZWxTdGFuZG9mZiA9IG91dC5sYWJlbFN0YW5kb2ZmO1xuICAgIHZhciBsYWJlbEZucyA9IHt9O1xuXG4gICAgbGFiZWxGbnMueEZuID0gZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgcmFkID0gdDJnKGQpO1xuICAgICAgICByZXR1cm4gTWF0aC5jb3MocmFkKSAqIGxhYmVsU3RhbmRvZmY7XG4gICAgfTtcblxuICAgIGxhYmVsRm5zLnlGbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHJhZCA9IHQyZyhkKTtcbiAgICAgICAgdmFyIGZmID0gTWF0aC5zaW4ocmFkKSA+IDAgPyAwLjIgOiAxO1xuICAgICAgICByZXR1cm4gLU1hdGguc2luKHJhZCkgKiAobGFiZWxTdGFuZG9mZiArIGQuZm9udFNpemUgKiBmZikgK1xuICAgICAgICAgICAgTWF0aC5hYnMoTWF0aC5jb3MocmFkKSkgKiAoZC5mb250U2l6ZSAqIE1JRF9TSElGVCk7XG4gICAgfTtcblxuICAgIGxhYmVsRm5zLmFuY2hvckZuID0gZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgcmFkID0gdDJnKGQpO1xuICAgICAgICB2YXIgY29zID0gTWF0aC5jb3MocmFkKTtcbiAgICAgICAgcmV0dXJuIE1hdGguYWJzKGNvcykgPCAwLjEgP1xuICAgICAgICAgICAgJ21pZGRsZScgOlxuICAgICAgICAgICAgKGNvcyA+IDAgPyAnc3RhcnQnIDogJ2VuZCcpO1xuICAgIH07XG5cbiAgICBsYWJlbEZucy5oZWlnaHRGbiA9IGZ1bmN0aW9uKGQsIGEsIGgpIHtcbiAgICAgICAgdmFyIHJhZCA9IHQyZyhkKTtcbiAgICAgICAgcmV0dXJuIC0wLjUgKiAoMSArIE1hdGguc2luKHJhZCkpICogaDtcbiAgICB9O1xuXG4gICAgdmFyIG5ld1RpY2tMYXlvdXQgPSBzdHJUaWNrTGF5b3V0KGFuZ3VsYXJMYXlvdXQpO1xuICAgIGlmKF90aGlzLmFuZ3VsYXJUaWNrTGF5b3V0ICE9PSBuZXdUaWNrTGF5b3V0KSB7XG4gICAgICAgIGxheWVyc1snYW5ndWxhci1heGlzJ10uc2VsZWN0QWxsKCcuJyArIGF4Ll9pZCArICd0aWNrJykucmVtb3ZlKCk7XG4gICAgICAgIF90aGlzLmFuZ3VsYXJUaWNrTGF5b3V0ID0gbmV3VGlja0xheW91dDtcbiAgICB9XG5cbiAgICB2YXIgdmFscyA9IEF4ZXMuY2FsY1RpY2tzKGF4KTtcblxuICAgIC8vIGFuZ2xlIG9mIHBvbHlnb24gdmVydGljZXMgaW4gZ2VvbWV0cmljIHJhZGlhbnMgKG51bGwgbWVhbnMgY2lyY2xlcylcbiAgICAvLyBUT0RPIHdoYXQgdG8gZG8gd2hlbiBheC5wZXJpb2QgPiBheC5fY2F0ZWdvcmllcyA/P1xuICAgIHZhciB2YW5nbGVzO1xuICAgIGlmKHBvbGFyTGF5b3V0LmdyaWRzaGFwZSA9PT0gJ2xpbmVhcicpIHtcbiAgICAgICAgdmFuZ2xlcyA9IHZhbHMubWFwKHQyZyk7XG5cbiAgICAgICAgLy8gYXguX3ZhbHMgc2hvdWxkIGJlIGFsd2F5cyBvcmRlcmVkLCBtYWtlIHRoZW1cbiAgICAgICAgLy8gYWx3YXlzIHR1cm4gY291bnRlcmNsb2Nrd2lzZSBmb3IgY29udmVuaWVuY2UgaGVyZVxuICAgICAgICBpZihMaWIuYW5nbGVEZWx0YSh2YW5nbGVzWzBdLCB2YW5nbGVzWzFdKSA8IDApIHtcbiAgICAgICAgICAgIHZhbmdsZXMgPSB2YW5nbGVzLnNsaWNlKCkucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFuZ2xlcyA9IG51bGw7XG4gICAgfVxuICAgIF90aGlzLnZhbmdsZXMgPSB2YW5nbGVzO1xuXG4gICAgLy8gVXNlIHRpY2t2YWwgZmlsdGVyIGZvciBjYXRlZ29yeSBheGVzIGluc3RlYWQgb2YgdHdlYWtpbmdcbiAgICAvLyB0aGUgcmFuZ2Ugdy5yLnQgc2VjdG9yLCBzbyB0aGF0IHNlY3RvcnMgdGhhdCBjcm9zcyAzNjAgY2FuXG4gICAgLy8gc2hvdyBhbGwgdGhlaXIgdGlja3MuXG4gICAgaWYoYXgudHlwZSA9PT0gJ2NhdGVnb3J5Jykge1xuICAgICAgICB2YWxzID0gdmFscy5maWx0ZXIoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIExpYi5pc0FuZ2xlSW5zaWRlU2VjdG9yKHQyZyhkKSwgX3RoaXMuc2VjdG9ySW5SYWQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihheC52aXNpYmxlKSB7XG4gICAgICAgIHZhciB0aWNrU2lnbiA9IGF4LnRpY2tzID09PSAnaW5zaWRlJyA/IC0xIDogMTtcbiAgICAgICAgdmFyIHBhZCA9IChheC5saW5ld2lkdGggfHwgMSkgLyAyO1xuXG4gICAgICAgIEF4ZXMuZHJhd1RpY2tzKGdkLCBheCwge1xuICAgICAgICAgICAgdmFsczogdmFscyxcbiAgICAgICAgICAgIGxheWVyOiBsYXllcnNbJ2FuZ3VsYXItYXhpcyddLFxuICAgICAgICAgICAgcGF0aDogJ00nICsgKHRpY2tTaWduICogcGFkKSArICcsMGgnICsgKHRpY2tTaWduICogYXgudGlja2xlbiksXG4gICAgICAgICAgICB0cmFuc0ZuOiB0cmFuc0ZuMixcbiAgICAgICAgICAgIGNyaXNwOiBmYWxzZVxuICAgICAgICB9KTtcblxuICAgICAgICBBeGVzLmRyYXdHcmlkKGdkLCBheCwge1xuICAgICAgICAgICAgdmFsczogdmFscyxcbiAgICAgICAgICAgIGxheWVyOiBsYXllcnNbJ2FuZ3VsYXItZ3JpZCddLFxuICAgICAgICAgICAgcGF0aDogZ3JpZFBhdGhGbixcbiAgICAgICAgICAgIHRyYW5zRm46IExpYi5ub29wLFxuICAgICAgICAgICAgY3Jpc3A6IGZhbHNlXG4gICAgICAgIH0pO1xuXG4gICAgICAgIEF4ZXMuZHJhd0xhYmVscyhnZCwgYXgsIHtcbiAgICAgICAgICAgIHZhbHM6IHZhbHMsXG4gICAgICAgICAgICBsYXllcjogbGF5ZXJzWydhbmd1bGFyLWF4aXMnXSxcbiAgICAgICAgICAgIHJlcG9zaXRpb25PblVwZGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm4sXG4gICAgICAgICAgICBsYWJlbEZuczogbGFiZWxGbnNcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gVE9ETyBtYXliZSB0d28gYXJjcyBpcyBiZXR0ZXIgaGVyZT9cbiAgICAvLyBtYXliZSBzcGxpdCBzdHlsZSBhdHRyaWJ1dGVzIGJldHdlZW4gaW5uZXIgYW5kIG91dGVyIGFuZ3VsYXIgYXhlcz9cblxuICAgIHVwZGF0ZUVsZW1lbnQobGF5ZXJzWydhbmd1bGFyLWxpbmUnXS5zZWxlY3QoJ3BhdGgnKSwgYW5ndWxhckxheW91dC5zaG93bGluZSwge1xuICAgICAgICBkOiBfdGhpcy5wYXRoU3VicGxvdCgpLFxuICAgICAgICB0cmFuc2Zvcm06IHN0clRyYW5zbGF0ZShjeCwgY3kpXG4gICAgfSlcbiAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgYW5ndWxhckxheW91dC5saW5ld2lkdGgpXG4gICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBhbmd1bGFyTGF5b3V0LmxpbmVjb2xvcik7XG59O1xuXG5wcm90by51cGRhdGVGeCA9IGZ1bmN0aW9uKGZ1bGxMYXlvdXQsIHBvbGFyTGF5b3V0KSB7XG4gICAgaWYoIXRoaXMuZ2QuX2NvbnRleHQuc3RhdGljUGxvdCkge1xuICAgICAgICB0aGlzLnVwZGF0ZUFuZ3VsYXJEcmFnKGZ1bGxMYXlvdXQpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJhZGlhbERyYWcoZnVsbExheW91dCwgcG9sYXJMYXlvdXQsIDApO1xuICAgICAgICB0aGlzLnVwZGF0ZVJhZGlhbERyYWcoZnVsbExheW91dCwgcG9sYXJMYXlvdXQsIDEpO1xuICAgICAgICB0aGlzLnVwZGF0ZU1haW5EcmFnKGZ1bGxMYXlvdXQpO1xuICAgIH1cbn07XG5cbnByb3RvLnVwZGF0ZU1haW5EcmFnID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGdkID0gX3RoaXMuZ2Q7XG4gICAgdmFyIGxheWVycyA9IF90aGlzLmxheWVycztcbiAgICB2YXIgem9vbWxheWVyID0gZnVsbExheW91dC5fem9vbWxheWVyO1xuICAgIHZhciBNSU5aT09NID0gY29uc3RhbnRzLk1JTlpPT007XG4gICAgdmFyIE9GRkVER0UgPSBjb25zdGFudHMuT0ZGRURHRTtcbiAgICB2YXIgcmFkaXVzID0gX3RoaXMucmFkaXVzO1xuICAgIHZhciBpbm5lclJhZGl1cyA9IF90aGlzLmlubmVyUmFkaXVzO1xuICAgIHZhciBjeCA9IF90aGlzLmN4O1xuICAgIHZhciBjeSA9IF90aGlzLmN5O1xuICAgIHZhciBjeHggPSBfdGhpcy5jeHg7XG4gICAgdmFyIGN5eSA9IF90aGlzLmN5eTtcbiAgICB2YXIgc2VjdG9ySW5SYWQgPSBfdGhpcy5zZWN0b3JJblJhZDtcbiAgICB2YXIgdmFuZ2xlcyA9IF90aGlzLnZhbmdsZXM7XG4gICAgdmFyIHJhZGlhbEF4aXMgPSBfdGhpcy5yYWRpYWxBeGlzO1xuICAgIHZhciBjbGFtcFRpbnkgPSBoZWxwZXJzLmNsYW1wVGlueTtcbiAgICB2YXIgZmluZFhZYXRMZW5ndGggPSBoZWxwZXJzLmZpbmRYWWF0TGVuZ3RoO1xuICAgIHZhciBmaW5kRW5jbG9zaW5nVmVydGV4QW5nbGVzID0gaGVscGVycy5maW5kRW5jbG9zaW5nVmVydGV4QW5nbGVzO1xuICAgIHZhciBjaHcgPSBjb25zdGFudHMuY29ybmVySGFsZldpZHRoO1xuICAgIHZhciBjaGwgPSBjb25zdGFudHMuY29ybmVyTGVuIC8gMjtcblxuICAgIHZhciBtYWluRHJhZyA9IGRyYWdCb3gubWFrZURyYWdnZXIobGF5ZXJzLCAncGF0aCcsICdtYWluZHJhZycsICdjcm9zc2hhaXInKTtcblxuICAgIGQzLnNlbGVjdChtYWluRHJhZylcbiAgICAgICAgLmF0dHIoJ2QnLCBfdGhpcy5wYXRoU3VicGxvdCgpKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgc3RyVHJhbnNsYXRlKGN4LCBjeSkpO1xuXG4gICAgdmFyIGRyYWdPcHRzID0ge1xuICAgICAgICBlbGVtZW50OiBtYWluRHJhZyxcbiAgICAgICAgZ2Q6IGdkLFxuICAgICAgICBzdWJwbG90OiBfdGhpcy5pZCxcbiAgICAgICAgcGxvdGluZm86IHtcbiAgICAgICAgICAgIGlkOiBfdGhpcy5pZCxcbiAgICAgICAgICAgIHhheGlzOiBfdGhpcy54YXhpcyxcbiAgICAgICAgICAgIHlheGlzOiBfdGhpcy55YXhpc1xuICAgICAgICB9LFxuICAgICAgICB4YXhlczogW190aGlzLnhheGlzXSxcbiAgICAgICAgeWF4ZXM6IFtfdGhpcy55YXhpc11cbiAgICB9O1xuXG4gICAgLy8gbW91c2UgcHggcG9zaXRpb24gYXQgZHJhZyBzdGFydCAoMCksIG1vdmUgKDEpXG4gICAgdmFyIHgwLCB5MDtcbiAgICAvLyByYWRpYWwgZGlzdGFuY2UgZnJvbSBjaXJjbGUgY2VudGVyIGF0IGRyYWcgc3RhcnQgKDApLCBtb3ZlICgxKVxuICAgIHZhciByMCwgcjE7XG4gICAgLy8gem9vbWJveCBwZXJzaXN0ZW50IHF1YW50aXRpZXNcbiAgICB2YXIgcGF0aDAsIGRpbW1lZCwgbHVtO1xuICAgIC8vIHpvb21ib3gsIGNvcm5lcnMgZWxlbWVudHNcbiAgICB2YXIgemIsIGNvcm5lcnM7XG5cbiAgICBmdW5jdGlvbiBub3JtKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIE1hdGguc3FydCh4ICogeCArIHkgKiB5KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB4eTJyKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIG5vcm0oeCAtIGN4eCwgeSAtIGN5eSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24geHkyYSh4LCB5KSB7XG4gICAgICAgIHJldHVybiBNYXRoLmF0YW4yKGN5eSAtIHksIHggLSBjeHgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJhMnh5KHIsIGEpIHtcbiAgICAgICAgcmV0dXJuIFtyICogTWF0aC5jb3MoYSksIHIgKiBNYXRoLnNpbigtYSldO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBhdGhDb3JuZXIociwgYSkge1xuICAgICAgICBpZihyID09PSAwKSByZXR1cm4gX3RoaXMucGF0aFNlY3RvcigyICogY2h3KTtcblxuICAgICAgICB2YXIgZGEgPSBjaGwgLyByO1xuICAgICAgICB2YXIgYW0gPSBhIC0gZGE7XG4gICAgICAgIHZhciBhcCA9IGEgKyBkYTtcbiAgICAgICAgdmFyIHJiID0gTWF0aC5tYXgoMCwgTWF0aC5taW4ociwgcmFkaXVzKSk7XG4gICAgICAgIHZhciBybSA9IHJiIC0gY2h3O1xuICAgICAgICB2YXIgcnAgPSByYiArIGNodztcblxuICAgICAgICByZXR1cm4gJ00nICsgcmEyeHkocm0sIGFtKSArXG4gICAgICAgICAgICAnQScgKyBbcm0sIHJtXSArICcgMCwwLDAgJyArIHJhMnh5KHJtLCBhcCkgK1xuICAgICAgICAgICAgJ0wnICsgcmEyeHkocnAsIGFwKSArXG4gICAgICAgICAgICAnQScgKyBbcnAsIHJwXSArICcgMCwwLDEgJyArIHJhMnh5KHJwLCBhbSkgK1xuICAgICAgICAgICAgJ1onO1xuICAgIH1cblxuICAgIC8vICh4LHkpIGlzIHRoZSBwdCBhdCBtaWRkbGUgb2YgdGhlIHZhMCA8LT4gdmExIGVkZ2VcbiAgICAvL1xuICAgIC8vIC4uLiB3ZSBjb3VsZCBldmVudHVhbGx5IGFkZCBhbm90aGVyIG1vZGUgZm9yIGN1cnNvclxuICAgIC8vIGFuZ2xlcyAnY2xvc2UgdG8nIGVub3VnaCB0byBhIHBhcnRpY3VsYXIgdmVydGV4LlxuICAgIGZ1bmN0aW9uIHBhdGhDb3JuZXJGb3JQb2x5Z29ucyhyLCB2YTAsIHZhMSkge1xuICAgICAgICBpZihyID09PSAwKSByZXR1cm4gX3RoaXMucGF0aFNlY3RvcigyICogY2h3KTtcblxuICAgICAgICB2YXIgeHkwID0gcmEyeHkociwgdmEwKTtcbiAgICAgICAgdmFyIHh5MSA9IHJhMnh5KHIsIHZhMSk7XG4gICAgICAgIHZhciB4ID0gY2xhbXBUaW55KCh4eTBbMF0gKyB4eTFbMF0pIC8gMik7XG4gICAgICAgIHZhciB5ID0gY2xhbXBUaW55KCh4eTBbMV0gKyB4eTFbMV0pIC8gMik7XG4gICAgICAgIHZhciBpbm5lclB0cywgb3V0ZXJQdHM7XG5cbiAgICAgICAgaWYoeCAmJiB5KSB7XG4gICAgICAgICAgICB2YXIgbSA9IHkgLyB4O1xuICAgICAgICAgICAgdmFyIG1wZXJwID0gLTEgLyBtO1xuICAgICAgICAgICAgdmFyIG1pZFB0cyA9IGZpbmRYWWF0TGVuZ3RoKGNodywgbSwgeCwgeSk7XG4gICAgICAgICAgICBpbm5lclB0cyA9IGZpbmRYWWF0TGVuZ3RoKGNobCwgbXBlcnAsIG1pZFB0c1swXVswXSwgbWlkUHRzWzBdWzFdKTtcbiAgICAgICAgICAgIG91dGVyUHRzID0gZmluZFhZYXRMZW5ndGgoY2hsLCBtcGVycCwgbWlkUHRzWzFdWzBdLCBtaWRQdHNbMV1bMV0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGR4LCBkeTtcbiAgICAgICAgICAgIGlmKHkpIHtcbiAgICAgICAgICAgICAgICAvLyBob3Jpem9udGFsIGhhbmRsZXNcbiAgICAgICAgICAgICAgICBkeCA9IGNobDtcbiAgICAgICAgICAgICAgICBkeSA9IGNodztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gdmVydGljYWwgaGFuZGxlc1xuICAgICAgICAgICAgICAgIGR4ID0gY2h3O1xuICAgICAgICAgICAgICAgIGR5ID0gY2hsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5uZXJQdHMgPSBbW3ggLSBkeCwgeSAtIGR5XSwgW3ggKyBkeCwgeSAtIGR5XV07XG4gICAgICAgICAgICBvdXRlclB0cyA9IFtbeCAtIGR4LCB5ICsgZHldLCBbeCArIGR4LCB5ICsgZHldXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAnTScgKyBpbm5lclB0cy5qb2luKCdMJykgK1xuICAgICAgICAgICAgJ0wnICsgb3V0ZXJQdHMucmV2ZXJzZSgpLmpvaW4oJ0wnKSArICdaJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tUHJlcCgpIHtcbiAgICAgICAgcjAgPSBudWxsO1xuICAgICAgICByMSA9IG51bGw7XG4gICAgICAgIHBhdGgwID0gX3RoaXMucGF0aFN1YnBsb3QoKTtcbiAgICAgICAgZGltbWVkID0gZmFsc2U7XG5cbiAgICAgICAgdmFyIHBvbGFyTGF5b3V0Tm93ID0gZ2QuX2Z1bGxMYXlvdXRbX3RoaXMuaWRdO1xuICAgICAgICBsdW0gPSB0aW55Y29sb3IocG9sYXJMYXlvdXROb3cuYmdjb2xvcikuZ2V0THVtaW5hbmNlKCk7XG5cbiAgICAgICAgemIgPSBkcmFnQm94Lm1ha2Vab29tYm94KHpvb21sYXllciwgbHVtLCBjeCwgY3ksIHBhdGgwKTtcbiAgICAgICAgemIuYXR0cignZmlsbC1ydWxlJywgJ2V2ZW5vZGQnKTtcbiAgICAgICAgY29ybmVycyA9IGRyYWdCb3gubWFrZUNvcm5lcnMoem9vbWxheWVyLCBjeCwgY3kpO1xuICAgICAgICBjbGVhclNlbGVjdChnZCk7XG4gICAgfVxuXG4gICAgLy8gTi5CLiB0aGlzIHNldHMgc2NvcGVkICdyMCcgYW5kICdyMSdcbiAgICAvLyByZXR1cm4gdHJ1ZSBpZiAndmFsaWQnIHpvb20gZGlzdGFuY2UsIGZhbHNlIG90aGVyd2lzZVxuICAgIGZ1bmN0aW9uIGNsYW1wQW5kU2V0UjBSMShycjAsIHJyMSkge1xuICAgICAgICBycjEgPSBNYXRoLm1heChNYXRoLm1pbihycjEsIHJhZGl1cyksIGlubmVyUmFkaXVzKTtcblxuICAgICAgICAvLyBzdGFydGluZyBvciBlbmRpbmcgZHJhZyBuZWFyIGNlbnRlciAob3V0ZXIgZWRnZSksXG4gICAgICAgIC8vIGNsYW1wcyByYWRpYWwgZGlzdGFuY2UgYXQgb3JpZ2luIChhdCByPXJhZGl1cylcbiAgICAgICAgaWYocnIwIDwgT0ZGRURHRSkgcnIwID0gMDtcbiAgICAgICAgZWxzZSBpZigocmFkaXVzIC0gcnIwKSA8IE9GRkVER0UpIHJyMCA9IHJhZGl1cztcbiAgICAgICAgZWxzZSBpZihycjEgPCBPRkZFREdFKSBycjEgPSAwO1xuICAgICAgICBlbHNlIGlmKChyYWRpdXMgLSBycjEpIDwgT0ZGRURHRSkgcnIxID0gcmFkaXVzO1xuXG4gICAgICAgIC8vIG1ha2Ugc3VyZSByMCA8IHIxLFxuICAgICAgICAvLyB0byBnZXQgY29ycmVjdCBmaWxsIHBhdHRlcm4gaW4gcGF0aDEgYmVsb3dcbiAgICAgICAgaWYoTWF0aC5hYnMocnIxIC0gcnIwKSA+IE1JTlpPT00pIHtcbiAgICAgICAgICAgIGlmKHJyMCA8IHJyMSkge1xuICAgICAgICAgICAgICAgIHIwID0gcnIwO1xuICAgICAgICAgICAgICAgIHIxID0gcnIxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByMCA9IHJyMTtcbiAgICAgICAgICAgICAgICByMSA9IHJyMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcjAgPSBudWxsO1xuICAgICAgICAgICAgcjEgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXBwbHlab29tTW92ZShwYXRoMSwgY3BhdGgpIHtcbiAgICAgICAgcGF0aDEgPSBwYXRoMSB8fCBwYXRoMDtcbiAgICAgICAgY3BhdGggPSBjcGF0aCB8fCAnTTAsMFonO1xuXG4gICAgICAgIHpiLmF0dHIoJ2QnLCBwYXRoMSk7XG4gICAgICAgIGNvcm5lcnMuYXR0cignZCcsIGNwYXRoKTtcbiAgICAgICAgZHJhZ0JveC50cmFuc2l0aW9uWm9vbWJveCh6YiwgY29ybmVycywgZGltbWVkLCBsdW0pO1xuICAgICAgICBkaW1tZWQgPSB0cnVlO1xuXG4gICAgICAgIHZhciB1cGRhdGVPYmogPSB7fTtcbiAgICAgICAgY29tcHV0ZVpvb21VcGRhdGVzKHVwZGF0ZU9iaik7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9yZWxheW91dGluZycsIHVwZGF0ZU9iaik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gem9vbU1vdmUoZHgsIGR5KSB7XG4gICAgICAgIHZhciB4MSA9IHgwICsgZHg7XG4gICAgICAgIHZhciB5MSA9IHkwICsgZHk7XG4gICAgICAgIHZhciBycjAgPSB4eTJyKHgwLCB5MCk7XG4gICAgICAgIHZhciBycjEgPSBNYXRoLm1pbih4eTJyKHgxLCB5MSksIHJhZGl1cyk7XG4gICAgICAgIHZhciBhMCA9IHh5MmEoeDAsIHkwKTtcbiAgICAgICAgdmFyIHBhdGgxO1xuICAgICAgICB2YXIgY3BhdGg7XG5cbiAgICAgICAgaWYoY2xhbXBBbmRTZXRSMFIxKHJyMCwgcnIxKSkge1xuICAgICAgICAgICAgcGF0aDEgPSBwYXRoMCArIF90aGlzLnBhdGhTZWN0b3IocjEpO1xuICAgICAgICAgICAgaWYocjApIHBhdGgxICs9IF90aGlzLnBhdGhTZWN0b3IocjApO1xuICAgICAgICAgICAgLy8ga2VlcCAnc3RhcnRpbmcnIGFuZ2xlXG4gICAgICAgICAgICBjcGF0aCA9IHBhdGhDb3JuZXIocjAsIGEwKSArIHBhdGhDb3JuZXIocjEsIGEwKTtcbiAgICAgICAgfVxuICAgICAgICBhcHBseVpvb21Nb3ZlKHBhdGgxLCBjcGF0aCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZmluZFBvbHlnb25SYWRpdXMoeCwgeSwgdmEwLCB2YTEpIHtcbiAgICAgICAgdmFyIHh5ID0gaGVscGVycy5maW5kSW50ZXJzZWN0aW9uWFkodmEwLCB2YTEsIHZhMCwgW3ggLSBjeHgsIGN5eSAtIHldKTtcbiAgICAgICAgcmV0dXJuIG5vcm0oeHlbMF0sIHh5WzFdKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tTW92ZUZvclBvbHlnb25zKGR4LCBkeSkge1xuICAgICAgICB2YXIgeDEgPSB4MCArIGR4O1xuICAgICAgICB2YXIgeTEgPSB5MCArIGR5O1xuICAgICAgICB2YXIgYTAgPSB4eTJhKHgwLCB5MCk7XG4gICAgICAgIHZhciBhMSA9IHh5MmEoeDEsIHkxKTtcbiAgICAgICAgdmFyIHZhbmdsZXMwID0gZmluZEVuY2xvc2luZ1ZlcnRleEFuZ2xlcyhhMCwgdmFuZ2xlcyk7XG4gICAgICAgIHZhciB2YW5nbGVzMSA9IGZpbmRFbmNsb3NpbmdWZXJ0ZXhBbmdsZXMoYTEsIHZhbmdsZXMpO1xuICAgICAgICB2YXIgcnIwID0gZmluZFBvbHlnb25SYWRpdXMoeDAsIHkwLCB2YW5nbGVzMFswXSwgdmFuZ2xlczBbMV0pO1xuICAgICAgICB2YXIgcnIxID0gTWF0aC5taW4oZmluZFBvbHlnb25SYWRpdXMoeDEsIHkxLCB2YW5nbGVzMVswXSwgdmFuZ2xlczFbMV0pLCByYWRpdXMpO1xuICAgICAgICB2YXIgcGF0aDE7XG4gICAgICAgIHZhciBjcGF0aDtcblxuICAgICAgICBpZihjbGFtcEFuZFNldFIwUjEocnIwLCBycjEpKSB7XG4gICAgICAgICAgICBwYXRoMSA9IHBhdGgwICsgX3RoaXMucGF0aFNlY3RvcihyMSk7XG4gICAgICAgICAgICBpZihyMCkgcGF0aDEgKz0gX3RoaXMucGF0aFNlY3RvcihyMCk7XG4gICAgICAgICAgICAvLyBrZWVwICdzdGFydGluZycgYW5nbGUgaGVyZSB0b29cbiAgICAgICAgICAgIGNwYXRoID0gW1xuICAgICAgICAgICAgICAgIHBhdGhDb3JuZXJGb3JQb2x5Z29ucyhyMCwgdmFuZ2xlczBbMF0sIHZhbmdsZXMwWzFdKSxcbiAgICAgICAgICAgICAgICBwYXRoQ29ybmVyRm9yUG9seWdvbnMocjEsIHZhbmdsZXMwWzBdLCB2YW5nbGVzMFsxXSlcbiAgICAgICAgICAgIF0uam9pbignICcpO1xuICAgICAgICB9XG4gICAgICAgIGFwcGx5Wm9vbU1vdmUocGF0aDEsIGNwYXRoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6b29tRG9uZSgpIHtcbiAgICAgICAgZHJhZ0JveC5yZW1vdmVab29tYm94KGdkKTtcblxuICAgICAgICBpZihyMCA9PT0gbnVsbCB8fCByMSA9PT0gbnVsbCkgcmV0dXJuO1xuICAgICAgICB2YXIgdXBkYXRlT2JqID0ge307XG4gICAgICAgIGNvbXB1dGVab29tVXBkYXRlcyh1cGRhdGVPYmopO1xuXG4gICAgICAgIGRyYWdCb3guc2hvd0RvdWJsZUNsaWNrTm90aWZpZXIoZ2QpO1xuXG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCB1cGRhdGVPYmopO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbXB1dGVab29tVXBkYXRlcyh1cGRhdGUpIHtcbiAgICAgICAgdmFyIHJsID0gcmFkaWFsQXhpcy5fcmw7XG4gICAgICAgIHZhciBtID0gKHJsWzFdIC0gcmxbMF0pIC8gKDEgLSBpbm5lclJhZGl1cyAvIHJhZGl1cykgLyByYWRpdXM7XG4gICAgICAgIHZhciBuZXdSbmcgPSBbXG4gICAgICAgICAgICBybFswXSArIChyMCAtIGlubmVyUmFkaXVzKSAqIG0sXG4gICAgICAgICAgICBybFswXSArIChyMSAtIGlubmVyUmFkaXVzKSAqIG1cbiAgICAgICAgXTtcbiAgICAgICAgdXBkYXRlW190aGlzLmlkICsgJy5yYWRpYWxheGlzLnJhbmdlJ10gPSBuZXdSbmc7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gem9vbUNsaWNrKG51bUNsaWNrcywgZXZ0KSB7XG4gICAgICAgIHZhciBjbGlja01vZGUgPSBnZC5fZnVsbExheW91dC5jbGlja21vZGU7XG5cbiAgICAgICAgZHJhZ0JveC5yZW1vdmVab29tYm94KGdkKTtcblxuICAgICAgICAvLyBUT0RPIGRvdWJsZSBvbmNlIHZzIHR3aWNlIGxvZ2ljIChhdXRvcmFuZ2UgdnMgZml4ZWQgcmFuZ2UpXG4gICAgICAgIGlmKG51bUNsaWNrcyA9PT0gMikge1xuICAgICAgICAgICAgdmFyIHVwZGF0ZU9iaiA9IHt9O1xuICAgICAgICAgICAgZm9yKHZhciBrIGluIF90aGlzLnZpZXdJbml0aWFsKSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlT2JqW190aGlzLmlkICsgJy4nICsga10gPSBfdGhpcy52aWV3SW5pdGlhbFtrXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2RvdWJsZWNsaWNrJywgbnVsbCk7XG4gICAgICAgICAgICBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVsYXlvdXQnLCBnZCwgdXBkYXRlT2JqKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNsaWNrTW9kZS5pbmRleE9mKCdzZWxlY3QnKSA+IC0xICYmIG51bUNsaWNrcyA9PT0gMSkge1xuICAgICAgICAgICAgc2VsZWN0T25DbGljayhldnQsIGdkLCBbX3RoaXMueGF4aXNdLCBbX3RoaXMueWF4aXNdLCBfdGhpcy5pZCwgZHJhZ09wdHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY2xpY2tNb2RlLmluZGV4T2YoJ2V2ZW50JykgPiAtMSkge1xuICAgICAgICAgICAgRnguY2xpY2soZ2QsIGV2dCwgX3RoaXMuaWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZHJhZ09wdHMucHJlcEZuID0gZnVuY3Rpb24oZXZ0LCBzdGFydFgsIHN0YXJ0WSkge1xuICAgICAgICB2YXIgZHJhZ01vZGVOb3cgPSBnZC5fZnVsbExheW91dC5kcmFnbW9kZTtcblxuICAgICAgICB2YXIgYmJveCA9IG1haW5EcmFnLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB4MCA9IHN0YXJ0WCAtIGJib3gubGVmdDtcbiAgICAgICAgeTAgPSBzdGFydFkgLSBiYm94LnRvcDtcblxuICAgICAgICAvLyBuZWVkIHRvIG9mZnNldCB4L3kgYXMgYmJveCBjZW50ZXIgZG9lcyBub3RcbiAgICAgICAgLy8gbWF0Y2ggb3JpZ2luIGZvciBhc3ltbWV0cmljIHBvbHlnb25zXG4gICAgICAgIGlmKHZhbmdsZXMpIHtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSBoZWxwZXJzLmZpbmRQb2x5Z29uT2Zmc2V0KHJhZGl1cywgc2VjdG9ySW5SYWRbMF0sIHNlY3RvckluUmFkWzFdLCB2YW5nbGVzKTtcbiAgICAgICAgICAgIHgwICs9IGN4eCArIG9mZnNldFswXTtcbiAgICAgICAgICAgIHkwICs9IGN5eSArIG9mZnNldFsxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaChkcmFnTW9kZU5vdykge1xuICAgICAgICAgICAgY2FzZSAnem9vbSc6XG4gICAgICAgICAgICAgICAgaWYodmFuZ2xlcykge1xuICAgICAgICAgICAgICAgICAgICBkcmFnT3B0cy5tb3ZlRm4gPSB6b29tTW92ZUZvclBvbHlnb25zO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRyYWdPcHRzLm1vdmVGbiA9IHpvb21Nb3ZlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkcmFnT3B0cy5jbGlja0ZuID0gem9vbUNsaWNrO1xuICAgICAgICAgICAgICAgIGRyYWdPcHRzLmRvbmVGbiA9IHpvb21Eb25lO1xuICAgICAgICAgICAgICAgIHpvb21QcmVwKGV2dCwgc3RhcnRYLCBzdGFydFkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2VsZWN0JzpcbiAgICAgICAgICAgIGNhc2UgJ2xhc3NvJzpcbiAgICAgICAgICAgICAgICBwcmVwU2VsZWN0KGV2dCwgc3RhcnRYLCBzdGFydFksIGRyYWdPcHRzLCBkcmFnTW9kZU5vdyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgbWFpbkRyYWcub25tb3VzZW1vdmUgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgRnguaG92ZXIoZ2QsIGV2dCwgX3RoaXMuaWQpO1xuICAgICAgICBnZC5fZnVsbExheW91dC5fbGFzdGhvdmVyID0gbWFpbkRyYWc7XG4gICAgICAgIGdkLl9mdWxsTGF5b3V0Ll9ob3ZlcnN1YnBsb3QgPSBfdGhpcy5pZDtcbiAgICB9O1xuXG4gICAgbWFpbkRyYWcub25tb3VzZW91dCA9IGZ1bmN0aW9uKGV2dCkge1xuICAgICAgICBpZihnZC5fZHJhZ2dpbmcpIHJldHVybjtcbiAgICAgICAgZHJhZ0VsZW1lbnQudW5ob3ZlcihnZCwgZXZ0KTtcbiAgICB9O1xuXG4gICAgZHJhZ0VsZW1lbnQuaW5pdChkcmFnT3B0cyk7XG59O1xuXG5wcm90by51cGRhdGVSYWRpYWxEcmFnID0gZnVuY3Rpb24oZnVsbExheW91dCwgcG9sYXJMYXlvdXQsIHJuZ0luZGV4KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgZ2QgPSBfdGhpcy5nZDtcbiAgICB2YXIgbGF5ZXJzID0gX3RoaXMubGF5ZXJzO1xuICAgIHZhciByYWRpdXMgPSBfdGhpcy5yYWRpdXM7XG4gICAgdmFyIGlubmVyUmFkaXVzID0gX3RoaXMuaW5uZXJSYWRpdXM7XG4gICAgdmFyIGN4ID0gX3RoaXMuY3g7XG4gICAgdmFyIGN5ID0gX3RoaXMuY3k7XG4gICAgdmFyIHJhZGlhbEF4aXMgPSBfdGhpcy5yYWRpYWxBeGlzO1xuICAgIHZhciBibCA9IGNvbnN0YW50cy5yYWRpYWxEcmFnQm94U2l6ZTtcbiAgICB2YXIgYmwyID0gYmwgLyAyO1xuXG4gICAgaWYoIXJhZGlhbEF4aXMudmlzaWJsZSkgcmV0dXJuO1xuXG4gICAgdmFyIGFuZ2xlMCA9IGRlZzJyYWQoX3RoaXMucmFkaWFsQXhpc0FuZ2xlKTtcbiAgICB2YXIgcmwgPSByYWRpYWxBeGlzLl9ybDtcbiAgICB2YXIgcmwwID0gcmxbMF07XG4gICAgdmFyIHJsMSA9IHJsWzFdO1xuICAgIHZhciByYmFzZSA9IHJsW3JuZ0luZGV4XTtcbiAgICB2YXIgbSA9IDAuNzUgKiAocmxbMV0gLSBybFswXSkgLyAoMSAtIHBvbGFyTGF5b3V0LmhvbGUpIC8gcmFkaXVzO1xuXG4gICAgdmFyIHR4LCB0eSwgY2xhc3NOYW1lO1xuICAgIGlmKHJuZ0luZGV4KSB7XG4gICAgICAgIHR4ID0gY3ggKyAocmFkaXVzICsgYmwyKSAqIE1hdGguY29zKGFuZ2xlMCk7XG4gICAgICAgIHR5ID0gY3kgLSAocmFkaXVzICsgYmwyKSAqIE1hdGguc2luKGFuZ2xlMCk7XG4gICAgICAgIGNsYXNzTmFtZSA9ICdyYWRpYWxkcmFnJztcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB0aGUgJ2lubmVyJyBib3ggY2FuIGdldCBjYWxsZWQ6XG4gICAgICAgIC8vIC0gd2hlbiBwb2xhci5ob2xlPjBcbiAgICAgICAgLy8gLSB3aGVuIHBvbGFyLnNlY3RvciBpc24ndCBhIGZ1bGwgY2lyY2xlXG4gICAgICAgIC8vIG90aGVyd2lzZSBpdCBpcyBoaWRkZW4gYmVoaW5kIHRoZSBtYWluIGRyYWcuXG4gICAgICAgIHR4ID0gY3ggKyAoaW5uZXJSYWRpdXMgLSBibDIpICogTWF0aC5jb3MoYW5nbGUwKTtcbiAgICAgICAgdHkgPSBjeSAtIChpbm5lclJhZGl1cyAtIGJsMikgKiBNYXRoLnNpbihhbmdsZTApO1xuICAgICAgICBjbGFzc05hbWUgPSAncmFkaWFsZHJhZy1pbm5lcic7XG4gICAgfVxuXG4gICAgdmFyIHJhZGlhbERyYWcgPSBkcmFnQm94Lm1ha2VSZWN0RHJhZ2dlcihsYXllcnMsIGNsYXNzTmFtZSwgJ2Nyb3NzaGFpcicsIC1ibDIsIC1ibDIsIGJsLCBibCk7XG4gICAgdmFyIGRyYWdPcHRzID0ge2VsZW1lbnQ6IHJhZGlhbERyYWcsIGdkOiBnZH07XG5cbiAgICB1cGRhdGVFbGVtZW50KGQzLnNlbGVjdChyYWRpYWxEcmFnKSwgcmFkaWFsQXhpcy52aXNpYmxlICYmIGlubmVyUmFkaXVzIDwgcmFkaXVzLCB7XG4gICAgICAgIHRyYW5zZm9ybTogc3RyVHJhbnNsYXRlKHR4LCB0eSlcbiAgICB9KTtcblxuICAgIC8vIG1vdmUgZnVuY3Rpb24gKGVpdGhlciByb3RhdGUgb3IgcmUtcmFuZ2UgZmxhdm9yKVxuICAgIHZhciBtb3ZlRm4yO1xuICAgIC8vIHJvdGF0ZSBhbmdsZSBvbiBkb25lXG4gICAgdmFyIGFuZ2xlMTtcbiAgICAvLyByZS1yYW5nZSByYW5nZVsxXSAob3IgcmFuZ2VbMF0pIG9uIGRvbmVcbiAgICB2YXIgcnByaW1lO1xuXG4gICAgZnVuY3Rpb24gbW92ZUZuKGR4LCBkeSkge1xuICAgICAgICBpZihtb3ZlRm4yKSB7XG4gICAgICAgICAgICBtb3ZlRm4yKGR4LCBkeSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgZHZlYyA9IFtkeCwgLWR5XTtcbiAgICAgICAgICAgIHZhciBydmVjID0gW01hdGguY29zKGFuZ2xlMCksIE1hdGguc2luKGFuZ2xlMCldO1xuICAgICAgICAgICAgdmFyIGNvbXAgPSBNYXRoLmFicyhMaWIuZG90KGR2ZWMsIHJ2ZWMpIC8gTWF0aC5zcXJ0KExpYi5kb3QoZHZlYywgZHZlYykpKTtcblxuICAgICAgICAgICAgLy8gbW9zdGx5IHBlcnBlbmRpY3VsYXIgbW90aW9ucyByb3RhdGUsXG4gICAgICAgICAgICAvLyBtb3N0bHkgcGFyYWxsZWwgbW90aW9ucyByZS1yYW5nZVxuICAgICAgICAgICAgaWYoIWlzTmFOKGNvbXApKSB7XG4gICAgICAgICAgICAgICAgbW92ZUZuMiA9IGNvbXAgPCAwLjUgPyByb3RhdGVNb3ZlIDogcmVyYW5nZU1vdmU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdXBkYXRlID0ge307XG4gICAgICAgIGNvbXB1dGVSYWRpYWxBeGlzVXBkYXRlcyh1cGRhdGUpO1xuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVsYXlvdXRpbmcnLCB1cGRhdGUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbXB1dGVSYWRpYWxBeGlzVXBkYXRlcyh1cGRhdGUpIHtcbiAgICAgICAgaWYoYW5nbGUxICE9PSBudWxsKSB7XG4gICAgICAgICAgICB1cGRhdGVbX3RoaXMuaWQgKyAnLnJhZGlhbGF4aXMuYW5nbGUnXSA9IGFuZ2xlMTtcbiAgICAgICAgfSBlbHNlIGlmKHJwcmltZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdXBkYXRlW190aGlzLmlkICsgJy5yYWRpYWxheGlzLnJhbmdlWycgKyBybmdJbmRleCArICddJ10gPSBycHJpbWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkb25lRm4oKSB7XG4gICAgICAgIGlmKGFuZ2xlMSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIF90aGlzLmlkICsgJy5yYWRpYWxheGlzLmFuZ2xlJywgYW5nbGUxKTtcbiAgICAgICAgfSBlbHNlIGlmKHJwcmltZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIF90aGlzLmlkICsgJy5yYWRpYWxheGlzLnJhbmdlWycgKyBybmdJbmRleCArICddJywgcnByaW1lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJvdGF0ZU1vdmUoZHgsIGR5KSB7XG4gICAgICAgIC8vIGRpc2FibGUgZm9yIGlubmVyIGRyYWcgYm94ZXNcbiAgICAgICAgaWYocm5nSW5kZXggPT09IDApIHJldHVybjtcblxuICAgICAgICB2YXIgeDEgPSB0eCArIGR4O1xuICAgICAgICB2YXIgeTEgPSB0eSArIGR5O1xuXG4gICAgICAgIGFuZ2xlMSA9IE1hdGguYXRhbjIoY3kgLSB5MSwgeDEgLSBjeCk7XG4gICAgICAgIGlmKF90aGlzLnZhbmdsZXMpIGFuZ2xlMSA9IHNuYXBUb1ZlcnRleEFuZ2xlKGFuZ2xlMSwgX3RoaXMudmFuZ2xlcyk7XG4gICAgICAgIGFuZ2xlMSA9IHJhZDJkZWcoYW5nbGUxKTtcblxuICAgICAgICB2YXIgdHJhbnNmb3JtID0gc3RyVHJhbnNsYXRlKGN4LCBjeSkgKyBzdHJSb3RhdGUoLWFuZ2xlMSk7XG4gICAgICAgIGxheWVyc1sncmFkaWFsLWF4aXMnXS5hdHRyKCd0cmFuc2Zvcm0nLCB0cmFuc2Zvcm0pO1xuICAgICAgICBsYXllcnNbJ3JhZGlhbC1saW5lJ10uc2VsZWN0KCdsaW5lJykuYXR0cigndHJhbnNmb3JtJywgdHJhbnNmb3JtKTtcblxuICAgICAgICB2YXIgZnVsbExheW91dE5vdyA9IF90aGlzLmdkLl9mdWxsTGF5b3V0O1xuICAgICAgICB2YXIgcG9sYXJMYXlvdXROb3cgPSBmdWxsTGF5b3V0Tm93W190aGlzLmlkXTtcbiAgICAgICAgX3RoaXMudXBkYXRlUmFkaWFsQXhpc1RpdGxlKGZ1bGxMYXlvdXROb3csIHBvbGFyTGF5b3V0Tm93LCBhbmdsZTEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlcmFuZ2VNb3ZlKGR4LCBkeSkge1xuICAgICAgICAvLyBwcm9qZWN0IChkeCwgZHkpIHVudG8gdW5pdCByYWRpYWwgYXhpcyB2ZWN0b3JcbiAgICAgICAgdmFyIGRyID0gTGliLmRvdChbZHgsIC1keV0sIFtNYXRoLmNvcyhhbmdsZTApLCBNYXRoLnNpbihhbmdsZTApXSk7XG4gICAgICAgIHJwcmltZSA9IHJiYXNlIC0gbSAqIGRyO1xuXG4gICAgICAgIC8vIG1ha2Ugc3VyZSBycHJpbWUgZG9lcyBub3QgY2hhbmdlIHRoZSByYW5nZVswXSAtPiByYW5nZVsxXSBzaWduXG4gICAgICAgIGlmKChtID4gMCkgIT09IChybmdJbmRleCA/IHJwcmltZSA+IHJsMCA6IHJwcmltZSA8IHJsMSkpIHtcbiAgICAgICAgICAgIHJwcmltZSA9IG51bGw7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZnVsbExheW91dE5vdyA9IGdkLl9mdWxsTGF5b3V0O1xuICAgICAgICB2YXIgcG9sYXJMYXlvdXROb3cgPSBmdWxsTGF5b3V0Tm93W190aGlzLmlkXTtcblxuICAgICAgICAvLyB1cGRhdGUgcmFkaWFsIHJhbmdlIC0+IHVwZGF0ZSBjMmcgLT4gdXBkYXRlIF9tLF9iXG4gICAgICAgIHJhZGlhbEF4aXMucmFuZ2Vbcm5nSW5kZXhdID0gcnByaW1lO1xuICAgICAgICByYWRpYWxBeGlzLl9ybFtybmdJbmRleF0gPSBycHJpbWU7XG4gICAgICAgIF90aGlzLnVwZGF0ZVJhZGlhbEF4aXMoZnVsbExheW91dE5vdywgcG9sYXJMYXlvdXROb3cpO1xuXG4gICAgICAgIF90aGlzLnhheGlzLnNldFJhbmdlKCk7XG4gICAgICAgIF90aGlzLnhheGlzLnNldFNjYWxlKCk7XG4gICAgICAgIF90aGlzLnlheGlzLnNldFJhbmdlKCk7XG4gICAgICAgIF90aGlzLnlheGlzLnNldFNjYWxlKCk7XG5cbiAgICAgICAgdmFyIGhhc1JlZ2wgPSBmYWxzZTtcblxuICAgICAgICBmb3IodmFyIHRyYWNlVHlwZSBpbiBfdGhpcy50cmFjZUhhc2gpIHtcbiAgICAgICAgICAgIHZhciBtb2R1bGVDYWxjRGF0YSA9IF90aGlzLnRyYWNlSGFzaFt0cmFjZVR5cGVdO1xuICAgICAgICAgICAgdmFyIG1vZHVsZUNhbGNEYXRhVmlzaWJsZSA9IExpYi5maWx0ZXJWaXNpYmxlKG1vZHVsZUNhbGNEYXRhKTtcbiAgICAgICAgICAgIHZhciBfbW9kdWxlID0gbW9kdWxlQ2FsY0RhdGFbMF1bMF0udHJhY2UuX21vZHVsZTtcbiAgICAgICAgICAgIF9tb2R1bGUucGxvdChnZCwgX3RoaXMsIG1vZHVsZUNhbGNEYXRhVmlzaWJsZSwgcG9sYXJMYXlvdXROb3cpO1xuICAgICAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZVR5cGUsICdnbCcpICYmIG1vZHVsZUNhbGNEYXRhVmlzaWJsZS5sZW5ndGgpIGhhc1JlZ2wgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaGFzUmVnbCkge1xuICAgICAgICAgICAgY2xlYXJHbENhbnZhc2VzKGdkKTtcbiAgICAgICAgICAgIHJlZHJhd1JlZ2xUcmFjZXMoZ2QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZHJhZ09wdHMucHJlcEZuID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIG1vdmVGbjIgPSBudWxsO1xuICAgICAgICBhbmdsZTEgPSBudWxsO1xuICAgICAgICBycHJpbWUgPSBudWxsO1xuXG4gICAgICAgIGRyYWdPcHRzLm1vdmVGbiA9IG1vdmVGbjtcbiAgICAgICAgZHJhZ09wdHMuZG9uZUZuID0gZG9uZUZuO1xuXG4gICAgICAgIGNsZWFyU2VsZWN0KGdkKTtcbiAgICB9O1xuXG4gICAgZHJhZ09wdHMuY2xhbXBGbiA9IGZ1bmN0aW9uKGR4LCBkeSkge1xuICAgICAgICBpZihNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpIDwgY29uc3RhbnRzLk1JTkRSQUcpIHtcbiAgICAgICAgICAgIGR4ID0gMDtcbiAgICAgICAgICAgIGR5ID0gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW2R4LCBkeV07XG4gICAgfTtcblxuICAgIGRyYWdFbGVtZW50LmluaXQoZHJhZ09wdHMpO1xufTtcblxucHJvdG8udXBkYXRlQW5ndWxhckRyYWcgPSBmdW5jdGlvbihmdWxsTGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgZ2QgPSBfdGhpcy5nZDtcbiAgICB2YXIgbGF5ZXJzID0gX3RoaXMubGF5ZXJzO1xuICAgIHZhciByYWRpdXMgPSBfdGhpcy5yYWRpdXM7XG4gICAgdmFyIGFuZ3VsYXJBeGlzID0gX3RoaXMuYW5ndWxhckF4aXM7XG4gICAgdmFyIGN4ID0gX3RoaXMuY3g7XG4gICAgdmFyIGN5ID0gX3RoaXMuY3k7XG4gICAgdmFyIGN4eCA9IF90aGlzLmN4eDtcbiAgICB2YXIgY3l5ID0gX3RoaXMuY3l5O1xuICAgIHZhciBkYnMgPSBjb25zdGFudHMuYW5ndWxhckRyYWdCb3hTaXplO1xuXG4gICAgdmFyIGFuZ3VsYXJEcmFnID0gZHJhZ0JveC5tYWtlRHJhZ2dlcihsYXllcnMsICdwYXRoJywgJ2FuZ3VsYXJkcmFnJywgJ21vdmUnKTtcbiAgICB2YXIgZHJhZ09wdHMgPSB7ZWxlbWVudDogYW5ndWxhckRyYWcsIGdkOiBnZH07XG5cbiAgICBkMy5zZWxlY3QoYW5ndWxhckRyYWcpXG4gICAgICAgIC5hdHRyKCdkJywgX3RoaXMucGF0aEFubnVsdXMocmFkaXVzLCByYWRpdXMgKyBkYnMpKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgc3RyVHJhbnNsYXRlKGN4LCBjeSkpXG4gICAgICAgIC5jYWxsKHNldEN1cnNvciwgJ21vdmUnKTtcblxuICAgIGZ1bmN0aW9uIHh5MmEoeCwgeSkge1xuICAgICAgICByZXR1cm4gTWF0aC5hdGFuMihjeXkgKyBkYnMgLSB5LCB4IC0gY3h4IC0gZGJzKTtcbiAgICB9XG5cbiAgICAvLyBzY2F0dGVyIHRyYWNlLCBwb2ludHMgYW5kIHRleHRwb2ludHMgc2VsZWN0aW9uc1xuICAgIHZhciBzY2F0dGVyVHJhY2VzID0gbGF5ZXJzLmZyb250cGxvdC5zZWxlY3QoJy5zY2F0dGVybGF5ZXInKS5zZWxlY3RBbGwoJy50cmFjZScpO1xuICAgIHZhciBzY2F0dGVyUG9pbnRzID0gc2NhdHRlclRyYWNlcy5zZWxlY3RBbGwoJy5wb2ludCcpO1xuICAgIHZhciBzY2F0dGVyVGV4dFBvaW50cyA9IHNjYXR0ZXJUcmFjZXMuc2VsZWN0QWxsKCcudGV4dHBvaW50Jyk7XG5cbiAgICAvLyBtb3VzZSBweCBwb3NpdGlvbiBhdCBkcmFnIHN0YXJ0ICgwKSwgbW92ZSAoMSlcbiAgICB2YXIgeDAsIHkwO1xuICAgIC8vIGFuZ3VsYXIgYXhpcyBhbmdsZSByb3RhdGlvbiBhdCBkcmFnIHN0YXJ0ICgwKSwgbW92ZSAoMSlcbiAgICB2YXIgcm90MCwgcm90MTtcbiAgICAvLyBpbmR1Y2VkIHJhZGlhbCBheGlzIHJvdGF0aW9uIChvbmx5IHVzZWQgb24gcG9seWdvbiBncmlkcylcbiAgICB2YXIgcnJvdDE7XG4gICAgLy8gYW5nbGUgYWJvdXQgY2lyY2xlIGNlbnRlciBhdCBkcmFnIHN0YXJ0XG4gICAgdmFyIGEwO1xuXG4gICAgZnVuY3Rpb24gbW92ZUZuKGR4LCBkeSkge1xuICAgICAgICB2YXIgZnVsbExheW91dE5vdyA9IF90aGlzLmdkLl9mdWxsTGF5b3V0O1xuICAgICAgICB2YXIgcG9sYXJMYXlvdXROb3cgPSBmdWxsTGF5b3V0Tm93W190aGlzLmlkXTtcblxuICAgICAgICB2YXIgeDEgPSB4MCArIGR4O1xuICAgICAgICB2YXIgeTEgPSB5MCArIGR5O1xuICAgICAgICB2YXIgYTEgPSB4eTJhKHgxLCB5MSk7XG4gICAgICAgIHZhciBkYSA9IHJhZDJkZWcoYTEgLSBhMCk7XG4gICAgICAgIHJvdDEgPSByb3QwICsgZGE7XG5cbiAgICAgICAgbGF5ZXJzLmZyb250cGxvdC5hdHRyKCd0cmFuc2Zvcm0nLFxuICAgICAgICAgICAgc3RyVHJhbnNsYXRlKF90aGlzLnhPZmZzZXQyLCBfdGhpcy55T2Zmc2V0MikgKyBzdHJSb3RhdGUoWy1kYSwgY3h4LCBjeXldKVxuICAgICAgICApO1xuXG4gICAgICAgIGlmKF90aGlzLnZhbmdsZXMpIHtcbiAgICAgICAgICAgIHJyb3QxID0gX3RoaXMucmFkaWFsQXhpc0FuZ2xlICsgZGE7XG5cbiAgICAgICAgICAgIHZhciB0cmFucyA9IHN0clRyYW5zbGF0ZShjeCwgY3kpICsgc3RyUm90YXRlKC1kYSk7XG4gICAgICAgICAgICB2YXIgdHJhbnMyID0gc3RyVHJhbnNsYXRlKGN4LCBjeSkgKyBzdHJSb3RhdGUoLXJyb3QxKTtcblxuICAgICAgICAgICAgbGF5ZXJzLmJnLmF0dHIoJ3RyYW5zZm9ybScsIHRyYW5zKTtcbiAgICAgICAgICAgIGxheWVyc1sncmFkaWFsLWdyaWQnXS5hdHRyKCd0cmFuc2Zvcm0nLCB0cmFucyk7XG4gICAgICAgICAgICBsYXllcnNbJ3JhZGlhbC1heGlzJ10uYXR0cigndHJhbnNmb3JtJywgdHJhbnMyKTtcbiAgICAgICAgICAgIGxheWVyc1sncmFkaWFsLWxpbmUnXS5zZWxlY3QoJ2xpbmUnKS5hdHRyKCd0cmFuc2Zvcm0nLCB0cmFuczIpO1xuICAgICAgICAgICAgX3RoaXMudXBkYXRlUmFkaWFsQXhpc1RpdGxlKGZ1bGxMYXlvdXROb3csIHBvbGFyTGF5b3V0Tm93LCBycm90MSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBfdGhpcy5jbGlwUGF0aHMuZm9yVHJhY2VzLnNlbGVjdCgncGF0aCcpLmF0dHIoJ3RyYW5zZm9ybScsXG4gICAgICAgICAgICAgICAgc3RyVHJhbnNsYXRlKGN4eCwgY3l5KSArIHN0clJvdGF0ZShkYSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAndW4tcm90YXRlJyBtYXJrZXIgYW5kIHRleHQgcG9pbnRzXG4gICAgICAgIHNjYXR0ZXJQb2ludHMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBzZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgeHkgPSBEcmF3aW5nLmdldFRyYW5zbGF0ZShzZWwpO1xuICAgICAgICAgICAgc2VsLmF0dHIoJ3RyYW5zZm9ybScsIHN0clRyYW5zbGF0ZSh4eS54LCB4eS55KSArIHN0clJvdGF0ZShbZGFdKSk7XG4gICAgICAgIH0pO1xuICAgICAgICBzY2F0dGVyVGV4dFBvaW50cy5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHNlbCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIHZhciB0eCA9IHNlbC5zZWxlY3QoJ3RleHQnKTtcbiAgICAgICAgICAgIHZhciB4eSA9IERyYXdpbmcuZ2V0VHJhbnNsYXRlKHNlbCk7XG4gICAgICAgICAgICAvLyBOLkIgcm90YXRlIC0+IHRyYW5zbGF0ZSBvcmRlcmluZyBtYXR0ZXJzXG4gICAgICAgICAgICBzZWwuYXR0cigndHJhbnNmb3JtJywgc3RyUm90YXRlKFtkYSwgdHguYXR0cigneCcpLCB0eC5hdHRyKCd5JyldKSArIHN0clRyYW5zbGF0ZSh4eS54LCB4eS55KSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIHVwZGF0ZSByb3RhdGlvbiAtPiByYW5nZSAtPiBfbSxfYlxuICAgICAgICBhbmd1bGFyQXhpcy5yb3RhdGlvbiA9IExpYi5tb2RIYWxmKHJvdDEsIDM2MCk7XG4gICAgICAgIF90aGlzLnVwZGF0ZUFuZ3VsYXJBeGlzKGZ1bGxMYXlvdXROb3csIHBvbGFyTGF5b3V0Tm93KTtcblxuICAgICAgICBpZihfdGhpcy5faGFzQ2xpcE9uQXhpc0ZhbHNlICYmICFMaWIuaXNGdWxsQ2lyY2xlKF90aGlzLnNlY3RvckluUmFkKSkge1xuICAgICAgICAgICAgc2NhdHRlclRyYWNlcy5jYWxsKERyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50cywgX3RoaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGhhc1JlZ2wgPSBmYWxzZTtcblxuICAgICAgICBmb3IodmFyIHRyYWNlVHlwZSBpbiBfdGhpcy50cmFjZUhhc2gpIHtcbiAgICAgICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2VUeXBlLCAnZ2wnKSkge1xuICAgICAgICAgICAgICAgIHZhciBtb2R1bGVDYWxjRGF0YSA9IF90aGlzLnRyYWNlSGFzaFt0cmFjZVR5cGVdO1xuICAgICAgICAgICAgICAgIHZhciBtb2R1bGVDYWxjRGF0YVZpc2libGUgPSBMaWIuZmlsdGVyVmlzaWJsZShtb2R1bGVDYWxjRGF0YSk7XG4gICAgICAgICAgICAgICAgdmFyIF9tb2R1bGUgPSBtb2R1bGVDYWxjRGF0YVswXVswXS50cmFjZS5fbW9kdWxlO1xuICAgICAgICAgICAgICAgIF9tb2R1bGUucGxvdChnZCwgX3RoaXMsIG1vZHVsZUNhbGNEYXRhVmlzaWJsZSwgcG9sYXJMYXlvdXROb3cpO1xuICAgICAgICAgICAgICAgIGlmKG1vZHVsZUNhbGNEYXRhVmlzaWJsZS5sZW5ndGgpIGhhc1JlZ2wgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoaGFzUmVnbCkge1xuICAgICAgICAgICAgY2xlYXJHbENhbnZhc2VzKGdkKTtcbiAgICAgICAgICAgIHJlZHJhd1JlZ2xUcmFjZXMoZ2QpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHVwZGF0ZSA9IHt9O1xuICAgICAgICBjb21wdXRlUm90YXRpb25VcGRhdGVzKHVwZGF0ZSk7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9yZWxheW91dGluZycsIHVwZGF0ZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZVJvdGF0aW9uVXBkYXRlcyh1cGRhdGVPYmopIHtcbiAgICAgICAgdXBkYXRlT2JqW190aGlzLmlkICsgJy5hbmd1bGFyYXhpcy5yb3RhdGlvbiddID0gcm90MTtcblxuICAgICAgICBpZihfdGhpcy52YW5nbGVzKSB7XG4gICAgICAgICAgICB1cGRhdGVPYmpbX3RoaXMuaWQgKyAnLnJhZGlhbGF4aXMuYW5nbGUnXSA9IHJyb3QxO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZG9uZUZuKCkge1xuICAgICAgICBzY2F0dGVyVGV4dFBvaW50cy5zZWxlY3QoJ3RleHQnKS5hdHRyKCd0cmFuc2Zvcm0nLCBudWxsKTtcblxuICAgICAgICB2YXIgdXBkYXRlT2JqID0ge307XG4gICAgICAgIGNvbXB1dGVSb3RhdGlvblVwZGF0ZXModXBkYXRlT2JqKTtcbiAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIHVwZGF0ZU9iaik7XG4gICAgfVxuXG4gICAgZHJhZ09wdHMucHJlcEZuID0gZnVuY3Rpb24oZXZ0LCBzdGFydFgsIHN0YXJ0WSkge1xuICAgICAgICB2YXIgcG9sYXJMYXlvdXROb3cgPSBmdWxsTGF5b3V0W190aGlzLmlkXTtcbiAgICAgICAgcm90MCA9IHBvbGFyTGF5b3V0Tm93LmFuZ3VsYXJheGlzLnJvdGF0aW9uO1xuXG4gICAgICAgIHZhciBiYm94ID0gYW5ndWxhckRyYWcuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHgwID0gc3RhcnRYIC0gYmJveC5sZWZ0O1xuICAgICAgICB5MCA9IHN0YXJ0WSAtIGJib3gudG9wO1xuICAgICAgICBhMCA9IHh5MmEoeDAsIHkwKTtcblxuICAgICAgICBkcmFnT3B0cy5tb3ZlRm4gPSBtb3ZlRm47XG4gICAgICAgIGRyYWdPcHRzLmRvbmVGbiA9IGRvbmVGbjtcblxuICAgICAgICBjbGVhclNlbGVjdChnZCk7XG4gICAgfTtcblxuICAgIC8vIEkgZG9uJ3Qgd2hhdCB3ZSBzaG91bGQgZG8gaW4gdGhpcyBjYXNlLCBza2lwIHdlIG5vd1xuICAgIGlmKF90aGlzLnZhbmdsZXMgJiYgIUxpYi5pc0Z1bGxDaXJjbGUoX3RoaXMuc2VjdG9ySW5SYWQpKSB7XG4gICAgICAgIGRyYWdPcHRzLnByZXBGbiA9IExpYi5ub29wO1xuICAgICAgICBzZXRDdXJzb3IoZDMuc2VsZWN0KGFuZ3VsYXJEcmFnKSwgbnVsbCk7XG4gICAgfVxuXG4gICAgZHJhZ0VsZW1lbnQuaW5pdChkcmFnT3B0cyk7XG59O1xuXG5wcm90by5pc1B0SW5zaWRlID0gZnVuY3Rpb24oZCkge1xuICAgIHZhciBzZWN0b3JJblJhZCA9IHRoaXMuc2VjdG9ySW5SYWQ7XG4gICAgdmFyIHZhbmdsZXMgPSB0aGlzLnZhbmdsZXM7XG4gICAgdmFyIHRoZXRhZyA9IHRoaXMuYW5ndWxhckF4aXMuYzJnKGQudGhldGEpO1xuICAgIHZhciByYWRpYWxBeGlzID0gdGhpcy5yYWRpYWxBeGlzO1xuICAgIHZhciByID0gcmFkaWFsQXhpcy5jMmwoZC5yKTtcbiAgICB2YXIgcmwgPSByYWRpYWxBeGlzLl9ybDtcblxuICAgIHZhciBmbiA9IHZhbmdsZXMgPyBoZWxwZXJzLmlzUHRJbnNpZGVQb2x5Z29uIDogTGliLmlzUHRJbnNpZGVTZWN0b3I7XG4gICAgcmV0dXJuIGZuKHIsIHRoZXRhZywgcmwsIHNlY3RvckluUmFkLCB2YW5nbGVzKTtcbn07XG5cbnByb3RvLnBhdGhBcmMgPSBmdW5jdGlvbihyKSB7XG4gICAgdmFyIHNlY3RvckluUmFkID0gdGhpcy5zZWN0b3JJblJhZDtcbiAgICB2YXIgdmFuZ2xlcyA9IHRoaXMudmFuZ2xlcztcbiAgICB2YXIgZm4gPSB2YW5nbGVzID8gaGVscGVycy5wYXRoUG9seWdvbiA6IExpYi5wYXRoQXJjO1xuICAgIHJldHVybiBmbihyLCBzZWN0b3JJblJhZFswXSwgc2VjdG9ySW5SYWRbMV0sIHZhbmdsZXMpO1xufTtcblxucHJvdG8ucGF0aFNlY3RvciA9IGZ1bmN0aW9uKHIpIHtcbiAgICB2YXIgc2VjdG9ySW5SYWQgPSB0aGlzLnNlY3RvckluUmFkO1xuICAgIHZhciB2YW5nbGVzID0gdGhpcy52YW5nbGVzO1xuICAgIHZhciBmbiA9IHZhbmdsZXMgPyBoZWxwZXJzLnBhdGhQb2x5Z29uIDogTGliLnBhdGhTZWN0b3I7XG4gICAgcmV0dXJuIGZuKHIsIHNlY3RvckluUmFkWzBdLCBzZWN0b3JJblJhZFsxXSwgdmFuZ2xlcyk7XG59O1xuXG5wcm90by5wYXRoQW5udWx1cyA9IGZ1bmN0aW9uKHIwLCByMSkge1xuICAgIHZhciBzZWN0b3JJblJhZCA9IHRoaXMuc2VjdG9ySW5SYWQ7XG4gICAgdmFyIHZhbmdsZXMgPSB0aGlzLnZhbmdsZXM7XG4gICAgdmFyIGZuID0gdmFuZ2xlcyA/IGhlbHBlcnMucGF0aFBvbHlnb25Bbm51bHVzIDogTGliLnBhdGhBbm51bHVzO1xuICAgIHJldHVybiBmbihyMCwgcjEsIHNlY3RvckluUmFkWzBdLCBzZWN0b3JJblJhZFsxXSwgdmFuZ2xlcyk7XG59O1xuXG5wcm90by5wYXRoU3VicGxvdCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByMCA9IHRoaXMuaW5uZXJSYWRpdXM7XG4gICAgdmFyIHIxID0gdGhpcy5yYWRpdXM7XG4gICAgcmV0dXJuIHIwID8gdGhpcy5wYXRoQW5udWx1cyhyMCwgcjEpIDogdGhpcy5wYXRoU2VjdG9yKHIxKTtcbn07XG5cbnByb3RvLmZpbGxWaWV3SW5pdGlhbEtleSA9IGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgaWYoIShrZXkgaW4gdGhpcy52aWV3SW5pdGlhbCkpIHtcbiAgICAgICAgdGhpcy52aWV3SW5pdGlhbFtrZXldID0gdmFsO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHN0clRpY2tMYXlvdXQoYXhMYXlvdXQpIHtcbiAgICB2YXIgb3V0ID0gYXhMYXlvdXQudGlja3MgKyBTdHJpbmcoYXhMYXlvdXQudGlja2xlbikgKyBTdHJpbmcoYXhMYXlvdXQuc2hvd3RpY2tsYWJlbHMpO1xuICAgIGlmKCdzaWRlJyBpbiBheExheW91dCkgb3V0ICs9IGF4TGF5b3V0LnNpZGU7XG4gICAgcmV0dXJuIG91dDtcbn1cblxuLy8gRmluZHMgdGhlIGJvdW5kaW5nIGJveCBvZiBhIGdpdmVuIGNpcmNsZSBzZWN0b3IsXG4vLyBpbnNwaXJlZCBieSBodHRwczovL21hdGguc3RhY2tleGNoYW5nZS5jb20vcS8xODUyNzAzXG4vL1xuLy8gYXNzdW1lczpcbi8vIC0gc2VjdG9yWzBdIDwgc2VjdG9yWzFdXG4vLyAtIGNvdW50ZXJjbG9ja3dpc2Ugcm90YXRpb25cbmZ1bmN0aW9uIGNvbXB1dGVTZWN0b3JCQm94KHNlY3Rvcikge1xuICAgIHZhciBzMCA9IHNlY3RvclswXTtcbiAgICB2YXIgczEgPSBzZWN0b3JbMV07XG4gICAgdmFyIGFyYyA9IHMxIC0gczA7XG4gICAgdmFyIGEwID0gbW9kKHMwLCAzNjApO1xuICAgIHZhciBhMSA9IGEwICsgYXJjO1xuXG4gICAgdmFyIGF4MCA9IE1hdGguY29zKGRlZzJyYWQoYTApKTtcbiAgICB2YXIgYXkwID0gTWF0aC5zaW4oZGVnMnJhZChhMCkpO1xuICAgIHZhciBheDEgPSBNYXRoLmNvcyhkZWcycmFkKGExKSk7XG4gICAgdmFyIGF5MSA9IE1hdGguc2luKGRlZzJyYWQoYTEpKTtcblxuICAgIHZhciB4MCwgeTAsIHgxLCB5MTtcblxuICAgIGlmKChhMCA8PSA5MCAmJiBhMSA+PSA5MCkgfHwgKGEwID4gOTAgJiYgYTEgPj0gNDUwKSkge1xuICAgICAgICB5MSA9IDE7XG4gICAgfSBlbHNlIGlmKGF5MCA8PSAwICYmIGF5MSA8PSAwKSB7XG4gICAgICAgIHkxID0gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB5MSA9IE1hdGgubWF4KGF5MCwgYXkxKTtcbiAgICB9XG5cbiAgICBpZigoYTAgPD0gMTgwICYmIGExID49IDE4MCkgfHwgKGEwID4gMTgwICYmIGExID49IDU0MCkpIHtcbiAgICAgICAgeDAgPSAtMTtcbiAgICB9IGVsc2UgaWYoYXgwID49IDAgJiYgYXgxID49IDApIHtcbiAgICAgICAgeDAgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHgwID0gTWF0aC5taW4oYXgwLCBheDEpO1xuICAgIH1cblxuICAgIGlmKChhMCA8PSAyNzAgJiYgYTEgPj0gMjcwKSB8fCAoYTAgPiAyNzAgJiYgYTEgPj0gNjMwKSkge1xuICAgICAgICB5MCA9IC0xO1xuICAgIH0gZWxzZSBpZihheTAgPj0gMCAmJiBheTEgPj0gMCkge1xuICAgICAgICB5MCA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgeTAgPSBNYXRoLm1pbihheTAsIGF5MSk7XG4gICAgfVxuXG4gICAgaWYoYTEgPj0gMzYwKSB7XG4gICAgICAgIHgxID0gMTtcbiAgICB9IGVsc2UgaWYoYXgwIDw9IDAgJiYgYXgxIDw9IDApIHtcbiAgICAgICAgeDEgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHgxID0gTWF0aC5tYXgoYXgwLCBheDEpO1xuICAgIH1cblxuICAgIHJldHVybiBbeDAsIHkwLCB4MSwgeTFdO1xufVxuXG5mdW5jdGlvbiBzbmFwVG9WZXJ0ZXhBbmdsZShhLCB2YW5nbGVzKSB7XG4gICAgdmFyIGZuID0gZnVuY3Rpb24odikgeyByZXR1cm4gTGliLmFuZ2xlRGlzdChhLCB2KTsgfTtcbiAgICB2YXIgaW5kID0gTGliLmZpbmRJbmRleE9mTWluKHZhbmdsZXMsIGZuKTtcbiAgICByZXR1cm4gdmFuZ2xlc1tpbmRdO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVFbGVtZW50KHNlbCwgc2hvd0F0dHIsIGF0dHJzKSB7XG4gICAgaWYoc2hvd0F0dHIpIHtcbiAgICAgICAgc2VsLmF0dHIoJ2Rpc3BsYXknLCBudWxsKTtcbiAgICAgICAgc2VsLmF0dHIoYXR0cnMpO1xuICAgIH0gZWxzZSBpZihzZWwpIHtcbiAgICAgICAgc2VsLmF0dHIoJ2Rpc3BsYXknLCAnbm9uZScpO1xuICAgIH1cbiAgICByZXR1cm4gc2VsO1xufVxuXG5mdW5jdGlvbiBzdHJUcmFuc2xhdGUoeCwgeSkge1xuICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyB4ICsgJywnICsgeSArICcpJztcbn1cblxuZnVuY3Rpb24gc3RyUm90YXRlKGFuZ2xlKSB7XG4gICAgcmV0dXJuICdyb3RhdGUoJyArIGFuZ2xlICsgJyknO1xufVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9jb21wb25lbnRzL2RyYWdlbGVtZW50XCI6NjExLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vY29tcG9uZW50cy9meFwiOjYzMixcIi4uLy4uL2NvbXBvbmVudHMvdGl0bGVzXCI6NjgxLFwiLi4vLi4vY29uc3RhbnRzL2FsaWdubWVudFwiOjY4OCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9jbGVhcl9nbF9jYW52YXNlc1wiOjcwNCxcIi4uLy4uL2xpYi9zZXRjdXJzb3JcIjo3MzksXCIuLi8uLi9wbG90X2FwaS9zdWJyb3V0aW5lc1wiOjc1OCxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9jYXJ0ZXNpYW4vYXV0b3JhbmdlXCI6NzY2LFwiLi4vY2FydGVzaWFuL2RyYWdib3hcIjo3NzUsXCIuLi9jYXJ0ZXNpYW4vc2VsZWN0XCI6Nzg0LFwiLi4vY2FydGVzaWFuL3NldF9jb252ZXJ0XCI6Nzg1LFwiLi4vcGxvdHNcIjo4MjgsXCIuL2NvbnN0YW50c1wiOjgyOSxcIi4vaGVscGVyc1wiOjgzMCxcIi4vc2V0X2NvbnZlcnRcIjo4NDEsXCJkM1wiOjE2MyxcInRpbnljb2xvcjJcIjo1Mzd9XSw4NDE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgc2V0Q29udmVydENhcnRlc2lhbiA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9zZXRfY29udmVydCcpO1xuXG52YXIgZGVnMnJhZCA9IExpYi5kZWcycmFkO1xudmFyIHJhZDJkZWcgPSBMaWIucmFkMmRlZztcblxuLyoqXG4gKiBzZXRDb252ZXJ0IGZvciBwb2xhciBheGVzIVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBheFxuICogICBheGlzIGluIHF1ZXN0aW9uICh3b3JrcyBmb3IgYm90aCByYWRpYWwgYW5kIGFuZ3VsYXIgYXhlcylcbiAqIEBwYXJhbSB7b2JqZWN0fSBwb2xhckxheW91dFxuICogICBmdWxsIHBvbGFyIGxheW91dCBvZiB0aGUgc3VicGxvdCBhc3NvY2lhdGVkIHdpdGggJ2F4J1xuICogQHBhcmFtIHtvYmplY3R9IGZ1bGxMYXlvdXRcbiAqICAgZnVsbCBsYXlvdXRcbiAqXG4gKiBIZXJlLCByZXVzZSBzb21lIG9mIHRoZSBDYXJ0ZXNpYW4gc2V0Q29udmVydCBsb2dpYyxcbiAqIGJ1dCB3ZSBtdXN0IGV4dGVuZCBzb21lIG9mIGl0LCBhcyBib3RoIHJhZGlhbCBhbmQgYW5ndWxhciBheGVzXG4gKiBkb24ndCBoYXZlIGRvbWFpbnMgYW5kIGFuZ3VsYXIgYXhlcyBkb24ndCBoYXZlIF90cnVlXyByYW5nZXMuXG4gKlxuICogTW9yZW92ZXIsIHdlIGludHJvZHVjZSB0d28gbmV3IGNvb3JkaW5hdGUgc3lzdGVtczpcbiAqIC0gJ2cnIGZvciBnZW9tZXRyaWMgY29vcmRpbmF0ZXMgYW5kXG4gKiAtICd0JyBmb3IgYW5ndWxhciB0aWNrc1xuICpcbiAqIFJhZGlhbCBheGlzIGNvb3JkaW5hdGUgc3lzdGVtczpcbiAqIC0gZCwgYyBhbmQgbDogc2FtZSBhcyBmb3IgY2FydGVzaWFuIGF4ZXNcbiAqIC0gZzogbGlrZSBjYWxjZGF0YSBidXQgdHJhbnNsYXRlZCBhYm91dCBgcmFkaWFsYXhpcy5yYW5nZVswXWAgJiBgcG9sYXIuaG9sZWBcbiAqXG4gKiBBbmd1bGFyIGF4aXMgY29vcmRpbmF0ZSBzeXN0ZW1zOlxuICogLSBkOiBkYXRhLCBpbiB3aGF0ZXZlciBmb3JtIGl0J3MgcHJvdmlkZWRcbiAqIC0gYzogY2FsY2RhdGEsIHR1cm5lZCBpbnRvIHJhZGlhbnMgKGZvciBsaW5lYXIgYXhlcylcbiAqICAgICAgb3IgY2F0ZWdvcnkgaW5kaWNlcyAoY2F0ZWdvcnkgYXhlcylcbiAqIC0gdDogdGljayBjYWxjZGF0YSwganVzdCBsaWtlICdjJyBidXQgaW4gZGVncmVlcyBmb3IgbGluZWFyIGF4ZXNcbiAqIC0gZzogZ2VvbWV0cmljIGNhbGNkYXRhLCByYWRpYW5zIGNvb3JkaW5hdGVzIHRoYXQgdGFrZSBpbnRvIGFjY291bnRcbiAqICAgICAgYXhpcyByb3RhdGlvbiBhbmQgZGlyZWN0aW9uXG4gKlxuICogVGhlbiwgJ2cnZW9tZXRyaWMgZGF0YSBpcyByZWFkeSB0byBiZSBjb252ZXJ0ZWQgdG8gKHgseSkuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2V0Q29udmVydChheCwgcG9sYXJMYXlvdXQsIGZ1bGxMYXlvdXQpIHtcbiAgICBzZXRDb252ZXJ0Q2FydGVzaWFuKGF4LCBmdWxsTGF5b3V0KTtcblxuICAgIHN3aXRjaChheC5faWQpIHtcbiAgICAgICAgY2FzZSAneCc6XG4gICAgICAgIGNhc2UgJ3JhZGlhbGF4aXMnOlxuICAgICAgICAgICAgc2V0Q29udmVydFJhZGlhbChheCwgcG9sYXJMYXlvdXQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2FuZ3VsYXJheGlzJzpcbiAgICAgICAgICAgIHNldENvbnZlcnRBbmd1bGFyKGF4LCBwb2xhckxheW91dCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBzZXRDb252ZXJ0UmFkaWFsKGF4LCBwb2xhckxheW91dCkge1xuICAgIHZhciBzdWJwbG90ID0gcG9sYXJMYXlvdXQuX3N1YnBsb3Q7XG5cbiAgICBheC5zZXRHZW9tZXRyeSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgcmwwID0gYXguX3JsWzBdO1xuICAgICAgICB2YXIgcmwxID0gYXguX3JsWzFdO1xuXG4gICAgICAgIHZhciBiID0gc3VicGxvdC5pbm5lclJhZGl1cztcbiAgICAgICAgdmFyIG0gPSAoc3VicGxvdC5yYWRpdXMgLSBiKSAvIChybDEgLSBybDApO1xuICAgICAgICB2YXIgYjIgPSBiIC8gbTtcblxuICAgICAgICB2YXIgckZpbHRlciA9IHJsMCA+IHJsMSA/XG4gICAgICAgICAgICBmdW5jdGlvbih2KSB7IHJldHVybiB2IDw9IDA7IH0gOlxuICAgICAgICAgICAgZnVuY3Rpb24odikgeyByZXR1cm4gdiA+PSAwOyB9O1xuXG4gICAgICAgIGF4LmMyZyA9IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHZhciByID0gYXguYzJsKHYpIC0gcmwwO1xuICAgICAgICAgICAgcmV0dXJuIChyRmlsdGVyKHIpID8gciA6IDApICsgYjI7XG4gICAgICAgIH07XG5cbiAgICAgICAgYXguZzJjID0gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgcmV0dXJuIGF4LmwyYyh2ICsgcmwwIC0gYjIpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGF4LmcycCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHYgKiBtOyB9O1xuICAgICAgICBheC5jMnAgPSBmdW5jdGlvbih2KSB7IHJldHVybiBheC5nMnAoYXguYzJnKHYpKTsgfTtcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB0b1JhZGlhbnModiwgdW5pdCkge1xuICAgIHJldHVybiB1bml0ID09PSAnZGVncmVlcycgPyBkZWcycmFkKHYpIDogdjtcbn1cblxuZnVuY3Rpb24gZnJvbVJhZGlhbnModiwgdW5pdCkge1xuICAgIHJldHVybiB1bml0ID09PSAnZGVncmVlcycgPyByYWQyZGVnKHYpIDogdjtcbn1cblxuZnVuY3Rpb24gc2V0Q29udmVydEFuZ3VsYXIoYXgsIHBvbGFyTGF5b3V0KSB7XG4gICAgdmFyIGF4VHlwZSA9IGF4LnR5cGU7XG5cbiAgICBpZihheFR5cGUgPT09ICdsaW5lYXInKSB7XG4gICAgICAgIHZhciBfZDJjID0gYXguZDJjO1xuICAgICAgICB2YXIgX2MyZCA9IGF4LmMyZDtcblxuICAgICAgICBheC5kMmMgPSBmdW5jdGlvbih2LCB1bml0KSB7IHJldHVybiB0b1JhZGlhbnMoX2QyYyh2KSwgdW5pdCk7IH07XG4gICAgICAgIGF4LmMyZCA9IGZ1bmN0aW9uKHYsIHVuaXQpIHsgcmV0dXJuIF9jMmQoZnJvbVJhZGlhbnModiwgdW5pdCkpOyB9O1xuICAgIH1cblxuICAgIC8vIG92ZXJyaWRlIG1ha2VDYWxjZGF0YSB0byBoYW5kbGUgdGhldGF1bml0IGFuZCBzcGVjaWFsIHRoZXRhMC9kdGhldGEgbG9naWNcbiAgICBheC5tYWtlQ2FsY2RhdGEgPSBmdW5jdGlvbih0cmFjZSwgY29vcmQpIHtcbiAgICAgICAgdmFyIGFycmF5SW4gPSB0cmFjZVtjb29yZF07XG4gICAgICAgIHZhciBsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgICAgICB2YXIgYXJyYXlPdXQsIGk7XG5cbiAgICAgICAgdmFyIF9kMmMgPSBmdW5jdGlvbih2KSB7IHJldHVybiBheC5kMmModiwgdHJhY2UudGhldGF1bml0KTsgfTtcblxuICAgICAgICBpZihhcnJheUluKSB7XG4gICAgICAgICAgICBpZihMaWIuaXNUeXBlZEFycmF5KGFycmF5SW4pICYmIGF4VHlwZSA9PT0gJ2xpbmVhcicpIHtcbiAgICAgICAgICAgICAgICBpZihsZW4gPT09IGFycmF5SW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnJheUluO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihhcnJheUluLnN1YmFycmF5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnJheUluLnN1YmFycmF5KDAsIGxlbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBhcnJheU91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcnJheU91dFtpXSA9IF9kMmMoYXJyYXlJbltpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgY29vcmQwID0gY29vcmQgKyAnMCc7XG4gICAgICAgICAgICB2YXIgZGNvb3JkID0gJ2QnICsgY29vcmQ7XG4gICAgICAgICAgICB2YXIgdjAgPSAoY29vcmQwIGluIHRyYWNlKSA/IF9kMmModHJhY2VbY29vcmQwXSkgOiAwO1xuICAgICAgICAgICAgdmFyIGR2ID0gKHRyYWNlW2Rjb29yZF0pID8gX2QyYyh0cmFjZVtkY29vcmRdKSA6IChheC5wZXJpb2QgfHwgMiAqIE1hdGguUEkpIC8gbGVuO1xuXG4gICAgICAgICAgICBhcnJheU91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcnJheU91dFtpXSA9IHYwICsgaSAqIGR2O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFycmF5T3V0O1xuICAgIH07XG5cbiAgICAvLyBOLkIuIHdlIG1vY2sgdGhlIGF4aXMgJ3JhbmdlJyBoZXJlXG4gICAgYXguc2V0R2VvbWV0cnkgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHNlY3RvciA9IHBvbGFyTGF5b3V0LnNlY3RvcjtcbiAgICAgICAgdmFyIHNlY3RvckluUmFkID0gc2VjdG9yLm1hcChkZWcycmFkKTtcbiAgICAgICAgdmFyIGRpciA9IHtjbG9ja3dpc2U6IC0xLCBjb3VudGVyY2xvY2t3aXNlOiAxfVtheC5kaXJlY3Rpb25dO1xuICAgICAgICB2YXIgcm90ID0gZGVnMnJhZChheC5yb3RhdGlvbik7XG5cbiAgICAgICAgdmFyIHJhZDJnID0gZnVuY3Rpb24odikgeyByZXR1cm4gZGlyICogdiArIHJvdDsgfTtcbiAgICAgICAgdmFyIGcycmFkID0gZnVuY3Rpb24odikgeyByZXR1cm4gKHYgLSByb3QpIC8gZGlyOyB9O1xuXG4gICAgICAgIHZhciByYWQyYywgYzJyYWQ7XG4gICAgICAgIHZhciByYWQydCwgdDJyYWQ7XG5cbiAgICAgICAgc3dpdGNoKGF4VHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnbGluZWFyJzpcbiAgICAgICAgICAgICAgICBjMnJhZCA9IHJhZDJjID0gTGliLmlkZW50aXR5O1xuICAgICAgICAgICAgICAgIHQycmFkID0gZGVnMnJhZDtcbiAgICAgICAgICAgICAgICByYWQydCA9IHJhZDJkZWc7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGFuZ3VsYXIgcmFuZ2UgaW4gZGVncmVlcyB0byBtYWtlIGF1dG8tdGljayBjb21wdXRhdGlvbiBjbGVhbmVyLFxuICAgICAgICAgICAgICAgIC8vIGNoYW5naW5nIHJvdGF0aW9uL2RpcmVjdGlvbiBzaG91bGQgbm90IGFmZmVjdCB0aGUgYW5ndWxhciB0aWNrIHZhbHVlLlxuICAgICAgICAgICAgICAgIGF4LnJhbmdlID0gTGliLmlzRnVsbENpcmNsZShzZWN0b3JJblJhZCkgP1xuICAgICAgICAgICAgICAgICAgICBbc2VjdG9yWzBdLCBzZWN0b3JbMF0gKyAzNjBdIDpcbiAgICAgICAgICAgICAgICAgICAgc2VjdG9ySW5SYWQubWFwKGcycmFkKS5tYXAocmFkMmRlZyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgJ2NhdGVnb3J5JzpcbiAgICAgICAgICAgICAgICB2YXIgY2F0TGVuID0gYXguX2NhdGVnb3JpZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBfcGVyaW9kID0gYXgucGVyaW9kID8gTWF0aC5tYXgoYXgucGVyaW9kLCBjYXRMZW4pIDogY2F0TGVuO1xuXG4gICAgICAgICAgICAgICAgLy8gZmFsbGJhY2sgaW4gY2FzZSBhbGwgY2F0ZWdvcmllcyBoYXZlIGJlZW4gZmlsdGVyZWQgb3V0XG4gICAgICAgICAgICAgICAgaWYoX3BlcmlvZCA9PT0gMCkgX3BlcmlvZCA9IDE7XG5cbiAgICAgICAgICAgICAgICBjMnJhZCA9IHQycmFkID0gZnVuY3Rpb24odikgeyByZXR1cm4gdiAqIDIgKiBNYXRoLlBJIC8gX3BlcmlvZDsgfTtcbiAgICAgICAgICAgICAgICByYWQyYyA9IHJhZDJ0ID0gZnVuY3Rpb24odikgeyByZXR1cm4gdiAqIF9wZXJpb2QgLyBNYXRoLlBJIC8gMjsgfTtcblxuICAgICAgICAgICAgICAgIGF4LnJhbmdlID0gWzAsIF9wZXJpb2RdO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgYXguYzJnID0gZnVuY3Rpb24odikgeyByZXR1cm4gcmFkMmcoYzJyYWQodikpOyB9O1xuICAgICAgICBheC5nMmMgPSBmdW5jdGlvbih2KSB7IHJldHVybiByYWQyYyhnMnJhZCh2KSk7IH07XG5cbiAgICAgICAgYXgudDJnID0gZnVuY3Rpb24odikgeyByZXR1cm4gcmFkMmcodDJyYWQodikpOyB9O1xuICAgICAgICBheC5nMnQgPSBmdW5jdGlvbih2KSB7IHJldHVybiByYWQydChnMnJhZCh2KSk7IH07XG4gICAgfTtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi9jYXJ0ZXNpYW4vc2V0X2NvbnZlcnRcIjo3ODV9XSw4NDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcbnZhciBUZW1wbGF0ZSA9IF9kZXJlcV8oJy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcbnZhciBoYW5kbGVEb21haW5EZWZhdWx0cyA9IF9kZXJlcV8oJy4vZG9tYWluJykuZGVmYXVsdHM7XG5cblxuLyoqXG4gKiBGaW5kIGFuZCBzdXBwbHkgZGVmYXVsdHMgdG8gYWxsIHN1YnBsb3RzIG9mIGEgZ2l2ZW4gdHlwZVxuICogVGhpcyBoYW5kbGVzIHN1YnBsb3RzIHRoYXQgYXJlIGNvbnRhaW5lZCB3aXRoaW4gb25lIGNvbnRhaW5lciAtIHNvXG4gKiBnbDNkLCBnZW8sIHRlcm5hcnkuLi4gYnV0IG5vdCAyZCBheGVzIHdoaWNoIGhhdmUgc2VwYXJhdGUgeCBhbmQgeSBheGVzXG4gKiBmaW5kcyBzdWJwbG90cywgY29lcmNlcyB0aGVpciBgZG9tYWluYCBhdHRyaWJ1dGVzLCB0aGVuIGNhbGxzIHRoZVxuICogZ2l2ZW4gaGFuZGxlRGVmYXVsdHMgZnVuY3Rpb24gdG8gZmlsbCBpbiBldmVyeXRoaW5nIGVsc2UuXG4gKlxuICogbGF5b3V0SW46IHRoZSBjb21wbGV0ZSB1c2VyLXN1cHBsaWVkIGlucHV0IGxheW91dFxuICogbGF5b3V0T3V0OiB0aGUgY29tcGxldGUgZmluaXNoZWQgbGF5b3V0XG4gKiBmdWxsRGF0YTogdGhlIGZpbmlzaGVkIGRhdGEgYXJyYXksIHVzZWQgb25seSB0byBmaW5kIHN1YnBsb3RzXG4gKiBvcHRzOiB7XG4gKiAgdHlwZTogc3VicGxvdCB0eXBlIHN0cmluZ1xuICogIGF0dHJpYnV0ZXM6IHN1YnBsb3QgYXR0cmlidXRlcyBvYmplY3RcbiAqICBwYXJ0aXRpb246ICd4JyBvciAneScsIHdoaWNoIGRpcmVjdGlvbiB0byBkaXZpZGUgZG9tYWluIHNwYWNlIGJ5IGRlZmF1bHRcbiAqICAgICAgKGRlZmF1bHQgJ3gnLCBpZSBzaWRlLWJ5LXNpZGUgc3VicGxvdHMpXG4gKiAgICAgIFRPRE86IHRoaXMgb3B0aW9uIGlzIG9ubHkgaGVyZSBiZWNhdXNlIDNEIGFuZCBnZW8gbWFkZSBvcHBvc2l0ZVxuICogICAgICBjaG9pY2VzIGluIHRoaXMgcmVnYXJkIHByZXZpb3VzbHkgYW5kIEkgZGlkbid0IHdhbnQgdG8gY2hhbmdlIGl0LlxuICogICAgICBJbnN0ZWFkIHdlIHNob3VsZCBkbzpcbiAqICAgICAgLSBzb21ldGhpbmcgY29uc2lzdGVudFxuICogICAgICAtIHNvbWV0aGluZyBtb3JlIHNxdWFyZSAoNCBjdXRzIDJ4MiwgNS82IGN1dHMgMngzLCBldGMuKVxuICogICAgICAtIHNvbWV0aGluZyB0aGF0IGluY2x1ZGVzIGFsbCBzdWJwbG90IHR5cGVzIGluIG9uZSBhcnJhbmdlbWVudCxcbiAqICAgICAgICBub3cgdGhhdCB3ZSBjYW4gaGF2ZSB0aGVtIHRvZ2V0aGVyIVxuICogIGhhbmRsZURlZmF1bHRzOiBmdW5jdGlvbiBvZiAoc3VicGxvdExheW91dEluLCBzdWJwbG90TGF5b3V0T3V0LCBjb2VyY2UsIG9wdHMpXG4gKiAgICAgIHRoaXMgb3B0cyBvYmplY3QgaXMgcGFzc2VkIHRocm91Z2ggdG8gaGFuZGxlRGVmYXVsdHMsIHNvIGF0dGFjaCBhbnlcbiAqICAgICAgYWRkaXRpb25hbCBpdGVtcyBuZWVkZWQgYnkgdGhpcyBmdW5jdGlvbiBoZXJlIGFzIHdlbGxcbiAqIH1cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVTdWJwbG90RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEsIG9wdHMpIHtcbiAgICB2YXIgc3VicGxvdFR5cGUgPSBvcHRzLnR5cGU7XG4gICAgdmFyIHN1YnBsb3RBdHRyaWJ1dGVzID0gb3B0cy5hdHRyaWJ1dGVzO1xuICAgIHZhciBoYW5kbGVEZWZhdWx0cyA9IG9wdHMuaGFuZGxlRGVmYXVsdHM7XG4gICAgdmFyIHBhcnRpdGlvbiA9IG9wdHMucGFydGl0aW9uIHx8ICd4JztcblxuICAgIHZhciBpZHMgPSBsYXlvdXRPdXQuX3N1YnBsb3RzW3N1YnBsb3RUeXBlXTtcbiAgICB2YXIgaWRzTGVuZ3RoID0gaWRzLmxlbmd0aDtcblxuICAgIHZhciBiYXNlSWQgPSBpZHNMZW5ndGggJiYgaWRzWzBdLnJlcGxhY2UoL1xcZCskLywgJycpO1xuXG4gICAgdmFyIHN1YnBsb3RMYXlvdXRJbiwgc3VicGxvdExheW91dE91dDtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHN1YnBsb3RMYXlvdXRJbiwgc3VicGxvdExheW91dE91dCwgc3VicGxvdEF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBpZHNMZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaWQgPSBpZHNbaV07XG5cbiAgICAgICAgLy8gdGVybmFyeSB0cmFjZXMgZ2V0IGEgbGF5b3V0IHRlcm5hcnkgZm9yIGZyZWUhXG4gICAgICAgIGlmKGxheW91dEluW2lkXSkgc3VicGxvdExheW91dEluID0gbGF5b3V0SW5baWRdO1xuICAgICAgICBlbHNlIHN1YnBsb3RMYXlvdXRJbiA9IGxheW91dEluW2lkXSA9IHt9O1xuXG4gICAgICAgIHN1YnBsb3RMYXlvdXRPdXQgPSBUZW1wbGF0ZS5uZXdDb250YWluZXIobGF5b3V0T3V0LCBpZCwgYmFzZUlkKTtcblxuICAgICAgICAvLyBBbGwgc3VicGxvdCBjb250YWluZXJzIGdldCBhIGB1aXJldmlzaW9uYCBpbmhlcml0aW5nIGZyb20gdGhlIGJhc2UuXG4gICAgICAgIC8vIEN1cnJlbnRseSBhbGwgc3VicGxvdHMgY29udGFpbmVycyBoYXZlIHNvbWUgdXNlciBpbnRlcmFjdGlvblxuICAgICAgICAvLyBhdHRyaWJ1dGVzLCBidXQgaWYgd2UgZXZlciBhZGQgb25lIHRoYXQgZG9lc24ndCwgd2Ugd291bGQgbmVlZCBhblxuICAgICAgICAvLyBvcHRpb24gdG8gc2tpcCB0aGlzIHN0ZXAuXG4gICAgICAgIGNvZXJjZSgndWlyZXZpc2lvbicsIGxheW91dE91dC51aXJldmlzaW9uKTtcblxuICAgICAgICB2YXIgZGZsdERvbWFpbnMgPSB7fTtcbiAgICAgICAgZGZsdERvbWFpbnNbcGFydGl0aW9uXSA9IFtpIC8gaWRzTGVuZ3RoLCAoaSArIDEpIC8gaWRzTGVuZ3RoXTtcbiAgICAgICAgaGFuZGxlRG9tYWluRGVmYXVsdHMoc3VicGxvdExheW91dE91dCwgbGF5b3V0T3V0LCBjb2VyY2UsIGRmbHREb21haW5zKTtcblxuICAgICAgICBvcHRzLmlkID0gaWQ7XG4gICAgICAgIGhhbmRsZURlZmF1bHRzKHN1YnBsb3RMYXlvdXRJbiwgc3VicGxvdExheW91dE91dCwgY29lcmNlLCBvcHRzKTtcbiAgICB9XG59O1xuXG59LHtcIi4uL2xpYlwiOjcxOSxcIi4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuL2RvbWFpblwiOjc5Mn1dLDg0MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFRlcm5hcnkgPSBfZGVyZXFfKCcuL3Rlcm5hcnknKTtcblxudmFyIGdldFN1YnBsb3RDYWxjRGF0YSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2dldF9kYXRhJykuZ2V0U3VicGxvdENhbGNEYXRhO1xudmFyIGNvdW50ZXJSZWdleCA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmNvdW50ZXJSZWdleDtcbnZhciBURVJOQVJZID0gJ3Rlcm5hcnknO1xuXG5leHBvcnRzLm5hbWUgPSBURVJOQVJZO1xuXG52YXIgYXR0ciA9IGV4cG9ydHMuYXR0ciA9ICdzdWJwbG90JztcblxuZXhwb3J0cy5pZFJvb3QgPSBURVJOQVJZO1xuXG5leHBvcnRzLmlkUmVnZXggPSBleHBvcnRzLmF0dHJSZWdleCA9IGNvdW50ZXJSZWdleChURVJOQVJZKTtcblxudmFyIGF0dHJpYnV0ZXMgPSBleHBvcnRzLmF0dHJpYnV0ZXMgPSB7fTtcbmF0dHJpYnV0ZXNbYXR0cl0gPSB7XG4gICAgdmFsVHlwZTogJ3N1YnBsb3RpZCcsXG4gICAgXG4gICAgZGZsdDogJ3Rlcm5hcnknLFxuICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgXG59O1xuXG5leHBvcnRzLmxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbmV4cG9ydHMuc3VwcGx5TGF5b3V0RGVmYXVsdHMgPSBfZGVyZXFfKCcuL2xheW91dF9kZWZhdWx0cycpO1xuXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbiBwbG90KGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2FsY0RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgdGVybmFyeUlkcyA9IGZ1bGxMYXlvdXQuX3N1YnBsb3RzW1RFUk5BUlldO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRlcm5hcnlJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRlcm5hcnlJZCA9IHRlcm5hcnlJZHNbaV07XG4gICAgICAgIHZhciB0ZXJuYXJ5Q2FsY0RhdGEgPSBnZXRTdWJwbG90Q2FsY0RhdGEoY2FsY0RhdGEsIFRFUk5BUlksIHRlcm5hcnlJZCk7XG4gICAgICAgIHZhciB0ZXJuYXJ5ID0gZnVsbExheW91dFt0ZXJuYXJ5SWRdLl9zdWJwbG90O1xuXG4gICAgICAgIC8vIElmIHRlcm5hcnkgaXMgbm90IGluc3RhbnRpYXRlZCwgY3JlYXRlIG9uZSFcbiAgICAgICAgaWYoIXRlcm5hcnkpIHtcbiAgICAgICAgICAgIHRlcm5hcnkgPSBuZXcgVGVybmFyeSh7XG4gICAgICAgICAgICAgICAgaWQ6IHRlcm5hcnlJZCxcbiAgICAgICAgICAgICAgICBncmFwaERpdjogZ2QsXG4gICAgICAgICAgICAgICAgY29udGFpbmVyOiBmdWxsTGF5b3V0Ll90ZXJuYXJ5bGF5ZXIubm9kZSgpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGZ1bGxMYXlvdXRcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGZ1bGxMYXlvdXRbdGVybmFyeUlkXS5fc3VicGxvdCA9IHRlcm5hcnk7XG4gICAgICAgIH1cblxuICAgICAgICB0ZXJuYXJ5LnBsb3QodGVybmFyeUNhbGNEYXRhLCBmdWxsTGF5b3V0LCBnZC5fcHJvbWlzZXMpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgb2xkVGVybmFyeUtleXMgPSBvbGRGdWxsTGF5b3V0Ll9zdWJwbG90c1tURVJOQVJZXSB8fCBbXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBvbGRUZXJuYXJ5S2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb2xkVGVybmFyeUtleSA9IG9sZFRlcm5hcnlLZXlzW2ldO1xuICAgICAgICB2YXIgb2xkVGVybmFyeSA9IG9sZEZ1bGxMYXlvdXRbb2xkVGVybmFyeUtleV0uX3N1YnBsb3Q7XG5cbiAgICAgICAgaWYoIW5ld0Z1bGxMYXlvdXRbb2xkVGVybmFyeUtleV0gJiYgISFvbGRUZXJuYXJ5KSB7XG4gICAgICAgICAgICBvbGRUZXJuYXJ5LnBsb3RDb250YWluZXIucmVtb3ZlKCk7XG4gICAgICAgICAgICBvbGRUZXJuYXJ5LmNsaXBEZWYucmVtb3ZlKCk7XG4gICAgICAgICAgICBvbGRUZXJuYXJ5LmNsaXBEZWZSZWxhdGl2ZS5yZW1vdmUoKTtcbiAgICAgICAgICAgIG9sZFRlcm5hcnkubGF5ZXJzWydhLXRpdGxlJ10ucmVtb3ZlKCk7XG4gICAgICAgICAgICBvbGRUZXJuYXJ5LmxheWVyc1snYi10aXRsZSddLnJlbW92ZSgpO1xuICAgICAgICAgICAgb2xkVGVybmFyeS5sYXllcnNbJ2MtdGl0bGUnXS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvZ2V0X2RhdGFcIjo4MDIsXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6ODQ0LFwiLi9sYXlvdXRfZGVmYXVsdHNcIjo4NDUsXCIuL3Rlcm5hcnlcIjo4NDZ9XSw4NDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gX2RlcmVxXygnLi4vZG9tYWluJykuYXR0cmlidXRlcztcbnZhciBheGVzQXR0cnMgPSBfZGVyZXFfKCcuLi9jYXJ0ZXNpYW4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxudmFyIG92ZXJyaWRlQWxsID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIHRlcm5hcnlBeGVzQXR0cnMgPSB7XG4gICAgdGl0bGU6IGF4ZXNBdHRycy50aXRsZSxcbiAgICBjb2xvcjogYXhlc0F0dHJzLmNvbG9yLFxuICAgIC8vIHRpY2tzXG4gICAgdGlja21vZGU6IGF4ZXNBdHRycy50aWNrbW9kZSxcbiAgICBudGlja3M6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy5udGlja3MsIHtkZmx0OiA2LCBtaW46IDF9KSxcbiAgICB0aWNrMDogYXhlc0F0dHJzLnRpY2swLFxuICAgIGR0aWNrOiBheGVzQXR0cnMuZHRpY2ssXG4gICAgdGlja3ZhbHM6IGF4ZXNBdHRycy50aWNrdmFscyxcbiAgICB0aWNrdGV4dDogYXhlc0F0dHJzLnRpY2t0ZXh0LFxuICAgIHRpY2tzOiBheGVzQXR0cnMudGlja3MsXG4gICAgdGlja2xlbjogYXhlc0F0dHJzLnRpY2tsZW4sXG4gICAgdGlja3dpZHRoOiBheGVzQXR0cnMudGlja3dpZHRoLFxuICAgIHRpY2tjb2xvcjogYXhlc0F0dHJzLnRpY2tjb2xvcixcbiAgICBzaG93dGlja2xhYmVsczogYXhlc0F0dHJzLnNob3d0aWNrbGFiZWxzLFxuICAgIHNob3d0aWNrcHJlZml4OiBheGVzQXR0cnMuc2hvd3RpY2twcmVmaXgsXG4gICAgdGlja3ByZWZpeDogYXhlc0F0dHJzLnRpY2twcmVmaXgsXG4gICAgc2hvd3RpY2tzdWZmaXg6IGF4ZXNBdHRycy5zaG93dGlja3N1ZmZpeCxcbiAgICB0aWNrc3VmZml4OiBheGVzQXR0cnMudGlja3N1ZmZpeCxcbiAgICBzaG93ZXhwb25lbnQ6IGF4ZXNBdHRycy5zaG93ZXhwb25lbnQsXG4gICAgZXhwb25lbnRmb3JtYXQ6IGF4ZXNBdHRycy5leHBvbmVudGZvcm1hdCxcbiAgICBzZXBhcmF0ZXRob3VzYW5kczogYXhlc0F0dHJzLnNlcGFyYXRldGhvdXNhbmRzLFxuICAgIHRpY2tmb250OiBheGVzQXR0cnMudGlja2ZvbnQsXG4gICAgdGlja2FuZ2xlOiBheGVzQXR0cnMudGlja2FuZ2xlLFxuICAgIHRpY2tmb3JtYXQ6IGF4ZXNBdHRycy50aWNrZm9ybWF0LFxuICAgIHRpY2tmb3JtYXRzdG9wczogYXhlc0F0dHJzLnRpY2tmb3JtYXRzdG9wcyxcbiAgICBob3ZlcmZvcm1hdDogYXhlc0F0dHJzLmhvdmVyZm9ybWF0LFxuICAgIC8vIGxpbmVzIGFuZCBncmlkc1xuICAgIHNob3dsaW5lOiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMuc2hvd2xpbmUsIHtkZmx0OiB0cnVlfSksXG4gICAgbGluZWNvbG9yOiBheGVzQXR0cnMubGluZWNvbG9yLFxuICAgIGxpbmV3aWR0aDogYXhlc0F0dHJzLmxpbmV3aWR0aCxcbiAgICBzaG93Z3JpZDogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLnNob3dncmlkLCB7ZGZsdDogdHJ1ZX0pLFxuICAgIGdyaWRjb2xvcjogYXhlc0F0dHJzLmdyaWRjb2xvcixcbiAgICBncmlkd2lkdGg6IGF4ZXNBdHRycy5ncmlkd2lkdGgsXG4gICAgbGF5ZXI6IGF4ZXNBdHRycy5sYXllcixcbiAgICAvLyByYW5nZVxuICAgIG1pbjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgXG4gICAgfSxcbiAgICBfZGVwcmVjYXRlZDoge1xuICAgICAgICB0aXRsZTogYXhlc0F0dHJzLl9kZXByZWNhdGVkLnRpdGxlLFxuICAgICAgICB0aXRsZWZvbnQ6IGF4ZXNBdHRycy5fZGVwcmVjYXRlZC50aXRsZWZvbnRcbiAgICB9XG59O1xuXG52YXIgYXR0cnMgPSBtb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHtcbiAgICBkb21haW46IGRvbWFpbkF0dHJzKHtuYW1lOiAndGVybmFyeSd9KSxcblxuICAgIGJnY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuYmFja2dyb3VuZCxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzdW06IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYWF4aXM6IHRlcm5hcnlBeGVzQXR0cnMsXG4gICAgYmF4aXM6IHRlcm5hcnlBeGVzQXR0cnMsXG4gICAgY2F4aXM6IHRlcm5hcnlBeGVzQXR0cnNcbn0sICdwbG90JywgJ2Zyb20tcm9vdCcpO1xuXG4vLyBzZXQgdWlyZXZpc2lvbnMgb3V0c2lkZSBvZiBgb3ZlcnJpZGVBbGxgIHNvIHdlIGNhbiBnZXQgYGVkaXRUeXBlOiBub25lYFxuYXR0cnMudWlyZXZpc2lvbiA9IHtcbiAgICB2YWxUeXBlOiAnYW55JyxcbiAgICBcbiAgICBlZGl0VHlwZTogJ25vbmUnLFxuICAgIFxufTtcblxuYXR0cnMuYWF4aXMudWlyZXZpc2lvbiA9IGF0dHJzLmJheGlzLnVpcmV2aXNpb24gPSBhdHRycy5jYXhpcy51aXJldmlzaW9uID0ge1xuICAgIHZhbFR5cGU6ICdhbnknLFxuICAgIFxuICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgXG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlc1wiOjU5MixcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vY2FydGVzaWFuL2xheW91dF9hdHRyaWJ1dGVzXCI6Nzc5LFwiLi4vZG9tYWluXCI6NzkyfV0sODQ1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIFRlbXBsYXRlID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgaGFuZGxlU3VicGxvdERlZmF1bHRzID0gX2RlcmVxXygnLi4vc3VicGxvdF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL3RpY2tfbGFiZWxfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrTWFya0RlZmF1bHRzID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL3RpY2tfbWFya19kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRpY2tWYWx1ZURlZmF1bHRzID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL3RpY2tfdmFsdWVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVMaW5lR3JpZERlZmF1bHRzID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL2xpbmVfZ3JpZF9kZWZhdWx0cycpO1xudmFyIGxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbnZhciBheGVzTmFtZXMgPSBbJ2FheGlzJywgJ2JheGlzJywgJ2NheGlzJ107XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICBoYW5kbGVTdWJwbG90RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEsIHtcbiAgICAgICAgdHlwZTogJ3Rlcm5hcnknLFxuICAgICAgICBhdHRyaWJ1dGVzOiBsYXlvdXRBdHRyaWJ1dGVzLFxuICAgICAgICBoYW5kbGVEZWZhdWx0czogaGFuZGxlVGVybmFyeURlZmF1bHRzLFxuICAgICAgICBmb250OiBsYXlvdXRPdXQuZm9udCxcbiAgICAgICAgcGFwZXJfYmdjb2xvcjogbGF5b3V0T3V0LnBhcGVyX2JnY29sb3JcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZVRlcm5hcnlEZWZhdWx0cyh0ZXJuYXJ5TGF5b3V0SW4sIHRlcm5hcnlMYXlvdXRPdXQsIGNvZXJjZSwgb3B0aW9ucykge1xuICAgIHZhciBiZ0NvbG9yID0gY29lcmNlKCdiZ2NvbG9yJyk7XG4gICAgdmFyIHN1bSA9IGNvZXJjZSgnc3VtJyk7XG4gICAgb3B0aW9ucy5iZ0NvbG9yID0gQ29sb3IuY29tYmluZShiZ0NvbG9yLCBvcHRpb25zLnBhcGVyX2JnY29sb3IpO1xuICAgIHZhciBheE5hbWUsIGNvbnRhaW5lckluLCBjb250YWluZXJPdXQ7XG5cbiAgICAvLyBUT0RPOiBhbGxvdyBtb3N0IChpZiBub3QgYWxsKSBheGlzIGF0dHJpYnV0ZXMgdG8gYmUgc2V0XG4gICAgLy8gaW4gdGhlIG91dGVyIGNvbnRhaW5lciBhbmQgdXNlZCBhcyBkZWZhdWx0cyBpbiB0aGUgaW5kaXZpZHVhbCBheGVzP1xuXG4gICAgZm9yKHZhciBqID0gMDsgaiA8IGF4ZXNOYW1lcy5sZW5ndGg7IGorKykge1xuICAgICAgICBheE5hbWUgPSBheGVzTmFtZXNbal07XG4gICAgICAgIGNvbnRhaW5lckluID0gdGVybmFyeUxheW91dEluW2F4TmFtZV0gfHwge307XG4gICAgICAgIGNvbnRhaW5lck91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcih0ZXJuYXJ5TGF5b3V0T3V0LCBheE5hbWUpO1xuICAgICAgICBjb250YWluZXJPdXQuX25hbWUgPSBheE5hbWU7XG5cbiAgICAgICAgaGFuZGxlQXhpc0RlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIG9wdGlvbnMsIHRlcm5hcnlMYXlvdXRPdXQpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZSBtaW4gdmFsdWVzIGNvbnRyYWRpY3QgZWFjaCBvdGhlciwgc2V0IHRoZW0gYWxsIHRvIGRlZmF1bHQgKDApXG4gICAgLy8gYW5kIGRlbGV0ZSAqYWxsKiB0aGUgaW5wdXRzIHNvIHRoZSB1c2VyIGRvZXNuJ3QgZ2V0IGNvbmZ1c2VkIGxhdGVyIGJ5XG4gICAgLy8gY2hhbmdpbmcgb25lIGFuZCBoYXZpbmcgdGhlbSBhbGwgY2hhbmdlLlxuICAgIHZhciBhYXhpcyA9IHRlcm5hcnlMYXlvdXRPdXQuYWF4aXM7XG4gICAgdmFyIGJheGlzID0gdGVybmFyeUxheW91dE91dC5iYXhpcztcbiAgICB2YXIgY2F4aXMgPSB0ZXJuYXJ5TGF5b3V0T3V0LmNheGlzO1xuICAgIGlmKGFheGlzLm1pbiArIGJheGlzLm1pbiArIGNheGlzLm1pbiA+PSBzdW0pIHtcbiAgICAgICAgYWF4aXMubWluID0gMDtcbiAgICAgICAgYmF4aXMubWluID0gMDtcbiAgICAgICAgY2F4aXMubWluID0gMDtcbiAgICAgICAgaWYodGVybmFyeUxheW91dEluLmFheGlzKSBkZWxldGUgdGVybmFyeUxheW91dEluLmFheGlzLm1pbjtcbiAgICAgICAgaWYodGVybmFyeUxheW91dEluLmJheGlzKSBkZWxldGUgdGVybmFyeUxheW91dEluLmJheGlzLm1pbjtcbiAgICAgICAgaWYodGVybmFyeUxheW91dEluLmNheGlzKSBkZWxldGUgdGVybmFyeUxheW91dEluLmNheGlzLm1pbjtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGhhbmRsZUF4aXNEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBvcHRpb25zLCB0ZXJuYXJ5TGF5b3V0T3V0KSB7XG4gICAgdmFyIGF4QXR0cnMgPSBsYXlvdXRBdHRyaWJ1dGVzW2NvbnRhaW5lck91dC5fbmFtZV07XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBheEF0dHJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3VpcmV2aXNpb24nLCB0ZXJuYXJ5TGF5b3V0T3V0LnVpcmV2aXNpb24pO1xuXG4gICAgY29udGFpbmVyT3V0LnR5cGUgPSAnbGluZWFyJzsgLy8gbm8gb3RoZXIgdHlwZXMgYWxsb3dlZCBmb3IgdGVybmFyeVxuXG4gICAgdmFyIGRmbHRDb2xvciA9IGNvZXJjZSgnY29sb3InKTtcbiAgICAvLyBpZiBheGlzLmNvbG9yIHdhcyBwcm92aWRlZCwgdXNlIGl0IGZvciBmb250cyB0b287IG90aGVyd2lzZSxcbiAgICAvLyBpbmhlcml0IGZyb20gZ2xvYmFsIGZvbnQgY29sb3IgaW4gY2FzZSB0aGF0IHdhcyBwcm92aWRlZC5cbiAgICB2YXIgZGZsdEZvbnRDb2xvciA9IChkZmx0Q29sb3IgIT09IGF4QXR0cnMuY29sb3IuZGZsdCkgPyBkZmx0Q29sb3IgOiBvcHRpb25zLmZvbnQuY29sb3I7XG5cbiAgICB2YXIgYXhOYW1lID0gY29udGFpbmVyT3V0Ll9uYW1lO1xuICAgIHZhciBsZXR0ZXJVcHBlciA9IGF4TmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKTtcbiAgICB2YXIgZGZsdFRpdGxlID0gJ0NvbXBvbmVudCAnICsgbGV0dGVyVXBwZXI7XG5cbiAgICB2YXIgdGl0bGUgPSBjb2VyY2UoJ3RpdGxlLnRleHQnLCBkZmx0VGl0bGUpO1xuICAgIGNvbnRhaW5lck91dC5faG92ZXJ0aXRsZSA9IHRpdGxlID09PSBkZmx0VGl0bGUgPyB0aXRsZSA6IGxldHRlclVwcGVyO1xuXG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAndGl0bGUuZm9udCcsIHtcbiAgICAgICAgZmFtaWx5OiBvcHRpb25zLmZvbnQuZmFtaWx5LFxuICAgICAgICBzaXplOiBNYXRoLnJvdW5kKG9wdGlvbnMuZm9udC5zaXplICogMS4yKSxcbiAgICAgICAgY29sb3I6IGRmbHRGb250Q29sb3JcbiAgICB9KTtcblxuICAgIC8vIHJhbmdlIGlzIGp1c3Qgc2V0IGJ5ICdtaW4nIC0gbWF4IGlzIGRldGVybWluZWQgYnkgdGhlIG90aGVyIGF4ZXMgbWluc1xuICAgIGNvZXJjZSgnbWluJyk7XG5cbiAgICBoYW5kbGVUaWNrVmFsdWVEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsICdsaW5lYXInKTtcbiAgICBoYW5kbGVUaWNrTGFiZWxEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsICdsaW5lYXInLCB7fSk7XG4gICAgaGFuZGxlVGlja01hcmtEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBjb2VyY2UsXG4gICAgICAgIHsgb3V0ZXJUaWNrczogdHJ1ZSB9KTtcblxuICAgIHZhciBzaG93VGlja0xhYmVscyA9IGNvZXJjZSgnc2hvd3RpY2tsYWJlbHMnKTtcbiAgICBpZihzaG93VGlja0xhYmVscykge1xuICAgICAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICd0aWNrZm9udCcsIHtcbiAgICAgICAgICAgIGZhbWlseTogb3B0aW9ucy5mb250LmZhbWlseSxcbiAgICAgICAgICAgIHNpemU6IG9wdGlvbnMuZm9udC5zaXplLFxuICAgICAgICAgICAgY29sb3I6IGRmbHRGb250Q29sb3JcbiAgICAgICAgfSk7XG4gICAgICAgIGNvZXJjZSgndGlja2FuZ2xlJyk7XG4gICAgICAgIGNvZXJjZSgndGlja2Zvcm1hdCcpO1xuICAgIH1cblxuICAgIGhhbmRsZUxpbmVHcmlkRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCB7XG4gICAgICAgIGRmbHRDb2xvcjogZGZsdENvbG9yLFxuICAgICAgICBiZ0NvbG9yOiBvcHRpb25zLmJnQ29sb3IsXG4gICAgICAgIC8vIGRlZmF1bHQgZ3JpZCBjb2xvciBpcyBkYXJrZXIgaGVyZSAoNjAlLCB2cyBjYXJ0ZXNpYW4gZGVmYXVsdCB+OTElKVxuICAgICAgICAvLyBiZWNhdXNlIHRoZSBncmlkIGlzIG5vdCBzcXVhcmUgc28gdGhlIGV5ZSBuZWVkcyBoZWF2aWVyIGN1ZXMgdG8gZm9sbG93XG4gICAgICAgIGJsZW5kOiA2MCxcbiAgICAgICAgc2hvd0xpbmU6IHRydWUsXG4gICAgICAgIHNob3dHcmlkOiB0cnVlLFxuICAgICAgICBub1plcm9MaW5lOiB0cnVlLFxuICAgICAgICBhdHRyaWJ1dGVzOiBheEF0dHJzXG4gICAgfSk7XG5cbiAgICBjb2VyY2UoJ2hvdmVyZm9ybWF0Jyk7XG4gICAgY29lcmNlKCdsYXllcicpO1xufVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi4vY2FydGVzaWFuL2xpbmVfZ3JpZF9kZWZhdWx0c1wiOjc4MSxcIi4uL2NhcnRlc2lhbi90aWNrX2xhYmVsX2RlZmF1bHRzXCI6Nzg2LFwiLi4vY2FydGVzaWFuL3RpY2tfbWFya19kZWZhdWx0c1wiOjc4NyxcIi4uL2NhcnRlc2lhbi90aWNrX3ZhbHVlX2RlZmF1bHRzXCI6Nzg4LFwiLi4vc3VicGxvdF9kZWZhdWx0c1wiOjg0MixcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo4NDR9XSw4NDY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgdGlueWNvbG9yID0gX2RlcmVxXygndGlueWNvbG9yMicpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIF8gPSBMaWIuXztcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgc2V0Q29udmVydCA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9zZXRfY29udmVydCcpO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBQbG90cyA9IF9kZXJlcV8oJy4uL3Bsb3RzJyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgZHJhZ0VsZW1lbnQgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYWdlbGVtZW50Jyk7XG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgVGl0bGVzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy90aXRsZXMnKTtcbnZhciBwcmVwU2VsZWN0ID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL3NlbGVjdCcpLnByZXBTZWxlY3Q7XG52YXIgc2VsZWN0T25DbGljayA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9zZWxlY3QnKS5zZWxlY3RPbkNsaWNrO1xudmFyIGNsZWFyU2VsZWN0ID0gX2RlcmVxXygnLi4vY2FydGVzaWFuL3NlbGVjdCcpLmNsZWFyU2VsZWN0O1xudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4uL2NhcnRlc2lhbi9jb25zdGFudHMnKTtcblxuZnVuY3Rpb24gVGVybmFyeShvcHRpb25zLCBmdWxsTGF5b3V0KSB7XG4gICAgdGhpcy5pZCA9IG9wdGlvbnMuaWQ7XG4gICAgdGhpcy5ncmFwaERpdiA9IG9wdGlvbnMuZ3JhcGhEaXY7XG4gICAgdGhpcy5pbml0KGZ1bGxMYXlvdXQpO1xuICAgIHRoaXMubWFrZUZyYW1ld29yayhmdWxsTGF5b3V0KTtcblxuICAgIC8vIHVuZm9ydHVuYXRlbHksIHdlIGhhdmUgdG8ga2VlcCB0cmFjayBvZiBzb21lIGF4aXMgdGljayBzZXR0aW5nc1xuICAgIC8vIGFzIHRlcm5hcnkgc3VicGxvdHMgZG8gbm90IGltcGxlbWVudCB0aGUgJ3RpY2tzJyBlZGl0VHlwZVxuICAgIHRoaXMuYVRpY2tMYXlvdXQgPSBudWxsO1xuICAgIHRoaXMuYlRpY2tMYXlvdXQgPSBudWxsO1xuICAgIHRoaXMuY1RpY2tMYXlvdXQgPSBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFRlcm5hcnk7XG5cbnZhciBwcm90byA9IFRlcm5hcnkucHJvdG90eXBlO1xuXG5wcm90by5pbml0ID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIHRoaXMuY29udGFpbmVyID0gZnVsbExheW91dC5fdGVybmFyeWxheWVyO1xuICAgIHRoaXMuZGVmcyA9IGZ1bGxMYXlvdXQuX2RlZnM7XG4gICAgdGhpcy5sYXlvdXRJZCA9IGZ1bGxMYXlvdXQuX3VpZDtcbiAgICB0aGlzLnRyYWNlSGFzaCA9IHt9O1xuICAgIHRoaXMubGF5ZXJzID0ge307XG59O1xuXG5wcm90by5wbG90ID0gZnVuY3Rpb24odGVybmFyeUNhbGNEYXRhLCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgdGVybmFyeUxheW91dCA9IGZ1bGxMYXlvdXRbX3RoaXMuaWRdO1xuICAgIHZhciBncmFwaFNpemUgPSBmdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgX3RoaXMuX2hhc0NsaXBPbkF4aXNGYWxzZSA9IGZhbHNlO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0ZXJuYXJ5Q2FsY0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gdGVybmFyeUNhbGNEYXRhW2ldWzBdLnRyYWNlO1xuXG4gICAgICAgIGlmKHRyYWNlLmNsaXBvbmF4aXMgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBfdGhpcy5faGFzQ2xpcE9uQXhpc0ZhbHNlID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgX3RoaXMudXBkYXRlTGF5ZXJzKHRlcm5hcnlMYXlvdXQpO1xuICAgIF90aGlzLmFkanVzdExheW91dCh0ZXJuYXJ5TGF5b3V0LCBncmFwaFNpemUpO1xuICAgIFBsb3RzLmdlbmVyYWxVcGRhdGVQZXJUcmFjZU1vZHVsZShfdGhpcy5ncmFwaERpdiwgX3RoaXMsIHRlcm5hcnlDYWxjRGF0YSwgdGVybmFyeUxheW91dCk7XG4gICAgX3RoaXMubGF5ZXJzLnBsb3RiZy5zZWxlY3QoJ3BhdGgnKS5jYWxsKENvbG9yLmZpbGwsIHRlcm5hcnlMYXlvdXQuYmdjb2xvcik7XG59O1xuXG5wcm90by5tYWtlRnJhbWV3b3JrID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGdkID0gX3RoaXMuZ3JhcGhEaXY7XG4gICAgdmFyIHRlcm5hcnlMYXlvdXQgPSBmdWxsTGF5b3V0W190aGlzLmlkXTtcblxuICAgIHZhciBjbGlwSWQgPSBfdGhpcy5jbGlwSWQgPSAnY2xpcCcgKyBfdGhpcy5sYXlvdXRJZCArIF90aGlzLmlkO1xuICAgIHZhciBjbGlwSWRSZWxhdGl2ZSA9IF90aGlzLmNsaXBJZFJlbGF0aXZlID0gJ2NsaXAtcmVsYXRpdmUnICsgX3RoaXMubGF5b3V0SWQgKyBfdGhpcy5pZDtcblxuICAgIC8vIGNsaXBwYXRoIGZvciB0aGlzIHRlcm5hcnkgc3VicGxvdFxuICAgIF90aGlzLmNsaXBEZWYgPSBMaWIuZW5zdXJlU2luZ2xlQnlJZChmdWxsTGF5b3V0Ll9jbGlwcywgJ2NsaXBQYXRoJywgY2xpcElkLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXBwZW5kKCdwYXRoJykuYXR0cignZCcsICdNMCwwWicpO1xuICAgIH0pO1xuXG4gICAgLy8gJ3JlbGF0aXZlJyBjbGlwcGF0aCAoaS5lLiBubyB0cmFuc2xhdGlvbikgZm9yIHRoaXMgdGVybmFyeSBzdWJwbG90XG4gICAgX3RoaXMuY2xpcERlZlJlbGF0aXZlID0gTGliLmVuc3VyZVNpbmdsZUJ5SWQoZnVsbExheW91dC5fY2xpcHMsICdjbGlwUGF0aCcsIGNsaXBJZFJlbGF0aXZlLCBmdW5jdGlvbihzKSB7XG4gICAgICAgIHMuYXBwZW5kKCdwYXRoJykuYXR0cignZCcsICdNMCwwWicpO1xuICAgIH0pO1xuXG4gICAgLy8gY29udGFpbmVyIGZvciBldmVyeXRoaW5nIGluIHRoaXMgdGVybmFyeSBzdWJwbG90XG4gICAgX3RoaXMucGxvdENvbnRhaW5lciA9IExpYi5lbnN1cmVTaW5nbGUoX3RoaXMuY29udGFpbmVyLCAnZycsIF90aGlzLmlkKTtcbiAgICBfdGhpcy51cGRhdGVMYXllcnModGVybmFyeUxheW91dCk7XG5cbiAgICBEcmF3aW5nLnNldENsaXBVcmwoX3RoaXMubGF5ZXJzLmJhY2twbG90LCBjbGlwSWQsIGdkKTtcbiAgICBEcmF3aW5nLnNldENsaXBVcmwoX3RoaXMubGF5ZXJzLmdyaWRzLCBjbGlwSWQsIGdkKTtcbn07XG5cbnByb3RvLnVwZGF0ZUxheWVycyA9IGZ1bmN0aW9uKHRlcm5hcnlMYXlvdXQpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBsYXllcnMgPSBfdGhpcy5sYXllcnM7XG5cbiAgICAvLyBpbnNpZGUgdGhhdCBjb250YWluZXIsIHdlIGhhdmUgb25lIGNvbnRhaW5lciBmb3IgdGhlIGRhdGEsIGFuZFxuICAgIC8vIG9uZSBlYWNoIGZvciB0aGUgdGhyZWUgYXhlcyBhcm91bmQgaXQuXG5cbiAgICB2YXIgcGxvdExheWVycyA9IFsnZHJhZ2xheWVyJywgJ3Bsb3RiZycsICdiYWNrcGxvdCcsICdncmlkcyddO1xuXG4gICAgaWYodGVybmFyeUxheW91dC5hYXhpcy5sYXllciA9PT0gJ2JlbG93IHRyYWNlcycpIHtcbiAgICAgICAgcGxvdExheWVycy5wdXNoKCdhYXhpcycsICdhbGluZScpO1xuICAgIH1cbiAgICBpZih0ZXJuYXJ5TGF5b3V0LmJheGlzLmxheWVyID09PSAnYmVsb3cgdHJhY2VzJykge1xuICAgICAgICBwbG90TGF5ZXJzLnB1c2goJ2JheGlzJywgJ2JsaW5lJyk7XG4gICAgfVxuICAgIGlmKHRlcm5hcnlMYXlvdXQuY2F4aXMubGF5ZXIgPT09ICdiZWxvdyB0cmFjZXMnKSB7XG4gICAgICAgIHBsb3RMYXllcnMucHVzaCgnY2F4aXMnLCAnY2xpbmUnKTtcbiAgICB9XG5cbiAgICBwbG90TGF5ZXJzLnB1c2goJ2Zyb250cGxvdCcpO1xuXG4gICAgaWYodGVybmFyeUxheW91dC5hYXhpcy5sYXllciA9PT0gJ2Fib3ZlIHRyYWNlcycpIHtcbiAgICAgICAgcGxvdExheWVycy5wdXNoKCdhYXhpcycsICdhbGluZScpO1xuICAgIH1cbiAgICBpZih0ZXJuYXJ5TGF5b3V0LmJheGlzLmxheWVyID09PSAnYWJvdmUgdHJhY2VzJykge1xuICAgICAgICBwbG90TGF5ZXJzLnB1c2goJ2JheGlzJywgJ2JsaW5lJyk7XG4gICAgfVxuICAgIGlmKHRlcm5hcnlMYXlvdXQuY2F4aXMubGF5ZXIgPT09ICdhYm92ZSB0cmFjZXMnKSB7XG4gICAgICAgIHBsb3RMYXllcnMucHVzaCgnY2F4aXMnLCAnY2xpbmUnKTtcbiAgICB9XG5cbiAgICB2YXIgdG9wbGV2ZWwgPSBfdGhpcy5wbG90Q29udGFpbmVyLnNlbGVjdEFsbCgnZy50b3BsZXZlbCcpXG4gICAgICAgIC5kYXRhKHBsb3RMYXllcnMsIFN0cmluZyk7XG5cbiAgICB2YXIgZ3JpZHMgPSBbJ2FncmlkJywgJ2JncmlkJywgJ2NncmlkJ107XG5cbiAgICB0b3BsZXZlbC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuICd0b3BsZXZlbCAnICsgZDsgfSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHMgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBsYXllcnNbZF0gPSBzO1xuXG4gICAgICAgICAgICAvLyBjb250YWluZXJzIGZvciBkaWZmZXJlbnQgdHJhY2UgdHlwZXMuXG4gICAgICAgICAgICAvLyBOT1RFIC0gdGhpcyBpcyBkaWZmZXJlbnQgZnJvbSBjYXJ0ZXNpYW4sIHdoZXJlIGFsbCB0cmFjZXNcbiAgICAgICAgICAgIC8vIGFyZSBpbiBmcm9udCBvZiBncmlkcy4gSGVyZSBJJ20gcHV0dGluZyBtYXBzIGJlaGluZCB0aGUgZ3JpZHNcbiAgICAgICAgICAgIC8vIHNvIHRoZSBncmlkcyB3aWxsIGFsd2F5cyBiZSB2aXNpYmxlIGlmIHRoZXkncmUgcmVxdWVzdGVkLlxuICAgICAgICAgICAgLy8gUGVyaGFwcyB3ZSB3YW50IHRoYXQgZm9yIGNhcnRlc2lhbiB0b28/XG4gICAgICAgICAgICBpZihkID09PSAnZnJvbnRwbG90Jykge1xuICAgICAgICAgICAgICAgIHMuYXBwZW5kKCdnJykuY2xhc3NlZCgnc2NhdHRlcmxheWVyJywgdHJ1ZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoZCA9PT0gJ2JhY2twbG90Jykge1xuICAgICAgICAgICAgICAgIHMuYXBwZW5kKCdnJykuY2xhc3NlZCgnbWFwbGF5ZXInLCB0cnVlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihkID09PSAncGxvdGJnJykge1xuICAgICAgICAgICAgICAgIHMuYXBwZW5kKCdwYXRoJykuYXR0cignZCcsICdNMCwwWicpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGQgPT09ICdhbGluZScgfHwgZCA9PT0gJ2JsaW5lJyB8fCBkID09PSAnY2xpbmUnKSB7XG4gICAgICAgICAgICAgICAgcy5hcHBlbmQoJ3BhdGgnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihkID09PSAnZ3JpZHMnKSB7XG4gICAgICAgICAgICAgICAgZ3JpZHMuZm9yRWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgICAgIGxheWVyc1tkXSA9IHMuYXBwZW5kKCdnJykuY2xhc3NlZCgnZ3JpZCAnICsgZCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgdG9wbGV2ZWwub3JkZXIoKTtcbn07XG5cbnZhciB3aFJhdGlvID0gTWF0aC5zcXJ0KDQgLyAzKTtcblxucHJvdG8uYWRqdXN0TGF5b3V0ID0gZnVuY3Rpb24odGVybmFyeUxheW91dCwgZ3JhcGhTaXplKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgZG9tYWluID0gdGVybmFyeUxheW91dC5kb21haW47XG4gICAgdmFyIHhEb21haW5DZW50ZXIgPSAoZG9tYWluLnhbMF0gKyBkb21haW4ueFsxXSkgLyAyO1xuICAgIHZhciB5RG9tYWluQ2VudGVyID0gKGRvbWFpbi55WzBdICsgZG9tYWluLnlbMV0pIC8gMjtcbiAgICB2YXIgeERvbWFpbiA9IGRvbWFpbi54WzFdIC0gZG9tYWluLnhbMF07XG4gICAgdmFyIHlEb21haW4gPSBkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdO1xuICAgIHZhciB3bWF4ID0geERvbWFpbiAqIGdyYXBoU2l6ZS53O1xuICAgIHZhciBobWF4ID0geURvbWFpbiAqIGdyYXBoU2l6ZS5oO1xuICAgIHZhciBzdW0gPSB0ZXJuYXJ5TGF5b3V0LnN1bTtcbiAgICB2YXIgYW1pbiA9IHRlcm5hcnlMYXlvdXQuYWF4aXMubWluO1xuICAgIHZhciBibWluID0gdGVybmFyeUxheW91dC5iYXhpcy5taW47XG4gICAgdmFyIGNtaW4gPSB0ZXJuYXJ5TGF5b3V0LmNheGlzLm1pbjtcblxuICAgIHZhciB4MCwgeTAsIHcsIGgsIHhEb21haW5GaW5hbCwgeURvbWFpbkZpbmFsO1xuXG4gICAgaWYod21heCA+IHdoUmF0aW8gKiBobWF4KSB7XG4gICAgICAgIGggPSBobWF4O1xuICAgICAgICB3ID0gaCAqIHdoUmF0aW87XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdyA9IHdtYXg7XG4gICAgICAgIGggPSB3IC8gd2hSYXRpbztcbiAgICB9XG5cbiAgICB4RG9tYWluRmluYWwgPSB4RG9tYWluICogdyAvIHdtYXg7XG4gICAgeURvbWFpbkZpbmFsID0geURvbWFpbiAqIGggLyBobWF4O1xuXG4gICAgeDAgPSBncmFwaFNpemUubCArIGdyYXBoU2l6ZS53ICogeERvbWFpbkNlbnRlciAtIHcgLyAyO1xuICAgIHkwID0gZ3JhcGhTaXplLnQgKyBncmFwaFNpemUuaCAqICgxIC0geURvbWFpbkNlbnRlcikgLSBoIC8gMjtcblxuICAgIF90aGlzLngwID0geDA7XG4gICAgX3RoaXMueTAgPSB5MDtcbiAgICBfdGhpcy53ID0gdztcbiAgICBfdGhpcy5oID0gaDtcbiAgICBfdGhpcy5zdW0gPSBzdW07XG5cbiAgICAvLyBzZXQgdXAgdGhlIHggYW5kIHkgYXhpcyBvYmplY3RzIHdlJ2xsIHVzZSB0byBsYXkgb3V0IHRoZSBwb2ludHNcbiAgICBfdGhpcy54YXhpcyA9IHtcbiAgICAgICAgdHlwZTogJ2xpbmVhcicsXG4gICAgICAgIHJhbmdlOiBbYW1pbiArIDIgKiBjbWluIC0gc3VtLCBzdW0gLSBhbWluIC0gMiAqIGJtaW5dLFxuICAgICAgICBkb21haW46IFtcbiAgICAgICAgICAgIHhEb21haW5DZW50ZXIgLSB4RG9tYWluRmluYWwgLyAyLFxuICAgICAgICAgICAgeERvbWFpbkNlbnRlciArIHhEb21haW5GaW5hbCAvIDJcbiAgICAgICAgXSxcbiAgICAgICAgX2lkOiAneCdcbiAgICB9O1xuICAgIHNldENvbnZlcnQoX3RoaXMueGF4aXMsIF90aGlzLmdyYXBoRGl2Ll9mdWxsTGF5b3V0KTtcbiAgICBfdGhpcy54YXhpcy5zZXRTY2FsZSgpO1xuICAgIF90aGlzLnhheGlzLmlzUHRXaXRoaW5SYW5nZSA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGQuYSA+PSBfdGhpcy5hYXhpcy5yYW5nZVswXSAmJlxuICAgICAgICAgICAgZC5hIDw9IF90aGlzLmFheGlzLnJhbmdlWzFdICYmXG4gICAgICAgICAgICBkLmIgPj0gX3RoaXMuYmF4aXMucmFuZ2VbMV0gJiZcbiAgICAgICAgICAgIGQuYiA8PSBfdGhpcy5iYXhpcy5yYW5nZVswXSAmJlxuICAgICAgICAgICAgZC5jID49IF90aGlzLmNheGlzLnJhbmdlWzFdICYmXG4gICAgICAgICAgICBkLmMgPD0gX3RoaXMuY2F4aXMucmFuZ2VbMF1cbiAgICAgICAgKTtcbiAgICB9O1xuXG4gICAgX3RoaXMueWF4aXMgPSB7XG4gICAgICAgIHR5cGU6ICdsaW5lYXInLFxuICAgICAgICByYW5nZTogW2FtaW4sIHN1bSAtIGJtaW4gLSBjbWluXSxcbiAgICAgICAgZG9tYWluOiBbXG4gICAgICAgICAgICB5RG9tYWluQ2VudGVyIC0geURvbWFpbkZpbmFsIC8gMixcbiAgICAgICAgICAgIHlEb21haW5DZW50ZXIgKyB5RG9tYWluRmluYWwgLyAyXG4gICAgICAgIF0sXG4gICAgICAgIF9pZDogJ3knXG4gICAgfTtcbiAgICBzZXRDb252ZXJ0KF90aGlzLnlheGlzLCBfdGhpcy5ncmFwaERpdi5fZnVsbExheW91dCk7XG4gICAgX3RoaXMueWF4aXMuc2V0U2NhbGUoKTtcbiAgICBfdGhpcy55YXhpcy5pc1B0V2l0aGluUmFuZ2UgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRydWU7IH07XG5cbiAgICAvLyBzZXQgdXAgdGhlIG1vZGlmaWVkIGF4ZXMgZm9yIHRpY2sgZHJhd2luZ1xuICAgIHZhciB5RG9tYWluMCA9IF90aGlzLnlheGlzLmRvbWFpblswXTtcblxuICAgIC8vIGFheGlzIGdvZXMgdXAgdGhlIGxlZnQgc2lkZS4gU2V0IGl0IHVwIGFzIGEgeSBheGlzLCBidXQgd2l0aFxuICAgIC8vIGZpY3RpdGlvdXMgYW5nbGVzIGFuZCBkb21haW4sIGJ1dCB0aGVuIHJvdGF0ZSBhbmQgdHJhbnNsYXRlXG4gICAgLy8gaXQgaW50byBwbGFjZSBhdCB0aGUgZW5kXG4gICAgdmFyIGFheGlzID0gX3RoaXMuYWF4aXMgPSBleHRlbmRGbGF0KHt9LCB0ZXJuYXJ5TGF5b3V0LmFheGlzLCB7XG4gICAgICAgIHJhbmdlOiBbYW1pbiwgc3VtIC0gYm1pbiAtIGNtaW5dLFxuICAgICAgICBzaWRlOiAnbGVmdCcsXG4gICAgICAgIC8vIHRpY2thbmdsZSA9ICdhdXRvJyBtZWFucyAwIGFueXdheSBmb3IgYSB5IGF4aXMsIG5lZWQgdG8gY29lcmNlIHRvIDAgaGVyZVxuICAgICAgICAvLyBzbyB3ZSBjYW4gc2hpZnQgYnkgMzAuXG4gICAgICAgIHRpY2thbmdsZTogKCt0ZXJuYXJ5TGF5b3V0LmFheGlzLnRpY2thbmdsZSB8fCAwKSAtIDMwLFxuICAgICAgICBkb21haW46IFt5RG9tYWluMCwgeURvbWFpbjAgKyB5RG9tYWluRmluYWwgKiB3aFJhdGlvXSxcbiAgICAgICAgYW5jaG9yOiAnZnJlZScsXG4gICAgICAgIHBvc2l0aW9uOiAwLFxuICAgICAgICBfaWQ6ICd5JyxcbiAgICAgICAgX2xlbmd0aDogd1xuICAgIH0pO1xuICAgIHNldENvbnZlcnQoYWF4aXMsIF90aGlzLmdyYXBoRGl2Ll9mdWxsTGF5b3V0KTtcbiAgICBhYXhpcy5zZXRTY2FsZSgpO1xuXG4gICAgLy8gYmF4aXMgZ29lcyBhY3Jvc3MgdGhlIGJvdHRvbSAoYmFja3dhcmQpLiBXZSBjYW4gc2V0IGl0IHVwIGFzIGFuIHggYXhpc1xuICAgIC8vIHdpdGhvdXQgYW55IGVuY2xvc2luZyB0cmFuc2Zvcm1hdGlvbi5cbiAgICB2YXIgYmF4aXMgPSBfdGhpcy5iYXhpcyA9IGV4dGVuZEZsYXQoe30sIHRlcm5hcnlMYXlvdXQuYmF4aXMsIHtcbiAgICAgICAgcmFuZ2U6IFtzdW0gLSBhbWluIC0gY21pbiwgYm1pbl0sXG4gICAgICAgIHNpZGU6ICdib3R0b20nLFxuICAgICAgICBkb21haW46IF90aGlzLnhheGlzLmRvbWFpbixcbiAgICAgICAgYW5jaG9yOiAnZnJlZScsXG4gICAgICAgIHBvc2l0aW9uOiAwLFxuICAgICAgICBfaWQ6ICd4JyxcbiAgICAgICAgX2xlbmd0aDogd1xuICAgIH0pO1xuICAgIHNldENvbnZlcnQoYmF4aXMsIF90aGlzLmdyYXBoRGl2Ll9mdWxsTGF5b3V0KTtcbiAgICBiYXhpcy5zZXRTY2FsZSgpO1xuXG4gICAgLy8gY2F4aXMgZ29lcyBkb3duIHRoZSByaWdodCBzaWRlLiBTZXQgaXQgdXAgYXMgYSB5IGF4aXMsIHdpdGhcbiAgICAvLyBwb3N0LXRyYW5zZm9ybWF0aW9uIHNpbWlsYXIgdG8gYWF4aXNcbiAgICB2YXIgY2F4aXMgPSBfdGhpcy5jYXhpcyA9IGV4dGVuZEZsYXQoe30sIHRlcm5hcnlMYXlvdXQuY2F4aXMsIHtcbiAgICAgICAgcmFuZ2U6IFtzdW0gLSBhbWluIC0gYm1pbiwgY21pbl0sXG4gICAgICAgIHNpZGU6ICdyaWdodCcsXG4gICAgICAgIHRpY2thbmdsZTogKCt0ZXJuYXJ5TGF5b3V0LmNheGlzLnRpY2thbmdsZSB8fCAwKSArIDMwLFxuICAgICAgICBkb21haW46IFt5RG9tYWluMCwgeURvbWFpbjAgKyB5RG9tYWluRmluYWwgKiB3aFJhdGlvXSxcbiAgICAgICAgYW5jaG9yOiAnZnJlZScsXG4gICAgICAgIHBvc2l0aW9uOiAwLFxuICAgICAgICBfaWQ6ICd5JyxcbiAgICAgICAgX2xlbmd0aDogd1xuICAgIH0pO1xuICAgIHNldENvbnZlcnQoY2F4aXMsIF90aGlzLmdyYXBoRGl2Ll9mdWxsTGF5b3V0KTtcbiAgICBjYXhpcy5zZXRTY2FsZSgpO1xuXG4gICAgdmFyIHRyaWFuZ2xlQ2xpcCA9ICdNJyArIHgwICsgJywnICsgKHkwICsgaCkgKyAnaCcgKyB3ICsgJ2wtJyArICh3IC8gMikgKyAnLC0nICsgaCArICdaJztcbiAgICBfdGhpcy5jbGlwRGVmLnNlbGVjdCgncGF0aCcpLmF0dHIoJ2QnLCB0cmlhbmdsZUNsaXApO1xuICAgIF90aGlzLmxheWVycy5wbG90Ymcuc2VsZWN0KCdwYXRoJykuYXR0cignZCcsIHRyaWFuZ2xlQ2xpcCk7XG5cbiAgICB2YXIgdHJpYW5nbGVDbGlwUmVsYXRpdmUgPSAnTTAsJyArIGggKyAnaCcgKyB3ICsgJ2wtJyArICh3IC8gMikgKyAnLC0nICsgaCArICdaJztcbiAgICBfdGhpcy5jbGlwRGVmUmVsYXRpdmUuc2VsZWN0KCdwYXRoJykuYXR0cignZCcsIHRyaWFuZ2xlQ2xpcFJlbGF0aXZlKTtcblxuICAgIHZhciBwbG90VHJhbnNmb3JtID0gJ3RyYW5zbGF0ZSgnICsgeDAgKyAnLCcgKyB5MCArICcpJztcbiAgICBfdGhpcy5wbG90Q29udGFpbmVyLnNlbGVjdEFsbCgnLnNjYXR0ZXJsYXllciwubWFwbGF5ZXInKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgcGxvdFRyYW5zZm9ybSk7XG5cbiAgICBfdGhpcy5jbGlwRGVmUmVsYXRpdmUuc2VsZWN0KCdwYXRoJykuYXR0cigndHJhbnNmb3JtJywgbnVsbCk7XG5cbiAgICAvLyBUT0RPOiBzaGlmdCBheGVzIHRvIGFjY29tbW9kYXRlIGxpbmV3aWR0aCpzaW4oMzApIHRpY2sgbWFyayBhbmdsZVxuXG4gICAgLy8gVE9ETzogdGhlcmUncyBwcm9iYWJseSBhbiBlYXNpZXIgd2F5IHRvIGhhbmRsZSB0aGVzZSB0cmFuc2xhdGlvbnMvb2Zmc2V0cyBub3cuLi5cbiAgICB2YXIgYlRyYW5zZm9ybSA9ICd0cmFuc2xhdGUoJyArICh4MCAtIGJheGlzLl9vZmZzZXQpICsgJywnICsgKHkwICsgaCkgKyAnKSc7XG5cbiAgICBfdGhpcy5sYXllcnMuYmF4aXMuYXR0cigndHJhbnNmb3JtJywgYlRyYW5zZm9ybSk7XG4gICAgX3RoaXMubGF5ZXJzLmJncmlkLmF0dHIoJ3RyYW5zZm9ybScsIGJUcmFuc2Zvcm0pO1xuXG4gICAgdmFyIGFUcmFuc2Zvcm0gPSAndHJhbnNsYXRlKCcgKyAoeDAgKyB3IC8gMikgKyAnLCcgKyB5MCArXG4gICAgICAgICcpcm90YXRlKDMwKXRyYW5zbGF0ZSgwLCcgKyAtYWF4aXMuX29mZnNldCArICcpJztcbiAgICBfdGhpcy5sYXllcnMuYWF4aXMuYXR0cigndHJhbnNmb3JtJywgYVRyYW5zZm9ybSk7XG4gICAgX3RoaXMubGF5ZXJzLmFncmlkLmF0dHIoJ3RyYW5zZm9ybScsIGFUcmFuc2Zvcm0pO1xuXG4gICAgdmFyIGNUcmFuc2Zvcm0gPSAndHJhbnNsYXRlKCcgKyAoeDAgKyB3IC8gMikgKyAnLCcgKyB5MCArXG4gICAgICAgICcpcm90YXRlKC0zMCl0cmFuc2xhdGUoMCwnICsgLWNheGlzLl9vZmZzZXQgKyAnKSc7XG4gICAgX3RoaXMubGF5ZXJzLmNheGlzLmF0dHIoJ3RyYW5zZm9ybScsIGNUcmFuc2Zvcm0pO1xuICAgIF90aGlzLmxheWVycy5jZ3JpZC5hdHRyKCd0cmFuc2Zvcm0nLCBjVHJhbnNmb3JtKTtcblxuICAgIF90aGlzLmRyYXdBeGVzKHRydWUpO1xuXG4gICAgX3RoaXMubGF5ZXJzLmFsaW5lLnNlbGVjdCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdkJywgYWF4aXMuc2hvd2xpbmUgP1xuICAgICAgICAgICAgJ00nICsgeDAgKyAnLCcgKyAoeTAgKyBoKSArICdsJyArICh3IC8gMikgKyAnLC0nICsgaCA6ICdNMCwwJylcbiAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBhYXhpcy5saW5lY29sb3IgfHwgJyMwMDAnKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIChhYXhpcy5saW5ld2lkdGggfHwgMCkgKyAncHgnKTtcbiAgICBfdGhpcy5sYXllcnMuYmxpbmUuc2VsZWN0KCdwYXRoJylcbiAgICAgICAgLmF0dHIoJ2QnLCBiYXhpcy5zaG93bGluZSA/XG4gICAgICAgICAgICAnTScgKyB4MCArICcsJyArICh5MCArIGgpICsgJ2gnICsgdyA6ICdNMCwwJylcbiAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBiYXhpcy5saW5lY29sb3IgfHwgJyMwMDAnKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIChiYXhpcy5saW5ld2lkdGggfHwgMCkgKyAncHgnKTtcbiAgICBfdGhpcy5sYXllcnMuY2xpbmUuc2VsZWN0KCdwYXRoJylcbiAgICAgICAgLmF0dHIoJ2QnLCBjYXhpcy5zaG93bGluZSA/XG4gICAgICAgICAgICAnTScgKyAoeDAgKyB3IC8gMikgKyAnLCcgKyB5MCArICdsJyArICh3IC8gMikgKyAnLCcgKyBoIDogJ00wLDAnKVxuICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIGNheGlzLmxpbmVjb2xvciB8fCAnIzAwMCcpXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgKGNheGlzLmxpbmV3aWR0aCB8fCAwKSArICdweCcpO1xuXG4gICAgaWYoIV90aGlzLmdyYXBoRGl2Ll9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgX3RoaXMuaW5pdEludGVyYWN0aW9ucygpO1xuICAgIH1cblxuICAgIERyYXdpbmcuc2V0Q2xpcFVybChcbiAgICAgICAgX3RoaXMubGF5ZXJzLmZyb250cGxvdCxcbiAgICAgICAgX3RoaXMuX2hhc0NsaXBPbkF4aXNGYWxzZSA/IG51bGwgOiBfdGhpcy5jbGlwSWQsXG4gICAgICAgIF90aGlzLmdyYXBoRGl2XG4gICAgKTtcbn07XG5cbnByb3RvLmRyYXdBeGVzID0gZnVuY3Rpb24oZG9UaXRsZXMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIHZhciBnZCA9IF90aGlzLmdyYXBoRGl2O1xuICAgIHZhciB0aXRsZXN1ZmZpeCA9IF90aGlzLmlkLnN1YnN0cig3KSArICd0aXRsZSc7XG4gICAgdmFyIGxheWVycyA9IF90aGlzLmxheWVycztcbiAgICB2YXIgYWF4aXMgPSBfdGhpcy5hYXhpcztcbiAgICB2YXIgYmF4aXMgPSBfdGhpcy5iYXhpcztcbiAgICB2YXIgY2F4aXMgPSBfdGhpcy5jYXhpcztcblxuICAgIF90aGlzLmRyYXdBeChhYXhpcyk7XG4gICAgX3RoaXMuZHJhd0F4KGJheGlzKTtcbiAgICBfdGhpcy5kcmF3QXgoY2F4aXMpO1xuXG4gICAgaWYoZG9UaXRsZXMpIHtcbiAgICAgICAgdmFyIGFwYWQgPSBNYXRoLm1heChhYXhpcy5zaG93dGlja2xhYmVscyA/IGFheGlzLnRpY2tmb250LnNpemUgLyAyIDogMCxcbiAgICAgICAgICAgIChjYXhpcy5zaG93dGlja2xhYmVscyA/IGNheGlzLnRpY2tmb250LnNpemUgKiAwLjc1IDogMCkgK1xuICAgICAgICAgICAgKGNheGlzLnRpY2tzID09PSAnb3V0c2lkZScgPyBjYXhpcy50aWNrbGVuICogMC44NyA6IDApKTtcbiAgICAgICAgdmFyIGJwYWQgPSAoYmF4aXMuc2hvd3RpY2tsYWJlbHMgPyBiYXhpcy50aWNrZm9udC5zaXplIDogMCkgK1xuICAgICAgICAgICAgKGJheGlzLnRpY2tzID09PSAnb3V0c2lkZScgPyBiYXhpcy50aWNrbGVuIDogMCkgKyAzO1xuXG4gICAgICAgIGxheWVyc1snYS10aXRsZSddID0gVGl0bGVzLmRyYXcoZ2QsICdhJyArIHRpdGxlc3VmZml4LCB7XG4gICAgICAgICAgICBwcm9wQ29udGFpbmVyOiBhYXhpcyxcbiAgICAgICAgICAgIHByb3BOYW1lOiBfdGhpcy5pZCArICcuYWF4aXMudGl0bGUnLFxuICAgICAgICAgICAgcGxhY2Vob2xkZXI6IF8oZ2QsICdDbGljayB0byBlbnRlciBDb21wb25lbnQgQSB0aXRsZScpLFxuICAgICAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgICAgIHg6IF90aGlzLngwICsgX3RoaXMudyAvIDIsXG4gICAgICAgICAgICAgICAgeTogX3RoaXMueTAgLSBhYXhpcy50aXRsZS5mb250LnNpemUgLyAzIC0gYXBhZCxcbiAgICAgICAgICAgICAgICAndGV4dC1hbmNob3InOiAnbWlkZGxlJ1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgbGF5ZXJzWydiLXRpdGxlJ10gPSBUaXRsZXMuZHJhdyhnZCwgJ2InICsgdGl0bGVzdWZmaXgsIHtcbiAgICAgICAgICAgIHByb3BDb250YWluZXI6IGJheGlzLFxuICAgICAgICAgICAgcHJvcE5hbWU6IF90aGlzLmlkICsgJy5iYXhpcy50aXRsZScsXG4gICAgICAgICAgICBwbGFjZWhvbGRlcjogXyhnZCwgJ0NsaWNrIHRvIGVudGVyIENvbXBvbmVudCBCIHRpdGxlJyksXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgICAgeDogX3RoaXMueDAgLSBicGFkLFxuICAgICAgICAgICAgICAgIHk6IF90aGlzLnkwICsgX3RoaXMuaCArIGJheGlzLnRpdGxlLmZvbnQuc2l6ZSAqIDAuODMgKyBicGFkLFxuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6ICdtaWRkbGUnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBsYXllcnNbJ2MtdGl0bGUnXSA9IFRpdGxlcy5kcmF3KGdkLCAnYycgKyB0aXRsZXN1ZmZpeCwge1xuICAgICAgICAgICAgcHJvcENvbnRhaW5lcjogY2F4aXMsXG4gICAgICAgICAgICBwcm9wTmFtZTogX3RoaXMuaWQgKyAnLmNheGlzLnRpdGxlJyxcbiAgICAgICAgICAgIHBsYWNlaG9sZGVyOiBfKGdkLCAnQ2xpY2sgdG8gZW50ZXIgQ29tcG9uZW50IEMgdGl0bGUnKSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgICB4OiBfdGhpcy54MCArIF90aGlzLncgKyBicGFkLFxuICAgICAgICAgICAgICAgIHk6IF90aGlzLnkwICsgX3RoaXMuaCArIGNheGlzLnRpdGxlLmZvbnQuc2l6ZSAqIDAuODMgKyBicGFkLFxuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6ICdtaWRkbGUnXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5cbnByb3RvLmRyYXdBeCA9IGZ1bmN0aW9uKGF4KSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB2YXIgZ2QgPSBfdGhpcy5ncmFwaERpdjtcbiAgICB2YXIgYXhOYW1lID0gYXguX25hbWU7XG4gICAgdmFyIGF4TGV0dGVyID0gYXhOYW1lLmNoYXJBdCgwKTtcbiAgICB2YXIgYXhJZCA9IGF4Ll9pZDtcbiAgICB2YXIgYXhMYXllciA9IF90aGlzLmxheWVyc1theE5hbWVdO1xuICAgIHZhciBjb3VudGVyQW5nbGUgPSAzMDtcblxuICAgIHZhciBzdGFzaEtleSA9IGF4TGV0dGVyICsgJ3RpY2tMYXlvdXQnO1xuICAgIHZhciBuZXdUaWNrTGF5b3V0ID0gc3RyVGlja0xheW91dChheCk7XG4gICAgaWYoX3RoaXNbc3Rhc2hLZXldICE9PSBuZXdUaWNrTGF5b3V0KSB7XG4gICAgICAgIGF4TGF5ZXIuc2VsZWN0QWxsKCcuJyArIGF4SWQgKyAndGljaycpLnJlbW92ZSgpO1xuICAgICAgICBfdGhpc1tzdGFzaEtleV0gPSBuZXdUaWNrTGF5b3V0O1xuICAgIH1cblxuICAgIGF4LnNldFNjYWxlKCk7XG5cbiAgICB2YXIgdmFscyA9IEF4ZXMuY2FsY1RpY2tzKGF4KTtcbiAgICB2YXIgdmFsc0NsaXBwZWQgPSBBeGVzLmNsaXBFbmRzKGF4LCB2YWxzKTtcbiAgICB2YXIgdHJhbnNGbiA9IEF4ZXMubWFrZVRyYW5zRm4oYXgpO1xuICAgIHZhciB0aWNrU2lnbiA9IEF4ZXMuZ2V0VGlja1NpZ25zKGF4KVsyXTtcblxuICAgIHZhciBjYVJhZCA9IExpYi5kZWcycmFkKGNvdW50ZXJBbmdsZSk7XG4gICAgdmFyIHBhZCA9IHRpY2tTaWduICogKGF4LmxpbmV3aWR0aCB8fCAxKSAvIDI7XG4gICAgdmFyIGxlbiA9IHRpY2tTaWduICogYXgudGlja2xlbjtcbiAgICB2YXIgdyA9IF90aGlzLnc7XG4gICAgdmFyIGggPSBfdGhpcy5oO1xuXG4gICAgdmFyIHRpY2tQYXRoID0gYXhMZXR0ZXIgPT09ICdiJyA/XG4gICAgICAgICdNMCwnICsgcGFkICsgJ2wnICsgKE1hdGguc2luKGNhUmFkKSAqIGxlbikgKyAnLCcgKyAoTWF0aC5jb3MoY2FSYWQpICogbGVuKSA6XG4gICAgICAgICdNJyArIHBhZCArICcsMGwnICsgKE1hdGguY29zKGNhUmFkKSAqIGxlbikgKyAnLCcgKyAoLU1hdGguc2luKGNhUmFkKSAqIGxlbik7XG5cbiAgICB2YXIgZ3JpZFBhdGggPSB7XG4gICAgICAgIGE6ICdNMCwwbCcgKyBoICsgJywtJyArICh3IC8gMiksXG4gICAgICAgIGI6ICdNMCwwbC0nICsgKHcgLyAyKSArICcsLScgKyBoLFxuICAgICAgICBjOiAnTTAsMGwtJyArIGggKyAnLCcgKyAodyAvIDIpXG4gICAgfVtheExldHRlcl07XG5cbiAgICBBeGVzLmRyYXdUaWNrcyhnZCwgYXgsIHtcbiAgICAgICAgdmFsczogYXgudGlja3MgPT09ICdpbnNpZGUnID8gdmFsc0NsaXBwZWQgOiB2YWxzLFxuICAgICAgICBsYXllcjogYXhMYXllcixcbiAgICAgICAgcGF0aDogdGlja1BhdGgsXG4gICAgICAgIHRyYW5zRm46IHRyYW5zRm4sXG4gICAgICAgIGNyaXNwOiBmYWxzZVxuICAgIH0pO1xuXG4gICAgQXhlcy5kcmF3R3JpZChnZCwgYXgsIHtcbiAgICAgICAgdmFsczogdmFsc0NsaXBwZWQsXG4gICAgICAgIGxheWVyOiBfdGhpcy5sYXllcnNbYXhMZXR0ZXIgKyAnZ3JpZCddLFxuICAgICAgICBwYXRoOiBncmlkUGF0aCxcbiAgICAgICAgdHJhbnNGbjogdHJhbnNGbixcbiAgICAgICAgY3Jpc3A6IGZhbHNlXG4gICAgfSk7XG5cbiAgICBBeGVzLmRyYXdMYWJlbHMoZ2QsIGF4LCB7XG4gICAgICAgIHZhbHM6IHZhbHMsXG4gICAgICAgIGxheWVyOiBheExheWVyLFxuICAgICAgICB0cmFuc0ZuOiB0cmFuc0ZuLFxuICAgICAgICBsYWJlbEZuczogQXhlcy5tYWtlTGFiZWxGbnMoYXgsIDAsIGNvdW50ZXJBbmdsZSlcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIHN0clRpY2tMYXlvdXQoYXhMYXlvdXQpIHtcbiAgICByZXR1cm4gYXhMYXlvdXQudGlja3MgKyBTdHJpbmcoYXhMYXlvdXQudGlja2xlbikgKyBTdHJpbmcoYXhMYXlvdXQuc2hvd3RpY2tsYWJlbHMpO1xufVxuXG4vLyBoYXJkIGNvZGVkIHBhdGhzIGZvciB6b29tIGNvcm5lcnNcbi8vIHVzZXMgdGhlIHNhbWUgc2l6aW5nIGFzIGNhcnRlc2lhbiwgbGVuZ3RoIGlzIE1JTlpPT00vMiwgd2lkdGggaXMgM3B4XG52YXIgQ0xFTiA9IGNvbnN0YW50cy5NSU5aT09NIC8gMiArIDAuODc7XG52YXIgQkxQQVRIID0gJ20tMC44NywuNWgnICsgQ0xFTiArICd2M2gtJyArIChDTEVOICsgNS4yKSArXG4gICAgJ2wnICsgKENMRU4gLyAyICsgMi42KSArICcsLScgKyAoQ0xFTiAqIDAuODcgKyA0LjUpICtcbiAgICAnbDIuNiwxLjVsLScgKyAoQ0xFTiAvIDIpICsgJywnICsgKENMRU4gKiAwLjg3KSArICdaJztcbnZhciBCUlBBVEggPSAnbTAuODcsLjVoLScgKyBDTEVOICsgJ3YzaCcgKyAoQ0xFTiArIDUuMikgK1xuICAgICdsLScgKyAoQ0xFTiAvIDIgKyAyLjYpICsgJywtJyArIChDTEVOICogMC44NyArIDQuNSkgK1xuICAgICdsLTIuNiwxLjVsJyArIChDTEVOIC8gMikgKyAnLCcgKyAoQ0xFTiAqIDAuODcpICsgJ1onO1xudmFyIFRPUFBBVEggPSAnbTAsMWwnICsgKENMRU4gLyAyKSArICcsJyArIChDTEVOICogMC44NykgK1xuICAgICdsMi42LC0xLjVsLScgKyAoQ0xFTiAvIDIgKyAyLjYpICsgJywtJyArIChDTEVOICogMC44NyArIDQuNSkgK1xuICAgICdsLScgKyAoQ0xFTiAvIDIgKyAyLjYpICsgJywnICsgKENMRU4gKiAwLjg3ICsgNC41KSArXG4gICAgJ2wyLjYsMS41bCcgKyAoQ0xFTiAvIDIpICsgJywtJyArIChDTEVOICogMC44NykgKyAnWic7XG52YXIgU1RBUlRNQVJLRVIgPSAnbTAuNSwwLjVoNXYtMmgtNXYtNWgtMnY1aC01djJoNXY1aDJaJztcblxuLy8gSSBndWVzcyB0aGlzIGNvdWxkIGJlIHNoYXJlZCB3aXRoIGNhcnRlc2lhbi4uLiBidXQgZm9yIG5vdyBpdCdzIHNlcGFyYXRlLlxudmFyIFNIT1daT09NT1VUVElQID0gdHJ1ZTtcblxucHJvdG8uaW5pdEludGVyYWN0aW9ucyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgdmFyIGRyYWdnZXIgPSBfdGhpcy5sYXllcnMucGxvdGJnLnNlbGVjdCgncGF0aCcpLm5vZGUoKTtcbiAgICB2YXIgZ2QgPSBfdGhpcy5ncmFwaERpdjtcbiAgICB2YXIgem9vbUxheWVyID0gZ2QuX2Z1bGxMYXlvdXQuX3pvb21sYXllcjtcblxuICAgIC8vIHVzZSBwbG90YmcgZm9yIHRoZSBtYWluIGludGVyYWN0aW9uc1xuICAgIHZhciBkcmFnT3B0aW9ucyA9IHtcbiAgICAgICAgZWxlbWVudDogZHJhZ2dlcixcbiAgICAgICAgZ2Q6IGdkLFxuICAgICAgICBwbG90aW5mbzoge1xuICAgICAgICAgICAgaWQ6IF90aGlzLmlkLFxuICAgICAgICAgICAgeGF4aXM6IF90aGlzLnhheGlzLFxuICAgICAgICAgICAgeWF4aXM6IF90aGlzLnlheGlzXG4gICAgICAgIH0sXG4gICAgICAgIHN1YnBsb3Q6IF90aGlzLmlkLFxuICAgICAgICBwcmVwRm46IGZ1bmN0aW9uKGUsIHN0YXJ0WCwgc3RhcnRZKSB7XG4gICAgICAgICAgICAvLyB0aGVzZSBhcmVuJ3QgYXZhaWxhYmxlIHlldCB3aGVuIGluaXRJbnRlcmFjdGlvbnNcbiAgICAgICAgICAgIC8vIGlzIGNhbGxlZFxuICAgICAgICAgICAgZHJhZ09wdGlvbnMueGF4ZXMgPSBbX3RoaXMueGF4aXNdO1xuICAgICAgICAgICAgZHJhZ09wdGlvbnMueWF4ZXMgPSBbX3RoaXMueWF4aXNdO1xuICAgICAgICAgICAgdmFyIGRyYWdNb2RlTm93ID0gZ2QuX2Z1bGxMYXlvdXQuZHJhZ21vZGU7XG5cbiAgICAgICAgICAgIGlmKGRyYWdNb2RlTm93ID09PSAnbGFzc28nKSBkcmFnT3B0aW9ucy5taW5EcmFnID0gMTtcbiAgICAgICAgICAgIGVsc2UgZHJhZ09wdGlvbnMubWluRHJhZyA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgaWYoZHJhZ01vZGVOb3cgPT09ICd6b29tJykge1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLm1vdmVGbiA9IHpvb21Nb3ZlO1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLmNsaWNrRm4gPSBjbGlja1pvb21QYW47XG4gICAgICAgICAgICAgICAgZHJhZ09wdGlvbnMuZG9uZUZuID0gem9vbURvbmU7XG4gICAgICAgICAgICAgICAgem9vbVByZXAoZSwgc3RhcnRYLCBzdGFydFkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGRyYWdNb2RlTm93ID09PSAncGFuJykge1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLm1vdmVGbiA9IHBsb3REcmFnO1xuICAgICAgICAgICAgICAgIGRyYWdPcHRpb25zLmNsaWNrRm4gPSBjbGlja1pvb21QYW47XG4gICAgICAgICAgICAgICAgZHJhZ09wdGlvbnMuZG9uZUZuID0gZHJhZ0RvbmU7XG4gICAgICAgICAgICAgICAgcGFuUHJlcCgpO1xuICAgICAgICAgICAgICAgIGNsZWFyU2VsZWN0KGdkKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihkcmFnTW9kZU5vdyA9PT0gJ3NlbGVjdCcgfHwgZHJhZ01vZGVOb3cgPT09ICdsYXNzbycpIHtcbiAgICAgICAgICAgICAgICBwcmVwU2VsZWN0KGUsIHN0YXJ0WCwgc3RhcnRZLCBkcmFnT3B0aW9ucywgZHJhZ01vZGVOb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhciB4MCwgeTAsIG1pbnMwLCBzcGFuMCwgbWlucywgbHVtLCBwYXRoMCwgZGltbWVkLCB6YiwgY29ybmVycztcblxuICAgIGZ1bmN0aW9uIG1ha2VVcGRhdGUoX21pbnMpIHtcbiAgICAgICAgdmFyIGF0dHJzID0ge307XG4gICAgICAgIGF0dHJzW190aGlzLmlkICsgJy5hYXhpcy5taW4nXSA9IF9taW5zLmE7XG4gICAgICAgIGF0dHJzW190aGlzLmlkICsgJy5iYXhpcy5taW4nXSA9IF9taW5zLmI7XG4gICAgICAgIGF0dHJzW190aGlzLmlkICsgJy5jYXhpcy5taW4nXSA9IF9taW5zLmM7XG4gICAgICAgIHJldHVybiBhdHRycztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjbGlja1pvb21QYW4obnVtQ2xpY2tzLCBldnQpIHtcbiAgICAgICAgdmFyIGNsaWNrTW9kZSA9IGdkLl9mdWxsTGF5b3V0LmNsaWNrbW9kZTtcblxuICAgICAgICByZW1vdmVab29tYm94KGdkKTtcblxuICAgICAgICBpZihudW1DbGlja3MgPT09IDIpIHtcbiAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9kb3VibGVjbGljaycsIG51bGwpO1xuICAgICAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIG1ha2VVcGRhdGUoe2E6IDAsIGI6IDAsIGM6IDB9KSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihjbGlja01vZGUuaW5kZXhPZignc2VsZWN0JykgPiAtMSAmJiBudW1DbGlja3MgPT09IDEpIHtcbiAgICAgICAgICAgIHNlbGVjdE9uQ2xpY2soZXZ0LCBnZCwgW190aGlzLnhheGlzXSwgW190aGlzLnlheGlzXSwgX3RoaXMuaWQsIGRyYWdPcHRpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNsaWNrTW9kZS5pbmRleE9mKCdldmVudCcpID4gLTEpIHtcbiAgICAgICAgICAgIEZ4LmNsaWNrKGdkLCBldnQsIF90aGlzLmlkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHpvb21QcmVwKGUsIHN0YXJ0WCwgc3RhcnRZKSB7XG4gICAgICAgIHZhciBkcmFnQkJveCA9IGRyYWdnZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHgwID0gc3RhcnRYIC0gZHJhZ0JCb3gubGVmdDtcbiAgICAgICAgeTAgPSBzdGFydFkgLSBkcmFnQkJveC50b3A7XG4gICAgICAgIG1pbnMwID0ge1xuICAgICAgICAgICAgYTogX3RoaXMuYWF4aXMucmFuZ2VbMF0sXG4gICAgICAgICAgICBiOiBfdGhpcy5iYXhpcy5yYW5nZVsxXSxcbiAgICAgICAgICAgIGM6IF90aGlzLmNheGlzLnJhbmdlWzFdXG4gICAgICAgIH07XG4gICAgICAgIG1pbnMgPSBtaW5zMDtcbiAgICAgICAgc3BhbjAgPSBfdGhpcy5hYXhpcy5yYW5nZVsxXSAtIG1pbnMwLmE7XG4gICAgICAgIGx1bSA9IHRpbnljb2xvcihfdGhpcy5ncmFwaERpdi5fZnVsbExheW91dFtfdGhpcy5pZF0uYmdjb2xvcikuZ2V0THVtaW5hbmNlKCk7XG4gICAgICAgIHBhdGgwID0gJ00wLCcgKyBfdGhpcy5oICsgJ0wnICsgKF90aGlzLncgLyAyKSArICcsIDBMJyArIF90aGlzLncgKyAnLCcgKyBfdGhpcy5oICsgJ1onO1xuICAgICAgICBkaW1tZWQgPSBmYWxzZTtcblxuICAgICAgICB6YiA9IHpvb21MYXllci5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ3pvb21ib3gnKVxuICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIF90aGlzLngwICsgJywgJyArIF90aGlzLnkwICsgJyknKVxuICAgICAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAnZmlsbCc6IGx1bSA+IDAuMiA/ICdyZ2JhKDAsMCwwLDApJyA6ICdyZ2JhKDI1NSwyNTUsMjU1LDApJyxcbiAgICAgICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogMFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hdHRyKCdkJywgcGF0aDApO1xuXG4gICAgICAgIGNvcm5lcnMgPSB6b29tTGF5ZXIuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgIC5hdHRyKCdjbGFzcycsICd6b29tYm94LWNvcm5lcnMnKVxuICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIF90aGlzLngwICsgJywgJyArIF90aGlzLnkwICsgJyknKVxuICAgICAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICAgICBmaWxsOiBDb2xvci5iYWNrZ3JvdW5kLFxuICAgICAgICAgICAgICAgIHN0cm9rZTogQ29sb3IuZGVmYXVsdExpbmUsXG4gICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IDEsXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5hdHRyKCdkJywgJ00wLDBaJyk7XG5cbiAgICAgICAgY2xlYXJTZWxlY3QoZ2QpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEFGcmFjKHgsIHkpIHsgcmV0dXJuIDEgLSAoeSAvIF90aGlzLmgpOyB9XG4gICAgZnVuY3Rpb24gZ2V0QkZyYWMoeCwgeSkgeyByZXR1cm4gMSAtICgoeCArIChfdGhpcy5oIC0geSkgLyBNYXRoLnNxcnQoMykpIC8gX3RoaXMudyk7IH1cbiAgICBmdW5jdGlvbiBnZXRDRnJhYyh4LCB5KSB7IHJldHVybiAoKHggLSAoX3RoaXMuaCAtIHkpIC8gTWF0aC5zcXJ0KDMpKSAvIF90aGlzLncpOyB9XG5cbiAgICBmdW5jdGlvbiB6b29tTW92ZShkeDAsIGR5MCkge1xuICAgICAgICB2YXIgeDEgPSB4MCArIGR4MDtcbiAgICAgICAgdmFyIHkxID0geTAgKyBkeTA7XG4gICAgICAgIHZhciBhZnJhYyA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGdldEFGcmFjKHgwLCB5MCksIGdldEFGcmFjKHgxLCB5MSkpKTtcbiAgICAgICAgdmFyIGJmcmFjID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgZ2V0QkZyYWMoeDAsIHkwKSwgZ2V0QkZyYWMoeDEsIHkxKSkpO1xuICAgICAgICB2YXIgY2ZyYWMgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBnZXRDRnJhYyh4MCwgeTApLCBnZXRDRnJhYyh4MSwgeTEpKSk7XG4gICAgICAgIHZhciB4TGVmdCA9ICgoYWZyYWMgLyAyKSArIGNmcmFjKSAqIF90aGlzLnc7XG4gICAgICAgIHZhciB4UmlnaHQgPSAoMSAtIChhZnJhYyAvIDIpIC0gYmZyYWMpICogX3RoaXMudztcbiAgICAgICAgdmFyIHhDZW50ZXIgPSAoeExlZnQgKyB4UmlnaHQpIC8gMjtcbiAgICAgICAgdmFyIHhTcGFuID0geFJpZ2h0IC0geExlZnQ7XG4gICAgICAgIHZhciB5Qm90dG9tID0gKDEgLSBhZnJhYykgKiBfdGhpcy5oO1xuICAgICAgICB2YXIgeVRvcCA9IHlCb3R0b20gLSB4U3BhbiAvIHdoUmF0aW87XG5cbiAgICAgICAgaWYoeFNwYW4gPCBjb25zdGFudHMuTUlOWk9PTSkge1xuICAgICAgICAgICAgbWlucyA9IG1pbnMwO1xuICAgICAgICAgICAgemIuYXR0cignZCcsIHBhdGgwKTtcbiAgICAgICAgICAgIGNvcm5lcnMuYXR0cignZCcsICdNMCwwWicpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbWlucyA9IHtcbiAgICAgICAgICAgICAgICBhOiBtaW5zMC5hICsgYWZyYWMgKiBzcGFuMCxcbiAgICAgICAgICAgICAgICBiOiBtaW5zMC5iICsgYmZyYWMgKiBzcGFuMCxcbiAgICAgICAgICAgICAgICBjOiBtaW5zMC5jICsgY2ZyYWMgKiBzcGFuMFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHpiLmF0dHIoJ2QnLCBwYXRoMCArICdNJyArIHhMZWZ0ICsgJywnICsgeUJvdHRvbSArXG4gICAgICAgICAgICAgICAgJ0gnICsgeFJpZ2h0ICsgJ0wnICsgeENlbnRlciArICcsJyArIHlUb3AgK1xuICAgICAgICAgICAgICAgICdMJyArIHhMZWZ0ICsgJywnICsgeUJvdHRvbSArICdaJyk7XG4gICAgICAgICAgICBjb3JuZXJzLmF0dHIoJ2QnLCAnTScgKyB4MCArICcsJyArIHkwICsgU1RBUlRNQVJLRVIgK1xuICAgICAgICAgICAgICAgICdNJyArIHhMZWZ0ICsgJywnICsgeUJvdHRvbSArIEJMUEFUSCArXG4gICAgICAgICAgICAgICAgJ00nICsgeFJpZ2h0ICsgJywnICsgeUJvdHRvbSArIEJSUEFUSCArXG4gICAgICAgICAgICAgICAgJ00nICsgeENlbnRlciArICcsJyArIHlUb3AgKyBUT1BQQVRIKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFkaW1tZWQpIHtcbiAgICAgICAgICAgIHpiLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnZmlsbCcsIGx1bSA+IDAuMiA/ICdyZ2JhKDAsMCwwLDAuNCknIDpcbiAgICAgICAgICAgICAgICAgICAgJ3JnYmEoMjU1LDI1NSwyNTUsMC4zKScpXG4gICAgICAgICAgICAgICAgLmR1cmF0aW9uKDIwMCk7XG4gICAgICAgICAgICBjb3JuZXJzLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDEpXG4gICAgICAgICAgICAgICAgLmR1cmF0aW9uKDIwMCk7XG4gICAgICAgICAgICBkaW1tZWQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3JlbGF5b3V0aW5nJywgbWFrZVVwZGF0ZShtaW5zKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gem9vbURvbmUoKSB7XG4gICAgICAgIHJlbW92ZVpvb21ib3goZ2QpO1xuXG4gICAgICAgIGlmKG1pbnMgPT09IG1pbnMwKSByZXR1cm47XG5cbiAgICAgICAgUmVnaXN0cnkuY2FsbCgnX2d1aVJlbGF5b3V0JywgZ2QsIG1ha2VVcGRhdGUobWlucykpO1xuXG4gICAgICAgIGlmKFNIT1daT09NT1VUVElQICYmIGdkLmRhdGEgJiYgZ2QuX2NvbnRleHQuc2hvd1RpcHMpIHtcbiAgICAgICAgICAgIExpYi5ub3RpZmllcihfKGdkLCAnRG91YmxlLWNsaWNrIHRvIHpvb20gYmFjayBvdXQnKSwgJ2xvbmcnKTtcbiAgICAgICAgICAgIFNIT1daT09NT1VUVElQID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYW5QcmVwKCkge1xuICAgICAgICBtaW5zMCA9IHtcbiAgICAgICAgICAgIGE6IF90aGlzLmFheGlzLnJhbmdlWzBdLFxuICAgICAgICAgICAgYjogX3RoaXMuYmF4aXMucmFuZ2VbMV0sXG4gICAgICAgICAgICBjOiBfdGhpcy5jYXhpcy5yYW5nZVsxXVxuICAgICAgICB9O1xuICAgICAgICBtaW5zID0gbWluczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGxvdERyYWcoZHgsIGR5KSB7XG4gICAgICAgIHZhciBkeFNjYWxlZCA9IGR4IC8gX3RoaXMueGF4aXMuX207XG4gICAgICAgIHZhciBkeVNjYWxlZCA9IGR5IC8gX3RoaXMueWF4aXMuX207XG4gICAgICAgIG1pbnMgPSB7XG4gICAgICAgICAgICBhOiBtaW5zMC5hIC0gZHlTY2FsZWQsXG4gICAgICAgICAgICBiOiBtaW5zMC5iICsgKGR4U2NhbGVkICsgZHlTY2FsZWQpIC8gMixcbiAgICAgICAgICAgIGM6IG1pbnMwLmMgLSAoZHhTY2FsZWQgLSBkeVNjYWxlZCkgLyAyXG4gICAgICAgIH07XG4gICAgICAgIHZhciBtaW5zb3J0ZWQgPSBbbWlucy5hLCBtaW5zLmIsIG1pbnMuY10uc29ydCgpO1xuICAgICAgICB2YXIgbWluaW5kaWNlcyA9IHtcbiAgICAgICAgICAgIGE6IG1pbnNvcnRlZC5pbmRleE9mKG1pbnMuYSksXG4gICAgICAgICAgICBiOiBtaW5zb3J0ZWQuaW5kZXhPZihtaW5zLmIpLFxuICAgICAgICAgICAgYzogbWluc29ydGVkLmluZGV4T2YobWlucy5jKVxuICAgICAgICB9O1xuICAgICAgICBpZihtaW5zb3J0ZWRbMF0gPCAwKSB7XG4gICAgICAgICAgICBpZihtaW5zb3J0ZWRbMV0gKyBtaW5zb3J0ZWRbMF0gLyAyIDwgMCkge1xuICAgICAgICAgICAgICAgIG1pbnNvcnRlZFsyXSArPSBtaW5zb3J0ZWRbMF0gKyBtaW5zb3J0ZWRbMV07XG4gICAgICAgICAgICAgICAgbWluc29ydGVkWzBdID0gbWluc29ydGVkWzFdID0gMDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbWluc29ydGVkWzJdICs9IG1pbnNvcnRlZFswXSAvIDI7XG4gICAgICAgICAgICAgICAgbWluc29ydGVkWzFdICs9IG1pbnNvcnRlZFswXSAvIDI7XG4gICAgICAgICAgICAgICAgbWluc29ydGVkWzBdID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1pbnMgPSB7XG4gICAgICAgICAgICAgICAgYTogbWluc29ydGVkW21pbmluZGljZXMuYV0sXG4gICAgICAgICAgICAgICAgYjogbWluc29ydGVkW21pbmluZGljZXMuYl0sXG4gICAgICAgICAgICAgICAgYzogbWluc29ydGVkW21pbmluZGljZXMuY11cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBkeSA9IChtaW5zMC5hIC0gbWlucy5hKSAqIF90aGlzLnlheGlzLl9tO1xuICAgICAgICAgICAgZHggPSAobWluczAuYyAtIG1pbnMuYyAtIG1pbnMwLmIgKyBtaW5zLmIpICogX3RoaXMueGF4aXMuX207XG4gICAgICAgIH1cblxuICAgICAgICAvLyBtb3ZlIHRoZSBkYXRhICh0cmFuc2xhdGUsIGRvbid0IHJlZHJhdylcbiAgICAgICAgdmFyIHBsb3RUcmFuc2Zvcm0gPSAndHJhbnNsYXRlKCcgKyAoX3RoaXMueDAgKyBkeCkgKyAnLCcgKyAoX3RoaXMueTAgKyBkeSkgKyAnKSc7XG4gICAgICAgIF90aGlzLnBsb3RDb250YWluZXIuc2VsZWN0QWxsKCcuc2NhdHRlcmxheWVyLC5tYXBsYXllcicpXG4gICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgcGxvdFRyYW5zZm9ybSk7XG5cbiAgICAgICAgdmFyIHBsb3RUcmFuc2Zvcm0yID0gJ3RyYW5zbGF0ZSgnICsgLWR4ICsgJywnICsgLWR5ICsgJyknO1xuICAgICAgICBfdGhpcy5jbGlwRGVmUmVsYXRpdmUuc2VsZWN0KCdwYXRoJykuYXR0cigndHJhbnNmb3JtJywgcGxvdFRyYW5zZm9ybTIpO1xuXG4gICAgICAgIC8vIG1vdmUgdGhlIHRpY2tzXG4gICAgICAgIF90aGlzLmFheGlzLnJhbmdlID0gW21pbnMuYSwgX3RoaXMuc3VtIC0gbWlucy5iIC0gbWlucy5jXTtcbiAgICAgICAgX3RoaXMuYmF4aXMucmFuZ2UgPSBbX3RoaXMuc3VtIC0gbWlucy5hIC0gbWlucy5jLCBtaW5zLmJdO1xuICAgICAgICBfdGhpcy5jYXhpcy5yYW5nZSA9IFtfdGhpcy5zdW0gLSBtaW5zLmEgLSBtaW5zLmIsIG1pbnMuY107XG5cbiAgICAgICAgX3RoaXMuZHJhd0F4ZXMoZmFsc2UpO1xuXG4gICAgICAgIGlmKF90aGlzLl9oYXNDbGlwT25BeGlzRmFsc2UpIHtcbiAgICAgICAgICAgIF90aGlzLnBsb3RDb250YWluZXJcbiAgICAgICAgICAgICAgICAuc2VsZWN0KCcuc2NhdHRlcmxheWVyJykuc2VsZWN0QWxsKCcudHJhY2UnKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuaGlkZU91dHNpZGVSYW5nZVBvaW50cywgX3RoaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3JlbGF5b3V0aW5nJywgbWFrZVVwZGF0ZShtaW5zKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhZ0RvbmUoKSB7XG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZWxheW91dCcsIGdkLCBtYWtlVXBkYXRlKG1pbnMpKTtcbiAgICB9XG5cbiAgICAvLyBmaW5hbGx5LCBzZXQgdXAgaG92ZXIgYW5kIGNsaWNrXG4gICAgLy8gdGhlc2UgZXZlbnQgaGFuZGxlcnMgbXVzdCBhbHJlYWR5IGJlIHNldCBiZWZvcmUgZHJhZ0VsZW1lbnQuaW5pdFxuICAgIC8vIHNvIGl0IGNhbiBzdGFzaCB0aGVtIGFuZCBvdmVycmlkZSB0aGVtLlxuICAgIGRyYWdnZXIub25tb3VzZW1vdmUgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgRnguaG92ZXIoZ2QsIGV2dCwgX3RoaXMuaWQpO1xuICAgICAgICBnZC5fZnVsbExheW91dC5fbGFzdGhvdmVyID0gZHJhZ2dlcjtcbiAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX2hvdmVyc3VicGxvdCA9IF90aGlzLmlkO1xuICAgIH07XG5cbiAgICBkcmFnZ2VyLm9ubW91c2VvdXQgPSBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgaWYoZ2QuX2RyYWdnaW5nKSByZXR1cm47XG5cbiAgICAgICAgZHJhZ0VsZW1lbnQudW5ob3ZlcihnZCwgZXZ0KTtcbiAgICB9O1xuXG4gICAgZHJhZ0VsZW1lbnQuaW5pdChkcmFnT3B0aW9ucyk7XG59O1xuXG5mdW5jdGlvbiByZW1vdmVab29tYm94KGdkKSB7XG4gICAgZDMuc2VsZWN0KGdkKVxuICAgICAgICAuc2VsZWN0QWxsKCcuem9vbWJveCwuanMtem9vbWJveC1iYWNrZHJvcCwuanMtem9vbWJveC1tZW51LC56b29tYm94LWNvcm5lcnMnKVxuICAgICAgICAucmVtb3ZlKCk7XG59XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZHJhZ2VsZW1lbnRcIjo2MTEsXCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi4vLi4vY29tcG9uZW50cy90aXRsZXNcIjo2ODEsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL2NhcnRlc2lhbi9jb25zdGFudHNcIjo3NzMsXCIuLi9jYXJ0ZXNpYW4vc2VsZWN0XCI6Nzg0LFwiLi4vY2FydGVzaWFuL3NldF9jb252ZXJ0XCI6Nzg1LFwiLi4vcGxvdHNcIjo4MjgsXCJkM1wiOjE2MyxcInRpbnljb2xvcjJcIjo1Mzd9XSw4NDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTG9nZ2VycyA9IF9kZXJlcV8oJy4vbGliL2xvZ2dlcnMnKTtcbnZhciBub29wID0gX2RlcmVxXygnLi9saWIvbm9vcCcpO1xudmFyIHB1c2hVbmlxdWUgPSBfZGVyZXFfKCcuL2xpYi9wdXNoX3VuaXF1ZScpO1xudmFyIGlzUGxhaW5PYmplY3QgPSBfZGVyZXFfKCcuL2xpYi9pc19wbGFpbl9vYmplY3QnKTtcbnZhciBhZGRTdHlsZVJ1bGUgPSBfZGVyZXFfKCcuL2xpYi9kb20nKS5hZGRTdHlsZVJ1bGU7XG52YXIgRXh0ZW5kTW9kdWxlID0gX2RlcmVxXygnLi9saWIvZXh0ZW5kJyk7XG5cbnZhciBiYXNlUGxvdEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcbnZhciBiYXNlTGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vcGxvdHMvbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSBFeHRlbmRNb2R1bGUuZXh0ZW5kRmxhdDtcbnZhciBleHRlbmREZWVwQWxsID0gRXh0ZW5kTW9kdWxlLmV4dGVuZERlZXBBbGw7XG5cbmV4cG9ydHMubW9kdWxlcyA9IHt9O1xuZXhwb3J0cy5hbGxDYXRlZ29yaWVzID0ge307XG5leHBvcnRzLmFsbFR5cGVzID0gW107XG5leHBvcnRzLnN1YnBsb3RzUmVnaXN0cnkgPSB7fTtcbmV4cG9ydHMudHJhbnNmb3Jtc1JlZ2lzdHJ5ID0ge307XG5leHBvcnRzLmNvbXBvbmVudHNSZWdpc3RyeSA9IHt9O1xuZXhwb3J0cy5sYXlvdXRBcnJheUNvbnRhaW5lcnMgPSBbXTtcbmV4cG9ydHMubGF5b3V0QXJyYXlSZWdleGVzID0gW107XG5leHBvcnRzLnRyYWNlTGF5b3V0QXR0cmlidXRlcyA9IHt9O1xuZXhwb3J0cy5sb2NhbGVSZWdpc3RyeSA9IHt9O1xuZXhwb3J0cy5hcGlNZXRob2RSZWdpc3RyeSA9IHt9O1xuZXhwb3J0cy5jb2xsZWN0YWJsZVN1YnBsb3RUeXBlcyA9IG51bGw7XG5cbi8qKlxuICogVG9wLWxldmVsIHJlZ2lzdGVyIHJvdXRpbmUsIGV4cG9ydGVkIGFzIFBsb3RseS5yZWdpc3RlclxuICpcbiAqIEBwYXJhbSB7b2JqZWN0IGFycmF5IG9yIGFycmF5IG9mIG9iamVjdHN9IF9tb2R1bGVzIDpcbiAqICBtb2R1bGUgb2JqZWN0IG9yIGxpc3Qgb2YgbW9kdWxlIG9iamVjdCB0byByZWdpc3Rlci5cbiAqXG4gKiAgQSB2YWxpZCBgbW9kdWxlVHlwZTogJ3RyYWNlJ2AgbW9kdWxlIGhhcyBmaWVsZHM6XG4gKiAgLSBuYW1lIHtzdHJpbmd9IDogdGhlIHRyYWNlIHR5cGVcbiAqICAtIGNhdGVnb3JpZXMge2FycmF5fSA6IGNhdGVnb3JpZXMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdHJhY2UgdHlwZSxcbiAqICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RlZCB3aXRoIFJlZ2lzdGVyLnRyYWNlSXMoKVxuICogIC0gbWV0YSB7b2JqZWN0fSA6IG1ldGEgaW5mbyAobW9zdGx5IGZvciBwbG90LXNjaGVtYSlcbiAqXG4gKiAgQSB2YWxpZCBgbW9kdWxlVHlwZTogJ2xvY2FsZSdgIG1vZHVsZSBoYXMgZmllbGRzOlxuICogIC0gbmFtZSB7c3RyaW5nfSA6IHRoZSBsb2NhbGUgbmFtZS4gU2hvdWxkIGJlIGEgMi1kaWdpdCBsYW5ndWFnZSBzdHJpbmcgKCdlbicsICdkZScpXG4gKiAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxseSB3aXRoIGEgY291bnRyeS9yZWdpb24gY29kZSAoJ2VuLUdCJywgJ2RlLUNIJykuIElmIGEgY291bnRyeVxuICogICAgICAgICAgICAgICAgICAgIGNvZGUgaXMgdXNlZCBidXQgdGhlIGJhc2UgbGFuZ3VhZ2UgbG9jYWxlIGhhcyBub3QgeWV0IGJlZW4gc3VwcGxpZWQsXG4gKiAgICAgICAgICAgICAgICAgICAgd2Ugd2lsbCB1c2UgdGhpcyBsb2NhbGUgZm9yIHRoZSBiYXNlIGFzIHdlbGwuXG4gKiAgLSBkaWN0aW9uYXJ5IHtvYmplY3R9IDogdGhlIGRpY3Rpb25hcnkgbWFwcGluZyBpbnB1dCBzdHJpbmdzIHRvIGxvY2FsaXplZCBzdHJpbmdzXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXJhbGx5IHRoZSBrZXlzIHNob3VsZCBiZSB0aGUgbGl0ZXJhbCBpbnB1dCBzdHJpbmdzLCBidXRcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICBpZiBkZWZhdWx0IHRyYW5zbGF0aW9ucyBhcmUgcHJvdmlkZWQgeW91IGNhbiB1c2UgYW55IHN0cmluZyBhcyBhIGtleS5cbiAqICAtIGZvcm1hdCB7b2JqZWN0fSA6IGEgYGQzLmxvY2FsZWAgZm9ybWF0IHNwZWNpZmllciBmb3IgdGhpcyBsb2NhbGVcbiAqICAgICAgICAgICAgICAgICAgICAgIGFueSBvbWl0dGVkIGtleXMgd2UnbGwgZmFsbCBiYWNrIG9uIGVuLVVTLlxuICpcbiAqICBBIHZhbGlkIGBtb2R1bGVUeXBlOiAndHJhbnNmb3JtJ2AgbW9kdWxlIGhhcyBmaWVsZHM6XG4gKiAgLSBuYW1lIHtzdHJpbmd9IDogdHJhbnNmb3JtIG5hbWVcbiAqICAtIHRyYW5zZm9ybSB7ZnVuY3Rpb259IDogZGVmYXVsdC1sZXZlbCB0cmFuc2Zvcm0gZnVuY3Rpb25cbiAqICAtIGNhbGNUcmFuc2Zvcm0ge2Z1bmN0aW9ufSA6IGNhbGMtbGV2ZWwgdHJhbnNmb3JtIGZ1bmN0aW9uXG4gKiAgLSBhdHRyaWJ1dGVzIHtvYmplY3R9IDogdHJhbnNmb3JtIGF0dHJpYnV0ZXMgZGVjbGFyYXRpb25zXG4gKiAgLSBzdXBwbHlEZWZhdWx0cyB7ZnVuY3Rpb259IDogYXR0cmlidXRlcyBkZWZhdWx0LXN1cHBseSBmdW5jdGlvblxuICpcbiAqICBBIHZhbGlkIGBtb2R1bGVUeXBlOiAnY29tcG9uZW50J2AgbW9kdWxlIGhhcyBmaWVsZHM6XG4gKiAgLSBuYW1lIHtzdHJpbmd9IDogdGhlIGNvbXBvbmVudCBuYW1lLCB1c2VkIGl0IHdpdGggUmVnaXN0ZXIuZ2V0Q29tcG9uZW50TWV0aG9kKClcbiAqICAgICAgICAgICAgICAgICAgICB0byBlbXBsb3kgY29tcG9uZW50IG1ldGhvZC5cbiAqXG4gKiAgQSB2YWxpZCBgbW9kdWxlVHlwZTogJ2FwaU1ldGhvZCdgIG1vZHVsZSBoYXMgZmllbGRzOlxuICogIC0gbmFtZSB7c3RyaW5nfSA6IHRoZSBhcGkgbWV0aG9kIG5hbWUuXG4gKiAgLSBmbiB7ZnVuY3Rpb259IDogdGhlIGFwaSBtZXRob2QgY2FsbGVkIHdpdGggUmVnaXN0ZXIuY2FsbCgpO1xuICpcbiAqL1xuZXhwb3J0cy5yZWdpc3RlciA9IGZ1bmN0aW9uIHJlZ2lzdGVyKF9tb2R1bGVzKSB7XG4gICAgZXhwb3J0cy5jb2xsZWN0YWJsZVN1YnBsb3RUeXBlcyA9IG51bGw7XG5cbiAgICBpZighX21vZHVsZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBhcmd1bWVudCBwYXNzZWQgdG8gUGxvdGx5LnJlZ2lzdGVyLicpO1xuICAgIH0gZWxzZSBpZihfbW9kdWxlcyAmJiAhQXJyYXkuaXNBcnJheShfbW9kdWxlcykpIHtcbiAgICAgICAgX21vZHVsZXMgPSBbX21vZHVsZXNdO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBfbW9kdWxlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbmV3TW9kdWxlID0gX21vZHVsZXNbaV07XG5cbiAgICAgICAgaWYoIW5ld01vZHVsZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1vZHVsZSB3YXMgYXR0ZW1wdGVkIHRvIGJlIHJlZ2lzdGVyZWQhJyk7XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2gobmV3TW9kdWxlLm1vZHVsZVR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ3RyYWNlJzpcbiAgICAgICAgICAgICAgICByZWdpc3RlclRyYWNlTW9kdWxlKG5ld01vZHVsZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd0cmFuc2Zvcm0nOlxuICAgICAgICAgICAgICAgIHJlZ2lzdGVyVHJhbnNmb3JtTW9kdWxlKG5ld01vZHVsZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdjb21wb25lbnQnOlxuICAgICAgICAgICAgICAgIHJlZ2lzdGVyQ29tcG9uZW50TW9kdWxlKG5ld01vZHVsZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdsb2NhbGUnOlxuICAgICAgICAgICAgICAgIHJlZ2lzdGVyTG9jYWxlKG5ld01vZHVsZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdhcGlNZXRob2QnOlxuICAgICAgICAgICAgICAgIHZhciBuYW1lID0gbmV3TW9kdWxlLm5hbWU7XG4gICAgICAgICAgICAgICAgZXhwb3J0cy5hcGlNZXRob2RSZWdpc3RyeVtuYW1lXSA9IG5ld01vZHVsZS5mbjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1vZHVsZSB3YXMgYXR0ZW1wdGVkIHRvIGJlIHJlZ2lzdGVyZWQhJyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vKipcbiAqIEdldCByZWdpc3RlcmVkIG1vZHVsZSB1c2luZyB0cmFjZSBvYmplY3Qgb3IgdHJhY2UgdHlwZVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fHxzdHJpbmd9IHRyYWNlXG4gKiAgdHJhY2Ugb2JqZWN0IHdpdGggcHJvcCAndHlwZScgb3IgdHJhY2UgdHlwZSBhcyBhIHN0cmluZ1xuICogQHJldHVybiB7b2JqZWN0fVxuICogIG1vZHVsZSBvYmplY3QgY29ycmVzcG9uZGluZyB0byB0cmFjZSB0eXBlXG4gKi9cbmV4cG9ydHMuZ2V0TW9kdWxlID0gZnVuY3Rpb24odHJhY2UpIHtcbiAgICB2YXIgX21vZHVsZSA9IGV4cG9ydHMubW9kdWxlc1tnZXRUcmFjZVR5cGUodHJhY2UpXTtcbiAgICBpZighX21vZHVsZSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiBfbW9kdWxlLl9tb2R1bGU7XG59O1xuXG4vKipcbiAqIERldGVybWluZSBpZiB0aGlzIHRyYWNlIHR5cGUgaXMgaW4gYSBnaXZlbiBjYXRlZ29yeVxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fHxzdHJpbmd9IHRyYWNlVHlwZVxuICogIGEgdHJhY2UgKG9iamVjdCkgb3IgdHJhY2UgdHlwZSAoc3RyaW5nKVxuICogQHBhcmFtIHtzdHJpbmd9IGNhdGVnb3J5XG4gKiAgY2F0ZWdvcnkgaW4gcXVlc3Rpb25cbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbmV4cG9ydHMudHJhY2VJcyA9IGZ1bmN0aW9uKHRyYWNlVHlwZSwgY2F0ZWdvcnkpIHtcbiAgICB0cmFjZVR5cGUgPSBnZXRUcmFjZVR5cGUodHJhY2VUeXBlKTtcblxuICAgIC8vIG9sZCBwbG90Lmx5IHdvcmtzcGFjZSBoYWNrLCBub3RoaW5nIHRvIHNlZSBoZXJlXG4gICAgaWYodHJhY2VUeXBlID09PSAndmFyaW91cycpIHJldHVybiBmYWxzZTtcblxuICAgIHZhciBfbW9kdWxlID0gZXhwb3J0cy5tb2R1bGVzW3RyYWNlVHlwZV07XG5cbiAgICBpZighX21vZHVsZSkge1xuICAgICAgICBpZih0cmFjZVR5cGUgJiYgdHJhY2VUeXBlICE9PSAnYXJlYScpIHtcbiAgICAgICAgICAgIExvZ2dlcnMubG9nKCdVbnJlY29nbml6ZWQgdHJhY2UgdHlwZSAnICsgdHJhY2VUeXBlICsgJy4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIF9tb2R1bGUgPSBleHBvcnRzLm1vZHVsZXNbYmFzZVBsb3RBdHRyaWJ1dGVzLnR5cGUuZGZsdF07XG4gICAgfVxuXG4gICAgcmV0dXJuICEhX21vZHVsZS5jYXRlZ29yaWVzW2NhdGVnb3J5XTtcbn07XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIHRoaXMgdHJhY2UgaGFzIGEgdHJhbnNmb3JtIG9mIHRoZSBnaXZlbiB0eXBlIGFuZCByZXR1cm5cbiAqIGFycmF5IG9mIG1hdGNoaW5nIGluZGljZXMuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGRhdGFcbiAqICBhIHRyYWNlIG9iamVjdCAobWVtYmVyIG9mIGRhdGEgb3IgZnVsbERhdGEpXG4gKiBAcGFyYW0ge3N0cmluZ30gdHlwZVxuICogIHR5cGUgb2YgdHJhY2UgdG8gdGVzdFxuICogQHJldHVybiB7YXJyYXl9XG4gKiAgYXJyYXkgb2YgbWF0Y2hpbmcgaW5kaWNlcy4gSWYgbm9uZSBmb3VuZCwgcmV0dXJucyBbXVxuICovXG5leHBvcnRzLmdldFRyYW5zZm9ybUluZGljZXMgPSBmdW5jdGlvbihkYXRhLCB0eXBlKSB7XG4gICAgdmFyIGluZGljZXMgPSBbXTtcbiAgICB2YXIgdHJhbnNmb3JtcyA9IGRhdGEudHJhbnNmb3JtcyB8fCBbXTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdHJhbnNmb3Jtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZih0cmFuc2Zvcm1zW2ldLnR5cGUgPT09IHR5cGUpIHtcbiAgICAgICAgICAgIGluZGljZXMucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaW5kaWNlcztcbn07XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIHRoaXMgdHJhY2UgaGFzIGEgdHJhbnNmb3JtIG9mIHRoZSBnaXZlbiB0eXBlXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGRhdGFcbiAqICBhIHRyYWNlIG9iamVjdCAobWVtYmVyIG9mIGRhdGEgb3IgZnVsbERhdGEpXG4gKiBAcGFyYW0ge3N0cmluZ30gdHlwZVxuICogIHR5cGUgb2YgdHJhY2UgdG8gdGVzdFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0cy5oYXNUcmFuc2Zvcm0gPSBmdW5jdGlvbihkYXRhLCB0eXBlKSB7XG4gICAgdmFyIHRyYW5zZm9ybXMgPSBkYXRhLnRyYW5zZm9ybXMgfHwgW107XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYW5zZm9ybXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYodHJhbnNmb3Jtc1tpXS50eXBlID09PSB0eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIGNvbXBvbmVudCBtb2R1bGUgbWV0aG9kLiBGYWxscyBiYWNrIG9uIG5vb3AgaWYgZWl0aGVyIHRoZVxuICogbW9kdWxlIG9yIHRoZSBtZXRob2QgaXMgbWlzc2luZywgc28gdGhlIHJlc3VsdCBjYW4gYWx3YXlzIGJlIHNhZmVseSBjYWxsZWRcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogIG5hbWUgb2YgY29tcG9uZW50IChhcyBkZWNsYXJlZCBpbiBjb21wb25lbnQgbW9kdWxlKVxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZFxuICogIG5hbWUgb2YgY29tcG9uZW50IG1vZHVsZSBtZXRob2RcbiAqIEByZXR1cm4ge2Z1bmN0aW9ufVxuICovXG5leHBvcnRzLmdldENvbXBvbmVudE1ldGhvZCA9IGZ1bmN0aW9uKG5hbWUsIG1ldGhvZCkge1xuICAgIHZhciBfbW9kdWxlID0gZXhwb3J0cy5jb21wb25lbnRzUmVnaXN0cnlbbmFtZV07XG5cbiAgICBpZighX21vZHVsZSkgcmV0dXJuIG5vb3A7XG4gICAgcmV0dXJuIF9tb2R1bGVbbWV0aG9kXSB8fCBub29wO1xufTtcblxuLyoqXG4gKiBDYWxsIHJlZ2lzdGVyZWQgYXBpIG1ldGhvZC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSA6IGFwaSBtZXRob2QgbmFtZVxuICogQHBhcmFtIHsuLi5hcnJheX0gYXJncyA6IGFyZ3VtZW50cyBwYXNzZWQgdG8gYXBpIG1ldGhvZFxuICogQHJldHVybiB7YW55fSA6IHJldHVybnMgYXBpIG1ldGhvZCBvdXRwdXRcbiAqL1xuZXhwb3J0cy5jYWxsID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG5hbWUgPSBhcmd1bWVudHNbMF07XG4gICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgcmV0dXJuIGV4cG9ydHMuYXBpTWV0aG9kUmVnaXN0cnlbbmFtZV0uYXBwbHkobnVsbCwgYXJncyk7XG59O1xuXG5mdW5jdGlvbiByZWdpc3RlclRyYWNlTW9kdWxlKF9tb2R1bGUpIHtcbiAgICB2YXIgdGhpc1R5cGUgPSBfbW9kdWxlLm5hbWU7XG4gICAgdmFyIGNhdGVnb3JpZXNJbiA9IF9tb2R1bGUuY2F0ZWdvcmllcztcbiAgICB2YXIgbWV0YSA9IF9tb2R1bGUubWV0YTtcblxuICAgIGlmKGV4cG9ydHMubW9kdWxlc1t0aGlzVHlwZV0pIHtcbiAgICAgICAgTG9nZ2Vycy5sb2coJ1R5cGUgJyArIHRoaXNUeXBlICsgJyBhbHJlYWR5IHJlZ2lzdGVyZWQnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmKCFleHBvcnRzLnN1YnBsb3RzUmVnaXN0cnlbX21vZHVsZS5iYXNlUGxvdE1vZHVsZS5uYW1lXSkge1xuICAgICAgICByZWdpc3RlclN1YnBsb3QoX21vZHVsZS5iYXNlUGxvdE1vZHVsZSk7XG4gICAgfVxuXG4gICAgdmFyIGNhdGVnb3J5T2JqID0ge307XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhdGVnb3JpZXNJbi5sZW5ndGg7IGkrKykge1xuICAgICAgICBjYXRlZ29yeU9ialtjYXRlZ29yaWVzSW5baV1dID0gdHJ1ZTtcbiAgICAgICAgZXhwb3J0cy5hbGxDYXRlZ29yaWVzW2NhdGVnb3JpZXNJbltpXV0gPSB0cnVlO1xuICAgIH1cblxuICAgIGV4cG9ydHMubW9kdWxlc1t0aGlzVHlwZV0gPSB7XG4gICAgICAgIF9tb2R1bGU6IF9tb2R1bGUsXG4gICAgICAgIGNhdGVnb3JpZXM6IGNhdGVnb3J5T2JqXG4gICAgfTtcblxuICAgIGlmKG1ldGEgJiYgT2JqZWN0LmtleXMobWV0YSkubGVuZ3RoKSB7XG4gICAgICAgIGV4cG9ydHMubW9kdWxlc1t0aGlzVHlwZV0ubWV0YSA9IG1ldGE7XG4gICAgfVxuXG4gICAgZXhwb3J0cy5hbGxUeXBlcy5wdXNoKHRoaXNUeXBlKTtcblxuICAgIGZvcih2YXIgY29tcG9uZW50TmFtZSBpbiBleHBvcnRzLmNvbXBvbmVudHNSZWdpc3RyeSkge1xuICAgICAgICBtZXJnZUNvbXBvbmVudEF0dHJzVG9UcmFjZShjb21wb25lbnROYW1lLCB0aGlzVHlwZSk7XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBDb2xsZWN0IGFsbCB0cmFjZSBsYXlvdXQgYXR0cmlidXRlcyBpbiBvbmUgcGxhY2UgZm9yIGVhc2llciBsb29rdXAgbGF0ZXJcbiAgICAgKiBidXQgZG9uJ3QgbWVyZ2UgdGhlbSBpbnRvIHRoZSBiYXNlIHNjaGVtYSBhcyBpdCB3b3VsZCBjb25mdXNlIHRoZSBkb2NzXG4gICAgICogKGF0IGxlYXN0IGFmdGVyIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvZG9jdW1lbnRhdGlvbi9pc3N1ZXMvMjAyIGdldHMgZG9uZSEpXG4gICAgICovXG4gICAgaWYoX21vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzKSB7XG4gICAgICAgIGV4dGVuZEZsYXQoZXhwb3J0cy50cmFjZUxheW91dEF0dHJpYnV0ZXMsIF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcyk7XG4gICAgfVxuXG4gICAgdmFyIGJhc2VQbG90TW9kdWxlID0gX21vZHVsZS5iYXNlUGxvdE1vZHVsZTtcbiAgICB2YXIgYnBtTmFtZSA9IGJhc2VQbG90TW9kdWxlLm5hbWU7XG5cbiAgICAvLyBhZGQgbWFwYm94LWdsIENTUyBoZXJlIHRvIGF2b2lkIGNvbnNvbGUgd2FybmluZyBvbiBpbnN0YW50aWF0aW9uXG4gICAgaWYoYnBtTmFtZSA9PT0gJ21hcGJveCcpIHtcbiAgICAgICAgdmFyIHN0eWxlUnVsZXMgPSBiYXNlUGxvdE1vZHVsZS5jb25zdGFudHMuc3R5bGVSdWxlcztcbiAgICAgICAgZm9yKHZhciBrIGluIHN0eWxlUnVsZXMpIHtcbiAgICAgICAgICAgIGFkZFN0eWxlUnVsZSgnLmpzLXBsb3RseS1wbG90IC5wbG90bHkgLm1hcGJveGdsLScgKyBrLCBzdHlsZVJ1bGVzW2tdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGlmIGBwbG90bHktZ2VvLWFzc2V0cy5qc2AgaXMgbm90IGluY2x1ZGVkLFxuICAgIC8vIGFkZCBgUGxvdGx5R2VvQXNzZXRzYCBnbG9iYWwgdG8gc3Rhc2ggcmVmZXJlbmNlcyB0byBhbGwgZmV0Y2hlZFxuICAgIC8vIHRvcG9qc29uIC8gZ2VvanNvbiBkYXRhXG4gICAgaWYoKGJwbU5hbWUgPT09ICdnZW8nIHx8IGJwbU5hbWUgPT09ICdtYXBib3gnKSAmJlxuICAgICAgICAodHlwZW9mIHdpbmRvdyAhPT0gdW5kZWZpbmVkICYmIHdpbmRvdy5QbG90bHlHZW9Bc3NldHMgPT09IHVuZGVmaW5lZClcbiAgICApIHtcbiAgICAgICAgd2luZG93LlBsb3RseUdlb0Fzc2V0cyA9IHt0b3BvanNvbjoge319O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVnaXN0ZXJTdWJwbG90KF9tb2R1bGUpIHtcbiAgICB2YXIgcGxvdFR5cGUgPSBfbW9kdWxlLm5hbWU7XG5cbiAgICBpZihleHBvcnRzLnN1YnBsb3RzUmVnaXN0cnlbcGxvdFR5cGVdKSB7XG4gICAgICAgIExvZ2dlcnMubG9nKCdQbG90IHR5cGUgJyArIHBsb3RUeXBlICsgJyBhbHJlYWR5IHJlZ2lzdGVyZWQuJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyByZWxheW91dCBhcnJheSBoYW5kbGluZyB3aWxsIGxvb2sgZm9yIGNvbXBvbmVudCBtb2R1bGUgbWV0aG9kcyB3aXRoIHRoaXNcbiAgICAvLyBuYW1lIGFuZCB3b24ndCBmaW5kIHRoZW0gYmVjYXVzZSB0aGlzIGlzIGEgc3VicGxvdCBtb2R1bGUuLi4gYnV0IHRoYXRcbiAgICAvLyBzaG91bGQgYmUgZmluZSwgaXQgd2lsbCBqdXN0IGZhbGwgYmFjayBvbiByZWRyYXdpbmcgdGhlIHBsb3QuXG4gICAgZmluZEFycmF5UmVnZXhwcyhfbW9kdWxlKTtcblxuICAgIC8vIG5vdCBzdXJlIHdoYXQncyBiZXN0IGZvciB0aGUgJ2NhcnRlc2lhbicgdHlwZSBhdCB0aGlzIHBvaW50XG4gICAgZXhwb3J0cy5zdWJwbG90c1JlZ2lzdHJ5W3Bsb3RUeXBlXSA9IF9tb2R1bGU7XG5cbiAgICBmb3IodmFyIGNvbXBvbmVudE5hbWUgaW4gZXhwb3J0cy5jb21wb25lbnRzUmVnaXN0cnkpIHtcbiAgICAgICAgbWVyZ2VDb21wb25lbnRBdHRyc1RvU3VicGxvdChjb21wb25lbnROYW1lLCBfbW9kdWxlLm5hbWUpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVnaXN0ZXJDb21wb25lbnRNb2R1bGUoX21vZHVsZSkge1xuICAgIGlmKHR5cGVvZiBfbW9kdWxlLm5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ29tcG9uZW50IG1vZHVsZSAqbmFtZSogbXVzdCBiZSBhIHN0cmluZy4nKTtcbiAgICB9XG5cbiAgICB2YXIgbmFtZSA9IF9tb2R1bGUubmFtZTtcbiAgICBleHBvcnRzLmNvbXBvbmVudHNSZWdpc3RyeVtuYW1lXSA9IF9tb2R1bGU7XG5cbiAgICBpZihfbW9kdWxlLmxheW91dEF0dHJpYnV0ZXMpIHtcbiAgICAgICAgaWYoX21vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzLl9pc0xpbmtlZFRvQXJyYXkpIHtcbiAgICAgICAgICAgIHB1c2hVbmlxdWUoZXhwb3J0cy5sYXlvdXRBcnJheUNvbnRhaW5lcnMsIG5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmRBcnJheVJlZ2V4cHMoX21vZHVsZSk7XG4gICAgfVxuXG4gICAgZm9yKHZhciB0cmFjZVR5cGUgaW4gZXhwb3J0cy5tb2R1bGVzKSB7XG4gICAgICAgIG1lcmdlQ29tcG9uZW50QXR0cnNUb1RyYWNlKG5hbWUsIHRyYWNlVHlwZSk7XG4gICAgfVxuXG4gICAgZm9yKHZhciBzdWJwbG90TmFtZSBpbiBleHBvcnRzLnN1YnBsb3RzUmVnaXN0cnkpIHtcbiAgICAgICAgbWVyZ2VDb21wb25lbnRBdHRyc1RvU3VicGxvdChuYW1lLCBzdWJwbG90TmFtZSk7XG4gICAgfVxuXG4gICAgZm9yKHZhciB0cmFuc2Zvcm1UeXBlIGluIGV4cG9ydHMudHJhbnNmb3Jtc1JlZ2lzdHJ5KSB7XG4gICAgICAgIG1lcmdlQ29tcG9uZW50QXR0cnNUb1RyYW5zZm9ybShuYW1lLCB0cmFuc2Zvcm1UeXBlKTtcbiAgICB9XG5cbiAgICBpZihfbW9kdWxlLnNjaGVtYSAmJiBfbW9kdWxlLnNjaGVtYS5sYXlvdXQpIHtcbiAgICAgICAgZXh0ZW5kRGVlcEFsbChiYXNlTGF5b3V0QXR0cmlidXRlcywgX21vZHVsZS5zY2hlbWEubGF5b3V0KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlZ2lzdGVyVHJhbnNmb3JtTW9kdWxlKF9tb2R1bGUpIHtcbiAgICBpZih0eXBlb2YgX21vZHVsZS5uYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyYW5zZm9ybSBtb2R1bGUgKm5hbWUqIG11c3QgYmUgYSBzdHJpbmcuJyk7XG4gICAgfVxuXG4gICAgdmFyIHByZWZpeCA9ICdUcmFuc2Zvcm0gbW9kdWxlICcgKyBfbW9kdWxlLm5hbWU7XG4gICAgdmFyIGhhc1RyYW5zZm9ybSA9IHR5cGVvZiBfbW9kdWxlLnRyYW5zZm9ybSA9PT0gJ2Z1bmN0aW9uJztcbiAgICB2YXIgaGFzQ2FsY1RyYW5zZm9ybSA9IHR5cGVvZiBfbW9kdWxlLmNhbGNUcmFuc2Zvcm0gPT09ICdmdW5jdGlvbic7XG5cbiAgICBpZighaGFzVHJhbnNmb3JtICYmICFoYXNDYWxjVHJhbnNmb3JtKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihwcmVmaXggKyAnIGlzIG1pc3NpbmcgYSAqdHJhbnNmb3JtKiBvciAqY2FsY1RyYW5zZm9ybSogbWV0aG9kLicpO1xuICAgIH1cbiAgICBpZihoYXNUcmFuc2Zvcm0gJiYgaGFzQ2FsY1RyYW5zZm9ybSkge1xuICAgICAgICBMb2dnZXJzLmxvZyhbXG4gICAgICAgICAgICBwcmVmaXggKyAnIGhhcyBib3RoIGEgKnRyYW5zZm9ybSogYW5kICpjYWxjVHJhbnNmb3JtKiBtZXRob2RzLicsXG4gICAgICAgICAgICAnUGxlYXNlIG5vdGUgdGhhdCBhbGwgKnRyYW5zZm9ybSogbWV0aG9kcyBhcmUgZXhlY3V0ZWQnLFxuICAgICAgICAgICAgJ2JlZm9yZSBhbGwgKmNhbGNUcmFuc2Zvcm0qIG1ldGhvZHMuJ1xuICAgICAgICBdLmpvaW4oJyAnKSk7XG4gICAgfVxuICAgIGlmKCFpc1BsYWluT2JqZWN0KF9tb2R1bGUuYXR0cmlidXRlcykpIHtcbiAgICAgICAgTG9nZ2Vycy5sb2cocHJlZml4ICsgJyByZWdpc3RlcmVkIHdpdGhvdXQgYW4gKmF0dHJpYnV0ZXMqIG9iamVjdC4nKTtcbiAgICB9XG4gICAgaWYodHlwZW9mIF9tb2R1bGUuc3VwcGx5RGVmYXVsdHMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgTG9nZ2Vycy5sb2cocHJlZml4ICsgJyByZWdpc3RlcmVkIHdpdGhvdXQgYSAqc3VwcGx5RGVmYXVsdHMqIG1ldGhvZC4nKTtcbiAgICB9XG5cbiAgICBleHBvcnRzLnRyYW5zZm9ybXNSZWdpc3RyeVtfbW9kdWxlLm5hbWVdID0gX21vZHVsZTtcblxuICAgIGZvcih2YXIgY29tcG9uZW50TmFtZSBpbiBleHBvcnRzLmNvbXBvbmVudHNSZWdpc3RyeSkge1xuICAgICAgICBtZXJnZUNvbXBvbmVudEF0dHJzVG9UcmFuc2Zvcm0oY29tcG9uZW50TmFtZSwgX21vZHVsZS5uYW1lKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlZ2lzdGVyTG9jYWxlKF9tb2R1bGUpIHtcbiAgICB2YXIgbG9jYWxlID0gX21vZHVsZS5uYW1lO1xuICAgIHZhciBiYXNlTG9jYWxlID0gbG9jYWxlLnNwbGl0KCctJylbMF07XG5cbiAgICB2YXIgbmV3RGljdCA9IF9tb2R1bGUuZGljdGlvbmFyeTtcbiAgICB2YXIgbmV3Rm9ybWF0ID0gX21vZHVsZS5mb3JtYXQ7XG4gICAgdmFyIGhhc0RpY3QgPSBuZXdEaWN0ICYmIE9iamVjdC5rZXlzKG5ld0RpY3QpLmxlbmd0aDtcbiAgICB2YXIgaGFzRm9ybWF0ID0gbmV3Rm9ybWF0ICYmIE9iamVjdC5rZXlzKG5ld0Zvcm1hdCkubGVuZ3RoO1xuXG4gICAgdmFyIGxvY2FsZXMgPSBleHBvcnRzLmxvY2FsZVJlZ2lzdHJ5O1xuXG4gICAgdmFyIGxvY2FsZU9iaiA9IGxvY2FsZXNbbG9jYWxlXTtcbiAgICBpZighbG9jYWxlT2JqKSBsb2NhbGVzW2xvY2FsZV0gPSBsb2NhbGVPYmogPSB7fTtcblxuICAgIC8vIFNob3VsZCB3ZSB1c2UgdGhpcyBkaWN0IGZvciB0aGUgYmFzZSBsb2NhbGU/XG4gICAgLy8gSW4gY2FzZSB3ZSdyZSBvdmVyd3JpdGluZyBhIHByZXZpb3VzIGRpY3QgZm9yIHRoaXMgbG9jYWxlLCBjaGVja1xuICAgIC8vIHdoZXRoZXIgdGhlIGJhc2UgbWF0Y2hlcyB0aGUgZnVsbCBsb2NhbGUgZGljdCBub3cuIElmIHdlJ3JlIG5vdFxuICAgIC8vIG92ZXJ3cml0aW5nLCBsb2NhbGVzW2xvY2FsZV0gaXMgdW5kZWZpbmVkIHNvIHRoaXMganVzdCBjaGVja3MgaWZcbiAgICAvLyBiYXNlTG9jYWxlIGFscmVhZHkgaGFkIGEgZGljdCBvciBub3QuXG4gICAgLy8gU2FtZSBsb2dpYyBmb3IgZGF0ZUZvcm1hdHNcbiAgICBpZihiYXNlTG9jYWxlICE9PSBsb2NhbGUpIHtcbiAgICAgICAgdmFyIGJhc2VMb2NhbGVPYmogPSBsb2NhbGVzW2Jhc2VMb2NhbGVdO1xuICAgICAgICBpZighYmFzZUxvY2FsZU9iaikgbG9jYWxlc1tiYXNlTG9jYWxlXSA9IGJhc2VMb2NhbGVPYmogPSB7fTtcblxuICAgICAgICBpZihoYXNEaWN0ICYmIGJhc2VMb2NhbGVPYmouZGljdGlvbmFyeSA9PT0gbG9jYWxlT2JqLmRpY3Rpb25hcnkpIHtcbiAgICAgICAgICAgIGJhc2VMb2NhbGVPYmouZGljdGlvbmFyeSA9IG5ld0RpY3Q7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaGFzRm9ybWF0ICYmIGJhc2VMb2NhbGVPYmouZm9ybWF0ID09PSBsb2NhbGVPYmouZm9ybWF0KSB7XG4gICAgICAgICAgICBiYXNlTG9jYWxlT2JqLmZvcm1hdCA9IG5ld0Zvcm1hdDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGhhc0RpY3QpIGxvY2FsZU9iai5kaWN0aW9uYXJ5ID0gbmV3RGljdDtcbiAgICBpZihoYXNGb3JtYXQpIGxvY2FsZU9iai5mb3JtYXQgPSBuZXdGb3JtYXQ7XG59XG5cbmZ1bmN0aW9uIGZpbmRBcnJheVJlZ2V4cHMoX21vZHVsZSkge1xuICAgIGlmKF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcykge1xuICAgICAgICB2YXIgYXJyYXlBdHRyUmVnZXhwcyA9IF9tb2R1bGUubGF5b3V0QXR0cmlidXRlcy5fYXJyYXlBdHRyUmVnZXhwcztcbiAgICAgICAgaWYoYXJyYXlBdHRyUmVnZXhwcykge1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGFycmF5QXR0clJlZ2V4cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwdXNoVW5pcXVlKGV4cG9ydHMubGF5b3V0QXJyYXlSZWdleGVzLCBhcnJheUF0dHJSZWdleHBzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gbWVyZ2VDb21wb25lbnRBdHRyc1RvVHJhY2UoY29tcG9uZW50TmFtZSwgdHJhY2VUeXBlKSB7XG4gICAgdmFyIGNvbXBvbmVudFNjaGVtYSA9IGV4cG9ydHMuY29tcG9uZW50c1JlZ2lzdHJ5W2NvbXBvbmVudE5hbWVdLnNjaGVtYTtcbiAgICBpZighY29tcG9uZW50U2NoZW1hIHx8ICFjb21wb25lbnRTY2hlbWEudHJhY2VzKSByZXR1cm47XG5cbiAgICB2YXIgdHJhY2VBdHRycyA9IGNvbXBvbmVudFNjaGVtYS50cmFjZXNbdHJhY2VUeXBlXTtcbiAgICBpZih0cmFjZUF0dHJzKSB7XG4gICAgICAgIGV4dGVuZERlZXBBbGwoZXhwb3J0cy5tb2R1bGVzW3RyYWNlVHlwZV0uX21vZHVsZS5hdHRyaWJ1dGVzLCB0cmFjZUF0dHJzKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIG1lcmdlQ29tcG9uZW50QXR0cnNUb1RyYW5zZm9ybShjb21wb25lbnROYW1lLCB0cmFuc2Zvcm1UeXBlKSB7XG4gICAgdmFyIGNvbXBvbmVudFNjaGVtYSA9IGV4cG9ydHMuY29tcG9uZW50c1JlZ2lzdHJ5W2NvbXBvbmVudE5hbWVdLnNjaGVtYTtcbiAgICBpZighY29tcG9uZW50U2NoZW1hIHx8ICFjb21wb25lbnRTY2hlbWEudHJhbnNmb3JtcykgcmV0dXJuO1xuXG4gICAgdmFyIHRyYW5zZm9ybUF0dHJzID0gY29tcG9uZW50U2NoZW1hLnRyYW5zZm9ybXNbdHJhbnNmb3JtVHlwZV07XG4gICAgaWYodHJhbnNmb3JtQXR0cnMpIHtcbiAgICAgICAgZXh0ZW5kRGVlcEFsbChleHBvcnRzLnRyYW5zZm9ybXNSZWdpc3RyeVt0cmFuc2Zvcm1UeXBlXS5hdHRyaWJ1dGVzLCB0cmFuc2Zvcm1BdHRycyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBtZXJnZUNvbXBvbmVudEF0dHJzVG9TdWJwbG90KGNvbXBvbmVudE5hbWUsIHN1YnBsb3ROYW1lKSB7XG4gICAgdmFyIGNvbXBvbmVudFNjaGVtYSA9IGV4cG9ydHMuY29tcG9uZW50c1JlZ2lzdHJ5W2NvbXBvbmVudE5hbWVdLnNjaGVtYTtcbiAgICBpZighY29tcG9uZW50U2NoZW1hIHx8ICFjb21wb25lbnRTY2hlbWEuc3VicGxvdHMpIHJldHVybjtcblxuICAgIHZhciBzdWJwbG90TW9kdWxlID0gZXhwb3J0cy5zdWJwbG90c1JlZ2lzdHJ5W3N1YnBsb3ROYW1lXTtcbiAgICB2YXIgc3VicGxvdEF0dHJzID0gc3VicGxvdE1vZHVsZS5sYXlvdXRBdHRyaWJ1dGVzO1xuICAgIHZhciBzdWJwbG90QXR0ciA9IHN1YnBsb3RNb2R1bGUuYXR0ciA9PT0gJ3N1YnBsb3QnID8gc3VicGxvdE1vZHVsZS5uYW1lIDogc3VicGxvdE1vZHVsZS5hdHRyO1xuICAgIGlmKEFycmF5LmlzQXJyYXkoc3VicGxvdEF0dHIpKSBzdWJwbG90QXR0ciA9IHN1YnBsb3RBdHRyWzBdO1xuXG4gICAgdmFyIGNvbXBvbmVudExheW91dEF0dHJzID0gY29tcG9uZW50U2NoZW1hLnN1YnBsb3RzW3N1YnBsb3RBdHRyXTtcbiAgICBpZihzdWJwbG90QXR0cnMgJiYgY29tcG9uZW50TGF5b3V0QXR0cnMpIHtcbiAgICAgICAgZXh0ZW5kRGVlcEFsbChzdWJwbG90QXR0cnMsIGNvbXBvbmVudExheW91dEF0dHJzKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldFRyYWNlVHlwZSh0cmFjZVR5cGUpIHtcbiAgICBpZih0eXBlb2YgdHJhY2VUeXBlID09PSAnb2JqZWN0JykgdHJhY2VUeXBlID0gdHJhY2VUeXBlLnR5cGU7XG4gICAgcmV0dXJuIHRyYWNlVHlwZTtcbn1cblxufSx7XCIuL2xpYi9kb21cIjo3MDgsXCIuL2xpYi9leHRlbmRcIjo3MTAsXCIuL2xpYi9pc19wbGFpbl9vYmplY3RcIjo3MjAsXCIuL2xpYi9sb2dnZXJzXCI6NzIzLFwiLi9saWIvbm9vcFwiOjcyOCxcIi4vbGliL3B1c2hfdW5pcXVlXCI6NzMzLFwiLi9wbG90cy9hdHRyaWJ1dGVzXCI6NzY0LFwiLi9wbG90cy9sYXlvdXRfYXR0cmlidXRlc1wiOjgxOX1dLDg0ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gTGliLmV4dGVuZEZsYXQ7XG52YXIgZXh0ZW5kRGVlcCA9IExpYi5leHRlbmREZWVwO1xuXG4vLyBQdXQgZGVmYXVsdCBwbG90VGlsZSBsYXlvdXRzIGhlcmVcbmZ1bmN0aW9uIGNsb25lTGF5b3V0T3ZlcnJpZGUodGlsZUNsYXNzKSB7XG4gICAgdmFyIG92ZXJyaWRlO1xuXG4gICAgc3dpdGNoKHRpbGVDbGFzcykge1xuICAgICAgICBjYXNlICd0aGVtZXNfX3RodW1iJzpcbiAgICAgICAgICAgIG92ZXJyaWRlID0ge1xuICAgICAgICAgICAgICAgIGF1dG9zaXplOiB0cnVlLFxuICAgICAgICAgICAgICAgIHdpZHRoOiAxNTAsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiAxNTAsXG4gICAgICAgICAgICAgICAgdGl0bGU6IHt0ZXh0OiAnJ30sXG4gICAgICAgICAgICAgICAgc2hvd2xlZ2VuZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgbWFyZ2luOiB7bDogNSwgcjogNSwgdDogNSwgYjogNSwgcGFkOiAwfSxcbiAgICAgICAgICAgICAgICBhbm5vdGF0aW9uczogW11cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlICd0aHVtYm5haWwnOlxuICAgICAgICAgICAgb3ZlcnJpZGUgPSB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IHt0ZXh0OiAnJ30sXG4gICAgICAgICAgICAgICAgaGlkZXNvdXJjZXM6IHRydWUsXG4gICAgICAgICAgICAgICAgc2hvd2xlZ2VuZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgYm9yZGVyd2lkdGg6IDAsXG4gICAgICAgICAgICAgICAgYm9yZGVyY29sb3I6ICcnLFxuICAgICAgICAgICAgICAgIG1hcmdpbjoge2w6IDEsIHI6IDEsIHQ6IDEsIGI6IDEsIHBhZDogMH0sXG4gICAgICAgICAgICAgICAgYW5ub3RhdGlvbnM6IFtdXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIG92ZXJyaWRlID0ge307XG4gICAgfVxuXG5cbiAgICByZXR1cm4gb3ZlcnJpZGU7XG59XG5cbmZ1bmN0aW9uIGtleUlzQXhpcyhrZXlOYW1lKSB7XG4gICAgdmFyIHR5cGVzID0gWyd4YXhpcycsICd5YXhpcycsICd6YXhpcyddO1xuICAgIHJldHVybiAodHlwZXMuaW5kZXhPZihrZXlOYW1lLnNsaWNlKDAsIDUpKSA+IC0xKTtcbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNsb25lUGxvdChncmFwaE9iaiwgb3B0aW9ucykge1xuICAgIC8vIFBvbGFyIHBsb3QgY29tcGF0aWJpbGl0eVxuICAgIGlmKGdyYXBoT2JqLmZyYW1ld29yayAmJiBncmFwaE9iai5mcmFtZXdvcmsuaXNQb2xhcikge1xuICAgICAgICBncmFwaE9iaiA9IGdyYXBoT2JqLmZyYW1ld29yay5nZXRDb25maWcoKTtcbiAgICB9XG5cbiAgICB2YXIgaTtcbiAgICB2YXIgb2xkRGF0YSA9IGdyYXBoT2JqLmRhdGE7XG4gICAgdmFyIG9sZExheW91dCA9IGdyYXBoT2JqLmxheW91dDtcbiAgICB2YXIgbmV3RGF0YSA9IGV4dGVuZERlZXAoW10sIG9sZERhdGEpO1xuICAgIHZhciBuZXdMYXlvdXQgPSBleHRlbmREZWVwKHt9LCBvbGRMYXlvdXQsIGNsb25lTGF5b3V0T3ZlcnJpZGUob3B0aW9ucy50aWxlQ2xhc3MpKTtcbiAgICB2YXIgY29udGV4dCA9IGdyYXBoT2JqLl9jb250ZXh0IHx8IHt9O1xuXG4gICAgaWYob3B0aW9ucy53aWR0aCkgbmV3TGF5b3V0LndpZHRoID0gb3B0aW9ucy53aWR0aDtcbiAgICBpZihvcHRpb25zLmhlaWdodCkgbmV3TGF5b3V0LmhlaWdodCA9IG9wdGlvbnMuaGVpZ2h0O1xuXG4gICAgaWYob3B0aW9ucy50aWxlQ2xhc3MgPT09ICd0aHVtYm5haWwnIHx8IG9wdGlvbnMudGlsZUNsYXNzID09PSAndGhlbWVzX190aHVtYicpIHtcbiAgICAgICAgLy8ga2lsbCBhbm5vdGF0aW9uc1xuICAgICAgICBuZXdMYXlvdXQuYW5ub3RhdGlvbnMgPSBbXTtcbiAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhuZXdMYXlvdXQpO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGtleUlzQXhpcyhrZXlzW2ldKSkge1xuICAgICAgICAgICAgICAgIG5ld0xheW91dFtrZXlzW2ldXS50aXRsZSA9IHt0ZXh0OiAnJ307XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBraWxsIGNvbG9yYmFyIGFuZCBwaWUgbGFiZWxzXG4gICAgICAgIGZvcihpID0gMDsgaSA8IG5ld0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IG5ld0RhdGFbaV07XG4gICAgICAgICAgICB0cmFjZS5zaG93c2NhbGUgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmKHRyYWNlLm1hcmtlcikgdHJhY2UubWFya2VyLnNob3dzY2FsZSA9IGZhbHNlO1xuICAgICAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJ3BpZS1saWtlJykpIHRyYWNlLnRleHRwb3NpdGlvbiA9ICdub25lJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKEFycmF5LmlzQXJyYXkob3B0aW9ucy5hbm5vdGF0aW9ucykpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgb3B0aW9ucy5hbm5vdGF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbmV3TGF5b3V0LmFubm90YXRpb25zLnB1c2gob3B0aW9ucy5hbm5vdGF0aW9uc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUT0RPOiBkb2VzIHRoaXMgc2NlbmUgbW9kaWZpY2F0aW9uIHJlYWxseSBiZWxvbmcgaGVyZT9cbiAgICAvLyBJZiB3ZSBzdGlsbCBuZWVkIGl0LCBjYW4gaXQgbW92ZSBpbnRvIHRoZSBnbDNkIG1vZHVsZT9cbiAgICB2YXIgc2NlbmVJZHMgPSBPYmplY3Qua2V5cyhuZXdMYXlvdXQpLmZpbHRlcihmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgcmV0dXJuIGtleS5tYXRjaCgvXnNjZW5lXFxkKiQvKTtcbiAgICB9KTtcbiAgICBpZihzY2VuZUlkcy5sZW5ndGgpIHtcbiAgICAgICAgdmFyIGF4ZXNJbWFnZU92ZXJyaWRlID0ge307XG4gICAgICAgIGlmKG9wdGlvbnMudGlsZUNsYXNzID09PSAndGh1bWJuYWlsJykge1xuICAgICAgICAgICAgYXhlc0ltYWdlT3ZlcnJpZGUgPSB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IHt0ZXh0OiAnJ30sXG4gICAgICAgICAgICAgICAgc2hvd2F4ZXNsYWJlbHM6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHNob3d0aWNrbGFiZWxzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBsaW5ldGlja2VuYWJsZTogZmFsc2VcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2NlbmVJZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBzY2VuZSA9IG5ld0xheW91dFtzY2VuZUlkc1tpXV07XG5cbiAgICAgICAgICAgIGlmKCFzY2VuZS54YXhpcykge1xuICAgICAgICAgICAgICAgIHNjZW5lLnhheGlzID0ge307XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKCFzY2VuZS55YXhpcykge1xuICAgICAgICAgICAgICAgIHNjZW5lLnlheGlzID0ge307XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKCFzY2VuZS56YXhpcykge1xuICAgICAgICAgICAgICAgIHNjZW5lLnpheGlzID0ge307XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGV4dGVuZEZsYXQoc2NlbmUueGF4aXMsIGF4ZXNJbWFnZU92ZXJyaWRlKTtcbiAgICAgICAgICAgIGV4dGVuZEZsYXQoc2NlbmUueWF4aXMsIGF4ZXNJbWFnZU92ZXJyaWRlKTtcbiAgICAgICAgICAgIGV4dGVuZEZsYXQoc2NlbmUuemF4aXMsIGF4ZXNJbWFnZU92ZXJyaWRlKTtcblxuICAgICAgICAgICAgLy8gVE9ETyB3aGF0IGRvZXMgdGhpcyBkbz9cbiAgICAgICAgICAgIHNjZW5lLl9zY2VuZSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZ2QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBpZihvcHRpb25zLnRpbGVDbGFzcykgZ2QuY2xhc3NOYW1lID0gb3B0aW9ucy50aWxlQ2xhc3M7XG5cbiAgICB2YXIgcGxvdFRpbGUgPSB7XG4gICAgICAgIGdkOiBnZCxcbiAgICAgICAgdGQ6IGdkLCAvLyBmb3IgZXh0ZXJuYWwgKGltYWdlIHNlcnZlcikgY29tcGF0aWJpbGl0eVxuICAgICAgICBsYXlvdXQ6IG5ld0xheW91dCxcbiAgICAgICAgZGF0YTogbmV3RGF0YSxcbiAgICAgICAgY29uZmlnOiB7XG4gICAgICAgICAgICBzdGF0aWNQbG90OiAob3B0aW9ucy5zdGF0aWNQbG90ID09PSB1bmRlZmluZWQpID9cbiAgICAgICAgICAgICAgICB0cnVlIDpcbiAgICAgICAgICAgICAgICBvcHRpb25zLnN0YXRpY1Bsb3QsXG4gICAgICAgICAgICBwbG90R2xQaXhlbFJhdGlvOiAob3B0aW9ucy5wbG90R2xQaXhlbFJhdGlvID09PSB1bmRlZmluZWQpID9cbiAgICAgICAgICAgICAgICAyIDpcbiAgICAgICAgICAgICAgICBvcHRpb25zLnBsb3RHbFBpeGVsUmF0aW8sXG4gICAgICAgICAgICBkaXNwbGF5bG9nbzogb3B0aW9ucy5kaXNwbGF5bG9nbyB8fCBmYWxzZSxcbiAgICAgICAgICAgIHNob3dMaW5rOiBvcHRpb25zLnNob3dMaW5rIHx8IGZhbHNlLFxuICAgICAgICAgICAgc2hvd1RpcHM6IG9wdGlvbnMuc2hvd1RpcHMgfHwgZmFsc2UsXG4gICAgICAgICAgICBtYXBib3hBY2Nlc3NUb2tlbjogY29udGV4dC5tYXBib3hBY2Nlc3NUb2tlblxuICAgICAgICB9XG4gICAgfTtcblxuICAgIGlmKG9wdGlvbnMuc2V0QmFja2dyb3VuZCAhPT0gJ3RyYW5zcGFyZW50Jykge1xuICAgICAgICBwbG90VGlsZS5jb25maWcuc2V0QmFja2dyb3VuZCA9IG9wdGlvbnMuc2V0QmFja2dyb3VuZCB8fCAnb3BhcXVlJztcbiAgICB9XG5cbiAgICAvLyBhdHRhY2hpbmcgdGhlIGRlZmF1bHQgTGF5b3V0IHRoZSBnZCwgc28geW91IGNhbiBncmFiIGl0IGxhdGVyXG4gICAgcGxvdFRpbGUuZ2QuZGVmYXVsdExheW91dCA9IGNsb25lTGF5b3V0T3ZlcnJpZGUob3B0aW9ucy50aWxlQ2xhc3MpO1xuXG4gICAgcmV0dXJuIHBsb3RUaWxlO1xufTtcblxufSx7XCIuLi9saWJcIjo3MTksXCIuLi9yZWdpc3RyeVwiOjg0N31dLDg0OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcblxudmFyIHRvSW1hZ2UgPSBfZGVyZXFfKCcuLi9wbG90X2FwaS90b19pbWFnZScpO1xuXG52YXIgZmlsZVNhdmVyID0gX2RlcmVxXygnLi9maWxlc2F2ZXInKTtcbnZhciBoZWxwZXJzID0gX2RlcmVxXygnLi9oZWxwZXJzJyk7XG5cbi8qKlxuICogUGxvdGx5LmRvd25sb2FkSW1hZ2VcbiAqXG4gKiBAcGFyYW0ge29iamVjdCB8IHN0cmluZyB8IEhUTUwgZGl2fSBnZFxuICogICBjYW4gZWl0aGVyIGJlIGEgZGF0YS9sYXlvdXQvY29uZmlnIG9iamVjdFxuICogICBvciBhbiBleGlzdGluZyBncmFwaCA8ZGl2PlxuICogICBvciBhbiBpZCB0byBhbiBleGlzdGluZyBncmFwaCA8ZGl2PlxuICogQHBhcmFtIHtvYmplY3R9IG9wdHMgKHNlZSBQbG90bHkudG9JbWFnZSBpbiAuLi9wbG90X2FwaS90b19pbWFnZSlcbiAqIEByZXR1cm4ge3Byb21pc2V9XG4gKi9cbmZ1bmN0aW9uIGRvd25sb2FkSW1hZ2UoZ2QsIG9wdHMpIHtcbiAgICB2YXIgX2dkO1xuICAgIGlmKCFMaWIuaXNQbGFpbk9iamVjdChnZCkpIF9nZCA9IExpYi5nZXRHcmFwaERpdihnZCk7XG5cbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcbiAgICBvcHRzLmZvcm1hdCA9IG9wdHMuZm9ybWF0IHx8ICdwbmcnO1xuICAgIG9wdHMuaW1hZ2VEYXRhT25seSA9IHRydWU7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGlmKF9nZCAmJiBfZ2QuX3NuYXBzaG90SW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignU25hcHNob3R0aW5nIGFscmVhZHkgaW4gcHJvZ3Jlc3MuJykpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc2VlIGNvbW1lbnRzIHdpdGhpbiBzdmd0b2ltZyBmb3IgYWRkaXRpb25hbFxuICAgICAgICAvLyAgIGRpc2N1c3Npb24gb2YgcHJvYmxlbXMgd2l0aCBJRVxuICAgICAgICAvLyAgIGNhbiBub3cgZHJhdyB0byBjYW52YXMsIGJ1dCBDT1JTIHRhaW50ZWQgY2FudmFzXG4gICAgICAgIC8vICAgZG9lcyBub3QgYWxsb3cgdG9EYXRhVVJMXG4gICAgICAgIC8vICAgc3ZnIGZvcm1hdCB3aWxsIHdvcmsgdGhvdWdoXG4gICAgICAgIGlmKExpYi5pc0lFKCkgJiYgb3B0cy5mb3JtYXQgIT09ICdzdmcnKSB7XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGhlbHBlcnMuTVNHX0lFX0JBRF9GT1JNQVQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKF9nZCkgX2dkLl9zbmFwc2hvdEluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICB2YXIgcHJvbWlzZSA9IHRvSW1hZ2UoZ2QsIG9wdHMpO1xuXG4gICAgICAgIHZhciBmaWxlbmFtZSA9IG9wdHMuZmlsZW5hbWUgfHwgZ2QuZm4gfHwgJ25ld3Bsb3QnO1xuICAgICAgICBmaWxlbmFtZSArPSAnLicgKyBvcHRzLmZvcm1hdDtcblxuICAgICAgICBwcm9taXNlLnRoZW4oZnVuY3Rpb24ocmVzdWx0KSB7XG4gICAgICAgICAgICBpZihfZ2QpIF9nZC5fc25hcHNob3RJblByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gZmlsZVNhdmVyKHJlc3VsdCwgZmlsZW5hbWUsIG9wdHMuZm9ybWF0KTtcbiAgICAgICAgfSkudGhlbihmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgICAgICByZXNvbHZlKG5hbWUpO1xuICAgICAgICB9KS5jYXRjaChmdW5jdGlvbihlcnIpIHtcbiAgICAgICAgICAgIGlmKF9nZCkgX2dkLl9zbmFwc2hvdEluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBkb3dubG9hZEltYWdlO1xuXG59LHtcIi4uL2xpYlwiOjcxOSxcIi4uL3Bsb3RfYXBpL3RvX2ltYWdlXCI6NzYwLFwiLi9maWxlc2F2ZXJcIjo4NTAsXCIuL2hlbHBlcnNcIjo4NTF9XSw4NTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xuXG4vKlxuKiBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGlzIGNvZGUgZnJvbSBGaWxlU2F2ZXIuanNcbiogaHR0cHM6Ly9naXRodWIuY29tL2VsaWdyZXkvRmlsZVNhdmVyLmpzXG4qIExpY2Vuc2U6IGh0dHBzOi8vZ2l0aHViLmNvbS9lbGlncmV5L0ZpbGVTYXZlci5qcy9ibG9iL21hc3Rlci9MSUNFTlNFLm1kXG4qIEZpbGVTYXZlci5qc1xuKiBBIHNhdmVBcygpIEZpbGVTYXZlciBpbXBsZW1lbnRhdGlvbi5cbiogMS4xLjIwMTYwMzI4XG4qXG4qIEJ5IEVsaSBHcmV5LCBodHRwOi8vZWxpZ3JleS5jb21cbiogTGljZW5zZTogTUlUXG4qICAgU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbGlncmV5L0ZpbGVTYXZlci5qcy9ibG9iL21hc3Rlci9MSUNFTlNFLm1kXG4qL1xuZnVuY3Rpb24gZmlsZVNhdmVyKHVybCwgbmFtZSwgZm9ybWF0KSB7XG4gICAgdmFyIHNhdmVMaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgIHZhciBjYW5Vc2VTYXZlTGluayA9ICdkb3dubG9hZCcgaW4gc2F2ZUxpbms7XG5cbiAgICB2YXIgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICB2YXIgYmxvYjtcbiAgICAgICAgdmFyIG9iamVjdFVybDtcblxuICAgICAgICBpZihMaWIuaXNJRTlvckJlbG93KCkpIHtcbiAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0lFIDwgMTAgdW5zdXBwb3J0ZWQnKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTYWZhcmkgZG9lc24ndCBhbGxvdyBkb3dubG9hZGluZyBvZiBibG9iIHVybHNcbiAgICAgICAgaWYoTGliLmlzU2FmYXJpKCkpIHtcbiAgICAgICAgICAgIHZhciBwcmVmaXggPSBmb3JtYXQgPT09ICdzdmcnID8gJywnIDogJztiYXNlNjQsJztcbiAgICAgICAgICAgIGhlbHBlcnMub2N0ZXRTdHJlYW0ocHJlZml4ICsgZW5jb2RlVVJJQ29tcG9uZW50KHVybCkpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJRSAxMCsgKG5hdGl2ZSBzYXZlQXMpXG4gICAgICAgIGlmKExpYi5pc0lFKCkpIHtcbiAgICAgICAgICAgIC8vIEF0IHRoaXMgcG9pbnQgd2UgYXJlIG9ubHkgZGVhbGluZyB3aXRoIGEgZGVjb2RlZCBTVkcgYXNcbiAgICAgICAgICAgIC8vIGEgZGF0YSBVUkwgKHNpbmNlIElFIG9ubHkgc3VwcG9ydHMgU1ZHKVxuICAgICAgICAgICAgYmxvYiA9IGhlbHBlcnMuY3JlYXRlQmxvYih1cmwsICdzdmcnKTtcbiAgICAgICAgICAgIHdpbmRvdy5uYXZpZ2F0b3IubXNTYXZlQmxvYihibG9iLCBuYW1lKTtcbiAgICAgICAgICAgIGJsb2IgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihjYW5Vc2VTYXZlTGluaykge1xuICAgICAgICAgICAgYmxvYiA9IGhlbHBlcnMuY3JlYXRlQmxvYih1cmwsIGZvcm1hdCk7XG4gICAgICAgICAgICBvYmplY3RVcmwgPSBoZWxwZXJzLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcblxuICAgICAgICAgICAgc2F2ZUxpbmsuaHJlZiA9IG9iamVjdFVybDtcbiAgICAgICAgICAgIHNhdmVMaW5rLmRvd25sb2FkID0gbmFtZTtcbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc2F2ZUxpbmspO1xuICAgICAgICAgICAgc2F2ZUxpbmsuY2xpY2soKTtcblxuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChzYXZlTGluayk7XG4gICAgICAgICAgICBoZWxwZXJzLnJldm9rZU9iamVjdFVSTChvYmplY3RVcmwpO1xuICAgICAgICAgICAgYmxvYiA9IG51bGw7XG5cbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG5hbWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignZG93bmxvYWQgZXJyb3InKSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcHJvbWlzZTtcbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZpbGVTYXZlcjtcblxufSx7XCIuLi9saWJcIjo3MTksXCIuL2hlbHBlcnNcIjo4NTF9XSw4NTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi9yZWdpc3RyeScpO1xuXG5leHBvcnRzLmdldERlbGF5ID0gZnVuY3Rpb24oZnVsbExheW91dCkge1xuICAgIGlmKCFmdWxsTGF5b3V0Ll9oYXMpIHJldHVybiAwO1xuXG4gICAgcmV0dXJuIChcbiAgICAgICAgZnVsbExheW91dC5faGFzKCdnbDNkJykgfHxcbiAgICAgICAgZnVsbExheW91dC5faGFzKCdnbDJkJykgfHxcbiAgICAgICAgZnVsbExheW91dC5faGFzKCdtYXBib3gnKVxuICAgICkgPyA1MDAgOiAwO1xufTtcblxuZXhwb3J0cy5nZXRSZWRyYXdGdW5jID0gZnVuY3Rpb24oZ2QpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQgfHwge307XG4gICAgICAgIHZhciBoYXNQb2xhciA9IGZ1bGxMYXlvdXQuX2hhcyAmJiBmdWxsTGF5b3V0Ll9oYXMoJ3BvbGFyJyk7XG4gICAgICAgIHZhciBoYXNMZWdhY3lQb2xhciA9ICFoYXNQb2xhciAmJiBnZC5kYXRhICYmIGdkLmRhdGFbMF0gJiYgZ2QuZGF0YVswXS5yO1xuXG4gICAgICAgIGlmKCFoYXNMZWdhY3lQb2xhcikge1xuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjb2xvcmJhcicsICdkcmF3JykoZ2QpO1xuICAgICAgICB9XG4gICAgfTtcbn07XG5cbmV4cG9ydHMuZW5jb2RlU1ZHID0gZnVuY3Rpb24oc3ZnKSB7XG4gICAgcmV0dXJuICdkYXRhOmltYWdlL3N2Zyt4bWwsJyArIGVuY29kZVVSSUNvbXBvbmVudChzdmcpO1xufTtcblxudmFyIERPTV9VUkwgPSB3aW5kb3cuVVJMIHx8IHdpbmRvdy53ZWJraXRVUkw7XG5cbmV4cG9ydHMuY3JlYXRlT2JqZWN0VVJMID0gZnVuY3Rpb24oYmxvYikge1xuICAgIHJldHVybiBET01fVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcbn07XG5cbmV4cG9ydHMucmV2b2tlT2JqZWN0VVJMID0gZnVuY3Rpb24odXJsKSB7XG4gICAgcmV0dXJuIERPTV9VUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG59O1xuXG5leHBvcnRzLmNyZWF0ZUJsb2IgPSBmdW5jdGlvbih1cmwsIGZvcm1hdCkge1xuICAgIGlmKGZvcm1hdCA9PT0gJ3N2ZycpIHtcbiAgICAgICAgcmV0dXJuIG5ldyB3aW5kb3cuQmxvYihbdXJsXSwge3R5cGU6ICdpbWFnZS9zdmcreG1sO2NoYXJzZXQ9dXRmLTgnfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGJpbmFyeSA9IGZpeEJpbmFyeSh3aW5kb3cuYXRvYih1cmwpKTtcbiAgICAgICAgcmV0dXJuIG5ldyB3aW5kb3cuQmxvYihbYmluYXJ5XSwge3R5cGU6ICdpbWFnZS8nICsgZm9ybWF0fSk7XG4gICAgfVxufTtcblxuZXhwb3J0cy5vY3RldFN0cmVhbSA9IGZ1bmN0aW9uKHMpIHtcbiAgICBkb2N1bWVudC5sb2NhdGlvbi5ocmVmID0gJ2RhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtJyArIHM7XG59O1xuXG4vLyBUYWtlbiBmcm9tIGh0dHBzOi8vYmwub2Nrcy5vcmcvbm9sYW5sYXdzb24vMGVhYzMwNmU0ZGFjMjExNGM3NTJcbmZ1bmN0aW9uIGZpeEJpbmFyeShiKSB7XG4gICAgdmFyIGxlbiA9IGIubGVuZ3RoO1xuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIobGVuKTtcbiAgICB2YXIgYXJyID0gbmV3IFVpbnQ4QXJyYXkoYnVmKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgYXJyW2ldID0gYi5jaGFyQ29kZUF0KGkpO1xuICAgIH1cbiAgICByZXR1cm4gYnVmO1xufVxuXG5leHBvcnRzLklNQUdFX1VSTF9QUkVGSVggPSAvXmRhdGE6aW1hZ2VcXC9cXHcrO2Jhc2U2NCwvO1xuXG5leHBvcnRzLk1TR19JRV9CQURfRk9STUFUID0gJ1NvcnJ5IElFIGRvZXMgbm90IHN1cHBvcnQgZG93bmxvYWRpbmcgZnJvbSBjYW52YXMuIFRyeSB7Zm9ybWF0OlxcJ3N2Z1xcJ30gaW5zdGVhZC4nO1xuXG59LHtcIi4uL3JlZ2lzdHJ5XCI6ODQ3fV0sODUyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xuXG52YXIgU25hcHNob3QgPSB7XG4gICAgZ2V0RGVsYXk6IGhlbHBlcnMuZ2V0RGVsYXksXG4gICAgZ2V0UmVkcmF3RnVuYzogaGVscGVycy5nZXRSZWRyYXdGdW5jLFxuICAgIGNsb25lOiBfZGVyZXFfKCcuL2Nsb25lcGxvdCcpLFxuICAgIHRvU1ZHOiBfZGVyZXFfKCcuL3Rvc3ZnJyksXG4gICAgc3ZnVG9JbWc6IF9kZXJlcV8oJy4vc3ZndG9pbWcnKSxcbiAgICB0b0ltYWdlOiBfZGVyZXFfKCcuL3RvaW1hZ2UnKSxcbiAgICBkb3dubG9hZEltYWdlOiBfZGVyZXFfKCcuL2Rvd25sb2FkJylcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gU25hcHNob3Q7XG5cbn0se1wiLi9jbG9uZXBsb3RcIjo4NDgsXCIuL2Rvd25sb2FkXCI6ODQ5LFwiLi9oZWxwZXJzXCI6ODUxLFwiLi9zdmd0b2ltZ1wiOjg1MyxcIi4vdG9pbWFnZVwiOjg1NCxcIi4vdG9zdmdcIjo4NTV9XSw4NTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG52YXIgRXZlbnRFbWl0dGVyID0gX2RlcmVxXygnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuXG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xuXG5mdW5jdGlvbiBzdmdUb0ltZyhvcHRzKSB7XG4gICAgdmFyIGV2ID0gb3B0cy5lbWl0dGVyIHx8IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIHZhciBwcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIHZhciBJbWFnZSA9IHdpbmRvdy5JbWFnZTtcbiAgICAgICAgdmFyIHN2ZyA9IG9wdHMuc3ZnO1xuICAgICAgICB2YXIgZm9ybWF0ID0gb3B0cy5mb3JtYXQgfHwgJ3BuZyc7XG5cbiAgICAgICAgLy8gSUUgb25seSBzdXBwb3J0IHN2Z1xuICAgICAgICBpZihMaWIuaXNJRSgpICYmIGZvcm1hdCAhPT0gJ3N2ZycpIHtcbiAgICAgICAgICAgIHZhciBpZVN2Z0Vycm9yID0gbmV3IEVycm9yKGhlbHBlcnMuTVNHX0lFX0JBRF9GT1JNQVQpO1xuICAgICAgICAgICAgcmVqZWN0KGllU3ZnRXJyb3IpO1xuICAgICAgICAgICAgLy8gZXZlbnR1YWxseSByZW1vdmUgdGhlIGV2XG4gICAgICAgICAgICAvLyAgaW4gZmF2b3Igb2YgcHJvbWlzZXNcbiAgICAgICAgICAgIGlmKCFvcHRzLnByb21pc2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXYuZW1pdCgnZXJyb3InLCBpZVN2Z0Vycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY2FudmFzID0gb3B0cy5jYW52YXM7XG4gICAgICAgIHZhciBzY2FsZSA9IG9wdHMuc2NhbGUgfHwgMTtcbiAgICAgICAgdmFyIHcwID0gb3B0cy53aWR0aCB8fCAzMDA7XG4gICAgICAgIHZhciBoMCA9IG9wdHMuaGVpZ2h0IHx8IDE1MDtcbiAgICAgICAgdmFyIHcxID0gc2NhbGUgKiB3MDtcbiAgICAgICAgdmFyIGgxID0gc2NhbGUgKiBoMDtcblxuICAgICAgICB2YXIgY3R4ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgIHZhciBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgdmFyIHN2Z0Jsb2IsIHVybDtcblxuICAgICAgICBpZihmb3JtYXQgPT09ICdzdmcnIHx8IExpYi5pc0lFOW9yQmVsb3coKSB8fCBMaWIuaXNTYWZhcmkoKSkge1xuICAgICAgICAgICAgdXJsID0gaGVscGVycy5lbmNvZGVTVkcoc3ZnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN2Z0Jsb2IgPSBoZWxwZXJzLmNyZWF0ZUJsb2Ioc3ZnLCAnc3ZnJyk7XG4gICAgICAgICAgICB1cmwgPSBoZWxwZXJzLmNyZWF0ZU9iamVjdFVSTChzdmdCbG9iKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHcxO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gaDE7XG5cbiAgICAgICAgaW1nLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGltZ0RhdGE7XG5cbiAgICAgICAgICAgIHN2Z0Jsb2IgPSBudWxsO1xuICAgICAgICAgICAgaGVscGVycy5yZXZva2VPYmplY3RVUkwodXJsKTtcblxuICAgICAgICAgICAgLy8gZG9uJ3QgbmVlZCB0byBkcmF3IHRvIGNhbnZhcyBpZiBzdmdcbiAgICAgICAgICAgIC8vICBzYXZlIHNvbWUgdGltZSBhbmQgYWxzbyBhdm9pZCBmYWlsdXJlIG9uIElFXG4gICAgICAgICAgICBpZihmb3JtYXQgIT09ICdzdmcnKSB7XG4gICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShpbWcsIDAsIDAsIHcxLCBoMSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN3aXRjaChmb3JtYXQpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdqcGVnJzpcbiAgICAgICAgICAgICAgICAgICAgaW1nRGF0YSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL2pwZWcnKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAncG5nJzpcbiAgICAgICAgICAgICAgICAgICAgaW1nRGF0YSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd3ZWJwJzpcbiAgICAgICAgICAgICAgICAgICAgaW1nRGF0YSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3dlYnAnKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3ZnJzpcbiAgICAgICAgICAgICAgICAgICAgaW1nRGF0YSA9IHVybDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yTXNnID0gJ0ltYWdlIGZvcm1hdCBpcyBub3QganBlZywgcG5nLCBzdmcgb3Igd2VicC4nO1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGVycm9yTXNnKSk7XG4gICAgICAgICAgICAgICAgICAgIC8vIGV2ZW50dWFsbHkgcmVtb3ZlIHRoZSBldlxuICAgICAgICAgICAgICAgICAgICAvLyAgaW4gZmF2b3Igb2YgcHJvbWlzZXNcbiAgICAgICAgICAgICAgICAgICAgaWYoIW9wdHMucHJvbWlzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV2LmVtaXQoJ2Vycm9yJywgZXJyb3JNc2cpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXNvbHZlKGltZ0RhdGEpO1xuICAgICAgICAgICAgLy8gZXZlbnR1YWxseSByZW1vdmUgdGhlIGV2XG4gICAgICAgICAgICAvLyAgaW4gZmF2b3Igb2YgcHJvbWlzZXNcbiAgICAgICAgICAgIGlmKCFvcHRzLnByb21pc2UpIHtcbiAgICAgICAgICAgICAgICBldi5lbWl0KCdzdWNjZXNzJywgaW1nRGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaW1nLm9uZXJyb3IgPSBmdW5jdGlvbihlcnIpIHtcbiAgICAgICAgICAgIHN2Z0Jsb2IgPSBudWxsO1xuICAgICAgICAgICAgaGVscGVycy5yZXZva2VPYmplY3RVUkwodXJsKTtcblxuICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAvLyBldmVudHVhbGx5IHJlbW92ZSB0aGUgZXZcbiAgICAgICAgICAgIC8vICBpbiBmYXZvciBvZiBwcm9taXNlc1xuICAgICAgICAgICAgaWYoIW9wdHMucHJvbWlzZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBldi5lbWl0KCdlcnJvcicsIGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaW1nLnNyYyA9IHVybDtcbiAgICB9KTtcblxuICAgIC8vIHRlbXBvcmFyeSBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eVxuICAgIC8vICBtb3ZlIHRvIG9ubHkgUHJvbWlzZSBpbiAyLjAuMFxuICAgIC8vICBhbmQgZWxpbWluYXRlIHRoZSBFdmVudEVtaXR0ZXJcbiAgICBpZihvcHRzLnByb21pc2UpIHtcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV2O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHN2Z1RvSW1nO1xuXG59LHtcIi4uL2xpYlwiOjcxOSxcIi4vaGVscGVyc1wiOjg1MSxcImV2ZW50c1wiOjEwNH1dLDg1NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBFdmVudEVtaXR0ZXIgPSBfZGVyZXFfKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG5cbnZhciBoZWxwZXJzID0gX2RlcmVxXygnLi9oZWxwZXJzJyk7XG52YXIgY2xvbmVQbG90ID0gX2RlcmVxXygnLi9jbG9uZXBsb3QnKTtcbnZhciB0b1NWRyA9IF9kZXJlcV8oJy4vdG9zdmcnKTtcbnZhciBzdmdUb0ltZyA9IF9kZXJlcV8oJy4vc3ZndG9pbWcnKTtcblxuLyoqXG4gKiBAcGFyYW0ge29iamVjdH0gZ2QgZmlndXJlIE9iamVjdFxuICogQHBhcmFtIHtvYmplY3R9IG9wdHMgb3B0aW9uIG9iamVjdFxuICogQHBhcmFtIG9wdHMuZm9ybWF0ICdqcGVnJyB8ICdwbmcnIHwgJ3dlYnAnIHwgJ3N2ZydcbiAqL1xuZnVuY3Rpb24gdG9JbWFnZShnZCwgb3B0cykge1xuICAgIC8vIGZpcnN0IGNsb25lIHRoZSBHRCBzbyB3ZSBjYW4gb3BlcmF0ZSBpbiBhIGNsZWFuIGVudmlyb25tZW50XG4gICAgdmFyIGV2ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgdmFyIGNsb25lID0gY2xvbmVQbG90KGdkLCB7Zm9ybWF0OiAncG5nJ30pO1xuICAgIHZhciBjbG9uZWRHZCA9IGNsb25lLmdkO1xuXG4gICAgLy8gcHV0IHRoZSBjbG9uZWQgZGl2IHNvbWV3aGVyZSBvZmYgc2NyZWVuIGJlZm9yZSBhdHRhY2hpbmcgdG8gRE9NXG4gICAgY2xvbmVkR2Quc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgIGNsb25lZEdkLnN0eWxlLmxlZnQgPSAnLTUwMDBweCc7XG4gICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChjbG9uZWRHZCk7XG5cbiAgICBmdW5jdGlvbiB3YWl0KCkge1xuICAgICAgICB2YXIgZGVsYXkgPSBoZWxwZXJzLmdldERlbGF5KGNsb25lZEdkLl9mdWxsTGF5b3V0KTtcblxuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHN2ZyA9IHRvU1ZHKGNsb25lZEdkKTtcblxuICAgICAgICAgICAgdmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgY2FudmFzLmlkID0gTGliLnJhbmRzdHIoKTtcblxuICAgICAgICAgICAgZXYgPSBzdmdUb0ltZyh7XG4gICAgICAgICAgICAgICAgZm9ybWF0OiBvcHRzLmZvcm1hdCxcbiAgICAgICAgICAgICAgICB3aWR0aDogY2xvbmVkR2QuX2Z1bGxMYXlvdXQud2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBjbG9uZWRHZC5fZnVsbExheW91dC5oZWlnaHQsXG4gICAgICAgICAgICAgICAgY2FudmFzOiBjYW52YXMsXG4gICAgICAgICAgICAgICAgZW1pdHRlcjogZXYsXG4gICAgICAgICAgICAgICAgc3ZnOiBzdmdcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBldi5jbGVhbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIGlmKGNsb25lZEdkKSBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGNsb25lZEdkKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIGRlbGF5KTtcbiAgICB9XG5cbiAgICB2YXIgcmVkcmF3RnVuYyA9IGhlbHBlcnMuZ2V0UmVkcmF3RnVuYyhjbG9uZWRHZCk7XG5cbiAgICBSZWdpc3RyeS5jYWxsKCdwbG90JywgY2xvbmVkR2QsIGNsb25lLmRhdGEsIGNsb25lLmxheW91dCwgY2xvbmUuY29uZmlnKVxuICAgICAgICAudGhlbihyZWRyYXdGdW5jKVxuICAgICAgICAudGhlbih3YWl0KVxuICAgICAgICAuY2F0Y2goZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgICAgICBldi5lbWl0KCdlcnJvcicsIGVycik7XG4gICAgICAgIH0pO1xuXG5cbiAgICByZXR1cm4gZXY7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdG9JbWFnZTtcblxufSx7XCIuLi9saWJcIjo3MTksXCIuLi9yZWdpc3RyeVwiOjg0NyxcIi4vY2xvbmVwbG90XCI6ODQ4LFwiLi9oZWxwZXJzXCI6ODUxLFwiLi9zdmd0b2ltZ1wiOjg1MyxcIi4vdG9zdmdcIjo4NTUsXCJldmVudHNcIjoxMDR9XSw4NTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi9jb21wb25lbnRzL2NvbG9yJyk7XG5cbnZhciB4bWxuc05hbWVzcGFjZXMgPSBfZGVyZXFfKCcuLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlcycpO1xudmFyIERPVUJMRVFVT1RFX1JFR0VYID0gL1wiL2c7XG52YXIgRFVNTVlfU1VCID0gJ1RPQkVTVFJJUFBFRCc7XG52YXIgRFVNTVlfUkVHRVggPSBuZXcgUmVnRXhwKCcoXCInICsgRFVNTVlfU1VCICsgJyl8KCcgKyBEVU1NWV9TVUIgKyAnXCIpJywgJ2cnKTtcblxuZnVuY3Rpb24gaHRtbEVudGl0eURlY29kZShzKSB7XG4gICAgdmFyIGhpZGRlbkRpdiA9IGQzLnNlbGVjdCgnYm9keScpLmFwcGVuZCgnZGl2Jykuc3R5bGUoe2Rpc3BsYXk6ICdub25lJ30pLmh0bWwoJycpO1xuICAgIHZhciByZXBsYWNlZCA9IHMucmVwbGFjZSgvKCZbXjtdKjspL2dpLCBmdW5jdGlvbihkKSB7XG4gICAgICAgIGlmKGQgPT09ICcmbHQ7JykgeyByZXR1cm4gJyYjNjA7JzsgfSAvLyBzcGVjaWFsIGhhbmRsaW5nIGZvciBicmFja2V0c1xuICAgICAgICBpZihkID09PSAnJnJ0OycpIHsgcmV0dXJuICcmIzYyOyc7IH1cbiAgICAgICAgaWYoZC5pbmRleE9mKCc8JykgIT09IC0xIHx8IGQuaW5kZXhPZignPicpICE9PSAtMSkgeyByZXR1cm4gJyc7IH1cbiAgICAgICAgcmV0dXJuIGhpZGRlbkRpdi5odG1sKGQpLnRleHQoKTsgLy8gZXZlcnl0aGluZyBlbHNlLCBsZXQgdGhlIGJyb3dzZXIgZGVjb2RlIGl0IHRvIHVuaWNvZGVcbiAgICB9KTtcbiAgICBoaWRkZW5EaXYucmVtb3ZlKCk7XG4gICAgcmV0dXJuIHJlcGxhY2VkO1xufVxuXG5mdW5jdGlvbiB4bWxFbnRpdHlFbmNvZGUoc3RyKSB7XG4gICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8mKD8hXFx3Kzt8XFwjWzAtOV0rO3wgXFwjeFswLTlBLUZdKzspL2csICcmYW1wOycpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHRvU1ZHKGdkLCBmb3JtYXQsIHNjYWxlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3ZnID0gZnVsbExheW91dC5fcGFwZXI7XG4gICAgdmFyIHRvcHBhcGVyID0gZnVsbExheW91dC5fdG9wcGFwZXI7XG4gICAgdmFyIHdpZHRoID0gZnVsbExheW91dC53aWR0aDtcbiAgICB2YXIgaGVpZ2h0ID0gZnVsbExheW91dC5oZWlnaHQ7XG4gICAgdmFyIGk7XG5cbiAgICAvLyBtYWtlIGJhY2tncm91bmQgY29sb3IgYSByZWN0IGluIHRoZSBzdmcsIHRoZW4gcmV2ZXJ0IGFmdGVyIHNjcmFwaW5nXG4gICAgLy8gYWxsIG90aGVyIGFsdGVyYXRpb25zIGhhdmUgYmVlbiBkZWFsdCB3aXRoIGJ5IHByb3Blcmx5IHByZXBhcmluZyB0aGUgc3ZnXG4gICAgLy8gaW4gdGhlIGZpcnN0IHBsYWNlLi4uIGxpa2Ugc2V0dGluZyBjdXJzb3JzIHdpdGggY3NzIGNsYXNzZXMgc28gd2UgZG9uJ3RcbiAgICAvLyBoYXZlIHRvIHJlbW92ZSB0aGVtLCBhbmQgcHJvdmlkaW5nIHRoZSByaWdodCBuYW1lc3BhY2VzIGluIHRoZSBzdmcgdG9cbiAgICAvLyBiZWdpbiB3aXRoXG4gICAgc3ZnLmluc2VydCgncmVjdCcsICc6Zmlyc3QtY2hpbGQnKVxuICAgICAgICAuY2FsbChEcmF3aW5nLnNldFJlY3QsIDAsIDAsIHdpZHRoLCBoZWlnaHQpXG4gICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGZ1bGxMYXlvdXQucGFwZXJfYmdjb2xvcik7XG5cbiAgICAvLyBzdWJwbG90LXNwZWNpZmljIHRvLVNWRyBtZXRob2RzXG4gICAgLy8gd2hpY2ggbm90YWJseSBhZGQgdGhlIGNvbnRlbnRzIG9mIHRoZSBnbC1jb250YWluZXJcbiAgICAvLyBpbnRvIHRoZSBtYWluIHN2ZyBub2RlXG4gICAgdmFyIGJhc2VQbG90TW9kdWxlcyA9IGZ1bGxMYXlvdXQuX2Jhc2VQbG90TW9kdWxlcyB8fCBbXTtcbiAgICBmb3IoaSA9IDA7IGkgPCBiYXNlUGxvdE1vZHVsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIF9tb2R1bGUgPSBiYXNlUGxvdE1vZHVsZXNbaV07XG5cbiAgICAgICAgaWYoX21vZHVsZS50b1NWRykgX21vZHVsZS50b1NWRyhnZCk7XG4gICAgfVxuXG4gICAgLy8gYWRkIHRvcCBpdGVtcyBhYm92ZSB0aGVtIGFzc3VtZXMgZXZlcnl0aGluZyBpbiB0b3BwYXBlciBpcyBlaXRoZXJcbiAgICAvLyBhIGdyb3VwIG9yIGEgZGVmcywgYW5kIGlmIGl0J3MgZW1wdHkgKGxpa2UgaG92ZXJsYXllcikgd2UgY2FuIGlnbm9yZSBpdC5cbiAgICBpZih0b3BwYXBlcikge1xuICAgICAgICB2YXIgbm9kZXMgPSB0b3BwYXBlci5ub2RlKCkuY2hpbGROb2RlcztcblxuICAgICAgICAvLyBtYWtlIGNvcHkgb2Ygbm9kZXMgYXMgY2hpbGROb2RlcyBwcm9wIGdldHMgbXV0YXRlZCBpbiBsb29wIGJlbG93XG4gICAgICAgIHZhciB0b3BHcm91cHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChub2Rlcyk7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgdG9wR3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdG9wR3JvdXAgPSB0b3BHcm91cHNbaV07XG5cbiAgICAgICAgICAgIGlmKHRvcEdyb3VwLmNoaWxkTm9kZXMubGVuZ3RoKSBzdmcubm9kZSgpLmFwcGVuZENoaWxkKHRvcEdyb3VwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHJlbW92ZSBkcmFnbGF5ZXIgZm9yIEFkb2JlIElsbHVzdHJhdG9yIGNvbXBhdGliaWxpdHlcbiAgICBpZihmdWxsTGF5b3V0Ll9kcmFnZ2Vycykge1xuICAgICAgICBmdWxsTGF5b3V0Ll9kcmFnZ2Vycy5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICAvLyBpbiBjYXNlIHRoZSBzdmcgZWxlbWVudCBoYWQgYW4gZXhwbGljaXQgYmFja2dyb3VuZCBjb2xvciwgcmVtb3ZlIHRoaXNcbiAgICAvLyB3ZSB3YW50IHRoZSByZWN0IHRvIGdldCB0aGUgY29sb3Igc28gaXQncyB0aGUgcmlnaHQgc2l6ZTsgc3ZnIGJnIHdpbGxcbiAgICAvLyBmaWxsIHdoYXRldmVyIGNvbnRhaW5lciBpdCdzIGRpc3BsYXllZCBpbiByZWdhcmRsZXNzIG9mIHBsb3Qgc2l6ZS5cbiAgICBzdmcubm9kZSgpLnN0eWxlLmJhY2tncm91bmQgPSAnJztcblxuICAgIHN2Zy5zZWxlY3RBbGwoJ3RleHQnKVxuICAgICAgICAuYXR0cih7J2RhdGEtdW5mb3JtYXR0ZWQnOiBudWxsLCAnZGF0YS1tYXRoJzogbnVsbH0pXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHR4dCA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICAgICAgLy8gaGlkZGVuIHRleHQgaXMgcHJlLWZvcm1hdHRpbmcgbWF0aGpheCwgdGhlIGJyb3dzZXIgaWdub3JlcyBpdFxuICAgICAgICAgICAgLy8gYnV0IGluIGEgc3RhdGljIHBsb3QgaXQncyB1c2VsZXNzIGFuZCBpdCBjYW4gY29uZnVzZSBiYXRpa1xuICAgICAgICAgICAgLy8gd2UndmUgdHJpZWQgdG8gc3RhbmRhcmRpemUgb24gZGlzcGxheTpub25lIGJ1dCBtYWtlIHN1cmUgd2Ugc3RpbGxcbiAgICAgICAgICAgIC8vIGNhdGNoIHZpc2liaWxpdHk6aGlkZGVuIGlmIGl0IGV2ZXIgYXJpc2VzXG4gICAgICAgICAgICBpZih0aGlzLnN0eWxlLnZpc2liaWxpdHkgPT09ICdoaWRkZW4nIHx8IHRoaXMuc3R5bGUuZGlzcGxheSA9PT0gJ25vbmUnKSB7XG4gICAgICAgICAgICAgICAgdHh0LnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY2xlYXIgb3RoZXIgdmlzaWJpbGl0eS9kaXNwbGF5IHZhbHVlcyB0byBkZWZhdWx0XG4gICAgICAgICAgICAgICAgLy8gdG8gbm90IHBvdGVudGlhbGx5IGNvbmZ1c2Ugbm9uLWJyb3dzZXIgU1ZHIGltcGxlbWVudGF0aW9uc1xuICAgICAgICAgICAgICAgIHR4dC5zdHlsZSh7dmlzaWJpbGl0eTogbnVsbCwgZGlzcGxheTogbnVsbH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGb250IGZhbWlseSBzdHlsZXMgYnJlYWsgdGhpbmdzIGJlY2F1c2Ugb2YgcXVvdGF0aW9uIG1hcmtzLFxuICAgICAgICAgICAgLy8gc28gd2UgbXVzdCByZW1vdmUgdGhlbSAqYWZ0ZXIqIHRoZSBTVkcgRE9NIGhhcyBiZWVuIHNlcmlhbGl6ZWRcbiAgICAgICAgICAgIC8vIHRvIGEgc3RyaW5nIChicm93c2VycyBjb252ZXJ0IHNpbmdsZXMgYmFjaylcbiAgICAgICAgICAgIHZhciBmZiA9IHRoaXMuc3R5bGUuZm9udEZhbWlseTtcbiAgICAgICAgICAgIGlmKGZmICYmIGZmLmluZGV4T2YoJ1wiJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdHh0LnN0eWxlKCdmb250LWZhbWlseScsIGZmLnJlcGxhY2UoRE9VQkxFUVVPVEVfUkVHRVgsIERVTU1ZX1NVQikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHN2Zy5zZWxlY3RBbGwoJy5wb2ludCwgLnNjYXR0ZXJwdHMsIC5sZWdlbmRmaWxsPnBhdGgsIC5sZWdlbmRsaW5lcz5wYXRoLCAuY2JmaWxsJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHB0ID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIC8vIHNpbWlsYXIgdG8gZm9udCBmYW1pbHkgc3R5bGVzIGFib3ZlLFxuICAgICAgICAvLyB3ZSBtdXN0IHJlbW92ZSBcIiBhZnRlciB0aGUgU1ZHIERPTSBoYXMgYmVlbiBzZXJpYWxpemVkXG4gICAgICAgIHZhciBmaWxsID0gdGhpcy5zdHlsZS5maWxsO1xuICAgICAgICBpZihmaWxsICYmIGZpbGwuaW5kZXhPZigndXJsKCcpICE9PSAtMSkge1xuICAgICAgICAgICAgcHQuc3R5bGUoJ2ZpbGwnLCBmaWxsLnJlcGxhY2UoRE9VQkxFUVVPVEVfUkVHRVgsIERVTU1ZX1NVQikpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHN0cm9rZSA9IHRoaXMuc3R5bGUuc3Ryb2tlO1xuICAgICAgICBpZihzdHJva2UgJiYgc3Ryb2tlLmluZGV4T2YoJ3VybCgnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHB0LnN0eWxlKCdzdHJva2UnLCBzdHJva2UucmVwbGFjZShET1VCTEVRVU9URV9SRUdFWCwgRFVNTVlfU1VCKSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmKGZvcm1hdCA9PT0gJ3BkZicgfHwgZm9ybWF0ID09PSAnZXBzJykge1xuICAgICAgICAvLyB0aGVzZSBmb3JtYXRzIG1ha2UgdGhlIGV4dHJhIGxpbmUgTWF0aEpheCBhZGRzIGFyb3VuZCBzeW1ib2xzIGxvb2sgc3VwZXIgdGhpY2sgaW4gc29tZSBjYXNlc1xuICAgICAgICAvLyBpdCBsb29rcyBiZXR0ZXIgaWYgdGhpcyBpcyByZW1vdmVkIGVudGlyZWx5LlxuICAgICAgICBzdmcuc2VsZWN0QWxsKCcjTWF0aEpheF9TVkdfZ2x5cGhzIHBhdGgnKVxuICAgICAgICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIDApO1xuICAgIH1cblxuICAgIC8vIGZpeCBmb3IgSUUgbmFtZXNwYWNpbmcgcXVpcms/XG4gICAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xOTYxMDA4OS91bndhbnRlZC1uYW1lc3BhY2VzLW9uLXN2Zy1tYXJrdXAtd2hlbi11c2luZy14bWxzZXJpYWxpemVyLWluLWphdmFzY3JpcHQtd2l0aC1pZVxuICAgIHN2Zy5ub2RlKCkuc2V0QXR0cmlidXRlTlMoeG1sbnNOYW1lc3BhY2VzLnhtbG5zLCAneG1sbnMnLCB4bWxuc05hbWVzcGFjZXMuc3ZnKTtcbiAgICBzdmcubm9kZSgpLnNldEF0dHJpYnV0ZU5TKHhtbG5zTmFtZXNwYWNlcy54bWxucywgJ3htbG5zOnhsaW5rJywgeG1sbnNOYW1lc3BhY2VzLnhsaW5rKTtcblxuICAgIGlmKGZvcm1hdCA9PT0gJ3N2ZycgJiYgc2NhbGUpIHtcbiAgICAgICAgc3ZnLmF0dHIoJ3dpZHRoJywgc2NhbGUgKiB3aWR0aCk7XG4gICAgICAgIHN2Zy5hdHRyKCdoZWlnaHQnLCBzY2FsZSAqIGhlaWdodCk7XG4gICAgICAgIHN2Zy5hdHRyKCd2aWV3Qm94JywgJzAgMCAnICsgd2lkdGggKyAnICcgKyBoZWlnaHQpO1xuICAgIH1cblxuICAgIHZhciBzID0gbmV3IHdpbmRvdy5YTUxTZXJpYWxpemVyKCkuc2VyaWFsaXplVG9TdHJpbmcoc3ZnLm5vZGUoKSk7XG4gICAgcyA9IGh0bWxFbnRpdHlEZWNvZGUocyk7XG4gICAgcyA9IHhtbEVudGl0eUVuY29kZShzKTtcblxuICAgIC8vIEZpeCBxdW90YXRpb25zIGFyb3VuZCBmb250IHN0cmluZ3MgYW5kIGdyYWRpZW50IFVSTHNcbiAgICBzID0gcy5yZXBsYWNlKERVTU1ZX1JFR0VYLCAnXFwnJyk7XG5cbiAgICAvLyBJRSBpcyB2ZXJ5IHN0cmljdCwgc28gd2Ugd2lsbCBuZWVkIHRvIGNsZWFuXG4gICAgLy8gIHN2ZyB3aXRoIHRoZSBmb2xsb3dpbmcgcmVnZXhcbiAgICAvLyAgeWVzIHRoaXMgaXMgbWVzc3ksIGJ1dCBkbyBub3Qga25vdyBhIGJldHRlciB3YXlcbiAgICAvLyBFdmVuIHdpdGggdGhpcyBJRSB3aWxsIG5vdCB3b3JrIGR1ZSB0byB0YWludGVkIGNhbnZhc1xuICAgIC8vICBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2thbmdheC9mYWJyaWMuanMvaXNzdWVzLzE5NTdcbiAgICAvLyAgICAgIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTgxMTIwNDcvY2FudmFzLXRvZGF0YXVybC13b3JraW5nLWluLWFsbC1icm93c2Vycy1leGNlcHQtaWUxMFxuICAgIC8vIExlYXZlIGhlcmUganVzdCBpbiBjYXNlIHRoZSBDT1JTL3RhaW50ZWQgSUUgaXNzdWUgZ2V0cyByZXNvbHZlZFxuICAgIGlmKExpYi5pc0lFKCkpIHtcbiAgICAgICAgLy8gcmVwbGFjZSBkb3VibGUgcXVvdGUgd2l0aCBzaW5nbGUgcXVvdGVcbiAgICAgICAgcyA9IHMucmVwbGFjZSgvXCIvZ2ksICdcXCcnKTtcbiAgICAgICAgLy8gdXJsIGluIHN2ZyBhcmUgc2luZ2xlIHF1b3RlZFxuICAgICAgICAvLyAgIHNpbmNlIHdlIGNoYW5nZWQgZG91YmxlIHRvIHNpbmdsZVxuICAgICAgICAvLyAgIHdlJ2xsIG5lZWQgdG8gY2hhbmdlIHRoZXNlIHRvIGRvdWJsZS1xdW90ZWRcbiAgICAgICAgcyA9IHMucmVwbGFjZSgvKFxcKCcjKShbXiddKikoJ1xcKSkvZ2ksICcoXFxcIiMkMlxcXCIpJyk7XG4gICAgICAgIC8vIGZvbnQgbmFtZXMgd2l0aCBzcGFjZXMgd2lsbCBiZSBlc2NhcGVkIHNpbmdsZS1xdW90ZWRcbiAgICAgICAgLy8gICB3ZSdsbCBuZWVkIHRvIGNoYW5nZSB0aGVzZSB0byBkb3VibGUtcXVvdGVkXG4gICAgICAgIHMgPSBzLnJlcGxhY2UoLyhcXFxcJykvZ2ksICdcXFwiJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHM7XG59O1xuXG59LHtcIi4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlc1wiOjY5NixcIi4uL2xpYlwiOjcxOSxcImQzXCI6MTYzfV0sODU2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG4vLyBhcnJheU9rIGF0dHJpYnV0ZXMsIG1lcmdlIHRoZW0gaW50byBjYWxjZGF0YSBhcnJheVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykgY2RbaV0uaSA9IGk7XG5cbiAgICBMaWIubWVyZ2VBcnJheSh0cmFjZS50ZXh0LCBjZCwgJ3R4Jyk7XG4gICAgTGliLm1lcmdlQXJyYXkodHJhY2UuaG92ZXJ0ZXh0LCBjZCwgJ2h0eCcpO1xuXG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlcjtcbiAgICBpZihtYXJrZXIpIHtcbiAgICAgICAgTGliLm1lcmdlQXJyYXkobWFya2VyLm9wYWNpdHksIGNkLCAnbW8nLCB0cnVlKTtcbiAgICAgICAgTGliLm1lcmdlQXJyYXkobWFya2VyLmNvbG9yLCBjZCwgJ21jJyk7XG5cbiAgICAgICAgdmFyIG1hcmtlckxpbmUgPSBtYXJrZXIubGluZTtcbiAgICAgICAgaWYobWFya2VyTGluZSkge1xuICAgICAgICAgICAgTGliLm1lcmdlQXJyYXkobWFya2VyTGluZS5jb2xvciwgY2QsICdtbGMnKTtcbiAgICAgICAgICAgIExpYi5tZXJnZUFycmF5Q2FzdFBvc2l0aXZlKG1hcmtlckxpbmUud2lkdGgsIGNkLCAnbWx3Jyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOX1dLDg1NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyQXR0cnMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2F0dHJpYnV0ZXMnKTtcbnZhciBob3ZlcnRlbXBsYXRlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlcycpO1xudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgZm9udEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMuanMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIHRleHRGb250QXR0cnMgPSBmb250QXR0cnMoe1xuICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgYXJyYXlPazogdHJ1ZSxcbiAgICBjb2xvckVkaXRUeXBlOiAnc3R5bGUnLFxuICAgIFxufSk7XG5cbnZhciBzY2F0dGVyTWFya2VyQXR0cnMgPSBzY2F0dGVyQXR0cnMubWFya2VyO1xudmFyIHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMgPSBzY2F0dGVyTWFya2VyQXR0cnMubGluZTtcblxudmFyIG1hcmtlckxpbmVXaWR0aCA9IGV4dGVuZEZsYXQoe30sXG4gICAgc2NhdHRlck1hcmtlckxpbmVBdHRycy53aWR0aCwgeyBkZmx0OiAwIH0pO1xuXG52YXIgbWFya2VyTGluZSA9IGV4dGVuZEZsYXQoe1xuICAgIHdpZHRoOiBtYXJrZXJMaW5lV2lkdGgsXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufSwgY29sb3JTY2FsZUF0dHJzKCdtYXJrZXIubGluZScpKTtcblxudmFyIG1hcmtlciA9IGV4dGVuZEZsYXQoe1xuICAgIGxpbmU6IG1hcmtlckxpbmUsXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufSwgY29sb3JTY2FsZUF0dHJzKCdtYXJrZXInKSwge1xuICAgIG9wYWNpdHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB4OiBzY2F0dGVyQXR0cnMueCxcbiAgICB4MDogc2NhdHRlckF0dHJzLngwLFxuICAgIGR4OiBzY2F0dGVyQXR0cnMuZHgsXG4gICAgeTogc2NhdHRlckF0dHJzLnksXG4gICAgeTA6IHNjYXR0ZXJBdHRycy55MCxcbiAgICBkeTogc2NhdHRlckF0dHJzLmR5LFxuXG4gICAgdGV4dDogc2NhdHRlckF0dHJzLnRleHQsXG4gICAgaG92ZXJ0ZXh0OiBzY2F0dGVyQXR0cnMuaG92ZXJ0ZXh0LFxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycyh7fSwge1xuICAgICAgICBrZXlzOiBjb25zdGFudHMuZXZlbnREYXRhS2V5c1xuICAgIH0pLFxuXG4gICAgdGV4dHBvc2l0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWydpbnNpZGUnLCAnb3V0c2lkZScsICdhdXRvJywgJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ25vbmUnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgaW5zaWRldGV4dGFuY2hvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydlbmQnLCAnbWlkZGxlJywgJ3N0YXJ0J10sXG4gICAgICAgIGRmbHQ6ICdlbmQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHRhbmdsZToge1xuICAgICAgICB2YWxUeXBlOiAnYW5nbGUnLFxuICAgICAgICBkZmx0OiAnYXV0bycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGV4dGZvbnQ6IGV4dGVuZEZsYXQoe30sIHRleHRGb250QXR0cnMsIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBpbnNpZGV0ZXh0Zm9udDogZXh0ZW5kRmxhdCh7fSwgdGV4dEZvbnRBdHRycywge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIG91dHNpZGV0ZXh0Zm9udDogZXh0ZW5kRmxhdCh7fSwgdGV4dEZvbnRBdHRycywge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIGNvbnN0cmFpbnRleHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnaW5zaWRlJywgJ291dHNpZGUnLCAnYm90aCcsICdub25lJ10sXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnYm90aCcsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBjbGlwb25heGlzOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuY2xpcG9uYXhpcywge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIG9yaWVudGF0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWyd2JywgJ2gnXSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGJhc2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgb2Zmc2V0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbWFya2VyOiBtYXJrZXIsXG5cbiAgICBvZmZzZXRncm91cDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFsaWdubWVudGdyb3VwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBzZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IHNjYXR0ZXJBdHRycy5zZWxlY3RlZC5tYXJrZXIub3BhY2l0eSxcbiAgICAgICAgICAgIGNvbG9yOiBzY2F0dGVyQXR0cnMuc2VsZWN0ZWQubWFya2VyLmNvbG9yLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICAgICAgfSxcbiAgICAgICAgdGV4dGZvbnQ6IHNjYXR0ZXJBdHRycy5zZWxlY3RlZC50ZXh0Zm9udCxcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICB9LFxuICAgIHVuc2VsZWN0ZWQ6IHtcbiAgICAgICAgbWFya2VyOiB7XG4gICAgICAgICAgICBvcGFjaXR5OiBzY2F0dGVyQXR0cnMudW5zZWxlY3RlZC5tYXJrZXIub3BhY2l0eSxcbiAgICAgICAgICAgIGNvbG9yOiBzY2F0dGVyQXR0cnMudW5zZWxlY3RlZC5tYXJrZXIuY29sb3IsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuICAgICAgICB0ZXh0Zm9udDogc2NhdHRlckF0dHJzLnVuc2VsZWN0ZWQudGV4dGZvbnQsXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfSxcblxuICAgIHI6IHNjYXR0ZXJBdHRycy5yLFxuICAgIHQ6IHNjYXR0ZXJBdHRycy50LFxuXG4gICAgX2RlcHJlY2F0ZWQ6IHtcbiAgICAgICAgYmFyZGlyOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICB2YWx1ZXM6IFsndicsICdoJ10sXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXNcIjo2MDAsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTMsXCIuLi9zY2F0dGVyL2F0dHJpYnV0ZXNcIjoxMTEyLFwiLi9jb25zdGFudHMuanNcIjo4NTl9XSw4NTg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgaGFzQ29sb3JzY2FsZSA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9oZWxwZXJzJykuaGFzQ29sb3JzY2FsZTtcbnZhciBjb2xvcnNjYWxlQ2FsYyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjJyk7XG52YXIgYXJyYXlzVG9DYWxjZGF0YSA9IF9kZXJlcV8oJy4vYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgY2FsY1NlbGVjdGlvbiA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb24nKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciB4YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS54YXhpcyB8fCAneCcpO1xuICAgIHZhciB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS55YXhpcyB8fCAneScpO1xuICAgIHZhciBzaXplLCBwb3M7XG5cbiAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgIHNpemUgPSB4YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd4Jyk7XG4gICAgICAgIHBvcyA9IHlhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3knKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzaXplID0geWEubWFrZUNhbGNkYXRhKHRyYWNlLCAneScpO1xuICAgICAgICBwb3MgPSB4YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd4Jyk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIHRoZSBcImNhbGN1bGF0ZWQgZGF0YVwiIHRvIHBsb3RcbiAgICB2YXIgc2VyaWVzbGVuID0gTWF0aC5taW4ocG9zLmxlbmd0aCwgc2l6ZS5sZW5ndGgpO1xuICAgIHZhciBjZCA9IG5ldyBBcnJheShzZXJpZXNsZW4pO1xuXG4gICAgLy8gc2V0IHBvc2l0aW9uIGFuZCBzaXplXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNlcmllc2xlbjsgaSsrKSB7XG4gICAgICAgIGNkW2ldID0geyBwOiBwb3NbaV0sIHM6IHNpemVbaV0gfTtcblxuICAgICAgICBpZih0cmFjZS5pZHMpIHtcbiAgICAgICAgICAgIGNkW2ldLmlkID0gU3RyaW5nKHRyYWNlLmlkc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhdXRvLXogYW5kIGF1dG9jb2xvcnNjYWxlIGlmIGFwcGxpY2FibGVcbiAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlLCAnbWFya2VyJykpIHtcbiAgICAgICAgY29sb3JzY2FsZUNhbGMoZ2QsIHRyYWNlLCB7XG4gICAgICAgICAgICB2YWxzOiB0cmFjZS5tYXJrZXIuY29sb3IsXG4gICAgICAgICAgICBjb250YWluZXJTdHI6ICdtYXJrZXInLFxuICAgICAgICAgICAgY0xldHRlcjogJ2MnXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlLCAnbWFya2VyLmxpbmUnKSkge1xuICAgICAgICBjb2xvcnNjYWxlQ2FsYyhnZCwgdHJhY2UsIHtcbiAgICAgICAgICAgIHZhbHM6IHRyYWNlLm1hcmtlci5saW5lLmNvbG9yLFxuICAgICAgICAgICAgY29udGFpbmVyU3RyOiAnbWFya2VyLmxpbmUnLFxuICAgICAgICAgICAgY0xldHRlcjogJ2MnXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFycmF5c1RvQ2FsY2RhdGEoY2QsIHRyYWNlKTtcbiAgICBjYWxjU2VsZWN0aW9uKGNkLCB0cmFjZSk7XG5cbiAgICByZXR1cm4gY2Q7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjXCI6NjAxLFwiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hlbHBlcnNcIjo2MDQsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb25cIjoxMTE0LFwiLi9hcnJheXNfdG9fY2FsY2RhdGFcIjo4NTZ9XSw4NTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGV2ZW50RGF0YUtleXM6IFtdXG59O1xuXG59LHt9XSw4NjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGdldEF4aXNHcm91cCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkcycpLmdldEF4aXNHcm91cDtcbnZhciBTaWV2ZSA9IF9kZXJlcV8oJy4vc2lldmUuanMnKTtcblxuLypcbiAqIEJhciBjaGFydCBzdGFja2luZy9ncm91cGluZyBwb3NpdGlvbmluZyBhbmQgYXV0b3NjYWxpbmcgY2FsY3VsYXRpb25zXG4gKiBmb3IgZWFjaCBkaXJlY3Rpb24gc2VwYXJhdGVseSBjYWxjdWxhdGUgdGhlIHJhbmdlcyBhbmQgcG9zaXRpb25zXG4gKiBub3RlIHRoYXQgdGhpcyBoYW5kbGVzIGhpc3RvZ3JhbXMgdG9vXG4gKiBub3cgZG9pbmcgdGhpcyBvbmUgc3VicGxvdCBhdCBhIHRpbWVcbiAqL1xuXG5mdW5jdGlvbiBjcm9zc1RyYWNlQ2FsYyhnZCwgcGxvdGluZm8pIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGZ1bGxUcmFjZXMgPSBnZC5fZnVsbERhdGE7XG4gICAgdmFyIGNhbGNUcmFjZXMgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgY2FsY1RyYWNlc0hvcnogPSBbXTtcbiAgICB2YXIgY2FsY1RyYWNlc1ZlcnQgPSBbXTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmdWxsVHJhY2UgPSBmdWxsVHJhY2VzW2ldO1xuICAgICAgICBpZihcbiAgICAgICAgICAgIGZ1bGxUcmFjZS52aXNpYmxlID09PSB0cnVlICYmXG4gICAgICAgICAgICBSZWdpc3RyeS50cmFjZUlzKGZ1bGxUcmFjZSwgJ2JhcicpICYmXG4gICAgICAgICAgICBmdWxsVHJhY2UueGF4aXMgPT09IHhhLl9pZCAmJlxuICAgICAgICAgICAgZnVsbFRyYWNlLnlheGlzID09PSB5YS5faWRcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBpZihmdWxsVHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICAgICAgICAgIGNhbGNUcmFjZXNIb3J6LnB1c2goY2FsY1RyYWNlc1tpXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGNUcmFjZXNWZXJ0LnB1c2goY2FsY1RyYWNlc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgb3B0cyA9IHtcbiAgICAgICAgbW9kZTogZnVsbExheW91dC5iYXJtb2RlLFxuICAgICAgICBub3JtOiBmdWxsTGF5b3V0LmJhcm5vcm0sXG4gICAgICAgIGdhcDogZnVsbExheW91dC5iYXJnYXAsXG4gICAgICAgIGdyb3VwZ2FwOiBmdWxsTGF5b3V0LmJhcmdyb3VwZ2FwXG4gICAgfTtcblxuICAgIHNldEdyb3VwUG9zaXRpb25zKGdkLCB4YSwgeWEsIGNhbGNUcmFjZXNWZXJ0LCBvcHRzKTtcbiAgICBzZXRHcm91cFBvc2l0aW9ucyhnZCwgeWEsIHhhLCBjYWxjVHJhY2VzSG9yeiwgb3B0cyk7XG59XG5cbmZ1bmN0aW9uIHNldEdyb3VwUG9zaXRpb25zKGdkLCBwYSwgc2EsIGNhbGNUcmFjZXMsIG9wdHMpIHtcbiAgICBpZighY2FsY1RyYWNlcy5sZW5ndGgpIHJldHVybjtcblxuICAgIHZhciBleGNsdWRlZDtcbiAgICB2YXIgaW5jbHVkZWQ7XG4gICAgdmFyIGksIGNhbGNUcmFjZSwgZnVsbFRyYWNlO1xuXG4gICAgaW5pdEJhc2Uoc2EsIGNhbGNUcmFjZXMpO1xuXG4gICAgc3dpdGNoKG9wdHMubW9kZSkge1xuICAgICAgICBjYXNlICdvdmVybGF5JzpcbiAgICAgICAgICAgIHNldEdyb3VwUG9zaXRpb25zSW5PdmVybGF5TW9kZShwYSwgc2EsIGNhbGNUcmFjZXMsIG9wdHMpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnZ3JvdXAnOlxuICAgICAgICAgICAgLy8gZXhjbHVkZSBmcm9tIHRoZSBncm91cCB0aG9zZSB0cmFjZXMgZm9yIHdoaWNoIHRoZSB1c2VyIHNldCBhbiBvZmZzZXRcbiAgICAgICAgICAgIGV4Y2x1ZGVkID0gW107XG4gICAgICAgICAgICBpbmNsdWRlZCA9IFtdO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNhbGNUcmFjZSA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgICAgICAgICAgZnVsbFRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYoZnVsbFRyYWNlLm9mZnNldCA9PT0gdW5kZWZpbmVkKSBpbmNsdWRlZC5wdXNoKGNhbGNUcmFjZSk7XG4gICAgICAgICAgICAgICAgZWxzZSBleGNsdWRlZC5wdXNoKGNhbGNUcmFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGluY2x1ZGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNldEdyb3VwUG9zaXRpb25zSW5Hcm91cE1vZGUoZ2QsIHBhLCBzYSwgaW5jbHVkZWQsIG9wdHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoZXhjbHVkZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgc2V0R3JvdXBQb3NpdGlvbnNJbk92ZXJsYXlNb2RlKHBhLCBzYSwgZXhjbHVkZWQsIG9wdHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnc3RhY2snOlxuICAgICAgICBjYXNlICdyZWxhdGl2ZSc6XG4gICAgICAgICAgICAvLyBleGNsdWRlIGZyb20gdGhlIHN0YWNrIHRob3NlIHRyYWNlcyBmb3Igd2hpY2ggdGhlIHVzZXIgc2V0IGEgYmFzZVxuICAgICAgICAgICAgZXhjbHVkZWQgPSBbXTtcbiAgICAgICAgICAgIGluY2x1ZGVkID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjYWxjVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXTtcbiAgICAgICAgICAgICAgICBmdWxsVHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG5cbiAgICAgICAgICAgICAgICBpZihmdWxsVHJhY2UuYmFzZSA9PT0gdW5kZWZpbmVkKSBpbmNsdWRlZC5wdXNoKGNhbGNUcmFjZSk7XG4gICAgICAgICAgICAgICAgZWxzZSBleGNsdWRlZC5wdXNoKGNhbGNUcmFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGluY2x1ZGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNldEdyb3VwUG9zaXRpb25zSW5TdGFja09yUmVsYXRpdmVNb2RlKGdkLCBwYSwgc2EsIGluY2x1ZGVkLCBvcHRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGV4Y2x1ZGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNldEdyb3VwUG9zaXRpb25zSW5PdmVybGF5TW9kZShwYSwgc2EsIGV4Y2x1ZGVkLCBvcHRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGNvbGxlY3RFeHRlbnRzKGNhbGNUcmFjZXMsIHBhKTtcbn1cblxuZnVuY3Rpb24gaW5pdEJhc2Uoc2EsIGNhbGNUcmFjZXMpIHtcbiAgICB2YXIgaSwgajtcblxuICAgIGZvcihpID0gMDsgaSA8IGNhbGNUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkID0gY2FsY1RyYWNlc1tpXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgICAgIHZhciBiYXNlID0gKHRyYWNlLnR5cGUgPT09ICdmdW5uZWwnKSA/IHRyYWNlLl9iYXNlIDogdHJhY2UuYmFzZTtcbiAgICAgICAgdmFyIGI7XG5cbiAgICAgICAgLy8gbm90IHN1cmUgaWYgaXQgcmVhbGx5IG1ha2VzIHNlbnNlIHRvIGhhdmUgZGF0ZXMgZm9yIGJhciBzaXplIGRhdGEuLi5cbiAgICAgICAgLy8gaWRlYWxseSBpZiB3ZSB3YW50IHRvIG1ha2UgZ2FudHQgY2hhcnRzIG9yIHNvbWV0aGluZyB3ZSdkIHRyZWF0XG4gICAgICAgIC8vIHRoZSBhY3R1YWwgc2l6ZSAodHJhY2UueCBvciB5KSBhcyB0aW1lIGRlbHRhIGJ1dCBiYXNlIGFzIGFic29sdXRlXG4gICAgICAgIC8vIHRpbWUuIEJ1dCBpbmNsdWRlZCBoZXJlIGZvciBjb21wbGV0ZW5lc3MuXG4gICAgICAgIHZhciBzY2FsZW5kYXIgPSB0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnID8gdHJhY2UueGNhbGVuZGFyIDogdHJhY2UueWNhbGVuZGFyO1xuXG4gICAgICAgIC8vICdiYXNlJyBvbiBjYXRlZ29yaWNhbCBheGVzIG1ha2VzIG5vIHNlbnNlXG4gICAgICAgIHZhciBkMmMgPSBzYS50eXBlID09PSAnY2F0ZWdvcnknIHx8IHNhLnR5cGUgPT09ICdtdWx0aWNhdGVnb3J5JyA/XG4gICAgICAgICAgICBmdW5jdGlvbigpIHsgcmV0dXJuIG51bGw7IH0gOlxuICAgICAgICAgICAgc2EuZDJjO1xuXG4gICAgICAgIGlmKGlzQXJyYXlPclR5cGVkQXJyYXkoYmFzZSkpIHtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IE1hdGgubWluKGJhc2UubGVuZ3RoLCBjZC5sZW5ndGgpOyBqKyspIHtcbiAgICAgICAgICAgICAgICBiID0gZDJjKGJhc2Vbal0sIDAsIHNjYWxlbmRhcik7XG4gICAgICAgICAgICAgICAgaWYoaXNOdW1lcmljKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNkW2pdLmIgPSArYjtcbiAgICAgICAgICAgICAgICAgICAgY2Rbal0uaGFzQiA9IDE7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGNkW2pdLmIgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yKDsgaiA8IGNkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgY2Rbal0uYiA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBiID0gZDJjKGJhc2UsIDAsIHNjYWxlbmRhcik7XG4gICAgICAgICAgICB2YXIgaGFzQmFzZSA9IGlzTnVtZXJpYyhiKTtcbiAgICAgICAgICAgIGIgPSBoYXNCYXNlID8gYiA6IDA7XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBjZC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGNkW2pdLmIgPSBiO1xuICAgICAgICAgICAgICAgIGlmKGhhc0Jhc2UpIGNkW2pdLmhhc0IgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzZXRHcm91cFBvc2l0aW9uc0luT3ZlcmxheU1vZGUocGEsIHNhLCBjYWxjVHJhY2VzLCBvcHRzKSB7XG4gICAgLy8gdXBkYXRlIHBvc2l0aW9uIGF4aXMgYW5kIHNldCBiYXIgb2Zmc2V0cyBhbmQgd2lkdGhzXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNUcmFjZSA9IGNhbGNUcmFjZXNbaV07XG5cbiAgICAgICAgdmFyIHNpZXZlID0gbmV3IFNpZXZlKFtjYWxjVHJhY2VdLCB7XG4gICAgICAgICAgICBzZXBOZWdWYWw6IGZhbHNlLFxuICAgICAgICAgICAgb3ZlcmxhcE5vTWVyZ2U6ICFvcHRzLm5vcm1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gc2V0IGJhciBvZmZzZXRzIGFuZCB3aWR0aHMsIGFuZCB1cGRhdGUgcG9zaXRpb24gYXhpc1xuICAgICAgICBzZXRPZmZzZXRBbmRXaWR0aChwYSwgc2lldmUsIG9wdHMpO1xuXG4gICAgICAgIC8vIHNldCBiYXIgYmFzZXMgYW5kIHNpemVzLCBhbmQgdXBkYXRlIHNpemUgYXhpc1xuICAgICAgICAvL1xuICAgICAgICAvLyAobm90ZSB0aGF0IGBzZXRHcm91cFBvc2l0aW9uc0luT3ZlcmxheU1vZGVgIGhhbmRsZXMgdGhlIGNhc2UgYmFybm9ybVxuICAgICAgICAvLyBpcyBkZWZpbmVkLCBiZWNhdXNlIHRoaXMgZnVuY3Rpb24gaXMgYWxzbyBpbnZva2VkIGZvciB0cmFjZXMgdGhhdFxuICAgICAgICAvLyBjYW4ndCBiZSBncm91cGVkIG9yIHN0YWNrZWQpXG4gICAgICAgIGlmKG9wdHMubm9ybSkge1xuICAgICAgICAgICAgc2lldmVCYXJzKHNpZXZlKTtcbiAgICAgICAgICAgIG5vcm1hbGl6ZUJhcnMoc2EsIHNpZXZlLCBvcHRzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldEJhc2VBbmRUb3Aoc2EsIHNpZXZlKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gc2V0R3JvdXBQb3NpdGlvbnNJbkdyb3VwTW9kZShnZCwgcGEsIHNhLCBjYWxjVHJhY2VzLCBvcHRzKSB7XG4gICAgdmFyIHNpZXZlID0gbmV3IFNpZXZlKGNhbGNUcmFjZXMsIHtcbiAgICAgICAgc2VwTmVnVmFsOiBmYWxzZSxcbiAgICAgICAgb3ZlcmxhcE5vTWVyZ2U6ICFvcHRzLm5vcm1cbiAgICB9KTtcblxuICAgIC8vIHNldCBiYXIgb2Zmc2V0cyBhbmQgd2lkdGhzLCBhbmQgdXBkYXRlIHBvc2l0aW9uIGF4aXNcbiAgICBzZXRPZmZzZXRBbmRXaWR0aEluR3JvdXBNb2RlKGdkLCBwYSwgc2lldmUsIG9wdHMpO1xuXG4gICAgLy8gcmVsYXRpdmUtc3RhY2sgYmFycyB3aXRoaW4gdGhlIHNhbWUgdHJhY2UgdGhhdCB3b3VsZCBvdGhlcndpc2VcbiAgICAvLyBiZSBoaWRkZW5cbiAgICB1bmhpZGVCYXJzV2l0aGluVHJhY2Uoc2lldmUpO1xuXG4gICAgLy8gc2V0IGJhciBiYXNlcyBhbmQgc2l6ZXMsIGFuZCB1cGRhdGUgc2l6ZSBheGlzXG4gICAgaWYob3B0cy5ub3JtKSB7XG4gICAgICAgIHNpZXZlQmFycyhzaWV2ZSk7XG4gICAgICAgIG5vcm1hbGl6ZUJhcnMoc2EsIHNpZXZlLCBvcHRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzZXRCYXNlQW5kVG9wKHNhLCBzaWV2ZSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzZXRHcm91cFBvc2l0aW9uc0luU3RhY2tPclJlbGF0aXZlTW9kZShnZCwgcGEsIHNhLCBjYWxjVHJhY2VzLCBvcHRzKSB7XG4gICAgdmFyIHNpZXZlID0gbmV3IFNpZXZlKGNhbGNUcmFjZXMsIHtcbiAgICAgICAgc2VwTmVnVmFsOiBvcHRzLm1vZGUgPT09ICdyZWxhdGl2ZScsXG4gICAgICAgIG92ZXJsYXBOb01lcmdlOiAhKG9wdHMubm9ybSB8fCBvcHRzLm1vZGUgPT09ICdzdGFjaycgfHwgb3B0cy5tb2RlID09PSAncmVsYXRpdmUnKVxuICAgIH0pO1xuXG4gICAgLy8gc2V0IGJhciBvZmZzZXRzIGFuZCB3aWR0aHMsIGFuZCB1cGRhdGUgcG9zaXRpb24gYXhpc1xuICAgIHNldE9mZnNldEFuZFdpZHRoKHBhLCBzaWV2ZSwgb3B0cyk7XG5cbiAgICAvLyBzZXQgYmFyIGJhc2VzIGFuZCBzaXplcywgYW5kIHVwZGF0ZSBzaXplIGF4aXNcbiAgICBzdGFja0JhcnMoc2EsIHNpZXZlLCBvcHRzKTtcblxuICAgIC8vIGZsYWcgdGhlIG91dG1vc3QgYmFyIChmb3IgdGV4dCBkaXNwbGF5IHB1cnBvc2VzKVxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjVHJhY2UgPSBjYWxjVHJhY2VzW2ldO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjYWxjVHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBiYXIgPSBjYWxjVHJhY2Vbal07XG5cbiAgICAgICAgICAgIGlmKGJhci5zICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaXNPdXRtb3N0QmFyID0gKChiYXIuYiArIGJhci5zKSA9PT0gc2lldmUuZ2V0KGJhci5wLCBiYXIucykpO1xuICAgICAgICAgICAgICAgIGlmKGlzT3V0bW9zdEJhcikgYmFyLl9vdXRtb3N0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdGUgdGhhdCBtYXJraW5nIHRoZSBvdXRtb3N0IGJhcnMgaGFzIHRvIGJlIGRvbmVcbiAgICAvLyBiZWZvcmUgYG5vcm1hbGl6ZUJhcnNgIGNoYW5nZXMgYGJhci5iYCBhbmQgYGJhci5zYC5cbiAgICBpZihvcHRzLm5vcm0pIG5vcm1hbGl6ZUJhcnMoc2EsIHNpZXZlLCBvcHRzKTtcbn1cblxuZnVuY3Rpb24gc2V0T2Zmc2V0QW5kV2lkdGgocGEsIHNpZXZlLCBvcHRzKSB7XG4gICAgdmFyIG1pbkRpZmYgPSBzaWV2ZS5taW5EaWZmO1xuICAgIHZhciBjYWxjVHJhY2VzID0gc2lldmUudHJhY2VzO1xuXG4gICAgLy8gc2V0IGJhciBvZmZzZXRzIGFuZCB3aWR0aHNcbiAgICB2YXIgYmFyR3JvdXBXaWR0aCA9IG1pbkRpZmYgKiAoMSAtIG9wdHMuZ2FwKTtcbiAgICB2YXIgYmFyV2lkdGhQbHVzR2FwID0gYmFyR3JvdXBXaWR0aDtcbiAgICB2YXIgYmFyV2lkdGggPSBiYXJXaWR0aFBsdXNHYXAgKiAoMSAtIChvcHRzLmdyb3VwZ2FwIHx8IDApKTtcblxuICAgIC8vIGNvbXB1dGVyIGJhciBncm91cCBjZW50ZXIgYW5kIGJhciBvZmZzZXRcbiAgICB2YXIgb2Zmc2V0RnJvbUNlbnRlciA9IC1iYXJXaWR0aCAvIDI7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXTtcbiAgICAgICAgdmFyIHQgPSBjYWxjVHJhY2VbMF0udDtcblxuICAgICAgICAvLyBzdG9yZSBiYXIgd2lkdGggYW5kIG9mZnNldCBmb3IgdGhpcyB0cmFjZVxuICAgICAgICB0LmJhcndpZHRoID0gYmFyV2lkdGg7XG4gICAgICAgIHQucG9mZnNldCA9IG9mZnNldEZyb21DZW50ZXI7XG4gICAgICAgIHQuYmFyZ3JvdXB3aWR0aCA9IGJhckdyb3VwV2lkdGg7XG4gICAgICAgIHQuYmFyZGVsdGEgPSBtaW5EaWZmO1xuICAgIH1cblxuICAgIC8vIHN0YWNrIGJhcnMgdGhhdCBvbmx5IGRpZmZlciBieSByb3VuZGluZ1xuICAgIHNpZXZlLmJpbldpZHRoID0gY2FsY1RyYWNlc1swXVswXS50LmJhcndpZHRoIC8gMTAwO1xuXG4gICAgLy8gaWYgZGVmaW5lZCwgYXBwbHkgdHJhY2Ugb2Zmc2V0IGFuZCB3aWR0aFxuICAgIGFwcGx5QXR0cmlidXRlcyhzaWV2ZSk7XG5cbiAgICAvLyBzdG9yZSB0aGUgYmFyIGNlbnRlciBpbiBlYWNoIGNhbGNkYXRhIGl0ZW1cbiAgICBzZXRCYXJDZW50ZXJBbmRXaWR0aChwYSwgc2lldmUpO1xuXG4gICAgLy8gdXBkYXRlIHBvc2l0aW9uIGF4ZXNcbiAgICB1cGRhdGVQb3NpdGlvbkF4aXMocGEsIHNpZXZlKTtcbn1cblxuZnVuY3Rpb24gc2V0T2Zmc2V0QW5kV2lkdGhJbkdyb3VwTW9kZShnZCwgcGEsIHNpZXZlLCBvcHRzKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgcG9zaXRpb25zID0gc2lldmUucG9zaXRpb25zO1xuICAgIHZhciBkaXN0aW5jdFBvc2l0aW9ucyA9IHNpZXZlLmRpc3RpbmN0UG9zaXRpb25zO1xuICAgIHZhciBtaW5EaWZmID0gc2lldmUubWluRGlmZjtcbiAgICB2YXIgY2FsY1RyYWNlcyA9IHNpZXZlLnRyYWNlcztcbiAgICB2YXIgblRyYWNlcyA9IGNhbGNUcmFjZXMubGVuZ3RoO1xuXG4gICAgLy8gaWYgdGhlcmUgYXJlbid0IGFueSBvdmVybGFwcGluZyBwb3NpdGlvbnMsXG4gICAgLy8gbGV0IHRoZW0gaGF2ZSBmdWxsIHdpZHRoIGV2ZW4gaWYgbW9kZSBpcyBncm91cFxuICAgIHZhciBvdmVybGFwID0gKHBvc2l0aW9ucy5sZW5ndGggIT09IGRpc3RpbmN0UG9zaXRpb25zLmxlbmd0aCk7XG4gICAgdmFyIGJhckdyb3VwV2lkdGggPSBtaW5EaWZmICogKDEgLSBvcHRzLmdhcCk7XG5cbiAgICB2YXIgZ3JvdXBJZCA9IGdldEF4aXNHcm91cChmdWxsTGF5b3V0LCBwYS5faWQpICsgY2FsY1RyYWNlc1swXVswXS50cmFjZS5vcmllbnRhdGlvbjtcbiAgICB2YXIgYWxpZ25tZW50R3JvdXBzID0gZnVsbExheW91dC5fYWxpZ25tZW50T3B0c1tncm91cElkXSB8fCB7fTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBuVHJhY2VzOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNUcmFjZSA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgICAgICB2YXIgYWxpZ25tZW50R3JvdXBPcHRzID0gYWxpZ25tZW50R3JvdXBzW3RyYWNlLmFsaWdubWVudGdyb3VwXSB8fCB7fTtcbiAgICAgICAgdmFyIG5PZmZzZXRHcm91cHMgPSBPYmplY3Qua2V5cyhhbGlnbm1lbnRHcm91cE9wdHMub2Zmc2V0R3JvdXBzIHx8IHt9KS5sZW5ndGg7XG5cbiAgICAgICAgdmFyIGJhcldpZHRoUGx1c0dhcDtcbiAgICAgICAgaWYobk9mZnNldEdyb3Vwcykge1xuICAgICAgICAgICAgYmFyV2lkdGhQbHVzR2FwID0gYmFyR3JvdXBXaWR0aCAvIG5PZmZzZXRHcm91cHM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBiYXJXaWR0aFBsdXNHYXAgPSBvdmVybGFwID8gYmFyR3JvdXBXaWR0aCAvIG5UcmFjZXMgOiBiYXJHcm91cFdpZHRoO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGJhcldpZHRoID0gYmFyV2lkdGhQbHVzR2FwICogKDEgLSAob3B0cy5ncm91cGdhcCB8fCAwKSk7XG5cbiAgICAgICAgdmFyIG9mZnNldEZyb21DZW50ZXI7XG4gICAgICAgIGlmKG5PZmZzZXRHcm91cHMpIHtcbiAgICAgICAgICAgIG9mZnNldEZyb21DZW50ZXIgPSAoKDIgKiB0cmFjZS5fb2Zmc2V0SW5kZXggKyAxIC0gbk9mZnNldEdyb3VwcykgKiBiYXJXaWR0aFBsdXNHYXAgLSBiYXJXaWR0aCkgLyAyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb2Zmc2V0RnJvbUNlbnRlciA9IG92ZXJsYXAgP1xuICAgICAgICAgICAgICAgICgoMiAqIGkgKyAxIC0gblRyYWNlcykgKiBiYXJXaWR0aFBsdXNHYXAgLSBiYXJXaWR0aCkgLyAyIDpcbiAgICAgICAgICAgICAgICAtYmFyV2lkdGggLyAyO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHQgPSBjYWxjVHJhY2VbMF0udDtcbiAgICAgICAgdC5iYXJ3aWR0aCA9IGJhcldpZHRoO1xuICAgICAgICB0LnBvZmZzZXQgPSBvZmZzZXRGcm9tQ2VudGVyO1xuICAgICAgICB0LmJhcmdyb3Vwd2lkdGggPSBiYXJHcm91cFdpZHRoO1xuICAgICAgICB0LmJhcmRlbHRhID0gbWluRGlmZjtcbiAgICB9XG5cbiAgICAvLyBzdGFjayBiYXJzIHRoYXQgb25seSBkaWZmZXIgYnkgcm91bmRpbmdcbiAgICBzaWV2ZS5iaW5XaWR0aCA9IGNhbGNUcmFjZXNbMF1bMF0udC5iYXJ3aWR0aCAvIDEwMDtcblxuICAgIC8vIGlmIGRlZmluZWQsIGFwcGx5IHRyYWNlIHdpZHRoXG4gICAgYXBwbHlBdHRyaWJ1dGVzKHNpZXZlKTtcblxuICAgIC8vIHN0b3JlIHRoZSBiYXIgY2VudGVyIGluIGVhY2ggY2FsY2RhdGEgaXRlbVxuICAgIHNldEJhckNlbnRlckFuZFdpZHRoKHBhLCBzaWV2ZSk7XG5cbiAgICAvLyB1cGRhdGUgcG9zaXRpb24gYXhlc1xuICAgIHVwZGF0ZVBvc2l0aW9uQXhpcyhwYSwgc2lldmUsIG92ZXJsYXApO1xufVxuXG5mdW5jdGlvbiBhcHBseUF0dHJpYnV0ZXMoc2lldmUpIHtcbiAgICB2YXIgY2FsY1RyYWNlcyA9IHNpZXZlLnRyYWNlcztcbiAgICB2YXIgaSwgajtcblxuICAgIGZvcihpID0gMDsgaSA8IGNhbGNUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNUcmFjZSA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgIHZhciBjYWxjVHJhY2UwID0gY2FsY1RyYWNlWzBdO1xuICAgICAgICB2YXIgZnVsbFRyYWNlID0gY2FsY1RyYWNlMC50cmFjZTtcbiAgICAgICAgdmFyIHQgPSBjYWxjVHJhY2UwLnQ7XG4gICAgICAgIHZhciBvZmZzZXQgPSBmdWxsVHJhY2UuX29mZnNldCB8fCBmdWxsVHJhY2Uub2Zmc2V0O1xuICAgICAgICB2YXIgaW5pdGlhbFBvZmZzZXQgPSB0LnBvZmZzZXQ7XG4gICAgICAgIHZhciBuZXdQb2Zmc2V0O1xuXG4gICAgICAgIGlmKGlzQXJyYXlPclR5cGVkQXJyYXkob2Zmc2V0KSkge1xuICAgICAgICAgICAgLy8gaWYgb2Zmc2V0IGlzIGFuIGFycmF5LCB0aGVuIGNsb25lIGl0IGludG8gdC5wb2Zmc2V0LlxuICAgICAgICAgICAgbmV3UG9mZnNldCA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKG9mZnNldCwgMCwgY2FsY1RyYWNlLmxlbmd0aCk7XG5cbiAgICAgICAgICAgIC8vIGd1YXJkIGFnYWluc3Qgbm9uLW51bWVyaWMgaXRlbXNcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5ld1BvZmZzZXQubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZighaXNOdW1lcmljKG5ld1BvZmZzZXRbal0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld1BvZmZzZXRbal0gPSBpbml0aWFsUG9mZnNldDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGlmIHRoZSBsZW5ndGggb2YgdGhlIGFycmF5IGlzIHRvbyBzaG9ydCxcbiAgICAgICAgICAgIC8vIHRoZW4gZXh0ZW5kIGl0IHdpdGggdGhlIGluaXRpYWwgdmFsdWUgb2YgdC5wb2Zmc2V0XG4gICAgICAgICAgICBmb3IoaiA9IG5ld1BvZmZzZXQubGVuZ3RoOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgbmV3UG9mZnNldC5wdXNoKGluaXRpYWxQb2Zmc2V0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdC5wb2Zmc2V0ID0gbmV3UG9mZnNldDtcbiAgICAgICAgfSBlbHNlIGlmKG9mZnNldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0LnBvZmZzZXQgPSBvZmZzZXQ7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgd2lkdGggPSBmdWxsVHJhY2UuX3dpZHRoIHx8IGZ1bGxUcmFjZS53aWR0aDtcbiAgICAgICAgdmFyIGluaXRpYWxCYXJ3aWR0aCA9IHQuYmFyd2lkdGg7XG5cbiAgICAgICAgaWYoaXNBcnJheU9yVHlwZWRBcnJheSh3aWR0aCkpIHtcbiAgICAgICAgICAgIC8vIGlmIHdpZHRoIGlzIGFuIGFycmF5LCB0aGVuIGNsb25lIGl0IGludG8gdC5iYXJ3aWR0aC5cbiAgICAgICAgICAgIHZhciBuZXdCYXJ3aWR0aCA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHdpZHRoLCAwLCBjYWxjVHJhY2UubGVuZ3RoKTtcblxuICAgICAgICAgICAgLy8gZ3VhcmQgYWdhaW5zdCBub24tbnVtZXJpYyBpdGVtc1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbmV3QmFyd2lkdGgubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBpZighaXNOdW1lcmljKG5ld0JhcndpZHRoW2pdKSkgbmV3QmFyd2lkdGhbal0gPSBpbml0aWFsQmFyd2lkdGg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGlmIHRoZSBsZW5ndGggb2YgdGhlIGFycmF5IGlzIHRvbyBzaG9ydCxcbiAgICAgICAgICAgIC8vIHRoZW4gZXh0ZW5kIGl0IHdpdGggdGhlIGluaXRpYWwgdmFsdWUgb2YgdC5iYXJ3aWR0aFxuICAgICAgICAgICAgZm9yKGogPSBuZXdCYXJ3aWR0aC5sZW5ndGg7IGogPCBjYWxjVHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBuZXdCYXJ3aWR0aC5wdXNoKGluaXRpYWxCYXJ3aWR0aCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHQuYmFyd2lkdGggPSBuZXdCYXJ3aWR0aDtcblxuICAgICAgICAgICAgLy8gaWYgdXNlciBkaWRuJ3Qgc2V0IG9mZnNldCxcbiAgICAgICAgICAgIC8vIHRoZW4gY29ycmVjdCB0LnBvZmZzZXQgdG8gZW5zdXJlIGJhcnMgcmVtYWluIGNlbnRlcmVkXG4gICAgICAgICAgICBpZihvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIG5ld1BvZmZzZXQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBjYWxjVHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3UG9mZnNldC5wdXNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbFBvZmZzZXQgKyAoaW5pdGlhbEJhcndpZHRoIC0gbmV3QmFyd2lkdGhbal0pIC8gMlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0LnBvZmZzZXQgPSBuZXdQb2Zmc2V0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYod2lkdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdC5iYXJ3aWR0aCA9IHdpZHRoO1xuXG4gICAgICAgICAgICAvLyBpZiB1c2VyIGRpZG4ndCBzZXQgb2Zmc2V0LFxuICAgICAgICAgICAgLy8gdGhlbiBjb3JyZWN0IHQucG9mZnNldCB0byBlbnN1cmUgYmFycyByZW1haW4gY2VudGVyZWRcbiAgICAgICAgICAgIGlmKG9mZnNldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdC5wb2Zmc2V0ID0gaW5pdGlhbFBvZmZzZXQgKyAoaW5pdGlhbEJhcndpZHRoIC0gd2lkdGgpIC8gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gc2V0QmFyQ2VudGVyQW5kV2lkdGgocGEsIHNpZXZlKSB7XG4gICAgdmFyIGNhbGNUcmFjZXMgPSBzaWV2ZS50cmFjZXM7XG4gICAgdmFyIHBMZXR0ZXIgPSBnZXRBeGlzTGV0dGVyKHBhKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjVHJhY2UgPSBjYWxjVHJhY2VzW2ldO1xuICAgICAgICB2YXIgdCA9IGNhbGNUcmFjZVswXS50O1xuICAgICAgICB2YXIgcG9mZnNldCA9IHQucG9mZnNldDtcbiAgICAgICAgdmFyIHBvZmZzZXRJc0FycmF5ID0gQXJyYXkuaXNBcnJheShwb2Zmc2V0KTtcbiAgICAgICAgdmFyIGJhcndpZHRoID0gdC5iYXJ3aWR0aDtcbiAgICAgICAgdmFyIGJhcndpZHRoSXNBcnJheSA9IEFycmF5LmlzQXJyYXkoYmFyd2lkdGgpO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjYWxjVHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBjYWxjQmFyID0gY2FsY1RyYWNlW2pdO1xuXG4gICAgICAgICAgICAvLyBzdG9yZSB0aGUgYWN0dWFsIGJhciB3aWR0aCBhbmQgcG9zaXRpb24sIGZvciB1c2UgYnkgaG92ZXJcbiAgICAgICAgICAgIHZhciB3aWR0aCA9IGNhbGNCYXIudyA9IGJhcndpZHRoSXNBcnJheSA/IGJhcndpZHRoW2pdIDogYmFyd2lkdGg7XG4gICAgICAgICAgICBjYWxjQmFyW3BMZXR0ZXJdID0gY2FsY0Jhci5wICsgKHBvZmZzZXRJc0FycmF5ID8gcG9mZnNldFtqXSA6IHBvZmZzZXQpICsgd2lkdGggLyAyO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVQb3NpdGlvbkF4aXMocGEsIHNpZXZlLCBhbGxvd01pbkR0aWNrKSB7XG4gICAgdmFyIGNhbGNUcmFjZXMgPSBzaWV2ZS50cmFjZXM7XG4gICAgdmFyIG1pbkRpZmYgPSBzaWV2ZS5taW5EaWZmO1xuICAgIHZhciB2cGFkID0gbWluRGlmZiAvIDI7XG5cbiAgICBBeGVzLm1pbkR0aWNrKHBhLCBzaWV2ZS5taW5EaWZmLCBzaWV2ZS5kaXN0aW5jdFBvc2l0aW9uc1swXSwgYWxsb3dNaW5EdGljayk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXTtcbiAgICAgICAgdmFyIGNhbGNUcmFjZTAgPSBjYWxjVHJhY2VbMF07XG4gICAgICAgIHZhciBmdWxsVHJhY2UgPSBjYWxjVHJhY2UwLnRyYWNlO1xuICAgICAgICB2YXIgcHRzID0gW107XG4gICAgICAgIHZhciBiYXIsIGwsIHIsIGo7XG5cbiAgICAgICAgZm9yKGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBiYXIgPSBjYWxjVHJhY2Vbal07XG4gICAgICAgICAgICBsID0gYmFyLnAgLSB2cGFkO1xuICAgICAgICAgICAgciA9IGJhci5wICsgdnBhZDtcbiAgICAgICAgICAgIHB0cy5wdXNoKGwsIHIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZnVsbFRyYWNlLndpZHRoIHx8IGZ1bGxUcmFjZS5vZmZzZXQpIHtcbiAgICAgICAgICAgIHZhciB0ID0gY2FsY1RyYWNlMC50O1xuICAgICAgICAgICAgdmFyIHBvZmZzZXQgPSB0LnBvZmZzZXQ7XG4gICAgICAgICAgICB2YXIgYmFyd2lkdGggPSB0LmJhcndpZHRoO1xuICAgICAgICAgICAgdmFyIHBvZmZzZXRJc0FycmF5ID0gQXJyYXkuaXNBcnJheShwb2Zmc2V0KTtcbiAgICAgICAgICAgIHZhciBiYXJ3aWR0aElzQXJyYXkgPSBBcnJheS5pc0FycmF5KGJhcndpZHRoKTtcblxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgYmFyID0gY2FsY1RyYWNlW2pdO1xuICAgICAgICAgICAgICAgIHZhciBjYWxjQmFyT2Zmc2V0ID0gcG9mZnNldElzQXJyYXkgPyBwb2Zmc2V0W2pdIDogcG9mZnNldDtcbiAgICAgICAgICAgICAgICB2YXIgY2FsY0JhcldpZHRoID0gYmFyd2lkdGhJc0FycmF5ID8gYmFyd2lkdGhbal0gOiBiYXJ3aWR0aDtcbiAgICAgICAgICAgICAgICBsID0gYmFyLnAgKyBjYWxjQmFyT2Zmc2V0O1xuICAgICAgICAgICAgICAgIHIgPSBsICsgY2FsY0JhcldpZHRoO1xuICAgICAgICAgICAgICAgIHB0cy5wdXNoKGwsIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVsbFRyYWNlLl9leHRyZW1lc1twYS5faWRdID0gQXhlcy5maW5kRXh0cmVtZXMocGEsIHB0cywge3BhZGRlZDogZmFsc2V9KTtcbiAgICB9XG59XG5cbi8vIHN0b3JlIHRoZXNlIGJhciBiYXNlcyBhbmQgdG9wcyBpbiBjYWxjZGF0YVxuLy8gYW5kIG1ha2Ugc3VyZSB0aGUgc2l6ZSBheGlzIGluY2x1ZGVzIHplcm8sXG4vLyBhbG9uZyB3aXRoIHRoZSBiYXNlcyBhbmQgdG9wcyBvZiBlYWNoIGJhci5cbmZ1bmN0aW9uIHNldEJhc2VBbmRUb3Aoc2EsIHNpZXZlKSB7XG4gICAgdmFyIGNhbGNUcmFjZXMgPSBzaWV2ZS50cmFjZXM7XG4gICAgdmFyIHNMZXR0ZXIgPSBnZXRBeGlzTGV0dGVyKHNhKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjVHJhY2UgPSBjYWxjVHJhY2VzW2ldO1xuICAgICAgICB2YXIgZnVsbFRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgICAgICB2YXIgcHRzID0gW107XG4gICAgICAgIHZhciBhbGxCYXNlQWJvdmVaZXJvID0gdHJ1ZTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgYmFyID0gY2FsY1RyYWNlW2pdO1xuICAgICAgICAgICAgdmFyIGJhc2UgPSBiYXIuYjtcbiAgICAgICAgICAgIHZhciB0b3AgPSBiYXNlICsgYmFyLnM7XG5cbiAgICAgICAgICAgIGJhcltzTGV0dGVyXSA9IHRvcDtcbiAgICAgICAgICAgIHB0cy5wdXNoKHRvcCk7XG4gICAgICAgICAgICBpZihiYXIuaGFzQikgcHRzLnB1c2goYmFzZSk7XG5cbiAgICAgICAgICAgIGlmKCFiYXIuaGFzQiB8fCAhKGJhci5iID4gMCAmJiBiYXIucyA+IDApKSB7XG4gICAgICAgICAgICAgICAgYWxsQmFzZUFib3ZlWmVybyA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVsbFRyYWNlLl9leHRyZW1lc1tzYS5faWRdID0gQXhlcy5maW5kRXh0cmVtZXMoc2EsIHB0cywge1xuICAgICAgICAgICAgdG96ZXJvOiAhYWxsQmFzZUFib3ZlWmVybyxcbiAgICAgICAgICAgIHBhZGRlZDogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHN0YWNrQmFycyhzYSwgc2lldmUsIG9wdHMpIHtcbiAgICB2YXIgc0xldHRlciA9IGdldEF4aXNMZXR0ZXIoc2EpO1xuICAgIHZhciBjYWxjVHJhY2VzID0gc2lldmUudHJhY2VzO1xuICAgIHZhciBjYWxjVHJhY2U7XG4gICAgdmFyIGZ1bGxUcmFjZTtcbiAgICB2YXIgaXNGdW5uZWw7XG4gICAgdmFyIGksIGo7XG4gICAgdmFyIGJhcjtcblxuICAgIGZvcihpID0gMDsgaSA8IGNhbGNUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXTtcbiAgICAgICAgZnVsbFRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuXG4gICAgICAgIGlmKGZ1bGxUcmFjZS50eXBlID09PSAnZnVubmVsJykge1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgYmFyID0gY2FsY1RyYWNlW2pdO1xuXG4gICAgICAgICAgICAgICAgaWYoYmFyLnMgIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjcmVhdGUgYmFzZSBvZiBmdW5uZWxzXG4gICAgICAgICAgICAgICAgICAgIHNpZXZlLnB1dChiYXIucCwgLTAuNSAqIGJhci5zKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBjYWxjVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNhbGNUcmFjZSA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgIGZ1bGxUcmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgICAgICBpc0Z1bm5lbCA9IChmdWxsVHJhY2UudHlwZSA9PT0gJ2Z1bm5lbCcpO1xuXG4gICAgICAgIHZhciBwdHMgPSBbXTtcblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBjYWxjVHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGJhciA9IGNhbGNUcmFjZVtqXTtcblxuICAgICAgICAgICAgaWYoYmFyLnMgIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgIC8vIHN0YWNrIGN1cnJlbnQgYmFyIGFuZCBnZXQgcHJldmlvdXMgc3VtXG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlO1xuICAgICAgICAgICAgICAgIGlmKGlzRnVubmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gYmFyLnM7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBiYXIucyArIGJhci5iO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBiYXNlID0gc2lldmUucHV0KGJhci5wLCB2YWx1ZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgdG9wID0gYmFzZSArIHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgLy8gc3RvcmUgdGhlIGJhciBiYXNlIGFuZCB0b3AgaW4gZWFjaCBjYWxjZGF0YSBpdGVtXG4gICAgICAgICAgICAgICAgYmFyLmIgPSBiYXNlO1xuICAgICAgICAgICAgICAgIGJhcltzTGV0dGVyXSA9IHRvcDtcblxuICAgICAgICAgICAgICAgIGlmKCFvcHRzLm5vcm0pIHtcbiAgICAgICAgICAgICAgICAgICAgcHRzLnB1c2godG9wKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoYmFyLmhhc0IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB0cy5wdXNoKGJhc2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgYmFybm9ybSBpcyBzZXQsIGxldCBub3JtYWxpemVCYXJzIHVwZGF0ZSB0aGUgYXhpcyByYW5nZVxuICAgICAgICBpZighb3B0cy5ub3JtKSB7XG4gICAgICAgICAgICBmdWxsVHJhY2UuX2V4dHJlbWVzW3NhLl9pZF0gPSBBeGVzLmZpbmRFeHRyZW1lcyhzYSwgcHRzLCB7XG4gICAgICAgICAgICAgICAgLy8gTi5CLiB3ZSBkb24ndCBzdGFjayBiYXNlIHdpdGggJ2Jhc2UnLFxuICAgICAgICAgICAgICAgIC8vIHNvIHNldCB0b3plcm86dHJ1ZSBhbHdheXMhXG4gICAgICAgICAgICAgICAgdG96ZXJvOiB0cnVlLFxuICAgICAgICAgICAgICAgIHBhZGRlZDogdHJ1ZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNpZXZlQmFycyhzaWV2ZSkge1xuICAgIHZhciBjYWxjVHJhY2VzID0gc2lldmUudHJhY2VzO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNUcmFjZSA9IGNhbGNUcmFjZXNbaV07XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNhbGNUcmFjZS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGJhciA9IGNhbGNUcmFjZVtqXTtcblxuICAgICAgICAgICAgaWYoYmFyLnMgIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgIHNpZXZlLnB1dChiYXIucCwgYmFyLmIgKyBiYXIucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHVuaGlkZUJhcnNXaXRoaW5UcmFjZShzaWV2ZSkge1xuICAgIHZhciBjYWxjVHJhY2VzID0gc2lldmUudHJhY2VzO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNhbGNUcmFjZSA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgIHZhciBmdWxsVHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG5cbiAgICAgICAgaWYoZnVsbFRyYWNlLmJhc2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdmFyIGluVHJhY2VTaWV2ZSA9IG5ldyBTaWV2ZShbY2FsY1RyYWNlXSwge1xuICAgICAgICAgICAgICAgIHNlcE5lZ1ZhbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBvdmVybGFwTm9NZXJnZTogdHJ1ZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjYWxjVHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgYmFyID0gY2FsY1RyYWNlW2pdO1xuXG4gICAgICAgICAgICAgICAgaWYoYmFyLnAgIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBzdGFjayBjdXJyZW50IGJhciBhbmQgZ2V0IHByZXZpb3VzIHN1bVxuICAgICAgICAgICAgICAgICAgICB2YXIgYmFzZSA9IGluVHJhY2VTaWV2ZS5wdXQoYmFyLnAsIGJhci5iICsgYmFyLnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIHByZXZpb3VzIHN1bSBpZiBub24temVybywgdGhpcyBtZWFuczpcbiAgICAgICAgICAgICAgICAgICAgLy8gbXVsdGlwbGUgYmFycyBoYXZlIHNhbWUgc3RhcnRpbmcgcG9pbnQgYXJlIHBvdGVudGlhbGx5IGhpZGRlbixcbiAgICAgICAgICAgICAgICAgICAgLy8gc2hpZnQgdGhlbSB2ZXJ0aWNhbGx5IHNvIHRoYXQgYWxsIGJhcnMgYXJlIHZpc2libGUgYnkgZGVmYXVsdFxuICAgICAgICAgICAgICAgICAgICBpZihiYXNlKSBiYXIuYiA9IGJhc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyBOb3RlOlxuLy9cbi8vIG5vcm1hbGl6ZUJhcnMgcmVxdWlyZXMgdGhhdCBlaXRoZXIgc2lldmVCYXJzIG9yIHN0YWNrQmFycyBoYXMgYmVlblxuLy8gcHJldmlvdXNseSBpbnZva2VkLlxuZnVuY3Rpb24gbm9ybWFsaXplQmFycyhzYSwgc2lldmUsIG9wdHMpIHtcbiAgICB2YXIgY2FsY1RyYWNlcyA9IHNpZXZlLnRyYWNlcztcbiAgICB2YXIgc0xldHRlciA9IGdldEF4aXNMZXR0ZXIoc2EpO1xuICAgIHZhciBzVG9wID0gb3B0cy5ub3JtID09PSAnZnJhY3Rpb24nID8gMSA6IDEwMDtcbiAgICB2YXIgc1RpbnkgPSBzVG9wIC8gMWU5OyAvLyBpbiBjYXNlIG9mIHJvdW5kaW5nIGVycm9yIGluIHN1bVxuICAgIHZhciBzTWluID0gc2EubDJjKHNhLmMybCgwKSk7XG4gICAgdmFyIHNNYXggPSBvcHRzLm1vZGUgPT09ICdzdGFjaycgPyBzVG9wIDogc01pbjtcblxuICAgIGZ1bmN0aW9uIG5lZWRzUGFkZGluZyh2KSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBpc051bWVyaWMoc2EuYzJsKHYpKSAmJlxuICAgICAgICAgICAgKCh2IDwgc01pbiAtIHNUaW55KSB8fCAodiA+IHNNYXggKyBzVGlueSkgfHwgIWlzTnVtZXJpYyhzTWluKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1RyYWNlID0gY2FsY1RyYWNlc1tpXTtcbiAgICAgICAgdmFyIGZ1bGxUcmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcbiAgICAgICAgdmFyIHB0cyA9IFtdO1xuICAgICAgICB2YXIgYWxsQmFzZUFib3ZlWmVybyA9IHRydWU7XG4gICAgICAgIHZhciBwYWRkZWQgPSBmYWxzZTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgYmFyID0gY2FsY1RyYWNlW2pdO1xuXG4gICAgICAgICAgICBpZihiYXIucyAhPT0gQkFETlVNKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNjYWxlID0gTWF0aC5hYnMoc1RvcCAvIHNpZXZlLmdldChiYXIucCwgYmFyLnMpKTtcbiAgICAgICAgICAgICAgICBiYXIuYiAqPSBzY2FsZTtcbiAgICAgICAgICAgICAgICBiYXIucyAqPSBzY2FsZTtcblxuICAgICAgICAgICAgICAgIHZhciBiYXNlID0gYmFyLmI7XG4gICAgICAgICAgICAgICAgdmFyIHRvcCA9IGJhc2UgKyBiYXIucztcblxuICAgICAgICAgICAgICAgIGJhcltzTGV0dGVyXSA9IHRvcDtcbiAgICAgICAgICAgICAgICBwdHMucHVzaCh0b3ApO1xuICAgICAgICAgICAgICAgIHBhZGRlZCA9IHBhZGRlZCB8fCBuZWVkc1BhZGRpbmcodG9wKTtcblxuICAgICAgICAgICAgICAgIGlmKGJhci5oYXNCKSB7XG4gICAgICAgICAgICAgICAgICAgIHB0cy5wdXNoKGJhc2UpO1xuICAgICAgICAgICAgICAgICAgICBwYWRkZWQgPSBwYWRkZWQgfHwgbmVlZHNQYWRkaW5nKGJhc2UpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKCFiYXIuaGFzQiB8fCAhKGJhci5iID4gMCAmJiBiYXIucyA+IDApKSB7XG4gICAgICAgICAgICAgICAgICAgIGFsbEJhc2VBYm92ZVplcm8gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdWxsVHJhY2UuX2V4dHJlbWVzW3NhLl9pZF0gPSBBeGVzLmZpbmRFeHRyZW1lcyhzYSwgcHRzLCB7XG4gICAgICAgICAgICB0b3plcm86ICFhbGxCYXNlQWJvdmVaZXJvLFxuICAgICAgICAgICAgcGFkZGVkOiBwYWRkZWRcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG4vLyBmaW5kIHRoZSBmdWxsIHBvc2l0aW9uIHNwYW4gb2YgYmFycyBhdCBlYWNoIHBvc2l0aW9uXG4vLyBmb3IgdXNlIGJ5IGhvdmVyLCB0byBlbnN1cmUgbGFiZWxzIG1vdmUgaW4gaWYgYmFycyBhcmVcbi8vIG5hcnJvd2VyIHRoYW4gdGhlIHNwYWNlIHRoZXkncmUgaW4uXG4vLyBydW4gb25jZSBwZXIgdHJhY2UgZ3JvdXAgKHN1YnBsb3QgJiBkaXJlY3Rpb24pIGFuZFxuLy8gdGhlIHNhbWUgbWFwcGluZyBpcyBhdHRhY2hlZCB0byBhbGwgY2FsY2RhdGEgdHJhY2VzXG5mdW5jdGlvbiBjb2xsZWN0RXh0ZW50cyhjYWxjVHJhY2VzLCBwYSkge1xuICAgIHZhciBwTGV0dGVyID0gZ2V0QXhpc0xldHRlcihwYSk7XG4gICAgdmFyIGV4dGVudHMgPSB7fTtcbiAgICB2YXIgaSwgaiwgY2Q7XG5cbiAgICB2YXIgcE1pbiA9IEluZmluaXR5O1xuICAgIHZhciBwTWF4ID0gLUluZmluaXR5O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjZCA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgIGZvcihqID0gMDsgaiA8IGNkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgcCA9IGNkW2pdLnA7XG4gICAgICAgICAgICBpZihpc051bWVyaWMocCkpIHtcbiAgICAgICAgICAgICAgICBwTWluID0gTWF0aC5taW4ocE1pbiwgcCk7XG4gICAgICAgICAgICAgICAgcE1heCA9IE1hdGgubWF4KHBNYXgsIHApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGhpcyBpcyBqdXN0IGZvciBwb3NpdGlvbmluZyBvZiBob3ZlciBsYWJlbHMsIGFuZCBub2JvZHkgd2lsbCBjYXJlIGlmXG4gICAgLy8gdGhlIGxhYmVsIGlzIDFweCB0b28gZmFyIG91dDsgc28gcm91bmQgcG9zaXRpb25zIHRvIDEvMTBLIGluIGNhc2VcbiAgICAvLyBwb3NpdGlvbiB2YWx1ZXMgZG9uJ3QgZXhhY3RseSBtYXRjaCBmcm9tIHRyYWNlIHRvIHRyYWNlXG4gICAgdmFyIHJvdW5kRmFjdG9yID0gMTAwMDAgLyAocE1heCAtIHBNaW4pO1xuICAgIHZhciByb3VuZCA9IGV4dGVudHMucm91bmQgPSBmdW5jdGlvbihwKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcoTWF0aC5yb3VuZChyb3VuZEZhY3RvciAqIChwIC0gcE1pbikpKTtcbiAgICB9O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjZCA9IGNhbGNUcmFjZXNbaV07XG4gICAgICAgIGNkWzBdLnQuZXh0ZW50cyA9IGV4dGVudHM7XG5cbiAgICAgICAgdmFyIHBvZmZzZXQgPSBjZFswXS50LnBvZmZzZXQ7XG4gICAgICAgIHZhciBwb2Zmc2V0SXNBcnJheSA9IEFycmF5LmlzQXJyYXkocG9mZnNldCk7XG5cbiAgICAgICAgZm9yKGogPSAwOyBqIDwgY2QubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBkaSA9IGNkW2pdO1xuICAgICAgICAgICAgdmFyIHAwID0gZGlbcExldHRlcl0gLSBkaS53IC8gMjtcblxuICAgICAgICAgICAgaWYoaXNOdW1lcmljKHAwKSkge1xuICAgICAgICAgICAgICAgIHZhciBwMSA9IGRpW3BMZXR0ZXJdICsgZGkudyAvIDI7XG4gICAgICAgICAgICAgICAgdmFyIHBWYWwgPSByb3VuZChkaS5wKTtcbiAgICAgICAgICAgICAgICBpZihleHRlbnRzW3BWYWxdKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4dGVudHNbcFZhbF0gPSBbTWF0aC5taW4ocDAsIGV4dGVudHNbcFZhbF1bMF0pLCBNYXRoLm1heChwMSwgZXh0ZW50c1twVmFsXVsxXSldO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGV4dGVudHNbcFZhbF0gPSBbcDAsIHAxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRpLnAwID0gZGkucCArIChwb2Zmc2V0SXNBcnJheSA/IHBvZmZzZXRbal0gOiBwb2Zmc2V0KTtcbiAgICAgICAgICAgIGRpLnAxID0gZGkucDAgKyBkaS53O1xuICAgICAgICAgICAgZGkuczAgPSBkaS5iO1xuICAgICAgICAgICAgZGkuczEgPSBkaS5zMCArIGRpLnM7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldEF4aXNMZXR0ZXIoYXgpIHtcbiAgICByZXR1cm4gYXguX2lkLmNoYXJBdCgwKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY3Jvc3NUcmFjZUNhbGM6IGNyb3NzVHJhY2VDYWxjLFxuICAgIHNldEdyb3VwUG9zaXRpb25zOiBzZXRHcm91cFBvc2l0aW9uc1xufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHNcIjo3NzAsXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4vc2lldmUuanNcIjo4NjksXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDg2MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG5cbnZhciBoYW5kbGVYWURlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci94eV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVN0eWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuL3N0eWxlX2RlZmF1bHRzJyk7XG52YXIgZ2V0QXhpc0dyb3VwID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJykuZ2V0QXhpc0dyb3VwO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxudmFyIGNvZXJjZUZvbnQgPSBMaWIuY29lcmNlRm9udDtcblxuZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsZW4gPSBoYW5kbGVYWURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ29yaWVudGF0aW9uJywgKHRyYWNlT3V0LnggJiYgIXRyYWNlT3V0LnkpID8gJ2gnIDogJ3YnKTtcbiAgICBjb2VyY2UoJ2Jhc2UnKTtcbiAgICBjb2VyY2UoJ29mZnNldCcpO1xuICAgIGNvZXJjZSgnd2lkdGgnKTtcblxuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG5cbiAgICB2YXIgdGV4dHBvc2l0aW9uID0gY29lcmNlKCd0ZXh0cG9zaXRpb24nKTtcbiAgICBoYW5kbGVUZXh0KHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwgdGV4dHBvc2l0aW9uLCB7XG4gICAgICAgIG1vZHVsZUhhc1NlbGVjdGVkOiB0cnVlLFxuICAgICAgICBtb2R1bGVIYXNVbnNlbGVjdGVkOiB0cnVlLFxuICAgICAgICBtb2R1bGVIYXNDb25zdHJhaW46IHRydWUsXG4gICAgICAgIG1vZHVsZUhhc0NsaXBvbmF4aXM6IHRydWUsXG4gICAgICAgIG1vZHVsZUhhc1RleHRhbmdsZTogdHJ1ZSxcbiAgICAgICAgbW9kdWxlSGFzSW5zaWRlYW5jaG9yOiB0cnVlXG4gICAgfSk7XG5cbiAgICBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGRlZmF1bHRDb2xvciwgbGF5b3V0KTtcblxuICAgIHZhciBsaW5lQ29sb3IgPSAodHJhY2VPdXQubWFya2VyLmxpbmUgfHwge30pLmNvbG9yO1xuXG4gICAgLy8gb3ZlcnJpZGUgZGVmYXVsdENvbG9yIGZvciBlcnJvciBiYXJzIHdpdGggZGVmYXVsdExpbmVcbiAgICB2YXIgZXJyb3JCYXJzU3VwcGx5RGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdzdXBwbHlEZWZhdWx0cycpO1xuICAgIGVycm9yQmFyc1N1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsaW5lQ29sb3IgfHwgQ29sb3IuZGVmYXVsdExpbmUsIHtheGlzOiAneSd9KTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGluZUNvbG9yIHx8IENvbG9yLmRlZmF1bHRMaW5lLCB7YXhpczogJ3gnLCBpbmhlcml0OiAneSd9KTtcblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVHcm91cGluZ0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBmdWxsTGF5b3V0LCBjb2VyY2UpIHtcbiAgICB2YXIgb3JpZW50YXRpb24gPSB0cmFjZU91dC5vcmllbnRhdGlvbjtcbiAgICAvLyBOLkIuIGdyb3VwaW5nIGlzIGRvbmUgYWNyb3NzIGFsbCB0cmFjZSB0eXBlcyB0aGF0IHN1cHBvcnQgaXRcbiAgICB2YXIgcG9zQXhJZCA9IHRyYWNlT3V0W3t2OiAneCcsIGg6ICd5J31bb3JpZW50YXRpb25dICsgJ2F4aXMnXTtcbiAgICB2YXIgZ3JvdXBJZCA9IGdldEF4aXNHcm91cChmdWxsTGF5b3V0LCBwb3NBeElkKSArIG9yaWVudGF0aW9uO1xuXG4gICAgdmFyIGFsaWdubWVudE9wdHMgPSBmdWxsTGF5b3V0Ll9hbGlnbm1lbnRPcHRzIHx8IHt9O1xuICAgIHZhciBhbGlnbm1lbnRncm91cCA9IGNvZXJjZSgnYWxpZ25tZW50Z3JvdXAnKTtcblxuICAgIHZhciBhbGlnbm1lbnRHcm91cHMgPSBhbGlnbm1lbnRPcHRzW2dyb3VwSWRdO1xuICAgIGlmKCFhbGlnbm1lbnRHcm91cHMpIGFsaWdubWVudEdyb3VwcyA9IGFsaWdubWVudE9wdHNbZ3JvdXBJZF0gPSB7fTtcblxuICAgIHZhciBhbGlnbm1lbnRHcm91cE9wdHMgPSBhbGlnbm1lbnRHcm91cHNbYWxpZ25tZW50Z3JvdXBdO1xuXG4gICAgaWYoYWxpZ25tZW50R3JvdXBPcHRzKSB7XG4gICAgICAgIGFsaWdubWVudEdyb3VwT3B0cy50cmFjZXMucHVzaCh0cmFjZU91dCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYWxpZ25tZW50R3JvdXBPcHRzID0gYWxpZ25tZW50R3JvdXBzW2FsaWdubWVudGdyb3VwXSA9IHtcbiAgICAgICAgICAgIHRyYWNlczogW3RyYWNlT3V0XSxcbiAgICAgICAgICAgIGFsaWdubWVudEluZGV4OiBPYmplY3Qua2V5cyhhbGlnbm1lbnRHcm91cHMpLmxlbmd0aCxcbiAgICAgICAgICAgIG9mZnNldEdyb3Vwczoge31cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgb2Zmc2V0Z3JvdXAgPSBjb2VyY2UoJ29mZnNldGdyb3VwJyk7XG4gICAgdmFyIG9mZnNldEdyb3VwcyA9IGFsaWdubWVudEdyb3VwT3B0cy5vZmZzZXRHcm91cHM7XG4gICAgdmFyIG9mZnNldEdyb3VwT3B0cyA9IG9mZnNldEdyb3Vwc1tvZmZzZXRncm91cF07XG5cbiAgICBpZihvZmZzZXRncm91cCkge1xuICAgICAgICBpZighb2Zmc2V0R3JvdXBPcHRzKSB7XG4gICAgICAgICAgICBvZmZzZXRHcm91cE9wdHMgPSBvZmZzZXRHcm91cHNbb2Zmc2V0Z3JvdXBdID0ge1xuICAgICAgICAgICAgICAgIG9mZnNldEluZGV4OiBPYmplY3Qua2V5cyhvZmZzZXRHcm91cHMpLmxlbmd0aFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyYWNlT3V0Ll9vZmZzZXRJbmRleCA9IG9mZnNldEdyb3VwT3B0cy5vZmZzZXRJbmRleDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNyb3NzVHJhY2VEZWZhdWx0cyhmdWxsRGF0YSwgZnVsbExheW91dCkge1xuICAgIHZhciB0cmFjZUluLCB0cmFjZU91dDtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyKSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlT3V0Ll9pbnB1dCwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIpO1xuICAgIH1cblxuICAgIGlmKGZ1bGxMYXlvdXQuYmFybW9kZSA9PT0gJ2dyb3VwJykge1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyYWNlT3V0ID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgICAgIGlmKHRyYWNlT3V0LnR5cGUgPT09ICdiYXInKSB7XG4gICAgICAgICAgICAgICAgdHJhY2VJbiA9IHRyYWNlT3V0Ll9pbnB1dDtcbiAgICAgICAgICAgICAgICBoYW5kbGVHcm91cGluZ0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBmdWxsTGF5b3V0LCBjb2VyY2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBoYW5kbGVUZXh0KHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwgdGV4dHBvc2l0aW9uLCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG4gICAgdmFyIG1vZHVsZUhhc1NlbGVjdGVkID0gIShvcHRzLm1vZHVsZUhhc1NlbGVjdGVkID09PSBmYWxzZSk7XG4gICAgdmFyIG1vZHVsZUhhc1Vuc2VsZWN0ZWQgPSAhKG9wdHMubW9kdWxlSGFzVW5zZWxlY3RlZCA9PT0gZmFsc2UpO1xuICAgIHZhciBtb2R1bGVIYXNDb25zdHJhaW4gPSAhKG9wdHMubW9kdWxlSGFzQ29uc3RyYWluID09PSBmYWxzZSk7XG4gICAgdmFyIG1vZHVsZUhhc0NsaXBvbmF4aXMgPSAhKG9wdHMubW9kdWxlSGFzQ2xpcG9uYXhpcyA9PT0gZmFsc2UpO1xuICAgIHZhciBtb2R1bGVIYXNUZXh0YW5nbGUgPSAhKG9wdHMubW9kdWxlSGFzVGV4dGFuZ2xlID09PSBmYWxzZSk7XG4gICAgdmFyIG1vZHVsZUhhc0luc2lkZWFuY2hvciA9ICEob3B0cy5tb2R1bGVIYXNJbnNpZGVhbmNob3IgPT09IGZhbHNlKTtcblxuICAgIHZhciBoYXNCb3RoID0gQXJyYXkuaXNBcnJheSh0ZXh0cG9zaXRpb24pIHx8IHRleHRwb3NpdGlvbiA9PT0gJ2F1dG8nO1xuICAgIHZhciBoYXNJbnNpZGUgPSBoYXNCb3RoIHx8IHRleHRwb3NpdGlvbiA9PT0gJ2luc2lkZSc7XG4gICAgdmFyIGhhc091dHNpZGUgPSBoYXNCb3RoIHx8IHRleHRwb3NpdGlvbiA9PT0gJ291dHNpZGUnO1xuXG4gICAgaWYoaGFzSW5zaWRlIHx8IGhhc091dHNpZGUpIHtcbiAgICAgICAgdmFyIGRmbHRGb250ID0gY29lcmNlRm9udChjb2VyY2UsICd0ZXh0Zm9udCcsIGxheW91dC5mb250KTtcblxuICAgICAgICAvLyBOb3RlIHRoYXQgY29lcmNpbmcgYGluc2lkZXRleHRmb250YCBpcyBhbHdheXMgbmVlZGVkIOKAk1xuICAgICAgICAvLyBldmVuIGlmIGB0ZXh0cG9zaXRpb25gIGlzIGBvdXRzaWRlYCBmb3IgZWFjaCB0cmFjZSDigJMgc2luY2VcbiAgICAgICAgLy8gYW4gb3V0c2lkZSBsYWJlbCBjYW4gYmVjb21lIGFuIGluc2lkZSBvbmUsIGZvciBleGFtcGxlIGJlY2F1c2VcbiAgICAgICAgLy8gb2YgYSBiYXIgYmVpbmcgc3RhY2tlZCBvbiB0b3Agb2YgaXQuXG4gICAgICAgIHZhciBpbnNpZGVUZXh0Rm9udERlZmF1bHQgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgZGZsdEZvbnQpO1xuICAgICAgICB2YXIgaXNUcmFjZVRleHRmb250Q29sb3JTZXQgPSB0cmFjZUluLnRleHRmb250ICYmIHRyYWNlSW4udGV4dGZvbnQuY29sb3I7XG4gICAgICAgIHZhciBpc0NvbG9ySW5oZXJpdGVkRnJvbUxheW91dEZvbnQgPSAhaXNUcmFjZVRleHRmb250Q29sb3JTZXQ7XG4gICAgICAgIGlmKGlzQ29sb3JJbmhlcml0ZWRGcm9tTGF5b3V0Rm9udCkge1xuICAgICAgICAgICAgZGVsZXRlIGluc2lkZVRleHRGb250RGVmYXVsdC5jb2xvcjtcbiAgICAgICAgfVxuICAgICAgICBjb2VyY2VGb250KGNvZXJjZSwgJ2luc2lkZXRleHRmb250JywgaW5zaWRlVGV4dEZvbnREZWZhdWx0KTtcblxuICAgICAgICBpZihoYXNPdXRzaWRlKSBjb2VyY2VGb250KGNvZXJjZSwgJ291dHNpZGV0ZXh0Zm9udCcsIGRmbHRGb250KTtcblxuXG4gICAgICAgIGlmKG1vZHVsZUhhc1NlbGVjdGVkKSBjb2VyY2UoJ3NlbGVjdGVkLnRleHRmb250LmNvbG9yJyk7XG4gICAgICAgIGlmKG1vZHVsZUhhc1Vuc2VsZWN0ZWQpIGNvZXJjZSgndW5zZWxlY3RlZC50ZXh0Zm9udC5jb2xvcicpO1xuICAgICAgICBpZihtb2R1bGVIYXNDb25zdHJhaW4pIGNvZXJjZSgnY29uc3RyYWludGV4dCcpO1xuICAgICAgICBpZihtb2R1bGVIYXNDbGlwb25heGlzKSBjb2VyY2UoJ2NsaXBvbmF4aXMnKTtcbiAgICAgICAgaWYobW9kdWxlSGFzVGV4dGFuZ2xlKSBjb2VyY2UoJ3RleHRhbmdsZScpO1xuICAgIH1cblxuICAgIGlmKGhhc0luc2lkZSkge1xuICAgICAgICBpZihtb2R1bGVIYXNJbnNpZGVhbmNob3IpIGNvZXJjZSgnaW5zaWRldGV4dGFuY2hvcicpO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3VwcGx5RGVmYXVsdHM6IHN1cHBseURlZmF1bHRzLFxuICAgIGNyb3NzVHJhY2VEZWZhdWx0czogY3Jvc3NUcmFjZURlZmF1bHRzLFxuICAgIGhhbmRsZUdyb3VwaW5nRGVmYXVsdHM6IGhhbmRsZUdyb3VwaW5nRGVmYXVsdHMsXG4gICAgaGFuZGxlVGV4dDogaGFuZGxlVGV4dFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzXCI6NzcwLFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9zY2F0dGVyL3h5X2RlZmF1bHRzXCI6MTEzNyxcIi4vYXR0cmlidXRlc1wiOjg1NyxcIi4vc3R5bGVfZGVmYXVsdHNcIjo4NzF9XSw4NjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcbnZhciB0aW55Y29sb3IgPSBfZGVyZXFfKCd0aW55Y29sb3IyJyk7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG5cbmV4cG9ydHMuY29lcmNlU3RyaW5nID0gZnVuY3Rpb24oYXR0cmlidXRlRGVmaW5pdGlvbiwgdmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICAgIGlmKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYodmFsdWUgfHwgIWF0dHJpYnV0ZURlZmluaXRpb24ubm9CbGFuaykgcmV0dXJuIHZhbHVlO1xuICAgIH0gZWxzZSBpZih0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInIHx8IHZhbHVlID09PSB0cnVlKSB7XG4gICAgICAgIGlmKCFhdHRyaWJ1dGVEZWZpbml0aW9uLnN0cmljdCkgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIChkZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCkgP1xuICAgICAgZGVmYXVsdFZhbHVlIDpcbiAgICAgIGF0dHJpYnV0ZURlZmluaXRpb24uZGZsdDtcbn07XG5cbmV4cG9ydHMuY29lcmNlTnVtYmVyID0gZnVuY3Rpb24oYXR0cmlidXRlRGVmaW5pdGlvbiwgdmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICAgIGlmKGlzTnVtZXJpYyh2YWx1ZSkpIHtcbiAgICAgICAgdmFsdWUgPSArdmFsdWU7XG5cbiAgICAgICAgdmFyIG1pbiA9IGF0dHJpYnV0ZURlZmluaXRpb24ubWluO1xuICAgICAgICB2YXIgbWF4ID0gYXR0cmlidXRlRGVmaW5pdGlvbi5tYXg7XG4gICAgICAgIHZhciBpc091dE9mQm91bmRzID0gKG1pbiAhPT0gdW5kZWZpbmVkICYmIHZhbHVlIDwgbWluKSB8fFxuICAgICAgICAgICAgICAobWF4ICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgPiBtYXgpO1xuXG4gICAgICAgIGlmKCFpc091dE9mQm91bmRzKSByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIChkZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCkgP1xuICAgICAgZGVmYXVsdFZhbHVlIDpcbiAgICAgIGF0dHJpYnV0ZURlZmluaXRpb24uZGZsdDtcbn07XG5cbmV4cG9ydHMuY29lcmNlQ29sb3IgPSBmdW5jdGlvbihhdHRyaWJ1dGVEZWZpbml0aW9uLCB2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gICAgaWYodGlueWNvbG9yKHZhbHVlKS5pc1ZhbGlkKCkpIHJldHVybiB2YWx1ZTtcblxuICAgIHJldHVybiAoZGVmYXVsdFZhbHVlICE9PSB1bmRlZmluZWQpID9cbiAgICAgIGRlZmF1bHRWYWx1ZSA6XG4gICAgICBhdHRyaWJ1dGVEZWZpbml0aW9uLmRmbHQ7XG59O1xuXG5leHBvcnRzLmNvZXJjZUVudW1lcmF0ZWQgPSBmdW5jdGlvbihhdHRyaWJ1dGVEZWZpbml0aW9uLCB2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gICAgaWYoYXR0cmlidXRlRGVmaW5pdGlvbi5jb2VyY2VOdW1iZXIpIHZhbHVlID0gK3ZhbHVlO1xuXG4gICAgaWYoYXR0cmlidXRlRGVmaW5pdGlvbi52YWx1ZXMuaW5kZXhPZih2YWx1ZSkgIT09IC0xKSByZXR1cm4gdmFsdWU7XG5cbiAgICByZXR1cm4gKGRlZmF1bHRWYWx1ZSAhPT0gdW5kZWZpbmVkKSA/XG4gICAgICBkZWZhdWx0VmFsdWUgOlxuICAgICAgYXR0cmlidXRlRGVmaW5pdGlvbi5kZmx0O1xufTtcblxuZXhwb3J0cy5nZXRWYWx1ZSA9IGZ1bmN0aW9uKGFycmF5T3JTY2FsYXIsIGluZGV4KSB7XG4gICAgdmFyIHZhbHVlO1xuICAgIGlmKCFBcnJheS5pc0FycmF5KGFycmF5T3JTY2FsYXIpKSB2YWx1ZSA9IGFycmF5T3JTY2FsYXI7XG4gICAgZWxzZSBpZihpbmRleCA8IGFycmF5T3JTY2FsYXIubGVuZ3RoKSB2YWx1ZSA9IGFycmF5T3JTY2FsYXJbaW5kZXhdO1xuICAgIHJldHVybiB2YWx1ZTtcbn07XG5cbmV4cG9ydHMuZ2V0TGluZVdpZHRoID0gZnVuY3Rpb24odHJhY2UsIGRpKSB7XG4gICAgdmFyIHcgPVxuICAgICAgICAoMCA8IGRpLm1sdykgPyBkaS5tbHcgOlxuICAgICAgICAhaXNBcnJheU9yVHlwZWRBcnJheSh0cmFjZS5tYXJrZXIubGluZS53aWR0aCkgPyB0cmFjZS5tYXJrZXIubGluZS53aWR0aCA6XG4gICAgICAgIDA7XG5cbiAgICByZXR1cm4gdztcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiZmFzdC1pc251bWVyaWNcIjoyMjUsXCJ0aW55Y29sb3IyXCI6NTM3fV0sODYzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG52YXIgZmlsbFRleHQgPSBfZGVyZXFfKCcuLi8uLi9saWInKS5maWxsVGV4dDtcbnZhciBnZXRMaW5lV2lkdGggPSBfZGVyZXFfKCcuL2hlbHBlcnMnKS5nZXRMaW5lV2lkdGg7XG5cbmZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIGJhclBvaW50RGF0YSA9IGhvdmVyT25CYXJzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKTtcblxuICAgIGlmKGJhclBvaW50RGF0YSkge1xuICAgICAgICB2YXIgY2QgPSBiYXJQb2ludERhdGEuY2Q7XG4gICAgICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgICAgICB2YXIgZGkgPSBjZFtiYXJQb2ludERhdGEuaW5kZXhdO1xuXG4gICAgICAgIGJhclBvaW50RGF0YS5jb2xvciA9IGdldFRyYWNlQ29sb3IodHJhY2UsIGRpKTtcbiAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnaG92ZXJJbmZvJykoZGksIHRyYWNlLCBiYXJQb2ludERhdGEpO1xuXG4gICAgICAgIHJldHVybiBbYmFyUG9pbnREYXRhXTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGhvdmVyT25CYXJzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIGNkID0gcG9pbnREYXRhLmNkO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciB0ID0gY2RbMF0udDtcbiAgICB2YXIgaXNDbG9zZXN0ID0gKGhvdmVybW9kZSA9PT0gJ2Nsb3Nlc3QnKTtcbiAgICB2YXIgaXNXYXRlcmZhbGwgPSAodHJhY2UudHlwZSA9PT0gJ3dhdGVyZmFsbCcpO1xuICAgIHZhciBtYXhIb3ZlckRpc3RhbmNlID0gcG9pbnREYXRhLm1heEhvdmVyRGlzdGFuY2U7XG4gICAgdmFyIG1heFNwaWtlRGlzdGFuY2UgPSBwb2ludERhdGEubWF4U3Bpa2VEaXN0YW5jZTtcblxuICAgIHZhciBwb3NWYWwsIHNpemVWYWwsIHBvc0xldHRlciwgc2l6ZUxldHRlciwgZHgsIGR5LCBwUmFuZ2VDYWxjO1xuXG4gICAgZnVuY3Rpb24gdGhpc0Jhck1pblBvcyhkaSkgeyByZXR1cm4gZGlbcG9zTGV0dGVyXSAtIGRpLncgLyAyOyB9XG4gICAgZnVuY3Rpb24gdGhpc0Jhck1heFBvcyhkaSkgeyByZXR1cm4gZGlbcG9zTGV0dGVyXSArIGRpLncgLyAyOyB9XG5cbiAgICB2YXIgbWluUG9zID0gaXNDbG9zZXN0ID9cbiAgICAgICAgdGhpc0Jhck1pblBvcyA6XG4gICAgICAgIGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogSW4gY29tcGFyZSBtb2RlLCBhY2NlcHQgYSBiYXIgaWYgeW91J3JlIG9uIGl0ICpvciogaXRzIGdyb3VwLlxuICAgICAgICAgICAgICogTmVhcmx5IGFsd2F5cyBpdCdzIHRoZSBncm91cCB0aGF0IG1hdHRlcnMsIGJ1dCBpbiBjYXNlIHRoZSBiYXJcbiAgICAgICAgICAgICAqIHdhcyBleHBsaWNpdGx5IHNldCB3aWRlciB0aGFuIGl0cyBncm91cCB3ZSdkIGJldHRlciBhY2NlcHQgdGhlXG4gICAgICAgICAgICAgKiB3aG9sZSBiYXIuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogdXNlIGBiYXJkZWx0YWAgaW5zdGVhZCBvZiBgYmFyZ3JvdXB3aWR0aGAgc28gd2UgYWNjZXB0IGhvdmVyXG4gICAgICAgICAgICAgKiBpbiB0aGUgZ2FwLiBUaGF0IHdheSBob3ZlciBkb2Vzbid0IGZsYXNoIG9uIGFuZCBvZmYgYXMgeW91XG4gICAgICAgICAgICAgKiBtb3VzZSBvdmVyIHRoZSBwbG90IGluIGNvbXBhcmUgbW9kZXMuXG4gICAgICAgICAgICAgKiBJbiAnY2xvc2VzdCcgbW9kZSB0aG91Z2ggdGhlIGZsYXNoaW5nIHNlZW1zIGluZXZpdGFibGUsXG4gICAgICAgICAgICAgKiB3aXRob3V0IGZhciBtb3JlIGNvbXBsZXggbG9naWNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubWluKHRoaXNCYXJNaW5Qb3MoZGkpLCBkaS5wIC0gdC5iYXJkZWx0YSAvIDIpO1xuICAgICAgICB9O1xuXG4gICAgdmFyIG1heFBvcyA9IGlzQ2xvc2VzdCA/XG4gICAgICAgIHRoaXNCYXJNYXhQb3MgOlxuICAgICAgICBmdW5jdGlvbihkaSkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubWF4KHRoaXNCYXJNYXhQb3MoZGkpLCBkaS5wICsgdC5iYXJkZWx0YSAvIDIpO1xuICAgICAgICB9O1xuXG4gICAgZnVuY3Rpb24gX3Bvc2l0aW9uRm4oX21pblBvcywgX21heFBvcykge1xuICAgICAgICAvLyBhZGQgYSBsaXR0bGUgdG8gdGhlIHBzZXVkby1kaXN0YW5jZSBmb3Igd2lkZXIgYmFycywgc28gdGhhdCBsaWtlIHNjYXR0ZXIsXG4gICAgICAgIC8vIGlmIHlvdSBhcmUgb3ZlciB0d28gb3ZlcmxhcHBpbmcgYmFycywgdGhlIG5hcnJvd2VyIG9uZSB3aW5zLlxuICAgICAgICByZXR1cm4gRnguaW5ib3goX21pblBvcyAtIHBvc1ZhbCwgX21heFBvcyAtIHBvc1ZhbCxcbiAgICAgICAgICAgIG1heEhvdmVyRGlzdGFuY2UgKyBNYXRoLm1pbigxLCBNYXRoLmFicyhfbWF4UG9zIC0gX21pblBvcykgLyBwUmFuZ2VDYWxjKSAtIDEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBvc2l0aW9uRm4oZGkpIHtcbiAgICAgICAgcmV0dXJuIF9wb3NpdGlvbkZuKG1pblBvcyhkaSksIG1heFBvcyhkaSkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRoaXNCYXJQb3NpdGlvbkZuKGRpKSB7XG4gICAgICAgIHJldHVybiBfcG9zaXRpb25Gbih0aGlzQmFyTWluUG9zKGRpKSwgdGhpc0Jhck1heFBvcyhkaSkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNpemVGbihkaSkge1xuICAgICAgICB2YXIgdiA9IHNpemVWYWw7XG4gICAgICAgIHZhciBiID0gZGkuYjtcbiAgICAgICAgdmFyIHMgPSBkaVtzaXplTGV0dGVyXTtcblxuICAgICAgICBpZihpc1dhdGVyZmFsbCkge1xuICAgICAgICAgICAgcyArPSBNYXRoLmFicyhkaS5yYXdTIHx8IDApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gYWRkIGEgZ3JhZGllbnQgc28gaG92ZXJpbmcgbmVhciB0aGUgZW5kIG9mIGFcbiAgICAgICAgLy8gYmFyIG1ha2VzIGl0IGEgbGl0dGxlIGNsb3NlciBtYXRjaFxuICAgICAgICByZXR1cm4gRnguaW5ib3goYiAtIHYsIHMgLSB2LCBtYXhIb3ZlckRpc3RhbmNlICsgKHMgLSB2KSAvIChzIC0gYikgLSAxKTtcbiAgICB9XG5cbiAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgIHBvc1ZhbCA9IHl2YWw7XG4gICAgICAgIHNpemVWYWwgPSB4dmFsO1xuICAgICAgICBwb3NMZXR0ZXIgPSAneSc7XG4gICAgICAgIHNpemVMZXR0ZXIgPSAneCc7XG4gICAgICAgIGR4ID0gc2l6ZUZuO1xuICAgICAgICBkeSA9IHBvc2l0aW9uRm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcG9zVmFsID0geHZhbDtcbiAgICAgICAgc2l6ZVZhbCA9IHl2YWw7XG4gICAgICAgIHBvc0xldHRlciA9ICd4JztcbiAgICAgICAgc2l6ZUxldHRlciA9ICd5JztcbiAgICAgICAgZHkgPSBzaXplRm47XG4gICAgICAgIGR4ID0gcG9zaXRpb25GbjtcbiAgICB9XG5cbiAgICB2YXIgcGEgPSBwb2ludERhdGFbcG9zTGV0dGVyICsgJ2EnXTtcbiAgICB2YXIgc2EgPSBwb2ludERhdGFbc2l6ZUxldHRlciArICdhJ107XG5cbiAgICBwUmFuZ2VDYWxjID0gTWF0aC5hYnMocGEucjJjKHBhLnJhbmdlWzFdKSAtIHBhLnIyYyhwYS5yYW5nZVswXSkpO1xuXG4gICAgZnVuY3Rpb24gZHh5KGRpKSB7IHJldHVybiAoZHgoZGkpICsgZHkoZGkpKSAvIDI7IH1cbiAgICB2YXIgZGlzdGZuID0gRnguZ2V0RGlzdGFuY2VGdW5jdGlvbihob3Zlcm1vZGUsIGR4LCBkeSwgZHh5KTtcbiAgICBGeC5nZXRDbG9zZXN0KGNkLCBkaXN0Zm4sIHBvaW50RGF0YSk7XG5cbiAgICAvLyBza2lwIHRoZSByZXN0IChmb3IgdGhpcyB0cmFjZSkgaWYgd2UgZGlkbid0IGZpbmQgYSBjbG9zZSBwb2ludFxuICAgIGlmKHBvaW50RGF0YS5pbmRleCA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIC8vIGlmIHdlIGdldCBoZXJlIGFuZCB3ZSdyZSBub3QgaW4gJ2Nsb3Nlc3QnIG1vZGUsIHB1c2ggbWluL21heCBwb3MgYmFja1xuICAgIC8vIG9udG8gdGhlIGdyb3VwIC0gZXZlbiB0aG91Z2ggdGhhdCBtZWFucyBvY2Nhc2lvbmFsbHkgdGhlIG1vdXNlIHdpbGwgYmVcbiAgICAvLyBvdmVyIHRoZSBob3ZlciBsYWJlbC5cbiAgICBpZighaXNDbG9zZXN0KSB7XG4gICAgICAgIG1pblBvcyA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5taW4odGhpc0Jhck1pblBvcyhkaSksIGRpLnAgLSB0LmJhcmdyb3Vwd2lkdGggLyAyKTtcbiAgICAgICAgfTtcbiAgICAgICAgbWF4UG9zID0gZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLm1heCh0aGlzQmFyTWF4UG9zKGRpKSwgZGkucCArIHQuYmFyZ3JvdXB3aWR0aCAvIDIpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIHRoZSBjbG9zZXN0IGRhdGEgcG9pbnRcbiAgICB2YXIgaW5kZXggPSBwb2ludERhdGEuaW5kZXg7XG4gICAgdmFyIGRpID0gY2RbaW5kZXhdO1xuXG4gICAgdmFyIHNpemUgPSAodHJhY2UuYmFzZSkgPyBkaS5iICsgZGkucyA6IGRpLnM7XG4gICAgcG9pbnREYXRhW3NpemVMZXR0ZXIgKyAnMCddID0gcG9pbnREYXRhW3NpemVMZXR0ZXIgKyAnMSddID0gc2EuYzJwKGRpW3NpemVMZXR0ZXJdLCB0cnVlKTtcbiAgICBwb2ludERhdGFbc2l6ZUxldHRlciArICdMYWJlbFZhbCddID0gc2l6ZTtcblxuICAgIHZhciBleHRlbnQgPSB0LmV4dGVudHNbdC5leHRlbnRzLnJvdW5kKGRpLnApXTtcbiAgICBwb2ludERhdGFbcG9zTGV0dGVyICsgJzAnXSA9IHBhLmMycChpc0Nsb3Nlc3QgPyBtaW5Qb3MoZGkpIDogZXh0ZW50WzBdLCB0cnVlKTtcbiAgICBwb2ludERhdGFbcG9zTGV0dGVyICsgJzEnXSA9IHBhLmMycChpc0Nsb3Nlc3QgPyBtYXhQb3MoZGkpIDogZXh0ZW50WzFdLCB0cnVlKTtcbiAgICBwb2ludERhdGFbcG9zTGV0dGVyICsgJ0xhYmVsVmFsJ10gPSBkaS5wO1xuXG4gICAgLy8gc3Bpa2VsaW5lcyBhbHdheXMgd2FudCBcImNsb3Nlc3RcIiBkaXN0YW5jZSByZWdhcmRsZXNzIG9mIGhvdmVybW9kZVxuICAgIHBvaW50RGF0YS5zcGlrZURpc3RhbmNlID0gKHNpemVGbihkaSkgKyB0aGlzQmFyUG9zaXRpb25GbihkaSkpIC8gMiArIG1heFNwaWtlRGlzdGFuY2UgLSBtYXhIb3ZlckRpc3RhbmNlO1xuICAgIC8vIHRoZXkgYWxzbyB3YW50IHRvIHBvaW50IHRvIHRoZSBkYXRhIHZhbHVlLCByZWdhcmRsZXNzIG9mIHdoZXJlIHRoZSBsYWJlbCBnb2VzXG4gICAgLy8gaW4gY2FzZSBvZiBiYXJzIHNoaWZ0ZWQgd2l0aGluIGdyb3Vwc1xuICAgIHBvaW50RGF0YVtwb3NMZXR0ZXIgKyAnU3Bpa2UnXSA9IHBhLmMycChkaS5wLCB0cnVlKTtcblxuICAgIGZpbGxUZXh0KGRpLCB0cmFjZSwgcG9pbnREYXRhKTtcbiAgICBwb2ludERhdGEuaG92ZXJ0ZW1wbGF0ZSA9IHRyYWNlLmhvdmVydGVtcGxhdGU7XG5cbiAgICByZXR1cm4gcG9pbnREYXRhO1xufVxuXG5mdW5jdGlvbiBnZXRUcmFjZUNvbG9yKHRyYWNlLCBkaSkge1xuICAgIHZhciBtYyA9IGRpLm1jYyB8fCB0cmFjZS5tYXJrZXIuY29sb3I7XG4gICAgdmFyIG1sYyA9IGRpLm1sY2MgfHwgdHJhY2UubWFya2VyLmxpbmUuY29sb3I7XG4gICAgdmFyIG1sdyA9IGdldExpbmVXaWR0aCh0cmFjZSwgZGkpO1xuXG4gICAgaWYoQ29sb3Iub3BhY2l0eShtYykpIHJldHVybiBtYztcbiAgICBlbHNlIGlmKENvbG9yLm9wYWNpdHkobWxjKSAmJiBtbHcpIHJldHVybiBtbGM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhvdmVyUG9pbnRzOiBob3ZlclBvaW50cyxcbiAgICBob3Zlck9uQmFyczogaG92ZXJPbkJhcnMsXG4gICAgZ2V0VHJhY2VDb2xvcjogZ2V0VHJhY2VDb2xvclxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9meFwiOjYzMixcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9oZWxwZXJzXCI6ODYyfV0sODY0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJykuc3VwcGx5RGVmYXVsdHMsXG4gICAgY3Jvc3NUcmFjZURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJykuY3Jvc3NUcmFjZURlZmF1bHRzLFxuICAgIHN1cHBseUxheW91dERlZmF1bHRzOiBfZGVyZXFfKCcuL2xheW91dF9kZWZhdWx0cycpLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLFxuICAgIGNyb3NzVHJhY2VDYWxjOiBfZGVyZXFfKCcuL2Nyb3NzX3RyYWNlX2NhbGMnKS5jcm9zc1RyYWNlQ2FsYyxcbiAgICBjb2xvcmJhcjogX2RlcmVxXygnLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXInKSxcbiAgICBhcnJheXNUb0NhbGNkYXRhOiBfZGVyZXFfKCcuL2FycmF5c190b19jYWxjZGF0YScpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLnBsb3QsXG4gICAgc3R5bGU6IF9kZXJlcV8oJy4vc3R5bGUnKS5zdHlsZSxcbiAgICBzdHlsZU9uU2VsZWN0OiBfZGVyZXFfKCcuL3N0eWxlJykuc3R5bGVPblNlbGVjdCxcbiAgICBob3ZlclBvaW50czogX2RlcmVxXygnLi9ob3ZlcicpLmhvdmVyUG9pbnRzLFxuICAgIHNlbGVjdFBvaW50czogX2RlcmVxXygnLi9zZWxlY3QnKSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ2JhcicsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnYmFyLWxpa2UnLCAnY2FydGVzaWFuJywgJ3N2ZycsICdiYXInLCAnb3JpZW50ZWQnLCAnZXJyb3JCYXJzT0snLCAnc2hvd0xlZ2VuZCcsICd6b29tU2NhbGUnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvY2FydGVzaWFuXCI6Nzc4LFwiLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXJcIjoxMTI5LFwiLi9hcnJheXNfdG9fY2FsY2RhdGFcIjo4NTYsXCIuL2F0dHJpYnV0ZXNcIjo4NTcsXCIuL2NhbGNcIjo4NTgsXCIuL2Nyb3NzX3RyYWNlX2NhbGNcIjo4NjAsXCIuL2RlZmF1bHRzXCI6ODYxLFwiLi9ob3ZlclwiOjg2MyxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo4NjUsXCIuL2xheW91dF9kZWZhdWx0c1wiOjg2NixcIi4vcGxvdFwiOjg2NyxcIi4vc2VsZWN0XCI6ODY4LFwiLi9zdHlsZVwiOjg3MH1dLDg2NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYmFybW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydzdGFjaycsICdncm91cCcsICdvdmVybGF5JywgJ3JlbGF0aXZlJ10sXG4gICAgICAgIGRmbHQ6ICdncm91cCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJhcm5vcm06IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnJywgJ2ZyYWN0aW9uJywgJ3BlcmNlbnQnXSxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJhcmdhcDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJhcmdyb3VwZ2FwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se31dLDg2NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGF5b3V0SW4sIGxheW91dE91dCwgbGF5b3V0QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGhhc0JhcnMgPSBmYWxzZTtcbiAgICB2YXIgc2hvdWxkQmVHYXBsZXNzID0gZmFsc2U7XG4gICAgdmFyIGdhcHBlZEFueXdheSA9IGZhbHNlO1xuICAgIHZhciB1c2VkU3VicGxvdHMgPSB7fTtcblxuICAgIHZhciBtb2RlID0gY29lcmNlKCdiYXJtb2RlJyk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG4gICAgICAgIGlmKFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdiYXInKSAmJiB0cmFjZS52aXNpYmxlKSBoYXNCYXJzID0gdHJ1ZTtcbiAgICAgICAgZWxzZSBjb250aW51ZTtcblxuICAgICAgICAvLyBpZiB3ZSBoYXZlIGF0IGxlYXN0IDIgZ3JvdXBlZCBiYXIgdHJhY2VzIG9uIHRoZSBzYW1lIHN1YnBsb3QsXG4gICAgICAgIC8vIHdlIHNob3VsZCBkZWZhdWx0IHRvIGEgZ2FwIGFueXdheSwgZXZlbiBpZiB0aGUgZGF0YSBpcyBoaXN0b2dyYW1zXG4gICAgICAgIGlmKG1vZGUgPT09ICdncm91cCcpIHtcbiAgICAgICAgICAgIHZhciBzdWJwbG90aSA9IHRyYWNlLnhheGlzICsgdHJhY2UueWF4aXM7XG4gICAgICAgICAgICBpZih1c2VkU3VicGxvdHNbc3VicGxvdGldKSBnYXBwZWRBbnl3YXkgPSB0cnVlO1xuICAgICAgICAgICAgdXNlZFN1YnBsb3RzW3N1YnBsb3RpXSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0cmFjZS52aXNpYmxlICYmIHRyYWNlLnR5cGUgPT09ICdoaXN0b2dyYW0nKSB7XG4gICAgICAgICAgICB2YXIgcGEgPSBBeGVzLmdldEZyb21JZCh7X2Z1bGxMYXlvdXQ6IGxheW91dE91dH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFjZVt0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ3YnID8gJ3hheGlzJyA6ICd5YXhpcyddKTtcbiAgICAgICAgICAgIGlmKHBhLnR5cGUgIT09ICdjYXRlZ29yeScpIHNob3VsZEJlR2FwbGVzcyA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZighaGFzQmFycykge1xuICAgICAgICBkZWxldGUgbGF5b3V0T3V0LmJhcm1vZGU7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZihtb2RlICE9PSAnb3ZlcmxheScpIGNvZXJjZSgnYmFybm9ybScpO1xuXG4gICAgY29lcmNlKCdiYXJnYXAnLCAoc2hvdWxkQmVHYXBsZXNzICYmICFnYXBwZWRBbnl3YXkpID8gMCA6IDAuMik7XG4gICAgY29lcmNlKCdiYXJncm91cGdhcCcpO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjg2NX1dLDg2NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xuXG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciB0aWNrVGV4dCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJykudGlja1RleHQ7XG5cbnZhciBzdHlsZSA9IF9kZXJlcV8oJy4vc3R5bGUnKTtcbnZhciBoZWxwZXJzID0gX2RlcmVxXygnLi9oZWxwZXJzJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG52YXIgYXR0cmlidXRlVGV4dCA9IGF0dHJpYnV0ZXMudGV4dDtcbnZhciBhdHRyaWJ1dGVUZXh0UG9zaXRpb24gPSBhdHRyaWJ1dGVzLnRleHRwb3NpdGlvbjtcblxuLy8gcGFkZGluZyBpbiBwaXhlbHMgYXJvdW5kIHRleHRcbnZhciBURVhUUEFEID0gMztcblxuZnVuY3Rpb24gZGlyU2lnbihhLCBiKSB7XG4gICAgcmV0dXJuIChhIDwgYikgPyAxIDogLTE7XG59XG5cbmZ1bmN0aW9uIGdldFhZKGRpLCB4YSwgeWEsIGlzSG9yaXpvbnRhbCkge1xuICAgIHZhciBzID0gW107XG4gICAgdmFyIHAgPSBbXTtcblxuICAgIHZhciBzQXhpcyA9IGlzSG9yaXpvbnRhbCA/IHhhIDogeWE7XG4gICAgdmFyIHBBeGlzID0gaXNIb3Jpem9udGFsID8geWEgOiB4YTtcblxuICAgIHNbMF0gPSBzQXhpcy5jMnAoZGkuczAsIHRydWUpO1xuICAgIHBbMF0gPSBwQXhpcy5jMnAoZGkucDAsIHRydWUpO1xuXG4gICAgc1sxXSA9IHNBeGlzLmMycChkaS5zMSwgdHJ1ZSk7XG4gICAgcFsxXSA9IHBBeGlzLmMycChkaS5wMSwgdHJ1ZSk7XG5cbiAgICByZXR1cm4gaXNIb3Jpem9udGFsID8gW3MsIHBdIDogW3AsIHNdO1xufVxuXG5mdW5jdGlvbiBwbG90KGdkLCBwbG90aW5mbywgY2RNb2R1bGUsIHRyYWNlTGF5ZXIsIG9wdHMpIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgaWYoIW9wdHMpIHtcbiAgICAgICAgb3B0cyA9IHtcbiAgICAgICAgICAgIG1vZGU6IGZ1bGxMYXlvdXQuYmFybW9kZSxcbiAgICAgICAgICAgIG5vcm06IGZ1bGxMYXlvdXQuYmFybW9kZSxcbiAgICAgICAgICAgIGdhcDogZnVsbExheW91dC5iYXJnYXAsXG4gICAgICAgICAgICBncm91cGdhcDogZnVsbExheW91dC5iYXJncm91cGdhcFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBiYXJ0cmFjZXMgPSBMaWIubWFrZVRyYWNlR3JvdXBzKHRyYWNlTGF5ZXIsIGNkTW9kdWxlLCAndHJhY2UgYmFycycpLmVhY2goZnVuY3Rpb24oY2QpIHtcbiAgICAgICAgdmFyIHBsb3RHcm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgICAgIHZhciBpc1dhdGVyZmFsbCA9ICh0cmFjZS50eXBlID09PSAnd2F0ZXJmYWxsJyk7XG4gICAgICAgIHZhciBpc0Z1bm5lbCA9ICh0cmFjZS50eXBlID09PSAnZnVubmVsJyk7XG4gICAgICAgIHZhciBpc0JhciA9ICh0cmFjZS50eXBlID09PSAnYmFyJyk7XG4gICAgICAgIHZhciBzaG91bGREaXNwbGF5WmVyb3MgPSAoaXNCYXIgfHwgaXNGdW5uZWwpO1xuXG4gICAgICAgIHZhciBhZGp1c3RQaXhlbCA9IDA7XG4gICAgICAgIGlmKGlzV2F0ZXJmYWxsICYmIHRyYWNlLmNvbm5lY3Rvci52aXNpYmxlICYmIHRyYWNlLmNvbm5lY3Rvci5tb2RlID09PSAnYmV0d2VlbicpIHtcbiAgICAgICAgICAgIGFkanVzdFBpeGVsID0gdHJhY2UuY29ubmVjdG9yLmxpbmUud2lkdGggLyAyO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlzSG9yaXpvbnRhbCA9ICh0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKTtcblxuICAgICAgICB2YXIgcG9pbnRHcm91cCA9IExpYi5lbnN1cmVTaW5nbGUocGxvdEdyb3VwLCAnZycsICdwb2ludHMnKTtcblxuICAgICAgICB2YXIgYmFycyA9IHBvaW50R3JvdXAuc2VsZWN0QWxsKCdnLnBvaW50JykuZGF0YShMaWIuaWRlbnRpdHkpO1xuXG4gICAgICAgIGJhcnMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAgICAgLmNsYXNzZWQoJ3BvaW50JywgdHJ1ZSk7XG5cbiAgICAgICAgYmFycy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgYmFycy5lYWNoKGZ1bmN0aW9uKGRpLCBpKSB7XG4gICAgICAgICAgICB2YXIgYmFyID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgICAgICAvLyBub3cgZGlzcGxheSB0aGUgYmFyXG4gICAgICAgICAgICAvLyBjbGlwcGVkIHhmL3lmICgybmQgYXJnIHRydWUpOiBub24tcG9zaXRpdmVcbiAgICAgICAgICAgIC8vIGxvZyB2YWx1ZXMgZ28gb2ZmLXNjcmVlbiBieSBwbG90d2lkdGhcbiAgICAgICAgICAgIC8vIHNvIHlvdSBzZWUgdGhlbSBjb250aW51ZSBpZiB5b3UgZHJhZyB0aGUgcGxvdFxuXG4gICAgICAgICAgICB2YXIgeHkgPSBnZXRYWShkaSwgeGEsIHlhLCBpc0hvcml6b250YWwpO1xuXG4gICAgICAgICAgICB2YXIgeDAgPSB4eVswXVswXTtcbiAgICAgICAgICAgIHZhciB4MSA9IHh5WzBdWzFdO1xuICAgICAgICAgICAgdmFyIHkwID0geHlbMV1bMF07XG4gICAgICAgICAgICB2YXIgeTEgPSB4eVsxXVsxXTtcblxuICAgICAgICAgICAgdmFyIGlzQmxhbmsgPSAoXG4gICAgICAgICAgICAgICAgeDAgPT09IHgxIHx8XG4gICAgICAgICAgICAgICAgeTAgPT09IHkxIHx8XG4gICAgICAgICAgICAgICAgIWlzTnVtZXJpYyh4MCkgfHxcbiAgICAgICAgICAgICAgICAhaXNOdW1lcmljKHgxKSB8fFxuICAgICAgICAgICAgICAgICFpc051bWVyaWMoeTApIHx8XG4gICAgICAgICAgICAgICAgIWlzTnVtZXJpYyh5MSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICAvLyBkaXNwbGF5IHplcm9zIGlmIGxpbmUud2lkdGggPiAwXG4gICAgICAgICAgICBpZihpc0JsYW5rICYmIHNob3VsZERpc3BsYXlaZXJvcyAmJiBoZWxwZXJzLmdldExpbmVXaWR0aCh0cmFjZSwgZGkpICYmIChpc0hvcml6b250YWwgPyB4MSAtIHgwID09PSAwIDogeTEgLSB5MCA9PT0gMCkpIHtcbiAgICAgICAgICAgICAgICBpc0JsYW5rID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaS5pc0JsYW5rID0gaXNCbGFuaztcblxuICAgICAgICAgICAgLy8gaW4gd2F0ZXJmYWxsIG1vZGUgYGJldHdlZW5gIHdlIG5lZWQgdG8gYWRqdXN0IGJhciBlbmQgcG9pbnRzIHRvIG1hdGNoIHRoZSBjb25uZWN0b3Igd2lkdGhcbiAgICAgICAgICAgIGlmKGFkanVzdFBpeGVsKSB7XG4gICAgICAgICAgICAgICAgaWYoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICAgICAgICAgIHgwIC09IGRpclNpZ24oeDAsIHgxKSAqIGFkanVzdFBpeGVsO1xuICAgICAgICAgICAgICAgICAgICB4MSArPSBkaXJTaWduKHgwLCB4MSkgKiBhZGp1c3RQaXhlbDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB5MCAtPSBkaXJTaWduKHkwLCB5MSkgKiBhZGp1c3RQaXhlbDtcbiAgICAgICAgICAgICAgICAgICAgeTEgKz0gZGlyU2lnbih5MCwgeTEpICogYWRqdXN0UGl4ZWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgbHc7XG4gICAgICAgICAgICB2YXIgbWM7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICd3YXRlcmZhbGwnKSB7XG4gICAgICAgICAgICAgICAgaWYoIWlzQmxhbmspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbnQgPSB0cmFjZVtkaS5kaXJdLm1hcmtlcjtcbiAgICAgICAgICAgICAgICAgICAgbHcgPSBjb250LmxpbmUud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIG1jID0gY29udC5jb2xvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGx3ID0gaGVscGVycy5nZXRMaW5lV2lkdGgodHJhY2UsIGRpKTtcbiAgICAgICAgICAgICAgICBtYyA9IGRpLm1jIHx8IHRyYWNlLm1hcmtlci5jb2xvcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIG9mZnNldCA9IGQzLnJvdW5kKChsdyAvIDIpICUgMSwgMik7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJvdW5kV2l0aExpbmUodikge1xuICAgICAgICAgICAgICAgIC8vIGlmIHRoZXJlIGFyZSBleHBsaWNpdCBnYXBzLCBkb24ndCByb3VuZCxcbiAgICAgICAgICAgICAgICAvLyBpdCBjYW4gbWFrZSB0aGUgZ2FwcyBsb29rIGNyYXBweVxuICAgICAgICAgICAgICAgIHJldHVybiAob3B0cy5nYXAgPT09IDAgJiYgb3B0cy5ncm91cGdhcCA9PT0gMCkgP1xuICAgICAgICAgICAgICAgICAgICBkMy5yb3VuZChNYXRoLnJvdW5kKHYpIC0gb2Zmc2V0LCAyKSA6IHY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGV4cGFuZFRvVmlzaWJsZSh2LCB2Yykge1xuICAgICAgICAgICAgICAgIC8vIGlmIGl0J3Mgbm90IGluIGRhbmdlciBvZiBkaXNhcHBlYXJpbmcgZW50aXJlbHksXG4gICAgICAgICAgICAgICAgLy8gcm91bmQgbW9yZSBwcmVjaXNlbHlcbiAgICAgICAgICAgICAgICByZXR1cm4gTWF0aC5hYnModiAtIHZjKSA+PSAyID8gcm91bmRXaXRoTGluZSh2KSA6XG4gICAgICAgICAgICAgICAgLy8gYnV0IGlmIGl0J3MgdmVyeSB0aGluLCBleHBhbmQgaXQgc28gaXQnc1xuICAgICAgICAgICAgICAgIC8vIG5lY2Vzc2FyaWx5IHZpc2libGUsIGV2ZW4gaWYgaXQgbWlnaHQgb3ZlcmxhcFxuICAgICAgICAgICAgICAgIC8vIGl0cyBuZWlnaGJvclxuICAgICAgICAgICAgICAgICh2ID4gdmMgPyBNYXRoLmNlaWwodikgOiBNYXRoLmZsb29yKHYpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIWdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiBiYXJzIGFyZSBub3QgZnVsbHkgb3BhcXVlIG9yIHRoZXkgaGF2ZSBhIGxpbmVcbiAgICAgICAgICAgICAgICAvLyBhcm91bmQgdGhlbSwgcm91bmQgdG8gaW50ZWdlciBwaXhlbHMsIG1haW5seSBmb3JcbiAgICAgICAgICAgICAgICAvLyBzYWZhcmkgc28gd2UgcHJldmVudCBvdmVybGFwcyBmcm9tIGl0cyBleHBhbnNpdmVcbiAgICAgICAgICAgICAgICAvLyBwaXhlbGF0aW9uLiBpZiB0aGUgYmFycyBBUkUgZnVsbHkgb3BhcXVlIGFuZCBoYXZlXG4gICAgICAgICAgICAgICAgLy8gbm8gbGluZSwgZXhwYW5kIHRvIGEgZnVsbCBwaXhlbCB0byBtYWtlIHN1cmUgd2VcbiAgICAgICAgICAgICAgICAvLyBjYW4gc2VlIHRoZW1cblxuICAgICAgICAgICAgICAgIHZhciBvcCA9IENvbG9yLm9wYWNpdHkobWMpO1xuICAgICAgICAgICAgICAgIHZhciBmaXhweCA9IChvcCA8IDEgfHwgbHcgPiAwLjAxKSA/IHJvdW5kV2l0aExpbmUgOiBleHBhbmRUb1Zpc2libGU7XG4gICAgICAgICAgICAgICAgeDAgPSBmaXhweCh4MCwgeDEpO1xuICAgICAgICAgICAgICAgIHgxID0gZml4cHgoeDEsIHgwKTtcbiAgICAgICAgICAgICAgICB5MCA9IGZpeHB4KHkwLCB5MSk7XG4gICAgICAgICAgICAgICAgeTEgPSBmaXhweCh5MSwgeTApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGJhciwgJ3BhdGgnKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKVxuICAgICAgICAgICAgICAgIC5hdHRyKCdkJywgaXNCbGFuayA/ICdNMCwwWicgOiAnTScgKyB4MCArICcsJyArIHkwICsgJ1YnICsgeTEgKyAnSCcgKyB4MSArICdWJyArIHkwICsgJ1onKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuc2V0Q2xpcFVybCwgcGxvdGluZm8ubGF5ZXJDbGlwSWQsIGdkKTtcblxuICAgICAgICAgICAgYXBwZW5kQmFyVGV4dChnZCwgcGxvdGluZm8sIGJhciwgY2QsIGksIHgwLCB4MSwgeTAsIHkxLCBvcHRzKTtcblxuICAgICAgICAgICAgaWYocGxvdGluZm8ubGF5ZXJDbGlwSWQpIHtcbiAgICAgICAgICAgICAgICBEcmF3aW5nLmhpZGVPdXRzaWRlUmFuZ2VQb2ludChkaSwgYmFyLnNlbGVjdCgndGV4dCcpLCB4YSwgeWEsIHRyYWNlLnhjYWxlbmRhciwgdHJhY2UueWNhbGVuZGFyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gbGFzdGx5LCBjbGlwIHBvaW50cyBncm91cHMgb2YgYGNsaXBvbmF4aXMgIT09IGZhbHNlYCB0cmFjZXNcbiAgICAgICAgLy8gb24gYHBsb3RpbmZvLl9oYXNDbGlwT25BeGlzRmFsc2UgPT09IHRydWVgIHN1YnBsb3RzXG4gICAgICAgIHZhciBoYXNDbGlwT25BeGlzRmFsc2UgPSB0cmFjZS5jbGlwb25heGlzID09PSBmYWxzZTtcbiAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKHBsb3RHcm91cCwgaGFzQ2xpcE9uQXhpc0ZhbHNlID8gbnVsbCA6IHBsb3RpbmZvLmxheWVyQ2xpcElkLCBnZCk7XG4gICAgfSk7XG5cbiAgICAvLyBlcnJvciBiYXJzIGFyZSBvbiB0aGUgdG9wXG4gICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAncGxvdCcpKGdkLCBiYXJ0cmFjZXMsIHBsb3RpbmZvKTtcbn1cblxuZnVuY3Rpb24gYXBwZW5kQmFyVGV4dChnZCwgcGxvdGluZm8sIGJhciwgY2FsY1RyYWNlLCBpLCB4MCwgeDEsIHkwLCB5MSwgb3B0cykge1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgdGV4dFBvc2l0aW9uO1xuXG4gICAgZnVuY3Rpb24gYXBwZW5kVGV4dE5vZGUoYmFyLCB0ZXh0LCB0ZXh0Rm9udCkge1xuICAgICAgICB2YXIgdGV4dFNlbGVjdGlvbiA9IExpYi5lbnN1cmVTaW5nbGUoYmFyLCAndGV4dCcpXG4gICAgICAgICAgICAudGV4dCh0ZXh0KVxuICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICdjbGFzcyc6ICdiYXJ0ZXh0IGJhcnRleHQtJyArIHRleHRQb3NpdGlvbixcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICcnLFxuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6ICdtaWRkbGUnLFxuICAgICAgICAgICAgICAgIC8vIHByb2hpYml0IHRleCBpbnRlcnByZXRhdGlvbiB1bnRpbCB3ZSBjYW4gaGFuZGxlXG4gICAgICAgICAgICAgICAgLy8gdGV4IGFuZCByZWd1bGFyIHRleHQgdG9nZXRoZXJcbiAgICAgICAgICAgICAgICAnZGF0YS1ub3RleCc6IDFcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIHRleHRGb250KVxuICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgIHJldHVybiB0ZXh0U2VsZWN0aW9uO1xuICAgIH1cblxuICAgIC8vIGdldCB0cmFjZSBhdHRyaWJ1dGVzXG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgIHZhciBpc0hvcml6b250YWwgPSAodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJyk7XG5cbiAgICB2YXIgdGV4dCA9IGdldFRleHQoY2FsY1RyYWNlLCBpLCB4YSwgeWEpO1xuICAgIHRleHRQb3NpdGlvbiA9IGdldFRleHRQb3NpdGlvbih0cmFjZSwgaSk7XG5cbiAgICAvLyBjb21wdXRlIHRleHQgcG9zaXRpb25cbiAgICB2YXIgaW5TdGFja09yUmVsYXRpdmVNb2RlID1cbiAgICAgICAgb3B0cy5tb2RlID09PSAnc3RhY2snIHx8XG4gICAgICAgIG9wdHMubW9kZSA9PT0gJ3JlbGF0aXZlJztcblxuICAgIHZhciBjYWxjQmFyID0gY2FsY1RyYWNlW2ldO1xuICAgIHZhciBpc091dG1vc3RCYXIgPSAhaW5TdGFja09yUmVsYXRpdmVNb2RlIHx8IGNhbGNCYXIuX291dG1vc3Q7XG5cbiAgICBpZighdGV4dCB8fFxuICAgICAgICB0ZXh0UG9zaXRpb24gPT09ICdub25lJyB8fFxuICAgICAgICAoKGNhbGNCYXIuaXNCbGFuayB8fCB4MCA9PT0geDEgfHwgeTAgPT09IHkxKSAmJiAoXG4gICAgICAgICAgICB0ZXh0UG9zaXRpb24gPT09ICdhdXRvJyB8fFxuICAgICAgICAgICAgdGV4dFBvc2l0aW9uID09PSAnaW5zaWRlJykpKSB7XG4gICAgICAgIGJhci5zZWxlY3QoJ3RleHQnKS5yZW1vdmUoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBsYXlvdXRGb250ID0gZnVsbExheW91dC5mb250O1xuICAgIHZhciBiYXJDb2xvciA9IHN0eWxlLmdldEJhckNvbG9yKGNhbGNUcmFjZVtpXSwgdHJhY2UpO1xuICAgIHZhciBpbnNpZGVUZXh0Rm9udCA9IHN0eWxlLmdldEluc2lkZVRleHRGb250KHRyYWNlLCBpLCBsYXlvdXRGb250LCBiYXJDb2xvcik7XG4gICAgdmFyIG91dHNpZGVUZXh0Rm9udCA9IHN0eWxlLmdldE91dHNpZGVUZXh0Rm9udCh0cmFjZSwgaSwgbGF5b3V0Rm9udCk7XG5cbiAgICAvLyBTcGVjaWFsIGNhc2U6IGRvbid0IHVzZSB0aGUgYzJwKHYsIHRydWUpIHZhbHVlIG9uIGxvZyBzaXplIGF4ZXMsXG4gICAgLy8gc28gdGhhdCB3ZSBjYW4gZ2V0IGNvcnJlY3RseSBpbnNpZGUgdGV4dCBzY2FsaW5nXG4gICAgdmFyIGRpID0gYmFyLmRhdHVtKCk7XG4gICAgaWYoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgIGlmKHhhLnR5cGUgPT09ICdsb2cnICYmIGRpLnMwIDw9IDApIHtcbiAgICAgICAgICAgIGlmKHhhLnJhbmdlWzBdIDwgeGEucmFuZ2VbMV0pIHtcbiAgICAgICAgICAgICAgICB4MCA9IDA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHgwID0geGEuX2xlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKHlhLnR5cGUgPT09ICdsb2cnICYmIGRpLnMwIDw9IDApIHtcbiAgICAgICAgICAgIGlmKHlhLnJhbmdlWzBdIDwgeWEucmFuZ2VbMV0pIHtcbiAgICAgICAgICAgICAgICB5MCA9IHlhLl9sZW5ndGg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHkwID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHBhZGRpbmcgZXhjbHVkZWRcbiAgICB2YXIgYmFyV2lkdGggPSBNYXRoLmFicyh4MSAtIHgwKSAtIDIgKiBURVhUUEFEO1xuICAgIHZhciBiYXJIZWlnaHQgPSBNYXRoLmFicyh5MSAtIHkwKSAtIDIgKiBURVhUUEFEO1xuXG4gICAgdmFyIHRleHRTZWxlY3Rpb247XG4gICAgdmFyIHRleHRCQjtcbiAgICB2YXIgdGV4dFdpZHRoO1xuICAgIHZhciB0ZXh0SGVpZ2h0O1xuXG4gICAgaWYodGV4dFBvc2l0aW9uID09PSAnb3V0c2lkZScpIHtcbiAgICAgICAgaWYoIWlzT3V0bW9zdEJhciAmJiAhY2FsY0Jhci5oYXNCKSB0ZXh0UG9zaXRpb24gPSAnaW5zaWRlJztcbiAgICB9XG5cbiAgICBpZih0ZXh0UG9zaXRpb24gPT09ICdhdXRvJykge1xuICAgICAgICBpZihpc091dG1vc3RCYXIpIHtcbiAgICAgICAgICAgIC8vIGRyYXcgdGV4dCB1c2luZyBpbnNpZGVUZXh0Rm9udCBhbmQgY2hlY2sgaWYgaXQgZml0cyBpbnNpZGUgYmFyXG4gICAgICAgICAgICB0ZXh0UG9zaXRpb24gPSAnaW5zaWRlJztcbiAgICAgICAgICAgIHRleHRTZWxlY3Rpb24gPSBhcHBlbmRUZXh0Tm9kZShiYXIsIHRleHQsIGluc2lkZVRleHRGb250KTtcblxuICAgICAgICAgICAgdGV4dEJCID0gRHJhd2luZy5iQm94KHRleHRTZWxlY3Rpb24ubm9kZSgpKSxcbiAgICAgICAgICAgIHRleHRXaWR0aCA9IHRleHRCQi53aWR0aCxcbiAgICAgICAgICAgIHRleHRIZWlnaHQgPSB0ZXh0QkIuaGVpZ2h0O1xuXG4gICAgICAgICAgICB2YXIgdGV4dEhhc1NpemUgPSAodGV4dFdpZHRoID4gMCAmJiB0ZXh0SGVpZ2h0ID4gMCk7XG4gICAgICAgICAgICB2YXIgZml0c0luc2lkZSA9ICh0ZXh0V2lkdGggPD0gYmFyV2lkdGggJiYgdGV4dEhlaWdodCA8PSBiYXJIZWlnaHQpO1xuICAgICAgICAgICAgdmFyIGZpdHNJbnNpZGVJZlJvdGF0ZWQgPSAodGV4dFdpZHRoIDw9IGJhckhlaWdodCAmJiB0ZXh0SGVpZ2h0IDw9IGJhcldpZHRoKTtcbiAgICAgICAgICAgIHZhciBmaXRzSW5zaWRlSWZTaHJ1bmsgPSAoaXNIb3Jpem9udGFsKSA/XG4gICAgICAgICAgICAgICAgKGJhcldpZHRoID49IHRleHRXaWR0aCAqIChiYXJIZWlnaHQgLyB0ZXh0SGVpZ2h0KSkgOlxuICAgICAgICAgICAgICAgIChiYXJIZWlnaHQgPj0gdGV4dEhlaWdodCAqIChiYXJXaWR0aCAvIHRleHRXaWR0aCkpO1xuXG4gICAgICAgICAgICBpZih0ZXh0SGFzU2l6ZSAmJiAoXG4gICAgICAgICAgICAgICAgZml0c0luc2lkZSB8fFxuICAgICAgICAgICAgICAgIGZpdHNJbnNpZGVJZlJvdGF0ZWQgfHxcbiAgICAgICAgICAgICAgICBmaXRzSW5zaWRlSWZTaHJ1bmspXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICB0ZXh0UG9zaXRpb24gPSAnaW5zaWRlJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGV4dFBvc2l0aW9uID0gJ291dHNpZGUnO1xuICAgICAgICAgICAgICAgIHRleHRTZWxlY3Rpb24ucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgdGV4dFNlbGVjdGlvbiA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0ZXh0UG9zaXRpb24gPSAnaW5zaWRlJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKCF0ZXh0U2VsZWN0aW9uKSB7XG4gICAgICAgIHRleHRTZWxlY3Rpb24gPSBhcHBlbmRUZXh0Tm9kZShiYXIsIHRleHQsXG4gICAgICAgICAgICAgICAgKHRleHRQb3NpdGlvbiA9PT0gJ291dHNpZGUnKSA/XG4gICAgICAgICAgICAgICAgb3V0c2lkZVRleHRGb250IDogaW5zaWRlVGV4dEZvbnQpO1xuXG4gICAgICAgIHRleHRCQiA9IERyYXdpbmcuYkJveCh0ZXh0U2VsZWN0aW9uLm5vZGUoKSksXG4gICAgICAgIHRleHRXaWR0aCA9IHRleHRCQi53aWR0aCxcbiAgICAgICAgdGV4dEhlaWdodCA9IHRleHRCQi5oZWlnaHQ7XG5cbiAgICAgICAgaWYodGV4dFdpZHRoIDw9IDAgfHwgdGV4dEhlaWdodCA8PSAwKSB7XG4gICAgICAgICAgICB0ZXh0U2VsZWN0aW9uLnJlbW92ZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gY29tcHV0ZSB0ZXh0IHRyYW5zZm9ybVxuICAgIHZhciB0cmFuc2Zvcm0sIGNvbnN0cmFpbmVkO1xuICAgIGlmKHRleHRQb3NpdGlvbiA9PT0gJ291dHNpZGUnKSB7XG4gICAgICAgIGNvbnN0cmFpbmVkID1cbiAgICAgICAgICAgIHRyYWNlLmNvbnN0cmFpbnRleHQgPT09ICdib3RoJyB8fFxuICAgICAgICAgICAgdHJhY2UuY29uc3RyYWludGV4dCA9PT0gJ291dHNpZGUnO1xuXG4gICAgICAgIHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybSh0b01vdmVPdXRzaWRlQmFyKHgwLCB4MSwgeTAsIHkxLCB0ZXh0QkIsIHtcbiAgICAgICAgICAgIGlzSG9yaXpvbnRhbDogaXNIb3Jpem9udGFsLFxuICAgICAgICAgICAgY29uc3RyYWluZWQ6IGNvbnN0cmFpbmVkLFxuICAgICAgICAgICAgYW5nbGU6IHRyYWNlLnRleHRhbmdsZVxuICAgICAgICB9KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3RyYWluZWQgPVxuICAgICAgICAgICAgdHJhY2UuY29uc3RyYWludGV4dCA9PT0gJ2JvdGgnIHx8XG4gICAgICAgICAgICB0cmFjZS5jb25zdHJhaW50ZXh0ID09PSAnaW5zaWRlJztcblxuICAgICAgICB0cmFuc2Zvcm0gPSBnZXRUcmFuc2Zvcm0odG9Nb3ZlSW5zaWRlQmFyKHgwLCB4MSwgeTAsIHkxLCB0ZXh0QkIsIHtcbiAgICAgICAgICAgIGlzSG9yaXpvbnRhbDogaXNIb3Jpem9udGFsLFxuICAgICAgICAgICAgY29uc3RyYWluZWQ6IGNvbnN0cmFpbmVkLFxuICAgICAgICAgICAgYW5nbGU6IHRyYWNlLnRleHRhbmdsZSxcbiAgICAgICAgICAgIGFuY2hvcjogdHJhY2UuaW5zaWRldGV4dGFuY2hvclxuICAgICAgICB9KSk7XG4gICAgfVxuXG4gICAgdGV4dFNlbGVjdGlvbi5hdHRyKCd0cmFuc2Zvcm0nLCB0cmFuc2Zvcm0pO1xufVxuXG5mdW5jdGlvbiBnZXRSb3RhdGVGcm9tQW5nbGUoYW5nbGUpIHtcbiAgICByZXR1cm4gKGFuZ2xlID09PSAnYXV0bycpID8gMCA6IGFuZ2xlO1xufVxuXG5mdW5jdGlvbiB0b01vdmVJbnNpZGVCYXIoeDAsIHgxLCB5MCwgeTEsIHRleHRCQiwgb3B0cykge1xuICAgIHZhciBpc0hvcml6b250YWwgPSAhIW9wdHMuaXNIb3Jpem9udGFsO1xuICAgIHZhciBjb25zdHJhaW5lZCA9ICEhb3B0cy5jb25zdHJhaW5lZDtcbiAgICB2YXIgYW5nbGUgPSBvcHRzLmFuZ2xlIHx8IDA7XG4gICAgdmFyIGFuY2hvciA9IG9wdHMuYW5jaG9yIHx8IDA7XG5cbiAgICB2YXIgdGV4dFdpZHRoID0gdGV4dEJCLndpZHRoO1xuICAgIHZhciB0ZXh0SGVpZ2h0ID0gdGV4dEJCLmhlaWdodDtcbiAgICB2YXIgbHggPSBNYXRoLmFicyh4MSAtIHgwKTtcbiAgICB2YXIgbHkgPSBNYXRoLmFicyh5MSAtIHkwKTtcblxuICAgIHZhciB0ZXh0cGFkID0gKFxuICAgICAgICBseCA+ICgyICogVEVYVFBBRCkgJiZcbiAgICAgICAgbHkgPiAoMiAqIFRFWFRQQUQpXG4gICAgKSA/IFRFWFRQQUQgOiAwO1xuXG4gICAgbHggLT0gMiAqIHRleHRwYWQ7XG4gICAgbHkgLT0gMiAqIHRleHRwYWQ7XG5cbiAgICB2YXIgYXV0b1JvdGF0ZSA9IChhbmdsZSA9PT0gJ2F1dG8nKTtcbiAgICB2YXIgaXNBdXRvUm90YXRlZCA9IGZhbHNlO1xuICAgIGlmKGF1dG9Sb3RhdGUgJiZcbiAgICAgICAgISh0ZXh0V2lkdGggPD0gbHggJiYgdGV4dEhlaWdodCA8PSBseSkgJiZcbiAgICAgICAgKHRleHRXaWR0aCA+IGx4IHx8IHRleHRIZWlnaHQgPiBseSkgJiYgKFxuICAgICAgICAhKHRleHRXaWR0aCA+IGx5IHx8IHRleHRIZWlnaHQgPiBseCkgfHxcbiAgICAgICAgKCh0ZXh0V2lkdGggPCB0ZXh0SGVpZ2h0KSAhPT0gKGx4IDwgbHkpKVxuICAgICkpIHtcbiAgICAgICAgaXNBdXRvUm90YXRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYoaXNBdXRvUm90YXRlZCkge1xuICAgICAgICAvLyBkb24ndCByb3RhdGUgeWV0IG9ubHkgc3dhcCBiYXIgd2lkdGggd2l0aCBoZWlnaHRcbiAgICAgICAgdmFyIHRtcCA9IGx5O1xuICAgICAgICBseSA9IGx4O1xuICAgICAgICBseCA9IHRtcDtcbiAgICB9XG5cbiAgICB2YXIgcm90YXRlID0gZ2V0Um90YXRlRnJvbUFuZ2xlKGFuZ2xlKTtcbiAgICB2YXIgYWJzU2luID0gTWF0aC5hYnMoTWF0aC5zaW4oTWF0aC5QSSAvIDE4MCAqIHJvdGF0ZSkpO1xuICAgIHZhciBhYnNDb3MgPSBNYXRoLmFicyhNYXRoLmNvcyhNYXRoLlBJIC8gMTgwICogcm90YXRlKSk7XG5cbiAgICAvLyBjb21wdXRlIGFuZCBhcHBseSB0ZXh0IHBhZGRpbmdcbiAgICB2YXIgZHggPSBNYXRoLm1heChseCAqIGFic0NvcywgbHkgKiBhYnNTaW4pO1xuICAgIHZhciBkeSA9IE1hdGgubWF4KGx4ICogYWJzU2luLCBseSAqIGFic0Nvcyk7XG5cbiAgICB2YXIgc2NhbGUgPSAoY29uc3RyYWluZWQpID9cbiAgICAgICAgTWF0aC5taW4oZHggLyB0ZXh0V2lkdGgsIGR5IC8gdGV4dEhlaWdodCkgOlxuICAgICAgICBNYXRoLm1heChhYnNDb3MsIGFic1Npbik7XG5cbiAgICBzY2FsZSA9IE1hdGgubWluKDEsIHNjYWxlKTtcblxuICAgIC8vIGNvbXB1dGUgdGV4dCBhbmQgdGFyZ2V0IHBvc2l0aW9uc1xuICAgIHZhciB0YXJnZXRYID0gKHgwICsgeDEpIC8gMjtcbiAgICB2YXIgdGFyZ2V0WSA9ICh5MCArIHkxKSAvIDI7XG5cbiAgICBpZihhbmNob3IgIT09ICdtaWRkbGUnKSB7IC8vIGNhc2Ugb2YgJ3N0YXJ0JyBvciAnZW5kJ1xuICAgICAgICB2YXIgdGFyZ2V0V2lkdGggPSBzY2FsZSAqIChpc0hvcml6b250YWwgIT09IGlzQXV0b1JvdGF0ZWQgPyB0ZXh0SGVpZ2h0IDogdGV4dFdpZHRoKTtcbiAgICAgICAgdmFyIHRhcmdldEhlaWdodCA9IHNjYWxlICogKGlzSG9yaXpvbnRhbCAhPT0gaXNBdXRvUm90YXRlZCA/IHRleHRXaWR0aCA6IHRleHRIZWlnaHQpO1xuICAgICAgICB0ZXh0cGFkICs9IDAuNSAqICh0YXJnZXRXaWR0aCAqIGFic1NpbiArIHRhcmdldEhlaWdodCAqIGFic0Nvcyk7XG5cbiAgICAgICAgaWYoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICB0ZXh0cGFkICo9IGRpclNpZ24oeDAsIHgxKTtcbiAgICAgICAgICAgIHRhcmdldFggPSAoYW5jaG9yID09PSAnc3RhcnQnKSA/IHgwICsgdGV4dHBhZCA6IHgxIC0gdGV4dHBhZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRleHRwYWQgKj0gZGlyU2lnbih5MCwgeTEpO1xuICAgICAgICAgICAgdGFyZ2V0WSA9IChhbmNob3IgPT09ICdzdGFydCcpID8geTAgKyB0ZXh0cGFkIDogeTEgLSB0ZXh0cGFkO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHRleHRYID0gKHRleHRCQi5sZWZ0ICsgdGV4dEJCLnJpZ2h0KSAvIDI7XG4gICAgdmFyIHRleHRZID0gKHRleHRCQi50b3AgKyB0ZXh0QkIuYm90dG9tKSAvIDI7XG5cbiAgICAvLyBsYXN0bHkgYXBwbHkgYXV0byByb3RhdGlvblxuICAgIGlmKGlzQXV0b1JvdGF0ZWQpIHJvdGF0ZSArPSA5MDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHRleHRYOiB0ZXh0WCxcbiAgICAgICAgdGV4dFk6IHRleHRZLFxuICAgICAgICB0YXJnZXRYOiB0YXJnZXRYLFxuICAgICAgICB0YXJnZXRZOiB0YXJnZXRZLFxuICAgICAgICBzY2FsZTogc2NhbGUsXG4gICAgICAgIHJvdGF0ZTogcm90YXRlXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gdG9Nb3ZlT3V0c2lkZUJhcih4MCwgeDEsIHkwLCB5MSwgdGV4dEJCLCBvcHRzKSB7XG4gICAgdmFyIGlzSG9yaXpvbnRhbCA9ICEhb3B0cy5pc0hvcml6b250YWw7XG4gICAgdmFyIGNvbnN0cmFpbmVkID0gISFvcHRzLmNvbnN0cmFpbmVkO1xuICAgIHZhciBhbmdsZSA9IG9wdHMuYW5nbGUgfHwgMDtcblxuICAgIHZhciB0ZXh0V2lkdGggPSB0ZXh0QkIud2lkdGg7XG4gICAgdmFyIHRleHRIZWlnaHQgPSB0ZXh0QkIuaGVpZ2h0O1xuICAgIHZhciBseCA9IE1hdGguYWJzKHgxIC0geDApO1xuICAgIHZhciBseSA9IE1hdGguYWJzKHkxIC0geTApO1xuXG4gICAgdmFyIHRleHRwYWQ7XG4gICAgLy8gS2VlcCB0aGUgcGFkZGluZyBzbyB0aGUgdGV4dCBkb2Vzbid0IHNpdCByaWdodCBhZ2FpbnN0XG4gICAgLy8gdGhlIGJhcnMsIGJ1dCBkb24ndCBmYWN0b3IgaXQgaW50byBiYXJXaWR0aFxuICAgIGlmKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICB0ZXh0cGFkID0gKGx5ID4gMiAqIFRFWFRQQUQpID8gVEVYVFBBRCA6IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGV4dHBhZCA9IChseCA+IDIgKiBURVhUUEFEKSA/IFRFWFRQQUQgOiAwO1xuICAgIH1cblxuICAgIC8vIGNvbXB1dGUgcm90YXRlIGFuZCBzY2FsZVxuICAgIHZhciBzY2FsZSA9IDE7XG4gICAgaWYoY29uc3RyYWluZWQpIHtcbiAgICAgICAgc2NhbGUgPSAoaXNIb3Jpem9udGFsKSA/XG4gICAgICAgICAgICBNYXRoLm1pbigxLCBseSAvIHRleHRIZWlnaHQpIDpcbiAgICAgICAgICAgIE1hdGgubWluKDEsIGx4IC8gdGV4dFdpZHRoKTtcbiAgICB9XG5cbiAgICB2YXIgcm90YXRlID0gZ2V0Um90YXRlRnJvbUFuZ2xlKGFuZ2xlKTtcbiAgICB2YXIgYWJzU2luID0gTWF0aC5hYnMoTWF0aC5zaW4oTWF0aC5QSSAvIDE4MCAqIHJvdGF0ZSkpO1xuICAgIHZhciBhYnNDb3MgPSBNYXRoLmFicyhNYXRoLmNvcyhNYXRoLlBJIC8gMTgwICogcm90YXRlKSk7XG5cbiAgICAvLyBjb21wdXRlIHRleHQgYW5kIHRhcmdldCBwb3NpdGlvbnNcbiAgICB2YXIgdGFyZ2V0V2lkdGggPSBzY2FsZSAqIChpc0hvcml6b250YWwgPyB0ZXh0SGVpZ2h0IDogdGV4dFdpZHRoKTtcbiAgICB2YXIgdGFyZ2V0SGVpZ2h0ID0gc2NhbGUgKiAoaXNIb3Jpem9udGFsID8gdGV4dFdpZHRoIDogdGV4dEhlaWdodCk7XG4gICAgdGV4dHBhZCArPSAwLjUgKiAodGFyZ2V0V2lkdGggKiBhYnNTaW4gKyB0YXJnZXRIZWlnaHQgKiBhYnNDb3MpO1xuXG4gICAgdmFyIHRhcmdldFggPSAoeDAgKyB4MSkgLyAyO1xuICAgIHZhciB0YXJnZXRZID0gKHkwICsgeTEpIC8gMjtcblxuICAgIGlmKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICB0YXJnZXRYID0geDEgLSB0ZXh0cGFkICogZGlyU2lnbih4MSwgeDApO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRhcmdldFkgPSB5MSArIHRleHRwYWQgKiBkaXJTaWduKHkwLCB5MSk7XG4gICAgfVxuXG4gICAgdmFyIHRleHRYID0gKHRleHRCQi5sZWZ0ICsgdGV4dEJCLnJpZ2h0KSAvIDI7XG4gICAgdmFyIHRleHRZID0gKHRleHRCQi50b3AgKyB0ZXh0QkIuYm90dG9tKSAvIDI7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB0ZXh0WDogdGV4dFgsXG4gICAgICAgIHRleHRZOiB0ZXh0WSxcbiAgICAgICAgdGFyZ2V0WDogdGFyZ2V0WCxcbiAgICAgICAgdGFyZ2V0WTogdGFyZ2V0WSxcbiAgICAgICAgc2NhbGU6IHNjYWxlLFxuICAgICAgICByb3RhdGU6IHJvdGF0ZVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldFRyYW5zZm9ybShvcHRzKSB7XG4gICAgdmFyIHRleHRYID0gb3B0cy50ZXh0WDtcbiAgICB2YXIgdGV4dFkgPSBvcHRzLnRleHRZO1xuICAgIHZhciB0YXJnZXRYID0gb3B0cy50YXJnZXRYO1xuICAgIHZhciB0YXJnZXRZID0gb3B0cy50YXJnZXRZO1xuICAgIHZhciBzY2FsZSA9IG9wdHMuc2NhbGU7XG4gICAgdmFyIHJvdGF0ZSA9IG9wdHMucm90YXRlO1xuXG4gICAgdmFyIHRyYW5zZm9ybVNjYWxlO1xuICAgIHZhciB0cmFuc2Zvcm1Sb3RhdGU7XG4gICAgdmFyIHRyYW5zZm9ybVRyYW5zbGF0ZTtcblxuICAgIGlmKHNjYWxlIDwgMSkgdHJhbnNmb3JtU2NhbGUgPSAnc2NhbGUoJyArIHNjYWxlICsgJykgJztcbiAgICBlbHNlIHtcbiAgICAgICAgc2NhbGUgPSAxO1xuICAgICAgICB0cmFuc2Zvcm1TY2FsZSA9ICcnO1xuICAgIH1cblxuICAgIHRyYW5zZm9ybVJvdGF0ZSA9IChyb3RhdGUpID9cbiAgICAgICAgJ3JvdGF0ZSgnICsgcm90YXRlICsgJyAnICsgdGV4dFggKyAnICcgKyB0ZXh0WSArICcpICcgOiAnJztcblxuICAgIC8vIE5vdGUgdGhhdCBzY2FsaW5nIGFsc28gYWZmZWN0cyB0aGUgY2VudGVyIG9mIHRoZSB0ZXh0IGJveFxuICAgIHZhciB0cmFuc2xhdGVYID0gKHRhcmdldFggLSBzY2FsZSAqIHRleHRYKTtcbiAgICB2YXIgdHJhbnNsYXRlWSA9ICh0YXJnZXRZIC0gc2NhbGUgKiB0ZXh0WSk7XG4gICAgdHJhbnNmb3JtVHJhbnNsYXRlID0gJ3RyYW5zbGF0ZSgnICsgdHJhbnNsYXRlWCArICcgJyArIHRyYW5zbGF0ZVkgKyAnKSc7XG5cbiAgICByZXR1cm4gdHJhbnNmb3JtVHJhbnNsYXRlICsgdHJhbnNmb3JtU2NhbGUgKyB0cmFuc2Zvcm1Sb3RhdGU7XG59XG5cbmZ1bmN0aW9uIGdldFRleHQoY2FsY1RyYWNlLCBpbmRleCwgeGEsIHlhKSB7XG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuXG4gICAgdmFyIHZhbHVlO1xuICAgIGlmKCF0cmFjZS50ZXh0aW5mbykge1xuICAgICAgICB2YWx1ZSA9IGhlbHBlcnMuZ2V0VmFsdWUodHJhY2UudGV4dCwgaW5kZXgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhbHVlID0gY2FsY1RleHRpbmZvKGNhbGNUcmFjZSwgaW5kZXgsIHhhLCB5YSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGhlbHBlcnMuY29lcmNlU3RyaW5nKGF0dHJpYnV0ZVRleHQsIHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gZ2V0VGV4dFBvc2l0aW9uKHRyYWNlLCBpbmRleCkge1xuICAgIHZhciB2YWx1ZSA9IGhlbHBlcnMuZ2V0VmFsdWUodHJhY2UudGV4dHBvc2l0aW9uLCBpbmRleCk7XG4gICAgcmV0dXJuIGhlbHBlcnMuY29lcmNlRW51bWVyYXRlZChhdHRyaWJ1dGVUZXh0UG9zaXRpb24sIHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FsY1RleHRpbmZvKGNhbGNUcmFjZSwgaW5kZXgsIHhhLCB5YSkge1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcbiAgICB2YXIgaXNIb3Jpem9udGFsID0gKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpO1xuICAgIHZhciBpc1dhdGVyZmFsbCA9ICh0cmFjZS50eXBlID09PSAnd2F0ZXJmYWxsJyk7XG4gICAgdmFyIGlzRnVubmVsID0gKHRyYWNlLnR5cGUgPT09ICdmdW5uZWwnKTtcblxuICAgIGZ1bmN0aW9uIGZvcm1hdExhYmVsKHUpIHtcbiAgICAgICAgdmFyIHBBeGlzID0gaXNIb3Jpem9udGFsID8geWEgOiB4YTtcbiAgICAgICAgcmV0dXJuIHRpY2tUZXh0KHBBeGlzLCB1LCB0cnVlKS50ZXh0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZvcm1hdE51bWJlcih2KSB7XG4gICAgICAgIHZhciBzQXhpcyA9IGlzSG9yaXpvbnRhbCA/IHhhIDogeWE7XG4gICAgICAgIHJldHVybiB0aWNrVGV4dChzQXhpcywgK3YsIHRydWUpLnRleHQ7XG4gICAgfVxuXG4gICAgdmFyIHRleHRpbmZvID0gdHJhY2UudGV4dGluZm87XG4gICAgdmFyIGNkaSA9IGNhbGNUcmFjZVtpbmRleF07XG5cbiAgICB2YXIgcGFydHMgPSB0ZXh0aW5mby5zcGxpdCgnKycpO1xuICAgIHZhciB0ZXh0ID0gW107XG4gICAgdmFyIHR4O1xuXG4gICAgdmFyIGhhc0ZsYWcgPSBmdW5jdGlvbihmbGFnKSB7IHJldHVybiBwYXJ0cy5pbmRleE9mKGZsYWcpICE9PSAtMTsgfTtcblxuICAgIGlmKGhhc0ZsYWcoJ2xhYmVsJykpIHtcbiAgICAgICAgdGV4dC5wdXNoKGZvcm1hdExhYmVsKGNhbGNUcmFjZVtpbmRleF0ucCkpO1xuICAgIH1cblxuICAgIGlmKGhhc0ZsYWcoJ3RleHQnKSkge1xuICAgICAgICB0eCA9IExpYi5jYXN0T3B0aW9uKHRyYWNlLCBjZGkuaSwgJ3RleHQnKTtcbiAgICAgICAgaWYodHggPT09IDAgfHwgdHgpIHRleHQucHVzaCh0eCk7XG4gICAgfVxuXG4gICAgaWYoaXNXYXRlcmZhbGwpIHtcbiAgICAgICAgdmFyIGRlbHRhID0gK2NkaS5yYXdTIHx8IGNkaS5zO1xuICAgICAgICB2YXIgZmluYWwgPSBjZGkudjtcbiAgICAgICAgdmFyIGluaXRpYWwgPSBmaW5hbCAtIGRlbHRhO1xuXG4gICAgICAgIGlmKGhhc0ZsYWcoJ2luaXRpYWwnKSkgdGV4dC5wdXNoKGZvcm1hdE51bWJlcihpbml0aWFsKSk7XG4gICAgICAgIGlmKGhhc0ZsYWcoJ2RlbHRhJykpIHRleHQucHVzaChmb3JtYXROdW1iZXIoZGVsdGEpKTtcbiAgICAgICAgaWYoaGFzRmxhZygnZmluYWwnKSkgdGV4dC5wdXNoKGZvcm1hdE51bWJlcihmaW5hbCkpO1xuICAgIH1cblxuICAgIGlmKGlzRnVubmVsKSB7XG4gICAgICAgIGlmKGhhc0ZsYWcoJ3ZhbHVlJykpIHRleHQucHVzaChmb3JtYXROdW1iZXIoY2RpLnMpKTtcblxuICAgICAgICB2YXIgblBlcmNlbnQgPSAwO1xuICAgICAgICBpZihoYXNGbGFnKCdwZXJjZW50IGluaXRpYWwnKSkgblBlcmNlbnQrKztcbiAgICAgICAgaWYoaGFzRmxhZygncGVyY2VudCBwcmV2aW91cycpKSBuUGVyY2VudCsrO1xuICAgICAgICBpZihoYXNGbGFnKCdwZXJjZW50IHRvdGFsJykpIG5QZXJjZW50Kys7XG5cbiAgICAgICAgdmFyIGhhc011bHRpcGxlUGVyY2VudHMgPSBuUGVyY2VudCA+IDE7XG5cbiAgICAgICAgaWYoaGFzRmxhZygncGVyY2VudCBpbml0aWFsJykpIHtcbiAgICAgICAgICAgIHR4ID0gTGliLmZvcm1hdFBlcmNlbnQoY2RpLmJlZ1IpO1xuICAgICAgICAgICAgaWYoaGFzTXVsdGlwbGVQZXJjZW50cykgdHggKz0gJyBvZiBpbml0aWFsJztcbiAgICAgICAgICAgIHRleHQucHVzaCh0eCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaGFzRmxhZygncGVyY2VudCBwcmV2aW91cycpKSB7XG4gICAgICAgICAgICB0eCA9IExpYi5mb3JtYXRQZXJjZW50KGNkaS5kaWZSKTtcbiAgICAgICAgICAgIGlmKGhhc011bHRpcGxlUGVyY2VudHMpIHR4ICs9ICcgb2YgcHJldmlvdXMnO1xuICAgICAgICAgICAgdGV4dC5wdXNoKHR4KTtcbiAgICAgICAgfVxuICAgICAgICBpZihoYXNGbGFnKCdwZXJjZW50IHRvdGFsJykpIHtcbiAgICAgICAgICAgIHR4ID0gTGliLmZvcm1hdFBlcmNlbnQoY2RpLnN1bVIpO1xuICAgICAgICAgICAgaWYoaGFzTXVsdGlwbGVQZXJjZW50cykgdHggKz0gJyBvZiB0b3RhbCc7XG4gICAgICAgICAgICB0ZXh0LnB1c2godHgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRleHQuam9pbignPGJyPicpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBwbG90OiBwbG90LFxuICAgIGdldFRyYW5zZm9ybTogZ2V0VHJhbnNmb3JtLFxuICAgIHRvTW92ZUluc2lkZUJhcjogdG9Nb3ZlSW5zaWRlQmFyLFxuICAgIHRvTW92ZU91dHNpZGVCYXI6IHRvTW92ZU91dHNpZGVCYXJcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2F0dHJpYnV0ZXNcIjo4NTcsXCIuL2hlbHBlcnNcIjo4NjIsXCIuL3N0eWxlXCI6ODcwLFwiZDNcIjoxNjMsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDg2ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2VsZWN0UG9pbnRzKHNlYXJjaEluZm8sIHNlbGVjdGlvblRlc3Rlcikge1xuICAgIHZhciBjZCA9IHNlYXJjaEluZm8uY2Q7XG4gICAgdmFyIHhhID0gc2VhcmNoSW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBzZWFyY2hJbmZvLnlheGlzO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciBpc0Z1bm5lbCA9ICh0cmFjZS50eXBlID09PSAnZnVubmVsJyk7XG4gICAgdmFyIGlzSG9yaXpvbnRhbCA9ICh0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKTtcbiAgICB2YXIgc2VsZWN0aW9uID0gW107XG4gICAgdmFyIGk7XG5cbiAgICBpZihzZWxlY3Rpb25UZXN0ZXIgPT09IGZhbHNlKSB7XG4gICAgICAgIC8vIGNsZWFyIHNlbGVjdGlvblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBkaSA9IGNkW2ldO1xuICAgICAgICAgICAgdmFyIGN0ID0gJ2N0JyBpbiBkaSA/IGRpLmN0IDogZ2V0Q2VudHJvaWQoZGksIHhhLCB5YSwgaXNIb3Jpem9udGFsLCBpc0Z1bm5lbCk7XG5cbiAgICAgICAgICAgIGlmKHNlbGVjdGlvblRlc3Rlci5jb250YWlucyhjdCwgZmFsc2UsIGksIHNlYXJjaEluZm8pKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogaSxcbiAgICAgICAgICAgICAgICAgICAgeDogeGEuYzJkKGRpLngpLFxuICAgICAgICAgICAgICAgICAgICB5OiB5YS5jMmQoZGkueSlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBkaS5zZWxlY3RlZCA9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRpLnNlbGVjdGVkID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzZWxlY3Rpb247XG59O1xuXG5mdW5jdGlvbiBnZXRDZW50cm9pZChkLCB4YSwgeWEsIGlzSG9yaXpvbnRhbCwgaXNGdW5uZWwpIHtcbiAgICB2YXIgeDAgPSB4YS5jMnAoaXNIb3Jpem9udGFsID8gZC5zMCA6IGQucDAsIHRydWUpO1xuICAgIHZhciB4MSA9IHhhLmMycChpc0hvcml6b250YWwgPyBkLnMxIDogZC5wMSwgdHJ1ZSk7XG4gICAgdmFyIHkwID0geWEuYzJwKGlzSG9yaXpvbnRhbCA/IGQucDAgOiBkLnMwLCB0cnVlKTtcbiAgICB2YXIgeTEgPSB5YS5jMnAoaXNIb3Jpem9udGFsID8gZC5wMSA6IGQuczEsIHRydWUpO1xuXG4gICAgaWYoaXNGdW5uZWwpIHtcbiAgICAgICAgcmV0dXJuIFsoeDAgKyB4MSkgLyAyLCAoeTAgKyB5MSkgLyAyXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZihpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgIHJldHVybiBbeDEsICh5MCArIHkxKSAvIDJdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIFsoeDAgKyB4MSkgLyAyLCB5MV07XG4gICAgICAgIH1cbiAgICB9XG59XG5cbn0se31dLDg2OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gU2lldmU7XG5cbnZhciBkaXN0aW5jdFZhbHMgPSBfZGVyZXFfKCcuLi8uLi9saWInKS5kaXN0aW5jdFZhbHM7XG52YXIgQkFETlVNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxuLyoqXG4gKiBIZWxwZXIgY2xhc3MgdG8gc2lldmUgZGF0YSBmcm9tIHRyYWNlcyBpbnRvIGJpbnNcbiAqXG4gKiBAY2xhc3NcbiAqXG4gKiBAcGFyYW0ge0FycmF5fSB0cmFjZXNcbiogICBBcnJheSBvZiBjYWxjdWxhdGVkIHRyYWNlc1xuICogQHBhcmFtIHtvYmplY3R9IG9wdHNcbiAqICAtIEBwYXJhbSB7Ym9vbGVhbn0gW3NlcE5lZ1ZhbF1cbiAqICAgICAgSWYgdHJ1ZSwgdGhlbiBzcGxpdCBkYXRhIGF0IHRoZSBzYW1lIHBvc2l0aW9uIGludG8gYSBiYXJcbiAqICAgICAgZm9yIHBvc2l0aXZlIHZhbHVlcyBhbmQgYW5vdGhlciBmb3IgbmVnYXRpdmUgdmFsdWVzXG4gKiAgLSBAcGFyYW0ge2Jvb2xlYW59IFtvdmVybGFwTm9NZXJnZV1cbiAqICAgICBJZiB0cnVlLCB0aGVuIGRvbid0IG1lcmdlIG92ZXJsYXBwaW5nIGJhcnMgaW50byBhIHNpbmdsZSBiYXJcbiAqL1xuZnVuY3Rpb24gU2lldmUodHJhY2VzLCBvcHRzKSB7XG4gICAgdGhpcy50cmFjZXMgPSB0cmFjZXM7XG4gICAgdGhpcy5zZXBOZWdWYWwgPSBvcHRzLnNlcE5lZ1ZhbDtcbiAgICB0aGlzLm92ZXJsYXBOb01lcmdlID0gb3B0cy5vdmVybGFwTm9NZXJnZTtcblxuICAgIC8vIGZvciBzaW5nbGUtYmluIGhpc3RvZ3JhbXMgLSBzZWUgaGlzdG9ncmFtL2NhbGNcbiAgICB2YXIgd2lkdGgxID0gSW5maW5pdHk7XG5cbiAgICB2YXIgcG9zaXRpb25zID0gW107XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2UgPSB0cmFjZXNbaV07XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCB0cmFjZS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGJhciA9IHRyYWNlW2pdO1xuICAgICAgICAgICAgaWYoYmFyLnAgIT09IEJBRE5VTSkgcG9zaXRpb25zLnB1c2goYmFyLnApO1xuICAgICAgICB9XG4gICAgICAgIGlmKHRyYWNlWzBdICYmIHRyYWNlWzBdLndpZHRoMSkge1xuICAgICAgICAgICAgd2lkdGgxID0gTWF0aC5taW4odHJhY2VbMF0ud2lkdGgxLCB3aWR0aDEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRoaXMucG9zaXRpb25zID0gcG9zaXRpb25zO1xuXG4gICAgdmFyIGR2ID0gZGlzdGluY3RWYWxzKHBvc2l0aW9ucyk7XG4gICAgdGhpcy5kaXN0aW5jdFBvc2l0aW9ucyA9IGR2LnZhbHM7XG4gICAgaWYoZHYudmFscy5sZW5ndGggPT09IDEgJiYgd2lkdGgxICE9PSBJbmZpbml0eSkgdGhpcy5taW5EaWZmID0gd2lkdGgxO1xuICAgIGVsc2UgdGhpcy5taW5EaWZmID0gTWF0aC5taW4oZHYubWluRGlmZiwgd2lkdGgxKTtcblxuICAgIHRoaXMuYmluV2lkdGggPSB0aGlzLm1pbkRpZmY7XG5cbiAgICB0aGlzLmJpbnMgPSB7fTtcbn1cblxuLyoqXG4gKiBTaWV2ZSBkYXR1bVxuICpcbiAqIEBtZXRob2RcbiAqIEBwYXJhbSB7bnVtYmVyfSBwb3NpdGlvblxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBQcmV2aW91cyBiaW4gdmFsdWVcbiAqL1xuU2lldmUucHJvdG90eXBlLnB1dCA9IGZ1bmN0aW9uIHB1dChwb3NpdGlvbiwgdmFsdWUpIHtcbiAgICB2YXIgbGFiZWwgPSB0aGlzLmdldExhYmVsKHBvc2l0aW9uLCB2YWx1ZSk7XG4gICAgdmFyIG9sZFZhbHVlID0gdGhpcy5iaW5zW2xhYmVsXSB8fCAwO1xuXG4gICAgdGhpcy5iaW5zW2xhYmVsXSA9IG9sZFZhbHVlICsgdmFsdWU7XG5cbiAgICByZXR1cm4gb2xkVmFsdWU7XG59O1xuXG4vKipcbiAqIEdldCBjdXJyZW50IGJpbiB2YWx1ZSBmb3IgYSBnaXZlbiBkYXR1bVxuICpcbiAqIEBtZXRob2RcbiAqIEBwYXJhbSB7bnVtYmVyfSBwb3NpdGlvbiAgUG9zaXRpb24gb2YgZGF0dW1cbiAqIEBwYXJhbSB7bnVtYmVyfSBbdmFsdWVdICAgVmFsdWUgb2YgZGF0dW1cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgKHJlcXVpcmVkIGlmIHRoaXMuc2VwTmVnVmFsIGlzIHRydWUpXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBDdXJyZW50IGJpbiB2YWx1ZVxuICovXG5TaWV2ZS5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gZ2V0KHBvc2l0aW9uLCB2YWx1ZSkge1xuICAgIHZhciBsYWJlbCA9IHRoaXMuZ2V0TGFiZWwocG9zaXRpb24sIHZhbHVlKTtcbiAgICByZXR1cm4gdGhpcy5iaW5zW2xhYmVsXSB8fCAwO1xufTtcblxuLyoqXG4gKiBHZXQgYmluIGxhYmVsIGZvciBhIGdpdmVuIGRhdHVtXG4gKlxuICogQG1ldGhvZFxuICogQHBhcmFtIHtudW1iZXJ9IHBvc2l0aW9uICBQb3NpdGlvbiBvZiBkYXR1bVxuICogQHBhcmFtIHtudW1iZXJ9IFt2YWx1ZV0gICBWYWx1ZSBvZiBkYXR1bVxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAocmVxdWlyZWQgaWYgdGhpcy5zZXBOZWdWYWwgaXMgdHJ1ZSlcbiAqIEByZXR1cm5zIHtzdHJpbmd9IEJpbiBsYWJlbFxuICogKHByZWZpeGVkIHdpdGggYSAndicgaWYgdmFsdWUgaXMgbmVnYXRpdmUgYW5kIHRoaXMuc2VwTmVnVmFsIGlzXG4gKiB0cnVlOyBvdGhlcndpc2UgcHJlZml4ZWQgd2l0aCAnXicpXG4gKi9cblNpZXZlLnByb3RvdHlwZS5nZXRMYWJlbCA9IGZ1bmN0aW9uIGdldExhYmVsKHBvc2l0aW9uLCB2YWx1ZSkge1xuICAgIHZhciBwcmVmaXggPSAodmFsdWUgPCAwICYmIHRoaXMuc2VwTmVnVmFsKSA/ICd2JyA6ICdeJztcbiAgICB2YXIgbGFiZWwgPSAodGhpcy5vdmVybGFwTm9NZXJnZSkgP1xuICAgICAgICBwb3NpdGlvbiA6XG4gICAgICAgIE1hdGgucm91bmQocG9zaXRpb24gLyB0aGlzLmJpbldpZHRoKTtcbiAgICByZXR1cm4gcHJlZml4ICsgbGFiZWw7XG59O1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTl9XSw4NzA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG52YXIgYXR0cmlidXRlVGV4dEZvbnQgPSBhdHRyaWJ1dGVzLnRleHRmb250O1xudmFyIGF0dHJpYnV0ZUluc2lkZVRleHRGb250ID0gYXR0cmlidXRlcy5pbnNpZGV0ZXh0Zm9udDtcbnZhciBhdHRyaWJ1dGVPdXRzaWRlVGV4dEZvbnQgPSBhdHRyaWJ1dGVzLm91dHNpZGV0ZXh0Zm9udDtcbnZhciBoZWxwZXJzID0gX2RlcmVxXygnLi9oZWxwZXJzJyk7XG5cbmZ1bmN0aW9uIHN0eWxlKGdkKSB7XG4gICAgdmFyIHMgPSBkMy5zZWxlY3QoZ2QpLnNlbGVjdEFsbCgnZy5iYXJsYXllcicpLnNlbGVjdEFsbCgnZy50cmFjZScpO1xuICAgIHZhciBiYXJjb3VudCA9IHMuc2l6ZSgpO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICAvLyB0cmFjZSBzdHlsaW5nXG4gICAgcy5zdHlsZSgnb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGRbMF0udHJhY2Uub3BhY2l0eTsgfSlcblxuICAgIC8vIGZvciBnYXBsZXNzIChlaXRoZXIgc3RhY2tlZCBvciBuZWlnaGJvcmluZyBncm91cGVkKSBiYXJzIHVzZVxuICAgIC8vIGNyaXNwRWRnZXMgdG8gdHVybiBvZmYgYW50aWFsaWFzaW5nIHNvIGFuIGFydGlmaWNpYWwgZ2FwXG4gICAgLy8gaXNuJ3QgaW50cm9kdWNlZC5cbiAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIGlmKChmdWxsTGF5b3V0LmJhcm1vZGUgPT09ICdzdGFjaycgJiYgYmFyY291bnQgPiAxKSB8fFxuICAgICAgICAgICAgICAgIChmdWxsTGF5b3V0LmJhcmdhcCA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICBmdWxsTGF5b3V0LmJhcmdyb3VwZ2FwID09PSAwICYmXG4gICAgICAgICAgICAgICAgICFkWzBdLnRyYWNlLm1hcmtlci5saW5lLndpZHRoKSkge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ3NoYXBlLXJlbmRlcmluZycsICdjcmlzcEVkZ2VzJyk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHMuc2VsZWN0QWxsKCdnLnBvaW50cycpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgc2VsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuICAgICAgICBzdHlsZVBvaW50cyhzZWwsIHRyYWNlLCBnZCk7XG4gICAgfSk7XG5cbiAgICBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdzdHlsZScpKHMpO1xufVxuXG5mdW5jdGlvbiBzdHlsZVBvaW50cyhzZWwsIHRyYWNlLCBnZCkge1xuICAgIERyYXdpbmcucG9pbnRTdHlsZShzZWwuc2VsZWN0QWxsKCdwYXRoJyksIHRyYWNlLCBnZCk7XG4gICAgc3R5bGVUZXh0UG9pbnRzKHNlbCwgdHJhY2UsIGdkKTtcbn1cblxuZnVuY3Rpb24gc3R5bGVUZXh0UG9pbnRzKHNlbCwgdHJhY2UsIGdkKSB7XG4gICAgc2VsLnNlbGVjdEFsbCgndGV4dCcpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgdHggPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBmb250ID0gZGV0ZXJtaW5lRm9udCh0eCwgZCwgdHJhY2UsIGdkKTtcbiAgICAgICAgRHJhd2luZy5mb250KHR4LCBmb250KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gc3R5bGVPblNlbGVjdChnZCwgY2QsIHNlbCkge1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuXG4gICAgaWYodHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHtcbiAgICAgICAgc3R5bGVQb2ludHNJblNlbGVjdGlvbk1vZGUoc2VsLCB0cmFjZSwgZ2QpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHN0eWxlUG9pbnRzKHNlbCwgdHJhY2UsIGdkKTtcbiAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnc3R5bGUnKShzZWwpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc3R5bGVQb2ludHNJblNlbGVjdGlvbk1vZGUocywgdHJhY2UsIGdkKSB7XG4gICAgRHJhd2luZy5zZWxlY3RlZFBvaW50U3R5bGUocy5zZWxlY3RBbGwoJ3BhdGgnKSwgdHJhY2UpO1xuICAgIHN0eWxlVGV4dEluU2VsZWN0aW9uTW9kZShzLnNlbGVjdEFsbCgndGV4dCcpLCB0cmFjZSwgZ2QpO1xufVxuXG5mdW5jdGlvbiBzdHlsZVRleHRJblNlbGVjdGlvbk1vZGUodHhzLCB0cmFjZSwgZ2QpIHtcbiAgICB0eHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciB0eCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGZvbnQ7XG5cbiAgICAgICAgaWYoZC5zZWxlY3RlZCkge1xuICAgICAgICAgICAgZm9udCA9IExpYi5leHRlbmRGbGF0KHt9LCBkZXRlcm1pbmVGb250KHR4LCBkLCB0cmFjZSwgZ2QpKTtcblxuICAgICAgICAgICAgdmFyIHNlbGVjdGVkRm9udENvbG9yID0gdHJhY2Uuc2VsZWN0ZWQudGV4dGZvbnQgJiYgdHJhY2Uuc2VsZWN0ZWQudGV4dGZvbnQuY29sb3I7XG4gICAgICAgICAgICBpZihzZWxlY3RlZEZvbnRDb2xvcikge1xuICAgICAgICAgICAgICAgIGZvbnQuY29sb3IgPSBzZWxlY3RlZEZvbnRDb2xvcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRHJhd2luZy5mb250KHR4LCBmb250KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIERyYXdpbmcuc2VsZWN0ZWRUZXh0U3R5bGUodHgsIHRyYWNlKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBkZXRlcm1pbmVGb250KHR4LCBkLCB0cmFjZSwgZ2QpIHtcbiAgICB2YXIgbGF5b3V0Rm9udCA9IGdkLl9mdWxsTGF5b3V0LmZvbnQ7XG4gICAgdmFyIHRleHRGb250ID0gdHJhY2UudGV4dGZvbnQ7XG5cbiAgICBpZih0eC5jbGFzc2VkKCdiYXJ0ZXh0LWluc2lkZScpKSB7XG4gICAgICAgIHZhciBiYXJDb2xvciA9IGdldEJhckNvbG9yKGQsIHRyYWNlKTtcbiAgICAgICAgdGV4dEZvbnQgPSBnZXRJbnNpZGVUZXh0Rm9udCh0cmFjZSwgZC5pLCBsYXlvdXRGb250LCBiYXJDb2xvcik7XG4gICAgfSBlbHNlIGlmKHR4LmNsYXNzZWQoJ2JhcnRleHQtb3V0c2lkZScpKSB7XG4gICAgICAgIHRleHRGb250ID0gZ2V0T3V0c2lkZVRleHRGb250KHRyYWNlLCBkLmksIGxheW91dEZvbnQpO1xuICAgIH1cblxuICAgIHJldHVybiB0ZXh0Rm9udDtcbn1cblxuZnVuY3Rpb24gZ2V0VGV4dEZvbnQodHJhY2UsIGluZGV4LCBkZWZhdWx0VmFsdWUpIHtcbiAgICByZXR1cm4gZ2V0Rm9udFZhbHVlKFxuICAgICAgYXR0cmlidXRlVGV4dEZvbnQsIHRyYWNlLnRleHRmb250LCBpbmRleCwgZGVmYXVsdFZhbHVlKTtcbn1cblxuZnVuY3Rpb24gZ2V0SW5zaWRlVGV4dEZvbnQodHJhY2UsIGluZGV4LCBsYXlvdXRGb250LCBiYXJDb2xvcikge1xuICAgIHZhciBkZWZhdWx0Rm9udCA9IGdldFRleHRGb250KHRyYWNlLCBpbmRleCwgbGF5b3V0Rm9udCk7XG5cbiAgICB2YXIgd291bGRGYWxsQmFja1RvTGF5b3V0Rm9udCA9XG4gICAgICAodHJhY2UuX2lucHV0LnRleHRmb250ID09PSB1bmRlZmluZWQgfHwgdHJhY2UuX2lucHV0LnRleHRmb250LmNvbG9yID09PSB1bmRlZmluZWQpIHx8XG4gICAgICAoQXJyYXkuaXNBcnJheSh0cmFjZS50ZXh0Zm9udC5jb2xvcikgJiYgdHJhY2UudGV4dGZvbnQuY29sb3JbaW5kZXhdID09PSB1bmRlZmluZWQpO1xuICAgIGlmKHdvdWxkRmFsbEJhY2tUb0xheW91dEZvbnQpIHtcbiAgICAgICAgZGVmYXVsdEZvbnQgPSB7XG4gICAgICAgICAgICBjb2xvcjogQ29sb3IuY29udHJhc3QoYmFyQ29sb3IpLFxuICAgICAgICAgICAgZmFtaWx5OiBkZWZhdWx0Rm9udC5mYW1pbHksXG4gICAgICAgICAgICBzaXplOiBkZWZhdWx0Rm9udC5zaXplXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGdldEZvbnRWYWx1ZShcbiAgICAgIGF0dHJpYnV0ZUluc2lkZVRleHRGb250LCB0cmFjZS5pbnNpZGV0ZXh0Zm9udCwgaW5kZXgsIGRlZmF1bHRGb250KTtcbn1cblxuZnVuY3Rpb24gZ2V0T3V0c2lkZVRleHRGb250KHRyYWNlLCBpbmRleCwgbGF5b3V0Rm9udCkge1xuICAgIHZhciBkZWZhdWx0Rm9udCA9IGdldFRleHRGb250KHRyYWNlLCBpbmRleCwgbGF5b3V0Rm9udCk7XG4gICAgcmV0dXJuIGdldEZvbnRWYWx1ZShcbiAgICAgIGF0dHJpYnV0ZU91dHNpZGVUZXh0Rm9udCwgdHJhY2Uub3V0c2lkZXRleHRmb250LCBpbmRleCwgZGVmYXVsdEZvbnQpO1xufVxuXG5mdW5jdGlvbiBnZXRGb250VmFsdWUoYXR0cmlidXRlRGVmaW5pdGlvbiwgYXR0cmlidXRlVmFsdWUsIGluZGV4LCBkZWZhdWx0VmFsdWUpIHtcbiAgICBhdHRyaWJ1dGVWYWx1ZSA9IGF0dHJpYnV0ZVZhbHVlIHx8IHt9O1xuXG4gICAgdmFyIGZhbWlseVZhbHVlID0gaGVscGVycy5nZXRWYWx1ZShhdHRyaWJ1dGVWYWx1ZS5mYW1pbHksIGluZGV4KTtcbiAgICB2YXIgc2l6ZVZhbHVlID0gaGVscGVycy5nZXRWYWx1ZShhdHRyaWJ1dGVWYWx1ZS5zaXplLCBpbmRleCk7XG4gICAgdmFyIGNvbG9yVmFsdWUgPSBoZWxwZXJzLmdldFZhbHVlKGF0dHJpYnV0ZVZhbHVlLmNvbG9yLCBpbmRleCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBmYW1pbHk6IGhlbHBlcnMuY29lcmNlU3RyaW5nKFxuICAgICAgICAgIGF0dHJpYnV0ZURlZmluaXRpb24uZmFtaWx5LCBmYW1pbHlWYWx1ZSwgZGVmYXVsdFZhbHVlLmZhbWlseSksXG4gICAgICAgIHNpemU6IGhlbHBlcnMuY29lcmNlTnVtYmVyKFxuICAgICAgICAgIGF0dHJpYnV0ZURlZmluaXRpb24uc2l6ZSwgc2l6ZVZhbHVlLCBkZWZhdWx0VmFsdWUuc2l6ZSksXG4gICAgICAgIGNvbG9yOiBoZWxwZXJzLmNvZXJjZUNvbG9yKFxuICAgICAgICAgIGF0dHJpYnV0ZURlZmluaXRpb24uY29sb3IsIGNvbG9yVmFsdWUsIGRlZmF1bHRWYWx1ZS5jb2xvcilcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBnZXRCYXJDb2xvcihjZCwgdHJhY2UpIHtcbiAgICBpZih0cmFjZS50eXBlID09PSAnd2F0ZXJmYWxsJykge1xuICAgICAgICByZXR1cm4gdHJhY2VbY2QuZGlyXS5tYXJrZXIuY29sb3I7XG4gICAgfVxuICAgIHJldHVybiBjZC5tYyB8fCB0cmFjZS5tYXJrZXIuY29sb3I7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN0eWxlOiBzdHlsZSxcbiAgICBzdHlsZVRleHRQb2ludHM6IHN0eWxlVGV4dFBvaW50cyxcbiAgICBzdHlsZU9uU2VsZWN0OiBzdHlsZU9uU2VsZWN0LFxuICAgIGdldEluc2lkZVRleHRGb250OiBnZXRJbnNpZGVUZXh0Rm9udCxcbiAgICBnZXRPdXRzaWRlVGV4dEZvbnQ6IGdldE91dHNpZGVUZXh0Rm9udCxcbiAgICBnZXRCYXJDb2xvcjogZ2V0QmFyQ29sb3Jcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9hdHRyaWJ1dGVzXCI6ODU3LFwiLi9oZWxwZXJzXCI6ODYyLFwiZDNcIjoxNjN9XSw4NzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgaGFzQ29sb3JzY2FsZSA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9oZWxwZXJzJykuaGFzQ29sb3JzY2FsZTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgY29lcmNlKCdtYXJrZXIuY29sb3InLCBkZWZhdWx0Q29sb3IpO1xuXG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZUluLCAnbWFya2VyJykpIHtcbiAgICAgICAgY29sb3JzY2FsZURlZmF1bHRzKFxuICAgICAgICAgICAgdHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnbWFya2VyLicsIGNMZXR0ZXI6ICdjJ31cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ21hcmtlci5saW5lLmNvbG9yJywgQ29sb3IuZGVmYXVsdExpbmUpO1xuXG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZUluLCAnbWFya2VyLmxpbmUnKSkge1xuICAgICAgICBjb2xvcnNjYWxlRGVmYXVsdHMoXG4gICAgICAgICAgICB0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICdtYXJrZXIubGluZS4nLCBjTGV0dGVyOiAnYyd9XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdtYXJrZXIubGluZS53aWR0aCcpO1xuICAgIGNvZXJjZSgnbWFya2VyLm9wYWNpdHknKTtcbiAgICBjb2VyY2UoJ3NlbGVjdGVkLm1hcmtlci5jb2xvcicpO1xuICAgIGNvZXJjZSgndW5zZWxlY3RlZC5tYXJrZXIuY29sb3InKTtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0c1wiOjYwMyxcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9oZWxwZXJzXCI6NjA0fV0sODcyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGhvdmVydGVtcGxhdGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIHNjYXR0ZXJQb2xhckF0dHJzID0gX2RlcmVxXygnLi4vc2NhdHRlcnBvbGFyL2F0dHJpYnV0ZXMnKTtcbnZhciBiYXJBdHRycyA9IF9kZXJlcV8oJy4uL2Jhci9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHI6IHNjYXR0ZXJQb2xhckF0dHJzLnIsXG4gICAgdGhldGE6IHNjYXR0ZXJQb2xhckF0dHJzLnRoZXRhLFxuICAgIHIwOiBzY2F0dGVyUG9sYXJBdHRycy5yMCxcbiAgICBkcjogc2NhdHRlclBvbGFyQXR0cnMuZHIsXG4gICAgdGhldGEwOiBzY2F0dGVyUG9sYXJBdHRycy50aGV0YTAsXG4gICAgZHRoZXRhOiBzY2F0dGVyUG9sYXJBdHRycy5kdGhldGEsXG4gICAgdGhldGF1bml0OiBzY2F0dGVyUG9sYXJBdHRycy50aGV0YXVuaXQsXG5cbiAgICAvLyBvcmllbnRhdGlvbjoge1xuICAgIC8vICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgLy8gICAgIFxuICAgIC8vICAgICB2YWx1ZXM6IFsncmFkaWFsJywgJ2FuZ3VsYXInXSxcbiAgICAvLyAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAvLyAgICAgXG4gICAgLy8gfSxcblxuICAgIGJhc2U6IGV4dGVuZEZsYXQoe30sIGJhckF0dHJzLmJhc2UsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgb2Zmc2V0OiBleHRlbmRGbGF0KHt9LCBiYXJBdHRycy5vZmZzZXQsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgd2lkdGg6IGV4dGVuZEZsYXQoe30sIGJhckF0dHJzLndpZHRoLCB7XG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgdGV4dDogZXh0ZW5kRmxhdCh7fSwgYmFyQXR0cnMudGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcnRleHQ6IGV4dGVuZEZsYXQoe30sIGJhckF0dHJzLmhvdmVydGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIC8vIHRleHRwb3NpdGlvbjoge30sXG4gICAgLy8gdGV4dGZvbnQ6IHt9LFxuICAgIC8vIGluc2lkZXRleHRmb250OiB7fSxcbiAgICAvLyBvdXRzaWRldGV4dGZvbnQ6IHt9LFxuICAgIC8vIGNvbnN0cmFpbnRleHQ6IHt9LFxuICAgIC8vIGNsaXBvbmF4aXM6IGV4dGVuZEZsYXQoe30sIGJhckF0dHJzLmNsaXBvbmF4aXMsIHtkZmx0OiBmYWxzZX0pLFxuXG4gICAgbWFya2VyOiBiYXJBdHRycy5tYXJrZXIsXG5cbiAgICBob3ZlcmluZm86IHNjYXR0ZXJQb2xhckF0dHJzLmhvdmVyaW5mbyxcbiAgICBob3ZlcnRlbXBsYXRlOiBob3ZlcnRlbXBsYXRlQXR0cnMoKSxcblxuICAgIHNlbGVjdGVkOiBiYXJBdHRycy5zZWxlY3RlZCxcbiAgICB1bnNlbGVjdGVkOiBiYXJBdHRycy51bnNlbGVjdGVkXG5cbiAgICAvLyBlcnJvcl94IChlcnJvcl9yLCBlcnJvcl90aGV0YSlcbiAgICAvLyBlcnJvcl95XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uL2Jhci9hdHRyaWJ1dGVzXCI6ODU3LFwiLi4vc2NhdHRlcnBvbGFyL2F0dHJpYnV0ZXNcIjoxMTc5fV0sODczOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGhhc0NvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvaGVscGVycycpLmhhc0NvbG9yc2NhbGU7XG52YXIgY29sb3JzY2FsZUNhbGMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsYycpO1xudmFyIGFycmF5c1RvQ2FsY2RhdGEgPSBfZGVyZXFfKCcuLi9iYXIvYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgc2V0R3JvdXBQb3NpdGlvbnMgPSBfZGVyZXFfKCcuLi9iYXIvY3Jvc3NfdHJhY2VfY2FsYycpLnNldEdyb3VwUG9zaXRpb25zO1xudmFyIGNhbGNTZWxlY3Rpb24gPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NhbGNfc2VsZWN0aW9uJyk7XG52YXIgdHJhY2VJcyA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5JykudHJhY2VJcztcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliJykuZXh0ZW5kRmxhdDtcblxuZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzdWJwbG90SWQgPSB0cmFjZS5zdWJwbG90O1xuICAgIHZhciByYWRpYWxBeGlzID0gZnVsbExheW91dFtzdWJwbG90SWRdLnJhZGlhbGF4aXM7XG4gICAgdmFyIGFuZ3VsYXJBeGlzID0gZnVsbExheW91dFtzdWJwbG90SWRdLmFuZ3VsYXJheGlzO1xuICAgIHZhciByQXJyYXkgPSByYWRpYWxBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3InKTtcbiAgICB2YXIgdGhldGFBcnJheSA9IGFuZ3VsYXJBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3RoZXRhJyk7XG4gICAgdmFyIGxlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGNkID0gbmV3IEFycmF5KGxlbik7XG5cbiAgICAvLyAnc2l6ZScgYXhpcyB2YXJpYWJsZXNcbiAgICB2YXIgc0FycmF5ID0gckFycmF5O1xuICAgIC8vICdwb3MnIGF4aXMgdmFyaWFibGVzXG4gICAgdmFyIHBBcnJheSA9IHRoZXRhQXJyYXk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgY2RbaV0gPSB7cDogcEFycmF5W2ldLCBzOiBzQXJyYXlbaV19O1xuICAgIH1cblxuICAgIC8vIGNvbnZlcnQgd2lkdGggYW5kIG9mZnNldCBpbiAnYycgY29vcmRpbmF0ZSxcbiAgICAvLyBzZXQgJ2MnIHZhbHVlKHMpIGluIHRyYWNlLl93aWR0aCBhbmQgdHJhY2UuX29mZnNldCxcbiAgICAvLyB0byBtYWtlIEJhci5jcm9zc1RyYWNlQ2FsYyBcImp1c3Qgd29ya1wiXG4gICAgZnVuY3Rpb24gZDJjKGF0dHIpIHtcbiAgICAgICAgdmFyIHZhbCA9IHRyYWNlW2F0dHJdO1xuICAgICAgICBpZih2YWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdHJhY2VbJ18nICsgYXR0cl0gPSBBcnJheS5pc0FycmF5KHZhbCkgP1xuICAgICAgICAgICAgICAgIGFuZ3VsYXJBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgYXR0cikgOlxuICAgICAgICAgICAgICAgIGFuZ3VsYXJBeGlzLmQyYyh2YWwsIHRyYWNlLnRoZXRhdW5pdCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihhbmd1bGFyQXhpcy50eXBlID09PSAnbGluZWFyJykge1xuICAgICAgICBkMmMoJ3dpZHRoJyk7XG4gICAgICAgIGQyYygnb2Zmc2V0Jyk7XG4gICAgfVxuXG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZSwgJ21hcmtlcicpKSB7XG4gICAgICAgIGNvbG9yc2NhbGVDYWxjKGdkLCB0cmFjZSwge1xuICAgICAgICAgICAgdmFsczogdHJhY2UubWFya2VyLmNvbG9yLFxuICAgICAgICAgICAgY29udGFpbmVyU3RyOiAnbWFya2VyJyxcbiAgICAgICAgICAgIGNMZXR0ZXI6ICdjJ1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZSwgJ21hcmtlci5saW5lJykpIHtcbiAgICAgICAgY29sb3JzY2FsZUNhbGMoZ2QsIHRyYWNlLCB7XG4gICAgICAgICAgICB2YWxzOiB0cmFjZS5tYXJrZXIubGluZS5jb2xvcixcbiAgICAgICAgICAgIGNvbnRhaW5lclN0cjogJ21hcmtlci5saW5lJyxcbiAgICAgICAgICAgIGNMZXR0ZXI6ICdjJ1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSk7XG4gICAgY2FsY1NlbGVjdGlvbihjZCwgdHJhY2UpO1xuXG4gICAgcmV0dXJuIGNkO1xufVxuXG5mdW5jdGlvbiBjcm9zc1RyYWNlQ2FsYyhnZCwgcG9sYXJMYXlvdXQsIHN1YnBsb3RJZCkge1xuICAgIHZhciBjYWxjZGF0YSA9IGdkLmNhbGNkYXRhO1xuICAgIHZhciBiYXJQb2xhckNkID0gW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY2RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkaSA9IGNhbGNkYXRhW2ldO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZGlbMF0udHJhY2U7XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSA9PT0gdHJ1ZSAmJiB0cmFjZUlzKHRyYWNlLCAnYmFyJykgJiZcbiAgICAgICAgICAgIHRyYWNlLnN1YnBsb3QgPT09IHN1YnBsb3RJZFxuICAgICAgICApIHtcbiAgICAgICAgICAgIGJhclBvbGFyQ2QucHVzaChjZGkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gdG8gbWFrZSBfZXh0cmVtZXMgaXMgZmlsbGVkIGluIGNvcnJlY3RseSBzbyB0aGF0XG4gICAgLy8gcG9sYXIuX3N1YnBsb3QucmFkaWFsQXhpcyBjYW4gZ2V0IGF1b3RyYW5nZSdkXG4gICAgLy8gVE9ETyBjbGVhbiB1cCFcbiAgICAvLyBJIHRoaW5rIHdlIHdhbnQgdG8gY2FsbCBnZXRBdXRvcmFuZ2Ugb24gcG9sYXIucmFkaWFsYXhpc1xuICAgIC8vIE5PVCBvbiBwb2xhci5fc3VicGxvdC5yYWRpYWxBeGlzXG4gICAgdmFyIHJBeGlzID0gZXh0ZW5kRmxhdCh7fSwgcG9sYXJMYXlvdXQucmFkaWFsYXhpcywge19pZDogJ3gnfSk7XG4gICAgdmFyIGFBeGlzID0gcG9sYXJMYXlvdXQuYW5ndWxhcmF4aXM7XG5cbiAgICBzZXRHcm91cFBvc2l0aW9ucyhnZCwgYUF4aXMsIHJBeGlzLCBiYXJQb2xhckNkLCB7XG4gICAgICAgIG1vZGU6IHBvbGFyTGF5b3V0LmJhcm1vZGUsXG4gICAgICAgIG5vcm06IHBvbGFyTGF5b3V0LmJhcm5vcm0sXG4gICAgICAgIGdhcDogcG9sYXJMYXlvdXQuYmFyZ2FwLFxuICAgICAgICBncm91cGdhcDogcG9sYXJMYXlvdXQuYmFyZ3JvdXBnYXBcbiAgICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY2FsYzogY2FsYyxcbiAgICBjcm9zc1RyYWNlQ2FsYzogY3Jvc3NUcmFjZUNhbGNcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGNcIjo2MDEsXCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvaGVscGVyc1wiOjYwNCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vYmFyL2FycmF5c190b19jYWxjZGF0YVwiOjg1NixcIi4uL2Jhci9jcm9zc190cmFjZV9jYWxjXCI6ODYwLFwiLi4vc2NhdHRlci9jYWxjX3NlbGVjdGlvblwiOjExMTR9XSw4NzQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBoYW5kbGVSVGhldGFEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXJwb2xhci9kZWZhdWx0cycpLmhhbmRsZVJUaGV0YURlZmF1bHRzO1xudmFyIGhhbmRsZVN0eWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9iYXIvc3R5bGVfZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsZW4gPSBoYW5kbGVSVGhldGFEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuICAgIGlmKCFsZW4pIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gY29lcmNlKCdvcmllbnRhdGlvbicsICh0cmFjZU91dC50aGV0YSAmJiAhdHJhY2VPdXQucikgPyAnYW5ndWxhcicgOiAncmFkaWFsJyk7XG5cbiAgICBjb2VyY2UoJ3RoZXRhdW5pdCcpO1xuICAgIGNvZXJjZSgnYmFzZScpO1xuICAgIGNvZXJjZSgnb2Zmc2V0Jyk7XG4gICAgY29lcmNlKCd3aWR0aCcpO1xuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGVtcGxhdGUnKTtcblxuICAgIC8vIHZhciB0ZXh0UG9zaXRpb24gPSBjb2VyY2UoJ3RleHRwb3NpdGlvbicpO1xuICAgIC8vIHZhciBoYXNCb3RoID0gQXJyYXkuaXNBcnJheSh0ZXh0UG9zaXRpb24pIHx8IHRleHRQb3NpdGlvbiA9PT0gJ2F1dG8nO1xuICAgIC8vIHZhciBoYXNJbnNpZGUgPSBoYXNCb3RoIHx8IHRleHRQb3NpdGlvbiA9PT0gJ2luc2lkZSc7XG4gICAgLy8gdmFyIGhhc091dHNpZGUgPSBoYXNCb3RoIHx8IHRleHRQb3NpdGlvbiA9PT0gJ291dHNpZGUnO1xuXG4gICAgLy8gaWYoaGFzSW5zaWRlIHx8IGhhc091dHNpZGUpIHtcbiAgICAvLyAgICAgdmFyIHRleHRGb250ID0gY29lcmNlRm9udChjb2VyY2UsICd0ZXh0Zm9udCcsIGxheW91dC5mb250KTtcbiAgICAvLyAgICAgaWYoaGFzSW5zaWRlKSBjb2VyY2VGb250KGNvZXJjZSwgJ2luc2lkZXRleHRmb250JywgdGV4dEZvbnQpO1xuICAgIC8vICAgICBpZihoYXNPdXRzaWRlKSBjb2VyY2VGb250KGNvZXJjZSwgJ291dHNpZGV0ZXh0Zm9udCcsIHRleHRGb250KTtcbiAgICAvLyAgICAgY29lcmNlKCdjb25zdHJhaW50ZXh0Jyk7XG4gICAgLy8gICAgIGNvZXJjZSgnc2VsZWN0ZWQudGV4dGZvbnQuY29sb3InKTtcbiAgICAvLyAgICAgY29lcmNlKCd1bnNlbGVjdGVkLnRleHRmb250LmNvbG9yJyk7XG4gICAgLy8gICAgIGNvZXJjZSgnY2xpcG9uYXhpcycpO1xuICAgIC8vIH1cblxuICAgIGhhbmRsZVN0eWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgZGVmYXVsdENvbG9yLCBsYXlvdXQpO1xuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2Jhci9zdHlsZV9kZWZhdWx0c1wiOjg3MSxcIi4uL3NjYXR0ZXJwb2xhci9kZWZhdWx0c1wiOjExODEsXCIuL2F0dHJpYnV0ZXNcIjo4NzJ9XSw4NzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgZ2V0VHJhY2VDb2xvciA9IF9kZXJlcV8oJy4uL2Jhci9ob3ZlcicpLmdldFRyYWNlQ29sb3I7XG52YXIgZmlsbFRleHQgPSBMaWIuZmlsbFRleHQ7XG52YXIgbWFrZUhvdmVyUG9pbnRUZXh0ID0gX2RlcmVxXygnLi4vc2NhdHRlcnBvbGFyL2hvdmVyJykubWFrZUhvdmVyUG9pbnRUZXh0O1xudmFyIGlzUHRJbnNpZGVQb2x5Z29uID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvcG9sYXIvaGVscGVycycpLmlzUHRJbnNpZGVQb2x5Z29uO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgIHZhciBzdWJwbG90ID0gcG9pbnREYXRhLnN1YnBsb3Q7XG4gICAgdmFyIHJhZGlhbEF4aXMgPSBzdWJwbG90LnJhZGlhbEF4aXM7XG4gICAgdmFyIGFuZ3VsYXJBeGlzID0gc3VicGxvdC5hbmd1bGFyQXhpcztcbiAgICB2YXIgdmFuZ2xlcyA9IHN1YnBsb3QudmFuZ2xlcztcbiAgICB2YXIgaW5ib3hGbiA9IHZhbmdsZXMgPyBpc1B0SW5zaWRlUG9seWdvbiA6IExpYi5pc1B0SW5zaWRlU2VjdG9yO1xuICAgIHZhciBtYXhIb3ZlckRpc3RhbmNlID0gcG9pbnREYXRhLm1heEhvdmVyRGlzdGFuY2U7XG4gICAgdmFyIHBlcmlvZCA9IGFuZ3VsYXJBeGlzLl9wZXJpb2QgfHwgMiAqIE1hdGguUEk7XG5cbiAgICB2YXIgclZhbCA9IE1hdGguYWJzKHJhZGlhbEF4aXMuZzJwKE1hdGguc3FydCh4dmFsICogeHZhbCArIHl2YWwgKiB5dmFsKSkpO1xuICAgIHZhciB0aGV0YVZhbCA9IE1hdGguYXRhbjIoeXZhbCwgeHZhbCk7XG5cbiAgICAvLyBwb2xhci4oeHx5KWF4aXMucDJjIGRvZXNuJ3QgZ2V0IHRoZSByZXZlcnNlZCByYWRpYWwgYXhpcyByYW5nZSBjYXNlIHJpZ2h0XG4gICAgaWYocmFkaWFsQXhpcy5yYW5nZVswXSA+IHJhZGlhbEF4aXMucmFuZ2VbMV0pIHtcbiAgICAgICAgdGhldGFWYWwgKz0gTWF0aC5QSTtcbiAgICB9XG5cbiAgICB2YXIgZGlzdEZuID0gZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgaWYoaW5ib3hGbihyVmFsLCB0aGV0YVZhbCwgW2RpLnJwMCwgZGkucnAxXSwgW2RpLnRoZXRhZzAsIGRpLnRoZXRhZzFdLCB2YW5nbGVzKSkge1xuICAgICAgICAgICAgcmV0dXJuIG1heEhvdmVyRGlzdGFuY2UgK1xuICAgICAgICAgICAgICAgIC8vIGFkZCBhIGxpdHRsZSB0byB0aGUgcHNldWRvLWRpc3RhbmNlIGZvciB3aWRlciBiYXJzLCBzbyB0aGF0IGxpa2Ugc2NhdHRlcixcbiAgICAgICAgICAgICAgICAvLyBpZiB5b3UgYXJlIG92ZXIgdHdvIG92ZXJsYXBwaW5nIGJhcnMsIHRoZSBuYXJyb3dlciBvbmUgd2lucy5cbiAgICAgICAgICAgICAgICBNYXRoLm1pbigxLCBNYXRoLmFicyhkaS50aGV0YWcxIC0gZGkudGhldGFnMCkgLyBwZXJpb2QpIC0gMSArXG4gICAgICAgICAgICAgICAgLy8gYWRkIGEgZ3JhZGllbnQgc28gaG92ZXJpbmcgbmVhciB0aGUgZW5kIG9mIGFcbiAgICAgICAgICAgICAgICAvLyBiYXIgbWFrZXMgaXQgYSBsaXR0bGUgY2xvc2VyIG1hdGNoXG4gICAgICAgICAgICAgICAgKGRpLnJwMSAtIHJWYWwpIC8gKGRpLnJwMSAtIGRpLnJwMCkgLSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIEluZmluaXR5O1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIEZ4LmdldENsb3Nlc3QoY2QsIGRpc3RGbiwgcG9pbnREYXRhKTtcbiAgICBpZihwb2ludERhdGEuaW5kZXggPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICB2YXIgaW5kZXggPSBwb2ludERhdGEuaW5kZXg7XG4gICAgdmFyIGNkaSA9IGNkW2luZGV4XTtcblxuICAgIHBvaW50RGF0YS54MCA9IHBvaW50RGF0YS54MSA9IGNkaS5jdFswXTtcbiAgICBwb2ludERhdGEueTAgPSBwb2ludERhdGEueTEgPSBjZGkuY3RbMV07XG5cbiAgICB2YXIgX2NkaSA9IExpYi5leHRlbmRGbGF0KHt9LCBjZGksIHtyOiBjZGkucywgdGhldGE6IGNkaS5wfSk7XG4gICAgZmlsbFRleHQoY2RpLCB0cmFjZSwgcG9pbnREYXRhKTtcbiAgICBtYWtlSG92ZXJQb2ludFRleHQoX2NkaSwgdHJhY2UsIHN1YnBsb3QsIHBvaW50RGF0YSk7XG4gICAgcG9pbnREYXRhLmhvdmVydGVtcGxhdGUgPSB0cmFjZS5ob3ZlcnRlbXBsYXRlO1xuICAgIHBvaW50RGF0YS5jb2xvciA9IGdldFRyYWNlQ29sb3IodHJhY2UsIGNkaSk7XG4gICAgcG9pbnREYXRhLnhMYWJlbFZhbCA9IHBvaW50RGF0YS55TGFiZWxWYWwgPSB1bmRlZmluZWQ7XG5cbiAgICBpZihjZGkucyA8IDApIHtcbiAgICAgICAgcG9pbnREYXRhLmlkZWFsQWxpZ24gPSAnbGVmdCc7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtwb2ludERhdGFdO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvcG9sYXIvaGVscGVyc1wiOjgzMCxcIi4uL2Jhci9ob3ZlclwiOjg2MyxcIi4uL3NjYXR0ZXJwb2xhci9ob3ZlclwiOjExODJ9XSw4NzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdiYXJwb2xhcicsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL3BvbGFyJyksXG4gICAgY2F0ZWdvcmllczogWydwb2xhcicsICdiYXInLCAnc2hvd0xlZ2VuZCddLFxuXG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2RlZmF1bHRzJyksXG5cbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKS5jYWxjLFxuICAgIGNyb3NzVHJhY2VDYWxjOiBfZGVyZXFfKCcuL2NhbGMnKS5jcm9zc1RyYWNlQ2FsYyxcblxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIGNvbG9yYmFyOiBfZGVyZXFfKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpLFxuXG4gICAgc3R5bGU6IF9kZXJlcV8oJy4uL2Jhci9zdHlsZScpLnN0eWxlLFxuICAgIHN0eWxlT25TZWxlY3Q6IF9kZXJlcV8oJy4uL2Jhci9zdHlsZScpLnN0eWxlT25TZWxlY3QsXG5cbiAgICBob3ZlclBvaW50czogX2RlcmVxXygnLi9ob3ZlcicpLFxuICAgIHNlbGVjdFBvaW50czogX2RlcmVxXygnLi4vYmFyL3NlbGVjdCcpLFxuXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9wb2xhclwiOjgzMSxcIi4uL2Jhci9zZWxlY3RcIjo4NjgsXCIuLi9iYXIvc3R5bGVcIjo4NzAsXCIuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhclwiOjExMjksXCIuL2F0dHJpYnV0ZXNcIjo4NzIsXCIuL2NhbGNcIjo4NzMsXCIuL2RlZmF1bHRzXCI6ODc0LFwiLi9ob3ZlclwiOjg3NSxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo4NzcsXCIuL2xheW91dF9kZWZhdWx0c1wiOjg3OCxcIi4vcGxvdFwiOjg3OX1dLDg3NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGJhcm1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnc3RhY2snLCAnb3ZlcmxheSddLFxuICAgICAgICBkZmx0OiAnc3RhY2snLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBiYXJnYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAuMSxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHt9XSw4Nzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgYXR0cnMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24obGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEpIHtcbiAgICB2YXIgc3VicGxvdHNEb25lID0ge307XG4gICAgdmFyIHNwO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGF5b3V0SW5bc3BdIHx8IHt9LCBsYXlvdXRPdXRbc3BdLCBhdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICBpZih0cmFjZS50eXBlID09PSAnYmFycG9sYXInICYmIHRyYWNlLnZpc2libGUgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHNwID0gdHJhY2Uuc3VicGxvdDtcbiAgICAgICAgICAgIGlmKCFzdWJwbG90c0RvbmVbc3BdKSB7XG4gICAgICAgICAgICAgICAgY29lcmNlKCdiYXJtb2RlJyk7XG4gICAgICAgICAgICAgICAgY29lcmNlKCdiYXJnYXAnKTtcbiAgICAgICAgICAgICAgICBzdWJwbG90c0RvbmVbc3BdID0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjg3N31dLDg3OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBoZWxwZXJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvcG9sYXIvaGVscGVycycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHN1YnBsb3QsIGNkYmFyKSB7XG4gICAgdmFyIHhhID0gc3VicGxvdC54YXhpcztcbiAgICB2YXIgeWEgPSBzdWJwbG90LnlheGlzO1xuICAgIHZhciByYWRpYWxBeGlzID0gc3VicGxvdC5yYWRpYWxBeGlzO1xuICAgIHZhciBhbmd1bGFyQXhpcyA9IHN1YnBsb3QuYW5ndWxhckF4aXM7XG4gICAgdmFyIHBhdGhGbiA9IG1ha2VQYXRoRm4oc3VicGxvdCk7XG4gICAgdmFyIGJhckxheWVyID0gc3VicGxvdC5sYXllcnMuZnJvbnRwbG90LnNlbGVjdCgnZy5iYXJsYXllcicpO1xuXG4gICAgTGliLm1ha2VUcmFjZUdyb3VwcyhiYXJMYXllciwgY2RiYXIsICd0cmFjZSBiYXJzJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHBsb3RHcm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIHBvaW50R3JvdXAgPSBMaWIuZW5zdXJlU2luZ2xlKHBsb3RHcm91cCwgJ2cnLCAncG9pbnRzJyk7XG4gICAgICAgIHZhciBiYXJzID0gcG9pbnRHcm91cC5zZWxlY3RBbGwoJ2cucG9pbnQnKS5kYXRhKExpYi5pZGVudGl0eSk7XG5cbiAgICAgICAgYmFycy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAuc3R5bGUoJ3ZlY3Rvci1lZmZlY3QnLCAnbm9uLXNjYWxpbmctc3Ryb2tlJylcbiAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLW1pdGVybGltaXQnLCAyKVxuICAgICAgICAgICAgLmNsYXNzZWQoJ3BvaW50JywgdHJ1ZSk7XG5cbiAgICAgICAgYmFycy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgYmFycy5lYWNoKGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICB2YXIgYmFyID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgICAgICB2YXIgcnAwID0gZGkucnAwID0gcmFkaWFsQXhpcy5jMnAoZGkuczApO1xuICAgICAgICAgICAgdmFyIHJwMSA9IGRpLnJwMSA9IHJhZGlhbEF4aXMuYzJwKGRpLnMxKTtcbiAgICAgICAgICAgIHZhciB0aGV0YWcwID0gZGkudGhldGFnMCA9IGFuZ3VsYXJBeGlzLmMyZyhkaS5wMCk7XG4gICAgICAgICAgICB2YXIgdGhldGFnMSA9IGRpLnRoZXRhZzEgPSBhbmd1bGFyQXhpcy5jMmcoZGkucDEpO1xuXG4gICAgICAgICAgICB2YXIgZFBhdGg7XG5cbiAgICAgICAgICAgIGlmKCFpc051bWVyaWMocnAwKSB8fCAhaXNOdW1lcmljKHJwMSkgfHxcbiAgICAgICAgICAgICAgICAhaXNOdW1lcmljKHRoZXRhZzApIHx8ICFpc051bWVyaWModGhldGFnMSkgfHxcbiAgICAgICAgICAgICAgICBycDAgPT09IHJwMSB8fCB0aGV0YWcwID09PSB0aGV0YWcxXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAvLyBkbyBub3QgcmVtb3ZlIGJsYW5rIGJhcnMsIHRvIGtlZXAgZGF0YS10by1ub2RlXG4gICAgICAgICAgICAgICAgLy8gbWFwcGluZyBpbnRhY3QgZHVyaW5nIHJhZGlhbCBkcmFnLCB0aGF0IHdlXG4gICAgICAgICAgICAgICAgLy8gY2FuIHNraXAgY2FsbGluZyBfbW9kdWxlLnN0eWxlIGR1cmluZyBpbnRlcmFjdGlvbnNcbiAgICAgICAgICAgICAgICBkUGF0aCA9ICdNMCwwWic7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgJ2NlbnRlcicgcHQgaXMgdXNlZCBmb3Igc2VsZWN0aW9ucyBhbmQgaG92ZXIgbGFiZWxzXG4gICAgICAgICAgICAgICAgdmFyIHJnMSA9IHJhZGlhbEF4aXMuYzJnKGRpLnMxKTtcbiAgICAgICAgICAgICAgICB2YXIgdGhldGFnTWlkID0gKHRoZXRhZzAgKyB0aGV0YWcxKSAvIDI7XG4gICAgICAgICAgICAgICAgZGkuY3QgPSBbXG4gICAgICAgICAgICAgICAgICAgIHhhLmMycChyZzEgKiBNYXRoLmNvcyh0aGV0YWdNaWQpKSxcbiAgICAgICAgICAgICAgICAgICAgeWEuYzJwKHJnMSAqIE1hdGguc2luKHRoZXRhZ01pZCkpXG4gICAgICAgICAgICAgICAgXTtcblxuICAgICAgICAgICAgICAgIGRQYXRoID0gcGF0aEZuKHJwMCwgcnAxLCB0aGV0YWcwLCB0aGV0YWcxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgTGliLmVuc3VyZVNpbmdsZShiYXIsICdwYXRoJykuYXR0cignZCcsIGRQYXRoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gY2xpcCBwbG90R3JvdXAsIHdoZW4gdHJhY2UgbGF5ZXIgaXNuJ3QgY2xpcHBlZFxuICAgICAgICBEcmF3aW5nLnNldENsaXBVcmwoXG4gICAgICAgICAgICBwbG90R3JvdXAsXG4gICAgICAgICAgICBzdWJwbG90Ll9oYXNDbGlwT25BeGlzRmFsc2UgPyBzdWJwbG90LmNsaXBJZHMuZm9yVHJhY2VzIDogbnVsbCxcbiAgICAgICAgICAgIGdkXG4gICAgICAgICk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBtYWtlUGF0aEZuKHN1YnBsb3QpIHtcbiAgICB2YXIgY3h4ID0gc3VicGxvdC5jeHg7XG4gICAgdmFyIGN5eSA9IHN1YnBsb3QuY3l5O1xuXG4gICAgaWYoc3VicGxvdC52YW5nbGVzKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihyMCwgcjEsIF9hMCwgX2ExKSB7XG4gICAgICAgICAgICB2YXIgYTAsIGExO1xuXG4gICAgICAgICAgICBpZihMaWIuYW5nbGVEZWx0YShfYTAsIF9hMSkgPiAwKSB7XG4gICAgICAgICAgICAgICAgYTAgPSBfYTA7XG4gICAgICAgICAgICAgICAgYTEgPSBfYTE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGEwID0gX2ExO1xuICAgICAgICAgICAgICAgIGExID0gX2EwO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgdmEwID0gaGVscGVycy5maW5kRW5jbG9zaW5nVmVydGV4QW5nbGVzKGEwLCBzdWJwbG90LnZhbmdsZXMpWzBdO1xuICAgICAgICAgICAgdmFyIHZhMSA9IGhlbHBlcnMuZmluZEVuY2xvc2luZ1ZlcnRleEFuZ2xlcyhhMSwgc3VicGxvdC52YW5nbGVzKVsxXTtcbiAgICAgICAgICAgIHZhciB2YUJhciA9IFt2YTAsIChhMCArIGExKSAvIDIsIHZhMV07XG4gICAgICAgICAgICByZXR1cm4gaGVscGVycy5wYXRoUG9seWdvbkFubnVsdXMocjAsIHIxLCBhMCwgYTEsIHZhQmFyLCBjeHgsIGN5eSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKHIwLCByMSwgYTAsIGExKSB7XG4gICAgICAgIHJldHVybiBMaWIucGF0aEFubnVsdXMocjAsIHIxLCBhMCwgYTEsIGN4eCwgY3l5KTtcbiAgICB9O1xufVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL3BvbGFyL2hlbHBlcnNcIjo4MzAsXCJkM1wiOjE2MyxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sODgwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJBdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIGJhckF0dHJzID0gX2RlcmVxXygnLi4vYmFyL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciBzY2F0dGVyTWFya2VyQXR0cnMgPSBzY2F0dGVyQXR0cnMubWFya2VyO1xudmFyIHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMgPSBzY2F0dGVyTWFya2VyQXR0cnMubGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgeToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeDA6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHkwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBuYW1lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0ZXh0OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMudGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcnRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5ob3ZlcnRleHQsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgd2hpc2tlcndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMC41LFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBub3RjaGVkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbm90Y2h3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDAuNSxcbiAgICAgICAgZGZsdDogMC4yNSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm94cG9pbnRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FsbCcsICdvdXRsaWVycycsICdzdXNwZWN0ZWRvdXRsaWVycycsIGZhbHNlXSxcbiAgICAgICAgZGZsdDogJ291dGxpZXJzJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm94bWVhbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW3RydWUsICdzZCcsIGZhbHNlXSxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGppdHRlcjoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHBvaW50cG9zOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IC0yLFxuICAgICAgICBtYXg6IDIsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG9yaWVudGF0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3YnLCAnaCddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHdpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbWFya2VyOiB7XG4gICAgICAgIG91dGxpZXJjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIGRmbHQ6ICdyZ2JhKDAsIDAsIDAsIDApJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc3ltYm9sOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyQXR0cnMuc3ltYm9sLFxuICAgICAgICAgICAge2FycmF5T2s6IGZhbHNlLCBlZGl0VHlwZTogJ3Bsb3QnfSksXG4gICAgICAgIG9wYWNpdHk6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJBdHRycy5vcGFjaXR5LFxuICAgICAgICAgICAge2FycmF5T2s6IGZhbHNlLCBkZmx0OiAxLCBlZGl0VHlwZTogJ3N0eWxlJ30pLFxuICAgICAgICBzaXplOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZSxcbiAgICAgICAgICAgIHthcnJheU9rOiBmYWxzZSwgZWRpdFR5cGU6ICdjYWxjJ30pLFxuICAgICAgICBjb2xvcjogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlck1hcmtlckF0dHJzLmNvbG9yLFxuICAgICAgICAgICAge2FycmF5T2s6IGZhbHNlLCBlZGl0VHlwZTogJ3N0eWxlJ30pLFxuICAgICAgICBsaW5lOiB7XG4gICAgICAgICAgICBjb2xvcjogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlck1hcmtlckxpbmVBdHRycy5jb2xvcixcbiAgICAgICAgICAgICAgICB7YXJyYXlPazogZmFsc2UsIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsIGVkaXRUeXBlOiAnc3R5bGUnfVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyTGluZUF0dHJzLndpZHRoLFxuICAgICAgICAgICAgICAgIHthcnJheU9rOiBmYWxzZSwgZGZsdDogMCwgZWRpdFR5cGU6ICdzdHlsZSd9XG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgb3V0bGllcmNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvdXRsaWVyd2lkdGg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgZGZsdDogMSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICBsaW5lOiB7XG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDIsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICBmaWxsY29sb3I6IHNjYXR0ZXJBdHRycy5maWxsY29sb3IsXG5cbiAgICBvZmZzZXRncm91cDogYmFyQXR0cnMub2Zmc2V0Z3JvdXAsXG4gICAgYWxpZ25tZW50Z3JvdXA6IGJhckF0dHJzLmFsaWdubWVudGdyb3VwLFxuXG4gICAgc2VsZWN0ZWQ6IHtcbiAgICAgICAgbWFya2VyOiBzY2F0dGVyQXR0cnMuc2VsZWN0ZWQubWFya2VyLFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH0sXG4gICAgdW5zZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHNjYXR0ZXJBdHRycy51bnNlbGVjdGVkLm1hcmtlcixcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICB9LFxuICAgIGhvdmVyb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICAgICAgZmxhZ3M6IFsnYm94ZXMnLCAncG9pbnRzJ10sXG4gICAgICAgIGRmbHQ6ICdib3hlcytwb2ludHMnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzXCI6NTkyLFwiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXNcIjo2MzEsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vYmFyL2F0dHJpYnV0ZXNcIjo4NTcsXCIuLi9zY2F0dGVyL2F0dHJpYnV0ZXNcIjoxMTEyfV0sODgxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBfID0gTGliLl87XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG5cbi8vIG91dGxpZXIgZGVmaW5pdGlvbiBiYXNlZCBvbiBodHRwOi8vd3d3LnBoeXNpY3MuY3Nic2p1LmVkdS9zdGF0cy9ib3gyLmh0bWxcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciB4YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS54YXhpcyB8fCAneCcpO1xuICAgIHZhciB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS55YXhpcyB8fCAneScpO1xuICAgIHZhciBjZCA9IFtdO1xuXG4gICAgLy8gTi5CLiB2aW9saW4gcmV1c2VzIHNhbWUgQm94LmNhbGNcbiAgICB2YXIgbnVtS2V5ID0gdHJhY2UudHlwZSA9PT0gJ3Zpb2xpbicgPyAnX251bVZpb2xpbnMnIDogJ19udW1Cb3hlcyc7XG5cbiAgICB2YXIgaTtcbiAgICB2YXIgdmFsQXhpcywgdmFsTGV0dGVyO1xuICAgIHZhciBwb3NBeGlzLCBwb3NMZXR0ZXI7XG5cbiAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgIHZhbEF4aXMgPSB4YTtcbiAgICAgICAgdmFsTGV0dGVyID0gJ3gnO1xuICAgICAgICBwb3NBeGlzID0geWE7XG4gICAgICAgIHBvc0xldHRlciA9ICd5JztcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YWxBeGlzID0geWE7XG4gICAgICAgIHZhbExldHRlciA9ICd5JztcbiAgICAgICAgcG9zQXhpcyA9IHhhO1xuICAgICAgICBwb3NMZXR0ZXIgPSAneCc7XG4gICAgfVxuXG4gICAgdmFyIHZhbCA9IHZhbEF4aXMubWFrZUNhbGNkYXRhKHRyYWNlLCB2YWxMZXR0ZXIpO1xuICAgIHZhciBwb3MgPSBnZXRQb3ModHJhY2UsIHBvc0xldHRlciwgcG9zQXhpcywgdmFsLCBmdWxsTGF5b3V0W251bUtleV0pO1xuXG4gICAgdmFyIGR2ID0gTGliLmRpc3RpbmN0VmFscyhwb3MpO1xuICAgIHZhciBwb3NEaXN0aW5jdCA9IGR2LnZhbHM7XG4gICAgdmFyIGRQb3MgPSBkdi5taW5EaWZmIC8gMjtcbiAgICB2YXIgcG9zQmlucyA9IG1ha2VCaW5zKHBvc0Rpc3RpbmN0LCBkUG9zKTtcblxuICAgIHZhciBwTGVuID0gcG9zRGlzdGluY3QubGVuZ3RoO1xuICAgIHZhciBwdHNQZXJCaW4gPSBpbml0TmVzdGVkQXJyYXkocExlbik7XG5cbiAgICAvLyBiaW4gcHRzIGluZm8gcGVyIHBvc2l0aW9uIGJpbnNcbiAgICBmb3IoaSA9IDA7IGkgPCB0cmFjZS5fbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHYgPSB2YWxbaV07XG4gICAgICAgIGlmKCFpc051bWVyaWModikpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciBuID0gTGliLmZpbmRCaW4ocG9zW2ldLCBwb3NCaW5zKTtcbiAgICAgICAgaWYobiA+PSAwICYmIG4gPCBwTGVuKSB7XG4gICAgICAgICAgICB2YXIgcHQgPSB7djogdiwgaTogaX07XG4gICAgICAgICAgICBhcnJheXNUb0NhbGNkYXRhKHB0LCB0cmFjZSwgaSk7XG4gICAgICAgICAgICBwdHNQZXJCaW5bbl0ucHVzaChwdCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgY2RpO1xuICAgIHZhciBwdEZpbHRlckZuID0gKHRyYWNlLmJveHBvaW50cyB8fCB0cmFjZS5wb2ludHMpID09PSAnYWxsJyA/XG4gICAgICAgIExpYi5pZGVudGl0eSA6XG4gICAgICAgIGZ1bmN0aW9uKHB0KSB7IHJldHVybiAocHQudiA8IGNkaS5sZiB8fCBwdC52ID4gY2RpLnVmKTsgfTtcblxuICAgIC8vIGJ1aWxkIGNhbGNkYXRhIHRyYWNlIGl0ZW1zLCBvbmUgaXRlbSBwZXIgZGlzdGluY3QgcG9zaXRpb25cbiAgICBmb3IoaSA9IDA7IGkgPCBwTGVuOyBpKyspIHtcbiAgICAgICAgaWYocHRzUGVyQmluW2ldLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHZhciBwdHMgPSBwdHNQZXJCaW5baV0uc29ydChzb3J0QnlWYWwpO1xuICAgICAgICAgICAgdmFyIGJveFZhbHMgPSBwdHMubWFwKGV4dHJhY3RWYWwpO1xuICAgICAgICAgICAgdmFyIGJ2TGVuID0gYm94VmFscy5sZW5ndGg7XG5cbiAgICAgICAgICAgIGNkaSA9IHt9O1xuICAgICAgICAgICAgY2RpLnBvcyA9IHBvc0Rpc3RpbmN0W2ldO1xuICAgICAgICAgICAgY2RpLnB0cyA9IHB0cztcblxuICAgICAgICAgICAgLy8gU29ydCBjYXRlZ29yaWVzIGJ5IHZhbHVlc1xuICAgICAgICAgICAgY2RpW3Bvc0xldHRlcl0gPSBjZGkucG9zO1xuICAgICAgICAgICAgY2RpW3ZhbExldHRlcl0gPSBjZGkucHRzLm1hcChmdW5jdGlvbihwdCkgeyByZXR1cm4gcHQudjsgfSk7XG5cbiAgICAgICAgICAgIGNkaS5taW4gPSBib3hWYWxzWzBdO1xuICAgICAgICAgICAgY2RpLm1heCA9IGJveFZhbHNbYnZMZW4gLSAxXTtcbiAgICAgICAgICAgIGNkaS5tZWFuID0gTGliLm1lYW4oYm94VmFscywgYnZMZW4pO1xuICAgICAgICAgICAgY2RpLnNkID0gTGliLnN0ZGV2KGJveFZhbHMsIGJ2TGVuLCBjZGkubWVhbik7XG5cbiAgICAgICAgICAgIC8vIGZpcnN0IHF1YXJ0aWxlXG4gICAgICAgICAgICBjZGkucTEgPSBMaWIuaW50ZXJwKGJveFZhbHMsIDAuMjUpO1xuICAgICAgICAgICAgIC8vIG1lZGlhblxuICAgICAgICAgICAgY2RpLm1lZCA9IExpYi5pbnRlcnAoYm94VmFscywgMC41KTtcbiAgICAgICAgICAgIC8vIHRoaXJkIHF1YXJ0aWxlXG4gICAgICAgICAgICBjZGkucTMgPSBMaWIuaW50ZXJwKGJveFZhbHMsIDAuNzUpO1xuXG4gICAgICAgICAgICAvLyBsb3dlciBhbmQgdXBwZXIgZmVuY2VzIC0gbGFzdCBwb2ludCBpbnNpZGVcbiAgICAgICAgICAgIC8vIDEuNSBpbnRlcnF1YXJ0aWxlIHJhbmdlcyBmcm9tIHF1YXJ0aWxlc1xuICAgICAgICAgICAgY2RpLmxmID0gTWF0aC5taW4oXG4gICAgICAgICAgICAgICAgY2RpLnExLFxuICAgICAgICAgICAgICAgIGJveFZhbHNbTWF0aC5taW4oXG4gICAgICAgICAgICAgICAgICAgIExpYi5maW5kQmluKDIuNSAqIGNkaS5xMSAtIDEuNSAqIGNkaS5xMywgYm94VmFscywgdHJ1ZSkgKyAxLFxuICAgICAgICAgICAgICAgICAgICBidkxlbiAtIDFcbiAgICAgICAgICAgICAgICApXVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNkaS51ZiA9IE1hdGgubWF4KFxuICAgICAgICAgICAgICAgIGNkaS5xMyxcbiAgICAgICAgICAgICAgICBib3hWYWxzW01hdGgubWF4KFxuICAgICAgICAgICAgICAgICAgICBMaWIuZmluZEJpbigyLjUgKiBjZGkucTMgLSAxLjUgKiBjZGkucTEsIGJveFZhbHMpLFxuICAgICAgICAgICAgICAgICAgICAwXG4gICAgICAgICAgICAgICAgKV1cbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIGxvd2VyIGFuZCB1cHBlciBvdXRsaWVycyAtIDMgSVFSIG91dCAoZG9uJ3QgY2xpcCB0byBtYXgvbWluLFxuICAgICAgICAgICAgLy8gdGhpcyBpcyBvbmx5IGZvciBkaXNjcmltaW5hdGluZyBzdXNwZWN0ZWQgJiBmYXIgb3V0bGllcnMpXG4gICAgICAgICAgICBjZGkubG8gPSA0ICogY2RpLnExIC0gMyAqIGNkaS5xMztcbiAgICAgICAgICAgIGNkaS51byA9IDQgKiBjZGkucTMgLSAzICogY2RpLnExO1xuXG4gICAgICAgICAgICAvLyBsb3dlciBhbmQgdXBwZXIgbm90Y2hlcyB+OTUlIENvbmZpZGVuY2UgSW50ZXJ2YWxzIGZvciBtZWRpYW5cbiAgICAgICAgICAgIHZhciBpcXIgPSBjZGkucTMgLSBjZGkucTE7XG4gICAgICAgICAgICB2YXIgbWNpID0gMS41NyAqIGlxciAvIE1hdGguc3FydChidkxlbik7XG4gICAgICAgICAgICBjZGkubG4gPSBjZGkubWVkIC0gbWNpO1xuICAgICAgICAgICAgY2RpLnVuID0gY2RpLm1lZCArIG1jaTtcblxuICAgICAgICAgICAgY2RpLnB0czIgPSBwdHMuZmlsdGVyKHB0RmlsdGVyRm4pO1xuXG4gICAgICAgICAgICBjZC5wdXNoKGNkaSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjYWxjU2VsZWN0aW9uKGNkLCB0cmFjZSk7XG4gICAgdmFyIGV4dHJlbWVzID0gQXhlcy5maW5kRXh0cmVtZXModmFsQXhpcywgdmFsLCB7cGFkZGVkOiB0cnVlfSk7XG4gICAgdHJhY2UuX2V4dHJlbWVzW3ZhbEF4aXMuX2lkXSA9IGV4dHJlbWVzO1xuXG4gICAgaWYoY2QubGVuZ3RoID4gMCkge1xuICAgICAgICBjZFswXS50ID0ge1xuICAgICAgICAgICAgbnVtOiBmdWxsTGF5b3V0W251bUtleV0sXG4gICAgICAgICAgICBkUG9zOiBkUG9zLFxuICAgICAgICAgICAgcG9zTGV0dGVyOiBwb3NMZXR0ZXIsXG4gICAgICAgICAgICB2YWxMZXR0ZXI6IHZhbExldHRlcixcbiAgICAgICAgICAgIGxhYmVsczoge1xuICAgICAgICAgICAgICAgIG1lZDogXyhnZCwgJ21lZGlhbjonKSxcbiAgICAgICAgICAgICAgICBtaW46IF8oZ2QsICdtaW46JyksXG4gICAgICAgICAgICAgICAgcTE6IF8oZ2QsICdxMTonKSxcbiAgICAgICAgICAgICAgICBxMzogXyhnZCwgJ3EzOicpLFxuICAgICAgICAgICAgICAgIG1heDogXyhnZCwgJ21heDonKSxcbiAgICAgICAgICAgICAgICBtZWFuOiB0cmFjZS5ib3htZWFuID09PSAnc2QnID8gXyhnZCwgJ21lYW4gwrEgz4M6JykgOiBfKGdkLCAnbWVhbjonKSxcbiAgICAgICAgICAgICAgICBsZjogXyhnZCwgJ2xvd2VyIGZlbmNlOicpLFxuICAgICAgICAgICAgICAgIHVmOiBfKGdkLCAndXBwZXIgZmVuY2U6JylcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBmdWxsTGF5b3V0W251bUtleV0rKztcbiAgICAgICAgcmV0dXJuIGNkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbe3Q6IHtlbXB0eTogdHJ1ZX19XTtcbiAgICB9XG59O1xuXG4vLyBJbiB2ZXJ0aWNhbCAoaG9yaXpvbnRhbCkgYm94IHBsb3RzOlxuLy8gaWYgbm8geCAoeSkgZGF0YSwgdXNlIHgwICh5MCksIG9yIG5hbWVcbi8vIHNvIGlmIHlvdSB3YW50IG9uZSBib3hcbi8vIHBlciB0cmFjZSwgc2V0IHgwICh5MCkgdG8gdGhlIHggKHkpIHZhbHVlIG9yIGNhdGVnb3J5IGZvciB0aGlzIHRyYWNlXG4vLyAob3Igc2V0IHggKHkpIHRvIGEgY29uc3RhbnQgYXJyYXkgbWF0Y2hpbmcgeSAoeCkpXG5mdW5jdGlvbiBnZXRQb3ModHJhY2UsIHBvc0xldHRlciwgcG9zQXhpcywgdmFsLCBudW0pIHtcbiAgICBpZihwb3NMZXR0ZXIgaW4gdHJhY2UpIHtcbiAgICAgICAgcmV0dXJuIHBvc0F4aXMubWFrZUNhbGNkYXRhKHRyYWNlLCBwb3NMZXR0ZXIpO1xuICAgIH1cblxuICAgIHZhciBwb3MwO1xuXG4gICAgaWYocG9zTGV0dGVyICsgJzAnIGluIHRyYWNlKSB7XG4gICAgICAgIHBvczAgPSB0cmFjZVtwb3NMZXR0ZXIgKyAnMCddO1xuICAgIH0gZWxzZSBpZignbmFtZScgaW4gdHJhY2UgJiYgKFxuICAgICAgICBwb3NBeGlzLnR5cGUgPT09ICdjYXRlZ29yeScgfHwgKFxuICAgICAgICAgICAgaXNOdW1lcmljKHRyYWNlLm5hbWUpICYmXG4gICAgICAgICAgICBbJ2xpbmVhcicsICdsb2cnXS5pbmRleE9mKHBvc0F4aXMudHlwZSkgIT09IC0xXG4gICAgICAgICkgfHwgKFxuICAgICAgICAgICAgTGliLmlzRGF0ZVRpbWUodHJhY2UubmFtZSkgJiZcbiAgICAgICAgICAgIHBvc0F4aXMudHlwZSA9PT0gJ2RhdGUnXG4gICAgICAgIClcbiAgICApKSB7XG4gICAgICAgIHBvczAgPSB0cmFjZS5uYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHBvczAgPSBudW07XG4gICAgfVxuXG4gICAgdmFyIHBvczBjID0gcG9zQXhpcy50eXBlID09PSAnbXVsdGljYXRlZ29yeScgP1xuICAgICAgICBwb3NBeGlzLnIyY19qdXN0X2luZGljZXMocG9zMCkgOlxuICAgICAgICBwb3NBeGlzLmQyYyhwb3MwLCAwLCB0cmFjZVtwb3NMZXR0ZXIgKyAnY2FsZW5kYXInXSk7XG5cbiAgICByZXR1cm4gdmFsLm1hcChmdW5jdGlvbigpIHsgcmV0dXJuIHBvczBjOyB9KTtcbn1cblxuZnVuY3Rpb24gbWFrZUJpbnMoeCwgZHgpIHtcbiAgICB2YXIgbGVuID0geC5sZW5ndGg7XG4gICAgdmFyIGJpbnMgPSBuZXcgQXJyYXkobGVuICsgMSk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgYmluc1tpXSA9IHhbaV0gLSBkeDtcbiAgICB9XG4gICAgYmluc1tsZW5dID0geFtsZW4gLSAxXSArIGR4O1xuXG4gICAgcmV0dXJuIGJpbnM7XG59XG5cbmZ1bmN0aW9uIGluaXROZXN0ZWRBcnJheShsZW4pIHtcbiAgICB2YXIgYXJyID0gbmV3IEFycmF5KGxlbik7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGFycltpXSA9IFtdO1xuICAgIH1cbiAgICByZXR1cm4gYXJyO1xufVxuXG5mdW5jdGlvbiBhcnJheXNUb0NhbGNkYXRhKHB0LCB0cmFjZSwgaSkge1xuICAgIHZhciB0cmFjZTJjYWxjID0ge1xuICAgICAgICB0ZXh0OiAndHgnLFxuICAgICAgICBob3ZlcnRleHQ6ICdodHgnXG4gICAgfTtcblxuICAgIGZvcih2YXIgayBpbiB0cmFjZTJjYWxjKSB7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodHJhY2Vba10pKSB7XG4gICAgICAgICAgICBwdFt0cmFjZTJjYWxjW2tdXSA9IHRyYWNlW2tdW2ldO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjYWxjU2VsZWN0aW9uKGNkLCB0cmFjZSkge1xuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRyYWNlLnNlbGVjdGVkcG9pbnRzKSkge1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwdHMgPSBjZFtpXS5wdHMgfHwgW107XG4gICAgICAgICAgICB2YXIgcHROdW1iZXIyY2RJbmRleCA9IHt9O1xuXG4gICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgcHRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgcHROdW1iZXIyY2RJbmRleFtwdHNbal0uaV0gPSBqO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBMaWIudGFnU2VsZWN0ZWQocHRzLCB0cmFjZSwgcHROdW1iZXIyY2RJbmRleCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNvcnRCeVZhbChhLCBiKSB7IHJldHVybiBhLnYgLSBiLnY7IH1cblxuZnVuY3Rpb24gZXh0cmFjdFZhbChvKSB7IHJldHVybiBvLnY7IH1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sODgyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGdldEF4aXNHcm91cCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkcycpLmdldEF4aXNHcm91cDtcblxudmFyIG9yaWVudGF0aW9ucyA9IFsndicsICdoJ107XG5cbmZ1bmN0aW9uIGNyb3NzVHJhY2VDYWxjKGdkLCBwbG90aW5mbykge1xuICAgIHZhciBjYWxjZGF0YSA9IGdkLmNhbGNkYXRhO1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG9yaWVudGF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgb3JpZW50YXRpb24gPSBvcmllbnRhdGlvbnNbaV07XG4gICAgICAgIHZhciBwb3NBeGlzID0gb3JpZW50YXRpb24gPT09ICdoJyA/IHlhIDogeGE7XG4gICAgICAgIHZhciBib3hMaXN0ID0gW107XG5cbiAgICAgICAgLy8gbWFrZSBsaXN0IG9mIGJveGVzIC8gY2FuZGxlc3RpY2tzXG4gICAgICAgIC8vIEZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LCBjYW5kbGVzdGlja3MgYXJlIHRyZWF0ZWQgYXMgaWYgdGhleSAqYXJlKiBib3ggdHJhY2VzIGhlcmVcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNhbGNkYXRhLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgY2QgPSBjYWxjZGF0YVtqXTtcbiAgICAgICAgICAgIHZhciB0ID0gY2RbMF0udDtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuXG4gICAgICAgICAgICBpZih0cmFjZS52aXNpYmxlID09PSB0cnVlICYmXG4gICAgICAgICAgICAgICAgICAgICh0cmFjZS50eXBlID09PSAnYm94JyB8fCB0cmFjZS50eXBlID09PSAnY2FuZGxlc3RpY2snKSAmJlxuICAgICAgICAgICAgICAgICAgICAhdC5lbXB0eSAmJlxuICAgICAgICAgICAgICAgICAgICAodHJhY2Uub3JpZW50YXRpb24gfHwgJ3YnKSA9PT0gb3JpZW50YXRpb24gJiZcbiAgICAgICAgICAgICAgICAgICAgdHJhY2UueGF4aXMgPT09IHhhLl9pZCAmJlxuICAgICAgICAgICAgICAgICAgICB0cmFjZS55YXhpcyA9PT0geWEuX2lkXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGJveExpc3QucHVzaChqKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNldFBvc2l0aW9uT2Zmc2V0KCdib3gnLCBnZCwgYm94TGlzdCwgcG9zQXhpcyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzZXRQb3NpdGlvbk9mZnNldCh0cmFjZVR5cGUsIGdkLCBib3hMaXN0LCBwb3NBeGlzKSB7XG4gICAgdmFyIGNhbGNkYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgYXhJZCA9IHBvc0F4aXMuX2lkO1xuICAgIHZhciBheExldHRlciA9IGF4SWQuY2hhckF0KDApO1xuXG4gICAgdmFyIGksIGosIGNhbGNUcmFjZTtcbiAgICB2YXIgcG9pbnRMaXN0ID0gW107XG4gICAgdmFyIHNob3duUHRzID0gMDtcblxuICAgIC8vIG1ha2UgbGlzdCBvZiBib3ggcG9pbnRzXG4gICAgZm9yKGkgPSAwOyBpIDwgYm94TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjYWxjVHJhY2UgPSBjYWxjZGF0YVtib3hMaXN0W2ldXTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgY2FsY1RyYWNlLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBwb2ludExpc3QucHVzaChjYWxjVHJhY2Vbal0ucG9zKTtcbiAgICAgICAgICAgIHNob3duUHRzICs9IChjYWxjVHJhY2Vbal0ucHRzMiB8fCBbXSkubGVuZ3RoO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoIXBvaW50TGlzdC5sZW5ndGgpIHJldHVybjtcblxuICAgIC8vIGJveCBwbG90cyAtIHVwZGF0ZSBkUG9zIGJhc2VkIG9uIG11bHRpcGxlIHRyYWNlc1xuICAgIHZhciBib3hkdiA9IExpYi5kaXN0aW5jdFZhbHMocG9pbnRMaXN0KTtcbiAgICB2YXIgZFBvczAgPSBib3hkdi5taW5EaWZmIC8gMjtcblxuICAgIC8vIGNoZWNrIGZvciBmb3JjZWQgbWluaW11bSBkdGlja1xuICAgIEF4ZXMubWluRHRpY2socG9zQXhpcywgYm94ZHYubWluRGlmZiwgYm94ZHYudmFsc1swXSwgdHJ1ZSk7XG5cbiAgICB2YXIgbnVtS2V5ID0gdHJhY2VUeXBlID09PSAndmlvbGluJyA/ICdfbnVtVmlvbGlucycgOiAnX251bUJveGVzJztcbiAgICB2YXIgbnVtVG90YWwgPSBmdWxsTGF5b3V0W251bUtleV07XG4gICAgdmFyIGdyb3VwID0gZnVsbExheW91dFt0cmFjZVR5cGUgKyAnbW9kZSddID09PSAnZ3JvdXAnICYmIG51bVRvdGFsID4gMTtcbiAgICB2YXIgZ3JvdXBGcmFjdGlvbiA9IDEgLSBmdWxsTGF5b3V0W3RyYWNlVHlwZSArICdnYXAnXTtcbiAgICB2YXIgZ3JvdXBHYXBGcmFjdGlvbiA9IDEgLSBmdWxsTGF5b3V0W3RyYWNlVHlwZSArICdncm91cGdhcCddO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYm94TGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjYWxjVHJhY2UgPSBjYWxjZGF0YVtib3hMaXN0W2ldXTtcblxuICAgICAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG4gICAgICAgIHZhciB0ID0gY2FsY1RyYWNlWzBdLnQ7XG4gICAgICAgIHZhciB3aWR0aCA9IHRyYWNlLndpZHRoO1xuICAgICAgICB2YXIgc2lkZSA9IHRyYWNlLnNpZGU7XG5cbiAgICAgICAgLy8gcG9zaXRpb24gY29vcmRpbmF0ZSBkZWx0YVxuICAgICAgICB2YXIgZFBvcztcbiAgICAgICAgLy8gYm94IGhhbGYgd2lkdGg7XG4gICAgICAgIHZhciBiZFBvcztcbiAgICAgICAgLy8gYm94IGNlbnRlciBvZmZzZXRcbiAgICAgICAgdmFyIGJQb3M7XG4gICAgICAgIC8vIGhhbGYtd2lkdGggd2l0aGluIHdoaWNoIHRvIGFjY2VwdCBob3ZlciBmb3IgdGhpcyBib3gvdmlvbGluXG4gICAgICAgIC8vIGFsd2F5cyBzcGxpdCB0aGUgZGlzdGFuY2UgdG8gdGhlIGNsb3Nlc3QgYm94L3Zpb2xpblxuICAgICAgICB2YXIgd0hvdmVyO1xuXG4gICAgICAgIGlmKHdpZHRoKSB7XG4gICAgICAgICAgICBkUG9zID0gYmRQb3MgPSB3SG92ZXIgPSB3aWR0aCAvIDI7XG4gICAgICAgICAgICBiUG9zID0gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRQb3MgPSBkUG9zMDtcblxuICAgICAgICAgICAgaWYoZ3JvdXApIHtcbiAgICAgICAgICAgICAgICB2YXIgZ3JvdXBJZCA9IGdldEF4aXNHcm91cChmdWxsTGF5b3V0LCBwb3NBeGlzLl9pZCkgKyB0cmFjZS5vcmllbnRhdGlvbjtcbiAgICAgICAgICAgICAgICB2YXIgYWxpZ25tZW50R3JvdXBzID0gZnVsbExheW91dC5fYWxpZ25tZW50T3B0c1tncm91cElkXSB8fCB7fTtcbiAgICAgICAgICAgICAgICB2YXIgYWxpZ25tZW50R3JvdXBPcHRzID0gYWxpZ25tZW50R3JvdXBzW3RyYWNlLmFsaWdubWVudGdyb3VwXSB8fCB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbk9mZnNldEdyb3VwcyA9IE9iamVjdC5rZXlzKGFsaWdubWVudEdyb3VwT3B0cy5vZmZzZXRHcm91cHMgfHwge30pLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbnVtID0gbk9mZnNldEdyb3VwcyB8fCBudW1Ub3RhbDtcbiAgICAgICAgICAgICAgICB2YXIgc2hpZnQgPSBuT2Zmc2V0R3JvdXBzID8gdHJhY2UuX29mZnNldEluZGV4IDogdC5udW07XG5cbiAgICAgICAgICAgICAgICBiZFBvcyA9IGRQb3MgKiBncm91cEZyYWN0aW9uICogZ3JvdXBHYXBGcmFjdGlvbiAvIG51bTtcbiAgICAgICAgICAgICAgICBiUG9zID0gMiAqIGRQb3MgKiAoLTAuNSArIChzaGlmdCArIDAuNSkgLyBudW0pICogZ3JvdXBGcmFjdGlvbjtcbiAgICAgICAgICAgICAgICB3SG92ZXIgPSBkUG9zICogZ3JvdXBGcmFjdGlvbiAvIG51bTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYmRQb3MgPSBkUG9zICogZ3JvdXBGcmFjdGlvbiAqIGdyb3VwR2FwRnJhY3Rpb247XG4gICAgICAgICAgICAgICAgYlBvcyA9IDA7XG4gICAgICAgICAgICAgICAgd0hvdmVyID0gZFBvcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0LmRQb3MgPSBkUG9zO1xuICAgICAgICB0LmJQb3MgPSBiUG9zO1xuICAgICAgICB0LmJkUG9zID0gYmRQb3M7XG4gICAgICAgIHQud0hvdmVyID0gd0hvdmVyO1xuXG4gICAgICAgIC8vIGJveC92aW9saW4tb25seSB2YWx1ZS1zcGFjZSBwdXNoIHZhbHVlXG4gICAgICAgIHZhciBwdXNocGx1cztcbiAgICAgICAgdmFyIHB1c2htaW51cztcbiAgICAgICAgLy8gZWRnZSBvZiBib3gvdmlvbGluXG4gICAgICAgIHZhciBlZGdlID0gYlBvcyArIGJkUG9zO1xuICAgICAgICB2YXIgZWRnZXBsdXM7XG4gICAgICAgIHZhciBlZGdlbWludXM7XG4gICAgICAgIC8vIHZhbHVlLXNwYWNlIHBhZGRpbmdcbiAgICAgICAgdmFyIHZwYWRwbHVzO1xuICAgICAgICB2YXIgdnBhZG1pbnVzO1xuICAgICAgICAvLyBwaXhlbC1zcGFjZSBwYWRkaW5nXG4gICAgICAgIHZhciBwcGFkcGx1cztcbiAgICAgICAgdmFyIHBwYWRtaW51cztcbiAgICAgICAgLy8gZG8gd2UgYWRkIDUlIG9mIGJvdGggc2lkZXMgKG1vcmUgbG9naWMgZm9yIHBvaW50cyBiZXlvbmQgYm94L3Zpb2xpbiBiZWxvdylcbiAgICAgICAgdmFyIHBhZGRlZCA9IEJvb2xlYW4od2lkdGgpO1xuICAgICAgICAvLyBkb2VzIHRoaXMgdHJhY2Ugc2hvdyBwb2ludHM/XG4gICAgICAgIHZhciBoYXNQdHMgPSAodHJhY2UuYm94cG9pbnRzIHx8IHRyYWNlLnBvaW50cykgJiYgKHNob3duUHRzID4gMCk7XG5cbiAgICAgICAgaWYoc2lkZSA9PT0gJ3Bvc2l0aXZlJykge1xuICAgICAgICAgICAgcHVzaHBsdXMgPSBkUG9zICogKHdpZHRoID8gMSA6IDAuNSk7XG4gICAgICAgICAgICBlZGdlcGx1cyA9IGVkZ2U7XG4gICAgICAgICAgICBwdXNobWludXMgPSBlZGdlcGx1cyA9IGJQb3M7XG4gICAgICAgIH0gZWxzZSBpZihzaWRlID09PSAnbmVnYXRpdmUnKSB7XG4gICAgICAgICAgICBwdXNocGx1cyA9IGVkZ2VwbHVzID0gYlBvcztcbiAgICAgICAgICAgIHB1c2htaW51cyA9IGRQb3MgKiAod2lkdGggPyAxIDogMC41KTtcbiAgICAgICAgICAgIGVkZ2VtaW51cyA9IGVkZ2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwdXNocGx1cyA9IHB1c2htaW51cyA9IGRQb3M7XG4gICAgICAgICAgICBlZGdlcGx1cyA9IGVkZ2VtaW51cyA9IGVkZ2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZihoYXNQdHMpIHtcbiAgICAgICAgICAgIHZhciBwb2ludHBvcyA9IHRyYWNlLnBvaW50cG9zO1xuICAgICAgICAgICAgdmFyIGppdHRlciA9IHRyYWNlLmppdHRlcjtcbiAgICAgICAgICAgIHZhciBtcyA9IHRyYWNlLm1hcmtlci5zaXplIC8gMjtcblxuICAgICAgICAgICAgdmFyIHBwID0gMDtcbiAgICAgICAgICAgIGlmKChwb2ludHBvcyArIGppdHRlcikgPj0gMCkge1xuICAgICAgICAgICAgICAgIHBwID0gZWRnZSAqIChwb2ludHBvcyArIGppdHRlcik7XG4gICAgICAgICAgICAgICAgaWYocHAgPiBwdXNocGx1cykge1xuICAgICAgICAgICAgICAgICAgICAvLyAoKyspIGJleW9uZCBwbHVzLXZhbHVlLCB1c2UgcHBcbiAgICAgICAgICAgICAgICAgICAgcGFkZGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcHBhZHBsdXMgPSBtcztcbiAgICAgICAgICAgICAgICAgICAgdnBhZHBsdXMgPSBwcDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYocHAgPiBlZGdlcGx1cykge1xuICAgICAgICAgICAgICAgICAgICAvLyAoKyksIHVzZSBwdXNoLXZhbHVlIChpdCdzIGJpZ2dlciksIGJ1dCBhZGQgcHgtcGFkXG4gICAgICAgICAgICAgICAgICAgIHBwYWRwbHVzID0gbXM7XG4gICAgICAgICAgICAgICAgICAgIHZwYWRwbHVzID0gcHVzaHBsdXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYocHAgPD0gcHVzaHBsdXMpIHtcbiAgICAgICAgICAgICAgICAvLyAoLT4pIGZhbGxiYWNrIHRvIHB1c2ggdmFsdWVcbiAgICAgICAgICAgICAgICB2cGFkcGx1cyA9IHB1c2hwbHVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcG0gPSAwO1xuICAgICAgICAgICAgaWYoKHBvaW50cG9zIC0gaml0dGVyKSA8PSAwKSB7XG4gICAgICAgICAgICAgICAgcG0gPSAtZWRnZSAqIChwb2ludHBvcyAtIGppdHRlcik7XG4gICAgICAgICAgICAgICAgaWYocG0gPiBwdXNobWludXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gKC0tKSBiZXlvbmQgcGx1cy12YWx1ZSwgdXNlIHBwXG4gICAgICAgICAgICAgICAgICAgIHBhZGRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHBwYWRtaW51cyA9IG1zO1xuICAgICAgICAgICAgICAgICAgICB2cGFkbWludXMgPSBwbTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYocG0gPiBlZGdlbWludXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gKC0pLCB1c2UgcHVzaC12YWx1ZSAoaXQncyBiaWdnZXIpLCBidXQgYWRkIHB4LXBhZFxuICAgICAgICAgICAgICAgICAgICBwcGFkbWludXMgPSBtcztcbiAgICAgICAgICAgICAgICAgICAgdnBhZG1pbnVzID0gcHVzaG1pbnVzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHBtIDw9IHB1c2htaW51cykge1xuICAgICAgICAgICAgICAgIC8vICg8LSkgZmFsbGJhY2sgdG8gcHVzaCB2YWx1ZVxuICAgICAgICAgICAgICAgIHZwYWRtaW51cyA9IHB1c2htaW51cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZwYWRwbHVzID0gcHVzaHBsdXM7XG4gICAgICAgICAgICB2cGFkbWludXMgPSBwdXNobWludXM7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcG9zID0gbmV3IEFycmF5KGNhbGNUcmFjZS5sZW5ndGgpO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBjYWxjVHJhY2UubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHBvc1tqXSA9IGNhbGNUcmFjZVtqXS5wb3M7XG4gICAgICAgIH1cblxuICAgICAgICB0cmFjZS5fZXh0cmVtZXNbYXhJZF0gPSBBeGVzLmZpbmRFeHRyZW1lcyhwb3NBeGlzLCBwb3MsIHtcbiAgICAgICAgICAgIHBhZGRlZDogcGFkZGVkLFxuICAgICAgICAgICAgdnBhZG1pbnVzOiB2cGFkbWludXMsXG4gICAgICAgICAgICB2cGFkcGx1czogdnBhZHBsdXMsXG4gICAgICAgICAgICAvLyBOLkIuIFNWRyBweC1zcGFjZSBwb3NpdGl2ZS9uZWdhdGl2ZVxuICAgICAgICAgICAgcHBhZG1pbnVzOiB7eDogcHBhZG1pbnVzLCB5OiBwcGFkcGx1c31bYXhMZXR0ZXJdLFxuICAgICAgICAgICAgcHBhZHBsdXM6IHt4OiBwcGFkcGx1cywgeTogcHBhZG1pbnVzfVtheExldHRlcl0sXG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY3Jvc3NUcmFjZUNhbGM6IGNyb3NzVHJhY2VDYWxjLFxuICAgIHNldFBvc2l0aW9uT2Zmc2V0OiBzZXRQb3NpdGlvbk9mZnNldFxufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkc1wiOjc3MH1dLDg4MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgaGFuZGxlR3JvdXBpbmdEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL2Jhci9kZWZhdWx0cycpLmhhbmRsZUdyb3VwaW5nRGVmYXVsdHM7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG5mdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgaGFuZGxlU2FtcGxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KTtcbiAgICBpZih0cmFjZU91dC52aXNpYmxlID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgY29lcmNlKCdsaW5lLmNvbG9yJywgKHRyYWNlSW4ubWFya2VyIHx8IHt9KS5jb2xvciB8fCBkZWZhdWx0Q29sb3IpO1xuICAgIGNvZXJjZSgnbGluZS53aWR0aCcpO1xuICAgIGNvZXJjZSgnZmlsbGNvbG9yJywgQ29sb3IuYWRkT3BhY2l0eSh0cmFjZU91dC5saW5lLmNvbG9yLCAwLjUpKTtcblxuICAgIGNvZXJjZSgnd2hpc2tlcndpZHRoJyk7XG4gICAgY29lcmNlKCdib3htZWFuJyk7XG4gICAgY29lcmNlKCd3aWR0aCcpO1xuXG4gICAgdmFyIG5vdGNoZWQgPSBjb2VyY2UoJ25vdGNoZWQnLCB0cmFjZUluLm5vdGNod2lkdGggIT09IHVuZGVmaW5lZCk7XG4gICAgaWYobm90Y2hlZCkgY29lcmNlKCdub3RjaHdpZHRoJyk7XG5cbiAgICBoYW5kbGVQb2ludHNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCB7cHJlZml4OiAnYm94J30pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVTYW1wbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpIHtcbiAgICB2YXIgeSA9IGNvZXJjZSgneScpO1xuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIGhhc1ggPSB4ICYmIHgubGVuZ3RoO1xuXG4gICAgdmFyIGRlZmF1bHRPcmllbnRhdGlvbiwgbGVuO1xuXG4gICAgaWYoeSAmJiB5Lmxlbmd0aCkge1xuICAgICAgICBkZWZhdWx0T3JpZW50YXRpb24gPSAndic7XG4gICAgICAgIGlmKGhhc1gpIHtcbiAgICAgICAgICAgIGxlbiA9IE1hdGgubWluKExpYi5taW5Sb3dMZW5ndGgoeCksIExpYi5taW5Sb3dMZW5ndGgoeSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29lcmNlKCd4MCcpO1xuICAgICAgICAgICAgbGVuID0gTGliLm1pblJvd0xlbmd0aCh5KTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZihoYXNYKSB7XG4gICAgICAgIGRlZmF1bHRPcmllbnRhdGlvbiA9ICdoJztcbiAgICAgICAgY29lcmNlKCd5MCcpO1xuICAgICAgICBsZW4gPSBMaWIubWluUm93TGVuZ3RoKHgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuXG4gICAgdmFyIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdoYW5kbGVUcmFjZURlZmF1bHRzJyk7XG4gICAgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgWyd4JywgJ3knXSwgbGF5b3V0KTtcblxuICAgIGNvZXJjZSgnb3JpZW50YXRpb24nLCBkZWZhdWx0T3JpZW50YXRpb24pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVQb2ludHNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBvcHRzKSB7XG4gICAgdmFyIHByZWZpeCA9IG9wdHMucHJlZml4O1xuXG4gICAgdmFyIG91dGxpZXJDb2xvckRmbHQgPSBMaWIuY29lcmNlMih0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgJ21hcmtlci5vdXRsaWVyY29sb3InKTtcbiAgICB2YXIgbGluZW91dGxpZXJjb2xvciA9IGNvZXJjZSgnbWFya2VyLmxpbmUub3V0bGllcmNvbG9yJyk7XG5cbiAgICB2YXIgcG9pbnRzID0gY29lcmNlKFxuICAgICAgICBwcmVmaXggKyAncG9pbnRzJyxcbiAgICAgICAgKG91dGxpZXJDb2xvckRmbHQgfHwgbGluZW91dGxpZXJjb2xvcikgPyAnc3VzcGVjdGVkb3V0bGllcnMnIDogdW5kZWZpbmVkXG4gICAgKTtcblxuICAgIGlmKHBvaW50cykge1xuICAgICAgICBjb2VyY2UoJ2ppdHRlcicsIHBvaW50cyA9PT0gJ2FsbCcgPyAwLjMgOiAwKTtcbiAgICAgICAgY29lcmNlKCdwb2ludHBvcycsIHBvaW50cyA9PT0gJ2FsbCcgPyAtMS41IDogMCk7XG5cbiAgICAgICAgY29lcmNlKCdtYXJrZXIuc3ltYm9sJyk7XG4gICAgICAgIGNvZXJjZSgnbWFya2VyLm9wYWNpdHknKTtcbiAgICAgICAgY29lcmNlKCdtYXJrZXIuc2l6ZScpO1xuICAgICAgICBjb2VyY2UoJ21hcmtlci5jb2xvcicsIHRyYWNlT3V0LmxpbmUuY29sb3IpO1xuICAgICAgICBjb2VyY2UoJ21hcmtlci5saW5lLmNvbG9yJyk7XG4gICAgICAgIGNvZXJjZSgnbWFya2VyLmxpbmUud2lkdGgnKTtcblxuICAgICAgICBpZihwb2ludHMgPT09ICdzdXNwZWN0ZWRvdXRsaWVycycpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnbWFya2VyLmxpbmUub3V0bGllcmNvbG9yJywgdHJhY2VPdXQubWFya2VyLmNvbG9yKTtcbiAgICAgICAgICAgIGNvZXJjZSgnbWFya2VyLmxpbmUub3V0bGllcndpZHRoJyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb2VyY2UoJ3NlbGVjdGVkLm1hcmtlci5jb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ3Vuc2VsZWN0ZWQubWFya2VyLmNvbG9yJyk7XG4gICAgICAgIGNvZXJjZSgnc2VsZWN0ZWQubWFya2VyLnNpemUnKTtcbiAgICAgICAgY29lcmNlKCd1bnNlbGVjdGVkLm1hcmtlci5zaXplJyk7XG5cbiAgICAgICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZGVsZXRlIHRyYWNlT3V0Lm1hcmtlcjtcbiAgICB9XG5cbiAgICB2YXIgaG92ZXJvbiA9IGNvZXJjZSgnaG92ZXJvbicpO1xuICAgIGlmKGhvdmVyb24gPT09ICdhbGwnIHx8IGhvdmVyb24uaW5kZXhPZigncG9pbnRzJykgIT09IC0xKSB7XG4gICAgICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuICAgIH1cblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufVxuXG5mdW5jdGlvbiBjcm9zc1RyYWNlRGVmYXVsdHMoZnVsbERhdGEsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgdHJhY2VJbiwgdHJhY2VPdXQ7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0cikge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZU91dC5faW5wdXQsIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyKTtcbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJhY2VPdXQgPSBmdWxsRGF0YVtpXTtcbiAgICAgICAgdmFyIHRyYWNlVHlwZSA9IHRyYWNlT3V0LnR5cGU7XG5cbiAgICAgICAgaWYodHJhY2VUeXBlID09PSAnYm94JyB8fCB0cmFjZVR5cGUgPT09ICd2aW9saW4nKSB7XG4gICAgICAgICAgICB0cmFjZUluID0gdHJhY2VPdXQuX2lucHV0O1xuICAgICAgICAgICAgaWYoZnVsbExheW91dFt0cmFjZVR5cGUgKyAnbW9kZSddID09PSAnZ3JvdXAnKSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlR3JvdXBpbmdEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZnVsbExheW91dCwgY29lcmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3VwcGx5RGVmYXVsdHM6IHN1cHBseURlZmF1bHRzLFxuICAgIGNyb3NzVHJhY2VEZWZhdWx0czogY3Jvc3NUcmFjZURlZmF1bHRzLFxuXG4gICAgaGFuZGxlU2FtcGxlRGVmYXVsdHM6IGhhbmRsZVNhbXBsZURlZmF1bHRzLFxuICAgIGhhbmRsZVBvaW50c0RlZmF1bHRzOiBoYW5kbGVQb2ludHNEZWZhdWx0c1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9iYXIvZGVmYXVsdHNcIjo4NjEsXCIuL2F0dHJpYnV0ZXNcIjo4ODB9XSw4ODQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0KSB7XG4gICAgLy8gTm90ZTogaG92ZXJPbkJveCBwcm9wZXJ0eSBpcyBuZWVkZWQgZm9yIGNsaWNrLXRvLXNlbGVjdFxuICAgIC8vIHRvIGlnbm9yZSB3aGVuIGEgYm94IHdhcyBjbGlja2VkLiBUaGlzIGlzIHRoZSByZWFzb24gYm94XG4gICAgLy8gaW1wbGVtZW50cyB0aGlzIGN1c3RvbSBldmVudERhdGEgZnVuY3Rpb24uXG4gICAgaWYocHQuaG92ZXJPbkJveCkgb3V0LmhvdmVyT25Cb3ggPSBwdC5ob3Zlck9uQm94O1xuXG4gICAgaWYoJ3hWYWwnIGluIHB0KSBvdXQueCA9IHB0LnhWYWw7XG4gICAgaWYoJ3lWYWwnIGluIHB0KSBvdXQueSA9IHB0LnlWYWw7XG4gICAgaWYocHQueGEpIG91dC54YXhpcyA9IHB0LnhhO1xuICAgIGlmKHB0LnlhKSBvdXQueWF4aXMgPSBwdC55YTtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG59LHt9XSw4ODU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgZmlsbFRleHQgPSBMaWIuZmlsbFRleHQ7XG5cbmZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIGNkID0gcG9pbnREYXRhLmNkO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciBob3Zlcm9uID0gdHJhY2UuaG92ZXJvbjtcbiAgICB2YXIgY2xvc2VCb3hEYXRhID0gW107XG4gICAgdmFyIGNsb3NlUHREYXRhO1xuXG4gICAgaWYoaG92ZXJvbi5pbmRleE9mKCdib3hlcycpICE9PSAtMSkge1xuICAgICAgICBjbG9zZUJveERhdGEgPSBjbG9zZUJveERhdGEuY29uY2F0KGhvdmVyT25Cb3hlcyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkpO1xuICAgIH1cblxuICAgIGlmKGhvdmVyb24uaW5kZXhPZigncG9pbnRzJykgIT09IC0xKSB7XG4gICAgICAgIGNsb3NlUHREYXRhID0gaG92ZXJPblBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwpO1xuICAgIH1cblxuICAgIC8vIElmIHRoZXJlJ3MgYSBwb2ludCBpbiByYW5nZSBhbmQgaG92ZXJvbiBoYXMgcG9pbnRzLCBzaG93IHRoZSBiZXN0IHNpbmdsZSBwb2ludCBvbmx5LlxuICAgIC8vIElmIGhvdmVyb24gaGFzIGJveGVzIGFuZCB0aGVyZSdzIG5vIHBvaW50IGluIHJhbmdlIChvciBob3Zlcm9uIGRvZXNuJ3QgaGF2ZSBwb2ludHMpLCBzaG93IHRoZSBib3ggc3RhdHMuXG4gICAgaWYoaG92ZXJtb2RlID09PSAnY2xvc2VzdCcpIHtcbiAgICAgICAgaWYoY2xvc2VQdERhdGEpIHJldHVybiBbY2xvc2VQdERhdGFdO1xuICAgICAgICByZXR1cm4gY2xvc2VCb3hEYXRhO1xuICAgIH1cblxuICAgIC8vIE90aGVyd2lzZSBpbiBjb21wYXJlIG1vZGUsIGFsbG93IGEgcG9pbnQgQU5EIHRoZSBib3ggc3RhdHMgdG8gYmUgbGFiZWxlZFxuICAgIC8vIElmIHRoZXJlIGFyZSBtdWx0aXBsZSBib3hlcyBpbiByYW5nZSAoaWUgYm94bW9kZSA9ICdvdmVybGF5Jykgd2UnbGwgc2VlIHN0YXRzIGZvciBhbGwgb2YgdGhlbS5cbiAgICBpZihjbG9zZVB0RGF0YSkge1xuICAgICAgICBjbG9zZUJveERhdGEucHVzaChjbG9zZVB0RGF0YSk7XG4gICAgICAgIHJldHVybiBjbG9zZUJveERhdGE7XG4gICAgfVxuICAgIHJldHVybiBjbG9zZUJveERhdGE7XG59XG5cbmZ1bmN0aW9uIGhvdmVyT25Cb3hlcyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgeGEgPSBwb2ludERhdGEueGE7XG4gICAgdmFyIHlhID0gcG9pbnREYXRhLnlhO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciB0ID0gY2RbMF0udDtcbiAgICB2YXIgaXNWaW9saW4gPSB0cmFjZS50eXBlID09PSAndmlvbGluJztcbiAgICB2YXIgY2xvc2VCb3hEYXRhID0gW107XG5cbiAgICB2YXIgcExldHRlciwgdkxldHRlciwgcEF4aXMsIHZBeGlzLCB2VmFsLCBwVmFsLCBkeCwgZHksIGRQb3MsXG4gICAgICAgIGhvdmVyUHNldWRvRGlzdGFuY2UsIHNwaWtlUHNldWRvRGlzdGFuY2U7XG5cbiAgICB2YXIgYm94RGVsdGEgPSB0LmJkUG9zO1xuICAgIHZhciBib3hEZWx0YVBvcywgYm94RGVsdGFOZWc7XG4gICAgdmFyIHBvc0FjY2VwdGFuY2UgPSB0LndIb3ZlcjtcbiAgICB2YXIgc2hpZnRQb3MgPSBmdW5jdGlvbihkaSkgeyByZXR1cm4gZGkucG9zICsgdC5iUG9zIC0gcFZhbDsgfTtcblxuICAgIGlmKGlzVmlvbGluICYmIHRyYWNlLnNpZGUgIT09ICdib3RoJykge1xuICAgICAgICBpZih0cmFjZS5zaWRlID09PSAncG9zaXRpdmUnKSB7XG4gICAgICAgICAgICBkUG9zID0gZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcG9zID0gc2hpZnRQb3MoZGkpO1xuICAgICAgICAgICAgICAgIHJldHVybiBGeC5pbmJveChwb3MsIHBvcyArIHBvc0FjY2VwdGFuY2UsIGhvdmVyUHNldWRvRGlzdGFuY2UpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGJveERlbHRhUG9zID0gYm94RGVsdGE7XG4gICAgICAgICAgICBib3hEZWx0YU5lZyA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYodHJhY2Uuc2lkZSA9PT0gJ25lZ2F0aXZlJykge1xuICAgICAgICAgICAgZFBvcyA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBvcyA9IHNoaWZ0UG9zKGRpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gRnguaW5ib3gocG9zIC0gcG9zQWNjZXB0YW5jZSwgcG9zLCBob3ZlclBzZXVkb0Rpc3RhbmNlKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBib3hEZWx0YVBvcyA9IDA7XG4gICAgICAgICAgICBib3hEZWx0YU5lZyA9IGJveERlbHRhO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZFBvcyA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICB2YXIgcG9zID0gc2hpZnRQb3MoZGkpO1xuICAgICAgICAgICAgcmV0dXJuIEZ4LmluYm94KHBvcyAtIHBvc0FjY2VwdGFuY2UsIHBvcyArIHBvc0FjY2VwdGFuY2UsIGhvdmVyUHNldWRvRGlzdGFuY2UpO1xuICAgICAgICB9O1xuICAgICAgICBib3hEZWx0YVBvcyA9IGJveERlbHRhTmVnID0gYm94RGVsdGE7XG4gICAgfVxuXG4gICAgdmFyIGRWYWw7XG5cbiAgICBpZihpc1Zpb2xpbikge1xuICAgICAgICBkVmFsID0gZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgIHJldHVybiBGeC5pbmJveChkaS5zcGFuWzBdIC0gdlZhbCwgZGkuc3BhblsxXSAtIHZWYWwsIGhvdmVyUHNldWRvRGlzdGFuY2UpO1xuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRWYWwgPSBmdW5jdGlvbihkaSkge1xuICAgICAgICAgICAgcmV0dXJuIEZ4LmluYm94KGRpLm1pbiAtIHZWYWwsIGRpLm1heCAtIHZWYWwsIGhvdmVyUHNldWRvRGlzdGFuY2UpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgdlZhbCA9IHh2YWw7XG4gICAgICAgIHBWYWwgPSB5dmFsO1xuICAgICAgICBkeCA9IGRWYWw7XG4gICAgICAgIGR5ID0gZFBvcztcbiAgICAgICAgcExldHRlciA9ICd5JztcbiAgICAgICAgcEF4aXMgPSB5YTtcbiAgICAgICAgdkxldHRlciA9ICd4JztcbiAgICAgICAgdkF4aXMgPSB4YTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2VmFsID0geXZhbDtcbiAgICAgICAgcFZhbCA9IHh2YWw7XG4gICAgICAgIGR4ID0gZFBvcztcbiAgICAgICAgZHkgPSBkVmFsO1xuICAgICAgICBwTGV0dGVyID0gJ3gnO1xuICAgICAgICBwQXhpcyA9IHhhO1xuICAgICAgICB2TGV0dGVyID0gJ3knO1xuICAgICAgICB2QXhpcyA9IHlhO1xuICAgIH1cblxuICAgIC8vIGlmIHR3byBib3hlcyBhcmUgb3ZlcmxheWluZywgbGV0IHRoZSBuYXJyb3dlc3Qgb25lIHdpblxuICAgIHZhciBwc2V1ZG9EaXN0YW5jZSA9IE1hdGgubWluKDEsIGJveERlbHRhIC8gTWF0aC5hYnMocEF4aXMucjJjKHBBeGlzLnJhbmdlWzFdKSAtIHBBeGlzLnIyYyhwQXhpcy5yYW5nZVswXSkpKTtcbiAgICBob3ZlclBzZXVkb0Rpc3RhbmNlID0gcG9pbnREYXRhLm1heEhvdmVyRGlzdGFuY2UgLSBwc2V1ZG9EaXN0YW5jZTtcbiAgICBzcGlrZVBzZXVkb0Rpc3RhbmNlID0gcG9pbnREYXRhLm1heFNwaWtlRGlzdGFuY2UgLSBwc2V1ZG9EaXN0YW5jZTtcblxuICAgIGZ1bmN0aW9uIGR4eShkaSkgeyByZXR1cm4gKGR4KGRpKSArIGR5KGRpKSkgLyAyOyB9XG4gICAgdmFyIGRpc3RmbiA9IEZ4LmdldERpc3RhbmNlRnVuY3Rpb24oaG92ZXJtb2RlLCBkeCwgZHksIGR4eSk7XG4gICAgRnguZ2V0Q2xvc2VzdChjZCwgZGlzdGZuLCBwb2ludERhdGEpO1xuXG4gICAgLy8gc2tpcCB0aGUgcmVzdCAoZm9yIHRoaXMgdHJhY2UpIGlmIHdlIGRpZG4ndCBmaW5kIGEgY2xvc2UgcG9pbnRcbiAgICAvLyBhbmQgY3JlYXRlIHRoZSBpdGVtKHMpIGluIGNsb3NlZGF0YSBmb3IgdGhpcyBwb2ludFxuICAgIGlmKHBvaW50RGF0YS5pbmRleCA9PT0gZmFsc2UpIHJldHVybiBbXTtcblxuICAgIHZhciBkaSA9IGNkW3BvaW50RGF0YS5pbmRleF07XG4gICAgdmFyIGxjID0gdHJhY2UubGluZS5jb2xvcjtcbiAgICB2YXIgbWMgPSAodHJhY2UubWFya2VyIHx8IHt9KS5jb2xvcjtcblxuICAgIGlmKENvbG9yLm9wYWNpdHkobGMpICYmIHRyYWNlLmxpbmUud2lkdGgpIHBvaW50RGF0YS5jb2xvciA9IGxjO1xuICAgIGVsc2UgaWYoQ29sb3Iub3BhY2l0eShtYykgJiYgdHJhY2UuYm94cG9pbnRzKSBwb2ludERhdGEuY29sb3IgPSBtYztcbiAgICBlbHNlIHBvaW50RGF0YS5jb2xvciA9IHRyYWNlLmZpbGxjb2xvcjtcblxuICAgIHBvaW50RGF0YVtwTGV0dGVyICsgJzAnXSA9IHBBeGlzLmMycChkaS5wb3MgKyB0LmJQb3MgLSBib3hEZWx0YU5lZywgdHJ1ZSk7XG4gICAgcG9pbnREYXRhW3BMZXR0ZXIgKyAnMSddID0gcEF4aXMuYzJwKGRpLnBvcyArIHQuYlBvcyArIGJveERlbHRhUG9zLCB0cnVlKTtcblxuICAgIHBvaW50RGF0YVtwTGV0dGVyICsgJ0xhYmVsVmFsJ10gPSBkaS5wb3M7XG5cbiAgICB2YXIgc3Bpa2VQb3NBdHRyID0gcExldHRlciArICdTcGlrZSc7XG4gICAgcG9pbnREYXRhLnNwaWtlRGlzdGFuY2UgPSBkeHkoZGkpICogc3Bpa2VQc2V1ZG9EaXN0YW5jZSAvIGhvdmVyUHNldWRvRGlzdGFuY2U7XG4gICAgcG9pbnREYXRhW3NwaWtlUG9zQXR0cl0gPSBwQXhpcy5jMnAoZGkucG9zLCB0cnVlKTtcblxuICAgIC8vIGJveCBwbG90czogZWFjaCBcInBvaW50XCIgZ2V0cyBtYW55IGxhYmVsc1xuICAgIHZhciB1c2VkVmFscyA9IHt9O1xuICAgIHZhciBhdHRycyA9IFsnbWVkJywgJ3ExJywgJ3EzJywgJ21pbicsICdtYXgnXTtcblxuICAgIGlmKHRyYWNlLmJveG1lYW4gfHwgKHRyYWNlLm1lYW5saW5lIHx8IHt9KS52aXNpYmxlKSB7XG4gICAgICAgIGF0dHJzLnB1c2goJ21lYW4nKTtcbiAgICB9XG4gICAgaWYodHJhY2UuYm94cG9pbnRzIHx8IHRyYWNlLnBvaW50cykge1xuICAgICAgICBhdHRycy5wdXNoKCdsZicsICd1ZicpO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhdHRycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgYXR0ciA9IGF0dHJzW2ldO1xuXG4gICAgICAgIGlmKCEoYXR0ciBpbiBkaSkgfHwgKGRpW2F0dHJdIGluIHVzZWRWYWxzKSkgY29udGludWU7XG4gICAgICAgIHVzZWRWYWxzW2RpW2F0dHJdXSA9IHRydWU7XG5cbiAgICAgICAgLy8gY29weSBvdXQgdG8gYSBuZXcgb2JqZWN0IGZvciBlYWNoIHZhbHVlIHRvIGxhYmVsXG4gICAgICAgIHZhciB2YWwgPSBkaVthdHRyXTtcbiAgICAgICAgdmFyIHZhbFB4ID0gdkF4aXMuYzJwKHZhbCwgdHJ1ZSk7XG4gICAgICAgIHZhciBwb2ludERhdGEyID0gTGliLmV4dGVuZEZsYXQoe30sIHBvaW50RGF0YSk7XG5cbiAgICAgICAgcG9pbnREYXRhMi5hdHRyID0gYXR0cjtcbiAgICAgICAgcG9pbnREYXRhMlt2TGV0dGVyICsgJzAnXSA9IHBvaW50RGF0YTJbdkxldHRlciArICcxJ10gPSB2YWxQeDtcbiAgICAgICAgcG9pbnREYXRhMlt2TGV0dGVyICsgJ0xhYmVsVmFsJ10gPSB2YWw7XG4gICAgICAgIHBvaW50RGF0YTJbdkxldHRlciArICdMYWJlbCddID0gKHQubGFiZWxzID8gdC5sYWJlbHNbYXR0cl0gKyAnICcgOiAnJykgKyBBeGVzLmhvdmVyTGFiZWxUZXh0KHZBeGlzLCB2YWwpO1xuXG4gICAgICAgIC8vIE5vdGU6IGludHJvZHVjZWQgdG8gYmUgYWJsZSB0byBkaXN0aW5ndWlzaCBhXG4gICAgICAgIC8vIGNsaWNrZWQgcG9pbnQgZnJvbSBhIGJveCBkdXJpbmcgY2xpY2stdG8tc2VsZWN0XG4gICAgICAgIHBvaW50RGF0YTIuaG92ZXJPbkJveCA9IHRydWU7XG5cbiAgICAgICAgaWYoYXR0ciA9PT0gJ21lYW4nICYmICgnc2QnIGluIGRpKSAmJiB0cmFjZS5ib3htZWFuID09PSAnc2QnKSB7XG4gICAgICAgICAgICBwb2ludERhdGEyW3ZMZXR0ZXIgKyAnZXJyJ10gPSBkaS5zZDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG9ubHkga2VlcCBuYW1lIGFuZCBzcGlrZXMgb24gdGhlIGZpcnN0IGl0ZW0gKG1lZGlhbilcbiAgICAgICAgcG9pbnREYXRhLm5hbWUgPSAnJztcbiAgICAgICAgcG9pbnREYXRhLnNwaWtlRGlzdGFuY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgIHBvaW50RGF0YVtzcGlrZVBvc0F0dHJdID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIC8vIG5vIGhvdmVydGVtcGxhdGUgc3VwcG9ydCB5ZXRcbiAgICAgICAgcG9pbnREYXRhMi5ob3ZlcnRlbXBsYXRlID0gZmFsc2U7XG5cbiAgICAgICAgY2xvc2VCb3hEYXRhLnB1c2gocG9pbnREYXRhMik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsb3NlQm94RGF0YTtcbn1cblxuZnVuY3Rpb24gaG92ZXJPblBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHhhID0gcG9pbnREYXRhLnhhO1xuICAgIHZhciB5YSA9IHBvaW50RGF0YS55YTtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgeFB4ID0geGEuYzJwKHh2YWwpO1xuICAgIHZhciB5UHggPSB5YS5jMnAoeXZhbCk7XG4gICAgdmFyIGNsb3NlUHREYXRhO1xuXG4gICAgdmFyIGR4ID0gZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgdmFyIHJhZCA9IE1hdGgubWF4KDMsIGRpLm1yYyB8fCAwKTtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KE1hdGguYWJzKHhhLmMycChkaS54KSAtIHhQeCkgLSByYWQsIDEgLSAzIC8gcmFkKTtcbiAgICB9O1xuICAgIHZhciBkeSA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgIHZhciByYWQgPSBNYXRoLm1heCgzLCBkaS5tcmMgfHwgMCk7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChNYXRoLmFicyh5YS5jMnAoZGkueSkgLSB5UHgpIC0gcmFkLCAxIC0gMyAvIHJhZCk7XG4gICAgfTtcbiAgICB2YXIgZGlzdGZuID0gRngucXVhZHJhdHVyZShkeCwgZHkpO1xuXG4gICAgLy8gc2hvdyBvbmUgcG9pbnQgcGVyIHRyYWNlXG4gICAgdmFyIGlqQ2xvc2VzdCA9IGZhbHNlO1xuICAgIHZhciBkaSwgcHQ7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZGkgPSBjZFtpXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgKGRpLnB0cyB8fCBbXSkubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHB0ID0gZGkucHRzW2pdO1xuXG4gICAgICAgICAgICB2YXIgbmV3RGlzdGFuY2UgPSBkaXN0Zm4ocHQpO1xuICAgICAgICAgICAgaWYobmV3RGlzdGFuY2UgPD0gcG9pbnREYXRhLmRpc3RhbmNlKSB7XG4gICAgICAgICAgICAgICAgcG9pbnREYXRhLmRpc3RhbmNlID0gbmV3RGlzdGFuY2U7XG4gICAgICAgICAgICAgICAgaWpDbG9zZXN0ID0gW2ksIGpdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoIWlqQ2xvc2VzdCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZGkgPSBjZFtpakNsb3Nlc3RbMF1dO1xuICAgIHB0ID0gZGkucHRzW2lqQ2xvc2VzdFsxXV07XG5cbiAgICB2YXIgeGMgPSB4YS5jMnAocHQueCwgdHJ1ZSk7XG4gICAgdmFyIHljID0geWEuYzJwKHB0LnksIHRydWUpO1xuICAgIHZhciByYWQgPSBwdC5tcmMgfHwgMTtcblxuICAgIGNsb3NlUHREYXRhID0gTGliLmV4dGVuZEZsYXQoe30sIHBvaW50RGF0YSwge1xuICAgICAgICAvLyBjb3JyZXNwb25kcyB0byBpbmRleCBpbiB4L3kgaW5wdXQgZGF0YSBhcnJheVxuICAgICAgICBpbmRleDogcHQuaSxcbiAgICAgICAgY29sb3I6ICh0cmFjZS5tYXJrZXIgfHwge30pLmNvbG9yLFxuICAgICAgICBuYW1lOiB0cmFjZS5uYW1lLFxuICAgICAgICB4MDogeGMgLSByYWQsXG4gICAgICAgIHgxOiB4YyArIHJhZCxcbiAgICAgICAgeTA6IHljIC0gcmFkLFxuICAgICAgICB5MTogeWMgKyByYWQsXG4gICAgICAgIHNwaWtlRGlzdGFuY2U6IHBvaW50RGF0YS5kaXN0YW5jZSxcbiAgICAgICAgaG92ZXJ0ZW1wbGF0ZTogdHJhY2UuaG92ZXJ0ZW1wbGF0ZVxuICAgIH0pO1xuXG4gICAgdmFyIHBhO1xuICAgIGlmKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgcGEgPSB5YTtcbiAgICAgICAgY2xvc2VQdERhdGEueExhYmVsVmFsID0gcHQueDtcbiAgICAgICAgY2xvc2VQdERhdGEueUxhYmVsVmFsID0gZGkucG9zO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHBhID0geGE7XG4gICAgICAgIGNsb3NlUHREYXRhLnhMYWJlbFZhbCA9IGRpLnBvcztcbiAgICAgICAgY2xvc2VQdERhdGEueUxhYmVsVmFsID0gcHQueTtcbiAgICB9XG5cbiAgICB2YXIgcExldHRlciA9IHBhLl9pZC5jaGFyQXQoMCk7XG4gICAgY2xvc2VQdERhdGFbcExldHRlciArICdTcGlrZSddID0gcGEuYzJwKGRpLnBvcywgdHJ1ZSk7XG5cbiAgICBmaWxsVGV4dChwdCwgdHJhY2UsIGNsb3NlUHREYXRhKTtcblxuICAgIHJldHVybiBjbG9zZVB0RGF0YTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaG92ZXJQb2ludHM6IGhvdmVyUG9pbnRzLFxuICAgIGhvdmVyT25Cb3hlczogaG92ZXJPbkJveGVzLFxuICAgIGhvdmVyT25Qb2ludHM6IGhvdmVyT25Qb2ludHNcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZnhcIjo2MzIsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2N31dLDg4NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIGxheW91dEF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLnN1cHBseURlZmF1bHRzLFxuICAgIGNyb3NzVHJhY2VEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLmNyb3NzVHJhY2VEZWZhdWx0cyxcbiAgICBzdXBwbHlMYXlvdXREZWZhdWx0czogX2RlcmVxXygnLi9sYXlvdXRfZGVmYXVsdHMnKS5zdXBwbHlMYXlvdXREZWZhdWx0cyxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBjcm9zc1RyYWNlQ2FsYzogX2RlcmVxXygnLi9jcm9zc190cmFjZV9jYWxjJykuY3Jvc3NUcmFjZUNhbGMsXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JykucGxvdCxcbiAgICBzdHlsZTogX2RlcmVxXygnLi9zdHlsZScpLnN0eWxlLFxuICAgIHN0eWxlT25TZWxlY3Q6IF9kZXJlcV8oJy4vc3R5bGUnKS5zdHlsZU9uU2VsZWN0LFxuICAgIGhvdmVyUG9pbnRzOiBfZGVyZXFfKCcuL2hvdmVyJykuaG92ZXJQb2ludHMsXG4gICAgZXZlbnREYXRhOiBfZGVyZXFfKCcuL2V2ZW50X2RhdGEnKSxcbiAgICBzZWxlY3RQb2ludHM6IF9kZXJlcV8oJy4vc2VsZWN0JyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdib3gnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKSxcbiAgICBjYXRlZ29yaWVzOiBbJ2NhcnRlc2lhbicsICdzdmcnLCAnc3ltYm9scycsICdvcmllbnRlZCcsICdib3gtdmlvbGluJywgJ3Nob3dMZWdlbmQnLCAnYm94TGF5b3V0JywgJ3pvb21TY2FsZSddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW5cIjo3NzgsXCIuL2F0dHJpYnV0ZXNcIjo4ODAsXCIuL2NhbGNcIjo4ODEsXCIuL2Nyb3NzX3RyYWNlX2NhbGNcIjo4ODIsXCIuL2RlZmF1bHRzXCI6ODgzLFwiLi9ldmVudF9kYXRhXCI6ODg0LFwiLi9ob3ZlclwiOjg4NSxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo4ODcsXCIuL2xheW91dF9kZWZhdWx0c1wiOjg4OCxcIi4vcGxvdFwiOjg4OSxcIi4vc2VsZWN0XCI6ODkwLFwiLi9zdHlsZVwiOjg5MX1dLDg4NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYm94bW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydncm91cCcsICdvdmVybGF5J10sXG4gICAgICAgIGRmbHQ6ICdvdmVybGF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYm94Z2FwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMC4zLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBib3hncm91cGdhcDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDAuMyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se31dLDg4ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxuZnVuY3Rpb24gX3N1cHBseShsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSwgY29lcmNlLCB0cmFjZVR5cGUpIHtcbiAgICB2YXIgY2F0ZWdvcnkgPSB0cmFjZVR5cGUgKyAnTGF5b3V0JztcbiAgICB2YXIgaGFzVHJhY2VUeXBlID0gZmFsc2U7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZnVsbERhdGFbaV07XG5cbiAgICAgICAgaWYoUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgY2F0ZWdvcnkpKSB7XG4gICAgICAgICAgICBoYXNUcmFjZVR5cGUgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYoIWhhc1RyYWNlVHlwZSkgcmV0dXJuO1xuXG4gICAgY29lcmNlKHRyYWNlVHlwZSArICdtb2RlJyk7XG4gICAgY29lcmNlKHRyYWNlVHlwZSArICdnYXAnKTtcbiAgICBjb2VyY2UodHJhY2VUeXBlICsgJ2dyb3VwZ2FwJyk7XG59XG5cbmZ1bmN0aW9uIHN1cHBseUxheW91dERlZmF1bHRzKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGF5b3V0SW4sIGxheW91dE91dCwgbGF5b3V0QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuICAgIF9zdXBwbHkobGF5b3V0SW4sIGxheW91dE91dCwgZnVsbERhdGEsIGNvZXJjZSwgJ2JveCcpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBzdXBwbHlMYXlvdXREZWZhdWx0czogc3VwcGx5TGF5b3V0RGVmYXVsdHMsXG4gICAgX3N1cHBseTogX3N1cHBseVxufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo4ODd9XSw4ODk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xuXG4vLyBjb25zdGFudHMgZm9yIGR5bmFtaWMgaml0dGVyIChpZSBsZXNzIGppdHRlciBmb3Igc3BhcnNlciBwb2ludHMpXG52YXIgSklUVEVSQ09VTlQgPSA1OyAvLyBwb2ludHMgZWl0aGVyIHNpZGUgb2YgdGhpcyB0byBpbmNsdWRlXG52YXIgSklUVEVSU1BSRUFEID0gMC4wMTsgLy8gZnJhY3Rpb24gb2YgSVFSIHRvIGNvdW50IGFzIFwiZGVuc2VcIlxuXG5mdW5jdGlvbiBwbG90KGdkLCBwbG90aW5mbywgY2Rib3gsIGJveExheWVyKSB7XG4gICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICBMaWIubWFrZVRyYWNlR3JvdXBzKGJveExheWVyLCBjZGJveCwgJ3RyYWNlIGJveGVzJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0ID0gY2QwLnQ7XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICAvLyB3aGlza2VyIHdpZHRoXG4gICAgICAgIHQud2RQb3MgPSB0LmJkUG9zICogdHJhY2Uud2hpc2tlcndpZHRoO1xuXG4gICAgICAgIGlmKHRyYWNlLnZpc2libGUgIT09IHRydWUgfHwgdC5lbXB0eSkge1xuICAgICAgICAgICAgcGxvdEdyb3VwLnJlbW92ZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHBvc0F4aXMsIHZhbEF4aXM7XG5cbiAgICAgICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICAgICAgcG9zQXhpcyA9IHlhO1xuICAgICAgICAgICAgdmFsQXhpcyA9IHhhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9zQXhpcyA9IHhhO1xuICAgICAgICAgICAgdmFsQXhpcyA9IHlhO1xuICAgICAgICB9XG5cbiAgICAgICAgcGxvdEJveEFuZFdoaXNrZXJzKHBsb3RHcm91cCwge3BvczogcG9zQXhpcywgdmFsOiB2YWxBeGlzfSwgdHJhY2UsIHQpO1xuICAgICAgICBwbG90UG9pbnRzKHBsb3RHcm91cCwge3g6IHhhLCB5OiB5YX0sIHRyYWNlLCB0KTtcbiAgICAgICAgcGxvdEJveE1lYW4ocGxvdEdyb3VwLCB7cG9zOiBwb3NBeGlzLCB2YWw6IHZhbEF4aXN9LCB0cmFjZSwgdCk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHBsb3RCb3hBbmRXaGlza2VycyhzZWwsIGF4ZXMsIHRyYWNlLCB0KSB7XG4gICAgdmFyIHBvc0F4aXMgPSBheGVzLnBvcztcbiAgICB2YXIgdmFsQXhpcyA9IGF4ZXMudmFsO1xuICAgIHZhciBiUG9zID0gdC5iUG9zO1xuICAgIHZhciB3ZFBvcyA9IHQud2RQb3MgfHwgMDtcbiAgICB2YXIgYlBvc1B4T2Zmc2V0ID0gdC5iUG9zUHhPZmZzZXQgfHwgMDtcbiAgICB2YXIgd2hpc2tlcldpZHRoID0gdHJhY2Uud2hpc2tlcndpZHRoIHx8IDA7XG4gICAgdmFyIG5vdGNoZWQgPSB0cmFjZS5ub3RjaGVkIHx8IGZhbHNlO1xuICAgIHZhciBudyA9IG5vdGNoZWQgPyAxIC0gMiAqIHRyYWNlLm5vdGNod2lkdGggOiAxO1xuXG4gICAgLy8gdG8gc3VwcG9ydCBmb3Igb25lLXNpZGVkIGJveFxuICAgIHZhciBiZFBvczA7XG4gICAgdmFyIGJkUG9zMTtcbiAgICBpZihBcnJheS5pc0FycmF5KHQuYmRQb3MpKSB7XG4gICAgICAgIGJkUG9zMCA9IHQuYmRQb3NbMF07XG4gICAgICAgIGJkUG9zMSA9IHQuYmRQb3NbMV07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYmRQb3MwID0gdC5iZFBvcztcbiAgICAgICAgYmRQb3MxID0gdC5iZFBvcztcbiAgICB9XG5cbiAgICB2YXIgcGF0aHMgPSBzZWwuc2VsZWN0QWxsKCdwYXRoLmJveCcpLmRhdGEoKFxuICAgICAgICB0cmFjZS50eXBlICE9PSAndmlvbGluJyB8fFxuICAgICAgICB0cmFjZS5ib3gudmlzaWJsZVxuICAgICkgPyBMaWIuaWRlbnRpdHkgOiBbXSk7XG5cbiAgICBwYXRocy5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnYm94Jyk7XG5cbiAgICBwYXRocy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBwYXRocy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgaWYoZC5lbXB0eSkgcmV0dXJuICdNMCwwWic7XG5cbiAgICAgICAgdmFyIHBvcyA9IGQucG9zO1xuICAgICAgICB2YXIgcG9zYyA9IHBvc0F4aXMuYzJwKHBvcyArIGJQb3MsIHRydWUpICsgYlBvc1B4T2Zmc2V0O1xuICAgICAgICB2YXIgcG9zMCA9IHBvc0F4aXMuYzJwKHBvcyArIGJQb3MgLSBiZFBvczAsIHRydWUpICsgYlBvc1B4T2Zmc2V0O1xuICAgICAgICB2YXIgcG9zMSA9IHBvc0F4aXMuYzJwKHBvcyArIGJQb3MgKyBiZFBvczEsIHRydWUpICsgYlBvc1B4T2Zmc2V0O1xuICAgICAgICB2YXIgcG9zdzAgPSBwb3NBeGlzLmMycChwb3MgKyBiUG9zIC0gd2RQb3MsIHRydWUpICsgYlBvc1B4T2Zmc2V0O1xuICAgICAgICB2YXIgcG9zdzEgPSBwb3NBeGlzLmMycChwb3MgKyBiUG9zICsgd2RQb3MsIHRydWUpICsgYlBvc1B4T2Zmc2V0O1xuICAgICAgICB2YXIgcG9zbTAgPSBwb3NBeGlzLmMycChwb3MgKyBiUG9zIC0gYmRQb3MwICogbncsIHRydWUpICsgYlBvc1B4T2Zmc2V0O1xuICAgICAgICB2YXIgcG9zbTEgPSBwb3NBeGlzLmMycChwb3MgKyBiUG9zICsgYmRQb3MxICogbncsIHRydWUpICsgYlBvc1B4T2Zmc2V0O1xuICAgICAgICB2YXIgcTEgPSB2YWxBeGlzLmMycChkLnExLCB0cnVlKTtcbiAgICAgICAgdmFyIHEzID0gdmFsQXhpcy5jMnAoZC5xMywgdHJ1ZSk7XG4gICAgICAgIC8vIG1ha2Ugc3VyZSBtZWRpYW4gaXNuJ3QgaWRlbnRpY2FsIHRvIGVpdGhlciBvZiB0aGVcbiAgICAgICAgLy8gcXVhcnRpbGVzLCBzbyB3ZSBjYW4gc2VlIGl0XG4gICAgICAgIHZhciBtID0gTGliLmNvbnN0cmFpbihcbiAgICAgICAgICAgIHZhbEF4aXMuYzJwKGQubWVkLCB0cnVlKSxcbiAgICAgICAgICAgIE1hdGgubWluKHExLCBxMykgKyAxLCBNYXRoLm1heChxMSwgcTMpIC0gMVxuICAgICAgICApO1xuXG4gICAgICAgIC8vIGZvciBjb21wYXRpYmlsaXR5IHdpdGggYm94LCB2aW9saW4sIGFuZCBjYW5kbGVzdGlja1xuICAgICAgICAvLyBwZXJoYXBzIHdlIHNob3VsZCBwdXQgdGhpcyBpbnRvIGNkMC50IGluc3RlYWQgc28gaXQncyBtb3JlIGV4cGxpY2l0LFxuICAgICAgICAvLyBidXQgd2hhdCB3ZSBoYXZlIG5vdyBpczpcbiAgICAgICAgLy8gLSBib3ggYWx3YXlzIGhhcyBkLmxmLCBidXQgYm94cG9pbnRzIGNhbiBiZSBhbnl0aGluZ1xuICAgICAgICAvLyAtIHZpb2xpbiBoYXMgZC5sZiBhbmQgc2hvdWxkIGFsd2F5cyB1c2UgaXQgKGJveHBvaW50cyBpcyB1bmRlZmluZWQpXG4gICAgICAgIC8vIC0gY2FuZGxlc3RpY2sgaGFzIG9ubHkgbWluL21heFxuICAgICAgICB2YXIgdXNlRXh0cmVtZXMgPSAoZC5sZiA9PT0gdW5kZWZpbmVkKSB8fCAodHJhY2UuYm94cG9pbnRzID09PSBmYWxzZSk7XG4gICAgICAgIHZhciBsZiA9IHZhbEF4aXMuYzJwKHVzZUV4dHJlbWVzID8gZC5taW4gOiBkLmxmLCB0cnVlKTtcbiAgICAgICAgdmFyIHVmID0gdmFsQXhpcy5jMnAodXNlRXh0cmVtZXMgPyBkLm1heCA6IGQudWYsIHRydWUpO1xuICAgICAgICB2YXIgbG4gPSB2YWxBeGlzLmMycChkLmxuLCB0cnVlKTtcbiAgICAgICAgdmFyIHVuID0gdmFsQXhpcy5jMnAoZC51biwgdHJ1ZSk7XG5cbiAgICAgICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ2QnLFxuICAgICAgICAgICAgICAgICdNJyArIG0gKyAnLCcgKyBwb3NtMCArICdWJyArIHBvc20xICsgLy8gbWVkaWFuIGxpbmVcbiAgICAgICAgICAgICAgICAnTScgKyBxMSArICcsJyArIHBvczAgKyAnVicgKyBwb3MxICsgLy8gbGVmdCBlZGdlXG4gICAgICAgICAgICAgICAgKG5vdGNoZWQgPyAnSCcgKyBsbiArICdMJyArIG0gKyAnLCcgKyBwb3NtMSArICdMJyArIHVuICsgJywnICsgcG9zMSA6ICcnKSArIC8vIHRvcCBub3RjaGVkIGVkZ2VcbiAgICAgICAgICAgICAgICAnSCcgKyBxMyArIC8vIGVuZCBvZiB0aGUgdG9wIGVkZ2VcbiAgICAgICAgICAgICAgICAnVicgKyBwb3MwICsgLy8gcmlnaHQgZWRnZVxuICAgICAgICAgICAgICAgIChub3RjaGVkID8gJ0gnICsgdW4gKyAnTCcgKyBtICsgJywnICsgcG9zbTAgKyAnTCcgKyBsbiArICcsJyArIHBvczAgOiAnJykgKyAvLyBib3R0b20gbm90Y2hlZCBlZGdlXG4gICAgICAgICAgICAgICAgJ1onICsgLy8gZW5kIG9mIHRoZSBib3hcbiAgICAgICAgICAgICAgICAnTScgKyBxMSArICcsJyArIHBvc2MgKyAnSCcgKyBsZiArICdNJyArIHEzICsgJywnICsgcG9zYyArICdIJyArIHVmICsgLy8gd2hpc2tlcnNcbiAgICAgICAgICAgICAgICAoKHdoaXNrZXJXaWR0aCA9PT0gMCkgPyAnJyA6IC8vIHdoaXNrZXIgY2Fwc1xuICAgICAgICAgICAgICAgICAgICAnTScgKyBsZiArICcsJyArIHBvc3cwICsgJ1YnICsgcG9zdzEgKyAnTScgKyB1ZiArICcsJyArIHBvc3cwICsgJ1YnICsgcG9zdzEpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5hdHRyKCdkJyxcbiAgICAgICAgICAgICAgICAnTScgKyBwb3NtMCArICcsJyArIG0gKyAnSCcgKyBwb3NtMSArIC8vIG1lZGlhbiBsaW5lXG4gICAgICAgICAgICAgICAgJ00nICsgcG9zMCArICcsJyArIHExICsgJ0gnICsgcG9zMSArIC8vIHRvcCBvZiB0aGUgYm94XG4gICAgICAgICAgICAgICAgKG5vdGNoZWQgPyAnVicgKyBsbiArICdMJyArIHBvc20xICsgJywnICsgbSArICdMJyArIHBvczEgKyAnLCcgKyB1biA6ICcnKSArIC8vIG5vdGNoZWQgcmlnaHQgZWRnZVxuICAgICAgICAgICAgICAgICdWJyArIHEzICsgLy8gZW5kIG9mIHRoZSByaWdodCBlZGdlXG4gICAgICAgICAgICAgICAgJ0gnICsgcG9zMCArIC8vIGJvdHRvbSBvZiB0aGUgYm94XG4gICAgICAgICAgICAgICAgKG5vdGNoZWQgPyAnVicgKyB1biArICdMJyArIHBvc20wICsgJywnICsgbSArICdMJyArIHBvczAgKyAnLCcgKyBsbiA6ICcnKSArIC8vIG5vdGNoZWQgbGVmdCBlZGdlXG4gICAgICAgICAgICAgICAgJ1onICsgLy8gZW5kIG9mIHRoZSBib3hcbiAgICAgICAgICAgICAgICAnTScgKyBwb3NjICsgJywnICsgcTEgKyAnVicgKyBsZiArICdNJyArIHBvc2MgKyAnLCcgKyBxMyArICdWJyArIHVmICsgLy8gd2hpc2tlcnNcbiAgICAgICAgICAgICAgICAoKHdoaXNrZXJXaWR0aCA9PT0gMCkgPyAnJyA6IC8vIHdoaXNrZXIgY2Fwc1xuICAgICAgICAgICAgICAgICAgICAnTScgKyBwb3N3MCArICcsJyArIGxmICsgJ0gnICsgcG9zdzEgKyAnTScgKyBwb3N3MCArICcsJyArIHVmICsgJ0gnICsgcG9zdzEpKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBwbG90UG9pbnRzKHNlbCwgYXhlcywgdHJhY2UsIHQpIHtcbiAgICB2YXIgeGEgPSBheGVzLng7XG4gICAgdmFyIHlhID0gYXhlcy55O1xuICAgIHZhciBiZFBvcyA9IHQuYmRQb3M7XG4gICAgdmFyIGJQb3MgPSB0LmJQb3M7XG5cbiAgICAvLyB0byBzdXBwb3J0IHZpb2xpbiBwb2ludHNcbiAgICB2YXIgbW9kZSA9IHRyYWNlLmJveHBvaW50cyB8fCB0cmFjZS5wb2ludHM7XG5cbiAgICAvLyByZXBlYXRhYmxlIHBzZXVkby1yYW5kb20gbnVtYmVyIGdlbmVyYXRvclxuICAgIExpYi5zZWVkUHNldWRvUmFuZG9tKCk7XG5cbiAgICAvLyBzaW5jZSBib3ggcGxvdCBwb2ludHMgZ2V0IGFuIGV4dHJhIGxldmVsIG9mIG5lc3RpbmcsIGVhY2hcbiAgICAvLyBib3ggbmVlZHMgdGhlIHRyYWNlIHN0eWxpbmcgaW5mb1xuICAgIHZhciBmbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgZC5mb3JFYWNoKGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgIHYudCA9IHQ7XG4gICAgICAgICAgICB2LnRyYWNlID0gdHJhY2U7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZDtcbiAgICB9O1xuXG4gICAgdmFyIGdQb2ludHMgPSBzZWwuc2VsZWN0QWxsKCdnLnBvaW50cycpXG4gICAgICAgIC5kYXRhKG1vZGUgPyBmbiA6IFtdKTtcblxuICAgIGdQb2ludHMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAncG9pbnRzJyk7XG5cbiAgICBnUG9pbnRzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIHZhciBwYXRocyA9IGdQb2ludHMuc2VsZWN0QWxsKCdwYXRoJylcbiAgICAgICAgLmRhdGEoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGk7XG4gICAgICAgICAgICB2YXIgcHRzID0gZC5wdHMyO1xuXG4gICAgICAgICAgICAvLyBub3JtYWxseSB1c2UgSVFSLCBidXQgaWYgdGhpcyBpcyAwIG9yIHRvbyBzbWFsbCwgdXNlIG1heC1taW5cbiAgICAgICAgICAgIHZhciB0eXBpY2FsU3ByZWFkID0gTWF0aC5tYXgoKGQubWF4IC0gZC5taW4pIC8gMTAsIGQucTMgLSBkLnExKTtcbiAgICAgICAgICAgIHZhciBtaW5TcHJlYWQgPSB0eXBpY2FsU3ByZWFkICogMWUtOTtcbiAgICAgICAgICAgIHZhciBzcHJlYWRMaW1pdCA9IHR5cGljYWxTcHJlYWQgKiBKSVRURVJTUFJFQUQ7XG4gICAgICAgICAgICB2YXIgaml0dGVyRmFjdG9ycyA9IFtdO1xuICAgICAgICAgICAgdmFyIG1heEppdHRlckZhY3RvciA9IDA7XG4gICAgICAgICAgICB2YXIgbmV3Sml0dGVyO1xuXG4gICAgICAgICAgICAvLyBkeW5hbWljIGppdHRlclxuICAgICAgICAgICAgaWYodHJhY2Uuaml0dGVyKSB7XG4gICAgICAgICAgICAgICAgaWYodHlwaWNhbFNwcmVhZCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBlZGdlIGNhc2Ugb2Ygbm8gc3ByZWFkIGF0IGFsbDogZmFsbCBiYWNrIHRvIG1heCBqaXR0ZXJcbiAgICAgICAgICAgICAgICAgICAgbWF4Sml0dGVyRmFjdG9yID0gMTtcbiAgICAgICAgICAgICAgICAgICAgaml0dGVyRmFjdG9ycyA9IG5ldyBBcnJheShwdHMubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXJGYWN0b3JzW2ldID0gMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGkwID0gTWF0aC5tYXgoMCwgaSAtIEpJVFRFUkNPVU5UKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwbWluID0gcHRzW2kwXS52O1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGkxID0gTWF0aC5taW4ocHRzLmxlbmd0aCAtIDEsIGkgKyBKSVRURVJDT1VOVCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcG1heCA9IHB0c1tpMV0udjtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYobW9kZSAhPT0gJ2FsbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihwdHNbaV0udiA8IGQubGYpIHBtYXggPSBNYXRoLm1pbihwbWF4LCBkLmxmKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHBtaW4gPSBNYXRoLm1heChwbWluLCBkLnVmKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGppdHRlckZhY3RvciA9IE1hdGguc3FydChzcHJlYWRMaW1pdCAqIChpMSAtIGkwKSAvIChwbWF4IC0gcG1pbiArIG1pblNwcmVhZCkpIHx8IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXJGYWN0b3IgPSBMaWIuY29uc3RyYWluKE1hdGguYWJzKGppdHRlckZhY3RvciksIDAsIDEpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXJGYWN0b3JzLnB1c2goaml0dGVyRmFjdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEppdHRlckZhY3RvciA9IE1hdGgubWF4KGppdHRlckZhY3RvciwgbWF4Sml0dGVyRmFjdG9yKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBuZXdKaXR0ZXIgPSB0cmFjZS5qaXR0ZXIgKiAyIC8gKG1heEppdHRlckZhY3RvciB8fCAxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gZmlsbHMgaW4gJ3gnIGFuZCAneScgaW4gY2FsY2RhdGEgJ3B0cycgaXRlbVxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgcHRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHB0ID0gcHRzW2ldO1xuICAgICAgICAgICAgICAgIHZhciB2ID0gcHQudjtcblxuICAgICAgICAgICAgICAgIHZhciBqaXR0ZXJPZmZzZXQgPSB0cmFjZS5qaXR0ZXIgP1xuICAgICAgICAgICAgICAgICAgICAobmV3Sml0dGVyICogaml0dGVyRmFjdG9yc1tpXSAqIChMaWIucHNldWRvUmFuZG9tKCkgLSAwLjUpKSA6XG4gICAgICAgICAgICAgICAgICAgIDA7XG5cbiAgICAgICAgICAgICAgICB2YXIgcG9zUHggPSBkLnBvcyArIGJQb3MgKyBiZFBvcyAqICh0cmFjZS5wb2ludHBvcyArIGppdHRlck9mZnNldCk7XG5cbiAgICAgICAgICAgICAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICAgICAgICAgIHB0LnkgPSBwb3NQeDtcbiAgICAgICAgICAgICAgICAgICAgcHQueCA9IHY7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcHQueCA9IHBvc1B4O1xuICAgICAgICAgICAgICAgICAgICBwdC55ID0gdjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyB0YWcgc3VzcGVjdGVkIG91dGxpZXJzXG4gICAgICAgICAgICAgICAgaWYobW9kZSA9PT0gJ3N1c3BlY3RlZG91dGxpZXJzJyAmJiB2IDwgZC51byAmJiB2ID4gZC5sbykge1xuICAgICAgICAgICAgICAgICAgICBwdC5zbyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcHRzO1xuICAgICAgICB9KTtcblxuICAgIHBhdGhzLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgLmNsYXNzZWQoJ3BvaW50JywgdHJ1ZSk7XG5cbiAgICBwYXRocy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBwYXRocy5jYWxsKERyYXdpbmcudHJhbnNsYXRlUG9pbnRzLCB4YSwgeWEpO1xufVxuXG5mdW5jdGlvbiBwbG90Qm94TWVhbihzZWwsIGF4ZXMsIHRyYWNlLCB0KSB7XG4gICAgdmFyIHBvc0F4aXMgPSBheGVzLnBvcztcbiAgICB2YXIgdmFsQXhpcyA9IGF4ZXMudmFsO1xuICAgIHZhciBiUG9zID0gdC5iUG9zO1xuICAgIHZhciBiUG9zUHhPZmZzZXQgPSB0LmJQb3NQeE9mZnNldCB8fCAwO1xuXG4gICAgLy8gdG8gc3VwcG9ydCB2aW9saW4gbWVhbiBsaW5lc1xuICAgIHZhciBtb2RlID0gdHJhY2UuYm94bWVhbiB8fCAodHJhY2UubWVhbmxpbmUgfHwge30pLnZpc2libGU7XG5cbiAgICAvLyB0byBzdXBwb3J0IGZvciBvbmUtc2lkZWQgYm94XG4gICAgdmFyIGJkUG9zMDtcbiAgICB2YXIgYmRQb3MxO1xuICAgIGlmKEFycmF5LmlzQXJyYXkodC5iZFBvcykpIHtcbiAgICAgICAgYmRQb3MwID0gdC5iZFBvc1swXTtcbiAgICAgICAgYmRQb3MxID0gdC5iZFBvc1sxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBiZFBvczAgPSB0LmJkUG9zO1xuICAgICAgICBiZFBvczEgPSB0LmJkUG9zO1xuICAgIH1cblxuICAgIHZhciBwYXRocyA9IHNlbC5zZWxlY3RBbGwoJ3BhdGgubWVhbicpLmRhdGEoKFxuICAgICAgICAodHJhY2UudHlwZSA9PT0gJ2JveCcgJiYgdHJhY2UuYm94bWVhbikgfHxcbiAgICAgICAgKHRyYWNlLnR5cGUgPT09ICd2aW9saW4nICYmIHRyYWNlLmJveC52aXNpYmxlICYmIHRyYWNlLm1lYW5saW5lLnZpc2libGUpXG4gICAgKSA/IExpYi5pZGVudGl0eSA6IFtdKTtcblxuICAgIHBhdGhzLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ21lYW4nKVxuICAgICAgICAuc3R5bGUoe1xuICAgICAgICAgICAgZmlsbDogJ25vbmUnLFxuICAgICAgICAgICAgJ3ZlY3Rvci1lZmZlY3QnOiAnbm9uLXNjYWxpbmctc3Ryb2tlJ1xuICAgICAgICB9KTtcblxuICAgIHBhdGhzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIHBhdGhzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgcG9zYyA9IHBvc0F4aXMuYzJwKGQucG9zICsgYlBvcywgdHJ1ZSkgKyBiUG9zUHhPZmZzZXQ7XG4gICAgICAgIHZhciBwb3MwID0gcG9zQXhpcy5jMnAoZC5wb3MgKyBiUG9zIC0gYmRQb3MwLCB0cnVlKSArIGJQb3NQeE9mZnNldDtcbiAgICAgICAgdmFyIHBvczEgPSBwb3NBeGlzLmMycChkLnBvcyArIGJQb3MgKyBiZFBvczEsIHRydWUpICsgYlBvc1B4T2Zmc2V0O1xuICAgICAgICB2YXIgbSA9IHZhbEF4aXMuYzJwKGQubWVhbiwgdHJ1ZSk7XG4gICAgICAgIHZhciBzbCA9IHZhbEF4aXMuYzJwKGQubWVhbiAtIGQuc2QsIHRydWUpO1xuICAgICAgICB2YXIgc2ggPSB2YWxBeGlzLmMycChkLm1lYW4gKyBkLnNkLCB0cnVlKTtcblxuICAgICAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuYXR0cignZCcsXG4gICAgICAgICAgICAgICAgJ00nICsgbSArICcsJyArIHBvczAgKyAnVicgKyBwb3MxICtcbiAgICAgICAgICAgICAgICAobW9kZSA9PT0gJ3NkJyA/XG4gICAgICAgICAgICAgICAgICAgICdtMCwwTCcgKyBzbCArICcsJyArIHBvc2MgKyAnTCcgKyBtICsgJywnICsgcG9zMCArICdMJyArIHNoICsgJywnICsgcG9zYyArICdaJyA6XG4gICAgICAgICAgICAgICAgICAgICcnKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5hdHRyKCdkJyxcbiAgICAgICAgICAgICAgICAnTScgKyBwb3MwICsgJywnICsgbSArICdIJyArIHBvczEgK1xuICAgICAgICAgICAgICAgIChtb2RlID09PSAnc2QnID9cbiAgICAgICAgICAgICAgICAgICAgJ20wLDBMJyArIHBvc2MgKyAnLCcgKyBzbCArICdMJyArIHBvczAgKyAnLCcgKyBtICsgJ0wnICsgcG9zYyArICcsJyArIHNoICsgJ1onIDpcbiAgICAgICAgICAgICAgICAgICAgJycpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHBsb3Q6IHBsb3QsXG4gICAgcGxvdEJveEFuZFdoaXNrZXJzOiBwbG90Qm94QW5kV2hpc2tlcnMsXG4gICAgcGxvdFBvaW50czogcGxvdFBvaW50cyxcbiAgICBwbG90Qm94TWVhbjogcGxvdEJveE1lYW5cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vbGliXCI6NzE5LFwiZDNcIjoxNjN9XSw4OTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBzZWxlY3Rpb25UZXN0ZXIpIHtcbiAgICB2YXIgY2QgPSBzZWFyY2hJbmZvLmNkO1xuICAgIHZhciB4YSA9IHNlYXJjaEluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gc2VhcmNoSW5mby55YXhpcztcbiAgICB2YXIgc2VsZWN0aW9uID0gW107XG4gICAgdmFyIGksIGo7XG5cbiAgICBpZihzZWxlY3Rpb25UZXN0ZXIgPT09IGZhbHNlKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCAoY2RbaV0ucHRzIHx8IFtdKS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIC8vIGNsZWFyIHNlbGVjdGlvblxuICAgICAgICAgICAgICAgIGNkW2ldLnB0c1tqXS5zZWxlY3RlZCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgKGNkW2ldLnB0cyB8fCBbXSkubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcHQgPSBjZFtpXS5wdHNbal07XG4gICAgICAgICAgICAgICAgdmFyIHggPSB4YS5jMnAocHQueCk7XG4gICAgICAgICAgICAgICAgdmFyIHkgPSB5YS5jMnAocHQueSk7XG5cbiAgICAgICAgICAgICAgICBpZihzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3gsIHldLCBudWxsLCBwdC5pLCBzZWFyY2hJbmZvKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb24ucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogcHQuaSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IHhhLmMyZChwdC54KSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHk6IHlhLmMyZChwdC55KVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgcHQuc2VsZWN0ZWQgPSAxO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHB0LnNlbGVjdGVkID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0aW9uO1xufTtcblxufSx7fV0sODkxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG5cbmZ1bmN0aW9uIHN0eWxlKGdkLCBjZCwgc2VsKSB7XG4gICAgdmFyIHMgPSBzZWwgPyBzZWwgOiBkMy5zZWxlY3QoZ2QpLnNlbGVjdEFsbCgnZy50cmFjZS5ib3hlcycpO1xuXG4gICAgcy5zdHlsZSgnb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGRbMF0udHJhY2Uub3BhY2l0eTsgfSk7XG5cbiAgICBzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciB0cmFjZSA9IGRbMF0udHJhY2U7XG4gICAgICAgIHZhciBsaW5lV2lkdGggPSB0cmFjZS5saW5lLndpZHRoO1xuXG4gICAgICAgIGZ1bmN0aW9uIHN0eWxlQm94KGJveFNlbCwgbGluZVdpZHRoLCBsaW5lQ29sb3IsIGZpbGxDb2xvcikge1xuICAgICAgICAgICAgYm94U2VsLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBsaW5lV2lkdGggKyAncHgnKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgbGluZUNvbG9yKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGZpbGxDb2xvcik7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYWxsQm94ZXMgPSBlbC5zZWxlY3RBbGwoJ3BhdGguYm94Jyk7XG5cbiAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2NhbmRsZXN0aWNrJykge1xuICAgICAgICAgICAgYWxsQm94ZXMuZWFjaChmdW5jdGlvbihib3hEYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYoYm94RGF0YS5lbXB0eSkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRoaXNCb3ggPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRhaW5lciA9IHRyYWNlW2JveERhdGEuZGlyXTsgLy8gZGlyID0gJ2luY3JlYXNpbmcnIG9yICdkZWNyZWFzaW5nJ1xuICAgICAgICAgICAgICAgIHN0eWxlQm94KHRoaXNCb3gsIGNvbnRhaW5lci5saW5lLndpZHRoLCBjb250YWluZXIubGluZS5jb2xvciwgY29udGFpbmVyLmZpbGxjb2xvcik7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogY3VzdG9tIHNlbGVjdGlvbiBzdHlsZSBmb3IgY2FuZGxlc3RpY2tzXG4gICAgICAgICAgICAgICAgdGhpc0JveC5zdHlsZSgnb3BhY2l0eScsIHRyYWNlLnNlbGVjdGVkcG9pbnRzICYmICFib3hEYXRhLnNlbGVjdGVkID8gMC4zIDogMSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0eWxlQm94KGFsbEJveGVzLCBsaW5lV2lkdGgsIHRyYWNlLmxpbmUuY29sb3IsIHRyYWNlLmZpbGxjb2xvcik7XG4gICAgICAgICAgICBlbC5zZWxlY3RBbGwoJ3BhdGgubWVhbicpXG4gICAgICAgICAgICAgICAgLnN0eWxlKHtcbiAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS13aWR0aCc6IGxpbmVXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgJ3N0cm9rZS1kYXNoYXJyYXknOiAoMiAqIGxpbmVXaWR0aCkgKyAncHgsJyArIGxpbmVXaWR0aCArICdweCdcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgdHJhY2UubGluZS5jb2xvcik7XG5cbiAgICAgICAgICAgIHZhciBwdHMgPSBlbC5zZWxlY3RBbGwoJ3BhdGgucG9pbnQnKTtcbiAgICAgICAgICAgIERyYXdpbmcucG9pbnRTdHlsZShwdHMsIHRyYWNlLCBnZCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gc3R5bGVPblNlbGVjdChnZCwgY2QsIHNlbCkge1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciBwdHMgPSBzZWwuc2VsZWN0QWxsKCdwYXRoLnBvaW50Jyk7XG5cbiAgICBpZih0cmFjZS5zZWxlY3RlZHBvaW50cykge1xuICAgICAgICBEcmF3aW5nLnNlbGVjdGVkUG9pbnRTdHlsZShwdHMsIHRyYWNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBEcmF3aW5nLnBvaW50U3R5bGUocHRzLCB0cmFjZSwgZ2QpO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3R5bGU6IHN0eWxlLFxuICAgIHN0eWxlT25TZWxlY3Q6IHN0eWxlT25TZWxlY3Rcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcImQzXCI6MTYzfV0sODkyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmV4dGVuZEZsYXQ7XG52YXIgT0hMQ2F0dHJzID0gX2RlcmVxXygnLi4vb2hsYy9hdHRyaWJ1dGVzJyk7XG52YXIgYm94QXR0cnMgPSBfZGVyZXFfKCcuLi9ib3gvYXR0cmlidXRlcycpO1xuXG5mdW5jdGlvbiBkaXJlY3Rpb25BdHRycyhsaW5lQ29sb3JEZWZhdWx0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGluZToge1xuICAgICAgICAgICAgY29sb3I6IGV4dGVuZEZsYXQoe30sIGJveEF0dHJzLmxpbmUuY29sb3IsIHtkZmx0OiBsaW5lQ29sb3JEZWZhdWx0fSksXG4gICAgICAgICAgICB3aWR0aDogYm94QXR0cnMubGluZS53aWR0aCxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgICAgIH0sXG5cbiAgICAgICAgZmlsbGNvbG9yOiBib3hBdHRycy5maWxsY29sb3IsXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgeDogT0hMQ2F0dHJzLngsXG4gICAgb3BlbjogT0hMQ2F0dHJzLm9wZW4sXG4gICAgaGlnaDogT0hMQ2F0dHJzLmhpZ2gsXG4gICAgbG93OiBPSExDYXR0cnMubG93LFxuICAgIGNsb3NlOiBPSExDYXR0cnMuY2xvc2UsXG5cbiAgICBsaW5lOiB7XG4gICAgICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBib3hBdHRycy5saW5lLndpZHRoLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfSxcblxuICAgIGluY3JlYXNpbmc6IGRpcmVjdGlvbkF0dHJzKE9ITENhdHRycy5pbmNyZWFzaW5nLmxpbmUuY29sb3IuZGZsdCksXG5cbiAgICBkZWNyZWFzaW5nOiBkaXJlY3Rpb25BdHRycyhPSExDYXR0cnMuZGVjcmVhc2luZy5saW5lLmNvbG9yLmRmbHQpLFxuXG4gICAgdGV4dDogT0hMQ2F0dHJzLnRleHQsXG4gICAgaG92ZXJ0ZXh0OiBPSExDYXR0cnMuaG92ZXJ0ZXh0LFxuICAgIHdoaXNrZXJ3aWR0aDogZXh0ZW5kRmxhdCh7fSwgYm94QXR0cnMud2hpc2tlcndpZHRoLCB7IGRmbHQ6IDAgfSksXG5cbiAgICBob3ZlcmxhYmVsOiBPSExDYXR0cnMuaG92ZXJsYWJlbCxcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vYm94L2F0dHJpYnV0ZXNcIjo4ODAsXCIuLi9vaGxjL2F0dHJpYnV0ZXNcIjoxMDU4fV0sODkzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xuXG52YXIgY2FsY0NvbW1vbiA9IF9kZXJlcV8oJy4uL29obGMvY2FsYycpLmNhbGNDb21tb247XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueGF4aXMpO1xuICAgIHZhciB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS55YXhpcyk7XG5cbiAgICB2YXIgeCA9IHhhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3gnKTtcblxuICAgIHZhciBjZCA9IGNhbGNDb21tb24oZ2QsIHRyYWNlLCB4LCB5YSwgcHRGdW5jKTtcblxuICAgIGlmKGNkLmxlbmd0aCkge1xuICAgICAgICBMaWIuZXh0ZW5kRmxhdChjZFswXS50LCB7XG4gICAgICAgICAgICBudW06IGZ1bGxMYXlvdXQuX251bUJveGVzLFxuICAgICAgICAgICAgZFBvczogTGliLmRpc3RpbmN0VmFscyh4KS5taW5EaWZmIC8gMixcbiAgICAgICAgICAgIHBvc0xldHRlcjogJ3gnLFxuICAgICAgICAgICAgdmFsTGV0dGVyOiAneScsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGZ1bGxMYXlvdXQuX251bUJveGVzKys7XG4gICAgICAgIHJldHVybiBjZDtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gW3t0OiB7ZW1wdHk6IHRydWV9fV07XG4gICAgfVxufTtcblxuZnVuY3Rpb24gcHRGdW5jKG8sIGgsIGwsIGMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBtaW46IGwsXG4gICAgICAgIHExOiBNYXRoLm1pbihvLCBjKSxcbiAgICAgICAgbWVkOiBjLFxuICAgICAgICBxMzogTWF0aC5tYXgobywgYyksXG4gICAgICAgIG1heDogaCxcbiAgICB9O1xufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vb2hsYy9jYWxjXCI6MTA1OX1dLDg5NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGhhbmRsZU9ITEMgPSBfZGVyZXFfKCcuLi9vaGxjL29obGNfZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsZW4gPSBoYW5kbGVPSExDKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2xpbmUud2lkdGgnKTtcblxuICAgIGhhbmRsZURpcmVjdGlvbih0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCAnaW5jcmVhc2luZycpO1xuICAgIGhhbmRsZURpcmVjdGlvbih0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCAnZGVjcmVhc2luZycpO1xuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ3doaXNrZXJ3aWR0aCcpO1xuXG4gICAgbGF5b3V0Ll9yZXF1ZXN0UmFuZ2VzbGlkZXJbdHJhY2VPdXQueGF4aXNdID0gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZURpcmVjdGlvbih0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBkaXJlY3Rpb24pIHtcbiAgICB2YXIgbGluZUNvbG9yID0gY29lcmNlKGRpcmVjdGlvbiArICcubGluZS5jb2xvcicpO1xuICAgIGNvZXJjZShkaXJlY3Rpb24gKyAnLmxpbmUud2lkdGgnLCB0cmFjZU91dC5saW5lLndpZHRoKTtcbiAgICBjb2VyY2UoZGlyZWN0aW9uICsgJy5maWxsY29sb3InLCBDb2xvci5hZGRPcGFjaXR5KGxpbmVDb2xvciwgMC41KSk7XG59XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL29obGMvb2hsY19kZWZhdWx0c1wiOjEwNjMsXCIuL2F0dHJpYnV0ZXNcIjo4OTJ9XSw4OTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdjYW5kbGVzdGljaycsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnY2FydGVzaWFuJywgJ3N2ZycsICdzaG93TGVnZW5kJywgJ2NhbmRsZXN0aWNrJywgJ2JveExheW91dCddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIGxheW91dEF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4uL2JveC9sYXlvdXRfYXR0cmlidXRlcycpLFxuICAgIHN1cHBseUxheW91dERlZmF1bHRzOiBfZGVyZXFfKCcuLi9ib3gvbGF5b3V0X2RlZmF1bHRzJykuc3VwcGx5TGF5b3V0RGVmYXVsdHMsXG4gICAgY3Jvc3NUcmFjZUNhbGM6IF9kZXJlcV8oJy4uL2JveC9jcm9zc190cmFjZV9jYWxjJykuY3Jvc3NUcmFjZUNhbGMsXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuLi9ib3gvcGxvdCcpLnBsb3QsXG4gICAgbGF5ZXJOYW1lOiAnYm94bGF5ZXInLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuLi9ib3gvc3R5bGUnKS5zdHlsZSxcbiAgICBob3ZlclBvaW50czogX2RlcmVxXygnLi4vb2hsYy9ob3ZlcicpLmhvdmVyUG9pbnRzLFxuICAgIHNlbGVjdFBvaW50czogX2RlcmVxXygnLi4vb2hsYy9zZWxlY3QnKVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW5cIjo3NzgsXCIuLi9ib3gvY3Jvc3NfdHJhY2VfY2FsY1wiOjg4MixcIi4uL2JveC9sYXlvdXRfYXR0cmlidXRlc1wiOjg4NyxcIi4uL2JveC9sYXlvdXRfZGVmYXVsdHNcIjo4ODgsXCIuLi9ib3gvcGxvdFwiOjg4OSxcIi4uL2JveC9zdHlsZVwiOjg5MSxcIi4uL29obGMvaG92ZXJcIjoxMDYxLFwiLi4vb2hsYy9zZWxlY3RcIjoxMDY1LFwiLi9hdHRyaWJ1dGVzXCI6ODkyLFwiLi9jYWxjXCI6ODkzLFwiLi9kZWZhdWx0c1wiOjg5NH1dLDg5NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoYW5kbGVBeGlzRGVmYXVsdHMgPSBfZGVyZXFfKCcuL2F4aXNfZGVmYXVsdHMnKTtcbnZhciBUZW1wbGF0ZSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVBQkRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBmdWxsTGF5b3V0LCBjb2VyY2UsIGRmbHRDb2xvcikge1xuICAgIHZhciBhID0gY29lcmNlKCdhJyk7XG5cbiAgICBpZighYSkge1xuICAgICAgICBjb2VyY2UoJ2RhJyk7XG4gICAgICAgIGNvZXJjZSgnYTAnKTtcbiAgICB9XG5cbiAgICB2YXIgYiA9IGNvZXJjZSgnYicpO1xuXG4gICAgaWYoIWIpIHtcbiAgICAgICAgY29lcmNlKCdkYicpO1xuICAgICAgICBjb2VyY2UoJ2IwJyk7XG4gICAgfVxuXG4gICAgbWltaWNrQXhpc0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBmdWxsTGF5b3V0LCBkZmx0Q29sb3IpO1xufTtcblxuZnVuY3Rpb24gbWltaWNrQXhpc0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBmdWxsTGF5b3V0LCBkZmx0Q29sb3IpIHtcbiAgICB2YXIgYXhlc0xpc3QgPSBbJ2FheGlzJywgJ2JheGlzJ107XG5cbiAgICBheGVzTGlzdC5mb3JFYWNoKGZ1bmN0aW9uKGF4TmFtZSkge1xuICAgICAgICB2YXIgYXhMZXR0ZXIgPSBheE5hbWUuY2hhckF0KDApO1xuICAgICAgICB2YXIgYXhJbiA9IHRyYWNlSW5bYXhOYW1lXSB8fCB7fTtcbiAgICAgICAgdmFyIGF4T3V0ID0gVGVtcGxhdGUubmV3Q29udGFpbmVyKHRyYWNlT3V0LCBheE5hbWUpO1xuXG4gICAgICAgIHZhciBkZWZhdWx0T3B0aW9ucyA9IHtcbiAgICAgICAgICAgIHRpY2tmb250OiAneCcsXG4gICAgICAgICAgICBpZDogYXhMZXR0ZXIgKyAnYXhpcycsXG4gICAgICAgICAgICBsZXR0ZXI6IGF4TGV0dGVyLFxuICAgICAgICAgICAgZm9udDogdHJhY2VPdXQuZm9udCxcbiAgICAgICAgICAgIG5hbWU6IGF4TmFtZSxcbiAgICAgICAgICAgIGRhdGE6IHRyYWNlSW5bYXhMZXR0ZXJdLFxuICAgICAgICAgICAgY2FsZW5kYXI6IHRyYWNlT3V0LmNhbGVuZGFyLFxuICAgICAgICAgICAgZGZsdENvbG9yOiBkZmx0Q29sb3IsXG4gICAgICAgICAgICBiZ0NvbG9yOiBmdWxsTGF5b3V0LnBhcGVyX2JnY29sb3IsXG4gICAgICAgICAgICBmdWxsTGF5b3V0OiBmdWxsTGF5b3V0XG4gICAgICAgIH07XG5cbiAgICAgICAgaGFuZGxlQXhpc0RlZmF1bHRzKGF4SW4sIGF4T3V0LCBkZWZhdWx0T3B0aW9ucyk7XG4gICAgICAgIGF4T3V0Ll9jYXRlZ29yaWVzID0gYXhPdXQuX2NhdGVnb3JpZXMgfHwgW107XG5cbiAgICAgICAgLy8gc28gd2UgZG9uJ3QgaGF2ZSB0byByZXBlYXQgYXV0b3R5cGUgdW5uZWNlc3NhcmlseSxcbiAgICAgICAgLy8gY29weSBhbiBhdXRvdHlwZSBiYWNrIHRvIHRyYWNlSW5cbiAgICAgICAgaWYoIXRyYWNlSW5bYXhOYW1lXSAmJiBheEluLnR5cGUgIT09ICctJykge1xuICAgICAgICAgICAgdHJhY2VJbltheE5hbWVdID0ge3R5cGU6IGF4SW4udHlwZX07XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxufSx7XCIuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi9heGlzX2RlZmF1bHRzXCI6OTAxfV0sODk3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzQXJyYXlPclR5cGVkQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9saWInKS5pc0FycmF5T3JUeXBlZEFycmF5O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGEpIHtcbiAgICByZXR1cm4gbWluTWF4KGEsIDApO1xufTtcblxuZnVuY3Rpb24gbWluTWF4KGEsIGRlcHRoKSB7XG4gICAgLy8gTGltaXQgdG8gdGVuIGRpbWVuc2lvbmFsIGRhdGFzZXRzLiBUaGlzIHNlZW1zICpleGNlZWRpbmdseSogdW5saWtlbHkgdG9cbiAgICAvLyBldmVyIGNhdXNlIHByb2JsZW1zIG9yIGV2ZW4gYmUgYSBjb25jZXJuLiBJdCdzIGluY2x1ZGUgc3RyaWN0bHkgc28gdGhhdFxuICAgIC8vIGNpcmN1bGFyIGFycmF5cyBjb3VsZCBuZXZlciBjYXVzZSB0aGlzIHRvIGxvb3AuXG4gICAgaWYoIWlzQXJyYXlPclR5cGVkQXJyYXkoYSkgfHwgZGVwdGggPj0gMTApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIG1pbiA9IEluZmluaXR5O1xuICAgIHZhciBtYXggPSAtSW5maW5pdHk7XG4gICAgdmFyIG4gPSBhLmxlbmd0aDtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIHZhciBkYXR1bSA9IGFbaV07XG5cbiAgICAgICAgaWYoaXNBcnJheU9yVHlwZWRBcnJheShkYXR1bSkpIHtcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBtaW5NYXgoZGF0dW0sIGRlcHRoICsgMSk7XG5cbiAgICAgICAgICAgIGlmKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIG1pbiA9IE1hdGgubWluKHJlc3VsdFswXSwgbWluKTtcbiAgICAgICAgICAgICAgICBtYXggPSBNYXRoLm1heChyZXN1bHRbMV0sIG1heCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtaW4gPSBNYXRoLm1pbihkYXR1bSwgbWluKTtcbiAgICAgICAgICAgIG1heCA9IE1hdGgubWF4KGRhdHVtLCBtYXgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFttaW4sIG1heF07XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sODk4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGZvbnRBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGF4aXNBdHRycyA9IF9kZXJlcV8oJy4vYXhpc19hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xuXG52YXIgY2FycGV0Rm9udCA9IGZvbnRBdHRycyh7XG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICBcbn0pO1xuLy8gVE9ETzogaW5oZXJpdCBmcm9tIGdsb2JhbCBmb250XG5jYXJwZXRGb250LmZhbWlseS5kZmx0ID0gJ1wiT3BlbiBTYW5zXCIsIHZlcmRhbmEsIGFyaWFsLCBzYW5zLXNlcmlmJztcbmNhcnBldEZvbnQuc2l6ZS5kZmx0ID0gMTI7XG5jYXJwZXRGb250LmNvbG9yLmRmbHQgPSBjb2xvckF0dHJzLmRlZmF1bHRMaW5lO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjYXJwZXQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGE6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGEwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkYToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYjA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRiOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjaGVhdGVyc2xvcGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFheGlzOiBheGlzQXR0cnMsXG4gICAgYmF4aXM6IGF4aXNBdHRycyxcbiAgICBmb250OiBjYXJwZXRGb250LFxuICAgIGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRyYW5zZm9ybXM6IHVuZGVmaW5lZFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXNcIjo1OTIsXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTMsXCIuL2F4aXNfYXR0cmlidXRlc1wiOjkwMH1dLDg5OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcblxuLyogVGhpcyBmdW5jdGlvbiByZXRybnMgYSBzZXQgb2YgY29udHJvbCBwb2ludHMgdGhhdCBkZWZpbmUgYSBjdXJ2ZSBhbGlnbmVkIGFsb25nXG4gKiBlaXRoZXIgdGhlIGEgb3IgYiBheGlzLiBFeGFjdGx5IG9uZSBvZiBhIG9yIGIgbXVzdCBiZSBhbiBhcnJheSBkZWZpbmluZyB0aGUgcmFuZ2VcbiAqIHNwYW5uZWQuXG4gKlxuICogSG9uZXN0bHkgdGhpcyBpcyB0aGUgbW9zdCBjb21wbGljYXRlZCBmdW5jdGlvbiBJJ3ZlIGltcGxlbWVudGUgaGVyZSBzbyBmYXIgYmVjYXVzZVxuICogb2YgdGhlIHdheSBpdCBoYW5kbGVzIGtub3QgaW5zZXJ0aW9uIGFuZCBkaXJlY3Rpb24vYXhpcy1hZ25vc3RpYyBzbGljZXMuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oY2FycGV0LCBjYXJwZXRjZCwgYSwgYikge1xuICAgIHZhciBpZHgsIHRhbmdlbnQsIHRhbklzb0lkeCwgdGFuSXNvUGFyLCBzZWdtZW50LCByZWZpZHg7XG4gICAgdmFyIHAwLCBwMSwgdjAsIHYxLCBzdGFydCwgZW5kLCByYW5nZTtcblxuICAgIHZhciBheGlzID0gaXNBcnJheU9yVHlwZWRBcnJheShhKSA/ICdhJyA6ICdiJztcbiAgICB2YXIgYXggPSBheGlzID09PSAnYScgPyBjYXJwZXQuYWF4aXMgOiBjYXJwZXQuYmF4aXM7XG4gICAgdmFyIHNtb290aGluZyA9IGF4LnNtb290aGluZztcbiAgICB2YXIgdG9JZHggPSBheGlzID09PSAnYScgPyBjYXJwZXQuYTJpIDogY2FycGV0LmIyajtcbiAgICB2YXIgcHQgPSBheGlzID09PSAnYScgPyBhIDogYjtcbiAgICB2YXIgaXNvID0gYXhpcyA9PT0gJ2EnID8gYiA6IGE7XG4gICAgdmFyIG4gPSBheGlzID09PSAnYScgPyBjYXJwZXRjZC5hLmxlbmd0aCA6IGNhcnBldGNkLmIubGVuZ3RoO1xuICAgIHZhciBtID0gYXhpcyA9PT0gJ2EnID8gY2FycGV0Y2QuYi5sZW5ndGggOiBjYXJwZXRjZC5hLmxlbmd0aDtcbiAgICB2YXIgaXNvSWR4ID0gTWF0aC5mbG9vcihheGlzID09PSAnYScgPyBjYXJwZXQuYjJqKGlzbykgOiBjYXJwZXQuYTJpKGlzbykpO1xuXG4gICAgdmFyIHh5ID0gYXhpcyA9PT0gJ2EnID8gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGNhcnBldC5ldmFseHkoW10sIHZhbHVlLCBpc29JZHgpO1xuICAgIH0gOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICByZXR1cm4gY2FycGV0LmV2YWx4eShbXSwgaXNvSWR4LCB2YWx1ZSk7XG4gICAgfTtcblxuICAgIGlmKHNtb290aGluZykge1xuICAgICAgICB0YW5Jc29JZHggPSBNYXRoLm1heCgwLCBNYXRoLm1pbihtIC0gMiwgaXNvSWR4KSk7XG4gICAgICAgIHRhbklzb1BhciA9IGlzb0lkeCAtIHRhbklzb0lkeDtcbiAgICAgICAgdGFuZ2VudCA9IGF4aXMgPT09ICdhJyA/IGZ1bmN0aW9uKGksIHRpKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FycGV0LmR4eWRpKFtdLCBpLCB0YW5Jc29JZHgsIHRpLCB0YW5Jc29QYXIpO1xuICAgICAgICB9IDogZnVuY3Rpb24oaiwgdGopIHtcbiAgICAgICAgICAgIHJldHVybiBjYXJwZXQuZHh5ZGooW10sIHRhbklzb0lkeCwgaiwgdGFuSXNvUGFyLCB0aik7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIHZzdGFydCA9IHRvSWR4KHB0WzBdKTtcbiAgICB2YXIgdmVuZCA9IHRvSWR4KHB0WzFdKTtcblxuICAgIC8vIFNvIHRoYXQgd2UgY2FuIG1ha2UgdGhpcyB3b3JrIGluIHR3byBkaXJlY3Rpb25zLCBmbGlwIGFsbCBvZiB0aGVcbiAgICAvLyBtYXRoIGZ1bmN0aW9ucyBpZiB0aGUgZGlyZWN0aW9uIGlzIGZyb20gaGlnaGVyIHRvIGxvd2VyIGluZGljZXM6XG4gICAgLy9cbiAgICAvLyBOb3RlIHRoYXQgdGhlIHRvbGVyYW5jZSBpcyBkaXJlY3Rpb25hbCFcbiAgICB2YXIgZGlyID0gdnN0YXJ0IDwgdmVuZCA/IDEgOiAtMTtcbiAgICB2YXIgdG9sID0gKHZlbmQgLSB2c3RhcnQpICogMWUtODtcbiAgICB2YXIgZGlyZmxvb3IgPSBkaXIgPiAwID8gTWF0aC5mbG9vciA6IE1hdGguY2VpbDtcbiAgICB2YXIgZGlyY2VpbCA9IGRpciA+IDAgPyBNYXRoLmNlaWwgOiBNYXRoLmZsb29yO1xuICAgIHZhciBkaXJtaW4gPSBkaXIgPiAwID8gTWF0aC5taW4gOiBNYXRoLm1heDtcbiAgICB2YXIgZGlybWF4ID0gZGlyID4gMCA/IE1hdGgubWF4IDogTWF0aC5taW47XG5cbiAgICB2YXIgaWR4MCA9IGRpcmZsb29yKHZzdGFydCArIHRvbCk7XG4gICAgdmFyIGlkeDEgPSBkaXJjZWlsKHZlbmQgLSB0b2wpO1xuXG4gICAgcDAgPSB4eSh2c3RhcnQpO1xuICAgIHZhciBzZWdtZW50cyA9IFtbcDBdXTtcblxuICAgIGZvcihpZHggPSBpZHgwOyBpZHggKiBkaXIgPCBpZHgxICogZGlyOyBpZHggKz0gZGlyKSB7XG4gICAgICAgIHNlZ21lbnQgPSBbXTtcbiAgICAgICAgc3RhcnQgPSBkaXJtYXgodnN0YXJ0LCBpZHgpO1xuICAgICAgICBlbmQgPSBkaXJtaW4odmVuZCwgaWR4ICsgZGlyKTtcbiAgICAgICAgcmFuZ2UgPSBlbmQgLSBzdGFydDtcblxuICAgICAgICAvLyBJbiBvcmRlciB0byBmaWd1cmUgb3V0IHdoaWNoIGNlbGwgd2UncmUgaW4gZm9yIHRoZSBkZXJpdmF0aXZlIChyZW1lbWJlcixcbiAgICAgICAgLy8gdGhlIGRlcml2YXRpdmVzIGFyZSAqbm90KiBjb25zdGFudCBhY3Jvc3MgZ3JpZCBsaW5lcyksIGxldCdzIGp1c3QgYXZlcmFnZVxuICAgICAgICAvLyB0aGUgc3RhcnQgYW5kIGVuZCBwb2ludHMuIFRoaXMgY3V0cyBvdXQganVzdCBhIHRpbnkgYml0IG9mIGxvZ2ljIGFuZFxuICAgICAgICAvLyB0aGVyZSdzIHJlYWxseSBubyBjb21wdXRhdGlvbmFsIGRpZmZlcmVuY2U6XG4gICAgICAgIHJlZmlkeCA9IE1hdGgubWF4KDAsIE1hdGgubWluKG4gLSAyLCBNYXRoLmZsb29yKDAuNSAqIChzdGFydCArIGVuZCkpKSk7XG5cbiAgICAgICAgcDEgPSB4eShlbmQpO1xuICAgICAgICBpZihzbW9vdGhpbmcpIHtcbiAgICAgICAgICAgIHYwID0gdGFuZ2VudChyZWZpZHgsIHN0YXJ0IC0gcmVmaWR4KTtcbiAgICAgICAgICAgIHYxID0gdGFuZ2VudChyZWZpZHgsIGVuZCAtIHJlZmlkeCk7XG5cbiAgICAgICAgICAgIHNlZ21lbnQucHVzaChbXG4gICAgICAgICAgICAgICAgcDBbMF0gKyB2MFswXSAvIDMgKiByYW5nZSxcbiAgICAgICAgICAgICAgICBwMFsxXSArIHYwWzFdIC8gMyAqIHJhbmdlXG4gICAgICAgICAgICBdKTtcblxuICAgICAgICAgICAgc2VnbWVudC5wdXNoKFtcbiAgICAgICAgICAgICAgICBwMVswXSAtIHYxWzBdIC8gMyAqIHJhbmdlLFxuICAgICAgICAgICAgICAgIHAxWzFdIC0gdjFbMV0gLyAzICogcmFuZ2VcbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgc2VnbWVudC5wdXNoKHAxKTtcblxuICAgICAgICBzZWdtZW50cy5wdXNoKHNlZ21lbnQpO1xuICAgICAgICBwMCA9IHAxO1xuICAgIH1cblxuICAgIHJldHVybiBzZWdtZW50cztcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sOTAwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGZvbnRBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGNvbG9yQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXMnKTtcbnZhciBheGVzQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxudmFyIEZPUk1BVF9MSU5LID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2RvY3MnKS5GT1JNQVRfTElOSztcbnZhciBEQVRFX0ZPUk1BVF9MSU5LID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2RvY3MnKS5USU1FX0ZPUk1BVF9MSU5LO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzbW9vdGhpbmc6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLjMsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICB0aXRsZToge1xuICAgICAgICB0ZXh0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBvZmZzZXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiAxMCxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICB9LFxuICAgIHR5cGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAvLyAnLScgbWVhbnMgd2UgaGF2ZW4ndCB5ZXQgcnVuIGF1dG90eXBlIG9yIGNvdWxkbid0IGZpbmQgYW55IGRhdGFcbiAgICAgICAgLy8gaXQgZ2V0cyB0dXJuZWQgaW50byBsaW5lYXIgaW4gZ2QuX2Z1bGxMYXlvdXQgYnV0IG5vdCBjb3BpZWQgYmFja1xuICAgICAgICAvLyB0byBnZC5kYXRhIGxpa2UgdGhlIG90aGVycyBhcmUuXG4gICAgICAgIHZhbHVlczogWyctJywgJ2xpbmVhcicsICdkYXRlJywgJ2NhdGVnb3J5J10sXG4gICAgICAgIGRmbHQ6ICctJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYXV0b3JhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbdHJ1ZSwgZmFsc2UsICdyZXZlcnNlZCddLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICByYW5nZW1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbm9ybWFsJywgJ3RvemVybycsICdub25uZWdhdGl2ZSddLFxuICAgICAgICBkZmx0OiAnbm9ybWFsJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcmFuZ2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdjYWxjJ30sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ2FueScsIGVkaXRUeXBlOiAnY2FsYyd9XG4gICAgICAgIF0sXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBmaXhlZHJhbmdlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNoZWF0ZXJ0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2luZGV4JywgJ3ZhbHVlJ10sXG4gICAgICAgIGRmbHQ6ICd2YWx1ZScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICB0aWNrbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydsaW5lYXInLCAnYXJyYXknXSxcbiAgICAgICAgZGZsdDogJ2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgIG50aWNrczoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3ZhbHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2t0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93dGlja2xhYmVsczoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydzdGFydCcsICdlbmQnLCAnYm90aCcsICdub25lJ10sXG4gICAgICAgIGRmbHQ6ICdzdGFydCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tmb250OiBmb250QXR0cnMoe1xuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9KSxcbiAgICB0aWNrYW5nbGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FuZ2xlJyxcbiAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrcHJlZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2hvd3RpY2twcmVmaXg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnYWxsJywgJ2ZpcnN0JywgJ2xhc3QnLCAnbm9uZSddLFxuICAgICAgICBkZmx0OiAnYWxsJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja3N1ZmZpeDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3d0aWNrc3VmZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FsbCcsICdmaXJzdCcsICdsYXN0JywgJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ2FsbCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNob3dleHBvbmVudDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhbGwnLCAnZmlyc3QnLCAnbGFzdCcsICdub25lJ10sXG4gICAgICAgIGRmbHQ6ICdhbGwnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBleHBvbmVudGZvcm1hdDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydub25lJywgJ2UnLCAnRScsICdwb3dlcicsICdTSScsICdCJ10sXG4gICAgICAgIGRmbHQ6ICdCJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2VwYXJhdGV0aG91c2FuZHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGlja2Zvcm1hdDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRpY2tmb3JtYXRzdG9wczogb3ZlcnJpZGVBbGwoYXhlc0F0dHJzLnRpY2tmb3JtYXRzdG9wcywgJ2NhbGMnLCAnZnJvbS1yb290JyksXG4gICAgY2F0ZWdvcnlvcmRlcjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW1xuICAgICAgICAgICAgJ3RyYWNlJywgJ2NhdGVnb3J5IGFzY2VuZGluZycsICdjYXRlZ29yeSBkZXNjZW5kaW5nJywgJ2FycmF5J1xuICAgICAgICAgICAgLyogLCAndmFsdWUgYXNjZW5kaW5nJywgJ3ZhbHVlIGRlc2NlbmRpbmcnKi8gLy8gdmFsdWUgYXNjZW5kaW5nIC8gZGVzY2VuZGluZyB0byBiZSBpbXBsZW1lbnRlZCBsYXRlclxuICAgICAgICBdLFxuICAgICAgICBkZmx0OiAndHJhY2UnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjYXRlZ29yeWFycmF5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGFiZWxwYWRkaW5nOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDEwLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxhYmVscHJlZml4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsYWJlbHN1ZmZpeDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIGxpbmVzIGFuZCBncmlkc1xuICAgIHNob3dsaW5lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxpbmVjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBsaW5ld2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZ3JpZGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGdyaWR3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93Z3JpZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG1pbm9yZ3JpZGNvdW50OiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtaW5vcmdyaWR3aWR0aDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtaW5vcmdyaWRjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmxpZ2h0TGluZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RhcnRsaW5lOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RhcnRsaW5lY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3RhcnRsaW5ld2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVuZGxpbmU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlbmRsaW5ld2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGVuZGxpbmVjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0aWNrMDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBkdGljazoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhcnJheXRpY2swOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhcnJheWR0aWNrOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAxLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIF9kZXByZWNhdGVkOiB7XG4gICAgICAgIHRpdGxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB0aXRsZWZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICB0aXRsZW9mZnNldDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IDEwLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGVkaXRUeXBlOiAnY2FsYydcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzXCI6NTkyLFwiLi4vLi4vY29uc3RhbnRzL2RvY3NcIjo2OTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2xheW91dF9hdHRyaWJ1dGVzXCI6Nzc5LFwiLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzXCI6NzkzfV0sOTAxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNhcnBldEF0dHJzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbnZhciBhZGRPcGFjaXR5ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpLmFkZE9wYWNpdHk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGhhbmRsZVRpY2tWYWx1ZURlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfdmFsdWVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrTGFiZWxEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi90aWNrX2xhYmVsX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlQ2F0ZWdvcnlPcmRlckRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NhdGVnb3J5X29yZGVyX2RlZmF1bHRzJyk7XG52YXIgc2V0Q29udmVydCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9zZXRfY29udmVydCcpO1xudmFyIGF1dG9UeXBlID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfYXV0b3R5cGUnKTtcblxuLyoqXG4gKiBvcHRpb25zOiBvYmplY3QgY29udGFpbmluZzpcbiAqXG4gKiAgbGV0dGVyOiAnYScgb3IgJ2InXG4gKiAgdGl0bGU6IG5hbWUgb2YgdGhlIGF4aXMgKGllICdDb2xvcmJhcicpIHRvIGdvIGluIGRlZmF1bHQgdGl0bGVcbiAqICBuYW1lOiBheGlzIG9iamVjdCBuYW1lIChpZSAneGF4aXMnKSBpZiBvbmUgc2hvdWxkIGJlIHN0b3JlZFxuICogIGZvbnQ6IHRoZSBkZWZhdWx0IGZvbnQgdG8gaW5oZXJpdFxuICogIG91dGVyVGlja3M6IGJvb2xlYW4sIHNob3VsZCB0aWNrcyBkZWZhdWx0IHRvIG91dHNpZGU/XG4gKiAgc2hvd0dyaWQ6IGJvb2xlYW4sIHNob3VsZCBncmlkbGluZXMgYmUgc2hvd24gYnkgZGVmYXVsdD9cbiAqICBkYXRhOiB0aGUgcGxvdCBkYXRhIHRvIHVzZSBpbiBjaG9vc2luZyBhdXRvIHR5cGVcbiAqICBiZ0NvbG9yOiB0aGUgcGxvdCBiYWNrZ3JvdW5kIGNvbG9yLCB0byBjYWxjdWxhdGUgZGVmYXVsdCBncmlkbGluZSBjb2xvcnNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVBeGlzRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgb3B0aW9ucykge1xuICAgIHZhciBsZXR0ZXIgPSBvcHRpb25zLmxldHRlcjtcbiAgICB2YXIgZm9udCA9IG9wdGlvbnMuZm9udCB8fCB7fTtcbiAgICB2YXIgYXR0cmlidXRlcyA9IGNhcnBldEF0dHJzW2xldHRlciArICdheGlzJ107XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UyKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UyKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIC8vIHNldCB1cCBzb21lIHByaXZhdGUgcHJvcGVydGllc1xuICAgIGlmKG9wdGlvbnMubmFtZSkge1xuICAgICAgICBjb250YWluZXJPdXQuX25hbWUgPSBvcHRpb25zLm5hbWU7XG4gICAgICAgIGNvbnRhaW5lck91dC5faWQgPSBvcHRpb25zLm5hbWU7XG4gICAgfVxuXG4gICAgLy8gbm93IGZpZ3VyZSBvdXQgdHlwZSBhbmQgZG8gc29tZSBtb3JlIGluaXRpYWxpemF0aW9uXG4gICAgdmFyIGF4VHlwZSA9IGNvZXJjZSgndHlwZScpO1xuICAgIGlmKGF4VHlwZSA9PT0gJy0nKSB7XG4gICAgICAgIGlmKG9wdGlvbnMuZGF0YSkgc2V0QXV0b1R5cGUoY29udGFpbmVyT3V0LCBvcHRpb25zLmRhdGEpO1xuXG4gICAgICAgIGlmKGNvbnRhaW5lck91dC50eXBlID09PSAnLScpIHtcbiAgICAgICAgICAgIGNvbnRhaW5lck91dC50eXBlID0gJ2xpbmVhcic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBjb3B5IGF1dG9UeXBlIGJhY2sgdG8gaW5wdXQgYXhpc1xuICAgICAgICAgICAgLy8gbm90ZSB0aGF0IGlmIHRoaXMgb2JqZWN0IGRpZG4ndCBleGlzdFxuICAgICAgICAgICAgLy8gaW4gdGhlIGlucHV0IGxheW91dCwgd2UgaGF2ZSB0byBwdXQgaXQgaW5cbiAgICAgICAgICAgIC8vIHRoaXMgaGFwcGVucyBpbiB0aGUgbWFpbiBzdXBwbHlEZWZhdWx0cyBmdW5jdGlvblxuICAgICAgICAgICAgYXhUeXBlID0gY29udGFpbmVySW4udHlwZSA9IGNvbnRhaW5lck91dC50eXBlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29lcmNlKCdzbW9vdGhpbmcnKTtcbiAgICBjb2VyY2UoJ2NoZWF0ZXJ0eXBlJyk7XG5cbiAgICBjb2VyY2UoJ3Nob3d0aWNrbGFiZWxzJyk7XG4gICAgY29lcmNlKCdsYWJlbHByZWZpeCcsIGxldHRlciArICcgPSAnKTtcbiAgICBjb2VyY2UoJ2xhYmVsc3VmZml4Jyk7XG4gICAgY29lcmNlKCdzaG93dGlja3ByZWZpeCcpO1xuICAgIGNvZXJjZSgnc2hvd3RpY2tzdWZmaXgnKTtcblxuICAgIGNvZXJjZSgnc2VwYXJhdGV0aG91c2FuZHMnKTtcbiAgICBjb2VyY2UoJ3RpY2tmb3JtYXQnKTtcbiAgICBjb2VyY2UoJ2V4cG9uZW50Zm9ybWF0Jyk7XG4gICAgY29lcmNlKCdzaG93ZXhwb25lbnQnKTtcbiAgICBjb2VyY2UoJ2NhdGVnb3J5b3JkZXInKTtcblxuICAgIGNvZXJjZSgndGlja21vZGUnKTtcbiAgICBjb2VyY2UoJ3RpY2t2YWxzJyk7XG4gICAgY29lcmNlKCd0aWNrdGV4dCcpO1xuICAgIGNvZXJjZSgndGljazAnKTtcbiAgICBjb2VyY2UoJ2R0aWNrJyk7XG5cbiAgICBpZihjb250YWluZXJPdXQudGlja21vZGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgY29lcmNlKCdhcnJheXRpY2swJyk7XG4gICAgICAgIGNvZXJjZSgnYXJyYXlkdGljaycpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnbGFiZWxwYWRkaW5nJyk7XG5cbiAgICBjb250YWluZXJPdXQuX2hvdmVydGl0bGUgPSBsZXR0ZXI7XG5cblxuICAgIGlmKGF4VHlwZSA9PT0gJ2RhdGUnKSB7XG4gICAgICAgIHZhciBoYW5kbGVDYWxlbmRhckRlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnaGFuZGxlRGVmYXVsdHMnKTtcbiAgICAgICAgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyhjb250YWluZXJJbiwgY29udGFpbmVyT3V0LCAnY2FsZW5kYXInLCBvcHRpb25zLmNhbGVuZGFyKTtcbiAgICB9XG5cbiAgICAvLyB3ZSBuZWVkIHNvbWUgb2YgdGhlIG90aGVyIGZ1bmN0aW9ucyBzZXRDb252ZXJ0IGF0dGFjaGVzLCBidXQgZm9yXG4gICAgLy8gcGF0aCBmaW5kaW5nLCBvdmVycmlkZSBwaXhlbCBzY2FsaW5nIHRvIHNpbXBsZSBwYXNzdGhyb3VnaCAoaWRlbnRpdHkpXG4gICAgc2V0Q29udmVydChjb250YWluZXJPdXQsIG9wdGlvbnMuZnVsbExheW91dCk7XG4gICAgY29udGFpbmVyT3V0LmMycCA9IExpYi5pZGVudGl0eTtcblxuICAgIHZhciBkZmx0Q29sb3IgPSBjb2VyY2UoJ2NvbG9yJywgb3B0aW9ucy5kZmx0Q29sb3IpO1xuICAgIC8vIGlmIGF4aXMuY29sb3Igd2FzIHByb3ZpZGVkLCB1c2UgaXQgZm9yIGZvbnRzIHRvbzsgb3RoZXJ3aXNlLFxuICAgIC8vIGluaGVyaXQgZnJvbSBnbG9iYWwgZm9udCBjb2xvciBpbiBjYXNlIHRoYXQgd2FzIHByb3ZpZGVkLlxuICAgIHZhciBkZmx0Rm9udENvbG9yID0gKGRmbHRDb2xvciA9PT0gY29udGFpbmVySW4uY29sb3IpID8gZGZsdENvbG9yIDogZm9udC5jb2xvcjtcblxuICAgIHZhciB0aXRsZSA9IGNvZXJjZSgndGl0bGUudGV4dCcpO1xuICAgIGlmKHRpdGxlKSB7XG4gICAgICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3RpdGxlLmZvbnQnLCB7XG4gICAgICAgICAgICBmYW1pbHk6IGZvbnQuZmFtaWx5LFxuICAgICAgICAgICAgc2l6ZTogTWF0aC5yb3VuZChmb250LnNpemUgKiAxLjIpLFxuICAgICAgICAgICAgY29sb3I6IGRmbHRGb250Q29sb3JcbiAgICAgICAgfSk7XG4gICAgICAgIGNvZXJjZSgndGl0bGUub2Zmc2V0Jyk7XG4gICAgfVxuXG4gICAgY29lcmNlKCd0aWNrYW5nbGUnKTtcblxuICAgIHZhciBhdXRvUmFuZ2UgPSBjb2VyY2UoJ2F1dG9yYW5nZScsICFjb250YWluZXJPdXQuaXNWYWxpZFJhbmdlKGNvbnRhaW5lckluLnJhbmdlKSk7XG5cbiAgICBpZihhdXRvUmFuZ2UpIGNvZXJjZSgncmFuZ2Vtb2RlJyk7XG5cbiAgICBjb2VyY2UoJ3JhbmdlJyk7XG4gICAgY29udGFpbmVyT3V0LmNsZWFuUmFuZ2UoKTtcblxuICAgIGNvZXJjZSgnZml4ZWRyYW5nZScpO1xuXG4gICAgaGFuZGxlVGlja1ZhbHVlRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCBheFR5cGUpO1xuICAgIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzKGNvbnRhaW5lckluLCBjb250YWluZXJPdXQsIGNvZXJjZSwgYXhUeXBlLCBvcHRpb25zKTtcbiAgICBoYW5kbGVDYXRlZ29yeU9yZGVyRGVmYXVsdHMoY29udGFpbmVySW4sIGNvbnRhaW5lck91dCwgY29lcmNlLCB7XG4gICAgICAgIGRhdGE6IG9wdGlvbnMuZGF0YSxcbiAgICAgICAgZGF0YUF0dHI6IGxldHRlclxuICAgIH0pO1xuXG4gICAgdmFyIGdyaWRDb2xvciA9IGNvZXJjZTIoJ2dyaWRjb2xvcicsIGFkZE9wYWNpdHkoZGZsdENvbG9yLCAwLjMpKTtcbiAgICB2YXIgZ3JpZFdpZHRoID0gY29lcmNlMignZ3JpZHdpZHRoJyk7XG4gICAgdmFyIHNob3dHcmlkID0gY29lcmNlKCdzaG93Z3JpZCcpO1xuXG4gICAgaWYoIXNob3dHcmlkKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuZ3JpZGNvbG9yO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LmdyaWR3aWR0aDtcbiAgICB9XG5cbiAgICB2YXIgc3RhcnRMaW5lQ29sb3IgPSBjb2VyY2UyKCdzdGFydGxpbmVjb2xvcicsIGRmbHRDb2xvcik7XG4gICAgdmFyIHN0YXJ0TGluZVdpZHRoID0gY29lcmNlMignc3RhcnRsaW5ld2lkdGgnLCBncmlkV2lkdGgpO1xuICAgIHZhciBzaG93U3RhcnRMaW5lID0gY29lcmNlKCdzdGFydGxpbmUnLCBjb250YWluZXJPdXQuc2hvd2dyaWQgfHwgISFzdGFydExpbmVDb2xvciB8fCAhIXN0YXJ0TGluZVdpZHRoKTtcblxuICAgIGlmKCFzaG93U3RhcnRMaW5lKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuc3RhcnRsaW5lY29sb3I7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuc3RhcnRsaW5ld2lkdGg7XG4gICAgfVxuXG4gICAgdmFyIGVuZExpbmVDb2xvciA9IGNvZXJjZTIoJ2VuZGxpbmVjb2xvcicsIGRmbHRDb2xvcik7XG4gICAgdmFyIGVuZExpbmVXaWR0aCA9IGNvZXJjZTIoJ2VuZGxpbmV3aWR0aCcsIGdyaWRXaWR0aCk7XG4gICAgdmFyIHNob3dFbmRMaW5lID0gY29lcmNlKCdlbmRsaW5lJywgY29udGFpbmVyT3V0LnNob3dncmlkIHx8ICEhZW5kTGluZUNvbG9yIHx8ICEhZW5kTGluZVdpZHRoKTtcblxuICAgIGlmKCFzaG93RW5kTGluZSkge1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LmVuZGxpbmVjb2xvcjtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC5lbmRsaW5ld2lkdGg7XG4gICAgfVxuXG4gICAgaWYoIXNob3dHcmlkKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQuZ3JpZGNvbG9yO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LmdyaWRXaWR0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb2VyY2UoJ21pbm9yZ3JpZGNvdW50Jyk7XG4gICAgICAgIGNvZXJjZSgnbWlub3Jncmlkd2lkdGgnLCBncmlkV2lkdGgpO1xuICAgICAgICBjb2VyY2UoJ21pbm9yZ3JpZGNvbG9yJywgYWRkT3BhY2l0eShncmlkQ29sb3IsIDAuMDYpKTtcblxuICAgICAgICBpZighY29udGFpbmVyT3V0Lm1pbm9yZ3JpZGNvdW50KSB7XG4gICAgICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0Lm1pbm9yZ3JpZHdpZHRoO1xuICAgICAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC5taW5vcmdyaWRjb2xvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGNvbnRhaW5lck91dC5zaG93dGlja2xhYmVscyA9PT0gJ25vbmUnKSB7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQudGlja2ZvbnQ7XG4gICAgICAgIGRlbGV0ZSBjb250YWluZXJPdXQudGlja2FuZ2xlO1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnNob3dleHBvbmVudDtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC5leHBvbmVudGZvcm1hdDtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC50aWNrZm9ybWF0O1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnNob3d0aWNrc3VmZml4O1xuICAgICAgICBkZWxldGUgY29udGFpbmVyT3V0LnNob3d0aWNrcHJlZml4O1xuICAgIH1cblxuICAgIGlmKCFjb250YWluZXJPdXQuc2hvd3RpY2tzdWZmaXgpIHtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC50aWNrc3VmZml4O1xuICAgIH1cblxuICAgIGlmKCFjb250YWluZXJPdXQuc2hvd3RpY2twcmVmaXgpIHtcbiAgICAgICAgZGVsZXRlIGNvbnRhaW5lck91dC50aWNrcHJlZml4O1xuICAgIH1cblxuICAgIC8vIEl0IG5lZWRzIHRvIGJlIGNvZXJjZWQsIHRoZW4gc29tZXRoaW5nIGFib3ZlIG92ZXJyaWRlcyB0aGlzIGRlZXAgaW4gdGhlIGF4aXMgY29kZSxcbiAgICAvLyBidXQgbm8sIHdlICphY3R1YWxseSogd2FudCB0byBjb2VyY2UgdGhpcy5cbiAgICBjb2VyY2UoJ3RpY2ttb2RlJyk7XG5cbiAgICByZXR1cm4gY29udGFpbmVyT3V0O1xufTtcblxuZnVuY3Rpb24gc2V0QXV0b1R5cGUoYXgsIGRhdGEpIHtcbiAgICAvLyBuZXcgbG9naWM6IGxldCBwZW9wbGUgc3BlY2lmeSBhbnkgdHlwZSB0aGV5IHdhbnQsXG4gICAgLy8gb25seSBhdXRvdHlwZSBpZiB0eXBlIGlzICctJ1xuICAgIGlmKGF4LnR5cGUgIT09ICctJykgcmV0dXJuO1xuXG4gICAgdmFyIGlkID0gYXguX2lkO1xuICAgIHZhciBheExldHRlciA9IGlkLmNoYXJBdCgwKTtcblxuICAgIHZhciBjYWxBdHRyID0gYXhMZXR0ZXIgKyAnY2FsZW5kYXInO1xuICAgIHZhciBjYWxlbmRhciA9IGF4W2NhbEF0dHJdO1xuXG4gICAgYXgudHlwZSA9IGF1dG9UeXBlKGRhdGEsIGNhbGVuZGFyKTtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfYXV0b3R5cGVcIjo3NjgsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vY2F0ZWdvcnlfb3JkZXJfZGVmYXVsdHNcIjo3NzEsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vc2V0X2NvbnZlcnRcIjo3ODUsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vdGlja19sYWJlbF9kZWZhdWx0c1wiOjc4NixcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi90aWNrX3ZhbHVlX2RlZmF1bHRzXCI6Nzg4LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2F0dHJpYnV0ZXNcIjo4OTh9XSw5MDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgaXNBcnJheTFEID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheTFEO1xudmFyIGNoZWF0ZXJCYXNpcyA9IF9kZXJlcV8oJy4vY2hlYXRlcl9iYXNpcycpO1xudmFyIGFycmF5TWlubWF4ID0gX2RlcmVxXygnLi9hcnJheV9taW5tYXgnKTtcbnZhciBjYWxjR3JpZGxpbmVzID0gX2RlcmVxXygnLi9jYWxjX2dyaWRsaW5lcycpO1xudmFyIGNhbGNMYWJlbHMgPSBfZGVyZXFfKCcuL2NhbGNfbGFiZWxzJyk7XG52YXIgY2FsY0NsaXBQYXRoID0gX2RlcmVxXygnLi9jYWxjX2NsaXBwYXRoJyk7XG52YXIgY2xlYW4yZEFycmF5ID0gX2RlcmVxXygnLi4vaGVhdG1hcC9jbGVhbl8yZF9hcnJheScpO1xudmFyIHNtb290aEZpbGwyZEFycmF5ID0gX2RlcmVxXygnLi9zbW9vdGhfZmlsbF8yZF9hcnJheScpO1xudmFyIGNvbnZlcnRDb2x1bW5EYXRhID0gX2RlcmVxXygnLi4vaGVhdG1hcC9jb252ZXJ0X2NvbHVtbl94eXonKTtcbnZhciBzZXRDb252ZXJ0ID0gX2RlcmVxXygnLi9zZXRfY29udmVydCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnhheGlzKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMpO1xuICAgIHZhciBhYXggPSB0cmFjZS5hYXhpcztcbiAgICB2YXIgYmF4ID0gdHJhY2UuYmF4aXM7XG5cbiAgICB2YXIgeCA9IHRyYWNlLng7XG4gICAgdmFyIHkgPSB0cmFjZS55O1xuICAgIHZhciBjb2xzID0gW107XG4gICAgaWYoeCAmJiBpc0FycmF5MUQoeCkpIGNvbHMucHVzaCgneCcpO1xuICAgIGlmKHkgJiYgaXNBcnJheTFEKHkpKSBjb2xzLnB1c2goJ3knKTtcblxuICAgIGlmKGNvbHMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnZlcnRDb2x1bW5EYXRhKHRyYWNlLCBhYXgsIGJheCwgJ2EnLCAnYicsIGNvbHMpO1xuICAgIH1cblxuICAgIHZhciBhID0gdHJhY2UuX2EgPSB0cmFjZS5fYSB8fCB0cmFjZS5hO1xuICAgIHZhciBiID0gdHJhY2UuX2IgPSB0cmFjZS5fYiB8fCB0cmFjZS5iO1xuICAgIHggPSB0cmFjZS5feCB8fCB0cmFjZS54O1xuICAgIHkgPSB0cmFjZS5feSB8fCB0cmFjZS55O1xuXG4gICAgdmFyIHQgPSB7fTtcblxuICAgIGlmKHRyYWNlLl9jaGVhdGVyKSB7XG4gICAgICAgIHZhciBhdmFscyA9IGFheC5jaGVhdGVydHlwZSA9PT0gJ2luZGV4JyA/IGEubGVuZ3RoIDogYTtcbiAgICAgICAgdmFyIGJ2YWxzID0gYmF4LmNoZWF0ZXJ0eXBlID09PSAnaW5kZXgnID8gYi5sZW5ndGggOiBiO1xuICAgICAgICB4ID0gY2hlYXRlckJhc2lzKGF2YWxzLCBidmFscywgdHJhY2UuY2hlYXRlcnNsb3BlKTtcbiAgICB9XG5cbiAgICB0cmFjZS5feCA9IHggPSBjbGVhbjJkQXJyYXkoeCk7XG4gICAgdHJhY2UuX3kgPSB5ID0gY2xlYW4yZEFycmF5KHkpO1xuXG4gICAgLy8gRmlsbCBpbiBhbnkgdW5kZWZpbmVkIHZhbHVlcyB3aXRoIGVsbGlwdGljIHNtb290aGluZy4gVGhpcyBkb2Vzbid0IHRha2VcbiAgICAvLyBpbnRvIGFjY291bnQgdGhlIHNwYWNpbmcgb2YgdGhlIHZhbHVlcy4gVGhhdCBpcywgdGhlIGRlcml2YXRpdmVzIHNob3VsZFxuICAgIC8vIGJlIG1vZGlmaWVkIHRvIHVzZSBhIGFuZCBiIHZhbHVlcy4gSXQncyBub3QgdGhhdCBoYXJkLCBidXQgdGhpcyBpcyBhbHJlYWR5XG4gICAgLy8gbW9kZXJhdGUgb3ZlcmtpbGwgZm9yIGp1c3QgZmlsbGluZyBpbiBtaXNzaW5nIHZhbHVlcy5cbiAgICBzbW9vdGhGaWxsMmRBcnJheSh4LCBhLCBiKTtcbiAgICBzbW9vdGhGaWxsMmRBcnJheSh5LCBhLCBiKTtcblxuICAgIHNldENvbnZlcnQodHJhY2UpO1xuXG4gICAgLy8gY3JlYXRlIGNvbnZlcnNpb24gZnVuY3Rpb25zIHRoYXQgZGVwZW5kIG9uIHRoZSBkYXRhXG4gICAgdHJhY2Uuc2V0U2NhbGUoKTtcblxuICAgIC8vIFRoaXMgaXMgYSByYXRoZXIgZXhwZW5zaXZlIHNjYW4uIE5vdGhpbmcgZ3VhcmFudGVlcyBtb25vdG9uaWNpdHksXG4gICAgLy8gc28gd2UgbmVlZCB0byBzY2FuIHRocm91Z2ggYWxsIGRhdGEgdG8gZ2V0IHByb3BlciByYW5nZXM6XG4gICAgdmFyIHhyYW5nZSA9IGFycmF5TWlubWF4KHgpO1xuICAgIHZhciB5cmFuZ2UgPSBhcnJheU1pbm1heCh5KTtcblxuICAgIHZhciBkeCA9IDAuNSAqICh4cmFuZ2VbMV0gLSB4cmFuZ2VbMF0pO1xuICAgIHZhciB4YyA9IDAuNSAqICh4cmFuZ2VbMV0gKyB4cmFuZ2VbMF0pO1xuXG4gICAgdmFyIGR5ID0gMC41ICogKHlyYW5nZVsxXSAtIHlyYW5nZVswXSk7XG4gICAgdmFyIHljID0gMC41ICogKHlyYW5nZVsxXSArIHlyYW5nZVswXSk7XG5cbiAgICAvLyBFeHBhbmQgdGhlIGF4ZXMgdG8gZml0IHRoZSBwbG90LCBleGNlcHQganVzdCBncm93IGl0IGJ5IGEgZmFjdG9yIG9mIDEuM1xuICAgIC8vIGJlY2F1c2UgdGhlIGxhYmVscyBzaG91bGQgYmUgdGFrZW4gaW50byBhY2NvdW50IGV4Y2VwdCB0aGF0J3MgZGlmZmljdWx0XG4gICAgLy8gaGVuY2UgMS4zLlxuICAgIHZhciBncm93ID0gMS4zO1xuICAgIHhyYW5nZSA9IFt4YyAtIGR4ICogZ3JvdywgeGMgKyBkeCAqIGdyb3ddO1xuICAgIHlyYW5nZSA9IFt5YyAtIGR5ICogZ3JvdywgeWMgKyBkeSAqIGdyb3ddO1xuXG4gICAgdHJhY2UuX2V4dHJlbWVzW3hhLl9pZF0gPSBBeGVzLmZpbmRFeHRyZW1lcyh4YSwgeHJhbmdlLCB7cGFkZGVkOiB0cnVlfSk7XG4gICAgdHJhY2UuX2V4dHJlbWVzW3lhLl9pZF0gPSBBeGVzLmZpbmRFeHRyZW1lcyh5YSwgeXJhbmdlLCB7cGFkZGVkOiB0cnVlfSk7XG5cbiAgICAvLyBFbnVtZXJhdGUgdGhlIGdyaWRsaW5lcywgYm90aCBtYWpvciBhbmQgbWlub3IsIGFuZCBzdG9yZSB0aGVtIG9uIHRoZSB0cmFjZVxuICAgIC8vIG9iamVjdDpcbiAgICBjYWxjR3JpZGxpbmVzKHRyYWNlLCAnYScsICdiJyk7XG4gICAgY2FsY0dyaWRsaW5lcyh0cmFjZSwgJ2InLCAnYScpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSB0ZXh0IGxhYmVscyBmb3IgZWFjaCBtYWpvciBncmlkbGluZSBhbmQgc3RvcmUgdGhlbSBvbiB0aGVcbiAgICAvLyB0cmFjZSBvYmplY3Q6XG4gICAgY2FsY0xhYmVscyh0cmFjZSwgYWF4KTtcbiAgICBjYWxjTGFiZWxzKHRyYWNlLCBiYXgpO1xuXG4gICAgLy8gVGFidWxhdGUgcG9pbnRzIGZvciB0aGUgZm91ciBzZWdtZW50cyB0aGF0IGJvdW5kIHRoZSBheGVzIHNvIHRoYXQgd2UgY2FuXG4gICAgLy8gbWFwIHRvIHBpeGVsIGNvb3JkaW5hdGVzIGluIHRoZSBwbG90IGZ1bmN0aW9uIGFuZCBjcmVhdGUgYSBjbGlwIHJlY3Q6XG4gICAgdC5jbGlwc2VnbWVudHMgPSBjYWxjQ2xpcFBhdGgodHJhY2UuX3hjdHJsLCB0cmFjZS5feWN0cmwsIGFheCwgYmF4KTtcblxuICAgIHQueCA9IHg7XG4gICAgdC55ID0geTtcbiAgICB0LmEgPSBhO1xuICAgIHQuYiA9IGI7XG5cbiAgICByZXR1cm4gW3RdO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL2hlYXRtYXAvY2xlYW5fMmRfYXJyYXlcIjoxMDAzLFwiLi4vaGVhdG1hcC9jb252ZXJ0X2NvbHVtbl94eXpcIjoxMDA1LFwiLi9hcnJheV9taW5tYXhcIjo4OTcsXCIuL2NhbGNfY2xpcHBhdGhcIjo5MDMsXCIuL2NhbGNfZ3JpZGxpbmVzXCI6OTA0LFwiLi9jYWxjX2xhYmVsc1wiOjkwNSxcIi4vY2hlYXRlcl9iYXNpc1wiOjkwNyxcIi4vc2V0X2NvbnZlcnRcIjo5MjAsXCIuL3Ntb290aF9maWxsXzJkX2FycmF5XCI6OTIxfV0sOTAzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1ha2VDbGlwUGF0aCh4Y3RybCwgeWN0cmwsIGFheCwgYmF4KSB7XG4gICAgdmFyIGksIHgsIHk7XG4gICAgdmFyIHNlZ21lbnRzID0gW107XG5cbiAgICB2YXIgYXNtb290aGluZyA9ICEhYWF4LnNtb290aGluZztcbiAgICB2YXIgYnNtb290aGluZyA9ICEhYmF4LnNtb290aGluZztcbiAgICB2YXIgbmVhMSA9IHhjdHJsWzBdLmxlbmd0aCAtIDE7XG4gICAgdmFyIG5lYjEgPSB4Y3RybC5sZW5ndGggLSAxO1xuXG4gICAgLy8gQWxvbmcgdGhlIGxvd2VyIGEgYXhpczpcbiAgICBmb3IoaSA9IDAsIHggPSBbXSwgeSA9IFtdOyBpIDw9IG5lYTE7IGkrKykge1xuICAgICAgICB4W2ldID0geGN0cmxbMF1baV07XG4gICAgICAgIHlbaV0gPSB5Y3RybFswXVtpXTtcbiAgICB9XG4gICAgc2VnbWVudHMucHVzaCh7eDogeCwgeTogeSwgYmljdWJpYzogYXNtb290aGluZ30pO1xuXG4gICAgLy8gQWxvbmcgdGhlIHVwcGVyIGIgYXhpczpcbiAgICBmb3IoaSA9IDAsIHggPSBbXSwgeSA9IFtdOyBpIDw9IG5lYjE7IGkrKykge1xuICAgICAgICB4W2ldID0geGN0cmxbaV1bbmVhMV07XG4gICAgICAgIHlbaV0gPSB5Y3RybFtpXVtuZWExXTtcbiAgICB9XG4gICAgc2VnbWVudHMucHVzaCh7eDogeCwgeTogeSwgYmljdWJpYzogYnNtb290aGluZ30pO1xuXG4gICAgLy8gQmFja3dhcmRzIGFsb25nIHRoZSB1cHBlciBhIGF4aXM6XG4gICAgZm9yKGkgPSBuZWExLCB4ID0gW10sIHkgPSBbXTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgeFtuZWExIC0gaV0gPSB4Y3RybFtuZWIxXVtpXTtcbiAgICAgICAgeVtuZWExIC0gaV0gPSB5Y3RybFtuZWIxXVtpXTtcbiAgICB9XG4gICAgc2VnbWVudHMucHVzaCh7eDogeCwgeTogeSwgYmljdWJpYzogYXNtb290aGluZ30pO1xuXG4gICAgLy8gQmFja3dhcmRzIGFsb25nIHRoZSBsb3dlciBiIGF4aXM6XG4gICAgZm9yKGkgPSBuZWIxLCB4ID0gW10sIHkgPSBbXTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgeFtuZWIxIC0gaV0gPSB4Y3RybFtpXVswXTtcbiAgICAgICAgeVtuZWIxIC0gaV0gPSB5Y3RybFtpXVswXTtcbiAgICB9XG4gICAgc2VnbWVudHMucHVzaCh7eDogeCwgeTogeSwgYmljdWJpYzogYnNtb290aGluZ30pO1xuXG4gICAgcmV0dXJuIHNlZ21lbnRzO1xufTtcblxufSx7fV0sOTA0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjR3JpZGxpbmVzKHRyYWNlLCBheGlzTGV0dGVyLCBjcm9zc0F4aXNMZXR0ZXIpIHtcbiAgICB2YXIgaSwgaiwgajA7XG4gICAgdmFyIGVwcywgYm91bmRzLCBuMSwgbjIsIG4sIHZhbHVlLCB2O1xuICAgIHZhciBqMSwgdjAsIHYxLCBkO1xuXG4gICAgdmFyIGRhdGEgPSB0cmFjZVsnXycgKyBheGlzTGV0dGVyXTtcbiAgICB2YXIgYXhpcyA9IHRyYWNlW2F4aXNMZXR0ZXIgKyAnYXhpcyddO1xuXG4gICAgdmFyIGdyaWRsaW5lcyA9IGF4aXMuX2dyaWRsaW5lcyA9IFtdO1xuICAgIHZhciBtaW5vcmdyaWRsaW5lcyA9IGF4aXMuX21pbm9yZ3JpZGxpbmVzID0gW107XG4gICAgdmFyIGJvdW5kYXJ5bGluZXMgPSBheGlzLl9ib3VuZGFyeWxpbmVzID0gW107XG5cbiAgICB2YXIgY3Jvc3NEYXRhID0gdHJhY2VbJ18nICsgY3Jvc3NBeGlzTGV0dGVyXTtcbiAgICB2YXIgY3Jvc3NBeGlzID0gdHJhY2VbY3Jvc3NBeGlzTGV0dGVyICsgJ2F4aXMnXTtcblxuICAgIGlmKGF4aXMudGlja21vZGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgYXhpcy50aWNrdmFscyA9IGRhdGEuc2xpY2UoKTtcbiAgICB9XG5cbiAgICB2YXIgeGNwID0gdHJhY2UuX3hjdHJsO1xuICAgIHZhciB5Y3AgPSB0cmFjZS5feWN0cmw7XG4gICAgdmFyIG5lYSA9IHhjcFswXS5sZW5ndGg7XG4gICAgdmFyIG5lYiA9IHhjcC5sZW5ndGg7XG4gICAgdmFyIG5hID0gdHJhY2UuX2EubGVuZ3RoO1xuICAgIHZhciBuYiA9IHRyYWNlLl9iLmxlbmd0aDtcblxuICAgIEF4ZXMucHJlcFRpY2tzKGF4aXMpO1xuXG4gICAgLy8gZG9uJ3QgbGVhdmUgdGlja3ZhbHMgaW4gYXhpcyBsb29raW5nIGxpa2UgYW4gYXR0cmlidXRlXG4gICAgaWYoYXhpcy50aWNrbW9kZSA9PT0gJ2FycmF5JykgZGVsZXRlIGF4aXMudGlja3ZhbHM7XG5cbiAgICAvLyBUaGUgZGVmYXVsdCBpcyBhbiBlbXB0eSBhcnJheSB0aGF0IHdpbGwgY2F1c2UgdGhlIGpvaW4gdG8gcmVtb3ZlIHRoZSBncmlkbGluZSBpZlxuICAgIC8vIGl0J3MganVzdCBkaXNhcHBlYXJlZDpcbiAgICAvLyBheGlzLl9zdGFydGxpbmUgPSBheGlzLl9lbmRsaW5lID0gW107XG5cbiAgICAvLyBJZiB0aGUgY3Jvc3MgYXhpcyB1c2VzIGJpY3ViaWMgaW50ZXJwb2xhdGlvbiwgdGhlbiB0aGUgZ3JpZFxuICAgIC8vIGxpbmVzIGZhbGwgb25jZSBldmVyeSB0aHJlZSBleHBhbmRlZCBncmlkIHJvdy9jb2xzOlxuICAgIHZhciBzdHJpZGUgPSBheGlzLnNtb290aGluZyA/IDMgOiAxO1xuXG4gICAgZnVuY3Rpb24gY29uc3RydWN0VmFsdWVHcmlkbGluZSh2YWx1ZSkge1xuICAgICAgICB2YXIgaSwgaiwgajAsIHRqLCBweHksIGkwLCB0aSwgeHksIGR4eWRpMCwgZHh5ZGkxLCBkeHlkajAsIGR4eWRqMTtcbiAgICAgICAgdmFyIHhwb2ludHMgPSBbXTtcbiAgICAgICAgdmFyIHlwb2ludHMgPSBbXTtcbiAgICAgICAgdmFyIHJldCA9IHt9O1xuICAgICAgICAvLyBTZWFyY2ggZm9yIHRoZSBmcmFjdGlvbmFsIGdyaWQgaW5kZXggZ2l2aW5nIHRoaXMgbGluZTpcbiAgICAgICAgaWYoYXhpc0xldHRlciA9PT0gJ2InKSB7XG4gICAgICAgICAgICAvLyBGb3IgdGhlIHBvc2l0aW9uIHdlIHVzZSBqdXN0IHRoZSBpLWogY29vcmRpbmF0ZXM6XG4gICAgICAgICAgICBqID0gdHJhY2UuYjJqKHZhbHVlKTtcblxuICAgICAgICAgICAgLy8gVGhlIGRlcml2YXRpdmVzIGZvciBjYXRtdWxsLXJvbSBzcGxpbmVzIGFyZSBkaXNjb250aW51b3VzIGFjcm9zcyBjZWxsXG4gICAgICAgICAgICAvLyBib3VuZGFyaWVzIHRob3VnaCwgc28gd2UgbmVlZCB0byBwcm92aWRlIGJvdGggdGhlIGNlbGwgYW5kIHRoZSBwb3NpdGlvblxuICAgICAgICAgICAgLy8gd2l0aGluIHRoZSBjZWxsIHNlcGFyYXRlbHk6XG4gICAgICAgICAgICBqMCA9IE1hdGguZmxvb3IoTWF0aC5tYXgoMCwgTWF0aC5taW4obmIgLSAyLCBqKSkpO1xuICAgICAgICAgICAgdGogPSBqIC0gajA7XG5cbiAgICAgICAgICAgIHJldC5sZW5ndGggPSBuYjtcbiAgICAgICAgICAgIHJldC5jcm9zc0xlbmd0aCA9IG5hO1xuXG4gICAgICAgICAgICByZXQueHkgPSBmdW5jdGlvbihpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyYWNlLmV2YWx4eShbXSwgaSwgaik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXQuZHh5ID0gZnVuY3Rpb24oaTAsIHRpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyYWNlLmR4eWRpKFtdLCBpMCwgajAsIHRpLCB0aik7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBuYTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaTAgPSBNYXRoLm1pbihuYSAtIDIsIGkpO1xuICAgICAgICAgICAgICAgIHRpID0gaSAtIGkwO1xuICAgICAgICAgICAgICAgIHh5ID0gdHJhY2UuZXZhbHh5KFtdLCBpLCBqKTtcblxuICAgICAgICAgICAgICAgIGlmKGNyb3NzQXhpcy5zbW9vdGhpbmcgJiYgaSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyc3QgY29udHJvbCBwb2ludDpcbiAgICAgICAgICAgICAgICAgICAgZHh5ZGkwID0gdHJhY2UuZHh5ZGkoW10sIGkgLSAxLCBqMCwgMCwgdGopO1xuICAgICAgICAgICAgICAgICAgICB4cG9pbnRzLnB1c2gocHh5WzBdICsgZHh5ZGkwWzBdIC8gMyk7XG4gICAgICAgICAgICAgICAgICAgIHlwb2ludHMucHVzaChweHlbMV0gKyBkeHlkaTBbMV0gLyAzKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBTZWNvbmQgY29udHJvbCBwb2ludDpcbiAgICAgICAgICAgICAgICAgICAgZHh5ZGkxID0gdHJhY2UuZHh5ZGkoW10sIGkgLSAxLCBqMCwgMSwgdGopO1xuICAgICAgICAgICAgICAgICAgICB4cG9pbnRzLnB1c2goeHlbMF0gLSBkeHlkaTFbMF0gLyAzKTtcbiAgICAgICAgICAgICAgICAgICAgeXBvaW50cy5wdXNoKHh5WzFdIC0gZHh5ZGkxWzFdIC8gMyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgeHBvaW50cy5wdXNoKHh5WzBdKTtcbiAgICAgICAgICAgICAgICB5cG9pbnRzLnB1c2goeHlbMV0pO1xuXG4gICAgICAgICAgICAgICAgcHh5ID0geHk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpID0gdHJhY2UuYTJpKHZhbHVlKTtcbiAgICAgICAgICAgIGkwID0gTWF0aC5mbG9vcihNYXRoLm1heCgwLCBNYXRoLm1pbihuYSAtIDIsIGkpKSk7XG4gICAgICAgICAgICB0aSA9IGkgLSBpMDtcblxuICAgICAgICAgICAgcmV0Lmxlbmd0aCA9IG5hO1xuICAgICAgICAgICAgcmV0LmNyb3NzTGVuZ3RoID0gbmI7XG5cbiAgICAgICAgICAgIHJldC54eSA9IGZ1bmN0aW9uKGopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhY2UuZXZhbHh5KFtdLCBpLCBqKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJldC5keHkgPSBmdW5jdGlvbihqMCwgdGopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhY2UuZHh5ZGooW10sIGkwLCBqMCwgdGksIHRqKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5iOyBqKyspIHtcbiAgICAgICAgICAgICAgICBqMCA9IE1hdGgubWluKG5iIC0gMiwgaik7XG4gICAgICAgICAgICAgICAgdGogPSBqIC0gajA7XG4gICAgICAgICAgICAgICAgeHkgPSB0cmFjZS5ldmFseHkoW10sIGksIGopO1xuXG4gICAgICAgICAgICAgICAgaWYoY3Jvc3NBeGlzLnNtb290aGluZyAmJiBqID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBGaXJzdCBjb250cm9sIHBvaW50OlxuICAgICAgICAgICAgICAgICAgICBkeHlkajAgPSB0cmFjZS5keHlkaihbXSwgaTAsIGogLSAxLCB0aSwgMCk7XG4gICAgICAgICAgICAgICAgICAgIHhwb2ludHMucHVzaChweHlbMF0gKyBkeHlkajBbMF0gLyAzKTtcbiAgICAgICAgICAgICAgICAgICAgeXBvaW50cy5wdXNoKHB4eVsxXSArIGR4eWRqMFsxXSAvIDMpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFNlY29uZCBjb250cm9sIHBvaW50OlxuICAgICAgICAgICAgICAgICAgICBkeHlkajEgPSB0cmFjZS5keHlkaihbXSwgaTAsIGogLSAxLCB0aSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIHhwb2ludHMucHVzaCh4eVswXSAtIGR4eWRqMVswXSAvIDMpO1xuICAgICAgICAgICAgICAgICAgICB5cG9pbnRzLnB1c2goeHlbMV0gLSBkeHlkajFbMV0gLyAzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB4cG9pbnRzLnB1c2goeHlbMF0pO1xuICAgICAgICAgICAgICAgIHlwb2ludHMucHVzaCh4eVsxXSk7XG5cbiAgICAgICAgICAgICAgICBweHkgPSB4eTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldC5heGlzTGV0dGVyID0gYXhpc0xldHRlcjtcbiAgICAgICAgcmV0LmF4aXMgPSBheGlzO1xuICAgICAgICByZXQuY3Jvc3NBeGlzID0gY3Jvc3NBeGlzO1xuICAgICAgICByZXQudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgcmV0LmNvbnN0dmFyID0gY3Jvc3NBeGlzTGV0dGVyO1xuICAgICAgICByZXQuaW5kZXggPSBuO1xuICAgICAgICByZXQueCA9IHhwb2ludHM7XG4gICAgICAgIHJldC55ID0geXBvaW50cztcbiAgICAgICAgcmV0LnNtb290aGluZyA9IGNyb3NzQXhpcy5zbW9vdGhpbmc7XG5cbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb25zdHJ1Y3RBcnJheUdyaWRsaW5lKGlkeCkge1xuICAgICAgICB2YXIgaiwgaTAsIGowLCB0aSwgdGo7XG4gICAgICAgIHZhciB4cG9pbnRzID0gW107XG4gICAgICAgIHZhciB5cG9pbnRzID0gW107XG4gICAgICAgIHZhciByZXQgPSB7fTtcbiAgICAgICAgcmV0Lmxlbmd0aCA9IGRhdGEubGVuZ3RoO1xuICAgICAgICByZXQuY3Jvc3NMZW5ndGggPSBjcm9zc0RhdGEubGVuZ3RoO1xuXG4gICAgICAgIGlmKGF4aXNMZXR0ZXIgPT09ICdiJykge1xuICAgICAgICAgICAgajAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihuYiAtIDIsIGlkeCkpO1xuICAgICAgICAgICAgdGogPSBNYXRoLm1pbigxLCBNYXRoLm1heCgwLCBpZHggLSBqMCkpO1xuXG4gICAgICAgICAgICByZXQueHkgPSBmdW5jdGlvbihpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyYWNlLmV2YWx4eShbXSwgaSwgaWR4KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJldC5keHkgPSBmdW5jdGlvbihpMCwgdGkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhY2UuZHh5ZGkoW10sIGkwLCBqMCwgdGksIHRqKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8vIEluIHRoZSB0aWNrbW9kZTogYXJyYXkgY2FzZSwgdGhpcyBvcGVyYXRpb24gaXMgYSBzaW1wbGVcbiAgICAgICAgICAgIC8vIHRyYW5zZmVyIG9mIGRhdGE6XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBuZWE7IGorKykge1xuICAgICAgICAgICAgICAgIHhwb2ludHNbal0gPSB4Y3BbaWR4ICogc3RyaWRlXVtqXTtcbiAgICAgICAgICAgICAgICB5cG9pbnRzW2pdID0geWNwW2lkeCAqIHN0cmlkZV1bal07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKG5hIC0gMiwgaWR4KSk7XG4gICAgICAgICAgICB0aSA9IE1hdGgubWluKDEsIE1hdGgubWF4KDAsIGlkeCAtIGkwKSk7XG5cbiAgICAgICAgICAgIHJldC54eSA9IGZ1bmN0aW9uKGopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhY2UuZXZhbHh5KFtdLCBpZHgsIGopO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmV0LmR4eSA9IGZ1bmN0aW9uKGowLCB0aikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFjZS5keHlkaihbXSwgaTAsIGowLCB0aSwgdGopO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gSW4gdGhlIHRpY2ttb2RlOiBhcnJheSBjYXNlLCB0aGlzIG9wZXJhdGlvbiBpcyBhIHNpbXBsZVxuICAgICAgICAgICAgLy8gdHJhbnNmZXIgb2YgZGF0YTpcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5lYjsgaisrKSB7XG4gICAgICAgICAgICAgICAgeHBvaW50c1tqXSA9IHhjcFtqXVtpZHggKiBzdHJpZGVdO1xuICAgICAgICAgICAgICAgIHlwb2ludHNbal0gPSB5Y3Bbal1baWR4ICogc3RyaWRlXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldC5heGlzTGV0dGVyID0gYXhpc0xldHRlcjtcbiAgICAgICAgcmV0LmF4aXMgPSBheGlzO1xuICAgICAgICByZXQuY3Jvc3NBeGlzID0gY3Jvc3NBeGlzO1xuICAgICAgICByZXQudmFsdWUgPSBkYXRhW2lkeF07XG4gICAgICAgIHJldC5jb25zdHZhciA9IGNyb3NzQXhpc0xldHRlcjtcbiAgICAgICAgcmV0LmluZGV4ID0gaWR4O1xuICAgICAgICByZXQueCA9IHhwb2ludHM7XG4gICAgICAgIHJldC55ID0geXBvaW50cztcbiAgICAgICAgcmV0LnNtb290aGluZyA9IGNyb3NzQXhpcy5zbW9vdGhpbmc7XG5cbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG5cbiAgICBpZihheGlzLnRpY2ttb2RlID09PSAnYXJyYXknKSB7XG4gICAgICAgIC8vIHZhciBqMCA9IGF4aXMuc3RhcnRsaW5lID8gMSA6IDA7XG4gICAgICAgIC8vIHZhciBqMSA9IGRhdGEubGVuZ3RoIC0gKGF4aXMuZW5kbGluZSA/IDEgOiAwKTtcblxuICAgICAgICBlcHMgPSA1ZS0xNTtcbiAgICAgICAgYm91bmRzID0gW1xuICAgICAgICAgICAgTWF0aC5mbG9vcigoKGRhdGEubGVuZ3RoIC0gMSkgLSBheGlzLmFycmF5dGljazApIC8gYXhpcy5hcnJheWR0aWNrICogKDEgKyBlcHMpKSxcbiAgICAgICAgICAgIE1hdGguY2VpbCgoLSBheGlzLmFycmF5dGljazApIC8gYXhpcy5hcnJheWR0aWNrIC8gKDEgKyBlcHMpKVxuICAgICAgICBdLnNvcnQoZnVuY3Rpb24oYSwgYikge3JldHVybiBhIC0gYjt9KTtcblxuICAgICAgICAvLyBVbnBhY2sgc29ydGVkIHZhbHVlcyBzbyB3ZSBjYW4gYmUgc3VyZSB0byBhdm9pZCBpbmZpbml0ZSBsb29wcyBpZiBzb21ldGhpbmdcbiAgICAgICAgLy8gaXMgYmFja3dhcmRzOlxuICAgICAgICBuMSA9IGJvdW5kc1swXSAtIDE7XG4gICAgICAgIG4yID0gYm91bmRzWzFdICsgMTtcblxuICAgICAgICAvLyBJZiB0aGUgYXhlcyBmYWxsIGFsb25nIGFycmF5IGxpbmVzLCB0aGVuIHRoaXMgaXMgYSBtdWNoIHNpbXBsZXIgcHJvY2VzcyBzaW5jZVxuICAgICAgICAvLyB3ZSBhbHJlYWR5IGhhdmUgYWxsIHRoZSBjb250cm9sIHBvaW50cyB3ZSBuZWVkXG4gICAgICAgIGZvcihuID0gbjE7IG4gPCBuMjsgbisrKSB7XG4gICAgICAgICAgICBqID0gYXhpcy5hcnJheXRpY2swICsgYXhpcy5hcnJheWR0aWNrICogbjtcbiAgICAgICAgICAgIGlmKGogPCAwIHx8IGogPiBkYXRhLmxlbmd0aCAtIDEpIGNvbnRpbnVlO1xuICAgICAgICAgICAgZ3JpZGxpbmVzLnB1c2goZXh0ZW5kRmxhdChjb25zdHJ1Y3RBcnJheUdyaWRsaW5lKGopLCB7XG4gICAgICAgICAgICAgICAgY29sb3I6IGF4aXMuZ3JpZGNvbG9yLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBheGlzLmdyaWR3aWR0aFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yKG4gPSBuMTsgbiA8IG4yOyBuKyspIHtcbiAgICAgICAgICAgIGowID0gYXhpcy5hcnJheXRpY2swICsgYXhpcy5hcnJheWR0aWNrICogbjtcbiAgICAgICAgICAgIGoxID0gTWF0aC5taW4oajAgKyBheGlzLmFycmF5ZHRpY2ssIGRhdGEubGVuZ3RoIC0gMSk7XG5cbiAgICAgICAgICAgIC8vIFRPRE86IGZpeCB0aGUgYm91bmRzIGNvbXB1dGF0aW9uIHNvIHdlIGRvbid0IGhhdmUgdG8gZG8gYSBsYXJnZSByYW5nZSBhbmQgdGhlbiB0aHJvd1xuICAgICAgICAgICAgLy8gb3V0IHVubmVlZGVkIG51bWJlcnNcbiAgICAgICAgICAgIGlmKGowIDwgMCB8fCBqMCA+IGRhdGEubGVuZ3RoIC0gMSkgY29udGludWU7XG4gICAgICAgICAgICBpZihqMSA8IDAgfHwgajEgPiBkYXRhLmxlbmd0aCAtIDEpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB2MCA9IGRhdGFbajBdO1xuICAgICAgICAgICAgdjEgPSBkYXRhW2oxXTtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgYXhpcy5taW5vcmdyaWRjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZCA9IGoxIC0gajA7XG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBmaXggdGhlIGJvdW5kcyBjb21wdXRhdGlvbiBzbyB3ZSBkb24ndCBoYXZlIHRvIGRvIGEgbGFyZ2UgcmFuZ2UgYW5kIHRoZW4gdGhyb3dcbiAgICAgICAgICAgICAgICAvLyBvdXQgdW5uZWVkZWQgbnVtYmVyc1xuICAgICAgICAgICAgICAgIGlmKGQgPD0gMCkgY29udGludWU7XG5cbiAgICAgICAgICAgICAgICAvLyBYWFg6IFRoaXMgY2FsY3VsYXRpb24gaXNuJ3QgcXVpdGUgcmlnaHQuIE9mZiBieSBvbmUgc29tZXdoZXJlP1xuICAgICAgICAgICAgICAgIHYgPSB2MCArICh2MSAtIHYwKSAqIChpICsgMSkgLyAoYXhpcy5taW5vcmdyaWRjb3VudCArIDEpICogKGF4aXMuYXJyYXlkdGljayAvIGQpO1xuXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogZml4IHRoZSBib3VuZHMgY29tcHV0YXRpb24gc28gd2UgZG9uJ3QgaGF2ZSB0byBkbyBhIGxhcmdlIHJhbmdlIGFuZCB0aGVuIHRocm93XG4gICAgICAgICAgICAgICAgLy8gb3V0IHVubmVlZGVkIG51bWJlcnNcbiAgICAgICAgICAgICAgICBpZih2IDwgZGF0YVswXSB8fCB2ID4gZGF0YVtkYXRhLmxlbmd0aCAtIDFdKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBtaW5vcmdyaWRsaW5lcy5wdXNoKGV4dGVuZEZsYXQoY29uc3RydWN0VmFsdWVHcmlkbGluZSh2KSwge1xuICAgICAgICAgICAgICAgICAgICBjb2xvcjogYXhpcy5taW5vcmdyaWRjb2xvcixcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IGF4aXMubWlub3Jncmlkd2lkdGhcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihheGlzLnN0YXJ0bGluZSkge1xuICAgICAgICAgICAgYm91bmRhcnlsaW5lcy5wdXNoKGV4dGVuZEZsYXQoY29uc3RydWN0QXJyYXlHcmlkbGluZSgwKSwge1xuICAgICAgICAgICAgICAgIGNvbG9yOiBheGlzLnN0YXJ0bGluZWNvbG9yLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBheGlzLnN0YXJ0bGluZXdpZHRoXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihheGlzLmVuZGxpbmUpIHtcbiAgICAgICAgICAgIGJvdW5kYXJ5bGluZXMucHVzaChleHRlbmRGbGF0KGNvbnN0cnVjdEFycmF5R3JpZGxpbmUoZGF0YS5sZW5ndGggLSAxKSwge1xuICAgICAgICAgICAgICAgIGNvbG9yOiBheGlzLmVuZGxpbmVjb2xvcixcbiAgICAgICAgICAgICAgICB3aWR0aDogYXhpcy5lbmRsaW5ld2lkdGhcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIElmIHRoZSBsaW5lcyBkbyBub3QgZmFsbCBhbG9uZyB0aGUgYXhlcywgdGhlbiB3ZSBoYXZlIHRvIGludGVycG9sYXRlXG4gICAgICAgIC8vIHRoZSBjb250cm8gcG9pbnRzIGFuZCBzbyBzb21lIG1hdGggdG8gZmlndXJlIG91dCB3aGVyZSB0aGUgbGluZXMgYXJlXG4gICAgICAgIC8vIGluIHRoZSBmaXJzdCBwbGFjZS5cblxuICAgICAgICAvLyBDb21wdXRlIHRoZSBpbnRlZ2VyIGJvdWRucyBvZiB0aWNrMCArIG4gKiBkdGljayB0aGF0IGZhbGwgd2l0aGluIHRoZSByYW5nZVxuICAgICAgICAvLyAocm91Z2hseSBzcGVha2luZyk6XG4gICAgICAgIC8vIEdpdmUgdGhpcyBhIG5pY2UgZ2VuZXJvdXMgZXBzaWxvbi4gV2UgdXNlIGF0IGFzICogKDEgKyBlcHMpIGluIG9yZGVyIHRvIG1ha2VcbiAgICAgICAgLy8gaW5lcXVhbGl0aWVzIGEgbGl0dGxlIHRvbGVyYW50IGluIGEgbW9yZSBvciBsZXNzIGNvcnJlY3QgbWFubmVyOlxuICAgICAgICBlcHMgPSA1ZS0xNTtcbiAgICAgICAgYm91bmRzID0gW1xuICAgICAgICAgICAgTWF0aC5mbG9vcigoZGF0YVtkYXRhLmxlbmd0aCAtIDFdIC0gYXhpcy50aWNrMCkgLyBheGlzLmR0aWNrICogKDEgKyBlcHMpKSxcbiAgICAgICAgICAgIE1hdGguY2VpbCgoZGF0YVswXSAtIGF4aXMudGljazApIC8gYXhpcy5kdGljayAvICgxICsgZXBzKSlcbiAgICAgICAgXS5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtyZXR1cm4gYSAtIGI7fSk7XG5cbiAgICAgICAgLy8gVW5wYWNrIHNvcnRlZCB2YWx1ZXMgc28gd2UgY2FuIGJlIHN1cmUgdG8gYXZvaWQgaW5maW5pdGUgbG9vcHMgaWYgc29tZXRoaW5nXG4gICAgICAgIC8vIGlzIGJhY2t3YXJkczpcbiAgICAgICAgbjEgPSBib3VuZHNbMF07XG4gICAgICAgIG4yID0gYm91bmRzWzFdO1xuXG4gICAgICAgIGZvcihuID0gbjE7IG4gPD0gbjI7IG4rKykge1xuICAgICAgICAgICAgdmFsdWUgPSBheGlzLnRpY2swICsgYXhpcy5kdGljayAqIG47XG5cbiAgICAgICAgICAgIGdyaWRsaW5lcy5wdXNoKGV4dGVuZEZsYXQoY29uc3RydWN0VmFsdWVHcmlkbGluZSh2YWx1ZSksIHtcbiAgICAgICAgICAgICAgICBjb2xvcjogYXhpcy5ncmlkY29sb3IsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGF4aXMuZ3JpZHdpZHRoXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IobiA9IG4xIC0gMTsgbiA8IG4yICsgMTsgbisrKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGF4aXMudGljazAgKyBheGlzLmR0aWNrICogbjtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgYXhpcy5taW5vcmdyaWRjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdiA9IHZhbHVlICsgYXhpcy5kdGljayAqIChpICsgMSkgLyAoYXhpcy5taW5vcmdyaWRjb3VudCArIDEpO1xuICAgICAgICAgICAgICAgIGlmKHYgPCBkYXRhWzBdIHx8IHYgPiBkYXRhW2RhdGEubGVuZ3RoIC0gMV0pIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIG1pbm9yZ3JpZGxpbmVzLnB1c2goZXh0ZW5kRmxhdChjb25zdHJ1Y3RWYWx1ZUdyaWRsaW5lKHYpLCB7XG4gICAgICAgICAgICAgICAgICAgIGNvbG9yOiBheGlzLm1pbm9yZ3JpZGNvbG9yLFxuICAgICAgICAgICAgICAgICAgICB3aWR0aDogYXhpcy5taW5vcmdyaWR3aWR0aFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF4aXMuc3RhcnRsaW5lKSB7XG4gICAgICAgICAgICBib3VuZGFyeWxpbmVzLnB1c2goZXh0ZW5kRmxhdChjb25zdHJ1Y3RWYWx1ZUdyaWRsaW5lKGRhdGFbMF0pLCB7XG4gICAgICAgICAgICAgICAgY29sb3I6IGF4aXMuc3RhcnRsaW5lY29sb3IsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGF4aXMuc3RhcnRsaW5ld2lkdGhcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGF4aXMuZW5kbGluZSkge1xuICAgICAgICAgICAgYm91bmRhcnlsaW5lcy5wdXNoKGV4dGVuZEZsYXQoY29uc3RydWN0VmFsdWVHcmlkbGluZShkYXRhW2RhdGEubGVuZ3RoIC0gMV0pLCB7XG4gICAgICAgICAgICAgICAgY29sb3I6IGF4aXMuZW5kbGluZWNvbG9yLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBheGlzLmVuZGxpbmV3aWR0aFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3Njd9XSw5MDU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGNMYWJlbHModHJhY2UsIGF4aXMpIHtcbiAgICB2YXIgaSwgdG9iaiwgcHJlZml4LCBzdWZmaXgsIGdyaWRsaW5lO1xuXG4gICAgdmFyIGxhYmVscyA9IGF4aXMuX2xhYmVscyA9IFtdO1xuICAgIHZhciBncmlkbGluZXMgPSBheGlzLl9ncmlkbGluZXM7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBncmlkbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZ3JpZGxpbmUgPSBncmlkbGluZXNbaV07XG5cbiAgICAgICAgaWYoWydzdGFydCcsICdib3RoJ10uaW5kZXhPZihheGlzLnNob3d0aWNrbGFiZWxzKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHRvYmogPSBBeGVzLnRpY2tUZXh0KGF4aXMsIGdyaWRsaW5lLnZhbHVlKTtcblxuICAgICAgICAgICAgZXh0ZW5kRmxhdCh0b2JqLCB7XG4gICAgICAgICAgICAgICAgcHJlZml4OiBwcmVmaXgsXG4gICAgICAgICAgICAgICAgc3VmZml4OiBzdWZmaXgsXG4gICAgICAgICAgICAgICAgZW5kQW5jaG9yOiB0cnVlLFxuICAgICAgICAgICAgICAgIHh5OiBncmlkbGluZS54eSgwKSxcbiAgICAgICAgICAgICAgICBkeHk6IGdyaWRsaW5lLmR4eSgwLCAwKSxcbiAgICAgICAgICAgICAgICBheGlzOiBncmlkbGluZS5heGlzLFxuICAgICAgICAgICAgICAgIGxlbmd0aDogZ3JpZGxpbmUuY3Jvc3NBeGlzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICBmb250OiBncmlkbGluZS5heGlzLnRpY2tmb250LFxuICAgICAgICAgICAgICAgIGlzRmlyc3Q6IGkgPT09IDAsXG4gICAgICAgICAgICAgICAgaXNMYXN0OiBpID09PSBncmlkbGluZXMubGVuZ3RoIC0gMVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGxhYmVscy5wdXNoKHRvYmopO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoWydlbmQnLCAnYm90aCddLmluZGV4T2YoYXhpcy5zaG93dGlja2xhYmVscykgIT09IC0xKSB7XG4gICAgICAgICAgICB0b2JqID0gQXhlcy50aWNrVGV4dChheGlzLCBncmlkbGluZS52YWx1ZSk7XG5cbiAgICAgICAgICAgIGV4dGVuZEZsYXQodG9iaiwge1xuICAgICAgICAgICAgICAgIGVuZEFuY2hvcjogZmFsc2UsXG4gICAgICAgICAgICAgICAgeHk6IGdyaWRsaW5lLnh5KGdyaWRsaW5lLmNyb3NzTGVuZ3RoIC0gMSksXG4gICAgICAgICAgICAgICAgZHh5OiBncmlkbGluZS5keHkoZ3JpZGxpbmUuY3Jvc3NMZW5ndGggLSAyLCAxKSxcbiAgICAgICAgICAgICAgICBheGlzOiBncmlkbGluZS5heGlzLFxuICAgICAgICAgICAgICAgIGxlbmd0aDogZ3JpZGxpbmUuY3Jvc3NBeGlzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICBmb250OiBncmlkbGluZS5heGlzLnRpY2tmb250LFxuICAgICAgICAgICAgICAgIGlzRmlyc3Q6IGkgPT09IDAsXG4gICAgICAgICAgICAgICAgaXNMYXN0OiBpID09PSBncmlkbGluZXMubGVuZ3RoIC0gMVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGxhYmVscy5wdXNoKHRvYmopO1xuICAgICAgICB9XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3Njd9XSw5MDY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogQ29tcHV0ZSB0aGUgdGFuZ2VudCB2ZWN0b3IgYWNjb3JkaW5nIHRvIGNhdG11bGwtcm9tIGN1YmljIHNwbGluZXMgKGNlbnRyaXBldGFsLFxuICogSSB0aGluaykuIFRoYXQgZGlmZmVycyBmcm9tIHRoZSBjb250cm9sIHBvaW50IGluIHR3byB3YXlzOlxuICogICAxLiBJdCBpcyBhIHZlY3Rvciwgbm90IGEgcG9zaXRpb24gcmVsYXRpdmUgdG8gdGhlIHBvaW50XG4gKiAgIDIuIHRoZSB2ZWN0b3IgaXMgbG9uZ2VyIHRoYW4gdGhlIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHAxIGJ5IGEgZmFjdG9yIG9mIDNcbiAqXG4gKiBDbG9zZSB0byB0aGUgYm91bmRhcmllcywgd2UnbGwgdXNlIHRoZXNlIGFzICpxdWFkcmF0aWMgY29udHJvbCBwb2ludHMsIHNvIHRoYXRcbiAqIHRvIG1ha2UgYSBuaWNlIGdyaWQsIHdlJ2xsIG5lZWQgdG8gZGl2aWRlIHRoZSB0YW5nZW50IGJ5IDIgaW5zdGVhZCBvZiAzLiAoVGhlXG4gKiBtYXRoIHdvcmtzIG91dCB0aGlzIHdheSBpZiB5b3Ugd29yayB0aHJvdWdoIHRoZSBiZXppZXIgZGVyaXZhdGl2ZXMpXG4gKi9cbnZhciBDYXRtdWxsUm9tRXhwID0gMC41O1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlQ29udHJvbFBvaW50cyhwMCwgcDEsIHAyLCBzbW9vdGhuZXNzKSB7XG4gICAgdmFyIGQxeCA9IHAwWzBdIC0gcDFbMF07XG4gICAgdmFyIGQxeSA9IHAwWzFdIC0gcDFbMV07XG4gICAgdmFyIGQyeCA9IHAyWzBdIC0gcDFbMF07XG4gICAgdmFyIGQyeSA9IHAyWzFdIC0gcDFbMV07XG4gICAgdmFyIGQxYSA9IE1hdGgucG93KGQxeCAqIGQxeCArIGQxeSAqIGQxeSwgQ2F0bXVsbFJvbUV4cCAvIDIpO1xuICAgIHZhciBkMmEgPSBNYXRoLnBvdyhkMnggKiBkMnggKyBkMnkgKiBkMnksIENhdG11bGxSb21FeHAgLyAyKTtcbiAgICB2YXIgbnVteCA9IChkMmEgKiBkMmEgKiBkMXggLSBkMWEgKiBkMWEgKiBkMngpICogc21vb3RobmVzcztcbiAgICB2YXIgbnVteSA9IChkMmEgKiBkMmEgKiBkMXkgLSBkMWEgKiBkMWEgKiBkMnkpICogc21vb3RobmVzcztcbiAgICB2YXIgZGVub20xID0gZDJhICogKGQxYSArIGQyYSkgKiAzO1xuICAgIHZhciBkZW5vbTIgPSBkMWEgKiAoZDFhICsgZDJhKSAqIDM7XG5cbiAgICByZXR1cm4gW1tcbiAgICAgICAgcDFbMF0gKyAoZGVub20xICYmIG51bXggLyBkZW5vbTEpLFxuICAgICAgICBwMVsxXSArIChkZW5vbTEgJiYgbnVteSAvIGRlbm9tMSlcbiAgICBdLCBbXG4gICAgICAgIHAxWzBdIC0gKGRlbm9tMiAmJiBudW14IC8gZGVub20yKSxcbiAgICAgICAgcDFbMV0gLSAoZGVub20yICYmIG51bXkgLyBkZW5vbTIpXG4gICAgXV07XG59O1xuXG59LHt9XSw5MDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG5cbi8qXG4gKiBDb25zdHJ1Y3QgYSAyRCBhcnJheSBvZiBjaGVhdGVyIHZhbHVlcyBnaXZlbiBhLCBiLCBhbmQgYSBzbG9wZS5cbiAqIElmXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oYSwgYiwgY2hlYXRlcnNsb3BlKSB7XG4gICAgdmFyIGksIGosIGFzY2FsLCBic2NhbCwgYXZhbCwgYnZhbDtcbiAgICB2YXIgZGF0YSA9IFtdO1xuXG4gICAgdmFyIG5hID0gaXNBcnJheU9yVHlwZWRBcnJheShhKSA/IGEubGVuZ3RoIDogYTtcbiAgICB2YXIgbmIgPSBpc0FycmF5T3JUeXBlZEFycmF5KGIpID8gYi5sZW5ndGggOiBiO1xuICAgIHZhciBhZGF0YSA9IGlzQXJyYXlPclR5cGVkQXJyYXkoYSkgPyBhIDogbnVsbDtcbiAgICB2YXIgYmRhdGEgPSBpc0FycmF5T3JUeXBlZEFycmF5KGIpID8gYiA6IG51bGw7XG5cbiAgICAvLyBJZiB3ZSdyZSB1c2luZyBkYXRhLCBzY2FsZSBpdCBzbyB0aGF0IGZvciBkYXRhIHRoYXQncyBqdXN0IGJhcmVseVxuICAgIC8vIG5vdCBldmVubHkgc3BhY2VkLCB0aGUgc3dpdGNoIHRvIHZhbHVlLWJhc2VkIGluZGV4aW5nIGlzIGNvbnRpbnVvdXMuXG4gICAgLy8gVGhpcyBtZWFucyBldmVubHkgc3BhY2VkIGRhdGEgc2hvdWxkIGxvb2sgdGhlIHNhbWUgd2hldGhlciB2YWx1ZVxuICAgIC8vIG9yIGluZGV4IGNoZWF0ZXJ0eXBlLlxuICAgIGlmKGFkYXRhKSB7XG4gICAgICAgIGFzY2FsID0gKGFkYXRhLmxlbmd0aCAtIDEpIC8gKGFkYXRhW2FkYXRhLmxlbmd0aCAtIDFdIC0gYWRhdGFbMF0pIC8gKG5hIC0gMSk7XG4gICAgfVxuXG4gICAgaWYoYmRhdGEpIHtcbiAgICAgICAgYnNjYWwgPSAoYmRhdGEubGVuZ3RoIC0gMSkgLyAoYmRhdGFbYmRhdGEubGVuZ3RoIC0gMV0gLSBiZGF0YVswXSkgLyAobmIgLSAxKTtcbiAgICB9XG5cbiAgICB2YXIgeHZhbDtcbiAgICB2YXIgeG1pbiA9IEluZmluaXR5O1xuICAgIHZhciB4bWF4ID0gLUluZmluaXR5O1xuICAgIGZvcihqID0gMDsgaiA8IG5iOyBqKyspIHtcbiAgICAgICAgZGF0YVtqXSA9IFtdO1xuICAgICAgICBidmFsID0gYmRhdGEgPyAoYmRhdGFbal0gLSBiZGF0YVswXSkgKiBic2NhbCA6IGogLyAobmIgLSAxKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbmE7IGkrKykge1xuICAgICAgICAgICAgYXZhbCA9IGFkYXRhID8gKGFkYXRhW2ldIC0gYWRhdGFbMF0pICogYXNjYWwgOiBpIC8gKG5hIC0gMSk7XG4gICAgICAgICAgICB4dmFsID0gYXZhbCAtIGJ2YWwgKiBjaGVhdGVyc2xvcGU7XG4gICAgICAgICAgICB4bWluID0gTWF0aC5taW4oeHZhbCwgeG1pbik7XG4gICAgICAgICAgICB4bWF4ID0gTWF0aC5tYXgoeHZhbCwgeG1heCk7XG4gICAgICAgICAgICBkYXRhW2pdW2ldID0geHZhbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vcm1hbGl6ZSBjaGVhdGVyIHZhbHVlcyB0byB0aGUgMC0xIHJhbmdlLiBUaGlzIGNvbWVzIGludG8gcGxheSB3aGVuIHlvdSBoYXZlXG4gICAgLy8gbXVsdGlwbGUgY2hlYXRlciBwbG90cy4gQWZ0ZXIgY2FyZWZ1bCBjb25zaWRlcmF0aW9uLCBpdCBzZWVtcyBiZXR0ZXIgaWYgY2hlYXRlclxuICAgIC8vIHZhbHVlcyBhcmUgbm9ybWFsaXplZCB0byBhIGNvbnNpc3RlbnQgcmFuZ2UuIE90aGVyd2lzZSBvbmUgY2hlYXRlciBhZmZlY3RzIHRoZVxuICAgIC8vIGxheW91dCBvZiBvdGhlciBjaGVhdGVycyBvbiB0aGUgc2FtZSBheGlzLlxuICAgIHZhciBzbG9wZSA9IDEuMCAvICh4bWF4IC0geG1pbik7XG4gICAgdmFyIG9mZnNldCA9IC14bWluICogc2xvcGU7XG4gICAgZm9yKGogPSAwOyBqIDwgbmI7IGorKykge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBuYTsgaSsrKSB7XG4gICAgICAgICAgICBkYXRhW2pdW2ldID0gc2xvcGUgKiBkYXRhW2pdW2ldICsgb2Zmc2V0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGRhdGE7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOX1dLDkwODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBtYWtlQ29udHJvbFBvaW50cyA9IF9kZXJlcV8oJy4vY2F0bXVsbF9yb20nKTtcbnZhciBlbnN1cmVBcnJheSA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmVuc3VyZUFycmF5O1xuXG4vKlxuICogVHVybnMgYSBjb2Fyc2UgZ3JpZCBpbnRvIGEgZmluZSBncmlkIHdpdGggY29udHJvbCBwb2ludHMuXG4gKlxuICogSGVyZSdzIGFuIEFTQ0lJIHJlcHJlc2VudGF0aW9uOlxuICpcbiAqICAgICAgIG8gLS0tLS0gbyAtLS0tLSBvIC0tLS0tIG9cbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIG8gLS0tLS0gbyAtLS0tLSBvIC0tLS0tIG9cbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgIF4gIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgIHwgIG8gLS0tLS0gbyAtLS0tLSBvIC0tLS0tIG9cbiAqICBiIHwgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgIHwgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgIHwgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIG8gLS0tLS0gbyAtLS0tLSBvIC0tLS0tIG9cbiAqICAgICAgICAgLS0tLS0tPlxuICogICAgICAgICAgIGFcbiAqXG4gKiBGaXJzdCBvZiBhbGwsIG5vdGUgdGhhdCB3ZSB3YW50IHRvIGRvIHRoaXMgaW4gKmNhcnRlc2lhbiogc3BhY2UuIFRoaXMgbWVhbnNcbiAqIHdlIG1pZ2h0IHJ1biBpbnRvIHByb2JsZW1zIHdoZW4gdGhlcmUgYXJlIGV4dHJlbWUgZGlmZmVyZW5jZXMgaW4geC95IHNjYWxpbmcsXG4gKiBidXQgdGhlIGFsdGVybmF0aXZlIGlzIHRoYXQgdGhlIHRvcG9sb2d5IG9mIHRoZSBjb250b3VycyBtaWdodCBhY3R1YWxseSBiZVxuICogdmlldy1kZXBlbmRlbnQsIHdoaWNoIHNlZW1zIHdvcnNlLiBBcyBhIGZhbGxiYWNrLCB0aGUgb25seSBwYXJhbWV0ZXIgdGhhdFxuICogYWN0dWFsbHkgYWZmZWN0cyB0aGUgcmVzdWx0IGlzIHRoZSAqYXNwZWN0IHJhdGlvKiwgc28gdGhhdCB3ZSBjYW4gYXQgbGVhc3RcbiAqIGltcHJvdmUgdGhlIHNpdHVhdGlvbiBhIGJpdCB3aXRob3V0IGdvaW5nIGFsbCB0aGUgd2F5IHRvIHNjcmVlbiBjb29yZGluYXRlcy5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGZsYXR0ZW5zIHRoZSBwb2ludHMgKyB0YW5nZW50cyAgaW50byBhIHNsaWdodGx5IGRlbnNlciBncmlkIG9mXG4gKiAqY29udHJvbCBwb2ludHMqLiBUaGUgcmVzdWx0aW5nIGdyaWQgbG9va3MgbGlrZSB0aGlzOlxuICpcbiAqICAgICAgIDkgKy0tby1vLS0rIC1vLW8tLSstLW8tby0tK1xuICogICAgICAgOCBvICBvIG8gIG8gIG8gbyAgbyAgbyBvICBvXG4gKiAgICAgICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAqICAgICAgIDcgbyAgbyBvICBvICBvIG8gIG8gIG8gbyAgb1xuICogICAgICAgNiArLS1vLW8tLSsgLW8tby0tKy0tby1vLS0rXG4gKiAgICAgICA1IG8gIG8gbyAgbyAgbyBvICBvICBvIG8gIG9cbiAqICAgICAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICogICAgXiAgNCBvICBvIG8gIG8gIG8gbyAgbyAgbyBvICBvXG4gKiAgICB8ICAzICstLW8tby0tKyAtby1vLS0rLS1vLW8tLStcbiAqICBiIHwgIDIgbyAgbyBvICBvICBvIG8gIG8gIG8gbyAgb1xuICogICAgfCAgICB8ICAgICAgIHwgICAgICAgfCAgICAgICB8XG4gKiAgICB8ICAxIG8gIG8gbyAgbyAgbyBvICBvICBvIG8gIG9cbiAqICAgICAgIDAgKy0tby1vLS0rIC1vLW8tLSstLW8tby0tK1xuICogICAgICAgICAwICAxIDIgIDMgIDQgNSAgNiAgNyA4ICA5XG4gKiAgICAgICAgIC0tLS0tLT5cbiAqICAgICAgICAgICBhXG4gKlxuICogd2hlcmUgYG9gcyByZXByZXNlbnQgbmV3bHktY29tcHV0ZWQgY29udHJvbCBwb2ludHMuIHRoZSByZXN1bHRpbmcgZGltZW5zaW9uIGlzXG4gKlxuICogICAgIChtIC0gMSkgKiAzICsgMVxuICogICA9IDMgKiBtIC0gMlxuICpcbiAqIFdlIGNvdWxkIHNpbXBseSBzdG9yZSB0aGUgdGFuZ2VudHMgc2VwYXJhdGVseSwgYnV0IHRoYXQncyBhIG5pZ2h0bWFyZSB0byBvcmdhbml6ZVxuICogaW4gdHdvIGRpbWVuc2lvbnMgc2luY2Ugd2UnbGwgYmUgc2xpY2luZyBncmlkIGxpbmVzIGluIGJvdGggZGlyZWN0aW9ucyBhbmQgc2luY2VcbiAqIHRoYXQgYmFzaWNhbGx5IHJlcXVpcmVzIHZlcnkgbmVhcmx5IGp1c3QgYXMgbXVjaCBzdG9yYWdlIGFzIGp1c3Qgc3RvcmluZyB0aGUgZGVuc2VcbiAqIGdyaWQuXG4gKlxuICogV293IVxuICovXG5cblxuLypcbiAqIENhdG11bGwtcm9tIGlzIGJpYXNlZCBhdCB0aGUgYm91bmRhcmllcyB0b3dhcmQgdGhlIGludGVyaW9yIGFuZCB3ZSBhY3R1YWxseVxuICogY2FuJ3QgdXNlIGNhdG11bGwtcm9tIHRvIGNvbXB1dGUgdGhlIGNvbnRyb2wgcG9pbnQgY2xvc2VzdCB0byAoYnV0IGluc2lkZSlcbiAqIHRoZSBib3VuZGFyeS5cbiAqXG4gKiBBIG5vdGUgb24gcGxvdGx5J3Mgc3BsaW5lIGludGVycG9sYXRpb24uIEl0IHVzZXMgdGhlIGNhdG11bGwgcm9tIGNvbnRyb2wgcG9pbnRcbiAqIGNsb3Nlc3QgdG8gdGhlIGJvdW5kYXJ5ICphcyogYSBxdWFkcmF0aWMgY29udHJvbCBwb2ludC4gVGhpcyBzZWVtcyBpbmNvcnJlY3QsXG4gKiBzbyBJJ3ZlIGVsZWN0ZWQgbm90IHRvIGZvbGxvdyB0aGF0LiBHaXZlbiBjb250cm9sIHBvaW50cyAwIGFuZCAxLCByZWd1bGFyIHBsb3RseVxuICogc3BsaW5lcyBnaXZlICplcXVpdmFsZW50KiBjdWJpYyBjb250cm9sIHBvaW50czpcbiAqXG4gKiBJbnB1dDpcbiAqXG4gKiAgIGJvdW5kYXJ5XG4gKiAgICAgfCAgICAgICAgICAgICAgICAgICAgfFxuICogICAgIHAwICAgICAgICAgICBwMiAgICAgIHAzICAgIC0tPiBpbnRlcmlvclxuICogICAgIDAuMCAgICAgICAgICAwLjY2NyAgIDEuMFxuICogICAgIHwgICAgICAgICAgICAgICAgICAgIHxcbiAqXG4gKiBDdWJpYy1lcXVpdmFsZW50IG9mIHdoYXQgcGxvdGx5IHNwbGluZXMgZHJhdzo6XG4gKlxuICogICBib3VuZGFyeVxuICogICAgIHwgICAgICAgICAgICAgICAgICAgIHxcbiAqICAgICBwMCAgIHAxICAgICAgcDIgICAgICBwMyAgICAtLT4gaW50ZXJpb3JcbiAqICAgICAwLjAgIDAuNDQ0NCAgMC44ODg4ICAxLjBcbiAqICAgICB8ICAgICAgICAgICAgICAgICAgICB8XG4gKlxuICogV2hhdCB0aGlzIGZ1bmN0aW9uIGZpbGxzIGluOlxuICpcbiAqICAgYm91bmRhcnlcbiAqICAgICB8ICAgICAgICAgICAgICAgICAgICB8XG4gKiAgICAgcDAgICAgcDEgICAgIHAyICAgICAgcDMgICAgLS0+IGludGVyaW9yXG4gKiAgICAgMC4wICAgMC4zMzMgIDAuNjY3ICAgMS4wXG4gKiAgICAgfCAgICAgICAgICAgICAgICAgICAgfFxuICpcbiAqIFBhcmFtZXRlcnM6XG4gKiAgIHAwOiBib3VuZGFyeSBwb2ludFxuICogICBwMjogY2F0bXVsbCByb20gcG9pbnQgYmFzZWQgb24gY29tcHV0YXRpb24gYXQgcDNcbiAqICAgcDM6IGZpcnN0IGdyaWQgcG9pbnRcbiAqXG4gKiBPZiBjb3Vyc2UgaXQgd29ya3Mgd2hpY2hldmVyIHdheSBpdCdzIG9yaWVudGVkOyB5b3UganVzdCBuZWVkIHRvIGludGVycHJldCB0aGVcbiAqIGlucHV0L291dHB1dCBhY2NvcmRpbmdseS5cbiAqL1xuZnVuY3Rpb24gaW5mZXJDdWJpY0NvbnRyb2xQb2ludChwMCwgcDIsIHAzKSB7XG4gICAgLy8gRXh0ZW5kIHAxIGF3YXkgZnJvbSBwMCBieSA1MCUuIFRoaXMgaXMgdGhlIGVxdWl2YWxlbnQgcXVhZHJhdGljIHBvaW50IHRoYXRcbiAgICAvLyB3b3VsZCBnaXZlIHRoZSBzYW1lIHNsb3BlIGFzIGNhdG11bGwgcm9tIGF0IHAwLlxuICAgIHZhciBwMmUwID0gLTAuNSAqIHAzWzBdICsgMS41ICogcDJbMF07XG4gICAgdmFyIHAyZTEgPSAtMC41ICogcDNbMV0gKyAxLjUgKiBwMlsxXTtcblxuICAgIHJldHVybiBbXG4gICAgICAgICgyICogcDJlMCArIHAwWzBdKSAvIDMsXG4gICAgICAgICgyICogcDJlMSArIHAwWzFdKSAvIDMsXG4gICAgXTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb21wdXRlQ29udHJvbFBvaW50cyh4ZSwgeWUsIHgsIHksIGFzbW9vdGhpbmcsIGJzbW9vdGhpbmcpIHtcbiAgICB2YXIgaSwgaiwgaWUsIGplLCB4ZWosIHllaiwgeGosIHlqLCBjcCwgcDE7XG4gICAgLy8gQXQgdGhpcyBwb2ludCwgd2Uga25vdyB0aGVzZSBkaW1lbnNpb25zIGFyZSBjb3JyZWN0IGFuZCByZXByZXNlbnRhdGl2ZSBvZlxuICAgIC8vIHRoZSB3aG9sZSAyRCBhcnJheXM6XG4gICAgdmFyIG5hID0geFswXS5sZW5ndGg7XG4gICAgdmFyIG5iID0geC5sZW5ndGg7XG5cbiAgICAvLyAobil1bWJlciBvZiAoZSl4cGFuZGVkIHBvaW50czpcbiAgICB2YXIgbmVhID0gYXNtb290aGluZyA/IDMgKiBuYSAtIDIgOiBuYTtcbiAgICB2YXIgbmViID0gYnNtb290aGluZyA/IDMgKiBuYiAtIDIgOiBuYjtcblxuICAgIHhlID0gZW5zdXJlQXJyYXkoeGUsIG5lYik7XG4gICAgeWUgPSBlbnN1cmVBcnJheSh5ZSwgbmViKTtcblxuICAgIGZvcihpZSA9IDA7IGllIDwgbmViOyBpZSsrKSB7XG4gICAgICAgIHhlW2llXSA9IGVuc3VyZUFycmF5KHhlW2llXSwgbmVhKTtcbiAgICAgICAgeWVbaWVdID0gZW5zdXJlQXJyYXkoeWVbaWVdLCBuZWEpO1xuICAgIH1cblxuICAgIC8vIFRoaXMgbG9vcCBmaWxscyBpbiB0aGUgWCdkIHBvaW50czpcbiAgICAvL1xuICAgIC8vICAgIC4gICAgICAgLiAgICAgICAuICAgICAgIC5cbiAgICAvLyAgICAuICAgICAgIC4gICAgICAgLiAgICAgICAuXG4gICAgLy8gICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgIC8vICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAgICAvLyAgICBYIC0tLS0tIFggLS0tLS0gWCAtLS0tLSBYXG4gICAgLy8gICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgIC8vICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAgICAvLyAgICB8ICAgICAgIHwgICAgICAgfCAgICAgICB8XG4gICAgLy8gICAgWCAtLS0tLSBYIC0tLS0tIFggLS0tLS0gWFxuICAgIC8vXG4gICAgLy9cbiAgICAvLyBpZSA9IChpKSAoZSl4cGFuZGVkOlxuICAgIGZvcihqID0gMCwgamUgPSAwOyBqIDwgbmI7IGorKywgamUgKz0gYnNtb290aGluZyA/IDMgOiAxKSB7XG4gICAgICAgIHhlaiA9IHhlW2plXTtcbiAgICAgICAgeWVqID0geWVbamVdO1xuICAgICAgICB4aiA9IHhbal07XG4gICAgICAgIHlqID0geVtqXTtcblxuICAgICAgICAvLyBqZSA9IChqKSAoZSl4cGFuZGVkOlxuICAgICAgICBmb3IoaSA9IDAsIGllID0gMDsgaSA8IG5hOyBpKyssIGllICs9IGFzbW9vdGhpbmcgPyAzIDogMSkge1xuICAgICAgICAgICAgeGVqW2llXSA9IHhqW2ldO1xuICAgICAgICAgICAgeWVqW2llXSA9IHlqW2ldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoYXNtb290aGluZykge1xuICAgICAgICAvLyBJZiB0aGVyZSdzIGEtc21vb3RoaW5nLCB0aGlzIGxvb3AgZmlsbHMgaW4gdGhlIFgnZCBwb2ludHMgd2l0aCBjYXRtdWxsLXJvbVxuICAgICAgICAvLyBjb250cm9sIHBvaW50cyBjb21wdXRlZCBhbG9uZyB0aGUgYS1heGlzOlxuICAgICAgICAvLyAgICAgLiAgICAgICAuICAgICAgIC4gICAgICAgLlxuICAgICAgICAvLyAgICAgLiAgICAgICAuICAgICAgIC4gICAgICAgLlxuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgbyAtWS1YLSBvIC1YLVgtIG8gLVgtWS0gb1xuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgfCAgICAgICB8ICAgICAgIHwgICAgICAgfFxuICAgICAgICAvLyAgICAgbyAtWS1YLSBvIC1YLVgtIG8gLVgtWS0gb1xuICAgICAgICAvL1xuICAgICAgICAvLyBpOiAgMCAgICAgICAxICAgICAgIDIgICAgICAgM1xuICAgICAgICAvLyBpZTogMCAgMSAzICAzICA0IDUgIDYgIDcgOCAgOVxuICAgICAgICAvL1xuICAgICAgICAvLyAgICAgICAgICAgLS0tLS0tPlxuICAgICAgICAvLyAgICAgICAgICAgICBhXG4gICAgICAgIC8vXG4gICAgICAgIGZvcihqID0gMCwgamUgPSAwOyBqIDwgbmI7IGorKywgamUgKz0gYnNtb290aGluZyA/IDMgOiAxKSB7XG4gICAgICAgICAgICAvLyBGaWxsIGluIHRoZSBwb2ludHMgbWFya2VkIFggZm9yIHRoaXMgYS1yb3c6XG4gICAgICAgICAgICBmb3IoaSA9IDEsIGllID0gMzsgaSA8IG5hIC0gMTsgaSsrLCBpZSArPSAzKSB7XG4gICAgICAgICAgICAgICAgY3AgPSBtYWtlQ29udHJvbFBvaW50cyhcbiAgICAgICAgICAgICAgICAgICAgW3hbal1baSAtIDFdLCB5W2pdW2kgLSAxXV0sXG4gICAgICAgICAgICAgICAgICAgIFt4W2pdW2kgXSwgeVtqXVtpXV0sXG4gICAgICAgICAgICAgICAgICAgIFt4W2pdW2kgKyAxXSwgeVtqXVtpICsgMV1dLFxuICAgICAgICAgICAgICAgICAgICBhc21vb3RoaW5nXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIHhlW2plXVtpZSAtIDFdID0gY3BbMF1bMF07XG4gICAgICAgICAgICAgICAgeWVbamVdW2llIC0gMV0gPSBjcFswXVsxXTtcbiAgICAgICAgICAgICAgICB4ZVtqZV1baWUgKyAxXSA9IGNwWzFdWzBdO1xuICAgICAgICAgICAgICAgIHllW2plXVtpZSArIDFdID0gY3BbMV1bMV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRoZSB2ZXJ5IGZpcnN0IGN1YmljIGludGVycG9sYXRpb24gcG9pbnQgKHRvIHRoZSBsZWZ0IGZvciBpID0gMSBhYm92ZSkgaXNcbiAgICAgICAgICAgIC8vIHVzZWQgYXMgYSAqcXVhZHJhdGljKiBpbnRlcnBvbGF0aW9uIHBvaW50IGJ5IHRoZSBzcGxpbmUgZHJhd2luZyBmdW5jdGlvblxuICAgICAgICAgICAgLy8gd2hpY2ggaXNuJ3QgcmVhbGx5IGNvcnJlY3QuIEJ1dCBmb3IgdGhlIHNha2Ugb2YgY29uc2lzdGVuY3ksIHdlJ2xsIHVzZSBpdFxuICAgICAgICAgICAgLy8gYXMgc3VjaC4gU2luY2Ugd2UncmUgdXNpbmcgY3ViaWMgc3BsaW5lcywgdGhhdCBtZWFucyB3ZSBuZWVkIHRvIHNob3J0ZW4gdGhlXG4gICAgICAgICAgICAvLyB0YW5nZW50IGJ5IDEvMyBhbmQgYWxzbyBjb25zdHJ1Y3QgYSBuZXcgY3ViaWMgc3BsaW5lIGNvbnRyb2wgcG9pbnQgMS8zIGZyb21cbiAgICAgICAgICAgIC8vIHRoZSBvcmlnaW5hbCB0byB0aGUgaSA9IDAgcG9pbnQuXG4gICAgICAgICAgICBwMSA9IGluZmVyQ3ViaWNDb250cm9sUG9pbnQoXG4gICAgICAgICAgICAgICAgW3hlW2plXVswXSwgeWVbamVdWzBdXSxcbiAgICAgICAgICAgICAgICBbeGVbamVdWzJdLCB5ZVtqZV1bMl1dLFxuICAgICAgICAgICAgICAgIFt4ZVtqZV1bM10sIHllW2plXVszXV1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB4ZVtqZV1bMV0gPSBwMVswXTtcbiAgICAgICAgICAgIHllW2plXVsxXSA9IHAxWzFdO1xuXG4gICAgICAgICAgICAvLyBEaXR0byBsYXN0IHBvaW50cywgc2FucyBleHBsYW5hdGlvbjpcbiAgICAgICAgICAgIHAxID0gaW5mZXJDdWJpY0NvbnRyb2xQb2ludChcbiAgICAgICAgICAgICAgICBbeGVbamVdW25lYSAtIDFdLCB5ZVtqZV1bbmVhIC0gMV1dLFxuICAgICAgICAgICAgICAgIFt4ZVtqZV1bbmVhIC0gM10sIHllW2plXVtuZWEgLSAzXV0sXG4gICAgICAgICAgICAgICAgW3hlW2plXVtuZWEgLSA0XSwgeWVbamVdW25lYSAtIDRdXVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHhlW2plXVtuZWEgLSAyXSA9IHAxWzBdO1xuICAgICAgICAgICAgeWVbamVdW25lYSAtIDJdID0gcDFbMV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihic21vb3RoaW5nKSB7XG4gICAgICAgIC8vIElmIHRoZXJlJ3MgYS1zbW9vdGhpbmcsIHRoaXMgbG9vcCBmaWxscyBpbiB0aGUgWCdkIHBvaW50cyB3aXRoIGNhdG11bGwtcm9tXG4gICAgICAgIC8vIGNvbnRyb2wgcG9pbnRzIGNvbXB1dGVkIGFsb25nIHRoZSBiLWF4aXM6XG4gICAgICAgIC8vICAgICAuICAgICAgIC4gICAgICAgLiAgICAgICAuXG4gICAgICAgIC8vICAgICBYICBYIFggIFggIFggWCAgWCAgWCBYICBYXG4gICAgICAgIC8vICAgICB8ICAgICAgIHwgICAgICAgfCAgICAgICB8XG4gICAgICAgIC8vICAgICBYICBYIFggIFggIFggWCAgWCAgWCBYICBYXG4gICAgICAgIC8vICAgICBvIC1vLW8tIG8gLW8tby0gbyAtby1vLSBvXG4gICAgICAgIC8vICAgICBYICBYIFggIFggIFggWCAgWCAgWCBYICBYXG4gICAgICAgIC8vICAgICB8ICAgICAgIHwgICAgICAgfCAgICAgICB8XG4gICAgICAgIC8vICAgICBZICBZIFkgIFkgIFkgWSAgWSAgWSBZICBZXG4gICAgICAgIC8vICAgICBvIC1vLW8tIG8gLW8tby0gbyAtby1vLSBvXG4gICAgICAgIC8vXG4gICAgICAgIC8vIGk6ICAwICAgICAgIDEgICAgICAgMiAgICAgICAzXG4gICAgICAgIC8vIGllOiAwICAxIDMgIDMgIDQgNSAgNiAgNyA4ICA5XG4gICAgICAgIC8vXG4gICAgICAgIC8vICAgICAgICAgICAtLS0tLS0+XG4gICAgICAgIC8vICAgICAgICAgICAgIGFcbiAgICAgICAgLy9cbiAgICAgICAgZm9yKGllID0gMDsgaWUgPCBuZWE7IGllKyspIHtcbiAgICAgICAgICAgIGZvcihqZSA9IDM7IGplIDwgbmViIC0gMzsgamUgKz0gMykge1xuICAgICAgICAgICAgICAgIGNwID0gbWFrZUNvbnRyb2xQb2ludHMoXG4gICAgICAgICAgICAgICAgICAgIFt4ZVtqZSAtIDNdW2llXSwgeWVbamUgLSAzXVtpZV1dLFxuICAgICAgICAgICAgICAgICAgICBbeGVbamVdW2llXSwgeWVbamVdW2llXV0sXG4gICAgICAgICAgICAgICAgICAgIFt4ZVtqZSArIDNdW2llXSwgeWVbamUgKyAzXVtpZV1dLFxuICAgICAgICAgICAgICAgICAgICBic21vb3RoaW5nXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIHhlW2plIC0gMV1baWVdID0gY3BbMF1bMF07XG4gICAgICAgICAgICAgICAgeWVbamUgLSAxXVtpZV0gPSBjcFswXVsxXTtcbiAgICAgICAgICAgICAgICB4ZVtqZSArIDFdW2llXSA9IGNwWzFdWzBdO1xuICAgICAgICAgICAgICAgIHllW2plICsgMV1baWVdID0gY3BbMV1bMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBEbyB0aGUgc2FtZSBib3VuZGFyeSBjb25kaXRpb24gbWFnaWMgZm9yIHRoZXNlIGNvbnRyb2wgcG9pbnRzIG1hcmtlZCBZIGFib3ZlOlxuICAgICAgICAgICAgcDEgPSBpbmZlckN1YmljQ29udHJvbFBvaW50KFxuICAgICAgICAgICAgICAgIFt4ZVswXVtpZV0sIHllWzBdW2llXV0sXG4gICAgICAgICAgICAgICAgW3hlWzJdW2llXSwgeWVbMl1baWVdXSxcbiAgICAgICAgICAgICAgICBbeGVbM11baWVdLCB5ZVszXVtpZV1dXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgeGVbMV1baWVdID0gcDFbMF07XG4gICAgICAgICAgICB5ZVsxXVtpZV0gPSBwMVsxXTtcblxuICAgICAgICAgICAgcDEgPSBpbmZlckN1YmljQ29udHJvbFBvaW50KFxuICAgICAgICAgICAgICAgIFt4ZVtuZWIgLSAxXVtpZV0sIHllW25lYiAtIDFdW2llXV0sXG4gICAgICAgICAgICAgICAgW3hlW25lYiAtIDNdW2llXSwgeWVbbmViIC0gM11baWVdXSxcbiAgICAgICAgICAgICAgICBbeGVbbmViIC0gNF1baWVdLCB5ZVtuZWIgLSA0XVtpZV1dXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgeGVbbmViIC0gMl1baWVdID0gcDFbMF07XG4gICAgICAgICAgICB5ZVtuZWIgLSAyXVtpZV0gPSBwMVsxXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGFzbW9vdGhpbmcgJiYgYnNtb290aGluZykge1xuICAgICAgICAvLyBEbyBvbmUgbW9yZSBwYXNzLCB0aGlzIHRpbWUgcmVjb21wdXRpbmcgZXhhY3RseSB3aGF0IHdlIGp1c3QgY29tcHV0ZWQuXG4gICAgICAgIC8vIEl0J3Mgb3ZlcmRldGVybWluZWQgc2luY2Ugd2UncmUgcGVmb3JtaW5nIGNhdG11bGwtcm9tIGluIHR3byBkaXJlY3Rpb25zLFxuICAgICAgICAvLyBzbyB3ZSdsbCBqdXN0IGF2ZXJhZ2UgdGhlIG92ZXJkZXRlcm1pbmVkLiBUaGVzZSBwb2ludHMgZG9uJ3QgbGllIGFsb25nIHRoZVxuICAgICAgICAvLyBncmlkIGxpbmVzLCBzbyBub3RlIHRoYXQgb25seSBncmlkIGxpbmVzIHdpbGwgZm9sbG93IG5vcm1hbCBwbG90bHkgc3BsaW5lXG4gICAgICAgIC8vIGludGVycG9sYXRpb24uXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFVubGVzcyBvZiBjb3Vyc2UgdGhlcmUgd2FzIG5vIGIgc21vb3RoaW5nLiBUaGVuIHRoZXNlIGludGVybWVkaWF0ZSBwb2ludHNcbiAgICAgICAgLy8gZG9uJ3QgYWN0dWFsbHkgZXhpc3QgYW5kIHRoaXMgc2VjdGlvbiBpcyBieXBhc3NlZC5cbiAgICAgICAgLy8gICAgIC4gICAgICAgLiAgICAgICAuICAgICAgIC5cbiAgICAgICAgLy8gICAgIG8gIFggWCAgbyAgWCBYICBvICBYIFggIG9cbiAgICAgICAgLy8gICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAgICAgICAgLy8gICAgIG8gIFggWCAgbyAgWCBYICBvICBYIFggIG9cbiAgICAgICAgLy8gICAgIG8gLW8tby0gbyAtby1vLSBvIC1vLW8tIG9cbiAgICAgICAgLy8gICAgIG8gIFggWCAgbyAgWCBYICBvICBYIFggIG9cbiAgICAgICAgLy8gICAgIHwgICAgICAgfCAgICAgICB8ICAgICAgIHxcbiAgICAgICAgLy8gICAgIG8gIFkgWSAgbyAgWSBZICBvICBZIFkgIG9cbiAgICAgICAgLy8gICAgIG8gLW8tby0gbyAtby1vLSBvIC1vLW8tIG9cbiAgICAgICAgLy9cbiAgICAgICAgLy8gaTogIDAgICAgICAgMSAgICAgICAyICAgICAgIDNcbiAgICAgICAgLy8gaWU6IDAgIDEgMyAgMyAgNCA1ICA2ICA3IDggIDlcbiAgICAgICAgLy9cbiAgICAgICAgLy8gICAgICAgICAgIC0tLS0tLT5cbiAgICAgICAgLy8gICAgICAgICAgICAgYVxuICAgICAgICAvL1xuICAgICAgICBmb3IoamUgPSAxOyBqZSA8IG5lYjsgamUgKz0gKGplICsgMSkgJSAzID09PSAwID8gMiA6IDEpIHtcbiAgICAgICAgICAgIC8vIEZpbGwgaW4gdGhlIHBvaW50cyBtYXJrZWQgWCBmb3IgdGhpcyBhLXJvdzpcbiAgICAgICAgICAgIGZvcihpZSA9IDM7IGllIDwgbmVhIC0gMzsgaWUgKz0gMykge1xuICAgICAgICAgICAgICAgIGNwID0gbWFrZUNvbnRyb2xQb2ludHMoXG4gICAgICAgICAgICAgICAgICAgIFt4ZVtqZV1baWUgLSAzXSwgeWVbamVdW2llIC0gM11dLFxuICAgICAgICAgICAgICAgICAgICBbeGVbamVdW2llXSwgeWVbamVdW2llXV0sXG4gICAgICAgICAgICAgICAgICAgIFt4ZVtqZV1baWUgKyAzXSwgeWVbamVdW2llICsgM11dLFxuICAgICAgICAgICAgICAgICAgICBhc21vb3RoaW5nXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIHhlW2plXVtpZSAtIDFdID0gMC41ICogKHhlW2plXVtpZSAtIDFdICsgY3BbMF1bMF0pO1xuICAgICAgICAgICAgICAgIHllW2plXVtpZSAtIDFdID0gMC41ICogKHllW2plXVtpZSAtIDFdICsgY3BbMF1bMV0pO1xuICAgICAgICAgICAgICAgIHhlW2plXVtpZSArIDFdID0gMC41ICogKHhlW2plXVtpZSArIDFdICsgY3BbMV1bMF0pO1xuICAgICAgICAgICAgICAgIHllW2plXVtpZSArIDFdID0gMC41ICogKHllW2plXVtpZSArIDFdICsgY3BbMV1bMV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBUaGlzIGNhc2UgaXMganVzdCBzbGlnaHRseSBkaWZmZXJlbnQuIFRoZSBjb21wdXRhdGlvbiBpcyB0aGUgc2FtZSxcbiAgICAgICAgICAgIC8vIGJ1dCBoYXZpbmcgY29tcHV0ZWQgdGhpcywgd2UnbGwgYXZlcmFnZSB3aXRoIHRoZSBleGlzdGluZyByZXN1bHQuXG4gICAgICAgICAgICBwMSA9IGluZmVyQ3ViaWNDb250cm9sUG9pbnQoXG4gICAgICAgICAgICAgICAgW3hlW2plXVswXSwgeWVbamVdWzBdXSxcbiAgICAgICAgICAgICAgICBbeGVbamVdWzJdLCB5ZVtqZV1bMl1dLFxuICAgICAgICAgICAgICAgIFt4ZVtqZV1bM10sIHllW2plXVszXV1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB4ZVtqZV1bMV0gPSAwLjUgKiAoeGVbamVdWzFdICsgcDFbMF0pO1xuICAgICAgICAgICAgeWVbamVdWzFdID0gMC41ICogKHllW2plXVsxXSArIHAxWzFdKTtcblxuICAgICAgICAgICAgcDEgPSBpbmZlckN1YmljQ29udHJvbFBvaW50KFxuICAgICAgICAgICAgICAgIFt4ZVtqZV1bbmVhIC0gMV0sIHllW2plXVtuZWEgLSAxXV0sXG4gICAgICAgICAgICAgICAgW3hlW2plXVtuZWEgLSAzXSwgeWVbamVdW25lYSAtIDNdXSxcbiAgICAgICAgICAgICAgICBbeGVbamVdW25lYSAtIDRdLCB5ZVtqZV1bbmVhIC0gNF1dXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgeGVbamVdW25lYSAtIDJdID0gMC41ICogKHhlW2plXVtuZWEgLSAyXSArIHAxWzBdKTtcbiAgICAgICAgICAgIHllW2plXVtuZWEgLSAyXSA9IDAuNSAqICh5ZVtqZV1bbmVhIC0gMl0gKyBwMVsxXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gW3hlLCB5ZV07XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4vY2F0bXVsbF9yb21cIjo5MDZ9XSw5MDk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIFJFTEFUSVZFX0NVTExfVE9MRVJBTkNFOiAxZS02XG59O1xuXG59LHt9XSw5MTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogRXZhbHVhdGVzIHRoZSBkZXJpdmF0aXZlIG9mIGEgbGlzdCBvZiBjb250cm9sIHBvaW50IGFycmF5cy4gVGhhdCBpcywgaXQgZXhwZWN0cyBhbiBhcnJheSBvciBhcnJheXNcbiAqIHRoYXQgYXJlIGV4cGFuZGVkIHJlbGF0aXZlIHRvIHRoZSByYXcgZGF0YSB0byBpbmNsdWRlIHRoZSBiaWN1YmljIGNvbnRyb2wgcG9pbnRzLCBpZiBhcHBsaWNhYmxlLiBJZlxuICogb25seSBsaW5lYXIgaW50ZXJwb2xhdGlvbiBpcyBkZXNpcmVkLCB0aGVuIHRoZSBkYXRhIHBvaW50cyBjb3JyZXNwb25kIDEtMSBhbG9uZyB0aGF0IGF4aXMgdG8gdGhlXG4gKiBkYXRhIGl0c2VsZi4gU2luY2UgaXQncyBjYXRtdWxsLXJvbSBzcGxpbmVzIGluIGVpdGhlciBkaXJlY3Rpb24gbm90ZSBpbiBwYXJ0aWN1bGFyIHRoYXQgdGhlXG4gKiBkZXJpdmF0aXZlcyBhcmUgZGlzY29udGludW91cyBhY3Jvc3MgY2VsbCBib3VuZGFyaWVzLiBUaGF0J3MgdGhlIHJlYXNvbiB5b3UgbmVlZCBib3RoIHRoZSAqY2VsbCpcbiAqIGFuZCB0aGUgKnBvaW50IHdpdGhpbiB0aGUgY2VsbCouXG4gKlxuICogQWxzbyBub3RlIHRoYXQgdGhlIGRpc2NvbnRpbnVpdHkgb2YgdGhlIGRlcml2YXRpdmUgaXMgaW4gbWFnbml0dWRlIG9ubHkuIFRoZSBkaXJlY3Rpb24gKmlzKlxuICogY29udGludW91cyBhY3Jvc3MgY2VsbCBib3VuZGFyaWVzLlxuICpcbiAqIEZvciBleGFtcGxlLCB0byBjb21wdXRlIHRoZSBkZXJpdmF0aXZlIG9mIHRoZSB4Y29vcmRpbmF0ZSBoYWxmd2F5IGJldHdlbiB0aGUgNyBhbmQgOHRoIGktZ3JpZHBvaW50c1xuICogYW5kIHRoZSAxMHRoIGFuZCAxMXRoIGotZ3JpZHBvaW50cyBnaXZlbiBiaWN1YmljIHNtb290aGluZyBpbiBib3RoIGRpbWVuc2lvbnMsIHlvdSdkIHdyaXRlOlxuICpcbiAqICAgICB2YXIgZGVyaXYgPSBjcmVhdGVJRGVyaXZhdGl2ZUV2YWx1YXRvcihbeF0sIDEsIDEpO1xuICpcbiAqICAgICB2YXIgZHhkaSA9IGRlcml2KFtdLCA3LCAxMCwgMC41LCAwLjUpO1xuICogICAgIC8vID0+IFswLjEyMzQ1XVxuICpcbiAqIFNpbmNlIHRoZXJlJ2QgYmUgYSBidW5jaCBvZiBkdXBsaWNhdGUgY29tcHV0YXRpb24gdG8gY29tcHV0ZSBtdWx0aXBsZSBkZXJpdmF0aXZlcywgeW91IGNhbiBkb3VibGVcbiAqIHRoaXMgdXAgYnkgcHJvdmlkaW5nIG1vcmUgYXJyYXlzOlxuICpcbiAqICAgICB2YXIgZGVyaXYgPSBjcmVhdGVJRGVyaXZhdGl2ZUV2YWx1YXRvcihbeCwgeV0sIDEsIDEpO1xuICpcbiAqICAgICB2YXIgZHhkaSA9IGRlcml2KFtdLCA3LCAxMCwgMC41LCAwLjUpO1xuICogICAgIC8vID0+IFswLjEyMzQ1LCAwLjc4OTEwXVxuICpcbiAqIE5COiBJdCdzIHByZXN1bWVkIHRoYXQgYXQgdGhpcyBwb2ludCBhbGwgZGF0YSBoYXMgYmVlbiBzYW5pdGl6ZWQgYW5kIGlzIHZhbGlkIG51bWVyaWNhbCBkYXRhIGFycmF5c1xuICogb2YgdGhlIGNvcnJlY3QgZGltZW5zaW9uLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGFycmF5cywgYXNtb290aGluZywgYnNtb290aGluZykge1xuICAgIGlmKGFzbW9vdGhpbmcgJiYgYnNtb290aGluZykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBpMCwgajAsIHUsIHYpIHtcbiAgICAgICAgICAgIGlmKCFvdXQpIG91dCA9IFtdO1xuICAgICAgICAgICAgdmFyIGYwLCBmMSwgZjIsIGYzLCBhaywgaztcblxuICAgICAgICAgICAgLy8gU2luY2UgaXQncyBhIGdyaWQgb2YgY29udHJvbCBwb2ludHMsIHRoZSBhY3R1YWwgaW5kaWNlcyBhcmUgKiAzOlxuICAgICAgICAgICAgaTAgKj0gMztcbiAgICAgICAgICAgIGowICo9IDM7XG5cbiAgICAgICAgICAgIC8vIFByZWNvbXB1dGUgc29tZSBudW1iZXJzOlxuICAgICAgICAgICAgdmFyIHUyID0gdSAqIHU7XG4gICAgICAgICAgICB2YXIgb3UgPSAxIC0gdTtcbiAgICAgICAgICAgIHZhciBvdTIgPSBvdSAqIG91O1xuICAgICAgICAgICAgdmFyIG91dTIgPSBvdSAqIHUgKiAyO1xuICAgICAgICAgICAgdmFyIGEgPSAtMyAqIG91MjtcbiAgICAgICAgICAgIHZhciBiID0gMyAqIChvdTIgLSBvdXUyKTtcbiAgICAgICAgICAgIHZhciBjID0gMyAqIChvdXUyIC0gdTIpO1xuICAgICAgICAgICAgdmFyIGQgPSAzICogdTI7XG5cbiAgICAgICAgICAgIHZhciB2MiA9IHYgKiB2O1xuICAgICAgICAgICAgdmFyIHYzID0gdjIgKiB2O1xuICAgICAgICAgICAgdmFyIG92ID0gMSAtIHY7XG4gICAgICAgICAgICB2YXIgb3YyID0gb3YgKiBvdjtcbiAgICAgICAgICAgIHZhciBvdjMgPSBvdjIgKiBvdjtcblxuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgLy8gQ29tcHV0ZSB0aGUgZGVyaXZhdGl2ZXMgaW4gdGhlIHUtZGlyZWN0aW9uOlxuICAgICAgICAgICAgICAgIGYwID0gYSAqIGFrW2owIF1baTBdICsgYiAqIGFrW2owIF1baTAgKyAxXSArIGMgKiBha1tqMCBdW2kwICsgMl0gKyBkICogYWtbajAgXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIGYxID0gYSAqIGFrW2owICsgMV1baTBdICsgYiAqIGFrW2owICsgMV1baTAgKyAxXSArIGMgKiBha1tqMCArIDFdW2kwICsgMl0gKyBkICogYWtbajAgKyAxXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIGYyID0gYSAqIGFrW2owICsgMl1baTBdICsgYiAqIGFrW2owICsgMl1baTAgKyAxXSArIGMgKiBha1tqMCArIDJdW2kwICsgMl0gKyBkICogYWtbajAgKyAyXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIGYzID0gYSAqIGFrW2owICsgM11baTBdICsgYiAqIGFrW2owICsgM11baTAgKyAxXSArIGMgKiBha1tqMCArIDNdW2kwICsgMl0gKyBkICogYWtbajAgKyAzXVtpMCArIDNdO1xuXG4gICAgICAgICAgICAgICAgLy8gTm93IGp1c3QgaW50ZXJwb2xhdGUgaW4gdGhlIHYtZGlyZWN0aW9uIHNpbmNlIGl0J3MgYWxsIHNlcGFyYWJsZTpcbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdjMgKiBmMCArIDMgKiAob3YyICogdiAqIGYxICsgb3YgKiB2MiAqIGYyKSArIHYzICogZjM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIGlmKGFzbW9vdGhpbmcpIHtcbiAgICAgICAgLy8gSGFuZGxlIHNtb290aCBpbiB0aGUgYS1kaXJlY3Rpb24gYnV0IGxpbmVhciBpbiB0aGUgYi1kaXJlY3Rpb24gYnkgcGVyZm9ybWluZyBmb3VyXG4gICAgICAgIC8vIGxpbmVhciBpbnRlcnBvbGF0aW9ucyBmb2xsb3dlZCBieSBvbmUgY3ViaWMgaW50ZXJwb2xhdGlvbiBvZiB0aGUgcmVzdWx0XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGkwLCBqMCwgdSwgdikge1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBrLCBhaztcbiAgICAgICAgICAgIGkwICo9IDM7XG4gICAgICAgICAgICB2YXIgdTIgPSB1ICogdTtcbiAgICAgICAgICAgIHZhciBvdSA9IDEgLSB1O1xuICAgICAgICAgICAgdmFyIG91MiA9IG91ICogb3U7XG4gICAgICAgICAgICB2YXIgb3V1MiA9IG91ICogdSAqIDI7XG4gICAgICAgICAgICB2YXIgYSA9IC0zICogb3UyO1xuICAgICAgICAgICAgdmFyIGIgPSAzICogKG91MiAtIG91dTIpO1xuICAgICAgICAgICAgdmFyIGMgPSAzICogKG91dTIgLSB1Mik7XG4gICAgICAgICAgICB2YXIgZCA9IDMgKiB1MjtcbiAgICAgICAgICAgIHZhciBvdiA9IDEgLSB2O1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgZjAgPSBhICogYWtbajAgXVtpMF0gKyBiICogYWtbajAgXVtpMCArIDFdICsgYyAqIGFrW2owIF1baTAgKyAyXSArIGQgKiBha1tqMCBdW2kwICsgM107XG4gICAgICAgICAgICAgICAgZjEgPSBhICogYWtbajAgKyAxXVtpMF0gKyBiICogYWtbajAgKyAxXVtpMCArIDFdICsgYyAqIGFrW2owICsgMV1baTAgKyAyXSArIGQgKiBha1tqMCArIDFdW2kwICsgM107XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdiAqIGYwICsgdiAqIGYxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYoYnNtb290aGluZykge1xuICAgICAgICAvLyBTYW1lIGFzIHRoZSBhYm92ZSBjYXNlLCBleGNlcHQgcmV2ZXJzZWQuIEkndmUgZGlzYWJsZWQgdGhlIG5vLXVudXNlZCB2YXJzIHJ1bGVcbiAgICAgICAgLy8gc28gdGhhdCB0aGlzIGZ1bmN0aW9uIGlzIGZ1bGx5IGludGVycG9sYXRpb24tYWdub3N0aWMuIE90aGVyd2lzZSBpdCB3b3VsZCBuZWVkXG4gICAgICAgIC8vIHRvIGJlIGNhbGxlZCBkaWZmZXJlbnRseSBpbiBkaWZmZXJlbnQgY2FzZXMuIFdoaWNoIHdvdWxkbid0IGJlIHRoZSB3b3JzdCwgYnV0XG4gICAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGkwLCBqMCwgdSwgdikge1xuICAgICAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLXVudXNlZC12YXJzICovXG4gICAgICAgICAgICBpZighb3V0KSBvdXQgPSBbXTtcbiAgICAgICAgICAgIHZhciBmMCwgZjEsIGYyLCBmMywgaywgYWs7XG4gICAgICAgICAgICBqMCAqPSAzO1xuICAgICAgICAgICAgdmFyIHYyID0gdiAqIHY7XG4gICAgICAgICAgICB2YXIgdjMgPSB2MiAqIHY7XG4gICAgICAgICAgICB2YXIgb3YgPSAxIC0gdjtcbiAgICAgICAgICAgIHZhciBvdjIgPSBvdiAqIG92O1xuICAgICAgICAgICAgdmFyIG92MyA9IG92MiAqIG92O1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgZjAgPSBha1tqMF1baTAgKyAxXSAtIGFrW2owXVtpMF07XG4gICAgICAgICAgICAgICAgZjEgPSBha1tqMCArIDFdW2kwICsgMV0gLSBha1tqMCArIDFdW2kwXTtcbiAgICAgICAgICAgICAgICBmMiA9IGFrW2owICsgMl1baTAgKyAxXSAtIGFrW2owICsgMl1baTBdO1xuICAgICAgICAgICAgICAgIGYzID0gYWtbajAgKyAzXVtpMCArIDFdIC0gYWtbajAgKyAzXVtpMF07XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdjMgKiBmMCArIDMgKiAob3YyICogdiAqIGYxICsgb3YgKiB2MiAqIGYyKSArIHYzICogZjM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEZpbmFsbHksIGJvdGggZGlyZWN0aW9ucyBhcmUgbGluZWFyOlxuICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqL1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBpMCwgajAsIHUsIHYpIHtcbiAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby11bnVzZWQtdmFycyAqL1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBrLCBhaztcbiAgICAgICAgICAgIHZhciBvdiA9IDEgLSB2O1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgZjAgPSBha1tqMF1baTAgKyAxXSAtIGFrW2owXVtpMF07XG4gICAgICAgICAgICAgICAgZjEgPSBha1tqMCArIDFdW2kwICsgMV0gLSBha1tqMCArIDFdW2kwXTtcblxuICAgICAgICAgICAgICAgIG91dFtrXSA9IG92ICogZjAgKyB2ICogZjE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH1cbn07XG5cbn0se31dLDkxMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oYXJyYXlzLCBhc21vb3RoaW5nLCBic21vb3RoaW5nKSB7XG4gICAgaWYoYXNtb290aGluZyAmJiBic21vb3RoaW5nKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGkwLCBqMCwgdSwgdikge1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBmMiwgZjMsIGFrLCBrO1xuXG4gICAgICAgICAgICAvLyBTaW5jZSBpdCdzIGEgZ3JpZCBvZiBjb250cm9sIHBvaW50cywgdGhlIGFjdHVhbCBpbmRpY2VzIGFyZSAqIDM6XG4gICAgICAgICAgICBpMCAqPSAzO1xuICAgICAgICAgICAgajAgKj0gMztcblxuICAgICAgICAgICAgLy8gUHJlY29tcHV0ZSBzb21lIG51bWJlcnM6XG4gICAgICAgICAgICB2YXIgdTIgPSB1ICogdTtcbiAgICAgICAgICAgIHZhciB1MyA9IHUyICogdTtcbiAgICAgICAgICAgIHZhciBvdSA9IDEgLSB1O1xuICAgICAgICAgICAgdmFyIG91MiA9IG91ICogb3U7XG4gICAgICAgICAgICB2YXIgb3UzID0gb3UyICogb3U7XG5cbiAgICAgICAgICAgIHZhciB2MiA9IHYgKiB2O1xuICAgICAgICAgICAgdmFyIG92ID0gMSAtIHY7XG4gICAgICAgICAgICB2YXIgb3YyID0gb3YgKiBvdjtcbiAgICAgICAgICAgIHZhciBvdnYyID0gb3YgKiB2ICogMjtcbiAgICAgICAgICAgIHZhciBhID0gLTMgKiBvdjI7XG4gICAgICAgICAgICB2YXIgYiA9IDMgKiAob3YyIC0gb3Z2Mik7XG4gICAgICAgICAgICB2YXIgYyA9IDMgKiAob3Z2MiAtIHYyKTtcbiAgICAgICAgICAgIHZhciBkID0gMyAqIHYyO1xuXG4gICAgICAgICAgICBmb3IoayA9IDA7IGsgPCBhcnJheXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBhayA9IGFycmF5c1trXTtcblxuICAgICAgICAgICAgICAgIC8vIENvbXB1dGUgdGhlIGRlcml2YXRpdmVzIGluIHRoZSB2LWRpcmVjdGlvbjpcbiAgICAgICAgICAgICAgICBmMCA9IGEgKiBha1tqMF1baTBdICsgYiAqIGFrW2owICsgMV1baTBdICsgYyAqIGFrW2owICsgMl1baTBdICsgZCAqIGFrW2owICsgM11baTBdO1xuICAgICAgICAgICAgICAgIGYxID0gYSAqIGFrW2owXVtpMCArIDFdICsgYiAqIGFrW2owICsgMV1baTAgKyAxXSArIGMgKiBha1tqMCArIDJdW2kwICsgMV0gKyBkICogYWtbajAgKyAzXVtpMCArIDFdO1xuICAgICAgICAgICAgICAgIGYyID0gYSAqIGFrW2owXVtpMCArIDJdICsgYiAqIGFrW2owICsgMV1baTAgKyAyXSArIGMgKiBha1tqMCArIDJdW2kwICsgMl0gKyBkICogYWtbajAgKyAzXVtpMCArIDJdO1xuICAgICAgICAgICAgICAgIGYzID0gYSAqIGFrW2owXVtpMCArIDNdICsgYiAqIGFrW2owICsgMV1baTAgKyAzXSArIGMgKiBha1tqMCArIDJdW2kwICsgM10gKyBkICogYWtbajAgKyAzXVtpMCArIDNdO1xuXG4gICAgICAgICAgICAgICAgLy8gTm93IGp1c3QgaW50ZXJwb2xhdGUgaW4gdGhlIHYtZGlyZWN0aW9uIHNpbmNlIGl0J3MgYWxsIHNlcGFyYWJsZTpcbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdTMgKiBmMCArIDMgKiAob3UyICogdSAqIGYxICsgb3UgKiB1MiAqIGYyKSArIHUzICogZjM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIGlmKGFzbW9vdGhpbmcpIHtcbiAgICAgICAgLy8gSGFuZGxlIHNtb290aCBpbiB0aGUgYS1kaXJlY3Rpb24gYnV0IGxpbmVhciBpbiB0aGUgYi1kaXJlY3Rpb24gYnkgcGVyZm9ybWluZyBmb3VyXG4gICAgICAgIC8vIGxpbmVhciBpbnRlcnBvbGF0aW9ucyBmb2xsb3dlZCBieSBvbmUgY3ViaWMgaW50ZXJwb2xhdGlvbiBvZiB0aGUgcmVzdWx0XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGkwLCBqMCwgdiwgdSkge1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBmMiwgZjMsIGssIGFrO1xuICAgICAgICAgICAgaTAgKj0gMztcbiAgICAgICAgICAgIHZhciB1MiA9IHUgKiB1O1xuICAgICAgICAgICAgdmFyIHUzID0gdTIgKiB1O1xuICAgICAgICAgICAgdmFyIG91ID0gMSAtIHU7XG4gICAgICAgICAgICB2YXIgb3UyID0gb3UgKiBvdTtcbiAgICAgICAgICAgIHZhciBvdTMgPSBvdTIgKiBvdTtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGFycmF5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGFrID0gYXJyYXlzW2tdO1xuXG4gICAgICAgICAgICAgICAgZjAgPSBha1tqMCArIDFdW2kwXSAtIGFrW2owXVtpMF07XG4gICAgICAgICAgICAgICAgZjEgPSBha1tqMCArIDFdW2kwICsgMV0gLSBha1tqMF1baTAgKyAxXTtcbiAgICAgICAgICAgICAgICBmMiA9IGFrW2owICsgMV1baTAgKyAyXSAtIGFrW2owXVtpMCArIDJdO1xuICAgICAgICAgICAgICAgIGYzID0gYWtbajAgKyAxXVtpMCArIDNdIC0gYWtbajBdW2kwICsgM107XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdTMgKiBmMCArIDMgKiAob3UyICogdSAqIGYxICsgb3UgKiB1MiAqIGYyKSArIHUzICogZjM7XG5cbiAgICAgICAgICAgICAgICAvLyBtYXRoZW1hdGljYWxseSBlcXVpdmFsZW50OlxuICAgICAgICAgICAgICAgIC8vIGYwID0gb3UzICogYWtbajAgICAgXVtpMF0gKyAzICogKG91MiAqIHUgKiBha1tqMCAgICBdW2kwICsgMV0gKyBvdSAqIHUyICogYWtbajAgICAgXVtpMCArIDJdKSArIHUzICogYWtbajAgICAgXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIC8vIGYxID0gb3UzICogYWtbajAgKyAxXVtpMF0gKyAzICogKG91MiAqIHUgKiBha1tqMCArIDFdW2kwICsgMV0gKyBvdSAqIHUyICogYWtbajAgKyAxXVtpMCArIDJdKSArIHUzICogYWtbajAgKyAxXVtpMCArIDNdO1xuICAgICAgICAgICAgICAgIC8vIG91dFtrXSA9IGYxIC0gZjA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZihic21vb3RoaW5nKSB7XG4gICAgICAgIC8vIFNhbWUgYXMgdGhlIGFib3ZlIGNhc2UsIGV4Y2VwdCByZXZlcnNlZDpcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgaTAsIGowLCB1LCB2KSB7XG4gICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICAgICAgICAgIGlmKCFvdXQpIG91dCA9IFtdO1xuICAgICAgICAgICAgdmFyIGYwLCBmMSwgaywgYWs7XG4gICAgICAgICAgICBqMCAqPSAzO1xuICAgICAgICAgICAgdmFyIG91ID0gMSAtIHU7XG4gICAgICAgICAgICB2YXIgdjIgPSB2ICogdjtcbiAgICAgICAgICAgIHZhciBvdiA9IDEgLSB2O1xuICAgICAgICAgICAgdmFyIG92MiA9IG92ICogb3Y7XG4gICAgICAgICAgICB2YXIgb3Z2MiA9IG92ICogdiAqIDI7XG4gICAgICAgICAgICB2YXIgYSA9IC0zICogb3YyO1xuICAgICAgICAgICAgdmFyIGIgPSAzICogKG92MiAtIG92djIpO1xuICAgICAgICAgICAgdmFyIGMgPSAzICogKG92djIgLSB2Mik7XG4gICAgICAgICAgICB2YXIgZCA9IDMgKiB2MjtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGFycmF5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGFrID0gYXJyYXlzW2tdO1xuICAgICAgICAgICAgICAgIGYwID0gYSAqIGFrW2owXVtpMF0gKyBiICogYWtbajAgKyAxXVtpMF0gKyBjICogYWtbajAgKyAyXVtpMF0gKyBkICogYWtbajAgKyAzXVtpMF07XG4gICAgICAgICAgICAgICAgZjEgPSBhICogYWtbajBdW2kwICsgMV0gKyBiICogYWtbajAgKyAxXVtpMCArIDFdICsgYyAqIGFrW2owICsgMl1baTAgKyAxXSArIGQgKiBha1tqMCArIDNdW2kwICsgMV07XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdSAqIGYwICsgdSAqIGYxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBGaW5hbGx5LCBib3RoIGRpcmVjdGlvbnMgYXJlIGxpbmVhcjpcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgaTAsIGowLCB2LCB1KSB7XG4gICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tdW51c2VkLXZhcnMgKi9cbiAgICAgICAgICAgIGlmKCFvdXQpIG91dCA9IFtdO1xuICAgICAgICAgICAgdmFyIGYwLCBmMSwgaywgYWs7XG4gICAgICAgICAgICB2YXIgb3YgPSAxIC0gdjtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGFycmF5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGFrID0gYXJyYXlzW2tdO1xuICAgICAgICAgICAgICAgIGYwID0gYWtbajAgKyAxXVtpMF0gLSBha1tqMF1baTBdO1xuICAgICAgICAgICAgICAgIGYxID0gYWtbajAgKyAxXVtpMCArIDFdIC0gYWtbajBdW2kwICsgMV07XG5cbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdiAqIGYwICsgdiAqIGYxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9XG59O1xuXG59LHt9XSw5MTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogUmV0dXJuIGEgZnVuY3Rpb24gdGhhdCBldmFsdWF0ZXMgYSBzZXQgb2YgbGluZWFyIG9yIGJpY3ViaWMgY29udHJvbCBwb2ludHMuXG4gKiBUaGlzIHdpbGwgZ2V0IGV2YWx1YXRlZCBhIGxvdCwgc28gd2UnbGwgYXQgbGVhc3QgZG8gYSBiaXQgb2YgZXh0cmEgd29yayB0b1xuICogZmxhdHRlbiBzb21lIG9mIHRoZSBjaG9pY2VzLiBJbiBwYXJ0aWN1bGFyLCB3ZSdsbCB1bnJvbGwgdGhlIGxpbmVhci9iaWN1YmljXG4gKiBjb21iaW5hdGlvbnMgYW5kIHdlJ2xsIGFsbG93IGNvbXB1dGluZyByZXN1bHRzIGluIHBhcmFsbGVsIHRvIGN1dCBkb3duXG4gKiBvbiByZXBlYXRlZCBhcml0aG1ldGljLlxuICpcbiAqIFRha2Ugbm90ZSB0aGF0IHdlIGRvbid0IHNlYXJjaCBmb3IgdGhlIGNvcnJlY3QgcmFuZ2UgaW4gdGhpcyBmdW5jdGlvbi4gVGhlXG4gKiByZWFzb24gaXMgZm9yIGNvbnNpc3RlbmN5IGR1ZSB0byB0aGUgY29ycnJlc3BvbmRpbmcgZGVyaXZhdGl2ZSBmdW5jdGlvbi4gSW5cbiAqIHBhcnRpY3VsYXIsIHRoZSBkZXJpdmF0aXZlcyBhcmVuJ3QgY29udGludW91cyBhY3Jvc3MgY2VsbHMsIHNvIGl0J3MgaW1wb3J0YW50XG4gKiB0byBiZSBhYmxlIGNvbnRyb2wgd2hldGhlciB0aGUgZGVyaXZhdGl2ZSBhdCBhIGNlbGwgYm91bmRhcnkgaXMgYXBwcm9hY2hlZFxuICogZnJvbSBvbmUgc2lkZSBvciB0aGUgb3RoZXIuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oYXJyYXlzLCBuYSwgbmIsIGFzbW9vdGhpbmcsIGJzbW9vdGhpbmcpIHtcbiAgICB2YXIgaW1heCA9IG5hIC0gMjtcbiAgICB2YXIgam1heCA9IG5iIC0gMjtcblxuICAgIGlmKGFzbW9vdGhpbmcgJiYgYnNtb290aGluZykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24ob3V0LCBpLCBqKSB7XG4gICAgICAgICAgICBpZighb3V0KSBvdXQgPSBbXTtcbiAgICAgICAgICAgIHZhciBmMCwgZjEsIGYyLCBmMywgYWssIGs7XG5cbiAgICAgICAgICAgIHZhciBpMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKE1hdGguZmxvb3IoaSksIGltYXgpKTtcbiAgICAgICAgICAgIHZhciBqMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKE1hdGguZmxvb3IoaiksIGptYXgpKTtcbiAgICAgICAgICAgIHZhciB1ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgaSAtIGkwKSk7XG4gICAgICAgICAgICB2YXIgdiA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGogLSBqMCkpO1xuXG4gICAgICAgICAgICAvLyBTaW5jZSBpdCdzIGEgZ3JpZCBvZiBjb250cm9sIHBvaW50cywgdGhlIGFjdHVhbCBpbmRpY2VzIGFyZSAqIDM6XG4gICAgICAgICAgICBpMCAqPSAzO1xuICAgICAgICAgICAgajAgKj0gMztcblxuICAgICAgICAgICAgLy8gUHJlY29tcHV0ZSBzb21lIG51bWJlcnM6XG4gICAgICAgICAgICB2YXIgdTIgPSB1ICogdTtcbiAgICAgICAgICAgIHZhciB1MyA9IHUyICogdTtcbiAgICAgICAgICAgIHZhciBvdSA9IDEgLSB1O1xuICAgICAgICAgICAgdmFyIG91MiA9IG91ICogb3U7XG4gICAgICAgICAgICB2YXIgb3UzID0gb3UyICogb3U7XG5cbiAgICAgICAgICAgIHZhciB2MiA9IHYgKiB2O1xuICAgICAgICAgICAgdmFyIHYzID0gdjIgKiB2O1xuICAgICAgICAgICAgdmFyIG92ID0gMSAtIHY7XG4gICAgICAgICAgICB2YXIgb3YyID0gb3YgKiBvdjtcbiAgICAgICAgICAgIHZhciBvdjMgPSBvdjIgKiBvdjtcblxuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgYWsgPSBhcnJheXNba107XG4gICAgICAgICAgICAgICAgZjAgPSBvdTMgKiBha1tqMF1baTBdICsgMyAqIChvdTIgKiB1ICogYWtbajBdW2kwICsgMV0gKyBvdSAqIHUyICogYWtbajBdW2kwICsgMl0pICsgdTMgKiBha1tqMF1baTAgKyAzXTtcbiAgICAgICAgICAgICAgICBmMSA9IG91MyAqIGFrW2owICsgMV1baTBdICsgMyAqIChvdTIgKiB1ICogYWtbajAgKyAxXVtpMCArIDFdICsgb3UgKiB1MiAqIGFrW2owICsgMV1baTAgKyAyXSkgKyB1MyAqIGFrW2owICsgMV1baTAgKyAzXTtcbiAgICAgICAgICAgICAgICBmMiA9IG91MyAqIGFrW2owICsgMl1baTBdICsgMyAqIChvdTIgKiB1ICogYWtbajAgKyAyXVtpMCArIDFdICsgb3UgKiB1MiAqIGFrW2owICsgMl1baTAgKyAyXSkgKyB1MyAqIGFrW2owICsgMl1baTAgKyAzXTtcbiAgICAgICAgICAgICAgICBmMyA9IG91MyAqIGFrW2owICsgM11baTBdICsgMyAqIChvdTIgKiB1ICogYWtbajAgKyAzXVtpMCArIDFdICsgb3UgKiB1MiAqIGFrW2owICsgM11baTAgKyAyXSkgKyB1MyAqIGFrW2owICsgM11baTAgKyAzXTtcbiAgICAgICAgICAgICAgICBvdXRba10gPSBvdjMgKiBmMCArIDMgKiAob3YyICogdiAqIGYxICsgb3YgKiB2MiAqIGYyKSArIHYzICogZjM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIGlmKGFzbW9vdGhpbmcpIHtcbiAgICAgICAgLy8gSGFuZGxlIHNtb290aCBpbiB0aGUgYS1kaXJlY3Rpb24gYnV0IGxpbmVhciBpbiB0aGUgYi1kaXJlY3Rpb24gYnkgcGVyZm9ybWluZyBmb3VyXG4gICAgICAgIC8vIGxpbmVhciBpbnRlcnBvbGF0aW9ucyBmb2xsb3dlZCBieSBvbmUgY3ViaWMgaW50ZXJwb2xhdGlvbiBvZiB0aGUgcmVzdWx0XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGksIGopIHtcbiAgICAgICAgICAgIGlmKCFvdXQpIG91dCA9IFtdO1xuXG4gICAgICAgICAgICB2YXIgaTAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihNYXRoLmZsb29yKGkpLCBpbWF4KSk7XG4gICAgICAgICAgICB2YXIgajAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihNYXRoLmZsb29yKGopLCBqbWF4KSk7XG4gICAgICAgICAgICB2YXIgdSA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGkgLSBpMCkpO1xuICAgICAgICAgICAgdmFyIHYgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBqIC0gajApKTtcblxuICAgICAgICAgICAgdmFyIGYwLCBmMSwgZjIsIGYzLCBrLCBhaztcbiAgICAgICAgICAgIGkwICo9IDM7XG4gICAgICAgICAgICB2YXIgdTIgPSB1ICogdTtcbiAgICAgICAgICAgIHZhciB1MyA9IHUyICogdTtcbiAgICAgICAgICAgIHZhciBvdSA9IDEgLSB1O1xuICAgICAgICAgICAgdmFyIG91MiA9IG91ICogb3U7XG4gICAgICAgICAgICB2YXIgb3UzID0gb3UyICogb3U7XG4gICAgICAgICAgICB2YXIgb3YgPSAxIC0gdjtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGFycmF5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGFrID0gYXJyYXlzW2tdO1xuICAgICAgICAgICAgICAgIGYwID0gb3YgKiBha1tqMF1baTBdICsgdiAqIGFrW2owICsgMV1baTBdO1xuICAgICAgICAgICAgICAgIGYxID0gb3YgKiBha1tqMF1baTAgKyAxXSArIHYgKiBha1tqMCArIDFdW2kwICsgMV07XG4gICAgICAgICAgICAgICAgZjIgPSBvdiAqIGFrW2owXVtpMCArIDJdICsgdiAqIGFrW2owICsgMV1baTAgKyAxXTtcbiAgICAgICAgICAgICAgICBmMyA9IG92ICogYWtbajBdW2kwICsgM10gKyB2ICogYWtbajAgKyAxXVtpMCArIDFdO1xuXG4gICAgICAgICAgICAgICAgb3V0W2tdID0gb3UzICogZjAgKyAzICogKG91MiAqIHUgKiBmMSArIG91ICogdTIgKiBmMikgKyB1MyAqIGYzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYoYnNtb290aGluZykge1xuICAgICAgICAvLyBTYW1lIGFzIHRoZSBhYm92ZSBjYXNlLCBleGNlcHQgcmV2ZXJzZWQ6XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvdXQsIGksIGopIHtcbiAgICAgICAgICAgIGlmKCFvdXQpIG91dCA9IFtdO1xuXG4gICAgICAgICAgICB2YXIgaTAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihNYXRoLmZsb29yKGkpLCBpbWF4KSk7XG4gICAgICAgICAgICB2YXIgajAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihNYXRoLmZsb29yKGopLCBqbWF4KSk7XG4gICAgICAgICAgICB2YXIgdSA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGkgLSBpMCkpO1xuICAgICAgICAgICAgdmFyIHYgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBqIC0gajApKTtcblxuICAgICAgICAgICAgdmFyIGYwLCBmMSwgZjIsIGYzLCBrLCBhaztcbiAgICAgICAgICAgIGowICo9IDM7XG4gICAgICAgICAgICB2YXIgdjIgPSB2ICogdjtcbiAgICAgICAgICAgIHZhciB2MyA9IHYyICogdjtcbiAgICAgICAgICAgIHZhciBvdiA9IDEgLSB2O1xuICAgICAgICAgICAgdmFyIG92MiA9IG92ICogb3Y7XG4gICAgICAgICAgICB2YXIgb3YzID0gb3YyICogb3Y7XG4gICAgICAgICAgICB2YXIgb3UgPSAxIC0gdTtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGFycmF5cy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGFrID0gYXJyYXlzW2tdO1xuICAgICAgICAgICAgICAgIGYwID0gb3UgKiBha1tqMF1baTBdICsgdSAqIGFrW2owXVtpMCArIDFdO1xuICAgICAgICAgICAgICAgIGYxID0gb3UgKiBha1tqMCArIDFdW2kwXSArIHUgKiBha1tqMCArIDFdW2kwICsgMV07XG4gICAgICAgICAgICAgICAgZjIgPSBvdSAqIGFrW2owICsgMl1baTBdICsgdSAqIGFrW2owICsgMl1baTAgKyAxXTtcbiAgICAgICAgICAgICAgICBmMyA9IG91ICogYWtbajAgKyAzXVtpMF0gKyB1ICogYWtbajAgKyAzXVtpMCArIDFdO1xuXG4gICAgICAgICAgICAgICAgb3V0W2tdID0gb3YzICogZjAgKyAzICogKG92MiAqIHYgKiBmMSArIG92ICogdjIgKiBmMikgKyB2MyAqIGYzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dDtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBGaW5hbGx5LCBib3RoIGRpcmVjdGlvbnMgYXJlIGxpbmVhcjpcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG91dCwgaSwgaikge1xuICAgICAgICAgICAgaWYoIW91dCkgb3V0ID0gW107XG5cbiAgICAgICAgICAgIHZhciBpMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKE1hdGguZmxvb3IoaSksIGltYXgpKTtcbiAgICAgICAgICAgIHZhciBqMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKE1hdGguZmxvb3IoaiksIGptYXgpKTtcbiAgICAgICAgICAgIHZhciB1ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgaSAtIGkwKSk7XG4gICAgICAgICAgICB2YXIgdiA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGogLSBqMCkpO1xuXG4gICAgICAgICAgICB2YXIgZjAsIGYxLCBrLCBhaztcbiAgICAgICAgICAgIHZhciBvdiA9IDEgLSB2O1xuICAgICAgICAgICAgdmFyIG91ID0gMSAtIHU7XG4gICAgICAgICAgICBmb3IoayA9IDA7IGsgPCBhcnJheXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBhayA9IGFycmF5c1trXTtcbiAgICAgICAgICAgICAgICBmMCA9IG91ICogYWtbajBdW2kwXSArIHUgKiBha1tqMF1baTAgKyAxXTtcbiAgICAgICAgICAgICAgICBmMSA9IG91ICogYWtbajAgKyAxXVtpMF0gKyB1ICogYWtbajAgKyAxXVtpMCArIDFdO1xuXG4gICAgICAgICAgICAgICAgb3V0W2tdID0gb3YgKiBmMCArIHYgKiBmMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgfVxufTtcblxufSx7fV0sOTEzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgaGFuZGxlWFlEZWZhdWx0cyA9IF9kZXJlcV8oJy4veHlfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVBQkRlZmF1bHRzID0gX2RlcmVxXygnLi9hYl9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRmbHRDb2xvciwgZnVsbExheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB0cmFjZU91dC5fY2xpcFBhdGhJZCA9ICdjbGlwJyArIHRyYWNlT3V0LnVpZCArICdjYXJwZXQnO1xuXG4gICAgdmFyIGRlZmF1bHRDb2xvciA9IGNvZXJjZSgnY29sb3InLCBjb2xvckF0dHJzLmRlZmF1bHRMaW5lKTtcbiAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICdmb250Jyk7XG5cbiAgICBjb2VyY2UoJ2NhcnBldCcpO1xuXG4gICAgaGFuZGxlQUJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZnVsbExheW91dCwgY29lcmNlLCBkZWZhdWx0Q29sb3IpO1xuXG4gICAgaWYoIXRyYWNlT3V0LmEgfHwgIXRyYWNlT3V0LmIpIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYodHJhY2VPdXQuYS5sZW5ndGggPCAzKSB7XG4gICAgICAgIHRyYWNlT3V0LmFheGlzLnNtb290aGluZyA9IDA7XG4gICAgfVxuXG4gICAgaWYodHJhY2VPdXQuYi5sZW5ndGggPCAzKSB7XG4gICAgICAgIHRyYWNlT3V0LmJheGlzLnNtb290aGluZyA9IDA7XG4gICAgfVxuXG4gICAgLy8gTkI6IHRoZSBpbnB1dCBpcyB4L3kgYXJyYXlzLiBZb3Ugc2hvdWxkIGtub3cgdGhhdCB0aGUgKmZpcnN0KiBkaW1lbnNpb24gb2YgeCBhbmQgeVxuICAgIC8vIGNvcnJlc3BvbmRzIHRvIGIgYW5kIHRoZSBzZWNvbmQgdG8gYS4gVGhpcyBzb3VuZHMgYmFja3dhcmRzIGJ1dCBlbmRzIHVwIG1ha2luZyBzZW5zZVxuICAgIC8vIHRoZSBpbXBvcnRhbnQgcGFydCB0byBrbm93IGlzIHRoYXQgd2hlbiB5b3Ugd3JpdGUgeVtqXVtpXSwgaiBnb2VzIGZyb20gMCB0byBiLmxlbmd0aCAtIDFcbiAgICAvLyBhbmQgaSBnb2VzIGZyb20gMCB0byBhLmxlbmd0aCAtIDEuXG4gICAgdmFyIHZhbGlkRGF0YSA9IGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSk7XG4gICAgaWYoIXZhbGlkRGF0YSkge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYodHJhY2VPdXQuX2NoZWF0ZXIpIHtcbiAgICAgICAgY29lcmNlKCdjaGVhdGVyc2xvcGUnKTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlc1wiOjU5MixcIi4uLy4uL2xpYlwiOjcxOSxcIi4vYWJfZGVmYXVsdHNcIjo4OTYsXCIuL2F0dHJpYnV0ZXNcIjo4OTgsXCIuL3h5X2RlZmF1bHRzXCI6OTIyfV0sOTE0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBhbmltYXRhYmxlOiB0cnVlLFxuICAgIGlzQ29udGFpbmVyOiB0cnVlLCAvLyBzbyBjYXJwZXQgdHJhY2VzIGdldCBgY2FsY2AgYmVmb3JlIG90aGVyIHRyYWNlc1xuXG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnY2FycGV0JyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuJyksXG4gICAgY2F0ZWdvcmllczogWydjYXJ0ZXNpYW4nLCAnc3ZnJywgJ2NhcnBldCcsICdjYXJwZXRBeGlzJywgJ25vdExlZ2VuZElzb2xhdGFibGUnLCAnbm9NdWx0aUNhdGVnb3J5J10sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhblwiOjc3OCxcIi4vYXR0cmlidXRlc1wiOjg5OCxcIi4vY2FsY1wiOjkwMixcIi4vZGVmYXVsdHNcIjo5MTMsXCIuL3Bsb3RcIjo5MTl9XSw5MTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogR2l2ZW4gYSB0cmFjZSwgbG9vayB1cCB0aGUgY2FycGV0IGF4aXMgYnkgY2FycGV0LlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGdkLCB0cmFjZSkge1xuICAgIHZhciBuID0gZ2QuX2Z1bGxEYXRhLmxlbmd0aDtcbiAgICB2YXIgZmlyc3RBeGlzO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgdmFyIG1heWJlQ2FycGV0ID0gZ2QuX2Z1bGxEYXRhW2ldO1xuXG4gICAgICAgIGlmKG1heWJlQ2FycGV0LmluZGV4ID09PSB0cmFjZS5pbmRleCkgY29udGludWU7XG5cbiAgICAgICAgaWYobWF5YmVDYXJwZXQudHlwZSA9PT0gJ2NhcnBldCcpIHtcbiAgICAgICAgICAgIGlmKCFmaXJzdEF4aXMpIHtcbiAgICAgICAgICAgICAgICBmaXJzdEF4aXMgPSBtYXliZUNhcnBldDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYobWF5YmVDYXJwZXQuY2FycGV0ID09PSB0cmFjZS5jYXJwZXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWF5YmVDYXJwZXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmlyc3RBeGlzO1xufTtcblxufSx7fV0sOTE2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlUGF0aCh4cCwgeXAsIGlzQmljdWJpYykge1xuICAgIC8vIFByZXZlbnQgZDMgZXJyb3JzIHRoYXQgd291bGQgcmVzdWx0IG90aGVyd2lzZTpcbiAgICBpZih4cC5sZW5ndGggPT09IDApIHJldHVybiAnJztcblxuICAgIHZhciBpO1xuICAgIHZhciBwYXRoID0gW107XG4gICAgdmFyIHN0cmlkZSA9IGlzQmljdWJpYyA/IDMgOiAxO1xuICAgIGZvcihpID0gMDsgaSA8IHhwLmxlbmd0aDsgaSArPSBzdHJpZGUpIHtcbiAgICAgICAgcGF0aC5wdXNoKHhwW2ldICsgJywnICsgeXBbaV0pO1xuXG4gICAgICAgIGlmKGlzQmljdWJpYyAmJiBpIDwgeHAubGVuZ3RoIC0gc3RyaWRlKSB7XG4gICAgICAgICAgICBwYXRoLnB1c2goJ0MnKTtcbiAgICAgICAgICAgIHBhdGgucHVzaChbXG4gICAgICAgICAgICAgICAgeHBbaSArIDFdICsgJywnICsgeXBbaSArIDFdLFxuICAgICAgICAgICAgICAgIHhwW2kgKyAyXSArICcsJyArIHlwW2kgKyAyXSArICcgJyxcbiAgICAgICAgICAgIF0uam9pbignICcpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGF0aC5qb2luKGlzQmljdWJpYyA/ICcnIDogJ0wnKTtcbn07XG5cbn0se31dLDkxNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcblxuLypcbiAqIE1hcCBhbiBhcnJheSBvZiB4IG9yIHkgY29vcmRpbmF0ZXMgKGMpIHRvIHNjcmVlbi1zcGFjZSBwaXhlbCBjb29yZGluYXRlcyAocCkuXG4gKiBUaGUgb3V0cHV0IGFycmF5IGlzIG9wdGlvbmFsLCBidXQgaWYgcHJvdmlkZWQsIGl0IHdpbGwgYmUgcmV1c2VkIHdpdGhvdXRcbiAqIHJlYWxsb2NhdGlvbiB0byB0aGUgZXh0ZW50IHBvc3NpYmxlLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1hcEFycmF5KG91dCwgZGF0YSwgZnVuYykge1xuICAgIHZhciBpO1xuXG4gICAgaWYoIWlzQXJyYXlPclR5cGVkQXJyYXkob3V0KSkge1xuICAgICAgICAvLyBJZiBub3QgYW4gYXJyYXksIG1ha2UgaXQgYW4gYXJyYXk6XG4gICAgICAgIG91dCA9IFtdO1xuICAgIH0gZWxzZSBpZihvdXQubGVuZ3RoID4gZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgLy8gSWYgdG9vIGxvbmcsIHRydW5jYXRlLiAoSWYgdG9vIHNob3J0LCBpdCB3aWxsIGdyb3dcbiAgICAgICAgLy8gYXV0b21hdGljYWxseSBzbyB3ZSBkb24ndCBjYXJlIGFib3V0IHRoYXQgY2FzZSlcbiAgICAgICAgb3V0ID0gb3V0LnNsaWNlKDAsIGRhdGEubGVuZ3RoKTtcbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG91dFtpXSA9IGZ1bmMoZGF0YVtpXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dDtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sOTE4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG9yaWVudFRleHQodHJhY2UsIHhheGlzLCB5YXhpcywgeHksIGR4eSwgcmVmRHh5KSB7XG4gICAgdmFyIGR4ID0gZHh5WzBdICogdHJhY2UuZHBkeCh4YXhpcyk7XG4gICAgdmFyIGR5ID0gZHh5WzFdICogdHJhY2UuZHBkeSh5YXhpcyk7XG4gICAgdmFyIGZsaXAgPSAxO1xuXG4gICAgdmFyIG9mZnNldE11bHRpcGxpZXIgPSAxLjA7XG4gICAgaWYocmVmRHh5KSB7XG4gICAgICAgIHZhciBsMSA9IE1hdGguc3FydChkeHlbMF0gKiBkeHlbMF0gKyBkeHlbMV0gKiBkeHlbMV0pO1xuICAgICAgICB2YXIgbDIgPSBNYXRoLnNxcnQocmVmRHh5WzBdICogcmVmRHh5WzBdICsgcmVmRHh5WzFdICogcmVmRHh5WzFdKTtcbiAgICAgICAgdmFyIGRvdCA9IChkeHlbMF0gKiByZWZEeHlbMF0gKyBkeHlbMV0gKiByZWZEeHlbMV0pIC8gbDEgLyBsMjtcbiAgICAgICAgb2Zmc2V0TXVsdGlwbGllciA9IE1hdGgubWF4KDAuMCwgZG90KTtcbiAgICB9XG5cbiAgICB2YXIgYW5nbGUgPSBNYXRoLmF0YW4yKGR5LCBkeCkgKiAxODAgLyBNYXRoLlBJO1xuICAgIGlmKGFuZ2xlIDwgLTkwKSB7XG4gICAgICAgIGFuZ2xlICs9IDE4MDtcbiAgICAgICAgZmxpcCA9IC1mbGlwO1xuICAgIH0gZWxzZSBpZihhbmdsZSA+IDkwKSB7XG4gICAgICAgIGFuZ2xlIC09IDE4MDtcbiAgICAgICAgZmxpcCA9IC1mbGlwO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGFuZ2xlOiBhbmdsZSxcbiAgICAgICAgZmxpcDogZmxpcCxcbiAgICAgICAgcDogdHJhY2UuYzJwKHh5LCB4YXhpcywgeWF4aXMpLFxuICAgICAgICBvZmZzZXRNdWx0cGxpZXI6IG9mZnNldE11bHRpcGxpZXJcbiAgICB9O1xufTtcblxufSx7fV0sOTE5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBtYXAxZEFycmF5ID0gX2RlcmVxXygnLi9tYXBfMWRfYXJyYXknKTtcbnZhciBtYWtlcGF0aCA9IF9kZXJlcV8oJy4vbWFrZXBhdGgnKTtcbnZhciBvcmllbnRUZXh0ID0gX2RlcmVxXygnLi9vcmllbnRfdGV4dCcpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGFsaWdubWVudENvbnN0YW50cyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBwbG90aW5mbywgY2RjYXJwZXQsIGNhcnBldExheWVyKSB7XG4gICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2xpcExheWVyID0gZnVsbExheW91dC5fY2xpcHM7XG5cbiAgICBMaWIubWFrZVRyYWNlR3JvdXBzKGNhcnBldExheWVyLCBjZGNhcnBldCwgJ3RyYWNlJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgYXhpc0xheWVyID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICAgICAgdmFyIGFheCA9IHRyYWNlLmFheGlzO1xuICAgICAgICB2YXIgYmF4ID0gdHJhY2UuYmF4aXM7XG5cbiAgICAgICAgdmFyIG1pbm9yTGF5ZXIgPSBMaWIuZW5zdXJlU2luZ2xlKGF4aXNMYXllciwgJ2cnLCAnbWlub3JsYXllcicpO1xuICAgICAgICB2YXIgbWFqb3JMYXllciA9IExpYi5lbnN1cmVTaW5nbGUoYXhpc0xheWVyLCAnZycsICdtYWpvcmxheWVyJyk7XG4gICAgICAgIHZhciBib3VuZGFyeUxheWVyID0gTGliLmVuc3VyZVNpbmdsZShheGlzTGF5ZXIsICdnJywgJ2JvdW5kYXJ5bGF5ZXInKTtcbiAgICAgICAgdmFyIGxhYmVsTGF5ZXIgPSBMaWIuZW5zdXJlU2luZ2xlKGF4aXNMYXllciwgJ2cnLCAnbGFiZWxsYXllcicpO1xuXG4gICAgICAgIGF4aXNMYXllci5zdHlsZSgnb3BhY2l0eScsIHRyYWNlLm9wYWNpdHkpO1xuXG4gICAgICAgIGRyYXdHcmlkTGluZXMoeGEsIHlhLCBtYWpvckxheWVyLCBhYXgsICdhJywgYWF4Ll9ncmlkbGluZXMsIHRydWUpO1xuICAgICAgICBkcmF3R3JpZExpbmVzKHhhLCB5YSwgbWFqb3JMYXllciwgYmF4LCAnYicsIGJheC5fZ3JpZGxpbmVzLCB0cnVlKTtcbiAgICAgICAgZHJhd0dyaWRMaW5lcyh4YSwgeWEsIG1pbm9yTGF5ZXIsIGFheCwgJ2EnLCBhYXguX21pbm9yZ3JpZGxpbmVzLCB0cnVlKTtcbiAgICAgICAgZHJhd0dyaWRMaW5lcyh4YSwgeWEsIG1pbm9yTGF5ZXIsIGJheCwgJ2InLCBiYXguX21pbm9yZ3JpZGxpbmVzLCB0cnVlKTtcblxuICAgICAgICAvLyBOQjogVGhlc2UgYXJlIG5vdCBvbW1pdHRlZCBpZiB0aGUgbGluZXMgYXJlIG5vdCBhY3RpdmUuIFRoZSBqb2lucyBtdXN0IGJlIGV4ZWN1dGVkXG4gICAgICAgIC8vIGluIG9yZGVyIGZvciB0aGVtIHRvIGdldCBjbGVhbmVkIHVwIHdpdGhvdXQgYSBmdWxsIHJlZHJhd1xuICAgICAgICBkcmF3R3JpZExpbmVzKHhhLCB5YSwgYm91bmRhcnlMYXllciwgYWF4LCAnYS1ib3VuZGFyeScsIGFheC5fYm91bmRhcnlsaW5lcyk7XG4gICAgICAgIGRyYXdHcmlkTGluZXMoeGEsIHlhLCBib3VuZGFyeUxheWVyLCBiYXgsICdiLWJvdW5kYXJ5JywgYmF4Ll9ib3VuZGFyeWxpbmVzKTtcblxuICAgICAgICB2YXIgbGFiZWxPcmllbnRhdGlvbkEgPSBkcmF3QXhpc0xhYmVscyhnZCwgeGEsIHlhLCB0cmFjZSwgY2QwLCBsYWJlbExheWVyLCBhYXguX2xhYmVscywgJ2EtbGFiZWwnKTtcbiAgICAgICAgdmFyIGxhYmVsT3JpZW50YXRpb25CID0gZHJhd0F4aXNMYWJlbHMoZ2QsIHhhLCB5YSwgdHJhY2UsIGNkMCwgbGFiZWxMYXllciwgYmF4Ll9sYWJlbHMsICdiLWxhYmVsJyk7XG5cbiAgICAgICAgZHJhd0F4aXNUaXRsZXMoZ2QsIGxhYmVsTGF5ZXIsIHRyYWNlLCBjZDAsIHhhLCB5YSwgbGFiZWxPcmllbnRhdGlvbkEsIGxhYmVsT3JpZW50YXRpb25CKTtcblxuICAgICAgICBkcmF3Q2xpcFBhdGgodHJhY2UsIGNkMCwgY2xpcExheWVyLCB4YSwgeWEpO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gZHJhd0NsaXBQYXRoKHRyYWNlLCB0LCBsYXllciwgeGF4aXMsIHlheGlzKSB7XG4gICAgdmFyIHNlZywgeHAsIHlwLCBpO1xuXG4gICAgdmFyIGNsaXAgPSBsYXllci5zZWxlY3QoJyMnICsgdHJhY2UuX2NsaXBQYXRoSWQpO1xuXG4gICAgaWYoIWNsaXAuc2l6ZSgpKSB7XG4gICAgICAgIGNsaXAgPSBsYXllci5hcHBlbmQoJ2NsaXBQYXRoJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdjYXJwZXRjbGlwJywgdHJ1ZSk7XG4gICAgfVxuXG4gICAgdmFyIHBhdGggPSBMaWIuZW5zdXJlU2luZ2xlKGNsaXAsICdwYXRoJywgJ2NhcnBldGJvdW5kYXJ5Jyk7XG4gICAgdmFyIHNlZ21lbnRzID0gdC5jbGlwc2VnbWVudHM7XG4gICAgdmFyIHNlZ3MgPSBbXTtcblxuICAgIGZvcihpID0gMDsgaSA8IHNlZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHNlZyA9IHNlZ21lbnRzW2ldO1xuICAgICAgICB4cCA9IG1hcDFkQXJyYXkoW10sIHNlZy54LCB4YXhpcy5jMnApO1xuICAgICAgICB5cCA9IG1hcDFkQXJyYXkoW10sIHNlZy55LCB5YXhpcy5jMnApO1xuICAgICAgICBzZWdzLnB1c2gobWFrZXBhdGgoeHAsIHlwLCBzZWcuYmljdWJpYykpO1xuICAgIH1cblxuICAgIC8vIFRoaXMgY291bGQgYmUgb3B0aW1pemVkIGV2ZXIgc28gc2xpZ2h0bHkgdG8gYXZvaWQgbm8tb3AgTCBzZWdtZW50c1xuICAgIC8vIGF0IHRoZSBjb3JuZXJzLCBidXQgaXQncyBzbyBuZWdsaWdpYmxlIHRoYXQgSSBkb24ndCB0aGluayBpdCdzIHdvcnRoXG4gICAgLy8gdGhlIGV4dHJhIGNvbXBsZXhpdHlcbiAgICB2YXIgY2xpcFBhdGhEYXRhID0gJ00nICsgc2Vncy5qb2luKCdMJykgKyAnWic7XG4gICAgY2xpcC5hdHRyKCdpZCcsIHRyYWNlLl9jbGlwUGF0aElkKTtcbiAgICBwYXRoLmF0dHIoJ2QnLCBjbGlwUGF0aERhdGEpO1xufVxuXG5mdW5jdGlvbiBkcmF3R3JpZExpbmVzKHhheGlzLCB5YXhpcywgbGF5ZXIsIGF4aXMsIGF4aXNMZXR0ZXIsIGdyaWRsaW5lcykge1xuICAgIHZhciBsaW5lQ2xhc3MgPSAnY29uc3QtJyArIGF4aXNMZXR0ZXIgKyAnLWxpbmVzJztcbiAgICB2YXIgZ3JpZEpvaW4gPSBsYXllci5zZWxlY3RBbGwoJy4nICsgbGluZUNsYXNzKS5kYXRhKGdyaWRsaW5lcyk7XG5cbiAgICBncmlkSm9pbi5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5jbGFzc2VkKGxpbmVDbGFzcywgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCd2ZWN0b3ItZWZmZWN0JywgJ25vbi1zY2FsaW5nLXN0cm9rZScpO1xuXG4gICAgZ3JpZEpvaW4uZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBncmlkbGluZSA9IGQ7XG4gICAgICAgIHZhciB4ID0gZ3JpZGxpbmUueDtcbiAgICAgICAgdmFyIHkgPSBncmlkbGluZS55O1xuXG4gICAgICAgIHZhciB4cCA9IG1hcDFkQXJyYXkoW10sIHgsIHhheGlzLmMycCk7XG4gICAgICAgIHZhciB5cCA9IG1hcDFkQXJyYXkoW10sIHksIHlheGlzLmMycCk7XG5cbiAgICAgICAgdmFyIHBhdGggPSAnTScgKyBtYWtlcGF0aCh4cCwgeXAsIGdyaWRsaW5lLnNtb290aGluZyk7XG5cbiAgICAgICAgdmFyIGVsID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIGVsLmF0dHIoJ2QnLCBwYXRoKVxuICAgICAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBncmlkbGluZS53aWR0aClcbiAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlJywgZ3JpZGxpbmUuY29sb3IpXG4gICAgICAgICAgICAuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpO1xuICAgIH0pO1xuXG4gICAgZ3JpZEpvaW4uZXhpdCgpLnJlbW92ZSgpO1xufVxuXG5mdW5jdGlvbiBkcmF3QXhpc0xhYmVscyhnZCwgeGF4aXMsIHlheGlzLCB0cmFjZSwgdCwgbGF5ZXIsIGxhYmVscywgbGFiZWxDbGFzcykge1xuICAgIHZhciBsYWJlbEpvaW4gPSBsYXllci5zZWxlY3RBbGwoJ3RleHQuJyArIGxhYmVsQ2xhc3MpLmRhdGEobGFiZWxzKTtcblxuICAgIGxhYmVsSm9pbi5lbnRlcigpLmFwcGVuZCgndGV4dCcpXG4gICAgICAgIC5jbGFzc2VkKGxhYmVsQ2xhc3MsIHRydWUpO1xuXG4gICAgdmFyIG1heEV4dGVudCA9IDA7XG4gICAgdmFyIGxhYmVsT3JpZW50YXRpb24gPSB7fTtcblxuICAgIGxhYmVsSm9pbi5lYWNoKGZ1bmN0aW9uKGxhYmVsLCBpKSB7XG4gICAgICAgIC8vIE1vc3Qgb2YgdGhlIHBvc2l0aW9uaW5nIGlzIGRvbmUgaW4gY2FsY19sYWJlbHMuIE9ubHkgdGhlIHBhcnRzIHRoYXQgZGVwZW5kIHVwb25cbiAgICAgICAgLy8gdGhlIHNjcmVlbiBzcGFjZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgeCBhbmQgeSBheGVzIGFyZSBoZXJlOlxuICAgICAgICB2YXIgb3JpZW50YXRpb247XG4gICAgICAgIGlmKGxhYmVsLmF4aXMudGlja2FuZ2xlID09PSAnYXV0bycpIHtcbiAgICAgICAgICAgIG9yaWVudGF0aW9uID0gb3JpZW50VGV4dCh0cmFjZSwgeGF4aXMsIHlheGlzLCBsYWJlbC54eSwgbGFiZWwuZHh5KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBhbmdsZSA9IChsYWJlbC5heGlzLnRpY2thbmdsZSArIDE4MC4wKSAqIE1hdGguUEkgLyAxODAuMDtcbiAgICAgICAgICAgIG9yaWVudGF0aW9uID0gb3JpZW50VGV4dCh0cmFjZSwgeGF4aXMsIHlheGlzLCBsYWJlbC54eSwgW01hdGguY29zKGFuZ2xlKSwgTWF0aC5zaW4oYW5nbGUpXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZighaSkge1xuICAgICAgICAgICAgLy8gVE9ETzogb2Zmc2V0TXVsdGlwbGllcj8gTm90IGN1cnJlbnRseSB1c2VkIGFueXdoZXJlLi4uXG4gICAgICAgICAgICBsYWJlbE9yaWVudGF0aW9uID0ge2FuZ2xlOiBvcmllbnRhdGlvbi5hbmdsZSwgZmxpcDogb3JpZW50YXRpb24uZmxpcH07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRpcmVjdGlvbiA9IChsYWJlbC5lbmRBbmNob3IgPyAtMSA6IDEpICogb3JpZW50YXRpb24uZmxpcDtcblxuICAgICAgICB2YXIgbGFiZWxFbCA9IGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICd0ZXh0LWFuY2hvcic6IGRpcmVjdGlvbiA+IDAgPyAnc3RhcnQnIDogJ2VuZCcsXG4gICAgICAgICAgICAgICAgJ2RhdGEtbm90ZXgnOiAxXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBsYWJlbC5mb250KVxuICAgICAgICAgICAgLnRleHQobGFiZWwudGV4dClcbiAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKTtcblxuICAgICAgICB2YXIgYmJveCA9IERyYXdpbmcuYkJveCh0aGlzKTtcblxuICAgICAgICBsYWJlbEVsLmF0dHIoJ3RyYW5zZm9ybScsXG4gICAgICAgICAgICAgICAgLy8gVHJhbnNsYXRlIHRvIHRoZSBjb3JyZWN0IHBvaW50OlxuICAgICAgICAgICAgICAgICd0cmFuc2xhdGUoJyArIG9yaWVudGF0aW9uLnBbMF0gKyAnLCcgKyBvcmllbnRhdGlvbi5wWzFdICsgJykgJyArXG4gICAgICAgICAgICAgICAgLy8gUm90YXRlIHRvIGxpbmUgdXAgd2l0aCBncmlkIGxpbmUgdGFuZ2VudDpcbiAgICAgICAgICAgICAgICAncm90YXRlKCcgKyBvcmllbnRhdGlvbi5hbmdsZSArICcpJyArXG4gICAgICAgICAgICAgICAgLy8gQWRqdXN0IHRoZSBiYXNlbGluZSBhbmQgaW5kZW50YXRpb246XG4gICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgbGFiZWwuYXhpcy5sYWJlbHBhZGRpbmcgKiBkaXJlY3Rpb24gKyAnLCcgKyBiYm94LmhlaWdodCAqIDAuMyArICcpJ1xuICAgICAgICAgICAgKTtcblxuICAgICAgICBtYXhFeHRlbnQgPSBNYXRoLm1heChtYXhFeHRlbnQsIGJib3gud2lkdGggKyBsYWJlbC5heGlzLmxhYmVscGFkZGluZyk7XG4gICAgfSk7XG5cbiAgICBsYWJlbEpvaW4uZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgbGFiZWxPcmllbnRhdGlvbi5tYXhFeHRlbnQgPSBtYXhFeHRlbnQ7XG4gICAgcmV0dXJuIGxhYmVsT3JpZW50YXRpb247XG59XG5cbmZ1bmN0aW9uIGRyYXdBeGlzVGl0bGVzKGdkLCBsYXllciwgdHJhY2UsIHQsIHhhLCB5YSwgbGFiZWxPcmllbnRhdGlvbkEsIGxhYmVsT3JpZW50YXRpb25CKSB7XG4gICAgdmFyIGEsIGIsIHh5LCBkeHk7XG5cbiAgICB2YXIgYU1pbiA9IExpYi5hZ2dOdW1zKE1hdGgubWluLCBudWxsLCB0cmFjZS5hKTtcbiAgICB2YXIgYU1heCA9IExpYi5hZ2dOdW1zKE1hdGgubWF4LCBudWxsLCB0cmFjZS5hKTtcbiAgICB2YXIgYk1pbiA9IExpYi5hZ2dOdW1zKE1hdGgubWluLCBudWxsLCB0cmFjZS5iKTtcbiAgICB2YXIgYk1heCA9IExpYi5hZ2dOdW1zKE1hdGgubWF4LCBudWxsLCB0cmFjZS5iKTtcblxuICAgIGEgPSAwLjUgKiAoYU1pbiArIGFNYXgpO1xuICAgIGIgPSBiTWluO1xuICAgIHh5ID0gdHJhY2UuYWIyeHkoYSwgYiwgdHJ1ZSk7XG4gICAgZHh5ID0gdHJhY2UuZHh5ZGFfcm91Z2goYSwgYik7XG4gICAgaWYobGFiZWxPcmllbnRhdGlvbkEuYW5nbGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBMaWIuZXh0ZW5kRmxhdChsYWJlbE9yaWVudGF0aW9uQSwgb3JpZW50VGV4dCh0cmFjZSwgeGEsIHlhLCB4eSwgdHJhY2UuZHh5ZGJfcm91Z2goYSwgYikpKTtcbiAgICB9XG4gICAgZHJhd0F4aXNUaXRsZShnZCwgbGF5ZXIsIHRyYWNlLCB0LCB4eSwgZHh5LCB0cmFjZS5hYXhpcywgeGEsIHlhLCBsYWJlbE9yaWVudGF0aW9uQSwgJ2EtdGl0bGUnKTtcblxuICAgIGEgPSBhTWluO1xuICAgIGIgPSAwLjUgKiAoYk1pbiArIGJNYXgpO1xuICAgIHh5ID0gdHJhY2UuYWIyeHkoYSwgYiwgdHJ1ZSk7XG4gICAgZHh5ID0gdHJhY2UuZHh5ZGJfcm91Z2goYSwgYik7XG4gICAgaWYobGFiZWxPcmllbnRhdGlvbkIuYW5nbGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBMaWIuZXh0ZW5kRmxhdChsYWJlbE9yaWVudGF0aW9uQiwgb3JpZW50VGV4dCh0cmFjZSwgeGEsIHlhLCB4eSwgdHJhY2UuZHh5ZGFfcm91Z2goYSwgYikpKTtcbiAgICB9XG4gICAgZHJhd0F4aXNUaXRsZShnZCwgbGF5ZXIsIHRyYWNlLCB0LCB4eSwgZHh5LCB0cmFjZS5iYXhpcywgeGEsIHlhLCBsYWJlbE9yaWVudGF0aW9uQiwgJ2ItdGl0bGUnKTtcbn1cblxudmFyIGxpbmVTcGFjaW5nID0gYWxpZ25tZW50Q29uc3RhbnRzLkxJTkVfU1BBQ0lORztcbnZhciBtaWRTaGlmdCA9ICgoMSAtIGFsaWdubWVudENvbnN0YW50cy5NSURfU0hJRlQpIC8gbGluZVNwYWNpbmcpICsgMTtcblxuZnVuY3Rpb24gZHJhd0F4aXNUaXRsZShnZCwgbGF5ZXIsIHRyYWNlLCB0LCB4eSwgZHh5LCBheGlzLCB4YSwgeWEsIGxhYmVsT3JpZW50YXRpb24sIGxhYmVsQ2xhc3MpIHtcbiAgICB2YXIgZGF0YSA9IFtdO1xuICAgIGlmKGF4aXMudGl0bGUudGV4dCkgZGF0YS5wdXNoKGF4aXMudGl0bGUudGV4dCk7XG4gICAgdmFyIHRpdGxlSm9pbiA9IGxheWVyLnNlbGVjdEFsbCgndGV4dC4nICsgbGFiZWxDbGFzcykuZGF0YShkYXRhKTtcbiAgICB2YXIgb2Zmc2V0ID0gbGFiZWxPcmllbnRhdGlvbi5tYXhFeHRlbnQ7XG5cbiAgICB0aXRsZUpvaW4uZW50ZXIoKS5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAuY2xhc3NlZChsYWJlbENsYXNzLCB0cnVlKTtcblxuICAgIC8vIFRoZXJlJ3Mgb25seSBvbmUsIGJ1dCB3ZSdsbCBkbyBpdCBhcyBhIGpvaW4gc28gaXQncyB1cGRhdGVkIG5pY2VseTpcbiAgICB0aXRsZUpvaW4uZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG9yaWVudGF0aW9uID0gb3JpZW50VGV4dCh0cmFjZSwgeGEsIHlhLCB4eSwgZHh5KTtcblxuICAgICAgICBpZihbJ3N0YXJ0JywgJ2JvdGgnXS5pbmRleE9mKGF4aXMuc2hvd3RpY2tsYWJlbHMpID09PSAtMSkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluIGFkZGl0aW9uIHRvIHRoZSBzaXplIG9mIHRoZSBsYWJlbHMsIGFkZCBvbiBzb21lIGV4dHJhIHBhZGRpbmc6XG4gICAgICAgIHZhciB0aXRsZVNpemUgPSBheGlzLnRpdGxlLmZvbnQuc2l6ZTtcbiAgICAgICAgb2Zmc2V0ICs9IHRpdGxlU2l6ZSArIGF4aXMudGl0bGUub2Zmc2V0O1xuXG4gICAgICAgIHZhciBsYWJlbE5vcm0gPSBsYWJlbE9yaWVudGF0aW9uLmFuZ2xlICsgKGxhYmVsT3JpZW50YXRpb24uZmxpcCA8IDAgPyAxODAgOiAwKTtcbiAgICAgICAgdmFyIGFuZ2xlRGlmZiA9IChsYWJlbE5vcm0gLSBvcmllbnRhdGlvbi5hbmdsZSArIDQ1MCkgJSAzNjA7XG4gICAgICAgIHZhciByZXZlcnNlVGl0bGUgPSBhbmdsZURpZmYgPiA5MCAmJiBhbmdsZURpZmYgPCAyNzA7XG5cbiAgICAgICAgdmFyIGVsID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIGVsLnRleHQoYXhpcy50aXRsZS50ZXh0KVxuICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgIGlmKHJldmVyc2VUaXRsZSkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gKC1zdmdUZXh0VXRpbHMubGluZUNvdW50KGVsKSArIG1pZFNoaWZ0KSAqIGxpbmVTcGFjaW5nICogdGl0bGVTaXplIC0gb2Zmc2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgZWwuYXR0cigndHJhbnNmb3JtJyxcbiAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgKyBvcmllbnRhdGlvbi5wWzBdICsgJywnICsgb3JpZW50YXRpb24ucFsxXSArICcpICcgK1xuICAgICAgICAgICAgICAgICdyb3RhdGUoJyArIG9yaWVudGF0aW9uLmFuZ2xlICsgJykgJyArXG4gICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgwLCcgKyBvZmZzZXQgKyAnKSdcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5jbGFzc2VkKCd1c2VyLXNlbGVjdC1ub25lJywgdHJ1ZSlcbiAgICAgICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsICdtaWRkbGUnKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBheGlzLnRpdGxlLmZvbnQpO1xuICAgIH0pO1xuXG4gICAgdGl0bGVKb2luLmV4aXQoKS5yZW1vdmUoKTtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50XCI6Njg4LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzXCI6NzQzLFwiLi9tYWtlcGF0aFwiOjkxNixcIi4vbWFwXzFkX2FycmF5XCI6OTE3LFwiLi9vcmllbnRfdGV4dFwiOjkxOCxcImQzXCI6MTYzfV0sOTIwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgc2VhcmNoID0gX2RlcmVxXygnLi4vLi4vbGliL3NlYXJjaCcpLmZpbmRCaW47XG52YXIgY29tcHV0ZUNvbnRyb2xQb2ludHMgPSBfZGVyZXFfKCcuL2NvbXB1dGVfY29udHJvbF9wb2ludHMnKTtcbnZhciBjcmVhdGVTcGxpbmVFdmFsdWF0b3IgPSBfZGVyZXFfKCcuL2NyZWF0ZV9zcGxpbmVfZXZhbHVhdG9yJyk7XG52YXIgY3JlYXRlSURlcml2YXRpdmVFdmFsdWF0b3IgPSBfZGVyZXFfKCcuL2NyZWF0ZV9pX2Rlcml2YXRpdmVfZXZhbHVhdG9yJyk7XG52YXIgY3JlYXRlSkRlcml2YXRpdmVFdmFsdWF0b3IgPSBfZGVyZXFfKCcuL2NyZWF0ZV9qX2Rlcml2YXRpdmVfZXZhbHVhdG9yJyk7XG5cbi8qXG4gKiBDcmVhdGUgY29udmVyc2lvbiBmdW5jdGlvbnMgdG8gZ28gZnJvbSBvbmUgYmFzaXMgdG8gYW5vdGhlci4gSW4gcGFydGljdWxhciB0aGUgbGV0dGVyXG4gKiBhYmJyZXZpYXRpb25zIGFyZTpcbiAqXG4gKiAgIGk6IGkvaiBjb29yZGluYXRlcyBhbG9uZyB0aGUgZ3JpZC4gSW50ZWdlciB2YWx1ZXMgY29ycmVzcG9uZCB0byBkYXRhIHBvaW50c1xuICogICBhOiByZWFsLXZhbHVlZCBjb29yZGluYXRlcyBhbG9uZyB0aGUgYS9iIGF4ZXNcbiAqICAgYzogY2FydGVzaWFuIHgteSBjb29yZGluYXRlc1xuICogICBwOiBzY3JlZW4tc3BhY2UgcGl4ZWwgY29vcmRpbmF0ZXNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzZXRDb252ZXJ0KHRyYWNlKSB7XG4gICAgdmFyIGEgPSB0cmFjZS5fYTtcbiAgICB2YXIgYiA9IHRyYWNlLl9iO1xuICAgIHZhciBuYSA9IGEubGVuZ3RoO1xuICAgIHZhciBuYiA9IGIubGVuZ3RoO1xuICAgIHZhciBhYXggPSB0cmFjZS5hYXhpcztcbiAgICB2YXIgYmF4ID0gdHJhY2UuYmF4aXM7XG5cbiAgICAvLyBHcmFiIHRoZSBsaW1pdHMgb25jZSByYXRoZXIgdGhhbiByZWNvbXB1dGluZyB0aGUgYm91bmRzIGZvciBldmVyeSBwb2ludFxuICAgIC8vIGluZGVwZW5kZW50bHk6XG4gICAgdmFyIGFtaW4gPSBhWzBdO1xuICAgIHZhciBhbWF4ID0gYVtuYSAtIDFdO1xuICAgIHZhciBibWluID0gYlswXTtcbiAgICB2YXIgYm1heCA9IGJbbmIgLSAxXTtcbiAgICB2YXIgYXJhbmdlID0gYVthLmxlbmd0aCAtIDFdIC0gYVswXTtcbiAgICB2YXIgYnJhbmdlID0gYltiLmxlbmd0aCAtIDFdIC0gYlswXTtcblxuICAgIC8vIENvbXB1dGUgdGhlIHRvbGVyYW5jZSBzbyB0aGF0IHBvaW50cyBhcmUgdmlzaWJsZSBzbGlnaHRseSBvdXRzaWRlIHRoZVxuICAgIC8vIGRlZmluZWQgY2FycGV0IGF4aXM6XG4gICAgdmFyIGF0b2wgPSBhcmFuZ2UgKiBjb25zdGFudHMuUkVMQVRJVkVfQ1VMTF9UT0xFUkFOQ0U7XG4gICAgdmFyIGJ0b2wgPSBicmFuZ2UgKiBjb25zdGFudHMuUkVMQVRJVkVfQ1VMTF9UT0xFUkFOQ0U7XG5cbiAgICAvLyBFeHBhbmQgdGhlIGxpbWl0cyB0byBpbmNsdWRlIHRoZSByZWxhdGl2ZSB0b2xlcmFuY2U6XG4gICAgYW1pbiAtPSBhdG9sO1xuICAgIGFtYXggKz0gYXRvbDtcbiAgICBibWluIC09IGJ0b2w7XG4gICAgYm1heCArPSBidG9sO1xuXG4gICAgdHJhY2UuaXNWaXNpYmxlID0gZnVuY3Rpb24oYSwgYikge1xuICAgICAgICByZXR1cm4gYSA+IGFtaW4gJiYgYSA8IGFtYXggJiYgYiA+IGJtaW4gJiYgYiA8IGJtYXg7XG4gICAgfTtcblxuICAgIHRyYWNlLmlzT2NjbHVkZWQgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBhIDwgYW1pbiB8fCBhID4gYW1heCB8fCBiIDwgYm1pbiB8fCBiID4gYm1heDtcbiAgICB9O1xuXG4gICAgdHJhY2Uuc2V0U2NhbGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHggPSB0cmFjZS5feDtcbiAgICAgICAgdmFyIHkgPSB0cmFjZS5feTtcblxuICAgICAgICAvLyBUaGlzIGlzIHBvdGVudGlhbGx5IGEgdmVyeSBleHBlbnNpdmUgc3RlcCEgSXQgZG9lcyB0aGUgYnVsayBvZiB0aGUgd29yayBvZiBjb25zdHJ1Y3RpbmdcbiAgICAgICAgLy8gYW4gZXhwYW5kZWQgYmFzaXMgb2YgY29udHJvbCBwb2ludHMuIE5vdGUgaW4gcGFydGljdWxhciB0aGF0IGl0IG92ZXJ3cml0ZXMgdGhlIGV4aXN0aW5nXG4gICAgICAgIC8vIGJhc2lzIHdpdGhvdXQgY3JlYXRpbmcgYSBuZXcgYXJyYXkgc2luY2UgdGhhdCB3b3VsZCBwb3RlbnRpYWxseSB0aHJhc2ggdGhlIGdhcmJhZ2VcbiAgICAgICAgLy8gY29sbGVjdG9yLlxuICAgICAgICB2YXIgcmVzdWx0ID0gY29tcHV0ZUNvbnRyb2xQb2ludHModHJhY2UuX3hjdHJsLCB0cmFjZS5feWN0cmwsIHgsIHksIGFheC5zbW9vdGhpbmcsIGJheC5zbW9vdGhpbmcpO1xuICAgICAgICB0cmFjZS5feGN0cmwgPSByZXN1bHRbMF07XG4gICAgICAgIHRyYWNlLl95Y3RybCA9IHJlc3VsdFsxXTtcblxuICAgICAgICAvLyBUaGlzIHN0ZXAgaXMgdGhlIHNlY29uZCBzdGVwIGluIHRoZSBwcm9jZXNzLCBidXQgaXQncyBzb21ld2hhdCBzaW1wbGVyLiBJdCBqdXN0IHVucm9sbHNcbiAgICAgICAgLy8gc29tZSBsb2dpYyBzaW5jZSBpdCB3b3VsZCBiZSB1bm5lY2Vzc2FyaWx5IGV4cGVuc2l2ZSB0byBjb21wdXRlIGJvdGggaW50ZXJwb2xhdGlvbnNcbiAgICAgICAgLy8gbmVhcmx5IGlkZW50aWNhbGx5IGJ1dCBzZXBhcmF0ZWx5IGFuZCB0byBpbmNsdWRlIGEgYnVuY2ggb2YgbGluZWFyIHZzLiBiaWN1YmljIGxvZ2ljIGluXG4gICAgICAgIC8vIGV2ZXJ5IHNpbmdsZSBjYWxsLlxuICAgICAgICB0cmFjZS5ldmFseHkgPSBjcmVhdGVTcGxpbmVFdmFsdWF0b3IoW3RyYWNlLl94Y3RybCwgdHJhY2UuX3ljdHJsXSwgbmEsIG5iLCBhYXguc21vb3RoaW5nLCBiYXguc21vb3RoaW5nKTtcblxuICAgICAgICB0cmFjZS5keHlkaSA9IGNyZWF0ZUlEZXJpdmF0aXZlRXZhbHVhdG9yKFt0cmFjZS5feGN0cmwsIHRyYWNlLl95Y3RybF0sIGFheC5zbW9vdGhpbmcsIGJheC5zbW9vdGhpbmcpO1xuICAgICAgICB0cmFjZS5keHlkaiA9IGNyZWF0ZUpEZXJpdmF0aXZlRXZhbHVhdG9yKFt0cmFjZS5feGN0cmwsIHRyYWNlLl95Y3RybF0sIGFheC5zbW9vdGhpbmcsIGJheC5zbW9vdGhpbmcpO1xuICAgIH07XG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgZnJvbSBpL2ogZGF0YSBncmlkIGNvb3JkaW5hdGVzIHRvIGEvYiB2YWx1ZXMuIE5vdGUgaW4gcGFydGljdWxhciB0aGF0IHRoaXNcbiAgICAgKiBpcyAqbGluZWFyKiBpbnRlcnBvbGF0aW9uLCBldmVuIGlmIHRoZSBkYXRhIGlzIGludGVycG9sYXRlZCBiaWN1YmljYWxseS5cbiAgICAgKi9cbiAgICB0cmFjZS5pMmEgPSBmdW5jdGlvbihpKSB7XG4gICAgICAgIHZhciBpMCA9IE1hdGgubWF4KDAsIE1hdGguZmxvb3IoaVswXSksIG5hIC0gMik7XG4gICAgICAgIHZhciB0aSA9IGlbMF0gLSBpMDtcbiAgICAgICAgcmV0dXJuICgxIC0gdGkpICogYVtpMF0gKyB0aSAqIGFbaTAgKyAxXTtcbiAgICB9O1xuXG4gICAgdHJhY2UuajJiID0gZnVuY3Rpb24oaikge1xuICAgICAgICB2YXIgajAgPSBNYXRoLm1heCgwLCBNYXRoLmZsb29yKGpbMV0pLCBuYSAtIDIpO1xuICAgICAgICB2YXIgdGogPSBqWzFdIC0gajA7XG4gICAgICAgIHJldHVybiAoMSAtIHRqKSAqIGJbajBdICsgdGogKiBiW2owICsgMV07XG4gICAgfTtcblxuICAgIHRyYWNlLmlqMmFiID0gZnVuY3Rpb24oaWopIHtcbiAgICAgICAgcmV0dXJuIFt0cmFjZS5pMmEoaWpbMF0pLCB0cmFjZS5qMmIoaWpbMV0pXTtcbiAgICB9O1xuXG4gICAgLypcbiAgICAgKiBDb252ZXJ0IGZyb20gYS9iIGNvb3JkaW5hdGVzIHRvIGkvaiBncmlkLW51bWJlcmVkIGNvb3JkaW5hdGVzLiBUaGlzIHJlcXVpcmVzIHNlYXJjaGluZ1xuICAgICAqIHRocm91Z2ggdGhlIGEvYiBkYXRhIGFycmF5cyBhbmQgYXNzdW1lcyB0aGV5IGFyZSBtb25vdG9uaWMsIHdoaWNoIGlzIHByZXN1bWVkIHRvIGhhdmVcbiAgICAgKiBiZWVuIGVuZm9yY2VkIGFscmVhZHkuXG4gICAgICovXG4gICAgdHJhY2UuYTJpID0gZnVuY3Rpb24oYXZhbCkge1xuICAgICAgICB2YXIgaTAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihzZWFyY2goYXZhbCwgYSksIG5hIC0gMikpO1xuICAgICAgICB2YXIgYTAgPSBhW2kwXTtcbiAgICAgICAgdmFyIGExID0gYVtpMCArIDFdO1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4obmEgLSAxLCBpMCArIChhdmFsIC0gYTApIC8gKGExIC0gYTApKSk7XG4gICAgfTtcblxuICAgIHRyYWNlLmIyaiA9IGZ1bmN0aW9uKGJ2YWwpIHtcbiAgICAgICAgdmFyIGowID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oc2VhcmNoKGJ2YWwsIGIpLCBuYiAtIDIpKTtcbiAgICAgICAgdmFyIGIwID0gYltqMF07XG4gICAgICAgIHZhciBiMSA9IGJbajAgKyAxXTtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KDAsIE1hdGgubWluKG5iIC0gMSwgajAgKyAoYnZhbCAtIGIwKSAvIChiMSAtIGIwKSkpO1xuICAgIH07XG5cbiAgICB0cmFjZS5hYjJpaiA9IGZ1bmN0aW9uKGFiKSB7XG4gICAgICAgIHJldHVybiBbdHJhY2UuYTJpKGFiWzBdKSwgdHJhY2UuYjJqKGFiWzFdKV07XG4gICAgfTtcblxuICAgIC8qXG4gICAgICogQ29udmVydCBmcm9tIGkvaiBjb29yZGluYXRlcyB0byB4L3kgY2FyZXRlc2lhbiBjb29yZGluYXRlcy4gVGhpcyBtZWFucyBlaXRoZXIgYmlsaW5lYXJcbiAgICAgKiBvciBiaWN1YmljIHNwbGluZSBldmFsdWF0aW9uLCBidXQgdGhlIGhhcmQgcGFydCBpcyBhbHJlYWR5IGRvbmUgYXQgdGhpcyBwb2ludC5cbiAgICAgKi9cbiAgICB0cmFjZS5pMmMgPSBmdW5jdGlvbihpLCBqKSB7XG4gICAgICAgIHJldHVybiB0cmFjZS5ldmFseHkoW10sIGksIGopO1xuICAgIH07XG5cbiAgICB0cmFjZS5hYjJ4eSA9IGZ1bmN0aW9uKGF2YWwsIGJ2YWwsIGV4dHJhcG9sYXRlKSB7XG4gICAgICAgIGlmKCFleHRyYXBvbGF0ZSAmJiAoYXZhbCA8IGFbMF0gfHwgYXZhbCA+IGFbbmEgLSAxXSB8IGJ2YWwgPCBiWzBdIHx8IGJ2YWwgPiBiW25iIC0gMV0pKSB7XG4gICAgICAgICAgICByZXR1cm4gW2ZhbHNlLCBmYWxzZV07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0cmFjZS5hMmkoYXZhbCk7XG4gICAgICAgIHZhciBqID0gdHJhY2UuYjJqKGJ2YWwpO1xuXG4gICAgICAgIHZhciBwdCA9IHRyYWNlLmV2YWx4eShbXSwgaSwgaik7XG5cbiAgICAgICAgaWYoZXh0cmFwb2xhdGUpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgc2VjdGlvbiB1c2VzIHRoZSBib3VuZGFyeSBkZXJpdmF0aXZlcyB0byBleHRyYXBvbGF0ZSBsaW5lYXJseSBvdXRzaWRlXG4gICAgICAgICAgICAvLyB0aGUgZGVmaW5lZCByYW5nZS4gQ29uc2lkZXIgYSBzY2F0dGVyIGxpbmUgd2l0aCBvbmUgcG9pbnQgaW5zaWRlIHRoZSBjYXJwZXRcbiAgICAgICAgICAgIC8vIGF4aXMgYW5kIG9uZSBwb2ludCBvdXRzaWRlLiBJZiB3ZSBkb24ndCBleHRyYXBvbGF0ZSwgd2UgY2FuJ3QgZHJhdyB0aGUgbGluZVxuICAgICAgICAgICAgLy8gYXQgYWxsLlxuICAgICAgICAgICAgdmFyIGlleCA9IDA7XG4gICAgICAgICAgICB2YXIgamV4ID0gMDtcbiAgICAgICAgICAgIHZhciBkZXIgPSBbXTtcblxuICAgICAgICAgICAgdmFyIGkwLCB0aSwgajAsIHRqO1xuICAgICAgICAgICAgaWYoYXZhbCA8IGFbMF0pIHtcbiAgICAgICAgICAgICAgICBpMCA9IDA7XG4gICAgICAgICAgICAgICAgdGkgPSAwO1xuICAgICAgICAgICAgICAgIGlleCA9IChhdmFsIC0gYVswXSkgLyAoYVsxXSAtIGFbMF0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGF2YWwgPiBhW25hIC0gMV0pIHtcbiAgICAgICAgICAgICAgICBpMCA9IG5hIC0gMjtcbiAgICAgICAgICAgICAgICB0aSA9IDE7XG4gICAgICAgICAgICAgICAgaWV4ID0gKGF2YWwgLSBhW25hIC0gMV0pIC8gKGFbbmEgLSAxXSAtIGFbbmEgLSAyXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGkwID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obmEgLSAyLCBNYXRoLmZsb29yKGkpKSk7XG4gICAgICAgICAgICAgICAgdGkgPSBpIC0gaTA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGJ2YWwgPCBiWzBdKSB7XG4gICAgICAgICAgICAgICAgajAgPSAwO1xuICAgICAgICAgICAgICAgIHRqID0gMDtcbiAgICAgICAgICAgICAgICBqZXggPSAoYnZhbCAtIGJbMF0pIC8gKGJbMV0gLSBiWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihidmFsID4gYltuYiAtIDFdKSB7XG4gICAgICAgICAgICAgICAgajAgPSBuYiAtIDI7XG4gICAgICAgICAgICAgICAgdGogPSAxO1xuICAgICAgICAgICAgICAgIGpleCA9IChidmFsIC0gYltuYiAtIDFdKSAvIChiW25iIC0gMV0gLSBiW25iIC0gMl0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBqMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKG5iIC0gMiwgTWF0aC5mbG9vcihqKSkpO1xuICAgICAgICAgICAgICAgIHRqID0gaiAtIGowO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihpZXgpIHtcbiAgICAgICAgICAgICAgICB0cmFjZS5keHlkaShkZXIsIGkwLCBqMCwgdGksIHRqKTtcbiAgICAgICAgICAgICAgICBwdFswXSArPSBkZXJbMF0gKiBpZXg7XG4gICAgICAgICAgICAgICAgcHRbMV0gKz0gZGVyWzFdICogaWV4O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihqZXgpIHtcbiAgICAgICAgICAgICAgICB0cmFjZS5keHlkaihkZXIsIGkwLCBqMCwgdGksIHRqKTtcbiAgICAgICAgICAgICAgICBwdFswXSArPSBkZXJbMF0gKiBqZXg7XG4gICAgICAgICAgICAgICAgcHRbMV0gKz0gZGVyWzFdICogamV4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHB0O1xuICAgIH07XG5cblxuICAgIHRyYWNlLmMycCA9IGZ1bmN0aW9uKHh5LCB4YSwgeWEpIHtcbiAgICAgICAgcmV0dXJuIFt4YS5jMnAoeHlbMF0pLCB5YS5jMnAoeHlbMV0pXTtcbiAgICB9O1xuXG4gICAgdHJhY2UucDJ4ID0gZnVuY3Rpb24ocCwgeGEsIHlhKSB7XG4gICAgICAgIHJldHVybiBbeGEucDJjKHBbMF0pLCB5YS5wMmMocFsxXSldO1xuICAgIH07XG5cbiAgICB0cmFjZS5kYWRpID0gZnVuY3Rpb24oaSAvKiAsIHUqLykge1xuICAgICAgICAvLyBSaWdodCBub3cgb25seSBhIHBpZWNld2lzZSBsaW5lYXIgYSBvciBiIGJhc2lzIGlzIHBlcm1pdHRlZCBzaW5jZSBzbW9vdGhlciBpbnRlcnBvbGF0aW9uXG4gICAgICAgIC8vIHdvdWxkIGNhdXNlIG1vbm90b25pY2l0eSBwcm9ibGVtcy4gQXMgYSByZXR1bHQsIHUgaXMgZW50aXJlbHkgZGlzcmVnYXJkZWQgaW4gdGhpc1xuICAgICAgICAvLyBjb21wdXRhdGlvbiwgdGhvdWdoIHdlJ2xsIHNwZWNpZnkgaXQgYXMgYSBwYXJhbWV0ZXIgZm9yIHRoZSBzYWtlIG9mIGNvbXBsZXRlbmVzcyBhbmRcbiAgICAgICAgLy8gZnV0dXJlLXByb29maW5nLiBJdCB3b3VsZCBiZSBwb3NzaWJsZSB0byB1c2UgbW9ub3RvbmljIGN1YmljIGludGVycG9sYXRpb24sIGZvciBleGFtcGxlLlxuICAgICAgICAvL1xuICAgICAgICAvLyBTZWU6IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01vbm90b25lX2N1YmljX2ludGVycG9sYXRpb25cblxuICAgICAgICAvLyB1ID0gdSB8fCAwO1xuXG4gICAgICAgIHZhciBpMCA9IE1hdGgubWF4KDAsIE1hdGgubWluKGEubGVuZ3RoIC0gMiwgaSkpO1xuXG4gICAgICAgIC8vIFRoZSBzdGVwIChkZW1vbmluYXRvcikgaXMgaW1wbGljaXRseSAxIHNpbmNlIHRoYXQncyB0aGUgZ3JpZCBzcGFjaW5nLlxuICAgICAgICByZXR1cm4gYVtpMCArIDFdIC0gYVtpMF07XG4gICAgfTtcblxuICAgIHRyYWNlLmRiZGogPSBmdW5jdGlvbihqIC8qICwgdiovKSB7XG4gICAgICAgIC8vIFNlZSBhYm92ZSBjYXZlYXRzIGZvciBkYWRpIHdoaWNoIGFsc28gYXBwbHkgaGVyZVxuICAgICAgICB2YXIgajAgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihiLmxlbmd0aCAtIDIsIGopKTtcblxuICAgICAgICAvLyBUaGUgc3RlcCAoZGVtb25pbmF0b3IpIGlzIGltcGxpY2l0bHkgMSBzaW5jZSB0aGF0J3MgdGhlIGdyaWQgc3BhY2luZy5cbiAgICAgICAgcmV0dXJuIGJbajAgKyAxXSAtIGJbajBdO1xuICAgIH07XG5cbiAgICAvLyBUYWtlczogZ3JpZCBjZWxsIGNvb3JkaW5hdGUgKGksIGopIGFuZCBmcmFjdGlvbmFsIGdyaWQgY2VsbCBjb29yZGluYXRlcyAodSwgdilcbiAgICAvLyBSZXR1cm5zOiAoZHgvZGEsIGR5L2RiKVxuICAgIC8vXG4gICAgLy8gTkI6IHNlcGFyYXRlIGdyaWQgY2VsbCArIGZyYWN0aW9uYWwgZ3JpZCBjZWxsIGNvb3JkaW5hdGUgZm9ybWF0IGlzIGR1ZSB0byB0aGUgZGlzY29udGludW91c1xuICAgIC8vIGRlcml2YXRpdmUsIGFzIGRlc2NyaWJlZCBiZXR0ZXIgaW4gY3JlYXRlX2lfZGVyaXZhdGl2ZV9ldmFsdWF0b3IuanNcbiAgICB0cmFjZS5keHlkYSA9IGZ1bmN0aW9uKGkwLCBqMCwgdSwgdikge1xuICAgICAgICB2YXIgZHh5ZGkgPSB0cmFjZS5keHlkaShudWxsLCBpMCwgajAsIHUsIHYpO1xuICAgICAgICB2YXIgZGFkaSA9IHRyYWNlLmRhZGkoaTAsIHUpO1xuXG4gICAgICAgIHJldHVybiBbZHh5ZGlbMF0gLyBkYWRpLCBkeHlkaVsxXSAvIGRhZGldO1xuICAgIH07XG5cbiAgICB0cmFjZS5keHlkYiA9IGZ1bmN0aW9uKGkwLCBqMCwgdSwgdikge1xuICAgICAgICB2YXIgZHh5ZGogPSB0cmFjZS5keHlkaihudWxsLCBpMCwgajAsIHUsIHYpO1xuICAgICAgICB2YXIgZGJkaiA9IHRyYWNlLmRiZGooajAsIHYpO1xuXG4gICAgICAgIHJldHVybiBbZHh5ZGpbMF0gLyBkYmRqLCBkeHlkalsxXSAvIGRiZGpdO1xuICAgIH07XG5cbiAgICAvLyBTb21ldGltZXMgd2UgZG9uJ3QgY2FyZSBhYm91dCBwcmVjaXNpb24gYW5kIGFsbCB3ZSByZWFsbHkgd2FudCBpcyBkZWNlbnQgcm91Z2hcbiAgICAvLyBkaXJlY3Rpb25zIChhcyBpcyB0aGUgY2FzZSB3aXRoIGxhYmVscykuIEluIHRoYXQgY2FzZSwgd2UgY2FuIGRvIGEgdmVyeSByb3VnaCBmaW5pdGVcbiAgICAvLyBkaWZmZXJlbmNlIGFuZCBzcGFyZSBoYXZpbmcgdG8gd29ycnkgYWJvdXQgcHJlY2lzZSBncmlkIGNvb3JkaW5hdGVzOlxuICAgIHRyYWNlLmR4eWRhX3JvdWdoID0gZnVuY3Rpb24oYSwgYiwgcmVsZGlmZikge1xuICAgICAgICB2YXIgaCA9IGFyYW5nZSAqIChyZWxkaWZmIHx8IDAuMSk7XG4gICAgICAgIHZhciBwbHVzID0gdHJhY2UuYWIyeHkoYSArIGgsIGIsIHRydWUpO1xuICAgICAgICB2YXIgbWludXMgPSB0cmFjZS5hYjJ4eShhIC0gaCwgYiwgdHJ1ZSk7XG5cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIChwbHVzWzBdIC0gbWludXNbMF0pICogMC41IC8gaCxcbiAgICAgICAgICAgIChwbHVzWzFdIC0gbWludXNbMV0pICogMC41IC8gaFxuICAgICAgICBdO1xuICAgIH07XG5cbiAgICB0cmFjZS5keHlkYl9yb3VnaCA9IGZ1bmN0aW9uKGEsIGIsIHJlbGRpZmYpIHtcbiAgICAgICAgdmFyIGggPSBicmFuZ2UgKiAocmVsZGlmZiB8fCAwLjEpO1xuICAgICAgICB2YXIgcGx1cyA9IHRyYWNlLmFiMnh5KGEsIGIgKyBoLCB0cnVlKTtcbiAgICAgICAgdmFyIG1pbnVzID0gdHJhY2UuYWIyeHkoYSwgYiAtIGgsIHRydWUpO1xuXG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAocGx1c1swXSAtIG1pbnVzWzBdKSAqIDAuNSAvIGgsXG4gICAgICAgICAgICAocGx1c1sxXSAtIG1pbnVzWzFdKSAqIDAuNSAvIGhcbiAgICAgICAgXTtcbiAgICB9O1xuXG4gICAgdHJhY2UuZHBkeCA9IGZ1bmN0aW9uKHhhKSB7XG4gICAgICAgIHJldHVybiB4YS5fbTtcbiAgICB9O1xuXG4gICAgdHJhY2UuZHBkeSA9IGZ1bmN0aW9uKHlhKSB7XG4gICAgICAgIHJldHVybiB5YS5fbTtcbiAgICB9O1xufTtcblxufSx7XCIuLi8uLi9saWIvc2VhcmNoXCI6NzM4LFwiLi9jb21wdXRlX2NvbnRyb2xfcG9pbnRzXCI6OTA4LFwiLi9jb25zdGFudHNcIjo5MDksXCIuL2NyZWF0ZV9pX2Rlcml2YXRpdmVfZXZhbHVhdG9yXCI6OTEwLFwiLi9jcmVhdGVfal9kZXJpdmF0aXZlX2V2YWx1YXRvclwiOjkxMSxcIi4vY3JlYXRlX3NwbGluZV9ldmFsdWF0b3JcIjo5MTJ9XSw5MjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbi8qXG4gKiBHaXZlbiBhIDJEIGFycmF5IGFzIHdlbGwgYXMgYSBiYXNpcyBpbiBlaXRoZXIgZGlyZWN0aW9uLCB0aGlzIGZ1bmN0aW9uIGZpbGxzIGluIHRoZVxuICogMkQgYXJyYXkgdXNpbmcgYSBjb21iaW5hdGlvbiBvZiBzbW9vdGhpbmcgYW5kIGV4dHJhcG9sYXRpb24uIFRoaXMgaXMgcmF0aGVyIGltcG9ydGFudFxuICogZm9yIGNhcnBldCBwbG90cyBzaW5jZSBpdCdzIHVzZWQgZm9yIGxheW91dCBzbyB0aGF0IHdlIGNhbid0IHNpbXBseSBvbWl0IG9yIGJsYW5rIG91dFxuICogcG9pbnRzLiBXZSBuZWVkIGEgcmVhc29uYWJsZSBndWVzcyBzbyB0aGF0IHRoZSBpbnRlcnBvbGF0aW9uIHB1dHMgcG9pbnRzIHNvbWV3aGVyZVxuICogZXZlbiBpZiB3ZSB3ZXJlIHRvIHNvbWVob3cgcmVwcmVzZW50IHRoYXQgdGhlIGRhdGEgd2FzIG1pc3NpbmcgbGF0ZXIgb24uXG4gKlxuICogaW5wdXQ6XG4gKiAgLSBkYXRhOiAyRCBhcnJheSBvZiBhcnJheXNcbiAqICAtIGE6IGFycmF5IHN1Y2ggdGhhdCBhLmxlbmd0aCA9PT0gZGF0YVswXS5sZW5ndGhcbiAqICAtIGI6IGFycmF5IHN1Y2ggdGhhdCBiLmxlbmd0aCA9PT0gZGF0YS5sZW5ndGhcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzbW9vdGhGaWxsMmRBcnJheShkYXRhLCBhLCBiKSB7XG4gICAgdmFyIGksIGosIGs7XG4gICAgdmFyIGlwID0gW107XG4gICAgdmFyIGpwID0gW107XG4gICAgLy8gdmFyIG5laWdoYm9yQ250cyA9IFtdO1xuXG4gICAgdmFyIG5pID0gZGF0YVswXS5sZW5ndGg7XG4gICAgdmFyIG5qID0gZGF0YS5sZW5ndGg7XG5cbiAgICBmdW5jdGlvbiBhdmdTdXJyb3VuZGluZyhpLCBqKSB7XG4gICAgICAgIC8vIEFzIGEgbG93LXF1YWxpdHkgc3RhcnQsIHdlIGNhbiBzaW1wbHkgYXZlcmFnZSBzdXJyb3VuZGluZyBwb2ludHMgKGluIGEgbm90XG4gICAgICAgIC8vIG5vbi11bmlmb3JtIGdyaWQgYXdhcmUgbWFubmVyKTpcbiAgICAgICAgdmFyIHN1bSA9IDAuMDtcbiAgICAgICAgdmFyIHZhbDtcbiAgICAgICAgdmFyIGNudCA9IDA7XG4gICAgICAgIGlmKGkgPiAwICYmICh2YWwgPSBkYXRhW2pdW2kgLSAxXSkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgY250Kys7XG4gICAgICAgICAgICBzdW0gKz0gdmFsO1xuICAgICAgICB9XG4gICAgICAgIGlmKGkgPCBuaSAtIDEgJiYgKHZhbCA9IGRhdGFbal1baSArIDFdKSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjbnQrKztcbiAgICAgICAgICAgIHN1bSArPSB2YWw7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaiA+IDAgJiYgKHZhbCA9IGRhdGFbaiAtIDFdW2ldKSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjbnQrKztcbiAgICAgICAgICAgIHN1bSArPSB2YWw7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaiA8IG5qIC0gMSAmJiAodmFsID0gZGF0YVtqICsgMV1baV0pICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNudCsrO1xuICAgICAgICAgICAgc3VtICs9IHZhbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3VtIC8gTWF0aC5tYXgoMSwgY250KTtcbiAgICB9XG5cbiAgICAvLyBUaGlzIGxvb3AgaXRlcmF0ZXMgb3ZlciBhbGwgY2VsbHMuIEFueSBjZWxscyB0aGF0IGFyZSBudWxsIHdpbGwgYmUgbm90ZWQgYW5kIHRob3NlXG4gICAgLy8gYXJlIHRoZSBvbmx5IHBvaW50cyB3ZSB3aWxsIGxvb3Agb3ZlciBhbmQgdXBkYXRlIHZpYSBsYXBsYWNlJ3MgZXF1YXRpb24uIFBvaW50cyB3aXRoXG4gICAgLy8gYW55IG5laWdoYm9ycyB3aWxsIHJlY2VpdmUgdGhlIGF2ZXJhZ2UuIElmIHRoZXJlIGFyZSBubyBuZWlnaGJvcmluZyBwb2ludHMsIHRoZW4gdGhleVxuICAgIC8vIHdpbGwgYmUgc2V0IHRvIHplcm8uIEFsc28gYXMgd2UgZ28sIHRyYWNrIHRoZSBtYXhpbXVtIG1hZ25pdHVkZSBzbyB0aGF0IHdlIGNhbiBzY2FsZVxuICAgIC8vIG91ciB0b2xlcmFuY2UgYWNjb3JkaW5nbHkuXG4gICAgdmFyIGRtYXggPSAwLjA7XG4gICAgZm9yKGkgPSAwOyBpIDwgbmk7IGkrKykge1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBuajsgaisrKSB7XG4gICAgICAgICAgICBpZihkYXRhW2pdW2ldID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpcC5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIGpwLnB1c2goaik7XG5cbiAgICAgICAgICAgICAgICBkYXRhW2pdW2ldID0gYXZnU3Vycm91bmRpbmcoaSwgaik7XG4gICAgICAgICAgICAgICAgLy8gbmVpZ2hib3JDbnRzLnB1c2gocmVzdWx0Lm5laWdoYm9ycyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkbWF4ID0gTWF0aC5tYXgoZG1heCwgTWF0aC5hYnMoZGF0YVtqXVtpXSkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoIWlwLmxlbmd0aCkgcmV0dXJuIGRhdGE7XG5cbiAgICAvLyBUaGUgdG9sZXJhbmNlIGRvZXNuJ3QgbmVlZCB0byBiZSBleGNlc3NpdmUuIEl0J3MganVzdCBmb3IgZGlzcGxheSBwb3NpdGlvbmluZ1xuICAgIHZhciBkeHAsIGR4bSwgZGFwLCBkYW0sIGRicCwgZGJtLCBjLCBkLCBkaWZmLCByZWxkaWZmLCBvdmVycmVsYXhhdGlvbjtcbiAgICB2YXIgdG9sID0gMWUtNTtcbiAgICB2YXIgcmVzaWQgPSAwO1xuICAgIHZhciBpdGVybWF4ID0gMTAwO1xuICAgIHZhciBpdGVyID0gMDtcbiAgICB2YXIgbiA9IGlwLmxlbmd0aDtcbiAgICBkbyB7XG4gICAgICAgIHJlc2lkID0gMDtcbiAgICAgICAgLy8gTm9ybWFsbHkgd2UnZCBsb29wIGluIHR3byBkaW1lbnNpb25zLCBidXQgbm90IGFsbCBwb2ludHMgYXJlIGJsYW5rIGFuZCBuZWVkXG4gICAgICAgIC8vIGFuIHVwZGF0ZSwgc28gd2UgaW5zdGVhZCBsb29wIG9ubHkgb3ZlciB0aGUgcG9pbnRzIHRoYXQgd2VyZSB0YWJ1bGF0ZWQgYWJvdmVcbiAgICAgICAgZm9yKGsgPSAwOyBrIDwgbjsgaysrKSB7XG4gICAgICAgICAgICBpID0gaXBba107XG4gICAgICAgICAgICBqID0ganBba107XG4gICAgICAgICAgICAvLyBuZWlnaGJvckNudCA9IG5laWdoYm9yQ250c1trXTtcblxuICAgICAgICAgICAgLy8gVHJhY2sgYSBjb3VudGVyIGZvciBob3cgbWFueSBjb250cmlidXRpb25zIHRoZXJlIGFyZS4gV2UnbGwgdXNlIHRoaXMgY291bnRlclxuICAgICAgICAgICAgLy8gdG8gYXZlcmFnZSBhdCB0aGUgZW5kLCB3aGljaCByZWR1Y2VzIHRvIGxhcGxhY2UncyBlcXVhdGlvbiB3aXRoIG5ldW1hbm4gYm91bmRhcnlcbiAgICAgICAgICAgIC8vIGNvbmRpdGlvbnMgb24gdGhlIGZpcnN0IGRlcml2YXRpdmUgKHNlY29uZCBkZXJpdmF0aXZlIGlzIHplcm8gc28gdGhhdCB3ZSBnZXRcbiAgICAgICAgICAgIC8vIGEgbmljZSBsaW5lYXIgZXh0cmFwb2xhdGlvbiBhdCB0aGUgYm91bmRhcmllcykuXG4gICAgICAgICAgICB2YXIgYm91bmRhcnlDbnQgPSAwO1xuICAgICAgICAgICAgdmFyIG5ld1ZhbCA9IDA7XG5cbiAgICAgICAgICAgIHZhciBkMCwgZDEsIHgwLCB4MSwgaTAsIGowO1xuICAgICAgICAgICAgaWYoaSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgbGllcyBhbG9uZyB0aGUgaSA9IDAgYm91bmRhcnksIGV4dHJhcG9sYXRlIGZyb20gdGhlIHR3byBwb2ludHNcbiAgICAgICAgICAgICAgICAvLyB0byB0aGUgcmlnaHQgb2YgdGhpcyBwb2ludC4gTm90ZSB0aGF0IHRoZSBmaW5pdGUgZGlmZmVyZW5jZXMgdGFrZSBpbnRvXG4gICAgICAgICAgICAgICAgLy8gYWNjb3VudCBub24tdW5pZm9ybSBncmlkIHNwYWNpbmc6XG4gICAgICAgICAgICAgICAgaTAgPSBNYXRoLm1pbihuaSAtIDEsIDIpO1xuICAgICAgICAgICAgICAgIHgwID0gYVtpMF07XG4gICAgICAgICAgICAgICAgeDEgPSBhWzFdO1xuICAgICAgICAgICAgICAgIGQwID0gZGF0YVtqXVtpMF07XG4gICAgICAgICAgICAgICAgZDEgPSBkYXRhW2pdWzFdO1xuICAgICAgICAgICAgICAgIG5ld1ZhbCArPSBkMSArIChkMSAtIGQwKSAqIChhWzBdIC0geDEpIC8gKHgxIC0geDApO1xuICAgICAgICAgICAgICAgIGJvdW5kYXJ5Q250Kys7XG4gICAgICAgICAgICB9IGVsc2UgaWYoaSA9PT0gbmkgLSAxKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgYWxvbmcgdGhlIGhpZ2ggaSBib3VuZGFyeSwgZXh0cmFwb2xhdGUgZnJvbSB0aGUgdHdvIHBvaW50cyB0byB0aGVcbiAgICAgICAgICAgICAgICAvLyBsZWZ0IG9mIHRoaXMgcG9pbnRcbiAgICAgICAgICAgICAgICBpMCA9IE1hdGgubWF4KDAsIG5pIC0gMyk7XG4gICAgICAgICAgICAgICAgeDAgPSBhW2kwXTtcbiAgICAgICAgICAgICAgICB4MSA9IGFbbmkgLSAyXTtcbiAgICAgICAgICAgICAgICBkMCA9IGRhdGFbal1baTBdO1xuICAgICAgICAgICAgICAgIGQxID0gZGF0YVtqXVtuaSAtIDJdO1xuICAgICAgICAgICAgICAgIG5ld1ZhbCArPSBkMSArIChkMSAtIGQwKSAqIChhW25pIC0gMV0gLSB4MSkgLyAoeDEgLSB4MCk7XG4gICAgICAgICAgICAgICAgYm91bmRhcnlDbnQrKztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoKGkgPT09IDAgfHwgaSA9PT0gbmkgLSAxKSAmJiAoaiA+IDAgJiYgaiA8IG5qIC0gMSkpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBhbG9uZyB0aGUgbWluKGkpIG9yIG1heChpKSBib3VuZGFyaWVzLCBhbHNvIHNtb290aCB2ZXJ0aWNhbGx5IGFzIGxvbmdcbiAgICAgICAgICAgICAgICAvLyBhcyB3ZSdyZSBub3QgaW4gYSBjb3JuZXIuIE5vdGUgdGhhdCB0aGUgZmluaXRlIGRpZmZlcmVuY2VzIHVzZWQgaGVyZVxuICAgICAgICAgICAgICAgIC8vIGFyZSBhbHNvIGF3YXJlIG9mIG5vbnVuaWZvcm0gZ3JpZCBzcGFjaW5nOlxuICAgICAgICAgICAgICAgIGR4cCA9IGJbaiArIDFdIC0gYltqXTtcbiAgICAgICAgICAgICAgICBkeG0gPSBiW2pdIC0gYltqIC0gMV07XG4gICAgICAgICAgICAgICAgbmV3VmFsICs9IChkeG0gKiBkYXRhW2ogKyAxXVtpXSArIGR4cCAqIGRhdGFbaiAtIDFdW2ldKSAvIChkeG0gKyBkeHApO1xuICAgICAgICAgICAgICAgIGJvdW5kYXJ5Q250Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKGogPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBhbG9uZyB0aGUgaiA9IDAgYm91bmRhcnksIGV4dHJwb2xhdGUgdGhpcyBwb2ludCBmcm9tIHRoZSB0d28gcG9pbnRzXG4gICAgICAgICAgICAgICAgLy8gYWJvdmUgaXRcbiAgICAgICAgICAgICAgICBqMCA9IE1hdGgubWluKG5qIC0gMSwgMik7XG4gICAgICAgICAgICAgICAgeDAgPSBiW2owXTtcbiAgICAgICAgICAgICAgICB4MSA9IGJbMV07XG4gICAgICAgICAgICAgICAgZDAgPSBkYXRhW2owXVtpXTtcbiAgICAgICAgICAgICAgICBkMSA9IGRhdGFbMV1baV07XG4gICAgICAgICAgICAgICAgbmV3VmFsICs9IGQxICsgKGQxIC0gZDApICogKGJbMF0gLSB4MSkgLyAoeDEgLSB4MCk7XG4gICAgICAgICAgICAgICAgYm91bmRhcnlDbnQrKztcbiAgICAgICAgICAgIH0gZWxzZSBpZihqID09PSBuaiAtIDEpIHtcbiAgICAgICAgICAgICAgICAvLyBTYW1lIGZvciB0aGUgbWF4IGogYm91bmRhcnkgZnJvbSB0aGUgY2VsbHMgYmVsb3cgaXQ6XG4gICAgICAgICAgICAgICAgajAgPSBNYXRoLm1heCgwLCBuaiAtIDMpO1xuICAgICAgICAgICAgICAgIHgwID0gYltqMF07XG4gICAgICAgICAgICAgICAgeDEgPSBiW25qIC0gMl07XG4gICAgICAgICAgICAgICAgZDAgPSBkYXRhW2owXVtpXTtcbiAgICAgICAgICAgICAgICBkMSA9IGRhdGFbbmogLSAyXVtpXTtcbiAgICAgICAgICAgICAgICBuZXdWYWwgKz0gZDEgKyAoZDEgLSBkMCkgKiAoYltuaiAtIDFdIC0geDEpIC8gKHgxIC0geDApO1xuICAgICAgICAgICAgICAgIGJvdW5kYXJ5Q250Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKChqID09PSAwIHx8IGogPT09IG5qIC0gMSkgJiYgKGkgPiAwICYmIGkgPCBuaSAtIDEpKSB7XG4gICAgICAgICAgICAgICAgLy8gTm93IGF2ZXJhZ2UgcG9pbnRzIHRvIHRoZSBsZWZ0L3JpZ2h0IGFzIGxvbmcgYXMgbm90IGluIGEgY29ybmVyOlxuICAgICAgICAgICAgICAgIGR4cCA9IGFbaSArIDFdIC0gYVtpXTtcbiAgICAgICAgICAgICAgICBkeG0gPSBhW2ldIC0gYVtpIC0gMV07XG4gICAgICAgICAgICAgICAgbmV3VmFsICs9IChkeG0gKiBkYXRhW2pdW2kgKyAxXSArIGR4cCAqIGRhdGFbal1baSAtIDFdKSAvIChkeG0gKyBkeHApO1xuICAgICAgICAgICAgICAgIGJvdW5kYXJ5Q250Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKCFib3VuZGFyeUNudCkge1xuICAgICAgICAgICAgICAgIC8vIElmIG5vbmUgb2YgdGhlIGFib3ZlIGNvbmRpdGlvbnMgd2VyZSB0cmlnZ2VyZWQsIHRoZW4gdGhpcyBpcyBhbiBpbnRlcmlvclxuICAgICAgICAgICAgICAgIC8vIHBvaW50IGFuZCB3ZSBjYW4ganVzdCBkbyBhIGxhcGxhY2UgZXF1YXRpb24gdXBkYXRlLiBBcyBhYm92ZSwgdGhlc2UgZGlmZmVyZW5jZXNcbiAgICAgICAgICAgICAgICAvLyBhcmUgYXdhcmUgb2Ygbm9udW5pZm9ybSBncmlkIHNwYWNpbmc6XG4gICAgICAgICAgICAgICAgZGFwID0gYVtpICsgMV0gLSBhW2ldO1xuICAgICAgICAgICAgICAgIGRhbSA9IGFbaV0gLSBhW2kgLSAxXTtcbiAgICAgICAgICAgICAgICBkYnAgPSBiW2ogKyAxXSAtIGJbal07XG4gICAgICAgICAgICAgICAgZGJtID0gYltqXSAtIGJbaiAtIDFdO1xuXG4gICAgICAgICAgICAgICAgLy8gVGhlc2UgYXJlIGp1c3Qgc29tZSB1c2VmdWwgY29uc3RhbnRzIGZvciB0aGUgaXRlcmF0aW9uLCB3aGljaCBpcyBwZXJmZWN0bHlcbiAgICAgICAgICAgICAgICAvLyBzdHJhaWdodGZvcndhcmQgYnV0IGEgbGl0dGxlIGxvbmcgdG8gZGVyaXZlIGZyb20gZl94eCArIGZfeXkgPSAwLlxuICAgICAgICAgICAgICAgIGMgPSBkYXAgKiBkYW0gKiAoZGFwICsgZGFtKTtcbiAgICAgICAgICAgICAgICBkID0gZGJwICogZGJtICogKGRicCArIGRibSk7XG5cbiAgICAgICAgICAgICAgICBuZXdWYWwgPSAoYyAqIChkYm0gKiBkYXRhW2ogKyAxXVtpXSArIGRicCAqIGRhdGFbaiAtIDFdW2ldKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGQgKiAoZGFtICogZGF0YVtqXVtpICsgMV0gKyBkYXAgKiBkYXRhW2pdW2kgLSAxXSkpIC9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgKGQgKiAoZGFtICsgZGFwKSArIGMgKiAoZGJtICsgZGJwKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIElmIHdlIGRpZCBoYXZlIGNvbnRyaWJ1dGlvbnMgZnJvbSB0aGUgYm91bmRhcnkgY29uZGl0aW9ucywgdGhlbiBhdmVyYWdlXG4gICAgICAgICAgICAgICAgLy8gdGhlIHJlc3VsdCBmcm9tIHRoZSB2YXJpb3VzIGNvbnRyaWJ1dGlvbnM6XG4gICAgICAgICAgICAgICAgbmV3VmFsIC89IGJvdW5kYXJ5Q250O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBKYWNvYmkgdXBkYXRlcyBhcmUgcmlkaWN1bG91c2x5IHNsb3cgdG8gY29udmVyZ2UsIHNvIHRoaXMgYXBwcm9hY2ggdXNlcyBhXG4gICAgICAgICAgICAvLyBHYXVzcy1zZWlkZWwgaXRlcmF0aW9uIHdoaWNoIGlzIGRyYW1hdGljYWxseSBmYXN0ZXIuXG4gICAgICAgICAgICBkaWZmID0gbmV3VmFsIC0gZGF0YVtqXVtpXTtcbiAgICAgICAgICAgIHJlbGRpZmYgPSBkaWZmIC8gZG1heDtcbiAgICAgICAgICAgIHJlc2lkICs9IHJlbGRpZmYgKiByZWxkaWZmO1xuXG4gICAgICAgICAgICAvLyBHYXVzcy1TZWlkZWwtaXNoIGl0ZXJhdGlvbiwgb21lZ2EgY2hvc2VuIGJhc2VkIG9uIGhldXJpc3RpY3MgYW5kIHNvbWVcbiAgICAgICAgICAgIC8vIHF1aWNrIHRlc3RzLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIE5COiBEb24ndCBvdmVycmVsYXggdGhlIGJvdW5kYXJpZS4gT3RoZXJ3aXNlIHNldCBhbiBvdmVycmVsYXhhdGlvbiBmYWN0b3JcbiAgICAgICAgICAgIC8vIHdoaWNoIGlzIGEgbGl0dGxlIGxvdyBidXQgc2FmZWx5IG9wdGltYWwtaXNoOlxuICAgICAgICAgICAgb3ZlcnJlbGF4YXRpb24gPSBib3VuZGFyeUNudCA/IDAgOiAwLjg1O1xuXG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgZm91ciBub24tbnVsbCBuZWlnaGJvcnMsIHRoZW4gd2Ugd2FudCBhIHNpbXBsZSBhdmVyYWdlIHdpdGhvdXRcbiAgICAgICAgICAgIC8vIG92ZXJyZWxheGF0aW9uLiBJZiBhbGwgdGhlIHN1cnJvdWRpbmcgcG9pbnRzIGFyZSBudWxsLCB0aGVuIHdlIHdhbnQgdGhlIGZ1bGxcbiAgICAgICAgICAgIC8vIG92ZXJyZWxheGF0aW9uXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gQmFzZWQgb24gZXhwZXJpbWVudHMsIHRoaXMgYWN0dWFsbHkgc2VlbXMgdG8gc2xvdyBkb3duIGNvbnZlcmdlbmNlIGp1c3QgYSBiaXQuXG4gICAgICAgICAgICAvLyBJJ2xsIGxlYXZlIGl0IGhlcmUgZm9yIHJlZmVyZW5jZSBpbiBjYXNlIHRoaXMgbmVlZHMgdG8gYmUgcmV2aXNpdGVkLCBidXRcbiAgICAgICAgICAgIC8vIGl0IHNlZW1zIHRvIHdvcmsganVzdCBmaW5lIHdpdGhvdXQgdGhpcy5cbiAgICAgICAgICAgIC8vIGlmIChvdmVycmVsYXhhdGlvbikgb3ZlcnJlbGF4YXRpb24gKj0gKDQgLSBuZWlnaGJvckNudCkgLyA0O1xuXG4gICAgICAgICAgICBkYXRhW2pdW2ldICs9IGRpZmYgKiAoMSArIG92ZXJyZWxheGF0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc2lkID0gTWF0aC5zcXJ0KHJlc2lkKTtcbiAgICB9IHdoaWxlKGl0ZXIrKyA8IGl0ZXJtYXggJiYgcmVzaWQgPiB0b2wpO1xuXG4gICAgTGliLmxvZygnU21vb3RoZXIgY29udmVyZ2VkIHRvJywgcmVzaWQsICdhZnRlcicsIGl0ZXIsICdpdGVyYXRpb25zJyk7XG5cbiAgICByZXR1cm4gZGF0YTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sOTIyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNBcnJheTFEID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheTFEO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSkge1xuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIGhhc1ggPSB4ICYmIHgubGVuZ3RoO1xuICAgIHZhciB5ID0gY29lcmNlKCd5Jyk7XG4gICAgdmFyIGhhc1kgPSB5ICYmIHkubGVuZ3RoO1xuICAgIGlmKCFoYXNYICYmICFoYXNZKSByZXR1cm4gZmFsc2U7XG5cbiAgICB0cmFjZU91dC5fY2hlYXRlciA9ICF4O1xuXG4gICAgaWYoKCFoYXNYIHx8IGlzQXJyYXkxRCh4KSkgJiYgKCFoYXNZIHx8IGlzQXJyYXkxRCh5KSkpIHtcbiAgICAgICAgdmFyIGxlbiA9IGhhc1ggPyB4Lmxlbmd0aCA6IEluZmluaXR5O1xuICAgICAgICBpZihoYXNZKSBsZW4gPSBNYXRoLm1pbihsZW4sIHkubGVuZ3RoKTtcbiAgICAgICAgaWYodHJhY2VPdXQuYSAmJiB0cmFjZU91dC5hLmxlbmd0aCkgbGVuID0gTWF0aC5taW4obGVuLCB0cmFjZU91dC5hLmxlbmd0aCk7XG4gICAgICAgIGlmKHRyYWNlT3V0LmIgJiYgdHJhY2VPdXQuYi5sZW5ndGgpIGxlbiA9IE1hdGgubWluKGxlbiwgdHJhY2VPdXQuYi5sZW5ndGgpO1xuICAgICAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuICAgIH0gZWxzZSB0cmFjZU91dC5fbGVuZ3RoID0gbnVsbDtcblxuICAgIHJldHVybiB0cnVlO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTl9XSw5MjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBzY2F0dGVyR2VvQXR0cnMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyZ2VvL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIHBsb3RBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcbnZhciBkZWZhdWx0TGluZSA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpLmRlZmF1bHRMaW5lO1xuXG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG52YXIgc2NhdHRlckdlb01hcmtlckxpbmVBdHRycyA9IHNjYXR0ZXJHZW9BdHRycy5tYXJrZXIubGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSBleHRlbmRGbGF0KHtcbiAgICBsb2NhdGlvbnM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxvY2F0aW9ubW9kZTogc2NhdHRlckdlb0F0dHJzLmxvY2F0aW9ubW9kZSxcbiAgICB6OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0ZXh0OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyR2VvQXR0cnMudGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcnRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJHZW9BdHRycy5ob3ZlcnRleHQsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgbWFya2VyOiB7XG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyR2VvTWFya2VyTGluZUF0dHJzLmNvbG9yLCB7ZGZsdDogZGVmYXVsdExpbmV9KSxcbiAgICAgICAgICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyR2VvTWFya2VyTGluZUF0dHJzLndpZHRoLCB7ZGZsdDogMX0pLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgICAgICB9LFxuICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcblxuICAgIHNlbGVjdGVkOiB7XG4gICAgICAgIG1hcmtlcjoge1xuICAgICAgICAgICAgb3BhY2l0eTogc2NhdHRlckdlb0F0dHJzLnNlbGVjdGVkLm1hcmtlci5vcGFjaXR5LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICB1bnNlbGVjdGVkOiB7XG4gICAgICAgIG1hcmtlcjoge1xuICAgICAgICAgICAgb3BhY2l0eTogc2NhdHRlckdlb0F0dHJzLnVuc2VsZWN0ZWQubWFya2VyLm9wYWNpdHksXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBwbG90QXR0cnMuaG92ZXJpbmZvLCB7XG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGZsYWdzOiBbJ2xvY2F0aW9uJywgJ3onLCAndGV4dCcsICduYW1lJ11cbiAgICB9KSxcbiAgICBob3ZlcnRlbXBsYXRlOiBob3ZlcnRlbXBsYXRlQXR0cnMoKSxcbn0sXG5cbiAgICBjb2xvclNjYWxlQXR0cnMoJycsIHtcbiAgICAgICAgY0xldHRlcjogJ3onLFxuICAgICAgICBlZGl0VHlwZU92ZXJyaWRlOiAnY2FsYydcbiAgICB9KVxuKTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXNcIjo1OTIsXCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9zY2F0dGVyZ2VvL2F0dHJpYnV0ZXNcIjoxMTUxfV0sOTI0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgQkFETlVNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxudmFyIGNvbG9yc2NhbGVDYWxjID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcbnZhciBhcnJheXNUb0NhbGNkYXRhID0gX2RlcmVxXygnLi4vc2NhdHRlci9hcnJheXNfdG9fY2FsY2RhdGEnKTtcbnZhciBjYWxjU2VsZWN0aW9uID0gX2RlcmVxXygnLi4vc2NhdHRlci9jYWxjX3NlbGVjdGlvbicpO1xuXG5mdW5jdGlvbiBpc05vbkJsYW5rU3RyaW5nKHYpIHtcbiAgICByZXR1cm4gdiAmJiB0eXBlb2YgdiA9PT0gJ3N0cmluZyc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgbGVuID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgY2FsY1RyYWNlID0gbmV3IEFycmF5KGxlbik7XG5cbiAgICB2YXIgaXNWYWxpZExvYztcblxuICAgIGlmKHRyYWNlLmdlb2pzb24pIHtcbiAgICAgICAgaXNWYWxpZExvYyA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGlzTm9uQmxhbmtTdHJpbmcodikgfHwgaXNOdW1lcmljKHYpOyB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlzVmFsaWRMb2MgPSBpc05vbkJsYW5rU3RyaW5nO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgY2FsY1B0ID0gY2FsY1RyYWNlW2ldID0ge307XG4gICAgICAgIHZhciBsb2MgPSB0cmFjZS5sb2NhdGlvbnNbaV07XG4gICAgICAgIHZhciB6ID0gdHJhY2UueltpXTtcblxuICAgICAgICBpZihpc1ZhbGlkTG9jKGxvYykgJiYgaXNOdW1lcmljKHopKSB7XG4gICAgICAgICAgICBjYWxjUHQubG9jID0gbG9jO1xuICAgICAgICAgICAgY2FsY1B0LnogPSB6O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FsY1B0LmxvYyA9IG51bGw7XG4gICAgICAgICAgICBjYWxjUHQueiA9IEJBRE5VTTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGNQdC5pbmRleCA9IGk7XG4gICAgfVxuXG4gICAgYXJyYXlzVG9DYWxjZGF0YShjYWxjVHJhY2UsIHRyYWNlKTtcbiAgICBjb2xvcnNjYWxlQ2FsYyhnZCwgdHJhY2UsIHtcbiAgICAgICAgdmFsczogdHJhY2UueixcbiAgICAgICAgY29udGFpbmVyU3RyOiAnJyxcbiAgICAgICAgY0xldHRlcjogJ3onXG4gICAgfSk7XG4gICAgY2FsY1NlbGVjdGlvbihjYWxjVHJhY2UsIHRyYWNlKTtcblxuICAgIHJldHVybiBjYWxjVHJhY2U7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjXCI6NjAxLFwiLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbFwiOjY5NSxcIi4uL3NjYXR0ZXIvYXJyYXlzX3RvX2NhbGNkYXRhXCI6MTExMSxcIi4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb25cIjoxMTE0LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSw5MjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsb2NhdGlvbnMgPSBjb2VyY2UoJ2xvY2F0aW9ucycpO1xuICAgIHZhciB6ID0gY29lcmNlKCd6Jyk7XG5cbiAgICBpZighKGxvY2F0aW9ucyAmJiBsb2NhdGlvbnMubGVuZ3RoICYmIExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHopICYmIHoubGVuZ3RoKSkge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gTWF0aC5taW4obG9jYXRpb25zLmxlbmd0aCwgei5sZW5ndGgpO1xuXG4gICAgY29lcmNlKCdsb2NhdGlvbm1vZGUnKTtcblxuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG5cbiAgICB2YXIgbWx3ID0gY29lcmNlKCdtYXJrZXIubGluZS53aWR0aCcpO1xuICAgIGlmKG1sdykgY29lcmNlKCdtYXJrZXIubGluZS5jb2xvcicpO1xuICAgIGNvZXJjZSgnbWFya2VyLm9wYWNpdHknKTtcblxuICAgIGNvbG9yc2NhbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICcnLCBjTGV0dGVyOiAneid9KTtcblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHNcIjo2MDMsXCIuLi8uLi9saWJcIjo3MTksXCIuL2F0dHJpYnV0ZXNcIjo5MjN9XSw5MjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0LCB0cmFjZSwgY2QsIHBvaW50TnVtYmVyKSB7XG4gICAgb3V0LmxvY2F0aW9uID0gcHQubG9jYXRpb247XG4gICAgb3V0LnogPSBwdC56O1xuXG4gICAgdmFyIGNkaSA9IGNkW3BvaW50TnVtYmVyXTtcbiAgICBpZihjZGkuZkluKSB7XG4gICAgICAgIG91dC5wcm9wZXJ0aWVzID0gY2RpLmZJbi5wcm9wZXJ0aWVzO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG59LHt9XSw5Mjc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIGZpbGxUZXh0ID0gX2RlcmVxXygnLi4vLi4vbGliJykuZmlsbFRleHQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsKSB7XG4gICAgdmFyIGNkID0gcG9pbnREYXRhLmNkO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciBnZW8gPSBwb2ludERhdGEuc3VicGxvdDtcblxuICAgIHZhciBwdCwgaSwgaiwgaXNJbnNpZGU7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICBwdCA9IGNkW2ldO1xuICAgICAgICBpc0luc2lkZSA9IGZhbHNlO1xuXG4gICAgICAgIGlmKHB0Ll9wb2x5Z29ucykge1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgcHQuX3BvbHlnb25zLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYocHQuX3BvbHlnb25zW2pdLmNvbnRhaW5zKFt4dmFsLCB5dmFsXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNJbnNpZGUgPSAhaXNJbnNpZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGZvciBwb2x5Z29ucyB0aGF0IGNyb3NzIGFudGltZXJpZGlhbiBhcyB4dmFsIGlzIGluIFstMTgwLCAxODBdXG4gICAgICAgICAgICAgICAgaWYocHQuX3BvbHlnb25zW2pdLmNvbnRhaW5zKFt4dmFsICsgMzYwLCB5dmFsXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNJbnNpZGUgPSAhaXNJbnNpZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihpc0luc2lkZSkgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZighaXNJbnNpZGUgfHwgIXB0KSByZXR1cm47XG5cbiAgICBwb2ludERhdGEueDAgPSBwb2ludERhdGEueDEgPSBwb2ludERhdGEueGEuYzJwKHB0LmN0KTtcbiAgICBwb2ludERhdGEueTAgPSBwb2ludERhdGEueTEgPSBwb2ludERhdGEueWEuYzJwKHB0LmN0KTtcblxuICAgIHBvaW50RGF0YS5pbmRleCA9IHB0LmluZGV4O1xuICAgIHBvaW50RGF0YS5sb2NhdGlvbiA9IHB0LmxvYztcbiAgICBwb2ludERhdGEueiA9IHB0Lno7XG4gICAgcG9pbnREYXRhLnpMYWJlbCA9IEF4ZXMudGlja1RleHQoZ2VvLm1vY2tBeGlzLCBnZW8ubW9ja0F4aXMuYzJsKHB0LnopLCAnaG92ZXInKS50ZXh0O1xuICAgIHBvaW50RGF0YS5ob3ZlcnRlbXBsYXRlID0gcHQuaG92ZXJ0ZW1wbGF0ZTtcblxuICAgIG1ha2VIb3ZlckluZm8ocG9pbnREYXRhLCB0cmFjZSwgcHQsIGdlby5tb2NrQXhpcyk7XG5cbiAgICByZXR1cm4gW3BvaW50RGF0YV07XG59O1xuXG5mdW5jdGlvbiBtYWtlSG92ZXJJbmZvKHBvaW50RGF0YSwgdHJhY2UsIHB0KSB7XG4gICAgaWYodHJhY2UuaG92ZXJ0ZW1wbGF0ZSkgcmV0dXJuO1xuXG4gICAgdmFyIGhvdmVyaW5mbyA9IHB0LmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcblxuICAgIHZhciBwYXJ0cyA9IChob3ZlcmluZm8gPT09ICdhbGwnKSA/XG4gICAgICAgIGF0dHJpYnV0ZXMuaG92ZXJpbmZvLmZsYWdzIDpcbiAgICAgICAgaG92ZXJpbmZvLnNwbGl0KCcrJyk7XG5cbiAgICB2YXIgaGFzTmFtZSA9IChwYXJ0cy5pbmRleE9mKCduYW1lJykgIT09IC0xKTtcbiAgICB2YXIgaGFzTG9jYXRpb24gPSAocGFydHMuaW5kZXhPZignbG9jYXRpb24nKSAhPT0gLTEpO1xuICAgIHZhciBoYXNaID0gKHBhcnRzLmluZGV4T2YoJ3onKSAhPT0gLTEpO1xuICAgIHZhciBoYXNUZXh0ID0gKHBhcnRzLmluZGV4T2YoJ3RleHQnKSAhPT0gLTEpO1xuICAgIHZhciBoYXNJZEFzTmFtZUxhYmVsID0gIWhhc05hbWUgJiYgaGFzTG9jYXRpb247XG5cbiAgICB2YXIgdGV4dCA9IFtdO1xuXG4gICAgaWYoaGFzSWRBc05hbWVMYWJlbCkge1xuICAgICAgICBwb2ludERhdGEubmFtZU92ZXJyaWRlID0gcHQubG9jO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKGhhc05hbWUpIHBvaW50RGF0YS5uYW1lT3ZlcnJpZGUgPSB0cmFjZS5uYW1lO1xuICAgICAgICBpZihoYXNMb2NhdGlvbikgdGV4dC5wdXNoKHB0LmxvYyk7XG4gICAgfVxuXG4gICAgaWYoaGFzWikge1xuICAgICAgICB0ZXh0LnB1c2gocG9pbnREYXRhLnpMYWJlbCk7XG4gICAgfVxuICAgIGlmKGhhc1RleHQpIHtcbiAgICAgICAgZmlsbFRleHQocHQsIHRyYWNlLCB0ZXh0KTtcbiAgICB9XG5cbiAgICBwb2ludERhdGEuZXh0cmFUZXh0ID0gdGV4dC5qb2luKCc8YnI+Jyk7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuL2F0dHJpYnV0ZXNcIjo5MjN9XSw5Mjg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNvbG9yYmFyOiBfZGVyZXFfKCcuLi9oZWF0bWFwL2NvbG9yYmFyJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JykucGxvdCxcbiAgICBzdHlsZTogX2RlcmVxXygnLi9zdHlsZScpLnN0eWxlLFxuICAgIHN0eWxlT25TZWxlY3Q6IF9kZXJlcV8oJy4vc3R5bGUnKS5zdHlsZU9uU2VsZWN0LFxuICAgIGhvdmVyUG9pbnRzOiBfZGVyZXFfKCcuL2hvdmVyJyksXG4gICAgZXZlbnREYXRhOiBfZGVyZXFfKCcuL2V2ZW50X2RhdGEnKSxcbiAgICBzZWxlY3RQb2ludHM6IF9kZXJlcV8oJy4vc2VsZWN0JyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdjaG9yb3BsZXRoJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2VvJyksXG4gICAgY2F0ZWdvcmllczogWydnZW8nLCAnbm9PcGFjaXR5J10sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2dlb1wiOjc5NyxcIi4uL2hlYXRtYXAvY29sb3JiYXJcIjoxMDA0LFwiLi9hdHRyaWJ1dGVzXCI6OTIzLFwiLi9jYWxjXCI6OTI0LFwiLi9kZWZhdWx0c1wiOjkyNSxcIi4vZXZlbnRfZGF0YVwiOjkyNixcIi4vaG92ZXJcIjo5MjcsXCIuL3Bsb3RcIjo5MjksXCIuL3NlbGVjdFwiOjkzMCxcIi4vc3R5bGVcIjo5MzF9XSw5Mjk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgcG9seWdvbiA9IF9kZXJlcV8oJy4uLy4uL2xpYi9wb2x5Z29uJyk7XG5cbnZhciBnZXRUb3BvanNvbkZlYXR1cmVzID0gX2RlcmVxXygnLi4vLi4vbGliL3RvcG9qc29uX3V0aWxzJykuZ2V0VG9wb2pzb25GZWF0dXJlcztcbnZhciBsb2NhdGlvblRvRmVhdHVyZSA9IF9kZXJlcV8oJy4uLy4uL2xpYi9nZW9fbG9jYXRpb25fdXRpbHMnKS5sb2NhdGlvblRvRmVhdHVyZTtcbnZhciBzdHlsZSA9IF9kZXJlcV8oJy4vc3R5bGUnKS5zdHlsZTtcblxuZnVuY3Rpb24gcGxvdChnZCwgZ2VvLCBjYWxjRGF0YSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBjYWxjR2VvSlNPTihjYWxjRGF0YVtpXSwgZ2VvLnRvcG9qc29uKTtcbiAgICB9XG5cbiAgICB2YXIgY2hvcm9wbGV0aExheWVyID0gZ2VvLmxheWVycy5iYWNrcGxvdC5zZWxlY3QoJy5jaG9yb3BsZXRobGF5ZXInKTtcbiAgICBMaWIubWFrZVRyYWNlR3JvdXBzKGNob3JvcGxldGhMYXllciwgY2FsY0RhdGEsICd0cmFjZSBjaG9yb3BsZXRoJykuZWFjaChmdW5jdGlvbihjYWxjVHJhY2UpIHtcbiAgICAgICAgdmFyIHNlbCA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICB2YXIgcGF0aHMgPSBzZWwuc2VsZWN0QWxsKCdwYXRoLmNob3JvcGxldGhsb2NhdGlvbicpXG4gICAgICAgICAgICAuZGF0YShMaWIuaWRlbnRpdHkpO1xuXG4gICAgICAgIHBhdGhzLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdjaG9yb3BsZXRobG9jYXRpb24nLCB0cnVlKTtcblxuICAgICAgICBwYXRocy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgLy8gY2FsbCBzdHlsZSBoZXJlIHdpdGhpbiB0b3BvanNvbiByZXF1ZXN0IGNhbGxiYWNrXG4gICAgICAgIHN0eWxlKGdkLCBjYWxjVHJhY2UpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBjYWxjR2VvSlNPTihjYWxjVHJhY2UsIHRvcG9qc29uKSB7XG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgIHZhciBsZW4gPSBjYWxjVHJhY2UubGVuZ3RoO1xuICAgIHZhciBmZWF0dXJlcyA9IGdldFRvcG9qc29uRmVhdHVyZXModHJhY2UsIHRvcG9qc29uKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgY2FsY1B0ID0gY2FsY1RyYWNlW2ldO1xuICAgICAgICB2YXIgZmVhdHVyZSA9IGxvY2F0aW9uVG9GZWF0dXJlKHRyYWNlLmxvY2F0aW9ubW9kZSwgY2FsY1B0LmxvYywgZmVhdHVyZXMpO1xuXG4gICAgICAgIGlmKCFmZWF0dXJlKSB7XG4gICAgICAgICAgICBjYWxjUHQuZ2VvanNvbiA9IG51bGw7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGNQdC5nZW9qc29uID0gZmVhdHVyZTtcbiAgICAgICAgY2FsY1B0LmN0ID0gZmVhdHVyZS5wcm9wZXJ0aWVzLmN0O1xuICAgICAgICBjYWxjUHQuX3BvbHlnb25zID0gZmVhdHVyZTJwb2x5Z29ucyhmZWF0dXJlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGZlYXR1cmUycG9seWdvbnMoZmVhdHVyZSkge1xuICAgIHZhciBnZW9tZXRyeSA9IGZlYXR1cmUuZ2VvbWV0cnk7XG4gICAgdmFyIGNvb3JkcyA9IGdlb21ldHJ5LmNvb3JkaW5hdGVzO1xuICAgIHZhciBsb2MgPSBmZWF0dXJlLmlkO1xuXG4gICAgdmFyIHBvbHlnb25zID0gW107XG4gICAgdmFyIGFwcGVuZFBvbHlnb24sIGosIGssIG07XG5cbiAgICBmdW5jdGlvbiBkb2VzQ3Jvc3NBbnRpTWVyZGlhbihwdHMpIHtcbiAgICAgICAgZm9yKHZhciBsID0gMDsgbCA8IHB0cy5sZW5ndGggLSAxOyBsKyspIHtcbiAgICAgICAgICAgIGlmKHB0c1tsXVswXSA+IDAgJiYgcHRzW2wgKyAxXVswXSA8IDApIHJldHVybiBsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGlmKGxvYyA9PT0gJ1JVUycgfHwgbG9jID09PSAnRkpJJykge1xuICAgICAgICAvLyBSdXNzaWEgYW5kIEZpamkgaGF2ZSBsYW5kbWFzc2VzIHRoYXQgY3Jvc3MgdGhlIGFudGltZXJpZGlhbixcbiAgICAgICAgLy8gd2UgbmVlZCB0byBhZGQgKzM2MCB0byB0aGVpciBsb25naXR1ZGUgY29vcmRpbmF0ZXMsIHNvIHRoYXRcbiAgICAgICAgLy8gcG9seWdvbiAnY29udGFpbnMnIGRvZXNuJ3QgZ2V0IGNvbmZ1c2VkIHdoZW4gY3Jvc3NpbmcgdGhlIGFudGltZXJpZGlhbi5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gTm90ZSB0aGF0IG90aGVyIGNvdW50cmllcyBoYXZlIHBvbHlnb25zIG9uIGVpdGhlciBzaWRlIG9mIHRoZSBhbnRpbWVyaWRpYW5cbiAgICAgICAgLy8gKGUuZy4gc29tZSBBbGV1dGlhbiBpc2xhbmQgZm9yIHRoZSBVU0EpLCBidXQgdGhvc2UgZG9uJ3QgY29uZnVzZVxuICAgICAgICAvLyB0aGUgJ2NvbnRhaW5zJyBtZXRob2Q7IHRoZXNlIGFyZSBza2lwcGVkIGhlcmUuXG4gICAgICAgIGFwcGVuZFBvbHlnb24gPSBmdW5jdGlvbihfcHRzKSB7XG4gICAgICAgICAgICB2YXIgcHRzO1xuXG4gICAgICAgICAgICBpZihkb2VzQ3Jvc3NBbnRpTWVyZGlhbihfcHRzKSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHB0cyA9IF9wdHM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHB0cyA9IG5ldyBBcnJheShfcHRzLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgZm9yKG0gPSAwOyBtIDwgX3B0cy5sZW5ndGg7IG0rKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBkbyBudXQgbXV0YXRlIGNhbGNkYXRhW2ldW2pdLmdlb2pzb24gISFcbiAgICAgICAgICAgICAgICAgICAgcHRzW21dID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgX3B0c1ttXVswXSA8IDAgPyBfcHRzW21dWzBdICsgMzYwIDogX3B0c1ttXVswXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIF9wdHNbbV1bMV1cbiAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHBvbHlnb25zLnB1c2gocG9seWdvbi50ZXN0ZXIocHRzKSk7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIGlmKGxvYyA9PT0gJ0FUQScpIHtcbiAgICAgICAgLy8gQW50YXJjdGljYSBoYXMgYSBsYW5kbWFzcyB0aGF0IHdyYXBzIGFyb3VuZCBldmVyeSBsb25naXR1ZGVzIHdoaWNoXG4gICAgICAgIC8vIGNvbmZ1c2VzIHRoZSAnY29udGFpbnMnIG1ldGhvZHMuXG4gICAgICAgIGFwcGVuZFBvbHlnb24gPSBmdW5jdGlvbihwdHMpIHtcbiAgICAgICAgICAgIHZhciBjcm9zc0FudGlNZXJpZGlhbkluZGV4ID0gZG9lc0Nyb3NzQW50aU1lcmRpYW4ocHRzKTtcblxuICAgICAgICAgICAgLy8gcG9seWdvbiB0aGF0IGRvIG5vdCBjcm9zcyBhbnRpLW1lcmlkaWFuIG5lZWQgbm8gc3BlY2lhbCBoYW5kbGluZ1xuICAgICAgICAgICAgaWYoY3Jvc3NBbnRpTWVyaWRpYW5JbmRleCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwb2x5Z29ucy5wdXNoKHBvbHlnb24udGVzdGVyKHB0cykpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBzdGl0Y2ggcG9seWdvbiBieSBhZGRpbmcgcHQgb3ZlciBTb3V0aCBQb2xlLFxuICAgICAgICAgICAgLy8gc28gdGhhdCBpdCBjb3ZlcnMgdGhlIHByb2plY3RlZCByZWdpb24gY292ZXJzIGFsbCBsYXRpdHVkZXNcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBOb3RlIHRoYXQgdGhlIGFsZ29yaXRobSBiZWxvdyBvbmx5IHdvcmtzIGZvciBwb2x5Z29ucyB0aGF0XG4gICAgICAgICAgICAvLyBzdGFydCBhbmQgZW5kIG9uIGxvbmdpdHVkZSAtMTgwIChsaWtlIHRoZSBvbmVzIGJ1aWx0IGJ5XG4gICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZXRwaW5hcmQvc2FuZS10b3BvanNvbikuXG4gICAgICAgICAgICB2YXIgc3RpdGNoID0gbmV3IEFycmF5KHB0cy5sZW5ndGggKyAxKTtcbiAgICAgICAgICAgIHZhciBzaSA9IDA7XG5cbiAgICAgICAgICAgIGZvcihtID0gMDsgbSA8IHB0cy5sZW5ndGg7IG0rKykge1xuICAgICAgICAgICAgICAgIGlmKG0gPiBjcm9zc0FudGlNZXJpZGlhbkluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0aXRjaFtzaSsrXSA9IFtwdHNbbV1bMF0gKyAzNjAsIHB0c1ttXVsxXV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKG0gPT09IGNyb3NzQW50aU1lcmlkaWFuSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RpdGNoW3NpKytdID0gcHRzW21dO1xuICAgICAgICAgICAgICAgICAgICBzdGl0Y2hbc2krK10gPSBbcHRzW21dWzBdLCAtOTBdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHN0aXRjaFtzaSsrXSA9IHB0c1ttXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHBvbHlnb24udGVzdGVyIGJ5IGRlZmF1bHQgYXBwZW5kcyBwdFswXSB0byB0aGUgcG9pbnRzIGxpc3QsXG4gICAgICAgICAgICAvLyB3ZSBtdXN0IHJlbW92ZSBpdCBoZXJlLCB0byBhdm9pZCBhIGp1bXAgaW4gbG9uZ2l0dWRlIGZyb20gMTgwIHRvIC0xODAsXG4gICAgICAgICAgICAvLyB0aGF0IHdvdWxkIGNvbmZ1c2UgdGhlICdjb250YWlucycgbWV0aG9kXG4gICAgICAgICAgICB2YXIgdGVzdGVyID0gcG9seWdvbi50ZXN0ZXIoc3RpdGNoKTtcbiAgICAgICAgICAgIHRlc3Rlci5wdHMucG9wKCk7XG4gICAgICAgICAgICBwb2x5Z29ucy5wdXNoKHRlc3Rlcik7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gb3RoZXJ3aXNlIHVzaW5nIHNhbWUgYXJyYXkgcmVmIGlzIGZpbmVcbiAgICAgICAgYXBwZW5kUG9seWdvbiA9IGZ1bmN0aW9uKHB0cykge1xuICAgICAgICAgICAgcG9seWdvbnMucHVzaChwb2x5Z29uLnRlc3RlcihwdHMpKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBzd2l0Y2goZ2VvbWV0cnkudHlwZSkge1xuICAgICAgICBjYXNlICdNdWx0aVBvbHlnb24nOlxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgY29vcmRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgY29vcmRzW2pdLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgIGFwcGVuZFBvbHlnb24oY29vcmRzW2pdW2tdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnUG9seWdvbic6XG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBjb29yZHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBhcHBlbmRQb2x5Z29uKGNvb3Jkc1tqXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICByZXR1cm4gcG9seWdvbnM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHBsb3Q6IHBsb3QsXG4gICAgZmVhdHVyZTJwb2x5Z29uczogZmVhdHVyZTJwb2x5Z29uc1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZ2VvX2xvY2F0aW9uX3V0aWxzXCI6NzEzLFwiLi4vLi4vbGliL3BvbHlnb25cIjo3MzEsXCIuLi8uLi9saWIvdG9wb2pzb25fdXRpbHNcIjo3NDYsXCIuL3N0eWxlXCI6OTMxLFwiZDNcIjoxNjN9XSw5MzA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBzZWxlY3Rpb25UZXN0ZXIpIHtcbiAgICB2YXIgY2QgPSBzZWFyY2hJbmZvLmNkO1xuICAgIHZhciB4YSA9IHNlYXJjaEluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gc2VhcmNoSW5mby55YXhpcztcbiAgICB2YXIgc2VsZWN0aW9uID0gW107XG5cbiAgICB2YXIgaSwgZGksIGN0LCB4LCB5O1xuXG4gICAgaWYoc2VsZWN0aW9uVGVzdGVyID09PSBmYWxzZSkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGRpID0gY2RbaV07XG4gICAgICAgICAgICBjdCA9IGRpLmN0O1xuXG4gICAgICAgICAgICBpZighY3QpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB4ID0geGEuYzJwKGN0KTtcbiAgICAgICAgICAgIHkgPSB5YS5jMnAoY3QpO1xuXG4gICAgICAgICAgICBpZihzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3gsIHldLCBudWxsLCBpLCBzZWFyY2hJbmZvKSkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnROdW1iZXI6IGksXG4gICAgICAgICAgICAgICAgICAgIGxvbjogY3RbMF0sXG4gICAgICAgICAgICAgICAgICAgIGxhdDogY3RbMV1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBkaS5zZWxlY3RlZCA9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRpLnNlbGVjdGVkID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzZWxlY3Rpb247XG59O1xuXG59LHt9XSw5MzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBDb2xvcnNjYWxlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlJyk7XG5cbmZ1bmN0aW9uIHN0eWxlKGdkLCBjYWxjVHJhY2UpIHtcbiAgICBpZihjYWxjVHJhY2UpIHN0eWxlVHJhY2UoZ2QsIGNhbGNUcmFjZSk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlVHJhY2UoZ2QsIGNhbGNUcmFjZSkge1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcbiAgICB2YXIgcyA9IGNhbGNUcmFjZVswXS5ub2RlMztcbiAgICB2YXIgbG9jcyA9IHMuc2VsZWN0QWxsKCcuY2hvcm9wbGV0aGxvY2F0aW9uJyk7XG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlciB8fCB7fTtcbiAgICB2YXIgbWFya2VyTGluZSA9IG1hcmtlci5saW5lIHx8IHt9O1xuXG4gICAgdmFyIHNjbEZ1bmMgPSBDb2xvcnNjYWxlLm1ha2VDb2xvclNjYWxlRnVuY0Zyb21UcmFjZSh0cmFjZSk7XG5cbiAgICBsb2NzLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICBkMy5zZWxlY3QodGhpcylcbiAgICAgICAgICAgIC5hdHRyKCdmaWxsJywgc2NsRnVuYyhkLnopKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBkLm1sYyB8fCBtYXJrZXJMaW5lLmNvbG9yKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5kYXNoTGluZSwgJycsIGQubWx3IHx8IG1hcmtlckxpbmUud2lkdGggfHwgMClcbiAgICAgICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIG1hcmtlci5vcGFjaXR5KTtcbiAgICB9KTtcblxuICAgIERyYXdpbmcuc2VsZWN0ZWRQb2ludFN0eWxlKGxvY3MsIHRyYWNlLCBnZCk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlT25TZWxlY3QoZ2QsIGNhbGNUcmFjZSkge1xuICAgIHZhciBzID0gY2FsY1RyYWNlWzBdLm5vZGUzO1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgIGlmKHRyYWNlLnNlbGVjdGVkcG9pbnRzKSB7XG4gICAgICAgIERyYXdpbmcuc2VsZWN0ZWRQb2ludFN0eWxlKHMuc2VsZWN0QWxsKCcuY2hvcm9wbGV0aGxvY2F0aW9uJyksIHRyYWNlLCBnZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc3R5bGVUcmFjZShnZCwgY2FsY1RyYWNlKTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN0eWxlOiBzdHlsZSxcbiAgICBzdHlsZU9uU2VsZWN0OiBzdHlsZU9uU2VsZWN0XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGVcIjo2MDUsXCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCJkM1wiOjE2M31dLDkzMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjaG9yb3BsZXRoQXR0cnMgPSBfZGVyZXFfKCcuLi9jaG9yb3BsZXRoL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGhvdmVydGVtcGxhdGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZXh0ZW5kRmxhdCh7XG4gICAgbG9jYXRpb25zOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIC8vIFRPRE9cbiAgICAvLyBNYXliZSBzdGFydCB3aXRoIG9ubHkgb25lIHZhbHVlICh0aGF0IHdlIGNvdWxkIG5hbWUgZS5nLiAnZ2VvanNvbi1pZCcpLFxuICAgIC8vIGJ1dCBldmVudHVhbGx5OlxuICAgIC8vIC0gd2UgY291bGQgYWxzbyBzdXBwb3J0IGZvciBvdXIgb3duIGRpc3QvdG9wb2pzb24vKlxuICAgIC8vIC0gc29tZSBwZW9wbGUgbWlnaHQgd2FudCBgZ2VvanNvbi1wcm9wZXJ0aWVzLW5hbWVgIHRvIG1hcCBkYXRhIGFycmF5cyB0b1xuICAgIC8vICAgR2VvSlNPTiBmZWF0dXJlc1xuICAgIC8vIGxvY2F0aW9ubW9kZTogY2hvcm9wbGV0aEF0dHJzLmxvY2F0aW9ubW9kZSxcblxuICAgIHo6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgLy8gVE9ETyBtYXliZSB3ZSBjb3VsZCBhbHNvIHNldCBhIFwia2V5XCIgdG8gZGlnIG91dCB2YWx1ZXMgb3V0IG9mIHRoZVxuICAgIC8vIEdlb0pTT04gZmVhdHVyZSBgcHJvcGVydGllc2AgZmllbGRzP1xuXG4gICAgZ2VvanNvbjoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICAvLyBUT0RPIGFncmVlIG9uIG5hbWUgLyBiZWhhdmlvdXJcbiAgICAvL1xuICAgIC8vICdiZWxvdycgaXMgdXNlZCBjdXJyZW50bHkgZm9yIGxheW91dC5tYXBib3gubGF5ZXJzLFxuICAgIC8vIGV2ZW4gdGhvdWdoIGl0J3Mgbm90IHZlcnkgcGxvdGx5LWVzcXVlLlxuICAgIC8vXG4gICAgLy8gTm90ZSBhbHNvLCB0aGF0IHRoZSBtYXBib3gtZ2wgc3R5bGUgZG9uJ3QgYWxsIGhhdmUgdGhlIHNhbWUgbGF5ZXJzLFxuICAgIC8vIHNlZSBodHRwczovL2NvZGVwZW4uaW8vZXRwaW5hcmQvcGVuL3lkVk13TSBmb3IgZnVsbCBsaXN0XG4gICAgYmVsb3c6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGV4dDogY2hvcm9wbGV0aEF0dHJzLnRleHQsXG4gICAgaG92ZXJ0ZXh0OiBjaG9yb3BsZXRoQXR0cnMuaG92ZXJ0ZXh0LFxuXG4gICAgbWFya2VyOiB7XG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBjaG9yb3BsZXRoQXR0cnMubWFya2VyLmxpbmUuY29sb3IsIHtlZGl0VHlwZTogJ3Bsb3QnfSksXG4gICAgICAgICAgICB3aWR0aDogZXh0ZW5kRmxhdCh7fSwgY2hvcm9wbGV0aEF0dHJzLm1hcmtlci5saW5lLndpZHRoLCB7ZWRpdFR5cGU6ICdwbG90J30pLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgICAgICB9LFxuICAgICAgICAvLyBUT0RPIG1heWJlIGhhdmluZyBhIGRmbHQgbGVzcyB0aGFuIDEsIHRvZ2V0aGVyIHdpdGggYGJlbG93OicnYCB3b3VsZCBiZSBiZXR0ZXI/XG4gICAgICAgIG9wYWNpdHk6IGV4dGVuZEZsYXQoe30sIGNob3JvcGxldGhBdHRycy5tYXJrZXIub3BhY2l0eSwge2VkaXRUeXBlOiAncGxvdCd9KSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG5cbiAgICBzZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IGV4dGVuZEZsYXQoe30sIGNob3JvcGxldGhBdHRycy5zZWxlY3RlZC5tYXJrZXIub3BhY2l0eSwge2VkaXRUeXBlOiAncGxvdCd9KSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgIH0sXG4gICAgdW5zZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IGV4dGVuZEZsYXQoe30sIGNob3JvcGxldGhBdHRycy51bnNlbGVjdGVkLm1hcmtlci5vcGFjaXR5LCB7ZWRpdFR5cGU6ICdwbG90J30pLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcblxuICAgIGhvdmVyaW5mbzogY2hvcm9wbGV0aEF0dHJzLmhvdmVyaW5mbyxcbiAgICBob3ZlcnRlbXBsYXRlOiBob3ZlcnRlbXBsYXRlQXR0cnMoe30sIHtrZXlzOiBbJ3Byb3BlcnRpZXMnXX0pXG59LFxuXG4gICAgY29sb3JTY2FsZUF0dHJzKCcnLCB7XG4gICAgICAgIGNMZXR0ZXI6ICd6JyxcbiAgICAgICAgZWRpdFR5cGVPdmVycmlkZTogJ2NhbGMnXG4gICAgfSlcbik7XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXNcIjo2MDAsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi9jaG9yb3BsZXRoL2F0dHJpYnV0ZXNcIjo5MjN9XSw5MzM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcbnZhciB0dXJmQXJlYSA9IF9kZXJlcV8oJ0B0dXJmL2FyZWEnKTtcbnZhciB0dXJmQ2VudHJvaWQgPSBfZGVyZXFfKCdAdHVyZi9jZW50cm9pZCcpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQ29sb3JzY2FsZSA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZScpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcblxudmFyIG1ha2VCbGFuayA9IF9kZXJlcV8oJy4uLy4uL2xpYi9nZW9qc29uX3V0aWxzJykubWFrZUJsYW5rO1xudmFyIGZlYXR1cmUycG9seWdvbnMgPSBfZGVyZXFfKCcuLi9jaG9yb3BsZXRoL3Bsb3QnKS5mZWF0dXJlMnBvbHlnb25zO1xuXG4vKiBOLkIuXG4gKlxuICogV2UgZmV0Y2ggdGhlIEdlb0pTT04gZmlsZXMgXCJvdXJzZWx2ZXNcIiAoZHVyaW5nXG4gKiBtYXBib3gucHJvdG90eXBlLmZldGNoTWFwRGF0YSkgd2hlcmUgdGhleSBhcmUgc3RvcmVkIGluIGEgZ2xvYmFsIG9iamVjdFxuICogbmFtZWQgYFBsb3RseUdlb0Fzc2V0c2AgKHNhbWUgYXMgZm9yIHRvcG9qc29uIGZpbGVzIGluIGBnZW9gIHN1YnBsb3RzKS5cbiAqXG4gKiBNYXBib3ggZG9lcyBhbGxvdyB1c2luZyBVUkxzIGFzIGdlb2pzb24gc291cmNlcywgYnV0IGRvZXMgTk9UIGFsbG93IGZpbHRlcmluZ1xuICogZmVhdHVyZXMgYnkgZmVhdHVyZSBgaWRgIHRoYXQgYXJlIG5vdCBudW1iZXJzIChtb3JlIGluZm8gaW46XG4gKiBodHRwczovL2dpdGh1Yi5jb20vbWFwYm94L21hcGJveC1nbC1qcy9pc3N1ZXMvODA4OCkuXG4gKi9cblxuZnVuY3Rpb24gY29udmVydChjYWxjVHJhY2UpIHtcbiAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG4gICAgdmFyIGlzVmlzaWJsZSA9IHRyYWNlLnZpc2libGUgPT09IHRydWUgJiYgdHJhY2UuX2xlbmd0aCAhPT0gMDtcblxuICAgIHZhciBmaWxsID0ge1xuICAgICAgICBsYXlvdXQ6IHt2aXNpYmlsaXR5OiAnbm9uZSd9LFxuICAgICAgICBwYWludDoge31cbiAgICB9O1xuXG4gICAgdmFyIGxpbmUgPSB7XG4gICAgICAgIGxheW91dDoge3Zpc2liaWxpdHk6ICdub25lJ30sXG4gICAgICAgIHBhaW50OiB7fVxuICAgIH07XG5cbiAgICB2YXIgb3B0cyA9IHRyYWNlLl9vcHRzID0ge1xuICAgICAgICBmaWxsOiBmaWxsLFxuICAgICAgICBsaW5lOiBsaW5lLFxuICAgICAgICBnZW9qc29uOiBtYWtlQmxhbmsoKVxuICAgIH07XG5cbiAgICBpZighaXNWaXNpYmxlKSByZXR1cm4gb3B0cztcblxuICAgIHZhciBnZW9qc29uSW4gPSB0eXBlb2YgdHJhY2UuZ2VvanNvbiA9PT0gJ3N0cmluZycgP1xuICAgICAgICAod2luZG93LlBsb3RseUdlb0Fzc2V0cyB8fCB7fSlbdHJhY2UuZ2VvanNvbl0gOlxuICAgICAgICB0cmFjZS5nZW9qc29uO1xuXG4gICAgLy8gVGhpcyBzaG91bGQgbm90IGhhcHBlbiwgYnV0IGp1c3QgaW4gY2FzZSBzb21ldGhpbmcgZ29lc1xuICAgIC8vIHJlYWxseSB3cm9uZyB3aGVuIGZldGNoaW5nIHRoZSBHZW9KU09OXG4gICAgaWYoIUxpYi5pc1BsYWluT2JqZWN0KGdlb2pzb25JbikpIHtcbiAgICAgICAgTGliLmVycm9yKCdPb3BzIC4uLiBzb21ldGhpbmcgd2hlbiB3cm9uZyB3aGVuIGZldGNoaW5nICcgKyB0cmFjZS5nZW9qc29uKTtcbiAgICAgICAgcmV0dXJuIG9wdHM7XG4gICAgfVxuXG4gICAgdmFyIGxvb2t1cCA9IHt9O1xuICAgIHZhciBmZWF0dXJlc091dCA9IFtdO1xuICAgIHZhciBpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjZGkgPSBjYWxjVHJhY2VbaV07XG4gICAgICAgIGlmKGNkaS5sb2MpIGxvb2t1cFtjZGkubG9jXSA9IGNkaTtcbiAgICB9XG5cbiAgICB2YXIgc2NsRnVuYyA9IENvbG9yc2NhbGUubWFrZUNvbG9yU2NhbGVGdW5jRnJvbVRyYWNlKHRyYWNlKTtcbiAgICB2YXIgbWFya2VyID0gdHJhY2UubWFya2VyO1xuICAgIHZhciBtYXJrZXJMaW5lID0gbWFya2VyLmxpbmUgfHwge307XG5cbiAgICB2YXIgb3BhY2l0eUZuO1xuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG1hcmtlci5vcGFjaXR5KSkge1xuICAgICAgICBvcGFjaXR5Rm4gPSBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgbW8gPSBkLm1vO1xuICAgICAgICAgICAgcmV0dXJuIGlzTnVtZXJpYyhtbykgPyArTGliLmNvbnN0cmFpbihtbywgMCwgMSkgOiAwO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBsaW5lQ29sb3JGbjtcbiAgICBpZihMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXJMaW5lLmNvbG9yKSkge1xuICAgICAgICBsaW5lQ29sb3JGbiA9IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQubWxjOyB9O1xuICAgIH1cblxuICAgIHZhciBsaW5lV2lkdGhGbjtcbiAgICBpZihMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXJMaW5lLndpZHRoKSkge1xuICAgICAgICBsaW5lV2lkdGhGbiA9IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQubWx3OyB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFwcGVuZEZlYXR1cmUoZkluKSB7XG4gICAgICAgIHZhciBjZGkgPSBsb29rdXBbZkluLmlkXTtcblxuICAgICAgICBpZihjZGkpIHtcbiAgICAgICAgICAgIHZhciBnZW9tZXRyeSA9IGZJbi5nZW9tZXRyeTtcblxuICAgICAgICAgICAgaWYoZ2VvbWV0cnkudHlwZSA9PT0gJ1BvbHlnb24nIHx8IGdlb21ldHJ5LnR5cGUgPT09ICdNdWx0aVBvbHlnb24nKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0ge2ZjOiBzY2xGdW5jKGNkaS56KX07XG5cbiAgICAgICAgICAgICAgICBpZihvcGFjaXR5Rm4pIHByb3BzLm1vID0gb3BhY2l0eUZuKGNkaSk7XG4gICAgICAgICAgICAgICAgaWYobGluZUNvbG9yRm4pIHByb3BzLm1sYyA9IGxpbmVDb2xvckZuKGNkaSk7XG4gICAgICAgICAgICAgICAgaWYobGluZVdpZHRoRm4pIHByb3BzLm1sdyA9IGxpbmVXaWR0aEZuKGNkaSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgZk91dCA9IHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ0ZlYXR1cmUnLFxuICAgICAgICAgICAgICAgICAgICBnZW9tZXRyeTogZ2VvbWV0cnksXG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGNkaS5fcG9seWdvbnMgPSBmZWF0dXJlMnBvbHlnb25zKGZPdXQpO1xuICAgICAgICAgICAgICAgIGNkaS5jdCA9IGZpbmRDZW50cm9pZChmT3V0KTtcbiAgICAgICAgICAgICAgICBjZGkuZkluID0gZkluO1xuICAgICAgICAgICAgICAgIGNkaS5mT3V0ID0gZk91dDtcbiAgICAgICAgICAgICAgICBmZWF0dXJlc091dC5wdXNoKGZPdXQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBMaWIubG9nKFtcbiAgICAgICAgICAgICAgICAgICAgJ0xvY2F0aW9uIHdpdGggaWQnLCBjZGkubG9jLCAnZG9lcyBub3QgaGF2ZSBhIHZhbGlkIEdlb0pTT04gZ2VvbWV0cnksJyxcbiAgICAgICAgICAgICAgICAgICAgJ2Nob3JvcGxldGhtYXBib3ggdHJhY2VzIG9ubHkgc3VwcG9ydCAqUG9seWdvbiogYW5kICpNdWx0aVBvbHlnb24qIGdlb21ldHJpZXMuJ1xuICAgICAgICAgICAgICAgIF0uam9pbignICcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlbW92ZSBrZXkgZnJvbSBsb29rdXAsIHNvIHRoYXQgd2UgY2FuIHRyYWNrIChpZiBhbnkpXG4gICAgICAgIC8vIHRoZSBsb2NhdGlvbnMgdGhhdCBkaWQgbm90IGhhdmUgYSBjb3JyZXNwb25kaW5nIEdlb0pTT04gZmVhdHVyZVxuICAgICAgICBkZWxldGUgbG9va3VwW2ZJbi5pZF07XG4gICAgfVxuXG4gICAgc3dpdGNoKGdlb2pzb25Jbi50eXBlKSB7XG4gICAgICAgIGNhc2UgJ0ZlYXR1cmVDb2xsZWN0aW9uJzpcbiAgICAgICAgICAgIHZhciBmZWF0dXJlc0luID0gZ2VvanNvbkluLmZlYXR1cmVzO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgZmVhdHVyZXNJbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGFwcGVuZEZlYXR1cmUoZmVhdHVyZXNJbltpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnRmVhdHVyZSc6XG4gICAgICAgICAgICBhcHBlbmRGZWF0dXJlKGdlb2pzb25Jbik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIExpYi53YXJuKFtcbiAgICAgICAgICAgICAgICAnSW52YWxpZCBHZW9KU09OIHR5cGUnLCAoZ2VvanNvbkluLnR5cGUgfHwgJ25vbmUnKSArICcsJyxcbiAgICAgICAgICAgICAgICAnY2hvcm9wbGV0aG1hcGJveCB0cmFjZXMgb25seSBzdXBwb3J0ICpGZWF0dXJlQ29sbGVjdGlvbiogYW5kICpGZWF0dXJlKiB0eXBlcy4nXG4gICAgICAgICAgICBdLmpvaW4oJyAnKSk7XG4gICAgICAgICAgICByZXR1cm4gb3B0cztcbiAgICB9XG5cbiAgICBmb3IodmFyIGxvYyBpbiBsb29rdXApIHtcbiAgICAgICAgTGliLmxvZygnTG9jYXRpb24gd2l0aCBpZCAnICsgbG9jICsgJyBkb2VzIG5vdCBoYXZlIGEgbWF0Y2hpbmcgZmVhdHVyZScpO1xuICAgIH1cblxuICAgIHZhciBvcGFjaXR5U2V0dGluZyA9IG9wYWNpdHlGbiA/XG4gICAgICAgIHt0eXBlOiAnaWRlbnRpdHknLCBwcm9wZXJ0eTogJ21vJ30gOlxuICAgICAgICBtYXJrZXIub3BhY2l0eTtcblxuICAgIExpYi5leHRlbmRGbGF0KGZpbGwucGFpbnQsIHtcbiAgICAgICAgJ2ZpbGwtY29sb3InOiB7dHlwZTogJ2lkZW50aXR5JywgcHJvcGVydHk6ICdmYyd9LFxuICAgICAgICAnZmlsbC1vcGFjaXR5Jzogb3BhY2l0eVNldHRpbmdcbiAgICB9KTtcblxuICAgIExpYi5leHRlbmRGbGF0KGxpbmUucGFpbnQsIHtcbiAgICAgICAgJ2xpbmUtY29sb3InOiBsaW5lQ29sb3JGbiA/XG4gICAgICAgICAgICB7dHlwZTogJ2lkZW50aXR5JywgcHJvcGVydHk6ICdtbGMnfSA6XG4gICAgICAgICAgICBtYXJrZXJMaW5lLmNvbG9yLFxuICAgICAgICAnbGluZS13aWR0aCc6IGxpbmVXaWR0aEZuID9cbiAgICAgICAgICAgIHt0eXBlOiAnaWRlbnRpdHknLCBwcm9wZXJ0eTogJ21sdyd9IDpcbiAgICAgICAgICAgIG1hcmtlckxpbmUud2lkdGgsXG4gICAgICAgICdsaW5lLW9wYWNpdHknOiBvcGFjaXR5U2V0dGluZ1xuICAgIH0pO1xuXG4gICAgZmlsbC5sYXlvdXQudmlzaWJpbGl0eSA9ICd2aXNpYmxlJztcbiAgICBsaW5lLmxheW91dC52aXNpYmlsaXR5ID0gJ3Zpc2libGUnO1xuXG4gICAgb3B0cy5nZW9qc29uID0ge3R5cGU6ICdGZWF0dXJlQ29sbGVjdGlvbicsIGZlYXR1cmVzOiBmZWF0dXJlc091dH07XG5cbiAgICBjb252ZXJ0T25TZWxlY3QoY2FsY1RyYWNlKTtcblxuICAgIHJldHVybiBvcHRzO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0T25TZWxlY3QoY2FsY1RyYWNlKSB7XG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgIHZhciBvcHRzID0gdHJhY2UuX29wdHM7XG4gICAgdmFyIG9wYWNpdHlTZXR0aW5nO1xuXG4gICAgaWYodHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHtcbiAgICAgICAgdmFyIGZucyA9IERyYXdpbmcubWFrZVNlbGVjdGVkUG9pbnRTdHlsZUZucyh0cmFjZSk7XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNUcmFjZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGNkaSA9IGNhbGNUcmFjZVtpXTtcbiAgICAgICAgICAgIGlmKGNkaS5mT3V0KSB7XG4gICAgICAgICAgICAgICAgY2RpLmZPdXQucHJvcGVydGllcy5tbzIgPSBmbnMuc2VsZWN0ZWRPcGFjaXR5Rm4oY2RpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIG9wYWNpdHlTZXR0aW5nID0ge3R5cGU6ICdpZGVudGl0eScsIHByb3BlcnR5OiAnbW8yJ307XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3BhY2l0eVNldHRpbmcgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheSh0cmFjZS5tYXJrZXIub3BhY2l0eSkgP1xuICAgICAgICAgICAge3R5cGU6ICdpZGVudGl0eScsIHByb3BlcnR5OiAnbW8nfSA6XG4gICAgICAgICAgICB0cmFjZS5tYXJrZXIub3BhY2l0eTtcbiAgICB9XG5cbiAgICBMaWIuZXh0ZW5kRmxhdChvcHRzLmZpbGwucGFpbnQsIHsnZmlsbC1vcGFjaXR5Jzogb3BhY2l0eVNldHRpbmd9KTtcbiAgICBMaWIuZXh0ZW5kRmxhdChvcHRzLmxpbmUucGFpbnQsIHsnbGluZS1vcGFjaXR5Jzogb3BhY2l0eVNldHRpbmd9KTtcblxuICAgIHJldHVybiBvcHRzO1xufVxuXG4vLyBUT0RPIHRoaXMgZmluZCB0aGUgY2VudHJvaWQgb2YgdGhlIHBvbHlnb24gb2YgbWF4QXJlYVxuLy8gKGp1c3QgbGlrZSB3ZSBjdXJyZW50bHkgZG8gZm9yIGdlbyBjaG9yb3BsZXRoIHBvbHlnb25zKSxcbi8vIG1heWJlIGluc3RlYWQgaXQgd291bGQgbWFrZSBtb3JlIHNlbnNlIHRvIGNvbXB1dGUgdGhlIGNlbnRyb2lkXG4vLyBvZiBlYWNoIHBvbHlnb24gYW5kIGNvbnNpZGVyIHRob3NlIG9uIGhvdmVyL3NlbGVjdFxuZnVuY3Rpb24gZmluZENlbnRyb2lkKGZlYXR1cmUpIHtcbiAgICB2YXIgZ2VvbWV0cnkgPSBmZWF0dXJlLmdlb21ldHJ5O1xuICAgIHZhciBwb2x5O1xuXG4gICAgaWYoZ2VvbWV0cnkudHlwZSA9PT0gJ011bHRpUG9seWdvbicpIHtcbiAgICAgICAgdmFyIGNvb3JkcyA9IGdlb21ldHJ5LmNvb3JkaW5hdGVzO1xuICAgICAgICB2YXIgbWF4QXJlYSA9IDA7XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGNvb3Jkcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHBvbHlpID0ge3R5cGU6ICdQb2x5Z29uJywgY29vcmRpbmF0ZXM6IGNvb3Jkc1tpXX07XG4gICAgICAgICAgICB2YXIgYXJlYSA9IHR1cmZBcmVhLmRlZmF1bHQocG9seWkpO1xuICAgICAgICAgICAgaWYoYXJlYSA+IG1heEFyZWEpIHtcbiAgICAgICAgICAgICAgICBtYXhBcmVhID0gYXJlYTtcbiAgICAgICAgICAgICAgICBwb2x5ID0gcG9seWk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBwb2x5ID0gZ2VvbWV0cnk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHR1cmZDZW50cm9pZC5kZWZhdWx0KHBvbHkpLmdlb21ldHJ5LmNvb3JkaW5hdGVzO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjb252ZXJ0OiBjb252ZXJ0LFxuICAgIGNvbnZlcnRPblNlbGVjdDogY29udmVydE9uU2VsZWN0XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZVwiOjYwNSxcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9nZW9qc29uX3V0aWxzXCI6NzE0LFwiLi4vY2hvcm9wbGV0aC9wbG90XCI6OTI5LFwiQHR1cmYvYXJlYVwiOjU1LFwiQHR1cmYvY2VudHJvaWRcIjo1NixcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sOTM0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxvY2F0aW9ucyA9IGNvZXJjZSgnbG9jYXRpb25zJyk7XG4gICAgdmFyIHogPSBjb2VyY2UoJ3onKTtcbiAgICB2YXIgZ2VvanNvbiA9IGNvZXJjZSgnZ2VvanNvbicpO1xuXG4gICAgaWYoIUxpYi5pc0FycmF5T3JUeXBlZEFycmF5KGxvY2F0aW9ucykgfHwgIWxvY2F0aW9ucy5sZW5ndGggfHxcbiAgICAgICAgIUxpYi5pc0FycmF5T3JUeXBlZEFycmF5KHopIHx8ICF6Lmxlbmd0aCB8fFxuICAgICAgICAhKCh0eXBlb2YgZ2VvanNvbiA9PT0gJ3N0cmluZycgJiYgZ2VvanNvbiAhPT0gJycpIHx8IExpYi5pc1BsYWluT2JqZWN0KGdlb2pzb24pKVxuICAgICkge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gTWF0aC5taW4obG9jYXRpb25zLmxlbmd0aCwgei5sZW5ndGgpO1xuXG4gICAgY29lcmNlKCdiZWxvdycpO1xuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGVtcGxhdGUnKTtcblxuICAgIHZhciBtbHcgPSBjb2VyY2UoJ21hcmtlci5saW5lLndpZHRoJyk7XG4gICAgaWYobWx3KSBjb2VyY2UoJ21hcmtlci5saW5lLmNvbG9yJyk7XG4gICAgY29lcmNlKCdtYXJrZXIub3BhY2l0eScpO1xuXG4gICAgY29sb3JzY2FsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge3ByZWZpeDogJycsIGNMZXR0ZXI6ICd6J30pO1xuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0c1wiOjYwMyxcIi4uLy4uL2xpYlwiOjcxOSxcIi4vYXR0cmlidXRlc1wiOjkzMn1dLDkzNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgY29sb3JiYXI6IF9kZXJlcV8oJy4uL2hlYXRtYXAvY29sb3JiYXInKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuLi9jaG9yb3BsZXRoL2NhbGMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKSxcbiAgICBob3ZlclBvaW50czogX2RlcmVxXygnLi4vY2hvcm9wbGV0aC9ob3ZlcicpLFxuICAgIGV2ZW50RGF0YTogX2RlcmVxXygnLi4vY2hvcm9wbGV0aC9ldmVudF9kYXRhJyksXG4gICAgc2VsZWN0UG9pbnRzOiBfZGVyZXFfKCcuLi9jaG9yb3BsZXRoL3NlbGVjdCcpLFxuXG4gICAgc3R5bGVPblNlbGVjdDogZnVuY3Rpb24oXywgY2QpIHtcbiAgICAgICAgaWYoY2QpIHtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgICAgICAgICAgdHJhY2UuX2dsVHJhY2UudXBkYXRlT25TZWxlY3QoY2QpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIGdldEJlbG93OiBmdW5jdGlvbih0cmFjZSwgc3VicGxvdCkge1xuICAgICAgICB2YXIgbWFwTGF5ZXJzID0gc3VicGxvdC5nZXRNYXBMYXllcnMoKTtcblxuICAgICAgICAvLyBmaW5kIGxheWVyIGp1c3QgYWJvdmUgdG9wLW1vc3QgXCJ3YXRlclwiIGxheWVyXG4gICAgICAgIC8vIHRoYXQgaXMgbm90IGEgcGxvdGx5IGxheWVyXG4gICAgICAgIGZvcih2YXIgaSA9IG1hcExheWVycy5sZW5ndGggLSAyOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgdmFyIGxheWVySWQgPSBtYXBMYXllcnNbaV0uaWQ7XG5cbiAgICAgICAgICAgIGlmKHR5cGVvZiBsYXllcklkID09PSAnc3RyaW5nJyAmJlxuICAgICAgICAgICAgICAgIGxheWVySWQuaW5kZXhPZignd2F0ZXInKSA9PT0gMFxuICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaiA9IGkgKyAxOyBqIDwgbWFwTGF5ZXJzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxheWVySWQgPSBtYXBMYXllcnNbal0uaWQ7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYodHlwZW9mIGxheWVySWQgPT09ICdzdHJpbmcnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXllcklkLmluZGV4T2YoJ3Bsb3RseS0nKSA9PT0gLTFcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbGF5ZXJJZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdjaG9yb3BsZXRobWFwYm94JyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvbWFwYm94JyksXG4gICAgY2F0ZWdvcmllczogWydtYXBib3gnLCAnZ2wnLCAnbm9PcGFjaXR5J10sXG4gICAgbWV0YToge1xuICAgICAgICBocl9uYW1lOiAnY2hvcm9wbGV0aF9tYXBib3gnLFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL21hcGJveFwiOjgyMixcIi4uL2Nob3JvcGxldGgvY2FsY1wiOjkyNCxcIi4uL2Nob3JvcGxldGgvZXZlbnRfZGF0YVwiOjkyNixcIi4uL2Nob3JvcGxldGgvaG92ZXJcIjo5MjcsXCIuLi9jaG9yb3BsZXRoL3NlbGVjdFwiOjkzMCxcIi4uL2hlYXRtYXAvY29sb3JiYXJcIjoxMDA0LFwiLi9hdHRyaWJ1dGVzXCI6OTMyLFwiLi9kZWZhdWx0c1wiOjkzNCxcIi4vcGxvdFwiOjkzNn1dLDkzNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb252ZXJ0ID0gX2RlcmVxXygnLi9jb252ZXJ0JykuY29udmVydDtcbnZhciBjb252ZXJ0T25TZWxlY3QgPSBfZGVyZXFfKCcuL2NvbnZlcnQnKS5jb252ZXJ0T25TZWxlY3Q7XG52YXIgTEFZRVJfUFJFRklYID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvbWFwYm94L2NvbnN0YW50cycpLnRyYWNlTGF5ZXJQcmVmaXg7XG5cbmZ1bmN0aW9uIENob3JvcGxldGhNYXBib3goc3VicGxvdCwgdWlkKSB7XG4gICAgdGhpcy5zdWJwbG90ID0gc3VicGxvdDtcbiAgICB0aGlzLnVpZCA9IHVpZDtcblxuICAgIC8vIE4uQi4gZmlsbCBhbmQgbGluZSBsYXllcnMgc2hhcmUgc2FtZSBzb3VyY2VcbiAgICB0aGlzLnNvdXJjZUlkID0gJ3NvdXJjZS0nICsgdWlkO1xuXG4gICAgdGhpcy5sYXllckxpc3QgPSBbXG4gICAgICAgIFsnZmlsbCcsIExBWUVSX1BSRUZJWCArIHVpZCArICctZmlsbCddLFxuICAgICAgICBbJ2xpbmUnLCBMQVlFUl9QUkVGSVggKyB1aWQgKyAnLWxpbmUnXVxuICAgIF07XG5cbiAgICAvLyBwcmV2aW91cyAnYmVsb3cnIHZhbHVlLFxuICAgIC8vIG5lZWQgdGhpcyB0byB1cGRhdGUgaXQgcHJvcGVybHlcbiAgICB0aGlzLmJlbG93ID0gbnVsbDtcbn1cblxudmFyIHByb3RvID0gQ2hvcm9wbGV0aE1hcGJveC5wcm90b3R5cGU7XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGNhbGNUcmFjZSkge1xuICAgIHRoaXMuX3VwZGF0ZShjb252ZXJ0KGNhbGNUcmFjZSkpO1xufTtcblxucHJvdG8udXBkYXRlT25TZWxlY3QgPSBmdW5jdGlvbihjYWxjVHJhY2UpIHtcbiAgICB0aGlzLl91cGRhdGUoY29udmVydE9uU2VsZWN0KGNhbGNUcmFjZSkpO1xufTtcblxucHJvdG8uX3VwZGF0ZSA9IGZ1bmN0aW9uKG9wdHNBbGwpIHtcbiAgICB2YXIgc3VicGxvdCA9IHRoaXMuc3VicGxvdDtcbiAgICB2YXIgbGF5ZXJMaXN0ID0gdGhpcy5sYXllckxpc3Q7XG4gICAgdmFyIGJlbG93ID0gc3VicGxvdC5iZWxvd0xvb2t1cFsndHJhY2UtJyArIHRoaXMudWlkXTtcblxuICAgIHN1YnBsb3QubWFwXG4gICAgICAgIC5nZXRTb3VyY2UodGhpcy5zb3VyY2VJZClcbiAgICAgICAgLnNldERhdGEob3B0c0FsbC5nZW9qc29uKTtcblxuICAgIGlmKGJlbG93ICE9PSB0aGlzLmJlbG93KSB7XG4gICAgICAgIHRoaXMuX3JlbW92ZUxheWVycygpO1xuICAgICAgICB0aGlzLl9hZGRMYXllcnMob3B0c0FsbCwgYmVsb3cpO1xuICAgICAgICB0aGlzLmJlbG93ID0gYmVsb3c7XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxheWVyTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaXRlbSA9IGxheWVyTGlzdFtpXTtcbiAgICAgICAgdmFyIGsgPSBpdGVtWzBdO1xuICAgICAgICB2YXIgaWQgPSBpdGVtWzFdO1xuICAgICAgICB2YXIgb3B0cyA9IG9wdHNBbGxba107XG5cbiAgICAgICAgc3VicGxvdC5zZXRPcHRpb25zKGlkLCAnc2V0TGF5b3V0UHJvcGVydHknLCBvcHRzLmxheW91dCk7XG5cbiAgICAgICAgaWYob3B0cy5sYXlvdXQudmlzaWJpbGl0eSA9PT0gJ3Zpc2libGUnKSB7XG4gICAgICAgICAgICBzdWJwbG90LnNldE9wdGlvbnMoaWQsICdzZXRQYWludFByb3BlcnR5Jywgb3B0cy5wYWludCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5wcm90by5fYWRkTGF5ZXJzID0gZnVuY3Rpb24ob3B0c0FsbCwgYmVsb3cpIHtcbiAgICB2YXIgc3VicGxvdCA9IHRoaXMuc3VicGxvdDtcbiAgICB2YXIgbGF5ZXJMaXN0ID0gdGhpcy5sYXllckxpc3Q7XG4gICAgdmFyIHNvdXJjZUlkID0gdGhpcy5zb3VyY2VJZDtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsYXllckxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGl0ZW0gPSBsYXllckxpc3RbaV07XG4gICAgICAgIHZhciBrID0gaXRlbVswXTtcbiAgICAgICAgdmFyIG9wdHMgPSBvcHRzQWxsW2tdO1xuXG4gICAgICAgIHN1YnBsb3QuYWRkTGF5ZXIoe1xuICAgICAgICAgICAgdHlwZTogayxcbiAgICAgICAgICAgIGlkOiBpdGVtWzFdLFxuICAgICAgICAgICAgc291cmNlOiBzb3VyY2VJZCxcbiAgICAgICAgICAgIGxheW91dDogb3B0cy5sYXlvdXQsXG4gICAgICAgICAgICBwYWludDogb3B0cy5wYWludFxuICAgICAgICB9LCBiZWxvdyk7XG4gICAgfVxufTtcblxucHJvdG8uX3JlbW92ZUxheWVycyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBtYXAgPSB0aGlzLnN1YnBsb3QubWFwO1xuICAgIHZhciBsYXllckxpc3QgPSB0aGlzLmxheWVyTGlzdDtcblxuICAgIGZvcih2YXIgaSA9IGxheWVyTGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBtYXAucmVtb3ZlTGF5ZXIobGF5ZXJMaXN0W2ldWzFdKTtcbiAgICB9XG59O1xuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1hcCA9IHRoaXMuc3VicGxvdC5tYXA7XG4gICAgdGhpcy5fcmVtb3ZlTGF5ZXJzKCk7XG4gICAgbWFwLnJlbW92ZVNvdXJjZSh0aGlzLnNvdXJjZUlkKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3JlYXRlQ2hvcm9wbGV0aE1hcGJveChzdWJwbG90LCBjYWxjVHJhY2UpIHtcbiAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG4gICAgdmFyIGNob3JvcGxldGhNYXBib3ggPSBuZXcgQ2hvcm9wbGV0aE1hcGJveChzdWJwbG90LCB0cmFjZS51aWQpO1xuICAgIHZhciBzb3VyY2VJZCA9IGNob3JvcGxldGhNYXBib3guc291cmNlSWQ7XG4gICAgdmFyIG9wdHNBbGwgPSBjb252ZXJ0KGNhbGNUcmFjZSk7XG4gICAgdmFyIGJlbG93ID0gY2hvcm9wbGV0aE1hcGJveC5iZWxvdyA9IHN1YnBsb3QuYmVsb3dMb29rdXBbJ3RyYWNlLScgKyB0cmFjZS51aWRdO1xuXG4gICAgc3VicGxvdC5tYXAuYWRkU291cmNlKHNvdXJjZUlkLCB7XG4gICAgICAgIHR5cGU6ICdnZW9qc29uJyxcbiAgICAgICAgZGF0YTogb3B0c0FsbC5nZW9qc29uXG4gICAgfSk7XG5cbiAgICBjaG9yb3BsZXRoTWFwYm94Ll9hZGRMYXllcnMob3B0c0FsbCwgYmVsb3cpO1xuXG4gICAgLy8gbGluayByZWYgZm9yIHF1aWNrIHVwZGF0ZSBkdXJpbmcgc2VsZWN0aW9uc1xuICAgIGNhbGNUcmFjZVswXS50cmFjZS5fZ2xUcmFjZSA9IGNob3JvcGxldGhNYXBib3g7XG5cbiAgICByZXR1cm4gY2hvcm9wbGV0aE1hcGJveDtcbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvbWFwYm94L2NvbnN0YW50c1wiOjgyMCxcIi4vY29udmVydFwiOjkzM31dLDkzNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGhvdmVydGVtcGxhdGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzJyk7XG52YXIgbWVzaDNkQXR0cnMgPSBfZGVyZXFfKCcuLi9tZXNoM2QvYXR0cmlidXRlcycpO1xudmFyIGJhc2VBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIGF0dHJzID0ge1xuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgejoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdzoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICAvLyBUT0RPIGFkZCB3YXkgdG8gc3BlY2lmeSBjb25lIHBvc2l0aW9ucyBpbmRlcGVuZGVudGx5IG9mIHRoZSB2ZWN0b3IgZmllbGRcbiAgICAvLyBwcm92aWRlZCwgc2ltaWxhciB0byBNQVRMQUIncyBjb25lcGxvdCBDeC9DeS9DeiBtZXNoZ3JpZHMsXG4gICAgLy8gc2VlIGh0dHBzOi8vd3d3Lm1hdGh3b3Jrcy5jb20vaGVscC9tYXRsYWIvcmVmL2NvbmVwbG90Lmh0bWxcbiAgICAvL1xuICAgIC8vIEFsdGVybmF0aXZlbHksIGlmIG91ciBnb2FsIGlzIG9ubHkgdG8gJ2ZpbGwgaW4gZ2FwcycgaW4gdGhlIHZlY3RvciBkYXRhLFxuICAgIC8vIHdlIGNvdWxkIHRyeSB0byBleHRlbmQgdGhlIGhlYXRtYXAgJ2Nvbm5lY3RnYXBzJyBhbGdvcml0aG0gdG8gM0QuXG4gICAgLy8gRnJvbSBBSjogdGhpcyBwYXJ0aWN1bGFyIGFsZ29yaXRobSB3aGljaCBhbW91bnRzIHRvIGEgUG9pc3NvbiBlcXVhdGlvbixcbiAgICAvLyBib3RoIGZvciBpbnRlcnBvbGF0aW9uIGFuZCBleHRyYXBvbGF0aW9uIC0gaXMgdGhlIHJpZ2h0IG9uZSB0byB1c2UgZm9yXG4gICAgLy8gY29uZXMgdG9vLiAgSXQgbWFrZXMgYSBmaWVsZCB3aXRoIHplcm8gZGl2ZXJnZW5jZSwgd2hpY2ggaXMgYSBnb29kXG4gICAgLy8gYmFzZWxpbmUgYXNzdW1wdGlvbiBmb3IgdmVjdG9yIGZpZWxkcy5cbiAgICAvL1xuICAgIC8vIGNvbmVzOiB7XG4gICAgLy8gICAgIC8vIHBvdGVudGlhbCBhdHRyaWJ1dGVzIHRvIGFkZDpcbiAgICAvLyAgICAgLy9cbiAgICAvLyAgICAgLy8gLSBtZXNobW9kZTogJ2NhcnRlc2lhbi1wcm9kdWN0JywgJ3B0cycsICdncmlkJ1xuICAgIC8vICAgICAvL1xuICAgIC8vICAgICAvLyB1bmRlciBgbWVzaG1vZGU6ICdncmlkJ2BcbiAgICAvLyAgICAgLy8gLSAoeHx5fHopZ3JpZC5zdGFydFxuICAgIC8vICAgICAvLyAtICh4fHl8eilncmlkLmVuZFxuICAgIC8vICAgICAvLyAtICh4fHl8eilncmlkLnNpemVcbiAgICAvL1xuICAgIC8vICAgICB4OiB7XG4gICAgLy8gICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgLy8gICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIC8vICAgICAgICAgXG4gICAgLy8gICAgIH0sXG4gICAgLy8gICAgIHk6IHtcbiAgICAvLyAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAvLyAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgLy8gICAgICAgICBcbiAgICAvLyAgICAgfSxcbiAgICAvLyAgICAgejoge1xuICAgIC8vICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgIC8vICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAvLyAgICAgICAgIFxuICAgIC8vICAgICB9LFxuICAgIC8vXG4gICAgLy8gICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgLy8gICAgIFxuICAgIC8vIH0sXG5cbiAgICBzaXplbW9kZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydzY2FsZWQnLCAnYWJzb2x1dGUnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIGRmbHQ6ICdzY2FsZWQnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNpemVyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBhbmNob3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgdmFsdWVzOiBbJ3RpcCcsICd0YWlsJywgJ2NtJywgJ2NlbnRlciddLFxuICAgICAgICBkZmx0OiAnY20nLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVydGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycyh7ZWRpdFR5cGU6ICdjYWxjJ30sIHtrZXlzOiBbJ25vcm0nXX0pXG59O1xuXG5leHRlbmRGbGF0KGF0dHJzLCBjb2xvclNjYWxlQXR0cnMoJycsIHtcbiAgICBjb2xvckF0dHI6ICd1L3YvdyBub3JtJyxcbiAgICBzaG93U2NhbGVEZmx0OiB0cnVlLFxuICAgIGVkaXRUeXBlT3ZlcnJpZGU6ICdjYWxjJ1xufSkpO1xuXG52YXIgZnJvbU1lc2gzZCA9IFsnb3BhY2l0eScsICdsaWdodHBvc2l0aW9uJywgJ2xpZ2h0aW5nJ107XG5cbmZyb21NZXNoM2QuZm9yRWFjaChmdW5jdGlvbihrKSB7XG4gICAgYXR0cnNba10gPSBtZXNoM2RBdHRyc1trXTtcbn0pO1xuXG5hdHRycy5ob3ZlcmluZm8gPSBleHRlbmRGbGF0KHt9LCBiYXNlQXR0cnMuaG92ZXJpbmZvLCB7XG4gICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICBmbGFnczogWyd4JywgJ3knLCAneicsICd1JywgJ3YnLCAndycsICdub3JtJywgJ3RleHQnLCAnbmFtZSddLFxuICAgIGRmbHQ6ICd4K3kreitub3JtK3RleHQrbmFtZSdcbn0pO1xuXG5hdHRycy50cmFuc2Zvcm1zID0gdW5kZWZpbmVkO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGF0dHJzO1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzXCI6NjAwLFwiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXNcIjo2MzEsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NCxcIi4uL21lc2gzZC9hdHRyaWJ1dGVzXCI6MTA1M31dLDkzODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvcnNjYWxlQ2FsYyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgdSA9IHRyYWNlLnU7XG4gICAgdmFyIHYgPSB0cmFjZS52O1xuICAgIHZhciB3ID0gdHJhY2UudztcbiAgICB2YXIgbGVuID0gTWF0aC5taW4oXG4gICAgICAgIHRyYWNlLngubGVuZ3RoLCB0cmFjZS55Lmxlbmd0aCwgdHJhY2Uuei5sZW5ndGgsXG4gICAgICAgIHUubGVuZ3RoLCB2Lmxlbmd0aCwgdy5sZW5ndGhcbiAgICApO1xuICAgIHZhciBub3JtTWF4ID0gLUluZmluaXR5O1xuICAgIHZhciBub3JtTWluID0gSW5maW5pdHk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIHV1ID0gdVtpXTtcbiAgICAgICAgdmFyIHZ2ID0gdltpXTtcbiAgICAgICAgdmFyIHd3ID0gd1tpXTtcbiAgICAgICAgdmFyIG5vcm0gPSBNYXRoLnNxcnQodXUgKiB1dSArIHZ2ICogdnYgKyB3dyAqIHd3KTtcblxuICAgICAgICBub3JtTWF4ID0gTWF0aC5tYXgobm9ybU1heCwgbm9ybSk7XG4gICAgICAgIG5vcm1NaW4gPSBNYXRoLm1pbihub3JtTWluLCBub3JtKTtcbiAgICB9XG5cbiAgICB0cmFjZS5fbGVuID0gbGVuO1xuICAgIHRyYWNlLl9ub3JtTWF4ID0gbm9ybU1heDtcblxuICAgIGNvbG9yc2NhbGVDYWxjKGdkLCB0cmFjZSwge1xuICAgICAgICB2YWxzOiBbbm9ybU1pbiwgbm9ybU1heF0sXG4gICAgICAgIGNvbnRhaW5lclN0cjogJycsXG4gICAgICAgIGNMZXR0ZXI6ICdjJ1xuICAgIH0pO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsY1wiOjYwMX1dLDkzOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb25lUGxvdCA9IF9kZXJlcV8oJ2dsLWNvbmUzZCcpO1xudmFyIGNyZWF0ZUNvbmVNZXNoID0gX2RlcmVxXygnZ2wtY29uZTNkJykuY3JlYXRlQ29uZU1lc2g7XG5cbnZhciBzaW1wbGVNYXAgPSBfZGVyZXFfKCcuLi8uLi9saWInKS5zaW1wbGVNYXA7XG52YXIgcGFyc2VDb2xvclNjYWxlID0gX2RlcmVxXygnLi4vLi4vbGliL2dsX2Zvcm1hdF9jb2xvcicpLnBhcnNlQ29sb3JTY2FsZTtcbnZhciBleHRyYWN0T3B0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZScpLmV4dHJhY3RPcHRzO1xudmFyIHppcDMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9nbDNkL3ppcDMnKTtcblxuZnVuY3Rpb24gQ29uZShzY2VuZSwgdWlkKSB7XG4gICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIHRoaXMudWlkID0gdWlkO1xuICAgIHRoaXMubWVzaCA9IG51bGw7XG4gICAgdGhpcy5kYXRhID0gbnVsbDtcbn1cblxudmFyIHByb3RvID0gQ29uZS5wcm90b3R5cGU7XG5cbnByb3RvLmhhbmRsZVBpY2sgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcbiAgICBpZihzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLm1lc2gpIHtcbiAgICAgICAgdmFyIHNlbGVjdEluZGV4ID0gc2VsZWN0aW9uLmluZGV4ID0gc2VsZWN0aW9uLmRhdGEuaW5kZXg7XG4gICAgICAgIHZhciB4eCA9IHRoaXMuZGF0YS54W3NlbGVjdEluZGV4XTtcbiAgICAgICAgdmFyIHl5ID0gdGhpcy5kYXRhLnlbc2VsZWN0SW5kZXhdO1xuICAgICAgICB2YXIgenogPSB0aGlzLmRhdGEueltzZWxlY3RJbmRleF07XG4gICAgICAgIHZhciB1dSA9IHRoaXMuZGF0YS51W3NlbGVjdEluZGV4XTtcbiAgICAgICAgdmFyIHZ2ID0gdGhpcy5kYXRhLnZbc2VsZWN0SW5kZXhdO1xuICAgICAgICB2YXIgd3cgPSB0aGlzLmRhdGEud1tzZWxlY3RJbmRleF07XG5cbiAgICAgICAgc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZSA9IFtcbiAgICAgICAgICAgIHh4LCB5eSwgenosXG4gICAgICAgICAgICB1dSwgdnYsIHd3LFxuICAgICAgICAgICAgTWF0aC5zcXJ0KHV1ICogdXUgKyB2diAqIHZ2ICsgd3cgKiB3dylcbiAgICAgICAgXTtcblxuICAgICAgICB2YXIgdGV4dCA9IHRoaXMuZGF0YS5ob3ZlcnRleHQgfHwgdGhpcy5kYXRhLnRleHQ7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodGV4dCkgJiYgdGV4dFtzZWxlY3RJbmRleF0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgc2VsZWN0aW9uLnRleHRMYWJlbCA9IHRleHRbc2VsZWN0SW5kZXhdO1xuICAgICAgICB9IGVsc2UgaWYodGV4dCkge1xuICAgICAgICAgICAgc2VsZWN0aW9uLnRleHRMYWJlbCA9IHRleHQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59O1xuXG52YXIgYXhpc05hbWUyc2NhbGVJbmRleCA9IHt4YXhpczogMCwgeWF4aXM6IDEsIHpheGlzOiAyfTtcbnZhciBhbmNob3IyY29uZU9mZnNldCA9IHt0aXA6IDEsIHRhaWw6IDAsIGNtOiAwLjI1LCBjZW50ZXI6IDAuNX07XG52YXIgYW5jaG9yMmNvbmVTcGFuID0ge3RpcDogMSwgdGFpbDogMSwgY206IDAuNzUsIGNlbnRlcjogMC41fTtcblxuZnVuY3Rpb24gY29udmVydChzY2VuZSwgdHJhY2UpIHtcbiAgICB2YXIgc2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIGRhdGFTY2FsZSA9IHNjZW5lLmRhdGFTY2FsZTtcbiAgICB2YXIgY29uZU9wdHMgPSB7fTtcblxuICAgIGZ1bmN0aW9uIHRvRGF0YUNvb3JkcyhhcnIsIGF4aXNOYW1lKSB7XG4gICAgICAgIHZhciBheCA9IHNjZW5lTGF5b3V0W2F4aXNOYW1lXTtcbiAgICAgICAgdmFyIHNjYWxlID0gZGF0YVNjYWxlW2F4aXNOYW1lMnNjYWxlSW5kZXhbYXhpc05hbWVdXTtcbiAgICAgICAgcmV0dXJuIHNpbXBsZU1hcChhcnIsIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGF4LmQybCh2KSAqIHNjYWxlOyB9KTtcbiAgICB9XG5cbiAgICBjb25lT3B0cy52ZWN0b3JzID0gemlwMyhcbiAgICAgICAgdG9EYXRhQ29vcmRzKHRyYWNlLnUsICd4YXhpcycpLFxuICAgICAgICB0b0RhdGFDb29yZHModHJhY2UudiwgJ3lheGlzJyksXG4gICAgICAgIHRvRGF0YUNvb3Jkcyh0cmFjZS53LCAnemF4aXMnKSxcbiAgICAgICAgdHJhY2UuX2xlblxuICAgICk7XG5cbiAgICBjb25lT3B0cy5wb3NpdGlvbnMgPSB6aXAzKFxuICAgICAgICB0b0RhdGFDb29yZHModHJhY2UueCwgJ3hheGlzJyksXG4gICAgICAgIHRvRGF0YUNvb3Jkcyh0cmFjZS55LCAneWF4aXMnKSxcbiAgICAgICAgdG9EYXRhQ29vcmRzKHRyYWNlLnosICd6YXhpcycpLFxuICAgICAgICB0cmFjZS5fbGVuXG4gICAgKTtcblxuICAgIHZhciBjT3B0cyA9IGV4dHJhY3RPcHRzKHRyYWNlKTtcbiAgICBjb25lT3B0cy5jb2xvcm1hcCA9IHBhcnNlQ29sb3JTY2FsZSh0cmFjZSk7XG4gICAgY29uZU9wdHMudmVydGV4SW50ZW5zaXR5Qm91bmRzID0gW2NPcHRzLm1pbiAvIHRyYWNlLl9ub3JtTWF4LCBjT3B0cy5tYXggLyB0cmFjZS5fbm9ybU1heF07XG4gICAgY29uZU9wdHMuY29uZU9mZnNldCA9IGFuY2hvcjJjb25lT2Zmc2V0W3RyYWNlLmFuY2hvcl07XG5cbiAgICBpZih0cmFjZS5zaXplbW9kZSA9PT0gJ3NjYWxlZCcpIHtcbiAgICAgICAgLy8gdW5pdGxlc3Mgc2l6ZXJlZlxuICAgICAgICBjb25lT3B0cy5jb25lU2l6ZSA9IHRyYWNlLnNpemVyZWYgfHwgMC41O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNpemVyZWYgaGVyZSBoYXMgdW5pdCBvZiB2ZWxvY2l0eVxuICAgICAgICBjb25lT3B0cy5jb25lU2l6ZSA9IHRyYWNlLnNpemVyZWYgJiYgdHJhY2UuX25vcm1NYXggP1xuICAgICAgICAgICAgdHJhY2Uuc2l6ZXJlZiAvIHRyYWNlLl9ub3JtTWF4IDpcbiAgICAgICAgICAgIDAuNTtcbiAgICB9XG5cbiAgICB2YXIgbWVzaERhdGEgPSBjb25lUGxvdChjb25lT3B0cyk7XG5cbiAgICAvLyBwYXNzIGdsLW1lc2gzZCBsaWdodGluZyBhdHRyaWJ1dGVzXG4gICAgdmFyIGxwID0gdHJhY2UubGlnaHRwb3NpdGlvbjtcbiAgICBtZXNoRGF0YS5saWdodFBvc2l0aW9uID0gW2xwLngsIGxwLnksIGxwLnpdO1xuICAgIG1lc2hEYXRhLmFtYmllbnQgPSB0cmFjZS5saWdodGluZy5hbWJpZW50O1xuICAgIG1lc2hEYXRhLmRpZmZ1c2UgPSB0cmFjZS5saWdodGluZy5kaWZmdXNlO1xuICAgIG1lc2hEYXRhLnNwZWN1bGFyID0gdHJhY2UubGlnaHRpbmcuc3BlY3VsYXI7XG4gICAgbWVzaERhdGEucm91Z2huZXNzID0gdHJhY2UubGlnaHRpbmcucm91Z2huZXNzO1xuICAgIG1lc2hEYXRhLmZyZXNuZWwgPSB0cmFjZS5saWdodGluZy5mcmVzbmVsO1xuICAgIG1lc2hEYXRhLm9wYWNpdHkgPSB0cmFjZS5vcGFjaXR5O1xuXG4gICAgLy8gc3Rhc2ggYXV0b3JhbmdlIHBhZCB2YWx1ZVxuICAgIHRyYWNlLl9wYWQgPSBhbmNob3IyY29uZVNwYW5bdHJhY2UuYW5jaG9yXSAqIG1lc2hEYXRhLnZlY3RvclNjYWxlICogbWVzaERhdGEuY29uZVNjYWxlICogdHJhY2UuX25vcm1NYXg7XG5cbiAgICByZXR1cm4gbWVzaERhdGE7XG59XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuXG4gICAgdmFyIG1lc2hEYXRhID0gY29udmVydCh0aGlzLnNjZW5lLCBkYXRhKTtcbiAgICB0aGlzLm1lc2gudXBkYXRlKG1lc2hEYXRhKTtcbn07XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5tZXNoKTtcbiAgICB0aGlzLm1lc2guZGlzcG9zZSgpO1xufTtcblxuZnVuY3Rpb24gY3JlYXRlQ29uZVRyYWNlKHNjZW5lLCBkYXRhKSB7XG4gICAgdmFyIGdsID0gc2NlbmUuZ2xwbG90LmdsO1xuXG4gICAgdmFyIG1lc2hEYXRhID0gY29udmVydChzY2VuZSwgZGF0YSk7XG4gICAgdmFyIG1lc2ggPSBjcmVhdGVDb25lTWVzaChnbCwgbWVzaERhdGEpO1xuXG4gICAgdmFyIGNvbmUgPSBuZXcgQ29uZShzY2VuZSwgZGF0YS51aWQpO1xuICAgIGNvbmUubWVzaCA9IG1lc2g7XG4gICAgY29uZS5kYXRhID0gZGF0YTtcbiAgICBtZXNoLl90cmFjZSA9IGNvbmU7XG5cbiAgICBzY2VuZS5nbHBsb3QuYWRkKG1lc2gpO1xuXG4gICAgcmV0dXJuIGNvbmU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlQ29uZVRyYWNlO1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZVwiOjYwNSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9nbF9mb3JtYXRfY29sb3JcIjo3MTYsXCIuLi8uLi9wbG90cy9nbDNkL3ppcDNcIjo4MTgsXCJnbC1jb25lM2RcIjoyNDJ9XSw5NDA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHUgPSBjb2VyY2UoJ3UnKTtcbiAgICB2YXIgdiA9IGNvZXJjZSgndicpO1xuICAgIHZhciB3ID0gY29lcmNlKCd3Jyk7XG5cbiAgICB2YXIgeCA9IGNvZXJjZSgneCcpO1xuICAgIHZhciB5ID0gY29lcmNlKCd5Jyk7XG4gICAgdmFyIHogPSBjb2VyY2UoJ3onKTtcblxuICAgIGlmKFxuICAgICAgICAhdSB8fCAhdS5sZW5ndGggfHwgIXYgfHwgIXYubGVuZ3RoIHx8ICF3IHx8ICF3Lmxlbmd0aCB8fFxuICAgICAgICAheCB8fCAheC5sZW5ndGggfHwgIXkgfHwgIXkubGVuZ3RoIHx8ICF6IHx8ICF6Lmxlbmd0aFxuICAgICkge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3NpemVyZWYnKTtcbiAgICBjb2VyY2UoJ3NpemVtb2RlJyk7XG5cbiAgICBjb2VyY2UoJ2FuY2hvcicpO1xuXG4gICAgY29lcmNlKCdsaWdodGluZy5hbWJpZW50Jyk7XG4gICAgY29lcmNlKCdsaWdodGluZy5kaWZmdXNlJyk7XG4gICAgY29lcmNlKCdsaWdodGluZy5zcGVjdWxhcicpO1xuICAgIGNvZXJjZSgnbGlnaHRpbmcucm91Z2huZXNzJyk7XG4gICAgY29lcmNlKCdsaWdodGluZy5mcmVzbmVsJyk7XG4gICAgY29lcmNlKCdsaWdodHBvc2l0aW9uLngnKTtcbiAgICBjb2VyY2UoJ2xpZ2h0cG9zaXRpb24ueScpO1xuICAgIGNvZXJjZSgnbGlnaHRwb3NpdGlvbi56Jyk7XG5cbiAgICBjb2xvcnNjYWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnJywgY0xldHRlcjogJ2MnfSk7XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgLy8gZGlzYWJsZSAxRCB0cmFuc2Zvcm1zIChmb3Igbm93KVxuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBudWxsO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHNcIjo2MDMsXCIuLi8uLi9saWJcIjo3MTksXCIuL2F0dHJpYnV0ZXNcIjo5Mzd9XSw5NDE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdjb25lJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2wzZCcpLFxuICAgIGNhdGVnb3JpZXM6IFsnZ2wzZCddLFxuXG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjb2xvcmJhcjoge1xuICAgICAgICBtaW46ICdjbWluJyxcbiAgICAgICAgbWF4OiAnY21heCdcbiAgICB9LFxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vY29udmVydCcpLFxuICAgIGV2ZW50RGF0YTogZnVuY3Rpb24ob3V0LCBwdCkge1xuICAgICAgICBvdXQubm9ybSA9IHB0LnRyYWNlQ29vcmRpbmF0ZVs2XTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9LFxuXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2dsM2RcIjo4MDcsXCIuL2F0dHJpYnV0ZXNcIjo5MzcsXCIuL2NhbGNcIjo5MzgsXCIuL2NvbnZlcnRcIjo5MzksXCIuL2RlZmF1bHRzXCI6OTQwfV0sOTQyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGhlYXRtYXBBdHRycyA9IF9kZXJlcV8oJy4uL2hlYXRtYXAvYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJBdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgZGFzaCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZy9hdHRyaWJ1dGVzJykuZGFzaDtcbnZhciBmb250QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciBmaWx0ZXJPcHMgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvZmlsdGVyX29wcycpO1xudmFyIENPTVBBUklTT05fT1BTMiA9IGZpbHRlck9wcy5DT01QQVJJU09OX09QUzI7XG52YXIgSU5URVJWQUxfT1BTID0gZmlsdGVyT3BzLklOVEVSVkFMX09QUztcblxudmFyIEZPUk1BVF9MSU5LID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2RvY3MnKS5GT1JNQVRfTElOSztcblxudmFyIHNjYXR0ZXJMaW5lQXR0cnMgPSBzY2F0dGVyQXR0cnMubGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSBleHRlbmRGbGF0KHtcbiAgICB6OiBoZWF0bWFwQXR0cnMueixcbiAgICB4OiBoZWF0bWFwQXR0cnMueCxcbiAgICB4MDogaGVhdG1hcEF0dHJzLngwLFxuICAgIGR4OiBoZWF0bWFwQXR0cnMuZHgsXG4gICAgeTogaGVhdG1hcEF0dHJzLnksXG4gICAgeTA6IGhlYXRtYXBBdHRycy55MCxcbiAgICBkeTogaGVhdG1hcEF0dHJzLmR5LFxuICAgIHRleHQ6IGhlYXRtYXBBdHRycy50ZXh0LFxuICAgIGhvdmVydGV4dDogaGVhdG1hcEF0dHJzLmhvdmVydGV4dCxcbiAgICB0cmFuc3Bvc2U6IGhlYXRtYXBBdHRycy50cmFuc3Bvc2UsXG4gICAgeHR5cGU6IGhlYXRtYXBBdHRycy54dHlwZSxcbiAgICB5dHlwZTogaGVhdG1hcEF0dHJzLnl0eXBlLFxuICAgIHpob3ZlcmZvcm1hdDogaGVhdG1hcEF0dHJzLnpob3ZlcmZvcm1hdCxcbiAgICBob3ZlcnRlbXBsYXRlOiBoZWF0bWFwQXR0cnMuaG92ZXJ0ZW1wbGF0ZSxcblxuICAgIGNvbm5lY3RnYXBzOiBoZWF0bWFwQXR0cnMuY29ubmVjdGdhcHMsXG5cbiAgICBmaWxsY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBhdXRvY29udG91cjoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBpbXBsaWVkRWRpdHM6IHtcbiAgICAgICAgICAgICdjb250b3Vycy5zdGFydCc6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICdjb250b3Vycy5lbmQnOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAnY29udG91cnMuc2l6ZSc6IHVuZGVmaW5lZFxuICAgICAgICB9LFxuICAgICAgICBcbiAgICB9LFxuICAgIG5jb250b3Vyczoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIGRmbHQ6IDE1LFxuICAgICAgICBtaW46IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgY29udG91cnM6IHtcbiAgICAgICAgdHlwZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2xldmVscycsICdjb25zdHJhaW50J10sXG4gICAgICAgICAgICBkZmx0OiAnbGV2ZWxzJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzdGFydDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7J15hdXRvY29udG91cic6IGZhbHNlfSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlbmQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIGltcGxpZWRFZGl0czogeydeYXV0b2NvbnRvdXInOiBmYWxzZX0sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2l6ZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgaW1wbGllZEVkaXRzOiB7J15hdXRvY29udG91cic6IGZhbHNlfSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBjb2xvcmluZzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2ZpbGwnLCAnaGVhdG1hcCcsICdsaW5lcycsICdub25lJ10sXG4gICAgICAgICAgICBkZmx0OiAnZmlsbCcsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2hvd2xpbmVzOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNob3dsYWJlbHM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxhYmVsZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBjb2xvckVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBsYWJlbGZvcm1hdDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBvcGVyYXRpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogW10uY29uY2F0KENPTVBBUklTT05fT1BTMikuY29uY2F0KElOVEVSVkFMX09QUyksXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6ICc9JyxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdhbnknLFxuICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBpbXBsaWVkRWRpdHM6IHsnYXV0b2NvbnRvdXInOiBmYWxzZX1cbiAgICB9LFxuXG4gICAgbGluZToge1xuICAgICAgICBjb2xvcjogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckxpbmVBdHRycy5jb2xvciwge1xuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZStjb2xvcmJhcnMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICB3aWR0aDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckxpbmVBdHRycy53aWR0aCwge1xuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZStjb2xvcmJhcnMnXG4gICAgICAgIH0pLFxuICAgICAgICBkYXNoOiBkYXNoLFxuICAgICAgICBzbW9vdGhpbmc6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJMaW5lQXR0cnMuc21vb3RoaW5nLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9XG59LFxuICAgIGNvbG9yU2NhbGVBdHRycygnJywge1xuICAgICAgICBjTGV0dGVyOiAneicsXG4gICAgICAgIGF1dG9Db2xvckRmbHQ6IGZhbHNlLFxuICAgICAgICBlZGl0VHlwZU92ZXJyaWRlOiAnY2FsYydcbiAgICB9KVxuKTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZy9hdHRyaWJ1dGVzXCI6NjEzLFwiLi4vLi4vY29uc3RhbnRzL2RvY3NcIjo2OTAsXCIuLi8uLi9jb25zdGFudHMvZmlsdGVyX29wc1wiOjY5MSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTMsXCIuLi9oZWF0bWFwL2F0dHJpYnV0ZXNcIjoxMDAxLFwiLi4vc2NhdHRlci9hdHRyaWJ1dGVzXCI6MTExMn1dLDk0MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBDb2xvcnNjYWxlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlJyk7XG5cbnZhciBoZWF0bWFwQ2FsYyA9IF9kZXJlcV8oJy4uL2hlYXRtYXAvY2FsYycpO1xudmFyIHNldENvbnRvdXJzID0gX2RlcmVxXygnLi9zZXRfY29udG91cnMnKTtcbnZhciBlbmRQbHVzID0gX2RlcmVxXygnLi9lbmRfcGx1cycpO1xuXG4vLyBtb3N0IGlzIHRoZSBzYW1lIGFzIGhlYXRtYXAgY2FsYywgdGhlbiBhZGp1c3QgaXRcbi8vIHRob3VnaCBhIGZldyB0aGluZ3MgaW5zaWRlIGhlYXRtYXAgY2FsYyBzdGlsbCBsb29rIGZvclxuLy8gY29udG91ciBtYXBzLCBiZWNhdXNlIHRoZSBtYWtlQm91bmRBcnJheSBjYWxscyBhcmUgdG9vIGVudGFuZ2xlZFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBjZCA9IGhlYXRtYXBDYWxjKGdkLCB0cmFjZSk7XG5cbiAgICB2YXIgek91dCA9IGNkWzBdLno7XG4gICAgc2V0Q29udG91cnModHJhY2UsIHpPdXQpO1xuXG4gICAgdmFyIGNvbnRvdXJzID0gdHJhY2UuY29udG91cnM7XG4gICAgdmFyIGNPcHRzID0gQ29sb3JzY2FsZS5leHRyYWN0T3B0cyh0cmFjZSk7XG4gICAgdmFyIGNWYWxzO1xuXG4gICAgaWYoY29udG91cnMuY29sb3JpbmcgPT09ICdoZWF0bWFwJyAmJiBjT3B0cy5hdXRvICYmIHRyYWNlLmF1dG9jb250b3VyID09PSBmYWxzZSkge1xuICAgICAgICB2YXIgc3RhcnQgPSBjb250b3Vycy5zdGFydDtcbiAgICAgICAgdmFyIGVuZCA9IGVuZFBsdXMoY29udG91cnMpO1xuICAgICAgICB2YXIgY3MgPSBjb250b3Vycy5zaXplIHx8IDE7XG4gICAgICAgIHZhciBuYyA9IE1hdGguZmxvb3IoKGVuZCAtIHN0YXJ0KSAvIGNzKSArIDE7XG5cbiAgICAgICAgaWYoIWlzRmluaXRlKGNzKSkge1xuICAgICAgICAgICAgY3MgPSAxO1xuICAgICAgICAgICAgbmMgPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1pbjAgPSBzdGFydCAtIGNzIC8gMjtcbiAgICAgICAgdmFyIG1heDAgPSBtaW4wICsgbmMgKiBjcztcbiAgICAgICAgY1ZhbHMgPSBbbWluMCwgbWF4MF07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY1ZhbHMgPSB6T3V0O1xuICAgIH1cblxuICAgIENvbG9yc2NhbGUuY2FsYyhnZCwgdHJhY2UsIHt2YWxzOiBjVmFscywgY0xldHRlcjogJ3onfSk7XG5cbiAgICByZXR1cm4gY2Q7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZVwiOjYwNSxcIi4uL2hlYXRtYXAvY2FsY1wiOjEwMDIsXCIuL2VuZF9wbHVzXCI6OTUzLFwiLi9zZXRfY29udG91cnNcIjo5NjF9XSw5NDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHBhdGhpbmZvLCBvcGVyYXRpb24sIHBlcmltZXRlciwgdHJhY2UpIHtcbiAgICAvLyBBYmFuZG9uIGFsbCBob3BlLCB5ZSB3aG8gZW50ZXIgaGVyZS5cbiAgICB2YXIgaSwgdjEsIHYyO1xuICAgIHZhciBwaTAgPSBwYXRoaW5mb1swXTtcbiAgICB2YXIgbmEgPSBwaTAueC5sZW5ndGg7XG4gICAgdmFyIG5iID0gcGkwLnkubGVuZ3RoO1xuICAgIHZhciB6ID0gcGkwLno7XG4gICAgdmFyIGNvbnRvdXJzID0gdHJhY2UuY29udG91cnM7XG5cbiAgICB2YXIgYm91bmRhcnlNYXggPSAtSW5maW5pdHk7XG4gICAgdmFyIGJvdW5kYXJ5TWluID0gSW5maW5pdHk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBuYjsgaSsrKSB7XG4gICAgICAgIGJvdW5kYXJ5TWluID0gTWF0aC5taW4oYm91bmRhcnlNaW4sIHpbaV1bMF0pO1xuICAgICAgICBib3VuZGFyeU1pbiA9IE1hdGgubWluKGJvdW5kYXJ5TWluLCB6W2ldW25hIC0gMV0pO1xuICAgICAgICBib3VuZGFyeU1heCA9IE1hdGgubWF4KGJvdW5kYXJ5TWF4LCB6W2ldWzBdKTtcbiAgICAgICAgYm91bmRhcnlNYXggPSBNYXRoLm1heChib3VuZGFyeU1heCwgeltpXVtuYSAtIDFdKTtcbiAgICB9XG5cbiAgICBmb3IoaSA9IDE7IGkgPCBuYSAtIDE7IGkrKykge1xuICAgICAgICBib3VuZGFyeU1pbiA9IE1hdGgubWluKGJvdW5kYXJ5TWluLCB6WzBdW2ldKTtcbiAgICAgICAgYm91bmRhcnlNaW4gPSBNYXRoLm1pbihib3VuZGFyeU1pbiwgeltuYiAtIDFdW2ldKTtcbiAgICAgICAgYm91bmRhcnlNYXggPSBNYXRoLm1heChib3VuZGFyeU1heCwgelswXVtpXSk7XG4gICAgICAgIGJvdW5kYXJ5TWF4ID0gTWF0aC5tYXgoYm91bmRhcnlNYXgsIHpbbmIgLSAxXVtpXSk7XG4gICAgfVxuXG4gICAgcGkwLnByZWZpeEJvdW5kYXJ5ID0gZmFsc2U7XG5cbiAgICBzd2l0Y2gob3BlcmF0aW9uKSB7XG4gICAgICAgIGNhc2UgJz4nOlxuICAgICAgICAgICAgaWYoY29udG91cnMudmFsdWUgPiBib3VuZGFyeU1heCkge1xuICAgICAgICAgICAgICAgIHBpMC5wcmVmaXhCb3VuZGFyeSA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnPCc6XG4gICAgICAgICAgICBpZihjb250b3Vycy52YWx1ZSA8IGJvdW5kYXJ5TWluKSB7XG4gICAgICAgICAgICAgICAgcGkwLnByZWZpeEJvdW5kYXJ5ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdbXSc6XG4gICAgICAgICAgICB2MSA9IE1hdGgubWluLmFwcGx5KG51bGwsIGNvbnRvdXJzLnZhbHVlKTtcbiAgICAgICAgICAgIHYyID0gTWF0aC5tYXguYXBwbHkobnVsbCwgY29udG91cnMudmFsdWUpO1xuICAgICAgICAgICAgaWYodjIgPCBib3VuZGFyeU1pbiB8fCB2MSA+IGJvdW5kYXJ5TWF4KSB7XG4gICAgICAgICAgICAgICAgcGkwLnByZWZpeEJvdW5kYXJ5ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICddWyc6XG4gICAgICAgICAgICB2MSA9IE1hdGgubWluLmFwcGx5KG51bGwsIGNvbnRvdXJzLnZhbHVlKTtcbiAgICAgICAgICAgIHYyID0gTWF0aC5tYXguYXBwbHkobnVsbCwgY29udG91cnMudmFsdWUpO1xuICAgICAgICAgICAgaWYodjEgPCBib3VuZGFyeU1pbiAmJiB2MiA+IGJvdW5kYXJ5TWF4KSB7XG4gICAgICAgICAgICAgICAgcGkwLnByZWZpeEJvdW5kYXJ5ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbn07XG5cbn0se31dLDk0NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBleHRyYWN0T3B0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZScpLmV4dHJhY3RPcHRzO1xudmFyIG1ha2VDb2xvck1hcCA9IF9kZXJlcV8oJy4vbWFrZV9jb2xvcl9tYXAnKTtcbnZhciBlbmRQbHVzID0gX2RlcmVxXygnLi9lbmRfcGx1cycpO1xuXG5mdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSwgb3B0cykge1xuICAgIHZhciBjb250b3VycyA9IHRyYWNlLmNvbnRvdXJzO1xuICAgIHZhciBsaW5lID0gdHJhY2UubGluZTtcbiAgICB2YXIgY3MgPSBjb250b3Vycy5zaXplIHx8IDE7XG4gICAgdmFyIGNvbG9yaW5nID0gY29udG91cnMuY29sb3Jpbmc7XG4gICAgdmFyIGNvbG9yTWFwID0gbWFrZUNvbG9yTWFwKHRyYWNlLCB7aXNDb2xvcmJhcjogdHJ1ZX0pO1xuXG4gICAgaWYoY29sb3JpbmcgPT09ICdoZWF0bWFwJykge1xuICAgICAgICB2YXIgY09wdHMgPSBleHRyYWN0T3B0cyh0cmFjZSk7XG4gICAgICAgIG9wdHMuX2ZpbGxncmFkaWVudCA9IHRyYWNlLmNvbG9yc2NhbGU7XG4gICAgICAgIG9wdHMuX3pyYW5nZSA9IFtjT3B0cy5taW4sIGNPcHRzLm1heF07XG4gICAgfSBlbHNlIGlmKGNvbG9yaW5nID09PSAnZmlsbCcpIHtcbiAgICAgICAgb3B0cy5fZmlsbGNvbG9yID0gY29sb3JNYXA7XG4gICAgfVxuXG4gICAgb3B0cy5fbGluZSA9IHtcbiAgICAgICAgY29sb3I6IGNvbG9yaW5nID09PSAnbGluZXMnID8gY29sb3JNYXAgOiBsaW5lLmNvbG9yLFxuICAgICAgICB3aWR0aDogY29udG91cnMuc2hvd2xpbmVzICE9PSBmYWxzZSA/IGxpbmUud2lkdGggOiAwLFxuICAgICAgICBkYXNoOiBsaW5lLmRhc2hcbiAgICB9O1xuXG4gICAgb3B0cy5fbGV2ZWxzID0ge1xuICAgICAgICBzdGFydDogY29udG91cnMuc3RhcnQsXG4gICAgICAgIGVuZDogZW5kUGx1cyhjb250b3VycyksXG4gICAgICAgIHNpemU6IGNzXG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbWluOiAnem1pbicsXG4gICAgbWF4OiAnem1heCcsXG4gICAgY2FsYzogY2FsY1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGVcIjo2MDUsXCIuL2VuZF9wbHVzXCI6OTUzLFwiLi9tYWtlX2NvbG9yX21hcFwiOjk1OH1dLDk0NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAvLyBzb21lIGNvbnN0YW50cyB0byBoZWxwIHdpdGggbWFyY2hpbmcgc3F1YXJlcyBhbGdvcml0aG1cbiAgICAvLyB3aGVyZSBkb2VzIHRoZSBwYXRoIHN0YXJ0IGZvciBlYWNoIGluZGV4P1xuICAgIEJPVFRPTVNUQVJUOiBbMSwgOSwgMTMsIDEwNCwgNzEzXSxcbiAgICBUT1BTVEFSVDogWzQsIDYsIDcsIDEwNCwgNzEzXSxcbiAgICBMRUZUU1RBUlQ6IFs4LCAxMiwgMTQsIDIwOCwgMTExNF0sXG4gICAgUklHSFRTVEFSVDogWzIsIDMsIDExLCAyMDgsIDExMTRdLFxuXG4gICAgLy8gd2hpY2ggd2F5IFtkeCxkeV0gZG8gd2UgbGVhdmUgYSBnaXZlbiBpbmRleD9cbiAgICAvLyBzYWRkbGVzIGFyZSBhbHJlYWR5IGRpc2FtYmlndWF0ZWRcbiAgICBORVdERUxUQTogW1xuICAgICAgICBudWxsLCBbLTEsIDBdLCBbMCwgLTFdLCBbLTEsIDBdLFxuICAgICAgICBbMSwgMF0sIG51bGwsIFswLCAtMV0sIFstMSwgMF0sXG4gICAgICAgIFswLCAxXSwgWzAsIDFdLCBudWxsLCBbMCwgMV0sXG4gICAgICAgIFsxLCAwXSwgWzEsIDBdLCBbMCwgLTFdXG4gICAgXSxcblxuICAgIC8vIGZvciBlYWNoIHNhZGRsZSwgdGhlIGZpcnN0IGluZGV4IGhlcmUgaXMgdXNlZFxuICAgIC8vIGZvciBkeHx8ZHk8MCwgdGhlIHNlY29uZCBmb3IgZHh8fGR5PjBcbiAgICBDSE9PU0VTQURETEU6IHtcbiAgICAgICAgMTA0OiBbNCwgMV0sXG4gICAgICAgIDIwODogWzIsIDhdLFxuICAgICAgICA3MTM6IFs3LCAxM10sXG4gICAgICAgIDExMTQ6IFsxMSwgMTRdXG4gICAgfSxcblxuICAgIC8vIGFmdGVyIG9uZSBpbmRleCBoYXMgYmVlbiB1c2VkIGZvciBhIHNhZGRsZSwgd2hpY2ggZG8gd2VcbiAgICAvLyBzdWJzdGl0dXRlIHRvIGJlIHVzZWQgdXAgbGF0ZXI/XG4gICAgU0FERExFUkVNQUlOREVSOiB7MTogNCwgMjogOCwgNDogMSwgNzogMTMsIDg6IDIsIDExOiAxNCwgMTM6IDcsIDE0OiAxMX0sXG5cbiAgICAvLyBsZW5ndGggb2YgYSBjb250b3VyLCBhcyBhIG11bHRpcGxlIG9mIHRoZSBwbG90IGFyZWEgZGlhZ29uYWwsIHBlciBsYWJlbFxuICAgIExBQkVMRElTVEFOQ0U6IDIsXG5cbiAgICAvLyBudW1iZXIgb2YgY29udG91ciBsZXZlbHMgYWZ0ZXIgd2hpY2ggd2Ugc3RhcnQgaW5jcmVhc2luZyB0aGUgbnVtYmVyIG9mXG4gICAgLy8gbGFiZWxzIHdlIGRyYXcuIE1hbnkgY29udG91cnMgbWVhbnMgdGhleSB3aWxsIGdlbmVyYWxseSBiZSBjbG9zZVxuICAgIC8vIHRvZ2V0aGVyLCBzbyBpdCB3aWxsIGJlIGhhcmRlciB0byBmb2xsb3cgYSBsb25nIHdheSB0byBmaW5kIGEgbGFiZWxcbiAgICBMQUJFTElOQ1JFQVNFOiAxMCxcblxuICAgIC8vIG1pbmltdW0gbGVuZ3RoIG9mIGEgY29udG91ciBsaW5lLCBhcyBhIG11bHRpcGxlIG9mIHRoZSBsYWJlbCBsZW5ndGgsXG4gICAgLy8gYXQgd2hpY2ggd2UgZHJhdyAqYW55KiBsYWJlbHNcbiAgICBMQUJFTE1JTjogMyxcblxuICAgIC8vIG1heCBudW1iZXIgb2YgbGFiZWxzIHRvIGRyYXcgb24gYSBzaW5nbGUgY29udG91ciBwYXRoLCBubyBtYXR0ZXIgaG93IGxvbmdcbiAgICBMQUJFTE1BWDogMTAsXG5cbiAgICAvLyBjb25zdGFudHMgZm9yIHRoZSBsYWJlbCBwb3NpdGlvbiBjb3N0IGZ1bmN0aW9uXG4gICAgTEFCRUxPUFRJTUlaRVI6IHtcbiAgICAgICAgLy8gd2VpZ2h0IGdpdmVuIHRvIGVkZ2UgcHJveGltaXR5XG4gICAgICAgIEVER0VDT1NUOiAxLFxuICAgICAgICAvLyB3ZWlnaHQgZ2l2ZW4gdG8gdGhlIGFuZ2xlIG9mZiBob3Jpem9udGFsXG4gICAgICAgIEFOR0xFQ09TVDogMSxcbiAgICAgICAgLy8gd2VpZ2h0IGdpdmVuIHRvIGRpc3RhbmNlIGZyb20gYWxyZWFkeS1wbGFjZWQgbGFiZWxzXG4gICAgICAgIE5FSUdIQk9SQ09TVDogNSxcbiAgICAgICAgLy8gY29zdCBtdWx0aXBsaWVyIGZvciBsYWJlbHMgb24gdGhlIHNhbWUgbGV2ZWxcbiAgICAgICAgU0FNRUxFVkVMRkFDVE9SOiAxMCxcbiAgICAgICAgLy8gbWluaW11bSBkaXN0YW5jZSAoYXMgYSBtdWx0aXBsZSBvZiB0aGUgbGFiZWwgbGVuZ3RoKVxuICAgICAgICAvLyBmb3IgbGFiZWxzIG9uIHRoZSBzYW1lIGxldmVsXG4gICAgICAgIFNBTUVMRVZFTERJU1RBTkNFOiA1LFxuICAgICAgICAvLyBtYXhpbXVtIGNvc3QgYmVmb3JlIHdlIHdvbid0IGV2ZW4gcGxhY2UgdGhlIGxhYmVsXG4gICAgICAgIE1BWENPU1Q6IDEwMCxcbiAgICAgICAgLy8gbnVtYmVyIG9mIGV2ZW5seSBzcGFjZWQgcG9pbnRzIHRvIGxvb2sgYXQgaW4gdGhlIGZpcnN0XG4gICAgICAgIC8vIGl0ZXJhdGlvbiBvZiB0aGUgc2VhcmNoXG4gICAgICAgIElOSVRJQUxTRUFSQ0hQT0lOVFM6IDEwLFxuICAgICAgICAvLyBudW1iZXIgb2YgYmluYXJ5IHNlYXJjaCBpdGVyYXRpb25zIGFmdGVyIHRoZSBpbml0aWFsIHdpZGUgc2VhcmNoXG4gICAgICAgIElURVJBVElPTlM6IDVcbiAgICB9XG59O1xuXG59LHt9XSw5NDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIGhhbmRsZUxhYmVsRGVmYXVsdHMgPSBfZGVyZXFfKCcuL2xhYmVsX2RlZmF1bHRzJyk7XG5cbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBhZGRPcGFjaXR5ID0gQ29sb3IuYWRkT3BhY2l0eTtcbnZhciBvcGFjaXR5ID0gQ29sb3Iub3BhY2l0eTtcblxudmFyIGZpbHRlck9wcyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9maWx0ZXJfb3BzJyk7XG52YXIgQ09OU1RSQUlOVF9SRURVQ1RJT04gPSBmaWx0ZXJPcHMuQ09OU1RSQUlOVF9SRURVQ1RJT047XG52YXIgQ09NUEFSSVNPTl9PUFMyID0gZmlsdGVyT3BzLkNPTVBBUklTT05fT1BTMjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVDb25zdHJhaW50RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0LCBkZWZhdWx0Q29sb3IsIG9wdHMpIHtcbiAgICB2YXIgY29udG91cnMgPSB0cmFjZU91dC5jb250b3VycztcbiAgICB2YXIgc2hvd0xpbmVzLCBsaW5lQ29sb3IsIGZpbGxDb2xvcjtcblxuICAgIHZhciBvcGVyYXRpb24gPSBjb2VyY2UoJ2NvbnRvdXJzLm9wZXJhdGlvbicpO1xuICAgIGNvbnRvdXJzLl9vcGVyYXRpb24gPSBDT05TVFJBSU5UX1JFRFVDVElPTltvcGVyYXRpb25dO1xuXG4gICAgaGFuZGxlQ29uc3RyYWludFZhbHVlRGVmYXVsdHMoY29lcmNlLCBjb250b3Vycyk7XG5cbiAgICBpZihvcGVyYXRpb24gPT09ICc9Jykge1xuICAgICAgICBzaG93TGluZXMgPSBjb250b3Vycy5zaG93bGluZXMgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNob3dMaW5lcyA9IGNvZXJjZSgnY29udG91cnMuc2hvd2xpbmVzJyk7XG4gICAgICAgIGZpbGxDb2xvciA9IGNvZXJjZSgnZmlsbGNvbG9yJywgYWRkT3BhY2l0eShcbiAgICAgICAgICAgICh0cmFjZUluLmxpbmUgfHwge30pLmNvbG9yIHx8IGRlZmF1bHRDb2xvciwgMC41XG4gICAgICAgICkpO1xuICAgIH1cblxuICAgIGlmKHNob3dMaW5lcykge1xuICAgICAgICB2YXIgbGluZURmbHRDb2xvciA9IGZpbGxDb2xvciAmJiBvcGFjaXR5KGZpbGxDb2xvcikgP1xuICAgICAgICAgICAgYWRkT3BhY2l0eSh0cmFjZU91dC5maWxsY29sb3IsIDEpIDpcbiAgICAgICAgICAgIGRlZmF1bHRDb2xvcjtcbiAgICAgICAgbGluZUNvbG9yID0gY29lcmNlKCdsaW5lLmNvbG9yJywgbGluZURmbHRDb2xvcik7XG4gICAgICAgIGNvZXJjZSgnbGluZS53aWR0aCcsIDIpO1xuICAgICAgICBjb2VyY2UoJ2xpbmUuZGFzaCcpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnbGluZS5zbW9vdGhpbmcnKTtcblxuICAgIGhhbmRsZUxhYmVsRGVmYXVsdHMoY29lcmNlLCBsYXlvdXQsIGxpbmVDb2xvciwgb3B0cyk7XG59O1xuXG5mdW5jdGlvbiBoYW5kbGVDb25zdHJhaW50VmFsdWVEZWZhdWx0cyhjb2VyY2UsIGNvbnRvdXJzKSB7XG4gICAgdmFyIHp2YWx1ZTtcblxuICAgIGlmKENPTVBBUklTT05fT1BTMi5pbmRleE9mKGNvbnRvdXJzLm9wZXJhdGlvbikgPT09IC0xKSB7XG4gICAgICAgIC8vIFJlcXVpcmVzIGFuIGFycmF5IG9mIHR3byBudW1iZXJzOlxuICAgICAgICBjb2VyY2UoJ2NvbnRvdXJzLnZhbHVlJywgWzAsIDFdKTtcblxuICAgICAgICBpZighQXJyYXkuaXNBcnJheShjb250b3Vycy52YWx1ZSkpIHtcbiAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhjb250b3Vycy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICB6dmFsdWUgPSBwYXJzZUZsb2F0KGNvbnRvdXJzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICBjb250b3Vycy52YWx1ZSA9IFt6dmFsdWUsIHp2YWx1ZSArIDFdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYoY29udG91cnMudmFsdWUubGVuZ3RoID4gMikge1xuICAgICAgICAgICAgY29udG91cnMudmFsdWUgPSBjb250b3Vycy52YWx1ZS5zbGljZSgyKTtcbiAgICAgICAgfSBlbHNlIGlmKGNvbnRvdXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgY29udG91cnMudmFsdWUgPSBbMCwgMV07XG4gICAgICAgIH0gZWxzZSBpZihjb250b3Vycy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgICB6dmFsdWUgPSBwYXJzZUZsb2F0KGNvbnRvdXJzLnZhbHVlWzBdKTtcbiAgICAgICAgICAgIGNvbnRvdXJzLnZhbHVlID0gW3p2YWx1ZSwgenZhbHVlICsgMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb250b3Vycy52YWx1ZSA9IFtcbiAgICAgICAgICAgICAgICBwYXJzZUZsb2F0KGNvbnRvdXJzLnZhbHVlWzBdKSxcbiAgICAgICAgICAgICAgICBwYXJzZUZsb2F0KGNvbnRvdXJzLnZhbHVlWzFdKVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFJlcXVpcmVzIGEgc2luZ2xlIHNjYWxhcjpcbiAgICAgICAgY29lcmNlKCdjb250b3Vycy52YWx1ZScsIDApO1xuXG4gICAgICAgIGlmKCFpc051bWVyaWMoY29udG91cnMudmFsdWUpKSB7XG4gICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KGNvbnRvdXJzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgIGNvbnRvdXJzLnZhbHVlID0gcGFyc2VGbG9hdChjb250b3Vycy52YWx1ZVswXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnRvdXJzLnZhbHVlID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29uc3RhbnRzL2ZpbHRlcl9vcHNcIjo2OTEsXCIuL2xhYmVsX2RlZmF1bHRzXCI6OTU3LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSw5NDg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZmlsdGVyT3BzID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2ZpbHRlcl9vcHMnKTtcbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xuXG4vLyBUaGlzIHN5bnRheCBjb25mb3JtcyB0byB0aGUgZXhpc3RpbmcgZmlsdGVyIHRyYW5zZm9ybSBzeW50YXgsIGJ1dCB3ZSBkb24ndCBjYXJlXG4vLyBhYm91dCBvcGVuIHZzLiBjbG9zZWQgaW50ZXJ2YWxzIGZvciBzaW1wbHkgZHJhd2luZyBjb250b3VycyBjb25zdHJhaW50czpcbm1vZHVsZS5leHBvcnRzID0ge1xuICAgICdbXSc6IG1ha2VSYW5nZVNldHRpbmdzKCdbXScpLFxuICAgICddWyc6IG1ha2VSYW5nZVNldHRpbmdzKCddWycpLFxuICAgICc+JzogbWFrZUluZXF1YWxpdHlTZXR0aW5ncygnPicpLFxuICAgICc8JzogbWFrZUluZXF1YWxpdHlTZXR0aW5ncygnPCcpLFxuICAgICc9JzogbWFrZUluZXF1YWxpdHlTZXR0aW5ncygnPScpXG59O1xuXG4vLyBUaGlzIGRvZXMgbm90IGluIGFueSB3YXkgc2hhcGUgb3IgZm9ybSBzdXBwb3J0IGNhbGVuZGFycy4gSXQncyBhZGFwdGVkIGZyb21cbi8vIHRyYW5zZm9ybXMvZmlsdGVyLmpzLlxuZnVuY3Rpb24gY29lcmNlVmFsdWUob3BlcmF0aW9uLCB2YWx1ZSkge1xuICAgIHZhciBoYXNBcnJheVZhbHVlID0gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG5cbiAgICB2YXIgY29lcmNlZFZhbHVlO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBpc051bWVyaWModmFsdWUpID8gKCt2YWx1ZSkgOiBudWxsO1xuICAgIH1cblxuICAgIGlmKGZpbHRlck9wcy5DT01QQVJJU09OX09QUzIuaW5kZXhPZihvcGVyYXRpb24pICE9PSAtMSkge1xuICAgICAgICBjb2VyY2VkVmFsdWUgPSBoYXNBcnJheVZhbHVlID8gY29lcmNlKHZhbHVlWzBdKSA6IGNvZXJjZSh2YWx1ZSk7XG4gICAgfSBlbHNlIGlmKGZpbHRlck9wcy5JTlRFUlZBTF9PUFMuaW5kZXhPZihvcGVyYXRpb24pICE9PSAtMSkge1xuICAgICAgICBjb2VyY2VkVmFsdWUgPSBoYXNBcnJheVZhbHVlID9cbiAgICAgICAgICAgIFtjb2VyY2UodmFsdWVbMF0pLCBjb2VyY2UodmFsdWVbMV0pXSA6XG4gICAgICAgICAgICBbY29lcmNlKHZhbHVlKSwgY29lcmNlKHZhbHVlKV07XG4gICAgfSBlbHNlIGlmKGZpbHRlck9wcy5TRVRfT1BTLmluZGV4T2Yob3BlcmF0aW9uKSAhPT0gLTEpIHtcbiAgICAgICAgY29lcmNlZFZhbHVlID0gaGFzQXJyYXlWYWx1ZSA/IHZhbHVlLm1hcChjb2VyY2UpIDogW2NvZXJjZSh2YWx1ZSldO1xuICAgIH1cblxuICAgIHJldHVybiBjb2VyY2VkVmFsdWU7XG59XG5cbi8vIFJldHVybnMgYSBwYXJhYm9sYSBzY2FsZWQgc28gdGhhdCB0aGUgbWluL21heCBpcyBlaXRoZXIgKy8tIDEgYW5kIHplcm8gYXQgdGhlIHR3byB2YWx1ZXNcbi8vIHByb3ZpZGVkLiBUaGUgZGF0YSBpcyBtYXBwZWQgYnkgdGhpcyBmdW5jdGlvbiB3aGVuIGNvbnN0cnVjdGluZyBpbnRlcnZhbHMgc28gdGhhdCBpdCdzXG4vLyB2ZXJ5IGVhc3kgdG8gY29uc3RydWN0IGNvbnRvdXJzIGFzIG5vcm1hbC5cbmZ1bmN0aW9uIG1ha2VSYW5nZVNldHRpbmdzKG9wZXJhdGlvbikge1xuICAgIHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICB2YWx1ZSA9IGNvZXJjZVZhbHVlKG9wZXJhdGlvbiwgdmFsdWUpO1xuXG4gICAgICAgIC8vIEVuc3VyZSBwcm9wZXIgb3JkZXJpbmc6XG4gICAgICAgIHZhciBtaW4gPSBNYXRoLm1pbih2YWx1ZVswXSwgdmFsdWVbMV0pO1xuICAgICAgICB2YXIgbWF4ID0gTWF0aC5tYXgodmFsdWVbMF0sIHZhbHVlWzFdKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RhcnQ6IG1pbixcbiAgICAgICAgICAgIGVuZDogbWF4LFxuICAgICAgICAgICAgc2l6ZTogbWF4IC0gbWluXG4gICAgICAgIH07XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gbWFrZUluZXF1YWxpdHlTZXR0aW5ncyhvcGVyYXRpb24pIHtcbiAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgdmFsdWUgPSBjb2VyY2VWYWx1ZShvcGVyYXRpb24sIHZhbHVlKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RhcnQ6IHZhbHVlLFxuICAgICAgICAgICAgZW5kOiBJbmZpbml0eSxcbiAgICAgICAgICAgIHNpemU6IEluZmluaXR5XG4gICAgICAgIH07XG4gICAgfTtcbn1cblxufSx7XCIuLi8uLi9jb25zdGFudHMvZmlsdGVyX29wc1wiOjY5MSxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sOTQ5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVDb250b3VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgY29lcmNlMikge1xuICAgIHZhciBjb250b3VyU3RhcnQgPSBjb2VyY2UyKCdjb250b3Vycy5zdGFydCcpO1xuICAgIHZhciBjb250b3VyRW5kID0gY29lcmNlMignY29udG91cnMuZW5kJyk7XG4gICAgdmFyIG1pc3NpbmdFbmQgPSAoY29udG91clN0YXJ0ID09PSBmYWxzZSkgfHwgKGNvbnRvdXJFbmQgPT09IGZhbHNlKTtcblxuICAgIC8vIG5vcm1hbGx5IHdlIG9ubHkgbmVlZCBzaXplIGlmIGF1dG9jb250b3VyIGlzIG9mZi4gQnV0IGNvbnRvdXIuY2FsY1xuICAgIC8vIHB1c2hlcyBpdHMgY2FsY3VsYXRlZCBjb250b3VyIHNpemUgYmFjayB0byB0aGUgaW5wdXQgdHJhY2UsIHNvIGZvclxuICAgIC8vIHRoaW5ncyBsaWtlIHJlc3R5bGUgdGhhdCBjYW4gY2FsbCBzdXBwbHlEZWZhdWx0cyB3aXRob3V0IGNhbGNcbiAgICAvLyBhZnRlciB0aGUgaW5pdGlhbCBkcmF3LCB3ZSBjYW4ganVzdCByZXVzZSB0aGUgcHJldmlvdXMgY2FsY3VsYXRpb25cbiAgICB2YXIgY29udG91clNpemUgPSBjb2VyY2UoJ2NvbnRvdXJzLnNpemUnKTtcbiAgICB2YXIgYXV0b0NvbnRvdXI7XG5cbiAgICBpZihtaXNzaW5nRW5kKSBhdXRvQ29udG91ciA9IHRyYWNlT3V0LmF1dG9jb250b3VyID0gdHJ1ZTtcbiAgICBlbHNlIGF1dG9Db250b3VyID0gY29lcmNlKCdhdXRvY29udG91cicsIGZhbHNlKTtcblxuICAgIGlmKGF1dG9Db250b3VyIHx8ICFjb250b3VyU2l6ZSkgY29lcmNlKCduY29udG91cnMnKTtcbn07XG5cbn0se31dLDk1MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxuLy8gVGhlIGNvbnRvdXIgZXh0cmFjdGlvbiBpcyBncmVhdCwgZXhjZXB0IGl0IHRvdGFsbHkgZmFpbHMgZm9yIGNvbnN0cmFpbnRzIGJlY2F1c2Ugd2Vcbi8vIG5lZWQgd2VpcmQgcmFuZ2UgbG9vcHMgYW5kIGZsaXBwZWQgY29udG91cnMgaW5zdGVhZCBvZiB0aGUgdXN1YWwgZm9ybWF0LiBUaGlzIGZ1bmN0aW9uXG4vLyBkb2VzIHNvbWUgd2VpcmQgbWFuaXB1bGF0aW9uIG9mIHRoZSBleHRyYWN0ZWQgcGF0aGluZm8gZGF0YSBzdWNoIHRoYXQgaXQgbWFnaWNhbGx5XG4vLyBkcmF3cyBjb250b3VycyBjb3JyZWN0bHkgKmFzKiBjb25zdHJhaW50cy5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ocGF0aGluZm8sIG9wZXJhdGlvbikge1xuICAgIHZhciBpLCBwaTAsIHBpMTtcblxuICAgIHZhciBvcDAgPSBmdW5jdGlvbihhcnIpIHsgcmV0dXJuIGFyci5yZXZlcnNlKCk7IH07XG4gICAgdmFyIG9wMSA9IGZ1bmN0aW9uKGFycikgeyByZXR1cm4gYXJyOyB9O1xuXG4gICAgc3dpdGNoKG9wZXJhdGlvbikge1xuICAgICAgICBjYXNlICc9JzpcbiAgICAgICAgY2FzZSAnPCc6XG4gICAgICAgICAgICByZXR1cm4gcGF0aGluZm87XG4gICAgICAgIGNhc2UgJz4nOlxuICAgICAgICAgICAgaWYocGF0aGluZm8ubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgTGliLndhcm4oJ0NvbnRvdXIgZGF0YSBpbnZhbGlkIGZvciB0aGUgc3BlY2lmaWVkIGluZXF1YWxpdHkgb3BlcmF0aW9uLicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJbiB0aGlzIGNhc2UgdGhlcmUgc2hvdWxkIGJlIGV4YWN0bHkgdHdvIGNvbnRvdXIgbGV2ZWxzIGluIHBhdGhpbmZvLiBXZVxuICAgICAgICAgICAgLy8gc2ltcGx5IGNvbmNhdGVuYXRlIHRoZSBpbmZvIGludG8gb25lIHBhdGhpbmZvIGFuZCBmbGlwIGFsbCBvZiB0aGUgZGF0YVxuICAgICAgICAgICAgLy8gaW4gb25lLiBUaGlzIHdpbGwgZHJhdyB0aGUgY29udG91ciBhcyBjbG9zZWQuXG4gICAgICAgICAgICBwaTAgPSBwYXRoaW5mb1swXTtcblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGkwLmVkZ2VwYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHBpMC5lZGdlcGF0aHNbaV0gPSBvcDAocGkwLmVkZ2VwYXRoc1tpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHBpMC5wYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHBpMC5wYXRoc1tpXSA9IG9wMChwaTAucGF0aHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHBhdGhpbmZvO1xuICAgICAgICBjYXNlICddWyc6XG4gICAgICAgICAgICB2YXIgdG1wID0gb3AwO1xuICAgICAgICAgICAgb3AwID0gb3AxO1xuICAgICAgICAgICAgb3AxID0gdG1wO1xuICAgICAgICAgICAgLy8gSXQncyBhIG5pY2UgcnVsZSwgZXhjZXB0IHRoaXMgZGVmaW5pdGVseSAqaXMqIHdoYXQncyBpbnRlbmRlZCBoZXJlLlxuICAgICAgICAgICAgLyogZXNsaW50LWRpc2FibGU6IG5vLWZhbGx0aHJvdWdoICovXG4gICAgICAgIGNhc2UgJ1tdJzpcbiAgICAgICAgICAgIC8qIGVzbGludC1lbmFibGU6IG5vLWZhbGx0aHJvdWdoICovXG4gICAgICAgICAgICBpZihwYXRoaW5mby5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgICAgICBMaWIud2FybignQ29udG91ciBkYXRhIGludmFsaWQgZm9yIHRoZSBzcGVjaWZpZWQgaW5lcXVhbGl0eSByYW5nZSBvcGVyYXRpb24uJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSB0aGVyZSBzaG91bGQgYmUgZXhhY3RseSB0d28gY29udG91ciBsZXZlbHMgaW4gcGF0aGluZm8uIFdlXG4gICAgICAgICAgICAvLyBzaW1wbHkgY29uY2F0ZW5hdGUgdGhlIGluZm8gaW50byBvbmUgcGF0aGluZm8gYW5kIGZsaXAgYWxsIG9mIHRoZSBkYXRhXG4gICAgICAgICAgICAvLyBpbiBvbmUuIFRoaXMgd2lsbCBkcmF3IHRoZSBjb250b3VyIGFzIGNsb3NlZC5cbiAgICAgICAgICAgIHBpMCA9IGNvcHlQYXRoaW5mbyhwYXRoaW5mb1swXSk7XG4gICAgICAgICAgICBwaTEgPSBjb3B5UGF0aGluZm8ocGF0aGluZm9bMV0pO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBwaTAuZWRnZXBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcGkwLmVkZ2VwYXRoc1tpXSA9IG9wMChwaTAuZWRnZXBhdGhzW2ldKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGkwLnBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcGkwLnBhdGhzW2ldID0gb3AwKHBpMC5wYXRoc1tpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHdoaWxlKHBpMS5lZGdlcGF0aHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcGkwLmVkZ2VwYXRocy5wdXNoKG9wMShwaTEuZWRnZXBhdGhzLnNoaWZ0KCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlKHBpMS5wYXRocy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBwaTAucGF0aHMucHVzaChvcDEocGkxLnBhdGhzLnNoaWZ0KCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBbcGkwXTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjb3B5UGF0aGluZm8ocGkpIHtcbiAgICByZXR1cm4gTGliLmV4dGVuZEZsYXQoe30sIHBpLCB7XG4gICAgICAgIGVkZ2VwYXRoczogTGliLmV4dGVuZERlZXAoW10sIHBpLmVkZ2VwYXRocyksXG4gICAgICAgIHBhdGhzOiBMaWIuZXh0ZW5kRGVlcChbXSwgcGkucGF0aHMpXG4gICAgfSk7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sOTUxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgaGFuZGxlWFlaRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9oZWF0bWFwL3h5el9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNvbnN0cmFpbnREZWZhdWx0cyA9IF9kZXJlcV8oJy4vY29uc3RyYWludF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNvbnRvdXJzRGVmYXVsdHMgPSBfZGVyZXFfKCcuL2NvbnRvdXJzX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlU3R5bGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4vc3R5bGVfZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29lcmNlMihhdHRyKSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlMih0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0cik7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVhZWkRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgdmFyIGlzQ29uc3RyYWludCA9IChjb2VyY2UoJ2NvbnRvdXJzLnR5cGUnKSA9PT0gJ2NvbnN0cmFpbnQnKTtcbiAgICBjb2VyY2UoJ2Nvbm5lY3RnYXBzJywgTGliLmlzQXJyYXkxRCh0cmFjZU91dC56KSk7XG5cbiAgICBpZihpc0NvbnN0cmFpbnQpIHtcbiAgICAgICAgaGFuZGxlQ29uc3RyYWludERlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCwgZGVmYXVsdENvbG9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBoYW5kbGVDb250b3Vyc0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGNvZXJjZTIpO1xuICAgICAgICBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi9oZWF0bWFwL3h5el9kZWZhdWx0c1wiOjEwMTUsXCIuL2F0dHJpYnV0ZXNcIjo5NDIsXCIuL2NvbnN0cmFpbnRfZGVmYXVsdHNcIjo5NDcsXCIuL2NvbnRvdXJzX2RlZmF1bHRzXCI6OTQ5LFwiLi9zdHlsZV9kZWZhdWx0c1wiOjk2M31dLDk1MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBjb25zdHJhaW50TWFwcGluZyA9IF9kZXJlcV8oJy4vY29uc3RyYWludF9tYXBwaW5nJyk7XG52YXIgZW5kUGx1cyA9IF9kZXJlcV8oJy4vZW5kX3BsdXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBlbXB0eVBhdGhpbmZvKGNvbnRvdXJzLCBwbG90aW5mbywgY2QwKSB7XG4gICAgdmFyIGNvbnRvdXJzRmluYWwgPSAoY29udG91cnMudHlwZSA9PT0gJ2NvbnN0cmFpbnQnKSA/XG4gICAgICAgIGNvbnN0cmFpbnRNYXBwaW5nW2NvbnRvdXJzLl9vcGVyYXRpb25dKGNvbnRvdXJzLnZhbHVlKSA6XG4gICAgICAgIGNvbnRvdXJzO1xuXG4gICAgdmFyIGNzID0gY29udG91cnNGaW5hbC5zaXplO1xuICAgIHZhciBwYXRoaW5mbyA9IFtdO1xuICAgIHZhciBlbmQgPSBlbmRQbHVzKGNvbnRvdXJzRmluYWwpO1xuXG4gICAgdmFyIGNhcnBldCA9IGNkMC50cmFjZS5fY2FycGV0VHJhY2U7XG5cbiAgICB2YXIgYmFzZVBhdGhpbmZvID0gY2FycGV0ID8ge1xuICAgICAgICAvLyBzdG9yZSBheGVzIHNvIHdlIGNhbiBjb252ZXJ0IHRvIHB4XG4gICAgICAgIHhheGlzOiBjYXJwZXQuYWF4aXMsXG4gICAgICAgIHlheGlzOiBjYXJwZXQuYmF4aXMsXG4gICAgICAgIC8vIGZ1bGwgZGF0YSBhcnJheXMgdG8gdXNlIGZvciBpbnRlcnBvbGF0aW9uXG4gICAgICAgIHg6IGNkMC5hLFxuICAgICAgICB5OiBjZDAuYlxuICAgIH0gOiB7XG4gICAgICAgIHhheGlzOiBwbG90aW5mby54YXhpcyxcbiAgICAgICAgeWF4aXM6IHBsb3RpbmZvLnlheGlzLFxuICAgICAgICB4OiBjZDAueCxcbiAgICAgICAgeTogY2QwLnlcbiAgICB9O1xuXG4gICAgZm9yKHZhciBjaSA9IGNvbnRvdXJzRmluYWwuc3RhcnQ7IGNpIDwgZW5kOyBjaSArPSBjcykge1xuICAgICAgICBwYXRoaW5mby5wdXNoKExpYi5leHRlbmRGbGF0KHtcbiAgICAgICAgICAgIGxldmVsOiBjaSxcbiAgICAgICAgICAgIC8vIGFsbCB0aGUgY2VsbHMgd2l0aCBub250cml2aWFsIG1hcmNoaW5nIGluZGV4XG4gICAgICAgICAgICBjcm9zc2luZ3M6IHt9LFxuICAgICAgICAgICAgLy8gc3RhcnRpbmcgcG9pbnRzIG9uIHRoZSBlZGdlcyBvZiB0aGUgbGF0dGljZSBmb3IgZWFjaCBjb250b3VyXG4gICAgICAgICAgICBzdGFydHM6IFtdLFxuICAgICAgICAgICAgLy8gYWxsIHVuY2xvc2VkIHBhdGhzIChtYXkgaGF2ZSBsZXNzIGl0ZW1zIHRoYW4gc3RhcnRzLFxuICAgICAgICAgICAgLy8gaWYgYSBwYXRoIGlzIGNsb3NlZCBieSByb3VuZGluZylcbiAgICAgICAgICAgIGVkZ2VwYXRoczogW10sXG4gICAgICAgICAgICAvLyBhbGwgY2xvc2VkIHBhdGhzXG4gICAgICAgICAgICBwYXRoczogW10sXG4gICAgICAgICAgICB6OiBjZDAueixcbiAgICAgICAgICAgIHNtb290aGluZzogY2QwLnRyYWNlLmxpbmUuc21vb3RoaW5nXG4gICAgICAgIH0sIGJhc2VQYXRoaW5mbykpO1xuXG4gICAgICAgIGlmKHBhdGhpbmZvLmxlbmd0aCA+IDEwMDApIHtcbiAgICAgICAgICAgIExpYi53YXJuKCdUb28gbWFueSBjb250b3VycywgY2xpcHBpbmcgYXQgMTAwMCcsIGNvbnRvdXJzKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXRoaW5mbztcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi9jb25zdHJhaW50X21hcHBpbmdcIjo5NDgsXCIuL2VuZF9wbHVzXCI6OTUzfV0sOTUzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKlxuICogdGlueSBoZWxwZXIgdG8gbW92ZSB0aGUgZW5kIG9mIHRoZSBjb250b3VycyBhIGxpdHRsZSB0byBwcmV2ZW50XG4gKiBsb3NpbmcgdGhlIGxhc3QgY29udG91ciB0byByb3VuZGluZyBlcnJvcnNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBlbmRQbHVzKGNvbnRvdXJzKSB7XG4gICAgcmV0dXJuIGNvbnRvdXJzLmVuZCArIGNvbnRvdXJzLnNpemUgLyAxZTY7XG59O1xuXG59LHt9XSw5NTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBmaW5kQWxsUGF0aHMocGF0aGluZm8sIHh0b2wsIHl0b2wpIHtcbiAgICB2YXIgY250LFxuICAgICAgICBzdGFydExvYyxcbiAgICAgICAgaSxcbiAgICAgICAgcGksXG4gICAgICAgIGo7XG5cbiAgICAvLyBEZWZhdWx0IGp1c3QgcGFzc2VzIHRoZXNlIHZhbHVlcyB0aHJvdWdoIGFzIHRoZXkgd2VyZSBiZWZvcmU6XG4gICAgeHRvbCA9IHh0b2wgfHwgMC4wMTtcbiAgICB5dG9sID0geXRvbCB8fCAwLjAxO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgcGF0aGluZm8ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcGkgPSBwYXRoaW5mb1tpXTtcblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBwaS5zdGFydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHN0YXJ0TG9jID0gcGkuc3RhcnRzW2pdO1xuICAgICAgICAgICAgbWFrZVBhdGgocGksIHN0YXJ0TG9jLCAnZWRnZScsIHh0b2wsIHl0b2wpO1xuICAgICAgICB9XG5cbiAgICAgICAgY250ID0gMDtcbiAgICAgICAgd2hpbGUoT2JqZWN0LmtleXMocGkuY3Jvc3NpbmdzKS5sZW5ndGggJiYgY250IDwgMTAwMDApIHtcbiAgICAgICAgICAgIGNudCsrO1xuICAgICAgICAgICAgc3RhcnRMb2MgPSBPYmplY3Qua2V5cyhwaS5jcm9zc2luZ3MpWzBdLnNwbGl0KCcsJykubWFwKE51bWJlcik7XG4gICAgICAgICAgICBtYWtlUGF0aChwaSwgc3RhcnRMb2MsIHVuZGVmaW5lZCwgeHRvbCwgeXRvbCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoY250ID09PSAxMDAwMCkgTGliLmxvZygnSW5maW5pdGUgbG9vcCBpbiBjb250b3VyPycpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGVxdWFsUHRzKHB0MSwgcHQyLCB4dG9sLCB5dG9sKSB7XG4gICAgcmV0dXJuIE1hdGguYWJzKHB0MVswXSAtIHB0MlswXSkgPCB4dG9sICYmXG4gICAgICAgICAgIE1hdGguYWJzKHB0MVsxXSAtIHB0MlsxXSkgPCB5dG9sO1xufVxuXG4vLyBkaXN0YW5jZSBpbiBpbmRleCB1bml0cyAtIHVzZXMgdGhlIDNyZCBhbmQgNHRoIGl0ZW1zIGluIHBvaW50c1xuZnVuY3Rpb24gcHREaXN0KHB0MSwgcHQyKSB7XG4gICAgdmFyIGR4ID0gcHQxWzJdIC0gcHQyWzJdO1xuICAgIHZhciBkeSA9IHB0MVszXSAtIHB0MlszXTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbn1cblxuZnVuY3Rpb24gbWFrZVBhdGgocGksIGxvYywgZWRnZWZsYWcsIHh0b2wsIHl0b2wpIHtcbiAgICB2YXIgc3RhcnRMb2NTdHIgPSBsb2Muam9pbignLCcpO1xuICAgIHZhciBsb2NTdHIgPSBzdGFydExvY1N0cjtcbiAgICB2YXIgbWkgPSBwaS5jcm9zc2luZ3NbbG9jU3RyXTtcbiAgICB2YXIgbWFyY2hTdGVwID0gc3RhcnRTdGVwKG1pLCBlZGdlZmxhZywgbG9jKTtcbiAgICAvLyBzdGFydCBieSBnb2luZyBiYWNrd2FyZCBhIGhhbGYgc3RlcCBhbmQgZmluZGluZyB0aGUgY3Jvc3NpbmcgcG9pbnRcbiAgICB2YXIgcHRzID0gW2dldEludGVycFB4KHBpLCBsb2MsIFstbWFyY2hTdGVwWzBdLCAtbWFyY2hTdGVwWzFdXSldO1xuICAgIHZhciBzdGFydFN0ZXBTdHIgPSBtYXJjaFN0ZXAuam9pbignLCcpO1xuICAgIHZhciBtID0gcGkuei5sZW5ndGg7XG4gICAgdmFyIG4gPSBwaS56WzBdLmxlbmd0aDtcbiAgICB2YXIgY250O1xuXG4gICAgLy8gbm93IGZvbGxvdyB0aGUgcGF0aFxuICAgIGZvcihjbnQgPSAwOyBjbnQgPCAxMDAwMDsgY250KyspIHsgLy8ganVzdCB0byBhdm9pZCBpbmZpbml0ZSBsb29wc1xuICAgICAgICBpZihtaSA+IDIwKSB7XG4gICAgICAgICAgICBtaSA9IGNvbnN0YW50cy5DSE9PU0VTQURETEVbbWldWyhtYXJjaFN0ZXBbMF0gfHwgbWFyY2hTdGVwWzFdKSA8IDAgPyAwIDogMV07XG4gICAgICAgICAgICBwaS5jcm9zc2luZ3NbbG9jU3RyXSA9IGNvbnN0YW50cy5TQURETEVSRU1BSU5ERVJbbWldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVsZXRlIHBpLmNyb3NzaW5nc1tsb2NTdHJdO1xuICAgICAgICB9XG5cbiAgICAgICAgbWFyY2hTdGVwID0gY29uc3RhbnRzLk5FV0RFTFRBW21pXTtcbiAgICAgICAgaWYoIW1hcmNoU3RlcCkge1xuICAgICAgICAgICAgTGliLmxvZygnRm91bmQgYmFkIG1hcmNoaW5nIGluZGV4OicsIG1pLCBsb2MsIHBpLmxldmVsKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluZCB0aGUgY3Jvc3NpbmcgYSBoYWxmIHN0ZXAgZm9yd2FyZCwgYW5kIHRoZW4gdGFrZSB0aGUgZnVsbCBzdGVwXG4gICAgICAgIHB0cy5wdXNoKGdldEludGVycFB4KHBpLCBsb2MsIG1hcmNoU3RlcCkpO1xuICAgICAgICBsb2NbMF0gKz0gbWFyY2hTdGVwWzBdO1xuICAgICAgICBsb2NbMV0gKz0gbWFyY2hTdGVwWzFdO1xuXG4gICAgICAgIC8vIGRvbid0IGluY2x1ZGUgdGhlIHNhbWUgcG9pbnQgbXVsdGlwbGUgdGltZXNcbiAgICAgICAgaWYoZXF1YWxQdHMocHRzW3B0cy5sZW5ndGggLSAxXSwgcHRzW3B0cy5sZW5ndGggLSAyXSwgeHRvbCwgeXRvbCkpIHB0cy5wb3AoKTtcbiAgICAgICAgbG9jU3RyID0gbG9jLmpvaW4oJywnKTtcblxuICAgICAgICB2YXIgYXRFZGdlID0gKG1hcmNoU3RlcFswXSAmJiAobG9jWzBdIDwgMCB8fCBsb2NbMF0gPiBuIC0gMikpIHx8XG4gICAgICAgICAgICAgICAgKG1hcmNoU3RlcFsxXSAmJiAobG9jWzFdIDwgMCB8fCBsb2NbMV0gPiBtIC0gMikpO1xuICAgICAgICB2YXIgY2xvc2VkTG9vcCA9IChsb2NTdHIgPT09IHN0YXJ0TG9jU3RyKSAmJiAobWFyY2hTdGVwLmpvaW4oJywnKSA9PT0gc3RhcnRTdGVwU3RyKTtcblxuICAgICAgICAvLyBoYXZlIHdlIGNvbXBsZXRlZCBhIGxvb3AsIG9yIHJlYWNoZWQgYW4gZWRnZT9cbiAgICAgICAgaWYoKGNsb3NlZExvb3ApIHx8IChlZGdlZmxhZyAmJiBhdEVkZ2UpKSBicmVhaztcblxuICAgICAgICBtaSA9IHBpLmNyb3NzaW5nc1tsb2NTdHJdO1xuICAgIH1cblxuICAgIGlmKGNudCA9PT0gMTAwMDApIHtcbiAgICAgICAgTGliLmxvZygnSW5maW5pdGUgbG9vcCBpbiBjb250b3VyPycpO1xuICAgIH1cbiAgICB2YXIgY2xvc2VkcGF0aCA9IGVxdWFsUHRzKHB0c1swXSwgcHRzW3B0cy5sZW5ndGggLSAxXSwgeHRvbCwgeXRvbCk7XG4gICAgdmFyIHRvdGFsZGlzdCA9IDA7XG4gICAgdmFyIGRpc3RUaHJlc2hvbGRGYWN0b3IgPSAwLjIgKiBwaS5zbW9vdGhpbmc7XG4gICAgdmFyIGFsbGRpc3RzID0gW107XG4gICAgdmFyIGNyb3BzdGFydCA9IDA7XG4gICAgdmFyIGRpc3Rncm91cCwgY250MiwgY250MywgbmV3cHQsIHB0Y250LCBwdGF2ZywgdGhpc2Rpc3QsXG4gICAgICAgIGksIGosIGVkZ2VwYXRoaSwgZWRnZXBhdGhqO1xuXG4gICAgLypcbiAgICAgKiBDaGVjayBmb3IgcG9pbnRzIHRoYXQgYXJlIHRvbyBjbG9zZSB0b2dldGhlciAoPDEvNSB0aGUgYXZlcmFnZSBkaXN0XG4gICAgICogKmluIGdyaWQgaW5kZXggdW5pdHMqIChpbXBvcnRhbnQgZm9yIGxvZyBheGVzIGFuZCBub251bmlmb3JtIGdyaWRzKSxcbiAgICAgKiBsZXNzIGlmIGxlc3Mgc21vb3RoZWQpIGFuZCBqdXN0IHRha2UgdGhlIGNlbnRlciAob3IgYXZnIG9mIGNlbnRlciAyKS5cbiAgICAgKiBUaGlzIGN1dHMgZG93biBvbiBmdW5ueSBiZWhhdmlvciB3aGVuIGEgcG9pbnQgaXMgdmVyeSBjbG9zZSB0byBhXG4gICAgICogY29udG91ciBsZXZlbC5cbiAgICAgKi9cbiAgICBmb3IoY250ID0gMTsgY250IDwgcHRzLmxlbmd0aDsgY250KyspIHtcbiAgICAgICAgdGhpc2Rpc3QgPSBwdERpc3QocHRzW2NudF0sIHB0c1tjbnQgLSAxXSk7XG4gICAgICAgIHRvdGFsZGlzdCArPSB0aGlzZGlzdDtcbiAgICAgICAgYWxsZGlzdHMucHVzaCh0aGlzZGlzdCk7XG4gICAgfVxuXG4gICAgdmFyIGRpc3RUaHJlc2hvbGQgPSB0b3RhbGRpc3QgLyBhbGxkaXN0cy5sZW5ndGggKiBkaXN0VGhyZXNob2xkRmFjdG9yO1xuXG4gICAgZnVuY3Rpb24gZ2V0cHQoaSkgeyByZXR1cm4gcHRzW2kgJSBwdHMubGVuZ3RoXTsgfVxuXG4gICAgZm9yKGNudCA9IHB0cy5sZW5ndGggLSAyOyBjbnQgPj0gY3JvcHN0YXJ0OyBjbnQtLSkge1xuICAgICAgICBkaXN0Z3JvdXAgPSBhbGxkaXN0c1tjbnRdO1xuICAgICAgICBpZihkaXN0Z3JvdXAgPCBkaXN0VGhyZXNob2xkKSB7XG4gICAgICAgICAgICBjbnQzID0gMDtcbiAgICAgICAgICAgIGZvcihjbnQyID0gY250IC0gMTsgY250MiA+PSBjcm9wc3RhcnQ7IGNudDItLSkge1xuICAgICAgICAgICAgICAgIGlmKGRpc3Rncm91cCArIGFsbGRpc3RzW2NudDJdIDwgZGlzdFRocmVzaG9sZCkge1xuICAgICAgICAgICAgICAgICAgICBkaXN0Z3JvdXAgKz0gYWxsZGlzdHNbY250Ml07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBjbG9zZWQgcGF0aCB3aXRoIGNsb3NlIHBvaW50cyB3cmFwcGluZyBhcm91bmQgdGhlIGJvdW5kYXJ5P1xuICAgICAgICAgICAgaWYoY2xvc2VkcGF0aCAmJiBjbnQgPT09IHB0cy5sZW5ndGggLSAyKSB7XG4gICAgICAgICAgICAgICAgZm9yKGNudDMgPSAwOyBjbnQzIDwgY250MjsgY250MysrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGRpc3Rncm91cCArIGFsbGRpc3RzW2NudDNdIDwgZGlzdFRocmVzaG9sZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGdyb3VwICs9IGFsbGRpc3RzW2NudDNdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHRjbnQgPSBjbnQgLSBjbnQyICsgY250MyArIDE7XG4gICAgICAgICAgICBwdGF2ZyA9IE1hdGguZmxvb3IoKGNudCArIGNudDIgKyBjbnQzICsgMikgLyAyKTtcblxuICAgICAgICAgICAgLy8gZWl0aGVyIGVuZHBvaW50IGluY2x1ZGVkOiBrZWVwIHRoZSBlbmRwb2ludFxuICAgICAgICAgICAgaWYoIWNsb3NlZHBhdGggJiYgY250ID09PSBwdHMubGVuZ3RoIC0gMikgbmV3cHQgPSBwdHNbcHRzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgZWxzZSBpZighY2xvc2VkcGF0aCAmJiBjbnQyID09PSAtMSkgbmV3cHQgPSBwdHNbMF07XG5cbiAgICAgICAgICAgIC8vIG9kZCAjIG9mIHBvaW50cyAtIGp1c3QgdGFrZSB0aGUgY2VudHJhbCBvbmVcbiAgICAgICAgICAgIGVsc2UgaWYocHRjbnQgJSAyKSBuZXdwdCA9IGdldHB0KHB0YXZnKTtcblxuICAgICAgICAgICAgLy8gZXZlbiAjIG9mIHB0cyAtIGF2ZXJhZ2UgY2VudHJhbCB0d29cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG5ld3B0ID0gWyhnZXRwdChwdGF2ZylbMF0gKyBnZXRwdChwdGF2ZyArIDEpWzBdKSAvIDIsXG4gICAgICAgICAgICAgICAgICAgIChnZXRwdChwdGF2ZylbMV0gKyBnZXRwdChwdGF2ZyArIDEpWzFdKSAvIDJdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwdHMuc3BsaWNlKGNudDIgKyAxLCBjbnQgLSBjbnQyICsgMSwgbmV3cHQpO1xuICAgICAgICAgICAgY250ID0gY250MiArIDE7XG4gICAgICAgICAgICBpZihjbnQzKSBjcm9wc3RhcnQgPSBjbnQzO1xuICAgICAgICAgICAgaWYoY2xvc2VkcGF0aCkge1xuICAgICAgICAgICAgICAgIGlmKGNudCA9PT0gcHRzLmxlbmd0aCAtIDIpIHB0c1tjbnQzXSA9IHB0c1twdHMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgZWxzZSBpZihjbnQgPT09IDApIHB0c1twdHMubGVuZ3RoIC0gMV0gPSBwdHNbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcHRzLnNwbGljZSgwLCBjcm9wc3RhcnQpO1xuXG4gICAgLy8gZG9uZSB3aXRoIHRoZSBpbmRleCBwYXJ0cyAtIHJlbW92ZSB0aGVtIHNvIHBhdGggZ2VuZXJhdGlvbiB3b3JrcyByaWdodFxuICAgIC8vIGJlY2F1c2UgaXQgZGVwZW5kcyBvbiBvbmx5IGhhdmluZyBbeHB4LCB5cHhdXG4gICAgZm9yKGNudCA9IDA7IGNudCA8IHB0cy5sZW5ndGg7IGNudCsrKSBwdHNbY250XS5sZW5ndGggPSAyO1xuXG4gICAgLy8gZG9uJ3QgcmV0dXJuIHNpbmdsZS1wb2ludCBwYXRocyAoaWUgYWxsIHBvaW50cyB3ZXJlIHRoZSBzYW1lXG4gICAgLy8gc28gdGhleSBnb3QgZGVsZXRlZD8pXG4gICAgaWYocHRzLmxlbmd0aCA8IDIpIHJldHVybjtcbiAgICBlbHNlIGlmKGNsb3NlZHBhdGgpIHtcbiAgICAgICAgcHRzLnBvcCgpO1xuICAgICAgICBwaS5wYXRocy5wdXNoKHB0cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYoIWVkZ2VmbGFnKSB7XG4gICAgICAgICAgICBMaWIubG9nKCdVbmNsb3NlZCBpbnRlcmlvciBjb250b3VyPycsXG4gICAgICAgICAgICAgICAgcGkubGV2ZWwsIHN0YXJ0TG9jU3RyLCBwdHMuam9pbignTCcpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGVkZ2UgcGF0aCAtIGRvZXMgaXQgc3RhcnQgd2hlcmUgYW4gZXhpc3RpbmcgZWRnZSBwYXRoIGVuZHMsIG9yIHZpY2UgdmVyc2E/XG4gICAgICAgIHZhciBtZXJnZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGkuZWRnZXBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBlZGdlcGF0aGkgPSBwaS5lZGdlcGF0aHNbaV07XG4gICAgICAgICAgICBpZighbWVyZ2VkICYmIGVxdWFsUHRzKGVkZ2VwYXRoaVswXSwgcHRzW3B0cy5sZW5ndGggLSAxXSwgeHRvbCwgeXRvbCkpIHtcbiAgICAgICAgICAgICAgICBwdHMucG9wKCk7XG4gICAgICAgICAgICAgICAgbWVyZ2VkID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIC8vIG5vdyBkb2VzIGl0IEFMU08gbWVldCB0aGUgZW5kIG9mIGFub3RoZXIgKG9yIHRoZSBzYW1lKSBwYXRoP1xuICAgICAgICAgICAgICAgIHZhciBkb3VibGVtZXJnZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBwaS5lZGdlcGF0aHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZWRnZXBhdGhqID0gcGkuZWRnZXBhdGhzW2pdO1xuICAgICAgICAgICAgICAgICAgICBpZihlcXVhbFB0cyhlZGdlcGF0aGpbZWRnZXBhdGhqLmxlbmd0aCAtIDFdLCBwdHNbMF0sIHh0b2wsIHl0b2wpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb3VibGVtZXJnZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHRzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwaS5lZGdlcGF0aHMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaiA9PT0gaSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBwYXRoIGlzIG5vdyBjbG9zZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaS5wYXRocy5wdXNoKHB0cy5jb25jYXQoZWRnZXBhdGhqKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGogPiBpKSBqLS07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGkuZWRnZXBhdGhzW2pdID0gZWRnZXBhdGhqLmNvbmNhdChwdHMsIGVkZ2VwYXRoaSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZighZG91YmxlbWVyZ2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHBpLmVkZ2VwYXRoc1tpXSA9IHB0cy5jb25jYXQoZWRnZXBhdGhpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGkuZWRnZXBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihtZXJnZWQpIGJyZWFrO1xuICAgICAgICAgICAgZWRnZXBhdGhpID0gcGkuZWRnZXBhdGhzW2ldO1xuICAgICAgICAgICAgaWYoZXF1YWxQdHMoZWRnZXBhdGhpW2VkZ2VwYXRoaS5sZW5ndGggLSAxXSwgcHRzWzBdLCB4dG9sLCB5dG9sKSkge1xuICAgICAgICAgICAgICAgIHB0cy5zaGlmdCgpO1xuICAgICAgICAgICAgICAgIHBpLmVkZ2VwYXRoc1tpXSA9IGVkZ2VwYXRoaS5jb25jYXQocHRzKTtcbiAgICAgICAgICAgICAgICBtZXJnZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoIW1lcmdlZCkgcGkuZWRnZXBhdGhzLnB1c2gocHRzKTtcbiAgICB9XG59XG5cbi8vIHNwZWNpYWwgZnVuY3Rpb24gdG8gZ2V0IHRoZSBtYXJjaGluZyBzdGVwIG9mIHRoZVxuLy8gZmlyc3QgcG9pbnQgaW4gdGhlIHBhdGggKGxlYWRpbmcgdG8gbG9jKVxuZnVuY3Rpb24gc3RhcnRTdGVwKG1pLCBlZGdlZmxhZywgbG9jKSB7XG4gICAgdmFyIGR4ID0gMDtcbiAgICB2YXIgZHkgPSAwO1xuICAgIGlmKG1pID4gMjAgJiYgZWRnZWZsYWcpIHtcbiAgICAgICAgLy8gdGhlc2Ugc2FkZGxlcyBzdGFydCBhdCArLy0geFxuICAgICAgICBpZihtaSA9PT0gMjA4IHx8IG1pID09PSAxMTE0KSB7XG4gICAgICAgICAgICAvLyBpZiB3ZSdyZSBzdGFydGluZyBhdCB0aGUgbGVmdCBzaWRlLCB3ZSBtdXN0IGJlIGdvaW5nIHJpZ2h0XG4gICAgICAgICAgICBkeCA9IGxvY1swXSA9PT0gMCA/IDEgOiAtMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGlmIHdlJ3JlIHN0YXJ0aW5nIGF0IHRoZSBib3R0b20sIHdlIG11c3QgYmUgZ29pbmcgdXBcbiAgICAgICAgICAgIGR5ID0gbG9jWzFdID09PSAwID8gMSA6IC0xO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKGNvbnN0YW50cy5CT1RUT01TVEFSVC5pbmRleE9mKG1pKSAhPT0gLTEpIGR5ID0gMTtcbiAgICBlbHNlIGlmKGNvbnN0YW50cy5MRUZUU1RBUlQuaW5kZXhPZihtaSkgIT09IC0xKSBkeCA9IDE7XG4gICAgZWxzZSBpZihjb25zdGFudHMuVE9QU1RBUlQuaW5kZXhPZihtaSkgIT09IC0xKSBkeSA9IC0xO1xuICAgIGVsc2UgZHggPSAtMTtcbiAgICByZXR1cm4gW2R4LCBkeV07XG59XG5cbi8qXG4gKiBGaW5kIHRoZSBwaXhlbCBjb29yZGluYXRlcyBvZiBhIHBhcnRpY3VsYXIgY3Jvc3NpbmdcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gcGk6IHRoZSBwYXRoaW5mbyBvYmplY3QgYXQgdGhpcyBsZXZlbFxuICogQHBhcmFtIHthcnJheX0gbG9jOiB0aGUgZ3JpZCBpbmRleCBbeCwgeV0gb2YgdGhlIGNyb3NzaW5nXG4gKiBAcGFyYW0ge2FycmF5fSBzdGVwOiB0aGUgZGlyZWN0aW9uIFtkeCwgZHldIHdlJ3JlIG1vdmluZyBvbiB0aGUgZ3JpZFxuICpcbiAqIEByZXR1cm4ge2FycmF5fSBbeHB4LCB5cHgsIHhpLCB5aV06IHRoZSBmaXJzdCB0d28gYXJlIHRoZSBwaXhlbCBsb2NhdGlvbixcbiAqICAgdGhlIG5leHQgdHdvIGFyZSB0aGUgaW50ZXJwb2xhdGVkIGdyaWQgaW5kaWNlcywgd2hpY2ggd2UgdXNlIGZvclxuICogICBkaXN0YW5jZSBjYWxjdWxhdGlvbnMgdG8gZGVsZXRlIHBvaW50cyB0aGF0IGFyZSB0b28gY2xvc2UgdG9nZXRoZXIuXG4gKiAgIFRoaXMgaXMgaW1wb3J0YW50IHdoZW4gdGhlIGdyaWQgaXMgbm9udW5pZm9ybSAoYW5kIG1vc3QgZHJhbWF0aWNhbGx5IHdoZW5cbiAqICAgd2UncmUgb24gbG9nIGF4ZXMgYW5kIGluY2x1ZGUgaW52YWxpZCAoMCBvciBuZWdhdGl2ZSkgdmFsdWVzLlxuICogICBJdCdzIGNydWNpYWwgdG8gZGVsZXRlIHRoZXNlIGV4dHJhIHR3byBiZWZvcmUgdHVybmluZyBhbiBhcnJheSBvZiB0aGVzZVxuICogICBwb2ludHMgaW50byBhIHBhdGgsIGJlY2F1c2UgdGhvc2Ugcm91dGluZXMgcmVxdWlyZSBsZW5ndGgtMiBwb2ludHMuXG4gKi9cbmZ1bmN0aW9uIGdldEludGVycFB4KHBpLCBsb2MsIHN0ZXApIHtcbiAgICB2YXIgbG9jeCA9IGxvY1swXSArIE1hdGgubWF4KHN0ZXBbMF0sIDApO1xuICAgIHZhciBsb2N5ID0gbG9jWzFdICsgTWF0aC5tYXgoc3RlcFsxXSwgMCk7XG4gICAgdmFyIHp4eSA9IHBpLnpbbG9jeV1bbG9jeF07XG4gICAgdmFyIHhhID0gcGkueGF4aXM7XG4gICAgdmFyIHlhID0gcGkueWF4aXM7XG5cbiAgICBpZihzdGVwWzFdKSB7XG4gICAgICAgIHZhciBkeCA9IChwaS5sZXZlbCAtIHp4eSkgLyAocGkueltsb2N5XVtsb2N4ICsgMV0gLSB6eHkpO1xuXG4gICAgICAgIHJldHVybiBbeGEuYzJwKCgxIC0gZHgpICogcGkueFtsb2N4XSArIGR4ICogcGkueFtsb2N4ICsgMV0sIHRydWUpLFxuICAgICAgICAgICAgeWEuYzJwKHBpLnlbbG9jeV0sIHRydWUpLFxuICAgICAgICAgICAgbG9jeCArIGR4LCBsb2N5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgZHkgPSAocGkubGV2ZWwgLSB6eHkpIC8gKHBpLnpbbG9jeSArIDFdW2xvY3hdIC0genh5KTtcbiAgICAgICAgcmV0dXJuIFt4YS5jMnAocGkueFtsb2N4XSwgdHJ1ZSksXG4gICAgICAgICAgICB5YS5jMnAoKDEgLSBkeSkgKiBwaS55W2xvY3ldICsgZHkgKiBwaS55W2xvY3kgKyAxXSwgdHJ1ZSksXG4gICAgICAgICAgICBsb2N4LCBsb2N5ICsgZHldO1xuICAgIH1cbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuL2NvbnN0YW50c1wiOjk0Nn1dLDk1NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG52YXIgaGVhdG1hcEhvdmVyUG9pbnRzID0gX2RlcmVxXygnLi4vaGVhdG1hcC9ob3ZlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlLCBob3ZlckxheWVyKSB7XG4gICAgdmFyIGhvdmVyRGF0YSA9IGhlYXRtYXBIb3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSwgaG92ZXJMYXllciwgdHJ1ZSk7XG5cbiAgICBpZihob3ZlckRhdGEpIHtcbiAgICAgICAgaG92ZXJEYXRhLmZvckVhY2goZnVuY3Rpb24oaG92ZXJQdCkge1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gaG92ZXJQdC50cmFjZTtcbiAgICAgICAgICAgIGlmKHRyYWNlLmNvbnRvdXJzLnR5cGUgPT09ICdjb25zdHJhaW50Jykge1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlLmZpbGxjb2xvciAmJiBDb2xvci5vcGFjaXR5KHRyYWNlLmZpbGxjb2xvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJQdC5jb2xvciA9IENvbG9yLmFkZE9wYWNpdHkodHJhY2UuZmlsbGNvbG9yLCAxKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYodHJhY2UuY29udG91cnMuc2hvd2xpbmVzICYmIENvbG9yLm9wYWNpdHkodHJhY2UubGluZS5jb2xvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJQdC5jb2xvciA9IENvbG9yLmFkZE9wYWNpdHkodHJhY2UubGluZS5jb2xvciwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gaG92ZXJEYXRhO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vaGVhdG1hcC9ob3ZlclwiOjEwMDh9XSw5NTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLnBsb3QsXG4gICAgc3R5bGU6IF9kZXJlcV8oJy4vc3R5bGUnKSxcbiAgICBjb2xvcmJhcjogX2RlcmVxXygnLi9jb2xvcmJhcicpLFxuICAgIGhvdmVyUG9pbnRzOiBfZGVyZXFfKCcuL2hvdmVyJyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdjb250b3VyJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuJyksXG4gICAgY2F0ZWdvcmllczogWydjYXJ0ZXNpYW4nLCAnc3ZnJywgJzJkTWFwJywgJ2NvbnRvdXInLCAnc2hvd0xlZ2VuZCddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW5cIjo3NzgsXCIuL2F0dHJpYnV0ZXNcIjo5NDIsXCIuL2NhbGNcIjo5NDMsXCIuL2NvbG9yYmFyXCI6OTQ1LFwiLi9kZWZhdWx0c1wiOjk1MSxcIi4vaG92ZXJcIjo5NTUsXCIuL3Bsb3RcIjo5NjAsXCIuL3N0eWxlXCI6OTYyfV0sOTU3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFuZGxlTGFiZWxEZWZhdWx0cyhjb2VyY2UsIGxheW91dCwgbGluZUNvbG9yLCBvcHRzKSB7XG4gICAgaWYoIW9wdHMpIG9wdHMgPSB7fTtcbiAgICB2YXIgc2hvd0xhYmVscyA9IGNvZXJjZSgnY29udG91cnMuc2hvd2xhYmVscycpO1xuICAgIGlmKHNob3dMYWJlbHMpIHtcbiAgICAgICAgdmFyIGdsb2JhbEZvbnQgPSBsYXlvdXQuZm9udDtcbiAgICAgICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnY29udG91cnMubGFiZWxmb250Jywge1xuICAgICAgICAgICAgZmFtaWx5OiBnbG9iYWxGb250LmZhbWlseSxcbiAgICAgICAgICAgIHNpemU6IGdsb2JhbEZvbnQuc2l6ZSxcbiAgICAgICAgICAgIGNvbG9yOiBsaW5lQ29sb3JcbiAgICAgICAgfSk7XG4gICAgICAgIGNvZXJjZSgnY29udG91cnMubGFiZWxmb3JtYXQnKTtcbiAgICB9XG5cbiAgICBpZihvcHRzLmhhc0hvdmVyICE9PSBmYWxzZSkgY29lcmNlKCd6aG92ZXJmb3JtYXQnKTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sOTU4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIENvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKTtcbnZhciBlbmRQbHVzID0gX2RlcmVxXygnLi9lbmRfcGx1cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1ha2VDb2xvck1hcCh0cmFjZSkge1xuICAgIHZhciBjb250b3VycyA9IHRyYWNlLmNvbnRvdXJzO1xuICAgIHZhciBzdGFydCA9IGNvbnRvdXJzLnN0YXJ0O1xuICAgIHZhciBlbmQgPSBlbmRQbHVzKGNvbnRvdXJzKTtcbiAgICB2YXIgY3MgPSBjb250b3Vycy5zaXplIHx8IDE7XG4gICAgdmFyIG5jID0gTWF0aC5mbG9vcigoZW5kIC0gc3RhcnQpIC8gY3MpICsgMTtcbiAgICB2YXIgZXh0cmEgPSBjb250b3Vycy5jb2xvcmluZyA9PT0gJ2xpbmVzJyA/IDAgOiAxO1xuICAgIHZhciBjT3B0cyA9IENvbG9yc2NhbGUuZXh0cmFjdE9wdHModHJhY2UpO1xuXG4gICAgaWYoIWlzRmluaXRlKGNzKSkge1xuICAgICAgICBjcyA9IDE7XG4gICAgICAgIG5jID0gMTtcbiAgICB9XG5cbiAgICB2YXIgc2NsID0gY09wdHMucmV2ZXJzZXNjYWxlID9cbiAgICAgICAgQ29sb3JzY2FsZS5mbGlwU2NhbGUoY09wdHMuY29sb3JzY2FsZSkgOlxuICAgICAgICBjT3B0cy5jb2xvcnNjYWxlO1xuXG4gICAgdmFyIGxlbiA9IHNjbC5sZW5ndGg7XG4gICAgdmFyIGRvbWFpbiA9IG5ldyBBcnJheShsZW4pO1xuICAgIHZhciByYW5nZSA9IG5ldyBBcnJheShsZW4pO1xuXG4gICAgdmFyIHNpLCBpO1xuXG4gICAgaWYoY29udG91cnMuY29sb3JpbmcgPT09ICdoZWF0bWFwJykge1xuICAgICAgICB2YXIgem1pbjAgPSBjT3B0cy5taW47XG4gICAgICAgIHZhciB6bWF4MCA9IGNPcHRzLm1heDtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgc2kgPSBzY2xbaV07XG4gICAgICAgICAgICBkb21haW5baV0gPSBzaVswXSAqICh6bWF4MCAtIHptaW4wKSArIHptaW4wO1xuICAgICAgICAgICAgcmFuZ2VbaV0gPSBzaVsxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGRvIHRoZSBjb250b3VycyBleHRlbmQgYmV5b25kIHRoZSBjb2xvcnNjYWxlP1xuICAgICAgICAvLyBpZiBzbywgZXh0ZW5kIHRoZSBjb2xvcnNjYWxlIHdpdGggY29uc3RhbnRzXG4gICAgICAgIHZhciB6UmFuZ2UgPSBkMy5leHRlbnQoW1xuICAgICAgICAgICAgem1pbjAsXG4gICAgICAgICAgICB6bWF4MCxcbiAgICAgICAgICAgIGNvbnRvdXJzLnN0YXJ0LFxuICAgICAgICAgICAgY29udG91cnMuc3RhcnQgKyBjcyAqIChuYyAtIDEpXG4gICAgICAgIF0pO1xuICAgICAgICB2YXIgem1pbiA9IHpSYW5nZVt6bWluMCA8IHptYXgwID8gMCA6IDFdO1xuICAgICAgICB2YXIgem1heCA9IHpSYW5nZVt6bWluMCA8IHptYXgwID8gMSA6IDBdO1xuXG4gICAgICAgIGlmKHptaW4gIT09IHptaW4wKSB7XG4gICAgICAgICAgICBkb21haW4uc3BsaWNlKDAsIDAsIHptaW4pO1xuICAgICAgICAgICAgcmFuZ2Uuc3BsaWNlKDAsIDAsIHJhbmdlWzBdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHptYXggIT09IHptYXgwKSB7XG4gICAgICAgICAgICBkb21haW4ucHVzaCh6bWF4KTtcbiAgICAgICAgICAgIHJhbmdlLnB1c2gocmFuZ2VbcmFuZ2UubGVuZ3RoIC0gMV0pO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIHNpID0gc2NsW2ldO1xuICAgICAgICAgICAgZG9tYWluW2ldID0gKHNpWzBdICogKG5jICsgZXh0cmEgLSAxKSAtIChleHRyYSAvIDIpKSAqIGNzICsgc3RhcnQ7XG4gICAgICAgICAgICByYW5nZVtpXSA9IHNpWzFdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIENvbG9yc2NhbGUubWFrZUNvbG9yU2NhbGVGdW5jKFxuICAgICAgICB7ZG9tYWluOiBkb21haW4sIHJhbmdlOiByYW5nZX0sXG4gICAgICAgIHtub051bWVyaWNDaGVjazogdHJ1ZX1cbiAgICApO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGVcIjo2MDUsXCIuL2VuZF9wbHVzXCI6OTUzLFwiZDNcIjoxNjN9XSw5NTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcblxuLy8gQ2FsY3VsYXRlIGFsbCB0aGUgbWFyY2hpbmcgaW5kaWNlcywgZm9yIEFMTCBsZXZlbHMgYXQgb25jZS5cbi8vIHNpbmNlIHdlIHdhbnQgdG8gYmUgZXhoYXVzdGl2ZSB3ZSdsbCBjaGVjayBmb3IgY29udG91ciBjcm9zc2luZ3Ncbi8vIGF0IGV2ZXJ5IGludGVyc2VjdGlvbiwgcmF0aGVyIHRoYW4ganVzdCBmb2xsb3dpbmcgYSBwYXRoXG4vLyBUT0RPOiBzaG9ydGVuIHRoZSBpbm5lciBsb29wIHRvIG9ubHkgdGhlIHJlbGV2YW50IGxldmVsc1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlQ3Jvc3NpbmdzKHBhdGhpbmZvKSB7XG4gICAgdmFyIHogPSBwYXRoaW5mb1swXS56O1xuICAgIHZhciBtID0gei5sZW5ndGg7XG4gICAgdmFyIG4gPSB6WzBdLmxlbmd0aDsgLy8gd2UgYWxyZWFkeSBtYWRlIHN1cmUgeiBpc24ndCByYWdnZWQgaW4gaW50ZXJwMmRcbiAgICB2YXIgdHdvV2lkZSA9IG0gPT09IDIgfHwgbiA9PT0gMjtcbiAgICB2YXIgeGk7XG4gICAgdmFyIHlpO1xuICAgIHZhciBzdGFydEluZGljZXM7XG4gICAgdmFyIHlzdGFydEluZGljZXM7XG4gICAgdmFyIGxhYmVsO1xuICAgIHZhciBjb3JuZXJzO1xuICAgIHZhciBtaTtcbiAgICB2YXIgcGk7XG4gICAgdmFyIGk7XG5cbiAgICBmb3IoeWkgPSAwOyB5aSA8IG0gLSAxOyB5aSsrKSB7XG4gICAgICAgIHlzdGFydEluZGljZXMgPSBbXTtcbiAgICAgICAgaWYoeWkgPT09IDApIHlzdGFydEluZGljZXMgPSB5c3RhcnRJbmRpY2VzLmNvbmNhdChjb25zdGFudHMuQk9UVE9NU1RBUlQpO1xuICAgICAgICBpZih5aSA9PT0gbSAtIDIpIHlzdGFydEluZGljZXMgPSB5c3RhcnRJbmRpY2VzLmNvbmNhdChjb25zdGFudHMuVE9QU1RBUlQpO1xuXG4gICAgICAgIGZvcih4aSA9IDA7IHhpIDwgbiAtIDE7IHhpKyspIHtcbiAgICAgICAgICAgIHN0YXJ0SW5kaWNlcyA9IHlzdGFydEluZGljZXMuc2xpY2UoKTtcbiAgICAgICAgICAgIGlmKHhpID09PSAwKSBzdGFydEluZGljZXMgPSBzdGFydEluZGljZXMuY29uY2F0KGNvbnN0YW50cy5MRUZUU1RBUlQpO1xuICAgICAgICAgICAgaWYoeGkgPT09IG4gLSAyKSBzdGFydEluZGljZXMgPSBzdGFydEluZGljZXMuY29uY2F0KGNvbnN0YW50cy5SSUdIVFNUQVJUKTtcblxuICAgICAgICAgICAgbGFiZWwgPSB4aSArICcsJyArIHlpO1xuICAgICAgICAgICAgY29ybmVycyA9IFtbelt5aV1beGldLCB6W3lpXVt4aSArIDFdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgW3pbeWkgKyAxXVt4aV0sIHpbeWkgKyAxXVt4aSArIDFdXV07XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBwYXRoaW5mby5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHBpID0gcGF0aGluZm9baV07XG4gICAgICAgICAgICAgICAgbWkgPSBnZXRNYXJjaGluZ0luZGV4KHBpLmxldmVsLCBjb3JuZXJzKTtcbiAgICAgICAgICAgICAgICBpZighbWkpIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICAgICAgcGkuY3Jvc3NpbmdzW2xhYmVsXSA9IG1pO1xuICAgICAgICAgICAgICAgIGlmKHN0YXJ0SW5kaWNlcy5pbmRleE9mKG1pKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcGkuc3RhcnRzLnB1c2goW3hpLCB5aV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih0d29XaWRlICYmIHN0YXJ0SW5kaWNlcy5pbmRleE9mKG1pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0SW5kaWNlcy5pbmRleE9mKG1pKSArIDEpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHNhbWUgc3F1YXJlIGhhcyBzdGFydHMgZnJvbSBvcHBvc2l0ZSBzaWRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXQncyBub3QgcG9zc2libGUgdG8gaGF2ZSBzdGFydHMgb24gb3Bwb3NpdGUgZWRnZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG9mIGEgY29ybmVyLCBvbmx5IGEgc3RhcnQgYW5kIGFuIGVuZC4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYnV0IGlmIHRoZSBhcnJheSBpcyBvbmx5IHR3byBwb2ludHMgd2lkZSAoZWl0aGVyIHdheSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHlvdSBjYW4gaGF2ZSBzdGFydHMgb24gb3Bwb3NpdGUgc2lkZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICBwaS5zdGFydHMucHVzaChbeGksIHlpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG4vLyBtb2RpZmllZCBtYXJjaGluZyBzcXVhcmVzIGFsZ29yaXRobSxcbi8vIHNvIHdlIGRpc2FtYmlndWF0ZSB0aGUgc2FkZGxlIHBvaW50cyBmcm9tIHRoZSBzdGFydFxuLy8gYW5kIHdlIGlnbm9yZSB0aGUgY2FzZXMgd2l0aCBubyBjcm9zc2luZ3Ncbi8vIHRoZSBpbmRleCBJJ20gdXNpbmcgaXMgYmFzZWQgb246XG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01hcmNoaW5nX3NxdWFyZXNcbi8vIGV4Y2VwdCB0aGF0IHRoZSBzYWRkbGVzIGJpZnVyY2F0ZSBhbmQgSSByZXByZXNlbnQgdGhlbVxuLy8gYXMgdGhlIGRlY2ltYWwgY29tYmluYXRpb24gb2YgdGhlIHR3byBhcHByb3ByaWF0ZVxuLy8gbm9uLXNhZGRsZSBpbmRpY2VzXG5mdW5jdGlvbiBnZXRNYXJjaGluZ0luZGV4KHZhbCwgY29ybmVycykge1xuICAgIHZhciBtaSA9IChjb3JuZXJzWzBdWzBdID4gdmFsID8gMCA6IDEpICtcbiAgICAgICAgICAgICAoY29ybmVyc1swXVsxXSA+IHZhbCA/IDAgOiAyKSArXG4gICAgICAgICAgICAgKGNvcm5lcnNbMV1bMV0gPiB2YWwgPyAwIDogNCkgK1xuICAgICAgICAgICAgIChjb3JuZXJzWzFdWzBdID4gdmFsID8gMCA6IDgpO1xuICAgIGlmKG1pID09PSA1IHx8IG1pID09PSAxMCkge1xuICAgICAgICB2YXIgYXZnID0gKGNvcm5lcnNbMF1bMF0gKyBjb3JuZXJzWzBdWzFdICtcbiAgICAgICAgICAgICAgICAgICBjb3JuZXJzWzFdWzBdICsgY29ybmVyc1sxXVsxXSkgLyA0O1xuICAgICAgICAvLyB0d28gcGVha3Mgd2l0aCBhIGJpZyB2YWxsZXlcbiAgICAgICAgaWYodmFsID4gYXZnKSByZXR1cm4gKG1pID09PSA1KSA/IDcxMyA6IDExMTQ7XG4gICAgICAgIC8vIHR3byB2YWxsZXlzIHdpdGggYSBiaWcgcmlkZ2VcbiAgICAgICAgcmV0dXJuIChtaSA9PT0gNSkgPyAxMDQgOiAyMDg7XG4gICAgfVxuICAgIHJldHVybiAobWkgPT09IDE1KSA/IDAgOiBtaTtcbn1cblxufSx7XCIuL2NvbnN0YW50c1wiOjk0Nn1dLDk2MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBzdmdUZXh0VXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBzZXRDb252ZXJ0ID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3NldF9jb252ZXJ0Jyk7XG5cbnZhciBoZWF0bWFwUGxvdCA9IF9kZXJlcV8oJy4uL2hlYXRtYXAvcGxvdCcpO1xudmFyIG1ha2VDcm9zc2luZ3MgPSBfZGVyZXFfKCcuL21ha2VfY3Jvc3NpbmdzJyk7XG52YXIgZmluZEFsbFBhdGhzID0gX2RlcmVxXygnLi9maW5kX2FsbF9wYXRocycpO1xudmFyIGVtcHR5UGF0aGluZm8gPSBfZGVyZXFfKCcuL2VtcHR5X3BhdGhpbmZvJyk7XG52YXIgY29udmVydFRvQ29uc3RyYWludHMgPSBfZGVyZXFfKCcuL2NvbnZlcnRfdG9fY29uc3RyYWludHMnKTtcbnZhciBjbG9zZUJvdW5kYXJpZXMgPSBfZGVyZXFfKCcuL2Nsb3NlX2JvdW5kYXJpZXMnKTtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIGNvc3RDb25zdGFudHMgPSBjb25zdGFudHMuTEFCRUxPUFRJTUlaRVI7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHBsb3RpbmZvLCBjZGNvbnRvdXJzLCBjb250b3VyTGF5ZXIpIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIExpYi5tYWtlVHJhY2VHcm91cHMoY29udG91ckxheWVyLCBjZGNvbnRvdXJzLCAnY29udG91cicpLmVhY2goZnVuY3Rpb24oY2QpIHtcbiAgICAgICAgdmFyIHBsb3RHcm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgICAgIHZhciB4ID0gY2QwLng7XG4gICAgICAgIHZhciB5ID0gY2QwLnk7XG4gICAgICAgIHZhciBjb250b3VycyA9IHRyYWNlLmNvbnRvdXJzO1xuICAgICAgICB2YXIgcGF0aGluZm8gPSBlbXB0eVBhdGhpbmZvKGNvbnRvdXJzLCBwbG90aW5mbywgY2QwKTtcblxuICAgICAgICAvLyB1c2UgYSBoZWF0bWFwIHRvIGZpbGwgLSBkcmF3IGl0IGJlaGluZCB0aGUgbGluZXNcbiAgICAgICAgdmFyIGhlYXRtYXBDb2xvcmluZ0xheWVyID0gTGliLmVuc3VyZVNpbmdsZShwbG90R3JvdXAsICdnJywgJ2hlYXRtYXBjb2xvcmluZycpO1xuICAgICAgICB2YXIgY2RoZWF0bWFwcyA9IFtdO1xuICAgICAgICBpZihjb250b3Vycy5jb2xvcmluZyA9PT0gJ2hlYXRtYXAnKSB7XG4gICAgICAgICAgICBjZGhlYXRtYXBzID0gW2NkXTtcbiAgICAgICAgfVxuICAgICAgICBoZWF0bWFwUGxvdChnZCwgcGxvdGluZm8sIGNkaGVhdG1hcHMsIGhlYXRtYXBDb2xvcmluZ0xheWVyKTtcblxuICAgICAgICBtYWtlQ3Jvc3NpbmdzKHBhdGhpbmZvKTtcbiAgICAgICAgZmluZEFsbFBhdGhzKHBhdGhpbmZvKTtcblxuICAgICAgICB2YXIgbGVmdGVkZ2UgPSB4YS5jMnAoeFswXSwgdHJ1ZSk7XG4gICAgICAgIHZhciByaWdodGVkZ2UgPSB4YS5jMnAoeFt4Lmxlbmd0aCAtIDFdLCB0cnVlKTtcbiAgICAgICAgdmFyIGJvdHRvbWVkZ2UgPSB5YS5jMnAoeVswXSwgdHJ1ZSk7XG4gICAgICAgIHZhciB0b3BlZGdlID0geWEuYzJwKHlbeS5sZW5ndGggLSAxXSwgdHJ1ZSk7XG4gICAgICAgIHZhciBwZXJpbWV0ZXIgPSBbXG4gICAgICAgICAgICBbbGVmdGVkZ2UsIHRvcGVkZ2VdLFxuICAgICAgICAgICAgW3JpZ2h0ZWRnZSwgdG9wZWRnZV0sXG4gICAgICAgICAgICBbcmlnaHRlZGdlLCBib3R0b21lZGdlXSxcbiAgICAgICAgICAgIFtsZWZ0ZWRnZSwgYm90dG9tZWRnZV1cbiAgICAgICAgXTtcblxuICAgICAgICB2YXIgZmlsbFBhdGhpbmZvID0gcGF0aGluZm87XG4gICAgICAgIGlmKGNvbnRvdXJzLnR5cGUgPT09ICdjb25zdHJhaW50Jykge1xuICAgICAgICAgICAgZmlsbFBhdGhpbmZvID0gY29udmVydFRvQ29uc3RyYWludHMocGF0aGluZm8sIGNvbnRvdXJzLl9vcGVyYXRpb24pO1xuICAgICAgICAgICAgY2xvc2VCb3VuZGFyaWVzKGZpbGxQYXRoaW5mbywgY29udG91cnMuX29wZXJhdGlvbiwgcGVyaW1ldGVyLCB0cmFjZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkcmF3IGV2ZXJ5dGhpbmdcbiAgICAgICAgbWFrZUJhY2tncm91bmQocGxvdEdyb3VwLCBwZXJpbWV0ZXIsIGNvbnRvdXJzKTtcbiAgICAgICAgbWFrZUZpbGxzKHBsb3RHcm91cCwgZmlsbFBhdGhpbmZvLCBwZXJpbWV0ZXIsIGNvbnRvdXJzKTtcbiAgICAgICAgbWFrZUxpbmVzQW5kTGFiZWxzKHBsb3RHcm91cCwgcGF0aGluZm8sIGdkLCBjZDAsIGNvbnRvdXJzKTtcbiAgICAgICAgY2xpcEdhcHMocGxvdEdyb3VwLCBwbG90aW5mbywgZ2QsIGNkMCwgcGVyaW1ldGVyKTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VCYWNrZ3JvdW5kKHBsb3Rncm91cCwgcGVyaW1ldGVyLCBjb250b3Vycykge1xuICAgIHZhciBiZ2dyb3VwID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2NvbnRvdXJiZycpO1xuXG4gICAgdmFyIGJnZmlsbCA9IGJnZ3JvdXAuc2VsZWN0QWxsKCdwYXRoJylcbiAgICAgICAgLmRhdGEoY29udG91cnMuY29sb3JpbmcgPT09ICdmaWxsJyA/IFswXSA6IFtdKTtcbiAgICBiZ2ZpbGwuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKTtcbiAgICBiZ2ZpbGwuZXhpdCgpLnJlbW92ZSgpO1xuICAgIGJnZmlsbFxuICAgICAgICAuYXR0cignZCcsICdNJyArIHBlcmltZXRlci5qb2luKCdMJykgKyAnWicpXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlJywgJ25vbmUnKTtcbn1cblxuZnVuY3Rpb24gbWFrZUZpbGxzKHBsb3Rncm91cCwgcGF0aGluZm8sIHBlcmltZXRlciwgY29udG91cnMpIHtcbiAgICB2YXIgZmlsbGdyb3VwID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2NvbnRvdXJmaWxsJyk7XG5cbiAgICB2YXIgZmlsbGl0ZW1zID0gZmlsbGdyb3VwLnNlbGVjdEFsbCgncGF0aCcpXG4gICAgICAgIC5kYXRhKGNvbnRvdXJzLmNvbG9yaW5nID09PSAnZmlsbCcgfHwgKGNvbnRvdXJzLnR5cGUgPT09ICdjb25zdHJhaW50JyAmJiBjb250b3Vycy5fb3BlcmF0aW9uICE9PSAnPScpID8gcGF0aGluZm8gOiBbXSk7XG4gICAgZmlsbGl0ZW1zLmVudGVyKCkuYXBwZW5kKCdwYXRoJyk7XG4gICAgZmlsbGl0ZW1zLmV4aXQoKS5yZW1vdmUoKTtcbiAgICBmaWxsaXRlbXMuZWFjaChmdW5jdGlvbihwaSkge1xuICAgICAgICAvLyBqb2luIGFsbCBwYXRocyBmb3IgdGhpcyBsZXZlbCB0b2dldGhlciBpbnRvIGEgc2luZ2xlIHBhdGhcbiAgICAgICAgLy8gZmlyc3QgZm9sbG93IGNsb2Nrd2lzZSBhcm91bmQgdGhlIHBlcmltZXRlciB0byBjbG9zZSBhbnkgb3BlbiBwYXRoc1xuICAgICAgICAvLyBpZiB0aGUgd2hvbGUgcGVyaW1ldGVyIGlzIGFib3ZlIHRoaXMgbGV2ZWwsIHN0YXJ0IHdpdGggYSBwYXRoXG4gICAgICAgIC8vIGVuY2xvc2luZyB0aGUgd2hvbGUgdGhpbmcuIFdpdGggYWxsIHRoYXQsIHRoZSBwYXJpdHkgc2hvdWxkIG1lYW5cbiAgICAgICAgLy8gdGhhdCB3ZSBhbHdheXMgZmlsbCBldmVyeXRoaW5nIGFib3ZlIHRoZSBjb250b3VyLCBub3RoaW5nIGJlbG93XG4gICAgICAgIHZhciBmdWxscGF0aCA9IGpvaW5BbGxQYXRocyhwaSwgcGVyaW1ldGVyKTtcblxuICAgICAgICBpZighZnVsbHBhdGgpIGQzLnNlbGVjdCh0aGlzKS5yZW1vdmUoKTtcbiAgICAgICAgZWxzZSBkMy5zZWxlY3QodGhpcykuYXR0cignZCcsIGZ1bGxwYXRoKS5zdHlsZSgnc3Ryb2tlJywgJ25vbmUnKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gaW5pdEZ1bGxQYXRoKHBpLCBwZXJpbWV0ZXIpIHtcbiAgICB2YXIgcHJlZml4Qm91bmRhcnkgPSBwaS5wcmVmaXhCb3VuZGFyeTtcbiAgICBpZihwcmVmaXhCb3VuZGFyeSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhciBlZGdlVmFsMiA9IE1hdGgubWluKHBpLnpbMF1bMF0sIHBpLnpbMF1bMV0pO1xuICAgICAgICBwcmVmaXhCb3VuZGFyeSA9ICghcGkuZWRnZXBhdGhzLmxlbmd0aCAmJiBlZGdlVmFsMiA+IHBpLmxldmVsKTtcbiAgICB9XG5cbiAgICBpZihwcmVmaXhCb3VuZGFyeSkge1xuICAgICAgICAvLyBUT0RPOiB3aHkgZG9lcyBeXiBub3Qgd29yayBmb3IgY29uc3RyYWludHM/XG4gICAgICAgIC8vIHBpLnByZWZpeEJvdW5kYXJ5IGdldHMgc2V0IGJ5IGNsb3NlQm91bmRhcmllc1xuICAgICAgICByZXR1cm4gJ00nICsgcGVyaW1ldGVyLmpvaW4oJ0wnKSArICdaJztcbiAgICB9XG4gICAgcmV0dXJuICcnO1xufVxuXG5mdW5jdGlvbiBqb2luQWxsUGF0aHMocGksIHBlcmltZXRlcikge1xuICAgIHZhciBmdWxscGF0aCA9IGluaXRGdWxsUGF0aChwaSwgcGVyaW1ldGVyKTtcbiAgICB2YXIgaSA9IDA7XG4gICAgdmFyIHN0YXJ0c2xlZnQgPSBwaS5lZGdlcGF0aHMubWFwKGZ1bmN0aW9uKHYsIGkpIHsgcmV0dXJuIGk7IH0pO1xuICAgIHZhciBuZXdsb29wID0gdHJ1ZTtcbiAgICB2YXIgZW5kcHQ7XG4gICAgdmFyIG5ld2VuZHB0O1xuICAgIHZhciBjbnQ7XG4gICAgdmFyIG5leHRpO1xuICAgIHZhciBwb3NzaWJsZWk7XG4gICAgdmFyIGFkZHBhdGg7XG5cbiAgICBmdW5jdGlvbiBpc3RvcChwdCkgeyByZXR1cm4gTWF0aC5hYnMocHRbMV0gLSBwZXJpbWV0ZXJbMF1bMV0pIDwgMC4wMTsgfVxuICAgIGZ1bmN0aW9uIGlzYm90dG9tKHB0KSB7IHJldHVybiBNYXRoLmFicyhwdFsxXSAtIHBlcmltZXRlclsyXVsxXSkgPCAwLjAxOyB9XG4gICAgZnVuY3Rpb24gaXNsZWZ0KHB0KSB7IHJldHVybiBNYXRoLmFicyhwdFswXSAtIHBlcmltZXRlclswXVswXSkgPCAwLjAxOyB9XG4gICAgZnVuY3Rpb24gaXNyaWdodChwdCkgeyByZXR1cm4gTWF0aC5hYnMocHRbMF0gLSBwZXJpbWV0ZXJbMl1bMF0pIDwgMC4wMTsgfVxuXG4gICAgd2hpbGUoc3RhcnRzbGVmdC5sZW5ndGgpIHtcbiAgICAgICAgYWRkcGF0aCA9IERyYXdpbmcuc21vb3Rob3BlbihwaS5lZGdlcGF0aHNbaV0sIHBpLnNtb290aGluZyk7XG4gICAgICAgIGZ1bGxwYXRoICs9IG5ld2xvb3AgPyBhZGRwYXRoIDogYWRkcGF0aC5yZXBsYWNlKC9eTS8sICdMJyk7XG4gICAgICAgIHN0YXJ0c2xlZnQuc3BsaWNlKHN0YXJ0c2xlZnQuaW5kZXhPZihpKSwgMSk7XG4gICAgICAgIGVuZHB0ID0gcGkuZWRnZXBhdGhzW2ldW3BpLmVkZ2VwYXRoc1tpXS5sZW5ndGggLSAxXTtcbiAgICAgICAgbmV4dGkgPSAtMTtcblxuICAgICAgICAvLyBub3cgbG9vcCB0aHJvdWdoIHNpZGVzLCBtb3Zpbmcgb3VyIGVuZHBvaW50IHVudGlsIHdlIGZpbmQgYSBuZXcgc3RhcnRcbiAgICAgICAgZm9yKGNudCA9IDA7IGNudCA8IDQ7IGNudCsrKSB7IC8vIGp1c3QgdG8gcHJldmVudCBpbmZpbml0ZSBsb29wc1xuICAgICAgICAgICAgaWYoIWVuZHB0KSB7XG4gICAgICAgICAgICAgICAgTGliLmxvZygnTWlzc2luZyBlbmQ/JywgaSwgcGkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihpc3RvcChlbmRwdCkgJiYgIWlzcmlnaHQoZW5kcHQpKSBuZXdlbmRwdCA9IHBlcmltZXRlclsxXTsgLy8gcmlnaHQgdG9wXG4gICAgICAgICAgICBlbHNlIGlmKGlzbGVmdChlbmRwdCkpIG5ld2VuZHB0ID0gcGVyaW1ldGVyWzBdOyAvLyBsZWZ0IHRvcFxuICAgICAgICAgICAgZWxzZSBpZihpc2JvdHRvbShlbmRwdCkpIG5ld2VuZHB0ID0gcGVyaW1ldGVyWzNdOyAvLyByaWdodCBib3R0b21cbiAgICAgICAgICAgIGVsc2UgaWYoaXNyaWdodChlbmRwdCkpIG5ld2VuZHB0ID0gcGVyaW1ldGVyWzJdOyAvLyBsZWZ0IGJvdHRvbVxuXG4gICAgICAgICAgICBmb3IocG9zc2libGVpID0gMDsgcG9zc2libGVpIDwgcGkuZWRnZXBhdGhzLmxlbmd0aDsgcG9zc2libGVpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcHROZXcgPSBwaS5lZGdlcGF0aHNbcG9zc2libGVpXVswXTtcbiAgICAgICAgICAgICAgICAvLyBpcyBwdE5ldyBvbiB0aGUgKGhvcnouIG9yIHZlcnQuKSBzZWdtZW50IGZyb20gZW5kcHQgdG8gbmV3ZW5kcHQ/XG4gICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMoZW5kcHRbMF0gLSBuZXdlbmRwdFswXSkgPCAwLjAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKE1hdGguYWJzKGVuZHB0WzBdIC0gcHROZXdbMF0pIDwgMC4wMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwdE5ld1sxXSAtIGVuZHB0WzFdKSAqIChuZXdlbmRwdFsxXSAtIHB0TmV3WzFdKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdlbmRwdCA9IHB0TmV3O1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dGkgPSBwb3NzaWJsZWk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoTWF0aC5hYnMoZW5kcHRbMV0gLSBuZXdlbmRwdFsxXSkgPCAwLjAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKE1hdGguYWJzKGVuZHB0WzFdIC0gcHROZXdbMV0pIDwgMC4wMSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwdE5ld1swXSAtIGVuZHB0WzBdKSAqIChuZXdlbmRwdFswXSAtIHB0TmV3WzBdKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdlbmRwdCA9IHB0TmV3O1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dGkgPSBwb3NzaWJsZWk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBMaWIubG9nKCdlbmRwdCB0byBuZXdlbmRwdCBpcyBub3QgdmVydC4gb3IgaG9yei4nLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5kcHQsIG5ld2VuZHB0LCBwdE5ldyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBlbmRwdCA9IG5ld2VuZHB0O1xuXG4gICAgICAgICAgICBpZihuZXh0aSA+PSAwKSBicmVhaztcbiAgICAgICAgICAgIGZ1bGxwYXRoICs9ICdMJyArIG5ld2VuZHB0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobmV4dGkgPT09IHBpLmVkZ2VwYXRocy5sZW5ndGgpIHtcbiAgICAgICAgICAgIExpYi5sb2coJ3VuY2xvc2VkIHBlcmltZXRlciBwYXRoJyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGkgPSBuZXh0aTtcblxuICAgICAgICAvLyBpZiB3ZSBjbG9zZWQgYmFjayBvbiBhIGxvb3Agd2UgYWxyZWFkeSBpbmNsdWRlZCxcbiAgICAgICAgLy8gY2xvc2UgaXQgYW5kIHN0YXJ0IGEgbmV3IGxvb3BcbiAgICAgICAgbmV3bG9vcCA9IChzdGFydHNsZWZ0LmluZGV4T2YoaSkgPT09IC0xKTtcbiAgICAgICAgaWYobmV3bG9vcCkge1xuICAgICAgICAgICAgaSA9IHN0YXJ0c2xlZnRbMF07XG4gICAgICAgICAgICBmdWxscGF0aCArPSAnWic7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmaW5hbGx5IGFkZCB0aGUgaW50ZXJpb3IgcGF0aHNcbiAgICBmb3IoaSA9IDA7IGkgPCBwaS5wYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICBmdWxscGF0aCArPSBEcmF3aW5nLnNtb290aGNsb3NlZChwaS5wYXRoc1tpXSwgcGkuc21vb3RoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVsbHBhdGg7XG59XG5cbmZ1bmN0aW9uIG1ha2VMaW5lc0FuZExhYmVscyhwbG90Z3JvdXAsIHBhdGhpbmZvLCBnZCwgY2QwLCBjb250b3Vycykge1xuICAgIHZhciBsaW5lQ29udGFpbmVyID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2NvbnRvdXJsaW5lcycpO1xuICAgIHZhciBzaG93TGluZXMgPSBjb250b3Vycy5zaG93bGluZXMgIT09IGZhbHNlO1xuICAgIHZhciBzaG93TGFiZWxzID0gY29udG91cnMuc2hvd2xhYmVscztcbiAgICB2YXIgY2xpcExpbmVzRm9yTGFiZWxzID0gc2hvd0xpbmVzICYmIHNob3dMYWJlbHM7XG5cbiAgICAvLyBFdmVuIGlmIHdlJ3JlIG5vdCBnb2luZyB0byBzaG93IGxpbmVzLCB3ZSBuZWVkIHRvIGNyZWF0ZSB0aGVtXG4gICAgLy8gaWYgd2UncmUgc2hvd2luZyBsYWJlbHMsIGJlY2F1c2UgdGhlIGZpbGwgcGF0aHMgaW5jbHVkZSB0aGUgcGVyaW1ldGVyXG4gICAgLy8gc28gY2FuJ3QgYmUgdXNlZCB0byBwb3NpdGlvbiB0aGUgbGFiZWxzIGNvcnJlY3RseS5cbiAgICAvLyBJbiB0aGlzIGNhc2Ugd2UnbGwgcmVtb3ZlIHRoZSBsaW5lcyBhZnRlciBtYWtpbmcgdGhlIGxhYmVscy5cbiAgICB2YXIgbGluZWdyb3VwID0gZXhwb3J0cy5jcmVhdGVMaW5lcyhsaW5lQ29udGFpbmVyLCBzaG93TGluZXMgfHwgc2hvd0xhYmVscywgcGF0aGluZm8pO1xuXG4gICAgdmFyIGxpbmVDbGlwID0gZXhwb3J0cy5jcmVhdGVMaW5lQ2xpcChsaW5lQ29udGFpbmVyLCBjbGlwTGluZXNGb3JMYWJlbHMsIGdkLCBjZDAudHJhY2UudWlkKTtcblxuICAgIHZhciBsYWJlbEdyb3VwID0gcGxvdGdyb3VwLnNlbGVjdEFsbCgnZy5jb250b3VybGFiZWxzJylcbiAgICAgICAgLmRhdGEoc2hvd0xhYmVscyA/IFswXSA6IFtdKTtcblxuICAgIGxhYmVsR3JvdXAuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgbGFiZWxHcm91cC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdjb250b3VybGFiZWxzJywgdHJ1ZSk7XG5cbiAgICBpZihzaG93TGFiZWxzKSB7XG4gICAgICAgIHZhciBsYWJlbENsaXBQYXRoRGF0YSA9IFtdO1xuICAgICAgICB2YXIgbGFiZWxEYXRhID0gW107XG5cbiAgICAgICAgLy8gaW52YWxpZGF0ZSB0aGUgZ2V0VGV4dExvY2F0aW9uIGNhY2hlIGluIGNhc2UgcGF0aHMgY2hhbmdlZFxuICAgICAgICBMaWIuY2xlYXJMb2NhdGlvbkNhY2hlKCk7XG5cbiAgICAgICAgdmFyIGNvbnRvdXJGb3JtYXQgPSBleHBvcnRzLmxhYmVsRm9ybWF0dGVyKGNvbnRvdXJzLCBjZDAudC5jYiwgZ2QuX2Z1bGxMYXlvdXQpO1xuXG4gICAgICAgIHZhciBkdW1teVRleHQgPSBEcmF3aW5nLnRlc3Rlci5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAgICAgLmF0dHIoJ2RhdGEtbm90ZXgnLCAxKVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBjb250b3Vycy5sYWJlbGZvbnQpO1xuXG4gICAgICAgIHZhciB4YSA9IHBhdGhpbmZvWzBdLnhheGlzO1xuICAgICAgICB2YXIgeWEgPSBwYXRoaW5mb1swXS55YXhpcztcbiAgICAgICAgdmFyIHhMZW4gPSB4YS5fbGVuZ3RoO1xuICAgICAgICB2YXIgeUxlbiA9IHlhLl9sZW5ndGg7XG4gICAgICAgIHZhciB4Um5nID0geGEucmFuZ2U7XG4gICAgICAgIHZhciB5Um5nID0geWEucmFuZ2U7XG4gICAgICAgIHZhciB4TWluID0gTGliLmFnZ051bXMoTWF0aC5taW4sIG51bGwsIGNkMC54KTtcbiAgICAgICAgdmFyIHhNYXggPSBMaWIuYWdnTnVtcyhNYXRoLm1heCwgbnVsbCwgY2QwLngpO1xuICAgICAgICB2YXIgeU1pbiA9IExpYi5hZ2dOdW1zKE1hdGgubWluLCBudWxsLCBjZDAueSk7XG4gICAgICAgIHZhciB5TWF4ID0gTGliLmFnZ051bXMoTWF0aC5tYXgsIG51bGwsIGNkMC55KTtcbiAgICAgICAgdmFyIHgwID0gTWF0aC5tYXgoeGEuYzJwKHhNaW4sIHRydWUpLCAwKTtcbiAgICAgICAgdmFyIHgxID0gTWF0aC5taW4oeGEuYzJwKHhNYXgsIHRydWUpLCB4TGVuKTtcbiAgICAgICAgdmFyIHkwID0gTWF0aC5tYXgoeWEuYzJwKHlNYXgsIHRydWUpLCAwKTtcbiAgICAgICAgdmFyIHkxID0gTWF0aC5taW4oeWEuYzJwKHlNaW4sIHRydWUpLCB5TGVuKTtcblxuICAgICAgICAvLyB2aXNpYmxlIGJvdW5kcyBvZiB0aGUgY29udG91ciB0cmFjZSAoYW5kIHRoZSBtaWRwb2ludHMsIHRvXG4gICAgICAgIC8vIGhlbHAgd2l0aCBjb3N0IGNhbGN1bGF0aW9ucylcbiAgICAgICAgdmFyIGJvdW5kcyA9IHt9O1xuXG4gICAgICAgIGlmKHhSbmdbMF0gPCB4Um5nWzFdKSB7XG4gICAgICAgICAgICBib3VuZHMubGVmdCA9IHgwO1xuICAgICAgICAgICAgYm91bmRzLnJpZ2h0ID0geDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBib3VuZHMubGVmdCA9IHgxO1xuICAgICAgICAgICAgYm91bmRzLnJpZ2h0ID0geDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZih5Um5nWzBdIDwgeVJuZ1sxXSkge1xuICAgICAgICAgICAgYm91bmRzLnRvcCA9IHkwO1xuICAgICAgICAgICAgYm91bmRzLmJvdHRvbSA9IHkxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYm91bmRzLnRvcCA9IHkxO1xuICAgICAgICAgICAgYm91bmRzLmJvdHRvbSA9IHkwO1xuICAgICAgICB9XG5cbiAgICAgICAgYm91bmRzLm1pZGRsZSA9IChib3VuZHMudG9wICsgYm91bmRzLmJvdHRvbSkgLyAyO1xuICAgICAgICBib3VuZHMuY2VudGVyID0gKGJvdW5kcy5sZWZ0ICsgYm91bmRzLnJpZ2h0KSAvIDI7XG5cbiAgICAgICAgbGFiZWxDbGlwUGF0aERhdGEucHVzaChbXG4gICAgICAgICAgICBbYm91bmRzLmxlZnQsIGJvdW5kcy50b3BdLFxuICAgICAgICAgICAgW2JvdW5kcy5yaWdodCwgYm91bmRzLnRvcF0sXG4gICAgICAgICAgICBbYm91bmRzLnJpZ2h0LCBib3VuZHMuYm90dG9tXSxcbiAgICAgICAgICAgIFtib3VuZHMubGVmdCwgYm91bmRzLmJvdHRvbV1cbiAgICAgICAgXSk7XG5cbiAgICAgICAgdmFyIHBsb3REaWFnb25hbCA9IE1hdGguc3FydCh4TGVuICogeExlbiArIHlMZW4gKiB5TGVuKTtcblxuICAgICAgICAvLyB0aGUgcGF0aCBsZW5ndGggdG8gdXNlIHRvIHNjYWxlIHRoZSBudW1iZXIgb2YgbGFiZWxzIHRvIGRyYXc6XG4gICAgICAgIHZhciBub3JtTGVuZ3RoID0gY29uc3RhbnRzLkxBQkVMRElTVEFOQ0UgKiBwbG90RGlhZ29uYWwgL1xuICAgICAgICAgICAgTWF0aC5tYXgoMSwgcGF0aGluZm8ubGVuZ3RoIC8gY29uc3RhbnRzLkxBQkVMSU5DUkVBU0UpO1xuXG4gICAgICAgIGxpbmVncm91cC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB0ZXh0T3B0cyA9IGV4cG9ydHMuY2FsY1RleHRPcHRzKGQubGV2ZWwsIGNvbnRvdXJGb3JtYXQsIGR1bW15VGV4dCwgZ2QpO1xuXG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdwYXRoJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0aCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGhCb3VuZHMgPSBMaWIuZ2V0VmlzaWJsZVNlZ21lbnQocGF0aCwgYm91bmRzLCB0ZXh0T3B0cy5oZWlnaHQgLyAyKTtcbiAgICAgICAgICAgICAgICBpZighcGF0aEJvdW5kcykgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgaWYocGF0aEJvdW5kcy5sZW4gPCAodGV4dE9wdHMud2lkdGggKyB0ZXh0T3B0cy5oZWlnaHQpICogY29uc3RhbnRzLkxBQkVMTUlOKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICB2YXIgbWF4TGFiZWxzID0gTWF0aC5taW4oTWF0aC5jZWlsKHBhdGhCb3VuZHMubGVuIC8gbm9ybUxlbmd0aCksXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0YW50cy5MQUJFTE1BWCk7XG5cbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbWF4TGFiZWxzOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxvYyA9IGV4cG9ydHMuZmluZEJlc3RUZXh0TG9jYXRpb24ocGF0aCwgcGF0aEJvdW5kcywgdGV4dE9wdHMsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYWJlbERhdGEsIGJvdW5kcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoIWxvYykgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0cy5hZGRMYWJlbERhdGEobG9jLCB0ZXh0T3B0cywgbGFiZWxEYXRhLCBsYWJlbENsaXBQYXRoRGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGR1bW15VGV4dC5yZW1vdmUoKTtcblxuICAgICAgICBleHBvcnRzLmRyYXdMYWJlbHMobGFiZWxHcm91cCwgbGFiZWxEYXRhLCBnZCwgbGluZUNsaXAsXG4gICAgICAgICAgICBjbGlwTGluZXNGb3JMYWJlbHMgPyBsYWJlbENsaXBQYXRoRGF0YSA6IG51bGwpO1xuICAgIH1cblxuICAgIGlmKHNob3dMYWJlbHMgJiYgIXNob3dMaW5lcykgbGluZWdyb3VwLnJlbW92ZSgpO1xufVxuXG5leHBvcnRzLmNyZWF0ZUxpbmVzID0gZnVuY3Rpb24obGluZUNvbnRhaW5lciwgbWFrZUxpbmVzLCBwYXRoaW5mbykge1xuICAgIHZhciBzbW9vdGhpbmcgPSBwYXRoaW5mb1swXS5zbW9vdGhpbmc7XG5cbiAgICB2YXIgbGluZWdyb3VwID0gbGluZUNvbnRhaW5lci5zZWxlY3RBbGwoJ2cuY29udG91cmxldmVsJylcbiAgICAgICAgLmRhdGEobWFrZUxpbmVzID8gcGF0aGluZm8gOiBbXSk7XG5cbiAgICBsaW5lZ3JvdXAuZXhpdCgpLnJlbW92ZSgpO1xuICAgIGxpbmVncm91cC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdjb250b3VybGV2ZWwnLCB0cnVlKTtcblxuICAgIGlmKG1ha2VMaW5lcykge1xuICAgICAgICAvLyBwZWRnZXBhdGhzIC8gcHBhdGhzIGFyZSB1c2VkIGJ5IGNvbnRvdXJjYXJwZXQsIGZvciB0aGUgcGF0aHMgdHJhbnNmb3JtZWQgZnJvbSBhL2IgdG8geC95XG4gICAgICAgIC8vIGVkZ2VwYXRocyAvIHBhdGhzIGFyZSB1c2VkIGJ5IGNvbnRvdXIgc2luY2UgaXQncyBpbiB4L3kgZnJvbSB0aGUgc3RhcnRcbiAgICAgICAgdmFyIG9wZW5jb250b3VybGluZXMgPSBsaW5lZ3JvdXAuc2VsZWN0QWxsKCdwYXRoLm9wZW5saW5lJylcbiAgICAgICAgICAgIC5kYXRhKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQucGVkZ2VwYXRocyB8fCBkLmVkZ2VwYXRoczsgfSk7XG5cbiAgICAgICAgb3BlbmNvbnRvdXJsaW5lcy5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIG9wZW5jb250b3VybGluZXMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgLmNsYXNzZWQoJ29wZW5saW5lJywgdHJ1ZSk7XG5cbiAgICAgICAgb3BlbmNvbnRvdXJsaW5lc1xuICAgICAgICAgICAgLmF0dHIoJ2QnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIERyYXdpbmcuc21vb3Rob3BlbihkLCBzbW9vdGhpbmcpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLW1pdGVybGltaXQnLCAxKVxuICAgICAgICAgICAgLnN0eWxlKCd2ZWN0b3ItZWZmZWN0JywgJ25vbi1zY2FsaW5nLXN0cm9rZScpO1xuXG4gICAgICAgIHZhciBjbG9zZWRjb250b3VybGluZXMgPSBsaW5lZ3JvdXAuc2VsZWN0QWxsKCdwYXRoLmNsb3NlZGxpbmUnKVxuICAgICAgICAgICAgLmRhdGEoZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5wcGF0aHMgfHwgZC5wYXRoczsgfSk7XG5cbiAgICAgICAgY2xvc2VkY29udG91cmxpbmVzLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgY2xvc2VkY29udG91cmxpbmVzLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdjbG9zZWRsaW5lJywgdHJ1ZSk7XG5cbiAgICAgICAgY2xvc2VkY29udG91cmxpbmVzXG4gICAgICAgICAgICAuYXR0cignZCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRHJhd2luZy5zbW9vdGhjbG9zZWQoZCwgc21vb3RoaW5nKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMSlcbiAgICAgICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbGluZWdyb3VwO1xufTtcblxuZXhwb3J0cy5jcmVhdGVMaW5lQ2xpcCA9IGZ1bmN0aW9uKGxpbmVDb250YWluZXIsIGNsaXBMaW5lc0ZvckxhYmVscywgZ2QsIHVpZCkge1xuICAgIHZhciBjbGlwcyA9IGdkLl9mdWxsTGF5b3V0Ll9jbGlwcztcbiAgICB2YXIgY2xpcElkID0gY2xpcExpbmVzRm9yTGFiZWxzID8gKCdjbGlwbGluZScgKyB1aWQpIDogbnVsbDtcblxuICAgIHZhciBsaW5lQ2xpcCA9IGNsaXBzLnNlbGVjdEFsbCgnIycgKyBjbGlwSWQpXG4gICAgICAgIC5kYXRhKGNsaXBMaW5lc0ZvckxhYmVscyA/IFswXSA6IFtdKTtcbiAgICBsaW5lQ2xpcC5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBsaW5lQ2xpcC5lbnRlcigpLmFwcGVuZCgnY2xpcFBhdGgnKVxuICAgICAgICAuY2xhc3NlZCgnY29udG91cmxpbmVjbGlwJywgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2lkJywgY2xpcElkKTtcblxuICAgIERyYXdpbmcuc2V0Q2xpcFVybChsaW5lQ29udGFpbmVyLCBjbGlwSWQsIGdkKTtcblxuICAgIHJldHVybiBsaW5lQ2xpcDtcbn07XG5cbmV4cG9ydHMubGFiZWxGb3JtYXR0ZXIgPSBmdW5jdGlvbihjb250b3VycywgY29sb3JiYXIsIGZ1bGxMYXlvdXQpIHtcbiAgICBpZihjb250b3Vycy5sYWJlbGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gZnVsbExheW91dC5fZDNsb2NhbGUubnVtYmVyRm9ybWF0KGNvbnRvdXJzLmxhYmVsZm9ybWF0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgZm9ybWF0QXhpcztcbiAgICAgICAgaWYoY29sb3JiYXIpIHtcbiAgICAgICAgICAgIGZvcm1hdEF4aXMgPSBjb2xvcmJhci5heGlzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZm9ybWF0QXhpcyA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgICAgICAgICBfaWQ6ICd5Y29udG91cicsXG4gICAgICAgICAgICAgICAgc2hvd2V4cG9uZW50OiAnYWxsJyxcbiAgICAgICAgICAgICAgICBleHBvbmVudGZvcm1hdDogJ0InXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZihjb250b3Vycy50eXBlID09PSAnY29uc3RyYWludCcpIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBjb250b3Vycy52YWx1ZTtcbiAgICAgICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3JtYXRBeGlzLnJhbmdlID0gW3ZhbHVlWzBdLCB2YWx1ZVt2YWx1ZS5sZW5ndGggLSAxXV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGZvcm1hdEF4aXMucmFuZ2UgPSBbdmFsdWUsIHZhbHVlXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0QXhpcy5yYW5nZSA9IFtjb250b3Vycy5zdGFydCwgY29udG91cnMuZW5kXTtcbiAgICAgICAgICAgICAgICBmb3JtYXRBeGlzLm50aWNrcyA9IChjb250b3Vycy5lbmQgLSBjb250b3Vycy5zdGFydCkgLyBjb250b3Vycy5zaXplO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihmb3JtYXRBeGlzLnJhbmdlWzBdID09PSBmb3JtYXRBeGlzLnJhbmdlWzFdKSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0QXhpcy5yYW5nZVsxXSArPSBmb3JtYXRBeGlzLnJhbmdlWzBdIHx8IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZighZm9ybWF0QXhpcy5udGlja3MpIGZvcm1hdEF4aXMubnRpY2tzID0gMTAwMDtcblxuICAgICAgICAgICAgc2V0Q29udmVydChmb3JtYXRBeGlzLCBmdWxsTGF5b3V0KTtcbiAgICAgICAgICAgIEF4ZXMucHJlcFRpY2tzKGZvcm1hdEF4aXMpO1xuICAgICAgICAgICAgZm9ybWF0QXhpcy5fdG1pbiA9IG51bGw7XG4gICAgICAgICAgICBmb3JtYXRBeGlzLl90bWF4ID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgcmV0dXJuIEF4ZXMudGlja1RleHQoZm9ybWF0QXhpcywgdikudGV4dDtcbiAgICAgICAgfTtcbiAgICB9XG59O1xuXG5leHBvcnRzLmNhbGNUZXh0T3B0cyA9IGZ1bmN0aW9uKGxldmVsLCBjb250b3VyRm9ybWF0LCBkdW1teVRleHQsIGdkKSB7XG4gICAgdmFyIHRleHQgPSBjb250b3VyRm9ybWF0KGxldmVsKTtcbiAgICBkdW1teVRleHQudGV4dCh0ZXh0KVxuICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG4gICAgdmFyIGJCb3ggPSBEcmF3aW5nLmJCb3goZHVtbXlUZXh0Lm5vZGUoKSwgdHJ1ZSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB0ZXh0OiB0ZXh0LFxuICAgICAgICB3aWR0aDogYkJveC53aWR0aCxcbiAgICAgICAgaGVpZ2h0OiBiQm94LmhlaWdodCxcbiAgICAgICAgbGV2ZWw6IGxldmVsLFxuICAgICAgICBkeTogKGJCb3gudG9wICsgYkJveC5ib3R0b20pIC8gMlxuICAgIH07XG59O1xuXG5leHBvcnRzLmZpbmRCZXN0VGV4dExvY2F0aW9uID0gZnVuY3Rpb24ocGF0aCwgcGF0aEJvdW5kcywgdGV4dE9wdHMsIGxhYmVsRGF0YSwgcGxvdEJvdW5kcykge1xuICAgIHZhciB0ZXh0V2lkdGggPSB0ZXh0T3B0cy53aWR0aDtcblxuICAgIHZhciBwMCwgZHAsIHBNYXgsIHBNaW4sIGxvYztcbiAgICBpZihwYXRoQm91bmRzLmlzQ2xvc2VkKSB7XG4gICAgICAgIGRwID0gcGF0aEJvdW5kcy5sZW4gLyBjb3N0Q29uc3RhbnRzLklOSVRJQUxTRUFSQ0hQT0lOVFM7XG4gICAgICAgIHAwID0gcGF0aEJvdW5kcy5taW4gKyBkcCAvIDI7XG4gICAgICAgIHBNYXggPSBwYXRoQm91bmRzLm1heDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkcCA9IChwYXRoQm91bmRzLmxlbiAtIHRleHRXaWR0aCkgLyAoY29zdENvbnN0YW50cy5JTklUSUFMU0VBUkNIUE9JTlRTICsgMSk7XG4gICAgICAgIHAwID0gcGF0aEJvdW5kcy5taW4gKyBkcCArIHRleHRXaWR0aCAvIDI7XG4gICAgICAgIHBNYXggPSBwYXRoQm91bmRzLm1heCAtIChkcCArIHRleHRXaWR0aCkgLyAyO1xuICAgIH1cblxuICAgIHZhciBjb3N0ID0gSW5maW5pdHk7XG4gICAgZm9yKHZhciBqID0gMDsgaiA8IGNvc3RDb25zdGFudHMuSVRFUkFUSU9OUzsgaisrKSB7XG4gICAgICAgIGZvcih2YXIgcCA9IHAwOyBwIDwgcE1heDsgcCArPSBkcCkge1xuICAgICAgICAgICAgdmFyIG5ld0xvY2F0aW9uID0gTGliLmdldFRleHRMb2NhdGlvbihwYXRoLCBwYXRoQm91bmRzLnRvdGFsLCBwLCB0ZXh0V2lkdGgpO1xuICAgICAgICAgICAgdmFyIG5ld0Nvc3QgPSBsb2NhdGlvbkNvc3QobmV3TG9jYXRpb24sIHRleHRPcHRzLCBsYWJlbERhdGEsIHBsb3RCb3VuZHMpO1xuICAgICAgICAgICAgaWYobmV3Q29zdCA8IGNvc3QpIHtcbiAgICAgICAgICAgICAgICBjb3N0ID0gbmV3Q29zdDtcbiAgICAgICAgICAgICAgICBsb2MgPSBuZXdMb2NhdGlvbjtcbiAgICAgICAgICAgICAgICBwTWluID0gcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZihjb3N0ID4gY29zdENvbnN0YW50cy5NQVhDT1NUICogMikgYnJlYWs7XG5cbiAgICAgICAgLy8gc3Vic2VxdWVudCBpdGVyYXRpb25zIGp1c3QgbG9vayBoYWxmIHN0ZXBzIGF3YXkgZnJvbSB0aGVcbiAgICAgICAgLy8gYmVzdCB3ZSBmb3VuZCBpbiB0aGUgcHJldmlvdXMgaXRlcmF0aW9uXG4gICAgICAgIGlmKGopIGRwIC89IDI7XG4gICAgICAgIHAwID0gcE1pbiAtIGRwIC8gMjtcbiAgICAgICAgcE1heCA9IHAwICsgZHAgKiAxLjU7XG4gICAgfVxuICAgIGlmKGNvc3QgPD0gY29zdENvbnN0YW50cy5NQVhDT1NUKSByZXR1cm4gbG9jO1xufTtcblxuLypcbiAqIGxvY2F0aW9uQ29zdDogYSBjb3N0IGZ1bmN0aW9uIGZvciBsYWJlbCBsb2NhdGlvbnNcbiAqIGNvbXBvc2VkIG9mIHRocmVlIGtpbmRzIG9mIHBlbmFsdHk6XG4gKiAtIGZvciBvcGVuIHBhdGhzLCBiZWluZyBjbG9zZSB0byB0aGUgZW5kIG9mIHRoZSBwYXRoXG4gKiAtIHRoZSBhbmdsZSBhd2F5IGZyb20gaG9yaXpvbnRhbFxuICogLSBiZWluZyB0b28gY2xvc2UgdG8gYWxyZWFkeSBwbGFjZWQgbmVpZ2hib3JzXG4gKi9cbmZ1bmN0aW9uIGxvY2F0aW9uQ29zdChsb2MsIHRleHRPcHRzLCBsYWJlbERhdGEsIGJvdW5kcykge1xuICAgIHZhciBoYWxmV2lkdGggPSB0ZXh0T3B0cy53aWR0aCAvIDI7XG4gICAgdmFyIGhhbGZIZWlnaHQgPSB0ZXh0T3B0cy5oZWlnaHQgLyAyO1xuICAgIHZhciB4ID0gbG9jLng7XG4gICAgdmFyIHkgPSBsb2MueTtcbiAgICB2YXIgdGhldGEgPSBsb2MudGhldGE7XG4gICAgdmFyIGR4ID0gTWF0aC5jb3ModGhldGEpICogaGFsZldpZHRoO1xuICAgIHZhciBkeSA9IE1hdGguc2luKHRoZXRhKSAqIGhhbGZXaWR0aDtcblxuICAgIC8vIGNvc3QgZm9yIGJlaW5nIG5lYXIgYW4gZWRnZVxuICAgIHZhciBub3JtWCA9ICgoeCA+IGJvdW5kcy5jZW50ZXIpID8gKGJvdW5kcy5yaWdodCAtIHgpIDogKHggLSBib3VuZHMubGVmdCkpIC9cbiAgICAgICAgKGR4ICsgTWF0aC5hYnMoTWF0aC5zaW4odGhldGEpICogaGFsZkhlaWdodCkpO1xuICAgIHZhciBub3JtWSA9ICgoeSA+IGJvdW5kcy5taWRkbGUpID8gKGJvdW5kcy5ib3R0b20gLSB5KSA6ICh5IC0gYm91bmRzLnRvcCkpIC9cbiAgICAgICAgKE1hdGguYWJzKGR5KSArIE1hdGguY29zKHRoZXRhKSAqIGhhbGZIZWlnaHQpO1xuICAgIGlmKG5vcm1YIDwgMSB8fCBub3JtWSA8IDEpIHJldHVybiBJbmZpbml0eTtcbiAgICB2YXIgY29zdCA9IGNvc3RDb25zdGFudHMuRURHRUNPU1QgKiAoMSAvIChub3JtWCAtIDEpICsgMSAvIChub3JtWSAtIDEpKTtcblxuICAgIC8vIGNvc3QgZm9yIG5vdCBiZWluZyBob3Jpem9udGFsXG4gICAgY29zdCArPSBjb3N0Q29uc3RhbnRzLkFOR0xFQ09TVCAqIHRoZXRhICogdGhldGE7XG5cbiAgICAvLyBjb3N0IGZvciBiZWluZyBjbG9zZSB0byBvdGhlciBsYWJlbHNcbiAgICB2YXIgeDEgPSB4IC0gZHg7XG4gICAgdmFyIHkxID0geSAtIGR5O1xuICAgIHZhciB4MiA9IHggKyBkeDtcbiAgICB2YXIgeTIgPSB5ICsgZHk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxhYmVsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbGFiZWxpID0gbGFiZWxEYXRhW2ldO1xuICAgICAgICB2YXIgZHhkID0gTWF0aC5jb3MobGFiZWxpLnRoZXRhKSAqIGxhYmVsaS53aWR0aCAvIDI7XG4gICAgICAgIHZhciBkeWQgPSBNYXRoLnNpbihsYWJlbGkudGhldGEpICogbGFiZWxpLndpZHRoIC8gMjtcbiAgICAgICAgdmFyIGRpc3QgPSBMaWIuc2VnbWVudERpc3RhbmNlKFxuICAgICAgICAgICAgeDEsIHkxLFxuICAgICAgICAgICAgeDIsIHkyLFxuICAgICAgICAgICAgbGFiZWxpLnggLSBkeGQsIGxhYmVsaS55IC0gZHlkLFxuICAgICAgICAgICAgbGFiZWxpLnggKyBkeGQsIGxhYmVsaS55ICsgZHlkXG4gICAgICAgICkgKiAyIC8gKHRleHRPcHRzLmhlaWdodCArIGxhYmVsaS5oZWlnaHQpO1xuXG4gICAgICAgIHZhciBzYW1lTGV2ZWwgPSBsYWJlbGkubGV2ZWwgPT09IHRleHRPcHRzLmxldmVsO1xuICAgICAgICB2YXIgZGlzdE9mZnNldCA9IHNhbWVMZXZlbCA/IGNvc3RDb25zdGFudHMuU0FNRUxFVkVMRElTVEFOQ0UgOiAxO1xuXG4gICAgICAgIGlmKGRpc3QgPD0gZGlzdE9mZnNldCkgcmV0dXJuIEluZmluaXR5O1xuXG4gICAgICAgIHZhciBkaXN0RmFjdG9yID0gY29zdENvbnN0YW50cy5ORUlHSEJPUkNPU1QgKlxuICAgICAgICAgICAgKHNhbWVMZXZlbCA/IGNvc3RDb25zdGFudHMuU0FNRUxFVkVMRkFDVE9SIDogMSk7XG5cbiAgICAgICAgY29zdCArPSBkaXN0RmFjdG9yIC8gKGRpc3QgLSBkaXN0T2Zmc2V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29zdDtcbn1cblxuZXhwb3J0cy5hZGRMYWJlbERhdGEgPSBmdW5jdGlvbihsb2MsIHRleHRPcHRzLCBsYWJlbERhdGEsIGxhYmVsQ2xpcFBhdGhEYXRhKSB7XG4gICAgdmFyIGhhbGZXaWR0aCA9IHRleHRPcHRzLndpZHRoIC8gMjtcbiAgICB2YXIgaGFsZkhlaWdodCA9IHRleHRPcHRzLmhlaWdodCAvIDI7XG5cbiAgICB2YXIgeCA9IGxvYy54O1xuICAgIHZhciB5ID0gbG9jLnk7XG4gICAgdmFyIHRoZXRhID0gbG9jLnRoZXRhO1xuXG4gICAgdmFyIHNpbiA9IE1hdGguc2luKHRoZXRhKTtcbiAgICB2YXIgY29zID0gTWF0aC5jb3ModGhldGEpO1xuICAgIHZhciBkeHcgPSBoYWxmV2lkdGggKiBjb3M7XG4gICAgdmFyIGR4aCA9IGhhbGZIZWlnaHQgKiBzaW47XG4gICAgdmFyIGR5dyA9IGhhbGZXaWR0aCAqIHNpbjtcbiAgICB2YXIgZHloID0gLWhhbGZIZWlnaHQgKiBjb3M7XG4gICAgdmFyIGJCb3hQdHMgPSBbXG4gICAgICAgIFt4IC0gZHh3IC0gZHhoLCB5IC0gZHl3IC0gZHloXSxcbiAgICAgICAgW3ggKyBkeHcgLSBkeGgsIHkgKyBkeXcgLSBkeWhdLFxuICAgICAgICBbeCArIGR4dyArIGR4aCwgeSArIGR5dyArIGR5aF0sXG4gICAgICAgIFt4IC0gZHh3ICsgZHhoLCB5IC0gZHl3ICsgZHloXSxcbiAgICBdO1xuXG4gICAgbGFiZWxEYXRhLnB1c2goe1xuICAgICAgICB0ZXh0OiB0ZXh0T3B0cy50ZXh0LFxuICAgICAgICB4OiB4LFxuICAgICAgICB5OiB5LFxuICAgICAgICBkeTogdGV4dE9wdHMuZHksXG4gICAgICAgIHRoZXRhOiB0aGV0YSxcbiAgICAgICAgbGV2ZWw6IHRleHRPcHRzLmxldmVsLFxuICAgICAgICB3aWR0aDogdGV4dE9wdHMud2lkdGgsXG4gICAgICAgIGhlaWdodDogdGV4dE9wdHMuaGVpZ2h0XG4gICAgfSk7XG5cbiAgICBsYWJlbENsaXBQYXRoRGF0YS5wdXNoKGJCb3hQdHMpO1xufTtcblxuZXhwb3J0cy5kcmF3TGFiZWxzID0gZnVuY3Rpb24obGFiZWxHcm91cCwgbGFiZWxEYXRhLCBnZCwgbGluZUNsaXAsIGxhYmVsQ2xpcFBhdGhEYXRhKSB7XG4gICAgdmFyIGxhYmVscyA9IGxhYmVsR3JvdXAuc2VsZWN0QWxsKCd0ZXh0JylcbiAgICAgICAgLmRhdGEobGFiZWxEYXRhLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC50ZXh0ICsgJywnICsgZC54ICsgJywnICsgZC55ICsgJywnICsgZC50aGV0YTtcbiAgICAgICAgfSk7XG5cbiAgICBsYWJlbHMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgbGFiZWxzLmVudGVyKCkuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgJ2RhdGEtbm90ZXgnOiAxLFxuICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSdcbiAgICAgICAgfSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHggPSBkLnggKyBNYXRoLnNpbihkLnRoZXRhKSAqIGQuZHk7XG4gICAgICAgICAgICB2YXIgeSA9IGQueSAtIE1hdGguY29zKGQudGhldGEpICogZC5keTtcbiAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgICAgIC50ZXh0KGQudGV4dClcbiAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgIHg6IHgsXG4gICAgICAgICAgICAgICAgICAgIHk6IHksXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJ3JvdGF0ZSgnICsgKDE4MCAqIGQudGhldGEgLyBNYXRoLlBJKSArICcgJyArIHggKyAnICcgKyB5ICsgJyknXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG4gICAgICAgIH0pO1xuXG4gICAgaWYobGFiZWxDbGlwUGF0aERhdGEpIHtcbiAgICAgICAgdmFyIGNsaXBQYXRoID0gJyc7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsYWJlbENsaXBQYXRoRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2xpcFBhdGggKz0gJ00nICsgbGFiZWxDbGlwUGF0aERhdGFbaV0uam9pbignTCcpICsgJ1onO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxpbmVDbGlwUGF0aCA9IExpYi5lbnN1cmVTaW5nbGUobGluZUNsaXAsICdwYXRoJywgJycpO1xuICAgICAgICBsaW5lQ2xpcFBhdGguYXR0cignZCcsIGNsaXBQYXRoKTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBjbGlwR2FwcyhwbG90R3JvdXAsIHBsb3RpbmZvLCBnZCwgY2QwLCBwZXJpbWV0ZXIpIHtcbiAgICB2YXIgY2xpcHMgPSBnZC5fZnVsbExheW91dC5fY2xpcHM7XG4gICAgdmFyIGNsaXBJZCA9ICdjbGlwJyArIGNkMC50cmFjZS51aWQ7XG5cbiAgICB2YXIgY2xpcFBhdGggPSBjbGlwcy5zZWxlY3RBbGwoJyMnICsgY2xpcElkKVxuICAgICAgICAuZGF0YShjZDAudHJhY2UuY29ubmVjdGdhcHMgPyBbXSA6IFswXSk7XG4gICAgY2xpcFBhdGguZW50ZXIoKS5hcHBlbmQoJ2NsaXBQYXRoJylcbiAgICAgICAgLmNsYXNzZWQoJ2NvbnRvdXJjbGlwJywgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2lkJywgY2xpcElkKTtcbiAgICBjbGlwUGF0aC5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBpZihjZDAudHJhY2UuY29ubmVjdGdhcHMgPT09IGZhbHNlKSB7XG4gICAgICAgIHZhciBjbGlwUGF0aEluZm8gPSB7XG4gICAgICAgICAgICAvLyBmcmFjdGlvbiBvZiB0aGUgd2F5IGZyb20gbWlzc2luZyB0byBwcmVzZW50IHBvaW50XG4gICAgICAgICAgICAvLyB0byBkcmF3IHRoZSBib3VuZGFyeS5cbiAgICAgICAgICAgIC8vIGlmIHlvdSBtYWtlIHRoaXMgMSAob3IgMS1lcHNpbG9uKSB0aGVuIGEgcG9pbnQgaW5cbiAgICAgICAgICAgIC8vIGEgc2VhIG9mIG1pc3NpbmcgZGF0YSB3aWxsIGRpc2FwcGVhciBlbnRpcmVseS5cbiAgICAgICAgICAgIGxldmVsOiAwLjksXG4gICAgICAgICAgICBjcm9zc2luZ3M6IHt9LFxuICAgICAgICAgICAgc3RhcnRzOiBbXSxcbiAgICAgICAgICAgIGVkZ2VwYXRoczogW10sXG4gICAgICAgICAgICBwYXRoczogW10sXG4gICAgICAgICAgICB4YXhpczogcGxvdGluZm8ueGF4aXMsXG4gICAgICAgICAgICB5YXhpczogcGxvdGluZm8ueWF4aXMsXG4gICAgICAgICAgICB4OiBjZDAueCxcbiAgICAgICAgICAgIHk6IGNkMC55LFxuICAgICAgICAgICAgLy8gMCA9IG5vIGRhdGEsIDEgPSBkYXRhXG4gICAgICAgICAgICB6OiBtYWtlQ2xpcE1hc2soY2QwKSxcbiAgICAgICAgICAgIHNtb290aGluZzogMFxuICAgICAgICB9O1xuXG4gICAgICAgIG1ha2VDcm9zc2luZ3MoW2NsaXBQYXRoSW5mb10pO1xuICAgICAgICBmaW5kQWxsUGF0aHMoW2NsaXBQYXRoSW5mb10pO1xuICAgICAgICB2YXIgZnVsbHBhdGggPSBqb2luQWxsUGF0aHMoY2xpcFBhdGhJbmZvLCBwZXJpbWV0ZXIpO1xuXG4gICAgICAgIHZhciBwYXRoID0gTGliLmVuc3VyZVNpbmdsZShjbGlwUGF0aCwgJ3BhdGgnLCAnJyk7XG4gICAgICAgIHBhdGguYXR0cignZCcsIGZ1bGxwYXRoKTtcbiAgICB9IGVsc2UgY2xpcElkID0gbnVsbDtcblxuICAgIERyYXdpbmcuc2V0Q2xpcFVybChwbG90R3JvdXAsIGNsaXBJZCwgZ2QpO1xufVxuXG5mdW5jdGlvbiBtYWtlQ2xpcE1hc2soY2QwKSB7XG4gICAgdmFyIGVtcHRpZXMgPSBjZDAudHJhY2UuX2VtcHR5cG9pbnRzO1xuICAgIHZhciB6ID0gW107XG4gICAgdmFyIG0gPSBjZDAuei5sZW5ndGg7XG4gICAgdmFyIG4gPSBjZDAuelswXS5sZW5ndGg7XG4gICAgdmFyIGk7XG4gICAgdmFyIHJvdyA9IFtdO1xuICAgIHZhciBlbXB0eVBvaW50O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgbjsgaSsrKSByb3cucHVzaCgxKTtcbiAgICBmb3IoaSA9IDA7IGkgPCBtOyBpKyspIHoucHVzaChyb3cuc2xpY2UoKSk7XG4gICAgZm9yKGkgPSAwOyBpIDwgZW1wdGllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBlbXB0eVBvaW50ID0gZW1wdGllc1tpXTtcbiAgICAgICAgeltlbXB0eVBvaW50WzBdXVtlbXB0eVBvaW50WzFdXSA9IDA7XG4gICAgfVxuICAgIC8vIHNhdmUgdGhpcyBtYXNrIHRvIGRldGVybWluZSB3aGV0aGVyIHRvIHNob3cgdGhpcyBkYXRhIGluIGhvdmVyXG4gICAgY2QwLnptYXNrID0gejtcbiAgICByZXR1cm4gejtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHNcIjo3NDMsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9zZXRfY29udmVydFwiOjc4NSxcIi4uL2hlYXRtYXAvcGxvdFwiOjEwMTIsXCIuL2Nsb3NlX2JvdW5kYXJpZXNcIjo5NDQsXCIuL2NvbnN0YW50c1wiOjk0NixcIi4vY29udmVydF90b19jb25zdHJhaW50c1wiOjk1MCxcIi4vZW1wdHlfcGF0aGluZm9cIjo5NTIsXCIuL2ZpbmRfYWxsX3BhdGhzXCI6OTU0LFwiLi9tYWtlX2Nyb3NzaW5nc1wiOjk1OSxcImQzXCI6MTYzfV0sOTYxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNldENvbnRvdXJzKHRyYWNlLCB2YWxzKSB7XG4gICAgdmFyIGNvbnRvdXJzID0gdHJhY2UuY29udG91cnM7XG5cbiAgICAvLyBjaGVjayBpZiB3ZSBuZWVkIHRvIGF1dG8tY2hvb3NlIGNvbnRvdXIgbGV2ZWxzXG4gICAgaWYodHJhY2UuYXV0b2NvbnRvdXIpIHtcbiAgICAgICAgLy8gTi5CLiBkbyBub3QgdHJ5IHRvIHVzZSBjb2xvcmF4aXMgY21pbi9jbWF4LFxuICAgICAgICAvLyB0aGVzZSB2YWx1ZXMgaGVyZSBhcmUgbWVhbnQgdG8gcmVtYWluIFwicGVyLXRyYWNlXCIgZm9yIG5vd1xuICAgICAgICB2YXIgem1pbiA9IHRyYWNlLnptaW47XG4gICAgICAgIHZhciB6bWF4ID0gdHJhY2Uuem1heDtcbiAgICAgICAgaWYodHJhY2UuemF1dG8gfHwgem1pbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB6bWluID0gTGliLmFnZ051bXMoTWF0aC5taW4sIG51bGwsIHZhbHMpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHRyYWNlLnphdXRvIHx8IHptYXggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgem1heCA9IExpYi5hZ2dOdW1zKE1hdGgubWF4LCBudWxsLCB2YWxzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkdW1teUF4ID0gYXV0b0NvbnRvdXJzKHptaW4sIHptYXgsIHRyYWNlLm5jb250b3Vycyk7XG4gICAgICAgIGNvbnRvdXJzLnNpemUgPSBkdW1teUF4LmR0aWNrO1xuICAgICAgICBjb250b3Vycy5zdGFydCA9IEF4ZXMudGlja0ZpcnN0KGR1bW15QXgpO1xuICAgICAgICBkdW1teUF4LnJhbmdlLnJldmVyc2UoKTtcbiAgICAgICAgY29udG91cnMuZW5kID0gQXhlcy50aWNrRmlyc3QoZHVtbXlBeCk7XG5cbiAgICAgICAgaWYoY29udG91cnMuc3RhcnQgPT09IHptaW4pIGNvbnRvdXJzLnN0YXJ0ICs9IGNvbnRvdXJzLnNpemU7XG4gICAgICAgIGlmKGNvbnRvdXJzLmVuZCA9PT0gem1heCkgY29udG91cnMuZW5kIC09IGNvbnRvdXJzLnNpemU7XG5cbiAgICAgICAgLy8gaWYgeW91IHNldCBhIHNtYWxsIG5jb250b3VycywgKmFuZCogdGhlIGVuZHMgYXJlIGV4YWN0bHkgb24gem1pbi96bWF4XG4gICAgICAgIC8vIHRoZXJlJ3MgYW4gZWRnZSBjYXNlIHdoZXJlIHN0YXJ0ID4gZW5kIG5vdy4gTWFrZSBzdXJlIHRoZXJlJ3MgYXQgbGVhc3RcbiAgICAgICAgLy8gb25lIG1lYW5pbmdmdWwgY29udG91ciwgcHV0IGl0IG1pZHdheSBiZXR3ZWVuIHRoZSBjcm9zc2VkIHZhbHVlc1xuICAgICAgICBpZihjb250b3Vycy5zdGFydCA+IGNvbnRvdXJzLmVuZCkge1xuICAgICAgICAgICAgY29udG91cnMuc3RhcnQgPSBjb250b3Vycy5lbmQgPSAoY29udG91cnMuc3RhcnQgKyBjb250b3Vycy5lbmQpIC8gMjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNvcHkgYXV0by1jb250b3VyIGluZm8gYmFjayB0byB0aGUgc291cmNlIGRhdGEuXG4gICAgICAgIC8vIHByZXZpb3VzbHkgd2UgY29waWVkIHRoZSB3aG9sZSBjb250b3VycyBvYmplY3QgYmFjaywgYnV0IHRoYXQgaGFkXG4gICAgICAgIC8vIG90aGVyIGluZm8gKGNvbG9yaW5nLCBzaG93bGluZXMpIHRoYXQgc2hvdWxkIGJlIGxlZnQgdG8gc3VwcGx5RGVmYXVsdHNcbiAgICAgICAgaWYoIXRyYWNlLl9pbnB1dC5jb250b3VycykgdHJhY2UuX2lucHV0LmNvbnRvdXJzID0ge307XG4gICAgICAgIExpYi5leHRlbmRGbGF0KHRyYWNlLl9pbnB1dC5jb250b3Vycywge1xuICAgICAgICAgICAgc3RhcnQ6IGNvbnRvdXJzLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiBjb250b3Vycy5lbmQsXG4gICAgICAgICAgICBzaXplOiBjb250b3Vycy5zaXplXG4gICAgICAgIH0pO1xuICAgICAgICB0cmFjZS5faW5wdXQuYXV0b2NvbnRvdXIgPSB0cnVlO1xuICAgIH0gZWxzZSBpZihjb250b3Vycy50eXBlICE9PSAnY29uc3RyYWludCcpIHtcbiAgICAgICAgLy8gc2FuaXR5IGNoZWNrcyBvbiBtYW51YWxseS1zdXBwbGllZCBzdGFydC9lbmQvc2l6ZVxuICAgICAgICB2YXIgc3RhcnQgPSBjb250b3Vycy5zdGFydDtcbiAgICAgICAgdmFyIGVuZCA9IGNvbnRvdXJzLmVuZDtcbiAgICAgICAgdmFyIGlucHV0Q29udG91cnMgPSB0cmFjZS5faW5wdXQuY29udG91cnM7XG5cbiAgICAgICAgaWYoc3RhcnQgPiBlbmQpIHtcbiAgICAgICAgICAgIGNvbnRvdXJzLnN0YXJ0ID0gaW5wdXRDb250b3Vycy5zdGFydCA9IGVuZDtcbiAgICAgICAgICAgIGVuZCA9IGNvbnRvdXJzLmVuZCA9IGlucHV0Q29udG91cnMuZW5kID0gc3RhcnQ7XG4gICAgICAgICAgICBzdGFydCA9IGNvbnRvdXJzLnN0YXJ0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoIShjb250b3Vycy5zaXplID4gMCkpIHtcbiAgICAgICAgICAgIHZhciBzaXplT3V0O1xuICAgICAgICAgICAgaWYoc3RhcnQgPT09IGVuZCkgc2l6ZU91dCA9IDE7XG4gICAgICAgICAgICBlbHNlIHNpemVPdXQgPSBhdXRvQ29udG91cnMoc3RhcnQsIGVuZCwgdHJhY2UubmNvbnRvdXJzKS5kdGljaztcblxuICAgICAgICAgICAgaW5wdXRDb250b3Vycy5zaXplID0gY29udG91cnMuc2l6ZSA9IHNpemVPdXQ7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5cbi8qXG4gKiBhdXRvQ29udG91cnM6IG1ha2UgYSBkdW1teSBheGlzIG9iamVjdCB3aXRoIGR0aWNrIHdlIGNhbiB1c2VcbiAqIGFzIGNvbnRvdXJzLnNpemUsIGFuZCBpZiBuZWVkZWQgd2UgY2FuIHVzZSBBeGVzLnRpY2tGaXJzdFxuICogd2l0aCB0aGlzIGF4aXMgb2JqZWN0IHRvIGNhbGN1bGF0ZSB0aGUgc3RhcnQgYW5kIGVuZCB0b29cbiAqXG4gKiBzdGFydDogdGhlIHZhbHVlIHRvIHN0YXJ0IHRoZSBjb250b3VycyBhdFxuICogZW5kOiB0aGUgdmFsdWUgdG8gZW5kIGF0IChtdXN0IGJlID4gc3RhcnQpXG4gKiBuY29udG91cnM6IG1heCBudW1iZXIgb2YgY29udG91cnMgdG8gbWFrZSwgbGlrZSByb3VnaERUaWNrXG4gKlxuICogcmV0dXJuczogYW4gYXhpcyBvYmplY3RcbiAqL1xuZnVuY3Rpb24gYXV0b0NvbnRvdXJzKHN0YXJ0LCBlbmQsIG5jb250b3Vycykge1xuICAgIHZhciBkdW1teUF4ID0ge1xuICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgcmFuZ2U6IFtzdGFydCwgZW5kXVxuICAgIH07XG5cbiAgICBBeGVzLmF1dG9UaWNrcyhcbiAgICAgICAgZHVtbXlBeCxcbiAgICAgICAgKGVuZCAtIHN0YXJ0KSAvIChuY29udG91cnMgfHwgMTUpXG4gICAgKTtcblxuICAgIHJldHVybiBkdW1teUF4O1xufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3fV0sOTYyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIGhlYXRtYXBTdHlsZSA9IF9kZXJlcV8oJy4uL2hlYXRtYXAvc3R5bGUnKTtcblxudmFyIG1ha2VDb2xvck1hcCA9IF9kZXJlcV8oJy4vbWFrZV9jb2xvcl9tYXAnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN0eWxlKGdkKSB7XG4gICAgdmFyIGNvbnRvdXJzID0gZDMuc2VsZWN0KGdkKS5zZWxlY3RBbGwoJ2cuY29udG91cicpO1xuXG4gICAgY29udG91cnMuc3R5bGUoJ29wYWNpdHknLCBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBkWzBdLnRyYWNlLm9wYWNpdHk7XG4gICAgfSk7XG5cbiAgICBjb250b3Vycy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGMgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciB0cmFjZSA9IGRbMF0udHJhY2U7XG4gICAgICAgIHZhciBjb250b3VycyA9IHRyYWNlLmNvbnRvdXJzO1xuICAgICAgICB2YXIgbGluZSA9IHRyYWNlLmxpbmU7XG4gICAgICAgIHZhciBjcyA9IGNvbnRvdXJzLnNpemUgfHwgMTtcbiAgICAgICAgdmFyIHN0YXJ0ID0gY29udG91cnMuc3RhcnQ7XG5cbiAgICAgICAgLy8gZm9yIGNvbnRvdXJjYXJwZXQgb25seSAtIGlzIHRoaXMgYSBjb25zdHJhaW50LXR5cGUgY29udG91ciB0cmFjZT9cbiAgICAgICAgdmFyIGlzQ29uc3RyYWludFR5cGUgPSBjb250b3Vycy50eXBlID09PSAnY29uc3RyYWludCc7XG4gICAgICAgIHZhciBjb2xvckxpbmVzID0gIWlzQ29uc3RyYWludFR5cGUgJiYgY29udG91cnMuY29sb3JpbmcgPT09ICdsaW5lcyc7XG4gICAgICAgIHZhciBjb2xvckZpbGxzID0gIWlzQ29uc3RyYWludFR5cGUgJiYgY29udG91cnMuY29sb3JpbmcgPT09ICdmaWxsJztcblxuICAgICAgICB2YXIgY29sb3JNYXAgPSAoY29sb3JMaW5lcyB8fCBjb2xvckZpbGxzKSA/IG1ha2VDb2xvck1hcCh0cmFjZSkgOiBudWxsO1xuXG4gICAgICAgIGMuc2VsZWN0QWxsKCdnLmNvbnRvdXJsZXZlbCcpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgncGF0aCcpXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5saW5lR3JvdXBTdHlsZSxcbiAgICAgICAgICAgICAgICAgICAgbGluZS53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgY29sb3JMaW5lcyA/IGNvbG9yTWFwKGQubGV2ZWwpIDogbGluZS5jb2xvcixcbiAgICAgICAgICAgICAgICAgICAgbGluZS5kYXNoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGxhYmVsRm9udCA9IGNvbnRvdXJzLmxhYmVsZm9udDtcbiAgICAgICAgYy5zZWxlY3RBbGwoJ2cuY29udG91cmxhYmVscyB0ZXh0JykuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBEcmF3aW5nLmZvbnQoZDMuc2VsZWN0KHRoaXMpLCB7XG4gICAgICAgICAgICAgICAgZmFtaWx5OiBsYWJlbEZvbnQuZmFtaWx5LFxuICAgICAgICAgICAgICAgIHNpemU6IGxhYmVsRm9udC5zaXplLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBsYWJlbEZvbnQuY29sb3IgfHwgKGNvbG9yTGluZXMgPyBjb2xvck1hcChkLmxldmVsKSA6IGxpbmUuY29sb3IpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYoaXNDb25zdHJhaW50VHlwZSkge1xuICAgICAgICAgICAgYy5zZWxlY3RBbGwoJ2cuY29udG91cmZpbGwgcGF0aCcpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgdHJhY2UuZmlsbGNvbG9yKTtcbiAgICAgICAgfSBlbHNlIGlmKGNvbG9yRmlsbHMpIHtcbiAgICAgICAgICAgIHZhciBmaXJzdEZpbGw7XG5cbiAgICAgICAgICAgIGMuc2VsZWN0QWxsKCdnLmNvbnRvdXJmaWxsIHBhdGgnKVxuICAgICAgICAgICAgICAgIC5zdHlsZSgnZmlsbCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoZmlyc3RGaWxsID09PSB1bmRlZmluZWQpIGZpcnN0RmlsbCA9IGQubGV2ZWw7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb2xvck1hcChkLmxldmVsICsgMC41ICogY3MpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZihmaXJzdEZpbGwgPT09IHVuZGVmaW5lZCkgZmlyc3RGaWxsID0gc3RhcnQ7XG5cbiAgICAgICAgICAgIGMuc2VsZWN0QWxsKCdnLmNvbnRvdXJiZyBwYXRoJylcbiAgICAgICAgICAgICAgICAuc3R5bGUoJ2ZpbGwnLCBjb2xvck1hcChmaXJzdEZpbGwgLSAwLjUgKiBjcykpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBoZWF0bWFwU3R5bGUoZ2QpO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi9oZWF0bWFwL3N0eWxlXCI6MTAxMyxcIi4vbWFrZV9jb2xvcl9tYXBcIjo5NTgsXCJkM1wiOjE2M31dLDk2MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxhYmVsRGVmYXVsdHMgPSBfZGVyZXFfKCcuL2xhYmVsX2RlZmF1bHRzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCwgb3B0cykge1xuICAgIHZhciBjb2xvcmluZyA9IGNvZXJjZSgnY29udG91cnMuY29sb3JpbmcnKTtcblxuICAgIHZhciBzaG93TGluZXM7XG4gICAgdmFyIGxpbmVDb2xvciA9ICcnO1xuICAgIGlmKGNvbG9yaW5nID09PSAnZmlsbCcpIHNob3dMaW5lcyA9IGNvZXJjZSgnY29udG91cnMuc2hvd2xpbmVzJyk7XG5cbiAgICBpZihzaG93TGluZXMgIT09IGZhbHNlKSB7XG4gICAgICAgIGlmKGNvbG9yaW5nICE9PSAnbGluZXMnKSBsaW5lQ29sb3IgPSBjb2VyY2UoJ2xpbmUuY29sb3InLCAnIzAwMCcpO1xuICAgICAgICBjb2VyY2UoJ2xpbmUud2lkdGgnLCAwLjUpO1xuICAgICAgICBjb2VyY2UoJ2xpbmUuZGFzaCcpO1xuICAgIH1cblxuICAgIGlmKGNvbG9yaW5nICE9PSAnbm9uZScpIHtcbiAgICAgICAgLy8gcGxvdHMvcGxvdHMgYWx3YXlzIGNvZXJjZXMgc2hvd2xlZ2VuZCB0byB0cnVlLCBidXQgaW4gdGhpcyBjYXNlXG4gICAgICAgIC8vIHdlIGRlZmF1bHQgdG8gZmFsc2UgYW5kIChieSBkZWZhdWx0KSBzaG93IGEgY29sb3JiYXIgaW5zdGVhZFxuICAgICAgICBpZih0cmFjZUluLnNob3dsZWdlbmQgIT09IHRydWUpIHRyYWNlT3V0LnNob3dsZWdlbmQgPSBmYWxzZTtcbiAgICAgICAgdHJhY2VPdXQuX2RmbHRTaG93TGVnZW5kID0gZmFsc2U7XG5cbiAgICAgICAgY29sb3JzY2FsZURlZmF1bHRzKFxuICAgICAgICAgICAgdHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnJywgY0xldHRlcjogJ3onfVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGNvZXJjZSgnbGluZS5zbW9vdGhpbmcnKTtcblxuICAgIGhhbmRsZUxhYmVsRGVmYXVsdHMoY29lcmNlLCBsYXlvdXQsIGxpbmVDb2xvciwgb3B0cyk7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0c1wiOjYwMyxcIi4vbGFiZWxfZGVmYXVsdHNcIjo5NTd9XSw5NjQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVhdG1hcEF0dHJzID0gX2RlcmVxXygnLi4vaGVhdG1hcC9hdHRyaWJ1dGVzJyk7XG52YXIgY29udG91ckF0dHJzID0gX2RlcmVxXygnLi4vY29udG91ci9hdHRyaWJ1dGVzJyk7XG52YXIgY29udG91ckNvbnRvdXJBdHRycyA9IGNvbnRvdXJBdHRycy5jb250b3VycztcbnZhciBzY2F0dGVyQXR0cnMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xuXG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG52YXIgc2NhdHRlckxpbmVBdHRycyA9IHNjYXR0ZXJBdHRycy5saW5lO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGV4dGVuZEZsYXQoe1xuICAgIGNhcnBldDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgejogaGVhdG1hcEF0dHJzLnosXG4gICAgYTogaGVhdG1hcEF0dHJzLngsXG4gICAgYTA6IGhlYXRtYXBBdHRycy54MCxcbiAgICBkYTogaGVhdG1hcEF0dHJzLmR4LFxuICAgIGI6IGhlYXRtYXBBdHRycy55LFxuICAgIGIwOiBoZWF0bWFwQXR0cnMueTAsXG4gICAgZGI6IGhlYXRtYXBBdHRycy5keSxcbiAgICB0ZXh0OiBoZWF0bWFwQXR0cnMudGV4dCxcbiAgICBob3ZlcnRleHQ6IGhlYXRtYXBBdHRycy5ob3ZlcnRleHQsXG4gICAgdHJhbnNwb3NlOiBoZWF0bWFwQXR0cnMudHJhbnNwb3NlLFxuICAgIGF0eXBlOiBoZWF0bWFwQXR0cnMueHR5cGUsXG4gICAgYnR5cGU6IGhlYXRtYXBBdHRycy55dHlwZSxcblxuICAgIGZpbGxjb2xvcjogY29udG91ckF0dHJzLmZpbGxjb2xvcixcblxuICAgIGF1dG9jb250b3VyOiBjb250b3VyQXR0cnMuYXV0b2NvbnRvdXIsXG4gICAgbmNvbnRvdXJzOiBjb250b3VyQXR0cnMubmNvbnRvdXJzLFxuXG4gICAgY29udG91cnM6IHtcbiAgICAgICAgdHlwZTogY29udG91ckNvbnRvdXJBdHRycy50eXBlLFxuICAgICAgICBzdGFydDogY29udG91ckNvbnRvdXJBdHRycy5zdGFydCxcbiAgICAgICAgZW5kOiBjb250b3VyQ29udG91ckF0dHJzLmVuZCxcbiAgICAgICAgc2l6ZTogY29udG91ckNvbnRvdXJBdHRycy5zaXplLFxuICAgICAgICBjb2xvcmluZzoge1xuICAgICAgICAgICAgLy8gZnJvbSBjb250b3VyQXR0cnMuY29udG91cnMuY29sb3JpbmcgYnV0IG5vICdoZWF0bWFwJyBvcHRpb25cbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydmaWxsJywgJ2xpbmVzJywgJ25vbmUnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdmaWxsJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaG93bGluZXM6IGNvbnRvdXJDb250b3VyQXR0cnMuc2hvd2xpbmVzLFxuICAgICAgICBzaG93bGFiZWxzOiBjb250b3VyQ29udG91ckF0dHJzLnNob3dsYWJlbHMsXG4gICAgICAgIGxhYmVsZm9udDogY29udG91ckNvbnRvdXJBdHRycy5sYWJlbGZvbnQsXG4gICAgICAgIGxhYmVsZm9ybWF0OiBjb250b3VyQ29udG91ckF0dHJzLmxhYmVsZm9ybWF0LFxuICAgICAgICBvcGVyYXRpb246IGNvbnRvdXJDb250b3VyQXR0cnMub3BlcmF0aW9uLFxuICAgICAgICB2YWx1ZTogY29udG91ckNvbnRvdXJBdHRycy52YWx1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgaW1wbGllZEVkaXRzOiB7J2F1dG9jb250b3VyJzogZmFsc2V9XG4gICAgfSxcblxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJMaW5lQXR0cnMuY29sb3IsIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgd2lkdGg6IHNjYXR0ZXJMaW5lQXR0cnMud2lkdGgsXG4gICAgICAgIGRhc2g6IHNjYXR0ZXJMaW5lQXR0cnMuZGFzaCxcbiAgICAgICAgc21vb3RoaW5nOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTGluZUF0dHJzLnNtb290aGluZywge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICB0cmFuc2Zvcm1zOiB1bmRlZmluZWRcbn0sXG5cbiAgICBjb2xvclNjYWxlQXR0cnMoJycsIHtcbiAgICAgICAgY0xldHRlcjogJ3onLFxuICAgICAgICBhdXRvQ29sb3JEZmx0OiBmYWxzZVxuICAgIH0pXG4pO1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzXCI6NjAwLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uL2NvbnRvdXIvYXR0cmlidXRlc1wiOjk0MixcIi4uL2hlYXRtYXAvYXR0cmlidXRlc1wiOjEwMDEsXCIuLi9zY2F0dGVyL2F0dHJpYnV0ZXNcIjoxMTEyfV0sOTY1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yc2NhbGVDYWxjID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIGNvbnZlcnRDb2x1bW5EYXRhID0gX2RlcmVxXygnLi4vaGVhdG1hcC9jb252ZXJ0X2NvbHVtbl94eXonKTtcbnZhciBjbGVhbjJkQXJyYXkgPSBfZGVyZXFfKCcuLi9oZWF0bWFwL2NsZWFuXzJkX2FycmF5Jyk7XG52YXIgaW50ZXJwMmQgPSBfZGVyZXFfKCcuLi9oZWF0bWFwL2ludGVycDJkJyk7XG52YXIgZmluZEVtcHRpZXMgPSBfZGVyZXFfKCcuLi9oZWF0bWFwL2ZpbmRfZW1wdGllcycpO1xudmFyIG1ha2VCb3VuZEFycmF5ID0gX2RlcmVxXygnLi4vaGVhdG1hcC9tYWtlX2JvdW5kX2FycmF5Jyk7XG52YXIgc3VwcGx5RGVmYXVsdHMgPSBfZGVyZXFfKCcuL2RlZmF1bHRzJyk7XG52YXIgbG9va3VwQ2FycGV0ID0gX2RlcmVxXygnLi4vY2FycGV0L2xvb2t1cF9jYXJwZXRpZCcpO1xudmFyIHNldENvbnRvdXJzID0gX2RlcmVxXygnLi4vY29udG91ci9zZXRfY29udG91cnMnKTtcblxuLy8gbW9zdCBpcyB0aGUgc2FtZSBhcyBoZWF0bWFwIGNhbGMsIHRoZW4gYWRqdXN0IGl0XG4vLyB0aG91Z2ggYSBmZXcgdGhpbmdzIGluc2lkZSBoZWF0bWFwIGNhbGMgc3RpbGwgbG9vayBmb3Jcbi8vIGNvbnRvdXIgbWFwcywgYmVjYXVzZSB0aGUgbWFrZUJvdW5kQXJyYXkgY2FsbHMgYXJlIHRvbyBlbnRhbmdsZWRcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgY2FycGV0ID0gdHJhY2UuX2NhcnBldFRyYWNlID0gbG9va3VwQ2FycGV0KGdkLCB0cmFjZSk7XG4gICAgaWYoIWNhcnBldCB8fCAhY2FycGV0LnZpc2libGUgfHwgY2FycGV0LnZpc2libGUgPT09ICdsZWdlbmRvbmx5JykgcmV0dXJuO1xuXG4gICAgaWYoIXRyYWNlLmEgfHwgIXRyYWNlLmIpIHtcbiAgICAgICAgLy8gTG9vayB1cCB0aGUgb3JpZ2luYWwgaW5jb21pbmcgY2FycGV0IGRhdGE6XG4gICAgICAgIHZhciBjYXJwZXRkYXRhID0gZ2QuZGF0YVtjYXJwZXQuaW5kZXhdO1xuXG4gICAgICAgIC8vIExvb2sgdXAgdGhlIGluY29taW5nIHRyYWNlIGRhdGEsICpleGNlcHQqIHBlcmZvcm0gYSBzaGFsbG93XG4gICAgICAgIC8vIGNvcHkgc28gdGhhdCB3ZSdyZSBub3QgYWN0dWFsbHkgbW9kaWZ5aW5nIGl0IHdoZW4gd2UgdXNlIGl0XG4gICAgICAgIC8vIHRvIHN1cHBseSBkZWZhdWx0czpcbiAgICAgICAgdmFyIHRyYWNlZGF0YSA9IGdkLmRhdGFbdHJhY2UuaW5kZXhdO1xuICAgICAgICAvLyB2YXIgdHJhY2VkYXRhID0gZXh0ZW5kRmxhdCh7fSwgZ2QuZGF0YVt0cmFjZS5pbmRleF0pO1xuXG4gICAgICAgIC8vIElmIHRoZSBkYXRhIGlzIG5vdCBzcGVjaWZpZWRcbiAgICAgICAgaWYoIXRyYWNlZGF0YS5hKSB0cmFjZWRhdGEuYSA9IGNhcnBldGRhdGEuYTtcbiAgICAgICAgaWYoIXRyYWNlZGF0YS5iKSB0cmFjZWRhdGEuYiA9IGNhcnBldGRhdGEuYjtcblxuICAgICAgICBzdXBwbHlEZWZhdWx0cyh0cmFjZWRhdGEsIHRyYWNlLCB0cmFjZS5fZGVmYXVsdENvbG9yLCBnZC5fZnVsbExheW91dCk7XG4gICAgfVxuXG4gICAgdmFyIGNkID0gaGVhdG1hcHBpc2hDYWxjKGdkLCB0cmFjZSk7XG4gICAgc2V0Q29udG91cnModHJhY2UsIHRyYWNlLl96KTtcblxuICAgIHJldHVybiBjZDtcbn07XG5cbmZ1bmN0aW9uIGhlYXRtYXBwaXNoQ2FsYyhnZCwgdHJhY2UpIHtcbiAgICAvLyBwcmVwYXJlIHRoZSByYXcgZGF0YVxuICAgIC8vIHJ1biBtYWtlQ2FsY2RhdGEgb24geCBhbmQgeSBldmVuIGZvciBoZWF0bWFwcywgaW4gY2FzZSBvZiBjYXRlZ29yeSBtYXBwaW5nc1xuICAgIHZhciBjYXJwZXQgPSB0cmFjZS5fY2FycGV0VHJhY2U7XG4gICAgdmFyIGFheCA9IGNhcnBldC5hYXhpcztcbiAgICB2YXIgYmF4ID0gY2FycGV0LmJheGlzO1xuICAgIHZhciBhLFxuICAgICAgICBhMCxcbiAgICAgICAgZGEsXG4gICAgICAgIGIsXG4gICAgICAgIGIwLFxuICAgICAgICBkYixcbiAgICAgICAgejtcblxuICAgIC8vIGNhbmNlbCBtaW5pbXVtIHRpY2sgc3BhY2luZ3MgKG9ubHkgYXBwbGllcyB0byBiYXJzIGFuZCBib3hlcylcbiAgICBhYXguX21pbkR0aWNrID0gMDtcbiAgICBiYXguX21pbkR0aWNrID0gMDtcblxuICAgIGlmKExpYi5pc0FycmF5MUQodHJhY2UueikpIGNvbnZlcnRDb2x1bW5EYXRhKHRyYWNlLCBhYXgsIGJheCwgJ2EnLCAnYicsIFsneiddKTtcbiAgICBhID0gdHJhY2UuX2EgPSB0cmFjZS5fYSB8fCB0cmFjZS5hO1xuICAgIGIgPSB0cmFjZS5fYiA9IHRyYWNlLl9iIHx8IHRyYWNlLmI7XG5cbiAgICBhID0gYSA/IGFheC5tYWtlQ2FsY2RhdGEodHJhY2UsICdfYScpIDogW107XG4gICAgYiA9IGIgPyBiYXgubWFrZUNhbGNkYXRhKHRyYWNlLCAnX2InKSA6IFtdO1xuICAgIGEwID0gdHJhY2UuYTAgfHwgMDtcbiAgICBkYSA9IHRyYWNlLmRhIHx8IDE7XG4gICAgYjAgPSB0cmFjZS5iMCB8fCAwO1xuICAgIGRiID0gdHJhY2UuZGIgfHwgMTtcblxuICAgIHogPSB0cmFjZS5feiA9IGNsZWFuMmRBcnJheSh0cmFjZS5feiB8fCB0cmFjZS56LCB0cmFjZS50cmFuc3Bvc2UpO1xuXG4gICAgdHJhY2UuX2VtcHR5cG9pbnRzID0gZmluZEVtcHRpZXMoeik7XG4gICAgaW50ZXJwMmQoeiwgdHJhY2UuX2VtcHR5cG9pbnRzKTtcblxuICAgIC8vIGNyZWF0ZSBhcnJheXMgb2YgYnJpY2sgYm91bmRhcmllcywgdG8gYmUgdXNlZCBieSBhdXRvcmFuZ2UgYW5kIGhlYXRtYXAucGxvdFxuICAgIHZhciB4bGVuID0gTGliLm1heFJvd0xlbmd0aCh6KTtcbiAgICB2YXIgeEluID0gdHJhY2UueHR5cGUgPT09ICdzY2FsZWQnID8gJycgOiBhO1xuICAgIHZhciB4QXJyYXkgPSBtYWtlQm91bmRBcnJheSh0cmFjZSwgeEluLCBhMCwgZGEsIHhsZW4sIGFheCk7XG4gICAgdmFyIHlJbiA9IHRyYWNlLnl0eXBlID09PSAnc2NhbGVkJyA/ICcnIDogYjtcbiAgICB2YXIgeUFycmF5ID0gbWFrZUJvdW5kQXJyYXkodHJhY2UsIHlJbiwgYjAsIGRiLCB6Lmxlbmd0aCwgYmF4KTtcblxuICAgIHZhciBjZDAgPSB7XG4gICAgICAgIGE6IHhBcnJheSxcbiAgICAgICAgYjogeUFycmF5LFxuICAgICAgICB6OiB6LFxuICAgIH07XG5cbiAgICBpZih0cmFjZS5jb250b3Vycy50eXBlID09PSAnbGV2ZWxzJyAmJiB0cmFjZS5jb250b3Vycy5jb2xvcmluZyAhPT0gJ25vbmUnKSB7XG4gICAgICAgIC8vIGF1dG8teiBhbmQgYXV0b2NvbG9yc2NhbGUgaWYgYXBwbGljYWJsZVxuICAgICAgICBjb2xvcnNjYWxlQ2FsYyhnZCwgdHJhY2UsIHtcbiAgICAgICAgICAgIHZhbHM6IHosXG4gICAgICAgICAgICBjb250YWluZXJTdHI6ICcnLFxuICAgICAgICAgICAgY0xldHRlcjogJ3onXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBbY2QwXTtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsY1wiOjYwMSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2NhcnBldC9sb29rdXBfY2FycGV0aWRcIjo5MTUsXCIuLi9jb250b3VyL3NldF9jb250b3Vyc1wiOjk2MSxcIi4uL2hlYXRtYXAvY2xlYW5fMmRfYXJyYXlcIjoxMDAzLFwiLi4vaGVhdG1hcC9jb252ZXJ0X2NvbHVtbl94eXpcIjoxMDA1LFwiLi4vaGVhdG1hcC9maW5kX2VtcHRpZXNcIjoxMDA3LFwiLi4vaGVhdG1hcC9pbnRlcnAyZFwiOjEwMTAsXCIuLi9oZWF0bWFwL21ha2VfYm91bmRfYXJyYXlcIjoxMDExLFwiLi9kZWZhdWx0c1wiOjk2Nn1dLDk2NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgaGFuZGxlWFlaRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9oZWF0bWFwL3h5el9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBoYW5kbGVDb25zdHJhaW50RGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9jb250b3VyL2NvbnN0cmFpbnRfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVDb250b3Vyc0RlZmF1bHRzID0gX2RlcmVxXygnLi4vY29udG91ci9jb250b3Vyc19kZWZhdWx0cycpO1xudmFyIGhhbmRsZVN0eWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9jb250b3VyL3N0eWxlX2RlZmF1bHRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvZXJjZTIoYXR0cikge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZTIodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnY2FycGV0Jyk7XG5cbiAgICAvLyBJZiBlaXRoZXIgYSBvciBiIGlzIG5vdCBwcmVzZW50LCB0aGVuIGl0J3Mgbm90IGEgdmFsaWQgdHJhY2UgKnVubGVzcyogdGhlIGNhcnBldFxuICAgIC8vIGF4aXMgaGFzIHRoZSBhIG9yIGIgdmFsdWVzIHdlJ3JlIGxvb2tpbmcgZm9yLiBTbyBpZiB0aGVzZSBhcmUgbm90IGZvdW5kLCBqdXN0IGRlZmVyXG4gICAgLy8gdGhhdCBkZWNpc2lvbiB1bnRpbCB0aGUgY2FsYyBzdGVwLlxuICAgIC8vXG4gICAgLy8gTkI6IHRoZSBjYWxjIHN0ZXAgd2lsbCBtb2RpZnkgdGhlIG9yaWdpbmFsIGRhdGEgaW5wdXQgYnkgYXNzaWduaW5nIHdoaWNoZXZlciBvZlxuICAgIC8vIGEgb3IgYiBhcmUgbWlzc2luZy4gVGhpcyBpcyBuZWNlc3NhcnkgYmVjYXVzZSBwYW5uaW5nIGdvZXMgcmlnaHQgZnJvbSBzdXBwbHlEZWZhdWx0c1xuICAgIC8vIHRvIHBsb3QgKHNraXBwaW5nIGNhbGMpLiBUaGF0IG1lYW5zIG9uIHN1YnNlcXVlbnQgdXBkYXRlcywgdGhpcyAqd2lsbCogbmVlZCB0byBiZVxuICAgIC8vIGFibGUgdG8gZmluZCBhIGFuZCBiLlxuICAgIC8vXG4gICAgLy8gVGhlIGxvbmctdGVybSBwcm9wZXIgZml4IGlzIHRoYXQgdGhpcyBzaG91bGQgcGVyaGFwcyB1c2UgdW5kZXJzY29yZWQgYXR0cmlidXRlcyB0b1xuICAgIC8vIGF0IGxlYXN0IG1vZGlmeSB0aGUgdXNlciBpbnB1dCB0byBhIHNsaWdodGx5IGxlc3NlciBleHRlbnQuIEZ1bGx5IHJlbW92aW5nIHRoZVxuICAgIC8vIGlucHV0IG11dGF0aW9uIGlzIGNoYWxsZW5naW5nLiBUaGUgdW5kZXJzY29yZSBhcHByb2FjaCBpcyBub3QgY3VycmVudGx5IHRha2VuIHNpbmNlXG4gICAgLy8gaXQgcmVxdWlyZXMgbW9kaWZpY2F0aW9uIHRvIGFsbCBvZiB0aGUgZnVuY3Rpb25zIGJlbG93IHRoYXQgZXhwZWN0IHRoZSBjb2VyY2VkXG4gICAgLy8gYXR0cmlidXRlIG5hbWUgdG8gbWF0Y2ggdGhlIHByb3BlcnR5IG5hbWUgLS0gZXhjZXB0ICdfYScgIT09ICdhJyBzbyB0aGF0IGlzIG5vdFxuICAgIC8vIHN0cmFpZ2h0Zm9yd2FyZC5cbiAgICBpZih0cmFjZUluLmEgJiYgdHJhY2VJbi5iKSB7XG4gICAgICAgIHZhciBsZW4gPSBoYW5kbGVYWVpEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQsICdhJywgJ2InKTtcblxuICAgICAgICBpZighbGVuKSB7XG4gICAgICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICAgICAgdmFyIGlzQ29uc3RyYWludCA9IChjb2VyY2UoJ2NvbnRvdXJzLnR5cGUnKSA9PT0gJ2NvbnN0cmFpbnQnKTtcblxuICAgICAgICBpZihpc0NvbnN0cmFpbnQpIHtcbiAgICAgICAgICAgIGhhbmRsZUNvbnN0cmFpbnREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQsIGRlZmF1bHRDb2xvciwge2hhc0hvdmVyOiBmYWxzZX0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaGFuZGxlQ29udG91cnNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBjb2VyY2UyKTtcbiAgICAgICAgICAgIGhhbmRsZVN0eWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0LCB7aGFzSG92ZXI6IGZhbHNlfSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICB0cmFjZU91dC5fZGVmYXVsdENvbG9yID0gZGVmYXVsdENvbG9yO1xuICAgICAgICB0cmFjZU91dC5fbGVuZ3RoID0gbnVsbDtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2NvbnRvdXIvY29uc3RyYWludF9kZWZhdWx0c1wiOjk0NyxcIi4uL2NvbnRvdXIvY29udG91cnNfZGVmYXVsdHNcIjo5NDksXCIuLi9jb250b3VyL3N0eWxlX2RlZmF1bHRzXCI6OTYzLFwiLi4vaGVhdG1hcC94eXpfZGVmYXVsdHNcIjoxMDE1LFwiLi9hdHRyaWJ1dGVzXCI6OTY0fV0sOTY3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjb2xvcmJhcjogX2RlcmVxXygnLi4vY29udG91ci9jb2xvcmJhcicpLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuLi9jb250b3VyL3N0eWxlJyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdjb250b3VyY2FycGV0JyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuJyksXG4gICAgY2F0ZWdvcmllczogWydjYXJ0ZXNpYW4nLCAnc3ZnJywgJ2NhcnBldCcsICdjb250b3VyJywgJ3N5bWJvbHMnLCAnc2hvd0xlZ2VuZCcsICdoYXNMaW5lcycsICdjYXJwZXREZXBlbmRlbnQnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhblwiOjc3OCxcIi4uL2NvbnRvdXIvY29sb3JiYXJcIjo5NDUsXCIuLi9jb250b3VyL3N0eWxlXCI6OTYyLFwiLi9hdHRyaWJ1dGVzXCI6OTY0LFwiLi9jYWxjXCI6OTY1LFwiLi9kZWZhdWx0c1wiOjk2NixcIi4vcGxvdFwiOjk3MH1dLDk2ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgYXhpc0FsaWduZWRMaW5lID0gX2RlcmVxXygnLi4vY2FycGV0L2F4aXNfYWxpZ25lZF9saW5lJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gam9pbkFsbFBhdGhzKHRyYWNlLCBwaSwgcGVyaW1ldGVyLCBhYjJwLCBjYXJwZXQsIGNhcnBldGNkLCB4YSwgeWEpIHtcbiAgICB2YXIgaTtcbiAgICB2YXIgZnVsbHBhdGggPSAnJztcblxuICAgIHZhciBzdGFydHNsZWZ0ID0gcGkuZWRnZXBhdGhzLm1hcChmdW5jdGlvbih2LCBpKSB7IHJldHVybiBpOyB9KTtcbiAgICB2YXIgbmV3bG9vcCA9IHRydWU7XG4gICAgdmFyIGVuZHB0LCBuZXdlbmRwdCwgY250LCBuZXh0aSwgcG9zc2libGVpLCBhZGRwYXRoO1xuXG4gICAgdmFyIGF0b2wgPSBNYXRoLmFicyhwZXJpbWV0ZXJbMF1bMF0gLSBwZXJpbWV0ZXJbMl1bMF0pICogMWUtNDtcbiAgICB2YXIgYnRvbCA9IE1hdGguYWJzKHBlcmltZXRlclswXVsxXSAtIHBlcmltZXRlclsyXVsxXSkgKiAxZS00O1xuXG4gICAgZnVuY3Rpb24gaXN0b3AocHQpIHsgcmV0dXJuIE1hdGguYWJzKHB0WzFdIC0gcGVyaW1ldGVyWzBdWzFdKSA8IGJ0b2w7IH1cbiAgICBmdW5jdGlvbiBpc2JvdHRvbShwdCkgeyByZXR1cm4gTWF0aC5hYnMocHRbMV0gLSBwZXJpbWV0ZXJbMl1bMV0pIDwgYnRvbDsgfVxuICAgIGZ1bmN0aW9uIGlzbGVmdChwdCkgeyByZXR1cm4gTWF0aC5hYnMocHRbMF0gLSBwZXJpbWV0ZXJbMF1bMF0pIDwgYXRvbDsgfVxuICAgIGZ1bmN0aW9uIGlzcmlnaHQocHQpIHsgcmV0dXJuIE1hdGguYWJzKHB0WzBdIC0gcGVyaW1ldGVyWzJdWzBdKSA8IGF0b2w7IH1cblxuICAgIGZ1bmN0aW9uIHBhdGh0byhwdDAsIHB0MSkge1xuICAgICAgICB2YXIgaSwgaiwgc2VnbWVudHMsIGF4aXM7XG4gICAgICAgIHZhciBwYXRoID0gJyc7XG5cbiAgICAgICAgaWYoKGlzdG9wKHB0MCkgJiYgIWlzcmlnaHQocHQwKSkgfHwgKGlzYm90dG9tKHB0MCkgJiYgIWlzbGVmdChwdDApKSkge1xuICAgICAgICAgICAgYXhpcyA9IGNhcnBldC5hYXhpcztcbiAgICAgICAgICAgIHNlZ21lbnRzID0gYXhpc0FsaWduZWRMaW5lKGNhcnBldCwgY2FycGV0Y2QsIFtwdDBbMF0sIHB0MVswXV0sIDAuNSAqIChwdDBbMV0gKyBwdDFbMV0pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGF4aXMgPSBjYXJwZXQuYmF4aXM7XG4gICAgICAgICAgICBzZWdtZW50cyA9IGF4aXNBbGlnbmVkTGluZShjYXJwZXQsIGNhcnBldGNkLCAwLjUgKiAocHQwWzBdICsgcHQxWzBdKSwgW3B0MFsxXSwgcHQxWzFdXSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IDE7IGkgPCBzZWdtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgcGF0aCArPSBheGlzLnNtb290aGluZyA/ICdDJyA6ICdMJztcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHNlZ21lbnRzW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHB0ID0gc2VnbWVudHNbaV1bal07XG4gICAgICAgICAgICAgICAgcGF0aCArPSBbeGEuYzJwKHB0WzBdKSwgeWEuYzJwKHB0WzFdKV0gKyAnICc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcGF0aDtcbiAgICB9XG5cbiAgICBpID0gMDtcbiAgICBlbmRwdCA9IG51bGw7XG4gICAgd2hpbGUoc3RhcnRzbGVmdC5sZW5ndGgpIHtcbiAgICAgICAgdmFyIHN0YXJ0cHQgPSBwaS5lZGdlcGF0aHNbaV1bMF07XG5cbiAgICAgICAgaWYoZW5kcHQpIHtcbiAgICAgICAgICAgIGZ1bGxwYXRoICs9IHBhdGh0byhlbmRwdCwgc3RhcnRwdCk7XG4gICAgICAgIH1cblxuICAgICAgICBhZGRwYXRoID0gRHJhd2luZy5zbW9vdGhvcGVuKHBpLmVkZ2VwYXRoc1tpXS5tYXAoYWIycCksIHBpLnNtb290aGluZyk7XG4gICAgICAgIGZ1bGxwYXRoICs9IG5ld2xvb3AgPyBhZGRwYXRoIDogYWRkcGF0aC5yZXBsYWNlKC9eTS8sICdMJyk7XG4gICAgICAgIHN0YXJ0c2xlZnQuc3BsaWNlKHN0YXJ0c2xlZnQuaW5kZXhPZihpKSwgMSk7XG4gICAgICAgIGVuZHB0ID0gcGkuZWRnZXBhdGhzW2ldW3BpLmVkZ2VwYXRoc1tpXS5sZW5ndGggLSAxXTtcbiAgICAgICAgbmV4dGkgPSAtMTtcblxuICAgICAgICAvLyBub3cgbG9vcCB0aHJvdWdoIHNpZGVzLCBtb3Zpbmcgb3VyIGVuZHBvaW50IHVudGlsIHdlIGZpbmQgYSBuZXcgc3RhcnRcbiAgICAgICAgZm9yKGNudCA9IDA7IGNudCA8IDQ7IGNudCsrKSB7IC8vIGp1c3QgdG8gcHJldmVudCBpbmZpbml0ZSBsb29wc1xuICAgICAgICAgICAgaWYoIWVuZHB0KSB7XG4gICAgICAgICAgICAgICAgTGliLmxvZygnTWlzc2luZyBlbmQ/JywgaSwgcGkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihpc3RvcChlbmRwdCkgJiYgIWlzcmlnaHQoZW5kcHQpKSB7XG4gICAgICAgICAgICAgICAgbmV3ZW5kcHQgPSBwZXJpbWV0ZXJbMV07IC8vIGxlZnQgdG9wIC0tLT4gcmlnaHQgdG9wXG4gICAgICAgICAgICB9IGVsc2UgaWYoaXNsZWZ0KGVuZHB0KSkge1xuICAgICAgICAgICAgICAgIG5ld2VuZHB0ID0gcGVyaW1ldGVyWzBdOyAvLyBsZWZ0IGJvdHRvbSAtLS0+IGxlZnQgdG9wXG4gICAgICAgICAgICB9IGVsc2UgaWYoaXNib3R0b20oZW5kcHQpKSB7XG4gICAgICAgICAgICAgICAgbmV3ZW5kcHQgPSBwZXJpbWV0ZXJbM107IC8vIHJpZ2h0IGJvdHRvbVxuICAgICAgICAgICAgfSBlbHNlIGlmKGlzcmlnaHQoZW5kcHQpKSB7XG4gICAgICAgICAgICAgICAgbmV3ZW5kcHQgPSBwZXJpbWV0ZXJbMl07IC8vIGxlZnQgYm90dG9tXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihwb3NzaWJsZWkgPSAwOyBwb3NzaWJsZWkgPCBwaS5lZGdlcGF0aHMubGVuZ3RoOyBwb3NzaWJsZWkrKykge1xuICAgICAgICAgICAgICAgIHZhciBwdE5ldyA9IHBpLmVkZ2VwYXRoc1twb3NzaWJsZWldWzBdO1xuICAgICAgICAgICAgICAgIC8vIGlzIHB0TmV3IG9uIHRoZSAoaG9yei4gb3IgdmVydC4pIHNlZ21lbnQgZnJvbSBlbmRwdCB0byBuZXdlbmRwdD9cbiAgICAgICAgICAgICAgICBpZihNYXRoLmFicyhlbmRwdFswXSAtIG5ld2VuZHB0WzBdKSA8IGF0b2wpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMoZW5kcHRbMF0gLSBwdE5ld1swXSkgPCBhdG9sICYmIChwdE5ld1sxXSAtIGVuZHB0WzFdKSAqIChuZXdlbmRwdFsxXSAtIHB0TmV3WzFdKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdlbmRwdCA9IHB0TmV3O1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dGkgPSBwb3NzaWJsZWk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoTWF0aC5hYnMoZW5kcHRbMV0gLSBuZXdlbmRwdFsxXSkgPCBidG9sKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKE1hdGguYWJzKGVuZHB0WzFdIC0gcHROZXdbMV0pIDwgYnRvbCAmJiAocHROZXdbMF0gLSBlbmRwdFswXSkgKiAobmV3ZW5kcHRbMF0gLSBwdE5ld1swXSkgPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZW5kcHQgPSBwdE5ldztcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRpID0gcG9zc2libGVpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgTGliLmxvZygnZW5kcHQgdG8gbmV3ZW5kcHQgaXMgbm90IHZlcnQuIG9yIGhvcnouJywgZW5kcHQsIG5ld2VuZHB0LCBwdE5ldyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihuZXh0aSA+PSAwKSBicmVhaztcbiAgICAgICAgICAgIGZ1bGxwYXRoICs9IHBhdGh0byhlbmRwdCwgbmV3ZW5kcHQpO1xuICAgICAgICAgICAgZW5kcHQgPSBuZXdlbmRwdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG5leHRpID09PSBwaS5lZGdlcGF0aHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBMaWIubG9nKCd1bmNsb3NlZCBwZXJpbWV0ZXIgcGF0aCcpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBpID0gbmV4dGk7XG5cbiAgICAgICAgLy8gaWYgd2UgY2xvc2VkIGJhY2sgb24gYSBsb29wIHdlIGFscmVhZHkgaW5jbHVkZWQsXG4gICAgICAgIC8vIGNsb3NlIGl0IGFuZCBzdGFydCBhIG5ldyBsb29wXG4gICAgICAgIG5ld2xvb3AgPSAoc3RhcnRzbGVmdC5pbmRleE9mKGkpID09PSAtMSk7XG4gICAgICAgIGlmKG5ld2xvb3ApIHtcbiAgICAgICAgICAgIGkgPSBzdGFydHNsZWZ0WzBdO1xuICAgICAgICAgICAgZnVsbHBhdGggKz0gcGF0aHRvKGVuZHB0LCBuZXdlbmRwdCkgKyAnWic7XG4gICAgICAgICAgICBlbmRwdCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmaW5hbGx5IGFkZCB0aGUgaW50ZXJpb3IgcGF0aHNcbiAgICBmb3IoaSA9IDA7IGkgPCBwaS5wYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICBmdWxscGF0aCArPSBEcmF3aW5nLnNtb290aGNsb3NlZChwaS5wYXRoc1tpXS5tYXAoYWIycCksIHBpLnNtb290aGluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1bGxwYXRoO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9saWJcIjo3MTksXCIuLi9jYXJwZXQvYXhpc19hbGlnbmVkX2xpbmVcIjo4OTl9XSw5Njk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1hcFBhdGhpbmZvKHBhdGhpbmZvLCBtYXApIHtcbiAgICB2YXIgaSwgaiwgaywgcGksIHBlZGdlcGF0aHMsIHBwYXRocywgcGVkZ2VwYXRoLCBwcGF0aCwgcGF0aDtcblxuICAgIGZvcihpID0gMDsgaSA8IHBhdGhpbmZvLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHBpID0gcGF0aGluZm9baV07XG4gICAgICAgIHBlZGdlcGF0aHMgPSBwaS5wZWRnZXBhdGhzID0gW107XG4gICAgICAgIHBwYXRocyA9IHBpLnBwYXRocyA9IFtdO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBwaS5lZGdlcGF0aHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHBhdGggPSBwaS5lZGdlcGF0aHNbal07XG4gICAgICAgICAgICBwZWRnZXBhdGggPSBbXTtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IHBhdGgubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBwZWRnZXBhdGhba10gPSBtYXAocGF0aFtrXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwZWRnZXBhdGhzLnB1c2gocGVkZ2VwYXRoKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaiA9IDA7IGogPCBwaS5wYXRocy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgcGF0aCA9IHBpLnBhdGhzW2pdO1xuICAgICAgICAgICAgcHBhdGggPSBbXTtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IHBhdGgubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBwcGF0aFtrXSA9IG1hcChwYXRoW2tdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBwYXRocy5wdXNoKHBwYXRoKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se31dLDk3MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgbWFwMWRBcnJheSA9IF9kZXJlcV8oJy4uL2NhcnBldC9tYXBfMWRfYXJyYXknKTtcbnZhciBtYWtlcGF0aCA9IF9kZXJlcV8oJy4uL2NhcnBldC9tYWtlcGF0aCcpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIG1ha2VDcm9zc2luZ3MgPSBfZGVyZXFfKCcuLi9jb250b3VyL21ha2VfY3Jvc3NpbmdzJyk7XG52YXIgZmluZEFsbFBhdGhzID0gX2RlcmVxXygnLi4vY29udG91ci9maW5kX2FsbF9wYXRocycpO1xudmFyIGNvbnRvdXJQbG90ID0gX2RlcmVxXygnLi4vY29udG91ci9wbG90Jyk7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi4vY29udG91ci9jb25zdGFudHMnKTtcbnZhciBjb252ZXJ0VG9Db25zdHJhaW50cyA9IF9kZXJlcV8oJy4uL2NvbnRvdXIvY29udmVydF90b19jb25zdHJhaW50cycpO1xudmFyIGpvaW5BbGxQYXRocyA9IF9kZXJlcV8oJy4vam9pbl9hbGxfcGF0aHMnKTtcbnZhciBlbXB0eVBhdGhpbmZvID0gX2RlcmVxXygnLi4vY29udG91ci9lbXB0eV9wYXRoaW5mbycpO1xudmFyIG1hcFBhdGhpbmZvID0gX2RlcmVxXygnLi9tYXBfcGF0aGluZm8nKTtcbnZhciBsb29rdXBDYXJwZXQgPSBfZGVyZXFfKCcuLi9jYXJwZXQvbG9va3VwX2NhcnBldGlkJyk7XG52YXIgY2xvc2VCb3VuZGFyaWVzID0gX2RlcmVxXygnLi4vY29udG91ci9jbG9zZV9ib3VuZGFyaWVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgcGxvdGluZm8sIGNkY29udG91cnMsIGNvbnRvdXJjYXJwZXRMYXllcikge1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgTGliLm1ha2VUcmFjZUdyb3Vwcyhjb250b3VyY2FycGV0TGF5ZXIsIGNkY29udG91cnMsICdjb250b3VyJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICB2YXIgY2FycGV0ID0gdHJhY2UuX2NhcnBldFRyYWNlID0gbG9va3VwQ2FycGV0KGdkLCB0cmFjZSk7XG4gICAgICAgIHZhciBjYXJwZXRjZCA9IGdkLmNhbGNkYXRhW2NhcnBldC5pbmRleF1bMF07XG5cbiAgICAgICAgaWYoIWNhcnBldC52aXNpYmxlIHx8IGNhcnBldC52aXNpYmxlID09PSAnbGVnZW5kb25seScpIHJldHVybjtcblxuICAgICAgICB2YXIgYSA9IGNkMC5hO1xuICAgICAgICB2YXIgYiA9IGNkMC5iO1xuICAgICAgICB2YXIgY29udG91cnMgPSB0cmFjZS5jb250b3VycztcbiAgICAgICAgdmFyIHBhdGhpbmZvID0gZW1wdHlQYXRoaW5mbyhjb250b3VycywgcGxvdGluZm8sIGNkMCk7XG4gICAgICAgIHZhciBpc0NvbnN0cmFpbnQgPSBjb250b3Vycy50eXBlID09PSAnY29uc3RyYWludCc7XG4gICAgICAgIHZhciBvcGVyYXRpb24gPSBjb250b3Vycy5fb3BlcmF0aW9uO1xuICAgICAgICB2YXIgY29sb3JpbmcgPSBpc0NvbnN0cmFpbnQgPyAob3BlcmF0aW9uID09PSAnPScgPyAnbGluZXMnIDogJ2ZpbGwnKSA6IGNvbnRvdXJzLmNvbG9yaW5nO1xuXG4gICAgICAgIC8vIE1hcCBbYSwgYl0gKGRhdGEpIC0tPiBbaSwgal0gKHBpeGVscylcbiAgICAgICAgZnVuY3Rpb24gYWIycChhYikge1xuICAgICAgICAgICAgdmFyIHB0ID0gY2FycGV0LmFiMnh5KGFiWzBdLCBhYlsxXSwgdHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm4gW3hhLmMycChwdFswXSksIHlhLmMycChwdFsxXSldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmaW5lIHRoZSBwZXJpbWV0ZXIgaW4gYS9iIGNvb3JkaW5hdGVzOlxuICAgICAgICB2YXIgcGVyaW1ldGVyID0gW1xuICAgICAgICAgICAgW2FbMF0sIGJbYi5sZW5ndGggLSAxXV0sXG4gICAgICAgICAgICBbYVthLmxlbmd0aCAtIDFdLCBiW2IubGVuZ3RoIC0gMV1dLFxuICAgICAgICAgICAgW2FbYS5sZW5ndGggLSAxXSwgYlswXV0sXG4gICAgICAgICAgICBbYVswXSwgYlswXV1cbiAgICAgICAgXTtcblxuICAgICAgICAvLyBFeHRyYWN0IHRoZSBjb250b3VyIGxldmVsczpcbiAgICAgICAgbWFrZUNyb3NzaW5ncyhwYXRoaW5mbyk7XG4gICAgICAgIHZhciBhdG9sID0gKGFbYS5sZW5ndGggLSAxXSAtIGFbMF0pICogMWUtODtcbiAgICAgICAgdmFyIGJ0b2wgPSAoYltiLmxlbmd0aCAtIDFdIC0gYlswXSkgKiAxZS04O1xuICAgICAgICBmaW5kQWxsUGF0aHMocGF0aGluZm8sIGF0b2wsIGJ0b2wpO1xuXG4gICAgICAgIC8vIENvbnN0cmFpbnRzIG1pZ2h0IG5lZWQgdG8gYmUgZHJhdyBpbnZlcnRlZCwgd2hpY2ggaXMgbm90IHNvbWV0aGluZyBjb250b3Vyc1xuICAgICAgICAvLyBoYW5kbGUgYnkgZGVmYXVsdCBzaW5jZSB0aGV5J3JlIGFzc3VtZWQgZnVsbHkgb3BhcXVlIHNvIHRoYXQgdGhleSBjYW4gYmVcbiAgICAgICAgLy8gZHJhd24gb3ZlcmxhcHBpbmcuIFRoaXMgZnVuY3Rpb24gZmxpcHMgdGhlIHBhdGhzIGFzIG5lY2Vzc2FyeSBzbyB0aGF0IHRoZXkncmVcbiAgICAgICAgLy8gZHJhd24gY29ycmVjdGx5LlxuICAgICAgICAvL1xuICAgICAgICAvLyBUT0RPOiBQZXJoYXBzIHRoaXMgc2hvdWxkIGJlIGdlbmVyYWxpemVkIGFuZCAqYWxsKiBwYXRocyBzaG91bGQgYmUgZHJhd24gYXNcbiAgICAgICAgLy8gY2xvc2VkIHJlZ2lvbnMgc28gdGhhdCB0cmFuc2x1Y2VudCBjb250b3VyIGxldmVscyB3b3VsZCBiZSB2YWxpZC5cbiAgICAgICAgLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvMTM1NlxuICAgICAgICB2YXIgZmlsbFBhdGhpbmZvID0gcGF0aGluZm87XG4gICAgICAgIGlmKGNvbnRvdXJzLnR5cGUgPT09ICdjb25zdHJhaW50Jykge1xuICAgICAgICAgICAgZmlsbFBhdGhpbmZvID0gY29udmVydFRvQ29uc3RyYWludHMocGF0aGluZm8sIG9wZXJhdGlvbik7XG4gICAgICAgICAgICBjbG9zZUJvdW5kYXJpZXMoZmlsbFBhdGhpbmZvLCBvcGVyYXRpb24sIHBlcmltZXRlciwgdHJhY2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFwIHRoZSBwYXRocyBpbiBhL2IgY29vcmRpbmF0ZXMgdG8gcGl4ZWwgY29vcmRpbmF0ZXM6XG4gICAgICAgIG1hcFBhdGhpbmZvKHBhdGhpbmZvLCBhYjJwKTtcblxuICAgICAgICAvLyBkcmF3IGV2ZXJ5dGhpbmdcblxuICAgICAgICAvLyBDb21wdXRlIHRoZSBib3VuZGFyeSBwYXRoXG4gICAgICAgIHZhciBzZWcsIHhwLCB5cCwgaTtcbiAgICAgICAgdmFyIHNlZ3MgPSBbXTtcbiAgICAgICAgZm9yKGkgPSBjYXJwZXRjZC5jbGlwc2VnbWVudHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIHNlZyA9IGNhcnBldGNkLmNsaXBzZWdtZW50c1tpXTtcbiAgICAgICAgICAgIHhwID0gbWFwMWRBcnJheShbXSwgc2VnLngsIHhhLmMycCk7XG4gICAgICAgICAgICB5cCA9IG1hcDFkQXJyYXkoW10sIHNlZy55LCB5YS5jMnApO1xuICAgICAgICAgICAgeHAucmV2ZXJzZSgpO1xuICAgICAgICAgICAgeXAucmV2ZXJzZSgpO1xuICAgICAgICAgICAgc2Vncy5wdXNoKG1ha2VwYXRoKHhwLCB5cCwgc2VnLmJpY3ViaWMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBib3VuZGFyeVBhdGggPSAnTScgKyBzZWdzLmpvaW4oJ0wnKSArICdaJztcblxuICAgICAgICAvLyBEcmF3IHRoZSBiYXNlbGluZSBiYWNrZ3JvdW5kIGZpbGwgdGhhdCBmaWxscyBpbiB0aGUgc3BhY2UgYmVoaW5kIGFueSBvdGhlclxuICAgICAgICAvLyBjb250b3VyIGxldmVsczpcbiAgICAgICAgbWFrZUJhY2tncm91bmQocGxvdEdyb3VwLCBjYXJwZXRjZC5jbGlwc2VnbWVudHMsIHhhLCB5YSwgaXNDb25zdHJhaW50LCBjb2xvcmluZyk7XG5cbiAgICAgICAgLy8gRHJhdyB0aGUgc3BlY2lmaWMgY29udG91ciBmaWxscy4gQXMgYSBzaW1wbGlmaWNhdGlvbiwgdGhleSdyZSBhc3N1bWVkIHRvIGJlXG4gICAgICAgIC8vIGZ1bGx5IG9wYXF1ZSBzbyB0aGF0IGl0J3MgZWFzeSB0byBkcmF3IHRoZW0gc2ltcGx5IG92ZXJsYXBwaW5nLiBUaGUgYWx0ZXJuYXRpdmVcbiAgICAgICAgLy8gd291bGQgYmUgdG8gZmxpcCBhZGphY2VudCBwYXRocyBhbmQgZHJhdyBjbG9zZWQgcGF0aHMgZm9yIGVhY2ggbGV2ZWwgaW5zdGVhZC5cbiAgICAgICAgbWFrZUZpbGxzKHRyYWNlLCBwbG90R3JvdXAsIHhhLCB5YSwgZmlsbFBhdGhpbmZvLCBwZXJpbWV0ZXIsIGFiMnAsIGNhcnBldCwgY2FycGV0Y2QsIGNvbG9yaW5nLCBib3VuZGFyeVBhdGgpO1xuXG4gICAgICAgIC8vIERyYXcgY29udG91ciBsaW5lczpcbiAgICAgICAgbWFrZUxpbmVzQW5kTGFiZWxzKHBsb3RHcm91cCwgcGF0aGluZm8sIGdkLCBjZDAsIGNvbnRvdXJzLCBwbG90aW5mbywgY2FycGV0KTtcblxuICAgICAgICAvLyBDbGlwIHRoZSBib3VuZGFyeSBvZiB0aGUgcGxvdFxuICAgICAgICBEcmF3aW5nLnNldENsaXBVcmwocGxvdEdyb3VwLCBjYXJwZXQuX2NsaXBQYXRoSWQsIGdkKTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VMaW5lc0FuZExhYmVscyhwbG90Z3JvdXAsIHBhdGhpbmZvLCBnZCwgY2QwLCBjb250b3VycywgcGxvdGluZm8sIGNhcnBldCkge1xuICAgIHZhciBsaW5lQ29udGFpbmVyID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2NvbnRvdXJsaW5lcycpO1xuICAgIHZhciBzaG93TGluZXMgPSBjb250b3Vycy5zaG93bGluZXMgIT09IGZhbHNlO1xuICAgIHZhciBzaG93TGFiZWxzID0gY29udG91cnMuc2hvd2xhYmVscztcbiAgICB2YXIgY2xpcExpbmVzRm9yTGFiZWxzID0gc2hvd0xpbmVzICYmIHNob3dMYWJlbHM7XG5cbiAgICAvLyBFdmVuIGlmIHdlJ3JlIG5vdCBnb2luZyB0byBzaG93IGxpbmVzLCB3ZSBuZWVkIHRvIGNyZWF0ZSB0aGVtXG4gICAgLy8gaWYgd2UncmUgc2hvd2luZyBsYWJlbHMsIGJlY2F1c2UgdGhlIGZpbGwgcGF0aHMgaW5jbHVkZSB0aGUgcGVyaW1ldGVyXG4gICAgLy8gc28gY2FuJ3QgYmUgdXNlZCB0byBwb3NpdGlvbiB0aGUgbGFiZWxzIGNvcnJlY3RseS5cbiAgICAvLyBJbiB0aGlzIGNhc2Ugd2UnbGwgcmVtb3ZlIHRoZSBsaW5lcyBhZnRlciBtYWtpbmcgdGhlIGxhYmVscy5cbiAgICB2YXIgbGluZWdyb3VwID0gY29udG91clBsb3QuY3JlYXRlTGluZXMobGluZUNvbnRhaW5lciwgc2hvd0xpbmVzIHx8IHNob3dMYWJlbHMsIHBhdGhpbmZvKTtcblxuICAgIHZhciBsaW5lQ2xpcCA9IGNvbnRvdXJQbG90LmNyZWF0ZUxpbmVDbGlwKGxpbmVDb250YWluZXIsIGNsaXBMaW5lc0ZvckxhYmVscywgZ2QsIGNkMC50cmFjZS51aWQpO1xuXG4gICAgdmFyIGxhYmVsR3JvdXAgPSBwbG90Z3JvdXAuc2VsZWN0QWxsKCdnLmNvbnRvdXJsYWJlbHMnKVxuICAgICAgICAuZGF0YShzaG93TGFiZWxzID8gWzBdIDogW10pO1xuXG4gICAgbGFiZWxHcm91cC5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICBsYWJlbEdyb3VwLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoJ2NvbnRvdXJsYWJlbHMnLCB0cnVlKTtcblxuICAgIGlmKHNob3dMYWJlbHMpIHtcbiAgICAgICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuICAgICAgICB2YXIgeExlbiA9IHhhLl9sZW5ndGg7XG4gICAgICAgIHZhciB5TGVuID0geWEuX2xlbmd0aDtcbiAgICAgICAgLy8gZm9yIHNpbXBsaWNpdHkgdXNlIHRoZSB4eSBib3ggZm9yIGxhYmVsIGNsaXBwaW5nIG91dGxpbmUuXG4gICAgICAgIHZhciBsYWJlbENsaXBQYXRoRGF0YSA9IFtbXG4gICAgICAgICAgICBbMCwgMF0sXG4gICAgICAgICAgICBbeExlbiwgMF0sXG4gICAgICAgICAgICBbeExlbiwgeUxlbl0sXG4gICAgICAgICAgICBbMCwgeUxlbl1cbiAgICAgICAgXV07XG5cblxuICAgICAgICB2YXIgbGFiZWxEYXRhID0gW107XG5cbiAgICAgICAgLy8gaW52YWxpZGF0ZSB0aGUgZ2V0VGV4dExvY2F0aW9uIGNhY2hlIGluIGNhc2UgcGF0aHMgY2hhbmdlZFxuICAgICAgICBMaWIuY2xlYXJMb2NhdGlvbkNhY2hlKCk7XG5cbiAgICAgICAgdmFyIGNvbnRvdXJGb3JtYXQgPSBjb250b3VyUGxvdC5sYWJlbEZvcm1hdHRlcihjb250b3VycywgY2QwLnQuY2IsIGdkLl9mdWxsTGF5b3V0KTtcblxuICAgICAgICB2YXIgZHVtbXlUZXh0ID0gRHJhd2luZy50ZXN0ZXIuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgICAgIC5hdHRyKCdkYXRhLW5vdGV4JywgMSlcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZm9udCwgY29udG91cnMubGFiZWxmb250KTtcblxuICAgICAgICAvLyB1c2UgYGJvdW5kc2Agb25seSB0byBrZWVwIGxhYmVscyBhd2F5IGZyb20gdGhlIHgveSBib3VuZGFyaWVzXG4gICAgICAgIC8vIGBjb25zdHJhaW5Ub0NhcnBldGAgYmVsb3cgZW5zdXJlcyBsYWJlbHMgZG9uJ3QgZ28gb2ZmIHRoZVxuICAgICAgICAvLyBjYXJwZXQgZWRnZXNcbiAgICAgICAgdmFyIGJvdW5kcyA9IHtcbiAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICByaWdodDogeExlbixcbiAgICAgICAgICAgIGNlbnRlcjogeExlbiAvIDIsXG4gICAgICAgICAgICB0b3A6IDAsXG4gICAgICAgICAgICBib3R0b206IHlMZW4sXG4gICAgICAgICAgICBtaWRkbGU6IHlMZW4gLyAyXG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIHBsb3REaWFnb25hbCA9IE1hdGguc3FydCh4TGVuICogeExlbiArIHlMZW4gKiB5TGVuKTtcblxuICAgICAgICAvLyB0aGUgcGF0aCBsZW5ndGggdG8gdXNlIHRvIHNjYWxlIHRoZSBudW1iZXIgb2YgbGFiZWxzIHRvIGRyYXc6XG4gICAgICAgIHZhciBub3JtTGVuZ3RoID0gY29uc3RhbnRzLkxBQkVMRElTVEFOQ0UgKiBwbG90RGlhZ29uYWwgL1xuICAgICAgICAgICAgTWF0aC5tYXgoMSwgcGF0aGluZm8ubGVuZ3RoIC8gY29uc3RhbnRzLkxBQkVMSU5DUkVBU0UpO1xuXG4gICAgICAgIGxpbmVncm91cC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB0ZXh0T3B0cyA9IGNvbnRvdXJQbG90LmNhbGNUZXh0T3B0cyhkLmxldmVsLCBjb250b3VyRm9ybWF0LCBkdW1teVRleHQsIGdkKTtcblxuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgncGF0aCcpLmVhY2goZnVuY3Rpb24ocGF0aERhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0aCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGhCb3VuZHMgPSBMaWIuZ2V0VmlzaWJsZVNlZ21lbnQocGF0aCwgYm91bmRzLCB0ZXh0T3B0cy5oZWlnaHQgLyAyKTtcbiAgICAgICAgICAgICAgICBpZighcGF0aEJvdW5kcykgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgY29uc3RyYWluVG9DYXJwZXQocGF0aCwgcGF0aERhdGEsIGQsIHBhdGhCb3VuZHMsIGNhcnBldCwgdGV4dE9wdHMuaGVpZ2h0KTtcblxuICAgICAgICAgICAgICAgIGlmKHBhdGhCb3VuZHMubGVuIDwgKHRleHRPcHRzLndpZHRoICsgdGV4dE9wdHMuaGVpZ2h0KSAqIGNvbnN0YW50cy5MQUJFTE1JTikgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1heExhYmVscyA9IE1hdGgubWluKE1hdGguY2VpbChwYXRoQm91bmRzLmxlbiAvIG5vcm1MZW5ndGgpLFxuICAgICAgICAgICAgICAgICAgICBjb25zdGFudHMuTEFCRUxNQVgpO1xuXG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG1heExhYmVsczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsb2MgPSBjb250b3VyUGxvdC5maW5kQmVzdFRleHRMb2NhdGlvbihwYXRoLCBwYXRoQm91bmRzLCB0ZXh0T3B0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsRGF0YSwgYm91bmRzKTtcblxuICAgICAgICAgICAgICAgICAgICBpZighbG9jKSBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICBjb250b3VyUGxvdC5hZGRMYWJlbERhdGEobG9jLCB0ZXh0T3B0cywgbGFiZWxEYXRhLCBsYWJlbENsaXBQYXRoRGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGR1bW15VGV4dC5yZW1vdmUoKTtcblxuICAgICAgICBjb250b3VyUGxvdC5kcmF3TGFiZWxzKGxhYmVsR3JvdXAsIGxhYmVsRGF0YSwgZ2QsIGxpbmVDbGlwLFxuICAgICAgICAgICAgY2xpcExpbmVzRm9yTGFiZWxzID8gbGFiZWxDbGlwUGF0aERhdGEgOiBudWxsKTtcbiAgICB9XG5cbiAgICBpZihzaG93TGFiZWxzICYmICFzaG93TGluZXMpIGxpbmVncm91cC5yZW1vdmUoKTtcbn1cblxuLy8gZmlndXJlIG91dCBpZiB0aGlzIHBhdGggZ29lcyBvZmYgdGhlIGVkZ2Ugb2YgdGhlIGNhcnBldFxuLy8gYW5kIHNob3J0ZW4gdGhlIHBhcnQgd2UgY2FsbCB2aXNpYmxlIHRvIGtlZXAgbGFiZWxzIGF3YXkgZnJvbSB0aGUgZWRnZVxuZnVuY3Rpb24gY29uc3RyYWluVG9DYXJwZXQocGF0aCwgcGF0aERhdGEsIGxldmVsRGF0YSwgcGF0aEJvdW5kcywgY2FycGV0LCB0ZXh0SGVpZ2h0KSB7XG4gICAgdmFyIHBhdGhBQkRhdGE7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxldmVsRGF0YS5wZWRnZXBhdGhzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKHBhdGhEYXRhID09PSBsZXZlbERhdGEucGVkZ2VwYXRoc1tpXSkge1xuICAgICAgICAgICAgcGF0aEFCRGF0YSA9IGxldmVsRGF0YS5lZGdlcGF0aHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYoIXBhdGhBQkRhdGEpIHJldHVybjtcblxuICAgIHZhciBhTWluID0gY2FycGV0LmFbMF07XG4gICAgdmFyIGFNYXggPSBjYXJwZXQuYVtjYXJwZXQuYS5sZW5ndGggLSAxXTtcbiAgICB2YXIgYk1pbiA9IGNhcnBldC5iWzBdO1xuICAgIHZhciBiTWF4ID0gY2FycGV0LmJbY2FycGV0LmIubGVuZ3RoIC0gMV07XG5cbiAgICBmdW5jdGlvbiBnZXRPZmZzZXQoYWJQdCwgcGF0aFZlY3Rvcikge1xuICAgICAgICB2YXIgb2Zmc2V0ID0gMDtcbiAgICAgICAgdmFyIGVkZ2VWZWN0b3I7XG4gICAgICAgIHZhciBkQUIgPSAwLjE7XG4gICAgICAgIGlmKE1hdGguYWJzKGFiUHRbMF0gLSBhTWluKSA8IGRBQiB8fCBNYXRoLmFicyhhYlB0WzBdIC0gYU1heCkgPCBkQUIpIHtcbiAgICAgICAgICAgIGVkZ2VWZWN0b3IgPSBub3JtYWxpemVWZWN0b3IoY2FycGV0LmR4eWRiX3JvdWdoKGFiUHRbMF0sIGFiUHRbMV0sIGRBQikpO1xuICAgICAgICAgICAgb2Zmc2V0ID0gTWF0aC5tYXgob2Zmc2V0LCB0ZXh0SGVpZ2h0ICogdmVjdG9yVGFuKHBhdGhWZWN0b3IsIGVkZ2VWZWN0b3IpIC8gMik7XG4gICAgICAgIH1cblxuICAgICAgICBpZihNYXRoLmFicyhhYlB0WzFdIC0gYk1pbikgPCBkQUIgfHwgTWF0aC5hYnMoYWJQdFsxXSAtIGJNYXgpIDwgZEFCKSB7XG4gICAgICAgICAgICBlZGdlVmVjdG9yID0gbm9ybWFsaXplVmVjdG9yKGNhcnBldC5keHlkYV9yb3VnaChhYlB0WzBdLCBhYlB0WzFdLCBkQUIpKTtcbiAgICAgICAgICAgIG9mZnNldCA9IE1hdGgubWF4KG9mZnNldCwgdGV4dEhlaWdodCAqIHZlY3RvclRhbihwYXRoVmVjdG9yLCBlZGdlVmVjdG9yKSAvIDIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgdmFyIHN0YXJ0VmVjdG9yID0gZ2V0VW5pdFZlY3RvcihwYXRoLCAwLCAxKTtcbiAgICB2YXIgZW5kVmVjdG9yID0gZ2V0VW5pdFZlY3RvcihwYXRoLCBwYXRoQm91bmRzLnRvdGFsLCBwYXRoQm91bmRzLnRvdGFsIC0gMSk7XG4gICAgdmFyIG1pblN0YXJ0ID0gZ2V0T2Zmc2V0KHBhdGhBQkRhdGFbMF0sIHN0YXJ0VmVjdG9yKTtcbiAgICB2YXIgbWF4RW5kID0gcGF0aEJvdW5kcy50b3RhbCAtIGdldE9mZnNldChwYXRoQUJEYXRhW3BhdGhBQkRhdGEubGVuZ3RoIC0gMV0sIGVuZFZlY3Rvcik7XG5cbiAgICBpZihwYXRoQm91bmRzLm1pbiA8IG1pblN0YXJ0KSBwYXRoQm91bmRzLm1pbiA9IG1pblN0YXJ0O1xuICAgIGlmKHBhdGhCb3VuZHMubWF4ID4gbWF4RW5kKSBwYXRoQm91bmRzLm1heCA9IG1heEVuZDtcblxuICAgIHBhdGhCb3VuZHMubGVuID0gcGF0aEJvdW5kcy5tYXggLSBwYXRoQm91bmRzLm1pbjtcbn1cblxuZnVuY3Rpb24gZ2V0VW5pdFZlY3RvcihwYXRoLCBwMCwgcDEpIHtcbiAgICB2YXIgcHQwID0gcGF0aC5nZXRQb2ludEF0TGVuZ3RoKHAwKTtcbiAgICB2YXIgcHQxID0gcGF0aC5nZXRQb2ludEF0TGVuZ3RoKHAxKTtcbiAgICB2YXIgZHggPSBwdDEueCAtIHB0MC54O1xuICAgIHZhciBkeSA9IHB0MS55IC0gcHQwLnk7XG4gICAgdmFyIGxlbiA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gICAgcmV0dXJuIFtkeCAvIGxlbiwgZHkgLyBsZW5dO1xufVxuXG5mdW5jdGlvbiBub3JtYWxpemVWZWN0b3Iodikge1xuICAgIHZhciBsZW4gPSBNYXRoLnNxcnQodlswXSAqIHZbMF0gKyB2WzFdICogdlsxXSk7XG4gICAgcmV0dXJuIFt2WzBdIC8gbGVuLCB2WzFdIC8gbGVuXTtcbn1cblxuZnVuY3Rpb24gdmVjdG9yVGFuKHYwLCB2MSkge1xuICAgIHZhciBjb3MgPSBNYXRoLmFicyh2MFswXSAqIHYxWzBdICsgdjBbMV0gKiB2MVsxXSk7XG4gICAgdmFyIHNpbiA9IE1hdGguc3FydCgxIC0gY29zICogY29zKTtcbiAgICByZXR1cm4gc2luIC8gY29zO1xufVxuXG5mdW5jdGlvbiBtYWtlQmFja2dyb3VuZChwbG90Z3JvdXAsIGNsaXBzZWdtZW50cywgeGF4aXMsIHlheGlzLCBpc0NvbnN0cmFpbnQsIGNvbG9yaW5nKSB7XG4gICAgdmFyIHNlZywgeHAsIHlwLCBpO1xuICAgIHZhciBiZ2dyb3VwID0gTGliLmVuc3VyZVNpbmdsZShwbG90Z3JvdXAsICdnJywgJ2NvbnRvdXJiZycpO1xuXG4gICAgdmFyIGJnZmlsbCA9IGJnZ3JvdXAuc2VsZWN0QWxsKCdwYXRoJylcbiAgICAgICAgLmRhdGEoKGNvbG9yaW5nID09PSAnZmlsbCcgJiYgIWlzQ29uc3RyYWludCkgPyBbMF0gOiBbXSk7XG4gICAgYmdmaWxsLmVudGVyKCkuYXBwZW5kKCdwYXRoJyk7XG4gICAgYmdmaWxsLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIHZhciBzZWdzID0gW107XG4gICAgZm9yKGkgPSAwOyBpIDwgY2xpcHNlZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHNlZyA9IGNsaXBzZWdtZW50c1tpXTtcbiAgICAgICAgeHAgPSBtYXAxZEFycmF5KFtdLCBzZWcueCwgeGF4aXMuYzJwKTtcbiAgICAgICAgeXAgPSBtYXAxZEFycmF5KFtdLCBzZWcueSwgeWF4aXMuYzJwKTtcbiAgICAgICAgc2Vncy5wdXNoKG1ha2VwYXRoKHhwLCB5cCwgc2VnLmJpY3ViaWMpKTtcbiAgICB9XG5cbiAgICBiZ2ZpbGxcbiAgICAgICAgLmF0dHIoJ2QnLCAnTScgKyBzZWdzLmpvaW4oJ0wnKSArICdaJylcbiAgICAgICAgLnN0eWxlKCdzdHJva2UnLCAnbm9uZScpO1xufVxuXG5mdW5jdGlvbiBtYWtlRmlsbHModHJhY2UsIHBsb3Rncm91cCwgeGEsIHlhLCBwYXRoaW5mbywgcGVyaW1ldGVyLCBhYjJwLCBjYXJwZXQsIGNhcnBldGNkLCBjb2xvcmluZywgYm91bmRhcnlQYXRoKSB7XG4gICAgdmFyIGZpbGxncm91cCA9IExpYi5lbnN1cmVTaW5nbGUocGxvdGdyb3VwLCAnZycsICdjb250b3VyZmlsbCcpO1xuXG4gICAgdmFyIGZpbGxpdGVtcyA9IGZpbGxncm91cC5zZWxlY3RBbGwoJ3BhdGgnKVxuICAgICAgICAuZGF0YShjb2xvcmluZyA9PT0gJ2ZpbGwnID8gcGF0aGluZm8gOiBbXSk7XG4gICAgZmlsbGl0ZW1zLmVudGVyKCkuYXBwZW5kKCdwYXRoJyk7XG4gICAgZmlsbGl0ZW1zLmV4aXQoKS5yZW1vdmUoKTtcbiAgICBmaWxsaXRlbXMuZWFjaChmdW5jdGlvbihwaSkge1xuICAgICAgICAvLyBqb2luIGFsbCBwYXRocyBmb3IgdGhpcyBsZXZlbCB0b2dldGhlciBpbnRvIGEgc2luZ2xlIHBhdGhcbiAgICAgICAgLy8gZmlyc3QgZm9sbG93IGNsb2Nrd2lzZSBhcm91bmQgdGhlIHBlcmltZXRlciB0byBjbG9zZSBhbnkgb3BlbiBwYXRoc1xuICAgICAgICAvLyBpZiB0aGUgd2hvbGUgcGVyaW1ldGVyIGlzIGFib3ZlIHRoaXMgbGV2ZWwsIHN0YXJ0IHdpdGggYSBwYXRoXG4gICAgICAgIC8vIGVuY2xvc2luZyB0aGUgd2hvbGUgdGhpbmcuIFdpdGggYWxsIHRoYXQsIHRoZSBwYXJpdHkgc2hvdWxkIG1lYW5cbiAgICAgICAgLy8gdGhhdCB3ZSBhbHdheXMgZmlsbCBldmVyeXRoaW5nIGFib3ZlIHRoZSBjb250b3VyLCBub3RoaW5nIGJlbG93XG4gICAgICAgIHZhciBmdWxscGF0aCA9IGpvaW5BbGxQYXRocyh0cmFjZSwgcGksIHBlcmltZXRlciwgYWIycCwgY2FycGV0LCBjYXJwZXRjZCwgeGEsIHlhKTtcblxuICAgICAgICBpZihwaS5wcmVmaXhCb3VuZGFyeSkge1xuICAgICAgICAgICAgZnVsbHBhdGggPSBib3VuZGFyeVBhdGggKyBmdWxscGF0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFmdWxscGF0aCkge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnJlbW92ZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAgICAgLmF0dHIoJ2QnLCBmdWxscGF0aClcbiAgICAgICAgICAgICAgICAuc3R5bGUoJ3N0cm9rZScsICdub25lJyk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9saWJcIjo3MTksXCIuLi9jYXJwZXQvbG9va3VwX2NhcnBldGlkXCI6OTE1LFwiLi4vY2FycGV0L21ha2VwYXRoXCI6OTE2LFwiLi4vY2FycGV0L21hcF8xZF9hcnJheVwiOjkxNyxcIi4uL2NvbnRvdXIvY2xvc2VfYm91bmRhcmllc1wiOjk0NCxcIi4uL2NvbnRvdXIvY29uc3RhbnRzXCI6OTQ2LFwiLi4vY29udG91ci9jb252ZXJ0X3RvX2NvbnN0cmFpbnRzXCI6OTUwLFwiLi4vY29udG91ci9lbXB0eV9wYXRoaW5mb1wiOjk1MixcIi4uL2NvbnRvdXIvZmluZF9hbGxfcGF0aHNcIjo5NTQsXCIuLi9jb250b3VyL21ha2VfY3Jvc3NpbmdzXCI6OTU5LFwiLi4vY29udG91ci9wbG90XCI6OTYwLFwiLi9qb2luX2FsbF9wYXRoc1wiOjk2OCxcIi4vbWFwX3BhdGhpbmZvXCI6OTY5LFwiZDNcIjoxNjN9XSw5NzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JTY2FsZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBob3ZlcnRlbXBsYXRlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlcycpO1xudmFyIHBsb3RBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcbnZhciBzY2F0dGVyTWFwYm94QXR0cnMgPSBfZGVyZXFfKCcuLi9zY2F0dGVybWFwYm94L2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxuLypcbiAqIC0gaHR0cHM6Ly9kb2NzLm1hcGJveC5jb20vaGVscC90dXRvcmlhbHMvbWFrZS1hLWhlYXRtYXAtd2l0aC1tYXBib3gtZ2wtanMvXG4gKiAtIGh0dHBzOi8vZG9jcy5tYXBib3guY29tL21hcGJveC1nbC1qcy9leGFtcGxlL2hlYXRtYXAtbGF5ZXIvXG4gKiAtIGh0dHBzOi8vZG9jcy5tYXBib3guY29tL21hcGJveC1nbC1qcy9zdHlsZS1zcGVjLyNsYXllcnMtaGVhdG1hcFxuICogLSBodHRwczovL2Jsb2cubWFwYm94LmNvbS9pbnRyb2R1Y2luZy1oZWF0bWFwcy1pbi1tYXBib3gtZ2wtanMtNzEzNTVhZGE5ZTZjXG4gKlxuICogR290Y2hhczpcbiAqIC0gaHR0cHM6Ly9naXRodWIuY29tL21hcGJveC9tYXBib3gtZ2wtanMvaXNzdWVzLzY0NjNcbiAqIC0gaHR0cHM6Ly9naXRodWIuY29tL21hcGJveC9tYXBib3gtZ2wtanMvaXNzdWVzLzYxMTJcbiAqL1xuXG4vKlxuICpcbiAqIEluIG1hdGhlbWF0aWNhbCB0ZXJtcywgTWFwYm94IEdMIGhlYXRtYXBzIGFyZSBhIGJpdmFyaWF0ZSAoMkQpIGtlcm5lbCBkZW5zaXR5XG4gKiBlc3RpbWF0aW9uIHdpdGggYSBHYXVzc2lhbiBrZXJuZWwuIEl0IG1lYW5zIHRoYXQgZWFjaCBkYXRhIHBvaW50IGhhcyBhbiBhcmVhXG4gKiBvZiDigJxpbmZsdWVuY2XigJ0gYXJvdW5kIGl0IChjYWxsZWQgYSBrZXJuZWwpIHdoZXJlIHRoZSBudW1lcmljYWwgdmFsdWUgb2ZcbiAqIGluZmx1ZW5jZSAod2hpY2ggd2UgY2FsbCBkZW5zaXR5KSBkZWNyZWFzZXMgYXMgeW91IGdvIGZ1cnRoZXIgZnJvbSB0aGUgcG9pbnQuXG4gKiBJZiB3ZSBzdW0gZGVuc2l0eSB2YWx1ZXMgb2YgYWxsIHBvaW50cyBpbiBldmVyeSBwaXhlbCBvZiB0aGUgc2NyZWVuLCB3ZSBnZXQgYVxuICogY29tYmluZWQgZGVuc2l0eSB2YWx1ZSB3aGljaCB3ZSB0aGVuIG1hcCB0byBhIGhlYXRtYXAgY29sb3IuXG4gKlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZXh0ZW5kRmxhdCh7XG4gICAgbG9uOiBzY2F0dGVyTWFwYm94QXR0cnMubG9uLFxuICAgIGxhdDogc2NhdHRlck1hcGJveEF0dHJzLmxhdCxcblxuICAgIHo6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgcmFkaXVzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgbWluOiAxLFxuICAgICAgICBkZmx0OiAzMCxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGJlbG93OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHQ6IHNjYXR0ZXJNYXBib3hBdHRycy50ZXh0LFxuICAgIGhvdmVydGV4dDogc2NhdHRlck1hcGJveEF0dHJzLmhvdmVydGV4dCxcblxuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgcGxvdEF0dHJzLmhvdmVyaW5mbywge1xuICAgICAgICBmbGFnczogWydsb24nLCAnbGF0JywgJ3onLCAndGV4dCcsICduYW1lJ11cbiAgICB9KSxcbiAgICBob3ZlcnRlbXBsYXRlOiBob3ZlcnRlbXBsYXRlQXR0cnMoKVxufSxcbiAgICBjb2xvclNjYWxlQXR0cnMoJycsIHtcbiAgICAgICAgY0xldHRlcjogJ3onLFxuICAgICAgICBlZGl0VHlwZU92ZXJyaWRlOiAnY2FsYydcbiAgICB9KVxuKTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9zY2F0dGVybWFwYm94L2F0dHJpYnV0ZXNcIjoxMTcxfV0sOTcyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG52YXIgY29sb3JzY2FsZUNhbGMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsYycpO1xudmFyIF8gPSBfZGVyZXFfKCcuLi8uLi9saWInKS5fO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGxlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGNhbGNUcmFjZSA9IG5ldyBBcnJheShsZW4pO1xuICAgIHZhciB6ID0gdHJhY2UuejtcbiAgICB2YXIgaGFzWiA9IGlzQXJyYXlPclR5cGVkQXJyYXkoeikgJiYgei5sZW5ndGg7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIGNkaSA9IGNhbGNUcmFjZVtpXSA9IHt9O1xuXG4gICAgICAgIHZhciBsb24gPSB0cmFjZS5sb25baV07XG4gICAgICAgIHZhciBsYXQgPSB0cmFjZS5sYXRbaV07XG5cbiAgICAgICAgY2RpLmxvbmxhdCA9IGlzTnVtZXJpYyhsb24pICYmIGlzTnVtZXJpYyhsYXQpID9cbiAgICAgICAgICAgIFsrbG9uLCArbGF0XSA6XG4gICAgICAgICAgICBbQkFETlVNLCBCQUROVU1dO1xuXG4gICAgICAgIGlmKGhhc1opIHtcbiAgICAgICAgICAgIHZhciB6aSA9IHpbaV07XG4gICAgICAgICAgICBjZGkueiA9IGlzTnVtZXJpYyh6aSkgPyB6aSA6IEJBRE5VTTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbG9yc2NhbGVDYWxjKGdkLCB0cmFjZSwge1xuICAgICAgICB2YWxzOiBoYXNaID8geiA6IFswLCAxXSxcbiAgICAgICAgY29udGFpbmVyU3RyOiAnJyxcbiAgICAgICAgY0xldHRlcjogJ3onXG4gICAgfSk7XG5cbiAgICBpZihsZW4pIHtcbiAgICAgICAgY2FsY1RyYWNlWzBdLnQgPSB7XG4gICAgICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAgICAgICBsYXQ6IF8oZ2QsICdsYXQ6JykgKyAnICcsXG4gICAgICAgICAgICAgICAgbG9uOiBfKGdkLCAnbG9uOicpICsgJyAnXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGNhbGNUcmFjZTtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGNcIjo2MDEsXCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vbGliXCI6NzE5LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSw5NzM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIENvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKTtcblxudmFyIEJBRE5VTSA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG52YXIgbWFrZUJsYW5rID0gX2RlcmVxXygnLi4vLi4vbGliL2dlb2pzb25fdXRpbHMnKS5tYWtlQmxhbms7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29udmVydChjYWxjVHJhY2UpIHtcbiAgICB2YXIgdHJhY2UgPSBjYWxjVHJhY2VbMF0udHJhY2U7XG4gICAgdmFyIGlzVmlzaWJsZSA9ICh0cmFjZS52aXNpYmxlID09PSB0cnVlICYmIHRyYWNlLl9sZW5ndGggIT09IDApO1xuXG4gICAgdmFyIGhlYXRtYXAgPSB7XG4gICAgICAgIGxheW91dDoge3Zpc2liaWxpdHk6ICdub25lJ30sXG4gICAgICAgIHBhaW50OiB7fVxuICAgIH07XG5cbiAgICB2YXIgb3B0cyA9IHRyYWNlLl9vcHRzID0ge1xuICAgICAgICBoZWF0bWFwOiBoZWF0bWFwLFxuICAgICAgICBnZW9qc29uOiBtYWtlQmxhbmsoKVxuICAgIH07XG5cbiAgICAvLyBlYXJseSByZXR1cm4gaWYgbm90IHZpc2libGUgb3IgcGxhY2Vob2xkZXJcbiAgICBpZighaXNWaXNpYmxlKSByZXR1cm4gb3B0cztcblxuICAgIHZhciBmZWF0dXJlcyA9IFtdO1xuICAgIHZhciBpO1xuXG4gICAgdmFyIHogPSB0cmFjZS56O1xuICAgIHZhciByYWRpdXMgPSB0cmFjZS5yYWRpdXM7XG4gICAgdmFyIGhhc1ogPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheSh6KSAmJiB6Lmxlbmd0aDtcbiAgICB2YXIgaGFzQXJyYXlSYWRpdXMgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShyYWRpdXMpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgY2FsY1RyYWNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjZGkgPSBjYWxjVHJhY2VbaV07XG4gICAgICAgIHZhciBsb25sYXQgPSBjZGkubG9ubGF0O1xuXG4gICAgICAgIGlmKGxvbmxhdFswXSAhPT0gQkFETlVNKSB7XG4gICAgICAgICAgICB2YXIgcHJvcHMgPSB7fTtcblxuICAgICAgICAgICAgaWYoaGFzWikge1xuICAgICAgICAgICAgICAgIHZhciB6aSA9IGNkaS56O1xuICAgICAgICAgICAgICAgIHByb3BzLnogPSB6aSAhPT0gQkFETlVNID8gemkgOiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoaGFzQXJyYXlSYWRpdXMpIHtcbiAgICAgICAgICAgICAgICBwcm9wcy5yID0gKGlzTnVtZXJpYyhyYWRpdXNbaV0pICYmIHJhZGl1c1tpXSA+IDApID8gK3JhZGl1c1tpXSA6IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZlYXR1cmVzLnB1c2goe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdGZWF0dXJlJyxcbiAgICAgICAgICAgICAgICBnZW9tZXRyeToge3R5cGU6ICdQb2ludCcsIGNvb3JkaW5hdGVzOiBsb25sYXR9LFxuICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBjT3B0cyA9IENvbG9yc2NhbGUuZXh0cmFjdE9wdHModHJhY2UpO1xuICAgIHZhciBzY2wgPSBjT3B0cy5yZXZlcnNlc2NhbGUgP1xuICAgICAgICBDb2xvcnNjYWxlLmZsaXBTY2FsZShjT3B0cy5jb2xvcnNjYWxlKSA6XG4gICAgICAgIGNPcHRzLmNvbG9yc2NhbGU7XG5cbiAgICAvLyBBZGQgYWxwaGEgY2hhbm5lbCB0byBmaXJzdCBjb2xvcnNjYWxlIHN0ZXAuXG4gICAgLy8gSWYgbm90LCB3ZSB3b3VsZCBlc3NlbnRpYWxseSBjb2xvciB0aGUgZW50aXJlIG1hcC5cbiAgICAvLyBTZWUgaHR0cHM6Ly9kb2NzLm1hcGJveC5jb20vbWFwYm94LWdsLWpzL2V4YW1wbGUvaGVhdG1hcC1sYXllci9cbiAgICB2YXIgc2NsMDEgPSBzY2xbMF1bMV07XG4gICAgdmFyIGNvbG9yMCA9IENvbG9yLm9wYWNpdHkoc2NsMDEpIDwgMSA/IHNjbDAxIDogQ29sb3IuYWRkT3BhY2l0eShzY2wwMSwgMCk7XG5cbiAgICB2YXIgaGVhdG1hcENvbG9yID0gW1xuICAgICAgICAnaW50ZXJwb2xhdGUnLCBbJ2xpbmVhciddLFxuICAgICAgICBbJ2hlYXRtYXAtZGVuc2l0eSddLFxuICAgICAgICAwLCBjb2xvcjBcbiAgICBdO1xuICAgIGZvcihpID0gMTsgaSA8IHNjbC5sZW5ndGg7IGkrKykge1xuICAgICAgICBoZWF0bWFwQ29sb3IucHVzaChzY2xbaV1bMF0sIHNjbFtpXVsxXSk7XG4gICAgfVxuXG4gICAgLy8gVGhvc2UgXCJ3ZWlnaHRzXCIgaGF2ZSB0byBiZSBpbiBbMCwgMV0sIHdlIGNhbiBkbyB0aGlzIGVpdGhlcjpcbiAgICAvLyAtIGFzIGhlcmUgdXNpbmcgYSBtYXBib3gtZ2wgZXhwcmVzc2lvblxuICAgIC8vIC0gb3IsIHNjYWxlIHRoZSAneicgcHJvcGVydHkgaW4gdGhlIGZlYXR1cmUgbG9vcFxuICAgIHZhciB6RXhwID0gW1xuICAgICAgICAnaW50ZXJwb2xhdGUnLCBbJ2xpbmVhciddLFxuICAgICAgICBbJ2dldCcsICd6J10sXG4gICAgICAgIGNPcHRzLm1pbiwgMCxcbiAgICAgICAgY09wdHMubWF4LCAxXG4gICAgXTtcblxuICAgIExpYi5leHRlbmRGbGF0KG9wdHMuaGVhdG1hcC5wYWludCwge1xuICAgICAgICAnaGVhdG1hcC13ZWlnaHQnOiBoYXNaID8gekV4cCA6IDEgLyAoY09wdHMubWF4IC0gY09wdHMubWluKSxcblxuICAgICAgICAnaGVhdG1hcC1jb2xvcic6IGhlYXRtYXBDb2xvcixcblxuICAgICAgICAnaGVhdG1hcC1yYWRpdXMnOiBoYXNBcnJheVJhZGl1cyA/XG4gICAgICAgICAgICB7dHlwZTogJ2lkZW50aXR5JywgcHJvcGVydHk6ICdyJ30gOlxuICAgICAgICAgICAgdHJhY2UucmFkaXVzLFxuXG4gICAgICAgICdoZWF0bWFwLW9wYWNpdHknOiB0cmFjZS5vcGFjaXR5XG4gICAgfSk7XG5cbiAgICBvcHRzLmdlb2pzb24gPSB7dHlwZTogJ0ZlYXR1cmVDb2xsZWN0aW9uJywgZmVhdHVyZXM6IGZlYXR1cmVzfTtcbiAgICBvcHRzLmhlYXRtYXAubGF5b3V0LnZpc2liaWxpdHkgPSAndmlzaWJsZSc7XG5cbiAgICByZXR1cm4gb3B0cztcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZVwiOjYwNSxcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZ2VvanNvbl91dGlsc1wiOjcxNCxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sOTc0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxvbiA9IGNvZXJjZSgnbG9uJykgfHwgW107XG4gICAgdmFyIGxhdCA9IGNvZXJjZSgnbGF0JykgfHwgW107XG5cbiAgICB2YXIgbGVuID0gTWF0aC5taW4obG9uLmxlbmd0aCwgbGF0Lmxlbmd0aCk7XG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuXG4gICAgY29lcmNlKCd6Jyk7XG4gICAgY29lcmNlKCdyYWRpdXMnKTtcbiAgICBjb2VyY2UoJ2JlbG93Jyk7XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgY29sb3JzY2FsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge3ByZWZpeDogJycsIGNMZXR0ZXI6ICd6J30pO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHNcIjo2MDMsXCIuLi8uLi9saWJcIjo3MTksXCIuL2F0dHJpYnV0ZXNcIjo5NzF9XSw5NzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0KSB7XG4gICAgb3V0LmxvbiA9IHB0LmxvbjtcbiAgICBvdXQubGF0ID0gcHQubGF0O1xuICAgIG91dC56ID0gcHQuejtcbiAgICByZXR1cm4gb3V0O1xufTtcblxufSx7fV0sOTc2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIHNjYXR0ZXJNYXBib3hIb3ZlclBvaW50cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXJtYXBib3gvaG92ZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwpIHtcbiAgICB2YXIgcHRzID0gc2NhdHRlck1hcGJveEhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCk7XG4gICAgaWYoIXB0cykgcmV0dXJuO1xuXG4gICAgdmFyIG5ld1BvaW50RGF0YSA9IHB0c1swXTtcbiAgICB2YXIgY2QgPSBuZXdQb2ludERhdGEuY2Q7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIGRpID0gY2RbbmV3UG9pbnREYXRhLmluZGV4XTtcblxuICAgIC8vIGxldCBGeC5ob3ZlciBwaWNrIHRoZSBjb2xvclxuICAgIGRlbGV0ZSBuZXdQb2ludERhdGEuY29sb3I7XG5cbiAgICBpZigneicgaW4gZGkpIHtcbiAgICAgICAgdmFyIGF4ID0gbmV3UG9pbnREYXRhLnN1YnBsb3QubW9ja0F4aXM7XG4gICAgICAgIG5ld1BvaW50RGF0YS56ID0gZGkuejtcbiAgICAgICAgbmV3UG9pbnREYXRhLnpMYWJlbCA9IEF4ZXMudGlja1RleHQoYXgsIGF4LmMybChkaS56KSwgJ2hvdmVyJykudGV4dDtcbiAgICB9XG5cbiAgICBuZXdQb2ludERhdGEuZXh0cmFUZXh0ID0gZ2V0RXh0cmFUZXh0KHRyYWNlLCBkaSwgY2RbMF0udC5sYWJlbHMpO1xuXG4gICAgcmV0dXJuIFtuZXdQb2ludERhdGFdO1xufTtcblxuZnVuY3Rpb24gZ2V0RXh0cmFUZXh0KHRyYWNlLCBkaSwgbGFiZWxzKSB7XG4gICAgaWYodHJhY2UuaG92ZXJ0ZW1wbGF0ZSkgcmV0dXJuO1xuXG4gICAgdmFyIGhvdmVyaW5mbyA9IGRpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgcGFydHMgPSBob3ZlcmluZm8uc3BsaXQoJysnKTtcbiAgICB2YXIgaXNBbGwgPSBwYXJ0cy5pbmRleE9mKCdhbGwnKSAhPT0gLTE7XG4gICAgdmFyIGhhc0xvbiA9IHBhcnRzLmluZGV4T2YoJ2xvbicpICE9PSAtMTtcbiAgICB2YXIgaGFzTGF0ID0gcGFydHMuaW5kZXhPZignbGF0JykgIT09IC0xO1xuICAgIHZhciBsb25sYXQgPSBkaS5sb25sYXQ7XG4gICAgdmFyIHRleHQgPSBbXTtcblxuICAgIGZ1bmN0aW9uIGZvcm1hdCh2KSB7XG4gICAgICAgIHJldHVybiB2ICsgJ1xcdTAwQjAnO1xuICAgIH1cblxuICAgIGlmKGlzQWxsIHx8IChoYXNMb24gJiYgaGFzTGF0KSkge1xuICAgICAgICB0ZXh0LnB1c2goJygnICsgZm9ybWF0KGxvbmxhdFswXSkgKyAnLCAnICsgZm9ybWF0KGxvbmxhdFsxXSkgKyAnKScpO1xuICAgIH0gZWxzZSBpZihoYXNMb24pIHtcbiAgICAgICAgdGV4dC5wdXNoKGxhYmVscy5sb24gKyBmb3JtYXQobG9ubGF0WzBdKSk7XG4gICAgfSBlbHNlIGlmKGhhc0xhdCkge1xuICAgICAgICB0ZXh0LnB1c2gobGFiZWxzLmxhdCArIGZvcm1hdChsb25sYXRbMV0pKTtcbiAgICB9XG5cbiAgICBpZihpc0FsbCB8fCBwYXJ0cy5pbmRleE9mKCd0ZXh0JykgIT09IC0xKSB7XG4gICAgICAgIExpYi5maWxsVGV4dChkaSwgdHJhY2UsIHRleHQpO1xuICAgIH1cblxuICAgIHJldHVybiB0ZXh0LmpvaW4oJzxicj4nKTtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL3NjYXR0ZXJtYXBib3gvaG92ZXJcIjoxMTc1fV0sOTc3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjb2xvcmJhcjogX2RlcmVxXygnLi4vaGVhdG1hcC9jb2xvcmJhcicpLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIGhvdmVyUG9pbnRzOiBfZGVyZXFfKCcuL2hvdmVyJyksXG4gICAgZXZlbnREYXRhOiBfZGVyZXFfKCcuL2V2ZW50X2RhdGEnKSxcblxuICAgIGdldEJlbG93OiBmdW5jdGlvbih0cmFjZSwgc3VicGxvdCkge1xuICAgICAgICB2YXIgbWFwTGF5ZXJzID0gc3VicGxvdC5nZXRNYXBMYXllcnMoKTtcblxuICAgICAgICAvLyBmaW5kIGZpcnN0IGxheWVyIHdpdGggYHR5cGU6ICdzeW1ib2wnYCxcbiAgICAgICAgLy8gdGhhdCBpcyBub3QgYSBwbG90bHkgbGF5ZXJcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG1hcExheWVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGxheWVyID0gbWFwTGF5ZXJzW2ldO1xuICAgICAgICAgICAgdmFyIGxheWVySWQgPSBsYXllci5pZDtcbiAgICAgICAgICAgIGlmKGxheWVyLnR5cGUgPT09ICdzeW1ib2wnICYmXG4gICAgICAgICAgICAgICAgdHlwZW9mIGxheWVySWQgPT09ICdzdHJpbmcnICYmIGxheWVySWQuaW5kZXhPZigncGxvdGx5LScpID09PSAtMVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxheWVySWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnZGVuc2l0eW1hcGJveCcsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL21hcGJveCcpLFxuICAgIGNhdGVnb3JpZXM6IFsnbWFwYm94JywgJ2dsJ10sXG4gICAgbWV0YToge1xuICAgICAgICBocl9uYW1lOiAnZGVuc2l0eV9tYXBib3gnLFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL21hcGJveFwiOjgyMixcIi4uL2hlYXRtYXAvY29sb3JiYXJcIjoxMDA0LFwiLi9hdHRyaWJ1dGVzXCI6OTcxLFwiLi9jYWxjXCI6OTcyLFwiLi9kZWZhdWx0c1wiOjk3NCxcIi4vZXZlbnRfZGF0YVwiOjk3NSxcIi4vaG92ZXJcIjo5NzYsXCIuL3Bsb3RcIjo5Nzh9XSw5Nzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29udmVydCA9IF9kZXJlcV8oJy4vY29udmVydCcpO1xudmFyIExBWUVSX1BSRUZJWCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL21hcGJveC9jb25zdGFudHMnKS50cmFjZUxheWVyUHJlZml4O1xuXG5mdW5jdGlvbiBEZW5zaXR5TWFwYm94KHN1YnBsb3QsIHVpZCkge1xuICAgIHRoaXMuc3VicGxvdCA9IHN1YnBsb3Q7XG4gICAgdGhpcy51aWQgPSB1aWQ7XG5cbiAgICB0aGlzLnNvdXJjZUlkID0gJ3NvdXJjZS0nICsgdWlkO1xuXG4gICAgdGhpcy5sYXllckxpc3QgPSBbXG4gICAgICAgIFsnaGVhdG1hcCcsIExBWUVSX1BSRUZJWCArIHVpZCArICctaGVhdG1hcCddXG4gICAgXTtcblxuICAgIC8vIHByZXZpb3VzICdiZWxvdycgdmFsdWUsXG4gICAgLy8gbmVlZCB0aGlzIHRvIHVwZGF0ZSBpdCBwcm9wZXJseVxuICAgIHRoaXMuYmVsb3cgPSBudWxsO1xufVxuXG52YXIgcHJvdG8gPSBEZW5zaXR5TWFwYm94LnByb3RvdHlwZTtcblxucHJvdG8udXBkYXRlID0gZnVuY3Rpb24oY2FsY1RyYWNlKSB7XG4gICAgdmFyIHN1YnBsb3QgPSB0aGlzLnN1YnBsb3Q7XG4gICAgdmFyIGxheWVyTGlzdCA9IHRoaXMubGF5ZXJMaXN0O1xuICAgIHZhciBvcHRzQWxsID0gY29udmVydChjYWxjVHJhY2UpO1xuICAgIHZhciBiZWxvdyA9IHN1YnBsb3QuYmVsb3dMb29rdXBbJ3RyYWNlLScgKyB0aGlzLnVpZF07XG5cbiAgICBzdWJwbG90Lm1hcFxuICAgICAgICAuZ2V0U291cmNlKHRoaXMuc291cmNlSWQpXG4gICAgICAgIC5zZXREYXRhKG9wdHNBbGwuZ2VvanNvbik7XG5cbiAgICBpZihiZWxvdyAhPT0gdGhpcy5iZWxvdykge1xuICAgICAgICB0aGlzLl9yZW1vdmVMYXllcnMoKTtcbiAgICAgICAgdGhpcy5fYWRkTGF5ZXJzKG9wdHNBbGwsIGJlbG93KTtcbiAgICAgICAgdGhpcy5iZWxvdyA9IGJlbG93O1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsYXllckxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGl0ZW0gPSBsYXllckxpc3RbaV07XG4gICAgICAgIHZhciBrID0gaXRlbVswXTtcbiAgICAgICAgdmFyIGlkID0gaXRlbVsxXTtcbiAgICAgICAgdmFyIG9wdHMgPSBvcHRzQWxsW2tdO1xuXG4gICAgICAgIHN1YnBsb3Quc2V0T3B0aW9ucyhpZCwgJ3NldExheW91dFByb3BlcnR5Jywgb3B0cy5sYXlvdXQpO1xuXG4gICAgICAgIGlmKG9wdHMubGF5b3V0LnZpc2liaWxpdHkgPT09ICd2aXNpYmxlJykge1xuICAgICAgICAgICAgc3VicGxvdC5zZXRPcHRpb25zKGlkLCAnc2V0UGFpbnRQcm9wZXJ0eScsIG9wdHMucGFpbnQpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxucHJvdG8uX2FkZExheWVycyA9IGZ1bmN0aW9uKG9wdHNBbGwsIGJlbG93KSB7XG4gICAgdmFyIHN1YnBsb3QgPSB0aGlzLnN1YnBsb3Q7XG4gICAgdmFyIGxheWVyTGlzdCA9IHRoaXMubGF5ZXJMaXN0O1xuICAgIHZhciBzb3VyY2VJZCA9IHRoaXMuc291cmNlSWQ7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGF5ZXJMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBpdGVtID0gbGF5ZXJMaXN0W2ldO1xuICAgICAgICB2YXIgayA9IGl0ZW1bMF07XG4gICAgICAgIHZhciBvcHRzID0gb3B0c0FsbFtrXTtcblxuICAgICAgICBzdWJwbG90LmFkZExheWVyKHtcbiAgICAgICAgICAgIHR5cGU6IGssXG4gICAgICAgICAgICBpZDogaXRlbVsxXSxcbiAgICAgICAgICAgIHNvdXJjZTogc291cmNlSWQsXG4gICAgICAgICAgICBsYXlvdXQ6IG9wdHMubGF5b3V0LFxuICAgICAgICAgICAgcGFpbnQ6IG9wdHMucGFpbnRcbiAgICAgICAgfSwgYmVsb3cpO1xuICAgIH1cbn07XG5cbnByb3RvLl9yZW1vdmVMYXllcnMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5zdWJwbG90Lm1hcDtcbiAgICB2YXIgbGF5ZXJMaXN0ID0gdGhpcy5sYXllckxpc3Q7XG5cbiAgICBmb3IodmFyIGkgPSBsYXllckxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgbWFwLnJlbW92ZUxheWVyKGxheWVyTGlzdFtpXVsxXSk7XG4gICAgfVxufTtcblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBtYXAgPSB0aGlzLnN1YnBsb3QubWFwO1xuICAgIHRoaXMuX3JlbW92ZUxheWVycygpO1xuICAgIG1hcC5yZW1vdmVTb3VyY2UodGhpcy5zb3VyY2VJZCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyZWF0ZURlbnNpdHlNYXBib3goc3VicGxvdCwgY2FsY1RyYWNlKSB7XG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgIHZhciBkZW5zaXR5TWFwYm94ID0gbmV3IERlbnNpdHlNYXBib3goc3VicGxvdCwgdHJhY2UudWlkKTtcbiAgICB2YXIgc291cmNlSWQgPSBkZW5zaXR5TWFwYm94LnNvdXJjZUlkO1xuICAgIHZhciBvcHRzQWxsID0gY29udmVydChjYWxjVHJhY2UpO1xuICAgIHZhciBiZWxvdyA9IGRlbnNpdHlNYXBib3guYmVsb3cgPSBzdWJwbG90LmJlbG93TG9va3VwWyd0cmFjZS0nICsgdHJhY2UudWlkXTtcblxuICAgIHN1YnBsb3QubWFwLmFkZFNvdXJjZShzb3VyY2VJZCwge1xuICAgICAgICB0eXBlOiAnZ2VvanNvbicsXG4gICAgICAgIGRhdGE6IG9wdHNBbGwuZ2VvanNvblxuICAgIH0pO1xuXG4gICAgZGVuc2l0eU1hcGJveC5fYWRkTGF5ZXJzKG9wdHNBbGwsIGJlbG93KTtcblxuICAgIHJldHVybiBkZW5zaXR5TWFwYm94O1xufTtcblxufSx7XCIuLi8uLi9wbG90cy9tYXBib3gvY29uc3RhbnRzXCI6ODIwLFwiLi9jb252ZXJ0XCI6OTczfV0sOTc5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG4vLyBhcnJheU9rIGF0dHJpYnV0ZXMsIG1lcmdlIHRoZW0gaW50byBjYWxjZGF0YSBhcnJheVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykgY2RbaV0uaSA9IGk7XG5cbiAgICBMaWIubWVyZ2VBcnJheSh0cmFjZS50ZXh0LCBjZCwgJ3R4Jyk7XG4gICAgTGliLm1lcmdlQXJyYXkodHJhY2UuaG92ZXJ0ZXh0LCBjZCwgJ2h0eCcpO1xuXG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlcjtcbiAgICBpZihtYXJrZXIpIHtcbiAgICAgICAgTGliLm1lcmdlQXJyYXkobWFya2VyLm9wYWNpdHksIGNkLCAnbW8nKTtcbiAgICAgICAgTGliLm1lcmdlQXJyYXkobWFya2VyLmNvbG9yLCBjZCwgJ21jJyk7XG5cbiAgICAgICAgdmFyIG1hcmtlckxpbmUgPSBtYXJrZXIubGluZTtcbiAgICAgICAgaWYobWFya2VyTGluZSkge1xuICAgICAgICAgICAgTGliLm1lcmdlQXJyYXkobWFya2VyTGluZS5jb2xvciwgY2QsICdtbGMnKTtcbiAgICAgICAgICAgIExpYi5tZXJnZUFycmF5Q2FzdFBvc2l0aXZlKG1hcmtlckxpbmUud2lkdGgsIGNkLCAnbWx3Jyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOX1dLDk4MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBiYXJBdHRycyA9IF9kZXJlcV8oJy4uL2Jhci9hdHRyaWJ1dGVzJyk7XG52YXIgbGluZUF0dHJzID0gX2RlcmVxXygnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJykubGluZTtcbnZhciBwbG90QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgeDogYmFyQXR0cnMueCxcbiAgICB4MDogYmFyQXR0cnMueDAsXG4gICAgZHg6IGJhckF0dHJzLmR4LFxuICAgIHk6IGJhckF0dHJzLnksXG4gICAgeTA6IGJhckF0dHJzLnkwLFxuICAgIGR5OiBiYXJBdHRycy5keSxcblxuICAgIGhvdmVydGV4dDogYmFyQXR0cnMuaG92ZXJ0ZXh0LFxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycyh7fSwge1xuICAgICAgICBrZXlzOiBjb25zdGFudHMuZXZlbnREYXRhS2V5c1xuICAgIH0pLFxuXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBwbG90QXR0cnMuaG92ZXJpbmZvLCB7XG4gICAgICAgIGZsYWdzOiBbJ25hbWUnLCAneCcsICd5JywgJ3RleHQnLCAncGVyY2VudCBpbml0aWFsJywgJ3BlcmNlbnQgcHJldmlvdXMnLCAncGVyY2VudCB0b3RhbCddXG4gICAgfSksXG5cbiAgICB0ZXh0aW5mbzoge1xuICAgICAgICB2YWxUeXBlOiAnZmxhZ2xpc3QnLFxuICAgICAgICBmbGFnczogWydsYWJlbCcsICd0ZXh0JywgJ3BlcmNlbnQgaW5pdGlhbCcsICdwZXJjZW50IHByZXZpb3VzJywgJ3BlcmNlbnQgdG90YWwnLCAndmFsdWUnXSxcbiAgICAgICAgZXh0cmFzOiBbJ25vbmUnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIGFycmF5T2s6IGZhbHNlLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGV4dDogYmFyQXR0cnMudGV4dCxcbiAgICB0ZXh0cG9zaXRpb246IGV4dGVuZEZsYXQoe30sIGJhckF0dHJzLnRleHRwb3NpdGlvbiwge2RmbHQ6ICdhdXRvJ30pLFxuICAgIGluc2lkZXRleHRhbmNob3I6IGV4dGVuZEZsYXQoe30sIGJhckF0dHJzLmluc2lkZXRleHRhbmNob3IsIHtkZmx0OiAnbWlkZGxlJ30pLFxuICAgIHRleHRhbmdsZTogZXh0ZW5kRmxhdCh7fSwgYmFyQXR0cnMudGV4dGFuZ2xlLCB7ZGZsdDogMH0pLFxuICAgIHRleHRmb250OiBiYXJBdHRycy50ZXh0Zm9udCxcbiAgICBpbnNpZGV0ZXh0Zm9udDogYmFyQXR0cnMuaW5zaWRldGV4dGZvbnQsXG4gICAgb3V0c2lkZXRleHRmb250OiBiYXJBdHRycy5vdXRzaWRldGV4dGZvbnQsXG4gICAgY29uc3RyYWludGV4dDogYmFyQXR0cnMuY29uc3RyYWludGV4dCxcbiAgICBjbGlwb25heGlzOiBiYXJBdHRycy5jbGlwb25heGlzLFxuXG4gICAgb3JpZW50YXRpb246IGV4dGVuZEZsYXQoe30sIGJhckF0dHJzLm9yaWVudGF0aW9uLCB7XG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgb2Zmc2V0OiBleHRlbmRGbGF0KHt9LCBiYXJBdHRycy5vZmZzZXQsIHthcnJheU9rOiBmYWxzZX0pLFxuICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBiYXJBdHRycy53aWR0aCwge2FycmF5T2s6IGZhbHNlfSksXG5cbiAgICBtYXJrZXI6IGJhckF0dHJzLm1hcmtlcixcblxuICAgIGNvbm5lY3Rvcjoge1xuICAgICAgICBmaWxsY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBsaW5lQXR0cnMuY29sb3IsIHtkZmx0OiBDb2xvci5kZWZhdWx0TGluZX0pLFxuICAgICAgICAgICAgd2lkdGg6IGV4dGVuZEZsYXQoe30sIGxpbmVBdHRycy53aWR0aCwge1xuICAgICAgICAgICAgICAgIGRmbHQ6IDAsXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgZGFzaDogbGluZUF0dHJzLmRhc2gsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuXG4gICAgb2Zmc2V0Z3JvdXA6IGJhckF0dHJzLm9mZnNldGdyb3VwLFxuICAgIGFsaWdubWVudGdyb3VwOiBiYXJBdHRycy5hbGlnbm1lbnRncm91cFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXNcIjo2MzEsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NCxcIi4uL2Jhci9hdHRyaWJ1dGVzXCI6ODU3LFwiLi4vc2NhdHRlci9hdHRyaWJ1dGVzXCI6MTExMixcIi4vY29uc3RhbnRzXCI6OTgyfV0sOTgxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGFycmF5c1RvQ2FsY2RhdGEgPSBfZGVyZXFfKCcuL2FycmF5c190b19jYWxjZGF0YScpO1xudmFyIGNhbGNTZWxlY3Rpb24gPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NhbGNfc2VsZWN0aW9uJyk7XG52YXIgQkFETlVNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciB4YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS54YXhpcyB8fCAneCcpO1xuICAgIHZhciB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS55YXhpcyB8fCAneScpO1xuICAgIHZhciBzaXplLCBwb3MsIGksIGNkaTtcblxuICAgIGlmKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgc2l6ZSA9IHhhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3gnKTtcbiAgICAgICAgcG9zID0geWEubWFrZUNhbGNkYXRhKHRyYWNlLCAneScpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNpemUgPSB5YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd5Jyk7XG4gICAgICAgIHBvcyA9IHhhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3gnKTtcbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgdGhlIFwiY2FsY3VsYXRlZCBkYXRhXCIgdG8gcGxvdFxuICAgIHZhciBzZXJpZXNsZW4gPSBNYXRoLm1pbihwb3MubGVuZ3RoLCBzaXplLmxlbmd0aCk7XG4gICAgdmFyIGNkID0gbmV3IEFycmF5KHNlcmllc2xlbik7XG5cbiAgICAvLyBVbmxpa2Ugb3RoZXIgYmFyLWxpa2UgdHJhY2VzIGZ1bm5lbHMgZG8gbm90IHN1cHBvcnQgYmFzZSBhdHRyaWJ1dGUuXG4gICAgLy8gYmFzZXMgZm9yIGZ1bm5lbHMgYXJlIGNvbXB1dGVkIGludGVybmFsbHkgaW4gYSB3YXkgdGhhdFxuICAgIC8vIHRoZSBtaWQtcG9pbnQgb2YgZWFjaCBiYXIgYXJlIGxvY2F0ZWQgb24gdGhlIGF4aXMgbGluZS5cbiAgICB0cmFjZS5fYmFzZSA9IFtdO1xuXG4gICAgLy8gc2V0IHBvc2l0aW9uIGFuZCBzaXplXG4gICAgZm9yKGkgPSAwOyBpIDwgc2VyaWVzbGVuOyBpKyspIHtcbiAgICAgICAgLy8gdHJlYXQgbmVnYXRpdmUgdmFsdWVzIGFzIGJhZCBudW1iZXJzXG4gICAgICAgIGlmKHNpemVbaV0gPCAwKSBzaXplW2ldID0gQkFETlVNO1xuXG4gICAgICAgIHZhciBjb25uZWN0VG9OZXh0ID0gZmFsc2U7XG4gICAgICAgIGlmKHNpemVbaV0gIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgaWYoaSArIDEgPCBzZXJpZXNsZW4gJiYgc2l6ZVtpICsgMV0gIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgIGNvbm5lY3RUb05leHQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY2RpID0gY2RbaV0gPSB7XG4gICAgICAgICAgICBwOiBwb3NbaV0sXG4gICAgICAgICAgICBzOiBzaXplW2ldLFxuICAgICAgICAgICAgY05leHQ6IGNvbm5lY3RUb05leHRcbiAgICAgICAgfTtcblxuICAgICAgICB0cmFjZS5fYmFzZVtpXSA9IC0wLjUgKiBjZGkucztcblxuICAgICAgICBpZih0cmFjZS5pZHMpIHtcbiAgICAgICAgICAgIGNkaS5pZCA9IFN0cmluZyh0cmFjZS5pZHNbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2FsY3VsYXRlIHRvdGFsIHZhbHVlc1xuICAgICAgICBpZihpID09PSAwKSBjZFswXS52VG90YWwgPSAwO1xuICAgICAgICBjZFswXS52VG90YWwgKz0gZml4TnVtKGNkaS5zKTtcblxuICAgICAgICAvLyByYXRpbyBmcm9tIGluaXRpYWwgdmFsdWVcbiAgICAgICAgY2RpLmJlZ1IgPSBmaXhOdW0oY2RpLnMpIC8gZml4TnVtKGNkWzBdLnMpO1xuICAgIH1cblxuICAgIHZhciBwcmV2R29vZE51bTtcbiAgICBmb3IoaSA9IDA7IGkgPCBzZXJpZXNsZW47IGkrKykge1xuICAgICAgICBjZGkgPSBjZFtpXTtcbiAgICAgICAgaWYoY2RpLnMgPT09IEJBRE5VTSkgY29udGludWU7XG5cbiAgICAgICAgLy8gcmF0aW8gb2YgdG90YWwgdmFsdWVcbiAgICAgICAgY2RpLnN1bVIgPSBjZGkucyAvIGNkWzBdLnZUb3RhbDtcblxuICAgICAgICAvLyByYXRpbyBvZiBwcmV2aW91cyAoZ29vZCkgdmFsdWVcbiAgICAgICAgY2RpLmRpZlIgPSAocHJldkdvb2ROdW0gIT09IHVuZGVmaW5lZCkgPyBjZGkucyAvIHByZXZHb29kTnVtIDogMTtcblxuICAgICAgICBwcmV2R29vZE51bSA9IGNkaS5zO1xuICAgIH1cblxuICAgIGFycmF5c1RvQ2FsY2RhdGEoY2QsIHRyYWNlKTtcbiAgICBjYWxjU2VsZWN0aW9uKGNkLCB0cmFjZSk7XG5cbiAgICByZXR1cm4gY2Q7XG59O1xuXG5mdW5jdGlvbiBmaXhOdW0oYSkge1xuICAgIHJldHVybiAoYSA9PT0gQkFETlVNKSA/IDAgOiBhO1xufVxuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb25cIjoxMTE0LFwiLi9hcnJheXNfdG9fY2FsY2RhdGFcIjo5Nzl9XSw5ODI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBldmVudERhdGFLZXlzOiBbXG4gICAgICAgICdwZXJjZW50SW5pdGlhbCcsXG4gICAgICAgICdwZXJjZW50UHJldmlvdXMnLFxuICAgICAgICAncGVyY2VudFRvdGFsJ1xuICAgIF1cbn07XG5cbn0se31dLDk4MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzZXRHcm91cFBvc2l0aW9ucyA9IF9kZXJlcV8oJy4uL2Jhci9jcm9zc190cmFjZV9jYWxjJykuc2V0R3JvdXBQb3NpdGlvbnM7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3Jvc3NUcmFjZUNhbGMoZ2QsIHBsb3RpbmZvKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZnVsbERhdGEgPSBnZC5fZnVsbERhdGE7XG4gICAgdmFyIGNhbGNkYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG4gICAgdmFyIGZ1bm5lbHMgPSBbXTtcbiAgICB2YXIgZnVubmVsc1ZlcnQgPSBbXTtcbiAgICB2YXIgZnVubmVsc0hvcnogPSBbXTtcbiAgICB2YXIgY2QsIGk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZnVsbFRyYWNlID0gZnVsbERhdGFbaV07XG4gICAgICAgIHZhciBpc0hvcml6b250YWwgPSAoZnVsbFRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpO1xuXG4gICAgICAgIGlmKFxuICAgICAgICAgICAgZnVsbFRyYWNlLnZpc2libGUgPT09IHRydWUgJiZcbiAgICAgICAgICAgIGZ1bGxUcmFjZS54YXhpcyA9PT0geGEuX2lkICYmXG4gICAgICAgICAgICBmdWxsVHJhY2UueWF4aXMgPT09IHlhLl9pZCAmJlxuICAgICAgICAgICAgZnVsbFRyYWNlLnR5cGUgPT09ICdmdW5uZWwnXG4gICAgICAgICkge1xuICAgICAgICAgICAgY2QgPSBjYWxjZGF0YVtpXTtcblxuICAgICAgICAgICAgaWYoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICAgICAgZnVubmVsc0hvcnoucHVzaChjZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZ1bm5lbHNWZXJ0LnB1c2goY2QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5uZWxzLnB1c2goY2QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIG9wdHMgPSB7XG4gICAgICAgIG1vZGU6IGZ1bGxMYXlvdXQuZnVubmVsbW9kZSxcbiAgICAgICAgbm9ybTogZnVsbExheW91dC5mdW5uZWxub3JtLFxuICAgICAgICBnYXA6IGZ1bGxMYXlvdXQuZnVubmVsZ2FwLFxuICAgICAgICBncm91cGdhcDogZnVsbExheW91dC5mdW5uZWxncm91cGdhcFxuICAgIH07XG5cbiAgICBzZXRHcm91cFBvc2l0aW9ucyhnZCwgeGEsIHlhLCBmdW5uZWxzVmVydCwgb3B0cyk7XG4gICAgc2V0R3JvdXBQb3NpdGlvbnMoZ2QsIHlhLCB4YSwgZnVubmVsc0hvcnosIG9wdHMpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgZnVubmVscy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjZCA9IGZ1bm5lbHNbaV07XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZihqICsgMSA8IGNkLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGNkW2pdLm5leHRQMCA9IGNkW2ogKyAxXS5wMDtcbiAgICAgICAgICAgICAgICBjZFtqXS5uZXh0UzAgPSBjZFtqICsgMV0uczA7XG5cbiAgICAgICAgICAgICAgICBjZFtqXS5uZXh0UDEgPSBjZFtqICsgMV0ucDE7XG4gICAgICAgICAgICAgICAgY2Rbal0ubmV4dFMxID0gY2RbaiArIDFdLnMxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxufSx7XCIuLi9iYXIvY3Jvc3NfdHJhY2VfY2FsY1wiOjg2MH1dLDk4NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIGhhbmRsZUdyb3VwaW5nRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9iYXIvZGVmYXVsdHMnKS5oYW5kbGVHcm91cGluZ0RlZmF1bHRzO1xudmFyIGhhbmRsZVRleHQgPSBfZGVyZXFfKCcuLi9iYXIvZGVmYXVsdHMnKS5oYW5kbGVUZXh0O1xudmFyIGhhbmRsZVhZRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3h5X2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG5mdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgnb3JpZW50YXRpb24nLCAodHJhY2VPdXQueSAmJiAhdHJhY2VPdXQueCkgPyAndicgOiAnaCcpO1xuICAgIGNvZXJjZSgnb2Zmc2V0Jyk7XG4gICAgY29lcmNlKCd3aWR0aCcpO1xuXG4gICAgdmFyIHRleHQgPSBjb2VyY2UoJ3RleHQnKTtcblxuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG5cbiAgICB2YXIgdGV4dHBvc2l0aW9uID0gY29lcmNlKCd0ZXh0cG9zaXRpb24nKTtcbiAgICBoYW5kbGVUZXh0KHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwgdGV4dHBvc2l0aW9uLCB7XG4gICAgICAgIG1vZHVsZUhhc1NlbGVjdGVkOiBmYWxzZSxcbiAgICAgICAgbW9kdWxlSGFzVW5zZWxlY3RlZDogZmFsc2UsXG4gICAgICAgIG1vZHVsZUhhc0NvbnN0cmFpbjogdHJ1ZSxcbiAgICAgICAgbW9kdWxlSGFzQ2xpcG9uYXhpczogdHJ1ZSxcbiAgICAgICAgbW9kdWxlSGFzVGV4dGFuZ2xlOiB0cnVlLFxuICAgICAgICBtb2R1bGVIYXNJbnNpZGVhbmNob3I6IHRydWVcbiAgICB9KTtcblxuICAgIGlmKHRyYWNlT3V0LnRleHRwb3NpdGlvbiAhPT0gJ25vbmUnKSB7XG4gICAgICAgIGNvZXJjZSgndGV4dGluZm8nLCBBcnJheS5pc0FycmF5KHRleHQpID8gJ3RleHQrdmFsdWUnIDogJ3ZhbHVlJyk7XG4gICAgfVxuXG4gICAgdmFyIG1hcmtlckNvbG9yID0gY29lcmNlKCdtYXJrZXIuY29sb3InLCBkZWZhdWx0Q29sb3IpO1xuICAgIGNvZXJjZSgnbWFya2VyLmxpbmUuY29sb3InLCBDb2xvci5kZWZhdWx0TGluZSk7XG4gICAgY29lcmNlKCdtYXJrZXIubGluZS53aWR0aCcpO1xuXG4gICAgdmFyIGNvbm5lY3RvclZpc2libGUgPSBjb2VyY2UoJ2Nvbm5lY3Rvci52aXNpYmxlJyk7XG4gICAgaWYoY29ubmVjdG9yVmlzaWJsZSkge1xuICAgICAgICBjb2VyY2UoJ2Nvbm5lY3Rvci5maWxsY29sb3InLCBkZWZhdWx0RmlsbENvbG9yKG1hcmtlckNvbG9yKSk7XG5cbiAgICAgICAgdmFyIGNvbm5lY3RvckxpbmVXaWR0aCA9IGNvZXJjZSgnY29ubmVjdG9yLmxpbmUud2lkdGgnKTtcbiAgICAgICAgaWYoY29ubmVjdG9yTGluZVdpZHRoKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ2Nvbm5lY3Rvci5saW5lLmNvbG9yJyk7XG4gICAgICAgICAgICBjb2VyY2UoJ2Nvbm5lY3Rvci5saW5lLmRhc2gnKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZGVmYXVsdEZpbGxDb2xvcihtYXJrZXJDb2xvcikge1xuICAgIHZhciBjQmFzZSA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG1hcmtlckNvbG9yKSA/ICcjMDAwJyA6IG1hcmtlckNvbG9yO1xuXG4gICAgcmV0dXJuIENvbG9yLmFkZE9wYWNpdHkoY0Jhc2UsIDAuNSAqIENvbG9yLm9wYWNpdHkoY0Jhc2UpKTtcbn1cblxuZnVuY3Rpb24gY3Jvc3NUcmFjZURlZmF1bHRzKGZ1bGxEYXRhLCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIHRyYWNlSW4sIHRyYWNlT3V0O1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VPdXQuX2lucHV0LCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0cik7XG4gICAgfVxuXG4gICAgaWYoZnVsbExheW91dC5mdW5uZWxtb2RlID09PSAnZ3JvdXAnKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdHJhY2VPdXQgPSBmdWxsRGF0YVtpXTtcbiAgICAgICAgICAgIHRyYWNlSW4gPSB0cmFjZU91dC5faW5wdXQ7XG5cbiAgICAgICAgICAgIGhhbmRsZUdyb3VwaW5nRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGZ1bGxMYXlvdXQsIGNvZXJjZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN1cHBseURlZmF1bHRzOiBzdXBwbHlEZWZhdWx0cyxcbiAgICBjcm9zc1RyYWNlRGVmYXVsdHM6IGNyb3NzVHJhY2VEZWZhdWx0c1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vYmFyL2RlZmF1bHRzXCI6ODYxLFwiLi4vc2NhdHRlci94eV9kZWZhdWx0c1wiOjExMzcsXCIuL2F0dHJpYnV0ZXNcIjo5ODB9XSw5ODU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0IC8qICwgdHJhY2UsIGNkLCBwb2ludE51bWJlciAqLykge1xuICAgIC8vIHN0YW5kYXJkIGNhcnRlc2lhbiBldmVudCBkYXRhXG4gICAgb3V0LnggPSAneFZhbCcgaW4gcHQgPyBwdC54VmFsIDogcHQueDtcbiAgICBvdXQueSA9ICd5VmFsJyBpbiBwdCA/IHB0LnlWYWwgOiBwdC55O1xuXG4gICAgLy8gZm9yIGZ1bm5lbFxuICAgIGlmKCdwZXJjZW50SW5pdGlhbCcgaW4gcHQpIG91dC5wZXJjZW50SW5pdGlhbCA9IHB0LnBlcmNlbnRJbml0aWFsO1xuICAgIGlmKCdwZXJjZW50UHJldmlvdXMnIGluIHB0KSBvdXQucGVyY2VudFByZXZpb3VzID0gcHQucGVyY2VudFByZXZpb3VzO1xuICAgIGlmKCdwZXJjZW50VG90YWwnIGluIHB0KSBvdXQucGVyY2VudFRvdGFsID0gcHQucGVyY2VudFRvdGFsO1xuXG4gICAgaWYocHQueGEpIG91dC54YXhpcyA9IHB0LnhhO1xuICAgIGlmKHB0LnlhKSBvdXQueWF4aXMgPSBwdC55YTtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG59LHt9XSw5ODY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgb3BhY2l0eSA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKS5vcGFjaXR5O1xudmFyIGhvdmVyT25CYXJzID0gX2RlcmVxXygnLi4vYmFyL2hvdmVyJykuaG92ZXJPbkJhcnM7XG52YXIgZm9ybWF0UGVyY2VudCA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmZvcm1hdFBlcmNlbnQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgcG9pbnQgPSBob3Zlck9uQmFycyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSk7XG4gICAgaWYoIXBvaW50KSByZXR1cm47XG5cbiAgICB2YXIgY2QgPSBwb2ludC5jZDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgaXNIb3Jpem9udGFsID0gKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpO1xuXG4gICAgLy8gdGhlIGNsb3Nlc3QgZGF0YSBwb2ludFxuICAgIHZhciBpbmRleCA9IHBvaW50LmluZGV4O1xuICAgIHZhciBkaSA9IGNkW2luZGV4XTtcblxuICAgIHZhciBzaXplTGV0dGVyID0gaXNIb3Jpem9udGFsID8gJ3gnIDogJ3knO1xuICAgIHBvaW50W3NpemVMZXR0ZXIgKyAnTGFiZWxWYWwnXSA9IGRpLnM7XG5cbiAgICBwb2ludC5wZXJjZW50SW5pdGlhbCA9IGRpLmJlZ1I7XG4gICAgcG9pbnQucGVyY2VudEluaXRpYWxMYWJlbCA9IGZvcm1hdFBlcmNlbnQoZGkuYmVnUiwgMSk7XG5cbiAgICBwb2ludC5wZXJjZW50UHJldmlvdXMgPSBkaS5kaWZSO1xuICAgIHBvaW50LnBlcmNlbnRQcmV2aW91c0xhYmVsID0gZm9ybWF0UGVyY2VudChkaS5kaWZSLCAxKTtcblxuICAgIHBvaW50LnBlcmNlbnRUb3RhbCA9IGRpLnN1bVI7XG4gICAgcG9pbnQucGVyY2VudFRvdGFsTGFiZWwgPSBmb3JtYXRQZXJjZW50KGRpLnN1bVIsIDEpO1xuXG4gICAgdmFyIGhvdmVyaW5mbyA9IGRpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgdGV4dCA9IFtdO1xuICAgIGlmKGhvdmVyaW5mbyAmJiBob3ZlcmluZm8gIT09ICdub25lJyAmJiBob3ZlcmluZm8gIT09ICdza2lwJykge1xuICAgICAgICB2YXIgaXNBbGwgPSAoaG92ZXJpbmZvID09PSAnYWxsJyk7XG4gICAgICAgIHZhciBwYXJ0cyA9IGhvdmVyaW5mby5zcGxpdCgnKycpO1xuXG4gICAgICAgIHZhciBoYXNGbGFnID0gZnVuY3Rpb24oZmxhZykgeyByZXR1cm4gaXNBbGwgfHwgcGFydHMuaW5kZXhPZihmbGFnKSAhPT0gLTE7IH07XG5cbiAgICAgICAgaWYoaGFzRmxhZygncGVyY2VudCBpbml0aWFsJykpIHtcbiAgICAgICAgICAgIHRleHQucHVzaChwb2ludC5wZXJjZW50SW5pdGlhbExhYmVsICsgJyBvZiBpbml0aWFsJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaGFzRmxhZygncGVyY2VudCBwcmV2aW91cycpKSB7XG4gICAgICAgICAgICB0ZXh0LnB1c2gocG9pbnQucGVyY2VudFByZXZpb3VzTGFiZWwgKyAnIG9mIHByZXZpb3VzJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoaGFzRmxhZygncGVyY2VudCB0b3RhbCcpKSB7XG4gICAgICAgICAgICB0ZXh0LnB1c2gocG9pbnQucGVyY2VudFRvdGFsTGFiZWwgKyAnIG9mIHRvdGFsJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcG9pbnQuZXh0cmFUZXh0ID0gdGV4dC5qb2luKCc8YnI+Jyk7XG5cbiAgICBwb2ludC5jb2xvciA9IGdldFRyYWNlQ29sb3IodHJhY2UsIGRpKTtcblxuICAgIHJldHVybiBbcG9pbnRdO1xufTtcblxuZnVuY3Rpb24gZ2V0VHJhY2VDb2xvcih0cmFjZSwgZGkpIHtcbiAgICB2YXIgY29udCA9IHRyYWNlLm1hcmtlcjtcbiAgICB2YXIgbWMgPSBkaS5tYyB8fCBjb250LmNvbG9yO1xuICAgIHZhciBtbGMgPSBkaS5tbGMgfHwgY29udC5saW5lLmNvbG9yO1xuICAgIHZhciBtbHcgPSBkaS5tbHcgfHwgY29udC5saW5lLndpZHRoO1xuICAgIGlmKG9wYWNpdHkobWMpKSByZXR1cm4gbWM7XG4gICAgZWxzZSBpZihvcGFjaXR5KG1sYykgJiYgbWx3KSByZXR1cm4gbWxjO1xufVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9saWJcIjo3MTksXCIuLi9iYXIvaG92ZXJcIjo4NjN9XSw5ODc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKS5zdXBwbHlEZWZhdWx0cyxcbiAgICBjcm9zc1RyYWNlRGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKS5jcm9zc1RyYWNlRGVmYXVsdHMsXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2RlZmF1bHRzJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgY3Jvc3NUcmFjZUNhbGM6IF9kZXJlcV8oJy4vY3Jvc3NfdHJhY2VfY2FsYycpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuL3N0eWxlJykuc3R5bGUsXG4gICAgaG92ZXJQb2ludHM6IF9kZXJlcV8oJy4vaG92ZXInKSxcbiAgICBldmVudERhdGE6IF9kZXJlcV8oJy4vZXZlbnRfZGF0YScpLFxuXG4gICAgc2VsZWN0UG9pbnRzOiBfZGVyZXFfKCcuLi9iYXIvc2VsZWN0JyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdmdW5uZWwnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKSxcbiAgICBjYXRlZ29yaWVzOiBbJ2Jhci1saWtlJywgJ2NhcnRlc2lhbicsICdzdmcnLCAnb3JpZW50ZWQnLCAnc2hvd0xlZ2VuZCcsICd6b29tU2NhbGUnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvY2FydGVzaWFuXCI6Nzc4LFwiLi4vYmFyL3NlbGVjdFwiOjg2OCxcIi4vYXR0cmlidXRlc1wiOjk4MCxcIi4vY2FsY1wiOjk4MSxcIi4vY3Jvc3NfdHJhY2VfY2FsY1wiOjk4MyxcIi4vZGVmYXVsdHNcIjo5ODQsXCIuL2V2ZW50X2RhdGFcIjo5ODUsXCIuL2hvdmVyXCI6OTg2LFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjk4OCxcIi4vbGF5b3V0X2RlZmF1bHRzXCI6OTg5LFwiLi9wbG90XCI6OTkwLFwiLi9zdHlsZVwiOjk5MX1dLDk4ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGZ1bm5lbG1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnc3RhY2snLCAnZ3JvdXAnLCAnb3ZlcmxheSddLFxuICAgICAgICBkZmx0OiAnc3RhY2snLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBmdW5uZWxnYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBmdW5uZWxncm91cGdhcDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHt9XSw5ODk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSkge1xuICAgIHZhciBoYXNUcmFjZVR5cGUgPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGxheW91dEluLCBsYXlvdXRPdXQsIGxheW91dEF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2UgPSBmdWxsRGF0YVtpXTtcblxuICAgICAgICBpZih0cmFjZS52aXNpYmxlICYmIHRyYWNlLnR5cGUgPT09ICdmdW5uZWwnKSB7XG4gICAgICAgICAgICBoYXNUcmFjZVR5cGUgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihoYXNUcmFjZVR5cGUpIHtcbiAgICAgICAgY29lcmNlKCdmdW5uZWxtb2RlJyk7XG4gICAgICAgIGNvZXJjZSgnZnVubmVsZ2FwJywgMC4yKTtcbiAgICAgICAgY29lcmNlKCdmdW5uZWxncm91cGdhcCcpO1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjk4OH1dLDk5MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIGJhclBsb3QgPSBfZGVyZXFfKCcuLi9iYXIvcGxvdCcpLnBsb3Q7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgcGxvdGluZm8sIGNkTW9kdWxlLCB0cmFjZUxheWVyKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcblxuICAgIHBsb3RDb25uZWN0b3JSZWdpb25zKGdkLCBwbG90aW5mbywgY2RNb2R1bGUsIHRyYWNlTGF5ZXIpO1xuICAgIHBsb3RDb25uZWN0b3JMaW5lcyhnZCwgcGxvdGluZm8sIGNkTW9kdWxlLCB0cmFjZUxheWVyKTtcblxuICAgIGJhclBsb3QoZ2QsIHBsb3RpbmZvLCBjZE1vZHVsZSwgdHJhY2VMYXllciwge1xuICAgICAgICBtb2RlOiBmdWxsTGF5b3V0LmZ1bm5lbG1vZGUsXG4gICAgICAgIG5vcm06IGZ1bGxMYXlvdXQuZnVubmVsbW9kZSxcbiAgICAgICAgZ2FwOiBmdWxsTGF5b3V0LmZ1bm5lbGdhcCxcbiAgICAgICAgZ3JvdXBnYXA6IGZ1bGxMYXlvdXQuZnVubmVsZ3JvdXBnYXBcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIHBsb3RDb25uZWN0b3JSZWdpb25zKGdkLCBwbG90aW5mbywgY2RNb2R1bGUsIHRyYWNlTGF5ZXIpIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIExpYi5tYWtlVHJhY2VHcm91cHModHJhY2VMYXllciwgY2RNb2R1bGUsICd0cmFjZSBiYXJzJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgICAgICB2YXIgZ3JvdXAgPSBMaWIuZW5zdXJlU2luZ2xlKHBsb3RHcm91cCwgJ2cnLCAncmVnaW9ucycpO1xuXG4gICAgICAgIGlmKCF0cmFjZS5jb25uZWN0b3IgfHwgIXRyYWNlLmNvbm5lY3Rvci52aXNpYmxlKSB7XG4gICAgICAgICAgICBncm91cC5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpc0hvcml6b250YWwgPSAodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJyk7XG5cbiAgICAgICAgdmFyIGNvbm5lY3RvcnMgPSBncm91cC5zZWxlY3RBbGwoJ2cucmVnaW9uJykuZGF0YShMaWIuaWRlbnRpdHkpO1xuXG4gICAgICAgIGNvbm5lY3RvcnMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAgICAgLmNsYXNzZWQoJ3JlZ2lvbicsIHRydWUpO1xuXG4gICAgICAgIGNvbm5lY3RvcnMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIHZhciBsZW4gPSBjb25uZWN0b3JzLnNpemUoKTtcblxuICAgICAgICBjb25uZWN0b3JzLmVhY2goZnVuY3Rpb24oZGksIGkpIHtcbiAgICAgICAgICAgIC8vIGRvbid0IGRyYXcgbGluZXMgYmV0d2VlbiBudWxsc1xuICAgICAgICAgICAgaWYoaSAhPT0gbGVuIC0gMSAmJiAhZGkuY05leHQpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIHh5ID0gZ2V0WFkoZGksIHhhLCB5YSwgaXNIb3Jpem9udGFsKTtcbiAgICAgICAgICAgIHZhciB4ID0geHlbMF07XG4gICAgICAgICAgICB2YXIgeSA9IHh5WzFdO1xuXG4gICAgICAgICAgICB2YXIgc2hhcGUgPSAnJztcblxuICAgICAgICAgICAgaWYoeFszXSAhPT0gdW5kZWZpbmVkICYmIHlbM10gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmKGlzSG9yaXpvbnRhbCkge1xuICAgICAgICAgICAgICAgICAgICBzaGFwZSArPSAnTScgKyB4WzBdICsgJywnICsgeVsxXSArICdMJyArIHhbMl0gKyAnLCcgKyB5WzJdICsgJ0gnICsgeFszXSArICdMJyArIHhbMV0gKyAnLCcgKyB5WzFdICsgJ1onO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNoYXBlICs9ICdNJyArIHhbMV0gKyAnLCcgKyB5WzFdICsgJ0wnICsgeFsyXSArICcsJyArIHlbM10gKyAnVicgKyB5WzJdICsgJ0wnICsgeFsxXSArICcsJyArIHlbMF0gKyAnWic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGQzLnNlbGVjdCh0aGlzKSwgJ3BhdGgnKVxuICAgICAgICAgICAgICAgIC5hdHRyKCdkJywgc2hhcGUpXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRDbGlwVXJsLCBwbG90aW5mby5sYXllckNsaXBJZCwgZ2QpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gcGxvdENvbm5lY3RvckxpbmVzKGdkLCBwbG90aW5mbywgY2RNb2R1bGUsIHRyYWNlTGF5ZXIpIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIExpYi5tYWtlVHJhY2VHcm91cHModHJhY2VMYXllciwgY2RNb2R1bGUsICd0cmFjZSBiYXJzJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgICAgICB2YXIgZ3JvdXAgPSBMaWIuZW5zdXJlU2luZ2xlKHBsb3RHcm91cCwgJ2cnLCAnbGluZXMnKTtcblxuICAgICAgICBpZighdHJhY2UuY29ubmVjdG9yIHx8ICF0cmFjZS5jb25uZWN0b3IudmlzaWJsZSB8fCAhdHJhY2UuY29ubmVjdG9yLmxpbmUud2lkdGgpIHtcbiAgICAgICAgICAgIGdyb3VwLnJlbW92ZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlzSG9yaXpvbnRhbCA9ICh0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKTtcblxuICAgICAgICB2YXIgY29ubmVjdG9ycyA9IGdyb3VwLnNlbGVjdEFsbCgnZy5saW5lJykuZGF0YShMaWIuaWRlbnRpdHkpO1xuXG4gICAgICAgIGNvbm5lY3RvcnMuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAgICAgLmNsYXNzZWQoJ2xpbmUnLCB0cnVlKTtcblxuICAgICAgICBjb25uZWN0b3JzLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgICAgICB2YXIgbGVuID0gY29ubmVjdG9ycy5zaXplKCk7XG5cbiAgICAgICAgY29ubmVjdG9ycy5lYWNoKGZ1bmN0aW9uKGRpLCBpKSB7XG4gICAgICAgICAgICAvLyBkb24ndCBkcmF3IGxpbmVzIGJldHdlZW4gbnVsbHNcbiAgICAgICAgICAgIGlmKGkgIT09IGxlbiAtIDEgJiYgIWRpLmNOZXh0KSByZXR1cm47XG5cbiAgICAgICAgICAgIHZhciB4eSA9IGdldFhZKGRpLCB4YSwgeWEsIGlzSG9yaXpvbnRhbCk7XG4gICAgICAgICAgICB2YXIgeCA9IHh5WzBdO1xuICAgICAgICAgICAgdmFyIHkgPSB4eVsxXTtcblxuICAgICAgICAgICAgdmFyIHNoYXBlID0gJyc7XG5cbiAgICAgICAgICAgIGlmKHhbM10gIT09IHVuZGVmaW5lZCAmJiB5WzNdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZihpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgc2hhcGUgKz0gJ00nICsgeFswXSArICcsJyArIHlbMV0gKyAnTCcgKyB4WzJdICsgJywnICsgeVsyXTtcbiAgICAgICAgICAgICAgICAgICAgc2hhcGUgKz0gJ00nICsgeFsxXSArICcsJyArIHlbMV0gKyAnTCcgKyB4WzNdICsgJywnICsgeVsyXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzaGFwZSArPSAnTScgKyB4WzFdICsgJywnICsgeVsxXSArICdMJyArIHhbMl0gKyAnLCcgKyB5WzNdO1xuICAgICAgICAgICAgICAgICAgICBzaGFwZSArPSAnTScgKyB4WzFdICsgJywnICsgeVswXSArICdMJyArIHhbMl0gKyAnLCcgKyB5WzJdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoc2hhcGUgPT09ICcnKSBzaGFwZSA9ICdNMCwwWic7XG5cbiAgICAgICAgICAgIExpYi5lbnN1cmVTaW5nbGUoZDMuc2VsZWN0KHRoaXMpLCAncGF0aCcpXG4gICAgICAgICAgICAgICAgLmF0dHIoJ2QnLCBzaGFwZSlcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNldENsaXBVcmwsIHBsb3RpbmZvLmxheWVyQ2xpcElkLCBnZCk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRYWShkaSwgeGEsIHlhLCBpc0hvcml6b250YWwpIHtcbiAgICB2YXIgcyA9IFtdO1xuICAgIHZhciBwID0gW107XG5cbiAgICB2YXIgc0F4aXMgPSBpc0hvcml6b250YWwgPyB4YSA6IHlhO1xuICAgIHZhciBwQXhpcyA9IGlzSG9yaXpvbnRhbCA/IHlhIDogeGE7XG5cbiAgICBzWzBdID0gc0F4aXMuYzJwKGRpLnMwLCB0cnVlKTtcbiAgICBwWzBdID0gcEF4aXMuYzJwKGRpLnAwLCB0cnVlKTtcblxuICAgIHNbMV0gPSBzQXhpcy5jMnAoZGkuczEsIHRydWUpO1xuICAgIHBbMV0gPSBwQXhpcy5jMnAoZGkucDEsIHRydWUpO1xuXG4gICAgc1syXSA9IHNBeGlzLmMycChkaS5uZXh0UzAsIHRydWUpO1xuICAgIHBbMl0gPSBwQXhpcy5jMnAoZGkubmV4dFAwLCB0cnVlKTtcblxuICAgIHNbM10gPSBzQXhpcy5jMnAoZGkubmV4dFMxLCB0cnVlKTtcbiAgICBwWzNdID0gcEF4aXMuYzJwKGRpLm5leHRQMSwgdHJ1ZSk7XG5cbiAgICByZXR1cm4gaXNIb3Jpem9udGFsID8gW3MsIHBdIDogW3AsIHNdO1xufVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2Jhci9wbG90XCI6ODY3LFwiZDNcIjoxNjN9XSw5OTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERFU0VMRUNURElNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2ludGVyYWN0aW9ucycpLkRFU0VMRUNURElNO1xuXG52YXIgc3R5bGVUZXh0UG9pbnRzID0gX2RlcmVxXygnLi4vYmFyL3N0eWxlJykuc3R5bGVUZXh0UG9pbnRzO1xuXG5mdW5jdGlvbiBzdHlsZShnZCwgY2QsIHNlbCkge1xuICAgIHZhciBzID0gc2VsID8gc2VsIDogZDMuc2VsZWN0KGdkKS5zZWxlY3RBbGwoJ2cuZnVubmVsbGF5ZXInKS5zZWxlY3RBbGwoJ2cudHJhY2UnKTtcblxuICAgIHMuc3R5bGUoJ29wYWNpdHknLCBmdW5jdGlvbihkKSB7IHJldHVybiBkWzBdLnRyYWNlLm9wYWNpdHk7IH0pO1xuXG4gICAgcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIGdUcmFjZSA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZTtcblxuICAgICAgICBnVHJhY2Uuc2VsZWN0QWxsKCcucG9pbnQgPiBwYXRoJykuZWFjaChmdW5jdGlvbihkaSkge1xuICAgICAgICAgICAgaWYoIWRpLmlzQmxhbmspIHtcbiAgICAgICAgICAgICAgICB2YXIgY29udCA9IHRyYWNlLm1hcmtlcjtcblxuICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBkaS5tYyB8fCBjb250LmNvbG9yKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIGRpLm1sYyB8fCBjb250LmxpbmUuY29sb3IpXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZGFzaExpbmUsIGNvbnQubGluZS5kYXNoLCBkaS5tbHcgfHwgY29udC5saW5lLndpZHRoKVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCB0cmFjZS5zZWxlY3RlZHBvaW50cyAmJiAhZGkuc2VsZWN0ZWQgPyBERVNFTEVDVERJTSA6IDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBzdHlsZVRleHRQb2ludHMoZ1RyYWNlLCB0cmFjZSwgZ2QpO1xuXG4gICAgICAgIGdUcmFjZS5zZWxlY3RBbGwoJy5yZWdpb25zJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ3BhdGgnKS5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgMCkuY2FsbChDb2xvci5maWxsLCB0cmFjZS5jb25uZWN0b3IuZmlsbGNvbG9yKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZ1RyYWNlLnNlbGVjdEFsbCgnLmxpbmVzJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBjb250ID0gdHJhY2UuY29ubmVjdG9yLmxpbmU7XG5cbiAgICAgICAgICAgIERyYXdpbmcubGluZUdyb3VwU3R5bGUoXG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgncGF0aCcpLFxuICAgICAgICAgICAgICAgIGNvbnQud2lkdGgsXG4gICAgICAgICAgICAgICAgY29udC5jb2xvcixcbiAgICAgICAgICAgICAgICBjb250LmRhc2hcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBzdHlsZTogc3R5bGVcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2NvbnN0YW50cy9pbnRlcmFjdGlvbnNcIjo2OTQsXCIuLi9iYXIvc3R5bGVcIjo4NzAsXCJkM1wiOjE2M31dLDk5MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBwaWVBdHRycyA9IF9kZXJlcV8oJy4uL3BpZS9hdHRyaWJ1dGVzJyk7XG52YXIgcGxvdEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZG9tYWluJykuYXR0cmlidXRlcztcbnZhciBob3ZlcnRlbXBsYXRlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlcycpO1xuXG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBsYWJlbHM6IHBpZUF0dHJzLmxhYmVscyxcbiAgICAvLyBlcXVpdmFsZW50IG9mIHgwIGFuZCBkeCwgaWYgbGFiZWwgaXMgbWlzc2luZ1xuICAgIGxhYmVsMDogcGllQXR0cnMubGFiZWwwLFxuICAgIGRsYWJlbDogcGllQXR0cnMuZGxhYmVsLFxuICAgIHZhbHVlczogcGllQXR0cnMudmFsdWVzLFxuXG4gICAgbWFya2VyOiB7XG4gICAgICAgIGNvbG9yczogcGllQXR0cnMubWFya2VyLmNvbG9ycyxcbiAgICAgICAgbGluZToge1xuICAgICAgICAgICAgY29sb3I6IGV4dGVuZEZsYXQoe30sIHBpZUF0dHJzLm1hcmtlci5saW5lLmNvbG9yLCB7XG4gICAgICAgICAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgd2lkdGg6IGV4dGVuZEZsYXQoe30sIHBpZUF0dHJzLm1hcmtlci5saW5lLndpZHRoLCB7ZGZsdDogMX0pLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcblxuICAgIHRleHQ6IHBpZUF0dHJzLnRleHQsXG4gICAgaG92ZXJ0ZXh0OiBwaWVBdHRycy5ob3ZlcnRleHQsXG5cbiAgICBzY2FsZWdyb3VwOiBleHRlbmRGbGF0KHt9LCBwaWVBdHRycy5zY2FsZWdyb3VwLCB7XG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgdGV4dGluZm86IGV4dGVuZEZsYXQoe30sIHBpZUF0dHJzLnRleHRpbmZvLCB7XG4gICAgICAgIGZsYWdzOiBbJ2xhYmVsJywgJ3RleHQnLCAndmFsdWUnLCAncGVyY2VudCddXG4gICAgfSksXG5cbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIHBsb3RBdHRycy5ob3ZlcmluZm8sIHtcbiAgICAgICAgZmxhZ3M6IFsnbGFiZWwnLCAndGV4dCcsICd2YWx1ZScsICdwZXJjZW50JywgJ25hbWUnXVxuICAgIH0pLFxuXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKHt9LCB7XG4gICAgICAgIGtleXM6IFsnbGFiZWwnLCAnY29sb3InLCAndmFsdWUnLCAncGVyY2VudCcsICd0ZXh0J11cbiAgICB9KSxcblxuICAgIHRleHRwb3NpdGlvbjogZXh0ZW5kRmxhdCh7fSwgcGllQXR0cnMudGV4dHBvc2l0aW9uLCB7XG4gICAgICAgIHZhbHVlczogWydpbnNpZGUnLCAnbm9uZSddLFxuICAgICAgICBkZmx0OiAnaW5zaWRlJ1xuICAgIH0pLFxuXG4gICAgdGV4dGZvbnQ6IHBpZUF0dHJzLnRleHRmb250LFxuICAgIGluc2lkZXRleHRmb250OiBwaWVBdHRycy5pbnNpZGV0ZXh0Zm9udCxcblxuICAgIHRpdGxlOiB7XG4gICAgICAgIHRleHQ6IHBpZUF0dHJzLnRpdGxlLnRleHQsXG4gICAgICAgIGZvbnQ6IHBpZUF0dHJzLnRpdGxlLmZvbnQsXG4gICAgICAgIHBvc2l0aW9uOiBleHRlbmRGbGF0KHt9LCBwaWVBdHRycy50aXRsZS5wb3NpdGlvbiwge1xuICAgICAgICAgICAgdmFsdWVzOiBbJ3RvcCBsZWZ0JywgJ3RvcCBjZW50ZXInLCAndG9wIHJpZ2h0J10sXG4gICAgICAgICAgICBkZmx0OiAndG9wIGNlbnRlcidcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuXG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ2Z1bm5lbGFyZWEnLCB0cmFjZTogdHJ1ZSwgZWRpdFR5cGU6ICdjYWxjJ30pLFxuXG4gICAgYXNwZWN0cmF0aW86IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBiYXNlcmF0aW86IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMC4zMzMsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXNcIjo2MzEsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NCxcIi4uLy4uL3Bsb3RzL2RvbWFpblwiOjc5MixcIi4uL3BpZS9hdHRyaWJ1dGVzXCI6MTA4Nn1dLDk5MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgZ2V0TW9kdWxlQ2FsY0RhdGEgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9nZXRfZGF0YScpLmdldE1vZHVsZUNhbGNEYXRhO1xuXG5leHBvcnRzLm5hbWUgPSAnZnVubmVsYXJlYSc7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIEZ1bm5lbGFyZWEgPSBSZWdpc3RyeS5nZXRNb2R1bGUoJ2Z1bm5lbGFyZWEnKTtcbiAgICB2YXIgY2RGdW5uZWxhcmVhID0gZ2V0TW9kdWxlQ2FsY0RhdGEoZ2QuY2FsY2RhdGEsIEZ1bm5lbGFyZWEpWzBdO1xuICAgIEZ1bm5lbGFyZWEucGxvdChnZCwgY2RGdW5uZWxhcmVhKTtcbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgaGFkRnVubmVsYXJlYSA9IChvbGRGdWxsTGF5b3V0Ll9oYXMgJiYgb2xkRnVsbExheW91dC5faGFzKCdmdW5uZWxhcmVhJykpO1xuICAgIHZhciBoYXNGdW5uZWxhcmVhID0gKG5ld0Z1bGxMYXlvdXQuX2hhcyAmJiBuZXdGdWxsTGF5b3V0Ll9oYXMoJ2Z1bm5lbGFyZWEnKSk7XG5cbiAgICBpZihoYWRGdW5uZWxhcmVhICYmICFoYXNGdW5uZWxhcmVhKSB7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX2Z1bm5lbGFyZWFsYXllci5zZWxlY3RBbGwoJ2cudHJhY2UnKS5yZW1vdmUoKTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2dldF9kYXRhXCI6ODAyLFwiLi4vLi4vcmVnaXN0cnlcIjo4NDd9XSw5OTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgcGllQ2FsYyA9IF9kZXJlcV8oJy4uL3BpZS9jYWxjJyk7XG5cbmZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgcmV0dXJuIHBpZUNhbGMuY2FsYyhnZCwgdHJhY2UpO1xufVxuXG5mdW5jdGlvbiBjcm9zc1RyYWNlQ2FsYyhnZCkge1xuICAgIHBpZUNhbGMuY3Jvc3NUcmFjZUNhbGMoZ2QsIHsgdHlwZTogJ2Z1bm5lbGFyZWEnIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjYWxjOiBjYWxjLFxuICAgIGNyb3NzVHJhY2VDYWxjOiBjcm9zc1RyYWNlQ2FsY1xufTtcblxufSx7XCIuLi9waWUvY2FsY1wiOjEwODh9XSw5OTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZURvbWFpbkRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZG9tYWluJykuZGVmYXVsdHM7XG52YXIgaGFuZGxlVGV4dCA9IF9kZXJlcV8oJy4uL2Jhci9kZWZhdWx0cycpLmhhbmRsZVRleHQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsZW47XG4gICAgdmFyIHZhbHMgPSBjb2VyY2UoJ3ZhbHVlcycpO1xuICAgIHZhciBoYXNWYWxzID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkodmFscyk7XG4gICAgdmFyIGxhYmVscyA9IGNvZXJjZSgnbGFiZWxzJyk7XG4gICAgaWYoQXJyYXkuaXNBcnJheShsYWJlbHMpKSB7XG4gICAgICAgIGxlbiA9IGxhYmVscy5sZW5ndGg7XG4gICAgICAgIGlmKGhhc1ZhbHMpIGxlbiA9IE1hdGgubWluKGxlbiwgdmFscy5sZW5ndGgpO1xuICAgIH0gZWxzZSBpZihoYXNWYWxzKSB7XG4gICAgICAgIGxlbiA9IHZhbHMubGVuZ3RoO1xuXG4gICAgICAgIGNvZXJjZSgnbGFiZWwwJyk7XG4gICAgICAgIGNvZXJjZSgnZGxhYmVsJyk7XG4gICAgfVxuXG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIHZhciBsaW5lV2lkdGggPSBjb2VyY2UoJ21hcmtlci5saW5lLndpZHRoJyk7XG4gICAgaWYobGluZVdpZHRoKSBjb2VyY2UoJ21hcmtlci5saW5lLmNvbG9yJywgbGF5b3V0LnBhcGVyX2JnY29sb3IpO1xuXG4gICAgY29lcmNlKCdtYXJrZXIuY29sb3JzJyk7XG5cbiAgICBjb2VyY2UoJ3NjYWxlZ3JvdXAnKTtcblxuICAgIHZhciB0ZXh0RGF0YSA9IGNvZXJjZSgndGV4dCcpO1xuICAgIHZhciB0ZXh0SW5mbyA9IGNvZXJjZSgndGV4dGluZm8nLCBBcnJheS5pc0FycmF5KHRleHREYXRhKSA/ICd0ZXh0K3BlcmNlbnQnIDogJ3BlcmNlbnQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgaWYodGV4dEluZm8gJiYgdGV4dEluZm8gIT09ICdub25lJykge1xuICAgICAgICB2YXIgdGV4dHBvc2l0aW9uID0gY29lcmNlKCd0ZXh0cG9zaXRpb24nKTtcbiAgICAgICAgaGFuZGxlVGV4dCh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHRleHRwb3NpdGlvbiwge1xuICAgICAgICAgICAgbW9kdWxlSGFzU2VsZWN0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgbW9kdWxlSGFzVW5zZWxlY3RlZDogZmFsc2UsXG4gICAgICAgICAgICBtb2R1bGVIYXNDb25zdHJhaW46IGZhbHNlLFxuICAgICAgICAgICAgbW9kdWxlSGFzQ2xpcG9uYXhpczogZmFsc2UsXG4gICAgICAgICAgICBtb2R1bGVIYXNUZXh0YW5nbGU6IGZhbHNlLFxuICAgICAgICAgICAgbW9kdWxlSGFzSW5zaWRlYW5jaG9yOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBoYW5kbGVEb21haW5EZWZhdWx0cyh0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuXG4gICAgdmFyIHRpdGxlID0gY29lcmNlKCd0aXRsZS50ZXh0Jyk7XG4gICAgaWYodGl0bGUpIHtcbiAgICAgICAgY29lcmNlKCd0aXRsZS5wb3NpdGlvbicpO1xuICAgICAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICd0aXRsZS5mb250JywgbGF5b3V0LmZvbnQpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnYXNwZWN0cmF0aW8nKTtcbiAgICBjb2VyY2UoJ2Jhc2VyYXRpbycpO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9kb21haW5cIjo3OTIsXCIuLi9iYXIvZGVmYXVsdHNcIjo4NjEsXCIuL2F0dHJpYnV0ZXNcIjo5OTJ9XSw5OTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdmdW5uZWxhcmVhJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi9iYXNlX3Bsb3QnKSxcbiAgICBjYXRlZ29yaWVzOiBbJ3BpZS1saWtlJywgJ2Z1bm5lbGFyZWEnLCAnc2hvd0xlZ2VuZCddLFxuXG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2RlZmF1bHRzJyksXG5cbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKS5jYWxjLFxuICAgIGNyb3NzVHJhY2VDYWxjOiBfZGVyZXFfKCcuL2NhbGMnKS5jcm9zc1RyYWNlQ2FsYyxcblxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuL3N0eWxlJyksXG4gICAgc3R5bGVPbmU6IF9kZXJlcV8oJy4uL3BpZS9zdHlsZV9vbmUnKSxcblxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi9waWUvc3R5bGVfb25lXCI6MTA5NyxcIi4vYXR0cmlidXRlc1wiOjk5MixcIi4vYmFzZV9wbG90XCI6OTkzLFwiLi9jYWxjXCI6OTk0LFwiLi9kZWZhdWx0c1wiOjk5NSxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo5OTcsXCIuL2xheW91dF9kZWZhdWx0c1wiOjk5OCxcIi4vcGxvdFwiOjk5OSxcIi4vc3R5bGVcIjoxMDAwfV0sOTk3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGhpZGRlbmxhYmVscyA9IF9kZXJlcV8oJy4uL3BpZS9sYXlvdXRfYXR0cmlidXRlcycpLmhpZGRlbmxhYmVscztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaGlkZGVubGFiZWxzOiBoaWRkZW5sYWJlbHMsXG5cbiAgICBmdW5uZWxhcmVhY29sb3J3YXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9ybGlzdCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGV4dGVuZGZ1bm5lbGFyZWFjb2xvcnM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi9waWUvbGF5b3V0X2F0dHJpYnV0ZXNcIjoxMDkzfV0sOTk4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGF5b3V0SW4sIGxheW91dE91dCwgbGF5b3V0QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdoaWRkZW5sYWJlbHMnKTtcbiAgICBjb2VyY2UoJ2Z1bm5lbGFyZWFjb2xvcndheScsIGxheW91dE91dC5jb2xvcndheSk7XG4gICAgY29lcmNlKCdleHRlbmRmdW5uZWxhcmVhY29sb3JzJyk7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo5OTd9XSw5OTk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xuXG52YXIgYmFyUGxvdCA9IF9kZXJlcV8oJy4uL2Jhci9wbG90Jyk7XG52YXIgZ2V0VHJhbnNmb3JtID0gYmFyUGxvdC5nZXRUcmFuc2Zvcm07XG52YXIgdG9Nb3ZlSW5zaWRlQmFyID0gYmFyUGxvdC50b01vdmVJbnNpZGVCYXI7XG5cbnZhciBwaWVIZWxwZXJzID0gX2RlcmVxXygnLi4vcGllL2hlbHBlcnMnKTtcbnZhciBwaWVQbG90ID0gX2RlcmVxXygnLi4vcGllL3Bsb3QnKTtcblxudmFyIGF0dGFjaEZ4SGFuZGxlcnMgPSBwaWVQbG90LmF0dGFjaEZ4SGFuZGxlcnM7XG52YXIgZGV0ZXJtaW5lSW5zaWRlVGV4dEZvbnQgPSBwaWVQbG90LmRldGVybWluZUluc2lkZVRleHRGb250O1xuXG52YXIgbGF5b3V0QXJlYXMgPSBwaWVQbG90LmxheW91dEFyZWFzO1xudmFyIHByZXJlbmRlclRpdGxlcyA9IHBpZVBsb3QucHJlcmVuZGVyVGl0bGVzO1xudmFyIHBvc2l0aW9uVGl0bGVPdXRzaWRlID0gcGllUGxvdC5wb3NpdGlvblRpdGxlT3V0c2lkZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBjZE1vZHVsZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBwcmVyZW5kZXJUaXRsZXMoY2RNb2R1bGUsIGdkKTtcbiAgICBsYXlvdXRBcmVhcyhjZE1vZHVsZSwgZnVsbExheW91dC5fc2l6ZSk7XG5cbiAgICBMaWIubWFrZVRyYWNlR3JvdXBzKGZ1bGxMYXlvdXQuX2Z1bm5lbGFyZWFsYXllciwgY2RNb2R1bGUsICd0cmFjZScpLmVhY2goZnVuY3Rpb24oY2QpIHtcbiAgICAgICAgdmFyIHBsb3RHcm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG5cbiAgICAgICAgc2V0Q29vcmRzKGNkKTtcblxuICAgICAgICBwbG90R3JvdXAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBzbGljZXMgPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdnLnNsaWNlJykuZGF0YShjZCk7XG5cbiAgICAgICAgICAgIHNsaWNlcy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3NsaWNlJywgdHJ1ZSk7XG4gICAgICAgICAgICBzbGljZXMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgICAgICBzbGljZXMuZWFjaChmdW5jdGlvbihwdCkge1xuICAgICAgICAgICAgICAgIGlmKHB0LmhpZGRlbikge1xuICAgICAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdwYXRoLGcnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHRvIGhhdmUgY29uc2lzdGVudCBldmVudCBkYXRhIGNvbXBhcmVkIHRvIG90aGVyIHRyYWNlc1xuICAgICAgICAgICAgICAgIHB0LnBvaW50TnVtYmVyID0gcHQuaTtcbiAgICAgICAgICAgICAgICBwdC5jdXJ2ZU51bWJlciA9IHRyYWNlLmluZGV4O1xuXG4gICAgICAgICAgICAgICAgdmFyIGN4ID0gY2QwLmN4O1xuICAgICAgICAgICAgICAgIHZhciBjeSA9IGNkMC5jeTtcbiAgICAgICAgICAgICAgICB2YXIgc2xpY2VUb3AgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICAgICAgdmFyIHNsaWNlUGF0aCA9IHNsaWNlVG9wLnNlbGVjdEFsbCgncGF0aC5zdXJmYWNlJykuZGF0YShbcHRdKTtcblxuICAgICAgICAgICAgICAgIHNsaWNlUGF0aC5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzdXJmYWNlJywgdHJ1ZSlcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKHsncG9pbnRlci1ldmVudHMnOiAnYWxsJ30pO1xuXG4gICAgICAgICAgICAgICAgc2xpY2VUb3AuY2FsbChhdHRhY2hGeEhhbmRsZXJzLCBnZCwgY2QpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHNoYXBlID1cbiAgICAgICAgICAgICAgICAgICAgJ00nICsgKGN4ICsgcHQuVFJbMF0pICsgJywnICsgKGN5ICsgcHQuVFJbMV0pICtcbiAgICAgICAgICAgICAgICAgICAgbGluZShwdC5UUiwgcHQuQlIpICtcbiAgICAgICAgICAgICAgICAgICAgbGluZShwdC5CUiwgcHQuQkwpICtcbiAgICAgICAgICAgICAgICAgICAgbGluZShwdC5CTCwgcHQuVEwpICtcbiAgICAgICAgICAgICAgICAgICAgJ1onO1xuXG4gICAgICAgICAgICAgICAgc2xpY2VQYXRoLmF0dHIoJ2QnLCBzaGFwZSk7XG5cbiAgICAgICAgICAgICAgICAvLyBhZGQgdGV4dFxuICAgICAgICAgICAgICAgIHZhciB0ZXh0UG9zaXRpb24gPSBwaWVIZWxwZXJzLmNhc3RPcHRpb24odHJhY2UudGV4dHBvc2l0aW9uLCBwdC5wdHMpO1xuICAgICAgICAgICAgICAgIHZhciBzbGljZVRleHRHcm91cCA9IHNsaWNlVG9wLnNlbGVjdEFsbCgnZy5zbGljZXRleHQnKVxuICAgICAgICAgICAgICAgICAgICAuZGF0YShwdC50ZXh0ICYmICh0ZXh0UG9zaXRpb24gIT09ICdub25lJykgPyBbMF0gOiBbXSk7XG5cbiAgICAgICAgICAgICAgICBzbGljZVRleHRHcm91cC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAgICAgICAgIC5jbGFzc2VkKCdzbGljZXRleHQnLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBzbGljZVRleHRHcm91cC5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgICAgICAgICBzbGljZVRleHRHcm91cC5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2xpY2VUZXh0ID0gTGliLmVuc3VyZVNpbmdsZShkMy5zZWxlY3QodGhpcyksICd0ZXh0JywgJycsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByb2hpYml0IHRleCBpbnRlcnByZXRhdGlvbiB1bnRpbCB3ZSBjYW4gaGFuZGxlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0ZXggYW5kIHJlZ3VsYXIgdGV4dCB0b2dldGhlclxuICAgICAgICAgICAgICAgICAgICAgICAgcy5hdHRyKCdkYXRhLW5vdGV4JywgMSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHNsaWNlVGV4dC50ZXh0KHB0LnRleHQpXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ3NsaWNldGV4dCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAndGV4dC1hbmNob3InOiAnbWlkZGxlJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZm9udCwgZGV0ZXJtaW5lSW5zaWRlVGV4dEZvbnQodHJhY2UsIHB0LCBnZC5fZnVsbExheW91dC5mb250KSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBwb3NpdGlvbiB0aGUgdGV4dCByZWxhdGl2ZSB0byB0aGUgc2xpY2VcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRleHRCQiA9IERyYXdpbmcuYkJveChzbGljZVRleHQubm9kZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgeDAsIHgxO1xuICAgICAgICAgICAgICAgICAgICB2YXIgeTAgPSBNYXRoLm1pbihwdC5CTFsxXSwgcHQuQlJbMV0pO1xuICAgICAgICAgICAgICAgICAgICB2YXIgeTEgPSBNYXRoLm1heChwdC5UTFsxXSwgcHQuVFJbMV0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHgwID0gTWF0aC5tYXgocHQuVExbMF0sIHB0LkJMWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgeDEgPSBNYXRoLm1pbihwdC5UUlswXSwgcHQuQlJbMF0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybSh0b01vdmVJbnNpZGVCYXIoeDAsIHgxLCB5MCwgeTEsIHRleHRCQiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNIb3Jpem9udGFsOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWluZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBhbmdsZTogMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuY2hvcjogJ21pZGRsZSdcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuXG4gICAgICAgICAgICAgICAgICAgIHNsaWNlVGV4dC5hdHRyKCd0cmFuc2Zvcm0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgY3ggKyAnLCcgKyBjeSArICcpJyArIHRyYW5zZm9ybVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIGFkZCB0aGUgdGl0bGVcbiAgICAgICAgICAgIHZhciB0aXRsZVRleHRHcm91cCA9IGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ2cudGl0bGV0ZXh0JylcbiAgICAgICAgICAgICAgICAuZGF0YSh0cmFjZS50aXRsZS50ZXh0ID8gWzBdIDogW10pO1xuXG4gICAgICAgICAgICB0aXRsZVRleHRHcm91cC5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3RpdGxldGV4dCcsIHRydWUpO1xuICAgICAgICAgICAgdGl0bGVUZXh0R3JvdXAuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgICAgICB0aXRsZVRleHRHcm91cC5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHZhciB0aXRsZVRleHQgPSBMaWIuZW5zdXJlU2luZ2xlKGQzLnNlbGVjdCh0aGlzKSwgJ3RleHQnLCAnJywgZnVuY3Rpb24ocykge1xuICAgICAgICAgICAgICAgICAgICAvLyBwcm9oaWJpdCB0ZXggaW50ZXJwcmV0YXRpb24gYXMgYWJvdmVcbiAgICAgICAgICAgICAgICAgICAgcy5hdHRyKCdkYXRhLW5vdGV4JywgMSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgdHh0ID0gdHJhY2UudGl0bGUudGV4dDtcbiAgICAgICAgICAgICAgICBpZih0cmFjZS5fbWV0YSkge1xuICAgICAgICAgICAgICAgICAgICB0eHQgPSBMaWIudGVtcGxhdGVTdHJpbmcodHh0LCB0cmFjZS5fbWV0YSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGl0bGVUZXh0LnRleHQodHh0KVxuICAgICAgICAgICAgICAgICAgICAuYXR0cih7XG4gICAgICAgICAgICAgICAgICAgICAgICAnY2xhc3MnOiAndGl0bGV0ZXh0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAndGV4dC1hbmNob3InOiAnbWlkZGxlJyxcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIHRyYWNlLnRpdGxlLmZvbnQpXG4gICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHBvc2l0aW9uVGl0bGVPdXRzaWRlKGNkMCwgZnVsbExheW91dC5fc2l6ZSk7XG5cbiAgICAgICAgICAgICAgICB0aXRsZVRleHQuYXR0cigndHJhbnNmb3JtJyxcbiAgICAgICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgdHJhbnNmb3JtLnggKyAnLCcgKyB0cmFuc2Zvcm0ueSArICcpJyArXG4gICAgICAgICAgICAgICAgICAgICh0cmFuc2Zvcm0uc2NhbGUgPCAxID8gKCdzY2FsZSgnICsgdHJhbnNmb3JtLnNjYWxlICsgJyknKSA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAgICd0cmFuc2xhdGUoJyArIHRyYW5zZm9ybS50eCArICcsJyArIHRyYW5zZm9ybS50eSArICcpJyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBsaW5lKGEsIGIpIHtcbiAgICB2YXIgZHggPSBiWzBdIC0gYVswXTtcbiAgICB2YXIgZHkgPSBiWzFdIC0gYVsxXTtcblxuICAgIHJldHVybiAnbCcgKyBkeCArICcsJyArIGR5O1xufVxuXG5mdW5jdGlvbiBnZXRCZXR3ZWVuKGEsIGIpIHtcbiAgICByZXR1cm4gW1xuICAgICAgICAwLjUgKiAoYVswXSArIGJbMF0pLFxuICAgICAgICAwLjUgKiAoYVsxXSArIGJbMV0pXG4gICAgXTtcbn1cblxuZnVuY3Rpb24gc2V0Q29vcmRzKGNkKSB7XG4gICAgaWYoIWNkLmxlbmd0aCkgcmV0dXJuO1xuXG4gICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgIHZhciBhc3BlY3RyYXRpbyA9IHRyYWNlLmFzcGVjdHJhdGlvO1xuXG4gICAgdmFyIGggPSB0cmFjZS5iYXNlcmF0aW87XG4gICAgaWYoaCA+IDAuOTk5KSBoID0gMC45OTk7IC8vIFRPRE86IG1heSBoYW5kbGUgdGhpcyBjYXNlIHNlcGFyYXRlbHlcbiAgICB2YXIgaDIgPSBNYXRoLnBvdyhoLCAyKTtcblxuICAgIHZhciB2MSA9IGNkMC52VG90YWw7XG4gICAgdmFyIHYwID0gdjEgKiBoMiAvICgxIC0gaDIpO1xuXG4gICAgdmFyIHRvdGFsVmFsdWVzID0gdjE7XG4gICAgdmFyIHN1bVN0ZXBzID0gdjAgLyB2MTtcblxuICAgIGZ1bmN0aW9uIGNhbGNQb3MoKSB7XG4gICAgICAgIHZhciBxID0gTWF0aC5zcXJ0KHN1bVN0ZXBzKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6IHEsXG4gICAgICAgICAgICB5OiAtcVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFBvaW50KCkge1xuICAgICAgICB2YXIgcG9zID0gY2FsY1BvcygpO1xuICAgICAgICByZXR1cm4gW3Bvcy54LCBwb3MueV07XG4gICAgfVxuXG4gICAgdmFyIHA7XG4gICAgdmFyIGFsbFBvaW50cyA9IFtdO1xuICAgIGFsbFBvaW50cy5wdXNoKGdldFBvaW50KCkpO1xuXG4gICAgdmFyIGksIGNkaTtcbiAgICBmb3IoaSA9IGNkLmxlbmd0aCAtIDE7IGkgPiAtMTsgaS0tKSB7XG4gICAgICAgIGNkaSA9IGNkW2ldO1xuICAgICAgICBpZihjZGkuaGlkZGVuKSBjb250aW51ZTtcblxuICAgICAgICB2YXIgc3RlcCA9IGNkaS52IC8gdG90YWxWYWx1ZXM7XG4gICAgICAgIHN1bVN0ZXBzICs9IHN0ZXA7XG5cbiAgICAgICAgYWxsUG9pbnRzLnB1c2goZ2V0UG9pbnQoKSk7XG4gICAgfVxuXG4gICAgdmFyIG1pblkgPSBJbmZpbml0eTtcbiAgICB2YXIgbWF4WSA9IC1JbmZpbml0eTtcbiAgICBmb3IoaSA9IDA7IGkgPCBhbGxQb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcCA9IGFsbFBvaW50c1tpXTtcbiAgICAgICAgbWluWSA9IE1hdGgubWluKG1pblksIHBbMV0pO1xuICAgICAgICBtYXhZID0gTWF0aC5tYXgobWF4WSwgcFsxXSk7XG4gICAgfVxuXG4gICAgLy8gY2VudGVyIHRoZSBzaGFwZVxuICAgIGZvcihpID0gMDsgaSA8IGFsbFBvaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBhbGxQb2ludHNbaV1bMV0gLT0gKG1heFkgKyBtaW5ZKSAvIDI7XG4gICAgfVxuXG4gICAgdmFyIGxhc3RYID0gYWxsUG9pbnRzW2FsbFBvaW50cy5sZW5ndGggLSAxXVswXTtcblxuICAgIC8vIGdldCBwaWUgclxuICAgIHZhciByID0gY2QwLnI7XG5cbiAgICB2YXIgclkgPSAobWF4WSAtIG1pblkpIC8gMjtcbiAgICB2YXIgc2NhbGVYID0gciAvIGxhc3RYO1xuICAgIHZhciBzY2FsZVkgPSByIC8gclkgKiBhc3BlY3RyYXRpbztcblxuICAgIC8vIHNldCBmdW5uZWxhcmVhIHJcbiAgICBjZDAuciA9IHNjYWxlWSAqIHJZO1xuXG4gICAgLy8gc2NhbGUgdGhlIHNoYXBlXG4gICAgZm9yKGkgPSAwOyBpIDwgYWxsUG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFsbFBvaW50c1tpXVswXSAqPSBzY2FsZVg7XG4gICAgICAgIGFsbFBvaW50c1tpXVsxXSAqPSBzY2FsZVk7XG4gICAgfVxuXG4gICAgLy8gcmVjb3JkIGZpcnN0IHBvc2l0aW9uXG4gICAgcCA9IGFsbFBvaW50c1swXTtcbiAgICB2YXIgcHJldkxlZnQgPSBbLXBbMF0sIHBbMV1dO1xuICAgIHZhciBwcmV2UmlnaHQgPSBbcFswXSwgcFsxXV07XG5cbiAgICB2YXIgbiA9IDA7IC8vIG5vdGUgd2Ugc2tpcCB0aGUgdmVyeSBmaXJzdCBwb2ludC5cbiAgICBmb3IoaSA9IGNkLmxlbmd0aCAtIDE7IGkgPiAtMTsgaS0tKSB7XG4gICAgICAgIGNkaSA9IGNkW2ldO1xuICAgICAgICBpZihjZGkuaGlkZGVuKSBjb250aW51ZTtcblxuICAgICAgICBuICs9IDE7XG4gICAgICAgIHZhciB4ID0gYWxsUG9pbnRzW25dWzBdO1xuICAgICAgICB2YXIgeSA9IGFsbFBvaW50c1tuXVsxXTtcblxuICAgICAgICBjZGkuVEwgPSBbLXgsIHldO1xuICAgICAgICBjZGkuVFIgPSBbeCwgeV07XG5cbiAgICAgICAgY2RpLkJMID0gcHJldkxlZnQ7XG4gICAgICAgIGNkaS5CUiA9IHByZXZSaWdodDtcblxuICAgICAgICBjZGkucHhtaWQgPSBnZXRCZXR3ZWVuKGNkaS5UUiwgY2RpLkJSKTtcblxuICAgICAgICBwcmV2TGVmdCA9IGNkaS5UTDtcbiAgICAgICAgcHJldlJpZ2h0ID0gY2RpLlRSO1xuICAgIH1cbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHNcIjo3NDMsXCIuLi9iYXIvcGxvdFwiOjg2NyxcIi4uL3BpZS9oZWxwZXJzXCI6MTA5MSxcIi4uL3BpZS9wbG90XCI6MTA5NSxcImQzXCI6MTYzfV0sMTAwMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG5cbnZhciBzdHlsZU9uZSA9IF9kZXJlcV8oJy4uL3BpZS9zdHlsZV9vbmUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHlsZShnZCkge1xuICAgIGdkLl9mdWxsTGF5b3V0Ll9mdW5uZWxhcmVhbGF5ZXIuc2VsZWN0QWxsKCcudHJhY2UnKS5lYWNoKGZ1bmN0aW9uKGNkKSB7XG4gICAgICAgIHZhciBjZDAgPSBjZFswXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgICAgICB2YXIgdHJhY2VTZWxlY3Rpb24gPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgdHJhY2VTZWxlY3Rpb24uc3R5bGUoe29wYWNpdHk6IHRyYWNlLm9wYWNpdHl9KTtcblxuICAgICAgICB0cmFjZVNlbGVjdGlvbi5zZWxlY3RBbGwoJ3BhdGguc3VyZmFjZScpLmVhY2goZnVuY3Rpb24ocHQpIHtcbiAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKS5jYWxsKHN0eWxlT25lLCBwdCwgdHJhY2UpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG5cbn0se1wiLi4vcGllL3N0eWxlX29uZVwiOjEwOTcsXCJkM1wiOjE2M31dLDEwMDE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2NhdHRlckF0dHJzID0gX2RlcmVxXygnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIEZPUk1BVF9MSU5LID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2RvY3MnKS5GT1JNQVRfTElOSztcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxubW9kdWxlLmV4cG9ydHMgPSBleHRlbmRGbGF0KHtcbiAgICB6OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMueCwge2ltcGxpZWRFZGl0czoge3h0eXBlOiAnYXJyYXknfX0pLFxuICAgIHgwOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMueDAsIHtpbXBsaWVkRWRpdHM6IHt4dHlwZTogJ3NjYWxlZCd9fSksXG4gICAgZHg6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5keCwge2ltcGxpZWRFZGl0czoge3h0eXBlOiAnc2NhbGVkJ319KSxcbiAgICB5OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMueSwge2ltcGxpZWRFZGl0czoge3l0eXBlOiAnYXJyYXknfX0pLFxuICAgIHkwOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMueTAsIHtpbXBsaWVkRWRpdHM6IHt5dHlwZTogJ3NjYWxlZCd9fSksXG4gICAgZHk6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5keSwge2ltcGxpZWRFZGl0czoge3l0eXBlOiAnc2NhbGVkJ319KSxcblxuICAgIHRleHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVydGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdHJhbnNwb3NlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHh0eXBlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FycmF5JywgJ3NjYWxlZCddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5dHlwZToge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydhcnJheScsICdzY2FsZWQnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgenNtb290aDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydmYXN0JywgJ2Jlc3QnLCBmYWxzZV0sXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBjb25uZWN0Z2Fwczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB4Z2FwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHlnYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgemhvdmVyZm9ybWF0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKClcbn0sIHtcbiAgICB0cmFuc2Zvcm1zOiB1bmRlZmluZWRcbn0sXG4gICAgY29sb3JTY2FsZUF0dHJzKCcnLCB7Y0xldHRlcjogJ3onLCBhdXRvQ29sb3JEZmx0OiBmYWxzZX0pXG4pO1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzXCI6NjAwLFwiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXNcIjo2MzEsXCIuLi8uLi9jb25zdGFudHMvZG9jc1wiOjY5MCxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi9zY2F0dGVyL2F0dHJpYnV0ZXNcIjoxMTEyfV0sMTAwMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG5cbnZhciBoaXN0b2dyYW0yZENhbGMgPSBfZGVyZXFfKCcuLi9oaXN0b2dyYW0yZC9jYWxjJyk7XG52YXIgY29sb3JzY2FsZUNhbGMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsYycpO1xudmFyIGNvbnZlcnRDb2x1bW5EYXRhID0gX2RlcmVxXygnLi9jb252ZXJ0X2NvbHVtbl94eXonKTtcbnZhciBjbGVhbjJkQXJyYXkgPSBfZGVyZXFfKCcuL2NsZWFuXzJkX2FycmF5Jyk7XG52YXIgaW50ZXJwMmQgPSBfZGVyZXFfKCcuL2ludGVycDJkJyk7XG52YXIgZmluZEVtcHRpZXMgPSBfZGVyZXFfKCcuL2ZpbmRfZW1wdGllcycpO1xudmFyIG1ha2VCb3VuZEFycmF5ID0gX2RlcmVxXygnLi9tYWtlX2JvdW5kX2FycmF5Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICAvLyBwcmVwYXJlIHRoZSByYXcgZGF0YVxuICAgIC8vIHJ1biBtYWtlQ2FsY2RhdGEgb24geCBhbmQgeSBldmVuIGZvciBoZWF0bWFwcywgaW4gY2FzZSBvZiBjYXRlZ29yeSBtYXBwaW5nc1xuICAgIHZhciB4YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS54YXhpcyB8fCAneCcpO1xuICAgIHZhciB5YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS55YXhpcyB8fCAneScpO1xuICAgIHZhciBpc0NvbnRvdXIgPSBSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnY29udG91cicpO1xuICAgIHZhciBpc0hpc3QgPSBSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnaGlzdG9ncmFtJyk7XG4gICAgdmFyIGlzR0wyRCA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdnbDJkJyk7XG4gICAgdmFyIHpzbW9vdGggPSBpc0NvbnRvdXIgPyAnYmVzdCcgOiB0cmFjZS56c21vb3RoO1xuICAgIHZhciB4O1xuICAgIHZhciB4MDtcbiAgICB2YXIgZHg7XG4gICAgdmFyIHk7XG4gICAgdmFyIHkwO1xuICAgIHZhciBkeTtcbiAgICB2YXIgejtcbiAgICB2YXIgaTtcbiAgICB2YXIgYmlubmVkO1xuXG4gICAgLy8gY2FuY2VsIG1pbmltdW0gdGljayBzcGFjaW5ncyAob25seSBhcHBsaWVzIHRvIGJhcnMgYW5kIGJveGVzKVxuICAgIHhhLl9taW5EdGljayA9IDA7XG4gICAgeWEuX21pbkR0aWNrID0gMDtcblxuICAgIGlmKGlzSGlzdCkge1xuICAgICAgICBiaW5uZWQgPSBoaXN0b2dyYW0yZENhbGMoZ2QsIHRyYWNlKTtcbiAgICAgICAgeCA9IGJpbm5lZC54O1xuICAgICAgICB4MCA9IGJpbm5lZC54MDtcbiAgICAgICAgZHggPSBiaW5uZWQuZHg7XG4gICAgICAgIHkgPSBiaW5uZWQueTtcbiAgICAgICAgeTAgPSBiaW5uZWQueTA7XG4gICAgICAgIGR5ID0gYmlubmVkLmR5O1xuICAgICAgICB6ID0gYmlubmVkLno7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHpJbiA9IHRyYWNlLno7XG4gICAgICAgIGlmKExpYi5pc0FycmF5MUQoekluKSkge1xuICAgICAgICAgICAgY29udmVydENvbHVtbkRhdGEodHJhY2UsIHhhLCB5YSwgJ3gnLCAneScsIFsneiddKTtcbiAgICAgICAgICAgIHggPSB0cmFjZS5feDtcbiAgICAgICAgICAgIHkgPSB0cmFjZS5feTtcbiAgICAgICAgICAgIHpJbiA9IHRyYWNlLl96O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgeCA9IHRyYWNlLl94ID0gdHJhY2UueCA/IHhhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3gnKSA6IFtdO1xuICAgICAgICAgICAgeSA9IHRyYWNlLl95ID0gdHJhY2UueSA/IHlhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3knKSA6IFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgeDAgPSB0cmFjZS54MDtcbiAgICAgICAgZHggPSB0cmFjZS5keDtcbiAgICAgICAgeTAgPSB0cmFjZS55MDtcbiAgICAgICAgZHkgPSB0cmFjZS5keTtcblxuICAgICAgICB6ID0gY2xlYW4yZEFycmF5KHpJbiwgdHJhY2UsIHhhLCB5YSk7XG5cbiAgICAgICAgaWYoaXNDb250b3VyIHx8IHRyYWNlLmNvbm5lY3RnYXBzKSB7XG4gICAgICAgICAgICB0cmFjZS5fZW1wdHlwb2ludHMgPSBmaW5kRW1wdGllcyh6KTtcbiAgICAgICAgICAgIGludGVycDJkKHosIHRyYWNlLl9lbXB0eXBvaW50cyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBub1pzbW9vdGgobXNnKSB7XG4gICAgICAgIHpzbW9vdGggPSB0cmFjZS5faW5wdXQuenNtb290aCA9IHRyYWNlLnpzbW9vdGggPSBmYWxzZTtcbiAgICAgICAgTGliLndhcm4oJ2Nhbm5vdCB1c2UgenNtb290aDogXCJmYXN0XCI6ICcgKyBtc2cpO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIHdoZXRoZXIgd2UgcmVhbGx5IGNhbiBzbW9vdGggKGllIGFsbCBib3hlcyBhcmUgYWJvdXQgdGhlIHNhbWUgc2l6ZSlcbiAgICBpZih6c21vb3RoID09PSAnZmFzdCcpIHtcbiAgICAgICAgaWYoeGEudHlwZSA9PT0gJ2xvZycgfHwgeWEudHlwZSA9PT0gJ2xvZycpIHtcbiAgICAgICAgICAgIG5vWnNtb290aCgnbG9nIGF4aXMgZm91bmQnKTtcbiAgICAgICAgfSBlbHNlIGlmKCFpc0hpc3QpIHtcbiAgICAgICAgICAgIGlmKHgubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGF2Z2R4ID0gKHhbeC5sZW5ndGggLSAxXSAtIHhbMF0pIC8gKHgubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgdmFyIG1heEVyclggPSBNYXRoLmFicyhhdmdkeCAvIDEwMCk7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgeC5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMoeFtpICsgMV0gLSB4W2ldIC0gYXZnZHgpID4gbWF4RXJyWCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9ac21vb3RoKCd4IHNjYWxlIGlzIG5vdCBsaW5lYXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoeS5sZW5ndGggJiYgenNtb290aCA9PT0gJ2Zhc3QnKSB7XG4gICAgICAgICAgICAgICAgdmFyIGF2Z2R5ID0gKHlbeS5sZW5ndGggLSAxXSAtIHlbMF0pIC8gKHkubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgdmFyIG1heEVyclkgPSBNYXRoLmFicyhhdmdkeSAvIDEwMCk7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgeS5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoTWF0aC5hYnMoeVtpICsgMV0gLSB5W2ldIC0gYXZnZHkpID4gbWF4RXJyWSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9ac21vb3RoKCd5IHNjYWxlIGlzIG5vdCBsaW5lYXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIGFycmF5cyBvZiBicmljayBib3VuZGFyaWVzLCB0byBiZSB1c2VkIGJ5IGF1dG9yYW5nZSBhbmQgaGVhdG1hcC5wbG90XG4gICAgdmFyIHhsZW4gPSBMaWIubWF4Um93TGVuZ3RoKHopO1xuICAgIHZhciB4SW4gPSB0cmFjZS54dHlwZSA9PT0gJ3NjYWxlZCcgPyAnJyA6IHg7XG4gICAgdmFyIHhBcnJheSA9IG1ha2VCb3VuZEFycmF5KHRyYWNlLCB4SW4sIHgwLCBkeCwgeGxlbiwgeGEpO1xuICAgIHZhciB5SW4gPSB0cmFjZS55dHlwZSA9PT0gJ3NjYWxlZCcgPyAnJyA6IHk7XG4gICAgdmFyIHlBcnJheSA9IG1ha2VCb3VuZEFycmF5KHRyYWNlLCB5SW4sIHkwLCBkeSwgei5sZW5ndGgsIHlhKTtcblxuICAgIC8vIGhhbmRsZWQgaW4gZ2wyZCBjb252ZXJ0IHN0ZXBcbiAgICBpZighaXNHTDJEKSB7XG4gICAgICAgIHRyYWNlLl9leHRyZW1lc1t4YS5faWRdID0gQXhlcy5maW5kRXh0cmVtZXMoeGEsIHhBcnJheSk7XG4gICAgICAgIHRyYWNlLl9leHRyZW1lc1t5YS5faWRdID0gQXhlcy5maW5kRXh0cmVtZXMoeWEsIHlBcnJheSk7XG4gICAgfVxuXG4gICAgdmFyIGNkMCA9IHtcbiAgICAgICAgeDogeEFycmF5LFxuICAgICAgICB5OiB5QXJyYXksXG4gICAgICAgIHo6IHosXG4gICAgICAgIHRleHQ6IHRyYWNlLl90ZXh0IHx8IHRyYWNlLnRleHQsXG4gICAgICAgIGhvdmVydGV4dDogdHJhY2UuX2hvdmVydGV4dCB8fCB0cmFjZS5ob3ZlcnRleHRcbiAgICB9O1xuXG4gICAgaWYoeEluICYmIHhJbi5sZW5ndGggPT09IHhBcnJheS5sZW5ndGggLSAxKSBjZDAueENlbnRlciA9IHhJbjtcbiAgICBpZih5SW4gJiYgeUluLmxlbmd0aCA9PT0geUFycmF5Lmxlbmd0aCAtIDEpIGNkMC55Q2VudGVyID0geUluO1xuXG4gICAgaWYoaXNIaXN0KSB7XG4gICAgICAgIGNkMC54UmFuZ2VzID0gYmlubmVkLnhSYW5nZXM7XG4gICAgICAgIGNkMC55UmFuZ2VzID0gYmlubmVkLnlSYW5nZXM7XG4gICAgICAgIGNkMC5wdHMgPSBiaW5uZWQucHRzO1xuICAgIH1cblxuICAgIGlmKCFpc0NvbnRvdXIpIHtcbiAgICAgICAgY29sb3JzY2FsZUNhbGMoZ2QsIHRyYWNlLCB7dmFsczogeiwgY0xldHRlcjogJ3onfSk7XG4gICAgfVxuXG4gICAgaWYoaXNDb250b3VyICYmIHRyYWNlLmNvbnRvdXJzICYmIHRyYWNlLmNvbnRvdXJzLmNvbG9yaW5nID09PSAnaGVhdG1hcCcpIHtcbiAgICAgICAgdmFyIGR1bW15VHJhY2UgPSB7XG4gICAgICAgICAgICB0eXBlOiB0cmFjZS50eXBlID09PSAnY29udG91cicgPyAnaGVhdG1hcCcgOiAnaGlzdG9ncmFtMmQnLFxuICAgICAgICAgICAgeGNhbGVuZGFyOiB0cmFjZS54Y2FsZW5kYXIsXG4gICAgICAgICAgICB5Y2FsZW5kYXI6IHRyYWNlLnljYWxlbmRhclxuICAgICAgICB9O1xuICAgICAgICBjZDAueGZpbGwgPSBtYWtlQm91bmRBcnJheShkdW1teVRyYWNlLCB4SW4sIHgwLCBkeCwgeGxlbiwgeGEpO1xuICAgICAgICBjZDAueWZpbGwgPSBtYWtlQm91bmRBcnJheShkdW1teVRyYWNlLCB5SW4sIHkwLCBkeSwgei5sZW5ndGgsIHlhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW2NkMF07XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjXCI6NjAxLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4uL2hpc3RvZ3JhbTJkL2NhbGNcIjoxMDMzLFwiLi9jbGVhbl8yZF9hcnJheVwiOjEwMDMsXCIuL2NvbnZlcnRfY29sdW1uX3h5elwiOjEwMDUsXCIuL2ZpbmRfZW1wdGllc1wiOjEwMDcsXCIuL2ludGVycDJkXCI6MTAxMCxcIi4vbWFrZV9ib3VuZF9hcnJheVwiOjEwMTF9XSwxMDAzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQkFETlVNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjbGVhbjJkQXJyYXkoek9sZCwgdHJhY2UsIHhhLCB5YSkge1xuICAgIHZhciByb3dsZW4sIGNvbGxlbiwgZ2V0Q29sbGVuLCBvbGQybmV3LCBpLCBqO1xuXG4gICAgZnVuY3Rpb24gY2xlYW5admFsdWUodikge1xuICAgICAgICBpZighaXNOdW1lcmljKHYpKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICByZXR1cm4gK3Y7XG4gICAgfVxuXG4gICAgaWYodHJhY2UgJiYgdHJhY2UudHJhbnNwb3NlKSB7XG4gICAgICAgIHJvd2xlbiA9IDA7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHpPbGQubGVuZ3RoOyBpKyspIHJvd2xlbiA9IE1hdGgubWF4KHJvd2xlbiwgek9sZFtpXS5sZW5ndGgpO1xuICAgICAgICBpZihyb3dsZW4gPT09IDApIHJldHVybiBmYWxzZTtcbiAgICAgICAgZ2V0Q29sbGVuID0gZnVuY3Rpb24oek9sZCkgeyByZXR1cm4gek9sZC5sZW5ndGg7IH07XG4gICAgICAgIG9sZDJuZXcgPSBmdW5jdGlvbih6T2xkLCBpLCBqKSB7IHJldHVybiAoek9sZFtqXSB8fCBbXSlbaV07IH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcm93bGVuID0gek9sZC5sZW5ndGg7XG4gICAgICAgIGdldENvbGxlbiA9IGZ1bmN0aW9uKHpPbGQsIGkpIHsgcmV0dXJuIHpPbGRbaV0ubGVuZ3RoOyB9O1xuICAgICAgICBvbGQybmV3ID0gZnVuY3Rpb24oek9sZCwgaSwgaikgeyByZXR1cm4gKHpPbGRbaV0gfHwgW10pW2pdOyB9O1xuICAgIH1cblxuICAgIHZhciBwYWRPbGQybmV3ID0gZnVuY3Rpb24oek9sZCwgaSwgaikge1xuICAgICAgICBpZihpID09PSBCQUROVU0gfHwgaiA9PT0gQkFETlVNKSByZXR1cm4gQkFETlVNO1xuICAgICAgICByZXR1cm4gb2xkMm5ldyh6T2xkLCBpLCBqKTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gYXhpc01hcHBpbmcoYXgpIHtcbiAgICAgICAgaWYodHJhY2UgJiYgdHJhY2UudHlwZSAhPT0gJ2NhcnBldCcgJiYgdHJhY2UudHlwZSAhPT0gJ2NvbnRvdXJjYXJwZXQnICYmXG4gICAgICAgICAgICBheCAmJiBheC50eXBlID09PSAnY2F0ZWdvcnknICYmIHRyYWNlWydfJyArIGF4Ll9pZC5jaGFyQXQoMCldLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIGF4TGV0dGVyID0gYXguX2lkLmNoYXJBdCgwKTtcbiAgICAgICAgICAgIHZhciBheE1hcHBpbmcgPSB7fTtcbiAgICAgICAgICAgIHZhciB0cmFjZUNhdGVnb3JpZXMgPSB0cmFjZVsnXycgKyBheExldHRlciArICdDYXRlZ29yeU1hcCddIHx8IHRyYWNlW2F4TGV0dGVyXTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHRyYWNlQ2F0ZWdvcmllcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGF4TWFwcGluZ1t0cmFjZUNhdGVnb3JpZXNbaV1dID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZCA9IGF4TWFwcGluZ1theC5fY2F0ZWdvcmllc1tpXV07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZCArIDEgPyBpbmQgOiBCQUROVU07XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIExpYi5pZGVudGl0eTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciB4TWFwID0gYXhpc01hcHBpbmcoeGEpO1xuICAgIHZhciB5TWFwID0gYXhpc01hcHBpbmcoeWEpO1xuXG4gICAgaWYoeWEgJiYgeWEudHlwZSA9PT0gJ2NhdGVnb3J5Jykgcm93bGVuID0geWEuX2NhdGVnb3JpZXMubGVuZ3RoO1xuICAgIHZhciB6TmV3ID0gbmV3IEFycmF5KHJvd2xlbik7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCByb3dsZW47IGkrKykge1xuICAgICAgICBpZih4YSAmJiB4YS50eXBlID09PSAnY2F0ZWdvcnknKSB7XG4gICAgICAgICAgICBjb2xsZW4gPSB4YS5fY2F0ZWdvcmllcy5sZW5ndGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb2xsZW4gPSBnZXRDb2xsZW4oek9sZCwgaSk7XG4gICAgICAgIH1cbiAgICAgICAgek5ld1tpXSA9IG5ldyBBcnJheShjb2xsZW4pO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBjb2xsZW47IGorKykgek5ld1tpXVtqXSA9IGNsZWFuWnZhbHVlKHBhZE9sZDJuZXcoek9sZCwgeU1hcChpKSwgeE1hcChqKSkpO1xuICAgIH1cblxuICAgIHJldHVybiB6TmV3O1xufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vbGliXCI6NzE5LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSwxMDA0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbWluOiAnem1pbicsXG4gICAgbWF4OiAnem1heCdcbn07XG5cbn0se31dLDEwMDU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNvbnZlcnRDb2x1bW5EYXRhKHRyYWNlLCBheDEsIGF4MiwgdmFyMU5hbWUsIHZhcjJOYW1lLCBhcnJheVZhck5hbWVzKSB7XG4gICAgdmFyIGNvbExlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGNvbDEgPSBheDEubWFrZUNhbGNkYXRhKHRyYWNlLCB2YXIxTmFtZSk7XG4gICAgdmFyIGNvbDIgPSBheDIubWFrZUNhbGNkYXRhKHRyYWNlLCB2YXIyTmFtZSk7XG4gICAgdmFyIHRleHRDb2wgPSB0cmFjZS50ZXh0O1xuICAgIHZhciBoYXNDb2x1bW5UZXh0ID0gKHRleHRDb2wgIT09IHVuZGVmaW5lZCAmJiBMaWIuaXNBcnJheTFEKHRleHRDb2wpKTtcbiAgICB2YXIgaG92ZXJUZXh0Q29sID0gdHJhY2UuaG92ZXJ0ZXh0O1xuICAgIHZhciBoYXNDb2x1bW5Ib3ZlclRleHQgPSAoaG92ZXJUZXh0Q29sICE9PSB1bmRlZmluZWQgJiYgTGliLmlzQXJyYXkxRChob3ZlclRleHRDb2wpKTtcbiAgICB2YXIgaSwgajtcblxuICAgIHZhciBjb2wxZHYgPSBMaWIuZGlzdGluY3RWYWxzKGNvbDEpO1xuICAgIHZhciBjb2wxdmFscyA9IGNvbDFkdi52YWxzO1xuICAgIHZhciBjb2wyZHYgPSBMaWIuZGlzdGluY3RWYWxzKGNvbDIpO1xuICAgIHZhciBjb2wydmFscyA9IGNvbDJkdi52YWxzO1xuICAgIHZhciBuZXdBcnJheXMgPSBbXTtcbiAgICB2YXIgdGV4dDtcbiAgICB2YXIgaG92ZXJ0ZXh0O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgYXJyYXlWYXJOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBuZXdBcnJheXNbaV0gPSBMaWIuaW5pdDJkQXJyYXkoY29sMnZhbHMubGVuZ3RoLCBjb2wxdmFscy5sZW5ndGgpO1xuICAgIH1cblxuICAgIGlmKGhhc0NvbHVtblRleHQpIHtcbiAgICAgICAgdGV4dCA9IExpYi5pbml0MmRBcnJheShjb2wydmFscy5sZW5ndGgsIGNvbDF2YWxzLmxlbmd0aCk7XG4gICAgfVxuICAgIGlmKGhhc0NvbHVtbkhvdmVyVGV4dCkge1xuICAgICAgICBob3ZlcnRleHQgPSBMaWIuaW5pdDJkQXJyYXkoY29sMnZhbHMubGVuZ3RoLCBjb2wxdmFscy5sZW5ndGgpO1xuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IGNvbExlbjsgaSsrKSB7XG4gICAgICAgIGlmKGNvbDFbaV0gIT09IEJBRE5VTSAmJiBjb2wyW2ldICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgIHZhciBpMSA9IExpYi5maW5kQmluKGNvbDFbaV0gKyBjb2wxZHYubWluRGlmZiAvIDIsIGNvbDF2YWxzKTtcbiAgICAgICAgICAgIHZhciBpMiA9IExpYi5maW5kQmluKGNvbDJbaV0gKyBjb2wyZHYubWluRGlmZiAvIDIsIGNvbDJ2YWxzKTtcblxuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgYXJyYXlWYXJOYW1lcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBhcnJheVZhck5hbWUgPSBhcnJheVZhck5hbWVzW2pdO1xuICAgICAgICAgICAgICAgIHZhciBhcnJheVZhciA9IHRyYWNlW2FycmF5VmFyTmFtZV07XG4gICAgICAgICAgICAgICAgdmFyIG5ld0FycmF5ID0gbmV3QXJyYXlzW2pdO1xuICAgICAgICAgICAgICAgIG5ld0FycmF5W2kyXVtpMV0gPSBhcnJheVZhcltpXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaGFzQ29sdW1uVGV4dCkgdGV4dFtpMl1baTFdID0gdGV4dENvbFtpXTtcbiAgICAgICAgICAgIGlmKGhhc0NvbHVtbkhvdmVyVGV4dCkgaG92ZXJ0ZXh0W2kyXVtpMV0gPSBob3ZlclRleHRDb2xbaV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0cmFjZVsnXycgKyB2YXIxTmFtZV0gPSBjb2wxdmFscztcbiAgICB0cmFjZVsnXycgKyB2YXIyTmFtZV0gPSBjb2wydmFscztcbiAgICBmb3IoaiA9IDA7IGogPCBhcnJheVZhck5hbWVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIHRyYWNlWydfJyArIGFycmF5VmFyTmFtZXNbal1dID0gbmV3QXJyYXlzW2pdO1xuICAgIH1cbiAgICBpZihoYXNDb2x1bW5UZXh0KSB0cmFjZS5fdGV4dCA9IHRleHQ7XG4gICAgaWYoaGFzQ29sdW1uSG92ZXJUZXh0KSB0cmFjZS5faG92ZXJ0ZXh0ID0gaG92ZXJ0ZXh0O1xuXG4gICAgaWYoYXgxICYmIGF4MS50eXBlID09PSAnY2F0ZWdvcnknKSB7XG4gICAgICAgIHRyYWNlWydfJyArIHZhcjFOYW1lICsgJ0NhdGVnb3J5TWFwJ10gPSBjb2wxdmFscy5tYXAoZnVuY3Rpb24odikgeyByZXR1cm4gYXgxLl9jYXRlZ29yaWVzW3ZdO30pO1xuICAgIH1cblxuICAgIGlmKGF4MiAmJiBheDIudHlwZSA9PT0gJ2NhdGVnb3J5Jykge1xuICAgICAgICB0cmFjZVsnXycgKyB2YXIyTmFtZSArICdDYXRlZ29yeU1hcCddID0gY29sMnZhbHMubWFwKGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGF4Mi5fY2F0ZWdvcmllc1t2XTt9KTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTl9XSwxMDA2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBoYW5kbGVYWVpEZWZhdWx0cyA9IF9kZXJlcV8oJy4veHl6X2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlU3R5bGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4vc3R5bGVfZGVmYXVsdHMnKTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZhbGlkRGF0YSA9IGhhbmRsZVhZWkRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgaWYoIXZhbGlkRGF0YSkge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgaGFuZGxlU3R5bGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpO1xuXG4gICAgY29lcmNlKCdjb25uZWN0Z2FwcycsIExpYi5pc0FycmF5MUQodHJhY2VPdXQueikgJiYgKHRyYWNlT3V0LnpzbW9vdGggIT09IGZhbHNlKSk7XG5cbiAgICBjb2xvcnNjYWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnJywgY0xldHRlcjogJ3onfSk7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0c1wiOjYwMyxcIi4uLy4uL2xpYlwiOjcxOSxcIi4vYXR0cmlidXRlc1wiOjEwMDEsXCIuL3N0eWxlX2RlZmF1bHRzXCI6MTAxNCxcIi4veHl6X2RlZmF1bHRzXCI6MTAxNX1dLDEwMDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbWF4Um93TGVuZ3RoID0gX2RlcmVxXygnLi4vLi4vbGliJykubWF4Um93TGVuZ3RoO1xuXG4vKiBSZXR1cm4gYSBsaXN0IG9mIGVtcHR5IHBvaW50cyBpbiAyRCBhcnJheSB6XG4gKiBlYWNoIGVtcHR5IHBvaW50IHpbaV1bal0gZ2l2ZXMgYW4gYXJyYXkgW2ksIGosIG5laWdoYm9yQ291bnRdXG4gKiBuZWlnaGJvckNvdW50IGlzIHRoZSBjb3VudCBvZiA0IG5lYXJlc3QgbmVpZ2hib3JzIHRoYXQgRE8gZXhpc3RcbiAqIHRoaXMgaXMgdG8gZ2l2ZSB1cyBhbiBvcmRlciBvZiBwb2ludHMgdG8gZXZhbHVhdGUgZm9yIGludGVycG9sYXRpb24uXG4gKiBpZiBubyBuZWlnaGJvcnMgZXhpc3QsIHdlIGl0ZXJhdGl2ZWx5IGxvb2sgZm9yIG5laWdoYm9ycyB0aGF0IEhBVkVcbiAqIG5laWdoYm9ycywgYW5kIGFkZCBhIGZyYWN0aW9uYWwgbmVpZ2hib3JDb3VudFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGZpbmRFbXB0aWVzKHopIHtcbiAgICB2YXIgZW1wdGllcyA9IFtdO1xuICAgIHZhciBuZWlnaGJvckhhc2ggPSB7fTtcbiAgICB2YXIgbm9OZWlnaGJvckxpc3QgPSBbXTtcbiAgICB2YXIgbmV4dFJvdyA9IHpbMF07XG4gICAgdmFyIHJvdyA9IFtdO1xuICAgIHZhciBibGFuayA9IFswLCAwLCAwXTtcbiAgICB2YXIgcm93TGVuZ3RoID0gbWF4Um93TGVuZ3RoKHopO1xuICAgIHZhciBwcmV2Um93O1xuICAgIHZhciBpO1xuICAgIHZhciBqO1xuICAgIHZhciB0aGlzUHQ7XG4gICAgdmFyIHA7XG4gICAgdmFyIG5laWdoYm9yQ291bnQ7XG4gICAgdmFyIG5ld05laWdoYm9ySGFzaDtcbiAgICB2YXIgZm91bmROZXdOZWlnaGJvcnM7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCB6Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHByZXZSb3cgPSByb3c7XG4gICAgICAgIHJvdyA9IG5leHRSb3c7XG4gICAgICAgIG5leHRSb3cgPSB6W2kgKyAxXSB8fCBbXTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgcm93TGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKHJvd1tqXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbmVpZ2hib3JDb3VudCA9IChyb3dbaiAtIDFdICE9PSB1bmRlZmluZWQgPyAxIDogMCkgK1xuICAgICAgICAgICAgICAgICAgICAocm93W2ogKyAxXSAhPT0gdW5kZWZpbmVkID8gMSA6IDApICtcbiAgICAgICAgICAgICAgICAgICAgKHByZXZSb3dbal0gIT09IHVuZGVmaW5lZCA/IDEgOiAwKSArXG4gICAgICAgICAgICAgICAgICAgIChuZXh0Um93W2pdICE9PSB1bmRlZmluZWQgPyAxIDogMCk7XG5cbiAgICAgICAgICAgICAgICBpZihuZWlnaGJvckNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGZvciB0aGlzIHB1cnBvc2UsIGRvbid0IGNvdW50IG9mZi10aGUtZWRnZSBwb2ludHNcbiAgICAgICAgICAgICAgICAgICAgLy8gYXMgdW5kZWZpbmVkIG5laWdoYm9yc1xuICAgICAgICAgICAgICAgICAgICBpZihpID09PSAwKSBuZWlnaGJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgIGlmKGogPT09IDApIG5laWdoYm9yQ291bnQrKztcbiAgICAgICAgICAgICAgICAgICAgaWYoaSA9PT0gei5sZW5ndGggLSAxKSBuZWlnaGJvckNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgIGlmKGogPT09IHJvdy5sZW5ndGggLSAxKSBuZWlnaGJvckNvdW50Kys7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgYWxsIG5laWdoYm9ycyB0aGF0IGNvdWxkIGV4aXN0IGRvLCB3ZSBkb24ndFxuICAgICAgICAgICAgICAgICAgICAvLyBuZWVkIHRoaXMgZm9yIGZpbmRpbmcgZmFydGhlciBuZWlnaGJvcnNcbiAgICAgICAgICAgICAgICAgICAgaWYobmVpZ2hib3JDb3VudCA8IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5laWdoYm9ySGFzaFtbaSwgal1dID0gW2ksIGosIG5laWdoYm9yQ291bnRdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgZW1wdGllcy5wdXNoKFtpLCBqLCBuZWlnaGJvckNvdW50XSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIG5vTmVpZ2hib3JMaXN0LnB1c2goW2ksIGpdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHdoaWxlKG5vTmVpZ2hib3JMaXN0Lmxlbmd0aCkge1xuICAgICAgICBuZXdOZWlnaGJvckhhc2ggPSB7fTtcbiAgICAgICAgZm91bmROZXdOZWlnaGJvcnMgPSBmYWxzZTtcblxuICAgICAgICAvLyBsb29rIGZvciBjZWxscyB0aGF0IG5vdyBoYXZlIG5laWdoYm9ycyBidXQgZGlkbid0IGJlZm9yZVxuICAgICAgICBmb3IocCA9IG5vTmVpZ2hib3JMaXN0Lmxlbmd0aCAtIDE7IHAgPj0gMDsgcC0tKSB7XG4gICAgICAgICAgICB0aGlzUHQgPSBub05laWdoYm9yTGlzdFtwXTtcbiAgICAgICAgICAgIGkgPSB0aGlzUHRbMF07XG4gICAgICAgICAgICBqID0gdGhpc1B0WzFdO1xuXG4gICAgICAgICAgICBuZWlnaGJvckNvdW50ID0gKChuZWlnaGJvckhhc2hbW2kgLSAxLCBqXV0gfHwgYmxhbmspWzJdICtcbiAgICAgICAgICAgICAgICAobmVpZ2hib3JIYXNoW1tpICsgMSwgal1dIHx8IGJsYW5rKVsyXSArXG4gICAgICAgICAgICAgICAgKG5laWdoYm9ySGFzaFtbaSwgaiAtIDFdXSB8fCBibGFuaylbMl0gK1xuICAgICAgICAgICAgICAgIChuZWlnaGJvckhhc2hbW2ksIGogKyAxXV0gfHwgYmxhbmspWzJdKSAvIDIwO1xuXG4gICAgICAgICAgICBpZihuZWlnaGJvckNvdW50KSB7XG4gICAgICAgICAgICAgICAgbmV3TmVpZ2hib3JIYXNoW3RoaXNQdF0gPSBbaSwgaiwgbmVpZ2hib3JDb3VudF07XG4gICAgICAgICAgICAgICAgbm9OZWlnaGJvckxpc3Quc3BsaWNlKHAsIDEpO1xuICAgICAgICAgICAgICAgIGZvdW5kTmV3TmVpZ2hib3JzID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKCFmb3VuZE5ld05laWdoYm9ycykge1xuICAgICAgICAgICAgdGhyb3cgJ2ZpbmRFbXB0aWVzIGl0ZXJhdGVkIHdpdGggbm8gbmV3IG5laWdoYm9ycyc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwdXQgdGhlc2UgbmV3IGNlbGxzIGludG8gdGhlIG1haW4gbmVpZ2hib3IgbGlzdFxuICAgICAgICBmb3IodGhpc1B0IGluIG5ld05laWdoYm9ySGFzaCkge1xuICAgICAgICAgICAgbmVpZ2hib3JIYXNoW3RoaXNQdF0gPSBuZXdOZWlnaGJvckhhc2hbdGhpc1B0XTtcbiAgICAgICAgICAgIGVtcHRpZXMucHVzaChuZXdOZWlnaGJvckhhc2hbdGhpc1B0XSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzb3J0IHRoZSBmdWxsIGxpc3QgaW4gZGVzY2VuZGluZyBvcmRlciBvZiBuZWlnaGJvciBjb3VudFxuICAgIHJldHVybiBlbXB0aWVzLnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYlsyXSAtIGFbMl07IH0pO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTl9XSwxMDA4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEZ4ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGV4dHJhY3RPcHRzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlJykuZXh0cmFjdE9wdHM7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUsIGhvdmVyTGF5ZXIsIGNvbnRvdXIpIHtcbiAgICB2YXIgY2QwID0gcG9pbnREYXRhLmNkWzBdO1xuICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICB2YXIgeGEgPSBwb2ludERhdGEueGE7XG4gICAgdmFyIHlhID0gcG9pbnREYXRhLnlhO1xuICAgIHZhciB4ID0gY2QwLng7XG4gICAgdmFyIHkgPSBjZDAueTtcbiAgICB2YXIgeiA9IGNkMC56O1xuICAgIHZhciB4YyA9IGNkMC54Q2VudGVyO1xuICAgIHZhciB5YyA9IGNkMC55Q2VudGVyO1xuICAgIHZhciB6bWFzayA9IGNkMC56bWFzaztcbiAgICB2YXIgemhvdmVyZm9ybWF0ID0gdHJhY2UuemhvdmVyZm9ybWF0O1xuICAgIHZhciB4MiA9IHg7XG4gICAgdmFyIHkyID0geTtcblxuICAgIHZhciB4bCwgeWwsIG54LCBueTtcblxuICAgIGlmKHBvaW50RGF0YS5pbmRleCAhPT0gZmFsc2UpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG54ID0gTWF0aC5yb3VuZChwb2ludERhdGEuaW5kZXhbMV0pO1xuICAgICAgICAgICAgbnkgPSBNYXRoLnJvdW5kKHBvaW50RGF0YS5pbmRleFswXSk7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgTGliLmVycm9yKCdFcnJvciBob3ZlcmluZyBvbiBoZWF0bWFwLCAnICtcbiAgICAgICAgICAgICAgICAncG9pbnROdW1iZXIgbXVzdCBiZSBbcm93LGNvbF0sIGZvdW5kOicsIHBvaW50RGF0YS5pbmRleCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYobnggPCAwIHx8IG54ID49IHpbMF0ubGVuZ3RoIHx8IG55IDwgMCB8fCBueSA+IHoubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYoRnguaW5ib3goeHZhbCAtIHhbMF0sIHh2YWwgLSB4W3gubGVuZ3RoIC0gMV0sIDApID4gMCB8fFxuICAgICAgICAgICAgRnguaW5ib3goeXZhbCAtIHlbMF0sIHl2YWwgLSB5W3kubGVuZ3RoIC0gMV0sIDApID4gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYoY29udG91cikge1xuICAgICAgICAgICAgdmFyIGkyO1xuICAgICAgICAgICAgeDIgPSBbMiAqIHhbMF0gLSB4WzFdXTtcblxuICAgICAgICAgICAgZm9yKGkyID0gMTsgaTIgPCB4Lmxlbmd0aDsgaTIrKykge1xuICAgICAgICAgICAgICAgIHgyLnB1c2goKHhbaTJdICsgeFtpMiAtIDFdKSAvIDIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeDIucHVzaChbMiAqIHhbeC5sZW5ndGggLSAxXSAtIHhbeC5sZW5ndGggLSAyXV0pO1xuXG4gICAgICAgICAgICB5MiA9IFsyICogeVswXSAtIHlbMV1dO1xuICAgICAgICAgICAgZm9yKGkyID0gMTsgaTIgPCB5Lmxlbmd0aDsgaTIrKykge1xuICAgICAgICAgICAgICAgIHkyLnB1c2goKHlbaTJdICsgeVtpMiAtIDFdKSAvIDIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeTIucHVzaChbMiAqIHlbeS5sZW5ndGggLSAxXSAtIHlbeS5sZW5ndGggLSAyXV0pO1xuICAgICAgICB9XG4gICAgICAgIG54ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oeDIubGVuZ3RoIC0gMiwgTGliLmZpbmRCaW4oeHZhbCwgeDIpKSk7XG4gICAgICAgIG55ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oeTIubGVuZ3RoIC0gMiwgTGliLmZpbmRCaW4oeXZhbCwgeTIpKSk7XG4gICAgfVxuXG4gICAgdmFyIHgwID0geGEuYzJwKHhbbnhdKTtcbiAgICB2YXIgeDEgPSB4YS5jMnAoeFtueCArIDFdKTtcbiAgICB2YXIgeTAgPSB5YS5jMnAoeVtueV0pO1xuICAgIHZhciB5MSA9IHlhLmMycCh5W255ICsgMV0pO1xuXG4gICAgaWYoY29udG91cikge1xuICAgICAgICB4MSA9IHgwO1xuICAgICAgICB4bCA9IHhbbnhdO1xuICAgICAgICB5MSA9IHkwO1xuICAgICAgICB5bCA9IHlbbnldO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHhsID0geGMgPyB4Y1tueF0gOiAoKHhbbnhdICsgeFtueCArIDFdKSAvIDIpO1xuICAgICAgICB5bCA9IHljID8geWNbbnldIDogKCh5W255XSArIHlbbnkgKyAxXSkgLyAyKTtcblxuICAgICAgICBpZih4YSAmJiB4YS50eXBlID09PSAnY2F0ZWdvcnknKSB4bCA9IHhbbnhdO1xuICAgICAgICBpZih5YSAmJiB5YS50eXBlID09PSAnY2F0ZWdvcnknKSB5bCA9IHlbbnldO1xuXG4gICAgICAgIGlmKHRyYWNlLnpzbW9vdGgpIHtcbiAgICAgICAgICAgIHgwID0geDEgPSB4YS5jMnAoeGwpO1xuICAgICAgICAgICAgeTAgPSB5MSA9IHlhLmMycCh5bCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgelZhbCA9IHpbbnldW254XTtcbiAgICBpZih6bWFzayAmJiAhem1hc2tbbnldW254XSkgelZhbCA9IHVuZGVmaW5lZDtcblxuICAgIHZhciB0ZXh0O1xuICAgIGlmKEFycmF5LmlzQXJyYXkoY2QwLmhvdmVydGV4dCkgJiYgQXJyYXkuaXNBcnJheShjZDAuaG92ZXJ0ZXh0W255XSkpIHtcbiAgICAgICAgdGV4dCA9IGNkMC5ob3ZlcnRleHRbbnldW254XTtcbiAgICB9IGVsc2UgaWYoQXJyYXkuaXNBcnJheShjZDAudGV4dCkgJiYgQXJyYXkuaXNBcnJheShjZDAudGV4dFtueV0pKSB7XG4gICAgICAgIHRleHQgPSBjZDAudGV4dFtueV1bbnhdO1xuICAgIH1cblxuICAgIC8vIGR1bW15IGF4aXMgZm9yIGZvcm1hdHRpbmcgdGhlIHogdmFsdWVcbiAgICB2YXIgY09wdHMgPSBleHRyYWN0T3B0cyh0cmFjZSk7XG4gICAgdmFyIGR1bW15QXggPSB7XG4gICAgICAgIHR5cGU6ICdsaW5lYXInLFxuICAgICAgICByYW5nZTogW2NPcHRzLm1pbiwgY09wdHMubWF4XSxcbiAgICAgICAgaG92ZXJmb3JtYXQ6IHpob3ZlcmZvcm1hdCxcbiAgICAgICAgX3NlcGFyYXRvcnM6IHhhLl9zZXBhcmF0b3JzLFxuICAgICAgICBfbnVtRm9ybWF0OiB4YS5fbnVtRm9ybWF0XG4gICAgfTtcbiAgICB2YXIgekxhYmVsID0gQXhlcy50aWNrVGV4dChkdW1teUF4LCB6VmFsLCAnaG92ZXInKS50ZXh0O1xuXG4gICAgcmV0dXJuIFtMaWIuZXh0ZW5kRmxhdChwb2ludERhdGEsIHtcbiAgICAgICAgaW5kZXg6IFtueSwgbnhdLFxuICAgICAgICAvLyBuZXZlciBsZXQgYSAyRCBvdmVycmlkZSAxRCB0eXBlIGFzIGNsb3Nlc3QgcG9pbnRcbiAgICAgICAgZGlzdGFuY2U6IHBvaW50RGF0YS5tYXhIb3ZlckRpc3RhbmNlLFxuICAgICAgICBzcGlrZURpc3RhbmNlOiBwb2ludERhdGEubWF4U3Bpa2VEaXN0YW5jZSxcbiAgICAgICAgeDA6IHgwLFxuICAgICAgICB4MTogeDEsXG4gICAgICAgIHkwOiB5MCxcbiAgICAgICAgeTE6IHkxLFxuICAgICAgICB4TGFiZWxWYWw6IHhsLFxuICAgICAgICB5TGFiZWxWYWw6IHlsLFxuICAgICAgICB6TGFiZWxWYWw6IHpWYWwsXG4gICAgICAgIHpMYWJlbDogekxhYmVsLFxuICAgICAgICB0ZXh0OiB0ZXh0XG4gICAgfSldO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGVcIjo2MDUsXCIuLi8uLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3Njd9XSwxMDA5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKSxcbiAgICBjb2xvcmJhcjogX2RlcmVxXygnLi9jb2xvcmJhcicpLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuL3N0eWxlJyksXG4gICAgaG92ZXJQb2ludHM6IF9kZXJlcV8oJy4vaG92ZXInKSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ2hlYXRtYXAnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKSxcbiAgICBjYXRlZ29yaWVzOiBbJ2NhcnRlc2lhbicsICdzdmcnLCAnMmRNYXAnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvY2FydGVzaWFuXCI6Nzc4LFwiLi9hdHRyaWJ1dGVzXCI6MTAwMSxcIi4vY2FsY1wiOjEwMDIsXCIuL2NvbG9yYmFyXCI6MTAwNCxcIi4vZGVmYXVsdHNcIjoxMDA2LFwiLi9ob3ZlclwiOjEwMDgsXCIuL3Bsb3RcIjoxMDEyLFwiLi9zdHlsZVwiOjEwMTN9XSwxMDEwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgSU5URVJQVEhSRVNIT0xEID0gMWUtMjtcbnZhciBORUlHSEJPUlNISUZUUyA9IFtbLTEsIDBdLCBbMSwgMF0sIFswLCAtMV0sIFswLCAxXV07XG5cbmZ1bmN0aW9uIGNvcnJlY3Rpb25PdmVyc2hvb3QobWF4RnJhY3Rpb25hbENoYW5nZSkge1xuICAgIC8vIHN0YXJ0IHdpdGggbGVzcyBvdmVyc2hvb3QsIHVudGlsIHdlIGtub3cgaXQncyBjb252ZXJnaW5nLFxuICAgIC8vIHRoZW4gcmFtcCB1cCB0aGUgb3ZlcnNob290IGZvciBmYXN0ZXIgY29udmVyZ2VuY2VcbiAgICByZXR1cm4gMC41IC0gMC4yNSAqIE1hdGgubWluKDEsIG1heEZyYWN0aW9uYWxDaGFuZ2UgKiAwLjUpO1xufVxuXG4vKlxuICogaW50ZXJwMmQ6IEZpbGwgaW4gbWlzc2luZyBkYXRhIGZyb20gYSAyRCBhcnJheSB1c2luZyBhbiBpdGVyYXRpdmVcbiAqICAgcG9pc3NvbiBlcXVhdGlvbiBzb2x2ZXIgd2l0aCB6ZXJvLWRlcml2YXRpdmUgQkMgYXQgZWRnZXMuXG4gKiAgIEFtYXppbmdseSwgdGhpcyBqdXN0IGFtb3VudHMgdG8gcmVwZWF0ZWRseSBhdmVyYWdpbmcgYWxsIHRoZSBleGlzdGluZ1xuICogICBuZWFyZXN0IG5laWdoYm9ycywgYXQgbGVhc3QgaWYgd2UgZG9uJ3QgdGFrZSB4L3kgc2NhbGluZyBpbnRvIGFjY291bnQsXG4gKiAgIHdoaWNoIGlzIHRoZSByaWdodCBhcHByb2FjaCBoZXJlIHdoZXJlIHggYW5kIHkgbWF5IG5vdCBldmVuIGhhdmUgdGhlXG4gKiAgIHNhbWUgdW5pdHMuXG4gKlxuICogQHBhcmFtIHthcnJheSBvZiBhcnJheXN9IHpcbiAqICAgICAgVGhlIDJEIGFycmF5IHRvIGZpbGwgaW4uIFdpbGwgYmUgbXV0YXRlZCBoZXJlLiBBc3N1bWVkIHRvIGFscmVhZHkgYmVcbiAqICAgICAgY2xlYW5lZCwgc28gYWxsIGVudHJpZXMgYXJlIG51bWJlcnMgZXhjZXB0IGdhcHMsIHdoaWNoIGFyZSBgdW5kZWZpbmVkYC5cbiAqIEBwYXJhbSB7YXJyYXkgb2YgYXJyYXlzfSBlbXB0eVBvaW50c1xuICogICAgICBFYWNoIGVudHJ5IFtpLCBqLCBuZWlnaGJvckNvdW50XSBmb3IgZW1wdHkgcG9pbnRzIHpbaV1bal0gYW5kIHRoZSBudW1iZXJcbiAqICAgICAgb2YgbmVpZ2hib3JzIHRoYXQgYXJlICpub3QqIG1pc3NpbmcuIEFzc3VtZWQgdG8gYmUgc29ydGVkIGZyb20gbW9zdCB0b1xuICogICAgICBsZWFzdCBuZWlnaGJvcnMsIGFzIHByb2R1Y2VkIGJ5IGhlYXRtYXAvZmluZF9lbXB0aWVzLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGludGVycDJkKHosIGVtcHR5UG9pbnRzKSB7XG4gICAgdmFyIG1heEZyYWN0aW9uYWxDaGFuZ2UgPSAxO1xuICAgIHZhciBpO1xuXG4gICAgLy8gb25lIHBhc3MgdG8gZmlsbCBpbiBhIHN0YXJ0aW5nIHZhbHVlIGZvciBhbGwgdGhlIGVtcHRpZXNcbiAgICBpdGVyYXRlSW50ZXJwMmQoeiwgZW1wdHlQb2ludHMpO1xuXG4gICAgLy8gd2UncmUgZG9uJ3QgbmVlZCB0byBpdGVyYXRlIGxvbmUgZW1wdGllcyAtIHJlbW92ZSB0aGVtXG4gICAgZm9yKGkgPSAwOyBpIDwgZW1wdHlQb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoZW1wdHlQb2ludHNbaV1bMl0gPCA0KSBicmVhaztcbiAgICB9XG4gICAgLy8gYnV0IGRvbid0IHJlbW92ZSB0aGVzZSBwb2ludHMgZnJvbSB0aGUgb3JpZ2luYWwgYXJyYXksXG4gICAgLy8gd2UnbGwgdXNlIHRoZW0gZm9yIG1hc2tpbmcsIHNvIG1ha2UgYSBjb3B5LlxuICAgIGVtcHR5UG9pbnRzID0gZW1wdHlQb2ludHMuc2xpY2UoaSk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCAxMDAgJiYgbWF4RnJhY3Rpb25hbENoYW5nZSA+IElOVEVSUFRIUkVTSE9MRDsgaSsrKSB7XG4gICAgICAgIG1heEZyYWN0aW9uYWxDaGFuZ2UgPSBpdGVyYXRlSW50ZXJwMmQoeiwgZW1wdHlQb2ludHMsXG4gICAgICAgICAgICBjb3JyZWN0aW9uT3ZlcnNob290KG1heEZyYWN0aW9uYWxDaGFuZ2UpKTtcbiAgICB9XG4gICAgaWYobWF4RnJhY3Rpb25hbENoYW5nZSA+IElOVEVSUFRIUkVTSE9MRCkge1xuICAgICAgICBMaWIubG9nKCdpbnRlcnAyZCBkaWRuXFwndCBjb252ZXJnZSBxdWlja2x5JywgbWF4RnJhY3Rpb25hbENoYW5nZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHo7XG59O1xuXG5mdW5jdGlvbiBpdGVyYXRlSW50ZXJwMmQoeiwgZW1wdHlQb2ludHMsIG92ZXJzaG9vdCkge1xuICAgIHZhciBtYXhGcmFjdGlvbmFsQ2hhbmdlID0gMDtcbiAgICB2YXIgdGhpc1B0O1xuICAgIHZhciBpO1xuICAgIHZhciBqO1xuICAgIHZhciBwO1xuICAgIHZhciBxO1xuICAgIHZhciBuZWlnaGJvclNoaWZ0O1xuICAgIHZhciBuZWlnaGJvclJvdztcbiAgICB2YXIgbmVpZ2hib3JWYWw7XG4gICAgdmFyIG5laWdoYm9yQ291bnQ7XG4gICAgdmFyIG5laWdoYm9yU3VtO1xuICAgIHZhciBpbml0aWFsVmFsO1xuICAgIHZhciBtaW5OZWlnaGJvcjtcbiAgICB2YXIgbWF4TmVpZ2hib3I7XG5cbiAgICBmb3IocCA9IDA7IHAgPCBlbXB0eVBvaW50cy5sZW5ndGg7IHArKykge1xuICAgICAgICB0aGlzUHQgPSBlbXB0eVBvaW50c1twXTtcbiAgICAgICAgaSA9IHRoaXNQdFswXTtcbiAgICAgICAgaiA9IHRoaXNQdFsxXTtcbiAgICAgICAgaW5pdGlhbFZhbCA9IHpbaV1bal07XG4gICAgICAgIG5laWdoYm9yU3VtID0gMDtcbiAgICAgICAgbmVpZ2hib3JDb3VudCA9IDA7XG5cbiAgICAgICAgZm9yKHEgPSAwOyBxIDwgNDsgcSsrKSB7XG4gICAgICAgICAgICBuZWlnaGJvclNoaWZ0ID0gTkVJR0hCT1JTSElGVFNbcV07XG4gICAgICAgICAgICBuZWlnaGJvclJvdyA9IHpbaSArIG5laWdoYm9yU2hpZnRbMF1dO1xuICAgICAgICAgICAgaWYoIW5laWdoYm9yUm93KSBjb250aW51ZTtcbiAgICAgICAgICAgIG5laWdoYm9yVmFsID0gbmVpZ2hib3JSb3dbaiArIG5laWdoYm9yU2hpZnRbMV1dO1xuICAgICAgICAgICAgaWYobmVpZ2hib3JWYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmKG5laWdoYm9yU3VtID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG1pbk5laWdoYm9yID0gbWF4TmVpZ2hib3IgPSBuZWlnaGJvclZhbDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtaW5OZWlnaGJvciA9IE1hdGgubWluKG1pbk5laWdoYm9yLCBuZWlnaGJvclZhbCk7XG4gICAgICAgICAgICAgICAgICAgIG1heE5laWdoYm9yID0gTWF0aC5tYXgobWF4TmVpZ2hib3IsIG5laWdoYm9yVmFsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbmVpZ2hib3JDb3VudCsrO1xuICAgICAgICAgICAgICAgIG5laWdoYm9yU3VtICs9IG5laWdoYm9yVmFsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYobmVpZ2hib3JDb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgJ2l0ZXJhdGVJbnRlcnAyZCBvcmRlciBpcyB3cm9uZzogbm8gZGVmaW5lZCBuZWlnaGJvcnMnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhpcyBpcyB0aGUgbGFwbGFjZSBlcXVhdGlvbiBpbnRlcnBvbGF0aW9uOlxuICAgICAgICAvLyBlYWNoIHBvaW50IGlzIGp1c3QgdGhlIGF2ZXJhZ2Ugb2YgaXRzIG5laWdoYm9yc1xuICAgICAgICAvLyBub3RlIHRoYXQgdGhpcyBpZ25vcmVzIGRpZmZlcmVudGlhbCB4L3kgc2NhbGluZ1xuICAgICAgICAvLyB3aGljaCBJIHRoaW5rIGlzIHRoZSByaWdodCBhcHByb2FjaCwgc2luY2Ugd2VcbiAgICAgICAgLy8gZG9uJ3Qga25vdyB3aGF0IHRoYXQgc2NhbGluZyBtZWFuc1xuICAgICAgICB6W2ldW2pdID0gbmVpZ2hib3JTdW0gLyBuZWlnaGJvckNvdW50O1xuXG4gICAgICAgIGlmKGluaXRpYWxWYWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYobmVpZ2hib3JDb3VudCA8IDQpIG1heEZyYWN0aW9uYWxDaGFuZ2UgPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gd2UgY2FuIG1ha2UgbGFyZ2UgZW1wdHkgcmVnaW9ucyBjb252ZXJnZSBmYXN0ZXJcbiAgICAgICAgICAgIC8vIGlmIHdlIG92ZXJzaG9vdCB0aGUgY2hhbmdlIHZzIHRoZSBwcmV2aW91cyB2YWx1ZVxuICAgICAgICAgICAgeltpXVtqXSA9ICgxICsgb3ZlcnNob290KSAqIHpbaV1bal0gLSBvdmVyc2hvb3QgKiBpbml0aWFsVmFsO1xuXG4gICAgICAgICAgICBpZihtYXhOZWlnaGJvciA+IG1pbk5laWdoYm9yKSB7XG4gICAgICAgICAgICAgICAgbWF4RnJhY3Rpb25hbENoYW5nZSA9IE1hdGgubWF4KG1heEZyYWN0aW9uYWxDaGFuZ2UsXG4gICAgICAgICAgICAgICAgICAgIE1hdGguYWJzKHpbaV1bal0gLSBpbml0aWFsVmFsKSAvIChtYXhOZWlnaGJvciAtIG1pbk5laWdoYm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWF4RnJhY3Rpb25hbENoYW5nZTtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTl9XSwxMDExOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlQm91bmRBcnJheSh0cmFjZSwgYXJyYXlJbiwgdjBJbiwgZHZJbiwgbnVtYnJpY2tzLCBheCkge1xuICAgIHZhciBhcnJheU91dCA9IFtdO1xuICAgIHZhciBpc0NvbnRvdXIgPSBSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnY29udG91cicpO1xuICAgIHZhciBpc0hpc3QgPSBSZWdpc3RyeS50cmFjZUlzKHRyYWNlLCAnaGlzdG9ncmFtJyk7XG4gICAgdmFyIGlzR0wyRCA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdnbDJkJyk7XG4gICAgdmFyIHYwO1xuICAgIHZhciBkdjtcbiAgICB2YXIgaTtcblxuICAgIHZhciBpc0FycmF5T2ZUd29JdGVtc09yTW9yZSA9IGlzQXJyYXlPclR5cGVkQXJyYXkoYXJyYXlJbikgJiYgYXJyYXlJbi5sZW5ndGggPiAxO1xuXG4gICAgaWYoaXNBcnJheU9mVHdvSXRlbXNPck1vcmUgJiYgIWlzSGlzdCAmJiAoYXgudHlwZSAhPT0gJ2NhdGVnb3J5JykpIHtcbiAgICAgICAgdmFyIGxlbiA9IGFycmF5SW4ubGVuZ3RoO1xuXG4gICAgICAgIC8vIGdpdmVuIHZhbHMgYXJlIGJyaWNrIGNlbnRlcnNcbiAgICAgICAgLy8gaG9wZWZ1bGx5IGxlbmd0aCA9PT0gbnVtYnJpY2tzLCBidXQgdXNlIHRoaXMgbWV0aG9kIGV2ZW4gaWYgdG9vIGZldyBhcmUgc3VwcGxpZWRcbiAgICAgICAgLy8gYW5kIGV4dGVuZCBpdCBsaW5lYXJseSBiYXNlZCBvbiB0aGUgbGFzdCB0d28gcG9pbnRzXG4gICAgICAgIGlmKGxlbiA8PSBudW1icmlja3MpIHtcbiAgICAgICAgICAgIC8vIGNvbnRvdXIgcGxvdHMgb25seSB3YW50IHRoZSBjZW50ZXJzXG4gICAgICAgICAgICBpZihpc0NvbnRvdXIgfHwgaXNHTDJEKSBhcnJheU91dCA9IGFycmF5SW4uc2xpY2UoMCwgbnVtYnJpY2tzKTtcbiAgICAgICAgICAgIGVsc2UgaWYobnVtYnJpY2tzID09PSAxKSB7XG4gICAgICAgICAgICAgICAgYXJyYXlPdXQgPSBbYXJyYXlJblswXSAtIDAuNSwgYXJyYXlJblswXSArIDAuNV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFycmF5T3V0ID0gWzEuNSAqIGFycmF5SW5bMF0gLSAwLjUgKiBhcnJheUluWzFdXTtcblxuICAgICAgICAgICAgICAgIGZvcihpID0gMTsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGFycmF5T3V0LnB1c2goKGFycmF5SW5baSAtIDFdICsgYXJyYXlJbltpXSkgKiAwLjUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGFycmF5T3V0LnB1c2goMS41ICogYXJyYXlJbltsZW4gLSAxXSAtIDAuNSAqIGFycmF5SW5bbGVuIC0gMl0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihsZW4gPCBudW1icmlja3MpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGFzdFB0ID0gYXJyYXlPdXRbYXJyYXlPdXQubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgdmFyIGRlbHRhID0gbGFzdFB0IC0gYXJyYXlPdXRbYXJyYXlPdXQubGVuZ3RoIC0gMl07XG5cbiAgICAgICAgICAgICAgICBmb3IoaSA9IGxlbjsgaSA8IG51bWJyaWNrczsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGxhc3RQdCArPSBkZWx0YTtcbiAgICAgICAgICAgICAgICAgICAgYXJyYXlPdXQucHVzaChsYXN0UHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGhvcGVmdWxseSBsZW5ndGggPT09IG51bWJyaWNrcysxLCBidXQgZG8gc29tZXRoaW5nIHJlZ2FyZGxlc3M6XG4gICAgICAgICAgICAvLyBnaXZlbiB2YWxzIGFyZSBicmljayBib3VuZGFyaWVzXG4gICAgICAgICAgICByZXR1cm4gaXNDb250b3VyID9cbiAgICAgICAgICAgICAgICBhcnJheUluLnNsaWNlKDAsIG51bWJyaWNrcykgOiAgLy8gd2UgbXVzdCBiZSBzdHJpY3QgZm9yIGNvbnRvdXJzXG4gICAgICAgICAgICAgICAgYXJyYXlJbi5zbGljZSgwLCBudW1icmlja3MgKyAxKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRyYWNlW2F4Ll9pZC5jaGFyQXQoMCkgKyAnY2FsZW5kYXInXTtcblxuICAgICAgICBpZihpc0hpc3QpIHtcbiAgICAgICAgICAgIHYwID0gYXgucjJjKHYwSW4sIDAsIGNhbGVuZGFyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKGlzQXJyYXlPclR5cGVkQXJyYXkoYXJyYXlJbikgJiYgYXJyYXlJbi5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICB2MCA9IGFycmF5SW5bMF07XG4gICAgICAgICAgICB9IGVsc2UgaWYodjBJbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdjAgPSAwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgZm4gPSBheC50eXBlID09PSAnbG9nJyA/IGF4LmQyYyA6IGF4LnIyYztcbiAgICAgICAgICAgICAgICB2MCA9IGZuKHYwSW4sIDAsIGNhbGVuZGFyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGR2ID0gZHZJbiB8fCAxO1xuXG4gICAgICAgIGZvcihpID0gKGlzQ29udG91ciB8fCBpc0dMMkQpID8gMCA6IC0wLjU7IGkgPCBudW1icmlja3M7IGkrKykge1xuICAgICAgICAgICAgYXJyYXlPdXQucHVzaCh2MCArIGR2ICogaSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYXJyYXlPdXQ7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3fV0sMTAxMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciB0aW55Y29sb3IgPSBfZGVyZXFfKCd0aW55Y29sb3IyJyk7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgbWFrZUNvbG9yU2NhbGVGdW5jRnJvbVRyYWNlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlJykubWFrZUNvbG9yU2NhbGVGdW5jRnJvbVRyYWNlO1xudmFyIHhtbG5zTmFtZXNwYWNlcyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy94bWxuc19uYW1lc3BhY2VzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZ2QsIHBsb3RpbmZvLCBjZGhlYXRtYXBzLCBoZWF0bWFwTGF5ZXIpIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIExpYi5tYWtlVHJhY2VHcm91cHMoaGVhdG1hcExheWVyLCBjZGhlYXRtYXBzLCAnaG0nKS5lYWNoKGZ1bmN0aW9uKGNkKSB7XG4gICAgICAgIHZhciBwbG90R3JvdXAgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBjZDAgPSBjZFswXTtcbiAgICAgICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuXG4gICAgICAgIHZhciB6ID0gY2QwLno7XG4gICAgICAgIHZhciB4ID0gY2QwLng7XG4gICAgICAgIHZhciB5ID0gY2QwLnk7XG4gICAgICAgIHZhciB4YyA9IGNkMC54Q2VudGVyO1xuICAgICAgICB2YXIgeWMgPSBjZDAueUNlbnRlcjtcbiAgICAgICAgdmFyIGlzQ29udG91ciA9IFJlZ2lzdHJ5LnRyYWNlSXModHJhY2UsICdjb250b3VyJyk7XG4gICAgICAgIHZhciB6c21vb3RoID0gaXNDb250b3VyID8gJ2Jlc3QnIDogdHJhY2UuenNtb290aDtcblxuICAgICAgICAvLyBnZXQgeiBkaW1zXG4gICAgICAgIHZhciBtID0gei5sZW5ndGg7XG4gICAgICAgIHZhciBuID0gTGliLm1heFJvd0xlbmd0aCh6KTtcbiAgICAgICAgdmFyIHhyZXYgPSBmYWxzZTtcbiAgICAgICAgdmFyIHlyZXYgPSBmYWxzZTtcblxuICAgICAgICB2YXIgbGVmdCwgcmlnaHQsIHRlbXAsIHRvcCwgYm90dG9tLCBpO1xuXG4gICAgICAgIC8vIFRPRE86IGlmIHRoZXJlIGFyZSBtdWx0aXBsZSBvdmVybGFwcGluZyBjYXRlZ29yaWNhbCBoZWF0bWFwcyxcbiAgICAgICAgLy8gb3IgaWYgd2UgYWxsb3cgY2F0ZWdvcnkgc29ydGluZywgdGhlbiB0aGUgY2F0ZWdvcmllcyBtYXkgbm90IGJlXG4gICAgICAgIC8vIHNlcXVlbnRpYWwuLi4gbWF5IG5lZWQgdG8gcmVvcmRlciBhbmQvb3IgZXhwYW5kIHpcblxuICAgICAgICAvLyBHZXQgZWRnZXMgb2YgcG5nIGluIHBpeGVscyAoeGEuYzJwKCkgbWFwcyBheGVzIGNvb3JkaW5hdGVzIHRvIHBpeGVsIGNvb3JkaW5hdGVzKVxuICAgICAgICAvLyBmaWd1cmUgb3V0IGlmIGVpdGhlciBheGlzIGlzIHJldmVyc2VkICh5IGlzIHVzdWFsbHkgcmV2ZXJzZWQsIGluIHBpeGVsIGNvb3JkcylcbiAgICAgICAgLy8gYWxzbyBjbGlwIHRoZSBpbWFnZSB0byBtYXhpbXVtIDUwJSBvdXRzaWRlIHRoZSB2aXNpYmxlIHBsb3QgYXJlYVxuICAgICAgICAvLyBiaWdnZXIgaW1hZ2UgbGV0cyB5b3UgcGFuIG1vcmUgbmF0dXJhbGx5LCBidXQgc2xvd3MgcGVyZm9ybWFuY2UuXG4gICAgICAgIC8vIFRPRE86IHVzZSBsb3ctcmVzb2x1dGlvbiBpbWFnZXMgb3V0c2lkZSB0aGUgdmlzaWJsZSBwbG90IGZvciBwYW5uaW5nXG4gICAgICAgIC8vIHRoZXNlIHdoaWxlIGxvb3BzIGZpbmQgdGhlIGZpcnN0IGFuZCBsYXN0IGJyaWNrIGJvdW5kcyB0aGF0IGFyZSBkZWZpbmVkXG4gICAgICAgIC8vIChpbiBjYXNlIG9mIGxvZyBvZiBhIG5lZ2F0aXZlKVxuICAgICAgICBpID0gMDtcbiAgICAgICAgd2hpbGUobGVmdCA9PT0gdW5kZWZpbmVkICYmIGkgPCB4Lmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIGxlZnQgPSB4YS5jMnAoeFtpXSk7XG4gICAgICAgICAgICBpKys7XG4gICAgICAgIH1cbiAgICAgICAgaSA9IHgubGVuZ3RoIC0gMTtcbiAgICAgICAgd2hpbGUocmlnaHQgPT09IHVuZGVmaW5lZCAmJiBpID4gMCkge1xuICAgICAgICAgICAgcmlnaHQgPSB4YS5jMnAoeFtpXSk7XG4gICAgICAgICAgICBpLS07XG4gICAgICAgIH1cblxuICAgICAgICBpZihyaWdodCA8IGxlZnQpIHtcbiAgICAgICAgICAgIHRlbXAgPSByaWdodDtcbiAgICAgICAgICAgIHJpZ2h0ID0gbGVmdDtcbiAgICAgICAgICAgIGxlZnQgPSB0ZW1wO1xuICAgICAgICAgICAgeHJldiA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpID0gMDtcbiAgICAgICAgd2hpbGUodG9wID09PSB1bmRlZmluZWQgJiYgaSA8IHkubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgdG9wID0geWEuYzJwKHlbaV0pO1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICB9XG4gICAgICAgIGkgPSB5Lmxlbmd0aCAtIDE7XG4gICAgICAgIHdoaWxlKGJvdHRvbSA9PT0gdW5kZWZpbmVkICYmIGkgPiAwKSB7XG4gICAgICAgICAgICBib3R0b20gPSB5YS5jMnAoeVtpXSk7XG4gICAgICAgICAgICBpLS07XG4gICAgICAgIH1cblxuICAgICAgICBpZihib3R0b20gPCB0b3ApIHtcbiAgICAgICAgICAgIHRlbXAgPSB0b3A7XG4gICAgICAgICAgICB0b3AgPSBib3R0b207XG4gICAgICAgICAgICBib3R0b20gPSB0ZW1wO1xuICAgICAgICAgICAgeXJldiA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmb3IgY29udG91cnMgd2l0aCBoZWF0bWFwIGZpbGwsIHdlIGdlbmVyYXRlIHRoZSBib3VuZGFyaWVzIGJhc2VkIG9uXG4gICAgICAgIC8vIGJyaWNrIGNlbnRlcnMgYnV0IHRoZW4gdXNlIHRoZSBicmljayBlZGdlcyBmb3IgZHJhd2luZyB0aGUgYnJpY2tzXG4gICAgICAgIGlmKGlzQ29udG91cikge1xuICAgICAgICAgICAgeGMgPSB4O1xuICAgICAgICAgICAgeWMgPSB5O1xuICAgICAgICAgICAgeCA9IGNkMC54ZmlsbDtcbiAgICAgICAgICAgIHkgPSBjZDAueWZpbGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBtYWtlIGFuIGltYWdlIHRoYXQgZ29lcyBhdCBtb3N0IGhhbGYgYSBzY3JlZW4gb2ZmIGVpdGhlciBzaWRlLCB0byBrZWVwXG4gICAgICAgIC8vIHRpbWUgcmVhc29uYWJsZSB3aGVuIHlvdSB6b29tIGluLiBpZiB6c21vb3RoIGlzIHRydWUvZmFzdCwgZG9uJ3Qgd29ycnlcbiAgICAgICAgLy8gYWJvdXQgdGhpcywgYmVjYXVzZSB6b29taW5nIGRvZXNuJ3QgaW5jcmVhc2UgbnVtYmVyIG9mIHBpeGVsc1xuICAgICAgICAvLyBpZiB6c21vb3RoIGlzIGJlc3QsIGRvbid0IGluY2x1ZGUgYW55dGhpbmcgb2ZmIHNjcmVlbiBiZWNhdXNlIGl0IHRha2VzIHRvbyBsb25nXG4gICAgICAgIGlmKHpzbW9vdGggIT09ICdmYXN0Jykge1xuICAgICAgICAgICAgdmFyIGV4dHJhID0genNtb290aCA9PT0gJ2Jlc3QnID8gMCA6IDAuNTtcbiAgICAgICAgICAgIGxlZnQgPSBNYXRoLm1heCgtZXh0cmEgKiB4YS5fbGVuZ3RoLCBsZWZ0KTtcbiAgICAgICAgICAgIHJpZ2h0ID0gTWF0aC5taW4oKDEgKyBleHRyYSkgKiB4YS5fbGVuZ3RoLCByaWdodCk7XG4gICAgICAgICAgICB0b3AgPSBNYXRoLm1heCgtZXh0cmEgKiB5YS5fbGVuZ3RoLCB0b3ApO1xuICAgICAgICAgICAgYm90dG9tID0gTWF0aC5taW4oKDEgKyBleHRyYSkgKiB5YS5fbGVuZ3RoLCBib3R0b20pO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGltYWdlV2lkdGggPSBNYXRoLnJvdW5kKHJpZ2h0IC0gbGVmdCk7XG4gICAgICAgIHZhciBpbWFnZUhlaWdodCA9IE1hdGgucm91bmQoYm90dG9tIC0gdG9wKTtcblxuICAgICAgICAvLyBzZXR1cCBpbWFnZSBub2Rlc1xuXG4gICAgICAgIC8vIGlmIGltYWdlIGlzIGVudGlyZWx5IG9mZi1zY3JlZW4sIGRvbid0IGV2ZW4gZHJhdyBpdFxuICAgICAgICB2YXIgaXNPZmZTY3JlZW4gPSAoaW1hZ2VXaWR0aCA8PSAwIHx8IGltYWdlSGVpZ2h0IDw9IDApO1xuXG4gICAgICAgIGlmKGlzT2ZmU2NyZWVuKSB7XG4gICAgICAgICAgICB2YXIgbm9JbWFnZSA9IHBsb3RHcm91cC5zZWxlY3RBbGwoJ2ltYWdlJykuZGF0YShbXSk7XG4gICAgICAgICAgICBub0ltYWdlLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGdlbmVyYXRlIGltYWdlIGRhdGFcblxuICAgICAgICB2YXIgY2FudmFzVywgY2FudmFzSDtcbiAgICAgICAgaWYoenNtb290aCA9PT0gJ2Zhc3QnKSB7XG4gICAgICAgICAgICBjYW52YXNXID0gbjtcbiAgICAgICAgICAgIGNhbnZhc0ggPSBtO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FudmFzVyA9IGltYWdlV2lkdGg7XG4gICAgICAgICAgICBjYW52YXNIID0gaW1hZ2VIZWlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IGNhbnZhc1c7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBjYW52YXNIO1xuICAgICAgICB2YXIgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICAgIHZhciBzY2xGdW5jID0gbWFrZUNvbG9yU2NhbGVGdW5jRnJvbVRyYWNlKHRyYWNlLCB7bm9OdW1lcmljQ2hlY2s6IHRydWUsIHJldHVybkFycmF5OiB0cnVlfSk7XG5cbiAgICAgICAgLy8gbWFwIGJyaWNrIGJvdW5kYXJpZXMgdG8gaW1hZ2UgcGl4ZWxzXG4gICAgICAgIHZhciB4cHgsXG4gICAgICAgICAgICB5cHg7XG4gICAgICAgIGlmKHpzbW9vdGggPT09ICdmYXN0Jykge1xuICAgICAgICAgICAgeHB4ID0geHJldiA/XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24oaW5kZXgpIHsgcmV0dXJuIG4gLSAxIC0gaW5kZXg7IH0gOlxuICAgICAgICAgICAgICAgIExpYi5pZGVudGl0eTtcbiAgICAgICAgICAgIHlweCA9IHlyZXYgP1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGluZGV4KSB7IHJldHVybiBtIC0gMSAtIGluZGV4OyB9IDpcbiAgICAgICAgICAgICAgICBMaWIuaWRlbnRpdHk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB4cHggPSBmdW5jdGlvbihpbmRleCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBMaWIuY29uc3RyYWluKE1hdGgucm91bmQoeGEuYzJwKHhbaW5kZXhdKSAtIGxlZnQpLFxuICAgICAgICAgICAgICAgICAgICAwLCBpbWFnZVdpZHRoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB5cHggPSBmdW5jdGlvbihpbmRleCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBMaWIuY29uc3RyYWluKE1hdGgucm91bmQoeWEuYzJwKHlbaW5kZXhdKSAtIHRvcCksXG4gICAgICAgICAgICAgICAgICAgIDAsIGltYWdlSGVpZ2h0KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBidWlsZCB0aGUgcGl4ZWwgbWFwIGJyaWNrLWJ5LWJyaWNrXG4gICAgICAgIC8vIGNydWlzZSB0aHJvdWdoIHotbWF0cml4IHJvdy1ieS1yb3dcbiAgICAgICAgLy8gYnVpbGQgYSBicmljayBhdCBlYWNoIHotbWF0cml4IHZhbHVlXG4gICAgICAgIHZhciB5aSA9IHlweCgwKTtcbiAgICAgICAgdmFyIHliID0gW3lpLCB5aV07XG4gICAgICAgIHZhciB4YmkgPSB4cmV2ID8gMCA6IDE7XG4gICAgICAgIHZhciB5YmkgPSB5cmV2ID8gMCA6IDE7XG4gICAgICAgIC8vIGZvciBjb2xsZWN0aW5nIGFuIGF2ZXJhZ2UgbHVtaW5vc2l0eSBvZiB0aGUgaGVhdG1hcFxuICAgICAgICB2YXIgcGl4Y291bnQgPSAwO1xuICAgICAgICB2YXIgcmNvdW50ID0gMDtcbiAgICAgICAgdmFyIGdjb3VudCA9IDA7XG4gICAgICAgIHZhciBiY291bnQgPSAwO1xuXG4gICAgICAgIHZhciB4YiwgaiwgeGksIHYsIHJvdywgYztcblxuICAgICAgICBmdW5jdGlvbiBzZXRDb2xvcih2LCBwaXhzaXplKSB7XG4gICAgICAgICAgICBpZih2ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgYyA9IHNjbEZ1bmModik7XG4gICAgICAgICAgICAgICAgY1swXSA9IE1hdGgucm91bmQoY1swXSk7XG4gICAgICAgICAgICAgICAgY1sxXSA9IE1hdGgucm91bmQoY1sxXSk7XG4gICAgICAgICAgICAgICAgY1syXSA9IE1hdGgucm91bmQoY1syXSk7XG5cbiAgICAgICAgICAgICAgICBwaXhjb3VudCArPSBwaXhzaXplO1xuICAgICAgICAgICAgICAgIHJjb3VudCArPSBjWzBdICogcGl4c2l6ZTtcbiAgICAgICAgICAgICAgICBnY291bnQgKz0gY1sxXSAqIHBpeHNpemU7XG4gICAgICAgICAgICAgICAgYmNvdW50ICs9IGNbMl0gKiBwaXhzaXplO1xuICAgICAgICAgICAgICAgIHJldHVybiBjO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIFswLCAwLCAwLCAwXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGludGVycENvbG9yKHIwLCByMSwgeGludGVycCwgeWludGVycCkge1xuICAgICAgICAgICAgdmFyIHowMCA9IHIwW3hpbnRlcnAuYmluMF07XG4gICAgICAgICAgICBpZih6MDAgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHNldENvbG9yKHVuZGVmaW5lZCwgMSk7XG5cbiAgICAgICAgICAgIHZhciB6MDEgPSByMFt4aW50ZXJwLmJpbjFdO1xuICAgICAgICAgICAgdmFyIHoxMCA9IHIxW3hpbnRlcnAuYmluMF07XG4gICAgICAgICAgICB2YXIgejExID0gcjFbeGludGVycC5iaW4xXTtcbiAgICAgICAgICAgIHZhciBkeCA9ICh6MDEgLSB6MDApIHx8IDA7XG4gICAgICAgICAgICB2YXIgZHkgPSAoejEwIC0gejAwKSB8fCAwO1xuICAgICAgICAgICAgdmFyIGR4eTtcblxuICAgICAgICAgICAgLy8gdGhlIGJpbGluZWFyIGludGVycG9sYXRpb24gdGVybSBuZWVkcyBkaWZmZXJlbnQgY2FsY3VsYXRpb25zXG4gICAgICAgICAgICAvLyBmb3IgYWxsIHRoZSBkaWZmZXJlbnQgcGVybXV0YXRpb25zIG9mIG1pc3NpbmcgZGF0YVxuICAgICAgICAgICAgLy8gYW1vbmcgdGhlIG5laWdoYm9ycyBvZiB0aGUgbWFpbiBwb2ludCwgdG8gZW5zdXJlXG4gICAgICAgICAgICAvLyBjb250aW51aXR5IGFjcm9zcyBicmljayBib3VuZGFyaWVzLlxuICAgICAgICAgICAgaWYoejAxID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZih6MTEgPT09IHVuZGVmaW5lZCkgZHh5ID0gMDtcbiAgICAgICAgICAgICAgICBlbHNlIGlmKHoxMCA9PT0gdW5kZWZpbmVkKSBkeHkgPSAyICogKHoxMSAtIHowMCk7XG4gICAgICAgICAgICAgICAgZWxzZSBkeHkgPSAoMiAqIHoxMSAtIHoxMCAtIHowMCkgKiAyIC8gMztcbiAgICAgICAgICAgIH0gZWxzZSBpZih6MTEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmKHoxMCA9PT0gdW5kZWZpbmVkKSBkeHkgPSAwO1xuICAgICAgICAgICAgICAgIGVsc2UgZHh5ID0gKDIgKiB6MDAgLSB6MDEgLSB6MTApICogMiAvIDM7XG4gICAgICAgICAgICB9IGVsc2UgaWYoejEwID09PSB1bmRlZmluZWQpIGR4eSA9ICgyICogejExIC0gejAxIC0gejAwKSAqIDIgLyAzO1xuICAgICAgICAgICAgZWxzZSBkeHkgPSAoejExICsgejAwIC0gejAxIC0gejEwKTtcblxuICAgICAgICAgICAgcmV0dXJuIHNldENvbG9yKHowMCArIHhpbnRlcnAuZnJhYyAqIGR4ICsgeWludGVycC5mcmFjICogKGR5ICsgeGludGVycC5mcmFjICogZHh5KSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih6c21vb3RoKSB7IC8vIGJlc3Qgb3IgZmFzdCwgd29ya3MgZmFzdGVzdCB3aXRoIGltYWdlRGF0YVxuICAgICAgICAgICAgdmFyIHB4SW5kZXggPSAwO1xuICAgICAgICAgICAgdmFyIHBpeGVscztcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBwaXhlbHMgPSBuZXcgVWludDhBcnJheShpbWFnZVdpZHRoICogaW1hZ2VIZWlnaHQgKiA0KTtcbiAgICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgICAgIHBpeGVscyA9IG5ldyBBcnJheShpbWFnZVdpZHRoICogaW1hZ2VIZWlnaHQgKiA0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoenNtb290aCA9PT0gJ2Jlc3QnKSB7XG4gICAgICAgICAgICAgICAgdmFyIHhGb3JQeCA9IHhjIHx8IHg7XG4gICAgICAgICAgICAgICAgdmFyIHlGb3JQeCA9IHljIHx8IHk7XG4gICAgICAgICAgICAgICAgdmFyIHhQaXhBcnJheSA9IG5ldyBBcnJheSh4Rm9yUHgubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB2YXIgeVBpeEFycmF5ID0gbmV3IEFycmF5KHlGb3JQeC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIHZhciB4aW50ZXJwQXJyYXkgPSBuZXcgQXJyYXkoaW1hZ2VXaWR0aCk7XG4gICAgICAgICAgICAgICAgdmFyIGZpbmRJbnRlcnBYID0geGMgPyBmaW5kSW50ZXJwRnJvbUNlbnRlcnMgOiBmaW5kSW50ZXJwO1xuICAgICAgICAgICAgICAgIHZhciBmaW5kSW50ZXJwWSA9IHljID8gZmluZEludGVycEZyb21DZW50ZXJzIDogZmluZEludGVycDtcbiAgICAgICAgICAgICAgICB2YXIgeWludGVycCwgcjAsIHIxO1xuXG4gICAgICAgICAgICAgICAgLy8gZmlyc3QgbWFrZSBhcnJheXMgb2YgeCBhbmQgeSBwaXhlbCBsb2NhdGlvbnMgb2YgYnJpY2sgYm91bmRhcmllc1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHhGb3JQeC5sZW5ndGg7IGkrKykgeFBpeEFycmF5W2ldID0gTWF0aC5yb3VuZCh4YS5jMnAoeEZvclB4W2ldKSAtIGxlZnQpO1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHlGb3JQeC5sZW5ndGg7IGkrKykgeVBpeEFycmF5W2ldID0gTWF0aC5yb3VuZCh5YS5jMnAoeUZvclB4W2ldKSAtIHRvcCk7XG5cbiAgICAgICAgICAgICAgICAvLyB0aGVuIG1ha2UgYXJyYXlzIG9mIGludGVycG9sYXRpb25zXG4gICAgICAgICAgICAgICAgLy8gKGJpbjA9Y2xvc2VzdCwgYmluMT1uZXh0LCBmcmFjPWZyYWN0aW9uYWwgZGlzdC4pXG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW1hZ2VXaWR0aDsgaSsrKSB4aW50ZXJwQXJyYXlbaV0gPSBmaW5kSW50ZXJwWChpLCB4UGl4QXJyYXkpO1xuXG4gICAgICAgICAgICAgICAgLy8gbm93IGRvIHRoZSBpbnRlcnBvbGF0aW9ucyBhbmQgZmlsbCB0aGUgcG5nXG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgaW1hZ2VIZWlnaHQ7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB5aW50ZXJwID0gZmluZEludGVycFkoaiwgeVBpeEFycmF5KTtcbiAgICAgICAgICAgICAgICAgICAgcjAgPSB6W3lpbnRlcnAuYmluMF07XG4gICAgICAgICAgICAgICAgICAgIHIxID0gelt5aW50ZXJwLmJpbjFdO1xuICAgICAgICAgICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBpbWFnZVdpZHRoOyBpKyssIHB4SW5kZXggKz0gNCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYyA9IGludGVycENvbG9yKHIwLCByMSwgeGludGVycEFycmF5W2ldLCB5aW50ZXJwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1dENvbG9yKHBpeGVscywgcHhJbmRleCwgYyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgeyAvLyB6c21vb3RoID0gZmFzdFxuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG07IGorKykge1xuICAgICAgICAgICAgICAgICAgICByb3cgPSB6W2pdO1xuICAgICAgICAgICAgICAgICAgICB5YiA9IHlweChqKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW1hZ2VXaWR0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjID0gc2V0Q29sb3Iocm93W2ldLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB4SW5kZXggPSAoeWIgKiBpbWFnZVdpZHRoICsgeHB4KGkpKSAqIDQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdXRDb2xvcihwaXhlbHMsIHB4SW5kZXgsIGMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgaW1hZ2VEYXRhID0gY29udGV4dC5jcmVhdGVJbWFnZURhdGEoaW1hZ2VXaWR0aCwgaW1hZ2VIZWlnaHQpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpbWFnZURhdGEuZGF0YS5zZXQocGl4ZWxzKTtcbiAgICAgICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgICAgICAgIHZhciBweEFycmF5ID0gaW1hZ2VEYXRhLmRhdGE7XG4gICAgICAgICAgICAgICAgdmFyIGRsZW4gPSBweEFycmF5Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBkbGVuOyBqICsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHB4QXJyYXlbal0gPSBwaXhlbHNbal07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb250ZXh0LnB1dEltYWdlRGF0YShpbWFnZURhdGEsIDAsIDApO1xuICAgICAgICB9IGVsc2UgeyAvLyB6c21vb3RoID0gZmFsc2UgLT4gZmlsbGluZyBwb3RlbnRpYWxseSBsYXJnZSBicmlja3Mgd29ya3MgZmFzdGVzdCB3aXRoIGZpbGxSZWN0XG4gICAgICAgICAgICAvLyBnYXBzIGRvIG5vdCBuZWVkIHRvIGJlIGV4YWN0IGludGVnZXJzLCBidXQgaWYgdGhleSAqYXJlKiB3ZSB3aWxsIGdldFxuICAgICAgICAgICAgLy8gY2xlYW5lciBlZGdlcyBieSByb3VuZGluZyBhdCBsZWFzdCBvbmUgZWRnZVxuICAgICAgICAgICAgdmFyIHhHYXAgPSB0cmFjZS54Z2FwO1xuICAgICAgICAgICAgdmFyIHlHYXAgPSB0cmFjZS55Z2FwO1xuICAgICAgICAgICAgdmFyIHhHYXBMZWZ0ID0gTWF0aC5mbG9vcih4R2FwIC8gMik7XG4gICAgICAgICAgICB2YXIgeUdhcFRvcCA9IE1hdGguZmxvb3IoeUdhcCAvIDIpO1xuXG4gICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBtOyBqKyspIHtcbiAgICAgICAgICAgICAgICByb3cgPSB6W2pdO1xuICAgICAgICAgICAgICAgIHliLnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICB5Ylt5YmldID0geXB4KGogKyAxKTtcbiAgICAgICAgICAgICAgICBpZih5YlswXSA9PT0geWJbMV0gfHwgeWJbMF0gPT09IHVuZGVmaW5lZCB8fCB5YlsxXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB4aSA9IHhweCgwKTtcbiAgICAgICAgICAgICAgICB4YiA9IFt4aSwgeGldO1xuICAgICAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAvLyBidWlsZCBvbmUgY29sb3IgYnJpY2shXG4gICAgICAgICAgICAgICAgICAgIHhiLnJldmVyc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgeGJbeGJpXSA9IHhweChpICsgMSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHhiWzBdID09PSB4YlsxXSB8fCB4YlswXSA9PT0gdW5kZWZpbmVkIHx8IHhiWzFdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHYgPSByb3dbaV07XG4gICAgICAgICAgICAgICAgICAgIGMgPSBzZXRDb2xvcih2LCAoeGJbMV0gLSB4YlswXSkgKiAoeWJbMV0gLSB5YlswXSkpO1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LmZpbGxTdHlsZSA9ICdyZ2JhKCcgKyBjLmpvaW4oJywnKSArICcpJztcblxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LmZpbGxSZWN0KHhiWzBdICsgeEdhcExlZnQsIHliWzBdICsgeUdhcFRvcCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHhiWzFdIC0geGJbMF0gLSB4R2FwLCB5YlsxXSAtIHliWzBdIC0geUdhcCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmNvdW50ID0gTWF0aC5yb3VuZChyY291bnQgLyBwaXhjb3VudCk7XG4gICAgICAgIGdjb3VudCA9IE1hdGgucm91bmQoZ2NvdW50IC8gcGl4Y291bnQpO1xuICAgICAgICBiY291bnQgPSBNYXRoLnJvdW5kKGJjb3VudCAvIHBpeGNvdW50KTtcbiAgICAgICAgdmFyIGF2Z0NvbG9yID0gdGlueWNvbG9yKCdyZ2IoJyArIHJjb3VudCArICcsJyArIGdjb3VudCArICcsJyArIGJjb3VudCArICcpJyk7XG5cbiAgICAgICAgZ2QuX2htcGl4Y291bnQgPSAoZ2QuX2htcGl4Y291bnR8fDApICsgcGl4Y291bnQ7XG4gICAgICAgIGdkLl9obWx1bWNvdW50ID0gKGdkLl9obWx1bWNvdW50fHwwKSArIHBpeGNvdW50ICogYXZnQ29sb3IuZ2V0THVtaW5hbmNlKCk7XG5cbiAgICAgICAgdmFyIGltYWdlMyA9IHBsb3RHcm91cC5zZWxlY3RBbGwoJ2ltYWdlJylcbiAgICAgICAgICAgIC5kYXRhKGNkKTtcblxuICAgICAgICBpbWFnZTMuZW50ZXIoKS5hcHBlbmQoJ3N2ZzppbWFnZScpLmF0dHIoe1xuICAgICAgICAgICAgeG1sbnM6IHhtbG5zTmFtZXNwYWNlcy5zdmcsXG4gICAgICAgICAgICBwcmVzZXJ2ZUFzcGVjdFJhdGlvOiAnbm9uZSdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaW1hZ2UzLmF0dHIoe1xuICAgICAgICAgICAgaGVpZ2h0OiBpbWFnZUhlaWdodCxcbiAgICAgICAgICAgIHdpZHRoOiBpbWFnZVdpZHRoLFxuICAgICAgICAgICAgeDogbGVmdCxcbiAgICAgICAgICAgIHk6IHRvcCxcbiAgICAgICAgICAgICd4bGluazpocmVmJzogY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJylcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG4vLyBnZXQgaW50ZXJwb2xhdGVkIGJpbiB2YWx1ZS4gUmV0dXJucyB7YmluMDpjbG9zZXN0IGJpbiwgZnJhYzpmcmFjdGlvbmFsIGRpc3QgdG8gbmV4dCwgYmluMTpuZXh0IGJpbn1cbmZ1bmN0aW9uIGZpbmRJbnRlcnAocGl4ZWwsIHBpeEFycmF5KSB7XG4gICAgdmFyIG1heEJpbiA9IHBpeEFycmF5Lmxlbmd0aCAtIDI7XG4gICAgdmFyIGJpbiA9IExpYi5jb25zdHJhaW4oTGliLmZpbmRCaW4ocGl4ZWwsIHBpeEFycmF5KSwgMCwgbWF4QmluKTtcbiAgICB2YXIgcGl4MCA9IHBpeEFycmF5W2Jpbl07XG4gICAgdmFyIHBpeDEgPSBwaXhBcnJheVtiaW4gKyAxXTtcbiAgICB2YXIgaW50ZXJwID0gTGliLmNvbnN0cmFpbihiaW4gKyAocGl4ZWwgLSBwaXgwKSAvIChwaXgxIC0gcGl4MCkgLSAwLjUsIDAsIG1heEJpbik7XG4gICAgdmFyIGJpbjAgPSBNYXRoLnJvdW5kKGludGVycCk7XG4gICAgdmFyIGZyYWMgPSBNYXRoLmFicyhpbnRlcnAgLSBiaW4wKTtcblxuICAgIGlmKCFpbnRlcnAgfHwgaW50ZXJwID09PSBtYXhCaW4gfHwgIWZyYWMpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGJpbjA6IGJpbjAsXG4gICAgICAgICAgICBiaW4xOiBiaW4wLFxuICAgICAgICAgICAgZnJhYzogMFxuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBiaW4wOiBiaW4wLFxuICAgICAgICBmcmFjOiBmcmFjLFxuICAgICAgICBiaW4xOiBNYXRoLnJvdW5kKGJpbjAgKyBmcmFjIC8gKGludGVycCAtIGJpbjApKVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGZpbmRJbnRlcnBGcm9tQ2VudGVycyhwaXhlbCwgY2VudGVyUGl4QXJyYXkpIHtcbiAgICB2YXIgbWF4QmluID0gY2VudGVyUGl4QXJyYXkubGVuZ3RoIC0gMTtcbiAgICB2YXIgYmluID0gTGliLmNvbnN0cmFpbihMaWIuZmluZEJpbihwaXhlbCwgY2VudGVyUGl4QXJyYXkpLCAwLCBtYXhCaW4pO1xuICAgIHZhciBwaXgwID0gY2VudGVyUGl4QXJyYXlbYmluXTtcbiAgICB2YXIgcGl4MSA9IGNlbnRlclBpeEFycmF5W2JpbiArIDFdO1xuICAgIHZhciBmcmFjID0gKChwaXhlbCAtIHBpeDApIC8gKHBpeDEgLSBwaXgwKSkgfHwgMDtcbiAgICBpZihmcmFjIDw9IDApIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGJpbjA6IGJpbixcbiAgICAgICAgICAgIGJpbjE6IGJpbixcbiAgICAgICAgICAgIGZyYWM6IDBcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYoZnJhYyA8IDAuNSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYmluMDogYmluLFxuICAgICAgICAgICAgYmluMTogYmluICsgMSxcbiAgICAgICAgICAgIGZyYWM6IGZyYWNcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYmluMDogYmluICsgMSxcbiAgICAgICAgYmluMTogYmluLFxuICAgICAgICBmcmFjOiAxIC0gZnJhY1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIHB1dENvbG9yKHBpeGVscywgcHhJbmRleCwgYykge1xuICAgIHBpeGVsc1tweEluZGV4XSA9IGNbMF07XG4gICAgcGl4ZWxzW3B4SW5kZXggKyAxXSA9IGNbMV07XG4gICAgcGl4ZWxzW3B4SW5kZXggKyAyXSA9IGNbMl07XG4gICAgcGl4ZWxzW3B4SW5kZXggKyAzXSA9IE1hdGgucm91bmQoY1szXSAqIDI1NSk7XG59XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlXCI6NjA1LFwiLi4vLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXNcIjo2OTYsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcImQzXCI6MTYzLFwidGlueWNvbG9yMlwiOjUzN31dLDEwMTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3R5bGUoZ2QpIHtcbiAgICBkMy5zZWxlY3QoZ2QpLnNlbGVjdEFsbCgnLmhtIGltYWdlJylcbiAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQudHJhY2Uub3BhY2l0eTtcbiAgICAgICAgfSk7XG59O1xuXG59LHtcImQzXCI6MTYzfV0sMTAxNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UpIHtcbiAgICB2YXIgenNtb290aCA9IGNvZXJjZSgnenNtb290aCcpO1xuICAgIGlmKHpzbW9vdGggPT09IGZhbHNlKSB7XG4gICAgICAgIC8vIGVuc3VyZSB0aGF0IHhnYXAgYW5kIHlnYXAgYXJlIGNvZXJjZWQgb25seSB3aGVuIHpzbW9vdGggYWxsb3dzIHRoZW0gdG8gaGF2ZSBhbiBlZmZlY3QuXG4gICAgICAgIGNvZXJjZSgneGdhcCcpO1xuICAgICAgICBjb2VyY2UoJ3lnYXAnKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3pob3ZlcmZvcm1hdCcpO1xufTtcblxufSx7fV0sMTAxNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZVhZWkRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCwgeE5hbWUsIHlOYW1lKSB7XG4gICAgdmFyIHogPSBjb2VyY2UoJ3onKTtcbiAgICB4TmFtZSA9IHhOYW1lIHx8ICd4JztcbiAgICB5TmFtZSA9IHlOYW1lIHx8ICd5JztcbiAgICB2YXIgeCwgeTtcblxuICAgIGlmKHogPT09IHVuZGVmaW5lZCB8fCAhei5sZW5ndGgpIHJldHVybiAwO1xuXG4gICAgaWYoTGliLmlzQXJyYXkxRCh0cmFjZUluLnopKSB7XG4gICAgICAgIHggPSBjb2VyY2UoeE5hbWUpO1xuICAgICAgICB5ID0gY29lcmNlKHlOYW1lKTtcblxuICAgICAgICB2YXIgeGxlbiA9IExpYi5taW5Sb3dMZW5ndGgoeCk7XG4gICAgICAgIHZhciB5bGVuID0gTGliLm1pblJvd0xlbmd0aCh5KTtcblxuICAgICAgICAvLyBjb2x1bW4geiBtdXN0IGJlIGFjY29tcGFuaWVkIGJ5IHhOYW1lIGFuZCB5TmFtZSBhcnJheXNcbiAgICAgICAgaWYoeGxlbiA9PT0gMCB8fCB5bGVuID09PSAwKSByZXR1cm4gMDtcblxuICAgICAgICB0cmFjZU91dC5fbGVuZ3RoID0gTWF0aC5taW4oeGxlbiwgeWxlbiwgei5sZW5ndGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHggPSBjb29yZERlZmF1bHRzKHhOYW1lLCBjb2VyY2UpO1xuICAgICAgICB5ID0gY29vcmREZWZhdWx0cyh5TmFtZSwgY29lcmNlKTtcblxuICAgICAgICAvLyBUT0RPIHB1dCB6IHZhbGlkYXRpb24gZWxzZXdoZXJlXG4gICAgICAgIGlmKCFpc1ZhbGlkWih6KSkgcmV0dXJuIDA7XG5cbiAgICAgICAgY29lcmNlKCd0cmFuc3Bvc2UnKTtcblxuICAgICAgICB0cmFjZU91dC5fbGVuZ3RoID0gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2hhbmRsZVRyYWNlRGVmYXVsdHMnKTtcbiAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBbeE5hbWUsIHlOYW1lXSwgbGF5b3V0KTtcblxuICAgIHJldHVybiB0cnVlO1xufTtcblxuZnVuY3Rpb24gY29vcmREZWZhdWx0cyhjb29yZFN0ciwgY29lcmNlKSB7XG4gICAgdmFyIGNvb3JkID0gY29lcmNlKGNvb3JkU3RyKTtcbiAgICB2YXIgY29vcmRUeXBlID0gY29vcmQgPyBjb2VyY2UoY29vcmRTdHIgKyAndHlwZScsICdhcnJheScpIDogJ3NjYWxlZCc7XG5cbiAgICBpZihjb29yZFR5cGUgPT09ICdzY2FsZWQnKSB7XG4gICAgICAgIGNvZXJjZShjb29yZFN0ciArICcwJyk7XG4gICAgICAgIGNvZXJjZSgnZCcgKyBjb29yZFN0cik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvb3JkO1xufVxuXG5mdW5jdGlvbiBpc1ZhbGlkWih6KSB7XG4gICAgdmFyIGFsbFJvd3NBcmVBcnJheXMgPSB0cnVlO1xuICAgIHZhciBvbmVSb3dJc0ZpbGxlZCA9IGZhbHNlO1xuICAgIHZhciBoYXNPbmVOdW1iZXIgPSBmYWxzZTtcbiAgICB2YXIgemk7XG5cbiAgICAvKlxuICAgICAqIFdpdGhvdXQgdGhpcyBzdGVwOlxuICAgICAqXG4gICAgICogaGFzT25lTnVtYmVyID0gZmFsc2UgYnJlYWtzIGNvbnRvdXIgYnV0IG5vdCBoZWF0bWFwXG4gICAgICogYWxsUm93c0FyZUFycmF5cyA9IGZhbHNlIGJyZWFrcyBjb250b3VyIGJ1dCBub3QgaGVhdG1hcFxuICAgICAqIG9uZVJvd0lzRmlsbGVkID0gZmFsc2UgYnJlYWtzIGJvdGhcbiAgICAgKi9cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB6Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHppID0geltpXTtcbiAgICAgICAgaWYoIUxpYi5pc0FycmF5T3JUeXBlZEFycmF5KHppKSkge1xuICAgICAgICAgICAgYWxsUm93c0FyZUFycmF5cyA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYoemkubGVuZ3RoID4gMCkgb25lUm93SXNGaWxsZWQgPSB0cnVlO1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgemkubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKGlzTnVtZXJpYyh6aVtqXSkpIHtcbiAgICAgICAgICAgICAgICBoYXNPbmVOdW1iZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIChhbGxSb3dzQXJlQXJyYXlzICYmIG9uZVJvd0lzRmlsbGVkICYmIGhhc09uZU51bWJlcik7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDEwMTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVhdG1hcEF0dHJzID0gX2RlcmVxXygnLi4vaGVhdG1hcC9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JTY2FsZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBvdmVycmlkZUFsbCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXMnKS5vdmVycmlkZUFsbDtcblxudmFyIGNvbW1vbkxpc3QgPSBbXG4gICAgJ3onLFxuICAgICd4JywgJ3gwJywgJ2R4JyxcbiAgICAneScsICd5MCcsICdkeScsXG4gICAgJ3RleHQnLCAndHJhbnNwb3NlJyxcbiAgICAneHR5cGUnLCAneXR5cGUnXG5dO1xuXG52YXIgYXR0cnMgPSB7fTtcblxuZm9yKHZhciBpID0gMDsgaSA8IGNvbW1vbkxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgayA9IGNvbW1vbkxpc3RbaV07XG4gICAgYXR0cnNba10gPSBoZWF0bWFwQXR0cnNba107XG59XG5cbmV4dGVuZEZsYXQoXG4gICAgYXR0cnMsXG4gICAgY29sb3JTY2FsZUF0dHJzKCcnLCB7Y0xldHRlcjogJ3onLCBhdXRvQ29sb3JEZmx0OiBmYWxzZX0pXG4pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKGF0dHJzLCAnY2FsYycsICduZXN0ZWQnKTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vaGVhdG1hcC9hdHRyaWJ1dGVzXCI6MTAwMX1dLDEwMTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVIZWF0bWFwMkQgPSBfZGVyZXFfKCdnbC1oZWF0bWFwMmQnKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBzdHIyUkdCQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3RyMnJnYmFycmF5Jyk7XG5cblxuZnVuY3Rpb24gSGVhdG1hcChzY2VuZSwgdWlkKSB7XG4gICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIHRoaXMudWlkID0gdWlkO1xuICAgIHRoaXMudHlwZSA9ICdoZWF0bWFwZ2wnO1xuXG4gICAgdGhpcy5uYW1lID0gJyc7XG4gICAgdGhpcy5ob3ZlcmluZm8gPSAnYWxsJztcblxuICAgIHRoaXMueERhdGEgPSBbXTtcbiAgICB0aGlzLnlEYXRhID0gW107XG4gICAgdGhpcy56RGF0YSA9IFtdO1xuICAgIHRoaXMudGV4dExhYmVscyA9IFtdO1xuXG4gICAgdGhpcy5pZFRvSW5kZXggPSBbXTtcbiAgICB0aGlzLmJvdW5kcyA9IFswLCAwLCAwLCAwXTtcblxuICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgejogW10sXG4gICAgICAgIHg6IFtdLFxuICAgICAgICB5OiBbXSxcbiAgICAgICAgc2hhcGU6IFswLCAwXSxcbiAgICAgICAgY29sb3JMZXZlbHM6IFswXSxcbiAgICAgICAgY29sb3JWYWx1ZXM6IFswLCAwLCAwLCAxXVxuICAgIH07XG5cbiAgICB0aGlzLmhlYXRtYXAgPSBjcmVhdGVIZWF0bWFwMkQoc2NlbmUuZ2xwbG90LCB0aGlzLm9wdGlvbnMpO1xuICAgIHRoaXMuaGVhdG1hcC5fdHJhY2UgPSB0aGlzO1xufVxuXG52YXIgcHJvdG8gPSBIZWF0bWFwLnByb3RvdHlwZTtcblxucHJvdG8uaGFuZGxlUGljayA9IGZ1bmN0aW9uKHBpY2tSZXN1bHQpIHtcbiAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICB2YXIgc2hhcGUgPSBvcHRpb25zLnNoYXBlO1xuICAgIHZhciBpbmRleCA9IHBpY2tSZXN1bHQucG9pbnRJZDtcbiAgICB2YXIgeEluZGV4ID0gaW5kZXggJSBzaGFwZVswXTtcbiAgICB2YXIgeUluZGV4ID0gTWF0aC5mbG9vcihpbmRleCAvIHNoYXBlWzBdKTtcbiAgICB2YXIgekluZGV4ID0gaW5kZXg7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB0cmFjZTogdGhpcyxcbiAgICAgICAgZGF0YUNvb3JkOiBwaWNrUmVzdWx0LmRhdGFDb29yZCxcbiAgICAgICAgdHJhY2VDb29yZDogW1xuICAgICAgICAgICAgb3B0aW9ucy54W3hJbmRleF0sXG4gICAgICAgICAgICBvcHRpb25zLnlbeUluZGV4XSxcbiAgICAgICAgICAgIG9wdGlvbnMuelt6SW5kZXhdXG4gICAgICAgIF0sXG4gICAgICAgIHRleHRMYWJlbDogdGhpcy50ZXh0TGFiZWxzW2luZGV4XSxcbiAgICAgICAgbmFtZTogdGhpcy5uYW1lLFxuICAgICAgICBwb2ludEluZGV4OiBbeUluZGV4LCB4SW5kZXhdLFxuICAgICAgICBob3ZlcmluZm86IHRoaXMuaG92ZXJpbmZvXG4gICAgfTtcbn07XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGZ1bGxUcmFjZSwgY2FsY1RyYWNlKSB7XG4gICAgdmFyIGNhbGNQdCA9IGNhbGNUcmFjZVswXTtcblxuICAgIHRoaXMuaW5kZXggPSBmdWxsVHJhY2UuaW5kZXg7XG4gICAgdGhpcy5uYW1lID0gZnVsbFRyYWNlLm5hbWU7XG4gICAgdGhpcy5ob3ZlcmluZm8gPSBmdWxsVHJhY2UuaG92ZXJpbmZvO1xuXG4gICAgLy8gY29udmVydCB6IGZyb20gMkQgLT4gMURcbiAgICB2YXIgeiA9IGNhbGNQdC56O1xuICAgIHRoaXMub3B0aW9ucy56ID0gW10uY29uY2F0LmFwcGx5KFtdLCB6KTtcblxuICAgIHZhciByb3dMZW4gPSB6WzBdLmxlbmd0aDtcbiAgICB2YXIgY29sTGVuID0gei5sZW5ndGg7XG4gICAgdGhpcy5vcHRpb25zLnNoYXBlID0gW3Jvd0xlbiwgY29sTGVuXTtcblxuICAgIHRoaXMub3B0aW9ucy54ID0gY2FsY1B0Lng7XG4gICAgdGhpcy5vcHRpb25zLnkgPSBjYWxjUHQueTtcblxuICAgIHZhciBjb2xvck9wdGlvbnMgPSBjb252ZXJ0Q29sb3JzY2FsZShmdWxsVHJhY2UpO1xuICAgIHRoaXMub3B0aW9ucy5jb2xvckxldmVscyA9IGNvbG9yT3B0aW9ucy5jb2xvckxldmVscztcbiAgICB0aGlzLm9wdGlvbnMuY29sb3JWYWx1ZXMgPSBjb2xvck9wdGlvbnMuY29sb3JWYWx1ZXM7XG5cbiAgICAvLyBjb252ZXJ0IHRleHQgZnJvbSAyRCAtPiAxRFxuICAgIHRoaXMudGV4dExhYmVscyA9IFtdLmNvbmNhdC5hcHBseShbXSwgZnVsbFRyYWNlLnRleHQpO1xuXG4gICAgdGhpcy5oZWF0bWFwLnVwZGF0ZSh0aGlzLm9wdGlvbnMpO1xuXG4gICAgdmFyIHhhID0gdGhpcy5zY2VuZS54YXhpcztcbiAgICB2YXIgeWEgPSB0aGlzLnNjZW5lLnlheGlzO1xuICAgIGZ1bGxUcmFjZS5fZXh0cmVtZXNbeGEuX2lkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKHhhLCBjYWxjUHQueCk7XG4gICAgZnVsbFRyYWNlLl9leHRyZW1lc1t5YS5faWRdID0gQXhlcy5maW5kRXh0cmVtZXMoeWEsIGNhbGNQdC55KTtcbn07XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLmhlYXRtYXAuZGlzcG9zZSgpO1xufTtcblxuZnVuY3Rpb24gY29udmVydENvbG9yc2NhbGUoZnVsbFRyYWNlKSB7XG4gICAgdmFyIHNjbCA9IGZ1bGxUcmFjZS5jb2xvcnNjYWxlO1xuICAgIHZhciB6bWluID0gZnVsbFRyYWNlLnptaW47XG4gICAgdmFyIHptYXggPSBmdWxsVHJhY2Uuem1heDtcblxuICAgIHZhciBOID0gc2NsLmxlbmd0aDtcbiAgICB2YXIgZG9tYWluID0gbmV3IEFycmF5KE4pO1xuICAgIHZhciByYW5nZSA9IG5ldyBBcnJheSg0ICogTik7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgTjsgaSsrKSB7XG4gICAgICAgIHZhciBzaSA9IHNjbFtpXTtcbiAgICAgICAgdmFyIGNvbG9yID0gc3RyMlJHQkFycmF5KHNpWzFdKTtcblxuICAgICAgICBkb21haW5baV0gPSB6bWluICsgc2lbMF0gKiAoem1heCAtIHptaW4pO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCA0OyBqKyspIHtcbiAgICAgICAgICAgIHJhbmdlWyg0ICogaSkgKyBqXSA9IGNvbG9yW2pdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29sb3JMZXZlbHM6IGRvbWFpbixcbiAgICAgICAgY29sb3JWYWx1ZXM6IHJhbmdlXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlSGVhdG1hcChzY2VuZSwgZnVsbFRyYWNlLCBjYWxjVHJhY2UpIHtcbiAgICB2YXIgcGxvdCA9IG5ldyBIZWF0bWFwKHNjZW5lLCBmdWxsVHJhY2UudWlkKTtcbiAgICBwbG90LnVwZGF0ZShmdWxsVHJhY2UsIGNhbGNUcmFjZSk7XG4gICAgcmV0dXJuIHBsb3Q7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlSGVhdG1hcDtcblxufSx7XCIuLi8uLi9saWIvc3RyMnJnYmFycmF5XCI6NzQyLFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCJnbC1oZWF0bWFwMmRcIjoyNTF9XSwxMDE4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4uL2hlYXRtYXAvZGVmYXVsdHMnKSxcbiAgICBjb2xvcmJhcjogX2RlcmVxXygnLi4vaGVhdG1hcC9jb2xvcmJhcicpLFxuXG4gICAgY2FsYzogX2RlcmVxXygnLi4vaGVhdG1hcC9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9jb252ZXJ0JyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdoZWF0bWFwZ2wnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9nbDJkJyksXG4gICAgY2F0ZWdvcmllczogWydnbCcsICdnbDJkJywgJzJkTWFwJ10sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2dsMmRcIjo4MDUsXCIuLi9oZWF0bWFwL2NhbGNcIjoxMDAyLFwiLi4vaGVhdG1hcC9jb2xvcmJhclwiOjEwMDQsXCIuLi9oZWF0bWFwL2RlZmF1bHRzXCI6MTAwNixcIi4vYXR0cmlidXRlc1wiOjEwMTYsXCIuL2NvbnZlcnRcIjoxMDE3fV0sMTAxOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBiYXJBdHRycyA9IF9kZXJlcV8oJy4uL2Jhci9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBtYWtlQmluQXR0cnMgPSBfZGVyZXFfKCcuL2Jpbl9hdHRyaWJ1dGVzJyk7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGV4dDogZXh0ZW5kRmxhdCh7fSwgYmFyQXR0cnMudGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcnRleHQ6IGV4dGVuZEZsYXQoe30sIGJhckF0dHJzLmhvdmVydGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBvcmllbnRhdGlvbjogYmFyQXR0cnMub3JpZW50YXRpb24sXG5cbiAgICBoaXN0ZnVuYzoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydjb3VudCcsICdzdW0nLCAnYXZnJywgJ21pbicsICdtYXgnXSxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICdjb3VudCcsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaGlzdG5vcm06IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnJywgJ3BlcmNlbnQnLCAncHJvYmFiaWxpdHknLCAnZGVuc2l0eScsICdwcm9iYWJpbGl0eSBkZW5zaXR5J10sXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGN1bXVsYXRpdmU6IHtcbiAgICAgICAgZW5hYmxlZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBkaXJlY3Rpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydpbmNyZWFzaW5nJywgJ2RlY3JlYXNpbmcnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdpbmNyZWFzaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGN1cnJlbnRiaW46IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydpbmNsdWRlJywgJ2V4Y2x1ZGUnLCAnaGFsZiddLFxuICAgICAgICAgICAgZGZsdDogJ2luY2x1ZGUnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgIG5iaW5zeDoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGJpbnM6IG1ha2VCaW5BdHRycygneCcsIHRydWUpLFxuXG4gICAgbmJpbnN5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5YmluczogbWFrZUJpbkF0dHJzKCd5JywgdHJ1ZSksXG4gICAgYXV0b2Jpbng6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBhdXRvYmlueToge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgYmluZ3JvdXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycyh7fSwge1xuICAgICAgICBrZXlzOiBjb25zdGFudHMuZXZlbnREYXRhS2V5c1xuICAgIH0pLFxuXG4gICAgbWFya2VyOiBiYXJBdHRycy5tYXJrZXIsXG5cbiAgICBvZmZzZXRncm91cDogYmFyQXR0cnMub2Zmc2V0Z3JvdXAsXG4gICAgYWxpZ25tZW50Z3JvdXA6IGJhckF0dHJzLmFsaWdubWVudGdyb3VwLFxuXG4gICAgc2VsZWN0ZWQ6IGJhckF0dHJzLnNlbGVjdGVkLFxuICAgIHVuc2VsZWN0ZWQ6IGJhckF0dHJzLnVuc2VsZWN0ZWQsXG5cbiAgICBfZGVwcmVjYXRlZDoge1xuICAgICAgICBiYXJkaXI6IGJhckF0dHJzLl9kZXByZWNhdGVkLmJhcmRpclxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXNcIjo2MzEsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vYmFyL2F0dHJpYnV0ZXNcIjo4NTcsXCIuL2Jpbl9hdHRyaWJ1dGVzXCI6MTAyMSxcIi4vY29uc3RhbnRzXCI6MTAyNX1dLDEwMjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkb0F2ZyhzaXplLCBjb3VudHMpIHtcbiAgICB2YXIgbk1heCA9IHNpemUubGVuZ3RoO1xuICAgIHZhciB0b3RhbCA9IDA7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG5NYXg7IGkrKykge1xuICAgICAgICBpZihjb3VudHNbaV0pIHtcbiAgICAgICAgICAgIHNpemVbaV0gLz0gY291bnRzW2ldO1xuICAgICAgICAgICAgdG90YWwgKz0gc2l6ZVtpXTtcbiAgICAgICAgfSBlbHNlIHNpemVbaV0gPSBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gdG90YWw7XG59O1xuXG59LHt9XSwxMDIxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBtYWtlQmluQXR0cnMoYXhMZXR0ZXIsIG1hdGNoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdhbnknLCAvLyBmb3IgZGF0ZSBheGVzXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZW5kOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYW55JywgLy8gZm9yIGRhdGUgYXhlc1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNpemU6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdhbnknLCAvLyBmb3IgZGF0ZSBheGVzXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH07XG59O1xuXG59LHt9XSwxMDIyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjb3VudDogZnVuY3Rpb24obiwgaSwgc2l6ZSkge1xuICAgICAgICBzaXplW25dKys7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH0sXG5cbiAgICBzdW06IGZ1bmN0aW9uKG4sIGksIHNpemUsIGNvdW50ZXJEYXRhKSB7XG4gICAgICAgIHZhciB2ID0gY291bnRlckRhdGFbaV07XG4gICAgICAgIGlmKGlzTnVtZXJpYyh2KSkge1xuICAgICAgICAgICAgdiA9IE51bWJlcih2KTtcbiAgICAgICAgICAgIHNpemVbbl0gKz0gdjtcbiAgICAgICAgICAgIHJldHVybiB2O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgIH0sXG5cbiAgICBhdmc6IGZ1bmN0aW9uKG4sIGksIHNpemUsIGNvdW50ZXJEYXRhLCBjb3VudHMpIHtcbiAgICAgICAgdmFyIHYgPSBjb3VudGVyRGF0YVtpXTtcbiAgICAgICAgaWYoaXNOdW1lcmljKHYpKSB7XG4gICAgICAgICAgICB2ID0gTnVtYmVyKHYpO1xuICAgICAgICAgICAgc2l6ZVtuXSArPSB2O1xuICAgICAgICAgICAgY291bnRzW25dKys7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfSxcblxuICAgIG1pbjogZnVuY3Rpb24obiwgaSwgc2l6ZSwgY291bnRlckRhdGEpIHtcbiAgICAgICAgdmFyIHYgPSBjb3VudGVyRGF0YVtpXTtcbiAgICAgICAgaWYoaXNOdW1lcmljKHYpKSB7XG4gICAgICAgICAgICB2ID0gTnVtYmVyKHYpO1xuICAgICAgICAgICAgaWYoIWlzTnVtZXJpYyhzaXplW25dKSkge1xuICAgICAgICAgICAgICAgIHNpemVbbl0gPSB2O1xuICAgICAgICAgICAgICAgIHJldHVybiB2O1xuICAgICAgICAgICAgfSBlbHNlIGlmKHNpemVbbl0gPiB2KSB7XG4gICAgICAgICAgICAgICAgdmFyIGRlbHRhID0gdiAtIHNpemVbbl07XG4gICAgICAgICAgICAgICAgc2l6ZVtuXSA9IHY7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRlbHRhO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgIH0sXG5cbiAgICBtYXg6IGZ1bmN0aW9uKG4sIGksIHNpemUsIGNvdW50ZXJEYXRhKSB7XG4gICAgICAgIHZhciB2ID0gY291bnRlckRhdGFbaV07XG4gICAgICAgIGlmKGlzTnVtZXJpYyh2KSkge1xuICAgICAgICAgICAgdiA9IE51bWJlcih2KTtcbiAgICAgICAgICAgIGlmKCFpc051bWVyaWMoc2l6ZVtuXSkpIHtcbiAgICAgICAgICAgICAgICBzaXplW25dID0gdjtcbiAgICAgICAgICAgICAgICByZXR1cm4gdjtcbiAgICAgICAgICAgIH0gZWxzZSBpZihzaXplW25dIDwgdikge1xuICAgICAgICAgICAgICAgIHZhciBkZWx0YSA9IHYgLSBzaXplW25dO1xuICAgICAgICAgICAgICAgIHNpemVbbl0gPSB2O1xuICAgICAgICAgICAgICAgIHJldHVybiBkZWx0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG59O1xuXG59LHtcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sMTAyMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIG51bUNvbnN0YW50cyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKTtcbnZhciBvbmVZZWFyID0gbnVtQ29uc3RhbnRzLk9ORUFWR1lFQVI7XG52YXIgb25lTW9udGggPSBudW1Db25zdGFudHMuT05FQVZHTU9OVEg7XG52YXIgb25lRGF5ID0gbnVtQ29uc3RhbnRzLk9ORURBWTtcbnZhciBvbmVIb3VyID0gbnVtQ29uc3RhbnRzLk9ORUhPVVI7XG52YXIgb25lTWluID0gbnVtQ29uc3RhbnRzLk9ORU1JTjtcbnZhciBvbmVTZWMgPSBudW1Db25zdGFudHMuT05FU0VDO1xudmFyIHRpY2tJbmNyZW1lbnQgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpLnRpY2tJbmNyZW1lbnQ7XG5cblxuLypcbiAqIG1ha2UgYSBmdW5jdGlvbiB0aGF0IHdpbGwgZmluZCByb3VuZGVkIGJpbiBlZGdlc1xuICogQHBhcmFtIHtudW1iZXJ9IGxlZnRHYXA6IGhvdyBmYXIgZnJvbSB0aGUgbGVmdCBlZGdlIG9mIGFueSBiaW4gaXMgdGhlIGNsb3Nlc3QgZGF0YSB2YWx1ZT9cbiAqIEBwYXJhbSB7bnVtYmVyfSByaWdodEdhcDogaG93IGZhciBmcm9tIHRoZSByaWdodCBlZGdlIG9mIGFueSBiaW4gaXMgdGhlIGNsb3Nlc3QgZGF0YSB2YWx1ZT9cbiAqIEBwYXJhbSB7QXJyYXlbbnVtYmVyXX0gYmluRWRnZXM6IHRoZSBhY3R1YWwgZWRnZSB2YWx1ZXMgdXNlZCBpbiBiaW5uaW5nXG4gKiBAcGFyYW0ge29iamVjdH0gcGE6IHRoZSBwb3NpdGlvbiBheGlzXG4gKiBAcGFyYW0ge3N0cmluZ30gY2FsZW5kYXI6IHRoZSBkYXRhIGNhbGVuZGFyXG4gKlxuICogQHJldHVybiB7ZnVuY3Rpb24odiwgaXNSaWdodEVkZ2UpfTpcbiAqICAgZmluZCB0aGUgc3RhcnQgKGlzUmlnaHRFZGdlIGlzIGZhbHN5KSBvciBlbmQgKHRydXRoeSkgbGFiZWwgdmFsdWUgZm9yIGEgYmluIGVkZ2UgYHZgXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0QmluU3BhbkxhYmVsUm91bmQobGVmdEdhcCwgcmlnaHRHYXAsIGJpbkVkZ2VzLCBwYSwgY2FsZW5kYXIpIHtcbiAgICAvLyB0aGUgcm91bmRpbmcgZGlnaXQgaXMgdGhlIGxhcmdlc3QgZGlnaXQgdGhhdCBjaGFuZ2VzIGluICphbGwqIG9mIDQgcmVnaW9uczpcbiAgICAvLyAtIGluc2lkZSB0aGUgcmlnaHRHYXAgYmVmb3JlIGJpbkVkZ2VzWzBdIChzaGlmdGVkIDEwJSB0byB0aGUgbGVmdClcbiAgICAvLyAtIGluc2lkZSB0aGUgbGVmdEdhcCBhZnRlciBiaW5FZGdlc1swXSAoZXhwYW5kZWQgYnkgMTAlIG9mIHJpZ2h0R2FwIG9uIGVhY2ggZW5kKVxuICAgIC8vIC0gc2FtZSBmb3IgYmluRWRnZXNbMV1cbiAgICB2YXIgZHYwID0gLTEuMSAqIHJpZ2h0R2FwO1xuICAgIHZhciBkdjEgPSAtMC4xICogcmlnaHRHYXA7XG4gICAgdmFyIGR2MiA9IGxlZnRHYXAgLSBkdjE7XG4gICAgdmFyIGVkZ2UwID0gYmluRWRnZXNbMF07XG4gICAgdmFyIGVkZ2UxID0gYmluRWRnZXNbMV07XG4gICAgdmFyIGxlZnREaWdpdCA9IE1hdGgubWluKFxuICAgICAgICBiaWdnZXN0RGlnaXRDaGFuZ2VkKGVkZ2UwICsgZHYxLCBlZGdlMCArIGR2MiwgcGEsIGNhbGVuZGFyKSxcbiAgICAgICAgYmlnZ2VzdERpZ2l0Q2hhbmdlZChlZGdlMSArIGR2MSwgZWRnZTEgKyBkdjIsIHBhLCBjYWxlbmRhcilcbiAgICApO1xuICAgIHZhciByaWdodERpZ2l0ID0gTWF0aC5taW4oXG4gICAgICAgIGJpZ2dlc3REaWdpdENoYW5nZWQoZWRnZTAgKyBkdjAsIGVkZ2UwICsgZHYxLCBwYSwgY2FsZW5kYXIpLFxuICAgICAgICBiaWdnZXN0RGlnaXRDaGFuZ2VkKGVkZ2UxICsgZHYwLCBlZGdlMSArIGR2MSwgcGEsIGNhbGVuZGFyKVxuICAgICk7XG5cbiAgICAvLyBub3JtYWxseSB3ZSB0cnkgdG8gbWFrZSB0aGUgbGFiZWwgZm9yIHRoZSByaWdodCBlZGdlIGRpZmZlcmVudCBmcm9tXG4gICAgLy8gdGhlIGxlZnQgZWRnZSBsYWJlbCwgc28gaXQncyB1bmFtYmlndW91cyB3aGljaCBiaW4gZ2V0cyBkYXRhIG9uIHRoZSBlZGdlLlxuICAgIC8vIGJ1dCBpZiB0aGlzIHJlc3VsdHMgaW4gbW9yZSB0aGFuIDMgZXh0cmEgZGlnaXRzIChvciBmb3IgZGF0ZXMsIG1vcmUgdGhhblxuICAgIC8vIDIgZmllbGRzIGllIGhyJm1pbiBvciBtaW4mc2VjLCB3aGljaCBpcyAzNjAweCksIGl0J2xsIGJlIG1vcmUgY2x1dHRlciB0aGFuXG4gICAgLy8gdXNlZnVsIHNvIGtlZXAgdGhlIGxhYmVsIGNsZWFuZXIgaW5zdGVhZFxuICAgIHZhciBkaWdpdCwgZGlzYW1iaWd1YXRlRWRnZXM7XG4gICAgaWYobGVmdERpZ2l0ID4gcmlnaHREaWdpdCAmJiByaWdodERpZ2l0IDwgTWF0aC5hYnMoZWRnZTEgLSBlZGdlMCkgLyA0MDAwKSB7XG4gICAgICAgIGRpZ2l0ID0gbGVmdERpZ2l0O1xuICAgICAgICBkaXNhbWJpZ3VhdGVFZGdlcyA9IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRpZ2l0ID0gTWF0aC5taW4obGVmdERpZ2l0LCByaWdodERpZ2l0KTtcbiAgICAgICAgZGlzYW1iaWd1YXRlRWRnZXMgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmKHBhLnR5cGUgPT09ICdkYXRlJyAmJiBkaWdpdCA+IG9uZURheSkge1xuICAgICAgICB2YXIgZGFzaEV4Y2x1ZGUgPSAoZGlnaXQgPT09IG9uZVllYXIpID8gMSA6IDY7XG4gICAgICAgIHZhciBpbmNyZW1lbnQgPSAoZGlnaXQgPT09IG9uZVllYXIpID8gJ00xMicgOiAnTTEnO1xuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbih2LCBpc1JpZ2h0RWRnZSkge1xuICAgICAgICAgICAgdmFyIGRhdGVTdHIgPSBwYS5jMmQodiwgb25lWWVhciwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgdmFyIGRhc2hQb3MgPSBkYXRlU3RyLmluZGV4T2YoJy0nLCBkYXNoRXhjbHVkZSk7XG4gICAgICAgICAgICBpZihkYXNoUG9zID4gMCkgZGF0ZVN0ciA9IGRhdGVTdHIuc3Vic3RyKDAsIGRhc2hQb3MpO1xuICAgICAgICAgICAgdmFyIHJvdW5kZWRWID0gcGEuZDJjKGRhdGVTdHIsIDAsIGNhbGVuZGFyKTtcblxuICAgICAgICAgICAgaWYocm91bmRlZFYgPCB2KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5leHRWID0gdGlja0luY3JlbWVudChyb3VuZGVkViwgaW5jcmVtZW50LCBmYWxzZSwgY2FsZW5kYXIpO1xuICAgICAgICAgICAgICAgIGlmKChyb3VuZGVkViArIG5leHRWKSAvIDIgPCB2ICsgbGVmdEdhcCkgcm91bmRlZFYgPSBuZXh0VjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaXNSaWdodEVkZ2UgJiYgZGlzYW1iaWd1YXRlRWRnZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGlja0luY3JlbWVudChyb3VuZGVkViwgaW5jcmVtZW50LCB0cnVlLCBjYWxlbmRhcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByb3VuZGVkVjtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24odiwgaXNSaWdodEVkZ2UpIHtcbiAgICAgICAgdmFyIHJvdW5kZWRWID0gZGlnaXQgKiBNYXRoLnJvdW5kKHYgLyBkaWdpdCk7XG4gICAgICAgIC8vIGlmIHdlIHJvdW5kZWQgZG93biBhbmQgd2UgY291bGQgcm91bmQgdXAgYW5kIHN0aWxsIGJlIDwgbGVmdEdhcFxuICAgICAgICAvLyAob3Igd2hhdCBsZWZ0R2FwIHZhbHVlcyByb3VuZCB0byksIGRvIHRoYXRcbiAgICAgICAgaWYocm91bmRlZFYgKyAoZGlnaXQgLyAxMCkgPCB2ICYmIHJvdW5kZWRWICsgKGRpZ2l0ICogMC45KSA8IHYgKyBsZWZ0R2FwKSB7XG4gICAgICAgICAgICByb3VuZGVkViArPSBkaWdpdDtcbiAgICAgICAgfVxuICAgICAgICAvLyBmaW5hbGx5IGZvciB0aGUgcmlnaHQgZWRnZSBiYWNrIG9mZiBvbmUgZGlnaXQgLSBidXQgb25seSBpZiB3ZSBjYW4gZG8gdGhhdFxuICAgICAgICAvLyBhbmQgbm90IGNsaXAgb2ZmIGFueSBkYXRhIHRoYXQncyBwb3RlbnRpYWxseSBpbiB0aGUgYmluXG4gICAgICAgIGlmKGlzUmlnaHRFZGdlICYmIGRpc2FtYmlndWF0ZUVkZ2VzKSB7XG4gICAgICAgICAgICByb3VuZGVkViAtPSBkaWdpdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcm91bmRlZFY7XG4gICAgfTtcbn07XG5cbi8qXG4gKiBGaW5kIHRoZSBsYXJnZXN0IGRpZ2l0IHRoYXQgY2hhbmdlcyB3aXRoaW4gYSAoY2FsY2RhdGEpIHJlZ2lvbiBbdjEsIHYyXVxuICogaWYgZGF0ZXMsIFwiZGlnaXRcIiBtZWFucyBkYXRlL3RpbWUgcGFydCB3aGVuIGl0J3MgYmlnZ2VyIHRoYW4gYSBzZWNvbmRcbiAqIHJldHVybnMgdGhlIHVuaXQgdmFsdWUgdG8gcm91bmQgdG8gdGhpcyBkaWdpdCwgZWcgMC4wMSB0byByb3VuZCB0byBodW5kcmVkdGhzLCBvclxuICogMTAwIHRvIHJvdW5kIHRvIGh1bmRyZWRzLiByZXR1cm5zIG9uZU1vbnRoIG9yIG9uZVllYXIgZm9yIG1vbnRoIG9yIHllYXIgcm91bmRpbmcsXG4gKiBzbyB0aGF0IE1hdGgubWluIHdpbGwgd29yaywgcmF0aGVyIHRoYW4gJ00xJyBhbmQgJ00xMidcbiAqL1xuZnVuY3Rpb24gYmlnZ2VzdERpZ2l0Q2hhbmdlZCh2MSwgdjIsIHBhLCBjYWxlbmRhcikge1xuICAgIC8vIGFyZSB3ZSBjcm9zc2luZyB6ZXJvPyBjYW4ndCBzYXkgYW55dGhpbmcuXG4gICAgLy8gaW4gcHJpbmNpcGxlIHRoaXMgZG9lc24ndCBhcHBseSB0byBkYXRlcyBidXQgdHVybnMgb3V0IHRoaXMgZG9lc24ndCBtYXR0ZXIuXG4gICAgaWYodjEgKiB2MiA8PSAwKSByZXR1cm4gSW5maW5pdHk7XG5cbiAgICB2YXIgZHYgPSBNYXRoLmFicyh2MiAtIHYxKTtcbiAgICB2YXIgaXNEYXRlID0gcGEudHlwZSA9PT0gJ2RhdGUnO1xuICAgIHZhciBkaWdpdCA9IGJpZ2dlc3RHdWFyYW50ZWVkRGlnaXRDaGFuZ2VkKGR2LCBpc0RhdGUpO1xuICAgIC8vIHNlZSBpZiBhIGxhcmdlciBkaWdpdCBhbHNvIGNoYW5nZWRcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMTA7IGkrKykge1xuICAgICAgICAvLyBudW1iZXJzOiBuZXh0IGRpZ2l0IG5lZWRzIHRvIGJlID4xMHggYnV0IDwxMDB4IHRoZW4gZ2V0cyByb3VuZGVkIGRvd24uXG4gICAgICAgIC8vIGRhdGVzOiBuZXh0IGRpZ2l0IGNhbiBiZSBhcyBtdWNoIGFzIDYweCAodGhlbiByb3VuZGVkIGRvd24pXG4gICAgICAgIHZhciBuZXh0RGlnaXQgPSBiaWdnZXN0R3VhcmFudGVlZERpZ2l0Q2hhbmdlZChkaWdpdCAqIDgwLCBpc0RhdGUpO1xuICAgICAgICAvLyBpZiB3ZSBnZXQgdG8geWVhcnMsIHRoZSBjaGFpbiBzdG9wc1xuICAgICAgICBpZihkaWdpdCA9PT0gbmV4dERpZ2l0KSBicmVhaztcbiAgICAgICAgaWYoZGlkRGlnaXRDaGFuZ2UobmV4dERpZ2l0LCB2MSwgdjIsIGlzRGF0ZSwgcGEsIGNhbGVuZGFyKSkgZGlnaXQgPSBuZXh0RGlnaXQ7XG4gICAgICAgIGVsc2UgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiBkaWdpdDtcbn1cblxuLypcbiAqIEZpbmQgdGhlIGxhcmdlc3QgZGlnaXQgdGhhdCAqZGVmaW5pdGVseSogY2hhbmdlcyBpbiBhIHJlZ2lvbiBbdiwgdiArIGR2XSBmb3IgYW55IHZcbiAqIGZvciBub251bmlmb3JtIGRhdGUgcmVnaW9ucyAobW9udGhzL3llYXJzKSBwaWNrIHRoZSBsYXJnZXN0XG4gKi9cbmZ1bmN0aW9uIGJpZ2dlc3RHdWFyYW50ZWVkRGlnaXRDaGFuZ2VkKGR2LCBpc0RhdGUpIHtcbiAgICBpZihpc0RhdGUgJiYgZHYgPiBvbmVTZWMpIHtcbiAgICAgICAgLy8gdGhpcyBpcyBzdXBwb3NlZCB0byBiZSB0aGUgYmlnZ2VzdCAqZ3VhcmFudGVlZCogY2hhbmdlXG4gICAgICAgIC8vIHNvIGNvbXBhcmUgdG8gdGhlIGxvbmdlc3QgbW9udGggYW5kIHllYXIgYWNyb3NzIGFueSBjYWxlbmRhcixcbiAgICAgICAgLy8gYW5kIHdlJ2xsIGl0ZXJhdGUgYmFjayB1cCBsYXRlclxuICAgICAgICAvLyBub3RlOiBkb2VzIG5vdCBzdXBwb3J0IHJvdW5kaW5nIGxhcmdlciB0aGFuIG9uZSB5ZWFyLiBXZSBjb3VsZCBhZGRcbiAgICAgICAgLy8gdGhhdCBpZiBhbnlvbmUgd2FudHMgaXQsIGJ1dCBzZWVtcyB1bnVzdWFsIGFuZCBub3Qgc3RyaWN0bHkgbmVjZXNzYXJ5LlxuICAgICAgICBpZihkdiA+IG9uZURheSkge1xuICAgICAgICAgICAgaWYoZHYgPiBvbmVZZWFyICogMS4xKSByZXR1cm4gb25lWWVhcjtcbiAgICAgICAgICAgIGlmKGR2ID4gb25lTW9udGggKiAxLjEpIHJldHVybiBvbmVNb250aDtcbiAgICAgICAgICAgIHJldHVybiBvbmVEYXk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihkdiA+IG9uZUhvdXIpIHJldHVybiBvbmVIb3VyO1xuICAgICAgICBpZihkdiA+IG9uZU1pbikgcmV0dXJuIG9uZU1pbjtcbiAgICAgICAgcmV0dXJuIG9uZVNlYztcbiAgICB9XG4gICAgcmV0dXJuIE1hdGgucG93KDEwLCBNYXRoLmZsb29yKE1hdGgubG9nKGR2KSAvIE1hdGguTE4xMCkpO1xufVxuXG5mdW5jdGlvbiBkaWREaWdpdENoYW5nZShkaWdpdCwgdjEsIHYyLCBpc0RhdGUsIHBhLCBjYWxlbmRhcikge1xuICAgIGlmKGlzRGF0ZSAmJiBkaWdpdCA+IG9uZURheSkge1xuICAgICAgICB2YXIgZGF0ZVBhcnRzMSA9IGRhdGVQYXJ0cyh2MSwgcGEsIGNhbGVuZGFyKTtcbiAgICAgICAgdmFyIGRhdGVQYXJ0czIgPSBkYXRlUGFydHModjIsIHBhLCBjYWxlbmRhcik7XG4gICAgICAgIHZhciBwYXJ0aSA9IChkaWdpdCA9PT0gb25lWWVhcikgPyAwIDogMTtcbiAgICAgICAgcmV0dXJuIGRhdGVQYXJ0czFbcGFydGldICE9PSBkYXRlUGFydHMyW3BhcnRpXTtcbiAgICB9XG4gICAgcmV0dXJuIE1hdGguZmxvb3IodjIgLyBkaWdpdCkgLSBNYXRoLmZsb29yKHYxIC8gZGlnaXQpID4gMC4xO1xufVxuXG5mdW5jdGlvbiBkYXRlUGFydHModiwgcGEsIGNhbGVuZGFyKSB7XG4gICAgdmFyIHBhcnRzID0gcGEuYzJkKHYsIG9uZVllYXIsIGNhbGVuZGFyKS5zcGxpdCgnLScpO1xuICAgIGlmKHBhcnRzWzBdID09PSAnJykge1xuICAgICAgICBwYXJ0cy51bnNoaWZ0KCk7XG4gICAgICAgIHBhcnRzWzBdID0gJy0nICsgcGFydHNbMF07XG4gICAgfVxuICAgIHJldHVybiBwYXJ0cztcbn1cblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3Njd9XSwxMDI0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG5cbnZhciBhcnJheXNUb0NhbGNkYXRhID0gX2RlcmVxXygnLi4vYmFyL2FycmF5c190b19jYWxjZGF0YScpO1xudmFyIGJpbkZ1bmN0aW9ucyA9IF9kZXJlcV8oJy4vYmluX2Z1bmN0aW9ucycpO1xudmFyIG5vcm1GdW5jdGlvbnMgPSBfZGVyZXFfKCcuL25vcm1fZnVuY3Rpb25zJyk7XG52YXIgZG9BdmcgPSBfZGVyZXFfKCcuL2F2ZXJhZ2UnKTtcbnZhciBnZXRCaW5TcGFuTGFiZWxSb3VuZCA9IF9kZXJlcV8oJy4vYmluX2xhYmVsX3ZhbHMnKTtcblxuZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgcG9zID0gW107XG4gICAgdmFyIHNpemUgPSBbXTtcbiAgICB2YXIgcGEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2Uub3JpZW50YXRpb24gPT09ICdoJyA/IHRyYWNlLnlheGlzIDogdHJhY2UueGF4aXMpO1xuICAgIHZhciBtYWluRGF0YSA9IHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcgPyAneScgOiAneCc7XG4gICAgdmFyIGNvdW50ZXJEYXRhID0ge3g6ICd5JywgeTogJ3gnfVttYWluRGF0YV07XG4gICAgdmFyIGNhbGVuZGFyID0gdHJhY2VbbWFpbkRhdGEgKyAnY2FsZW5kYXInXTtcbiAgICB2YXIgY3VtdWxhdGl2ZVNwZWMgPSB0cmFjZS5jdW11bGF0aXZlO1xuICAgIHZhciBpO1xuXG4gICAgdmFyIGJpbnNBbmRQb3MgPSBjYWxjQWxsQXV0b0JpbnMoZ2QsIHRyYWNlLCBwYSwgbWFpbkRhdGEpO1xuICAgIHZhciBiaW5TcGVjID0gYmluc0FuZFBvc1swXTtcbiAgICB2YXIgcG9zMCA9IGJpbnNBbmRQb3NbMV07XG5cbiAgICB2YXIgbm9udW5pZm9ybUJpbnMgPSB0eXBlb2YgYmluU3BlYy5zaXplID09PSAnc3RyaW5nJztcbiAgICB2YXIgYmluRWRnZXMgPSBbXTtcbiAgICB2YXIgYmlucyA9IG5vbnVuaWZvcm1CaW5zID8gYmluRWRnZXMgOiBiaW5TcGVjO1xuICAgIC8vIG1ha2UgdGhlIGVtcHR5IGJpbiBhcnJheVxuICAgIHZhciBpbmMgPSBbXTtcbiAgICB2YXIgY291bnRzID0gW107XG4gICAgdmFyIGlucHV0UG9pbnRzID0gW107XG4gICAgdmFyIHRvdGFsID0gMDtcbiAgICB2YXIgbm9ybSA9IHRyYWNlLmhpc3Rub3JtO1xuICAgIHZhciBmdW5jID0gdHJhY2UuaGlzdGZ1bmM7XG4gICAgdmFyIGRlbnNpdHlOb3JtID0gbm9ybS5pbmRleE9mKCdkZW5zaXR5JykgIT09IC0xO1xuICAgIHZhciBpMiwgYmluRW5kLCBuO1xuXG4gICAgaWYoY3VtdWxhdGl2ZVNwZWMuZW5hYmxlZCAmJiBkZW5zaXR5Tm9ybSkge1xuICAgICAgICAvLyB3ZSB0cmVhdCBcImN1bXVsYXRpdmVcIiBsaWtlIGl0IG1lYW5zIFwiaW50ZWdyYWxcIiBpZiB5b3UgdXNlIGEgZGVuc2l0eSBub3JtLFxuICAgICAgICAvLyB3aGljaCBpbiB0aGUgZW5kIG1lYW5zIGl0J3MgdGhlIHNhbWUgYXMgd2l0aG91dCBcImRlbnNpdHlcIlxuICAgICAgICBub3JtID0gbm9ybS5yZXBsYWNlKC8gP2RlbnNpdHkkLywgJycpO1xuICAgICAgICBkZW5zaXR5Tm9ybSA9IGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBleHRyZW1lRnVuYyA9IGZ1bmMgPT09ICdtYXgnIHx8IGZ1bmMgPT09ICdtaW4nO1xuICAgIHZhciBzaXplSW5pdCA9IGV4dHJlbWVGdW5jID8gbnVsbCA6IDA7XG4gICAgdmFyIGJpbkZ1bmMgPSBiaW5GdW5jdGlvbnMuY291bnQ7XG4gICAgdmFyIG5vcm1GdW5jID0gbm9ybUZ1bmN0aW9uc1tub3JtXTtcbiAgICB2YXIgaXNBdmcgPSBmYWxzZTtcbiAgICB2YXIgcHIyYyA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHBhLnIyYyh2LCAwLCBjYWxlbmRhcik7IH07XG4gICAgdmFyIHJhd0NvdW50ZXJEYXRhO1xuXG4gICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkodHJhY2VbY291bnRlckRhdGFdKSAmJiBmdW5jICE9PSAnY291bnQnKSB7XG4gICAgICAgIHJhd0NvdW50ZXJEYXRhID0gdHJhY2VbY291bnRlckRhdGFdO1xuICAgICAgICBpc0F2ZyA9IGZ1bmMgPT09ICdhdmcnO1xuICAgICAgICBiaW5GdW5jID0gYmluRnVuY3Rpb25zW2Z1bmNdO1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSB0aGUgYmlucyAoYW5kIGFueSBleHRyYSBhcnJheXMgbmVlZGVkKVxuICAgIC8vIGFzc3VtZSBtb3JlIHRoYW4gMWU2IGJpbnMgaXMgYW4gZXJyb3IsIHNvIHdlIGRvbid0IGNyYXNoIHRoZSBicm93c2VyXG4gICAgaSA9IHByMmMoYmluU3BlYy5zdGFydCk7XG5cbiAgICAvLyBkZWNyZWFzZSBlbmQgYSBsaXR0bGUgaW4gY2FzZSBvZiByb3VuZGluZyBlcnJvcnNcbiAgICBiaW5FbmQgPSBwcjJjKGJpblNwZWMuZW5kKSArIChpIC0gQXhlcy50aWNrSW5jcmVtZW50KGksIGJpblNwZWMuc2l6ZSwgZmFsc2UsIGNhbGVuZGFyKSkgLyAxZTY7XG5cbiAgICB3aGlsZShpIDwgYmluRW5kICYmIHBvcy5sZW5ndGggPCAxZTYpIHtcbiAgICAgICAgaTIgPSBBeGVzLnRpY2tJbmNyZW1lbnQoaSwgYmluU3BlYy5zaXplLCBmYWxzZSwgY2FsZW5kYXIpO1xuICAgICAgICBwb3MucHVzaCgoaSArIGkyKSAvIDIpO1xuICAgICAgICBzaXplLnB1c2goc2l6ZUluaXQpO1xuICAgICAgICBpbnB1dFBvaW50cy5wdXNoKFtdKTtcbiAgICAgICAgLy8gbm9udW5pZm9ybSBiaW5zIChsaWtlIG1vbnRocykgd2UgbmVlZCB0byBzZWFyY2gsXG4gICAgICAgIC8vIHJhdGhlciB0aGFuIHN0cmFpZ2h0IGNhbGN1bGF0ZSB0aGUgYmluIHdlJ3JlIGluXG4gICAgICAgIGJpbkVkZ2VzLnB1c2goaSk7XG4gICAgICAgIC8vIG5vbnVuaWZvcm0gYmlucyBhbHNvIG5lZWQgbm9udW5pZm9ybSBub3JtYWxpemF0aW9uIGZhY3RvcnNcbiAgICAgICAgaWYoZGVuc2l0eU5vcm0pIGluYy5wdXNoKDEgLyAoaTIgLSBpKSk7XG4gICAgICAgIGlmKGlzQXZnKSBjb3VudHMucHVzaCgwKTtcbiAgICAgICAgLy8gYnJlYWsgdG8gYXZvaWQgaW5maW5pdGUgbG9vcHNcbiAgICAgICAgaWYoaTIgPD0gaSkgYnJlYWs7XG4gICAgICAgIGkgPSBpMjtcbiAgICB9XG4gICAgYmluRWRnZXMucHVzaChpKTtcblxuICAgIC8vIGZvciBkYXRlIGF4ZXMgd2UgbmVlZCBiaW4gYm91bmRzIHRvIGJlIGNhbGNkYXRhLiBGb3Igbm9udW5pZm9ybSBiaW5zXG4gICAgLy8gd2UgYWxyZWFkeSBoYXZlIHRoaXMsIGJ1dCB1bmlmb3JtIHdpdGggc3RhcnQvZW5kL3NpemUgdGhleSdyZSBzdGlsbCBzdHJpbmdzLlxuICAgIGlmKCFub251bmlmb3JtQmlucyAmJiBwYS50eXBlID09PSAnZGF0ZScpIHtcbiAgICAgICAgYmlucyA9IHtcbiAgICAgICAgICAgIHN0YXJ0OiBwcjJjKGJpbnMuc3RhcnQpLFxuICAgICAgICAgICAgZW5kOiBwcjJjKGJpbnMuZW5kKSxcbiAgICAgICAgICAgIHNpemU6IGJpbnMuc2l6ZVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIGJpbiB0aGUgZGF0YVxuICAgIC8vIGFuZCBtYWtlIGhpc3RvZ3JhbS1zcGVjaWZpYyBwdC1udW1iZXItdG8tY2QtaW5kZXggbWFwIG9iamVjdFxuICAgIHZhciBuTWF4ID0gc2l6ZS5sZW5ndGg7XG4gICAgdmFyIHVuaXF1ZVZhbHNQZXJCaW4gPSB0cnVlO1xuICAgIHZhciBsZWZ0R2FwID0gSW5maW5pdHk7XG4gICAgdmFyIHJpZ2h0R2FwID0gSW5maW5pdHk7XG4gICAgdmFyIHB0TnVtYmVyMmNkSW5kZXggPSB7fTtcbiAgICBmb3IoaSA9IDA7IGkgPCBwb3MwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwb3NpID0gcG9zMFtpXTtcbiAgICAgICAgbiA9IExpYi5maW5kQmluKHBvc2ksIGJpbnMpO1xuICAgICAgICBpZihuID49IDAgJiYgbiA8IG5NYXgpIHtcbiAgICAgICAgICAgIHRvdGFsICs9IGJpbkZ1bmMobiwgaSwgc2l6ZSwgcmF3Q291bnRlckRhdGEsIGNvdW50cyk7XG4gICAgICAgICAgICBpZih1bmlxdWVWYWxzUGVyQmluICYmIGlucHV0UG9pbnRzW25dLmxlbmd0aCAmJiBwb3NpICE9PSBwb3MwW2lucHV0UG9pbnRzW25dWzBdXSkge1xuICAgICAgICAgICAgICAgIHVuaXF1ZVZhbHNQZXJCaW4gPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlucHV0UG9pbnRzW25dLnB1c2goaSk7XG4gICAgICAgICAgICBwdE51bWJlcjJjZEluZGV4W2ldID0gbjtcblxuICAgICAgICAgICAgbGVmdEdhcCA9IE1hdGgubWluKGxlZnRHYXAsIHBvc2kgLSBiaW5FZGdlc1tuXSk7XG4gICAgICAgICAgICByaWdodEdhcCA9IE1hdGgubWluKHJpZ2h0R2FwLCBiaW5FZGdlc1tuICsgMV0gLSBwb3NpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciByb3VuZEZuO1xuICAgIGlmKCF1bmlxdWVWYWxzUGVyQmluKSB7XG4gICAgICAgIHJvdW5kRm4gPSBnZXRCaW5TcGFuTGFiZWxSb3VuZChsZWZ0R2FwLCByaWdodEdhcCwgYmluRWRnZXMsIHBhLCBjYWxlbmRhcik7XG4gICAgfVxuXG4gICAgLy8gYXZlcmFnZSBhbmQvb3Igbm9ybWFsaXplIHRoZSBkYXRhLCBpZiBuZWVkZWRcbiAgICBpZihpc0F2ZykgdG90YWwgPSBkb0F2ZyhzaXplLCBjb3VudHMpO1xuICAgIGlmKG5vcm1GdW5jKSBub3JtRnVuYyhzaXplLCB0b3RhbCwgaW5jKTtcblxuICAgIC8vIGFmdGVyIGFsbCBub3JtYWxpemF0aW9uIGV0Yywgbm93IHdlIGNhbiBhY2N1bXVsYXRlIGlmIGRlc2lyZWRcbiAgICBpZihjdW11bGF0aXZlU3BlYy5lbmFibGVkKSBjZGYoc2l6ZSwgY3VtdWxhdGl2ZVNwZWMuZGlyZWN0aW9uLCBjdW11bGF0aXZlU3BlYy5jdXJyZW50YmluKTtcblxuICAgIHZhciBzZXJpZXNMZW4gPSBNYXRoLm1pbihwb3MubGVuZ3RoLCBzaXplLmxlbmd0aCk7XG4gICAgdmFyIGNkID0gW107XG4gICAgdmFyIGZpcnN0Tm9uemVybyA9IDA7XG4gICAgdmFyIGxhc3ROb256ZXJvID0gc2VyaWVzTGVuIC0gMTtcblxuICAgIC8vIGxvb2sgZm9yIGVtcHR5IGJpbnMgYXQgdGhlIGVuZHMgdG8gcmVtb3ZlLCBzbyBhdXRvc2NhbGUgb21pdHMgdGhlbVxuICAgIGZvcihpID0gMDsgaSA8IHNlcmllc0xlbjsgaSsrKSB7XG4gICAgICAgIGlmKHNpemVbaV0pIHtcbiAgICAgICAgICAgIGZpcnN0Tm9uemVybyA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IoaSA9IHNlcmllc0xlbiAtIDE7IGkgPj0gZmlyc3ROb256ZXJvOyBpLS0pIHtcbiAgICAgICAgaWYoc2l6ZVtpXSkge1xuICAgICAgICAgICAgbGFzdE5vbnplcm8gPSBpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgdGhlIFwiY2FsY3VsYXRlZCBkYXRhXCIgdG8gcGxvdFxuICAgIGZvcihpID0gZmlyc3ROb256ZXJvOyBpIDw9IGxhc3ROb256ZXJvOyBpKyspIHtcbiAgICAgICAgaWYoKGlzTnVtZXJpYyhwb3NbaV0pICYmIGlzTnVtZXJpYyhzaXplW2ldKSkpIHtcbiAgICAgICAgICAgIHZhciBjZGkgPSB7XG4gICAgICAgICAgICAgICAgcDogcG9zW2ldLFxuICAgICAgICAgICAgICAgIHM6IHNpemVbaV0sXG4gICAgICAgICAgICAgICAgYjogMFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gc2V0dXAgaG92ZXIgYW5kIGV2ZW50IGRhdGEgZmllbGRzLFxuICAgICAgICAgICAgLy8gTi5CLiBwdHMgYW5kIFwiaG92ZXJcIiBwb3NpdGlvbnMgcGgwL3BoMSBkb24ndCBzZWVtIHRvIG1ha2UgbXVjaCBzZW5zZVxuICAgICAgICAgICAgLy8gZm9yIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uc1xuICAgICAgICAgICAgaWYoIWN1bXVsYXRpdmVTcGVjLmVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICBjZGkucHRzID0gaW5wdXRQb2ludHNbaV07XG4gICAgICAgICAgICAgICAgaWYodW5pcXVlVmFsc1BlckJpbikge1xuICAgICAgICAgICAgICAgICAgICBjZGkucGgwID0gY2RpLnBoMSA9IChpbnB1dFBvaW50c1tpXS5sZW5ndGgpID8gcG9zMFtpbnB1dFBvaW50c1tpXVswXV0gOiBwb3NbaV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2RpLnBoMCA9IHJvdW5kRm4oYmluRWRnZXNbaV0pO1xuICAgICAgICAgICAgICAgICAgICBjZGkucGgxID0gcm91bmRGbihiaW5FZGdlc1tpICsgMV0sIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNkLnB1c2goY2RpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGNkLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAvLyB3aGVuIHdlIGNvbGxhcHNlIHRvIGEgc2luZ2xlIGJpbiwgY2FsY2RhdGEgbm8gbG9uZ2VyIGRlc2NyaWJlcyBiaW4gc2l6ZVxuICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIGV4cGxpY2l0bHkgc3BlY2lmeSBpdFxuICAgICAgICBjZFswXS53aWR0aDEgPSBBeGVzLnRpY2tJbmNyZW1lbnQoY2RbMF0ucCwgYmluU3BlYy5zaXplLCBmYWxzZSwgY2FsZW5kYXIpIC0gY2RbMF0ucDtcbiAgICB9XG5cbiAgICBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSk7XG5cbiAgICBpZihMaWIuaXNBcnJheU9yVHlwZWRBcnJheSh0cmFjZS5zZWxlY3RlZHBvaW50cykpIHtcbiAgICAgICAgTGliLnRhZ1NlbGVjdGVkKGNkLCB0cmFjZSwgcHROdW1iZXIyY2RJbmRleCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNkO1xufVxuXG4vKlxuICogY2FsY0FsbEF1dG9CaW5zOiB3ZSB3YW50IGFsbCBoaXN0b2dyYW1zIGluc2lkZSB0aGUgc2FtZSBiaW5ncm91cFxuICogKHNlZSBsb2dpYyBpbiBIaXN0b2dyYW0uY3Jvc3NUcmFjZURlZmF1bHRzKSB0byBzaGFyZSBiaW4gc3BlY3NcbiAqXG4gKiBJZiB0aGUgdXNlciBoYXMgZXhwbGljaXRseSBzcGVjaWZpZWQgZGlmZmVyaW5nXG4gKiBiaW4gc3BlY3MsIHRoZXJlJ3Mgbm90aGluZyB3ZSBjYW4gZG8sIGJ1dCBpZiBwb3NzaWJsZSB3ZSB3aWxsIHRyeSB0byB1c2UgdGhlXG4gKiBzbWFsbGVzdCBiaW5zIG9mIGFueSBvZiB0aGUgYXV0byB2YWx1ZXMgZm9yIGFsbCBoaXN0b2dyYW1zIGluc2lkZSB0aGUgc2FtZVxuICogYmluZ3JvdXAuXG4gKi9cbmZ1bmN0aW9uIGNhbGNBbGxBdXRvQmlucyhnZCwgdHJhY2UsIHBhLCBtYWluRGF0YSwgX292ZXJsYXlFZGdlQ2FzZSkge1xuICAgIHZhciBiaW5BdHRyID0gbWFpbkRhdGEgKyAnYmlucyc7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgZ3JvdXBOYW1lID0gdHJhY2VbJ18nICsgbWFpbkRhdGEgKyAnYmluZ3JvdXAnXTtcbiAgICB2YXIgYmluT3B0cyA9IGZ1bGxMYXlvdXQuX2hpc3RvZ3JhbUJpbk9wdHNbZ3JvdXBOYW1lXTtcbiAgICB2YXIgaXNPdmVybGF5ID0gZnVsbExheW91dC5iYXJtb2RlID09PSAnb3ZlcmxheSc7XG4gICAgdmFyIGksIHRyYWNlcywgdHJhY2VpLCBjYWxlbmRhciwgcG9zMCwgYXV0b1ZhbHMsIGN1bXVsYXRpdmVTcGVjO1xuXG4gICAgdmFyIHIyYyA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHBhLnIyYyh2LCAwLCBjYWxlbmRhcik7IH07XG4gICAgdmFyIGMyciA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHBhLmMycih2LCAwLCBjYWxlbmRhcik7IH07XG5cbiAgICB2YXIgY2xlYW5Cb3VuZCA9IHBhLnR5cGUgPT09ICdkYXRlJyA/XG4gICAgICAgIGZ1bmN0aW9uKHYpIHsgcmV0dXJuICh2IHx8IHYgPT09IDApID8gTGliLmNsZWFuRGF0ZSh2LCBudWxsLCBjYWxlbmRhcikgOiBudWxsOyB9IDpcbiAgICAgICAgZnVuY3Rpb24odikgeyByZXR1cm4gaXNOdW1lcmljKHYpID8gTnVtYmVyKHYpIDogbnVsbDsgfTtcblxuICAgIGZ1bmN0aW9uIHNldEJvdW5kKGF0dHIsIGJpbnMsIG5ld0JpbnMpIHtcbiAgICAgICAgaWYoYmluc1thdHRyICsgJ0ZvdW5kJ10pIHtcbiAgICAgICAgICAgIGJpbnNbYXR0cl0gPSBjbGVhbkJvdW5kKGJpbnNbYXR0cl0pO1xuICAgICAgICAgICAgaWYoYmluc1thdHRyXSA9PT0gbnVsbCkgYmluc1thdHRyXSA9IG5ld0JpbnNbYXR0cl07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhdXRvVmFsc1thdHRyXSA9IGJpbnNbYXR0cl0gPSBuZXdCaW5zW2F0dHJdO1xuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlc1swXSwgYmluQXR0ciArICcuJyArIGF0dHIpLnNldChuZXdCaW5zW2F0dHJdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFsbCBidXQgdGhlIGZpcnN0IHRyYWNlIGluIHRoaXMgZ3JvdXAgaGFzIGFscmVhZHkgYmVlbiBtYXJrZWQgZmluaXNoZWRcbiAgICAvLyBjbGVhciB0aGlzIGZsYWcsIHNvIG5leHQgdGltZSB3ZSBydW4gY2FsYyB3ZSB3aWxsIHJ1biBhdXRvYmluIGFnYWluXG4gICAgaWYodHJhY2VbJ18nICsgbWFpbkRhdGEgKyAnYXV0b0JpbkZpbmlzaGVkJ10pIHtcbiAgICAgICAgZGVsZXRlIHRyYWNlWydfJyArIG1haW5EYXRhICsgJ2F1dG9CaW5GaW5pc2hlZCddO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYWNlcyA9IGJpbk9wdHMudHJhY2VzO1xuICAgICAgICB2YXIgYWxsUG9zID0gW107XG5cbiAgICAgICAgLy8gTm90ZTogd2UncmUgaW5jbHVkaW5nIGBsZWdlbmRvbmx5YCB0cmFjZXMgaGVyZSBmb3IgYXV0b2JpbiBwdXJwb3NlcyxcbiAgICAgICAgLy8gc28gdGhhdCBzaG93aW5nICYgaGlkaW5nIGZyb20gdGhlIGxlZ2VuZCB3b24ndCBhZmZlY3QgYmlucy5cbiAgICAgICAgLy8gQnV0IHRoaXMgY29tcGxpY2F0ZXMgdGhpbmdzIGEgYml0IHNpbmNlIHRob3NlIHRyYWNlcyBkb24ndCBgY2FsY2AsXG4gICAgICAgIC8vIGhlbmNlIGBpc0ZpcnN0VmlzaWJsZWAuXG4gICAgICAgIHZhciBpc0ZpcnN0VmlzaWJsZSA9IHRydWU7XG4gICAgICAgIHZhciBoYXMyZE1hcCA9IGZhbHNlO1xuICAgICAgICB2YXIgaGFzSGlzdDJkQ29udG91ciA9IGZhbHNlO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCB0cmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyYWNlaSA9IHRyYWNlc1tpXTtcblxuICAgICAgICAgICAgaWYodHJhY2VpLnZpc2libGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgbWFpbkRhdGFpID0gYmluT3B0cy5kaXJzW2ldO1xuICAgICAgICAgICAgICAgIHBvczAgPSB0cmFjZWlbJ18nICsgbWFpbkRhdGFpICsgJ3BvczAnXSA9IHBhLm1ha2VDYWxjZGF0YSh0cmFjZWksIG1haW5EYXRhaSk7XG5cbiAgICAgICAgICAgICAgICBhbGxQb3MgPSBMaWIuY29uY2F0KGFsbFBvcywgcG9zMCk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRyYWNlaVsnXycgKyBtYWluRGF0YSArICdhdXRvQmluRmluaXNoZWQnXTtcblxuICAgICAgICAgICAgICAgIGlmKHRyYWNlLnZpc2libGUgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoaXNGaXJzdFZpc2libGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzRmlyc3RWaXNpYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdHJhY2VpLl9hdXRvQmluO1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2VpWydfJyArIG1haW5EYXRhICsgJ2F1dG9CaW5GaW5pc2hlZCddID0gMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZihSZWdpc3RyeS50cmFjZUlzKHRyYWNlaSwgJzJkTWFwJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhczJkTWFwID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZih0cmFjZWkudHlwZSA9PT0gJ2hpc3RvZ3JhbTJkY29udG91cicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc0hpc3QyZENvbnRvdXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY2FsZW5kYXIgPSB0cmFjZXNbMF1bbWFpbkRhdGEgKyAnY2FsZW5kYXInXTtcbiAgICAgICAgdmFyIG5ld0JpblNwZWMgPSBBeGVzLmF1dG9CaW4oYWxsUG9zLCBwYSwgYmluT3B0cy5uYmlucywgaGFzMmRNYXAsIGNhbGVuZGFyLCBiaW5PcHRzLnNpemVGb3VuZCAmJiBiaW5PcHRzLnNpemUpO1xuXG4gICAgICAgIHZhciBhdXRvQmluID0gdHJhY2VzWzBdLl9hdXRvQmluID0ge307XG4gICAgICAgIGF1dG9WYWxzID0gYXV0b0JpbltiaW5PcHRzLmRpcnNbMF1dID0ge307XG5cbiAgICAgICAgaWYoaGFzSGlzdDJkQ29udG91cikge1xuICAgICAgICAgICAgLy8gdGhlIFwidHJ1ZVwiIDJuZCBhcmd1bWVudCByZXZlcnNlcyB0aGUgdGljayBkaXJlY3Rpb24gKHdoaWNoIHdlIGNhbid0XG4gICAgICAgICAgICAvLyBqdXN0IGRvIHdpdGggYSBtaW51cyBzaWduIGJlY2F1c2Ugb2YgbW9udGggYmlucylcbiAgICAgICAgICAgIGlmKCFiaW5PcHRzLnNpemUpIHtcbiAgICAgICAgICAgICAgICBuZXdCaW5TcGVjLnN0YXJ0ID0gYzJyKEF4ZXMudGlja0luY3JlbWVudChcbiAgICAgICAgICAgICAgICAgICAgcjJjKG5ld0JpblNwZWMuc3RhcnQpLCBuZXdCaW5TcGVjLnNpemUsIHRydWUsIGNhbGVuZGFyKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihiaW5PcHRzLmVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbmV3QmluU3BlYy5lbmQgPSBjMnIoQXhlcy50aWNrSW5jcmVtZW50KFxuICAgICAgICAgICAgICAgICAgICByMmMobmV3QmluU3BlYy5lbmQpLCBuZXdCaW5TcGVjLnNpemUsIGZhbHNlLCBjYWxlbmRhcikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gRWRnZSBjYXNlOiBzaW5nbGUtdmFsdWVkIGhpc3RvZ3JhbSBvdmVybGF5aW5nIG90aGVyc1xuICAgICAgICAvLyBVc2UgdGhlbSBhbGwgdG9nZXRoZXIgdG8gY2FsY3VsYXRlIHRoZSBiaW4gc2l6ZSBmb3IgdGhlIHNpbmdsZS12YWx1ZWQgb25lXG4gICAgICAgIGlmKGlzT3ZlcmxheSAmJiAhUmVnaXN0cnkudHJhY2VJcyh0cmFjZSwgJzJkTWFwJykgJiYgbmV3QmluU3BlYy5fZGF0YVNwYW4gPT09IDAgJiZcbiAgICAgICAgICAgIHBhLnR5cGUgIT09ICdjYXRlZ29yeScgJiYgcGEudHlwZSAhPT0gJ211bHRpY2F0ZWdvcnknKSB7XG4gICAgICAgICAgICAvLyBTZXZlcmFsIHNpbmdsZS12YWx1ZWQgaGlzdG9ncmFtcyEgU3RvcCBpbmZpbml0ZSByZWN1cnNpb24sXG4gICAgICAgICAgICAvLyBqdXN0IHJldHVybiBhbiBleHRyYSBmbGFnIHRoYXQgdGVsbHMgaGFuZGxlU2luZ2xlVmFsdWVPdmVybGF5c1xuICAgICAgICAgICAgLy8gdG8gc29ydCBvdXQgdGhpcyB0cmFjZSB0b29cbiAgICAgICAgICAgIGlmKF9vdmVybGF5RWRnZUNhc2UpIHJldHVybiBbbmV3QmluU3BlYywgcG9zMCwgdHJ1ZV07XG5cbiAgICAgICAgICAgIG5ld0JpblNwZWMgPSBoYW5kbGVTaW5nbGVWYWx1ZU92ZXJsYXlzKGdkLCB0cmFjZSwgcGEsIG1haW5EYXRhLCBiaW5BdHRyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFkanVzdCBmb3IgQ0RGIGVkZ2UgY2FzZXNcbiAgICAgICAgY3VtdWxhdGl2ZVNwZWMgPSB0cmFjZWkuY3VtdWxhdGl2ZSB8fCB7fTtcbiAgICAgICAgaWYoY3VtdWxhdGl2ZVNwZWMuZW5hYmxlZCAmJiAoY3VtdWxhdGl2ZVNwZWMuY3VycmVudGJpbiAhPT0gJ2luY2x1ZGUnKSkge1xuICAgICAgICAgICAgaWYoY3VtdWxhdGl2ZVNwZWMuZGlyZWN0aW9uID09PSAnZGVjcmVhc2luZycpIHtcbiAgICAgICAgICAgICAgICBuZXdCaW5TcGVjLnN0YXJ0ID0gYzJyKEF4ZXMudGlja0luY3JlbWVudChcbiAgICAgICAgICAgICAgICAgICAgcjJjKG5ld0JpblNwZWMuc3RhcnQpLCBuZXdCaW5TcGVjLnNpemUsIHRydWUsIGNhbGVuZGFyKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG5ld0JpblNwZWMuZW5kID0gYzJyKEF4ZXMudGlja0luY3JlbWVudChcbiAgICAgICAgICAgICAgICAgICAgcjJjKG5ld0JpblNwZWMuZW5kKSwgbmV3QmluU3BlYy5zaXplLCBmYWxzZSwgY2FsZW5kYXIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGJpbk9wdHMuc2l6ZSA9IG5ld0JpblNwZWMuc2l6ZTtcbiAgICAgICAgaWYoIWJpbk9wdHMuc2l6ZUZvdW5kKSB7XG4gICAgICAgICAgICBhdXRvVmFscy5zaXplID0gbmV3QmluU3BlYy5zaXplO1xuICAgICAgICAgICAgTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlc1swXSwgYmluQXR0ciArICcuc2l6ZScpLnNldChuZXdCaW5TcGVjLnNpemUpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0Qm91bmQoJ3N0YXJ0JywgYmluT3B0cywgbmV3QmluU3BlYyk7XG4gICAgICAgIHNldEJvdW5kKCdlbmQnLCBiaW5PcHRzLCBuZXdCaW5TcGVjKTtcbiAgICB9XG5cbiAgICBwb3MwID0gdHJhY2VbJ18nICsgbWFpbkRhdGEgKyAncG9zMCddO1xuICAgIGRlbGV0ZSB0cmFjZVsnXycgKyBtYWluRGF0YSArICdwb3MwJ107XG5cbiAgICAvLyBFYWNoIHRyYWNlIGNhbiBzcGVjaWZ5IGl0cyBvd24gc3RhcnQvZW5kLCBvciBpZiBvbWl0dGVkXG4gICAgLy8gd2UgZW5zdXJlIHRoZXkncmUgYmV5b25kIHRoZSBib3VuZHMgb2YgdGhpcyB0cmFjZSdzIGRhdGEsXG4gICAgLy8gYW5kIHdlIG5lZWQgdG8gbWFrZSBzdXJlIHN0YXJ0IGlzIGFsaWduZWQgd2l0aCB0aGUgbWFpbiBzdGFydFxuICAgIHZhciB0cmFjZUlucHV0QmlucyA9IHRyYWNlLl9pbnB1dFtiaW5BdHRyXSB8fCB7fTtcbiAgICB2YXIgdHJhY2VCaW5PcHRzQ2FsYyA9IExpYi5leHRlbmRGbGF0KHt9LCBiaW5PcHRzKTtcbiAgICB2YXIgbWFpblN0YXJ0ID0gYmluT3B0cy5zdGFydDtcbiAgICB2YXIgc3RhcnRJbiA9IHBhLnIybCh0cmFjZUlucHV0Qmlucy5zdGFydCk7XG4gICAgdmFyIGhhc1N0YXJ0ID0gc3RhcnRJbiAhPT0gdW5kZWZpbmVkO1xuICAgIGlmKChiaW5PcHRzLnN0YXJ0Rm91bmQgfHwgaGFzU3RhcnQpICYmIHN0YXJ0SW4gIT09IHBhLnIybChtYWluU3RhcnQpKSB7XG4gICAgICAgIC8vIFdlIGhhdmUgYW4gZXhwbGljaXQgc3RhcnQgdG8gcmVjb25jaWxlIGFjcm9zcyB0cmFjZXNcbiAgICAgICAgLy8gaWYgdGhpcyB0cmFjZSBoYXMgYW4gZXhwbGljaXQgc3RhcnQsIHNoaWZ0IGl0IGRvd24gdG8gYSBiaW4gZWRnZVxuICAgICAgICAvLyBpZiBhbm90aGVyIHRyYWNlIGhhZCBhbiBleHBsaWNpdCBzdGFydCwgc2hpZnQgaXQgZG93biB0byBhXG4gICAgICAgIC8vIGJpbiBlZGdlIHBhc3Qgb3VyIGRhdGFcbiAgICAgICAgdmFyIHRyYWNlU3RhcnQgPSBoYXNTdGFydCA/XG4gICAgICAgICAgICBzdGFydEluIDpcbiAgICAgICAgICAgIExpYi5hZ2dOdW1zKE1hdGgubWluLCBudWxsLCBwb3MwKTtcblxuICAgICAgICB2YXIgZHVtbXlBeCA9IHtcbiAgICAgICAgICAgIHR5cGU6IChwYS50eXBlID09PSAnY2F0ZWdvcnknIHx8IHBhLnR5cGUgPT09ICdtdWx0aWNhdGVnb3J5JykgPyAnbGluZWFyJyA6IHBhLnR5cGUsXG4gICAgICAgICAgICByMmw6IHBhLnIybCxcbiAgICAgICAgICAgIGR0aWNrOiBiaW5PcHRzLnNpemUsXG4gICAgICAgICAgICB0aWNrMDogbWFpblN0YXJ0LFxuICAgICAgICAgICAgY2FsZW5kYXI6IGNhbGVuZGFyLFxuICAgICAgICAgICAgcmFuZ2U6IChbdHJhY2VTdGFydCwgQXhlcy50aWNrSW5jcmVtZW50KHRyYWNlU3RhcnQsIGJpbk9wdHMuc2l6ZSwgZmFsc2UsIGNhbGVuZGFyKV0pLm1hcChwYS5sMnIpXG4gICAgICAgIH07XG4gICAgICAgIHZhciBuZXdTdGFydCA9IEF4ZXMudGlja0ZpcnN0KGR1bW15QXgpO1xuICAgICAgICBpZihuZXdTdGFydCA+IHBhLnIybCh0cmFjZVN0YXJ0KSkge1xuICAgICAgICAgICAgbmV3U3RhcnQgPSBBeGVzLnRpY2tJbmNyZW1lbnQobmV3U3RhcnQsIGJpbk9wdHMuc2l6ZSwgdHJ1ZSwgY2FsZW5kYXIpO1xuICAgICAgICB9XG4gICAgICAgIHRyYWNlQmluT3B0c0NhbGMuc3RhcnQgPSBwYS5sMnIobmV3U3RhcnQpO1xuICAgICAgICBpZighaGFzU3RhcnQpIExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgYmluQXR0ciArICcuc3RhcnQnKS5zZXQodHJhY2VCaW5PcHRzQ2FsYy5zdGFydCk7XG4gICAgfVxuXG4gICAgdmFyIG1haW5FbmQgPSBiaW5PcHRzLmVuZDtcbiAgICB2YXIgZW5kSW4gPSBwYS5yMmwodHJhY2VJbnB1dEJpbnMuZW5kKTtcbiAgICB2YXIgaGFzRW5kID0gZW5kSW4gIT09IHVuZGVmaW5lZDtcbiAgICBpZigoYmluT3B0cy5lbmRGb3VuZCB8fCBoYXNFbmQpICYmIGVuZEluICE9PSBwYS5yMmwobWFpbkVuZCkpIHtcbiAgICAgICAgLy8gUmVjb25jaWxpbmcgYW4gZXhwbGljaXQgZW5kIGlzIGVhc2llciwgYXMgaXQgZG9lc24ndCBuZWVkIHRvXG4gICAgICAgIC8vIG1hdGNoIGJpbiBlZGdlc1xuICAgICAgICB2YXIgdHJhY2VFbmQgPSBoYXNFbmQgP1xuICAgICAgICAgICAgZW5kSW4gOlxuICAgICAgICAgICAgTGliLmFnZ051bXMoTWF0aC5tYXgsIG51bGwsIHBvczApO1xuXG4gICAgICAgIHRyYWNlQmluT3B0c0NhbGMuZW5kID0gcGEubDJyKHRyYWNlRW5kKTtcbiAgICAgICAgaWYoIWhhc0VuZCkgTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBiaW5BdHRyICsgJy5zdGFydCcpLnNldCh0cmFjZUJpbk9wdHNDYWxjLmVuZCk7XG4gICAgfVxuXG4gICAgLy8gQmFja3dhcmQgY29tcGF0aWJpbGl0eSBmb3Igb25lLXRpbWUgYXV0b2Jpbm5pbmcuXG4gICAgLy8gYXV0b2JpbjogdHJ1ZSBpcyBoYW5kbGVkIGluIGNsZWFuRGF0YSwgYnV0IGF1dG9iaW46IGZhbHNlXG4gICAgLy8gbmVlZHMgdG8gYmUgaGVyZSB3aGVyZSB3ZSBoYXZlIGRldGVybWluZWQgdGhlIHZhbHVlcy5cbiAgICB2YXIgYXV0b0JpbkF0dHIgPSAnYXV0b2JpbicgKyBtYWluRGF0YTtcbiAgICBpZih0cmFjZS5faW5wdXRbYXV0b0JpbkF0dHJdID09PSBmYWxzZSkge1xuICAgICAgICB0cmFjZS5faW5wdXRbYmluQXR0cl0gPSBMaWIuZXh0ZW5kRmxhdCh7fSwgdHJhY2VbYmluQXR0cl0gfHwge30pO1xuICAgICAgICBkZWxldGUgdHJhY2UuX2lucHV0W2F1dG9CaW5BdHRyXTtcbiAgICAgICAgZGVsZXRlIHRyYWNlW2F1dG9CaW5BdHRyXTtcbiAgICB9XG5cbiAgICByZXR1cm4gW3RyYWNlQmluT3B0c0NhbGMsIHBvczBdO1xufVxuXG4vKlxuICogQWRqdXN0IHNpbmdsZS12YWx1ZSBoaXN0b2dyYW1zIGluIG92ZXJsYXkgbW9kZSB0byBtYWtlIGFzIGdvb2QgYVxuICogZ3Vlc3MgYXMgd2UgY2FuIGF0IGF1dG9iaW4gdmFsdWVzIHRoZSB1c2VyIHdvdWxkIGxpa2UuXG4gKlxuICogUmV0dXJucyB0aGUgYmluU3BlYyBmb3IgdGhlIHRyYWNlIHRoYXQgc3BhcmtlZCBhbGwgdGhpc1xuICovXG5mdW5jdGlvbiBoYW5kbGVTaW5nbGVWYWx1ZU92ZXJsYXlzKGdkLCB0cmFjZSwgcGEsIG1haW5EYXRhLCBiaW5BdHRyKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgb3ZlcmxhaWRUcmFjZUdyb3VwID0gZ2V0Q29ubmVjdGVkSGlzdG9ncmFtcyhnZCwgdHJhY2UpO1xuICAgIHZhciBwYXN0VGhpc1RyYWNlID0gZmFsc2U7XG4gICAgdmFyIG1pblNpemUgPSBJbmZpbml0eTtcbiAgICB2YXIgc2luZ2xlVmFsdWVkVHJhY2VzID0gW3RyYWNlXTtcbiAgICB2YXIgaSwgdHJhY2VpLCBiaW5PcHRzO1xuXG4gICAgLy8gZmlyc3QgY29sbGVjdCBhbGwgdGhlOlxuICAgIC8vIC0gbWluIGJpbiBzaXplIGZyb20gYWxsIG11bHRpLXZhbHVlZCB0cmFjZXNcbiAgICAvLyAtIHNpbmdsZS12YWx1ZWQgdHJhY2VzXG4gICAgZm9yKGkgPSAwOyBpIDwgb3ZlcmxhaWRUcmFjZUdyb3VwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlaSA9IG92ZXJsYWlkVHJhY2VHcm91cFtpXTtcblxuICAgICAgICBpZih0cmFjZWkgPT09IHRyYWNlKSB7XG4gICAgICAgICAgICBwYXN0VGhpc1RyYWNlID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIGlmKCFwYXN0VGhpc1RyYWNlKSB7XG4gICAgICAgICAgICAvLyBUaGlzIHRyYWNlIGhhcyBhbHJlYWR5IGhhZCBpdHMgYXV0b2JpbnMgY2FsY3VsYXRlZCwgc28gZWl0aGVyOlxuICAgICAgICAgICAgLy8gLSBpdCBpcyBwYXJ0IG9mIGEgYmluZ3JvdXBcbiAgICAgICAgICAgIC8vIC0gaXQgaXMgTk9UIGEgc2luZ2xlLXZhbHVlZCB0cmFjZVxuICAgICAgICAgICAgYmluT3B0cyA9IGZ1bGxMYXlvdXQuX2hpc3RvZ3JhbUJpbk9wdHNbdHJhY2VpWydfJyArIG1haW5EYXRhICsgJ2Jpbmdyb3VwJ11dO1xuICAgICAgICAgICAgbWluU2l6ZSA9IE1hdGgubWluKG1pblNpemUsIGJpbk9wdHMuc2l6ZSB8fCB0cmFjZWlbYmluQXR0cl0uc2l6ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0aSA9IGNhbGNBbGxBdXRvQmlucyhnZCwgdHJhY2VpLCBwYSwgbWFpbkRhdGEsIHRydWUpO1xuICAgICAgICAgICAgdmFyIGJpblNwZWNpID0gcmVzdWx0aVswXTtcbiAgICAgICAgICAgIHZhciBpc1NpbmdsZVZhbHVlZCA9IHJlc3VsdGlbMl07XG5cbiAgICAgICAgICAgIC8vIHNvIHdlIGNhbiB1c2UgdGhpcyByZXN1bHQgd2hlbiB3ZSBnZXQgdG8gdHJhY2VpIGluIHRoZSBub3JtYWxcbiAgICAgICAgICAgIC8vIGNvdXJzZSBvZiBldmVudHMsIG1hcmsgaXQgYXMgZG9uZSBhbmQgcHV0IF9wb3MwIGJhY2tcbiAgICAgICAgICAgIHRyYWNlaVsnXycgKyBtYWluRGF0YSArICdhdXRvQmluRmluaXNoZWQnXSA9IDE7XG4gICAgICAgICAgICB0cmFjZWlbJ18nICsgbWFpbkRhdGEgKyAncG9zMCddID0gcmVzdWx0aVsxXTtcblxuICAgICAgICAgICAgaWYoaXNTaW5nbGVWYWx1ZWQpIHtcbiAgICAgICAgICAgICAgICBzaW5nbGVWYWx1ZWRUcmFjZXMucHVzaCh0cmFjZWkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtaW5TaXplID0gTWF0aC5taW4obWluU2l6ZSwgYmluU3BlY2kuc2l6ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBmaW5kIHRoZSByZWFsIGRhdGEgdmFsdWVzIGZvciBlYWNoIHNpbmdsZS12YWx1ZWQgdHJhY2VcbiAgICAvLyBodW50IHRocm91Z2ggcG9zMCBmb3IgdGhlIGZpcnN0IHZhbGlkIHZhbHVlXG4gICAgdmFyIGRhdGFWYWxzID0gbmV3IEFycmF5KHNpbmdsZVZhbHVlZFRyYWNlcy5sZW5ndGgpO1xuICAgIGZvcihpID0gMDsgaSA8IHNpbmdsZVZhbHVlZFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcG9zMCA9IHNpbmdsZVZhbHVlZFRyYWNlc1tpXVsnXycgKyBtYWluRGF0YSArICdwb3MwJ107XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBwb3MwLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZihwb3MwW2pdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBkYXRhVmFsc1tpXSA9IHBvczBbal07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhcmUgQUxMIHRyYWNlcyBhcmUgc2luZ2xlLXZhbHVlZD8gdXNlIHRoZSBtaW4gZGlmZmVyZW5jZSBiZXR3ZWVuXG4gICAgLy8gYWxsIG9mIHRoZWlyIHZhbHVlcyAod2hpY2ggZGVmYXVsdHMgdG8gMSBpZiB0aGVyZSdzIHN0aWxsIG9ubHkgb25lKVxuICAgIGlmKCFpc0Zpbml0ZShtaW5TaXplKSkge1xuICAgICAgICBtaW5TaXplID0gTGliLmRpc3RpbmN0VmFscyhkYXRhVmFscykubWluRGlmZjtcbiAgICB9XG5cbiAgICAvLyBub3cgYXBwbHkgdGhlIG1pbiBzaXplIHdlIGZvdW5kIHRvIGFsbCBzaW5nbGUtdmFsdWVkIHRyYWNlc1xuICAgIGZvcihpID0gMDsgaSA8IHNpbmdsZVZhbHVlZFRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0cmFjZWkgPSBzaW5nbGVWYWx1ZWRUcmFjZXNbaV07XG4gICAgICAgIHZhciBjYWxlbmRhciA9IHRyYWNlaVttYWluRGF0YSArICdjYWxlbmRhciddO1xuXG4gICAgICAgIHZhciBuZXdCaW5zID0ge1xuICAgICAgICAgICAgc3RhcnQ6IHBhLmMycihkYXRhVmFsc1tpXSAtIG1pblNpemUgLyAyLCAwLCBjYWxlbmRhciksXG4gICAgICAgICAgICBlbmQ6IHBhLmMycihkYXRhVmFsc1tpXSArIG1pblNpemUgLyAyLCAwLCBjYWxlbmRhciksXG4gICAgICAgICAgICBzaXplOiBtaW5TaXplXG4gICAgICAgIH07XG5cbiAgICAgICAgdHJhY2VpLl9pbnB1dFtiaW5BdHRyXSA9IHRyYWNlaVtiaW5BdHRyXSA9IG5ld0JpbnM7XG5cbiAgICAgICAgYmluT3B0cyA9IGZ1bGxMYXlvdXQuX2hpc3RvZ3JhbUJpbk9wdHNbdHJhY2VpWydfJyArIG1haW5EYXRhICsgJ2Jpbmdyb3VwJ11dO1xuICAgICAgICBpZihiaW5PcHRzKSBMaWIuZXh0ZW5kRmxhdChiaW5PcHRzLCBuZXdCaW5zKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJhY2VbYmluQXR0cl07XG59XG5cbi8qXG4gKiBSZXR1cm4gYW4gYXJyYXkgb2YgaGlzdG9ncmFtcyB0aGF0IHNoYXJlIGF4ZXMgYW5kIG9yaWVudGF0aW9uLlxuICpcbiAqIE9ubHkgY29uc2lkZXJzIGhpc3RvZ3JhbXMuIEluIHByaW5jaXBsZSB3ZSBjb3VsZCBpbmNsdWRlIGJhcnMgaW4gYVxuICogc2ltaWxhciB3YXkgdG8gaG93IHdlIGRvIG1hbnVhbGx5IGJpbm5lZCBoaXN0b2dyYW1zLCB0aG91Z2ggdGhpc1xuICogd291bGQgaGF2ZSB0b25zIG9mIGVkZ2UgY2FzZXMgYW5kIHZhbHVlIGp1ZGdtZW50cyB0byBtYWtlLlxuICovXG5mdW5jdGlvbiBnZXRDb25uZWN0ZWRIaXN0b2dyYW1zKGdkLCB0cmFjZSkge1xuICAgIHZhciB4aWQgPSB0cmFjZS54YXhpcztcbiAgICB2YXIgeWlkID0gdHJhY2UueWF4aXM7XG4gICAgdmFyIG9yaWVudGF0aW9uID0gdHJhY2Uub3JpZW50YXRpb247XG5cbiAgICB2YXIgb3V0ID0gW107XG4gICAgdmFyIGZ1bGxEYXRhID0gZ2QuX2Z1bGxEYXRhO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdHJhY2VpID0gZnVsbERhdGFbaV07XG4gICAgICAgIGlmKHRyYWNlaS50eXBlID09PSAnaGlzdG9ncmFtJyAmJlxuICAgICAgICAgICAgdHJhY2VpLnZpc2libGUgPT09IHRydWUgJiZcbiAgICAgICAgICAgIHRyYWNlaS5vcmllbnRhdGlvbiA9PT0gb3JpZW50YXRpb24gJiZcbiAgICAgICAgICAgIHRyYWNlaS54YXhpcyA9PT0geGlkICYmIHRyYWNlaS55YXhpcyA9PT0geWlkXG4gICAgICAgICkge1xuICAgICAgICAgICAgb3V0LnB1c2godHJhY2VpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGNkZihzaXplLCBkaXJlY3Rpb24sIGN1cnJlbnRCaW4pIHtcbiAgICB2YXIgaSwgdmksIHByZXZTdW07XG5cbiAgICBmdW5jdGlvbiBmaXJzdEhhbGZQb2ludChpKSB7XG4gICAgICAgIHByZXZTdW0gPSBzaXplW2ldO1xuICAgICAgICBzaXplW2ldIC89IDI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbmV4dEhhbGZQb2ludChpKSB7XG4gICAgICAgIHZpID0gc2l6ZVtpXTtcbiAgICAgICAgc2l6ZVtpXSA9IHByZXZTdW0gKyB2aSAvIDI7XG4gICAgICAgIHByZXZTdW0gKz0gdmk7XG4gICAgfVxuXG4gICAgaWYoY3VycmVudEJpbiA9PT0gJ2hhbGYnKSB7XG4gICAgICAgIGlmKGRpcmVjdGlvbiA9PT0gJ2luY3JlYXNpbmcnKSB7XG4gICAgICAgICAgICBmaXJzdEhhbGZQb2ludCgwKTtcbiAgICAgICAgICAgIGZvcihpID0gMTsgaSA8IHNpemUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBuZXh0SGFsZlBvaW50KGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZmlyc3RIYWxmUG9pbnQoc2l6ZS5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIGZvcihpID0gc2l6ZS5sZW5ndGggLSAyOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIG5leHRIYWxmUG9pbnQoaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYoZGlyZWN0aW9uID09PSAnaW5jcmVhc2luZycpIHtcbiAgICAgICAgZm9yKGkgPSAxOyBpIDwgc2l6ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc2l6ZVtpXSArPSBzaXplW2kgLSAxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vICdleGNsdWRlJyBpcyBpZGVudGljYWwgdG8gJ2luY2x1ZGUnIGp1c3Qgc2hpZnRlZCBvbmUgYmluIG92ZXJcbiAgICAgICAgaWYoY3VycmVudEJpbiA9PT0gJ2V4Y2x1ZGUnKSB7XG4gICAgICAgICAgICBzaXplLnVuc2hpZnQoMCk7XG4gICAgICAgICAgICBzaXplLnBvcCgpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSBzaXplLmxlbmd0aCAtIDI7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBzaXplW2ldICs9IHNpemVbaSArIDFdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY3VycmVudEJpbiA9PT0gJ2V4Y2x1ZGUnKSB7XG4gICAgICAgICAgICBzaXplLnB1c2goMCk7XG4gICAgICAgICAgICBzaXplLnNoaWZ0KCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNhbGM6IGNhbGMsXG4gICAgY2FsY0FsbEF1dG9CaW5zOiBjYWxjQWxsQXV0b0JpbnNcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4uL2Jhci9hcnJheXNfdG9fY2FsY2RhdGFcIjo4NTYsXCIuL2F2ZXJhZ2VcIjoxMDIwLFwiLi9iaW5fZnVuY3Rpb25zXCI6MTAyMixcIi4vYmluX2xhYmVsX3ZhbHNcIjoxMDIzLFwiLi9ub3JtX2Z1bmN0aW9uc1wiOjEwMzEsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDEwMjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGV2ZW50RGF0YUtleXM6IFsnYmluTnVtYmVyJ11cbn07XG5cbn0se31dLDEwMjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgYXhpc0lkcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkcycpO1xuXG52YXIgdHJhY2VJcyA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5JykudHJhY2VJcztcbnZhciBoYW5kbGVHcm91cGluZ0RlZmF1bHRzID0gX2RlcmVxXygnLi4vYmFyL2RlZmF1bHRzJykuaGFuZGxlR3JvdXBpbmdEZWZhdWx0cztcblxudmFyIG5lc3RlZFByb3BlcnR5ID0gTGliLm5lc3RlZFByb3BlcnR5O1xudmFyIGdldEF4aXNHcm91cCA9IGF4aXNJZHMuZ2V0QXhpc0dyb3VwO1xuXG52YXIgQklOQVRUUlMgPSBbXG4gICAge2FTdHI6IHt4OiAneGJpbnMuc3RhcnQnLCB5OiAneWJpbnMuc3RhcnQnfSwgbmFtZTogJ3N0YXJ0J30sXG4gICAge2FTdHI6IHt4OiAneGJpbnMuZW5kJywgeTogJ3liaW5zLmVuZCd9LCBuYW1lOiAnZW5kJ30sXG4gICAge2FTdHI6IHt4OiAneGJpbnMuc2l6ZScsIHk6ICd5Ymlucy5zaXplJ30sIG5hbWU6ICdzaXplJ30sXG4gICAge2FTdHI6IHt4OiAnbmJpbnN4JywgeTogJ25iaW5zeSd9LCBuYW1lOiAnbmJpbnMnfVxuXTtcblxudmFyIEJJTkRJUkVDVElPTlMgPSBbJ3gnLCAneSddO1xuXG4vLyBoYW5kbGUgYmluIGF0dHJzIGFuZCByZWxpbmsgYXV0by1kZXRlcm1pbmVkIHZhbHVlcyBzbyBmdWxsRGF0YSBpcyBjb21wbGV0ZVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcm9zc1RyYWNlRGVmYXVsdHMoZnVsbERhdGEsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgYWxsQmluT3B0cyA9IGZ1bGxMYXlvdXQuX2hpc3RvZ3JhbUJpbk9wdHMgPSB7fTtcbiAgICB2YXIgaGlzdFRyYWNlcyA9IFtdO1xuICAgIHZhciBtdXN0TWF0Y2hUcmFjZXNMb29rdXAgPSB7fTtcbiAgICB2YXIgb3RoZXJUcmFjZXNMaXN0ID0gW107XG5cbiAgICB2YXIgdHJhY2VPdXQsIHRyYWNlcywgZ3JvdXBOYW1lLCBiaW5EaXI7XG4gICAgdmFyIGksIGosIGs7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZU91dC5faW5wdXQsIHRyYWNlT3V0LCB0cmFjZU91dC5fbW9kdWxlLmF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9yaWVudGF0aW9uMmJpbkRpcih0cmFjZU91dCkge1xuICAgICAgICByZXR1cm4gdHJhY2VPdXQub3JpZW50YXRpb24gPT09ICd2JyA/ICd4JyA6ICd5JztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRBeGlzVHlwZSh0cmFjZU91dCwgYmluRGlyKSB7XG4gICAgICAgIHZhciBheCA9IGF4aXNJZHMuZ2V0RnJvbVRyYWNlKHtfZnVsbExheW91dDogZnVsbExheW91dH0sIHRyYWNlT3V0LCBiaW5EaXIpO1xuICAgICAgICByZXR1cm4gYXgudHlwZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmaWxsQmluT3B0cyh0cmFjZU91dCwgZ3JvdXBOYW1lLCBiaW5EaXIpIHtcbiAgICAgICAgLy8gTi5CLiBncm91cCB0cmFjZXMgdGhhdCBkb24ndCBoYXZlIGEgYmluZ3JvdXAgd2l0aCB0aGVtc2VsdmVzXG4gICAgICAgIHZhciBmYWxsYmFja0dyb3VwTmFtZSA9IHRyYWNlT3V0LnVpZCArICdfXycgKyBiaW5EaXI7XG4gICAgICAgIGlmKCFncm91cE5hbWUpIGdyb3VwTmFtZSA9IGZhbGxiYWNrR3JvdXBOYW1lO1xuXG4gICAgICAgIHZhciBheFR5cGUgPSBnZXRBeGlzVHlwZSh0cmFjZU91dCwgYmluRGlyKTtcbiAgICAgICAgdmFyIGNhbGVuZGFyID0gdHJhY2VPdXRbYmluRGlyICsgJ2NhbGVuZGFyJ107XG4gICAgICAgIHZhciBiaW5PcHRzID0gYWxsQmluT3B0c1tncm91cE5hbWVdO1xuICAgICAgICB2YXIgbmVlZHNOZXdJdGVtID0gdHJ1ZTtcblxuICAgICAgICBpZihiaW5PcHRzKSB7XG4gICAgICAgICAgICBpZihheFR5cGUgPT09IGJpbk9wdHMuYXhUeXBlICYmIGNhbGVuZGFyID09PSBiaW5PcHRzLmNhbGVuZGFyKSB7XG4gICAgICAgICAgICAgICAgbmVlZHNOZXdJdGVtID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgYmluT3B0cy50cmFjZXMucHVzaCh0cmFjZU91dCk7XG4gICAgICAgICAgICAgICAgYmluT3B0cy5kaXJzLnB1c2goYmluRGlyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBOYW1lID0gZmFsbGJhY2tHcm91cE5hbWU7XG5cbiAgICAgICAgICAgICAgICBpZihheFR5cGUgIT09IGJpbk9wdHMuYXhUeXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIExpYi53YXJuKFtcbiAgICAgICAgICAgICAgICAgICAgICAgICdBdHRlbXB0ZWQgdG8gZ3JvdXAgdGhlIGJpbnMgb2YgdHJhY2UnLCB0cmFjZU91dC5pbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgICdzZXQgb24gYScsICd0eXBlOicgKyBheFR5cGUsICdheGlzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICd3aXRoIGJpbnMgb24nLCAndHlwZTonICsgYmluT3B0cy5heFR5cGUsICdheGlzLidcbiAgICAgICAgICAgICAgICAgICAgXS5qb2luKCcgJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZihjYWxlbmRhciAhPT0gYmluT3B0cy5jYWxlbmRhcikge1xuICAgICAgICAgICAgICAgICAgICAvLyBwcm9oaWJpdCBiaW5ncm91cCBmb3IgdHJhY2VzIHVzaW5nIGRpZmZlcmVudCBjYWxlbmRhcixcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlcmUncyBwcm9iYWJseSBhIHdheSB0byBtYWtlIHRoaXMgd29yaywgYnV0IHNraXAgZm9yIG5vd1xuICAgICAgICAgICAgICAgICAgICBMaWIud2FybihbXG4gICAgICAgICAgICAgICAgICAgICAgICAnQXR0ZW1wdGVkIHRvIGdyb3VwIHRoZSBiaW5zIG9mIHRyYWNlJywgdHJhY2VPdXQuaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICAnc2V0IHdpdGggYScsIGNhbGVuZGFyLCAnY2FsZW5kYXInLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3dpdGggYmlucycsXG4gICAgICAgICAgICAgICAgICAgICAgICAoYmluT3B0cy5jYWxlbmRhciA/ICdvbiBhICcgKyBiaW5PcHRzLmNhbGVuZGFyICsgJyBjYWxlbmRhcicgOiAndy9vIGEgc2V0IGNhbGVuZGFyJylcbiAgICAgICAgICAgICAgICAgICAgXS5qb2luKCcgJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG5lZWRzTmV3SXRlbSkge1xuICAgICAgICAgICAgYWxsQmluT3B0c1tncm91cE5hbWVdID0ge1xuICAgICAgICAgICAgICAgIHRyYWNlczogW3RyYWNlT3V0XSxcbiAgICAgICAgICAgICAgICBkaXJzOiBbYmluRGlyXSxcbiAgICAgICAgICAgICAgICBheFR5cGU6IGF4VHlwZSxcbiAgICAgICAgICAgICAgICBjYWxlbmRhcjogdHJhY2VPdXRbYmluRGlyICsgJ2NhbGVuZGFyJ10gfHwgJydcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgdHJhY2VPdXRbJ18nICsgYmluRGlyICsgJ2Jpbmdyb3VwJ10gPSBncm91cE5hbWU7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgZnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJhY2VPdXQgPSBmdWxsRGF0YVtpXTtcblxuICAgICAgICBpZih0cmFjZUlzKHRyYWNlT3V0LCAnaGlzdG9ncmFtJykpIHtcbiAgICAgICAgICAgIGhpc3RUcmFjZXMucHVzaCh0cmFjZU91dCk7XG5cbiAgICAgICAgICAgIC8vIFRPRE86IHRoaXMgc2hvdWxkbid0IGJlIHJlbGlua2VkIGFzIGl0J3Mgb25seSB1c2VkIHdpdGhpbiBjYWxjXG4gICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvNzQ5XG4gICAgICAgICAgICBkZWxldGUgdHJhY2VPdXQuX3hhdXRvQmluRmluaXNoZWQ7XG4gICAgICAgICAgICBkZWxldGUgdHJhY2VPdXQuX3lhdXRvQmluRmluaXNoZWQ7XG5cbiAgICAgICAgICAgIC8vIE4uQi4gbmVlZCB0byBjb2VyY2UgKmFsaWdubWVudGdyb3VwKiBiZWZvcmUgKmJpbmdyb3VwKiwgYXMgdHJhY2VzXG4gICAgICAgICAgICAvLyBpbiBzYW1lIGFsaWdubWVudGdyb3VwIFwiaGF2ZSB0byBtYXRjaFwiXG4gICAgICAgICAgICBpZighdHJhY2VJcyh0cmFjZU91dCwgJzJkTWFwJykpIHtcbiAgICAgICAgICAgICAgICBoYW5kbGVHcm91cGluZ0RlZmF1bHRzKHRyYWNlT3V0Ll9pbnB1dCwgdHJhY2VPdXQsIGZ1bGxMYXlvdXQsIGNvZXJjZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgYWxpZ25tZW50T3B0cyA9IGZ1bGxMYXlvdXQuX2FsaWdubWVudE9wdHMgfHwge307XG5cbiAgICAvLyBMb29rIGZvciB0cmFjZXMgdGhhdCBcImhhdmUgdG8gbWF0Y2hcIiwgdGhhdCBpczpcbiAgICAvLyAtIDFkIGhpc3RvZ3JhbSB0cmFjZXMgb24gdGhlIHNhbWUgc3VicGxvdCB3aXRoIHNhbWUgb3JpZW50YXRpb24gdW5kZXIgYmFybW9kZTpzdGFjayxcbiAgICAvLyAtIDFkIGhpc3RvZ3JhbSB0cmFjZXMgb24gdGhlIHNhbWUgc3VicGxvdCB3aXRoIHNhbWUgb3JpZW50YXRpb24gdW5kZXIgYmFybW9kZTpncm91cFxuICAgIC8vIC0gMWQgaGlzdG9ncmFtIHRyYWNlcyBvbiB0aGUgc2FtZSBwb3NpdGlvbiBheGlzIHdpdGggdGhlIHNhbWUgb3JpZW50YXRpb25cbiAgICAvLyAgIGFuZCB0aGUgc2FtZSAqYWxpZ25tZW50Z3JvdXAqIChjb2VyY2VkIHVuZGVyIGJhcm1vZGU6Z3JvdXApXG4gICAgLy8gLSBPbmNlIGBzdGFja2dyb3VwYCBnZXRzIGltcGxlbWVudGVkIChzZWUgaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzM2MTQpLFxuICAgIC8vICAgdHJhY2VzIHdpdGhpbiB0aGUgc2FtZSBzdGFja2dyb3VwIHdpbGwgYWxzbyBcImhhdmUgdG8gbWF0Y2hcIlxuICAgIGZvcihpID0gMDsgaSA8IGhpc3RUcmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdHJhY2VPdXQgPSBoaXN0VHJhY2VzW2ldO1xuICAgICAgICBncm91cE5hbWUgPSAnJztcblxuICAgICAgICBpZighdHJhY2VJcyh0cmFjZU91dCwgJzJkTWFwJykpIHtcbiAgICAgICAgICAgIGJpbkRpciA9IG9yaWVudGF0aW9uMmJpbkRpcih0cmFjZU91dCk7XG5cbiAgICAgICAgICAgIGlmKGZ1bGxMYXlvdXQuYmFybW9kZSA9PT0gJ2dyb3VwJyAmJiB0cmFjZU91dC5hbGlnbm1lbnRncm91cCkge1xuICAgICAgICAgICAgICAgIHZhciBwYSA9IHRyYWNlT3V0W2JpbkRpciArICdheGlzJ107XG4gICAgICAgICAgICAgICAgdmFyIGFHcm91cElkID0gZ2V0QXhpc0dyb3VwKGZ1bGxMYXlvdXQsIHBhKSArIHRyYWNlT3V0Lm9yaWVudGF0aW9uO1xuICAgICAgICAgICAgICAgIGlmKChhbGlnbm1lbnRPcHRzW2FHcm91cElkXSB8fCB7fSlbdHJhY2VPdXQuYWxpZ25tZW50Z3JvdXBdKSB7XG4gICAgICAgICAgICAgICAgICAgIGdyb3VwTmFtZSA9IGFHcm91cElkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoIWdyb3VwTmFtZSAmJiBmdWxsTGF5b3V0LmJhcm1vZGUgIT09ICdvdmVybGF5Jykge1xuICAgICAgICAgICAgICAgIGdyb3VwTmFtZSA9IChcbiAgICAgICAgICAgICAgICAgICAgZ2V0QXhpc0dyb3VwKGZ1bGxMYXlvdXQsIHRyYWNlT3V0LnhheGlzKSArXG4gICAgICAgICAgICAgICAgICAgIGdldEF4aXNHcm91cChmdWxsTGF5b3V0LCB0cmFjZU91dC55YXhpcykgK1xuICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbjJiaW5EaXIodHJhY2VPdXQpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGdyb3VwTmFtZSkge1xuICAgICAgICAgICAgaWYoIW11c3RNYXRjaFRyYWNlc0xvb2t1cFtncm91cE5hbWVdKSB7XG4gICAgICAgICAgICAgICAgbXVzdE1hdGNoVHJhY2VzTG9va3VwW2dyb3VwTmFtZV0gPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG11c3RNYXRjaFRyYWNlc0xvb2t1cFtncm91cE5hbWVdLnB1c2godHJhY2VPdXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3RoZXJUcmFjZXNMaXN0LnB1c2godHJhY2VPdXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gU2V0dXAgYmluT3B0cyBmb3IgdHJhY2VzIHRoYXQgaGF2ZSB0byBtYXRjaCxcbiAgICAvLyBpZiB0aGUgdHJhY2VzIGhhdmUgYSB2YWxpZCBiaW5ncm91cCwgdXNlIHRoYXRcbiAgICAvLyBpZiBub3QgdXNlIGF4aXMrYmluRGlyIGdyb3VwTmFtZVxuICAgIGZvcihncm91cE5hbWUgaW4gbXVzdE1hdGNoVHJhY2VzTG9va3VwKSB7XG4gICAgICAgIHRyYWNlcyA9IG11c3RNYXRjaFRyYWNlc0xvb2t1cFtncm91cE5hbWVdO1xuXG4gICAgICAgIC8vIG5vIG5lZWQgdG8gJ2ZvcmNlJyBhbnl0aGluZyB3aGVuIGEgc2luZ2xlXG4gICAgICAgIC8vIHRyYWNlIGlzIGRldGVjdGVkIGFzIFwibXVzdCBtYXRjaFwiXG4gICAgICAgIGlmKHRyYWNlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIG90aGVyVHJhY2VzTGlzdC5wdXNoKHRyYWNlc1swXSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBiaW5Hcm91cEZvdW5kID0gZmFsc2U7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdHJhY2VPdXQgPSB0cmFjZXNbaV07XG4gICAgICAgICAgICBiaW5Hcm91cEZvdW5kID0gY29lcmNlKCdiaW5ncm91cCcpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBncm91cE5hbWUgPSBiaW5Hcm91cEZvdW5kIHx8IGdyb3VwTmFtZTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCB0cmFjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyYWNlT3V0ID0gdHJhY2VzW2ldO1xuICAgICAgICAgICAgdmFyIGJpbmdyb3VwSW4gPSB0cmFjZU91dC5faW5wdXQuYmluZ3JvdXA7XG4gICAgICAgICAgICBpZihiaW5ncm91cEluICYmIGJpbmdyb3VwSW4gIT09IGdyb3VwTmFtZSkge1xuICAgICAgICAgICAgICAgIExpYi53YXJuKFtcbiAgICAgICAgICAgICAgICAgICAgJ1RyYWNlJywgdHJhY2VPdXQuaW5kZXgsICdtdXN0IG1hdGNoJyxcbiAgICAgICAgICAgICAgICAgICAgJ3dpdGhpbiBiaW5ncm91cCcsIGdyb3VwTmFtZSArICcuJyxcbiAgICAgICAgICAgICAgICAgICAgJ0lnbm9yaW5nIGl0cyBiaW5ncm91cDonLCBiaW5ncm91cEluLCAnc2V0dGluZy4nXG4gICAgICAgICAgICAgICAgXS5qb2luKCcgJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHJhY2VPdXQuYmluZ3JvdXAgPSBncm91cE5hbWU7XG5cbiAgICAgICAgICAgIC8vIE4uQi4gbm8gbmVlZCB0byB3b3JyeSBhYm91dCAyZE1hcCBjYXNlXG4gICAgICAgICAgICAvLyAod2hlcmUgYm90aCBiaW4gZGlyZWN0aW9uIGFyZSBzZXQgaW4gZWFjaCB0cmFjZSlcbiAgICAgICAgICAgIC8vIGFzIDJkTWFwIHRyYWNlIG5ldmVyIFwiaGF2ZSB0byBtYXRjaFwiXG4gICAgICAgICAgICBmaWxsQmluT3B0cyh0cmFjZU91dCwgZ3JvdXBOYW1lLCBvcmllbnRhdGlvbjJiaW5EaXIodHJhY2VPdXQpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNldHVwIGJpbk9wdHMgZm9yIHRyYWNlcyB0aGF0IGNhbiBidXQgZG9uJ3QgaGF2ZSB0byBtYXRjaCxcbiAgICAvLyBub3RpY2UgdGhhdCB0aGVzZSB0cmFjZXMgY2FuIGJlIG1hdGNoZWQgd2l0aCB0cmFjZXMgdGhhdCBoYXZlIHRvIG1hdGNoXG4gICAgZm9yKGkgPSAwOyBpIDwgb3RoZXJUcmFjZXNMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlT3V0ID0gb3RoZXJUcmFjZXNMaXN0W2ldO1xuXG4gICAgICAgIHZhciBiaW5Hcm91cCA9IGNvZXJjZSgnYmluZ3JvdXAnKTtcblxuICAgICAgICBpZih0cmFjZUlzKHRyYWNlT3V0LCAnMmRNYXAnKSkge1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgMjsgaysrKSB7XG4gICAgICAgICAgICAgICAgYmluRGlyID0gQklORElSRUNUSU9OU1trXTtcbiAgICAgICAgICAgICAgICB2YXIgYmluR3JvdXBJbkRpciA9IGNvZXJjZShiaW5EaXIgKyAnYmluZ3JvdXAnLFxuICAgICAgICAgICAgICAgICAgICBiaW5Hcm91cCA/IGJpbkdyb3VwICsgJ19fJyArIGJpbkRpciA6IG51bGxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGZpbGxCaW5PcHRzKHRyYWNlT3V0LCBiaW5Hcm91cEluRGlyLCBiaW5EaXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZmlsbEJpbk9wdHModHJhY2VPdXQsIGJpbkdyb3VwLCBvcmllbnRhdGlvbjJiaW5EaXIodHJhY2VPdXQpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNvZXJjZSBiaW4gYXR0cnMhXG4gICAgZm9yKGdyb3VwTmFtZSBpbiBhbGxCaW5PcHRzKSB7XG4gICAgICAgIHZhciBiaW5PcHRzID0gYWxsQmluT3B0c1tncm91cE5hbWVdO1xuICAgICAgICB0cmFjZXMgPSBiaW5PcHRzLnRyYWNlcztcblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBCSU5BVFRSUy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIGF0dHJTcGVjID0gQklOQVRUUlNbal07XG4gICAgICAgICAgICB2YXIgYXR0ciA9IGF0dHJTcGVjLm5hbWU7XG4gICAgICAgICAgICB2YXIgYVN0cjtcbiAgICAgICAgICAgIHZhciBhdXRvVmFscztcblxuICAgICAgICAgICAgLy8gbmJpbnMoeHx5KSBpcyBtb290IGlmIHdlIGhhdmUgYSBzaXplLiBUaGlzIGRlcGVuZHMgb25cbiAgICAgICAgICAgIC8vIG5iaW5zIGNvbWluZyBhZnRlciBzaXplIGluIGJpbkF0dHJzLlxuICAgICAgICAgICAgaWYoYXR0ciA9PT0gJ25iaW5zJyAmJiBiaW5PcHRzLnNpemVGb3VuZCkgY29udGludWU7XG5cbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHRyYWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRyYWNlT3V0ID0gdHJhY2VzW2ldO1xuICAgICAgICAgICAgICAgIGJpbkRpciA9IGJpbk9wdHMuZGlyc1tpXTtcbiAgICAgICAgICAgICAgICBhU3RyID0gYXR0clNwZWMuYVN0cltiaW5EaXJdO1xuXG4gICAgICAgICAgICAgICAgaWYobmVzdGVkUHJvcGVydHkodHJhY2VPdXQuX2lucHV0LCBhU3RyKS5nZXQoKSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGJpbk9wdHNbYXR0cl0gPSBjb2VyY2UoYVN0cik7XG4gICAgICAgICAgICAgICAgICAgIGJpbk9wdHNbYXR0ciArICdGb3VuZCddID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgYXV0b1ZhbHMgPSAodHJhY2VPdXQuX2F1dG9CaW4gfHwge30pW2JpbkRpcl0gfHwge307XG4gICAgICAgICAgICAgICAgaWYoYXV0b1ZhbHNbYXR0cl0pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhpcyBpcyB0aGUgKmZpcnN0KiBhdXRvdmFsXG4gICAgICAgICAgICAgICAgICAgIG5lc3RlZFByb3BlcnR5KHRyYWNlT3V0LCBhU3RyKS5zZXQoYXV0b1ZhbHNbYXR0cl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gc3RhcnQgYW5kIGVuZCB3ZSBuZWVkIHRvIGNvZXJjZSBhbnl3YXksIGFmdGVyIGhhdmluZyBjb2xsZWN0ZWQgdGhlXG4gICAgICAgICAgICAvLyBmaXJzdCBvZiBlYWNoIGludG8gYmluT3B0cywgaW4gY2FzZSBhIHRyYWNlIHdhbnRzIHRvIHJlc3RyaWN0IGl0c1xuICAgICAgICAgICAgLy8gZGF0YSB0byBhIGNlcnRhaW4gcmFuZ2VcbiAgICAgICAgICAgIGlmKGF0dHIgPT09ICdzdGFydCcgfHwgYXR0ciA9PT0gJ2VuZCcpIHtcbiAgICAgICAgICAgICAgICBmb3IoOyBpIDwgdHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYWNlT3V0ID0gdHJhY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZih0cmFjZU91dFsnXycgKyBiaW5EaXIgKyAnYmluZ3JvdXAnXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXV0b1ZhbHMgPSAodHJhY2VPdXQuX2F1dG9CaW4gfHwge30pW2JpbkRpcl0gfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2VyY2UoYVN0ciwgYXV0b1ZhbHNbYXR0cl0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihhdHRyID09PSAnbmJpbnMnICYmICFiaW5PcHRzLnNpemVGb3VuZCAmJiAhYmluT3B0cy5uYmluc0ZvdW5kKSB7XG4gICAgICAgICAgICAgICAgdHJhY2VPdXQgPSB0cmFjZXNbMF07XG4gICAgICAgICAgICAgICAgYmluT3B0c1thdHRyXSA9IGNvZXJjZShhU3RyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzXCI6NzcwLFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9iYXIvZGVmYXVsdHNcIjo4NjF9XSwxMDI3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcblxudmFyIGhhbmRsZVN0eWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9iYXIvc3R5bGVfZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIHkgPSBjb2VyY2UoJ3knKTtcblxuICAgIHZhciBjdW11bGF0aXZlID0gY29lcmNlKCdjdW11bGF0aXZlLmVuYWJsZWQnKTtcbiAgICBpZihjdW11bGF0aXZlKSB7XG4gICAgICAgIGNvZXJjZSgnY3VtdWxhdGl2ZS5kaXJlY3Rpb24nKTtcbiAgICAgICAgY29lcmNlKCdjdW11bGF0aXZlLmN1cnJlbnRiaW4nKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgdmFyIG9yaWVudGF0aW9uID0gY29lcmNlKCdvcmllbnRhdGlvbicsICh5ICYmICF4KSA/ICdoJyA6ICd2Jyk7XG4gICAgdmFyIHNhbXBsZUxldHRlciA9IG9yaWVudGF0aW9uID09PSAndicgPyAneCcgOiAneSc7XG4gICAgdmFyIGFnZ0xldHRlciA9IG9yaWVudGF0aW9uID09PSAndicgPyAneScgOiAneCc7XG5cbiAgICB2YXIgbGVuID0gKHggJiYgeSkgP1xuICAgICAgICBNYXRoLm1pbihMaWIubWluUm93TGVuZ3RoKHgpICYmIExpYi5taW5Sb3dMZW5ndGgoeSkpIDpcbiAgICAgICAgTGliLm1pblJvd0xlbmd0aCh0cmFjZU91dFtzYW1wbGVMZXR0ZXJdIHx8IFtdKTtcblxuICAgIGlmKCFsZW4pIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIHZhciBoYW5kbGVDYWxlbmRhckRlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnaGFuZGxlVHJhY2VEZWZhdWx0cycpO1xuICAgIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIFsneCcsICd5J10sIGxheW91dCk7XG5cbiAgICB2YXIgaGFzQWdncmVnYXRpb25EYXRhID0gdHJhY2VPdXRbYWdnTGV0dGVyXTtcbiAgICBpZihoYXNBZ2dyZWdhdGlvbkRhdGEpIGNvZXJjZSgnaGlzdGZ1bmMnKTtcbiAgICBjb2VyY2UoJ2hpc3Rub3JtJyk7XG5cbiAgICAvLyBOb3RlOiBiaW4gZGVmYXVsdHMgYXJlIG5vdyBoYW5kbGVkIGluIEhpc3RvZ3JhbS5jcm9zc1RyYWNlRGVmYXVsdHNcbiAgICAvLyBhdXRvYmluKHh8eSkgYXJlIG9ubHkgaW5jbHVkZWQgaGVyZSB0byBhcHBlYXNlIFBsb3RseS52YWxpZGF0ZVxuICAgIGNvZXJjZSgnYXV0b2JpbicgKyBzYW1wbGVMZXR0ZXIpO1xuXG4gICAgaGFuZGxlU3R5bGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBkZWZhdWx0Q29sb3IsIGxheW91dCk7XG5cbiAgICBMaWIuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eSh0cmFjZU91dCwgY29lcmNlKTtcblxuICAgIHZhciBsaW5lQ29sb3IgPSAodHJhY2VPdXQubWFya2VyLmxpbmUgfHwge30pLmNvbG9yO1xuXG4gICAgLy8gb3ZlcnJpZGUgZGVmYXVsdENvbG9yIGZvciBlcnJvciBiYXJzIHdpdGggZGVmYXVsdExpbmVcbiAgICB2YXIgZXJyb3JCYXJzU3VwcGx5RGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdzdXBwbHlEZWZhdWx0cycpO1xuICAgIGVycm9yQmFyc1N1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsaW5lQ29sb3IgfHwgQ29sb3IuZGVmYXVsdExpbmUsIHtheGlzOiAneSd9KTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGluZUNvbG9yIHx8IENvbG9yLmRlZmF1bHRMaW5lLCB7YXhpczogJ3gnLCBpbmhlcml0OiAneSd9KTtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vYmFyL3N0eWxlX2RlZmF1bHRzXCI6ODcxLFwiLi9hdHRyaWJ1dGVzXCI6MTAxOX1dLDEwMjg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0LCB0cmFjZSwgY2QsIHBvaW50TnVtYmVyKSB7XG4gICAgLy8gc3RhbmRhcmQgY2FydGVzaWFuIGV2ZW50IGRhdGFcbiAgICBvdXQueCA9ICd4VmFsJyBpbiBwdCA/IHB0LnhWYWwgOiBwdC54O1xuICAgIG91dC55ID0gJ3lWYWwnIGluIHB0ID8gcHQueVZhbCA6IHB0Lnk7XG5cbiAgICAvLyBmb3IgMmQgaGlzdG9ncmFtc1xuICAgIGlmKCd6TGFiZWxWYWwnIGluIHB0KSBvdXQueiA9IHB0LnpMYWJlbFZhbDtcblxuICAgIGlmKHB0LnhhKSBvdXQueGF4aXMgPSBwdC54YTtcbiAgICBpZihwdC55YSkgb3V0LnlheGlzID0gcHQueWE7XG5cbiAgICAvLyBzcGVjaWZpYyB0byBoaXN0b2dyYW0gLSBDREZzIGRvIG5vdCBoYXZlIHB0cyAoeWV0PylcbiAgICBpZighKHRyYWNlLmN1bXVsYXRpdmUgfHwge30pLmVuYWJsZWQpIHtcbiAgICAgICAgdmFyIHB0cyA9IEFycmF5LmlzQXJyYXkocG9pbnROdW1iZXIpID9cbiAgICAgICAgICAgIGNkWzBdLnB0c1twb2ludE51bWJlclswXV1bcG9pbnROdW1iZXJbMV1dIDpcbiAgICAgICAgICAgIGNkW3BvaW50TnVtYmVyXS5wdHM7XG5cbiAgICAgICAgb3V0LnBvaW50TnVtYmVycyA9IHB0cztcbiAgICAgICAgb3V0LmJpbk51bWJlciA9IG91dC5wb2ludE51bWJlcjtcbiAgICAgICAgZGVsZXRlIG91dC5wb2ludE51bWJlcjtcbiAgICAgICAgZGVsZXRlIG91dC5wb2ludEluZGV4O1xuXG4gICAgICAgIHZhciBwb2ludEluZGljZXM7XG4gICAgICAgIGlmKHRyYWNlLl9pbmRleFRvUG9pbnRzKSB7XG4gICAgICAgICAgICBwb2ludEluZGljZXMgPSBbXTtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBwdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwb2ludEluZGljZXMgPSBwb2ludEluZGljZXMuY29uY2F0KHRyYWNlLl9pbmRleFRvUG9pbnRzW3B0c1tpXV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9pbnRJbmRpY2VzID0gcHRzO1xuICAgICAgICB9XG5cbiAgICAgICAgb3V0LnBvaW50SW5kaWNlcyA9IHBvaW50SW5kaWNlcztcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxufSx7fV0sMTAyOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGJhckhvdmVyID0gX2RlcmVxXygnLi4vYmFyL2hvdmVyJykuaG92ZXJQb2ludHM7XG52YXIgaG92ZXJMYWJlbFRleHQgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpLmhvdmVyTGFiZWxUZXh0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIHB0cyA9IGJhckhvdmVyKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKTtcblxuICAgIGlmKCFwdHMpIHJldHVybjtcblxuICAgIHBvaW50RGF0YSA9IHB0c1swXTtcbiAgICB2YXIgZGkgPSBwb2ludERhdGEuY2RbcG9pbnREYXRhLmluZGV4XTtcbiAgICB2YXIgdHJhY2UgPSBwb2ludERhdGEuY2RbMF0udHJhY2U7XG5cbiAgICBpZighdHJhY2UuY3VtdWxhdGl2ZS5lbmFibGVkKSB7XG4gICAgICAgIHZhciBwb3NMZXR0ZXIgPSB0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnID8gJ3knIDogJ3gnO1xuXG4gICAgICAgIHBvaW50RGF0YVtwb3NMZXR0ZXIgKyAnTGFiZWwnXSA9IGhvdmVyTGFiZWxUZXh0KHBvaW50RGF0YVtwb3NMZXR0ZXIgKyAnYSddLCBkaS5waDAsIGRpLnBoMSk7XG4gICAgfVxuXG4gICAgaWYodHJhY2UuaG92ZXJtcGxhdGUpIHBvaW50RGF0YS5ob3ZlcnRlbXBsYXRlID0gdHJhY2UuaG92ZXJ0ZW1wbGF0ZTtcblxuICAgIHJldHVybiBwdHM7XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vYmFyL2hvdmVyXCI6ODYzfV0sMTAzMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8qKlxuICogSGlzdG9ncmFtIGhhcyBpdHMgb3duIGF0dHJpYnV0ZSwgZGVmYXVsdHMgYW5kIGNhbGMgc3RlcHMsXG4gKiBidXQgdXNlcyBiYXIncyBwbG90IHRvIGRpc3BsYXlcbiAqIGFuZCBiYXIncyBjcm9zc1RyYWNlQ2FsYyAoZm9ybWVybHkga25vd24gYXMgc2V0UG9zaXRpb25zKSBmb3Igc3RhY2tpbmcgYW5kIGdyb3VwaW5nXG4gKi9cblxuLyoqXG4gKiBoaXN0b2dyYW0gZXJyb3JCYXJzT0sgaXMgZGViYXRhYmxlLCBidXQgaXQncyBwdXQgaW4gZm9yIGJhY2t3YXJkIGNvbXBhdC5cbiAqIHRoZXJlIGFyZSB1c2UgY2FzZXMgZm9yIGl0IC0gc3FydCBmb3IgYSBzaW1wbGUgaGlzdG9ncmFtIHdvcmtzIHJpZ2h0IG5vdyxcbiAqIGNvbnN0YW50IGFuZCAlIHdvcmsgYnV0IHRoZXkncmUgbm90IHNvIG1lYW5pbmdmdWwuIEkgZ3Vlc3MgaXQgY291bGQgYmUgY29vbFxuICogdG8gYWxsb3cgcXVhZHJhdHVyZSBjb21iaW5hdGlvbiBvZiBlcnJvcnMgaW4gc3VtbWVkIGhpc3RvZ3JhbXMuLi5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBfZGVyZXFfKCcuLi9iYXIvbGF5b3V0X2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNyb3NzVHJhY2VEZWZhdWx0czogX2RlcmVxXygnLi9jcm9zc190cmFjZV9kZWZhdWx0cycpLFxuICAgIHN1cHBseUxheW91dERlZmF1bHRzOiBfZGVyZXFfKCcuLi9iYXIvbGF5b3V0X2RlZmF1bHRzJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJykuY2FsYyxcbiAgICBjcm9zc1RyYWNlQ2FsYzogX2RlcmVxXygnLi4vYmFyL2Nyb3NzX3RyYWNlX2NhbGMnKS5jcm9zc1RyYWNlQ2FsYyxcbiAgICBwbG90OiBfZGVyZXFfKCcuLi9iYXIvcGxvdCcpLnBsb3QsXG4gICAgbGF5ZXJOYW1lOiAnYmFybGF5ZXInLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuLi9iYXIvc3R5bGUnKS5zdHlsZSxcbiAgICBzdHlsZU9uU2VsZWN0OiBfZGVyZXFfKCcuLi9iYXIvc3R5bGUnKS5zdHlsZU9uU2VsZWN0LFxuICAgIGNvbG9yYmFyOiBfZGVyZXFfKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpLFxuICAgIGhvdmVyUG9pbnRzOiBfZGVyZXFfKCcuL2hvdmVyJyksXG4gICAgc2VsZWN0UG9pbnRzOiBfZGVyZXFfKCcuLi9iYXIvc2VsZWN0JyksXG4gICAgZXZlbnREYXRhOiBfZGVyZXFfKCcuL2V2ZW50X2RhdGEnKSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ2hpc3RvZ3JhbScsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnYmFyLWxpa2UnLCAnY2FydGVzaWFuJywgJ3N2ZycsICdiYXInLCAnaGlzdG9ncmFtJywgJ29yaWVudGVkJywgJ2Vycm9yQmFyc09LJywgJ3Nob3dMZWdlbmQnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvY2FydGVzaWFuXCI6Nzc4LFwiLi4vYmFyL2Nyb3NzX3RyYWNlX2NhbGNcIjo4NjAsXCIuLi9iYXIvbGF5b3V0X2F0dHJpYnV0ZXNcIjo4NjUsXCIuLi9iYXIvbGF5b3V0X2RlZmF1bHRzXCI6ODY2LFwiLi4vYmFyL3Bsb3RcIjo4NjcsXCIuLi9iYXIvc2VsZWN0XCI6ODY4LFwiLi4vYmFyL3N0eWxlXCI6ODcwLFwiLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXJcIjoxMTI5LFwiLi9hdHRyaWJ1dGVzXCI6MTAxOSxcIi4vY2FsY1wiOjEwMjQsXCIuL2Nyb3NzX3RyYWNlX2RlZmF1bHRzXCI6MTAyNixcIi4vZGVmYXVsdHNcIjoxMDI3LFwiLi9ldmVudF9kYXRhXCI6MTAyOCxcIi4vaG92ZXJcIjoxMDI5fV0sMTAzMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBwZXJjZW50OiBmdW5jdGlvbihzaXplLCB0b3RhbCkge1xuICAgICAgICB2YXIgbk1heCA9IHNpemUubGVuZ3RoO1xuICAgICAgICB2YXIgbm9ybSA9IDEwMCAvIHRvdGFsO1xuICAgICAgICBmb3IodmFyIG4gPSAwOyBuIDwgbk1heDsgbisrKSBzaXplW25dICo9IG5vcm07XG4gICAgfSxcbiAgICBwcm9iYWJpbGl0eTogZnVuY3Rpb24oc2l6ZSwgdG90YWwpIHtcbiAgICAgICAgdmFyIG5NYXggPSBzaXplLmxlbmd0aDtcbiAgICAgICAgZm9yKHZhciBuID0gMDsgbiA8IG5NYXg7IG4rKykgc2l6ZVtuXSAvPSB0b3RhbDtcbiAgICB9LFxuICAgIGRlbnNpdHk6IGZ1bmN0aW9uKHNpemUsIHRvdGFsLCBpbmMsIHlpbmMpIHtcbiAgICAgICAgdmFyIG5NYXggPSBzaXplLmxlbmd0aDtcbiAgICAgICAgeWluYyA9IHlpbmMgfHwgMTtcbiAgICAgICAgZm9yKHZhciBuID0gMDsgbiA8IG5NYXg7IG4rKykgc2l6ZVtuXSAqPSBpbmNbbl0gKiB5aW5jO1xuICAgIH0sXG4gICAgJ3Byb2JhYmlsaXR5IGRlbnNpdHknOiBmdW5jdGlvbihzaXplLCB0b3RhbCwgaW5jLCB5aW5jKSB7XG4gICAgICAgIHZhciBuTWF4ID0gc2l6ZS5sZW5ndGg7XG4gICAgICAgIGlmKHlpbmMpIHRvdGFsIC89IHlpbmM7XG4gICAgICAgIGZvcih2YXIgbiA9IDA7IG4gPCBuTWF4OyBuKyspIHNpemVbbl0gKj0gaW5jW25dIC8gdG90YWw7XG4gICAgfVxufTtcblxufSx7fV0sMTAzMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoaXN0b2dyYW1BdHRycyA9IF9kZXJlcV8oJy4uL2hpc3RvZ3JhbS9hdHRyaWJ1dGVzJyk7XG52YXIgbWFrZUJpbkF0dHJzID0gX2RlcmVxXygnLi4vaGlzdG9ncmFtL2Jpbl9hdHRyaWJ1dGVzJyk7XG52YXIgaGVhdG1hcEF0dHJzID0gX2RlcmVxXygnLi4vaGVhdG1hcC9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xuXG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGV4dGVuZEZsYXQoXG4gICAge1xuICAgICAgICB4OiBoaXN0b2dyYW1BdHRycy54LFxuICAgICAgICB5OiBoaXN0b2dyYW1BdHRycy55LFxuXG4gICAgICAgIHo6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbWFya2VyOiB7XG4gICAgICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICAgICAgfSxcblxuICAgICAgICBoaXN0bm9ybTogaGlzdG9ncmFtQXR0cnMuaGlzdG5vcm0sXG4gICAgICAgIGhpc3RmdW5jOiBoaXN0b2dyYW1BdHRycy5oaXN0ZnVuYyxcbiAgICAgICAgbmJpbnN4OiBoaXN0b2dyYW1BdHRycy5uYmluc3gsXG4gICAgICAgIHhiaW5zOiBtYWtlQmluQXR0cnMoJ3gnKSxcbiAgICAgICAgbmJpbnN5OiBoaXN0b2dyYW1BdHRycy5uYmluc3ksXG4gICAgICAgIHliaW5zOiBtYWtlQmluQXR0cnMoJ3knKSxcbiAgICAgICAgYXV0b2Jpbng6IGhpc3RvZ3JhbUF0dHJzLmF1dG9iaW54LFxuICAgICAgICBhdXRvYmlueTogaGlzdG9ncmFtQXR0cnMuYXV0b2JpbnksXG5cbiAgICAgICAgYmluZ3JvdXA6IGV4dGVuZEZsYXQoe30sIGhpc3RvZ3JhbUF0dHJzLmJpbmdyb3VwLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIHhiaW5ncm91cDogZXh0ZW5kRmxhdCh7fSwgaGlzdG9ncmFtQXR0cnMuYmluZ3JvdXAsIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgeWJpbmdyb3VwOiBleHRlbmRGbGF0KHt9LCBoaXN0b2dyYW1BdHRycy5iaW5ncm91cCwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuXG4gICAgICAgIHhnYXA6IGhlYXRtYXBBdHRycy54Z2FwLFxuICAgICAgICB5Z2FwOiBoZWF0bWFwQXR0cnMueWdhcCxcbiAgICAgICAgenNtb290aDogaGVhdG1hcEF0dHJzLnpzbW9vdGgsXG4gICAgICAgIHpob3ZlcmZvcm1hdDogaGVhdG1hcEF0dHJzLnpob3ZlcmZvcm1hdCxcbiAgICAgICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKHt9LCB7a2V5czogJ3onfSlcbiAgICB9LFxuICAgIGNvbG9yU2NhbGVBdHRycygnJywge2NMZXR0ZXI6ICd6JywgYXV0b0NvbG9yRGZsdDogZmFsc2V9KVxuKTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uL2hlYXRtYXAvYXR0cmlidXRlc1wiOjEwMDEsXCIuLi9oaXN0b2dyYW0vYXR0cmlidXRlc1wiOjEwMTksXCIuLi9oaXN0b2dyYW0vYmluX2F0dHJpYnV0ZXNcIjoxMDIxfV0sMTAzMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcblxudmFyIGJpbkZ1bmN0aW9ucyA9IF9kZXJlcV8oJy4uL2hpc3RvZ3JhbS9iaW5fZnVuY3Rpb25zJyk7XG52YXIgbm9ybUZ1bmN0aW9ucyA9IF9kZXJlcV8oJy4uL2hpc3RvZ3JhbS9ub3JtX2Z1bmN0aW9ucycpO1xudmFyIGRvQXZnID0gX2RlcmVxXygnLi4vaGlzdG9ncmFtL2F2ZXJhZ2UnKTtcbnZhciBnZXRCaW5TcGFuTGFiZWxSb3VuZCA9IF9kZXJlcV8oJy4uL2hpc3RvZ3JhbS9iaW5fbGFiZWxfdmFscycpO1xudmFyIGNhbGNBbGxBdXRvQmlucyA9IF9kZXJlcV8oJy4uL2hpc3RvZ3JhbS9jYWxjJykuY2FsY0FsbEF1dG9CaW5zO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIHhhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnhheGlzKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMpO1xuXG4gICAgdmFyIHhjYWxlbmRhciA9IHRyYWNlLnhjYWxlbmRhcjtcbiAgICB2YXIgeWNhbGVuZGFyID0gdHJhY2UueWNhbGVuZGFyO1xuICAgIHZhciB4cjJjID0gZnVuY3Rpb24odikgeyByZXR1cm4geGEucjJjKHYsIDAsIHhjYWxlbmRhcik7IH07XG4gICAgdmFyIHlyMmMgPSBmdW5jdGlvbih2KSB7IHJldHVybiB5YS5yMmModiwgMCwgeWNhbGVuZGFyKTsgfTtcbiAgICB2YXIgeGMyciA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHhhLmMycih2LCAwLCB4Y2FsZW5kYXIpOyB9O1xuICAgIHZhciB5YzJyID0gZnVuY3Rpb24odikgeyByZXR1cm4geWEuYzJyKHYsIDAsIHljYWxlbmRhcik7IH07XG5cbiAgICB2YXIgaSwgaiwgbiwgbTtcblxuICAgIC8vIGNhbGN1bGF0ZSB0aGUgYmluc1xuICAgIHZhciB4Qmluc0FuZFBvcyA9IGNhbGNBbGxBdXRvQmlucyhnZCwgdHJhY2UsIHhhLCAneCcpO1xuICAgIHZhciB4QmluU3BlYyA9IHhCaW5zQW5kUG9zWzBdO1xuICAgIHZhciB4UG9zMCA9IHhCaW5zQW5kUG9zWzFdO1xuICAgIHZhciB5Qmluc0FuZFBvcyA9IGNhbGNBbGxBdXRvQmlucyhnZCwgdHJhY2UsIHlhLCAneScpO1xuICAgIHZhciB5QmluU3BlYyA9IHlCaW5zQW5kUG9zWzBdO1xuICAgIHZhciB5UG9zMCA9IHlCaW5zQW5kUG9zWzFdO1xuXG4gICAgdmFyIHNlcmllc2xlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgaWYoeFBvczAubGVuZ3RoID4gc2VyaWVzbGVuKSB4UG9zMC5zcGxpY2Uoc2VyaWVzbGVuLCB4UG9zMC5sZW5ndGggLSBzZXJpZXNsZW4pO1xuICAgIGlmKHlQb3MwLmxlbmd0aCA+IHNlcmllc2xlbikgeVBvczAuc3BsaWNlKHNlcmllc2xlbiwgeVBvczAubGVuZ3RoIC0gc2VyaWVzbGVuKTtcblxuICAgIC8vIG1ha2UgdGhlIGVtcHR5IGJpbiBhcnJheSAmIHNjYWxlIHRoZSBtYXBcbiAgICB2YXIgeiA9IFtdO1xuICAgIHZhciBvbmVjb2wgPSBbXTtcbiAgICB2YXIgemVyb2NvbCA9IFtdO1xuICAgIHZhciBub251bmlmb3JtQmluc1ggPSB0eXBlb2YgeEJpblNwZWMuc2l6ZSA9PT0gJ3N0cmluZyc7XG4gICAgdmFyIG5vbnVuaWZvcm1CaW5zWSA9IHR5cGVvZiB5QmluU3BlYy5zaXplID09PSAnc3RyaW5nJztcbiAgICB2YXIgeEVkZ2VzID0gW107XG4gICAgdmFyIHlFZGdlcyA9IFtdO1xuICAgIHZhciB4YmlucyA9IG5vbnVuaWZvcm1CaW5zWCA/IHhFZGdlcyA6IHhCaW5TcGVjO1xuICAgIHZhciB5YmlucyA9IG5vbnVuaWZvcm1CaW5zWSA/IHlFZGdlcyA6IHlCaW5TcGVjO1xuICAgIHZhciB0b3RhbCA9IDA7XG4gICAgdmFyIGNvdW50cyA9IFtdO1xuICAgIHZhciBpbnB1dFBvaW50cyA9IFtdO1xuICAgIHZhciBub3JtID0gdHJhY2UuaGlzdG5vcm07XG4gICAgdmFyIGZ1bmMgPSB0cmFjZS5oaXN0ZnVuYztcbiAgICB2YXIgZGVuc2l0eW5vcm0gPSBub3JtLmluZGV4T2YoJ2RlbnNpdHknKSAhPT0gLTE7XG4gICAgdmFyIGV4dHJlbWVmdW5jID0gZnVuYyA9PT0gJ21heCcgfHwgZnVuYyA9PT0gJ21pbic7XG4gICAgdmFyIHNpemVpbml0ID0gZXh0cmVtZWZ1bmMgPyBudWxsIDogMDtcbiAgICB2YXIgYmluZnVuYyA9IGJpbkZ1bmN0aW9ucy5jb3VudDtcbiAgICB2YXIgbm9ybWZ1bmMgPSBub3JtRnVuY3Rpb25zW25vcm1dO1xuICAgIHZhciBkb2F2ZyA9IGZhbHNlO1xuICAgIHZhciB4aW5jID0gW107XG4gICAgdmFyIHlpbmMgPSBbXTtcblxuICAgIC8vIHNldCBhIGJpbm5pbmcgZnVuY3Rpb24gb3RoZXIgdGhhbiBjb3VudD9cbiAgICAvLyBmb3IgYmlubmluZyBmdW5jdGlvbnM6IGNoZWNrIGZpcnN0IGZvciAneicsXG4gICAgLy8gdGhlbiAnbWMnIGluIGNhc2Ugd2UgaGFkIGEgY29sb3JlZCBzY2F0dGVyIHBsb3RcbiAgICAvLyBhbmQgd2FudCB0byB0cmFuc2ZlciB0aGVzZSBjb2xvcnMgdG8gdGhlIDJEIGhpc3RvXG4gICAgLy8gVE9ETzogYXhlIHRoaXMsIG1ha2UgaXQgdGhlIHJlc3BvbnNpYmlsaXR5IG9mIHRoZSBhcHAgY2hhbmdpbmcgdHlwZT8gb3IgYW4gaW1wbGllZEVkaXQ/XG4gICAgdmFyIHJhd0NvdW50ZXJEYXRhID0gKCd6JyBpbiB0cmFjZSkgP1xuICAgICAgICB0cmFjZS56IDpcbiAgICAgICAgKCgnbWFya2VyJyBpbiB0cmFjZSAmJiBBcnJheS5pc0FycmF5KHRyYWNlLm1hcmtlci5jb2xvcikpID9cbiAgICAgICAgICAgIHRyYWNlLm1hcmtlci5jb2xvciA6ICcnKTtcbiAgICBpZihyYXdDb3VudGVyRGF0YSAmJiBmdW5jICE9PSAnY291bnQnKSB7XG4gICAgICAgIGRvYXZnID0gZnVuYyA9PT0gJ2F2Zyc7XG4gICAgICAgIGJpbmZ1bmMgPSBiaW5GdW5jdGlvbnNbZnVuY107XG4gICAgfVxuXG4gICAgLy8gZGVjcmVhc2UgZW5kIGEgbGl0dGxlIGluIGNhc2Ugb2Ygcm91bmRpbmcgZXJyb3JzXG4gICAgdmFyIHhCaW5TaXplID0geEJpblNwZWMuc2l6ZTtcbiAgICB2YXIgeEJpblN0YXJ0ID0geHIyYyh4QmluU3BlYy5zdGFydCk7XG4gICAgdmFyIHhCaW5FbmQgPSB4cjJjKHhCaW5TcGVjLmVuZCkgK1xuICAgICAgICAoeEJpblN0YXJ0IC0gQXhlcy50aWNrSW5jcmVtZW50KHhCaW5TdGFydCwgeEJpblNpemUsIGZhbHNlLCB4Y2FsZW5kYXIpKSAvIDFlNjtcblxuICAgIGZvcihpID0geEJpblN0YXJ0OyBpIDwgeEJpbkVuZDsgaSA9IEF4ZXMudGlja0luY3JlbWVudChpLCB4QmluU2l6ZSwgZmFsc2UsIHhjYWxlbmRhcikpIHtcbiAgICAgICAgb25lY29sLnB1c2goc2l6ZWluaXQpO1xuICAgICAgICB4RWRnZXMucHVzaChpKTtcbiAgICAgICAgaWYoZG9hdmcpIHplcm9jb2wucHVzaCgwKTtcbiAgICB9XG4gICAgeEVkZ2VzLnB1c2goaSk7XG5cbiAgICB2YXIgbnggPSBvbmVjb2wubGVuZ3RoO1xuICAgIHZhciBkeCA9IChpIC0geEJpblN0YXJ0KSAvIG54O1xuICAgIHZhciB4MCA9IHhjMnIoeEJpblN0YXJ0ICsgZHggLyAyKTtcblxuICAgIHZhciB5QmluU2l6ZSA9IHlCaW5TcGVjLnNpemU7XG4gICAgdmFyIHlCaW5TdGFydCA9IHlyMmMoeUJpblNwZWMuc3RhcnQpO1xuICAgIHZhciB5QmluRW5kID0geXIyYyh5QmluU3BlYy5lbmQpICtcbiAgICAgICAgKHlCaW5TdGFydCAtIEF4ZXMudGlja0luY3JlbWVudCh5QmluU3RhcnQsIHlCaW5TaXplLCBmYWxzZSwgeWNhbGVuZGFyKSkgLyAxZTY7XG5cbiAgICBmb3IoaSA9IHlCaW5TdGFydDsgaSA8IHlCaW5FbmQ7IGkgPSBBeGVzLnRpY2tJbmNyZW1lbnQoaSwgeUJpblNpemUsIGZhbHNlLCB5Y2FsZW5kYXIpKSB7XG4gICAgICAgIHoucHVzaChvbmVjb2wuc2xpY2UoKSk7XG4gICAgICAgIHlFZGdlcy5wdXNoKGkpO1xuICAgICAgICB2YXIgaXBDb2wgPSBuZXcgQXJyYXkobngpO1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBueDsgaisrKSBpcENvbFtqXSA9IFtdO1xuICAgICAgICBpbnB1dFBvaW50cy5wdXNoKGlwQ29sKTtcbiAgICAgICAgaWYoZG9hdmcpIGNvdW50cy5wdXNoKHplcm9jb2wuc2xpY2UoKSk7XG4gICAgfVxuICAgIHlFZGdlcy5wdXNoKGkpO1xuXG4gICAgdmFyIG55ID0gei5sZW5ndGg7XG4gICAgdmFyIGR5ID0gKGkgLSB5QmluU3RhcnQpIC8gbnk7XG4gICAgdmFyIHkwID0geWMycih5QmluU3RhcnQgKyBkeSAvIDIpO1xuXG4gICAgaWYoZGVuc2l0eW5vcm0pIHtcbiAgICAgICAgeGluYyA9IG1ha2VJbmNyZW1lbnRzKG9uZWNvbC5sZW5ndGgsIHhiaW5zLCBkeCwgbm9udW5pZm9ybUJpbnNYKTtcbiAgICAgICAgeWluYyA9IG1ha2VJbmNyZW1lbnRzKHoubGVuZ3RoLCB5YmlucywgZHksIG5vbnVuaWZvcm1CaW5zWSk7XG4gICAgfVxuXG4gICAgLy8gZm9yIGRhdGUgYXhlcyB3ZSBuZWVkIGJpbiBib3VuZHMgdG8gYmUgY2FsY2RhdGEuIEZvciBub251bmlmb3JtIGJpbnNcbiAgICAvLyB3ZSBhbHJlYWR5IGhhdmUgdGhpcywgYnV0IHVuaWZvcm0gd2l0aCBzdGFydC9lbmQvc2l6ZSB0aGV5J3JlIHN0aWxsIHN0cmluZ3MuXG4gICAgaWYoIW5vbnVuaWZvcm1CaW5zWCAmJiB4YS50eXBlID09PSAnZGF0ZScpIHhiaW5zID0gYmluc1RvQ2FsYyh4cjJjLCB4Ymlucyk7XG4gICAgaWYoIW5vbnVuaWZvcm1CaW5zWSAmJiB5YS50eXBlID09PSAnZGF0ZScpIHliaW5zID0gYmluc1RvQ2FsYyh5cjJjLCB5Ymlucyk7XG5cbiAgICAvLyBwdXQgZGF0YSBpbnRvIGJpbnNcbiAgICB2YXIgdW5pcXVlVmFsc1BlclggPSB0cnVlO1xuICAgIHZhciB1bmlxdWVWYWxzUGVyWSA9IHRydWU7XG4gICAgdmFyIHhWYWxzID0gbmV3IEFycmF5KG54KTtcbiAgICB2YXIgeVZhbHMgPSBuZXcgQXJyYXkobnkpO1xuICAgIHZhciB4R2FwTG93ID0gSW5maW5pdHk7XG4gICAgdmFyIHhHYXBIaWdoID0gSW5maW5pdHk7XG4gICAgdmFyIHlHYXBMb3cgPSBJbmZpbml0eTtcbiAgICB2YXIgeUdhcEhpZ2ggPSBJbmZpbml0eTtcbiAgICBmb3IoaSA9IDA7IGkgPCBzZXJpZXNsZW47IGkrKykge1xuICAgICAgICB2YXIgeGkgPSB4UG9zMFtpXTtcbiAgICAgICAgdmFyIHlpID0geVBvczBbaV07XG4gICAgICAgIG4gPSBMaWIuZmluZEJpbih4aSwgeGJpbnMpO1xuICAgICAgICBtID0gTGliLmZpbmRCaW4oeWksIHliaW5zKTtcbiAgICAgICAgaWYobiA+PSAwICYmIG4gPCBueCAmJiBtID49IDAgJiYgbSA8IG55KSB7XG4gICAgICAgICAgICB0b3RhbCArPSBiaW5mdW5jKG4sIGksIHpbbV0sIHJhd0NvdW50ZXJEYXRhLCBjb3VudHNbbV0pO1xuICAgICAgICAgICAgaW5wdXRQb2ludHNbbV1bbl0ucHVzaChpKTtcblxuICAgICAgICAgICAgaWYodW5pcXVlVmFsc1BlclgpIHtcbiAgICAgICAgICAgICAgICBpZih4VmFsc1tuXSA9PT0gdW5kZWZpbmVkKSB4VmFsc1tuXSA9IHhpO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYoeFZhbHNbbl0gIT09IHhpKSB1bmlxdWVWYWxzUGVyWCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYodW5pcXVlVmFsc1BlclkpIHtcbiAgICAgICAgICAgICAgICBpZih5VmFsc1ttXSA9PT0gdW5kZWZpbmVkKSB5VmFsc1ttXSA9IHlpO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYoeVZhbHNbbV0gIT09IHlpKSB1bmlxdWVWYWxzUGVyWSA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB4R2FwTG93ID0gTWF0aC5taW4oeEdhcExvdywgeGkgLSB4RWRnZXNbbl0pO1xuICAgICAgICAgICAgeEdhcEhpZ2ggPSBNYXRoLm1pbih4R2FwSGlnaCwgeEVkZ2VzW24gKyAxXSAtIHhpKTtcbiAgICAgICAgICAgIHlHYXBMb3cgPSBNYXRoLm1pbih5R2FwTG93LCB5aSAtIHlFZGdlc1ttXSk7XG4gICAgICAgICAgICB5R2FwSGlnaCA9IE1hdGgubWluKHlHYXBIaWdoLCB5RWRnZXNbbSArIDFdIC0geWkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIG5vcm1hbGl6ZSwgaWYgbmVlZGVkXG4gICAgaWYoZG9hdmcpIHtcbiAgICAgICAgZm9yKG0gPSAwOyBtIDwgbnk7IG0rKykgdG90YWwgKz0gZG9BdmcoelttXSwgY291bnRzW21dKTtcbiAgICB9XG4gICAgaWYobm9ybWZ1bmMpIHtcbiAgICAgICAgZm9yKG0gPSAwOyBtIDwgbnk7IG0rKykgbm9ybWZ1bmMoelttXSwgdG90YWwsIHhpbmMsIHlpbmNbbV0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHg6IHhQb3MwLFxuICAgICAgICB4UmFuZ2VzOiBnZXRSYW5nZXMoeEVkZ2VzLCB1bmlxdWVWYWxzUGVyWCAmJiB4VmFscywgeEdhcExvdywgeEdhcEhpZ2gsIHhhLCB4Y2FsZW5kYXIpLFxuICAgICAgICB4MDogeDAsXG4gICAgICAgIGR4OiBkeCxcbiAgICAgICAgeTogeVBvczAsXG4gICAgICAgIHlSYW5nZXM6IGdldFJhbmdlcyh5RWRnZXMsIHVuaXF1ZVZhbHNQZXJZICYmIHlWYWxzLCB5R2FwTG93LCB5R2FwSGlnaCwgeWEsIHljYWxlbmRhciksXG4gICAgICAgIHkwOiB5MCxcbiAgICAgICAgZHk6IGR5LFxuICAgICAgICB6OiB6LFxuICAgICAgICBwdHM6IGlucHV0UG9pbnRzXG4gICAgfTtcbn07XG5cbmZ1bmN0aW9uIG1ha2VJbmNyZW1lbnRzKGxlbiwgYmlucywgZHYsIG5vbnVuaWZvcm0pIHtcbiAgICB2YXIgb3V0ID0gbmV3IEFycmF5KGxlbik7XG4gICAgdmFyIGk7XG4gICAgaWYobm9udW5pZm9ybSkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykgb3V0W2ldID0gMSAvIChiaW5zW2kgKyAxXSAtIGJpbnNbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBpbmMgPSAxIC8gZHY7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSBvdXRbaV0gPSBpbmM7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGJpbnNUb0NhbGMocjJjLCBiaW5zKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IHIyYyhiaW5zLnN0YXJ0KSxcbiAgICAgICAgZW5kOiByMmMoYmlucy5lbmQpLFxuICAgICAgICBzaXplOiBiaW5zLnNpemVcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBnZXRSYW5nZXMoZWRnZXMsIHVuaXF1ZVZhbHMsIGdhcExvdywgZ2FwSGlnaCwgYXgsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGk7XG4gICAgdmFyIGxlbiA9IGVkZ2VzLmxlbmd0aCAtIDE7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgIHZhciByb3VuZEZuID0gZ2V0QmluU3BhbkxhYmVsUm91bmQoZ2FwTG93LCBnYXBIaWdoLCBlZGdlcywgYXgsIGNhbGVuZGFyKTtcblxuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciB2ID0gKHVuaXF1ZVZhbHMgfHwgW10pW2ldO1xuICAgICAgICBvdXRbaV0gPSB2ID09PSB1bmRlZmluZWQgP1xuICAgICAgICAgICAgW3JvdW5kRm4oZWRnZXNbaV0pLCByb3VuZEZuKGVkZ2VzW2kgKyAxXSwgdHJ1ZSldIDpcbiAgICAgICAgICAgIFt2LCB2XTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL2hpc3RvZ3JhbS9hdmVyYWdlXCI6MTAyMCxcIi4uL2hpc3RvZ3JhbS9iaW5fZnVuY3Rpb25zXCI6MTAyMixcIi4uL2hpc3RvZ3JhbS9iaW5fbGFiZWxfdmFsc1wiOjEwMjMsXCIuLi9oaXN0b2dyYW0vY2FsY1wiOjEwMjQsXCIuLi9oaXN0b2dyYW0vbm9ybV9mdW5jdGlvbnNcIjoxMDMxfV0sMTAzNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgaGFuZGxlU2FtcGxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuL3NhbXBsZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVN0eWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9oZWF0bWFwL3N0eWxlX2RlZmF1bHRzJyk7XG52YXIgY29sb3JzY2FsZURlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGhhbmRsZVNhbXBsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgaWYodHJhY2VPdXQudmlzaWJsZSA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIGhhbmRsZVN0eWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KTtcbiAgICBjb2xvcnNjYWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnJywgY0xldHRlcjogJ3onfSk7XG4gICAgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0c1wiOjYwMyxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2hlYXRtYXAvc3R5bGVfZGVmYXVsdHNcIjoxMDE0LFwiLi9hdHRyaWJ1dGVzXCI6MTAzMixcIi4vc2FtcGxlX2RlZmF1bHRzXCI6MTAzN31dLDEwMzU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoZWF0bWFwSG92ZXIgPSBfZGVyZXFfKCcuLi9oZWF0bWFwL2hvdmVyJyk7XG52YXIgaG92ZXJMYWJlbFRleHQgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpLmhvdmVyTGFiZWxUZXh0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlLCBob3ZlckxheWVyLCBjb250b3VyKSB7XG4gICAgdmFyIHB0cyA9IGhlYXRtYXBIb3Zlcihwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSwgaG92ZXJMYXllciwgY29udG91cik7XG5cbiAgICBpZighcHRzKSByZXR1cm47XG5cbiAgICBwb2ludERhdGEgPSBwdHNbMF07XG4gICAgdmFyIGluZGljZXMgPSBwb2ludERhdGEuaW5kZXg7XG4gICAgdmFyIG55ID0gaW5kaWNlc1swXTtcbiAgICB2YXIgbnggPSBpbmRpY2VzWzFdO1xuICAgIHZhciBjZDAgPSBwb2ludERhdGEuY2RbMF07XG4gICAgdmFyIHhSYW5nZSA9IGNkMC54UmFuZ2VzW254XTtcbiAgICB2YXIgeVJhbmdlID0gY2QwLnlSYW5nZXNbbnldO1xuXG4gICAgcG9pbnREYXRhLnhMYWJlbCA9IGhvdmVyTGFiZWxUZXh0KHBvaW50RGF0YS54YSwgeFJhbmdlWzBdLCB4UmFuZ2VbMV0pO1xuICAgIHBvaW50RGF0YS55TGFiZWwgPSBob3ZlckxhYmVsVGV4dChwb2ludERhdGEueWEsIHlSYW5nZVswXSwgeVJhbmdlWzFdKTtcblxuICAgIHJldHVybiBwdHM7XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vaGVhdG1hcC9ob3ZlclwiOjEwMDh9XSwxMDM2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNyb3NzVHJhY2VEZWZhdWx0czogX2RlcmVxXygnLi4vaGlzdG9ncmFtL2Nyb3NzX3RyYWNlX2RlZmF1bHRzJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi4vaGVhdG1hcC9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi4vaGVhdG1hcC9wbG90JyksXG4gICAgbGF5ZXJOYW1lOiAnaGVhdG1hcGxheWVyJyxcbiAgICBjb2xvcmJhcjogX2RlcmVxXygnLi4vaGVhdG1hcC9jb2xvcmJhcicpLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuLi9oZWF0bWFwL3N0eWxlJyksXG4gICAgaG92ZXJQb2ludHM6IF9kZXJlcV8oJy4vaG92ZXInKSxcbiAgICBldmVudERhdGE6IF9kZXJlcV8oJy4uL2hpc3RvZ3JhbS9ldmVudF9kYXRhJyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdoaXN0b2dyYW0yZCcsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnY2FydGVzaWFuJywgJ3N2ZycsICcyZE1hcCcsICdoaXN0b2dyYW0nXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhblwiOjc3OCxcIi4uL2hlYXRtYXAvY2FsY1wiOjEwMDIsXCIuLi9oZWF0bWFwL2NvbG9yYmFyXCI6MTAwNCxcIi4uL2hlYXRtYXAvcGxvdFwiOjEwMTIsXCIuLi9oZWF0bWFwL3N0eWxlXCI6MTAxMyxcIi4uL2hpc3RvZ3JhbS9jcm9zc190cmFjZV9kZWZhdWx0c1wiOjEwMjYsXCIuLi9oaXN0b2dyYW0vZXZlbnRfZGF0YVwiOjEwMjgsXCIuL2F0dHJpYnV0ZXNcIjoxMDMyLFwiLi9kZWZhdWx0c1wiOjEwMzQsXCIuL2hvdmVyXCI6MTAzNX1dLDEwMzc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZVNhbXBsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCkge1xuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIHkgPSBjb2VyY2UoJ3knKTtcbiAgICB2YXIgeGxlbiA9IExpYi5taW5Sb3dMZW5ndGgoeCk7XG4gICAgdmFyIHlsZW4gPSBMaWIubWluUm93TGVuZ3RoKHkpO1xuXG4gICAgLy8gd2UgY291bGQgdHJ5IHRvIGFjY2VwdCB4MCBhbmQgZHgsIGV0Yy4uLlxuICAgIC8vIGJ1dCB0aGF0J3MgYSBwcmV0dHkgd2VpcmQgdXNlIGNhc2UuXG4gICAgLy8gZm9yIG5vdyByZXF1aXJlIGJvdGggeCBhbmQgeSBleHBsaWNpdGx5IHNwZWNpZmllZC5cbiAgICBpZigheGxlbiB8fCAheWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gTWF0aC5taW4oeGxlbiwgeWxlbik7XG5cbiAgICB2YXIgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2hhbmRsZVRyYWNlRGVmYXVsdHMnKTtcbiAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBbJ3gnLCAneSddLCBsYXlvdXQpO1xuXG4gICAgLy8gaWYgbWFya2VyLmNvbG9yIGlzIGFuIGFycmF5LCB3ZSBjYW4gdXNlIGl0IGluIGFnZ3JlZ2F0aW9uIGluc3RlYWQgb2YgelxuICAgIHZhciBoYXNBZ2dyZWdhdGlvbkRhdGEgPSBjb2VyY2UoJ3onKSB8fCBjb2VyY2UoJ21hcmtlci5jb2xvcicpO1xuXG4gICAgaWYoaGFzQWdncmVnYXRpb25EYXRhKSBjb2VyY2UoJ2hpc3RmdW5jJyk7XG4gICAgY29lcmNlKCdoaXN0bm9ybScpO1xuXG4gICAgLy8gTm90ZTogYmluIGRlZmF1bHRzIGFyZSBub3cgaGFuZGxlZCBpbiBIaXN0b2dyYW0yRC5jcm9zc1RyYWNlRGVmYXVsdHNcbiAgICAvLyBhdXRvYmluKHh8eSkgYXJlIG9ubHkgaW5jbHVkZWQgaGVyZSB0byBhcHBlYXNlIFBsb3RseS52YWxpZGF0ZVxuICAgIGNvZXJjZSgnYXV0b2JpbngnKTtcbiAgICBjb2VyY2UoJ2F1dG9iaW55Jyk7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3fV0sMTAzODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoaXN0b2dyYW0yZEF0dHJzID0gX2RlcmVxXygnLi4vaGlzdG9ncmFtMmQvYXR0cmlidXRlcycpO1xudmFyIGNvbnRvdXJBdHRycyA9IF9kZXJlcV8oJy4uL2NvbnRvdXIvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZXh0ZW5kRmxhdCh7XG4gICAgeDogaGlzdG9ncmFtMmRBdHRycy54LFxuICAgIHk6IGhpc3RvZ3JhbTJkQXR0cnMueSxcbiAgICB6OiBoaXN0b2dyYW0yZEF0dHJzLnosXG4gICAgbWFya2VyOiBoaXN0b2dyYW0yZEF0dHJzLm1hcmtlcixcblxuICAgIGhpc3Rub3JtOiBoaXN0b2dyYW0yZEF0dHJzLmhpc3Rub3JtLFxuICAgIGhpc3RmdW5jOiBoaXN0b2dyYW0yZEF0dHJzLmhpc3RmdW5jLFxuICAgIG5iaW5zeDogaGlzdG9ncmFtMmRBdHRycy5uYmluc3gsXG4gICAgeGJpbnM6IGhpc3RvZ3JhbTJkQXR0cnMueGJpbnMsXG4gICAgbmJpbnN5OiBoaXN0b2dyYW0yZEF0dHJzLm5iaW5zeSxcbiAgICB5YmluczogaGlzdG9ncmFtMmRBdHRycy55YmlucyxcbiAgICBhdXRvYmlueDogaGlzdG9ncmFtMmRBdHRycy5hdXRvYmlueCxcbiAgICBhdXRvYmlueTogaGlzdG9ncmFtMmRBdHRycy5hdXRvYmlueSxcblxuICAgIGJpbmdyb3VwOiBoaXN0b2dyYW0yZEF0dHJzLmJpbmdyb3VwLFxuICAgIHhiaW5ncm91cDogaGlzdG9ncmFtMmRBdHRycy54YmluZ3JvdXAsXG4gICAgeWJpbmdyb3VwOiBoaXN0b2dyYW0yZEF0dHJzLnliaW5ncm91cCxcblxuICAgIGF1dG9jb250b3VyOiBjb250b3VyQXR0cnMuYXV0b2NvbnRvdXIsXG4gICAgbmNvbnRvdXJzOiBjb250b3VyQXR0cnMubmNvbnRvdXJzLFxuICAgIGNvbnRvdXJzOiBjb250b3VyQXR0cnMuY29udG91cnMsXG4gICAgbGluZTogY29udG91ckF0dHJzLmxpbmUsXG4gICAgemhvdmVyZm9ybWF0OiBoaXN0b2dyYW0yZEF0dHJzLnpob3ZlcmZvcm1hdCxcbiAgICBob3ZlcnRlbXBsYXRlOiBoaXN0b2dyYW0yZEF0dHJzLmhvdmVydGVtcGxhdGVcbn0sXG4gICAgY29sb3JTY2FsZUF0dHJzKCcnLCB7XG4gICAgICAgIGNMZXR0ZXI6ICd6JyxcbiAgICAgICAgZWRpdFR5cGVPdmVycmlkZTogJ2NhbGMnXG4gICAgfSlcbik7XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXNcIjo2MDAsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vY29udG91ci9hdHRyaWJ1dGVzXCI6OTQyLFwiLi4vaGlzdG9ncmFtMmQvYXR0cmlidXRlc1wiOjEwMzJ9XSwxMDM5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBoYW5kbGVTYW1wbGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL2hpc3RvZ3JhbTJkL3NhbXBsZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUNvbnRvdXJzRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9jb250b3VyL2NvbnRvdXJzX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlU3R5bGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL2NvbnRvdXIvc3R5bGVfZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29lcmNlMihhdHRyKSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlMih0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0cik7XG4gICAgfVxuXG4gICAgaGFuZGxlU2FtcGxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwgbGF5b3V0KTtcbiAgICBpZih0cmFjZU91dC52aXNpYmxlID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgaGFuZGxlQ29udG91cnNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBjb2VyY2UyKTtcbiAgICBoYW5kbGVTdHlsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2NvbnRvdXIvY29udG91cnNfZGVmYXVsdHNcIjo5NDksXCIuLi9jb250b3VyL3N0eWxlX2RlZmF1bHRzXCI6OTYzLFwiLi4vaGlzdG9ncmFtMmQvc2FtcGxlX2RlZmF1bHRzXCI6MTAzNyxcIi4vYXR0cmlidXRlc1wiOjEwMzh9XSwxMDQwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjcm9zc1RyYWNlRGVmYXVsdHM6IF9kZXJlcV8oJy4uL2hpc3RvZ3JhbS9jcm9zc190cmFjZV9kZWZhdWx0cycpLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4uL2NvbnRvdXIvY2FsYycpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4uL2NvbnRvdXIvcGxvdCcpLnBsb3QsXG4gICAgbGF5ZXJOYW1lOiAnY29udG91cmxheWVyJyxcbiAgICBzdHlsZTogX2RlcmVxXygnLi4vY29udG91ci9zdHlsZScpLFxuICAgIGNvbG9yYmFyOiBfZGVyZXFfKCcuLi9jb250b3VyL2NvbG9yYmFyJyksXG4gICAgaG92ZXJQb2ludHM6IF9kZXJlcV8oJy4uL2NvbnRvdXIvaG92ZXInKSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ2hpc3RvZ3JhbTJkY29udG91cicsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnY2FydGVzaWFuJywgJ3N2ZycsICcyZE1hcCcsICdjb250b3VyJywgJ2hpc3RvZ3JhbScsICdzaG93TGVnZW5kJ10sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW5cIjo3NzgsXCIuLi9jb250b3VyL2NhbGNcIjo5NDMsXCIuLi9jb250b3VyL2NvbG9yYmFyXCI6OTQ1LFwiLi4vY29udG91ci9ob3ZlclwiOjk1NSxcIi4uL2NvbnRvdXIvcGxvdFwiOjk2MCxcIi4uL2NvbnRvdXIvc3R5bGVcIjo5NjIsXCIuLi9oaXN0b2dyYW0vY3Jvc3NfdHJhY2VfZGVmYXVsdHNcIjoxMDI2LFwiLi9hdHRyaWJ1dGVzXCI6MTAzOCxcIi4vZGVmYXVsdHNcIjoxMDM5fV0sMTA0MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgZXh0ZW5kRGVlcCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmREZWVwO1xudmFyIG92ZXJyaWRlQWxsID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xudmFyIGZvbnRBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGNvbG9yQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXMnKTtcbnZhciBkb21haW5BdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2RvbWFpbicpLmF0dHJpYnV0ZXM7XG52YXIgYXhlc0F0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgdGVtcGxhdGVkQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJykudGVtcGxhdGVkQXJyYXk7XG52YXIgZGVsdGEgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvZGVsdGEuanMnKTtcbnZhciBGT1JNQVRfTElOSyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9kb2NzJykuRk9STUFUX0xJTks7XG5cbnZhciB0ZXh0Rm9udEF0dHJzID0gZm9udEF0dHJzKHtcbiAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgIGNvbG9yRWRpdFR5cGU6ICdwbG90J1xufSk7XG5cbnZhciBnYXVnZUJhckF0dHJzID0ge1xuICAgIGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IGNvbG9yQXR0cnMuZGVmYXVsdExpbmUsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgdGhpY2tuZXNzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufTtcblxudmFyIHJhbmdlQXR0ciA9IHtcbiAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgXG4gICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnbnVtYmVyJywgZWRpdFR5cGU6ICdwbG90J30sXG4gICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIGVkaXRUeXBlOiAncGxvdCd9XG4gICAgXSxcbiAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgIFxufTtcblxudmFyIHN0ZXBzQXR0cnMgPSB0ZW1wbGF0ZWRBcnJheSgnc3RlcHMnLCBleHRlbmREZWVwKHt9LCBnYXVnZUJhckF0dHJzLCB7XG4gICAgcmFuZ2U6IHJhbmdlQXR0clxufSkpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdmbGFnbGlzdCcsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgICAgICBmbGFnczogWydudW1iZXInLCAnZGVsdGEnLCAnZ2F1Z2UnXSxcbiAgICAgICAgZGZsdDogJ251bWJlcicsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmFsdWU6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGFsaWduOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2xlZnQnLCAnY2VudGVyJywgJ3JpZ2h0J10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIC8vIHBvc2l0aW9uXG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ2luZGljYXRvcicsIHRyYWNlOiB0cnVlLCBlZGl0VHlwZTogJ2NhbGMnfSksXG5cbiAgICB0aXRsZToge1xuICAgICAgICB0ZXh0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBhbGlnbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2xlZnQnLCAnY2VudGVyJywgJ3JpZ2h0J10sXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZm9udDogZXh0ZW5kRmxhdCh7fSwgdGV4dEZvbnRBdHRycywge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICBudW1iZXI6IHtcbiAgICAgICAgdmFsdWVmb3JtYXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGZsdDogJycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZm9udDogZXh0ZW5kRmxhdCh7fSwgdGV4dEZvbnRBdHRycywge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBwcmVmaXg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGZsdDogJycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc3VmZml4OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuICAgIGRlbHRhOiB7XG4gICAgICAgIHJlZmVyZW5jZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgcG9zaXRpb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWyd0b3AnLCAnYm90dG9tJywgJ2xlZnQnLCAncmlnaHQnXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogJ2JvdHRvbScsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHJlbGF0aXZlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB2YWx1ZWZvcm1hdDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgaW5jcmVhc2luZzoge1xuICAgICAgICAgICAgc3ltYm9sOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZGZsdDogZGVsdGEuSU5DUkVBU0lORy5TWU1CT0wsXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZGZsdDogZGVsdGEuSU5DUkVBU0lORy5DT0xPUixcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIC8vIFRPRE86IGFkZCBhdHRyaWJ1dGUgdG8gc2hvdyBzaWduXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgICAgIH0sXG4gICAgICAgIGRlY3JlYXNpbmc6IHtcbiAgICAgICAgICAgIHN5bWJvbDoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGRmbHQ6IGRlbHRhLkRFQ1JFQVNJTkcuU1lNQk9MLFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGRmbHQ6IGRlbHRhLkRFQ1JFQVNJTkcuQ09MT1IsXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAvLyBUT0RPOiBhZGQgYXR0cmlidXRlIHRvIGhpZGUgc2lnblxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICB9LFxuICAgICAgICBmb250OiBleHRlbmRGbGF0KHt9LCB0ZXh0Rm9udEF0dHJzLCB7XG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgIGdhdWdlOiB7XG4gICAgICAgIHNoYXBlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiAnYW5ndWxhcicsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnYW5ndWxhcicsICdidWxsZXQnXSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBiYXI6IGV4dGVuZERlZXAoe30sIGdhdWdlQmFyQXR0cnMsIHtcbiAgICAgICAgICAgIGNvbG9yOiB7ZGZsdDogJ2dyZWVuJ30sXG4gICAgICAgICAgICBcbiAgICAgICAgfSksXG4gICAgICAgIC8vIEJhY2tncm91bmQgb2YgdGhlIGdhdWdlXG4gICAgICAgIGJnY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgYm9yZGVyY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGJvcmRlcndpZHRoOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgYXhpczogb3ZlcnJpZGVBbGwoe1xuICAgICAgICAgICAgcmFuZ2U6IHJhbmdlQXR0cixcbiAgICAgICAgICAgIHZpc2libGU6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy52aXNpYmxlLCB7XG4gICAgICAgICAgICAgICAgZGZsdDogdHJ1ZVxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAvLyB0aWNrIGFuZCB0aXRsZSBwcm9wZXJ0aWVzIG5hbWVkIGFuZCBmdW5jdGlvbiBleGFjdGx5IGFzIGluIGF4ZXNcbiAgICAgICAgICAgIHRpY2ttb2RlOiBheGVzQXR0cnMudGlja21vZGUsXG4gICAgICAgICAgICBudGlja3M6IGF4ZXNBdHRycy5udGlja3MsXG4gICAgICAgICAgICB0aWNrMDogYXhlc0F0dHJzLnRpY2swLFxuICAgICAgICAgICAgZHRpY2s6IGF4ZXNBdHRycy5kdGljayxcbiAgICAgICAgICAgIHRpY2t2YWxzOiBheGVzQXR0cnMudGlja3ZhbHMsXG4gICAgICAgICAgICB0aWNrdGV4dDogYXhlc0F0dHJzLnRpY2t0ZXh0LFxuICAgICAgICAgICAgdGlja3M6IGV4dGVuZEZsYXQoe30sIGF4ZXNBdHRycy50aWNrcywge2RmbHQ6ICdvdXRzaWRlJ30pLFxuICAgICAgICAgICAgdGlja2xlbjogYXhlc0F0dHJzLnRpY2tsZW4sXG4gICAgICAgICAgICB0aWNrd2lkdGg6IGF4ZXNBdHRycy50aWNrd2lkdGgsXG4gICAgICAgICAgICB0aWNrY29sb3I6IGF4ZXNBdHRycy50aWNrY29sb3IsXG4gICAgICAgICAgICBzaG93dGlja2xhYmVsczogYXhlc0F0dHJzLnNob3d0aWNrbGFiZWxzLFxuICAgICAgICAgICAgdGlja2ZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIHRpY2thbmdsZTogYXhlc0F0dHJzLnRpY2thbmdsZSxcbiAgICAgICAgICAgIHRpY2tmb3JtYXQ6IGF4ZXNBdHRycy50aWNrZm9ybWF0LFxuICAgICAgICAgICAgdGlja2Zvcm1hdHN0b3BzOiBheGVzQXR0cnMudGlja2Zvcm1hdHN0b3BzLFxuICAgICAgICAgICAgdGlja3ByZWZpeDogYXhlc0F0dHJzLnRpY2twcmVmaXgsXG4gICAgICAgICAgICBzaG93dGlja3ByZWZpeDogYXhlc0F0dHJzLnNob3d0aWNrcHJlZml4LFxuICAgICAgICAgICAgdGlja3N1ZmZpeDogYXhlc0F0dHJzLnRpY2tzdWZmaXgsXG4gICAgICAgICAgICBzaG93dGlja3N1ZmZpeDogYXhlc0F0dHJzLnNob3d0aWNrc3VmZml4LFxuICAgICAgICAgICAgc2VwYXJhdGV0aG91c2FuZHM6IGF4ZXNBdHRycy5zZXBhcmF0ZXRob3VzYW5kcyxcbiAgICAgICAgICAgIGV4cG9uZW50Zm9ybWF0OiBheGVzQXR0cnMuZXhwb25lbnRmb3JtYXQsXG4gICAgICAgICAgICBzaG93ZXhwb25lbnQ6IGF4ZXNBdHRycy5zaG93ZXhwb25lbnQsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgICAgIH0sICdwbG90JyksXG4gICAgICAgIC8vIFN0ZXBzIChvciByYW5nZXMpIGFuZCB0aHJlc2hvbGRzXG4gICAgICAgIHN0ZXBzOiBzdGVwc0F0dHJzLFxuICAgICAgICB0aHJlc2hvbGQ6IHtcbiAgICAgICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgICAgICBjb2xvcjogZXh0ZW5kRmxhdCh7fSwgZ2F1Z2VCYXJBdHRycy5saW5lLmNvbG9yLCB7XG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBnYXVnZUJhckF0dHJzLmxpbmUud2lkdGgsIHtcbiAgICAgICAgICAgICAgICAgICAgZGZsdDogMSxcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaWNrbmVzczogZXh0ZW5kRmxhdCh7fSwgZ2F1Z2VCYXJBdHRycy50aGlja25lc3MsIHtcbiAgICAgICAgICAgICAgICBkZmx0OiAwLjg1LFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICB9LFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICAvLyBUT0RPOiBpbiBmdXR1cmUgdmVyc2lvbiwgYWRkIG1hcmtlcjogKGJhcnxuZWVkbGUpXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yL2F0dHJpYnV0ZXNcIjo1OTIsXCIuLi8uLi9jb25zdGFudHMvZGVsdGEuanNcIjo2ODksXCIuLi8uLi9jb25zdGFudHMvZG9jc1wiOjY5MCxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlc1wiOjc3OSxcIi4uLy4uL3Bsb3RzL2RvbWFpblwiOjc5MixcIi4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlc1wiOjc5M31dLDEwNDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIGdldE1vZHVsZUNhbGNEYXRhID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRNb2R1bGVDYWxjRGF0YTtcblxudmFyIG5hbWUgPSBleHBvcnRzLm5hbWUgPSAnaW5kaWNhdG9yJztcblxuZXhwb3J0cy5wbG90ID0gZnVuY3Rpb24oZ2QsIHRyYWNlcywgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICB2YXIgX21vZHVsZSA9IFJlZ2lzdHJ5LmdldE1vZHVsZShuYW1lKTtcbiAgICB2YXIgY2Rtb2R1bGUgPSBnZXRNb2R1bGVDYWxjRGF0YShnZC5jYWxjZGF0YSwgX21vZHVsZSlbMF07XG4gICAgX21vZHVsZS5wbG90KGdkLCBjZG1vZHVsZSwgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spO1xufTtcblxuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBoYWQgPSAob2xkRnVsbExheW91dC5faGFzICYmIG9sZEZ1bGxMYXlvdXQuX2hhcyhuYW1lKSk7XG4gICAgdmFyIGhhcyA9IChuZXdGdWxsTGF5b3V0Ll9oYXMgJiYgbmV3RnVsbExheW91dC5faGFzKG5hbWUpKTtcblxuICAgIGlmKGhhZCAmJiAhaGFzKSB7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX2luZGljYXRvcmxheWVyLnNlbGVjdEFsbCgnZy50cmFjZScpLnJlbW92ZSgpO1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvZ2V0X2RhdGFcIjo4MDIsXCIuLi8uLi9yZWdpc3RyeVwiOjg0N31dLDEwNDM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vLyB2YXIgTGliID0gcmVxdWlyZSgnLi4vLi4vbGliJyk7XG5cbmZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGNkID0gW107XG5cbiAgICB2YXIgbGFzdFJlYWRpbmcgPSB0cmFjZS52YWx1ZTtcbiAgICBpZighKHR5cGVvZiB0cmFjZS5fbGFzdFZhbHVlID09PSAnbnVtYmVyJykpIHRyYWNlLl9sYXN0VmFsdWUgPSB0cmFjZS52YWx1ZTtcbiAgICB2YXIgc2Vjb25kTGFzdFJlYWRpbmcgPSB0cmFjZS5fbGFzdFZhbHVlO1xuICAgIHZhciBkZWx0YVJlZiA9IHNlY29uZExhc3RSZWFkaW5nO1xuICAgIGlmKHRyYWNlLl9oYXNEZWx0YSAmJiB0eXBlb2YgdHJhY2UuZGVsdGEucmVmZXJlbmNlID09PSAnbnVtYmVyJykge1xuICAgICAgICBkZWx0YVJlZiA9IHRyYWNlLmRlbHRhLnJlZmVyZW5jZTtcbiAgICB9XG4gICAgY2RbMF0gPSB7XG4gICAgICAgIHk6IGxhc3RSZWFkaW5nLFxuICAgICAgICBsYXN0WTogc2Vjb25kTGFzdFJlYWRpbmcsXG5cbiAgICAgICAgZGVsdGE6IGxhc3RSZWFkaW5nIC0gZGVsdGFSZWYsXG4gICAgICAgIHJlbGF0aXZlRGVsdGE6IChsYXN0UmVhZGluZyAtIGRlbHRhUmVmKSAvIGRlbHRhUmVmLFxuICAgIH07XG4gICAgcmV0dXJuIGNkO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjYWxjOiBjYWxjXG59O1xuXG59LHt9XSwxMDQ0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgLy8gRGVmYXVsdHMgZm9yIGRlbHRhXG4gICAgZGVmYXVsdE51bWJlckZvbnRTaXplOiA4MCxcbiAgICBidWxsZXROdW1iZXJEb21haW5TaXplOiAwLjI1LFxuICAgIGJ1bGxldFBhZGRpbmc6IDAuMDI1LFxuICAgIGlubmVyUmFkaXVzOiAwLjc1LFxuICAgIHZhbHVlVGhpY2tuZXNzOiAwLjUsIC8vIHRoaWNrbmVzcyBvZiB2YWx1ZSBiYXJzIHJlbGF0aXZlIHRvIGZ1bGwgdGhpY2tuZXNzLFxuICAgIHRpdGxlUGFkZGluZzogNSxcbiAgICBob3Jpem9udGFsUGFkZGluZzogMTBcbn07XG5cbn0se31dLDEwNDU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZURvbWFpbkRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZG9tYWluJykuZGVmYXVsdHM7XG52YXIgVGVtcGxhdGUgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlJyk7XG52YXIgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0cycpO1xudmFyIGNuID0gX2RlcmVxXygnLi9jb25zdGFudHMuanMnKTtcblxudmFyIGhhbmRsZVRpY2tWYWx1ZURlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfdmFsdWVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUaWNrTWFya0RlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfbWFya19kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRpY2tMYWJlbERlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfbGFiZWxfZGVmYXVsdHMnKTtcblxuZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGhhbmRsZURvbWFpbkRlZmF1bHRzKHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICAvLyBNb2RlXG4gICAgY29lcmNlKCdtb2RlJyk7XG4gICAgdHJhY2VPdXQuX2hhc051bWJlciA9IHRyYWNlT3V0Lm1vZGUuaW5kZXhPZignbnVtYmVyJykgIT09IC0xO1xuICAgIHRyYWNlT3V0Ll9oYXNEZWx0YSA9IHRyYWNlT3V0Lm1vZGUuaW5kZXhPZignZGVsdGEnKSAhPT0gLTE7XG4gICAgdHJhY2VPdXQuX2hhc0dhdWdlID0gdHJhY2VPdXQubW9kZS5pbmRleE9mKCdnYXVnZScpICE9PSAtMTtcblxuICAgIHZhciB2YWx1ZSA9IGNvZXJjZSgndmFsdWUnKTtcbiAgICB0cmFjZU91dC5fcmFuZ2UgPSBbMCwgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgPyAxLjUgKiB2YWx1ZSA6IDEpXTtcblxuICAgIC8vIE51bWJlciBhdHRyaWJ1dGVzXG4gICAgdmFyIGF1dG8gPSBuZXcgQXJyYXkoMik7XG4gICAgdmFyIGJpZ251bWJlckZvbnRTaXplO1xuICAgIGlmKHRyYWNlT3V0Ll9oYXNOdW1iZXIpIHtcbiAgICAgICAgY29lcmNlKCdudW1iZXIudmFsdWVmb3JtYXQnKTtcbiAgICAgICAgY29lcmNlKCdudW1iZXIuZm9udC5jb2xvcicsIGxheW91dC5mb250LmNvbG9yKTtcbiAgICAgICAgY29lcmNlKCdudW1iZXIuZm9udC5mYW1pbHknLCBsYXlvdXQuZm9udC5mYW1pbHkpO1xuICAgICAgICBjb2VyY2UoJ251bWJlci5mb250LnNpemUnKTtcbiAgICAgICAgaWYodHJhY2VPdXQubnVtYmVyLmZvbnQuc2l6ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0cmFjZU91dC5udW1iZXIuZm9udC5zaXplID0gY24uZGVmYXVsdE51bWJlckZvbnRTaXplO1xuICAgICAgICAgICAgYXV0b1swXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgY29lcmNlKCdudW1iZXIucHJlZml4Jyk7XG4gICAgICAgIGNvZXJjZSgnbnVtYmVyLnN1ZmZpeCcpO1xuICAgICAgICBiaWdudW1iZXJGb250U2l6ZSA9IHRyYWNlT3V0Lm51bWJlci5mb250LnNpemU7XG4gICAgfVxuXG4gICAgLy8gZGVsdGEgYXR0cmlidXRlc1xuICAgIHZhciBkZWx0YUZvbnRTaXplO1xuICAgIGlmKHRyYWNlT3V0Ll9oYXNEZWx0YSkge1xuICAgICAgICBjb2VyY2UoJ2RlbHRhLmZvbnQuY29sb3InLCBsYXlvdXQuZm9udC5jb2xvcik7XG4gICAgICAgIGNvZXJjZSgnZGVsdGEuZm9udC5mYW1pbHknLCBsYXlvdXQuZm9udC5mYW1pbHkpO1xuICAgICAgICBjb2VyY2UoJ2RlbHRhLmZvbnQuc2l6ZScpO1xuICAgICAgICBpZih0cmFjZU91dC5kZWx0YS5mb250LnNpemUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdHJhY2VPdXQuZGVsdGEuZm9udC5zaXplID0gKHRyYWNlT3V0Ll9oYXNOdW1iZXIgPyAwLjUgOiAxKSAqIChiaWdudW1iZXJGb250U2l6ZSB8fCBjbi5kZWZhdWx0TnVtYmVyRm9udFNpemUpO1xuICAgICAgICAgICAgYXV0b1sxXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgY29lcmNlKCdkZWx0YS5yZWZlcmVuY2UnLCB0cmFjZU91dC52YWx1ZSk7XG4gICAgICAgIGNvZXJjZSgnZGVsdGEucmVsYXRpdmUnKTtcbiAgICAgICAgY29lcmNlKCdkZWx0YS52YWx1ZWZvcm1hdCcsIHRyYWNlT3V0LmRlbHRhLnJlbGF0aXZlID8gJzIlJyA6ICcnKTtcbiAgICAgICAgY29lcmNlKCdkZWx0YS5pbmNyZWFzaW5nLnN5bWJvbCcpO1xuICAgICAgICBjb2VyY2UoJ2RlbHRhLmluY3JlYXNpbmcuY29sb3InKTtcbiAgICAgICAgY29lcmNlKCdkZWx0YS5kZWNyZWFzaW5nLnN5bWJvbCcpO1xuICAgICAgICBjb2VyY2UoJ2RlbHRhLmRlY3JlYXNpbmcuY29sb3InKTtcbiAgICAgICAgY29lcmNlKCdkZWx0YS5wb3NpdGlvbicpO1xuICAgICAgICBkZWx0YUZvbnRTaXplID0gdHJhY2VPdXQuZGVsdGEuZm9udC5zaXplO1xuICAgIH1cbiAgICB0cmFjZU91dC5fc2NhbGVOdW1iZXJzID0gKCF0cmFjZU91dC5faGFzTnVtYmVyIHx8IGF1dG9bMF0pICYmICghdHJhY2VPdXQuX2hhc0RlbHRhIHx8IGF1dG9bMV0pIHx8IGZhbHNlO1xuXG4gICAgLy8gVGl0bGUgYXR0cmlidXRlc1xuICAgIGNvZXJjZSgndGl0bGUuZm9udC5jb2xvcicsIGxheW91dC5mb250LmNvbG9yKTtcbiAgICBjb2VyY2UoJ3RpdGxlLmZvbnQuZmFtaWx5JywgbGF5b3V0LmZvbnQuZmFtaWx5KTtcbiAgICBjb2VyY2UoJ3RpdGxlLmZvbnQuc2l6ZScsIDAuMjUgKiAoYmlnbnVtYmVyRm9udFNpemUgfHwgZGVsdGFGb250U2l6ZSB8fCBjbi5kZWZhdWx0TnVtYmVyRm9udFNpemUpKTtcbiAgICBjb2VyY2UoJ3RpdGxlLnRleHQnKTtcblxuICAgIC8vIEdhdWdlIGF0dHJpYnV0ZXNcbiAgICB2YXIgZ2F1Z2VJbiwgZ2F1Z2VPdXQsIGF4aXNJbiwgYXhpc091dDtcbiAgICBmdW5jdGlvbiBjb2VyY2VHYXVnZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGdhdWdlSW4sIGdhdWdlT3V0LCBhdHRyaWJ1dGVzLmdhdWdlLCBhdHRyLCBkZmx0KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gY29lcmNlR2F1Z2VBeGlzKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoYXhpc0luLCBheGlzT3V0LCBhdHRyaWJ1dGVzLmdhdWdlLmF4aXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGlmKHRyYWNlT3V0Ll9oYXNHYXVnZSkge1xuICAgICAgICBnYXVnZUluID0gdHJhY2VJbi5nYXVnZTtcbiAgICAgICAgaWYoIWdhdWdlSW4pIGdhdWdlSW4gPSB7fTtcbiAgICAgICAgZ2F1Z2VPdXQgPSBUZW1wbGF0ZS5uZXdDb250YWluZXIodHJhY2VPdXQsICdnYXVnZScpO1xuICAgICAgICBjb2VyY2VHYXVnZSgnc2hhcGUnKTtcbiAgICAgICAgdmFyIGlzQnVsbGV0ID0gdHJhY2VPdXQuX2lzQnVsbGV0ID0gdHJhY2VPdXQuZ2F1Z2Uuc2hhcGUgPT09ICdidWxsZXQnO1xuICAgICAgICBpZighaXNCdWxsZXQpIHtcbiAgICAgICAgICAgIGNvZXJjZSgndGl0bGUuYWxpZ24nLCAnY2VudGVyJyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGlzQW5ndWxhciA9IHRyYWNlT3V0Ll9pc0FuZ3VsYXIgPSB0cmFjZU91dC5nYXVnZS5zaGFwZSA9PT0gJ2FuZ3VsYXInO1xuICAgICAgICBpZighaXNBbmd1bGFyKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ2FsaWduJywgJ2NlbnRlcicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZ2F1Z2UgYmFja2dyb3VuZFxuICAgICAgICBjb2VyY2VHYXVnZSgnYmdjb2xvcicsIGxheW91dC5wYXBlcl9iZ2NvbG9yKTtcbiAgICAgICAgY29lcmNlR2F1Z2UoJ2JvcmRlcndpZHRoJyk7XG4gICAgICAgIGNvZXJjZUdhdWdlKCdib3JkZXJjb2xvcicpO1xuXG4gICAgICAgIC8vIGdhdWdlIGJhciBpbmRpY2F0b3JcbiAgICAgICAgY29lcmNlR2F1Z2UoJ2Jhci5jb2xvcicpO1xuICAgICAgICBjb2VyY2VHYXVnZSgnYmFyLmxpbmUuY29sb3InKTtcbiAgICAgICAgY29lcmNlR2F1Z2UoJ2Jhci5saW5lLndpZHRoJyk7XG4gICAgICAgIHZhciBkZWZhdWx0QmFyVGhpY2tuZXNzID0gY24udmFsdWVUaGlja25lc3MgKiAodHJhY2VPdXQuZ2F1Z2Uuc2hhcGUgPT09ICdidWxsZXQnID8gMC41IDogMSk7XG4gICAgICAgIGNvZXJjZUdhdWdlKCdiYXIudGhpY2tuZXNzJywgZGVmYXVsdEJhclRoaWNrbmVzcyk7XG5cbiAgICAgICAgLy8gR2F1Z2Ugc3RlcHNcbiAgICAgICAgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyhnYXVnZUluLCBnYXVnZU91dCwge1xuICAgICAgICAgICAgbmFtZTogJ3N0ZXBzJyxcbiAgICAgICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogc3RlcERlZmF1bHRzXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEdhdWdlIHRocmVzaG9sZFxuICAgICAgICBjb2VyY2VHYXVnZSgndGhyZXNob2xkLnZhbHVlJyk7XG4gICAgICAgIGNvZXJjZUdhdWdlKCd0aHJlc2hvbGQudGhpY2tuZXNzJyk7XG4gICAgICAgIGNvZXJjZUdhdWdlKCd0aHJlc2hvbGQubGluZS53aWR0aCcpO1xuICAgICAgICBjb2VyY2VHYXVnZSgndGhyZXNob2xkLmxpbmUuY29sb3InKTtcblxuICAgICAgICAvLyBHYXVnZSBheGlzXG4gICAgICAgIGF4aXNJbiA9IHt9O1xuICAgICAgICBpZihnYXVnZUluKSBheGlzSW4gPSBnYXVnZUluLmF4aXMgfHwge307XG4gICAgICAgIGF4aXNPdXQgPSBUZW1wbGF0ZS5uZXdDb250YWluZXIoZ2F1Z2VPdXQsICdheGlzJyk7XG4gICAgICAgIGNvZXJjZUdhdWdlQXhpcygndmlzaWJsZScpO1xuICAgICAgICB0cmFjZU91dC5fcmFuZ2UgPSBjb2VyY2VHYXVnZUF4aXMoJ3JhbmdlJywgdHJhY2VPdXQuX3JhbmdlKTtcblxuICAgICAgICB2YXIgb3B0cyA9IHtvdXRlclRpY2tzOiB0cnVlfTtcbiAgICAgICAgaGFuZGxlVGlja1ZhbHVlRGVmYXVsdHMoYXhpc0luLCBheGlzT3V0LCBjb2VyY2VHYXVnZUF4aXMsICdsaW5lYXInKTtcbiAgICAgICAgaGFuZGxlVGlja0xhYmVsRGVmYXVsdHMoYXhpc0luLCBheGlzT3V0LCBjb2VyY2VHYXVnZUF4aXMsICdsaW5lYXInLCBvcHRzKTtcbiAgICAgICAgaGFuZGxlVGlja01hcmtEZWZhdWx0cyhheGlzSW4sIGF4aXNPdXQsIGNvZXJjZUdhdWdlQXhpcywgb3B0cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29lcmNlKCd0aXRsZS5hbGlnbicsICdjZW50ZXInKTtcbiAgICAgICAgY29lcmNlKCdhbGlnbicsICdjZW50ZXInKTtcbiAgICAgICAgdHJhY2VPdXQuX2lzQW5ndWxhciA9IHRyYWNlT3V0Ll9pc0J1bGxldCA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8vIGRpc2FibGUgMUQgdHJhbnNmb3Jtc1xuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBudWxsO1xufVxuXG5mdW5jdGlvbiBzdGVwRGVmYXVsdHMoc3RlcEluLCBzdGVwT3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2Uoc3RlcEluLCBzdGVwT3V0LCBhdHRyaWJ1dGVzLmdhdWdlLnN0ZXBzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2NvbG9yJyk7XG4gICAgY29lcmNlKCdsaW5lLmNvbG9yJyk7XG4gICAgY29lcmNlKCdsaW5lLndpZHRoJyk7XG4gICAgY29lcmNlKCdyYW5nZScpO1xuICAgIGNvZXJjZSgndGhpY2tuZXNzJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN1cHBseURlZmF1bHRzOiBzdXBwbHlEZWZhdWx0c1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzXCI6NzYzLFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfbGFiZWxfZGVmYXVsdHNcIjo3ODYsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vdGlja19tYXJrX2RlZmF1bHRzXCI6Nzg3LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL3RpY2tfdmFsdWVfZGVmYXVsdHNcIjo3ODgsXCIuLi8uLi9wbG90cy9kb21haW5cIjo3OTIsXCIuL2F0dHJpYnV0ZXNcIjoxMDQxLFwiLi9jb25zdGFudHMuanNcIjoxMDQ0fV0sMTA0NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ2luZGljYXRvcicsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4vYmFzZV9wbG90JyksXG4gICAgY2F0ZWdvcmllczogWydzdmcnLCAnbm9PcGFjaXR5JywgJ25vSG92ZXInXSxcbiAgICBhbmltYXRhYmxlOiB0cnVlLFxuXG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKS5zdXBwbHlEZWZhdWx0cyxcblxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLmNhbGMsXG5cbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKSxcblxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuL2F0dHJpYnV0ZXNcIjoxMDQxLFwiLi9iYXNlX3Bsb3RcIjoxMDQyLFwiLi9jYWxjXCI6MTA0MyxcIi4vZGVmYXVsdHNcIjoxMDQ1LFwiLi9wbG90XCI6MTA0N31dLDEwNDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgcmFkMmRlZyA9IExpYi5yYWQyZGVnO1xudmFyIE1JRF9TSElGVCA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9hbGlnbm1lbnQnKS5NSURfU0hJRlQ7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIGNuID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcbnZhciBzdmdUZXh0VXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcblxudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGhhbmRsZUF4aXNEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlQXhpc1Bvc2l0aW9uRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vcG9zaXRpb25fZGVmYXVsdHMnKTtcbnZhciBheGlzTGF5b3V0QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGFuY2hvciA9IHtcbiAgICAnbGVmdCc6ICdzdGFydCcsXG4gICAgJ2NlbnRlcic6ICdtaWRkbGUnLFxuICAgICdyaWdodCc6ICdlbmQnXG59O1xudmFyIHBvc2l0aW9uID0ge1xuICAgICdsZWZ0JzogMCxcbiAgICAnY2VudGVyJzogMC41LFxuICAgICdyaWdodCc6IDFcbn07XG5cbnZhciBTSV9QUkVGSVggPSAvW3l6YWZwbsK1bWtNR1RQRVpZXS87XG5cbmZ1bmN0aW9uIGhhc1RyYW5zaXRpb24odHJhbnNpdGlvbk9wdHMpIHtcbiAgICAvLyBJZiB0cmFuc2l0aW9uIGNvbmZpZyBpcyBwcm92aWRlZCwgdGhlbiBpdCBpcyBvbmx5IGEgcGFydGlhbCByZXBsb3QgYW5kIHRyYWNlcyBub3RcbiAgICAvLyB1cGRhdGVkIGFyZSByZW1vdmVkLlxuICAgIHJldHVybiB0cmFuc2l0aW9uT3B0cyAmJiB0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbiA+IDA7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgY2RNb2R1bGUsIHRyYW5zaXRpb25PcHRzLCBtYWtlT25Db21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgb25Db21wbGV0ZTtcblxuICAgIGlmKGhhc1RyYW5zaXRpb24odHJhbnNpdGlvbk9wdHMpKSB7XG4gICAgICAgIGlmKG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIC8vIElmIGl0IHdhcyBwYXNzZWQgYSBjYWxsYmFjayB0byByZWdpc3RlciBjb21wbGV0aW9uLCBtYWtlIGEgY2FsbGJhY2suIElmXG4gICAgICAgICAgICAvLyB0aGlzIGlzIGNyZWF0ZWQsIHRoZW4gaXQgbXVzdCBiZSBleGVjdXRlZCBvbiBjb21wbGV0aW9uLCBvdGhlcndpc2UgdGhlXG4gICAgICAgICAgICAvLyBwb3MtdHJhbnNpdGlvbiByZWRyYXcgd2lsbCBub3QgZXhlY3V0ZTpcbiAgICAgICAgICAgIG9uQ29tcGxldGUgPSBtYWtlT25Db21wbGV0ZUNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBMaWIubWFrZVRyYWNlR3JvdXBzKGZ1bGxMYXlvdXQuX2luZGljYXRvcmxheWVyLCBjZE1vZHVsZSwgJ3RyYWNlJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIC8vIEVsZW1lbnRzIGluIHRyYWNlXG4gICAgICAgIHZhciBoYXNHYXVnZSA9IHRyYWNlLl9oYXNHYXVnZTtcbiAgICAgICAgdmFyIGlzQW5ndWxhciA9IHRyYWNlLl9pc0FuZ3VsYXI7XG4gICAgICAgIHZhciBpc0J1bGxldCA9IHRyYWNlLl9pc0J1bGxldDtcblxuICAgICAgICAvLyBEb21haW4gc2l6ZVxuICAgICAgICB2YXIgZG9tYWluID0gdHJhY2UuZG9tYWluO1xuICAgICAgICB2YXIgc2l6ZSA9IHtcbiAgICAgICAgICAgIHc6IGZ1bGxMYXlvdXQuX3NpemUudyAqIChkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdKSxcbiAgICAgICAgICAgIGg6IGZ1bGxMYXlvdXQuX3NpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKSxcbiAgICAgICAgICAgIGw6IGZ1bGxMYXlvdXQuX3NpemUubCArIGZ1bGxMYXlvdXQuX3NpemUudyAqIGRvbWFpbi54WzBdLFxuICAgICAgICAgICAgcjogZnVsbExheW91dC5fc2l6ZS5yICsgZnVsbExheW91dC5fc2l6ZS53ICogKDEgLSBkb21haW4ueFsxXSksXG4gICAgICAgICAgICB0OiBmdWxsTGF5b3V0Ll9zaXplLnQgKyBmdWxsTGF5b3V0Ll9zaXplLmggKiAoMSAtIGRvbWFpbi55WzFdKSxcbiAgICAgICAgICAgIGI6IGZ1bGxMYXlvdXQuX3NpemUuYiArIGZ1bGxMYXlvdXQuX3NpemUuaCAqIChkb21haW4ueVswXSlcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNlbnRlclggPSBzaXplLmwgKyBzaXplLncgLyAyO1xuICAgICAgICB2YXIgY2VudGVyWSA9IHNpemUudCArIHNpemUuaCAvIDI7XG5cbiAgICAgICAgLy8gQW5ndWxhciBnYXVnZSBzaXplXG4gICAgICAgIHZhciByYWRpdXMgPSBNYXRoLm1pbihzaXplLncgLyAyLCBzaXplLmgpOyAvLyBmaWxsIGRvbWFpblxuICAgICAgICB2YXIgaW5uZXJSYWRpdXMgPSBjbi5pbm5lclJhZGl1cyAqIHJhZGl1cztcblxuICAgICAgICAvLyBQb3NpdGlvbiBudW1iZXJzIGJhc2VkIG9uIG1vZGUgYW5kIHNldCB0aGUgc2NhbGluZyBsb2dpY1xuICAgICAgICB2YXIgbnVtYmVyc1gsIG51bWJlcnNZLCBudW1iZXJzU2NhbGVyO1xuICAgICAgICB2YXIgbnVtYmVyc0FsaWduID0gdHJhY2UuYWxpZ24gfHwgJ2NlbnRlcic7XG5cbiAgICAgICAgbnVtYmVyc1kgPSBjZW50ZXJZO1xuICAgICAgICBpZighaGFzR2F1Z2UpIHtcbiAgICAgICAgICAgIG51bWJlcnNYID0gc2l6ZS5sICsgcG9zaXRpb25bbnVtYmVyc0FsaWduXSAqIHNpemUudztcbiAgICAgICAgICAgIG51bWJlcnNTY2FsZXIgPSBmdW5jdGlvbihlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmaXRUZXh0SW5zaWRlQm94KGVsLCBzaXplLncsIHNpemUuaCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYoaXNBbmd1bGFyKSB7XG4gICAgICAgICAgICAgICAgbnVtYmVyc1ggPSBjZW50ZXJYO1xuICAgICAgICAgICAgICAgIG51bWJlcnNZID0gY2VudGVyWSArIHJhZGl1cyAvIDI7XG4gICAgICAgICAgICAgICAgbnVtYmVyc1NjYWxlciA9IGZ1bmN0aW9uKGVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmaXRUZXh0SW5zaWRlQ2lyY2xlKGVsLCAwLjkgKiBpbm5lclJhZGl1cyk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGlzQnVsbGV0KSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhZGRpbmcgPSBjbi5idWxsZXRQYWRkaW5nO1xuICAgICAgICAgICAgICAgIHZhciBwID0gKDEgLSBjbi5idWxsZXROdW1iZXJEb21haW5TaXplKSArIHBhZGRpbmc7XG4gICAgICAgICAgICAgICAgbnVtYmVyc1ggPSBzaXplLmwgKyAocCArICgxIC0gcCkgKiBwb3NpdGlvbltudW1iZXJzQWxpZ25dKSAqIHNpemUudztcbiAgICAgICAgICAgICAgICBudW1iZXJzU2NhbGVyID0gZnVuY3Rpb24oZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZpdFRleHRJbnNpZGVCb3goZWwsIChjbi5idWxsZXROdW1iZXJEb21haW5TaXplIC0gcGFkZGluZykgKiBzaXplLncsIHNpemUuaCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERyYXcgbnVtYmVyc1xuICAgICAgICBkcmF3TnVtYmVycyhnZCwgcGxvdEdyb3VwLCBjZCwge1xuICAgICAgICAgICAgbnVtYmVyc1g6IG51bWJlcnNYLFxuICAgICAgICAgICAgbnVtYmVyc1k6IG51bWJlcnNZLFxuICAgICAgICAgICAgbnVtYmVyc1NjYWxlcjogbnVtYmVyc1NjYWxlcixcbiAgICAgICAgICAgIHRyYW5zaXRpb25PcHRzOiB0cmFuc2l0aW9uT3B0cyxcbiAgICAgICAgICAgIG9uQ29tcGxldGU6IG9uQ29tcGxldGVcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gUmVleHByZXNzIG91ciBnYXVnZSBiYWNrZ3JvdW5kIGF0dHJpYnV0ZXMgZm9yIGRyYXdpbmdcbiAgICAgICAgdmFyIGdhdWdlQmcsIGdhdWdlT3V0bGluZTtcbiAgICAgICAgaWYoaGFzR2F1Z2UpIHtcbiAgICAgICAgICAgIGdhdWdlQmcgPSB7XG4gICAgICAgICAgICAgICAgcmFuZ2U6IHRyYWNlLmdhdWdlLmF4aXMucmFuZ2UsXG4gICAgICAgICAgICAgICAgY29sb3I6IHRyYWNlLmdhdWdlLmJnY29sb3IsXG4gICAgICAgICAgICAgICAgbGluZToge1xuICAgICAgICAgICAgICAgICAgICBjb2xvcjogdHJhY2UuZ2F1Z2UuYm9yZGVyY29sb3IsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiAwXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB0aGlja25lc3M6IDFcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGdhdWdlT3V0bGluZSA9IHtcbiAgICAgICAgICAgICAgICByYW5nZTogdHJhY2UuZ2F1Z2UuYXhpcy5yYW5nZSxcbiAgICAgICAgICAgICAgICBjb2xvcjogJ3JnYmEoMCwgMCwgMCwgMCknLFxuICAgICAgICAgICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgICAgICAgICAgY29sb3I6IHRyYWNlLmdhdWdlLmJvcmRlcmNvbG9yLFxuICAgICAgICAgICAgICAgICAgICB3aWR0aDogdHJhY2UuZ2F1Z2UuYm9yZGVyd2lkdGhcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHRoaWNrbmVzczogMVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXBhcmUgYW5ndWxhciBnYXVnZSBsYXllcnNcbiAgICAgICAgdmFyIGFuZ3VsYXJHYXVnZSA9IHBsb3RHcm91cC5zZWxlY3RBbGwoJ2cuYW5ndWxhcicpLmRhdGEoaXNBbmd1bGFyID8gY2QgOiBbXSk7XG4gICAgICAgIGFuZ3VsYXJHYXVnZS5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIHZhciBhbmd1bGFyYXhpc0xheWVyID0gcGxvdEdyb3VwLnNlbGVjdEFsbCgnZy5hbmd1bGFyYXhpcycpLmRhdGEoaXNBbmd1bGFyID8gY2QgOiBbXSk7XG4gICAgICAgIGFuZ3VsYXJheGlzTGF5ZXIuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIGlmKGlzQW5ndWxhcikge1xuICAgICAgICAgICAgZHJhd0FuZ3VsYXJHYXVnZShnZCwgcGxvdEdyb3VwLCBjZCwge1xuICAgICAgICAgICAgICAgIHJhZGl1czogcmFkaXVzLFxuICAgICAgICAgICAgICAgIGlubmVyUmFkaXVzOiBpbm5lclJhZGl1cyxcblxuICAgICAgICAgICAgICAgIGdhdWdlOiBhbmd1bGFyR2F1Z2UsXG4gICAgICAgICAgICAgICAgbGF5ZXI6IGFuZ3VsYXJheGlzTGF5ZXIsXG4gICAgICAgICAgICAgICAgc2l6ZTogc2l6ZSxcbiAgICAgICAgICAgICAgICBnYXVnZUJnOiBnYXVnZUJnLFxuICAgICAgICAgICAgICAgIGdhdWdlT3V0bGluZTogZ2F1Z2VPdXRsaW5lLFxuICAgICAgICAgICAgICAgIHRyYW5zaXRpb25PcHRzOiB0cmFuc2l0aW9uT3B0cyxcbiAgICAgICAgICAgICAgICBvbkNvbXBsZXRlOiBvbkNvbXBsZXRlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXBhcmUgYnVsbGV0IGxheWVyc1xuICAgICAgICB2YXIgYnVsbGV0R2F1Z2UgPSBwbG90R3JvdXAuc2VsZWN0QWxsKCdnLmJ1bGxldCcpLmRhdGEoaXNCdWxsZXQgPyBjZCA6IFtdKTtcbiAgICAgICAgYnVsbGV0R2F1Z2UuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICB2YXIgYnVsbGV0YXhpc0xheWVyID0gcGxvdEdyb3VwLnNlbGVjdEFsbCgnZy5idWxsZXRheGlzJykuZGF0YShpc0J1bGxldCA/IGNkIDogW10pO1xuICAgICAgICBidWxsZXRheGlzTGF5ZXIuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIGlmKGlzQnVsbGV0KSB7XG4gICAgICAgICAgICBkcmF3QnVsbGV0R2F1Z2UoZ2QsIHBsb3RHcm91cCwgY2QsIHtcbiAgICAgICAgICAgICAgICBnYXVnZTogYnVsbGV0R2F1Z2UsXG4gICAgICAgICAgICAgICAgbGF5ZXI6IGJ1bGxldGF4aXNMYXllcixcbiAgICAgICAgICAgICAgICBzaXplOiBzaXplLFxuICAgICAgICAgICAgICAgIGdhdWdlQmc6IGdhdWdlQmcsXG4gICAgICAgICAgICAgICAgZ2F1Z2VPdXRsaW5lOiBnYXVnZU91dGxpbmUsXG4gICAgICAgICAgICAgICAgdHJhbnNpdGlvbk9wdHM6IHRyYW5zaXRpb25PcHRzLFxuICAgICAgICAgICAgICAgIG9uQ29tcGxldGU6IG9uQ29tcGxldGVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGl0bGVcbiAgICAgICAgdmFyIHRpdGxlID0gcGxvdEdyb3VwLnNlbGVjdEFsbCgndGV4dC50aXRsZScpLmRhdGEoY2QpO1xuICAgICAgICB0aXRsZS5leGl0KCkucmVtb3ZlKCk7XG4gICAgICAgIHRpdGxlLmVudGVyKCkuYXBwZW5kKCd0ZXh0JykuY2xhc3NlZCgndGl0bGUnLCB0cnVlKTtcbiAgICAgICAgdGl0bGVcbiAgICAgICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0J1bGxldCA/IGFuY2hvci5yaWdodCA6IGFuY2hvclt0cmFjZS50aXRsZS5hbGlnbl07XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRleHQodHJhY2UudGl0bGUudGV4dClcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZm9udCwgdHJhY2UudGl0bGUuZm9udClcbiAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKTtcblxuICAgICAgICAvLyBQb3NpdGlvbiB0aXRsZVxuICAgICAgICB0aXRsZS5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciB0aXRsZVggPSBzaXplLmwgKyBzaXplLncgKiBwb3NpdGlvblt0cmFjZS50aXRsZS5hbGlnbl07XG4gICAgICAgICAgICB2YXIgdGl0bGVZO1xuICAgICAgICAgICAgdmFyIHRpdGxlUGFkZGluZyA9IGNuLnRpdGxlUGFkZGluZztcbiAgICAgICAgICAgIHZhciB0aXRsZWJCb3ggPSBEcmF3aW5nLmJCb3godGl0bGUubm9kZSgpKTtcbiAgICAgICAgICAgIGlmKGhhc0dhdWdlKSB7XG4gICAgICAgICAgICAgICAgaWYoaXNBbmd1bGFyKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHBvc2l0aW9uIGFib3ZlIGF4aXMgdGlja3MvbGFiZWxzXG4gICAgICAgICAgICAgICAgICAgIGlmKHRyYWNlLmdhdWdlLmF4aXMudmlzaWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJCb3ggPSBEcmF3aW5nLmJCb3goYW5ndWxhcmF4aXNMYXllci5ub2RlKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGVZID0gKGJCb3gudG9wIC0gdGl0bGVQYWRkaW5nKSAtIHRpdGxlYkJveC5ib3R0b207XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aXRsZVkgPSBzaXplLnQgKyBzaXplLmggLyAyIC0gcmFkaXVzIC8gMiAtIHRpdGxlYkJveC5ib3R0b20gLSB0aXRsZVBhZGRpbmc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYoaXNCdWxsZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcG9zaXRpb24gb3V0c2lkZSBkb21haW5cbiAgICAgICAgICAgICAgICAgICAgdGl0bGVZID0gbnVtYmVyc1kgLSAodGl0bGViQm94LnRvcCArIHRpdGxlYkJveC5ib3R0b20pIC8gMjtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGVYID0gc2l6ZS5sIC0gY24uYnVsbGV0UGFkZGluZyAqIHNpemUudzsgLy8gT3V0c2lkZSBkb21haW4sIG9uIHRoZSBsZWZ0XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBwb3NpdGlvbiBhYm92ZSBudW1iZXJzXG4gICAgICAgICAgICAgICAgdGl0bGVZID0gKHRyYWNlLl9udW1iZXJzVG9wIC0gdGl0bGVQYWRkaW5nKSAtIHRpdGxlYkJveC5ib3R0b207XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3RyVHJhbnNsYXRlKHRpdGxlWCwgdGl0bGVZKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG5mdW5jdGlvbiBkcmF3QnVsbGV0R2F1Z2UoZ2QsIHBsb3RHcm91cCwgY2QsIG9wdHMpIHtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgIHZhciBidWxsZXQgPSBvcHRzLmdhdWdlO1xuICAgIHZhciBheGlzTGF5ZXIgPSBvcHRzLmxheWVyO1xuICAgIHZhciBnYXVnZUJnID0gb3B0cy5nYXVnZUJnO1xuICAgIHZhciBnYXVnZU91dGxpbmUgPSBvcHRzLmdhdWdlT3V0bGluZTtcbiAgICB2YXIgc2l6ZSA9IG9wdHMuc2l6ZTtcbiAgICB2YXIgZG9tYWluID0gdHJhY2UuZG9tYWluO1xuXG4gICAgdmFyIHRyYW5zaXRpb25PcHRzID0gb3B0cy50cmFuc2l0aW9uT3B0cztcbiAgICB2YXIgb25Db21wbGV0ZSA9IG9wdHMub25Db21wbGV0ZTtcblxuICAgIC8vIHByZXBhcmluZyBheGlzXG4gICAgdmFyIGF4LCB2YWxzLCB0cmFuc0ZuLCB0aWNrU2lnbiwgc2hpZnQ7XG5cbiAgICAvLyBFbnRlciBidWxsZXQsIGF4aXNcbiAgICBidWxsZXQuZW50ZXIoKS5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdidWxsZXQnLCB0cnVlKTtcbiAgICBidWxsZXQuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgc2l6ZS5sICsgJywgJyArIHNpemUudCArICcpJyk7XG5cbiAgICBheGlzTGF5ZXIuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZCgnYnVsbGV0YXhpcycsIHRydWUpXG4gICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIHRydWUpO1xuICAgIGF4aXNMYXllci5zZWxlY3RBbGwoJ2cuJyArICd4YnVsbGV0YXhpcycgKyAndGljayxwYXRoLHRleHQnKS5yZW1vdmUoKTtcblxuICAgIC8vIERyYXcgYnVsbGV0XG4gICAgdmFyIGJ1bGxldEhlaWdodCA9IHNpemUuaDsgLy8gdXNlIGFsbCB2ZXJ0aWNhbCBkb21haW5cbiAgICB2YXIgaW5uZXJCdWxsZXRIZWlnaHQgPSB0cmFjZS5nYXVnZS5iYXIudGhpY2tuZXNzICogYnVsbGV0SGVpZ2h0O1xuICAgIHZhciBidWxsZXRMZWZ0ID0gZG9tYWluLnhbMF07XG4gICAgdmFyIGJ1bGxldFJpZ2h0ID0gZG9tYWluLnhbMF0gKyAoZG9tYWluLnhbMV0gLSBkb21haW4ueFswXSkgKiAoKHRyYWNlLl9oYXNOdW1iZXIgfHwgdHJhY2UuX2hhc0RlbHRhKSA/ICgxIC0gY24uYnVsbGV0TnVtYmVyRG9tYWluU2l6ZSkgOiAxKTtcblxuICAgIGF4ID0gbW9ja0F4aXMoZ2QsIHRyYWNlLmdhdWdlLmF4aXMpO1xuICAgIGF4Ll9pZCA9ICd4YnVsbGV0YXhpcyc7XG4gICAgYXguZG9tYWluID0gW2J1bGxldExlZnQsIGJ1bGxldFJpZ2h0XTtcbiAgICBheC5zZXRTY2FsZSgpO1xuXG4gICAgdmFscyA9IEF4ZXMuY2FsY1RpY2tzKGF4KTtcbiAgICB0cmFuc0ZuID0gQXhlcy5tYWtlVHJhbnNGbihheCk7XG4gICAgdGlja1NpZ24gPSBBeGVzLmdldFRpY2tTaWducyhheClbMl07XG5cbiAgICBzaGlmdCA9IHNpemUudCArIHNpemUuaDtcbiAgICBpZihheC52aXNpYmxlKSB7XG4gICAgICAgIEF4ZXMuZHJhd1RpY2tzKGdkLCBheCwge1xuICAgICAgICAgICAgdmFsczogYXgudGlja3MgPT09ICdpbnNpZGUnID8gQXhlcy5jbGlwRW5kcyhheCwgdmFscykgOiB2YWxzLFxuICAgICAgICAgICAgbGF5ZXI6IGF4aXNMYXllcixcbiAgICAgICAgICAgIHBhdGg6IEF4ZXMubWFrZVRpY2tQYXRoKGF4LCBzaGlmdCwgdGlja1NpZ24pLFxuICAgICAgICAgICAgdHJhbnNGbjogdHJhbnNGblxuICAgICAgICB9KTtcblxuICAgICAgICBBeGVzLmRyYXdMYWJlbHMoZ2QsIGF4LCB7XG4gICAgICAgICAgICB2YWxzOiB2YWxzLFxuICAgICAgICAgICAgbGF5ZXI6IGF4aXNMYXllcixcbiAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm4sXG4gICAgICAgICAgICBsYWJlbEZuczogQXhlcy5tYWtlTGFiZWxGbnMoYXgsIHNoaWZ0KVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3UmVjdChzKSB7XG4gICAgICAgIHNcbiAgICAgICAgICAgIC5hdHRyKCd3aWR0aCcsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIE1hdGgubWF4KDAsIGF4LmMycChkLnJhbmdlWzFdKSAtIGF4LmMycChkLnJhbmdlWzBdKSk7fSlcbiAgICAgICAgICAgIC5hdHRyKCd4JywgZnVuY3Rpb24oZCkgeyByZXR1cm4gYXguYzJwKGQucmFuZ2VbMF0pO30pXG4gICAgICAgICAgICAuYXR0cigneScsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIDAuNSAqICgxIC0gZC50aGlja25lc3MpICogYnVsbGV0SGVpZ2h0O30pXG4gICAgICAgICAgICAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCkgeyByZXR1cm4gZC50aGlja25lc3MgKiBidWxsZXRIZWlnaHQ7IH0pO1xuICAgIH1cblxuICAgIC8vIERyYXcgYnVsbGV0IGJhY2tncm91bmQsIHN0ZXBzXG4gICAgdmFyIGJveGVzID0gW2dhdWdlQmddLmNvbmNhdCh0cmFjZS5nYXVnZS5zdGVwcyk7XG4gICAgdmFyIGJnQnVsbGV0ID0gYnVsbGV0LnNlbGVjdEFsbCgnZy5iZy1idWxsZXQnKS5kYXRhKGJveGVzKTtcbiAgICBiZ0J1bGxldC5lbnRlcigpLmFwcGVuZCgnZycpLmNsYXNzZWQoJ2JnLWJ1bGxldCcsIHRydWUpLmFwcGVuZCgncmVjdCcpO1xuICAgIGJnQnVsbGV0LnNlbGVjdCgncmVjdCcpXG4gICAgICAgIC5jYWxsKGRyYXdSZWN0KVxuICAgICAgICAuY2FsbChzdHlsZVNoYXBlKTtcbiAgICBiZ0J1bGxldC5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAvLyBEcmF3IHZhbHVlIGJhciB3aXRoIHRyYW5zaXRpb25zXG4gICAgdmFyIGZnQnVsbGV0ID0gYnVsbGV0LnNlbGVjdEFsbCgnZy52YWx1ZS1idWxsZXQnKS5kYXRhKFt0cmFjZS5nYXVnZS5iYXJdKTtcbiAgICBmZ0J1bGxldC5lbnRlcigpLmFwcGVuZCgnZycpLmNsYXNzZWQoJ3ZhbHVlLWJ1bGxldCcsIHRydWUpLmFwcGVuZCgncmVjdCcpO1xuICAgIGZnQnVsbGV0LnNlbGVjdCgncmVjdCcpXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBpbm5lckJ1bGxldEhlaWdodClcbiAgICAgICAgLmF0dHIoJ3knLCAoYnVsbGV0SGVpZ2h0IC0gaW5uZXJCdWxsZXRIZWlnaHQpIC8gMilcbiAgICAgICAgLmNhbGwoc3R5bGVTaGFwZSk7XG4gICAgaWYoaGFzVHJhbnNpdGlvbih0cmFuc2l0aW9uT3B0cykpIHtcbiAgICAgICAgZmdCdWxsZXQuc2VsZWN0KCdyZWN0JylcbiAgICAgICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgICAgIC5kdXJhdGlvbih0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbilcbiAgICAgICAgICAgIC5lYXNlKHRyYW5zaXRpb25PcHRzLmVhc2luZylcbiAgICAgICAgICAgIC5lYWNoKCdlbmQnLCBmdW5jdGlvbigpIHsgb25Db21wbGV0ZSAmJiBvbkNvbXBsZXRlKCk7IH0pXG4gICAgICAgICAgICAuZWFjaCgnaW50ZXJydXB0JywgZnVuY3Rpb24oKSB7IG9uQ29tcGxldGUgJiYgb25Db21wbGV0ZSgpOyB9KVxuICAgICAgICAgICAgLmF0dHIoJ3dpZHRoJywgTWF0aC5tYXgoMCwgYXguYzJwKE1hdGgubWluKHRyYWNlLmdhdWdlLmF4aXMucmFuZ2VbMV0sIGNkWzBdLnkpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGZnQnVsbGV0LnNlbGVjdCgncmVjdCcpXG4gICAgICAgICAgICAuYXR0cignd2lkdGgnLCB0eXBlb2YgY2RbMF0ueSA9PT0gJ251bWJlcicgP1xuICAgICAgICAgICAgICAgIE1hdGgubWF4KDAsIGF4LmMycChNYXRoLm1pbih0cmFjZS5nYXVnZS5heGlzLnJhbmdlWzFdLCBjZFswXS55KSkpIDpcbiAgICAgICAgICAgICAgICAwKTtcbiAgICB9XG4gICAgZmdCdWxsZXQuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdmFyIGRhdGEgPSBjZC5maWx0ZXIoZnVuY3Rpb24oKSB7cmV0dXJuIHRyYWNlLmdhdWdlLnRocmVzaG9sZC52YWx1ZTt9KTtcbiAgICB2YXIgdGhyZXNob2xkID0gYnVsbGV0LnNlbGVjdEFsbCgnZy50aHJlc2hvbGQtYnVsbGV0JykuZGF0YShkYXRhKTtcbiAgICB0aHJlc2hvbGQuZW50ZXIoKS5hcHBlbmQoJ2cnKS5jbGFzc2VkKCd0aHJlc2hvbGQtYnVsbGV0JywgdHJ1ZSkuYXBwZW5kKCdsaW5lJyk7XG4gICAgdGhyZXNob2xkLnNlbGVjdCgnbGluZScpXG4gICAgICAgIC5hdHRyKCd4MScsIGF4LmMycCh0cmFjZS5nYXVnZS50aHJlc2hvbGQudmFsdWUpKVxuICAgICAgICAuYXR0cigneDInLCBheC5jMnAodHJhY2UuZ2F1Z2UudGhyZXNob2xkLnZhbHVlKSlcbiAgICAgICAgLmF0dHIoJ3kxJywgKDEgLSB0cmFjZS5nYXVnZS50aHJlc2hvbGQudGhpY2tuZXNzKSAvIDIgKiBidWxsZXRIZWlnaHQpXG4gICAgICAgIC5hdHRyKCd5MicsICgxIC0gKDEgLSB0cmFjZS5nYXVnZS50aHJlc2hvbGQudGhpY2tuZXNzKSAvIDIpICogYnVsbGV0SGVpZ2h0KVxuICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIHRyYWNlLmdhdWdlLnRocmVzaG9sZC5saW5lLmNvbG9yKVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIHRyYWNlLmdhdWdlLnRocmVzaG9sZC5saW5lLndpZHRoKTtcbiAgICB0aHJlc2hvbGQuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgdmFyIGJ1bGxldE91dGxpbmUgPSBidWxsZXQuc2VsZWN0QWxsKCdnLmdhdWdlLW91dGxpbmUnKS5kYXRhKFtnYXVnZU91dGxpbmVdKTtcbiAgICBidWxsZXRPdXRsaW5lLmVudGVyKCkuYXBwZW5kKCdnJykuY2xhc3NlZCgnZ2F1Z2Utb3V0bGluZScsIHRydWUpLmFwcGVuZCgncmVjdCcpO1xuICAgIGJ1bGxldE91dGxpbmUuc2VsZWN0KCdyZWN0JylcbiAgICAgICAgLmNhbGwoZHJhd1JlY3QpXG4gICAgICAgIC5jYWxsKHN0eWxlU2hhcGUpO1xuICAgIGJ1bGxldE91dGxpbmUuZXhpdCgpLnJlbW92ZSgpO1xufVxuXG5mdW5jdGlvbiBkcmF3QW5ndWxhckdhdWdlKGdkLCBwbG90R3JvdXAsIGNkLCBvcHRzKSB7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICB2YXIgc2l6ZSA9IG9wdHMuc2l6ZTtcbiAgICB2YXIgcmFkaXVzID0gb3B0cy5yYWRpdXM7XG4gICAgdmFyIGlubmVyUmFkaXVzID0gb3B0cy5pbm5lclJhZGl1cztcbiAgICB2YXIgZ2F1Z2VCZyA9IG9wdHMuZ2F1Z2VCZztcbiAgICB2YXIgZ2F1Z2VPdXRsaW5lID0gb3B0cy5nYXVnZU91dGxpbmU7XG4gICAgdmFyIGdhdWdlUG9zaXRpb24gPSBbc2l6ZS5sICsgc2l6ZS53IC8gMiwgc2l6ZS50ICsgc2l6ZS5oIC8gMiArIHJhZGl1cyAvIDJdO1xuICAgIHZhciBnYXVnZSA9IG9wdHMuZ2F1Z2U7XG4gICAgdmFyIGF4aXNMYXllciA9IG9wdHMubGF5ZXI7XG5cbiAgICB2YXIgdHJhbnNpdGlvbk9wdHMgPSBvcHRzLnRyYW5zaXRpb25PcHRzO1xuICAgIHZhciBvbkNvbXBsZXRlID0gb3B0cy5vbkNvbXBsZXRlO1xuXG4gICAgLy8gY2lyY3VsYXIgZ2F1Z2VcbiAgICB2YXIgdGhldGEgPSBNYXRoLlBJIC8gMjtcbiAgICBmdW5jdGlvbiB2YWx1ZVRvQW5nbGUodikge1xuICAgICAgICB2YXIgbWluID0gdHJhY2UuZ2F1Z2UuYXhpcy5yYW5nZVswXTtcbiAgICAgICAgdmFyIG1heCA9IHRyYWNlLmdhdWdlLmF4aXMucmFuZ2VbMV07XG4gICAgICAgIHZhciBhbmdsZSA9ICh2IC0gbWluKSAvIChtYXggLSBtaW4pICogTWF0aC5QSSAtIHRoZXRhO1xuICAgICAgICBpZihhbmdsZSA8IC10aGV0YSkgcmV0dXJuIC10aGV0YTtcbiAgICAgICAgaWYoYW5nbGUgPiB0aGV0YSkgcmV0dXJuIHRoZXRhO1xuICAgICAgICByZXR1cm4gYW5nbGU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXJjUGF0aEdlbmVyYXRvcihzaXplKSB7XG4gICAgICAgIHJldHVybiBkMy5zdmcuYXJjKClcbiAgICAgICAgICAgICAgICAgIC5pbm5lclJhZGl1cygoaW5uZXJSYWRpdXMgKyByYWRpdXMpIC8gMiAtIHNpemUgLyAyICogKHJhZGl1cyAtIGlubmVyUmFkaXVzKSlcbiAgICAgICAgICAgICAgICAgIC5vdXRlclJhZGl1cygoaW5uZXJSYWRpdXMgKyByYWRpdXMpIC8gMiArIHNpemUgLyAyICogKHJhZGl1cyAtIGlubmVyUmFkaXVzKSlcbiAgICAgICAgICAgICAgICAgIC5zdGFydEFuZ2xlKC10aGV0YSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd0FyYyhwKSB7XG4gICAgICAgIHBcbiAgICAgICAgICAgIC5hdHRyKCdkJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhcmNQYXRoR2VuZXJhdG9yKGQudGhpY2tuZXNzKVxuICAgICAgICAgICAgICAgICAgLnN0YXJ0QW5nbGUodmFsdWVUb0FuZ2xlKGQucmFuZ2VbMF0pKVxuICAgICAgICAgICAgICAgICAgLmVuZEFuZ2xlKHZhbHVlVG9BbmdsZShkLnJhbmdlWzFdKSkoKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIHByZXBhcmluZyBheGlzXG4gICAgdmFyIGF4LCB2YWxzLCB0cmFuc0ZuLCB0aWNrU2lnbjtcblxuICAgIC8vIEVudGVyIGdhdWdlIGFuZCBheGlzXG4gICAgZ2F1Z2UuZW50ZXIoKS5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdhbmd1bGFyJywgdHJ1ZSk7XG4gICAgZ2F1Z2UuYXR0cigndHJhbnNmb3JtJywgc3RyVHJhbnNsYXRlKGdhdWdlUG9zaXRpb25bMF0sIGdhdWdlUG9zaXRpb25bMV0pKTtcblxuICAgIGF4aXNMYXllci5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdhbmd1bGFyYXhpcycsIHRydWUpXG4gICAgICAgIC5jbGFzc2VkKCdjcmlzcCcsIHRydWUpO1xuICAgIGF4aXNMYXllci5zZWxlY3RBbGwoJ2cuJyArICd4YW5ndWxhcmF4aXMnICsgJ3RpY2sscGF0aCx0ZXh0JykucmVtb3ZlKCk7XG5cbiAgICBheCA9IG1vY2tBeGlzKGdkLCB0cmFjZS5nYXVnZS5heGlzKTtcbiAgICBheC50eXBlID0gJ2xpbmVhcic7XG4gICAgYXgucmFuZ2UgPSB0cmFjZS5nYXVnZS5heGlzLnJhbmdlO1xuICAgIGF4Ll9pZCA9ICd4YW5ndWxhcmF4aXMnOyAvLyBvciAneScsIGJ1dCBJIGRvbid0IHRoaW5rIHRoaXMgbWFrZXMgYSBkaWZmZXJlbmNlIGhlcmVcbiAgICBheC5zZXRTY2FsZSgpO1xuXG4gICAgLy8gJ3QnaWNrIHRvICdnJ2VvbWV0cmljIHJhZGlhbnMgaXMgdXNlZCBhbGwgb3ZlciB0aGUgcGxhY2UgaGVyZVxuICAgIHZhciB0MmcgPSBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiAoYXgucmFuZ2VbMF0gLSBkLngpIC8gKGF4LnJhbmdlWzFdIC0gYXgucmFuZ2VbMF0pICogTWF0aC5QSSArIE1hdGguUEk7XG4gICAgfTtcblxuICAgIHZhciBsYWJlbEZucyA9IHt9O1xuICAgIHZhciBvdXQgPSBBeGVzLm1ha2VMYWJlbEZucyhheCwgMCk7XG4gICAgdmFyIGxhYmVsU3RhbmRvZmYgPSBvdXQubGFiZWxTdGFuZG9mZjtcbiAgICBsYWJlbEZucy54Rm4gPSBmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciByYWQgPSB0MmcoZCk7XG4gICAgICAgIHJldHVybiBNYXRoLmNvcyhyYWQpICogbGFiZWxTdGFuZG9mZjtcbiAgICB9O1xuICAgIGxhYmVsRm5zLnlGbiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHJhZCA9IHQyZyhkKTtcbiAgICAgICAgdmFyIGZmID0gTWF0aC5zaW4ocmFkKSA+IDAgPyAwLjIgOiAxO1xuICAgICAgICByZXR1cm4gLU1hdGguc2luKHJhZCkgKiAobGFiZWxTdGFuZG9mZiArIGQuZm9udFNpemUgKiBmZikgK1xuICAgICAgICAgICAgICAgIE1hdGguYWJzKE1hdGguY29zKHJhZCkpICogKGQuZm9udFNpemUgKiBNSURfU0hJRlQpO1xuICAgIH07XG4gICAgbGFiZWxGbnMuYW5jaG9yRm4gPSBmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciByYWQgPSB0MmcoZCk7XG4gICAgICAgIHZhciBjb3MgPSBNYXRoLmNvcyhyYWQpO1xuICAgICAgICByZXR1cm4gTWF0aC5hYnMoY29zKSA8IDAuMSA/XG4gICAgICAgICAgICAgICAgJ21pZGRsZScgOlxuICAgICAgICAgICAgICAgIChjb3MgPiAwID8gJ3N0YXJ0JyA6ICdlbmQnKTtcbiAgICB9O1xuICAgIGxhYmVsRm5zLmhlaWdodEZuID0gZnVuY3Rpb24oZCwgYSwgaCkge1xuICAgICAgICB2YXIgcmFkID0gdDJnKGQpO1xuICAgICAgICByZXR1cm4gLTAuNSAqICgxICsgTWF0aC5zaW4ocmFkKSkgKiBoO1xuICAgIH07XG4gICAgdmFyIF90cmFuc0ZuID0gZnVuY3Rpb24ocmFkKSB7XG4gICAgICAgIHJldHVybiBzdHJUcmFuc2xhdGUoXG4gICAgICAgICAgICBnYXVnZVBvc2l0aW9uWzBdICsgcmFkaXVzICogTWF0aC5jb3MocmFkKSxcbiAgICAgICAgICAgIGdhdWdlUG9zaXRpb25bMV0gLSByYWRpdXMgKiBNYXRoLnNpbihyYWQpXG4gICAgICAgICk7XG4gICAgfTtcbiAgICB0cmFuc0ZuID0gZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gX3RyYW5zRm4odDJnKGQpKTtcbiAgICB9O1xuICAgIHZhciB0cmFuc0ZuMiA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHJhZCA9IHQyZyhkKTtcbiAgICAgICAgcmV0dXJuIF90cmFuc0ZuKHJhZCkgKyAncm90YXRlKCcgKyAtcmFkMmRlZyhyYWQpICsgJyknO1xuICAgIH07XG4gICAgdmFscyA9IEF4ZXMuY2FsY1RpY2tzKGF4KTtcbiAgICB0aWNrU2lnbiA9IEF4ZXMuZ2V0VGlja1NpZ25zKGF4KVsyXTtcbiAgICBpZihheC52aXNpYmxlKSB7XG4gICAgICAgIHRpY2tTaWduID0gYXgudGlja3MgPT09ICdpbnNpZGUnID8gLTEgOiAxO1xuICAgICAgICB2YXIgcGFkID0gKGF4LmxpbmV3aWR0aCB8fCAxKSAvIDI7XG4gICAgICAgIEF4ZXMuZHJhd1RpY2tzKGdkLCBheCwge1xuICAgICAgICAgICAgdmFsczogdmFscyxcbiAgICAgICAgICAgIGxheWVyOiBheGlzTGF5ZXIsXG4gICAgICAgICAgICBwYXRoOiAnTScgKyAodGlja1NpZ24gKiBwYWQpICsgJywwaCcgKyAodGlja1NpZ24gKiBheC50aWNrbGVuKSxcbiAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm4yXG4gICAgICAgIH0pO1xuICAgICAgICBBeGVzLmRyYXdMYWJlbHMoZ2QsIGF4LCB7XG4gICAgICAgICAgICB2YWxzOiB2YWxzLFxuICAgICAgICAgICAgbGF5ZXI6IGF4aXNMYXllcixcbiAgICAgICAgICAgIHRyYW5zRm46IHRyYW5zRm4sXG4gICAgICAgICAgICBsYWJlbEZuczogbGFiZWxGbnNcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gRHJhdyBiYWNrZ3JvdW5kICsgc3RlcHNcbiAgICB2YXIgYXJjcyA9IFtnYXVnZUJnXS5jb25jYXQodHJhY2UuZ2F1Z2Uuc3RlcHMpO1xuICAgIHZhciBiZ0FyYyA9IGdhdWdlLnNlbGVjdEFsbCgnZy5iZy1hcmMnKS5kYXRhKGFyY3MpO1xuICAgIGJnQXJjLmVudGVyKCkuYXBwZW5kKCdnJykuY2xhc3NlZCgnYmctYXJjJywgdHJ1ZSkuYXBwZW5kKCdwYXRoJyk7XG4gICAgYmdBcmMuc2VsZWN0KCdwYXRoJykuY2FsbChkcmF3QXJjKS5jYWxsKHN0eWxlU2hhcGUpO1xuICAgIGJnQXJjLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIC8vIERyYXcgZm9yZWdyb3VuZCB3aXRoIHRyYW5zaXRpb25cbiAgICB2YXIgdmFsdWVBcmNQYXRoR2VuZXJhdG9yID0gYXJjUGF0aEdlbmVyYXRvcih0cmFjZS5nYXVnZS5iYXIudGhpY2tuZXNzKTtcbiAgICB2YXIgdmFsdWVBcmMgPSBnYXVnZS5zZWxlY3RBbGwoJ2cudmFsdWUtYXJjJykuZGF0YShbdHJhY2UuZ2F1Z2UuYmFyXSk7XG4gICAgdmFsdWVBcmMuZW50ZXIoKS5hcHBlbmQoJ2cnKS5jbGFzc2VkKCd2YWx1ZS1hcmMnLCB0cnVlKS5hcHBlbmQoJ3BhdGgnKTtcbiAgICB2YXIgdmFsdWVBcmNQYXRoID0gdmFsdWVBcmMuc2VsZWN0KCdwYXRoJyk7XG4gICAgaWYoaGFzVHJhbnNpdGlvbih0cmFuc2l0aW9uT3B0cykpIHtcbiAgICAgICAgdmFsdWVBcmNQYXRoXG4gICAgICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAuZHVyYXRpb24odHJhbnNpdGlvbk9wdHMuZHVyYXRpb24pXG4gICAgICAgICAgICAuZWFzZSh0cmFuc2l0aW9uT3B0cy5lYXNpbmcpXG4gICAgICAgICAgICAuZWFjaCgnZW5kJywgZnVuY3Rpb24oKSB7IG9uQ29tcGxldGUgJiYgb25Db21wbGV0ZSgpOyB9KVxuICAgICAgICAgICAgLmVhY2goJ2ludGVycnVwdCcsIGZ1bmN0aW9uKCkgeyBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUoKTsgfSlcbiAgICAgICAgICAgIC5hdHRyVHdlZW4oJ2QnLCBhcmNUd2Vlbih2YWx1ZUFyY1BhdGhHZW5lcmF0b3IsIHZhbHVlVG9BbmdsZShjZFswXS5sYXN0WSksIHZhbHVlVG9BbmdsZShjZFswXS55KSkpO1xuICAgICAgICB0cmFjZS5fbGFzdFZhbHVlID0gY2RbMF0ueTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZUFyY1BhdGguYXR0cignZCcsIHR5cGVvZiBjZFswXS55ID09PSAnbnVtYmVyJyA/XG4gICAgICAgICAgICB2YWx1ZUFyY1BhdGhHZW5lcmF0b3IuZW5kQW5nbGUodmFsdWVUb0FuZ2xlKGNkWzBdLnkpKSA6XG4gICAgICAgICAgICAnTTAsMFonKTtcbiAgICB9XG4gICAgdmFsdWVBcmNQYXRoLmNhbGwoc3R5bGVTaGFwZSk7XG4gICAgdmFsdWVBcmMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgLy8gRHJhdyB0aHJlc2hvbGRcbiAgICBhcmNzID0gW107XG4gICAgdmFyIHYgPSB0cmFjZS5nYXVnZS50aHJlc2hvbGQudmFsdWU7XG4gICAgaWYodikge1xuICAgICAgICBhcmNzLnB1c2goe1xuICAgICAgICAgICAgcmFuZ2U6IFt2LCB2XSxcbiAgICAgICAgICAgIGNvbG9yOiB0cmFjZS5nYXVnZS50aHJlc2hvbGQuY29sb3IsXG4gICAgICAgICAgICBsaW5lOiB7XG4gICAgICAgICAgICAgICAgY29sb3I6IHRyYWNlLmdhdWdlLnRocmVzaG9sZC5saW5lLmNvbG9yLFxuICAgICAgICAgICAgICAgIHdpZHRoOiB0cmFjZS5nYXVnZS50aHJlc2hvbGQubGluZS53aWR0aFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRoaWNrbmVzczogdHJhY2UuZ2F1Z2UudGhyZXNob2xkLnRoaWNrbmVzc1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgdmFyIHRocmVzaG9sZEFyYyA9IGdhdWdlLnNlbGVjdEFsbCgnZy50aHJlc2hvbGQtYXJjJykuZGF0YShhcmNzKTtcbiAgICB0aHJlc2hvbGRBcmMuZW50ZXIoKS5hcHBlbmQoJ2cnKS5jbGFzc2VkKCd0aHJlc2hvbGQtYXJjJywgdHJ1ZSkuYXBwZW5kKCdwYXRoJyk7XG4gICAgdGhyZXNob2xkQXJjLnNlbGVjdCgncGF0aCcpLmNhbGwoZHJhd0FyYykuY2FsbChzdHlsZVNoYXBlKTtcbiAgICB0aHJlc2hvbGRBcmMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgLy8gRHJhdyBib3JkZXIgbGFzdFxuICAgIHZhciBnYXVnZUJvcmRlciA9IGdhdWdlLnNlbGVjdEFsbCgnZy5nYXVnZS1vdXRsaW5lJykuZGF0YShbZ2F1Z2VPdXRsaW5lXSk7XG4gICAgZ2F1Z2VCb3JkZXIuZW50ZXIoKS5hcHBlbmQoJ2cnKS5jbGFzc2VkKCdnYXVnZS1vdXRsaW5lJywgdHJ1ZSkuYXBwZW5kKCdwYXRoJyk7XG4gICAgZ2F1Z2VCb3JkZXIuc2VsZWN0KCdwYXRoJykuY2FsbChkcmF3QXJjKS5jYWxsKHN0eWxlU2hhcGUpO1xuICAgIGdhdWdlQm9yZGVyLmV4aXQoKS5yZW1vdmUoKTtcbn1cblxuZnVuY3Rpb24gZHJhd051bWJlcnMoZ2QsIHBsb3RHcm91cCwgY2QsIG9wdHMpIHtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgIHZhciBudW1iZXJzWCA9IG9wdHMubnVtYmVyc1g7XG4gICAgdmFyIG51bWJlcnNZID0gb3B0cy5udW1iZXJzWTtcbiAgICB2YXIgbnVtYmVyc0FsaWduID0gdHJhY2UuYWxpZ24gfHwgJ2NlbnRlcic7XG4gICAgdmFyIG51bWJlcnNBbmNob3IgPSBhbmNob3JbbnVtYmVyc0FsaWduXTtcblxuICAgIHZhciB0cmFuc2l0aW9uT3B0cyA9IG9wdHMudHJhbnNpdGlvbk9wdHM7XG4gICAgdmFyIG9uQ29tcGxldGUgPSBvcHRzLm9uQ29tcGxldGU7XG5cbiAgICB2YXIgbnVtYmVycyA9IExpYi5lbnN1cmVTaW5nbGUocGxvdEdyb3VwLCAnZycsICdudW1iZXJzJyk7XG4gICAgdmFyIGJpZ251bWJlcmJCb3gsIGRlbHRhYkJveDtcbiAgICB2YXIgbnVtYmVyc2JCb3g7XG5cbiAgICB2YXIgZGF0YSA9IFtdO1xuICAgIGlmKHRyYWNlLl9oYXNOdW1iZXIpIGRhdGEucHVzaCgnbnVtYmVyJyk7XG4gICAgaWYodHJhY2UuX2hhc0RlbHRhKSB7XG4gICAgICAgIGRhdGEucHVzaCgnZGVsdGEnKTtcbiAgICAgICAgaWYodHJhY2UuZGVsdGEucG9zaXRpb24gPT09ICdsZWZ0JykgZGF0YS5yZXZlcnNlKCk7XG4gICAgfVxuICAgIHZhciBzZWwgPSBudW1iZXJzLnNlbGVjdEFsbCgndGV4dCcpLmRhdGEoZGF0YSk7XG4gICAgc2VsLmVudGVyKCkuYXBwZW5kKCd0ZXh0Jyk7XG4gICAgc2VsXG4gICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsIGZ1bmN0aW9uKCkge3JldHVybiBudW1iZXJzQW5jaG9yO30pXG4gICAgICAgIC5hdHRyKCdjbGFzcycsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQ7fSlcbiAgICAgICAgLmF0dHIoJ3gnLCBudWxsKVxuICAgICAgICAuYXR0cigneScsIG51bGwpXG4gICAgICAgIC5hdHRyKCdkeCcsIG51bGwpXG4gICAgICAgIC5hdHRyKCdkeScsIG51bGwpO1xuICAgIHNlbC5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAvLyBGdW5jdGlvbiB0byBvdmVycmlkZSB0aGUgbnVtYmVyIGZvcm1hdHRpbmcgdXNlZCBkdXJpbmcgdHJhbnNpdGlvbnNcbiAgICBmdW5jdGlvbiB0cmFuc2l0aW9uRm9ybWF0KHZhbHVlZm9ybWF0LCBmbXQsIGZyb20sIHRvKSB7XG4gICAgICAgIC8vIEZvciBub3csIGRvIG5vdCBkaXNwbGF5IFNJIHByZWZpeCBpZiBzdGFydCBhbmQgZW5kIHZhbHVlIGRvIG5vdCBoYXZlIGFueVxuICAgICAgICBpZih2YWx1ZWZvcm1hdC5tYXRjaCgncycpICYmIC8vIElmIHVzaW5nIFNJIHByZWZpeFxuICAgICAgICAgICAgKGZyb20gPj0gMCAhPT0gdG8gPj0gMCkgJiYgLy8gSWYgc2lnbiBjaGFuZ2VcbiAgICAgICAgICAgICghZm10KGZyb20pLnNsaWNlKC0xKS5tYXRjaChTSV9QUkVGSVgpICYmICFmbXQodG8pLnNsaWNlKC0xKS5tYXRjaChTSV9QUkVGSVgpKSAvLyBIYXMgbm8gU0kgcHJlZml4XG4gICAgICAgICkge1xuICAgICAgICAgICAgdmFyIHRyYW5zaXRpb25WYWx1ZUZvcm1hdCA9IHZhbHVlZm9ybWF0LnNsaWNlKCkucmVwbGFjZSgncycsICdmJykucmVwbGFjZSgvXFxkKy8sIGZ1bmN0aW9uKG0pIHsgcmV0dXJuIHBhcnNlSW50KG0pIC0gMTt9KTtcbiAgICAgICAgICAgIHZhciB0cmFuc2l0aW9uQXggPSBtb2NrQXhpcyhnZCwge3RpY2tmb3JtYXQ6IHRyYW5zaXRpb25WYWx1ZUZvcm1hdH0pO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICAvLyBTd2l0Y2ggdG8gZml4ZWQgcHJlY2lzaW9uIGlmIG51bWJlciBpcyBzbWFsbGVyIHRoYW4gb25lXG4gICAgICAgICAgICAgICAgaWYoTWF0aC5hYnModikgPCAxKSByZXR1cm4gQXhlcy50aWNrVGV4dCh0cmFuc2l0aW9uQXgsIHYpLnRleHQ7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZtdCh2KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZm10O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd0JpZ251bWJlcigpIHtcbiAgICAgICAgdmFyIGJpZ251bWJlckF4ID0gbW9ja0F4aXMoZ2QsIHt0aWNrZm9ybWF0OiB0cmFjZS5udW1iZXIudmFsdWVmb3JtYXR9LCB0cmFjZS5fcmFuZ2UpO1xuICAgICAgICBiaWdudW1iZXJBeC5zZXRTY2FsZSgpO1xuICAgICAgICBBeGVzLmNhbGNUaWNrcyhiaWdudW1iZXJBeCk7XG5cbiAgICAgICAgdmFyIGZtdCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIEF4ZXMudGlja1RleHQoYmlnbnVtYmVyQXgsIHYpLnRleHQ7fTtcbiAgICAgICAgdmFyIGJpZ251bWJlclN1ZmZpeCA9IHRyYWNlLm51bWJlci5zdWZmaXg7XG4gICAgICAgIHZhciBiaWdudW1iZXJQcmVmaXggPSB0cmFjZS5udW1iZXIucHJlZml4O1xuXG4gICAgICAgIHZhciBudW1iZXIgPSBudW1iZXJzLnNlbGVjdCgndGV4dC5udW1iZXInKTtcblxuICAgICAgICBmdW5jdGlvbiB3cml0ZU51bWJlcigpIHtcbiAgICAgICAgICAgIHZhciB0eHQgPSB0eXBlb2YgY2RbMF0ueSA9PT0gJ251bWJlcicgP1xuICAgICAgICAgICAgICAgIGJpZ251bWJlclByZWZpeCArIGZtdChjZFswXS55KSArIGJpZ251bWJlclN1ZmZpeCA6XG4gICAgICAgICAgICAgICAgJy0nO1xuICAgICAgICAgICAgbnVtYmVyLnRleHQodHh0KVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZm9udCwgdHJhY2UubnVtYmVyLmZvbnQpXG4gICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaGFzVHJhbnNpdGlvbih0cmFuc2l0aW9uT3B0cykpIHtcbiAgICAgICAgICAgIG51bWJlclxuICAgICAgICAgICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgICAgICAgICAuZHVyYXRpb24odHJhbnNpdGlvbk9wdHMuZHVyYXRpb24pXG4gICAgICAgICAgICAgICAgLmVhc2UodHJhbnNpdGlvbk9wdHMuZWFzaW5nKVxuICAgICAgICAgICAgICAgIC5lYWNoKCdlbmQnLCBmdW5jdGlvbigpIHsgd3JpdGVOdW1iZXIoKTsgb25Db21wbGV0ZSAmJiBvbkNvbXBsZXRlKCk7IH0pXG4gICAgICAgICAgICAgICAgLmVhY2goJ2ludGVycnVwdCcsIGZ1bmN0aW9uKCkgeyB3cml0ZU51bWJlcigpOyBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUoKTsgfSlcbiAgICAgICAgICAgICAgICAuYXR0clR3ZWVuKCd0ZXh0JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaW50ZXJwb2xhdG9yID0gZDMuaW50ZXJwb2xhdGVOdW1iZXIoY2RbMF0ubGFzdFksIGNkWzBdLnkpO1xuICAgICAgICAgICAgICAgICAgICB0cmFjZS5fbGFzdFZhbHVlID0gY2RbMF0ueTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgdHJhbnNpdGlvbkZtdCA9IHRyYW5zaXRpb25Gb3JtYXQodHJhY2UubnVtYmVyLnZhbHVlZm9ybWF0LCBmbXQsIGNkWzBdLmxhc3RZLCBjZFswXS55KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQudGV4dChiaWdudW1iZXJQcmVmaXggKyB0cmFuc2l0aW9uRm10KGludGVycG9sYXRvcih0KSkgKyBiaWdudW1iZXJTdWZmaXgpO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd3JpdGVOdW1iZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJpZ251bWJlcmJCb3ggPSBtZWFzdXJlVGV4dChiaWdudW1iZXJQcmVmaXggKyBmbXQoY2RbMF0ueSkgKyBiaWdudW1iZXJTdWZmaXgsIHRyYWNlLm51bWJlci5mb250LCBudW1iZXJzQW5jaG9yLCBnZCk7XG4gICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd0RlbHRhKCkge1xuICAgICAgICB2YXIgZGVsdGFBeCA9IG1vY2tBeGlzKGdkLCB7dGlja2Zvcm1hdDogdHJhY2UuZGVsdGEudmFsdWVmb3JtYXR9LCB0cmFjZS5fcmFuZ2UpO1xuICAgICAgICBkZWx0YUF4LnNldFNjYWxlKCk7XG4gICAgICAgIEF4ZXMuY2FsY1RpY2tzKGRlbHRhQXgpO1xuXG4gICAgICAgIHZhciBkZWx0YUZtdCA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIEF4ZXMudGlja1RleHQoZGVsdGFBeCwgdikudGV4dDt9O1xuICAgICAgICB2YXIgZGVsdGFWYWx1ZSA9IGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IHRyYWNlLmRlbHRhLnJlbGF0aXZlID8gZC5yZWxhdGl2ZURlbHRhIDogZC5kZWx0YTtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGRlbHRhRm9ybWF0VGV4dCA9IGZ1bmN0aW9uKHZhbHVlLCBudW1iZXJGbXQpIHtcbiAgICAgICAgICAgIGlmKHZhbHVlID09PSAwIHx8IHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicgfHwgaXNOYU4odmFsdWUpKSByZXR1cm4gJy0nO1xuICAgICAgICAgICAgcmV0dXJuICh2YWx1ZSA+IDAgPyB0cmFjZS5kZWx0YS5pbmNyZWFzaW5nLnN5bWJvbCA6IHRyYWNlLmRlbHRhLmRlY3JlYXNpbmcuc3ltYm9sKSArIG51bWJlckZtdCh2YWx1ZSk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBkZWx0YUZpbGwgPSBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5kZWx0YSA+PSAwID8gdHJhY2UuZGVsdGEuaW5jcmVhc2luZy5jb2xvciA6IHRyYWNlLmRlbHRhLmRlY3JlYXNpbmcuY29sb3I7XG4gICAgICAgIH07XG4gICAgICAgIGlmKHRyYWNlLl9kZWx0YUxhc3RWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0cmFjZS5fZGVsdGFMYXN0VmFsdWUgPSBkZWx0YVZhbHVlKGNkWzBdKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGVsdGEgPSBudW1iZXJzLnNlbGVjdCgndGV4dC5kZWx0YScpO1xuICAgICAgICBkZWx0YVxuICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCB0cmFjZS5kZWx0YS5mb250KVxuICAgICAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgZGVsdGFGaWxsKHtkZWx0YTogdHJhY2UuX2RlbHRhTGFzdFZhbHVlfSkpO1xuXG4gICAgICAgIGZ1bmN0aW9uIHdyaXRlRGVsdGEoKSB7XG4gICAgICAgICAgICBkZWx0YS50ZXh0KGRlbHRhRm9ybWF0VGV4dChkZWx0YVZhbHVlKGNkWzBdKSwgZGVsdGFGbXQpKVxuICAgICAgICAgICAgICAgIC5jYWxsKENvbG9yLmZpbGwsIGRlbHRhRmlsbChjZFswXSkpXG4gICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaGFzVHJhbnNpdGlvbih0cmFuc2l0aW9uT3B0cykpIHtcbiAgICAgICAgICAgIGRlbHRhXG4gICAgICAgICAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgICAgIC5kdXJhdGlvbih0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbilcbiAgICAgICAgICAgICAgICAuZWFzZSh0cmFuc2l0aW9uT3B0cy5lYXNpbmcpXG4gICAgICAgICAgICAgICAgLnR3ZWVuKCd0ZXh0JywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdG8gPSBkZWx0YVZhbHVlKGNkWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZyb20gPSB0cmFjZS5fZGVsdGFMYXN0VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmFuc2l0aW9uRm10ID0gdHJhbnNpdGlvbkZvcm1hdCh0cmFjZS5kZWx0YS52YWx1ZWZvcm1hdCwgZGVsdGFGbXQsIGZyb20sIHRvKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGludGVycG9sYXRvciA9IGQzLmludGVycG9sYXRlTnVtYmVyKGZyb20sIHRvKTtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2UuX2RlbHRhTGFzdFZhbHVlID0gdG87XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGF0LnRleHQoZGVsdGFGb3JtYXRUZXh0KGludGVycG9sYXRvcih0KSwgdHJhbnNpdGlvbkZtdCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC5jYWxsKENvbG9yLmZpbGwsIGRlbHRhRmlsbCh7ZGVsdGE6IGludGVycG9sYXRvcih0KX0pKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5lYWNoKCdlbmQnLCBmdW5jdGlvbigpIHsgd3JpdGVEZWx0YSgpOyBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUoKTsgfSlcbiAgICAgICAgICAgICAgICAuZWFjaCgnaW50ZXJydXB0JywgZnVuY3Rpb24oKSB7IHdyaXRlRGVsdGEoKTsgb25Db21wbGV0ZSAmJiBvbkNvbXBsZXRlKCk7IH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd3JpdGVEZWx0YSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVsdGFiQm94ID0gbWVhc3VyZVRleHQoZGVsdGFGb3JtYXRUZXh0KGRlbHRhVmFsdWUoY2RbMF0pLCBkZWx0YUZtdCksIHRyYWNlLmRlbHRhLmZvbnQsIG51bWJlcnNBbmNob3IsIGdkKTtcbiAgICAgICAgcmV0dXJuIGRlbHRhO1xuICAgIH1cblxuICAgIHZhciBrZXkgPSB0cmFjZS5tb2RlICsgdHJhY2UuYWxpZ247XG4gICAgdmFyIGRlbHRhO1xuICAgIGlmKHRyYWNlLl9oYXNEZWx0YSkge1xuICAgICAgICBkZWx0YSA9IGRyYXdEZWx0YSgpO1xuICAgICAgICBrZXkgKz0gdHJhY2UuZGVsdGEucG9zaXRpb24gKyB0cmFjZS5kZWx0YS5mb250LnNpemUgKyB0cmFjZS5kZWx0YS5mb250LmZhbWlseSArIHRyYWNlLmRlbHRhLnZhbHVlZm9ybWF0O1xuICAgICAgICBrZXkgKz0gdHJhY2UuZGVsdGEuaW5jcmVhc2luZy5zeW1ib2wgKyB0cmFjZS5kZWx0YS5kZWNyZWFzaW5nLnN5bWJvbDtcbiAgICAgICAgbnVtYmVyc2JCb3ggPSBkZWx0YWJCb3g7XG4gICAgfVxuICAgIGlmKHRyYWNlLl9oYXNOdW1iZXIpIHtcbiAgICAgICAgZHJhd0JpZ251bWJlcigpO1xuICAgICAgICBrZXkgKz0gdHJhY2UubnVtYmVyLmZvbnQuc2l6ZSArIHRyYWNlLm51bWJlci5mb250LmZhbWlseSArIHRyYWNlLm51bWJlci52YWx1ZWZvcm1hdCArIHRyYWNlLm51bWJlci5zdWZmaXggKyB0cmFjZS5udW1iZXIucHJlZml4O1xuICAgICAgICBudW1iZXJzYkJveCA9IGJpZ251bWJlcmJCb3g7XG4gICAgfVxuXG4gICAgLy8gUG9zaXRpb24gZGVsdGEgcmVsYXRpdmUgdG8gYmlnbnVtYmVyXG4gICAgaWYodHJhY2UuX2hhc0RlbHRhICYmIHRyYWNlLl9oYXNOdW1iZXIpIHtcbiAgICAgICAgdmFyIGJpZ251bWJlckNlbnRlciA9IFtcbiAgICAgICAgICAgIChiaWdudW1iZXJiQm94LmxlZnQgKyBiaWdudW1iZXJiQm94LnJpZ2h0KSAvIDIsXG4gICAgICAgICAgICAoYmlnbnVtYmVyYkJveC50b3AgKyBiaWdudW1iZXJiQm94LmJvdHRvbSkgLyAyXG4gICAgICAgIF07XG4gICAgICAgIHZhciBkZWx0YUNlbnRlciA9IFtcbiAgICAgICAgICAgIChkZWx0YWJCb3gubGVmdCArIGRlbHRhYkJveC5yaWdodCkgLyAyLFxuICAgICAgICAgICAgKGRlbHRhYkJveC50b3AgKyBkZWx0YWJCb3guYm90dG9tKSAvIDJcbiAgICAgICAgXTtcblxuICAgICAgICB2YXIgZHgsIGR5O1xuICAgICAgICB2YXIgcGFkZGluZyA9IDAuNzUgKiB0cmFjZS5kZWx0YS5mb250LnNpemU7XG4gICAgICAgIGlmKHRyYWNlLmRlbHRhLnBvc2l0aW9uID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgIGR4ID0gY2FjaGUodHJhY2UsICdkZWx0YVBvcycsIDAsIC0xICogKGJpZ251bWJlcmJCb3gud2lkdGggKiAocG9zaXRpb25bdHJhY2UuYWxpZ25dKSArIGRlbHRhYkJveC53aWR0aCAqICgxIC0gcG9zaXRpb25bdHJhY2UuYWxpZ25dKSArIHBhZGRpbmcpLCBrZXksIE1hdGgubWluKTtcbiAgICAgICAgICAgIGR5ID0gYmlnbnVtYmVyQ2VudGVyWzFdIC0gZGVsdGFDZW50ZXJbMV07XG5cbiAgICAgICAgICAgIG51bWJlcnNiQm94ID0ge1xuICAgICAgICAgICAgICAgIHdpZHRoOiBiaWdudW1iZXJiQm94LndpZHRoICsgZGVsdGFiQm94LndpZHRoICsgcGFkZGluZyxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IE1hdGgubWF4KGJpZ251bWJlcmJCb3guaGVpZ2h0LCBkZWx0YWJCb3guaGVpZ2h0KSxcbiAgICAgICAgICAgICAgICBsZWZ0OiBkZWx0YWJCb3gubGVmdCArIGR4LFxuICAgICAgICAgICAgICAgIHJpZ2h0OiBiaWdudW1iZXJiQm94LnJpZ2h0LFxuICAgICAgICAgICAgICAgIHRvcDogTWF0aC5taW4oYmlnbnVtYmVyYkJveC50b3AsIGRlbHRhYkJveC50b3AgKyBkeSksXG4gICAgICAgICAgICAgICAgYm90dG9tOiBNYXRoLm1heChiaWdudW1iZXJiQm94LmJvdHRvbSwgZGVsdGFiQm94LmJvdHRvbSArIGR5KVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBpZih0cmFjZS5kZWx0YS5wb3NpdGlvbiA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICAgICAgZHggPSBjYWNoZSh0cmFjZSwgJ2RlbHRhUG9zJywgMCwgYmlnbnVtYmVyYkJveC53aWR0aCAqICgxIC0gcG9zaXRpb25bdHJhY2UuYWxpZ25dKSArIGRlbHRhYkJveC53aWR0aCAqIHBvc2l0aW9uW3RyYWNlLmFsaWduXSArIHBhZGRpbmcsIGtleSwgTWF0aC5tYXgpO1xuICAgICAgICAgICAgZHkgPSBiaWdudW1iZXJDZW50ZXJbMV0gLSBkZWx0YUNlbnRlclsxXTtcblxuICAgICAgICAgICAgbnVtYmVyc2JCb3ggPSB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IGJpZ251bWJlcmJCb3gud2lkdGggKyBkZWx0YWJCb3gud2lkdGggKyBwYWRkaW5nLFxuICAgICAgICAgICAgICAgIGhlaWdodDogTWF0aC5tYXgoYmlnbnVtYmVyYkJveC5oZWlnaHQsIGRlbHRhYkJveC5oZWlnaHQpLFxuICAgICAgICAgICAgICAgIGxlZnQ6IGJpZ251bWJlcmJCb3gubGVmdCxcbiAgICAgICAgICAgICAgICByaWdodDogZGVsdGFiQm94LnJpZ2h0ICsgZHgsXG4gICAgICAgICAgICAgICAgdG9wOiBNYXRoLm1pbihiaWdudW1iZXJiQm94LnRvcCwgZGVsdGFiQm94LnRvcCArIGR5KSxcbiAgICAgICAgICAgICAgICBib3R0b206IE1hdGgubWF4KGJpZ251bWJlcmJCb3guYm90dG9tLCBkZWx0YWJCb3guYm90dG9tICsgZHkpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmKHRyYWNlLmRlbHRhLnBvc2l0aW9uID09PSAnYm90dG9tJykge1xuICAgICAgICAgICAgZHggPSBudWxsO1xuICAgICAgICAgICAgZHkgPSBkZWx0YWJCb3guaGVpZ2h0O1xuXG4gICAgICAgICAgICBudW1iZXJzYkJveCA9IHtcbiAgICAgICAgICAgICAgICB3aWR0aDogTWF0aC5tYXgoYmlnbnVtYmVyYkJveC53aWR0aCwgZGVsdGFiQm94LndpZHRoKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGJpZ251bWJlcmJCb3guaGVpZ2h0ICsgZGVsdGFiQm94LmhlaWdodCxcbiAgICAgICAgICAgICAgICBsZWZ0OiBNYXRoLm1pbihiaWdudW1iZXJiQm94LmxlZnQsIGRlbHRhYkJveC5sZWZ0KSxcbiAgICAgICAgICAgICAgICByaWdodDogTWF0aC5tYXgoYmlnbnVtYmVyYkJveC5yaWdodCwgZGVsdGFiQm94LnJpZ2h0KSxcbiAgICAgICAgICAgICAgICB0b3A6IGJpZ251bWJlcmJCb3guYm90dG9tIC0gYmlnbnVtYmVyYkJveC5oZWlnaHQsXG4gICAgICAgICAgICAgICAgYm90dG9tOiBiaWdudW1iZXJiQm94LmJvdHRvbSArIGRlbHRhYkJveC5oZWlnaHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYodHJhY2UuZGVsdGEucG9zaXRpb24gPT09ICd0b3AnKSB7XG4gICAgICAgICAgICBkeCA9IG51bGw7XG4gICAgICAgICAgICBkeSA9IGJpZ251bWJlcmJCb3gudG9wO1xuXG4gICAgICAgICAgICBudW1iZXJzYkJveCA9IHtcbiAgICAgICAgICAgICAgICB3aWR0aDogTWF0aC5tYXgoYmlnbnVtYmVyYkJveC53aWR0aCwgZGVsdGFiQm94LndpZHRoKSxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGJpZ251bWJlcmJCb3guaGVpZ2h0ICsgZGVsdGFiQm94LmhlaWdodCxcbiAgICAgICAgICAgICAgICBsZWZ0OiBNYXRoLm1pbihiaWdudW1iZXJiQm94LmxlZnQsIGRlbHRhYkJveC5sZWZ0KSxcbiAgICAgICAgICAgICAgICByaWdodDogTWF0aC5tYXgoYmlnbnVtYmVyYkJveC5yaWdodCwgZGVsdGFiQm94LnJpZ2h0KSxcbiAgICAgICAgICAgICAgICB0b3A6IGJpZ251bWJlcmJCb3guYm90dG9tIC0gYmlnbnVtYmVyYkJveC5oZWlnaHQgLSBkZWx0YWJCb3guaGVpZ2h0LFxuICAgICAgICAgICAgICAgIGJvdHRvbTogYmlnbnVtYmVyYkJveC5ib3R0b21cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBkZWx0YS5hdHRyKHtkeDogZHgsIGR5OiBkeX0pO1xuICAgIH1cblxuICAgIC8vIFJlc2l6ZSBudW1iZXJzIHRvIGZpdCB3aXRoaW4gc3BhY2UgYW5kIHBvc2l0aW9uXG4gICAgaWYodHJhY2UuX2hhc051bWJlciB8fCB0cmFjZS5faGFzRGVsdGEpIHtcbiAgICAgICAgbnVtYmVycy5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBtID0gb3B0cy5udW1iZXJzU2NhbGVyKG51bWJlcnNiQm94KTtcbiAgICAgICAgICAgIGtleSArPSBtWzJdO1xuICAgICAgICAgICAgdmFyIHNjYWxlUmF0aW8gPSBjYWNoZSh0cmFjZSwgJ251bWJlcnNTY2FsZScsIDEsIG1bMF0sIGtleSwgTWF0aC5taW4pO1xuICAgICAgICAgICAgdmFyIHRyYW5zbGF0ZVk7XG4gICAgICAgICAgICBpZighdHJhY2UuX3NjYWxlTnVtYmVycykgc2NhbGVSYXRpbyA9IDE7XG4gICAgICAgICAgICBpZih0cmFjZS5faXNBbmd1bGFyKSB7XG4gICAgICAgICAgICAgICAgLy8gYWxpZ24gdmVydGljYWxseSB0byBib3R0b21cbiAgICAgICAgICAgICAgICB0cmFuc2xhdGVZID0gbnVtYmVyc1kgLSBzY2FsZVJhdGlvICogbnVtYmVyc2JCb3guYm90dG9tO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBhbGlnbiB2ZXJ0aWNhbGx5IHRvIGNlbnRlclxuICAgICAgICAgICAgICAgIHRyYW5zbGF0ZVkgPSBudW1iZXJzWSAtIHNjYWxlUmF0aW8gKiAobnVtYmVyc2JCb3gudG9wICsgbnVtYmVyc2JCb3guYm90dG9tKSAvIDI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0YXNoIHRoZSB0b3AgcG9zaXRpb24gb2YgbnVtYmVyc2JCb3ggZm9yIHRpdGxlIHBvc2l0aW9uaW5nXG4gICAgICAgICAgICB0cmFjZS5fbnVtYmVyc1RvcCA9IHNjYWxlUmF0aW8gKiAobnVtYmVyc2JCb3gudG9wKSArIHRyYW5zbGF0ZVk7XG5cbiAgICAgICAgICAgIHZhciByZWYgPSBudW1iZXJzYkJveFtudW1iZXJzQWxpZ25dO1xuICAgICAgICAgICAgaWYobnVtYmVyc0FsaWduID09PSAnY2VudGVyJykgcmVmID0gKG51bWJlcnNiQm94LmxlZnQgKyBudW1iZXJzYkJveC5yaWdodCkgLyAyO1xuICAgICAgICAgICAgdmFyIHRyYW5zbGF0ZVggPSBudW1iZXJzWCAtIHNjYWxlUmF0aW8gKiByZWY7XG5cbiAgICAgICAgICAgIC8vIFN0YXNoIHRyYW5zbGF0ZVhcbiAgICAgICAgICAgIHRyYW5zbGF0ZVggPSBjYWNoZSh0cmFjZSwgJ251bWJlcnNUcmFuc2xhdGUnLCAwLCB0cmFuc2xhdGVYLCBrZXksIE1hdGgubWF4KTtcbiAgICAgICAgICAgIHJldHVybiBzdHJUcmFuc2xhdGUodHJhbnNsYXRlWCwgdHJhbnNsYXRlWSkgKyAnIHNjYWxlKCcgKyBzY2FsZVJhdGlvICsgJyknO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cbi8vIEFwcGx5IGZpbGwsIHN0cm9rZSwgc3Ryb2tlLXdpZHRoIHRvIFNWRyBzaGFwZVxuZnVuY3Rpb24gc3R5bGVTaGFwZShwKSB7XG4gICAgcFxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7IENvbG9yLnN0cm9rZShkMy5zZWxlY3QodGhpcyksIGQubGluZS5jb2xvcik7fSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkgeyBDb2xvci5maWxsKGQzLnNlbGVjdCh0aGlzKSwgZC5jb2xvcik7fSlcbiAgICAgICAgLnN0eWxlKCdzdHJva2Utd2lkdGgnLCBmdW5jdGlvbihkKSB7IHJldHVybiBkLmxpbmUud2lkdGg7fSk7XG59XG5cbi8vIFJldHVybnMgYSB0d2VlbiBmb3IgYSB0cmFuc2l0aW9u4oCZcyBcImRcIiBhdHRyaWJ1dGUsIHRyYW5zaXRpb25pbmcgYW55IHNlbGVjdGVkXG4vLyBhcmNzIGZyb20gdGhlaXIgY3VycmVudCBhbmdsZSB0byB0aGUgc3BlY2lmaWVkIG5ldyBhbmdsZS5cbmZ1bmN0aW9uIGFyY1R3ZWVuKGFyYywgZW5kQW5nbGUsIG5ld0FuZ2xlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgaW50ZXJwb2xhdGUgPSBkMy5pbnRlcnBvbGF0ZShlbmRBbmdsZSwgbmV3QW5nbGUpO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgICAgICAgcmV0dXJuIGFyYy5lbmRBbmdsZShpbnRlcnBvbGF0ZSh0KSkoKTtcbiAgICAgICAgfTtcbiAgICB9O1xufVxuXG4vLyBtb2NrcyBvdXIgYXhpc1xuZnVuY3Rpb24gbW9ja0F4aXMoZ2QsIG9wdHMsIHpyYW5nZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICB2YXIgYXhpc0luID0gTGliLmV4dGVuZEZsYXQoe1xuICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgdGlja3M6ICdvdXRzaWRlJyxcbiAgICAgICAgcmFuZ2U6IHpyYW5nZSxcbiAgICAgICAgc2hvd2xpbmU6IHRydWVcbiAgICB9LCBvcHRzKTtcblxuICAgIHZhciBheGlzT3V0ID0ge1xuICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgX2lkOiAneCcgKyBvcHRzLl9pZFxuICAgIH07XG5cbiAgICB2YXIgYXhpc09wdGlvbnMgPSB7XG4gICAgICAgIGxldHRlcjogJ3gnLFxuICAgICAgICBmb250OiBmdWxsTGF5b3V0LmZvbnQsXG4gICAgICAgIG5vSG92ZXI6IHRydWUsXG4gICAgICAgIG5vVGlja3NvbjogdHJ1ZVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShheGlzSW4sIGF4aXNPdXQsIGF4aXNMYXlvdXRBdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgaGFuZGxlQXhpc0RlZmF1bHRzKGF4aXNJbiwgYXhpc091dCwgY29lcmNlLCBheGlzT3B0aW9ucywgZnVsbExheW91dCk7XG4gICAgaGFuZGxlQXhpc1Bvc2l0aW9uRGVmYXVsdHMoYXhpc0luLCBheGlzT3V0LCBjb2VyY2UsIGF4aXNPcHRpb25zKTtcblxuICAgIHJldHVybiBheGlzT3V0O1xufVxuXG5mdW5jdGlvbiBzdHJUcmFuc2xhdGUoeCwgeSkge1xuICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyB4ICsgJywnICsgeSArICcpJztcbn1cblxuZnVuY3Rpb24gZml0VGV4dEluc2lkZUJveCh0ZXh0QkIsIHdpZHRoLCBoZWlnaHQpIHtcbiAgICAvLyBjb21wdXRlIHNjYWxpbmcgcmF0aW8gdG8gaGF2ZSB0ZXh0IGZpdCB3aXRoaW4gc3BlY2lmaWVkIHdpZHRoIGFuZCBoZWlnaHRcbiAgICB2YXIgcmF0aW8gPSBNYXRoLm1pbih3aWR0aCAvIHRleHRCQi53aWR0aCwgaGVpZ2h0IC8gdGV4dEJCLmhlaWdodCk7XG4gICAgcmV0dXJuIFtyYXRpbywgdGV4dEJCLCB3aWR0aCArICd4JyArIGhlaWdodF07XG59XG5cbmZ1bmN0aW9uIGZpdFRleHRJbnNpZGVDaXJjbGUodGV4dEJCLCByYWRpdXMpIHtcbiAgICAvLyBjb21wdXRlIHNjYWxpbmcgcmF0aW8gdG8gaGF2ZSB0ZXh0IGZpdCB3aXRoaW4gc3BlY2lmaWVkIHJhZGl1c1xuICAgIHZhciBlbFJhZGl1cyA9IE1hdGguc3FydCgodGV4dEJCLndpZHRoIC8gMikgKiAodGV4dEJCLndpZHRoIC8gMikgKyB0ZXh0QkIuaGVpZ2h0ICogdGV4dEJCLmhlaWdodCk7XG4gICAgdmFyIHJhdGlvID0gcmFkaXVzIC8gZWxSYWRpdXM7XG4gICAgcmV0dXJuIFtyYXRpbywgdGV4dEJCLCByYWRpdXNdO1xufVxuXG5mdW5jdGlvbiBtZWFzdXJlVGV4dCh0eHQsIGZvbnQsIHRleHRBbmNob3IsIGdkKSB7XG4gICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJywgJ3RleHQnKTtcbiAgICB2YXIgc2VsID0gZDMuc2VsZWN0KGVsZW1lbnQpO1xuICAgIHNlbC50ZXh0KHR4dClcbiAgICAgIC5hdHRyKCd4JywgMClcbiAgICAgIC5hdHRyKCd5JywgMClcbiAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsIHRleHRBbmNob3IpXG4gICAgICAuYXR0cignZGF0YS11bmZvcm1hdHRlZCcsIHR4dClcbiAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKVxuICAgICAgLmNhbGwoRHJhd2luZy5mb250LCBmb250KTtcbiAgICByZXR1cm4gRHJhd2luZy5iQm94KHNlbC5ub2RlKCkpO1xufVxuXG5mdW5jdGlvbiBjYWNoZSh0cmFjZSwgbmFtZSwgaW5pdGlhbFZhbHVlLCB2YWx1ZSwga2V5LCBmbikge1xuICAgIHZhciBvYmpOYW1lID0gJ19jYWNoZScgKyBuYW1lO1xuICAgIGlmKCEodHJhY2Vbb2JqTmFtZV0gJiYgdHJhY2Vbb2JqTmFtZV0ua2V5ID09PSBrZXkpKSB7XG4gICAgICAgIHRyYWNlW29iak5hbWVdID0ge2tleToga2V5LCB2YWx1ZTogaW5pdGlhbFZhbHVlfTtcbiAgICB9XG4gICAgdmFyIHYgPSBMaWIuYWdnTnVtcyhmbiwgbnVsbCwgW3RyYWNlW29iak5hbWVdLnZhbHVlLCB2YWx1ZV0sIDIpO1xuICAgIHRyYWNlW29iak5hbWVdLnZhbHVlID0gdjtcblxuICAgIHJldHVybiB2O1xufVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9jb25zdGFudHMvYWxpZ25tZW50XCI6Njg4LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzXCI6NzQzLFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19kZWZhdWx0c1wiOjc2OSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlc1wiOjc3OSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9wb3NpdGlvbl9kZWZhdWx0c1wiOjc4MixcIi4vY29uc3RhbnRzXCI6MTA0NCxcImQzXCI6MTYzfV0sMTA0ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGhvdmVydGVtcGxhdGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzJyk7XG52YXIgbWVzaEF0dHJzID0gX2RlcmVxXygnLi4vbWVzaDNkL2F0dHJpYnV0ZXMnKTtcbnZhciBiYXNlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbmZ1bmN0aW9uIG1ha2VTbGljZUF0dHIoYXhMZXR0ZXIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBzaG93OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxvY2F0aW9uczoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgZGZsdDogW10sXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBmaWxsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxLFxuICAgICAgICAgICAgZGZsdDogMSxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gbWFrZUNhcEF0dHIoYXhMZXR0ZXIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBzaG93OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZmlsbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMSxcbiAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH07XG59XG5cbnZhciBhdHRycyA9IG1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoZXh0ZW5kRmxhdCh7XG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICB6OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmFsdWU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBpc29taW46IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGlzb21heDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBzdXJmYWNlOiB7XG4gICAgICAgIHNob3c6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBjb3VudDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2ludGVnZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiAyLFxuICAgICAgICAgICAgbWluOiAxLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGZpbGw6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHBhdHRlcm46IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdmbGFnbGlzdCcsXG4gICAgICAgICAgICBmbGFnczogWydBJywgJ0InLCAnQycsICdEJywgJ0UnXSxcbiAgICAgICAgICAgIGV4dHJhczogWydhbGwnLCAnb2RkJywgJ2V2ZW4nXSxcbiAgICAgICAgICAgIGRmbHQ6ICdhbGwnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBzcGFjZWZyYW1lOiB7XG4gICAgICAgIHNob3c6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZmlsbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMSxcbiAgICAgICAgICAgIGRmbHQ6IDAuMTUsXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBzbGljZXM6IHtcbiAgICAgICAgeDogbWFrZVNsaWNlQXR0cigneCcpLFxuICAgICAgICB5OiBtYWtlU2xpY2VBdHRyKCd5JyksXG4gICAgICAgIHo6IG1ha2VTbGljZUF0dHIoJ3onKVxuICAgIH0sXG5cbiAgICBjYXBzOiB7XG4gICAgICAgIHg6IG1ha2VDYXBBdHRyKCd4JyksXG4gICAgICAgIHk6IG1ha2VDYXBBdHRyKCd5JyksXG4gICAgICAgIHo6IG1ha2VDYXBBdHRyKCd6JylcbiAgICB9LFxuXG4gICAgdGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVydGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycygpXG59LFxuXG5jb2xvclNjYWxlQXR0cnMoJycsIHtcbiAgICBjb2xvckF0dHI6ICdgdmFsdWVgJyxcbiAgICBzaG93U2NhbGVEZmx0OiB0cnVlLFxuICAgIGVkaXRUeXBlT3ZlcnJpZGU6ICdjYWxjJ1xufSksIHtcbiAgICBvcGFjaXR5OiBtZXNoQXR0cnMub3BhY2l0eSxcbiAgICBsaWdodHBvc2l0aW9uOiBtZXNoQXR0cnMubGlnaHRwb3NpdGlvbixcbiAgICBsaWdodGluZzogbWVzaEF0dHJzLmxpZ2h0aW5nLFxuICAgIGZsYXRzaGFkaW5nOiBtZXNoQXR0cnMuZmxhdHNoYWRpbmcsXG4gICAgY29udG91cjogbWVzaEF0dHJzLmNvbnRvdXIsXG5cbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIGJhc2VBdHRycy5ob3ZlcmluZm8pXG59KSwgJ2NhbGMnLCAnbmVzdGVkJyk7XG5cbi8vIHJlcXVpcmVkIGRlZmF1bHRzIHRvIHNwZWVkIHVwIHN1cmZhY2Ugbm9ybWFsIGNhbGN1bGF0aW9uc1xuYXR0cnMuZmxhdHNoYWRpbmcuZGZsdCA9IHRydWU7IGF0dHJzLmxpZ2h0aW5nLmZhY2Vub3JtYWxzZXBzaWxvbi5kZmx0ID0gMDtcblxuYXR0cnMueC5lZGl0VHlwZSA9IGF0dHJzLnkuZWRpdFR5cGUgPSBhdHRycy56LmVkaXRUeXBlID0gYXR0cnMudmFsdWUuZWRpdFR5cGUgPSAnY2FsYytjbGVhckF4aXNUeXBlcyc7XG5hdHRycy50cmFuc2Zvcm1zID0gdW5kZWZpbmVkO1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzXCI6NjAwLFwiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXNcIjo2MzEsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlc1wiOjc1MCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9tZXNoM2QvYXR0cmlidXRlc1wiOjEwNTN9XSwxMDQ5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yc2NhbGVDYWxjID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHRyYWNlLl9sZW4gPSBNYXRoLm1pbih0cmFjZS54Lmxlbmd0aCwgdHJhY2UueS5sZW5ndGgsIHRyYWNlLnoubGVuZ3RoLCB0cmFjZS52YWx1ZS5sZW5ndGgpO1xuXG4gICAgdmFyIG1pbiA9IEluZmluaXR5O1xuICAgIHZhciBtYXggPSAtSW5maW5pdHk7XG4gICAgdmFyIGxlbiA9IHRyYWNlLnZhbHVlLmxlbmd0aDtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIHYgPSB0cmFjZS52YWx1ZVtpXTtcbiAgICAgICAgbWluID0gTWF0aC5taW4obWluLCB2KTtcbiAgICAgICAgbWF4ID0gTWF0aC5tYXgobWF4LCB2KTtcbiAgICB9XG5cbiAgICB0cmFjZS5fbWluVmFsdWVzID0gbWluO1xuICAgIHRyYWNlLl9tYXhWYWx1ZXMgPSBtYXg7XG5cbiAgICB0cmFjZS5fdk1pbiA9ICh0cmFjZS5pc29taW4gPT09IHVuZGVmaW5lZCB8fCB0cmFjZS5pc29taW4gPT09IG51bGwpID8gbWluIDogdHJhY2UuaXNvbWluO1xuICAgIHRyYWNlLl92TWF4ID0gKHRyYWNlLmlzb21heCA9PT0gdW5kZWZpbmVkIHx8IHRyYWNlLmlzb21pbiA9PT0gbnVsbCkgPyBtYXggOiB0cmFjZS5pc29tYXg7XG5cbiAgICBjb2xvcnNjYWxlQ2FsYyhnZCwgdHJhY2UsIHtcbiAgICAgICAgdmFsczogW3RyYWNlLl92TWluLCB0cmFjZS5fdk1heF0sXG4gICAgICAgIGNvbnRhaW5lclN0cjogJycsXG4gICAgICAgIGNMZXR0ZXI6ICdjJ1xuICAgIH0pO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsY1wiOjYwMX1dLDEwNTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3JlYXRlTWVzaCA9IF9kZXJlcV8oJ2dsLW1lc2gzZCcpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBwYXJzZUNvbG9yU2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9saWIvZ2xfZm9ybWF0X2NvbG9yJykucGFyc2VDb2xvclNjYWxlO1xudmFyIHN0cjJSZ2JhQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3RyMnJnYmFycmF5Jyk7XG52YXIgZXh0cmFjdE9wdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKS5leHRyYWN0T3B0cztcbnZhciB6aXAzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2wzZC96aXAzJyk7XG5cbmZ1bmN0aW9uIGRpc3RpbmN0VmFscyhjb2wpIHtcbiAgICByZXR1cm4gTGliLmRpc3RpbmN0VmFscyhjb2wpLnZhbHM7XG59XG5cbnZhciBmaW5kTmVhcmVzdE9uQXhpcyA9IGZ1bmN0aW9uKHcsIGFycikge1xuICAgIGZvcih2YXIgcSA9IGFyci5sZW5ndGggLSAxOyBxID4gMDsgcS0tKSB7XG4gICAgICAgIHZhciBtaW4gPSBNYXRoLm1pbihhcnJbcV0sIGFycltxIC0gMV0pO1xuICAgICAgICB2YXIgbWF4ID0gTWF0aC5tYXgoYXJyW3FdLCBhcnJbcSAtIDFdKTtcbiAgICAgICAgaWYobWF4ID4gbWluICYmIG1pbiA8IHcgJiYgdyA8PSBtYXgpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaWQ6IHEsXG4gICAgICAgICAgICAgICAgZGlzdFJhdGlvOiAobWF4IC0gdykgLyAobWF4IC0gbWluKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBpZDogMCxcbiAgICAgICAgZGlzdFJhdGlvOiAwXG4gICAgfTtcbn07XG5cbmZ1bmN0aW9uIElzb3N1cmZhY2VUcmFjZShzY2VuZSwgbWVzaCwgdWlkKSB7XG4gICAgdGhpcy5zY2VuZSA9IHNjZW5lO1xuICAgIHRoaXMudWlkID0gdWlkO1xuICAgIHRoaXMubWVzaCA9IG1lc2g7XG4gICAgdGhpcy5uYW1lID0gJyc7XG4gICAgdGhpcy5kYXRhID0gbnVsbDtcbiAgICB0aGlzLnNob3dDb250b3VyID0gZmFsc2U7XG59XG5cbnZhciBwcm90byA9IElzb3N1cmZhY2VUcmFjZS5wcm90b3R5cGU7XG5cbnByb3RvLmhhbmRsZVBpY2sgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcbiAgICBpZihzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLm1lc2gpIHtcbiAgICAgICAgdmFyIHJhd0lkID0gc2VsZWN0aW9uLmRhdGEuaW5kZXg7XG5cbiAgICAgICAgdmFyIHggPSB0aGlzLmRhdGEuX3hbcmF3SWRdO1xuICAgICAgICB2YXIgeSA9IHRoaXMuZGF0YS5feVtyYXdJZF07XG4gICAgICAgIHZhciB6ID0gdGhpcy5kYXRhLl96W3Jhd0lkXTtcblxuICAgICAgICB2YXIgaGVpZ2h0ID0gdGhpcy5kYXRhLl9Zcy5sZW5ndGg7XG4gICAgICAgIHZhciBkZXB0aCA9IHRoaXMuZGF0YS5fWnMubGVuZ3RoO1xuXG4gICAgICAgIHZhciBpID0gZmluZE5lYXJlc3RPbkF4aXMoeCwgdGhpcy5kYXRhLl9YcykuaWQ7XG4gICAgICAgIHZhciBqID0gZmluZE5lYXJlc3RPbkF4aXMoeSwgdGhpcy5kYXRhLl9ZcykuaWQ7XG4gICAgICAgIHZhciBrID0gZmluZE5lYXJlc3RPbkF4aXMoeiwgdGhpcy5kYXRhLl9acykuaWQ7XG5cbiAgICAgICAgdmFyIHNlbGVjdEluZGV4ID0gc2VsZWN0aW9uLmluZGV4ID0gayArIGRlcHRoICogaiArIGRlcHRoICogaGVpZ2h0ICogaTtcblxuICAgICAgICBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlID0gW1xuICAgICAgICAgICAgdGhpcy5kYXRhLl94W3NlbGVjdEluZGV4XSxcbiAgICAgICAgICAgIHRoaXMuZGF0YS5feVtzZWxlY3RJbmRleF0sXG4gICAgICAgICAgICB0aGlzLmRhdGEuX3pbc2VsZWN0SW5kZXhdLFxuICAgICAgICAgICAgdGhpcy5kYXRhLnZhbHVlW3NlbGVjdEluZGV4XVxuICAgICAgICBdO1xuXG4gICAgICAgIHZhciB0ZXh0ID0gdGhpcy5kYXRhLmhvdmVydGV4dCB8fCB0aGlzLmRhdGEudGV4dDtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh0ZXh0KSAmJiB0ZXh0W3NlbGVjdEluZGV4XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGV4dFtzZWxlY3RJbmRleF07XG4gICAgICAgIH0gZWxzZSBpZih0ZXh0KSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGV4dDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn07XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICB2YXIgc2NlbmUgPSB0aGlzLnNjZW5lO1xuICAgIHZhciBsYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG5cbiAgICB0aGlzLmRhdGEgPSBnZW5lcmF0ZUlzb01lc2hlcyhkYXRhKTtcblxuICAgIC8vIFVucGFjayBwb3NpdGlvbiBkYXRhXG4gICAgZnVuY3Rpb24gdG9EYXRhQ29vcmRzKGF4aXMsIGNvb3JkLCBzY2FsZSwgY2FsZW5kYXIpIHtcbiAgICAgICAgcmV0dXJuIGNvb3JkLm1hcChmdW5jdGlvbih4KSB7XG4gICAgICAgICAgICByZXR1cm4gYXhpcy5kMmwoeCwgMCwgY2FsZW5kYXIpICogc2NhbGU7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciBwb3NpdGlvbnMgPSB6aXAzKFxuICAgICAgICB0b0RhdGFDb29yZHMobGF5b3V0LnhheGlzLCBkYXRhLl94LCBzY2VuZS5kYXRhU2NhbGVbMF0sIGRhdGEueGNhbGVuZGFyKSxcbiAgICAgICAgdG9EYXRhQ29vcmRzKGxheW91dC55YXhpcywgZGF0YS5feSwgc2NlbmUuZGF0YVNjYWxlWzFdLCBkYXRhLnljYWxlbmRhciksXG4gICAgICAgIHRvRGF0YUNvb3JkcyhsYXlvdXQuemF4aXMsIGRhdGEuX3osIHNjZW5lLmRhdGFTY2FsZVsyXSwgZGF0YS56Y2FsZW5kYXIpKTtcblxuICAgIHZhciBjZWxscyA9IHppcDMoZGF0YS5faSwgZGF0YS5faiwgZGF0YS5fayk7XG5cbiAgICB2YXIgY29uZmlnID0ge1xuICAgICAgICBwb3NpdGlvbnM6IHBvc2l0aW9ucyxcbiAgICAgICAgY2VsbHM6IGNlbGxzLFxuICAgICAgICBsaWdodFBvc2l0aW9uOiBbZGF0YS5saWdodHBvc2l0aW9uLngsIGRhdGEubGlnaHRwb3NpdGlvbi55LCBkYXRhLmxpZ2h0cG9zaXRpb24uel0sXG4gICAgICAgIGFtYmllbnQ6IGRhdGEubGlnaHRpbmcuYW1iaWVudCxcbiAgICAgICAgZGlmZnVzZTogZGF0YS5saWdodGluZy5kaWZmdXNlLFxuICAgICAgICBzcGVjdWxhcjogZGF0YS5saWdodGluZy5zcGVjdWxhcixcbiAgICAgICAgcm91Z2huZXNzOiBkYXRhLmxpZ2h0aW5nLnJvdWdobmVzcyxcbiAgICAgICAgZnJlc25lbDogZGF0YS5saWdodGluZy5mcmVzbmVsLFxuICAgICAgICB2ZXJ0ZXhOb3JtYWxzRXBzaWxvbjogZGF0YS5saWdodGluZy52ZXJ0ZXhub3JtYWxzZXBzaWxvbixcbiAgICAgICAgZmFjZU5vcm1hbHNFcHNpbG9uOiBkYXRhLmxpZ2h0aW5nLmZhY2Vub3JtYWxzZXBzaWxvbixcbiAgICAgICAgb3BhY2l0eTogZGF0YS5vcGFjaXR5LFxuICAgICAgICBjb250b3VyRW5hYmxlOiBkYXRhLmNvbnRvdXIuc2hvdyxcbiAgICAgICAgY29udG91ckNvbG9yOiBzdHIyUmdiYUFycmF5KGRhdGEuY29udG91ci5jb2xvcikuc2xpY2UoMCwgMyksXG4gICAgICAgIGNvbnRvdXJXaWR0aDogZGF0YS5jb250b3VyLndpZHRoLFxuICAgICAgICB1c2VGYWNldE5vcm1hbHM6IGRhdGEuZmxhdHNoYWRpbmdcbiAgICB9O1xuXG4gICAgdmFyIGNPcHRzID0gZXh0cmFjdE9wdHMoZGF0YSk7XG4gICAgY29uZmlnLnZlcnRleEludGVuc2l0eSA9IGRhdGEuX2ludGVuc2l0eTtcbiAgICBjb25maWcudmVydGV4SW50ZW5zaXR5Qm91bmRzID0gW2NPcHRzLm1pbiwgY09wdHMubWF4XTtcbiAgICBjb25maWcuY29sb3JtYXAgPSBwYXJzZUNvbG9yU2NhbGUoZGF0YSk7XG5cbiAgICAvLyBVcGRhdGUgbWVzaFxuICAgIHRoaXMubWVzaC51cGRhdGUoY29uZmlnKTtcbn07XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5tZXNoKTtcbiAgICB0aGlzLm1lc2guZGlzcG9zZSgpO1xufTtcblxuZnVuY3Rpb24gZ2VuZXJhdGVJc29NZXNoZXMoZGF0YSkge1xuICAgIGRhdGEuX2kgPSBbXTtcbiAgICBkYXRhLl9qID0gW107XG4gICAgZGF0YS5fayA9IFtdO1xuXG4gICAgdmFyIHNob3dTdXJmYWNlID0gZGF0YS5zdXJmYWNlLnNob3c7XG4gICAgdmFyIHNob3dTcGFjZWZyYW1lID0gZGF0YS5zcGFjZWZyYW1lLnNob3c7XG5cbiAgICB2YXIgc3VyZmFjZUZpbGwgPSBkYXRhLnN1cmZhY2UuZmlsbDtcbiAgICB2YXIgc3BhY2VmcmFtZUZpbGwgPSBkYXRhLnNwYWNlZnJhbWUuZmlsbDtcblxuICAgIHZhciBkcmF3aW5nU3VyZmFjZSA9IGZhbHNlO1xuICAgIHZhciBkcmF3aW5nU3BhY2VmcmFtZSA9IGZhbHNlO1xuXG4gICAgdmFyIG51bUZhY2VzID0gMDtcbiAgICB2YXIgbnVtVmVydGljZXM7XG4gICAgdmFyIGJlZ2luVmVydGV4dExlbmd0aDtcblxuICAgIHZhciBYcyA9IGRpc3RpbmN0VmFscyhkYXRhLnguc2xpY2UoMCwgZGF0YS5fbGVuKSk7XG4gICAgdmFyIFlzID0gZGlzdGluY3RWYWxzKGRhdGEueS5zbGljZSgwLCBkYXRhLl9sZW4pKTtcbiAgICB2YXIgWnMgPSBkaXN0aW5jdFZhbHMoZGF0YS56LnNsaWNlKDAsIGRhdGEuX2xlbikpO1xuXG4gICAgdmFyIHdpZHRoID0gWHMubGVuZ3RoO1xuICAgIHZhciBoZWlnaHQgPSBZcy5sZW5ndGg7XG4gICAgdmFyIGRlcHRoID0gWnMubGVuZ3RoO1xuXG4gICAgZnVuY3Rpb24gZ2V0SW5kZXgoaSwgaiwgaykge1xuICAgICAgICByZXR1cm4gayArIGRlcHRoICogaiArIGRlcHRoICogaGVpZ2h0ICogaTtcbiAgICB9XG5cbiAgICB2YXIgbWluVmFsdWVzID0gZGF0YS5fbWluVmFsdWVzO1xuICAgIHZhciBtYXhWYWx1ZXMgPSBkYXRhLl9tYXhWYWx1ZXM7XG5cbiAgICB2YXIgdk1pbiA9IGRhdGEuX3ZNaW47XG4gICAgdmFyIHZNYXggPSBkYXRhLl92TWF4O1xuXG4gICAgdmFyIGFsbFhzO1xuICAgIHZhciBhbGxZcztcbiAgICB2YXIgYWxsWnM7XG4gICAgdmFyIGFsbFZzO1xuXG4gICAgZnVuY3Rpb24gZmluZFZlcnRleElkKHgsIHksIHopIHtcbiAgICAgICAgLy8gY291bGQgYmUgdXNlZCB0byBmaW5kIHRoZSB2ZXJ0ZXggaWQgb2YgcHJldmlvdXNseSBnZW5lcmF0ZWQgdmVydGV4IHdpdGhpbiB0aGUgZ3JvdXBcblxuICAgICAgICB2YXIgbGVuID0gYWxsVnMubGVuZ3RoO1xuICAgICAgICBmb3IodmFyIGYgPSBiZWdpblZlcnRleHRMZW5ndGg7IGYgPCBsZW47IGYrKykge1xuICAgICAgICAgICAgaWYoXG4gICAgICAgICAgICAgICAgeCA9PT0gYWxsWHNbZl0gJiZcbiAgICAgICAgICAgICAgICB5ID09PSBhbGxZc1tmXSAmJlxuICAgICAgICAgICAgICAgIHogPT09IGFsbFpzW2ZdXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYmVnaW5Hcm91cCgpIHtcbiAgICAgICAgYmVnaW5WZXJ0ZXh0TGVuZ3RoID0gbnVtVmVydGljZXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW1wdHlWZXJ0aWNlcygpIHtcbiAgICAgICAgYWxsWHMgPSBbXTtcbiAgICAgICAgYWxsWXMgPSBbXTtcbiAgICAgICAgYWxsWnMgPSBbXTtcbiAgICAgICAgYWxsVnMgPSBbXTtcbiAgICAgICAgbnVtVmVydGljZXMgPSAwO1xuXG4gICAgICAgIGJlZ2luR3JvdXAoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhZGRWZXJ0ZXgoeCwgeSwgeiwgdikge1xuICAgICAgICBhbGxYcy5wdXNoKHgpO1xuICAgICAgICBhbGxZcy5wdXNoKHkpO1xuICAgICAgICBhbGxacy5wdXNoKHopO1xuICAgICAgICBhbGxWcy5wdXNoKHYpO1xuICAgICAgICBudW1WZXJ0aWNlcysrO1xuXG4gICAgICAgIHJldHVybiBudW1WZXJ0aWNlcyAtIDE7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkRmFjZShhLCBiLCBjKSB7XG4gICAgICAgIGRhdGEuX2kucHVzaChhKTtcbiAgICAgICAgZGF0YS5fai5wdXNoKGIpO1xuICAgICAgICBkYXRhLl9rLnB1c2goYyk7XG4gICAgICAgIG51bUZhY2VzKys7XG5cbiAgICAgICAgcmV0dXJuIG51bUZhY2VzIC0gMTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRDZW50ZXIoQSwgQiwgQykge1xuICAgICAgICB2YXIgTSA9IFtdO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgQS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgTVtpXSA9IChBW2ldICsgQltpXSArIENbaV0pIC8gMy4wO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBNO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEJldHdlZW4oQSwgQiwgcikge1xuICAgICAgICB2YXIgTSA9IFtdO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgQS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgTVtpXSA9IEFbaV0gKiAoMSAtIHIpICsgciAqIEJbaV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIE07XG4gICAgfVxuXG4gICAgdmFyIGFjdGl2ZUZpbGw7XG4gICAgZnVuY3Rpb24gc2V0RmlsbChmaWxsKSB7XG4gICAgICAgIGFjdGl2ZUZpbGwgPSBmaWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZU9wZW5UcmkoeHl6diwgYWJjKSB7XG4gICAgICAgIHZhciBBID0geHl6dlswXTtcbiAgICAgICAgdmFyIEIgPSB4eXp2WzFdO1xuICAgICAgICB2YXIgQyA9IHh5enZbMl07XG4gICAgICAgIHZhciBHID0gZ2V0Q2VudGVyKEEsIEIsIEMpO1xuXG4gICAgICAgIHZhciByID0gTWF0aC5zcXJ0KDEgLSBhY3RpdmVGaWxsKTtcbiAgICAgICAgdmFyIHAxID0gZ2V0QmV0d2VlbihHLCBBLCByKTtcbiAgICAgICAgdmFyIHAyID0gZ2V0QmV0d2VlbihHLCBCLCByKTtcbiAgICAgICAgdmFyIHAzID0gZ2V0QmV0d2VlbihHLCBDLCByKTtcblxuICAgICAgICB2YXIgYSA9IGFiY1swXTtcbiAgICAgICAgdmFyIGIgPSBhYmNbMV07XG4gICAgICAgIHZhciBjID0gYWJjWzJdO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4eXp2OiBbXG4gICAgICAgICAgICAgICAgW0EsIEIsIHAyXSwgW3AyLCBwMSwgQV0sXG4gICAgICAgICAgICAgICAgW0IsIEMsIHAzXSwgW3AzLCBwMiwgQl0sXG4gICAgICAgICAgICAgICAgW0MsIEEsIHAxXSwgW3AxLCBwMywgQ11cbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBhYmM6IFtcbiAgICAgICAgICAgICAgICBbYSwgYiwgLTFdLCBbLTEsIC0xLCBhXSxcbiAgICAgICAgICAgICAgICBbYiwgYywgLTFdLCBbLTEsIC0xLCBiXSxcbiAgICAgICAgICAgICAgICBbYywgYSwgLTFdLCBbLTEsIC0xLCBjXVxuICAgICAgICAgICAgXVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0eWxlSW5jbHVkZXMoc3R5bGUsIGNoYXIpIHtcbiAgICAgICAgaWYoc3R5bGUgPT09ICdhbGwnIHx8IHN0eWxlID09PSBudWxsKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIChzdHlsZS5pbmRleE9mKGNoYXIpID4gLTEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1hcFZhbHVlKHN0eWxlLCB2YWx1ZSkge1xuICAgICAgICBpZihzdHlsZSA9PT0gbnVsbCkgcmV0dXJuIHZhbHVlO1xuICAgICAgICByZXR1cm4gc3R5bGU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1RyaShzdHlsZSwgeHl6diwgYWJjKSB7XG4gICAgICAgIGJlZ2luR3JvdXAoKTtcblxuICAgICAgICB2YXIgYWxsWFlaVnMgPSBbeHl6dl07XG4gICAgICAgIHZhciBhbGxBQkNzID0gW2FiY107XG4gICAgICAgIGlmKGFjdGl2ZUZpbGwgPj0gMSkge1xuICAgICAgICAgICAgYWxsWFlaVnMgPSBbeHl6dl07XG4gICAgICAgICAgICBhbGxBQkNzID0gW2FiY107XG4gICAgICAgIH0gZWxzZSBpZihhY3RpdmVGaWxsID4gMCkge1xuICAgICAgICAgICAgdmFyIG9wZW5UcmkgPSBjcmVhdGVPcGVuVHJpKHh5enYsIGFiYyk7XG4gICAgICAgICAgICBhbGxYWVpWcyA9IG9wZW5UcmkueHl6djtcbiAgICAgICAgICAgIGFsbEFCQ3MgPSBvcGVuVHJpLmFiYztcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcih2YXIgZiA9IDA7IGYgPCBhbGxYWVpWcy5sZW5ndGg7IGYrKykge1xuICAgICAgICAgICAgeHl6diA9IGFsbFhZWlZzW2ZdO1xuICAgICAgICAgICAgYWJjID0gYWxsQUJDc1tmXTtcblxuICAgICAgICAgICAgdmFyIHBudHMgPSBbXTtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgeCA9IHh5enZbaV1bMF07XG4gICAgICAgICAgICAgICAgdmFyIHkgPSB4eXp2W2ldWzFdO1xuICAgICAgICAgICAgICAgIHZhciB6ID0geHl6dltpXVsyXTtcbiAgICAgICAgICAgICAgICB2YXIgdiA9IHh5enZbaV1bM107XG5cbiAgICAgICAgICAgICAgICB2YXIgaWQgPSAoYWJjW2ldID4gLTEpID8gYWJjW2ldIDogZmluZFZlcnRleElkKHgsIHksIHopO1xuICAgICAgICAgICAgICAgIGlmKGlkID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcG50c1tpXSA9IGlkO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBudHNbaV0gPSBhZGRWZXJ0ZXgoeCwgeSwgeiwgbWFwVmFsdWUoc3R5bGUsIHYpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGFkZEZhY2UocG50c1swXSwgcG50c1sxXSwgcG50c1syXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3UXVhZChzdHlsZSwgeHl6diwgYWJjZCkge1xuICAgICAgICB2YXIgbWFrZVRyaSA9IGZ1bmN0aW9uKGksIGosIGspIHtcbiAgICAgICAgICAgIGRyYXdUcmkoc3R5bGUsIFt4eXp2W2ldLCB4eXp2W2pdLCB4eXp2W2tdXSwgW2FiY2RbaV0sIGFiY2Rbal0sIGFiY2Rba11dKTtcbiAgICAgICAgfTtcblxuICAgICAgICBtYWtlVHJpKDAsIDEsIDIpO1xuICAgICAgICBtYWtlVHJpKDIsIDMsIDApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRyYXdUZXRyYShzdHlsZSwgeHl6diwgYWJjZCkge1xuICAgICAgICB2YXIgbWFrZVRyaSA9IGZ1bmN0aW9uKGksIGosIGspIHtcbiAgICAgICAgICAgIGRyYXdUcmkoc3R5bGUsIFt4eXp2W2ldLCB4eXp2W2pdLCB4eXp2W2tdXSwgW2FiY2RbaV0sIGFiY2Rbal0sIGFiY2Rba11dKTtcbiAgICAgICAgfTtcblxuICAgICAgICBtYWtlVHJpKDAsIDEsIDIpO1xuICAgICAgICBtYWtlVHJpKDMsIDAsIDEpO1xuICAgICAgICBtYWtlVHJpKDIsIDMsIDApO1xuICAgICAgICBtYWtlVHJpKDEsIDIsIDMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNhbGNJbnRlcnNlY3Rpb24ocG9pbnRPdXQsIHBvaW50SW4sIG1pbiwgbWF4KSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHBvaW50T3V0WzNdO1xuXG4gICAgICAgIGlmKHZhbHVlIDwgbWluKSB2YWx1ZSA9IG1pbjtcbiAgICAgICAgaWYodmFsdWUgPiBtYXgpIHZhbHVlID0gbWF4O1xuXG4gICAgICAgIHZhciByYXRpbyA9IChwb2ludE91dFszXSAtIHZhbHVlKSAvIChwb2ludE91dFszXSAtIHBvaW50SW5bM10gKyAwLjAwMDAwMDAwMSk7IC8vIHdlIGhhZCB0byBhZGQgdGhpcyBlcnJvciB0byBmb3JjZSBzb2x2ZSB0aGUgdGlueSBjYXBzXG5cbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICBmb3IodmFyIHMgPSAwOyBzIDwgNDsgcysrKSB7XG4gICAgICAgICAgICByZXN1bHRbc10gPSAoMSAtIHJhdGlvKSAqIHBvaW50T3V0W3NdICsgcmF0aW8gKiBwb2ludEluW3NdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5SYW5nZSh2YWx1ZSwgbWluLCBtYXgpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHZhbHVlID49IG1pbiAmJlxuICAgICAgICAgICAgdmFsdWUgPD0gbWF4XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWxtb3N0SW5GaW5hbFJhbmdlKHZhbHVlKSB7XG4gICAgICAgIHZhciB2RXJyID0gMC4wMDEgKiAodk1heCAtIHZNaW4pO1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdmFsdWUgPj0gdk1pbiAtIHZFcnIgJiZcbiAgICAgICAgICAgIHZhbHVlIDw9IHZNYXggKyB2RXJyXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0WFlaVihpbmRlY2llcykge1xuICAgICAgICB2YXIgeHl6diA9IFtdO1xuICAgICAgICBmb3IodmFyIHEgPSAwOyBxIDwgNDsgcSsrKSB7XG4gICAgICAgICAgICB2YXIgaW5kZXggPSBpbmRlY2llc1txXTtcbiAgICAgICAgICAgIHh5enYucHVzaChcbiAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIGRhdGEueFtpbmRleF0sXG4gICAgICAgICAgICAgICAgICAgIGRhdGEueVtpbmRleF0sXG4gICAgICAgICAgICAgICAgICAgIGRhdGEueltpbmRleF0sXG4gICAgICAgICAgICAgICAgICAgIGRhdGEudmFsdWVbaW5kZXhdXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB4eXp2O1xuICAgIH1cblxuICAgIHZhciBNQVhfUEFTUyA9IDM7XG5cbiAgICBmdW5jdGlvbiB0cnlDcmVhdGVUcmkoc3R5bGUsIHh5enYsIGFiYywgbWluLCBtYXgsIG5QYXNzKSB7XG4gICAgICAgIGlmKCFuUGFzcykgblBhc3MgPSAxO1xuXG4gICAgICAgIGFiYyA9IFstMSwgLTEsIC0xXTsgLy8gTm90ZTogZm9yIHRoZSBtb21lbnQgd2Ugb3ZlcnJpZGUgaW5kaWNlc1xuICAgICAgICAvLyB0byBydW4gZmFzdGVyISBCdXQgaXQgaXMgcG9zc2libGUgdG8gY29tbWVudCB0aGlzIGxpbmVcbiAgICAgICAgLy8gdG8gcmVkdWNlIHRoZSBudW1iZXIgb2YgdmVydGljZXMuXG5cbiAgICAgICAgdmFyIHJlc3VsdCA9IGZhbHNlO1xuXG4gICAgICAgIHZhciBvayA9IFtcbiAgICAgICAgICAgIGluUmFuZ2UoeHl6dlswXVszXSwgbWluLCBtYXgpLFxuICAgICAgICAgICAgaW5SYW5nZSh4eXp2WzFdWzNdLCBtaW4sIG1heCksXG4gICAgICAgICAgICBpblJhbmdlKHh5enZbMl1bM10sIG1pbiwgbWF4KVxuICAgICAgICBdO1xuXG4gICAgICAgIGlmKCFva1swXSAmJiAhb2tbMV0gJiYgIW9rWzJdKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHJ5RHJhd1RyaSA9IGZ1bmN0aW9uKHN0eWxlLCB4eXp2LCBhYmMpIHtcbiAgICAgICAgICAgIGlmKCAvLyB3ZSBjaGVjayBoZXJlIGlmIHRoZSBwb2ludHMgYXJlIGluIGByZWFsYCBpc28tbWluL21heCByYW5nZVxuICAgICAgICAgICAgICAgIGFsbW9zdEluRmluYWxSYW5nZSh4eXp2WzBdWzNdKSAmJlxuICAgICAgICAgICAgICAgIGFsbW9zdEluRmluYWxSYW5nZSh4eXp2WzFdWzNdKSAmJlxuICAgICAgICAgICAgICAgIGFsbW9zdEluRmluYWxSYW5nZSh4eXp2WzJdWzNdKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgZHJhd1RyaShzdHlsZSwgeHl6diwgYWJjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihuUGFzcyA8IE1BWF9QQVNTKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyeUNyZWF0ZVRyaShzdHlsZSwgeHl6diwgYWJjLCB2TWluLCB2TWF4LCArK25QYXNzKTsgLy8gaS5lLiBzZWNvbmQgcGFzcyB1c2luZyBhY3R1YWwgdk1pbiB2TWF4IGJvdW5kc1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmKG9rWzBdICYmIG9rWzFdICYmIG9rWzJdKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ5RHJhd1RyaShzdHlsZSwgeHl6diwgYWJjKSB8fCByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaW50ZXJwb2xhdGVkID0gZmFsc2U7XG5cbiAgICAgICAgW1xuICAgICAgICAgICAgWzAsIDEsIDJdLFxuICAgICAgICAgICAgWzIsIDAsIDFdLFxuICAgICAgICAgICAgWzEsIDIsIDBdXG4gICAgICAgIF0uZm9yRWFjaChmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICBpZihva1tlWzBdXSAmJiBva1tlWzFdXSAmJiAhb2tbZVsyXV0pIHtcbiAgICAgICAgICAgICAgICB2YXIgQSA9IHh5enZbZVswXV07XG4gICAgICAgICAgICAgICAgdmFyIEIgPSB4eXp2W2VbMV1dO1xuICAgICAgICAgICAgICAgIHZhciBDID0geHl6dltlWzJdXTtcblxuICAgICAgICAgICAgICAgIHZhciBwMSA9IGNhbGNJbnRlcnNlY3Rpb24oQywgQSwgbWluLCBtYXgpO1xuICAgICAgICAgICAgICAgIHZhciBwMiA9IGNhbGNJbnRlcnNlY3Rpb24oQywgQiwgbWluLCBtYXgpO1xuXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdHJ5RHJhd1RyaShzdHlsZSwgW3AyLCBwMSwgQV0sIFstMSwgLTEsIGFiY1tlWzBdXV0pIHx8IHJlc3VsdDtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0cnlEcmF3VHJpKHN0eWxlLCBbQSwgQiwgcDJdLCBbYWJjW2VbMF1dLCBhYmNbZVsxXV0sIC0xXSkgfHwgcmVzdWx0O1xuXG4gICAgICAgICAgICAgICAgaW50ZXJwb2xhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmKGludGVycG9sYXRlZCkgcmV0dXJuIHJlc3VsdDtcblxuICAgICAgICBbXG4gICAgICAgICAgICBbMCwgMSwgMl0sXG4gICAgICAgICAgICBbMSwgMiwgMF0sXG4gICAgICAgICAgICBbMiwgMCwgMV1cbiAgICAgICAgXS5mb3JFYWNoKGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgICAgIGlmKG9rW2VbMF1dICYmICFva1tlWzFdXSAmJiAhb2tbZVsyXV0pIHtcbiAgICAgICAgICAgICAgICB2YXIgQSA9IHh5enZbZVswXV07XG4gICAgICAgICAgICAgICAgdmFyIEIgPSB4eXp2W2VbMV1dO1xuICAgICAgICAgICAgICAgIHZhciBDID0geHl6dltlWzJdXTtcblxuICAgICAgICAgICAgICAgIHZhciBwMSA9IGNhbGNJbnRlcnNlY3Rpb24oQiwgQSwgbWluLCBtYXgpO1xuICAgICAgICAgICAgICAgIHZhciBwMiA9IGNhbGNJbnRlcnNlY3Rpb24oQywgQSwgbWluLCBtYXgpO1xuXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdHJ5RHJhd1RyaShzdHlsZSwgW3AyLCBwMSwgQV0sIFstMSwgLTEsIGFiY1tlWzBdXV0pIHx8IHJlc3VsdDtcblxuICAgICAgICAgICAgICAgIGludGVycG9sYXRlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRyeUNyZWF0ZVRldHJhKHN0eWxlLCBhYmNkLCBtaW4sIG1heCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gZmFsc2U7XG5cbiAgICAgICAgdmFyIHh5enYgPSBnZXRYWVpWKGFiY2QpO1xuXG4gICAgICAgIHZhciBvayA9IFtcbiAgICAgICAgICAgIGluUmFuZ2UoeHl6dlswXVszXSwgbWluLCBtYXgpLFxuICAgICAgICAgICAgaW5SYW5nZSh4eXp2WzFdWzNdLCBtaW4sIG1heCksXG4gICAgICAgICAgICBpblJhbmdlKHh5enZbMl1bM10sIG1pbiwgbWF4KSxcbiAgICAgICAgICAgIGluUmFuZ2UoeHl6dlszXVszXSwgbWluLCBtYXgpXG4gICAgICAgIF07XG5cbiAgICAgICAgaWYoIW9rWzBdICYmICFva1sxXSAmJiAhb2tbMl0gJiYgIW9rWzNdKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYob2tbMF0gJiYgb2tbMV0gJiYgb2tbMl0gJiYgb2tbM10pIHtcbiAgICAgICAgICAgIGlmKGRyYXdpbmdTcGFjZWZyYW1lKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gZHJhd1RldHJhKHN0eWxlLCB4eXp2LCBhYmNkKSB8fCByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGludGVycG9sYXRlZCA9IGZhbHNlO1xuXG4gICAgICAgIFtcbiAgICAgICAgICAgIFswLCAxLCAyLCAzXSxcbiAgICAgICAgICAgIFszLCAwLCAxLCAyXSxcbiAgICAgICAgICAgIFsyLCAzLCAwLCAxXSxcbiAgICAgICAgICAgIFsxLCAyLCAzLCAwXVxuICAgICAgICBdLmZvckVhY2goZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgaWYob2tbZVswXV0gJiYgb2tbZVsxXV0gJiYgb2tbZVsyXV0gJiYgIW9rW2VbM11dKSB7XG4gICAgICAgICAgICAgICAgdmFyIEEgPSB4eXp2W2VbMF1dO1xuICAgICAgICAgICAgICAgIHZhciBCID0geHl6dltlWzFdXTtcbiAgICAgICAgICAgICAgICB2YXIgQyA9IHh5enZbZVsyXV07XG4gICAgICAgICAgICAgICAgdmFyIEQgPSB4eXp2W2VbM11dO1xuXG4gICAgICAgICAgICAgICAgaWYoZHJhd2luZ1NwYWNlZnJhbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gZHJhd1RyaShzdHlsZSwgW0EsIEIsIENdLCBbYWJjZFtlWzBdXSwgYWJjZFtlWzFdXSwgYWJjZFtlWzJdXV0pIHx8IHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcDEgPSBjYWxjSW50ZXJzZWN0aW9uKEQsIEEsIG1pbiwgbWF4KTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHAyID0gY2FsY0ludGVyc2VjdGlvbihELCBCLCBtaW4sIG1heCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwMyA9IGNhbGNJbnRlcnNlY3Rpb24oRCwgQywgbWluLCBtYXgpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGRyYXdUcmkobnVsbCwgW3AxLCBwMiwgcDNdLCBbLTEsIC0xLCAtMV0pIHx8IHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpbnRlcnBvbGF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYoaW50ZXJwb2xhdGVkKSByZXR1cm4gcmVzdWx0O1xuXG4gICAgICAgIFtcbiAgICAgICAgICAgIFswLCAxLCAyLCAzXSxcbiAgICAgICAgICAgIFsxLCAyLCAzLCAwXSxcbiAgICAgICAgICAgIFsyLCAzLCAwLCAxXSxcbiAgICAgICAgICAgIFszLCAwLCAxLCAyXSxcbiAgICAgICAgICAgIFswLCAyLCAzLCAxXSxcbiAgICAgICAgICAgIFsxLCAzLCAyLCAwXVxuICAgICAgICBdLmZvckVhY2goZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgaWYob2tbZVswXV0gJiYgb2tbZVsxXV0gJiYgIW9rW2VbMl1dICYmICFva1tlWzNdXSkge1xuICAgICAgICAgICAgICAgIHZhciBBID0geHl6dltlWzBdXTtcbiAgICAgICAgICAgICAgICB2YXIgQiA9IHh5enZbZVsxXV07XG4gICAgICAgICAgICAgICAgdmFyIEMgPSB4eXp2W2VbMl1dO1xuICAgICAgICAgICAgICAgIHZhciBEID0geHl6dltlWzNdXTtcblxuICAgICAgICAgICAgICAgIHZhciBwMSA9IGNhbGNJbnRlcnNlY3Rpb24oQywgQSwgbWluLCBtYXgpO1xuICAgICAgICAgICAgICAgIHZhciBwMiA9IGNhbGNJbnRlcnNlY3Rpb24oQywgQiwgbWluLCBtYXgpO1xuICAgICAgICAgICAgICAgIHZhciBwMyA9IGNhbGNJbnRlcnNlY3Rpb24oRCwgQiwgbWluLCBtYXgpO1xuICAgICAgICAgICAgICAgIHZhciBwNCA9IGNhbGNJbnRlcnNlY3Rpb24oRCwgQSwgbWluLCBtYXgpO1xuXG4gICAgICAgICAgICAgICAgaWYoZHJhd2luZ1NwYWNlZnJhbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gZHJhd1RyaShzdHlsZSwgW0EsIHA0LCBwMV0sIFthYmNkW2VbMF1dLCAtMSwgLTFdKSB8fCByZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGRyYXdUcmkoc3R5bGUsIFtCLCBwMiwgcDNdLCBbYWJjZFtlWzFdXSwgLTEsIC0xXSkgfHwgcmVzdWx0O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGRyYXdRdWFkKG51bGwsIFtwMSwgcDIsIHAzLCBwNF0sIFstMSwgLTEsIC0xLCAtMV0pIHx8IHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpbnRlcnBvbGF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYoaW50ZXJwb2xhdGVkKSByZXR1cm4gcmVzdWx0O1xuXG4gICAgICAgIFtcbiAgICAgICAgICAgIFswLCAxLCAyLCAzXSxcbiAgICAgICAgICAgIFsxLCAyLCAzLCAwXSxcbiAgICAgICAgICAgIFsyLCAzLCAwLCAxXSxcbiAgICAgICAgICAgIFszLCAwLCAxLCAyXVxuICAgICAgICBdLmZvckVhY2goZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgaWYob2tbZVswXV0gJiYgIW9rW2VbMV1dICYmICFva1tlWzJdXSAmJiAhb2tbZVszXV0pIHtcbiAgICAgICAgICAgICAgICB2YXIgQSA9IHh5enZbZVswXV07XG4gICAgICAgICAgICAgICAgdmFyIEIgPSB4eXp2W2VbMV1dO1xuICAgICAgICAgICAgICAgIHZhciBDID0geHl6dltlWzJdXTtcbiAgICAgICAgICAgICAgICB2YXIgRCA9IHh5enZbZVszXV07XG5cbiAgICAgICAgICAgICAgICB2YXIgcDEgPSBjYWxjSW50ZXJzZWN0aW9uKEIsIEEsIG1pbiwgbWF4KTtcbiAgICAgICAgICAgICAgICB2YXIgcDIgPSBjYWxjSW50ZXJzZWN0aW9uKEMsIEEsIG1pbiwgbWF4KTtcbiAgICAgICAgICAgICAgICB2YXIgcDMgPSBjYWxjSW50ZXJzZWN0aW9uKEQsIEEsIG1pbiwgbWF4KTtcblxuICAgICAgICAgICAgICAgIGlmKGRyYXdpbmdTcGFjZWZyYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGRyYXdUcmkoc3R5bGUsIFtBLCBwMSwgcDJdLCBbYWJjZFtlWzBdXSwgLTEsIC0xXSkgfHwgcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBkcmF3VHJpKHN0eWxlLCBbQSwgcDIsIHAzXSwgW2FiY2RbZVswXV0sIC0xLCAtMV0pIHx8IHJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gZHJhd1RyaShzdHlsZSwgW0EsIHAzLCBwMV0sIFthYmNkW2VbMF1dLCAtMSwgLTFdKSB8fCByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gZHJhd1RyaShudWxsLCBbcDEsIHAyLCBwM10sIFstMSwgLTEsIC0xXSkgfHwgcmVzdWx0O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGludGVycG9sYXRlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZEN1YmUoc3R5bGUsIHAwMDAsIHAwMDEsIHAwMTAsIHAwMTEsIHAxMDAsIHAxMDEsIHAxMTAsIHAxMTEsIG1pbiwgbWF4KSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBmYWxzZTtcblxuICAgICAgICBpZihkcmF3aW5nU3VyZmFjZSkge1xuICAgICAgICAgICAgaWYoc3R5bGVJbmNsdWRlcyhzdHlsZSwgJ0EnKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRyeUNyZWF0ZVRldHJhKG51bGwsIFtwMDAwLCBwMDAxLCBwMDEwLCBwMTAwXSwgbWluLCBtYXgpIHx8IHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHN0eWxlSW5jbHVkZXMoc3R5bGUsICdCJykpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0cnlDcmVhdGVUZXRyYShudWxsLCBbcDAwMSwgcDAxMCwgcDAxMSwgcDExMV0sIG1pbiwgbWF4KSB8fCByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihzdHlsZUluY2x1ZGVzKHN0eWxlLCAnQycpKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdHJ5Q3JlYXRlVGV0cmEobnVsbCwgW3AwMDEsIHAxMDAsIHAxMDEsIHAxMTFdLCBtaW4sIG1heCkgfHwgcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoc3R5bGVJbmNsdWRlcyhzdHlsZSwgJ0QnKSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRyeUNyZWF0ZVRldHJhKG51bGwsIFtwMDEwLCBwMTAwLCBwMTEwLCBwMTExXSwgbWluLCBtYXgpIHx8IHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKHN0eWxlSW5jbHVkZXMoc3R5bGUsICdFJykpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0cnlDcmVhdGVUZXRyYShudWxsLCBbcDAwMSwgcDAxMCwgcDEwMCwgcDExMV0sIG1pbiwgbWF4KSB8fCByZXN1bHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihkcmF3aW5nU3BhY2VmcmFtZSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gdHJ5Q3JlYXRlVGV0cmEoc3R5bGUsIFtwMDAxLCBwMDEwLCBwMTAwLCBwMTExXSwgbWluLCBtYXgpIHx8IHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkUmVjdChzdHlsZSwgYSwgYiwgYywgZCwgbWluLCBtYXgsIHByZXZpb3VzUmVzdWx0KSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAocHJldmlvdXNSZXN1bHRbMF0gPT09IHRydWUpID8gdHJ1ZSA6XG4gICAgICAgICAgICB0cnlDcmVhdGVUcmkoc3R5bGUsIGdldFhZWlYoW2EsIGIsIGNdKSwgW2EsIGIsIGNdLCBtaW4sIG1heCksXG4gICAgICAgICAgICAocHJldmlvdXNSZXN1bHRbMV0gPT09IHRydWUpID8gdHJ1ZSA6XG4gICAgICAgICAgICB0cnlDcmVhdGVUcmkoc3R5bGUsIGdldFhZWlYoW2MsIGQsIGFdKSwgW2MsIGQsIGFdLCBtaW4sIG1heClcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBiZWdpbjJkQ2VsbChzdHlsZSwgcDAwLCBwMDEsIHAxMCwgcDExLCBtaW4sIG1heCwgaXNFdmVuLCBwcmV2aW91c1Jlc3VsdCkge1xuICAgICAgICAvLyB1c2VkIHRvIGNyZWF0ZSBjYXBzIGFuZC9vciBzbGljZXMgb24gZXhhY3QgYXhpcyBwb2ludHNcbiAgICAgICAgaWYoaXNFdmVuKSB7XG4gICAgICAgICAgICByZXR1cm4gYWRkUmVjdChzdHlsZSwgcDAwLCBwMDEsIHAxMSwgcDEwLCBtaW4sIG1heCwgcHJldmlvdXNSZXN1bHQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGFkZFJlY3Qoc3R5bGUsIHAwMSwgcDExLCBwMTAsIHAwMCwgbWluLCBtYXgsIHByZXZpb3VzUmVzdWx0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJlZ2luU2VjdGlvbihzdHlsZSwgaSwgaiwgaywgbWluLCBtYXgsIGRpc3RSYXRpb3MpIHtcbiAgICAgICAgLy8gdXNlZCB0byBjcmVhdGUgc2xpY2VzIGJldHdlZW4gYXhpcyBwb2ludHNcblxuICAgICAgICB2YXIgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgIHZhciBBLCBCLCBDLCBEO1xuXG4gICAgICAgIHZhciBtYWtlU2VjdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gdHJ5Q3JlYXRlVHJpKHN0eWxlLCBbQSwgQiwgQ10sIFstMSwgLTEsIC0xXSwgbWluLCBtYXgpIHx8IHJlc3VsdDtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRyeUNyZWF0ZVRyaShzdHlsZSwgW0MsIEQsIEFdLCBbLTEsIC0xLCAtMV0sIG1pbiwgbWF4KSB8fCByZXN1bHQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIHJYID0gZGlzdFJhdGlvc1swXTtcbiAgICAgICAgdmFyIHJZID0gZGlzdFJhdGlvc1sxXTtcbiAgICAgICAgdmFyIHJaID0gZGlzdFJhdGlvc1syXTtcblxuICAgICAgICBpZihyWCkge1xuICAgICAgICAgICAgQSA9IGdldEJldHdlZW4oZ2V0WFlaVihbZ2V0SW5kZXgoaSwgaiAtIDAsIGsgLSAwKV0pWzBdLCBnZXRYWVpWKFtnZXRJbmRleChpIC0gMSwgaiAtIDAsIGsgLSAwKV0pWzBdLCByWCk7XG4gICAgICAgICAgICBCID0gZ2V0QmV0d2VlbihnZXRYWVpWKFtnZXRJbmRleChpLCBqIC0gMCwgayAtIDEpXSlbMF0sIGdldFhZWlYoW2dldEluZGV4KGkgLSAxLCBqIC0gMCwgayAtIDEpXSlbMF0sIHJYKTtcbiAgICAgICAgICAgIEMgPSBnZXRCZXR3ZWVuKGdldFhZWlYoW2dldEluZGV4KGksIGogLSAxLCBrIC0gMSldKVswXSwgZ2V0WFlaVihbZ2V0SW5kZXgoaSAtIDEsIGogLSAxLCBrIC0gMSldKVswXSwgclgpO1xuICAgICAgICAgICAgRCA9IGdldEJldHdlZW4oZ2V0WFlaVihbZ2V0SW5kZXgoaSwgaiAtIDEsIGsgLSAwKV0pWzBdLCBnZXRYWVpWKFtnZXRJbmRleChpIC0gMSwgaiAtIDEsIGsgLSAwKV0pWzBdLCByWCk7XG4gICAgICAgICAgICBtYWtlU2VjdGlvbigpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoclkpIHtcbiAgICAgICAgICAgIEEgPSBnZXRCZXR3ZWVuKGdldFhZWlYoW2dldEluZGV4KGkgLSAwLCBqLCBrIC0gMCldKVswXSwgZ2V0WFlaVihbZ2V0SW5kZXgoaSAtIDAsIGogLSAxLCBrIC0gMCldKVswXSwgclkpO1xuICAgICAgICAgICAgQiA9IGdldEJldHdlZW4oZ2V0WFlaVihbZ2V0SW5kZXgoaSAtIDAsIGosIGsgLSAxKV0pWzBdLCBnZXRYWVpWKFtnZXRJbmRleChpIC0gMCwgaiAtIDEsIGsgLSAxKV0pWzBdLCByWSk7XG4gICAgICAgICAgICBDID0gZ2V0QmV0d2VlbihnZXRYWVpWKFtnZXRJbmRleChpIC0gMSwgaiwgayAtIDEpXSlbMF0sIGdldFhZWlYoW2dldEluZGV4KGkgLSAxLCBqIC0gMSwgayAtIDEpXSlbMF0sIHJZKTtcbiAgICAgICAgICAgIEQgPSBnZXRCZXR3ZWVuKGdldFhZWlYoW2dldEluZGV4KGkgLSAxLCBqLCBrIC0gMCldKVswXSwgZ2V0WFlaVihbZ2V0SW5kZXgoaSAtIDEsIGogLSAxLCBrIC0gMCldKVswXSwgclkpO1xuICAgICAgICAgICAgbWFrZVNlY3Rpb24oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHJaKSB7XG4gICAgICAgICAgICBBID0gZ2V0QmV0d2VlbihnZXRYWVpWKFtnZXRJbmRleChpIC0gMCwgaiAtIDAsIGspXSlbMF0sIGdldFhZWlYoW2dldEluZGV4KGkgLSAwLCBqIC0gMCwgayAtIDEpXSlbMF0sIHJaKTtcbiAgICAgICAgICAgIEIgPSBnZXRCZXR3ZWVuKGdldFhZWlYoW2dldEluZGV4KGkgLSAwLCBqIC0gMSwgayldKVswXSwgZ2V0WFlaVihbZ2V0SW5kZXgoaSAtIDAsIGogLSAxLCBrIC0gMSldKVswXSwgclopO1xuICAgICAgICAgICAgQyA9IGdldEJldHdlZW4oZ2V0WFlaVihbZ2V0SW5kZXgoaSAtIDEsIGogLSAxLCBrKV0pWzBdLCBnZXRYWVpWKFtnZXRJbmRleChpIC0gMSwgaiAtIDEsIGsgLSAxKV0pWzBdLCByWik7XG4gICAgICAgICAgICBEID0gZ2V0QmV0d2VlbihnZXRYWVpWKFtnZXRJbmRleChpIC0gMSwgaiAtIDAsIGspXSlbMF0sIGdldFhZWlYoW2dldEluZGV4KGkgLSAxLCBqIC0gMCwgayAtIDEpXSlbMF0sIHJaKTtcbiAgICAgICAgICAgIG1ha2VTZWN0aW9uKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJlZ2luM2RDZWxsKHN0eWxlLCBwMDAwLCBwMDAxLCBwMDEwLCBwMDExLCBwMTAwLCBwMTAxLCBwMTEwLCBwMTExLCBtaW4sIG1heCwgaXNFdmVuKSB7XG4gICAgICAgIC8vIHVzZWQgdG8gY3JlYXRlIHNwYWNlZnJhbWUgYW5kL29yIGlzby1zdXJmYWNlc1xuXG4gICAgICAgIHZhciBjZWxsU3R5bGUgPSBzdHlsZTtcbiAgICAgICAgaWYoaXNFdmVuKSB7XG4gICAgICAgICAgICBpZihkcmF3aW5nU3VyZmFjZSAmJiBzdHlsZSA9PT0gJ2V2ZW4nKSBjZWxsU3R5bGUgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIGFkZEN1YmUoY2VsbFN0eWxlLCBwMDAwLCBwMDAxLCBwMDEwLCBwMDExLCBwMTAwLCBwMTAxLCBwMTEwLCBwMTExLCBtaW4sIG1heCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZihkcmF3aW5nU3VyZmFjZSAmJiBzdHlsZSA9PT0gJ29kZCcpIGNlbGxTdHlsZSA9IG51bGw7XG4gICAgICAgICAgICByZXR1cm4gYWRkQ3ViZShjZWxsU3R5bGUsIHAxMTEsIHAxMTAsIHAxMDEsIHAxMDAsIHAwMTEsIHAwMTAsIHAwMDEsIHAwMDAsIG1pbiwgbWF4KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRyYXcyZFgoc3R5bGUsIGl0ZW1zLCBtaW4sIG1heCwgcHJldmlvdXNSZXN1bHQpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICB2YXIgbiA9IDA7XG4gICAgICAgIGZvcih2YXIgcSA9IDA7IHEgPCBpdGVtcy5sZW5ndGg7IHErKykge1xuICAgICAgICAgICAgdmFyIGkgPSBpdGVtc1txXTtcbiAgICAgICAgICAgIGZvcih2YXIgayA9IDE7IGsgPCBkZXB0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBqID0gMTsgaiA8IGhlaWdodDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW4yZENlbGwoc3R5bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0SW5kZXgoaSwgaiAtIDEsIGsgLSAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRJbmRleChpLCBqIC0gMSwgayksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0SW5kZXgoaSwgaiwgayAtIDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEluZGV4KGksIGosIGspLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGkgKyBqICsgaykgJSAyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwcmV2aW91c1Jlc3VsdCAmJiBwcmV2aW91c1Jlc3VsdFtuXSkgPyBwcmV2aW91c1Jlc3VsdFtuXSA6IFtdXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIG4rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3MmRZKHN0eWxlLCBpdGVtcywgbWluLCBtYXgsIHByZXZpb3VzUmVzdWx0KSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgdmFyIG4gPSAwO1xuICAgICAgICBmb3IodmFyIHEgPSAwOyBxIDwgaXRlbXMubGVuZ3RoOyBxKyspIHtcbiAgICAgICAgICAgIHZhciBqID0gaXRlbXNbcV07XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAxOyBpIDwgd2lkdGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvcih2YXIgayA9IDE7IGsgPCBkZXB0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW4yZENlbGwoc3R5bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0SW5kZXgoaSAtIDEsIGosIGsgLSAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRJbmRleChpLCBqLCBrIC0gMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0SW5kZXgoaSAtIDEsIGosIGspLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEluZGV4KGksIGosIGspLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGkgKyBqICsgaykgJSAyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwcmV2aW91c1Jlc3VsdCAmJiBwcmV2aW91c1Jlc3VsdFtuXSkgPyBwcmV2aW91c1Jlc3VsdFtuXSA6IFtdXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIG4rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkcmF3MmRaKHN0eWxlLCBpdGVtcywgbWluLCBtYXgsIHByZXZpb3VzUmVzdWx0KSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgdmFyIG4gPSAwO1xuICAgICAgICBmb3IodmFyIHEgPSAwOyBxIDwgaXRlbXMubGVuZ3RoOyBxKyspIHtcbiAgICAgICAgICAgIHZhciBrID0gaXRlbXNbcV07XG4gICAgICAgICAgICBmb3IodmFyIGogPSAxOyBqIDwgaGVpZ2h0OyBqKyspIHtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAxOyBpIDwgd2lkdGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luMmRDZWxsKHN0eWxlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEluZGV4KGkgLSAxLCBqIC0gMSwgayksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0SW5kZXgoaSAtIDEsIGosIGspLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEluZGV4KGksIGogLSAxLCBrKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRJbmRleChpLCBqLCBrKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChpICsgaiArIGspICUgMixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAocHJldmlvdXNSZXN1bHQgJiYgcHJldmlvdXNSZXN1bHRbbl0pID8gcHJldmlvdXNSZXN1bHRbbl0gOiBbXVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBuKys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhdzNkKHN0eWxlLCBtaW4sIG1heCkge1xuICAgICAgICBmb3IodmFyIGsgPSAxOyBrIDwgZGVwdGg7IGsrKykge1xuICAgICAgICAgICAgZm9yKHZhciBqID0gMTsgaiA8IGhlaWdodDsgaisrKSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMTsgaSA8IHdpZHRoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgYmVnaW4zZENlbGwoc3R5bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRJbmRleChpIC0gMSwgaiAtIDEsIGsgLSAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldEluZGV4KGkgLSAxLCBqIC0gMSwgayksXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRJbmRleChpIC0gMSwgaiwgayAtIDEpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0SW5kZXgoaSAtIDEsIGosIGspLFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0SW5kZXgoaSwgaiAtIDEsIGsgLSAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldEluZGV4KGksIGogLSAxLCBrKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldEluZGV4KGksIGosIGsgLSAxKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldEluZGV4KGksIGosIGspLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWluLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF4LFxuICAgICAgICAgICAgICAgICAgICAgICAgKGkgKyBqICsgaykgJSAyXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1NwYWNlZnJhbWUoc3R5bGUsIG1pbiwgbWF4KSB7XG4gICAgICAgIGRyYXdpbmdTcGFjZWZyYW1lID0gdHJ1ZTtcbiAgICAgICAgZHJhdzNkKHN0eWxlLCBtaW4sIG1heCk7XG4gICAgICAgIGRyYXdpbmdTcGFjZWZyYW1lID0gZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1N1cmZhY2Uoc3R5bGUsIG1pbiwgbWF4KSB7XG4gICAgICAgIGRyYXdpbmdTdXJmYWNlID0gdHJ1ZTtcbiAgICAgICAgZHJhdzNkKHN0eWxlLCBtaW4sIG1heCk7XG4gICAgICAgIGRyYXdpbmdTdXJmYWNlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd1NlY3Rpb25YKHN0eWxlLCBpdGVtcywgbWluLCBtYXgsIGRpc3RSYXRpb3MsIHByZXZpb3VzUmVzdWx0KSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgdmFyIG4gPSAwO1xuICAgICAgICBmb3IodmFyIHEgPSAwOyBxIDwgaXRlbXMubGVuZ3RoOyBxKyspIHtcbiAgICAgICAgICAgIHZhciBpID0gaXRlbXNbcV07XG4gICAgICAgICAgICBmb3IodmFyIGsgPSAxOyBrIDwgZGVwdGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaiA9IDE7IGogPCBoZWlnaHQ7IGorKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luU2VjdGlvbihzdHlsZSwgaSwgaiwgaywgbWluLCBtYXgsIGRpc3RSYXRpb3NbcV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHByZXZpb3VzUmVzdWx0ICYmIHByZXZpb3VzUmVzdWx0W25dKSA/IHByZXZpb3VzUmVzdWx0W25dIDogW11cbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgbisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRyYXdTZWN0aW9uWShzdHlsZSwgaXRlbXMsIG1pbiwgbWF4LCBkaXN0UmF0aW9zLCBwcmV2aW91c1Jlc3VsdCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHZhciBuID0gMDtcbiAgICAgICAgZm9yKHZhciBxID0gMDsgcSA8IGl0ZW1zLmxlbmd0aDsgcSsrKSB7XG4gICAgICAgICAgICB2YXIgaiA9IGl0ZW1zW3FdO1xuICAgICAgICAgICAgZm9yKHZhciBpID0gMTsgaSA8IHdpZHRoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGsgPSAxOyBrIDwgZGVwdGg7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luU2VjdGlvbihzdHlsZSwgaSwgaiwgaywgbWluLCBtYXgsIGRpc3RSYXRpb3NbcV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHByZXZpb3VzUmVzdWx0ICYmIHByZXZpb3VzUmVzdWx0W25dKSA/IHByZXZpb3VzUmVzdWx0W25dIDogW11cbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgbisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRyYXdTZWN0aW9uWihzdHlsZSwgaXRlbXMsIG1pbiwgbWF4LCBkaXN0UmF0aW9zLCBwcmV2aW91c1Jlc3VsdCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgIHZhciBuID0gMDtcbiAgICAgICAgZm9yKHZhciBxID0gMDsgcSA8IGl0ZW1zLmxlbmd0aDsgcSsrKSB7XG4gICAgICAgICAgICB2YXIgayA9IGl0ZW1zW3FdO1xuICAgICAgICAgICAgZm9yKHZhciBqID0gMTsgaiA8IGhlaWdodDsgaisrKSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMTsgaSA8IHdpZHRoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goXG4gICAgICAgICAgICAgICAgICAgICAgICBiZWdpblNlY3Rpb24oc3R5bGUsIGksIGosIGssIG1pbiwgbWF4LCBkaXN0UmF0aW9zW3FdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwcmV2aW91c1Jlc3VsdCAmJiBwcmV2aW91c1Jlc3VsdFtuXSkgPyBwcmV2aW91c1Jlc3VsdFtuXSA6IFtdXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIG4rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVSYW5nZShhLCBiKSB7XG4gICAgICAgIHZhciByYW5nZSA9IFtdO1xuICAgICAgICBmb3IodmFyIHEgPSBhOyBxIDwgYjsgcSsrKSB7XG4gICAgICAgICAgICByYW5nZS5wdXNoKHEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByYW5nZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnNlcnRHcmlkUG9pbnRzKCkge1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgd2lkdGg7IGkrKykge1xuICAgICAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGhlaWdodDsgaisrKSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBrID0gMDsgayA8IGRlcHRoOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZ2V0SW5kZXgoaSwgaiwgayk7XG4gICAgICAgICAgICAgICAgICAgIGFkZFZlcnRleChcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEueFtpbmRleF0sXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnlbaW5kZXhdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS56W2luZGV4XSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEudmFsdWVbaW5kZXhdXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHJhd0FsbCgpIHtcbiAgICAgICAgZW1wdHlWZXJ0aWNlcygpO1xuXG4gICAgICAgIC8vIGluc2VydCBncmlkIHBvaW50c1xuICAgICAgICBpbnNlcnRHcmlkUG9pbnRzKCk7XG5cbiAgICAgICAgdmFyIGFjdGl2ZVN0eWxlID0gbnVsbDtcblxuICAgICAgICAvLyBkcmF3IHNwYWNlZnJhbWVzXG4gICAgICAgIGlmKHNob3dTcGFjZWZyYW1lICYmIHNwYWNlZnJhbWVGaWxsKSB7XG4gICAgICAgICAgICBzZXRGaWxsKHNwYWNlZnJhbWVGaWxsKTtcblxuICAgICAgICAgICAgZHJhd1NwYWNlZnJhbWUoYWN0aXZlU3R5bGUsIHZNaW4sIHZNYXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZHJhdyBpc28tc3VyZmFjZXNcbiAgICAgICAgaWYoc2hvd1N1cmZhY2UgJiYgc3VyZmFjZUZpbGwpIHtcbiAgICAgICAgICAgIHNldEZpbGwoc3VyZmFjZUZpbGwpO1xuXG4gICAgICAgICAgICB2YXIgc3VyZmFjZVBhdHRlcm4gPSBkYXRhLnN1cmZhY2UucGF0dGVybjtcbiAgICAgICAgICAgIHZhciBzdXJmYWNlQ291bnQgPSBkYXRhLnN1cmZhY2UuY291bnQ7XG4gICAgICAgICAgICBmb3IodmFyIHEgPSAwOyBxIDwgc3VyZmFjZUNvdW50OyBxKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcmF0aW8gPSAoc3VyZmFjZUNvdW50ID09PSAxKSA/IDAuNSA6IHEgLyAoc3VyZmFjZUNvdW50IC0gMSk7XG4gICAgICAgICAgICAgICAgdmFyIGxldmVsID0gKDEgLSByYXRpbykgKiB2TWluICsgcmF0aW8gKiB2TWF4O1xuXG4gICAgICAgICAgICAgICAgdmFyIGQxID0gTWF0aC5hYnMobGV2ZWwgLSBtaW5WYWx1ZXMpO1xuICAgICAgICAgICAgICAgIHZhciBkMiA9IE1hdGguYWJzKGxldmVsIC0gbWF4VmFsdWVzKTtcbiAgICAgICAgICAgICAgICB2YXIgcmFuZ2VzID0gKGQxID4gZDIpID9cbiAgICAgICAgICAgICAgICAgICAgW21pblZhbHVlcywgbGV2ZWxdIDpcbiAgICAgICAgICAgICAgICAgICAgW2xldmVsLCBtYXhWYWx1ZXNdO1xuXG4gICAgICAgICAgICAgICAgZHJhd1N1cmZhY2Uoc3VyZmFjZVBhdHRlcm4sIHJhbmdlc1swXSwgcmFuZ2VzWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzZXR1cE1pbk1heCA9IFtcbiAgICAgICAgICAgIFsgTWF0aC5taW4odk1pbiwgbWF4VmFsdWVzKSwgTWF0aC5tYXgodk1pbiwgbWF4VmFsdWVzKSBdLFxuICAgICAgICAgICAgWyBNYXRoLm1pbihtaW5WYWx1ZXMsIHZNYXgpLCBNYXRoLm1heChtaW5WYWx1ZXMsIHZNYXgpIF1cbiAgICAgICAgXTtcblxuICAgICAgICBbJ3gnLCAneScsICd6J10uZm9yRWFjaChmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICB2YXIgcHJlUmVzID0gW107XG4gICAgICAgICAgICBmb3IodmFyIHMgPSAwOyBzIDwgc2V0dXBNaW5NYXgubGVuZ3RoOyBzKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSAwO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFjdGl2ZU1pbiA9IHNldHVwTWluTWF4W3NdWzBdO1xuICAgICAgICAgICAgICAgIHZhciBhY3RpdmVNYXggPSBzZXR1cE1pbk1heFtzXVsxXTtcblxuICAgICAgICAgICAgICAgIC8vIGRyYXcgc2xpY2VzXG4gICAgICAgICAgICAgICAgdmFyIHNsaWNlID0gZGF0YS5zbGljZXNbZV07XG4gICAgICAgICAgICAgICAgaWYoc2xpY2Uuc2hvdyAmJiBzbGljZS5maWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldEZpbGwoc2xpY2UuZmlsbCk7XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGV4YWN0SW5kaWNlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2VpbEluZGljZXMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRpc3RSYXRpb3MgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc2xpY2UubG9jYXRpb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBxID0gMDsgcSA8IHNsaWNlLmxvY2F0aW9ucy5sZW5ndGg7IHErKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZWFyID0gZmluZE5lYXJlc3RPbkF4aXMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsaWNlLmxvY2F0aW9uc1txXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGUgPT09ICd4JykgPyBYcyA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlID09PSAneScpID8gWXMgOiBac1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihuZWFyLmRpc3RSYXRpbyA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGFjdEluZGljZXMucHVzaChuZWFyLmlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYobmVhci5pZCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VpbEluZGljZXMucHVzaChuZWFyLmlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoZSA9PT0gJ3gnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0UmF0aW9zLnB1c2goW25lYXIuZGlzdFJhdGlvLCAwLCAwXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihlID09PSAneScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RSYXRpb3MucHVzaChbMCwgbmVhci5kaXN0UmF0aW8sIDBdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RSYXRpb3MucHVzaChbMCwgMCwgbmVhci5kaXN0UmF0aW9dKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGUgPT09ICd4Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4YWN0SW5kaWNlcyA9IGNyZWF0ZVJhbmdlKDEsIHdpZHRoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoZSA9PT0gJ3knKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3RJbmRpY2VzID0gY3JlYXRlUmFuZ2UoMSwgaGVpZ2h0IC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4YWN0SW5kaWNlcyA9IGNyZWF0ZVJhbmdlKDEsIGRlcHRoIC0gMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZihjZWlsSW5kaWNlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihlID09PSAneCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVSZXNbY291bnRdID0gZHJhd1NlY3Rpb25YKGFjdGl2ZVN0eWxlLCBjZWlsSW5kaWNlcywgYWN0aXZlTWluLCBhY3RpdmVNYXgsIGRpc3RSYXRpb3MsIHByZVJlc1tjb3VudF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKGUgPT09ICd5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZVJlc1tjb3VudF0gPSBkcmF3U2VjdGlvblkoYWN0aXZlU3R5bGUsIGNlaWxJbmRpY2VzLCBhY3RpdmVNaW4sIGFjdGl2ZU1heCwgZGlzdFJhdGlvcywgcHJlUmVzW2NvdW50XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZVJlc1tjb3VudF0gPSBkcmF3U2VjdGlvblooYWN0aXZlU3R5bGUsIGNlaWxJbmRpY2VzLCBhY3RpdmVNaW4sIGFjdGl2ZU1heCwgZGlzdFJhdGlvcywgcHJlUmVzW2NvdW50XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoZXhhY3RJbmRpY2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGUgPT09ICd4Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZVJlc1tjb3VudF0gPSBkcmF3MmRYKGFjdGl2ZVN0eWxlLCBleGFjdEluZGljZXMsIGFjdGl2ZU1pbiwgYWN0aXZlTWF4LCBwcmVSZXNbY291bnRdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihlID09PSAneScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVSZXNbY291bnRdID0gZHJhdzJkWShhY3RpdmVTdHlsZSwgZXhhY3RJbmRpY2VzLCBhY3RpdmVNaW4sIGFjdGl2ZU1heCwgcHJlUmVzW2NvdW50XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZVJlc1tjb3VudF0gPSBkcmF3MmRaKGFjdGl2ZVN0eWxlLCBleGFjdEluZGljZXMsIGFjdGl2ZU1pbiwgYWN0aXZlTWF4LCBwcmVSZXNbY291bnRdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBkcmF3IGNhcHNcbiAgICAgICAgICAgICAgICB2YXIgY2FwID0gZGF0YS5jYXBzW2VdO1xuICAgICAgICAgICAgICAgIGlmKGNhcC5zaG93ICYmIGNhcC5maWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldEZpbGwoY2FwLmZpbGwpO1xuICAgICAgICAgICAgICAgICAgICBpZihlID09PSAneCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZVJlc1tjb3VudF0gPSBkcmF3MmRYKGFjdGl2ZVN0eWxlLCBbMCwgd2lkdGggLSAxXSwgYWN0aXZlTWluLCBhY3RpdmVNYXgsIHByZVJlc1tjb3VudF0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoZSA9PT0gJ3knKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmVSZXNbY291bnRdID0gZHJhdzJkWShhY3RpdmVTdHlsZSwgWzAsIGhlaWdodCAtIDFdLCBhY3RpdmVNaW4sIGFjdGl2ZU1heCwgcHJlUmVzW2NvdW50XSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmVSZXNbY291bnRdID0gZHJhdzJkWihhY3RpdmVTdHlsZSwgWzAsIGRlcHRoIC0gMV0sIGFjdGl2ZU1pbiwgYWN0aXZlTWF4LCBwcmVSZXNbY291bnRdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb3VudCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gcmVtb3ZlIHZlcnRpY2VzIGFycmF5cyAoaS5lLiBncmlkIHBvaW50cykgaW4gY2FzZSBubyBmYWNlIHdhcyBjcmVhdGVkLlxuICAgICAgICBpZihudW1GYWNlcyA9PT0gMCkge1xuICAgICAgICAgICAgZW1wdHlWZXJ0aWNlcygpO1xuICAgICAgICB9XG5cbiAgICAgICAgZGF0YS5feCA9IGFsbFhzO1xuICAgICAgICBkYXRhLl95ID0gYWxsWXM7XG4gICAgICAgIGRhdGEuX3ogPSBhbGxacztcbiAgICAgICAgZGF0YS5faW50ZW5zaXR5ID0gYWxsVnM7XG5cbiAgICAgICAgZGF0YS5fWHMgPSBYcztcbiAgICAgICAgZGF0YS5fWXMgPSBZcztcbiAgICAgICAgZGF0YS5fWnMgPSBacztcbiAgICB9XG5cbiAgICBkcmF3QWxsKCk7XG5cbiAgICByZXR1cm4gZGF0YTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlSXNvc3VyZmFjZVRyYWNlKHNjZW5lLCBkYXRhKSB7XG4gICAgdmFyIGdsID0gc2NlbmUuZ2xwbG90LmdsO1xuICAgIHZhciBtZXNoID0gY3JlYXRlTWVzaCh7Z2w6IGdsfSk7XG4gICAgdmFyIHJlc3VsdCA9IG5ldyBJc29zdXJmYWNlVHJhY2Uoc2NlbmUsIG1lc2gsIGRhdGEudWlkKTtcblxuICAgIG1lc2guX3RyYWNlID0gcmVzdWx0O1xuICAgIHJlc3VsdC51cGRhdGUoZGF0YSk7XG4gICAgc2NlbmUuZ2xwbG90LmFkZChtZXNoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBmaW5kTmVhcmVzdE9uQXhpczogZmluZE5lYXJlc3RPbkF4aXMsXG4gICAgZ2VuZXJhdGVJc29NZXNoZXM6IGdlbmVyYXRlSXNvTWVzaGVzLFxuICAgIGNyZWF0ZUlzb3N1cmZhY2VUcmFjZTogY3JlYXRlSXNvc3VyZmFjZVRyYWNlLFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGVcIjo2MDUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZ2xfZm9ybWF0X2NvbG9yXCI6NzE2LFwiLi4vLi4vbGliL3N0cjJyZ2JhcnJheVwiOjc0MixcIi4uLy4uL3Bsb3RzL2dsM2QvemlwM1wiOjgxOCxcImdsLW1lc2gzZFwiOjI4MH1dLDEwNTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcblxuZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHN1cHBseUlzb0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbn1cblxuZnVuY3Rpb24gc3VwcGx5SXNvRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpIHtcbiAgICB2YXIgaXNvbWluID0gY29lcmNlKCdpc29taW4nKTtcbiAgICB2YXIgaXNvbWF4ID0gY29lcmNlKCdpc29tYXgnKTtcblxuICAgIGlmKGlzb21heCAhPT0gdW5kZWZpbmVkICYmIGlzb21heCAhPT0gbnVsbCAmJlxuICAgICAgICBpc29taW4gIT09IHVuZGVmaW5lZCAmJiBpc29taW4gIT09IG51bGwgJiZcbiAgICAgICAgIGlzb21pbiA+IGlzb21heCkge1xuICAgICAgICAvLyBhcHBseWluZyBkZWZhdWx0IHZhbHVlcyBpbiB0aGlzIGNhc2U6XG4gICAgICAgIHRyYWNlT3V0Lmlzb21pbiA9IG51bGw7XG4gICAgICAgIHRyYWNlT3V0Lmlzb21heCA9IG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHggPSBjb2VyY2UoJ3gnKTtcbiAgICB2YXIgeSA9IGNvZXJjZSgneScpO1xuICAgIHZhciB6ID0gY29lcmNlKCd6Jyk7XG4gICAgdmFyIHZhbHVlID0gY29lcmNlKCd2YWx1ZScpO1xuXG4gICAgaWYoXG4gICAgICAgICF4IHx8ICF4Lmxlbmd0aCB8fFxuICAgICAgICAheSB8fCAheS5sZW5ndGggfHxcbiAgICAgICAgIXogfHwgIXoubGVuZ3RoIHx8XG4gICAgICAgICF2YWx1ZSB8fCAhdmFsdWUubGVuZ3RoXG4gICAgKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBoYW5kbGVDYWxlbmRhckRlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnaGFuZGxlVHJhY2VEZWZhdWx0cycpO1xuICAgIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIFsneCcsICd5JywgJ3onXSwgbGF5b3V0KTtcblxuICAgIFsneCcsICd5JywgJ3onXS5mb3JFYWNoKGZ1bmN0aW9uKGRpbSkge1xuICAgICAgICB2YXIgY2FwRGltID0gJ2NhcHMuJyArIGRpbTtcbiAgICAgICAgdmFyIHNob3dDYXAgPSBjb2VyY2UoY2FwRGltICsgJy5zaG93Jyk7XG4gICAgICAgIGlmKHNob3dDYXApIHtcbiAgICAgICAgICAgIGNvZXJjZShjYXBEaW0gKyAnLmZpbGwnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzbGljZURpbSA9ICdzbGljZXMuJyArIGRpbTtcbiAgICAgICAgdmFyIHNob3dTbGljZSA9IGNvZXJjZShzbGljZURpbSArICcuc2hvdycpO1xuICAgICAgICBpZihzaG93U2xpY2UpIHtcbiAgICAgICAgICAgIGNvZXJjZShzbGljZURpbSArICcuZmlsbCcpO1xuICAgICAgICAgICAgY29lcmNlKHNsaWNlRGltICsgJy5sb2NhdGlvbnMnKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFyIHNob3dTcGFjZWZyYW1lID0gY29lcmNlKCdzcGFjZWZyYW1lLnNob3cnKTtcbiAgICBpZihzaG93U3BhY2VmcmFtZSkge1xuICAgICAgICBjb2VyY2UoJ3NwYWNlZnJhbWUuZmlsbCcpO1xuICAgIH1cblxuICAgIHZhciBzaG93U3VyZmFjZSA9IGNvZXJjZSgnc3VyZmFjZS5zaG93Jyk7XG4gICAgaWYoc2hvd1N1cmZhY2UpIHtcbiAgICAgICAgY29lcmNlKCdzdXJmYWNlLmNvdW50Jyk7XG4gICAgICAgIGNvZXJjZSgnc3VyZmFjZS5maWxsJyk7XG4gICAgICAgIGNvZXJjZSgnc3VyZmFjZS5wYXR0ZXJuJyk7XG4gICAgfVxuXG4gICAgdmFyIHNob3dDb250b3VyID0gY29lcmNlKCdjb250b3VyLnNob3cnKTtcbiAgICBpZihzaG93Q29udG91cikge1xuICAgICAgICBjb2VyY2UoJ2NvbnRvdXIuY29sb3InKTtcbiAgICAgICAgY29lcmNlKCdjb250b3VyLndpZHRoJyk7XG4gICAgfVxuXG4gICAgLy8gQ29lcmNlIHJlbWFpbmluZyBwcm9wZXJ0aWVzXG4gICAgW1xuICAgICAgICAndGV4dCcsXG4gICAgICAgICdob3ZlcnRleHQnLFxuICAgICAgICAnaG92ZXJ0ZW1wbGF0ZScsXG4gICAgICAgICdsaWdodGluZy5hbWJpZW50JyxcbiAgICAgICAgJ2xpZ2h0aW5nLmRpZmZ1c2UnLFxuICAgICAgICAnbGlnaHRpbmcuc3BlY3VsYXInLFxuICAgICAgICAnbGlnaHRpbmcucm91Z2huZXNzJyxcbiAgICAgICAgJ2xpZ2h0aW5nLmZyZXNuZWwnLFxuICAgICAgICAnbGlnaHRpbmcudmVydGV4bm9ybWFsc2Vwc2lsb24nLFxuICAgICAgICAnbGlnaHRpbmcuZmFjZW5vcm1hbHNlcHNpbG9uJyxcbiAgICAgICAgJ2xpZ2h0cG9zaXRpb24ueCcsXG4gICAgICAgICdsaWdodHBvc2l0aW9uLnknLFxuICAgICAgICAnbGlnaHRwb3NpdGlvbi56JyxcbiAgICAgICAgJ2ZsYXRzaGFkaW5nJyxcbiAgICAgICAgJ29wYWNpdHknXG4gICAgXS5mb3JFYWNoKGZ1bmN0aW9uKHgpIHsgY29lcmNlKHgpOyB9KTtcblxuICAgIGNvbG9yc2NhbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICcnLCBjTGV0dGVyOiAnYyd9KTtcblxuICAgIC8vIGRpc2FibGUgMUQgdHJhbnNmb3JtcyAoZm9yIG5vdylcbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbnVsbDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3VwcGx5RGVmYXVsdHM6IHN1cHBseURlZmF1bHRzLFxuICAgIHN1cHBseUlzb0RlZmF1bHRzOiBzdXBwbHlJc29EZWZhdWx0c1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHNcIjo2MDMsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4vYXR0cmlidXRlc1wiOjEwNDh9XSwxMDUyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKS5zdXBwbHlEZWZhdWx0cyxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBjb2xvcmJhcjoge1xuICAgICAgICBtaW46ICdjbWluJyxcbiAgICAgICAgbWF4OiAnY21heCdcbiAgICB9LFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vY29udmVydCcpLmNyZWF0ZUlzb3N1cmZhY2VUcmFjZSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ2lzb3N1cmZhY2UnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9nbDNkJyksXG4gICAgY2F0ZWdvcmllczogWydnbDNkJ10sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2dsM2RcIjo4MDcsXCIuL2F0dHJpYnV0ZXNcIjoxMDQ4LFwiLi9jYWxjXCI6MTA0OSxcIi4vY29udmVydFwiOjEwNTAsXCIuL2RlZmF1bHRzXCI6MTA1MX1dLDEwNTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JTY2FsZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBob3ZlcnRlbXBsYXRlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlcycpO1xudmFyIHN1cmZhY2VBdHRzID0gX2RlcmVxXygnLi4vc3VyZmFjZS9hdHRyaWJ1dGVzJyk7XG52YXIgYmFzZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xuXG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGV4dGVuZEZsYXQoe1xuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHo6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgaToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgajoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuXG4gICAgfSxcbiAgICBrOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG5cbiAgICB9LFxuXG4gICAgdGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVydGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycyh7ZWRpdFR5cGU6ICdjYWxjJ30pLFxuXG4gICAgZGVsYXVuYXlheGlzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWyAneCcsICd5JywgJ3onIF0sXG4gICAgICAgIGRmbHQ6ICd6JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGFscGhhaHVsbDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IC0xLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgaW50ZW5zaXR5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIC8vIENvbG9yIGZpZWxkXG4gICAgY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmVydGV4Y29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBmYWNlY29sb3I6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB0cmFuc2Zvcm1zOiB1bmRlZmluZWRcbn0sXG5cbmNvbG9yU2NhbGVBdHRycygnJywge1xuICAgIGNvbG9yQXR0cjogJ2BpbnRlbnNpdHlgJyxcbiAgICBzaG93U2NhbGVEZmx0OiB0cnVlLFxuICAgIGVkaXRUeXBlT3ZlcnJpZGU6ICdjYWxjJ1xufSksIHtcbiAgICBvcGFjaXR5OiBzdXJmYWNlQXR0cy5vcGFjaXR5LFxuXG4gICAgLy8gRmxhdCBzaGFkZWQgbW9kZVxuICAgIGZsYXRzaGFkaW5nOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgY29udG91cjoge1xuICAgICAgICBzaG93OiBleHRlbmRGbGF0KHt9LCBzdXJmYWNlQXR0cy5jb250b3Vycy54LnNob3csIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgY29sb3I6IHN1cmZhY2VBdHRzLmNvbnRvdXJzLnguY29sb3IsXG4gICAgICAgIHdpZHRoOiBzdXJmYWNlQXR0cy5jb250b3Vycy54LndpZHRoLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcblxuICAgIGxpZ2h0cG9zaXRpb246IHtcbiAgICAgICAgeDogZXh0ZW5kRmxhdCh7fSwgc3VyZmFjZUF0dHMubGlnaHRwb3NpdGlvbi54LCB7ZGZsdDogMWU1fSksXG4gICAgICAgIHk6IGV4dGVuZEZsYXQoe30sIHN1cmZhY2VBdHRzLmxpZ2h0cG9zaXRpb24ueSwge2RmbHQ6IDFlNX0pLFxuICAgICAgICB6OiBleHRlbmRGbGF0KHt9LCBzdXJmYWNlQXR0cy5saWdodHBvc2l0aW9uLnosIHtkZmx0OiAwfSksXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgIGxpZ2h0aW5nOiBleHRlbmRGbGF0KHtcbiAgICAgICAgdmVydGV4bm9ybWFsc2Vwc2lsb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAuMDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAxZS0xMiwgLy8gb3RoZXJ3aXNlIGZpbmVseSB0ZXNzZWxsYXRlZCB0aGluZ3MgZWcuIHRoZSBicmFpbiB3aWxsIGhhdmUgbm8gc3BlY3VsYXIgbGlnaHQgcmVmbGVjdGlvblxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBmYWNlbm9ybWFsc2Vwc2lsb246IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAuMDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAxZS02LCAvLyBldmVuIHRoZSBicmFpbiBtb2RlbCBkb2Vzbid0IGFwcGVhciB0byBuZWVkIGZpbmVyIHRoYW4gdGhpc1xuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSwgc3VyZmFjZUF0dHMubGlnaHRpbmcpLFxuXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBiYXNlQXR0cnMuaG92ZXJpbmZvLCB7ZWRpdFR5cGU6ICdjYWxjJ30pXG59KTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9zdXJmYWNlL2F0dHJpYnV0ZXNcIjoxMjI0fV0sMTA1NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvcnNjYWxlQ2FsYyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICBpZih0cmFjZS5pbnRlbnNpdHkpIHtcbiAgICAgICAgY29sb3JzY2FsZUNhbGMoZ2QsIHRyYWNlLCB7XG4gICAgICAgICAgICB2YWxzOiB0cmFjZS5pbnRlbnNpdHksXG4gICAgICAgICAgICBjb250YWluZXJTdHI6ICcnLFxuICAgICAgICAgICAgY0xldHRlcjogJ2MnXG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGNcIjo2MDF9XSwxMDU1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNyZWF0ZU1lc2ggPSBfZGVyZXFfKCdnbC1tZXNoM2QnKTtcbnZhciB0cmlhbmd1bGF0ZSA9IF9kZXJlcV8oJ2RlbGF1bmF5LXRyaWFuZ3VsYXRlJyk7XG52YXIgYWxwaGFTaGFwZSA9IF9kZXJlcV8oJ2FscGhhLXNoYXBlJyk7XG52YXIgY29udmV4SHVsbCA9IF9kZXJlcV8oJ2NvbnZleC1odWxsJyk7XG5cbnZhciBwYXJzZUNvbG9yU2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9saWIvZ2xfZm9ybWF0X2NvbG9yJykucGFyc2VDb2xvclNjYWxlO1xudmFyIHN0cjJSZ2JhQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3RyMnJnYmFycmF5Jyk7XG52YXIgZXh0cmFjdE9wdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKS5leHRyYWN0T3B0cztcbnZhciB6aXAzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2wzZC96aXAzJyk7XG5cbmZ1bmN0aW9uIE1lc2gzRFRyYWNlKHNjZW5lLCBtZXNoLCB1aWQpIHtcbiAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgdGhpcy51aWQgPSB1aWQ7XG4gICAgdGhpcy5tZXNoID0gbWVzaDtcbiAgICB0aGlzLm5hbWUgPSAnJztcbiAgICB0aGlzLmNvbG9yID0gJyNmZmYnO1xuICAgIHRoaXMuZGF0YSA9IG51bGw7XG4gICAgdGhpcy5zaG93Q29udG91ciA9IGZhbHNlO1xufVxuXG52YXIgcHJvdG8gPSBNZXNoM0RUcmFjZS5wcm90b3R5cGU7XG5cbnByb3RvLmhhbmRsZVBpY2sgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcbiAgICBpZihzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLm1lc2gpIHtcbiAgICAgICAgdmFyIHNlbGVjdEluZGV4ID0gc2VsZWN0aW9uLmluZGV4ID0gc2VsZWN0aW9uLmRhdGEuaW5kZXg7XG5cbiAgICAgICAgc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZSA9IFtcbiAgICAgICAgICAgIHRoaXMuZGF0YS54W3NlbGVjdEluZGV4XSxcbiAgICAgICAgICAgIHRoaXMuZGF0YS55W3NlbGVjdEluZGV4XSxcbiAgICAgICAgICAgIHRoaXMuZGF0YS56W3NlbGVjdEluZGV4XVxuICAgICAgICBdO1xuXG4gICAgICAgIHZhciB0ZXh0ID0gdGhpcy5kYXRhLmhvdmVydGV4dCB8fCB0aGlzLmRhdGEudGV4dDtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh0ZXh0KSAmJiB0ZXh0W3NlbGVjdEluZGV4XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGV4dFtzZWxlY3RJbmRleF07XG4gICAgICAgIH0gZWxzZSBpZih0ZXh0KSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGV4dDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHBhcnNlQ29sb3JBcnJheShjb2xvcnMpIHtcbiAgICB2YXIgYiA9IFtdO1xuICAgIHZhciBsZW4gPSBjb2xvcnMubGVuZ3RoO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBiW2ldID0gc3RyMlJnYmFBcnJheShjb2xvcnNbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gYjtcbn1cblxuLy8gVW5wYWNrIHBvc2l0aW9uIGRhdGFcbmZ1bmN0aW9uIHRvRGF0YUNvb3JkcyhheGlzLCBjb29yZCwgc2NhbGUsIGNhbGVuZGFyKSB7XG4gICAgdmFyIGIgPSBbXTtcbiAgICB2YXIgbGVuID0gY29vcmQubGVuZ3RoO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBiW2ldID0gYXhpcy5kMmwoY29vcmRbaV0sIDAsIGNhbGVuZGFyKSAqIHNjYWxlO1xuICAgIH1cbiAgICByZXR1cm4gYjtcbn1cblxuLy8gUm91bmQgaW5kaWNlcyBpZiBwYXNzZWQgYXMgZmxvYXRzXG5mdW5jdGlvbiB0b1JvdW5kSW5kZXgoYSkge1xuICAgIHZhciBiID0gW107XG4gICAgdmFyIGxlbiA9IGEubGVuZ3RoO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBiW2ldID0gTWF0aC5yb3VuZChhW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIGI7XG59XG5cbmZ1bmN0aW9uIGRlbGF1bmF5Q2VsbHMoZGVsYXVuYXlheGlzLCBwb3NpdGlvbnMpIHtcbiAgICB2YXIgZCA9IFsneCcsICd5JywgJ3onXS5pbmRleE9mKGRlbGF1bmF5YXhpcyk7XG4gICAgdmFyIGIgPSBbXTtcbiAgICB2YXIgbGVuID0gcG9zaXRpb25zLmxlbmd0aDtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgYltpXSA9IFtwb3NpdGlvbnNbaV1bKGQgKyAxKSAlIDNdLCBwb3NpdGlvbnNbaV1bKGQgKyAyKSAlIDNdXTtcbiAgICB9XG4gICAgcmV0dXJuIHRyaWFuZ3VsYXRlKGIpO1xufVxuXG4vLyBWYWxpZGF0ZSBpbmRpY2VzXG5mdW5jdGlvbiBoYXNWYWxpZEluZGljZXMobGlzdCwgbnVtVmVydGljZXMpIHtcbiAgICB2YXIgbGVuID0gbGlzdC5sZW5ndGg7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmKGxpc3RbaV0gPD0gLTAuNSB8fCBsaXN0W2ldID49IG51bVZlcnRpY2VzIC0gMC41KSB7IC8vIE5vdGU6IHRoZSBpbmRpY2VzIHdvdWxkIGJlIHJvdW5kZWQgLTAuNDkgaXMgdmFsaWQuXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICB2YXIgc2NlbmUgPSB0aGlzLnNjZW5lO1xuICAgIHZhciBsYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG5cbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuXG4gICAgdmFyIG51bVZlcnRpY2VzID0gZGF0YS54Lmxlbmd0aDtcblxuICAgIHZhciBwb3NpdGlvbnMgPSB6aXAzKFxuICAgICAgICB0b0RhdGFDb29yZHMobGF5b3V0LnhheGlzLCBkYXRhLngsIHNjZW5lLmRhdGFTY2FsZVswXSwgZGF0YS54Y2FsZW5kYXIpLFxuICAgICAgICB0b0RhdGFDb29yZHMobGF5b3V0LnlheGlzLCBkYXRhLnksIHNjZW5lLmRhdGFTY2FsZVsxXSwgZGF0YS55Y2FsZW5kYXIpLFxuICAgICAgICB0b0RhdGFDb29yZHMobGF5b3V0LnpheGlzLCBkYXRhLnosIHNjZW5lLmRhdGFTY2FsZVsyXSwgZGF0YS56Y2FsZW5kYXIpXG4gICAgKTtcblxuICAgIHZhciBjZWxscztcbiAgICBpZihkYXRhLmkgJiYgZGF0YS5qICYmIGRhdGEuaykge1xuICAgICAgICBpZihcbiAgICAgICAgICAgIGRhdGEuaS5sZW5ndGggIT09IGRhdGEuai5sZW5ndGggfHxcbiAgICAgICAgICAgIGRhdGEuai5sZW5ndGggIT09IGRhdGEuay5sZW5ndGggfHxcbiAgICAgICAgICAgICFoYXNWYWxpZEluZGljZXMoZGF0YS5pLCBudW1WZXJ0aWNlcykgfHxcbiAgICAgICAgICAgICFoYXNWYWxpZEluZGljZXMoZGF0YS5qLCBudW1WZXJ0aWNlcykgfHxcbiAgICAgICAgICAgICFoYXNWYWxpZEluZGljZXMoZGF0YS5rLCBudW1WZXJ0aWNlcylcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY2VsbHMgPSB6aXAzKFxuICAgICAgICAgICAgdG9Sb3VuZEluZGV4KGRhdGEuaSksXG4gICAgICAgICAgICB0b1JvdW5kSW5kZXgoZGF0YS5qKSxcbiAgICAgICAgICAgIHRvUm91bmRJbmRleChkYXRhLmspXG4gICAgICAgICk7XG4gICAgfSBlbHNlIGlmKGRhdGEuYWxwaGFodWxsID09PSAwKSB7XG4gICAgICAgIGNlbGxzID0gY29udmV4SHVsbChwb3NpdGlvbnMpO1xuICAgIH0gZWxzZSBpZihkYXRhLmFscGhhaHVsbCA+IDApIHtcbiAgICAgICAgY2VsbHMgPSBhbHBoYVNoYXBlKGRhdGEuYWxwaGFodWxsLCBwb3NpdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNlbGxzID0gZGVsYXVuYXlDZWxscyhkYXRhLmRlbGF1bmF5YXhpcywgcG9zaXRpb25zKTtcbiAgICB9XG5cbiAgICB2YXIgY29uZmlnID0ge1xuICAgICAgICBwb3NpdGlvbnM6IHBvc2l0aW9ucyxcbiAgICAgICAgY2VsbHM6IGNlbGxzLFxuICAgICAgICBsaWdodFBvc2l0aW9uOiBbZGF0YS5saWdodHBvc2l0aW9uLngsIGRhdGEubGlnaHRwb3NpdGlvbi55LCBkYXRhLmxpZ2h0cG9zaXRpb24uel0sXG4gICAgICAgIGFtYmllbnQ6IGRhdGEubGlnaHRpbmcuYW1iaWVudCxcbiAgICAgICAgZGlmZnVzZTogZGF0YS5saWdodGluZy5kaWZmdXNlLFxuICAgICAgICBzcGVjdWxhcjogZGF0YS5saWdodGluZy5zcGVjdWxhcixcbiAgICAgICAgcm91Z2huZXNzOiBkYXRhLmxpZ2h0aW5nLnJvdWdobmVzcyxcbiAgICAgICAgZnJlc25lbDogZGF0YS5saWdodGluZy5mcmVzbmVsLFxuICAgICAgICB2ZXJ0ZXhOb3JtYWxzRXBzaWxvbjogZGF0YS5saWdodGluZy52ZXJ0ZXhub3JtYWxzZXBzaWxvbixcbiAgICAgICAgZmFjZU5vcm1hbHNFcHNpbG9uOiBkYXRhLmxpZ2h0aW5nLmZhY2Vub3JtYWxzZXBzaWxvbixcbiAgICAgICAgb3BhY2l0eTogZGF0YS5vcGFjaXR5LFxuICAgICAgICBjb250b3VyRW5hYmxlOiBkYXRhLmNvbnRvdXIuc2hvdyxcbiAgICAgICAgY29udG91ckNvbG9yOiBzdHIyUmdiYUFycmF5KGRhdGEuY29udG91ci5jb2xvcikuc2xpY2UoMCwgMyksXG4gICAgICAgIGNvbnRvdXJXaWR0aDogZGF0YS5jb250b3VyLndpZHRoLFxuICAgICAgICB1c2VGYWNldE5vcm1hbHM6IGRhdGEuZmxhdHNoYWRpbmdcbiAgICB9O1xuXG4gICAgaWYoZGF0YS5pbnRlbnNpdHkpIHtcbiAgICAgICAgdmFyIGNPcHRzID0gZXh0cmFjdE9wdHMoZGF0YSk7XG4gICAgICAgIHRoaXMuY29sb3IgPSAnI2ZmZic7XG4gICAgICAgIGNvbmZpZy52ZXJ0ZXhJbnRlbnNpdHkgPSBkYXRhLmludGVuc2l0eTtcbiAgICAgICAgY29uZmlnLnZlcnRleEludGVuc2l0eUJvdW5kcyA9IFtjT3B0cy5taW4sIGNPcHRzLm1heF07XG4gICAgICAgIGNvbmZpZy5jb2xvcm1hcCA9IHBhcnNlQ29sb3JTY2FsZShkYXRhKTtcbiAgICB9IGVsc2UgaWYoZGF0YS52ZXJ0ZXhjb2xvcikge1xuICAgICAgICB0aGlzLmNvbG9yID0gZGF0YS52ZXJ0ZXhjb2xvclswXTtcbiAgICAgICAgY29uZmlnLnZlcnRleENvbG9ycyA9IHBhcnNlQ29sb3JBcnJheShkYXRhLnZlcnRleGNvbG9yKTtcbiAgICB9IGVsc2UgaWYoZGF0YS5mYWNlY29sb3IpIHtcbiAgICAgICAgdGhpcy5jb2xvciA9IGRhdGEuZmFjZWNvbG9yWzBdO1xuICAgICAgICBjb25maWcuY2VsbENvbG9ycyA9IHBhcnNlQ29sb3JBcnJheShkYXRhLmZhY2Vjb2xvcik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jb2xvciA9IGRhdGEuY29sb3I7XG4gICAgICAgIGNvbmZpZy5tZXNoQ29sb3IgPSBzdHIyUmdiYUFycmF5KGRhdGEuY29sb3IpO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSBtZXNoXG4gICAgdGhpcy5tZXNoLnVwZGF0ZShjb25maWcpO1xufTtcblxucHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuc2NlbmUuZ2xwbG90LnJlbW92ZSh0aGlzLm1lc2gpO1xuICAgIHRoaXMubWVzaC5kaXNwb3NlKCk7XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVNZXNoM0RUcmFjZShzY2VuZSwgZGF0YSkge1xuICAgIHZhciBnbCA9IHNjZW5lLmdscGxvdC5nbDtcbiAgICB2YXIgbWVzaCA9IGNyZWF0ZU1lc2goe2dsOiBnbH0pO1xuICAgIHZhciByZXN1bHQgPSBuZXcgTWVzaDNEVHJhY2Uoc2NlbmUsIG1lc2gsIGRhdGEudWlkKTtcbiAgICBtZXNoLl90cmFjZSA9IHJlc3VsdDtcbiAgICByZXN1bHQudXBkYXRlKGRhdGEpO1xuICAgIHNjZW5lLmdscGxvdC5hZGQobWVzaCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVNZXNoM0RUcmFjZTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGVcIjo2MDUsXCIuLi8uLi9saWIvZ2xfZm9ybWF0X2NvbG9yXCI6NzE2LFwiLi4vLi4vbGliL3N0cjJyZ2JhcnJheVwiOjc0MixcIi4uLy4uL3Bsb3RzL2dsM2QvemlwM1wiOjgxOCxcImFscGhhLXNoYXBlXCI6NjQsXCJjb252ZXgtaHVsbFwiOjEzMCxcImRlbGF1bmF5LXRyaWFuZ3VsYXRlXCI6MTY1LFwiZ2wtbWVzaDNkXCI6MjgwfV0sMTA1NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBjb2xvcnNjYWxlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIC8vIHJlYWQgaW4gZmFjZS92ZXJ0ZXggcHJvcGVydGllc1xuICAgIGZ1bmN0aW9uIHJlYWRDb21wb25lbnRzKGFycmF5KSB7XG4gICAgICAgIHZhciByZXQgPSBhcnJheS5tYXAoZnVuY3Rpb24oYXR0cikge1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGNvZXJjZShhdHRyKTtcblxuICAgICAgICAgICAgaWYocmVzdWx0ICYmIExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHJlc3VsdCkpIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHJldC5ldmVyeShmdW5jdGlvbih4KSB7XG4gICAgICAgICAgICByZXR1cm4geCAmJiB4Lmxlbmd0aCA9PT0gcmV0WzBdLmxlbmd0aDtcbiAgICAgICAgfSkgJiYgcmV0O1xuICAgIH1cblxuICAgIHZhciBjb29yZHMgPSByZWFkQ29tcG9uZW50cyhbJ3gnLCAneScsICd6J10pO1xuICAgIGlmKCFjb29yZHMpIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcmVhZENvbXBvbmVudHMoWydpJywgJ2onLCAnayddKTtcbiAgICAvLyB0aHJlZSBpbmRpY2VzIHNob3VsZCBiZSBhbGwgcHJvdmlkZWQgb3Igbm90XG4gICAgaWYoXG4gICAgICAgICh0cmFjZU91dC5pICYmICghdHJhY2VPdXQuaiB8fCAhdHJhY2VPdXQuaykpIHx8XG4gICAgICAgICh0cmFjZU91dC5qICYmICghdHJhY2VPdXQuayB8fCAhdHJhY2VPdXQuaSkpIHx8XG4gICAgICAgICh0cmFjZU91dC5rICYmICghdHJhY2VPdXQuaSB8fCAhdHJhY2VPdXQuaikpXG4gICAgKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBoYW5kbGVDYWxlbmRhckRlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdjYWxlbmRhcnMnLCAnaGFuZGxlVHJhY2VEZWZhdWx0cycpO1xuICAgIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIFsneCcsICd5JywgJ3onXSwgbGF5b3V0KTtcblxuICAgIC8vIENvZXJjZSByZW1haW5pbmcgcHJvcGVydGllc1xuICAgIFtcbiAgICAgICAgJ2xpZ2h0aW5nLmFtYmllbnQnLFxuICAgICAgICAnbGlnaHRpbmcuZGlmZnVzZScsXG4gICAgICAgICdsaWdodGluZy5zcGVjdWxhcicsXG4gICAgICAgICdsaWdodGluZy5yb3VnaG5lc3MnLFxuICAgICAgICAnbGlnaHRpbmcuZnJlc25lbCcsXG4gICAgICAgICdsaWdodGluZy52ZXJ0ZXhub3JtYWxzZXBzaWxvbicsXG4gICAgICAgICdsaWdodGluZy5mYWNlbm9ybWFsc2Vwc2lsb24nLFxuICAgICAgICAnbGlnaHRwb3NpdGlvbi54JyxcbiAgICAgICAgJ2xpZ2h0cG9zaXRpb24ueScsXG4gICAgICAgICdsaWdodHBvc2l0aW9uLnonLFxuICAgICAgICAnY29udG91ci5zaG93JyxcbiAgICAgICAgJ2NvbnRvdXIuY29sb3InLFxuICAgICAgICAnY29udG91ci53aWR0aCcsXG4gICAgICAgICdjb2xvcnNjYWxlJyxcbiAgICAgICAgJ3JldmVyc2VzY2FsZScsXG4gICAgICAgICdmbGF0c2hhZGluZycsXG4gICAgICAgICdhbHBoYWh1bGwnLFxuICAgICAgICAnZGVsYXVuYXlheGlzJyxcbiAgICAgICAgJ29wYWNpdHknXG4gICAgXS5mb3JFYWNoKGZ1bmN0aW9uKHgpIHsgY29lcmNlKHgpOyB9KTtcblxuICAgIGlmKCdpbnRlbnNpdHknIGluIHRyYWNlSW4pIHtcbiAgICAgICAgY29lcmNlKCdpbnRlbnNpdHknKTtcbiAgICAgICAgY29sb3JzY2FsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge3ByZWZpeDogJycsIGNMZXR0ZXI6ICdjJ30pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYWNlT3V0LnNob3dzY2FsZSA9IGZhbHNlO1xuXG4gICAgICAgIGlmKCdmYWNlY29sb3InIGluIHRyYWNlSW4pIGNvZXJjZSgnZmFjZWNvbG9yJyk7XG4gICAgICAgIGVsc2UgaWYoJ3ZlcnRleGNvbG9yJyBpbiB0cmFjZUluKSBjb2VyY2UoJ3ZlcnRleGNvbG9yJyk7XG4gICAgICAgIGVsc2UgY29lcmNlKCdjb2xvcicsIGRlZmF1bHRDb2xvcik7XG4gICAgfVxuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGVtcGxhdGUnKTtcblxuICAgIC8vIGRpc2FibGUgMUQgdHJhbnNmb3Jtc1xuICAgIC8vIHgveS96IHNob3VsZCBtYXRjaCBsZW5ndGhzLCBhbmQgaS9qL2sgc2hvdWxkIG1hdGNoIGFzIHdlbGwsIGJ1dFxuICAgIC8vIHRoZSB0d28gc2V0cyBoYXZlIGRpZmZlcmVudCBsZW5ndGhzIHNvIHRyYW5zZm9ybXMgd291bGRuJ3Qgd29yay5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbnVsbDtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzXCI6NjAzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2F0dHJpYnV0ZXNcIjoxMDUzfV0sMTA1NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgY29sb3JiYXI6IHtcbiAgICAgICAgbWluOiAnY21pbicsXG4gICAgICAgIG1heDogJ2NtYXgnXG4gICAgfSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL2NvbnZlcnQnKSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ21lc2gzZCcsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2dsM2QnKSxcbiAgICBjYXRlZ29yaWVzOiBbJ2dsM2QnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvZ2wzZFwiOjgwNyxcIi4vYXR0cmlidXRlc1wiOjEwNTMsXCIuL2NhbGNcIjoxMDU0LFwiLi9jb252ZXJ0XCI6MTA1NSxcIi4vZGVmYXVsdHNcIjoxMDU2fV0sMTA1ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWInKS5leHRlbmRGbGF0O1xudmFyIHNjYXR0ZXJBdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIGRhc2ggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcvYXR0cmlidXRlcycpLmRhc2g7XG52YXIgZnhBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngvYXR0cmlidXRlcycpO1xudmFyIGRlbHRhID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2RlbHRhLmpzJyk7XG5cbnZhciBJTkNSRUFTSU5HX0NPTE9SID0gZGVsdGEuSU5DUkVBU0lORy5DT0xPUjtcbnZhciBERUNSRUFTSU5HX0NPTE9SID0gZGVsdGEuREVDUkVBU0lORy5DT0xPUjtcblxudmFyIGxpbmVBdHRycyA9IHNjYXR0ZXJBdHRycy5saW5lO1xuXG5mdW5jdGlvbiBkaXJlY3Rpb25BdHRycyhsaW5lQ29sb3JEZWZhdWx0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbGluZToge1xuICAgICAgICAgICAgY29sb3I6IGV4dGVuZEZsYXQoe30sIGxpbmVBdHRycy5jb2xvciwge2RmbHQ6IGxpbmVDb2xvckRlZmF1bHR9KSxcbiAgICAgICAgICAgIHdpZHRoOiBsaW5lQXR0cnMud2lkdGgsXG4gICAgICAgICAgICBkYXNoOiBkYXNoLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuICAgIHg6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgb3Blbjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBoaWdoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGxvdzoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBjbG9zZToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsaW5lOiB7XG4gICAgICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBsaW5lQXR0cnMud2lkdGgsIHtcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgZGFzaDogZXh0ZW5kRmxhdCh7fSwgZGFzaCwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH0sXG5cbiAgICBpbmNyZWFzaW5nOiBkaXJlY3Rpb25BdHRycyhJTkNSRUFTSU5HX0NPTE9SKSxcblxuICAgIGRlY3JlYXNpbmc6IGRpcmVjdGlvbkF0dHJzKERFQ1JFQVNJTkdfQ09MT1IpLFxuXG4gICAgdGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVydGV4dDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGlja3dpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMC41LFxuICAgICAgICBkZmx0OiAwLjMsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgaG92ZXJsYWJlbDogZXh0ZW5kRmxhdCh7fSwgZnhBdHRycy5ob3ZlcmxhYmVsLCB7XG4gICAgICAgIHNwbGl0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH0pLFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcvYXR0cmlidXRlc1wiOjYxMyxcIi4uLy4uL2NvbXBvbmVudHMvZngvYXR0cmlidXRlc1wiOjYyMyxcIi4uLy4uL2NvbnN0YW50cy9kZWx0YS5qc1wiOjY4OSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL3NjYXR0ZXIvYXR0cmlidXRlc1wiOjExMTJ9XSwxMDU5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIF8gPSBMaWIuXztcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG5mdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciB4YSA9IEF4ZXMuZ2V0RnJvbUlkKGdkLCB0cmFjZS54YXhpcyk7XG4gICAgdmFyIHlhID0gQXhlcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnlheGlzKTtcblxuICAgIHZhciB0aWNrTGVuID0gY29udmVydFRpY2tXaWR0aChnZCwgeGEsIHRyYWNlKTtcbiAgICB2YXIgbWluRGlmZiA9IHRyYWNlLl9taW5EaWZmO1xuICAgIHRyYWNlLl9taW5EaWZmID0gbnVsbDtcbiAgICB2YXIgeCA9IHRyYWNlLl94Y2FsYztcbiAgICB0cmFjZS5feGNhbGMgPSBudWxsO1xuXG4gICAgdmFyIGNkID0gY2FsY0NvbW1vbihnZCwgdHJhY2UsIHgsIHlhLCBwdEZ1bmMpO1xuXG4gICAgdHJhY2UuX2V4dHJlbWVzW3hhLl9pZF0gPSBBeGVzLmZpbmRFeHRyZW1lcyh4YSwgeCwge3ZwYWQ6IG1pbkRpZmYgLyAyfSk7XG4gICAgaWYoY2QubGVuZ3RoKSB7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KGNkWzBdLnQsIHtcbiAgICAgICAgICAgIHdIb3ZlcjogbWluRGlmZiAvIDIsXG4gICAgICAgICAgICB0aWNrTGVuOiB0aWNrTGVuXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY2Q7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFt7dDoge2VtcHR5OiB0cnVlfX1dO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcHRGdW5jKG8sIGgsIGwsIGMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBvOiBvLFxuICAgICAgICBoOiBoLFxuICAgICAgICBsOiBsLFxuICAgICAgICBjOiBjXG4gICAgfTtcbn1cblxuXG4vLyBzaGFyZWQgYmV0d2VlbiBPSExDIGFuZCBjYW5kbGVzdGlja1xuLy8gcHRGdW5jIG1ha2VzIGEgY2FsY2RhdGEgcG9pbnQgc3BlY2lmaWMgdG8gZWFjaCB0cmFjZSB0eXBlLCBmcm9tIG9pLCBoaSwgbGksIGNpXG5mdW5jdGlvbiBjYWxjQ29tbW9uKGdkLCB0cmFjZSwgeCwgeWEsIHB0RnVuYykge1xuICAgIHZhciBvID0geWEubWFrZUNhbGNkYXRhKHRyYWNlLCAnb3BlbicpO1xuICAgIHZhciBoID0geWEubWFrZUNhbGNkYXRhKHRyYWNlLCAnaGlnaCcpO1xuICAgIHZhciBsID0geWEubWFrZUNhbGNkYXRhKHRyYWNlLCAnbG93Jyk7XG4gICAgdmFyIGMgPSB5YS5tYWtlQ2FsY2RhdGEodHJhY2UsICdjbG9zZScpO1xuXG4gICAgdmFyIGhhc1RleHRBcnJheSA9IEFycmF5LmlzQXJyYXkodHJhY2UudGV4dCk7XG4gICAgdmFyIGhhc0hvdmVydGV4dEFycmF5ID0gQXJyYXkuaXNBcnJheSh0cmFjZS5ob3ZlcnRleHQpO1xuXG4gICAgLy8gd2UncmUgb3B0aW1pc3RzIC0gYmVmb3JlIHdlIGhhdmUgYW55IGNoYW5naW5nIGRhdGEsIGFzc3VtZSBpbmNyZWFzaW5nXG4gICAgdmFyIGluY3JlYXNpbmcgPSB0cnVlO1xuICAgIHZhciBjUHJldiA9IG51bGw7XG5cbiAgICB2YXIgY2QgPSBbXTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgeGkgPSB4W2ldO1xuICAgICAgICB2YXIgb2kgPSBvW2ldO1xuICAgICAgICB2YXIgaGkgPSBoW2ldO1xuICAgICAgICB2YXIgbGkgPSBsW2ldO1xuICAgICAgICB2YXIgY2kgPSBjW2ldO1xuXG4gICAgICAgIGlmKHhpICE9PSBCQUROVU0gJiYgb2kgIT09IEJBRE5VTSAmJiBoaSAhPT0gQkFETlVNICYmIGxpICE9PSBCQUROVU0gJiYgY2kgIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgaWYoY2kgPT09IG9pKSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgb3BlbiA9PSBjbG9zZSwgbG9vayBmb3IgYSBjaGFuZ2UgZnJvbSB0aGUgcHJldmlvdXMgY2xvc2VcbiAgICAgICAgICAgICAgICBpZihjUHJldiAhPT0gbnVsbCAmJiBjaSAhPT0gY1ByZXYpIGluY3JlYXNpbmcgPSBjaSA+IGNQcmV2O1xuICAgICAgICAgICAgICAgIC8vIGVsc2UgKGMgPT09IGNQcmV2IG9yIGNQcmV2IGlzIG51bGwpIG5vIGNoYW5nZVxuICAgICAgICAgICAgfSBlbHNlIGluY3JlYXNpbmcgPSBjaSA+IG9pO1xuXG4gICAgICAgICAgICBjUHJldiA9IGNpO1xuXG4gICAgICAgICAgICB2YXIgcHQgPSBwdEZ1bmMob2ksIGhpLCBsaSwgY2kpO1xuXG4gICAgICAgICAgICBwdC5wb3MgPSB4aTtcbiAgICAgICAgICAgIHB0LnljID0gKG9pICsgY2kpIC8gMjtcbiAgICAgICAgICAgIHB0LmkgPSBpO1xuICAgICAgICAgICAgcHQuZGlyID0gaW5jcmVhc2luZyA/ICdpbmNyZWFzaW5nJyA6ICdkZWNyZWFzaW5nJztcblxuICAgICAgICAgICAgLy8gRm9yIGNhdGVnb3J5b3JkZXIsIHN0b3JlIGxvdyBhbmQgaGlnaFxuICAgICAgICAgICAgcHQueCA9IHB0LnBvcztcbiAgICAgICAgICAgIHB0LnkgPSBbbGksIGhpXTtcblxuICAgICAgICAgICAgaWYoaGFzVGV4dEFycmF5KSBwdC50eCA9IHRyYWNlLnRleHRbaV07XG4gICAgICAgICAgICBpZihoYXNIb3ZlcnRleHRBcnJheSkgcHQuaHR4ID0gdHJhY2UuaG92ZXJ0ZXh0W2ldO1xuXG4gICAgICAgICAgICBjZC5wdXNoKHB0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNkLnB1c2goe3BvczogeGksIGVtcHR5OiB0cnVlfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0cmFjZS5fZXh0cmVtZXNbeWEuX2lkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKHlhLCBMaWIuY29uY2F0KGwsIGgpLCB7cGFkZGVkOiB0cnVlfSk7XG5cbiAgICBpZihjZC5sZW5ndGgpIHtcbiAgICAgICAgY2RbMF0udCA9IHtcbiAgICAgICAgICAgIGxhYmVsczoge1xuICAgICAgICAgICAgICAgIG9wZW46IF8oZ2QsICdvcGVuOicpICsgJyAnLFxuICAgICAgICAgICAgICAgIGhpZ2g6IF8oZ2QsICdoaWdoOicpICsgJyAnLFxuICAgICAgICAgICAgICAgIGxvdzogXyhnZCwgJ2xvdzonKSArICcgJyxcbiAgICAgICAgICAgICAgICBjbG9zZTogXyhnZCwgJ2Nsb3NlOicpICsgJyAnXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGNkO1xufVxuXG4vKlxuICogZmluZCBtaW4geC1jb29yZGluYXRlcyBkaWZmZXJlbmNlIG9mIGFsbCB0cmFjZXNcbiAqIGF0dGFjaGVkIHRvIHRoaXMgeC1heGlzIGFuZCBzdGFzaCB0aGUgcmVzdWx0IGluIF9taW5EaWZmXG4gKiBpbiBhbGwgdHJhY2VzOyB3aGVuIGEgdHJhY2UgdXNlcyB0aGlzIGluIGl0c1xuICogY2FsYyBzdGVwIGl0IGRlbGV0ZXMgX21pbkRpZmYsIHNvIHRoYXQgbmV4dCBjYWxjIHRoaXMgaXNcbiAqIGRvbmUgYWdhaW4gaW4gY2FzZSB0aGUgZGF0YSBjaGFuZ2VkLlxuICogYWxzbyBzaW5jZSB3ZSBuZWVkIGl0IGhlcmUsIHN0YXNoIF94Y2FsYyBvbiB0aGUgdHJhY2VcbiAqL1xuZnVuY3Rpb24gY29udmVydFRpY2tXaWR0aChnZCwgeGEsIHRyYWNlKSB7XG4gICAgdmFyIG1pbkRpZmYgPSB0cmFjZS5fbWluRGlmZjtcblxuICAgIGlmKCFtaW5EaWZmKSB7XG4gICAgICAgIHZhciBmdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICAgICAgdmFyIG9obGNUcmFjZXNPblRoaXNYYXhpcyA9IFtdO1xuXG4gICAgICAgIG1pbkRpZmYgPSBJbmZpbml0eTtcblxuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBmdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHRyYWNlaSA9IGZ1bGxEYXRhW2ldO1xuXG4gICAgICAgICAgICBpZih0cmFjZWkudHlwZSA9PT0gJ29obGMnICYmXG4gICAgICAgICAgICAgICAgdHJhY2VpLnZpc2libGUgPT09IHRydWUgJiZcbiAgICAgICAgICAgICAgICB0cmFjZWkueGF4aXMgPT09IHhhLl9pZFxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgb2hsY1RyYWNlc09uVGhpc1hheGlzLnB1c2godHJhY2VpKTtcblxuICAgICAgICAgICAgICAgIHZhciB4Y2FsYyA9IHhhLm1ha2VDYWxjZGF0YSh0cmFjZWksICd4Jyk7XG4gICAgICAgICAgICAgICAgdHJhY2VpLl94Y2FsYyA9IHhjYWxjO1xuXG4gICAgICAgICAgICAgICAgdmFyIF9taW5EaWZmID0gTGliLmRpc3RpbmN0VmFscyh4Y2FsYykubWluRGlmZjtcbiAgICAgICAgICAgICAgICBpZihfbWluRGlmZiAmJiBpc0Zpbml0ZShfbWluRGlmZikpIHtcbiAgICAgICAgICAgICAgICAgICAgbWluRGlmZiA9IE1hdGgubWluKG1pbkRpZmYsIF9taW5EaWZmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiBtaW5EaWZmIGlzIHN0aWxsIEluZmluaXR5IGhlcmUsIHNldCBpdCB0byAxXG4gICAgICAgIGlmKG1pbkRpZmYgPT09IEluZmluaXR5KSBtaW5EaWZmID0gMTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBvaGxjVHJhY2VzT25UaGlzWGF4aXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG9obGNUcmFjZXNPblRoaXNYYXhpc1tpXS5fbWluRGlmZiA9IG1pbkRpZmY7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWluRGlmZiAqIHRyYWNlLnRpY2t3aWR0aDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY2FsYzogY2FsYyxcbiAgICBjYWxjQ29tbW9uOiBjYWxjQ29tbW9uXG59O1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2N31dLDEwNjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBoYW5kbGVPSExDID0gX2RlcmVxXygnLi9vaGxjX2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlT0hMQyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpO1xuICAgIGlmKCFsZW4pIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29lcmNlKCdsaW5lLndpZHRoJyk7XG4gICAgY29lcmNlKCdsaW5lLmRhc2gnKTtcblxuICAgIGhhbmRsZURpcmVjdGlvbih0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCAnaW5jcmVhc2luZycpO1xuICAgIGhhbmRsZURpcmVjdGlvbih0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCAnZGVjcmVhc2luZycpO1xuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ3RpY2t3aWR0aCcpO1xuXG4gICAgbGF5b3V0Ll9yZXF1ZXN0UmFuZ2VzbGlkZXJbdHJhY2VPdXQueGF4aXNdID0gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZURpcmVjdGlvbih0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBkaXJlY3Rpb24pIHtcbiAgICBjb2VyY2UoZGlyZWN0aW9uICsgJy5saW5lLmNvbG9yJyk7XG4gICAgY29lcmNlKGRpcmVjdGlvbiArICcubGluZS53aWR0aCcsIHRyYWNlT3V0LmxpbmUud2lkdGgpO1xuICAgIGNvZXJjZShkaXJlY3Rpb24gKyAnLmxpbmUuZGFzaCcsIHRyYWNlT3V0LmxpbmUuZGFzaCk7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi9hdHRyaWJ1dGVzXCI6MTA1OCxcIi4vb2hsY19kZWZhdWx0c1wiOjEwNjN9XSwxMDYxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEZ4ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGZpbGxUZXh0ID0gX2RlcmVxXygnLi4vLi4vbGliJykuZmlsbFRleHQ7XG52YXIgZGVsdGEgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvZGVsdGEuanMnKTtcblxudmFyIERJUlNZTUJPTCA9IHtcbiAgICBpbmNyZWFzaW5nOiBkZWx0YS5JTkNSRUFTSU5HLlNZTUJPTCxcbiAgICBkZWNyZWFzaW5nOiBkZWx0YS5ERUNSRUFTSU5HLlNZTUJPTFxufTtcblxuZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICBpZih0cmFjZS5ob3ZlcmxhYmVsLnNwbGl0KSB7XG4gICAgICAgIHJldHVybiBob3ZlclNwbGl0KHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaG92ZXJPblBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSk7XG59XG5cbmZ1bmN0aW9uIGdldENsb3Nlc3RQb2ludChwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgeGEgPSBwb2ludERhdGEueGE7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIHQgPSBjZFswXS50O1xuXG4gICAgdmFyIHR5cGUgPSB0cmFjZS50eXBlO1xuICAgIHZhciBtaW5BdHRyID0gdHlwZSA9PT0gJ29obGMnID8gJ2wnIDogJ21pbic7XG4gICAgdmFyIG1heEF0dHIgPSB0eXBlID09PSAnb2hsYycgPyAnaCcgOiAnbWF4JztcblxuICAgIHZhciBob3ZlclBzZXVkb0Rpc3RhbmNlLCBzcGlrZVBzZXVkb0Rpc3RhbmNlO1xuXG4gICAgLy8gcG90ZW50aWFsbHkgc2hpZnQgeHZhbCBmb3IgZ3JvdXBlZCBjYW5kbGVzdGlja3NcbiAgICB2YXIgY2VudGVyU2hpZnQgPSB0LmJQb3MgfHwgMDtcbiAgICB2YXIgc2hpZnRQb3MgPSBmdW5jdGlvbihkaSkgeyByZXR1cm4gZGkucG9zICsgY2VudGVyU2hpZnQgLSB4dmFsOyB9O1xuXG4gICAgLy8gb2hsYyBhbmQgY2FuZGxlc3RpY2sgY2FsbCBkaXNwbGF5SGFsZldpZHRoIGRpZmZlcmVudCB0aGluZ3MuLi5cbiAgICB2YXIgZGlzcGxheUhhbGZXaWR0aCA9IHQuYmRQb3MgfHwgdC50aWNrTGVuO1xuICAgIHZhciBob3ZlckhhbGZXaWR0aCA9IHQud0hvdmVyO1xuXG4gICAgLy8gaWYgdHdvIGZpZ3VyZXMgYXJlIG92ZXJsYXlpbmcsIGxldCB0aGUgbmFycm93ZXN0IG9uZSB3aW5cbiAgICB2YXIgcHNldWRvRGlzdGFuY2UgPSBNYXRoLm1pbigxLCBkaXNwbGF5SGFsZldpZHRoIC8gTWF0aC5hYnMoeGEucjJjKHhhLnJhbmdlWzFdKSAtIHhhLnIyYyh4YS5yYW5nZVswXSkpKTtcbiAgICBob3ZlclBzZXVkb0Rpc3RhbmNlID0gcG9pbnREYXRhLm1heEhvdmVyRGlzdGFuY2UgLSBwc2V1ZG9EaXN0YW5jZTtcbiAgICBzcGlrZVBzZXVkb0Rpc3RhbmNlID0gcG9pbnREYXRhLm1heFNwaWtlRGlzdGFuY2UgLSBwc2V1ZG9EaXN0YW5jZTtcblxuICAgIGZ1bmN0aW9uIGR4KGRpKSB7XG4gICAgICAgIHZhciBwb3MgPSBzaGlmdFBvcyhkaSk7XG4gICAgICAgIHJldHVybiBGeC5pbmJveChwb3MgLSBob3ZlckhhbGZXaWR0aCwgcG9zICsgaG92ZXJIYWxmV2lkdGgsIGhvdmVyUHNldWRvRGlzdGFuY2UpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGR5KGRpKSB7XG4gICAgICAgIHZhciBtaW4gPSBkaVttaW5BdHRyXTtcbiAgICAgICAgdmFyIG1heCA9IGRpW21heEF0dHJdO1xuICAgICAgICByZXR1cm4gbWluID09PSBtYXggfHwgRnguaW5ib3gobWluIC0geXZhbCwgbWF4IC0geXZhbCwgaG92ZXJQc2V1ZG9EaXN0YW5jZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZHh5KGRpKSB7IHJldHVybiAoZHgoZGkpICsgZHkoZGkpKSAvIDI7IH1cblxuICAgIHZhciBkaXN0Zm4gPSBGeC5nZXREaXN0YW5jZUZ1bmN0aW9uKGhvdmVybW9kZSwgZHgsIGR5LCBkeHkpO1xuICAgIEZ4LmdldENsb3Nlc3QoY2QsIGRpc3RmbiwgcG9pbnREYXRhKTtcblxuICAgIGlmKHBvaW50RGF0YS5pbmRleCA9PT0gZmFsc2UpIHJldHVybiBudWxsO1xuXG4gICAgdmFyIGRpID0gY2RbcG9pbnREYXRhLmluZGV4XTtcblxuICAgIGlmKGRpLmVtcHR5KSByZXR1cm4gbnVsbDtcblxuICAgIHZhciBkaXIgPSBkaS5kaXI7XG4gICAgdmFyIGNvbnRhaW5lciA9IHRyYWNlW2Rpcl07XG4gICAgdmFyIGxjID0gY29udGFpbmVyLmxpbmUuY29sb3I7XG5cbiAgICBpZihDb2xvci5vcGFjaXR5KGxjKSAmJiBjb250YWluZXIubGluZS53aWR0aCkgcG9pbnREYXRhLmNvbG9yID0gbGM7XG4gICAgZWxzZSBwb2ludERhdGEuY29sb3IgPSBjb250YWluZXIuZmlsbGNvbG9yO1xuXG4gICAgcG9pbnREYXRhLngwID0geGEuYzJwKGRpLnBvcyArIGNlbnRlclNoaWZ0IC0gZGlzcGxheUhhbGZXaWR0aCwgdHJ1ZSk7XG4gICAgcG9pbnREYXRhLngxID0geGEuYzJwKGRpLnBvcyArIGNlbnRlclNoaWZ0ICsgZGlzcGxheUhhbGZXaWR0aCwgdHJ1ZSk7XG5cbiAgICBwb2ludERhdGEueExhYmVsVmFsID0gZGkucG9zO1xuXG4gICAgcG9pbnREYXRhLnNwaWtlRGlzdGFuY2UgPSBkeHkoZGkpICogc3Bpa2VQc2V1ZG9EaXN0YW5jZSAvIGhvdmVyUHNldWRvRGlzdGFuY2U7XG4gICAgcG9pbnREYXRhLnhTcGlrZSA9IHhhLmMycChkaS5wb3MsIHRydWUpO1xuXG4gICAgcmV0dXJuIHBvaW50RGF0YTtcbn1cblxuZnVuY3Rpb24gaG92ZXJTcGxpdChwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgeWEgPSBwb2ludERhdGEueWE7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIHQgPSBjZFswXS50O1xuICAgIHZhciBjbG9zZUJveERhdGEgPSBbXTtcblxuICAgIHZhciBjbG9zZXN0UG9pbnQgPSBnZXRDbG9zZXN0UG9pbnQocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpO1xuICAgIC8vIHNraXAgdGhlIHJlc3QgKGZvciB0aGlzIHRyYWNlKSBpZiB3ZSBkaWRuJ3QgZmluZCBhIGNsb3NlIHBvaW50XG4gICAgaWYoIWNsb3Nlc3RQb2ludCkgcmV0dXJuIFtdO1xuXG4gICAgdmFyIGNkSW5kZXggPSBjbG9zZXN0UG9pbnQuaW5kZXg7XG4gICAgdmFyIGRpID0gY2RbY2RJbmRleF07XG4gICAgdmFyIGhvdmVyaW5mbyA9IGRpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgaG92ZXJQYXJ0cyA9IGhvdmVyaW5mby5zcGxpdCgnKycpO1xuICAgIHZhciBpc0FsbCA9IGhvdmVyaW5mbyA9PT0gJ2FsbCc7XG4gICAgdmFyIGhhc1kgPSBpc0FsbCB8fCBob3ZlclBhcnRzLmluZGV4T2YoJ3knKSAhPT0gLTE7XG5cbiAgICAvLyBzaW1pbGFyIHRvIGhvdmVyT25Qb2ludHMsIHdlIHJldHVybiBub3RoaW5nXG4gICAgLy8gaWYgYWxsIG9yIHkgaXMgbm90IHByZXNlbnQuXG4gICAgaWYoIWhhc1kpIHJldHVybiBbXTtcblxuICAgIHZhciBhdHRycyA9IFsnaGlnaCcsICdvcGVuJywgJ2Nsb3NlJywgJ2xvdyddO1xuXG4gICAgLy8gc2V2ZXJhbCBhdHRyaWJ1dGVzIGNhbiBoYXZlIHRoZSBzYW1lIHktY29vcmRpbmF0ZS4gV2Ugd2lsbFxuICAgIC8vIGJ1bmNoIHRoZW0gdG9nZXRoZXIgaW4gYSBzaW5nbGUgdGV4dCBibG9jay4gRm9yIHRoaXMsIHdlIGtlZXBcbiAgICAvLyBhIGRpY3Rpb25hcnkgbWFwcGluZyB5LWNvb3JkIC0+IHBvaW50IGRhdGEuXG4gICAgdmFyIHVzZWRWYWxzID0ge307XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYXR0cnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGF0dHIgPSBhdHRyc1tpXTtcblxuICAgICAgICB2YXIgdmFsID0gdHJhY2VbYXR0cl1bY2xvc2VzdFBvaW50LmluZGV4XTtcbiAgICAgICAgdmFyIHZhbFB4ID0geWEuYzJwKHZhbCwgdHJ1ZSk7XG4gICAgICAgIHZhciBwb2ludERhdGEyO1xuICAgICAgICBpZih2YWwgaW4gdXNlZFZhbHMpIHtcbiAgICAgICAgICAgIHBvaW50RGF0YTIgPSB1c2VkVmFsc1t2YWxdO1xuICAgICAgICAgICAgcG9pbnREYXRhMi55TGFiZWwgKz0gJzxicj4nICsgdC5sYWJlbHNbYXR0cl0gKyBBeGVzLmhvdmVyTGFiZWxUZXh0KHlhLCB2YWwpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY29weSBvdXQgdG8gYSBuZXcgb2JqZWN0IGZvciBlYWNoIG5ldyB5LXZhbHVlIHRvIGxhYmVsXG4gICAgICAgICAgICBwb2ludERhdGEyID0gTGliLmV4dGVuZEZsYXQoe30sIGNsb3Nlc3RQb2ludCk7XG5cbiAgICAgICAgICAgIHBvaW50RGF0YTIueTAgPSBwb2ludERhdGEyLnkxID0gdmFsUHg7XG4gICAgICAgICAgICBwb2ludERhdGEyLnlMYWJlbFZhbCA9IHZhbDtcbiAgICAgICAgICAgIHBvaW50RGF0YTIueUxhYmVsID0gdC5sYWJlbHNbYXR0cl0gKyBBeGVzLmhvdmVyTGFiZWxUZXh0KHlhLCB2YWwpO1xuXG4gICAgICAgICAgICBwb2ludERhdGEyLm5hbWUgPSAnJztcblxuICAgICAgICAgICAgY2xvc2VCb3hEYXRhLnB1c2gocG9pbnREYXRhMik7XG4gICAgICAgICAgICB1c2VkVmFsc1t2YWxdID0gcG9pbnREYXRhMjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjbG9zZUJveERhdGE7XG59XG5cbmZ1bmN0aW9uIGhvdmVyT25Qb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHlhID0gcG9pbnREYXRhLnlhO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciB0ID0gY2RbMF0udDtcblxuICAgIHZhciBjbG9zZXN0UG9pbnQgPSBnZXRDbG9zZXN0UG9pbnQocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpO1xuICAgIC8vIHNraXAgdGhlIHJlc3QgKGZvciB0aGlzIHRyYWNlKSBpZiB3ZSBkaWRuJ3QgZmluZCBhIGNsb3NlIHBvaW50XG4gICAgaWYoIWNsb3Nlc3RQb2ludCkgcmV0dXJuIFtdO1xuXG4gICAgLy8gd2UgZG9uJ3QgbWFrZSBhIGNhbGNkYXRhIHBvaW50IGlmIHdlJ3JlIG1pc3NpbmcgYW55IHBpZWNlICh4L28vaC9sL2MpXG4gICAgLy8gc28gd2UgbmVlZCB0byBmaXggdGhlIGluZGV4IGhlcmUgdG8gcG9pbnQgdG8gdGhlIGRhdGEgYXJyYXlzXG4gICAgdmFyIGNkSW5kZXggPSBjbG9zZXN0UG9pbnQuaW5kZXg7XG4gICAgdmFyIGRpID0gY2RbY2RJbmRleF07XG4gICAgdmFyIGkgPSBjbG9zZXN0UG9pbnQuaW5kZXggPSBkaS5pO1xuICAgIHZhciBkaXIgPSBkaS5kaXI7XG5cbiAgICBmdW5jdGlvbiBnZXRMYWJlbExpbmUoYXR0cikge1xuICAgICAgICByZXR1cm4gdC5sYWJlbHNbYXR0cl0gKyBBeGVzLmhvdmVyTGFiZWxUZXh0KHlhLCB0cmFjZVthdHRyXVtpXSk7XG4gICAgfVxuXG4gICAgdmFyIGhvdmVyaW5mbyA9IGRpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgaG92ZXJQYXJ0cyA9IGhvdmVyaW5mby5zcGxpdCgnKycpO1xuICAgIHZhciBpc0FsbCA9IGhvdmVyaW5mbyA9PT0gJ2FsbCc7XG4gICAgdmFyIGhhc1kgPSBpc0FsbCB8fCBob3ZlclBhcnRzLmluZGV4T2YoJ3knKSAhPT0gLTE7XG4gICAgdmFyIGhhc1RleHQgPSBpc0FsbCB8fCBob3ZlclBhcnRzLmluZGV4T2YoJ3RleHQnKSAhPT0gLTE7XG5cbiAgICB2YXIgdGV4dFBhcnRzID0gaGFzWSA/IFtcbiAgICAgICAgZ2V0TGFiZWxMaW5lKCdvcGVuJyksXG4gICAgICAgIGdldExhYmVsTGluZSgnaGlnaCcpLFxuICAgICAgICBnZXRMYWJlbExpbmUoJ2xvdycpLFxuICAgICAgICBnZXRMYWJlbExpbmUoJ2Nsb3NlJykgKyAnICAnICsgRElSU1lNQk9MW2Rpcl1cbiAgICBdIDogW107XG4gICAgaWYoaGFzVGV4dCkgZmlsbFRleHQoZGksIHRyYWNlLCB0ZXh0UGFydHMpO1xuXG4gICAgLy8gZG9uJ3QgbWFrZSAueUxhYmVsVmFsIG9yIC50ZXh0LCBzaW5jZSB3ZSdyZSBtYW5hZ2luZyBob3ZlcmluZm9cbiAgICAvLyBwdXQgaXQgYWxsIGluIC5leHRyYVRleHRcbiAgICBjbG9zZXN0UG9pbnQuZXh0cmFUZXh0ID0gdGV4dFBhcnRzLmpvaW4oJzxicj4nKTtcblxuICAgIC8vIHRoaXMgcHV0cyB0aGUgbGFiZWwgKmFuZCB0aGUgc3Bpa2UqIGF0IHRoZSBtaWRwb2ludCBvZiB0aGUgYm94LCBpZVxuICAgIC8vIGhhbGZ3YXkgYmV0d2VlbiBvcGVuIGFuZCBjbG9zZSwgbm90IGJldHdlZW4gaGlnaCBhbmQgbG93LlxuICAgIGNsb3Nlc3RQb2ludC55MCA9IGNsb3Nlc3RQb2ludC55MSA9IHlhLmMycChkaS55YywgdHJ1ZSk7XG5cbiAgICByZXR1cm4gW2Nsb3Nlc3RQb2ludF07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhvdmVyUG9pbnRzOiBob3ZlclBvaW50cyxcbiAgICBob3ZlclNwbGl0OiBob3ZlclNwbGl0LFxuICAgIGhvdmVyT25Qb2ludHM6IGhvdmVyT25Qb2ludHNcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZnhcIjo2MzIsXCIuLi8uLi9jb25zdGFudHMvZGVsdGEuanNcIjo2ODksXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2N31dLDEwNjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdvaGxjJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuJyksXG4gICAgY2F0ZWdvcmllczogWydjYXJ0ZXNpYW4nLCAnc3ZnJywgJ3Nob3dMZWdlbmQnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLmNhbGMsXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JyksXG4gICAgc3R5bGU6IF9kZXJlcV8oJy4vc3R5bGUnKSxcbiAgICBob3ZlclBvaW50czogX2RlcmVxXygnLi9ob3ZlcicpLmhvdmVyUG9pbnRzLFxuICAgIHNlbGVjdFBvaW50czogX2RlcmVxXygnLi9zZWxlY3QnKVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW5cIjo3NzgsXCIuL2F0dHJpYnV0ZXNcIjoxMDU4LFwiLi9jYWxjXCI6MTA1OSxcIi4vZGVmYXVsdHNcIjoxMDYwLFwiLi9ob3ZlclwiOjEwNjEsXCIuL3Bsb3RcIjoxMDY0LFwiLi9zZWxlY3RcIjoxMDY1LFwiLi9zdHlsZVwiOjEwNjZ9XSwxMDYzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVPSExDKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCkge1xuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIG9wZW4gPSBjb2VyY2UoJ29wZW4nKTtcbiAgICB2YXIgaGlnaCA9IGNvZXJjZSgnaGlnaCcpO1xuICAgIHZhciBsb3cgPSBjb2VyY2UoJ2xvdycpO1xuICAgIHZhciBjbG9zZSA9IGNvZXJjZSgnY2xvc2UnKTtcblxuICAgIGNvZXJjZSgnaG92ZXJsYWJlbC5zcGxpdCcpO1xuXG4gICAgdmFyIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdoYW5kbGVUcmFjZURlZmF1bHRzJyk7XG4gICAgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgWyd4J10sIGxheW91dCk7XG5cbiAgICBpZighKG9wZW4gJiYgaGlnaCAmJiBsb3cgJiYgY2xvc2UpKSByZXR1cm47XG5cbiAgICB2YXIgbGVuID0gTWF0aC5taW4ob3Blbi5sZW5ndGgsIGhpZ2gubGVuZ3RoLCBsb3cubGVuZ3RoLCBjbG9zZS5sZW5ndGgpO1xuICAgIGlmKHgpIGxlbiA9IE1hdGgubWluKGxlbiwgTGliLm1pblJvd0xlbmd0aCh4KSk7XG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIHJldHVybiBsZW47XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3fV0sMTA2NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBwbG90aW5mbywgY2RPSExDLCBvaGxjTGF5ZXIpIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIExpYi5tYWtlVHJhY2VHcm91cHMob2hsY0xheWVyLCBjZE9ITEMsICd0cmFjZSBvaGxjJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0ID0gY2QwLnQ7XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICBpZih0cmFjZS52aXNpYmxlICE9PSB0cnVlIHx8IHQuZW1wdHkpIHtcbiAgICAgICAgICAgIHBsb3RHcm91cC5yZW1vdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0aWNrTGVuID0gdC50aWNrTGVuO1xuXG4gICAgICAgIHZhciBwYXRocyA9IHBsb3RHcm91cC5zZWxlY3RBbGwoJ3BhdGgnKS5kYXRhKExpYi5pZGVudGl0eSk7XG5cbiAgICAgICAgcGF0aHMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKTtcblxuICAgICAgICBwYXRocy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgcGF0aHMuYXR0cignZCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGlmKGQuZW1wdHkpIHJldHVybiAnTTAsMFonO1xuXG4gICAgICAgICAgICB2YXIgeCA9IHhhLmMycChkLnBvcywgdHJ1ZSk7XG4gICAgICAgICAgICB2YXIgeG8gPSB4YS5jMnAoZC5wb3MgLSB0aWNrTGVuLCB0cnVlKTtcbiAgICAgICAgICAgIHZhciB4YyA9IHhhLmMycChkLnBvcyArIHRpY2tMZW4sIHRydWUpO1xuXG4gICAgICAgICAgICB2YXIgeW8gPSB5YS5jMnAoZC5vLCB0cnVlKTtcbiAgICAgICAgICAgIHZhciB5aCA9IHlhLmMycChkLmgsIHRydWUpO1xuICAgICAgICAgICAgdmFyIHlsID0geWEuYzJwKGQubCwgdHJ1ZSk7XG4gICAgICAgICAgICB2YXIgeWMgPSB5YS5jMnAoZC5jLCB0cnVlKTtcblxuICAgICAgICAgICAgcmV0dXJuICdNJyArIHhvICsgJywnICsgeW8gKyAnSCcgKyB4ICtcbiAgICAgICAgICAgICAgICAnTScgKyB4ICsgJywnICsgeWggKyAnVicgKyB5bCArXG4gICAgICAgICAgICAgICAgJ00nICsgeGMgKyAnLCcgKyB5YyArICdIJyArIHg7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCJkM1wiOjE2M31dLDEwNjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNlbGVjdFBvaW50cyhzZWFyY2hJbmZvLCBzZWxlY3Rpb25UZXN0ZXIpIHtcbiAgICB2YXIgY2QgPSBzZWFyY2hJbmZvLmNkO1xuICAgIHZhciB4YSA9IHNlYXJjaEluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gc2VhcmNoSW5mby55YXhpcztcbiAgICB2YXIgc2VsZWN0aW9uID0gW107XG4gICAgdmFyIGk7XG4gICAgLy8gZm9yIChwb3RlbnRpYWxseSBncm91cGVkKSBjYW5kbGVzdGlja3NcbiAgICB2YXIgcG9zT2Zmc2V0ID0gY2RbMF0udC5iUG9zIHx8IDA7XG5cbiAgICBpZihzZWxlY3Rpb25UZXN0ZXIgPT09IGZhbHNlKSB7XG4gICAgICAgIC8vIGNsZWFyIHNlbGVjdGlvblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBkaSA9IGNkW2ldO1xuXG4gICAgICAgICAgICBpZihzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3hhLmMycChkaS5wb3MgKyBwb3NPZmZzZXQpLCB5YS5jMnAoZGkueWMpXSwgbnVsbCwgZGkuaSwgc2VhcmNoSW5mbykpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24ucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50TnVtYmVyOiBkaS5pLFxuICAgICAgICAgICAgICAgICAgICB4OiB4YS5jMmQoZGkucG9zKSxcbiAgICAgICAgICAgICAgICAgICAgeTogeWEuYzJkKGRpLnljKVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGRpLnNlbGVjdGVkID0gMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGkuc2VsZWN0ZWQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGVjdGlvbjtcbn07XG5cbn0se31dLDEwNjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHlsZShnZCwgY2QsIHNlbCkge1xuICAgIHZhciBzID0gc2VsID8gc2VsIDogZDMuc2VsZWN0KGdkKS5zZWxlY3RBbGwoJ2cub2hsY2xheWVyJykuc2VsZWN0QWxsKCdnLnRyYWNlJyk7XG5cbiAgICBzLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gZFswXS50cmFjZS5vcGFjaXR5O1xuICAgIH0pO1xuXG4gICAgcy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHRyYWNlID0gZFswXS50cmFjZTtcblxuICAgICAgICBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdwYXRoJykuZWFjaChmdW5jdGlvbihkaSkge1xuICAgICAgICAgICAgaWYoZGkuZW1wdHkpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIGRpckxpbmUgPSB0cmFjZVtkaS5kaXJdLmxpbmU7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcylcbiAgICAgICAgICAgICAgICAuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpXG4gICAgICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBkaXJMaW5lLmNvbG9yKVxuICAgICAgICAgICAgICAgIC5jYWxsKERyYXdpbmcuZGFzaExpbmUsIGRpckxpbmUuZGFzaCwgZGlyTGluZS53aWR0aClcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBjdXN0b20gc2VsZWN0aW9uIHN0eWxlIGZvciBPSExDXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgdHJhY2Uuc2VsZWN0ZWRwb2ludHMgJiYgIWRpLnNlbGVjdGVkID8gMC4zIDogMSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiZDNcIjoxNjN9XSwxMDY3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBwbG90QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgZm9udEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JTY2FsZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBob3ZlcnRlbXBsYXRlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZG9tYWluJykuYXR0cmlidXRlcztcblxudmFyIGxpbmUgPSBleHRlbmRGbGF0KFxuICAgIHtlZGl0VHlwZTogJ2NhbGMnfSxcbiAgICBjb2xvclNjYWxlQXR0cnMoJ2xpbmUnLCB7ZWRpdFR5cGVPdmVycmlkZTogJ2NhbGMnfSksXG4gICAge1xuICAgICAgICBzaGFwZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2xpbmVhcicsICdoc3BsaW5lJ10sXG4gICAgICAgICAgICBkZmx0OiAnbGluZWFyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycyh7XG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgYXJyYXlPazogZmFsc2VcbiAgICAgICAgfSwge1xuICAgICAgICAgICAga2V5czogWydjb3VudCcsICdwcm9iYWJpbGl0eSddLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pXG4gICAgfVxuKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ3BhcmNhdHMnLCB0cmFjZTogdHJ1ZSwgZWRpdFR5cGU6ICdjYWxjJ30pLFxuXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBwbG90QXR0cnMuaG92ZXJpbmZvLCB7XG4gICAgICAgIGZsYWdzOiBbJ2NvdW50JywgJ3Byb2JhYmlsaXR5J10sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIGFycmF5T2s6IGZhbHNlXG4gICAgfSksXG4gICAgaG92ZXJvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydjYXRlZ29yeScsICdjb2xvcicsICdkaW1lbnNpb24nXSxcbiAgICAgICAgZGZsdDogJ2NhdGVnb3J5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgYXJyYXlPazogZmFsc2VcbiAgICB9LCB7XG4gICAgICAgIGtleXM6IFtcbiAgICAgICAgICAgICdjb3VudCcsICdwcm9iYWJpbGl0eScsICdjYXRlZ29yeScsXG4gICAgICAgICAgICAnY2F0ZWdvcnljb3VudCcsICdjb2xvcmNvdW50JywgJ2JhbmRjb2xvcmNvdW50J1xuICAgICAgICBdLFxuICAgICAgICBcbiAgICB9KSxcblxuICAgIGFycmFuZ2VtZW50OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3BlcnBlbmRpY3VsYXInLCAnZnJlZWZvcm0nLCAnZml4ZWQnXSxcbiAgICAgICAgZGZsdDogJ3BlcnBlbmRpY3VsYXInLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBidW5kbGVjb2xvcnM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzb3J0cGF0aHM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnZm9yd2FyZCcsICdiYWNrd2FyZCddLFxuICAgICAgICBkZmx0OiAnZm9yd2FyZCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGxhYmVsZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICB0aWNrZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBkaW1lbnNpb25zOiB7XG4gICAgICAgIF9pc0xpbmtlZFRvQXJyYXk6ICdkaW1lbnNpb24nLFxuICAgICAgICBsYWJlbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgY2F0ZWdvcnlvcmRlcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAgICAgJ3RyYWNlJywgJ2NhdGVnb3J5IGFzY2VuZGluZycsICdjYXRlZ29yeSBkZXNjZW5kaW5nJywgJ2FycmF5J1xuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGRmbHQ6ICd0cmFjZScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgY2F0ZWdvcnlhcnJheToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHRpY2t0ZXh0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdmFsdWVzOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IFtdLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBkaXNwbGF5aW5kZXg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSxcblxuICAgIGxpbmU6IGxpbmUsXG4gICAgY291bnRzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgLy8gSGlkZSB1bnN1cHBvcnRlZCB0b3AtbGV2ZWwgcHJvcGVydGllcyBmcm9tIHBsb3Qtc2NoZW1hXG4gICAgY3VzdG9tZGF0YTogdW5kZWZpbmVkLFxuICAgIGhvdmVybGFiZWw6IHVuZGVmaW5lZCxcbiAgICBpZHM6IHVuZGVmaW5lZCxcbiAgICBsZWdlbmRncm91cDogdW5kZWZpbmVkLFxuICAgIG9wYWNpdHk6IHVuZGVmaW5lZCxcbiAgICBzZWxlY3RlZHBvaW50czogdW5kZWZpbmVkLFxuICAgIHNob3dsZWdlbmQ6IHVuZGVmaW5lZFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi8uLi9wbG90cy9kb21haW5cIjo3OTIsXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTN9XSwxMDY4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGdldE1vZHVsZUNhbGNEYXRhID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRNb2R1bGVDYWxjRGF0YTtcbnZhciBwYXJjYXRzUGxvdCA9IF9kZXJlcV8oJy4vcGxvdCcpO1xuXG52YXIgUEFSQ0FUUyA9ICdwYXJjYXRzJztcbmV4cG9ydHMubmFtZSA9IFBBUkNBVFM7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uKGdkLCB0cmFjZXMsIHRyYW5zaXRpb25PcHRzLCBtYWtlT25Db21wbGV0ZUNhbGxiYWNrKSB7XG4gICAgdmFyIGNkTW9kdWxlQW5kT3RoZXJzID0gZ2V0TW9kdWxlQ2FsY0RhdGEoZ2QuY2FsY2RhdGEsIFBBUkNBVFMpO1xuXG4gICAgaWYoY2RNb2R1bGVBbmRPdGhlcnMubGVuZ3RoKSB7XG4gICAgICAgIHZhciBjYWxjRGF0YSA9IGNkTW9kdWxlQW5kT3RoZXJzWzBdO1xuICAgICAgICBwYXJjYXRzUGxvdChnZCwgY2FsY0RhdGEsIHRyYW5zaXRpb25PcHRzLCBtYWtlT25Db21wbGV0ZUNhbGxiYWNrKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLmNsZWFuID0gZnVuY3Rpb24obmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxEYXRhLCBvbGRGdWxsTGF5b3V0KSB7XG4gICAgdmFyIGhhZFRhYmxlID0gKG9sZEZ1bGxMYXlvdXQuX2hhcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXMoJ3BhcmNhdHMnKSk7XG4gICAgdmFyIGhhc1RhYmxlID0gKG5ld0Z1bGxMYXlvdXQuX2hhcyAmJiBuZXdGdWxsTGF5b3V0Ll9oYXMoJ3BhcmNhdHMnKSk7XG5cbiAgICBpZihoYWRUYWJsZSAmJiAhaGFzVGFibGUpIHtcbiAgICAgICAgb2xkRnVsbExheW91dC5fcGFwZXJkaXYuc2VsZWN0QWxsKCcucGFyY2F0cycpLnJlbW92ZSgpO1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvZ2V0X2RhdGFcIjo4MDIsXCIuL3Bsb3RcIjoxMDczfV0sMTA2OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbi8vIFJlcXVpcmVtZW50c1xuLy8gPT09PT09PT09PT09XG52YXIgd3JhcCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9ndXAnKS53cmFwO1xudmFyIGhhc0NvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvaGVscGVycycpLmhhc0NvbG9yc2NhbGU7XG52YXIgY29sb3JzY2FsZUNhbGMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsYycpO1xudmFyIGZpbHRlclVuaXF1ZSA9IF9kZXJlcV8oJy4uLy4uL2xpYi9maWx0ZXJfdW5pcXVlLmpzJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG4vKipcbiAqIENyZWF0ZSBhIHdyYXBwZWQgUGFyY2F0c01vZGVsIG9iamVjdCBmcm9tIHRyYWNlXG4gKlxuICogTm90ZTogdHJhY2UgZGVmYXVsdHMgaGF2ZSBhbHJlYWR5IGJlZW4gYXBwbGllZFxuICogQHBhcmFtIHtPYmplY3R9IGdkXG4gKiBAcGFyYW0ge09iamVjdH0gdHJhY2VcbiAqIEByZXR1cm4ge0FycmF5LjxQYXJjYXRzTW9kZWw+fVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIHZpc2libGVEaW1zID0gTGliLmZpbHRlclZpc2libGUodHJhY2UuZGltZW5zaW9ucyk7XG5cbiAgICBpZih2aXNpYmxlRGltcy5sZW5ndGggPT09IDApIHJldHVybiBbXTtcblxuICAgIHZhciB1bmlxdWVJbmZvRGltcyA9IHZpc2libGVEaW1zLm1hcChmdW5jdGlvbihkaW0pIHtcbiAgICAgICAgdmFyIGNhdGVnb3J5VmFsdWVzO1xuICAgICAgICBpZihkaW0uY2F0ZWdvcnlvcmRlciA9PT0gJ3RyYWNlJykge1xuICAgICAgICAgICAgLy8gVXNlIG9yZGVyIG9mIGZpcnN0IG9jY3VycmVuY2UgaW4gdHJhY2VcbiAgICAgICAgICAgIGNhdGVnb3J5VmFsdWVzID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIGlmKGRpbS5jYXRlZ29yeW9yZGVyID09PSAnYXJyYXknKSB7XG4gICAgICAgICAgICAvLyBVc2UgY2F0ZWdvcmllcyBzcGVjaWZpZWQgaW4gYGNhdGVnb3J5YXJyYXlgIGZpcnN0LFxuICAgICAgICAgICAgLy8gdGhlbiBhZGQgZXh0cmEgdG8gdGhlIGVuZCBpbiB0cmFjZSBvcmRlclxuICAgICAgICAgICAgY2F0ZWdvcnlWYWx1ZXMgPSBkaW0uY2F0ZWdvcnlhcnJheTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEdldCBhbGwgY2F0ZWdvcmllcyB1cCBmcm9udCBzbyB3ZSBjYW4gb3JkZXIgdGhlbVxuICAgICAgICAgICAgLy8gU2hvdWxkIHdlIGNoZWNrIGZvciBudW1iZXJzIGFzIHNvcnQgbnVtZXJpY2FsbHk/XG4gICAgICAgICAgICBjYXRlZ29yeVZhbHVlcyA9IGZpbHRlclVuaXF1ZShkaW0udmFsdWVzKS5zb3J0KCk7XG4gICAgICAgICAgICBpZihkaW0uY2F0ZWdvcnlvcmRlciA9PT0gJ2NhdGVnb3J5IGRlc2NlbmRpbmcnKSB7XG4gICAgICAgICAgICAgICAgY2F0ZWdvcnlWYWx1ZXMgPSBjYXRlZ29yeVZhbHVlcy5yZXZlcnNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGdldFVuaXF1ZUluZm8oZGltLnZhbHVlcywgY2F0ZWdvcnlWYWx1ZXMpO1xuICAgIH0pO1xuXG4gICAgdmFyIGNvdW50cyxcbiAgICAgICAgY291bnQsXG4gICAgICAgIHRvdGFsQ291bnQ7XG4gICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkodHJhY2UuY291bnRzKSkge1xuICAgICAgICBjb3VudHMgPSB0cmFjZS5jb3VudHM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY291bnRzID0gW3RyYWNlLmNvdW50c107XG4gICAgfVxuXG4gICAgdmFsaWRhdGVEaW1lbnNpb25EaXNwbGF5SW5kcyh2aXNpYmxlRGltcyk7XG5cbiAgICB2aXNpYmxlRGltcy5mb3JFYWNoKGZ1bmN0aW9uKGRpbSwgZGltSW5kKSB7XG4gICAgICAgIHZhbGlkYXRlQ2F0ZWdvcnlQcm9wZXJ0aWVzKGRpbSwgdW5pcXVlSW5mb0RpbXNbZGltSW5kXSk7XG4gICAgfSk7XG5cbiAgICAvLyBIYW5kbGUgcGF0aCBjb2xvcnNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS1cbiAgICB2YXIgbGluZSA9IHRyYWNlLmxpbmU7XG4gICAgdmFyIG1hcmtlckNvbG9yc2NhbGU7XG5cbiAgICAvLyBQcm9jZXNzIGNvbG9yc2NhbGVcbiAgICBpZihsaW5lKSB7XG4gICAgICAgIGlmKGhhc0NvbG9yc2NhbGUodHJhY2UsICdsaW5lJykpIHtcbiAgICAgICAgICAgIGNvbG9yc2NhbGVDYWxjKGdkLCB0cmFjZSwge1xuICAgICAgICAgICAgICAgIHZhbHM6IHRyYWNlLmxpbmUuY29sb3IsXG4gICAgICAgICAgICAgICAgY29udGFpbmVyU3RyOiAnbGluZScsXG4gICAgICAgICAgICAgICAgY0xldHRlcjogJ2MnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBtYXJrZXJDb2xvcnNjYWxlID0gRHJhd2luZy50cnlDb2xvcnNjYWxlKGxpbmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1hcmtlckNvbG9yc2NhbGUgPSBMaWIuaWRlbnRpdHk7XG4gICAgfVxuXG4gICAgLy8gQnVpbGQgY29sb3IgZ2VuZXJhdGlvbiBmdW5jdGlvblxuICAgIGZ1bmN0aW9uIGdldE1hcmtlckNvbG9ySW5mbyhpbmRleCkge1xuICAgICAgICB2YXIgdmFsdWU7XG4gICAgICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGxpbmUuY29sb3IpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGxpbmUuY29sb3JbaW5kZXggJSBsaW5lLmNvbG9yLmxlbmd0aF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGxpbmUuY29sb3I7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge2NvbG9yOiBtYXJrZXJDb2xvcnNjYWxlKHZhbHVlKSwgcmF3Q29sb3I6IHZhbHVlfTtcbiAgICB9XG5cbiAgICAvLyBOdW1iZXIgb2YgdmFsdWVzIGFuZCBjb3VudHNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICB2YXIgbnVtVmFsdWVzID0gdmlzaWJsZURpbXNbMF0udmFsdWVzLmxlbmd0aDtcblxuICAgIC8vIEJ1aWxkIHBhdGggaW5mb1xuICAgIC8vIC0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIE1hcHBpbmcgZnJvbSBjYXRlZ29yeSBpbmRzIHRvIFBhdGhNb2RlbCBvYmplY3RzXG4gICAgdmFyIHBhdGhNb2RlbHMgPSB7fTtcblxuICAgIC8vIENhdGVnb3J5IGluZHMgYXJyYXkgZm9yIGVhY2ggZGltZW5zaW9uXG4gICAgdmFyIGNhdGVnb3J5SW5kc0RpbXMgPSB1bmlxdWVJbmZvRGltcy5tYXAoZnVuY3Rpb24oZGkpIHtyZXR1cm4gZGkuaW5kczt9KTtcblxuICAgIC8vIEluaXRpYWxpemUgdG90YWwgY291bnRcbiAgICB0b3RhbENvdW50ID0gMDtcbiAgICB2YXIgdmFsdWVJbmQ7XG4gICAgdmFyIGQ7XG5cbiAgICBmb3IodmFsdWVJbmQgPSAwOyB2YWx1ZUluZCA8IG51bVZhbHVlczsgdmFsdWVJbmQrKykge1xuICAgICAgICAvLyBDYXRlZ29yeSBpbmRzIGZvciB0aGlzIGlucHV0IHZhbHVlIGFjcm9zcyBkaW1lbnNpb25zXG4gICAgICAgIHZhciBjYXRlZ29yeUluZHNQYXRoID0gW107XG4gICAgICAgIGZvcihkID0gMDsgZCA8IGNhdGVnb3J5SW5kc0RpbXMubGVuZ3RoOyBkKyspIHtcbiAgICAgICAgICAgIGNhdGVnb3J5SW5kc1BhdGgucHVzaChjYXRlZ29yeUluZHNEaW1zW2RdW3ZhbHVlSW5kXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb3VudFxuICAgICAgICBjb3VudCA9IGNvdW50c1t2YWx1ZUluZCAlIGNvdW50cy5sZW5ndGhdO1xuXG4gICAgICAgIC8vIFVwZGF0ZSB0b3RhbCBjb3VudFxuICAgICAgICB0b3RhbENvdW50ICs9IGNvdW50O1xuXG4gICAgICAgIC8vIFBhdGggY29sb3JcbiAgICAgICAgdmFyIHBhdGhDb2xvckluZm8gPSBnZXRNYXJrZXJDb2xvckluZm8odmFsdWVJbmQpO1xuXG4gICAgICAgIC8vIHBhdGgga2V5XG4gICAgICAgIHZhciBwYXRoS2V5ID0gY2F0ZWdvcnlJbmRzUGF0aCArICctJyArIHBhdGhDb2xvckluZm8ucmF3Q29sb3I7XG5cbiAgICAgICAgLy8gQ3JlYXRlIC8gVXBkYXRlIFBhdGhNb2RlbFxuICAgICAgICBpZihwYXRoTW9kZWxzW3BhdGhLZXldID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHBhdGhNb2RlbHNbcGF0aEtleV0gPSBjcmVhdGVQYXRoTW9kZWwoY2F0ZWdvcnlJbmRzUGF0aCxcbiAgICAgICAgICAgICAgICBwYXRoQ29sb3JJbmZvLmNvbG9yLFxuICAgICAgICAgICAgICAgIHBhdGhDb2xvckluZm8ucmF3Q29sb3IpO1xuICAgICAgICB9XG4gICAgICAgIHVwZGF0ZVBhdGhNb2RlbChwYXRoTW9kZWxzW3BhdGhLZXldLCB2YWx1ZUluZCwgY291bnQpO1xuICAgIH1cblxuICAgIHZhciBkaW1lbnNpb25Nb2RlbHMgPSB2aXNpYmxlRGltcy5tYXAoZnVuY3Rpb24oZGksIGkpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZURpbWVuc2lvbk1vZGVsKGksIGRpLl9pbmRleCwgZGkuX2Rpc3BsYXlpbmRleCwgZGkubGFiZWwsIHRvdGFsQ291bnQpO1xuICAgIH0pO1xuXG5cbiAgICBmb3IodmFsdWVJbmQgPSAwOyB2YWx1ZUluZCA8IG51bVZhbHVlczsgdmFsdWVJbmQrKykge1xuICAgICAgICBjb3VudCA9IGNvdW50c1t2YWx1ZUluZCAlIGNvdW50cy5sZW5ndGhdO1xuXG4gICAgICAgIGZvcihkID0gMDsgZCA8IGRpbWVuc2lvbk1vZGVscy5sZW5ndGg7IGQrKykge1xuICAgICAgICAgICAgdmFyIGNvbnRhaW5lckluZCA9IGRpbWVuc2lvbk1vZGVsc1tkXS5jb250YWluZXJJbmQ7XG4gICAgICAgICAgICB2YXIgY2F0SW5kID0gdW5pcXVlSW5mb0RpbXNbZF0uaW5kc1t2YWx1ZUluZF07XG4gICAgICAgICAgICB2YXIgY2F0cyA9IGRpbWVuc2lvbk1vZGVsc1tkXS5jYXRlZ29yaWVzO1xuXG4gICAgICAgICAgICBpZihjYXRzW2NhdEluZF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHZhciBjYXRWYWx1ZSA9IHRyYWNlLmRpbWVuc2lvbnNbY29udGFpbmVySW5kXS5fY2F0ZWdvcnlhcnJheVtjYXRJbmRdO1xuICAgICAgICAgICAgICAgIHZhciBjYXRMYWJlbCA9IHRyYWNlLmRpbWVuc2lvbnNbY29udGFpbmVySW5kXS5fdGlja3RleHRbY2F0SW5kXTtcbiAgICAgICAgICAgICAgICBjYXRzW2NhdEluZF0gPSBjcmVhdGVDYXRlZ29yeU1vZGVsKGQsIGNhdEluZCwgY2F0VmFsdWUsIGNhdExhYmVsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdXBkYXRlQ2F0ZWdvcnlNb2RlbChjYXRzW2NhdEluZF0sIHZhbHVlSW5kLCBjb3VudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDb21wdXRlIHVuaXF1ZVxuICAgIHJldHVybiB3cmFwKGNyZWF0ZVBhcmNhdHNNb2RlbChkaW1lbnNpb25Nb2RlbHMsIHBhdGhNb2RlbHMsIHRvdGFsQ291bnQpKTtcbn07XG5cbi8vIE1vZGVsc1xuLy8gPT09PT09XG5cbi8vIFBhcmNhdHMgTW9kZWxcbi8vIC0tLS0tLS0tLS0tLS1cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUGFyY2F0c01vZGVsXG4gKiAgT2JqZWN0IGNvbnRhaW5pbmcgY2FsY3VsYXRlZCBpbmZvcm1hdGlvbiBhYm91dCBhIHBhcmNhdHMgdHJhY2VcbiAqXG4gKiBAcHJvcGVydHkge0FycmF5LjxEaW1lbnNpb25Nb2RlbD59IGRpbWVuc2lvbnNcbiAqICBBcnJheSBvZiBkaW1lbnNpb24gbW9kZWxzXG4gKiBAcHJvcGVydHkge09iamVjdC48c3RyaW5nLFBhdGhNb2RlbD59IHBhdGhzXG4gKiAgRGljdGlvbmFyeSBmcm9tIGNhdGVnb3J5IGluZHMgc3RyaW5nIChlLmcuIFwiMSwyLDEsMVwiKSB0byBwYXRoIG1vZGVsXG4gKiBAcHJvcGVydHkge051bWJlcn0gbWF4Q2F0c1xuICogIFRoZSBtYXhpbXVtIG51bWJlciBvZiBjYXRlZ29yaWVzIG9mIGFueSBkaW1lbnNpb24gaW4gdGhlIGRpYWdyYW1cbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBjb3VudFxuICogIFRvdGFsIG51bWJlciBvZiBpbnB1dCB2YWx1ZXNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSB0cmFjZVxuICovXG5cbi8qKlxuICogQ3JlYXRlIGFuZCBuZXcgUGFyY2F0c01vZGVsIG9iamVjdFxuICogQHBhcmFtIHtBcnJheS48RGltZW5zaW9uTW9kZWw+fSBkaW1lbnNpb25zXG4gKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLFBhdGhNb2RlbD59IHBhdGhzXG4gKiBAcGFyYW0ge051bWJlcn0gY291bnRcbiAqIEByZXR1cm4ge1BhcmNhdHNNb2RlbH1cbiAqL1xuZnVuY3Rpb24gY3JlYXRlUGFyY2F0c01vZGVsKGRpbWVuc2lvbnMsIHBhdGhzLCBjb3VudCkge1xuICAgIHZhciBtYXhDYXRzID0gZGltZW5zaW9uc1xuICAgICAgICAubWFwKGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5jYXRlZ29yaWVzLmxlbmd0aDt9KVxuICAgICAgICAucmVkdWNlKGZ1bmN0aW9uKHYxLCB2Mikge3JldHVybiBNYXRoLm1heCh2MSwgdjIpO30pO1xuICAgIHJldHVybiB7ZGltZW5zaW9uczogZGltZW5zaW9ucywgcGF0aHM6IHBhdGhzLCB0cmFjZTogdW5kZWZpbmVkLCBtYXhDYXRzOiBtYXhDYXRzLCBjb3VudDogY291bnR9O1xufVxuXG4vLyBEaW1lbnNpb24gTW9kZWxcbi8vIC0tLS0tLS0tLS0tLS0tLVxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEaW1lbnNpb25Nb2RlbFxuICogIE9iamVjdCBjb250YWluaW5nIGNhbGN1bGF0ZWQgaW5mb3JtYXRpb24gYWJvdXQgYSBzaW5nbGUgZGltZW5zaW9uXG4gKlxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGRpbWVuc2lvbkluZFxuICogIFRoZSBpbmRleCBvZiB0aGlzIGRpbWVuc2lvbiBhbW9uZyB0aGUgKnZpc2libGUqIGRpbWVuc2lvbnNcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBjb250YWluZXJJbmRcbiAqICBUaGUgaW5kZXggb2YgdGhpcyBkaW1lbnNpb24gaW4gdGhlIG9yaWdpbmFsIGRpbWVuc2lvbnMgY29udGFpbmVyLFxuICogIGlycmVzcGVjdGl2ZSBvZiBkaW1lbnNpb24gdmlzaWJpbGl0eVxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGRpc3BsYXlJbmRcbiAqICBUaGUgZGlzcGxheSBpbmRleCBvZiB0aGlzIGRpbWVuc2lvbiAod2hlcmUgMCBpcyB0aGUgbGVmdCBtb3N0IGRpbWVuc2lvbilcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBkaW1lbnNpb25MYWJlbFxuICogIFRoZSBsYWJlbCBvZiB0aGlzIGRpbWVuc2lvblxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGNvdW50XG4gKiAgVG90YWwgbnVtYmVyIG9mIGlucHV0IHZhbHVlc1xuICogQHByb3BlcnR5IHtBcnJheS48Q2F0ZWdvcnlNb2RlbD59IGNhdGVnb3JpZXNcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfG51bGx9IGRyYWdYXG4gKiAgVGhlIHggcG9zaXRpb24gb2YgZGltZW5zaW9uIHRoYXQgaXMgY3VycmVudGx5IGJlaW5nIGRyYWdnZWQuIG51bGwgaWYgbm90IGJlaW5nIGRyYWdnZWRcbiAqL1xuXG4vKipcbiAqIENyZWF0ZSBhbmQgbmV3IERpbWVuc2lvbk1vZGVsIG9iamVjdCB3aXRoIGFuIGVtcHR5IGNhdGVnb3JpZXMgYXJyYXlcbiAqIEBwYXJhbSB7TnVtYmVyfSBkaW1lbnNpb25JbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb250YWluZXJJbmRcbiAqIEBwYXJhbSB7TnVtYmVyfSBkaXNwbGF5SW5kXG4gKiBAcGFyYW0ge1N0cmluZ30gZGltZW5zaW9uTGFiZWxcbiAqIEBwYXJhbSB7TnVtYmVyfSBjb3VudFxuICogIFRvdGFsIG51bWJlciBvZiBpbnB1dCB2YWx1ZXNcbiAqIEByZXR1cm4ge0RpbWVuc2lvbk1vZGVsfVxuICovXG5mdW5jdGlvbiBjcmVhdGVEaW1lbnNpb25Nb2RlbChkaW1lbnNpb25JbmQsIGNvbnRhaW5lckluZCwgZGlzcGxheUluZCwgZGltZW5zaW9uTGFiZWwsIGNvdW50KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGltZW5zaW9uSW5kOiBkaW1lbnNpb25JbmQsXG4gICAgICAgIGNvbnRhaW5lckluZDogY29udGFpbmVySW5kLFxuICAgICAgICBkaXNwbGF5SW5kOiBkaXNwbGF5SW5kLFxuICAgICAgICBkaW1lbnNpb25MYWJlbDogZGltZW5zaW9uTGFiZWwsXG4gICAgICAgIGNvdW50OiBjb3VudCxcbiAgICAgICAgY2F0ZWdvcmllczogW10sXG4gICAgICAgIGRyYWdYOiBudWxsXG4gICAgfTtcbn1cblxuLy8gQ2F0ZWdvcnkgTW9kZWxcbi8vIC0tLS0tLS0tLS0tLS0tXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IENhdGVnb3J5TW9kZWxcbiAqICBPYmplY3QgY29udGFpbmluZyBjYWxjdWxhdGVkIGluZm9ybWF0aW9uIGFib3V0IGEgc2luZ2xlIGNhdGVnb3J5LlxuICpcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBkaW1lbnNpb25JbmRcbiAqICBUaGUgaW5kZXggb2YgdGhpcyBjYXRlZ29yaWVzIGRpbWVuc2lvblxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGNhdGVnb3J5SW5kXG4gKiAgVGhlIGluZGV4IG9mIHRoaXMgY2F0ZWdvcnlcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBkaXNwbGF5SW5kXG4gKiAgVGhlIGRpc3BsYXkgaW5kZXggb2YgdGhpcyBjYXRlZ29yeSAod2hlcmUgMCBpcyB0aGUgdG9wbW9zdCBjYXRlZ29yeSlcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBjYXRlZ29yeUxhYmVsXG4gKiAgVGhlIG5hbWUgb2YgdGhpcyBjYXRlZ29yeVxuICogQHByb3BlcnR5IGNhdGVnb3J5VmFsdWU6IFJhdyB2YWx1ZSBvZiB0aGUgY2F0ZWdvcnlcbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IHZhbHVlSW5kc1xuICogIEFycmF5IG9mIGluZGljZXMgKGludG8gdGhlIG9yaWdpbmFsIHZhbHVlIGFycmF5KSBvZiBhbGwgc2FtcGxlcyBpbiB0aGlzIGNhdGVnb3J5XG4gKiBAcHJvcGVydHkge051bWJlcn0gY291bnRcbiAqICBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIGZyb20gdGhlIG9yaWdpbmFsIGFycmF5IGluIHRoaXMgcGF0aFxuICogQHByb3BlcnR5IHtOdW1iZXJ8bnVsbH0gZHJhZ1lcbiAqICBUaGUgeSBwb3NpdGlvbiBvZiBjYXRlZ29yeSB0aGF0IGlzIGN1cnJlbnRseSBiZWluZyBkcmFnZ2VkLiBudWxsIGlmIG5vdCBiZWluZyBkcmFnZ2VkXG4gKi9cblxuLyoqXG4gKiBDcmVhdGUgYW5kIHJldHVybiBhIG5ldyBDYXRlZ29yeU1vZGVsIG9iamVjdFxuICogQHBhcmFtIHtOdW1iZXJ9IGRpbWVuc2lvbkluZFxuICogQHBhcmFtIHtOdW1iZXJ9IGNhdGVnb3J5SW5kXG4gKiAgVGhlIGRpc3BsYXkgaW5kZXggb2YgdGhpcyBjYXRlZ29yeSAod2hlcmUgMCBpcyB0aGUgdG9wbW9zdCBjYXRlZ29yeSlcbiAqIEBwYXJhbSB7U3RyaW5nfSBjYXRlZ29yeVZhbHVlXG4gKiBAcGFyYW0ge1N0cmluZ30gY2F0ZWdvcnlMYWJlbFxuICogQHJldHVybiB7Q2F0ZWdvcnlNb2RlbH1cbiAqL1xuZnVuY3Rpb24gY3JlYXRlQ2F0ZWdvcnlNb2RlbChkaW1lbnNpb25JbmQsIGNhdGVnb3J5SW5kLCBjYXRlZ29yeVZhbHVlLCBjYXRlZ29yeUxhYmVsKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGltZW5zaW9uSW5kOiBkaW1lbnNpb25JbmQsXG4gICAgICAgIGNhdGVnb3J5SW5kOiBjYXRlZ29yeUluZCxcbiAgICAgICAgY2F0ZWdvcnlWYWx1ZTogY2F0ZWdvcnlWYWx1ZSxcbiAgICAgICAgZGlzcGxheUluZDogY2F0ZWdvcnlJbmQsXG4gICAgICAgIGNhdGVnb3J5TGFiZWw6IGNhdGVnb3J5TGFiZWwsXG4gICAgICAgIHZhbHVlSW5kczogW10sXG4gICAgICAgIGNvdW50OiAwLFxuICAgICAgICBkcmFnWTogbnVsbFxuICAgIH07XG59XG5cbi8qKlxuICogVXBkYXRlIGEgQ2F0ZWdvcnlNb2RlbCBvYmplY3Qgd2l0aCBhIG5ldyB2YWx1ZSBpbmRleFxuICogTm90ZTogVGhlIGNhbGxpbmcgcGFyYW1ldGVyIGlzIG1vZGlmaWVkIGluIHBsYWNlLlxuICpcbiAqIEBwYXJhbSB7Q2F0ZWdvcnlNb2RlbH0gY2F0ZWdvcnlNb2RlbFxuICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlSW5kXG4gKiBAcGFyYW0ge051bWJlcn0gY291bnRcbiAqL1xuZnVuY3Rpb24gdXBkYXRlQ2F0ZWdvcnlNb2RlbChjYXRlZ29yeU1vZGVsLCB2YWx1ZUluZCwgY291bnQpIHtcbiAgICBjYXRlZ29yeU1vZGVsLnZhbHVlSW5kcy5wdXNoKHZhbHVlSW5kKTtcbiAgICBjYXRlZ29yeU1vZGVsLmNvdW50ICs9IGNvdW50O1xufVxuXG5cbi8vIFBhdGggTW9kZWxcbi8vIC0tLS0tLS0tLS1cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUGF0aE1vZGVsXG4gKiAgT2JqZWN0IGNvbnRhaW5pbmcgY2FsY3VsYXRlZCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc2FtcGxlcyBpbiBhIHBhdGguXG4gKlxuICogQHByb3BlcnR5IHtBcnJheX0gY2F0ZWdvcnlJbmRzXG4gKiAgQXJyYXkgb2YgY2F0ZWdvcnkgaW5kaWNlcyBmb3IgZWFjaCBkaW1lbnNpb24gKGxlbmd0aCBgbnVtRGltZW5zaW9uc2ApXG4gKiBAcGFyYW0ge1N0cmluZ30gcGF0aENvbG9yXG4gKiAgQ29sb3Igb2YgdGhpcyBwYXRoLiAoTm90ZTogQW55IGNvbG9yc2NhbGluZyBoYXMgYWxyZWFkeSB0YWtlbiBwbGFjZSlcbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IHZhbHVlSW5kc1xuICogIEFycmF5IG9mIGluZGljZXMgKGludG8gdGhlIG9yaWdpbmFsIHZhbHVlIGFycmF5KSBvZiBhbGwgc2FtcGxlcyBpbiB0aGlzIHBhdGhcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBjb3VudFxuICogIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgZnJvbSB0aGUgb3JpZ2luYWwgYXJyYXkgaW4gdGhpcyBwYXRoXG4gKiBAcHJvcGVydHkge1N0cmluZ30gY29sb3JcbiAqICBUaGUgcGF0aCdzIGNvbG9yIChhc3MgQ1NTIGNvbG9yIHN0cmluZylcbiAqIEBwcm9wZXJ0eSByYXdDb2xvclxuICogIFRoZSByYXcgY29sb3IgdmFsdWUgc3BlY2lmaWVkIGJ5IHRoZSB1c2VyLiBNYXkgYmUgYSBDU1MgY29sb3Igc3RyaW5nIG9yIGEgTnVtYmVyXG4gKi9cblxuLyoqXG4gKiBDcmVhdGUgYW5kIHJldHVybiBhIG5ldyBQYXRoTW9kZWwgb2JqZWN0XG4gKiBAcGFyYW0ge0FycmF5fSBjYXRlZ29yeUluZHNcbiAqIEBwYXJhbSBjb2xvclxuICogQHBhcmFtIHJhd0NvbG9yXG4gKiBAcmV0dXJuIHtQYXRoTW9kZWx9XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVBhdGhNb2RlbChjYXRlZ29yeUluZHMsIGNvbG9yLCByYXdDb2xvcikge1xuICAgIHJldHVybiB7XG4gICAgICAgIGNhdGVnb3J5SW5kczogY2F0ZWdvcnlJbmRzLFxuICAgICAgICBjb2xvcjogY29sb3IsXG4gICAgICAgIHJhd0NvbG9yOiByYXdDb2xvcixcbiAgICAgICAgdmFsdWVJbmRzOiBbXSxcbiAgICAgICAgY291bnQ6IDBcbiAgICB9O1xufVxuXG4vKipcbiAqIFVwZGF0ZSBhIFBhdGhNb2RlbCBvYmplY3Qgd2l0aCBhIG5ldyB2YWx1ZSBpbmRleFxuICogTm90ZTogVGhlIGNhbGxpbmcgcGFyYW1ldGVyIGlzIG1vZGlmaWVkIGluIHBsYWNlLlxuICpcbiAqIEBwYXJhbSB7UGF0aE1vZGVsfSBwYXRoTW9kZWxcbiAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZUluZFxuICogQHBhcmFtIHtOdW1iZXJ9IGNvdW50XG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVBhdGhNb2RlbChwYXRoTW9kZWwsIHZhbHVlSW5kLCBjb3VudCkge1xuICAgIHBhdGhNb2RlbC52YWx1ZUluZHMucHVzaCh2YWx1ZUluZCk7XG4gICAgcGF0aE1vZGVsLmNvdW50ICs9IGNvdW50O1xufVxuXG4vLyBVbmlxdWUgY2FsY3VsYXRpb25zXG4vLyA9PT09PT09PT09PT09PT09PT09XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFVuaXF1ZUluZm9cbiAqICBPYmplY3QgY29udGFpbmluZyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdW5pcXVlIHZhbHVlcyBvZiBhbiBpbnB1dCBhcnJheVxuICpcbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IHVuaXF1ZVZhbHVlc1xuICogIFRoZSB1bmlxdWUgdmFsdWVzIGluIHRoZSBpbnB1dCBhcnJheVxuICogQHByb3BlcnR5IHtBcnJheX0gdW5pcXVlQ291bnRzXG4gKiAgVGhlIG51bWJlciBvZiB0aW1lcyBlYWNoIGVudHJ5IGluIHVuaXF1ZVZhbHVlcyBvY2N1cnMgaW4gaW5wdXQgYXJyYXkuXG4gKiAgVGhpcyBoYXMgdGhlIHNhbWUgbGVuZ3RoIGFzIGB1bmlxdWVWYWx1ZXNgXG4gKiBAcHJvcGVydHkge0FycmF5fSBpbmRzXG4gKiAgSW5kaWNlcyBpbnRvIHVuaXF1ZVZhbHVlcyB0aGF0IHdvdWxkIHJlcHJvZHVjZSBvcmlnaW5hbCBpbnB1dCBhcnJheVxuICovXG5cbi8qKlxuICogQ29tcHV0ZSB1bmlxdWUgdmFsdWUgaW5mb3JtYXRpb24gZm9yIGFuIGFycmF5XG4gKlxuICogSU1QT1JUQU5UOiBOb3RlIHRoYXQgdmFsdWVzIGFyZSBjb25zaWRlcmVkIHVuaXF1ZVxuICogaWYgdGhlaXIgc3RyaW5nIHJlcHJlc2VudGF0aW9ucyBhcmUgdW5pcXVlLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlc1xuICogQHBhcmFtIHtBcnJheXx1bmRlZmluZWR9IHVuaXF1ZVZhbHVlc1xuICogIEFycmF5IG9mIGV4cGVjdGVkIHVuaXF1ZSB2YWx1ZXMuIFRoZSB1bmlxdWVWYWx1ZXMgcHJvcGVydHkgb2YgdGhlIHJlc3VsdGluZyBVbmlxdWVJbmZvIG9iamVjdCB3aWxsIGJlZ2luIHdpdGhcbiAqICB0aGVzZSBlbnRyaWVzLiBFbnRyaWVzIGFyZSBpbmNsdWRlZCBldmVuIGlmIHRoZXJlIGFyZSB6ZXJvIG9jY3VycmVuY2VzIGluIHRoZSB2YWx1ZXMgYXJyYXkuIEVudHJpZXMgZm91bmQgaW5cbiAqICB0aGUgdmFsdWVzIGFycmF5IHRoYXQgYXJlIG5vdCBwcmVzZW50IGluIHVuaXF1ZVZhbHVlcyB3aWxsIGJlIGluY2x1ZGVkIGF0IHRoZSBlbmQgb2YgdGhlIGFycmF5IGluIHRoZVxuICogIFVuaXF1ZUluZm8gb2JqZWN0LlxuICogQHJldHVybiB7VW5pcXVlSW5mb31cbiAqL1xuZnVuY3Rpb24gZ2V0VW5pcXVlSW5mbyh2YWx1ZXMsIHVuaXF1ZVZhbHVlcykge1xuICAgIC8vIEluaXRpYWxpemUgdW5pcXVlVmFsdWVzIGlmIG5vdCBzcGVjaWZpZWRcbiAgICBpZih1bmlxdWVWYWx1ZXMgPT09IHVuZGVmaW5lZCB8fCB1bmlxdWVWYWx1ZXMgPT09IG51bGwpIHtcbiAgICAgICAgdW5pcXVlVmFsdWVzID0gW107XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gU2hhbGxvdyBjb3B5IHNvIGFwcGVuZCBiZWxvdyBkb2Vzbid0IGFsdGVyIGlucHV0IGFycmF5XG4gICAgICAgIHVuaXF1ZVZhbHVlcyA9IHVuaXF1ZVZhbHVlcy5tYXAoZnVuY3Rpb24oZSkge3JldHVybiBlO30pO1xuICAgIH1cblxuICAgIC8vIEluaXRpYWxpemUgVmFyaWFibGVzXG4gICAgdmFyIHVuaXF1ZVZhbHVlQ291bnRzID0ge307XG4gICAgdmFyIHVuaXF1ZVZhbHVlSW5kcyA9IHt9O1xuICAgIHZhciBpbmRzID0gW107XG5cbiAgICAvLyBJbml0aWFsaXplIHVuaXF1ZVZhbHVlQ291bnRzIGFuZFxuICAgIHVuaXF1ZVZhbHVlcy5mb3JFYWNoKGZ1bmN0aW9uKHVuaXF1ZVZhbCwgdmFsSW5kKSB7XG4gICAgICAgIHVuaXF1ZVZhbHVlQ291bnRzW3VuaXF1ZVZhbF0gPSAwO1xuICAgICAgICB1bmlxdWVWYWx1ZUluZHNbdW5pcXVlVmFsXSA9IHZhbEluZDtcbiAgICB9KTtcblxuICAgIC8vIENvbXB1dGUgdGhlIG5lY2Vzc2FyeSB1bmlxdWUgaW5mbyBpbiBhIHNpbmdsZSBwYXNzXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgaXRlbSA9IHZhbHVlc1tpXTtcbiAgICAgICAgdmFyIGl0ZW1JbmQ7XG5cbiAgICAgICAgaWYodW5pcXVlVmFsdWVDb3VudHNbaXRlbV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gVGhpcyBpdGVtIGhhcyBhIHByZXZpb3VzbHkgdW5zZWVuIHZhbHVlXG4gICAgICAgICAgICB1bmlxdWVWYWx1ZUNvdW50c1tpdGVtXSA9IDE7XG4gICAgICAgICAgICBpdGVtSW5kID0gdW5pcXVlVmFsdWVzLnB1c2goaXRlbSkgLSAxO1xuICAgICAgICAgICAgdW5pcXVlVmFsdWVJbmRzW2l0ZW1dID0gaXRlbUluZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEluY3JlbWVudCBjb3VudCBmb3IgdGhpcyBpdGVtXG4gICAgICAgICAgICB1bmlxdWVWYWx1ZUNvdW50c1tpdGVtXSsrO1xuICAgICAgICAgICAgaXRlbUluZCA9IHVuaXF1ZVZhbHVlSW5kc1tpdGVtXTtcbiAgICAgICAgfVxuICAgICAgICBpbmRzLnB1c2goaXRlbUluZCk7XG4gICAgfVxuXG4gICAgLy8gQnVpbGQgVW5pcXVlSW5mb1xuICAgIHZhciB1bmlxdWVDb3VudHMgPSB1bmlxdWVWYWx1ZXMubWFwKGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHVuaXF1ZVZhbHVlQ291bnRzW3ZdOyB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIHVuaXF1ZVZhbHVlczogdW5pcXVlVmFsdWVzLFxuICAgICAgICB1bmlxdWVDb3VudHM6IHVuaXF1ZUNvdW50cyxcbiAgICAgICAgaW5kczogaW5kc1xuICAgIH07XG59XG5cblxuLyoqXG4gKiBWYWxpZGF0ZSB0aGUgcmVxdWVzdGVkIGRpc3BsYXkgb3JkZXIgZm9yIHRoZSBkaW1lbnNpb25zLlxuICogSWYgdGhlIGRpc3BsYXkgb3JkZXIgaXMgYSBwZXJtdXRhdGlvbiBvZiAwIHRocm91Z2ggZGltZW5zaW9ucy5sZW5ndGggLSAxLCBsaW5rIHRvIF9kaXNwbGF5aW5kZXhcbiAqIE90aGVyd2lzZSwgcmVwbGFjZSB0aGUgZGlzcGxheSBvcmRlciB3aXRoIHRoZSBkaW1lbnNpb24gb3JkZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSB0cmFjZVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZURpbWVuc2lvbkRpc3BsYXlJbmRzKHZpc2libGVEaW1zKSB7XG4gICAgdmFyIGRpc3BsYXlJbmRzID0gdmlzaWJsZURpbXMubWFwKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQuZGlzcGxheWluZGV4OyB9KTtcbiAgICB2YXIgaTtcblxuICAgIGlmKGlzUmFuZ2VQZXJtdXRhdGlvbihkaXNwbGF5SW5kcykpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgdmlzaWJsZURpbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZpc2libGVEaW1zW2ldLl9kaXNwbGF5aW5kZXggPSB2aXNpYmxlRGltc1tpXS5kaXNwbGF5aW5kZXg7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCB2aXNpYmxlRGltcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmlzaWJsZURpbXNbaV0uX2Rpc3BsYXlpbmRleCA9IGk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cblxuLyoqXG4gKiBVcGRhdGUgY2F0ZWdvcnkgcHJvcGVydGllcyBiYXNlZCBvbiB0aGUgdW5pcXVlIHZhbHVlcyBmb3VuZCBmb3IgdGhpcyBkaW1lbnNpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBkaW1cbiAqIEBwYXJhbSB7VW5pcXVlSW5mb30gdW5pcXVlSW5mb0RpbVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUNhdGVnb3J5UHJvcGVydGllcyhkaW0sIHVuaXF1ZUluZm9EaW0pIHtcbiAgICAvLyBVcGRhdGUgY2F0ZWdvcnlhcnJheVxuICAgIGRpbS5fY2F0ZWdvcnlhcnJheSA9IHVuaXF1ZUluZm9EaW0udW5pcXVlVmFsdWVzO1xuXG4gICAgLy8gSGFuZGxlIHRpY2t0ZXh0XG4gICAgaWYoZGltLnRpY2t0ZXh0ID09PSBudWxsIHx8IGRpbS50aWNrdGV4dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGRpbS5fdGlja3RleHQgPSBbXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBTaGFsbG93IGNvcHkgdG8gYXZvaWQgbW9kaWZ5aW5nIGlucHV0IGFycmF5XG4gICAgICAgIGRpbS5fdGlja3RleHQgPSBkaW0udGlja3RleHQuc2xpY2UoKTtcbiAgICB9XG5cbiAgICAvLyBFeHRlbmQgdGlja3RleHQgd2l0aCBlbGVtZW50cyBmcm9tIHVuaXF1ZUluZm9EaW0udW5pcXVlVmFsdWVzXG4gICAgZm9yKHZhciBpID0gZGltLl90aWNrdGV4dC5sZW5ndGg7IGkgPCB1bmlxdWVJbmZvRGltLnVuaXF1ZVZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBkaW0uX3RpY2t0ZXh0LnB1c2godW5pcXVlSW5mb0RpbS51bmlxdWVWYWx1ZXNbaV0pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciBhbiBhcnJheSBjb250YWlucyBhIHBlcm11dGF0aW9uIG9mIHRoZSBpbnRlZ2VycyBmcm9tIDAgdG8gdGhlIGFycmF5J3MgbGVuZ3RoIC0gMVxuICogQHBhcmFtIHtBcnJheX0gaW5kc1xuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNSYW5nZVBlcm11dGF0aW9uKGluZHMpIHtcbiAgICB2YXIgaW5kc1NwZWNpZmllZCA9IG5ldyBBcnJheShpbmRzLmxlbmd0aCk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5kcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAvLyBDaGVjayBmb3Igb3V0IG9mIGJvdW5kc1xuICAgICAgICBpZihpbmRzW2ldIDwgMCB8fCBpbmRzW2ldID49IGluZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBmb3IgY29sbGlzaW9ucyB3aXRoIGFscmVhZHkgc3BlY2lmaWVkIGluZGV4XG4gICAgICAgIGlmKGluZHNTcGVjaWZpZWRbaW5kc1tpXV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaW5kc1NwZWNpZmllZFtpbmRzW2ldXSA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gTm90aGluZyBvdXQgb2YgYm91bmRzIGFuZCBubyBjb2xsaXNpb25zLiBXZSBoYXZlIGEgcGVybXV0YXRpb25cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsY1wiOjYwMSxcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9oZWxwZXJzXCI6NjA0LFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL2ZpbHRlcl91bmlxdWUuanNcIjo3MTEsXCIuLi8uLi9saWIvZ3VwXCI6NzE3fV0sMTA3MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBoYXNDb2xvcnNjYWxlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hlbHBlcnMnKS5oYXNDb2xvcnNjYWxlO1xudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xudmFyIGhhbmRsZURvbWFpbkRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZG9tYWluJykuZGVmYXVsdHM7XG52YXIgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0cycpO1xuXG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIG1lcmdlTGVuZ3RoID0gX2RlcmVxXygnLi4vcGFyY29vcmRzL21lcmdlX2xlbmd0aCcpO1xuXG5mdW5jdGlvbiBoYW5kbGVMaW5lRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpIHtcbiAgICBjb2VyY2UoJ2xpbmUuc2hhcGUnKTtcbiAgICBjb2VyY2UoJ2xpbmUuaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgdmFyIGxpbmVDb2xvciA9IGNvZXJjZSgnbGluZS5jb2xvcicsIGxheW91dC5jb2xvcndheVswXSk7XG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZUluLCAnbGluZScpICYmIExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGxpbmVDb2xvcikpIHtcbiAgICAgICAgaWYobGluZUNvbG9yLmxlbmd0aCkge1xuICAgICAgICAgICAgY29lcmNlKCdsaW5lLmNvbG9yc2NhbGUnKTtcbiAgICAgICAgICAgIGNvbG9yc2NhbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICdsaW5lLicsIGNMZXR0ZXI6ICdjJ30pO1xuICAgICAgICAgICAgcmV0dXJuIGxpbmVDb2xvci5sZW5ndGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0cmFjZU91dC5saW5lLmNvbG9yID0gZGVmYXVsdENvbG9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBJbmZpbml0eTtcbn1cblxuZnVuY3Rpb24gZGltZW5zaW9uRGVmYXVsdHMoZGltZW5zaW9uSW4sIGRpbWVuc2lvbk91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGRpbWVuc2lvbkluLCBkaW1lbnNpb25PdXQsIGF0dHJpYnV0ZXMuZGltZW5zaW9ucywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIHZhbHVlcyA9IGNvZXJjZSgndmFsdWVzJyk7XG4gICAgdmFyIHZpc2libGUgPSBjb2VyY2UoJ3Zpc2libGUnKTtcbiAgICBpZighKHZhbHVlcyAmJiB2YWx1ZXMubGVuZ3RoKSkge1xuICAgICAgICB2aXNpYmxlID0gZGltZW5zaW9uT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZih2aXNpYmxlKSB7XG4gICAgICAgIC8vIERpbWVuc2lvbiBsZXZlbFxuICAgICAgICBjb2VyY2UoJ2xhYmVsJyk7XG4gICAgICAgIGNvZXJjZSgnZGlzcGxheWluZGV4JywgZGltZW5zaW9uT3V0Ll9pbmRleCk7XG5cbiAgICAgICAgLy8gQ2F0ZWdvcnkgbGV2ZWxcbiAgICAgICAgdmFyIGFycmF5SW4gPSBkaW1lbnNpb25Jbi5jYXRlZ29yeWFycmF5O1xuICAgICAgICB2YXIgaXNWYWxpZEFycmF5ID0gKEFycmF5LmlzQXJyYXkoYXJyYXlJbikgJiYgYXJyYXlJbi5sZW5ndGggPiAwKTtcblxuICAgICAgICB2YXIgb3JkZXJEZWZhdWx0O1xuICAgICAgICBpZihpc1ZhbGlkQXJyYXkpIG9yZGVyRGVmYXVsdCA9ICdhcnJheSc7XG4gICAgICAgIHZhciBvcmRlciA9IGNvZXJjZSgnY2F0ZWdvcnlvcmRlcicsIG9yZGVyRGVmYXVsdCk7XG5cbiAgICAgICAgLy8gY29lcmNlICdjYXRlZ29yeWFycmF5JyBvbmx5IGluIGFycmF5IG9yZGVyIGNhc2VcbiAgICAgICAgaWYob3JkZXIgPT09ICdhcnJheScpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnY2F0ZWdvcnlhcnJheScpO1xuICAgICAgICAgICAgY29lcmNlKCd0aWNrdGV4dCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVsZXRlIGRpbWVuc2lvbkluLmNhdGVnb3J5YXJyYXk7XG4gICAgICAgICAgICBkZWxldGUgZGltZW5zaW9uSW4udGlja3RleHQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjYW5ub3Qgc2V0ICdjYXRlZ29yeW9yZGVyJyB0byAnYXJyYXknIHdpdGggYW4gaW52YWxpZCAnY2F0ZWdvcnlhcnJheSdcbiAgICAgICAgaWYoIWlzVmFsaWRBcnJheSAmJiBvcmRlciA9PT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgZGltZW5zaW9uT3V0LmNhdGVnb3J5b3JkZXIgPSAndHJhY2UnO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgZGltZW5zaW9ucyA9IGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIHtcbiAgICAgICAgbmFtZTogJ2RpbWVuc2lvbnMnLFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IGRpbWVuc2lvbkRlZmF1bHRzXG4gICAgfSk7XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcblxuICAgIGhhbmRsZURvbWFpbkRlZmF1bHRzKHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheShkaW1lbnNpb25zKSB8fCAhZGltZW5zaW9ucy5sZW5ndGgpIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIG1lcmdlTGVuZ3RoKHRyYWNlT3V0LCBkaW1lbnNpb25zLCAndmFsdWVzJywgbGVuKTtcblxuICAgIGNvZXJjZSgnaG92ZXJvbicpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuICAgIGNvZXJjZSgnYXJyYW5nZW1lbnQnKTtcbiAgICBjb2VyY2UoJ2J1bmRsZWNvbG9ycycpO1xuICAgIGNvZXJjZSgnc29ydHBhdGhzJyk7XG4gICAgY29lcmNlKCdjb3VudHMnKTtcblxuICAgIHZhciBsYWJlbGZvbnREZmx0ID0ge1xuICAgICAgICBmYW1pbHk6IGxheW91dC5mb250LmZhbWlseSxcbiAgICAgICAgc2l6ZTogTWF0aC5yb3VuZChsYXlvdXQuZm9udC5zaXplKSxcbiAgICAgICAgY29sb3I6IGxheW91dC5mb250LmNvbG9yXG4gICAgfTtcblxuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2xhYmVsZm9udCcsIGxhYmVsZm9udERmbHQpO1xuXG4gICAgdmFyIGNhdGVnb3J5Zm9udERlZmF1bHQgPSB7XG4gICAgICAgIGZhbWlseTogbGF5b3V0LmZvbnQuZmFtaWx5LFxuICAgICAgICBzaXplOiBNYXRoLnJvdW5kKGxheW91dC5mb250LnNpemUgLyAxLjIpLFxuICAgICAgICBjb2xvcjogbGF5b3V0LmZvbnQuY29sb3JcbiAgICB9O1xuXG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAndGlja2ZvbnQnLCBjYXRlZ29yeWZvbnREZWZhdWx0KTtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzXCI6NjAzLFwiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hlbHBlcnNcIjo2MDQsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHNcIjo3NjMsXCIuLi8uLi9wbG90cy9kb21haW5cIjo3OTIsXCIuLi9wYXJjb29yZHMvbWVyZ2VfbGVuZ3RoXCI6MTA4MyxcIi4vYXR0cmlidXRlc1wiOjEwNjd9XSwxMDcxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKSxcbiAgICBjb2xvcmJhcjoge1xuICAgICAgICBjb250YWluZXI6ICdsaW5lJyxcbiAgICAgICAgbWluOiAnY21pbicsXG4gICAgICAgIG1heDogJ2NtYXgnXG4gICAgfSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3BhcmNhdHMnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuL2Jhc2VfcGxvdCcpLFxuICAgIGNhdGVnb3JpZXM6IFsnbm9PcGFjaXR5J10sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4vYXR0cmlidXRlc1wiOjEwNjcsXCIuL2Jhc2VfcGxvdFwiOjEwNjgsXCIuL2NhbGNcIjoxMDY5LFwiLi9kZWZhdWx0c1wiOjEwNzAsXCIuL3Bsb3RcIjoxMDczfV0sMTA3MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgUGxvdGx5ID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF9hcGknKTtcbnZhciBGeCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgdGlueWNvbG9yID0gX2RlcmVxXygndGlueWNvbG9yMicpO1xudmFyIHN2Z1RleHRVdGlscyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xuXG5mdW5jdGlvbiBwZXJmb3JtUGxvdChwYXJjYXRzTW9kZWxzLCBncmFwaERpdiwgbGF5b3V0LCBzdmcpIHtcbiAgICB2YXIgdmlld01vZGVscyA9IHBhcmNhdHNNb2RlbHMubWFwKGNyZWF0ZVBhcmNhdHNWaWV3TW9kZWwuYmluZCgwLCBncmFwaERpdiwgbGF5b3V0KSk7XG5cbiAgICAvLyBHZXQgKHBvdGVudGlhbGx5IGVtcHR5KSBwYXJjYXRzbGF5ZXIgc2VsZWN0aW9uIHdpdGggYm91bmQgZGF0YSB0byBzaW5nbGUgZWxlbWVudCBhcnJheVxuICAgIHZhciBsYXllclNlbGVjdGlvbiA9IHN2Zy5zZWxlY3RBbGwoJ2cucGFyY2F0c2xheWVyJykuZGF0YShbbnVsbF0pO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBzaW5nbGUgcGFyY2F0c2xheWVyIGdyb3VwIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICBsYXllclNlbGVjdGlvbi5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAncGFyY2F0c2xheWVyJylcbiAgICAgICAgLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhbGwnKTtcblxuICAgIC8vIEJpbmQgZGF0YSB0byBjaGlsZHJlbiBvZiBsYXllclNlbGVjdGlvbiBhbmQgZ2V0IHJlZmVyZW5jZSB0byB0cmFjZVNlbGVjdGlvblxuICAgIHZhciB0cmFjZVNlbGVjdGlvbiA9IGxheWVyU2VsZWN0aW9uXG4gICAgICAgIC5zZWxlY3RBbGwoJ2cudHJhY2UucGFyY2F0cycpXG4gICAgICAgIC5kYXRhKHZpZXdNb2RlbHMsIGtleSk7XG5cbiAgICAvLyBJbml0aWFsaXplIGdyb3VwIGZvciBlYWNoIHRyYWNlL2RpbWVuc2lvbnNcbiAgICB2YXIgdHJhY2VFbnRlciA9IHRyYWNlU2VsZWN0aW9uLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICd0cmFjZSBwYXJjYXRzJyk7XG5cbiAgICAvLyBVcGRhdGUgcHJvcGVydGllcyBmb3IgZWFjaCB0cmFjZVxuICAgIHRyYWNlU2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgZC54ICsgJywgJyArIGQueSArICcpJztcbiAgICAgICAgfSk7XG5cbiAgICAvLyBJbml0aWFsaXplIHBhdGhzIGdyb3VwXG4gICAgdHJhY2VFbnRlclxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ3BhdGhzJyk7XG5cbiAgICAvLyBVcGRhdGUgcGF0aHMgdHJhbnNmb3JtXG4gICAgdmFyIHBhdGhzU2VsZWN0aW9uID0gdHJhY2VTZWxlY3Rpb25cbiAgICAgICAgLnNlbGVjdCgnZy5wYXRocycpO1xuXG4gICAgLy8gR2V0IHBhdGhzIHNlbGVjdGlvblxuICAgIHZhciBwYXRoU2VsZWN0aW9uID0gcGF0aHNTZWxlY3Rpb25cbiAgICAgICAgLnNlbGVjdEFsbCgncGF0aC5wYXRoJylcbiAgICAgICAgLmRhdGEoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQucGF0aHM7XG4gICAgICAgIH0sIGtleSk7XG5cbiAgICAvLyBVcGRhdGUgZXhpc3RpbmcgcGF0aCBjb2xvcnNcbiAgICBwYXRoU2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCdmaWxsJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQubW9kZWwuY29sb3I7XG4gICAgICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIHBhdGhzXG4gICAgdmFyIHBhdGhTZWxlY3Rpb25FbnRlciA9IHBhdGhTZWxlY3Rpb25cbiAgICAgICAgLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncGF0aCcpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdwYXRoJylcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS1vcGFjaXR5JywgMClcbiAgICAgICAgLmF0dHIoJ2ZpbGwnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5tb2RlbC5jb2xvcjtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ2ZpbGwtb3BhY2l0eScsIDApO1xuXG4gICAgc3R5bGVQYXRoc05vSG92ZXIocGF0aFNlbGVjdGlvbkVudGVyKTtcblxuICAgIC8vIFNldCBwYXRoIGdlb21ldHJ5XG4gICAgcGF0aFNlbGVjdGlvblxuICAgICAgICAuYXR0cignZCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLnN2Z0Q7XG4gICAgICAgIH0pO1xuXG4gICAgLy8gc29ydCBwYXRoc1xuICAgIGlmKCFwYXRoU2VsZWN0aW9uRW50ZXIuZW1wdHkoKSkge1xuICAgICAgICAvLyBPbmx5IHNvcnQgcGF0aHMgaWYgdGhlcmUgaGFzIGJlZW4gYSBjaGFuZ2UuXG4gICAgICAgIC8vIE90aGVyd2lzZSBwYXRocyBhcmUgYWxyZWFkeSBzb3J0ZWQgb3IgYSBob3ZlciBvcGVyYXRpb24gbWF5IGJlIGluIHByb2dyZXNzXG4gICAgICAgIHBhdGhTZWxlY3Rpb24uc29ydChjb21wYXJlUmF3Q29sb3IpO1xuICAgIH1cblxuICAgIC8vIFJlbW92ZSBhbnkgb2xkIHBhdGhzXG4gICAgcGF0aFNlbGVjdGlvbi5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAvLyBQYXRoIGhvdmVyXG4gICAgcGF0aFNlbGVjdGlvblxuICAgICAgICAub24oJ21vdXNlb3ZlcicsIG1vdXNlb3ZlclBhdGgpXG4gICAgICAgIC5vbignbW91c2VvdXQnLCBtb3VzZW91dFBhdGgpXG4gICAgICAgIC5vbignY2xpY2snLCBjbGlja1BhdGgpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBkaW1lbnNpb25zIGdyb3VwXG4gICAgdHJhY2VFbnRlci5hcHBlbmQoJ2cnKS5hdHRyKCdjbGFzcycsICdkaW1lbnNpb25zJyk7XG5cbiAgICAvLyBVcGRhdGUgZGltZW5zaW9ucyB0cmFuc2Zvcm1cbiAgICB2YXIgZGltZW5zaW9uc1NlbGVjdGlvbiA9IHRyYWNlU2VsZWN0aW9uXG4gICAgICAgIC5zZWxlY3QoJ2cuZGltZW5zaW9ucycpO1xuXG4gICAgLy8gR2V0IGRpbWVuc2lvbiBzZWxlY3Rpb25cbiAgICB2YXIgZGltZW5zaW9uU2VsZWN0aW9uID0gZGltZW5zaW9uc1NlbGVjdGlvblxuICAgICAgICAuc2VsZWN0QWxsKCdnLmRpbWVuc2lvbicpXG4gICAgICAgIC5kYXRhKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLmRpbWVuc2lvbnM7XG4gICAgICAgIH0sIGtleSk7XG5cbiAgICAvLyBDcmVhdGUgZGltZW5zaW9uIGdyb3Vwc1xuICAgIGRpbWVuc2lvblNlbGVjdGlvbi5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnZGltZW5zaW9uJyk7XG5cbiAgICAvLyBVcGRhdGUgZGltZW5zaW9uIGdyb3VwIHRyYW5zZm9ybXNcbiAgICBkaW1lbnNpb25TZWxlY3Rpb24uYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgZC54ICsgJywgMCknO1xuICAgIH0pO1xuXG4gICAgLy8gUmVtb3ZlIGFueSBvbGQgZGltZW5zaW9uc1xuICAgIGRpbWVuc2lvblNlbGVjdGlvbi5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAvLyBHZXQgY2F0ZWdvcnkgc2VsZWN0aW9uXG4gICAgdmFyIGNhdGVnb3J5U2VsZWN0aW9uID0gZGltZW5zaW9uU2VsZWN0aW9uXG4gICAgICAgIC5zZWxlY3RBbGwoJ2cuY2F0ZWdvcnknKVxuICAgICAgICAuZGF0YShmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5jYXRlZ29yaWVzO1xuICAgICAgICB9LCBrZXkpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBjYXRlZ29yeSBncm91cHNcbiAgICB2YXIgY2F0ZWdvcnlHcm91cEVudGVyU2VsZWN0aW9uID0gY2F0ZWdvcnlTZWxlY3Rpb25cbiAgICAgICAgLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5hdHRyKCdjbGFzcycsICdjYXRlZ29yeScpO1xuXG4gICAgLy8gVXBkYXRlIGNhdGVnb3J5IHRyYW5zZm9ybXNcbiAgICBjYXRlZ29yeVNlbGVjdGlvblxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoMCwgJyArIGQueSArICcpJztcbiAgICAgICAgfSk7XG5cblxuICAgIC8vIEluaXRpYWxpemUgcmVjdGFuZ2xlXG4gICAgY2F0ZWdvcnlHcm91cEVudGVyU2VsZWN0aW9uXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnY2F0cmVjdCcpXG4gICAgICAgIC5hdHRyKCdwb2ludGVyLWV2ZW50cycsICdub25lJyk7XG5cblxuICAgIC8vIFVwZGF0ZSByZWN0YW5nbGVcbiAgICBjYXRlZ29yeVNlbGVjdGlvbi5zZWxlY3QoJ3JlY3QuY2F0cmVjdCcpXG4gICAgICAgIC5hdHRyKCdmaWxsJywgJ25vbmUnKVxuICAgICAgICAuYXR0cignd2lkdGgnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC53aWR0aDtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ2hlaWdodCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLmhlaWdodDtcbiAgICAgICAgfSk7XG5cbiAgICBzdHlsZUNhdGVnb3JpZXNOb0hvdmVyKGNhdGVnb3J5R3JvdXBFbnRlclNlbGVjdGlvbik7XG5cbiAgICAvLyBJbml0aWFsaXplIGNvbG9yIGJhbmQgcmVjdHNcbiAgICB2YXIgYmFuZFNlbGVjdGlvbiA9IGNhdGVnb3J5U2VsZWN0aW9uXG4gICAgICAgIC5zZWxlY3RBbGwoJ3JlY3QuYmFuZHJlY3QnKVxuICAgICAgICAuZGF0YShcbiAgICAgICAgICAgIC8qKiBAcGFyYW0ge0NhdGVnb3J5Vmlld01vZGVsfSBjYXRWaWV3TW9kZWwqL1xuICAgICAgICAgICAgZnVuY3Rpb24oY2F0Vmlld01vZGVsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhdFZpZXdNb2RlbC5iYW5kcztcbiAgICAgICAgICAgIH0sIGtleSk7XG5cbiAgICAvLyBSYWlzZSBhbGwgdXBkYXRlIGJhbmRzIHRvIHRoZSB0b3Agc28gdGhhdCBmYWRpbmcgZW50ZXIvZXhpdCBiYW5kcyB3aWxsIGJlIGJlaGluZFxuICAgIGJhbmRTZWxlY3Rpb24uZWFjaChmdW5jdGlvbigpIHtMaWIucmFpc2VUb1RvcCh0aGlzKTt9KTtcblxuICAgIC8vIFVwZGF0ZSBiYW5kIGNvbG9yXG4gICAgYmFuZFNlbGVjdGlvblxuICAgICAgICAuYXR0cignZmlsbCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLmNvbG9yO1xuICAgICAgICB9KTtcblxuICAgIHZhciBiYW5kc1NlbGVjdGlvbkVudGVyID0gYmFuZFNlbGVjdGlvbi5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnYmFuZHJlY3QnKVxuICAgICAgICAuYXR0cignc3Ryb2tlLW9wYWNpdHknLCAwKVxuICAgICAgICAuYXR0cignZmlsbCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLmNvbG9yO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignZmlsbC1vcGFjaXR5JywgMCk7XG5cbiAgICBiYW5kU2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCdmaWxsJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuY29sb3I7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLndpZHRoO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuaGVpZ2h0O1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cigneScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLnk7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCdjdXJzb3InLFxuICAgICAgICAgICAgLyoqIEBwYXJhbSB7Q2F0ZWdvcnlCYW5kVmlld01vZGVsfSBiYW5kTW9kZWwqL1xuICAgICAgICAgICAgZnVuY3Rpb24oYmFuZE1vZGVsKSB7XG4gICAgICAgICAgICAgICAgaWYoYmFuZE1vZGVsLnBhcmNhdHNWaWV3TW9kZWwuYXJyYW5nZW1lbnQgPT09ICdmaXhlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdkZWZhdWx0JztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoYmFuZE1vZGVsLnBhcmNhdHNWaWV3TW9kZWwuYXJyYW5nZW1lbnQgPT09ICdwZXJwZW5kaWN1bGFyJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ25zLXJlc2l6ZSc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdtb3ZlJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgIHN0eWxlQmFuZHNOb0hvdmVyKGJhbmRzU2VsZWN0aW9uRW50ZXIpO1xuXG4gICAgYmFuZFNlbGVjdGlvbi5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAvLyBJbml0aWFsaXplIGNhdGVnb3J5IGxhYmVsXG4gICAgY2F0ZWdvcnlHcm91cEVudGVyU2VsZWN0aW9uXG4gICAgICAgIC5hcHBlbmQoJ3RleHQnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnY2F0bGFiZWwnKVxuICAgICAgICAuYXR0cigncG9pbnRlci1ldmVudHMnLCAnbm9uZScpO1xuXG4gICAgdmFyIHBhcGVyQ29sb3IgPSBncmFwaERpdi5fZnVsbExheW91dC5wYXBlcl9iZ2NvbG9yO1xuXG4gICAgLy8gVXBkYXRlIGNhdGVnb3J5IGxhYmVsXG4gICAgY2F0ZWdvcnlTZWxlY3Rpb24uc2VsZWN0KCd0ZXh0LmNhdGxhYmVsJylcbiAgICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJyxcbiAgICAgICAgICAgIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBpZihjYXRJblJpZ2h0RGltKGQpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBsYWNlIGxhYmVsIHRvIHRoZSByaWdodCBvZiBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ3N0YXJ0JztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBsYWJlbCB0byB0aGUgbGVmdCBvZiBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ2VuZCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ2FsaWdubWVudC1iYXNlbGluZScsICdtaWRkbGUnKVxuXG4gICAgICAgIC5zdHlsZSgndGV4dC1zaGFkb3cnLFxuICAgICAgICAgICAgcGFwZXJDb2xvciArICcgLTFweCAgMXB4IDJweCwgJyArXG4gICAgICAgICAgICBwYXBlckNvbG9yICsgJyAxcHggIDFweCAycHgsICcgK1xuICAgICAgICAgICAgcGFwZXJDb2xvciArICcgIDFweCAtMXB4IDJweCwgJyArXG4gICAgICAgICAgICBwYXBlckNvbG9yICsgJyAtMXB4IC0xcHggMnB4JylcbiAgICAgICAgLnN0eWxlKCdmaWxsJywgJ3JnYigwLCAwLCAwKScpXG4gICAgICAgIC5hdHRyKCd4JyxcbiAgICAgICAgICAgIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBpZihjYXRJblJpZ2h0RGltKGQpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBsYWNlIGxhYmVsIHRvIHRoZSByaWdodCBvZiBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZC53aWR0aCArIDU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgbGFiZWwgdG8gdGhlIGxlZnQgb2YgY2F0ZWdvcnlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIC01O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd5JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuaGVpZ2h0IC8gMjtcbiAgICAgICAgfSlcbiAgICAgICAgLnRleHQoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQubW9kZWwuY2F0ZWdvcnlMYWJlbDtcbiAgICAgICAgfSlcbiAgICAgICAgLmVhY2goXG4gICAgICAgICAgICAvKiogQHBhcmFtIHtDYXRlZ29yeVZpZXdNb2RlbH0gY2F0TW9kZWwqL1xuICAgICAgICAgICAgZnVuY3Rpb24oY2F0TW9kZWwpIHtcbiAgICAgICAgICAgICAgICBEcmF3aW5nLmZvbnQoZDMuc2VsZWN0KHRoaXMpLCBjYXRNb2RlbC5wYXJjYXRzVmlld01vZGVsLmNhdGVnb3J5bGFiZWxmb250KTtcbiAgICAgICAgICAgICAgICBzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zKGQzLnNlbGVjdCh0aGlzKSwgZ3JhcGhEaXYpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAvLyBJbml0aWFsaXplIGRpbWVuc2lvbiBsYWJlbFxuICAgIGNhdGVnb3J5R3JvdXBFbnRlclNlbGVjdGlvblxuICAgICAgICAuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ2RpbWxhYmVsJyk7XG5cbiAgICAvLyBVcGRhdGUgZGltZW5zaW9uIGxhYmVsXG4gICAgY2F0ZWdvcnlTZWxlY3Rpb24uc2VsZWN0KCd0ZXh0LmRpbWxhYmVsJylcbiAgICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgICAgIC5hdHRyKCdhbGlnbm1lbnQtYmFzZWxpbmUnLCAnYmFzZWxpbmUnKVxuICAgICAgICAuYXR0cignY3Vyc29yJyxcbiAgICAgICAgICAgICAvKiogQHBhcmFtIHtDYXRlZ29yeVZpZXdNb2RlbH0gY2F0TW9kZWwqL1xuICAgICAgICAgICAgZnVuY3Rpb24oY2F0TW9kZWwpIHtcbiAgICAgICAgICAgICAgICBpZihjYXRNb2RlbC5wYXJjYXRzVmlld01vZGVsLmFycmFuZ2VtZW50ID09PSAnZml4ZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnZGVmYXVsdCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdldy1yZXNpemUnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd4JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQud2lkdGggLyAyO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cigneScsIC01KVxuICAgICAgICAudGV4dChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICBpZihpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gQWRkIGRpbWVuc2lvbiBsYWJlbCBhYm92ZSB0b3Btb3N0IGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zW2QubW9kZWwuZGltZW5zaW9uSW5kXS5kaW1lbnNpb25MYWJlbDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5lYWNoKFxuICAgICAgICAgICAgLyoqIEBwYXJhbSB7Q2F0ZWdvcnlWaWV3TW9kZWx9IGNhdE1vZGVsKi9cbiAgICAgICAgICAgIGZ1bmN0aW9uKGNhdE1vZGVsKSB7XG4gICAgICAgICAgICAgICAgRHJhd2luZy5mb250KGQzLnNlbGVjdCh0aGlzKSwgY2F0TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5sYWJlbGZvbnQpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAvLyBDYXRlZ29yeSBob3ZlclxuICAgIC8vIGNhdGVnb3J5U2VsZWN0aW9uLnNlbGVjdCgncmVjdC5jYXRyZWN0JylcbiAgICBjYXRlZ29yeVNlbGVjdGlvbi5zZWxlY3RBbGwoJ3JlY3QuYmFuZHJlY3QnKVxuICAgICAgICAub24oJ21vdXNlb3ZlcicsIG1vdXNlb3ZlckNhdGVnb3J5QmFuZClcbiAgICAgICAgLm9uKCdtb3VzZW91dCcsIG1vdXNlb3V0Q2F0ZWdvcnkpO1xuXG4gICAgLy8gUmVtb3ZlIHVudXNlZCBjYXRlZ29yaWVzXG4gICAgY2F0ZWdvcnlTZWxlY3Rpb24uZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgLy8gU2V0dXAgZHJhZ1xuICAgIGRpbWVuc2lvblNlbGVjdGlvbi5jYWxsKGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAub3JpZ2luKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiB7eDogZC54LCB5OiAwfTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdkcmFnc3RhcnQnLCBkcmFnRGltZW5zaW9uU3RhcnQpXG4gICAgICAgIC5vbignZHJhZycsIGRyYWdEaW1lbnNpb24pXG4gICAgICAgIC5vbignZHJhZ2VuZCcsIGRyYWdEaW1lbnNpb25FbmQpKTtcblxuXG4gICAgLy8gU2F2ZSBvZmYgc2VsZWN0aW9ucyB0byB2aWV3IG1vZGVsc1xuICAgIHRyYWNlU2VsZWN0aW9uLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICBkLnRyYWNlU2VsZWN0aW9uID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICBkLnBhdGhTZWxlY3Rpb24gPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdnLnBhdGhzJykuc2VsZWN0QWxsKCdwYXRoLnBhdGgnKTtcbiAgICAgICAgZC5kaW1lbnNpb25TZWxlY3Rpb24gPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdnLmRpbWVuc2lvbnMnKS5zZWxlY3RBbGwoJ2cuZGltZW5zaW9uJyk7XG4gICAgfSk7XG5cbiAgICAvLyBSZW1vdmUgYW55IG9ycGhhbiB0cmFjZXNcbiAgICB0cmFjZVNlbGVjdGlvbi5leGl0KCkucmVtb3ZlKCk7XG59XG5cbi8qKlxuICogQ3JlYXRlIC8gdXBkYXRlIHBhcmNhdCB0cmFjZXNcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gZ3JhcGhEaXZcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdmdcbiAqIEBwYXJhbSB7QXJyYXkuPFBhcmNhdHNNb2RlbD59IHBhcmNhdHNNb2RlbHNcbiAqIEBwYXJhbSB7TGF5b3V0fSBsYXlvdXRcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihncmFwaERpdiwgc3ZnLCBwYXJjYXRzTW9kZWxzLCBsYXlvdXQpIHtcbiAgICBwZXJmb3JtUGxvdChwYXJjYXRzTW9kZWxzLCBncmFwaERpdiwgbGF5b3V0LCBzdmcpO1xufTtcblxuLyoqXG4gKiBGdW5jdGlvbiB0aGUgcmV0dXJucyB0aGUga2V5IHByb3BlcnR5IG9mIGFuIG9iamVjdCBmb3IgdXNlIHdpdGggYXMgRDMgam9pbiBmdW5jdGlvblxuICogQHBhcmFtIGRcbiAqL1xuZnVuY3Rpb24ga2V5KGQpIHtcbiAgICByZXR1cm4gZC5rZXk7XG59XG5cbiAvKiogVHJ1ZSBpZiBhIGNhdGVnb3J5IHZpZXcgbW9kZWwgaXMgaW4gdGhlIHJpZ2h0LW1vc3QgZGlzcGxheSBkaW1lbnNpb25cbiAgKiBAcGFyYW0ge0NhdGVnb3J5Vmlld01vZGVsfSBkICovXG5mdW5jdGlvbiBjYXRJblJpZ2h0RGltKGQpIHtcbiAgICB2YXIgbnVtRGltcyA9IGQucGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25zLmxlbmd0aDtcbiAgICB2YXIgbGVmdERpbUluZCA9IGQucGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25zW251bURpbXMgLSAxXS5tb2RlbC5kaW1lbnNpb25JbmQ7XG4gICAgcmV0dXJuIGQubW9kZWwuZGltZW5zaW9uSW5kID09PSBsZWZ0RGltSW5kO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7UGF0aFZpZXdNb2RlbH0gYVxuICogQHBhcmFtIHtQYXRoVmlld01vZGVsfSBiXG4gKi9cbmZ1bmN0aW9uIGNvbXBhcmVSYXdDb2xvcihhLCBiKSB7XG4gICAgaWYoYS5tb2RlbC5yYXdDb2xvciA+IGIubW9kZWwucmF3Q29sb3IpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfSBlbHNlIGlmKGEubW9kZWwucmF3Q29sb3IgPCBiLm1vZGVsLnJhd0NvbG9yKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG59XG5cbi8qKlxuICogSGFuZGxlIHBhdGggbW91c2VvdmVyXG4gKiBAcGFyYW0ge1BhdGhWaWV3TW9kZWx9IGRcbiAqL1xuZnVuY3Rpb24gbW91c2VvdmVyUGF0aChkKSB7XG4gICAgaWYoIWQucGFyY2F0c1ZpZXdNb2RlbC5kcmFnRGltZW5zaW9uKSB7XG4gICAgICAgIC8vIFdlJ3JlIG5vdCBjdXJyZW50bHkgZHJhZ2dpbmdcblxuICAgICAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZignc2tpcCcpID09PSAtMSkge1xuICAgICAgICAgICAgLy8gaG92ZXJpbmZvIGlzIG5vdCBza2lwLCBzbyB3ZSBhdCBsZWFzdCBzdHlsZSB0aGUgcGF0aHMgYW5kIGVtaXQgaW50ZXJhY3Rpb24gZXZlbnRzXG5cbiAgICAgICAgICAgIC8vIFJhaXNlIHBhdGggdG8gdG9wXG4gICAgICAgICAgICBMaWIucmFpc2VUb1RvcCh0aGlzKTtcblxuICAgICAgICAgICAgc3R5bGVQYXRoc0hvdmVyKGQzLnNlbGVjdCh0aGlzKSk7XG5cbiAgICAgICAgICAgIC8vIEVtaXQgaG92ZXIgZXZlbnRcbiAgICAgICAgICAgIHZhciBwb2ludHMgPSBidWlsZFBvaW50c0FycmF5Rm9yUGF0aChkKTtcbiAgICAgICAgICAgIGQucGFyY2F0c1ZpZXdNb2RlbC5ncmFwaERpdi5lbWl0KCdwbG90bHlfaG92ZXInLCB7cG9pbnRzOiBwb2ludHMsIGV2ZW50OiBkMy5ldmVudH0pO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgaG92ZXIgbGFiZWxcbiAgICAgICAgICAgIGlmKGQucGFyY2F0c1ZpZXdNb2RlbC5ob3ZlcmluZm9JdGVtcy5pbmRleE9mKCdub25lJykgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgLy8gaG92ZXJpbmZvIGlzIGEgY29tYmluYXRpb24gb2YgJ2NvdW50JyBhbmQgJ3Byb2JhYmlsaXR5J1xuXG4gICAgICAgICAgICAgICAgLy8gTW91c2VcbiAgICAgICAgICAgICAgICB2YXIgaG92ZXJYID0gZDMubW91c2UodGhpcylbMF07XG5cbiAgICAgICAgICAgICAgICAvLyBMYWJlbFxuICAgICAgICAgICAgICAgIHZhciBnZCA9IGQucGFyY2F0c1ZpZXdNb2RlbC5ncmFwaERpdjtcbiAgICAgICAgICAgICAgICB2YXIgdHJhY2UgPSBkLnBhcmNhdHNWaWV3TW9kZWwudHJhY2U7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICAgICAgICAgICAgICB2YXIgcm9vdEJCb3ggPSBmdWxsTGF5b3V0Ll9wYXBlcmRpdi5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgdmFyIGdyYXBoRGl2QkJveCA9IGQucGFyY2F0c1ZpZXdNb2RlbC5ncmFwaERpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgICAgICAgICAgICAgIC8vIEZpbmQgcGF0aCBjZW50ZXIgaW4gcGF0aCBjb29yZGluYXRlc1xuICAgICAgICAgICAgICAgIHZhciBwYXRoQ2VudGVyWCxcbiAgICAgICAgICAgICAgICAgICAgcGF0aENlbnRlclksXG4gICAgICAgICAgICAgICAgICAgIGRpbUluZDtcblxuICAgICAgICAgICAgICAgIGZvcihkaW1JbmQgPSAwOyBkaW1JbmQgPCAoZC5sZWZ0WHMubGVuZ3RoIC0gMSk7IGRpbUluZCsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGQubGVmdFhzW2RpbUluZF0gKyBkLmRpbVdpZHRoc1tkaW1JbmRdIC0gMiA8PSBob3ZlclggJiYgaG92ZXJYIDw9IGQubGVmdFhzW2RpbUluZCArIDFdICsgMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnREaW0gPSBkLnBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9uc1tkaW1JbmRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0RGltID0gZC5wYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnNbZGltSW5kICsgMV07XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRoQ2VudGVyWCA9IChsZWZ0RGltLnggKyBsZWZ0RGltLndpZHRoICsgcmlnaHREaW0ueCkgLyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0aENlbnRlclkgPSAoZC50b3BZc1tkaW1JbmRdICsgZC50b3BZc1tkaW1JbmQgKyAxXSArIGQuaGVpZ2h0KSAvIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEZpbmQgcGF0aCBjZW50ZXIgaW4gcm9vdCBjb29yZGluYXRlc1xuICAgICAgICAgICAgICAgIHZhciBob3ZlckNlbnRlclggPSBkLnBhcmNhdHNWaWV3TW9kZWwueCArIHBhdGhDZW50ZXJYO1xuICAgICAgICAgICAgICAgIHZhciBob3ZlckNlbnRlclkgPSBkLnBhcmNhdHNWaWV3TW9kZWwueSArIHBhdGhDZW50ZXJZO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRleHRDb2xvciA9IHRpbnljb2xvci5tb3N0UmVhZGFibGUoZC5tb2RlbC5jb2xvciwgWydibGFjaycsICd3aGl0ZSddKTtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGQubW9kZWwuY291bnQ7XG4gICAgICAgICAgICAgICAgdmFyIHByb2IgPSBjb3VudCAvIGQucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5jb3VudDtcbiAgICAgICAgICAgICAgICB2YXIgbGFiZWxzID0ge1xuICAgICAgICAgICAgICAgICAgICBjb3VudExhYmVsOiBjb3VudCxcbiAgICAgICAgICAgICAgICAgICAgcHJvYmFiaWxpdHlMYWJlbDogcHJvYi50b0ZpeGVkKDMpXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIC8vIEJ1aWxkIGhvdmVyIHRleHRcbiAgICAgICAgICAgICAgICB2YXIgaG92ZXJ0ZXh0UGFydHMgPSBbXTtcbiAgICAgICAgICAgICAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZignY291bnQnKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJ0ZXh0UGFydHMucHVzaChbJ0NvdW50OicsIGxhYmVscy5jb3VudExhYmVsXS5qb2luKCcgJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZigncHJvYmFiaWxpdHknKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJ0ZXh0UGFydHMucHVzaChbJ1A6JywgbGFiZWxzLnByb2JhYmlsaXR5TGFiZWxdLmpvaW4oJyAnKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGhvdmVydGV4dCA9IGhvdmVydGV4dFBhcnRzLmpvaW4oJzxicj4nKTtcbiAgICAgICAgICAgICAgICB2YXIgbW91c2VYID0gZDMubW91c2UoZ2QpWzBdO1xuXG4gICAgICAgICAgICAgICAgRngubG9uZUhvdmVyKHtcbiAgICAgICAgICAgICAgICAgICAgdHJhY2U6IHRyYWNlLFxuICAgICAgICAgICAgICAgICAgICB4OiBob3ZlckNlbnRlclggLSByb290QkJveC5sZWZ0ICsgZ3JhcGhEaXZCQm94LmxlZnQsXG4gICAgICAgICAgICAgICAgICAgIHk6IGhvdmVyQ2VudGVyWSAtIHJvb3RCQm94LnRvcCArIGdyYXBoRGl2QkJveC50b3AsXG4gICAgICAgICAgICAgICAgICAgIHRleHQ6IGhvdmVydGV4dCxcbiAgICAgICAgICAgICAgICAgICAgY29sb3I6IGQubW9kZWwuY29sb3IsXG4gICAgICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiAnYmxhY2snLFxuICAgICAgICAgICAgICAgICAgICBmb250RmFtaWx5OiAnTW9uYWNvLCBcIkNvdXJpZXIgTmV3XCIsIG1vbm9zcGFjZScsXG4gICAgICAgICAgICAgICAgICAgIGZvbnRTaXplOiAxMCxcbiAgICAgICAgICAgICAgICAgICAgZm9udENvbG9yOiB0ZXh0Q29sb3IsXG4gICAgICAgICAgICAgICAgICAgIGlkZWFsQWxpZ246IG1vdXNlWCA8IGhvdmVyQ2VudGVyWCA/ICdyaWdodCcgOiAnbGVmdCcsXG4gICAgICAgICAgICAgICAgICAgIGhvdmVydGVtcGxhdGU6ICh0cmFjZS5saW5lIHx8IHt9KS5ob3ZlcnRlbXBsYXRlLFxuICAgICAgICAgICAgICAgICAgICBob3ZlcnRlbXBsYXRlTGFiZWxzOiBsYWJlbHMsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YTogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IHRyYWNlLl9pbnB1dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGxEYXRhOiB0cmFjZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiBjb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2JhYmlsaXR5OiBwcm9iXG4gICAgICAgICAgICAgICAgICAgIH1dXG4gICAgICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgICAgICBjb250YWluZXI6IGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIubm9kZSgpLFxuICAgICAgICAgICAgICAgICAgICBvdXRlckNvbnRhaW5lcjogZnVsbExheW91dC5fcGFwZXIubm9kZSgpLFxuICAgICAgICAgICAgICAgICAgICBnZDogZ2RcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBIYW5kbGUgcGF0aCBtb3VzZW91dFxuICogQHBhcmFtIHtQYXRoVmlld01vZGVsfSBkXG4gKi9cbmZ1bmN0aW9uIG1vdXNlb3V0UGF0aChkKSB7XG4gICAgaWYoIWQucGFyY2F0c1ZpZXdNb2RlbC5kcmFnRGltZW5zaW9uKSB7XG4gICAgICAgIC8vIFdlJ3JlIG5vdCBjdXJyZW50bHkgZHJhZ2dpbmdcbiAgICAgICAgc3R5bGVQYXRoc05vSG92ZXIoZDMuc2VsZWN0KHRoaXMpKTtcblxuICAgICAgICAvLyBSZW1vdmUgYW5kIGhvdmVyIGxhYmVsXG4gICAgICAgIEZ4LmxvbmVVbmhvdmVyKGQucGFyY2F0c1ZpZXdNb2RlbC5ncmFwaERpdi5fZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCkpO1xuXG4gICAgICAgIC8vIFJlc3RvcmUgcGF0aCBvcmRlclxuICAgICAgICBkLnBhcmNhdHNWaWV3TW9kZWwucGF0aFNlbGVjdGlvbi5zb3J0KGNvbXBhcmVSYXdDb2xvcik7XG5cbiAgICAgICAgLy8gRW1pdCB1bmhvdmVyIGV2ZW50XG4gICAgICAgIGlmKGQucGFyY2F0c1ZpZXdNb2RlbC5ob3ZlcmluZm9JdGVtcy5pbmRleE9mKCdza2lwJykgPT09IC0xKSB7XG4gICAgICAgICAgICB2YXIgcG9pbnRzID0gYnVpbGRQb2ludHNBcnJheUZvclBhdGgoZCk7XG4gICAgICAgICAgICBkLnBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXYuZW1pdCgncGxvdGx5X3VuaG92ZXInLCB7cG9pbnRzOiBwb2ludHMsIGV2ZW50OiBkMy5ldmVudH0pO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIEJ1aWxkIGFycmF5IG9mIHBvaW50IG9iamVjdHMgZm9yIGEgcGF0aFxuICpcbiAqIEZvciB1c2UgaW4gY2xpY2svaG92ZXIgZXZlbnRzXG4gKiBAcGFyYW0ge1BhdGhWaWV3TW9kZWx9IGRcbiAqL1xuZnVuY3Rpb24gYnVpbGRQb2ludHNBcnJheUZvclBhdGgoZCkge1xuICAgIHZhciBwb2ludHMgPSBbXTtcbiAgICB2YXIgY3VydmVOdW1iZXIgPSBnZXRUcmFjZUluZGV4KGQucGFyY2F0c1ZpZXdNb2RlbCk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZC5tb2RlbC52YWx1ZUluZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHBvaW50TnVtYmVyID0gZC5tb2RlbC52YWx1ZUluZHNbaV07XG4gICAgICAgIHBvaW50cy5wdXNoKHtcbiAgICAgICAgICAgIGN1cnZlTnVtYmVyOiBjdXJ2ZU51bWJlcixcbiAgICAgICAgICAgIHBvaW50TnVtYmVyOiBwb2ludE51bWJlclxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHBvaW50cztcbn1cblxuLyoqXG4gKiBIYW5kbGUgcGF0aCBjbGlja1xuICogQHBhcmFtIHtQYXRoVmlld01vZGVsfSBkXG4gKi9cbmZ1bmN0aW9uIGNsaWNrUGF0aChkKSB7XG4gICAgaWYoZC5wYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ3NraXAnKSA9PT0gLTEpIHtcbiAgICAgICAgLy8gaG92ZXJpbmZvIGl0J3Mgc2tpcCwgc28gaW50ZXJhY3Rpb24gZXZlbnRzIGFyZW4ndCBkaXNhYmxlZFxuICAgICAgICB2YXIgcG9pbnRzID0gYnVpbGRQb2ludHNBcnJheUZvclBhdGgoZCk7XG4gICAgICAgIGQucGFyY2F0c1ZpZXdNb2RlbC5ncmFwaERpdi5lbWl0KCdwbG90bHlfY2xpY2snLCB7cG9pbnRzOiBwb2ludHMsIGV2ZW50OiBkMy5ldmVudH0pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc3R5bGVQYXRoc05vSG92ZXIocGF0aFNlbGVjdGlvbikge1xuICAgIHBhdGhTZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ2ZpbGwnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5tb2RlbC5jb2xvcjtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ2ZpbGwtb3BhY2l0eScsIDAuNilcbiAgICAgICAgLmF0dHIoJ3N0cm9rZScsICdsaWdodGdyYXknKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgMC4yKVxuICAgICAgICAuYXR0cignc3Ryb2tlLW9wYWNpdHknLCAxLjApO1xufVxuXG5mdW5jdGlvbiBzdHlsZVBhdGhzSG92ZXIocGF0aFNlbGVjdGlvbikge1xuICAgIHBhdGhTZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ2ZpbGwtb3BhY2l0eScsIDAuOClcbiAgICAgICAgLmF0dHIoJ3N0cm9rZScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aW55Y29sb3IubW9zdFJlYWRhYmxlKGQubW9kZWwuY29sb3IsIFsnYmxhY2snLCAnd2hpdGUnXSk7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCAwLjMpO1xufVxuXG5mdW5jdGlvbiBzdHlsZUNhdGVnb3J5SG92ZXIoY2F0ZWdvcnlTZWxlY3Rpb24pIHtcbiAgICBjYXRlZ29yeVNlbGVjdGlvblxuICAgICAgICAuc2VsZWN0KCdyZWN0LmNhdHJlY3QnKVxuICAgICAgICAuYXR0cignc3Ryb2tlJywgJ2JsYWNrJylcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIDIuNSk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlQ2F0ZWdvcmllc05vSG92ZXIoY2F0ZWdvcnlTZWxlY3Rpb24pIHtcbiAgICBjYXRlZ29yeVNlbGVjdGlvblxuICAgICAgICAuc2VsZWN0KCdyZWN0LmNhdHJlY3QnKVxuICAgICAgICAuYXR0cignc3Ryb2tlJywgJ2JsYWNrJylcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIDEpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utb3BhY2l0eScsIDEpO1xufVxuXG5mdW5jdGlvbiBzdHlsZUJhbmRzSG92ZXIoYmFuZHNTZWxlY3Rpb24pIHtcbiAgICBiYW5kc1NlbGVjdGlvblxuICAgICAgICAuYXR0cignc3Ryb2tlJywgJ2JsYWNrJylcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIDEuNSk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlQmFuZHNOb0hvdmVyKGJhbmRzU2VsZWN0aW9uKSB7XG4gICAgYmFuZHNTZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ3N0cm9rZScsICdibGFjaycpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCAwLjIpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utb3BhY2l0eScsIDEuMClcbiAgICAgICAgLmF0dHIoJ2ZpbGwtb3BhY2l0eScsIDEuMCk7XG59XG5cbi8qKlxuICogUmV0dXJuIHNlbGVjdGlvbiBvZiBhbGwgcGF0aHMgdGhhdCBwYXNzIHRocm91Z2ggdGhlIHNwZWNpZmllZCBjYXRlZ29yeVxuICogQHBhcmFtIHtDYXRlZ29yeUJhbmRWaWV3TW9kZWx9IGNhdEJhbmRWaWV3TW9kZWxcbiAqL1xuZnVuY3Rpb24gc2VsZWN0UGF0aHNUaHJvdWdoQ2F0ZWdvcnlCYW5kQ29sb3IoY2F0QmFuZFZpZXdNb2RlbCkge1xuICAgIHZhciBhbGxQYXRocyA9IGNhdEJhbmRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5wYXRoU2VsZWN0aW9uO1xuICAgIHZhciBkaW1JbmQgPSBjYXRCYW5kVmlld01vZGVsLmNhdGVnb3J5Vmlld01vZGVsLm1vZGVsLmRpbWVuc2lvbkluZDtcbiAgICB2YXIgY2F0SW5kID0gY2F0QmFuZFZpZXdNb2RlbC5jYXRlZ29yeVZpZXdNb2RlbC5tb2RlbC5jYXRlZ29yeUluZDtcblxuICAgIHJldHVybiBhbGxQYXRoc1xuICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgLyoqIEBwYXJhbSB7UGF0aFZpZXdNb2RlbH0gcGF0aFZpZXdNb2RlbCAqL1xuICAgICAgICAgICAgZnVuY3Rpb24ocGF0aFZpZXdNb2RlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRoVmlld01vZGVsLm1vZGVsLmNhdGVnb3J5SW5kc1tkaW1JbmRdID09PSBjYXRJbmQgJiZcbiAgICAgICAgICAgICAgICAgICAgcGF0aFZpZXdNb2RlbC5tb2RlbC5jb2xvciA9PT0gY2F0QmFuZFZpZXdNb2RlbC5jb2xvcjtcbiAgICAgICAgICAgIH0pO1xufVxuXG5cbi8qKlxuICogUGVyZm9ybSBob3ZlciBzdHlsaW5nIGZvciBhbGwgcGF0aHMgdGhhdCBwYXNzIHRob3VnaCB0aGUgc3BlY2lmaWVkIGJhbmQgZWxlbWVudCdzIGNhdGVnb3J5XG4gKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gYmFuZEVsZW1lbnRcbiAqICBIVE1MIGVsZW1lbnQgZm9yIGJhbmRcbiAqXG4gKi9cbmZ1bmN0aW9uIHN0eWxlRm9yQ2F0ZWdvcnlIb3Zlcm1vZGUoYmFuZEVsZW1lbnQpIHtcbiAgICAvLyBHZXQgYWxsIGJhbmRzIGluIHRoZSBjdXJyZW50IGNhdGVnb3J5XG4gICAgdmFyIGJhbmRTZWwgPSBkMy5zZWxlY3QoYmFuZEVsZW1lbnQucGFyZW50Tm9kZSkuc2VsZWN0QWxsKCdyZWN0LmJhbmRyZWN0Jyk7XG5cbiAgICAvLyBSYWlzZSBhbmQgc3R5bGUgcGF0aHNcbiAgICBiYW5kU2VsLmVhY2goZnVuY3Rpb24oYnZtKSB7XG4gICAgICAgIHZhciBwYXRocyA9IHNlbGVjdFBhdGhzVGhyb3VnaENhdGVnb3J5QmFuZENvbG9yKGJ2bSk7XG4gICAgICAgIHN0eWxlUGF0aHNIb3ZlcihwYXRocyk7XG4gICAgICAgIHBhdGhzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBSYWlzZSBwYXRoIHRvIHRvcFxuICAgICAgICAgICAgTGliLnJhaXNlVG9Ub3AodGhpcyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gU3R5bGUgY2F0ZWdvcnlcbiAgICBzdHlsZUNhdGVnb3J5SG92ZXIoZDMuc2VsZWN0KGJhbmRFbGVtZW50LnBhcmVudE5vZGUpKTtcbn1cblxuLyoqXG4gKiBQZXJmb3JtIGhvdmVyIHN0eWxpbmcgZm9yIGFsbCBwYXRocyB0aGF0IHBhc3MgdGhvdWdoIHRoZSBjYXRlZ29yeSBvZiB0aGUgc3BlY2lmaWVkIGJhbmQgZWxlbWVudCBhbmQgc2hhcmUgdGhlXG4gKiBzYW1lIGNvbG9yXG4gKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gYmFuZEVsZW1lbnRcbiAqICBIVE1MIGVsZW1lbnQgZm9yIGJhbmRcbiAqXG4gKi9cbmZ1bmN0aW9uIHN0eWxlRm9yQ29sb3JIb3Zlcm1vZGUoYmFuZEVsZW1lbnQpIHtcbiAgICB2YXIgYmFuZFZpZXdNb2RlbCA9IGQzLnNlbGVjdChiYW5kRWxlbWVudCkuZGF0dW0oKTtcbiAgICB2YXIgY2F0UGF0aHMgPSBzZWxlY3RQYXRoc1Rocm91Z2hDYXRlZ29yeUJhbmRDb2xvcihiYW5kVmlld01vZGVsKTtcbiAgICBzdHlsZVBhdGhzSG92ZXIoY2F0UGF0aHMpO1xuICAgIGNhdFBhdGhzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIC8vIFJhaXNlIHBhdGggdG8gdG9wXG4gICAgICAgIExpYi5yYWlzZVRvVG9wKHRoaXMpO1xuICAgIH0pO1xuXG4gICAgLy8gU3R5bGUgY2F0ZWdvcnkgZm9yIGRyYWdcbiAgICBkMy5zZWxlY3QoYmFuZEVsZW1lbnQucGFyZW50Tm9kZSlcbiAgICAgICAgLnNlbGVjdEFsbCgncmVjdC5iYW5kcmVjdCcpXG4gICAgICAgIC5maWx0ZXIoZnVuY3Rpb24oYikge3JldHVybiBiLmNvbG9yID09PSBiYW5kVmlld01vZGVsLmNvbG9yO30pXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgTGliLnJhaXNlVG9Ub3AodGhpcyk7XG4gICAgICAgICAgICBzdHlsZUJhbmRzSG92ZXIoZDMuc2VsZWN0KHRoaXMpKTtcbiAgICAgICAgfSk7XG59XG5cblxuLyoqXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBiYW5kRWxlbWVudFxuICogIEhUTUwgZWxlbWVudCBmb3IgYmFuZFxuICogQHBhcmFtIGV2ZW50TmFtZVxuICogIEV2ZW50IG5hbWUgKHBsb3RseV9ob3ZlciBvciBwbG90bHlfY2xpY2spXG4gKiBAcGFyYW0gZXZlbnRcbiAqICBNb3VzZSBFdmVudFxuICovXG5mdW5jdGlvbiBlbWl0UG9pbnRzRXZlbnRDYXRlZ29yeUhvdmVybW9kZShiYW5kRWxlbWVudCwgZXZlbnROYW1lLCBldmVudCkge1xuICAgIC8vIEdldCBhbGwgYmFuZHMgaW4gdGhlIGN1cnJlbnQgY2F0ZWdvcnlcbiAgICB2YXIgYmFuZFZpZXdNb2RlbCA9IGQzLnNlbGVjdChiYW5kRWxlbWVudCkuZGF0dW0oKTtcbiAgICB2YXIgZ2QgPSBiYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXY7XG4gICAgdmFyIGJhbmRTZWwgPSBkMy5zZWxlY3QoYmFuZEVsZW1lbnQucGFyZW50Tm9kZSkuc2VsZWN0QWxsKCdyZWN0LmJhbmRyZWN0Jyk7XG5cbiAgICB2YXIgcG9pbnRzID0gW107XG4gICAgYmFuZFNlbC5lYWNoKGZ1bmN0aW9uKGJ2bSkge1xuICAgICAgICB2YXIgcGF0aHMgPSBzZWxlY3RQYXRoc1Rocm91Z2hDYXRlZ29yeUJhbmRDb2xvcihidm0pO1xuICAgICAgICBwYXRocy5lYWNoKGZ1bmN0aW9uKHBhdGhWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgIC8vIEV4dGVuZCBwb2ludHMgYXJyYXlcbiAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHBvaW50cywgYnVpbGRQb2ludHNBcnJheUZvclBhdGgocGF0aFZpZXdNb2RlbCkpO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIGdkLmVtaXQoZXZlbnROYW1lLCB7cG9pbnRzOiBwb2ludHMsIGV2ZW50OiBldmVudH0pO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGJhbmRFbGVtZW50XG4gKiAgSFRNTCBlbGVtZW50IGZvciBiYW5kXG4gKiBAcGFyYW0gZXZlbnROYW1lXG4gKiAgRXZlbnQgbmFtZSAocGxvdGx5X2hvdmVyIG9yIHBsb3RseV9jbGljaylcbiAqIEBwYXJhbSBldmVudFxuICogIE1vdXNlIEV2ZW50XG4gKi9cbmZ1bmN0aW9uIGVtaXRQb2ludHNFdmVudENvbG9ySG92ZXJtb2RlKGJhbmRFbGVtZW50LCBldmVudE5hbWUsIGV2ZW50KSB7XG4gICAgdmFyIGJhbmRWaWV3TW9kZWwgPSBkMy5zZWxlY3QoYmFuZEVsZW1lbnQpLmRhdHVtKCk7XG4gICAgdmFyIGdkID0gYmFuZFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmdyYXBoRGl2O1xuICAgIHZhciBwYXRocyA9IHNlbGVjdFBhdGhzVGhyb3VnaENhdGVnb3J5QmFuZENvbG9yKGJhbmRWaWV3TW9kZWwpO1xuXG4gICAgdmFyIHBvaW50cyA9IFtdO1xuICAgIHBhdGhzLmVhY2goZnVuY3Rpb24ocGF0aFZpZXdNb2RlbCkge1xuICAgICAgICAvLyBFeHRlbmQgcG9pbnRzIGFycmF5XG4gICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KHBvaW50cywgYnVpbGRQb2ludHNBcnJheUZvclBhdGgocGF0aFZpZXdNb2RlbCkpO1xuICAgIH0pO1xuXG4gICAgZ2QuZW1pdChldmVudE5hbWUsIHtwb2ludHM6IHBvaW50cywgZXZlbnQ6IGV2ZW50fSk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGhvdmVyIGxhYmVsIGZvciBhIGJhbmQgZWxlbWVudCdzIGNhdGVnb3J5IChmb3IgdXNlIHdoZW4gaG92ZXJvbiA9PT0gJ2NhdGVnb3J5JylcbiAqXG4gKiBAcGFyYW0ge0NsaWVudFJlY3R9IHJvb3RCQm94XG4gKiAgQ2xpZW50IGJvdW5kaW5nIGJveCBmb3Igcm9vdCBvZiBmaWd1cmVcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGJhbmRFbGVtZW50XG4gKiAgSFRNTCBlbGVtZW50IGZvciBiYW5kXG4gKlxuICovXG5mdW5jdGlvbiBjcmVhdGVIb3ZlckxhYmVsRm9yQ2F0ZWdvcnlIb3Zlcm1vZGUocm9vdEJCb3gsIGJhbmRFbGVtZW50KSB7XG4gICAgLy8gU2VsZWN0aW9uc1xuICAgIHZhciByZWN0U2VsZWN0aW9uID0gZDMuc2VsZWN0KGJhbmRFbGVtZW50LnBhcmVudE5vZGUpLnNlbGVjdCgncmVjdC5jYXRyZWN0Jyk7XG4gICAgdmFyIHJlY3RCb3VuZGluZ0JveCA9IHJlY3RTZWxlY3Rpb24ubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgLy8gTW9kZWxzXG4gICAgLyoqIEB0eXBlIHtDYXRlZ29yeVZpZXdNb2RlbH0gKi9cbiAgICB2YXIgY2F0Vmlld01vZGVsID0gcmVjdFNlbGVjdGlvbi5kYXR1bSgpO1xuICAgIHZhciBwYXJjYXRzVmlld01vZGVsID0gY2F0Vmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWw7XG4gICAgdmFyIGRpbWVuc2lvbk1vZGVsID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zW2NhdFZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25JbmRdO1xuICAgIHZhciB0cmFjZSA9IHBhcmNhdHNWaWV3TW9kZWwudHJhY2U7XG5cbiAgICAvLyBQb3NpdGlvbnNcbiAgICB2YXIgaG92ZXJDZW50ZXJZID0gcmVjdEJvdW5kaW5nQm94LnRvcCArIHJlY3RCb3VuZGluZ0JveC5oZWlnaHQgLyAyO1xuICAgIHZhciBob3ZlckNlbnRlclgsXG4gICAgICAgIGhvdmVyTGFiZWxJZGVhbEFsaWduO1xuXG4gICAgaWYocGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25zLmxlbmd0aCA+IDEgJiZcbiAgICAgICAgZGltZW5zaW9uTW9kZWwuZGlzcGxheUluZCA9PT0gcGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25zLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgLy8gcmlnaHQgbW9zdCBkaW1lbnNpb25cbiAgICAgICAgaG92ZXJDZW50ZXJYID0gcmVjdEJvdW5kaW5nQm94LmxlZnQ7XG4gICAgICAgIGhvdmVyTGFiZWxJZGVhbEFsaWduID0gJ2xlZnQnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhvdmVyQ2VudGVyWCA9IHJlY3RCb3VuZGluZ0JveC5sZWZ0ICsgcmVjdEJvdW5kaW5nQm94LndpZHRoO1xuICAgICAgICBob3ZlckxhYmVsSWRlYWxBbGlnbiA9ICdyaWdodCc7XG4gICAgfVxuXG4gICAgdmFyIGNvdW50ID0gY2F0Vmlld01vZGVsLm1vZGVsLmNvdW50O1xuICAgIHZhciBjYXRMYWJlbCA9IGNhdFZpZXdNb2RlbC5tb2RlbC5jYXRlZ29yeUxhYmVsO1xuICAgIHZhciBwcm9iID0gY291bnQgLyBjYXRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5jb3VudDtcbiAgICB2YXIgbGFiZWxzID0ge1xuICAgICAgICBjb3VudExhYmVsOiBjb3VudCxcbiAgICAgICAgY2F0ZWdvcnlMYWJlbDogY2F0TGFiZWwsXG4gICAgICAgIHByb2JhYmlsaXR5TGFiZWw6IHByb2IudG9GaXhlZCgzKVxuICAgIH07XG5cbiAgICAvLyBIb3ZlciBsYWJlbCB0ZXh0XG4gICAgdmFyIGhvdmVyaW5mb1BhcnRzID0gW107XG4gICAgaWYoY2F0Vmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZignY291bnQnKSAhPT0gLTEpIHtcbiAgICAgICAgaG92ZXJpbmZvUGFydHMucHVzaChbJ0NvdW50OicsIGxhYmVscy5jb3VudExhYmVsXS5qb2luKCcgJykpO1xuICAgIH1cbiAgICBpZihjYXRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5ob3ZlcmluZm9JdGVtcy5pbmRleE9mKCdwcm9iYWJpbGl0eScpICE9PSAtMSkge1xuICAgICAgICBob3ZlcmluZm9QYXJ0cy5wdXNoKFsnUCgnICsgbGFiZWxzLmNhdGVnb3J5TGFiZWwgKyAnKTonLCBsYWJlbHMucHJvYmFiaWxpdHlMYWJlbF0uam9pbignICcpKTtcbiAgICB9XG5cbiAgICB2YXIgaG92ZXJ0ZXh0ID0gaG92ZXJpbmZvUGFydHMuam9pbignPGJyPicpO1xuICAgIHJldHVybiB7XG4gICAgICAgIHRyYWNlOiB0cmFjZSxcbiAgICAgICAgeDogaG92ZXJDZW50ZXJYIC0gcm9vdEJCb3gubGVmdCxcbiAgICAgICAgeTogaG92ZXJDZW50ZXJZIC0gcm9vdEJCb3gudG9wLFxuICAgICAgICB0ZXh0OiBob3ZlcnRleHQsXG4gICAgICAgIGNvbG9yOiAnbGlnaHRncmF5JyxcbiAgICAgICAgYm9yZGVyQ29sb3I6ICdibGFjaycsXG4gICAgICAgIGZvbnRGYW1pbHk6ICdNb25hY28sIFwiQ291cmllciBOZXdcIiwgbW9ub3NwYWNlJyxcbiAgICAgICAgZm9udFNpemU6IDEyLFxuICAgICAgICBmb250Q29sb3I6ICdibGFjaycsXG4gICAgICAgIGlkZWFsQWxpZ246IGhvdmVyTGFiZWxJZGVhbEFsaWduLFxuICAgICAgICBob3ZlcnRlbXBsYXRlOiB0cmFjZS5ob3ZlcnRlbXBsYXRlLFxuICAgICAgICBob3ZlcnRlbXBsYXRlTGFiZWxzOiBsYWJlbHMsXG4gICAgICAgIGV2ZW50RGF0YTogW3tcbiAgICAgICAgICAgIGRhdGE6IHRyYWNlLl9pbnB1dCxcbiAgICAgICAgICAgIGZ1bGxEYXRhOiB0cmFjZSxcbiAgICAgICAgICAgIGNvdW50OiBjb3VudCxcbiAgICAgICAgICAgIGNhdGVnb3J5OiBjYXRMYWJlbCxcbiAgICAgICAgICAgIHByb2JhYmlsaXR5OiBwcm9iXG4gICAgICAgIH1dXG4gICAgfTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgaG92ZXIgbGFiZWwgZm9yIGEgYmFuZCBlbGVtZW50J3MgY2F0ZWdvcnkgKGZvciB1c2Ugd2hlbiBob3Zlcm9uID09PSAnY2F0ZWdvcnknKVxuICpcbiAqIEBwYXJhbSB7Q2xpZW50UmVjdH0gcm9vdEJCb3hcbiAqICBDbGllbnQgYm91bmRpbmcgYm94IGZvciByb290IG9mIGZpZ3VyZVxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gYmFuZEVsZW1lbnRcbiAqICBIVE1MIGVsZW1lbnQgZm9yIGJhbmRcbiAqXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUhvdmVyTGFiZWxGb3JEaW1lbnNpb25Ib3Zlcm1vZGUocm9vdEJCb3gsIGJhbmRFbGVtZW50KSB7XG4gICAgdmFyIGFsbEhvdmVybGFiZWxzID0gW107XG5cbiAgICBkMy5zZWxlY3QoYmFuZEVsZW1lbnQucGFyZW50Tm9kZS5wYXJlbnROb2RlKVxuICAgICAgICAuc2VsZWN0QWxsKCdnLmNhdGVnb3J5JylcbiAgICAgICAgLnNlbGVjdCgncmVjdC5jYXRyZWN0JylcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgYmFuZE5vZGUgPSB0aGlzO1xuICAgICAgICAgICAgYWxsSG92ZXJsYWJlbHMucHVzaChjcmVhdGVIb3ZlckxhYmVsRm9yQ2F0ZWdvcnlIb3Zlcm1vZGUocm9vdEJCb3gsIGJhbmROb2RlKSk7XG4gICAgICAgIH0pO1xuXG4gICAgcmV0dXJuIGFsbEhvdmVybGFiZWxzO1xufVxuXG4vKipcbiAqIENyZWF0ZSBob3ZlciBsYWJlbHMgZm9yIGEgYmFuZCBlbGVtZW50J3MgY2F0ZWdvcnkgKGZvciB1c2Ugd2hlbiBob3Zlcm9uID09PSAnZGltZW5zaW9uJylcbiAqXG4gKiBAcGFyYW0ge0NsaWVudFJlY3R9IHJvb3RCQm94XG4gKiAgQ2xpZW50IGJvdW5kaW5nIGJveCBmb3Igcm9vdCBvZiBmaWd1cmVcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGJhbmRFbGVtZW50XG4gKiAgSFRNTCBlbGVtZW50IGZvciBiYW5kXG4gKlxuICovXG5mdW5jdGlvbiBjcmVhdGVIb3ZlckxhYmVsRm9yQ29sb3JIb3Zlcm1vZGUocm9vdEJCb3gsIGJhbmRFbGVtZW50KSB7XG4gICAgdmFyIGJhbmRCb3VuZGluZ0JveCA9IGJhbmRFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgLy8gTW9kZWxzXG4gICAgLyoqIEB0eXBlIHtDYXRlZ29yeUJhbmRWaWV3TW9kZWx9ICovXG4gICAgdmFyIGJhbmRWaWV3TW9kZWwgPSBkMy5zZWxlY3QoYmFuZEVsZW1lbnQpLmRhdHVtKCk7XG4gICAgdmFyIGNhdFZpZXdNb2RlbCA9IGJhbmRWaWV3TW9kZWwuY2F0ZWdvcnlWaWV3TW9kZWw7XG4gICAgdmFyIHBhcmNhdHNWaWV3TW9kZWwgPSBjYXRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbDtcbiAgICB2YXIgZGltZW5zaW9uTW9kZWwgPSBwYXJjYXRzVmlld01vZGVsLm1vZGVsLmRpbWVuc2lvbnNbY2F0Vmlld01vZGVsLm1vZGVsLmRpbWVuc2lvbkluZF07XG4gICAgdmFyIHRyYWNlID0gcGFyY2F0c1ZpZXdNb2RlbC50cmFjZTtcblxuICAgIC8vIHBvc2l0aW9uc1xuICAgIHZhciBob3ZlckNlbnRlclkgPSBiYW5kQm91bmRpbmdCb3gueSArIGJhbmRCb3VuZGluZ0JveC5oZWlnaHQgLyAyO1xuXG4gICAgdmFyIGhvdmVyQ2VudGVyWCxcbiAgICAgICAgaG92ZXJMYWJlbElkZWFsQWxpZ247XG4gICAgaWYocGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25zLmxlbmd0aCA+IDEgJiZcbiAgICAgICAgZGltZW5zaW9uTW9kZWwuZGlzcGxheUluZCA9PT0gcGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25zLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgLy8gcmlnaHQgbW9zdCBkaW1lbnNpb25cbiAgICAgICAgaG92ZXJDZW50ZXJYID0gYmFuZEJvdW5kaW5nQm94LmxlZnQ7XG4gICAgICAgIGhvdmVyTGFiZWxJZGVhbEFsaWduID0gJ2xlZnQnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhvdmVyQ2VudGVyWCA9IGJhbmRCb3VuZGluZ0JveC5sZWZ0ICsgYmFuZEJvdW5kaW5nQm94LndpZHRoO1xuICAgICAgICBob3ZlckxhYmVsSWRlYWxBbGlnbiA9ICdyaWdodCc7XG4gICAgfVxuXG4gICAgLy8gTGFiZWxzXG4gICAgdmFyIGNhdExhYmVsID0gY2F0Vmlld01vZGVsLm1vZGVsLmNhdGVnb3J5TGFiZWw7XG5cbiAgICAvLyBDb3VudHNcbiAgICB2YXIgdG90YWxDb3VudCA9IGJhbmRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5jb3VudDtcblxuICAgIHZhciBiYW5kQ29sb3JDb3VudCA9IDA7XG4gICAgYmFuZFZpZXdNb2RlbC5jYXRlZ29yeVZpZXdNb2RlbC5iYW5kcy5mb3JFYWNoKGZ1bmN0aW9uKGIpIHtcbiAgICAgICAgaWYoYi5jb2xvciA9PT0gYmFuZFZpZXdNb2RlbC5jb2xvcikge1xuICAgICAgICAgICAgYmFuZENvbG9yQ291bnQgKz0gYi5jb3VudDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFyIGNhdENvdW50ID0gY2F0Vmlld01vZGVsLm1vZGVsLmNvdW50O1xuXG4gICAgdmFyIGNvbG9yQ291bnQgPSAwO1xuICAgIHBhcmNhdHNWaWV3TW9kZWwucGF0aFNlbGVjdGlvbi5lYWNoKFxuICAgICAgICAvKiogQHBhcmFtIHtQYXRoVmlld01vZGVsfSBwYXRoVmlld01vZGVsICovXG4gICAgICAgIGZ1bmN0aW9uKHBhdGhWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgIGlmKHBhdGhWaWV3TW9kZWwubW9kZWwuY29sb3IgPT09IGJhbmRWaWV3TW9kZWwuY29sb3IpIHtcbiAgICAgICAgICAgICAgICBjb2xvckNvdW50ICs9IHBhdGhWaWV3TW9kZWwubW9kZWwuY291bnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIHBDb2xvckFuZENhdCA9IGJhbmRDb2xvckNvdW50IC8gdG90YWxDb3VudDtcbiAgICB2YXIgcENhdEdpdmVuQ29sb3IgPSBiYW5kQ29sb3JDb3VudCAvIGNvbG9yQ291bnQ7XG4gICAgdmFyIHBDb2xvckdpdmVuQ2F0ID0gYmFuZENvbG9yQ291bnQgLyBjYXRDb3VudDtcblxuICAgIHZhciBsYWJlbHMgPSB7XG4gICAgICAgIGNvdW50TGFiZWw6IHRvdGFsQ291bnQsXG4gICAgICAgIGNhdGVnb3J5TGFiZWw6IGNhdExhYmVsLFxuICAgICAgICBwcm9iYWJpbGl0eUxhYmVsOiBwQ29sb3JBbmRDYXQudG9GaXhlZCgzKVxuICAgIH07XG5cbiAgICAvLyBIb3ZlciBsYWJlbCB0ZXh0XG4gICAgdmFyIGhvdmVyaW5mb1BhcnRzID0gW107XG4gICAgaWYoY2F0Vmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZignY291bnQnKSAhPT0gLTEpIHtcbiAgICAgICAgaG92ZXJpbmZvUGFydHMucHVzaChbJ0NvdW50OicsIGxhYmVscy5jb3VudExhYmVsXS5qb2luKCcgJykpO1xuICAgIH1cbiAgICBpZihjYXRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5ob3ZlcmluZm9JdGVtcy5pbmRleE9mKCdwcm9iYWJpbGl0eScpICE9PSAtMSkge1xuICAgICAgICBob3ZlcmluZm9QYXJ0cy5wdXNoKCdQKGNvbG9yIOKIqSAnICsgY2F0TGFiZWwgKyAnKTogJyArIGxhYmVscy5wcm9iYWJpbGl0eUxhYmVsKTtcbiAgICAgICAgaG92ZXJpbmZvUGFydHMucHVzaCgnUCgnICsgY2F0TGFiZWwgKyAnIHwgY29sb3IpOiAnICsgcENhdEdpdmVuQ29sb3IudG9GaXhlZCgzKSk7XG4gICAgICAgIGhvdmVyaW5mb1BhcnRzLnB1c2goJ1AoY29sb3IgfCAnICsgY2F0TGFiZWwgKyAnKTogJyArIHBDb2xvckdpdmVuQ2F0LnRvRml4ZWQoMykpO1xuICAgIH1cblxuICAgIHZhciBob3ZlcnRleHQgPSBob3ZlcmluZm9QYXJ0cy5qb2luKCc8YnI+Jyk7XG5cbiAgICAvLyBDb21wdXRlIHRleHQgY29sb3JcbiAgICB2YXIgdGV4dENvbG9yID0gdGlueWNvbG9yLm1vc3RSZWFkYWJsZShiYW5kVmlld01vZGVsLmNvbG9yLCBbJ2JsYWNrJywgJ3doaXRlJ10pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHJhY2U6IHRyYWNlLFxuICAgICAgICB4OiBob3ZlckNlbnRlclggLSByb290QkJveC5sZWZ0LFxuICAgICAgICB5OiBob3ZlckNlbnRlclkgLSByb290QkJveC50b3AsXG4gICAgICAgIC8vIG5hbWU6ICdOQU1FJyxcbiAgICAgICAgdGV4dDogaG92ZXJ0ZXh0LFxuICAgICAgICBjb2xvcjogYmFuZFZpZXdNb2RlbC5jb2xvcixcbiAgICAgICAgYm9yZGVyQ29sb3I6ICdibGFjaycsXG4gICAgICAgIGZvbnRGYW1pbHk6ICdNb25hY28sIFwiQ291cmllciBOZXdcIiwgbW9ub3NwYWNlJyxcbiAgICAgICAgZm9udENvbG9yOiB0ZXh0Q29sb3IsXG4gICAgICAgIGZvbnRTaXplOiAxMCxcbiAgICAgICAgaWRlYWxBbGlnbjogaG92ZXJMYWJlbElkZWFsQWxpZ24sXG4gICAgICAgIGhvdmVydGVtcGxhdGU6IHRyYWNlLmhvdmVydGVtcGxhdGUsXG4gICAgICAgIGhvdmVydGVtcGxhdGVMYWJlbHM6IGxhYmVscyxcbiAgICAgICAgZXZlbnREYXRhOiBbe1xuICAgICAgICAgICAgZGF0YTogdHJhY2UuX2lucHV0LFxuICAgICAgICAgICAgZnVsbERhdGE6IHRyYWNlLFxuICAgICAgICAgICAgY2F0ZWdvcnk6IGNhdExhYmVsLFxuICAgICAgICAgICAgY291bnQ6IHRvdGFsQ291bnQsXG4gICAgICAgICAgICBwcm9iYWJpbGl0eTogcENvbG9yQW5kQ2F0LFxuICAgICAgICAgICAgY2F0ZWdvcnljb3VudDogY2F0Q291bnQsXG4gICAgICAgICAgICBjb2xvcmNvdW50OiBjb2xvckNvdW50LFxuICAgICAgICAgICAgYmFuZGNvbG9yY291bnQ6IGJhbmRDb2xvckNvdW50XG4gICAgICAgIH1dXG4gICAgfTtcbn1cblxuLyoqXG4gKiBIYW5kbGUgZGltZW5zaW9uIG1vdXNlb3ZlclxuICogQHBhcmFtIHtDYXRlZ29yeUJhbmRWaWV3TW9kZWx9IGJhbmRWaWV3TW9kZWxcbiAqL1xuZnVuY3Rpb24gbW91c2VvdmVyQ2F0ZWdvcnlCYW5kKGJhbmRWaWV3TW9kZWwpIHtcbiAgICBpZighYmFuZFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmRyYWdEaW1lbnNpb24pIHtcbiAgICAgICAgLy8gV2UncmUgbm90IGN1cnJlbnRseSBkcmFnZ2luZ1xuXG4gICAgICAgIGlmKGJhbmRWaWV3TW9kZWwucGFyY2F0c1ZpZXdNb2RlbC5ob3ZlcmluZm9JdGVtcy5pbmRleE9mKCdza2lwJykgPT09IC0xKSB7XG4gICAgICAgICAgICAvLyBob3ZlcmluZm8gaXMgbm90IHNraXAsIHNvIHdlIGF0IGxlYXN0IHN0eWxlIHRoZSBiYW5kcyBhbmQgZW1pdCBpbnRlcmFjdGlvbiBldmVudHNcblxuICAgICAgICAgICAgLy8gTW91c2VcbiAgICAgICAgICAgIHZhciBtb3VzZVkgPSBkMy5tb3VzZSh0aGlzKVsxXTtcbiAgICAgICAgICAgIGlmKG1vdXNlWSA8IC0xKSB7XG4gICAgICAgICAgICAgICAgLy8gSG92ZXIgaXMgYWJvdmUgYWJvdmUgdGhlIGNhdGVnb3J5IHJlY3RhbmdsZSAocHJvYmFibHkgdGhlIGRpbWVuc2lvbiB0aXRsZSB0ZXh0KVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGdkID0gYmFuZFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmdyYXBoRGl2O1xuICAgICAgICAgICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICAgICAgICAgIHZhciByb290QkJveCA9IGZ1bGxMYXlvdXQuX3BhcGVyZGl2Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIHZhciBob3Zlcm9uID0gYmFuZFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmhvdmVyb247XG5cbiAgICAgICAgICAgIC8qKiBAdHlwZSB7SFRNTEVsZW1lbnR9ICovXG4gICAgICAgICAgICB2YXIgYmFuZEVsZW1lbnQgPSB0aGlzO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgc3R5bGUgYW5kIGV2ZW50c1xuICAgICAgICAgICAgaWYoaG92ZXJvbiA9PT0gJ2NvbG9yJykge1xuICAgICAgICAgICAgICAgIHN0eWxlRm9yQ29sb3JIb3Zlcm1vZGUoYmFuZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGVtaXRQb2ludHNFdmVudENvbG9ySG92ZXJtb2RlKGJhbmRFbGVtZW50LCAncGxvdGx5X2hvdmVyJywgZDMuZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdHlsZUZvckNhdGVnb3J5SG92ZXJtb2RlKGJhbmRFbGVtZW50KTtcbiAgICAgICAgICAgICAgICBlbWl0UG9pbnRzRXZlbnRDYXRlZ29yeUhvdmVybW9kZShiYW5kRWxlbWVudCwgJ3Bsb3RseV9ob3ZlcicsIGQzLmV2ZW50KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSGFuZGxlIGhvdmVyIGxhYmVsXG4gICAgICAgICAgICBpZihiYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJpbmZvSXRlbXMuaW5kZXhPZignbm9uZScpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHZhciBob3Zlckl0ZW1zO1xuICAgICAgICAgICAgICAgIGlmKGhvdmVyb24gPT09ICdjYXRlZ29yeScpIHtcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJJdGVtcyA9IGNyZWF0ZUhvdmVyTGFiZWxGb3JDYXRlZ29yeUhvdmVybW9kZShyb290QkJveCwgYmFuZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihob3Zlcm9uID09PSAnY29sb3InKSB7XG4gICAgICAgICAgICAgICAgICAgIGhvdmVySXRlbXMgPSBjcmVhdGVIb3ZlckxhYmVsRm9yQ29sb3JIb3Zlcm1vZGUocm9vdEJCb3gsIGJhbmRFbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYoaG92ZXJvbiA9PT0gJ2RpbWVuc2lvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJJdGVtcyA9IGNyZWF0ZUhvdmVyTGFiZWxGb3JEaW1lbnNpb25Ib3Zlcm1vZGUocm9vdEJCb3gsIGJhbmRFbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihob3Zlckl0ZW1zKSB7XG4gICAgICAgICAgICAgICAgICAgIEZ4LmxvbmVIb3Zlcihob3Zlckl0ZW1zLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXI6IGZ1bGxMYXlvdXQuX2hvdmVybGF5ZXIubm9kZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3V0ZXJDb250YWluZXI6IGZ1bGxMYXlvdXQuX3BhcGVyLm5vZGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdkOiBnZFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cblxuLyoqXG4gKiBIYW5kbGUgZGltZW5zaW9uIG1vdXNlb3ZlclxuICogQHBhcmFtIHtDYXRlZ29yeUJhbmRWaWV3TW9kZWx9IGJhbmRWaWV3TW9kZWxcbiAqL1xuZnVuY3Rpb24gbW91c2VvdXRDYXRlZ29yeShiYW5kVmlld01vZGVsKSB7XG4gICAgdmFyIHBhcmNhdHNWaWV3TW9kZWwgPSBiYW5kVmlld01vZGVsLnBhcmNhdHNWaWV3TW9kZWw7XG5cbiAgICBpZighcGFyY2F0c1ZpZXdNb2RlbC5kcmFnRGltZW5zaW9uKSB7XG4gICAgICAgIC8vIFdlJ3JlIG5vdCBkcmFnZ2luZyBhbnl0aGluZ1xuXG4gICAgICAgIC8vIFJlc2V0IHVuaG92ZXJlZCBzdHlsZXNcbiAgICAgICAgc3R5bGVQYXRoc05vSG92ZXIocGFyY2F0c1ZpZXdNb2RlbC5wYXRoU2VsZWN0aW9uKTtcbiAgICAgICAgc3R5bGVDYXRlZ29yaWVzTm9Ib3ZlcihwYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvblNlbGVjdGlvbi5zZWxlY3RBbGwoJ2cuY2F0ZWdvcnknKSk7XG4gICAgICAgIHN0eWxlQmFuZHNOb0hvdmVyKHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9uU2VsZWN0aW9uLnNlbGVjdEFsbCgnZy5jYXRlZ29yeScpLnNlbGVjdEFsbCgncmVjdC5iYW5kcmVjdCcpKTtcblxuICAgICAgICAvLyBSZW1vdmUgaG92ZXIgbGFiZWxcbiAgICAgICAgRngubG9uZVVuaG92ZXIocGFyY2F0c1ZpZXdNb2RlbC5ncmFwaERpdi5fZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCkpO1xuXG4gICAgICAgIC8vIFJlc3RvcmUgcGF0aCBvcmRlclxuICAgICAgICBwYXJjYXRzVmlld01vZGVsLnBhdGhTZWxlY3Rpb24uc29ydChjb21wYXJlUmF3Q29sb3IpO1xuXG4gICAgICAgIC8vIEVtaXQgdW5ob3ZlciBldmVudFxuICAgICAgICBpZihwYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ3NraXAnKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHZhciBob3Zlcm9uID0gYmFuZFZpZXdNb2RlbC5wYXJjYXRzVmlld01vZGVsLmhvdmVyb247XG4gICAgICAgICAgICB2YXIgYmFuZEVsZW1lbnQgPSB0aGlzO1xuXG4gICAgICAgICAgICAvLyBIYW5kbGUgc3R5bGUgYW5kIGV2ZW50c1xuICAgICAgICAgICAgaWYoaG92ZXJvbiA9PT0gJ2NvbG9yJykge1xuICAgICAgICAgICAgICAgIGVtaXRQb2ludHNFdmVudENvbG9ySG92ZXJtb2RlKGJhbmRFbGVtZW50LCAncGxvdGx5X3VuaG92ZXInLCBkMy5ldmVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGVtaXRQb2ludHNFdmVudENhdGVnb3J5SG92ZXJtb2RlKGJhbmRFbGVtZW50LCAncGxvdGx5X3VuaG92ZXInLCBkMy5ldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cblxuLyoqXG4gKiBIYW5kbGUgZGltZW5zaW9uIGRyYWcgc3RhcnRcbiAqIEBwYXJhbSB7RGltZW5zaW9uVmlld01vZGVsfSBkXG4gKi9cbmZ1bmN0aW9uIGRyYWdEaW1lbnNpb25TdGFydChkKSB7XG4gICAgLy8gQ2hlY2sgaWYgZHJhZ2dpbmcgaXMgc3VwcG9ydGVkXG4gICAgaWYoZC5wYXJjYXRzVmlld01vZGVsLmFycmFuZ2VtZW50ID09PSAnZml4ZWQnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBTYXZlIG9mZiBpbml0aWFsIGRyYWcgaW5kZXhlcyBmb3IgZGltZW5zaW9uXG4gICAgZC5kcmFnRGltZW5zaW9uRGlzcGxheUluZCA9IGQubW9kZWwuZGlzcGxheUluZDtcbiAgICBkLmluaXRpYWxEcmFnRGltZW5zaW9uRGlzcGxheUluZHMgPSBkLnBhcmNhdHNWaWV3TW9kZWwubW9kZWwuZGltZW5zaW9ucy5tYXAoZnVuY3Rpb24oZCkge3JldHVybiBkLmRpc3BsYXlJbmQ7fSk7XG4gICAgZC5kcmFnSGFzTW92ZWQgPSBmYWxzZTtcblxuICAgIC8vIENoZWNrIGZvciBjYXRlZ29yeSBoaXRcbiAgICBkLmRyYWdDYXRlZ29yeURpc3BsYXlJbmQgPSBudWxsO1xuICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAuc2VsZWN0QWxsKCdnLmNhdGVnb3J5JylcbiAgICAgICAgLnNlbGVjdCgncmVjdC5jYXRyZWN0JylcbiAgICAgICAgLmVhY2goXG4gICAgICAgICAgICAvKiogQHBhcmFtIHtDYXRlZ29yeVZpZXdNb2RlbH0gY2F0Vmlld01vZGVsICovXG4gICAgICAgICAgICBmdW5jdGlvbihjYXRWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2F0TW91c2VYID0gZDMubW91c2UodGhpcylbMF07XG4gICAgICAgICAgICAgICAgdmFyIGNhdE1vdXNlWSA9IGQzLm1vdXNlKHRoaXMpWzFdO1xuXG5cbiAgICAgICAgICAgICAgICBpZigtMiA8PSBjYXRNb3VzZVggJiYgY2F0TW91c2VYIDw9IGNhdFZpZXdNb2RlbC53aWR0aCArIDIgJiZcbiAgICAgICAgICAgICAgICAgICAgLTIgPD0gY2F0TW91c2VZICYmIGNhdE1vdXNlWSA8PSBjYXRWaWV3TW9kZWwuaGVpZ2h0ICsgMikge1xuICAgICAgICAgICAgICAgICAgICAvLyBTYXZlIG9mZiBpbml0aWFsIGRyYWcgaW5kZXhlcyBmb3IgY2F0ZWdvcmllc1xuICAgICAgICAgICAgICAgICAgICBkLmRyYWdDYXRlZ29yeURpc3BsYXlJbmQgPSBjYXRWaWV3TW9kZWwubW9kZWwuZGlzcGxheUluZDtcbiAgICAgICAgICAgICAgICAgICAgZC5pbml0aWFsRHJhZ0NhdGVnb3J5RGlzcGxheUluZHMgPSBkLm1vZGVsLmNhdGVnb3JpZXMubWFwKGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjLmRpc3BsYXlJbmQ7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgY2F0ZWdvcmllcyBkcmFnWSB0byBiZSB0aGUgY3VycmVudCB5IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgIGNhdFZpZXdNb2RlbC5tb2RlbC5kcmFnWSA9IGNhdFZpZXdNb2RlbC55O1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJhaXNlIGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgICAgIExpYi5yYWlzZVRvVG9wKHRoaXMucGFyZW50Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gR2V0IGJhbmQgZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcy5wYXJlbnROb2RlKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnNlbGVjdEFsbCgncmVjdC5iYW5kcmVjdCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAvKiogQHBhcmFtIHtDYXRlZ29yeUJhbmRWaWV3TW9kZWx9IGJhbmRWaWV3TW9kZWwgKi9cbiAgICAgICAgICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGJhbmRWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihiYW5kVmlld01vZGVsLnkgPCBjYXRNb3VzZVkgJiYgY2F0TW91c2VZIDw9IGJhbmRWaWV3TW9kZWwueSArIGJhbmRWaWV3TW9kZWwuaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQucG90ZW50aWFsQ2xpY2tCYW5kID0gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgIC8vIFVwZGF0ZSB0b3BsZXZlbCBkcmFnIGRpbWVuc2lvblxuICAgIGQucGFyY2F0c1ZpZXdNb2RlbC5kcmFnRGltZW5zaW9uID0gZDtcblxuICAgIC8vIFJlbW92ZSBob3ZlciBsYWJlbCBpZiBhbnlcbiAgICBGeC5sb25lVW5ob3ZlcihkLnBhcmNhdHNWaWV3TW9kZWwuZ3JhcGhEaXYuX2Z1bGxMYXlvdXQuX2hvdmVybGF5ZXIubm9kZSgpKTtcbn1cblxuLyoqXG4gKiBIYW5kbGUgZGltZW5zaW9uIGRyYWdcbiAqIEBwYXJhbSB7RGltZW5zaW9uVmlld01vZGVsfSBkXG4gKi9cbmZ1bmN0aW9uIGRyYWdEaW1lbnNpb24oZCkge1xuICAgIC8vIENoZWNrIGlmIGRyYWdnaW5nIGlzIHN1cHBvcnRlZFxuICAgIGlmKGQucGFyY2F0c1ZpZXdNb2RlbC5hcnJhbmdlbWVudCA9PT0gJ2ZpeGVkJykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZC5kcmFnSGFzTW92ZWQgPSB0cnVlO1xuXG4gICAgaWYoZC5kcmFnRGltZW5zaW9uRGlzcGxheUluZCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGRyYWdEaW1JbmQgPSBkLmRyYWdEaW1lbnNpb25EaXNwbGF5SW5kO1xuICAgIHZhciBwcmV2RGltSW5kID0gZHJhZ0RpbUluZCAtIDE7XG4gICAgdmFyIG5leHREaW1JbmQgPSBkcmFnRGltSW5kICsgMTtcblxuICAgIHZhciBkcmFnRGltZW5zaW9uID0gZC5wYXJjYXRzVmlld01vZGVsXG4gICAgICAgIC5kaW1lbnNpb25zW2RyYWdEaW1JbmRdO1xuXG4gICAgLy8gVXBkYXRlIGNhdGVnb3J5XG4gICAgaWYoZC5kcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kICE9PSBudWxsKSB7XG4gICAgICAgIHZhciBkcmFnQ2F0ZWdvcnkgPSBkcmFnRGltZW5zaW9uLmNhdGVnb3JpZXNbZC5kcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kXTtcblxuICAgICAgICAvLyBVcGRhdGUgZHJhZ1kgYnkgZHlcbiAgICAgICAgZHJhZ0NhdGVnb3J5Lm1vZGVsLmRyYWdZICs9IGQzLmV2ZW50LmR5O1xuICAgICAgICB2YXIgY2F0ZWdvcnlZID0gZHJhZ0NhdGVnb3J5Lm1vZGVsLmRyYWdZO1xuXG4gICAgICAgIC8vIENoZWNrIGZvciBjYXRlZ29yeSBkcmFnIHN3YXBzXG4gICAgICAgIHZhciBjYXREaXNwbGF5SW5kID0gZHJhZ0NhdGVnb3J5Lm1vZGVsLmRpc3BsYXlJbmQ7XG4gICAgICAgIHZhciBkaW1DYXRlZ29yeVZpZXdzID0gZHJhZ0RpbWVuc2lvbi5jYXRlZ29yaWVzO1xuXG4gICAgICAgIHZhciBjYXRBYm92ZSA9IGRpbUNhdGVnb3J5Vmlld3NbY2F0RGlzcGxheUluZCAtIDFdO1xuICAgICAgICB2YXIgY2F0QmVsb3cgPSBkaW1DYXRlZ29yeVZpZXdzW2NhdERpc3BsYXlJbmQgKyAxXTtcblxuICAgICAgICAvLyBDaGVjayBmb3Igb3ZlcmxhcCBhYm92ZVxuICAgICAgICBpZihjYXRBYm92ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZihjYXRlZ29yeVkgPCAoY2F0QWJvdmUueSArIGNhdEFib3ZlLmhlaWdodCAvIDIuMCkpIHtcbiAgICAgICAgICAgICAgICAvLyBTd2FwIGRpc3BsYXkgaW5kc1xuICAgICAgICAgICAgICAgIGRyYWdDYXRlZ29yeS5tb2RlbC5kaXNwbGF5SW5kID0gY2F0QWJvdmUubW9kZWwuZGlzcGxheUluZDtcbiAgICAgICAgICAgICAgICBjYXRBYm92ZS5tb2RlbC5kaXNwbGF5SW5kID0gY2F0RGlzcGxheUluZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNhdEJlbG93ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmKChjYXRlZ29yeVkgKyBkcmFnQ2F0ZWdvcnkuaGVpZ2h0KSA+IChjYXRCZWxvdy55ICsgY2F0QmVsb3cuaGVpZ2h0IC8gMi4wKSkge1xuICAgICAgICAgICAgICAgIC8vIFN3YXAgZGlzcGxheSBpbmRzXG4gICAgICAgICAgICAgICAgZHJhZ0NhdGVnb3J5Lm1vZGVsLmRpc3BsYXlJbmQgPSBjYXRCZWxvdy5tb2RlbC5kaXNwbGF5SW5kO1xuICAgICAgICAgICAgICAgIGNhdEJlbG93Lm1vZGVsLmRpc3BsYXlJbmQgPSBjYXREaXNwbGF5SW5kO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIGNhdGVnb3J5IGRyYWcgZGlzcGxheSBpbmRleFxuICAgICAgICBkLmRyYWdDYXRlZ29yeURpc3BsYXlJbmQgPSBkcmFnQ2F0ZWdvcnkubW9kZWwuZGlzcGxheUluZDtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgZGltZW5zaW9uIHBvc2l0aW9uXG4gICAgaWYoZC5kcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kID09PSBudWxsIHx8IGQucGFyY2F0c1ZpZXdNb2RlbC5hcnJhbmdlbWVudCA9PT0gJ2ZyZWVmb3JtJykge1xuICAgICAgICBkcmFnRGltZW5zaW9uLm1vZGVsLmRyYWdYID0gZDMuZXZlbnQueDtcblxuICAgICAgICAvLyBDaGVjayBmb3IgZGltZW5zaW9uIHN3YXBzXG4gICAgICAgIHZhciBwcmV2RGltZW5zaW9uID0gZC5wYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnNbcHJldkRpbUluZF07XG4gICAgICAgIHZhciBuZXh0RGltZW5zaW9uID0gZC5wYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnNbbmV4dERpbUluZF07XG5cbiAgICAgICAgaWYocHJldkRpbWVuc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpZihkcmFnRGltZW5zaW9uLm1vZGVsLmRyYWdYIDwgKHByZXZEaW1lbnNpb24ueCArIHByZXZEaW1lbnNpb24ud2lkdGgpKSB7XG4gICAgICAgICAgICAgICAgLy8gU3dhcCBkaXNwbGF5IGluZHNcbiAgICAgICAgICAgICAgICBkcmFnRGltZW5zaW9uLm1vZGVsLmRpc3BsYXlJbmQgPSBwcmV2RGltZW5zaW9uLm1vZGVsLmRpc3BsYXlJbmQ7XG4gICAgICAgICAgICAgICAgcHJldkRpbWVuc2lvbi5tb2RlbC5kaXNwbGF5SW5kID0gZHJhZ0RpbUluZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG5leHREaW1lbnNpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYoKGRyYWdEaW1lbnNpb24ubW9kZWwuZHJhZ1ggKyBkcmFnRGltZW5zaW9uLndpZHRoKSA+IG5leHREaW1lbnNpb24ueCkge1xuICAgICAgICAgICAgICAgIC8vIFN3YXAgZGlzcGxheSBpbmRzXG4gICAgICAgICAgICAgICAgZHJhZ0RpbWVuc2lvbi5tb2RlbC5kaXNwbGF5SW5kID0gbmV4dERpbWVuc2lvbi5tb2RlbC5kaXNwbGF5SW5kO1xuICAgICAgICAgICAgICAgIG5leHREaW1lbnNpb24ubW9kZWwuZGlzcGxheUluZCA9IGQuZHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgZHJhZyBkaXNwbGF5IGluZGV4XG4gICAgICAgIGQuZHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmQgPSBkcmFnRGltZW5zaW9uLm1vZGVsLmRpc3BsYXlJbmQ7XG4gICAgfVxuXG4gICAgLy8gVXBkYXRlIHZpZXcgbW9kZWxzXG4gICAgdXBkYXRlRGltZW5zaW9uVmlld01vZGVscyhkLnBhcmNhdHNWaWV3TW9kZWwpO1xuICAgIHVwZGF0ZVBhdGhWaWV3TW9kZWxzKGQucGFyY2F0c1ZpZXdNb2RlbCk7XG5cbiAgICAvLyBVcGRhdGUgc3ZnIGdlb21ldHJ5XG4gICAgdXBkYXRlU3ZnQ2F0ZWdvcmllcyhkLnBhcmNhdHNWaWV3TW9kZWwpO1xuICAgIHVwZGF0ZVN2Z1BhdGhzKGQucGFyY2F0c1ZpZXdNb2RlbCk7XG59XG5cblxuLyoqXG4gKiBIYW5kbGUgZGltZW5zaW9uIGRyYWcgZW5kXG4gKiBAcGFyYW0ge0RpbWVuc2lvblZpZXdNb2RlbH0gZFxuICovXG5mdW5jdGlvbiBkcmFnRGltZW5zaW9uRW5kKGQpIHtcbiAgICAvLyBDaGVjayBpZiBkcmFnZ2luZyBpcyBzdXBwb3J0ZWRcbiAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuYXJyYW5nZW1lbnQgPT09ICdmaXhlZCcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmKGQuZHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmQgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGQzLnNlbGVjdCh0aGlzKS5zZWxlY3RBbGwoJ3RleHQnKS5hdHRyKCdmb250LXdlaWdodCcsICdub3JtYWwnKTtcblxuICAgIC8vIENvbXB1dGUgcmVzdHlsZSBjb21tYW5kXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICB2YXIgcmVzdHlsZURhdGEgPSB7fTtcbiAgICB2YXIgdHJhY2VJbmQgPSBnZXRUcmFjZUluZGV4KGQucGFyY2F0c1ZpZXdNb2RlbCk7XG5cbiAgICAvLyAjIyMgSGFuZGxlIGRpbWVuc2lvbiByZW9yZGVyaW5nICMjI1xuICAgIHZhciBmaW5hbERyYWdEaW1lbnNpb25EaXNwbGF5SW5kcyA9IGQucGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zLm1hcChmdW5jdGlvbihkKSB7cmV0dXJuIGQuZGlzcGxheUluZDt9KTtcbiAgICB2YXIgYW55RGltc1Jlb3JkZXJlZCA9IGQuaW5pdGlhbERyYWdEaW1lbnNpb25EaXNwbGF5SW5kcy5zb21lKGZ1bmN0aW9uKGluaXREaW1EaXNwbGF5LCBkaW1JbmQpIHtcbiAgICAgICAgcmV0dXJuIGluaXREaW1EaXNwbGF5ICE9PSBmaW5hbERyYWdEaW1lbnNpb25EaXNwbGF5SW5kc1tkaW1JbmRdO1xuICAgIH0pO1xuXG4gICAgaWYoYW55RGltc1Jlb3JkZXJlZCkge1xuICAgICAgICBmaW5hbERyYWdEaW1lbnNpb25EaXNwbGF5SW5kcy5mb3JFYWNoKGZ1bmN0aW9uKGZpbmFsRGltRGlzcGxheSwgZGltSW5kKSB7XG4gICAgICAgICAgICB2YXIgY29udGFpbmVySW5kID0gZC5wYXJjYXRzVmlld01vZGVsLm1vZGVsLmRpbWVuc2lvbnNbZGltSW5kXS5jb250YWluZXJJbmQ7XG4gICAgICAgICAgICByZXN0eWxlRGF0YVsnZGltZW5zaW9uc1snICsgY29udGFpbmVySW5kICsgJ10uZGlzcGxheWluZGV4J10gPSBmaW5hbERpbURpc3BsYXk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vICMjIyBIYW5kbGUgY2F0ZWdvcnkgcmVvcmRlcmluZyAjIyNcbiAgICB2YXIgYW55Q2F0c1Jlb3JkZXJlZCA9IGZhbHNlO1xuICAgIGlmKGQuZHJhZ0NhdGVnb3J5RGlzcGxheUluZCAhPT0gbnVsbCkge1xuICAgICAgICB2YXIgZmluYWxEcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kcyA9IGQubW9kZWwuY2F0ZWdvcmllcy5tYXAoZnVuY3Rpb24oYykge1xuICAgICAgICAgICAgcmV0dXJuIGMuZGlzcGxheUluZDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYW55Q2F0c1Jlb3JkZXJlZCA9IGQuaW5pdGlhbERyYWdDYXRlZ29yeURpc3BsYXlJbmRzLnNvbWUoZnVuY3Rpb24oaW5pdENhdERpc3BsYXksIGNhdEluZCkge1xuICAgICAgICAgICAgcmV0dXJuIGluaXRDYXREaXNwbGF5ICE9PSBmaW5hbERyYWdDYXRlZ29yeURpc3BsYXlJbmRzW2NhdEluZF07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKGFueUNhdHNSZW9yZGVyZWQpIHtcbiAgICAgICAgICAgIC8vIFNvcnQgYSBzaGFsbG93IGNvcHkgb2YgdGhlIGNhdGVnb3J5IG1vZGVscyBieSBkaXNwbGF5IGluZGV4XG4gICAgICAgICAgICB2YXIgc29ydGVkQ2F0ZWdvcnlNb2RlbHMgPSBkLm1vZGVsLmNhdGVnb3JpZXMuc2xpY2UoKS5zb3J0KFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGEuZGlzcGxheUluZCAtIGIuZGlzcGxheUluZDsgfSk7XG5cbiAgICAgICAgICAgIC8vIEdldCBuZXcgY2F0ZWdvcnlhcnJheSBhbmQgdGlja3RleHQgdmFsdWVzXG4gICAgICAgICAgICB2YXIgbmV3Q2F0ZWdvcnlBcnJheSA9IHNvcnRlZENhdGVnb3J5TW9kZWxzLm1hcChmdW5jdGlvbih2KSB7IHJldHVybiB2LmNhdGVnb3J5VmFsdWU7IH0pO1xuICAgICAgICAgICAgdmFyIG5ld0NhdGVnb3J5TGFiZWxzID0gc29ydGVkQ2F0ZWdvcnlNb2RlbHMubWFwKGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHYuY2F0ZWdvcnlMYWJlbDsgfSk7XG5cbiAgICAgICAgICAgIHJlc3R5bGVEYXRhWydkaW1lbnNpb25zWycgKyBkLm1vZGVsLmNvbnRhaW5lckluZCArICddLmNhdGVnb3J5YXJyYXknXSA9IFtuZXdDYXRlZ29yeUFycmF5XTtcbiAgICAgICAgICAgIHJlc3R5bGVEYXRhWydkaW1lbnNpb25zWycgKyBkLm1vZGVsLmNvbnRhaW5lckluZCArICddLnRpY2t0ZXh0J10gPSBbbmV3Q2F0ZWdvcnlMYWJlbHNdO1xuICAgICAgICAgICAgcmVzdHlsZURhdGFbJ2RpbWVuc2lvbnNbJyArIGQubW9kZWwuY29udGFpbmVySW5kICsgJ10uY2F0ZWdvcnlvcmRlciddID0gJ2FycmF5JztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEhhbmRsZSBwb3RlbnRpYWwgY2xpY2sgZXZlbnRcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgaWYoZC5wYXJjYXRzVmlld01vZGVsLmhvdmVyaW5mb0l0ZW1zLmluZGV4T2YoJ3NraXAnKSA9PT0gLTEpIHtcbiAgICAgICAgaWYoIWQuZHJhZ0hhc01vdmVkICYmIGQucG90ZW50aWFsQ2xpY2tCYW5kKSB7XG4gICAgICAgICAgICBpZihkLnBhcmNhdHNWaWV3TW9kZWwuaG92ZXJvbiA9PT0gJ2NvbG9yJykge1xuICAgICAgICAgICAgICAgIGVtaXRQb2ludHNFdmVudENvbG9ySG92ZXJtb2RlKGQucG90ZW50aWFsQ2xpY2tCYW5kLCAncGxvdGx5X2NsaWNrJywgZDMuZXZlbnQuc291cmNlRXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlbWl0UG9pbnRzRXZlbnRDYXRlZ29yeUhvdmVybW9kZShkLnBvdGVudGlhbENsaWNrQmFuZCwgJ3Bsb3RseV9jbGljaycsIGQzLmV2ZW50LnNvdXJjZUV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIE51bGxpZnkgZHJhZyBzdGF0ZXNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgZC5tb2RlbC5kcmFnWCA9IG51bGw7XG4gICAgaWYoZC5kcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kICE9PSBudWxsKSB7XG4gICAgICAgIHZhciBkcmFnQ2F0ZWdvcnkgPSBkLnBhcmNhdHNWaWV3TW9kZWxcbiAgICAgICAgICAgIC5kaW1lbnNpb25zW2QuZHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmRdXG4gICAgICAgICAgICAuY2F0ZWdvcmllc1tkLmRyYWdDYXRlZ29yeURpc3BsYXlJbmRdO1xuXG4gICAgICAgIGRyYWdDYXRlZ29yeS5tb2RlbC5kcmFnWSA9IG51bGw7XG4gICAgICAgIGQuZHJhZ0NhdGVnb3J5RGlzcGxheUluZCA9IG51bGw7XG4gICAgfVxuXG4gICAgZC5kcmFnRGltZW5zaW9uRGlzcGxheUluZCA9IG51bGw7XG4gICAgZC5wYXJjYXRzVmlld01vZGVsLmRyYWdEaW1lbnNpb24gPSBudWxsO1xuICAgIGQuZHJhZ0hhc01vdmVkID0gbnVsbDtcbiAgICBkLnBvdGVudGlhbENsaWNrQmFuZCA9IG51bGw7XG5cbiAgICAvLyBVcGRhdGUgdmlldyBtb2RlbHNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS1cbiAgICB1cGRhdGVEaW1lbnNpb25WaWV3TW9kZWxzKGQucGFyY2F0c1ZpZXdNb2RlbCk7XG4gICAgdXBkYXRlUGF0aFZpZXdNb2RlbHMoZC5wYXJjYXRzVmlld01vZGVsKTtcblxuICAgIC8vIFBlcmZvcm0gdHJhbnNpdGlvblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHZhciB0cmFuc2l0aW9uID0gZDMudHJhbnNpdGlvbigpXG4gICAgICAgIC5kdXJhdGlvbigzMDApXG4gICAgICAgIC5lYXNlKCdjdWJpYy1pbi1vdXQnKTtcblxuICAgIHRyYW5zaXRpb25cbiAgICAgICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB1cGRhdGVTdmdDYXRlZ29yaWVzKGQucGFyY2F0c1ZpZXdNb2RlbCwgdHJ1ZSk7XG4gICAgICAgICAgICB1cGRhdGVTdmdQYXRocyhkLnBhcmNhdHNWaWV3TW9kZWwsIHRydWUpO1xuICAgICAgICB9KVxuICAgICAgICAuZWFjaCgnZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZihhbnlEaW1zUmVvcmRlcmVkIHx8IGFueUNhdHNSZW9yZGVyZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBQZXJmb3JtIHJlc3R5bGUgaWYgdGhlIG9yZGVyIG9mIGNhdGVnb3JpZXMgb3IgZGltZW5zaW9ucyBjaGFuZ2VkXG4gICAgICAgICAgICAgICAgUGxvdGx5LnJlc3R5bGUoZC5wYXJjYXRzVmlld01vZGVsLmdyYXBoRGl2LCByZXN0eWxlRGF0YSwgW3RyYWNlSW5kXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0ge1BhcmNhdHNWaWV3TW9kZWx9IHBhcmNhdHNWaWV3TW9kZWxcbiAqL1xuZnVuY3Rpb24gZ2V0VHJhY2VJbmRleChwYXJjYXRzVmlld01vZGVsKSB7XG4gICAgdmFyIHRyYWNlSW5kO1xuICAgIHZhciBhbGxUcmFjZXMgPSBwYXJjYXRzVmlld01vZGVsLmdyYXBoRGl2Ll9mdWxsRGF0YTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgYWxsVHJhY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKHBhcmNhdHNWaWV3TW9kZWwua2V5ID09PSBhbGxUcmFjZXNbaV0udWlkKSB7XG4gICAgICAgICAgICB0cmFjZUluZCA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJhY2VJbmQ7XG59XG5cbi8qKiBVcGRhdGUgdGhlIHN2ZyBwYXRocyBmb3IgdmlldyBtb2RlbFxuICogQHBhcmFtIHtQYXJjYXRzVmlld01vZGVsfSBwYXJjYXRzVmlld01vZGVsXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGhhc1RyYW5zaXRpb24gV2hldGhlciB0byB1cGRhdGUgZWxlbWVudCB3aXRoIHRyYW5zaXRpb25cbiAqL1xuZnVuY3Rpb24gdXBkYXRlU3ZnUGF0aHMocGFyY2F0c1ZpZXdNb2RlbCwgaGFzVHJhbnNpdGlvbikge1xuICAgIGlmKGhhc1RyYW5zaXRpb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBoYXNUcmFuc2l0aW9uID0gZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdHJhbnNpdGlvbihzZWxlY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIGhhc1RyYW5zaXRpb24gPyBzZWxlY3Rpb24udHJhbnNpdGlvbigpIDogc2VsZWN0aW9uO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSBiaW5kaW5nXG4gICAgcGFyY2F0c1ZpZXdNb2RlbC5wYXRoU2VsZWN0aW9uLmRhdGEoZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gZC5wYXRocztcbiAgICB9LCBrZXkpO1xuXG4gICAgLy8gVXBkYXRlIHBhdGhzXG4gICAgdHJhbnNpdGlvbihwYXJjYXRzVmlld01vZGVsLnBhdGhTZWxlY3Rpb24pLmF0dHIoJ2QnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBkLnN2Z0Q7XG4gICAgfSk7XG59XG5cbi8qKiBVcGRhdGUgdGhlIHN2ZyBwYXRocyBmb3IgdmlldyBtb2RlbFxuICogQHBhcmFtIHtQYXJjYXRzVmlld01vZGVsfSBwYXJjYXRzVmlld01vZGVsXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGhhc1RyYW5zaXRpb24gV2hldGhlciB0byB1cGRhdGUgZWxlbWVudCB3aXRoIHRyYW5zaXRpb25cbiAqL1xuZnVuY3Rpb24gdXBkYXRlU3ZnQ2F0ZWdvcmllcyhwYXJjYXRzVmlld01vZGVsLCBoYXNUcmFuc2l0aW9uKSB7XG4gICAgaWYoaGFzVHJhbnNpdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGhhc1RyYW5zaXRpb24gPSBmYWxzZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0cmFuc2l0aW9uKHNlbGVjdGlvbikge1xuICAgICAgICByZXR1cm4gaGFzVHJhbnNpdGlvbiA/IHNlbGVjdGlvbi50cmFuc2l0aW9uKCkgOiBzZWxlY3Rpb247XG4gICAgfVxuXG4gICAgLy8gVXBkYXRlIGJpbmRpbmdcbiAgICBwYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvblNlbGVjdGlvblxuICAgICAgICAuZGF0YShmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5kaW1lbnNpb25zO1xuICAgICAgICB9LCBrZXkpO1xuXG4gICAgdmFyIGNhdGVnb3J5U2VsZWN0aW9uID0gcGFyY2F0c1ZpZXdNb2RlbC5kaW1lbnNpb25TZWxlY3Rpb25cbiAgICAgICAgLnNlbGVjdEFsbCgnZy5jYXRlZ29yeScpXG4gICAgICAgIC5kYXRhKGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5jYXRlZ29yaWVzO30sIGtleSk7XG5cbiAgICAvLyBVcGRhdGUgZGltZW5zaW9uIHBvc2l0aW9uXG4gICAgdHJhbnNpdGlvbihwYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvblNlbGVjdGlvbilcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyBkLnggKyAnLCAwKSc7XG4gICAgICAgIH0pO1xuXG4gICAgLy8gVXBkYXRlIGNhdGVnb3J5IHBvc2l0aW9uXG4gICAgdHJhbnNpdGlvbihjYXRlZ29yeVNlbGVjdGlvbilcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiAndHJhbnNsYXRlKDAsICcgKyBkLnkgKyAnKSc7XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIGRpbUxhYmVsU2VsZWN0aW9uID0gY2F0ZWdvcnlTZWxlY3Rpb24uc2VsZWN0KCcuZGltbGFiZWwnKTtcblxuICAgIC8vICMjIyBVcGRhdGUgZGltZW5zaW9uIGxhYmVsXG4gICAgLy8gT25seSB0aGUgdG9wLW1vc3QgZGlzcGxheSBjYXRlZ29yeSBzaG91bGQgaGF2ZSB0aGUgZGltZW5zaW9uIGxhYmVsXG4gICAgZGltTGFiZWxTZWxlY3Rpb25cbiAgICAgICAgLnRleHQoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgaWYoaSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIEFkZCBkaW1lbnNpb24gbGFiZWwgYWJvdmUgdG9wbW9zdCBjYXRlZ29yeVxuICAgICAgICAgICAgICAgIHJldHVybiBkLnBhcmNhdHNWaWV3TW9kZWwubW9kZWwuZGltZW5zaW9uc1tkLm1vZGVsLmRpbWVuc2lvbkluZF0uZGltZW5zaW9uTGFiZWw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIC8vIFVwZGF0ZSBjYXRlZ29yeSBsYWJlbFxuICAgIC8vIENhdGVnb3JpZXMgaW4gdGhlIHJpZ2h0LW1vc3QgZGlzcGxheSBkaW1lbnNpb24gaGF2ZSB0aGVpciBsYWJlbHMgb25cbiAgICAvLyB0aGUgcmlnaHQsIGFsbCBvdGhlcnMgb24gdGhlIGxlZnRcbiAgICB2YXIgY2F0TGFiZWxTZWxlY3Rpb24gPSBjYXRlZ29yeVNlbGVjdGlvbi5zZWxlY3QoJy5jYXRsYWJlbCcpO1xuICAgIGNhdExhYmVsU2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsXG4gICAgICAgICAgICBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgaWYoY2F0SW5SaWdodERpbShkKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBsYWJlbCB0byB0aGUgcmlnaHQgb2YgY2F0ZWdvcnlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdzdGFydCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgbGFiZWwgdG8gdGhlIGxlZnQgb2YgY2F0ZWdvcnlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdlbmQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd4JyxcbiAgICAgICAgICAgIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBpZihjYXRJblJpZ2h0RGltKGQpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFBsYWNlIGxhYmVsIHRvIHRoZSByaWdodCBvZiBjYXRlZ29yeVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZC53aWR0aCArIDU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgbGFiZWwgdG8gdGhlIGxlZnQgb2YgY2F0ZWdvcnlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIC01O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBhdHRyaXVidXRlcyBvZiA8dHNwYW4+IGVsZW1lbnRzXG4gICAgICAgICAgICB2YXIgbmV3WDtcbiAgICAgICAgICAgIHZhciBuZXdBbmNob3I7XG4gICAgICAgICAgICBpZihjYXRJblJpZ2h0RGltKGQpKSB7XG4gICAgICAgICAgICAgICAgLy8gUGxhY2UgbGFiZWwgdG8gdGhlIHJpZ2h0IG9mIGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgbmV3WCA9IGQud2lkdGggKyA1O1xuICAgICAgICAgICAgICAgIG5ld0FuY2hvciA9ICdzdGFydCc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFBsYWNlIGxhYmVsIHRvIHRoZSBsZWZ0IG9mIGNhdGVnb3J5XG4gICAgICAgICAgICAgICAgbmV3WCA9IC01O1xuICAgICAgICAgICAgICAgIG5ld0FuY2hvciA9ICdlbmQnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAgICAgLnNlbGVjdEFsbCgndHNwYW4nKVxuICAgICAgICAgICAgICAgIC5hdHRyKCd4JywgbmV3WClcbiAgICAgICAgICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLCBuZXdBbmNob3IpO1xuICAgICAgICB9KTtcblxuICAgIC8vIFVwZGF0ZSBiYW5kc1xuICAgIC8vIEluaXRpYWxpemUgY29sb3IgYmFuZCByZWN0c1xuICAgIHZhciBiYW5kU2VsZWN0aW9uID0gY2F0ZWdvcnlTZWxlY3Rpb25cbiAgICAgICAgLnNlbGVjdEFsbCgncmVjdC5iYW5kcmVjdCcpXG4gICAgICAgIC5kYXRhKFxuICAgICAgICAgICAgLyoqIEBwYXJhbSB7Q2F0ZWdvcnlWaWV3TW9kZWx9IGNhdFZpZXdNb2RlbCovXG4gICAgICAgICAgICBmdW5jdGlvbihjYXRWaWV3TW9kZWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2F0Vmlld01vZGVsLmJhbmRzO1xuICAgICAgICAgICAgfSwga2V5KTtcblxuICAgIHZhciBiYW5kc1NlbGVjdGlvbkVudGVyID0gYmFuZFNlbGVjdGlvbi5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuYXR0cignY2xhc3MnLCAnYmFuZHJlY3QnKVxuICAgICAgICAuYXR0cignY3Vyc29yJywgJ21vdmUnKVxuICAgICAgICAuYXR0cignc3Ryb2tlLW9wYWNpdHknLCAwKVxuICAgICAgICAuYXR0cignZmlsbCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLmNvbG9yO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignZmlsbC1vcGFjaXR5JywgMCk7XG5cbiAgICBiYW5kU2VsZWN0aW9uXG4gICAgICAgIC5hdHRyKCdmaWxsJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuY29sb3I7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLndpZHRoO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuaGVpZ2h0O1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cigneScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLnk7XG4gICAgICAgIH0pO1xuXG4gICAgc3R5bGVCYW5kc05vSG92ZXIoYmFuZHNTZWxlY3Rpb25FbnRlcik7XG5cbiAgICAvLyBSYWlzZSBiYW5kcyB0byB0aGUgdG9wXG4gICAgYmFuZFNlbGVjdGlvbi5lYWNoKGZ1bmN0aW9uKCkge0xpYi5yYWlzZVRvVG9wKHRoaXMpO30pO1xuXG4gICAgLy8gUmVtb3ZlIHVudXNlZCBiYW5kc1xuICAgIGJhbmRTZWxlY3Rpb24uZXhpdCgpLnJlbW92ZSgpO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIFBhcmNhdHNWaWV3TW9kZWwgdHJhY2VzXG4gKiBAcGFyYW0ge09iamVjdH0gZ3JhcGhEaXZcbiAqICBUb3AtbGV2ZWwgZ3JhcGggZGl2IGVsZW1lbnRcbiAqIEBwYXJhbSB7TGF5b3V0fSBsYXlvdXRcbiAqICBTVkcgbGF5b3V0IG9iamVjdFxuICogQHBhcmFtIHtBcnJheS48UGFyY2F0c01vZGVsPn0gd3JhcHBlZFBhcmNhdHNNb2RlbFxuICogIFdyYXBwZWQgUGFyY2F0c01vZGVsIGZvciB0aGlzIHRyYWNlXG4gKiBAcmV0dXJuIHtQYXJjYXRzVmlld01vZGVsfVxuICovXG5mdW5jdGlvbiBjcmVhdGVQYXJjYXRzVmlld01vZGVsKGdyYXBoRGl2LCBsYXlvdXQsIHdyYXBwZWRQYXJjYXRzTW9kZWwpIHtcbiAgICAvLyBVbndyYXAgbW9kZWxcbiAgICB2YXIgcGFyY2F0c01vZGVsID0gd3JhcHBlZFBhcmNhdHNNb2RlbFswXTtcblxuICAgIC8vIENvbXB1dGUgbWFyZ2luXG4gICAgdmFyIG1hcmdpbiA9IGxheW91dC5tYXJnaW4gfHwge2w6IDgwLCByOiA4MCwgdDogMTAwLCBiOiA4MH07XG5cbiAgICAvLyBDb21wdXRlIHBpeGVsIHBvc2l0aW9uL2V4dGVudHNcbiAgICB2YXIgdHJhY2UgPSBwYXJjYXRzTW9kZWwudHJhY2U7XG4gICAgdmFyIGRvbWFpbiA9IHRyYWNlLmRvbWFpbjtcbiAgICB2YXIgZmlndXJlV2lkdGggPSBsYXlvdXQud2lkdGg7XG4gICAgdmFyIGZpZ3VyZUhlaWdodCA9IGxheW91dC5oZWlnaHQ7XG4gICAgdmFyIHRyYWNlV2lkdGggPSBNYXRoLmZsb29yKGZpZ3VyZVdpZHRoICogKGRvbWFpbi54WzFdIC0gZG9tYWluLnhbMF0pKTtcbiAgICB2YXIgdHJhY2VIZWlnaHQgPSBNYXRoLmZsb29yKGZpZ3VyZUhlaWdodCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKSk7XG4gICAgdmFyIHRyYWNlWCA9IGRvbWFpbi54WzBdICogZmlndXJlV2lkdGggKyBtYXJnaW4ubDtcbiAgICB2YXIgdHJhY2VZID0gbGF5b3V0LmhlaWdodCAtIGRvbWFpbi55WzFdICogbGF5b3V0LmhlaWdodCArIG1hcmdpbi50O1xuXG4gICAgLy8gSGFuZGxlIHBhdGggc2hhcGVcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLVxuICAgIHZhciBwYXRoU2hhcGUgPSB0cmFjZS5saW5lLnNoYXBlO1xuXG4gICAgLy8gSGFuZGxlIGhvdmVyIGluZm9cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLVxuICAgIHZhciBob3ZlcmluZm9JdGVtcztcbiAgICBpZih0cmFjZS5ob3ZlcmluZm8gPT09ICdhbGwnKSB7XG4gICAgICAgIGhvdmVyaW5mb0l0ZW1zID0gWydjb3VudCcsICdwcm9iYWJpbGl0eSddO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhvdmVyaW5mb0l0ZW1zID0gKHRyYWNlLmhvdmVyaW5mbyB8fCAnJykuc3BsaXQoJysnKTtcbiAgICB9XG5cbiAgICAvLyBDb25zdHJ1Y3QgcGFyY2F0c1ZpZXdNb2RlbFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdmFyIHBhcmNhdHNWaWV3TW9kZWwgPSB7XG4gICAgICAgIHRyYWNlOiB0cmFjZSxcbiAgICAgICAga2V5OiB0cmFjZS51aWQsXG4gICAgICAgIG1vZGVsOiBwYXJjYXRzTW9kZWwsXG4gICAgICAgIHg6IHRyYWNlWCxcbiAgICAgICAgeTogdHJhY2VZLFxuICAgICAgICB3aWR0aDogdHJhY2VXaWR0aCxcbiAgICAgICAgaGVpZ2h0OiB0cmFjZUhlaWdodCxcbiAgICAgICAgaG92ZXJvbjogdHJhY2UuaG92ZXJvbixcbiAgICAgICAgaG92ZXJpbmZvSXRlbXM6IGhvdmVyaW5mb0l0ZW1zLFxuICAgICAgICBhcnJhbmdlbWVudDogdHJhY2UuYXJyYW5nZW1lbnQsXG4gICAgICAgIGJ1bmRsZWNvbG9yczogdHJhY2UuYnVuZGxlY29sb3JzLFxuICAgICAgICBzb3J0cGF0aHM6IHRyYWNlLnNvcnRwYXRocyxcbiAgICAgICAgbGFiZWxmb250OiB0cmFjZS5sYWJlbGZvbnQsXG4gICAgICAgIGNhdGVnb3J5bGFiZWxmb250OiB0cmFjZS50aWNrZm9udCxcbiAgICAgICAgcGF0aFNoYXBlOiBwYXRoU2hhcGUsXG4gICAgICAgIGRyYWdEaW1lbnNpb246IG51bGwsXG4gICAgICAgIG1hcmdpbjogbWFyZ2luLFxuICAgICAgICBwYXRoczogW10sXG4gICAgICAgIGRpbWVuc2lvbnM6IFtdLFxuICAgICAgICBncmFwaERpdjogZ3JhcGhEaXYsXG4gICAgICAgIHRyYWNlU2VsZWN0aW9uOiBudWxsLFxuICAgICAgICBwYXRoU2VsZWN0aW9uOiBudWxsLFxuICAgICAgICBkaW1lbnNpb25TZWxlY3Rpb246IG51bGxcbiAgICB9O1xuXG4gICAgLy8gVXBkYXRlIGRpbWVuc2lvbiB2aWV3IG1vZGVscyBpZiB3ZSBoYXZlIGF0IGxlYXN0IDEgZGltZW5zaW9uXG4gICAgaWYocGFyY2F0c01vZGVsLmRpbWVuc2lvbnMpIHtcbiAgICAgICAgdXBkYXRlRGltZW5zaW9uVmlld01vZGVscyhwYXJjYXRzVmlld01vZGVsKTtcblxuICAgICAgICAvLyBVcGRhdGUgcGF0aCB2aWV3IG1vZGVscyBpZiB3ZSBoYXZlIGF0IGxlYXN0IDIgZGltZW5zaW9uc1xuICAgICAgICB1cGRhdGVQYXRoVmlld01vZGVscyhwYXJjYXRzVmlld01vZGVsKTtcbiAgICB9XG4gICAgLy8gSW5zaWRlIGEgY2F0ZWdvcmllcyB2aWV3IG1vZGVsXG4gICAgcmV0dXJuIHBhcmNhdHNWaWV3TW9kZWw7XG59XG5cbi8qKlxuICogQnVpbGQgdGhlIFNWRyBzdHJpbmcgdG8gcmVwcmVzZW50cyBhIHBhcmFsbGVsIGNhdGVnb3JpZXMgcGF0aFxuICogQHBhcmFtIHtBcnJheS48TnVtYmVyPn0gbGVmdFhQb3NpdGlvbnNcbiAqICBBcnJheSBvZiB0aGUgeCBwb3NpdGlvbnMgb2YgdGhlIGxlZnQgZWRnZSBvZiBlYWNoIGRpbWVuc2lvbiAoaW4gZGlzcGxheSBvcmRlcilcbiAqIEBwYXJhbSB7QXJyYXkuPE51bWJlcj59IHBhdGhZc1xuICogIEFycmF5IG9mIHRoZSB5IHBvc2l0aW9ucyBvZiB0aGUgdG9wIG9mIHRoZSBwYXRoIGF0IGVhY2ggZGltZW5zaW9uIChpbiBkaXNwbGF5IG9yZGVyKVxuICogQHBhcmFtIHtBcnJheS48TnVtYmVyPn0gZGltV2lkdGhzXG4gKiAgQXJyYXkgb2YgdGhlIHdpZHRocyBvZiBlYWNoIGRpbWVuc2lvbiBpbiBkaXNwbGF5IG9yZGVyXG4gKiBAcGFyYW0ge051bWJlcn0gcGF0aEhlaWdodFxuICogIFRoZSBoZWlnaHQgb2YgdGhlIHBhdGggaW4gcGl4ZWxzXG4gKiBAcGFyYW0ge051bWJlcn0gY3VydmF0dXJlXG4gKiAgVGhlIGN1cnZhdHVyZSBmYWN0b3IgZm9yIHRoZSBwYXRoLiAwIHJlc3VsdHMgaW4gYSBzdHJhaWdodCBsaW5lIGFuZCB2YWx1ZXMgZ3JlYXRlciB0aGFuIHplcm8gcmVzdWx0IGluIGN1cnZlZCBwYXRoc1xuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiBidWlsZFN2Z1BhdGgobGVmdFhQb3NpdGlvbnMsIHBhdGhZcywgZGltV2lkdGhzLCBwYXRoSGVpZ2h0LCBjdXJ2YXR1cmUpIHtcbiAgICAvLyBDb21wdXRlIHRoZSB4IG1pZHBvaW50IG9mIGVhY2ggcGF0aCBzZWdtZW50XG4gICAgdmFyIHhSZWZQb2ludHMxID0gW107XG4gICAgdmFyIHhSZWZQb2ludHMyID0gW107XG4gICAgdmFyIHJlZkludGVycG9sYXRvcjtcbiAgICB2YXIgZDtcblxuICAgIGZvcihkID0gMDsgZCA8IGRpbVdpZHRocy5sZW5ndGggLSAxOyBkKyspIHtcbiAgICAgICAgcmVmSW50ZXJwb2xhdG9yID0gZDMuaW50ZXJwb2xhdGVOdW1iZXIoZGltV2lkdGhzW2RdICsgbGVmdFhQb3NpdGlvbnNbZF0sIGxlZnRYUG9zaXRpb25zW2QgKyAxXSk7XG4gICAgICAgIHhSZWZQb2ludHMxLnB1c2gocmVmSW50ZXJwb2xhdG9yKGN1cnZhdHVyZSkpO1xuICAgICAgICB4UmVmUG9pbnRzMi5wdXNoKHJlZkludGVycG9sYXRvcigxIC0gY3VydmF0dXJlKSk7XG4gICAgfVxuXG4gICAgLy8gTW92ZSB0byB0b3Agb2YgcGF0aCBvbiBsZWZ0IGVkZ2Ugb2YgbGVmdC1tb3N0IGNhdGVnb3J5XG4gICAgdmFyIHN2Z0QgPSAnTSAnICsgbGVmdFhQb3NpdGlvbnNbMF0gKyAnLCcgKyBwYXRoWXNbMF07XG5cbiAgICAvLyBIb3Jpem9udGFsIGxpbmUgdG8gcmlnaHQgZWRnZVxuICAgIHN2Z0QgKz0gJ2wnICsgZGltV2lkdGhzWzBdICsgJywwICc7XG5cbiAgICAvLyBIb3Jpem9udGFsIGxpbmUgdG8gcmlnaHQgZWRnZVxuICAgIGZvcihkID0gMTsgZCA8IGRpbVdpZHRocy5sZW5ndGg7IGQrKykge1xuICAgICAgICAvLyBDdXJ2ZSB0byBsZWZ0IGVkZ2Ugb2YgY2F0ZWdvcnlcbiAgICAgICAgc3ZnRCArPSAnQycgKyB4UmVmUG9pbnRzMVtkIC0gMV0gKyAnLCcgKyBwYXRoWXNbZCAtIDFdICtcbiAgICAgICAgICAgICAgJyAnICsgeFJlZlBvaW50czJbZCAtIDFdICsgJywnICsgcGF0aFlzW2RdICtcbiAgICAgICAgICAgICAgJyAnICsgbGVmdFhQb3NpdGlvbnNbZF0gKyAnLCcgKyBwYXRoWXNbZF07XG5cbiAgICAgICAgLy8gc3ZnRCArPSAnTCcgKyBsZWZ0WFBvc2l0aW9uc1tkXSArICcsJyArIHBhdGhZc1tkXTtcblxuICAgICAgICAvLyBIb3Jpem9udGFsIGxpbmUgdG8gcmlnaHQgZWRnZVxuICAgICAgICBzdmdEICs9ICdsJyArIGRpbVdpZHRoc1tkXSArICcsMCAnO1xuICAgIH1cblxuICAgIC8vIExpbmUgZG93blxuICAgIHN2Z0QgKz0gJ2wnICsgJzAsJyArIHBhdGhIZWlnaHQgKyAnICc7XG5cbiAgICAvLyBMaW5lIHRvIGxlZnQgZWRnZSBvZiByaWdodC1tb3N0IGNhdGVnb3J5XG4gICAgc3ZnRCArPSAnbCAtJyArIGRpbVdpZHRoc1tkaW1XaWR0aHMubGVuZ3RoIC0gMV0gKyAnLDAgJztcblxuICAgIGZvcihkID0gZGltV2lkdGhzLmxlbmd0aCAtIDI7IGQgPj0gMDsgZC0tKSB7XG4gICAgICAgIC8vIEN1cnZlIHRvIHJpZ2h0IGVkZ2Ugb2YgY2F0ZWdvcnlcbiAgICAgICAgc3ZnRCArPSAnQycgKyB4UmVmUG9pbnRzMltkXSArICcsJyArIChwYXRoWXNbZCArIDFdICsgcGF0aEhlaWdodCkgK1xuICAgICAgICAgICAgICcgJyArIHhSZWZQb2ludHMxW2RdICsgJywnICsgKHBhdGhZc1tkXSArIHBhdGhIZWlnaHQpICtcbiAgICAgICAgICAgICAnICcgKyAobGVmdFhQb3NpdGlvbnNbZF0gKyBkaW1XaWR0aHNbZF0pICsgJywnICsgKHBhdGhZc1tkXSArIHBhdGhIZWlnaHQpO1xuXG4gICAgICAgIC8vIHN2Z0QgKz0gJ0wnICsgKGxlZnRYUG9zaXRpb25zW2RdICsgZGltV2lkdGhzW2RdKSArICcsJyArIChwYXRoWXNbZF0gKyBwYXRoSGVpZ2h0KTtcblxuICAgICAgICAvLyBIb3Jpem9udGFsIGxpbmUgdG8gcmlnaHQgZWRnZVxuICAgICAgICBzdmdEICs9ICdsLScgKyBkaW1XaWR0aHNbZF0gKyAnLDAgJztcbiAgICB9XG5cbiAgICAvLyBDbG9zZSBwYXRoXG4gICAgc3ZnRCArPSAnWic7XG4gICAgcmV0dXJuIHN2Z0Q7XG59XG5cbi8qKlxuICogVXBkYXRlIHRoZSBwYXRoIHZpZXcgbW9kZWxzIGJhc2VkIG9uIHRoZSBkaW1lbnNpb24gdmlldyBtb2RlbHMgaW4gYSBQYXJjYXRzVmlld01vZGVsXG4gKlxuICogQHBhcmFtIHtQYXJjYXRzVmlld01vZGVsfSBwYXJjYXRzVmlld01vZGVsXG4gKiAgVmlldyBtb2RlbCBmb3IgdHJhY2VcbiAqL1xuZnVuY3Rpb24gdXBkYXRlUGF0aFZpZXdNb2RlbHMocGFyY2F0c1ZpZXdNb2RlbCkge1xuICAgIC8vIEluaXRpYWxpemUgYW4gYXJyYXkgb2YgdGhlIHkgcG9zaXRpb24gb2YgdGhlIHRvcCBvZiB0aGUgbmV4dCBwYXRoIHRvIGJlIGFkZGVkIHRvIGVhY2ggY2F0ZWdvcnkuXG4gICAgLy9cbiAgICAvLyBuZXh0WVBvc2l0aW9uc1tkXVtjXSBpcyB0aGUgeSBwb3NpdGlvbiBvZiB0aGUgbmV4dCBwYXRoIHRocm91Z2ggY2F0ZWdvcnkgd2l0aCBpbmRleCBjIG9mIGRpbWVuc2lvbiB3aXRoIGluZGV4IGRcbiAgICB2YXIgZGltZW5zaW9uVmlld01vZGVscyA9IHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9ucztcbiAgICB2YXIgcGFyY2F0c01vZGVsID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbDtcbiAgICB2YXIgbmV4dFlQb3NpdGlvbnMgPSBkaW1lbnNpb25WaWV3TW9kZWxzLm1hcChcbiAgICAgICAgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuY2F0ZWdvcmllcy5tYXAoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24oYykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYy55O1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgIC8vIEFycmF5IGZyb20gY2F0ZWdvcnkgaW5kZXggdG8gY2F0ZWdvcnkgZGlzcGxheSBpbmRleCBmb3IgZWFjaCB0cnVlIGRpbWVuc2lvbiBpbmRleFxuICAgIHZhciBjYXRUb0Rpc3BsYXlJbmRQZXJEaW0gPSBwYXJjYXRzVmlld01vZGVsLm1vZGVsLmRpbWVuc2lvbnMubWFwKFxuICAgICAgICBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5jYXRlZ29yaWVzLm1hcChmdW5jdGlvbihjKSB7cmV0dXJuIGMuZGlzcGxheUluZDt9KTtcbiAgICAgICAgfSk7XG5cbiAgICAvLyBBcnJheSBmcm9tIHRydWUgZGltZW5zaW9uIGluZGV4IHRvIGRpbWVuc2lvbiBkaXNwbGF5IGluZGV4XG4gICAgdmFyIGRpbVRvRGlzcGxheUluZCA9IHBhcmNhdHNWaWV3TW9kZWwubW9kZWwuZGltZW5zaW9ucy5tYXAoZnVuY3Rpb24oZCkge3JldHVybiBkLmRpc3BsYXlJbmQ7fSk7XG4gICAgdmFyIGRpc3BsYXlUb0RpbUluZCA9IHBhcmNhdHNWaWV3TW9kZWwuZGltZW5zaW9ucy5tYXAoZnVuY3Rpb24oZCkge3JldHVybiBkLm1vZGVsLmRpbWVuc2lvbkluZDt9KTtcblxuICAgIC8vIEFycmF5IG9mIHRoZSB4IHBvc2l0aW9uIG9mIHRoZSBsZWZ0IGVkZ2Ugb2YgdGhlIHJlY3RhbmdsZXMgZm9yIGVhY2ggZGltZW5zaW9uXG4gICAgdmFyIGxlZnRYUG9zaXRpb25zID0gZGltZW5zaW9uVmlld01vZGVscy5tYXAoXG4gICAgICAgIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLng7XG4gICAgICAgIH0pO1xuXG4gICAgLy8gQ29tcHV0ZSBkaW1lbnNpb24gd2lkdGhzXG4gICAgdmFyIGRpbVdpZHRocyA9IGRpbWVuc2lvblZpZXdNb2RlbHMubWFwKGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC53aWR0aDt9KTtcblxuICAgIC8vIEJ1aWxkIHNvcnRlZCBBcnJheSBvZiBQYXRoTW9kZWwgb2JqZWN0c1xuICAgIHZhciBwYXRoTW9kZWxzID0gW107XG4gICAgZm9yKHZhciBwIGluIHBhcmNhdHNNb2RlbC5wYXRocykge1xuICAgICAgICBpZihwYXJjYXRzTW9kZWwucGF0aHMuaGFzT3duUHJvcGVydHkocCkpIHtcbiAgICAgICAgICAgIHBhdGhNb2RlbHMucHVzaChwYXJjYXRzTW9kZWwucGF0aHNbcF0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ29tcHV0ZSBjYXRlZ29yeSBkaXNwbGF5IGluZHMgdG8gdXNlIGZvciBzb3J0aW5nIHBhdGhzXG4gICAgZnVuY3Rpb24gcGF0aERpc3BsYXlDYXRlZ29yeUluZHMocGF0aE1vZGVsKSB7XG4gICAgICAgIHZhciBkaW1lbnNpb25JbmRzID0gcGF0aE1vZGVsLmNhdGVnb3J5SW5kcy5tYXAoZnVuY3Rpb24oY2F0SW5kLCBkaW1JbmQpIHtyZXR1cm4gY2F0VG9EaXNwbGF5SW5kUGVyRGltW2RpbUluZF1bY2F0SW5kXTt9KTtcbiAgICAgICAgdmFyIGRpc3BsYXlJbmRzID0gZGlzcGxheVRvRGltSW5kLm1hcChmdW5jdGlvbihkaW1JbmQpIHtcbiAgICAgICAgICAgIHJldHVybiBkaW1lbnNpb25JbmRzW2RpbUluZF07XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZGlzcGxheUluZHM7XG4gICAgfVxuXG4gICAgLy8gU29ydCBpbiBhc2NlbmRpbmcgb3JkZXIgYnkgZGlzcGxheSBpbmRleCBhcnJheVxuICAgIHBhdGhNb2RlbHMuc29ydChmdW5jdGlvbih2MSwgdjIpIHtcbiAgICAgICAgLy8gQnVpbGQgZGlzcGxheSBpbmRzIGZvciBlYWNoIHBhdGhcbiAgICAgICAgdmFyIHNvcnRBcnJheTEgPSBwYXRoRGlzcGxheUNhdGVnb3J5SW5kcyh2MSk7XG4gICAgICAgIHZhciBzb3J0QXJyYXkyID0gcGF0aERpc3BsYXlDYXRlZ29yeUluZHModjIpO1xuXG4gICAgICAgIC8vIEhhbmRsZSBwYXRoIHNvcnQgb3JkZXJcbiAgICAgICAgaWYocGFyY2F0c1ZpZXdNb2RlbC5zb3J0cGF0aHMgPT09ICdiYWNrd2FyZCcpIHtcbiAgICAgICAgICAgIHNvcnRBcnJheTEucmV2ZXJzZSgpO1xuICAgICAgICAgICAgc29ydEFycmF5Mi5yZXZlcnNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBcHBlbmQgdGhlIGZpcnN0IHZhbHVlIGluZGV4IG9mIHRoZSBwYXRoIHRvIGJyZWFrIHRpZXNcbiAgICAgICAgc29ydEFycmF5MS5wdXNoKHYxLnZhbHVlSW5kc1swXSk7XG4gICAgICAgIHNvcnRBcnJheTIucHVzaCh2Mi52YWx1ZUluZHNbMF0pO1xuXG4gICAgICAgIC8vIEhhbmRsZSBjb2xvciBidW5kbGluZ1xuICAgICAgICBpZihwYXJjYXRzVmlld01vZGVsLmJ1bmRsZWNvbG9ycykge1xuICAgICAgICAgICAgLy8gUHJlcGVuZCBzb3J0IGFycmF5IHdpdGggdGhlIHJhdyBjb2xvciB2YWx1ZVxuICAgICAgICAgICAgc29ydEFycmF5MS51bnNoaWZ0KHYxLnJhd0NvbG9yKTtcbiAgICAgICAgICAgIHNvcnRBcnJheTIudW5zaGlmdCh2Mi5yYXdDb2xvcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjb2xvcnMgZXF1YWwsIHNvcnQgYnkgZGlzcGxheSBjYXRlZ29yaWVzXG4gICAgICAgIGlmKHNvcnRBcnJheTEgPCBzb3J0QXJyYXkyKSB7XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgICAgaWYoc29ydEFycmF5MSA+IHNvcnRBcnJheTIpIHtcbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgcGF0aCBtb2RlbHNcbiAgICB2YXIgcGF0aFZpZXdNb2RlbHMgPSBuZXcgQXJyYXkocGF0aE1vZGVscy5sZW5ndGgpO1xuICAgIHZhciB0b3RhbENvdW50ID0gZGltZW5zaW9uVmlld01vZGVsc1swXS5tb2RlbC5jb3VudDtcbiAgICB2YXIgdG90YWxIZWlnaHQgPSBkaW1lbnNpb25WaWV3TW9kZWxzWzBdLmNhdGVnb3JpZXNcbiAgICAgICAgLm1hcChmdW5jdGlvbihjKSB7IHJldHVybiBjLmhlaWdodDsgfSlcbiAgICAgICAgLnJlZHVjZShmdW5jdGlvbih2MSwgdjIpIHsgcmV0dXJuIHYxICsgdjI7IH0pO1xuXG5cbiAgICBmb3IodmFyIHBhdGhOdW1iZXIgPSAwOyBwYXRoTnVtYmVyIDwgcGF0aE1vZGVscy5sZW5ndGg7IHBhdGhOdW1iZXIrKykge1xuICAgICAgICB2YXIgcGF0aE1vZGVsID0gcGF0aE1vZGVsc1twYXRoTnVtYmVyXTtcblxuICAgICAgICB2YXIgcGF0aEhlaWdodDtcbiAgICAgICAgaWYodG90YWxDb3VudCA+IDApIHtcbiAgICAgICAgICAgIHBhdGhIZWlnaHQgPSB0b3RhbEhlaWdodCAqIChwYXRoTW9kZWwuY291bnQgLyB0b3RhbENvdW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBhdGhIZWlnaHQgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQnVpbGQgcGF0aCB5IGNvb3Jkc1xuICAgICAgICB2YXIgcGF0aFlzID0gbmV3IEFycmF5KG5leHRZUG9zaXRpb25zLmxlbmd0aCk7XG4gICAgICAgIGZvcih2YXIgZCA9IDA7IGQgPCBwYXRoTW9kZWwuY2F0ZWdvcnlJbmRzLmxlbmd0aDsgZCsrKSB7XG4gICAgICAgICAgICB2YXIgY2F0SW5kID0gcGF0aE1vZGVsLmNhdGVnb3J5SW5kc1tkXTtcbiAgICAgICAgICAgIHZhciBjYXREaXNwbGF5SW5kID0gY2F0VG9EaXNwbGF5SW5kUGVyRGltW2RdW2NhdEluZF07XG4gICAgICAgICAgICB2YXIgZGltRGlzcGxheUluZCA9IGRpbVRvRGlzcGxheUluZFtkXTtcblxuICAgICAgICAgICAgLy8gVXBkYXRlIG5leHQgeSBwb3NpdGlvblxuICAgICAgICAgICAgcGF0aFlzW2RpbURpc3BsYXlJbmRdID0gbmV4dFlQb3NpdGlvbnNbZGltRGlzcGxheUluZF1bY2F0RGlzcGxheUluZF07XG4gICAgICAgICAgICBuZXh0WVBvc2l0aW9uc1tkaW1EaXNwbGF5SW5kXVtjYXREaXNwbGF5SW5kXSArPSBwYXRoSGVpZ2h0O1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgY2F0ZWdvcnkgY29sb3IgaW5mb3JtYXRpb25cbiAgICAgICAgICAgIHZhciBjYXRWaWV3TW9kbGUgPSBwYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnNbZGltRGlzcGxheUluZF0uY2F0ZWdvcmllc1tjYXREaXNwbGF5SW5kXTtcbiAgICAgICAgICAgIHZhciBudW1CYW5kcyA9IGNhdFZpZXdNb2RsZS5iYW5kcy5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgbGFzdENhdEJhbmQgPSBjYXRWaWV3TW9kbGUuYmFuZHNbbnVtQmFuZHMgLSAxXTtcblxuICAgICAgICAgICAgaWYobGFzdENhdEJhbmQgPT09IHVuZGVmaW5lZCB8fCBwYXRoTW9kZWwucmF3Q29sb3IgIT09IGxhc3RDYXRCYW5kLnJhd0NvbG9yKSB7XG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IGJhbmRcbiAgICAgICAgICAgICAgICB2YXIgYmFuZFkgPSBsYXN0Q2F0QmFuZCA9PT0gdW5kZWZpbmVkID8gMCA6IGxhc3RDYXRCYW5kLnkgKyBsYXN0Q2F0QmFuZC5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgY2F0Vmlld01vZGxlLmJhbmRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBrZXk6IGJhbmRZLFxuICAgICAgICAgICAgICAgICAgICBjb2xvcjogcGF0aE1vZGVsLmNvbG9yLFxuICAgICAgICAgICAgICAgICAgICByYXdDb2xvcjogcGF0aE1vZGVsLnJhd0NvbG9yLFxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHBhdGhIZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiBjYXRWaWV3TW9kbGUud2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIGNvdW50OiBwYXRoTW9kZWwuY291bnQsXG4gICAgICAgICAgICAgICAgICAgIHk6IGJhbmRZLFxuICAgICAgICAgICAgICAgICAgICBjYXRlZ29yeVZpZXdNb2RlbDogY2F0Vmlld01vZGxlLFxuICAgICAgICAgICAgICAgICAgICBwYXJjYXRzVmlld01vZGVsOiBwYXJjYXRzVmlld01vZGVsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIEV4dGVuZCBjdXJyZW50IGJhbmRcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEJhbmQgPSBjYXRWaWV3TW9kbGUuYmFuZHNbbnVtQmFuZHMgLSAxXTtcbiAgICAgICAgICAgICAgICBjdXJyZW50QmFuZC5oZWlnaHQgKz0gcGF0aEhlaWdodDtcbiAgICAgICAgICAgICAgICBjdXJyZW50QmFuZC5jb3VudCArPSBwYXRoTW9kZWwuY291bnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBidWlsZCBzdmcgcGF0aFxuICAgICAgICB2YXIgc3ZnRDtcbiAgICAgICAgaWYocGFyY2F0c1ZpZXdNb2RlbC5wYXRoU2hhcGUgPT09ICdoc3BsaW5lJykge1xuICAgICAgICAgICAgc3ZnRCA9IGJ1aWxkU3ZnUGF0aChsZWZ0WFBvc2l0aW9ucywgcGF0aFlzLCBkaW1XaWR0aHMsIHBhdGhIZWlnaHQsIDAuNSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdmdEID0gYnVpbGRTdmdQYXRoKGxlZnRYUG9zaXRpb25zLCBwYXRoWXMsIGRpbVdpZHRocywgcGF0aEhlaWdodCwgMCk7XG4gICAgICAgIH1cblxuICAgICAgICBwYXRoVmlld01vZGVsc1twYXRoTnVtYmVyXSA9IHtcbiAgICAgICAgICAgIGtleTogcGF0aE1vZGVsLnZhbHVlSW5kc1swXSxcbiAgICAgICAgICAgIG1vZGVsOiBwYXRoTW9kZWwsXG4gICAgICAgICAgICBoZWlnaHQ6IHBhdGhIZWlnaHQsXG4gICAgICAgICAgICBsZWZ0WHM6IGxlZnRYUG9zaXRpb25zLFxuICAgICAgICAgICAgdG9wWXM6IHBhdGhZcyxcbiAgICAgICAgICAgIGRpbVdpZHRoczogZGltV2lkdGhzLFxuICAgICAgICAgICAgc3ZnRDogc3ZnRCxcbiAgICAgICAgICAgIHBhcmNhdHNWaWV3TW9kZWw6IHBhcmNhdHNWaWV3TW9kZWxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwYXJjYXRzVmlld01vZGVsLnBhdGhzID0gcGF0aFZpZXdNb2RlbHM7XG5cbiAvLyAqIEBwcm9wZXJ0eSBrZXlcbiAvLyAqICBVbmlxdWUga2V5IGZvciB0aGlzIG1vZGVsXG4gLy8gKiBAcHJvcGVydHkge1BhdGhNb2RlbH0gbW9kZWxcbiAvLyAqICBTb3VyY2UgcGF0aCBtb2RlbFxuIC8vICogQHByb3BlcnR5IHtOdW1iZXJ9IGhlaWdodFxuIC8vICogIEhlaWdodCBvZiB0aGlzIHBhdGggKHBpeGVscylcbiAvLyAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBzdmdEXG4gLy8gKiAgU1ZHIHBhdGggXCJkXCIgYXR0cmlidXRlIHN0cmluZ1xufVxuXG4vKipcbiAqIFVwZGF0ZSB0aGUgZGltZW5zaW9uIHZpZXcgbW9kZWxzIGJhc2VkIG9uIHRoZSBkaW1lbnNpb24gbW9kZWxzIGluIGEgUGFyY2F0c1ZpZXdNb2RlbFxuICpcbiAqIEBwYXJhbSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogIFZpZXcgbW9kZWwgZm9yIHRyYWNlXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZURpbWVuc2lvblZpZXdNb2RlbHMocGFyY2F0c1ZpZXdNb2RlbCkge1xuICAgIC8vIENvbXB1dGUgZGltZW5zaW9uIG9yZGVyaW5nXG4gICAgdmFyIGRpbWVuc2lvbnNJbmRJbmZvID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zLm1hcChmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiB7ZGlzcGxheUluZDogZC5kaXNwbGF5SW5kLCBkaW1lbnNpb25JbmQ6IGQuZGltZW5zaW9uSW5kfTtcbiAgICB9KTtcblxuICAgIGRpbWVuc2lvbnNJbmRJbmZvLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICByZXR1cm4gYS5kaXNwbGF5SW5kIC0gYi5kaXNwbGF5SW5kO1xuICAgIH0pO1xuXG4gICAgdmFyIGRpbWVuc2lvbnMgPSBbXTtcbiAgICBmb3IodmFyIGRpc3BsYXlJbmQgaW4gZGltZW5zaW9uc0luZEluZm8pIHtcbiAgICAgICAgdmFyIGRpbWVuc2lvbkluZCA9IGRpbWVuc2lvbnNJbmRJbmZvW2Rpc3BsYXlJbmRdLmRpbWVuc2lvbkluZDtcbiAgICAgICAgdmFyIGRpbU1vZGVsID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zW2RpbWVuc2lvbkluZF07XG4gICAgICAgIGRpbWVuc2lvbnMucHVzaChjcmVhdGVEaW1lbnNpb25WaWV3TW9kZWwocGFyY2F0c1ZpZXdNb2RlbCwgZGltTW9kZWwpKTtcbiAgICB9XG5cbiAgICBwYXJjYXRzVmlld01vZGVsLmRpbWVuc2lvbnMgPSBkaW1lbnNpb25zO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHBhcmNhdHMgRGltZW5zaW9uVmlld01vZGVsXG4gKlxuICogQHBhcmFtIHtQYXJjYXRzVmlld01vZGVsfSBwYXJjYXRzVmlld01vZGVsXG4gKiAgVmlldyBtb2RlbCBmb3IgdHJhY2VcbiAqIEBwYXJhbSB7RGltZW5zaW9uTW9kZWx9IGRpbWVuc2lvbk1vZGVsXG4gKiBAcmV0dXJuIHtEaW1lbnNpb25WaWV3TW9kZWx9XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZURpbWVuc2lvblZpZXdNb2RlbChwYXJjYXRzVmlld01vZGVsLCBkaW1lbnNpb25Nb2RlbCkge1xuICAgIC8vIENvbXB1dGUgZGltZW5zaW9uIHggcG9zaXRpb25cbiAgICB2YXIgY2F0ZWdvcnlMYWJlbFBhZCA9IDQwO1xuICAgIHZhciBkaW1XaWR0aCA9IDE2O1xuICAgIHZhciBudW1EaW1lbnNpb25zID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5kaW1lbnNpb25zLmxlbmd0aDtcbiAgICB2YXIgZGlzcGxheUluZCA9IGRpbWVuc2lvbk1vZGVsLmRpc3BsYXlJbmQ7XG5cbiAgICAvLyBDb21wdXRlIHggY29vcmRpbmF0ZSB2YWx1ZXNcbiAgICB2YXIgZGltRHg7XG4gICAgdmFyIGRpbVgwO1xuICAgIHZhciBkaW1YO1xuXG4gICAgaWYobnVtRGltZW5zaW9ucyA+IDEpIHtcbiAgICAgICAgZGltRHggPSAocGFyY2F0c1ZpZXdNb2RlbC53aWR0aCAtIDIgKiBjYXRlZ29yeUxhYmVsUGFkIC0gZGltV2lkdGgpIC8gKG51bURpbWVuc2lvbnMgLSAxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkaW1EeCA9IDA7XG4gICAgfVxuICAgIGRpbVgwID0gY2F0ZWdvcnlMYWJlbFBhZDtcbiAgICBkaW1YID0gZGltWDAgKyBkaW1EeCAqIGRpc3BsYXlJbmQ7XG5cbiAgICAvLyBDb21wdXRlIGNhdGVnb3JpZXNcbiAgICB2YXIgY2F0ZWdvcmllcyA9IFtdO1xuICAgIHZhciBtYXhDYXRzID0gcGFyY2F0c1ZpZXdNb2RlbC5tb2RlbC5tYXhDYXRzO1xuICAgIHZhciBudW1DYXRzID0gZGltZW5zaW9uTW9kZWwuY2F0ZWdvcmllcy5sZW5ndGg7XG4gICAgdmFyIGNhdFNwYWNpbmcgPSA4O1xuICAgIHZhciB0b3RhbENvdW50ID0gZGltZW5zaW9uTW9kZWwuY291bnQ7XG4gICAgdmFyIHRvdGFsSGVpZ2h0ID0gcGFyY2F0c1ZpZXdNb2RlbC5oZWlnaHQgLSBjYXRTcGFjaW5nICogKG1heENhdHMgLSAxKTtcbiAgICB2YXIgbmV4dENhdEhlaWdodDtcbiAgICB2YXIgbmV4dENhdE1vZGVsO1xuICAgIHZhciBuZXh0Q2F0O1xuICAgIHZhciBjYXRJbmQ7XG4gICAgdmFyIGNhdERpc3BsYXlJbmQ7XG5cbiAgICAvLyBDb21wdXRlIHN0YXJ0aW5nIFkgb2Zmc2V0XG4gICAgdmFyIG5leHRDYXRZID0gKG1heENhdHMgLSBudW1DYXRzKSAqIGNhdFNwYWNpbmcgLyAyLjA7XG5cbiAgICAvLyBDb21wdXRlIGNhdGVnb3J5IG9yZGVyaW5nXG4gICAgdmFyIGNhdGVnb3J5SW5kSW5mbyA9IGRpbWVuc2lvbk1vZGVsLmNhdGVnb3JpZXMubWFwKGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgcmV0dXJuIHtkaXNwbGF5SW5kOiBjLmRpc3BsYXlJbmQsIGNhdGVnb3J5SW5kOiBjLmNhdGVnb3J5SW5kfTtcbiAgICB9KTtcblxuICAgIGNhdGVnb3J5SW5kSW5mby5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEuZGlzcGxheUluZCAtIGIuZGlzcGxheUluZDtcbiAgICB9KTtcblxuICAgIGZvcihjYXREaXNwbGF5SW5kID0gMDsgY2F0RGlzcGxheUluZCA8IG51bUNhdHM7IGNhdERpc3BsYXlJbmQrKykge1xuICAgICAgICBjYXRJbmQgPSBjYXRlZ29yeUluZEluZm9bY2F0RGlzcGxheUluZF0uY2F0ZWdvcnlJbmQ7XG4gICAgICAgIG5leHRDYXRNb2RlbCA9IGRpbWVuc2lvbk1vZGVsLmNhdGVnb3JpZXNbY2F0SW5kXTtcblxuICAgICAgICBpZih0b3RhbENvdW50ID4gMCkge1xuICAgICAgICAgICAgbmV4dENhdEhlaWdodCA9IChuZXh0Q2F0TW9kZWwuY291bnQgLyB0b3RhbENvdW50KSAqIHRvdGFsSGVpZ2h0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV4dENhdEhlaWdodCA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBuZXh0Q2F0ID0ge1xuICAgICAgICAgICAga2V5OiBuZXh0Q2F0TW9kZWwudmFsdWVJbmRzWzBdLFxuICAgICAgICAgICAgbW9kZWw6IG5leHRDYXRNb2RlbCxcbiAgICAgICAgICAgIHdpZHRoOiBkaW1XaWR0aCxcbiAgICAgICAgICAgIGhlaWdodDogbmV4dENhdEhlaWdodCxcbiAgICAgICAgICAgIHk6IG5leHRDYXRNb2RlbC5kcmFnWSAhPT0gbnVsbCA/IG5leHRDYXRNb2RlbC5kcmFnWSA6IG5leHRDYXRZLFxuICAgICAgICAgICAgYmFuZHM6IFtdLFxuICAgICAgICAgICAgcGFyY2F0c1ZpZXdNb2RlbDogcGFyY2F0c1ZpZXdNb2RlbFxuICAgICAgICB9O1xuXG4gICAgICAgIG5leHRDYXRZID0gbmV4dENhdFkgKyBuZXh0Q2F0SGVpZ2h0ICsgY2F0U3BhY2luZztcbiAgICAgICAgY2F0ZWdvcmllcy5wdXNoKG5leHRDYXQpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGtleTogZGltZW5zaW9uTW9kZWwuZGltZW5zaW9uSW5kLFxuICAgICAgICB4OiBkaW1lbnNpb25Nb2RlbC5kcmFnWCAhPT0gbnVsbCA/IGRpbWVuc2lvbk1vZGVsLmRyYWdYIDogZGltWCxcbiAgICAgICAgeTogMCxcbiAgICAgICAgd2lkdGg6IGRpbVdpZHRoLFxuICAgICAgICBtb2RlbDogZGltZW5zaW9uTW9kZWwsXG4gICAgICAgIGNhdGVnb3JpZXM6IGNhdGVnb3JpZXMsXG4gICAgICAgIHBhcmNhdHNWaWV3TW9kZWw6IHBhcmNhdHNWaWV3TW9kZWwsXG4gICAgICAgIGRyYWdDYXRlZ29yeURpc3BsYXlJbmQ6IG51bGwsXG4gICAgICAgIGRyYWdEaW1lbnNpb25EaXNwbGF5SW5kOiBudWxsLFxuICAgICAgICBpbml0aWFsRHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmRzOiBudWxsLFxuICAgICAgICBpbml0aWFsRHJhZ0NhdGVnb3J5RGlzcGxheUluZHM6IG51bGwsXG4gICAgICAgIGRyYWdIYXNNb3ZlZDogbnVsbCxcbiAgICAgICAgcG90ZW50aWFsQ2xpY2tCYW5kOiBudWxsXG4gICAgfTtcbn1cblxuLy8gSlNEb2MgdHlwZWRlZnNcbi8vID09PT09PT09PT09PT09XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IExheW91dFxuICogIE9iamVjdCBjb250YWluaW5nIHN2ZyBsYXlvdXQgaW5mb3JtYXRpb25cbiAqXG4gKiBAcHJvcGVydHkge051bWJlcn0gd2lkdGggKHBpeGVscylcbiAqICBVc2FibGUgd2lkdGggZm9yIEZpZ3VyZSAoYWZ0ZXIgbWFyZ2lucyBhcmUgcmVtb3ZlZClcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBoZWlnaHQgKHBpeGVscylcbiAqICBVc2FibGUgaGVpZ2h0IGZvciBGaWd1cmUgKGFmdGVyIG1hcmdpbnMgYXJlIHJlbW92ZWQpXG4gKiBAcHJvcGVydHkge01hcmdpbn0gbWFyZ2luXG4gKiAgTWFyZ2luIGFyb3VuZCB0aGUgRmlndXJlIChwaXhlbHMpXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBNYXJnaW5cbiAqICBPYmplY3QgY29udGFpbmluZyBwYWRkaW5nIGluZm9ybWF0aW9uIGluIHBpeGVsc1xuICpcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSB0XG4gKiAgVG9wIG1hcmdpblxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHJcbiAqICBSaWdodCBtYXJnaW5cbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBiXG4gKiAgQm90dG9tIG1hcmdpblxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGxcbiAqICBMZWZ0IG1hcmdpblxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gRm9udFxuICogIE9iamVjdCBjb250YWluaW5nIGZvbnQgaW5mb3JtYXRpb25cbiAqXG4gKiBAcHJvcGVydHkge051bWJlcn0gc2l6ZTogRm9udCBzaXplXG4gKiBAcHJvcGVydHkge1N0cmluZ30gY29sb3I6IEZvbnQgY29sb3JcbiAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBmYW1pbHk6IEZvbnQgZmFtaWx5XG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBQYXJjYXRzVmlld01vZGVsXG4gKiAgT2JqZWN0IGNvbnRhaW5pbmcgY2FsY3VsYXRlZCBwYXJjYXRzIHZpZXcgaW5mb3JtYXRpb25cbiAqXG4gKiAgVGhlc2UgYXJlIHF1YW50aXRpZXMgdGhhdCByZXF1aXJlIExheW91dCBpbmZvcm1hdGlvbiB0byBjYWxjdWxhdGVcbiAqIEBwcm9wZXJ0eSBrZXlcbiAqICBVbmlxdWUga2V5IGZvciB0aGlzIG1vZGVsXG4gKiBAcHJvcGVydHkge1BhcmNhdHNNb2RlbH0gbW9kZWxcbiAqICBTb3VyY2UgcGFyY2F0cyBtb2RlbFxuICogQHByb3BlcnR5IHtBcnJheS48RGltZW5zaW9uVmlld01vZGVsPn0gZGltZW5zaW9uc1xuICogIEFycmF5IG9mIGRpbWVuc2lvbiB2aWV3IG1vZGVsc1xuICogQHByb3BlcnR5IHtOdW1iZXJ9IHdpZHRoXG4gKiAgV2lkdGggZm9yIHRoaXMgdHJhY2UgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBoZWlnaHRcbiAqICBIZWlnaHQgZm9yIHRoaXMgdHJhY2UgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSB4XG4gKiAgWCBwb3NpdGlvbiBvZiB0aGlzIHRyYWNlIHdpdGggcmVzcGVjdCB0byB0aGUgRmlndXJlIChwaXhlbHMpXG4gKiBAcHJvcGVydHkge051bWJlcn0geVxuICogIFkgcG9zaXRpb24gb2YgdGhpcyB0cmFjZSB3aXRoIHJlc3BlY3QgdG8gdGhlIEZpZ3VyZSAocGl4ZWxzKVxuICogQHByb3BlcnR5IHtTdHJpbmd9IGhvdmVyb25cbiAqICBIb3ZlciBpbnRlcmFjdGlvbiBtb2RlLiBPbmUgb2Y6ICdjYXRlZ29yeScsICdjb2xvcicsIG9yICdkaW1lbnNpb24nXG4gKiBAcHJvcGVydHkge0FycmF5LjxTdHJpbmc+fSBob3ZlcmluZm9JdGVtc1xuICogIEluZm8gdG8gZGlzcGxheSBvbiBob3Zlci4gQXJyYXkgd2l0aCBhIGNvbWJpbmF0aW9uIG9mICdjb3VudHMnIGFuZC9vciAncHJvYmFiaWxpdGllcycsIG9yICdub25lJywgb3IgJ3NraXAnXG4gKiBAcHJvcGVydHkge1N0cmluZ30gYXJyYW5nZW1lbnRcbiAqICBDYXRlZ29yeSBhcnJhbmdlbWVudC4gT25lIG9mOiAncGVycGVuZGljdWxhcicsICdmcmVlZm9ybScsIG9yICdmaXhlZCdcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gYnVuZGxlY29sb3JzXG4gKiAgV2hldGhlciBwYXRocyBzaG91bGQgYmUgc29ydGVkIHNvIHRoYXQgbGlrZSBjb2xvcnMgYXJlIGJ1bmRsZWQgdG9nZXRoZXIgYXMgdGhleSBwYXNzIHRocm91Z2ggY2F0ZWdvcmllc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IHNvcnRwYXRoc1xuICogIElmICdmb3J3YXJkJyB0aGVuIHNvcnQgcGF0aHMgYmFzZWQgb24gZGltZW5zaW9ucyBmcm9tIGxlZnQgdG8gcmlnaHQuIElmICdiYWNrd2FyZCcgc29ydCBiYXNlZCBvbiBkaW1lbnNpb25zXG4gKiAgZnJvbSByaWdodCB0byBsZWZ0XG4gKiBAcHJvcGVydHkge0ZvbnR9IGxhYmVsZm9udFxuICogIEZvbnQgZm9yIHRoZSBkaW1lbnNpb24gbGFiZWxzXG4gKiBAcHJvcGVydHkge0ZvbnR9IGNhdGVnb3J5bGFiZWxmb250XG4gKiAgRm9udCBmb3IgdGhlIGNhdGVnb3J5IGxhYmVsc1xuICogQHByb3BlcnR5IHtTdHJpbmd9IHBhdGhTaGFwZVxuICogIFRoZSBzaGFwZSBvZiB0aGUgcGF0aHMuIEVpdGhlciAnbGluZWFyJyBvciAnaHNwbGluZScuXG4gKiBAcHJvcGVydHkge0RpbWVuc2lvblZpZXdNb2RlbHxudWxsfSBkcmFnRGltZW5zaW9uXG4gKiAgRGltZW5zaW9uIGN1cnJlbnRseSBiZWluZyBkcmFnZ2VkLiBOdWxsIGlmIG5vIGRyYWcgaW4gcHJvZ3Jlc3NcbiAqIEBwcm9wZXJ0eSB7TWFyZ2lufSBtYXJnaW5cbiAqICBNYXJnaW4gYXJvdW5kIHRoZSBGaWd1cmVcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBncmFwaERpdlxuICogIFRvcC1sZXZlbCBncmFwaCBkaXYgZWxlbWVudFxuICogQHByb3BlcnR5IHtPYmplY3R9IHRyYWNlU2VsZWN0aW9uXG4gKiAgRDMgc2VsZWN0aW9uIG9mIHRoaXMgdmlldyBtb2RlbHMgdHJhY2UgZ3JvdXAgZWxlbWVudFxuICogQHByb3BlcnR5IHtPYmplY3R9IHBhdGhTZWxlY3Rpb25cbiAqICBEMyBzZWxlY3Rpb24gb2YgdGhpcyB2aWV3IG1vZGVscyBwYXRoIGVsZW1lbnRzXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGltZW5zaW9uU2VsZWN0aW9uXG4gKiAgRDMgc2VsZWN0aW9uIG9mIHRoaXMgdmlldyBtb2RlbHMgZGltZW5zaW9uIGdyb3VwIGVsZW1lbnRcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IERpbWVuc2lvblZpZXdNb2RlbFxuICogIE9iamVjdCBjb250YWluaW5nIGNhbGN1bGF0ZWQgcGFyY2F0cyBkaW1lbnNpb24gdmlldyBpbmZvcm1hdGlvblxuICpcbiAqICBUaGVzZSBhcmUgcXVhbnRpdGllcyB0aGF0IHJlcXVpcmUgTGF5b3V0IGluZm9ybWF0aW9uIHRvIGNhbGN1bGF0ZVxuICogQHByb3BlcnR5IGtleVxuICogIFVuaXF1ZSBrZXkgZm9yIHRoaXMgbW9kZWxcbiAqIEBwcm9wZXJ0eSB7RGltZW5zaW9uTW9kZWx9IG1vZGVsXG4gKiAgU291cmNlIGRpbWVuc2lvbiBtb2RlbFxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHhcbiAqICBYIHBvc2l0aW9uIG9mIHRoZSBjZW50ZXIgb2YgdGhpcyBkaW1lbnNpb24gd2l0aCByZXNwZWN0IHRvIHRoZSBGaWd1cmUgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSB5XG4gKiAgWSBwb3NpdGlvbiBvZiB0aGUgdG9wIG9mIHRoaXMgZGltZW5zaW9uIHdpdGggcmVzcGVjdCB0byB0aGUgRmlndXJlIChwaXhlbHMpXG4gKiBAcHJvcGVydHkge051bWJlcn0gd2lkdGhcbiAqICBXaWR0aCBvZiBjYXRlZ29yaWVzIGluIHRoaXMgZGltZW5zaW9uIChwaXhlbHMpXG4gKiBAcHJvcGVydHkge1BhcmNhdHNWaWV3TW9kZWx9IHBhcmNhdHNWaWV3TW9kZWxcbiAqICBUaGUgcGFyZW50IHRyYWNlJ3MgdmlldyBtb2RlbFxuICogQHByb3BlcnR5IHtBcnJheS48Q2F0ZWdvcnlWaWV3TW9kZWw+fSBjYXRlZ29yaWVzXG4gKiAgRGltZW5zaW9ucyBjYXRlZ29yeSB2aWV3IG1vZGVsc1xuICogQHByb3BlcnR5IHtOdW1iZXJ8bnVsbH0gZHJhZ0NhdGVnb3J5RGlzcGxheUluZFxuICogIERpc3BsYXkgaW5kZXggb2YgY2F0ZWdvcnkgY3VycmVudGx5IGJlaW5nIGRyYWdnZWQuIG51bGwgaWYgbm8gY2F0ZWdvcnkgaXMgYmVpbmcgZHJhZ2dlZFxuICogQHByb3BlcnR5IHtOdW1iZXJ8bnVsbH0gZHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmRcbiAqICBEaXNwbGF5IGluZGV4IG9mIHRoZSBkaW1lbnNpb24gYmVpbmcgZHJhZ2dlZC4gbnVsbCBpZiBubyBkaW1lbnNpb24gaXMgYmVpbmcgZHJhZ2dlZFxuICogQHByb3BlcnR5IHtBcnJheS48TnVtYmVyPnxudWxsfSBpbml0aWFsRHJhZ0RpbWVuc2lvbkRpc3BsYXlJbmRzXG4gKiAgRGltZW5zaW9ucyBkaXNwbGF5IGluZGV4ZXMgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgY3VycmVudCBkcmFnLiBudWxsIGlmIG5vIGRpbWVuc2lvbiBpcyBiZWluZyBkcmFnZ2VkXG4gKiBAcHJvcGVydHkge0FycmF5LjxOdW1iZXI+fG51bGx9IGluaXRpYWxEcmFnQ2F0ZWdvcnlEaXNwbGF5SW5kc1xuICogIENhdGVnb3J5IGRpc3BsYXkgaW5kZXhlcyBmb3IgdGhlIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGN1cnJlbnQgZHJhZy4gbnVsbCBpZiBubyBjYXRlZ29yeSBpcyBiZWluZyBkcmFnZ2VkXG4gKiBAcHJvcGVydHkge0hUTUxFbGVtZW50fSBwb3RlbnRpYWxDbGlja0JhbmRcbiAqICBCYW5kIHVuZGVyIG1vdXNlIHdoZW4gY3VycmVudCBkcmFnIGJlZ2FuLiBJZiBubyBkcmFnIG1vdmVtZW50IHRha2VzIHBsYWNlIHRoZW4gYSBjbGljayB3aWxsIGJlIGVtaXR0ZWQgZm9yIHRoaXNcbiAqICBiYW5kLiBOdWxsIGlmIG5vdCBkcmFnIGluIHByb2dyZXNzLlxuICogQHByb3BlcnR5IHtCb29sZWFufSBkcmFnSGFzTW92ZWRcbiAqICBUcnVlIGlmIHRoZXJlIGlzIGFuIGFjdGl2ZSBkcmFnIGFuZCB0aGUgZHJhZyBoYXMgbW92ZWQuIElmIGRyYWcgZG9lc24ndCBtb3ZlIGJlZm9yZSBiZWluZyBlbmRlZCB0aGVuXG4gKiAgdGhpcyBtYXkgYmUgaW50ZXJwcmV0ZWQgYXMgYSBjbGljay4gTnVsbCBpZiBubyBkcmFnIGluIHByb2dyZXNzXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDYXRlZ29yeVZpZXdNb2RlbFxuICogIE9iamVjdCBjb250YWluaW5nIGNhbGN1bGF0ZWQgcGFyY2F0cyBjYXRlZ29yeSB2aWV3IGluZm9ybWF0aW9uXG4gKlxuICogIFRoZXNlIGFyZSBxdWFudGl0aWVzIHRoYXQgcmVxdWlyZSBMYXlvdXQgaW5mb3JtYXRpb24gdG8gY2FsY3VsYXRlXG4gKiBAcHJvcGVydHkga2V5XG4gKiAgVW5pcXVlIGtleSBmb3IgdGhpcyBtb2RlbFxuICogQHByb3BlcnR5IHtDYXRlZ29yeU1vZGVsfSBtb2RlbFxuICogIFNvdXJjZSBjYXRlZ29yeSBtb2RlbFxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHdpZHRoXG4gKiAgV2lkdGggZm9yIHRoaXMgY2F0ZWdvcnkgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBoZWlnaHRcbiAqICBIZWlnaHQgZm9yIHRoaXMgY2F0ZWdvcnkgKHBpeGVscylcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSB5XG4gKiAgWSBwb3NpdGlvbiBvZiB0aGlzIGNhdGVvZ3J5IHdpdGggcmVzcGVjdCB0byB0aGUgRmlndXJlIChwaXhlbHMpXG4gKiBAcHJvcGVydHkge0FycmF5LjxDYXRlZ29yeUJhbmRWaWV3TW9kZWw+fSBiYW5kc1xuICogIEFycmF5IG9mIGNvbG9yIGJhbmRzIGluc2lkZSB0aGUgY2F0ZWdvcnlcbiAqIEBwcm9wZXJ0eSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogIFRoZSBwYXJlbnQgdHJhY2UncyB2aWV3IG1vZGVsXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDYXRlZ29yeUJhbmRWaWV3TW9kZWxcbiAqICBPYmplY3QgY29udGFpbmluZyBjYWxjdWxhdGVkIGNhdGVnb3J5IGJhbmQgaW5mb3JtYXRpb24uIEEgY2F0ZWdvcnkgYmFuZCBpcyBhIHJlZ2lvbiBpbnNpZGUgYSBjYXRlZ29yeSBjb3ZlcmluZ1xuICogIHBhdGhzIG9mIGEgc2luZ2xlIGNvbG9yXG4gKlxuICogQHByb3BlcnR5IGtleVxuICogIFVuaXF1ZSBrZXkgZm9yIHRoaXMgbW9kZWxcbiAqIEBwcm9wZXJ0eSBjb2xvclxuICogIEJhbmQgY29sb3JcbiAqIEBwcm9wZXJ0eSByYXdDb2xvclxuICogIFJhdyBjb2xvciB2YWx1ZSBmb3IgYmFuZFxuICogQHByb3BlcnR5IHtOdW1iZXJ9IHdpZHRoXG4gKiAgQmFuZCB3aWR0aFxuICogQHByb3BlcnR5IHtOdW1iZXJ9IGhlaWdodFxuICogIEJhbmQgaGVpZ2h0XG4gKiBAcHJvcGVydHkge051bWJlcn0geVxuICogIFkgcG9zaXRpb24gb2YgdG9wIG9mIHRoZSBiYW5kIHdpdGggcmVzcGVjdCB0byB0aGUgY2F0ZWdvcnlcbiAqIEBwcm9wZXJ0eSB7TnVtYmVyfSBjb3VudFxuICogIFRoZSBudW1iZXIgb2Ygc2FtcGxlcyByZXByZXNlbnRlZCBieSB0aGUgYmFuZFxuICogQHByb3BlcnR5IHtDYXRlZ29yeVZpZXdNb2RlbH0gY2F0ZWdvcnlWaWV3TW9kZWxcbiAqICBUaGUgcGFyZW50IGNhdGVnb3JpZSdzIHZpZXcgbW9kZWxcbiAqIEBwcm9wZXJ0eSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogIFRoZSBwYXJlbnQgdHJhY2UncyB2aWV3IG1vZGVsXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBQYXRoVmlld01vZGVsXG4gKiAgT2JqZWN0IGNvbnRhaW5pbmcgY2FsY3VsYXRlZCBwYXJjYXRzIHBhdGggdmlldyBpbmZvcm1hdGlvblxuICpcbiAqICBUaGVzZSBhcmUgcXVhbnRpdGllcyB0aGF0IHJlcXVpcmUgTGF5b3V0IGluZm9ybWF0aW9uIHRvIGNhbGN1bGF0ZVxuICogQHByb3BlcnR5IGtleVxuICogIFVuaXF1ZSBrZXkgZm9yIHRoaXMgbW9kZWxcbiAqIEBwcm9wZXJ0eSB7UGF0aE1vZGVsfSBtb2RlbFxuICogIFNvdXJjZSBwYXRoIG1vZGVsXG4gKiBAcHJvcGVydHkge051bWJlcn0gaGVpZ2h0XG4gKiAgSGVpZ2h0IG9mIHRoaXMgcGF0aCAocGl4ZWxzKVxuICogQHByb3BlcnR5IHtBcnJheS48TnVtYmVyPn0gbGVmdFhzXG4gKiAgVGhlIHggcG9zaXRpb24gb2YgdGhlIGxlZnQgZWRnZSBvZiBlYWNoIGRpc3BsYXkgZGltZW5zaW9uXG4gKiBAcHJvcGVydHkge0FycmF5LjxOdW1iZXI+fSB0b3BZc1xuICogIFRoZSB5IHBvc2l0aW9uIG9mIHRoZSB0b3Agb2YgdGhlIHBhdGggZm9yIGVhY2ggZGlzcGxheSBkaW1lbnNpb25cbiAqIEBwcm9wZXJ0eSB7QXJyYXkuPE51bWJlcj59IGRpbVdpZHRoc1xuICogIFRoZSB3aWR0aCBvZiBlYWNoIGRpc3BsYXkgZGltZW5zaW9uXG4gKiBAcHJvcGVydHkge1N0cmluZ30gc3ZnRFxuICogIFNWRyBwYXRoIFwiZFwiIGF0dHJpYnV0ZSBzdHJpbmdcbiAqIEBwcm9wZXJ0eSB7UGFyY2F0c1ZpZXdNb2RlbH0gcGFyY2F0c1ZpZXdNb2RlbFxuICogIFRoZSBwYXJlbnQgdHJhY2UncyB2aWV3IG1vZGVsXG4gKi9cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzXCI6NzQzLFwiLi4vLi4vcGxvdF9hcGkvcGxvdF9hcGlcIjo3NTQsXCJkM1wiOjE2MyxcInRpbnljb2xvcjJcIjo1Mzd9XSwxMDczOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuXG52YXIgcGFyY2F0cyA9IF9kZXJlcV8oJy4vcGFyY2F0cycpO1xuXG4vKipcbiAqIENyZWF0ZSAvIHVwZGF0ZSBwYXJjYXQgdHJhY2VzXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGdyYXBoRGl2XG4gKiBAcGFyYW0ge0FycmF5LjxQYXJjYXRzTW9kZWw+fSBwYXJjYXRzTW9kZWxzXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChncmFwaERpdiwgcGFyY2F0c01vZGVscywgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdyYXBoRGl2Ll9mdWxsTGF5b3V0O1xuICAgIHZhciBzdmcgPSBmdWxsTGF5b3V0Ll9wYXBlcjtcbiAgICB2YXIgc2l6ZSA9IGZ1bGxMYXlvdXQuX3NpemU7XG5cbiAgICBwYXJjYXRzKFxuICAgICAgICBncmFwaERpdixcbiAgICAgICAgc3ZnLFxuICAgICAgICBwYXJjYXRzTW9kZWxzLFxuICAgICAgICB7XG4gICAgICAgICAgICB3aWR0aDogc2l6ZS53LFxuICAgICAgICAgICAgaGVpZ2h0OiBzaXplLmgsXG4gICAgICAgICAgICBtYXJnaW46IHtcbiAgICAgICAgICAgICAgICB0OiBzaXplLnQsXG4gICAgICAgICAgICAgICAgcjogc2l6ZS5yLFxuICAgICAgICAgICAgICAgIGI6IHNpemUuYixcbiAgICAgICAgICAgICAgICBsOiBzaXplLmxcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgdHJhbnNpdGlvbk9wdHMsXG4gICAgICAgIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2tcbiAgICApO1xufTtcblxufSx7XCIuL3BhcmNhdHNcIjoxMDcyfV0sMTA3NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGF4ZXNBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9sYXlvdXRfYXR0cmlidXRlcycpO1xudmFyIGZvbnRBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZG9tYWluJykuYXR0cmlidXRlcztcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciB0ZW1wbGF0ZWRBcnJheSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKS50ZW1wbGF0ZWRBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ3BhcmNvb3JkcycsIHRyYWNlOiB0cnVlLCBlZGl0VHlwZTogJ3Bsb3QnfSksXG5cbiAgICBsYWJlbGFuZ2xlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdhbmdsZScsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbGFiZWxzaWRlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWyd0b3AnLCAnYm90dG9tJ10sXG4gICAgICAgIGRmbHQ6ICd0b3AnLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbGFiZWxmb250OiBmb250QXR0cnMoe1xuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9KSxcbiAgICB0aWNrZm9udDogZm9udEF0dHJzKHtcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSksXG4gICAgcmFuZ2Vmb250OiBmb250QXR0cnMoe1xuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9KSxcblxuICAgIGRpbWVuc2lvbnM6IHRlbXBsYXRlZEFycmF5KCdkaW1lbnNpb24nLCB7XG4gICAgICAgIGxhYmVsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICAvLyBUT0RPOiBiZXR0ZXIgd2F5IHRvIGRldGVybWluZSBvcmRpbmFsIHZzIGNvbnRpbnVvdXMgYXhlcyxcbiAgICAgICAgLy8gc28gdXNlcnMgY2FuIHVzZSB0aWNrdmFscy90aWNrdGV4dCB3aXRoIGEgY29udGludW91cyBheGlzLlxuICAgICAgICB0aWNrdmFsczogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLnRpY2t2YWxzLCB7XG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICB0aWNrdGV4dDogZXh0ZW5kRmxhdCh7fSwgYXhlc0F0dHJzLnRpY2t0ZXh0LCB7XG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICB0aWNrZm9ybWF0OiBleHRlbmRGbGF0KHt9LCBheGVzQXR0cnMudGlja2Zvcm1hdCwge1xuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICB9KSxcbiAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICByYW5nZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAgICAgIHt2YWxUeXBlOiAnbnVtYmVyJywgZWRpdFR5cGU6ICdwbG90J30sXG4gICAgICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInLCBlZGl0VHlwZTogJ3Bsb3QnfVxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgY29uc3RyYWludHJhbmdlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnaW5mb19hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGZyZWVMZW5ndGg6IHRydWUsXG4gICAgICAgICAgICBkaW1lbnNpb25zOiAnMS0yJyxcbiAgICAgICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICAgICAge3ZhbFR5cGU6ICdudW1iZXInLCBlZGl0VHlwZTogJ3Bsb3QnfSxcbiAgICAgICAgICAgICAgICB7dmFsVHlwZTogJ251bWJlcicsIGVkaXRUeXBlOiAncGxvdCd9XG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBtdWx0aXNlbGVjdDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB2YWx1ZXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9KSxcblxuICAgIGxpbmU6IGV4dGVuZEZsYXQoe2VkaXRUeXBlOiAnY2FsYyd9LFxuICAgICAgICBjb2xvclNjYWxlQXR0cnMoJ2xpbmUnLCB7XG4gICAgICAgICAgICAvLyB0aGUgZGVmYXVsdCBhdXRvY29sb3JzY2FsZSBpc24ndCBxdWl0ZSB1c2FibGUgZm9yIHBhcmNvb3JkcyBkdWUgdG8gY29udGV4dCBhbWJpZ3VpdHkgYXJvdW5kIDAgKGdyZXksIG9mZi13aGl0ZSlcbiAgICAgICAgICAgIC8vIGF1dG9jb2xvcnNjYWxlIHRoZXJlZm9yZSBkZWZhdWx0cyB0byBmYWxzZSB0b28sIHRvIGF2b2lkIGJlaW5nIG92ZXJyaWRkZW4gYnkgdGhlIGJsdWUtd2hpdGUtcmVkIGF1dG9jb2xvciBwYWxldHRlXG4gICAgICAgICAgICBjb2xvcnNjYWxlRGZsdDogJ1ZpcmlkaXMnLFxuICAgICAgICAgICAgYXV0b0NvbG9yRGZsdDogZmFsc2UsXG4gICAgICAgICAgICBlZGl0VHlwZU92ZXJyaWRlOiAnY2FsYydcbiAgICAgICAgfSlcbiAgICApXG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzXCI6NjAwLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGVcIjo3NTcsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vbGF5b3V0X2F0dHJpYnV0ZXNcIjo3NzksXCIuLi8uLi9wbG90cy9kb21haW5cIjo3OTIsXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTN9XSwxMDc1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciBrZXlGdW4gPSBfZGVyZXFfKCcuLi8uLi9saWIvZ3VwJykua2V5RnVuO1xudmFyIHJlcGVhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9ndXAnKS5yZXBlYXQ7XG52YXIgc29ydEFzYyA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLnNvcnRlckFzYztcblxudmFyIHNuYXBSYXRpbyA9IGMuYmFyLnNuYXBSYXRpbztcbmZ1bmN0aW9uIHNuYXBPdmVyc2hvb3QodiwgdkFkamFjZW50KSB7IHJldHVybiB2ICogKDEgLSBzbmFwUmF0aW8pICsgdkFkamFjZW50ICogc25hcFJhdGlvOyB9XG5cbnZhciBzbmFwQ2xvc2UgPSBjLmJhci5zbmFwQ2xvc2U7XG5mdW5jdGlvbiBjbG9zZVRvQ292ZXJpbmcodiwgdkFkamFjZW50KSB7IHJldHVybiB2ICogKDEgLSBzbmFwQ2xvc2UpICsgdkFkamFjZW50ICogc25hcENsb3NlOyB9XG5cbi8vIHNuYXAgZm9yIHRoZSBsb3cgZW5kIG9mIGEgcmFuZ2Ugb24gYW4gb3JkaW5hbCBzY2FsZVxuLy8gb24gYW4gb3JkaW5hbCBzY2FsZSwgYWx3YXlzIHNob3cgc29tZSBvdmVyc2hvb3QgZnJvbSB0aGUgZXhhY3QgdmFsdWUsXG4vLyBzbyBpdCdzIGNsZWFyIHdlJ3JlIGNvdmVyaW5nIGl0XG4vLyBmaW5kIHRoZSBpbnRlcnZhbCB3ZSdyZSBpbiwgYW5kIHNuYXAgdG8gMS80IHRoZSBkaXN0YW5jZSB0byB0aGUgbmV4dFxuLy8gdGhlc2UgdHdvIGNvdWxkIGJlIHVuaWZpZWQgYXQgYSBzbGlnaHQgbG9zcyBvZiByZWFkYWJpbGl0eSAvIHBlcmZcbmZ1bmN0aW9uIG9yZGluYWxTY2FsZVNuYXAoaXNIaWdoLCBhLCB2LCBleGlzdGluZ1Jhbmdlcykge1xuICAgIGlmKG92ZXJsYXBwaW5nRXhpc3RpbmcodiwgZXhpc3RpbmdSYW5nZXMpKSByZXR1cm4gdjtcblxuICAgIHZhciBkaXIgPSBpc0hpZ2ggPyAtMSA6IDE7XG5cbiAgICB2YXIgZmlyc3QgPSAwO1xuICAgIHZhciBsYXN0ID0gYS5sZW5ndGggLSAxO1xuICAgIGlmKGRpciA8IDApIHtcbiAgICAgICAgdmFyIHRtcCA9IGZpcnN0O1xuICAgICAgICBmaXJzdCA9IGxhc3Q7XG4gICAgICAgIGxhc3QgPSB0bXA7XG4gICAgfVxuXG4gICAgdmFyIGFIZXJlID0gYVtmaXJzdF07XG4gICAgdmFyIGFQcmV2ID0gYUhlcmU7XG4gICAgZm9yKHZhciBpID0gZmlyc3Q7IGRpciAqIGkgPCBkaXIgKiBsYXN0OyBpICs9IGRpcikge1xuICAgICAgICB2YXIgbmV4dEkgPSBpICsgZGlyO1xuICAgICAgICB2YXIgYU5leHQgPSBhW25leHRJXTtcblxuICAgICAgICAvLyB2ZXJ5IGNsb3NlIHRvIHRoZSBwcmV2aW91cyAtIHNuYXAgZG93biB0byBpdFxuICAgICAgICBpZihkaXIgKiB2IDwgZGlyICogY2xvc2VUb0NvdmVyaW5nKGFIZXJlLCBhTmV4dCkpIHJldHVybiBzbmFwT3ZlcnNob290KGFIZXJlLCBhUHJldik7XG4gICAgICAgIGlmKGRpciAqIHYgPCBkaXIgKiBhTmV4dCB8fCBuZXh0SSA9PT0gbGFzdCkgcmV0dXJuIHNuYXBPdmVyc2hvb3QoYU5leHQsIGFIZXJlKTtcblxuICAgICAgICBhUHJldiA9IGFIZXJlO1xuICAgICAgICBhSGVyZSA9IGFOZXh0O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gb3ZlcmxhcHBpbmdFeGlzdGluZyh2LCBleGlzdGluZ1Jhbmdlcykge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBleGlzdGluZ1Jhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZih2ID49IGV4aXN0aW5nUmFuZ2VzW2ldWzBdICYmIHYgPD0gZXhpc3RpbmdSYW5nZXNbaV1bMV0pIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGJhckhvcml6b250YWxTZXR1cChzZWxlY3Rpb24pIHtcbiAgICBzZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ3gnLCAtYy5iYXIuY2FwdHVyZVdpZHRoIC8gMilcbiAgICAgICAgLmF0dHIoJ3dpZHRoJywgYy5iYXIuY2FwdHVyZVdpZHRoKTtcbn1cblxuZnVuY3Rpb24gYmFja2dyb3VuZEJhckhvcml6b250YWxTZXR1cChzZWxlY3Rpb24pIHtcbiAgICBzZWxlY3Rpb25cbiAgICAgICAgLmF0dHIoJ3Zpc2liaWxpdHknLCAndmlzaWJsZScpXG4gICAgICAgIC5zdHlsZSgndmlzaWJpbGl0eScsICd2aXNpYmxlJylcbiAgICAgICAgLmF0dHIoJ2ZpbGwnLCAneWVsbG93JylcbiAgICAgICAgLmF0dHIoJ29wYWNpdHknLCAwKTtcbn1cblxuZnVuY3Rpb24gc2V0SGlnaGxpZ2h0KGQpIHtcbiAgICBpZighZC5icnVzaC5maWx0ZXJTcGVjaWZpZWQpIHtcbiAgICAgICAgcmV0dXJuICcwLCcgKyBkLmhlaWdodDtcbiAgICB9XG5cbiAgICB2YXIgcGl4ZWxSYW5nZXMgPSB1bml0VG9QeChkLmJydXNoLmZpbHRlci5nZXRDb25zb2xpZGF0ZWQoKSwgZC5oZWlnaHQpO1xuICAgIHZhciBkYXNoQXJyYXkgPSBbMF07IC8vIHdlIHN0YXJ0IHdpdGggYSAwIGxlbmd0aCBzZWxlY3Rpb24gYXMgZmlsdGVyIHJhbmdlcyBhcmUgaW5jbHVzaXZlLCBub3QgZXhjbHVzaXZlXG4gICAgdmFyIHAsIHNlY3Rpb25IZWlnaHQsIGlOZXh0O1xuICAgIHZhciBjdXJyZW50R2FwID0gcGl4ZWxSYW5nZXMubGVuZ3RoID8gcGl4ZWxSYW5nZXNbMF1bMF0gOiBudWxsO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBwaXhlbFJhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBwID0gcGl4ZWxSYW5nZXNbaV07XG4gICAgICAgIHNlY3Rpb25IZWlnaHQgPSBwWzFdIC0gcFswXTtcbiAgICAgICAgZGFzaEFycmF5LnB1c2goY3VycmVudEdhcCk7XG4gICAgICAgIGRhc2hBcnJheS5wdXNoKHNlY3Rpb25IZWlnaHQpO1xuICAgICAgICBpTmV4dCA9IGkgKyAxO1xuICAgICAgICBpZihpTmV4dCA8IHBpeGVsUmFuZ2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgY3VycmVudEdhcCA9IHBpeGVsUmFuZ2VzW2lOZXh0XVswXSAtIHBbMV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgZGFzaEFycmF5LnB1c2goZC5oZWlnaHQpO1xuICAgIC8vIGQuaGVpZ2h0IGlzIGFkZGVkIGF0IHRoZSBlbmQgdG8gZW5zdXJlIHRoYXQgKDEpIHdlIGhhdmUgYW4gZXZlbiBudW1iZXIgb2YgZGFzaGFycmF5IHBvaW50cywgTUROIHBhZ2Ugc2F5c1xuICAgIC8vIFwiSWYgYW4gb2RkIG51bWJlciBvZiB2YWx1ZXMgaXMgcHJvdmlkZWQsIHRoZW4gdGhlIGxpc3Qgb2YgdmFsdWVzIGlzIHJlcGVhdGVkIHRvIHlpZWxkIGFuIGV2ZW4gbnVtYmVyIG9mIHZhbHVlcy5cIlxuICAgIC8vIGFuZCAoMikgaXQncyBfYXQgbGVhc3RfIGFzIGxvbmcgYXMgdGhlIGZ1bGwgaGVpZ2h0IChldmVuIGlmIHJhbmdlIGlzIG1pbnVzY3VsZSBhbmQgYXQgdGhlIGJvdHRvbSkgdGhvdWdoIHRoaXNcbiAgICAvLyBtYXkgbm90IGJlIG5lY2Vzc2FyeSwgbWF5YmUgZHVwbGljYXRpbmcgdGhlIGxhc3QgcG9pbnQgd291bGQgZG8gdG9vLiBCdXQgbm8gaGFybSBpbiBhIGxvbmdlciBkYXNoYXJyYXkgdGhhbiBsaW5lLlxuICAgIHJldHVybiBkYXNoQXJyYXk7XG59XG5cbmZ1bmN0aW9uIHVuaXRUb1B4KHVuaXRSYW5nZXMsIGhlaWdodCkge1xuICAgIHJldHVybiB1bml0UmFuZ2VzLm1hcChmdW5jdGlvbihwcikge1xuICAgICAgICByZXR1cm4gcHIubWFwKGZ1bmN0aW9uKHYpIHsgcmV0dXJuIE1hdGgubWF4KDAsIHYgKiBoZWlnaHQpOyB9KS5zb3J0KHNvcnRBc2MpO1xuICAgIH0pO1xufVxuXG4vLyBpcyB0aGUgY3Vyc29yIG92ZXIgdGhlIG5vcnRoLCBtaWRkbGUsIG9yIHNvdXRoIG9mIGEgYmFyP1xuLy8gdGhlIGVuZCBoYW5kbGVzIGV4dGVuZCBvdmVyIHRoZSBsYXN0IDEwJSBvZiB0aGUgYmFyXG5mdW5jdGlvbiBnZXRSZWdpb24oZlBpeCwgeSkge1xuICAgIHZhciBwYWQgPSBjLmJhci5oYW5kbGVIZWlnaHQ7XG4gICAgaWYoeSA+IGZQaXhbMV0gKyBwYWQgfHwgeSA8IGZQaXhbMF0gLSBwYWQpIHJldHVybjtcbiAgICBpZih5ID49IDAuOSAqIGZQaXhbMV0gKyAwLjEgKiBmUGl4WzBdKSByZXR1cm4gJ24nO1xuICAgIGlmKHkgPD0gMC45ICogZlBpeFswXSArIDAuMSAqIGZQaXhbMV0pIHJldHVybiAncyc7XG4gICAgcmV0dXJuICducyc7XG59XG5cbmZ1bmN0aW9uIGNsZWFyQ3Vyc29yKCkge1xuICAgIGQzLnNlbGVjdChkb2N1bWVudC5ib2R5KVxuICAgICAgICAuc3R5bGUoJ2N1cnNvcicsIG51bGwpO1xufVxuXG5mdW5jdGlvbiBzdHlsZUhpZ2hsaWdodChzZWxlY3Rpb24pIHtcbiAgICAvLyBzdHJva2UtZGFzaGFycmF5IGlzIHVzZWQgdG8gbWluaW1pemUgdGhlIG51bWJlciBvZiBjcmVhdGVkIERPTSBub2RlcywgYmVjYXVzZSB0aGUgcmVxdWlyZW1lbnQgY2FsbHMgZm9yIHVwIHRvXG4gICAgLy8gMTAwMCBpbmRpdmlkdWFsIHNlbGVjdGlvbnMgb24gYW4gYXhpcywgYW5kIHRoZXJlIGNhbiBiZSA2MCBheGVzIHBlciBwYXJjb29yZHMsIGFuZCBtdWx0aXBsZSBwYXJjb29yZHMgcGVyXG4gICAgLy8gZGFzaGJvYXJkLiBUaGUgdGVjaG5pcXVlIGlzIHNpbWlsYXIgdG8gaHR0cHM6Ly9jb2RlcGVuLmlvL21vbmZlcmEvcGVuL3JMWXFXUiBhbmQgdXNpbmcgYSBgcG9seWxpbmVgIHdpdGhcbiAgICAvLyBtdWx0aXBsZSBzZWN0aW9ucywgb3IgYSBgcGF0aGAgZWxlbWVudCB2aWEgaXRzIGBkYCBhdHRyaWJ1dGUgd291bGQgYWxzbyBiZSBET00tc3BhcmluZyBhbHRlcm5hdGl2ZXMuXG4gICAgc2VsZWN0aW9uLmF0dHIoJ3N0cm9rZS1kYXNoYXJyYXknLCBzZXRIaWdobGlnaHQpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJIaWdobGlnaHQocm9vdCwgdHdlZW5DYWxsYmFjaykge1xuICAgIHZhciBiYXIgPSBkMy5zZWxlY3Qocm9vdCkuc2VsZWN0QWxsKCcuaGlnaGxpZ2h0LCAuaGlnaGxpZ2h0LXNoYWRvdycpO1xuICAgIHZhciBiYXJUb1N0eWxlID0gdHdlZW5DYWxsYmFjayA/IGJhci50cmFuc2l0aW9uKCkuZHVyYXRpb24oYy5iYXIuc25hcER1cmF0aW9uKS5lYWNoKCdlbmQnLCB0d2VlbkNhbGxiYWNrKSA6IGJhcjtcbiAgICBzdHlsZUhpZ2hsaWdodChiYXJUb1N0eWxlKTtcbn1cblxuZnVuY3Rpb24gZ2V0SW50ZXJ2YWwoZCwgeSkge1xuICAgIHZhciBiID0gZC5icnVzaDtcbiAgICB2YXIgYWN0aXZlID0gYi5maWx0ZXJTcGVjaWZpZWQ7XG4gICAgdmFyIGNsb3Nlc3RJbnRlcnZhbCA9IE5hTjtcbiAgICB2YXIgb3V0ID0ge307XG4gICAgdmFyIGk7XG5cbiAgICBpZihhY3RpdmUpIHtcbiAgICAgICAgdmFyIGhlaWdodCA9IGQuaGVpZ2h0O1xuICAgICAgICB2YXIgaW50ZXJ2YWxzID0gYi5maWx0ZXIuZ2V0Q29uc29saWRhdGVkKCk7XG4gICAgICAgIHZhciBwaXhJbnRlcnZhbHMgPSB1bml0VG9QeChpbnRlcnZhbHMsIGhlaWdodCk7XG4gICAgICAgIHZhciBob3ZlcmVkSW50ZXJ2YWwgPSBOYU47XG4gICAgICAgIHZhciBwcmV2aW91c0ludGVydmFsID0gTmFOO1xuICAgICAgICB2YXIgbmV4dEludGVydmFsID0gTmFOO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPD0gcGl4SW50ZXJ2YWxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgcCA9IHBpeEludGVydmFsc1tpXTtcbiAgICAgICAgICAgIGlmKHAgJiYgcFswXSA8PSB5ICYmIHkgPD0gcFsxXSkge1xuICAgICAgICAgICAgICAgIC8vIG92ZXIgYSBiYXJcbiAgICAgICAgICAgICAgICBob3ZlcmVkSW50ZXJ2YWwgPSBpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBiZXR3ZWVuIGJhcnMsIG9yIGJlZm9yZS9hZnRlciB0aGUgZmlyc3QvbGFzdCBiYXJcbiAgICAgICAgICAgICAgICBwcmV2aW91c0ludGVydmFsID0gaSA/IGkgLSAxIDogTmFOO1xuICAgICAgICAgICAgICAgIGlmKHAgJiYgcFswXSA+IHkpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV4dEludGVydmFsID0gaTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7IC8vIG5vIHBvaW50IGNvbnRpbnVpbmcgYXMgaW50ZXJ2YWxzIGFyZSBub24tb3ZlcmxhcHBpbmcgYW5kIHNvcnRlZDsgY291bGQgdXNlIGxvZyBzZWFyY2hcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjbG9zZXN0SW50ZXJ2YWwgPSBob3ZlcmVkSW50ZXJ2YWw7XG4gICAgICAgIGlmKGlzTmFOKGNsb3Nlc3RJbnRlcnZhbCkpIHtcbiAgICAgICAgICAgIGlmKGlzTmFOKHByZXZpb3VzSW50ZXJ2YWwpIHx8IGlzTmFOKG5leHRJbnRlcnZhbCkpIHtcbiAgICAgICAgICAgICAgICBjbG9zZXN0SW50ZXJ2YWwgPSBpc05hTihwcmV2aW91c0ludGVydmFsKSA/IG5leHRJbnRlcnZhbCA6IHByZXZpb3VzSW50ZXJ2YWw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNsb3Nlc3RJbnRlcnZhbCA9ICh5IC0gcGl4SW50ZXJ2YWxzW3ByZXZpb3VzSW50ZXJ2YWxdWzFdIDwgcGl4SW50ZXJ2YWxzW25leHRJbnRlcnZhbF1bMF0gLSB5KSA/XG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzSW50ZXJ2YWwgOiBuZXh0SW50ZXJ2YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZighaXNOYU4oY2xvc2VzdEludGVydmFsKSkge1xuICAgICAgICAgICAgdmFyIGZQaXggPSBwaXhJbnRlcnZhbHNbY2xvc2VzdEludGVydmFsXTtcbiAgICAgICAgICAgIHZhciByZWdpb24gPSBnZXRSZWdpb24oZlBpeCwgeSk7XG5cbiAgICAgICAgICAgIGlmKHJlZ2lvbikge1xuICAgICAgICAgICAgICAgIG91dC5pbnRlcnZhbCA9IGludGVydmFsc1tjbG9zZXN0SW50ZXJ2YWxdO1xuICAgICAgICAgICAgICAgIG91dC5pbnRlcnZhbFBpeCA9IGZQaXg7XG4gICAgICAgICAgICAgICAgb3V0LnJlZ2lvbiA9IHJlZ2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGQub3JkaW5hbCAmJiAhb3V0LnJlZ2lvbikge1xuICAgICAgICB2YXIgYSA9IGQudW5pdFRpY2t2YWxzO1xuICAgICAgICB2YXIgdW5pdExvY2F0aW9uID0gZC51bml0VG9QYWRkZWRQeC5pbnZlcnQoeSk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciByYW5nZWkgPSBbXG4gICAgICAgICAgICAgICAgYVtNYXRoLm1heChpIC0gMSwgMCldICogMC4yNSArIGFbaV0gKiAwLjc1LFxuICAgICAgICAgICAgICAgIGFbTWF0aC5taW4oaSArIDEsIGEubGVuZ3RoIC0gMSldICogMC4yNSArIGFbaV0gKiAwLjc1XG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgaWYodW5pdExvY2F0aW9uID49IHJhbmdlaVswXSAmJiB1bml0TG9jYXRpb24gPD0gcmFuZ2VpWzFdKSB7XG4gICAgICAgICAgICAgICAgb3V0LmNsaWNrYWJsZU9yZGluYWxSYW5nZSA9IHJhbmdlaTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGRyYWdzdGFydChsVGhpcywgZCkge1xuICAgIGQzLmV2ZW50LnNvdXJjZUV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHZhciB5ID0gZC5oZWlnaHQgLSBkMy5tb3VzZShsVGhpcylbMV0gLSAyICogYy52ZXJ0aWNhbFBhZGRpbmc7XG4gICAgdmFyIHVuaXRMb2NhdGlvbiA9IGQudW5pdFRvUGFkZGVkUHguaW52ZXJ0KHkpO1xuICAgIHZhciBiID0gZC5icnVzaDtcbiAgICB2YXIgaW50ZXJ2YWwgPSBnZXRJbnRlcnZhbChkLCB5KTtcbiAgICB2YXIgdW5pdFJhbmdlID0gaW50ZXJ2YWwuaW50ZXJ2YWw7XG4gICAgdmFyIHMgPSBiLnN2Z0JydXNoO1xuICAgIHMud2FzRHJhZ2dlZCA9IGZhbHNlOyAvLyB3ZSBzdGFydCBhc3N1bWluZyB0aGVyZSB3b24ndCBiZSBhIGRyYWcgLSB1c2VmdWwgZm9yIHJlc2V0XG4gICAgcy5ncmFiYmluZ0JhciA9IGludGVydmFsLnJlZ2lvbiA9PT0gJ25zJztcbiAgICBpZihzLmdyYWJiaW5nQmFyKSB7XG4gICAgICAgIHZhciBwaXhlbFJhbmdlID0gdW5pdFJhbmdlLm1hcChkLnVuaXRUb1BhZGRlZFB4KTtcbiAgICAgICAgcy5ncmFiUG9pbnQgPSB5IC0gcGl4ZWxSYW5nZVswXSAtIGMudmVydGljYWxQYWRkaW5nO1xuICAgICAgICBzLmJhckxlbmd0aCA9IHBpeGVsUmFuZ2VbMV0gLSBwaXhlbFJhbmdlWzBdO1xuICAgIH1cbiAgICBzLmNsaWNrYWJsZU9yZGluYWxSYW5nZSA9IGludGVydmFsLmNsaWNrYWJsZU9yZGluYWxSYW5nZTtcbiAgICBzLnN0YXlpbmdJbnRlcnZhbHMgPSAoZC5tdWx0aXNlbGVjdCAmJiBiLmZpbHRlclNwZWNpZmllZCkgPyBiLmZpbHRlci5nZXRDb25zb2xpZGF0ZWQoKSA6IFtdO1xuICAgIGlmKHVuaXRSYW5nZSkge1xuICAgICAgICBzLnN0YXlpbmdJbnRlcnZhbHMgPSBzLnN0YXlpbmdJbnRlcnZhbHMuZmlsdGVyKGZ1bmN0aW9uKGludDIpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnQyWzBdICE9PSB1bml0UmFuZ2VbMF0gJiYgaW50MlsxXSAhPT0gdW5pdFJhbmdlWzFdO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgcy5zdGFydEV4dGVudCA9IGludGVydmFsLnJlZ2lvbiA/IHVuaXRSYW5nZVtpbnRlcnZhbC5yZWdpb24gPT09ICdzJyA/IDEgOiAwXSA6IHVuaXRMb2NhdGlvbjtcbiAgICBkLnBhcmVudC5pbkJydXNoRHJhZyA9IHRydWU7XG4gICAgcy5icnVzaFN0YXJ0Q2FsbGJhY2soKTtcbn1cblxuZnVuY3Rpb24gZHJhZyhsVGhpcywgZCkge1xuICAgIGQzLmV2ZW50LnNvdXJjZUV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHZhciB5ID0gZC5oZWlnaHQgLSBkMy5tb3VzZShsVGhpcylbMV0gLSAyICogYy52ZXJ0aWNhbFBhZGRpbmc7XG4gICAgdmFyIHMgPSBkLmJydXNoLnN2Z0JydXNoO1xuICAgIHMud2FzRHJhZ2dlZCA9IHRydWU7XG4gICAgcy5fZHJhZ2dpbmcgPSB0cnVlO1xuXG4gICAgaWYocy5ncmFiYmluZ0JhcikgeyAvLyBtb3ZpbmcgdGhlIGJhclxuICAgICAgICBzLm5ld0V4dGVudCA9IFt5IC0gcy5ncmFiUG9pbnQsIHkgKyBzLmJhckxlbmd0aCAtIHMuZ3JhYlBvaW50XS5tYXAoZC51bml0VG9QYWRkZWRQeC5pbnZlcnQpO1xuICAgIH0gZWxzZSB7IC8vIHNvdXRoL25vcnRoIGRyYWcgb3IgbmV3IGJhciBjcmVhdGlvblxuICAgICAgICBzLm5ld0V4dGVudCA9IFtzLnN0YXJ0RXh0ZW50LCBkLnVuaXRUb1BhZGRlZFB4LmludmVydCh5KV0uc29ydChzb3J0QXNjKTtcbiAgICB9XG5cbiAgICBkLmJydXNoLmZpbHRlclNwZWNpZmllZCA9IHRydWU7XG4gICAgcy5leHRlbnQgPSBzLnN0YXlpbmdJbnRlcnZhbHMuY29uY2F0KFtzLm5ld0V4dGVudF0pO1xuICAgIHMuYnJ1c2hDYWxsYmFjayhkKTtcbiAgICByZW5kZXJIaWdobGlnaHQobFRoaXMucGFyZW50Tm9kZSk7XG59XG5cbmZ1bmN0aW9uIGRyYWdlbmQobFRoaXMsIGQpIHtcbiAgICB2YXIgYnJ1c2ggPSBkLmJydXNoO1xuICAgIHZhciBmaWx0ZXIgPSBicnVzaC5maWx0ZXI7XG4gICAgdmFyIHMgPSBicnVzaC5zdmdCcnVzaDtcblxuICAgIGlmKCFzLl9kcmFnZ2luZykgeyAvLyBpLmUuIGNsaWNrXG4gICAgICAgIC8vIG1vY2sgemVybyBkcmFnXG4gICAgICAgIG1vdXNlbW92ZShsVGhpcywgZCk7XG4gICAgICAgIGRyYWcobFRoaXMsIGQpO1xuICAgICAgICAvLyByZW1lbWJlciBpdCBpcyBhIGNsaWNrIG5vdCBhIGRyYWdcbiAgICAgICAgZC5icnVzaC5zdmdCcnVzaC53YXNEcmFnZ2VkID0gZmFsc2U7XG4gICAgfVxuICAgIHMuX2RyYWdnaW5nID0gZmFsc2U7XG5cbiAgICB2YXIgZSA9IGQzLmV2ZW50O1xuICAgIGUuc291cmNlRXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdmFyIGdyYWJiaW5nQmFyID0gcy5ncmFiYmluZ0JhcjtcbiAgICBzLmdyYWJiaW5nQmFyID0gZmFsc2U7XG4gICAgcy5ncmFiTG9jYXRpb24gPSB1bmRlZmluZWQ7XG4gICAgZC5wYXJlbnQuaW5CcnVzaERyYWcgPSBmYWxzZTtcbiAgICBjbGVhckN1cnNvcigpOyAvLyBpbnN0ZWFkIG9mIGNsZWFyaW5nLCBhIG5pY2VyIHRoaW5nIHdvdWxkIGJlIHRvIHNldCBpdCBhY2NvcmRpbmcgdG8gY3VycmVudCBsb2NhdGlvblxuICAgIGlmKCFzLndhc0RyYWdnZWQpIHsgLy8gYSBjbGljaytyZWxlYXNlIG9uIHRoZSBzYW1lIHNwb3QgKGllLiB3L28gZHJhZ2dpbmcpIG1lYW5zIGEgYmFyIG9yIGZ1bGwgcmVzZXRcbiAgICAgICAgcy53YXNEcmFnZ2VkID0gdW5kZWZpbmVkOyAvLyBsb2dpYy13aXNlIHVubmVlZGVkLCBqdXN0IHNob3dzIGB3YXNEcmFnZ2VkYCBoYXMgbm8gbG9uZ2VyIGEgbWVhbmluZ1xuICAgICAgICBpZihzLmNsaWNrYWJsZU9yZGluYWxSYW5nZSkge1xuICAgICAgICAgICAgaWYoYnJ1c2guZmlsdGVyU3BlY2lmaWVkICYmIGQubXVsdGlzZWxlY3QpIHtcbiAgICAgICAgICAgICAgICBzLmV4dGVudC5wdXNoKHMuY2xpY2thYmxlT3JkaW5hbFJhbmdlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcy5leHRlbnQgPSBbcy5jbGlja2FibGVPcmRpbmFsUmFuZ2VdO1xuICAgICAgICAgICAgICAgIGJydXNoLmZpbHRlclNwZWNpZmllZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZihncmFiYmluZ0Jhcikge1xuICAgICAgICAgICAgcy5leHRlbnQgPSBzLnN0YXlpbmdJbnRlcnZhbHM7XG4gICAgICAgICAgICBpZihzLmV4dGVudC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBicnVzaENsZWFyKGJydXNoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJydXNoQ2xlYXIoYnJ1c2gpO1xuICAgICAgICB9XG4gICAgICAgIHMuYnJ1c2hDYWxsYmFjayhkKTtcbiAgICAgICAgcmVuZGVySGlnaGxpZ2h0KGxUaGlzLnBhcmVudE5vZGUpO1xuICAgICAgICBzLmJydXNoRW5kQ2FsbGJhY2soYnJ1c2guZmlsdGVyU3BlY2lmaWVkID8gZmlsdGVyLmdldENvbnNvbGlkYXRlZCgpIDogW10pO1xuICAgICAgICByZXR1cm47IC8vIG5vIG5lZWQgdG8gZnVzZSBpbnRlcnZhbHMgb3Igc25hcCB0byBvcmRpbmFscywgc28gd2UgY2FuIGJhaWwgZWFybHlcbiAgICB9XG5cbiAgICB2YXIgbWVyZ2VJbnRlcnZhbHMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gS2V5IHBpZWNlIG9mIGxvZ2ljOiBvbmNlIHRoZSBidXR0b24gaXMgcmVsZWFzZWQsIHBvc3NpYmx5IG92ZXJsYXBwaW5nIGludGVydmFscyB3aWxsIGJlIGZ1c2VkOlxuICAgICAgICAvLyBIZXJlIGl0J3MgZG9uZSBpbW1lZGlhdGVseSBvbiBjbGljayByZWxlYXNlIHdoaWxlIG9uIG9yZGluYWwgc25hcCB0cmFuc2l0aW9uIGl0J3MgZG9uZSBhdCB0aGUgZW5kXG4gICAgICAgIGZpbHRlci5zZXQoZmlsdGVyLmdldENvbnNvbGlkYXRlZCgpKTtcbiAgICB9O1xuXG4gICAgaWYoZC5vcmRpbmFsKSB7XG4gICAgICAgIHZhciBhID0gZC51bml0VGlja3ZhbHM7XG4gICAgICAgIGlmKGFbYS5sZW5ndGggLSAxXSA8IGFbMF0pIGEucmV2ZXJzZSgpO1xuICAgICAgICBzLm5ld0V4dGVudCA9IFtcbiAgICAgICAgICAgIG9yZGluYWxTY2FsZVNuYXAoMCwgYSwgcy5uZXdFeHRlbnRbMF0sIHMuc3RheWluZ0ludGVydmFscyksXG4gICAgICAgICAgICBvcmRpbmFsU2NhbGVTbmFwKDEsIGEsIHMubmV3RXh0ZW50WzFdLCBzLnN0YXlpbmdJbnRlcnZhbHMpXG4gICAgICAgIF07XG4gICAgICAgIHZhciBoYXNOZXdFeHRlbnQgPSBzLm5ld0V4dGVudFsxXSA+IHMubmV3RXh0ZW50WzBdO1xuICAgICAgICBzLmV4dGVudCA9IHMuc3RheWluZ0ludGVydmFscy5jb25jYXQoaGFzTmV3RXh0ZW50ID8gW3MubmV3RXh0ZW50XSA6IFtdKTtcbiAgICAgICAgaWYoIXMuZXh0ZW50Lmxlbmd0aCkge1xuICAgICAgICAgICAgYnJ1c2hDbGVhcihicnVzaCk7XG4gICAgICAgIH1cbiAgICAgICAgcy5icnVzaENhbGxiYWNrKGQpO1xuICAgICAgICBpZihoYXNOZXdFeHRlbnQpIHtcbiAgICAgICAgICAgIC8vIG1lcmdpbmcgaW50ZXJ2YWxzIHBvc3QgdGhlIHNuYXAgdHdlZW5cbiAgICAgICAgICAgIHJlbmRlckhpZ2hsaWdodChsVGhpcy5wYXJlbnROb2RlLCBtZXJnZUludGVydmFscyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBpZiBubyBuZXcgaW50ZXJ2YWwsIGRvbid0IGFuaW1hdGUsIGp1c3QgcmVkcmF3IHRoZSBoaWdobGlnaHQgaW1tZWRpYXRlbHlcbiAgICAgICAgICAgIG1lcmdlSW50ZXJ2YWxzKCk7XG4gICAgICAgICAgICByZW5kZXJIaWdobGlnaHQobFRoaXMucGFyZW50Tm9kZSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBtZXJnZUludGVydmFscygpOyAvLyBtZXJnaW5nIGludGVydmFscyBpbW1lZGlhdGVseVxuICAgIH1cbiAgICBzLmJydXNoRW5kQ2FsbGJhY2soYnJ1c2guZmlsdGVyU3BlY2lmaWVkID8gZmlsdGVyLmdldENvbnNvbGlkYXRlZCgpIDogW10pO1xufVxuXG5mdW5jdGlvbiBtb3VzZW1vdmUobFRoaXMsIGQpIHtcbiAgICB2YXIgeSA9IGQuaGVpZ2h0IC0gZDMubW91c2UobFRoaXMpWzFdIC0gMiAqIGMudmVydGljYWxQYWRkaW5nO1xuICAgIHZhciBpbnRlcnZhbCA9IGdldEludGVydmFsKGQsIHkpO1xuXG4gICAgdmFyIGN1cnNvciA9ICdjcm9zc2hhaXInO1xuICAgIGlmKGludGVydmFsLmNsaWNrYWJsZU9yZGluYWxSYW5nZSkgY3Vyc29yID0gJ3BvaW50ZXInO1xuICAgIGVsc2UgaWYoaW50ZXJ2YWwucmVnaW9uKSBjdXJzb3IgPSBpbnRlcnZhbC5yZWdpb24gKyAnLXJlc2l6ZSc7XG4gICAgZDMuc2VsZWN0KGRvY3VtZW50LmJvZHkpXG4gICAgICAgIC5zdHlsZSgnY3Vyc29yJywgY3Vyc29yKTtcbn1cblxuZnVuY3Rpb24gYXR0YWNoRHJhZ0JlaGF2aW9yKHNlbGVjdGlvbikge1xuICAgIC8vIFRoZXJlJ3Mgc29tZSBmaWRkbGluZyB3aXRoIHBvaW50ZXIgY3Vyc29yIHN0eWxpbmcgc28gdGhhdCB0aGUgY3Vyc29yIHByZXNlcnZlcyBpdHMgc2hhcGUgd2hpbGUgZHJhZ2dpbmcgYSBicnVzaFxuICAgIC8vIGV2ZW4gaWYgdGhlIGN1cnNvciBzdHJheXMgZnJvbSB0aGUgaW50ZXJhY3RpbmcgYmFyLCB3aGljaCBpcyBib3VuZCB0byBoYXBwZW4gYXMgYmFycyBhcmUgdGhpbiBhbmQgdGhlIHVzZXJcbiAgICAvLyB3aWxsIGluZXZpdGFibHkgbGVhdmUgdGhlIGhvdHNwb3Qgc3RyaXAuIEluIHRoaXMgcmVnYXJkLCBpdCBkb2VzIHNvbWV0aGluZyBzaW1pbGFyIHRvIHdoYXQgdGhlIEQzIGJydXNoIHdvdWxkIGRvLlxuICAgIHNlbGVjdGlvblxuICAgICAgICAub24oJ21vdXNlbW92ZScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGQzLmV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBpZighZC5wYXJlbnQuaW5CcnVzaERyYWcpIG1vdXNlbW92ZSh0aGlzLCBkKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdtb3VzZWxlYXZlJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgaWYoIWQucGFyZW50LmluQnJ1c2hEcmFnKSBjbGVhckN1cnNvcigpO1xuICAgICAgICB9KVxuICAgICAgICAuY2FsbChkMy5iZWhhdmlvci5kcmFnKClcbiAgICAgICAgICAgIC5vbignZHJhZ3N0YXJ0JywgZnVuY3Rpb24oZCkgeyBkcmFnc3RhcnQodGhpcywgZCk7IH0pXG4gICAgICAgICAgICAub24oJ2RyYWcnLCBmdW5jdGlvbihkKSB7IGRyYWcodGhpcywgZCk7IH0pXG4gICAgICAgICAgICAub24oJ2RyYWdlbmQnLCBmdW5jdGlvbihkKSB7IGRyYWdlbmQodGhpcywgZCk7IH0pXG4gICAgICAgICk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0QXNjKGEsIGIpIHsgcmV0dXJuIGFbMF0gLSBiWzBdOyB9XG5cbmZ1bmN0aW9uIHJlbmRlckF4aXNCcnVzaChheGlzQnJ1c2gpIHtcbiAgICB2YXIgYmFja2dyb3VuZCA9IGF4aXNCcnVzaC5zZWxlY3RBbGwoJy5iYWNrZ3JvdW5kJykuZGF0YShyZXBlYXQpO1xuXG4gICAgYmFja2dyb3VuZC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZCgnYmFja2dyb3VuZCcsIHRydWUpXG4gICAgICAgIC5jYWxsKGJhckhvcml6b250YWxTZXR1cClcbiAgICAgICAgLmNhbGwoYmFja2dyb3VuZEJhckhvcml6b250YWxTZXR1cClcbiAgICAgICAgLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhdXRvJykgLy8gcGFyZW50IHBvaW50ZXIgZXZlbnRzIGFyZSBkaXNhYmxlZDsgd2UgbXVzdCBoYXZlIGl0IHRvIHJlZ2lzdGVyIGV2ZW50c1xuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgwICcgKyBjLnZlcnRpY2FsUGFkZGluZyArICcpJyk7XG5cbiAgICBiYWNrZ3JvdW5kXG4gICAgICAgIC5jYWxsKGF0dGFjaERyYWdCZWhhdmlvcilcbiAgICAgICAgLmF0dHIoJ2hlaWdodCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLmhlaWdodCAtIGMudmVydGljYWxQYWRkaW5nO1xuICAgICAgICB9KTtcblxuICAgIHZhciBoaWdobGlnaHRTaGFkb3cgPSBheGlzQnJ1c2guc2VsZWN0QWxsKCcuaGlnaGxpZ2h0LXNoYWRvdycpLmRhdGEocmVwZWF0KTsgLy8gd2UgaGF2ZSBhIHNldCBoZXJlLCBjYW4ndCBjYWxsIGl0IGBleHRlbnRgXG5cbiAgICBoaWdobGlnaHRTaGFkb3cuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdsaW5lJylcbiAgICAgICAgLmNsYXNzZWQoJ2hpZ2hsaWdodC1zaGFkb3cnLCB0cnVlKVxuICAgICAgICAuYXR0cigneCcsIC1jLmJhci53aWR0aCAvIDIpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBjLmJhci53aWR0aCArIGMuYmFyLnN0cm9rZVdpZHRoKVxuICAgICAgICAuYXR0cignc3Ryb2tlJywgYy5iYXIuc3Ryb2tlQ29sb3IpXG4gICAgICAgIC5hdHRyKCdvcGFjaXR5JywgYy5iYXIuc3Ryb2tlT3BhY2l0eSlcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS1saW5lY2FwJywgJ2J1dHQnKTtcblxuICAgIGhpZ2hsaWdodFNoYWRvd1xuICAgICAgICAuYXR0cigneTEnLCBmdW5jdGlvbihkKSB7IHJldHVybiBkLmhlaWdodDsgfSlcbiAgICAgICAgLmNhbGwoc3R5bGVIaWdobGlnaHQpO1xuXG4gICAgdmFyIGhpZ2hsaWdodCA9IGF4aXNCcnVzaC5zZWxlY3RBbGwoJy5oaWdobGlnaHQnKS5kYXRhKHJlcGVhdCk7IC8vIHdlIGhhdmUgYSBzZXQgaGVyZSwgY2FuJ3QgY2FsbCBpdCBgZXh0ZW50YFxuXG4gICAgaGlnaGxpZ2h0LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnbGluZScpXG4gICAgICAgIC5jbGFzc2VkKCdoaWdobGlnaHQnLCB0cnVlKVxuICAgICAgICAuYXR0cigneCcsIC1jLmJhci53aWR0aCAvIDIpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBjLmJhci53aWR0aCAtIGMuYmFyLnN0cm9rZVdpZHRoKVxuICAgICAgICAuYXR0cignc3Ryb2tlJywgYy5iYXIuZmlsbENvbG9yKVxuICAgICAgICAuYXR0cignb3BhY2l0eScsIGMuYmFyLmZpbGxPcGFjaXR5KVxuICAgICAgICAuYXR0cignc3Ryb2tlLWxpbmVjYXAnLCAnYnV0dCcpO1xuXG4gICAgaGlnaGxpZ2h0XG4gICAgICAgIC5hdHRyKCd5MScsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQuaGVpZ2h0OyB9KVxuICAgICAgICAuY2FsbChzdHlsZUhpZ2hsaWdodCk7XG59XG5cbmZ1bmN0aW9uIGVuc3VyZUF4aXNCcnVzaChheGlzT3ZlcmxheXMpIHtcbiAgICB2YXIgYXhpc0JydXNoID0gYXhpc092ZXJsYXlzLnNlbGVjdEFsbCgnLicgKyBjLmNuLmF4aXNCcnVzaClcbiAgICAgICAgLmRhdGEocmVwZWF0LCBrZXlGdW4pO1xuXG4gICAgYXhpc0JydXNoLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uYXhpc0JydXNoLCB0cnVlKTtcblxuICAgIHJlbmRlckF4aXNCcnVzaChheGlzQnJ1c2gpO1xufVxuXG5mdW5jdGlvbiBnZXRCcnVzaEV4dGVudChicnVzaCkge1xuICAgIHJldHVybiBicnVzaC5zdmdCcnVzaC5leHRlbnQubWFwKGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS5zbGljZSgpO30pO1xufVxuXG5mdW5jdGlvbiBicnVzaENsZWFyKGJydXNoKSB7XG4gICAgYnJ1c2guZmlsdGVyU3BlY2lmaWVkID0gZmFsc2U7XG4gICAgYnJ1c2guc3ZnQnJ1c2guZXh0ZW50ID0gW1stSW5maW5pdHksIEluZmluaXR5XV07XG59XG5cbmZ1bmN0aW9uIGF4aXNCcnVzaE1vdmVkKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIGF4aXNCcnVzaE1vdmVkKGRpbWVuc2lvbikge1xuICAgICAgICB2YXIgYnJ1c2ggPSBkaW1lbnNpb24uYnJ1c2g7XG4gICAgICAgIHZhciBleHRlbnQgPSBnZXRCcnVzaEV4dGVudChicnVzaCk7XG4gICAgICAgIHZhciBuZXdFeHRlbnQgPSBleHRlbnQuc2xpY2UoKTtcbiAgICAgICAgYnJ1c2guZmlsdGVyLnNldChuZXdFeHRlbnQpO1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGRlZHVwZVJlYWxSYW5nZXMoaW50ZXJ2YWxzKSB7XG4gICAgLy8gRnVzZXMgZWxlbWVudHMgb2YgaW50ZXJ2YWxzIGlmIHRoZXkgb3ZlcmxhcCwgeWllbGRpbmcgZGlzY29udGlndW91cyBpbnRlcnZhbHMsIHJlc3VsdHMubGVuZ3RoIDw9IGludGVydmFscy5sZW5ndGhcbiAgICAvLyBDdXJyZW50bHkgdXNlcyBjbG9zZWQgaW50ZXJ2YWxzLCBpZS4gZGVkdXBlUmVhbFJhbmdlcyhbWzQwMCwgODAwXSwgWzMwMCwgNDAwXV0pIC0+IFszMDAsIDgwMF1cbiAgICB2YXIgcXVldWUgPSBpbnRlcnZhbHMuc2xpY2UoKTtcbiAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgdmFyIGN1cnJlbnRJbnRlcnZhbDtcbiAgICB2YXIgY3VycmVudCA9IHF1ZXVlLnNoaWZ0KCk7XG4gICAgd2hpbGUoY3VycmVudCkgeyAvLyBbXS5zaGlmdCA9PT0gdW5kZWZpbmVkLCBzbyB3ZSBkb24ndCBkZXNjZW5kIGludG8gYW4gZW1wdHkgYXJyYXlcbiAgICAgICAgY3VycmVudEludGVydmFsID0gY3VycmVudC5zbGljZSgpO1xuICAgICAgICB3aGlsZSgoY3VycmVudCA9IHF1ZXVlLnNoaWZ0KCkpICYmIGN1cnJlbnRbMF0gPD0gLyogcmlnaHQtb3BlbiBpbnRlcnZhbCB3b3VsZCBuZWVkIGA8YCAqLyBjdXJyZW50SW50ZXJ2YWxbMV0pIHtcbiAgICAgICAgICAgIGN1cnJlbnRJbnRlcnZhbFsxXSA9IE1hdGgubWF4KGN1cnJlbnRJbnRlcnZhbFsxXSwgY3VycmVudFsxXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0LnB1c2goY3VycmVudEludGVydmFsKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gbWFrZUZpbHRlcigpIHtcbiAgICB2YXIgZmlsdGVyID0gW107XG4gICAgdmFyIGNvbnNvbGlkYXRlZDtcbiAgICB2YXIgYm91bmRzO1xuICAgIHJldHVybiB7XG4gICAgICAgIHNldDogZnVuY3Rpb24oYSkge1xuICAgICAgICAgICAgZmlsdGVyID0gYVxuICAgICAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5zbGljZSgpLnNvcnQoc29ydEFzYyk7IH0pXG4gICAgICAgICAgICAgICAgLnNvcnQoc3RhcnRBc2MpO1xuXG4gICAgICAgICAgICAvLyBoYW5kbGUgdW5zZWxlY3RlZCBjYXNlXG4gICAgICAgICAgICBpZihmaWx0ZXIubGVuZ3RoID09PSAxICYmXG4gICAgICAgICAgICAgICAgZmlsdGVyWzBdWzBdID09PSAtSW5maW5pdHkgJiZcbiAgICAgICAgICAgICAgICBmaWx0ZXJbMF1bMV0gPT09IEluZmluaXR5KSB7XG4gICAgICAgICAgICAgICAgZmlsdGVyID0gW1swLCAtMV1dO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zb2xpZGF0ZWQgPSBkZWR1cGVSZWFsUmFuZ2VzKGZpbHRlcik7XG4gICAgICAgICAgICBib3VuZHMgPSBmaWx0ZXIucmVkdWNlKGZ1bmN0aW9uKHAsIG4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW01hdGgubWluKHBbMF0sIG5bMF0pLCBNYXRoLm1heChwWzFdLCBuWzFdKV07XG4gICAgICAgICAgICB9LCBbSW5maW5pdHksIC1JbmZpbml0eV0pO1xuICAgICAgICB9LFxuICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gZmlsdGVyLnNsaWNlKCk7IH0sXG4gICAgICAgIGdldENvbnNvbGlkYXRlZDogZnVuY3Rpb24oKSB7IHJldHVybiBjb25zb2xpZGF0ZWQ7IH0sXG4gICAgICAgIGdldEJvdW5kczogZnVuY3Rpb24oKSB7IHJldHVybiBib3VuZHM7IH1cbiAgICB9O1xufVxuXG5mdW5jdGlvbiBtYWtlQnJ1c2goc3RhdGUsIHJhbmdlU3BlY2lmaWVkLCBpbml0aWFsUmFuZ2UsIGJydXNoU3RhcnRDYWxsYmFjaywgYnJ1c2hDYWxsYmFjaywgYnJ1c2hFbmRDYWxsYmFjaykge1xuICAgIHZhciBmaWx0ZXIgPSBtYWtlRmlsdGVyKCk7XG4gICAgZmlsdGVyLnNldChpbml0aWFsUmFuZ2UpO1xuICAgIHJldHVybiB7XG4gICAgICAgIGZpbHRlcjogZmlsdGVyLFxuICAgICAgICBmaWx0ZXJTcGVjaWZpZWQ6IHJhbmdlU3BlY2lmaWVkLCAvLyB0aGVyZSdzIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIG5vdCBmaWx0ZXJpbmcgYW5kIGZpbHRlcmluZyBhIG5vbi1wcm9wZXIgc3Vic2V0XG4gICAgICAgIHN2Z0JydXNoOiB7XG4gICAgICAgICAgICBleHRlbnQ6IFtdLCAvLyB0aGlzIGlzIHdoZXJlIHRoZSBzdmdCcnVzaCB3cml0ZXMgY29udGVudHMgaW50b1xuICAgICAgICAgICAgYnJ1c2hTdGFydENhbGxiYWNrOiBicnVzaFN0YXJ0Q2FsbGJhY2ssXG4gICAgICAgICAgICBicnVzaENhbGxiYWNrOiBheGlzQnJ1c2hNb3ZlZChicnVzaENhbGxiYWNrKSxcbiAgICAgICAgICAgIGJydXNoRW5kQ2FsbGJhY2s6IGJydXNoRW5kQ2FsbGJhY2tcbiAgICAgICAgfVxuICAgIH07XG59XG5cbi8vIGZvciB1c2UgYnkgc3VwcGx5RGVmYXVsdHMsIGJ1dCBpdCBuZWVkZWQgdG9ucyBvZiBwaWVjZXMgZnJvbSBoZXJlIHNvXG4vLyBzZWVtZWQgdG8gbWFrZSBtb3JlIHNlbnNlIGp1c3QgdG8gcHV0IHRoZSB3aG9sZSByb3V0aW5lIGhlcmVcbmZ1bmN0aW9uIGNsZWFuUmFuZ2VzKHJhbmdlcywgZGltZW5zaW9uKSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheShyYW5nZXNbMF0pKSB7XG4gICAgICAgIHJhbmdlcyA9IHJhbmdlcy5tYXAoZnVuY3Rpb24ocmkpIHsgcmV0dXJuIHJpLnNvcnQoc29ydEFzYyk7IH0pO1xuXG4gICAgICAgIGlmKCFkaW1lbnNpb24ubXVsdGlzZWxlY3QpIHJhbmdlcyA9IFtyYW5nZXNbMF1dO1xuICAgICAgICBlbHNlIHJhbmdlcyA9IGRlZHVwZVJlYWxSYW5nZXMocmFuZ2VzLnNvcnQoc3RhcnRBc2MpKTtcbiAgICB9IGVsc2UgcmFuZ2VzID0gW3Jhbmdlcy5zb3J0KHNvcnRBc2MpXTtcblxuICAgIC8vIG9yZGluYWwgc25hcHBpbmdcbiAgICBpZihkaW1lbnNpb24udGlja3ZhbHMpIHtcbiAgICAgICAgdmFyIHNvcnRlZFRpY2tWYWxzID0gZGltZW5zaW9uLnRpY2t2YWxzLnNsaWNlKCkuc29ydChzb3J0QXNjKTtcbiAgICAgICAgcmFuZ2VzID0gcmFuZ2VzLm1hcChmdW5jdGlvbihyaSkge1xuICAgICAgICAgICAgdmFyIHJTbmFwcGVkID0gW1xuICAgICAgICAgICAgICAgIG9yZGluYWxTY2FsZVNuYXAoMCwgc29ydGVkVGlja1ZhbHMsIHJpWzBdLCBbXSksXG4gICAgICAgICAgICAgICAgb3JkaW5hbFNjYWxlU25hcCgxLCBzb3J0ZWRUaWNrVmFscywgcmlbMV0sIFtdKVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGlmKHJTbmFwcGVkWzFdID4gclNuYXBwZWRbMF0pIHJldHVybiByU25hcHBlZDtcbiAgICAgICAgfSlcbiAgICAgICAgLmZpbHRlcihmdW5jdGlvbihyaSkgeyByZXR1cm4gcmk7IH0pO1xuXG4gICAgICAgIGlmKCFyYW5nZXMubGVuZ3RoKSByZXR1cm47XG4gICAgfVxuICAgIHJldHVybiByYW5nZXMubGVuZ3RoID4gMSA/IHJhbmdlcyA6IHJhbmdlc1swXTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbWFrZUJydXNoOiBtYWtlQnJ1c2gsXG4gICAgZW5zdXJlQXhpc0JydXNoOiBlbnN1cmVBeGlzQnJ1c2gsXG4gICAgY2xlYW5SYW5nZXM6IGNsZWFuUmFuZ2VzXG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9ndXBcIjo3MTcsXCIuL2NvbnN0YW50c1wiOjEwNzgsXCJkM1wiOjE2M31dLDEwNzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIGdldE1vZHVsZUNhbGNEYXRhID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRNb2R1bGVDYWxjRGF0YTtcbnZhciBwYXJjb29yZHNQbG90ID0gX2RlcmVxXygnLi9wbG90Jyk7XG52YXIgeG1sbnNOYW1lc3BhY2VzID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL3htbG5zX25hbWVzcGFjZXMnKTtcblxuZXhwb3J0cy5uYW1lID0gJ3BhcmNvb3Jkcyc7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGNhbGNEYXRhID0gZ2V0TW9kdWxlQ2FsY0RhdGEoZ2QuY2FsY2RhdGEsICdwYXJjb29yZHMnKVswXTtcbiAgICBpZihjYWxjRGF0YS5sZW5ndGgpIHBhcmNvb3Jkc1Bsb3QoZ2QsIGNhbGNEYXRhKTtcbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgaGFkUGFyY29vcmRzID0gKG9sZEZ1bGxMYXlvdXQuX2hhcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXMoJ3BhcmNvb3JkcycpKTtcbiAgICB2YXIgaGFzUGFyY29vcmRzID0gKG5ld0Z1bGxMYXlvdXQuX2hhcyAmJiBuZXdGdWxsTGF5b3V0Ll9oYXMoJ3BhcmNvb3JkcycpKTtcblxuICAgIGlmKGhhZFBhcmNvb3JkcyAmJiAhaGFzUGFyY29vcmRzKSB7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX3BhcGVyZGl2LnNlbGVjdEFsbCgnLnBhcmNvb3JkcycpLnJlbW92ZSgpO1xuICAgICAgICBvbGRGdWxsTGF5b3V0Ll9nbGltYWdlcy5zZWxlY3RBbGwoJyonKS5yZW1vdmUoKTtcbiAgICB9XG59O1xuXG5leHBvcnRzLnRvU1ZHID0gZnVuY3Rpb24oZ2QpIHtcbiAgICB2YXIgaW1hZ2VSb290ID0gZ2QuX2Z1bGxMYXlvdXQuX2dsaW1hZ2VzO1xuICAgIHZhciByb290ID0gZDMuc2VsZWN0KGdkKS5zZWxlY3RBbGwoJy5zdmctY29udGFpbmVyJyk7XG4gICAgdmFyIGNhbnZhc2VzID0gcm9vdC5maWx0ZXIoZnVuY3Rpb24oZCwgaSkge3JldHVybiBpID09PSByb290LnNpemUoKSAtIDE7fSlcbiAgICAgICAgLnNlbGVjdEFsbCgnLmdsLWNhbnZhcy1jb250ZXh0LCAuZ2wtY2FudmFzLWZvY3VzJyk7XG5cbiAgICBmdW5jdGlvbiBjYW52YXNUb0ltYWdlKCkge1xuICAgICAgICB2YXIgY2FudmFzID0gdGhpcztcbiAgICAgICAgdmFyIGltYWdlRGF0YSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuICAgICAgICB2YXIgaW1hZ2UgPSBpbWFnZVJvb3QuYXBwZW5kKCdzdmc6aW1hZ2UnKTtcblxuICAgICAgICBpbWFnZS5hdHRyKHtcbiAgICAgICAgICAgIHhtbG5zOiB4bWxuc05hbWVzcGFjZXMuc3ZnLFxuICAgICAgICAgICAgJ3hsaW5rOmhyZWYnOiBpbWFnZURhdGEsXG4gICAgICAgICAgICBwcmVzZXJ2ZUFzcGVjdFJhdGlvOiAnbm9uZScsXG4gICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgIHdpZHRoOiBjYW52YXMud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IGNhbnZhcy5oZWlnaHRcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgY2FudmFzZXMuZWFjaChjYW52YXNUb0ltYWdlKTtcblxuICAgIC8vIENocm9tZSAvIFNhZmFyaSBidWcgd29ya2Fyb3VuZCAtIGJyb3dzZXIgYXBwYXJlbnRseSBsb3NlcyBjb25uZWN0aW9uIHRvIHRoZSBkZWZpbmVkIHBhdHRlcm5cbiAgICAvLyBXaXRob3V0IHRoZSB3b3JrYXJvdW5kLCB0aGVzZSBicm93c2VycyAnbG9zZScgdGhlIGZpbHRlciBicnVzaCBzdHlsaW5nIChjb2xvciBldGMuKSBhZnRlciBhIHNuYXBzaG90XG4gICAgLy8gb24gYSBzdWJzZXF1ZW50IGludGVyYWN0aW9uLlxuICAgIC8vIEZpcmVmb3ggd29ya3MgZmluZSB3aXRob3V0IHRoaXMgd29ya2Fyb3VuZFxuICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICBkMy5zZWxlY3RBbGwoJyNmaWx0ZXJCYXJQYXR0ZXJuJylcbiAgICAgICAgICAgIC5hdHRyKCdpZCcsICdmaWx0ZXJCYXJQYXR0ZXJuJyk7XG4gICAgfSwgNjApO1xufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMveG1sbnNfbmFtZXNwYWNlc1wiOjY5NixcIi4uLy4uL3Bsb3RzL2dldF9kYXRhXCI6ODAyLFwiLi9wbG90XCI6MTA4NSxcImQzXCI6MTYzfV0sMTA3NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcbnZhciBDb2xvcnNjYWxlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlJyk7XG52YXIgd3JhcCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9ndXAnKS53cmFwO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGxpbmVDb2xvcjtcbiAgICB2YXIgY3NjYWxlO1xuXG4gICAgaWYoQ29sb3JzY2FsZS5oYXNDb2xvcnNjYWxlKHRyYWNlLCAnbGluZScpICYmIGlzQXJyYXlPclR5cGVkQXJyYXkodHJhY2UubGluZS5jb2xvcikpIHtcbiAgICAgICAgbGluZUNvbG9yID0gdHJhY2UubGluZS5jb2xvcjtcbiAgICAgICAgY3NjYWxlID0gQ29sb3JzY2FsZS5leHRyYWN0T3B0cyh0cmFjZS5saW5lKS5jb2xvcnNjYWxlO1xuXG4gICAgICAgIENvbG9yc2NhbGUuY2FsYyhnZCwgdHJhY2UsIHtcbiAgICAgICAgICAgIHZhbHM6IGxpbmVDb2xvcixcbiAgICAgICAgICAgIGNvbnRhaW5lclN0cjogJ2xpbmUnLFxuICAgICAgICAgICAgY0xldHRlcjogJ2MnXG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxpbmVDb2xvciA9IGNvbnN0SGFsZih0cmFjZS5fbGVuZ3RoKTtcbiAgICAgICAgY3NjYWxlID0gW1swLCB0cmFjZS5saW5lLmNvbG9yXSwgWzEsIHRyYWNlLmxpbmUuY29sb3JdXTtcbiAgICB9XG5cbiAgICByZXR1cm4gd3JhcCh7bGluZUNvbG9yOiBsaW5lQ29sb3IsIGNzY2FsZTogY3NjYWxlfSk7XG59O1xuXG5mdW5jdGlvbiBjb25zdEhhbGYobGVuKSB7XG4gICAgdmFyIG91dCA9IG5ldyBBcnJheShsZW4pO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBvdXRbaV0gPSAwLjU7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlXCI6NjA1LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL2d1cFwiOjcxN31dLDEwNzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1heERpbWVuc2lvbkNvdW50OiA2MCwgLy8gdGhpcyBjYW5ub3QgYmUgaW5jcmVhc2VkIHdpdGhvdXQgV2ViR0wgY29kZSByZWZhY3RvcmluZ1xuICAgIG92ZXJkcmFnOiA0NSxcbiAgICB2ZXJ0aWNhbFBhZGRpbmc6IDIsIC8vIG90aGVyd2lzZSwgaG9yaXpvbnRhbCBsaW5lcyBvbiB0b3Agb3IgYm90dG9tIGFyZSBvZiBsb3dlciB3aWR0aFxuICAgIHRpY2tEaXN0YW5jZTogNTAsXG4gICAgY2FudmFzUGl4ZWxSYXRpbzogMSxcbiAgICBibG9ja0xpbmVDb3VudDogNTAwMCxcbiAgICBsYXllcnM6IFsnY29udGV4dExpbmVMYXllcicsICdmb2N1c0xpbmVMYXllcicsICdwaWNrTGluZUxheWVyJ10sXG4gICAgYXhpc1RpdGxlT2Zmc2V0OiAyOCxcbiAgICBheGlzRXh0ZW50T2Zmc2V0OiAxMCxcbiAgICBkZXNlbGVjdGVkTGluZUNvbG9yOiAnIzc3NycsXG4gICAgYmFyOiB7XG4gICAgICAgIHdpZHRoOiA0LCAvLyBWaXNpYmxlIHdpZHRoIG9mIHRoZSBmaWx0ZXIgYmFyXG4gICAgICAgIGNhcHR1cmVXaWR0aDogMTAsIC8vIE1vdXNlLXNlbnNpdGl2ZSB3aWR0aCBmb3IgaW50ZXJhY3Rpb24gKEZpdHRzIGxhdylcbiAgICAgICAgZmlsbENvbG9yOiAnbWFnZW50YScsIC8vIENvbG9yIG9mIHRoZSBmaWx0ZXIgYmFyIGZpbGxcbiAgICAgICAgZmlsbE9wYWNpdHk6IDEsIC8vIEZpbHRlciBiYXIgZmlsbCBvcGFjaXR5XG4gICAgICAgIHNuYXBEdXJhdGlvbjogMTUwLCAvLyB0d2VlbiBkdXJhdGlvbiBpbiBtcyBmb3IgYnJ1c2ggc25hcCBmb3Igb3JkaW5hbCBheGVzXG4gICAgICAgIHNuYXBSYXRpbzogMC4yNSwgLy8gcmF0aW8gb2YgYmFyIGV4dGVuc2lvbiByZWxhdGl2ZSB0byB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0d28gYWRqYWNlbnQgb3JkaW5hbCB2YWx1ZXNcbiAgICAgICAgc25hcENsb3NlOiAwLjAxLCAvLyBmcmFjdGlvbiBvZiBpbnRlci12YWx1ZSBkaXN0YW5jZSB0byBzbmFwIHRvIHRoZSBjbG9zZXIgb25lLCBldmVuIGlmIHlvdSdyZSBub3Qgb3ZlciBpdFxuICAgICAgICBzdHJva2VDb2xvcjogJ3doaXRlJywgLy8gQ29sb3Igb2YgdGhlIGZpbHRlciBiYXIgc2lkZSBsaW5lc1xuICAgICAgICBzdHJva2VPcGFjaXR5OiAxLCAvLyBGaWx0ZXIgYmFyIHNpZGUgc3Ryb2tlIG9wYWNpdHlcbiAgICAgICAgc3Ryb2tlV2lkdGg6IDEsIC8vIEZpbHRlciBiYXIgc2lkZSBzdHJva2Ugd2lkdGggaW4gcGl4ZWxzXG4gICAgICAgIGhhbmRsZUhlaWdodDogOCwgLy8gSGVpZ2h0IG9mIHRoZSBmaWx0ZXIgYmFyIHZlcnRpY2FsIHJlc2l6ZSBhcmVhcyBvbiB0b3AgYW5kIGJvdHRvbVxuICAgICAgICBoYW5kbGVPcGFjaXR5OiAxLCAvLyBPcGFjaXR5IG9mIHRoZSBmaWx0ZXIgYmFyIHZlcnRpY2FsIHJlc2l6ZSBhcmVhcyBvbiB0b3AgYW5kIGJvdHRvbVxuICAgICAgICBoYW5kbGVPdmVybGFwOiAwIC8vIEEgbGFyZ2VyIHRoYW4gMCB2YWx1ZSBjYXVzZXMgb3ZlcmxhcHMgd2l0aCB0aGUgZmlsdGVyIGJhciwgcmVwcmVzZW50ZWQgYXMgcGl4ZWxzXG4gICAgfSxcbiAgICBjbjoge1xuICAgICAgICBheGlzRXh0ZW50VGV4dDogJ2F4aXMtZXh0ZW50LXRleHQnLFxuICAgICAgICBwYXJjb29yZHNMaW5lTGF5ZXJzOiAncGFyY29vcmRzLWxpbmUtbGF5ZXJzJyxcbiAgICAgICAgcGFyY29vcmRzTGluZUxheWVyOiAncGFyY29vcmRzLWxpbmVzJyxcbiAgICAgICAgcGFyY29vcmRzOiAncGFyY29vcmRzJyxcbiAgICAgICAgcGFyY29vcmRzQ29udHJvbFZpZXc6ICdwYXJjb29yZHMtY29udHJvbC12aWV3JyxcbiAgICAgICAgeUF4aXM6ICd5LWF4aXMnLFxuICAgICAgICBheGlzT3ZlcmxheXM6ICdheGlzLW92ZXJsYXlzJyxcbiAgICAgICAgYXhpczogJ2F4aXMnLFxuICAgICAgICBheGlzSGVhZGluZzogJ2F4aXMtaGVhZGluZycsXG4gICAgICAgIGF4aXNUaXRsZTogJ2F4aXMtdGl0bGUnLFxuICAgICAgICBheGlzRXh0ZW50OiAnYXhpcy1leHRlbnQnLFxuICAgICAgICBheGlzRXh0ZW50VG9wOiAnYXhpcy1leHRlbnQtdG9wJyxcbiAgICAgICAgYXhpc0V4dGVudFRvcFRleHQ6ICdheGlzLWV4dGVudC10b3AtdGV4dCcsXG4gICAgICAgIGF4aXNFeHRlbnRCb3R0b206ICdheGlzLWV4dGVudC1ib3R0b20nLFxuICAgICAgICBheGlzRXh0ZW50Qm90dG9tVGV4dDogJ2F4aXMtZXh0ZW50LWJvdHRvbS10ZXh0JyxcbiAgICAgICAgYXhpc0JydXNoOiAnYXhpcy1icnVzaCdcbiAgICB9LFxuICAgIGlkOiB7XG4gICAgICAgIGZpbHRlckJhclBhdHRlcm46ICdmaWx0ZXItYmFyLXBhdHRlcm4nXG5cbiAgICB9XG59O1xuXG59LHt9XSwxMDc5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGhhc0NvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvaGVscGVycycpLmhhc0NvbG9yc2NhbGU7XG52YXIgY29sb3JzY2FsZURlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlRG9tYWluRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9kb21haW4nKS5kZWZhdWx0cztcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG52YXIgYXhpc0JydXNoID0gX2RlcmVxXygnLi9heGlzYnJ1c2gnKTtcbnZhciBtYXhEaW1lbnNpb25Db3VudCA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJykubWF4RGltZW5zaW9uQ291bnQ7XG52YXIgbWVyZ2VMZW5ndGggPSBfZGVyZXFfKCcuL21lcmdlX2xlbmd0aCcpO1xuXG5mdW5jdGlvbiBoYW5kbGVMaW5lRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpIHtcbiAgICB2YXIgbGluZUNvbG9yID0gY29lcmNlKCdsaW5lLmNvbG9yJywgZGVmYXVsdENvbG9yKTtcblxuICAgIGlmKGhhc0NvbG9yc2NhbGUodHJhY2VJbiwgJ2xpbmUnKSAmJiBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShsaW5lQ29sb3IpKSB7XG4gICAgICAgIGlmKGxpbmVDb2xvci5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnbGluZS5jb2xvcnNjYWxlJyk7XG4gICAgICAgICAgICBjb2xvcnNjYWxlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnbGluZS4nLCBjTGV0dGVyOiAnYyd9KTtcbiAgICAgICAgICAgIC8vIFRPRE86IEkgdGhpbmsgaXQgd291bGQgYmUgYmV0dGVyIHRvIGtlZXAgc2hvd2luZyBsaW5lcyBiZXlvbmQgdGhlIGxhc3QgbGluZSBjb2xvclxuICAgICAgICAgICAgLy8gYnV0IEknbSBub3Qgc3VyZSB3aGF0IGNvbG9yIHRvIGdpdmUgdGhlc2UgbGluZXMgLSBwcm9iYWJseSBibGFjayBvciB3aGl0ZVxuICAgICAgICAgICAgLy8gZGVwZW5kaW5nIG9uIHRoZSBiYWNrZ3JvdW5kIGNvbG9yP1xuICAgICAgICAgICAgcmV0dXJuIGxpbmVDb2xvci5sZW5ndGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0cmFjZU91dC5saW5lLmNvbG9yID0gZGVmYXVsdENvbG9yO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBJbmZpbml0eTtcbn1cblxuZnVuY3Rpb24gZGltZW5zaW9uRGVmYXVsdHMoZGltZW5zaW9uSW4sIGRpbWVuc2lvbk91dCwgcGFyZW50T3V0LCBvcHRzKSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoZGltZW5zaW9uSW4sIGRpbWVuc2lvbk91dCwgYXR0cmlidXRlcy5kaW1lbnNpb25zLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdmFsdWVzID0gY29lcmNlKCd2YWx1ZXMnKTtcbiAgICB2YXIgdmlzaWJsZSA9IGNvZXJjZSgndmlzaWJsZScpO1xuICAgIGlmKCEodmFsdWVzICYmIHZhbHVlcy5sZW5ndGgpKSB7XG4gICAgICAgIHZpc2libGUgPSBkaW1lbnNpb25PdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmKHZpc2libGUpIHtcbiAgICAgICAgY29lcmNlKCdsYWJlbCcpO1xuICAgICAgICBjb2VyY2UoJ3RpY2t2YWxzJyk7XG4gICAgICAgIGNvZXJjZSgndGlja3RleHQnKTtcbiAgICAgICAgY29lcmNlKCd0aWNrZm9ybWF0Jyk7XG4gICAgICAgIHZhciByYW5nZSA9IGNvZXJjZSgncmFuZ2UnKTtcblxuICAgICAgICBkaW1lbnNpb25PdXQuX2F4ID0ge1xuICAgICAgICAgICAgX2lkOiAneScsXG4gICAgICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgICAgIHNob3dleHBvbmVudDogJ2FsbCcsXG4gICAgICAgICAgICBleHBvbmVudGZvcm1hdDogJ0InLFxuICAgICAgICAgICAgcmFuZ2U6IHJhbmdlXG4gICAgICAgIH07XG5cbiAgICAgICAgQXhlcy5zZXRDb252ZXJ0KGRpbWVuc2lvbk91dC5fYXgsIG9wdHMubGF5b3V0KTtcblxuICAgICAgICBjb2VyY2UoJ211bHRpc2VsZWN0Jyk7XG4gICAgICAgIHZhciBjb25zdHJhaW50UmFuZ2UgPSBjb2VyY2UoJ2NvbnN0cmFpbnRyYW5nZScpO1xuICAgICAgICBpZihjb25zdHJhaW50UmFuZ2UpIHtcbiAgICAgICAgICAgIGRpbWVuc2lvbk91dC5jb25zdHJhaW50cmFuZ2UgPSBheGlzQnJ1c2guY2xlYW5SYW5nZXMoY29uc3RyYWludFJhbmdlLCBkaW1lbnNpb25PdXQpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgZGltZW5zaW9uc0luID0gdHJhY2VJbi5kaW1lbnNpb25zO1xuICAgIGlmKEFycmF5LmlzQXJyYXkoZGltZW5zaW9uc0luKSAmJiBkaW1lbnNpb25zSW4ubGVuZ3RoID4gbWF4RGltZW5zaW9uQ291bnQpIHtcbiAgICAgICAgTGliLmxvZygncGFyY29vcmRzIHRyYWNlcyBzdXBwb3J0IHVwIHRvICcgKyBtYXhEaW1lbnNpb25Db3VudCArICcgZGltZW5zaW9ucyBhdCB0aGUgbW9tZW50Jyk7XG4gICAgICAgIGRpbWVuc2lvbnNJbi5zcGxpY2UobWF4RGltZW5zaW9uQ291bnQpO1xuICAgIH1cblxuICAgIHZhciBkaW1lbnNpb25zID0gaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwge1xuICAgICAgICBuYW1lOiAnZGltZW5zaW9ucycsXG4gICAgICAgIGxheW91dDogbGF5b3V0LFxuICAgICAgICBoYW5kbGVJdGVtRGVmYXVsdHM6IGRpbWVuc2lvbkRlZmF1bHRzXG4gICAgfSk7XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcblxuICAgIGhhbmRsZURvbWFpbkRlZmF1bHRzKHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICBpZighQXJyYXkuaXNBcnJheShkaW1lbnNpb25zKSB8fCAhZGltZW5zaW9ucy5sZW5ndGgpIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIG1lcmdlTGVuZ3RoKHRyYWNlT3V0LCBkaW1lbnNpb25zLCAndmFsdWVzJywgbGVuKTtcblxuICAgIC8vIG1ha2UgZGVmYXVsdCBmb250IHNpemUgMTBweCAoZGVmYXVsdCBpcyAxMiksXG4gICAgLy8gc2NhbGUgbGluZWFybHkgd2l0aCBnbG9iYWwgZm9udCBzaXplXG4gICAgdmFyIGZvbnREZmx0ID0ge1xuICAgICAgICBmYW1pbHk6IGxheW91dC5mb250LmZhbWlseSxcbiAgICAgICAgc2l6ZTogTWF0aC5yb3VuZChsYXlvdXQuZm9udC5zaXplIC8gMS4yKSxcbiAgICAgICAgY29sb3I6IGxheW91dC5mb250LmNvbG9yXG4gICAgfTtcblxuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ2xhYmVsZm9udCcsIGZvbnREZmx0KTtcbiAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICd0aWNrZm9udCcsIGZvbnREZmx0KTtcbiAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICdyYW5nZWZvbnQnLCBmb250RGZsdCk7XG5cbiAgICBjb2VyY2UoJ2xhYmVsYW5nbGUnKTtcbiAgICBjb2VyY2UoJ2xhYmVsc2lkZScpO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHNcIjo2MDMsXCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvaGVscGVyc1wiOjYwNCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0c1wiOjc2MyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vLi4vcGxvdHMvZG9tYWluXCI6NzkyLFwiLi9hdHRyaWJ1dGVzXCI6MTA3NCxcIi4vYXhpc2JydXNoXCI6MTA3NSxcIi4vY29uc3RhbnRzXCI6MTA3OCxcIi4vbWVyZ2VfbGVuZ3RoXCI6MTA4M31dLDEwODA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNUeXBlZEFycmF5O1xuXG5leHBvcnRzLmNvbnZlcnRUeXBlZEFycmF5ID0gZnVuY3Rpb24oYSkge1xuICAgIHJldHVybiBpc1R5cGVkQXJyYXkoYSkgPyBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhKSA6IGE7XG59O1xuXG5leHBvcnRzLmlzT3JkaW5hbCA9IGZ1bmN0aW9uKGRpbWVuc2lvbikge1xuICAgIHJldHVybiAhIWRpbWVuc2lvbi50aWNrdmFscztcbn07XG5cbmV4cG9ydHMuaXNWaXNpYmxlID0gZnVuY3Rpb24oZGltZW5zaW9uKSB7XG4gICAgcmV0dXJuIGRpbWVuc2lvbi52aXNpYmxlIHx8ICEoJ3Zpc2libGUnIGluIGRpbWVuc2lvbik7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOX1dLDEwODE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIGNvbG9yYmFyOiB7XG4gICAgICAgIGNvbnRhaW5lcjogJ2xpbmUnLFxuICAgICAgICBtaW46ICdjbWluJyxcbiAgICAgICAgbWF4OiAnY21heCdcbiAgICB9LFxuXG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAncGFyY29vcmRzJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi9iYXNlX3Bsb3QnKSxcbiAgICBjYXRlZ29yaWVzOiBbJ2dsJywgJ3JlZ2wnLCAnbm9PcGFjaXR5JywgJ25vSG92ZXInXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi9hdHRyaWJ1dGVzXCI6MTA3NCxcIi4vYmFzZV9wbG90XCI6MTA3NixcIi4vY2FsY1wiOjEwNzcsXCIuL2RlZmF1bHRzXCI6MTA3OSxcIi4vcGxvdFwiOjEwODV9XSwxMDgyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGdsc2xpZnkgPSBfZGVyZXFfKCdnbHNsaWZ5Jyk7XG52YXIgdmVydGV4U2hhZGVyU291cmNlID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcblxcbmF0dHJpYnV0ZSB2ZWM0IHAwMV8wNCwgcDA1XzA4LCBwMDlfMTIsIHAxM18xNixcXG4gICAgICAgICAgICAgICBwMTdfMjAsIHAyMV8yNCwgcDI1XzI4LCBwMjlfMzIsXFxuICAgICAgICAgICAgICAgcDMzXzM2LCBwMzdfNDAsIHA0MV80NCwgcDQ1XzQ4LFxcbiAgICAgICAgICAgICAgIHA0OV81MiwgcDUzXzU2LCBwNTdfNjAsIGNvbG9ycztcXG5cXG51bmlmb3JtIG1hdDQgZGltMEEsIGRpbTFBLCBkaW0wQiwgZGltMUIsIGRpbTBDLCBkaW0xQywgZGltMEQsIGRpbTFELFxcbiAgICAgICAgICAgICBsb0EsIGhpQSwgbG9CLCBoaUIsIGxvQywgaGlDLCBsb0QsIGhpRDtcXG5cXG51bmlmb3JtIHZlYzIgcmVzb2x1dGlvbiwgdmlld0JveFBvcywgdmlld0JveFNpemU7XFxudW5pZm9ybSBzYW1wbGVyMkQgbWFzaywgcGFsZXR0ZTtcXG51bmlmb3JtIGZsb2F0IG1hc2tIZWlnaHQ7XFxudW5pZm9ybSBmbG9hdCBkcndMYXllcjsgLy8gMDogY29udGV4dCwgMTogZm9jdXMsIDI6IHBpY2tcXG51bmlmb3JtIHZlYzQgY29udGV4dENvbG9yO1xcblxcbmJvb2wgaXNQaWNrICAgID0gKGRyd0xheWVyID4gMS41KTtcXG5ib29sIGlzQ29udGV4dCA9IChkcndMYXllciA8IDAuNSk7XFxuXFxuY29uc3QgdmVjNCBaRVJPUyA9IHZlYzQoMC4wLCAwLjAsIDAuMCwgMC4wKTtcXG5jb25zdCB2ZWM0IFVOSVRTID0gdmVjNCgxLjAsIDEuMCwgMS4wLCAxLjApO1xcblxcbmZsb2F0IHZhbChtYXQ0IHAsIG1hdDQgdikge1xcbiAgICByZXR1cm4gZG90KG1hdHJpeENvbXBNdWx0KHAsIHYpICogVU5JVFMsIFVOSVRTKTtcXG59XFxuXFxuZmxvYXQgYXhpc1koZmxvYXQgcmF0aW8sIG1hdDQgQSwgbWF0NCBCLCBtYXQ0IEMsIG1hdDQgRCkge1xcbiAgICBmbG9hdCB5MSA9IHZhbChBLCBkaW0wQSkgKyB2YWwoQiwgZGltMEIpICsgdmFsKEMsIGRpbTBDKSArIHZhbChELCBkaW0wRCk7XFxuICAgIGZsb2F0IHkyID0gdmFsKEEsIGRpbTFBKSArIHZhbChCLCBkaW0xQikgKyB2YWwoQywgZGltMUMpICsgdmFsKEQsIGRpbTFEKTtcXG4gICAgcmV0dXJuIHkxICogKDEuMCAtIHJhdGlvKSArIHkyICogcmF0aW87XFxufVxcblxcbmludCBpTW9kKGludCBhLCBpbnQgYikge1xcbiAgICByZXR1cm4gYSAtIGIgKiAoYSAvIGIpO1xcbn1cXG5cXG5ib29sIGZPdXRzaWRlKGZsb2F0IHAsIGZsb2F0IGxvLCBmbG9hdCBoaSkge1xcbiAgICByZXR1cm4gKGxvIDwgaGkpICYmIChsbyA+IHAgfHwgcCA+IGhpKTtcXG59XFxuXFxuYm9vbCB2T3V0c2lkZSh2ZWM0IHAsIHZlYzQgbG8sIHZlYzQgaGkpIHtcXG4gICAgcmV0dXJuIChcXG4gICAgICAgIGZPdXRzaWRlKHBbMF0sIGxvWzBdLCBoaVswXSkgfHxcXG4gICAgICAgIGZPdXRzaWRlKHBbMV0sIGxvWzFdLCBoaVsxXSkgfHxcXG4gICAgICAgIGZPdXRzaWRlKHBbMl0sIGxvWzJdLCBoaVsyXSkgfHxcXG4gICAgICAgIGZPdXRzaWRlKHBbM10sIGxvWzNdLCBoaVszXSlcXG4gICAgKTtcXG59XFxuXFxuYm9vbCBtT3V0c2lkZShtYXQ0IHAsIG1hdDQgbG8sIG1hdDQgaGkpIHtcXG4gICAgcmV0dXJuIChcXG4gICAgICAgIHZPdXRzaWRlKHBbMF0sIGxvWzBdLCBoaVswXSkgfHxcXG4gICAgICAgIHZPdXRzaWRlKHBbMV0sIGxvWzFdLCBoaVsxXSkgfHxcXG4gICAgICAgIHZPdXRzaWRlKHBbMl0sIGxvWzJdLCBoaVsyXSkgfHxcXG4gICAgICAgIHZPdXRzaWRlKHBbM10sIGxvWzNdLCBoaVszXSlcXG4gICAgKTtcXG59XFxuXFxuYm9vbCBvdXRzaWRlQm91bmRpbmdCb3gobWF0NCBBLCBtYXQ0IEIsIG1hdDQgQywgbWF0NCBEKSB7XFxuICAgIHJldHVybiBtT3V0c2lkZShBLCBsb0EsIGhpQSkgfHxcXG4gICAgICAgICAgIG1PdXRzaWRlKEIsIGxvQiwgaGlCKSB8fFxcbiAgICAgICAgICAgbU91dHNpZGUoQywgbG9DLCBoaUMpIHx8XFxuICAgICAgICAgICBtT3V0c2lkZShELCBsb0QsIGhpRCk7XFxufVxcblxcbmJvb2wgb3V0c2lkZVJhc3Rlck1hc2sobWF0NCBBLCBtYXQ0IEIsIG1hdDQgQywgbWF0NCBEKSB7XFxuICAgIG1hdDQgcG50c1s0XTtcXG4gICAgcG50c1swXSA9IEE7XFxuICAgIHBudHNbMV0gPSBCO1xcbiAgICBwbnRzWzJdID0gQztcXG4gICAgcG50c1szXSA9IEQ7XFxuXFxuICAgIGZvcihpbnQgaSA9IDA7IGkgPCA0OyArK2kpIHtcXG4gICAgICAgIGZvcihpbnQgaiA9IDA7IGogPCA0OyArK2opIHtcXG4gICAgICAgICAgICBmb3IoaW50IGsgPSAwOyBrIDwgNDsgKytrKSB7XFxuICAgICAgICAgICAgICAgIGlmKDAgPT0gaU1vZChcXG4gICAgICAgICAgICAgICAgICAgIGludCgyNTUuMCAqIHRleHR1cmUyRChtYXNrLFxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZlYzIoXFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChmbG9hdChpICogMiArIGogLyAyKSArIDAuNSkgLyA4LjAsXFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwbnRzW2ldW2pdW2tdICogKG1hc2tIZWlnaHQgLSAxLjApICsgMS4wKSAvIG1hc2tIZWlnaHRcXG4gICAgICAgICAgICAgICAgICAgICAgICApKVszXVxcbiAgICAgICAgICAgICAgICAgICAgKSAvIGludChwb3coMi4wLCBmbG9hdChpTW9kKGogKiA0ICsgaywgOCkpKSksXFxuICAgICAgICAgICAgICAgICAgICAyXFxuICAgICAgICAgICAgICAgICkpIHJldHVybiB0cnVlO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgIH1cXG4gICAgfVxcbiAgICByZXR1cm4gZmFsc2U7XFxufVxcblxcbnZlYzQgcG9zaXRpb24oYm9vbCBpc0NvbnRleHQsIGZsb2F0IHYsIG1hdDQgQSwgbWF0NCBCLCBtYXQ0IEMsIG1hdDQgRCkge1xcbiAgICBmbG9hdCB4ID0gMC41ICogc2lnbih2KSArIDAuNTtcXG4gICAgZmxvYXQgeSA9IGF4aXNZKHgsIEEsIEIsIEMsIEQpO1xcbiAgICBmbG9hdCB6ID0gMS4wIC0gYWJzKHYpO1xcblxcbiAgICB6ICs9IGlzQ29udGV4dCA/IDAuMCA6IDIuMCAqIGZsb2F0KFxcbiAgICAgICAgb3V0c2lkZUJvdW5kaW5nQm94KEEsIEIsIEMsIEQpIHx8XFxuICAgICAgICBvdXRzaWRlUmFzdGVyTWFzayhBLCBCLCBDLCBEKVxcbiAgICApO1xcblxcbiAgICByZXR1cm4gdmVjNChcXG4gICAgICAgIDIuMCAqICh2ZWMyKHgsIHkpICogdmlld0JveFNpemUgKyB2aWV3Qm94UG9zKSAvIHJlc29sdXRpb24gLSAxLjAsXFxuICAgICAgICB6LFxcbiAgICAgICAgMS4wXFxuICAgICk7XFxufVxcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgbWF0NCBBID0gbWF0NChwMDFfMDQsIHAwNV8wOCwgcDA5XzEyLCBwMTNfMTYpO1xcbiAgICBtYXQ0IEIgPSBtYXQ0KHAxN18yMCwgcDIxXzI0LCBwMjVfMjgsIHAyOV8zMik7XFxuICAgIG1hdDQgQyA9IG1hdDQocDMzXzM2LCBwMzdfNDAsIHA0MV80NCwgcDQ1XzQ4KTtcXG4gICAgbWF0NCBEID0gbWF0NChwNDlfNTIsIHA1M181NiwgcDU3XzYwLCBaRVJPUyk7XFxuXFxuICAgIGZsb2F0IHYgPSBjb2xvcnNbM107XFxuXFxuICAgIGdsX1Bvc2l0aW9uID0gcG9zaXRpb24oaXNDb250ZXh0LCB2LCBBLCBCLCBDLCBEKTtcXG5cXG4gICAgZnJhZ0NvbG9yID1cXG4gICAgICAgIGlzQ29udGV4dCA/IHZlYzQoY29udGV4dENvbG9yKSA6XFxuICAgICAgICBpc1BpY2sgPyB2ZWM0KGNvbG9ycy5yZ2IsIDEuMCkgOiB0ZXh0dXJlMkQocGFsZXR0ZSwgdmVjMihhYnModiksIDAuNSkpO1xcbn1cXG5cIl0pO1xudmFyIGZyYWdtZW50U2hhZGVyU291cmNlID0gZ2xzbGlmeShbXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XFxuI2RlZmluZSBHTFNMSUZZIDFcXG5cXG52YXJ5aW5nIHZlYzQgZnJhZ0NvbG9yO1xcblxcbnZvaWQgbWFpbigpIHtcXG4gICAgZ2xfRnJhZ0NvbG9yID0gZnJhZ0NvbG9yO1xcbn1cXG5cIl0pO1xudmFyIG1heERpbSA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJykubWF4RGltZW5zaW9uQ291bnQ7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxuLy8gZG9uJ3QgY2hhbmdlOyBvdGhlcndpc2UgbmVhci9mYXIgcGxhbmUgbGluZXMgYXJlIGxvc3RcbnZhciBkZXB0aExpbWl0RXBzaWxvbiA9IDFlLTY7XG5cbi8vIHByZWNpc2lvbiBvZiBtdWx0aXNlbGVjdCBpcyB0aGUgZnVsbCByYW5nZSBkaXZpZGVkIGludG8gdGhpcyBtYW55IHBhcnRzXG52YXIgbWFza0hlaWdodCA9IDIwNDg7XG5cbnZhciBkdW1teVBpeGVsID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG52YXIgZGF0YVBpeGVsID0gbmV3IFVpbnQ4QXJyYXkoNCk7XG5cbnZhciBwYWxldHRlVGV4dHVyZUNvbmZpZyA9IHtcbiAgICBzaGFwZTogWzI1NiwgMV0sXG4gICAgZm9ybWF0OiAncmdiYScsXG4gICAgdHlwZTogJ3VpbnQ4JyxcbiAgICBtYWc6ICduZWFyZXN0JyxcbiAgICBtaW46ICduZWFyZXN0J1xufTtcblxuZnVuY3Rpb24gZW5zdXJlRHJhdyhyZWdsKSB7XG4gICAgcmVnbC5yZWFkKHtcbiAgICAgICAgeDogMCxcbiAgICAgICAgeTogMCxcbiAgICAgICAgd2lkdGg6IDEsXG4gICAgICAgIGhlaWdodDogMSxcbiAgICAgICAgZGF0YTogZHVtbXlQaXhlbFxuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBjbGVhcihyZWdsLCB4LCB5LCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIGdsID0gcmVnbC5fZ2w7XG4gICAgZ2wuZW5hYmxlKGdsLlNDSVNTT1JfVEVTVCk7XG4gICAgZ2wuc2Npc3Nvcih4LCB5LCB3aWR0aCwgaGVpZ2h0KTtcbiAgICByZWdsLmNsZWFyKHtjb2xvcjogWzAsIDAsIDAsIDBdLCBkZXB0aDogMX0pOyAvLyBjbGVhcmluZyBpcyBkb25lIGluIHNjaXNzb3JlZCBwYW5lbCBvbmx5XG59XG5cbmZ1bmN0aW9uIHJlbmRlckJsb2NrKHJlZ2wsIGdsQWVzLCByZW5kZXJTdGF0ZSwgYmxvY2tMaW5lQ291bnQsIHNhbXBsZUNvdW50LCBpdGVtKSB7XG4gICAgdmFyIHJhZktleSA9IGl0ZW0ua2V5O1xuXG4gICAgZnVuY3Rpb24gcmVuZGVyKGJsb2NrTnVtYmVyKSB7XG4gICAgICAgIHZhciBjb3VudCA9IE1hdGgubWluKGJsb2NrTGluZUNvdW50LCBzYW1wbGVDb3VudCAtIGJsb2NrTnVtYmVyICogYmxvY2tMaW5lQ291bnQpO1xuXG4gICAgICAgIGlmKGJsb2NrTnVtYmVyID09PSAwKSB7XG4gICAgICAgICAgICAvLyBzdG9wIGRyYXdpbmcgcG9zc2libHkgc3RhbGUgZ2x5cGhzIGJlZm9yZSBjbGVhcmluZ1xuICAgICAgICAgICAgd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lKHJlbmRlclN0YXRlLmN1cnJlbnRSYWZzW3JhZktleV0pO1xuICAgICAgICAgICAgZGVsZXRlIHJlbmRlclN0YXRlLmN1cnJlbnRSYWZzW3JhZktleV07XG4gICAgICAgICAgICBjbGVhcihyZWdsLCBpdGVtLnNjaXNzb3JYLCBpdGVtLnNjaXNzb3JZLCBpdGVtLnNjaXNzb3JXaWR0aCwgaXRlbS52aWV3Qm94U2l6ZVsxXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihyZW5kZXJTdGF0ZS5jbGVhck9ubHkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGl0ZW0uY291bnQgPSAyICogY291bnQ7XG4gICAgICAgIGl0ZW0ub2Zmc2V0ID0gMiAqIGJsb2NrTnVtYmVyICogYmxvY2tMaW5lQ291bnQ7XG4gICAgICAgIGdsQWVzKGl0ZW0pO1xuXG4gICAgICAgIGlmKGJsb2NrTnVtYmVyICogYmxvY2tMaW5lQ291bnQgKyBjb3VudCA8IHNhbXBsZUNvdW50KSB7XG4gICAgICAgICAgICByZW5kZXJTdGF0ZS5jdXJyZW50UmFmc1tyYWZLZXldID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZShmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZW5kZXIoYmxvY2tOdW1iZXIgKyAxKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVuZGVyU3RhdGUuZHJhd0NvbXBsZXRlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmKCFyZW5kZXJTdGF0ZS5kcmF3Q29tcGxldGVkKSB7XG4gICAgICAgIGVuc3VyZURyYXcocmVnbCk7XG4gICAgICAgIHJlbmRlclN0YXRlLmRyYXdDb21wbGV0ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIHN0YXJ0IHdpdGggcmVuZGVyaW5nIGl0ZW0gMDsgcmVjdXJzaW9uIGhhbmRsZXMgdGhlIHJlc3RcbiAgICByZW5kZXIoMCk7XG59XG5cbmZ1bmN0aW9uIGFkanVzdERlcHRoKGQpIHtcbiAgICAvLyBXZWJHTCBtYXRyaXggb3BlcmF0aW9ucyB1c2UgZmxvYXRzIHdpdGggbGltaXRlZCBwcmVjaXNpb24sIHBvdGVudGlhbGx5IGNhdXNpbmcgYSBudW1iZXIgbmVhciBhIGJvcmRlciBvZiBbMCwgMV1cbiAgICAvLyB0byBlbmQgdXAgc2xpZ2h0bHkgb3V0c2lkZSB0aGUgYm9yZGVyLiBXaXRoIGFuIGVwc2lsb24sIHdlIHJlZHVjZSB0aGUgY2hhbmNlIHRoYXQgYSBsaW5lIGdldHMgY2xpcHBlZCBieSB0aGVcbiAgICAvLyBuZWFyIG9yIHRoZSBmYXIgcGxhbmUuXG4gICAgcmV0dXJuIE1hdGgubWF4KGRlcHRoTGltaXRFcHNpbG9uLCBNYXRoLm1pbigxIC0gZGVwdGhMaW1pdEVwc2lsb24sIGQpKTtcbn1cblxuZnVuY3Rpb24gcGFsZXR0ZSh1bml0VG9Db2xvciwgb3BhY2l0eSkge1xuICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkoMjU2KTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgMjU2OyBpKyspIHtcbiAgICAgICAgcmVzdWx0W2ldID0gdW5pdFRvQ29sb3IoaSAvIDI1NSkuY29uY2F0KG9wYWNpdHkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vLyBNYXBzIHRoZSBzYW1wbGUgaW5kZXggWzAuLi5zYW1wbGVDb3VudCAtIDFdIHRvIGEgcmFuZ2Ugb2YgWzAsIDFdIGFzIHRoZSBzaGFkZXIgZXhwZWN0cyBjb2xvcnMgaW4gdGhlIFswLCAxXSByYW5nZS5cbi8vIGJ1dCBmaXJzdCBpdCBzaGlmdHMgdGhlIHNhbXBsZSBpbmRleCBieSAwLCA4IG9yIDE2IGJpdHMgZGVwZW5kaW5nIG9uIHJnYkluZGV4IFswLi4yXVxuLy8gd2l0aCB0aGUgZW5kIHJlc3VsdCB0aGF0IGVhY2ggbGluZSB3aWxsIGJlIG9mIGEgdW5pcXVlIGNvbG9yLCBtYWtpbmcgaXQgcG9zc2libGUgZm9yIHRoZSBwaWNrIGhhbmRsZXJcbi8vIHRvIHVuaXF1ZWx5IGlkZW50aWZ5IHdoaWNoIGxpbmUgaXMgaG92ZXJlZCBvdmVyIChiaWplY3RpdmUgbWFwcGluZykuXG4vLyBUaGUgaW52ZXJzZSwgaS5lLiByZWFkUGl4ZWwgaXMgaW52b2tlZCBmcm9tICdwYXJjb29yZHMuanMnXG5mdW5jdGlvbiBjYWxjUGlja0NvbG9yKGksIHJnYkluZGV4KSB7XG4gICAgcmV0dXJuIChpID4+PiA4ICogcmdiSW5kZXgpICUgMjU2IC8gMjU1O1xufVxuXG5mdW5jdGlvbiBtYWtlUG9pbnRzKHNhbXBsZUNvdW50LCBkaW1zLCBjb2xvcikge1xuICAgIHZhciBwb2ludHMgPSBuZXcgQXJyYXkoc2FtcGxlQ291bnQgKiAobWF4RGltICsgNCkpO1xuICAgIHZhciBuID0gMDtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2FtcGxlQ291bnQ7IGkrKykge1xuICAgICAgICBmb3IodmFyIGsgPSAwOyBrIDwgbWF4RGltOyBrKyspIHtcbiAgICAgICAgICAgIHBvaW50c1tuKytdID0gKGsgPCBkaW1zLmxlbmd0aCkgPyBkaW1zW2tdLnBhZGRlZFVuaXRWYWx1ZXNbaV0gOiAwLjU7XG4gICAgICAgIH1cbiAgICAgICAgcG9pbnRzW24rK10gPSBjYWxjUGlja0NvbG9yKGksIDIpO1xuICAgICAgICBwb2ludHNbbisrXSA9IGNhbGNQaWNrQ29sb3IoaSwgMSk7XG4gICAgICAgIHBvaW50c1tuKytdID0gY2FsY1BpY2tDb2xvcihpLCAwKTtcbiAgICAgICAgcG9pbnRzW24rK10gPSBhZGp1c3REZXB0aChjb2xvcltpXSk7XG4gICAgfVxuICAgIHJldHVybiBwb2ludHM7XG59XG5cbmZ1bmN0aW9uIG1ha2VWZWNBdHRyKHZlY0luZGV4LCBzYW1wbGVDb3VudCwgcG9pbnRzKSB7XG4gICAgdmFyIHBvaW50UGFpcnMgPSBuZXcgQXJyYXkoc2FtcGxlQ291bnQgKiA4KTtcbiAgICB2YXIgbiA9IDA7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNhbXBsZUNvdW50OyBpKyspIHtcbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IDI7IGorKykge1xuICAgICAgICAgICAgZm9yKHZhciBrID0gMDsgayA8IDQ7IGsrKykge1xuICAgICAgICAgICAgICAgIHZhciBxID0gdmVjSW5kZXggKiA0ICsgaztcbiAgICAgICAgICAgICAgICB2YXIgdiA9IHBvaW50c1tpICogNjQgKyBxXTtcbiAgICAgICAgICAgICAgICBpZihxID09PSA2MyAmJiBqID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHYgKj0gLTE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHBvaW50UGFpcnNbbisrXSA9IHY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBvaW50UGFpcnM7XG59XG5cbmZ1bmN0aW9uIHBhZDIobnVtKSB7XG4gICAgdmFyIHMgPSAnMCcgKyBudW07XG4gICAgcmV0dXJuIHMuc3Vic3RyKHMubGVuZ3RoIC0gMik7XG59XG5cbmZ1bmN0aW9uIGdldEF0dHJOYW1lKGkpIHtcbiAgICByZXR1cm4gKGkgPCBtYXhEaW0pID8gJ3AnICsgcGFkMihpICsgMSkgKyAnXycgKyBwYWQyKGkgKyA0KSA6ICdjb2xvcnMnO1xufVxuXG5mdW5jdGlvbiBzZXRBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMsIHNhbXBsZUNvdW50LCBwb2ludHMpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDw9IG1heERpbTsgaSArPSA0KSB7XG4gICAgICAgIGF0dHJpYnV0ZXNbZ2V0QXR0ck5hbWUoaSldKG1ha2VWZWNBdHRyKGkgLyA0LCBzYW1wbGVDb3VudCwgcG9pbnRzKSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBlbXB0eUF0dHJpYnV0ZXMocmVnbCkge1xuICAgIHZhciBhdHRyaWJ1dGVzID0ge307XG4gICAgZm9yKHZhciBpID0gMDsgaSA8PSBtYXhEaW07IGkgKz0gNCkge1xuICAgICAgICBhdHRyaWJ1dGVzW2dldEF0dHJOYW1lKGkpXSA9IHJlZ2wuYnVmZmVyKHt1c2FnZTogJ2R5bmFtaWMnLCB0eXBlOiAnZmxvYXQnLCBkYXRhOiBuZXcgVWludDhBcnJheSgwKX0pO1xuICAgIH1cbiAgICByZXR1cm4gYXR0cmlidXRlcztcbn1cblxuZnVuY3Rpb24gbWFrZUl0ZW0obW9kZWwsIGxlZnRtb3N0LCByaWdodG1vc3QsIGl0ZW1OdW1iZXIsIGkwLCBpMSwgeCwgeSwgcGFuZWxTaXplWCwgcGFuZWxTaXplWSwgY3Jvc3NmaWx0ZXJEaW1lbnNpb25JbmRleCwgZHJ3TGF5ZXIsIGNvbnN0cmFpbnRzKSB7XG4gICAgdmFyIGRpbXMgPSBbW10sIFtdXTtcbiAgICBmb3IodmFyIGsgPSAwOyBrIDwgNjQ7IGsrKykge1xuICAgICAgICBkaW1zWzBdW2tdID0gKGsgPT09IGkwKSA/IDEgOiAwO1xuICAgICAgICBkaW1zWzFdW2tdID0gKGsgPT09IGkxKSA/IDEgOiAwO1xuICAgIH1cblxuICAgIHZhciBvdmVyZHJhZyA9IG1vZGVsLmxpbmVzLmNhbnZhc092ZXJkcmFnO1xuICAgIHZhciBkb21haW4gPSBtb2RlbC5kb21haW47XG4gICAgdmFyIGNhbnZhc1dpZHRoID0gbW9kZWwuY2FudmFzV2lkdGg7XG4gICAgdmFyIGNhbnZhc0hlaWdodCA9IG1vZGVsLmNhbnZhc0hlaWdodDtcblxuICAgIHZhciBkZXNlbGVjdGVkTGluZXNDb2xvciA9IG1vZGVsLmRlc2VsZWN0ZWRMaW5lcy5jb2xvcjtcblxuICAgIHZhciBpdGVtTW9kZWwgPSBMaWIuZXh0ZW5kRmxhdCh7XG4gICAgICAgIGtleTogY3Jvc3NmaWx0ZXJEaW1lbnNpb25JbmRleCxcbiAgICAgICAgcmVzb2x1dGlvbjogW2NhbnZhc1dpZHRoLCBjYW52YXNIZWlnaHRdLFxuICAgICAgICB2aWV3Qm94UG9zOiBbeCArIG92ZXJkcmFnLCB5XSxcbiAgICAgICAgdmlld0JveFNpemU6IFtwYW5lbFNpemVYLCBwYW5lbFNpemVZXSxcbiAgICAgICAgaTA6IGkwLFxuICAgICAgICBpMTogaTEsXG5cbiAgICAgICAgZGltMEE6IGRpbXNbMF0uc2xpY2UoMCwgMTYpLFxuICAgICAgICBkaW0wQjogZGltc1swXS5zbGljZSgxNiwgMzIpLFxuICAgICAgICBkaW0wQzogZGltc1swXS5zbGljZSgzMiwgNDgpLFxuICAgICAgICBkaW0wRDogZGltc1swXS5zbGljZSg0OCwgNjQpLFxuICAgICAgICBkaW0xQTogZGltc1sxXS5zbGljZSgwLCAxNiksXG4gICAgICAgIGRpbTFCOiBkaW1zWzFdLnNsaWNlKDE2LCAzMiksXG4gICAgICAgIGRpbTFDOiBkaW1zWzFdLnNsaWNlKDMyLCA0OCksXG4gICAgICAgIGRpbTFEOiBkaW1zWzFdLnNsaWNlKDQ4LCA2NCksXG5cbiAgICAgICAgZHJ3TGF5ZXI6IGRyd0xheWVyLFxuICAgICAgICBjb250ZXh0Q29sb3I6IFtcbiAgICAgICAgICAgIGRlc2VsZWN0ZWRMaW5lc0NvbG9yWzBdIC8gMjU1LFxuICAgICAgICAgICAgZGVzZWxlY3RlZExpbmVzQ29sb3JbMV0gLyAyNTUsXG4gICAgICAgICAgICBkZXNlbGVjdGVkTGluZXNDb2xvclsyXSAvIDI1NSxcbiAgICAgICAgICAgIGRlc2VsZWN0ZWRMaW5lc0NvbG9yWzNdIDwgMSA/XG4gICAgICAgICAgICAgICAgZGVzZWxlY3RlZExpbmVzQ29sb3JbM10gOlxuICAgICAgICAgICAgICAgIE1hdGgubWF4KDEgLyAyNTUsIE1hdGgucG93KDEgLyBtb2RlbC5saW5lcy5jb2xvci5sZW5ndGgsIDEgLyAzKSlcbiAgICAgICAgXSxcblxuICAgICAgICBzY2lzc29yWDogKGl0ZW1OdW1iZXIgPT09IGxlZnRtb3N0ID8gMCA6IHggKyBvdmVyZHJhZykgKyAobW9kZWwucGFkLmwgLSBvdmVyZHJhZykgKyBtb2RlbC5sYXlvdXRXaWR0aCAqIGRvbWFpbi54WzBdLFxuICAgICAgICBzY2lzc29yV2lkdGg6IChpdGVtTnVtYmVyID09PSByaWdodG1vc3QgPyBjYW52YXNXaWR0aCAtIHggKyBvdmVyZHJhZyA6IHBhbmVsU2l6ZVggKyAwLjUpICsgKGl0ZW1OdW1iZXIgPT09IGxlZnRtb3N0ID8geCArIG92ZXJkcmFnIDogMCksXG4gICAgICAgIHNjaXNzb3JZOiB5ICsgbW9kZWwucGFkLmIgKyBtb2RlbC5sYXlvdXRIZWlnaHQgKiBkb21haW4ueVswXSxcbiAgICAgICAgc2Npc3NvckhlaWdodDogcGFuZWxTaXplWSxcblxuICAgICAgICB2aWV3cG9ydFg6IG1vZGVsLnBhZC5sIC0gb3ZlcmRyYWcgKyBtb2RlbC5sYXlvdXRXaWR0aCAqIGRvbWFpbi54WzBdLFxuICAgICAgICB2aWV3cG9ydFk6IG1vZGVsLnBhZC5iICsgbW9kZWwubGF5b3V0SGVpZ2h0ICogZG9tYWluLnlbMF0sXG4gICAgICAgIHZpZXdwb3J0V2lkdGg6IGNhbnZhc1dpZHRoLFxuICAgICAgICB2aWV3cG9ydEhlaWdodDogY2FudmFzSGVpZ2h0XG4gICAgfSwgY29uc3RyYWludHMpO1xuXG4gICAgcmV0dXJuIGl0ZW1Nb2RlbDtcbn1cblxuZnVuY3Rpb24gZXhwYW5kZWRQaXhlbFJhbmdlKGJvdW5kcykge1xuICAgIHZhciBkaCA9IG1hc2tIZWlnaHQgLSAxO1xuICAgIHZhciBhID0gTWF0aC5tYXgoMCwgTWF0aC5mbG9vcihib3VuZHNbMF0gKiBkaCksIDApO1xuICAgIHZhciBiID0gTWF0aC5taW4oZGgsIE1hdGguY2VpbChib3VuZHNbMV0gKiBkaCksIGRoKTtcbiAgICByZXR1cm4gW1xuICAgICAgICBNYXRoLm1pbihhLCBiKSxcbiAgICAgICAgTWF0aC5tYXgoYSwgYilcbiAgICBdO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGNhbnZhc0dMLCBkKSB7XG4gICAgLy8gY29udGV4dCAmIHBpY2sgZGVzY3JpYmUgd2hpY2ggY2FudmFzIHdlJ3JlIHRhbGtpbmcgYWJvdXQgLSB3b24ndCBjaGFuZ2Ugd2l0aCBuZXcgZGF0YVxuICAgIHZhciBpc0NvbnRleHQgPSBkLmNvbnRleHQ7XG4gICAgdmFyIGlzUGljayA9IGQucGljaztcblxuICAgIHZhciByZWdsID0gZC5yZWdsO1xuXG4gICAgdmFyIHJlbmRlclN0YXRlID0ge1xuICAgICAgICBjdXJyZW50UmFmczoge30sXG4gICAgICAgIGRyYXdDb21wbGV0ZWQ6IHRydWUsXG4gICAgICAgIGNsZWFyT25seTogZmFsc2VcbiAgICB9O1xuXG4gICAgLy8gc3RhdGUgdG8gYmUgc2V0IGJ5IHVwZGF0ZSBhbmQgdXNlZCBsYXRlclxuICAgIHZhciBtb2RlbDtcbiAgICB2YXIgdm07XG4gICAgdmFyIGluaXRpYWxEaW1zO1xuICAgIHZhciBzYW1wbGVDb3VudDtcbiAgICB2YXIgYXR0cmlidXRlcyA9IGVtcHR5QXR0cmlidXRlcyhyZWdsKTtcbiAgICB2YXIgbWFza1RleHR1cmU7XG4gICAgdmFyIHBhbGV0dGVUZXh0dXJlID0gcmVnbC50ZXh0dXJlKHBhbGV0dGVUZXh0dXJlQ29uZmlnKTtcblxuICAgIHZhciBwcmV2QXhpc09yZGVyID0gW107XG5cbiAgICB1cGRhdGUoZCk7XG5cbiAgICB2YXIgZ2xBZXMgPSByZWdsKHtcblxuICAgICAgICBwcm9maWxlOiBmYWxzZSxcblxuICAgICAgICBibGVuZDoge1xuICAgICAgICAgICAgZW5hYmxlOiBpc0NvbnRleHQsXG4gICAgICAgICAgICBmdW5jOiB7XG4gICAgICAgICAgICAgICAgc3JjUkdCOiAnc3JjIGFscGhhJyxcbiAgICAgICAgICAgICAgICBkc3RSR0I6ICdvbmUgbWludXMgc3JjIGFscGhhJyxcbiAgICAgICAgICAgICAgICBzcmNBbHBoYTogMSxcbiAgICAgICAgICAgICAgICBkc3RBbHBoYTogMSAvLyAnb25lIG1pbnVzIHNyYyBhbHBoYSdcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlcXVhdGlvbjoge1xuICAgICAgICAgICAgICAgIHJnYjogJ2FkZCcsXG4gICAgICAgICAgICAgICAgYWxwaGE6ICdhZGQnXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3I6IFswLCAwLCAwLCAwXVxuICAgICAgICB9LFxuXG4gICAgICAgIGRlcHRoOiB7XG4gICAgICAgICAgICBlbmFibGU6ICFpc0NvbnRleHQsXG4gICAgICAgICAgICBtYXNrOiB0cnVlLFxuICAgICAgICAgICAgZnVuYzogJ2xlc3MnLFxuICAgICAgICAgICAgcmFuZ2U6IFswLCAxXVxuICAgICAgICB9LFxuXG4gICAgICAgIC8vIGZvciBwb2x5Z29uc1xuICAgICAgICBjdWxsOiB7XG4gICAgICAgICAgICBlbmFibGU6IHRydWUsXG4gICAgICAgICAgICBmYWNlOiAnYmFjaydcbiAgICAgICAgfSxcblxuICAgICAgICBzY2lzc29yOiB7XG4gICAgICAgICAgICBlbmFibGU6IHRydWUsXG4gICAgICAgICAgICBib3g6IHtcbiAgICAgICAgICAgICAgICB4OiByZWdsLnByb3AoJ3NjaXNzb3JYJyksXG4gICAgICAgICAgICAgICAgeTogcmVnbC5wcm9wKCdzY2lzc29yWScpLFxuICAgICAgICAgICAgICAgIHdpZHRoOiByZWdsLnByb3AoJ3NjaXNzb3JXaWR0aCcpLFxuICAgICAgICAgICAgICAgIGhlaWdodDogcmVnbC5wcm9wKCdzY2lzc29ySGVpZ2h0JylcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICB2aWV3cG9ydDoge1xuICAgICAgICAgICAgeDogcmVnbC5wcm9wKCd2aWV3cG9ydFgnKSxcbiAgICAgICAgICAgIHk6IHJlZ2wucHJvcCgndmlld3BvcnRZJyksXG4gICAgICAgICAgICB3aWR0aDogcmVnbC5wcm9wKCd2aWV3cG9ydFdpZHRoJyksXG4gICAgICAgICAgICBoZWlnaHQ6IHJlZ2wucHJvcCgndmlld3BvcnRIZWlnaHQnKVxuICAgICAgICB9LFxuXG4gICAgICAgIGRpdGhlcjogZmFsc2UsXG5cbiAgICAgICAgdmVydDogdmVydGV4U2hhZGVyU291cmNlLFxuXG4gICAgICAgIGZyYWc6IGZyYWdtZW50U2hhZGVyU291cmNlLFxuXG4gICAgICAgIHByaW1pdGl2ZTogJ2xpbmVzJyxcbiAgICAgICAgbGluZVdpZHRoOiAxLFxuICAgICAgICBhdHRyaWJ1dGVzOiBhdHRyaWJ1dGVzLFxuICAgICAgICB1bmlmb3Jtczoge1xuICAgICAgICAgICAgcmVzb2x1dGlvbjogcmVnbC5wcm9wKCdyZXNvbHV0aW9uJyksXG4gICAgICAgICAgICB2aWV3Qm94UG9zOiByZWdsLnByb3AoJ3ZpZXdCb3hQb3MnKSxcbiAgICAgICAgICAgIHZpZXdCb3hTaXplOiByZWdsLnByb3AoJ3ZpZXdCb3hTaXplJyksXG4gICAgICAgICAgICBkaW0wQTogcmVnbC5wcm9wKCdkaW0wQScpLFxuICAgICAgICAgICAgZGltMUE6IHJlZ2wucHJvcCgnZGltMUEnKSxcbiAgICAgICAgICAgIGRpbTBCOiByZWdsLnByb3AoJ2RpbTBCJyksXG4gICAgICAgICAgICBkaW0xQjogcmVnbC5wcm9wKCdkaW0xQicpLFxuICAgICAgICAgICAgZGltMEM6IHJlZ2wucHJvcCgnZGltMEMnKSxcbiAgICAgICAgICAgIGRpbTFDOiByZWdsLnByb3AoJ2RpbTFDJyksXG4gICAgICAgICAgICBkaW0wRDogcmVnbC5wcm9wKCdkaW0wRCcpLFxuICAgICAgICAgICAgZGltMUQ6IHJlZ2wucHJvcCgnZGltMUQnKSxcbiAgICAgICAgICAgIGxvQTogcmVnbC5wcm9wKCdsb0EnKSxcbiAgICAgICAgICAgIGhpQTogcmVnbC5wcm9wKCdoaUEnKSxcbiAgICAgICAgICAgIGxvQjogcmVnbC5wcm9wKCdsb0InKSxcbiAgICAgICAgICAgIGhpQjogcmVnbC5wcm9wKCdoaUInKSxcbiAgICAgICAgICAgIGxvQzogcmVnbC5wcm9wKCdsb0MnKSxcbiAgICAgICAgICAgIGhpQzogcmVnbC5wcm9wKCdoaUMnKSxcbiAgICAgICAgICAgIGxvRDogcmVnbC5wcm9wKCdsb0QnKSxcbiAgICAgICAgICAgIGhpRDogcmVnbC5wcm9wKCdoaUQnKSxcbiAgICAgICAgICAgIHBhbGV0dGU6IHBhbGV0dGVUZXh0dXJlLFxuICAgICAgICAgICAgY29udGV4dENvbG9yOiByZWdsLnByb3AoJ2NvbnRleHRDb2xvcicpLFxuICAgICAgICAgICAgbWFzazogcmVnbC5wcm9wKCdtYXNrVGV4dHVyZScpLFxuICAgICAgICAgICAgZHJ3TGF5ZXI6IHJlZ2wucHJvcCgnZHJ3TGF5ZXInKSxcbiAgICAgICAgICAgIG1hc2tIZWlnaHQ6IHJlZ2wucHJvcCgnbWFza0hlaWdodCcpXG4gICAgICAgIH0sXG4gICAgICAgIG9mZnNldDogcmVnbC5wcm9wKCdvZmZzZXQnKSxcbiAgICAgICAgY291bnQ6IHJlZ2wucHJvcCgnY291bnQnKVxuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gdXBkYXRlKGROZXcpIHtcbiAgICAgICAgbW9kZWwgPSBkTmV3Lm1vZGVsO1xuICAgICAgICB2bSA9IGROZXcudmlld01vZGVsO1xuICAgICAgICBpbml0aWFsRGltcyA9IHZtLmRpbWVuc2lvbnMuc2xpY2UoKTtcbiAgICAgICAgc2FtcGxlQ291bnQgPSBpbml0aWFsRGltc1swXSA/IGluaXRpYWxEaW1zWzBdLnZhbHVlcy5sZW5ndGggOiAwO1xuXG4gICAgICAgIHZhciBsaW5lcyA9IG1vZGVsLmxpbmVzO1xuICAgICAgICB2YXIgY29sb3IgPSBpc1BpY2sgPyBsaW5lcy5jb2xvci5tYXAoZnVuY3Rpb24oXywgaSkge3JldHVybiBpIC8gbGluZXMuY29sb3IubGVuZ3RoO30pIDogbGluZXMuY29sb3I7XG5cbiAgICAgICAgdmFyIHBvaW50cyA9IG1ha2VQb2ludHMoc2FtcGxlQ291bnQsIGluaXRpYWxEaW1zLCBjb2xvcik7XG4gICAgICAgIHNldEF0dHJpYnV0ZXMoYXR0cmlidXRlcywgc2FtcGxlQ291bnQsIHBvaW50cyk7XG5cbiAgICAgICAgaWYoIWlzQ29udGV4dCAmJiAhaXNQaWNrKSB7XG4gICAgICAgICAgICBwYWxldHRlVGV4dHVyZSA9IHJlZ2wudGV4dHVyZShMaWIuZXh0ZW5kRmxhdCh7XG4gICAgICAgICAgICAgICAgZGF0YTogcGFsZXR0ZShtb2RlbC51bml0VG9Db2xvciwgMjU1KVxuICAgICAgICAgICAgfSwgcGFsZXR0ZVRleHR1cmVDb25maWcpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VDb25zdHJhaW50cyhpc0NvbnRleHQpIHtcbiAgICAgICAgdmFyIGksIGosIGs7XG5cbiAgICAgICAgdmFyIGxpbWl0cyA9IFtbXSwgW11dO1xuICAgICAgICBmb3IoayA9IDA7IGsgPCA2NDsgaysrKSB7XG4gICAgICAgICAgICB2YXIgcCA9ICghaXNDb250ZXh0ICYmIGsgPCBpbml0aWFsRGltcy5sZW5ndGgpID9cbiAgICAgICAgICAgICAgICBpbml0aWFsRGltc1trXS5icnVzaC5maWx0ZXIuZ2V0Qm91bmRzKCkgOiBbLUluZmluaXR5LCBJbmZpbml0eV07XG5cbiAgICAgICAgICAgIGxpbWl0c1swXVtrXSA9IHBbMF07XG4gICAgICAgICAgICBsaW1pdHNbMV1ba10gPSBwWzFdO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxlbiA9IG1hc2tIZWlnaHQgKiA4O1xuICAgICAgICB2YXIgbWFzayA9IG5ldyBBcnJheShsZW4pO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgbWFza1tpXSA9IDI1NTtcbiAgICAgICAgfVxuICAgICAgICBpZighaXNDb250ZXh0KSB7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBpbml0aWFsRGltcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciB1ID0gaSAlIDg7XG4gICAgICAgICAgICAgICAgdmFyIHYgPSAoaSAtIHUpIC8gODtcbiAgICAgICAgICAgICAgICB2YXIgYml0TWFzayA9IE1hdGgucG93KDIsIHUpO1xuICAgICAgICAgICAgICAgIHZhciBkaW0gPSBpbml0aWFsRGltc1tpXTtcbiAgICAgICAgICAgICAgICB2YXIgcmFuZ2VzID0gZGltLmJydXNoLmZpbHRlci5nZXQoKTtcbiAgICAgICAgICAgICAgICBpZihyYW5nZXMubGVuZ3RoIDwgMikgY29udGludWU7IC8vIGJhaWwgaWYgdGhlIGJvdW5kaW5nIGJveCBiYXNlZCBmaWx0ZXIgaXMgc3VmZmljaWVudFxuXG4gICAgICAgICAgICAgICAgdmFyIHByZXZFbmQgPSBleHBhbmRlZFBpeGVsUmFuZ2UocmFuZ2VzWzBdKVsxXTtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDE7IGogPCByYW5nZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRSYW5nZSA9IGV4cGFuZGVkUGl4ZWxSYW5nZShyYW5nZXNbal0pO1xuICAgICAgICAgICAgICAgICAgICBmb3IoayA9IHByZXZFbmQgKyAxOyBrIDwgbmV4dFJhbmdlWzBdOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tbayAqIDggKyB2XSAmPSB+Yml0TWFzaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwcmV2RW5kID0gTWF0aC5tYXgocHJldkVuZCwgbmV4dFJhbmdlWzFdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdGV4dHVyZURhdGEgPSB7XG4gICAgICAgICAgICAvLyA4IHVuaXRzIHggOCBiaXRzID0gNjQgYml0cywganVzdCBzdWZmaWNpZW50IGZvciB0aGUgYWxtb3N0IDY0IGRpbWVuc2lvbnMgd2Ugc3VwcG9ydFxuICAgICAgICAgICAgc2hhcGU6IFs4LCBtYXNrSGVpZ2h0XSxcbiAgICAgICAgICAgIGZvcm1hdDogJ2FscGhhJyxcbiAgICAgICAgICAgIHR5cGU6ICd1aW50OCcsXG4gICAgICAgICAgICBtYWc6ICduZWFyZXN0JyxcbiAgICAgICAgICAgIG1pbjogJ25lYXJlc3QnLFxuICAgICAgICAgICAgZGF0YTogbWFza1xuICAgICAgICB9O1xuICAgICAgICBpZihtYXNrVGV4dHVyZSkgbWFza1RleHR1cmUodGV4dHVyZURhdGEpO1xuICAgICAgICBlbHNlIG1hc2tUZXh0dXJlID0gcmVnbC50ZXh0dXJlKHRleHR1cmVEYXRhKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbWFza1RleHR1cmU6IG1hc2tUZXh0dXJlLFxuICAgICAgICAgICAgbWFza0hlaWdodDogbWFza0hlaWdodCxcbiAgICAgICAgICAgIGxvQTogbGltaXRzWzBdLnNsaWNlKDAsIDE2KSxcbiAgICAgICAgICAgIGxvQjogbGltaXRzWzBdLnNsaWNlKDE2LCAzMiksXG4gICAgICAgICAgICBsb0M6IGxpbWl0c1swXS5zbGljZSgzMiwgNDgpLFxuICAgICAgICAgICAgbG9EOiBsaW1pdHNbMF0uc2xpY2UoNDgsIDY0KSxcbiAgICAgICAgICAgIGhpQTogbGltaXRzWzFdLnNsaWNlKDAsIDE2KSxcbiAgICAgICAgICAgIGhpQjogbGltaXRzWzFdLnNsaWNlKDE2LCAzMiksXG4gICAgICAgICAgICBoaUM6IGxpbWl0c1sxXS5zbGljZSgzMiwgNDgpLFxuICAgICAgICAgICAgaGlEOiBsaW1pdHNbMV0uc2xpY2UoNDgsIDY0KSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW5kZXJHTFBhcmNvb3JkcyhwYW5lbHMsIHNldENoYW5nZWQsIGNsZWFyT25seSkge1xuICAgICAgICB2YXIgcGFuZWxDb3VudCA9IHBhbmVscy5sZW5ndGg7XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIHZhciBsZWZ0bW9zdDtcbiAgICAgICAgdmFyIHJpZ2h0bW9zdDtcbiAgICAgICAgdmFyIGxvd2VzdFggPSBJbmZpbml0eTtcbiAgICAgICAgdmFyIGhpZ2hlc3RYID0gLUluZmluaXR5O1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHBhbmVsQ291bnQ7IGkrKykge1xuICAgICAgICAgICAgaWYocGFuZWxzW2ldLmRpbTAuY2FudmFzWCA8IGxvd2VzdFgpIHtcbiAgICAgICAgICAgICAgICBsb3dlc3RYID0gcGFuZWxzW2ldLmRpbTAuY2FudmFzWDtcbiAgICAgICAgICAgICAgICBsZWZ0bW9zdCA9IGk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihwYW5lbHNbaV0uZGltMS5jYW52YXNYID4gaGlnaGVzdFgpIHtcbiAgICAgICAgICAgICAgICBoaWdoZXN0WCA9IHBhbmVsc1tpXS5kaW0xLmNhbnZhc1g7XG4gICAgICAgICAgICAgICAgcmlnaHRtb3N0ID0gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHBhbmVsQ291bnQgPT09IDApIHtcbiAgICAgICAgICAgIC8vIGNsZWFyIGNhbnZhcyBoZXJlLCBhcyB0aGUgcGFuZWwgaXRlcmF0aW9uIGJlbG93IHdpbGwgbm90IGVudGVyIHRoZSBsb29wIGJvZHlcbiAgICAgICAgICAgIGNsZWFyKHJlZ2wsIDAsIDAsIG1vZGVsLmNhbnZhc1dpZHRoLCBtb2RlbC5jYW52YXNIZWlnaHQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb25zdHJhaW50cyA9IG1ha2VDb25zdHJhaW50cyhpc0NvbnRleHQpO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHBhbmVsQ291bnQ7IGkrKykge1xuICAgICAgICAgICAgdmFyIHAgPSBwYW5lbHNbaV07XG4gICAgICAgICAgICB2YXIgaTAgPSBwLmRpbTAuY3Jvc3NmaWx0ZXJEaW1lbnNpb25JbmRleDtcbiAgICAgICAgICAgIHZhciBpMSA9IHAuZGltMS5jcm9zc2ZpbHRlckRpbWVuc2lvbkluZGV4O1xuICAgICAgICAgICAgdmFyIHggPSBwLmNhbnZhc1g7XG4gICAgICAgICAgICB2YXIgeSA9IHAuY2FudmFzWTtcbiAgICAgICAgICAgIHZhciBuZXh0WCA9IHggKyBwLnBhbmVsU2l6ZVg7XG4gICAgICAgICAgICBpZihzZXRDaGFuZ2VkIHx8XG4gICAgICAgICAgICAgICAgIXByZXZBeGlzT3JkZXJbaTBdIHx8XG4gICAgICAgICAgICAgICAgcHJldkF4aXNPcmRlcltpMF1bMF0gIT09IHggfHxcbiAgICAgICAgICAgICAgICBwcmV2QXhpc09yZGVyW2kwXVsxXSAhPT0gbmV4dFhcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHByZXZBeGlzT3JkZXJbaTBdID0gW3gsIG5leHRYXTtcblxuICAgICAgICAgICAgICAgIHZhciBpdGVtID0gbWFrZUl0ZW0oXG4gICAgICAgICAgICAgICAgICAgIG1vZGVsLFxuICAgICAgICAgICAgICAgICAgICBsZWZ0bW9zdCwgcmlnaHRtb3N0LCBpLCBpMCwgaTEsIHgsIHksXG4gICAgICAgICAgICAgICAgICAgIHAucGFuZWxTaXplWCwgcC5wYW5lbFNpemVZLFxuICAgICAgICAgICAgICAgICAgICBwLmRpbTAuY3Jvc3NmaWx0ZXJEaW1lbnNpb25JbmRleCxcbiAgICAgICAgICAgICAgICAgICAgaXNDb250ZXh0ID8gMCA6IGlzUGljayA/IDIgOiAxLFxuICAgICAgICAgICAgICAgICAgICBjb25zdHJhaW50c1xuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICByZW5kZXJTdGF0ZS5jbGVhck9ubHkgPSBjbGVhck9ubHk7XG5cbiAgICAgICAgICAgICAgICB2YXIgYmxvY2tMaW5lQ291bnQgPSBzZXRDaGFuZ2VkID8gbW9kZWwubGluZXMuYmxvY2tMaW5lQ291bnQgOiBzYW1wbGVDb3VudDtcbiAgICAgICAgICAgICAgICByZW5kZXJCbG9jayhcbiAgICAgICAgICAgICAgICAgICAgcmVnbCwgZ2xBZXMsIHJlbmRlclN0YXRlLCBibG9ja0xpbmVDb3VudCwgc2FtcGxlQ291bnQsIGl0ZW1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVhZFBpeGVsKGNhbnZhc1gsIGNhbnZhc1kpIHtcbiAgICAgICAgcmVnbC5yZWFkKHtcbiAgICAgICAgICAgIHg6IGNhbnZhc1gsXG4gICAgICAgICAgICB5OiBjYW52YXNZLFxuICAgICAgICAgICAgd2lkdGg6IDEsXG4gICAgICAgICAgICBoZWlnaHQ6IDEsXG4gICAgICAgICAgICBkYXRhOiBkYXRhUGl4ZWxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBkYXRhUGl4ZWw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVhZFBpeGVscyhjYW52YXNYLCBjYW52YXNZLCB3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgIHZhciBwaXhlbEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoNCAqIHdpZHRoICogaGVpZ2h0KTtcbiAgICAgICAgcmVnbC5yZWFkKHtcbiAgICAgICAgICAgIHg6IGNhbnZhc1gsXG4gICAgICAgICAgICB5OiBjYW52YXNZLFxuICAgICAgICAgICAgd2lkdGg6IHdpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgICBkYXRhOiBwaXhlbEFycmF5XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcGl4ZWxBcnJheTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICBjYW52YXNHTC5zdHlsZVsncG9pbnRlci1ldmVudHMnXSA9ICdub25lJztcbiAgICAgICAgcGFsZXR0ZVRleHR1cmUuZGVzdHJveSgpO1xuICAgICAgICBpZihtYXNrVGV4dHVyZSkgbWFza1RleHR1cmUuZGVzdHJveSgpO1xuICAgICAgICBmb3IodmFyIGsgaW4gYXR0cmlidXRlcykgYXR0cmlidXRlc1trXS5kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgcmVuZGVyOiByZW5kZXJHTFBhcmNvb3JkcyxcbiAgICAgICAgcmVhZFBpeGVsOiByZWFkUGl4ZWwsXG4gICAgICAgIHJlYWRQaXhlbHM6IHJlYWRQaXhlbHMsXG4gICAgICAgIGRlc3Ryb3k6IGRlc3Ryb3ksXG4gICAgICAgIHVwZGF0ZTogdXBkYXRlXG4gICAgfTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi9jb25zdGFudHNcIjoxMDc4LFwiZ2xzbGlmeVwiOjQwOX1dLDEwODM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIG1lcmdlTGVuZ3RoOiBzZXQgdHJhY2UgbGVuZ3RoIGFzIHRoZSBtaW5pbXVtIG9mIGFsbCBkaW1lbnNpb24gZGF0YSBsZW5ndGhzXG4gKiAgICAgYW5kIHByb3BhZ2F0ZXMgdGhpcyBsZW5ndGggaW50byBlYWNoIGRpbWVuc2lvblxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFjZU91dDogdGhlIGZ1bGxEYXRhIHRyYWNlXG4gKiBAcGFyYW0ge0FycmF5KG9iamVjdCl9IGRpbWVuc2lvbnM6IGFycmF5IG9mIGRpbWVuc2lvbiBvYmplY3RzXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YUF0dHI6IHRoZSBhdHRyaWJ1dGUgb2YgZWFjaCBkaW1lbnNpb24gY29udGFpbmluZyB0aGUgZGF0YVxuICogQHBhcmFtIHtpbnRlZ2VyfSBsZW46IGFuIGFscmVhZHktZXhpc3RpbmcgbGVuZ3RoIGZyb20gb3RoZXIgYXR0cmlidXRlc1xuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHRyYWNlT3V0LCBkaW1lbnNpb25zLCBkYXRhQXR0ciwgbGVuKSB7XG4gICAgaWYoIWxlbikgbGVuID0gSW5maW5pdHk7XG4gICAgdmFyIGksIGRpbWk7XG4gICAgZm9yKGkgPSAwOyBpIDwgZGltZW5zaW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBkaW1pID0gZGltZW5zaW9uc1tpXTtcbiAgICAgICAgaWYoZGltaS52aXNpYmxlKSBsZW4gPSBNYXRoLm1pbihsZW4sIGRpbWlbZGF0YUF0dHJdLmxlbmd0aCk7XG4gICAgfVxuICAgIGlmKGxlbiA9PT0gSW5maW5pdHkpIGxlbiA9IDA7XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuICAgIGZvcihpID0gMDsgaSA8IGRpbWVuc2lvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZGltaSA9IGRpbWVuc2lvbnNbaV07XG4gICAgICAgIGlmKGRpbWkudmlzaWJsZSkgZGltaS5fbGVuZ3RoID0gbGVuO1xuICAgIH1cblxuICAgIHJldHVybiBsZW47XG59O1xuXG59LHt9XSwxMDg0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciByZ2JhID0gX2RlcmVxXygnY29sb3ItcmdiYScpO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgc3ZnVGV4dFV0aWxzID0gX2RlcmVxXygnLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIENvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKTtcblxudmFyIGd1cCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9ndXAnKTtcbnZhciBrZXlGdW4gPSBndXAua2V5RnVuO1xudmFyIHJlcGVhdCA9IGd1cC5yZXBlYXQ7XG52YXIgdW53cmFwID0gZ3VwLnVud3JhcDtcblxudmFyIGhlbHBlcnMgPSBfZGVyZXFfKCcuL2hlbHBlcnMnKTtcbnZhciBjID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcbnZhciBicnVzaCA9IF9kZXJlcV8oJy4vYXhpc2JydXNoJyk7XG52YXIgbGluZUxheWVyTWFrZXIgPSBfZGVyZXFfKCcuL2xpbmVzJyk7XG5cbmZ1bmN0aW9uIGZpbmRFeHRyZW1lKGZuLCB2YWx1ZXMsIGxlbikge1xuICAgIHJldHVybiBMaWIuYWdnTnVtcyhmbiwgbnVsbCwgdmFsdWVzLCBsZW4pO1xufVxuXG5mdW5jdGlvbiBmaW5kRXh0cmVtZXModmFsdWVzLCBsZW4pIHtcbiAgICByZXR1cm4gZml4RXh0cmVtZXMoXG4gICAgICAgIGZpbmRFeHRyZW1lKE1hdGgubWluLCB2YWx1ZXMsIGxlbiksXG4gICAgICAgIGZpbmRFeHRyZW1lKE1hdGgubWF4LCB2YWx1ZXMsIGxlbilcbiAgICApO1xufVxuXG5mdW5jdGlvbiBkaW1lbnNpb25FeHRlbnQoZGltZW5zaW9uKSB7XG4gICAgdmFyIHJhbmdlID0gZGltZW5zaW9uLnJhbmdlO1xuICAgIHJldHVybiByYW5nZSA/XG4gICAgICAgIGZpeEV4dHJlbWVzKHJhbmdlWzBdLCByYW5nZVsxXSkgOlxuICAgICAgICBmaW5kRXh0cmVtZXMoZGltZW5zaW9uLnZhbHVlcywgZGltZW5zaW9uLl9sZW5ndGgpO1xufVxuXG5mdW5jdGlvbiBmaXhFeHRyZW1lcyhsbywgaGkpIHtcbiAgICBpZihpc05hTihsbykgfHwgIWlzRmluaXRlKGxvKSkge1xuICAgICAgICBsbyA9IDA7XG4gICAgfVxuXG4gICAgaWYoaXNOYU4oaGkpIHx8ICFpc0Zpbml0ZShoaSkpIHtcbiAgICAgICAgaGkgPSAwO1xuICAgIH1cblxuICAgIC8vIGF2b2lkIGEgZGVnZW5lcmF0ZSAoemVyby13aWR0aCkgZG9tYWluXG4gICAgaWYobG8gPT09IGhpKSB7XG4gICAgICAgIGlmKGxvID09PSAwKSB7XG4gICAgICAgICAgICAvLyBubyB1c2UgdG8gbXVsdGlwbHlpbmcgemVybywgc28gYWRkL3N1YnRyYWN0IGluIHRoaXMgY2FzZVxuICAgICAgICAgICAgbG8gLT0gMTtcbiAgICAgICAgICAgIGhpICs9IDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB0aGlzIGtlZXBzIHRoZSByYW5nZSBpbiB0aGUgb3JkZXIgb2YgbWFnbml0dWRlIG9mIHRoZSBkYXRhXG4gICAgICAgICAgICBsbyAqPSAwLjk7XG4gICAgICAgICAgICBoaSAqPSAxLjE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gW2xvLCBoaV07XG59XG5cbmZ1bmN0aW9uIHRvVGV4dChmb3JtYXR0ZXIsIHRleHRzKSB7XG4gICAgaWYodGV4dHMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYsIGkpIHtcbiAgICAgICAgICAgIHZhciB0ZXh0ID0gdGV4dHNbaV07XG4gICAgICAgICAgICBpZih0ZXh0ID09PSBudWxsIHx8IHRleHQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGZvcm1hdHRlcih2KTtcbiAgICAgICAgICAgIHJldHVybiB0ZXh0O1xuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gZm9ybWF0dGVyO1xufVxuXG5mdW5jdGlvbiBkb21haW5TY2FsZShoZWlnaHQsIHBhZGRpbmcsIGRpbWVuc2lvbiwgdGlja3ZhbHMsIHRpY2t0ZXh0KSB7XG4gICAgdmFyIGV4dGVudCA9IGRpbWVuc2lvbkV4dGVudChkaW1lbnNpb24pO1xuICAgIGlmKHRpY2t2YWxzKSB7XG4gICAgICAgIHJldHVybiBkMy5zY2FsZS5vcmRpbmFsKClcbiAgICAgICAgICAgIC5kb21haW4odGlja3ZhbHMubWFwKHRvVGV4dChkMy5mb3JtYXQoZGltZW5zaW9uLnRpY2tmb3JtYXQpLCB0aWNrdGV4dCkpKVxuICAgICAgICAgICAgLnJhbmdlKHRpY2t2YWxzXG4gICAgICAgICAgICAgICAgLm1hcChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB1bml0VmFsID0gKGQgLSBleHRlbnRbMF0pIC8gKGV4dGVudFsxXSAtIGV4dGVudFswXSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoaGVpZ2h0IC0gcGFkZGluZyArIHVuaXRWYWwgKiAoMiAqIHBhZGRpbmcgLSBoZWlnaHQpKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGQzLnNjYWxlLmxpbmVhcigpXG4gICAgICAgIC5kb21haW4oZXh0ZW50KVxuICAgICAgICAucmFuZ2UoW2hlaWdodCAtIHBhZGRpbmcsIHBhZGRpbmddKTtcbn1cblxuZnVuY3Rpb24gdW5pdFRvUGFkZGVkUHgoaGVpZ2h0LCBwYWRkaW5nKSB7XG4gICAgcmV0dXJuIGQzLnNjYWxlLmxpbmVhcigpLnJhbmdlKFtwYWRkaW5nLCBoZWlnaHQgLSBwYWRkaW5nXSk7XG59XG5cbmZ1bmN0aW9uIGRvbWFpblRvUGFkZGVkVW5pdFNjYWxlKGRpbWVuc2lvbiwgcGFkRnJhY3Rpb24pIHtcbiAgICByZXR1cm4gZDMuc2NhbGUubGluZWFyKClcbiAgICAgICAgLmRvbWFpbihkaW1lbnNpb25FeHRlbnQoZGltZW5zaW9uKSlcbiAgICAgICAgLnJhbmdlKFtwYWRGcmFjdGlvbiwgMSAtIHBhZEZyYWN0aW9uXSk7XG59XG5cbmZ1bmN0aW9uIG9yZGluYWxTY2FsZShkaW1lbnNpb24pIHtcbiAgICBpZighZGltZW5zaW9uLnRpY2t2YWxzKSByZXR1cm47XG5cbiAgICB2YXIgZXh0ZW50ID0gZGltZW5zaW9uRXh0ZW50KGRpbWVuc2lvbik7XG4gICAgcmV0dXJuIGQzLnNjYWxlLm9yZGluYWwoKVxuICAgICAgICAuZG9tYWluKGRpbWVuc2lvbi50aWNrdmFscylcbiAgICAgICAgLnJhbmdlKGRpbWVuc2lvbi50aWNrdmFscy5tYXAoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIChkIC0gZXh0ZW50WzBdKSAvIChleHRlbnRbMV0gLSBleHRlbnRbMF0pO1xuICAgICAgICB9KSk7XG59XG5cbmZ1bmN0aW9uIHVuaXRUb0NvbG9yU2NhbGUoY3NjYWxlKSB7XG4gICAgdmFyIGNvbG9yU3RvcHMgPSBjc2NhbGUubWFwKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGRbMF07IH0pO1xuICAgIHZhciBjb2xvclR1cGxlcyA9IGNzY2FsZS5tYXAoZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgUkdCQSA9IHJnYmEoZFsxXSk7XG4gICAgICAgIHJldHVybiBkMy5yZ2IoJ3JnYignICsgUkdCQVswXSArICcsJyArIFJHQkFbMV0gKyAnLCcgKyBSR0JBWzJdICsgJyknKTtcbiAgICB9KTtcbiAgICB2YXIgcHJvcCA9IGZ1bmN0aW9uKG4pIHsgcmV0dXJuIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG9bbl07IH07IH07XG5cbiAgICAvLyBXZSBjYW4ndCB1c2UgZDMgY29sb3IgaW50ZXJwb2xhdGlvbiBhcyB3ZSBtYXkgaGF2ZSBub24tdW5pZm9ybSBjb2xvciBwYWxldHRlIHJhc3RlclxuICAgIC8vICh2YXJpb3VzIGNvbG9yIHN0b3AgZGlzdGFuY2VzKS5cbiAgICB2YXIgcG9seWxpbmVhclVuaXRTY2FsZXMgPSAncmdiJy5zcGxpdCgnJykubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgICByZXR1cm4gZDMuc2NhbGUubGluZWFyKClcbiAgICAgICAgICAgIC5jbGFtcCh0cnVlKVxuICAgICAgICAgICAgLmRvbWFpbihjb2xvclN0b3BzKVxuICAgICAgICAgICAgLnJhbmdlKGNvbG9yVHVwbGVzLm1hcChwcm9wKGtleSkpKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiBwb2x5bGluZWFyVW5pdFNjYWxlcy5tYXAoZnVuY3Rpb24ocykge1xuICAgICAgICAgICAgcmV0dXJuIHMoZCk7XG4gICAgICAgIH0pO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIHNvbWVGaWx0ZXJzQWN0aXZlKHZpZXcpIHtcbiAgICByZXR1cm4gdmlldy5kaW1lbnNpb25zLnNvbWUoZnVuY3Rpb24ocCkge1xuICAgICAgICByZXR1cm4gcC5icnVzaC5maWx0ZXJTcGVjaWZpZWQ7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIG1vZGVsKGxheW91dCwgZCwgaSkge1xuICAgIHZhciBjZDAgPSB1bndyYXAoZCk7XG4gICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgIHZhciBsaW5lQ29sb3IgPSBoZWxwZXJzLmNvbnZlcnRUeXBlZEFycmF5KGNkMC5saW5lQ29sb3IpO1xuICAgIHZhciBsaW5lID0gdHJhY2UubGluZTtcbiAgICB2YXIgZGVzZWxlY3RlZExpbmVzID0ge2NvbG9yOiByZ2JhKGMuZGVzZWxlY3RlZExpbmVDb2xvcil9O1xuICAgIHZhciBjT3B0cyA9IENvbG9yc2NhbGUuZXh0cmFjdE9wdHMobGluZSk7XG4gICAgdmFyIGNzY2FsZSA9IGNPcHRzLnJldmVyc2VzY2FsZSA/IENvbG9yc2NhbGUuZmxpcFNjYWxlKGNkMC5jc2NhbGUpIDogY2QwLmNzY2FsZTtcbiAgICB2YXIgZG9tYWluID0gdHJhY2UuZG9tYWluO1xuICAgIHZhciBkaW1lbnNpb25zID0gdHJhY2UuZGltZW5zaW9ucztcbiAgICB2YXIgd2lkdGggPSBsYXlvdXQud2lkdGg7XG4gICAgdmFyIGxhYmVsQW5nbGUgPSB0cmFjZS5sYWJlbGFuZ2xlO1xuICAgIHZhciBsYWJlbFNpZGUgPSB0cmFjZS5sYWJlbHNpZGU7XG4gICAgdmFyIGxhYmVsRm9udCA9IHRyYWNlLmxhYmVsZm9udDtcbiAgICB2YXIgdGlja0ZvbnQgPSB0cmFjZS50aWNrZm9udDtcbiAgICB2YXIgcmFuZ2VGb250ID0gdHJhY2UucmFuZ2Vmb250O1xuXG4gICAgdmFyIGxpbmVzID0gTGliLmV4dGVuZERlZXBOb0FycmF5cyh7fSwgbGluZSwge1xuICAgICAgICBjb2xvcjogbGluZUNvbG9yLm1hcChkMy5zY2FsZS5saW5lYXIoKS5kb21haW4oXG4gICAgICAgICAgICBkaW1lbnNpb25FeHRlbnQoe1xuICAgICAgICAgICAgICAgIHZhbHVlczogbGluZUNvbG9yLFxuICAgICAgICAgICAgICAgIHJhbmdlOiBbY09wdHMubWluLCBjT3B0cy5tYXhdLFxuICAgICAgICAgICAgICAgIF9sZW5ndGg6IHRyYWNlLl9sZW5ndGhcbiAgICAgICAgICAgIH0pXG4gICAgICAgICkpLFxuICAgICAgICBibG9ja0xpbmVDb3VudDogYy5ibG9ja0xpbmVDb3VudCxcbiAgICAgICAgY2FudmFzT3ZlcmRyYWc6IGMub3ZlcmRyYWcgKiBjLmNhbnZhc1BpeGVsUmF0aW9cbiAgICB9KTtcblxuICAgIHZhciBncm91cFdpZHRoID0gTWF0aC5mbG9vcih3aWR0aCAqIChkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdKSk7XG4gICAgdmFyIGdyb3VwSGVpZ2h0ID0gTWF0aC5mbG9vcihsYXlvdXQuaGVpZ2h0ICogKGRvbWFpbi55WzFdIC0gZG9tYWluLnlbMF0pKTtcblxuICAgIHZhciBwYWQgPSBsYXlvdXQubWFyZ2luIHx8IHtsOiA4MCwgcjogODAsIHQ6IDEwMCwgYjogODB9O1xuICAgIHZhciByb3dDb250ZW50V2lkdGggPSBncm91cFdpZHRoO1xuICAgIHZhciByb3dIZWlnaHQgPSBncm91cEhlaWdodDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGtleTogaSxcbiAgICAgICAgY29sQ291bnQ6IGRpbWVuc2lvbnMuZmlsdGVyKGhlbHBlcnMuaXNWaXNpYmxlKS5sZW5ndGgsXG4gICAgICAgIGRpbWVuc2lvbnM6IGRpbWVuc2lvbnMsXG4gICAgICAgIHRpY2tEaXN0YW5jZTogYy50aWNrRGlzdGFuY2UsXG4gICAgICAgIHVuaXRUb0NvbG9yOiB1bml0VG9Db2xvclNjYWxlKGNzY2FsZSksXG4gICAgICAgIGxpbmVzOiBsaW5lcyxcbiAgICAgICAgZGVzZWxlY3RlZExpbmVzOiBkZXNlbGVjdGVkTGluZXMsXG4gICAgICAgIGxhYmVsQW5nbGU6IGxhYmVsQW5nbGUsXG4gICAgICAgIGxhYmVsU2lkZTogbGFiZWxTaWRlLFxuICAgICAgICBsYWJlbEZvbnQ6IGxhYmVsRm9udCxcbiAgICAgICAgdGlja0ZvbnQ6IHRpY2tGb250LFxuICAgICAgICByYW5nZUZvbnQ6IHJhbmdlRm9udCxcbiAgICAgICAgbGF5b3V0V2lkdGg6IHdpZHRoLFxuICAgICAgICBsYXlvdXRIZWlnaHQ6IGxheW91dC5oZWlnaHQsXG4gICAgICAgIGRvbWFpbjogZG9tYWluLFxuICAgICAgICB0cmFuc2xhdGVYOiBkb21haW4ueFswXSAqIHdpZHRoLFxuICAgICAgICB0cmFuc2xhdGVZOiBsYXlvdXQuaGVpZ2h0IC0gZG9tYWluLnlbMV0gKiBsYXlvdXQuaGVpZ2h0LFxuICAgICAgICBwYWQ6IHBhZCxcbiAgICAgICAgY2FudmFzV2lkdGg6IHJvd0NvbnRlbnRXaWR0aCAqIGMuY2FudmFzUGl4ZWxSYXRpbyArIDIgKiBsaW5lcy5jYW52YXNPdmVyZHJhZyxcbiAgICAgICAgY2FudmFzSGVpZ2h0OiByb3dIZWlnaHQgKiBjLmNhbnZhc1BpeGVsUmF0aW8sXG4gICAgICAgIHdpZHRoOiByb3dDb250ZW50V2lkdGgsXG4gICAgICAgIGhlaWdodDogcm93SGVpZ2h0LFxuICAgICAgICBjYW52YXNQaXhlbFJhdGlvOiBjLmNhbnZhc1BpeGVsUmF0aW9cbiAgICB9O1xufVxuXG5mdW5jdGlvbiB2aWV3TW9kZWwoc3RhdGUsIGNhbGxiYWNrcywgbW9kZWwpIHtcbiAgICB2YXIgd2lkdGggPSBtb2RlbC53aWR0aDtcbiAgICB2YXIgaGVpZ2h0ID0gbW9kZWwuaGVpZ2h0O1xuICAgIHZhciBkaW1lbnNpb25zID0gbW9kZWwuZGltZW5zaW9ucztcbiAgICB2YXIgY2FudmFzUGl4ZWxSYXRpbyA9IG1vZGVsLmNhbnZhc1BpeGVsUmF0aW87XG5cbiAgICB2YXIgeFNjYWxlID0gZnVuY3Rpb24oZCkge3JldHVybiB3aWR0aCAqIGQgLyBNYXRoLm1heCgxLCBtb2RlbC5jb2xDb3VudCAtIDEpO307XG5cbiAgICB2YXIgdW5pdFBhZCA9IGMudmVydGljYWxQYWRkaW5nIC8gaGVpZ2h0O1xuICAgIHZhciBfdW5pdFRvUGFkZGVkUHggPSB1bml0VG9QYWRkZWRQeChoZWlnaHQsIGMudmVydGljYWxQYWRkaW5nKTtcblxuICAgIHZhciB2bSA9IHtcbiAgICAgICAga2V5OiBtb2RlbC5rZXksXG4gICAgICAgIHhTY2FsZTogeFNjYWxlLFxuICAgICAgICBtb2RlbDogbW9kZWwsXG4gICAgICAgIGluQnJ1c2hEcmFnOiBmYWxzZSAvLyBjb25zaWRlciBmYWN0b3JpbmcgaXQgb3V0IGFuZCBwdXR0aW5nIGl0IGluIGEgY2VudHJhbGl6ZWQgZ2xvYmFsLWlzaCBnZXN0dXJlIHN0YXRlIG9iamVjdFxuICAgIH07XG5cbiAgICB2YXIgdW5pcXVlS2V5cyA9IHt9O1xuXG4gICAgdm0uZGltZW5zaW9ucyA9IGRpbWVuc2lvbnMuZmlsdGVyKGhlbHBlcnMuaXNWaXNpYmxlKS5tYXAoZnVuY3Rpb24oZGltZW5zaW9uLCBpKSB7XG4gICAgICAgIHZhciBkb21haW5Ub1BhZGRlZFVuaXQgPSBkb21haW5Ub1BhZGRlZFVuaXRTY2FsZShkaW1lbnNpb24sIHVuaXRQYWQpO1xuICAgICAgICB2YXIgZm91bmRLZXkgPSB1bmlxdWVLZXlzW2RpbWVuc2lvbi5sYWJlbF07XG4gICAgICAgIHVuaXF1ZUtleXNbZGltZW5zaW9uLmxhYmVsXSA9IChmb3VuZEtleSB8fCAwKSArIDE7XG4gICAgICAgIHZhciBrZXkgPSBkaW1lbnNpb24ubGFiZWwgKyAoZm91bmRLZXkgPyAnX18nICsgZm91bmRLZXkgOiAnJyk7XG4gICAgICAgIHZhciBzcGVjaWZpZWRDb25zdHJhaW50ID0gZGltZW5zaW9uLmNvbnN0cmFpbnRyYW5nZTtcbiAgICAgICAgdmFyIGZpbHRlclJhbmdlU3BlY2lmaWVkID0gc3BlY2lmaWVkQ29uc3RyYWludCAmJiBzcGVjaWZpZWRDb25zdHJhaW50Lmxlbmd0aDtcbiAgICAgICAgaWYoZmlsdGVyUmFuZ2VTcGVjaWZpZWQgJiYgIUFycmF5LmlzQXJyYXkoc3BlY2lmaWVkQ29uc3RyYWludFswXSkpIHtcbiAgICAgICAgICAgIHNwZWNpZmllZENvbnN0cmFpbnQgPSBbc3BlY2lmaWVkQ29uc3RyYWludF07XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGZpbHRlclJhbmdlID0gZmlsdGVyUmFuZ2VTcGVjaWZpZWQgP1xuICAgICAgICAgICAgc3BlY2lmaWVkQ29uc3RyYWludC5tYXAoZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5tYXAoZG9tYWluVG9QYWRkZWRVbml0KTsgfSkgOlxuICAgICAgICAgICAgW1stSW5maW5pdHksIEluZmluaXR5XV07XG4gICAgICAgIHZhciBicnVzaE1vdmUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBwID0gdm07XG4gICAgICAgICAgICBwLmZvY3VzTGF5ZXIgJiYgcC5mb2N1c0xheWVyLnJlbmRlcihwLnBhbmVscywgdHJ1ZSk7XG4gICAgICAgICAgICB2YXIgZmlsdGVyc0FjdGl2ZSA9IHNvbWVGaWx0ZXJzQWN0aXZlKHApO1xuICAgICAgICAgICAgaWYoIXN0YXRlLmNvbnRleHRTaG93bigpICYmIGZpbHRlcnNBY3RpdmUpIHtcbiAgICAgICAgICAgICAgICBwLmNvbnRleHRMYXllciAmJiBwLmNvbnRleHRMYXllci5yZW5kZXIocC5wYW5lbHMsIHRydWUpO1xuICAgICAgICAgICAgICAgIHN0YXRlLmNvbnRleHRTaG93bih0cnVlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihzdGF0ZS5jb250ZXh0U2hvd24oKSAmJiAhZmlsdGVyc0FjdGl2ZSkge1xuICAgICAgICAgICAgICAgIHAuY29udGV4dExheWVyICYmIHAuY29udGV4dExheWVyLnJlbmRlcihwLnBhbmVscywgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgc3RhdGUuY29udGV4dFNob3duKGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgdHJ1bmNhdGVkVmFsdWVzID0gZGltZW5zaW9uLnZhbHVlcztcbiAgICAgICAgaWYodHJ1bmNhdGVkVmFsdWVzLmxlbmd0aCA+IGRpbWVuc2lvbi5fbGVuZ3RoKSB7XG4gICAgICAgICAgICB0cnVuY2F0ZWRWYWx1ZXMgPSB0cnVuY2F0ZWRWYWx1ZXMuc2xpY2UoMCwgZGltZW5zaW9uLl9sZW5ndGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRpY2t2YWxzID0gZGltZW5zaW9uLnRpY2t2YWxzO1xuICAgICAgICB2YXIgdGlja3RleHQ7XG4gICAgICAgIGZ1bmN0aW9uIG1ha2VUaWNrSXRlbSh2LCBpKSB7IHJldHVybiB7dmFsOiB2LCB0ZXh0OiB0aWNrdGV4dFtpXX07IH1cbiAgICAgICAgZnVuY3Rpb24gc29ydFRpY2tJdGVtKGEsIGIpIHsgcmV0dXJuIGEudmFsIC0gYi52YWw7IH1cbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh0aWNrdmFscykgJiYgdGlja3ZhbHMubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aWNrdGV4dCA9IGRpbWVuc2lvbi50aWNrdGV4dDtcblxuICAgICAgICAgICAgLy8gZW5zdXJlIHRpY2t0ZXh0IGFuZCB0aWNrdmFscyBoYXZlIHNhbWUgbGVuZ3RoXG4gICAgICAgICAgICBpZighQXJyYXkuaXNBcnJheSh0aWNrdGV4dCkgfHwgIXRpY2t0ZXh0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRpY2t0ZXh0ID0gdGlja3ZhbHMubWFwKGQzLmZvcm1hdChkaW1lbnNpb24udGlja2Zvcm1hdCkpO1xuICAgICAgICAgICAgfSBlbHNlIGlmKHRpY2t0ZXh0Lmxlbmd0aCA+IHRpY2t2YWxzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRpY2t0ZXh0ID0gdGlja3RleHQuc2xpY2UoMCwgdGlja3ZhbHMubGVuZ3RoKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZih0aWNrdmFscy5sZW5ndGggPiB0aWNrdGV4dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aWNrdmFscyA9IHRpY2t2YWxzLnNsaWNlKDAsIHRpY2t0ZXh0Lmxlbmd0aCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGNoZWNrIGlmIHdlIG5lZWQgdG8gc29ydCB0aWNrdmFscy90aWNrdGV4dFxuICAgICAgICAgICAgZm9yKHZhciBqID0gMTsgaiA8IHRpY2t2YWxzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgaWYodGlja3ZhbHNbal0gPCB0aWNrdmFsc1tqIC0gMV0pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRpY2tJdGVtcyA9IHRpY2t2YWxzLm1hcChtYWtlVGlja0l0ZW0pLnNvcnQoc29ydFRpY2tJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBrID0gMDsgayA8IHRpY2t2YWxzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aWNrdmFsc1trXSA9IHRpY2tJdGVtc1trXS52YWw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aWNrdGV4dFtrXSA9IHRpY2tJdGVtc1trXS50ZXh0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHRpY2t2YWxzID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIHRydW5jYXRlZFZhbHVlcyA9IGhlbHBlcnMuY29udmVydFR5cGVkQXJyYXkodHJ1bmNhdGVkVmFsdWVzKTtcbiAgICAgICAgdHJ1bmNhdGVkVmFsdWVzID0gaGVscGVycy5jb252ZXJ0VHlwZWRBcnJheSh0cnVuY2F0ZWRWYWx1ZXMpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgIGxhYmVsOiBkaW1lbnNpb24ubGFiZWwsXG4gICAgICAgICAgICB0aWNrRm9ybWF0OiBkaW1lbnNpb24udGlja2Zvcm1hdCxcbiAgICAgICAgICAgIHRpY2t2YWxzOiB0aWNrdmFscyxcbiAgICAgICAgICAgIHRpY2t0ZXh0OiB0aWNrdGV4dCxcbiAgICAgICAgICAgIG9yZGluYWw6IGhlbHBlcnMuaXNPcmRpbmFsKGRpbWVuc2lvbiksXG4gICAgICAgICAgICBtdWx0aXNlbGVjdDogZGltZW5zaW9uLm11bHRpc2VsZWN0LFxuICAgICAgICAgICAgeEluZGV4OiBpLFxuICAgICAgICAgICAgY3Jvc3NmaWx0ZXJEaW1lbnNpb25JbmRleDogaSxcbiAgICAgICAgICAgIHZpc2libGVJbmRleDogZGltZW5zaW9uLl9pbmRleCxcbiAgICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgICAgdmFsdWVzOiB0cnVuY2F0ZWRWYWx1ZXMsXG4gICAgICAgICAgICBwYWRkZWRVbml0VmFsdWVzOiB0cnVuY2F0ZWRWYWx1ZXMubWFwKGRvbWFpblRvUGFkZGVkVW5pdCksXG4gICAgICAgICAgICB1bml0VGlja3ZhbHM6IHRpY2t2YWxzICYmIHRpY2t2YWxzLm1hcChkb21haW5Ub1BhZGRlZFVuaXQpLFxuICAgICAgICAgICAgeFNjYWxlOiB4U2NhbGUsXG4gICAgICAgICAgICB4OiB4U2NhbGUoaSksXG4gICAgICAgICAgICBjYW52YXNYOiB4U2NhbGUoaSkgKiBjYW52YXNQaXhlbFJhdGlvLFxuICAgICAgICAgICAgdW5pdFRvUGFkZGVkUHg6IF91bml0VG9QYWRkZWRQeCxcbiAgICAgICAgICAgIGRvbWFpblNjYWxlOiBkb21haW5TY2FsZShoZWlnaHQsIGMudmVydGljYWxQYWRkaW5nLCBkaW1lbnNpb24sIHRpY2t2YWxzLCB0aWNrdGV4dCksXG4gICAgICAgICAgICBvcmRpbmFsU2NhbGU6IG9yZGluYWxTY2FsZShkaW1lbnNpb24pLFxuICAgICAgICAgICAgcGFyZW50OiB2bSxcbiAgICAgICAgICAgIG1vZGVsOiBtb2RlbCxcbiAgICAgICAgICAgIGJydXNoOiBicnVzaC5tYWtlQnJ1c2goXG4gICAgICAgICAgICAgICAgc3RhdGUsXG4gICAgICAgICAgICAgICAgZmlsdGVyUmFuZ2VTcGVjaWZpZWQsXG4gICAgICAgICAgICAgICAgZmlsdGVyUmFuZ2UsXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlLmxpbmVQaWNrQWN0aXZlKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGJydXNoTW92ZSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbihmKSB7XG4gICAgICAgICAgICAgICAgICAgIHZtLmZvY3VzTGF5ZXIucmVuZGVyKHZtLnBhbmVscywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHZtLnBpY2tMYXllciAmJiB2bS5waWNrTGF5ZXIucmVuZGVyKHZtLnBhbmVscywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlLmxpbmVQaWNrQWN0aXZlKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBpZihjYWxsYmFja3MgJiYgY2FsbGJhY2tzLmZpbHRlckNoYW5nZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbnZTY2FsZSA9IGRvbWFpblRvUGFkZGVkVW5pdC5pbnZlcnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHVwZGF0ZSBnZC5kYXRhIGFzIGlmIGEgUGxvdGx5LnJlc3R5bGUgd2VyZSBmaXJlZFxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld1JhbmdlcyA9IGYubWFwKGZ1bmN0aW9uKHIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gci5tYXAoaW52U2NhbGUpLnNvcnQoTGliLnNvcnRlckFzYyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGFbMF0gLSBiWzBdOyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrcy5maWx0ZXJDaGFuZ2VkKHZtLmtleSwgZGltZW5zaW9uLl9pbmRleCwgbmV3UmFuZ2VzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIClcbiAgICAgICAgfTtcbiAgICB9KTtcblxuICAgIHJldHVybiB2bTtcbn1cblxuZnVuY3Rpb24gc3R5bGVFeHRlbnRUZXh0cyhzZWxlY3Rpb24pIHtcbiAgICBzZWxlY3Rpb25cbiAgICAgICAgLmNsYXNzZWQoYy5jbi5heGlzRXh0ZW50VGV4dCwgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgICAgIC5zdHlsZSgnY3Vyc29yJywgJ2RlZmF1bHQnKVxuICAgICAgICAuc3R5bGUoJ3VzZXItc2VsZWN0JywgJ25vbmUnKTtcbn1cblxuZnVuY3Rpb24gcGFyY29vcmRzSW50ZXJhY3Rpb25TdGF0ZSgpIHtcbiAgICB2YXIgbGluZVBpY2tBY3RpdmUgPSB0cnVlO1xuICAgIHZhciBjb250ZXh0U2hvd24gPSBmYWxzZTtcbiAgICByZXR1cm4ge1xuICAgICAgICBsaW5lUGlja0FjdGl2ZTogZnVuY3Rpb24odmFsKSB7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyBsaW5lUGlja0FjdGl2ZSA9ICEhdmFsIDogbGluZVBpY2tBY3RpdmU7fSxcbiAgICAgICAgY29udGV4dFNob3duOiBmdW5jdGlvbih2YWwpIHtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IGNvbnRleHRTaG93biA9ICEhdmFsIDogY29udGV4dFNob3duO31cbiAgICB9O1xufVxuXG5mdW5jdGlvbiBjYWxjVGlsdChhbmdsZSwgcG9zaXRpb24pIHtcbiAgICB2YXIgZGlyID0gKHBvc2l0aW9uID09PSAndG9wJykgPyAxIDogLTE7XG4gICAgdmFyIHJhZGlhbnMgPSBhbmdsZSAqIE1hdGguUEkgLyAxODA7XG4gICAgdmFyIGR4ID0gTWF0aC5zaW4ocmFkaWFucyk7XG4gICAgdmFyIGR5ID0gTWF0aC5jb3MocmFkaWFucyk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGlyOiBkaXIsXG4gICAgICAgIGR4OiBkeCxcbiAgICAgICAgZHk6IGR5LFxuICAgICAgICBkZWdyZWVzOiBhbmdsZVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVBhbmVsTGF5b3V0KHlBeGlzLCB2bSkge1xuICAgIHZhciBwYW5lbHMgPSB2bS5wYW5lbHMgfHwgKHZtLnBhbmVscyA9IFtdKTtcbiAgICB2YXIgZGF0YSA9IHlBeGlzLmRhdGEoKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZGF0YS5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgdmFyIHAgPSBwYW5lbHNbaV0gfHwgKHBhbmVsc1tpXSA9IHt9KTtcbiAgICAgICAgdmFyIGRpbTAgPSBkYXRhW2ldO1xuICAgICAgICB2YXIgZGltMSA9IGRhdGFbaSArIDFdO1xuICAgICAgICBwLmRpbTAgPSBkaW0wO1xuICAgICAgICBwLmRpbTEgPSBkaW0xO1xuICAgICAgICBwLmNhbnZhc1ggPSBkaW0wLmNhbnZhc1g7XG4gICAgICAgIHAucGFuZWxTaXplWCA9IGRpbTEuY2FudmFzWCAtIGRpbTAuY2FudmFzWDtcbiAgICAgICAgcC5wYW5lbFNpemVZID0gdm0ubW9kZWwuY2FudmFzSGVpZ2h0O1xuICAgICAgICBwLnkgPSAwO1xuICAgICAgICBwLmNhbnZhc1kgPSAwO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gY2FsY0FsbFRpY2tzKGNkKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjZFtpXS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gY2RbaV1bal0udHJhY2U7XG4gICAgICAgICAgICB2YXIgZGltZW5zaW9ucyA9IHRyYWNlLmRpbWVuc2lvbnM7XG5cbiAgICAgICAgICAgIGZvcih2YXIgayA9IDA7IGsgPCBkaW1lbnNpb25zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IGRpbWVuc2lvbnNba10udmFsdWVzO1xuICAgICAgICAgICAgICAgIHZhciBkaW0gPSBkaW1lbnNpb25zW2tdLl9heDtcblxuICAgICAgICAgICAgICAgIGlmKGRpbSkge1xuICAgICAgICAgICAgICAgICAgICBpZighZGltLnJhbmdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaW0ucmFuZ2UgPSBmaW5kRXh0cmVtZXModmFsdWVzLCB0cmFjZS5fbGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpbS5yYW5nZSA9IGZpeEV4dHJlbWVzKGRpbS5yYW5nZVswXSwgZGltLnJhbmdlWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmKCFkaW0uZHRpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpbS5kdGljayA9IDAuMDEgKiAoTWF0aC5hYnMoZGltLnJhbmdlWzFdIC0gZGltLnJhbmdlWzBdKSB8fCAxKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGRpbS50aWNrZm9ybWF0ID0gZGltZW5zaW9uc1trXS50aWNrZm9ybWF0O1xuICAgICAgICAgICAgICAgICAgICBBeGVzLmNhbGNUaWNrcyhkaW0pO1xuICAgICAgICAgICAgICAgICAgICBkaW0uY2xlYW5SYW5nZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gbGluZWFyRm9ybWF0KGRpbSwgdikge1xuICAgIHJldHVybiBBeGVzLnRpY2tUZXh0KGRpbS5fYXgsIHYsIGZhbHNlKS50ZXh0O1xufVxuXG5mdW5jdGlvbiBleHRyZW1lVGV4dChkLCBpc1RvcCkge1xuICAgIGlmKGQub3JkaW5hbCkgcmV0dXJuICcnO1xuICAgIHZhciBkb21haW4gPSBkLmRvbWFpblNjYWxlLmRvbWFpbigpO1xuICAgIHZhciB2ID0gKGRvbWFpbltpc1RvcCA/IGRvbWFpbi5sZW5ndGggLSAxIDogMF0pO1xuXG4gICAgcmV0dXJuIGxpbmVhckZvcm1hdChkLm1vZGVsLmRpbWVuc2lvbnNbZC52aXNpYmxlSW5kZXhdLCB2KTtcbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhcmNvb3JkcyhnZCwgY2RNb2R1bGUsIGxheW91dCwgY2FsbGJhY2tzKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3ZnID0gZnVsbExheW91dC5fdG9wcGFwZXI7XG4gICAgdmFyIGdsQ29udGFpbmVyID0gZnVsbExheW91dC5fZ2xjb250YWluZXI7XG5cbiAgICBjYWxjQWxsVGlja3MoY2RNb2R1bGUpO1xuXG4gICAgdmFyIHN0YXRlID0gcGFyY29vcmRzSW50ZXJhY3Rpb25TdGF0ZSgpO1xuXG4gICAgdmFyIHZtID0gY2RNb2R1bGVcbiAgICAgICAgLmZpbHRlcihmdW5jdGlvbihkKSB7IHJldHVybiB1bndyYXAoZCkudHJhY2UudmlzaWJsZTsgfSlcbiAgICAgICAgLm1hcChtb2RlbC5iaW5kKDAsIGxheW91dCkpXG4gICAgICAgIC5tYXAodmlld01vZGVsLmJpbmQoMCwgc3RhdGUsIGNhbGxiYWNrcykpO1xuXG4gICAgZ2xDb250YWluZXIuZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgIHJldHVybiBMaWIuZXh0ZW5kRmxhdChkLCB2bVtpXSk7XG4gICAgfSk7XG5cbiAgICB2YXIgZ2xMYXllcnMgPSBnbENvbnRhaW5lci5zZWxlY3RBbGwoJy5nbC1jYW52YXMnKVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAvLyBGSVhNRTogZmlndXJlIG91dCBob3cgdG8gaGFuZGxlIG11bHRpcGxlIGluc3RhbmNlc1xuICAgICAgICAgICAgZC52aWV3TW9kZWwgPSB2bVswXTtcbiAgICAgICAgICAgIGQubW9kZWwgPSBkLnZpZXdNb2RlbCA/IGQudmlld01vZGVsLm1vZGVsIDogbnVsbDtcbiAgICAgICAgfSk7XG5cbiAgICB2YXIgbGFzdEhvdmVyZWQgPSBudWxsO1xuXG4gICAgdmFyIHBpY2tMYXllciA9IGdsTGF5ZXJzLmZpbHRlcihmdW5jdGlvbihkKSB7cmV0dXJuIGQucGljazt9KTtcblxuICAgIC8vIGVtaXQgaG92ZXIgLyB1bmhvdmVyIGV2ZW50XG4gICAgcGlja0xheWVyXG4gICAgICAgIC5zdHlsZSgncG9pbnRlci1ldmVudHMnLCAnYXV0bycpXG4gICAgICAgIC5vbignbW91c2Vtb3ZlJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgaWYoc3RhdGUubGluZVBpY2tBY3RpdmUoKSAmJiBkLmxpbmVMYXllciAmJiBjYWxsYmFja3MgJiYgY2FsbGJhY2tzLmhvdmVyKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50ID0gZDMuZXZlbnQ7XG4gICAgICAgICAgICAgICAgdmFyIGN3ID0gdGhpcy53aWR0aDtcbiAgICAgICAgICAgICAgICB2YXIgY2ggPSB0aGlzLmhlaWdodDtcbiAgICAgICAgICAgICAgICB2YXIgcG9pbnRlciA9IGQzLm1vdXNlKHRoaXMpO1xuICAgICAgICAgICAgICAgIHZhciB4ID0gcG9pbnRlclswXTtcbiAgICAgICAgICAgICAgICB2YXIgeSA9IHBvaW50ZXJbMV07XG5cbiAgICAgICAgICAgICAgICBpZih4IDwgMCB8fCB5IDwgMCB8fCB4ID49IGN3IHx8IHkgPj0gY2gpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcGl4ZWwgPSBkLmxpbmVMYXllci5yZWFkUGl4ZWwoeCwgY2ggLSAxIC0geSk7XG4gICAgICAgICAgICAgICAgdmFyIGZvdW5kID0gcGl4ZWxbM10gIT09IDA7XG4gICAgICAgICAgICAgICAgLy8gaW52ZXJzZSBvZiB0aGUgY2FsY1BpY2tDb2xvciBpbiBgbGluZXMuanNgOyBkZXRhaWxlZCBjb21tZW50IHRoZXJlXG4gICAgICAgICAgICAgICAgdmFyIGN1cnZlTnVtYmVyID0gZm91bmQgPyBwaXhlbFsyXSArIDI1NiAqIChwaXhlbFsxXSArIDI1NiAqIHBpeGVsWzBdKSA6IG51bGw7XG4gICAgICAgICAgICAgICAgdmFyIGV2ZW50RGF0YSA9IHtcbiAgICAgICAgICAgICAgICAgICAgeDogeCxcbiAgICAgICAgICAgICAgICAgICAgeTogeSxcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50WDogZXZlbnQuY2xpZW50WCxcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50WTogZXZlbnQuY2xpZW50WSxcbiAgICAgICAgICAgICAgICAgICAgZGF0YUluZGV4OiBkLm1vZGVsLmtleSxcbiAgICAgICAgICAgICAgICAgICAgY3VydmVOdW1iZXI6IGN1cnZlTnVtYmVyXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZihjdXJ2ZU51bWJlciAhPT0gbGFzdEhvdmVyZWQpIHsgLy8gZG9uJ3QgdW5uZWNlc3NhcmlseSByZXBlYXQgdGhlIHNhbWUgaGl0IChvciBtaXNzKVxuICAgICAgICAgICAgICAgICAgICBpZihmb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tzLmhvdmVyKGV2ZW50RGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihjYWxsYmFja3MudW5ob3Zlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tzLnVuaG92ZXIoZXZlbnREYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsYXN0SG92ZXJlZCA9IGN1cnZlTnVtYmVyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICBnbExheWVyc1xuICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQucGljayA/IDAgOiAxO30pO1xuXG4gICAgc3ZnLnN0eWxlKCdiYWNrZ3JvdW5kJywgJ3JnYmEoMjU1LCAyNTUsIDI1NSwgMCknKTtcbiAgICB2YXIgY29udHJvbE92ZXJsYXkgPSBzdmcuc2VsZWN0QWxsKCcuJyArIGMuY24ucGFyY29vcmRzKVxuICAgICAgICAuZGF0YSh2bSwga2V5RnVuKTtcblxuICAgIGNvbnRyb2xPdmVybGF5LmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIGNvbnRyb2xPdmVybGF5LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24ucGFyY29vcmRzLCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ3NoYXBlLXJlbmRlcmluZycsICdjcmlzcEVkZ2VzJylcbiAgICAgICAgLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdub25lJyk7XG5cbiAgICBjb250cm9sT3ZlcmxheS5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyBkLm1vZGVsLnRyYW5zbGF0ZVggKyAnLCcgKyBkLm1vZGVsLnRyYW5zbGF0ZVkgKyAnKSc7XG4gICAgfSk7XG5cbiAgICB2YXIgcGFyY29vcmRzQ29udHJvbFZpZXcgPSBjb250cm9sT3ZlcmxheS5zZWxlY3RBbGwoJy4nICsgYy5jbi5wYXJjb29yZHNDb250cm9sVmlldylcbiAgICAgICAgLmRhdGEocmVwZWF0LCBrZXlGdW4pO1xuXG4gICAgcGFyY29vcmRzQ29udHJvbFZpZXcuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5wYXJjb29yZHNDb250cm9sVmlldywgdHJ1ZSk7XG5cbiAgICBwYXJjb29yZHNDb250cm9sVmlldy5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyBkLm1vZGVsLnBhZC5sICsgJywnICsgZC5tb2RlbC5wYWQudCArICcpJztcbiAgICB9KTtcblxuICAgIHZhciB5QXhpcyA9IHBhcmNvb3Jkc0NvbnRyb2xWaWV3LnNlbGVjdEFsbCgnLicgKyBjLmNuLnlBeGlzKVxuICAgICAgICAuZGF0YShmdW5jdGlvbihwKSB7IHJldHVybiBwLmRpbWVuc2lvbnM7IH0sIGtleUZ1bik7XG5cbiAgICB5QXhpcy5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnlBeGlzLCB0cnVlKTtcblxuICAgIHBhcmNvb3Jkc0NvbnRyb2xWaWV3LmVhY2goZnVuY3Rpb24ocCkge1xuICAgICAgICB1cGRhdGVQYW5lbExheW91dCh5QXhpcywgcCk7XG4gICAgfSk7XG5cbiAgICBnbExheWVyc1xuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBpZihkLnZpZXdNb2RlbCkge1xuICAgICAgICAgICAgICAgIGlmKCFkLmxpbmVMYXllciB8fCBjYWxsYmFja3MpIHsgLy8gcmVjcmVhdGUgaW4gY2FzZSBvZiBoYXZpbmcgY2FsbGJhY2tzIGUuZy4gcmVzdHlsZS4gU2hvdWxkIHdlIHRlc3QgZm9yIGNhbGxiYWNrIHRvIGJlIGEgcmVzdHlsZT9cbiAgICAgICAgICAgICAgICAgICAgZC5saW5lTGF5ZXIgPSBsaW5lTGF5ZXJNYWtlcih0aGlzLCBkKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgZC5saW5lTGF5ZXIudXBkYXRlKGQpO1xuXG4gICAgICAgICAgICAgICAgaWYoZC5rZXkgfHwgZC5rZXkgPT09IDApIGQudmlld01vZGVsW2Qua2V5XSA9IGQubGluZUxheWVyO1xuXG4gICAgICAgICAgICAgICAgdmFyIHNldENoYW5nZWQgPSAoIWQuY29udGV4dCB8fCAvLyBkb24ndCB1cGRhdGUgYmFja2dyb3VuZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrcyk7ICAgLy8gdW5sZXNzIHRoZXJlIGlzIGEgY2FsbGJhY2sgb24gdGhlIGNvbnRleHQgbGF5ZXIuIFNob3VsZCB3ZSB0ZXN0IHRoZSBjYWxsYmFjaz9cblxuICAgICAgICAgICAgICAgIGQubGluZUxheWVyLnJlbmRlcihkLnZpZXdNb2RlbC5wYW5lbHMsIHNldENoYW5nZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIHlBeGlzLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIGQueFNjYWxlKGQueEluZGV4KSArICcsIDApJztcbiAgICB9KTtcblxuICAgIC8vIGRyYWcgY29sdW1uIGZvciByZW9yZGVyaW5nIGNvbHVtbnNcbiAgICB5QXhpcy5jYWxsKGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAub3JpZ2luKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQ7IH0pXG4gICAgICAgIC5vbignZHJhZycsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBwID0gZC5wYXJlbnQ7XG4gICAgICAgICAgICBzdGF0ZS5saW5lUGlja0FjdGl2ZShmYWxzZSk7XG4gICAgICAgICAgICBkLnggPSBNYXRoLm1heCgtYy5vdmVyZHJhZywgTWF0aC5taW4oZC5tb2RlbC53aWR0aCArIGMub3ZlcmRyYWcsIGQzLmV2ZW50LngpKTtcbiAgICAgICAgICAgIGQuY2FudmFzWCA9IGQueCAqIGQubW9kZWwuY2FudmFzUGl4ZWxSYXRpbztcbiAgICAgICAgICAgIHlBeGlzXG4gICAgICAgICAgICAgICAgLnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYS54IC0gYi54OyB9KVxuICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGUsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgZS54SW5kZXggPSBpO1xuICAgICAgICAgICAgICAgICAgICBlLnggPSBkID09PSBlID8gZS54IDogZS54U2NhbGUoZS54SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICBlLmNhbnZhc1ggPSBlLnggKiBlLm1vZGVsLmNhbnZhc1BpeGVsUmF0aW87XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHVwZGF0ZVBhbmVsTGF5b3V0KHlBeGlzLCBwKTtcblxuICAgICAgICAgICAgeUF4aXMuZmlsdGVyKGZ1bmN0aW9uKGUpIHsgcmV0dXJuIE1hdGguYWJzKGQueEluZGV4IC0gZS54SW5kZXgpICE9PSAwOyB9KVxuICAgICAgICAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7IHJldHVybiAndHJhbnNsYXRlKCcgKyBkLnhTY2FsZShkLnhJbmRleCkgKyAnLCAwKSc7IH0pO1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIGQueCArICcsIDApJyk7XG4gICAgICAgICAgICB5QXhpcy5lYWNoKGZ1bmN0aW9uKGUsIGkwLCBpMSkgeyBpZihpMSA9PT0gZC5wYXJlbnQua2V5KSBwLmRpbWVuc2lvbnNbaTBdID0gZTsgfSk7XG4gICAgICAgICAgICBwLmNvbnRleHRMYXllciAmJiBwLmNvbnRleHRMYXllci5yZW5kZXIocC5wYW5lbHMsIGZhbHNlLCAhc29tZUZpbHRlcnNBY3RpdmUocCkpO1xuICAgICAgICAgICAgcC5mb2N1c0xheWVyLnJlbmRlciAmJiBwLmZvY3VzTGF5ZXIucmVuZGVyKHAucGFuZWxzKTtcbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdkcmFnZW5kJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIHAgPSBkLnBhcmVudDtcbiAgICAgICAgICAgIGQueCA9IGQueFNjYWxlKGQueEluZGV4KTtcbiAgICAgICAgICAgIGQuY2FudmFzWCA9IGQueCAqIGQubW9kZWwuY2FudmFzUGl4ZWxSYXRpbztcbiAgICAgICAgICAgIHVwZGF0ZVBhbmVsTGF5b3V0KHlBeGlzLCBwKTtcbiAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7IHJldHVybiAndHJhbnNsYXRlKCcgKyBkLnggKyAnLCAwKSc7IH0pO1xuICAgICAgICAgICAgcC5jb250ZXh0TGF5ZXIgJiYgcC5jb250ZXh0TGF5ZXIucmVuZGVyKHAucGFuZWxzLCBmYWxzZSwgIXNvbWVGaWx0ZXJzQWN0aXZlKHApKTtcbiAgICAgICAgICAgIHAuZm9jdXNMYXllciAmJiBwLmZvY3VzTGF5ZXIucmVuZGVyKHAucGFuZWxzKTtcbiAgICAgICAgICAgIHAucGlja0xheWVyICYmIHAucGlja0xheWVyLnJlbmRlcihwLnBhbmVscywgdHJ1ZSk7XG4gICAgICAgICAgICBzdGF0ZS5saW5lUGlja0FjdGl2ZSh0cnVlKTtcblxuICAgICAgICAgICAgaWYoY2FsbGJhY2tzICYmIGNhbGxiYWNrcy5heGVzTW92ZWQpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFja3MuYXhlc01vdmVkKHAua2V5LCBwLmRpbWVuc2lvbnMubWFwKGZ1bmN0aW9uKGUpIHtyZXR1cm4gZS5jcm9zc2ZpbHRlckRpbWVuc2lvbkluZGV4O30pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICApO1xuXG4gICAgeUF4aXMuZXhpdCgpXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIHZhciBheGlzT3ZlcmxheXMgPSB5QXhpcy5zZWxlY3RBbGwoJy4nICsgYy5jbi5heGlzT3ZlcmxheXMpXG4gICAgICAgIC5kYXRhKHJlcGVhdCwga2V5RnVuKTtcblxuICAgIGF4aXNPdmVybGF5cy5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmF4aXNPdmVybGF5cywgdHJ1ZSk7XG5cbiAgICBheGlzT3ZlcmxheXMuc2VsZWN0QWxsKCcuJyArIGMuY24uYXhpcykucmVtb3ZlKCk7XG5cbiAgICB2YXIgYXhpcyA9IGF4aXNPdmVybGF5cy5zZWxlY3RBbGwoJy4nICsgYy5jbi5heGlzKVxuICAgICAgICAuZGF0YShyZXBlYXQsIGtleUZ1bik7XG5cbiAgICBheGlzLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uYXhpcywgdHJ1ZSk7XG5cbiAgICBheGlzXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB3YW50ZWRUaWNrQ291bnQgPSBkLm1vZGVsLmhlaWdodCAvIGQubW9kZWwudGlja0Rpc3RhbmNlO1xuICAgICAgICAgICAgdmFyIHNjYWxlID0gZC5kb21haW5TY2FsZTtcbiAgICAgICAgICAgIHZhciBzZG9tID0gc2NhbGUuZG9tYWluKCk7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcylcbiAgICAgICAgICAgICAgICAuY2FsbChkMy5zdmcuYXhpcygpXG4gICAgICAgICAgICAgICAgICAgIC5vcmllbnQoJ2xlZnQnKVxuICAgICAgICAgICAgICAgICAgICAudGlja1NpemUoNClcbiAgICAgICAgICAgICAgICAgICAgLm91dGVyVGlja1NpemUoMilcbiAgICAgICAgICAgICAgICAgICAgLnRpY2tzKHdhbnRlZFRpY2tDb3VudCwgZC50aWNrRm9ybWF0KSAvLyB3b3JrcyBmb3IgY29udGludW91cyBzY2FsZXMgb25seS4uLlxuICAgICAgICAgICAgICAgICAgICAudGlja1ZhbHVlcyhkLm9yZGluYWwgPyAvLyBhbmQgdGhpcyB3b3JrcyBmb3Igb3JkaW5hbCBzY2FsZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIHNkb20gOlxuICAgICAgICAgICAgICAgICAgICAgICAgbnVsbClcbiAgICAgICAgICAgICAgICAgICAgLnRpY2tGb3JtYXQoZnVuY3Rpb24odikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGhlbHBlcnMuaXNPcmRpbmFsKGQpID8gdiA6IGxpbmVhckZvcm1hdChkLm1vZGVsLmRpbWVuc2lvbnNbZC52aXNpYmxlSW5kZXhdLCB2KTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLnNjYWxlKHNjYWxlKSk7XG4gICAgICAgICAgICBEcmF3aW5nLmZvbnQoYXhpcy5zZWxlY3RBbGwoJ3RleHQnKSwgZC5tb2RlbC50aWNrRm9udCk7XG4gICAgICAgIH0pO1xuXG4gICAgYXhpcy5zZWxlY3RBbGwoJy5kb21haW4sIC50aWNrPmxpbmUnKVxuICAgICAgICAuYXR0cignZmlsbCcsICdub25lJylcbiAgICAgICAgLmF0dHIoJ3N0cm9rZScsICdibGFjaycpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utb3BhY2l0eScsIDAuMjUpXG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCAnMXB4Jyk7XG5cbiAgICBheGlzLnNlbGVjdEFsbCgndGV4dCcpXG4gICAgICAgIC5zdHlsZSgndGV4dC1zaGFkb3cnLCAnMXB4IDFweCAxcHggI2ZmZiwgLTFweCAtMXB4IDFweCAjZmZmLCAxcHggLTFweCAxcHggI2ZmZiwgLTFweCAxcHggMXB4ICNmZmYnKVxuICAgICAgICAuc3R5bGUoJ2N1cnNvcicsICdkZWZhdWx0JylcbiAgICAgICAgLnN0eWxlKCd1c2VyLXNlbGVjdCcsICdub25lJyk7XG5cbiAgICB2YXIgYXhpc0hlYWRpbmcgPSBheGlzT3ZlcmxheXMuc2VsZWN0QWxsKCcuJyArIGMuY24uYXhpc0hlYWRpbmcpXG4gICAgICAgIC5kYXRhKHJlcGVhdCwga2V5RnVuKTtcblxuICAgIGF4aXNIZWFkaW5nLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uYXhpc0hlYWRpbmcsIHRydWUpO1xuXG4gICAgdmFyIGF4aXNUaXRsZSA9IGF4aXNIZWFkaW5nLnNlbGVjdEFsbCgnLicgKyBjLmNuLmF4aXNUaXRsZSlcbiAgICAgICAgLmRhdGEocmVwZWF0LCBrZXlGdW4pO1xuXG4gICAgYXhpc1RpdGxlLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgndGV4dCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uYXhpc1RpdGxlLCB0cnVlKVxuICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLCAnbWlkZGxlJylcbiAgICAgICAgLnN0eWxlKCdjdXJzb3InLCAnZXctcmVzaXplJylcbiAgICAgICAgLnN0eWxlKCd1c2VyLXNlbGVjdCcsICdub25lJylcbiAgICAgICAgLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhdXRvJyk7XG5cbiAgICBheGlzVGl0bGVcbiAgICAgICAgLnRleHQoZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5sYWJlbDsgfSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGUgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBEcmF3aW5nLmZvbnQoZSwgZC5tb2RlbC5sYWJlbEZvbnQpO1xuICAgICAgICAgICAgc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucyhlLCBnZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgdGlsdCA9IGNhbGNUaWx0KGQubW9kZWwubGFiZWxBbmdsZSwgZC5tb2RlbC5sYWJlbFNpZGUpO1xuICAgICAgICAgICAgdmFyIHIgPSBjLmF4aXNUaXRsZU9mZnNldDtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgKHRpbHQuZGlyID4gMCA/ICcnIDogJ3RyYW5zbGF0ZSgwLCcgKyAoMiAqIHIgKyBkLm1vZGVsLmhlaWdodCkgKyAnKScpICtcbiAgICAgICAgICAgICAgICAncm90YXRlKCcgKyB0aWx0LmRlZ3JlZXMgKyAnKScgK1xuICAgICAgICAgICAgICAgICd0cmFuc2xhdGUoJyArICgtciAqIHRpbHQuZHgpICsgJywnICsgKC1yICogdGlsdC5keSkgKyAnKSdcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCd0ZXh0LWFuY2hvcicsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB0aWx0ID0gY2FsY1RpbHQoZC5tb2RlbC5sYWJlbEFuZ2xlLCBkLm1vZGVsLmxhYmVsU2lkZSk7XG4gICAgICAgICAgICB2YXIgYWR4ID0gTWF0aC5hYnModGlsdC5keCk7XG4gICAgICAgICAgICB2YXIgYWR5ID0gTWF0aC5hYnModGlsdC5keSk7XG5cbiAgICAgICAgICAgIGlmKDIgKiBhZHggPiBhZHkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHRpbHQuZGlyICogdGlsdC5keCA8IDApID8gJ3N0YXJ0JyA6ICdlbmQnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ21pZGRsZSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIGF4aXNFeHRlbnQgPSBheGlzT3ZlcmxheXMuc2VsZWN0QWxsKCcuJyArIGMuY24uYXhpc0V4dGVudClcbiAgICAgICAgLmRhdGEocmVwZWF0LCBrZXlGdW4pO1xuXG4gICAgYXhpc0V4dGVudC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmF4aXNFeHRlbnQsIHRydWUpO1xuXG4gICAgdmFyIGF4aXNFeHRlbnRUb3AgPSBheGlzRXh0ZW50LnNlbGVjdEFsbCgnLicgKyBjLmNuLmF4aXNFeHRlbnRUb3ApXG4gICAgICAgIC5kYXRhKHJlcGVhdCwga2V5RnVuKTtcblxuICAgIGF4aXNFeHRlbnRUb3AuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5heGlzRXh0ZW50VG9wLCB0cnVlKTtcblxuICAgIGF4aXNFeHRlbnRUb3BcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIDAgKyAnLCcgKyAtYy5heGlzRXh0ZW50T2Zmc2V0ICsgJyknKTtcblxuICAgIHZhciBheGlzRXh0ZW50VG9wVGV4dCA9IGF4aXNFeHRlbnRUb3Auc2VsZWN0QWxsKCcuJyArIGMuY24uYXhpc0V4dGVudFRvcFRleHQpXG4gICAgICAgIC5kYXRhKHJlcGVhdCwga2V5RnVuKTtcblxuICAgIGF4aXNFeHRlbnRUb3BUZXh0LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgndGV4dCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uYXhpc0V4dGVudFRvcFRleHQsIHRydWUpXG4gICAgICAgIC5jYWxsKHN0eWxlRXh0ZW50VGV4dHMpO1xuXG4gICAgYXhpc0V4dGVudFRvcFRleHRcbiAgICAgICAgLnRleHQoZnVuY3Rpb24oZCkgeyByZXR1cm4gZXh0cmVtZVRleHQoZCwgdHJ1ZSk7IH0pXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHsgRHJhd2luZy5mb250KGQzLnNlbGVjdCh0aGlzKSwgZC5tb2RlbC5yYW5nZUZvbnQpOyB9KTtcblxuICAgIHZhciBheGlzRXh0ZW50Qm90dG9tID0gYXhpc0V4dGVudC5zZWxlY3RBbGwoJy4nICsgYy5jbi5heGlzRXh0ZW50Qm90dG9tKVxuICAgICAgICAuZGF0YShyZXBlYXQsIGtleUZ1bik7XG5cbiAgICBheGlzRXh0ZW50Qm90dG9tLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uYXhpc0V4dGVudEJvdHRvbSwgdHJ1ZSk7XG5cbiAgICBheGlzRXh0ZW50Qm90dG9tXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgnICsgMCArICcsJyArIChkLm1vZGVsLmhlaWdodCArIGMuYXhpc0V4dGVudE9mZnNldCkgKyAnKSc7XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIGF4aXNFeHRlbnRCb3R0b21UZXh0ID0gYXhpc0V4dGVudEJvdHRvbS5zZWxlY3RBbGwoJy4nICsgYy5jbi5heGlzRXh0ZW50Qm90dG9tVGV4dClcbiAgICAgICAgLmRhdGEocmVwZWF0LCBrZXlGdW4pO1xuXG4gICAgYXhpc0V4dGVudEJvdHRvbVRleHQuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5heGlzRXh0ZW50Qm90dG9tVGV4dCwgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2R5JywgJzAuNzVlbScpXG4gICAgICAgIC5jYWxsKHN0eWxlRXh0ZW50VGV4dHMpO1xuXG4gICAgYXhpc0V4dGVudEJvdHRvbVRleHRcbiAgICAgICAgLnRleHQoZnVuY3Rpb24oZCkgeyByZXR1cm4gZXh0cmVtZVRleHQoZCwgZmFsc2UpOyB9KVxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7IERyYXdpbmcuZm9udChkMy5zZWxlY3QodGhpcyksIGQubW9kZWwucmFuZ2VGb250KTsgfSk7XG5cbiAgICBicnVzaC5lbnN1cmVBeGlzQnJ1c2goYXhpc092ZXJsYXlzKTtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlXCI6NjA1LFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL2d1cFwiOjcxNyxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi9heGlzYnJ1c2hcIjoxMDc1LFwiLi9jb25zdGFudHNcIjoxMDc4LFwiLi9oZWxwZXJzXCI6MTA4MCxcIi4vbGluZXNcIjoxMDgyLFwiY29sb3ItcmdiYVwiOjEyMixcImQzXCI6MTYzfV0sMTA4NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBwYXJjb29yZHMgPSBfZGVyZXFfKCcuL3BhcmNvb3JkcycpO1xudmFyIHByZXBhcmVSZWdsID0gX2RlcmVxXygnLi4vLi4vbGliL3ByZXBhcmVfcmVnbCcpO1xudmFyIGlzVmlzaWJsZSA9IF9kZXJlcV8oJy4vaGVscGVycycpLmlzVmlzaWJsZTtcblxuZnVuY3Rpb24gbmV3SW5kZXgodmlzaWJsZUluZGljZXMsIG9yaWcsIGRpbSkge1xuICAgIHZhciBvcmlnSW5kZXggPSBvcmlnLmluZGV4T2YoZGltKTtcbiAgICB2YXIgY3VycmVudEluZGV4ID0gdmlzaWJsZUluZGljZXMuaW5kZXhPZihvcmlnSW5kZXgpO1xuICAgIGlmKGN1cnJlbnRJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgLy8gaW52aXNpYmxlIGRpbWVuc2lvbnMgaW5pdGlhbGx5IGdvIHRvIHRoZSBlbmRcbiAgICAgICAgY3VycmVudEluZGV4ICs9IG9yaWcubGVuZ3RoO1xuICAgIH1cbiAgICByZXR1cm4gY3VycmVudEluZGV4O1xufVxuXG5mdW5jdGlvbiBzb3J0ZXIodmlzaWJsZUluZGljZXMsIG9yaWcpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gc29ydGVyKGQxLCBkMikge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgbmV3SW5kZXgodmlzaWJsZUluZGljZXMsIG9yaWcsIGQxKSAtXG4gICAgICAgICAgICBuZXdJbmRleCh2aXNpYmxlSW5kaWNlcywgb3JpZywgZDIpXG4gICAgICAgICk7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBjZE1vZHVsZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICB2YXIgc3VjY2VzcyA9IHByZXBhcmVSZWdsKGdkKTtcbiAgICBpZighc3VjY2VzcykgcmV0dXJuO1xuXG4gICAgdmFyIGN1cnJlbnREaW1zID0ge307XG4gICAgdmFyIGluaXRpYWxEaW1zID0ge307XG4gICAgdmFyIGZ1bGxJbmRpY2VzID0ge307XG4gICAgdmFyIGlucHV0SW5kaWNlcyA9IHt9O1xuXG4gICAgdmFyIHNpemUgPSBmdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgY2RNb2R1bGUuZm9yRWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGRbMF0udHJhY2U7XG4gICAgICAgIGZ1bGxJbmRpY2VzW2ldID0gdHJhY2UuaW5kZXg7XG4gICAgICAgIHZhciBpSW4gPSBpbnB1dEluZGljZXNbaV0gPSB0cmFjZS5fZnVsbElucHV0LmluZGV4O1xuICAgICAgICBjdXJyZW50RGltc1tpXSA9IGdkLmRhdGFbaUluXS5kaW1lbnNpb25zO1xuICAgICAgICBpbml0aWFsRGltc1tpXSA9IGdkLmRhdGFbaUluXS5kaW1lbnNpb25zLnNsaWNlKCk7XG4gICAgfSk7XG5cbiAgICB2YXIgZmlsdGVyQ2hhbmdlZCA9IGZ1bmN0aW9uKGksIGluaXRpYWxEaW1JbmRleCwgbmV3UmFuZ2VzKSB7XG4gICAgICAgIC8vIEhhdmUgdXBkYXRlZCBgY29uc3RyYWludHJhbmdlYCBkYXRhIG9uIGBnZC5kYXRhYCBhbmQgcmFpc2UgYFBsb3RseS5yZXN0eWxlYCBldmVudFxuICAgICAgICAvLyB3aXRob3V0IGhhdmluZyB0byBpbmN1ciBoZWF2eSBVSSBibG9ja2luZyBkdWUgdG8gYW4gYWN0dWFsIGBQbG90bHkucmVzdHlsZWAgY2FsbFxuXG4gICAgICAgIHZhciBkaW0gPSBpbml0aWFsRGltc1tpXVtpbml0aWFsRGltSW5kZXhdO1xuICAgICAgICB2YXIgbmV3Q29uc3RyYWludHMgPSBuZXdSYW5nZXMubWFwKGZ1bmN0aW9uKHIpIHsgcmV0dXJuIHIuc2xpY2UoKTsgfSk7XG5cbiAgICAgICAgLy8gU3RvcmUgY29uc3RyYWludCByYW5nZSBpbiBwcmVHVUlcbiAgICAgICAgLy8gVGhpcyBvbmUgZG9lc24ndCB3b3JrIGlmIGl0J3Mgc3RvcmVkIGluIHBpZWNlcyBpbiBfc3RvcmVEaXJlY3RHVUlFZGl0XG4gICAgICAgIC8vIGJlY2F1c2UgaXQncyBhbiBhcnJheSBvZiB2YXJpYWJsZSBkaW1lbnNpb25hbGl0eS4gU28gc3RvcmUgdGhlIHdob2xlXG4gICAgICAgIC8vIHRoaW5nIGF0IG9uY2UgbWFudWFsbHkuXG4gICAgICAgIHZhciBhU3RyID0gJ2RpbWVuc2lvbnNbJyArIGluaXRpYWxEaW1JbmRleCArICddLmNvbnN0cmFpbnRyYW5nZSc7XG4gICAgICAgIHZhciBwcmVHVUkgPSBmdWxsTGF5b3V0Ll90cmFjZVByZUdVSVtnZC5fZnVsbERhdGFbZnVsbEluZGljZXNbaV1dLl9mdWxsSW5wdXQudWlkXTtcbiAgICAgICAgaWYocHJlR1VJW2FTdHJdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHZhciBpbml0aWFsVmFsID0gZGltLmNvbnN0cmFpbnRyYW5nZTtcbiAgICAgICAgICAgIHByZUdVSVthU3RyXSA9IGluaXRpYWxWYWwgfHwgbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBmdWxsRGltZW5zaW9uID0gZ2QuX2Z1bGxEYXRhW2Z1bGxJbmRpY2VzW2ldXS5kaW1lbnNpb25zW2luaXRpYWxEaW1JbmRleF07XG5cbiAgICAgICAgaWYoIW5ld0NvbnN0cmFpbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgZGVsZXRlIGRpbS5jb25zdHJhaW50cmFuZ2U7XG4gICAgICAgICAgICBkZWxldGUgZnVsbERpbWVuc2lvbi5jb25zdHJhaW50cmFuZ2U7XG4gICAgICAgICAgICBuZXdDb25zdHJhaW50cyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZihuZXdDb25zdHJhaW50cy5sZW5ndGggPT09IDEpIG5ld0NvbnN0cmFpbnRzID0gbmV3Q29uc3RyYWludHNbMF07XG4gICAgICAgICAgICBkaW0uY29uc3RyYWludHJhbmdlID0gbmV3Q29uc3RyYWludHM7XG4gICAgICAgICAgICBmdWxsRGltZW5zaW9uLmNvbnN0cmFpbnRyYW5nZSA9IG5ld0NvbnN0cmFpbnRzLnNsaWNlKCk7XG4gICAgICAgICAgICAvLyB3cmFwIGluIGFub3RoZXIgYXJyYXkgZm9yIHJlc3R5bGUgZXZlbnQgZGF0YVxuICAgICAgICAgICAgbmV3Q29uc3RyYWludHMgPSBbbmV3Q29uc3RyYWludHNdO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHJlc3R5bGVEYXRhID0ge307XG4gICAgICAgIHJlc3R5bGVEYXRhW2FTdHJdID0gbmV3Q29uc3RyYWludHM7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9yZXN0eWxlJywgW3Jlc3R5bGVEYXRhLCBbaW5wdXRJbmRpY2VzW2ldXV0pO1xuICAgIH07XG5cbiAgICB2YXIgaG92ZXIgPSBmdW5jdGlvbihldmVudERhdGEpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2hvdmVyJywgZXZlbnREYXRhKTtcbiAgICB9O1xuXG4gICAgdmFyIHVuaG92ZXIgPSBmdW5jdGlvbihldmVudERhdGEpIHtcbiAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3VuaG92ZXInLCBldmVudERhdGEpO1xuICAgIH07XG5cbiAgICB2YXIgYXhlc01vdmVkID0gZnVuY3Rpb24oaSwgdmlzaWJsZUluZGljZXMpIHtcbiAgICAgICAgLy8gSGF2ZSB1cGRhdGVkIG9yZGVyIGRhdGEgb24gYGdkLmRhdGFgIGFuZCByYWlzZSBgUGxvdGx5LnJlc3R5bGVgIGV2ZW50XG4gICAgICAgIC8vIHdpdGhvdXQgaGF2aW5nIHRvIGluY3VyIGhlYXZ5IFVJIGJsb2NraW5nIGR1ZSB0byBhbiBhY3R1YWwgYFBsb3RseS5yZXN0eWxlYCBjYWxsXG5cbiAgICAgICAgLy8gZHJhZyZkcm9wIHNvcnRpbmcgb2YgdGhlIHZpc2libGUgZGltZW5zaW9uc1xuICAgICAgICB2YXIgb3JpZyA9IHNvcnRlcih2aXNpYmxlSW5kaWNlcywgaW5pdGlhbERpbXNbaV0uZmlsdGVyKGlzVmlzaWJsZSkpO1xuICAgICAgICBjdXJyZW50RGltc1tpXS5zb3J0KG9yaWcpO1xuXG4gICAgICAgIC8vIGludmlzaWJsZSBkaW1lbnNpb25zIGFyZSBub3QgaW50ZXJwcmV0ZWQgaW4gdGhlIGNvbnRleHQgb2YgZHJhZyZkcm9wIHNvcnRpbmcgYXMgYW4gaW52aXNpYmxlIGRpbWVuc2lvblxuICAgICAgICAvLyBjYW5ub3QgYmUgZHJhZ2dlZDsgdGhleSdyZSBpbnRlcnNwZXJzZWQgaW50byB0aGVpciBvcmlnaW5hbCBwb3NpdGlvbnMgYnkgdGhpcyBzdWJzZXF1ZW50IG1lcmdpbmcgc3RlcFxuICAgICAgICBpbml0aWFsRGltc1tpXS5maWx0ZXIoZnVuY3Rpb24oZCkge3JldHVybiAhaXNWaXNpYmxlKGQpO30pXG4gICAgICAgICAgICAgLnNvcnQoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgICAvLyBzdWJzZXF1ZW50IHNwbGljaW5nIHRvIGJlIGRvbmUgbGVmdCB0byByaWdodCwgb3RoZXJ3aXNlIGluZGljZXMgbWF5IGJlIGluY29ycmVjdFxuICAgICAgICAgICAgICAgICByZXR1cm4gaW5pdGlhbERpbXNbaV0uaW5kZXhPZihkKTtcbiAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmZvckVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnREaW1zW2ldLnNwbGljZShjdXJyZW50RGltc1tpXS5pbmRleE9mKGQpLCAxKTsgLy8gcmVtb3ZlIGZyb20gdGhlIGVuZFxuICAgICAgICAgICAgICAgIGN1cnJlbnREaW1zW2ldLnNwbGljZShpbml0aWFsRGltc1tpXS5pbmRleE9mKGQpLCAwLCBkKTsgLy8gaW5zZXJ0IGF0IG9yaWdpbmFsIGluZGV4XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAvLyBUT0RPOiB3ZSBjYW4ndCByZWFsbHkgc3RvcmUgdGhpcyBwYXJ0IG9mIHRoZSBpbnRlcmFjdGlvbiBzdGF0ZVxuICAgICAgICAvLyBkaXJlY3RseSBhcyBiZWxvdywgc2luY2UgaXQgaW5jdWRlcyBkYXRhIGFycmF5cy4gSWYgd2Ugd2FudCB0b1xuICAgICAgICAvLyBwZXJzaXN0IGNvbHVtbiBvcmRlciB3ZSBtYXkgaGF2ZSB0byBkbyBzb21ldGhpbmcgc3BlY2lhbCBmb3IgdGhpc1xuICAgICAgICAvLyBjYXNlIHRvIGp1c3Qgc3RvcmUgdGhlIG9yZGVyIGl0c2VsZi5cbiAgICAgICAgLy8gUmVnaXN0cnkuY2FsbCgnX3N0b3JlRGlyZWN0R1VJRWRpdCcsXG4gICAgICAgIC8vICAgICBnZC5kYXRhW2lucHV0SW5kaWNlc1tpXV0sXG4gICAgICAgIC8vICAgICBmdWxsTGF5b3V0Ll90cmFjZVByZUdVSVtnZC5fZnVsbERhdGFbZnVsbEluZGljZXNbaV1dLl9mdWxsSW5wdXQudWlkXSxcbiAgICAgICAgLy8gICAgIHtkaW1lbnNpb25zOiBjdXJyZW50RGltc1tpXX1cbiAgICAgICAgLy8gKTtcblxuICAgICAgICBnZC5lbWl0KCdwbG90bHlfcmVzdHlsZScsIFt7ZGltZW5zaW9uczogW2N1cnJlbnREaW1zW2ldXX0sIFtpbnB1dEluZGljZXNbaV1dXSk7XG4gICAgfTtcblxuICAgIHBhcmNvb3JkcyhcbiAgICAgICAgZ2QsXG4gICAgICAgIGNkTW9kdWxlLFxuICAgICAgICB7IC8vIGxheW91dFxuICAgICAgICAgICAgd2lkdGg6IHNpemUudyxcbiAgICAgICAgICAgIGhlaWdodDogc2l6ZS5oLFxuICAgICAgICAgICAgbWFyZ2luOiB7XG4gICAgICAgICAgICAgICAgdDogc2l6ZS50LFxuICAgICAgICAgICAgICAgIHI6IHNpemUucixcbiAgICAgICAgICAgICAgICBiOiBzaXplLmIsXG4gICAgICAgICAgICAgICAgbDogc2l6ZS5sXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHsgLy8gY2FsbGJhY2tzXG4gICAgICAgICAgICBmaWx0ZXJDaGFuZ2VkOiBmaWx0ZXJDaGFuZ2VkLFxuICAgICAgICAgICAgaG92ZXI6IGhvdmVyLFxuICAgICAgICAgICAgdW5ob3ZlcjogdW5ob3ZlcixcbiAgICAgICAgICAgIGF4ZXNNb3ZlZDogYXhlc01vdmVkXG4gICAgICAgIH1cbiAgICApO1xufTtcblxufSx7XCIuLi8uLi9saWIvcHJlcGFyZV9yZWdsXCI6NzMyLFwiLi9oZWxwZXJzXCI6MTA4MCxcIi4vcGFyY29vcmRzXCI6MTA4NH1dLDEwODY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgcGxvdEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZG9tYWluJykuYXR0cmlidXRlcztcbnZhciBmb250QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIHRleHRGb250QXR0cnMgPSBmb250QXR0cnMoe1xuICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgYXJyYXlPazogdHJ1ZSxcbiAgICBjb2xvckVkaXRUeXBlOiAncGxvdCcsXG4gICAgXG59KTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbGFiZWxzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICAvLyBlcXVpdmFsZW50IG9mIHgwIGFuZCBkeCwgaWYgbGFiZWwgaXMgbWlzc2luZ1xuICAgIGxhYmVsMDoge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZGxhYmVsOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogMSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHZhbHVlczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBtYXJrZXI6IHtcbiAgICAgICAgY29sb3JzOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsICAvLyBUT0RPICdjb2xvcl9hcnJheScgP1xuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG5cbiAgICB0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBob3ZlcnRleHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgIFxuICAgIH0sXG5cbi8vICdzZWUgZWc6J1xuLy8gJ2h0dHBzOi8vd3d3LmUtZWR1Y2F0aW9uLnBzdS5lZHUvbmF0dXJlb2ZnZW9pbmZvL3NpdGVzL3d3dy5lLWVkdWNhdGlvbi5wc3UuZWR1Lm5hdHVyZW9mZ2VvaW5mby9maWxlcy9pbWFnZS9oaXNwX3BpZXMuZ2lmJyxcbi8vICcodGhpcyBleGFtcGxlIGludm9sdmVzIGEgbWFwIHRvbyAtIG1heSBzb21lZGF5IGJlIGEgd2hvbGUgdHJhY2UgdHlwZScsXG4vLyAnb2YgaXRzIG93bi4gYnV0IHRoZSBwb2ludCBpcyB0aGUgc2l6ZSBvZiB0aGUgd2hvbGUgcGllIGlzIGltcG9ydGFudC4pJ1xuICAgIHNjYWxlZ3JvdXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiAnJyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIC8vIGxhYmVscyAobGVnZW5kIGlzIGhhbmRsZWQgYnkgcGxvdHMuYXR0cmlidXRlcy5zaG93bGVnZW5kIGFuZCBsYXlvdXQuaGlkZGVubGFiZWxzKVxuICAgIHRleHRpbmZvOiB7XG4gICAgICAgIHZhbFR5cGU6ICdmbGFnbGlzdCcsXG4gICAgICAgIFxuICAgICAgICBmbGFnczogWydsYWJlbCcsICd0ZXh0JywgJ3ZhbHVlJywgJ3BlcmNlbnQnXSxcbiAgICAgICAgZXh0cmFzOiBbJ25vbmUnXSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIHBsb3RBdHRycy5ob3ZlcmluZm8sIHtcbiAgICAgICAgZmxhZ3M6IFsnbGFiZWwnLCAndGV4dCcsICd2YWx1ZScsICdwZXJjZW50JywgJ25hbWUnXVxuICAgIH0pLFxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycyh7fSwge1xuICAgICAgICBrZXlzOiBbJ2xhYmVsJywgJ2NvbG9yJywgJ3ZhbHVlJywgJ3BlcmNlbnQnLCAndGV4dCddXG4gICAgfSksXG4gICAgdGV4dHBvc2l0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWydpbnNpZGUnLCAnb3V0c2lkZScsICdhdXRvJywgJ25vbmUnXSxcbiAgICAgICAgZGZsdDogJ2F1dG8nLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRleHRmb250OiBleHRlbmRGbGF0KHt9LCB0ZXh0Rm9udEF0dHJzLCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIGluc2lkZXRleHRmb250OiBleHRlbmRGbGF0KHt9LCB0ZXh0Rm9udEF0dHJzLCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIG91dHNpZGV0ZXh0Zm9udDogZXh0ZW5kRmxhdCh7fSwgdGV4dEZvbnRBdHRycywge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIHRpdGxlOiB7XG4gICAgICAgIHRleHQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGZsdDogJycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZm9udDogZXh0ZW5kRmxhdCh7fSwgdGV4dEZvbnRBdHRycywge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbXG4gICAgICAgICAgICAgICAgJ3RvcCBsZWZ0JywgJ3RvcCBjZW50ZXInLCAndG9wIHJpZ2h0JyxcbiAgICAgICAgICAgICAgICAnbWlkZGxlIGNlbnRlcicsXG4gICAgICAgICAgICAgICAgJ2JvdHRvbSBsZWZ0JywgJ2JvdHRvbSBjZW50ZXInLCAnYm90dG9tIHJpZ2h0J1xuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuXG4gICAgLy8gcG9zaXRpb24gYW5kIHNoYXBlXG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ3BpZScsIHRyYWNlOiB0cnVlLCBlZGl0VHlwZTogJ2NhbGMnfSksXG5cbiAgICBob2xlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBtYXg6IDEsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICAvLyBvcmRlcmluZyBhbmQgZGlyZWN0aW9uXG4gICAgc29ydDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRpcmVjdGlvbjoge1xuICAgICAgICAvKipcbiAgICAgICAgICogdGhlcmUgYXJlIHR3byBjb21tb24gY29udmVudGlvbnMsIGJvdGggb2Ygd2hpY2ggcGxhY2UgdGhlIGZpcnN0XG4gICAgICAgICAqIChsYXJnZXN0LCBpZiBzb3J0ZWQpIHNsaWNlIHdpdGggaXRzIGxlZnQgZWRnZSBhdCAxMiBvJ2Nsb2NrIGJ1dFxuICAgICAgICAgKiBzdWNjZWVkaW5nIHNsaWNlcyBmb2xsb3cgZWl0aGVyIGN3IG9yIGNjdyBmcm9tIHRoZXJlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBzZWUgaHR0cDovL3Zpc2FnZS5jby9kYXRhLXZpc3VhbGl6YXRpb24tMTAxLXBpZS1jaGFydHMvXG4gICAgICAgICAqL1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydjbG9ja3dpc2UnLCAnY291bnRlcmNsb2Nrd2lzZSddLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ2NvdW50ZXJjbG9ja3dpc2UnLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHJvdGF0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgbWluOiAtMzYwLFxuICAgICAgICBtYXg6IDM2MCxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHB1bGw6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIF9kZXByZWNhdGVkOiB7XG4gICAgICAgIHRpdGxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHRpdGxlZm9udDogZXh0ZW5kRmxhdCh7fSwgdGV4dEZvbnRBdHRycywge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICB0aXRsZXBvc2l0aW9uOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICAgICAndG9wIGxlZnQnLCAndG9wIGNlbnRlcicsICd0b3AgcmlnaHQnLFxuICAgICAgICAgICAgICAgICdtaWRkbGUgY2VudGVyJyxcbiAgICAgICAgICAgICAgICAnYm90dG9tIGxlZnQnLCAnYm90dG9tIGNlbnRlcicsICdib3R0b20gcmlnaHQnXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlc1wiOjU5MixcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi8uLi9wbG90cy9kb21haW5cIjo3OTIsXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTN9XSwxMDg3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBnZXRNb2R1bGVDYWxjRGF0YSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2dldF9kYXRhJykuZ2V0TW9kdWxlQ2FsY0RhdGE7XG5cbmV4cG9ydHMubmFtZSA9ICdwaWUnO1xuXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBQaWUgPSBSZWdpc3RyeS5nZXRNb2R1bGUoJ3BpZScpO1xuICAgIHZhciBjZFBpZSA9IGdldE1vZHVsZUNhbGNEYXRhKGdkLmNhbGNkYXRhLCBQaWUpWzBdO1xuICAgIFBpZS5wbG90KGdkLCBjZFBpZSk7XG59O1xuXG5leHBvcnRzLmNsZWFuID0gZnVuY3Rpb24obmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxEYXRhLCBvbGRGdWxsTGF5b3V0KSB7XG4gICAgdmFyIGhhZFBpZSA9IChvbGRGdWxsTGF5b3V0Ll9oYXMgJiYgb2xkRnVsbExheW91dC5faGFzKCdwaWUnKSk7XG4gICAgdmFyIGhhc1BpZSA9IChuZXdGdWxsTGF5b3V0Ll9oYXMgJiYgbmV3RnVsbExheW91dC5faGFzKCdwaWUnKSk7XG5cbiAgICBpZihoYWRQaWUgJiYgIWhhc1BpZSkge1xuICAgICAgICBvbGRGdWxsTGF5b3V0Ll9waWVsYXllci5zZWxlY3RBbGwoJ2cudHJhY2UnKS5yZW1vdmUoKTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2dldF9kYXRhXCI6ODAyLFwiLi4vLi4vcmVnaXN0cnlcIjo4NDd9XSwxMDg4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgaXNBcnJheU9yVHlwZWRBcnJheSA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmlzQXJyYXlPclR5cGVkQXJyYXk7XG52YXIgdGlueWNvbG9yID0gX2RlcmVxXygndGlueWNvbG9yMicpO1xuXG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xudmFyIGlzVmFsaWRUZXh0VmFsdWUgPSBfZGVyZXFfKCcuLi8uLi9saWInKS5pc1ZhbGlkVGV4dFZhbHVlO1xuXG52YXIgZXh0ZW5kZWRDb2xvcldheUxpc3QgPSB7fTtcblxuZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgY2QgPSBbXTtcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGhpZGRlbkxhYmVscyA9IGZ1bGxMYXlvdXQuaGlkZGVubGFiZWxzIHx8IFtdO1xuXG4gICAgdmFyIGxhYmVscyA9IHRyYWNlLmxhYmVscztcbiAgICB2YXIgY29sb3JzID0gdHJhY2UubWFya2VyLmNvbG9ycyB8fCBbXTtcbiAgICB2YXIgdmFscyA9IHRyYWNlLnZhbHVlcztcbiAgICB2YXIgaGFzVmFscyA9IGlzQXJyYXlPclR5cGVkQXJyYXkodmFscykgJiYgdmFscy5sZW5ndGg7XG5cbiAgICB2YXIgaSwgcHQ7XG5cbiAgICBpZih0cmFjZS5kbGFiZWwpIHtcbiAgICAgICAgbGFiZWxzID0gbmV3IEFycmF5KHZhbHMubGVuZ3RoKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgdmFscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGFiZWxzW2ldID0gU3RyaW5nKHRyYWNlLmxhYmVsMCArIGkgKiB0cmFjZS5kbGFiZWwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGFsbFRoaXNUcmFjZUxhYmVscyA9IHt9O1xuICAgIHZhciBwdWxsQ29sb3IgPSBtYWtlUHVsbENvbG9yRm4oZnVsbExheW91dFsnXycgKyB0cmFjZS50eXBlICsgJ2NvbG9ybWFwJ10pO1xuICAgIHZhciBzZXJpZXNMZW4gPSAoaGFzVmFscyA/IHZhbHMgOiBsYWJlbHMpLmxlbmd0aDtcbiAgICB2YXIgdlRvdGFsID0gMDtcbiAgICB2YXIgaXNBZ2dyZWdhdGVkID0gZmFsc2U7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzZXJpZXNMZW47IGkrKykge1xuICAgICAgICB2YXIgdiwgbGFiZWwsIGhpZGRlbjtcbiAgICAgICAgaWYoaGFzVmFscykge1xuICAgICAgICAgICAgdiA9IHZhbHNbaV07XG4gICAgICAgICAgICBpZighaXNOdW1lcmljKHYpKSBjb250aW51ZTtcbiAgICAgICAgICAgIHYgPSArdjtcbiAgICAgICAgICAgIGlmKHYgPCAwKSBjb250aW51ZTtcbiAgICAgICAgfSBlbHNlIHYgPSAxO1xuXG4gICAgICAgIGxhYmVsID0gbGFiZWxzW2ldO1xuICAgICAgICBpZihsYWJlbCA9PT0gdW5kZWZpbmVkIHx8IGxhYmVsID09PSAnJykgbGFiZWwgPSBpO1xuICAgICAgICBsYWJlbCA9IFN0cmluZyhsYWJlbCk7XG5cbiAgICAgICAgdmFyIHRoaXNMYWJlbEluZGV4ID0gYWxsVGhpc1RyYWNlTGFiZWxzW2xhYmVsXTtcbiAgICAgICAgaWYodGhpc0xhYmVsSW5kZXggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgYWxsVGhpc1RyYWNlTGFiZWxzW2xhYmVsXSA9IGNkLmxlbmd0aDtcblxuICAgICAgICAgICAgaGlkZGVuID0gaGlkZGVuTGFiZWxzLmluZGV4T2YobGFiZWwpICE9PSAtMTtcblxuICAgICAgICAgICAgaWYoIWhpZGRlbikgdlRvdGFsICs9IHY7XG5cbiAgICAgICAgICAgIGNkLnB1c2goe1xuICAgICAgICAgICAgICAgIHY6IHYsXG4gICAgICAgICAgICAgICAgbGFiZWw6IGxhYmVsLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBwdWxsQ29sb3IoY29sb3JzW2ldLCBsYWJlbCksXG4gICAgICAgICAgICAgICAgaTogaSxcbiAgICAgICAgICAgICAgICBwdHM6IFtpXSxcbiAgICAgICAgICAgICAgICBoaWRkZW46IGhpZGRlblxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpc0FnZ3JlZ2F0ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICBwdCA9IGNkW3RoaXNMYWJlbEluZGV4XTtcbiAgICAgICAgICAgIHB0LnYgKz0gdjtcbiAgICAgICAgICAgIHB0LnB0cy5wdXNoKGkpO1xuICAgICAgICAgICAgaWYoIXB0LmhpZGRlbikgdlRvdGFsICs9IHY7XG5cbiAgICAgICAgICAgIGlmKHB0LmNvbG9yID09PSBmYWxzZSAmJiBjb2xvcnNbaV0pIHtcbiAgICAgICAgICAgICAgICBwdC5jb2xvciA9IHB1bGxDb2xvcihjb2xvcnNbaV0sIGxhYmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBzaG91bGRTb3J0ID0gKHRyYWNlLnR5cGUgPT09ICdmdW5uZWxhcmVhJykgPyBpc0FnZ3JlZ2F0ZWQgOiB0cmFjZS5zb3J0O1xuICAgIGlmKHNob3VsZFNvcnQpIGNkLnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYi52IC0gYS52OyB9KTtcblxuICAgIC8vIGluY2x1ZGUgdGhlIHN1bSBvZiBhbGwgdmFsdWVzIGluIHRoZSBmaXJzdCBwb2ludFxuICAgIGlmKGNkWzBdKSBjZFswXS52VG90YWwgPSB2VG90YWw7XG5cbiAgICAvLyBub3cgaW5zZXJ0IHRleHRcbiAgICB2YXIgdGV4dGluZm8gPSB0cmFjZS50ZXh0aW5mbztcbiAgICBpZih0ZXh0aW5mbyAmJiB0ZXh0aW5mbyAhPT0gJ25vbmUnKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IHRleHRpbmZvLnNwbGl0KCcrJyk7XG4gICAgICAgIHZhciBoYXNGbGFnID0gZnVuY3Rpb24oZmxhZykgeyByZXR1cm4gcGFydHMuaW5kZXhPZihmbGFnKSAhPT0gLTE7IH07XG4gICAgICAgIHZhciBoYXNMYWJlbCA9IGhhc0ZsYWcoJ2xhYmVsJyk7XG4gICAgICAgIHZhciBoYXNUZXh0ID0gaGFzRmxhZygndGV4dCcpO1xuICAgICAgICB2YXIgaGFzVmFsdWUgPSBoYXNGbGFnKCd2YWx1ZScpO1xuICAgICAgICB2YXIgaGFzUGVyY2VudCA9IGhhc0ZsYWcoJ3BlcmNlbnQnKTtcblxuICAgICAgICB2YXIgc2VwYXJhdG9ycyA9IGZ1bGxMYXlvdXQuc2VwYXJhdG9ycztcbiAgICAgICAgdmFyIHRleHQ7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHB0ID0gY2RbaV07XG4gICAgICAgICAgICB0ZXh0ID0gaGFzTGFiZWwgPyBbcHQubGFiZWxdIDogW107XG4gICAgICAgICAgICBpZihoYXNUZXh0KSB7XG4gICAgICAgICAgICAgICAgdmFyIHR4ID0gaGVscGVycy5nZXRGaXJzdEZpbGxlZCh0cmFjZS50ZXh0LCBwdC5wdHMpO1xuICAgICAgICAgICAgICAgIGlmKGlzVmFsaWRUZXh0VmFsdWUodHgpKSB0ZXh0LnB1c2godHgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoaGFzVmFsdWUpIHRleHQucHVzaChoZWxwZXJzLmZvcm1hdFBpZVZhbHVlKHB0LnYsIHNlcGFyYXRvcnMpKTtcbiAgICAgICAgICAgIGlmKGhhc1BlcmNlbnQpIHRleHQucHVzaChoZWxwZXJzLmZvcm1hdFBpZVBlcmNlbnQocHQudiAvIHZUb3RhbCwgc2VwYXJhdG9ycykpO1xuICAgICAgICAgICAgcHQudGV4dCA9IHRleHQuam9pbignPGJyPicpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNkO1xufVxuXG5mdW5jdGlvbiBtYWtlUHVsbENvbG9yRm4oY29sb3JNYXApIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gcHVsbENvbG9yKGNvbG9yLCBpZCkge1xuICAgICAgICBpZighY29sb3IpIHJldHVybiBmYWxzZTtcblxuICAgICAgICBjb2xvciA9IHRpbnljb2xvcihjb2xvcik7XG4gICAgICAgIGlmKCFjb2xvci5pc1ZhbGlkKCkpIHJldHVybiBmYWxzZTtcblxuICAgICAgICBjb2xvciA9IENvbG9yLmFkZE9wYWNpdHkoY29sb3IsIGNvbG9yLmdldEFscGhhKCkpO1xuICAgICAgICBpZighY29sb3JNYXBbaWRdKSBjb2xvck1hcFtpZF0gPSBjb2xvcjtcblxuICAgICAgICByZXR1cm4gY29sb3I7XG4gICAgfTtcbn1cblxuLypcbiAqIGBjYWxjYCBmaWxsZWQgaW4gKGFuZCBjb2xsYXRlZCkgZXhwbGljaXQgY29sb3JzLlxuICogTm93IHdlIG5lZWQgdG8gcHJvcGFnYXRlIHRoZXNlIGV4cGxpY2l0IGNvbG9ycyB0byBvdGhlciB0cmFjZXMsXG4gKiBhbmQgZmlsbCBpbiBkZWZhdWx0IGNvbG9ycy5cbiAqIFRoaXMgaXMgZG9uZSBhZnRlciBzb3J0aW5nLCBzbyB3ZSBwaWNrIGRlZmF1bHRzXG4gKiBpbiB0aGUgb3JkZXIgc2xpY2VzIHdpbGwgYmUgZGlzcGxheWVkXG4gKi9cbmZ1bmN0aW9uIGNyb3NzVHJhY2VDYWxjKGdkLCBwbG90aW5mbykgeyAvLyBUT0RPOiBzaG91bGQgd2UgbmFtZSB0aGUgc2Vjb25kIGFyZ3VtZW50IG9wdHM/XG4gICAgdmFyIGRlc2lyZWRUeXBlID0gKHBsb3RpbmZvIHx8IHt9KS50eXBlO1xuICAgIGlmKCFkZXNpcmVkVHlwZSkgZGVzaXJlZFR5cGUgPSAncGllJztcblxuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGNhbGNkYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIGNvbG9yV2F5ID0gZnVsbExheW91dFtkZXNpcmVkVHlwZSArICdjb2xvcndheSddO1xuICAgIHZhciBjb2xvck1hcCA9IGZ1bGxMYXlvdXRbJ18nICsgZGVzaXJlZFR5cGUgKyAnY29sb3JtYXAnXTtcblxuICAgIGlmKGZ1bGxMYXlvdXRbJ2V4dGVuZCcgKyBkZXNpcmVkVHlwZSArICdjb2xvcnMnXSkge1xuICAgICAgICBjb2xvcldheSA9IGdlbmVyYXRlRXh0ZW5kZWRDb2xvcnMoY29sb3JXYXksIGV4dGVuZGVkQ29sb3JXYXlMaXN0KTtcbiAgICB9XG4gICAgdmFyIGRmbHRDb2xvckNvdW50ID0gMDtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjYWxjZGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2QgPSBjYWxjZGF0YVtpXTtcbiAgICAgICAgdmFyIHRyYWNlVHlwZSA9IGNkWzBdLnRyYWNlLnR5cGU7XG4gICAgICAgIGlmKHRyYWNlVHlwZSAhPT0gZGVzaXJlZFR5cGUpIGNvbnRpbnVlO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjZC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIHB0ID0gY2Rbal07XG4gICAgICAgICAgICBpZihwdC5jb2xvciA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICAvLyBoYXZlIHdlIHNlZW4gdGhpcyBsYWJlbCBhbmQgYXNzaWduZWQgYSBjb2xvciB0byBpdCBpbiBhIHByZXZpb3VzIHRyYWNlP1xuICAgICAgICAgICAgICAgIGlmKGNvbG9yTWFwW3B0LmxhYmVsXSkge1xuICAgICAgICAgICAgICAgICAgICBwdC5jb2xvciA9IGNvbG9yTWFwW3B0LmxhYmVsXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb2xvck1hcFtwdC5sYWJlbF0gPSBwdC5jb2xvciA9IGNvbG9yV2F5W2RmbHRDb2xvckNvdW50ICUgY29sb3JXYXkubGVuZ3RoXTtcbiAgICAgICAgICAgICAgICAgICAgZGZsdENvbG9yQ291bnQrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogcGljayBhIGRlZmF1bHQgY29sb3IgZnJvbSB0aGUgbWFpbiBkZWZhdWx0IHNldCwgYXVnbWVudGVkIGJ5XG4gKiBpdHNlbGYgbGlnaHRlciB0aGVuIGRhcmtlciBiZWZvcmUgcmVwZWF0aW5nXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlRXh0ZW5kZWRDb2xvcnMoY29sb3JMaXN0LCBleHRlbmRlZENvbG9yV2F5cykge1xuICAgIHZhciBpO1xuICAgIHZhciBjb2xvclN0cmluZyA9IEpTT04uc3RyaW5naWZ5KGNvbG9yTGlzdCk7XG4gICAgdmFyIGNvbG9ycyA9IGV4dGVuZGVkQ29sb3JXYXlzW2NvbG9yU3RyaW5nXTtcbiAgICBpZighY29sb3JzKSB7XG4gICAgICAgIGNvbG9ycyA9IGNvbG9yTGlzdC5zbGljZSgpO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNvbG9yTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29sb3JzLnB1c2godGlueWNvbG9yKGNvbG9yTGlzdFtpXSkubGlnaHRlbigyMCkudG9IZXhTdHJpbmcoKSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb2xvckxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbG9ycy5wdXNoKHRpbnljb2xvcihjb2xvckxpc3RbaV0pLmRhcmtlbigyMCkudG9IZXhTdHJpbmcoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZXh0ZW5kZWRDb2xvcldheXNbY29sb3JTdHJpbmddID0gY29sb3JzO1xuICAgIH1cblxuICAgIHJldHVybiBjb2xvcnM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNhbGM6IGNhbGMsXG4gICAgY3Jvc3NUcmFjZUNhbGM6IGNyb3NzVHJhY2VDYWxjLFxuXG4gICAgbWFrZVB1bGxDb2xvckZuOiBtYWtlUHVsbENvbG9yRm4sXG4gICAgZ2VuZXJhdGVFeHRlbmRlZENvbG9yczogZ2VuZXJhdGVFeHRlbmRlZENvbG9yc1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi9oZWxwZXJzXCI6MTA5MSxcImZhc3QtaXNudW1lcmljXCI6MjI1LFwidGlueWNvbG9yMlwiOjUzN31dLDEwODk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIGhhbmRsZURvbWFpbkRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZG9tYWluJykuZGVmYXVsdHM7XG52YXIgaGFuZGxlVGV4dCA9IF9kZXJlcV8oJy4uL2Jhci9kZWZhdWx0cycpLmhhbmRsZVRleHQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsZW47XG4gICAgdmFyIHZhbHMgPSBjb2VyY2UoJ3ZhbHVlcycpO1xuICAgIHZhciBoYXNWYWxzID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkodmFscyk7XG4gICAgdmFyIGxhYmVscyA9IGNvZXJjZSgnbGFiZWxzJyk7XG4gICAgaWYoQXJyYXkuaXNBcnJheShsYWJlbHMpKSB7XG4gICAgICAgIGxlbiA9IGxhYmVscy5sZW5ndGg7XG4gICAgICAgIGlmKGhhc1ZhbHMpIGxlbiA9IE1hdGgubWluKGxlbiwgdmFscy5sZW5ndGgpO1xuICAgIH0gZWxzZSBpZihoYXNWYWxzKSB7XG4gICAgICAgIGxlbiA9IHZhbHMubGVuZ3RoO1xuXG4gICAgICAgIGNvZXJjZSgnbGFiZWwwJyk7XG4gICAgICAgIGNvZXJjZSgnZGxhYmVsJyk7XG4gICAgfVxuXG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIHZhciBsaW5lV2lkdGggPSBjb2VyY2UoJ21hcmtlci5saW5lLndpZHRoJyk7XG4gICAgaWYobGluZVdpZHRoKSBjb2VyY2UoJ21hcmtlci5saW5lLmNvbG9yJyk7XG5cbiAgICBjb2VyY2UoJ21hcmtlci5jb2xvcnMnKTtcblxuICAgIGNvZXJjZSgnc2NhbGVncm91cCcpO1xuICAgIC8vIFRPRE86IGhvbGUgbmVlZHMgdG8gYmUgY29lcmNlZCB0byB0aGUgc2FtZSB2YWx1ZSB3aXRoaW4gYSBzY2FsZWVncm91cFxuXG4gICAgdmFyIHRleHREYXRhID0gY29lcmNlKCd0ZXh0Jyk7XG4gICAgdmFyIHRleHRJbmZvID0gY29lcmNlKCd0ZXh0aW5mbycsIEFycmF5LmlzQXJyYXkodGV4dERhdGEpID8gJ3RleHQrcGVyY2VudCcgOiAncGVyY2VudCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG5cbiAgICBpZih0ZXh0SW5mbyAmJiB0ZXh0SW5mbyAhPT0gJ25vbmUnKSB7XG4gICAgICAgIHZhciB0ZXh0cG9zaXRpb24gPSBjb2VyY2UoJ3RleHRwb3NpdGlvbicpO1xuICAgICAgICBoYW5kbGVUZXh0KHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwgdGV4dHBvc2l0aW9uLCB7XG4gICAgICAgICAgICBtb2R1bGVIYXNTZWxlY3RlZDogZmFsc2UsXG4gICAgICAgICAgICBtb2R1bGVIYXNVbnNlbGVjdGVkOiBmYWxzZSxcbiAgICAgICAgICAgIG1vZHVsZUhhc0NvbnN0cmFpbjogZmFsc2UsXG4gICAgICAgICAgICBtb2R1bGVIYXNDbGlwb25heGlzOiBmYWxzZSxcbiAgICAgICAgICAgIG1vZHVsZUhhc1RleHRhbmdsZTogZmFsc2UsXG4gICAgICAgICAgICBtb2R1bGVIYXNJbnNpZGVhbmNob3I6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGhhbmRsZURvbWFpbkRlZmF1bHRzKHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICB2YXIgaG9sZSA9IGNvZXJjZSgnaG9sZScpO1xuICAgIHZhciB0aXRsZSA9IGNvZXJjZSgndGl0bGUudGV4dCcpO1xuICAgIGlmKHRpdGxlKSB7XG4gICAgICAgIHZhciB0aXRsZVBvc2l0aW9uID0gY29lcmNlKCd0aXRsZS5wb3NpdGlvbicsIGhvbGUgPyAnbWlkZGxlIGNlbnRlcicgOiAndG9wIGNlbnRlcicpO1xuICAgICAgICBpZighaG9sZSAmJiB0aXRsZVBvc2l0aW9uID09PSAnbWlkZGxlIGNlbnRlcicpIHRyYWNlT3V0LnRpdGxlLnBvc2l0aW9uID0gJ3RvcCBjZW50ZXInO1xuICAgICAgICBMaWIuY29lcmNlRm9udChjb2VyY2UsICd0aXRsZS5mb250JywgbGF5b3V0LmZvbnQpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnc29ydCcpO1xuICAgIGNvZXJjZSgnZGlyZWN0aW9uJyk7XG4gICAgY29lcmNlKCdyb3RhdGlvbicpO1xuICAgIGNvZXJjZSgncHVsbCcpO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9kb21haW5cIjo3OTIsXCIuLi9iYXIvZGVmYXVsdHNcIjo4NjEsXCIuL2F0dHJpYnV0ZXNcIjoxMDg2fV0sMTA5MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBhcHBlbmRBcnJheU11bHRpUG9pbnRWYWx1ZXMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hlbHBlcnMnKS5hcHBlbmRBcnJheU11bHRpUG9pbnRWYWx1ZXM7XG5cbi8vIE5vdGU6IGxpa2Ugb3RoZXIgZXZlbnREYXRhIHJvdXRpbmVzLCB0aGlzIGNyZWF0ZXMgdGhlIGRhdGEgZm9yIGhvdmVyL3VuaG92ZXIvY2xpY2sgZXZlbnRzXG4vLyBidXQgaXQgaGFzIGEgZGlmZmVyZW50IEFQSSBhbmQgZ29lcyB0aHJvdWdoIGEgdG90YWxseSBkaWZmZXJlbnQgcGF0aHdheS5cbi8vIFNvIHRvIGVuc3VyZSBpdCBkb2Vzbid0IGdldCBtaXN1c2VkLCBpdCdzIG5vdCBhdHRhY2hlZCB0byB0aGUgUGllIG1vZHVsZS5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZXZlbnREYXRhKHB0LCB0cmFjZSkge1xuICAgIHZhciBvdXQgPSB7XG4gICAgICAgIGN1cnZlTnVtYmVyOiB0cmFjZS5pbmRleCxcbiAgICAgICAgcG9pbnROdW1iZXJzOiBwdC5wdHMsXG4gICAgICAgIGRhdGE6IHRyYWNlLl9pbnB1dCxcbiAgICAgICAgZnVsbERhdGE6IHRyYWNlLFxuICAgICAgICBsYWJlbDogcHQubGFiZWwsXG4gICAgICAgIGNvbG9yOiBwdC5jb2xvcixcbiAgICAgICAgdmFsdWU6IHB0LnYsXG4gICAgICAgIHBlcmNlbnQ6IHB0LnBlcmNlbnQsXG4gICAgICAgIHRleHQ6IHB0LnRleHQsXG5cbiAgICAgICAgLy8gcHQudiAoYW5kIHB0LmkgYmVsb3cpIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgICAgIHY6IHB0LnZcbiAgICB9O1xuXG4gICAgLy8gT25seSBpbmNsdWRlIHBvaW50TnVtYmVyIGlmIGl0J3MgdW5hbWJpZ3VvdXNcbiAgICBpZihwdC5wdHMubGVuZ3RoID09PSAxKSBvdXQucG9pbnROdW1iZXIgPSBvdXQuaSA9IHB0LnB0c1swXTtcblxuICAgIC8vIEFkZCBleHRyYSBkYXRhIGFycmF5cyB0byB0aGUgb3V0cHV0XG4gICAgLy8gbm90aWNlIHRoYXQgdGhpcyBpcyB0aGUgbXVsdGktcG9pbnQgdmVyc2lvbiAoJ3MnIG9uIHRoZSBlbmQhKVxuICAgIC8vIHNvIGFkZGVkIGRhdGEgd2lsbCBiZSBhcnJheXMgbWF0Y2hpbmcgdGhlIHBvaW50TnVtYmVycyBhcnJheS5cbiAgICBhcHBlbmRBcnJheU11bHRpUG9pbnRWYWx1ZXMob3V0LCB0cmFjZSwgcHQucHRzKTtcblxuICAgIC8vIGRvbid0IGluY2x1ZGUgb2Jzb2xldGUgZmllbGRzIGluIG5ldyBmdW5uZWxhcmVhIHRyYWNlc1xuICAgIGlmKHRyYWNlLnR5cGUgPT09ICdmdW5uZWxhcmVhJykge1xuICAgICAgICBkZWxldGUgb3V0LnY7XG4gICAgICAgIGRlbGV0ZSBvdXQuaTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2Z4L2hlbHBlcnNcIjo2Mjh9XSwxMDkxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG5leHBvcnRzLmZvcm1hdFBpZVBlcmNlbnQgPSBmdW5jdGlvbiBmb3JtYXRQaWVQZXJjZW50KHYsIHNlcGFyYXRvcnMpIHtcbiAgICB2YXIgdlJvdW5kZWQgPSAodiAqIDEwMCkudG9QcmVjaXNpb24oMyk7XG4gICAgaWYodlJvdW5kZWQubGFzdEluZGV4T2YoJy4nKSAhPT0gLTEpIHtcbiAgICAgICAgdlJvdW5kZWQgPSB2Um91bmRlZC5yZXBsYWNlKC9bLl0/MCskLywgJycpO1xuICAgIH1cbiAgICByZXR1cm4gTGliLm51bVNlcGFyYXRlKHZSb3VuZGVkLCBzZXBhcmF0b3JzKSArICclJztcbn07XG5cbmV4cG9ydHMuZm9ybWF0UGllVmFsdWUgPSBmdW5jdGlvbiBmb3JtYXRQaWVWYWx1ZSh2LCBzZXBhcmF0b3JzKSB7XG4gICAgdmFyIHZSb3VuZGVkID0gdi50b1ByZWNpc2lvbigxMCk7XG4gICAgaWYodlJvdW5kZWQubGFzdEluZGV4T2YoJy4nKSAhPT0gLTEpIHtcbiAgICAgICAgdlJvdW5kZWQgPSB2Um91bmRlZC5yZXBsYWNlKC9bLl0/MCskLywgJycpO1xuICAgIH1cbiAgICByZXR1cm4gTGliLm51bVNlcGFyYXRlKHZSb3VuZGVkLCBzZXBhcmF0b3JzKTtcbn07XG5cbmV4cG9ydHMuZ2V0Rmlyc3RGaWxsZWQgPSBmdW5jdGlvbiBnZXRGaXJzdEZpbGxlZChhcnJheSwgaW5kaWNlcykge1xuICAgIGlmKCFBcnJheS5pc0FycmF5KGFycmF5KSkgcmV0dXJuO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB2ID0gYXJyYXlbaW5kaWNlc1tpXV07XG4gICAgICAgIGlmKHYgfHwgdiA9PT0gMCkgcmV0dXJuIHY7XG4gICAgfVxufTtcblxuZXhwb3J0cy5jYXN0T3B0aW9uID0gZnVuY3Rpb24gY2FzdE9wdGlvbihpdGVtLCBpbmRpY2VzKSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheShpdGVtKSkgcmV0dXJuIGV4cG9ydHMuZ2V0Rmlyc3RGaWxsZWQoaXRlbSwgaW5kaWNlcyk7XG4gICAgZWxzZSBpZihpdGVtKSByZXR1cm4gaXRlbTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sMTA5MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2RlZmF1bHRzJyksXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpLFxuXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJykuY2FsYyxcbiAgICBjcm9zc1RyYWNlQ2FsYzogX2RlcmVxXygnLi9jYWxjJykuY3Jvc3NUcmFjZUNhbGMsXG5cbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKS5wbG90LFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuL3N0eWxlJyksXG4gICAgc3R5bGVPbmU6IF9kZXJlcV8oJy4vc3R5bGVfb25lJyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdwaWUnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuL2Jhc2VfcGxvdCcpLFxuICAgIGNhdGVnb3JpZXM6IFsncGllLWxpa2UnLCAncGllJywgJ3Nob3dMZWdlbmQnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi9hdHRyaWJ1dGVzXCI6MTA4NixcIi4vYmFzZV9wbG90XCI6MTA4NyxcIi4vY2FsY1wiOjEwODgsXCIuL2RlZmF1bHRzXCI6MTA4OSxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjoxMDkzLFwiLi9sYXlvdXRfZGVmYXVsdHNcIjoxMDk0LFwiLi9wbG90XCI6MTA5NSxcIi4vc3R5bGVcIjoxMDk2LFwiLi9zdHlsZV9vbmVcIjoxMDk3fV0sMTA5MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhpZGRlbmxhYmVsczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHBpZWNvbG9yd2F5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcmxpc3QnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBleHRlbmRwaWVjb2xvcnM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7fV0sMTA5NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIGxheW91dEF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2xheW91dF9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5TGF5b3V0RGVmYXVsdHMobGF5b3V0SW4sIGxheW91dE91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGxheW91dEluLCBsYXlvdXRPdXQsIGxheW91dEF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnaGlkZGVubGFiZWxzJyk7XG4gICAgY29lcmNlKCdwaWVjb2xvcndheScsIGxheW91dE91dC5jb2xvcndheSk7XG4gICAgY29lcmNlKCdleHRlbmRwaWVjb2xvcnMnKTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjEwOTN9XSwxMDk1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIEZ4ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meCcpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBzdmdUZXh0VXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcblxudmFyIGhlbHBlcnMgPSBfZGVyZXFfKCcuL2hlbHBlcnMnKTtcbnZhciBldmVudERhdGEgPSBfZGVyZXFfKCcuL2V2ZW50X2RhdGEnKTtcblxuZnVuY3Rpb24gcGxvdChnZCwgY2RNb2R1bGUpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgcHJlcmVuZGVyVGl0bGVzKGNkTW9kdWxlLCBnZCk7XG4gICAgbGF5b3V0QXJlYXMoY2RNb2R1bGUsIGZ1bGxMYXlvdXQuX3NpemUpO1xuXG4gICAgdmFyIHBsb3RHcm91cHMgPSBMaWIubWFrZVRyYWNlR3JvdXBzKGZ1bGxMYXlvdXQuX3BpZWxheWVyLCBjZE1vZHVsZSwgJ3RyYWNlJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICBzZXRDb29yZHMoY2QpO1xuXG4gICAgICAgIC8vIFRPRE86IG1pdGVyIG1pZ2h0IGxvb2sgYmV0dGVyIGJ1dCBjYW4gc29tZXRpbWVzIGNhdXNlIHByb2JsZW1zXG4gICAgICAgIC8vIG1heWJlIG1pdGVyIHdpdGggYSBzbWFsbC1pc2ggc3Ryb2tlLW1pdGVybGltaXQ/XG4gICAgICAgIHBsb3RHcm91cC5hdHRyKCdzdHJva2UtbGluZWpvaW4nLCAncm91bmQnKTtcblxuICAgICAgICBwbG90R3JvdXAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBzbGljZXMgPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdnLnNsaWNlJykuZGF0YShjZCk7XG5cbiAgICAgICAgICAgIHNsaWNlcy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3NsaWNlJywgdHJ1ZSk7XG4gICAgICAgICAgICBzbGljZXMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgICAgICB2YXIgcXVhZHJhbnRzID0gW1xuICAgICAgICAgICAgICAgIFtbXSwgW11dLCAvLyB5PDA6IHg8MCwgeD49MFxuICAgICAgICAgICAgICAgIFtbXSwgW11dIC8vIHk+PTA6IHg8MCwgeD49MFxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHZhciBoYXNPdXRzaWRlVGV4dCA9IGZhbHNlO1xuXG4gICAgICAgICAgICBzbGljZXMuZWFjaChmdW5jdGlvbihwdCkge1xuICAgICAgICAgICAgICAgIGlmKHB0LmhpZGRlbikge1xuICAgICAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdwYXRoLGcnKS5yZW1vdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHRvIGhhdmUgY29uc2lzdGVudCBldmVudCBkYXRhIGNvbXBhcmVkIHRvIG90aGVyIHRyYWNlc1xuICAgICAgICAgICAgICAgIHB0LnBvaW50TnVtYmVyID0gcHQuaTtcbiAgICAgICAgICAgICAgICBwdC5jdXJ2ZU51bWJlciA9IHRyYWNlLmluZGV4O1xuXG4gICAgICAgICAgICAgICAgcXVhZHJhbnRzW3B0LnB4bWlkWzFdIDwgMCA/IDAgOiAxXVtwdC5weG1pZFswXSA8IDAgPyAwIDogMV0ucHVzaChwdCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY3ggPSBjZDAuY3g7XG4gICAgICAgICAgICAgICAgdmFyIGN5ID0gY2QwLmN5O1xuICAgICAgICAgICAgICAgIHZhciBzbGljZVRvcCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgICAgICB2YXIgc2xpY2VQYXRoID0gc2xpY2VUb3Auc2VsZWN0QWxsKCdwYXRoLnN1cmZhY2UnKS5kYXRhKFtwdF0pO1xuXG4gICAgICAgICAgICAgICAgc2xpY2VQYXRoLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgICAgICAgLmNsYXNzZWQoJ3N1cmZhY2UnLCB0cnVlKVxuICAgICAgICAgICAgICAgICAgICAuc3R5bGUoeydwb2ludGVyLWV2ZW50cyc6ICdhbGwnfSk7XG5cbiAgICAgICAgICAgICAgICBzbGljZVRvcC5jYWxsKGF0dGFjaEZ4SGFuZGxlcnMsIGdkLCBjZCk7XG5cbiAgICAgICAgICAgICAgICBpZih0cmFjZS5wdWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwdWxsID0gK2hlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS5wdWxsLCBwdC5wdHMpIHx8IDA7XG4gICAgICAgICAgICAgICAgICAgIGlmKHB1bGwgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjeCArPSBwdWxsICogcHQucHhtaWRbMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBjeSArPSBwdWxsICogcHQucHhtaWRbMV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwdC5jeEZpbmFsID0gY3g7XG4gICAgICAgICAgICAgICAgcHQuY3lGaW5hbCA9IGN5O1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gYXJjKHN0YXJ0LCBmaW5pc2gsIGN3LCBzY2FsZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZHggPSBzY2FsZSAqIChmaW5pc2hbMF0gLSBzdGFydFswXSk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkeSA9IHNjYWxlICogKGZpbmlzaFsxXSAtIHN0YXJ0WzFdKTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ2EnICtcbiAgICAgICAgICAgICAgICAgICAgICAgIChzY2FsZSAqIGNkMC5yKSArICcsJyArIChzY2FsZSAqIGNkMC5yKSArICcgMCAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB0LmxhcmdlQXJjICsgKGN3ID8gJyAxICcgOiAnIDAgJykgKyBkeCArICcsJyArIGR5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBob2xlID0gdHJhY2UuaG9sZTtcbiAgICAgICAgICAgICAgICBpZihwdC52ID09PSBjZDAudlRvdGFsKSB7IC8vIDEwMCUgZmFpbHMgYmNzIGFyYyBzdGFydCBhbmQgZW5kIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dGVyQ2lyY2xlID0gJ00nICsgKGN4ICsgcHQucHgwWzBdKSArICcsJyArIChjeSArIHB0LnB4MFsxXSkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgYXJjKHB0LnB4MCwgcHQucHhtaWQsIHRydWUsIDEpICtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyYyhwdC5weG1pZCwgcHQucHgwLCB0cnVlLCAxKSArICdaJztcbiAgICAgICAgICAgICAgICAgICAgaWYoaG9sZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2xpY2VQYXRoLmF0dHIoJ2QnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdNJyArIChjeCArIGhvbGUgKiBwdC5weDBbMF0pICsgJywnICsgKGN5ICsgaG9sZSAqIHB0LnB4MFsxXSkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyYyhwdC5weDAsIHB0LnB4bWlkLCBmYWxzZSwgaG9sZSkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyYyhwdC5weG1pZCwgcHQucHgwLCBmYWxzZSwgaG9sZSkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdaJyArIG91dGVyQ2lyY2xlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHNsaWNlUGF0aC5hdHRyKCdkJywgb3V0ZXJDaXJjbGUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRlckFyYyA9IGFyYyhwdC5weDAsIHB0LnB4MSwgdHJ1ZSwgMSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoaG9sZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJpbSA9IDEgLSBob2xlO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2xpY2VQYXRoLmF0dHIoJ2QnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdNJyArIChjeCArIGhvbGUgKiBwdC5weDFbMF0pICsgJywnICsgKGN5ICsgaG9sZSAqIHB0LnB4MVsxXSkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyYyhwdC5weDEsIHB0LnB4MCwgZmFsc2UsIGhvbGUpICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbCcgKyAocmltICogcHQucHgwWzBdKSArICcsJyArIChyaW0gKiBwdC5weDBbMV0pICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRlckFyYyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1onKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNsaWNlUGF0aC5hdHRyKCdkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTScgKyBjeCArICcsJyArIGN5ICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbCcgKyBwdC5weDBbMF0gKyAnLCcgKyBwdC5weDBbMV0gK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGVyQXJjICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnWicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gYWRkIHRleHRcbiAgICAgICAgICAgICAgICB2YXIgdGV4dFBvc2l0aW9uID0gaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLnRleHRwb3NpdGlvbiwgcHQucHRzKTtcbiAgICAgICAgICAgICAgICB2YXIgc2xpY2VUZXh0R3JvdXAgPSBzbGljZVRvcC5zZWxlY3RBbGwoJ2cuc2xpY2V0ZXh0JylcbiAgICAgICAgICAgICAgICAgICAgLmRhdGEocHQudGV4dCAmJiAodGV4dFBvc2l0aW9uICE9PSAnbm9uZScpID8gWzBdIDogW10pO1xuXG4gICAgICAgICAgICAgICAgc2xpY2VUZXh0R3JvdXAuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAgICAgICAgICAgICAuY2xhc3NlZCgnc2xpY2V0ZXh0JywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgc2xpY2VUZXh0R3JvdXAuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgICAgICAgICAgc2xpY2VUZXh0R3JvdXAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNsaWNlVGV4dCA9IExpYi5lbnN1cmVTaW5nbGUoZDMuc2VsZWN0KHRoaXMpLCAndGV4dCcsICcnLCBmdW5jdGlvbihzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwcm9oaWJpdCB0ZXggaW50ZXJwcmV0YXRpb24gdW50aWwgd2UgY2FuIGhhbmRsZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGV4IGFuZCByZWd1bGFyIHRleHQgdG9nZXRoZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIHMuYXR0cignZGF0YS1ub3RleCcsIDEpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBzbGljZVRleHQudGV4dChwdC50ZXh0KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjbGFzcyc6ICdzbGljZXRleHQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogJycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZSdcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIHRleHRQb3NpdGlvbiA9PT0gJ291dHNpZGUnID9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgZGV0ZXJtaW5lT3V0c2lkZVRleHRGb250KHRyYWNlLCBwdCwgZ2QuX2Z1bGxMYXlvdXQuZm9udCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICBkZXRlcm1pbmVJbnNpZGVUZXh0Rm9udCh0cmFjZSwgcHQsIGdkLl9mdWxsTGF5b3V0LmZvbnQpKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhbGwoc3ZnVGV4dFV0aWxzLmNvbnZlcnRUb1RzcGFucywgZ2QpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHBvc2l0aW9uIHRoZSB0ZXh0IHJlbGF0aXZlIHRvIHRoZSBzbGljZVxuICAgICAgICAgICAgICAgICAgICB2YXIgdGV4dEJCID0gRHJhd2luZy5iQm94KHNsaWNlVGV4dC5ub2RlKCkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHJhbnNmb3JtO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKHRleHRQb3NpdGlvbiA9PT0gJ291dHNpZGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSB0cmFuc2Zvcm1PdXRzaWRlVGV4dCh0ZXh0QkIsIHB0KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9IHRyYW5zZm9ybUluc2lkZVRleHQodGV4dEJCLCBwdCwgY2QwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRleHRQb3NpdGlvbiA9PT0gJ2F1dG8nICYmIHRyYW5zZm9ybS5zY2FsZSA8IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbGljZVRleHQuY2FsbChEcmF3aW5nLmZvbnQsIHRyYWNlLm91dHNpZGV0ZXh0Zm9udCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYodHJhY2Uub3V0c2lkZXRleHRmb250LmZhbWlseSAhPT0gdHJhY2UuaW5zaWRldGV4dGZvbnQuZmFtaWx5IHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZS5vdXRzaWRldGV4dGZvbnQuc2l6ZSAhPT0gdHJhY2UuaW5zaWRldGV4dGZvbnQuc2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0QkIgPSBEcmF3aW5nLmJCb3goc2xpY2VUZXh0Lm5vZGUoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9IHRyYW5zZm9ybU91dHNpZGVUZXh0KHRleHRCQiwgcHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHRyYW5zbGF0ZVggPSBjeCArIHB0LnB4bWlkWzBdICogdHJhbnNmb3JtLnJDZW50ZXIgKyAodHJhbnNmb3JtLnggfHwgMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0cmFuc2xhdGVZID0gY3kgKyBwdC5weG1pZFsxXSAqIHRyYW5zZm9ybS5yQ2VudGVyICsgKHRyYW5zZm9ybS55IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHNhdmUgc29tZSBzdHVmZiB0byB1c2UgbGF0ZXIgZW5zdXJlIG5vIGxhYmVscyBvdmVybGFwXG4gICAgICAgICAgICAgICAgICAgIGlmKHRyYW5zZm9ybS5vdXRzaWRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdC55TGFiZWxNaW4gPSB0cmFuc2xhdGVZIC0gdGV4dEJCLmhlaWdodCAvIDI7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdC55TGFiZWxNaWQgPSB0cmFuc2xhdGVZO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHQueUxhYmVsTWF4ID0gdHJhbnNsYXRlWSArIHRleHRCQi5oZWlnaHQgLyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHQubGFiZWxFeHRyYVggPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHQubGFiZWxFeHRyYVkgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzT3V0c2lkZVRleHQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgc2xpY2VUZXh0LmF0dHIoJ3RyYW5zZm9ybScsXG4gICAgICAgICAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgKyB0cmFuc2xhdGVYICsgJywnICsgdHJhbnNsYXRlWSArICcpJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAodHJhbnNmb3JtLnNjYWxlIDwgMSA/ICgnc2NhbGUoJyArIHRyYW5zZm9ybS5zY2FsZSArICcpJykgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgKHRyYW5zZm9ybS5yb3RhdGUgPyAoJ3JvdGF0ZSgnICsgdHJhbnNmb3JtLnJvdGF0ZSArICcpJykgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoLSh0ZXh0QkIubGVmdCArIHRleHRCQi5yaWdodCkgLyAyKSArICcsJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKC0odGV4dEJCLnRvcCArIHRleHRCQi5ib3R0b20pIC8gMikgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJyknKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBhZGQgdGhlIHRpdGxlXG4gICAgICAgICAgICB2YXIgdGl0bGVUZXh0R3JvdXAgPSBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdnLnRpdGxldGV4dCcpXG4gICAgICAgICAgICAgICAgLmRhdGEodHJhY2UudGl0bGUudGV4dCA/IFswXSA6IFtdKTtcblxuICAgICAgICAgICAgdGl0bGVUZXh0R3JvdXAuZW50ZXIoKS5hcHBlbmQoJ2cnKVxuICAgICAgICAgICAgICAgIC5jbGFzc2VkKCd0aXRsZXRleHQnLCB0cnVlKTtcbiAgICAgICAgICAgIHRpdGxlVGV4dEdyb3VwLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgICAgICAgICAgdGl0bGVUZXh0R3JvdXAuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGl0bGVUZXh0ID0gTGliLmVuc3VyZVNpbmdsZShkMy5zZWxlY3QodGhpcyksICd0ZXh0JywgJycsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcHJvaGliaXQgdGV4IGludGVycHJldGF0aW9uIGFzIGFib3ZlXG4gICAgICAgICAgICAgICAgICAgIHMuYXR0cignZGF0YS1ub3RleCcsIDEpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIHR4dCA9IHRyYWNlLnRpdGxlLnRleHQ7XG4gICAgICAgICAgICAgICAgaWYodHJhY2UuX21ldGEpIHtcbiAgICAgICAgICAgICAgICAgICAgdHh0ID0gTGliLnRlbXBsYXRlU3RyaW5nKHR4dCwgdHJhY2UuX21ldGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRpdGxlVGV4dC50ZXh0KHR4dClcbiAgICAgICAgICAgICAgICAgICAgLmF0dHIoe1xuICAgICAgICAgICAgICAgICAgICAgICAgJ2NsYXNzJzogJ3RpdGxldGV4dCcsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ3RleHQtYW5jaG9yJzogJ21pZGRsZScsXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5mb250LCB0cmFjZS50aXRsZS5mb250KVxuICAgICAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKTtcblxuICAgICAgICAgICAgICAgIHZhciB0cmFuc2Zvcm07XG5cbiAgICAgICAgICAgICAgICBpZih0cmFjZS50aXRsZS5wb3NpdGlvbiA9PT0gJ21pZGRsZSBjZW50ZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybSA9IHBvc2l0aW9uVGl0bGVJbnNpZGUoY2QwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSBwb3NpdGlvblRpdGxlT3V0c2lkZShjZDAsIGZ1bGxMYXlvdXQuX3NpemUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRpdGxlVGV4dC5hdHRyKCd0cmFuc2Zvcm0nLFxuICAgICAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgKyB0cmFuc2Zvcm0ueCArICcsJyArIHRyYW5zZm9ybS55ICsgJyknICtcbiAgICAgICAgICAgICAgICAgICAgKHRyYW5zZm9ybS5zY2FsZSA8IDEgPyAoJ3NjYWxlKCcgKyB0cmFuc2Zvcm0uc2NhbGUgKyAnKScpIDogJycpICtcbiAgICAgICAgICAgICAgICAgICAgJ3RyYW5zbGF0ZSgnICsgdHJhbnNmb3JtLnR4ICsgJywnICsgdHJhbnNmb3JtLnR5ICsgJyknKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBub3cgbWFrZSBzdXJlIG5vIGxhYmVscyBvdmVybGFwIChhdCBsZWFzdCB3aXRoaW4gb25lIHBpZSlcbiAgICAgICAgICAgIGlmKGhhc091dHNpZGVUZXh0KSBzY29vdExhYmVscyhxdWFkcmFudHMsIHRyYWNlKTtcblxuICAgICAgICAgICAgcGxvdFRleHRMaW5lcyhzbGljZXMsIHRyYWNlKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBUaGlzIGlzIGZvciBhIGJ1ZyBpbiBDaHJvbWUgKGFzIG9mIDIwMTUtMDctMjIsIGFuZCBkb2VzIG5vdCBhZmZlY3QgRkYpXG4gICAgLy8gaWYgaW5zaWRldGV4dGZvbnQgYW5kIG91dHNpZGV0ZXh0Zm9udCBhcmUgZGlmZmVyZW50IHNpemVzLCBzb21ldGltZXMgdGhlIHNpemVcbiAgICAvLyBvZiBhbiBcImVtXCIgZ2V0cyB0YWtlbiBmcm9tIHRoZSB3cm9uZyBlbGVtZW50IGF0IGZpcnN0IHNvIGxpbmVzIGFyZVxuICAgIC8vIHNwYWNlZCB3cm9uZy4gWW91IGp1c3QgaGF2ZSB0byB0ZWxsIGl0IHRvIHRyeSBhZ2FpbiBsYXRlciBhbmQgaXQgZ2V0cyBmaXhlZC5cbiAgICAvLyBJIGhhdmUgbm8gaWRlYSB3aHkgd2UgaGF2ZW4ndCBzZWVuIHRoaXMgaW4gb3RoZXIgY29udGV4dHMuIEFsc28sIHNvbWV0aW1lc1xuICAgIC8vIGl0IGdldHMgdGhlIGluaXRpYWwgZHJhdyBjb3JyZWN0IGJ1dCBvbiByZWRyYXcgaXQgZ2V0cyBjb25mdXNlZC5cbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICBwbG90R3JvdXBzLnNlbGVjdEFsbCgndHNwYW4nKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHMgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICBpZihzLmF0dHIoJ2R5JykpIHMuYXR0cignZHknLCBzLmF0dHIoJ2R5JykpO1xuICAgICAgICB9KTtcbiAgICB9LCAwKTtcbn1cblxuLy8gVE9ETyBhZGQgc3VwcG9ydCBmb3IgdHJhbnNpdGlvblxuZnVuY3Rpb24gcGxvdFRleHRMaW5lcyhzbGljZXMsIHRyYWNlKSB7XG4gICAgc2xpY2VzLmVhY2goZnVuY3Rpb24ocHQpIHtcbiAgICAgICAgdmFyIHNsaWNlVG9wID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIGlmKCFwdC5sYWJlbEV4dHJhWCAmJiAhcHQubGFiZWxFeHRyYVkpIHtcbiAgICAgICAgICAgIHNsaWNlVG9wLnNlbGVjdCgncGF0aC50ZXh0bGluZScpLnJlbW92ZSgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmlyc3QgbW92ZSB0aGUgdGV4dCB0byBpdHMgbmV3IGxvY2F0aW9uXG4gICAgICAgIHZhciBzbGljZVRleHQgPSBzbGljZVRvcC5zZWxlY3QoJ2cuc2xpY2V0ZXh0IHRleHQnKTtcblxuICAgICAgICBzbGljZVRleHQuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgcHQubGFiZWxFeHRyYVggKyAnLCcgKyBwdC5sYWJlbEV4dHJhWSArICcpJyArXG4gICAgICAgICAgICBzbGljZVRleHQuYXR0cigndHJhbnNmb3JtJykpO1xuXG4gICAgICAgIC8vIHRoZW4gYWRkIGEgbGluZSB0byB0aGUgbmV3IGxvY2F0aW9uXG4gICAgICAgIHZhciBsaW5lU3RhcnRYID0gcHQuY3hGaW5hbCArIHB0LnB4bWlkWzBdO1xuICAgICAgICB2YXIgbGluZVN0YXJ0WSA9IHB0LmN5RmluYWwgKyBwdC5weG1pZFsxXTtcbiAgICAgICAgdmFyIHRleHRMaW5lUGF0aCA9ICdNJyArIGxpbmVTdGFydFggKyAnLCcgKyBsaW5lU3RhcnRZO1xuICAgICAgICB2YXIgZmluYWxYID0gKHB0LnlMYWJlbE1heCAtIHB0LnlMYWJlbE1pbikgKiAocHQucHhtaWRbMF0gPCAwID8gLTEgOiAxKSAvIDQ7XG5cbiAgICAgICAgaWYocHQubGFiZWxFeHRyYVgpIHtcbiAgICAgICAgICAgIHZhciB5RnJvbVggPSBwdC5sYWJlbEV4dHJhWCAqIHB0LnB4bWlkWzFdIC8gcHQucHhtaWRbMF07XG4gICAgICAgICAgICB2YXIgeU5ldCA9IHB0LnlMYWJlbE1pZCArIHB0LmxhYmVsRXh0cmFZIC0gKHB0LmN5RmluYWwgKyBwdC5weG1pZFsxXSk7XG5cbiAgICAgICAgICAgIGlmKE1hdGguYWJzKHlGcm9tWCkgPiBNYXRoLmFicyh5TmV0KSkge1xuICAgICAgICAgICAgICAgIHRleHRMaW5lUGF0aCArPVxuICAgICAgICAgICAgICAgICAgICAnbCcgKyAoeU5ldCAqIHB0LnB4bWlkWzBdIC8gcHQucHhtaWRbMV0pICsgJywnICsgeU5ldCArXG4gICAgICAgICAgICAgICAgICAgICdIJyArIChsaW5lU3RhcnRYICsgcHQubGFiZWxFeHRyYVggKyBmaW5hbFgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0ZXh0TGluZVBhdGggKz0gJ2wnICsgcHQubGFiZWxFeHRyYVggKyAnLCcgKyB5RnJvbVggK1xuICAgICAgICAgICAgICAgICAgICAndicgKyAoeU5ldCAtIHlGcm9tWCkgK1xuICAgICAgICAgICAgICAgICAgICAnaCcgKyBmaW5hbFg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0ZXh0TGluZVBhdGggKz1cbiAgICAgICAgICAgICAgICAnVicgKyAocHQueUxhYmVsTWlkICsgcHQubGFiZWxFeHRyYVkpICtcbiAgICAgICAgICAgICAgICAnaCcgKyBmaW5hbFg7XG4gICAgICAgIH1cblxuICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKHNsaWNlVG9wLCAncGF0aCcsICd0ZXh0bGluZScpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIHRyYWNlLm91dHNpZGV0ZXh0Zm9udC5jb2xvcilcbiAgICAgICAgICAgIC5hdHRyKHtcbiAgICAgICAgICAgICAgICAnc3Ryb2tlLXdpZHRoJzogTWF0aC5taW4oMiwgdHJhY2Uub3V0c2lkZXRleHRmb250LnNpemUgLyA4KSxcbiAgICAgICAgICAgICAgICBkOiB0ZXh0TGluZVBhdGgsXG4gICAgICAgICAgICAgICAgZmlsbDogJ25vbmUnXG4gICAgICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gYXR0YWNoRnhIYW5kbGVycyhzbGljZVRvcCwgZ2QsIGNkKSB7XG4gICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICB2YXIgY3ggPSBjZDAuY3g7XG4gICAgdmFyIGN5ID0gY2QwLmN5O1xuXG4gICAgLy8gaG92ZXIgc3RhdGUgdmFyc1xuICAgIC8vIGhhdmUgd2UgZHJhd24gYSBob3ZlciBsYWJlbCwgc28gaXQgc2hvdWxkIGJlIGNsZWFyZWQgbGF0ZXJcbiAgICBpZighKCdfaGFzSG92ZXJMYWJlbCcgaW4gdHJhY2UpKSB0cmFjZS5faGFzSG92ZXJMYWJlbCA9IGZhbHNlO1xuICAgIC8vIGhhdmUgd2UgZW1pdHRlZCBhIGhvdmVyIGV2ZW50LCBzbyBsYXRlciBhbiB1bmhvdmVyIGV2ZW50IHNob3VsZCBiZSBlbWl0dGVkXG4gICAgLy8gbm90ZSB0aGF0IGNsaWNrIGV2ZW50cyBkbyBub3QgZGVwZW5kIG9uIHRoaXMgLSB5b3UgY2FuIHN0aWxsIGdldCB0aGVtXG4gICAgLy8gd2l0aCBob3Zlcm1vZGU6IGZhbHNlIG9yIGlmIHlvdSB3ZXJlIGVhcmxpZXIgZHJhZ2dpbmcsIHRoZW4gY2xpY2tlZFxuICAgIC8vIGluIHRoZSBzYW1lIHNsaWNlIHRoYXQgeW91IG1vdXNlZCB1cCBpblxuICAgIGlmKCEoJ19oYXNIb3ZlckV2ZW50JyBpbiB0cmFjZSkpIHRyYWNlLl9oYXNIb3ZlckV2ZW50ID0gZmFsc2U7XG5cbiAgICBzbGljZVRvcC5vbignbW91c2VvdmVyJywgZnVuY3Rpb24ocHQpIHtcbiAgICAgICAgLy8gaW4gY2FzZSBmdWxsTGF5b3V0IG9yIGZ1bGxEYXRhIGhhcyBjaGFuZ2VkIHdpdGhvdXQgYSByZXBsb3RcbiAgICAgICAgdmFyIGZ1bGxMYXlvdXQyID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgIHZhciB0cmFjZTIgPSBnZC5fZnVsbERhdGFbdHJhY2UuaW5kZXhdO1xuXG4gICAgICAgIGlmKGdkLl9kcmFnZ2luZyB8fCBmdWxsTGF5b3V0Mi5ob3Zlcm1vZGUgPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICAgICAgdmFyIGhvdmVyaW5mbyA9IHRyYWNlMi5ob3ZlcmluZm87XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoaG92ZXJpbmZvKSkge1xuICAgICAgICAgICAgLy8gc3VwZXIgaGFja3k6IHdlIG5lZWQgdG8gcHVsbCBvdXQgdGhlICpmaXJzdCogaG92ZXJpbmZvIGZyb21cbiAgICAgICAgICAgIC8vIHB0LnB0cywgdGhlbiBwdXQgaXQgYmFjayBpbnRvIGFuIGFycmF5IGluIGEgZHVtbXkgdHJhY2VcbiAgICAgICAgICAgIC8vIGFuZCBjYWxsIGNhc3RIb3ZlcmluZm8gb24gdGhhdC5cbiAgICAgICAgICAgIC8vIFRPRE86IGRvIHdlIHdhbnQgdG8gaGF2ZSBGeC5jYXN0SG92ZXJpbmZvIHNvbWVob3cgaGFuZGxlIHRoaXM/XG4gICAgICAgICAgICAvLyBpdCBhbHJlYWR5IHRha2VzIGFuIGFycmF5IGZvciBpbmRleCwgZm9yIDJELCBzbyB0aGlzIHNlZW1zIHRyaWNreS5cbiAgICAgICAgICAgIGhvdmVyaW5mbyA9IEZ4LmNhc3RIb3ZlcmluZm8oe1xuICAgICAgICAgICAgICAgIGhvdmVyaW5mbzogW2hlbHBlcnMuY2FzdE9wdGlvbihob3ZlcmluZm8sIHB0LnB0cyldLFxuICAgICAgICAgICAgICAgIF9tb2R1bGU6IHRyYWNlLl9tb2R1bGVcbiAgICAgICAgICAgIH0sIGZ1bGxMYXlvdXQyLCAwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGhvdmVyaW5mbyA9PT0gJ2FsbCcpIGhvdmVyaW5mbyA9ICdsYWJlbCt0ZXh0K3ZhbHVlK3BlcmNlbnQrbmFtZSc7XG5cbiAgICAgICAgLy8gaW4gY2FzZSB3ZSBkcmFnZ2VkIG92ZXIgdGhlIHBpZSBmcm9tIGFub3RoZXIgc3VicGxvdCxcbiAgICAgICAgLy8gb3IgaWYgaG92ZXIgaXMgdHVybmVkIG9mZlxuICAgICAgICBpZih0cmFjZTIuaG92ZXJ0ZW1wbGF0ZSB8fCAoaG92ZXJpbmZvICE9PSAnbm9uZScgJiYgaG92ZXJpbmZvICE9PSAnc2tpcCcgJiYgaG92ZXJpbmZvKSkge1xuICAgICAgICAgICAgdmFyIHJJbnNjcmliZWQgPSBwdC5ySW5zY3JpYmVkIHx8IDA7XG4gICAgICAgICAgICB2YXIgaG92ZXJDZW50ZXJYID0gY3ggKyBwdC5weG1pZFswXSAqICgxIC0gckluc2NyaWJlZCk7XG4gICAgICAgICAgICB2YXIgaG92ZXJDZW50ZXJZID0gY3kgKyBwdC5weG1pZFsxXSAqICgxIC0gckluc2NyaWJlZCk7XG4gICAgICAgICAgICB2YXIgc2VwYXJhdG9ycyA9IGZ1bGxMYXlvdXQyLnNlcGFyYXRvcnM7XG4gICAgICAgICAgICB2YXIgdGV4dCA9IFtdO1xuXG4gICAgICAgICAgICBpZihob3ZlcmluZm8gJiYgaG92ZXJpbmZvLmluZGV4T2YoJ2xhYmVsJykgIT09IC0xKSB0ZXh0LnB1c2gocHQubGFiZWwpO1xuICAgICAgICAgICAgcHQudGV4dCA9IGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZTIuaG92ZXJ0ZXh0IHx8IHRyYWNlMi50ZXh0LCBwdC5wdHMpO1xuICAgICAgICAgICAgaWYoaG92ZXJpbmZvICYmIGhvdmVyaW5mby5pbmRleE9mKCd0ZXh0JykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR4ID0gcHQudGV4dDtcbiAgICAgICAgICAgICAgICBpZihMaWIuaXNWYWxpZFRleHRWYWx1ZSh0eCkpIHRleHQucHVzaCh0eCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwdC52YWx1ZSA9IHB0LnY7XG4gICAgICAgICAgICBwdC52YWx1ZUxhYmVsID0gaGVscGVycy5mb3JtYXRQaWVWYWx1ZShwdC52LCBzZXBhcmF0b3JzKTtcbiAgICAgICAgICAgIGlmKGhvdmVyaW5mbyAmJiBob3ZlcmluZm8uaW5kZXhPZigndmFsdWUnKSAhPT0gLTEpIHRleHQucHVzaChwdC52YWx1ZUxhYmVsKTtcbiAgICAgICAgICAgIHB0LnBlcmNlbnQgPSBwdC52IC8gY2QwLnZUb3RhbDtcbiAgICAgICAgICAgIHB0LnBlcmNlbnRMYWJlbCA9IGhlbHBlcnMuZm9ybWF0UGllUGVyY2VudChwdC5wZXJjZW50LCBzZXBhcmF0b3JzKTtcbiAgICAgICAgICAgIGlmKGhvdmVyaW5mbyAmJiBob3ZlcmluZm8uaW5kZXhPZigncGVyY2VudCcpICE9PSAtMSkgdGV4dC5wdXNoKHB0LnBlcmNlbnRMYWJlbCk7XG5cbiAgICAgICAgICAgIHZhciBob3ZlckxhYmVsID0gdHJhY2UyLmhvdmVybGFiZWw7XG4gICAgICAgICAgICB2YXIgaG92ZXJGb250ID0gaG92ZXJMYWJlbC5mb250O1xuXG4gICAgICAgICAgICBGeC5sb25lSG92ZXIoe1xuICAgICAgICAgICAgICAgIHRyYWNlOiB0cmFjZSxcbiAgICAgICAgICAgICAgICB4MDogaG92ZXJDZW50ZXJYIC0gckluc2NyaWJlZCAqIGNkMC5yLFxuICAgICAgICAgICAgICAgIHgxOiBob3ZlckNlbnRlclggKyBySW5zY3JpYmVkICogY2QwLnIsXG4gICAgICAgICAgICAgICAgeTogaG92ZXJDZW50ZXJZLFxuICAgICAgICAgICAgICAgIHRleHQ6IHRleHQuam9pbignPGJyPicpLFxuICAgICAgICAgICAgICAgIG5hbWU6ICh0cmFjZTIuaG92ZXJ0ZW1wbGF0ZSB8fCBob3ZlcmluZm8uaW5kZXhPZignbmFtZScpICE9PSAtMSkgPyB0cmFjZTIubmFtZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBpZGVhbEFsaWduOiBwdC5weG1pZFswXSA8IDAgPyAnbGVmdCcgOiAncmlnaHQnLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBoZWxwZXJzLmNhc3RPcHRpb24oaG92ZXJMYWJlbC5iZ2NvbG9yLCBwdC5wdHMpIHx8IHB0LmNvbG9yLFxuICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiBoZWxwZXJzLmNhc3RPcHRpb24oaG92ZXJMYWJlbC5ib3JkZXJjb2xvciwgcHQucHRzKSxcbiAgICAgICAgICAgICAgICBmb250RmFtaWx5OiBoZWxwZXJzLmNhc3RPcHRpb24oaG92ZXJGb250LmZhbWlseSwgcHQucHRzKSxcbiAgICAgICAgICAgICAgICBmb250U2l6ZTogaGVscGVycy5jYXN0T3B0aW9uKGhvdmVyRm9udC5zaXplLCBwdC5wdHMpLFxuICAgICAgICAgICAgICAgIGZvbnRDb2xvcjogaGVscGVycy5jYXN0T3B0aW9uKGhvdmVyRm9udC5jb2xvciwgcHQucHRzKSxcbiAgICAgICAgICAgICAgICBuYW1lTGVuZ3RoOiBoZWxwZXJzLmNhc3RPcHRpb24oaG92ZXJMYWJlbC5uYW1lbGVuZ3RoLCBwdC5wdHMpLFxuICAgICAgICAgICAgICAgIHRleHRBbGlnbjogaGVscGVycy5jYXN0T3B0aW9uKGhvdmVyTGFiZWwuYWxpZ24sIHB0LnB0cyksXG4gICAgICAgICAgICAgICAgaG92ZXJ0ZW1wbGF0ZTogaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlMi5ob3ZlcnRlbXBsYXRlLCBwdC5wdHMpLFxuICAgICAgICAgICAgICAgIGhvdmVydGVtcGxhdGVMYWJlbHM6IHB0LFxuICAgICAgICAgICAgICAgIGV2ZW50RGF0YTogW2V2ZW50RGF0YShwdCwgdHJhY2UyKV1cbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXI6IGZ1bGxMYXlvdXQyLl9ob3ZlcmxheWVyLm5vZGUoKSxcbiAgICAgICAgICAgICAgICBvdXRlckNvbnRhaW5lcjogZnVsbExheW91dDIuX3BhcGVyLm5vZGUoKSxcbiAgICAgICAgICAgICAgICBnZDogZ2RcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0cmFjZS5faGFzSG92ZXJMYWJlbCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB0cmFjZS5faGFzSG92ZXJFdmVudCA9IHRydWU7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9ob3ZlcicsIHtcbiAgICAgICAgICAgIHBvaW50czogW2V2ZW50RGF0YShwdCwgdHJhY2UyKV0sXG4gICAgICAgICAgICBldmVudDogZDMuZXZlbnRcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBzbGljZVRvcC5vbignbW91c2VvdXQnLCBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgdmFyIGZ1bGxMYXlvdXQyID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgIHZhciB0cmFjZTIgPSBnZC5fZnVsbERhdGFbdHJhY2UuaW5kZXhdO1xuICAgICAgICB2YXIgcHQgPSBkMy5zZWxlY3QodGhpcykuZGF0dW0oKTtcblxuICAgICAgICBpZih0cmFjZS5faGFzSG92ZXJFdmVudCkge1xuICAgICAgICAgICAgZXZ0Lm9yaWdpbmFsRXZlbnQgPSBkMy5ldmVudDtcbiAgICAgICAgICAgIGdkLmVtaXQoJ3Bsb3RseV91bmhvdmVyJywge1xuICAgICAgICAgICAgICAgIHBvaW50czogW2V2ZW50RGF0YShwdCwgdHJhY2UyKV0sXG4gICAgICAgICAgICAgICAgZXZlbnQ6IGQzLmV2ZW50XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRyYWNlLl9oYXNIb3ZlckV2ZW50ID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0cmFjZS5faGFzSG92ZXJMYWJlbCkge1xuICAgICAgICAgICAgRngubG9uZVVuaG92ZXIoZnVsbExheW91dDIuX2hvdmVybGF5ZXIubm9kZSgpKTtcbiAgICAgICAgICAgIHRyYWNlLl9oYXNIb3ZlckxhYmVsID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHNsaWNlVG9wLm9uKCdjbGljaycsIGZ1bmN0aW9uKHB0KSB7XG4gICAgICAgIC8vIFRPRE86IHRoaXMgZG9lcyBub3Qgc3VwcG9ydCByaWdodC1jbGljay4gSWYgd2Ugd2FudCB0byBzdXBwb3J0IGl0LCB3ZVxuICAgICAgICAvLyB3b3VsZCBsaWtlbHkgbmVlZCB0byBjaGFuZ2UgcGllIHRvIHVzZSBkcmFnRWxlbWVudCBpbnN0ZWFkIG9mIHN0cmFpZ2h0XG4gICAgICAgIC8vIG1hcGJveCBldmVudCBiaW5kaW5nLiBPciBwZXJoYXBzIGJldHRlciwgbWFrZSBhIHNpbXBsZSB3cmFwcGVyIHdpdGggdGhlXG4gICAgICAgIC8vIHJpZ2h0IG1vdXNlZG93biwgbW91c2Vtb3ZlLCBhbmQgbW91c2V1cCBoYW5kbGVycyBqdXN0IGZvciBhIGxlZnQvcmlnaHQgY2xpY2tcbiAgICAgICAgLy8gbWFwYm94IHdvdWxkIHVzZSB0aGlzIHRvby5cbiAgICAgICAgdmFyIGZ1bGxMYXlvdXQyID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgICAgIHZhciB0cmFjZTIgPSBnZC5fZnVsbERhdGFbdHJhY2UuaW5kZXhdO1xuXG4gICAgICAgIGlmKGdkLl9kcmFnZ2luZyB8fCBmdWxsTGF5b3V0Mi5ob3Zlcm1vZGUgPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICAgICAgZ2QuX2hvdmVyZGF0YSA9IFtldmVudERhdGEocHQsIHRyYWNlMildO1xuICAgICAgICBGeC5jbGljayhnZCwgZDMuZXZlbnQpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBkZXRlcm1pbmVPdXRzaWRlVGV4dEZvbnQodHJhY2UsIHB0LCBsYXlvdXRGb250KSB7XG4gICAgdmFyIGNvbG9yID1cbiAgICAgICAgaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLm91dHNpZGV0ZXh0Zm9udC5jb2xvciwgcHQucHRzKSB8fFxuICAgICAgICBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2UudGV4dGZvbnQuY29sb3IsIHB0LnB0cykgfHxcbiAgICAgICAgbGF5b3V0Rm9udC5jb2xvcjtcblxuICAgIHZhciBmYW1pbHkgPVxuICAgICAgICBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2Uub3V0c2lkZXRleHRmb250LmZhbWlseSwgcHQucHRzKSB8fFxuICAgICAgICBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2UudGV4dGZvbnQuZmFtaWx5LCBwdC5wdHMpIHx8XG4gICAgICAgIGxheW91dEZvbnQuZmFtaWx5O1xuXG4gICAgdmFyIHNpemUgPVxuICAgICAgICBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2Uub3V0c2lkZXRleHRmb250LnNpemUsIHB0LnB0cykgfHxcbiAgICAgICAgaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLnRleHRmb250LnNpemUsIHB0LnB0cykgfHxcbiAgICAgICAgbGF5b3V0Rm9udC5zaXplO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29sb3I6IGNvbG9yLFxuICAgICAgICBmYW1pbHk6IGZhbWlseSxcbiAgICAgICAgc2l6ZTogc2l6ZVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGRldGVybWluZUluc2lkZVRleHRGb250KHRyYWNlLCBwdCwgbGF5b3V0Rm9udCkge1xuICAgIHZhciBjdXN0b21Db2xvciA9IGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS5pbnNpZGV0ZXh0Zm9udC5jb2xvciwgcHQucHRzKTtcbiAgICBpZighY3VzdG9tQ29sb3IgJiYgdHJhY2UuX2lucHV0LnRleHRmb250KSB7XG4gICAgICAgIC8vIFdoeSBub3Qgc2ltcGx5IHVzaW5nIHRyYWNlLnRleHRmb250PyBCZWNhdXNlIGlmIG5vdCBzZXQsIGl0XG4gICAgICAgIC8vIGRlZmF1bHRzIHRvIGxheW91dC5mb250IHdoaWNoIGhhcyBhIGRlZmF1bHQgY29sb3IuIEJ1dCBpZlxuICAgICAgICAvLyB0ZXh0Zm9udC5jb2xvciBhbmQgaW5zaWRldGV4dGZvbnQuY29sb3IgZG9uJ3Qgc3VwcGx5IGEgdmFsdWUsXG4gICAgICAgIC8vIGEgY29udHJhc3RpbmcgY29sb3Igc2hhbGwgYmUgdXNlZC5cbiAgICAgICAgY3VzdG9tQ29sb3IgPSBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2UuX2lucHV0LnRleHRmb250LmNvbG9yLCBwdC5wdHMpO1xuICAgIH1cblxuICAgIHZhciBmYW1pbHkgPVxuICAgICAgICBoZWxwZXJzLmNhc3RPcHRpb24odHJhY2UuaW5zaWRldGV4dGZvbnQuZmFtaWx5LCBwdC5wdHMpIHx8XG4gICAgICAgIGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS50ZXh0Zm9udC5mYW1pbHksIHB0LnB0cykgfHxcbiAgICAgICAgbGF5b3V0Rm9udC5mYW1pbHk7XG5cbiAgICB2YXIgc2l6ZSA9XG4gICAgICAgIGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS5pbnNpZGV0ZXh0Zm9udC5zaXplLCBwdC5wdHMpIHx8XG4gICAgICAgIGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS50ZXh0Zm9udC5zaXplLCBwdC5wdHMpIHx8XG4gICAgICAgIGxheW91dEZvbnQuc2l6ZTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGNvbG9yOiBjdXN0b21Db2xvciB8fCBDb2xvci5jb250cmFzdChwdC5jb2xvciksXG4gICAgICAgIGZhbWlseTogZmFtaWx5LFxuICAgICAgICBzaXplOiBzaXplXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gcHJlcmVuZGVyVGl0bGVzKGNkTW9kdWxlLCBnZCkge1xuICAgIHZhciBjZDAsIHRyYWNlO1xuXG4gICAgLy8gRGV0ZXJtaW5lIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSB0aXRsZSBmb3IgZWFjaCBwaWUuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNkTW9kdWxlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNkMCA9IGNkTW9kdWxlW2ldWzBdO1xuICAgICAgICB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICBpZih0cmFjZS50aXRsZS50ZXh0KSB7XG4gICAgICAgICAgICB2YXIgdHh0ID0gdHJhY2UudGl0bGUudGV4dDtcbiAgICAgICAgICAgIGlmKHRyYWNlLl9tZXRhKSB7XG4gICAgICAgICAgICAgICAgdHh0ID0gTGliLnRlbXBsYXRlU3RyaW5nKHR4dCwgdHJhY2UuX21ldGEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZHVtbXlUaXRsZSA9IERyYXdpbmcudGVzdGVyLmFwcGVuZCgndGV4dCcpXG4gICAgICAgICAgICAgIC5hdHRyKCdkYXRhLW5vdGV4JywgMSlcbiAgICAgICAgICAgICAgLnRleHQodHh0KVxuICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIHRyYWNlLnRpdGxlLmZvbnQpXG4gICAgICAgICAgICAgIC5jYWxsKHN2Z1RleHRVdGlscy5jb252ZXJ0VG9Uc3BhbnMsIGdkKTtcbiAgICAgICAgICAgIHZhciBiQm94ID0gRHJhd2luZy5iQm94KGR1bW15VGl0bGUubm9kZSgpLCB0cnVlKTtcbiAgICAgICAgICAgIGNkMC50aXRsZUJveCA9IHtcbiAgICAgICAgICAgICAgICB3aWR0aDogYkJveC53aWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGJCb3guaGVpZ2h0LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGR1bW15VGl0bGUucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybUluc2lkZVRleHQodGV4dEJCLCBwdCwgY2QwKSB7XG4gICAgdmFyIHRleHREaWFtZXRlciA9IE1hdGguc3FydCh0ZXh0QkIud2lkdGggKiB0ZXh0QkIud2lkdGggKyB0ZXh0QkIuaGVpZ2h0ICogdGV4dEJCLmhlaWdodCk7XG4gICAgdmFyIHRleHRBc3BlY3QgPSB0ZXh0QkIud2lkdGggLyB0ZXh0QkIuaGVpZ2h0O1xuICAgIHZhciBoYWxmQW5nbGUgPSBwdC5oYWxmYW5nbGU7XG4gICAgdmFyIHJpbmcgPSBwdC5yaW5nO1xuICAgIHZhciBySW5zY3JpYmVkID0gcHQuckluc2NyaWJlZDtcbiAgICB2YXIgciA9IGNkMC5yIHx8IHB0LnJweDE7XG5cbiAgICAvLyBtYXggc2l6ZSB0ZXh0IGNhbiBiZSBpbnNlcnRlZCBpbnNpZGUgd2l0aG91dCByb3RhdGluZyBpdFxuICAgIC8vIHRoaXMgaW5zY3JpYmVzIHRoZSB0ZXh0IHJlY3RhbmdsZSBpbiBhIGNpcmNsZSwgd2hpY2ggaXMgdGhlbiBpbnNjcmliZWRcbiAgICAvLyBpbiB0aGUgc2xpY2UsIHNvIGl0IHdpbGwgYmUgYW4gdW5kZXJlc3RpbWF0ZSwgd2hpY2ggc29tZSBkYXkgd2UgbWF5IHdhbnRcbiAgICAvLyB0byBpbXByb3ZlIHNvIHRoaXMgY2FzZSBjYW4gZ2V0IG1vcmUgdXNlXG4gICAgdmFyIHRyYW5zZm9ybSA9IHtcbiAgICAgICAgc2NhbGU6IHJJbnNjcmliZWQgKiByICogMiAvIHRleHREaWFtZXRlcixcblxuICAgICAgICAvLyBhbmQgdGhlIGNlbnRlciBwb3NpdGlvbiBhbmQgcm90YXRpb24gaW4gdGhpcyBjYXNlXG4gICAgICAgIHJDZW50ZXI6IDEgLSBySW5zY3JpYmVkLFxuICAgICAgICByb3RhdGU6IDBcbiAgICB9O1xuXG4gICAgaWYodHJhbnNmb3JtLnNjYWxlID49IDEpIHJldHVybiB0cmFuc2Zvcm07XG5cbiAgICAvLyBtYXggc2l6ZSBpZiB0ZXh0IGlzIHJvdGF0ZWQgcmFkaWFsbHlcbiAgICB2YXIgUXIgPSB0ZXh0QXNwZWN0ICsgMSAvICgyICogTWF0aC50YW4oaGFsZkFuZ2xlKSk7XG4gICAgdmFyIG1heEhhbGZIZWlnaHRSb3RSYWRpYWwgPSByICogTWF0aC5taW4oXG4gICAgICAgIDEgLyAoTWF0aC5zcXJ0KFFyICogUXIgKyAwLjUpICsgUXIpLFxuICAgICAgICByaW5nIC8gKE1hdGguc3FydCh0ZXh0QXNwZWN0ICogdGV4dEFzcGVjdCArIHJpbmcgLyAyKSArIHRleHRBc3BlY3QpXG4gICAgKTtcbiAgICB2YXIgcmFkaWFsVHJhbnNmb3JtID0ge1xuICAgICAgICBzY2FsZTogbWF4SGFsZkhlaWdodFJvdFJhZGlhbCAqIDIgLyB0ZXh0QkIuaGVpZ2h0LFxuICAgICAgICByQ2VudGVyOiBNYXRoLmNvcyhtYXhIYWxmSGVpZ2h0Um90UmFkaWFsIC8gcikgLVxuICAgICAgICAgICAgbWF4SGFsZkhlaWdodFJvdFJhZGlhbCAqIHRleHRBc3BlY3QgLyByLFxuICAgICAgICByb3RhdGU6ICgxODAgLyBNYXRoLlBJICogcHQubWlkYW5nbGUgKyA3MjApICUgMTgwIC0gOTBcbiAgICB9O1xuXG4gICAgLy8gbWF4IHNpemUgaWYgdGV4dCBpcyByb3RhdGVkIHRhbmdlbnRpYWxseVxuICAgIHZhciBhc3BlY3RJbnYgPSAxIC8gdGV4dEFzcGVjdDtcbiAgICB2YXIgUXQgPSBhc3BlY3RJbnYgKyAxIC8gKDIgKiBNYXRoLnRhbihoYWxmQW5nbGUpKTtcbiAgICB2YXIgbWF4SGFsZldpZHRoVGFuZ2VudGlhbCA9IHIgKiBNYXRoLm1pbihcbiAgICAgICAgMSAvIChNYXRoLnNxcnQoUXQgKiBRdCArIDAuNSkgKyBRdCksXG4gICAgICAgIHJpbmcgLyAoTWF0aC5zcXJ0KGFzcGVjdEludiAqIGFzcGVjdEludiArIHJpbmcgLyAyKSArIGFzcGVjdEludilcbiAgICApO1xuICAgIHZhciB0YW5nZW50aWFsVHJhbnNmb3JtID0ge1xuICAgICAgICBzY2FsZTogbWF4SGFsZldpZHRoVGFuZ2VudGlhbCAqIDIgLyB0ZXh0QkIud2lkdGgsXG4gICAgICAgIHJDZW50ZXI6IE1hdGguY29zKG1heEhhbGZXaWR0aFRhbmdlbnRpYWwgLyByKSAtXG4gICAgICAgICAgICBtYXhIYWxmV2lkdGhUYW5nZW50aWFsIC8gdGV4dEFzcGVjdCAvIHIsXG4gICAgICAgIHJvdGF0ZTogKDE4MCAvIE1hdGguUEkgKiBwdC5taWRhbmdsZSArIDgxMCkgJSAxODAgLSA5MFxuICAgIH07XG4gICAgLy8gaWYgd2UgbmVlZCBhIHJvdGF0ZWQgdHJhbnNmb3JtLCBwaWNrIHRoZSBiaWdnZXN0IG9uZVxuICAgIC8vIGV2ZW4gaWYgYm90aCBhcmUgYmlnZ2VyIHRoYW4gMVxuICAgIHZhciByb3RhdGVkVHJhbnNmb3JtID0gdGFuZ2VudGlhbFRyYW5zZm9ybS5zY2FsZSA+IHJhZGlhbFRyYW5zZm9ybS5zY2FsZSA/XG4gICAgICAgICAgICB0YW5nZW50aWFsVHJhbnNmb3JtIDogcmFkaWFsVHJhbnNmb3JtO1xuXG4gICAgaWYodHJhbnNmb3JtLnNjYWxlIDwgMSAmJiByb3RhdGVkVHJhbnNmb3JtLnNjYWxlID4gdHJhbnNmb3JtLnNjYWxlKSByZXR1cm4gcm90YXRlZFRyYW5zZm9ybTtcbiAgICByZXR1cm4gdHJhbnNmb3JtO1xufVxuXG5mdW5jdGlvbiBnZXRJbnNjcmliZWRSYWRpdXNGcmFjdGlvbihwdCwgY2QwKSB7XG4gICAgaWYocHQudiA9PT0gY2QwLnZUb3RhbCAmJiAhY2QwLnRyYWNlLmhvbGUpIHJldHVybiAxOy8vIHNwZWNpYWwgY2FzZSBvZiAxMDAlIHdpdGggbm8gaG9sZVxuXG4gICAgcmV0dXJuIE1hdGgubWluKDEgLyAoMSArIDEgLyBNYXRoLnNpbihwdC5oYWxmYW5nbGUpKSwgcHQucmluZyAvIDIpO1xufVxuXG5mdW5jdGlvbiB0cmFuc2Zvcm1PdXRzaWRlVGV4dCh0ZXh0QkIsIHB0KSB7XG4gICAgdmFyIHggPSBwdC5weG1pZFswXTtcbiAgICB2YXIgeSA9IHB0LnB4bWlkWzFdO1xuICAgIHZhciBkeCA9IHRleHRCQi53aWR0aCAvIDI7XG4gICAgdmFyIGR5ID0gdGV4dEJCLmhlaWdodCAvIDI7XG5cbiAgICBpZih4IDwgMCkgZHggKj0gLTE7XG4gICAgaWYoeSA8IDApIGR5ICo9IC0xO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgc2NhbGU6IDEsXG4gICAgICAgIHJDZW50ZXI6IDEsXG4gICAgICAgIHJvdGF0ZTogMCxcbiAgICAgICAgeDogZHggKyBNYXRoLmFicyhkeSkgKiAoZHggPiAwID8gMSA6IC0xKSAvIDIsXG4gICAgICAgIHk6IGR5IC8gKDEgKyB4ICogeCAvICh5ICogeSkpLFxuICAgICAgICBvdXRzaWRlOiB0cnVlXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gcG9zaXRpb25UaXRsZUluc2lkZShjZDApIHtcbiAgICB2YXIgdGV4dERpYW1ldGVyID1cbiAgICAgICAgTWF0aC5zcXJ0KGNkMC50aXRsZUJveC53aWR0aCAqIGNkMC50aXRsZUJveC53aWR0aCArIGNkMC50aXRsZUJveC5oZWlnaHQgKiBjZDAudGl0bGVCb3guaGVpZ2h0KTtcbiAgICByZXR1cm4ge1xuICAgICAgICB4OiBjZDAuY3gsXG4gICAgICAgIHk6IGNkMC5jeSxcbiAgICAgICAgc2NhbGU6IGNkMC50cmFjZS5ob2xlICogY2QwLnIgKiAyIC8gdGV4dERpYW1ldGVyLFxuICAgICAgICB0eDogMCxcbiAgICAgICAgdHk6IC0gY2QwLnRpdGxlQm94LmhlaWdodCAvIDIgKyBjZDAudHJhY2UudGl0bGUuZm9udC5zaXplXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gcG9zaXRpb25UaXRsZU91dHNpZGUoY2QwLCBwbG90U2l6ZSkge1xuICAgIHZhciBzY2FsZVggPSAxO1xuICAgIHZhciBzY2FsZVkgPSAxO1xuICAgIHZhciBtYXhQdWxsO1xuXG4gICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgIC8vIHBvc2l0aW9uIG9mIHRoZSBiYXNlbGluZSBwb2ludCBvZiB0aGUgdGV4dCBib3ggaW4gdGhlIHBsb3QsIGJlZm9yZSBzY2FsaW5nLlxuICAgIC8vIHdlIGFuY2hvcmVkIHRoZSB0ZXh0IGluIHRoZSBtaWRkbGUsIHNvIHRoZSBiYXNlbGluZSBpcyBvbiB0aGUgYm90dG9tIG1pZGRsZVxuICAgIC8vIG9mIHRoZSBmaXJzdCBsaW5lIG9mIHRleHQuXG4gICAgdmFyIHRvcE1pZGRsZSA9IHtcbiAgICAgICAgeDogY2QwLmN4LFxuICAgICAgICB5OiBjZDAuY3lcbiAgICB9O1xuICAgIC8vIHJlbGF0aXZlIHRyYW5zbGF0aW9uIG9mIHRoZSB0ZXh0IGJveCBhZnRlciBzY2FsaW5nXG4gICAgdmFyIHRyYW5zbGF0ZSA9IHtcbiAgICAgICAgdHg6IDAsXG4gICAgICAgIHR5OiAwXG4gICAgfTtcblxuICAgIC8vIHdlIHJlYXNvbiBiZWxvdyBhcyBpZiB0aGUgYmFzZWxpbmUgaXMgdGhlIHRvcCBtaWRkbGUgcG9pbnQgb2YgdGhlIHRleHQgYm94LlxuICAgIC8vIHNvIHdlIG11c3QgYWRkIHRoZSBmb250IHNpemUgdG8gYXBwcm94aW1hdGUgdGhlIHktY29vcmQuIG9mIHRoZSB0b3AuXG4gICAgLy8gbm90ZSB0aGF0IHRoaXMgY29ycmVjdGlvbiBtdXN0IGhhcHBlbiBhZnRlciBzY2FsaW5nLlxuICAgIHRyYW5zbGF0ZS50eSArPSB0cmFjZS50aXRsZS5mb250LnNpemU7XG4gICAgbWF4UHVsbCA9IGdldE1heFB1bGwodHJhY2UpO1xuXG4gICAgaWYodHJhY2UudGl0bGUucG9zaXRpb24uaW5kZXhPZigndG9wJykgIT09IC0xKSB7XG4gICAgICAgIHRvcE1pZGRsZS55IC09ICgxICsgbWF4UHVsbCkgKiBjZDAucjtcbiAgICAgICAgdHJhbnNsYXRlLnR5IC09IGNkMC50aXRsZUJveC5oZWlnaHQ7XG4gICAgfSBlbHNlIGlmKHRyYWNlLnRpdGxlLnBvc2l0aW9uLmluZGV4T2YoJ2JvdHRvbScpICE9PSAtMSkge1xuICAgICAgICB0b3BNaWRkbGUueSArPSAoMSArIG1heFB1bGwpICogY2QwLnI7XG4gICAgfVxuXG4gICAgdmFyIHJ4ID0gYXBwbHlBc3BlY3RSYXRpbyhjZDAuciwgY2QwLnRyYWNlLmFzcGVjdHJhdGlvKTtcblxuICAgIHZhciBtYXhXaWR0aCA9IHBsb3RTaXplLncgKiAodHJhY2UuZG9tYWluLnhbMV0gLSB0cmFjZS5kb21haW4ueFswXSkgLyAyO1xuICAgIGlmKHRyYWNlLnRpdGxlLnBvc2l0aW9uLmluZGV4T2YoJ2xlZnQnKSAhPT0gLTEpIHtcbiAgICAgICAgLy8gd2Ugc3RhcnQgdGhlIHRleHQgYXQgdGhlIGxlZnQgZWRnZSBvZiB0aGUgcGllXG4gICAgICAgIG1heFdpZHRoID0gbWF4V2lkdGggKyByeDtcbiAgICAgICAgdG9wTWlkZGxlLnggLT0gKDEgKyBtYXhQdWxsKSAqIHJ4O1xuICAgICAgICB0cmFuc2xhdGUudHggKz0gY2QwLnRpdGxlQm94LndpZHRoIC8gMjtcbiAgICB9IGVsc2UgaWYodHJhY2UudGl0bGUucG9zaXRpb24uaW5kZXhPZignY2VudGVyJykgIT09IC0xKSB7XG4gICAgICAgIG1heFdpZHRoICo9IDI7XG4gICAgfSBlbHNlIGlmKHRyYWNlLnRpdGxlLnBvc2l0aW9uLmluZGV4T2YoJ3JpZ2h0JykgIT09IC0xKSB7XG4gICAgICAgIG1heFdpZHRoID0gbWF4V2lkdGggKyByeDtcbiAgICAgICAgdG9wTWlkZGxlLnggKz0gKDEgKyBtYXhQdWxsKSAqIHJ4O1xuICAgICAgICB0cmFuc2xhdGUudHggLT0gY2QwLnRpdGxlQm94LndpZHRoIC8gMjtcbiAgICB9XG4gICAgc2NhbGVYID0gbWF4V2lkdGggLyBjZDAudGl0bGVCb3gud2lkdGg7XG4gICAgc2NhbGVZID0gZ2V0VGl0bGVTcGFjZShjZDAsIHBsb3RTaXplKSAvIGNkMC50aXRsZUJveC5oZWlnaHQ7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgeDogdG9wTWlkZGxlLngsXG4gICAgICAgIHk6IHRvcE1pZGRsZS55LFxuICAgICAgICBzY2FsZTogTWF0aC5taW4oc2NhbGVYLCBzY2FsZVkpLFxuICAgICAgICB0eDogdHJhbnNsYXRlLnR4LFxuICAgICAgICB0eTogdHJhbnNsYXRlLnR5XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gYXBwbHlBc3BlY3RSYXRpbyh4LCBhc3BlY3RyYXRpbykge1xuICAgIHJldHVybiB4IC8gKChhc3BlY3RyYXRpbyA9PT0gdW5kZWZpbmVkKSA/IDEgOiBhc3BlY3RyYXRpbyk7XG59XG5cbmZ1bmN0aW9uIGdldFRpdGxlU3BhY2UoY2QwLCBwbG90U2l6ZSkge1xuICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICB2YXIgcGllQm94SGVpZ2h0ID0gcGxvdFNpemUuaCAqICh0cmFjZS5kb21haW4ueVsxXSAtIHRyYWNlLmRvbWFpbi55WzBdKTtcbiAgICAvLyB1c2UgYXQgbW9zdCBoYWxmIG9mIHRoZSBwbG90IGZvciB0aGUgdGl0bGVcbiAgICByZXR1cm4gTWF0aC5taW4oY2QwLnRpdGxlQm94LmhlaWdodCwgcGllQm94SGVpZ2h0IC8gMik7XG59XG5cbmZ1bmN0aW9uIGdldE1heFB1bGwodHJhY2UpIHtcbiAgICB2YXIgbWF4UHVsbCA9IHRyYWNlLnB1bGw7XG4gICAgaWYoIW1heFB1bGwpIHJldHVybiAwO1xuXG4gICAgdmFyIGo7XG4gICAgaWYoQXJyYXkuaXNBcnJheShtYXhQdWxsKSkge1xuICAgICAgICBtYXhQdWxsID0gMDtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgdHJhY2UucHVsbC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgaWYodHJhY2UucHVsbFtqXSA+IG1heFB1bGwpIG1heFB1bGwgPSB0cmFjZS5wdWxsW2pdO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBtYXhQdWxsO1xufVxuXG5mdW5jdGlvbiBzY29vdExhYmVscyhxdWFkcmFudHMsIHRyYWNlKSB7XG4gICAgdmFyIHhIYWxmLCB5SGFsZiwgZXF1YXRvckZpcnN0LCBmYXJ0aGVzdFgsIGZhcnRoZXN0WSxcbiAgICAgICAgeERpZmZTaWduLCB5RGlmZlNpZ24sIHRoaXNRdWFkLCBvcHBvc2l0ZVF1YWQsXG4gICAgICAgIHdob2xlU2lkZSwgaSwgdGhpc1F1YWRPdXRzaWRlLCBmaXJzdE9wcG9zaXRlT3V0c2lkZVB0O1xuXG4gICAgZnVuY3Rpb24gdG9wRmlyc3QoYSwgYikgeyByZXR1cm4gYS5weG1pZFsxXSAtIGIucHhtaWRbMV07IH1cbiAgICBmdW5jdGlvbiBib3R0b21GaXJzdChhLCBiKSB7IHJldHVybiBiLnB4bWlkWzFdIC0gYS5weG1pZFsxXTsgfVxuXG4gICAgZnVuY3Rpb24gc2Nvb3RPbmVMYWJlbCh0aGlzUHQsIHByZXZQdCkge1xuICAgICAgICBpZighcHJldlB0KSBwcmV2UHQgPSB7fTtcblxuICAgICAgICB2YXIgcHJldk91dGVyWSA9IHByZXZQdC5sYWJlbEV4dHJhWSArICh5SGFsZiA/IHByZXZQdC55TGFiZWxNYXggOiBwcmV2UHQueUxhYmVsTWluKTtcbiAgICAgICAgdmFyIHRoaXNJbm5lclkgPSB5SGFsZiA/IHRoaXNQdC55TGFiZWxNaW4gOiB0aGlzUHQueUxhYmVsTWF4O1xuICAgICAgICB2YXIgdGhpc091dGVyWSA9IHlIYWxmID8gdGhpc1B0LnlMYWJlbE1heCA6IHRoaXNQdC55TGFiZWxNaW47XG4gICAgICAgIHZhciB0aGlzU2xpY2VPdXRlclkgPSB0aGlzUHQuY3lGaW5hbCArIGZhcnRoZXN0WSh0aGlzUHQucHgwWzFdLCB0aGlzUHQucHgxWzFdKTtcbiAgICAgICAgdmFyIG5ld0V4dHJhWSA9IHByZXZPdXRlclkgLSB0aGlzSW5uZXJZO1xuXG4gICAgICAgIHZhciB4QnVmZmVyLCBpLCBvdGhlclB0LCBvdGhlck91dGVyWSwgb3RoZXJPdXRlclgsIG5ld0V4dHJhWDtcblxuICAgICAgICAvLyBtYWtlIHN1cmUgdGhpcyBsYWJlbCBkb2Vzbid0IG92ZXJsYXAgb3RoZXIgbGFiZWxzXG4gICAgICAgIC8vIHRoaXMgKm9ubHkqIGhhcyB1cyBtb3ZlIHRoZXNlIGxhYmVscyB2ZXJ0aWNhbGx5XG4gICAgICAgIGlmKG5ld0V4dHJhWSAqIHlEaWZmU2lnbiA+IDApIHRoaXNQdC5sYWJlbEV4dHJhWSA9IG5ld0V4dHJhWTtcblxuICAgICAgICAvLyBtYWtlIHN1cmUgdGhpcyBsYWJlbCBkb2Vzbid0IG92ZXJsYXAgYW55IHNsaWNlc1xuICAgICAgICBpZighQXJyYXkuaXNBcnJheSh0cmFjZS5wdWxsKSkgcmV0dXJuOyAvLyB0aGlzIGNhbiBvbmx5IGhhcHBlbiB3aXRoIGFycmF5IHB1bGxzXG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgd2hvbGVTaWRlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBvdGhlclB0ID0gd2hvbGVTaWRlW2ldO1xuXG4gICAgICAgICAgICAvLyBvdmVybGFwIGNhbiBvbmx5IGhhcHBlbiBpZiB0aGUgb3RoZXIgcG9pbnQgaXMgcHVsbGVkIG1vcmUgdGhhbiB0aGlzIG9uZVxuICAgICAgICAgICAgaWYob3RoZXJQdCA9PT0gdGhpc1B0IHx8IChcbiAgICAgICAgICAgICAgICAoaGVscGVycy5jYXN0T3B0aW9uKHRyYWNlLnB1bGwsIHRoaXNQdC5wdHMpIHx8IDApID49XG4gICAgICAgICAgICAgICAgKGhlbHBlcnMuY2FzdE9wdGlvbih0cmFjZS5wdWxsLCBvdGhlclB0LnB0cykgfHwgMCkpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoKHRoaXNQdC5weG1pZFsxXSAtIG90aGVyUHQucHhtaWRbMV0pICogeURpZmZTaWduID4gMCkge1xuICAgICAgICAgICAgICAgIC8vIGNsb3NlciB0byB0aGUgZXF1YXRvciAtIGJ5IGNvbnN0cnVjdGlvbiBhbGwgb2YgdGhlc2UgaGFwcGVuIGZpcnN0XG4gICAgICAgICAgICAgICAgLy8gbW92ZSB0aGUgdGV4dCB2ZXJ0aWNhbGx5IHRvIGdldCBhd2F5IGZyb20gdGhlc2Ugc2xpY2VzXG4gICAgICAgICAgICAgICAgb3RoZXJPdXRlclkgPSBvdGhlclB0LmN5RmluYWwgKyBmYXJ0aGVzdFkob3RoZXJQdC5weDBbMV0sIG90aGVyUHQucHgxWzFdKTtcbiAgICAgICAgICAgICAgICBuZXdFeHRyYVkgPSBvdGhlck91dGVyWSAtIHRoaXNJbm5lclkgLSB0aGlzUHQubGFiZWxFeHRyYVk7XG5cbiAgICAgICAgICAgICAgICBpZihuZXdFeHRyYVkgKiB5RGlmZlNpZ24gPiAwKSB0aGlzUHQubGFiZWxFeHRyYVkgKz0gbmV3RXh0cmFZO1xuICAgICAgICAgICAgfSBlbHNlIGlmKCh0aGlzT3V0ZXJZICsgdGhpc1B0LmxhYmVsRXh0cmFZIC0gdGhpc1NsaWNlT3V0ZXJZKSAqIHlEaWZmU2lnbiA+IDApIHtcbiAgICAgICAgICAgICAgICAvLyBmYXJ0aGVyIGZyb20gdGhlIGVxdWF0b3IgLSBoYXBwZW5zIGFmdGVyIHdlJ3ZlIGRvbmUgYWxsIHRoZVxuICAgICAgICAgICAgICAgIC8vIHZlcnRpY2FsIG1vdmluZyB3ZSdyZSBnb2luZyB0byBkb1xuICAgICAgICAgICAgICAgIC8vIG1vdmUgaG9yaXpvbnRhbGx5IHRvIGdldCBhd2F5IGZyb20gdGhlc2UgbW9yZSBwb2xhciBzbGljZXNcblxuICAgICAgICAgICAgICAgIC8vIGlmIHdlJ3JlIG1vdmluZyBob3J6LiBiYXNlZCBvbiBhIHNsaWNlIHRoYXQncyBzZXZlcmFsIHNsaWNlcyBhd2F5IGZyb20gdGhpcyBvbmVcbiAgICAgICAgICAgICAgICAvLyB0aGVuIHdlIG5lZWQgc29tZSBleHRyYSBzcGFjZSBmb3IgdGhlIGxpbmVzIHRvIGxhYmVscyBiZXR3ZWVuIHRoZW1cbiAgICAgICAgICAgICAgICB4QnVmZmVyID0gMyAqIHhEaWZmU2lnbiAqIE1hdGguYWJzKGkgLSB3aG9sZVNpZGUuaW5kZXhPZih0aGlzUHQpKTtcblxuICAgICAgICAgICAgICAgIG90aGVyT3V0ZXJYID0gb3RoZXJQdC5jeEZpbmFsICsgZmFydGhlc3RYKG90aGVyUHQucHgwWzBdLCBvdGhlclB0LnB4MVswXSk7XG4gICAgICAgICAgICAgICAgbmV3RXh0cmFYID0gb3RoZXJPdXRlclggKyB4QnVmZmVyIC0gKHRoaXNQdC5jeEZpbmFsICsgdGhpc1B0LnB4bWlkWzBdKSAtIHRoaXNQdC5sYWJlbEV4dHJhWDtcblxuICAgICAgICAgICAgICAgIGlmKG5ld0V4dHJhWCAqIHhEaWZmU2lnbiA+IDApIHRoaXNQdC5sYWJlbEV4dHJhWCArPSBuZXdFeHRyYVg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoeUhhbGYgPSAwOyB5SGFsZiA8IDI7IHlIYWxmKyspIHtcbiAgICAgICAgZXF1YXRvckZpcnN0ID0geUhhbGYgPyB0b3BGaXJzdCA6IGJvdHRvbUZpcnN0O1xuICAgICAgICBmYXJ0aGVzdFkgPSB5SGFsZiA/IE1hdGgubWF4IDogTWF0aC5taW47XG4gICAgICAgIHlEaWZmU2lnbiA9IHlIYWxmID8gMSA6IC0xO1xuXG4gICAgICAgIGZvcih4SGFsZiA9IDA7IHhIYWxmIDwgMjsgeEhhbGYrKykge1xuICAgICAgICAgICAgZmFydGhlc3RYID0geEhhbGYgPyBNYXRoLm1heCA6IE1hdGgubWluO1xuICAgICAgICAgICAgeERpZmZTaWduID0geEhhbGYgPyAxIDogLTE7XG5cbiAgICAgICAgICAgIC8vIGZpcnN0IHNvcnQgdGhlIGFycmF5XG4gICAgICAgICAgICAvLyBub3RlIHRoaXMgaXMgYSBjb3B5IG9mIGNkLCBzbyBjZCBpdHNlbGYgZG9lc24ndCBnZXQgc29ydGVkXG4gICAgICAgICAgICAvLyBidXQgd2UgY2FuIHN0aWxsIG1vZGlmeSBwb2ludHMgaW4gcGxhY2UuXG4gICAgICAgICAgICB0aGlzUXVhZCA9IHF1YWRyYW50c1t5SGFsZl1beEhhbGZdO1xuICAgICAgICAgICAgdGhpc1F1YWQuc29ydChlcXVhdG9yRmlyc3QpO1xuXG4gICAgICAgICAgICBvcHBvc2l0ZVF1YWQgPSBxdWFkcmFudHNbMSAtIHlIYWxmXVt4SGFsZl07XG4gICAgICAgICAgICB3aG9sZVNpZGUgPSBvcHBvc2l0ZVF1YWQuY29uY2F0KHRoaXNRdWFkKTtcblxuICAgICAgICAgICAgdGhpc1F1YWRPdXRzaWRlID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCB0aGlzUXVhZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKHRoaXNRdWFkW2ldLnlMYWJlbE1pZCAhPT0gdW5kZWZpbmVkKSB0aGlzUXVhZE91dHNpZGUucHVzaCh0aGlzUXVhZFtpXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZpcnN0T3Bwb3NpdGVPdXRzaWRlUHQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgeUhhbGYgJiYgaSA8IG9wcG9zaXRlUXVhZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKG9wcG9zaXRlUXVhZFtpXS55TGFiZWxNaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdE9wcG9zaXRlT3V0c2lkZVB0ID0gb3Bwb3NpdGVRdWFkW2ldO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGVhY2ggbmVlZHMgdG8gYXZvaWQgdGhlIHByZXZpb3VzXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCB0aGlzUXVhZE91dHNpZGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldlB0ID0gaSAmJiB0aGlzUXVhZE91dHNpZGVbaSAtIDFdO1xuICAgICAgICAgICAgICAgIC8vIGJvdHRvbSBoYWxmIG5lZWRzIHRvIGF2b2lkIHRoZSBmaXJzdCBsYWJlbCBvZiB0aGUgdG9wIGhhbGZcbiAgICAgICAgICAgICAgICAvLyB0b3AgaGFsZiB3ZSBzdGlsbCBuZWVkIHRvIGNhbGwgc2Nvb3RPbmVMYWJlbCBvbiB0aGUgZmlyc3Qgc2xpY2VcbiAgICAgICAgICAgICAgICAvLyBzbyB3ZSBjYW4gYXZvaWQgb3RoZXIgc2xpY2VzLCBidXQgd2UgZG9uJ3QgcGFzcyBhIHByZXZQdFxuICAgICAgICAgICAgICAgIGlmKGZpcnN0T3Bwb3NpdGVPdXRzaWRlUHQgJiYgIWkpIHByZXZQdCA9IGZpcnN0T3Bwb3NpdGVPdXRzaWRlUHQ7XG4gICAgICAgICAgICAgICAgc2Nvb3RPbmVMYWJlbCh0aGlzUXVhZE91dHNpZGVbaV0sIHByZXZQdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGxheW91dEFyZWFzKGNkTW9kdWxlLCBwbG90U2l6ZSkge1xuICAgIHZhciBzY2FsZUdyb3VwcyA9IFtdO1xuXG4gICAgLy8gZmlndXJlIG91dCB0aGUgY2VudGVyIGFuZCBtYXhpbXVtIHJhZGl1c1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjZE1vZHVsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2QwID0gY2RNb2R1bGVbaV1bMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICB2YXIgZG9tYWluID0gdHJhY2UuZG9tYWluO1xuICAgICAgICB2YXIgd2lkdGggPSBwbG90U2l6ZS53ICogKGRvbWFpbi54WzFdIC0gZG9tYWluLnhbMF0pO1xuICAgICAgICB2YXIgaGVpZ2h0ID0gcGxvdFNpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKTtcbiAgICAgICAgLy8gbGVhdmUgc29tZSBzcGFjZSBmb3IgdGhlIHRpdGxlLCBpZiBpdCB3aWxsIGJlIGRpc3BsYXllZCBvdXRzaWRlXG4gICAgICAgIGlmKHRyYWNlLnRpdGxlLnRleHQgJiYgdHJhY2UudGl0bGUucG9zaXRpb24gIT09ICdtaWRkbGUgY2VudGVyJykge1xuICAgICAgICAgICAgaGVpZ2h0IC09IGdldFRpdGxlU3BhY2UoY2QwLCBwbG90U2l6ZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcnggPSB3aWR0aCAvIDI7XG4gICAgICAgIHZhciByeSA9IGhlaWdodCAvIDI7XG4gICAgICAgIGlmKHRyYWNlLnR5cGUgPT09ICdmdW5uZWxhcmVhJyAmJiAhdHJhY2Uuc2NhbGVncm91cCkge1xuICAgICAgICAgICAgcnkgLz0gdHJhY2UuYXNwZWN0cmF0aW87XG4gICAgICAgIH1cblxuICAgICAgICBjZDAuciA9IE1hdGgubWluKHJ4LCByeSkgLyAoMSArIGdldE1heFB1bGwodHJhY2UpKTtcblxuICAgICAgICBjZDAuY3ggPSBwbG90U2l6ZS5sICsgcGxvdFNpemUudyAqICh0cmFjZS5kb21haW4ueFsxXSArIHRyYWNlLmRvbWFpbi54WzBdKSAvIDI7XG4gICAgICAgIGNkMC5jeSA9IHBsb3RTaXplLnQgKyBwbG90U2l6ZS5oICogKDEgLSB0cmFjZS5kb21haW4ueVswXSkgLSBoZWlnaHQgLyAyO1xuICAgICAgICBpZih0cmFjZS50aXRsZS50ZXh0ICYmIHRyYWNlLnRpdGxlLnBvc2l0aW9uLmluZGV4T2YoJ2JvdHRvbScpICE9PSAtMSkge1xuICAgICAgICAgICAgY2QwLmN5IC09IGdldFRpdGxlU3BhY2UoY2QwLCBwbG90U2l6ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0cmFjZS5zY2FsZWdyb3VwICYmIHNjYWxlR3JvdXBzLmluZGV4T2YodHJhY2Uuc2NhbGVncm91cCkgPT09IC0xKSB7XG4gICAgICAgICAgICBzY2FsZUdyb3Vwcy5wdXNoKHRyYWNlLnNjYWxlZ3JvdXApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ3JvdXBTY2FsZShjZE1vZHVsZSwgc2NhbGVHcm91cHMpO1xufVxuXG5mdW5jdGlvbiBncm91cFNjYWxlKGNkTW9kdWxlLCBzY2FsZUdyb3Vwcykge1xuICAgIHZhciBjZDAsIGksIHRyYWNlO1xuXG4gICAgLy8gc2NhbGUgdGhvc2UgdGhhdCBhcmUgZ3JvdXBlZFxuICAgIGZvcih2YXIgayA9IDA7IGsgPCBzY2FsZUdyb3Vwcy5sZW5ndGg7IGsrKykge1xuICAgICAgICB2YXIgbWluID0gSW5maW5pdHk7XG4gICAgICAgIHZhciBnID0gc2NhbGVHcm91cHNba107XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2RNb2R1bGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNkMCA9IGNkTW9kdWxlW2ldWzBdO1xuICAgICAgICAgICAgdHJhY2UgPSBjZDAudHJhY2U7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlLnNjYWxlZ3JvdXAgPT09IGcpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXJlYTtcbiAgICAgICAgICAgICAgICBpZih0cmFjZS50eXBlID09PSAncGllJykge1xuICAgICAgICAgICAgICAgICAgICBhcmVhID0gY2QwLnIgKiBjZDAucjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYodHJhY2UudHlwZSA9PT0gJ2Z1bm5lbGFyZWEnKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByeCwgcnk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYodHJhY2UuYXNwZWN0cmF0aW8gPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByeCA9IGNkMC5yO1xuICAgICAgICAgICAgICAgICAgICAgICAgcnkgPSByeCAvIHRyYWNlLmFzcGVjdHJhdGlvO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcnkgPSBjZDAucjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ4ID0gcnkgKiB0cmFjZS5hc3BlY3RyYXRpbztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJ4ICo9ICgxICsgdHJhY2UuYmFzZXJhdGlvKSAvIDI7XG5cbiAgICAgICAgICAgICAgICAgICAgYXJlYSA9IHJ4ICogcnk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbWluID0gTWF0aC5taW4obWluLCBhcmVhIC8gY2QwLnZUb3RhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZE1vZHVsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2QwID0gY2RNb2R1bGVbaV1bMF07XG4gICAgICAgICAgICB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICAgICAgICAgIGlmKHRyYWNlLnNjYWxlZ3JvdXAgPT09IGcpIHtcbiAgICAgICAgICAgICAgICB2YXIgdiA9IG1pbiAqIGNkMC52VG90YWw7XG4gICAgICAgICAgICAgICAgaWYodHJhY2UudHlwZSA9PT0gJ2Z1bm5lbGFyZWEnKSB7XG4gICAgICAgICAgICAgICAgICAgIHYgLz0gKDEgKyB0cmFjZS5iYXNlcmF0aW8pIC8gMjtcbiAgICAgICAgICAgICAgICAgICAgdiAvPSB0cmFjZS5hc3BlY3RyYXRpbztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjZDAuciA9IE1hdGguc3FydCh2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gc2V0Q29vcmRzKGNkKSB7XG4gICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICB2YXIgY3VycmVudEFuZ2xlID0gdHJhY2Uucm90YXRpb24gKiBNYXRoLlBJIC8gMTgwO1xuICAgIHZhciBhbmdsZUZhY3RvciA9IDIgKiBNYXRoLlBJIC8gY2QwLnZUb3RhbDtcbiAgICB2YXIgZmlyc3RQdCA9ICdweDAnO1xuICAgIHZhciBsYXN0UHQgPSAncHgxJztcblxuICAgIHZhciBpLCBjZGksIGN1cnJlbnRDb29yZHM7XG5cbiAgICBpZih0cmFjZS5kaXJlY3Rpb24gPT09ICdjb3VudGVyY2xvY2t3aXNlJykge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoIWNkW2ldLmhpZGRlbikgYnJlYWs7IC8vIGZpbmQgdGhlIGZpcnN0IG5vbi1oaWRkZW4gc2xpY2VcbiAgICAgICAgfVxuICAgICAgICBpZihpID09PSBjZC5sZW5ndGgpIHJldHVybjsgLy8gYWxsIHNsaWNlcyBoaWRkZW5cblxuICAgICAgICBjdXJyZW50QW5nbGUgKz0gYW5nbGVGYWN0b3IgKiBjZFtpXS52O1xuICAgICAgICBhbmdsZUZhY3RvciAqPSAtMTtcbiAgICAgICAgZmlyc3RQdCA9ICdweDEnO1xuICAgICAgICBsYXN0UHQgPSAncHgwJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRDb29yZHMoYW5nbGUpIHtcbiAgICAgICAgcmV0dXJuIFtjZDAuciAqIE1hdGguc2luKGFuZ2xlKSwgLWNkMC5yICogTWF0aC5jb3MoYW5nbGUpXTtcbiAgICB9XG5cbiAgICBjdXJyZW50Q29vcmRzID0gZ2V0Q29vcmRzKGN1cnJlbnRBbmdsZSk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjZGkgPSBjZFtpXTtcbiAgICAgICAgaWYoY2RpLmhpZGRlbikgY29udGludWU7XG5cbiAgICAgICAgY2RpW2ZpcnN0UHRdID0gY3VycmVudENvb3JkcztcblxuICAgICAgICBjdXJyZW50QW5nbGUgKz0gYW5nbGVGYWN0b3IgKiBjZGkudiAvIDI7XG4gICAgICAgIGNkaS5weG1pZCA9IGdldENvb3JkcyhjdXJyZW50QW5nbGUpO1xuICAgICAgICBjZGkubWlkYW5nbGUgPSBjdXJyZW50QW5nbGU7XG5cbiAgICAgICAgY3VycmVudEFuZ2xlICs9IGFuZ2xlRmFjdG9yICogY2RpLnYgLyAyO1xuICAgICAgICBjdXJyZW50Q29vcmRzID0gZ2V0Q29vcmRzKGN1cnJlbnRBbmdsZSk7XG5cbiAgICAgICAgY2RpW2xhc3RQdF0gPSBjdXJyZW50Q29vcmRzO1xuXG4gICAgICAgIGNkaS5sYXJnZUFyYyA9IChjZGkudiA+IGNkMC52VG90YWwgLyAyKSA/IDEgOiAwO1xuXG4gICAgICAgIGNkaS5oYWxmYW5nbGUgPSBNYXRoLlBJICogTWF0aC5taW4oY2RpLnYgLyBjZDAudlRvdGFsLCAwLjUpO1xuICAgICAgICBjZGkucmluZyA9IDEgLSB0cmFjZS5ob2xlO1xuICAgICAgICBjZGkuckluc2NyaWJlZCA9IGdldEluc2NyaWJlZFJhZGl1c0ZyYWN0aW9uKGNkaSwgY2QwKTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHBsb3Q6IHBsb3QsXG4gICAgdHJhbnNmb3JtSW5zaWRlVGV4dDogdHJhbnNmb3JtSW5zaWRlVGV4dCxcbiAgICBkZXRlcm1pbmVJbnNpZGVUZXh0Rm9udDogZGV0ZXJtaW5lSW5zaWRlVGV4dEZvbnQsXG4gICAgcG9zaXRpb25UaXRsZU91dHNpZGU6IHBvc2l0aW9uVGl0bGVPdXRzaWRlLFxuICAgIHByZXJlbmRlclRpdGxlczogcHJlcmVuZGVyVGl0bGVzLFxuICAgIGxheW91dEFyZWFzOiBsYXlvdXRBcmVhcyxcbiAgICBhdHRhY2hGeEhhbmRsZXJzOiBhdHRhY2hGeEhhbmRsZXJzLFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vY29tcG9uZW50cy9meFwiOjYzMixcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4vZXZlbnRfZGF0YVwiOjEwOTAsXCIuL2hlbHBlcnNcIjoxMDkxLFwiZDNcIjoxNjN9XSwxMDk2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIHN0eWxlT25lID0gX2RlcmVxXygnLi9zdHlsZV9vbmUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHlsZShnZCkge1xuICAgIGdkLl9mdWxsTGF5b3V0Ll9waWVsYXllci5zZWxlY3RBbGwoJy50cmFjZScpLmVhY2goZnVuY3Rpb24oY2QpIHtcbiAgICAgICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgICAgIHZhciB0cmFjZVNlbGVjdGlvbiA9IGQzLnNlbGVjdCh0aGlzKTtcblxuICAgICAgICB0cmFjZVNlbGVjdGlvbi5zdHlsZSh7b3BhY2l0eTogdHJhY2Uub3BhY2l0eX0pO1xuXG4gICAgICAgIHRyYWNlU2VsZWN0aW9uLnNlbGVjdEFsbCgncGF0aC5zdXJmYWNlJykuZWFjaChmdW5jdGlvbihwdCkge1xuICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLmNhbGwoc3R5bGVPbmUsIHB0LCB0cmFjZSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxufSx7XCIuL3N0eWxlX29uZVwiOjEwOTcsXCJkM1wiOjE2M31dLDEwOTc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgY2FzdE9wdGlvbiA9IF9kZXJlcV8oJy4vaGVscGVycycpLmNhc3RPcHRpb247XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3R5bGVPbmUocywgcHQsIHRyYWNlKSB7XG4gICAgdmFyIGxpbmUgPSB0cmFjZS5tYXJrZXIubGluZTtcbiAgICB2YXIgbGluZUNvbG9yID0gY2FzdE9wdGlvbihsaW5lLmNvbG9yLCBwdC5wdHMpIHx8IENvbG9yLmRlZmF1bHRMaW5lO1xuICAgIHZhciBsaW5lV2lkdGggPSBjYXN0T3B0aW9uKGxpbmUud2lkdGgsIHB0LnB0cykgfHwgMDtcblxuICAgIHMuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIGxpbmVXaWR0aClcbiAgICAgICAgLmNhbGwoQ29sb3IuZmlsbCwgcHQuY29sb3IpXG4gICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgbGluZUNvbG9yKTtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4vaGVscGVyc1wiOjEwOTF9XSwxMDk4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJnbEF0dHJzID0gX2RlcmVxXygnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHg6IHNjYXR0ZXJnbEF0dHJzLngsXG4gICAgeTogc2NhdHRlcmdsQXR0cnMueSxcbiAgICB4eToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaW5kaWNlczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeGJvdW5kczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeWJvdW5kczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdGV4dDogc2NhdHRlcmdsQXR0cnMudGV4dCxcbiAgICBtYXJrZXI6IHtcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMSxcbiAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBibGVuZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaXplbWluOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMC4xLFxuICAgICAgICAgICAgbWF4OiAyLFxuICAgICAgICAgICAgZGZsdDogMC41LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNpemVtYXg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLjEsXG4gICAgICAgICAgICBkZmx0OiAyMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBib3JkZXI6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGFyZWFyYXRpbzoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgdHJhbnNmb3JtczogdW5kZWZpbmVkXG59O1xuXG59LHtcIi4uL3NjYXR0ZXIvYXR0cmlidXRlc1wiOjExMTJ9XSwxMDk5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNyZWF0ZVBvaW50Q2xvdWRSZW5kZXJlciA9IF9kZXJlcV8oJ2dsLXBvaW50Y2xvdWQyZCcpO1xuXG52YXIgc3RyMlJHQkFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliL3N0cjJyZ2JhcnJheScpO1xudmFyIGZpbmRFeHRyZW1lcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9hdXRvcmFuZ2UnKS5maW5kRXh0cmVtZXM7XG52YXIgZ2V0VHJhY2VDb2xvciA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvZ2V0X3RyYWNlX2NvbG9yJyk7XG5cbmZ1bmN0aW9uIFBvaW50Y2xvdWQoc2NlbmUsIHVpZCkge1xuICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICB0aGlzLnVpZCA9IHVpZDtcbiAgICB0aGlzLnR5cGUgPSAncG9pbnRjbG91ZCc7XG5cbiAgICB0aGlzLnBpY2tYRGF0YSA9IFtdO1xuICAgIHRoaXMucGlja1lEYXRhID0gW107XG4gICAgdGhpcy54RGF0YSA9IFtdO1xuICAgIHRoaXMueURhdGEgPSBbXTtcbiAgICB0aGlzLnRleHRMYWJlbHMgPSBbXTtcbiAgICB0aGlzLmNvbG9yID0gJ3JnYigwLCAwLCAwKSc7XG4gICAgdGhpcy5uYW1lID0gJyc7XG4gICAgdGhpcy5ob3ZlcmluZm8gPSAnYWxsJztcblxuICAgIHRoaXMuaWRUb0luZGV4ID0gbmV3IEludDMyQXJyYXkoMCk7XG4gICAgdGhpcy5ib3VuZHMgPSBbMCwgMCwgMCwgMF07XG5cbiAgICB0aGlzLnBvaW50Y2xvdWRPcHRpb25zID0ge1xuICAgICAgICBwb3NpdGlvbnM6IG5ldyBGbG9hdDMyQXJyYXkoMCksXG4gICAgICAgIGlkVG9JbmRleDogdGhpcy5pZFRvSW5kZXgsXG4gICAgICAgIHNpemVtaW46IDAuNSxcbiAgICAgICAgc2l6ZW1heDogMTIsXG4gICAgICAgIGNvbG9yOiBbMCwgMCwgMCwgMV0sXG4gICAgICAgIGFyZWFSYXRpbzogMSxcbiAgICAgICAgYm9yZGVyQ29sb3I6IFswLCAwLCAwLCAxXVxuICAgIH07XG4gICAgdGhpcy5wb2ludGNsb3VkID0gY3JlYXRlUG9pbnRDbG91ZFJlbmRlcmVyKHNjZW5lLmdscGxvdCwgdGhpcy5wb2ludGNsb3VkT3B0aW9ucyk7XG4gICAgdGhpcy5wb2ludGNsb3VkLl90cmFjZSA9IHRoaXM7IC8vIHNjZW5lMmQgcmVxdWlyZXMgdGhpcyBwcm9wXG59XG5cbnZhciBwcm90byA9IFBvaW50Y2xvdWQucHJvdG90eXBlO1xuXG5wcm90by5oYW5kbGVQaWNrID0gZnVuY3Rpb24ocGlja1Jlc3VsdCkge1xuICAgIHZhciBpbmRleCA9IHRoaXMuaWRUb0luZGV4W3BpY2tSZXN1bHQucG9pbnRJZF07XG5cbiAgICAvLyBwcmVmZXIgdGhlIHJlYWRvdXQgZnJvbSBYWSwgaWYgcHJlc2VudFxuICAgIHJldHVybiB7XG4gICAgICAgIHRyYWNlOiB0aGlzLFxuICAgICAgICBkYXRhQ29vcmQ6IHBpY2tSZXN1bHQuZGF0YUNvb3JkLFxuICAgICAgICB0cmFjZUNvb3JkOiB0aGlzLnBpY2tYWURhdGEgP1xuICAgICAgICAgICAgW3RoaXMucGlja1hZRGF0YVtpbmRleCAqIDJdLCB0aGlzLnBpY2tYWURhdGFbaW5kZXggKiAyICsgMV1dIDpcbiAgICAgICAgICAgIFt0aGlzLnBpY2tYRGF0YVtpbmRleF0sIHRoaXMucGlja1lEYXRhW2luZGV4XV0sXG4gICAgICAgIHRleHRMYWJlbDogQXJyYXkuaXNBcnJheSh0aGlzLnRleHRMYWJlbHMpID9cbiAgICAgICAgICAgIHRoaXMudGV4dExhYmVsc1tpbmRleF0gOlxuICAgICAgICAgICAgdGhpcy50ZXh0TGFiZWxzLFxuICAgICAgICBjb2xvcjogdGhpcy5jb2xvcixcbiAgICAgICAgbmFtZTogdGhpcy5uYW1lLFxuICAgICAgICBwb2ludEluZGV4OiBpbmRleCxcbiAgICAgICAgaG92ZXJpbmZvOiB0aGlzLmhvdmVyaW5mb1xuICAgIH07XG59O1xuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgdGhpcy5pbmRleCA9IG9wdGlvbnMuaW5kZXg7XG4gICAgdGhpcy50ZXh0TGFiZWxzID0gb3B0aW9ucy50ZXh0O1xuICAgIHRoaXMubmFtZSA9IG9wdGlvbnMubmFtZTtcbiAgICB0aGlzLmhvdmVyaW5mbyA9IG9wdGlvbnMuaG92ZXJpbmZvO1xuICAgIHRoaXMuYm91bmRzID0gW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldO1xuXG4gICAgdGhpcy51cGRhdGVGYXN0KG9wdGlvbnMpO1xuXG4gICAgdGhpcy5jb2xvciA9IGdldFRyYWNlQ29sb3Iob3B0aW9ucywge30pO1xufTtcblxucHJvdG8udXBkYXRlRmFzdCA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICB2YXIgeCA9IHRoaXMueERhdGEgPSB0aGlzLnBpY2tYRGF0YSA9IG9wdGlvbnMueDtcbiAgICB2YXIgeSA9IHRoaXMueURhdGEgPSB0aGlzLnBpY2tZRGF0YSA9IG9wdGlvbnMueTtcbiAgICB2YXIgeHkgPSB0aGlzLnBpY2tYWURhdGEgPSBvcHRpb25zLnh5O1xuXG4gICAgdmFyIHVzZXJCb3VuZHMgPSBvcHRpb25zLnhib3VuZHMgJiYgb3B0aW9ucy55Ym91bmRzO1xuICAgIHZhciBpbmRleCA9IG9wdGlvbnMuaW5kaWNlcztcblxuICAgIHZhciBsZW47XG4gICAgdmFyIGlkVG9JbmRleDtcbiAgICB2YXIgcG9zaXRpb25zO1xuICAgIHZhciBib3VuZHMgPSB0aGlzLmJvdW5kcztcblxuICAgIHZhciB4eCwgeXksIGk7XG5cbiAgICBpZih4eSkge1xuICAgICAgICBwb3NpdGlvbnMgPSB4eTtcblxuICAgICAgICAvLyBkaXZpZGluZyB4eS5sZW5ndGggYnkgMiBhbmQgdHJ1bmNhdGluZyB0byBpbnRlZ2VyIGlmIHh5Lmxlbmd0aCB3YXMgbm90IGV2ZW5cbiAgICAgICAgbGVuID0geHkubGVuZ3RoID4+PiAxO1xuXG4gICAgICAgIGlmKHVzZXJCb3VuZHMpIHtcbiAgICAgICAgICAgIGJvdW5kc1swXSA9IG9wdGlvbnMueGJvdW5kc1swXTtcbiAgICAgICAgICAgIGJvdW5kc1syXSA9IG9wdGlvbnMueGJvdW5kc1sxXTtcbiAgICAgICAgICAgIGJvdW5kc1sxXSA9IG9wdGlvbnMueWJvdW5kc1swXTtcbiAgICAgICAgICAgIGJvdW5kc1szXSA9IG9wdGlvbnMueWJvdW5kc1sxXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgeHggPSBwb3NpdGlvbnNbaSAqIDJdO1xuICAgICAgICAgICAgICAgIHl5ID0gcG9zaXRpb25zW2kgKiAyICsgMV07XG5cbiAgICAgICAgICAgICAgICBpZih4eCA8IGJvdW5kc1swXSkgYm91bmRzWzBdID0geHg7XG4gICAgICAgICAgICAgICAgaWYoeHggPiBib3VuZHNbMl0pIGJvdW5kc1syXSA9IHh4O1xuICAgICAgICAgICAgICAgIGlmKHl5IDwgYm91bmRzWzFdKSBib3VuZHNbMV0gPSB5eTtcbiAgICAgICAgICAgICAgICBpZih5eSA+IGJvdW5kc1szXSkgYm91bmRzWzNdID0geXk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihpbmRleCkge1xuICAgICAgICAgICAgaWRUb0luZGV4ID0gaW5kZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZFRvSW5kZXggPSBuZXcgSW50MzJBcnJheShsZW4pO1xuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgIGlkVG9JbmRleFtpXSA9IGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBsZW4gPSB4Lmxlbmd0aDtcblxuICAgICAgICBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KDIgKiBsZW4pO1xuICAgICAgICBpZFRvSW5kZXggPSBuZXcgSW50MzJBcnJheShsZW4pO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICB4eCA9IHhbaV07XG4gICAgICAgICAgICB5eSA9IHlbaV07XG5cbiAgICAgICAgICAgIGlkVG9JbmRleFtpXSA9IGk7XG5cbiAgICAgICAgICAgIHBvc2l0aW9uc1tpICogMl0gPSB4eDtcbiAgICAgICAgICAgIHBvc2l0aW9uc1tpICogMiArIDFdID0geXk7XG5cbiAgICAgICAgICAgIGlmKHh4IDwgYm91bmRzWzBdKSBib3VuZHNbMF0gPSB4eDtcbiAgICAgICAgICAgIGlmKHh4ID4gYm91bmRzWzJdKSBib3VuZHNbMl0gPSB4eDtcbiAgICAgICAgICAgIGlmKHl5IDwgYm91bmRzWzFdKSBib3VuZHNbMV0gPSB5eTtcbiAgICAgICAgICAgIGlmKHl5ID4gYm91bmRzWzNdKSBib3VuZHNbM10gPSB5eTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuaWRUb0luZGV4ID0gaWRUb0luZGV4O1xuICAgIHRoaXMucG9pbnRjbG91ZE9wdGlvbnMuaWRUb0luZGV4ID0gaWRUb0luZGV4O1xuXG4gICAgdGhpcy5wb2ludGNsb3VkT3B0aW9ucy5wb3NpdGlvbnMgPSBwb3NpdGlvbnM7XG5cbiAgICB2YXIgbWFya2VyQ29sb3IgPSBzdHIyUkdCQXJyYXkob3B0aW9ucy5tYXJrZXIuY29sb3IpO1xuICAgIHZhciBib3JkZXJDb2xvciA9IHN0cjJSR0JBcnJheShvcHRpb25zLm1hcmtlci5ib3JkZXIuY29sb3IpO1xuICAgIHZhciBvcGFjaXR5ID0gb3B0aW9ucy5vcGFjaXR5ICogb3B0aW9ucy5tYXJrZXIub3BhY2l0eTtcblxuICAgIG1hcmtlckNvbG9yWzNdICo9IG9wYWNpdHk7XG4gICAgdGhpcy5wb2ludGNsb3VkT3B0aW9ucy5jb2xvciA9IG1hcmtlckNvbG9yO1xuXG4gICAgLy8gZGV0ZWN0IGJsZW5kaW5nIGZyb20gdGhlIG51bWJlciBvZiBwb2ludHMsIGlmIHVuZGVmaW5lZFxuICAgIC8vIGJlY2F1c2UgbGFyZ2UgZGF0YSB3aXRoIGJsZW5kaW5nIGhpdHMgcGVyZm9ybWFuY2VcbiAgICB2YXIgYmxlbmQgPSBvcHRpb25zLm1hcmtlci5ibGVuZDtcbiAgICBpZihibGVuZCA9PT0gbnVsbCkge1xuICAgICAgICB2YXIgbWF4UG9pbnRzID0gMTAwO1xuICAgICAgICBibGVuZCA9IHgubGVuZ3RoIDwgbWF4UG9pbnRzIHx8IHkubGVuZ3RoIDwgbWF4UG9pbnRzO1xuICAgIH1cbiAgICB0aGlzLnBvaW50Y2xvdWRPcHRpb25zLmJsZW5kID0gYmxlbmQ7XG5cbiAgICBib3JkZXJDb2xvclszXSAqPSBvcGFjaXR5O1xuICAgIHRoaXMucG9pbnRjbG91ZE9wdGlvbnMuYm9yZGVyQ29sb3IgPSBib3JkZXJDb2xvcjtcblxuICAgIHZhciBtYXJrZXJTaXplTWluID0gb3B0aW9ucy5tYXJrZXIuc2l6ZW1pbjtcbiAgICB2YXIgbWFya2VyU2l6ZU1heCA9IE1hdGgubWF4KG9wdGlvbnMubWFya2VyLnNpemVtYXgsIG9wdGlvbnMubWFya2VyLnNpemVtaW4pO1xuICAgIHRoaXMucG9pbnRjbG91ZE9wdGlvbnMuc2l6ZU1pbiA9IG1hcmtlclNpemVNaW47XG4gICAgdGhpcy5wb2ludGNsb3VkT3B0aW9ucy5zaXplTWF4ID0gbWFya2VyU2l6ZU1heDtcbiAgICB0aGlzLnBvaW50Y2xvdWRPcHRpb25zLmFyZWFSYXRpbyA9IG9wdGlvbnMubWFya2VyLmJvcmRlci5hcmVhcmF0aW87XG5cbiAgICB0aGlzLnBvaW50Y2xvdWQudXBkYXRlKHRoaXMucG9pbnRjbG91ZE9wdGlvbnMpO1xuXG4gICAgLy8gYWRkIGl0ZW0gZm9yIGF1dG9yYW5nZSByb3V0aW5lXG4gICAgdmFyIHhhID0gdGhpcy5zY2VuZS54YXhpcztcbiAgICB2YXIgeWEgPSB0aGlzLnNjZW5lLnlheGlzO1xuICAgIHZhciBwYWQgPSBtYXJrZXJTaXplTWF4IC8gMiB8fCAwLjU7XG4gICAgb3B0aW9ucy5fZXh0cmVtZXNbeGEuX2lkXSA9IGZpbmRFeHRyZW1lcyh4YSwgW2JvdW5kc1swXSwgYm91bmRzWzJdXSwge3BwYWQ6IHBhZH0pO1xuICAgIG9wdGlvbnMuX2V4dHJlbWVzW3lhLl9pZF0gPSBmaW5kRXh0cmVtZXMoeWEsIFtib3VuZHNbMV0sIGJvdW5kc1szXV0sIHtwcGFkOiBwYWR9KTtcbn07XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnBvaW50Y2xvdWQuZGlzcG9zZSgpO1xufTtcblxuZnVuY3Rpb24gY3JlYXRlUG9pbnRjbG91ZChzY2VuZSwgZGF0YSkge1xuICAgIHZhciBwbG90ID0gbmV3IFBvaW50Y2xvdWQoc2NlbmUsIGRhdGEudWlkKTtcbiAgICBwbG90LnVwZGF0ZShkYXRhKTtcbiAgICByZXR1cm4gcGxvdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVQb2ludGNsb3VkO1xuXG59LHtcIi4uLy4uL2xpYi9zdHIycmdiYXJyYXlcIjo3NDIsXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXV0b3JhbmdlXCI6NzY2LFwiLi4vc2NhdHRlci9nZXRfdHJhY2VfY29sb3JcIjoxMTIxLFwiZ2wtcG9pbnRjbG91ZDJkXCI6MjkyfV0sMTEwMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgY29lcmNlKCd4Jyk7XG4gICAgY29lcmNlKCd5Jyk7XG5cbiAgICBjb2VyY2UoJ3hib3VuZHMnKTtcbiAgICBjb2VyY2UoJ3lib3VuZHMnKTtcblxuICAgIGlmKHRyYWNlSW4ueHkgJiYgdHJhY2VJbi54eSBpbnN0YW5jZW9mIEZsb2F0MzJBcnJheSkge1xuICAgICAgICB0cmFjZU91dC54eSA9IHRyYWNlSW4ueHk7XG4gICAgfVxuXG4gICAgaWYodHJhY2VJbi5pbmRpY2VzICYmIHRyYWNlSW4uaW5kaWNlcyBpbnN0YW5jZW9mIEludDMyQXJyYXkpIHtcbiAgICAgICAgdHJhY2VPdXQuaW5kaWNlcyA9IHRyYWNlSW4uaW5kaWNlcztcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ21hcmtlci5jb2xvcicsIGRlZmF1bHRDb2xvcik7XG4gICAgY29lcmNlKCdtYXJrZXIub3BhY2l0eScpO1xuICAgIGNvZXJjZSgnbWFya2VyLmJsZW5kJyk7XG4gICAgY29lcmNlKCdtYXJrZXIuc2l6ZW1pbicpO1xuICAgIGNvZXJjZSgnbWFya2VyLnNpemVtYXgnKTtcbiAgICBjb2VyY2UoJ21hcmtlci5ib3JkZXIuY29sb3InLCBkZWZhdWx0Q29sb3IpO1xuICAgIGNvZXJjZSgnbWFya2VyLmJvcmRlci5hcmVhcmF0aW8nKTtcblxuICAgIC8vIGRpc2FibGUgMUQgdHJhbnNmb3JtcyAtIHRoYXQgd291bGQgZGVmZWF0IHRoZSBwdXJwb3NlIG9mIHRoaXMgdHJhY2UgdHlwZSwgcGVyZm9ybWFuY2UhXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IG51bGw7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4vYXR0cmlidXRlc1wiOjEwOTh9XSwxMTAxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcblxuICAgIC8vIHJldXNlIHRoZSBTY2F0dGVyM0QgJ2R1bW15JyBjYWxjIHN0ZXAgc28gdGhhdCBsZWdlbmRzIGtub3cgd2hhdCB0byBkb1xuICAgIGNhbGM6IF9kZXJlcV8oJy4uL3NjYXR0ZXIzZC9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9jb252ZXJ0JyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdwb2ludGNsb3VkJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2wyZCcpLFxuICAgIGNhdGVnb3JpZXM6IFsnZ2wnLCAnZ2wyZCcsICdzaG93TGVnZW5kJ10sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2dsMmRcIjo4MDUsXCIuLi9zY2F0dGVyM2QvY2FsY1wiOjExMzksXCIuL2F0dHJpYnV0ZXNcIjoxMDk4LFwiLi9jb252ZXJ0XCI6MTA5OSxcIi4vZGVmYXVsdHNcIjoxMTAwfV0sMTEwMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBmb250QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXMnKTtcbnZhciBwbG90QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgY29sb3JBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3IvYXR0cmlidXRlcycpO1xudmFyIGZ4QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2F0dHJpYnV0ZXMnKTtcbnZhciBkb21haW5BdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2RvbWFpbicpLmF0dHJpYnV0ZXM7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIHRlbXBsYXRlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZScpLnRlbXBsYXRlZEFycmF5O1xuXG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIG92ZXJyaWRlQWxsID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xuXG52YXIgRk9STUFUX0xJTksgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvZG9jcycpLkZPUk1BVF9MSU5LO1xuXG52YXIgYXR0cnMgPSBtb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHtcbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIHBsb3RBdHRycy5ob3ZlcmluZm8sIHtcbiAgICAgICAgZmxhZ3M6IFtdLFxuICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgXG4gICAgfSksXG4gICAgaG92ZXJsYWJlbDogZnhBdHRycy5ob3ZlcmxhYmVsLFxuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICdzYW5rZXknLCB0cmFjZTogdHJ1ZX0pLFxuXG4gICAgb3JpZW50YXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsndicsICdoJ10sXG4gICAgICAgIGRmbHQ6ICdoJyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB2YWx1ZWZvcm1hdDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGZsdDogJy4zcycsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdmFsdWVzdWZmaXg6IHtcbiAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGFycmFuZ2VtZW50OiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3NuYXAnLCAncGVycGVuZGljdWxhcicsICdmcmVlZm9ybScsICdmaXhlZCddLFxuICAgICAgICBkZmx0OiAnc25hcCcsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGV4dGZvbnQ6IGZvbnRBdHRycyh7XG4gICAgICAgIFxuICAgIH0pLFxuXG4gICAgbm9kZToge1xuICAgICAgICBsYWJlbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgZGZsdDogW10sXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBncm91cHM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdpbmZvX2FycmF5JyxcbiAgICAgICAgICAgIGltcGxpZWRFZGl0czogeyd4JzogW10sICd5JzogW119LFxuICAgICAgICAgICAgZGltZW5zaW9uczogMixcbiAgICAgICAgICAgIGZyZWVMZW5ndGg6IHRydWUsXG4gICAgICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgICAgIGl0ZW1zOiB7dmFsVHlwZTogJ251bWJlcicsIGVkaXRUeXBlOiAnY2FsYyd9LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgeDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgZGZsdDogW10sXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgZGZsdDogMC41LFxuICAgICAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHBhZDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDIwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdGhpY2tuZXNzOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGFycmF5T2s6IGZhbHNlLFxuICAgICAgICAgICAgbWluOiAxLFxuICAgICAgICAgICAgZGZsdDogMjAsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBob3ZlcmluZm86IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogWydhbGwnLCAnbm9uZScsICdza2lwJ10sXG4gICAgICAgICAgICBkZmx0OiAnYWxsJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGhvdmVybGFiZWw6IGZ4QXR0cnMuaG92ZXJsYWJlbCwgLy8gbmVlZHMgZWRpdFR5cGUgb3ZlcnJpZGUsXG4gICAgICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycyh7fSwge1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBrZXlzOiBbJ3ZhbHVlJywgJ2xhYmVsJ11cbiAgICAgICAgfSksXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsaW5rOiB7XG4gICAgICAgIGxhYmVsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBkZmx0OiBjb2xvckF0dHJzLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzb3VyY2U6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogW10sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgdGFyZ2V0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IFtdLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGhvdmVyaW5mbzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2FsbCcsICdub25lJywgJ3NraXAnXSxcbiAgICAgICAgICAgIGRmbHQ6ICdhbGwnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgaG92ZXJsYWJlbDogZnhBdHRycy5ob3ZlcmxhYmVsLCAvLyBuZWVkcyBlZGl0VHlwZSBvdmVycmlkZSxcbiAgICAgICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKHt9LCB7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGtleXM6IFsndmFsdWUnLCAnbGFiZWwnXVxuICAgICAgICB9KSxcbiAgICAgICAgY29sb3JzY2FsZXM6IHRlbXBsYXRlZEFycmF5KCdjb25jZW50cmF0aW9uc2NhbGVzJywge1xuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIGxhYmVsOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBkZmx0OiAnJ1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNtYXg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY21pbjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjb2xvcnNjYWxlOiBleHRlbmRGbGF0KGNvbG9yQXR0cmlidXRlcygpLmNvbG9yc2NhbGUsIHtkZmx0OiBbWzAsICd3aGl0ZSddLCBbMSwgJ2JsYWNrJ11dfSlcbiAgICAgICAgfSksXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59LCAnY2FsYycsICduZXN0ZWQnKTtcbmF0dHJzLnRyYW5zZm9ybXMgPSB1bmRlZmluZWQ7XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvci9hdHRyaWJ1dGVzXCI6NTkyLFwiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXNcIjo2MDAsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2F0dHJpYnV0ZXNcIjo2MjMsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2NvbnN0YW50cy9kb2NzXCI6NjkwLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RfYXBpL2VkaXRfdHlwZXNcIjo3NTAsXCIuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NCxcIi4uLy4uL3Bsb3RzL2RvbWFpblwiOjc5MixcIi4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlc1wiOjc5M31dLDExMDM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG52YXIgZ2V0TW9kdWxlQ2FsY0RhdGEgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9nZXRfZGF0YScpLmdldE1vZHVsZUNhbGNEYXRhO1xudmFyIHBsb3QgPSBfZGVyZXFfKCcuL3Bsb3QnKTtcbnZhciBmeEF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG52YXIgc2V0Q3Vyc29yID0gX2RlcmVxXygnLi4vLi4vbGliL3NldGN1cnNvcicpO1xudmFyIGRyYWdFbGVtZW50ID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmFnZWxlbWVudCcpO1xudmFyIHByZXBTZWxlY3QgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vc2VsZWN0JykucHJlcFNlbGVjdDtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG5cbnZhciBTQU5LRVkgPSAnc2Fua2V5JztcblxuZXhwb3J0cy5uYW1lID0gU0FOS0VZO1xuXG5leHBvcnRzLmJhc2VMYXlvdXRBdHRyT3ZlcnJpZGVzID0gb3ZlcnJpZGVBbGwoe1xuICAgIGhvdmVybGFiZWw6IGZ4QXR0cnMuaG92ZXJsYWJlbFxufSwgJ3Bsb3QnLCAnbmVzdGVkJyk7XG5cbmV4cG9ydHMucGxvdCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGNhbGNEYXRhID0gZ2V0TW9kdWxlQ2FsY0RhdGEoZ2QuY2FsY2RhdGEsIFNBTktFWSlbMF07XG4gICAgcGxvdChnZCwgY2FsY0RhdGEpO1xuICAgIGV4cG9ydHMudXBkYXRlRngoZ2QpO1xufTtcblxuZXhwb3J0cy5jbGVhbiA9IGZ1bmN0aW9uKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBoYWRQbG90ID0gKG9sZEZ1bGxMYXlvdXQuX2hhcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXMoU0FOS0VZKSk7XG4gICAgdmFyIGhhc1Bsb3QgPSAobmV3RnVsbExheW91dC5faGFzICYmIG5ld0Z1bGxMYXlvdXQuX2hhcyhTQU5LRVkpKTtcblxuICAgIGlmKGhhZFBsb3QgJiYgIWhhc1Bsb3QpIHtcbiAgICAgICAgb2xkRnVsbExheW91dC5fcGFwZXJkaXYuc2VsZWN0QWxsKCcuc2Fua2V5JykucmVtb3ZlKCk7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX3BhcGVyZGl2LnNlbGVjdEFsbCgnLmJnc2Fua2V5JykucmVtb3ZlKCk7XG4gICAgfVxufTtcblxuZXhwb3J0cy51cGRhdGVGeCA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGdkLl9mdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBzdWJwbG90VXBkYXRlRngoZ2QsIGkpO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHN1YnBsb3RVcGRhdGVGeChnZCwgaW5kZXgpIHtcbiAgICB2YXIgdHJhY2UgPSBnZC5fZnVsbERhdGFbaW5kZXhdO1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICB2YXIgZHJhZ01vZGUgPSBmdWxsTGF5b3V0LmRyYWdtb2RlO1xuICAgIHZhciBjdXJzb3IgPSBmdWxsTGF5b3V0LmRyYWdtb2RlID09PSAncGFuJyA/ICdtb3ZlJyA6ICdjcm9zc2hhaXInO1xuICAgIHZhciBiZ1JlY3QgPSB0cmFjZS5fYmdSZWN0O1xuXG4gICAgaWYoZHJhZ01vZGUgPT09ICdwYW4nIHx8IGRyYWdNb2RlID09PSAnem9vbScpIHJldHVybjtcblxuICAgIHNldEN1cnNvcihiZ1JlY3QsIGN1cnNvcik7XG5cbiAgICB2YXIgeGF4aXMgPSB7XG4gICAgICAgIF9pZDogJ3gnLFxuICAgICAgICBjMnA6IExpYi5pZGVudGl0eSxcbiAgICAgICAgX29mZnNldDogdHJhY2UuX3NhbmtleS50cmFuc2xhdGVYLFxuICAgICAgICBfbGVuZ3RoOiB0cmFjZS5fc2Fua2V5LndpZHRoXG4gICAgfTtcbiAgICB2YXIgeWF4aXMgPSB7XG4gICAgICAgIF9pZDogJ3knLFxuICAgICAgICBjMnA6IExpYi5pZGVudGl0eSxcbiAgICAgICAgX29mZnNldDogdHJhY2UuX3NhbmtleS50cmFuc2xhdGVZLFxuICAgICAgICBfbGVuZ3RoOiB0cmFjZS5fc2Fua2V5LmhlaWdodFxuICAgIH07XG5cbiAgICAvLyBOb3RlOiBkcmFnT3B0aW9ucyBpcyBuZWVkZWQgdG8gYmUgZGVjbGFyZWQgZm9yIGFsbCBkcmFnbW9kZXMgYmVjYXVzZVxuICAgIC8vIGl0J3MgdGhlIG9iamVjdCB0aGF0IGhvbGRzIHBlcnNpc3RlbnQgc2VsZWN0aW9uIHN0YXRlLlxuICAgIHZhciBkcmFnT3B0aW9ucyA9IHtcbiAgICAgICAgZ2Q6IGdkLFxuICAgICAgICBlbGVtZW50OiBiZ1JlY3Qubm9kZSgpLFxuICAgICAgICBwbG90aW5mbzoge1xuICAgICAgICAgICAgaWQ6IGluZGV4LFxuICAgICAgICAgICAgeGF4aXM6IHhheGlzLFxuICAgICAgICAgICAgeWF4aXM6IHlheGlzLFxuICAgICAgICAgICAgZmlsbFJhbmdlSXRlbXM6IExpYi5ub29wXG4gICAgICAgIH0sXG4gICAgICAgIHN1YnBsb3Q6IGluZGV4LFxuICAgICAgICAvLyBjcmVhdGUgbW9jayB4L3kgYXhlcyBmb3IgaG92ZXIgcm91dGluZVxuICAgICAgICB4YXhlczogW3hheGlzXSxcbiAgICAgICAgeWF4ZXM6IFt5YXhpc10sXG4gICAgICAgIGRvbmVGbkNvbXBsZXRlZDogZnVuY3Rpb24oc2VsZWN0aW9uKSB7XG4gICAgICAgICAgICB2YXIgdHJhY2VOb3cgPSBnZC5fZnVsbERhdGFbaW5kZXhdO1xuICAgICAgICAgICAgdmFyIG5ld0dyb3VwcztcbiAgICAgICAgICAgIHZhciBvbGRHcm91cHMgPSB0cmFjZU5vdy5ub2RlLmdyb3Vwcy5zbGljZSgpO1xuICAgICAgICAgICAgdmFyIG5ld0dyb3VwID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGZpbmROb2RlKHB0KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gdHJhY2VOb3cuX3NhbmtleS5ncmFwaC5ub2RlcztcbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYobm9kZXNbaV0ucG9pbnROdW1iZXIgPT09IHB0KSByZXR1cm4gbm9kZXNbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgc2VsZWN0aW9uLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSBmaW5kTm9kZShzZWxlY3Rpb25bal0ucG9pbnROdW1iZXIpO1xuICAgICAgICAgICAgICAgIGlmKCFub2RlKSBjb250aW51ZTtcblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBub2RlIHJlcHJlc2VudHMgYSBncm91cFxuICAgICAgICAgICAgICAgIGlmKG5vZGUuZ3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFsbCBpdHMgY2hpbGRyZW4gdG8gdGhlIGN1cnJlbnQgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIGZvcih2YXIgayA9IDA7IGsgPCBub2RlLmNoaWxkcmVuTm9kZXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0dyb3VwLnB1c2gobm9kZS5jaGlsZHJlbk5vZGVzW2tdLnBvaW50TnVtYmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBGbGFnIGdyb3VwIGZvciByZW1vdmFsIGZyb20gZXhpc3RpbmcgbGlzdCBvZiBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgb2xkR3JvdXBzW25vZGUucG9pbnROdW1iZXIgLSB0cmFjZU5vdy5ub2RlLl9jb3VudF0gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdHcm91cC5wdXNoKG5vZGUucG9pbnROdW1iZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmV3R3JvdXBzID0gb2xkR3JvdXBzXG4gICAgICAgICAgICAgICAgLmZpbHRlcihCb29sZWFuKVxuICAgICAgICAgICAgICAgIC5jb25jYXQoW25ld0dyb3VwXSk7XG5cbiAgICAgICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19ndWlSZXN0eWxlJywgZ2QsIHtcbiAgICAgICAgICAgICAgICAnbm9kZS5ncm91cHMnOiBbIG5ld0dyb3VwcyBdXG4gICAgICAgICAgICB9LCBpbmRleCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZHJhZ09wdGlvbnMucHJlcEZuID0gZnVuY3Rpb24oZSwgc3RhcnRYLCBzdGFydFkpIHtcbiAgICAgICAgcHJlcFNlbGVjdChlLCBzdGFydFgsIHN0YXJ0WSwgZHJhZ09wdGlvbnMsIGRyYWdNb2RlKTtcbiAgICB9O1xuXG4gICAgZHJhZ0VsZW1lbnQuaW5pdChkcmFnT3B0aW9ucyk7XG59XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9kcmFnZWxlbWVudFwiOjYxMSxcIi4uLy4uL2NvbXBvbmVudHMvZngvbGF5b3V0X2F0dHJpYnV0ZXNcIjo2MzMsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvc2V0Y3Vyc29yXCI6NzM5LFwiLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlc1wiOjc1MCxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9zZWxlY3RcIjo3ODQsXCIuLi8uLi9wbG90cy9nZXRfZGF0YVwiOjgwMixcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9wbG90XCI6MTEwOH1dLDExMDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdGFyamFuID0gX2RlcmVxXygnc3Ryb25nbHktY29ubmVjdGVkLWNvbXBvbmVudHMnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciB3cmFwID0gX2RlcmVxXygnLi4vLi4vbGliL2d1cCcpLndyYXA7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXk7XG52YXIgaXNJbmRleCA9IExpYi5pc0luZGV4O1xudmFyIENvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKTtcblxuZnVuY3Rpb24gY29udmVydFRvRDNTYW5rZXkodHJhY2UpIHtcbiAgICB2YXIgbm9kZVNwZWMgPSB0cmFjZS5ub2RlO1xuICAgIHZhciBsaW5rU3BlYyA9IHRyYWNlLmxpbms7XG5cbiAgICB2YXIgbGlua3MgPSBbXTtcbiAgICB2YXIgaGFzTGlua0NvbG9yQXJyYXkgPSBpc0FycmF5T3JUeXBlZEFycmF5KGxpbmtTcGVjLmNvbG9yKTtcbiAgICB2YXIgbGlua2VkTm9kZXMgPSB7fTtcblxuICAgIHZhciBjb21wb25lbnRzID0ge307XG4gICAgdmFyIGNvbXBvbmVudENvdW50ID0gbGlua1NwZWMuY29sb3JzY2FsZXMubGVuZ3RoO1xuICAgIHZhciBpO1xuICAgIGZvcihpID0gMDsgaSA8IGNvbXBvbmVudENvdW50OyBpKyspIHtcbiAgICAgICAgdmFyIGNzY2FsZSA9IGxpbmtTcGVjLmNvbG9yc2NhbGVzW2ldO1xuICAgICAgICB2YXIgc3BlY3MgPSBDb2xvcnNjYWxlLmV4dHJhY3RTY2FsZShjc2NhbGUsIHtjTGV0dGVyOiAnYyd9KTtcbiAgICAgICAgdmFyIHNjYWxlID0gQ29sb3JzY2FsZS5tYWtlQ29sb3JTY2FsZUZ1bmMoc3BlY3MpO1xuICAgICAgICBjb21wb25lbnRzW2NzY2FsZS5sYWJlbF0gPSBzY2FsZTtcbiAgICB9XG5cbiAgICB2YXIgbWF4Tm9kZUlkID0gMDtcbiAgICBmb3IoaSA9IDA7IGkgPCBsaW5rU3BlYy52YWx1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihsaW5rU3BlYy5zb3VyY2VbaV0gPiBtYXhOb2RlSWQpIG1heE5vZGVJZCA9IGxpbmtTcGVjLnNvdXJjZVtpXTtcbiAgICAgICAgaWYobGlua1NwZWMudGFyZ2V0W2ldID4gbWF4Tm9kZUlkKSBtYXhOb2RlSWQgPSBsaW5rU3BlYy50YXJnZXRbaV07XG4gICAgfVxuICAgIHZhciBub2RlQ291bnQgPSBtYXhOb2RlSWQgKyAxO1xuICAgIHRyYWNlLm5vZGUuX2NvdW50ID0gbm9kZUNvdW50O1xuXG4gICAgLy8gR3JvdXAgbm9kZXNcbiAgICB2YXIgajtcbiAgICB2YXIgZ3JvdXBzID0gdHJhY2Uubm9kZS5ncm91cHM7XG4gICAgdmFyIGdyb3VwTG9va3VwID0ge307XG4gICAgZm9yKGkgPSAwOyBpIDwgZ3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBncm91cCA9IGdyb3Vwc1tpXTtcbiAgICAgICAgLy8gQnVpbGQgYSBsb29rdXAgdGFibGUgdG8gcXVpY2tseSBmaW5kIGluIHdoaWNoIGdyb3VwIGEgbm9kZSBpc1xuICAgICAgICBmb3IoaiA9IDA7IGogPCBncm91cC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGdyb3VwW2pdO1xuICAgICAgICAgICAgdmFyIGdyb3VwSW5kZXggPSBub2RlQ291bnQgKyBpO1xuICAgICAgICAgICAgaWYoZ3JvdXBMb29rdXAuaGFzT3duUHJvcGVydHkobm9kZUluZGV4KSkge1xuICAgICAgICAgICAgICAgIExpYi53YXJuKCdOb2RlICcgKyBub2RlSW5kZXggKyAnIGlzIGFscmVhZHkgcGFydCBvZiBhIGdyb3VwLicpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBncm91cExvb2t1cFtub2RlSW5kZXhdID0gZ3JvdXBJbmRleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFByb2Nlc3MgbGlua3NcbiAgICB2YXIgZ3JvdXBlZExpbmtzID0ge1xuICAgICAgICBzb3VyY2U6IFtdLFxuICAgICAgICB0YXJnZXQ6IFtdXG4gICAgfTtcbiAgICBmb3IoaSA9IDA7IGkgPCBsaW5rU3BlYy52YWx1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgdmFsID0gbGlua1NwZWMudmFsdWVbaV07XG4gICAgICAgIC8vIHJlbW92ZSBuZWdhdGl2ZSB2YWx1ZXMsIGJ1dCBrZWVwIHplcm9zIHdpdGggc3BlY2lhbCB0cmVhdG1lbnRcbiAgICAgICAgdmFyIHNvdXJjZSA9IGxpbmtTcGVjLnNvdXJjZVtpXTtcbiAgICAgICAgdmFyIHRhcmdldCA9IGxpbmtTcGVjLnRhcmdldFtpXTtcbiAgICAgICAgaWYoISh2YWwgPiAwICYmIGlzSW5kZXgoc291cmNlLCBub2RlQ291bnQpICYmIGlzSW5kZXgodGFyZ2V0LCBub2RlQ291bnQpKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmUgbGlua3MgdGhhdCBhcmUgd2l0aGluIHRoZSBzYW1lIGdyb3VwXG4gICAgICAgIGlmKGdyb3VwTG9va3VwLmhhc093blByb3BlcnR5KHNvdXJjZSkgJiYgZ3JvdXBMb29rdXAuaGFzT3duUHJvcGVydHkodGFyZ2V0KSAmJiBncm91cExvb2t1cFtzb3VyY2VdID09PSBncm91cExvb2t1cFt0YXJnZXRdKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGlmIGxpbmsgdGFyZ2V0cyBhIG5vZGUgaW4gdGhlIGdyb3VwLCByZWxpbmsgdGFyZ2V0IHRvIHRoYXQgZ3JvdXBcbiAgICAgICAgaWYoZ3JvdXBMb29rdXAuaGFzT3duUHJvcGVydHkodGFyZ2V0KSkge1xuICAgICAgICAgICAgdGFyZ2V0ID0gZ3JvdXBMb29rdXBbdGFyZ2V0XTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGlmIGxpbmsgb3JpZ2luYXRlcyBmcm9tIGEgbm9kZSBpbiBhIGdyb3VwLCByZWxpbmsgc291cmNlIHRvIHRoYXQgZ3JvdXBcbiAgICAgICAgaWYoZ3JvdXBMb29rdXAuaGFzT3duUHJvcGVydHkoc291cmNlKSkge1xuICAgICAgICAgICAgc291cmNlID0gZ3JvdXBMb29rdXBbc291cmNlXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNvdXJjZSA9ICtzb3VyY2U7XG4gICAgICAgIHRhcmdldCA9ICt0YXJnZXQ7XG4gICAgICAgIGxpbmtlZE5vZGVzW3NvdXJjZV0gPSBsaW5rZWROb2Rlc1t0YXJnZXRdID0gdHJ1ZTtcblxuICAgICAgICB2YXIgbGFiZWwgPSAnJztcbiAgICAgICAgaWYobGlua1NwZWMubGFiZWwgJiYgbGlua1NwZWMubGFiZWxbaV0pIGxhYmVsID0gbGlua1NwZWMubGFiZWxbaV07XG5cbiAgICAgICAgdmFyIGNvbmNlbnRyYXRpb25zY2FsZSA9IG51bGw7XG4gICAgICAgIGlmKGxhYmVsICYmIGNvbXBvbmVudHMuaGFzT3duUHJvcGVydHkobGFiZWwpKSBjb25jZW50cmF0aW9uc2NhbGUgPSBjb21wb25lbnRzW2xhYmVsXTtcblxuICAgICAgICBsaW5rcy5wdXNoKHtcbiAgICAgICAgICAgIHBvaW50TnVtYmVyOiBpLFxuICAgICAgICAgICAgbGFiZWw6IGxhYmVsLFxuICAgICAgICAgICAgY29sb3I6IGhhc0xpbmtDb2xvckFycmF5ID8gbGlua1NwZWMuY29sb3JbaV0gOiBsaW5rU3BlYy5jb2xvcixcbiAgICAgICAgICAgIGNvbmNlbnRyYXRpb25zY2FsZTogY29uY2VudHJhdGlvbnNjYWxlLFxuICAgICAgICAgICAgc291cmNlOiBzb3VyY2UsXG4gICAgICAgICAgICB0YXJnZXQ6IHRhcmdldCxcbiAgICAgICAgICAgIHZhbHVlOiArdmFsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGdyb3VwZWRMaW5rcy5zb3VyY2UucHVzaChzb3VyY2UpO1xuICAgICAgICBncm91cGVkTGlua3MudGFyZ2V0LnB1c2godGFyZ2V0KTtcbiAgICB9XG5cbiAgICAvLyBQcm9jZXNzIG5vZGVzXG4gICAgdmFyIHRvdGFsQ291bnQgPSBub2RlQ291bnQgKyBncm91cHMubGVuZ3RoO1xuICAgIHZhciBoYXNOb2RlQ29sb3JBcnJheSA9IGlzQXJyYXlPclR5cGVkQXJyYXkobm9kZVNwZWMuY29sb3IpO1xuICAgIHZhciBub2RlcyA9IFtdO1xuICAgIGZvcihpID0gMDsgaSA8IHRvdGFsQ291bnQ7IGkrKykge1xuICAgICAgICBpZighbGlua2VkTm9kZXNbaV0pIGNvbnRpbnVlO1xuICAgICAgICB2YXIgbCA9IG5vZGVTcGVjLmxhYmVsW2ldO1xuXG4gICAgICAgIG5vZGVzLnB1c2goe1xuICAgICAgICAgICAgZ3JvdXA6IChpID4gbm9kZUNvdW50IC0gMSksXG4gICAgICAgICAgICBjaGlsZHJlbk5vZGVzOiBbXSxcbiAgICAgICAgICAgIHBvaW50TnVtYmVyOiBpLFxuICAgICAgICAgICAgbGFiZWw6IGwsXG4gICAgICAgICAgICBjb2xvcjogaGFzTm9kZUNvbG9yQXJyYXkgPyBub2RlU3BlYy5jb2xvcltpXSA6IG5vZGVTcGVjLmNvbG9yXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgY2lyY3VsYXJpdHkgb24gdGhlIHJlc3VsdGluZyBncmFwaFxuICAgIHZhciBjaXJjdWxhciA9IGZhbHNlO1xuICAgIGlmKGNpcmN1bGFyaXR5UHJlc2VudCh0b3RhbENvdW50LCBncm91cGVkTGlua3Muc291cmNlLCBncm91cGVkTGlua3MudGFyZ2V0KSkge1xuICAgICAgICBjaXJjdWxhciA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY2lyY3VsYXI6IGNpcmN1bGFyLFxuICAgICAgICBsaW5rczogbGlua3MsXG4gICAgICAgIG5vZGVzOiBub2RlcyxcblxuICAgICAgICAvLyBEYXRhIHN0cnVjdHVyZSBmb3IgZ3JvdXBzXG4gICAgICAgIGdyb3VwczogZ3JvdXBzLFxuICAgICAgICBncm91cExvb2t1cDogZ3JvdXBMb29rdXBcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBjaXJjdWxhcml0eVByZXNlbnQobm9kZUxlbiwgc291cmNlcywgdGFyZ2V0cykge1xuICAgIHZhciBub2RlcyA9IExpYi5pbml0MmRBcnJheShub2RlTGVuLCAwKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBNYXRoLm1pbihzb3VyY2VzLmxlbmd0aCwgdGFyZ2V0cy5sZW5ndGgpOyBpKyspIHtcbiAgICAgICAgaWYoTGliLmlzSW5kZXgoc291cmNlc1tpXSwgbm9kZUxlbikgJiYgTGliLmlzSW5kZXgodGFyZ2V0c1tpXSwgbm9kZUxlbikpIHtcbiAgICAgICAgICAgIGlmKHNvdXJjZXNbaV0gPT09IHRhcmdldHNbaV0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsgLy8gc2VsZi1saW5rIHdoaWNoIGlzIGFsc28gYSBzY2Mgb2Ygb25lXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub2Rlc1tzb3VyY2VzW2ldXS5wdXNoKHRhcmdldHNbaV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHNjYyA9IHRhcmphbihub2Rlcyk7XG5cbiAgICAvLyBUYXJqw6FuJ3Mgc3Ryb25nbHkgY29ubmVjdGVkIGNvbXBvbmVudHMgYWxnb3JpdGhtIGNvZGVkIGJ5IE1pa29sYSBMeXNlbmtvXG4gICAgLy8gcmV0dXJucyBhdCBsZWFzdCBvbmUgbm9uLXNpbmd1bGFyIGNvbXBvbmVudCBpZiB0aGVyZSdzIGNpcmN1bGFyaXR5IGluIHRoZSBncmFwaFxuICAgIHJldHVybiBzY2MuY29tcG9uZW50cy5zb21lKGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgcmV0dXJuIGMubGVuZ3RoID4gMTtcbiAgICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciByZXN1bHQgPSBjb252ZXJ0VG9EM1NhbmtleSh0cmFjZSk7XG5cbiAgICByZXR1cm4gd3JhcCh7XG4gICAgICAgIGNpcmN1bGFyOiByZXN1bHQuY2lyY3VsYXIsXG4gICAgICAgIF9ub2RlczogcmVzdWx0Lm5vZGVzLFxuICAgICAgICBfbGlua3M6IHJlc3VsdC5saW5rcyxcblxuICAgICAgICAvLyBEYXRhIHN0cnVjdHVyZSBmb3IgZ3JvdXBpbmdcbiAgICAgICAgX2dyb3VwczogcmVzdWx0Lmdyb3VwcyxcbiAgICAgICAgX2dyb3VwTG9va3VwOiByZXN1bHQuZ3JvdXBMb29rdXAsXG4gICAgfSk7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZVwiOjYwNSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9ndXBcIjo3MTcsXCJzdHJvbmdseS1jb25uZWN0ZWQtY29tcG9uZW50c1wiOjUzMH1dLDExMDU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBub2RlVGV4dE9mZnNldEhvcml6b250YWw6IDQsXG4gICAgbm9kZVRleHRPZmZzZXRWZXJ0aWNhbDogMyxcbiAgICBub2RlUGFkQWNyb3NzOiAxMCxcbiAgICBzYW5rZXlJdGVyYXRpb25zOiA1MCxcbiAgICBmb3JjZUl0ZXJhdGlvbnM6IDUsXG4gICAgZm9yY2VUaWNrc1BlckZyYW1lOiAxMCxcbiAgICBkdXJhdGlvbjogNTAwLFxuICAgIGVhc2U6ICdsaW5lYXInLFxuICAgIGNuOiB7XG4gICAgICAgIHNhbmtleTogJ3NhbmtleScsXG4gICAgICAgIHNhbmtleUxpbmtzOiAnc2Fua2V5LWxpbmtzJyxcbiAgICAgICAgc2Fua2V5TGluazogJ3NhbmtleS1saW5rJyxcbiAgICAgICAgc2Fua2V5Tm9kZVNldDogJ3NhbmtleS1ub2RlLXNldCcsXG4gICAgICAgIHNhbmtleU5vZGU6ICdzYW5rZXktbm9kZScsXG4gICAgICAgIG5vZGVSZWN0OiAnbm9kZS1yZWN0JyxcbiAgICAgICAgbm9kZUNhcHR1cmU6ICdub2RlLWNhcHR1cmUnLFxuICAgICAgICBub2RlQ2VudGVyZWQ6ICdub2RlLWVudGVyZWQnLFxuICAgICAgICBub2RlTGFiZWxHdWlkZTogJ25vZGUtbGFiZWwtZ3VpZGUnLFxuICAgICAgICBub2RlTGFiZWw6ICdub2RlLWxhYmVsJyxcbiAgICAgICAgbm9kZUxhYmVsVGV4dFBhdGg6ICdub2RlLWxhYmVsLXRleHQtcGF0aCdcbiAgICB9XG59O1xuXG59LHt9XSwxMTA2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciB0aW55Y29sb3IgPSBfZGVyZXFfKCd0aW55Y29sb3IyJyk7XG52YXIgaGFuZGxlRG9tYWluRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9kb21haW4nKS5kZWZhdWx0cztcbnZhciBoYW5kbGVIb3ZlckxhYmVsRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVybGFiZWxfZGVmYXVsdHMnKTtcbnZhciBUZW1wbGF0ZSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKTtcbnZhciBoYW5kbGVBcnJheUNvbnRhaW5lckRlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXJyYXlfY29udGFpbmVyX2RlZmF1bHRzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBob3ZlcmxhYmVsRGVmYXVsdCA9IExpYi5leHRlbmREZWVwKGxheW91dC5ob3ZlcmxhYmVsLCB0cmFjZUluLmhvdmVybGFiZWwpO1xuXG4gICAgLy8gbm9kZSBhdHRyaWJ1dGVzXG4gICAgdmFyIG5vZGVJbiA9IHRyYWNlSW4ubm9kZTtcbiAgICB2YXIgbm9kZU91dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcih0cmFjZU91dCwgJ25vZGUnKTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZU5vZGUoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShub2RlSW4sIG5vZGVPdXQsIGF0dHJpYnV0ZXMubm9kZSwgYXR0ciwgZGZsdCk7XG4gICAgfVxuICAgIGNvZXJjZU5vZGUoJ2xhYmVsJyk7XG4gICAgY29lcmNlTm9kZSgnZ3JvdXBzJyk7XG4gICAgY29lcmNlTm9kZSgneCcpO1xuICAgIGNvZXJjZU5vZGUoJ3knKTtcbiAgICBjb2VyY2VOb2RlKCdwYWQnKTtcbiAgICBjb2VyY2VOb2RlKCd0aGlja25lc3MnKTtcbiAgICBjb2VyY2VOb2RlKCdsaW5lLmNvbG9yJyk7XG4gICAgY29lcmNlTm9kZSgnbGluZS53aWR0aCcpO1xuICAgIGNvZXJjZU5vZGUoJ2hvdmVyaW5mbycsIHRyYWNlSW4uaG92ZXJpbmZvKTtcbiAgICBoYW5kbGVIb3ZlckxhYmVsRGVmYXVsdHMobm9kZUluLCBub2RlT3V0LCBjb2VyY2VOb2RlLCBob3ZlcmxhYmVsRGVmYXVsdCk7XG4gICAgY29lcmNlTm9kZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgdmFyIGNvbG9ycyA9IGxheW91dC5jb2xvcndheTtcblxuICAgIHZhciBkZWZhdWx0Tm9kZVBhbGV0dGUgPSBmdW5jdGlvbihpKSB7cmV0dXJuIGNvbG9yc1tpICUgY29sb3JzLmxlbmd0aF07fTtcblxuICAgIGNvZXJjZU5vZGUoJ2NvbG9yJywgbm9kZU91dC5sYWJlbC5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICByZXR1cm4gQ29sb3IuYWRkT3BhY2l0eShkZWZhdWx0Tm9kZVBhbGV0dGUoaSksIDAuOCk7XG4gICAgfSkpO1xuXG4gICAgLy8gbGluayBhdHRyaWJ1dGVzXG4gICAgdmFyIGxpbmtJbiA9IHRyYWNlSW4ubGluayB8fCB7fTtcbiAgICB2YXIgbGlua091dCA9IFRlbXBsYXRlLm5ld0NvbnRhaW5lcih0cmFjZU91dCwgJ2xpbmsnKTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZUxpbmsoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShsaW5rSW4sIGxpbmtPdXQsIGF0dHJpYnV0ZXMubGluaywgYXR0ciwgZGZsdCk7XG4gICAgfVxuICAgIGNvZXJjZUxpbmsoJ2xhYmVsJyk7XG4gICAgY29lcmNlTGluaygnc291cmNlJyk7XG4gICAgY29lcmNlTGluaygndGFyZ2V0Jyk7XG4gICAgY29lcmNlTGluaygndmFsdWUnKTtcbiAgICBjb2VyY2VMaW5rKCdsaW5lLmNvbG9yJyk7XG4gICAgY29lcmNlTGluaygnbGluZS53aWR0aCcpO1xuICAgIGNvZXJjZUxpbmsoJ2hvdmVyaW5mbycsIHRyYWNlSW4uaG92ZXJpbmZvKTtcbiAgICBoYW5kbGVIb3ZlckxhYmVsRGVmYXVsdHMobGlua0luLCBsaW5rT3V0LCBjb2VyY2VMaW5rLCBob3ZlcmxhYmVsRGVmYXVsdCk7XG4gICAgY29lcmNlTGluaygnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgdmFyIGRlZmF1bHRMaW5rQ29sb3IgPSB0aW55Y29sb3IobGF5b3V0LnBhcGVyX2JnY29sb3IpLmdldEx1bWluYW5jZSgpIDwgMC4zMzMgP1xuICAgICAgICAgICAgICAgICdyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNiknIDpcbiAgICAgICAgICAgICAgICAncmdiYSgwLCAwLCAwLCAwLjIpJztcblxuICAgIGNvZXJjZUxpbmsoJ2NvbG9yJywgTGliLnJlcGVhdChkZWZhdWx0TGlua0NvbG9yLCBsaW5rT3V0LnZhbHVlLmxlbmd0aCkpO1xuXG4gICAgaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyhsaW5rSW4sIGxpbmtPdXQsIHtcbiAgICAgICAgbmFtZTogJ2NvbG9yc2NhbGVzJyxcbiAgICAgICAgaGFuZGxlSXRlbURlZmF1bHRzOiBjb25jZW50cmF0aW9uc2NhbGVzRGVmYXVsdHNcbiAgICB9KTtcblxuICAgIGhhbmRsZURvbWFpbkRlZmF1bHRzKHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICBjb2VyY2UoJ29yaWVudGF0aW9uJyk7XG4gICAgY29lcmNlKCd2YWx1ZWZvcm1hdCcpO1xuICAgIGNvZXJjZSgndmFsdWVzdWZmaXgnKTtcblxuICAgIHZhciBkZmx0QXJyYW5nZW1lbnQ7XG4gICAgaWYobm9kZU91dC54Lmxlbmd0aCAmJiBub2RlT3V0LnkubGVuZ3RoKSB7XG4gICAgICAgIGRmbHRBcnJhbmdlbWVudCA9ICdmcmVlZm9ybSc7XG4gICAgfVxuICAgIGNvZXJjZSgnYXJyYW5nZW1lbnQnLCBkZmx0QXJyYW5nZW1lbnQpO1xuXG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAndGV4dGZvbnQnLCBMaWIuZXh0ZW5kRmxhdCh7fSwgbGF5b3V0LmZvbnQpKTtcblxuICAgIC8vIGRpc2FibGUgMUQgdHJhbnNmb3JtcyAtIGFycmF5cyBoZXJlIGFyZSAxRCBidXQgdGhlaXIgbGVuZ3Rocy9tZWFuaW5nc1xuICAgIC8vIGRvbid0IG1hdGNoLCBiZXR3ZWVuIG5vZGVzIGFuZCBsaW5rc1xuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBudWxsO1xufTtcblxuZnVuY3Rpb24gY29uY2VudHJhdGlvbnNjYWxlc0RlZmF1bHRzKEluLCBPdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShJbiwgT3V0LCBhdHRyaWJ1dGVzLmxpbmsuY29sb3JzY2FsZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnbGFiZWwnKTtcbiAgICBjb2VyY2UoJ2NtaW4nKTtcbiAgICBjb2VyY2UoJ2NtYXgnKTtcbiAgICBjb2VyY2UoJ2NvbG9yc2NhbGUnKTtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcmxhYmVsX2RlZmF1bHRzXCI6NjMwLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdF9hcGkvcGxvdF90ZW1wbGF0ZVwiOjc1NyxcIi4uLy4uL3Bsb3RzL2FycmF5X2NvbnRhaW5lcl9kZWZhdWx0c1wiOjc2MyxcIi4uLy4uL3Bsb3RzL2RvbWFpblwiOjc5MixcIi4vYXR0cmlidXRlc1wiOjExMDIsXCJ0aW55Y29sb3IyXCI6NTM3fV0sMTEwNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdzYW5rZXknLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuL2Jhc2VfcGxvdCcpLFxuICAgIHNlbGVjdFBvaW50czogX2RlcmVxXygnLi9zZWxlY3QuanMnKSxcbiAgICBjYXRlZ29yaWVzOiBbJ25vT3BhY2l0eSddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuL2F0dHJpYnV0ZXNcIjoxMTAyLFwiLi9iYXNlX3Bsb3RcIjoxMTAzLFwiLi9jYWxjXCI6MTEwNCxcIi4vZGVmYXVsdHNcIjoxMTA2LFwiLi9wbG90XCI6MTEwOCxcIi4vc2VsZWN0LmpzXCI6MTExMH1dLDExMDg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIHJlbmRlciA9IF9kZXJlcV8oJy4vcmVuZGVyJyk7XG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgY24gPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpLmNuO1xuXG52YXIgXyA9IExpYi5fO1xuXG5mdW5jdGlvbiByZW5kZXJhYmxlVmFsdWVQcmVzZW50KGQpIHtyZXR1cm4gZCAhPT0gJyc7fVxuXG5mdW5jdGlvbiBvd25UcmFjZShzZWxlY3Rpb24sIGQpIHtcbiAgICByZXR1cm4gc2VsZWN0aW9uLmZpbHRlcihmdW5jdGlvbihzKSB7cmV0dXJuIHMua2V5ID09PSBkLnRyYWNlSWQ7fSk7XG59XG5cbmZ1bmN0aW9uIG1ha2VUcmFuc2x1Y2VudChlbGVtZW50LCBhbHBoYSkge1xuICAgIGQzLnNlbGVjdChlbGVtZW50KVxuICAgICAgICAuc2VsZWN0KCdwYXRoJylcbiAgICAgICAgLnN0eWxlKCdmaWxsLW9wYWNpdHknLCBhbHBoYSk7XG4gICAgZDMuc2VsZWN0KGVsZW1lbnQpXG4gICAgICAgIC5zZWxlY3QoJ3JlY3QnKVxuICAgICAgICAuc3R5bGUoJ2ZpbGwtb3BhY2l0eScsIGFscGhhKTtcbn1cblxuZnVuY3Rpb24gbWFrZVRleHRDb250cmFzdHkoZWxlbWVudCkge1xuICAgIGQzLnNlbGVjdChlbGVtZW50KVxuICAgICAgICAuc2VsZWN0KCd0ZXh0Lm5hbWUnKVxuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCAnYmxhY2snKTtcbn1cblxuZnVuY3Rpb24gcmVsYXRlZExpbmtzKGQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24obCkge1xuICAgICAgICByZXR1cm4gZC5ub2RlLnNvdXJjZUxpbmtzLmluZGV4T2YobC5saW5rKSAhPT0gLTEgfHwgZC5ub2RlLnRhcmdldExpbmtzLmluZGV4T2YobC5saW5rKSAhPT0gLTE7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gcmVsYXRlZE5vZGVzKGwpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oZCkge1xuICAgICAgICByZXR1cm4gZC5ub2RlLnNvdXJjZUxpbmtzLmluZGV4T2YobC5saW5rKSAhPT0gLTEgfHwgZC5ub2RlLnRhcmdldExpbmtzLmluZGV4T2YobC5saW5rKSAhPT0gLTE7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gbm9kZUhvdmVyZWRTdHlsZShzYW5rZXlOb2RlLCBkLCBzYW5rZXkpIHtcbiAgICBpZihkICYmIHNhbmtleSkge1xuICAgICAgICBvd25UcmFjZShzYW5rZXksIGQpXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCcuJyArIGNuLnNhbmtleUxpbmspXG4gICAgICAgICAgICAuZmlsdGVyKHJlbGF0ZWRMaW5rcyhkKSlcbiAgICAgICAgICAgIC5jYWxsKGxpbmtIb3ZlcmVkU3R5bGUuYmluZCgwLCBkLCBzYW5rZXksIGZhbHNlKSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBub2RlTm9uSG92ZXJlZFN0eWxlKHNhbmtleU5vZGUsIGQsIHNhbmtleSkge1xuICAgIGlmKGQgJiYgc2Fua2V5KSB7XG4gICAgICAgIG93blRyYWNlKHNhbmtleSwgZClcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJy4nICsgY24uc2Fua2V5TGluaylcbiAgICAgICAgICAgIC5maWx0ZXIocmVsYXRlZExpbmtzKGQpKVxuICAgICAgICAgICAgLmNhbGwobGlua05vbkhvdmVyZWRTdHlsZS5iaW5kKDAsIGQsIHNhbmtleSwgZmFsc2UpKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGxpbmtIb3ZlcmVkU3R5bGUoZCwgc2Fua2V5LCB2aXNpdE5vZGVzLCBzYW5rZXlMaW5rKSB7XG4gICAgdmFyIGxhYmVsID0gc2Fua2V5TGluay5kYXR1bSgpLmxpbmsubGFiZWw7XG5cbiAgICBzYW5rZXlMaW5rLnN0eWxlKCdmaWxsLW9wYWNpdHknLCBmdW5jdGlvbihsKSB7XG4gICAgICAgIGlmKCFsLmxpbmsuY29uY2VudHJhdGlvbnNjYWxlKSB7XG4gICAgICAgICAgICByZXR1cm4gMC40O1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBpZihsYWJlbCkge1xuICAgICAgICBvd25UcmFjZShzYW5rZXksIGQpXG4gICAgICAgICAgICAuc2VsZWN0QWxsKCcuJyArIGNuLnNhbmtleUxpbmspXG4gICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uKGwpIHtyZXR1cm4gbC5saW5rLmxhYmVsID09PSBsYWJlbDt9KVxuICAgICAgICAgICAgLnN0eWxlKCdmaWxsLW9wYWNpdHknLCBmdW5jdGlvbihsKSB7XG4gICAgICAgICAgICAgICAgaWYoIWwubGluay5jb25jZW50cmF0aW9uc2NhbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDAuNDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZih2aXNpdE5vZGVzKSB7XG4gICAgICAgIG93blRyYWNlKHNhbmtleSwgZClcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJy4nICsgY24uc2Fua2V5Tm9kZSlcbiAgICAgICAgICAgIC5maWx0ZXIocmVsYXRlZE5vZGVzKGQpKVxuICAgICAgICAgICAgLmNhbGwobm9kZUhvdmVyZWRTdHlsZSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBsaW5rTm9uSG92ZXJlZFN0eWxlKGQsIHNhbmtleSwgdmlzaXROb2Rlcywgc2Fua2V5TGluaykge1xuICAgIHZhciBsYWJlbCA9IHNhbmtleUxpbmsuZGF0dW0oKS5saW5rLmxhYmVsO1xuXG4gICAgc2Fua2V5TGluay5zdHlsZSgnZmlsbC1vcGFjaXR5JywgZnVuY3Rpb24oZCkge3JldHVybiBkLnRpbnlDb2xvckFscGhhO30pO1xuICAgIGlmKGxhYmVsKSB7XG4gICAgICAgIG93blRyYWNlKHNhbmtleSwgZClcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoJy4nICsgY24uc2Fua2V5TGluaylcbiAgICAgICAgICAgIC5maWx0ZXIoZnVuY3Rpb24obCkge3JldHVybiBsLmxpbmsubGFiZWwgPT09IGxhYmVsO30pXG4gICAgICAgICAgICAuc3R5bGUoJ2ZpbGwtb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC50aW55Q29sb3JBbHBoYTt9KTtcbiAgICB9XG5cbiAgICBpZih2aXNpdE5vZGVzKSB7XG4gICAgICAgIG93blRyYWNlKHNhbmtleSwgZClcbiAgICAgICAgICAgIC5zZWxlY3RBbGwoY24uc2Fua2V5Tm9kZSlcbiAgICAgICAgICAgIC5maWx0ZXIocmVsYXRlZE5vZGVzKGQpKVxuICAgICAgICAgICAgLmNhbGwobm9kZU5vbkhvdmVyZWRTdHlsZSk7XG4gICAgfVxufVxuXG4vLyBkb2VzIG5vdCBzdXBwb3J0IGFycmF5IHZhbHVlcyBmb3Igbm93XG5mdW5jdGlvbiBjYXN0SG92ZXJPcHRpb24odHJhY2UsIGF0dHIpIHtcbiAgICB2YXIgbGFiZWxPcHRzID0gdHJhY2UuaG92ZXJsYWJlbCB8fCB7fTtcbiAgICB2YXIgdmFsID0gTGliLm5lc3RlZFByb3BlcnR5KGxhYmVsT3B0cywgYXR0cikuZ2V0KCk7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsKSA/IGZhbHNlIDogdmFsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIGNhbGNEYXRhKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgc3ZnID0gZnVsbExheW91dC5fcGFwZXI7XG4gICAgdmFyIHNpemUgPSBmdWxsTGF5b3V0Ll9zaXplO1xuXG4gICAgLy8gc3Rhc2ggaW5pdGlhbCB2aWV3XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGdkLl9mdWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihnZC5fZnVsbERhdGFbaV0udHlwZSAhPT0gY24uc2Fua2V5KSBjb250aW51ZTtcbiAgICAgICAgaWYoIWdkLl9mdWxsRGF0YVtpXS5fdmlld0luaXRpYWwpIHtcbiAgICAgICAgICAgIHZhciBub2RlID0gZ2QuX2Z1bGxEYXRhW2ldLm5vZGU7XG4gICAgICAgICAgICBnZC5fZnVsbERhdGFbaV0uX3ZpZXdJbml0aWFsID0ge1xuICAgICAgICAgICAgICAgIG5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBzOiBub2RlLmdyb3Vwcy5zbGljZSgpLFxuICAgICAgICAgICAgICAgICAgICB4OiBub2RlLnguc2xpY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgeTogbm9kZS55LnNsaWNlKClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGxpbmtTZWxlY3QgPSBmdW5jdGlvbihlbGVtZW50LCBkKSB7XG4gICAgICAgIHZhciBldnQgPSBkLmxpbms7XG4gICAgICAgIGV2dC5vcmlnaW5hbEV2ZW50ID0gZDMuZXZlbnQ7XG4gICAgICAgIGdkLl9ob3ZlcmRhdGEgPSBbZXZ0XTtcbiAgICAgICAgRnguY2xpY2soZ2QsIHsgdGFyZ2V0OiB0cnVlIH0pO1xuICAgIH07XG5cbiAgICB2YXIgbGlua0hvdmVyID0gZnVuY3Rpb24oZWxlbWVudCwgZCwgc2Fua2V5KSB7XG4gICAgICAgIGlmKGdkLl9mdWxsTGF5b3V0LmhvdmVybW9kZSA9PT0gZmFsc2UpIHJldHVybjtcbiAgICAgICAgZDMuc2VsZWN0KGVsZW1lbnQpLmNhbGwobGlua0hvdmVyZWRTdHlsZS5iaW5kKDAsIGQsIHNhbmtleSwgdHJ1ZSkpO1xuICAgICAgICBpZihkLmxpbmsudHJhY2UubGluay5ob3ZlcmluZm8gIT09ICdza2lwJykge1xuICAgICAgICAgICAgZC5saW5rLmZ1bGxEYXRhID0gZC5saW5rLnRyYWNlO1xuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X2hvdmVyJywge1xuICAgICAgICAgICAgICAgIGV2ZW50OiBkMy5ldmVudCxcbiAgICAgICAgICAgICAgICBwb2ludHM6IFtkLmxpbmtdXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgc291cmNlTGFiZWwgPSBfKGdkLCAnc291cmNlOicpICsgJyAnO1xuICAgIHZhciB0YXJnZXRMYWJlbCA9IF8oZ2QsICd0YXJnZXQ6JykgKyAnICc7XG4gICAgdmFyIGNvbmNlbnRyYXRpb25MYWJlbCA9IF8oZ2QsICdjb25jZW50cmF0aW9uOicpICsgJyAnO1xuICAgIHZhciBpbmNvbWluZ0xhYmVsID0gXyhnZCwgJ2luY29taW5nIGZsb3cgY291bnQ6JykgKyAnICc7XG4gICAgdmFyIG91dGdvaW5nTGFiZWwgPSBfKGdkLCAnb3V0Z29pbmcgZmxvdyBjb3VudDonKSArICcgJztcblxuICAgIHZhciBsaW5rSG92ZXJGb2xsb3cgPSBmdW5jdGlvbihlbGVtZW50LCBkKSB7XG4gICAgICAgIGlmKGdkLl9mdWxsTGF5b3V0LmhvdmVybW9kZSA9PT0gZmFsc2UpIHJldHVybjtcbiAgICAgICAgdmFyIG9iaiA9IGQubGluay50cmFjZS5saW5rO1xuICAgICAgICBpZihvYmouaG92ZXJpbmZvID09PSAnbm9uZScgfHwgb2JqLmhvdmVyaW5mbyA9PT0gJ3NraXAnKSByZXR1cm47XG5cbiAgICAgICAgdmFyIGhvdmVySXRlbXMgPSBbXTtcblxuICAgICAgICBmdW5jdGlvbiBob3ZlckNlbnRlclBvc2l0aW9uKGxpbmspIHtcbiAgICAgICAgICAgIHZhciBob3ZlckNlbnRlclgsIGhvdmVyQ2VudGVyWTtcbiAgICAgICAgICAgIGlmKGxpbmsuY2lyY3VsYXIpIHtcbiAgICAgICAgICAgICAgICBob3ZlckNlbnRlclggPSAobGluay5jaXJjdWxhclBhdGhEYXRhLmxlZnRJbm5lckV4dGVudCArIGxpbmsuY2lyY3VsYXJQYXRoRGF0YS5yaWdodElubmVyRXh0ZW50KSAvIDIgKyBkLnBhcmVudC50cmFuc2xhdGVYO1xuICAgICAgICAgICAgICAgIGhvdmVyQ2VudGVyWSA9IGxpbmsuY2lyY3VsYXJQYXRoRGF0YS52ZXJ0aWNhbEZ1bGxFeHRlbnQgKyBkLnBhcmVudC50cmFuc2xhdGVZO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBob3ZlckNlbnRlclggPSAobGluay5zb3VyY2UueDEgKyBsaW5rLnRhcmdldC54MCkgLyAyICsgZC5wYXJlbnQudHJhbnNsYXRlWDtcbiAgICAgICAgICAgICAgICBob3ZlckNlbnRlclkgPSAobGluay55MCArIGxpbmsueTEpIC8gMiArIGQucGFyZW50LnRyYW5zbGF0ZVk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gW2hvdmVyQ2VudGVyWCwgaG92ZXJDZW50ZXJZXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZvciBlYWNoIHJlbGF0ZWQgbGlua3MsIGNyZWF0ZSBhIGhvdmVySXRlbVxuICAgICAgICB2YXIgYW5jaG9ySW5kZXggPSAwO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgZC5mbG93LmxpbmtzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgbGluayA9IGQuZmxvdy5saW5rc1tpXTtcbiAgICAgICAgICAgIGlmKGdkLl9mdWxsTGF5b3V0LmhvdmVybW9kZSA9PT0gJ2Nsb3Nlc3QnICYmIGQubGluay5wb2ludE51bWJlciAhPT0gbGluay5wb2ludE51bWJlcikgY29udGludWU7XG4gICAgICAgICAgICBpZihkLmxpbmsucG9pbnROdW1iZXIgPT09IGxpbmsucG9pbnROdW1iZXIpIGFuY2hvckluZGV4ID0gaTtcbiAgICAgICAgICAgIGxpbmsuZnVsbERhdGEgPSBsaW5rLnRyYWNlO1xuICAgICAgICAgICAgb2JqID0gZC5saW5rLnRyYWNlLmxpbms7XG4gICAgICAgICAgICB2YXIgaG92ZXJDZW50ZXIgPSBob3ZlckNlbnRlclBvc2l0aW9uKGxpbmspO1xuICAgICAgICAgICAgdmFyIGhvdmVydGVtcGxhdGVMYWJlbHMgPSB7dmFsdWVMYWJlbDogZDMuZm9ybWF0KGQudmFsdWVGb3JtYXQpKGxpbmsudmFsdWUpICsgZC52YWx1ZVN1ZmZpeH07XG5cbiAgICAgICAgICAgIGhvdmVySXRlbXMucHVzaCh7XG4gICAgICAgICAgICAgICAgeDogaG92ZXJDZW50ZXJbMF0sXG4gICAgICAgICAgICAgICAgeTogaG92ZXJDZW50ZXJbMV0sXG4gICAgICAgICAgICAgICAgbmFtZTogaG92ZXJ0ZW1wbGF0ZUxhYmVscy52YWx1ZUxhYmVsLFxuICAgICAgICAgICAgICAgIHRleHQ6IFtcbiAgICAgICAgICAgICAgICAgICAgbGluay5sYWJlbCB8fCAnJyxcbiAgICAgICAgICAgICAgICAgICAgc291cmNlTGFiZWwgKyBsaW5rLnNvdXJjZS5sYWJlbCxcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TGFiZWwgKyBsaW5rLnRhcmdldC5sYWJlbCxcbiAgICAgICAgICAgICAgICAgICAgbGluay5jb25jZW50cmF0aW9uc2NhbGUgPyBjb25jZW50cmF0aW9uTGFiZWwgKyBkMy5mb3JtYXQoJyUwLjJmJykobGluay5mbG93LmxhYmVsQ29uY2VudHJhdGlvbikgOiAnJ1xuICAgICAgICAgICAgICAgIF0uZmlsdGVyKHJlbmRlcmFibGVWYWx1ZVByZXNlbnQpLmpvaW4oJzxicj4nKSxcbiAgICAgICAgICAgICAgICBjb2xvcjogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2JnY29sb3InKSB8fCBDb2xvci5hZGRPcGFjaXR5KGxpbmsuY29sb3IsIDEpLFxuICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiBjYXN0SG92ZXJPcHRpb24ob2JqLCAnYm9yZGVyY29sb3InKSxcbiAgICAgICAgICAgICAgICBmb250RmFtaWx5OiBjYXN0SG92ZXJPcHRpb24ob2JqLCAnZm9udC5mYW1pbHknKSxcbiAgICAgICAgICAgICAgICBmb250U2l6ZTogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2ZvbnQuc2l6ZScpLFxuICAgICAgICAgICAgICAgIGZvbnRDb2xvcjogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2ZvbnQuY29sb3InKSxcbiAgICAgICAgICAgICAgICBuYW1lTGVuZ3RoOiBjYXN0SG92ZXJPcHRpb24ob2JqLCAnbmFtZWxlbmd0aCcpLFxuICAgICAgICAgICAgICAgIHRleHRBbGlnbjogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2FsaWduJyksXG4gICAgICAgICAgICAgICAgaWRlYWxBbGlnbjogZDMuZXZlbnQueCA8IGhvdmVyQ2VudGVyWzBdID8gJ3JpZ2h0JyA6ICdsZWZ0JyxcblxuICAgICAgICAgICAgICAgIGhvdmVydGVtcGxhdGU6IG9iai5ob3ZlcnRlbXBsYXRlLFxuICAgICAgICAgICAgICAgIGhvdmVydGVtcGxhdGVMYWJlbHM6IGhvdmVydGVtcGxhdGVMYWJlbHMsXG4gICAgICAgICAgICAgICAgZXZlbnREYXRhOiBbbGlua11cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRvb2x0aXBzID0gRngubG9uZUhvdmVyKGhvdmVySXRlbXMsIHtcbiAgICAgICAgICAgIGNvbnRhaW5lcjogZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCksXG4gICAgICAgICAgICBvdXRlckNvbnRhaW5lcjogZnVsbExheW91dC5fcGFwZXIubm9kZSgpLFxuICAgICAgICAgICAgZ2Q6IGdkLFxuICAgICAgICAgICAgYW5jaG9ySW5kZXg6IGFuY2hvckluZGV4XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRvb2x0aXBzLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgdG9vbHRpcCA9IHRoaXM7XG4gICAgICAgICAgICBpZighZC5saW5rLmNvbmNlbnRyYXRpb25zY2FsZSkge1xuICAgICAgICAgICAgICAgIG1ha2VUcmFuc2x1Y2VudCh0b29sdGlwLCAwLjY1KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1ha2VUZXh0Q29udHJhc3R5KHRvb2x0aXApO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgdmFyIGxpbmtVbmhvdmVyID0gZnVuY3Rpb24oZWxlbWVudCwgZCwgc2Fua2V5KSB7XG4gICAgICAgIGlmKGdkLl9mdWxsTGF5b3V0LmhvdmVybW9kZSA9PT0gZmFsc2UpIHJldHVybjtcbiAgICAgICAgZDMuc2VsZWN0KGVsZW1lbnQpLmNhbGwobGlua05vbkhvdmVyZWRTdHlsZS5iaW5kKDAsIGQsIHNhbmtleSwgdHJ1ZSkpO1xuICAgICAgICBpZihkLmxpbmsudHJhY2UubGluay5ob3ZlcmluZm8gIT09ICdza2lwJykge1xuICAgICAgICAgICAgZC5saW5rLmZ1bGxEYXRhID0gZC5saW5rLnRyYWNlO1xuICAgICAgICAgICAgZ2QuZW1pdCgncGxvdGx5X3VuaG92ZXInLCB7XG4gICAgICAgICAgICAgICAgZXZlbnQ6IGQzLmV2ZW50LFxuICAgICAgICAgICAgICAgIHBvaW50czogW2QubGlua11cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgRngubG9uZVVuaG92ZXIoZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCkpO1xuICAgIH07XG5cbiAgICB2YXIgbm9kZVNlbGVjdCA9IGZ1bmN0aW9uKGVsZW1lbnQsIGQsIHNhbmtleSkge1xuICAgICAgICB2YXIgZXZ0ID0gZC5ub2RlO1xuICAgICAgICBldnQub3JpZ2luYWxFdmVudCA9IGQzLmV2ZW50O1xuICAgICAgICBnZC5faG92ZXJkYXRhID0gW2V2dF07XG4gICAgICAgIGQzLnNlbGVjdChlbGVtZW50KS5jYWxsKG5vZGVOb25Ib3ZlcmVkU3R5bGUsIGQsIHNhbmtleSk7XG4gICAgICAgIEZ4LmNsaWNrKGdkLCB7IHRhcmdldDogdHJ1ZSB9KTtcbiAgICB9O1xuXG4gICAgdmFyIG5vZGVIb3ZlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIGQsIHNhbmtleSkge1xuICAgICAgICBpZihnZC5fZnVsbExheW91dC5ob3Zlcm1vZGUgPT09IGZhbHNlKSByZXR1cm47XG4gICAgICAgIGQzLnNlbGVjdChlbGVtZW50KS5jYWxsKG5vZGVIb3ZlcmVkU3R5bGUsIGQsIHNhbmtleSk7XG4gICAgICAgIGlmKGQubm9kZS50cmFjZS5ub2RlLmhvdmVyaW5mbyAhPT0gJ3NraXAnKSB7XG4gICAgICAgICAgICBkLm5vZGUuZnVsbERhdGEgPSBkLm5vZGUudHJhY2U7XG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfaG92ZXInLCB7XG4gICAgICAgICAgICAgICAgZXZlbnQ6IGQzLmV2ZW50LFxuICAgICAgICAgICAgICAgIHBvaW50czogW2Qubm9kZV1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHZhciBub2RlSG92ZXJGb2xsb3cgPSBmdW5jdGlvbihlbGVtZW50LCBkKSB7XG4gICAgICAgIGlmKGdkLl9mdWxsTGF5b3V0LmhvdmVybW9kZSA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgICAgICB2YXIgb2JqID0gZC5ub2RlLnRyYWNlLm5vZGU7XG4gICAgICAgIGlmKG9iai5ob3ZlcmluZm8gPT09ICdub25lJyB8fCBvYmouaG92ZXJpbmZvID09PSAnc2tpcCcpIHJldHVybjtcbiAgICAgICAgdmFyIG5vZGVSZWN0ID0gZDMuc2VsZWN0KGVsZW1lbnQpLnNlbGVjdCgnLicgKyBjbi5ub2RlUmVjdCk7XG4gICAgICAgIHZhciByb290QkJveCA9IGdkLl9mdWxsTGF5b3V0Ll9wYXBlcmRpdi5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHZhciBib3VuZGluZ0JveCA9IG5vZGVSZWN0Lm5vZGUoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdmFyIGhvdmVyQ2VudGVyWDAgPSBib3VuZGluZ0JveC5sZWZ0IC0gMiAtIHJvb3RCQm94LmxlZnQ7XG4gICAgICAgIHZhciBob3ZlckNlbnRlclgxID0gYm91bmRpbmdCb3gucmlnaHQgKyAyIC0gcm9vdEJCb3gubGVmdDtcbiAgICAgICAgdmFyIGhvdmVyQ2VudGVyWSA9IGJvdW5kaW5nQm94LnRvcCArIGJvdW5kaW5nQm94LmhlaWdodCAvIDQgLSByb290QkJveC50b3A7XG5cbiAgICAgICAgdmFyIGhvdmVydGVtcGxhdGVMYWJlbHMgPSB7dmFsdWVMYWJlbDogZDMuZm9ybWF0KGQudmFsdWVGb3JtYXQpKGQubm9kZS52YWx1ZSkgKyBkLnZhbHVlU3VmZml4fTtcbiAgICAgICAgZC5ub2RlLmZ1bGxEYXRhID0gZC5ub2RlLnRyYWNlO1xuXG4gICAgICAgIHZhciB0b29sdGlwID0gRngubG9uZUhvdmVyKHtcbiAgICAgICAgICAgIHgwOiBob3ZlckNlbnRlclgwLFxuICAgICAgICAgICAgeDE6IGhvdmVyQ2VudGVyWDEsXG4gICAgICAgICAgICB5OiBob3ZlckNlbnRlclksXG4gICAgICAgICAgICBuYW1lOiBkMy5mb3JtYXQoZC52YWx1ZUZvcm1hdCkoZC5ub2RlLnZhbHVlKSArIGQudmFsdWVTdWZmaXgsXG4gICAgICAgICAgICB0ZXh0OiBbXG4gICAgICAgICAgICAgICAgZC5ub2RlLmxhYmVsLFxuICAgICAgICAgICAgICAgIGluY29taW5nTGFiZWwgKyBkLm5vZGUudGFyZ2V0TGlua3MubGVuZ3RoLFxuICAgICAgICAgICAgICAgIG91dGdvaW5nTGFiZWwgKyBkLm5vZGUuc291cmNlTGlua3MubGVuZ3RoXG4gICAgICAgICAgICBdLmZpbHRlcihyZW5kZXJhYmxlVmFsdWVQcmVzZW50KS5qb2luKCc8YnI+JyksXG4gICAgICAgICAgICBjb2xvcjogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2JnY29sb3InKSB8fCBkLnRpbnlDb2xvckh1ZSxcbiAgICAgICAgICAgIGJvcmRlckNvbG9yOiBjYXN0SG92ZXJPcHRpb24ob2JqLCAnYm9yZGVyY29sb3InKSxcbiAgICAgICAgICAgIGZvbnRGYW1pbHk6IGNhc3RIb3Zlck9wdGlvbihvYmosICdmb250LmZhbWlseScpLFxuICAgICAgICAgICAgZm9udFNpemU6IGNhc3RIb3Zlck9wdGlvbihvYmosICdmb250LnNpemUnKSxcbiAgICAgICAgICAgIGZvbnRDb2xvcjogY2FzdEhvdmVyT3B0aW9uKG9iaiwgJ2ZvbnQuY29sb3InKSxcbiAgICAgICAgICAgIG5hbWVMZW5ndGg6IGNhc3RIb3Zlck9wdGlvbihvYmosICduYW1lbGVuZ3RoJyksXG4gICAgICAgICAgICB0ZXh0QWxpZ246IGNhc3RIb3Zlck9wdGlvbihvYmosICdhbGlnbicpLFxuICAgICAgICAgICAgaWRlYWxBbGlnbjogJ2xlZnQnLFxuXG4gICAgICAgICAgICBob3ZlcnRlbXBsYXRlOiBvYmouaG92ZXJ0ZW1wbGF0ZSxcbiAgICAgICAgICAgIGhvdmVydGVtcGxhdGVMYWJlbHM6IGhvdmVydGVtcGxhdGVMYWJlbHMsXG4gICAgICAgICAgICBldmVudERhdGE6IFtkLm5vZGVdXG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIGNvbnRhaW5lcjogZnVsbExheW91dC5faG92ZXJsYXllci5ub2RlKCksXG4gICAgICAgICAgICBvdXRlckNvbnRhaW5lcjogZnVsbExheW91dC5fcGFwZXIubm9kZSgpLFxuICAgICAgICAgICAgZ2Q6IGdkXG4gICAgICAgIH0pO1xuXG4gICAgICAgIG1ha2VUcmFuc2x1Y2VudCh0b29sdGlwLCAwLjg1KTtcbiAgICAgICAgbWFrZVRleHRDb250cmFzdHkodG9vbHRpcCk7XG4gICAgfTtcblxuICAgIHZhciBub2RlVW5ob3ZlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIGQsIHNhbmtleSkge1xuICAgICAgICBpZihnZC5fZnVsbExheW91dC5ob3Zlcm1vZGUgPT09IGZhbHNlKSByZXR1cm47XG4gICAgICAgIGQzLnNlbGVjdChlbGVtZW50KS5jYWxsKG5vZGVOb25Ib3ZlcmVkU3R5bGUsIGQsIHNhbmtleSk7XG4gICAgICAgIGlmKGQubm9kZS50cmFjZS5ub2RlLmhvdmVyaW5mbyAhPT0gJ3NraXAnKSB7XG4gICAgICAgICAgICBkLm5vZGUuZnVsbERhdGEgPSBkLm5vZGUudHJhY2U7XG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfdW5ob3ZlcicsIHtcbiAgICAgICAgICAgICAgICBldmVudDogZDMuZXZlbnQsXG4gICAgICAgICAgICAgICAgcG9pbnRzOiBbZC5ub2RlXVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBGeC5sb25lVW5ob3ZlcihmdWxsTGF5b3V0Ll9ob3ZlcmxheWVyLm5vZGUoKSk7XG4gICAgfTtcblxuICAgIHJlbmRlcihcbiAgICAgICAgZ2QsXG4gICAgICAgIHN2ZyxcbiAgICAgICAgY2FsY0RhdGEsXG4gICAgICAgIHtcbiAgICAgICAgICAgIHdpZHRoOiBzaXplLncsXG4gICAgICAgICAgICBoZWlnaHQ6IHNpemUuaCxcbiAgICAgICAgICAgIG1hcmdpbjoge1xuICAgICAgICAgICAgICAgIHQ6IHNpemUudCxcbiAgICAgICAgICAgICAgICByOiBzaXplLnIsXG4gICAgICAgICAgICAgICAgYjogc2l6ZS5iLFxuICAgICAgICAgICAgICAgIGw6IHNpemUubFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBsaW5rRXZlbnRzOiB7XG4gICAgICAgICAgICAgICAgaG92ZXI6IGxpbmtIb3ZlcixcbiAgICAgICAgICAgICAgICBmb2xsb3c6IGxpbmtIb3ZlckZvbGxvdyxcbiAgICAgICAgICAgICAgICB1bmhvdmVyOiBsaW5rVW5ob3ZlcixcbiAgICAgICAgICAgICAgICBzZWxlY3Q6IGxpbmtTZWxlY3RcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBub2RlRXZlbnRzOiB7XG4gICAgICAgICAgICAgICAgaG92ZXI6IG5vZGVIb3ZlcixcbiAgICAgICAgICAgICAgICBmb2xsb3c6IG5vZGVIb3ZlckZvbGxvdyxcbiAgICAgICAgICAgICAgICB1bmhvdmVyOiBub2RlVW5ob3ZlcixcbiAgICAgICAgICAgICAgICBzZWxlY3Q6IG5vZGVTZWxlY3RcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICk7XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi4vLi4vbGliXCI6NzE5LFwiLi9jb25zdGFudHNcIjoxMTA1LFwiLi9yZW5kZXJcIjoxMTA5LFwiZDNcIjoxNjN9XSwxMTA5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciB0aW55Y29sb3IgPSBfZGVyZXFfKCd0aW55Y29sb3IyJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIGQzU2Fua2V5ID0gX2RlcmVxXygnQHBsb3RseS9kMy1zYW5rZXknKTtcbnZhciBkM1NhbmtleUNpcmN1bGFyID0gX2RlcmVxXygnQHBsb3RseS9kMy1zYW5rZXktY2lyY3VsYXInKTtcbnZhciBkM0ZvcmNlID0gX2RlcmVxXygnZDMtZm9yY2UnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBndXAgPSBfZGVyZXFfKCcuLi8uLi9saWIvZ3VwJyk7XG52YXIga2V5RnVuID0gZ3VwLmtleUZ1bjtcbnZhciByZXBlYXQgPSBndXAucmVwZWF0O1xudmFyIHVud3JhcCA9IGd1cC51bndyYXA7XG52YXIgaW50ZXJwb2xhdGVOdW1iZXIgPSBfZGVyZXFfKCdkMy1pbnRlcnBvbGF0ZScpLmludGVycG9sYXRlTnVtYmVyO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xuXG4vLyB2aWV3IG1vZGVsc1xuXG5mdW5jdGlvbiBzYW5rZXlNb2RlbChsYXlvdXQsIGQsIHRyYWNlSW5kZXgpIHtcbiAgICB2YXIgY2FsY0RhdGEgPSB1bndyYXAoZCk7XG4gICAgdmFyIHRyYWNlID0gY2FsY0RhdGEudHJhY2U7XG4gICAgdmFyIGRvbWFpbiA9IHRyYWNlLmRvbWFpbjtcbiAgICB2YXIgaG9yaXpvbnRhbCA9IHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCc7XG4gICAgdmFyIG5vZGVQYWQgPSB0cmFjZS5ub2RlLnBhZDtcbiAgICB2YXIgbm9kZVRoaWNrbmVzcyA9IHRyYWNlLm5vZGUudGhpY2tuZXNzO1xuXG4gICAgdmFyIHdpZHRoID0gbGF5b3V0LndpZHRoICogKGRvbWFpbi54WzFdIC0gZG9tYWluLnhbMF0pO1xuICAgIHZhciBoZWlnaHQgPSBsYXlvdXQuaGVpZ2h0ICogKGRvbWFpbi55WzFdIC0gZG9tYWluLnlbMF0pO1xuXG4gICAgdmFyIG5vZGVzID0gY2FsY0RhdGEuX25vZGVzO1xuICAgIHZhciBsaW5rcyA9IGNhbGNEYXRhLl9saW5rcztcbiAgICB2YXIgY2lyY3VsYXIgPSBjYWxjRGF0YS5jaXJjdWxhcjtcblxuICAgIC8vIFNlbGVjdCBTYW5rZXkgZ2VuZXJhdG9yXG4gICAgdmFyIHNhbmtleTtcbiAgICBpZihjaXJjdWxhcikge1xuICAgICAgICBzYW5rZXkgPSBkM1NhbmtleUNpcmN1bGFyXG4gICAgICAgICAgICAuc2Fua2V5Q2lyY3VsYXIoKVxuICAgICAgICAgICAgLmNpcmN1bGFyTGlua0dhcCgwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzYW5rZXkgPSBkM1NhbmtleS5zYW5rZXkoKTtcbiAgICB9XG5cbiAgICBzYW5rZXlcbiAgICAgIC5pdGVyYXRpb25zKGMuc2Fua2V5SXRlcmF0aW9ucylcbiAgICAgIC5zaXplKGhvcml6b250YWwgPyBbd2lkdGgsIGhlaWdodF0gOiBbaGVpZ2h0LCB3aWR0aF0pXG4gICAgICAubm9kZVdpZHRoKG5vZGVUaGlja25lc3MpXG4gICAgICAubm9kZVBhZGRpbmcobm9kZVBhZClcbiAgICAgIC5ub2RlSWQoZnVuY3Rpb24oZCkge1xuICAgICAgICAgIHJldHVybiBkLnBvaW50TnVtYmVyO1xuICAgICAgfSlcbiAgICAgIC5ub2Rlcyhub2RlcylcbiAgICAgIC5saW5rcyhsaW5rcyk7XG5cbiAgICB2YXIgZ3JhcGggPSBzYW5rZXkoKTtcblxuICAgIGlmKHNhbmtleS5ub2RlUGFkZGluZygpIDwgbm9kZVBhZCkge1xuICAgICAgICBMaWIud2Fybignbm9kZS5wYWQgd2FzIHJlZHVjZWQgdG8gJywgc2Fua2V5Lm5vZGVQYWRkaW5nKCksICcgdG8gZml0IHdpdGhpbiB0aGUgZmlndXJlLicpO1xuICAgIH1cblxuICAgIC8vIENvdW50ZXJzIGZvciBuZXN0ZWQgbG9vcHNcbiAgICB2YXIgaSwgaiwgaztcblxuICAgIC8vIENyZWF0ZSB0cmFuc2llbnQgbm9kZXMgZm9yIGFuaW1hdGlvbnNcbiAgICBmb3IodmFyIG5vZGVQb2ludE51bWJlciBpbiBjYWxjRGF0YS5fZ3JvdXBMb29rdXApIHtcbiAgICAgICAgdmFyIGdyb3VwSW5kZXggPSBwYXJzZUludChjYWxjRGF0YS5fZ3JvdXBMb29rdXBbbm9kZVBvaW50TnVtYmVyXSk7XG5cbiAgICAgICAgLy8gRmluZCBub2RlIHJlcHJlc2VudGluZyBncm91cEluZGV4XG4gICAgICAgIHZhciBncm91cGluZ05vZGU7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgZ3JhcGgubm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGdyYXBoLm5vZGVzW2ldLnBvaW50TnVtYmVyID09PSBncm91cEluZGV4KSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBpbmdOb2RlID0gZ3JhcGgubm9kZXNbaV07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgZ3JvdXBpbk5vZGUgaXMgdW5kZWZpbmVkLCBubyBsaW5rcyBhcmUgdGFyZ2V0aW5nIHRoaXMgZ3JvdXBcbiAgICAgICAgaWYoIWdyb3VwaW5nTm9kZSkgY29udGludWU7XG5cbiAgICAgICAgdmFyIGNoaWxkID0ge1xuICAgICAgICAgICAgcG9pbnROdW1iZXI6IHBhcnNlSW50KG5vZGVQb2ludE51bWJlciksXG4gICAgICAgICAgICB4MDogZ3JvdXBpbmdOb2RlLngwLFxuICAgICAgICAgICAgeDE6IGdyb3VwaW5nTm9kZS54MSxcbiAgICAgICAgICAgIHkwOiBncm91cGluZ05vZGUueTAsXG4gICAgICAgICAgICB5MTogZ3JvdXBpbmdOb2RlLnkxLFxuICAgICAgICAgICAgcGFydE9mR3JvdXA6IHRydWUsXG4gICAgICAgICAgICBzb3VyY2VMaW5rczogW10sXG4gICAgICAgICAgICB0YXJnZXRMaW5rczogW11cbiAgICAgICAgfTtcblxuICAgICAgICBncmFwaC5ub2Rlcy51bnNoaWZ0KGNoaWxkKTtcbiAgICAgICAgZ3JvdXBpbmdOb2RlLmNoaWxkcmVuTm9kZXMudW5zaGlmdChjaGlsZCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZUxpbmtDb25jZW50cmF0aW9ucygpIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgZ3JhcGgubm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBub2RlID0gZ3JhcGgubm9kZXNbaV07XG4gICAgICAgICAgICAvLyBMaW5rcyBjb25uZWN0aW5nIHRoZSBzYW1lIHR3byBub2RlcyBhcmUgcGFydCBvZiBhIGZsb3dcbiAgICAgICAgICAgIHZhciBmbG93cyA9IHt9O1xuICAgICAgICAgICAgdmFyIGZsb3dLZXk7XG4gICAgICAgICAgICB2YXIgbGluaztcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5vZGUudGFyZ2V0TGlua3MubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBsaW5rID0gbm9kZS50YXJnZXRMaW5rc1tqXTtcbiAgICAgICAgICAgICAgICBmbG93S2V5ID0gbGluay5zb3VyY2UucG9pbnROdW1iZXIgKyAnOicgKyBsaW5rLnRhcmdldC5wb2ludE51bWJlcjtcbiAgICAgICAgICAgICAgICBpZighZmxvd3MuaGFzT3duUHJvcGVydHkoZmxvd0tleSkpIGZsb3dzW2Zsb3dLZXldID0gW107XG4gICAgICAgICAgICAgICAgZmxvd3NbZmxvd0tleV0ucHVzaChsaW5rKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ29tcHV0ZSBzdGF0aXN0aWNzIGZvciBlYWNoIGZsb3dcbiAgICAgICAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMoZmxvd3MpO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwga2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGZsb3dLZXkgPSBrZXlzW2pdO1xuICAgICAgICAgICAgICAgIHZhciBmbG93TGlua3MgPSBmbG93c1tmbG93S2V5XTtcblxuICAgICAgICAgICAgICAgIC8vIEZpbmQgdGhlIHRvdGFsIHNpemUgb2YgdGhlIGZsb3cgYW5kIHRvdGFsIHNpemUgcGVyIGxhYmVsXG4gICAgICAgICAgICAgICAgdmFyIHRvdGFsID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgdG90YWxQZXJMYWJlbCA9IHt9O1xuICAgICAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGZsb3dMaW5rcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBsaW5rID0gZmxvd0xpbmtzW2tdO1xuICAgICAgICAgICAgICAgICAgICBpZighdG90YWxQZXJMYWJlbFtsaW5rLmxhYmVsXSkgdG90YWxQZXJMYWJlbFtsaW5rLmxhYmVsXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHRvdGFsUGVyTGFiZWxbbGluay5sYWJlbF0gKz0gbGluay52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgdG90YWwgKz0gbGluay52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBGaW5kIHRoZSByYXRpbyBvZiB0aGUgbGluaydzIHZhbHVlIGFuZCB0aGUgc2l6ZSBvZiB0aGUgZmxvd1xuICAgICAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGZsb3dMaW5rcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBsaW5rID0gZmxvd0xpbmtzW2tdO1xuICAgICAgICAgICAgICAgICAgICBsaW5rLmZsb3cgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdG90YWwsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYWJlbENvbmNlbnRyYXRpb246IHRvdGFsUGVyTGFiZWxbbGluay5sYWJlbF0gLyB0b3RhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmNlbnRyYXRpb246IGxpbmsudmFsdWUgLyB0b3RhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmtzOiBmbG93TGlua3NcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgaWYobGluay5jb25jZW50cmF0aW9uc2NhbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmsuY29sb3IgPSB0aW55Y29sb3IobGluay5jb25jZW50cmF0aW9uc2NhbGUobGluay5mbG93LmxhYmVsQ29uY2VudHJhdGlvbikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBHYXRoZXIgc3RhdGlzdGljcyBvZiBhbGwgbGlua3MgYXQgY3VycmVudCBub2RlXG4gICAgICAgICAgICB2YXIgdG90YWxPdXRmbG93ID0gMDtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5vZGUuc291cmNlTGlua3MubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB0b3RhbE91dGZsb3cgKz0gbm9kZS5zb3VyY2VMaW5rc1tqXS52YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5vZGUuc291cmNlTGlua3MubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBsaW5rID0gbm9kZS5zb3VyY2VMaW5rc1tqXTtcbiAgICAgICAgICAgICAgICBsaW5rLmNvbmNlbnRyYXRpb25PdXQgPSBsaW5rLnZhbHVlIC8gdG90YWxPdXRmbG93O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgdG90YWxJbmZsb3cgPSAwO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbm9kZS50YXJnZXRMaW5rcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIHRvdGFsSW5mbG93ICs9IG5vZGUudGFyZ2V0TGlua3Nbal0udmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IG5vZGUudGFyZ2V0TGlua3MubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBsaW5rID0gbm9kZS50YXJnZXRMaW5rc1tqXTtcbiAgICAgICAgICAgICAgICBsaW5rLmNvbmNlbnJhdGlvbkluID0gbGluay52YWx1ZSAvIHRvdGFsSW5mbG93O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGNvbXB1dGVMaW5rQ29uY2VudHJhdGlvbnMoKTtcblxuICAgIC8vIFB1c2ggYW55IG92ZXJsYXBwaW5nIG5vZGVzIGRvd24uXG4gICAgZnVuY3Rpb24gcmVzb2x2ZUNvbGxpc2lvbnNUb3BUb0JvdHRvbShjb2x1bW5zKSB7XG4gICAgICAgIGNvbHVtbnMuZm9yRWFjaChmdW5jdGlvbihub2Rlcykge1xuICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICB2YXIgZHk7XG4gICAgICAgICAgICB2YXIgeSA9IDA7XG4gICAgICAgICAgICB2YXIgbiA9IG5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBpO1xuICAgICAgICAgICAgbm9kZXMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEueTAgLSBiLnkwO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICAgICAgICBub2RlID0gbm9kZXNbaV07XG4gICAgICAgICAgICAgICAgaWYobm9kZS55MCA+PSB5KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vIG92ZXJsYXBcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkeSA9ICh5IC0gbm9kZS55MCk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGR5ID4gMWUtNikgbm9kZS55MCArPSBkeSwgbm9kZS55MSArPSBkeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgeSA9IG5vZGUueTEgKyBub2RlUGFkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBHcm91cCBub2RlcyBpbnRvIGNvbHVtbnMgYmFzZWQgb24gdGhlaXIgeCBwb3NpdGlvblxuICAgIGZ1bmN0aW9uIHNuYXBUb0NvbHVtbnMobm9kZXMpIHtcbiAgICAgICAgLy8gU29ydCBub2RlcyBieSB4IHBvc2l0aW9uXG4gICAgICAgIHZhciBvcmRlcmVkTm9kZXMgPSBub2Rlcy5tYXAoZnVuY3Rpb24obiwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB4MDogbi54MCxcbiAgICAgICAgICAgICAgICBpbmRleDogaVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSlcbiAgICAgICAgLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGEueDAgLSBiLngwO1xuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgY29sdW1ucyA9IFtdO1xuICAgICAgICB2YXIgY29sTnVtYmVyID0gLTE7XG4gICAgICAgIHZhciBjb2xYOyAvLyBQb3NpdGlvbiBvZiBjb2x1bW5cbiAgICAgICAgdmFyIGxhc3RYID0gLUluZmluaXR5OyAvLyBQb3NpdGlvbiBvZiBsYXN0IG5vZGVcbiAgICAgICAgdmFyIGR4O1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBvcmRlcmVkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBub2RlID0gbm9kZXNbb3JkZXJlZE5vZGVzW2ldLmluZGV4XTtcbiAgICAgICAgICAgIC8vIElmIHRoZSBub2RlIGRvZXMgbm90IG92ZXJsYXAgd2l0aCB0aGUgbGFzdCBvbmVcbiAgICAgICAgICAgIGlmKG5vZGUueDAgPiBsYXN0WCArIG5vZGVUaGlja25lc3MpIHtcbiAgICAgICAgICAgICAgICAvLyBTdGFydCBhIG5ldyBjb2x1bW5cbiAgICAgICAgICAgICAgICBjb2xOdW1iZXIgKz0gMTtcbiAgICAgICAgICAgICAgICBjb2xYID0gbm9kZS54MDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxhc3RYID0gbm9kZS54MDtcblxuICAgICAgICAgICAgLy8gQWRkIG5vZGUgdG8gaXRzIGFzc29jaWF0ZWQgY29sdW1uXG4gICAgICAgICAgICBpZighY29sdW1uc1tjb2xOdW1iZXJdKSBjb2x1bW5zW2NvbE51bWJlcl0gPSBbXTtcbiAgICAgICAgICAgIGNvbHVtbnNbY29sTnVtYmVyXS5wdXNoKG5vZGUpO1xuXG4gICAgICAgICAgICAvLyBDaGFuZ2Ugbm9kZSdzIHggcG9zaXRpb24gdG8gYWxpZ24gaXQgd2l0aCBpdHMgY29sdW1uXG4gICAgICAgICAgICBkeCA9IGNvbFggLSBub2RlLngwO1xuICAgICAgICAgICAgbm9kZS54MCArPSBkeCwgbm9kZS54MSArPSBkeDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29sdW1ucztcbiAgICB9XG5cbiAgICAvLyBGb3JjZSBub2RlIHBvc2l0aW9uXG4gICAgaWYodHJhY2Uubm9kZS54Lmxlbmd0aCAmJiB0cmFjZS5ub2RlLnkubGVuZ3RoKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IE1hdGgubWluKHRyYWNlLm5vZGUueC5sZW5ndGgsIHRyYWNlLm5vZGUueS5sZW5ndGgsIGdyYXBoLm5vZGVzLmxlbmd0aCk7IGkrKykge1xuICAgICAgICAgICAgaWYodHJhY2Uubm9kZS54W2ldICYmIHRyYWNlLm5vZGUueVtpXSkge1xuICAgICAgICAgICAgICAgIHZhciBwb3MgPSBbdHJhY2Uubm9kZS54W2ldICogd2lkdGgsIHRyYWNlLm5vZGUueVtpXSAqIGhlaWdodF07XG4gICAgICAgICAgICAgICAgZ3JhcGgubm9kZXNbaV0ueDAgPSBwb3NbMF0gLSBub2RlVGhpY2tuZXNzIC8gMjtcbiAgICAgICAgICAgICAgICBncmFwaC5ub2Rlc1tpXS54MSA9IHBvc1swXSArIG5vZGVUaGlja25lc3MgLyAyO1xuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGVIZWlnaHQgPSBncmFwaC5ub2Rlc1tpXS55MSAtIGdyYXBoLm5vZGVzW2ldLnkwO1xuICAgICAgICAgICAgICAgIGdyYXBoLm5vZGVzW2ldLnkwID0gcG9zWzFdIC0gbm9kZUhlaWdodCAvIDI7XG4gICAgICAgICAgICAgICAgZ3JhcGgubm9kZXNbaV0ueTEgPSBwb3NbMV0gKyBub2RlSGVpZ2h0IC8gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZih0cmFjZS5hcnJhbmdlbWVudCA9PT0gJ3NuYXAnKSB7XG4gICAgICAgICAgICBub2RlcyA9IGdyYXBoLm5vZGVzO1xuICAgICAgICAgICAgdmFyIGNvbHVtbnMgPSBzbmFwVG9Db2x1bW5zKG5vZGVzKTtcbiAgICAgICAgICAgIHJlc29sdmVDb2xsaXNpb25zVG9wVG9Cb3R0b20oY29sdW1ucyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVXBkYXRlIGxpbmtzXG4gICAgICAgIHNhbmtleS51cGRhdGUoZ3JhcGgpO1xuICAgIH1cblxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY2lyY3VsYXI6IGNpcmN1bGFyLFxuICAgICAgICBrZXk6IHRyYWNlSW5kZXgsXG4gICAgICAgIHRyYWNlOiB0cmFjZSxcbiAgICAgICAgZ3VpZDogTGliLnJhbmRzdHIoKSxcbiAgICAgICAgaG9yaXpvbnRhbDogaG9yaXpvbnRhbCxcbiAgICAgICAgd2lkdGg6IHdpZHRoLFxuICAgICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgICAgbm9kZVBhZDogdHJhY2Uubm9kZS5wYWQsXG4gICAgICAgIG5vZGVMaW5lQ29sb3I6IHRyYWNlLm5vZGUubGluZS5jb2xvcixcbiAgICAgICAgbm9kZUxpbmVXaWR0aDogdHJhY2Uubm9kZS5saW5lLndpZHRoLFxuICAgICAgICBsaW5rTGluZUNvbG9yOiB0cmFjZS5saW5rLmxpbmUuY29sb3IsXG4gICAgICAgIGxpbmtMaW5lV2lkdGg6IHRyYWNlLmxpbmsubGluZS53aWR0aCxcbiAgICAgICAgdmFsdWVGb3JtYXQ6IHRyYWNlLnZhbHVlZm9ybWF0LFxuICAgICAgICB2YWx1ZVN1ZmZpeDogdHJhY2UudmFsdWVzdWZmaXgsXG4gICAgICAgIHRleHRGb250OiB0cmFjZS50ZXh0Zm9udCxcbiAgICAgICAgdHJhbnNsYXRlWDogZG9tYWluLnhbMF0gKiBsYXlvdXQud2lkdGggKyBsYXlvdXQubWFyZ2luLmwsXG4gICAgICAgIHRyYW5zbGF0ZVk6IGxheW91dC5oZWlnaHQgLSBkb21haW4ueVsxXSAqIGxheW91dC5oZWlnaHQgKyBsYXlvdXQubWFyZ2luLnQsXG4gICAgICAgIGRyYWdQYXJhbGxlbDogaG9yaXpvbnRhbCA/IGhlaWdodCA6IHdpZHRoLFxuICAgICAgICBkcmFnUGVycGVuZGljdWxhcjogaG9yaXpvbnRhbCA/IHdpZHRoIDogaGVpZ2h0LFxuICAgICAgICBhcnJhbmdlbWVudDogdHJhY2UuYXJyYW5nZW1lbnQsXG4gICAgICAgIHNhbmtleTogc2Fua2V5LFxuICAgICAgICBncmFwaDogZ3JhcGgsXG4gICAgICAgIGZvcmNlTGF5b3V0czoge30sXG4gICAgICAgIGludGVyYWN0aW9uU3RhdGU6IHtcbiAgICAgICAgICAgIGRyYWdJblByb2dyZXNzOiBmYWxzZSxcbiAgICAgICAgICAgIGhvdmVyZWQ6IGZhbHNlXG4gICAgICAgIH1cbiAgICB9O1xufVxuXG5mdW5jdGlvbiBsaW5rTW9kZWwoZCwgbCwgaSkge1xuICAgIHZhciB0YyA9IHRpbnljb2xvcihsLmNvbG9yKTtcbiAgICB2YXIgYmFzaWNLZXkgPSBsLnNvdXJjZS5sYWJlbCArICd8JyArIGwudGFyZ2V0LmxhYmVsO1xuICAgIHZhciBrZXkgPSBiYXNpY0tleSArICdfXycgKyBpO1xuXG4gICAgLy8gZm9yIGV2ZW50IGRhdGFcbiAgICBsLnRyYWNlID0gZC50cmFjZTtcbiAgICBsLmN1cnZlTnVtYmVyID0gZC50cmFjZS5pbmRleDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGNpcmN1bGFyOiBkLmNpcmN1bGFyLFxuICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgdHJhY2VJZDogZC5rZXksXG4gICAgICAgIHBvaW50TnVtYmVyOiBsLnBvaW50TnVtYmVyLFxuICAgICAgICBsaW5rOiBsLFxuICAgICAgICB0aW55Q29sb3JIdWU6IENvbG9yLnRpbnlSR0IodGMpLFxuICAgICAgICB0aW55Q29sb3JBbHBoYTogdGMuZ2V0QWxwaGEoKSxcbiAgICAgICAgbGlua1BhdGg6IGxpbmtQYXRoLFxuICAgICAgICBsaW5rTGluZUNvbG9yOiBkLmxpbmtMaW5lQ29sb3IsXG4gICAgICAgIGxpbmtMaW5lV2lkdGg6IGQubGlua0xpbmVXaWR0aCxcbiAgICAgICAgdmFsdWVGb3JtYXQ6IGQudmFsdWVGb3JtYXQsXG4gICAgICAgIHZhbHVlU3VmZml4OiBkLnZhbHVlU3VmZml4LFxuICAgICAgICBzYW5rZXk6IGQuc2Fua2V5LFxuICAgICAgICBwYXJlbnQ6IGQsXG4gICAgICAgIGludGVyYWN0aW9uU3RhdGU6IGQuaW50ZXJhY3Rpb25TdGF0ZSxcbiAgICAgICAgZmxvdzogbC5mbG93XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlQ2lyY3VsYXJDbG9zZWRQYXRoU3RyaW5nKGxpbmspIHtcbiAgICAvLyBVc2luZyBjb29yZGluYXRlcyBjb21wdXRlZCBieSBkMy1zYW5rZXktY2lyY3VsYXJcbiAgICB2YXIgcGF0aFN0cmluZyA9ICcnO1xuICAgIHZhciBvZmZzZXQgPSBsaW5rLndpZHRoIC8gMjtcbiAgICB2YXIgY29vcmRzID0gbGluay5jaXJjdWxhclBhdGhEYXRhO1xuICAgIGlmKGxpbmsuY2lyY3VsYXJMaW5rVHlwZSA9PT0gJ3RvcCcpIHtcbiAgICAgICAgLy8gVG9wIHBhdGhcbiAgICAgICAgcGF0aFN0cmluZyA9XG4gICAgICAgICAgLy8gc3RhcnQgYXQgdGhlIGxlZnQgb2YgdGhlIHRhcmdldCBub2RlXG4gICAgICAgICAgJ00gJyArXG4gICAgICAgICAgY29vcmRzLnRhcmdldFggKyAnICcgKyAoY29vcmRzLnRhcmdldFkgKyBvZmZzZXQpICsgJyAnICtcbiAgICAgICAgICAnTCcgK1xuICAgICAgICAgIGNvb3Jkcy5yaWdodElubmVyRXh0ZW50ICsgJyAnICsgKGNvb3Jkcy50YXJnZXRZICsgb2Zmc2V0KSArXG4gICAgICAgICAgJ0EnICtcbiAgICAgICAgICAoY29vcmRzLnJpZ2h0TGFyZ2VBcmNSYWRpdXMgKyBvZmZzZXQpICsgJyAnICsgKGNvb3Jkcy5yaWdodFNtYWxsQXJjUmFkaXVzICsgb2Zmc2V0KSArICcgMCAwIDEgJyArXG4gICAgICAgICAgKGNvb3Jkcy5yaWdodEZ1bGxFeHRlbnQgLSBvZmZzZXQpICsgJyAnICsgKGNvb3Jkcy50YXJnZXRZIC0gY29vcmRzLnJpZ2h0U21hbGxBcmNSYWRpdXMpICtcbiAgICAgICAgICAnTCcgK1xuICAgICAgICAgIChjb29yZHMucmlnaHRGdWxsRXh0ZW50IC0gb2Zmc2V0KSArICcgJyArIGNvb3Jkcy52ZXJ0aWNhbFJpZ2h0SW5uZXJFeHRlbnQgK1xuICAgICAgICAgICdBJyArXG4gICAgICAgICAgKGNvb3Jkcy5yaWdodExhcmdlQXJjUmFkaXVzICsgb2Zmc2V0KSArICcgJyArIChjb29yZHMucmlnaHRMYXJnZUFyY1JhZGl1cyArIG9mZnNldCkgKyAnIDAgMCAxICcgK1xuICAgICAgICAgIGNvb3Jkcy5yaWdodElubmVyRXh0ZW50ICsgJyAnICsgKGNvb3Jkcy52ZXJ0aWNhbEZ1bGxFeHRlbnQgLSBvZmZzZXQpICtcbiAgICAgICAgICAnTCcgK1xuICAgICAgICAgIGNvb3Jkcy5sZWZ0SW5uZXJFeHRlbnQgKyAnICcgKyAoY29vcmRzLnZlcnRpY2FsRnVsbEV4dGVudCAtIG9mZnNldCkgK1xuICAgICAgICAgICdBJyArXG4gICAgICAgICAgKGNvb3Jkcy5sZWZ0TGFyZ2VBcmNSYWRpdXMgKyBvZmZzZXQpICsgJyAnICsgKGNvb3Jkcy5sZWZ0TGFyZ2VBcmNSYWRpdXMgKyBvZmZzZXQpICsgJyAwIDAgMSAnICtcbiAgICAgICAgICAoY29vcmRzLmxlZnRGdWxsRXh0ZW50ICsgb2Zmc2V0KSArICcgJyArIGNvb3Jkcy52ZXJ0aWNhbExlZnRJbm5lckV4dGVudCArXG4gICAgICAgICAgJ0wnICtcbiAgICAgICAgICAoY29vcmRzLmxlZnRGdWxsRXh0ZW50ICsgb2Zmc2V0KSArICcgJyArIChjb29yZHMuc291cmNlWSAtIGNvb3Jkcy5sZWZ0U21hbGxBcmNSYWRpdXMpICtcbiAgICAgICAgICAnQScgK1xuICAgICAgICAgIChjb29yZHMubGVmdExhcmdlQXJjUmFkaXVzICsgb2Zmc2V0KSArICcgJyArIChjb29yZHMubGVmdFNtYWxsQXJjUmFkaXVzICsgb2Zmc2V0KSArICcgMCAwIDEgJyArXG4gICAgICAgICAgY29vcmRzLmxlZnRJbm5lckV4dGVudCArICcgJyArIChjb29yZHMuc291cmNlWSArIG9mZnNldCkgK1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgY29vcmRzLnNvdXJjZVggKyAnICcgKyAoY29vcmRzLnNvdXJjZVkgKyBvZmZzZXQpICtcblxuICAgICAgICAgIC8vIFdhbGtpbmcgYmFja1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgY29vcmRzLnNvdXJjZVggKyAnICcgKyAoY29vcmRzLnNvdXJjZVkgLSBvZmZzZXQpICtcbiAgICAgICAgICAnTCcgK1xuICAgICAgICAgIGNvb3Jkcy5sZWZ0SW5uZXJFeHRlbnQgKyAnICcgKyAoY29vcmRzLnNvdXJjZVkgLSBvZmZzZXQpICtcbiAgICAgICAgICAnQScgK1xuICAgICAgICAgIChjb29yZHMubGVmdExhcmdlQXJjUmFkaXVzIC0gb2Zmc2V0KSArICcgJyArIChjb29yZHMubGVmdFNtYWxsQXJjUmFkaXVzIC0gb2Zmc2V0KSArICcgMCAwIDAgJyArXG4gICAgICAgICAgKGNvb3Jkcy5sZWZ0RnVsbEV4dGVudCAtIG9mZnNldCkgKyAnICcgKyAoY29vcmRzLnNvdXJjZVkgLSBjb29yZHMubGVmdFNtYWxsQXJjUmFkaXVzKSArXG4gICAgICAgICAgJ0wnICtcbiAgICAgICAgICAoY29vcmRzLmxlZnRGdWxsRXh0ZW50IC0gb2Zmc2V0KSArICcgJyArIGNvb3Jkcy52ZXJ0aWNhbExlZnRJbm5lckV4dGVudCArXG4gICAgICAgICAgJ0EnICtcbiAgICAgICAgICAoY29vcmRzLmxlZnRMYXJnZUFyY1JhZGl1cyAtIG9mZnNldCkgKyAnICcgKyAoY29vcmRzLmxlZnRMYXJnZUFyY1JhZGl1cyAtIG9mZnNldCkgKyAnIDAgMCAwICcgK1xuICAgICAgICAgIGNvb3Jkcy5sZWZ0SW5uZXJFeHRlbnQgKyAnICcgKyAoY29vcmRzLnZlcnRpY2FsRnVsbEV4dGVudCArIG9mZnNldCkgK1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgY29vcmRzLnJpZ2h0SW5uZXJFeHRlbnQgKyAnICcgKyAoY29vcmRzLnZlcnRpY2FsRnVsbEV4dGVudCArIG9mZnNldCkgK1xuICAgICAgICAgICdBJyArXG4gICAgICAgICAgKGNvb3Jkcy5yaWdodExhcmdlQXJjUmFkaXVzIC0gb2Zmc2V0KSArICcgJyArIChjb29yZHMucmlnaHRMYXJnZUFyY1JhZGl1cyAtIG9mZnNldCkgKyAnIDAgMCAwICcgK1xuICAgICAgICAgIChjb29yZHMucmlnaHRGdWxsRXh0ZW50ICsgb2Zmc2V0KSArICcgJyArIGNvb3Jkcy52ZXJ0aWNhbFJpZ2h0SW5uZXJFeHRlbnQgK1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgKGNvb3Jkcy5yaWdodEZ1bGxFeHRlbnQgKyBvZmZzZXQpICsgJyAnICsgKGNvb3Jkcy50YXJnZXRZIC0gY29vcmRzLnJpZ2h0U21hbGxBcmNSYWRpdXMpICtcbiAgICAgICAgICAnQScgK1xuICAgICAgICAgIChjb29yZHMucmlnaHRMYXJnZUFyY1JhZGl1cyAtIG9mZnNldCkgKyAnICcgKyAoY29vcmRzLnJpZ2h0U21hbGxBcmNSYWRpdXMgLSBvZmZzZXQpICsgJyAwIDAgMCAnICtcbiAgICAgICAgICBjb29yZHMucmlnaHRJbm5lckV4dGVudCArICcgJyArIChjb29yZHMudGFyZ2V0WSAtIG9mZnNldCkgK1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgY29vcmRzLnRhcmdldFggKyAnICcgKyAoY29vcmRzLnRhcmdldFkgLSBvZmZzZXQpICtcbiAgICAgICAgICAnWic7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQm90dG9tIHBhdGhcbiAgICAgICAgcGF0aFN0cmluZyA9XG4gICAgICAgICAgLy8gc3RhcnQgYXQgdGhlIGxlZnQgb2YgdGhlIHRhcmdldCBub2RlXG4gICAgICAgICAgJ00gJyArXG4gICAgICAgICAgY29vcmRzLnRhcmdldFggKyAnICcgKyAoY29vcmRzLnRhcmdldFkgLSBvZmZzZXQpICsgJyAnICtcbiAgICAgICAgICAnTCcgK1xuICAgICAgICAgIGNvb3Jkcy5yaWdodElubmVyRXh0ZW50ICsgJyAnICsgKGNvb3Jkcy50YXJnZXRZIC0gb2Zmc2V0KSArXG4gICAgICAgICAgJ0EnICtcbiAgICAgICAgICAoY29vcmRzLnJpZ2h0TGFyZ2VBcmNSYWRpdXMgKyBvZmZzZXQpICsgJyAnICsgKGNvb3Jkcy5yaWdodFNtYWxsQXJjUmFkaXVzICsgb2Zmc2V0KSArICcgMCAwIDAgJyArXG4gICAgICAgICAgKGNvb3Jkcy5yaWdodEZ1bGxFeHRlbnQgLSBvZmZzZXQpICsgJyAnICsgKGNvb3Jkcy50YXJnZXRZICsgY29vcmRzLnJpZ2h0U21hbGxBcmNSYWRpdXMpICtcbiAgICAgICAgICAnTCcgK1xuICAgICAgICAgIChjb29yZHMucmlnaHRGdWxsRXh0ZW50IC0gb2Zmc2V0KSArICcgJyArIGNvb3Jkcy52ZXJ0aWNhbFJpZ2h0SW5uZXJFeHRlbnQgK1xuICAgICAgICAgICdBJyArXG4gICAgICAgICAgKGNvb3Jkcy5yaWdodExhcmdlQXJjUmFkaXVzICsgb2Zmc2V0KSArICcgJyArIChjb29yZHMucmlnaHRMYXJnZUFyY1JhZGl1cyArIG9mZnNldCkgKyAnIDAgMCAwICcgK1xuICAgICAgICAgIGNvb3Jkcy5yaWdodElubmVyRXh0ZW50ICsgJyAnICsgKGNvb3Jkcy52ZXJ0aWNhbEZ1bGxFeHRlbnQgKyBvZmZzZXQpICtcbiAgICAgICAgICAnTCcgK1xuICAgICAgICAgIGNvb3Jkcy5sZWZ0SW5uZXJFeHRlbnQgKyAnICcgKyAoY29vcmRzLnZlcnRpY2FsRnVsbEV4dGVudCArIG9mZnNldCkgK1xuICAgICAgICAgICdBJyArXG4gICAgICAgICAgKGNvb3Jkcy5sZWZ0TGFyZ2VBcmNSYWRpdXMgKyBvZmZzZXQpICsgJyAnICsgKGNvb3Jkcy5sZWZ0TGFyZ2VBcmNSYWRpdXMgKyBvZmZzZXQpICsgJyAwIDAgMCAnICtcbiAgICAgICAgICAoY29vcmRzLmxlZnRGdWxsRXh0ZW50ICsgb2Zmc2V0KSArICcgJyArIGNvb3Jkcy52ZXJ0aWNhbExlZnRJbm5lckV4dGVudCArXG4gICAgICAgICAgJ0wnICtcbiAgICAgICAgICAoY29vcmRzLmxlZnRGdWxsRXh0ZW50ICsgb2Zmc2V0KSArICcgJyArIChjb29yZHMuc291cmNlWSArIGNvb3Jkcy5sZWZ0U21hbGxBcmNSYWRpdXMpICtcbiAgICAgICAgICAnQScgK1xuICAgICAgICAgIChjb29yZHMubGVmdExhcmdlQXJjUmFkaXVzICsgb2Zmc2V0KSArICcgJyArIChjb29yZHMubGVmdFNtYWxsQXJjUmFkaXVzICsgb2Zmc2V0KSArICcgMCAwIDAgJyArXG4gICAgICAgICAgY29vcmRzLmxlZnRJbm5lckV4dGVudCArICcgJyArIChjb29yZHMuc291cmNlWSAtIG9mZnNldCkgK1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgY29vcmRzLnNvdXJjZVggKyAnICcgKyAoY29vcmRzLnNvdXJjZVkgLSBvZmZzZXQpICtcblxuICAgICAgICAgIC8vIFdhbGtpbmcgYmFja1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgY29vcmRzLnNvdXJjZVggKyAnICcgKyAoY29vcmRzLnNvdXJjZVkgKyBvZmZzZXQpICtcbiAgICAgICAgICAnTCcgK1xuICAgICAgICAgIGNvb3Jkcy5sZWZ0SW5uZXJFeHRlbnQgKyAnICcgKyAoY29vcmRzLnNvdXJjZVkgKyBvZmZzZXQpICtcbiAgICAgICAgICAnQScgK1xuICAgICAgICAgIChjb29yZHMubGVmdExhcmdlQXJjUmFkaXVzIC0gb2Zmc2V0KSArICcgJyArIChjb29yZHMubGVmdFNtYWxsQXJjUmFkaXVzIC0gb2Zmc2V0KSArICcgMCAwIDEgJyArXG4gICAgICAgICAgKGNvb3Jkcy5sZWZ0RnVsbEV4dGVudCAtIG9mZnNldCkgKyAnICcgKyAoY29vcmRzLnNvdXJjZVkgKyBjb29yZHMubGVmdFNtYWxsQXJjUmFkaXVzKSArXG4gICAgICAgICAgJ0wnICtcbiAgICAgICAgICAoY29vcmRzLmxlZnRGdWxsRXh0ZW50IC0gb2Zmc2V0KSArICcgJyArIGNvb3Jkcy52ZXJ0aWNhbExlZnRJbm5lckV4dGVudCArXG4gICAgICAgICAgJ0EnICtcbiAgICAgICAgICAoY29vcmRzLmxlZnRMYXJnZUFyY1JhZGl1cyAtIG9mZnNldCkgKyAnICcgKyAoY29vcmRzLmxlZnRMYXJnZUFyY1JhZGl1cyAtIG9mZnNldCkgKyAnIDAgMCAxICcgK1xuICAgICAgICAgIGNvb3Jkcy5sZWZ0SW5uZXJFeHRlbnQgKyAnICcgKyAoY29vcmRzLnZlcnRpY2FsRnVsbEV4dGVudCAtIG9mZnNldCkgK1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgY29vcmRzLnJpZ2h0SW5uZXJFeHRlbnQgKyAnICcgKyAoY29vcmRzLnZlcnRpY2FsRnVsbEV4dGVudCAtIG9mZnNldCkgK1xuICAgICAgICAgICdBJyArXG4gICAgICAgICAgKGNvb3Jkcy5yaWdodExhcmdlQXJjUmFkaXVzIC0gb2Zmc2V0KSArICcgJyArIChjb29yZHMucmlnaHRMYXJnZUFyY1JhZGl1cyAtIG9mZnNldCkgKyAnIDAgMCAxICcgK1xuICAgICAgICAgIChjb29yZHMucmlnaHRGdWxsRXh0ZW50ICsgb2Zmc2V0KSArICcgJyArIGNvb3Jkcy52ZXJ0aWNhbFJpZ2h0SW5uZXJFeHRlbnQgK1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgKGNvb3Jkcy5yaWdodEZ1bGxFeHRlbnQgKyBvZmZzZXQpICsgJyAnICsgKGNvb3Jkcy50YXJnZXRZICsgY29vcmRzLnJpZ2h0U21hbGxBcmNSYWRpdXMpICtcbiAgICAgICAgICAnQScgK1xuICAgICAgICAgIChjb29yZHMucmlnaHRMYXJnZUFyY1JhZGl1cyAtIG9mZnNldCkgKyAnICcgKyAoY29vcmRzLnJpZ2h0U21hbGxBcmNSYWRpdXMgLSBvZmZzZXQpICsgJyAwIDAgMSAnICtcbiAgICAgICAgICBjb29yZHMucmlnaHRJbm5lckV4dGVudCArICcgJyArIChjb29yZHMudGFyZ2V0WSArIG9mZnNldCkgK1xuICAgICAgICAgICdMJyArXG4gICAgICAgICAgY29vcmRzLnRhcmdldFggKyAnICcgKyAoY29vcmRzLnRhcmdldFkgKyBvZmZzZXQpICtcbiAgICAgICAgICAnWic7XG4gICAgfVxuICAgIHJldHVybiBwYXRoU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBsaW5rUGF0aCgpIHtcbiAgICB2YXIgY3VydmF0dXJlID0gMC41O1xuICAgIGZ1bmN0aW9uIHBhdGgoZCkge1xuICAgICAgICBpZihkLmxpbmsuY2lyY3VsYXIpIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVDaXJjdWxhckNsb3NlZFBhdGhTdHJpbmcoZC5saW5rKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciB4MCA9IGQubGluay5zb3VyY2UueDE7XG4gICAgICAgICAgICB2YXIgeDEgPSBkLmxpbmsudGFyZ2V0LngwO1xuICAgICAgICAgICAgdmFyIHhpID0gaW50ZXJwb2xhdGVOdW1iZXIoeDAsIHgxKTtcbiAgICAgICAgICAgIHZhciB4MiA9IHhpKGN1cnZhdHVyZSk7XG4gICAgICAgICAgICB2YXIgeDMgPSB4aSgxIC0gY3VydmF0dXJlKTtcbiAgICAgICAgICAgIHZhciB5MGEgPSBkLmxpbmsueTAgLSBkLmxpbmsud2lkdGggLyAyO1xuICAgICAgICAgICAgdmFyIHkwYiA9IGQubGluay55MCArIGQubGluay53aWR0aCAvIDI7XG4gICAgICAgICAgICB2YXIgeTFhID0gZC5saW5rLnkxIC0gZC5saW5rLndpZHRoIC8gMjtcbiAgICAgICAgICAgIHZhciB5MWIgPSBkLmxpbmsueTEgKyBkLmxpbmsud2lkdGggLyAyO1xuICAgICAgICAgICAgcmV0dXJuICdNJyArIHgwICsgJywnICsgeTBhICtcbiAgICAgICAgICAgICAgICAgJ0MnICsgeDIgKyAnLCcgKyB5MGEgK1xuICAgICAgICAgICAgICAgICAnICcgKyB4MyArICcsJyArIHkxYSArXG4gICAgICAgICAgICAgICAgICcgJyArIHgxICsgJywnICsgeTFhICtcbiAgICAgICAgICAgICAgICAgJ0wnICsgeDEgKyAnLCcgKyB5MWIgK1xuICAgICAgICAgICAgICAgICAnQycgKyB4MyArICcsJyArIHkxYiArXG4gICAgICAgICAgICAgICAgICcgJyArIHgyICsgJywnICsgeTBiICtcbiAgICAgICAgICAgICAgICAgJyAnICsgeDAgKyAnLCcgKyB5MGIgK1xuICAgICAgICAgICAgICAgICAnWic7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBhdGg7XG59XG5cbmZ1bmN0aW9uIG5vZGVNb2RlbChkLCBuKSB7XG4gICAgdmFyIHRjID0gdGlueWNvbG9yKG4uY29sb3IpO1xuICAgIHZhciB6b25lVGhpY2tuZXNzUGFkID0gYy5ub2RlUGFkQWNyb3NzO1xuICAgIHZhciB6b25lTGVuZ3RoUGFkID0gZC5ub2RlUGFkIC8gMjtcbiAgICBuLmR4ID0gbi54MSAtIG4ueDA7XG4gICAgbi5keSA9IG4ueTEgLSBuLnkwO1xuICAgIHZhciB2aXNpYmxlVGhpY2tuZXNzID0gbi5keDtcbiAgICB2YXIgdmlzaWJsZUxlbmd0aCA9IE1hdGgubWF4KDAuNSwgbi5keSk7XG5cbiAgICB2YXIga2V5ID0gJ25vZGVfJyArIG4ucG9pbnROdW1iZXI7XG4gICAgLy8gSWYgaXQncyBhIGdyb3VwLCBpdCdzIG11dGFibGUgYW5kIHNob3VsZCBiZSB1bmlxdWVcbiAgICBpZihuLmdyb3VwKSB7XG4gICAgICAgIGtleSA9IExpYi5yYW5kc3RyKCk7XG4gICAgfVxuXG4gICAgLy8gZm9yIGV2ZW50IGRhdGFcbiAgICBuLnRyYWNlID0gZC50cmFjZTtcbiAgICBuLmN1cnZlTnVtYmVyID0gZC50cmFjZS5pbmRleDtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGluZGV4OiBuLnBvaW50TnVtYmVyLFxuICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgcGFydE9mR3JvdXA6IG4ucGFydE9mR3JvdXAgfHwgZmFsc2UsXG4gICAgICAgIGdyb3VwOiBuLmdyb3VwLFxuICAgICAgICB0cmFjZUlkOiBkLmtleSxcbiAgICAgICAgdHJhY2U6IGQudHJhY2UsXG4gICAgICAgIG5vZGU6IG4sXG4gICAgICAgIG5vZGVQYWQ6IGQubm9kZVBhZCxcbiAgICAgICAgbm9kZUxpbmVDb2xvcjogZC5ub2RlTGluZUNvbG9yLFxuICAgICAgICBub2RlTGluZVdpZHRoOiBkLm5vZGVMaW5lV2lkdGgsXG4gICAgICAgIHRleHRGb250OiBkLnRleHRGb250LFxuICAgICAgICBzaXplOiBkLmhvcml6b250YWwgPyBkLmhlaWdodCA6IGQud2lkdGgsXG4gICAgICAgIHZpc2libGVXaWR0aDogTWF0aC5jZWlsKHZpc2libGVUaGlja25lc3MpLFxuICAgICAgICB2aXNpYmxlSGVpZ2h0OiB2aXNpYmxlTGVuZ3RoLFxuICAgICAgICB6b25lWDogLXpvbmVUaGlja25lc3NQYWQsXG4gICAgICAgIHpvbmVZOiAtem9uZUxlbmd0aFBhZCxcbiAgICAgICAgem9uZVdpZHRoOiB2aXNpYmxlVGhpY2tuZXNzICsgMiAqIHpvbmVUaGlja25lc3NQYWQsXG4gICAgICAgIHpvbmVIZWlnaHQ6IHZpc2libGVMZW5ndGggKyAyICogem9uZUxlbmd0aFBhZCxcbiAgICAgICAgbGFiZWxZOiBkLmhvcml6b250YWwgPyBuLmR5IC8gMiArIDEgOiBuLmR4IC8gMiArIDEsXG4gICAgICAgIGxlZnQ6IG4ub3JpZ2luYWxMYXllciA9PT0gMSxcbiAgICAgICAgc2l6ZUFjcm9zczogZC53aWR0aCxcbiAgICAgICAgZm9yY2VMYXlvdXRzOiBkLmZvcmNlTGF5b3V0cyxcbiAgICAgICAgaG9yaXpvbnRhbDogZC5ob3Jpem9udGFsLFxuICAgICAgICBkYXJrQmFja2dyb3VuZDogdGMuZ2V0QnJpZ2h0bmVzcygpIDw9IDEyOCxcbiAgICAgICAgdGlueUNvbG9ySHVlOiBDb2xvci50aW55UkdCKHRjKSxcbiAgICAgICAgdGlueUNvbG9yQWxwaGE6IHRjLmdldEFscGhhKCksXG4gICAgICAgIHZhbHVlRm9ybWF0OiBkLnZhbHVlRm9ybWF0LFxuICAgICAgICB2YWx1ZVN1ZmZpeDogZC52YWx1ZVN1ZmZpeCxcbiAgICAgICAgc2Fua2V5OiBkLnNhbmtleSxcbiAgICAgICAgZ3JhcGg6IGQuZ3JhcGgsXG4gICAgICAgIGFycmFuZ2VtZW50OiBkLmFycmFuZ2VtZW50LFxuICAgICAgICB1bmlxdWVOb2RlTGFiZWxQYXRoSWQ6IFtkLmd1aWQsIGQua2V5LCBrZXldLmpvaW4oJ18nKSxcbiAgICAgICAgaW50ZXJhY3Rpb25TdGF0ZTogZC5pbnRlcmFjdGlvblN0YXRlLFxuICAgICAgICBmaWd1cmU6IGRcbiAgICB9O1xufVxuXG4vLyByZW5kZXJpbmcgc25pcHBldHNcblxuZnVuY3Rpb24gdXBkYXRlTm9kZVBvc2l0aW9ucyhzYW5rZXlOb2RlKSB7XG4gICAgc2Fua2V5Tm9kZVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIGQubm9kZS54MC50b0ZpeGVkKDMpICsgJywgJyArIChkLm5vZGUueTApLnRvRml4ZWQoMykgKyAnKSc7XG4gICAgICAgIH0pO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVOb2RlU2hhcGVzKHNhbmtleU5vZGUpIHtcbiAgICBzYW5rZXlOb2RlLmNhbGwodXBkYXRlTm9kZVBvc2l0aW9ucyk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVNoYXBlcyhzYW5rZXlOb2RlLCBzYW5rZXlMaW5rKSB7XG4gICAgc2Fua2V5Tm9kZS5jYWxsKHVwZGF0ZU5vZGVTaGFwZXMpO1xuICAgIHNhbmtleUxpbmsuYXR0cignZCcsIGxpbmtQYXRoKCkpO1xufVxuXG5mdW5jdGlvbiBzaXplTm9kZShyZWN0KSB7XG4gICAgcmVjdFxuICAgICAgLmF0dHIoJ3dpZHRoJywgZnVuY3Rpb24oZCkge3JldHVybiBkLm5vZGUueDEgLSBkLm5vZGUueDA7fSlcbiAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQudmlzaWJsZUhlaWdodDt9KTtcbn1cblxuZnVuY3Rpb24gc2FsaWVudEVub3VnaChkKSB7cmV0dXJuIChkLmxpbmsud2lkdGggPiAxIHx8IGQubGlua0xpbmVXaWR0aCA+IDApO31cblxuZnVuY3Rpb24gc2Fua2V5VHJhbnNmb3JtKGQpIHtcbiAgICB2YXIgb2Zmc2V0ID0gJ3RyYW5zbGF0ZSgnICsgZC50cmFuc2xhdGVYICsgJywnICsgZC50cmFuc2xhdGVZICsgJyknO1xuICAgIHJldHVybiBvZmZzZXQgKyAoZC5ob3Jpem9udGFsID8gJ21hdHJpeCgxIDAgMCAxIDAgMCknIDogJ21hdHJpeCgwIDEgMSAwIDAgMCknKTtcbn1cblxuZnVuY3Rpb24gbm9kZUNlbnRlcmluZyhkKSB7XG4gICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIChkLmhvcml6b250YWwgPyAwIDogZC5sYWJlbFkpICsgJyAnICsgKGQuaG9yaXpvbnRhbCA/IGQubGFiZWxZIDogMCkgKyAnKSc7XG59XG5cbmZ1bmN0aW9uIHRleHRHdWlkZVBhdGgoZCkge1xuICAgIHJldHVybiBkMy5zdmcubGluZSgpKFtcbiAgICAgICAgW2QuaG9yaXpvbnRhbCA/IChkLmxlZnQgPyAtZC5zaXplQWNyb3NzIDogZC52aXNpYmxlV2lkdGggKyBjLm5vZGVUZXh0T2Zmc2V0SG9yaXpvbnRhbCkgOiBjLm5vZGVUZXh0T2Zmc2V0SG9yaXpvbnRhbCwgMF0sXG4gICAgICAgIFtkLmhvcml6b250YWwgPyAoZC5sZWZ0ID8gLSBjLm5vZGVUZXh0T2Zmc2V0SG9yaXpvbnRhbCA6IGQuc2l6ZUFjcm9zcykgOiBkLnZpc2libGVIZWlnaHQgLSBjLm5vZGVUZXh0T2Zmc2V0SG9yaXpvbnRhbCwgMF1cbiAgICBdKTtcbn1cblxuZnVuY3Rpb24gc2Fua2V5SW52ZXJzZVRyYW5zZm9ybShkKSB7cmV0dXJuIGQuaG9yaXpvbnRhbCA/ICdtYXRyaXgoMSAwIDAgMSAwIDApJyA6ICdtYXRyaXgoMCAxIDEgMCAwIDApJzt9XG5mdW5jdGlvbiB0ZXh0RmxpcChkKSB7cmV0dXJuIGQuaG9yaXpvbnRhbCA/ICdzY2FsZSgxIDEpJyA6ICdzY2FsZSgtMSAxKSc7fVxuZnVuY3Rpb24gbm9kZVRleHRDb2xvcihkKSB7cmV0dXJuIGQuZGFya0JhY2tncm91bmQgJiYgIWQuaG9yaXpvbnRhbCA/ICdyZ2IoMjU1LDI1NSwyNTUpJyA6ICdyZ2IoMCwwLDApJzt9XG5mdW5jdGlvbiBub2RlVGV4dE9mZnNldChkKSB7cmV0dXJuIGQuaG9yaXpvbnRhbCAmJiBkLmxlZnQgPyAnMTAwJScgOiAnMCUnO31cblxuLy8gZXZlbnQgaGFuZGxpbmdcblxuZnVuY3Rpb24gYXR0YWNoUG9pbnRlckV2ZW50cyhzZWxlY3Rpb24sIHNhbmtleSwgZXZlbnRTZXQpIHtcbiAgICBzZWxlY3Rpb25cbiAgICAgICAgLm9uKCcuYmFzaWMnLCBudWxsKSAvLyByZW1vdmUgYW55IHByZWV4aXN0aW5nIGhhbmRsZXJzXG4gICAgICAgIC5vbignbW91c2VvdmVyLmJhc2ljJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgaWYoIWQuaW50ZXJhY3Rpb25TdGF0ZS5kcmFnSW5Qcm9ncmVzcyAmJiAhZC5wYXJ0T2ZHcm91cCkge1xuICAgICAgICAgICAgICAgIGV2ZW50U2V0LmhvdmVyKHRoaXMsIGQsIHNhbmtleSk7XG4gICAgICAgICAgICAgICAgZC5pbnRlcmFjdGlvblN0YXRlLmhvdmVyZWQgPSBbdGhpcywgZF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5vbignbW91c2Vtb3ZlLmJhc2ljJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgaWYoIWQuaW50ZXJhY3Rpb25TdGF0ZS5kcmFnSW5Qcm9ncmVzcyAmJiAhZC5wYXJ0T2ZHcm91cCkge1xuICAgICAgICAgICAgICAgIGV2ZW50U2V0LmZvbGxvdyh0aGlzLCBkKTtcbiAgICAgICAgICAgICAgICBkLmludGVyYWN0aW9uU3RhdGUuaG92ZXJlZCA9IFt0aGlzLCBkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdtb3VzZW91dC5iYXNpYycsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGlmKCFkLmludGVyYWN0aW9uU3RhdGUuZHJhZ0luUHJvZ3Jlc3MgJiYgIWQucGFydE9mR3JvdXApIHtcbiAgICAgICAgICAgICAgICBldmVudFNldC51bmhvdmVyKHRoaXMsIGQsIHNhbmtleSk7XG4gICAgICAgICAgICAgICAgZC5pbnRlcmFjdGlvblN0YXRlLmhvdmVyZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLm9uKCdjbGljay5iYXNpYycsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGlmKGQuaW50ZXJhY3Rpb25TdGF0ZS5ob3ZlcmVkKSB7XG4gICAgICAgICAgICAgICAgZXZlbnRTZXQudW5ob3Zlcih0aGlzLCBkLCBzYW5rZXkpO1xuICAgICAgICAgICAgICAgIGQuaW50ZXJhY3Rpb25TdGF0ZS5ob3ZlcmVkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZighZC5pbnRlcmFjdGlvblN0YXRlLmRyYWdJblByb2dyZXNzICYmICFkLnBhcnRPZkdyb3VwKSB7XG4gICAgICAgICAgICAgICAgZXZlbnRTZXQuc2VsZWN0KHRoaXMsIGQsIHNhbmtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xufVxuXG5mdW5jdGlvbiBhdHRhY2hEcmFnSGFuZGxlcihzYW5rZXlOb2RlLCBzYW5rZXlMaW5rLCBjYWxsYmFja3MsIGdkKSB7XG4gICAgdmFyIGRyYWdCZWhhdmlvciA9IGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAub3JpZ2luKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgeDogZC5ub2RlLngwICsgZC52aXNpYmxlV2lkdGggLyAyLFxuICAgICAgICAgICAgICAgIHk6IGQubm9kZS55MCArIGQudmlzaWJsZUhlaWdodCAvIDJcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pXG5cbiAgICAgICAgLm9uKCdkcmFnc3RhcnQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBpZihkLmFycmFuZ2VtZW50ID09PSAnZml4ZWQnKSByZXR1cm47XG4gICAgICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGdkLl9mdWxsTGF5b3V0Ll9pbmZvbGF5ZXIsICdnJywgJ2RyYWdjb3ZlcicsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICAgICAgICBnZC5fZnVsbExheW91dC5fZHJhZ0NvdmVyID0gcztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgTGliLnJhaXNlVG9Ub3AodGhpcyk7XG4gICAgICAgICAgICBkLmludGVyYWN0aW9uU3RhdGUuZHJhZ0luUHJvZ3Jlc3MgPSBkLm5vZGU7XG5cbiAgICAgICAgICAgIHNhdmVDdXJyZW50RHJhZ1Bvc2l0aW9uKGQubm9kZSk7XG4gICAgICAgICAgICBpZihkLmludGVyYWN0aW9uU3RhdGUuaG92ZXJlZCkge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrcy5ub2RlRXZlbnRzLnVuaG92ZXIuYXBwbHkoMCwgZC5pbnRlcmFjdGlvblN0YXRlLmhvdmVyZWQpO1xuICAgICAgICAgICAgICAgIGQuaW50ZXJhY3Rpb25TdGF0ZS5ob3ZlcmVkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihkLmFycmFuZ2VtZW50ID09PSAnc25hcCcpIHtcbiAgICAgICAgICAgICAgICB2YXIgZm9yY2VLZXkgPSBkLnRyYWNlSWQgKyAnfCcgKyBkLmtleTtcbiAgICAgICAgICAgICAgICBpZihkLmZvcmNlTGF5b3V0c1tmb3JjZUtleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgZC5mb3JjZUxheW91dHNbZm9yY2VLZXldLmFscGhhKDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7IC8vIG1ha2UgYSBmb3JjZUxheW91dCBpZiBuZWVkZWRcbiAgICAgICAgICAgICAgICAgICAgYXR0YWNoRm9yY2Uoc2Fua2V5Tm9kZSwgZm9yY2VLZXksIGQsIGdkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3RhcnRGb3JjZShzYW5rZXlOb2RlLCBzYW5rZXlMaW5rLCBkLCBmb3JjZUtleSwgZ2QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuXG4gICAgICAgIC5vbignZHJhZycsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIGlmKGQuYXJyYW5nZW1lbnQgPT09ICdmaXhlZCcpIHJldHVybjtcbiAgICAgICAgICAgIHZhciB4ID0gZDMuZXZlbnQueDtcbiAgICAgICAgICAgIHZhciB5ID0gZDMuZXZlbnQueTtcbiAgICAgICAgICAgIGlmKGQuYXJyYW5nZW1lbnQgPT09ICdzbmFwJykge1xuICAgICAgICAgICAgICAgIGQubm9kZS54MCA9IHggLSBkLnZpc2libGVXaWR0aCAvIDI7XG4gICAgICAgICAgICAgICAgZC5ub2RlLngxID0geCArIGQudmlzaWJsZVdpZHRoIC8gMjtcbiAgICAgICAgICAgICAgICBkLm5vZGUueTAgPSB5IC0gZC52aXNpYmxlSGVpZ2h0IC8gMjtcbiAgICAgICAgICAgICAgICBkLm5vZGUueTEgPSB5ICsgZC52aXNpYmxlSGVpZ2h0IC8gMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYoZC5hcnJhbmdlbWVudCA9PT0gJ2ZyZWVmb3JtJykge1xuICAgICAgICAgICAgICAgICAgICBkLm5vZGUueDAgPSB4IC0gZC52aXNpYmxlV2lkdGggLyAyO1xuICAgICAgICAgICAgICAgICAgICBkLm5vZGUueDEgPSB4ICsgZC52aXNpYmxlV2lkdGggLyAyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB5ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oZC5zaXplIC0gZC52aXNpYmxlSGVpZ2h0IC8gMiwgeSkpO1xuICAgICAgICAgICAgICAgIGQubm9kZS55MCA9IHkgLSBkLnZpc2libGVIZWlnaHQgLyAyO1xuICAgICAgICAgICAgICAgIGQubm9kZS55MSA9IHkgKyBkLnZpc2libGVIZWlnaHQgLyAyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzYXZlQ3VycmVudERyYWdQb3NpdGlvbihkLm5vZGUpO1xuICAgICAgICAgICAgaWYoZC5hcnJhbmdlbWVudCAhPT0gJ3NuYXAnKSB7XG4gICAgICAgICAgICAgICAgZC5zYW5rZXkudXBkYXRlKGQuZ3JhcGgpO1xuICAgICAgICAgICAgICAgIHVwZGF0ZVNoYXBlcyhzYW5rZXlOb2RlLmZpbHRlcihzYW1lTGF5ZXIoZCkpLCBzYW5rZXlMaW5rKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcblxuICAgICAgICAub24oJ2RyYWdlbmQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBpZihkLmFycmFuZ2VtZW50ID09PSAnZml4ZWQnKSByZXR1cm47XG4gICAgICAgICAgICBkLmludGVyYWN0aW9uU3RhdGUuZHJhZ0luUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBkLm5vZGUuY2hpbGRyZW5Ob2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGQubm9kZS5jaGlsZHJlbk5vZGVzW2ldLnggPSBkLm5vZGUueDtcbiAgICAgICAgICAgICAgICBkLm5vZGUuY2hpbGRyZW5Ob2Rlc1tpXS55ID0gZC5ub2RlLnk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihkLmFycmFuZ2VtZW50ICE9PSAnc25hcCcpIHBlcnNpc3RGaW5hbE5vZGVQb3NpdGlvbnMoZCwgZ2QpO1xuICAgICAgICB9KTtcblxuICAgIHNhbmtleU5vZGVcbiAgICAgICAgLm9uKCcuZHJhZycsIG51bGwpIC8vIHJlbW92ZSBwb3NzaWJsZSBwcmV2aW91cyBoYW5kbGVyc1xuICAgICAgICAuY2FsbChkcmFnQmVoYXZpb3IpO1xufVxuXG5mdW5jdGlvbiBhdHRhY2hGb3JjZShzYW5rZXlOb2RlLCBmb3JjZUtleSwgZCwgZ2QpIHtcbiAgICAvLyBBdHRhY2ggZm9yY2UgdG8gbm9kZXMgaW4gdGhlIHNhbWUgY29sdW1uIChzYW1lIHggY29vcmRpbmF0ZSlcbiAgICBzd2l0Y2hUb0ZvcmNlRm9ybWF0KGQuZ3JhcGgubm9kZXMpO1xuICAgIHZhciBub2RlcyA9IGQuZ3JhcGgubm9kZXNcbiAgICAgICAgLmZpbHRlcihmdW5jdGlvbihuKSB7cmV0dXJuIG4ub3JpZ2luYWxYID09PSBkLm5vZGUub3JpZ2luYWxYO30pXG4gICAgICAgIC8vIEZpbHRlciBvdXQgY2hpbGRyZW5cbiAgICAgICAgLmZpbHRlcihmdW5jdGlvbihuKSB7cmV0dXJuICFuLnBhcnRPZkdyb3VwO30pO1xuICAgIGQuZm9yY2VMYXlvdXRzW2ZvcmNlS2V5XSA9IGQzRm9yY2UuZm9yY2VTaW11bGF0aW9uKG5vZGVzKVxuICAgICAgICAuYWxwaGFEZWNheSgwKVxuICAgICAgICAuZm9yY2UoJ2NvbGxpZGUnLCBkM0ZvcmNlLmZvcmNlQ29sbGlkZSgpXG4gICAgICAgICAgICAucmFkaXVzKGZ1bmN0aW9uKG4pIHtyZXR1cm4gbi5keSAvIDIgKyBkLm5vZGVQYWQgLyAyO30pXG4gICAgICAgICAgICAuc3RyZW5ndGgoMSlcbiAgICAgICAgICAgIC5pdGVyYXRpb25zKGMuZm9yY2VJdGVyYXRpb25zKSlcbiAgICAgICAgLmZvcmNlKCdjb25zdHJhaW4nLCBzbmFwcGluZ0ZvcmNlKHNhbmtleU5vZGUsIGZvcmNlS2V5LCBub2RlcywgZCwgZ2QpKVxuICAgICAgICAuc3RvcCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydEZvcmNlKHNhbmtleU5vZGUsIHNhbmtleUxpbmssIGQsIGZvcmNlS2V5LCBnZCkge1xuICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZnVuY3Rpb24gZmFzdGVyKCkge1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgYy5mb3JjZVRpY2tzUGVyRnJhbWU7IGkrKykge1xuICAgICAgICAgICAgZC5mb3JjZUxheW91dHNbZm9yY2VLZXldLnRpY2soKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBub2RlcyA9IGQuZ3JhcGgubm9kZXM7XG4gICAgICAgIHN3aXRjaFRvU2Fua2V5Rm9ybWF0KG5vZGVzKTtcblxuICAgICAgICBkLnNhbmtleS51cGRhdGUoZC5ncmFwaCk7XG4gICAgICAgIHVwZGF0ZVNoYXBlcyhzYW5rZXlOb2RlLmZpbHRlcihzYW1lTGF5ZXIoZCkpLCBzYW5rZXlMaW5rKTtcblxuICAgICAgICBpZihkLmZvcmNlTGF5b3V0c1tmb3JjZUtleV0uYWxwaGEoKSA+IDApIHtcbiAgICAgICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZmFzdGVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSB0aGUgZmluYWwgeCBwb3NpdGlvbiBpcyBlcXVhbCB0byBpdHMgb3JpZ2luYWwgdmFsdWVcbiAgICAgICAgICAgIC8vIGJlY2F1c2UgdGhlIGZvcmNlIHNpbXVsYXRpb24gd2lsbCBoYXZlIG51bWVyaWNhbCBlcnJvclxuICAgICAgICAgICAgdmFyIHggPSBkLm5vZGUub3JpZ2luYWxYO1xuICAgICAgICAgICAgZC5ub2RlLngwID0geCAtIGQudmlzaWJsZVdpZHRoIC8gMjtcbiAgICAgICAgICAgIGQubm9kZS54MSA9IHggKyBkLnZpc2libGVXaWR0aCAvIDI7XG5cbiAgICAgICAgICAgIHBlcnNpc3RGaW5hbE5vZGVQb3NpdGlvbnMoZCwgZ2QpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHNuYXBwaW5nRm9yY2Uoc2Fua2V5Tm9kZSwgZm9yY2VLZXksIG5vZGVzLCBkKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIF9zbmFwcGluZ0ZvcmNlKCkge1xuICAgICAgICB2YXIgbWF4VmVsb2NpdHkgPSAwO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBuID0gbm9kZXNbaV07XG4gICAgICAgICAgICBpZihuID09PSBkLmludGVyYWN0aW9uU3RhdGUuZHJhZ0luUHJvZ3Jlc3MpIHsgLy8gY29uc3RyYWluIG5vZGUgcG9zaXRpb24gdG8gdGhlIGRyYWdnaW5nIHBvaW50ZXJcbiAgICAgICAgICAgICAgICBuLnggPSBuLmxhc3REcmFnZ2VkWDtcbiAgICAgICAgICAgICAgICBuLnkgPSBuLmxhc3REcmFnZ2VkWTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbi52eCA9IChuLm9yaWdpbmFsWCAtIG4ueCkgLyBjLmZvcmNlVGlja3NQZXJGcmFtZTsgLy8gc25hcCB0byBsYXllclxuICAgICAgICAgICAgICAgIG4ueSA9IE1hdGgubWluKGQuc2l6ZSAtIG4uZHkgLyAyLCBNYXRoLm1heChuLmR5IC8gMiwgbi55KSk7IC8vIGNvbnN0cmFpbiB0byBleHRlbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1heFZlbG9jaXR5ID0gTWF0aC5tYXgobWF4VmVsb2NpdHksIE1hdGguYWJzKG4udngpLCBNYXRoLmFicyhuLnZ5KSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoIWQuaW50ZXJhY3Rpb25TdGF0ZS5kcmFnSW5Qcm9ncmVzcyAmJiBtYXhWZWxvY2l0eSA8IDAuMSAmJiBkLmZvcmNlTGF5b3V0c1tmb3JjZUtleV0uYWxwaGEoKSA+IDApIHtcbiAgICAgICAgICAgIGQuZm9yY2VMYXlvdXRzW2ZvcmNlS2V5XS5hbHBoYSgwKTsgLy8gVGhpcyB3aWxsIHN0b3AgdGhlIGFuaW1hdGlvbiBsb29wXG4gICAgICAgIH1cbiAgICB9O1xufVxuXG4vLyBiYXNpYyBkYXRhIHV0aWxpdGllc1xuXG5mdW5jdGlvbiBwZXJzaXN0RmluYWxOb2RlUG9zaXRpb25zKGQsIGdkKSB7XG4gICAgdmFyIHggPSBbXTtcbiAgICB2YXIgeSA9IFtdO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBkLmdyYXBoLm5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBub2RlWCA9IChkLmdyYXBoLm5vZGVzW2ldLngwICsgZC5ncmFwaC5ub2Rlc1tpXS54MSkgLyAyO1xuICAgICAgICB2YXIgbm9kZVkgPSAoZC5ncmFwaC5ub2Rlc1tpXS55MCArIGQuZ3JhcGgubm9kZXNbaV0ueTEpIC8gMjtcbiAgICAgICAgeC5wdXNoKG5vZGVYIC8gZC5maWd1cmUud2lkdGgpO1xuICAgICAgICB5LnB1c2gobm9kZVkgLyBkLmZpZ3VyZS5oZWlnaHQpO1xuICAgIH1cbiAgICBSZWdpc3RyeS5jYWxsKCdfZ3VpUmVzdHlsZScsIGdkLCB7XG4gICAgICAgICdub2RlLngnOiBbeF0sXG4gICAgICAgICdub2RlLnknOiBbeV1cbiAgICB9LCBkLnRyYWNlLmluZGV4KVxuICAgIC50aGVuKGZ1bmN0aW9uKCkge1xuICAgICAgICBpZihnZC5fZnVsbExheW91dC5fZHJhZ0NvdmVyKSBnZC5fZnVsbExheW91dC5fZHJhZ0NvdmVyLnJlbW92ZSgpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBwZXJzaXN0T3JpZ2luYWxQbGFjZShub2Rlcykge1xuICAgIHZhciBkaXN0aW5jdExheWVyUG9zaXRpb25zID0gW107XG4gICAgdmFyIGk7XG4gICAgZm9yKGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbm9kZXNbaV0ub3JpZ2luYWxYID0gKG5vZGVzW2ldLngwICsgbm9kZXNbaV0ueDEpIC8gMjtcbiAgICAgICAgbm9kZXNbaV0ub3JpZ2luYWxZID0gKG5vZGVzW2ldLnkwICsgbm9kZXNbaV0ueTEpIC8gMjtcbiAgICAgICAgaWYoZGlzdGluY3RMYXllclBvc2l0aW9ucy5pbmRleE9mKG5vZGVzW2ldLm9yaWdpbmFsWCkgPT09IC0xKSB7XG4gICAgICAgICAgICBkaXN0aW5jdExheWVyUG9zaXRpb25zLnB1c2gobm9kZXNbaV0ub3JpZ2luYWxYKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkaXN0aW5jdExheWVyUG9zaXRpb25zLnNvcnQoZnVuY3Rpb24oYSwgYikge3JldHVybiBhIC0gYjt9KTtcbiAgICBmb3IoaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBub2Rlc1tpXS5vcmlnaW5hbExheWVySW5kZXggPSBkaXN0aW5jdExheWVyUG9zaXRpb25zLmluZGV4T2Yobm9kZXNbaV0ub3JpZ2luYWxYKTtcbiAgICAgICAgbm9kZXNbaV0ub3JpZ2luYWxMYXllciA9IG5vZGVzW2ldLm9yaWdpbmFsTGF5ZXJJbmRleCAvIChkaXN0aW5jdExheWVyUG9zaXRpb25zLmxlbmd0aCAtIDEpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc2F2ZUN1cnJlbnREcmFnUG9zaXRpb24oZCkge1xuICAgIGQubGFzdERyYWdnZWRYID0gZC54MCArIGQuZHggLyAyO1xuICAgIGQubGFzdERyYWdnZWRZID0gZC55MCArIGQuZHkgLyAyO1xufVxuXG5mdW5jdGlvbiBzYW1lTGF5ZXIoZCkge1xuICAgIHJldHVybiBmdW5jdGlvbihuKSB7cmV0dXJuIG4ubm9kZS5vcmlnaW5hbFggPT09IGQubm9kZS5vcmlnaW5hbFg7fTtcbn1cblxuZnVuY3Rpb24gc3dpdGNoVG9Gb3JjZUZvcm1hdChub2Rlcykge1xuICAgIC8vIGZvcmNlIHVzZXMgeCwgeSBhcyBjZW50ZXJzXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG5vZGVzW2ldLnkgPSAobm9kZXNbaV0ueTAgKyBub2Rlc1tpXS55MSkgLyAyO1xuICAgICAgICBub2Rlc1tpXS54ID0gKG5vZGVzW2ldLngwICsgbm9kZXNbaV0ueDEpIC8gMjtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHN3aXRjaFRvU2Fua2V5Rm9ybWF0KG5vZGVzKSB7XG4gICAgLy8gc2Fua2V5IHVzZXMgeDAsIHgxLCB5MCwgeTFcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbm9kZXNbaV0ueTAgPSBub2Rlc1tpXS55IC0gbm9kZXNbaV0uZHkgLyAyO1xuICAgICAgICBub2Rlc1tpXS55MSA9IG5vZGVzW2ldLnkwICsgbm9kZXNbaV0uZHk7XG5cbiAgICAgICAgbm9kZXNbaV0ueDAgPSBub2Rlc1tpXS54IC0gbm9kZXNbaV0uZHggLyAyO1xuICAgICAgICBub2Rlc1tpXS54MSA9IG5vZGVzW2ldLngwICsgbm9kZXNbaV0uZHg7XG4gICAgfVxufVxuXG4vLyBzY2VuZSBncmFwaFxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihnZCwgc3ZnLCBjYWxjRGF0YSwgbGF5b3V0LCBjYWxsYmFja3MpIHtcbiAgICAvLyBUbyBwcmV2ZW50IGFuaW1hdGlvbiBvbiBmaXJzdCByZW5kZXJcbiAgICB2YXIgZmlyc3RSZW5kZXIgPSBmYWxzZTtcbiAgICBMaWIuZW5zdXJlU2luZ2xlKGdkLl9mdWxsTGF5b3V0Ll9pbmZvbGF5ZXIsICdnJywgJ2ZpcnN0LXJlbmRlcicsIGZ1bmN0aW9uKCkge1xuICAgICAgICBmaXJzdFJlbmRlciA9IHRydWU7XG4gICAgfSk7XG5cbiAgICAvLyBUbyBwcmV2ZW50IGFuaW1hdGlvbiBvbiBkcmFnZ2luZ1xuICAgIHZhciBkcmFnY292ZXIgPSBnZC5fZnVsbExheW91dC5fZHJhZ0NvdmVyO1xuXG4gICAgdmFyIHN0eWxlZERhdGEgPSBjYWxjRGF0YVxuICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbihkKSB7cmV0dXJuIHVud3JhcChkKS50cmFjZS52aXNpYmxlO30pXG4gICAgICAgICAgICAubWFwKHNhbmtleU1vZGVsLmJpbmQobnVsbCwgbGF5b3V0KSk7XG5cbiAgICB2YXIgc2Fua2V5ID0gc3ZnLnNlbGVjdEFsbCgnLicgKyBjLmNuLnNhbmtleSlcbiAgICAgICAgLmRhdGEoc3R5bGVkRGF0YSwga2V5RnVuKTtcblxuICAgIHNhbmtleS5leGl0KClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgc2Fua2V5LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Fua2V5LCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ2JveC1zaXppbmcnLCAnY29udGVudC1ib3gnKVxuICAgICAgICAuc3R5bGUoJ3Bvc2l0aW9uJywgJ2Fic29sdXRlJylcbiAgICAgICAgLnN0eWxlKCdsZWZ0JywgMClcbiAgICAgICAgLnN0eWxlKCdzaGFwZS1yZW5kZXJpbmcnLCAnZ2VvbWV0cmljUHJlY2lzaW9uJylcbiAgICAgICAgLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhdXRvJylcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHNhbmtleVRyYW5zZm9ybSk7XG5cbiAgICBzYW5rZXkuZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgIGdkLl9mdWxsRGF0YVtpXS5fc2Fua2V5ID0gZDtcbiAgICAgICAgLy8gQ3JlYXRlIGRyYWdib3ggaWYgbWlzc2luZ1xuICAgICAgICB2YXIgZHJhZ2JveENsYXNzTmFtZSA9ICdiZ3NhbmtleS0nICsgZC50cmFjZS51aWQgKyAnLScgKyBpO1xuICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGdkLl9mdWxsTGF5b3V0Ll9kcmFnZ2VycywgJ3JlY3QnLCBkcmFnYm94Q2xhc3NOYW1lKTtcblxuICAgICAgICBnZC5fZnVsbERhdGFbaV0uX2JnUmVjdCA9IGQzLnNlbGVjdCgnLicgKyBkcmFnYm94Q2xhc3NOYW1lKTtcblxuICAgICAgICAvLyBTdHlsZSBkcmFnYm94XG4gICAgICAgIGdkLl9mdWxsRGF0YVtpXS5fYmdSZWN0XG4gICAgICAgICAgLnN0eWxlKCdwb2ludGVyLWV2ZW50cycsICdhbGwnKVxuICAgICAgICAgIC5hdHRyKCd3aWR0aCcsIGQud2lkdGgpXG4gICAgICAgICAgLmF0dHIoJ2hlaWdodCcsIGQuaGVpZ2h0KVxuICAgICAgICAgIC5hdHRyKCd4JywgZC50cmFuc2xhdGVYKVxuICAgICAgICAgIC5hdHRyKCd5JywgZC50cmFuc2xhdGVZKVxuICAgICAgICAgIC5jbGFzc2VkKCdiZ3NhbmtleScsIHRydWUpXG4gICAgICAgICAgLnN0eWxlKHtmaWxsOiAndHJhbnNwYXJlbnQnLCAnc3Ryb2tlLXdpZHRoJzogMH0pO1xuICAgIH0pO1xuXG4gICAgc2Fua2V5LnRyYW5zaXRpb24oKVxuICAgICAgICAuZWFzZShjLmVhc2UpLmR1cmF0aW9uKGMuZHVyYXRpb24pXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBzYW5rZXlUcmFuc2Zvcm0pO1xuXG4gICAgdmFyIHNhbmtleUxpbmtzID0gc2Fua2V5LnNlbGVjdEFsbCgnLicgKyBjLmNuLnNhbmtleUxpbmtzKVxuICAgICAgICAuZGF0YShyZXBlYXQsIGtleUZ1bik7XG5cbiAgICBzYW5rZXlMaW5rcy5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNhbmtleUxpbmtzLCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpO1xuXG4gICAgdmFyIHNhbmtleUxpbmsgPSBzYW5rZXlMaW5rcy5zZWxlY3RBbGwoJy4nICsgYy5jbi5zYW5rZXlMaW5rKVxuICAgICAgICAgIC5kYXRhKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgdmFyIGxpbmtzID0gZC5ncmFwaC5saW5rcztcbiAgICAgICAgICAgICAgcmV0dXJuIGxpbmtzXG4gICAgICAgICAgICAgICAgLmZpbHRlcihmdW5jdGlvbihsKSB7cmV0dXJuIGwudmFsdWU7fSlcbiAgICAgICAgICAgICAgICAubWFwKGxpbmtNb2RlbC5iaW5kKG51bGwsIGQpKTtcbiAgICAgICAgICB9LCBrZXlGdW4pO1xuXG4gICAgc2Fua2V5TGlua1xuICAgICAgICAgIC5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgLmNsYXNzZWQoYy5jbi5zYW5rZXlMaW5rLCB0cnVlKVxuICAgICAgICAgIC5jYWxsKGF0dGFjaFBvaW50ZXJFdmVudHMsIHNhbmtleSwgY2FsbGJhY2tzLmxpbmtFdmVudHMpO1xuXG4gICAgc2Fua2V5TGlua1xuICAgICAgICAuc3R5bGUoJ3N0cm9rZScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBzYWxpZW50RW5vdWdoKGQpID8gQ29sb3IudGlueVJHQih0aW55Y29sb3IoZC5saW5rTGluZUNvbG9yKSkgOiBkLnRpbnlDb2xvckh1ZTtcbiAgICAgICAgfSlcbiAgICAgICAgLnN0eWxlKCdzdHJva2Utb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBzYWxpZW50RW5vdWdoKGQpID8gQ29sb3Iub3BhY2l0eShkLmxpbmtMaW5lQ29sb3IpIDogZC50aW55Q29sb3JBbHBoYTtcbiAgICAgICAgfSlcbiAgICAgICAgLnN0eWxlKCdmaWxsJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQudGlueUNvbG9ySHVlO1xuICAgICAgICB9KVxuICAgICAgICAuc3R5bGUoJ2ZpbGwtb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLnRpbnlDb2xvckFscGhhO1xuICAgICAgICB9KVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS13aWR0aCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBzYWxpZW50RW5vdWdoKGQpID8gZC5saW5rTGluZVdpZHRoIDogMTtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ2QnLCBsaW5rUGF0aCgpKTtcblxuICAgIHNhbmtleUxpbmtcbiAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oKSB7IHJldHVybiAoZ2QuX2NvbnRleHQuc3RhdGljUGxvdCB8fCBmaXJzdFJlbmRlciB8fCBkcmFnY292ZXIpID8gMSA6IDA7fSlcbiAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAuZWFzZShjLmVhc2UpLmR1cmF0aW9uKGMuZHVyYXRpb24pXG4gICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDEpO1xuXG4gICAgc2Fua2V5TGluay5leGl0KClcbiAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAuZWFzZShjLmVhc2UpLmR1cmF0aW9uKGMuZHVyYXRpb24pXG4gICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDApXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIHZhciBzYW5rZXlOb2RlU2V0ID0gc2Fua2V5LnNlbGVjdEFsbCgnLicgKyBjLmNuLnNhbmtleU5vZGVTZXQpXG4gICAgICAgIC5kYXRhKHJlcGVhdCwga2V5RnVuKTtcblxuICAgIHNhbmtleU5vZGVTZXQuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5zYW5rZXlOb2RlU2V0LCB0cnVlKTtcblxuICAgIHNhbmtleU5vZGVTZXRcbiAgICAgICAgLnN0eWxlKCdjdXJzb3InLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBzd2l0Y2goZC5hcnJhbmdlbWVudCkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2ZpeGVkJzogcmV0dXJuICdkZWZhdWx0JztcbiAgICAgICAgICAgICAgICBjYXNlICdwZXJwZW5kaWN1bGFyJzogcmV0dXJuICducy1yZXNpemUnO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHJldHVybiAnbW92ZSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIHNhbmtleU5vZGUgPSBzYW5rZXlOb2RlU2V0LnNlbGVjdEFsbCgnLicgKyBjLmNuLnNhbmtleU5vZGUpXG4gICAgICAgIC5kYXRhKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBub2RlcyA9IGQuZ3JhcGgubm9kZXM7XG4gICAgICAgICAgICBwZXJzaXN0T3JpZ2luYWxQbGFjZShub2Rlcyk7XG4gICAgICAgICAgICByZXR1cm4gbm9kZXNcbiAgICAgICAgICAgICAgLm1hcChub2RlTW9kZWwuYmluZChudWxsLCBkKSk7XG4gICAgICAgIH0sIGtleUZ1bik7XG5cbiAgICBzYW5rZXlOb2RlLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Fua2V5Tm9kZSwgdHJ1ZSlcbiAgICAgICAgLmNhbGwodXBkYXRlTm9kZVBvc2l0aW9ucylcbiAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24obikgeyByZXR1cm4gKChnZC5fY29udGV4dC5zdGF0aWNQbG90IHx8IGZpcnN0UmVuZGVyKSAmJiAhbi5wYXJ0T2ZHcm91cCkgPyAxIDogMDt9KTtcblxuICAgIHNhbmtleU5vZGVcbiAgICAgICAgLmNhbGwoYXR0YWNoUG9pbnRlckV2ZW50cywgc2Fua2V5LCBjYWxsYmFja3Mubm9kZUV2ZW50cylcbiAgICAgICAgLmNhbGwoYXR0YWNoRHJhZ0hhbmRsZXIsIHNhbmtleUxpbmssIGNhbGxiYWNrcywgZ2QpOyAvLyBoYXMgdG8gYmUgaGVyZSBhcyBpdCBiaW5kcyBzYW5rZXlMaW5rXG5cbiAgICBzYW5rZXlOb2RlXG4gICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgLmVhc2UoYy5lYXNlKS5kdXJhdGlvbihjLmR1cmF0aW9uKVxuICAgICAgICAuY2FsbCh1cGRhdGVOb2RlUG9zaXRpb25zKVxuICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCBmdW5jdGlvbihuKSB7IHJldHVybiBuLnBhcnRPZkdyb3VwID8gMCA6IDE7fSk7XG5cbiAgICBzYW5rZXlOb2RlLmV4aXQoKVxuICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGMuZWFzZSkuZHVyYXRpb24oYy5kdXJhdGlvbilcbiAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgdmFyIG5vZGVSZWN0ID0gc2Fua2V5Tm9kZS5zZWxlY3RBbGwoJy4nICsgYy5jbi5ub2RlUmVjdClcbiAgICAgICAgLmRhdGEocmVwZWF0KTtcblxuICAgIG5vZGVSZWN0LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24ubm9kZVJlY3QsIHRydWUpXG4gICAgICAgIC5jYWxsKHNpemVOb2RlKTtcblxuICAgIG5vZGVSZWN0XG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgZnVuY3Rpb24oZCkge3JldHVybiBkLm5vZGVMaW5lV2lkdGg7fSlcbiAgICAgICAgLnN0eWxlKCdzdHJva2UnLCBmdW5jdGlvbihkKSB7cmV0dXJuIENvbG9yLnRpbnlSR0IodGlueWNvbG9yKGQubm9kZUxpbmVDb2xvcikpO30pXG4gICAgICAgIC5zdHlsZSgnc3Ryb2tlLW9wYWNpdHknLCBmdW5jdGlvbihkKSB7cmV0dXJuIENvbG9yLm9wYWNpdHkoZC5ub2RlTGluZUNvbG9yKTt9KVxuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQudGlueUNvbG9ySHVlO30pXG4gICAgICAgIC5zdHlsZSgnZmlsbC1vcGFjaXR5JywgZnVuY3Rpb24oZCkge3JldHVybiBkLnRpbnlDb2xvckFscGhhO30pO1xuXG4gICAgbm9kZVJlY3QudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGMuZWFzZSkuZHVyYXRpb24oYy5kdXJhdGlvbilcbiAgICAgICAgLmNhbGwoc2l6ZU5vZGUpO1xuXG4gICAgdmFyIG5vZGVDYXB0dXJlID0gc2Fua2V5Tm9kZS5zZWxlY3RBbGwoJy4nICsgYy5jbi5ub2RlQ2FwdHVyZSlcbiAgICAgICAgLmRhdGEocmVwZWF0KTtcblxuICAgIG5vZGVDYXB0dXJlLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24ubm9kZUNhcHR1cmUsIHRydWUpXG4gICAgICAgIC5zdHlsZSgnZmlsbC1vcGFjaXR5JywgMCk7XG5cbiAgICBub2RlQ2FwdHVyZVxuICAgICAgICAuYXR0cigneCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC56b25lWDt9KVxuICAgICAgICAuYXR0cigneScsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC56b25lWTt9KVxuICAgICAgICAuYXR0cignd2lkdGgnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuem9uZVdpZHRoO30pXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuem9uZUhlaWdodDt9KTtcblxuICAgIHZhciBub2RlQ2VudGVyZWQgPSBzYW5rZXlOb2RlLnNlbGVjdEFsbCgnLicgKyBjLmNuLm5vZGVDZW50ZXJlZClcbiAgICAgICAgLmRhdGEocmVwZWF0KTtcblxuICAgIG5vZGVDZW50ZXJlZC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLm5vZGVDZW50ZXJlZCwgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIG5vZGVDZW50ZXJpbmcpO1xuXG4gICAgbm9kZUNlbnRlcmVkXG4gICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgLmVhc2UoYy5lYXNlKS5kdXJhdGlvbihjLmR1cmF0aW9uKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgbm9kZUNlbnRlcmluZyk7XG5cbiAgICB2YXIgbm9kZUxhYmVsR3VpZGUgPSBub2RlQ2VudGVyZWQuc2VsZWN0QWxsKCcuJyArIGMuY24ubm9kZUxhYmVsR3VpZGUpXG4gICAgICAgIC5kYXRhKHJlcGVhdCk7XG5cbiAgICBub2RlTGFiZWxHdWlkZS5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLm5vZGVMYWJlbEd1aWRlLCB0cnVlKVxuICAgICAgICAuYXR0cignaWQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQudW5pcXVlTm9kZUxhYmVsUGF0aElkO30pXG4gICAgICAgIC5hdHRyKCdkJywgdGV4dEd1aWRlUGF0aClcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHNhbmtleUludmVyc2VUcmFuc2Zvcm0pO1xuXG4gICAgbm9kZUxhYmVsR3VpZGVcbiAgICAgICAgLnRyYW5zaXRpb24oKVxuICAgICAgICAuZWFzZShjLmVhc2UpLmR1cmF0aW9uKGMuZHVyYXRpb24pXG4gICAgICAgIC5hdHRyKCdkJywgdGV4dEd1aWRlUGF0aClcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIHNhbmtleUludmVyc2VUcmFuc2Zvcm0pO1xuXG4gICAgdmFyIG5vZGVMYWJlbCA9IG5vZGVDZW50ZXJlZC5zZWxlY3RBbGwoJy4nICsgYy5jbi5ub2RlTGFiZWwpXG4gICAgICAgIC5kYXRhKHJlcGVhdCk7XG5cbiAgICBub2RlTGFiZWwuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5ub2RlTGFiZWwsIHRydWUpXG4gICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCB0ZXh0RmxpcClcbiAgICAgICAgLnN0eWxlKCd1c2VyLXNlbGVjdCcsICdub25lJylcbiAgICAgICAgLnN0eWxlKCdjdXJzb3InLCAnZGVmYXVsdCcpXG4gICAgICAgIC5zdHlsZSgnZmlsbCcsICdibGFjaycpO1xuXG4gICAgbm9kZUxhYmVsXG4gICAgICAgIC5zdHlsZSgndGV4dC1zaGFkb3cnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5ob3Jpem9udGFsID8gJy0xcHggMXB4IDFweCAjZmZmLCAxcHggMXB4IDFweCAjZmZmLCAxcHggLTFweCAxcHggI2ZmZiwgLTFweCAtMXB4IDFweCAjZmZmJyA6ICdub25lJztcbiAgICAgICAgfSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge0RyYXdpbmcuZm9udChub2RlTGFiZWwsIGQudGV4dEZvbnQpO30pO1xuXG4gICAgbm9kZUxhYmVsXG4gICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgLmVhc2UoYy5lYXNlKS5kdXJhdGlvbihjLmR1cmF0aW9uKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgdGV4dEZsaXApO1xuXG4gICAgdmFyIG5vZGVMYWJlbFRleHRQYXRoID0gbm9kZUxhYmVsLnNlbGVjdEFsbCgnLicgKyBjLmNuLm5vZGVMYWJlbFRleHRQYXRoKVxuICAgICAgICAuZGF0YShyZXBlYXQpO1xuXG4gICAgbm9kZUxhYmVsVGV4dFBhdGguZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCd0ZXh0UGF0aCcpXG4gICAgICAgIC5jbGFzc2VkKGMuY24ubm9kZUxhYmVsVGV4dFBhdGgsIHRydWUpXG4gICAgICAgIC5hdHRyKCdhbGlnbm1lbnQtYmFzZWxpbmUnLCAnbWlkZGxlJylcbiAgICAgICAgLmF0dHIoJ3hsaW5rOmhyZWYnLCBmdW5jdGlvbihkKSB7cmV0dXJuICcjJyArIGQudW5pcXVlTm9kZUxhYmVsUGF0aElkO30pXG4gICAgICAgIC5hdHRyKCdzdGFydE9mZnNldCcsIG5vZGVUZXh0T2Zmc2V0KVxuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCBub2RlVGV4dENvbG9yKTtcblxuICAgIG5vZGVMYWJlbFRleHRQYXRoXG4gICAgICAgIC50ZXh0KGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5ob3Jpem9udGFsIHx8IGQubm9kZS5keSA+IDUgPyBkLm5vZGUubGFiZWwgOiAnJzt9KVxuICAgICAgICAuYXR0cigndGV4dC1hbmNob3InLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuaG9yaXpvbnRhbCAmJiBkLmxlZnQgPyAnZW5kJyA6ICdzdGFydCc7fSk7XG5cbiAgICBub2RlTGFiZWxUZXh0UGF0aFxuICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGMuZWFzZSkuZHVyYXRpb24oYy5kdXJhdGlvbilcbiAgICAgICAgLmF0dHIoJ3N0YXJ0T2Zmc2V0Jywgbm9kZVRleHRPZmZzZXQpXG4gICAgICAgIC5zdHlsZSgnZmlsbCcsIG5vZGVUZXh0Q29sb3IpO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL2d1cFwiOjcxNyxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9jb25zdGFudHNcIjoxMTA1LFwiQHBsb3RseS9kMy1zYW5rZXlcIjo1NCxcIkBwbG90bHkvZDMtc2Fua2V5LWNpcmN1bGFyXCI6NTMsXCJkM1wiOjE2MyxcImQzLWZvcmNlXCI6MTU2LFwiZDMtaW50ZXJwb2xhdGVcIjoxNTgsXCJ0aW55Y29sb3IyXCI6NTM3fV0sMTExMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2VsZWN0UG9pbnRzKHNlYXJjaEluZm8sIHNlbGVjdGlvblRlc3Rlcikge1xuICAgIHZhciBjZCA9IHNlYXJjaEluZm8uY2Q7XG4gICAgdmFyIHNlbGVjdGlvbiA9IFtdO1xuICAgIHZhciBmdWxsRGF0YSA9IGNkWzBdLnRyYWNlO1xuXG4gICAgdmFyIG5vZGVzID0gZnVsbERhdGEuX3NhbmtleS5ncmFwaC5ub2RlcztcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICBpZihub2RlLnBhcnRPZkdyb3VwKSBjb250aW51ZTsgLy8gVGhvc2UgYXJlIGludmlzaWJsZVxuXG4gICAgICAgIC8vIFBvc2l0aW9uIG9mIG5vZGUncyBjZW50cm9pZFxuICAgICAgICB2YXIgcG9zID0gWyhub2RlLngwICsgbm9kZS54MSkgLyAyLCAobm9kZS55MCArIG5vZGUueTEpIC8gMl07XG5cbiAgICAgICAgLy8gU3dhcCB4IGFuZCB5IGlmIHRyYWNlIGlzIHZlcnRpY2FsXG4gICAgICAgIGlmKGZ1bGxEYXRhLm9yaWVudGF0aW9uID09PSAndicpIHBvcy5yZXZlcnNlKCk7XG5cbiAgICAgICAgaWYoc2VsZWN0aW9uVGVzdGVyICYmIHNlbGVjdGlvblRlc3Rlci5jb250YWlucyhwb3MsIGZhbHNlLCBpLCBzZWFyY2hJbmZvKSkge1xuICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgIHBvaW50TnVtYmVyOiBub2RlLnBvaW50TnVtYmVyXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogYWRkIGV2ZW50RGF0YVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHNlbGVjdGlvbjtcbn07XG5cbn0se31dLDExMTE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxuXG4vLyBhcnJheU9rIGF0dHJpYnV0ZXMsIG1lcmdlIHRoZW0gaW50byBjYWxjZGF0YSBhcnJheVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSkge1xuICAgIC8vIHNvIGVhY2ggcG9pbnQga25vd3Mgd2hpY2ggaW5kZXggaXQgb3JpZ2luYWxseSBjYW1lIGZyb21cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIGNkW2ldLmkgPSBpO1xuXG4gICAgTGliLm1lcmdlQXJyYXkodHJhY2UudGV4dCwgY2QsICd0eCcpO1xuICAgIExpYi5tZXJnZUFycmF5KHRyYWNlLmhvdmVydGV4dCwgY2QsICdodHgnKTtcbiAgICBMaWIubWVyZ2VBcnJheSh0cmFjZS5jdXN0b21kYXRhLCBjZCwgJ2RhdGEnKTtcbiAgICBMaWIubWVyZ2VBcnJheSh0cmFjZS50ZXh0cG9zaXRpb24sIGNkLCAndHAnKTtcbiAgICBpZih0cmFjZS50ZXh0Zm9udCkge1xuICAgICAgICBMaWIubWVyZ2VBcnJheUNhc3RQb3NpdGl2ZSh0cmFjZS50ZXh0Zm9udC5zaXplLCBjZCwgJ3RzJyk7XG4gICAgICAgIExpYi5tZXJnZUFycmF5KHRyYWNlLnRleHRmb250LmNvbG9yLCBjZCwgJ3RjJyk7XG4gICAgICAgIExpYi5tZXJnZUFycmF5KHRyYWNlLnRleHRmb250LmZhbWlseSwgY2QsICd0ZicpO1xuICAgIH1cblxuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXI7XG4gICAgaWYobWFya2VyKSB7XG4gICAgICAgIExpYi5tZXJnZUFycmF5Q2FzdFBvc2l0aXZlKG1hcmtlci5zaXplLCBjZCwgJ21zJyk7XG4gICAgICAgIExpYi5tZXJnZUFycmF5Q2FzdFBvc2l0aXZlKG1hcmtlci5vcGFjaXR5LCBjZCwgJ21vJyk7XG4gICAgICAgIExpYi5tZXJnZUFycmF5KG1hcmtlci5zeW1ib2wsIGNkLCAnbXgnKTtcbiAgICAgICAgTGliLm1lcmdlQXJyYXkobWFya2VyLmNvbG9yLCBjZCwgJ21jJyk7XG5cbiAgICAgICAgdmFyIG1hcmtlckxpbmUgPSBtYXJrZXIubGluZTtcbiAgICAgICAgaWYobWFya2VyLmxpbmUpIHtcbiAgICAgICAgICAgIExpYi5tZXJnZUFycmF5KG1hcmtlckxpbmUuY29sb3IsIGNkLCAnbWxjJyk7XG4gICAgICAgICAgICBMaWIubWVyZ2VBcnJheUNhc3RQb3NpdGl2ZShtYXJrZXJMaW5lLndpZHRoLCBjZCwgJ21sdycpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1hcmtlckdyYWRpZW50ID0gbWFya2VyLmdyYWRpZW50O1xuICAgICAgICBpZihtYXJrZXJHcmFkaWVudCAmJiBtYXJrZXJHcmFkaWVudC50eXBlICE9PSAnbm9uZScpIHtcbiAgICAgICAgICAgIExpYi5tZXJnZUFycmF5KG1hcmtlckdyYWRpZW50LnR5cGUsIGNkLCAnbWd0Jyk7XG4gICAgICAgICAgICBMaWIubWVyZ2VBcnJheShtYXJrZXJHcmFkaWVudC5jb2xvciwgY2QsICdtZ2MnKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sMTExMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBob3ZlcnRlbXBsYXRlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlcycpO1xudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgZm9udEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzJyk7XG52YXIgZGFzaCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZy9hdHRyaWJ1dGVzJykuZGFzaDtcblxudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIGFuaW06IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeDA6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuICAgIGR4OiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICB5MDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIGFuaW06IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc3RhY2tncm91cDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6ICcnLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG9yaWVudGF0aW9uOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgXG4gICAgICAgIHZhbHVlczogWyd2JywgJ2gnXSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBncm91cG5vcm06IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnJywgJ2ZyYWN0aW9uJywgJ3BlcmNlbnQnXSxcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN0YWNrZ2Fwczoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydpbmZlciB6ZXJvJywgJ2ludGVycG9sYXRlJ10sXG4gICAgICAgIGRmbHQ6ICdpbmZlciB6ZXJvJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICAgICAgZmxhZ3M6IFsnbGluZXMnLCAnbWFya2VycycsICd0ZXh0J10sXG4gICAgICAgIGV4dHJhczogWydub25lJ10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGhvdmVyb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICAgICAgZmxhZ3M6IFsncG9pbnRzJywgJ2ZpbGxzJ10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBob3ZlcnRlbXBsYXRlOiBob3ZlcnRlbXBsYXRlQXR0cnMoe30sIHtcbiAgICAgICAga2V5czogY29uc3RhbnRzLmV2ZW50RGF0YUtleXNcbiAgICB9KSxcbiAgICBsaW5lOiB7XG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIGFuaW06IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogMixcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNoYXBlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnbGluZWFyJywgJ3NwbGluZScsICdodicsICd2aCcsICdodmgnLCAndmh2J10sXG4gICAgICAgICAgICBkZmx0OiAnbGluZWFyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzbW9vdGhpbmc6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxLjMsXG4gICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGRhc2g6IGV4dGVuZEZsYXQoe30sIGRhc2gsIHtlZGl0VHlwZTogJ3N0eWxlJ30pLFxuICAgICAgICBzaW1wbGlmeToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcblxuICAgIGNvbm5lY3RnYXBzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGNsaXBvbmF4aXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGZpbGw6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbm9uZScsICd0b3plcm95JywgJ3RvemVyb3gnLCAndG9uZXh0eScsICd0b25leHR4JywgJ3Rvc2VsZicsICd0b25leHQnXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZmlsbGNvbG9yOiB7XG4gICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgXG4gICAgfSxcbiAgICBtYXJrZXI6IGV4dGVuZEZsYXQoe1xuICAgICAgICBzeW1ib2w6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgICAgIHZhbHVlczogRHJhd2luZy5zeW1ib2xMaXN0LFxuICAgICAgICAgICAgZGZsdDogJ2NpcmNsZScsXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMSxcbiAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaXplOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDYsXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgYW5pbTogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBtYXhkaXNwbGF5ZWQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgZGZsdDogMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzaXplcmVmOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2l6ZW1pbjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNpemVtb2RlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnZGlhbWV0ZXInLCAnYXJlYSddLFxuICAgICAgICAgICAgZGZsdDogJ2RpYW1ldGVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGxpbmU6IGV4dGVuZEZsYXQoe1xuICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBhbmltOiB0cnVlLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbG9yU2NhbGVBdHRycygnbWFya2VyLmxpbmUnLCB7YW5pbTogdHJ1ZX0pXG4gICAgICAgICksXG4gICAgICAgIGdyYWRpZW50OiB7XG4gICAgICAgICAgICB0eXBlOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgICAgIHZhbHVlczogWydyYWRpYWwnLCAnaG9yaXpvbnRhbCcsICd2ZXJ0aWNhbCcsICdub25lJ10sXG4gICAgICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkZmx0OiAnbm9uZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgICAgIGNvbG9yU2NhbGVBdHRycygnbWFya2VyJywge2FuaW06IHRydWV9KVxuICAgICksXG4gICAgc2VsZWN0ZWQ6IHtcbiAgICAgICAgbWFya2VyOiB7XG4gICAgICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgICAgIG1heDogMSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2l6ZToge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuICAgICAgICB0ZXh0Zm9udDoge1xuICAgICAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgfSxcbiAgICB1bnNlbGVjdGVkOiB7XG4gICAgICAgIG1hcmtlcjoge1xuICAgICAgICAgICAgb3BhY2l0eToge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNpemU6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZSdcbiAgICAgICAgfSxcbiAgICAgICAgdGV4dGZvbnQ6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH0sXG5cbiAgICB0ZXh0cG9zaXRpb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFtcbiAgICAgICAgICAgICd0b3AgbGVmdCcsICd0b3AgY2VudGVyJywgJ3RvcCByaWdodCcsXG4gICAgICAgICAgICAnbWlkZGxlIGxlZnQnLCAnbWlkZGxlIGNlbnRlcicsICdtaWRkbGUgcmlnaHQnLFxuICAgICAgICAgICAgJ2JvdHRvbSBsZWZ0JywgJ2JvdHRvbSBjZW50ZXInLCAnYm90dG9tIHJpZ2h0J1xuICAgICAgICBdLFxuICAgICAgICBkZmx0OiAnbWlkZGxlIGNlbnRlcicsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRleHRmb250OiBmb250QXR0cnMoe1xuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBjb2xvckVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBcbiAgICB9KSxcblxuICAgIHI6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHQ6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzXCI6NjAwLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nL2F0dHJpYnV0ZXNcIjo2MTMsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90cy9mb250X2F0dHJpYnV0ZXNcIjo3OTMsXCIuL2NvbnN0YW50c1wiOjExMTZ9XSwxMTEzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG52YXIgc3ViVHlwZXMgPSBfZGVyZXFfKCcuL3N1YnR5cGVzJyk7XG52YXIgY2FsY0NvbG9yc2NhbGUgPSBfZGVyZXFfKCcuL2NvbG9yc2NhbGVfY2FsYycpO1xudmFyIGFycmF5c1RvQ2FsY2RhdGEgPSBfZGVyZXFfKCcuL2FycmF5c190b19jYWxjZGF0YScpO1xudmFyIGNhbGNTZWxlY3Rpb24gPSBfZGVyZXFfKCcuL2NhbGNfc2VsZWN0aW9uJyk7XG5cbmZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueGF4aXMgfHwgJ3gnKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMgfHwgJ3knKTtcbiAgICB2YXIgeCA9IHhhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3gnKTtcbiAgICB2YXIgeSA9IHlhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3knKTtcbiAgICB2YXIgc2VyaWVzbGVuID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgY2QgPSBuZXcgQXJyYXkoc2VyaWVzbGVuKTtcbiAgICB2YXIgaWRzID0gdHJhY2UuaWRzO1xuICAgIHZhciBzdGFja0dyb3VwT3B0cyA9IGdldFN0YWNrT3B0cyh0cmFjZSwgZnVsbExheW91dCwgeGEsIHlhKTtcbiAgICB2YXIgaW50ZXJwb2xhdGVHYXBzID0gZmFsc2U7XG4gICAgdmFyIGlzViwgaSwgaiwgaywgaW50ZXJwb2xhdGUsIHZhbGk7XG5cbiAgICBzZXRGaXJzdFNjYXR0ZXIoZnVsbExheW91dCwgdHJhY2UpO1xuXG4gICAgdmFyIHhBdHRyID0gJ3gnO1xuICAgIHZhciB5QXR0ciA9ICd5JztcbiAgICB2YXIgcG9zQXR0cjtcbiAgICBpZihzdGFja0dyb3VwT3B0cykge1xuICAgICAgICBMaWIucHVzaFVuaXF1ZShzdGFja0dyb3VwT3B0cy50cmFjZUluZGljZXMsIHRyYWNlLl9leHBhbmRlZEluZGV4KTtcbiAgICAgICAgaXNWID0gc3RhY2tHcm91cE9wdHMub3JpZW50YXRpb24gPT09ICd2JztcblxuICAgICAgICAvLyBzaXplLCBsaWtlIHdlIHVzZSBmb3IgYmFyXG4gICAgICAgIGlmKGlzVikge1xuICAgICAgICAgICAgeUF0dHIgPSAncyc7XG4gICAgICAgICAgICBwb3NBdHRyID0gJ3gnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgeEF0dHIgPSAncyc7XG4gICAgICAgICAgICBwb3NBdHRyID0gJ3knO1xuICAgICAgICB9XG4gICAgICAgIGludGVycG9sYXRlID0gc3RhY2tHcm91cE9wdHMuc3RhY2tnYXBzID09PSAnaW50ZXJwb2xhdGUnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBwcGFkID0gY2FsY01hcmtlclNpemUodHJhY2UsIHNlcmllc2xlbik7XG4gICAgICAgIGNhbGNBeGlzRXhwYW5zaW9uKGdkLCB0cmFjZSwgeGEsIHlhLCB4LCB5LCBwcGFkKTtcbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBzZXJpZXNsZW47IGkrKykge1xuICAgICAgICB2YXIgY2RpID0gY2RbaV0gPSB7fTtcbiAgICAgICAgdmFyIHhWYWxpZCA9IGlzTnVtZXJpYyh4W2ldKTtcbiAgICAgICAgdmFyIHlWYWxpZCA9IGlzTnVtZXJpYyh5W2ldKTtcbiAgICAgICAgaWYoeFZhbGlkICYmIHlWYWxpZCkge1xuICAgICAgICAgICAgY2RpW3hBdHRyXSA9IHhbaV07XG4gICAgICAgICAgICBjZGlbeUF0dHJdID0geVtpXTtcbiAgICAgICAgfSBlbHNlIGlmKHN0YWNrR3JvdXBPcHRzICYmIChpc1YgPyB4VmFsaWQgOiB5VmFsaWQpKSB7XG4gICAgICAgICAgICAvLyBpZiB3ZSdyZSBzdGFja2luZyB3ZSBuZWVkIHRvIGhvbGQgb24gdG8gYWxsIHZhbGlkIHBvc2l0aW9uc1xuICAgICAgICAgICAgLy8gZXZlbiB3aXRoIGludmFsaWQgc2l6ZXNcblxuICAgICAgICAgICAgY2RpW3Bvc0F0dHJdID0gaXNWID8geFtpXSA6IHlbaV07XG4gICAgICAgICAgICBjZGkuZ2FwID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmKGludGVycG9sYXRlKSB7XG4gICAgICAgICAgICAgICAgY2RpLnMgPSBCQUROVU07XG4gICAgICAgICAgICAgICAgaW50ZXJwb2xhdGVHYXBzID0gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2RpLnMgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2RpW3hBdHRyXSA9IGNkaVt5QXR0cl0gPSBCQUROVU07XG4gICAgICAgIH1cblxuICAgICAgICBpZihpZHMpIHtcbiAgICAgICAgICAgIGNkaS5pZCA9IFN0cmluZyhpZHNbaV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXJyYXlzVG9DYWxjZGF0YShjZCwgdHJhY2UpO1xuICAgIGNhbGNDb2xvcnNjYWxlKGdkLCB0cmFjZSk7XG4gICAgY2FsY1NlbGVjdGlvbihjZCwgdHJhY2UpO1xuXG4gICAgaWYoc3RhY2tHcm91cE9wdHMpIHtcbiAgICAgICAgLy8gcmVtb3ZlIGJhZCBwb3NpdGlvbnMgYW5kIHNvcnRcbiAgICAgICAgLy8gbm90ZSB0aGF0IG9yaWdpbmFsIGluZGljZXMgZ2V0IGFkZGVkIHRvIGNkIGluIGFycmF5c1RvQ2FsY2RhdGFcbiAgICAgICAgaSA9IDA7XG4gICAgICAgIHdoaWxlKGkgPCBjZC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmKGNkW2ldW3Bvc0F0dHJdID09PSBCQUROVU0pIHtcbiAgICAgICAgICAgICAgICBjZC5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICB9IGVsc2UgaSsrO1xuICAgICAgICB9XG5cbiAgICAgICAgTGliLnNvcnQoY2QsIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiAoYVtwb3NBdHRyXSAtIGJbcG9zQXR0cl0pIHx8IChhLmkgLSBiLmkpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZihpbnRlcnBvbGF0ZUdhcHMpIHtcbiAgICAgICAgICAgIC8vIGZpcnN0IGZpbGwgdGhlIGJlZ2lubmluZyB3aXRoIGNvbnN0YW50IGZyb20gdGhlIGZpcnN0IHBvaW50XG4gICAgICAgICAgICBpID0gMDtcbiAgICAgICAgICAgIHdoaWxlKGkgPCBjZC5sZW5ndGggLSAxICYmIGNkW2ldLmdhcCkge1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhbGkgPSBjZFtpXS5zO1xuICAgICAgICAgICAgaWYoIXZhbGkpIHZhbGkgPSBjZFtpXS5zID0gMDsgLy8gaW4gY2FzZSBvZiBubyBkYXRhIEFUIEFMTCBpbiB0aGlzIHRyYWNlIC0gdXNlIDBcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGk7IGorKykge1xuICAgICAgICAgICAgICAgIGNkW2pdLnMgPSB2YWxpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gdGhlbiBmaWxsIHRoZSBlbmQgd2l0aCBjb25zdGFudCBmcm9tIHRoZSBsYXN0IHBvaW50XG4gICAgICAgICAgICBrID0gY2QubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIHdoaWxlKGsgPiBpICYmIGNkW2tdLmdhcCkge1xuICAgICAgICAgICAgICAgIGstLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhbGkgPSBjZFtrXS5zO1xuICAgICAgICAgICAgZm9yKGogPSBjZC5sZW5ndGggLSAxOyBqID4gazsgai0tKSB7XG4gICAgICAgICAgICAgICAgY2Rbal0ucyA9IHZhbGk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBub3cgaW50ZXJwb2xhdGUgaW50ZXJuYWwgZ2FwcyBsaW5lYXJseVxuICAgICAgICAgICAgd2hpbGUoaSA8IGspIHtcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICAgICAgaWYoY2RbaV0uZ2FwKSB7XG4gICAgICAgICAgICAgICAgICAgIGogPSBpICsgMTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUoY2Rbal0uZ2FwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBqKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvczAgPSBjZFtpIC0gMV1bcG9zQXR0cl07XG4gICAgICAgICAgICAgICAgICAgIHZhciBzaXplMCA9IGNkW2kgLSAxXS5zO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbSA9IChjZFtqXS5zIC0gc2l6ZTApIC8gKGNkW2pdW3Bvc0F0dHJdIC0gcG9zMCk7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlKGkgPCBqKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjZFtpXS5zID0gc2l6ZTAgKyAoY2RbaV1bcG9zQXR0cl0gLSBwb3MwKSAqIG07XG4gICAgICAgICAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY2Q7XG59XG5cbmZ1bmN0aW9uIGNhbGNBeGlzRXhwYW5zaW9uKGdkLCB0cmFjZSwgeGEsIHlhLCB4LCB5LCBwcGFkKSB7XG4gICAgdmFyIHNlcmllc2xlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgeElkID0geGEuX2lkO1xuICAgIHZhciB5SWQgPSB5YS5faWQ7XG4gICAgdmFyIGZpcnN0U2NhdHRlciA9IGZ1bGxMYXlvdXQuX2ZpcnN0U2NhdHRlcltmaXJzdFNjYXR0ZXJHcm91cCh0cmFjZSldID09PSB0cmFjZS51aWQ7XG4gICAgdmFyIHN0YWNrT3JpZW50YXRpb24gPSAoZ2V0U3RhY2tPcHRzKHRyYWNlLCBmdWxsTGF5b3V0LCB4YSwgeWEpIHx8IHt9KS5vcmllbnRhdGlvbjtcbiAgICB2YXIgZmlsbCA9IHRyYWNlLmZpbGw7XG5cbiAgICAvLyBjYW5jZWwgbWluaW11bSB0aWNrIHNwYWNpbmdzIChvbmx5IGFwcGxpZXMgdG8gYmFycyBhbmQgYm94ZXMpXG4gICAgeGEuX21pbkR0aWNrID0gMDtcbiAgICB5YS5fbWluRHRpY2sgPSAwO1xuXG4gICAgLy8gY2hlY2sgd2hldGhlciBib3VuZHMgc2hvdWxkIGJlIHRpZ2h0LCBwYWRkZWQsIGV4dGVuZGVkIHRvIHplcm8uLi5cbiAgICAvLyBtb3N0IGNhc2VzIGJvdGggc2hvdWxkIGJlIHBhZGRlZCBvbiBib3RoIGVuZHMsIHNvIHN0YXJ0IHdpdGggdGhhdC5cbiAgICB2YXIgeE9wdGlvbnMgPSB7cGFkZGVkOiB0cnVlfTtcbiAgICB2YXIgeU9wdGlvbnMgPSB7cGFkZGVkOiB0cnVlfTtcblxuICAgIGlmKHBwYWQpIHtcbiAgICAgICAgeE9wdGlvbnMucHBhZCA9IHlPcHRpb25zLnBwYWQgPSBwcGFkO1xuICAgIH1cblxuICAgIC8vIFRPRE86IHRleHQgc2l6ZVxuXG4gICAgdmFyIG9wZW5FbmRlZCA9IHNlcmllc2xlbiA8IDIgfHwgKHhbMF0gIT09IHhbc2VyaWVzbGVuIC0gMV0pIHx8ICh5WzBdICE9PSB5W3Nlcmllc2xlbiAtIDFdKTtcblxuICAgIGlmKG9wZW5FbmRlZCAmJiAoXG4gICAgICAgIChmaWxsID09PSAndG96ZXJveCcpIHx8XG4gICAgICAgICgoZmlsbCA9PT0gJ3RvbmV4dHgnKSAmJiAoZmlyc3RTY2F0dGVyIHx8IHN0YWNrT3JpZW50YXRpb24gPT09ICdoJykpXG4gICAgKSkge1xuICAgICAgICAvLyBpbmNsdWRlIHplcm8gKHRpZ2h0KSBhbmQgZXh0cmVtZXMgKHBhZGRlZCkgaWYgZmlsbCB0byB6ZXJvXG4gICAgICAgIC8vICh1bmxlc3MgdGhlIHNoYXBlIGlzIGNsb3NlZCwgdGhlbiBpdCdzIGp1c3QgZmlsbGluZyB0aGUgc2hhcGUgcmVnYXJkbGVzcylcblxuICAgICAgICB4T3B0aW9ucy50b3plcm8gPSB0cnVlO1xuICAgIH0gZWxzZSBpZighKHRyYWNlLmVycm9yX3kgfHwge30pLnZpc2libGUgJiYgKFxuICAgICAgICAvLyBpZiBubyBlcnJvciBiYXJzLCBtYXJrZXJzIG9yIHRleHQsIG9yIGZpbGwgdG8geT0wIHJlbW92ZSB4IHBhZGRpbmdcblxuICAgICAgICAgICAgKGZpbGwgPT09ICd0b25leHR5JyB8fCBmaWxsID09PSAndG96ZXJveScpIHx8XG4gICAgICAgICAgICAoIXN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpICYmICFzdWJUeXBlcy5oYXNUZXh0KHRyYWNlKSlcbiAgICAgICAgKSkge1xuICAgICAgICB4T3B0aW9ucy5wYWRkZWQgPSBmYWxzZTtcbiAgICAgICAgeE9wdGlvbnMucHBhZCA9IDA7XG4gICAgfVxuXG4gICAgaWYob3BlbkVuZGVkICYmIChcbiAgICAgICAgKGZpbGwgPT09ICd0b3plcm95JykgfHxcbiAgICAgICAgKChmaWxsID09PSAndG9uZXh0eScpICYmIChmaXJzdFNjYXR0ZXIgfHwgc3RhY2tPcmllbnRhdGlvbiA9PT0gJ3YnKSlcbiAgICApKSB7XG4gICAgICAgIC8vIG5vdyBjaGVjayBmb3IgeSAtIHJhdGhlciBkaWZmZXJlbnQgbG9naWMsIHRob3VnaCBzdGlsbCBtb3N0bHkgcGFkZGVkIGJvdGggZW5kc1xuICAgICAgICAvLyBpbmNsdWRlIHplcm8gKHRpZ2h0KSBhbmQgZXh0cmVtZXMgKHBhZGRlZCkgaWYgZmlsbCB0byB6ZXJvXG4gICAgICAgIC8vICh1bmxlc3MgdGhlIHNoYXBlIGlzIGNsb3NlZCwgdGhlbiBpdCdzIGp1c3QgZmlsbGluZyB0aGUgc2hhcGUgcmVnYXJkbGVzcylcblxuICAgICAgICB5T3B0aW9ucy50b3plcm8gPSB0cnVlO1xuICAgIH0gZWxzZSBpZihmaWxsID09PSAndG9uZXh0eCcgfHwgZmlsbCA9PT0gJ3RvemVyb3gnKSB7XG4gICAgICAgIC8vIHRpZ2h0IHk6IGFueSB4IGZpbGxcblxuICAgICAgICB5T3B0aW9ucy5wYWRkZWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBOLkIuIGFzeW1tZXRyaWMgc3Bsb20gdHJhY2VzIGNhbGwgdGhpcyB3aXRoIGJsYW5rIHt9IHhhIG9yIHlhXG4gICAgaWYoeElkKSB0cmFjZS5fZXh0cmVtZXNbeElkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKHhhLCB4LCB4T3B0aW9ucyk7XG4gICAgaWYoeUlkKSB0cmFjZS5fZXh0cmVtZXNbeUlkXSA9IEF4ZXMuZmluZEV4dHJlbWVzKHlhLCB5LCB5T3B0aW9ucyk7XG59XG5cbmZ1bmN0aW9uIGNhbGNNYXJrZXJTaXplKHRyYWNlLCBzZXJpZXNsZW4pIHtcbiAgICBpZighc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkpIHJldHVybjtcblxuICAgIC8vIFRyZWF0IHNpemUgbGlrZSB4IG9yIHkgYXJyYXlzIC0tLSBSdW4gZDJjXG4gICAgLy8gdGhpcyBuZWVkcyB0byBnbyBiZWZvcmUgcHBhZCBjb21wdXRhdGlvblxuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXI7XG4gICAgdmFyIHNpemVyZWYgPSAxLjYgKiAodHJhY2UubWFya2VyLnNpemVyZWYgfHwgMSk7XG4gICAgdmFyIG1hcmtlclRyYW5zO1xuXG4gICAgaWYodHJhY2UubWFya2VyLnNpemVtb2RlID09PSAnYXJlYScpIHtcbiAgICAgICAgbWFya2VyVHJhbnMgPSBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5tYXgoTWF0aC5zcXJ0KCh2IHx8IDApIC8gc2l6ZXJlZiksIDMpO1xuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1hcmtlclRyYW5zID0gZnVuY3Rpb24odikge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgubWF4KCh2IHx8IDApIC8gc2l6ZXJlZiwgMyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyLnNpemUpKSB7XG4gICAgICAgIC8vIEkgdHJpZWQgYXV0by10eXBlIGJ1dCBjYXRlZ29yeSBhbmQgZGF0ZXMgZG9udCBtYWtlIG11Y2ggc2Vuc2UuXG4gICAgICAgIHZhciBheCA9IHt0eXBlOiAnbGluZWFyJ307XG4gICAgICAgIEF4ZXMuc2V0Q29udmVydChheCk7XG5cbiAgICAgICAgdmFyIHMgPSBheC5tYWtlQ2FsY2RhdGEodHJhY2UubWFya2VyLCAnc2l6ZScpO1xuXG4gICAgICAgIHZhciBzaXplT3V0ID0gbmV3IEFycmF5KHNlcmllc2xlbik7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzZXJpZXNsZW47IGkrKykge1xuICAgICAgICAgICAgc2l6ZU91dFtpXSA9IG1hcmtlclRyYW5zKHNbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzaXplT3V0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBtYXJrZXJUcmFucyhtYXJrZXIuc2l6ZSk7XG4gICAgfVxufVxuXG4vKipcbiAqIG1hcmsgdGhlIGZpcnN0IHNjYXR0ZXIgdHJhY2UgZm9yIGVhY2ggc3VicGxvdFxuICogbm90ZSB0aGF0IHNjYXR0ZXIgYW5kIHNjYXR0ZXJnbCBlYWNoIGdldCB0aGVpciBvd24gZmlyc3QgdHJhY2VcbiAqIG5vdGUgYWxzbyB0aGF0IEknbSBkb2luZyB0aGlzIGR1cmluZyBjYWxjIHJhdGhlciB0aGFuIHN1cHBseURlZmF1bHRzXG4gKiBzbyBJIGRvbid0IG5lZWQgdG8gd29ycnkgYWJvdXQgdHJhbnNmb3JtcywgYnV0IGlmIHdlIGV2ZXIgZG9cbiAqIHBlci10cmFjZSBjYWxjIHRoaXMgd2lsbCBnZXQgY29uZnVzZWQuXG4gKi9cbmZ1bmN0aW9uIHNldEZpcnN0U2NhdHRlcihmdWxsTGF5b3V0LCB0cmFjZSkge1xuICAgIHZhciBncm91cCA9IGZpcnN0U2NhdHRlckdyb3VwKHRyYWNlKTtcbiAgICB2YXIgZmlyc3RTY2F0dGVyID0gZnVsbExheW91dC5fZmlyc3RTY2F0dGVyO1xuICAgIGlmKCFmaXJzdFNjYXR0ZXJbZ3JvdXBdKSBmaXJzdFNjYXR0ZXJbZ3JvdXBdID0gdHJhY2UudWlkO1xufVxuXG5mdW5jdGlvbiBmaXJzdFNjYXR0ZXJHcm91cCh0cmFjZSkge1xuICAgIHZhciBzdGFja0dyb3VwID0gdHJhY2Uuc3RhY2tncm91cDtcbiAgICByZXR1cm4gdHJhY2UueGF4aXMgKyB0cmFjZS55YXhpcyArIHRyYWNlLnR5cGUgK1xuICAgICAgICAoc3RhY2tHcm91cCA/ICctJyArIHN0YWNrR3JvdXAgOiAnJyk7XG59XG5cbmZ1bmN0aW9uIGdldFN0YWNrT3B0cyh0cmFjZSwgZnVsbExheW91dCwgeGEsIHlhKSB7XG4gICAgdmFyIHN0YWNrR3JvdXAgPSB0cmFjZS5zdGFja2dyb3VwO1xuICAgIGlmKCFzdGFja0dyb3VwKSByZXR1cm47XG4gICAgdmFyIHN0YWNrT3B0cyA9IGZ1bGxMYXlvdXQuX3NjYXR0ZXJTdGFja09wdHNbeGEuX2lkICsgeWEuX2lkXVtzdGFja0dyb3VwXTtcbiAgICB2YXIgc3RhY2tBeCA9IHN0YWNrT3B0cy5vcmllbnRhdGlvbiA9PT0gJ3YnID8geWEgOiB4YTtcbiAgICAvLyBBbGxvdyBzdGFja2luZyBvbmx5IG9uIG51bWVyaWMgYXhlc1xuICAgIC8vIGNhbGMgaXMgYSBsaXR0bGUgbGF0ZSB0byBiZSBmaWd1cmluZyB0aGlzIG91dCwgYnV0IGR1cmluZyBzdXBwbHlEZWZhdWx0c1xuICAgIC8vIHdlIGRvbid0IGtub3cgdGhlIGF4aXMgdHlwZSB5ZXRcbiAgICBpZihzdGFja0F4LnR5cGUgPT09ICdsaW5lYXInIHx8IHN0YWNrQXgudHlwZSA9PT0gJ2xvZycpIHJldHVybiBzdGFja09wdHM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNhbGM6IGNhbGMsXG4gICAgY2FsY01hcmtlclNpemU6IGNhbGNNYXJrZXJTaXplLFxuICAgIGNhbGNBeGlzRXhwYW5zaW9uOiBjYWxjQXhpc0V4cGFuc2lvbixcbiAgICBzZXRGaXJzdFNjYXR0ZXI6IHNldEZpcnN0U2NhdHRlcixcbiAgICBnZXRTdGFja09wdHM6IGdldFN0YWNrT3B0c1xufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuL2FycmF5c190b19jYWxjZGF0YVwiOjExMTEsXCIuL2NhbGNfc2VsZWN0aW9uXCI6MTExNCxcIi4vY29sb3JzY2FsZV9jYWxjXCI6MTExNSxcIi4vc3VidHlwZXNcIjoxMTM1LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSwxMTE0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGNTZWxlY3Rpb24oY2QsIHRyYWNlKSB7XG4gICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkodHJhY2Uuc2VsZWN0ZWRwb2ludHMpKSB7XG4gICAgICAgIExpYi50YWdTZWxlY3RlZChjZCwgdHJhY2UpO1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sMTExNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBoYXNDb2xvcnNjYWxlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hlbHBlcnMnKS5oYXNDb2xvcnNjYWxlO1xudmFyIGNhbGNDb2xvcnNjYWxlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcblxudmFyIHN1YlR5cGVzID0gX2RlcmVxXygnLi9zdWJ0eXBlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGNNYXJrZXJDb2xvcnNjYWxlKGdkLCB0cmFjZSkge1xuICAgIGlmKHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlKSAmJiBoYXNDb2xvcnNjYWxlKHRyYWNlLCAnbGluZScpKSB7XG4gICAgICAgIGNhbGNDb2xvcnNjYWxlKGdkLCB0cmFjZSwge1xuICAgICAgICAgICAgdmFsczogdHJhY2UubGluZS5jb2xvcixcbiAgICAgICAgICAgIGNvbnRhaW5lclN0cjogJ2xpbmUnLFxuICAgICAgICAgICAgY0xldHRlcjogJ2MnXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpKSB7XG4gICAgICAgIGlmKGhhc0NvbG9yc2NhbGUodHJhY2UsICdtYXJrZXInKSkge1xuICAgICAgICAgICAgY2FsY0NvbG9yc2NhbGUoZ2QsIHRyYWNlLCB7XG4gICAgICAgICAgICAgICAgdmFsczogdHJhY2UubWFya2VyLmNvbG9yLFxuICAgICAgICAgICAgICAgIGNvbnRhaW5lclN0cjogJ21hcmtlcicsXG4gICAgICAgICAgICAgICAgY0xldHRlcjogJ2MnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZihoYXNDb2xvcnNjYWxlKHRyYWNlLCAnbWFya2VyLmxpbmUnKSkge1xuICAgICAgICAgICAgY2FsY0NvbG9yc2NhbGUoZ2QsIHRyYWNlLCB7XG4gICAgICAgICAgICAgICAgdmFsczogdHJhY2UubWFya2VyLmxpbmUuY29sb3IsXG4gICAgICAgICAgICAgICAgY29udGFpbmVyU3RyOiAnbWFya2VyLmxpbmUnLFxuICAgICAgICAgICAgICAgIGNMZXR0ZXI6ICdjJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjXCI6NjAxLFwiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hlbHBlcnNcIjo2MDQsXCIuL3N1YnR5cGVzXCI6MTEzNX1dLDExMTY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIFBUU19MSU5FU09OTFk6IDIwLFxuXG4gICAgLy8gZml4ZWQgcGFyYW1ldGVycyBvZiBjbHVzdGVyaW5nIGFuZCBjbGlwcGluZyBhbGdvcml0aG1zXG5cbiAgICAvLyBmcmFjdGlvbiBvZiBjbHVzdGVyaW5nIHRvbGVyYW5jZSBcInNvIGNsb3NlIHdlIGRvbid0IGV2ZW4gY29uc2lkZXIgaXQgYSBuZXcgcG9pbnRcIlxuICAgIG1pblRvbGVyYW5jZTogMC4yLFxuICAgIC8vIGhvdyBmYXN0IGRvZXMgY2x1c3RlcmluZyB0b2xlcmFuY2UgaW5jcmVhc2UgYXMgeW91IGdldCBhd2F5IGZyb20gdGhlIHZpc2libGUgcmVnaW9uXG4gICAgdG9sZXJhbmNlR3Jvd3RoOiAxMCxcblxuICAgIC8vIG51bWJlciBvZiB2aWV3cG9ydCBzaXplcyBhd2F5IGZyb20gdGhlIHZpc2libGUgcmVnaW9uXG4gICAgLy8gYXQgd2hpY2ggd2UgY2xpcCBhbGwgbGluZXMgdG8gdGhlIHBlcmltZXRlclxuICAgIG1heFNjcmVlbnNBd2F5OiAyMCxcblxuICAgIGV2ZW50RGF0YUtleXM6IFtdXG59O1xuXG59LHt9XSwxMTE3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY2FsYyA9IF9kZXJlcV8oJy4vY2FsYycpO1xuXG4vKlxuICogU2NhdHRlciBzdGFja2luZyAmIG5vcm1hbGl6YXRpb24gY2FsY3VsYXRpb25zXG4gKiBydW5zIHBlciBzdWJwbG90LCBhbmQgY2FuIGhhbmRsZSBtdWx0aXBsZSBzdGFja2luZyBncm91cHNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyb3NzVHJhY2VDYWxjKGdkLCBwbG90aW5mbykge1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuICAgIHZhciBzdWJwbG90ID0geGEuX2lkICsgeWEuX2lkO1xuXG4gICAgdmFyIHN1YnBsb3RTdGFja09wdHMgPSBnZC5fZnVsbExheW91dC5fc2NhdHRlclN0YWNrT3B0c1tzdWJwbG90XTtcbiAgICBpZighc3VicGxvdFN0YWNrT3B0cykgcmV0dXJuO1xuXG4gICAgdmFyIGNhbGNUcmFjZXMgPSBnZC5jYWxjZGF0YTtcblxuICAgIHZhciBpLCBqLCBrLCBpMiwgY2QsIGNkMCwgcG9zaiwgc3Vtaiwgbm9ybTtcbiAgICB2YXIgZ3JvdXBPcHRzLCBpbnRlcnBvbGF0ZSwgZ3JvdXBub3JtLCBwb3NBdHRyLCB2YWxBdHRyO1xuICAgIHZhciBoYXNBbnlCbGFua3M7XG5cbiAgICBmb3IodmFyIHN0YWNrR3JvdXAgaW4gc3VicGxvdFN0YWNrT3B0cykge1xuICAgICAgICBncm91cE9wdHMgPSBzdWJwbG90U3RhY2tPcHRzW3N0YWNrR3JvdXBdO1xuICAgICAgICB2YXIgaW5kaWNlcyA9IGdyb3VwT3B0cy50cmFjZUluZGljZXM7XG5cbiAgICAgICAgLy8gY2FuIGdldCBoZXJlIHdpdGggbm8gaW5kaWNlcyBpZiB0aGUgc3RhY2sgYXhpcyBpcyBub24tbnVtZXJpY1xuICAgICAgICBpZighaW5kaWNlcy5sZW5ndGgpIGNvbnRpbnVlO1xuXG4gICAgICAgIGludGVycG9sYXRlID0gZ3JvdXBPcHRzLnN0YWNrZ2FwcyA9PT0gJ2ludGVycG9sYXRlJztcbiAgICAgICAgZ3JvdXBub3JtID0gZ3JvdXBPcHRzLmdyb3Vwbm9ybTtcbiAgICAgICAgaWYoZ3JvdXBPcHRzLm9yaWVudGF0aW9uID09PSAndicpIHtcbiAgICAgICAgICAgIHBvc0F0dHIgPSAneCc7XG4gICAgICAgICAgICB2YWxBdHRyID0gJ3knO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9zQXR0ciA9ICd5JztcbiAgICAgICAgICAgIHZhbEF0dHIgPSAneCc7XG4gICAgICAgIH1cbiAgICAgICAgaGFzQW55QmxhbmtzID0gbmV3IEFycmF5KGluZGljZXMubGVuZ3RoKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgaGFzQW55QmxhbmtzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBoYXNBbnlCbGFua3NbaV0gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbGxlY3QgdGhlIGNvbXBsZXRlIHNldCBvZiBhbGwgcG9zaXRpb25zIGFjcm9zcyBBTEwgdHJhY2VzLlxuICAgICAgICAvLyBTdGFydCB3aXRoIHRoZSBmaXJzdCB0cmFjZSwgdGhlbiBpbnRlcmxlYXZlIGl0ZW1zIGZyb20gbGF0ZXIgdHJhY2VzXG4gICAgICAgIC8vIGFzIG5lZWRlZC5cbiAgICAgICAgLy8gRmlsbCBpbiBtaXNpbmcgaXRlbXMgYXMgd2UgZ28uXG4gICAgICAgIGNkMCA9IGNhbGNUcmFjZXNbaW5kaWNlc1swXV07XG4gICAgICAgIHZhciBhbGxQb3NpdGlvbnMgPSBuZXcgQXJyYXkoY2QwLmxlbmd0aCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNkMC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYWxsUG9zaXRpb25zW2ldID0gY2QwW2ldW3Bvc0F0dHJdO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yKGkgPSAxOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2QgPSBjYWxjVHJhY2VzW2luZGljZXNbaV1dO1xuXG4gICAgICAgICAgICBmb3IoaiA9IGsgPSAwOyBqIDwgY2QubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBwb3NqID0gY2Rbal1bcG9zQXR0cl07XG4gICAgICAgICAgICAgICAgZm9yKDsgcG9zaiA+IGFsbFBvc2l0aW9uc1trXSAmJiBrIDwgYWxsUG9zaXRpb25zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBjdXJyZW50IHRyYWNlIGlzIG1pc3NpbmcgYSBwb3NpdGlvbiBmcm9tIHNvbWUgcHJldmlvdXMgdHJhY2UocylcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0QmxhbmsoY2QsIGosIGFsbFBvc2l0aW9uc1trXSwgaSwgaGFzQW55QmxhbmtzLCBpbnRlcnBvbGF0ZSwgcG9zQXR0cik7XG4gICAgICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYocG9zaiAhPT0gYWxsUG9zaXRpb25zW2tdKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHByZXZpb3VzIHRyYWNlKHMpIGFyZSBtaXNzaW5nIGEgcG9zaXRpb24gZnJvbSB0aGUgY3VycmVudCB0cmFjZVxuICAgICAgICAgICAgICAgICAgICBmb3IoaTIgPSAwOyBpMiA8IGk7IGkyKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydEJsYW5rKGNhbGNUcmFjZXNbaW5kaWNlc1tpMl1dLCBrLCBwb3NqLCBpMiwgaGFzQW55QmxhbmtzLCBpbnRlcnBvbGF0ZSwgcG9zQXR0cik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYWxsUG9zaXRpb25zLnNwbGljZShrLCAwLCBwb3NqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yKDsgayA8IGFsbFBvc2l0aW9ucy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIGluc2VydEJsYW5rKGNkLCBqLCBhbGxQb3NpdGlvbnNba10sIGksIGhhc0FueUJsYW5rcywgaW50ZXJwb2xhdGUsIHBvc0F0dHIpO1xuICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzZXJpZXNsZW4gPSBhbGxQb3NpdGlvbnMubGVuZ3RoO1xuXG4gICAgICAgIC8vIHN0YWNrIChhbmQgbm9ybWFsaXplKSFcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgY2QwLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBzdW1qID0gY2QwW2pdW3ZhbEF0dHJdID0gY2QwW2pdLnM7XG4gICAgICAgICAgICBmb3IoaSA9IDE7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2QgPSBjYWxjVHJhY2VzW2luZGljZXNbaV1dO1xuICAgICAgICAgICAgICAgIGNkWzBdLnRyYWNlLl9yYXdMZW5ndGggPSBjZFswXS50cmFjZS5fbGVuZ3RoO1xuICAgICAgICAgICAgICAgIGNkWzBdLnRyYWNlLl9sZW5ndGggPSBzZXJpZXNsZW47XG4gICAgICAgICAgICAgICAgc3VtaiArPSBjZFtqXS5zO1xuICAgICAgICAgICAgICAgIGNkW2pdW3ZhbEF0dHJdID0gc3VtajtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoZ3JvdXBub3JtKSB7XG4gICAgICAgICAgICAgICAgbm9ybSA9ICgoZ3JvdXBub3JtID09PSAnZnJhY3Rpb24nKSA/IHN1bWogOiAoc3VtaiAvIDEwMCkpIHx8IDE7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2RqID0gY2FsY1RyYWNlc1tpbmRpY2VzW2ldXVtqXTtcbiAgICAgICAgICAgICAgICAgICAgY2RqW3ZhbEF0dHJdIC89IG5vcm07XG4gICAgICAgICAgICAgICAgICAgIGNkai5zTm9ybSA9IGNkai5zIC8gbm9ybTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhdXRvcmFuZ2VcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2QgPSBjYWxjVHJhY2VzW2luZGljZXNbaV1dO1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgICAgICAgICB2YXIgcHBhZCA9IGNhbGMuY2FsY01hcmtlclNpemUodHJhY2UsIHRyYWNlLl9yYXdMZW5ndGgpO1xuICAgICAgICAgICAgdmFyIGFycmF5UGFkID0gQXJyYXkuaXNBcnJheShwcGFkKTtcbiAgICAgICAgICAgIGlmKChwcGFkICYmIGhhc0FueUJsYW5rc1tpXSkgfHwgYXJyYXlQYWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHBhZFJhdyA9IHBwYWQ7XG4gICAgICAgICAgICAgICAgcHBhZCA9IG5ldyBBcnJheShzZXJpZXNsZW4pO1xuICAgICAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IHNlcmllc2xlbjsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBwYWRbal0gPSBjZFtqXS5nYXAgPyAwIDogKGFycmF5UGFkID8gcHBhZFJhd1tjZFtqXS5pXSA6IHBwYWRSYXcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB4ID0gbmV3IEFycmF5KHNlcmllc2xlbik7XG4gICAgICAgICAgICB2YXIgeSA9IG5ldyBBcnJheShzZXJpZXNsZW4pO1xuICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgc2VyaWVzbGVuOyBqKyspIHtcbiAgICAgICAgICAgICAgICB4W2pdID0gY2Rbal0ueDtcbiAgICAgICAgICAgICAgICB5W2pdID0gY2Rbal0ueTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbGMuY2FsY0F4aXNFeHBhbnNpb24oZ2QsIHRyYWNlLCB4YSwgeWEsIHgsIHksIHBwYWQpO1xuXG4gICAgICAgICAgICAvLyB3aGlsZSB3ZSdyZSBoZXJlIChpbiBhIGxvb3Agb3ZlciBhbGwgdHJhY2VzIGluIHRoZSBzdGFjaylcbiAgICAgICAgICAgIC8vIHJlY29yZCB0aGUgb3JpZW50YXRpb24sIHNvIGhvdmVyIGNhbiBmaW5kIGl0IGVhc2lseVxuICAgICAgICAgICAgY2RbMF0udC5vcmllbnRhdGlvbiA9IGdyb3VwT3B0cy5vcmllbnRhdGlvbjtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGluc2VydEJsYW5rKGNhbGNUcmFjZSwgaW5kZXgsIHBvc2l0aW9uLCB0cmFjZUluZGV4LCBoYXNBbnlCbGFua3MsIGludGVycG9sYXRlLCBwb3NBdHRyKSB7XG4gICAgaGFzQW55QmxhbmtzW3RyYWNlSW5kZXhdID0gdHJ1ZTtcbiAgICB2YXIgbmV3RW50cnkgPSB7XG4gICAgICAgIGk6IG51bGwsXG4gICAgICAgIGdhcDogdHJ1ZSxcbiAgICAgICAgczogMFxuICAgIH07XG4gICAgbmV3RW50cnlbcG9zQXR0cl0gPSBwb3NpdGlvbjtcbiAgICBjYWxjVHJhY2Uuc3BsaWNlKGluZGV4LCAwLCBuZXdFbnRyeSk7XG4gICAgLy8gRXZlbiBpZiB3ZSdyZSBub3QgaW50ZXJwb2xhdGluZywgaWYgb25lIHRyYWNlIGhhcyBtdWx0aXBsZVxuICAgIC8vIHZhbHVlcyBhdCB0aGUgc2FtZSBwb3NpdGlvbiBhbmQgdGhpcyB0cmFjZSBvbmx5IGhhcyBvbmUgdmFsdWUgdGhlcmUsXG4gICAgLy8gd2UganVzdCBkdXBsaWNhdGUgdGhhdCBvbmUgdmFsdWUgcmF0aGVyIHRoYW4gaW5zZXJ0IGEgemVyby5cbiAgICAvLyBXZSBhbHNvIG1ha2UgaXQgbG9vayBsaWtlIGEgcmVhbCBwb2ludCAtIGJlY2F1c2UgaXQncyBhbWJpZ3VvdXMgd2hpY2hcbiAgICAvLyBvbmUgcmVhbGx5IGlzIHRoZSByZWFsIG9uZSFcbiAgICBpZihpbmRleCAmJiBwb3NpdGlvbiA9PT0gY2FsY1RyYWNlW2luZGV4IC0gMV1bcG9zQXR0cl0pIHtcbiAgICAgICAgdmFyIHByZXZFbnRyeSA9IGNhbGNUcmFjZVtpbmRleCAtIDFdO1xuICAgICAgICBuZXdFbnRyeS5zID0gcHJldkVudHJ5LnM7XG4gICAgICAgIC8vIFRPRE8gaXMgaXQgZ29pbmcgdG8gY2F1c2UgYW55IHByb2JsZW1zIHRvIGhhdmUgbXVsdGlwbGVcbiAgICAgICAgLy8gY2FsY2RhdGEgcG9pbnRzIHdpdGggdGhlIHNhbWUgaW5kZXg/XG4gICAgICAgIG5ld0VudHJ5LmkgPSBwcmV2RW50cnkuaTtcbiAgICAgICAgbmV3RW50cnkuZ2FwID0gcHJldkVudHJ5LmdhcDtcbiAgICB9IGVsc2UgaWYoaW50ZXJwb2xhdGUpIHtcbiAgICAgICAgbmV3RW50cnkucyA9IGdldEludGVycChjYWxjVHJhY2UsIGluZGV4LCBwb3NpdGlvbiwgcG9zQXR0cik7XG4gICAgfVxuICAgIGlmKCFpbmRleCkge1xuICAgICAgICAvLyB0IGFuZCB0cmFjZSBuZWVkIHRvIHN0YXkgb24gdGhlIGZpcnN0IGNkIGVudHJ5XG4gICAgICAgIGNhbGNUcmFjZVswXS50ID0gY2FsY1RyYWNlWzFdLnQ7XG4gICAgICAgIGNhbGNUcmFjZVswXS50cmFjZSA9IGNhbGNUcmFjZVsxXS50cmFjZTtcbiAgICAgICAgZGVsZXRlIGNhbGNUcmFjZVsxXS50O1xuICAgICAgICBkZWxldGUgY2FsY1RyYWNlWzFdLnRyYWNlO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0SW50ZXJwKGNhbGNUcmFjZSwgaW5kZXgsIHBvc2l0aW9uLCBwb3NBdHRyKSB7XG4gICAgdmFyIHB0MCA9IGNhbGNUcmFjZVtpbmRleCAtIDFdO1xuICAgIHZhciBwdDEgPSBjYWxjVHJhY2VbaW5kZXggKyAxXTtcbiAgICBpZighcHQxKSByZXR1cm4gcHQwLnM7XG4gICAgaWYoIXB0MCkgcmV0dXJuIHB0MS5zO1xuICAgIHJldHVybiBwdDAucyArIChwdDEucyAtIHB0MC5zKSAqIChwb3NpdGlvbiAtIHB0MFtwb3NBdHRyXSkgLyAocHQxW3Bvc0F0dHJdIC0gcHQwW3Bvc0F0dHJdKTtcbn1cblxufSx7XCIuL2NhbGNcIjoxMTEzfV0sMTExODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG4vLyByZW1vdmUgb3BhY2l0eSBmb3IgYW55IHRyYWNlIHRoYXQgaGFzIGEgZmlsbCBvciBpcyBmaWxsZWQgdG9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3Jvc3NUcmFjZURlZmF1bHRzKGZ1bGxEYXRhKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZWkgPSBmdWxsRGF0YVtpXTtcbiAgICAgICAgaWYodHJhY2VpLnR5cGUgIT09ICdzY2F0dGVyJykgY29udGludWU7XG5cbiAgICAgICAgdmFyIGZpbGxpID0gdHJhY2VpLmZpbGw7XG4gICAgICAgIGlmKGZpbGxpID09PSAnbm9uZScgfHwgZmlsbGkgPT09ICd0b3NlbGYnKSBjb250aW51ZTtcblxuICAgICAgICB0cmFjZWkub3BhY2l0eSA9IHVuZGVmaW5lZDtcblxuICAgICAgICBpZihmaWxsaSA9PT0gJ3RvbmV4dHknIHx8IGZpbGxpID09PSAndG9uZXh0eCcpIHtcbiAgICAgICAgICAgIGZvcih2YXIgaiA9IGkgLSAxOyBqID49IDA7IGotLSkge1xuICAgICAgICAgICAgICAgIHZhciB0cmFjZWogPSBmdWxsRGF0YVtqXTtcblxuICAgICAgICAgICAgICAgIGlmKCh0cmFjZWoudHlwZSA9PT0gJ3NjYXR0ZXInKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKHRyYWNlai54YXhpcyA9PT0gdHJhY2VpLnhheGlzKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKHRyYWNlai55YXhpcyA9PT0gdHJhY2VpLnlheGlzKSkge1xuICAgICAgICAgICAgICAgICAgICB0cmFjZWoub3BhY2l0eSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxufSx7fV0sMTExOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG52YXIgY29uc3RhbnRzID0gX2RlcmVxXygnLi9jb25zdGFudHMnKTtcbnZhciBzdWJUeXBlcyA9IF9kZXJlcV8oJy4vc3VidHlwZXMnKTtcbnZhciBoYW5kbGVYWURlZmF1bHRzID0gX2RlcmVxXygnLi94eV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVN0YWNrRGVmYXVsdHMgPSBfZGVyZXFfKCcuL3N0YWNrX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTWFya2VyRGVmYXVsdHMgPSBfZGVyZXFfKCcuL21hcmtlcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVEZWZhdWx0cyA9IF9kZXJlcV8oJy4vbGluZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVTaGFwZURlZmF1bHRzID0gX2RlcmVxXygnLi9saW5lX3NoYXBlX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlVGV4dERlZmF1bHRzID0gX2RlcmVxXygnLi90ZXh0X2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlRmlsbENvbG9yRGVmYXVsdHMgPSBfZGVyZXFfKCcuL2ZpbGxjb2xvcl9kZWZhdWx0cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlWFlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuICAgIGlmKCFsZW4pIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcblxuICAgIGlmKCF0cmFjZU91dC52aXNpYmxlKSByZXR1cm47XG5cbiAgICB2YXIgc3RhY2tHcm91cE9wdHMgPSBoYW5kbGVTdGFja0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICB2YXIgZGVmYXVsdE1vZGUgPSAhc3RhY2tHcm91cE9wdHMgJiYgKGxlbiA8IGNvbnN0YW50cy5QVFNfTElORVNPTkxZKSA/XG4gICAgICAgICdsaW5lcyttYXJrZXJzJyA6ICdsaW5lcyc7XG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ21vZGUnLCBkZWZhdWx0TW9kZSk7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICAgICAgaGFuZGxlTGluZVNoYXBlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSk7XG4gICAgICAgIGNvZXJjZSgnY29ubmVjdGdhcHMnKTtcbiAgICAgICAgY29lcmNlKCdsaW5lLnNpbXBsaWZ5Jyk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTWFya2VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UsIHtncmFkaWVudDogdHJ1ZX0pO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc1RleHQodHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZVRleHREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuICAgIH1cblxuICAgIHZhciBkZmx0SG92ZXJPbiA9IFtdO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkgfHwgc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgY29lcmNlKCdjbGlwb25heGlzJyk7XG4gICAgICAgIGNvZXJjZSgnbWFya2VyLm1heGRpc3BsYXllZCcpO1xuICAgICAgICBkZmx0SG92ZXJPbi5wdXNoKCdwb2ludHMnKTtcbiAgICB9XG5cbiAgICAvLyBJdCdzIHBvc3NpYmxlIGZvciB0aGlzIGRlZmF1bHQgdG8gYmUgY2hhbmdlZCBieSBhIGxhdGVyIHRyYWNlLlxuICAgIC8vIFdlIGhhbmRsZSB0aGF0IGNhc2UgaW4gc29tZSBoYWNreSBjb2RlIGluc2lkZSBoYW5kbGVTdGFja0RlZmF1bHRzLlxuICAgIGNvZXJjZSgnZmlsbCcsIHN0YWNrR3JvdXBPcHRzID8gc3RhY2tHcm91cE9wdHMuZmlsbERmbHQgOiAnbm9uZScpO1xuICAgIGlmKHRyYWNlT3V0LmZpbGwgIT09ICdub25lJykge1xuICAgICAgICBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBjb2VyY2UpO1xuICAgICAgICBpZighc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSBoYW5kbGVMaW5lU2hhcGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICB2YXIgbGluZUNvbG9yID0gKHRyYWNlT3V0LmxpbmUgfHwge30pLmNvbG9yO1xuICAgIHZhciBtYXJrZXJDb2xvciA9ICh0cmFjZU91dC5tYXJrZXIgfHwge30pLmNvbG9yO1xuXG4gICAgaWYodHJhY2VPdXQuZmlsbCA9PT0gJ3RvbmV4dCcgfHwgdHJhY2VPdXQuZmlsbCA9PT0gJ3Rvc2VsZicpIHtcbiAgICAgICAgZGZsdEhvdmVyT24ucHVzaCgnZmlsbHMnKTtcbiAgICB9XG4gICAgY29lcmNlKCdob3Zlcm9uJywgZGZsdEhvdmVyT24uam9pbignKycpIHx8ICdwb2ludHMnKTtcbiAgICBpZih0cmFjZU91dC5ob3Zlcm9uICE9PSAnZmlsbHMnKSBjb2VyY2UoJ2hvdmVydGVtcGxhdGUnKTtcbiAgICB2YXIgZXJyb3JCYXJzU3VwcGx5RGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdzdXBwbHlEZWZhdWx0cycpO1xuICAgIGVycm9yQmFyc1N1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsaW5lQ29sb3IgfHwgbWFya2VyQ29sb3IgfHwgZGVmYXVsdENvbG9yLCB7YXhpczogJ3knfSk7XG4gICAgZXJyb3JCYXJzU3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxpbmVDb2xvciB8fCBtYXJrZXJDb2xvciB8fCBkZWZhdWx0Q29sb3IsIHtheGlzOiAneCcsIGluaGVyaXQ6ICd5J30pO1xuXG4gICAgTGliLmNvZXJjZVNlbGVjdGlvbk1hcmtlck9wYWNpdHkodHJhY2VPdXQsIGNvZXJjZSk7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9hdHRyaWJ1dGVzXCI6MTExMixcIi4vY29uc3RhbnRzXCI6MTExNixcIi4vZmlsbGNvbG9yX2RlZmF1bHRzXCI6MTEyMCxcIi4vbGluZV9kZWZhdWx0c1wiOjExMjQsXCIuL2xpbmVfc2hhcGVfZGVmYXVsdHNcIjoxMTI2LFwiLi9tYXJrZXJfZGVmYXVsdHNcIjoxMTMwLFwiLi9zdGFja19kZWZhdWx0c1wiOjExMzMsXCIuL3N1YnR5cGVzXCI6MTEzNSxcIi4vdGV4dF9kZWZhdWx0c1wiOjExMzYsXCIuL3h5X2RlZmF1bHRzXCI6MTEzN31dLDExMjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBmaWxsQ29sb3JEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBjb2VyY2UpIHtcbiAgICB2YXIgaW5oZXJpdENvbG9yRnJvbU1hcmtlciA9IGZhbHNlO1xuXG4gICAgaWYodHJhY2VPdXQubWFya2VyKSB7XG4gICAgICAgIC8vIGRvbid0IHRyeSB0byBpbmhlcml0IGEgY29sb3IgYXJyYXlcbiAgICAgICAgdmFyIG1hcmtlckNvbG9yID0gdHJhY2VPdXQubWFya2VyLmNvbG9yO1xuICAgICAgICB2YXIgbWFya2VyTGluZUNvbG9yID0gKHRyYWNlT3V0Lm1hcmtlci5saW5lIHx8IHt9KS5jb2xvcjtcblxuICAgICAgICBpZihtYXJrZXJDb2xvciAmJiAhaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXJDb2xvcikpIHtcbiAgICAgICAgICAgIGluaGVyaXRDb2xvckZyb21NYXJrZXIgPSBtYXJrZXJDb2xvcjtcbiAgICAgICAgfSBlbHNlIGlmKG1hcmtlckxpbmVDb2xvciAmJiAhaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXJMaW5lQ29sb3IpKSB7XG4gICAgICAgICAgICBpbmhlcml0Q29sb3JGcm9tTWFya2VyID0gbWFya2VyTGluZUNvbG9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29lcmNlKCdmaWxsY29sb3InLCBDb2xvci5hZGRPcGFjaXR5KFxuICAgICAgICAodHJhY2VPdXQubGluZSB8fCB7fSkuY29sb3IgfHxcbiAgICAgICAgaW5oZXJpdENvbG9yRnJvbU1hcmtlciB8fFxuICAgICAgICBkZWZhdWx0Q29sb3IsIDAuNVxuICAgICkpO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5fV0sMTEyMTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIHN1YnR5cGVzID0gX2RlcmVxXygnLi9zdWJ0eXBlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0VHJhY2VDb2xvcih0cmFjZSwgZGkpIHtcbiAgICB2YXIgbGMsIHRjO1xuXG4gICAgLy8gVE9ETzogdGV4dCBtb2Rlc1xuXG4gICAgaWYodHJhY2UubW9kZSA9PT0gJ2xpbmVzJykge1xuICAgICAgICBsYyA9IHRyYWNlLmxpbmUuY29sb3I7XG4gICAgICAgIHJldHVybiAobGMgJiYgQ29sb3Iub3BhY2l0eShsYykpID9cbiAgICAgICAgICAgIGxjIDogdHJhY2UuZmlsbGNvbG9yO1xuICAgIH0gZWxzZSBpZih0cmFjZS5tb2RlID09PSAnbm9uZScpIHtcbiAgICAgICAgcmV0dXJuIHRyYWNlLmZpbGwgPyB0cmFjZS5maWxsY29sb3IgOiAnJztcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbWMgPSBkaS5tY2MgfHwgKHRyYWNlLm1hcmtlciB8fCB7fSkuY29sb3I7XG4gICAgICAgIHZhciBtbGMgPSBkaS5tbGNjIHx8ICgodHJhY2UubWFya2VyIHx8IHt9KS5saW5lIHx8IHt9KS5jb2xvcjtcblxuICAgICAgICB0YyA9IChtYyAmJiBDb2xvci5vcGFjaXR5KG1jKSkgPyBtYyA6XG4gICAgICAgICAgICAobWxjICYmIENvbG9yLm9wYWNpdHkobWxjKSAmJlxuICAgICAgICAgICAgICAgIChkaS5tbHcgfHwgKCh0cmFjZS5tYXJrZXIgfHwge30pLmxpbmUgfHwge30pLndpZHRoKSkgPyBtbGMgOiAnJztcblxuICAgICAgICBpZih0Yykge1xuICAgICAgICAgICAgLy8gbWFrZSBzdXJlIHRoZSBwb2ludHMgYXJlbid0IFRPTyB0cmFuc3BhcmVudFxuICAgICAgICAgICAgaWYoQ29sb3Iub3BhY2l0eSh0YykgPCAwLjMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gQ29sb3IuYWRkT3BhY2l0eSh0YywgMC4zKTtcbiAgICAgICAgICAgIH0gZWxzZSByZXR1cm4gdGM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsYyA9ICh0cmFjZS5saW5lIHx8IHt9KS5jb2xvcjtcbiAgICAgICAgICAgIHJldHVybiAobGMgJiYgQ29sb3Iub3BhY2l0eShsYykgJiZcbiAgICAgICAgICAgICAgICBzdWJ0eXBlcy5oYXNMaW5lcyh0cmFjZSkgJiYgdHJhY2UubGluZS53aWR0aCkgP1xuICAgICAgICAgICAgICAgICAgICBsYyA6IHRyYWNlLmZpbGxjb2xvcjtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4vc3VidHlwZXNcIjoxMTM1fV0sMTEyMjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBGeCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgZ2V0VHJhY2VDb2xvciA9IF9kZXJlcV8oJy4vZ2V0X3RyYWNlX2NvbG9yJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgZmlsbFRleHQgPSBMaWIuZmlsbFRleHQ7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIHhhID0gcG9pbnREYXRhLnhhO1xuICAgIHZhciB5YSA9IHBvaW50RGF0YS55YTtcbiAgICB2YXIgeHB4ID0geGEuYzJwKHh2YWwpO1xuICAgIHZhciB5cHggPSB5YS5jMnAoeXZhbCk7XG4gICAgdmFyIHB0ID0gW3hweCwgeXB4XTtcbiAgICB2YXIgaG92ZXJvbiA9IHRyYWNlLmhvdmVyb24gfHwgJyc7XG4gICAgdmFyIG1pblJhZCA9ICh0cmFjZS5tb2RlLmluZGV4T2YoJ21hcmtlcnMnKSAhPT0gLTEpID8gMyA6IDAuNTtcblxuICAgIC8vIGxvb2sgZm9yIHBvaW50cyB0byBob3ZlciBvbiBmaXJzdCwgdGhlbiB0YWtlIGZpbGxzIG9ubHkgaWYgd2VcbiAgICAvLyBkaWRuJ3QgZmluZCBhIHBvaW50XG4gICAgaWYoaG92ZXJvbi5pbmRleE9mKCdwb2ludHMnKSAhPT0gLTEpIHtcbiAgICAgICAgdmFyIGR4ID0gZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgIC8vIGR4IGFuZCBkeSBhcmUgdXNlZCBpbiBjb21wYXJlIG1vZGVzIC0gaGVyZSB3ZSB3YW50IHRvIGFsd2F5c1xuICAgICAgICAgICAgLy8gcHJpb3JpdGl6ZSB0aGUgY2xvc2VzdCBkYXRhIHBvaW50LCBhdCBsZWFzdCBhcyBsb25nIGFzIG1hcmtlcnMgYXJlXG4gICAgICAgICAgICAvLyB0aGUgc2FtZSBzaXplIG9yIG5vbmV4aXN0ZW50LCBidXQgc3RpbGwgdHJ5IHRvIHByaW9yaXRpemUgc21hbGwgbWFya2VycyB0b28uXG4gICAgICAgICAgICB2YXIgcmFkID0gTWF0aC5tYXgoMywgZGkubXJjIHx8IDApO1xuICAgICAgICAgICAgdmFyIGtpbmsgPSAxIC0gMSAvIHJhZDtcbiAgICAgICAgICAgIHZhciBkeFJhdyA9IE1hdGguYWJzKHhhLmMycChkaS54KSAtIHhweCk7XG4gICAgICAgICAgICB2YXIgZCA9IChkeFJhdyA8IHJhZCkgPyAoa2luayAqIGR4UmF3IC8gcmFkKSA6IChkeFJhdyAtIHJhZCArIGtpbmspO1xuICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBkeSA9IGZ1bmN0aW9uKGRpKSB7XG4gICAgICAgICAgICB2YXIgcmFkID0gTWF0aC5tYXgoMywgZGkubXJjIHx8IDApO1xuICAgICAgICAgICAgdmFyIGtpbmsgPSAxIC0gMSAvIHJhZDtcbiAgICAgICAgICAgIHZhciBkeVJhdyA9IE1hdGguYWJzKHlhLmMycChkaS55KSAtIHlweCk7XG4gICAgICAgICAgICByZXR1cm4gKGR5UmF3IDwgcmFkKSA/IChraW5rICogZHlSYXcgLyByYWQpIDogKGR5UmF3IC0gcmFkICsga2luayk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBkeHkgPSBmdW5jdGlvbihkaSkge1xuICAgICAgICAgICAgLy8gc2NhdHRlciBwb2ludHM6IGQubXJjIGlzIHRoZSBjYWxjdWxhdGVkIG1hcmtlciByYWRpdXNcbiAgICAgICAgICAgIC8vIGFkanVzdCB0aGUgZGlzdGFuY2Ugc28gaWYgeW91J3JlIGluc2lkZSB0aGUgbWFya2VyIGl0XG4gICAgICAgICAgICAvLyBhbHdheXMgd2lsbCBzaG93IHVwIHJlZ2FyZGxlc3Mgb2YgcG9pbnQgc2l6ZSwgYnV0XG4gICAgICAgICAgICAvLyBwcmlvcml0aXplIHNtYWxsZXIgcG9pbnRzXG4gICAgICAgICAgICB2YXIgcmFkID0gTWF0aC5tYXgobWluUmFkLCBkaS5tcmMgfHwgMCk7XG4gICAgICAgICAgICB2YXIgZHggPSB4YS5jMnAoZGkueCkgLSB4cHg7XG4gICAgICAgICAgICB2YXIgZHkgPSB5YS5jMnAoZGkueSkgLSB5cHg7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5tYXgoTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KSAtIHJhZCwgMSAtIG1pblJhZCAvIHJhZCk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBkaXN0Zm4gPSBGeC5nZXREaXN0YW5jZUZ1bmN0aW9uKGhvdmVybW9kZSwgZHgsIGR5LCBkeHkpO1xuXG4gICAgICAgIEZ4LmdldENsb3Nlc3QoY2QsIGRpc3RmbiwgcG9pbnREYXRhKTtcblxuICAgICAgICAvLyBza2lwIHRoZSByZXN0IChmb3IgdGhpcyB0cmFjZSkgaWYgd2UgZGlkbid0IGZpbmQgYSBjbG9zZSBwb2ludFxuICAgICAgICBpZihwb2ludERhdGEuaW5kZXggIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAvLyB0aGUgY2xvc2VzdCBkYXRhIHBvaW50XG4gICAgICAgICAgICB2YXIgZGkgPSBjZFtwb2ludERhdGEuaW5kZXhdO1xuICAgICAgICAgICAgdmFyIHhjID0geGEuYzJwKGRpLngsIHRydWUpO1xuICAgICAgICAgICAgdmFyIHljID0geWEuYzJwKGRpLnksIHRydWUpO1xuICAgICAgICAgICAgdmFyIHJhZCA9IGRpLm1yYyB8fCAxO1xuXG4gICAgICAgICAgICAvLyBub3cgd2UncmUgZG9uZSB1c2luZyB0aGUgd2hvbGUgYGNhbGNkYXRhYCBhcnJheSwgcmVwbGFjZSB0aGVcbiAgICAgICAgICAgIC8vIGluZGV4IHdpdGggdGhlIG9yaWdpbmFsIGluZGV4IChpbiBjYXNlIG9mIGluc2VydGVkIHBvaW50IGZyb21cbiAgICAgICAgICAgIC8vIHN0YWNrZWQgYXJlYSlcbiAgICAgICAgICAgIHBvaW50RGF0YS5pbmRleCA9IGRpLmk7XG5cbiAgICAgICAgICAgIHZhciBvcmllbnRhdGlvbiA9IGNkWzBdLnQub3JpZW50YXRpb247XG4gICAgICAgICAgICAvLyBUT0RPOiBmb3Igc2NhdHRlciBhbmQgYmFyLCBvcHRpb24gdG8gc2hvdyAoc3ViKXRvdGFscyBhbmRcbiAgICAgICAgICAgIC8vIHJhdyBkYXRhPyBDdXJyZW50bHkgc3RhY2tlZCBhbmQvb3Igbm9ybWFsaXplZCBiYXJzIGp1c3Qgc2hvd1xuICAgICAgICAgICAgLy8gdGhlIG5vcm1hbGl6ZWQgaW5kaXZpZHVhbCBzaXplcywgc28gdGhhdCdzIHdoYXQgSSdtIGRvaW5nIGhlcmVcbiAgICAgICAgICAgIC8vIGZvciBub3cuXG4gICAgICAgICAgICB2YXIgc2l6ZVZhbCA9IG9yaWVudGF0aW9uICYmIChkaS5zTm9ybSB8fCBkaS5zKTtcbiAgICAgICAgICAgIHZhciB4TGFiZWxWYWwgPSAob3JpZW50YXRpb24gPT09ICdoJykgPyBzaXplVmFsIDogZGkueDtcbiAgICAgICAgICAgIHZhciB5TGFiZWxWYWwgPSAob3JpZW50YXRpb24gPT09ICd2JykgPyBzaXplVmFsIDogZGkueTtcblxuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQocG9pbnREYXRhLCB7XG4gICAgICAgICAgICAgICAgY29sb3I6IGdldFRyYWNlQ29sb3IodHJhY2UsIGRpKSxcblxuICAgICAgICAgICAgICAgIHgwOiB4YyAtIHJhZCxcbiAgICAgICAgICAgICAgICB4MTogeGMgKyByYWQsXG4gICAgICAgICAgICAgICAgeExhYmVsVmFsOiB4TGFiZWxWYWwsXG5cbiAgICAgICAgICAgICAgICB5MDogeWMgLSByYWQsXG4gICAgICAgICAgICAgICAgeTE6IHljICsgcmFkLFxuICAgICAgICAgICAgICAgIHlMYWJlbFZhbDogeUxhYmVsVmFsLFxuXG4gICAgICAgICAgICAgICAgc3Bpa2VEaXN0YW5jZTogZHh5KGRpKSxcbiAgICAgICAgICAgICAgICBob3ZlcnRlbXBsYXRlOiB0cmFjZS5ob3ZlcnRlbXBsYXRlXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZmlsbFRleHQoZGksIHRyYWNlLCBwb2ludERhdGEpO1xuICAgICAgICAgICAgUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnaG92ZXJJbmZvJykoZGksIHRyYWNlLCBwb2ludERhdGEpO1xuXG4gICAgICAgICAgICByZXR1cm4gW3BvaW50RGF0YV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBldmVuIGlmIGhvdmVyb24gaXMgJ2ZpbGxzJywgb25seSB1c2UgaXQgaWYgd2UgaGF2ZSBwb2x5Z29ucyB0b29cbiAgICBpZihob3Zlcm9uLmluZGV4T2YoJ2ZpbGxzJykgIT09IC0xICYmIHRyYWNlLl9wb2x5Z29ucykge1xuICAgICAgICB2YXIgcG9seWdvbnMgPSB0cmFjZS5fcG9seWdvbnM7XG4gICAgICAgIHZhciBwb2x5Z29uc0luID0gW107XG4gICAgICAgIHZhciBpbnNpZGUgPSBmYWxzZTtcbiAgICAgICAgdmFyIHhtaW4gPSBJbmZpbml0eTtcbiAgICAgICAgdmFyIHhtYXggPSAtSW5maW5pdHk7XG4gICAgICAgIHZhciB5bWluID0gSW5maW5pdHk7XG4gICAgICAgIHZhciB5bWF4ID0gLUluZmluaXR5O1xuXG4gICAgICAgIHZhciBpLCBqLCBwb2x5Z29uLCBwdHMsIHhDcm9zcywgeDAsIHgxLCB5MCwgeTE7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgcG9seWdvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHBvbHlnb24gPSBwb2x5Z29uc1tpXTtcbiAgICAgICAgICAgIC8vIFRPRE86IHRoaXMgaXMgbm90IGdvaW5nIHRvIHdvcmsgcmlnaHQgZm9yIGN1cnZlZCBlZGdlcywgaXQgd2lsbFxuICAgICAgICAgICAgLy8gYWN0IGFzIHRob3VnaCB0aGV5J3JlIHN0cmFpZ2h0LiBUaGF0J3MgcHJvYmFibHkgZ29pbmcgdG8gbmVlZFxuICAgICAgICAgICAgLy8gdGhlIGVsZW1lbnRzIHRoZW1zZWx2ZXMgdG8gY2FwdHVyZSB0aGUgZXZlbnRzLiBXb3J0aCBpdD9cbiAgICAgICAgICAgIGlmKHBvbHlnb24uY29udGFpbnMocHQpKSB7XG4gICAgICAgICAgICAgICAgaW5zaWRlID0gIWluc2lkZTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBuZWVkIGJldHRlciB0aGFuIGp1c3QgdGhlIG92ZXJhbGwgYm91bmRpbmcgYm94XG4gICAgICAgICAgICAgICAgcG9seWdvbnNJbi5wdXNoKHBvbHlnb24pO1xuICAgICAgICAgICAgICAgIHltaW4gPSBNYXRoLm1pbih5bWluLCBwb2x5Z29uLnltaW4pO1xuICAgICAgICAgICAgICAgIHltYXggPSBNYXRoLm1heCh5bWF4LCBwb2x5Z29uLnltYXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoaW5zaWRlKSB7XG4gICAgICAgICAgICAvLyBjb25zdHJhaW4geW1pbi9tYXggdG8gdGhlIHZpc2libGUgcGxvdCwgc28gdGhlIGxhYmVsIGdvZXNcbiAgICAgICAgICAgIC8vIGF0IHRoZSBtaWRkbGUgb2YgdGhlIHBpZWNlIHlvdSBjYW4gc2VlXG4gICAgICAgICAgICB5bWluID0gTWF0aC5tYXgoeW1pbiwgMCk7XG4gICAgICAgICAgICB5bWF4ID0gTWF0aC5taW4oeW1heCwgeWEuX2xlbmd0aCk7XG5cbiAgICAgICAgICAgIC8vIGZpbmQgdGhlIG92ZXJhbGwgbGVmdC1tb3N0IGFuZCByaWdodC1tb3N0IHBvaW50cyBvZiB0aGVcbiAgICAgICAgICAgIC8vIHBvbHlnb24ocykgd2UncmUgaW5zaWRlIGF0IHRoZWlyIGNvbWJpbmVkIHZlcnRpY2FsIG1pZHBvaW50LlxuICAgICAgICAgICAgLy8gVGhpcyBpcyB3aGVyZSB3ZSB3aWxsIGRyYXcgdGhlIGhvdmVyIGxhYmVsLlxuICAgICAgICAgICAgLy8gTm90ZSB0aGF0IHRoaXMgbWlnaHQgbm90IGJlIHRoZSB2ZXJ0aWNhbCBtaWRwb2ludCBvZiB0aGVcbiAgICAgICAgICAgIC8vIHdob2xlIHRyYWNlLCBpZiBpdCdzIGRpc2pvaW50LlxuICAgICAgICAgICAgdmFyIHlBdmcgPSAoeW1pbiArIHltYXgpIC8gMjtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IHBvbHlnb25zSW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwdHMgPSBwb2x5Z29uc0luW2ldLnB0cztcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDE7IGogPCBwdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgeTAgPSBwdHNbaiAtIDFdWzFdO1xuICAgICAgICAgICAgICAgICAgICB5MSA9IHB0c1tqXVsxXTtcbiAgICAgICAgICAgICAgICAgICAgaWYoKHkwID4geUF2ZykgIT09ICh5MSA+PSB5QXZnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgeDAgPSBwdHNbaiAtIDFdWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgeDEgPSBwdHNbal1bMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih5MSAtIHkwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeENyb3NzID0geDAgKyAoeDEgLSB4MCkgKiAoeUF2ZyAtIHkwKSAvICh5MSAtIHkwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bWluID0gTWF0aC5taW4oeG1pbiwgeENyb3NzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bWF4ID0gTWF0aC5tYXgoeG1heCwgeENyb3NzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gY29uc3RyYWluIHhtaW4vbWF4IHRvIHRoZSB2aXNpYmxlIHBsb3Qgbm93IHRvb1xuICAgICAgICAgICAgeG1pbiA9IE1hdGgubWF4KHhtaW4sIDApO1xuICAgICAgICAgICAgeG1heCA9IE1hdGgubWluKHhtYXgsIHhhLl9sZW5ndGgpO1xuXG4gICAgICAgICAgICAvLyBnZXQgb25seSBmaWxsIG9yIGxpbmUgY29sb3IgZm9yIHRoZSBob3ZlciBjb2xvclxuICAgICAgICAgICAgdmFyIGNvbG9yID0gQ29sb3IuZGVmYXVsdExpbmU7XG4gICAgICAgICAgICBpZihDb2xvci5vcGFjaXR5KHRyYWNlLmZpbGxjb2xvcikpIGNvbG9yID0gdHJhY2UuZmlsbGNvbG9yO1xuICAgICAgICAgICAgZWxzZSBpZihDb2xvci5vcGFjaXR5KCh0cmFjZS5saW5lIHx8IHt9KS5jb2xvcikpIHtcbiAgICAgICAgICAgICAgICBjb2xvciA9IHRyYWNlLmxpbmUuY29sb3I7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KHBvaW50RGF0YSwge1xuICAgICAgICAgICAgICAgIC8vIG5ldmVyIGxldCBhIDJEIG92ZXJyaWRlIDFEIHR5cGUgYXMgY2xvc2VzdCBwb2ludFxuICAgICAgICAgICAgICAgIC8vIGFsc286IG5vIHNwaWtlRGlzdGFuY2UsIGl0J3Mgbm90IGFsbG93ZWQgZm9yIGZpbGxzXG4gICAgICAgICAgICAgICAgZGlzdGFuY2U6IHBvaW50RGF0YS5tYXhIb3ZlckRpc3RhbmNlLFxuICAgICAgICAgICAgICAgIHgwOiB4bWluLFxuICAgICAgICAgICAgICAgIHgxOiB4bWF4LFxuICAgICAgICAgICAgICAgIHkwOiB5QXZnLFxuICAgICAgICAgICAgICAgIHkxOiB5QXZnLFxuICAgICAgICAgICAgICAgIGNvbG9yOiBjb2xvcixcbiAgICAgICAgICAgICAgICBob3ZlcnRlbXBsYXRlOiBmYWxzZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGRlbGV0ZSBwb2ludERhdGEuaW5kZXg7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlLnRleHQgJiYgIUFycmF5LmlzQXJyYXkodHJhY2UudGV4dCkpIHtcbiAgICAgICAgICAgICAgICBwb2ludERhdGEudGV4dCA9IFN0cmluZyh0cmFjZS50ZXh0KTtcbiAgICAgICAgICAgIH0gZWxzZSBwb2ludERhdGEudGV4dCA9IHRyYWNlLm5hbWU7XG5cbiAgICAgICAgICAgIHJldHVybiBbcG9pbnREYXRhXTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZnhcIjo2MzIsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4vZ2V0X3RyYWNlX2NvbG9yXCI6MTEyMX1dLDExMjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3VidHlwZXMgPSBfZGVyZXFfKCcuL3N1YnR5cGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhhc0xpbmVzOiBzdWJ0eXBlcy5oYXNMaW5lcyxcbiAgICBoYXNNYXJrZXJzOiBzdWJ0eXBlcy5oYXNNYXJrZXJzLFxuICAgIGhhc1RleHQ6IHN1YnR5cGVzLmhhc1RleHQsXG4gICAgaXNCdWJibGU6IHN1YnR5cGVzLmlzQnViYmxlLFxuXG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjcm9zc1RyYWNlRGVmYXVsdHM6IF9kZXJlcV8oJy4vY3Jvc3NfdHJhY2VfZGVmYXVsdHMnKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKS5jYWxjLFxuICAgIGNyb3NzVHJhY2VDYWxjOiBfZGVyZXFfKCcuL2Nyb3NzX3RyYWNlX2NhbGMnKSxcbiAgICBhcnJheXNUb0NhbGNkYXRhOiBfZGVyZXFfKCcuL2FycmF5c190b19jYWxjZGF0YScpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIGNvbG9yYmFyOiBfZGVyZXFfKCcuL21hcmtlcl9jb2xvcmJhcicpLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuL3N0eWxlJykuc3R5bGUsXG4gICAgc3R5bGVPblNlbGVjdDogX2RlcmVxXygnLi9zdHlsZScpLnN0eWxlT25TZWxlY3QsXG4gICAgaG92ZXJQb2ludHM6IF9kZXJlcV8oJy4vaG92ZXInKSxcbiAgICBzZWxlY3RQb2ludHM6IF9kZXJlcV8oJy4vc2VsZWN0JyksXG4gICAgYW5pbWF0YWJsZTogdHJ1ZSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3NjYXR0ZXInLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKSxcbiAgICBjYXRlZ29yaWVzOiBbXG4gICAgICAgICdjYXJ0ZXNpYW4nLCAnc3ZnJywgJ3N5bWJvbHMnLCAnZXJyb3JCYXJzT0snLCAnc2hvd0xlZ2VuZCcsICdzY2F0dGVyLWxpa2UnLFxuICAgICAgICAnem9vbVNjYWxlJ1xuICAgIF0sXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhblwiOjc3OCxcIi4vYXJyYXlzX3RvX2NhbGNkYXRhXCI6MTExMSxcIi4vYXR0cmlidXRlc1wiOjExMTIsXCIuL2NhbGNcIjoxMTEzLFwiLi9jcm9zc190cmFjZV9jYWxjXCI6MTExNyxcIi4vY3Jvc3NfdHJhY2VfZGVmYXVsdHNcIjoxMTE4LFwiLi9kZWZhdWx0c1wiOjExMTksXCIuL2hvdmVyXCI6MTEyMixcIi4vbWFya2VyX2NvbG9yYmFyXCI6MTEyOSxcIi4vcGxvdFwiOjExMzEsXCIuL3NlbGVjdFwiOjExMzIsXCIuL3N0eWxlXCI6MTEzNCxcIi4vc3VidHlwZXNcIjoxMTM1fV0sMTEyNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcbnZhciBoYXNDb2xvcnNjYWxlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hlbHBlcnMnKS5oYXNDb2xvcnNjYWxlO1xudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGxpbmVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSwgb3B0cykge1xuICAgIHZhciBtYXJrZXJDb2xvciA9ICh0cmFjZUluLm1hcmtlciB8fCB7fSkuY29sb3I7XG5cbiAgICBjb2VyY2UoJ2xpbmUuY29sb3InLCBkZWZhdWx0Q29sb3IpO1xuXG4gICAgaWYoaGFzQ29sb3JzY2FsZSh0cmFjZUluLCAnbGluZScpKSB7XG4gICAgICAgIGNvbG9yc2NhbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICdsaW5lLicsIGNMZXR0ZXI6ICdjJ30pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBsaW5lQ29sb3JEZmx0ID0gKGlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyQ29sb3IpID8gZmFsc2UgOiBtYXJrZXJDb2xvcikgfHwgZGVmYXVsdENvbG9yO1xuICAgICAgICBjb2VyY2UoJ2xpbmUuY29sb3InLCBsaW5lQ29sb3JEZmx0KTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2xpbmUud2lkdGgnKTtcbiAgICBpZighKG9wdHMgfHwge30pLm5vRGFzaCkgY29lcmNlKCdsaW5lLmRhc2gnKTtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzXCI6NjAzLFwiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hlbHBlcnNcIjo2MDQsXCIuLi8uLi9saWJcIjo3MTl9XSwxMTI1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgbnVtQ29uc3RhbnRzID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpO1xudmFyIEJBRE5VTSA9IG51bUNvbnN0YW50cy5CQUROVU07XG52YXIgTE9HX0NMSVAgPSBudW1Db25zdGFudHMuTE9HX0NMSVA7XG52YXIgTE9HX0NMSVBfUExVUyA9IExPR19DTElQICsgMC41O1xudmFyIExPR19DTElQX01JTlVTID0gTE9HX0NMSVAgLSAwLjU7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgc2VnbWVudHNJbnRlcnNlY3QgPSBMaWIuc2VnbWVudHNJbnRlcnNlY3Q7XG52YXIgY29uc3RyYWluID0gTGliLmNvbnN0cmFpbjtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbGluZVBvaW50cyhkLCBvcHRzKSB7XG4gICAgdmFyIHhhID0gb3B0cy54YXhpcztcbiAgICB2YXIgeWEgPSBvcHRzLnlheGlzO1xuICAgIHZhciB4TG9nID0geGEudHlwZSA9PT0gJ2xvZyc7XG4gICAgdmFyIHlMb2cgPSB5YS50eXBlID09PSAnbG9nJztcbiAgICB2YXIgeExlbiA9IHhhLl9sZW5ndGg7XG4gICAgdmFyIHlMZW4gPSB5YS5fbGVuZ3RoO1xuICAgIHZhciBjb25uZWN0R2FwcyA9IG9wdHMuY29ubmVjdEdhcHM7XG4gICAgdmFyIGJhc2VUb2xlcmFuY2UgPSBvcHRzLmJhc2VUb2xlcmFuY2U7XG4gICAgdmFyIHNoYXBlID0gb3B0cy5zaGFwZTtcbiAgICB2YXIgbGluZWFyID0gc2hhcGUgPT09ICdsaW5lYXInO1xuICAgIHZhciBmaWxsID0gb3B0cy5maWxsICYmIG9wdHMuZmlsbCAhPT0gJ25vbmUnO1xuICAgIHZhciBzZWdtZW50cyA9IFtdO1xuICAgIHZhciBtaW5Ub2xlcmFuY2UgPSBjb25zdGFudHMubWluVG9sZXJhbmNlO1xuICAgIHZhciBsZW4gPSBkLmxlbmd0aDtcbiAgICB2YXIgcHRzID0gbmV3IEFycmF5KGxlbik7XG4gICAgdmFyIHB0aSA9IDA7XG5cbiAgICB2YXIgaTtcblxuICAgIC8vIHB0IHZhcmlhYmxlcyBhcmUgcGl4ZWwgY29vcmRpbmF0ZXMgW3gseV0gb2Ygb25lIHBvaW50XG4gICAgLy8gdGhlc2UgZm91ciBhcmUgdGhlIG91dHB1dHMgb2YgY2x1c3RlcmluZyBvbiBhIGxpbmVcbiAgICB2YXIgY2x1c3RlclN0YXJ0UHQsIGNsdXN0ZXJFbmRQdCwgY2x1c3RlckhpZ2hQdCwgY2x1c3Rlckxvd1B0O1xuXG4gICAgLy8gXCJ0aGlzXCIgaXMgdGhlIG5leHQgcG9pbnQgd2UncmUgY29uc2lkZXJpbmcgYWRkaW5nIHRvIHRoZSBjbHVzdGVyXG4gICAgdmFyIHRoaXNQdDtcblxuICAgIC8vIGRpZCB3ZSBlbmNvdW50ZXIgdGhlIGhpZ2ggcG9pbnQgZmlyc3QsIHRoZW4gYSBsb3cgcG9pbnQsIG9yIHZpY2UgdmVyc2E/XG4gICAgdmFyIGNsdXN0ZXJIaWdoRmlyc3Q7XG5cbiAgICAvLyB0aGUgZmlyc3QgdHdvIHBvaW50cyBpbiB0aGUgY2x1c3RlciBkZXRlcm1pbmUgaXRzIHVuaXQgdmVjdG9yXG4gICAgLy8gc28gdGhlIHNlY29uZCBpcyBhbHdheXMgaW4gdGhlIFwiSGlnaFwiIGRpcmVjdGlvblxuICAgIHZhciBjbHVzdGVyVW5pdFZlY3RvcjtcblxuICAgIC8vIHRoZSBwaXhlbCBkZWx0YSBmcm9tIGNsdXN0ZXJTdGFydFB0XG4gICAgdmFyIHRoaXNWZWN0b3I7XG5cbiAgICAvLyB2YWwgdmFyaWFibGVzIGFyZSAoc2lnbmVkKSBwaXhlbCBkaXN0YW5jZXMgYWxvbmcgdGhlIGNsdXN0ZXIgdmVjdG9yXG4gICAgdmFyIGNsdXN0ZXJSZWZEaXN0LCBjbHVzdGVySGlnaFZhbCwgY2x1c3Rlckxvd1ZhbCwgdGhpc1ZhbDtcblxuICAgIC8vIGRldmlhdGlvbiB2YXJpYWJsZXMgYXJlIChzaWduZWQpIHBpeGVsIGRpc3RhbmNlcyBub3JtYWwgdG8gdGhlIGNsdXN0ZXIgdmVjdG9yXG4gICAgdmFyIGNsdXN0ZXJNaW5EZXZpYXRpb24sIGNsdXN0ZXJNYXhEZXZpYXRpb24sIHRoaXNEZXZpYXRpb247XG5cbiAgICAvLyB0dXJuIG9uZSBjYWxjZGF0YSBwb2ludCBpbnRvIHBpeGVsIGNvb3JkaW5hdGVzXG4gICAgZnVuY3Rpb24gZ2V0UHQoaW5kZXgpIHtcbiAgICAgICAgdmFyIGRpID0gZFtpbmRleF07XG4gICAgICAgIGlmKCFkaSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB2YXIgeCA9IHhhLmMycChkaS54KTtcbiAgICAgICAgdmFyIHkgPSB5YS5jMnAoZGkueSk7XG5cbiAgICAgICAgLy8gaWYgbm9uLXBvc2l0aXZlIGxvZyB2YWx1ZXMsIHNldCB0aGVtIFZFUlkgZmFyIG9mZi1zY3JlZW5cbiAgICAgICAgLy8gc28gdGhlIGxpbmUgbG9va3MgZXNzZW50aWFsbHkgc3RyYWlnaHQgZnJvbSB0aGUgcHJldmlvdXMgcG9pbnQuXG4gICAgICAgIGlmKHggPT09IEJBRE5VTSkge1xuICAgICAgICAgICAgaWYoeExvZykgeCA9IHhhLmMycChkaS54LCB0cnVlKTtcbiAgICAgICAgICAgIGlmKHggPT09IEJBRE5VTSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgLy8gSWYgQk9USCB3ZXJlIGJhZCBsb2cgdmFsdWVzLCBtYWtlIHRoZSBsaW5lIGZvbGxvdyBhIGNvbnN0YW50XG4gICAgICAgICAgICAvLyBleHBvbmVudCByYXRoZXIgdGhhbiBhIGNvbnN0YW50IHNsb3BlXG4gICAgICAgICAgICBpZih5TG9nICYmIHkgPT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgIHggKj0gTWF0aC5hYnMoeGEuX20gKiB5TGVuICogKHhhLl9tID4gMCA/IExPR19DTElQX1BMVVMgOiBMT0dfQ0xJUF9NSU5VUykgL1xuICAgICAgICAgICAgICAgICAgICAoeWEuX20gKiB4TGVuICogKHlhLl9tID4gMCA/IExPR19DTElQX1BMVVMgOiBMT0dfQ0xJUF9NSU5VUykpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHggKj0gMTAwMDtcbiAgICAgICAgfVxuICAgICAgICBpZih5ID09PSBCQUROVU0pIHtcbiAgICAgICAgICAgIGlmKHlMb2cpIHkgPSB5YS5jMnAoZGkueSwgdHJ1ZSk7XG4gICAgICAgICAgICBpZih5ID09PSBCQUROVU0pIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHkgKj0gMTAwMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW3gsIHldO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyb3NzZXNWaWV3cG9ydCh4RnJhYzAsIHlGcmFjMCwgeEZyYWMxLCB5RnJhYzEpIHtcbiAgICAgICAgdmFyIGR4ID0geEZyYWMxIC0geEZyYWMwO1xuICAgICAgICB2YXIgZHkgPSB5RnJhYzEgLSB5RnJhYzA7XG4gICAgICAgIHZhciBkeDAgPSAwLjUgLSB4RnJhYzA7XG4gICAgICAgIHZhciBkeTAgPSAwLjUgLSB5RnJhYzA7XG4gICAgICAgIHZhciBub3JtMiA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgICB2YXIgZG90ID0gZHggKiBkeDAgKyBkeSAqIGR5MDtcbiAgICAgICAgaWYoZG90ID4gMCAmJiBkb3QgPCBub3JtMikge1xuICAgICAgICAgICAgdmFyIGNyb3NzID0gZHgwICogZHkgLSBkeTAgKiBkeDtcbiAgICAgICAgICAgIGlmKGNyb3NzICogY3Jvc3MgPCBub3JtMikgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbGF0ZXN0WEZyYWMsIGxhdGVzdFlGcmFjO1xuICAgIC8vIGlmIHdlJ3JlIG9mZi1zY3JlZW4sIGluY3JlYXNlIHRvbGVyYW5jZSBvdmVyIGJhc2VUb2xlcmFuY2VcbiAgICBmdW5jdGlvbiBnZXRUb2xlcmFuY2UocHQsIG5leHRQdCkge1xuICAgICAgICB2YXIgeEZyYWMgPSBwdFswXSAvIHhMZW47XG4gICAgICAgIHZhciB5RnJhYyA9IHB0WzFdIC8geUxlbjtcbiAgICAgICAgdmFyIG9mZlNjcmVlbkZyYWN0aW9uID0gTWF0aC5tYXgoMCwgLXhGcmFjLCB4RnJhYyAtIDEsIC15RnJhYywgeUZyYWMgLSAxKTtcbiAgICAgICAgaWYob2ZmU2NyZWVuRnJhY3Rpb24gJiYgKGxhdGVzdFhGcmFjICE9PSB1bmRlZmluZWQpICYmXG4gICAgICAgICAgICBjcm9zc2VzVmlld3BvcnQoeEZyYWMsIHlGcmFjLCBsYXRlc3RYRnJhYywgbGF0ZXN0WUZyYWMpXG4gICAgICAgICkge1xuICAgICAgICAgICAgb2ZmU2NyZWVuRnJhY3Rpb24gPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmKG9mZlNjcmVlbkZyYWN0aW9uICYmIG5leHRQdCAmJlxuICAgICAgICAgICAgY3Jvc3Nlc1ZpZXdwb3J0KHhGcmFjLCB5RnJhYywgbmV4dFB0WzBdIC8geExlbiwgbmV4dFB0WzFdIC8geUxlbilcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBvZmZTY3JlZW5GcmFjdGlvbiA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKDEgKyBjb25zdGFudHMudG9sZXJhbmNlR3Jvd3RoICogb2ZmU2NyZWVuRnJhY3Rpb24pICogYmFzZVRvbGVyYW5jZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwdERpc3QocHQxLCBwdDIpIHtcbiAgICAgICAgdmFyIGR4ID0gcHQxWzBdIC0gcHQyWzBdO1xuICAgICAgICB2YXIgZHkgPSBwdDFbMV0gLSBwdDJbMV07XG4gICAgICAgIHJldHVybiBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuICAgIH1cblxuICAgIC8vIGxhc3QgYml0IG9mIGZpbHRlcmluZzogY2xpcCBwYXRocyB0aGF0IGFyZSBWRVJZIGZhciBvZmYtc2NyZWVuXG4gICAgLy8gc28gd2UgZG9uJ3QgZ2V0IG5lYXIgdGhlIGJyb3dzZXIncyBoYXJkIGxpbWl0ICgrLy0gMl4yOSBweCBpbiBDaHJvbWUgYW5kIEZGKVxuXG4gICAgdmFyIG1heFNjcmVlbnNBd2F5ID0gY29uc3RhbnRzLm1heFNjcmVlbnNBd2F5O1xuXG4gICAgLy8gZmluZCB0aGUgaW50ZXJzZWN0aW9ucyBiZXR3ZWVuIHRoZSBzZWdtZW50IGZyb20gcHQxIHRvIHB0MlxuICAgIC8vIGFuZCB0aGUgbGFyZ2UgcmVjdGFuZ2xlIG1heFNjcmVlbnNBd2F5IGFyb3VuZCB0aGUgdmlld3BvcnRcbiAgICAvLyBpZiBvbmUgb2YgcHQxIGFuZCBwdDIgaXMgaW5zaWRlIGFuZCB0aGUgb3RoZXIgb3V0c2lkZSwgdGhlcmVcbiAgICAvLyB3aWxsIGJlIG9ubHkgb25lIGludGVyc2VjdGlvbi5cbiAgICAvLyBpZiBib3RoIGFyZSBvdXRzaWRlIHRoZXJlIHdpbGwgYmUgMCBvciAyIGludGVyc2VjdGlvbnNcbiAgICAvLyAob3IgMSBpZiBpdCdzIHJpZ2h0IGF0IGEgY29ybmVyIC0gd2UnbGwgdHJlYXQgdGhhdCBsaWtlIDApXG4gICAgLy8gcmV0dXJucyBhbiBhcnJheSBvZiBpbnRlcnNlY3Rpb24gcHRzXG4gICAgdmFyIHhFZGdlMCA9IC14TGVuICogbWF4U2NyZWVuc0F3YXk7XG4gICAgdmFyIHhFZGdlMSA9IHhMZW4gKiAoMSArIG1heFNjcmVlbnNBd2F5KTtcbiAgICB2YXIgeUVkZ2UwID0gLXlMZW4gKiBtYXhTY3JlZW5zQXdheTtcbiAgICB2YXIgeUVkZ2UxID0geUxlbiAqICgxICsgbWF4U2NyZWVuc0F3YXkpO1xuICAgIHZhciBlZGdlcyA9IFtcbiAgICAgICAgW3hFZGdlMCwgeUVkZ2UwLCB4RWRnZTEsIHlFZGdlMF0sXG4gICAgICAgIFt4RWRnZTEsIHlFZGdlMCwgeEVkZ2UxLCB5RWRnZTFdLFxuICAgICAgICBbeEVkZ2UxLCB5RWRnZTEsIHhFZGdlMCwgeUVkZ2UxXSxcbiAgICAgICAgW3hFZGdlMCwgeUVkZ2UxLCB4RWRnZTAsIHlFZGdlMF1cbiAgICBdO1xuICAgIHZhciB4RWRnZSwgeUVkZ2UsIGxhc3RYRWRnZSwgbGFzdFlFZGdlLCBsYXN0RmFyUHQsIGVkZ2VQdDtcblxuICAgIC8vIGZvciBsaW5lYXIgbGluZSBzaGFwZSwgZWRnZSBpbnRlcnNlY3Rpb25zIHNob3VsZCBiZSBsaW5lYXJseSBpbnRlcnBvbGF0ZWRcbiAgICAvLyBzcGxpbmUgdXNlcyB0aGlzIHRvbywgd2hpY2ggaXNuJ3QgcHJlY2lzZWx5IGNvcnJlY3QgYnV0IGlzIGFjdHVhbGx5IHByZXR0eVxuICAgIC8vIGdvb2QsIGJlY2F1c2UgQ2F0bXVsbC1Sb20gd2VpZ2h0cyBmYXItYXdheSBwb2ludHMgbGVzcyBpbiBjcmVhdGluZyB0aGUgY3VydmF0dXJlXG4gICAgZnVuY3Rpb24gZ2V0TGluZWFyRWRnZUludGVyc2VjdGlvbnMocHQxLCBwdDIpIHtcbiAgICAgICAgdmFyIG91dCA9IFtdO1xuICAgICAgICB2YXIgcHRDb3VudCA9IDA7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICAgICAgICAgIHZhciBlZGdlID0gZWRnZXNbaV07XG4gICAgICAgICAgICB2YXIgcHRJbnQgPSBzZWdtZW50c0ludGVyc2VjdChcbiAgICAgICAgICAgICAgICBwdDFbMF0sIHB0MVsxXSwgcHQyWzBdLCBwdDJbMV0sXG4gICAgICAgICAgICAgICAgZWRnZVswXSwgZWRnZVsxXSwgZWRnZVsyXSwgZWRnZVszXVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmKHB0SW50ICYmICghcHRDb3VudCB8fFxuICAgICAgICAgICAgICAgIE1hdGguYWJzKHB0SW50LnggLSBvdXRbMF1bMF0pID4gMSB8fFxuICAgICAgICAgICAgICAgIE1hdGguYWJzKHB0SW50LnkgLSBvdXRbMF1bMV0pID4gMVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgICAgICAgIHB0SW50ID0gW3B0SW50LngsIHB0SW50LnldO1xuICAgICAgICAgICAgICAgIC8vIGlmIHdlIGhhdmUgMiBpbnRlcnNlY3Rpb25zLCBtYWtlIHN1cmUgdGhlIGNsb3Nlc3Qgb25lIHRvIHB0MSBjb21lcyBmaXJzdFxuICAgICAgICAgICAgICAgIGlmKHB0Q291bnQgJiYgcHREaXN0KHB0SW50LCBwdDEpIDwgcHREaXN0KG91dFswXSwgcHQxKSkgb3V0LnVuc2hpZnQocHRJbnQpO1xuICAgICAgICAgICAgICAgIGVsc2Ugb3V0LnB1c2gocHRJbnQpO1xuICAgICAgICAgICAgICAgIHB0Q291bnQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9ubHlDb25zdHJhaW5lZFBvaW50KHB0KSB7XG4gICAgICAgIGlmKHB0WzBdIDwgeEVkZ2UwIHx8IHB0WzBdID4geEVkZ2UxIHx8IHB0WzFdIDwgeUVkZ2UwIHx8IHB0WzFdID4geUVkZ2UxKSB7XG4gICAgICAgICAgICByZXR1cm4gW2NvbnN0cmFpbihwdFswXSwgeEVkZ2UwLCB4RWRnZTEpLCBjb25zdHJhaW4ocHRbMV0sIHlFZGdlMCwgeUVkZ2UxKV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzYW1lRWRnZShwdDEsIHB0Mikge1xuICAgICAgICBpZihwdDFbMF0gPT09IHB0MlswXSAmJiAocHQxWzBdID09PSB4RWRnZTAgfHwgcHQxWzBdID09PSB4RWRnZTEpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgaWYocHQxWzFdID09PSBwdDJbMV0gJiYgKHB0MVsxXSA9PT0geUVkZ2UwIHx8IHB0MVsxXSA9PT0geUVkZ2UxKSkgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gZm9yIGxpbmUgc2hhcGVzIGh2IGFuZCB2aCwgbW92ZW1lbnQgaW4gdGhlIHR3byBkaW1lbnNpb25zIGlzIGRlY291cGxlZCxcbiAgICAvLyBzbyBhbGwgd2UgbmVlZCB0byBkbyBpcyBjb25zdHJhaW4gZWFjaCBkaW1lbnNpb24gaW5kZXBlbmRlbnRseVxuICAgIGZ1bmN0aW9uIGdldEhWRWRnZUludGVyc2VjdGlvbnMocHQxLCBwdDIpIHtcbiAgICAgICAgdmFyIG91dCA9IFtdO1xuICAgICAgICB2YXIgcHRJbnQxID0gb25seUNvbnN0cmFpbmVkUG9pbnQocHQxKTtcbiAgICAgICAgdmFyIHB0SW50MiA9IG9ubHlDb25zdHJhaW5lZFBvaW50KHB0Mik7XG4gICAgICAgIGlmKHB0SW50MSAmJiBwdEludDIgJiYgc2FtZUVkZ2UocHRJbnQxLCBwdEludDIpKSByZXR1cm4gb3V0O1xuXG4gICAgICAgIGlmKHB0SW50MSkgb3V0LnB1c2gocHRJbnQxKTtcbiAgICAgICAgaWYocHRJbnQyKSBvdXQucHVzaChwdEludDIpO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cblxuICAgIC8vIGh2aCBhbmQgdmh2IHdlIHNvbWV0aW1lcyBoYXZlIHRvIG1vdmUgb25lIG9mIHRoZSBpbnRlcnNlY3Rpb24gcG9pbnRzXG4gICAgLy8gb3V0IEJFWU9ORCB0aGUgY2xpcHBpbmcgcmVjdCwgYnkgYSBtYXhpbXVtIG9mIGEgZmFjdG9yIG9mIDIsIHNvIHRoYXRcbiAgICAvLyB0aGUgbWlkcG9pbnQgbGluZSBpcyBkcmF3biBpbiB0aGUgcmlnaHQgcGxhY2VcbiAgICBmdW5jdGlvbiBnZXRBQkFFZGdlSW50ZXJzZWN0aW9ucyhkaW0sIGxpbWl0MCwgbGltaXQxKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihwdDEsIHB0Mikge1xuICAgICAgICAgICAgdmFyIHB0SW50MSA9IG9ubHlDb25zdHJhaW5lZFBvaW50KHB0MSk7XG4gICAgICAgICAgICB2YXIgcHRJbnQyID0gb25seUNvbnN0cmFpbmVkUG9pbnQocHQyKTtcblxuICAgICAgICAgICAgdmFyIG91dCA9IFtdO1xuICAgICAgICAgICAgaWYocHRJbnQxICYmIHB0SW50MiAmJiBzYW1lRWRnZShwdEludDEsIHB0SW50MikpIHJldHVybiBvdXQ7XG5cbiAgICAgICAgICAgIGlmKHB0SW50MSkgb3V0LnB1c2gocHRJbnQxKTtcbiAgICAgICAgICAgIGlmKHB0SW50Mikgb3V0LnB1c2gocHRJbnQyKTtcblxuICAgICAgICAgICAgdmFyIG1pZFNoaWZ0ID0gMiAqIExpYi5jb25zdHJhaW4oKHB0MVtkaW1dICsgcHQyW2RpbV0pIC8gMiwgbGltaXQwLCBsaW1pdDEpIC1cbiAgICAgICAgICAgICAgICAoKHB0SW50MSB8fCBwdDEpW2RpbV0gKyAocHRJbnQyIHx8IHB0MilbZGltXSk7XG4gICAgICAgICAgICBpZihtaWRTaGlmdCkge1xuICAgICAgICAgICAgICAgIHZhciBwdFRvQWx0ZXI7XG4gICAgICAgICAgICAgICAgaWYocHRJbnQxICYmIHB0SW50Mikge1xuICAgICAgICAgICAgICAgICAgICBwdFRvQWx0ZXIgPSAobWlkU2hpZnQgPiAwID09PSBwdEludDFbZGltXSA+IHB0SW50MltkaW1dKSA/IHB0SW50MSA6IHB0SW50MjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgcHRUb0FsdGVyID0gcHRJbnQxIHx8IHB0SW50MjtcblxuICAgICAgICAgICAgICAgIHB0VG9BbHRlcltkaW1dICs9IG1pZFNoaWZ0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBnZXRFZGdlSW50ZXJzZWN0aW9ucztcbiAgICBpZihzaGFwZSA9PT0gJ2xpbmVhcicgfHwgc2hhcGUgPT09ICdzcGxpbmUnKSB7XG4gICAgICAgIGdldEVkZ2VJbnRlcnNlY3Rpb25zID0gZ2V0TGluZWFyRWRnZUludGVyc2VjdGlvbnM7XG4gICAgfSBlbHNlIGlmKHNoYXBlID09PSAnaHYnIHx8IHNoYXBlID09PSAndmgnKSB7XG4gICAgICAgIGdldEVkZ2VJbnRlcnNlY3Rpb25zID0gZ2V0SFZFZGdlSW50ZXJzZWN0aW9ucztcbiAgICB9IGVsc2UgaWYoc2hhcGUgPT09ICdodmgnKSBnZXRFZGdlSW50ZXJzZWN0aW9ucyA9IGdldEFCQUVkZ2VJbnRlcnNlY3Rpb25zKDAsIHhFZGdlMCwgeEVkZ2UxKTtcbiAgICBlbHNlIGlmKHNoYXBlID09PSAndmh2JykgZ2V0RWRnZUludGVyc2VjdGlvbnMgPSBnZXRBQkFFZGdlSW50ZXJzZWN0aW9ucygxLCB5RWRnZTAsIHlFZGdlMSk7XG5cbiAgICAvLyBhIHNlZ21lbnQgcHQxLT5wdDIgZW50aXJlbHkgb3V0c2lkZSB0aGUgbmVhcmJ5IHJlZ2lvbjpcbiAgICAvLyBmaW5kIHRoZSBjb3JuZXIgaXQgZ2V0cyBjbG9zZXN0IHRvIHRvdWNoaW5nXG4gICAgZnVuY3Rpb24gZ2V0Q2xvc2VzdENvcm5lcihwdDEsIHB0Mikge1xuICAgICAgICB2YXIgZHggPSBwdDJbMF0gLSBwdDFbMF07XG4gICAgICAgIHZhciBtID0gKHB0MlsxXSAtIHB0MVsxXSkgLyBkeDtcbiAgICAgICAgdmFyIGIgPSAocHQxWzFdICogcHQyWzBdIC0gcHQyWzFdICogcHQxWzBdKSAvIGR4O1xuXG4gICAgICAgIGlmKGIgPiAwKSByZXR1cm4gW20gPiAwID8geEVkZ2UwIDogeEVkZ2UxLCB5RWRnZTFdO1xuICAgICAgICBlbHNlIHJldHVybiBbbSA+IDAgPyB4RWRnZTEgOiB4RWRnZTAsIHlFZGdlMF07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlRWRnZShwdCkge1xuICAgICAgICB2YXIgeCA9IHB0WzBdO1xuICAgICAgICB2YXIgeSA9IHB0WzFdO1xuICAgICAgICB2YXIgeFNhbWUgPSB4ID09PSBwdHNbcHRpIC0gMV1bMF07XG4gICAgICAgIHZhciB5U2FtZSA9IHkgPT09IHB0c1twdGkgLSAxXVsxXTtcbiAgICAgICAgLy8gZHVwbGljYXRlIHBvaW50P1xuICAgICAgICBpZih4U2FtZSAmJiB5U2FtZSkgcmV0dXJuO1xuICAgICAgICBpZihwdGkgPiAxKSB7XG4gICAgICAgICAgICAvLyBiYWNrdHJhY2tpbmcgYWxvbmcgYW4gZWRnZT9cbiAgICAgICAgICAgIHZhciB4U2FtZTIgPSB4ID09PSBwdHNbcHRpIC0gMl1bMF07XG4gICAgICAgICAgICB2YXIgeVNhbWUyID0geSA9PT0gcHRzW3B0aSAtIDJdWzFdO1xuICAgICAgICAgICAgaWYoeFNhbWUgJiYgKHggPT09IHhFZGdlMCB8fCB4ID09PSB4RWRnZTEpICYmIHhTYW1lMikge1xuICAgICAgICAgICAgICAgIGlmKHlTYW1lMikgcHRpLS07IC8vIGJhY2t0cmFja2luZyBleGFjdGx5IC0gZHJvcCBwcmV2IHB0IGFuZCBkb24ndCBhZGRcbiAgICAgICAgICAgICAgICBlbHNlIHB0c1twdGkgLSAxXSA9IHB0OyAvLyBub3QgZXhhY3Q6IHJlcGxhY2UgdGhlIHByZXYgcHRcbiAgICAgICAgICAgIH0gZWxzZSBpZih5U2FtZSAmJiAoeSA9PT0geUVkZ2UwIHx8IHkgPT09IHlFZGdlMSkgJiYgeVNhbWUyKSB7XG4gICAgICAgICAgICAgICAgaWYoeFNhbWUyKSBwdGktLTtcbiAgICAgICAgICAgICAgICBlbHNlIHB0c1twdGkgLSAxXSA9IHB0O1xuICAgICAgICAgICAgfSBlbHNlIHB0c1twdGkrK10gPSBwdDtcbiAgICAgICAgfSBlbHNlIHB0c1twdGkrK10gPSBwdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVFZGdlc0ZvclJlZW50cnkocHQpIHtcbiAgICAgICAgLy8gaWYgd2UncmUgb3V0c2lkZSB0aGUgbmVhcmJ5IHJlZ2lvbiBhbmQgZ29pbmcgYmFjayBpbixcbiAgICAgICAgLy8gd2UgbWF5IG5lZWQgdG8gbG9vcCBhcm91bmQgYSBjb3JuZXIgcG9pbnRcbiAgICAgICAgaWYocHRzW3B0aSAtIDFdWzBdICE9PSBwdFswXSAmJiBwdHNbcHRpIC0gMV1bMV0gIT09IHB0WzFdKSB7XG4gICAgICAgICAgICB1cGRhdGVFZGdlKFtsYXN0WEVkZ2UsIGxhc3RZRWRnZV0pO1xuICAgICAgICB9XG4gICAgICAgIHVwZGF0ZUVkZ2UocHQpO1xuICAgICAgICBsYXN0RmFyUHQgPSBudWxsO1xuICAgICAgICBsYXN0WEVkZ2UgPSBsYXN0WUVkZ2UgPSAwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFB0KHB0KSB7XG4gICAgICAgIGxhdGVzdFhGcmFjID0gcHRbMF0gLyB4TGVuO1xuICAgICAgICBsYXRlc3RZRnJhYyA9IHB0WzFdIC8geUxlbjtcbiAgICAgICAgLy8gQXJlIHdlIG1vcmUgdGhhbiBtYXhTY3JlZW5zQXdheSBvZmYtc2NyZWVuIGFueSBkaXJlY3Rpb24/XG4gICAgICAgIC8vIGlmIHNvLCBjbGlwIHRvIHRoaXMgYm94LCBidXQgaW4gc3VjaCBhIHdheSB0aGF0IG9uLXNjcmVlblxuICAgICAgICAvLyBkcmF3aW5nIGlzIHVuY2hhbmdlZFxuICAgICAgICB4RWRnZSA9IChwdFswXSA8IHhFZGdlMCkgPyB4RWRnZTAgOiAocHRbMF0gPiB4RWRnZTEpID8geEVkZ2UxIDogMDtcbiAgICAgICAgeUVkZ2UgPSAocHRbMV0gPCB5RWRnZTApID8geUVkZ2UwIDogKHB0WzFdID4geUVkZ2UxKSA/IHlFZGdlMSA6IDA7XG4gICAgICAgIGlmKHhFZGdlIHx8IHlFZGdlKSB7XG4gICAgICAgICAgICBpZighcHRpKSB7XG4gICAgICAgICAgICAgICAgLy8gdG8gZ2V0IGZpbGxzIHJpZ2h0IC0gaWYgZmlyc3QgcG9pbnQgaXMgZmFyLCBwdXNoIGl0IHRvd2FyZCB0aGVcbiAgICAgICAgICAgICAgICAvLyBzY3JlZW4gaW4gd2hpY2hldmVyIGRpcmVjdGlvbihzKSBhcmUgZmFyXG5cbiAgICAgICAgICAgICAgICBwdHNbcHRpKytdID0gW3hFZGdlIHx8IHB0WzBdLCB5RWRnZSB8fCBwdFsxXV07XG4gICAgICAgICAgICB9IGVsc2UgaWYobGFzdEZhclB0KSB7XG4gICAgICAgICAgICAgICAgLy8gYm90aCB0aGlzIHBvaW50IGFuZCB0aGUgbGFzdCBhcmUgb3V0c2lkZSB0aGUgbmVhcmJ5IHJlZ2lvblxuICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIHdlJ3JlIGNyb3NzaW5nIHRoZSBuZWFyYnkgcmVnaW9uXG4gICAgICAgICAgICAgICAgdmFyIGludGVyc2VjdGlvbnMgPSBnZXRFZGdlSW50ZXJzZWN0aW9ucyhsYXN0RmFyUHQsIHB0KTtcbiAgICAgICAgICAgICAgICBpZihpbnRlcnNlY3Rpb25zLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlRWRnZXNGb3JSZWVudHJ5KGludGVyc2VjdGlvbnNbMF0pO1xuICAgICAgICAgICAgICAgICAgICBwdHNbcHRpKytdID0gaW50ZXJzZWN0aW9uc1sxXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHdlJ3JlIGxlYXZpbmcgdGhlIG5lYXJieSByZWdpb24gLSBhZGQgdGhlIHBvaW50IHdoZXJlIHdlIGxlZnQgaXRcblxuICAgICAgICAgICAgICAgIGVkZ2VQdCA9IGdldEVkZ2VJbnRlcnNlY3Rpb25zKHB0c1twdGkgLSAxXSwgcHQpWzBdO1xuICAgICAgICAgICAgICAgIHB0c1twdGkrK10gPSBlZGdlUHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBsYXN0UHQgPSBwdHNbcHRpIC0gMV07XG4gICAgICAgICAgICBpZih4RWRnZSAmJiB5RWRnZSAmJiAobGFzdFB0WzBdICE9PSB4RWRnZSB8fCBsYXN0UHRbMV0gIT09IHlFZGdlKSkge1xuICAgICAgICAgICAgICAgIC8vIHdlJ3ZlIGdvbmUgb3V0IGJleW9uZCBhIG5ldyBjb3JuZXI6IGFkZCB0aGUgY29ybmVyIHRvb1xuICAgICAgICAgICAgICAgIC8vIHNvIHRoYXQgdGhlIG5leHQgcG9pbnQgd2lsbCB0YWtlIHRoZSByaWdodCB3aW5kaW5nXG4gICAgICAgICAgICAgICAgaWYobGFzdEZhclB0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGxhc3RYRWRnZSAhPT0geEVkZ2UgJiYgbGFzdFlFZGdlICE9PSB5RWRnZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYobGFzdFhFZGdlICYmIGxhc3RZRWRnZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlJ3ZlIGdvbmUgYXJvdW5kIHRvIGFuIG9wcG9zaXRlIGNvcm5lciAtIHdlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbmVlZCB0byBhZGQgdGhlIGNvcnJlY3QgZXh0cmEgY29ybmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gb3JkZXIgdG8gZ2V0IHRoZSByaWdodCB3aW5kaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlRWRnZShnZXRDbG9zZXN0Q29ybmVyKGxhc3RGYXJQdCwgcHQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2UncmUgY29taW5nIGZyb20gYSBmYXIgZWRnZSAtIHRoZSBleHRyYSBjb3JuZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBuZWVkIGlzIGRldGVybWluZWQgdW5pcXVlbHkgYnkgdGhlIHNlY3RvcnNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVFZGdlKFtsYXN0WEVkZ2UgfHwgeEVkZ2UsIGxhc3RZRWRnZSB8fCB5RWRnZV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYobGFzdFhFZGdlICYmIGxhc3RZRWRnZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlRWRnZShbbGFzdFhFZGdlLCBsYXN0WUVkZ2VdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB1cGRhdGVFZGdlKFt4RWRnZSwgeUVkZ2VdKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZigobGFzdFhFZGdlIC0geEVkZ2UpICYmIChsYXN0WUVkZ2UgLSB5RWRnZSkpIHtcbiAgICAgICAgICAgICAgICAvLyB3ZSdyZSBjb21pbmcgZnJvbSBhbiBlZGdlIG9yIGZhciBjb3JuZXIgdG8gYW4gZWRnZSAtIGFnYWluIHRoZVxuICAgICAgICAgICAgICAgIC8vIGV4dHJhIGNvcm5lciB3ZSBuZWVkIGlzIHVuaXF1ZWx5IGRldGVybWluZWQgYnkgdGhlIHNlY3RvcnNcbiAgICAgICAgICAgICAgICB1cGRhdGVFZGdlKFt4RWRnZSB8fCBsYXN0WEVkZ2UsIHlFZGdlIHx8IGxhc3RZRWRnZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGFzdEZhclB0ID0gcHQ7XG4gICAgICAgICAgICBsYXN0WEVkZ2UgPSB4RWRnZTtcbiAgICAgICAgICAgIGxhc3RZRWRnZSA9IHlFZGdlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYobGFzdEZhclB0KSB7XG4gICAgICAgICAgICAgICAgLy8gdGhpcyBwb2ludCBpcyBpbiByYW5nZSBidXQgdGhlIHByZXZpb3VzIHdhc24ndDogYWRkIGl0cyBlbnRyeSBwdCBmaXJzdFxuICAgICAgICAgICAgICAgIHVwZGF0ZUVkZ2VzRm9yUmVlbnRyeShnZXRFZGdlSW50ZXJzZWN0aW9ucyhsYXN0RmFyUHQsIHB0KVswXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHB0c1twdGkrK10gPSBwdDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGxvb3Agb3ZlciBBTEwgcG9pbnRzIGluIHRoaXMgdHJhY2VcbiAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBjbHVzdGVyU3RhcnRQdCA9IGdldFB0KGkpO1xuICAgICAgICBpZighY2x1c3RlclN0YXJ0UHQpIGNvbnRpbnVlO1xuXG4gICAgICAgIHB0aSA9IDA7XG4gICAgICAgIGxhc3RGYXJQdCA9IG51bGw7XG4gICAgICAgIGFkZFB0KGNsdXN0ZXJTdGFydFB0KTtcblxuICAgICAgICAvLyBsb29wIG92ZXIgb25lIHNlZ21lbnQgb2YgdGhlIHRyYWNlXG4gICAgICAgIGZvcihpKys7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgY2x1c3RlckhpZ2hQdCA9IGdldFB0KGkpO1xuICAgICAgICAgICAgaWYoIWNsdXN0ZXJIaWdoUHQpIHtcbiAgICAgICAgICAgICAgICBpZihjb25uZWN0R2FwcykgY29udGludWU7XG4gICAgICAgICAgICAgICAgZWxzZSBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gY2FuJ3QgZGVjaW1hdGUgaWYgbm9ubGluZWFyIGxpbmUgc2hhcGVcbiAgICAgICAgICAgIC8vIFRPRE86IHdlICpjb3VsZCogZGVjaW1hdGUgW2h2XXsyLDN9IHNoYXBlcyBpZiB3ZSByZXN0cmljdGVkIGNsdXN0ZXJzIHRvIGhvcnogb3IgdmVydCBhZ2FpblxuICAgICAgICAgICAgLy8gYnV0IHNwbGluZSB3b3VsZCBiZSB2ZXJycnkgYXdrd2FyZCB0byBkZWNpbWF0ZVxuICAgICAgICAgICAgaWYoIWxpbmVhciB8fCAhb3B0cy5zaW1wbGlmeSkge1xuICAgICAgICAgICAgICAgIGFkZFB0KGNsdXN0ZXJIaWdoUHQpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgbmV4dFB0ID0gZ2V0UHQoaSArIDEpO1xuXG4gICAgICAgICAgICBjbHVzdGVyUmVmRGlzdCA9IHB0RGlzdChjbHVzdGVySGlnaFB0LCBjbHVzdGVyU3RhcnRQdCk7XG5cbiAgICAgICAgICAgIC8vICMzMTQ3IC0gYWx3YXlzIGluY2x1ZGUgdGhlIHZlcnkgZmlyc3QgYW5kIGxhc3QgcG9pbnRzIGZvciBmaWxsc1xuICAgICAgICAgICAgaWYoIShmaWxsICYmIChwdGkgPT09IDAgfHwgcHRpID09PSBsZW4gLSAxKSkgJiZcbiAgICAgICAgICAgICAgICBjbHVzdGVyUmVmRGlzdCA8IGdldFRvbGVyYW5jZShjbHVzdGVySGlnaFB0LCBuZXh0UHQpICogbWluVG9sZXJhbmNlKSBjb250aW51ZTtcblxuICAgICAgICAgICAgY2x1c3RlclVuaXRWZWN0b3IgPSBbXG4gICAgICAgICAgICAgICAgKGNsdXN0ZXJIaWdoUHRbMF0gLSBjbHVzdGVyU3RhcnRQdFswXSkgLyBjbHVzdGVyUmVmRGlzdCxcbiAgICAgICAgICAgICAgICAoY2x1c3RlckhpZ2hQdFsxXSAtIGNsdXN0ZXJTdGFydFB0WzFdKSAvIGNsdXN0ZXJSZWZEaXN0XG4gICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICBjbHVzdGVyTG93UHQgPSBjbHVzdGVyU3RhcnRQdDtcbiAgICAgICAgICAgIGNsdXN0ZXJIaWdoVmFsID0gY2x1c3RlclJlZkRpc3Q7XG4gICAgICAgICAgICBjbHVzdGVyTG93VmFsID0gY2x1c3Rlck1pbkRldmlhdGlvbiA9IGNsdXN0ZXJNYXhEZXZpYXRpb24gPSAwO1xuICAgICAgICAgICAgY2x1c3RlckhpZ2hGaXJzdCA9IGZhbHNlO1xuICAgICAgICAgICAgY2x1c3RlckVuZFB0ID0gY2x1c3RlckhpZ2hQdDtcblxuICAgICAgICAgICAgLy8gbG9vcCBvdmVyIG9uZSBjbHVzdGVyIG9mIHBvaW50cyB0aGF0IGNvbGxhcHNlIG9udG8gb25lIGxpbmVcbiAgICAgICAgICAgIGZvcihpKys7IGkgPCBkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpc1B0ID0gbmV4dFB0O1xuICAgICAgICAgICAgICAgIG5leHRQdCA9IGdldFB0KGkgKyAxKTtcbiAgICAgICAgICAgICAgICBpZighdGhpc1B0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGNvbm5lY3RHYXBzKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpc1ZlY3RvciA9IFtcbiAgICAgICAgICAgICAgICAgICAgdGhpc1B0WzBdIC0gY2x1c3RlclN0YXJ0UHRbMF0sXG4gICAgICAgICAgICAgICAgICAgIHRoaXNQdFsxXSAtIGNsdXN0ZXJTdGFydFB0WzFdXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAvLyBjcm9zcyBwcm9kdWN0IChvciBkb3Qgd2l0aCBub3JtYWwgdG8gdGhlIGNsdXN0ZXIgdmVjdG9yKVxuICAgICAgICAgICAgICAgIHRoaXNEZXZpYXRpb24gPSB0aGlzVmVjdG9yWzBdICogY2x1c3RlclVuaXRWZWN0b3JbMV0gLSB0aGlzVmVjdG9yWzFdICogY2x1c3RlclVuaXRWZWN0b3JbMF07XG4gICAgICAgICAgICAgICAgY2x1c3Rlck1pbkRldmlhdGlvbiA9IE1hdGgubWluKGNsdXN0ZXJNaW5EZXZpYXRpb24sIHRoaXNEZXZpYXRpb24pO1xuICAgICAgICAgICAgICAgIGNsdXN0ZXJNYXhEZXZpYXRpb24gPSBNYXRoLm1heChjbHVzdGVyTWF4RGV2aWF0aW9uLCB0aGlzRGV2aWF0aW9uKTtcblxuICAgICAgICAgICAgICAgIGlmKGNsdXN0ZXJNYXhEZXZpYXRpb24gLSBjbHVzdGVyTWluRGV2aWF0aW9uID4gZ2V0VG9sZXJhbmNlKHRoaXNQdCwgbmV4dFB0KSkgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjbHVzdGVyRW5kUHQgPSB0aGlzUHQ7XG4gICAgICAgICAgICAgICAgdGhpc1ZhbCA9IHRoaXNWZWN0b3JbMF0gKiBjbHVzdGVyVW5pdFZlY3RvclswXSArIHRoaXNWZWN0b3JbMV0gKiBjbHVzdGVyVW5pdFZlY3RvclsxXTtcblxuICAgICAgICAgICAgICAgIGlmKHRoaXNWYWwgPiBjbHVzdGVySGlnaFZhbCkge1xuICAgICAgICAgICAgICAgICAgICBjbHVzdGVySGlnaFZhbCA9IHRoaXNWYWw7XG4gICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJIaWdoUHQgPSB0aGlzUHQ7XG4gICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJIaWdoRmlyc3QgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYodGhpc1ZhbCA8IGNsdXN0ZXJMb3dWYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2x1c3Rlckxvd1ZhbCA9IHRoaXNWYWw7XG4gICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJMb3dQdCA9IHRoaXNQdDtcbiAgICAgICAgICAgICAgICAgICAgY2x1c3RlckhpZ2hGaXJzdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpbnNlcnQgdGhpcyBjbHVzdGVyIGludG8gcHRzXG4gICAgICAgICAgICAvLyB3ZSd2ZSBhbHJlYWR5IGluc2VydGVkIHRoZSBzdGFydCBwdCwgbm93IGNoZWNrIGlmIHdlIGhhdmUgaGlnaCBhbmQgbG93IHB0c1xuICAgICAgICAgICAgaWYoY2x1c3RlckhpZ2hGaXJzdCkge1xuICAgICAgICAgICAgICAgIGFkZFB0KGNsdXN0ZXJIaWdoUHQpO1xuICAgICAgICAgICAgICAgIGlmKGNsdXN0ZXJFbmRQdCAhPT0gY2x1c3Rlckxvd1B0KSBhZGRQdChjbHVzdGVyTG93UHQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZihjbHVzdGVyTG93UHQgIT09IGNsdXN0ZXJTdGFydFB0KSBhZGRQdChjbHVzdGVyTG93UHQpO1xuICAgICAgICAgICAgICAgIGlmKGNsdXN0ZXJFbmRQdCAhPT0gY2x1c3RlckhpZ2hQdCkgYWRkUHQoY2x1c3RlckhpZ2hQdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBhbmQgZmluYWxseSBpbnNlcnQgdGhlIGVuZCBwdFxuICAgICAgICAgICAgYWRkUHQoY2x1c3RlckVuZFB0KTtcblxuICAgICAgICAgICAgLy8gaGF2ZSB3ZSByZWFjaGVkIHRoZSBlbmQgb2YgdGhpcyBzZWdtZW50P1xuICAgICAgICAgICAgaWYoaSA+PSBkLmxlbmd0aCB8fCAhdGhpc1B0KSBicmVhaztcblxuICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIHdlIGhhdmUgYW4gb3V0LW9mLWNsdXN0ZXIgcG9pbnQgdG8gaW5zZXJ0IGFzIG5leHQgY2x1c3RlclN0YXJ0UHRcbiAgICAgICAgICAgIGFkZFB0KHRoaXNQdCk7XG4gICAgICAgICAgICBjbHVzdGVyU3RhcnRQdCA9IHRoaXNQdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRvIGdldCBmaWxscyByaWdodCAtIHJlcGVhdCB3aGF0IHdlIGRpZCBhdCB0aGUgc3RhcnRcbiAgICAgICAgaWYobGFzdEZhclB0KSB1cGRhdGVFZGdlKFtsYXN0WEVkZ2UgfHwgbGFzdEZhclB0WzBdLCBsYXN0WUVkZ2UgfHwgbGFzdEZhclB0WzFdXSk7XG5cbiAgICAgICAgc2VnbWVudHMucHVzaChwdHMuc2xpY2UoMCwgcHRpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlZ21lbnRzO1xufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vbGliXCI6NzE5LFwiLi9jb25zdGFudHNcIjoxMTE2fV0sMTEyNjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG4vLyBjb21tb24gdG8gJ3NjYXR0ZXInIGFuZCAnc2NhdHRlcnRlcm5hcnknXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZUxpbmVTaGFwZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UpIHtcbiAgICB2YXIgc2hhcGUgPSBjb2VyY2UoJ2xpbmUuc2hhcGUnKTtcbiAgICBpZihzaGFwZSA9PT0gJ3NwbGluZScpIGNvZXJjZSgnbGluZS5zbW9vdGhpbmcnKTtcbn07XG5cbn0se31dLDExMjc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTElOS0VERklMTFMgPSB7dG9uZXh0eDogMSwgdG9uZXh0eTogMSwgdG9uZXh0OiAxfTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBsaW5rVHJhY2VzKGdkLCBwbG90aW5mbywgY2RzY2F0dGVyKSB7XG4gICAgdmFyIHRyYWNlLCBpLCBncm91cCwgcHJldnRyYWNlLCBncm91cEluZGV4O1xuXG4gICAgLy8gZmlyc3Qgc29ydCB0cmFjZXMgdG8ga2VlcCBzdGFja3MgJiBmaWxsZWQtdG9nZXRoZXIgZ3JvdXBzIHRvZ2V0aGVyXG4gICAgdmFyIGdyb3VwSW5kaWNlcyA9IHt9O1xuICAgIHZhciBuZWVkc1NvcnQgPSBmYWxzZTtcbiAgICB2YXIgcHJldkdyb3VwSW5kZXggPSAtMTtcbiAgICB2YXIgbmV4dEdyb3VwSW5kZXggPSAwO1xuICAgIHZhciBwcmV2VW5zdGFja2VkR3JvdXBJbmRleCA9IC0xO1xuICAgIGZvcihpID0gMDsgaSA8IGNkc2NhdHRlci5sZW5ndGg7IGkrKykge1xuICAgICAgICB0cmFjZSA9IGNkc2NhdHRlcltpXVswXS50cmFjZTtcbiAgICAgICAgZ3JvdXAgPSB0cmFjZS5zdGFja2dyb3VwIHx8ICcnO1xuICAgICAgICBpZihncm91cCkge1xuICAgICAgICAgICAgaWYoZ3JvdXAgaW4gZ3JvdXBJbmRpY2VzKSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBJbmRleCA9IGdyb3VwSW5kaWNlc1tncm91cF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGdyb3VwSW5kZXggPSBncm91cEluZGljZXNbZ3JvdXBdID0gbmV4dEdyb3VwSW5kZXg7XG4gICAgICAgICAgICAgICAgbmV4dEdyb3VwSW5kZXgrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKHRyYWNlLmZpbGwgaW4gTElOS0VERklMTFMgJiYgcHJldlVuc3RhY2tlZEdyb3VwSW5kZXggPj0gMCkge1xuICAgICAgICAgICAgZ3JvdXBJbmRleCA9IHByZXZVbnN0YWNrZWRHcm91cEluZGV4O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ3JvdXBJbmRleCA9IHByZXZVbnN0YWNrZWRHcm91cEluZGV4ID0gbmV4dEdyb3VwSW5kZXg7XG4gICAgICAgICAgICBuZXh0R3JvdXBJbmRleCsrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZ3JvdXBJbmRleCA8IHByZXZHcm91cEluZGV4KSBuZWVkc1NvcnQgPSB0cnVlO1xuICAgICAgICB0cmFjZS5fZ3JvdXBJbmRleCA9IHByZXZHcm91cEluZGV4ID0gZ3JvdXBJbmRleDtcbiAgICB9XG5cbiAgICB2YXIgY2RzY2F0dGVyU29ydGVkID0gY2RzY2F0dGVyLnNsaWNlKCk7XG4gICAgaWYobmVlZHNTb3J0KSB7XG4gICAgICAgIGNkc2NhdHRlclNvcnRlZC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICAgIHZhciB0cmFjZUEgPSBhWzBdLnRyYWNlO1xuICAgICAgICAgICAgdmFyIHRyYWNlQiA9IGJbMF0udHJhY2U7XG4gICAgICAgICAgICByZXR1cm4gKHRyYWNlQS5fZ3JvdXBJbmRleCAtIHRyYWNlQi5fZ3JvdXBJbmRleCkgfHxcbiAgICAgICAgICAgICAgICAodHJhY2VBLmluZGV4IC0gdHJhY2VCLmluZGV4KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gbm93IGxpbmsgdHJhY2VzIHRvIGVhY2ggb3RoZXJcbiAgICB2YXIgcHJldnRyYWNlcyA9IHt9O1xuICAgIGZvcihpID0gMDsgaSA8IGNkc2NhdHRlclNvcnRlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICB0cmFjZSA9IGNkc2NhdHRlclNvcnRlZFtpXVswXS50cmFjZTtcbiAgICAgICAgZ3JvdXAgPSB0cmFjZS5zdGFja2dyb3VwIHx8ICcnO1xuXG4gICAgICAgIC8vIE5vdGU6IFRoZSBjaGVjayB3aGljaCBlbnN1cmVzIGFsbCBjZHNjYXR0ZXIgaGVyZSBhcmUgZm9yIHRoZSBzYW1lIGF4aXMgYW5kXG4gICAgICAgIC8vIGFyZSBlaXRoZXIgY2FydGVzaWFuIG9yIHNjYXR0ZXJ0ZXJuYXJ5IGhhcyBiZWVuIHJlbW92ZWQuIFRoaXMgY29kZSBhc3N1bWVzXG4gICAgICAgIC8vIHRoZSBwYXNzZWQgc2NhdHRlcnRyYWNlcyBoYXZlIGJlZW4gZmlsdGVyZWQgdG8gdGhlIHByb3BlciBwbG90IHR5cGVzIGFuZFxuICAgICAgICAvLyB0aGUgcHJvcGVyIHN1YnBsb3RzLlxuICAgICAgICBpZih0cmFjZS52aXNpYmxlID09PSB0cnVlKSB7XG4gICAgICAgICAgICB0cmFjZS5fbmV4dHRyYWNlID0gbnVsbDtcblxuICAgICAgICAgICAgaWYodHJhY2UuZmlsbCBpbiBMSU5LRURGSUxMUykge1xuICAgICAgICAgICAgICAgIHByZXZ0cmFjZSA9IHByZXZ0cmFjZXNbZ3JvdXBdO1xuICAgICAgICAgICAgICAgIHRyYWNlLl9wcmV2dHJhY2UgPSBwcmV2dHJhY2UgfHwgbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmKHByZXZ0cmFjZSkge1xuICAgICAgICAgICAgICAgICAgICBwcmV2dHJhY2UuX25leHR0cmFjZSA9IHRyYWNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHJhY2UuX293bmZpbGwgPSAodHJhY2UuZmlsbCAmJiAoXG4gICAgICAgICAgICAgICAgdHJhY2UuZmlsbC5zdWJzdHIoMCwgNikgPT09ICd0b3plcm8nIHx8XG4gICAgICAgICAgICAgICAgdHJhY2UuZmlsbCA9PT0gJ3Rvc2VsZicgfHxcbiAgICAgICAgICAgICAgICAodHJhY2UuZmlsbC5zdWJzdHIoMCwgMikgPT09ICd0bycgJiYgIXRyYWNlLl9wcmV2dHJhY2UpXG4gICAgICAgICAgICApKTtcblxuICAgICAgICAgICAgcHJldnRyYWNlc1tncm91cF0gPSB0cmFjZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRyYWNlLl9wcmV2dHJhY2UgPSB0cmFjZS5fbmV4dHRyYWNlID0gdHJhY2UuX293bmZpbGwgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNkc2NhdHRlclNvcnRlZDtcbn07XG5cbn0se31dLDExMjg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xuXG5cbi8vIHVzZWQgaW4gdGhlIGRyYXdpbmcgc3RlcCBmb3IgJ3NjYXR0ZXInIGFuZCAnc2NhdHRlZ2VvJyBhbmRcbi8vIGluIHRoZSBjb252ZXJ0IHN0ZXAgZm9yICdzY2F0dGVyM2QnXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1ha2VCdWJibGVTaXplRm4odHJhY2UpIHtcbiAgICB2YXIgbWFya2VyID0gdHJhY2UubWFya2VyO1xuICAgIHZhciBzaXplUmVmID0gbWFya2VyLnNpemVyZWYgfHwgMTtcbiAgICB2YXIgc2l6ZU1pbiA9IG1hcmtlci5zaXplbWluIHx8IDA7XG5cbiAgICAvLyBmb3IgYnViYmxlIGNoYXJ0cywgYWxsb3cgc2NhbGluZyB0aGUgcHJvdmlkZWQgdmFsdWUgbGluZWFybHlcbiAgICAvLyBhbmQgYnkgYXJlYSBvciBkaWFtZXRlci5cbiAgICAvLyBOb3RlIHRoaXMgb25seSBhcHBsaWVzIHRvIHRoZSBhcnJheS12YWx1ZSBzaXplc1xuXG4gICAgdmFyIGJhc2VGbiA9IChtYXJrZXIuc2l6ZW1vZGUgPT09ICdhcmVhJykgP1xuICAgICAgICBmdW5jdGlvbih2KSB7IHJldHVybiBNYXRoLnNxcnQodiAvIHNpemVSZWYpOyB9IDpcbiAgICAgICAgZnVuY3Rpb24odikgeyByZXR1cm4gdiAvIHNpemVSZWY7IH07XG5cbiAgICAvLyBUT0RPIGFkZCBzdXBwb3J0IGZvciBwb3NpdGlvbi9uZWdhdGl2ZSBidWJibGVzP1xuICAgIC8vIFRPRE8gYWRkICdzaXplb2Zmc2V0JyBhdHRyaWJ1dGU/XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgdmFyIGJhc2VTaXplID0gYmFzZUZuKHYgLyAyKTtcblxuICAgICAgICAvLyBkb24ndCBzaG93IG5vbi1udW1lcmljIGFuZCBuZWdhdGl2ZSBzaXplc1xuICAgICAgICByZXR1cm4gKGlzTnVtZXJpYyhiYXNlU2l6ZSkgJiYgKGJhc2VTaXplID4gMCkpID9cbiAgICAgICAgICAgIE1hdGgubWF4KGJhc2VTaXplLCBzaXplTWluKSA6XG4gICAgICAgICAgICAwO1xuICAgIH07XG59O1xuXG59LHtcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sMTEyOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgY29udGFpbmVyOiAnbWFya2VyJyxcbiAgICBtaW46ICdjbWluJyxcbiAgICBtYXg6ICdjbWF4J1xufTtcblxufSx7fV0sMTEzMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBoYXNDb2xvcnNjYWxlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hlbHBlcnMnKS5oYXNDb2xvcnNjYWxlO1xudmFyIGNvbG9yc2NhbGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9kZWZhdWx0cycpO1xuXG52YXIgc3ViVHlwZXMgPSBfZGVyZXFfKCcuL3N1YnR5cGVzJyk7XG5cbi8qXG4gKiBvcHRzOiBvYmplY3Qgb2YgZmxhZ3MgdG8gY29udHJvbCBmZWF0dXJlcyBub3QgYWxsIG1hcmtlciB1c2VycyBzdXBwb3J0XG4gKiAgIG5vTGluZTogY2FsbGVyIGRvZXMgbm90IHN1cHBvcnQgbWFya2VyIGxpbmVzXG4gKiAgIGdyYWRpZW50OiBjYWxsZXIgc3VwcG9ydHMgZ3JhZGllbnRzXG4gKiAgIG5vU2VsZWN0OiBjYWxsZXIgZG9lcyBub3Qgc3VwcG9ydCBzZWxlY3RlZC91bnNlbGVjdGVkIGF0dHJpYnV0ZSBjb250YWluZXJzXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbWFya2VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UsIG9wdHMpIHtcbiAgICB2YXIgaXNCdWJibGUgPSBzdWJUeXBlcy5pc0J1YmJsZSh0cmFjZUluKTtcbiAgICB2YXIgbGluZUNvbG9yID0gKHRyYWNlSW4ubGluZSB8fCB7fSkuY29sb3I7XG4gICAgdmFyIGRlZmF1bHRNTEM7XG5cbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICAgIC8vIG1hcmtlci5jb2xvciBpbmhlcml0IGZyb20gbGluZS5jb2xvciAoZXZlbiBpZiBsaW5lLmNvbG9yIGlzIGFuIGFycmF5KVxuICAgIGlmKGxpbmVDb2xvcikgZGVmYXVsdENvbG9yID0gbGluZUNvbG9yO1xuXG4gICAgY29lcmNlKCdtYXJrZXIuc3ltYm9sJyk7XG4gICAgY29lcmNlKCdtYXJrZXIub3BhY2l0eScsIGlzQnViYmxlID8gMC43IDogMSk7XG4gICAgY29lcmNlKCdtYXJrZXIuc2l6ZScpO1xuXG4gICAgY29lcmNlKCdtYXJrZXIuY29sb3InLCBkZWZhdWx0Q29sb3IpO1xuICAgIGlmKGhhc0NvbG9yc2NhbGUodHJhY2VJbiwgJ21hcmtlcicpKSB7XG4gICAgICAgIGNvbG9yc2NhbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICdtYXJrZXIuJywgY0xldHRlcjogJ2MnfSk7XG4gICAgfVxuXG4gICAgaWYoIW9wdHMubm9TZWxlY3QpIHtcbiAgICAgICAgY29lcmNlKCdzZWxlY3RlZC5tYXJrZXIuY29sb3InKTtcbiAgICAgICAgY29lcmNlKCd1bnNlbGVjdGVkLm1hcmtlci5jb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ3NlbGVjdGVkLm1hcmtlci5zaXplJyk7XG4gICAgICAgIGNvZXJjZSgndW5zZWxlY3RlZC5tYXJrZXIuc2l6ZScpO1xuICAgIH1cblxuICAgIGlmKCFvcHRzLm5vTGluZSkge1xuICAgICAgICAvLyBpZiB0aGVyZSdzIGEgbGluZSB3aXRoIGEgZGlmZmVyZW50IGNvbG9yIHRoYW4gdGhlIG1hcmtlciwgdXNlXG4gICAgICAgIC8vIHRoYXQgbGluZSBjb2xvciBhcyB0aGUgZGVmYXVsdCBtYXJrZXIgbGluZSBjb2xvclxuICAgICAgICAvLyAoZXhjZXB0IHdoZW4gaXQncyBhbiBhcnJheSlcbiAgICAgICAgLy8gbW9zdGx5IHRoaXMgaXMgZm9yIHRyYW5zcGFyZW50IG1hcmtlcnMgdG8gYmVoYXZlIG5pY2VseVxuICAgICAgICBpZihsaW5lQ29sb3IgJiYgIUFycmF5LmlzQXJyYXkobGluZUNvbG9yKSAmJiAodHJhY2VPdXQubWFya2VyLmNvbG9yICE9PSBsaW5lQ29sb3IpKSB7XG4gICAgICAgICAgICBkZWZhdWx0TUxDID0gbGluZUNvbG9yO1xuICAgICAgICB9IGVsc2UgaWYoaXNCdWJibGUpIGRlZmF1bHRNTEMgPSBDb2xvci5iYWNrZ3JvdW5kO1xuICAgICAgICBlbHNlIGRlZmF1bHRNTEMgPSBDb2xvci5kZWZhdWx0TGluZTtcblxuICAgICAgICBjb2VyY2UoJ21hcmtlci5saW5lLmNvbG9yJywgZGVmYXVsdE1MQyk7XG4gICAgICAgIGlmKGhhc0NvbG9yc2NhbGUodHJhY2VJbiwgJ21hcmtlci5saW5lJykpIHtcbiAgICAgICAgICAgIGNvbG9yc2NhbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtwcmVmaXg6ICdtYXJrZXIubGluZS4nLCBjTGV0dGVyOiAnYyd9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvZXJjZSgnbWFya2VyLmxpbmUud2lkdGgnLCBpc0J1YmJsZSA/IDEgOiAwKTtcbiAgICB9XG5cbiAgICBpZihpc0J1YmJsZSkge1xuICAgICAgICBjb2VyY2UoJ21hcmtlci5zaXplcmVmJyk7XG4gICAgICAgIGNvZXJjZSgnbWFya2VyLnNpemVtaW4nKTtcbiAgICAgICAgY29lcmNlKCdtYXJrZXIuc2l6ZW1vZGUnKTtcbiAgICB9XG5cbiAgICBpZihvcHRzLmdyYWRpZW50KSB7XG4gICAgICAgIHZhciBncmFkaWVudFR5cGUgPSBjb2VyY2UoJ21hcmtlci5ncmFkaWVudC50eXBlJyk7XG4gICAgICAgIGlmKGdyYWRpZW50VHlwZSAhPT0gJ25vbmUnKSB7XG4gICAgICAgICAgICBjb2VyY2UoJ21hcmtlci5ncmFkaWVudC5jb2xvcicpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzXCI6NjAzLFwiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2hlbHBlcnNcIjo2MDQsXCIuL3N1YnR5cGVzXCI6MTEzNX1dLDExMzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgZW5zdXJlU2luZ2xlID0gTGliLmVuc3VyZVNpbmdsZTtcbnZhciBpZGVudGl0eSA9IExpYi5pZGVudGl0eTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG5cbnZhciBzdWJUeXBlcyA9IF9kZXJlcV8oJy4vc3VidHlwZXMnKTtcbnZhciBsaW5lUG9pbnRzID0gX2RlcmVxXygnLi9saW5lX3BvaW50cycpO1xudmFyIGxpbmtUcmFjZXMgPSBfZGVyZXFfKCcuL2xpbmtfdHJhY2VzJyk7XG52YXIgcG9seWdvblRlc3RlciA9IF9kZXJlcV8oJy4uLy4uL2xpYi9wb2x5Z29uJykudGVzdGVyO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHBsb3RpbmZvLCBjZHNjYXR0ZXIsIHNjYXR0ZXJMYXllciwgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICB2YXIgam9pbiwgb25Db21wbGV0ZTtcblxuICAgIC8vIElmIHRyYW5zaXRpb24gY29uZmlnIGlzIHByb3ZpZGVkLCB0aGVuIGl0IGlzIG9ubHkgYSBwYXJ0aWFsIHJlcGxvdCBhbmQgdHJhY2VzIG5vdFxuICAgIC8vIHVwZGF0ZWQgYXJlIHJlbW92ZWQuXG4gICAgdmFyIGlzRnVsbFJlcGxvdCA9ICF0cmFuc2l0aW9uT3B0cztcbiAgICB2YXIgaGFzVHJhbnNpdGlvbiA9ICEhdHJhbnNpdGlvbk9wdHMgJiYgdHJhbnNpdGlvbk9wdHMuZHVyYXRpb24gPiAwO1xuXG4gICAgLy8gTGluayB0cmFjZXMgc28gdGhlIHotb3JkZXIgb2YgZmlsbCBsYXllcnMgaXMgY29ycmVjdFxuICAgIHZhciBjZHNjYXR0ZXJTb3J0ZWQgPSBsaW5rVHJhY2VzKGdkLCBwbG90aW5mbywgY2RzY2F0dGVyKTtcblxuICAgIGpvaW4gPSBzY2F0dGVyTGF5ZXIuc2VsZWN0QWxsKCdnLnRyYWNlJylcbiAgICAgICAgLmRhdGEoY2RzY2F0dGVyU29ydGVkLCBmdW5jdGlvbihkKSB7IHJldHVybiBkWzBdLnRyYWNlLnVpZDsgfSk7XG5cbiAgICAvLyBBcHBlbmQgbmV3IHRyYWNlczpcbiAgICBqb2luLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFjZSBzY2F0dGVyIHRyYWNlJyArIGRbMF0udHJhY2UudWlkO1xuICAgICAgICB9KVxuICAgICAgICAuc3R5bGUoJ3N0cm9rZS1taXRlcmxpbWl0JywgMik7XG4gICAgam9pbi5vcmRlcigpO1xuXG4gICAgY3JlYXRlRmlsbHMoZ2QsIGpvaW4sIHBsb3RpbmZvKTtcblxuICAgIGlmKGhhc1RyYW5zaXRpb24pIHtcbiAgICAgICAgaWYobWFrZU9uQ29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICAgICAgLy8gSWYgaXQgd2FzIHBhc3NlZCBhIGNhbGxiYWNrIHRvIHJlZ2lzdGVyIGNvbXBsZXRpb24sIG1ha2UgYSBjYWxsYmFjay4gSWZcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgY3JlYXRlZCwgdGhlbiBpdCBtdXN0IGJlIGV4ZWN1dGVkIG9uIGNvbXBsZXRpb24sIG90aGVyd2lzZSB0aGVcbiAgICAgICAgICAgIC8vIHBvcy10cmFuc2l0aW9uIHJlZHJhdyB3aWxsIG5vdCBleGVjdXRlOlxuICAgICAgICAgICAgb25Db21wbGV0ZSA9IG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2soKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0cmFuc2l0aW9uID0gZDMudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAuZHVyYXRpb24odHJhbnNpdGlvbk9wdHMuZHVyYXRpb24pXG4gICAgICAgICAgICAuZWFzZSh0cmFuc2l0aW9uT3B0cy5lYXNpbmcpXG4gICAgICAgICAgICAuZWFjaCgnZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgb25Db21wbGV0ZSAmJiBvbkNvbXBsZXRlKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmVhY2goJ2ludGVycnVwdCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIG9uQ29tcGxldGUgJiYgb25Db21wbGV0ZSgpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgdHJhbnNpdGlvbi5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgLy8gTXVzdCBydW4gdGhlIHNlbGVjdGlvbiBhZ2FpbiBzaW5jZSBvdGhlcndpc2UgZW50ZXJzL3VwZGF0ZXMgZ2V0IGdyb3VwZWQgdG9nZXRoZXJcbiAgICAgICAgICAgIC8vIGFuZCB0aGVzZSBnZXQgZXhlY3V0ZWQgb3V0IG9mIG9yZGVyLiBFeGNlcHQgd2UgbmVlZCB0aGVtIGluIG9yZGVyIVxuICAgICAgICAgICAgc2NhdHRlckxheWVyLnNlbGVjdEFsbCgnZy50cmFjZScpLmVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgICAgIHBsb3RPbmUoZ2QsIGksIHBsb3RpbmZvLCBkLCBjZHNjYXR0ZXJTb3J0ZWQsIHRoaXMsIHRyYW5zaXRpb25PcHRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBqb2luLmVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICAgICAgcGxvdE9uZShnZCwgaSwgcGxvdGluZm8sIGQsIGNkc2NhdHRlclNvcnRlZCwgdGhpcywgdHJhbnNpdGlvbk9wdHMpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihpc0Z1bGxSZXBsb3QpIHtcbiAgICAgICAgam9pbi5leGl0KCkucmVtb3ZlKCk7XG4gICAgfVxuXG4gICAgLy8gcmVtb3ZlIHBhdGhzIHRoYXQgZGlkbid0IGdldCB1c2VkXG4gICAgc2NhdHRlckxheWVyLnNlbGVjdEFsbCgncGF0aDpub3QoW2RdKScpLnJlbW92ZSgpO1xufTtcblxuZnVuY3Rpb24gY3JlYXRlRmlsbHMoZ2QsIHRyYWNlSm9pbiwgcGxvdGluZm8pIHtcbiAgICB0cmFjZUpvaW4uZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBmaWxscyA9IGVuc3VyZVNpbmdsZShkMy5zZWxlY3QodGhpcyksICdnJywgJ2ZpbGxzJyk7XG4gICAgICAgIERyYXdpbmcuc2V0Q2xpcFVybChmaWxscywgcGxvdGluZm8ubGF5ZXJDbGlwSWQsIGdkKTtcblxuICAgICAgICB2YXIgdHJhY2UgPSBkWzBdLnRyYWNlO1xuXG4gICAgICAgIHZhciBmaWxsRGF0YSA9IFtdO1xuICAgICAgICBpZih0cmFjZS5fb3duZmlsbCkgZmlsbERhdGEucHVzaCgnX293bkZpbGwnKTtcbiAgICAgICAgaWYodHJhY2UuX25leHR0cmFjZSkgZmlsbERhdGEucHVzaCgnX25leHRGaWxsJyk7XG5cbiAgICAgICAgdmFyIGZpbGxKb2luID0gZmlsbHMuc2VsZWN0QWxsKCdnJykuZGF0YShmaWxsRGF0YSwgaWRlbnRpdHkpO1xuXG4gICAgICAgIGZpbGxKb2luLmVudGVyKCkuYXBwZW5kKCdnJyk7XG5cbiAgICAgICAgZmlsbEpvaW4uZXhpdCgpXG4gICAgICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7IHRyYWNlW2RdID0gbnVsbDsgfSlcbiAgICAgICAgICAgIC5yZW1vdmUoKTtcblxuICAgICAgICBmaWxsSm9pbi5vcmRlcigpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgLy8gbWFrZSBhIHBhdGggZWxlbWVudCBpbnNpZGUgdGhlIGZpbGwgZ3JvdXAsIGp1c3Qgc29cbiAgICAgICAgICAgIC8vIHdlIGNhbiBnaXZlIGl0IGl0cyBvd24gZGF0YSBsYXRlciBvbiBhbmQgdGhlIGdyb3VwIGNhblxuICAgICAgICAgICAgLy8ga2VlcCBpdHMgc2ltcGxlICdfKkZpbGwnIGRhdGFcbiAgICAgICAgICAgIHRyYWNlW2RdID0gZW5zdXJlU2luZ2xlKGQzLnNlbGVjdCh0aGlzKSwgJ3BhdGgnLCAnanMtZmlsbCcpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gcGxvdE9uZShnZCwgaWR4LCBwbG90aW5mbywgY2RzY2F0dGVyLCBjZHNjYXR0ZXJBbGwsIGVsZW1lbnQsIHRyYW5zaXRpb25PcHRzKSB7XG4gICAgdmFyIGk7XG5cbiAgICAvLyBTaW5jZSB0aGlzIGhhcyBiZWVuIHJlb3JnYW5pemVkIGFuZCB3ZSdyZSBleGVjdXRpbmcgdGhpcyBvbiBpbmRpdmlkdWFsIHRyYWNlcyxcbiAgICAvLyB3ZSBuZWVkIHRvIHBhc3MgaXQgdGhlIGZ1bGwgbGlzdCBvZiBjZHNjYXR0ZXIgYXMgd2VsbCBhcyB0aGlzIHRyYWNlJ3MgaW5kZXggKGlkeClcbiAgICAvLyBzaW5jZSBpdCBkb2VzIGFuIGludGVybmFsIG5eMiBsb29wIG92ZXIgY29tcGFyaXNvbnMgd2l0aCBvdGhlciB0cmFjZXM6XG4gICAgc2VsZWN0TWFya2VycyhnZCwgaWR4LCBwbG90aW5mbywgY2RzY2F0dGVyLCBjZHNjYXR0ZXJBbGwpO1xuXG4gICAgdmFyIGhhc1RyYW5zaXRpb24gPSAhIXRyYW5zaXRpb25PcHRzICYmIHRyYW5zaXRpb25PcHRzLmR1cmF0aW9uID4gMDtcblxuICAgIGZ1bmN0aW9uIHRyYW5zaXRpb24oc2VsZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBoYXNUcmFuc2l0aW9uID8gc2VsZWN0aW9uLnRyYW5zaXRpb24oKSA6IHNlbGVjdGlvbjtcbiAgICB9XG5cbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIHZhciB0cmFjZSA9IGNkc2NhdHRlclswXS50cmFjZTtcbiAgICB2YXIgbGluZSA9IHRyYWNlLmxpbmU7XG4gICAgdmFyIHRyID0gZDMuc2VsZWN0KGVsZW1lbnQpO1xuXG4gICAgdmFyIGVycm9yQmFyR3JvdXAgPSBlbnN1cmVTaW5nbGUodHIsICdnJywgJ2Vycm9yYmFycycpO1xuICAgIHZhciBsaW5lcyA9IGVuc3VyZVNpbmdsZSh0ciwgJ2cnLCAnbGluZXMnKTtcbiAgICB2YXIgcG9pbnRzID0gZW5zdXJlU2luZ2xlKHRyLCAnZycsICdwb2ludHMnKTtcbiAgICB2YXIgdGV4dCA9IGVuc3VyZVNpbmdsZSh0ciwgJ2cnLCAndGV4dCcpO1xuXG4gICAgLy8gZXJyb3IgYmFycyBhcmUgYXQgdGhlIGJvdHRvbVxuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZXJyb3JiYXJzJywgJ3Bsb3QnKShnZCwgZXJyb3JCYXJHcm91cCwgcGxvdGluZm8sIHRyYW5zaXRpb25PcHRzKTtcblxuICAgIGlmKHRyYWNlLnZpc2libGUgIT09IHRydWUpIHJldHVybjtcblxuICAgIHRyYW5zaXRpb24odHIpLnN0eWxlKCdvcGFjaXR5JywgdHJhY2Uub3BhY2l0eSk7XG5cbiAgICAvLyBCVUlMRCBMSU5FUyBBTkQgRklMTFNcbiAgICB2YXIgb3duRmlsbEVsMywgdG9uZXh0O1xuICAgIHZhciBvd25GaWxsRGlyID0gdHJhY2UuZmlsbC5jaGFyQXQodHJhY2UuZmlsbC5sZW5ndGggLSAxKTtcbiAgICBpZihvd25GaWxsRGlyICE9PSAneCcgJiYgb3duRmlsbERpciAhPT0gJ3knKSBvd25GaWxsRGlyID0gJyc7XG5cbiAgICAvLyBzdG9yZSBub2RlIGZvciB0d2Vha2luZyBieSBzZWxlY3RQb2ludHNcbiAgICBjZHNjYXR0ZXJbMF1bcGxvdGluZm8uaXNSYW5nZVBsb3QgPyAnbm9kZVJhbmdlUGxvdDMnIDogJ25vZGUzJ10gPSB0cjtcblxuICAgIHZhciBwcmV2UmV2cGF0aCA9ICcnO1xuICAgIHZhciBwcmV2UG9seWdvbnMgPSBbXTtcbiAgICB2YXIgcHJldnRyYWNlID0gdHJhY2UuX3ByZXZ0cmFjZTtcblxuICAgIGlmKHByZXZ0cmFjZSkge1xuICAgICAgICBwcmV2UmV2cGF0aCA9IHByZXZ0cmFjZS5fcHJldlJldnBhdGggfHwgJyc7XG4gICAgICAgIHRvbmV4dCA9IHByZXZ0cmFjZS5fbmV4dEZpbGw7XG4gICAgICAgIHByZXZQb2x5Z29ucyA9IHByZXZ0cmFjZS5fcG9seWdvbnM7XG4gICAgfVxuXG4gICAgdmFyIHRoaXNwYXRoO1xuICAgIHZhciB0aGlzcmV2cGF0aDtcbiAgICAvLyBmdWxscGF0aCBpcyBhbGwgcGF0aHMgZm9yIHRoaXMgY3VydmUsIGpvaW5lZCB0b2dldGhlciBzdHJhaWdodFxuICAgIC8vIGFjcm9zcyBnYXBzLCBmb3IgZmlsbGluZ1xuICAgIHZhciBmdWxscGF0aCA9ICcnO1xuICAgIC8vIHJldnBhdGggaXMgZnVsbHBhdGggcmV2ZXJzZWQsIGZvciBmaWxsLXRvLW5leHRcbiAgICB2YXIgcmV2cGF0aCA9ICcnO1xuICAgIC8vIGZ1bmN0aW9ucyBmb3IgY29udmVydGluZyBhIHBvaW50IGFycmF5IHRvIGEgcGF0aFxuICAgIHZhciBwYXRoZm4sIHJldnBhdGhiYXNlLCByZXZwYXRoZm47XG4gICAgLy8gdmFyaWFibGVzIHVzZWQgYmVmb3JlIGFuZCBhZnRlciB0aGUgZGF0YSBqb2luXG4gICAgdmFyIHB0MCwgbGFzdFNlZ21lbnQsIHB0MSwgdGhpc1BvbHlnb25zO1xuXG4gICAgLy8gaW5pdGlhbGl6ZSBsaW5lIGpvaW4gZGF0YSAvIG1ldGhvZFxuICAgIHZhciBzZWdtZW50cyA9IFtdO1xuICAgIHZhciBtYWtlVXBkYXRlID0gTGliLm5vb3A7XG5cbiAgICBvd25GaWxsRWwzID0gdHJhY2UuX293bkZpbGw7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZSkgfHwgdHJhY2UuZmlsbCAhPT0gJ25vbmUnKSB7XG4gICAgICAgIGlmKHRvbmV4dCkge1xuICAgICAgICAgICAgLy8gVGhpcyB0ZWxscyAuc3R5bGUgd2hpY2ggdHJhY2UgdG8gdXNlIGZvciBmaWxsIGluZm9ybWF0aW9uOlxuICAgICAgICAgICAgdG9uZXh0LmRhdHVtKGNkc2NhdHRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZihbJ2h2JywgJ3ZoJywgJ2h2aCcsICd2aHYnXS5pbmRleE9mKGxpbmUuc2hhcGUpICE9PSAtMSkge1xuICAgICAgICAgICAgcGF0aGZuID0gRHJhd2luZy5zdGVwcyhsaW5lLnNoYXBlKTtcbiAgICAgICAgICAgIHJldnBhdGhiYXNlID0gRHJhd2luZy5zdGVwcyhcbiAgICAgICAgICAgICAgICBsaW5lLnNoYXBlLnNwbGl0KCcnKS5yZXZlcnNlKCkuam9pbignJylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZihsaW5lLnNoYXBlID09PSAnc3BsaW5lJykge1xuICAgICAgICAgICAgcGF0aGZuID0gcmV2cGF0aGJhc2UgPSBmdW5jdGlvbihwdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcExhc3QgPSBwdHNbcHRzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgICAgIGlmKHB0cy5sZW5ndGggPiAxICYmIHB0c1swXVswXSA9PT0gcExhc3RbMF0gJiYgcHRzWzBdWzFdID09PSBwTGFzdFsxXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZGVudGljYWwgc3RhcnQgYW5kIGVuZCBwb2ludHM6IHRyZWF0IGl0IGFzIGFcbiAgICAgICAgICAgICAgICAgICAgLy8gY2xvc2VkIGN1cnZlIHNvIHdlIGRvbid0IGdldCBhIGtpbmtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIERyYXdpbmcuc21vb3RoY2xvc2VkKHB0cy5zbGljZSgxKSwgbGluZS5zbW9vdGhpbmcpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBEcmF3aW5nLnNtb290aG9wZW4ocHRzLCBsaW5lLnNtb290aGluZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBhdGhmbiA9IHJldnBhdGhiYXNlID0gZnVuY3Rpb24ocHRzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdNJyArIHB0cy5qb2luKCdMJyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV2cGF0aGZuID0gZnVuY3Rpb24ocHRzKSB7XG4gICAgICAgICAgICAvLyBub3RlOiB0aGlzIGlzIGRlc3RydWN0aXZlIChyZXZlcnNlcyBwdHMgaW4gcGxhY2UpIHNvIGNhbid0IHVzZSBwdHMgYWZ0ZXIgdGhpc1xuICAgICAgICAgICAgcmV0dXJuIHJldnBhdGhiYXNlKHB0cy5yZXZlcnNlKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNlZ21lbnRzID0gbGluZVBvaW50cyhjZHNjYXR0ZXIsIHtcbiAgICAgICAgICAgIHhheGlzOiB4YSxcbiAgICAgICAgICAgIHlheGlzOiB5YSxcbiAgICAgICAgICAgIGNvbm5lY3RHYXBzOiB0cmFjZS5jb25uZWN0Z2FwcyxcbiAgICAgICAgICAgIGJhc2VUb2xlcmFuY2U6IE1hdGgubWF4KGxpbmUud2lkdGggfHwgMSwgMykgLyA0LFxuICAgICAgICAgICAgc2hhcGU6IGxpbmUuc2hhcGUsXG4gICAgICAgICAgICBzaW1wbGlmeTogbGluZS5zaW1wbGlmeSxcbiAgICAgICAgICAgIGZpbGw6IHRyYWNlLmZpbGxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gc2luY2Ugd2UgYWxyZWFkeSBoYXZlIHRoZSBwaXhlbCBzZWdtZW50cyBoZXJlLCB1c2UgdGhlbSB0byBtYWtlXG4gICAgICAgIC8vIHBvbHlnb25zIGZvciBob3ZlciBvbiBmaWxsXG4gICAgICAgIC8vIFRPRE86IGNhbiB3ZSBza2lwIHRoaXMgaWYgaG92ZXJvbiE9ZmlsbHM/IFRoYXQgd291bGQgbWVhbiB3ZVxuICAgICAgICAvLyBuZWVkIHRvIHJlZHJhdyB3aGVuIHlvdSBjaGFuZ2UgaG92ZXJvbi4uLlxuICAgICAgICB0aGlzUG9seWdvbnMgPSB0cmFjZS5fcG9seWdvbnMgPSBuZXcgQXJyYXkoc2VnbWVudHMubGVuZ3RoKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgc2VnbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRyYWNlLl9wb2x5Z29uc1tpXSA9IHBvbHlnb25UZXN0ZXIoc2VnbWVudHNbaV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoc2VnbWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBwdDAgPSBzZWdtZW50c1swXVswXTtcbiAgICAgICAgICAgIGxhc3RTZWdtZW50ID0gc2VnbWVudHNbc2VnbWVudHMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICBwdDEgPSBsYXN0U2VnbWVudFtsYXN0U2VnbWVudC5sZW5ndGggLSAxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIG1ha2VVcGRhdGUgPSBmdW5jdGlvbihpc0VudGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24ocHRzKSB7XG4gICAgICAgICAgICAgICAgdGhpc3BhdGggPSBwYXRoZm4ocHRzKTtcbiAgICAgICAgICAgICAgICB0aGlzcmV2cGF0aCA9IHJldnBhdGhmbihwdHMpO1xuICAgICAgICAgICAgICAgIGlmKCFmdWxscGF0aCkge1xuICAgICAgICAgICAgICAgICAgICBmdWxscGF0aCA9IHRoaXNwYXRoO1xuICAgICAgICAgICAgICAgICAgICByZXZwYXRoID0gdGhpc3JldnBhdGg7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKG93bkZpbGxEaXIpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVsbHBhdGggKz0gJ0wnICsgdGhpc3BhdGguc3Vic3RyKDEpO1xuICAgICAgICAgICAgICAgICAgICByZXZwYXRoID0gdGhpc3JldnBhdGggKyAoJ0wnICsgcmV2cGF0aC5zdWJzdHIoMSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bGxwYXRoICs9ICdaJyArIHRoaXNwYXRoO1xuICAgICAgICAgICAgICAgICAgICByZXZwYXRoID0gdGhpc3JldnBhdGggKyAnWicgKyByZXZwYXRoO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmKHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlKSAmJiBwdHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZWwgPSBkMy5zZWxlY3QodGhpcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBtYWtlcyB0aGUgY29sb3Jpbmcgd29yayBjb3JyZWN0bHk6XG4gICAgICAgICAgICAgICAgICAgIGVsLmRhdHVtKGNkc2NhdHRlcik7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYoaXNFbnRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbihlbC5zdHlsZSgnb3BhY2l0eScsIDApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ2QnLCB0aGlzcGF0aClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmxpbmVHcm91cFN0eWxlKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2VsID0gdHJhbnNpdGlvbihlbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWwuYXR0cignZCcsIHRoaXNwYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIERyYXdpbmcuc2luZ2xlTGluZVN0eWxlKGNkc2NhdHRlciwgc2VsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGxpbmVKb2luID0gbGluZXMuc2VsZWN0QWxsKCcuanMtbGluZScpLmRhdGEoc2VnbWVudHMpO1xuXG4gICAgdHJhbnNpdGlvbihsaW5lSm9pbi5leGl0KCkpXG4gICAgICAgIC5zdHlsZSgnb3BhY2l0eScsIDApXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIGxpbmVKb2luLmVhY2gobWFrZVVwZGF0ZShmYWxzZSkpO1xuXG4gICAgbGluZUpvaW4uZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAuY2xhc3NlZCgnanMtbGluZScsIHRydWUpXG4gICAgICAgIC5zdHlsZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKVxuICAgICAgICAuY2FsbChEcmF3aW5nLmxpbmVHcm91cFN0eWxlKVxuICAgICAgICAuZWFjaChtYWtlVXBkYXRlKHRydWUpKTtcblxuICAgIERyYXdpbmcuc2V0Q2xpcFVybChsaW5lSm9pbiwgcGxvdGluZm8ubGF5ZXJDbGlwSWQsIGdkKTtcblxuICAgIGZ1bmN0aW9uIGNsZWFyRmlsbChzZWxlY3Rpb24pIHtcbiAgICAgICAgdHJhbnNpdGlvbihzZWxlY3Rpb24pLmF0dHIoJ2QnLCAnTTAsMFonKTtcbiAgICB9XG5cbiAgICBpZihzZWdtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgaWYob3duRmlsbEVsMykge1xuICAgICAgICAgICAgb3duRmlsbEVsMy5kYXR1bShjZHNjYXR0ZXIpO1xuICAgICAgICAgICAgaWYocHQwICYmIHB0MSkge1xuICAgICAgICAgICAgICAgIGlmKG93bkZpbGxEaXIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYob3duRmlsbERpciA9PT0gJ3knKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdDBbMV0gPSBwdDFbMV0gPSB5YS5jMnAoMCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZihvd25GaWxsRGlyID09PSAneCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB0MFswXSA9IHB0MVswXSA9IHhhLmMycCgwLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIGZpbGwgdG8gemVybzogZnVsbCB0cmFjZSBwYXRoLCBwbHVzIGV4dGVuc2lvbiBvZlxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZW5kcG9pbnRzIHRvIHRoZSBhcHByb3ByaWF0ZSBheGlzXG4gICAgICAgICAgICAgICAgICAgIC8vIEZvciB0aGUgc2FrZSBvZiBhbmltYXRpb25zLCB3cmFwIHRoZSBwb2ludHMgYXJvdW5kIHNvIHRoYXRcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHBvaW50cyBvbiB0aGUgYXhlcyBhcmUgdGhlIGZpcnN0IHR3byBwb2ludHMuIE90aGVyd2lzZVxuICAgICAgICAgICAgICAgICAgICAvLyBhbmltYXRpb25zIGdldCBhIGxpdHRsZSBjcmF6eSBpZiB0aGUgbnVtYmVyIG9mIHBvaW50cyBjaGFuZ2VzLlxuICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9uKG93bkZpbGxFbDMpLmF0dHIoJ2QnLCAnTScgKyBwdDEgKyAnTCcgKyBwdDAgKyAnTCcgKyBmdWxscGF0aC5zdWJzdHIoMSkpXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNpbmdsZUZpbGxTdHlsZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gZmlsbCB0byBzZWxmOiBqdXN0IGpvaW4gdGhlIHBhdGggdG8gaXRzZWxmXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb24ob3duRmlsbEVsMykuYXR0cignZCcsIGZ1bGxwYXRoICsgJ1onKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zaW5nbGVGaWxsU3R5bGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmKHRvbmV4dCkge1xuICAgICAgICAgICAgaWYodHJhY2UuZmlsbC5zdWJzdHIoMCwgNikgPT09ICd0b25leHQnICYmIGZ1bGxwYXRoICYmIHByZXZSZXZwYXRoKSB7XG4gICAgICAgICAgICAgICAgLy8gZmlsbCB0byBuZXh0OiBmdWxsIHRyYWNlIHBhdGgsIHBsdXMgdGhlIHByZXZpb3VzIHBhdGggcmV2ZXJzZWRcbiAgICAgICAgICAgICAgICBpZih0cmFjZS5maWxsID09PSAndG9uZXh0Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyB0b25leHQ6IGZvciB1c2UgYnkgY29uY2VudHJpYyBzaGFwZXMsIGxpa2UgbWFudWFsbHkgY29uc3RydWN0ZWRcbiAgICAgICAgICAgICAgICAgICAgLy8gY29udG91cnMsIHdlIGp1c3QgYWRkIHRoZSB0d28gcGF0aHMgY2xvc2VkIG9uIHRoZW1zZWx2ZXMuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgbWFrZXMgc3RyYW5nZSByZXN1bHRzIGlmIG9uZSBwYXRoIGlzICpub3QqIGVudGlyZWx5XG4gICAgICAgICAgICAgICAgICAgIC8vIGluc2lkZSB0aGUgb3RoZXIsIGJ1dCB0aGVuIHRoYXQgaXMgYSBzdHJhbmdlIHVzYWdlLlxuICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9uKHRvbmV4dCkuYXR0cignZCcsIGZ1bGxwYXRoICsgJ1onICsgcHJldlJldnBhdGggKyAnWicpXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNpbmdsZUZpbGxTdHlsZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdG9uZXh0eC95OiBmb3Igbm93IGp1c3QgY29ubmVjdCBlbmRwb2ludHMgd2l0aCBsaW5lcy4gVGhpcyBpc1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgY29ycmVjdCBiZWhhdmlvciBpZiB0aGUgZW5kcG9pbnRzIGFyZSBhdCB0aGUgc2FtZSB2YWx1ZSBvZlxuICAgICAgICAgICAgICAgICAgICAvLyB5L3gsIGJ1dCBpZiB0aGV5ICphcmVuJ3QqLCB3ZSBzaG91bGQgaWRlYWxseSBkbyBtb3JlIGNvbXBsaWNhdGVkXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaW5ncyBkZXBlbmRpbmcgb24gd2hldGhlciB0aGUgbmV3IGVuZHBvaW50IHByb2plY3RzIG9udG8gdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vIGV4aXN0aW5nIGN1cnZlIG9yIG9mZiB0aGUgZW5kIG9mIGl0XG4gICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb24odG9uZXh0KS5hdHRyKCdkJywgZnVsbHBhdGggKyAnTCcgKyBwcmV2UmV2cGF0aC5zdWJzdHIoMSkgKyAnWicpXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLnNpbmdsZUZpbGxTdHlsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRyYWNlLl9wb2x5Z29ucyA9IHRyYWNlLl9wb2x5Z29ucy5jb25jYXQocHJldlBvbHlnb25zKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2xlYXJGaWxsKHRvbmV4dCk7XG4gICAgICAgICAgICAgICAgdHJhY2UuX3BvbHlnb25zID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0cmFjZS5fcHJldlJldnBhdGggPSByZXZwYXRoO1xuICAgICAgICB0cmFjZS5fcHJldlBvbHlnb25zID0gdGhpc1BvbHlnb25zO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKG93bkZpbGxFbDMpIGNsZWFyRmlsbChvd25GaWxsRWwzKTtcbiAgICAgICAgZWxzZSBpZih0b25leHQpIGNsZWFyRmlsbCh0b25leHQpO1xuICAgICAgICB0cmFjZS5fcG9seWdvbnMgPSB0cmFjZS5fcHJldlJldnBhdGggPSB0cmFjZS5fcHJldlBvbHlnb25zID0gbnVsbDtcbiAgICB9XG5cblxuICAgIGZ1bmN0aW9uIHZpc0ZpbHRlcihkKSB7XG4gICAgICAgIHJldHVybiBkLmZpbHRlcihmdW5jdGlvbih2KSB7IHJldHVybiAhdi5nYXAgJiYgdi52aXM7IH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHZpc0ZpbHRlcldpdGhHYXBzKGQpIHtcbiAgICAgICAgcmV0dXJuIGQuZmlsdGVyKGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHYudmlzOyB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnYXBGaWx0ZXIoZCkge1xuICAgICAgICByZXR1cm4gZC5maWx0ZXIoZnVuY3Rpb24odikgeyByZXR1cm4gIXYuZ2FwOyB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBrZXlGdW5jKGQpIHtcbiAgICAgICAgcmV0dXJuIGQuaWQ7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIGlmIHRoZSB0cmFjZSBpcyBrZXllZCwgb3RoZXJ3aXNlIHJldHVybnMgdW5kZWZpbmVkXG4gICAgZnVuY3Rpb24gZ2V0S2V5RnVuYyh0cmFjZSkge1xuICAgICAgICBpZih0cmFjZS5pZHMpIHtcbiAgICAgICAgICAgIHJldHVybiBrZXlGdW5jO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGlkZUZpbHRlcigpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VQb2ludHMocG9pbnRzLCB0ZXh0LCBjZHNjYXR0ZXIpIHtcbiAgICAgICAgdmFyIGpvaW4sIHNlbGVjdGlvbiwgaGFzTm9kZTtcblxuICAgICAgICB2YXIgdHJhY2UgPSBjZHNjYXR0ZXJbMF0udHJhY2U7XG4gICAgICAgIHZhciBzaG93TWFya2VycyA9IHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpO1xuICAgICAgICB2YXIgc2hvd1RleHQgPSBzdWJUeXBlcy5oYXNUZXh0KHRyYWNlKTtcblxuICAgICAgICB2YXIga2V5RnVuYyA9IGdldEtleUZ1bmModHJhY2UpO1xuICAgICAgICB2YXIgbWFya2VyRmlsdGVyID0gaGlkZUZpbHRlcjtcbiAgICAgICAgdmFyIHRleHRGaWx0ZXIgPSBoaWRlRmlsdGVyO1xuXG4gICAgICAgIGlmKHNob3dNYXJrZXJzIHx8IHNob3dUZXh0KSB7XG4gICAgICAgICAgICB2YXIgc2hvd0ZpbHRlciA9IGlkZW50aXR5O1xuICAgICAgICAgICAgLy8gaWYgd2UncmUgc3RhY2tpbmcsIFwiaW5mZXIgemVyb1wiIGdhcCBtb2RlIGdldHMgbWFya2VycyBpbiB0aGVcbiAgICAgICAgICAgIC8vIGdhcCBwb2ludHMgLSBiZWNhdXNlIHdlJ3ZlIGluZmVycmVkIGEgemVybyB0aGVyZSAtIGJ1dCBvdGhlclxuICAgICAgICAgICAgLy8gbW9kZXMgKGN1cnJlbnRseSBcImludGVycG9sYXRlXCIsIGxhdGVyIFwiaW50ZXJydXB0XCIgaG9wZWZ1bGx5KVxuICAgICAgICAgICAgLy8gd2UgZG9uJ3QgZHJhdyBnZW5lcmF0ZWQgbWFya2Vyc1xuICAgICAgICAgICAgdmFyIHN0YWNrR3JvdXAgPSB0cmFjZS5zdGFja2dyb3VwO1xuICAgICAgICAgICAgdmFyIGlzSW5mZXJaZXJvID0gc3RhY2tHcm91cCAmJiAoXG4gICAgICAgICAgICAgICAgZ2QuX2Z1bGxMYXlvdXQuX3NjYXR0ZXJTdGFja09wdHNbeGEuX2lkICsgeWEuX2lkXVtzdGFja0dyb3VwXS5zdGFja2dhcHMgPT09ICdpbmZlciB6ZXJvJyk7XG4gICAgICAgICAgICBpZih0cmFjZS5tYXJrZXIubWF4ZGlzcGxheWVkIHx8IHRyYWNlLl9uZWVkc0N1bGwpIHtcbiAgICAgICAgICAgICAgICBzaG93RmlsdGVyID0gaXNJbmZlclplcm8gPyB2aXNGaWx0ZXJXaXRoR2FwcyA6IHZpc0ZpbHRlcjtcbiAgICAgICAgICAgIH0gZWxzZSBpZihzdGFja0dyb3VwICYmICFpc0luZmVyWmVybykge1xuICAgICAgICAgICAgICAgIHNob3dGaWx0ZXIgPSBnYXBGaWx0ZXI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHNob3dNYXJrZXJzKSBtYXJrZXJGaWx0ZXIgPSBzaG93RmlsdGVyO1xuICAgICAgICAgICAgaWYoc2hvd1RleHQpIHRleHRGaWx0ZXIgPSBzaG93RmlsdGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbWFya2VyIHBvaW50c1xuXG4gICAgICAgIHNlbGVjdGlvbiA9IHBvaW50cy5zZWxlY3RBbGwoJ3BhdGgucG9pbnQnKTtcblxuICAgICAgICBqb2luID0gc2VsZWN0aW9uLmRhdGEobWFya2VyRmlsdGVyLCBrZXlGdW5jKTtcblxuICAgICAgICB2YXIgZW50ZXIgPSBqb2luLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgIC5jbGFzc2VkKCdwb2ludCcsIHRydWUpO1xuXG4gICAgICAgIGlmKGhhc1RyYW5zaXRpb24pIHtcbiAgICAgICAgICAgIGVudGVyXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5wb2ludFN0eWxlLCB0cmFjZSwgZ2QpXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy50cmFuc2xhdGVQb2ludHMsIHhhLCB5YSlcbiAgICAgICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAwKVxuICAgICAgICAgICAgICAgIC50cmFuc2l0aW9uKClcbiAgICAgICAgICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGpvaW4ub3JkZXIoKTtcblxuICAgICAgICB2YXIgc3R5bGVGbnM7XG4gICAgICAgIGlmKHNob3dNYXJrZXJzKSB7XG4gICAgICAgICAgICBzdHlsZUZucyA9IERyYXdpbmcubWFrZVBvaW50U3R5bGVGbnModHJhY2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgam9pbi5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBlbCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBzZWwgPSB0cmFuc2l0aW9uKGVsKTtcbiAgICAgICAgICAgIGhhc05vZGUgPSBEcmF3aW5nLnRyYW5zbGF0ZVBvaW50KGQsIHNlbCwgeGEsIHlhKTtcblxuICAgICAgICAgICAgaWYoaGFzTm9kZSkge1xuICAgICAgICAgICAgICAgIERyYXdpbmcuc2luZ2xlUG9pbnRTdHlsZShkLCBzZWwsIHRyYWNlLCBzdHlsZUZucywgZ2QpO1xuXG4gICAgICAgICAgICAgICAgaWYocGxvdGluZm8ubGF5ZXJDbGlwSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgRHJhd2luZy5oaWRlT3V0c2lkZVJhbmdlUG9pbnQoZCwgc2VsLCB4YSwgeWEsIHRyYWNlLnhjYWxlbmRhciwgdHJhY2UueWNhbGVuZGFyKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZih0cmFjZS5jdXN0b21kYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsLmNsYXNzZWQoJ3Bsb3RseS1jdXN0b21kYXRhJywgZC5kYXRhICE9PSBudWxsICYmIGQuZGF0YSAhPT0gdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbC5yZW1vdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYoaGFzVHJhbnNpdGlvbikge1xuICAgICAgICAgICAgam9pbi5leGl0KCkudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMClcbiAgICAgICAgICAgICAgICAucmVtb3ZlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBqb2luLmV4aXQoKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRleHQgcG9pbnRzXG4gICAgICAgIHNlbGVjdGlvbiA9IHRleHQuc2VsZWN0QWxsKCdnJyk7XG4gICAgICAgIGpvaW4gPSBzZWxlY3Rpb24uZGF0YSh0ZXh0RmlsdGVyLCBrZXlGdW5jKTtcblxuICAgICAgICAvLyBlYWNoIHRleHQgbmVlZHMgdG8gZ28gaW4gaXRzIG93biAnZycgaW4gY2FzZVxuICAgICAgICAvLyBpdCBnZXRzIGNvbnZlcnRlZCB0byBtYXRoamF4XG4gICAgICAgIGpvaW4uZW50ZXIoKS5hcHBlbmQoJ2cnKS5jbGFzc2VkKCd0ZXh0cG9pbnQnLCB0cnVlKS5hcHBlbmQoJ3RleHQnKTtcblxuICAgICAgICBqb2luLm9yZGVyKCk7XG5cbiAgICAgICAgam9pbi5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBnID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIHNlbCA9IHRyYW5zaXRpb24oZy5zZWxlY3QoJ3RleHQnKSk7XG4gICAgICAgICAgICBoYXNOb2RlID0gRHJhd2luZy50cmFuc2xhdGVQb2ludChkLCBzZWwsIHhhLCB5YSk7XG5cbiAgICAgICAgICAgIGlmKGhhc05vZGUpIHtcbiAgICAgICAgICAgICAgICBpZihwbG90aW5mby5sYXllckNsaXBJZCkge1xuICAgICAgICAgICAgICAgICAgICBEcmF3aW5nLmhpZGVPdXRzaWRlUmFuZ2VQb2ludChkLCBnLCB4YSwgeWEsIHRyYWNlLnhjYWxlbmRhciwgdHJhY2UueWNhbGVuZGFyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGcucmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGpvaW4uc2VsZWN0QWxsKCd0ZXh0JylcbiAgICAgICAgICAgIC5jYWxsKERyYXdpbmcudGV4dFBvaW50U3R5bGUsIHRyYWNlLCBnZClcbiAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGp1c3QgKmhhcyogdG8gYmUgdG90YWxseSBjdXN0b20gYmVjdWFzZSBvZiBTVkcgdGV4dCBwb3NpdGlvbmluZyA6KFxuICAgICAgICAgICAgICAgIC8vIEl0J3Mgb2J2aW91c2x5IGNvcGllZCBmcm9tIHRyYW5zbGF0ZVBvaW50OyB3ZSBqdXN0IGNhbid0IHVzZSB0aGF0XG4gICAgICAgICAgICAgICAgdmFyIHggPSB4YS5jMnAoZC54KTtcbiAgICAgICAgICAgICAgICB2YXIgeSA9IHlhLmMycChkLnkpO1xuXG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KHRoaXMpLnNlbGVjdEFsbCgndHNwYW4ubGluZScpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb24oZDMuc2VsZWN0KHRoaXMpKS5hdHRyKHt4OiB4LCB5OiB5fSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBqb2luLmV4aXQoKS5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICBwb2ludHMuZGF0dW0oY2RzY2F0dGVyKTtcbiAgICB0ZXh0LmRhdHVtKGNkc2NhdHRlcik7XG4gICAgbWFrZVBvaW50cyhwb2ludHMsIHRleHQsIGNkc2NhdHRlcik7XG5cbiAgICAvLyBsYXN0bHksIGNsaXAgcG9pbnRzIGdyb3VwcyBvZiBgY2xpcG9uYXhpcyAhPT0gZmFsc2VgIHRyYWNlc1xuICAgIC8vIG9uIGBwbG90aW5mby5faGFzQ2xpcE9uQXhpc0ZhbHNlID09PSB0cnVlYCBzdWJwbG90c1xuICAgIHZhciBoYXNDbGlwT25BeGlzRmFsc2UgPSB0cmFjZS5jbGlwb25heGlzID09PSBmYWxzZTtcbiAgICB2YXIgY2xpcFVybCA9IGhhc0NsaXBPbkF4aXNGYWxzZSA/IG51bGwgOiBwbG90aW5mby5sYXllckNsaXBJZDtcbiAgICBEcmF3aW5nLnNldENsaXBVcmwocG9pbnRzLCBjbGlwVXJsLCBnZCk7XG4gICAgRHJhd2luZy5zZXRDbGlwVXJsKHRleHQsIGNsaXBVcmwsIGdkKTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0TWFya2VycyhnZCwgaWR4LCBwbG90aW5mbywgY2RzY2F0dGVyLCBjZHNjYXR0ZXJBbGwpIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcbiAgICB2YXIgeHIgPSBkMy5leHRlbnQoTGliLnNpbXBsZU1hcCh4YS5yYW5nZSwgeGEucjJjKSk7XG4gICAgdmFyIHlyID0gZDMuZXh0ZW50KExpYi5zaW1wbGVNYXAoeWEucmFuZ2UsIHlhLnIyYykpO1xuXG4gICAgdmFyIHRyYWNlID0gY2RzY2F0dGVyWzBdLnRyYWNlO1xuICAgIGlmKCFzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlKSkgcmV0dXJuO1xuICAgIC8vIGlmIG1hcmtlci5tYXhkaXNwbGF5ZWQgaXMgdXNlZCwgc2VsZWN0IGEgbWF4aW11bSBvZlxuICAgIC8vIG1udW0gbWFya2VycyB0byBzaG93LCBmcm9tIHRoZSBzZXQgdGhhdCBhcmUgaW4gdGhlIHZpZXdwb3J0XG4gICAgdmFyIG1udW0gPSB0cmFjZS5tYXJrZXIubWF4ZGlzcGxheWVkO1xuXG4gICAgLy8gVE9ETzogcmVtb3ZlIHNvbWUgYXMgd2UgZ2V0IGF3YXkgZnJvbSB0aGUgdmlld3BvcnQ/XG4gICAgaWYobW51bSA9PT0gMCkgcmV0dXJuO1xuXG4gICAgdmFyIGNkID0gY2RzY2F0dGVyLmZpbHRlcihmdW5jdGlvbih2KSB7XG4gICAgICAgIHJldHVybiB2LnggPj0geHJbMF0gJiYgdi54IDw9IHhyWzFdICYmIHYueSA+PSB5clswXSAmJiB2LnkgPD0geXJbMV07XG4gICAgfSk7XG4gICAgdmFyIGluYyA9IE1hdGguY2VpbChjZC5sZW5ndGggLyBtbnVtKTtcbiAgICB2YXIgdG51bSA9IDA7XG4gICAgY2RzY2F0dGVyQWxsLmZvckVhY2goZnVuY3Rpb24oY2RqLCBqKSB7XG4gICAgICAgIHZhciB0cmFjZWkgPSBjZGpbMF0udHJhY2U7XG4gICAgICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2VpKSAmJlxuICAgICAgICAgICAgICAgIHRyYWNlaS5tYXJrZXIubWF4ZGlzcGxheWVkID4gMCAmJiBqIDwgaWR4KSB7XG4gICAgICAgICAgICB0bnVtKys7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIGlmIG11bHRpcGxlIHRyYWNlcyB1c2UgbWF4ZGlzcGxheWVkLCBzdGFnZ2VyIHdoaWNoIG1hcmtlcnMgd2VcbiAgICAvLyBkaXNwbGF5IHRoaXMgZm9ybXVsYSBvZmZzZXRzIHN1Y2Nlc3NpdmUgdHJhY2VzIGJ5IDEvMyBvZiB0aGVcbiAgICAvLyBpbmNyZW1lbnQsIGFkZGluZyBhbiBleHRyYSBzbWFsbCBhbW91bnQgYWZ0ZXIgZWFjaCB0cmlwbGV0IHNvXG4gICAgLy8gaXQncyBub3QgcXVpdGUgcGVyaW9kaWNcbiAgICB2YXIgaTAgPSBNYXRoLnJvdW5kKHRudW0gKiBpbmMgLyAzICsgTWF0aC5mbG9vcih0bnVtIC8gMykgKiBpbmMgLyA3LjEpO1xuXG4gICAgLy8gZm9yIGVycm9yIGJhcnM6IHNhdmUgaW4gY2Qgd2hpY2ggbWFya2VycyB0byBzaG93XG4gICAgLy8gc28gd2UgZG9uJ3QgaGF2ZSB0byByZXBlYXQgdGhpc1xuICAgIGNkc2NhdHRlci5mb3JFYWNoKGZ1bmN0aW9uKHYpIHsgZGVsZXRlIHYudmlzOyB9KTtcbiAgICBjZC5mb3JFYWNoKGZ1bmN0aW9uKHYsIGkpIHtcbiAgICAgICAgaWYoTWF0aC5yb3VuZCgoaSArIGkwKSAlIGluYykgPT09IDApIHYudmlzID0gdHJ1ZTtcbiAgICB9KTtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvcG9seWdvblwiOjczMSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9saW5lX3BvaW50c1wiOjExMjUsXCIuL2xpbmtfdHJhY2VzXCI6MTEyNyxcIi4vc3VidHlwZXNcIjoxMTM1LFwiZDNcIjoxNjN9XSwxMTMyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3VidHlwZXMgPSBfZGVyZXFfKCcuL3N1YnR5cGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2VsZWN0UG9pbnRzKHNlYXJjaEluZm8sIHNlbGVjdGlvblRlc3Rlcikge1xuICAgIHZhciBjZCA9IHNlYXJjaEluZm8uY2Q7XG4gICAgdmFyIHhhID0gc2VhcmNoSW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBzZWFyY2hJbmZvLnlheGlzO1xuICAgIHZhciBzZWxlY3Rpb24gPSBbXTtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgaTtcbiAgICB2YXIgZGk7XG4gICAgdmFyIHg7XG4gICAgdmFyIHk7XG5cbiAgICB2YXIgaGFzT25seUxpbmVzID0gKCFzdWJ0eXBlcy5oYXNNYXJrZXJzKHRyYWNlKSAmJiAhc3VidHlwZXMuaGFzVGV4dCh0cmFjZSkpO1xuICAgIGlmKGhhc09ubHlMaW5lcykgcmV0dXJuIFtdO1xuXG4gICAgaWYoc2VsZWN0aW9uVGVzdGVyID09PSBmYWxzZSkgeyAvLyBjbGVhciBzZWxlY3Rpb25cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNkW2ldLnNlbGVjdGVkID0gMDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBkaSA9IGNkW2ldO1xuICAgICAgICAgICAgeCA9IHhhLmMycChkaS54KTtcbiAgICAgICAgICAgIHkgPSB5YS5jMnAoZGkueSk7XG5cbiAgICAgICAgICAgIGlmKChkaS5pICE9PSBudWxsKSAmJiBzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3gsIHldLCBmYWxzZSwgaSwgc2VhcmNoSW5mbykpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24ucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHBvaW50TnVtYmVyOiBkaS5pLFxuICAgICAgICAgICAgICAgICAgICB4OiB4YS5jMmQoZGkueCksXG4gICAgICAgICAgICAgICAgICAgIHk6IHlhLmMyZChkaS55KVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGRpLnNlbGVjdGVkID0gMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGkuc2VsZWN0ZWQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGVjdGlvbjtcbn07XG5cbn0se1wiLi9zdWJ0eXBlc1wiOjExMzV9XSwxMTMzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHBlclN0YWNrQXR0cnMgPSBbJ29yaWVudGF0aW9uJywgJ2dyb3Vwbm9ybScsICdzdGFja2dhcHMnXTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBoYW5kbGVTdGFja0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSkge1xuICAgIHZhciBzdGFja09wdHMgPSBsYXlvdXQuX3NjYXR0ZXJTdGFja09wdHM7XG5cbiAgICB2YXIgc3RhY2tHcm91cCA9IGNvZXJjZSgnc3RhY2tncm91cCcpO1xuICAgIGlmKHN0YWNrR3JvdXApIHtcbiAgICAgICAgLy8gdXNlIGluZGVwZW5kZW50IHN0YWNraW5nIG9wdGlvbnMgcGVyIHN1YnBsb3RcbiAgICAgICAgdmFyIHN1YnBsb3QgPSB0cmFjZU91dC54YXhpcyArIHRyYWNlT3V0LnlheGlzO1xuICAgICAgICB2YXIgc3VicGxvdFN0YWNrT3B0cyA9IHN0YWNrT3B0c1tzdWJwbG90XTtcbiAgICAgICAgaWYoIXN1YnBsb3RTdGFja09wdHMpIHN1YnBsb3RTdGFja09wdHMgPSBzdGFja09wdHNbc3VicGxvdF0gPSB7fTtcblxuICAgICAgICB2YXIgZ3JvdXBPcHRzID0gc3VicGxvdFN0YWNrT3B0c1tzdGFja0dyb3VwXTtcbiAgICAgICAgdmFyIGZpcnN0VHJhY2UgPSBmYWxzZTtcbiAgICAgICAgaWYoZ3JvdXBPcHRzKSB7XG4gICAgICAgICAgICBncm91cE9wdHMudHJhY2VzLnB1c2godHJhY2VPdXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ3JvdXBPcHRzID0gc3VicGxvdFN0YWNrT3B0c1tzdGFja0dyb3VwXSA9IHtcbiAgICAgICAgICAgICAgICAvLyBrZWVwIHRyYWNrIG9mIHRyYWNlIGluZGljZXMgZm9yIHVzZSBkdXJpbmcgc3RhY2tpbmcgY2FsY3VsYXRpb25zXG4gICAgICAgICAgICAgICAgLy8gdGhpcyB3aWxsIGJlIGZpbGxlZCBpbiBkdXJpbmcgYGNhbGNgIGFuZCB1c2VkIGR1cmluZyBgY3Jvc3NUcmFjZUNhbGNgXG4gICAgICAgICAgICAgICAgLy8gc28gaXQncyBPSyBpZiB3ZSBkb24ndCByZWNyZWF0ZSBpdCBkdXJpbmcgYSBub24tY2FsYyBlZGl0XG4gICAgICAgICAgICAgICAgdHJhY2VJbmRpY2VzOiBbXSxcbiAgICAgICAgICAgICAgICAvLyBIb2xkIG9uIHRvIHRoZSB3aG9sZSBzZXQgb2YgcHJpb3IgdHJhY2VzXG4gICAgICAgICAgICAgICAgLy8gRmlyc3Qgb25lIGlzIG1vc3QgaW1wb3J0YW50LCBzbyB3ZSBjYW4gY2xlYXIgZGVmYXVsdHNcbiAgICAgICAgICAgICAgICAvLyB0aGVyZSBpZiB3ZSBmaW5kIGV4cGxpY2l0IHZhbHVlcyBvbmx5IGluIGxhdGVyIHRyYWNlcy5cbiAgICAgICAgICAgICAgICAvLyBXZSdyZSBvbmx5IGdvaW5nIHRvICp1c2UqIHRoZSB2YWx1ZXMgc3RvcmVkIGluIGdyb3VwT3B0cyxcbiAgICAgICAgICAgICAgICAvLyBidXQgZm9yIHRoZSBlZGl0b3IgYW5kIHZhbGlkYXRlIHdlIHdhbnQgdGhpbmdzIHNlbGYtY29uc2lzdGVudFxuICAgICAgICAgICAgICAgIC8vIFRoZSBmdWxsIHNldCBvZiB0cmFjZXMgaXMgdXNlZCBvbmx5IHRvIGZpeCBgZmlsbGAgZGVmYXVsdCBpZlxuICAgICAgICAgICAgICAgIC8vIHdlIGZpbmQgYG9yaWVudGF0aW9uOiAnaCdgIGJleW9uZCB0aGUgZmlyc3QgdHJhY2VcbiAgICAgICAgICAgICAgICB0cmFjZXM6IFt0cmFjZU91dF1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBmaXJzdFRyYWNlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUT0RPOiBob3cgaXMgdGhpcyBnb2luZyB0byB3b3JrIHdpdGggZ3JvdXBieSB0cmFuc2Zvcm1zP1xuICAgICAgICAvLyBpbiBwcmluY2lwbGUgaXQgc2hvdWxkIGJlIE9LIEkgZ3Vlc3MsIGFzIGxvbmcgYXMgZXhwbGljaXQgZ3JvdXAgc3R5bGVzXG4gICAgICAgIC8vIGRvbid0IG92ZXJyaWRlIGV4cGxpY2l0IGJhc2UtdHJhY2Ugc3R5bGVzP1xuXG4gICAgICAgIHZhciBkZmx0cyA9IHtcbiAgICAgICAgICAgIG9yaWVudGF0aW9uOiAodHJhY2VPdXQueCAmJiAhdHJhY2VPdXQueSkgPyAnaCcgOiAndidcbiAgICAgICAgfTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgcGVyU3RhY2tBdHRycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIGF0dHIgPSBwZXJTdGFja0F0dHJzW2ldO1xuICAgICAgICAgICAgdmFyIGF0dHJGb3VuZCA9IGF0dHIgKyAnRm91bmQnO1xuICAgICAgICAgICAgaWYoIWdyb3VwT3B0c1thdHRyRm91bmRdKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRyYWNlSGFzQXR0ciA9IHRyYWNlSW5bYXR0cl0gIT09IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB2YXIgaXNPcmllbnRhdGlvbiA9IGF0dHIgPT09ICdvcmllbnRhdGlvbic7XG4gICAgICAgICAgICAgICAgaWYodHJhY2VIYXNBdHRyIHx8IGZpcnN0VHJhY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBPcHRzW2F0dHJdID0gY29lcmNlKGF0dHIsIGRmbHRzW2F0dHJdKTtcblxuICAgICAgICAgICAgICAgICAgICBpZihpc09yaWVudGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBncm91cE9wdHMuZmlsbERmbHQgPSBncm91cE9wdHNbYXR0cl0gPT09ICdoJyA/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3RvbmV4dHgnIDogJ3RvbmV4dHknO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYodHJhY2VIYXNBdHRyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBOb3RlOiB0aGlzIHdpbGwgc2hvdyBhIHZhbHVlIGhlcmUgZXZlbiBpZiBpdCdzIGludmFsaWRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHdoaWNoIGNhc2UgaXQgd2lsbCByZXZlcnQgdG8gZGVmYXVsdC5cbiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwT3B0c1thdHRyRm91bmRdID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm90ZTogb25seSBvbmUgdHJhY2UgaW4gdGhlIHN0YWNrIHdpbGwgZ2V0IGEgX2Z1bGxEYXRhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBlbnRyeSBmb3IgYSBnaXZlbiBzdGFjay13aWRlIGF0dHJpYnV0ZS4gSWYgbm8gdHJhY2VzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAob3IgdGhlIGZpcnN0IHRyYWNlKSBzcGVjaWZ5IHRoYXQgYXR0cmlidXRlLCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZpcnN0IHRyYWNlIHdpbGwgZ2V0IGl0LiBJZiB0aGUgZmlyc3QgdHJhY2UgZG9lcyBOT1RcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNwZWNpZnkgaXQgYnV0IHNvbWUgbGF0ZXIgdHJhY2UgZG9lcywgdGhlbiBpdCBnZXRzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmVkIGZyb20gdGhlIGZpcnN0IHRyYWNlIGFuZCBvbmx5IGluY2x1ZGVkIGluIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gb25lIHRoYXQgc3BlY2lmaWVkIGl0LiBUaGlzIGlzIG1vc3RseSBpbXBvcnRhbnQgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBlZGl0b3JzICh0aGF0IHdhbnQgdG8gc2VlIHRoZSBmdWxsIHZhbHVlcyB0byBrbm93XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3aGF0IHNldHRpbmdzIGFyZSBhdmFpbGFibGUpIGFuZCBQbG90bHkucmVhY3QgZGlmZmluZy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVkaXRvcnMgbWF5IHdhbnQgdG8gdXNlIGZ1bGxMYXlvdXQuX3NjYXR0ZXJTdGFja09wdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRpcmVjdGx5IGFuZCBtYWtlIHRoZXNlIHNldHRpbmdzIGF2YWlsYWJsZSBmcm9tIGFsbFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHJhY2VzIGluIHRoZSBzdGFjay4uLiB0aGVuIHNldCB0aGUgbmV3IHZhbHVlIGludG9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmaXJzdCB0cmFjZSwgYW5kIGNsZWFyIGFsbCBsYXRlciB0cmFjZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZighZmlyc3RUcmFjZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBncm91cE9wdHMudHJhY2VzWzBdW2F0dHJdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3JpZW50YXRpb24gY2FuIGFmZmVjdCBkZWZhdWx0IGZpbGwgb2YgcHJldmlvdXMgdHJhY2VzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoaXNPcmllbnRhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgZ3JvdXBPcHRzLnRyYWNlcy5sZW5ndGggLSAxOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0cmFjZTIgPSBncm91cE9wdHMudHJhY2VzW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYodHJhY2UyLl9pbnB1dC5maWxsICE9PSB0cmFjZTIuZmlsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlMi5maWxsID0gZ3JvdXBPcHRzLmZpbGxEZmx0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBncm91cE9wdHM7XG4gICAgfVxufTtcblxufSx7fV0sMTEzNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xuXG5mdW5jdGlvbiBzdHlsZShnZCkge1xuICAgIHZhciBzID0gZDMuc2VsZWN0KGdkKS5zZWxlY3RBbGwoJ2cudHJhY2Uuc2NhdHRlcicpO1xuXG4gICAgcy5zdHlsZSgnb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgcmV0dXJuIGRbMF0udHJhY2Uub3BhY2l0eTtcbiAgICB9KTtcblxuICAgIHMuc2VsZWN0QWxsKCdnLnBvaW50cycpLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgc2VsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdHJhY2UgPSBkLnRyYWNlIHx8IGRbMF0udHJhY2U7XG4gICAgICAgIHN0eWxlUG9pbnRzKHNlbCwgdHJhY2UsIGdkKTtcbiAgICB9KTtcblxuICAgIHMuc2VsZWN0QWxsKCdnLnRleHQnKS5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgdmFyIHNlbCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIHRyYWNlID0gZC50cmFjZSB8fCBkWzBdLnRyYWNlO1xuICAgICAgICBzdHlsZVRleHQoc2VsLCB0cmFjZSwgZ2QpO1xuICAgIH0pO1xuXG4gICAgcy5zZWxlY3RBbGwoJ2cudHJhY2UgcGF0aC5qcy1saW5lJylcbiAgICAgICAgLmNhbGwoRHJhd2luZy5saW5lR3JvdXBTdHlsZSk7XG5cbiAgICBzLnNlbGVjdEFsbCgnZy50cmFjZSBwYXRoLmpzLWZpbGwnKVxuICAgICAgICAuY2FsbChEcmF3aW5nLmZpbGxHcm91cFN0eWxlKTtcblxuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZXJyb3JiYXJzJywgJ3N0eWxlJykocyk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlUG9pbnRzKHNlbCwgdHJhY2UsIGdkKSB7XG4gICAgRHJhd2luZy5wb2ludFN0eWxlKHNlbC5zZWxlY3RBbGwoJ3BhdGgucG9pbnQnKSwgdHJhY2UsIGdkKTtcbn1cblxuZnVuY3Rpb24gc3R5bGVUZXh0KHNlbCwgdHJhY2UsIGdkKSB7XG4gICAgRHJhd2luZy50ZXh0UG9pbnRTdHlsZShzZWwuc2VsZWN0QWxsKCd0ZXh0JyksIHRyYWNlLCBnZCk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlT25TZWxlY3QoZ2QsIGNkLCBzZWwpIHtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgIGlmKHRyYWNlLnNlbGVjdGVkcG9pbnRzKSB7XG4gICAgICAgIERyYXdpbmcuc2VsZWN0ZWRQb2ludFN0eWxlKHNlbC5zZWxlY3RBbGwoJ3BhdGgucG9pbnQnKSwgdHJhY2UpO1xuICAgICAgICBEcmF3aW5nLnNlbGVjdGVkVGV4dFN0eWxlKHNlbC5zZWxlY3RBbGwoJ3RleHQnKSwgdHJhY2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHN0eWxlUG9pbnRzKHNlbCwgdHJhY2UsIGdkKTtcbiAgICAgICAgc3R5bGVUZXh0KHNlbCwgdHJhY2UsIGdkKTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN0eWxlOiBzdHlsZSxcbiAgICBzdHlsZVBvaW50czogc3R5bGVQb2ludHMsXG4gICAgc3R5bGVUZXh0OiBzdHlsZVRleHQsXG4gICAgc3R5bGVPblNlbGVjdDogc3R5bGVPblNlbGVjdFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcImQzXCI6MTYzfV0sMTEzNTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBoYXNMaW5lczogZnVuY3Rpb24odHJhY2UpIHtcbiAgICAgICAgcmV0dXJuIHRyYWNlLnZpc2libGUgJiYgdHJhY2UubW9kZSAmJlxuICAgICAgICAgICAgdHJhY2UubW9kZS5pbmRleE9mKCdsaW5lcycpICE9PSAtMTtcbiAgICB9LFxuXG4gICAgaGFzTWFya2VyczogZnVuY3Rpb24odHJhY2UpIHtcbiAgICAgICAgcmV0dXJuIHRyYWNlLnZpc2libGUgJiYgKFxuICAgICAgICAgICAgKHRyYWNlLm1vZGUgJiYgdHJhY2UubW9kZS5pbmRleE9mKCdtYXJrZXJzJykgIT09IC0xKSB8fFxuICAgICAgICAgICAgLy8gdW50aWwgc3Bsb20gaW1wbGVtZW50cyAnbW9kZSdcbiAgICAgICAgICAgIHRyYWNlLnR5cGUgPT09ICdzcGxvbSdcbiAgICAgICAgKTtcbiAgICB9LFxuXG4gICAgaGFzVGV4dDogZnVuY3Rpb24odHJhY2UpIHtcbiAgICAgICAgcmV0dXJuIHRyYWNlLnZpc2libGUgJiYgdHJhY2UubW9kZSAmJlxuICAgICAgICAgICAgdHJhY2UubW9kZS5pbmRleE9mKCd0ZXh0JykgIT09IC0xO1xuICAgIH0sXG5cbiAgICBpc0J1YmJsZTogZnVuY3Rpb24odHJhY2UpIHtcbiAgICAgICAgcmV0dXJuIExpYi5pc1BsYWluT2JqZWN0KHRyYWNlLm1hcmtlcikgJiZcbiAgICAgICAgICAgIExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRyYWNlLm1hcmtlci5zaXplKTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOX1dLDExMzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxuLypcbiAqIG9wdHM6IG9iamVjdCBvZiBmbGFncyB0byBjb250cm9sIGZlYXR1cmVzIG5vdCBhbGwgdGV4dCB1c2VycyBzdXBwb3J0XG4gKiAgIG5vU2VsZWN0OiBjYWxsZXIgZG9lcyBub3Qgc3VwcG9ydCBzZWxlY3RlZC91bnNlbGVjdGVkIGF0dHJpYnV0ZSBjb250YWluZXJzXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24odHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCBvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICBjb2VyY2UoJ3RleHRwb3NpdGlvbicpO1xuICAgIExpYi5jb2VyY2VGb250KGNvZXJjZSwgJ3RleHRmb250JywgbGF5b3V0LmZvbnQpO1xuXG4gICAgaWYoIW9wdHMubm9TZWxlY3QpIHtcbiAgICAgICAgY29lcmNlKCdzZWxlY3RlZC50ZXh0Zm9udC5jb2xvcicpO1xuICAgICAgICBjb2VyY2UoJ3Vuc2VsZWN0ZWQudGV4dGZvbnQuY29sb3InKTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOX1dLDExMzc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKSB7XG4gICAgdmFyIHggPSBjb2VyY2UoJ3gnKTtcbiAgICB2YXIgeSA9IGNvZXJjZSgneScpO1xuICAgIHZhciBsZW47XG5cbiAgICB2YXIgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2hhbmRsZVRyYWNlRGVmYXVsdHMnKTtcbiAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBbJ3gnLCAneSddLCBsYXlvdXQpO1xuXG4gICAgaWYoeCkge1xuICAgICAgICB2YXIgeGxlbiA9IExpYi5taW5Sb3dMZW5ndGgoeCk7XG4gICAgICAgIGlmKHkpIHtcbiAgICAgICAgICAgIGxlbiA9IE1hdGgubWluKHhsZW4sIExpYi5taW5Sb3dMZW5ndGgoeSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGVuID0geGxlbjtcbiAgICAgICAgICAgIGNvZXJjZSgneTAnKTtcbiAgICAgICAgICAgIGNvZXJjZSgnZHknKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmKCF5KSByZXR1cm4gMDtcblxuICAgICAgICBsZW4gPSBMaWIubWluUm93TGVuZ3RoKHkpO1xuICAgICAgICBjb2VyY2UoJ3gwJyk7XG4gICAgICAgIGNvZXJjZSgnZHgnKTtcbiAgICB9XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuXG4gICAgcmV0dXJuIGxlbjtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDd9XSwxMTM4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJBdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yQXR0cmlidXRlcyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBiYXNlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgREFTSEVTID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2dsM2RfZGFzaGVzJyk7XG5cbnZhciBNQVJLRVJfU1lNQk9MUyA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9nbDNkX21hcmtlcnMnKTtcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbnZhciBzY2F0dGVyTGluZUF0dHJzID0gc2NhdHRlckF0dHJzLmxpbmU7XG52YXIgc2NhdHRlck1hcmtlckF0dHJzID0gc2NhdHRlckF0dHJzLm1hcmtlcjtcbnZhciBzY2F0dGVyTWFya2VyTGluZUF0dHJzID0gc2NhdHRlck1hcmtlckF0dHJzLmxpbmU7XG5cbnZhciBsaW5lQXR0cnMgPSBleHRlbmRGbGF0KHtcbiAgICB3aWR0aDogc2NhdHRlckxpbmVBdHRycy53aWR0aCxcbiAgICBkYXNoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBPYmplY3Qua2V5cyhEQVNIRVMpLFxuICAgICAgICBkZmx0OiAnc29saWQnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfVxufSwgY29sb3JBdHRyaWJ1dGVzKCdsaW5lJykpO1xuXG5mdW5jdGlvbiBtYWtlUHJvamVjdGlvbkF0dHIoYXhMZXR0ZXIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBzaG93OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIG9wYWNpdHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNjYWxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxMCxcbiAgICAgICAgICAgIGRmbHQ6IDIgLyAzLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9O1xufVxuXG52YXIgYXR0cnMgPSBtb2R1bGUuZXhwb3J0cyA9IG92ZXJyaWRlQWxsKHtcbiAgICB4OiBzY2F0dGVyQXR0cnMueCxcbiAgICB5OiBzY2F0dGVyQXR0cnMueSxcbiAgICB6OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy50ZXh0LCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIGhvdmVydGV4dDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLmhvdmVydGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcnRlbXBsYXRlOiBob3ZlcnRlbXBsYXRlQXR0cnMoKSxcblxuICAgIG1vZGU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5tb2RlLCAgLy8gc2hvdWxkbid0IHRoaXMgYmUgb24tcGFyIHdpdGggMkQ/XG4gICAgICAgIHtkZmx0OiAnbGluZXMrbWFya2Vycyd9KSxcbiAgICBzdXJmYWNlYXhpczoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIFxuICAgICAgICB2YWx1ZXM6IFstMSwgMCwgMSwgMl0sXG4gICAgICAgIGRmbHQ6IC0xLFxuICAgICAgICBcbiAgICB9LFxuICAgIHN1cmZhY2Vjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBwcm9qZWN0aW9uOiB7XG4gICAgICAgIHg6IG1ha2VQcm9qZWN0aW9uQXR0cigneCcpLFxuICAgICAgICB5OiBtYWtlUHJvamVjdGlvbkF0dHIoJ3knKSxcbiAgICAgICAgejogbWFrZVByb2plY3Rpb25BdHRyKCd6JylcbiAgICB9LFxuXG4gICAgY29ubmVjdGdhcHM6IHNjYXR0ZXJBdHRycy5jb25uZWN0Z2FwcyxcbiAgICBsaW5lOiBsaW5lQXR0cnMsXG5cbiAgICBtYXJrZXI6IGV4dGVuZEZsYXQoeyAgLy8gUGFyaXR5IHdpdGggc2NhdHRlci5qcz9cbiAgICAgICAgc3ltYm9sOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IE9iamVjdC5rZXlzKE1BUktFUl9TWU1CT0xTKSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogJ2NpcmNsZScsXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHNpemU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplLCB7ZGZsdDogOH0pLFxuICAgICAgICBzaXplcmVmOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZXJlZixcbiAgICAgICAgc2l6ZW1pbjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVtaW4sXG4gICAgICAgIHNpemVtb2RlOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZW1vZGUsXG4gICAgICAgIG9wYWNpdHk6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJNYXJrZXJBdHRycy5vcGFjaXR5LCB7XG4gICAgICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9KSxcbiAgICAgICAgY29sb3JiYXI6IHNjYXR0ZXJNYXJrZXJBdHRycy5jb2xvcmJhcixcblxuICAgICAgICBsaW5lOiBleHRlbmRGbGF0KHtcbiAgICAgICAgICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyTGluZUF0dHJzLndpZHRoLCB7YXJyYXlPazogZmFsc2V9KVxuICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXIubGluZScpXG4gICAgICAgIClcbiAgICB9LFxuICAgICAgICBjb2xvckF0dHJpYnV0ZXMoJ21hcmtlcicpXG4gICAgKSxcblxuICAgIHRleHRwb3NpdGlvbjogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLnRleHRwb3NpdGlvbiwge2RmbHQ6ICd0b3AgY2VudGVyJ30pLFxuICAgIHRleHRmb250OiB7XG4gICAgICAgIGNvbG9yOiBzY2F0dGVyQXR0cnMudGV4dGZvbnQuY29sb3IsXG4gICAgICAgIHNpemU6IHNjYXR0ZXJBdHRycy50ZXh0Zm9udC5zaXplLFxuICAgICAgICBmYW1pbHk6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy50ZXh0Zm9udC5mYW1pbHksIHthcnJheU9rOiBmYWxzZX0pXG4gICAgfSxcblxuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgYmFzZUF0dHJzLmhvdmVyaW5mbylcbn0sICdjYWxjJywgJ25lc3RlZCcpO1xuXG5hdHRycy54LmVkaXRUeXBlID0gYXR0cnMueS5lZGl0VHlwZSA9IGF0dHJzLnouZWRpdFR5cGUgPSAnY2FsYytjbGVhckF4aXNUeXBlcyc7XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXNcIjo2MDAsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2NvbnN0YW50cy9nbDNkX2Rhc2hlc1wiOjY5MixcIi4uLy4uL2NvbnN0YW50cy9nbDNkX21hcmtlcnNcIjo2OTMsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlc1wiOjc1MCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9zY2F0dGVyL2F0dHJpYnV0ZXNcIjoxMTEyfV0sMTEzOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBhcnJheXNUb0NhbGNkYXRhID0gX2RlcmVxXygnLi4vc2NhdHRlci9hcnJheXNfdG9fY2FsY2RhdGEnKTtcbnZhciBjYWxjQ29sb3JzY2FsZSA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjJyk7XG5cbi8qKlxuICogVGhpcyBpcyBhIGtsdWRnZSB0byBwdXQgdGhlIGFycmF5IGF0dHJpYnV0ZXMgaW50b1xuICogY2FsY2RhdGEgdGhlIHdheSBTY2F0dGVyLnBsb3QgZG9lcywgc28gdGhhdCBsZWdlbmRzIGFuZFxuICogcG9wb3ZlcnMga25vdyB3aGF0IHRvIGRvIHdpdGggdGhlbS5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBjZCA9IFt7eDogZmFsc2UsIHk6IGZhbHNlLCB0cmFjZTogdHJhY2UsIHQ6IHt9fV07XG5cbiAgICBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSk7XG4gICAgY2FsY0NvbG9yc2NhbGUoZ2QsIHRyYWNlKTtcblxuICAgIHJldHVybiBjZDtcbn07XG5cbn0se1wiLi4vc2NhdHRlci9hcnJheXNfdG9fY2FsY2RhdGFcIjoxMTExLFwiLi4vc2NhdHRlci9jb2xvcnNjYWxlX2NhbGNcIjoxMTE1fV0sMTE0MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZUF4aXNFcnJvcnMoZGF0YSwgcGFyYW1zLCBzY2FsZUZhY3RvciwgYXhpcykge1xuICAgIGlmKCFwYXJhbXMgfHwgIXBhcmFtcy52aXNpYmxlKSByZXR1cm4gbnVsbDtcblxuICAgIHZhciBjb21wdXRlRXJyb3IgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdtYWtlQ29tcHV0ZUVycm9yJykocGFyYW1zKTtcbiAgICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KGRhdGEubGVuZ3RoKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBlcnJvcnMgPSBjb21wdXRlRXJyb3IoK2RhdGFbaV0sIGkpO1xuXG4gICAgICAgIGlmKGF4aXMudHlwZSA9PT0gJ2xvZycpIHtcbiAgICAgICAgICAgIHZhciBwb2ludCA9IGF4aXMuYzJsKGRhdGFbaV0pO1xuICAgICAgICAgICAgdmFyIG1pbiA9IGRhdGFbaV0gLSBlcnJvcnNbMF07XG4gICAgICAgICAgICB2YXIgbWF4ID0gZGF0YVtpXSArIGVycm9yc1sxXTtcblxuICAgICAgICAgICAgcmVzdWx0W2ldID0gW1xuICAgICAgICAgICAgICAgIChheGlzLmMybChtaW4sIHRydWUpIC0gcG9pbnQpICogc2NhbGVGYWN0b3IsXG4gICAgICAgICAgICAgICAgKGF4aXMuYzJsKG1heCwgdHJ1ZSkgLSBwb2ludCkgKiBzY2FsZUZhY3RvclxuICAgICAgICAgICAgXTtcblxuICAgICAgICAgICAgLy8gS2VlcCB0cmFjayBvZiB0aGUgbG93ZXIgZXJyb3IgYm91bmQgd2hpY2ggaXNuJ3QgbmVnYXRpdmUhXG4gICAgICAgICAgICBpZihtaW4gPiAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxvd2VyID0gYXhpcy5jMmwobWluKTtcbiAgICAgICAgICAgICAgICBpZighYXhpcy5fbG93ZXJMb2dFcnJvckJvdW5kKSBheGlzLl9sb3dlckxvZ0Vycm9yQm91bmQgPSBsb3dlcjtcbiAgICAgICAgICAgICAgICBheGlzLl9sb3dlckVycm9yQm91bmQgPSBNYXRoLm1pbihheGlzLl9sb3dlckxvZ0Vycm9yQm91bmQsIGxvd2VyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdFtpXSA9IFtcbiAgICAgICAgICAgICAgICAtZXJyb3JzWzBdICogc2NhbGVGYWN0b3IsXG4gICAgICAgICAgICAgICAgZXJyb3JzWzFdICogc2NhbGVGYWN0b3JcbiAgICAgICAgICAgIF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBkYXRhTGVuZ3RoKGFycmF5KSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKGFycmF5W2ldKSByZXR1cm4gYXJyYXlbaV0ubGVuZ3RoO1xuICAgIH1cbiAgICByZXR1cm4gMDtcbn1cblxuZnVuY3Rpb24gY2FsY3VsYXRlRXJyb3JzKGRhdGEsIHNjYWxlRmFjdG9yLCBzY2VuZUxheW91dCkge1xuICAgIHZhciBlcnJvcnMgPSBbXG4gICAgICAgIGNhbGN1bGF0ZUF4aXNFcnJvcnMoZGF0YS54LCBkYXRhLmVycm9yX3gsIHNjYWxlRmFjdG9yWzBdLCBzY2VuZUxheW91dC54YXhpcyksXG4gICAgICAgIGNhbGN1bGF0ZUF4aXNFcnJvcnMoZGF0YS55LCBkYXRhLmVycm9yX3ksIHNjYWxlRmFjdG9yWzFdLCBzY2VuZUxheW91dC55YXhpcyksXG4gICAgICAgIGNhbGN1bGF0ZUF4aXNFcnJvcnMoZGF0YS56LCBkYXRhLmVycm9yX3osIHNjYWxlRmFjdG9yWzJdLCBzY2VuZUxheW91dC56YXhpcylcbiAgICBdO1xuXG4gICAgdmFyIG4gPSBkYXRhTGVuZ3RoKGVycm9ycyk7XG4gICAgaWYobiA9PT0gMCkgcmV0dXJuIG51bGw7XG5cbiAgICB2YXIgZXJyb3JCb3VuZHMgPSBuZXcgQXJyYXkobik7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgIHZhciBib3VuZCA9IFtbMCwgMCwgMF0sIFswLCAwLCAwXV07XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IDM7IGorKykge1xuICAgICAgICAgICAgaWYoZXJyb3JzW2pdKSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBrID0gMDsgayA8IDI7IGsrKykge1xuICAgICAgICAgICAgICAgICAgICBib3VuZFtrXVtqXSA9IGVycm9yc1tqXVtpXVtrXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBlcnJvckJvdW5kc1tpXSA9IGJvdW5kO1xuICAgIH1cblxuICAgIHJldHVybiBlcnJvckJvdW5kcztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjYWxjdWxhdGVFcnJvcnM7XG5cbn0se1wiLi4vLi4vcmVnaXN0cnlcIjo4NDd9XSwxMTQxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3JlYXRlTGluZVBsb3QgPSBfZGVyZXFfKCdnbC1saW5lM2QnKTtcbnZhciBjcmVhdGVTY2F0dGVyUGxvdCA9IF9kZXJlcV8oJ2dsLXNjYXR0ZXIzZCcpO1xudmFyIGNyZWF0ZUVycm9yQmFycyA9IF9kZXJlcV8oJ2dsLWVycm9yM2QnKTtcbnZhciBjcmVhdGVNZXNoID0gX2RlcmVxXygnZ2wtbWVzaDNkJyk7XG52YXIgdHJpYW5ndWxhdGUgPSBfZGVyZXFfKCdkZWxhdW5heS10cmlhbmd1bGF0ZScpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgc3RyMlJnYmFBcnJheSA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdHIycmdiYXJyYXknKTtcbnZhciBmb3JtYXRDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2xpYi9nbF9mb3JtYXRfY29sb3InKS5mb3JtYXRDb2xvcjtcbnZhciBtYWtlQnViYmxlU2l6ZUZuID0gX2RlcmVxXygnLi4vc2NhdHRlci9tYWtlX2J1YmJsZV9zaXplX2Z1bmMnKTtcbnZhciBEQVNIX1BBVFRFUk5TID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2dsM2RfZGFzaGVzJyk7XG52YXIgTUFSS0VSX1NZTUJPTFMgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvZ2wzZF9tYXJrZXJzJyk7XG5cbnZhciBjYWxjdWxhdGVFcnJvciA9IF9kZXJlcV8oJy4vY2FsY19lcnJvcnMnKTtcblxuZnVuY3Rpb24gTGluZVdpdGhNYXJrZXJzKHNjZW5lLCB1aWQpIHtcbiAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgdGhpcy51aWQgPSB1aWQ7XG4gICAgdGhpcy5saW5lUGxvdCA9IG51bGw7XG4gICAgdGhpcy5zY2F0dGVyUGxvdCA9IG51bGw7XG4gICAgdGhpcy5lcnJvckJhcnMgPSBudWxsO1xuICAgIHRoaXMudGV4dE1hcmtlcnMgPSBudWxsO1xuICAgIHRoaXMuZGVsYXVuYXlNZXNoID0gbnVsbDtcbiAgICB0aGlzLmNvbG9yID0gbnVsbDtcbiAgICB0aGlzLm1vZGUgPSAnJztcbiAgICB0aGlzLmRhdGFQb2ludHMgPSBbXTtcbiAgICB0aGlzLmF4ZXNCb3VuZHMgPSBbXG4gICAgICAgIFstSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XSxcbiAgICAgICAgW0luZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldXG4gICAgXTtcbiAgICB0aGlzLnRleHRMYWJlbHMgPSBudWxsO1xuICAgIHRoaXMuZGF0YSA9IG51bGw7XG59XG5cbnZhciBwcm90byA9IExpbmVXaXRoTWFya2Vycy5wcm90b3R5cGU7XG5cbnByb3RvLmhhbmRsZVBpY2sgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcbiAgICBpZihzZWxlY3Rpb24ub2JqZWN0ICYmXG4gICAgICAgIChzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLmxpbmVQbG90IHx8XG4gICAgICAgICBzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLmRlbGF1bmF5TWVzaCB8fFxuICAgICAgICAgc2VsZWN0aW9uLm9iamVjdCA9PT0gdGhpcy50ZXh0TWFya2VycyB8fFxuICAgICAgICAgc2VsZWN0aW9uLm9iamVjdCA9PT0gdGhpcy5zY2F0dGVyUGxvdClcbiAgICApIHtcbiAgICAgICAgdmFyIGluZCA9IHNlbGVjdGlvbi5pbmRleCA9IHNlbGVjdGlvbi5kYXRhLmluZGV4O1xuXG4gICAgICAgIGlmKHNlbGVjdGlvbi5vYmplY3QuaGlnaGxpZ2h0KSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24ub2JqZWN0LmhpZ2hsaWdodChudWxsKTtcbiAgICAgICAgfVxuICAgICAgICBpZih0aGlzLnNjYXR0ZXJQbG90KSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24ub2JqZWN0ID0gdGhpcy5zY2F0dGVyUGxvdDtcbiAgICAgICAgICAgIHRoaXMuc2NhdHRlclBsb3QuaGlnaGxpZ2h0KHNlbGVjdGlvbi5kYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSAnJztcbiAgICAgICAgaWYodGhpcy50ZXh0TGFiZWxzKSB7XG4gICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KHRoaXMudGV4dExhYmVscykpIHtcbiAgICAgICAgICAgICAgICBpZih0aGlzLnRleHRMYWJlbHNbaW5kXSB8fCB0aGlzLnRleHRMYWJlbHNbaW5kXSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGhpcy50ZXh0TGFiZWxzW2luZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGhpcy50ZXh0TGFiZWxzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZSA9IFtcbiAgICAgICAgICAgIHRoaXMuZGF0YS54W2luZF0sXG4gICAgICAgICAgICB0aGlzLmRhdGEueVtpbmRdLFxuICAgICAgICAgICAgdGhpcy5kYXRhLnpbaW5kXVxuICAgICAgICBdO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIGNvbnN0cnVjdERlbGF1bmF5KHBvaW50cywgY29sb3IsIGF4aXMpIHtcbiAgICB2YXIgdSA9IChheGlzICsgMSkgJSAzO1xuICAgIHZhciB2ID0gKGF4aXMgKyAyKSAlIDM7XG4gICAgdmFyIGZpbHRlcmVkUG9pbnRzID0gW107XG4gICAgdmFyIGZpbHRlcmVkSWRzID0gW107XG4gICAgdmFyIGk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgdmFyIHAgPSBwb2ludHNbaV07XG4gICAgICAgIGlmKGlzTmFOKHBbdV0pIHx8ICFpc0Zpbml0ZShwW3VdKSB8fFxuICAgICAgICAgICBpc05hTihwW3ZdKSB8fCAhaXNGaW5pdGUocFt2XSkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGZpbHRlcmVkUG9pbnRzLnB1c2goW3BbdV0sIHBbdl1dKTtcbiAgICAgICAgZmlsdGVyZWRJZHMucHVzaChpKTtcbiAgICB9XG4gICAgdmFyIGNlbGxzID0gdHJpYW5ndWxhdGUoZmlsdGVyZWRQb2ludHMpO1xuICAgIGZvcihpID0gMDsgaSA8IGNlbGxzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZhciBjID0gY2VsbHNbaV07XG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICBjW2pdID0gZmlsdGVyZWRJZHNbY1tqXV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgcG9zaXRpb25zOiBwb2ludHMsXG4gICAgICAgIGNlbGxzOiBjZWxscyxcbiAgICAgICAgbWVzaENvbG9yOiBjb2xvclxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZUVycm9yUGFyYW1zKGVycm9ycykge1xuICAgIHZhciBjYXBTaXplID0gWzAuMCwgMC4wLCAwLjBdO1xuICAgIHZhciBjb2xvciA9IFtbMCwgMCwgMF0sIFswLCAwLCAwXSwgWzAsIDAsIDBdXTtcbiAgICB2YXIgbGluZVdpZHRoID0gWzEuMCwgMS4wLCAxLjBdO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICB2YXIgZSA9IGVycm9yc1tpXTtcblxuICAgICAgICBpZihlICYmIGUuY29weV96c3R5bGUgIT09IGZhbHNlICYmIGVycm9yc1syXS52aXNpYmxlICE9PSBmYWxzZSkgZSA9IGVycm9yc1syXTtcbiAgICAgICAgaWYoIWUgfHwgIWUudmlzaWJsZSkgY29udGludWU7XG5cbiAgICAgICAgY2FwU2l6ZVtpXSA9IGUud2lkdGggLyAyOyAgLy8gYmFsbHBhcmsgcmVzY2FsaW5nXG4gICAgICAgIGNvbG9yW2ldID0gc3RyMlJnYmFBcnJheShlLmNvbG9yKTtcbiAgICAgICAgbGluZVdpZHRoW2ldID0gZS50aGlja25lc3M7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtjYXBTaXplOiBjYXBTaXplLCBjb2xvcjogY29sb3IsIGxpbmVXaWR0aDogbGluZVdpZHRofTtcbn1cblxuZnVuY3Rpb24gcGFyc2VBbGlnbm1lbnRYKGEpIHtcbiAgICBpZihhID09PSBudWxsIHx8IGEgPT09IHVuZGVmaW5lZCkgcmV0dXJuIDA7XG5cbiAgICByZXR1cm4gKGEuaW5kZXhPZignbGVmdCcpID4gLTEpID8gLTEgOlxuICAgICAgICAgICAoYS5pbmRleE9mKCdyaWdodCcpID4gLTEpID8gMSA6IDA7XG59XG5cbmZ1bmN0aW9uIHBhcnNlQWxpZ25tZW50WShhKSB7XG4gICAgaWYoYSA9PT0gbnVsbCB8fCBhID09PSB1bmRlZmluZWQpIHJldHVybiAwO1xuXG4gICAgcmV0dXJuIChhLmluZGV4T2YoJ3RvcCcpID4gLTEpID8gLTEgOlxuICAgICAgICAgICAoYS5pbmRleE9mKCdib3R0b20nKSA+IC0xKSA/IDEgOiAwO1xufVxuXG5mdW5jdGlvbiBjYWxjdWxhdGVUZXh0T2Zmc2V0KHRwKSB7XG4gICAgLy8gUmVhZCBvdXQgdGV4dCBwcm9wZXJ0aWVzXG5cbiAgICB2YXIgZGVmYXVsdEFsaWdubWVudFggPSAwO1xuICAgIHZhciBkZWZhdWx0QWxpZ25tZW50WSA9IDA7XG5cbiAgICB2YXIgdGV4dE9mZnNldCA9IFtcbiAgICAgICAgZGVmYXVsdEFsaWdubWVudFgsXG4gICAgICAgIGRlZmF1bHRBbGlnbm1lbnRZXG4gICAgXTtcblxuICAgIGlmKEFycmF5LmlzQXJyYXkodHApKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0cC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGV4dE9mZnNldFtpXSA9IFtcbiAgICAgICAgICAgICAgICBkZWZhdWx0QWxpZ25tZW50WCxcbiAgICAgICAgICAgICAgICBkZWZhdWx0QWxpZ25tZW50WVxuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGlmKHRwW2ldKSB7XG4gICAgICAgICAgICAgICAgdGV4dE9mZnNldFtpXVswXSA9IHBhcnNlQWxpZ25tZW50WCh0cFtpXSk7XG4gICAgICAgICAgICAgICAgdGV4dE9mZnNldFtpXVsxXSA9IHBhcnNlQWxpZ25tZW50WSh0cFtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICB0ZXh0T2Zmc2V0WzBdID0gcGFyc2VBbGlnbm1lbnRYKHRwKTtcbiAgICAgICAgdGV4dE9mZnNldFsxXSA9IHBhcnNlQWxpZ25tZW50WSh0cCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRleHRPZmZzZXQ7XG59XG5cblxuZnVuY3Rpb24gY2FsY3VsYXRlU2l6ZShzaXplSW4sIHNpemVGbikge1xuICAgIC8vIHJvdWdoIHBhcml0eSB3aXRoIFBsb3RseSAyRCBtYXJrZXJzXG4gICAgcmV0dXJuIHNpemVGbihzaXplSW4gKiA0KTtcbn1cblxuZnVuY3Rpb24gY2FsY3VsYXRlU3ltYm9sKHN5bWJvbEluKSB7XG4gICAgcmV0dXJuIE1BUktFUl9TWU1CT0xTW3N5bWJvbEluXTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0UGFyYW0ocGFyYW1JbiwgbGVuLCBjYWxjdWxhdGUsIGRmbHQsIGV4dHJhRm4pIHtcbiAgICB2YXIgcGFyYW1PdXQgPSBudWxsO1xuXG4gICAgaWYoTGliLmlzQXJyYXlPclR5cGVkQXJyYXkocGFyYW1JbikpIHtcbiAgICAgICAgcGFyYW1PdXQgPSBbXTtcblxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlmKHBhcmFtSW5baV0gPT09IHVuZGVmaW5lZCkgcGFyYW1PdXRbaV0gPSBkZmx0O1xuICAgICAgICAgICAgZWxzZSBwYXJhbU91dFtpXSA9IGNhbGN1bGF0ZShwYXJhbUluW2ldLCBleHRyYUZuKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBwYXJhbU91dCA9IGNhbGN1bGF0ZShwYXJhbUluLCBMaWIuaWRlbnRpdHkpO1xuXG4gICAgcmV0dXJuIHBhcmFtT3V0O1xufVxuXG5cbmZ1bmN0aW9uIGNvbnZlcnRQbG90bHlPcHRpb25zKHNjZW5lLCBkYXRhKSB7XG4gICAgdmFyIHBvaW50cyA9IFtdO1xuICAgIHZhciBzY2VuZUxheW91dCA9IHNjZW5lLmZ1bGxTY2VuZUxheW91dDtcbiAgICB2YXIgc2NhbGVGYWN0b3IgPSBzY2VuZS5kYXRhU2NhbGU7XG4gICAgdmFyIHhheGlzID0gc2NlbmVMYXlvdXQueGF4aXM7XG4gICAgdmFyIHlheGlzID0gc2NlbmVMYXlvdXQueWF4aXM7XG4gICAgdmFyIHpheGlzID0gc2NlbmVMYXlvdXQuemF4aXM7XG4gICAgdmFyIG1hcmtlciA9IGRhdGEubWFya2VyO1xuICAgIHZhciBsaW5lID0gZGF0YS5saW5lO1xuICAgIHZhciB4ID0gZGF0YS54IHx8IFtdO1xuICAgIHZhciB5ID0gZGF0YS55IHx8IFtdO1xuICAgIHZhciB6ID0gZGF0YS56IHx8IFtdO1xuICAgIHZhciBsZW4gPSB4Lmxlbmd0aDtcbiAgICB2YXIgeGNhbGVuZGFyID0gZGF0YS54Y2FsZW5kYXI7XG4gICAgdmFyIHljYWxlbmRhciA9IGRhdGEueWNhbGVuZGFyO1xuICAgIHZhciB6Y2FsZW5kYXIgPSBkYXRhLnpjYWxlbmRhcjtcbiAgICB2YXIgeGMsIHljLCB6YztcbiAgICB2YXIgcGFyYW1zLCBpO1xuICAgIHZhciB0ZXh0O1xuXG4gICAgLy8gQ29udmVydCBwb2ludHNcbiAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAvLyBzYW5pdGl6ZSBudW1iZXJzIGFuZCBhcHBseSB0cmFuc2Zvcm1zIGJhc2VkIG9uIGF4ZXMudHlwZVxuICAgICAgICB4YyA9IHhheGlzLmQybCh4W2ldLCAwLCB4Y2FsZW5kYXIpICogc2NhbGVGYWN0b3JbMF07XG4gICAgICAgIHljID0geWF4aXMuZDJsKHlbaV0sIDAsIHljYWxlbmRhcikgKiBzY2FsZUZhY3RvclsxXTtcbiAgICAgICAgemMgPSB6YXhpcy5kMmwoeltpXSwgMCwgemNhbGVuZGFyKSAqIHNjYWxlRmFjdG9yWzJdO1xuXG4gICAgICAgIHBvaW50c1tpXSA9IFt4YywgeWMsIHpjXTtcbiAgICB9XG5cbiAgICAvLyBjb252ZXJ0IHRleHRcbiAgICBpZihBcnJheS5pc0FycmF5KGRhdGEudGV4dCkpIHRleHQgPSBkYXRhLnRleHQ7XG4gICAgZWxzZSBpZihkYXRhLnRleHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0ZXh0ID0gbmV3IEFycmF5KGxlbik7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB0ZXh0W2ldID0gZGF0YS50ZXh0O1xuICAgIH1cblxuICAgIC8vIEJ1aWxkIG9iamVjdCBwYXJhbWV0ZXJzXG4gICAgcGFyYW1zID0ge1xuICAgICAgICBwb3NpdGlvbjogcG9pbnRzLFxuICAgICAgICBtb2RlOiBkYXRhLm1vZGUsXG4gICAgICAgIHRleHQ6IHRleHRcbiAgICB9O1xuXG4gICAgaWYoJ2xpbmUnIGluIGRhdGEpIHtcbiAgICAgICAgcGFyYW1zLmxpbmVDb2xvciA9IGZvcm1hdENvbG9yKGxpbmUsIDEsIGxlbik7XG4gICAgICAgIHBhcmFtcy5saW5lV2lkdGggPSBsaW5lLndpZHRoO1xuICAgICAgICBwYXJhbXMubGluZURhc2hlcyA9IGxpbmUuZGFzaDtcbiAgICB9XG5cbiAgICBpZignbWFya2VyJyBpbiBkYXRhKSB7XG4gICAgICAgIHZhciBzaXplRm4gPSBtYWtlQnViYmxlU2l6ZUZuKGRhdGEpO1xuXG4gICAgICAgIHBhcmFtcy5zY2F0dGVyQ29sb3IgPSBmb3JtYXRDb2xvcihtYXJrZXIsIDEsIGxlbik7XG4gICAgICAgIHBhcmFtcy5zY2F0dGVyU2l6ZSA9IGZvcm1hdFBhcmFtKG1hcmtlci5zaXplLCBsZW4sIGNhbGN1bGF0ZVNpemUsIDIwLCBzaXplRm4pO1xuICAgICAgICBwYXJhbXMuc2NhdHRlck1hcmtlciA9IGZvcm1hdFBhcmFtKG1hcmtlci5zeW1ib2wsIGxlbiwgY2FsY3VsYXRlU3ltYm9sLCAn4pePJyk7XG4gICAgICAgIHBhcmFtcy5zY2F0dGVyTGluZVdpZHRoID0gbWFya2VyLmxpbmUud2lkdGg7ICAvLyBhcnJheU9rID09PSBmYWxzZVxuICAgICAgICBwYXJhbXMuc2NhdHRlckxpbmVDb2xvciA9IGZvcm1hdENvbG9yKG1hcmtlci5saW5lLCAxLCBsZW4pO1xuICAgICAgICBwYXJhbXMuc2NhdHRlckFuZ2xlID0gMDtcbiAgICB9XG5cbiAgICBpZigndGV4dHBvc2l0aW9uJyBpbiBkYXRhKSB7XG4gICAgICAgIHBhcmFtcy50ZXh0T2Zmc2V0ID0gY2FsY3VsYXRlVGV4dE9mZnNldChkYXRhLnRleHRwb3NpdGlvbik7XG4gICAgICAgIHBhcmFtcy50ZXh0Q29sb3IgPSBmb3JtYXRDb2xvcihkYXRhLnRleHRmb250LCAxLCBsZW4pO1xuICAgICAgICBwYXJhbXMudGV4dFNpemUgPSBmb3JtYXRQYXJhbShkYXRhLnRleHRmb250LnNpemUsIGxlbiwgTGliLmlkZW50aXR5LCAxMik7XG4gICAgICAgIHBhcmFtcy50ZXh0Rm9udCA9IGRhdGEudGV4dGZvbnQuZmFtaWx5OyAgLy8gYXJyYXlPayA9PT0gZmFsc2VcbiAgICAgICAgcGFyYW1zLnRleHRBbmdsZSA9IDA7XG4gICAgfVxuXG4gICAgdmFyIGRpbXMgPSBbJ3gnLCAneScsICd6J107XG4gICAgcGFyYW1zLnByb2plY3QgPSBbZmFsc2UsIGZhbHNlLCBmYWxzZV07XG4gICAgcGFyYW1zLnByb2plY3RTY2FsZSA9IFsxLCAxLCAxXTtcbiAgICBwYXJhbXMucHJvamVjdE9wYWNpdHkgPSBbMSwgMSwgMV07XG4gICAgZm9yKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIHZhciBwcm9qZWN0aW9uID0gZGF0YS5wcm9qZWN0aW9uW2RpbXNbaV1dO1xuICAgICAgICBpZigocGFyYW1zLnByb2plY3RbaV0gPSBwcm9qZWN0aW9uLnNob3cpKSB7XG4gICAgICAgICAgICBwYXJhbXMucHJvamVjdE9wYWNpdHlbaV0gPSBwcm9qZWN0aW9uLm9wYWNpdHk7XG4gICAgICAgICAgICBwYXJhbXMucHJvamVjdFNjYWxlW2ldID0gcHJvamVjdGlvbi5zY2FsZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHBhcmFtcy5lcnJvckJvdW5kcyA9IGNhbGN1bGF0ZUVycm9yKGRhdGEsIHNjYWxlRmFjdG9yLCBzY2VuZUxheW91dCk7XG5cbiAgICB2YXIgZXJyb3JQYXJhbXMgPSBjYWxjdWxhdGVFcnJvclBhcmFtcyhbZGF0YS5lcnJvcl94LCBkYXRhLmVycm9yX3ksIGRhdGEuZXJyb3Jfel0pO1xuICAgIHBhcmFtcy5lcnJvckNvbG9yID0gZXJyb3JQYXJhbXMuY29sb3I7XG4gICAgcGFyYW1zLmVycm9yTGluZVdpZHRoID0gZXJyb3JQYXJhbXMubGluZVdpZHRoO1xuICAgIHBhcmFtcy5lcnJvckNhcFNpemUgPSBlcnJvclBhcmFtcy5jYXBTaXplO1xuXG4gICAgcGFyYW1zLmRlbGF1bmF5QXhpcyA9IGRhdGEuc3VyZmFjZWF4aXM7XG4gICAgcGFyYW1zLmRlbGF1bmF5Q29sb3IgPSBzdHIyUmdiYUFycmF5KGRhdGEuc3VyZmFjZWNvbG9yKTtcblxuICAgIHJldHVybiBwYXJhbXM7XG59XG5cbmZ1bmN0aW9uIGFycmF5VG9Db2xvcihjb2xvcikge1xuICAgIGlmKEFycmF5LmlzQXJyYXkoY29sb3IpKSB7XG4gICAgICAgIHZhciBjID0gY29sb3JbMF07XG5cbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheShjKSkgY29sb3IgPSBjO1xuXG4gICAgICAgIHJldHVybiAncmdiKCcgKyBjb2xvci5zbGljZSgwLCAzKS5tYXAoZnVuY3Rpb24oeCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoeCAqIDI1NSk7XG4gICAgICAgIH0pICsgJyknO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufVxuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgdmFyIGdsID0gdGhpcy5zY2VuZS5nbHBsb3QuZ2w7XG4gICAgdmFyIGxpbmVPcHRpb25zO1xuICAgIHZhciBzY2F0dGVyT3B0aW9ucztcbiAgICB2YXIgZXJyb3JPcHRpb25zO1xuICAgIHZhciB0ZXh0T3B0aW9ucztcbiAgICB2YXIgZGFzaFBhdHRlcm4gPSBEQVNIX1BBVFRFUk5TLnNvbGlkO1xuXG4gICAgLy8gU2F2ZSBkYXRhXG4gICAgdGhpcy5kYXRhID0gZGF0YTtcblxuICAgIC8vIFJ1biBkYXRhIGNvbnZlcnNpb25cbiAgICB2YXIgb3B0aW9ucyA9IGNvbnZlcnRQbG90bHlPcHRpb25zKHRoaXMuc2NlbmUsIGRhdGEpO1xuXG4gICAgaWYoJ21vZGUnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5tb2RlID0gb3B0aW9ucy5tb2RlO1xuICAgIH1cbiAgICBpZignbGluZURhc2hlcycgaW4gb3B0aW9ucykge1xuICAgICAgICBpZihvcHRpb25zLmxpbmVEYXNoZXMgaW4gREFTSF9QQVRURVJOUykge1xuICAgICAgICAgICAgZGFzaFBhdHRlcm4gPSBEQVNIX1BBVFRFUk5TW29wdGlvbnMubGluZURhc2hlc107XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmNvbG9yID0gYXJyYXlUb0NvbG9yKG9wdGlvbnMuc2NhdHRlckNvbG9yKSB8fFxuICAgICAgICAgICAgICAgICBhcnJheVRvQ29sb3Iob3B0aW9ucy5saW5lQ29sb3IpO1xuXG4gICAgLy8gU2F2ZSBkYXRhIHBvaW50c1xuICAgIHRoaXMuZGF0YVBvaW50cyA9IG9wdGlvbnMucG9zaXRpb247XG5cbiAgICBsaW5lT3B0aW9ucyA9IHtcbiAgICAgICAgZ2w6IHRoaXMuc2NlbmUuZ2xwbG90LmdsLFxuICAgICAgICBwb3NpdGlvbjogb3B0aW9ucy5wb3NpdGlvbixcbiAgICAgICAgY29sb3I6IG9wdGlvbnMubGluZUNvbG9yLFxuICAgICAgICBsaW5lV2lkdGg6IG9wdGlvbnMubGluZVdpZHRoIHx8IDEsXG4gICAgICAgIGRhc2hlczogZGFzaFBhdHRlcm5bMF0sXG4gICAgICAgIGRhc2hTY2FsZTogZGFzaFBhdHRlcm5bMV0sXG4gICAgICAgIG9wYWNpdHk6IGRhdGEub3BhY2l0eSxcbiAgICAgICAgY29ubmVjdEdhcHM6IGRhdGEuY29ubmVjdGdhcHNcbiAgICB9O1xuXG4gICAgaWYodGhpcy5tb2RlLmluZGV4T2YoJ2xpbmVzJykgIT09IC0xKSB7XG4gICAgICAgIGlmKHRoaXMubGluZVBsb3QpIHRoaXMubGluZVBsb3QudXBkYXRlKGxpbmVPcHRpb25zKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmxpbmVQbG90ID0gY3JlYXRlTGluZVBsb3QobGluZU9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5saW5lUGxvdC5fdHJhY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QuYWRkKHRoaXMubGluZVBsb3QpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKHRoaXMubGluZVBsb3QpIHtcbiAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QucmVtb3ZlKHRoaXMubGluZVBsb3QpO1xuICAgICAgICB0aGlzLmxpbmVQbG90LmRpc3Bvc2UoKTtcbiAgICAgICAgdGhpcy5saW5lUGxvdCA9IG51bGw7XG4gICAgfVxuXG4gICAgLy8gTi5CLiBtYXJrZXIub3BhY2l0eSBtdXN0IGJlIGEgc2NhbGFyIGZvciBwZXJmb3JtYW5jZVxuICAgIHZhciBzY2F0dGVyT3BhY2l0eSA9IGRhdGEub3BhY2l0eTtcbiAgICBpZihkYXRhLm1hcmtlciAmJiBkYXRhLm1hcmtlci5vcGFjaXR5KSBzY2F0dGVyT3BhY2l0eSAqPSBkYXRhLm1hcmtlci5vcGFjaXR5O1xuXG4gICAgc2NhdHRlck9wdGlvbnMgPSB7XG4gICAgICAgIGdsOiB0aGlzLnNjZW5lLmdscGxvdC5nbCxcbiAgICAgICAgcG9zaXRpb246IG9wdGlvbnMucG9zaXRpb24sXG4gICAgICAgIGNvbG9yOiBvcHRpb25zLnNjYXR0ZXJDb2xvcixcbiAgICAgICAgc2l6ZTogb3B0aW9ucy5zY2F0dGVyU2l6ZSxcbiAgICAgICAgZ2x5cGg6IG9wdGlvbnMuc2NhdHRlck1hcmtlcixcbiAgICAgICAgb3BhY2l0eTogc2NhdHRlck9wYWNpdHksXG4gICAgICAgIG9ydGhvZ3JhcGhpYzogdHJ1ZSxcbiAgICAgICAgbGluZVdpZHRoOiBvcHRpb25zLnNjYXR0ZXJMaW5lV2lkdGgsXG4gICAgICAgIGxpbmVDb2xvcjogb3B0aW9ucy5zY2F0dGVyTGluZUNvbG9yLFxuICAgICAgICBwcm9qZWN0OiBvcHRpb25zLnByb2plY3QsXG4gICAgICAgIHByb2plY3RTY2FsZTogb3B0aW9ucy5wcm9qZWN0U2NhbGUsXG4gICAgICAgIHByb2plY3RPcGFjaXR5OiBvcHRpb25zLnByb2plY3RPcGFjaXR5XG4gICAgfTtcblxuICAgIGlmKHRoaXMubW9kZS5pbmRleE9mKCdtYXJrZXJzJykgIT09IC0xKSB7XG4gICAgICAgIGlmKHRoaXMuc2NhdHRlclBsb3QpIHRoaXMuc2NhdHRlclBsb3QudXBkYXRlKHNjYXR0ZXJPcHRpb25zKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNjYXR0ZXJQbG90ID0gY3JlYXRlU2NhdHRlclBsb3Qoc2NhdHRlck9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5zY2F0dGVyUGxvdC5fdHJhY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5zY2F0dGVyUGxvdC5oaWdobGlnaHRTY2FsZSA9IDE7XG4gICAgICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5hZGQodGhpcy5zY2F0dGVyUGxvdCk7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYodGhpcy5zY2F0dGVyUGxvdCkge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5zY2F0dGVyUGxvdCk7XG4gICAgICAgIHRoaXMuc2NhdHRlclBsb3QuZGlzcG9zZSgpO1xuICAgICAgICB0aGlzLnNjYXR0ZXJQbG90ID0gbnVsbDtcbiAgICB9XG5cbiAgICB0ZXh0T3B0aW9ucyA9IHtcbiAgICAgICAgZ2w6IHRoaXMuc2NlbmUuZ2xwbG90LmdsLFxuICAgICAgICBwb3NpdGlvbjogb3B0aW9ucy5wb3NpdGlvbixcbiAgICAgICAgZ2x5cGg6IG9wdGlvbnMudGV4dCxcbiAgICAgICAgY29sb3I6IG9wdGlvbnMudGV4dENvbG9yLFxuICAgICAgICBzaXplOiBvcHRpb25zLnRleHRTaXplLFxuICAgICAgICBhbmdsZTogb3B0aW9ucy50ZXh0QW5nbGUsXG4gICAgICAgIGFsaWdubWVudDogb3B0aW9ucy50ZXh0T2Zmc2V0LFxuICAgICAgICBmb250OiBvcHRpb25zLnRleHRGb250LFxuICAgICAgICBvcnRob2dyYXBoaWM6IHRydWUsXG4gICAgICAgIGxpbmVXaWR0aDogMCxcbiAgICAgICAgcHJvamVjdDogZmFsc2UsXG4gICAgICAgIG9wYWNpdHk6IGRhdGEub3BhY2l0eVxuICAgIH07XG5cbiAgICB0aGlzLnRleHRMYWJlbHMgPSBkYXRhLmhvdmVydGV4dCB8fCBkYXRhLnRleHQ7XG5cbiAgICBpZih0aGlzLm1vZGUuaW5kZXhPZigndGV4dCcpICE9PSAtMSkge1xuICAgICAgICBpZih0aGlzLnRleHRNYXJrZXJzKSB0aGlzLnRleHRNYXJrZXJzLnVwZGF0ZSh0ZXh0T3B0aW9ucyk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy50ZXh0TWFya2VycyA9IGNyZWF0ZVNjYXR0ZXJQbG90KHRleHRPcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMudGV4dE1hcmtlcnMuX3RyYWNlID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMudGV4dE1hcmtlcnMuaGlnaGxpZ2h0U2NhbGUgPSAxO1xuICAgICAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QuYWRkKHRoaXMudGV4dE1hcmtlcnMpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmKHRoaXMudGV4dE1hcmtlcnMpIHtcbiAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QucmVtb3ZlKHRoaXMudGV4dE1hcmtlcnMpO1xuICAgICAgICB0aGlzLnRleHRNYXJrZXJzLmRpc3Bvc2UoKTtcbiAgICAgICAgdGhpcy50ZXh0TWFya2VycyA9IG51bGw7XG4gICAgfVxuXG4gICAgZXJyb3JPcHRpb25zID0ge1xuICAgICAgICBnbDogdGhpcy5zY2VuZS5nbHBsb3QuZ2wsXG4gICAgICAgIHBvc2l0aW9uOiBvcHRpb25zLnBvc2l0aW9uLFxuICAgICAgICBjb2xvcjogb3B0aW9ucy5lcnJvckNvbG9yLFxuICAgICAgICBlcnJvcjogb3B0aW9ucy5lcnJvckJvdW5kcyxcbiAgICAgICAgbGluZVdpZHRoOiBvcHRpb25zLmVycm9yTGluZVdpZHRoLFxuICAgICAgICBjYXBTaXplOiBvcHRpb25zLmVycm9yQ2FwU2l6ZSxcbiAgICAgICAgb3BhY2l0eTogZGF0YS5vcGFjaXR5XG4gICAgfTtcbiAgICBpZih0aGlzLmVycm9yQmFycykge1xuICAgICAgICBpZihvcHRpb25zLmVycm9yQm91bmRzKSB7XG4gICAgICAgICAgICB0aGlzLmVycm9yQmFycy51cGRhdGUoZXJyb3JPcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc2NlbmUuZ2xwbG90LnJlbW92ZSh0aGlzLmVycm9yQmFycyk7XG4gICAgICAgICAgICB0aGlzLmVycm9yQmFycy5kaXNwb3NlKCk7XG4gICAgICAgICAgICB0aGlzLmVycm9yQmFycyA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYob3B0aW9ucy5lcnJvckJvdW5kcykge1xuICAgICAgICB0aGlzLmVycm9yQmFycyA9IGNyZWF0ZUVycm9yQmFycyhlcnJvck9wdGlvbnMpO1xuICAgICAgICB0aGlzLmVycm9yQmFycy5fdHJhY2UgPSB0aGlzO1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5hZGQodGhpcy5lcnJvckJhcnMpO1xuICAgIH1cblxuICAgIGlmKG9wdGlvbnMuZGVsYXVuYXlBeGlzID49IDApIHtcbiAgICAgICAgdmFyIGRlbGF1bmF5T3B0aW9ucyA9IGNvbnN0cnVjdERlbGF1bmF5KFxuICAgICAgICAgICAgb3B0aW9ucy5wb3NpdGlvbixcbiAgICAgICAgICAgIG9wdGlvbnMuZGVsYXVuYXlDb2xvcixcbiAgICAgICAgICAgIG9wdGlvbnMuZGVsYXVuYXlBeGlzXG4gICAgICAgICk7XG4gICAgICAgIGRlbGF1bmF5T3B0aW9ucy5vcGFjaXR5ID0gZGF0YS5vcGFjaXR5O1xuXG4gICAgICAgIGlmKHRoaXMuZGVsYXVuYXlNZXNoKSB7XG4gICAgICAgICAgICB0aGlzLmRlbGF1bmF5TWVzaC51cGRhdGUoZGVsYXVuYXlPcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbGF1bmF5T3B0aW9ucy5nbCA9IGdsO1xuICAgICAgICAgICAgdGhpcy5kZWxhdW5heU1lc2ggPSBjcmVhdGVNZXNoKGRlbGF1bmF5T3B0aW9ucyk7XG4gICAgICAgICAgICB0aGlzLmRlbGF1bmF5TWVzaC5fdHJhY2UgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5zY2VuZS5nbHBsb3QuYWRkKHRoaXMuZGVsYXVuYXlNZXNoKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZih0aGlzLmRlbGF1bmF5TWVzaCkge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5kZWxhdW5heU1lc2gpO1xuICAgICAgICB0aGlzLmRlbGF1bmF5TWVzaC5kaXNwb3NlKCk7XG4gICAgICAgIHRoaXMuZGVsYXVuYXlNZXNoID0gbnVsbDtcbiAgICB9XG59O1xuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5saW5lUGxvdCkge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5saW5lUGxvdCk7XG4gICAgICAgIHRoaXMubGluZVBsb3QuZGlzcG9zZSgpO1xuICAgIH1cbiAgICBpZih0aGlzLnNjYXR0ZXJQbG90KSB7XG4gICAgICAgIHRoaXMuc2NlbmUuZ2xwbG90LnJlbW92ZSh0aGlzLnNjYXR0ZXJQbG90KTtcbiAgICAgICAgdGhpcy5zY2F0dGVyUGxvdC5kaXNwb3NlKCk7XG4gICAgfVxuICAgIGlmKHRoaXMuZXJyb3JCYXJzKSB7XG4gICAgICAgIHRoaXMuc2NlbmUuZ2xwbG90LnJlbW92ZSh0aGlzLmVycm9yQmFycyk7XG4gICAgICAgIHRoaXMuZXJyb3JCYXJzLmRpc3Bvc2UoKTtcbiAgICB9XG4gICAgaWYodGhpcy50ZXh0TWFya2Vycykge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy50ZXh0TWFya2Vycyk7XG4gICAgICAgIHRoaXMudGV4dE1hcmtlcnMuZGlzcG9zZSgpO1xuICAgIH1cbiAgICBpZih0aGlzLmRlbGF1bmF5TWVzaCkge1xuICAgICAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5kZWxhdW5heU1lc2gpO1xuICAgICAgICB0aGlzLmRlbGF1bmF5TWVzaC5kaXNwb3NlKCk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gY3JlYXRlTGluZVdpdGhNYXJrZXJzKHNjZW5lLCBkYXRhKSB7XG4gICAgdmFyIHBsb3QgPSBuZXcgTGluZVdpdGhNYXJrZXJzKHNjZW5lLCBkYXRhLnVpZCk7XG4gICAgcGxvdC51cGRhdGUoZGF0YSk7XG4gICAgcmV0dXJuIHBsb3Q7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlTGluZVdpdGhNYXJrZXJzO1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9nbDNkX2Rhc2hlc1wiOjY5MixcIi4uLy4uL2NvbnN0YW50cy9nbDNkX21hcmtlcnNcIjo2OTMsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZ2xfZm9ybWF0X2NvbG9yXCI6NzE2LFwiLi4vLi4vbGliL3N0cjJyZ2JhcnJheVwiOjc0MixcIi4uL3NjYXR0ZXIvbWFrZV9idWJibGVfc2l6ZV9mdW5jXCI6MTEyOCxcIi4vY2FsY19lcnJvcnNcIjoxMTQwLFwiZGVsYXVuYXktdHJpYW5ndWxhdGVcIjoxNjUsXCJnbC1lcnJvcjNkXCI6MjQ3LFwiZ2wtbGluZTNkXCI6MjU1LFwiZ2wtbWVzaDNkXCI6MjgwLFwiZ2wtc2NhdHRlcjNkXCI6Mjk3fV0sMTE0MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFJlZ2lzdHJ5ID0gX2RlcmVxXygnLi4vLi4vcmVnaXN0cnknKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIHN1YlR5cGVzID0gX2RlcmVxXygnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIGhhbmRsZU1hcmtlckRlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9tYXJrZXJfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVMaW5lRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2xpbmVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUZXh0RGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3RleHRfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVhZWkRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCk7XG4gICAgaWYoIWxlbikge1xuICAgICAgICB0cmFjZU91dC52aXNpYmxlID0gZmFsc2U7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuICAgIGNvZXJjZSgnbW9kZScpO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSB7XG4gICAgICAgIGNvZXJjZSgnY29ubmVjdGdhcHMnKTtcbiAgICAgICAgaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNNYXJrZXJzKHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVNYXJrZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSwge25vU2VsZWN0OiB0cnVlfSk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlVGV4dERlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge25vU2VsZWN0OiB0cnVlfSk7XG4gICAgfVxuXG4gICAgdmFyIGxpbmVDb2xvciA9ICh0cmFjZU91dC5saW5lIHx8IHt9KS5jb2xvcjtcbiAgICB2YXIgbWFya2VyQ29sb3IgPSAodHJhY2VPdXQubWFya2VyIHx8IHt9KS5jb2xvcjtcbiAgICBpZihjb2VyY2UoJ3N1cmZhY2VheGlzJykgPj0gMCkgY29lcmNlKCdzdXJmYWNlY29sb3InLCBsaW5lQ29sb3IgfHwgbWFya2VyQ29sb3IpO1xuXG4gICAgdmFyIGRpbXMgPSBbJ3gnLCAneScsICd6J107XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICB2YXIgcHJvamVjdGlvbiA9ICdwcm9qZWN0aW9uLicgKyBkaW1zW2ldO1xuICAgICAgICBpZihjb2VyY2UocHJvamVjdGlvbiArICcuc2hvdycpKSB7XG4gICAgICAgICAgICBjb2VyY2UocHJvamVjdGlvbiArICcub3BhY2l0eScpO1xuICAgICAgICAgICAgY29lcmNlKHByb2plY3Rpb24gKyAnLnNjYWxlJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZXJyb3JCYXJzU3VwcGx5RGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdzdXBwbHlEZWZhdWx0cycpO1xuICAgIGVycm9yQmFyc1N1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsaW5lQ29sb3IgfHwgbWFya2VyQ29sb3IgfHwgZGVmYXVsdENvbG9yLCB7YXhpczogJ3onfSk7XG4gICAgZXJyb3JCYXJzU3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxpbmVDb2xvciB8fCBtYXJrZXJDb2xvciB8fCBkZWZhdWx0Q29sb3IsIHtheGlzOiAneScsIGluaGVyaXQ6ICd6J30pO1xuICAgIGVycm9yQmFyc1N1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsaW5lQ29sb3IgfHwgbWFya2VyQ29sb3IgfHwgZGVmYXVsdENvbG9yLCB7YXhpczogJ3gnLCBpbmhlcml0OiAneid9KTtcbn07XG5cbmZ1bmN0aW9uIGhhbmRsZVhZWkRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UsIGxheW91dCkge1xuICAgIHZhciBsZW4gPSAwO1xuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIHkgPSBjb2VyY2UoJ3knKTtcbiAgICB2YXIgeiA9IGNvZXJjZSgneicpO1xuXG4gICAgdmFyIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdoYW5kbGVUcmFjZURlZmF1bHRzJyk7XG4gICAgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgWyd4JywgJ3knLCAneiddLCBsYXlvdXQpO1xuXG4gICAgaWYoeCAmJiB5ICYmIHopIHtcbiAgICAgICAgLy8gVE9ETzogd2hhdCBoYXBwZW5zIGlmIG9uZSBpcyBtaXNzaW5nP1xuICAgICAgICBsZW4gPSBNYXRoLm1pbih4Lmxlbmd0aCwgeS5sZW5ndGgsIHoubGVuZ3RoKTtcbiAgICAgICAgdHJhY2VPdXQuX2xlbmd0aCA9IHRyYWNlT3V0Ll94bGVuZ3RoID0gdHJhY2VPdXQuX3lsZW5ndGggPSB0cmFjZU91dC5femxlbmd0aCA9IGxlbjtcbiAgICB9XG5cbiAgICByZXR1cm4gbGVuO1xufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzXCI6MTEyNCxcIi4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzXCI6MTEzMCxcIi4uL3NjYXR0ZXIvc3VidHlwZXNcIjoxMTM1LFwiLi4vc2NhdHRlci90ZXh0X2RlZmF1bHRzXCI6MTEzNixcIi4vYXR0cmlidXRlc1wiOjExMzh9XSwxMTQzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgcGxvdDogX2RlcmVxXygnLi9jb252ZXJ0JyksXG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgbWFya2VyU3ltYm9sczogX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2dsM2RfbWFya2VycycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgY29sb3JiYXI6IFtcbiAgICAgICAge1xuICAgICAgICAgICAgY29udGFpbmVyOiAnbWFya2VyJyxcbiAgICAgICAgICAgIG1pbjogJ2NtaW4nLFxuICAgICAgICAgICAgbWF4OiAnY21heCdcbiAgICAgICAgfSwge1xuICAgICAgICAgICAgY29udGFpbmVyOiAnbGluZScsXG4gICAgICAgICAgICBtaW46ICdjbWluJyxcbiAgICAgICAgICAgIG1heDogJ2NtYXgnXG4gICAgICAgIH1cbiAgICBdLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLFxuXG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnc2NhdHRlcjNkJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2wzZCcpLFxuICAgIGNhdGVnb3JpZXM6IFsnZ2wzZCcsICdzeW1ib2xzJywgJ3Nob3dMZWdlbmQnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9nbDNkX21hcmtlcnNcIjo2OTMsXCIuLi8uLi9wbG90cy9nbDNkXCI6ODA3LFwiLi9hdHRyaWJ1dGVzXCI6MTEzOCxcIi4vY2FsY1wiOjExMzksXCIuL2NvbnZlcnRcIjoxMTQxLFwiLi9kZWZhdWx0c1wiOjExNDJ9XSwxMTQ0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJBdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIHBsb3RBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcbnZhciBob3ZlcnRlbXBsYXRlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlcycpO1xudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciBzY2F0dGVyTWFya2VyQXR0cnMgPSBzY2F0dGVyQXR0cnMubWFya2VyO1xudmFyIHNjYXR0ZXJMaW5lQXR0cnMgPSBzY2F0dGVyQXR0cnMubGluZTtcbnZhciBzY2F0dGVyTWFya2VyTGluZUF0dHJzID0gc2NhdHRlck1hcmtlckF0dHJzLmxpbmU7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGNhcnBldDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbW9kZTogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLm1vZGUsIHtkZmx0OiAnbWFya2Vycyd9KSxcbiAgICB0ZXh0OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMudGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcnRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5ob3ZlcnRleHQsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgbGluZToge1xuICAgICAgICBjb2xvcjogc2NhdHRlckxpbmVBdHRycy5jb2xvcixcbiAgICAgICAgd2lkdGg6IHNjYXR0ZXJMaW5lQXR0cnMud2lkdGgsXG4gICAgICAgIGRhc2g6IHNjYXR0ZXJMaW5lQXR0cnMuZGFzaCxcbiAgICAgICAgc2hhcGU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJMaW5lQXR0cnMuc2hhcGUsXG4gICAgICAgICAgICB7dmFsdWVzOiBbJ2xpbmVhcicsICdzcGxpbmUnXX0pLFxuICAgICAgICBzbW9vdGhpbmc6IHNjYXR0ZXJMaW5lQXR0cnMuc21vb3RoaW5nLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcbiAgICBjb25uZWN0Z2Fwczogc2NhdHRlckF0dHJzLmNvbm5lY3RnYXBzLFxuICAgIGZpbGw6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5maWxsLCB7XG4gICAgICAgIHZhbHVlczogWydub25lJywgJ3Rvc2VsZicsICd0b25leHQnXSxcbiAgICAgICAgZGZsdDogJ25vbmUnLFxuICAgICAgICBcbiAgICB9KSxcbiAgICBmaWxsY29sb3I6IHNjYXR0ZXJBdHRycy5maWxsY29sb3IsXG4gICAgbWFya2VyOiBleHRlbmRGbGF0KHtcbiAgICAgICAgc3ltYm9sOiBzY2F0dGVyTWFya2VyQXR0cnMuc3ltYm9sLFxuICAgICAgICBvcGFjaXR5OiBzY2F0dGVyTWFya2VyQXR0cnMub3BhY2l0eSxcbiAgICAgICAgbWF4ZGlzcGxheWVkOiBzY2F0dGVyTWFya2VyQXR0cnMubWF4ZGlzcGxheWVkLFxuICAgICAgICBzaXplOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZSxcbiAgICAgICAgc2l6ZXJlZjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVyZWYsXG4gICAgICAgIHNpemVtaW46IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplbWluLFxuICAgICAgICBzaXplbW9kZTogc2NhdHRlck1hcmtlckF0dHJzLnNpemVtb2RlLFxuICAgICAgICBsaW5lOiBleHRlbmRGbGF0KHtcbiAgICAgICAgICAgIHdpZHRoOiBzY2F0dGVyTWFya2VyTGluZUF0dHJzLndpZHRoLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3JTY2FsZUF0dHJzKCdtYXJrZXIubGluZScpXG4gICAgICAgICksXG4gICAgICAgIGdyYWRpZW50OiBzY2F0dGVyTWFya2VyQXR0cnMuZ3JhZGllbnQsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgICAgICBjb2xvclNjYWxlQXR0cnMoJ21hcmtlcicpXG4gICAgKSxcblxuICAgIHRleHRmb250OiBzY2F0dGVyQXR0cnMudGV4dGZvbnQsXG4gICAgdGV4dHBvc2l0aW9uOiBzY2F0dGVyQXR0cnMudGV4dHBvc2l0aW9uLFxuXG4gICAgc2VsZWN0ZWQ6IHNjYXR0ZXJBdHRycy5zZWxlY3RlZCxcbiAgICB1bnNlbGVjdGVkOiBzY2F0dGVyQXR0cnMudW5zZWxlY3RlZCxcblxuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgcGxvdEF0dHJzLmhvdmVyaW5mbywge1xuICAgICAgICBmbGFnczogWydhJywgJ2InLCAndGV4dCcsICduYW1lJ11cbiAgICB9KSxcbiAgICBob3Zlcm9uOiBzY2F0dGVyQXR0cnMuaG92ZXJvbixcbiAgICBob3ZlcnRlbXBsYXRlOiBob3ZlcnRlbXBsYXRlQXR0cnMoKVxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9zY2F0dGVyL2F0dHJpYnV0ZXNcIjoxMTEyfV0sMTE0NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbnZhciBjYWxjQ29sb3JzY2FsZSA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjJyk7XG52YXIgYXJyYXlzVG9DYWxjZGF0YSA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvYXJyYXlzX3RvX2NhbGNkYXRhJyk7XG52YXIgY2FsY1NlbGVjdGlvbiA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb24nKTtcbnZhciBjYWxjTWFya2VyU2l6ZSA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY2FsYycpLmNhbGNNYXJrZXJTaXplO1xudmFyIGxvb2t1cENhcnBldCA9IF9kZXJlcV8oJy4uL2NhcnBldC9sb29rdXBfY2FycGV0aWQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBjYXJwZXQgPSB0cmFjZS5fY2FycGV0VHJhY2UgPSBsb29rdXBDYXJwZXQoZ2QsIHRyYWNlKTtcbiAgICBpZighY2FycGV0IHx8ICFjYXJwZXQudmlzaWJsZSB8fCBjYXJwZXQudmlzaWJsZSA9PT0gJ2xlZ2VuZG9ubHknKSByZXR1cm47XG4gICAgdmFyIGk7XG5cbiAgICAvLyBUcmFuc2ZlciB0aGlzIG92ZXIgZnJvbSBjYXJwZXQgYmVmb3JlIHBsb3R0aW5nIHNpbmNlIHRoaXMgaXMgYSBuZWNlc3NhcnlcbiAgICAvLyBjb25kaXRpb24gaW4gb3JkZXIgZm9yIGNhcnRlc2lhbiB0byBhY3R1YWxseSBwbG90IHRoaXMgdHJhY2U6XG4gICAgdHJhY2UueGF4aXMgPSBjYXJwZXQueGF4aXM7XG4gICAgdHJhY2UueWF4aXMgPSBjYXJwZXQueWF4aXM7XG5cbiAgICAvLyBtYWtlIHRoZSBjYWxjZGF0YSBhcnJheVxuICAgIHZhciBzZXJpZXNsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgIHZhciBjZCA9IG5ldyBBcnJheShzZXJpZXNsZW4pO1xuICAgIHZhciBhLCBiO1xuICAgIHZhciBuZWVkc0N1bGwgPSBmYWxzZTtcbiAgICBmb3IoaSA9IDA7IGkgPCBzZXJpZXNsZW47IGkrKykge1xuICAgICAgICBhID0gdHJhY2UuYVtpXTtcbiAgICAgICAgYiA9IHRyYWNlLmJbaV07XG4gICAgICAgIGlmKGlzTnVtZXJpYyhhKSAmJiBpc051bWVyaWMoYikpIHtcbiAgICAgICAgICAgIHZhciB4eSA9IGNhcnBldC5hYjJ4eSgrYSwgK2IsIHRydWUpO1xuICAgICAgICAgICAgdmFyIHZpc2libGUgPSBjYXJwZXQuaXNWaXNpYmxlKCthLCArYik7XG4gICAgICAgICAgICBpZighdmlzaWJsZSkgbmVlZHNDdWxsID0gdHJ1ZTtcbiAgICAgICAgICAgIGNkW2ldID0ge3g6IHh5WzBdLCB5OiB4eVsxXSwgYTogYSwgYjogYiwgdmlzOiB2aXNpYmxlfTtcbiAgICAgICAgfSBlbHNlIGNkW2ldID0ge3g6IGZhbHNlLCB5OiBmYWxzZX07XG4gICAgfVxuXG4gICAgdHJhY2UuX25lZWRzQ3VsbCA9IG5lZWRzQ3VsbDtcblxuICAgIGNkWzBdLmNhcnBldCA9IGNhcnBldDtcbiAgICBjZFswXS50cmFjZSA9IHRyYWNlO1xuXG4gICAgY2FsY01hcmtlclNpemUodHJhY2UsIHNlcmllc2xlbik7XG4gICAgY2FsY0NvbG9yc2NhbGUoZ2QsIHRyYWNlKTtcbiAgICBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSk7XG4gICAgY2FsY1NlbGVjdGlvbihjZCwgdHJhY2UpO1xuXG4gICAgcmV0dXJuIGNkO1xufTtcblxufSx7XCIuLi9jYXJwZXQvbG9va3VwX2NhcnBldGlkXCI6OTE1LFwiLi4vc2NhdHRlci9hcnJheXNfdG9fY2FsY2RhdGFcIjoxMTExLFwiLi4vc2NhdHRlci9jYWxjXCI6MTExMyxcIi4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb25cIjoxMTE0LFwiLi4vc2NhdHRlci9jb2xvcnNjYWxlX2NhbGNcIjoxMTE1LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSwxMTQ2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NvbnN0YW50cycpO1xudmFyIHN1YlR5cGVzID0gX2RlcmVxXygnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIGhhbmRsZU1hcmtlckRlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9tYXJrZXJfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVMaW5lRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2xpbmVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVMaW5lU2hhcGVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbGluZV9zaGFwZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRleHREZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdjYXJwZXQnKTtcblxuICAgIC8vIFhYWDogRG9uJ3QgaGFyZCBjb2RlIHRoaXNcbiAgICB0cmFjZU91dC54YXhpcyA9ICd4JztcbiAgICB0cmFjZU91dC55YXhpcyA9ICd5JztcblxuICAgIHZhciBhID0gY29lcmNlKCdhJyk7XG4gICAgdmFyIGIgPSBjb2VyY2UoJ2InKTtcbiAgICB2YXIgbGVuID0gTWF0aC5taW4oYS5sZW5ndGgsIGIubGVuZ3RoKTtcblxuICAgIGlmKCFsZW4pIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG5cbiAgICB2YXIgZGVmYXVsdE1vZGUgPSBsZW4gPCBjb25zdGFudHMuUFRTX0xJTkVTT05MWSA/ICdsaW5lcyttYXJrZXJzJyA6ICdsaW5lcyc7XG4gICAgY29lcmNlKCdtb2RlJywgZGVmYXVsdE1vZGUpO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZUxpbmVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgICAgIGhhbmRsZUxpbmVTaGFwZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UpO1xuICAgICAgICBjb2VyY2UoJ2Nvbm5lY3RnYXBzJyk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTWFya2VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UsIHtncmFkaWVudDogdHJ1ZX0pO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc1RleHQodHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZVRleHREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuICAgIH1cblxuICAgIHZhciBkZmx0SG92ZXJPbiA9IFtdO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkgfHwgc3ViVHlwZXMuaGFzVGV4dCh0cmFjZU91dCkpIHtcbiAgICAgICAgY29lcmNlKCdtYXJrZXIubWF4ZGlzcGxheWVkJyk7XG4gICAgICAgIGRmbHRIb3Zlck9uLnB1c2goJ3BvaW50cycpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnZmlsbCcpO1xuICAgIGlmKHRyYWNlT3V0LmZpbGwgIT09ICdub25lJykge1xuICAgICAgICBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBjb2VyY2UpO1xuICAgICAgICBpZighc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSBoYW5kbGVMaW5lU2hhcGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBpZih0cmFjZU91dC5maWxsID09PSAndG9uZXh0JyB8fCB0cmFjZU91dC5maWxsID09PSAndG9zZWxmJykge1xuICAgICAgICBkZmx0SG92ZXJPbi5wdXNoKCdmaWxscycpO1xuICAgIH1cblxuICAgIHZhciBob3Zlck9uID0gY29lcmNlKCdob3Zlcm9uJywgZGZsdEhvdmVyT24uam9pbignKycpIHx8ICdwb2ludHMnKTtcbiAgICBpZihob3Zlck9uICE9PSAnZmlsbHMnKSBjb2VyY2UoJ2hvdmVydGVtcGxhdGUnKTtcblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi9zY2F0dGVyL2NvbnN0YW50c1wiOjExMTYsXCIuLi9zY2F0dGVyL2ZpbGxjb2xvcl9kZWZhdWx0c1wiOjExMjAsXCIuLi9zY2F0dGVyL2xpbmVfZGVmYXVsdHNcIjoxMTI0LFwiLi4vc2NhdHRlci9saW5lX3NoYXBlX2RlZmF1bHRzXCI6MTEyNixcIi4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzXCI6MTEzMCxcIi4uL3NjYXR0ZXIvc3VidHlwZXNcIjoxMTM1LFwiLi4vc2NhdHRlci90ZXh0X2RlZmF1bHRzXCI6MTEzNixcIi4vYXR0cmlidXRlc1wiOjExNDR9XSwxMTQ3OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBldmVudERhdGEob3V0LCBwdCwgdHJhY2UsIGNkLCBwb2ludE51bWJlcikge1xuICAgIHZhciBjZGkgPSBjZFtwb2ludE51bWJlcl07XG5cbiAgICBvdXQuYSA9IGNkaS5hO1xuICAgIG91dC5iID0gY2RpLmI7XG4gICAgb3V0LnkgPSBjZGkueTtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG59LHt9XSwxMTQ4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJIb3ZlciA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvaG92ZXInKTtcbnZhciBmaWxsVGV4dCA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmZpbGxUZXh0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIHNjYXR0ZXJQb2ludERhdGEgPSBzY2F0dGVySG92ZXIocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpO1xuICAgIGlmKCFzY2F0dGVyUG9pbnREYXRhIHx8IHNjYXR0ZXJQb2ludERhdGFbMF0uaW5kZXggPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICB2YXIgbmV3UG9pbnREYXRhID0gc2NhdHRlclBvaW50RGF0YVswXTtcblxuICAgIC8vIGlmIGhvdmVyaW5nIG9uIGEgZmlsbCwgd2UgZG9uJ3Qgc2hvdyBhbnkgcG9pbnQgZGF0YSBzbyB0aGUgbGFiZWwgaXNcbiAgICAvLyB1bmNoYW5nZWQgZnJvbSB3aGF0IHNjYXR0ZXIgZ2l2ZXMgdXMgLSBleGNlcHQgdGhhdCBpdCBuZWVkcyB0b1xuICAgIC8vIGJlIGNvbnN0cmFpbmVkIHRvIHRoZSB0cmlhbmdsdWxhciBwbG90IGFyZWEsIG5vdCBqdXN0IHRoZSByZWN0YW5ndWxhclxuICAgIC8vIGFyZWEgZGVmaW5lZCBieSB0aGUgc3ludGhldGljIHggYW5kIHkgYXhlc1xuICAgIC8vIFRPRE86IGluIHNvbWUgY2FzZXMgdGhlIHZlcnRpY2FsIG1pZGRsZSBvZiB0aGUgc2hhcGUgaXMgbm90IHdpdGhpblxuICAgIC8vIHRoZSB0cmlhbmd1bGFyIHZpZXdwb3J0IGF0IGFsbCwgc28gdGhlIGxhYmVsIGNhbiBiZWNvbWUgZGlzY29ubmVjdGVkXG4gICAgLy8gZnJvbSB0aGUgc2hhcGUgZW50aXJlbHkuIEJ1dCBjYWxjdWxhdGluZyB3aGF0IHBvcnRpb24gb2YgdGhlIHNoYXBlXG4gICAgLy8gaXMgYWN0dWFsbHkgdmlzaWJsZSwgYXMgY29uc3RyYWluZWQgYnkgdGhlIGRpYWdvbmFsIGF4aXMgbGluZXMsIGlzIG5vdFxuICAgIC8vIHNvIGVhc3kgYW5kIGFueXdheSB3ZSBsb3N0IHRoZSBpbmZvcm1hdGlvbiB3ZSB3b3VsZCBoYXZlIG5lZWRlZCB0byBkb1xuICAgIC8vIHRoaXMgaW5zaWRlIHNjYXR0ZXJIb3Zlci5cbiAgICBpZihuZXdQb2ludERhdGEuaW5kZXggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB2YXIgeUZyYWNVcCA9IDEgLSAobmV3UG9pbnREYXRhLnkwIC8gcG9pbnREYXRhLnlhLl9sZW5ndGgpO1xuICAgICAgICB2YXIgeExlbiA9IHBvaW50RGF0YS54YS5fbGVuZ3RoO1xuICAgICAgICB2YXIgeE1pbiA9IHhMZW4gKiB5RnJhY1VwIC8gMjtcbiAgICAgICAgdmFyIHhNYXggPSB4TGVuIC0geE1pbjtcbiAgICAgICAgbmV3UG9pbnREYXRhLngwID0gTWF0aC5tYXgoTWF0aC5taW4obmV3UG9pbnREYXRhLngwLCB4TWF4KSwgeE1pbik7XG4gICAgICAgIG5ld1BvaW50RGF0YS54MSA9IE1hdGgubWF4KE1hdGgubWluKG5ld1BvaW50RGF0YS54MSwgeE1heCksIHhNaW4pO1xuICAgICAgICByZXR1cm4gc2NhdHRlclBvaW50RGF0YTtcbiAgICB9XG5cbiAgICB2YXIgY2RpID0gbmV3UG9pbnREYXRhLmNkW25ld1BvaW50RGF0YS5pbmRleF07XG5cbiAgICBuZXdQb2ludERhdGEuYSA9IGNkaS5hO1xuICAgIG5ld1BvaW50RGF0YS5iID0gY2RpLmI7XG5cbiAgICBuZXdQb2ludERhdGEueExhYmVsVmFsID0gdW5kZWZpbmVkO1xuICAgIG5ld1BvaW50RGF0YS55TGFiZWxWYWwgPSB1bmRlZmluZWQ7XG4gICAgLy8gVE9ETzogbmljZSBmb3JtYXR0aW5nLCBhbmQgbGFiZWwgYnkgYXhpcyB0aXRsZSwgZm9yIGEsIGIsIGFuZCBjP1xuXG4gICAgdmFyIHRyYWNlID0gbmV3UG9pbnREYXRhLnRyYWNlO1xuICAgIHZhciBjYXJwZXQgPSB0cmFjZS5fY2FycGV0O1xuXG4gICAgdmFyIGlqID0gY2FycGV0LmFiMmlqKFtjZGkuYSwgY2RpLmJdKTtcbiAgICB2YXIgaTAgPSBNYXRoLmZsb29yKGlqWzBdKTtcbiAgICB2YXIgdGkgPSBpalswXSAtIGkwO1xuICAgIHZhciBqMCA9IE1hdGguZmxvb3IoaWpbMV0pO1xuICAgIHZhciB0aiA9IGlqWzFdIC0gajA7XG4gICAgdmFyIHh5ID0gY2FycGV0LmV2YWx4eShbXSwgaTAsIGowLCB0aSwgdGopO1xuICAgIG5ld1BvaW50RGF0YS55TGFiZWwgPSB4eVsxXS50b0ZpeGVkKDMpO1xuXG4gICAgZGVsZXRlIG5ld1BvaW50RGF0YS50ZXh0O1xuICAgIHZhciB0ZXh0ID0gW107XG5cbiAgICBmdW5jdGlvbiB0ZXh0UGFydChheCwgdmFsKSB7XG4gICAgICAgIHZhciBwcmVmaXg7XG5cbiAgICAgICAgaWYoYXgubGFiZWxwcmVmaXggJiYgYXgubGFiZWxwcmVmaXgubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcHJlZml4ID0gYXgubGFiZWxwcmVmaXgucmVwbGFjZSgvID0gJC8sICcnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByZWZpeCA9IGF4Ll9ob3ZlcnRpdGxlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGV4dC5wdXNoKHByZWZpeCArICc6ICcgKyB2YWwudG9GaXhlZCgzKSArIGF4LmxhYmVsc3VmZml4KTtcbiAgICB9XG5cblxuICAgIGlmKCF0cmFjZS5ob3ZlcnRlbXBsYXRlKSB7XG4gICAgICAgIHZhciBob3ZlcmluZm8gPSBjZGkuaGkgfHwgdHJhY2UuaG92ZXJpbmZvO1xuICAgICAgICB2YXIgcGFydHMgPSBob3ZlcmluZm8uc3BsaXQoJysnKTtcblxuICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCdhbGwnKSAhPT0gLTEpIHBhcnRzID0gWydhJywgJ2InLCAndGV4dCddO1xuICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCdhJykgIT09IC0xKSB0ZXh0UGFydChjYXJwZXQuYWF4aXMsIGNkaS5hKTtcbiAgICAgICAgaWYocGFydHMuaW5kZXhPZignYicpICE9PSAtMSkgdGV4dFBhcnQoY2FycGV0LmJheGlzLCBjZGkuYik7XG5cbiAgICAgICAgdGV4dC5wdXNoKCd5OiAnICsgbmV3UG9pbnREYXRhLnlMYWJlbCk7XG5cbiAgICAgICAgaWYocGFydHMuaW5kZXhPZigndGV4dCcpICE9PSAtMSkge1xuICAgICAgICAgICAgZmlsbFRleHQoY2RpLCB0cmFjZSwgdGV4dCk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdQb2ludERhdGEuZXh0cmFUZXh0ID0gdGV4dC5qb2luKCc8YnI+Jyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNjYXR0ZXJQb2ludERhdGE7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL3NjYXR0ZXIvaG92ZXJcIjoxMTIyfV0sMTE0OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgY29sb3JiYXI6IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbWFya2VyX2NvbG9yYmFyJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JyksXG4gICAgc3R5bGU6IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3R5bGUnKS5zdHlsZSxcbiAgICBzdHlsZU9uU2VsZWN0OiBfZGVyZXFfKCcuLi9zY2F0dGVyL3N0eWxlJykuc3R5bGVPblNlbGVjdCxcbiAgICBob3ZlclBvaW50czogX2RlcmVxXygnLi9ob3ZlcicpLFxuICAgIHNlbGVjdFBvaW50czogX2RlcmVxXygnLi4vc2NhdHRlci9zZWxlY3QnKSxcbiAgICBldmVudERhdGE6IF9kZXJlcV8oJy4vZXZlbnRfZGF0YScpLFxuXG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnc2NhdHRlcmNhcnBldCcsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnc3ZnJywgJ2NhcnBldCcsICdzeW1ib2xzJywgJ3Nob3dMZWdlbmQnLCAnY2FycGV0RGVwZW5kZW50JywgJ3pvb21TY2FsZSddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvY2FydGVzaWFuXCI6Nzc4LFwiLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXJcIjoxMTI5LFwiLi4vc2NhdHRlci9zZWxlY3RcIjoxMTMyLFwiLi4vc2NhdHRlci9zdHlsZVwiOjExMzQsXCIuL2F0dHJpYnV0ZXNcIjoxMTQ0LFwiLi9jYWxjXCI6MTE0NSxcIi4vZGVmYXVsdHNcIjoxMTQ2LFwiLi9ldmVudF9kYXRhXCI6MTE0NyxcIi4vaG92ZXJcIjoxMTQ4LFwiLi9wbG90XCI6MTE1MH1dLDExNTA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyUGxvdCA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvcGxvdCcpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBwbG90aW5mb3Byb3h5LCBkYXRhLCBsYXllcikge1xuICAgIHZhciBpLCB0cmFjZSwgbm9kZTtcblxuICAgIHZhciBjYXJwZXQgPSBkYXRhWzBdWzBdLmNhcnBldDtcbiAgICAvLyBtaW1pYyBjYXJ0ZXNpYW4gcGxvdGluZm9cbiAgICB2YXIgcGxvdGluZm8gPSB7XG4gICAgICAgIHhheGlzOiBBeGVzLmdldEZyb21JZChnZCwgY2FycGV0LnhheGlzIHx8ICd4JyksXG4gICAgICAgIHlheGlzOiBBeGVzLmdldEZyb21JZChnZCwgY2FycGV0LnlheGlzIHx8ICd5JyksXG4gICAgICAgIHBsb3Q6IHBsb3RpbmZvcHJveHkucGxvdCxcbiAgICB9O1xuXG4gICAgc2NhdHRlclBsb3QoZ2QsIHBsb3RpbmZvLCBkYXRhLCBsYXllcik7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRyYWNlID0gZGF0YVtpXVswXS50cmFjZTtcblxuICAgICAgICAvLyBOb3RlOiAuc2VsZWN0IGlzIGFkZXF1YXRlIGJ1dCBzZWVtcyB0byBtdXRhdGUgdGhlIG5vZGUgZGF0YSxcbiAgICAgICAgLy8gd2hpY2ggaXMgYXQgbGVhc3QgYSBiaXQgc3VwcmlzaW5nIGFuZCBjYXVzZXMgcHJvYmxlbXMgZWxzZXdoZXJlXG4gICAgICAgIG5vZGUgPSBsYXllci5zZWxlY3RBbGwoJ2cudHJhY2UnICsgdHJhY2UudWlkICsgJyAuanMtbGluZScpO1xuXG4gICAgICAgIC8vIE5vdGU6IGl0IHdvdWxkIGJlIG1vcmUgZWZmaWNpZW50IGlmIHRoaXMgZGlkbid0IG5lZWQgdG8gYmUgYXBwbGllZFxuICAgICAgICAvLyBzZXBhcmF0ZWx5IHRvIGFsbCBzY2F0dGVyY2FycGV0IHRyYWNlcywgYnV0IHRoYXQgd291bGQgcmVxdWlyZVxuICAgICAgICAvLyBsb3RzIG9mIHJlb3JnYW5pemF0aW9uIG9mIHNjYXR0ZXIgdHJhY2VzIHRoYXQgaXMgb3RoZXJ3aXNlIG5vdFxuICAgICAgICAvLyBuZWNlc3NhcnkuIFRoYXQgbWFrZXMgdGhpcyBhIHBvdGVudGlhbCBvcHRpbWl6YXRpb24uXG4gICAgICAgIERyYXdpbmcuc2V0Q2xpcFVybChub2RlLCBkYXRhW2ldWzBdLmNhcnBldC5fY2xpcFBhdGhJZCwgZ2QpO1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi9zY2F0dGVyL3Bsb3RcIjoxMTMxfV0sMTE1MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBob3ZlcnRlbXBsYXRlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJBdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIHBsb3RBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvckF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGRhc2ggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcvYXR0cmlidXRlcycpLmRhc2g7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbnZhciBzY2F0dGVyTWFya2VyQXR0cnMgPSBzY2F0dGVyQXR0cnMubWFya2VyO1xudmFyIHNjYXR0ZXJMaW5lQXR0cnMgPSBzY2F0dGVyQXR0cnMubGluZTtcbnZhciBzY2F0dGVyTWFya2VyTGluZUF0dHJzID0gc2NhdHRlck1hcmtlckF0dHJzLmxpbmU7XG5cbm1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoe1xuICAgIGxvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbGF0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGxvY2F0aW9uczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgbG9jYXRpb25tb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ0lTTy0zJywgJ1VTQS1zdGF0ZXMnLCAnY291bnRyeSBuYW1lcyddLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJ0lTTy0zJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIG1vZGU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5tb2RlLCB7ZGZsdDogJ21hcmtlcnMnfSksXG5cbiAgICB0ZXh0OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMudGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcnRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5ob3ZlcnRleHQsIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICB0ZXh0Zm9udDogc2NhdHRlckF0dHJzLnRleHRmb250LFxuICAgIHRleHRwb3NpdGlvbjogc2NhdHRlckF0dHJzLnRleHRwb3NpdGlvbixcblxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IHNjYXR0ZXJMaW5lQXR0cnMuY29sb3IsXG4gICAgICAgIHdpZHRoOiBzY2F0dGVyTGluZUF0dHJzLndpZHRoLFxuICAgICAgICBkYXNoOiBkYXNoXG4gICAgfSxcbiAgICBjb25uZWN0Z2Fwczogc2NhdHRlckF0dHJzLmNvbm5lY3RnYXBzLFxuXG4gICAgbWFya2VyOiBleHRlbmRGbGF0KHtcbiAgICAgICAgc3ltYm9sOiBzY2F0dGVyTWFya2VyQXR0cnMuc3ltYm9sLFxuICAgICAgICBvcGFjaXR5OiBzY2F0dGVyTWFya2VyQXR0cnMub3BhY2l0eSxcbiAgICAgICAgc2l6ZTogc2NhdHRlck1hcmtlckF0dHJzLnNpemUsXG4gICAgICAgIHNpemVyZWY6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplcmVmLFxuICAgICAgICBzaXplbWluOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZW1pbixcbiAgICAgICAgc2l6ZW1vZGU6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplbW9kZSxcbiAgICAgICAgY29sb3JiYXI6IHNjYXR0ZXJNYXJrZXJBdHRycy5jb2xvcmJhcixcbiAgICAgICAgbGluZTogZXh0ZW5kRmxhdCh7XG4gICAgICAgICAgICB3aWR0aDogc2NhdHRlck1hcmtlckxpbmVBdHRycy53aWR0aFxuICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3JBdHRyaWJ1dGVzKCdtYXJrZXIubGluZScpXG4gICAgICAgICksXG4gICAgICAgIGdyYWRpZW50OiBzY2F0dGVyTWFya2VyQXR0cnMuZ3JhZGllbnRcbiAgICB9LFxuICAgICAgICBjb2xvckF0dHJpYnV0ZXMoJ21hcmtlcicpXG4gICAgKSxcblxuICAgIGZpbGw6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnbm9uZScsICd0b3NlbGYnXSxcbiAgICAgICAgZGZsdDogJ25vbmUnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcbiAgICBmaWxsY29sb3I6IHNjYXR0ZXJBdHRycy5maWxsY29sb3IsXG5cbiAgICBzZWxlY3RlZDogc2NhdHRlckF0dHJzLnNlbGVjdGVkLFxuICAgIHVuc2VsZWN0ZWQ6IHNjYXR0ZXJBdHRycy51bnNlbGVjdGVkLFxuXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBwbG90QXR0cnMuaG92ZXJpbmZvLCB7XG4gICAgICAgIGZsYWdzOiBbJ2xvbicsICdsYXQnLCAnbG9jYXRpb24nLCAndGV4dCcsICduYW1lJ11cbiAgICB9KSxcbiAgICBob3ZlcnRlbXBsYXRlOiBob3ZlcnRlbXBsYXRlQXR0cnMoKSxcbn0sICdjYWxjJywgJ25lc3RlZCcpO1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzXCI6NjAwLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nL2F0dHJpYnV0ZXNcIjo2MTMsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NCxcIi4uL3NjYXR0ZXIvYXR0cmlidXRlc1wiOjExMTJ9XSwxMTUyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG52YXIgY2FsY01hcmtlckNvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NvbG9yc2NhbGVfY2FsYycpO1xudmFyIGFycmF5c1RvQ2FsY2RhdGEgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2FycmF5c190b19jYWxjZGF0YScpO1xudmFyIGNhbGNTZWxlY3Rpb24gPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NhbGNfc2VsZWN0aW9uJyk7XG5cbnZhciBfID0gX2RlcmVxXygnLi4vLi4vbGliJykuXztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBoYXNMb2NhdGlvbkRhdGEgPSBBcnJheS5pc0FycmF5KHRyYWNlLmxvY2F0aW9ucyk7XG4gICAgdmFyIGxlbiA9IGhhc0xvY2F0aW9uRGF0YSA/IHRyYWNlLmxvY2F0aW9ucy5sZW5ndGggOiB0cmFjZS5fbGVuZ3RoO1xuICAgIHZhciBjYWxjVHJhY2UgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgY2FsY1B0ID0gY2FsY1RyYWNlW2ldID0ge307XG5cbiAgICAgICAgaWYoaGFzTG9jYXRpb25EYXRhKSB7XG4gICAgICAgICAgICB2YXIgbG9jID0gdHJhY2UubG9jYXRpb25zW2ldO1xuICAgICAgICAgICAgY2FsY1B0LmxvYyA9IHR5cGVvZiBsb2MgPT09ICdzdHJpbmcnID8gbG9jIDogbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBsb24gPSB0cmFjZS5sb25baV07XG4gICAgICAgICAgICB2YXIgbGF0ID0gdHJhY2UubGF0W2ldO1xuXG4gICAgICAgICAgICBpZihpc051bWVyaWMobG9uKSAmJiBpc051bWVyaWMobGF0KSkgY2FsY1B0LmxvbmxhdCA9IFsrbG9uLCArbGF0XTtcbiAgICAgICAgICAgIGVsc2UgY2FsY1B0LmxvbmxhdCA9IFtCQUROVU0sIEJBRE5VTV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhcnJheXNUb0NhbGNkYXRhKGNhbGNUcmFjZSwgdHJhY2UpO1xuICAgIGNhbGNNYXJrZXJDb2xvcnNjYWxlKGdkLCB0cmFjZSk7XG4gICAgY2FsY1NlbGVjdGlvbihjYWxjVHJhY2UsIHRyYWNlKTtcblxuICAgIGlmKGxlbikge1xuICAgICAgICBjYWxjVHJhY2VbMF0udCA9IHtcbiAgICAgICAgICAgIGxhYmVsczoge1xuICAgICAgICAgICAgICAgIGxhdDogXyhnZCwgJ2xhdDonKSArICcgJyxcbiAgICAgICAgICAgICAgICBsb246IF8oZ2QsICdsb246JykgKyAnICdcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2FsY1RyYWNlO1xufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vc2NhdHRlci9hcnJheXNfdG9fY2FsY2RhdGFcIjoxMTExLFwiLi4vc2NhdHRlci9jYWxjX3NlbGVjdGlvblwiOjExMTQsXCIuLi9zY2F0dGVyL2NvbG9yc2NhbGVfY2FsY1wiOjExMTUsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDExNTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIHN1YlR5cGVzID0gX2RlcmVxXygnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIGhhbmRsZU1hcmtlckRlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9tYXJrZXJfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVMaW5lRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2xpbmVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUZXh0RGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3RleHRfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvZmlsbGNvbG9yX2RlZmF1bHRzJyk7XG5cbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZUxvbkxhdExvY0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UpO1xuICAgIGlmKCFsZW4pIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGVtcGxhdGUnKTtcbiAgICBjb2VyY2UoJ21vZGUnKTtcblxuICAgIGlmKHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVMaW5lRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpO1xuICAgICAgICBjb2VyY2UoJ2Nvbm5lY3RnYXBzJyk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTWFya2VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UsIHtncmFkaWVudDogdHJ1ZX0pO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc1RleHQodHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZVRleHREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnZmlsbCcpO1xuICAgIGlmKHRyYWNlT3V0LmZpbGwgIT09ICdub25lJykge1xuICAgICAgICBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBjb2VyY2UpO1xuICAgIH1cblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufTtcblxuZnVuY3Rpb24gaGFuZGxlTG9uTGF0TG9jRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSkge1xuICAgIHZhciBsZW4gPSAwO1xuICAgIHZhciBsb2NhdGlvbnMgPSBjb2VyY2UoJ2xvY2F0aW9ucycpO1xuXG4gICAgdmFyIGxvbiwgbGF0O1xuXG4gICAgaWYobG9jYXRpb25zKSB7XG4gICAgICAgIGNvZXJjZSgnbG9jYXRpb25tb2RlJyk7XG4gICAgICAgIGxlbiA9IGxvY2F0aW9ucy5sZW5ndGg7XG4gICAgICAgIHJldHVybiBsZW47XG4gICAgfVxuXG4gICAgbG9uID0gY29lcmNlKCdsb24nKSB8fCBbXTtcbiAgICBsYXQgPSBjb2VyY2UoJ2xhdCcpIHx8IFtdO1xuICAgIGxlbiA9IE1hdGgubWluKGxvbi5sZW5ndGgsIGxhdC5sZW5ndGgpO1xuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBsZW47XG5cbiAgICByZXR1cm4gbGVuO1xufVxuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL3NjYXR0ZXIvZmlsbGNvbG9yX2RlZmF1bHRzXCI6MTEyMCxcIi4uL3NjYXR0ZXIvbGluZV9kZWZhdWx0c1wiOjExMjQsXCIuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0c1wiOjExMzAsXCIuLi9zY2F0dGVyL3N1YnR5cGVzXCI6MTEzNSxcIi4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0c1wiOjExMzYsXCIuL2F0dHJpYnV0ZXNcIjoxMTUxfV0sMTE1NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV2ZW50RGF0YShvdXQsIHB0KSB7XG4gICAgb3V0LmxvbiA9IHB0LmxvbjtcbiAgICBvdXQubGF0ID0gcHQubGF0O1xuICAgIG91dC5sb2NhdGlvbiA9IHB0LmxvYyA/IHB0LmxvYyA6IG51bGw7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxufSx7fV0sMTE1NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBGeCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngnKTtcbnZhciBBeGVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG52YXIgZ2V0VHJhY2VDb2xvciA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvZ2V0X3RyYWNlX2NvbG9yJyk7XG52YXIgZmlsbFRleHQgPSBfZGVyZXFfKCcuLi8uLi9saWInKS5maWxsVGV4dDtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsKSB7XG4gICAgdmFyIGNkID0gcG9pbnREYXRhLmNkO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciB4YSA9IHBvaW50RGF0YS54YTtcbiAgICB2YXIgeWEgPSBwb2ludERhdGEueWE7XG4gICAgdmFyIGdlbyA9IHBvaW50RGF0YS5zdWJwbG90O1xuXG4gICAgdmFyIGlzTG9uTGF0T3ZlckVkZ2VzID0gZ2VvLnByb2plY3Rpb24uaXNMb25MYXRPdmVyRWRnZXM7XG4gICAgdmFyIHByb2plY3QgPSBnZW8ucHJvamVjdDtcblxuICAgIGZ1bmN0aW9uIGRpc3RGbihkKSB7XG4gICAgICAgIHZhciBsb25sYXQgPSBkLmxvbmxhdDtcblxuICAgICAgICBpZihsb25sYXRbMF0gPT09IEJBRE5VTSkgcmV0dXJuIEluZmluaXR5O1xuICAgICAgICBpZihpc0xvbkxhdE92ZXJFZGdlcyhsb25sYXQpKSByZXR1cm4gSW5maW5pdHk7XG5cbiAgICAgICAgdmFyIHB0ID0gcHJvamVjdChsb25sYXQpO1xuICAgICAgICB2YXIgcHggPSBwcm9qZWN0KFt4dmFsLCB5dmFsXSk7XG4gICAgICAgIHZhciBkeCA9IE1hdGguYWJzKHB0WzBdIC0gcHhbMF0pO1xuICAgICAgICB2YXIgZHkgPSBNYXRoLmFicyhwdFsxXSAtIHB4WzFdKTtcbiAgICAgICAgdmFyIHJhZCA9IE1hdGgubWF4KDMsIGQubXJjIHx8IDApO1xuXG4gICAgICAgIC8vIE4uQi4gZC5tcmMgaXMgdGhlIGNhbGN1bGF0ZWQgbWFya2VyIHJhZGl1c1xuICAgICAgICAvLyB3aGljaCBpcyBvbmx5IHNldCBmb3IgdHJhY2Ugd2l0aCAnbWFya2VycycgbW9kZS5cblxuICAgICAgICByZXR1cm4gTWF0aC5tYXgoTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KSAtIHJhZCwgMSAtIDMgLyByYWQpO1xuICAgIH1cblxuICAgIEZ4LmdldENsb3Nlc3QoY2QsIGRpc3RGbiwgcG9pbnREYXRhKTtcblxuICAgIC8vIHNraXAgdGhlIHJlc3QgKGZvciB0aGlzIHRyYWNlKSBpZiB3ZSBkaWRuJ3QgZmluZCBhIGNsb3NlIHBvaW50XG4gICAgaWYocG9pbnREYXRhLmluZGV4ID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgdmFyIGRpID0gY2RbcG9pbnREYXRhLmluZGV4XTtcbiAgICB2YXIgbG9ubGF0ID0gZGkubG9ubGF0O1xuICAgIHZhciBwb3MgPSBbeGEuYzJwKGxvbmxhdCksIHlhLmMycChsb25sYXQpXTtcbiAgICB2YXIgcmFkID0gZGkubXJjIHx8IDE7XG5cbiAgICBwb2ludERhdGEueDAgPSBwb3NbMF0gLSByYWQ7XG4gICAgcG9pbnREYXRhLngxID0gcG9zWzBdICsgcmFkO1xuICAgIHBvaW50RGF0YS55MCA9IHBvc1sxXSAtIHJhZDtcbiAgICBwb2ludERhdGEueTEgPSBwb3NbMV0gKyByYWQ7XG5cbiAgICBwb2ludERhdGEubG9jID0gZGkubG9jO1xuICAgIHBvaW50RGF0YS5sb24gPSBsb25sYXRbMF07XG4gICAgcG9pbnREYXRhLmxhdCA9IGxvbmxhdFsxXTtcblxuICAgIHZhciBheCA9IGdlby5tb2NrQXhpcztcbiAgICBwb2ludERhdGEubG9uTGFiZWwgPSBBeGVzLnRpY2tUZXh0KGF4LCBheC5jMmwocG9pbnREYXRhLmxvbiksICdob3ZlcicpLnRleHQ7XG4gICAgcG9pbnREYXRhLmxhdExhYmVsID0gQXhlcy50aWNrVGV4dChheCwgYXguYzJsKHBvaW50RGF0YS5sYXQpLCAnaG92ZXInKS50ZXh0O1xuXG4gICAgcG9pbnREYXRhLmNvbG9yID0gZ2V0VHJhY2VDb2xvcih0cmFjZSwgZGkpO1xuICAgIHBvaW50RGF0YS5leHRyYVRleHQgPSBnZXRFeHRyYVRleHQodHJhY2UsIGRpLCBwb2ludERhdGEsIGNkWzBdLnQubGFiZWxzKTtcbiAgICBwb2ludERhdGEuaG92ZXJ0ZW1wbGF0ZSA9IHRyYWNlLmhvdmVydGVtcGxhdGU7XG5cbiAgICByZXR1cm4gW3BvaW50RGF0YV07XG59O1xuXG5mdW5jdGlvbiBnZXRFeHRyYVRleHQodHJhY2UsIHB0LCBwb2ludERhdGEsIGxhYmVscykge1xuICAgIGlmKHRyYWNlLmhvdmVydGVtcGxhdGUpIHJldHVybjtcblxuICAgIHZhciBob3ZlcmluZm8gPSBwdC5oaSB8fCB0cmFjZS5ob3ZlcmluZm87XG5cbiAgICB2YXIgcGFydHMgPSBob3ZlcmluZm8gPT09ICdhbGwnID9cbiAgICAgICAgYXR0cmlidXRlcy5ob3ZlcmluZm8uZmxhZ3MgOlxuICAgICAgICBob3ZlcmluZm8uc3BsaXQoJysnKTtcblxuICAgIHZhciBoYXNMb2NhdGlvbiA9IHBhcnRzLmluZGV4T2YoJ2xvY2F0aW9uJykgIT09IC0xICYmIEFycmF5LmlzQXJyYXkodHJhY2UubG9jYXRpb25zKTtcbiAgICB2YXIgaGFzTG9uID0gKHBhcnRzLmluZGV4T2YoJ2xvbicpICE9PSAtMSk7XG4gICAgdmFyIGhhc0xhdCA9IChwYXJ0cy5pbmRleE9mKCdsYXQnKSAhPT0gLTEpO1xuICAgIHZhciBoYXNUZXh0ID0gKHBhcnRzLmluZGV4T2YoJ3RleHQnKSAhPT0gLTEpO1xuICAgIHZhciB0ZXh0ID0gW107XG5cbiAgICBmdW5jdGlvbiBmb3JtYXQodmFsKSB7IHJldHVybiB2YWwgKyAnXFx1MDBCMCc7IH1cblxuICAgIGlmKGhhc0xvY2F0aW9uKSB7XG4gICAgICAgIHRleHQucHVzaChwdC5sb2MpO1xuICAgIH0gZWxzZSBpZihoYXNMb24gJiYgaGFzTGF0KSB7XG4gICAgICAgIHRleHQucHVzaCgnKCcgKyBmb3JtYXQocG9pbnREYXRhLmxvbkxhYmVsKSArICcsICcgKyBmb3JtYXQocG9pbnREYXRhLmxhdExhYmVsKSArICcpJyk7XG4gICAgfSBlbHNlIGlmKGhhc0xvbikge1xuICAgICAgICB0ZXh0LnB1c2gobGFiZWxzLmxvbiArIGZvcm1hdChwb2ludERhdGEubG9uTGFiZWwpKTtcbiAgICB9IGVsc2UgaWYoaGFzTGF0KSB7XG4gICAgICAgIHRleHQucHVzaChsYWJlbHMubGF0ICsgZm9ybWF0KHBvaW50RGF0YS5sYXRMYWJlbCkpO1xuICAgIH1cblxuICAgIGlmKGhhc1RleHQpIHtcbiAgICAgICAgZmlsbFRleHQocHQsIHRyYWNlLCB0ZXh0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGV4dC5qb2luKCc8YnI+Jyk7XG59XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9meFwiOjYzMixcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL3NjYXR0ZXIvZ2V0X3RyYWNlX2NvbG9yXCI6MTEyMSxcIi4vYXR0cmlidXRlc1wiOjExNTF9XSwxMTU2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjb2xvcmJhcjogX2RlcmVxXygnLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXInKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKSxcbiAgICBzdHlsZTogX2RlcmVxXygnLi9zdHlsZScpLFxuICAgIHN0eWxlT25TZWxlY3Q6IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3R5bGUnKS5zdHlsZU9uU2VsZWN0LFxuICAgIGhvdmVyUG9pbnRzOiBfZGVyZXFfKCcuL2hvdmVyJyksXG4gICAgZXZlbnREYXRhOiBfZGVyZXFfKCcuL2V2ZW50X2RhdGEnKSxcbiAgICBzZWxlY3RQb2ludHM6IF9kZXJlcV8oJy4vc2VsZWN0JyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICdzY2F0dGVyZ2VvJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2VvJyksXG4gICAgY2F0ZWdvcmllczogWydnZW8nLCAnc3ltYm9scycsICdzaG93TGVnZW5kJywgJ3NjYXR0ZXItbGlrZSddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvZ2VvXCI6Nzk3LFwiLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXJcIjoxMTI5LFwiLi4vc2NhdHRlci9zdHlsZVwiOjExMzQsXCIuL2F0dHJpYnV0ZXNcIjoxMTUxLFwiLi9jYWxjXCI6MTE1MixcIi4vZGVmYXVsdHNcIjoxMTUzLFwiLi9ldmVudF9kYXRhXCI6MTE1NCxcIi4vaG92ZXJcIjoxMTU1LFwiLi9wbG90XCI6MTE1NyxcIi4vc2VsZWN0XCI6MTE1OCxcIi4vc3R5bGVcIjoxMTU5fV0sMTE1NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEJBRE5VTSA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG52YXIgZ2V0VG9wb2pzb25GZWF0dXJlcyA9IF9kZXJlcV8oJy4uLy4uL2xpYi90b3BvanNvbl91dGlscycpLmdldFRvcG9qc29uRmVhdHVyZXM7XG52YXIgbG9jYXRpb25Ub0ZlYXR1cmUgPSBfZGVyZXFfKCcuLi8uLi9saWIvZ2VvX2xvY2F0aW9uX3V0aWxzJykubG9jYXRpb25Ub0ZlYXR1cmU7XG52YXIgZ2VvSnNvblV0aWxzID0gX2RlcmVxXygnLi4vLi4vbGliL2dlb2pzb25fdXRpbHMnKTtcbnZhciBzdWJUeXBlcyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBzdHlsZSA9IF9kZXJlcV8oJy4vc3R5bGUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBnZW8sIGNhbGNEYXRhKSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNhbGNHZW9KU09OKGNhbGNEYXRhW2ldLCBnZW8udG9wb2pzb24pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbW92ZUJBRE5VTShkLCBub2RlKSB7XG4gICAgICAgIGlmKGQubG9ubGF0WzBdID09PSBCQUROVU0pIHtcbiAgICAgICAgICAgIGQzLnNlbGVjdChub2RlKS5yZW1vdmUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBzY2F0dGVyTGF5ZXIgPSBnZW8ubGF5ZXJzLmZyb250cGxvdC5zZWxlY3QoJy5zY2F0dGVybGF5ZXInKTtcbiAgICB2YXIgZ1RyYWNlcyA9IExpYi5tYWtlVHJhY2VHcm91cHMoc2NhdHRlckxheWVyLCBjYWxjRGF0YSwgJ3RyYWNlIHNjYXR0ZXJnZW8nKTtcblxuICAgIC8vIFRPRE8gZmluZCBhIHdheSB0byBvcmRlciB0aGUgaW5uZXIgbm9kZXMgb24gdXBkYXRlXG4gICAgZ1RyYWNlcy5zZWxlY3RBbGwoJyonKS5yZW1vdmUoKTtcblxuICAgIGdUcmFjZXMuZWFjaChmdW5jdGlvbihjYWxjVHJhY2UpIHtcbiAgICAgICAgdmFyIHMgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgICAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZSkgfHwgdHJhY2UuZmlsbCAhPT0gJ25vbmUnKSB7XG4gICAgICAgICAgICB2YXIgbGluZUNvb3JkcyA9IGdlb0pzb25VdGlscy5jYWxjVHJhY2VUb0xpbmVDb29yZHMoY2FsY1RyYWNlKTtcblxuICAgICAgICAgICAgdmFyIGxpbmVEYXRhID0gKHRyYWNlLmZpbGwgIT09ICdub25lJykgP1xuICAgICAgICAgICAgICAgIGdlb0pzb25VdGlscy5tYWtlUG9seWdvbihsaW5lQ29vcmRzKSA6XG4gICAgICAgICAgICAgICAgZ2VvSnNvblV0aWxzLm1ha2VMaW5lKGxpbmVDb29yZHMpO1xuXG4gICAgICAgICAgICBzLnNlbGVjdEFsbCgncGF0aC5qcy1saW5lJylcbiAgICAgICAgICAgICAgICAuZGF0YShbe2dlb2pzb246IGxpbmVEYXRhLCB0cmFjZTogdHJhY2V9XSlcbiAgICAgICAgICAgICAgLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgnanMtbGluZScsIHRydWUpXG4gICAgICAgICAgICAgICAgLnN0eWxlKCdzdHJva2UtbWl0ZXJsaW1pdCcsIDIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkpIHtcbiAgICAgICAgICAgIHMuc2VsZWN0QWxsKCdwYXRoLnBvaW50JylcbiAgICAgICAgICAgICAgICAuZGF0YShMaWIuaWRlbnRpdHkpXG4gICAgICAgICAgICAgLmVudGVyKCkuYXBwZW5kKCdwYXRoJylcbiAgICAgICAgICAgICAgICAuY2xhc3NlZCgncG9pbnQnLCB0cnVlKVxuICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGNhbGNQdCkgeyByZW1vdmVCQUROVU0oY2FsY1B0LCB0aGlzKTsgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihzdWJUeXBlcy5oYXNUZXh0KHRyYWNlKSkge1xuICAgICAgICAgICAgcy5zZWxlY3RBbGwoJ2cnKVxuICAgICAgICAgICAgICAgIC5kYXRhKExpYi5pZGVudGl0eSlcbiAgICAgICAgICAgICAgLmVudGVyKCkuYXBwZW5kKCdnJylcbiAgICAgICAgICAgICAgICAuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgICAgICAgICAuZWFjaChmdW5jdGlvbihjYWxjUHQpIHsgcmVtb3ZlQkFETlVNKGNhbGNQdCwgdGhpcyk7IH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2FsbCBzdHlsZSBoZXJlIHdpdGhpbiB0b3BvanNvbiByZXF1ZXN0IGNhbGxiYWNrXG4gICAgICAgIHN0eWxlKGdkLCBjYWxjVHJhY2UpO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gY2FsY0dlb0pTT04oY2FsY1RyYWNlLCB0b3BvanNvbikge1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgIGlmKCFBcnJheS5pc0FycmF5KHRyYWNlLmxvY2F0aW9ucykpIHJldHVybjtcblxuICAgIHZhciBmZWF0dXJlcyA9IGdldFRvcG9qc29uRmVhdHVyZXModHJhY2UsIHRvcG9qc29uKTtcbiAgICB2YXIgbG9jYXRpb25tb2RlID0gdHJhY2UubG9jYXRpb25tb2RlO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGNhbGNUcmFjZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1B0ID0gY2FsY1RyYWNlW2ldO1xuICAgICAgICB2YXIgZmVhdHVyZSA9IGxvY2F0aW9uVG9GZWF0dXJlKGxvY2F0aW9ubW9kZSwgY2FsY1B0LmxvYywgZmVhdHVyZXMpO1xuXG4gICAgICAgIGNhbGNQdC5sb25sYXQgPSBmZWF0dXJlID8gZmVhdHVyZS5wcm9wZXJ0aWVzLmN0IDogW0JBRE5VTSwgQkFETlVNXTtcbiAgICB9XG59XG5cbn0se1wiLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbFwiOjY5NSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9nZW9fbG9jYXRpb25fdXRpbHNcIjo3MTMsXCIuLi8uLi9saWIvZ2VvanNvbl91dGlsc1wiOjcxNCxcIi4uLy4uL2xpYi90b3BvanNvbl91dGlsc1wiOjc0NixcIi4uL3NjYXR0ZXIvc3VidHlwZXNcIjoxMTM1LFwiLi9zdHlsZVwiOjExNTksXCJkM1wiOjE2M31dLDExNTg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3VidHlwZXMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgQkFETlVNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzZWxlY3RQb2ludHMoc2VhcmNoSW5mbywgc2VsZWN0aW9uVGVzdGVyKSB7XG4gICAgdmFyIGNkID0gc2VhcmNoSW5mby5jZDtcbiAgICB2YXIgeGEgPSBzZWFyY2hJbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHNlYXJjaEluZm8ueWF4aXM7XG4gICAgdmFyIHNlbGVjdGlvbiA9IFtdO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuXG4gICAgdmFyIGRpLCBsb25sYXQsIHgsIHksIGk7XG5cbiAgICB2YXIgaGFzT25seUxpbmVzID0gKCFzdWJ0eXBlcy5oYXNNYXJrZXJzKHRyYWNlKSAmJiAhc3VidHlwZXMuaGFzVGV4dCh0cmFjZSkpO1xuICAgIGlmKGhhc09ubHlMaW5lcykgcmV0dXJuIFtdO1xuXG4gICAgaWYoc2VsZWN0aW9uVGVzdGVyID09PSBmYWxzZSkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGRpID0gY2RbaV07XG4gICAgICAgICAgICBsb25sYXQgPSBkaS5sb25sYXQ7XG5cbiAgICAgICAgICAgIC8vIHNvbWUgcHJvamVjdGlvbiB0eXBlcyBjYW4ndCBoYW5kbGUgQkFETlVNc1xuICAgICAgICAgICAgaWYobG9ubGF0WzBdID09PSBCQUROVU0pIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB4ID0geGEuYzJwKGxvbmxhdCk7XG4gICAgICAgICAgICB5ID0geWEuYzJwKGxvbmxhdCk7XG5cbiAgICAgICAgICAgIGlmKHNlbGVjdGlvblRlc3Rlci5jb250YWlucyhbeCwgeV0sIG51bGwsIGksIHNlYXJjaEluZm8pKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogaSxcbiAgICAgICAgICAgICAgICAgICAgbG9uOiBsb25sYXRbMF0sXG4gICAgICAgICAgICAgICAgICAgIGxhdDogbG9ubGF0WzFdXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZGkuc2VsZWN0ZWQgPSAxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaS5zZWxlY3RlZCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0aW9uO1xufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vc2NhdHRlci9zdWJ0eXBlc1wiOjExMzV9XSwxMTU5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG5cbnZhciBzY2F0dGVyU3R5bGUgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3N0eWxlJyk7XG52YXIgc3R5bGVQb2ludHMgPSBzY2F0dGVyU3R5bGUuc3R5bGVQb2ludHM7XG52YXIgc3R5bGVUZXh0ID0gc2NhdHRlclN0eWxlLnN0eWxlVGV4dDtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdHlsZShnZCwgY2FsY1RyYWNlKSB7XG4gICAgaWYoY2FsY1RyYWNlKSBzdHlsZVRyYWNlKGdkLCBjYWxjVHJhY2UpO1xufTtcblxuZnVuY3Rpb24gc3R5bGVUcmFjZShnZCwgY2FsY1RyYWNlKSB7XG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgIHZhciBzID0gY2FsY1RyYWNlWzBdLm5vZGUzO1xuXG4gICAgcy5zdHlsZSgnb3BhY2l0eScsIGNhbGNUcmFjZVswXS50cmFjZS5vcGFjaXR5KTtcblxuICAgIHN0eWxlUG9pbnRzKHMsIHRyYWNlLCBnZCk7XG4gICAgc3R5bGVUZXh0KHMsIHRyYWNlLCBnZCk7XG5cbiAgICAvLyB0aGlzIHBhcnQgaXMgaW5jb21wYXRpYmxlIHdpdGggRHJhd2luZy5saW5lR3JvdXBTdHlsZVxuICAgIHMuc2VsZWN0QWxsKCdwYXRoLmpzLWxpbmUnKVxuICAgICAgICAuc3R5bGUoJ2ZpbGwnLCAnbm9uZScpXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBwYXRoID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gZC50cmFjZTtcbiAgICAgICAgICAgIHZhciBsaW5lID0gdHJhY2UubGluZSB8fCB7fTtcblxuICAgICAgICAgICAgcGF0aC5jYWxsKENvbG9yLnN0cm9rZSwgbGluZS5jb2xvcilcbiAgICAgICAgICAgICAgICAuY2FsbChEcmF3aW5nLmRhc2hMaW5lLCBsaW5lLmRhc2ggfHwgJycsIGxpbmUud2lkdGggfHwgMCk7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlLmZpbGwgIT09ICdub25lJykge1xuICAgICAgICAgICAgICAgIHBhdGguY2FsbChDb2xvci5maWxsLCB0cmFjZS5maWxsY29sb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vc2NhdHRlci9zdHlsZVwiOjExMzQsXCJkM1wiOjE2M31dLDExNjA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgcGxvdEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJBdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG52YXIgREFTSEVTID0gX2RlcmVxXygnLi9jb25zdGFudHMnKS5EQVNIRVM7XG5cbnZhciBzY2F0dGVyTGluZUF0dHJzID0gc2NhdHRlckF0dHJzLmxpbmU7XG52YXIgc2NhdHRlck1hcmtlckF0dHJzID0gc2NhdHRlckF0dHJzLm1hcmtlcjtcbnZhciBzY2F0dGVyTWFya2VyTGluZUF0dHJzID0gc2NhdHRlck1hcmtlckF0dHJzLmxpbmU7XG5cbnZhciBhdHRycyA9IG1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoe1xuICAgIHg6IHNjYXR0ZXJBdHRycy54LFxuICAgIHgwOiBzY2F0dGVyQXR0cnMueDAsXG4gICAgZHg6IHNjYXR0ZXJBdHRycy5keCxcbiAgICB5OiBzY2F0dGVyQXR0cnMueSxcbiAgICB5MDogc2NhdHRlckF0dHJzLnkwLFxuICAgIGR5OiBzY2F0dGVyQXR0cnMuZHksXG5cbiAgICB0ZXh0OiBzY2F0dGVyQXR0cnMudGV4dCxcbiAgICBob3ZlcnRleHQ6IHNjYXR0ZXJBdHRycy5ob3ZlcnRleHQsXG5cbiAgICB0ZXh0cG9zaXRpb246IHNjYXR0ZXJBdHRycy50ZXh0cG9zaXRpb24sXG4gICAgdGV4dGZvbnQ6IHNjYXR0ZXJBdHRycy50ZXh0Zm9udCxcblxuICAgIG1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICAgICAgZmxhZ3M6IFsnbGluZXMnLCAnbWFya2VycycsICd0ZXh0J10sXG4gICAgICAgIGV4dHJhczogWydub25lJ10sXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IHNjYXR0ZXJMaW5lQXR0cnMuY29sb3IsXG4gICAgICAgIHdpZHRoOiBzY2F0dGVyTGluZUF0dHJzLndpZHRoLFxuICAgICAgICBzaGFwZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2xpbmVhcicsICdodicsICd2aCcsICdodmgnLCAndmh2J10sXG4gICAgICAgICAgICBkZmx0OiAnbGluZWFyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBkYXNoOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IE9iamVjdC5rZXlzKERBU0hFUyksXG4gICAgICAgICAgICBkZmx0OiAnc29saWQnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWFya2VyOiBleHRlbmRGbGF0KHt9LCBjb2xvclNjYWxlQXR0cnMoJ21hcmtlcicpLCB7XG4gICAgICAgIHN5bWJvbDogc2NhdHRlck1hcmtlckF0dHJzLnN5bWJvbCxcbiAgICAgICAgc2l6ZTogc2NhdHRlck1hcmtlckF0dHJzLnNpemUsXG4gICAgICAgIHNpemVyZWY6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplcmVmLFxuICAgICAgICBzaXplbWluOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZW1pbixcbiAgICAgICAgc2l6ZW1vZGU6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplbW9kZSxcbiAgICAgICAgb3BhY2l0eTogc2NhdHRlck1hcmtlckF0dHJzLm9wYWNpdHksXG4gICAgICAgIGNvbG9yYmFyOiBzY2F0dGVyTWFya2VyQXR0cnMuY29sb3JiYXIsXG4gICAgICAgIGxpbmU6IGV4dGVuZEZsYXQoe30sIGNvbG9yU2NhbGVBdHRycygnbWFya2VyLmxpbmUnKSwge1xuICAgICAgICAgICAgd2lkdGg6IHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMud2lkdGhcbiAgICAgICAgfSlcbiAgICB9KSxcbiAgICBjb25uZWN0Z2Fwczogc2NhdHRlckF0dHJzLmNvbm5lY3RnYXBzLFxuICAgIGZpbGw6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5maWxsLCB7ZGZsdDogJ25vbmUnfSksXG4gICAgZmlsbGNvbG9yOiBzY2F0dGVyQXR0cnMuZmlsbGNvbG9yLFxuXG4gICAgLy8gbm8gaG92ZXJvblxuXG4gICAgc2VsZWN0ZWQ6IHtcbiAgICAgICAgbWFya2VyOiBzY2F0dGVyQXR0cnMuc2VsZWN0ZWQubWFya2VyLFxuICAgICAgICB0ZXh0Zm9udDogc2NhdHRlckF0dHJzLnNlbGVjdGVkLnRleHRmb250XG4gICAgfSxcbiAgICB1bnNlbGVjdGVkOiB7XG4gICAgICAgIG1hcmtlcjogc2NhdHRlckF0dHJzLnVuc2VsZWN0ZWQubWFya2VyLFxuICAgICAgICB0ZXh0Zm9udDogc2NhdHRlckF0dHJzLnVuc2VsZWN0ZWQudGV4dGZvbnRcbiAgICB9LFxuXG4gICAgb3BhY2l0eTogcGxvdEF0dHJzLm9wYWNpdHlcblxufSwgJ2NhbGMnLCAnbmVzdGVkJyk7XG5cbmF0dHJzLnguZWRpdFR5cGUgPSBhdHRycy55LmVkaXRUeXBlID0gYXR0cnMueDAuZWRpdFR5cGUgPSBhdHRycy55MC5lZGl0VHlwZSA9ICdjYWxjK2NsZWFyQXhpc1R5cGVzJztcbmF0dHJzLmhvdmVydGVtcGxhdGUgPSBzY2F0dGVyQXR0cnMuaG92ZXJ0ZW1wbGF0ZTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NCxcIi4uL3NjYXR0ZXIvYXR0cmlidXRlc1wiOjExMTIsXCIuL2NvbnN0YW50c1wiOjExNjJ9XSwxMTYxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNsdXN0ZXIgPSBfZGVyZXFfKCdwb2ludC1jbHVzdGVyJyk7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBBeGlzSURzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG52YXIgZmluZEV4dHJlbWVzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F1dG9yYW5nZScpLmZpbmRFeHRyZW1lcztcblxudmFyIHNjYXR0ZXJDYWxjID0gX2RlcmVxXygnLi4vc2NhdHRlci9jYWxjJyk7XG52YXIgY2FsY01hcmtlclNpemUgPSBzY2F0dGVyQ2FsYy5jYWxjTWFya2VyU2l6ZTtcbnZhciBjYWxjQXhpc0V4cGFuc2lvbiA9IHNjYXR0ZXJDYWxjLmNhbGNBeGlzRXhwYW5zaW9uO1xudmFyIHNldEZpcnN0U2NhdHRlciA9IHNjYXR0ZXJDYWxjLnNldEZpcnN0U2NhdHRlcjtcbnZhciBjYWxjQ29sb3JzY2FsZSA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjJyk7XG52YXIgY29udmVydCA9IF9kZXJlcV8oJy4vY29udmVydCcpO1xudmFyIHNjZW5lVXBkYXRlID0gX2RlcmVxXygnLi9zY2VuZV91cGRhdGUnKTtcblxudmFyIEJBRE5VTSA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG52YXIgVE9PX01BTllfUE9JTlRTID0gX2RlcmVxXygnLi9jb25zdGFudHMnKS5UT09fTUFOWV9QT0lOVFM7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciB4YSA9IEF4aXNJRHMuZ2V0RnJvbUlkKGdkLCB0cmFjZS54YXhpcyk7XG4gICAgdmFyIHlhID0gQXhpc0lEcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnlheGlzKTtcbiAgICB2YXIgc3VicGxvdCA9IGZ1bGxMYXlvdXQuX3Bsb3RzW3RyYWNlLnhheGlzICsgdHJhY2UueWF4aXNdO1xuICAgIHZhciBsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgIHZhciBoYXNUb29NYW55UG9pbnRzID0gbGVuID49IFRPT19NQU5ZX1BPSU5UUztcbiAgICB2YXIgbGVuMiA9IGxlbiAqIDI7XG4gICAgdmFyIHN0YXNoID0ge307XG4gICAgdmFyIGksIHh4LCB5eTtcblxuICAgIHZhciB4ID0geGEubWFrZUNhbGNkYXRhKHRyYWNlLCAneCcpO1xuICAgIHZhciB5ID0geWEubWFrZUNhbGNkYXRhKHRyYWNlLCAneScpO1xuXG4gICAgLy8gd2UgbmVlZCBoaS1wcmVjaXNpb24gZm9yIHNjYXR0ZXIyZCxcbiAgICAvLyByZWdsLXNjYXR0ZXIyZCB1c2VzIE5hTnMgZm9yIGJhZC9taXNzaW5nIHZhbHVlc1xuICAgIHZhciBwb3NpdGlvbnMgPSBuZXcgQXJyYXkobGVuMik7XG4gICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgeHggPSB4W2ldO1xuICAgICAgICB5eSA9IHlbaV07XG4gICAgICAgIHBvc2l0aW9uc1tpICogMl0gPSB4eCA9PT0gQkFETlVNID8gTmFOIDogeHg7XG4gICAgICAgIHBvc2l0aW9uc1tpICogMiArIDFdID0geXkgPT09IEJBRE5VTSA/IE5hTiA6IHl5O1xuICAgIH1cblxuICAgIGlmKHhhLnR5cGUgPT09ICdsb2cnKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGxlbjI7IGkgKz0gMikge1xuICAgICAgICAgICAgcG9zaXRpb25zW2ldID0geGEuYzJsKHBvc2l0aW9uc1tpXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYoeWEudHlwZSA9PT0gJ2xvZycpIHtcbiAgICAgICAgZm9yKGkgPSAxOyBpIDwgbGVuMjsgaSArPSAyKSB7XG4gICAgICAgICAgICBwb3NpdGlvbnNbaV0gPSB5YS5jMmwocG9zaXRpb25zW2ldKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHdlIGRvbid0IGJ1aWxkIGEgdHJlZSBmb3IgbG9nIGF4ZXMgc2luY2UgaXQgdGFrZXMgbG9uZyB0byBjb252ZXJ0IGxvZzJweFxuICAgIC8vIGFuZCBpdCBpcyBhbHNvXG4gICAgaWYoaGFzVG9vTWFueVBvaW50cyAmJiAoeGEudHlwZSAhPT0gJ2xvZycgJiYgeWEudHlwZSAhPT0gJ2xvZycpKSB7XG4gICAgICAgIC8vIEZJWE1FOiBkZWxlZ2F0ZSB0aGlzIHRvIHdlYndvcmtlclxuICAgICAgICBzdGFzaC50cmVlID0gY2x1c3Rlcihwb3NpdGlvbnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBpZHMgPSBzdGFzaC5pZHMgPSBuZXcgQXJyYXkobGVuKTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIGlkc1tpXSA9IGk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgc2NlbmUgb3B0aW9ucyBhbmQgc2NlbmVcbiAgICBjYWxjQ29sb3JzY2FsZShnZCwgdHJhY2UpO1xuICAgIHZhciBvcHRzID0gc2NlbmVPcHRpb25zKGdkLCBzdWJwbG90LCB0cmFjZSwgcG9zaXRpb25zLCB4LCB5KTtcbiAgICB2YXIgc2NlbmUgPSBzY2VuZVVwZGF0ZShnZCwgc3VicGxvdCk7XG5cbiAgICAvLyBSZXVzZSBTVkcgc2NhdHRlciBheGlzIGV4cGFuc2lvbiByb3V0aW5lLlxuICAgIC8vIEZvciBncmFwaHMgd2l0aCB2ZXJ5IGxhcmdlIG51bWJlciBvZiBwb2ludHMgYW5kIGFycmF5IG1hcmtlci5zaXplLFxuICAgIC8vIHVzZSBhdmVyYWdlIG1hcmtlciBzaXplIGluc3RlYWQgdG8gc3BlZWQgdGhpbmdzIHVwLlxuICAgIHNldEZpcnN0U2NhdHRlcihmdWxsTGF5b3V0LCB0cmFjZSk7XG4gICAgdmFyIHBwYWQ7XG4gICAgaWYoIWhhc1Rvb01hbnlQb2ludHMpIHtcbiAgICAgICAgcHBhZCA9IGNhbGNNYXJrZXJTaXplKHRyYWNlLCBsZW4pO1xuICAgIH0gZWxzZSBpZihvcHRzLm1hcmtlcikge1xuICAgICAgICBwcGFkID0gMiAqIChvcHRzLm1hcmtlci5zaXplQXZnIHx8IE1hdGgubWF4KG9wdHMubWFya2VyLnNpemUsIDMpKTtcbiAgICB9XG4gICAgY2FsY0F4aXNFeHBhbnNpb24oZ2QsIHRyYWNlLCB4YSwgeWEsIHgsIHksIHBwYWQpO1xuICAgIGlmKG9wdHMuZXJyb3JYKSBleHBhbmRGb3JFcnJvckJhcnModHJhY2UsIHhhLCBvcHRzLmVycm9yWCk7XG4gICAgaWYob3B0cy5lcnJvclkpIGV4cGFuZEZvckVycm9yQmFycyh0cmFjZSwgeWEsIG9wdHMuZXJyb3JZKTtcblxuICAgIC8vIHNldCBmbGFncyB0byBjcmVhdGUgc2NlbmUgcmVuZGVyZXJzXG4gICAgaWYob3B0cy5maWxsICYmICFzY2VuZS5maWxsMmQpIHNjZW5lLmZpbGwyZCA9IHRydWU7XG4gICAgaWYob3B0cy5tYXJrZXIgJiYgIXNjZW5lLnNjYXR0ZXIyZCkgc2NlbmUuc2NhdHRlcjJkID0gdHJ1ZTtcbiAgICBpZihvcHRzLmxpbmUgJiYgIXNjZW5lLmxpbmUyZCkgc2NlbmUubGluZTJkID0gdHJ1ZTtcbiAgICBpZigob3B0cy5lcnJvclggfHwgb3B0cy5lcnJvclkpICYmICFzY2VuZS5lcnJvcjJkKSBzY2VuZS5lcnJvcjJkID0gdHJ1ZTtcbiAgICBpZihvcHRzLnRleHQgJiYgIXNjZW5lLmdsVGV4dCkgc2NlbmUuZ2xUZXh0ID0gdHJ1ZTtcblxuICAgIC8vIEZJWE1FOiBvcmdhbml6ZSBpdCBpbiBhIG1vcmUgYXBwcm9wcmlhdGUgbWFubmVyLCBwcm9iYWJseSBpbiBzY2VuZU9wdGlvbnNcbiAgICAvLyBwdXQgcG9pbnQtY2x1c3RlciBpbnN0YW5jZSBmb3Igb3B0aW1pemVkIHJlZ2wgY2FsY1xuICAgIGlmKG9wdHMubWFya2VyKSB7XG4gICAgICAgIG9wdHMubWFya2VyLnNuYXAgPSBzdGFzaC50cmVlIHx8IFRPT19NQU5ZX1BPSU5UUztcbiAgICB9XG5cbiAgICBzY2VuZS5saW5lT3B0aW9ucy5wdXNoKG9wdHMubGluZSk7XG4gICAgc2NlbmUuZXJyb3JYT3B0aW9ucy5wdXNoKG9wdHMuZXJyb3JYKTtcbiAgICBzY2VuZS5lcnJvcllPcHRpb25zLnB1c2gob3B0cy5lcnJvclkpO1xuICAgIHNjZW5lLmZpbGxPcHRpb25zLnB1c2gob3B0cy5maWxsKTtcbiAgICBzY2VuZS5tYXJrZXJPcHRpb25zLnB1c2gob3B0cy5tYXJrZXIpO1xuICAgIHNjZW5lLm1hcmtlclNlbGVjdGVkT3B0aW9ucy5wdXNoKG9wdHMubWFya2VyU2VsKTtcbiAgICBzY2VuZS5tYXJrZXJVbnNlbGVjdGVkT3B0aW9ucy5wdXNoKG9wdHMubWFya2VyVW5zZWwpO1xuICAgIHNjZW5lLnRleHRPcHRpb25zLnB1c2gob3B0cy50ZXh0KTtcbiAgICBzY2VuZS50ZXh0U2VsZWN0ZWRPcHRpb25zLnB1c2gob3B0cy50ZXh0U2VsKTtcbiAgICBzY2VuZS50ZXh0VW5zZWxlY3RlZE9wdGlvbnMucHVzaChvcHRzLnRleHRVbnNlbCk7XG4gICAgc2NlbmUuc2VsZWN0QmF0Y2gucHVzaChbXSk7XG4gICAgc2NlbmUudW5zZWxlY3RCYXRjaC5wdXNoKFtdKTtcblxuICAgIHN0YXNoLl9zY2VuZSA9IHNjZW5lO1xuICAgIHN0YXNoLmluZGV4ID0gc2NlbmUuY291bnQ7XG4gICAgc3Rhc2gueCA9IHg7XG4gICAgc3Rhc2gueSA9IHk7XG4gICAgc3Rhc2gucG9zaXRpb25zID0gcG9zaXRpb25zO1xuICAgIHNjZW5lLmNvdW50Kys7XG5cbiAgICByZXR1cm4gW3t4OiBmYWxzZSwgeTogZmFsc2UsIHQ6IHN0YXNoLCB0cmFjZTogdHJhY2V9XTtcbn07XG5cbmZ1bmN0aW9uIGV4cGFuZEZvckVycm9yQmFycyh0cmFjZSwgYXgsIG9wdHMpIHtcbiAgICB2YXIgZXh0cmVtZXMgPSB0cmFjZS5fZXh0cmVtZXNbYXguX2lkXTtcbiAgICB2YXIgZXJyRXh0ID0gZmluZEV4dHJlbWVzKGF4LCBvcHRzLl9ibmRzLCB7cGFkZGVkOiB0cnVlfSk7XG4gICAgZXh0cmVtZXMubWluID0gZXh0cmVtZXMubWluLmNvbmNhdChlcnJFeHQubWluKTtcbiAgICBleHRyZW1lcy5tYXggPSBleHRyZW1lcy5tYXguY29uY2F0KGVyckV4dC5tYXgpO1xufVxuXG5mdW5jdGlvbiBzY2VuZU9wdGlvbnMoZ2QsIHN1YnBsb3QsIHRyYWNlLCBwb3NpdGlvbnMsIHgsIHkpIHtcbiAgICB2YXIgb3B0cyA9IGNvbnZlcnQuc3R5bGUoZ2QsIHRyYWNlKTtcblxuICAgIGlmKG9wdHMubWFya2VyKSB7XG4gICAgICAgIG9wdHMubWFya2VyLnBvc2l0aW9ucyA9IHBvc2l0aW9ucztcbiAgICB9XG5cbiAgICBpZihvcHRzLmxpbmUgJiYgcG9zaXRpb25zLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgTGliLmV4dGVuZEZsYXQoXG4gICAgICAgICAgICBvcHRzLmxpbmUsXG4gICAgICAgICAgICBjb252ZXJ0LmxpbmVQb3NpdGlvbnMoZ2QsIHRyYWNlLCBwb3NpdGlvbnMpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgaWYob3B0cy5lcnJvclggfHwgb3B0cy5lcnJvclkpIHtcbiAgICAgICAgdmFyIGVycm9ycyA9IGNvbnZlcnQuZXJyb3JCYXJQb3NpdGlvbnMoZ2QsIHRyYWNlLCBwb3NpdGlvbnMsIHgsIHkpO1xuXG4gICAgICAgIGlmKG9wdHMuZXJyb3JYKSB7XG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChvcHRzLmVycm9yWCwgZXJyb3JzLngpO1xuICAgICAgICB9XG4gICAgICAgIGlmKG9wdHMuZXJyb3JZKSB7XG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChvcHRzLmVycm9yWSwgZXJyb3JzLnkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYob3B0cy50ZXh0KSB7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KFxuICAgICAgICAgICAgb3B0cy50ZXh0LFxuICAgICAgICAgICAge3Bvc2l0aW9uczogcG9zaXRpb25zfSxcbiAgICAgICAgICAgIGNvbnZlcnQudGV4dFBvc2l0aW9uKGdkLCB0cmFjZSwgb3B0cy50ZXh0LCBvcHRzLm1hcmtlcilcbiAgICAgICAgKTtcbiAgICAgICAgTGliLmV4dGVuZEZsYXQoXG4gICAgICAgICAgICBvcHRzLnRleHRTZWwsXG4gICAgICAgICAgICB7cG9zaXRpb25zOiBwb3NpdGlvbnN9LFxuICAgICAgICAgICAgY29udmVydC50ZXh0UG9zaXRpb24oZ2QsIHRyYWNlLCBvcHRzLnRleHQsIG9wdHMubWFya2VyU2VsKVxuICAgICAgICApO1xuICAgICAgICBMaWIuZXh0ZW5kRmxhdChcbiAgICAgICAgICAgIG9wdHMudGV4dFVuc2VsLFxuICAgICAgICAgICAge3Bvc2l0aW9uczogcG9zaXRpb25zfSxcbiAgICAgICAgICAgIGNvbnZlcnQudGV4dFBvc2l0aW9uKGdkLCB0cmFjZSwgb3B0cy50ZXh0LCBvcHRzLm1hcmtlclVuc2VsKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBvcHRzO1xufVxuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXV0b3JhbmdlXCI6NzY2LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzXCI6NzcwLFwiLi4vc2NhdHRlci9jYWxjXCI6MTExMyxcIi4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjXCI6MTExNSxcIi4vY29uc3RhbnRzXCI6MTE2MixcIi4vY29udmVydFwiOjExNjMsXCIuL3NjZW5lX3VwZGF0ZVwiOjExNjksXCJwb2ludC1jbHVzdGVyXCI6NDY5fV0sMTE2MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBTWU1CT0xfU0laRSA9IDIwO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBUT09fTUFOWV9QT0lOVFM6IDFlNSxcblxuICAgIFNZTUJPTF9TREZfU0laRTogMjAwLFxuICAgIFNZTUJPTF9TSVpFOiBTWU1CT0xfU0laRSxcbiAgICBTWU1CT0xfU1RST0tFOiBTWU1CT0xfU0laRSAvIDIwLFxuXG4gICAgRE9UX1JFOiAvLWRvdC8sXG4gICAgT1BFTl9SRTogLy1vcGVuLyxcblxuICAgIERBU0hFUzoge1xuICAgICAgICBzb2xpZDogWzFdLFxuICAgICAgICBkb3Q6IFsxLCAxXSxcbiAgICAgICAgZGFzaDogWzQsIDFdLFxuICAgICAgICBsb25nZGFzaDogWzgsIDFdLFxuICAgICAgICBkYXNoZG90OiBbNCwgMSwgMSwgMV0sXG4gICAgICAgIGxvbmdkYXNoZG90OiBbOCwgMSwgMSwgMV1cbiAgICB9XG59O1xuXG59LHt9XSwxMTYzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgc3ZnU2RmID0gX2RlcmVxXygnc3ZnLXBhdGgtc2RmJyk7XG52YXIgcmdiYSA9IF9kZXJlcV8oJ2NvbG9yLW5vcm1hbGl6ZScpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBBeGlzSURzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG5cbnZhciBmb3JtYXRDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2xpYi9nbF9mb3JtYXRfY29sb3InKS5mb3JtYXRDb2xvcjtcbnZhciBzdWJUeXBlcyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBtYWtlQnViYmxlU2l6ZUZuID0gX2RlcmVxXygnLi4vc2NhdHRlci9tYWtlX2J1YmJsZV9zaXplX2Z1bmMnKTtcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgREVTRUxFQ1RESU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvaW50ZXJhY3Rpb25zJykuREVTRUxFQ1RESU07XG5cbnZhciBURVhUT0ZGU0VUU0lHTiA9IHtcbiAgICBzdGFydDogMSwgbGVmdDogMSwgZW5kOiAtMSwgcmlnaHQ6IC0xLCBtaWRkbGU6IDAsIGNlbnRlcjogMCwgYm90dG9tOiAxLCB0b3A6IC0xXG59O1xuXG5mdW5jdGlvbiBjb252ZXJ0U3R5bGUoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGk7XG5cbiAgICB2YXIgb3B0cyA9IHtcbiAgICAgICAgbWFya2VyOiB1bmRlZmluZWQsXG4gICAgICAgIG1hcmtlclNlbDogdW5kZWZpbmVkLFxuICAgICAgICBtYXJrZXJVbnNlbDogdW5kZWZpbmVkLFxuICAgICAgICBsaW5lOiB1bmRlZmluZWQsXG4gICAgICAgIGZpbGw6IHVuZGVmaW5lZCxcbiAgICAgICAgZXJyb3JYOiB1bmRlZmluZWQsXG4gICAgICAgIGVycm9yWTogdW5kZWZpbmVkLFxuICAgICAgICB0ZXh0OiB1bmRlZmluZWQsXG4gICAgICAgIHRleHRTZWw6IHVuZGVmaW5lZCxcbiAgICAgICAgdGV4dFVuc2VsOiB1bmRlZmluZWRcbiAgICB9O1xuXG4gICAgaWYodHJhY2UudmlzaWJsZSAhPT0gdHJ1ZSkgcmV0dXJuIG9wdHM7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNUZXh0KHRyYWNlKSkge1xuICAgICAgICBvcHRzLnRleHQgPSBjb252ZXJ0VGV4dFN0eWxlKHRyYWNlKTtcbiAgICAgICAgb3B0cy50ZXh0U2VsID0gY29udmVydFRleHRTZWxlY3Rpb24odHJhY2UsIHRyYWNlLnNlbGVjdGVkKTtcbiAgICAgICAgb3B0cy50ZXh0VW5zZWwgPSBjb252ZXJ0VGV4dFNlbGVjdGlvbih0cmFjZSwgdHJhY2UudW5zZWxlY3RlZCk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkpIHtcbiAgICAgICAgb3B0cy5tYXJrZXIgPSBjb252ZXJ0TWFya2VyU3R5bGUodHJhY2UpO1xuICAgICAgICBvcHRzLm1hcmtlclNlbCA9IGNvbnZlcnRNYXJrZXJTZWxlY3Rpb24odHJhY2UsIHRyYWNlLnNlbGVjdGVkKTtcbiAgICAgICAgb3B0cy5tYXJrZXJVbnNlbCA9IGNvbnZlcnRNYXJrZXJTZWxlY3Rpb24odHJhY2UsIHRyYWNlLnVuc2VsZWN0ZWQpO1xuXG4gICAgICAgIGlmKCF0cmFjZS51bnNlbGVjdGVkICYmIEFycmF5LmlzQXJyYXkodHJhY2UubWFya2VyLm9wYWNpdHkpKSB7XG4gICAgICAgICAgICB2YXIgbW8gPSB0cmFjZS5tYXJrZXIub3BhY2l0eTtcbiAgICAgICAgICAgIG9wdHMubWFya2VyVW5zZWwub3BhY2l0eSA9IG5ldyBBcnJheShtby5sZW5ndGgpO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbW8ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBvcHRzLm1hcmtlclVuc2VsLm9wYWNpdHlbaV0gPSBERVNFTEVDVERJTSAqIG1vW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2UpKSB7XG4gICAgICAgIG9wdHMubGluZSA9IHtcbiAgICAgICAgICAgIG92ZXJsYXk6IHRydWUsXG4gICAgICAgICAgICB0aGlja25lc3M6IHRyYWNlLmxpbmUud2lkdGgsXG4gICAgICAgICAgICBjb2xvcjogdHJhY2UubGluZS5jb2xvcixcbiAgICAgICAgICAgIG9wYWNpdHk6IHRyYWNlLm9wYWNpdHlcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgZGFzaGVzID0gKGNvbnN0YW50cy5EQVNIRVNbdHJhY2UubGluZS5kYXNoXSB8fCBbMV0pLnNsaWNlKCk7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IGRhc2hlcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgZGFzaGVzW2ldICo9IHRyYWNlLmxpbmUud2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgb3B0cy5saW5lLmRhc2hlcyA9IGRhc2hlcztcbiAgICB9XG5cbiAgICBpZih0cmFjZS5lcnJvcl94ICYmIHRyYWNlLmVycm9yX3gudmlzaWJsZSkge1xuICAgICAgICBvcHRzLmVycm9yWCA9IGNvbnZlcnRFcnJvckJhclN0eWxlKHRyYWNlLCB0cmFjZS5lcnJvcl94KTtcbiAgICB9XG5cbiAgICBpZih0cmFjZS5lcnJvcl95ICYmIHRyYWNlLmVycm9yX3kudmlzaWJsZSkge1xuICAgICAgICBvcHRzLmVycm9yWSA9IGNvbnZlcnRFcnJvckJhclN0eWxlKHRyYWNlLCB0cmFjZS5lcnJvcl95KTtcbiAgICB9XG5cbiAgICBpZighIXRyYWNlLmZpbGwgJiYgdHJhY2UuZmlsbCAhPT0gJ25vbmUnKSB7XG4gICAgICAgIG9wdHMuZmlsbCA9IHtcbiAgICAgICAgICAgIGNsb3NlZDogdHJ1ZSxcbiAgICAgICAgICAgIGZpbGw6IHRyYWNlLmZpbGxjb2xvcixcbiAgICAgICAgICAgIHRoaWNrbmVzczogMFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBvcHRzO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0VGV4dFN0eWxlKHRyYWNlKSB7XG4gICAgdmFyIGNvdW50ID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgdGV4dGZvbnRJbiA9IHRyYWNlLnRleHRmb250O1xuICAgIHZhciB0ZXh0cG9zaXRpb25JbiA9IHRyYWNlLnRleHRwb3NpdGlvbjtcbiAgICB2YXIgdGV4dFBvcyA9IEFycmF5LmlzQXJyYXkodGV4dHBvc2l0aW9uSW4pID8gdGV4dHBvc2l0aW9uSW4gOiBbdGV4dHBvc2l0aW9uSW5dO1xuICAgIHZhciB0ZmMgPSB0ZXh0Zm9udEluLmNvbG9yO1xuICAgIHZhciB0ZnMgPSB0ZXh0Zm9udEluLnNpemU7XG4gICAgdmFyIHRmZiA9IHRleHRmb250SW4uZmFtaWx5O1xuICAgIHZhciBvcHRzT3V0ID0ge307XG4gICAgdmFyIGk7XG5cbiAgICBvcHRzT3V0LnRleHQgPSB0cmFjZS50ZXh0O1xuICAgIG9wdHNPdXQub3BhY2l0eSA9IHRyYWNlLm9wYWNpdHk7XG4gICAgb3B0c091dC5mb250ID0ge307XG4gICAgb3B0c091dC5hbGlnbiA9IFtdO1xuICAgIG9wdHNPdXQuYmFzZWxpbmUgPSBbXTtcblxuICAgIGZvcihpID0gMDsgaSA8IHRleHRQb3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHRwID0gdGV4dFBvc1tpXS5zcGxpdCgvXFxzKy8pO1xuXG4gICAgICAgIHN3aXRjaCh0cFsxXSkge1xuICAgICAgICAgICAgY2FzZSAnbGVmdCc6XG4gICAgICAgICAgICAgICAgb3B0c091dC5hbGlnbi5wdXNoKCdyaWdodCcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICAgICAgICAgIG9wdHNPdXQuYWxpZ24ucHVzaCgnbGVmdCcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBvcHRzT3V0LmFsaWduLnB1c2godHBbMV0pO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCh0cFswXSkge1xuICAgICAgICAgICAgY2FzZSAndG9wJzpcbiAgICAgICAgICAgICAgICBvcHRzT3V0LmJhc2VsaW5lLnB1c2goJ2JvdHRvbScpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnYm90dG9tJzpcbiAgICAgICAgICAgICAgICBvcHRzT3V0LmJhc2VsaW5lLnB1c2goJ3RvcCcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBvcHRzT3V0LmJhc2VsaW5lLnB1c2godHBbMF0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoQXJyYXkuaXNBcnJheSh0ZmMpKSB7XG4gICAgICAgIG9wdHNPdXQuY29sb3IgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICBvcHRzT3V0LmNvbG9yW2ldID0gdGZjW2ldO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3B0c091dC5jb2xvciA9IHRmYztcbiAgICB9XG5cbiAgICBpZihBcnJheS5pc0FycmF5KHRmcykgfHwgQXJyYXkuaXNBcnJheSh0ZmYpKSB7XG4gICAgICAgIC8vIGlmIGFueSB0ZXh0Zm9udCBwYXJhbSBpcyBhcnJheSAtIG1ha2UgcmVuZGVyIGEgYmF0Y2hcbiAgICAgICAgb3B0c091dC5mb250ID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgdmFyIGZvbnRpID0gb3B0c091dC5mb250W2ldID0ge307XG5cbiAgICAgICAgICAgIGZvbnRpLnNpemUgPSBBcnJheS5pc0FycmF5KHRmcykgP1xuICAgICAgICAgICAgICAgIChpc051bWVyaWModGZzW2ldKSA/IHRmc1tpXSA6IDApIDpcbiAgICAgICAgICAgICAgICB0ZnM7XG5cbiAgICAgICAgICAgIGZvbnRpLmZhbWlseSA9IEFycmF5LmlzQXJyYXkodGZmKSA/IHRmZltpXSA6IHRmZjtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGlmIGJvdGggYXJlIHNpbmdsZSB2YWx1ZXMsIG1ha2UgcmVuZGVyIGZhc3Qgc2luZ2xlLXZhbHVlXG4gICAgICAgIG9wdHNPdXQuZm9udCA9IHtzaXplOiB0ZnMsIGZhbWlseTogdGZmfTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3B0c091dDtcbn1cblxuXG5mdW5jdGlvbiBjb252ZXJ0TWFya2VyU3R5bGUodHJhY2UpIHtcbiAgICB2YXIgY291bnQgPSB0cmFjZS5fbGVuZ3RoO1xuICAgIHZhciBvcHRzSW4gPSB0cmFjZS5tYXJrZXI7XG4gICAgdmFyIG9wdHNPdXQgPSB7fTtcbiAgICB2YXIgaTtcblxuICAgIHZhciBtdWx0aVN5bWJvbCA9IEFycmF5LmlzQXJyYXkob3B0c0luLnN5bWJvbCk7XG4gICAgdmFyIG11bHRpQ29sb3IgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShvcHRzSW4uY29sb3IpO1xuICAgIHZhciBtdWx0aUxpbmVDb2xvciA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG9wdHNJbi5saW5lLmNvbG9yKTtcbiAgICB2YXIgbXVsdGlPcGFjaXR5ID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkob3B0c0luLm9wYWNpdHkpO1xuICAgIHZhciBtdWx0aVNpemUgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShvcHRzSW4uc2l6ZSk7XG4gICAgdmFyIG11bHRpTGluZVdpZHRoID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkob3B0c0luLmxpbmUud2lkdGgpO1xuXG4gICAgdmFyIGlzT3BlbjtcbiAgICBpZighbXVsdGlTeW1ib2wpIGlzT3BlbiA9IGNvbnN0YW50cy5PUEVOX1JFLnRlc3Qob3B0c0luLnN5bWJvbCk7XG5cbiAgICAvLyBwcmVwYXJlIGNvbG9yc1xuICAgIGlmKG11bHRpU3ltYm9sIHx8IG11bHRpQ29sb3IgfHwgbXVsdGlMaW5lQ29sb3IgfHwgbXVsdGlPcGFjaXR5KSB7XG4gICAgICAgIG9wdHNPdXQuY29sb3JzID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICAgICAgb3B0c091dC5ib3JkZXJDb2xvcnMgPSBuZXcgQXJyYXkoY291bnQpO1xuXG4gICAgICAgIHZhciBjb2xvcnMgPSBmb3JtYXRDb2xvcihvcHRzSW4sIG9wdHNJbi5vcGFjaXR5LCBjb3VudCk7XG4gICAgICAgIHZhciBib3JkZXJDb2xvcnMgPSBmb3JtYXRDb2xvcihvcHRzSW4ubGluZSwgb3B0c0luLm9wYWNpdHksIGNvdW50KTtcblxuICAgICAgICBpZighQXJyYXkuaXNBcnJheShib3JkZXJDb2xvcnNbMF0pKSB7XG4gICAgICAgICAgICB2YXIgYm9yZGVyQ29sb3IgPSBib3JkZXJDb2xvcnM7XG4gICAgICAgICAgICBib3JkZXJDb2xvcnMgPSBBcnJheShjb3VudCk7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYm9yZGVyQ29sb3JzW2ldID0gYm9yZGVyQ29sb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYoIUFycmF5LmlzQXJyYXkoY29sb3JzWzBdKSkge1xuICAgICAgICAgICAgdmFyIGNvbG9yID0gY29sb3JzO1xuICAgICAgICAgICAgY29sb3JzID0gQXJyYXkoY291bnQpO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbG9yc1tpXSA9IGNvbG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgb3B0c091dC5jb2xvcnMgPSBjb2xvcnM7XG4gICAgICAgIG9wdHNPdXQuYm9yZGVyQ29sb3JzID0gYm9yZGVyQ29sb3JzO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgIGlmKG11bHRpU3ltYm9sKSB7XG4gICAgICAgICAgICAgICAgdmFyIHN5bWJvbCA9IG9wdHNJbi5zeW1ib2xbaV07XG4gICAgICAgICAgICAgICAgaXNPcGVuID0gY29uc3RhbnRzLk9QRU5fUkUudGVzdChzeW1ib2wpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoaXNPcGVuKSB7XG4gICAgICAgICAgICAgICAgYm9yZGVyQ29sb3JzW2ldID0gY29sb3JzW2ldLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgY29sb3JzW2ldID0gY29sb3JzW2ldLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgY29sb3JzW2ldWzNdID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIG9wdHNPdXQub3BhY2l0eSA9IHRyYWNlLm9wYWNpdHk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYoaXNPcGVuKSB7XG4gICAgICAgICAgICBvcHRzT3V0LmNvbG9yID0gcmdiYShvcHRzSW4uY29sb3IsICd1aW50OCcpO1xuICAgICAgICAgICAgb3B0c091dC5jb2xvclszXSA9IDA7XG4gICAgICAgICAgICBvcHRzT3V0LmJvcmRlckNvbG9yID0gcmdiYShvcHRzSW4uY29sb3IsICd1aW50OCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3B0c091dC5jb2xvciA9IHJnYmEob3B0c0luLmNvbG9yLCAndWludDgnKTtcbiAgICAgICAgICAgIG9wdHNPdXQuYm9yZGVyQ29sb3IgPSByZ2JhKG9wdHNJbi5saW5lLmNvbG9yLCAndWludDgnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG9wdHNPdXQub3BhY2l0eSA9IHRyYWNlLm9wYWNpdHkgKiBvcHRzSW4ub3BhY2l0eTtcbiAgICB9XG5cbiAgICAvLyBwcmVwYXJlIHN5bWJvbHNcbiAgICBpZihtdWx0aVN5bWJvbCkge1xuICAgICAgICBvcHRzT3V0Lm1hcmtlcnMgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICBvcHRzT3V0Lm1hcmtlcnNbaV0gPSBnZXRTeW1ib2xTZGYob3B0c0luLnN5bWJvbFtpXSk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBvcHRzT3V0Lm1hcmtlciA9IGdldFN5bWJvbFNkZihvcHRzSW4uc3ltYm9sKTtcbiAgICB9XG5cbiAgICAvLyBwcmVwYXJlIHNpemVzXG4gICAgdmFyIG1hcmtlclNpemVGdW5jID0gbWFrZUJ1YmJsZVNpemVGbih0cmFjZSk7XG4gICAgdmFyIHM7XG5cbiAgICBpZihtdWx0aVNpemUgfHwgbXVsdGlMaW5lV2lkdGgpIHtcbiAgICAgICAgdmFyIHNpemVzID0gb3B0c091dC5zaXplcyA9IG5ldyBBcnJheShjb3VudCk7XG4gICAgICAgIHZhciBib3JkZXJTaXplcyA9IG9wdHNPdXQuYm9yZGVyU2l6ZXMgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgICAgICB2YXIgc2l6ZVRvdGFsID0gMDtcbiAgICAgICAgdmFyIHNpemVBdmc7XG5cbiAgICAgICAgaWYobXVsdGlTaXplKSB7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgc2l6ZXNbaV0gPSBtYXJrZXJTaXplRnVuYyhvcHRzSW4uc2l6ZVtpXSk7XG4gICAgICAgICAgICAgICAgc2l6ZVRvdGFsICs9IHNpemVzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2l6ZUF2ZyA9IHNpemVUb3RhbCAvIGNvdW50O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcyA9IG1hcmtlclNpemVGdW5jKG9wdHNJbi5zaXplKTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBzaXplc1tpXSA9IHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZWUgIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL3B1bGwvMTc4MSNkaXNjdXNzaW9uX3IxMjE4MjA3OThcbiAgICAgICAgaWYobXVsdGlMaW5lV2lkdGgpIHtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBib3JkZXJTaXplc1tpXSA9IG9wdHNJbi5saW5lLndpZHRoW2ldIC8gMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMgPSBvcHRzSW4ubGluZS53aWR0aCAvIDI7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgYm9yZGVyU2l6ZXNbaV0gPSBzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgb3B0c091dC5zaXplQXZnID0gc2l6ZUF2ZztcbiAgICB9IGVsc2Uge1xuICAgICAgICBvcHRzT3V0LnNpemUgPSBtYXJrZXJTaXplRnVuYyhvcHRzSW4gJiYgb3B0c0luLnNpemUgfHwgMTApO1xuICAgICAgICBvcHRzT3V0LmJvcmRlclNpemVzID0gbWFya2VyU2l6ZUZ1bmMob3B0c0luLmxpbmUud2lkdGgpO1xuICAgIH1cblxuICAgIHJldHVybiBvcHRzT3V0O1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0TWFya2VyU2VsZWN0aW9uKHRyYWNlLCB0YXJnZXQpIHtcbiAgICB2YXIgb3B0c0luID0gdHJhY2UubWFya2VyO1xuICAgIHZhciBvcHRzT3V0ID0ge307XG5cbiAgICBpZighdGFyZ2V0KSByZXR1cm4gb3B0c091dDtcblxuICAgIGlmKHRhcmdldC5tYXJrZXIgJiYgdGFyZ2V0Lm1hcmtlci5zeW1ib2wpIHtcbiAgICAgICAgb3B0c091dCA9IGNvbnZlcnRNYXJrZXJTdHlsZShMaWIuZXh0ZW5kRmxhdCh7fSwgb3B0c0luLCB0YXJnZXQubWFya2VyKSk7XG4gICAgfSBlbHNlIGlmKHRhcmdldC5tYXJrZXIpIHtcbiAgICAgICAgaWYodGFyZ2V0Lm1hcmtlci5zaXplKSBvcHRzT3V0LnNpemUgPSB0YXJnZXQubWFya2VyLnNpemUgLyAyO1xuICAgICAgICBpZih0YXJnZXQubWFya2VyLmNvbG9yKSBvcHRzT3V0LmNvbG9ycyA9IHRhcmdldC5tYXJrZXIuY29sb3I7XG4gICAgICAgIGlmKHRhcmdldC5tYXJrZXIub3BhY2l0eSAhPT0gdW5kZWZpbmVkKSBvcHRzT3V0Lm9wYWNpdHkgPSB0YXJnZXQubWFya2VyLm9wYWNpdHk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wdHNPdXQ7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRUZXh0U2VsZWN0aW9uKHRyYWNlLCB0YXJnZXQpIHtcbiAgICB2YXIgb3B0c091dCA9IHt9O1xuXG4gICAgaWYoIXRhcmdldCkgcmV0dXJuIG9wdHNPdXQ7XG5cbiAgICBpZih0YXJnZXQudGV4dGZvbnQpIHtcbiAgICAgICAgdmFyIG9wdHNJbiA9IHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgICAgICB0ZXh0OiB0cmFjZS50ZXh0LFxuICAgICAgICAgICAgdGV4dHBvc2l0aW9uOiB0cmFjZS50ZXh0cG9zaXRpb24sXG4gICAgICAgICAgICB0ZXh0Zm9udDogTGliLmV4dGVuZEZsYXQoe30sIHRyYWNlLnRleHRmb250KVxuICAgICAgICB9O1xuICAgICAgICBpZih0YXJnZXQudGV4dGZvbnQpIHtcbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KG9wdHNJbi50ZXh0Zm9udCwgdGFyZ2V0LnRleHRmb250KTtcbiAgICAgICAgfVxuICAgICAgICBvcHRzT3V0ID0gY29udmVydFRleHRTdHlsZShvcHRzSW4pO1xuICAgIH1cblxuICAgIHJldHVybiBvcHRzT3V0O1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0RXJyb3JCYXJTdHlsZSh0cmFjZSwgdGFyZ2V0KSB7XG4gICAgdmFyIG9wdHNPdXQgPSB7XG4gICAgICAgIGNhcFNpemU6IHRhcmdldC53aWR0aCAqIDIsXG4gICAgICAgIGxpbmVXaWR0aDogdGFyZ2V0LnRoaWNrbmVzcyxcbiAgICAgICAgY29sb3I6IHRhcmdldC5jb2xvclxuICAgIH07XG5cbiAgICBpZih0YXJnZXQuY29weV95c3R5bGUpIHtcbiAgICAgICAgb3B0c091dCA9IHRyYWNlLmVycm9yX3k7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wdHNPdXQ7XG59XG5cbnZhciBTWU1CT0xfU0RGX1NJWkUgPSBjb25zdGFudHMuU1lNQk9MX1NERl9TSVpFO1xudmFyIFNZTUJPTF9TSVpFID0gY29uc3RhbnRzLlNZTUJPTF9TSVpFO1xudmFyIFNZTUJPTF9TVFJPS0UgPSBjb25zdGFudHMuU1lNQk9MX1NUUk9LRTtcbnZhciBTWU1CT0xfU0RGID0ge307XG52YXIgU1lNQk9MX1NWR19DSVJDTEUgPSBEcmF3aW5nLnN5bWJvbEZ1bmNzWzBdKFNZTUJPTF9TSVpFICogMC4wNSk7XG5cbmZ1bmN0aW9uIGdldFN5bWJvbFNkZihzeW1ib2wpIHtcbiAgICBpZihzeW1ib2wgPT09ICdjaXJjbGUnKSByZXR1cm4gbnVsbDtcblxuICAgIHZhciBzeW1ib2xQYXRoLCBzeW1ib2xTZGY7XG4gICAgdmFyIHN5bWJvbE51bWJlciA9IERyYXdpbmcuc3ltYm9sTnVtYmVyKHN5bWJvbCk7XG4gICAgdmFyIHN5bWJvbEZ1bmMgPSBEcmF3aW5nLnN5bWJvbEZ1bmNzW3N5bWJvbE51bWJlciAlIDEwMF07XG4gICAgdmFyIHN5bWJvbE5vRG90ID0gISFEcmF3aW5nLnN5bWJvbE5vRG90W3N5bWJvbE51bWJlciAlIDEwMF07XG4gICAgdmFyIHN5bWJvbE5vRmlsbCA9ICEhRHJhd2luZy5zeW1ib2xOb0ZpbGxbc3ltYm9sTnVtYmVyICUgMTAwXTtcblxuICAgIHZhciBpc0RvdCA9IGNvbnN0YW50cy5ET1RfUkUudGVzdChzeW1ib2wpO1xuXG4gICAgLy8gZ2V0IHN5bWJvbCBzZGYgZnJvbSBjYWNoZSBvciBnZW5lcmF0ZSBpdFxuICAgIGlmKFNZTUJPTF9TREZbc3ltYm9sXSkgcmV0dXJuIFNZTUJPTF9TREZbc3ltYm9sXTtcblxuICAgIGlmKGlzRG90ICYmICFzeW1ib2xOb0RvdCkge1xuICAgICAgICBzeW1ib2xQYXRoID0gc3ltYm9sRnVuYyhTWU1CT0xfU0laRSAqIDEuMSkgKyBTWU1CT0xfU1ZHX0NJUkNMRTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzeW1ib2xQYXRoID0gc3ltYm9sRnVuYyhTWU1CT0xfU0laRSk7XG4gICAgfVxuXG4gICAgc3ltYm9sU2RmID0gc3ZnU2RmKHN5bWJvbFBhdGgsIHtcbiAgICAgICAgdzogU1lNQk9MX1NERl9TSVpFLFxuICAgICAgICBoOiBTWU1CT0xfU0RGX1NJWkUsXG4gICAgICAgIHZpZXdCb3g6IFstU1lNQk9MX1NJWkUsIC1TWU1CT0xfU0laRSwgU1lNQk9MX1NJWkUsIFNZTUJPTF9TSVpFXSxcbiAgICAgICAgc3Ryb2tlOiBzeW1ib2xOb0ZpbGwgPyBTWU1CT0xfU1RST0tFIDogLVNZTUJPTF9TVFJPS0VcbiAgICB9KTtcbiAgICBTWU1CT0xfU0RGW3N5bWJvbF0gPSBzeW1ib2xTZGY7XG5cbiAgICByZXR1cm4gc3ltYm9sU2RmIHx8IG51bGw7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRMaW5lUG9zaXRpb25zKGdkLCB0cmFjZSwgcG9zaXRpb25zKSB7XG4gICAgdmFyIGxlbiA9IHBvc2l0aW9ucy5sZW5ndGg7XG4gICAgdmFyIGNvdW50ID0gbGVuIC8gMjtcbiAgICB2YXIgbGluZVBvc2l0aW9ucztcbiAgICB2YXIgaTtcblxuICAgIGlmKHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlKSAmJiBjb3VudCkge1xuICAgICAgICBpZih0cmFjZS5saW5lLnNoYXBlID09PSAnaHYnKSB7XG4gICAgICAgICAgICBsaW5lUG9zaXRpb25zID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudCAtIDE7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKGlzTmFOKHBvc2l0aW9uc1tpICogMl0pIHx8IGlzTmFOKHBvc2l0aW9uc1tpICogMiArIDFdKSkge1xuICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2goTmFOLCBOYU4sIE5hTiwgTmFOKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2kgKiAyXSwgcG9zaXRpb25zW2kgKiAyICsgMV0pO1xuICAgICAgICAgICAgICAgICAgICBpZighaXNOYU4ocG9zaXRpb25zW2kgKiAyICsgMl0pICYmICFpc05hTihwb3NpdGlvbnNbaSAqIDIgKyAzXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChwb3NpdGlvbnNbaSAqIDIgKyAyXSwgcG9zaXRpb25zW2kgKiAyICsgMV0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKE5hTiwgTmFOKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChwb3NpdGlvbnNbbGVuIC0gMl0sIHBvc2l0aW9uc1tsZW4gLSAxXSk7XG4gICAgICAgIH0gZWxzZSBpZih0cmFjZS5saW5lLnNoYXBlID09PSAnaHZoJykge1xuICAgICAgICAgICAgbGluZVBvc2l0aW9ucyA9IFtdO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQgLSAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZihpc05hTihwb3NpdGlvbnNbaSAqIDJdKSB8fCBpc05hTihwb3NpdGlvbnNbaSAqIDIgKyAxXSkgfHwgaXNOYU4ocG9zaXRpb25zW2kgKiAyICsgMl0pIHx8IGlzTmFOKHBvc2l0aW9uc1tpICogMiArIDNdKSkge1xuICAgICAgICAgICAgICAgICAgICBpZighaXNOYU4ocG9zaXRpb25zW2kgKiAyXSkgJiYgIWlzTmFOKHBvc2l0aW9uc1tpICogMiArIDFdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKHBvc2l0aW9uc1tpICogMl0sIHBvc2l0aW9uc1tpICogMiArIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChOYU4sIE5hTik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKE5hTiwgTmFOKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWlkUHRYID0gKHBvc2l0aW9uc1tpICogMl0gKyBwb3NpdGlvbnNbaSAqIDIgKyAyXSkgLyAyO1xuICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2goXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbaSAqIDJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zW2kgKiAyICsgMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBtaWRQdFgsXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbaSAqIDIgKyAxXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pZFB0WCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uc1tpICogMiArIDNdXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKHBvc2l0aW9uc1tsZW4gLSAyXSwgcG9zaXRpb25zW2xlbiAtIDFdKTtcbiAgICAgICAgfSBlbHNlIGlmKHRyYWNlLmxpbmUuc2hhcGUgPT09ICd2aHYnKSB7XG4gICAgICAgICAgICBsaW5lUG9zaXRpb25zID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudCAtIDE7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKGlzTmFOKHBvc2l0aW9uc1tpICogMl0pIHx8IGlzTmFOKHBvc2l0aW9uc1tpICogMiArIDFdKSB8fCBpc05hTihwb3NpdGlvbnNbaSAqIDIgKyAyXSkgfHwgaXNOYU4ocG9zaXRpb25zW2kgKiAyICsgM10pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCFpc05hTihwb3NpdGlvbnNbaSAqIDJdKSAmJiAhaXNOYU4ocG9zaXRpb25zW2kgKiAyICsgMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2kgKiAyXSwgcG9zaXRpb25zW2kgKiAyICsgMV0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKE5hTiwgTmFOKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2goTmFOLCBOYU4pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtaWRQdFkgPSAocG9zaXRpb25zW2kgKiAyICsgMV0gKyBwb3NpdGlvbnNbaSAqIDIgKyAzXSkgLyAyO1xuICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2goXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbaSAqIDJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zW2kgKiAyICsgMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbaSAqIDJdLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWlkUHRZLFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zW2kgKiAyICsgMl0sXG4gICAgICAgICAgICAgICAgICAgICAgICBtaWRQdFlcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2xlbiAtIDJdLCBwb3NpdGlvbnNbbGVuIC0gMV0pO1xuICAgICAgICB9IGVsc2UgaWYodHJhY2UubGluZS5zaGFwZSA9PT0gJ3ZoJykge1xuICAgICAgICAgICAgbGluZVBvc2l0aW9ucyA9IFtdO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQgLSAxOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZihpc05hTihwb3NpdGlvbnNbaSAqIDJdKSB8fCBpc05hTihwb3NpdGlvbnNbaSAqIDIgKyAxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKE5hTiwgTmFOLCBOYU4sIE5hTik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKHBvc2l0aW9uc1tpICogMl0sIHBvc2l0aW9uc1tpICogMiArIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoIWlzTmFOKHBvc2l0aW9uc1tpICogMiArIDJdKSAmJiAhaXNOYU4ocG9zaXRpb25zW2kgKiAyICsgM10pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaW5lUG9zaXRpb25zLnB1c2gocG9zaXRpb25zW2kgKiAyXSwgcG9zaXRpb25zW2kgKiAyICsgM10pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGluZVBvc2l0aW9ucy5wdXNoKE5hTiwgTmFOKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpbmVQb3NpdGlvbnMucHVzaChwb3NpdGlvbnNbbGVuIC0gMl0sIHBvc2l0aW9uc1tsZW4gLSAxXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsaW5lUG9zaXRpb25zID0gcG9zaXRpb25zO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSWYgd2UgaGF2ZSBkYXRhIHdpdGggZ2Fwcywgd2Ugb3VnaHQgdG8gdXNlIHJlY3Qgam9pbnNcbiAgICAvLyBGSVhNRTogZ2V0IHJpZCBvZiB0aGlzXG4gICAgdmFyIGhhc05hTiA9IGZhbHNlO1xuICAgIGZvcihpID0gMDsgaSA8IGxpbmVQb3NpdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoaXNOYU4obGluZVBvc2l0aW9uc1tpXSkpIHtcbiAgICAgICAgICAgIGhhc05hTiA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBqb2luID0gKGhhc05hTiB8fCBsaW5lUG9zaXRpb25zLmxlbmd0aCA+IGNvbnN0YW50cy5UT09fTUFOWV9QT0lOVFMpID8gJ3JlY3QnIDpcbiAgICAgICAgc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkgPyAncmVjdCcgOiAncm91bmQnO1xuXG4gICAgLy8gZmlsbCBnYXBzXG4gICAgaWYoaGFzTmFOICYmIHRyYWNlLmNvbm5lY3RnYXBzKSB7XG4gICAgICAgIHZhciBsYXN0WCA9IGxpbmVQb3NpdGlvbnNbMF07XG4gICAgICAgIHZhciBsYXN0WSA9IGxpbmVQb3NpdGlvbnNbMV07XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGluZVBvc2l0aW9ucy5sZW5ndGg7IGkgKz0gMikge1xuICAgICAgICAgICAgaWYoaXNOYU4obGluZVBvc2l0aW9uc1tpXSkgfHwgaXNOYU4obGluZVBvc2l0aW9uc1tpICsgMV0pKSB7XG4gICAgICAgICAgICAgICAgbGluZVBvc2l0aW9uc1tpXSA9IGxhc3RYO1xuICAgICAgICAgICAgICAgIGxpbmVQb3NpdGlvbnNbaSArIDFdID0gbGFzdFk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGxhc3RYID0gbGluZVBvc2l0aW9uc1tpXTtcbiAgICAgICAgICAgICAgICBsYXN0WSA9IGxpbmVQb3NpdGlvbnNbaSArIDFdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgam9pbjogam9pbixcbiAgICAgICAgcG9zaXRpb25zOiBsaW5lUG9zaXRpb25zXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY29udmVydEVycm9yQmFyUG9zaXRpb25zKGdkLCB0cmFjZSwgcG9zaXRpb25zLCB4LCB5KSB7XG4gICAgdmFyIG1ha2VDb21wdXRlRXJyb3IgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2Vycm9yYmFycycsICdtYWtlQ29tcHV0ZUVycm9yJyk7XG4gICAgdmFyIHhhID0gQXhpc0lEcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLnhheGlzKTtcbiAgICB2YXIgeWEgPSBBeGlzSURzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMpO1xuICAgIHZhciBjb3VudCA9IHBvc2l0aW9ucy5sZW5ndGggLyAyO1xuICAgIHZhciBvdXQgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGNvbnZlcnRPbmVBeGlzKGNvb3JkcywgYXgpIHtcbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXguX2lkLmNoYXJBdCgwKTtcbiAgICAgICAgdmFyIG9wdHMgPSB0cmFjZVsnZXJyb3JfJyArIGF4TGV0dGVyXTtcblxuICAgICAgICBpZihvcHRzICYmIG9wdHMudmlzaWJsZSAmJiAoYXgudHlwZSA9PT0gJ2xpbmVhcicgfHwgYXgudHlwZSA9PT0gJ2xvZycpKSB7XG4gICAgICAgICAgICB2YXIgY29tcHV0ZUVycm9yID0gbWFrZUNvbXB1dGVFcnJvcihvcHRzKTtcbiAgICAgICAgICAgIHZhciBwT2Zmc2V0ID0ge3g6IDAsIHk6IDF9W2F4TGV0dGVyXTtcbiAgICAgICAgICAgIHZhciBlT2Zmc2V0ID0ge3g6IFswLCAxLCAyLCAzXSwgeTogWzIsIDMsIDAsIDFdfVtheExldHRlcl07XG4gICAgICAgICAgICB2YXIgZXJyb3JzID0gbmV3IEZsb2F0NjRBcnJheSg0ICogY291bnQpO1xuICAgICAgICAgICAgdmFyIG1pblNob2UgPSBJbmZpbml0eTtcbiAgICAgICAgICAgIHZhciBtYXhIYXQgPSAtSW5maW5pdHk7XG5cbiAgICAgICAgICAgIGZvcih2YXIgaSA9IDAsIGogPSAwOyBpIDwgY291bnQ7IGkrKywgaiArPSA0KSB7XG4gICAgICAgICAgICAgICAgdmFyIGRjID0gY29vcmRzW2ldO1xuXG4gICAgICAgICAgICAgICAgaWYoaXNOdW1lcmljKGRjKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGwgPSBwb3NpdGlvbnNbaSAqIDIgKyBwT2Zmc2V0XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHMgPSBjb21wdXRlRXJyb3IoZGMsIGkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbHYgPSB2YWxzWzBdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaHYgPSB2YWxzWzFdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGlzTnVtZXJpYyhsdikgJiYgaXNOdW1lcmljKGh2KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHNob2UgPSBkYyAtIGx2O1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGhhdCA9IGRjICsgaHY7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yc1tqICsgZU9mZnNldFswXV0gPSBkbCAtIGF4LmMybChzaG9lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yc1tqICsgZU9mZnNldFsxXV0gPSBheC5jMmwoaGF0KSAtIGRsO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzW2ogKyBlT2Zmc2V0WzJdXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnNbaiArIGVPZmZzZXRbM11dID0gMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgbWluU2hvZSA9IE1hdGgubWluKG1pblNob2UsIGRjIC0gbHYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SGF0ID0gTWF0aC5tYXgobWF4SGF0LCBkYyArIGh2KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgb3V0W2F4TGV0dGVyXSA9IHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbnM6IHBvc2l0aW9ucyxcbiAgICAgICAgICAgICAgICBlcnJvcnM6IGVycm9ycyxcbiAgICAgICAgICAgICAgICBfYm5kczogW21pblNob2UsIG1heEhhdF1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb252ZXJ0T25lQXhpcyh4LCB4YSk7XG4gICAgY29udmVydE9uZUF4aXMoeSwgeWEpO1xuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRUZXh0UG9zaXRpb24oZ2QsIHRyYWNlLCB0ZXh0T3B0cywgbWFya2VyT3B0cykge1xuICAgIHZhciBjb3VudCA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIG91dCA9IHt9O1xuICAgIHZhciBpO1xuXG4gICAgLy8gY29ycmVzcG9uZHMgdG8gdGV4dFBvaW50UG9zaXRpb24gZnJvbSBjb21wb25lbnQuZHJhd2luZ1xuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpKSB7XG4gICAgICAgIHZhciBmb250T3B0cyA9IHRleHRPcHRzLmZvbnQ7XG4gICAgICAgIHZhciBhbGlnbiA9IHRleHRPcHRzLmFsaWduO1xuICAgICAgICB2YXIgYmFzZWxpbmUgPSB0ZXh0T3B0cy5iYXNlbGluZTtcbiAgICAgICAgb3V0Lm9mZnNldCA9IG5ldyBBcnJheShjb3VudCk7XG5cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgdmFyIG1zID0gbWFya2VyT3B0cy5zaXplcyA/IG1hcmtlck9wdHMuc2l6ZXNbaV0gOiBtYXJrZXJPcHRzLnNpemU7XG4gICAgICAgICAgICB2YXIgZnMgPSBBcnJheS5pc0FycmF5KGZvbnRPcHRzKSA/IGZvbnRPcHRzW2ldLnNpemUgOiBmb250T3B0cy5zaXplO1xuXG4gICAgICAgICAgICB2YXIgYSA9IEFycmF5LmlzQXJyYXkoYWxpZ24pID9cbiAgICAgICAgICAgICAgICAoYWxpZ24ubGVuZ3RoID4gMSA/IGFsaWduW2ldIDogYWxpZ25bMF0pIDpcbiAgICAgICAgICAgICAgICBhbGlnbjtcbiAgICAgICAgICAgIHZhciBiID0gQXJyYXkuaXNBcnJheShiYXNlbGluZSkgP1xuICAgICAgICAgICAgICAgIChiYXNlbGluZS5sZW5ndGggPiAxID8gYmFzZWxpbmVbaV0gOiBiYXNlbGluZVswXSkgOlxuICAgICAgICAgICAgICAgIGJhc2VsaW5lO1xuXG4gICAgICAgICAgICB2YXIgaFNpZ24gPSBURVhUT0ZGU0VUU0lHTlthXTtcbiAgICAgICAgICAgIHZhciB2U2lnbiA9IFRFWFRPRkZTRVRTSUdOW2JdO1xuICAgICAgICAgICAgdmFyIHhQYWQgPSBtcyA/IG1zIC8gMC44ICsgMSA6IDA7XG4gICAgICAgICAgICB2YXIgeVBhZCA9IC12U2lnbiAqIHhQYWQgLSB2U2lnbiAqIDAuNTtcbiAgICAgICAgICAgIG91dC5vZmZzZXRbaV0gPSBbaFNpZ24gKiB4UGFkIC8gZnMsIHlQYWQgLyBmc107XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBzdHlsZTogY29udmVydFN0eWxlLFxuXG4gICAgbWFya2VyU3R5bGU6IGNvbnZlcnRNYXJrZXJTdHlsZSxcbiAgICBtYXJrZXJTZWxlY3Rpb246IGNvbnZlcnRNYXJrZXJTZWxlY3Rpb24sXG5cbiAgICBsaW5lUG9zaXRpb25zOiBjb252ZXJ0TGluZVBvc2l0aW9ucyxcbiAgICBlcnJvckJhclBvc2l0aW9uczogY29udmVydEVycm9yQmFyUG9zaXRpb25zLFxuICAgIHRleHRQb3NpdGlvbjogY29udmVydFRleHRQb3NpdGlvblxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9jb25zdGFudHMvaW50ZXJhY3Rpb25zXCI6Njk0LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vbGliL2dsX2Zvcm1hdF9jb2xvclwiOjcxNixcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkc1wiOjc3MCxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vc2NhdHRlci9tYWtlX2J1YmJsZV9zaXplX2Z1bmNcIjoxMTI4LFwiLi4vc2NhdHRlci9zdWJ0eXBlc1wiOjExMzUsXCIuL2NvbnN0YW50c1wiOjExNjIsXCJjb2xvci1ub3JtYWxpemVcIjoxMjAsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNSxcInN2Zy1wYXRoLXNkZlwiOjUzNX1dLDExNjQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xuXG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY29uc3RhbnRzJyk7XG52YXIgc3ViVHlwZXMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgaGFuZGxlWFlEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIveHlfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVNYXJrZXJEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZURlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlRmlsbENvbG9yRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2ZpbGxjb2xvcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRleHREZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgaXNPcGVuID0gdHJhY2VJbi5tYXJrZXIgPyAvLW9wZW4vLnRlc3QodHJhY2VJbi5tYXJrZXIuc3ltYm9sKSA6IGZhbHNlO1xuICAgIHZhciBpc0J1YmJsZSA9IHN1YlR5cGVzLmlzQnViYmxlKHRyYWNlSW4pO1xuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgZGVmYXVsdE1vZGUgPSBsZW4gPCBjb25zdGFudHMuUFRTX0xJTkVTT05MWSA/ICdsaW5lcyttYXJrZXJzJyA6ICdsaW5lcyc7XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuICAgIGNvZXJjZSgnbW9kZScsIGRlZmF1bHRNb2RlKTtcblxuICAgIGlmKHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlT3V0KSkge1xuICAgICAgICBjb2VyY2UoJ2Nvbm5lY3RnYXBzJyk7XG4gICAgICAgIGhhbmRsZUxpbmVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSk7XG4gICAgICAgIGNvZXJjZSgnbGluZS5zaGFwZScpO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZU1hcmtlckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICAgICAgY29lcmNlKCdtYXJrZXIubGluZS53aWR0aCcsIGlzT3BlbiB8fCBpc0J1YmJsZSA/IDEgOiAwKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNUZXh0KHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVUZXh0RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICB2YXIgbGluZUNvbG9yID0gKHRyYWNlT3V0LmxpbmUgfHwge30pLmNvbG9yO1xuICAgIHZhciBtYXJrZXJDb2xvciA9ICh0cmFjZU91dC5tYXJrZXIgfHwge30pLmNvbG9yO1xuXG4gICAgY29lcmNlKCdmaWxsJyk7XG4gICAgaWYodHJhY2VPdXQuZmlsbCAhPT0gJ25vbmUnKSB7XG4gICAgICAgIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGNvZXJjZSk7XG4gICAgfVxuXG4gICAgdmFyIGVycm9yQmFyc1N1cHBseURlZmF1bHRzID0gUmVnaXN0cnkuZ2V0Q29tcG9uZW50TWV0aG9kKCdlcnJvcmJhcnMnLCAnc3VwcGx5RGVmYXVsdHMnKTtcbiAgICBlcnJvckJhcnNTdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGluZUNvbG9yIHx8IG1hcmtlckNvbG9yIHx8IGRlZmF1bHRDb2xvciwge2F4aXM6ICd5J30pO1xuICAgIGVycm9yQmFyc1N1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsaW5lQ29sb3IgfHwgbWFya2VyQ29sb3IgfHwgZGVmYXVsdENvbG9yLCB7YXhpczogJ3gnLCBpbmhlcml0OiAneSd9KTtcblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4uL3NjYXR0ZXIvY29uc3RhbnRzXCI6MTExNixcIi4uL3NjYXR0ZXIvZmlsbGNvbG9yX2RlZmF1bHRzXCI6MTEyMCxcIi4uL3NjYXR0ZXIvbGluZV9kZWZhdWx0c1wiOjExMjQsXCIuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0c1wiOjExMzAsXCIuLi9zY2F0dGVyL3N1YnR5cGVzXCI6MTEzNSxcIi4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0c1wiOjExMzYsXCIuLi9zY2F0dGVyL3h5X2RlZmF1bHRzXCI6MTEzNyxcIi4vYXR0cmlidXRlc1wiOjExNjB9XSwxMTY1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG52YXIgREVTRUxFQ1RESU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvaW50ZXJhY3Rpb25zJykuREVTRUxFQ1RESU07XG5cbmZ1bmN0aW9uIHN0eWxlVGV4dFNlbGVjdGlvbihjZCkge1xuICAgIHZhciBjZDAgPSBjZFswXTtcbiAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgdmFyIHN0YXNoID0gY2QwLnQ7XG4gICAgdmFyIHNjZW5lID0gc3Rhc2guX3NjZW5lO1xuICAgIHZhciBpbmRleCA9IHN0YXNoLmluZGV4O1xuICAgIHZhciBlbHMgPSBzY2VuZS5zZWxlY3RCYXRjaFtpbmRleF07XG4gICAgdmFyIHVuZWxzID0gc2NlbmUudW5zZWxlY3RCYXRjaFtpbmRleF07XG4gICAgdmFyIGJhc2VPcHRzID0gc2NlbmUudGV4dE9wdGlvbnNbaW5kZXhdO1xuICAgIHZhciBzZWxPcHRzID0gc2NlbmUudGV4dFNlbGVjdGVkT3B0aW9uc1tpbmRleF0gfHwge307XG4gICAgdmFyIHVuc2VsT3B0cyA9IHNjZW5lLnRleHRVbnNlbGVjdGVkT3B0aW9uc1tpbmRleF0gfHwge307XG4gICAgdmFyIG9wdHMgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgYmFzZU9wdHMpO1xuICAgIHZhciBpLCBqO1xuXG4gICAgaWYoZWxzLmxlbmd0aCB8fCB1bmVscy5sZW5ndGgpIHtcbiAgICAgICAgdmFyIHN0YyA9IHNlbE9wdHMuY29sb3I7XG4gICAgICAgIHZhciB1dGMgPSB1bnNlbE9wdHMuY29sb3I7XG4gICAgICAgIHZhciBiYXNlID0gYmFzZU9wdHMuY29sb3I7XG4gICAgICAgIHZhciBoYXNBcnJheUJhc2UgPSBBcnJheS5pc0FycmF5KGJhc2UpO1xuICAgICAgICBvcHRzLmNvbG9yID0gbmV3IEFycmF5KHRyYWNlLl9sZW5ndGgpO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGVscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaiA9IGVsc1tpXTtcbiAgICAgICAgICAgIG9wdHMuY29sb3Jbal0gPSBzdGMgfHwgKGhhc0FycmF5QmFzZSA/IGJhc2Vbal0gOiBiYXNlKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IDA7IGkgPCB1bmVscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaiA9IHVuZWxzW2ldO1xuICAgICAgICAgICAgdmFyIGJhc2VqID0gaGFzQXJyYXlCYXNlID8gYmFzZVtqXSA6IGJhc2U7XG4gICAgICAgICAgICBvcHRzLmNvbG9yW2pdID0gdXRjID8gdXRjIDpcbiAgICAgICAgICAgICAgICBzdGMgPyBiYXNlaiA6IENvbG9yLmFkZE9wYWNpdHkoYmFzZWosIERFU0VMRUNURElNKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNjZW5lLmdsVGV4dFtpbmRleF0udXBkYXRlKG9wdHMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBzdHlsZVRleHRTZWxlY3Rpb246IHN0eWxlVGV4dFNlbGVjdGlvblxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29uc3RhbnRzL2ludGVyYWN0aW9uc1wiOjY5NCxcIi4uLy4uL2xpYlwiOjcxOX1dLDExNjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGdldFRyYWNlQ29sb3IgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2dldF90cmFjZV9jb2xvcicpO1xuXG5mdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBjZCA9IHBvaW50RGF0YS5jZDtcbiAgICB2YXIgc3Rhc2ggPSBjZFswXS50O1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciB4YSA9IHBvaW50RGF0YS54YTtcbiAgICB2YXIgeWEgPSBwb2ludERhdGEueWE7XG4gICAgdmFyIHggPSBzdGFzaC54O1xuICAgIHZhciB5ID0gc3Rhc2gueTtcbiAgICB2YXIgeHB4ID0geGEuYzJwKHh2YWwpO1xuICAgIHZhciB5cHggPSB5YS5jMnAoeXZhbCk7XG4gICAgdmFyIG1heERpc3RhbmNlID0gcG9pbnREYXRhLmRpc3RhbmNlO1xuICAgIHZhciBpZHM7XG5cbiAgICAvLyBGSVhNRTogbWFrZSBzdXJlIHRoaXMgaXMgYSBwcm9wZXIgd2F5IHRvIGNhbGMgc2VhcmNoIHJhZGl1c1xuICAgIGlmKHN0YXNoLnRyZWUpIHtcbiAgICAgICAgdmFyIHhsID0geGEucDJjKHhweCAtIG1heERpc3RhbmNlKTtcbiAgICAgICAgdmFyIHhyID0geGEucDJjKHhweCArIG1heERpc3RhbmNlKTtcbiAgICAgICAgdmFyIHlsID0geWEucDJjKHlweCAtIG1heERpc3RhbmNlKTtcbiAgICAgICAgdmFyIHlyID0geWEucDJjKHlweCArIG1heERpc3RhbmNlKTtcblxuICAgICAgICBpZihob3Zlcm1vZGUgPT09ICd4Jykge1xuICAgICAgICAgICAgaWRzID0gc3Rhc2gudHJlZS5yYW5nZShcbiAgICAgICAgICAgICAgICBNYXRoLm1pbih4bCwgeHIpLCBNYXRoLm1pbih5YS5fcmxbMF0sIHlhLl9ybFsxXSksXG4gICAgICAgICAgICAgICAgTWF0aC5tYXgoeGwsIHhyKSwgTWF0aC5tYXgoeWEuX3JsWzBdLCB5YS5fcmxbMV0pXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWRzID0gc3Rhc2gudHJlZS5yYW5nZShcbiAgICAgICAgICAgICAgICBNYXRoLm1pbih4bCwgeHIpLCBNYXRoLm1pbih5bCwgeXIpLFxuICAgICAgICAgICAgICAgIE1hdGgubWF4KHhsLCB4ciksIE1hdGgubWF4KHlsLCB5cilcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYoc3Rhc2guaWRzKSB7XG4gICAgICAgIGlkcyA9IHN0YXNoLmlkcztcbiAgICB9IGVsc2UgcmV0dXJuIFtwb2ludERhdGFdO1xuXG4gICAgLy8gcGljayB0aGUgaWQgY2xvc2VzdCB0byB0aGUgcG9pbnRcbiAgICAvLyBub3RlIHRoYXQgcG9pbnQgcG9zc2libHkgbWF5IG5vdCBiZSBmb3VuZFxuICAgIHZhciBpZCwgcHR4LCBwdHksIGksIGR4LCBkeSwgZGlzdCwgZHh5O1xuXG4gICAgdmFyIG1pbkRpc3QgPSBtYXhEaXN0YW5jZTtcbiAgICBpZihob3Zlcm1vZGUgPT09ICd4Jykge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHB0eCA9IHhbaWRzW2ldXTtcbiAgICAgICAgICAgIGR4ID0gTWF0aC5hYnMoeGEuYzJwKHB0eCkgLSB4cHgpO1xuICAgICAgICAgICAgaWYoZHggPCBtaW5EaXN0KSB7XG4gICAgICAgICAgICAgICAgbWluRGlzdCA9IGR4O1xuICAgICAgICAgICAgICAgIGR5ID0geWEuYzJwKHlbaWRzW2ldXSkgLSB5cHg7XG4gICAgICAgICAgICAgICAgZHh5ID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgICAgICAgICAgICAgICBpZCA9IGlkc1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGZvcihpID0gaWRzLmxlbmd0aCAtIDE7IGkgPiAtMTsgaS0tKSB7XG4gICAgICAgICAgICBwdHggPSB4W2lkc1tpXV07XG4gICAgICAgICAgICBwdHkgPSB5W2lkc1tpXV07XG4gICAgICAgICAgICBkeCA9IHhhLmMycChwdHgpIC0geHB4O1xuICAgICAgICAgICAgZHkgPSB5YS5jMnAocHR5KSAtIHlweDtcblxuICAgICAgICAgICAgZGlzdCA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gICAgICAgICAgICBpZihkaXN0IDwgbWluRGlzdCkge1xuICAgICAgICAgICAgICAgIG1pbkRpc3QgPSBkeHkgPSBkaXN0O1xuICAgICAgICAgICAgICAgIGlkID0gaWRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcG9pbnREYXRhLmluZGV4ID0gaWQ7XG4gICAgcG9pbnREYXRhLmRpc3RhbmNlID0gbWluRGlzdDtcbiAgICBwb2ludERhdGEuZHh5ID0gZHh5O1xuXG4gICAgaWYoaWQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIFtwb2ludERhdGFdO1xuXG4gICAgY2FsY0hvdmVyKHBvaW50RGF0YSwgeCwgeSwgdHJhY2UpO1xuXG4gICAgcmV0dXJuIFtwb2ludERhdGFdO1xufVxuXG5mdW5jdGlvbiBjYWxjSG92ZXIocG9pbnREYXRhLCB4LCB5LCB0cmFjZSkge1xuICAgIHZhciB4YSA9IHBvaW50RGF0YS54YTtcbiAgICB2YXIgeWEgPSBwb2ludERhdGEueWE7XG4gICAgdmFyIG1pbkRpc3QgPSBwb2ludERhdGEuZGlzdGFuY2U7XG4gICAgdmFyIGR4eSA9IHBvaW50RGF0YS5keHk7XG4gICAgdmFyIGlkID0gcG9pbnREYXRhLmluZGV4O1xuXG4gICAgLy8gdGhlIGNsb3Nlc3QgZGF0YSBwb2ludFxuICAgIHZhciBkaSA9IHtcbiAgICAgICAgcG9pbnROdW1iZXI6IGlkLFxuICAgICAgICB4OiB4W2lkXSxcbiAgICAgICAgeTogeVtpZF1cbiAgICB9O1xuXG4gICAgLy8gdGhhdCBpcyBzaW5nbGUtaXRlbSBhcnJheXNfdG9fY2FsY2RhdGEgZXhjZXJwdCwgc2luY2Ugd2UgYXJlIGRvaW5nIGl0IGZvciBhIHNpbmdsZSBwb2ludCBhbmQgd2UgZG9uJ3QgaGF2ZSB0byBkbyBpdCBiZWZvcmVoZWFkIGZvciAxZTYgcG9pbnRzXG4gICAgZGkudHggPSBBcnJheS5pc0FycmF5KHRyYWNlLnRleHQpID8gdHJhY2UudGV4dFtpZF0gOiB0cmFjZS50ZXh0O1xuICAgIGRpLmh0eCA9IEFycmF5LmlzQXJyYXkodHJhY2UuaG92ZXJ0ZXh0KSA/IHRyYWNlLmhvdmVydGV4dFtpZF0gOiB0cmFjZS5ob3ZlcnRleHQ7XG4gICAgZGkuZGF0YSA9IEFycmF5LmlzQXJyYXkodHJhY2UuY3VzdG9tZGF0YSkgPyB0cmFjZS5jdXN0b21kYXRhW2lkXSA6IHRyYWNlLmN1c3RvbWRhdGE7XG4gICAgZGkudHAgPSBBcnJheS5pc0FycmF5KHRyYWNlLnRleHRwb3NpdGlvbikgPyB0cmFjZS50ZXh0cG9zaXRpb25baWRdIDogdHJhY2UudGV4dHBvc2l0aW9uO1xuXG4gICAgdmFyIGZvbnQgPSB0cmFjZS50ZXh0Zm9udDtcbiAgICBpZihmb250KSB7XG4gICAgICAgIGRpLnRzID0gQXJyYXkuaXNBcnJheShmb250LnNpemUpID8gZm9udC5zaXplW2lkXSA6IGZvbnQuc2l6ZTtcbiAgICAgICAgZGkudGMgPSBBcnJheS5pc0FycmF5KGZvbnQuY29sb3IpID8gZm9udC5jb2xvcltpZF0gOiBmb250LmNvbG9yO1xuICAgICAgICBkaS50ZiA9IEFycmF5LmlzQXJyYXkoZm9udC5mYW1pbHkpID8gZm9udC5mYW1pbHlbaWRdIDogZm9udC5mYW1pbHk7XG4gICAgfVxuXG4gICAgdmFyIG1hcmtlciA9IHRyYWNlLm1hcmtlcjtcbiAgICBpZihtYXJrZXIpIHtcbiAgICAgICAgZGkubXMgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXIuc2l6ZSkgPyBtYXJrZXIuc2l6ZVtpZF0gOiBtYXJrZXIuc2l6ZTtcbiAgICAgICAgZGkubW8gPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXIub3BhY2l0eSkgPyBtYXJrZXIub3BhY2l0eVtpZF0gOiBtYXJrZXIub3BhY2l0eTtcbiAgICAgICAgZGkubXggPSBBcnJheS5pc0FycmF5KG1hcmtlci5zeW1ib2wpID8gbWFya2VyLnN5bWJvbFtpZF0gOiBtYXJrZXIuc3ltYm9sO1xuICAgICAgICBkaS5tYyA9IExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG1hcmtlci5jb2xvcikgPyBtYXJrZXIuY29sb3JbaWRdIDogbWFya2VyLmNvbG9yO1xuICAgIH1cblxuICAgIHZhciBsaW5lID0gbWFya2VyICYmIG1hcmtlci5saW5lO1xuICAgIGlmKGxpbmUpIHtcbiAgICAgICAgZGkubWxjID0gQXJyYXkuaXNBcnJheShsaW5lLmNvbG9yKSA/IGxpbmUuY29sb3JbaWRdIDogbGluZS5jb2xvcjtcbiAgICAgICAgZGkubWx3ID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobGluZS53aWR0aCkgPyBsaW5lLndpZHRoW2lkXSA6IGxpbmUud2lkdGg7XG4gICAgfVxuXG4gICAgdmFyIGdyYWQgPSBtYXJrZXIgJiYgbWFya2VyLmdyYWRpZW50O1xuICAgIGlmKGdyYWQgJiYgZ3JhZC50eXBlICE9PSAnbm9uZScpIHtcbiAgICAgICAgZGkubWd0ID0gQXJyYXkuaXNBcnJheShncmFkLnR5cGUpID8gZ3JhZC50eXBlW2lkXSA6IGdyYWQudHlwZTtcbiAgICAgICAgZGkubWdjID0gQXJyYXkuaXNBcnJheShncmFkLmNvbG9yKSA/IGdyYWQuY29sb3JbaWRdIDogZ3JhZC5jb2xvcjtcbiAgICB9XG5cbiAgICB2YXIgeHAgPSB4YS5jMnAoZGkueCwgdHJ1ZSk7XG4gICAgdmFyIHlwID0geWEuYzJwKGRpLnksIHRydWUpO1xuICAgIHZhciByYWQgPSBkaS5tcmMgfHwgMTtcblxuICAgIHZhciBob3ZlcmxhYmVsID0gdHJhY2UuaG92ZXJsYWJlbDtcblxuICAgIGlmKGhvdmVybGFiZWwpIHtcbiAgICAgICAgZGkuaGJnID0gQXJyYXkuaXNBcnJheShob3ZlcmxhYmVsLmJnY29sb3IpID8gaG92ZXJsYWJlbC5iZ2NvbG9yW2lkXSA6IGhvdmVybGFiZWwuYmdjb2xvcjtcbiAgICAgICAgZGkuaGJjID0gQXJyYXkuaXNBcnJheShob3ZlcmxhYmVsLmJvcmRlcmNvbG9yKSA/IGhvdmVybGFiZWwuYm9yZGVyY29sb3JbaWRdIDogaG92ZXJsYWJlbC5ib3JkZXJjb2xvcjtcbiAgICAgICAgZGkuaHRzID0gQXJyYXkuaXNBcnJheShob3ZlcmxhYmVsLmZvbnQuc2l6ZSkgPyBob3ZlcmxhYmVsLmZvbnQuc2l6ZVtpZF0gOiBob3ZlcmxhYmVsLmZvbnQuc2l6ZTtcbiAgICAgICAgZGkuaHRjID0gQXJyYXkuaXNBcnJheShob3ZlcmxhYmVsLmZvbnQuY29sb3IpID8gaG92ZXJsYWJlbC5mb250LmNvbG9yW2lkXSA6IGhvdmVybGFiZWwuZm9udC5jb2xvcjtcbiAgICAgICAgZGkuaHRmID0gQXJyYXkuaXNBcnJheShob3ZlcmxhYmVsLmZvbnQuZmFtaWx5KSA/IGhvdmVybGFiZWwuZm9udC5mYW1pbHlbaWRdIDogaG92ZXJsYWJlbC5mb250LmZhbWlseTtcbiAgICAgICAgZGkuaG5sID0gQXJyYXkuaXNBcnJheShob3ZlcmxhYmVsLm5hbWVsZW5ndGgpID8gaG92ZXJsYWJlbC5uYW1lbGVuZ3RoW2lkXSA6IGhvdmVybGFiZWwubmFtZWxlbmd0aDtcbiAgICB9XG4gICAgdmFyIGhvdmVyaW5mbyA9IHRyYWNlLmhvdmVyaW5mbztcbiAgICBpZihob3ZlcmluZm8pIHtcbiAgICAgICAgZGkuaGkgPSBBcnJheS5pc0FycmF5KGhvdmVyaW5mbykgPyBob3ZlcmluZm9baWRdIDogaG92ZXJpbmZvO1xuICAgIH1cblxuICAgIHZhciBob3ZlcnRlbXBsYXRlID0gdHJhY2UuaG92ZXJ0ZW1wbGF0ZTtcbiAgICBpZihob3ZlcnRlbXBsYXRlKSB7XG4gICAgICAgIGRpLmh0ID0gQXJyYXkuaXNBcnJheShob3ZlcnRlbXBsYXRlKSA/IGhvdmVydGVtcGxhdGVbaWRdIDogaG92ZXJ0ZW1wbGF0ZTtcbiAgICB9XG5cbiAgICB2YXIgZmFrZUNkID0ge307XG4gICAgZmFrZUNkW3BvaW50RGF0YS5pbmRleF0gPSBkaTtcblxuICAgIExpYi5leHRlbmRGbGF0KHBvaW50RGF0YSwge1xuICAgICAgICBjb2xvcjogZ2V0VHJhY2VDb2xvcih0cmFjZSwgZGkpLFxuXG4gICAgICAgIHgwOiB4cCAtIHJhZCxcbiAgICAgICAgeDE6IHhwICsgcmFkLFxuICAgICAgICB4TGFiZWxWYWw6IGRpLngsXG5cbiAgICAgICAgeTA6IHlwIC0gcmFkLFxuICAgICAgICB5MTogeXAgKyByYWQsXG4gICAgICAgIHlMYWJlbFZhbDogZGkueSxcblxuICAgICAgICBjZDogZmFrZUNkLFxuICAgICAgICBkaXN0YW5jZTogbWluRGlzdCxcbiAgICAgICAgc3Bpa2VEaXN0YW5jZTogZHh5LFxuXG4gICAgICAgIGhvdmVydGVtcGxhdGU6IGRpLmh0XG4gICAgfSk7XG5cbiAgICBpZihkaS5odHgpIHBvaW50RGF0YS50ZXh0ID0gZGkuaHR4O1xuICAgIGVsc2UgaWYoZGkudHgpIHBvaW50RGF0YS50ZXh0ID0gZGkudHg7XG4gICAgZWxzZSBpZih0cmFjZS50ZXh0KSBwb2ludERhdGEudGV4dCA9IHRyYWNlLnRleHQ7XG5cbiAgICBMaWIuZmlsbFRleHQoZGksIHRyYWNlLCBwb2ludERhdGEpO1xuICAgIFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnZXJyb3JiYXJzJywgJ2hvdmVySW5mbycpKGRpLCB0cmFjZSwgcG9pbnREYXRhKTtcblxuICAgIHJldHVybiBwb2ludERhdGE7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhvdmVyUG9pbnRzOiBob3ZlclBvaW50cyxcbiAgICBjYWxjSG92ZXI6IGNhbGNIb3ZlclxufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcIi4uL3NjYXR0ZXIvZ2V0X3RyYWNlX2NvbG9yXCI6MTEyMX1dLDExNjc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaG92ZXIgPSBfZGVyZXFfKCcuL2hvdmVyJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3NjYXR0ZXJnbCcsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnZ2wnLCAncmVnbCcsICdjYXJ0ZXNpYW4nLCAnc3ltYm9scycsICdlcnJvckJhcnNPSycsICdzaG93TGVnZW5kJywgJ3NjYXR0ZXItbGlrZSddLFxuXG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjcm9zc1RyYWNlRGVmYXVsdHM6IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY3Jvc3NfdHJhY2VfZGVmYXVsdHMnKSxcbiAgICBjb2xvcmJhcjogX2RlcmVxXygnLi4vc2NhdHRlci9tYXJrZXJfY29sb3JiYXInKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKSxcbiAgICBob3ZlclBvaW50czogaG92ZXIuaG92ZXJQb2ludHMsXG4gICAgc2VsZWN0UG9pbnRzOiBfZGVyZXFfKCcuL3NlbGVjdCcpLFxuXG4gICAgbWV0YToge1xuICAgICAgICBcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW5cIjo3NzgsXCIuLi9zY2F0dGVyL2Nyb3NzX3RyYWNlX2RlZmF1bHRzXCI6MTExOCxcIi4uL3NjYXR0ZXIvbWFya2VyX2NvbG9yYmFyXCI6MTEyOSxcIi4vYXR0cmlidXRlc1wiOjExNjAsXCIuL2NhbGNcIjoxMTYxLFwiLi9kZWZhdWx0c1wiOjExNjQsXCIuL2hvdmVyXCI6MTE2NixcIi4vcGxvdFwiOjExNjgsXCIuL3NlbGVjdFwiOjExNzB9XSwxMTY4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNyZWF0ZVNjYXR0ZXIgPSBfZGVyZXFfKCdyZWdsLXNjYXR0ZXIyZCcpO1xudmFyIGNyZWF0ZUxpbmUgPSBfZGVyZXFfKCdyZWdsLWxpbmUyZCcpO1xudmFyIGNyZWF0ZUVycm9yID0gX2RlcmVxXygncmVnbC1lcnJvcjJkJyk7XG52YXIgVGV4dCA9IF9kZXJlcV8oJ2dsLXRleHQnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHByZXBhcmVSZWdsID0gX2RlcmVxXygnLi4vLi4vbGliL3ByZXBhcmVfcmVnbCcpO1xuXG52YXIgc3ViVHlwZXMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgbGlua1RyYWNlcyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbGlua190cmFjZXMnKTtcblxudmFyIHN0eWxlVGV4dFNlbGVjdGlvbiA9IF9kZXJlcV8oJy4vZWRpdF9zdHlsZScpLnN0eWxlVGV4dFNlbGVjdGlvbjtcblxuZnVuY3Rpb24gZ2V0Vmlld3BvcnQoZnVsbExheW91dCwgeGF4aXMsIHlheGlzKSB7XG4gICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICB2YXIgd2lkdGggPSBmdWxsTGF5b3V0LndpZHRoO1xuICAgIHZhciBoZWlnaHQgPSBmdWxsTGF5b3V0LmhlaWdodDtcbiAgICByZXR1cm4gW1xuICAgICAgICBncy5sICsgeGF4aXMuZG9tYWluWzBdICogZ3MudyxcbiAgICAgICAgZ3MuYiArIHlheGlzLmRvbWFpblswXSAqIGdzLmgsXG4gICAgICAgICh3aWR0aCAtIGdzLnIpIC0gKDEgLSB4YXhpcy5kb21haW5bMV0pICogZ3MudyxcbiAgICAgICAgKGhlaWdodCAtIGdzLnQpIC0gKDEgLSB5YXhpcy5kb21haW5bMV0pICogZ3MuaFxuICAgIF07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgc3VicGxvdCwgY2RhdGEpIHtcbiAgICBpZighY2RhdGEubGVuZ3RoKSByZXR1cm47XG5cbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzY2VuZSA9IHN1YnBsb3QuX3NjZW5lO1xuICAgIHZhciB4YXhpcyA9IHN1YnBsb3QueGF4aXM7XG4gICAgdmFyIHlheGlzID0gc3VicGxvdC55YXhpcztcbiAgICB2YXIgaSwgajtcblxuICAgIC8vIHdlIG1heSBoYXZlIG1vcmUgc3VicGxvdHMgdGhhbiBpbml0aWFsaXplZCBkYXRhIGR1ZSB0byBBeGVzLmdldFN1YnBsb3RzIG1ldGhvZFxuICAgIGlmKCFzY2VuZSkgcmV0dXJuO1xuXG4gICAgdmFyIHN1Y2Nlc3MgPSBwcmVwYXJlUmVnbChnZCwgWydBTkdMRV9pbnN0YW5jZWRfYXJyYXlzJywgJ09FU19lbGVtZW50X2luZGV4X3VpbnQnXSk7XG4gICAgaWYoIXN1Y2Nlc3MpIHtcbiAgICAgICAgc2NlbmUuaW5pdCgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGNvdW50ID0gc2NlbmUuY291bnQ7XG4gICAgdmFyIHJlZ2wgPSBmdWxsTGF5b3V0Ll9nbGNhbnZhcy5kYXRhKClbMF0ucmVnbDtcblxuICAgIC8vIHRoYXQgaXMgbmVlZGVkIGZvciBmaWxsc1xuICAgIGxpbmtUcmFjZXMoZ2QsIHN1YnBsb3QsIGNkYXRhKTtcblxuICAgIGlmKHNjZW5lLmRpcnR5KSB7XG4gICAgICAgIC8vIG1ha2Ugc3VyZSBzY2VuZXMgYXJlIGNyZWF0ZWRcbiAgICAgICAgaWYoc2NlbmUuZXJyb3IyZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgc2NlbmUuZXJyb3IyZCA9IGNyZWF0ZUVycm9yKHJlZ2wpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHNjZW5lLmxpbmUyZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgc2NlbmUubGluZTJkID0gY3JlYXRlTGluZShyZWdsKTtcbiAgICAgICAgfVxuICAgICAgICBpZihzY2VuZS5zY2F0dGVyMmQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHNjZW5lLnNjYXR0ZXIyZCA9IGNyZWF0ZVNjYXR0ZXIocmVnbCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoc2NlbmUuZmlsbDJkID09PSB0cnVlKSB7XG4gICAgICAgICAgICBzY2VuZS5maWxsMmQgPSBjcmVhdGVMaW5lKHJlZ2wpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHNjZW5lLmdsVGV4dCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgc2NlbmUuZ2xUZXh0ID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICAgICAgICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBzY2VuZS5nbFRleHRbaV0gPSBuZXcgVGV4dChyZWdsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVwZGF0ZSBtYWluIG1hcmtlciBvcHRpb25zXG4gICAgICAgIGlmKHNjZW5lLmdsVGV4dCkge1xuICAgICAgICAgICAgaWYoY291bnQgPiBzY2VuZS5nbFRleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgLy8gYWRkIGdsIHRleHQgbWFya2VyXG4gICAgICAgICAgICAgICAgdmFyIHRleHRzVG9BZGQgPSBjb3VudCAtIHNjZW5lLmdsVGV4dC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgdGV4dHNUb0FkZDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjZW5lLmdsVGV4dC5wdXNoKG5ldyBUZXh0KHJlZ2wpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYoY291bnQgPCBzY2VuZS5nbFRleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGdsIHRleHQgbWFya2VyXG4gICAgICAgICAgICAgICAgdmFyIHRleHRzVG9SZW1vdmUgPSBzY2VuZS5nbFRleHQubGVuZ3RoIC0gY291bnQ7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZWRUZXh0cyA9IHNjZW5lLmdsVGV4dC5zcGxpY2UoY291bnQsIHRleHRzVG9SZW1vdmUpO1xuICAgICAgICAgICAgICAgIHJlbW92ZWRUZXh0cy5mb3JFYWNoKGZ1bmN0aW9uKHRleHQpIHsgdGV4dC5kZXN0cm95KCk7IH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgc2NlbmUuZ2xUZXh0W2ldLnVwZGF0ZShzY2VuZS50ZXh0T3B0aW9uc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYoc2NlbmUubGluZTJkKSB7XG4gICAgICAgICAgICBzY2VuZS5saW5lMmQudXBkYXRlKHNjZW5lLmxpbmVPcHRpb25zKTtcbiAgICAgICAgICAgIHNjZW5lLmxpbmVPcHRpb25zID0gc2NlbmUubGluZU9wdGlvbnMubWFwKGZ1bmN0aW9uKGxpbmVPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYobGluZU9wdGlvbnMgJiYgbGluZU9wdGlvbnMucG9zaXRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzcmNQb3MgPSBsaW5lT3B0aW9ucy5wb3NpdGlvbnM7XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGZpcnN0cHRkZWYgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZShmaXJzdHB0ZGVmIDwgc3JjUG9zLmxlbmd0aCAmJiAoaXNOYU4oc3JjUG9zW2ZpcnN0cHRkZWZdKSB8fCBpc05hTihzcmNQb3NbZmlyc3RwdGRlZiArIDFdKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0cHRkZWYgKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgbGFzdHB0ZGVmID0gc3JjUG9zLmxlbmd0aCAtIDI7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlKGxhc3RwdGRlZiA+IGZpcnN0cHRkZWYgJiYgKGlzTmFOKHNyY1Bvc1tsYXN0cHRkZWZdKSB8fCBpc05hTihzcmNQb3NbbGFzdHB0ZGVmICsgMV0pKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdHB0ZGVmIC09IDI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbGluZU9wdGlvbnMucG9zaXRpb25zID0gc3JjUG9zLnNsaWNlKGZpcnN0cHRkZWYsIGxhc3RwdGRlZiArIDIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbGluZU9wdGlvbnM7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNjZW5lLmxpbmUyZC51cGRhdGUoc2NlbmUubGluZU9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHNjZW5lLmVycm9yMmQpIHtcbiAgICAgICAgICAgIHZhciBlcnJvckJhdGNoID0gKHNjZW5lLmVycm9yWE9wdGlvbnMgfHwgW10pLmNvbmNhdChzY2VuZS5lcnJvcllPcHRpb25zIHx8IFtdKTtcbiAgICAgICAgICAgIHNjZW5lLmVycm9yMmQudXBkYXRlKGVycm9yQmF0Y2gpO1xuICAgICAgICB9XG4gICAgICAgIGlmKHNjZW5lLnNjYXR0ZXIyZCkge1xuICAgICAgICAgICAgc2NlbmUuc2NhdHRlcjJkLnVwZGF0ZShzY2VuZS5tYXJrZXJPcHRpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGZpbGwgcmVxdWlyZXMgbGlua2VkIHRyYWNlcywgc28gd2UgZ2VuZXJhdGUgaXQncyBwb3NpdGlvbnMgaGVyZVxuICAgICAgICBzY2VuZS5maWxsT3JkZXIgPSBMaWIucmVwZWF0KG51bGwsIGNvdW50KTtcbiAgICAgICAgaWYoc2NlbmUuZmlsbDJkKSB7XG4gICAgICAgICAgICBzY2VuZS5maWxsT3B0aW9ucyA9IHNjZW5lLmZpbGxPcHRpb25zLm1hcChmdW5jdGlvbihmaWxsT3B0aW9ucywgaSkge1xuICAgICAgICAgICAgICAgIHZhciBjZHNjYXR0ZXIgPSBjZGF0YVtpXTtcbiAgICAgICAgICAgICAgICBpZighZmlsbE9wdGlvbnMgfHwgIWNkc2NhdHRlciB8fCAhY2RzY2F0dGVyWzBdIHx8ICFjZHNjYXR0ZXJbMF0udHJhY2UpIHJldHVybjtcbiAgICAgICAgICAgICAgICB2YXIgY2QgPSBjZHNjYXR0ZXJbMF07XG4gICAgICAgICAgICAgICAgdmFyIHRyYWNlID0gY2QudHJhY2U7XG4gICAgICAgICAgICAgICAgdmFyIHN0YXNoID0gY2QudDtcbiAgICAgICAgICAgICAgICB2YXIgbGluZU9wdGlvbnMgPSBzY2VuZS5saW5lT3B0aW9uc1tpXTtcbiAgICAgICAgICAgICAgICB2YXIgbGFzdCwgajtcblxuICAgICAgICAgICAgICAgIHZhciBmaWxsRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlLl9vd25maWxsKSBmaWxsRGF0YS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIGlmKHRyYWNlLl9uZXh0dHJhY2UpIGZpbGxEYXRhLnB1c2goaSArIDEpO1xuICAgICAgICAgICAgICAgIGlmKGZpbGxEYXRhLmxlbmd0aCkgc2NlbmUuZmlsbE9yZGVyW2ldID0gZmlsbERhdGE7XG5cbiAgICAgICAgICAgICAgICB2YXIgcG9zID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNyY1BvcyA9IChsaW5lT3B0aW9ucyAmJiBsaW5lT3B0aW9ucy5wb3NpdGlvbnMpIHx8IHN0YXNoLnBvc2l0aW9ucztcbiAgICAgICAgICAgICAgICB2YXIgZmlyc3RwdGRlZiwgbGFzdHB0ZGVmO1xuXG4gICAgICAgICAgICAgICAgaWYodHJhY2UuZmlsbCA9PT0gJ3RvemVyb3knKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpcnN0cHRkZWYgPSAwO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZShmaXJzdHB0ZGVmIDwgc3JjUG9zLmxlbmd0aCAmJiBpc05hTihzcmNQb3NbZmlyc3RwdGRlZiArIDFdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3RwdGRlZiArPSAyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxhc3RwdGRlZiA9IHNyY1Bvcy5sZW5ndGggLSAyO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZShsYXN0cHRkZWYgPiBmaXJzdHB0ZGVmICYmIGlzTmFOKHNyY1Bvc1tsYXN0cHRkZWYgKyAxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RwdGRlZiAtPSAyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmKHNyY1Bvc1tmaXJzdHB0ZGVmICsgMV0gIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvcyA9IFtzcmNQb3NbZmlyc3RwdGRlZl0sIDBdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHBvcyA9IHBvcy5jb25jYXQoc3JjUG9zLnNsaWNlKGZpcnN0cHRkZWYsIGxhc3RwdGRlZiArIDIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc3JjUG9zW2xhc3RwdGRlZiArIDFdICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3MgPSBwb3MuY29uY2F0KFtzcmNQb3NbbGFzdHB0ZGVmXSwgMF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHRyYWNlLmZpbGwgPT09ICd0b3plcm94Jykge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdHB0ZGVmID0gMDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUoZmlyc3RwdGRlZiA8IHNyY1Bvcy5sZW5ndGggJiYgaXNOYU4oc3JjUG9zW2ZpcnN0cHRkZWZdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3RwdGRlZiArPSAyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxhc3RwdGRlZiA9IHNyY1Bvcy5sZW5ndGggLSAyO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZShsYXN0cHRkZWYgPiBmaXJzdHB0ZGVmICYmIGlzTmFOKHNyY1Bvc1tsYXN0cHRkZWZdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdHB0ZGVmIC09IDI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYoc3JjUG9zW2ZpcnN0cHRkZWZdICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3MgPSBbMCwgc3JjUG9zW2ZpcnN0cHRkZWYgKyAxXV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcG9zID0gcG9zLmNvbmNhdChzcmNQb3Muc2xpY2UoZmlyc3RwdGRlZiwgbGFzdHB0ZGVmICsgMikpO1xuICAgICAgICAgICAgICAgICAgICBpZihzcmNQb3NbbGFzdHB0ZGVmXSAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zID0gcG9zLmNvbmNhdChbIDAsIHNyY1Bvc1tsYXN0cHRkZWYgKyAxXV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmKHRyYWNlLmZpbGwgPT09ICd0b3NlbGYnIHx8IHRyYWNlLmZpbGwgPT09ICd0b25leHQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBsYXN0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgc3JjUG9zLmxlbmd0aDsgaiArPSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihpc05hTihzcmNQb3Nbal0pIHx8IGlzTmFOKHNyY1Bvc1tqICsgMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zID0gcG9zLmNvbmNhdChzcmNQb3Muc2xpY2UobGFzdCwgaikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5wdXNoKHNyY1Bvc1tsYXN0XSwgc3JjUG9zW2xhc3QgKyAxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdCA9IGogKyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHBvcyA9IHBvcy5jb25jYXQoc3JjUG9zLnNsaWNlKGxhc3QpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYobGFzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zLnB1c2goc3JjUG9zW2xhc3RdLCBzcmNQb3NbbGFzdCArIDFdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXh0VHJhY2UgPSB0cmFjZS5fbmV4dHRyYWNlO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKG5leHRUcmFjZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRPcHRpb25zID0gc2NlbmUubGluZU9wdGlvbnNbaSArIDFdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihuZXh0T3B0aW9ucykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0UG9zID0gbmV4dE9wdGlvbnMucG9zaXRpb25zO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRyYWNlLmZpbGwgPT09ICd0b25leHR5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3MgPSBzcmNQb3Muc2xpY2UoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IoaSA9IE1hdGguZmxvb3IobmV4dFBvcy5sZW5ndGggLyAyKTsgaS0tOykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHh4ID0gbmV4dFBvc1tpICogMl07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgeXkgPSBuZXh0UG9zW2kgKiAyICsgMV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihpc05hTih4eCkgfHwgaXNOYU4oeXkpKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcy5wdXNoKHh4LCB5eSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbE9wdGlvbnMuZmlsbCA9IG5leHRUcmFjZS5maWxsY29sb3I7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZGV0ZWN0IHByZXYgdHJhY2UgcG9zaXRpb25zIHRvIGV4Y2x1ZGUgZnJvbSBjdXJyZW50IGZpbGxcbiAgICAgICAgICAgICAgICBpZih0cmFjZS5fcHJldnRyYWNlICYmIHRyYWNlLl9wcmV2dHJhY2UuZmlsbCA9PT0gJ3RvbmV4dCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZMaW5lUG9zID0gc2NlbmUubGluZU9wdGlvbnNbaSAtIDFdLnBvc2l0aW9ucztcblxuICAgICAgICAgICAgICAgICAgICAvLyBGSVhNRTogbGlrZWx5IHRoaXMgbG9naWMgc2hvdWxkIGJlIHRlc3RlZCBiZXR0ZXJcbiAgICAgICAgICAgICAgICAgICAgdmFyIG9mZnNldCA9IHBvcy5sZW5ndGggLyAyO1xuICAgICAgICAgICAgICAgICAgICBsYXN0ID0gb2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICB2YXIgaG9sZSA9IFtsYXN0XTtcbiAgICAgICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgcHJldkxpbmVQb3MubGVuZ3RoOyBqICs9IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlzTmFOKHByZXZMaW5lUG9zW2pdKSB8fCBpc05hTihwcmV2TGluZVBvc1tqICsgMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9sZS5wdXNoKGogLyAyICsgb2Zmc2V0ICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdCA9IGogKyAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcG9zID0gcG9zLmNvbmNhdChwcmV2TGluZVBvcyk7XG4gICAgICAgICAgICAgICAgICAgIGZpbGxPcHRpb25zLmhvbGUgPSBob2xlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmaWxsT3B0aW9ucy5maWxsbW9kZSA9IHRyYWNlLmZpbGw7XG4gICAgICAgICAgICAgICAgZmlsbE9wdGlvbnMub3BhY2l0eSA9IHRyYWNlLm9wYWNpdHk7XG4gICAgICAgICAgICAgICAgZmlsbE9wdGlvbnMucG9zaXRpb25zID0gcG9zO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZpbGxPcHRpb25zO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHNjZW5lLmZpbGwyZC51cGRhdGUoc2NlbmUuZmlsbE9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZm9ybSBiYXRjaCBhcnJheXMsIGFuZCBjaGVjayBmb3Igc2VsZWN0ZWQgcG9pbnRzXG4gICAgdmFyIGRyYWdtb2RlID0gZnVsbExheW91dC5kcmFnbW9kZTtcbiAgICB2YXIgc2VsZWN0TW9kZSA9IGRyYWdtb2RlID09PSAnbGFzc28nIHx8IGRyYWdtb2RlID09PSAnc2VsZWN0JztcbiAgICB2YXIgY2xpY2tTZWxlY3RFbmFibGVkID0gZnVsbExheW91dC5jbGlja21vZGUuaW5kZXhPZignc2VsZWN0JykgPiAtMTtcblxuICAgIGZvcihpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgdmFyIGNkMCA9IGNkYXRhW2ldWzBdO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgICAgIHZhciBzdGFzaCA9IGNkMC50O1xuICAgICAgICB2YXIgaW5kZXggPSBzdGFzaC5pbmRleDtcbiAgICAgICAgdmFyIGxlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgICAgIHZhciB4ID0gc3Rhc2gueDtcbiAgICAgICAgdmFyIHkgPSBzdGFzaC55O1xuXG4gICAgICAgIGlmKHRyYWNlLnNlbGVjdGVkcG9pbnRzIHx8IHNlbGVjdE1vZGUgfHwgY2xpY2tTZWxlY3RFbmFibGVkKSB7XG4gICAgICAgICAgICBpZighc2VsZWN0TW9kZSkgc2VsZWN0TW9kZSA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIHJlZ2VuZXJhdGUgc2NlbmUgYmF0Y2gsIGlmIHRyYWNlcyBudW1iZXIgY2hhbmdlZCBkdXJpbmcgc2VsZWN0aW9uXG4gICAgICAgICAgICBpZih0cmFjZS5zZWxlY3RlZHBvaW50cykge1xuICAgICAgICAgICAgICAgIHZhciBzZWxQdHMgPSBzY2VuZS5zZWxlY3RCYXRjaFtpbmRleF0gPSBMaWIuc2VsSW5kaWNlczJzZWxQb2ludHModHJhY2UpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHNlbERpY3QgPSB7fTtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBzZWxQdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsRGljdFtzZWxQdHNbal1dID0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHVuc2VsUHRzID0gW107XG4gICAgICAgICAgICAgICAgZm9yKGogPSAwOyBqIDwgbGVuOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoIXNlbERpY3Rbal0pIHVuc2VsUHRzLnB1c2goaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2hbaW5kZXhdID0gdW5zZWxQdHM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHByZWNhbGN1bGF0ZSBweCBjb29yZHMgc2luY2Ugd2UgYXJlIG5vdCBnb2luZyB0byBwYW4gZHVyaW5nIHNlbGVjdFxuICAgICAgICAgICAgLy8gVE9ETywgY291bGQgZG8gYmV0dGVyIGhlcmUgZS5nLlxuICAgICAgICAgICAgLy8gLSBzcGluIHRoYXQgaW4gYSB3ZWJ3b3JrZXJcbiAgICAgICAgICAgIC8vIC0gY29tcHV0ZSBzZWxlY3Rpb24gZnJvbSBwb2x5Z29ucyBpbiBkYXRhIGNvb3JkaW5hdGVzXG4gICAgICAgICAgICAvLyAgIChtYXliZSBqdXN0IGZvciBsaW5lYXIgYXhlcylcbiAgICAgICAgICAgIHZhciB4cHggPSBzdGFzaC54cHggPSBuZXcgQXJyYXkobGVuKTtcbiAgICAgICAgICAgIHZhciB5cHggPSBzdGFzaC55cHggPSBuZXcgQXJyYXkobGVuKTtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IGxlbjsgaisrKSB7XG4gICAgICAgICAgICAgICAgeHB4W2pdID0geGF4aXMuYzJwKHhbal0pO1xuICAgICAgICAgICAgICAgIHlweFtqXSA9IHlheGlzLmMycCh5W2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXNoLnhweCA9IHN0YXNoLnlweCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihzZWxlY3RNb2RlKSB7XG4gICAgICAgIC8vIGNyZWF0ZSBzY2F0dGVyIGluc3RhbmNlIGJ5IGNsb25pbmcgc2NhdHRlcjJkXG4gICAgICAgIGlmKCFzY2VuZS5zZWxlY3QyZCkge1xuICAgICAgICAgICAgc2NlbmUuc2VsZWN0MmQgPSBjcmVhdGVTY2F0dGVyKGZ1bGxMYXlvdXQuX2dsY2FudmFzLmRhdGEoKVsxXS5yZWdsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVzZSB1bnNlbGVjdGVkIHN0eWxlcyBvbiAnY29udGV4dCcgY2FudmFzXG4gICAgICAgIGlmKHNjZW5lLnNjYXR0ZXIyZCkge1xuICAgICAgICAgICAgdmFyIHVuc2VsT3B0cyA9IG5ldyBBcnJheShjb3VudCk7XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdW5zZWxPcHRzW2ldID0gc2NlbmUuc2VsZWN0QmF0Y2hbaV0ubGVuZ3RoIHx8IHNjZW5lLnVuc2VsZWN0QmF0Y2hbaV0ubGVuZ3RoID9cbiAgICAgICAgICAgICAgICAgICAgc2NlbmUubWFya2VyVW5zZWxlY3RlZE9wdGlvbnNbaV0gOlxuICAgICAgICAgICAgICAgICAgICB7fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNjZW5lLnNjYXR0ZXIyZC51cGRhdGUodW5zZWxPcHRzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHVzZSBzZWxlY3RlZCBzdHlsZSBvbiAnZm9jdXMnIGNhbnZhc1xuICAgICAgICBpZihzY2VuZS5zZWxlY3QyZCkge1xuICAgICAgICAgICAgc2NlbmUuc2VsZWN0MmQudXBkYXRlKHNjZW5lLm1hcmtlck9wdGlvbnMpO1xuICAgICAgICAgICAgc2NlbmUuc2VsZWN0MmQudXBkYXRlKHNjZW5lLm1hcmtlclNlbGVjdGVkT3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihzY2VuZS5nbFRleHQpIHtcbiAgICAgICAgICAgIGNkYXRhLmZvckVhY2goZnVuY3Rpb24oY2RzY2F0dGVyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRyYWNlID0gKChjZHNjYXR0ZXIgfHwgW10pWzBdIHx8IHt9KS50cmFjZSB8fCB7fTtcbiAgICAgICAgICAgICAgICBpZihzdWJUeXBlcy5oYXNUZXh0KHRyYWNlKSkge1xuICAgICAgICAgICAgICAgICAgICBzdHlsZVRleHRTZWxlY3Rpb24oY2RzY2F0dGVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHJlc2V0ICdjb250ZXh0JyBzY2F0dGVyMmQgb3B0cyB0byBiYXNlIG9wdHMsXG4gICAgICAgIC8vIHRodXMgdW5zZXR0aW5nIG1hcmtlclVuc2VsZWN0ZWRPcHRpb25zIGZyb20gc2VsZWN0aW9uXG4gICAgICAgIGlmKHNjZW5lLnNjYXR0ZXIyZCkge1xuICAgICAgICAgICAgc2NlbmUuc2NhdHRlcjJkLnVwZGF0ZShzY2VuZS5tYXJrZXJPcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHByb3ZpZGUgdmlld3BvcnQgYW5kIHJhbmdlXG4gICAgdmFyIHZwUmFuZ2UwID0ge1xuICAgICAgICB2aWV3cG9ydDogZ2V0Vmlld3BvcnQoZnVsbExheW91dCwgeGF4aXMsIHlheGlzKSxcbiAgICAgICAgLy8gVE9ETyBkbyB3ZSBuZWVkIHRob3NlIGZhbGxiYWNrcz9cbiAgICAgICAgcmFuZ2U6IFtcbiAgICAgICAgICAgICh4YXhpcy5fcmwgfHwgeGF4aXMucmFuZ2UpWzBdLFxuICAgICAgICAgICAgKHlheGlzLl9ybCB8fCB5YXhpcy5yYW5nZSlbMF0sXG4gICAgICAgICAgICAoeGF4aXMuX3JsIHx8IHhheGlzLnJhbmdlKVsxXSxcbiAgICAgICAgICAgICh5YXhpcy5fcmwgfHwgeWF4aXMucmFuZ2UpWzFdXG4gICAgICAgIF1cbiAgICB9O1xuICAgIHZhciB2cFJhbmdlID0gTGliLnJlcGVhdCh2cFJhbmdlMCwgc2NlbmUuY291bnQpO1xuXG4gICAgLy8gdXBsb2FkIHZpZXdwb3J0L3JhbmdlIGRhdGEgdG8gR1BVXG4gICAgaWYoc2NlbmUuZmlsbDJkKSB7XG4gICAgICAgIHNjZW5lLmZpbGwyZC51cGRhdGUodnBSYW5nZSk7XG4gICAgfVxuICAgIGlmKHNjZW5lLmxpbmUyZCkge1xuICAgICAgICBzY2VuZS5saW5lMmQudXBkYXRlKHZwUmFuZ2UpO1xuICAgIH1cbiAgICBpZihzY2VuZS5lcnJvcjJkKSB7XG4gICAgICAgIHNjZW5lLmVycm9yMmQudXBkYXRlKHZwUmFuZ2UuY29uY2F0KHZwUmFuZ2UpKTtcbiAgICB9XG4gICAgaWYoc2NlbmUuc2NhdHRlcjJkKSB7XG4gICAgICAgIHNjZW5lLnNjYXR0ZXIyZC51cGRhdGUodnBSYW5nZSk7XG4gICAgfVxuICAgIGlmKHNjZW5lLnNlbGVjdDJkKSB7XG4gICAgICAgIHNjZW5lLnNlbGVjdDJkLnVwZGF0ZSh2cFJhbmdlKTtcbiAgICB9XG4gICAgaWYoc2NlbmUuZ2xUZXh0KSB7XG4gICAgICAgIHNjZW5lLmdsVGV4dC5mb3JFYWNoKGZ1bmN0aW9uKHRleHQpIHsgdGV4dC51cGRhdGUodnBSYW5nZTApOyB9KTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9wcmVwYXJlX3JlZ2xcIjo3MzIsXCIuLi9zY2F0dGVyL2xpbmtfdHJhY2VzXCI6MTEyNyxcIi4uL3NjYXR0ZXIvc3VidHlwZXNcIjoxMTM1LFwiLi9lZGl0X3N0eWxlXCI6MTE2NSxcImdsLXRleHRcIjozMTcsXCJyZWdsLWVycm9yMmRcIjo0OTAsXCJyZWdsLWxpbmUyZFwiOjQ5MSxcInJlZ2wtc2NhdHRlcjJkXCI6NDk3fV0sMTE2OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxuLy8gbWFrZSBzdXJlIHNjZW5lIGV4aXN0cyBvbiBzdWJwbG90LCByZXR1cm4gaXRcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2NlbmVVcGRhdGUoZ2QsIHN1YnBsb3QpIHtcbiAgICB2YXIgc2NlbmUgPSBzdWJwbG90Ll9zY2VuZTtcblxuICAgIHZhciByZXNldE9wdHMgPSB7XG4gICAgICAgIC8vIG51bWJlciBvZiB0cmFjZXMgaW4gc3VicGxvdCwgc2luY2Ugc2NlbmU6c3VicGxvdCAtPiAxOjFcbiAgICAgICAgY291bnQ6IDAsXG4gICAgICAgIC8vIHdoZXRoZXIgc2NlbmUgcmVxdWlyZXMgaW5pdCBob29rIGluIHBsb3QgY2FsbCAoZGlydHkgcGxvdCBjYWxsKVxuICAgICAgICBkaXJ0eTogdHJ1ZSxcbiAgICAgICAgLy8gbGFzdCB1c2VkIG9wdGlvbnNcbiAgICAgICAgbGluZU9wdGlvbnM6IFtdLFxuICAgICAgICBmaWxsT3B0aW9uczogW10sXG4gICAgICAgIG1hcmtlck9wdGlvbnM6IFtdLFxuICAgICAgICBtYXJrZXJTZWxlY3RlZE9wdGlvbnM6IFtdLFxuICAgICAgICBtYXJrZXJVbnNlbGVjdGVkT3B0aW9uczogW10sXG4gICAgICAgIGVycm9yWE9wdGlvbnM6IFtdLFxuICAgICAgICBlcnJvcllPcHRpb25zOiBbXSxcbiAgICAgICAgdGV4dE9wdGlvbnM6IFtdLFxuICAgICAgICB0ZXh0U2VsZWN0ZWRPcHRpb25zOiBbXSxcbiAgICAgICAgdGV4dFVuc2VsZWN0ZWRPcHRpb25zOiBbXSxcbiAgICAgICAgLy8gc2VsZWN0aW9uIGJhdGNoZXNcbiAgICAgICAgc2VsZWN0QmF0Y2g6IFtdLFxuICAgICAgICB1bnNlbGVjdEJhdGNoOiBbXVxuICAgIH07XG5cbiAgICAvLyByZWdsLSBjb21wb25lbnQgc3R1YnMsIGluaXRpYWxpemVkIGluIGRpcnR5IHBsb3QgY2FsbFxuICAgIHZhciBpbml0T3B0cyA9IHtcbiAgICAgICAgZmlsbDJkOiBmYWxzZSxcbiAgICAgICAgc2NhdHRlcjJkOiBmYWxzZSxcbiAgICAgICAgZXJyb3IyZDogZmFsc2UsXG4gICAgICAgIGxpbmUyZDogZmFsc2UsXG4gICAgICAgIGdsVGV4dDogZmFsc2UsXG4gICAgICAgIHNlbGVjdDJkOiBmYWxzZVxuICAgIH07XG5cbiAgICBpZighc3VicGxvdC5fc2NlbmUpIHtcbiAgICAgICAgc2NlbmUgPSBzdWJwbG90Ll9zY2VuZSA9IHt9O1xuXG4gICAgICAgIHNjZW5lLmluaXQgPSBmdW5jdGlvbiBpbml0KCkge1xuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQoc2NlbmUsIGluaXRPcHRzLCByZXNldE9wdHMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNjZW5lLmluaXQoKTtcblxuICAgICAgICAvLyBhcHBseSBuZXcgb3B0aW9uIHRvIGFsbCByZWdsIGNvbXBvbmVudHMgKHVzZWQgb24gZHJhZylcbiAgICAgICAgc2NlbmUudXBkYXRlID0gZnVuY3Rpb24gdXBkYXRlKG9wdCkge1xuICAgICAgICAgICAgdmFyIG9wdHMgPSBMaWIucmVwZWF0KG9wdCwgc2NlbmUuY291bnQpO1xuXG4gICAgICAgICAgICBpZihzY2VuZS5maWxsMmQpIHNjZW5lLmZpbGwyZC51cGRhdGUob3B0cyk7XG4gICAgICAgICAgICBpZihzY2VuZS5zY2F0dGVyMmQpIHNjZW5lLnNjYXR0ZXIyZC51cGRhdGUob3B0cyk7XG4gICAgICAgICAgICBpZihzY2VuZS5saW5lMmQpIHNjZW5lLmxpbmUyZC51cGRhdGUob3B0cyk7XG4gICAgICAgICAgICBpZihzY2VuZS5lcnJvcjJkKSBzY2VuZS5lcnJvcjJkLnVwZGF0ZShvcHRzLmNvbmNhdChvcHRzKSk7XG4gICAgICAgICAgICBpZihzY2VuZS5zZWxlY3QyZCkgc2NlbmUuc2VsZWN0MmQudXBkYXRlKG9wdHMpO1xuICAgICAgICAgICAgaWYoc2NlbmUuZ2xUZXh0KSB7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHNjZW5lLmNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgc2NlbmUuZ2xUZXh0W2ldLnVwZGF0ZShvcHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvLyBkcmF3IHRyYWNlcyBpbiBwcm9wZXIgb3JkZXJcbiAgICAgICAgc2NlbmUuZHJhdyA9IGZ1bmN0aW9uIGRyYXcoKSB7XG4gICAgICAgICAgICB2YXIgY291bnQgPSBzY2VuZS5jb3VudDtcbiAgICAgICAgICAgIHZhciBmaWxsMmQgPSBzY2VuZS5maWxsMmQ7XG4gICAgICAgICAgICB2YXIgZXJyb3IyZCA9IHNjZW5lLmVycm9yMmQ7XG4gICAgICAgICAgICB2YXIgbGluZTJkID0gc2NlbmUubGluZTJkO1xuICAgICAgICAgICAgdmFyIHNjYXR0ZXIyZCA9IHNjZW5lLnNjYXR0ZXIyZDtcbiAgICAgICAgICAgIHZhciBnbFRleHQgPSBzY2VuZS5nbFRleHQ7XG4gICAgICAgICAgICB2YXIgc2VsZWN0MmQgPSBzY2VuZS5zZWxlY3QyZDtcbiAgICAgICAgICAgIHZhciBzZWxlY3RCYXRjaCA9IHNjZW5lLnNlbGVjdEJhdGNoO1xuICAgICAgICAgICAgdmFyIHVuc2VsZWN0QmF0Y2ggPSBzY2VuZS51bnNlbGVjdEJhdGNoO1xuXG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKGZpbGwyZCAmJiBzY2VuZS5maWxsT3JkZXJbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgZmlsbDJkLmRyYXcoc2NlbmUuZmlsbE9yZGVyW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYobGluZTJkICYmIHNjZW5lLmxpbmVPcHRpb25zW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpbmUyZC5kcmF3KGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZihlcnJvcjJkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKHNjZW5lLmVycm9yWE9wdGlvbnNbaV0pIGVycm9yMmQuZHJhdyhpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoc2NlbmUuZXJyb3JZT3B0aW9uc1tpXSkgZXJyb3IyZC5kcmF3KGkgKyBjb3VudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKHNjYXR0ZXIyZCAmJiBzY2VuZS5tYXJrZXJPcHRpb25zW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKHVuc2VsZWN0QmF0Y2hbaV0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXJnID0gTGliLnJlcGVhdChbXSwgc2NlbmUuY291bnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXJnW2ldID0gdW5zZWxlY3RCYXRjaFtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjYXR0ZXIyZC5kcmF3KGFyZyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZighc2VsZWN0QmF0Y2hbaV0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzY2F0dGVyMmQuZHJhdyhpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZihnbFRleHRbaV0gJiYgc2NlbmUudGV4dE9wdGlvbnNbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgZ2xUZXh0W2ldLnJlbmRlcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoc2VsZWN0MmQpIHtcbiAgICAgICAgICAgICAgICBzZWxlY3QyZC5kcmF3KHNlbGVjdEJhdGNoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2NlbmUuZGlydHkgPSBmYWxzZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyByZW1vdmUgc2NlbmUgcmVzb3VyY2VzXG4gICAgICAgIHNjZW5lLmRlc3Ryb3kgPSBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICAgICAgaWYoc2NlbmUuZmlsbDJkICYmIHNjZW5lLmZpbGwyZC5kZXN0cm95KSBzY2VuZS5maWxsMmQuZGVzdHJveSgpO1xuICAgICAgICAgICAgaWYoc2NlbmUuc2NhdHRlcjJkICYmIHNjZW5lLnNjYXR0ZXIyZC5kZXN0cm95KSBzY2VuZS5zY2F0dGVyMmQuZGVzdHJveSgpO1xuICAgICAgICAgICAgaWYoc2NlbmUuZXJyb3IyZCAmJiBzY2VuZS5lcnJvcjJkLmRlc3Ryb3kpIHNjZW5lLmVycm9yMmQuZGVzdHJveSgpO1xuICAgICAgICAgICAgaWYoc2NlbmUubGluZTJkICYmIHNjZW5lLmxpbmUyZC5kZXN0cm95KSBzY2VuZS5saW5lMmQuZGVzdHJveSgpO1xuICAgICAgICAgICAgaWYoc2NlbmUuc2VsZWN0MmQgJiYgc2NlbmUuc2VsZWN0MmQuZGVzdHJveSkgc2NlbmUuc2VsZWN0MmQuZGVzdHJveSgpO1xuICAgICAgICAgICAgaWYoc2NlbmUuZ2xUZXh0KSB7XG4gICAgICAgICAgICAgICAgc2NlbmUuZ2xUZXh0LmZvckVhY2goZnVuY3Rpb24odGV4dCkge1xuICAgICAgICAgICAgICAgICAgICBpZih0ZXh0LmRlc3Ryb3kpIHRleHQuZGVzdHJveSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzY2VuZS5saW5lT3B0aW9ucyA9IG51bGw7XG4gICAgICAgICAgICBzY2VuZS5maWxsT3B0aW9ucyA9IG51bGw7XG4gICAgICAgICAgICBzY2VuZS5tYXJrZXJPcHRpb25zID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLm1hcmtlclNlbGVjdGVkT3B0aW9ucyA9IG51bGw7XG4gICAgICAgICAgICBzY2VuZS5tYXJrZXJVbnNlbGVjdGVkT3B0aW9ucyA9IG51bGw7XG4gICAgICAgICAgICBzY2VuZS5lcnJvclhPcHRpb25zID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLmVycm9yWU9wdGlvbnMgPSBudWxsO1xuICAgICAgICAgICAgc2NlbmUudGV4dE9wdGlvbnMgPSBudWxsO1xuICAgICAgICAgICAgc2NlbmUudGV4dFNlbGVjdGVkT3B0aW9ucyA9IG51bGw7XG4gICAgICAgICAgICBzY2VuZS50ZXh0VW5zZWxlY3RlZE9wdGlvbnMgPSBudWxsO1xuXG4gICAgICAgICAgICBzY2VuZS5zZWxlY3RCYXRjaCA9IG51bGw7XG4gICAgICAgICAgICBzY2VuZS51bnNlbGVjdEJhdGNoID0gbnVsbDtcblxuICAgICAgICAgICAgLy8gd2UgY2FuJ3QganVzdCBkZWxldGUgX3NjZW5lLCBiZWNhdXNlIGBkZXN0cm95YCBpcyBjYWxsZWQgaW4gdGhlXG4gICAgICAgICAgICAvLyBtaWRkbGUgb2Ygc3VwcGx5RGVmYXVsdHMsIGJlZm9yZSByZWxpbmtQcml2YXRlS2V5cyB3aGljaCB3aWxsIHB1dCBpdCBiYWNrLlxuICAgICAgICAgICAgc3VicGxvdC5fc2NlbmUgPSBudWxsO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIGluIGNhc2UgaWYgd2UgaGF2ZSBzY2VuZSBmcm9tIHRoZSBsYXN0IGNhbGMgLSByZXNldCBkYXRhXG4gICAgaWYoIXNjZW5lLmRpcnR5KSB7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KHNjZW5lLCByZXNldE9wdHMpO1xuICAgIH1cblxuICAgIHJldHVybiBzY2VuZTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5fV0sMTE3MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzdWJUeXBlcyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBzdHlsZVRleHRTZWxlY3Rpb24gPSBfZGVyZXFfKCcuL2VkaXRfc3R5bGUnKS5zdHlsZVRleHRTZWxlY3Rpb247XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2VsZWN0KHNlYXJjaEluZm8sIHNlbGVjdGlvblRlc3Rlcikge1xuICAgIHZhciBjZCA9IHNlYXJjaEluZm8uY2Q7XG4gICAgdmFyIHNlbGVjdGlvbiA9IFtdO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciBzdGFzaCA9IGNkWzBdLnQ7XG4gICAgdmFyIGxlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIHggPSBzdGFzaC54O1xuICAgIHZhciB5ID0gc3Rhc2gueTtcbiAgICB2YXIgc2NlbmUgPSBzdGFzaC5fc2NlbmU7XG4gICAgdmFyIGluZGV4ID0gc3Rhc2guaW5kZXg7XG5cbiAgICBpZighc2NlbmUpIHJldHVybiBzZWxlY3Rpb247XG5cbiAgICB2YXIgaGFzVGV4dCA9IHN1YlR5cGVzLmhhc1RleHQodHJhY2UpO1xuICAgIHZhciBoYXNNYXJrZXJzID0gc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSk7XG4gICAgdmFyIGhhc09ubHlMaW5lcyA9ICFoYXNNYXJrZXJzICYmICFoYXNUZXh0O1xuXG4gICAgaWYodHJhY2UudmlzaWJsZSAhPT0gdHJ1ZSB8fCBoYXNPbmx5TGluZXMpIHJldHVybiBzZWxlY3Rpb247XG5cbiAgICB2YXIgZWxzID0gW107XG4gICAgdmFyIHVuZWxzID0gW107XG5cbiAgICAvLyBkZWdlbmVyYXRlIHBvbHlnb24gZG9lcyBub3QgZW5hYmxlIHNlbGVjdGlvblxuICAgIC8vIGZpbHRlciBvdXQgcG9pbnRzIGJ5IHZpc2libGUgc2NhdHRlciBvbmVzXG4gICAgaWYoc2VsZWN0aW9uVGVzdGVyICE9PSBmYWxzZSAmJiAhc2VsZWN0aW9uVGVzdGVyLmRlZ2VuZXJhdGUpIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBpZihzZWxlY3Rpb25UZXN0ZXIuY29udGFpbnMoW3N0YXNoLnhweFtpXSwgc3Rhc2gueXB4W2ldXSwgZmFsc2UsIGksIHNlYXJjaEluZm8pKSB7XG4gICAgICAgICAgICAgICAgZWxzLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogaSxcbiAgICAgICAgICAgICAgICAgICAgeDogeFtpXSxcbiAgICAgICAgICAgICAgICAgICAgeTogeVtpXVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB1bmVscy5wdXNoKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoaGFzTWFya2Vycykge1xuICAgICAgICB2YXIgc2NhdHRlcjJkID0gc2NlbmUuc2NhdHRlcjJkO1xuXG4gICAgICAgIGlmKCFlbHMubGVuZ3RoICYmICF1bmVscy5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIHJlc2V0IHRvIGJhc2Ugc3R5bGVzIHdoZW4gY2xlYXJpbmdcbiAgICAgICAgICAgIHZhciBiYXNlT3B0cyA9IG5ldyBBcnJheShzY2VuZS5jb3VudCk7XG4gICAgICAgICAgICBiYXNlT3B0c1tpbmRleF0gPSBzY2VuZS5tYXJrZXJPcHRpb25zW2luZGV4XTtcbiAgICAgICAgICAgIHNjYXR0ZXIyZC51cGRhdGUuYXBwbHkoc2NhdHRlcjJkLCBiYXNlT3B0cyk7XG4gICAgICAgIH0gZWxzZSBpZighc2NlbmUuc2VsZWN0QmF0Y2hbaW5kZXhdLmxlbmd0aCAmJiAhc2NlbmUudW5zZWxlY3RCYXRjaFtpbmRleF0ubGVuZ3RoKSB7XG4gICAgICAgICAgICAvLyBzZXQgdW5zZWxlY3RlZCBzdHlsZXMgb24gJ2NvbnRleHQnIGNhbnZhcyAoaWYgbm90IGRvbmUgYWxyZWFkeSlcbiAgICAgICAgICAgIHZhciB1bnNlbE9wdHMgPSBuZXcgQXJyYXkoc2NlbmUuY291bnQpO1xuICAgICAgICAgICAgdW5zZWxPcHRzW2luZGV4XSA9IHNjZW5lLm1hcmtlclVuc2VsZWN0ZWRPcHRpb25zW2luZGV4XTtcbiAgICAgICAgICAgIHNjYXR0ZXIyZC51cGRhdGUuYXBwbHkoc2NhdHRlcjJkLCB1bnNlbE9wdHMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2NlbmUuc2VsZWN0QmF0Y2hbaW5kZXhdID0gZWxzO1xuICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2hbaW5kZXhdID0gdW5lbHM7XG5cbiAgICBpZihoYXNUZXh0KSB7XG4gICAgICAgIHN0eWxlVGV4dFNlbGVjdGlvbihjZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGVjdGlvbjtcbn07XG5cbn0se1wiLi4vc2NhdHRlci9zdWJ0eXBlc1wiOjExMzUsXCIuL2VkaXRfc3R5bGVcIjoxMTY1fV0sMTE3MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBob3ZlcnRlbXBsYXRlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJHZW9BdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXJnZW8vYXR0cmlidXRlcycpO1xudmFyIHNjYXR0ZXJBdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvYXR0cmlidXRlcycpO1xudmFyIG1hcGJveEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvbWFwYm94L2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgcGxvdEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbnZhciBsaW5lQXR0cnMgPSBzY2F0dGVyR2VvQXR0cnMubGluZTtcbnZhciBtYXJrZXJBdHRycyA9IHNjYXR0ZXJHZW9BdHRycy5tYXJrZXI7XG5cbm1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoe1xuICAgIGxvbjogc2NhdHRlckdlb0F0dHJzLmxvbixcbiAgICBsYXQ6IHNjYXR0ZXJHZW9BdHRycy5sYXQsXG5cbiAgICAvLyBsb2NhdGlvbnNcbiAgICAvLyBsb2NhdGlvbm1vZGVcblxuICAgIG1vZGU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5tb2RlLCB7XG4gICAgICAgIGRmbHQ6ICdtYXJrZXJzJyxcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICB0ZXh0OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMudGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcnRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5ob3ZlcnRleHQsIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBsaW5lOiB7XG4gICAgICAgIGNvbG9yOiBsaW5lQXR0cnMuY29sb3IsXG4gICAgICAgIHdpZHRoOiBsaW5lQXR0cnMud2lkdGhcblxuICAgICAgICAvLyBUT0RPXG4gICAgICAgIC8vIGRhc2g6IGRhc2hcbiAgICB9LFxuXG4gICAgY29ubmVjdGdhcHM6IHNjYXR0ZXJBdHRycy5jb25uZWN0Z2FwcyxcblxuICAgIG1hcmtlcjogZXh0ZW5kRmxhdCh7XG4gICAgICAgIHN5bWJvbDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBkZmx0OiAnY2lyY2xlJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBvcGFjaXR5OiBtYXJrZXJBdHRycy5vcGFjaXR5LFxuICAgICAgICBzaXplOiBtYXJrZXJBdHRycy5zaXplLFxuICAgICAgICBzaXplcmVmOiBtYXJrZXJBdHRycy5zaXplcmVmLFxuICAgICAgICBzaXplbWluOiBtYXJrZXJBdHRycy5zaXplbWluLFxuICAgICAgICBzaXplbW9kZTogbWFya2VyQXR0cnMuc2l6ZW1vZGVcbiAgICB9LFxuICAgICAgICBjb2xvclNjYWxlQXR0cnMoJ21hcmtlcicpXG4gICAgICAgIC8vIGxpbmVcbiAgICApLFxuXG4gICAgZmlsbDogc2NhdHRlckdlb0F0dHJzLmZpbGwsXG4gICAgZmlsbGNvbG9yOiBzY2F0dGVyQXR0cnMuZmlsbGNvbG9yLFxuXG4gICAgdGV4dGZvbnQ6IG1hcGJveEF0dHJzLmxheWVycy5zeW1ib2wudGV4dGZvbnQsXG4gICAgdGV4dHBvc2l0aW9uOiBtYXBib3hBdHRycy5sYXllcnMuc3ltYm9sLnRleHRwb3NpdGlvbixcblxuICAgIGJlbG93OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHNlbGVjdGVkOiB7XG4gICAgICAgIG1hcmtlcjogc2NhdHRlckF0dHJzLnNlbGVjdGVkLm1hcmtlclxuICAgIH0sXG4gICAgdW5zZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHNjYXR0ZXJBdHRycy51bnNlbGVjdGVkLm1hcmtlclxuICAgIH0sXG5cbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIHBsb3RBdHRycy5ob3ZlcmluZm8sIHtcbiAgICAgICAgZmxhZ3M6IFsnbG9uJywgJ2xhdCcsICd0ZXh0JywgJ25hbWUnXVxuICAgIH0pLFxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycygpLFxufSwgJ2NhbGMnLCAnbmVzdGVkJyk7XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXNcIjo2MDAsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NCxcIi4uLy4uL3Bsb3RzL21hcGJveC9sYXlvdXRfYXR0cmlidXRlc1wiOjgyNCxcIi4uL3NjYXR0ZXIvYXR0cmlidXRlc1wiOjExMTIsXCIuLi9zY2F0dGVyZ2VvL2F0dHJpYnV0ZXNcIjoxMTUxfV0sMTE3MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQkFETlVNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcbnZhciBnZW9Kc29uVXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvZ2VvanNvbl91dGlscycpO1xuXG52YXIgQ29sb3JzY2FsZSA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZScpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBtYWtlQnViYmxlU2l6ZUZuID0gX2RlcmVxXygnLi4vc2NhdHRlci9tYWtlX2J1YmJsZV9zaXplX2Z1bmMnKTtcbnZhciBzdWJUeXBlcyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBjb252ZXJ0VGV4dE9wdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9tYXBib3gvY29udmVydF90ZXh0X29wdHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb252ZXJ0KGNhbGNUcmFjZSkge1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgIHZhciBpc1Zpc2libGUgPSAodHJhY2UudmlzaWJsZSA9PT0gdHJ1ZSAmJiB0cmFjZS5fbGVuZ3RoICE9PSAwKTtcbiAgICB2YXIgaGFzRmlsbCA9ICh0cmFjZS5maWxsICE9PSAnbm9uZScpO1xuICAgIHZhciBoYXNMaW5lcyA9IHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlKTtcbiAgICB2YXIgaGFzTWFya2VycyA9IHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2UpO1xuICAgIHZhciBoYXNUZXh0ID0gc3ViVHlwZXMuaGFzVGV4dCh0cmFjZSk7XG4gICAgdmFyIGhhc0NpcmNsZXMgPSAoaGFzTWFya2VycyAmJiB0cmFjZS5tYXJrZXIuc3ltYm9sID09PSAnY2lyY2xlJyk7XG4gICAgdmFyIGhhc1N5bWJvbHMgPSAoaGFzTWFya2VycyAmJiB0cmFjZS5tYXJrZXIuc3ltYm9sICE9PSAnY2lyY2xlJyk7XG5cbiAgICB2YXIgZmlsbCA9IGluaXRDb250YWluZXIoKTtcbiAgICB2YXIgbGluZSA9IGluaXRDb250YWluZXIoKTtcbiAgICB2YXIgY2lyY2xlID0gaW5pdENvbnRhaW5lcigpO1xuICAgIHZhciBzeW1ib2wgPSBpbml0Q29udGFpbmVyKCk7XG5cbiAgICB2YXIgb3B0cyA9IHtcbiAgICAgICAgZmlsbDogZmlsbCxcbiAgICAgICAgbGluZTogbGluZSxcbiAgICAgICAgY2lyY2xlOiBjaXJjbGUsXG4gICAgICAgIHN5bWJvbDogc3ltYm9sXG4gICAgfTtcblxuICAgIC8vIGVhcmx5IHJldHVybiBpZiBub3QgdmlzaWJsZSBvciBwbGFjZWhvbGRlclxuICAgIGlmKCFpc1Zpc2libGUpIHJldHVybiBvcHRzO1xuXG4gICAgLy8gZmlsbCBsYXllciBhbmQgbGluZSBsYXllciB1c2UgdGhlIHNhbWUgY29vcmRzXG4gICAgdmFyIGxpbmVDb29yZHM7XG4gICAgaWYoaGFzRmlsbCB8fCBoYXNMaW5lcykge1xuICAgICAgICBsaW5lQ29vcmRzID0gZ2VvSnNvblV0aWxzLmNhbGNUcmFjZVRvTGluZUNvb3JkcyhjYWxjVHJhY2UpO1xuICAgIH1cblxuICAgIGlmKGhhc0ZpbGwpIHtcbiAgICAgICAgZmlsbC5nZW9qc29uID0gZ2VvSnNvblV0aWxzLm1ha2VQb2x5Z29uKGxpbmVDb29yZHMpO1xuICAgICAgICBmaWxsLmxheW91dC52aXNpYmlsaXR5ID0gJ3Zpc2libGUnO1xuXG4gICAgICAgIExpYi5leHRlbmRGbGF0KGZpbGwucGFpbnQsIHtcbiAgICAgICAgICAgICdmaWxsLWNvbG9yJzogdHJhY2UuZmlsbGNvbG9yXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKGhhc0xpbmVzKSB7XG4gICAgICAgIGxpbmUuZ2VvanNvbiA9IGdlb0pzb25VdGlscy5tYWtlTGluZShsaW5lQ29vcmRzKTtcbiAgICAgICAgbGluZS5sYXlvdXQudmlzaWJpbGl0eSA9ICd2aXNpYmxlJztcblxuICAgICAgICBMaWIuZXh0ZW5kRmxhdChsaW5lLnBhaW50LCB7XG4gICAgICAgICAgICAnbGluZS13aWR0aCc6IHRyYWNlLmxpbmUud2lkdGgsXG4gICAgICAgICAgICAnbGluZS1jb2xvcic6IHRyYWNlLmxpbmUuY29sb3IsXG4gICAgICAgICAgICAnbGluZS1vcGFjaXR5JzogdHJhY2Uub3BhY2l0eVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBUT0RPIGNvbnZlcnQgbGluZS5kYXNoIGludG8gbGluZS1kYXNoYXJyYXlcbiAgICB9XG5cbiAgICBpZihoYXNDaXJjbGVzKSB7XG4gICAgICAgIHZhciBjaXJjbGVPcHRzID0gbWFrZUNpcmNsZU9wdHMoY2FsY1RyYWNlKTtcbiAgICAgICAgY2lyY2xlLmdlb2pzb24gPSBjaXJjbGVPcHRzLmdlb2pzb247XG4gICAgICAgIGNpcmNsZS5sYXlvdXQudmlzaWJpbGl0eSA9ICd2aXNpYmxlJztcblxuICAgICAgICBMaWIuZXh0ZW5kRmxhdChjaXJjbGUucGFpbnQsIHtcbiAgICAgICAgICAgICdjaXJjbGUtY29sb3InOiBjaXJjbGVPcHRzLm1jYyxcbiAgICAgICAgICAgICdjaXJjbGUtcmFkaXVzJzogY2lyY2xlT3B0cy5tcmMsXG4gICAgICAgICAgICAnY2lyY2xlLW9wYWNpdHknOiBjaXJjbGVPcHRzLm1vXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmKGhhc1N5bWJvbHMgfHwgaGFzVGV4dCkge1xuICAgICAgICBzeW1ib2wuZ2VvanNvbiA9IG1ha2VTeW1ib2xHZW9KU09OKGNhbGNUcmFjZSk7XG5cbiAgICAgICAgTGliLmV4dGVuZEZsYXQoc3ltYm9sLmxheW91dCwge1xuICAgICAgICAgICAgdmlzaWJpbGl0eTogJ3Zpc2libGUnLFxuICAgICAgICAgICAgJ2ljb24taW1hZ2UnOiAne3N5bWJvbH0tMTUnLFxuICAgICAgICAgICAgJ3RleHQtZmllbGQnOiAne3RleHR9J1xuICAgICAgICB9KTtcblxuICAgICAgICBpZihoYXNTeW1ib2xzKSB7XG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChzeW1ib2wubGF5b3V0LCB7XG4gICAgICAgICAgICAgICAgJ2ljb24tc2l6ZSc6IHRyYWNlLm1hcmtlci5zaXplIC8gMTBcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChzeW1ib2wucGFpbnQsIHtcbiAgICAgICAgICAgICAgICAnaWNvbi1vcGFjaXR5JzogdHJhY2Uub3BhY2l0eSAqIHRyYWNlLm1hcmtlci5vcGFjaXR5LFxuXG4gICAgICAgICAgICAgICAgLy8gVE9ETyBkb2VzIG5vdCB3b3JrID8/XG4gICAgICAgICAgICAgICAgJ2ljb24tY29sb3InOiB0cmFjZS5tYXJrZXIuY29sb3JcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaGFzVGV4dCkge1xuICAgICAgICAgICAgdmFyIGljb25TaXplID0gKHRyYWNlLm1hcmtlciB8fCB7fSkuc2l6ZTtcbiAgICAgICAgICAgIHZhciB0ZXh0T3B0cyA9IGNvbnZlcnRUZXh0T3B0cyh0cmFjZS50ZXh0cG9zaXRpb24sIGljb25TaXplKTtcblxuICAgICAgICAgICAgLy8gYWxsIGRhdGEtZHJpdmVuIGJlbG93ICEhXG5cbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KHN5bWJvbC5sYXlvdXQsIHtcbiAgICAgICAgICAgICAgICAndGV4dC1zaXplJzogdHJhY2UudGV4dGZvbnQuc2l6ZSxcbiAgICAgICAgICAgICAgICAndGV4dC1hbmNob3InOiB0ZXh0T3B0cy5hbmNob3IsXG4gICAgICAgICAgICAgICAgJ3RleHQtb2Zmc2V0JzogdGV4dE9wdHMub2Zmc2V0XG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPIGZvbnQgZmFtaWx5XG4gICAgICAgICAgICAgICAgLy8gJ3RleHQtZm9udCc6IHN5bWJvbC50ZXh0Zm9udC5mYW1pbHkuc3BsaXQoJywgJyksXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQoc3ltYm9sLnBhaW50LCB7XG4gICAgICAgICAgICAgICAgJ3RleHQtY29sb3InOiB0cmFjZS50ZXh0Zm9udC5jb2xvcixcbiAgICAgICAgICAgICAgICAndGV4dC1vcGFjaXR5JzogdHJhY2Uub3BhY2l0eVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3B0cztcbn07XG5cbmZ1bmN0aW9uIGluaXRDb250YWluZXIoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZ2VvanNvbjogZ2VvSnNvblV0aWxzLm1ha2VCbGFuaygpLFxuICAgICAgICBsYXlvdXQ6IHsgdmlzaWJpbGl0eTogJ25vbmUnIH0sXG4gICAgICAgIHBhaW50OiB7fVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIG1ha2VDaXJjbGVPcHRzKGNhbGNUcmFjZSkge1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcbiAgICB2YXIgbWFya2VyID0gdHJhY2UubWFya2VyO1xuICAgIHZhciBzZWxlY3RlZHBvaW50cyA9IHRyYWNlLnNlbGVjdGVkcG9pbnRzO1xuICAgIHZhciBhcnJheUNvbG9yID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyLmNvbG9yKTtcbiAgICB2YXIgYXJyYXlTaXplID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXkobWFya2VyLnNpemUpO1xuICAgIHZhciBhcnJheU9wYWNpdHkgPSBMaWIuaXNBcnJheU9yVHlwZWRBcnJheShtYXJrZXIub3BhY2l0eSk7XG4gICAgdmFyIGk7XG5cbiAgICBmdW5jdGlvbiBhZGRUcmFjZU9wYWNpdHkobykgeyByZXR1cm4gdHJhY2Uub3BhY2l0eSAqIG87IH1cblxuICAgIGZ1bmN0aW9uIHNpemUycmFkaXVzKHMpIHsgcmV0dXJuIHMgLyAyOyB9XG5cbiAgICB2YXIgY29sb3JGbjtcbiAgICBpZihhcnJheUNvbG9yKSB7XG4gICAgICAgIGlmKENvbG9yc2NhbGUuaGFzQ29sb3JzY2FsZSh0cmFjZSwgJ21hcmtlcicpKSB7XG4gICAgICAgICAgICBjb2xvckZuID0gQ29sb3JzY2FsZS5tYWtlQ29sb3JTY2FsZUZ1bmNGcm9tVHJhY2UobWFya2VyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbG9yRm4gPSBMaWIuaWRlbnRpdHk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc2l6ZUZuO1xuICAgIGlmKGFycmF5U2l6ZSkge1xuICAgICAgICBzaXplRm4gPSBtYWtlQnViYmxlU2l6ZUZuKHRyYWNlKTtcbiAgICB9XG5cbiAgICB2YXIgb3BhY2l0eUZuO1xuICAgIGlmKGFycmF5T3BhY2l0eSkge1xuICAgICAgICBvcGFjaXR5Rm4gPSBmdW5jdGlvbihtbykge1xuICAgICAgICAgICAgdmFyIG1vMiA9IGlzTnVtZXJpYyhtbykgPyArTGliLmNvbnN0cmFpbihtbywgMCwgMSkgOiAwO1xuICAgICAgICAgICAgcmV0dXJuIGFkZFRyYWNlT3BhY2l0eShtbzIpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBmZWF0dXJlcyA9IFtdO1xuICAgIGZvcihpID0gMDsgaSA8IGNhbGNUcmFjZS5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2FsY1B0ID0gY2FsY1RyYWNlW2ldO1xuICAgICAgICB2YXIgbG9ubGF0ID0gY2FsY1B0LmxvbmxhdDtcblxuICAgICAgICBpZihpc0JBRE5VTShsb25sYXQpKSBjb250aW51ZTtcblxuICAgICAgICB2YXIgcHJvcHMgPSB7fTtcbiAgICAgICAgaWYoY29sb3JGbikgcHJvcHMubWNjID0gY2FsY1B0Lm1jYyA9IGNvbG9yRm4oY2FsY1B0Lm1jKTtcbiAgICAgICAgaWYoc2l6ZUZuKSBwcm9wcy5tcmMgPSBjYWxjUHQubXJjID0gc2l6ZUZuKGNhbGNQdC5tcyk7XG4gICAgICAgIGlmKG9wYWNpdHlGbikgcHJvcHMubW8gPSBvcGFjaXR5Rm4oY2FsY1B0Lm1vKTtcbiAgICAgICAgaWYoc2VsZWN0ZWRwb2ludHMpIHByb3BzLnNlbGVjdGVkID0gY2FsY1B0LnNlbGVjdGVkIHx8IDA7XG5cbiAgICAgICAgZmVhdHVyZXMucHVzaCh7XG4gICAgICAgICAgICB0eXBlOiAnRmVhdHVyZScsXG4gICAgICAgICAgICBnZW9tZXRyeToge3R5cGU6ICdQb2ludCcsIGNvb3JkaW5hdGVzOiBsb25sYXR9LFxuICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIGZucztcbiAgICBpZihzZWxlY3RlZHBvaW50cykge1xuICAgICAgICBmbnMgPSBEcmF3aW5nLm1ha2VTZWxlY3RlZFBvaW50U3R5bGVGbnModHJhY2UpO1xuXG4gICAgICAgIGZvcihpID0gMDsgaSA8IGZlYXR1cmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZCA9IGZlYXR1cmVzW2ldLnByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGlmKGZucy5zZWxlY3RlZE9wYWNpdHlGbikge1xuICAgICAgICAgICAgICAgIGQubW8gPSBhZGRUcmFjZU9wYWNpdHkoZm5zLnNlbGVjdGVkT3BhY2l0eUZuKGQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGZucy5zZWxlY3RlZENvbG9yRm4pIHtcbiAgICAgICAgICAgICAgICBkLm1jYyA9IGZucy5zZWxlY3RlZENvbG9yRm4oZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihmbnMuc2VsZWN0ZWRTaXplRm4pIHtcbiAgICAgICAgICAgICAgICBkLm1yYyA9IGZucy5zZWxlY3RlZFNpemVGbihkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGdlb2pzb246IHt0eXBlOiAnRmVhdHVyZUNvbGxlY3Rpb24nLCBmZWF0dXJlczogZmVhdHVyZXN9LFxuICAgICAgICBtY2M6IGFycmF5Q29sb3IgfHwgKGZucyAmJiBmbnMuc2VsZWN0ZWRDb2xvckZuKSA/XG4gICAgICAgICAgICB7dHlwZTogJ2lkZW50aXR5JywgcHJvcGVydHk6ICdtY2MnfSA6XG4gICAgICAgICAgICBtYXJrZXIuY29sb3IsXG4gICAgICAgIG1yYzogYXJyYXlTaXplIHx8IChmbnMgJiYgZm5zLnNlbGVjdGVkU2l6ZUZuKSA/XG4gICAgICAgICAgICB7dHlwZTogJ2lkZW50aXR5JywgcHJvcGVydHk6ICdtcmMnfSA6XG4gICAgICAgICAgICBzaXplMnJhZGl1cyhtYXJrZXIuc2l6ZSksXG4gICAgICAgIG1vOiBhcnJheU9wYWNpdHkgfHwgKGZucyAmJiBmbnMuc2VsZWN0ZWRPcGFjaXR5Rm4pID9cbiAgICAgICAgICAgIHt0eXBlOiAnaWRlbnRpdHknLCBwcm9wZXJ0eTogJ21vJ30gOlxuICAgICAgICAgICAgYWRkVHJhY2VPcGFjaXR5KG1hcmtlci5vcGFjaXR5KVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIG1ha2VTeW1ib2xHZW9KU09OKGNhbGNUcmFjZSkge1xuICAgIHZhciB0cmFjZSA9IGNhbGNUcmFjZVswXS50cmFjZTtcblxuICAgIHZhciBtYXJrZXIgPSB0cmFjZS5tYXJrZXIgfHwge307XG4gICAgdmFyIHN5bWJvbCA9IG1hcmtlci5zeW1ib2w7XG4gICAgdmFyIHRleHQgPSB0cmFjZS50ZXh0O1xuXG4gICAgdmFyIGZpbGxTeW1ib2wgPSAoc3ltYm9sICE9PSAnY2lyY2xlJykgP1xuICAgICAgICBnZXRGaWxsRnVuYyhzeW1ib2wpIDpcbiAgICAgICAgYmxhbmtGaWxsRnVuYztcblxuICAgIHZhciBmaWxsVGV4dCA9IHN1YlR5cGVzLmhhc1RleHQodHJhY2UpID9cbiAgICAgICAgZ2V0RmlsbEZ1bmModGV4dCkgOlxuICAgICAgICBibGFua0ZpbGxGdW5jO1xuXG4gICAgdmFyIGZlYXR1cmVzID0gW107XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY1RyYWNlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYWxjUHQgPSBjYWxjVHJhY2VbaV07XG5cbiAgICAgICAgaWYoaXNCQUROVU0oY2FsY1B0LmxvbmxhdCkpIGNvbnRpbnVlO1xuXG4gICAgICAgIGZlYXR1cmVzLnB1c2goe1xuICAgICAgICAgICAgdHlwZTogJ0ZlYXR1cmUnLFxuICAgICAgICAgICAgZ2VvbWV0cnk6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnUG9pbnQnLFxuICAgICAgICAgICAgICAgIGNvb3JkaW5hdGVzOiBjYWxjUHQubG9ubGF0XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgIHN5bWJvbDogZmlsbFN5bWJvbChjYWxjUHQubXgpLFxuICAgICAgICAgICAgICAgIHRleHQ6IGZpbGxUZXh0KGNhbGNQdC50eClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogJ0ZlYXR1cmVDb2xsZWN0aW9uJyxcbiAgICAgICAgZmVhdHVyZXM6IGZlYXR1cmVzXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0RmlsbEZ1bmMoYXR0cikge1xuICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KGF0dHIpKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7IHJldHVybiB2OyB9O1xuICAgIH0gZWxzZSBpZihhdHRyKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbigpIHsgcmV0dXJuIGF0dHI7IH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGJsYW5rRmlsbEZ1bmM7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBibGFua0ZpbGxGdW5jKCkgeyByZXR1cm4gJyc7IH1cblxuLy8gb25seSBuZWVkIHRvIGNoZWNrIGxvbiAoT1IgbGF0KVxuZnVuY3Rpb24gaXNCQUROVU0obG9ubGF0KSB7XG4gICAgcmV0dXJuIGxvbmxhdFswXSA9PT0gQkFETlVNO1xufVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZVwiOjYwNSxcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZ2VvanNvbl91dGlsc1wiOjcxNCxcIi4uLy4uL3Bsb3RzL21hcGJveC9jb252ZXJ0X3RleHRfb3B0c1wiOjgyMSxcIi4uL3NjYXR0ZXIvbWFrZV9idWJibGVfc2l6ZV9mdW5jXCI6MTEyOCxcIi4uL3NjYXR0ZXIvc3VidHlwZXNcIjoxMTM1LFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSwxMTczOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgc3ViVHlwZXMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgaGFuZGxlTWFya2VyRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbGluZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRleHREZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsZW4gPSBoYW5kbGVMb25MYXREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG4gICAgY29lcmNlKCdtb2RlJyk7XG4gICAgY29lcmNlKCdiZWxvdycpO1xuXG4gICAgaWYoc3ViVHlwZXMuaGFzTGluZXModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZUxpbmVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSwge25vRGFzaDogdHJ1ZX0pO1xuICAgICAgICBjb2VyY2UoJ2Nvbm5lY3RnYXBzJyk7XG4gICAgfVxuXG4gICAgaWYoc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTWFya2VyRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UsIHtub0xpbmU6IHRydWV9KTtcblxuICAgICAgICAvLyBhcnJheSBtYXJrZXIuc2l6ZSBhbmQgbWFya2VyLmNvbG9yIGFyZSBvbmx5IHN1cHBvcnRlZCB3aXRoIGNpcmNsZXNcbiAgICAgICAgdmFyIG1hcmtlciA9IHRyYWNlT3V0Lm1hcmtlcjtcbiAgICAgICAgaWYobWFya2VyLnN5bWJvbCAhPT0gJ2NpcmNsZScpIHtcbiAgICAgICAgICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG1hcmtlci5zaXplKSkgbWFya2VyLnNpemUgPSBtYXJrZXIuc2l6ZVswXTtcbiAgICAgICAgICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KG1hcmtlci5jb2xvcikpIG1hcmtlci5jb2xvciA9IG1hcmtlci5jb2xvclswXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc1RleHQodHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZVRleHREZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHtub1NlbGVjdDogdHJ1ZX0pO1xuICAgIH1cblxuICAgIGNvZXJjZSgnZmlsbCcpO1xuICAgIGlmKHRyYWNlT3V0LmZpbGwgIT09ICdub25lJykge1xuICAgICAgICBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBjb2VyY2UpO1xuICAgIH1cblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufTtcblxuZnVuY3Rpb24gaGFuZGxlTG9uTGF0RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSkge1xuICAgIHZhciBsb24gPSBjb2VyY2UoJ2xvbicpIHx8IFtdO1xuICAgIHZhciBsYXQgPSBjb2VyY2UoJ2xhdCcpIHx8IFtdO1xuICAgIHZhciBsZW4gPSBNYXRoLm1pbihsb24ubGVuZ3RoLCBsYXQubGVuZ3RoKTtcbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuXG4gICAgcmV0dXJuIGxlbjtcbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi9zY2F0dGVyL2ZpbGxjb2xvcl9kZWZhdWx0c1wiOjExMjAsXCIuLi9zY2F0dGVyL2xpbmVfZGVmYXVsdHNcIjoxMTI0LFwiLi4vc2NhdHRlci9tYXJrZXJfZGVmYXVsdHNcIjoxMTMwLFwiLi4vc2NhdHRlci9zdWJ0eXBlc1wiOjExMzUsXCIuLi9zY2F0dGVyL3RleHRfZGVmYXVsdHNcIjoxMTM2LFwiLi9hdHRyaWJ1dGVzXCI6MTE3MX1dLDExNzQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBldmVudERhdGEob3V0LCBwdCkge1xuICAgIG91dC5sb24gPSBwdC5sb247XG4gICAgb3V0LmxhdCA9IHB0LmxhdDtcblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG59LHt9XSwxMTc1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgZ2V0VHJhY2VDb2xvciA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvZ2V0X3RyYWNlX2NvbG9yJyk7XG52YXIgZmlsbFRleHQgPSBMaWIuZmlsbFRleHQ7XG52YXIgQkFETlVNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgdmFyIHhhID0gcG9pbnREYXRhLnhhO1xuICAgIHZhciB5YSA9IHBvaW50RGF0YS55YTtcbiAgICB2YXIgc3VicGxvdCA9IHBvaW50RGF0YS5zdWJwbG90O1xuXG4gICAgLy8gY29tcHV0ZSB3aW5kaW5nIG51bWJlciBhYm91dCBbLTE4MCwgMTgwXSBnbG9iZVxuICAgIHZhciB3aW5kaW5nID0gKHh2YWwgPj0gMCkgP1xuICAgICAgICBNYXRoLmZsb29yKCh4dmFsICsgMTgwKSAvIDM2MCkgOlxuICAgICAgICBNYXRoLmNlaWwoKHh2YWwgLSAxODApIC8gMzYwKTtcblxuICAgIC8vIHNoaWZ0IGxvbmdpdHVkZSB0byBbLTE4MCwgMTgwXSB0byBkZXRlcm1pbmUgY2xvc2VzdCBwb2ludFxuICAgIHZhciBsb25TaGlmdCA9IHdpbmRpbmcgKiAzNjA7XG4gICAgdmFyIHh2YWwyID0geHZhbCAtIGxvblNoaWZ0O1xuXG4gICAgZnVuY3Rpb24gZGlzdEZuKGQpIHtcbiAgICAgICAgdmFyIGxvbmxhdCA9IGQubG9ubGF0O1xuICAgICAgICBpZihsb25sYXRbMF0gPT09IEJBRE5VTSkgcmV0dXJuIEluZmluaXR5O1xuXG4gICAgICAgIHZhciBsb24gPSBMaWIubW9kSGFsZihsb25sYXRbMF0sIDM2MCk7XG4gICAgICAgIHZhciBsYXQgPSBsb25sYXRbMV07XG4gICAgICAgIHZhciBwdCA9IHN1YnBsb3QucHJvamVjdChbbG9uLCBsYXRdKTtcbiAgICAgICAgdmFyIGR4ID0gcHQueCAtIHhhLmMycChbeHZhbDIsIGxhdF0pO1xuICAgICAgICB2YXIgZHkgPSBwdC55IC0geWEuYzJwKFtsb24sIHl2YWxdKTtcbiAgICAgICAgdmFyIHJhZCA9IE1hdGgubWF4KDMsIGQubXJjIHx8IDApO1xuXG4gICAgICAgIHJldHVybiBNYXRoLm1heChNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpIC0gcmFkLCAxIC0gMyAvIHJhZCk7XG4gICAgfVxuXG4gICAgRnguZ2V0Q2xvc2VzdChjZCwgZGlzdEZuLCBwb2ludERhdGEpO1xuXG4gICAgLy8gc2tpcCB0aGUgcmVzdCAoZm9yIHRoaXMgdHJhY2UpIGlmIHdlIGRpZG4ndCBmaW5kIGEgY2xvc2UgcG9pbnRcbiAgICBpZihwb2ludERhdGEuaW5kZXggPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICB2YXIgZGkgPSBjZFtwb2ludERhdGEuaW5kZXhdO1xuICAgIHZhciBsb25sYXQgPSBkaS5sb25sYXQ7XG4gICAgdmFyIGxvbmxhdFNoaWZ0ZWQgPSBbTGliLm1vZEhhbGYobG9ubGF0WzBdLCAzNjApICsgbG9uU2hpZnQsIGxvbmxhdFsxXV07XG5cbiAgICAvLyBzaGlmdCBsYWJlbHMgYmFjayB0byBvcmlnaW5hbCB3aW5kZWQgZ2xvYmVcbiAgICB2YXIgeGMgPSB4YS5jMnAobG9ubGF0U2hpZnRlZCk7XG4gICAgdmFyIHljID0geWEuYzJwKGxvbmxhdFNoaWZ0ZWQpO1xuICAgIHZhciByYWQgPSBkaS5tcmMgfHwgMTtcblxuICAgIHBvaW50RGF0YS54MCA9IHhjIC0gcmFkO1xuICAgIHBvaW50RGF0YS54MSA9IHhjICsgcmFkO1xuICAgIHBvaW50RGF0YS55MCA9IHljIC0gcmFkO1xuICAgIHBvaW50RGF0YS55MSA9IHljICsgcmFkO1xuXG4gICAgcG9pbnREYXRhLmNvbG9yID0gZ2V0VHJhY2VDb2xvcih0cmFjZSwgZGkpO1xuICAgIHBvaW50RGF0YS5leHRyYVRleHQgPSBnZXRFeHRyYVRleHQodHJhY2UsIGRpLCBjZFswXS50LmxhYmVscyk7XG4gICAgcG9pbnREYXRhLmhvdmVydGVtcGxhdGUgPSB0cmFjZS5ob3ZlcnRlbXBsYXRlO1xuXG4gICAgcmV0dXJuIFtwb2ludERhdGFdO1xufTtcblxuZnVuY3Rpb24gZ2V0RXh0cmFUZXh0KHRyYWNlLCBkaSwgbGFiZWxzKSB7XG4gICAgaWYodHJhY2UuaG92ZXJ0ZW1wbGF0ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGhvdmVyaW5mbyA9IGRpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgcGFydHMgPSBob3ZlcmluZm8uc3BsaXQoJysnKTtcbiAgICB2YXIgaXNBbGwgPSBwYXJ0cy5pbmRleE9mKCdhbGwnKSAhPT0gLTE7XG4gICAgdmFyIGhhc0xvbiA9IHBhcnRzLmluZGV4T2YoJ2xvbicpICE9PSAtMTtcbiAgICB2YXIgaGFzTGF0ID0gcGFydHMuaW5kZXhPZignbGF0JykgIT09IC0xO1xuICAgIHZhciBsb25sYXQgPSBkaS5sb25sYXQ7XG4gICAgdmFyIHRleHQgPSBbXTtcblxuICAgIC8vIFRPRE8gc2hvdWxkIHdlIHVzZSBhIG1vY2sgYXhpcyB0byBmb3JtYXQgaG92ZXI/XG4gICAgLy8gSWYgc28sIHdlJ2xsIG5lZWQgdG8gbWFrZSBwcmVjaXNpb24gYmUgem9vbS1sZXZlbCBkZXBlbmRlbnRcbiAgICBmdW5jdGlvbiBmb3JtYXQodikge1xuICAgICAgICByZXR1cm4gdiArICdcXHUwMEIwJztcbiAgICB9XG5cbiAgICBpZihpc0FsbCB8fCAoaGFzTG9uICYmIGhhc0xhdCkpIHtcbiAgICAgICAgdGV4dC5wdXNoKCcoJyArIGZvcm1hdChsb25sYXRbMF0pICsgJywgJyArIGZvcm1hdChsb25sYXRbMV0pICsgJyknKTtcbiAgICB9IGVsc2UgaWYoaGFzTG9uKSB7XG4gICAgICAgIHRleHQucHVzaChsYWJlbHMubG9uICsgZm9ybWF0KGxvbmxhdFswXSkpO1xuICAgIH0gZWxzZSBpZihoYXNMYXQpIHtcbiAgICAgICAgdGV4dC5wdXNoKGxhYmVscy5sYXQgKyBmb3JtYXQobG9ubGF0WzFdKSk7XG4gICAgfVxuXG4gICAgaWYoaXNBbGwgfHwgcGFydHMuaW5kZXhPZigndGV4dCcpICE9PSAtMSkge1xuICAgICAgICBmaWxsVGV4dChkaSwgdHJhY2UsIHRleHQpO1xuICAgIH1cblxuICAgIHJldHVybiB0ZXh0LmpvaW4oJzxicj4nKTtcbn1cblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2Z4XCI6NjMyLFwiLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbFwiOjY5NSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL3NjYXR0ZXIvZ2V0X3RyYWNlX2NvbG9yXCI6MTEyMX1dLDExNzY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNvbG9yYmFyOiBfZGVyZXFfKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4uL3NjYXR0ZXJnZW8vY2FsYycpLFxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIGhvdmVyUG9pbnRzOiBfZGVyZXFfKCcuL2hvdmVyJyksXG4gICAgZXZlbnREYXRhOiBfZGVyZXFfKCcuL2V2ZW50X2RhdGEnKSxcbiAgICBzZWxlY3RQb2ludHM6IF9kZXJlcV8oJy4vc2VsZWN0JyksXG5cbiAgICBzdHlsZU9uU2VsZWN0OiBmdW5jdGlvbihfLCBjZCkge1xuICAgICAgICBpZihjZCkge1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG4gICAgICAgICAgICB0cmFjZS5fZ2xUcmFjZS51cGRhdGUoY2QpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3NjYXR0ZXJtYXBib3gnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9tYXBib3gnKSxcbiAgICBjYXRlZ29yaWVzOiBbJ21hcGJveCcsICdnbCcsICdzeW1ib2xzJywgJ3Nob3dMZWdlbmQnLCAnc2NhdHRlcmxpa2UnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL21hcGJveFwiOjgyMixcIi4uL3NjYXR0ZXIvbWFya2VyX2NvbG9yYmFyXCI6MTEyOSxcIi4uL3NjYXR0ZXJnZW8vY2FsY1wiOjExNTIsXCIuL2F0dHJpYnV0ZXNcIjoxMTcxLFwiLi9kZWZhdWx0c1wiOjExNzMsXCIuL2V2ZW50X2RhdGFcIjoxMTc0LFwiLi9ob3ZlclwiOjExNzUsXCIuL3Bsb3RcIjoxMTc3LFwiLi9zZWxlY3RcIjoxMTc4fV0sMTE3NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb252ZXJ0ID0gX2RlcmVxXygnLi9jb252ZXJ0Jyk7XG52YXIgTEFZRVJfUFJFRklYID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvbWFwYm94L2NvbnN0YW50cycpLnRyYWNlTGF5ZXJQcmVmaXg7XG52YXIgT1JERVIgPSBbJ2ZpbGwnLCAnbGluZScsICdjaXJjbGUnLCAnc3ltYm9sJ107XG5cbmZ1bmN0aW9uIFNjYXR0ZXJNYXBib3goc3VicGxvdCwgdWlkKSB7XG4gICAgdGhpcy5zdWJwbG90ID0gc3VicGxvdDtcbiAgICB0aGlzLnVpZCA9IHVpZDtcblxuICAgIHRoaXMuc291cmNlSWRzID0ge1xuICAgICAgICBmaWxsOiAnc291cmNlLScgKyB1aWQgKyAnLWZpbGwnLFxuICAgICAgICBsaW5lOiAnc291cmNlLScgKyB1aWQgKyAnLWxpbmUnLFxuICAgICAgICBjaXJjbGU6ICdzb3VyY2UtJyArIHVpZCArICctY2lyY2xlJyxcbiAgICAgICAgc3ltYm9sOiAnc291cmNlLScgKyB1aWQgKyAnLXN5bWJvbCdcbiAgICB9O1xuXG4gICAgdGhpcy5sYXllcklkcyA9IHtcbiAgICAgICAgZmlsbDogTEFZRVJfUFJFRklYICsgdWlkICsgJy1maWxsJyxcbiAgICAgICAgbGluZTogTEFZRVJfUFJFRklYICsgdWlkICsgJy1saW5lJyxcbiAgICAgICAgY2lyY2xlOiBMQVlFUl9QUkVGSVggKyB1aWQgKyAnLWNpcmNsZScsXG4gICAgICAgIHN5bWJvbDogTEFZRVJfUFJFRklYICsgdWlkICsgJy1zeW1ib2wnXG4gICAgfTtcblxuICAgIC8vIFdlIGNvdWxkIG1lcmdlIHRoZSAnZmlsbCcgc291cmNlIHdpdGggdGhlICdsaW5lJyBzb3VyY2UgYW5kXG4gICAgLy8gdGhlICdjaXJjbGUnIHNvdXJjZSB3aXRoIHRoZSAnc3ltYm9sJyBzb3VyY2UgaWYgZXZlciBoYXZpbmdcbiAgICAvLyBmb3IgdXAtdG8gNCBzb3VyY2VzIHBlciAnc2NhdHRlcm1hcGJveCcgdHJhY2VzIGJlY29tZXMgYSBwcm9ibGVtLlxuXG4gICAgLy8gcHJldmlvdXMgJ2JlbG93JyB2YWx1ZSxcbiAgICAvLyBuZWVkIHRoaXMgdG8gdXBkYXRlIGl0IHByb3Blcmx5XG4gICAgdGhpcy5iZWxvdyA9IG51bGw7XG59XG5cbnZhciBwcm90byA9IFNjYXR0ZXJNYXBib3gucHJvdG90eXBlO1xuXG5wcm90by5hZGRTb3VyY2UgPSBmdW5jdGlvbihrLCBvcHRzKSB7XG4gICAgdGhpcy5zdWJwbG90Lm1hcC5hZGRTb3VyY2UodGhpcy5zb3VyY2VJZHNba10sIHtcbiAgICAgICAgdHlwZTogJ2dlb2pzb24nLFxuICAgICAgICBkYXRhOiBvcHRzLmdlb2pzb25cbiAgICB9KTtcbn07XG5cbnByb3RvLnNldFNvdXJjZURhdGEgPSBmdW5jdGlvbihrLCBvcHRzKSB7XG4gICAgdGhpcy5zdWJwbG90Lm1hcFxuICAgICAgICAuZ2V0U291cmNlKHRoaXMuc291cmNlSWRzW2tdKVxuICAgICAgICAuc2V0RGF0YShvcHRzLmdlb2pzb24pO1xufTtcblxucHJvdG8uYWRkTGF5ZXIgPSBmdW5jdGlvbihrLCBvcHRzLCBiZWxvdykge1xuICAgIHRoaXMuc3VicGxvdC5hZGRMYXllcih7XG4gICAgICAgIHR5cGU6IGssXG4gICAgICAgIGlkOiB0aGlzLmxheWVySWRzW2tdLFxuICAgICAgICBzb3VyY2U6IHRoaXMuc291cmNlSWRzW2tdLFxuICAgICAgICBsYXlvdXQ6IG9wdHMubGF5b3V0LFxuICAgICAgICBwYWludDogb3B0cy5wYWludFxuICAgIH0sIGJlbG93KTtcbn07XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uIHVwZGF0ZShjYWxjVHJhY2UpIHtcbiAgICB2YXIgc3VicGxvdCA9IHRoaXMuc3VicGxvdDtcbiAgICB2YXIgbWFwID0gc3VicGxvdC5tYXA7XG4gICAgdmFyIG9wdHNBbGwgPSBjb252ZXJ0KGNhbGNUcmFjZSk7XG4gICAgdmFyIGJlbG93ID0gc3VicGxvdC5iZWxvd0xvb2t1cFsndHJhY2UtJyArIHRoaXMudWlkXTtcbiAgICB2YXIgaSwgaywgb3B0cztcblxuICAgIGlmKGJlbG93ICE9PSB0aGlzLmJlbG93KSB7XG4gICAgICAgIGZvcihpID0gT1JERVIubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGsgPSBPUkRFUltpXTtcbiAgICAgICAgICAgIG1hcC5yZW1vdmVMYXllcih0aGlzLmxheWVySWRzW2tdKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBPUkRFUi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgayA9IE9SREVSW2ldO1xuICAgICAgICAgICAgb3B0cyA9IG9wdHNBbGxba107XG4gICAgICAgICAgICB0aGlzLmFkZExheWVyKGssIG9wdHMsIGJlbG93KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJlbG93ID0gYmVsb3c7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgT1JERVIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgayA9IE9SREVSW2ldO1xuICAgICAgICBvcHRzID0gb3B0c0FsbFtrXTtcblxuICAgICAgICBzdWJwbG90LnNldE9wdGlvbnModGhpcy5sYXllcklkc1trXSwgJ3NldExheW91dFByb3BlcnR5Jywgb3B0cy5sYXlvdXQpO1xuXG4gICAgICAgIGlmKG9wdHMubGF5b3V0LnZpc2liaWxpdHkgPT09ICd2aXNpYmxlJykge1xuICAgICAgICAgICAgdGhpcy5zZXRTb3VyY2VEYXRhKGssIG9wdHMpO1xuICAgICAgICAgICAgc3VicGxvdC5zZXRPcHRpb25zKHRoaXMubGF5ZXJJZHNba10sICdzZXRQYWludFByb3BlcnR5Jywgb3B0cy5wYWludCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBsaW5rIHJlZiBmb3IgcXVpY2sgdXBkYXRlIGR1cmluZyBzZWxlY3Rpb25zXG4gICAgY2FsY1RyYWNlWzBdLnRyYWNlLl9nbFRyYWNlID0gdGhpcztcbn07XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgIHZhciBtYXAgPSB0aGlzLnN1YnBsb3QubWFwO1xuXG4gICAgZm9yKHZhciBpID0gT1JERVIubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGsgPSBPUkRFUltpXTtcbiAgICAgICAgbWFwLnJlbW92ZUxheWVyKHRoaXMubGF5ZXJJZHNba10pO1xuICAgICAgICBtYXAucmVtb3ZlU291cmNlKHRoaXMuc291cmNlSWRzW2tdKTtcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyZWF0ZVNjYXR0ZXJNYXBib3goc3VicGxvdCwgY2FsY1RyYWNlKSB7XG4gICAgdmFyIHRyYWNlID0gY2FsY1RyYWNlWzBdLnRyYWNlO1xuICAgIHZhciBzY2F0dGVyTWFwYm94ID0gbmV3IFNjYXR0ZXJNYXBib3goc3VicGxvdCwgdHJhY2UudWlkKTtcbiAgICB2YXIgb3B0c0FsbCA9IGNvbnZlcnQoY2FsY1RyYWNlKTtcbiAgICB2YXIgYmVsb3cgPSBzY2F0dGVyTWFwYm94LmJlbG93ID0gc3VicGxvdC5iZWxvd0xvb2t1cFsndHJhY2UtJyArIHRyYWNlLnVpZF07XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgT1JERVIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGsgPSBPUkRFUltpXTtcbiAgICAgICAgdmFyIG9wdHMgPSBvcHRzQWxsW2tdO1xuICAgICAgICBzY2F0dGVyTWFwYm94LmFkZFNvdXJjZShrLCBvcHRzKTtcbiAgICAgICAgc2NhdHRlck1hcGJveC5hZGRMYXllcihrLCBvcHRzLCBiZWxvdyk7XG4gICAgfVxuXG4gICAgLy8gbGluayByZWYgZm9yIHF1aWNrIHVwZGF0ZSBkdXJpbmcgc2VsZWN0aW9uc1xuICAgIGNhbGNUcmFjZVswXS50cmFjZS5fZ2xUcmFjZSA9IHNjYXR0ZXJNYXBib3g7XG5cbiAgICByZXR1cm4gc2NhdHRlck1hcGJveDtcbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvbWFwYm94L2NvbnN0YW50c1wiOjgyMCxcIi4vY29udmVydFwiOjExNzJ9XSwxMTc4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHN1YnR5cGVzID0gX2RlcmVxXygnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIEJBRE5VTSA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2VsZWN0UG9pbnRzKHNlYXJjaEluZm8sIHNlbGVjdGlvblRlc3Rlcikge1xuICAgIHZhciBjZCA9IHNlYXJjaEluZm8uY2Q7XG4gICAgdmFyIHhhID0gc2VhcmNoSW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBzZWFyY2hJbmZvLnlheGlzO1xuICAgIHZhciBzZWxlY3Rpb24gPSBbXTtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgaTtcblxuICAgIGlmKCFzdWJ0eXBlcy5oYXNNYXJrZXJzKHRyYWNlKSkgcmV0dXJuIFtdO1xuXG4gICAgaWYoc2VsZWN0aW9uVGVzdGVyID09PSBmYWxzZSkge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY2RbaV0uc2VsZWN0ZWQgPSAwO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBkaSA9IGNkW2ldO1xuICAgICAgICAgICAgdmFyIGxvbmxhdCA9IGRpLmxvbmxhdDtcblxuICAgICAgICAgICAgaWYobG9ubGF0WzBdICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgICAgICB2YXIgbG9ubGF0MiA9IFtMaWIubW9kSGFsZihsb25sYXRbMF0sIDM2MCksIGxvbmxhdFsxXV07XG4gICAgICAgICAgICAgICAgdmFyIHh5ID0gW3hhLmMycChsb25sYXQyKSwgeWEuYzJwKGxvbmxhdDIpXTtcblxuICAgICAgICAgICAgICAgIGlmKHNlbGVjdGlvblRlc3Rlci5jb250YWlucyh4eSwgbnVsbCwgaSwgc2VhcmNoSW5mbykpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnROdW1iZXI6IGksXG4gICAgICAgICAgICAgICAgICAgICAgICBsb246IGxvbmxhdFswXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhdDogbG9ubGF0WzFdXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBkaS5zZWxlY3RlZCA9IDE7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGkuc2VsZWN0ZWQgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzZWxlY3Rpb247XG59O1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi9zY2F0dGVyL3N1YnR5cGVzXCI6MTEzNX1dLDExNzk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgc2NhdHRlckF0dHJzID0gX2RlcmVxXygnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG52YXIgcGxvdEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGxpbmVBdHRycyA9IHNjYXR0ZXJBdHRycy5saW5lO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2RlOiBzY2F0dGVyQXR0cnMubW9kZSxcblxuICAgIHI6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgdGhldGE6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgcjA6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGRyOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRoZXRhMDoge1xuICAgICAgICB2YWxUeXBlOiAnYW55JyxcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZHRoZXRhOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRoZXRhdW5pdDoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydyYWRpYW5zJywgJ2RlZ3JlZXMnLCAnZ3JhZGlhbnMnXSxcbiAgICAgICAgZGZsdDogJ2RlZ3JlZXMnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHRleHQ6IHNjYXR0ZXJBdHRycy50ZXh0LFxuICAgIGhvdmVydGV4dDogc2NhdHRlckF0dHJzLmhvdmVydGV4dCxcblxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IGxpbmVBdHRycy5jb2xvcixcbiAgICAgICAgd2lkdGg6IGxpbmVBdHRycy53aWR0aCxcbiAgICAgICAgZGFzaDogbGluZUF0dHJzLmRhc2gsXG4gICAgICAgIHNoYXBlOiBleHRlbmRGbGF0KHt9LCBsaW5lQXR0cnMuc2hhcGUsIHtcbiAgICAgICAgICAgIHZhbHVlczogWydsaW5lYXInLCAnc3BsaW5lJ11cbiAgICAgICAgfSksXG4gICAgICAgIHNtb290aGluZzogbGluZUF0dHJzLnNtb290aGluZyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgY29ubmVjdGdhcHM6IHNjYXR0ZXJBdHRycy5jb25uZWN0Z2FwcyxcblxuICAgIG1hcmtlcjogc2NhdHRlckF0dHJzLm1hcmtlcixcbiAgICBjbGlwb25heGlzOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuY2xpcG9uYXhpcywge2RmbHQ6IGZhbHNlfSksXG5cbiAgICB0ZXh0cG9zaXRpb246IHNjYXR0ZXJBdHRycy50ZXh0cG9zaXRpb24sXG4gICAgdGV4dGZvbnQ6IHNjYXR0ZXJBdHRycy50ZXh0Zm9udCxcblxuICAgIGZpbGw6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5maWxsLCB7XG4gICAgICAgIHZhbHVlczogWydub25lJywgJ3Rvc2VsZicsICd0b25leHQnXSxcbiAgICAgICAgZGZsdDogJ25vbmUnLFxuICAgICAgICBcbiAgICB9KSxcbiAgICBmaWxsY29sb3I6IHNjYXR0ZXJBdHRycy5maWxsY29sb3IsXG5cbiAgICAvLyBUT0RPIGVycm9yIGJhcnNcbiAgICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMjY1OTc0ODcvNDA2ODQ5MlxuICAgIC8vIGVycm9yX3ggKGVycm9yX3IsIGVycm9yX3RoZXRhKVxuICAgIC8vIGVycm9yX3lcblxuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgcGxvdEF0dHJzLmhvdmVyaW5mbywge1xuICAgICAgICBmbGFnczogWydyJywgJ3RoZXRhJywgJ3RleHQnLCAnbmFtZSddXG4gICAgfSksXG4gICAgaG92ZXJvbjogc2NhdHRlckF0dHJzLmhvdmVyb24sXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKCksXG5cbiAgICBzZWxlY3RlZDogc2NhdHRlckF0dHJzLnNlbGVjdGVkLFxuICAgIHVuc2VsZWN0ZWQ6IHNjYXR0ZXJBdHRycy51bnNlbGVjdGVkXG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9zY2F0dGVyL2F0dHJpYnV0ZXNcIjoxMTEyfV0sMTE4MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG52YXIgQkFETlVNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xuXG52YXIgY2FsY0NvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NvbG9yc2NhbGVfY2FsYycpO1xudmFyIGFycmF5c1RvQ2FsY2RhdGEgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2FycmF5c190b19jYWxjZGF0YScpO1xudmFyIGNhbGNTZWxlY3Rpb24gPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NhbGNfc2VsZWN0aW9uJyk7XG52YXIgY2FsY01hcmtlclNpemUgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NhbGMnKS5jYWxjTWFya2VyU2l6ZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHN1YnBsb3RJZCA9IHRyYWNlLnN1YnBsb3Q7XG4gICAgdmFyIHJhZGlhbEF4aXMgPSBmdWxsTGF5b3V0W3N1YnBsb3RJZF0ucmFkaWFsYXhpcztcbiAgICB2YXIgYW5ndWxhckF4aXMgPSBmdWxsTGF5b3V0W3N1YnBsb3RJZF0uYW5ndWxhcmF4aXM7XG4gICAgdmFyIHJBcnJheSA9IHJhZGlhbEF4aXMubWFrZUNhbGNkYXRhKHRyYWNlLCAncicpO1xuICAgIHZhciB0aGV0YUFycmF5ID0gYW5ndWxhckF4aXMubWFrZUNhbGNkYXRhKHRyYWNlLCAndGhldGEnKTtcbiAgICB2YXIgbGVuID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgY2QgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgciA9IHJBcnJheVtpXTtcbiAgICAgICAgdmFyIHRoZXRhID0gdGhldGFBcnJheVtpXTtcbiAgICAgICAgdmFyIGNkaSA9IGNkW2ldID0ge307XG5cbiAgICAgICAgaWYoaXNOdW1lcmljKHIpICYmIGlzTnVtZXJpYyh0aGV0YSkpIHtcbiAgICAgICAgICAgIGNkaS5yID0gcjtcbiAgICAgICAgICAgIGNkaS50aGV0YSA9IHRoZXRhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2RpLnIgPSBCQUROVU07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcHBhZCA9IGNhbGNNYXJrZXJTaXplKHRyYWNlLCBsZW4pO1xuICAgIHRyYWNlLl9leHRyZW1lcy54ID0gQXhlcy5maW5kRXh0cmVtZXMocmFkaWFsQXhpcywgckFycmF5LCB7cHBhZDogcHBhZH0pO1xuXG4gICAgY2FsY0NvbG9yc2NhbGUoZ2QsIHRyYWNlKTtcbiAgICBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSk7XG4gICAgY2FsY1NlbGVjdGlvbihjZCwgdHJhY2UpO1xuXG4gICAgcmV0dXJuIGNkO1xufTtcblxufSx7XCIuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsXCI6Njk1LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi9zY2F0dGVyL2FycmF5c190b19jYWxjZGF0YVwiOjExMTEsXCIuLi9zY2F0dGVyL2NhbGNcIjoxMTEzLFwiLi4vc2NhdHRlci9jYWxjX3NlbGVjdGlvblwiOjExMTQsXCIuLi9zY2F0dGVyL2NvbG9yc2NhbGVfY2FsY1wiOjExMTUsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDExODE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBzdWJUeXBlcyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBoYW5kbGVNYXJrZXJEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZURlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlTGluZVNoYXBlRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2xpbmVfc2hhcGVfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVUZXh0RGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3RleHRfZGVmYXVsdHMnKTtcbnZhciBoYW5kbGVGaWxsQ29sb3JEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvZmlsbGNvbG9yX2RlZmF1bHRzJyk7XG52YXIgUFRTX0xJTkVTT05MWSA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY29uc3RhbnRzJykuUFRTX0xJTkVTT05MWTtcblxudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcblxuZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBsZW4gPSBoYW5kbGVSVGhldGFEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpO1xuICAgIGlmKCFsZW4pIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29lcmNlKCd0aGV0YXVuaXQnKTtcbiAgICBjb2VyY2UoJ21vZGUnLCBsZW4gPCBQVFNfTElORVNPTkxZID8gJ2xpbmVzK21hcmtlcnMnIDogJ2xpbmVzJyk7XG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBpZih0cmFjZU91dC5ob3Zlcm9uICE9PSAnZmlsbHMnKSBjb2VyY2UoJ2hvdmVydGVtcGxhdGUnKTtcblxuICAgIGlmKHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVMaW5lRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpO1xuICAgICAgICBoYW5kbGVMaW5lU2hhcGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKTtcbiAgICAgICAgY29lcmNlKCdjb25uZWN0Z2FwcycpO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZU1hcmtlckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlLCB7Z3JhZGllbnQ6IHRydWV9KTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNUZXh0KHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVUZXh0RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICB2YXIgZGZsdEhvdmVyT24gPSBbXTtcblxuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2VPdXQpIHx8IHN1YlR5cGVzLmhhc1RleHQodHJhY2VPdXQpKSB7XG4gICAgICAgIGNvZXJjZSgnY2xpcG9uYXhpcycpO1xuICAgICAgICBjb2VyY2UoJ21hcmtlci5tYXhkaXNwbGF5ZWQnKTtcbiAgICAgICAgZGZsdEhvdmVyT24ucHVzaCgncG9pbnRzJyk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdmaWxsJyk7XG5cbiAgICBpZih0cmFjZU91dC5maWxsICE9PSAnbm9uZScpIHtcbiAgICAgICAgaGFuZGxlRmlsbENvbG9yRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgY29lcmNlKTtcbiAgICAgICAgaWYoIXN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlT3V0KSkgaGFuZGxlTGluZVNoYXBlRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSk7XG4gICAgfVxuXG4gICAgaWYodHJhY2VPdXQuZmlsbCA9PT0gJ3RvbmV4dCcgfHwgdHJhY2VPdXQuZmlsbCA9PT0gJ3Rvc2VsZicpIHtcbiAgICAgICAgZGZsdEhvdmVyT24ucHVzaCgnZmlsbHMnKTtcbiAgICB9XG4gICAgY29lcmNlKCdob3Zlcm9uJywgZGZsdEhvdmVyT24uam9pbignKycpIHx8ICdwb2ludHMnKTtcblxuICAgIExpYi5jb2VyY2VTZWxlY3Rpb25NYXJrZXJPcGFjaXR5KHRyYWNlT3V0LCBjb2VyY2UpO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVSVGhldGFEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpIHtcbiAgICB2YXIgciA9IGNvZXJjZSgncicpO1xuICAgIHZhciB0aGV0YSA9IGNvZXJjZSgndGhldGEnKTtcbiAgICB2YXIgbGVuO1xuXG4gICAgaWYocikge1xuICAgICAgICBpZih0aGV0YSkge1xuICAgICAgICAgICAgbGVuID0gTWF0aC5taW4oci5sZW5ndGgsIHRoZXRhLmxlbmd0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsZW4gPSByLmxlbmd0aDtcbiAgICAgICAgICAgIGNvZXJjZSgndGhldGEwJyk7XG4gICAgICAgICAgICBjb2VyY2UoJ2R0aGV0YScpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYoIXRoZXRhKSByZXR1cm4gMDtcbiAgICAgICAgbGVuID0gdHJhY2VPdXQudGhldGEubGVuZ3RoO1xuICAgICAgICBjb2VyY2UoJ3IwJyk7XG4gICAgICAgIGNvZXJjZSgnZHInKTtcbiAgICB9XG5cbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbGVuO1xuICAgIHJldHVybiBsZW47XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhhbmRsZVJUaGV0YURlZmF1bHRzOiBoYW5kbGVSVGhldGFEZWZhdWx0cyxcbiAgICBzdXBwbHlEZWZhdWx0czogc3VwcGx5RGVmYXVsdHNcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vc2NhdHRlci9jb25zdGFudHNcIjoxMTE2LFwiLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHNcIjoxMTIwLFwiLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzXCI6MTEyNCxcIi4uL3NjYXR0ZXIvbGluZV9zaGFwZV9kZWZhdWx0c1wiOjExMjYsXCIuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0c1wiOjExMzAsXCIuLi9zY2F0dGVyL3N1YnR5cGVzXCI6MTEzNSxcIi4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0c1wiOjExMzYsXCIuL2F0dHJpYnV0ZXNcIjoxMTc5fV0sMTE4MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVySG92ZXIgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2hvdmVyJyk7XG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbmZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKSB7XG4gICAgdmFyIHNjYXR0ZXJQb2ludERhdGEgPSBzY2F0dGVySG92ZXIocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpO1xuICAgIGlmKCFzY2F0dGVyUG9pbnREYXRhIHx8IHNjYXR0ZXJQb2ludERhdGFbMF0uaW5kZXggPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICB2YXIgbmV3UG9pbnREYXRhID0gc2NhdHRlclBvaW50RGF0YVswXTtcblxuICAgIC8vIGhvdmVyaW5nIG9uIGZpbGwgY2FzZVxuICAgIGlmKG5ld1BvaW50RGF0YS5pbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBzY2F0dGVyUG9pbnREYXRhO1xuICAgIH1cblxuICAgIHZhciBzdWJwbG90ID0gcG9pbnREYXRhLnN1YnBsb3Q7XG4gICAgdmFyIGNkaSA9IG5ld1BvaW50RGF0YS5jZFtuZXdQb2ludERhdGEuaW5kZXhdO1xuICAgIHZhciB0cmFjZSA9IG5ld1BvaW50RGF0YS50cmFjZTtcblxuICAgIGlmKCFzdWJwbG90LmlzUHRJbnNpZGUoY2RpKSkgcmV0dXJuO1xuXG4gICAgbmV3UG9pbnREYXRhLnhMYWJlbFZhbCA9IHVuZGVmaW5lZDtcbiAgICBuZXdQb2ludERhdGEueUxhYmVsVmFsID0gdW5kZWZpbmVkO1xuICAgIG1ha2VIb3ZlclBvaW50VGV4dChjZGksIHRyYWNlLCBzdWJwbG90LCBuZXdQb2ludERhdGEpO1xuICAgIG5ld1BvaW50RGF0YS5ob3ZlcnRlbXBsYXRlID0gdHJhY2UuaG92ZXJ0ZW1wbGF0ZTtcbiAgICByZXR1cm4gc2NhdHRlclBvaW50RGF0YTtcbn1cblxuZnVuY3Rpb24gbWFrZUhvdmVyUG9pbnRUZXh0KGNkaSwgdHJhY2UsIHN1YnBsb3QsIHBvaW50RGF0YSkge1xuICAgIHZhciByYWRpYWxBeGlzID0gc3VicGxvdC5yYWRpYWxBeGlzO1xuICAgIHZhciBhbmd1bGFyQXhpcyA9IHN1YnBsb3QuYW5ndWxhckF4aXM7XG4gICAgcmFkaWFsQXhpcy5faG92ZXJ0aXRsZSA9ICdyJztcbiAgICBhbmd1bGFyQXhpcy5faG92ZXJ0aXRsZSA9ICfOuCc7XG5cbiAgICB2YXIgclZhbCA9IHJhZGlhbEF4aXMuYzJsKGNkaS5yKTtcbiAgICBwb2ludERhdGEuckxhYmVsID0gQXhlcy50aWNrVGV4dChyYWRpYWxBeGlzLCByVmFsLCAnaG92ZXInKS50ZXh0O1xuXG4gICAgLy8gTi5CIGhlcmUgdGhlIMKwIHNpZ24gaXMgcGFydCBvZiB0aGUgZm9ybWF0dGVkIHZhbHVlIGZvciB0aGV0YXVuaXQ6J2RlZ3JlZXMnXG4gICAgdmFyIHRoZXRhVmFsID0gYW5ndWxhckF4aXMudGhldGF1bml0ID09PSAnZGVncmVlcycgPyBMaWIucmFkMmRlZyhjZGkudGhldGEpIDogY2RpLnRoZXRhO1xuICAgIHBvaW50RGF0YS50aGV0YUxhYmVsID0gQXhlcy50aWNrVGV4dChhbmd1bGFyQXhpcywgdGhldGFWYWwsICdob3ZlcicpLnRleHQ7XG5cbiAgICB2YXIgaG92ZXJpbmZvID0gY2RpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgdGV4dCA9IFtdO1xuICAgIGZ1bmN0aW9uIHRleHRQYXJ0KGF4LCB2YWwpIHtcbiAgICAgICAgdGV4dC5wdXNoKGF4Ll9ob3ZlcnRpdGxlICsgJzogJyArIHZhbCk7XG4gICAgfVxuXG4gICAgaWYoIXRyYWNlLmhvdmVydGVtcGxhdGUpIHtcbiAgICAgICAgdmFyIHBhcnRzID0gaG92ZXJpbmZvLnNwbGl0KCcrJyk7XG5cbiAgICAgICAgaWYocGFydHMuaW5kZXhPZignYWxsJykgIT09IC0xKSBwYXJ0cyA9IFsncicsICd0aGV0YScsICd0ZXh0J107XG4gICAgICAgIGlmKHBhcnRzLmluZGV4T2YoJ3InKSAhPT0gLTEpIHRleHRQYXJ0KHJhZGlhbEF4aXMsIHBvaW50RGF0YS5yTGFiZWwpO1xuICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCd0aGV0YScpICE9PSAtMSkgdGV4dFBhcnQoYW5ndWxhckF4aXMsIHBvaW50RGF0YS50aGV0YUxhYmVsKTtcblxuICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCd0ZXh0JykgIT09IC0xICYmIHBvaW50RGF0YS50ZXh0KSB7XG4gICAgICAgICAgICB0ZXh0LnB1c2gocG9pbnREYXRhLnRleHQpO1xuICAgICAgICAgICAgZGVsZXRlIHBvaW50RGF0YS50ZXh0O1xuICAgICAgICB9XG5cbiAgICAgICAgcG9pbnREYXRhLmV4dHJhVGV4dCA9IHRleHQuam9pbignPGJyPicpO1xuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgaG92ZXJQb2ludHM6IGhvdmVyUG9pbnRzLFxuICAgIG1ha2VIb3ZlclBvaW50VGV4dDogbWFrZUhvdmVyUG9pbnRUZXh0XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vc2NhdHRlci9ob3ZlclwiOjExMjJ9XSwxMTgzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnc2NhdHRlcnBvbGFyJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi4vLi4vcGxvdHMvcG9sYXInKSxcbiAgICBjYXRlZ29yaWVzOiBbJ3BvbGFyJywgJ3N5bWJvbHMnLCAnc2hvd0xlZ2VuZCcsICdzY2F0dGVyLWxpa2UnXSxcblxuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJykuc3VwcGx5RGVmYXVsdHMsXG4gICAgY29sb3JiYXI6IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbWFya2VyX2NvbG9yYmFyJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JyksXG4gICAgc3R5bGU6IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3R5bGUnKS5zdHlsZSxcbiAgICBzdHlsZU9uU2VsZWN0OiBfZGVyZXFfKCcuLi9zY2F0dGVyL3N0eWxlJykuc3R5bGVPblNlbGVjdCxcbiAgICBob3ZlclBvaW50czogX2RlcmVxXygnLi9ob3ZlcicpLmhvdmVyUG9pbnRzLFxuICAgIHNlbGVjdFBvaW50czogX2RlcmVxXygnLi4vc2NhdHRlci9zZWxlY3QnKSxcblxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvcG9sYXJcIjo4MzEsXCIuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhclwiOjExMjksXCIuLi9zY2F0dGVyL3NlbGVjdFwiOjExMzIsXCIuLi9zY2F0dGVyL3N0eWxlXCI6MTEzNCxcIi4vYXR0cmlidXRlc1wiOjExNzksXCIuL2NhbGNcIjoxMTgwLFwiLi9kZWZhdWx0c1wiOjExODEsXCIuL2hvdmVyXCI6MTE4MixcIi4vcGxvdFwiOjExODR9XSwxMTg0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJQbG90ID0gX2RlcmVxXygnLi4vc2NhdHRlci9wbG90Jyk7XG52YXIgQkFETlVNID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbCcpLkJBRE5VTTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwbG90KGdkLCBzdWJwbG90LCBtb2R1bGVDYWxjRGF0YSkge1xuICAgIHZhciBtbGF5ZXIgPSBzdWJwbG90LmxheWVycy5mcm9udHBsb3Quc2VsZWN0KCdnLnNjYXR0ZXJsYXllcicpO1xuXG4gICAgdmFyIHBsb3RpbmZvID0ge1xuICAgICAgICB4YXhpczogc3VicGxvdC54YXhpcyxcbiAgICAgICAgeWF4aXM6IHN1YnBsb3QueWF4aXMsXG4gICAgICAgIHBsb3Q6IHN1YnBsb3QuZnJhbWV3b3JrLFxuICAgICAgICBsYXllckNsaXBJZDogc3VicGxvdC5faGFzQ2xpcE9uQXhpc0ZhbHNlID8gc3VicGxvdC5jbGlwSWRzLmZvclRyYWNlcyA6IG51bGxcbiAgICB9O1xuXG4gICAgdmFyIHJhZGlhbEF4aXMgPSBzdWJwbG90LnJhZGlhbEF4aXM7XG4gICAgdmFyIGFuZ3VsYXJBeGlzID0gc3VicGxvdC5hbmd1bGFyQXhpcztcblxuICAgIC8vIGNvbnZlcnQ6XG4gICAgLy8gJ2MnIChyLHRoZXRhKSAtPiAnZ2VvbWV0cmljJyAocix0aGV0YSkgLT4gKHgseSlcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgbW9kdWxlQ2FsY0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkaSA9IG1vZHVsZUNhbGNEYXRhW2ldO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjZGkubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBjZCA9IGNkaVtqXTtcbiAgICAgICAgICAgIHZhciByID0gY2QucjtcblxuICAgICAgICAgICAgaWYociA9PT0gQkFETlVNKSB7XG4gICAgICAgICAgICAgICAgY2QueCA9IGNkLnkgPSBCQUROVU07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciByZyA9IHJhZGlhbEF4aXMuYzJnKHIpO1xuICAgICAgICAgICAgICAgIHZhciB0aGV0YWcgPSBhbmd1bGFyQXhpcy5jMmcoY2QudGhldGEpO1xuICAgICAgICAgICAgICAgIGNkLnggPSByZyAqIE1hdGguY29zKHRoZXRhZyk7XG4gICAgICAgICAgICAgICAgY2QueSA9IHJnICogTWF0aC5zaW4odGhldGFnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNjYXR0ZXJQbG90KGdkLCBwbG90aW5mbywgbW9kdWxlQ2FsY0RhdGEsIG1sYXllcik7XG59O1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi9zY2F0dGVyL3Bsb3RcIjoxMTMxfV0sMTE4NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyUG9sYXJBdHRycyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXJwb2xhci9hdHRyaWJ1dGVzJyk7XG52YXIgc2NhdHRlckdsQXR0cnMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyZ2wvYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBtb2RlOiBzY2F0dGVyUG9sYXJBdHRycy5tb2RlLFxuICAgIHI6IHNjYXR0ZXJQb2xhckF0dHJzLnIsXG4gICAgdGhldGE6IHNjYXR0ZXJQb2xhckF0dHJzLnRoZXRhLFxuICAgIHIwOiBzY2F0dGVyUG9sYXJBdHRycy5yMCxcbiAgICBkcjogc2NhdHRlclBvbGFyQXR0cnMuZHIsXG4gICAgdGhldGEwOiBzY2F0dGVyUG9sYXJBdHRycy50aGV0YTAsXG4gICAgZHRoZXRhOiBzY2F0dGVyUG9sYXJBdHRycy5kdGhldGEsXG4gICAgdGhldGF1bml0OiBzY2F0dGVyUG9sYXJBdHRycy50aGV0YXVuaXQsXG5cbiAgICB0ZXh0OiBzY2F0dGVyUG9sYXJBdHRycy50ZXh0LFxuICAgIGhvdmVydGV4dDogc2NhdHRlclBvbGFyQXR0cnMuaG92ZXJ0ZXh0LFxuICAgIGhvdmVydGVtcGxhdGU6IHNjYXR0ZXJQb2xhckF0dHJzLmhvdmVydGVtcGxhdGUsXG5cbiAgICBsaW5lOiBzY2F0dGVyR2xBdHRycy5saW5lLFxuICAgIGNvbm5lY3RnYXBzOiBzY2F0dGVyR2xBdHRycy5jb25uZWN0Z2FwcyxcblxuICAgIG1hcmtlcjogc2NhdHRlckdsQXR0cnMubWFya2VyLFxuICAgIC8vIG5vIGNsaXBvbmF4aXNcblxuICAgIGZpbGw6IHNjYXR0ZXJHbEF0dHJzLmZpbGwsXG4gICAgZmlsbGNvbG9yOiBzY2F0dGVyR2xBdHRycy5maWxsY29sb3IsXG5cbiAgICB0ZXh0cG9zaXRpb246IHNjYXR0ZXJHbEF0dHJzLnRleHRwb3NpdGlvbixcbiAgICB0ZXh0Zm9udDogc2NhdHRlckdsQXR0cnMudGV4dGZvbnQsXG5cbiAgICBob3ZlcmluZm86IHNjYXR0ZXJQb2xhckF0dHJzLmhvdmVyaW5mbyxcbiAgICAvLyBubyBob3Zlcm9uXG5cbiAgICBzZWxlY3RlZDogc2NhdHRlclBvbGFyQXR0cnMuc2VsZWN0ZWQsXG4gICAgdW5zZWxlY3RlZDogc2NhdHRlclBvbGFyQXR0cnMudW5zZWxlY3RlZFxufTtcblxufSx7XCIuLi9zY2F0dGVyZ2wvYXR0cmlidXRlc1wiOjExNjAsXCIuLi9zY2F0dGVycG9sYXIvYXR0cmlidXRlc1wiOjExNzl9XSwxMTg2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNhbGNDb2xvcnNjYWxlID0gX2RlcmVxXygnLi4vc2NhdHRlci9jb2xvcnNjYWxlX2NhbGMnKTtcbnZhciBjYWxjTWFya2VyU2l6ZSA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY2FsYycpLmNhbGNNYXJrZXJTaXplO1xudmFyIGNvbnZlcnQgPSBfZGVyZXFfKCcuLi9zY2F0dGVyZ2wvY29udmVydCcpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIFRPT19NQU5ZX1BPSU5UUyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXJnbC9jb25zdGFudHMnKS5UT09fTUFOWV9QT0lOVFM7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBzdWJwbG90SWQgPSB0cmFjZS5zdWJwbG90O1xuICAgIHZhciByYWRpYWxBeGlzID0gZnVsbExheW91dFtzdWJwbG90SWRdLnJhZGlhbGF4aXM7XG4gICAgdmFyIGFuZ3VsYXJBeGlzID0gZnVsbExheW91dFtzdWJwbG90SWRdLmFuZ3VsYXJheGlzO1xuICAgIHZhciByQXJyYXkgPSByYWRpYWxBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3InKTtcbiAgICB2YXIgdGhldGFBcnJheSA9IGFuZ3VsYXJBeGlzLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3RoZXRhJyk7XG4gICAgdmFyIGxlbiA9IHRyYWNlLl9sZW5ndGg7XG4gICAgdmFyIHN0YXNoID0ge307XG5cbiAgICBpZihsZW4gPCByQXJyYXkubGVuZ3RoKSByQXJyYXkgPSByQXJyYXkuc2xpY2UoMCwgbGVuKTtcbiAgICBpZihsZW4gPCB0aGV0YUFycmF5Lmxlbmd0aCkgdGhldGFBcnJheSA9IHRoZXRhQXJyYXkuc2xpY2UoMCwgbGVuKTtcblxuICAgIHN0YXNoLnIgPSByQXJyYXk7XG4gICAgc3Rhc2gudGhldGEgPSB0aGV0YUFycmF5O1xuXG4gICAgY2FsY0NvbG9yc2NhbGUoZ2QsIHRyYWNlKTtcblxuICAgIC8vIG9ubHkgY29tcHV0ZSAnc3R5bGUnIG9wdGlvbnMgaW4gY2FsYywgYXMgcG9zaXRpb24gb3B0aW9uc1xuICAgIC8vIGRlcGVuZCBvbiB0aGUgcmFkaWFsIHJhbmdlIGFuZCBtdXN0IGJlIHNldCBpbiBwbG90XG4gICAgdmFyIG9wdHMgPSBzdGFzaC5vcHRzID0gY29udmVydC5zdHlsZShnZCwgdHJhY2UpO1xuXG4gICAgLy8gRm9yIGdyYXBocyB3aXRoIHZlcnkgbGFyZ2UgbnVtYmVyIG9mIHBvaW50cyBhbmQgYXJyYXkgbWFya2VyLnNpemUsXG4gICAgLy8gdXNlIGF2ZXJhZ2UgbWFya2VyIHNpemUgaW5zdGVhZCB0byBzcGVlZCB0aGluZ3MgdXAuXG4gICAgdmFyIHBwYWQ7XG4gICAgaWYobGVuIDwgVE9PX01BTllfUE9JTlRTKSB7XG4gICAgICAgIHBwYWQgPSBjYWxjTWFya2VyU2l6ZSh0cmFjZSwgbGVuKTtcbiAgICB9IGVsc2UgaWYob3B0cy5tYXJrZXIpIHtcbiAgICAgICAgcHBhZCA9IDIgKiAob3B0cy5tYXJrZXIuc2l6ZUF2ZyB8fCBNYXRoLm1heChvcHRzLm1hcmtlci5zaXplLCAzKSk7XG4gICAgfVxuICAgIHRyYWNlLl9leHRyZW1lcy54ID0gQXhlcy5maW5kRXh0cmVtZXMocmFkaWFsQXhpcywgckFycmF5LCB7cHBhZDogcHBhZH0pO1xuXG4gICAgcmV0dXJuIFt7eDogZmFsc2UsIHk6IGZhbHNlLCB0OiBzdGFzaCwgdHJhY2U6IHRyYWNlfV07XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vc2NhdHRlci9jYWxjXCI6MTExMyxcIi4uL3NjYXR0ZXIvY29sb3JzY2FsZV9jYWxjXCI6MTExNSxcIi4uL3NjYXR0ZXJnbC9jb25zdGFudHNcIjoxMTYyLFwiLi4vc2NhdHRlcmdsL2NvbnZlcnRcIjoxMTYzfV0sMTE4NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIHN1YlR5cGVzID0gX2RlcmVxXygnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIGhhbmRsZVJUaGV0YURlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlcnBvbGFyL2RlZmF1bHRzJykuaGFuZGxlUlRoZXRhRGVmYXVsdHM7XG52YXIgaGFuZGxlTWFya2VyRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbGluZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZVRleHREZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHMnKTtcbnZhciBQVFNfTElORVNPTkxZID0gX2RlcmVxXygnLi4vc2NhdHRlci9jb25zdGFudHMnKS5QVFNfTElORVNPTkxZO1xuXG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgbGVuID0gaGFuZGxlUlRoZXRhRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgndGhldGF1bml0Jyk7XG4gICAgY29lcmNlKCdtb2RlJywgbGVuIDwgUFRTX0xJTkVTT05MWSA/ICdsaW5lcyttYXJrZXJzJyA6ICdsaW5lcycpO1xuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgaWYodHJhY2VPdXQuaG92ZXJvbiAhPT0gJ2ZpbGxzJykgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG5cbiAgICBpZihzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZU91dCkpIHtcbiAgICAgICAgaGFuZGxlTGluZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICAgICAgY29lcmNlKCdjb25uZWN0Z2FwcycpO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZU1hcmtlckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNUZXh0KHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVUZXh0RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBjb2VyY2UoJ2ZpbGwnKTtcbiAgICBpZih0cmFjZU91dC5maWxsICE9PSAnbm9uZScpIHtcbiAgICAgICAgaGFuZGxlRmlsbENvbG9yRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgY29lcmNlKTtcbiAgICB9XG5cbiAgICBMaWIuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eSh0cmFjZU91dCwgY29lcmNlKTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vc2NhdHRlci9jb25zdGFudHNcIjoxMTE2LFwiLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHNcIjoxMTIwLFwiLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzXCI6MTEyNCxcIi4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzXCI6MTEzMCxcIi4uL3NjYXR0ZXIvc3VidHlwZXNcIjoxMTM1LFwiLi4vc2NhdHRlci90ZXh0X2RlZmF1bHRzXCI6MTEzNixcIi4uL3NjYXR0ZXJwb2xhci9kZWZhdWx0c1wiOjExODEsXCIuL2F0dHJpYnV0ZXNcIjoxMTg1fV0sMTE4ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBob3ZlciA9IF9kZXJlcV8oJy4uL3NjYXR0ZXJnbC9ob3ZlcicpO1xudmFyIG1ha2VIb3ZlclBvaW50VGV4dCA9IF9kZXJlcV8oJy4uL3NjYXR0ZXJwb2xhci9ob3ZlcicpLm1ha2VIb3ZlclBvaW50VGV4dDtcblxuZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgY2QgPSBwb2ludERhdGEuY2Q7XG4gICAgdmFyIHN0YXNoID0gY2RbMF0udDtcbiAgICB2YXIgckFycmF5ID0gc3Rhc2gucjtcbiAgICB2YXIgdGhldGFBcnJheSA9IHN0YXNoLnRoZXRhO1xuXG4gICAgdmFyIHNjYXR0ZXJQb2ludERhdGEgPSBob3Zlci5ob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSk7XG4gICAgaWYoIXNjYXR0ZXJQb2ludERhdGEgfHwgc2NhdHRlclBvaW50RGF0YVswXS5pbmRleCA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIHZhciBuZXdQb2ludERhdGEgPSBzY2F0dGVyUG9pbnREYXRhWzBdO1xuXG4gICAgaWYobmV3UG9pbnREYXRhLmluZGV4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHNjYXR0ZXJQb2ludERhdGE7XG4gICAgfVxuXG4gICAgdmFyIHN1YnBsb3QgPSBwb2ludERhdGEuc3VicGxvdDtcbiAgICB2YXIgY2RpID0gbmV3UG9pbnREYXRhLmNkW25ld1BvaW50RGF0YS5pbmRleF07XG4gICAgdmFyIHRyYWNlID0gbmV3UG9pbnREYXRhLnRyYWNlO1xuXG4gICAgLy8gYXVnbWVudCBwb2ludERhdGEgd2l0aCByL3RoZXRhIHBhcmFtXG4gICAgY2RpLnIgPSByQXJyYXlbbmV3UG9pbnREYXRhLmluZGV4XTtcbiAgICBjZGkudGhldGEgPSB0aGV0YUFycmF5W25ld1BvaW50RGF0YS5pbmRleF07XG5cbiAgICBpZighc3VicGxvdC5pc1B0SW5zaWRlKGNkaSkpIHJldHVybjtcblxuICAgIG5ld1BvaW50RGF0YS54TGFiZWxWYWwgPSB1bmRlZmluZWQ7XG4gICAgbmV3UG9pbnREYXRhLnlMYWJlbFZhbCA9IHVuZGVmaW5lZDtcbiAgICBtYWtlSG92ZXJQb2ludFRleHQoY2RpLCB0cmFjZSwgc3VicGxvdCwgbmV3UG9pbnREYXRhKTtcblxuICAgIHJldHVybiBzY2F0dGVyUG9pbnREYXRhO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBob3ZlclBvaW50czogaG92ZXJQb2ludHNcbn07XG5cbn0se1wiLi4vc2NhdHRlcmdsL2hvdmVyXCI6MTE2NixcIi4uL3NjYXR0ZXJwb2xhci9ob3ZlclwiOjExODJ9XSwxMTg5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnc2NhdHRlcnBvbGFyZ2wnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9wb2xhcicpLFxuICAgIGNhdGVnb3JpZXM6IFsnZ2wnLCAncmVnbCcsICdwb2xhcicsICdzeW1ib2xzJywgJ3Nob3dMZWdlbmQnLCAnc2NhdHRlci1saWtlJ10sXG5cbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNvbG9yYmFyOiBfZGVyZXFfKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpLFxuXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JyksXG4gICAgaG92ZXJQb2ludHM6IF9kZXJlcV8oJy4vaG92ZXInKS5ob3ZlclBvaW50cyxcbiAgICBzZWxlY3RQb2ludHM6IF9kZXJlcV8oJy4uL3NjYXR0ZXJnbC9zZWxlY3QnKSxcblxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvcG9sYXJcIjo4MzEsXCIuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhclwiOjExMjksXCIuLi9zY2F0dGVyZ2wvc2VsZWN0XCI6MTE3MCxcIi4vYXR0cmlidXRlc1wiOjExODUsXCIuL2NhbGNcIjoxMTg2LFwiLi9kZWZhdWx0c1wiOjExODcsXCIuL2hvdmVyXCI6MTE4OCxcIi4vcGxvdFwiOjExOTB9XSwxMTkwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNsdXN0ZXIgPSBfZGVyZXFfKCdwb2ludC1jbHVzdGVyJyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIHNjYXR0ZXJnbFBsb3QgPSBfZGVyZXFfKCcuLi9zY2F0dGVyZ2wvcGxvdCcpO1xudmFyIHNjZW5lVXBkYXRlID0gX2RlcmVxXygnLi4vc2NhdHRlcmdsL3NjZW5lX3VwZGF0ZScpO1xudmFyIGNvbnZlcnQgPSBfZGVyZXFfKCcuLi9zY2F0dGVyZ2wvY29udmVydCcpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbnZhciBUT09fTUFOWV9QT0lOVFMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyZ2wvY29uc3RhbnRzJykuVE9PX01BTllfUE9JTlRTO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHN1YnBsb3QsIGNkYXRhKSB7XG4gICAgaWYoIWNkYXRhLmxlbmd0aCkgcmV0dXJuO1xuXG4gICAgdmFyIHJhZGlhbEF4aXMgPSBzdWJwbG90LnJhZGlhbEF4aXM7XG4gICAgdmFyIGFuZ3VsYXJBeGlzID0gc3VicGxvdC5hbmd1bGFyQXhpcztcbiAgICB2YXIgc2NlbmUgPSBzY2VuZVVwZGF0ZShnZCwgc3VicGxvdCk7XG5cbiAgICBjZGF0YS5mb3JFYWNoKGZ1bmN0aW9uKGNkc2NhdHRlcikge1xuICAgICAgICBpZighY2RzY2F0dGVyIHx8ICFjZHNjYXR0ZXJbMF0gfHwgIWNkc2NhdHRlclswXS50cmFjZSkgcmV0dXJuO1xuICAgICAgICB2YXIgY2QgPSBjZHNjYXR0ZXJbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkLnRyYWNlO1xuICAgICAgICB2YXIgc3Rhc2ggPSBjZC50O1xuICAgICAgICB2YXIgbGVuID0gdHJhY2UuX2xlbmd0aDtcbiAgICAgICAgdmFyIHJBcnJheSA9IHN0YXNoLnI7XG4gICAgICAgIHZhciB0aGV0YUFycmF5ID0gc3Rhc2gudGhldGE7XG4gICAgICAgIHZhciBvcHRzID0gc3Rhc2gub3B0cztcbiAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgdmFyIHN1YlJBcnJheSA9IHJBcnJheS5zbGljZSgpO1xuICAgICAgICB2YXIgc3ViVGhldGFBcnJheSA9IHRoZXRhQXJyYXkuc2xpY2UoKTtcblxuICAgICAgICAvLyBmaWx0ZXIgb3V0IGJ5IHJhbmdlXG4gICAgICAgIGZvcihpID0gMDsgaSA8IHJBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoIXN1YnBsb3QuaXNQdEluc2lkZSh7cjogckFycmF5W2ldLCB0aGV0YTogdGhldGFBcnJheVtpXX0pKSB7XG4gICAgICAgICAgICAgICAgc3ViUkFycmF5W2ldID0gTmFOO1xuICAgICAgICAgICAgICAgIHN1YlRoZXRhQXJyYXlbaV0gPSBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcG9zaXRpb25zID0gbmV3IEFycmF5KGxlbiAqIDIpO1xuICAgICAgICB2YXIgeCA9IEFycmF5KGxlbik7XG4gICAgICAgIHZhciB5ID0gQXJyYXkobGVuKTtcblxuICAgICAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgdmFyIHIgPSBzdWJSQXJyYXlbaV07XG4gICAgICAgICAgICB2YXIgeHgsIHl5O1xuXG4gICAgICAgICAgICBpZihpc051bWVyaWMocikpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmcgPSByYWRpYWxBeGlzLmMyZyhyKTtcbiAgICAgICAgICAgICAgICB2YXIgdGhldGFnID0gYW5ndWxhckF4aXMuYzJnKHN1YlRoZXRhQXJyYXlbaV0sIHRyYWNlLnRoZXRhdW5pdCk7XG4gICAgICAgICAgICAgICAgeHggPSByZyAqIE1hdGguY29zKHRoZXRhZyk7XG4gICAgICAgICAgICAgICAgeXkgPSByZyAqIE1hdGguc2luKHRoZXRhZyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHh4ID0geXkgPSBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB4W2ldID0gcG9zaXRpb25zW2kgKiAyXSA9IHh4O1xuICAgICAgICAgICAgeVtpXSA9IHBvc2l0aW9uc1tpICogMiArIDFdID0geXk7XG4gICAgICAgIH1cblxuICAgICAgICBzdGFzaC50cmVlID0gY2x1c3Rlcihwb3NpdGlvbnMpO1xuXG4gICAgICAgIC8vIEZJWE1FOiBzZWUgc2NhdHRlcmdsLmpzIzEwOVxuICAgICAgICBpZihvcHRzLm1hcmtlciAmJiBsZW4gPj0gVE9PX01BTllfUE9JTlRTKSB7XG4gICAgICAgICAgICBvcHRzLm1hcmtlci5jbHVzdGVyID0gc3Rhc2gudHJlZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG9wdHMubWFya2VyKSB7XG4gICAgICAgICAgICBvcHRzLm1hcmtlclNlbC5wb3NpdGlvbnMgPSBvcHRzLm1hcmtlclVuc2VsLnBvc2l0aW9ucyA9IG9wdHMubWFya2VyLnBvc2l0aW9ucyA9IHBvc2l0aW9ucztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG9wdHMubGluZSAmJiBwb3NpdGlvbnMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQoXG4gICAgICAgICAgICAgICAgb3B0cy5saW5lLFxuICAgICAgICAgICAgICAgIGNvbnZlcnQubGluZVBvc2l0aW9ucyhnZCwgdHJhY2UsIHBvc2l0aW9ucylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihvcHRzLnRleHQpIHtcbiAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KFxuICAgICAgICAgICAgICAgIG9wdHMudGV4dCxcbiAgICAgICAgICAgICAgICB7cG9zaXRpb25zOiBwb3NpdGlvbnN9LFxuICAgICAgICAgICAgICAgIGNvbnZlcnQudGV4dFBvc2l0aW9uKGdkLCB0cmFjZSwgb3B0cy50ZXh0LCBvcHRzLm1hcmtlcilcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdChcbiAgICAgICAgICAgICAgICBvcHRzLnRleHRTZWwsXG4gICAgICAgICAgICAgICAge3Bvc2l0aW9uczogcG9zaXRpb25zfSxcbiAgICAgICAgICAgICAgICBjb252ZXJ0LnRleHRQb3NpdGlvbihnZCwgdHJhY2UsIG9wdHMudGV4dCwgb3B0cy5tYXJrZXJTZWwpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQoXG4gICAgICAgICAgICAgICAgb3B0cy50ZXh0VW5zZWwsXG4gICAgICAgICAgICAgICAge3Bvc2l0aW9uczogcG9zaXRpb25zfSxcbiAgICAgICAgICAgICAgICBjb252ZXJ0LnRleHRQb3NpdGlvbihnZCwgdHJhY2UsIG9wdHMudGV4dCwgb3B0cy5tYXJrZXJVbnNlbClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihvcHRzLmZpbGwgJiYgIXNjZW5lLmZpbGwyZCkgc2NlbmUuZmlsbDJkID0gdHJ1ZTtcbiAgICAgICAgaWYob3B0cy5tYXJrZXIgJiYgIXNjZW5lLnNjYXR0ZXIyZCkgc2NlbmUuc2NhdHRlcjJkID0gdHJ1ZTtcbiAgICAgICAgaWYob3B0cy5saW5lICYmICFzY2VuZS5saW5lMmQpIHNjZW5lLmxpbmUyZCA9IHRydWU7XG4gICAgICAgIGlmKG9wdHMudGV4dCAmJiAhc2NlbmUuZ2xUZXh0KSBzY2VuZS5nbFRleHQgPSB0cnVlO1xuXG4gICAgICAgIHNjZW5lLmxpbmVPcHRpb25zLnB1c2gob3B0cy5saW5lKTtcbiAgICAgICAgc2NlbmUuZmlsbE9wdGlvbnMucHVzaChvcHRzLmZpbGwpO1xuICAgICAgICBzY2VuZS5tYXJrZXJPcHRpb25zLnB1c2gob3B0cy5tYXJrZXIpO1xuICAgICAgICBzY2VuZS5tYXJrZXJTZWxlY3RlZE9wdGlvbnMucHVzaChvcHRzLm1hcmtlclNlbCk7XG4gICAgICAgIHNjZW5lLm1hcmtlclVuc2VsZWN0ZWRPcHRpb25zLnB1c2gob3B0cy5tYXJrZXJVbnNlbCk7XG4gICAgICAgIHNjZW5lLnRleHRPcHRpb25zLnB1c2gob3B0cy50ZXh0KTtcbiAgICAgICAgc2NlbmUudGV4dFNlbGVjdGVkT3B0aW9ucy5wdXNoKG9wdHMudGV4dFNlbCk7XG4gICAgICAgIHNjZW5lLnRleHRVbnNlbGVjdGVkT3B0aW9ucy5wdXNoKG9wdHMudGV4dFVuc2VsKTtcbiAgICAgICAgc2NlbmUuc2VsZWN0QmF0Y2gucHVzaChbXSk7XG4gICAgICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2gucHVzaChbXSk7XG5cbiAgICAgICAgc3Rhc2gueCA9IHg7XG4gICAgICAgIHN0YXNoLnkgPSB5O1xuICAgICAgICBzdGFzaC5yYXd4ID0geDtcbiAgICAgICAgc3Rhc2gucmF3eSA9IHk7XG4gICAgICAgIHN0YXNoLnIgPSByQXJyYXk7XG4gICAgICAgIHN0YXNoLnRoZXRhID0gdGhldGFBcnJheTtcbiAgICAgICAgc3Rhc2gucG9zaXRpb25zID0gcG9zaXRpb25zO1xuICAgICAgICBzdGFzaC5fc2NlbmUgPSBzY2VuZTtcbiAgICAgICAgc3Rhc2guaW5kZXggPSBzY2VuZS5jb3VudDtcbiAgICAgICAgc2NlbmUuY291bnQrKztcbiAgICB9KTtcblxuICAgIHJldHVybiBzY2F0dGVyZ2xQbG90KGdkLCBzdWJwbG90LCBjZGF0YSk7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL3NjYXR0ZXJnbC9jb25zdGFudHNcIjoxMTYyLFwiLi4vc2NhdHRlcmdsL2NvbnZlcnRcIjoxMTYzLFwiLi4vc2NhdHRlcmdsL3Bsb3RcIjoxMTY4LFwiLi4vc2NhdHRlcmdsL3NjZW5lX3VwZGF0ZVwiOjExNjksXCJmYXN0LWlzbnVtZXJpY1wiOjIyNSxcInBvaW50LWNsdXN0ZXJcIjo0Njl9XSwxMTkxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGhvdmVydGVtcGxhdGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzJyk7XG52YXIgc2NhdHRlckF0dHJzID0gX2RlcmVxXygnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJyk7XG52YXIgcGxvdEF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgZGFzaCA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZy9hdHRyaWJ1dGVzJykuZGFzaDtcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxudmFyIHNjYXR0ZXJNYXJrZXJBdHRycyA9IHNjYXR0ZXJBdHRycy5tYXJrZXI7XG52YXIgc2NhdHRlckxpbmVBdHRycyA9IHNjYXR0ZXJBdHRycy5saW5lO1xudmFyIHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMgPSBzY2F0dGVyTWFya2VyQXR0cnMubGluZTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYzoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc3VtOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogMCxcbiAgICAgICAgbWluOiAwLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG1vZGU6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJBdHRycy5tb2RlLCB7ZGZsdDogJ21hcmtlcnMnfSksXG4gICAgdGV4dDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLnRleHQsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgaG92ZXJ0ZXh0OiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyQXR0cnMuaG92ZXJ0ZXh0LCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIGxpbmU6IHtcbiAgICAgICAgY29sb3I6IHNjYXR0ZXJMaW5lQXR0cnMuY29sb3IsXG4gICAgICAgIHdpZHRoOiBzY2F0dGVyTGluZUF0dHJzLndpZHRoLFxuICAgICAgICBkYXNoOiBkYXNoLFxuICAgICAgICBzaGFwZTogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckxpbmVBdHRycy5zaGFwZSxcbiAgICAgICAgICAgIHt2YWx1ZXM6IFsnbGluZWFyJywgJ3NwbGluZSddfSksXG4gICAgICAgIHNtb290aGluZzogc2NhdHRlckxpbmVBdHRycy5zbW9vdGhpbmcsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuICAgIGNvbm5lY3RnYXBzOiBzY2F0dGVyQXR0cnMuY29ubmVjdGdhcHMsXG4gICAgY2xpcG9uYXhpczogc2NhdHRlckF0dHJzLmNsaXBvbmF4aXMsXG4gICAgZmlsbDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckF0dHJzLmZpbGwsIHtcbiAgICAgICAgdmFsdWVzOiBbJ25vbmUnLCAndG9zZWxmJywgJ3RvbmV4dCddLFxuICAgICAgICBkZmx0OiAnbm9uZScsXG4gICAgICAgIFxuICAgIH0pLFxuICAgIGZpbGxjb2xvcjogc2NhdHRlckF0dHJzLmZpbGxjb2xvcixcbiAgICBtYXJrZXI6IGV4dGVuZEZsYXQoe1xuICAgICAgICBzeW1ib2w6IHNjYXR0ZXJNYXJrZXJBdHRycy5zeW1ib2wsXG4gICAgICAgIG9wYWNpdHk6IHNjYXR0ZXJNYXJrZXJBdHRycy5vcGFjaXR5LFxuICAgICAgICBtYXhkaXNwbGF5ZWQ6IHNjYXR0ZXJNYXJrZXJBdHRycy5tYXhkaXNwbGF5ZWQsXG4gICAgICAgIHNpemU6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplLFxuICAgICAgICBzaXplcmVmOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZXJlZixcbiAgICAgICAgc2l6ZW1pbjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVtaW4sXG4gICAgICAgIHNpemVtb2RlOiBzY2F0dGVyTWFya2VyQXR0cnMuc2l6ZW1vZGUsXG4gICAgICAgIGxpbmU6IGV4dGVuZEZsYXQoe1xuICAgICAgICAgICAgd2lkdGg6IHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMud2lkdGgsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgICAgIH0sXG4gICAgICAgICAgICBjb2xvclNjYWxlQXR0cnMoJ21hcmtlci5saW5lJylcbiAgICAgICAgKSxcbiAgICAgICAgZ3JhZGllbnQ6IHNjYXR0ZXJNYXJrZXJBdHRycy5ncmFkaWVudCxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgICAgIGNvbG9yU2NhbGVBdHRycygnbWFya2VyJylcbiAgICApLFxuXG4gICAgdGV4dGZvbnQ6IHNjYXR0ZXJBdHRycy50ZXh0Zm9udCxcbiAgICB0ZXh0cG9zaXRpb246IHNjYXR0ZXJBdHRycy50ZXh0cG9zaXRpb24sXG5cbiAgICBzZWxlY3RlZDogc2NhdHRlckF0dHJzLnNlbGVjdGVkLFxuICAgIHVuc2VsZWN0ZWQ6IHNjYXR0ZXJBdHRycy51bnNlbGVjdGVkLFxuXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBwbG90QXR0cnMuaG92ZXJpbmZvLCB7XG4gICAgICAgIGZsYWdzOiBbJ2EnLCAnYicsICdjJywgJ3RleHQnLCAnbmFtZSddXG4gICAgfSksXG4gICAgaG92ZXJvbjogc2NhdHRlckF0dHJzLmhvdmVyb24sXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKCksXG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzXCI6NjAwLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nL2F0dHJpYnV0ZXNcIjo2MTMsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90cy9hdHRyaWJ1dGVzXCI6NzY0LFwiLi4vc2NhdHRlci9hdHRyaWJ1dGVzXCI6MTExMn1dLDExOTI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBpc051bWVyaWMgPSBfZGVyZXFfKCdmYXN0LWlzbnVtZXJpYycpO1xuXG52YXIgY2FsY0NvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NvbG9yc2NhbGVfY2FsYycpO1xudmFyIGFycmF5c1RvQ2FsY2RhdGEgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2FycmF5c190b19jYWxjZGF0YScpO1xudmFyIGNhbGNTZWxlY3Rpb24gPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NhbGNfc2VsZWN0aW9uJyk7XG52YXIgY2FsY01hcmtlclNpemUgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NhbGMnKS5jYWxjTWFya2VyU2l6ZTtcblxudmFyIGRhdGFBcnJheXMgPSBbJ2EnLCAnYicsICdjJ107XG52YXIgYXJyYXlzVG9GaWxsID0ge2E6IFsnYicsICdjJ10sIGI6IFsnYScsICdjJ10sIGM6IFsnYScsICdiJ119O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIHRlcm5hcnkgPSBnZC5fZnVsbExheW91dFt0cmFjZS5zdWJwbG90XTtcbiAgICB2YXIgZGlzcGxheVN1bSA9IHRlcm5hcnkuc3VtO1xuICAgIHZhciBub3JtU3VtID0gdHJhY2Uuc3VtIHx8IGRpc3BsYXlTdW07XG4gICAgdmFyIGFycmF5cyA9IHthOiB0cmFjZS5hLCBiOiB0cmFjZS5iLCBjOiB0cmFjZS5jfTtcblxuICAgIHZhciBpLCBqLCBkYXRhQXJyYXksIG5ld0FycmF5LCBmaWxsQXJyYXkxLCBmaWxsQXJyYXkyO1xuXG4gICAgLy8gZmlsbCBpbiBvbmUgbWlzc2luZyBjb21wb25lbnRcbiAgICBmb3IoaSA9IDA7IGkgPCBkYXRhQXJyYXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGRhdGFBcnJheSA9IGRhdGFBcnJheXNbaV07XG4gICAgICAgIGlmKGFycmF5c1tkYXRhQXJyYXldKSBjb250aW51ZTtcblxuICAgICAgICBmaWxsQXJyYXkxID0gYXJyYXlzW2FycmF5c1RvRmlsbFtkYXRhQXJyYXldWzBdXTtcbiAgICAgICAgZmlsbEFycmF5MiA9IGFycmF5c1thcnJheXNUb0ZpbGxbZGF0YUFycmF5XVsxXV07XG4gICAgICAgIG5ld0FycmF5ID0gbmV3IEFycmF5KGZpbGxBcnJheTEubGVuZ3RoKTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgZmlsbEFycmF5MS5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgbmV3QXJyYXlbal0gPSBub3JtU3VtIC0gZmlsbEFycmF5MVtqXSAtIGZpbGxBcnJheTJbal07XG4gICAgICAgIH1cbiAgICAgICAgYXJyYXlzW2RhdGFBcnJheV0gPSBuZXdBcnJheTtcbiAgICB9XG5cbiAgICAvLyBtYWtlIHRoZSBjYWxjZGF0YSBhcnJheVxuICAgIHZhciBzZXJpZXNsZW4gPSB0cmFjZS5fbGVuZ3RoO1xuICAgIHZhciBjZCA9IG5ldyBBcnJheShzZXJpZXNsZW4pO1xuICAgIHZhciBhLCBiLCBjLCBub3JtLCB4LCB5O1xuICAgIGZvcihpID0gMDsgaSA8IHNlcmllc2xlbjsgaSsrKSB7XG4gICAgICAgIGEgPSBhcnJheXMuYVtpXTtcbiAgICAgICAgYiA9IGFycmF5cy5iW2ldO1xuICAgICAgICBjID0gYXJyYXlzLmNbaV07XG4gICAgICAgIGlmKGlzTnVtZXJpYyhhKSAmJiBpc051bWVyaWMoYikgJiYgaXNOdW1lcmljKGMpKSB7XG4gICAgICAgICAgICBhID0gK2E7XG4gICAgICAgICAgICBiID0gK2I7XG4gICAgICAgICAgICBjID0gK2M7XG4gICAgICAgICAgICBub3JtID0gZGlzcGxheVN1bSAvIChhICsgYiArIGMpO1xuICAgICAgICAgICAgaWYobm9ybSAhPT0gMSkge1xuICAgICAgICAgICAgICAgIGEgKj0gbm9ybTtcbiAgICAgICAgICAgICAgICBiICo9IG5vcm07XG4gICAgICAgICAgICAgICAgYyAqPSBub3JtO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gbWFwIGEsIGIsIGMgb250byB4IGFuZCB5IHdoZXJlIHRoZSBmdWxsIHNjYWxlIG9mIHlcbiAgICAgICAgICAgIC8vIGlzIFswLCBzdW1dLCBhbmQgeCBpcyBbLXN1bSwgc3VtXVxuICAgICAgICAgICAgLy8gVE9ETzogdGhpcyBtYWtlcyBgYWAgYWx3YXlzIHRoZSB0b3AsIGBiYCB0aGUgYm90dG9tIGxlZnQsXG4gICAgICAgICAgICAvLyBhbmQgYGNgIHRoZSBib3R0b20gcmlnaHQuIERvIHdlIHdhbnQgb3B0aW9ucyB0byByZWFycmFuZ2VcbiAgICAgICAgICAgIC8vIHRoZXNlP1xuICAgICAgICAgICAgeSA9IGE7XG4gICAgICAgICAgICB4ID0gYyAtIGI7XG4gICAgICAgICAgICBjZFtpXSA9IHt4OiB4LCB5OiB5LCBhOiBhLCBiOiBiLCBjOiBjfTtcbiAgICAgICAgfSBlbHNlIGNkW2ldID0ge3g6IGZhbHNlLCB5OiBmYWxzZX07XG4gICAgfVxuXG4gICAgY2FsY01hcmtlclNpemUodHJhY2UsIHNlcmllc2xlbik7XG4gICAgY2FsY0NvbG9yc2NhbGUoZ2QsIHRyYWNlKTtcbiAgICBhcnJheXNUb0NhbGNkYXRhKGNkLCB0cmFjZSk7XG4gICAgY2FsY1NlbGVjdGlvbihjZCwgdHJhY2UpO1xuXG4gICAgcmV0dXJuIGNkO1xufTtcblxufSx7XCIuLi9zY2F0dGVyL2FycmF5c190b19jYWxjZGF0YVwiOjExMTEsXCIuLi9zY2F0dGVyL2NhbGNcIjoxMTEzLFwiLi4vc2NhdHRlci9jYWxjX3NlbGVjdGlvblwiOjExMTQsXCIuLi9zY2F0dGVyL2NvbG9yc2NhbGVfY2FsY1wiOjExMTUsXCJmYXN0LWlzbnVtZXJpY1wiOjIyNX1dLDExOTM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIGNvbnN0YW50cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY29uc3RhbnRzJyk7XG52YXIgc3ViVHlwZXMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3N1YnR5cGVzJyk7XG52YXIgaGFuZGxlTWFya2VyRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbGluZV9kZWZhdWx0cycpO1xudmFyIGhhbmRsZUxpbmVTaGFwZURlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9saW5lX3NoYXBlX2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlVGV4dERlZmF1bHRzID0gX2RlcmVxXygnLi4vc2NhdHRlci90ZXh0X2RlZmF1bHRzJyk7XG52YXIgaGFuZGxlRmlsbENvbG9yRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2ZpbGxjb2xvcl9kZWZhdWx0cycpO1xuXG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBhID0gY29lcmNlKCdhJyk7XG4gICAgdmFyIGIgPSBjb2VyY2UoJ2InKTtcbiAgICB2YXIgYyA9IGNvZXJjZSgnYycpO1xuICAgIHZhciBsZW47XG5cbiAgICAvLyBhbGxvdyBhbnkgb25lIGFycmF5IHRvIGJlIG1pc3NpbmcsIGxlbiBpcyB0aGUgbWluaW11bSBsZW5ndGggb2YgdGhvc2VcbiAgICAvLyBwcmVzZW50LiBOb3RlIHRoYXQgYWZ0ZXIgY29lcmNlIGRhdGFfYXJyYXkncyBhcmUgZWl0aGVyIEFycmF5cyAod2hpY2hcbiAgICAvLyBhcmUgdHJ1dGh5IGV2ZW4gaWYgZW1wdHkpIG9yIHVuZGVmaW5lZC4gQXMgaW4gc2NhdHRlciwgYW4gZW1wdHkgYXJyYXlcbiAgICAvLyBpcyBkaWZmZXJlbnQgZnJvbSB1bmRlZmluZWQsIGJlY2F1c2UgaXQgY2FuIHNpZ25pZnkgdGhhdCB0aGlzIGRhdGEgaXNcbiAgICAvLyBub3Qga25vd24geWV0IGJ1dCBleHBlY3RlZCBpbiB0aGUgZnV0dXJlXG4gICAgaWYoYSkge1xuICAgICAgICBsZW4gPSBhLmxlbmd0aDtcbiAgICAgICAgaWYoYikge1xuICAgICAgICAgICAgbGVuID0gTWF0aC5taW4obGVuLCBiLmxlbmd0aCk7XG4gICAgICAgICAgICBpZihjKSBsZW4gPSBNYXRoLm1pbihsZW4sIGMubGVuZ3RoKTtcbiAgICAgICAgfSBlbHNlIGlmKGMpIGxlbiA9IE1hdGgubWluKGxlbiwgYy5sZW5ndGgpO1xuICAgICAgICBlbHNlIGxlbiA9IDA7XG4gICAgfSBlbHNlIGlmKGIgJiYgYykge1xuICAgICAgICBsZW4gPSBNYXRoLm1pbihiLmxlbmd0aCwgYy5sZW5ndGgpO1xuICAgIH1cblxuICAgIGlmKCFsZW4pIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IGxlbjtcblxuICAgIGNvZXJjZSgnc3VtJyk7XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGlmKHRyYWNlT3V0LmhvdmVyb24gIT09ICdmaWxscycpIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgdmFyIGRlZmF1bHRNb2RlID0gbGVuIDwgY29uc3RhbnRzLlBUU19MSU5FU09OTFkgPyAnbGluZXMrbWFya2VycycgOiAnbGluZXMnO1xuICAgIGNvZXJjZSgnbW9kZScsIGRlZmF1bHRNb2RlKTtcblxuICAgIGlmKHN1YlR5cGVzLmhhc0xpbmVzKHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVMaW5lRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpO1xuICAgICAgICBoYW5kbGVMaW5lU2hhcGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlKTtcbiAgICAgICAgY29lcmNlKCdjb25uZWN0Z2FwcycpO1xuICAgIH1cblxuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2VPdXQpKSB7XG4gICAgICAgIGhhbmRsZU1hcmtlckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCwgY29lcmNlLCB7Z3JhZGllbnQ6IHRydWV9KTtcbiAgICB9XG5cbiAgICBpZihzdWJUeXBlcy5oYXNUZXh0KHRyYWNlT3V0KSkge1xuICAgICAgICBoYW5kbGVUZXh0RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICB9XG5cbiAgICB2YXIgZGZsdEhvdmVyT24gPSBbXTtcblxuICAgIGlmKHN1YlR5cGVzLmhhc01hcmtlcnModHJhY2VPdXQpIHx8IHN1YlR5cGVzLmhhc1RleHQodHJhY2VPdXQpKSB7XG4gICAgICAgIGNvZXJjZSgnY2xpcG9uYXhpcycpO1xuICAgICAgICBjb2VyY2UoJ21hcmtlci5tYXhkaXNwbGF5ZWQnKTtcbiAgICAgICAgZGZsdEhvdmVyT24ucHVzaCgncG9pbnRzJyk7XG4gICAgfVxuXG4gICAgY29lcmNlKCdmaWxsJyk7XG4gICAgaWYodHJhY2VPdXQuZmlsbCAhPT0gJ25vbmUnKSB7XG4gICAgICAgIGhhbmRsZUZpbGxDb2xvckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGNvZXJjZSk7XG4gICAgICAgIGlmKCFzdWJUeXBlcy5oYXNMaW5lcyh0cmFjZU91dCkpIGhhbmRsZUxpbmVTaGFwZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBjb2VyY2UpO1xuICAgIH1cblxuICAgIGlmKHRyYWNlT3V0LmZpbGwgPT09ICd0b25leHQnIHx8IHRyYWNlT3V0LmZpbGwgPT09ICd0b3NlbGYnKSB7XG4gICAgICAgIGRmbHRIb3Zlck9uLnB1c2goJ2ZpbGxzJyk7XG4gICAgfVxuICAgIGNvZXJjZSgnaG92ZXJvbicsIGRmbHRIb3Zlck9uLmpvaW4oJysnKSB8fCAncG9pbnRzJyk7XG5cbiAgICBMaWIuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eSh0cmFjZU91dCwgY29lcmNlKTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vc2NhdHRlci9jb25zdGFudHNcIjoxMTE2LFwiLi4vc2NhdHRlci9maWxsY29sb3JfZGVmYXVsdHNcIjoxMTIwLFwiLi4vc2NhdHRlci9saW5lX2RlZmF1bHRzXCI6MTEyNCxcIi4uL3NjYXR0ZXIvbGluZV9zaGFwZV9kZWZhdWx0c1wiOjExMjYsXCIuLi9zY2F0dGVyL21hcmtlcl9kZWZhdWx0c1wiOjExMzAsXCIuLi9zY2F0dGVyL3N1YnR5cGVzXCI6MTEzNSxcIi4uL3NjYXR0ZXIvdGV4dF9kZWZhdWx0c1wiOjExMzYsXCIuL2F0dHJpYnV0ZXNcIjoxMTkxfV0sMTE5NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZXZlbnREYXRhKG91dCwgcHQsIHRyYWNlLCBjZCwgcG9pbnROdW1iZXIpIHtcbiAgICBpZihwdC54YSkgb3V0LnhheGlzID0gcHQueGE7XG4gICAgaWYocHQueWEpIG91dC55YXhpcyA9IHB0LnlhO1xuXG4gICAgaWYoY2RbcG9pbnROdW1iZXJdKSB7XG4gICAgICAgIHZhciBjZGkgPSBjZFtwb2ludE51bWJlcl07XG5cbiAgICAgICAgLy8gTi5CLiBUaGVzZSBhcmUgdGhlIG5vcm1hbGl6ZWQgY29vcmRpbmF0ZXMuXG4gICAgICAgIG91dC5hID0gY2RpLmE7XG4gICAgICAgIG91dC5iID0gY2RpLmI7XG4gICAgICAgIG91dC5jID0gY2RpLmM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZm9yIGZpbGwtaG92ZXIgb25seVxuICAgICAgICBvdXQuYSA9IHB0LmE7XG4gICAgICAgIG91dC5iID0gcHQuYjtcbiAgICAgICAgb3V0LmMgPSBwdC5jO1xuICAgIH1cblxuICAgIHJldHVybiBvdXQ7XG59O1xuXG59LHt9XSwxMTk1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2NhdHRlckhvdmVyID0gX2RlcmVxXygnLi4vc2NhdHRlci9ob3ZlcicpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpIHtcbiAgICB2YXIgc2NhdHRlclBvaW50RGF0YSA9IHNjYXR0ZXJIb3Zlcihwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSk7XG4gICAgaWYoIXNjYXR0ZXJQb2ludERhdGEgfHwgc2NhdHRlclBvaW50RGF0YVswXS5pbmRleCA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgIHZhciBuZXdQb2ludERhdGEgPSBzY2F0dGVyUG9pbnREYXRhWzBdO1xuXG4gICAgLy8gaWYgaG92ZXJpbmcgb24gYSBmaWxsLCB3ZSBkb24ndCBzaG93IGFueSBwb2ludCBkYXRhIHNvIHRoZSBsYWJlbCBpc1xuICAgIC8vIHVuY2hhbmdlZCBmcm9tIHdoYXQgc2NhdHRlciBnaXZlcyB1cyAtIGV4Y2VwdCB0aGF0IGl0IG5lZWRzIHRvXG4gICAgLy8gYmUgY29uc3RyYWluZWQgdG8gdGhlIHRyaWFuZ2x1bGFyIHBsb3QgYXJlYSwgbm90IGp1c3QgdGhlIHJlY3Rhbmd1bGFyXG4gICAgLy8gYXJlYSBkZWZpbmVkIGJ5IHRoZSBzeW50aGV0aWMgeCBhbmQgeSBheGVzXG4gICAgLy8gVE9ETzogaW4gc29tZSBjYXNlcyB0aGUgdmVydGljYWwgbWlkZGxlIG9mIHRoZSBzaGFwZSBpcyBub3Qgd2l0aGluXG4gICAgLy8gdGhlIHRyaWFuZ3VsYXIgdmlld3BvcnQgYXQgYWxsLCBzbyB0aGUgbGFiZWwgY2FuIGJlY29tZSBkaXNjb25uZWN0ZWRcbiAgICAvLyBmcm9tIHRoZSBzaGFwZSBlbnRpcmVseS4gQnV0IGNhbGN1bGF0aW5nIHdoYXQgcG9ydGlvbiBvZiB0aGUgc2hhcGVcbiAgICAvLyBpcyBhY3R1YWxseSB2aXNpYmxlLCBhcyBjb25zdHJhaW5lZCBieSB0aGUgZGlhZ29uYWwgYXhpcyBsaW5lcywgaXMgbm90XG4gICAgLy8gc28gZWFzeSBhbmQgYW55d2F5IHdlIGxvc3QgdGhlIGluZm9ybWF0aW9uIHdlIHdvdWxkIGhhdmUgbmVlZGVkIHRvIGRvXG4gICAgLy8gdGhpcyBpbnNpZGUgc2NhdHRlckhvdmVyLlxuICAgIGlmKG5ld1BvaW50RGF0YS5pbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhciB5RnJhY1VwID0gMSAtIChuZXdQb2ludERhdGEueTAgLyBwb2ludERhdGEueWEuX2xlbmd0aCk7XG4gICAgICAgIHZhciB4TGVuID0gcG9pbnREYXRhLnhhLl9sZW5ndGg7XG4gICAgICAgIHZhciB4TWluID0geExlbiAqIHlGcmFjVXAgLyAyO1xuICAgICAgICB2YXIgeE1heCA9IHhMZW4gLSB4TWluO1xuICAgICAgICBuZXdQb2ludERhdGEueDAgPSBNYXRoLm1heChNYXRoLm1pbihuZXdQb2ludERhdGEueDAsIHhNYXgpLCB4TWluKTtcbiAgICAgICAgbmV3UG9pbnREYXRhLngxID0gTWF0aC5tYXgoTWF0aC5taW4obmV3UG9pbnREYXRhLngxLCB4TWF4KSwgeE1pbik7XG4gICAgICAgIHJldHVybiBzY2F0dGVyUG9pbnREYXRhO1xuICAgIH1cblxuICAgIHZhciBjZGkgPSBuZXdQb2ludERhdGEuY2RbbmV3UG9pbnREYXRhLmluZGV4XTtcblxuICAgIG5ld1BvaW50RGF0YS5hID0gY2RpLmE7XG4gICAgbmV3UG9pbnREYXRhLmIgPSBjZGkuYjtcbiAgICBuZXdQb2ludERhdGEuYyA9IGNkaS5jO1xuXG4gICAgbmV3UG9pbnREYXRhLnhMYWJlbFZhbCA9IHVuZGVmaW5lZDtcbiAgICBuZXdQb2ludERhdGEueUxhYmVsVmFsID0gdW5kZWZpbmVkO1xuXG4gICAgdmFyIHRlcm5hcnkgPSBuZXdQb2ludERhdGEuc3VicGxvdDtcbiAgICBuZXdQb2ludERhdGEuYUxhYmVsID0gQXhlcy50aWNrVGV4dCh0ZXJuYXJ5LmFheGlzLCBjZGkuYSwgJ2hvdmVyJykudGV4dDtcbiAgICBuZXdQb2ludERhdGEuYkxhYmVsID0gQXhlcy50aWNrVGV4dCh0ZXJuYXJ5LmJheGlzLCBjZGkuYiwgJ2hvdmVyJykudGV4dDtcbiAgICBuZXdQb2ludERhdGEuY0xhYmVsID0gQXhlcy50aWNrVGV4dCh0ZXJuYXJ5LmNheGlzLCBjZGkuYywgJ2hvdmVyJykudGV4dDtcblxuICAgIHZhciB0cmFjZSA9IG5ld1BvaW50RGF0YS50cmFjZTtcbiAgICB2YXIgaG92ZXJpbmZvID0gY2RpLmhpIHx8IHRyYWNlLmhvdmVyaW5mbztcbiAgICB2YXIgdGV4dCA9IFtdO1xuICAgIGZ1bmN0aW9uIHRleHRQYXJ0KGF4LCB2YWwpIHtcbiAgICAgICAgdGV4dC5wdXNoKGF4Ll9ob3ZlcnRpdGxlICsgJzogJyArIHZhbCk7XG4gICAgfVxuICAgIGlmKCF0cmFjZS5ob3ZlcnRlbXBsYXRlKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGhvdmVyaW5mby5zcGxpdCgnKycpO1xuICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCdhbGwnKSAhPT0gLTEpIHBhcnRzID0gWydhJywgJ2InLCAnYyddO1xuICAgICAgICBpZihwYXJ0cy5pbmRleE9mKCdhJykgIT09IC0xKSB0ZXh0UGFydCh0ZXJuYXJ5LmFheGlzLCBuZXdQb2ludERhdGEuYUxhYmVsKTtcbiAgICAgICAgaWYocGFydHMuaW5kZXhPZignYicpICE9PSAtMSkgdGV4dFBhcnQodGVybmFyeS5iYXhpcywgbmV3UG9pbnREYXRhLmJMYWJlbCk7XG4gICAgICAgIGlmKHBhcnRzLmluZGV4T2YoJ2MnKSAhPT0gLTEpIHRleHRQYXJ0KHRlcm5hcnkuY2F4aXMsIG5ld1BvaW50RGF0YS5jTGFiZWwpO1xuICAgIH1cbiAgICBuZXdQb2ludERhdGEuZXh0cmFUZXh0ID0gdGV4dC5qb2luKCc8YnI+Jyk7XG4gICAgbmV3UG9pbnREYXRhLmhvdmVydGVtcGxhdGUgPSB0cmFjZS5ob3ZlcnRlbXBsYXRlO1xuICAgIHJldHVybiBzY2F0dGVyUG9pbnREYXRhO1xufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL3NjYXR0ZXIvaG92ZXJcIjoxMTIyfV0sMTE5NjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgY29sb3JiYXI6IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbWFya2VyX2NvbG9yYmFyJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JyksXG4gICAgc3R5bGU6IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3R5bGUnKS5zdHlsZSxcbiAgICBzdHlsZU9uU2VsZWN0OiBfZGVyZXFfKCcuLi9zY2F0dGVyL3N0eWxlJykuc3R5bGVPblNlbGVjdCxcbiAgICBob3ZlclBvaW50czogX2RlcmVxXygnLi9ob3ZlcicpLFxuICAgIHNlbGVjdFBvaW50czogX2RlcmVxXygnLi4vc2NhdHRlci9zZWxlY3QnKSxcbiAgICBldmVudERhdGE6IF9kZXJlcV8oJy4vZXZlbnRfZGF0YScpLFxuXG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnc2NhdHRlcnRlcm5hcnknLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy90ZXJuYXJ5JyksXG4gICAgY2F0ZWdvcmllczogWyd0ZXJuYXJ5JywgJ3N5bWJvbHMnLCAnc2hvd0xlZ2VuZCcsICdzY2F0dGVyLWxpa2UnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgICAgICBcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL3Rlcm5hcnlcIjo4NDMsXCIuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhclwiOjExMjksXCIuLi9zY2F0dGVyL3NlbGVjdFwiOjExMzIsXCIuLi9zY2F0dGVyL3N0eWxlXCI6MTEzNCxcIi4vYXR0cmlidXRlc1wiOjExOTEsXCIuL2NhbGNcIjoxMTkyLFwiLi9kZWZhdWx0c1wiOjExOTMsXCIuL2V2ZW50X2RhdGFcIjoxMTk0LFwiLi9ob3ZlclwiOjExOTUsXCIuL3Bsb3RcIjoxMTk3fV0sMTE5NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNjYXR0ZXJQbG90ID0gX2RlcmVxXygnLi4vc2NhdHRlci9wbG90Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgdGVybmFyeSwgbW9kdWxlQ2FsY0RhdGEpIHtcbiAgICB2YXIgcGxvdENvbnRhaW5lciA9IHRlcm5hcnkucGxvdENvbnRhaW5lcjtcblxuICAgIC8vIHJlbW92ZSBhbGwgbm9kZXMgaW5zaWRlIHRoZSBzY2F0dGVyIGxheWVyXG4gICAgcGxvdENvbnRhaW5lci5zZWxlY3QoJy5zY2F0dGVybGF5ZXInKS5zZWxlY3RBbGwoJyonKS5yZW1vdmUoKTtcblxuICAgIC8vIG1pbWljIGNhcnRlc2lhbiBwbG90aW5mb1xuICAgIHZhciBwbG90aW5mbyA9IHtcbiAgICAgICAgeGF4aXM6IHRlcm5hcnkueGF4aXMsXG4gICAgICAgIHlheGlzOiB0ZXJuYXJ5LnlheGlzLFxuICAgICAgICBwbG90OiBwbG90Q29udGFpbmVyLFxuICAgICAgICBsYXllckNsaXBJZDogdGVybmFyeS5faGFzQ2xpcE9uQXhpc0ZhbHNlID8gdGVybmFyeS5jbGlwSWRSZWxhdGl2ZSA6IG51bGxcbiAgICB9O1xuXG4gICAgdmFyIHNjYXR0ZXJMYXllciA9IHRlcm5hcnkubGF5ZXJzLmZyb250cGxvdC5zZWxlY3QoJ2cuc2NhdHRlcmxheWVyJyk7XG5cbiAgICBzY2F0dGVyUGxvdChnZCwgcGxvdGluZm8sIG1vZHVsZUNhbGNEYXRhLCBzY2F0dGVyTGF5ZXIpO1xufTtcblxufSx7XCIuLi9zY2F0dGVyL3Bsb3RcIjoxMTMxfV0sMTE5ODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBzY2F0dGVyQXR0cnMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2F0dHJpYnV0ZXMnKTtcbnZhciBjb2xvclNjYWxlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlcycpO1xudmFyIGhvdmVydGVtcGxhdGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzJyk7XG52YXIgc2NhdHRlckdsQXR0cnMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyZ2wvYXR0cmlidXRlcycpO1xudmFyIGNhcnRlc2lhbklkUmVnZXggPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vY29uc3RhbnRzJykuaWRSZWdleDtcbnZhciB0ZW1wbGF0ZWRBcnJheSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RfYXBpL3Bsb3RfdGVtcGxhdGUnKS50ZW1wbGF0ZWRBcnJheTtcbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbnZhciBzY2F0dGVyTWFya2VyQXR0cnMgPSBzY2F0dGVyQXR0cnMubWFya2VyO1xudmFyIHNjYXR0ZXJNYXJrZXJMaW5lQXR0cnMgPSBzY2F0dGVyTWFya2VyQXR0cnMubGluZTtcblxudmFyIG1hcmtlckxpbmVBdHRycyA9IGV4dGVuZEZsYXQoY29sb3JTY2FsZUF0dHJzKCdtYXJrZXIubGluZScsIHtlZGl0VHlwZU92ZXJyaWRlOiAnY2FsYyd9KSwge1xuICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBzY2F0dGVyTWFya2VyTGluZUF0dHJzLndpZHRoLCB7ZWRpdFR5cGU6ICdjYWxjJ30pLFxuICAgIGVkaXRUeXBlOiAnY2FsYydcbn0pO1xuXG52YXIgbWFya2VyQXR0cnMgPSBleHRlbmRGbGF0KGNvbG9yU2NhbGVBdHRycygnbWFya2VyJyksIHtcbiAgICBzeW1ib2w6IHNjYXR0ZXJNYXJrZXJBdHRycy5zeW1ib2wsXG4gICAgc2l6ZTogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlck1hcmtlckF0dHJzLnNpemUsIHtlZGl0VHlwZTogJ21hcmtlclNpemUnfSksXG4gICAgc2l6ZXJlZjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVyZWYsXG4gICAgc2l6ZW1pbjogc2NhdHRlck1hcmtlckF0dHJzLnNpemVtaW4sXG4gICAgc2l6ZW1vZGU6IHNjYXR0ZXJNYXJrZXJBdHRycy5zaXplbW9kZSxcbiAgICBvcGFjaXR5OiBzY2F0dGVyTWFya2VyQXR0cnMub3BhY2l0eSxcbiAgICBjb2xvcmJhcjogc2NhdHRlck1hcmtlckF0dHJzLmNvbG9yYmFyLFxuICAgIGxpbmU6IG1hcmtlckxpbmVBdHRycyxcbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59KTtcblxubWFya2VyQXR0cnMuY29sb3IuZWRpdFR5cGUgPSBtYXJrZXJBdHRycy5jbWluLmVkaXRUeXBlID0gbWFya2VyQXR0cnMuY21heC5lZGl0VHlwZSA9ICdzdHlsZSc7XG5cbmZ1bmN0aW9uIG1ha2VBeGVzVmFsT2JqZWN0KGF4TGV0dGVyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBmcmVlTGVuZ3RoOiB0cnVlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgaXRlbXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdWJwbG90aWQnLFxuICAgICAgICAgICAgcmVnZXg6IGNhcnRlc2lhbklkUmVnZXhbYXhMZXR0ZXJdLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgICAgICB9LFxuICAgICAgICBcbiAgICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBkaW1lbnNpb25zOiB0ZW1wbGF0ZWRBcnJheSgnZGltZW5zaW9uJywge1xuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGxhYmVsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB2YWx1ZXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGF4aXM6IHtcbiAgICAgICAgICAgIHR5cGU6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICAgICAgdmFsdWVzOiBbJ2xpbmVhcicsICdsb2cnLCAnZGF0ZScsICdjYXRlZ29yeSddLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvLyBUT0RPIG1ha2UgJ3RydWUnIHRoZSBkZWZhdWx0IGluIHYyP1xuICAgICAgICAgICAgbWF0Y2hlczoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJ1xuICAgICAgICB9LFxuXG4gICAgICAgIC8vIFRPRE8gc2hvdWxkIGFkZCBhbiBhdHRyaWJ1dGUgdG8gcGluIGRvd24geCBvbmx5IHZhcnMgYW5kIHkgb25seSB2YXJzXG4gICAgICAgIC8vIGxpa2UgaHR0cHM6Ly9zZWFib3JuLnB5ZGF0YS5vcmcvZ2VuZXJhdGVkL3NlYWJvcm4ucGFpcnBsb3QuaHRtbFxuICAgICAgICAvLyB4X3ZhcnMgYW5kIHlfdmFyc1xuXG4gICAgICAgIC8vIG1heWJlIG1vcmUgYXhpcyBkZWZhdWx0aW5nIG9wdGlvbiBlLmcuIGBzaG93Z3JpZDogZmFsc2VgXG5cbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJ1xuICAgIH0pLFxuXG4gICAgLy8gbW9kZToge30sIChvbmx5ICdtYXJrZXJzJyBmb3Igbm93KVxuXG4gICAgdGV4dDogZXh0ZW5kRmxhdCh7fSwgc2NhdHRlckdsQXR0cnMudGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBob3ZlcnRleHQ6IGV4dGVuZEZsYXQoe30sIHNjYXR0ZXJHbEF0dHJzLmhvdmVydGV4dCwge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycygpLFxuXG4gICAgbWFya2VyOiBtYXJrZXJBdHRycyxcblxuICAgIHhheGVzOiBtYWtlQXhlc1ZhbE9iamVjdCgneCcpLFxuICAgIHlheGVzOiBtYWtlQXhlc1ZhbE9iamVjdCgneScpLFxuXG4gICAgZGlhZ29uYWw6IHtcbiAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIC8vIHR5cGU6ICdzY2F0dGVyZ2wnIHwgJ2hpc3RvZ3JhbScgfCAnYm94JyB8ICd2aW9saW4nXG4gICAgICAgIC8vIC4uLlxuICAgICAgICAvLyBtb3JlIG9wdGlvbnNcblxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcblxuICAgIHNob3d1cHBlcmhhbGY6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzaG93bG93ZXJoYWxmOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBzZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHNjYXR0ZXJHbEF0dHJzLnNlbGVjdGVkLm1hcmtlcixcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgdW5zZWxlY3RlZDoge1xuICAgICAgICBtYXJrZXI6IHNjYXR0ZXJHbEF0dHJzLnVuc2VsZWN0ZWQubWFya2VyLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcblxuICAgIG9wYWNpdHk6IHNjYXR0ZXJHbEF0dHJzLm9wYWNpdHlcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXNcIjo2MDAsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9wbG90X3RlbXBsYXRlXCI6NzU3LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2NvbnN0YW50c1wiOjc3MyxcIi4uL3NjYXR0ZXIvYXR0cmlidXRlc1wiOjExMTIsXCIuLi9zY2F0dGVyZ2wvYXR0cmlidXRlc1wiOjExNjB9XSwxMTk5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNyZWF0ZUxpbmUgPSBfZGVyZXFfKCdyZWdsLWxpbmUyZCcpO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIHByZXBhcmVSZWdsID0gX2RlcmVxXygnLi4vLi4vbGliL3ByZXBhcmVfcmVnbCcpO1xudmFyIGdldE1vZHVsZUNhbGNEYXRhID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRNb2R1bGVDYWxjRGF0YTtcbnZhciBDYXJ0ZXNpYW4gPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKTtcbnZhciBnZXRGcm9tSWQgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHMnKS5nZXRGcm9tSWQ7XG52YXIgc2hvdWxkU2hvd1plcm9MaW5lID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKS5zaG91bGRTaG93WmVyb0xpbmU7XG5cbnZhciBTUExPTSA9ICdzcGxvbSc7XG5cbmZ1bmN0aW9uIHBsb3QoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBfbW9kdWxlID0gUmVnaXN0cnkuZ2V0TW9kdWxlKFNQTE9NKTtcbiAgICB2YXIgc3Bsb21DYWxjRGF0YSA9IGdldE1vZHVsZUNhbGNEYXRhKGdkLmNhbGNkYXRhLCBfbW9kdWxlKVswXTtcblxuICAgIHZhciBzdWNjZXNzID0gcHJlcGFyZVJlZ2woZ2QsIFsnQU5HTEVfaW5zdGFuY2VkX2FycmF5cycsICdPRVNfZWxlbWVudF9pbmRleF91aW50J10pO1xuICAgIGlmKCFzdWNjZXNzKSByZXR1cm47XG5cbiAgICBpZihmdWxsTGF5b3V0Ll9oYXNPbmx5TGFyZ2VTcGxvbXMpIHtcbiAgICAgICAgdXBkYXRlR3JpZChnZCk7XG4gICAgfVxuXG4gICAgX21vZHVsZS5wbG90KGdkLCB7fSwgc3Bsb21DYWxjRGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRyYWcoZ2QpIHtcbiAgICB2YXIgY2QgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgaWYoZnVsbExheW91dC5faGFzT25seUxhcmdlU3Bsb21zKSB7XG4gICAgICAgIHVwZGF0ZUdyaWQoZ2QpO1xuICAgIH1cblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBjZC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY2QwID0gY2RbaV1bMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcbiAgICAgICAgdmFyIHNjZW5lID0gZnVsbExheW91dC5fc3Bsb21TY2VuZXNbdHJhY2UudWlkXTtcblxuICAgICAgICBpZih0cmFjZS50eXBlID09PSAnc3Bsb20nICYmIHNjZW5lICYmIHNjZW5lLm1hdHJpeCkge1xuICAgICAgICAgICAgZHJhZ09uZShnZCwgdHJhY2UsIHNjZW5lKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZHJhZ09uZShnZCwgdHJhY2UsIHNjZW5lKSB7XG4gICAgdmFyIHZpc2libGVMZW5ndGggPSBzY2VuZS5tYXRyaXhPcHRpb25zLmRhdGEubGVuZ3RoO1xuICAgIHZhciB2aXNpYmxlRGltcyA9IHRyYWNlLl92aXNpYmxlRGltcztcbiAgICB2YXIgcmFuZ2VzID0gc2NlbmUudmlld09wdHMucmFuZ2VzID0gbmV3IEFycmF5KHZpc2libGVMZW5ndGgpO1xuXG4gICAgZm9yKHZhciBrID0gMDsgayA8IHZpc2libGVEaW1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBpID0gdmlzaWJsZURpbXNba107XG4gICAgICAgIHZhciBybmcgPSByYW5nZXNba10gPSBuZXcgQXJyYXkoNCk7XG5cbiAgICAgICAgdmFyIHhhID0gZ2V0RnJvbUlkKGdkLCB0cmFjZS5fZGlhZ1tpXVswXSk7XG4gICAgICAgIGlmKHhhKSB7XG4gICAgICAgICAgICBybmdbMF0gPSB4YS5yMmwoeGEucmFuZ2VbMF0pO1xuICAgICAgICAgICAgcm5nWzJdID0geGEucjJsKHhhLnJhbmdlWzFdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB5YSA9IGdldEZyb21JZChnZCwgdHJhY2UuX2RpYWdbaV1bMV0pO1xuICAgICAgICBpZih5YSkge1xuICAgICAgICAgICAgcm5nWzFdID0geWEucjJsKHlhLnJhbmdlWzBdKTtcbiAgICAgICAgICAgIHJuZ1szXSA9IHlhLnIybCh5YS5yYW5nZVsxXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihzY2VuZS5zZWxlY3RCYXRjaC5sZW5ndGggfHwgc2NlbmUudW5zZWxlY3RCYXRjaC5sZW5ndGgpIHtcbiAgICAgICAgc2NlbmUubWF0cml4LnVwZGF0ZSh7cmFuZ2VzOiByYW5nZXN9LCB7cmFuZ2VzOiByYW5nZXN9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzY2VuZS5tYXRyaXgudXBkYXRlKHtyYW5nZXM6IHJhbmdlc30pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlR3JpZChnZCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIHJlZ2wgPSBmdWxsTGF5b3V0Ll9nbGNhbnZhcy5kYXRhKClbMF0ucmVnbDtcbiAgICB2YXIgc3Bsb21HcmlkID0gZnVsbExheW91dC5fc3Bsb21HcmlkO1xuXG4gICAgaWYoIXNwbG9tR3JpZCkge1xuICAgICAgICBzcGxvbUdyaWQgPSBmdWxsTGF5b3V0Ll9zcGxvbUdyaWQgPSBjcmVhdGVMaW5lKHJlZ2wpO1xuICAgIH1cbiAgICBzcGxvbUdyaWQudXBkYXRlKG1ha2VHcmlkRGF0YShnZCkpO1xufVxuXG5mdW5jdGlvbiBtYWtlR3JpZERhdGEoZ2QpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBncyA9IGZ1bGxMYXlvdXQuX3NpemU7XG4gICAgdmFyIGZ1bGxWaWV3ID0gWzAsIDAsIGZ1bGxMYXlvdXQud2lkdGgsIGZ1bGxMYXlvdXQuaGVpZ2h0XTtcbiAgICB2YXIgbG9va3VwID0ge307XG4gICAgdmFyIGs7XG5cbiAgICBmdW5jdGlvbiBwdXNoKHByZWZpeCwgYXgsIHgwLCB4MSwgeTAsIHkxKSB7XG4gICAgICAgIHZhciBsY29sb3IgPSBheFtwcmVmaXggKyAnY29sb3InXTtcbiAgICAgICAgdmFyIGx3aWR0aCA9IGF4W3ByZWZpeCArICd3aWR0aCddO1xuICAgICAgICB2YXIga2V5ID0gU3RyaW5nKGxjb2xvciArIGx3aWR0aCk7XG5cbiAgICAgICAgaWYoa2V5IGluIGxvb2t1cCkge1xuICAgICAgICAgICAgbG9va3VwW2tleV0uZGF0YS5wdXNoKE5hTiwgTmFOLCB4MCwgeDEsIHkwLCB5MSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb29rdXBba2V5XSA9IHtcbiAgICAgICAgICAgICAgICBkYXRhOiBbeDAsIHgxLCB5MCwgeTFdLFxuICAgICAgICAgICAgICAgIGpvaW46ICdyZWN0JyxcbiAgICAgICAgICAgICAgICB0aGlja25lc3M6IGx3aWR0aCxcbiAgICAgICAgICAgICAgICBjb2xvcjogbGNvbG9yLFxuICAgICAgICAgICAgICAgIHZpZXdwb3J0OiBmdWxsVmlldyxcbiAgICAgICAgICAgICAgICByYW5nZTogZnVsbFZpZXcsXG4gICAgICAgICAgICAgICAgb3ZlcmxheTogZmFsc2VcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoayBpbiBmdWxsTGF5b3V0Ll9zcGxvbVN1YnBsb3RzKSB7XG4gICAgICAgIHZhciBzcCA9IGZ1bGxMYXlvdXQuX3Bsb3RzW2tdO1xuICAgICAgICB2YXIgeGEgPSBzcC54YXhpcztcbiAgICAgICAgdmFyIHlhID0gc3AueWF4aXM7XG4gICAgICAgIHZhciB4VmFscyA9IHhhLl92YWxzO1xuICAgICAgICB2YXIgeVZhbHMgPSB5YS5fdmFscztcbiAgICAgICAgLy8geWEubDJwIGFzc3VtZXMgdG9wLXRvLWJvdHRvbSBjb29yZGluYXRlIHN5c3RlbSAoYSBsYSBTVkcpLFxuICAgICAgICAvLyB3ZSBuZWVkIHRvIGNvbXB1dGUgYm90dG9tLXRvLXRvcCBvZmZzZXRzIGFuZCBzbG9wZXM6XG4gICAgICAgIHZhciB5T2Zmc2V0ID0gZ3MuYiArIHlhLmRvbWFpblswXSAqIGdzLmg7XG4gICAgICAgIHZhciB5bSA9IC15YS5fbTtcbiAgICAgICAgdmFyIHliID0gLXltICogeWEucjJsKHlhLnJhbmdlWzBdLCB5YS5jYWxlbmRhcik7XG4gICAgICAgIHZhciB4LCB5O1xuXG4gICAgICAgIGlmKHhhLnNob3dncmlkKSB7XG4gICAgICAgICAgICBmb3IoayA9IDA7IGsgPCB4VmFscy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIHggPSB4YS5fb2Zmc2V0ICsgeGEubDJwKHhWYWxzW2tdLngpO1xuICAgICAgICAgICAgICAgIHB1c2goJ2dyaWQnLCB4YSwgeCwgeU9mZnNldCwgeCwgeU9mZnNldCArIHlhLl9sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmKHlhLnNob3dncmlkKSB7XG4gICAgICAgICAgICBmb3IoayA9IDA7IGsgPCB5VmFscy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgICAgICAgIHkgPSB5T2Zmc2V0ICsgeWIgKyB5bSAqIHlWYWxzW2tdLng7XG4gICAgICAgICAgICAgICAgcHVzaCgnZ3JpZCcsIHlhLCB4YS5fb2Zmc2V0LCB5LCB4YS5fb2Zmc2V0ICsgeGEuX2xlbmd0aCwgeSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYoc2hvdWxkU2hvd1plcm9MaW5lKGdkLCB4YSwgeWEpKSB7XG4gICAgICAgICAgICB4ID0geGEuX29mZnNldCArIHhhLmwycCgwKTtcbiAgICAgICAgICAgIHB1c2goJ3plcm9saW5lJywgeGEsIHgsIHlPZmZzZXQsIHgsIHlPZmZzZXQgKyB5YS5fbGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICBpZihzaG91bGRTaG93WmVyb0xpbmUoZ2QsIHlhLCB4YSkpIHtcbiAgICAgICAgICAgIHkgPSB5T2Zmc2V0ICsgeWIgKyAwO1xuICAgICAgICAgICAgcHVzaCgnemVyb2xpbmUnLCB5YSwgeGEuX29mZnNldCwgeSwgeGEuX29mZnNldCArIHhhLl9sZW5ndGgsIHkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGdyaWRCYXRjaGVzID0gW107XG4gICAgZm9yKGsgaW4gbG9va3VwKSB7XG4gICAgICAgIGdyaWRCYXRjaGVzLnB1c2gobG9va3VwW2tdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ3JpZEJhdGNoZXM7XG59XG5cbmZ1bmN0aW9uIGNsZWFuKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCkge1xuICAgIHZhciBsb29rdXAgPSB7fTtcbiAgICB2YXIgaTtcblxuICAgIGlmKG9sZEZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IG5ld0Z1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgbmV3VHJhY2UgPSBuZXdGdWxsRGF0YVtpXTtcbiAgICAgICAgICAgIGlmKG5ld1RyYWNlLnR5cGUgPT09ICdzcGxvbScpIHtcbiAgICAgICAgICAgICAgICBsb29rdXBbbmV3VHJhY2UudWlkXSA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgb2xkRnVsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBvbGRUcmFjZSA9IG9sZEZ1bGxEYXRhW2ldO1xuICAgICAgICAgICAgaWYoIWxvb2t1cFtvbGRUcmFjZS51aWRdKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNjZW5lID0gb2xkRnVsbExheW91dC5fc3Bsb21TY2VuZXNbb2xkVHJhY2UudWlkXTtcbiAgICAgICAgICAgICAgICBpZihzY2VuZSAmJiBzY2VuZS5kZXN0cm95KSBzY2VuZS5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgLy8gbXVzdCBmaXJzdCBzZXQgc2NlbmUgdG8gbnVsbCBpbiBvcmRlciB0byBnZXQgZ2FyYmFnZSBjb2xsZWN0ZWRcbiAgICAgICAgICAgICAgICBvbGRGdWxsTGF5b3V0Ll9zcGxvbVNjZW5lc1tvbGRUcmFjZS51aWRdID0gbnVsbDtcbiAgICAgICAgICAgICAgICBkZWxldGUgb2xkRnVsbExheW91dC5fc3Bsb21TY2VuZXNbb2xkVHJhY2UudWlkXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKE9iamVjdC5rZXlzKG9sZEZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzIHx8IHt9KS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgZGVsZXRlIG9sZEZ1bGxMYXlvdXQuX3NwbG9tU2NlbmVzO1xuICAgIH1cblxuICAgIGlmKG9sZEZ1bGxMYXlvdXQuX3NwbG9tR3JpZCAmJlxuICAgICAgICAoIW5ld0Z1bGxMYXlvdXQuX2hhc09ubHlMYXJnZVNwbG9tcyAmJiBvbGRGdWxsTGF5b3V0Ll9oYXNPbmx5TGFyZ2VTcGxvbXMpKSB7XG4gICAgICAgIC8vIG11c3QgZmlyc3Qgc2V0IHNjZW5lIHRvIG51bGwgaW4gb3JkZXIgdG8gZ2V0IGdhcmJhZ2UgY29sbGVjdGVkXG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX3NwbG9tR3JpZC5kZXN0cm95KCk7XG4gICAgICAgIG9sZEZ1bGxMYXlvdXQuX3NwbG9tR3JpZCA9IG51bGw7XG4gICAgICAgIGRlbGV0ZSBvbGRGdWxsTGF5b3V0Ll9zcGxvbUdyaWQ7XG4gICAgfVxuXG4gICAgQ2FydGVzaWFuLmNsZWFuKG5ld0Z1bGxEYXRhLCBuZXdGdWxsTGF5b3V0LCBvbGRGdWxsRGF0YSwgb2xkRnVsbExheW91dCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG5hbWU6IFNQTE9NLFxuICAgIGF0dHI6IENhcnRlc2lhbi5hdHRyLFxuICAgIGF0dHJSZWdleDogQ2FydGVzaWFuLmF0dHJSZWdleCxcbiAgICBsYXlvdXRBdHRyaWJ1dGVzOiBDYXJ0ZXNpYW4ubGF5b3V0QXR0cmlidXRlcyxcbiAgICBzdXBwbHlMYXlvdXREZWZhdWx0czogQ2FydGVzaWFuLnN1cHBseUxheW91dERlZmF1bHRzLFxuICAgIGRyYXdGcmFtZXdvcms6IENhcnRlc2lhbi5kcmF3RnJhbWV3b3JrLFxuICAgIHBsb3Q6IHBsb3QsXG4gICAgZHJhZzogZHJhZyxcbiAgICB1cGRhdGVHcmlkOiB1cGRhdGVHcmlkLFxuICAgIGNsZWFuOiBjbGVhbixcbiAgICB1cGRhdGVGeDogQ2FydGVzaWFuLnVwZGF0ZUZ4LFxuICAgIHRvU1ZHOiBDYXJ0ZXNpYW4udG9TVkdcbn07XG5cbn0se1wiLi4vLi4vbGliL3ByZXBhcmVfcmVnbFwiOjczMixcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhblwiOjc3OCxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzXCI6NzcwLFwiLi4vLi4vcGxvdHMvZ2V0X2RhdGFcIjo4MDIsXCIuLi8uLi9yZWdpc3RyeVwiOjg0NyxcInJlZ2wtbGluZTJkXCI6NDkxfV0sMTIwMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBBeGlzSURzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzJyk7XG5cbnZhciBjYWxjTWFya2VyU2l6ZSA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY2FsYycpLmNhbGNNYXJrZXJTaXplO1xudmFyIGNhbGNBeGlzRXhwYW5zaW9uID0gX2RlcmVxXygnLi4vc2NhdHRlci9jYWxjJykuY2FsY0F4aXNFeHBhbnNpb247XG52YXIgY2FsY0NvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NvbG9yc2NhbGVfY2FsYycpO1xudmFyIGNvbnZlcnRNYXJrZXJTZWxlY3Rpb24gPSBfZGVyZXFfKCcuLi9zY2F0dGVyZ2wvY29udmVydCcpLm1hcmtlclNlbGVjdGlvbjtcbnZhciBjb252ZXJ0TWFya2VyU3R5bGUgPSBfZGVyZXFfKCcuLi9zY2F0dGVyZ2wvY29udmVydCcpLm1hcmtlclN0eWxlO1xudmFyIHNjZW5lVXBkYXRlID0gX2RlcmVxXygnLi9zY2VuZV91cGRhdGUnKTtcblxudmFyIEJBRE5VTSA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9udW1lcmljYWwnKS5CQUROVU07XG52YXIgVE9PX01BTllfUE9JTlRTID0gX2RlcmVxXygnLi4vc2NhdHRlcmdsL2NvbnN0YW50cycpLlRPT19NQU5ZX1BPSU5UUztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBkaW1lbnNpb25zID0gdHJhY2UuZGltZW5zaW9ucztcbiAgICB2YXIgY29tbW9uTGVuZ3RoID0gdHJhY2UuX2xlbmd0aDtcbiAgICB2YXIgb3B0cyA9IHt9O1xuICAgIC8vICdjJyBmb3IgY2FsY3VsYXRlZCwgJ2wnIGZvciBsaW5lYXIsXG4gICAgLy8gb25seSBkaWZmZXIgaGVyZSBmb3IgbG9nIGF4ZXMsIHBhc3MgbGRhdGEgdG8gY3JlYXRlTWF0cml4IGFzICdkYXRhJ1xuICAgIHZhciBjZGF0YSA9IG9wdHMuY2RhdGEgPSBbXTtcbiAgICB2YXIgbGRhdGEgPSBvcHRzLmRhdGEgPSBbXTtcbiAgICAvLyBrZWVwIHRyYWNrIG9mIHZpc2libGUgZGltZW5zaW9uc1xuICAgIHZhciB2aXNpYmxlRGltcyA9IHRyYWNlLl92aXNpYmxlRGltcyA9IFtdO1xuICAgIHZhciBpLCBrLCBkaW0sIHhhLCB5YTtcblxuICAgIGZ1bmN0aW9uIG1ha2VDYWxjZGF0YShheCwgZGltKSB7XG4gICAgICAgIC8vIGNhbGwgbWFrZUNhbGNkYXRhIHdpdGggZmFrZSBpbnB1dFxuICAgICAgICB2YXIgY2NvbCA9IGF4Lm1ha2VDYWxjZGF0YSh7XG4gICAgICAgICAgICB2OiBkaW0udmFsdWVzLFxuICAgICAgICAgICAgdmNhbGVuZGFyOiB0cmFjZS5jYWxlbmRhclxuICAgICAgICB9LCAndicpO1xuXG4gICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBjY29sLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBjY29sW2pdID0gY2NvbFtqXSA9PT0gQkFETlVNID8gTmFOIDogY2NvbFtqXTtcbiAgICAgICAgfVxuICAgICAgICBjZGF0YS5wdXNoKGNjb2wpO1xuICAgICAgICBsZGF0YS5wdXNoKGF4LnR5cGUgPT09ICdsb2cnID8gTGliLnNpbXBsZU1hcChjY29sLCBheC5jMmwpIDogY2NvbCk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgZGltZW5zaW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBkaW0gPSBkaW1lbnNpb25zW2ldO1xuXG4gICAgICAgIGlmKGRpbS52aXNpYmxlKSB7XG4gICAgICAgICAgICB4YSA9IEF4aXNJRHMuZ2V0RnJvbUlkKGdkLCB0cmFjZS5fZGlhZ1tpXVswXSk7XG4gICAgICAgICAgICB5YSA9IEF4aXNJRHMuZ2V0RnJvbUlkKGdkLCB0cmFjZS5fZGlhZ1tpXVsxXSk7XG5cbiAgICAgICAgICAgIC8vIGlmIGNvcnJlc3BvbmRpbmcgeCAmIHkgYXhlcyBkb24ndCBoYXZlIG1hdGNoaW5nIHR5cGVzLCBza2lwIGRpbVxuICAgICAgICAgICAgaWYoeGEgJiYgeWEgJiYgeGEudHlwZSAhPT0geWEudHlwZSkge1xuICAgICAgICAgICAgICAgIExpYi5sb2coJ1NraXBwaW5nIHNwbG9tIGRpbWVuc2lvbiAnICsgaSArICcgd2l0aCBjb25mbGljdGluZyBheGlzIHR5cGVzJyk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHhhKSB7XG4gICAgICAgICAgICAgICAgbWFrZUNhbGNkYXRhKHhhLCBkaW0pO1xuICAgICAgICAgICAgICAgIGlmKHlhICYmIHlhLnR5cGUgPT09ICdjYXRlZ29yeScpIHtcbiAgICAgICAgICAgICAgICAgICAgeWEuX2NhdGVnb3JpZXMgPSB4YS5fY2F0ZWdvcmllcy5zbGljZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gc2hvdWxkIG5vdCBtYWtlIGl0IGhlcmUsIGlmIGJvdGggeGEgYW5kIHlhIHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIG1ha2VDYWxjZGF0YSh5YSwgZGltKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmlzaWJsZURpbXMucHVzaChpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNhbGNDb2xvcnNjYWxlKGdkLCB0cmFjZSk7XG4gICAgTGliLmV4dGVuZEZsYXQob3B0cywgY29udmVydE1hcmtlclN0eWxlKHRyYWNlKSk7XG5cbiAgICB2YXIgdmlzaWJsZUxlbmd0aCA9IGNkYXRhLmxlbmd0aDtcbiAgICB2YXIgaGFzVG9vTWFueVBvaW50cyA9ICh2aXNpYmxlTGVuZ3RoICogY29tbW9uTGVuZ3RoKSA+IFRPT19NQU5ZX1BPSU5UUztcblxuICAgIC8vIFJldXNlIFNWRyBzY2F0dGVyIGF4aXMgZXhwYW5zaW9uIHJvdXRpbmUuXG4gICAgLy8gRm9yIGdyYXBocyB3aXRoIHZlcnkgbGFyZ2UgbnVtYmVyIG9mIHBvaW50cyBhbmQgYXJyYXkgbWFya2VyLnNpemUsXG4gICAgLy8gdXNlIGF2ZXJhZ2UgbWFya2VyIHNpemUgaW5zdGVhZCB0byBzcGVlZCB0aGluZ3MgdXAuXG4gICAgdmFyIHBwYWQ7XG4gICAgaWYoaGFzVG9vTWFueVBvaW50cykge1xuICAgICAgICBwcGFkID0gMiAqIChvcHRzLnNpemVBdmcgfHwgTWF0aC5tYXgob3B0cy5zaXplLCAzKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcHBhZCA9IGNhbGNNYXJrZXJTaXplKHRyYWNlLCBjb21tb25MZW5ndGgpO1xuICAgIH1cblxuICAgIGZvcihrID0gMDsgayA8IHZpc2libGVEaW1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIGkgPSB2aXNpYmxlRGltc1trXTtcbiAgICAgICAgZGltID0gZGltZW5zaW9uc1tpXTtcbiAgICAgICAgeGEgPSBBeGlzSURzLmdldEZyb21JZChnZCwgdHJhY2UuX2RpYWdbaV1bMF0pIHx8IHt9O1xuICAgICAgICB5YSA9IEF4aXNJRHMuZ2V0RnJvbUlkKGdkLCB0cmFjZS5fZGlhZ1tpXVsxXSkgfHwge307XG4gICAgICAgIGNhbGNBeGlzRXhwYW5zaW9uKGdkLCB0cmFjZSwgeGEsIHlhLCBjZGF0YVtrXSwgY2RhdGFba10sIHBwYWQpO1xuICAgIH1cblxuICAgIHZhciBzY2VuZSA9IHNjZW5lVXBkYXRlKGdkLCB0cmFjZSk7XG4gICAgaWYoIXNjZW5lLm1hdHJpeCkgc2NlbmUubWF0cml4ID0gdHJ1ZTtcbiAgICBzY2VuZS5tYXRyaXhPcHRpb25zID0gb3B0cztcblxuICAgIHNjZW5lLnNlbGVjdGVkT3B0aW9ucyA9IGNvbnZlcnRNYXJrZXJTZWxlY3Rpb24odHJhY2UsIHRyYWNlLnNlbGVjdGVkKTtcbiAgICBzY2VuZS51bnNlbGVjdGVkT3B0aW9ucyA9IGNvbnZlcnRNYXJrZXJTZWxlY3Rpb24odHJhY2UsIHRyYWNlLnVuc2VsZWN0ZWQpO1xuXG4gICAgcmV0dXJuIFt7eDogZmFsc2UsIHk6IGZhbHNlLCB0OiB7fSwgdHJhY2U6IHRyYWNlfV07XG59O1xuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhpc19pZHNcIjo3NzAsXCIuLi9zY2F0dGVyL2NhbGNcIjoxMTEzLFwiLi4vc2NhdHRlci9jb2xvcnNjYWxlX2NhbGNcIjoxMTE1LFwiLi4vc2NhdHRlcmdsL2NvbnN0YW50c1wiOjExNjIsXCIuLi9zY2F0dGVyZ2wvY29udmVydFwiOjExNjMsXCIuL3NjZW5lX3VwZGF0ZVwiOjEyMDd9XSwxMjAxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGhhbmRsZUFycmF5Q29udGFpbmVyRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHMnKTtcblxudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBzdWJUeXBlcyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3VidHlwZXMnKTtcbnZhciBoYW5kbGVNYXJrZXJEZWZhdWx0cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzJyk7XG52YXIgbWVyZ2VMZW5ndGggPSBfZGVyZXFfKCcuLi9wYXJjb29yZHMvbWVyZ2VfbGVuZ3RoJyk7XG52YXIgT1BFTl9SRSA9IC8tb3Blbi87XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBkaW1lbnNpb25zID0gaGFuZGxlQXJyYXlDb250YWluZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwge1xuICAgICAgICBuYW1lOiAnZGltZW5zaW9ucycsXG4gICAgICAgIGhhbmRsZUl0ZW1EZWZhdWx0czogZGltZW5zaW9uRGVmYXVsdHNcbiAgICB9KTtcblxuICAgIHZhciBzaG93RGlhZyA9IGNvZXJjZSgnZGlhZ29uYWwudmlzaWJsZScpO1xuICAgIHZhciBzaG93VXBwZXIgPSBjb2VyY2UoJ3Nob3d1cHBlcmhhbGYnKTtcbiAgICB2YXIgc2hvd0xvd2VyID0gY29lcmNlKCdzaG93bG93ZXJoYWxmJyk7XG5cbiAgICB2YXIgZGltTGVuZ3RoID0gbWVyZ2VMZW5ndGgodHJhY2VPdXQsIGRpbWVuc2lvbnMsICd2YWx1ZXMnKTtcblxuICAgIGlmKCFkaW1MZW5ndGggfHwgKCFzaG93RGlhZyAmJiAhc2hvd1VwcGVyICYmICFzaG93TG93ZXIpKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgndGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG5cbiAgICBoYW5kbGVNYXJrZXJEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICB2YXIgaXNPcGVuID0gT1BFTl9SRS50ZXN0KHRyYWNlT3V0Lm1hcmtlci5zeW1ib2wpO1xuICAgIHZhciBpc0J1YmJsZSA9IHN1YlR5cGVzLmlzQnViYmxlKHRyYWNlT3V0KTtcbiAgICBjb2VyY2UoJ21hcmtlci5saW5lLndpZHRoJywgaXNPcGVuIHx8IGlzQnViYmxlID8gMSA6IDApO1xuXG4gICAgaGFuZGxlQXhpc0RlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICBMaWIuY29lcmNlU2VsZWN0aW9uTWFya2VyT3BhY2l0eSh0cmFjZU91dCwgY29lcmNlKTtcbn07XG5cbmZ1bmN0aW9uIGRpbWVuc2lvbkRlZmF1bHRzKGRpbUluLCBkaW1PdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZShkaW1JbiwgZGltT3V0LCBhdHRyaWJ1dGVzLmRpbWVuc2lvbnMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGNvZXJjZSgnbGFiZWwnKTtcbiAgICB2YXIgdmFsdWVzID0gY29lcmNlKCd2YWx1ZXMnKTtcblxuICAgIGlmKCEodmFsdWVzICYmIHZhbHVlcy5sZW5ndGgpKSBkaW1PdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgIGVsc2UgY29lcmNlKCd2aXNpYmxlJyk7XG5cbiAgICBjb2VyY2UoJ2F4aXMudHlwZScpO1xuICAgIGNvZXJjZSgnYXhpcy5tYXRjaGVzJyk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZUF4aXNEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UpIHtcbiAgICB2YXIgZGltZW5zaW9ucyA9IHRyYWNlT3V0LmRpbWVuc2lvbnM7XG4gICAgdmFyIGRpbUxlbmd0aCA9IGRpbWVuc2lvbnMubGVuZ3RoO1xuICAgIHZhciBzaG93VXBwZXIgPSB0cmFjZU91dC5zaG93dXBwZXJoYWxmO1xuICAgIHZhciBzaG93TG93ZXIgPSB0cmFjZU91dC5zaG93bG93ZXJoYWxmO1xuICAgIHZhciBzaG93RGlhZyA9IHRyYWNlT3V0LmRpYWdvbmFsLnZpc2libGU7XG4gICAgdmFyIGksIGo7XG5cbiAgICB2YXIgeEF4ZXNEZmx0ID0gbmV3IEFycmF5KGRpbUxlbmd0aCk7XG4gICAgdmFyIHlBeGVzRGZsdCA9IG5ldyBBcnJheShkaW1MZW5ndGgpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgZGltTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHN1ZmZpeCA9IGkgPyBpICsgMSA6ICcnO1xuICAgICAgICB4QXhlc0RmbHRbaV0gPSAneCcgKyBzdWZmaXg7XG4gICAgICAgIHlBeGVzRGZsdFtpXSA9ICd5JyArIHN1ZmZpeDtcbiAgICB9XG5cbiAgICB2YXIgeGF4ZXMgPSBjb2VyY2UoJ3hheGVzJywgeEF4ZXNEZmx0KTtcbiAgICB2YXIgeWF4ZXMgPSBjb2VyY2UoJ3lheGVzJywgeUF4ZXNEZmx0KTtcblxuICAgIC8vIGJ1aWxkIGxpc3Qgb2YgW3gseV0gYXhpcyBjb3JyZXNwb25kaW5nIHRvIGVhY2ggZGltZW5zaW9uc1tpXSxcbiAgICAvLyB2ZXJ5IHVzZWZ1bCBmb3IgcGFzc2luZyBvcHRpb25zIHRvIHJlZ2wtc3Bsb21cbiAgICB2YXIgZGlhZyA9IHRyYWNlT3V0Ll9kaWFnID0gbmV3IEFycmF5KGRpbUxlbmd0aCk7XG5cbiAgICAvLyBsb29rdXAgZm9yICdkcmF3bicgeHx5IGF4ZXMsIHRvIGF2b2lkIGNvc3RseSBpbmRleE9mIGRvd25zdHJlYW1cbiAgICB0cmFjZU91dC5feGF4ZXMgPSB7fTtcbiAgICB0cmFjZU91dC5feWF4ZXMgPSB7fTtcblxuICAgIC8vIGxpc3Qgb2YgJ2RyYXduJyB4fHkgYXhlcywgdXNlIHRvIGdlbmVyYXRlIGxpc3Qgb2Ygc3VicGxvdHNcbiAgICB2YXIgeExpc3QgPSBbXTtcbiAgICB2YXIgeUxpc3QgPSBbXTtcblxuICAgIGZ1bmN0aW9uIGZpbGxBeGlzU3Rhc2hlcyhheElkLCBjb3VudGVyQXhJZCwgZGltLCBsaXN0KSB7XG4gICAgICAgIGlmKCFheElkKSByZXR1cm47XG5cbiAgICAgICAgdmFyIGF4TGV0dGVyID0gYXhJZC5jaGFyQXQoMCk7XG4gICAgICAgIHZhciBzdGFzaCA9IGxheW91dC5fc3Bsb21BeGVzW2F4TGV0dGVyXTtcblxuICAgICAgICB0cmFjZU91dFsnXycgKyBheExldHRlciArICdheGVzJ11bYXhJZF0gPSAxO1xuICAgICAgICBsaXN0LnB1c2goYXhJZCk7XG5cbiAgICAgICAgaWYoIShheElkIGluIHN0YXNoKSkge1xuICAgICAgICAgICAgdmFyIHMgPSBzdGFzaFtheElkXSA9IHt9O1xuICAgICAgICAgICAgaWYoZGltKSB7XG4gICAgICAgICAgICAgICAgcy5sYWJlbCA9IGRpbS5sYWJlbCB8fCAnJztcbiAgICAgICAgICAgICAgICBpZihkaW0udmlzaWJsZSAmJiBkaW0uYXhpcykge1xuICAgICAgICAgICAgICAgICAgICBpZihkaW0uYXhpcy50eXBlKSBzLnR5cGUgPSBkaW0uYXhpcy50eXBlO1xuICAgICAgICAgICAgICAgICAgICBpZihkaW0uYXhpcy5tYXRjaGVzKSBzLm1hdGNoZXMgPSBjb3VudGVyQXhJZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBjYXNlcyB3aGVyZSBzaG93RGlhZyBhbmQgc2hvd0xvd2VyIG9yIHNob3dVcHBlciBhcmUgZmFsc2VcbiAgICAvLyBubyBzcGVjaWFsIHRyZWF0bWVudCBhcyB0aGUgJ2RyYXduJyB4LWF4ZXMgYW5kIHktYXhlcyBubyBsb25nZXIgbWF0Y2hcbiAgICAvLyB0aGUgZGltZW5zaW9ucyBpdGVtcyBhbmQgeGF4ZXN8eWF4ZXMgMS10by0xXG4gICAgdmFyIG11c3RTaGlmdFggPSAhc2hvd0RpYWcgJiYgIXNob3dMb3dlcjtcbiAgICB2YXIgbXVzdFNoaWZ0WSA9ICFzaG93RGlhZyAmJiAhc2hvd1VwcGVyO1xuXG4gICAgdHJhY2VPdXQuX2F4ZXNEaW0gPSB7fTtcbiAgICBmb3IoaSA9IDA7IGkgPCBkaW1MZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgZGltID0gZGltZW5zaW9uc1tpXTtcbiAgICAgICAgdmFyIGkwID0gaSA9PT0gMDtcbiAgICAgICAgdmFyIGlOID0gaSA9PT0gZGltTGVuZ3RoIC0gMTtcblxuICAgICAgICB2YXIgeGFJZCA9IChpMCAmJiBtdXN0U2hpZnRYKSB8fCAoaU4gJiYgbXVzdFNoaWZ0WSkgP1xuICAgICAgICAgICAgdW5kZWZpbmVkIDpcbiAgICAgICAgICAgIHhheGVzW2ldO1xuXG4gICAgICAgIHZhciB5YUlkID0gKGkwICYmIG11c3RTaGlmdFkpIHx8IChpTiAmJiBtdXN0U2hpZnRYKSA/XG4gICAgICAgICAgICB1bmRlZmluZWQgOlxuICAgICAgICAgICAgeWF4ZXNbaV07XG5cbiAgICAgICAgZmlsbEF4aXNTdGFzaGVzKHhhSWQsIHlhSWQsIGRpbSwgeExpc3QpO1xuICAgICAgICBmaWxsQXhpc1N0YXNoZXMoeWFJZCwgeGFJZCwgZGltLCB5TGlzdCk7XG4gICAgICAgIGRpYWdbaV0gPSBbeGFJZCwgeWFJZF07XG4gICAgICAgIHRyYWNlT3V0Ll9heGVzRGltW3hhSWRdID0gaTtcbiAgICAgICAgdHJhY2VPdXQuX2F4ZXNEaW1beWFJZF0gPSBpO1xuICAgIH1cblxuICAgIC8vIGZpbGwgaW4gc3Bsb20gc3VicGxvdCBrZXlzXG4gICAgZm9yKGkgPSAwOyBpIDwgeExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgeUxpc3QubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBpZCA9IHhMaXN0W2ldICsgeUxpc3Rbal07XG5cbiAgICAgICAgICAgIGlmKGkgPiBqICYmIHNob3dVcHBlcikge1xuICAgICAgICAgICAgICAgIGxheW91dC5fc3Bsb21TdWJwbG90c1tpZF0gPSAxO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGkgPCBqICYmIHNob3dMb3dlcikge1xuICAgICAgICAgICAgICAgIGxheW91dC5fc3Bsb21TdWJwbG90c1tpZF0gPSAxO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGkgPT09IGogJiYgKHNob3dEaWFnIHx8ICFzaG93TG93ZXIgfHwgIXNob3dVcHBlcikpIHtcbiAgICAgICAgICAgICAgICAvLyBuZWVkIHRvIGluY2x1ZGUgZGlhZ29uYWwgc3VicGxvdHMgd2hlblxuICAgICAgICAgICAgICAgIC8vIGhpZGluZyBvbmUgaGFsZiBhbmQgdGhlIGRpYWdvbmFsXG4gICAgICAgICAgICAgICAgbGF5b3V0Ll9zcGxvbVN1YnBsb3RzW2lkXSA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB3aGVuIGxvd2VyIGhhbGYgaXMgb21pdHRlZCwgb3Igd2hlbiBqdXN0IHRoZSBkaWFnb25hbCBpcyBnb25lLFxuICAgIC8vIG92ZXJyaWRlIGdyaWQgZGVmYXVsdCB0byBtYWtlIHN1cmUgYXhlcyByZW1haW4gb25cbiAgICAvLyB0aGUgbGVmdC9ib3R0b20gb2YgdGhlIHBsb3QgYXJlYVxuICAgIGlmKCFzaG93TG93ZXIgfHwgKCFzaG93RGlhZyAmJiBzaG93VXBwZXIgJiYgc2hvd0xvd2VyKSkge1xuICAgICAgICBsYXlvdXQuX3NwbG9tR3JpZERmbHQueHNpZGUgPSAnYm90dG9tJztcbiAgICAgICAgbGF5b3V0Ll9zcGxvbUdyaWREZmx0LnlzaWRlID0gJ2xlZnQnO1xuICAgIH1cbn1cblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9hcnJheV9jb250YWluZXJfZGVmYXVsdHNcIjo3NjMsXCIuLi9wYXJjb29yZHMvbWVyZ2VfbGVuZ3RoXCI6MTA4MyxcIi4uL3NjYXR0ZXIvbWFya2VyX2RlZmF1bHRzXCI6MTEzMCxcIi4uL3NjYXR0ZXIvc3VidHlwZXNcIjoxMTM1LFwiLi9hdHRyaWJ1dGVzXCI6MTE5OH1dLDEyMDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgY2FsY0NvbG9yc2NhbGUgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL2NvbG9yc2NhbGVfY2FsYycpO1xudmFyIGNvbnZlcnRNYXJrZXJTdHlsZSA9IF9kZXJlcV8oJy4uL3NjYXR0ZXJnbC9jb252ZXJ0JykubWFya2VyU3R5bGU7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZWRpdFN0eWxlKGdkLCBjZDApIHtcbiAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgdmFyIHNjZW5lID0gZ2QuX2Z1bGxMYXlvdXQuX3NwbG9tU2NlbmVzW3RyYWNlLnVpZF07XG5cbiAgICBpZihzY2VuZSkge1xuICAgICAgICBjYWxjQ29sb3JzY2FsZShnZCwgdHJhY2UpO1xuXG4gICAgICAgIExpYi5leHRlbmRGbGF0KHNjZW5lLm1hdHJpeE9wdGlvbnMsIGNvbnZlcnRNYXJrZXJTdHlsZSh0cmFjZSkpO1xuICAgICAgICAvLyBUT0RPIFt1bl1zZWxlY3RlZCBzdHlsZXM/XG5cbiAgICAgICAgdmFyIG9wdHMgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgc2NlbmUubWF0cml4T3B0aW9ucywgc2NlbmUudmlld09wdHMpO1xuXG4gICAgICAgIC8vIFRPRE8gdGhpcyBpcyB0b28gbG9uZyBmb3IgYXJyYXlPayBhdHRyaWJ1dGVzIVxuICAgICAgICBzY2VuZS5tYXRyaXgudXBkYXRlKG9wdHMsIG51bGwpO1xuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vc2NhdHRlci9jb2xvcnNjYWxlX2NhbGNcIjoxMTE1LFwiLi4vc2NhdHRlcmdsL2NvbnZlcnRcIjoxMTYzfV0sMTIwMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuZ2V0RGltSW5kZXggPSBmdW5jdGlvbiBnZXREaW1JbmRleCh0cmFjZSwgYXgpIHtcbiAgICB2YXIgYXhJZCA9IGF4Ll9pZDtcbiAgICB2YXIgYXhMZXR0ZXIgPSBheElkLmNoYXJBdCgwKTtcbiAgICB2YXIgaW5kID0ge3g6IDAsIHk6IDF9W2F4TGV0dGVyXTtcbiAgICB2YXIgdmlzaWJsZURpbXMgPSB0cmFjZS5fdmlzaWJsZURpbXM7XG5cbiAgICBmb3IodmFyIGsgPSAwOyBrIDwgdmlzaWJsZURpbXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgdmFyIGkgPSB2aXNpYmxlRGltc1trXTtcbiAgICAgICAgaWYodHJhY2UuX2RpYWdbaV1baW5kXSA9PT0gYXhJZCkgcmV0dXJuIGs7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn07XG5cbn0se31dLDEyMDQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xudmFyIGNhbGNIb3ZlciA9IF9kZXJlcV8oJy4uL3NjYXR0ZXJnbC9ob3ZlcicpLmNhbGNIb3ZlcjtcblxuZnVuY3Rpb24gaG92ZXJQb2ludHMocG9pbnREYXRhLCB4dmFsLCB5dmFsKSB7XG4gICAgdmFyIGNkID0gcG9pbnREYXRhLmNkO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciBzY2VuZSA9IHBvaW50RGF0YS5zY2VuZTtcbiAgICB2YXIgY2RhdGEgPSBzY2VuZS5tYXRyaXhPcHRpb25zLmNkYXRhO1xuICAgIHZhciB4YSA9IHBvaW50RGF0YS54YTtcbiAgICB2YXIgeWEgPSBwb2ludERhdGEueWE7XG4gICAgdmFyIHhweCA9IHhhLmMycCh4dmFsKTtcbiAgICB2YXIgeXB4ID0geWEuYzJwKHl2YWwpO1xuICAgIHZhciBtYXhEaXN0YW5jZSA9IHBvaW50RGF0YS5kaXN0YW5jZTtcblxuICAgIHZhciB4aSA9IGhlbHBlcnMuZ2V0RGltSW5kZXgodHJhY2UsIHhhKTtcbiAgICB2YXIgeWkgPSBoZWxwZXJzLmdldERpbUluZGV4KHRyYWNlLCB5YSk7XG4gICAgaWYoeGkgPT09IGZhbHNlIHx8IHlpID09PSBmYWxzZSkgcmV0dXJuIFtwb2ludERhdGFdO1xuXG4gICAgdmFyIHggPSBjZGF0YVt4aV07XG4gICAgdmFyIHkgPSBjZGF0YVt5aV07XG5cbiAgICB2YXIgaWQsIGR4eTtcbiAgICB2YXIgbWluRGlzdCA9IG1heERpc3RhbmNlO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHgubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHB0eCA9IHhbaV07XG4gICAgICAgIHZhciBwdHkgPSB5W2ldO1xuICAgICAgICB2YXIgZHggPSB4YS5jMnAocHR4KSAtIHhweDtcbiAgICAgICAgdmFyIGR5ID0geWEuYzJwKHB0eSkgLSB5cHg7XG4gICAgICAgIHZhciBkaXN0ID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcblxuICAgICAgICBpZihkaXN0IDwgbWluRGlzdCkge1xuICAgICAgICAgICAgbWluRGlzdCA9IGR4eSA9IGRpc3Q7XG4gICAgICAgICAgICBpZCA9IGk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwb2ludERhdGEuaW5kZXggPSBpZDtcbiAgICBwb2ludERhdGEuZGlzdGFuY2UgPSBtaW5EaXN0O1xuICAgIHBvaW50RGF0YS5keHkgPSBkeHk7XG5cbiAgICBpZihpZCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gW3BvaW50RGF0YV07XG5cbiAgICBjYWxjSG92ZXIocG9pbnREYXRhLCB4LCB5LCB0cmFjZSk7XG5cbiAgICByZXR1cm4gW3BvaW50RGF0YV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGhvdmVyUG9pbnRzOiBob3ZlclBvaW50c1xufTtcblxufSx7XCIuLi9zY2F0dGVyZ2wvaG92ZXJcIjoxMTY2LFwiLi9oZWxwZXJzXCI6MTIwM31dLDEyMDU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIEdyaWQgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2dyaWQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbW9kdWxlVHlwZTogJ3RyYWNlJyxcbiAgICBuYW1lOiAnc3Bsb20nLFxuXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4vYmFzZV9wbG90JyksXG4gICAgY2F0ZWdvcmllczogWydnbCcsICdyZWdsJywgJ2NhcnRlc2lhbicsICdzeW1ib2xzJywgJ3Nob3dMZWdlbmQnLCAnc2NhdHRlci1saWtlJ10sXG5cbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNvbG9yYmFyOiBfZGVyZXFfKCcuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhcicpLFxuXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JyksXG4gICAgaG92ZXJQb2ludHM6IF9kZXJlcV8oJy4vaG92ZXInKS5ob3ZlclBvaW50cyxcbiAgICBzZWxlY3RQb2ludHM6IF9kZXJlcV8oJy4vc2VsZWN0JyksXG4gICAgZWRpdFN0eWxlOiBfZGVyZXFfKCcuL2VkaXRfc3R5bGUnKSxcblxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxuLy8gc3Bsb20gdHJhY2VzIHVzZSB0aGUgJ2dyaWQnIGNvbXBvbmVudCB0byBnZW5lcmF0ZSB0aGVpciBheGVzLFxuLy8gcmVnaXN0ZXIgaXQgaGVyZVxuUmVnaXN0cnkucmVnaXN0ZXIoR3JpZCk7XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9ncmlkXCI6NjM2LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuLi9zY2F0dGVyL21hcmtlcl9jb2xvcmJhclwiOjExMjksXCIuL2F0dHJpYnV0ZXNcIjoxMTk4LFwiLi9iYXNlX3Bsb3RcIjoxMTk5LFwiLi9jYWxjXCI6MTIwMCxcIi4vZGVmYXVsdHNcIjoxMjAxLFwiLi9lZGl0X3N0eWxlXCI6MTIwMixcIi4vaG92ZXJcIjoxMjA0LFwiLi9wbG90XCI6MTIwNixcIi4vc2VsZWN0XCI6MTIwOH1dLDEyMDY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3JlYXRlTWF0cml4ID0gX2RlcmVxXygncmVnbC1zcGxvbScpO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgQXhpc0lEcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGlzX2lkcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIF8sIHNwbG9tQ2FsY0RhdGEpIHtcbiAgICBpZighc3Bsb21DYWxjRGF0YS5sZW5ndGgpIHJldHVybjtcblxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzcGxvbUNhbGNEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHBsb3RPbmUoZ2QsIHNwbG9tQ2FsY0RhdGFbaV1bMF0pO1xuICAgIH1cbn07XG5cbmZ1bmN0aW9uIHBsb3RPbmUoZ2QsIGNkMCkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGdzID0gZnVsbExheW91dC5fc2l6ZTtcbiAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG4gICAgdmFyIHN0YXNoID0gY2QwLnQ7XG4gICAgdmFyIHNjZW5lID0gZnVsbExheW91dC5fc3Bsb21TY2VuZXNbdHJhY2UudWlkXTtcbiAgICB2YXIgbWF0cml4T3B0cyA9IHNjZW5lLm1hdHJpeE9wdGlvbnM7XG4gICAgdmFyIGNkYXRhID0gbWF0cml4T3B0cy5jZGF0YTtcbiAgICB2YXIgcmVnbCA9IGZ1bGxMYXlvdXQuX2dsY2FudmFzLmRhdGEoKVswXS5yZWdsO1xuICAgIHZhciBkcmFnbW9kZSA9IGZ1bGxMYXlvdXQuZHJhZ21vZGU7XG4gICAgdmFyIHhhLCB5YTtcbiAgICB2YXIgaSwgaiwgaztcblxuICAgIGlmKGNkYXRhLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG4gICAgLy8gYXVnbWVudCBvcHRpb25zIHdpdGggcHJvcGVyIHVwcGVyL2xvd2VyIGhhbHZlc1xuICAgIC8vIHJlZ2wtc3Bsb20ncyBkZWZhdWx0IGdyaWQgc3RhcnRzIGZyb20gYm90dG9tLWxlZnRcbiAgICBtYXRyaXhPcHRzLmxvd2VyID0gdHJhY2Uuc2hvd3VwcGVyaGFsZjtcbiAgICBtYXRyaXhPcHRzLnVwcGVyID0gdHJhY2Uuc2hvd2xvd2VyaGFsZjtcbiAgICBtYXRyaXhPcHRzLmRpYWdvbmFsID0gdHJhY2UuZGlhZ29uYWwudmlzaWJsZTtcblxuICAgIHZhciB2aXNpYmxlRGltcyA9IHRyYWNlLl92aXNpYmxlRGltcztcbiAgICB2YXIgdmlzaWJsZUxlbmd0aCA9IGNkYXRhLmxlbmd0aDtcbiAgICB2YXIgdmlld09wdHMgPSBzY2VuZS52aWV3T3B0cyA9IHt9O1xuICAgIHZpZXdPcHRzLnJhbmdlcyA9IG5ldyBBcnJheSh2aXNpYmxlTGVuZ3RoKTtcbiAgICB2aWV3T3B0cy5kb21haW5zID0gbmV3IEFycmF5KHZpc2libGVMZW5ndGgpO1xuXG4gICAgZm9yKGsgPSAwOyBrIDwgdmlzaWJsZURpbXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgaSA9IHZpc2libGVEaW1zW2tdO1xuXG4gICAgICAgIHZhciBybmcgPSB2aWV3T3B0cy5yYW5nZXNba10gPSBuZXcgQXJyYXkoNCk7XG4gICAgICAgIHZhciBkbW4gPSB2aWV3T3B0cy5kb21haW5zW2tdID0gbmV3IEFycmF5KDQpO1xuXG4gICAgICAgIHhhID0gQXhpc0lEcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLl9kaWFnW2ldWzBdKTtcbiAgICAgICAgaWYoeGEpIHtcbiAgICAgICAgICAgIHJuZ1swXSA9IHhhLl9ybFswXTtcbiAgICAgICAgICAgIHJuZ1syXSA9IHhhLl9ybFsxXTtcbiAgICAgICAgICAgIGRtblswXSA9IHhhLmRvbWFpblswXTtcbiAgICAgICAgICAgIGRtblsyXSA9IHhhLmRvbWFpblsxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHlhID0gQXhpc0lEcy5nZXRGcm9tSWQoZ2QsIHRyYWNlLl9kaWFnW2ldWzFdKTtcbiAgICAgICAgaWYoeWEpIHtcbiAgICAgICAgICAgIHJuZ1sxXSA9IHlhLl9ybFswXTtcbiAgICAgICAgICAgIHJuZ1szXSA9IHlhLl9ybFsxXTtcbiAgICAgICAgICAgIGRtblsxXSA9IHlhLmRvbWFpblswXTtcbiAgICAgICAgICAgIGRtblszXSA9IHlhLmRvbWFpblsxXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZpZXdPcHRzLnZpZXdwb3J0ID0gW2dzLmwsIGdzLmIsIGdzLncgKyBncy5sLCBncy5oICsgZ3MuYl07XG5cbiAgICBpZihzY2VuZS5tYXRyaXggPT09IHRydWUpIHtcbiAgICAgICAgc2NlbmUubWF0cml4ID0gY3JlYXRlTWF0cml4KHJlZ2wpO1xuICAgIH1cblxuICAgIHZhciBjbGlja1NlbGVjdEVuYWJsZWQgPSBmdWxsTGF5b3V0LmNsaWNrbW9kZS5pbmRleE9mKCdzZWxlY3QnKSA+IC0xO1xuICAgIHZhciBzZWxlY3RNb2RlID0gZHJhZ21vZGUgPT09ICdsYXNzbycgfHwgZHJhZ21vZGUgPT09ICdzZWxlY3QnIHx8XG4gICAgICAhIXRyYWNlLnNlbGVjdGVkcG9pbnRzIHx8IGNsaWNrU2VsZWN0RW5hYmxlZDtcbiAgICB2YXIgbmVlZHNCYXNlVXBkYXRlID0gdHJ1ZTtcblxuICAgIGlmKHNlbGVjdE1vZGUpIHtcbiAgICAgICAgdmFyIGNvbW1vbkxlbmd0aCA9IHRyYWNlLl9sZW5ndGg7XG5cbiAgICAgICAgLy8gcmVnZW5lcmF0ZSBzY2VuZSBiYXRjaCwgaWYgdHJhY2VzIG51bWJlciBjaGFuZ2VkIGR1cmluZyBzZWxlY3Rpb25cbiAgICAgICAgaWYodHJhY2Uuc2VsZWN0ZWRwb2ludHMpIHtcbiAgICAgICAgICAgIHNjZW5lLnNlbGVjdEJhdGNoID0gdHJhY2Uuc2VsZWN0ZWRwb2ludHM7XG5cbiAgICAgICAgICAgIHZhciBzZWxQdHMgPSB0cmFjZS5zZWxlY3RlZHBvaW50cztcbiAgICAgICAgICAgIHZhciBzZWxEaWN0ID0ge307XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBzZWxQdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzZWxEaWN0W3NlbFB0c1tpXV0gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHVuc2VsUHRzID0gW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBjb21tb25MZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmKCFzZWxEaWN0W2ldKSB1bnNlbFB0cy5wdXNoKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2NlbmUudW5zZWxlY3RCYXRjaCA9IHVuc2VsUHRzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcHJlY2FsY3VsYXRlIHB4IGNvb3JkcyBzaW5jZSB3ZSBhcmUgbm90IGdvaW5nIHRvIHBhbiBkdXJpbmcgc2VsZWN0XG4gICAgICAgIHZhciB4cHggPSBzdGFzaC54cHggPSBuZXcgQXJyYXkodmlzaWJsZUxlbmd0aCk7XG4gICAgICAgIHZhciB5cHggPSBzdGFzaC55cHggPSBuZXcgQXJyYXkodmlzaWJsZUxlbmd0aCk7XG5cbiAgICAgICAgZm9yKGsgPSAwOyBrIDwgdmlzaWJsZURpbXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgIGkgPSB2aXNpYmxlRGltc1trXTtcblxuICAgICAgICAgICAgeGEgPSBBeGlzSURzLmdldEZyb21JZChnZCwgdHJhY2UuX2RpYWdbaV1bMF0pO1xuICAgICAgICAgICAgaWYoeGEpIHtcbiAgICAgICAgICAgICAgICB4cHhba10gPSBuZXcgQXJyYXkoY29tbW9uTGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBjb21tb25MZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB4cHhba11bal0gPSB4YS5jMnAoY2RhdGFba11bal0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgeWEgPSBBeGlzSURzLmdldEZyb21JZChnZCwgdHJhY2UuX2RpYWdbaV1bMV0pO1xuICAgICAgICAgICAgaWYoeWEpIHtcbiAgICAgICAgICAgICAgICB5cHhba10gPSBuZXcgQXJyYXkoY29tbW9uTGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBmb3IoaiA9IDA7IGogPCBjb21tb25MZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB5cHhba11bal0gPSB5YS5jMnAoY2RhdGFba11bal0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHNjZW5lLnNlbGVjdEJhdGNoLmxlbmd0aCB8fCBzY2VuZS51bnNlbGVjdEJhdGNoLmxlbmd0aCkge1xuICAgICAgICAgICAgdmFyIHVuc2VsT3B0cyA9IExpYi5leHRlbmRGbGF0KHt9LCBtYXRyaXhPcHRzLCBzY2VuZS51bnNlbGVjdGVkT3B0aW9ucywgdmlld09wdHMpO1xuICAgICAgICAgICAgdmFyIHNlbE9wdHMgPSBMaWIuZXh0ZW5kRmxhdCh7fSwgbWF0cml4T3B0cywgc2NlbmUuc2VsZWN0ZWRPcHRpb25zLCB2aWV3T3B0cyk7XG4gICAgICAgICAgICBzY2VuZS5tYXRyaXgudXBkYXRlKHVuc2VsT3B0cywgc2VsT3B0cyk7XG4gICAgICAgICAgICBuZWVkc0Jhc2VVcGRhdGUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHN0YXNoLnhweCA9IHN0YXNoLnlweCA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYobmVlZHNCYXNlVXBkYXRlKSB7XG4gICAgICAgIHZhciBvcHRzID0gTGliLmV4dGVuZEZsYXQoe30sIG1hdHJpeE9wdHMsIHZpZXdPcHRzKTtcbiAgICAgICAgc2NlbmUubWF0cml4LnVwZGF0ZShvcHRzLCBudWxsKTtcbiAgICB9XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4aXNfaWRzXCI6NzcwLFwicmVnbC1zcGxvbVwiOjUwMX1dLDEyMDc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2NlbmVVcGRhdGUoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgdWlkID0gdHJhY2UudWlkO1xuXG4gICAgLy8gbXVzdCBwbGFjZSByZWYgdG8gJ3NjZW5lJyBpbiBmdWxsTGF5b3V0LCBzbyB0aGF0OlxuICAgIC8vIC0gaXQgY2FuIGJlIHJlbGlua2VkIHByb3Blcmx5IG9uIHVwZGF0ZXNcbiAgICAvLyAtIGl0IGNhbiBiZSBkZXN0cm95ZWQgcHJvcGVybHkgd2hlbiBuZWVkZWRcbiAgICB2YXIgc3Bsb21TY2VuZXMgPSBmdWxsTGF5b3V0Ll9zcGxvbVNjZW5lcztcbiAgICBpZighc3Bsb21TY2VuZXMpIHNwbG9tU2NlbmVzID0gZnVsbExheW91dC5fc3Bsb21TY2VuZXMgPSB7fTtcblxuICAgIHZhciByZXNldCA9IHtkaXJ0eTogdHJ1ZX07XG5cbiAgICB2YXIgZmlyc3QgPSB7XG4gICAgICAgIG1hdHJpeDogZmFsc2UsXG4gICAgICAgIHNlbGVjdEJhdGNoOiBbXSxcbiAgICAgICAgdW5zZWxlY3RCYXRjaDogW11cbiAgICB9O1xuXG4gICAgdmFyIHNjZW5lID0gc3Bsb21TY2VuZXNbdHJhY2UudWlkXTtcblxuICAgIGlmKCFzY2VuZSkge1xuICAgICAgICBzY2VuZSA9IHNwbG9tU2NlbmVzW3VpZF0gPSBMaWIuZXh0ZW5kRmxhdCh7fSwgcmVzZXQsIGZpcnN0KTtcblxuICAgICAgICBzY2VuZS5kcmF3ID0gZnVuY3Rpb24gZHJhdygpIHtcbiAgICAgICAgICAgIGlmKHNjZW5lLm1hdHJpeCAmJiBzY2VuZS5tYXRyaXguZHJhdykge1xuICAgICAgICAgICAgICAgIGlmKHNjZW5lLnNlbGVjdEJhdGNoLmxlbmd0aCB8fCBzY2VuZS51bnNlbGVjdEJhdGNoLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzY2VuZS5tYXRyaXguZHJhdyhzY2VuZS51bnNlbGVjdEJhdGNoLCBzY2VuZS5zZWxlY3RCYXRjaCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2NlbmUubWF0cml4LmRyYXcoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNjZW5lLmRpcnR5ID0gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gcmVtb3ZlIHNjZW5lIHJlc291cmNlc1xuICAgICAgICBzY2VuZS5kZXN0cm95ID0gZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgICAgIGlmKHNjZW5lLm1hdHJpeCAmJiBzY2VuZS5tYXRyaXguZGVzdHJveSkge1xuICAgICAgICAgICAgICAgIHNjZW5lLm1hdHJpeC5kZXN0cm95KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzY2VuZS5tYXRyaXhPcHRpb25zID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLnNlbGVjdEJhdGNoID0gbnVsbDtcbiAgICAgICAgICAgIHNjZW5lLnVuc2VsZWN0QmF0Y2ggPSBudWxsO1xuICAgICAgICAgICAgc2NlbmUgPSBudWxsO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIEluIGNhc2UgaWYgd2UgaGF2ZSBzY2VuZSBmcm9tIHRoZSBsYXN0IGNhbGMgLSByZXNldCBkYXRhXG4gICAgaWYoIXNjZW5lLmRpcnR5KSB7XG4gICAgICAgIExpYi5leHRlbmRGbGF0KHNjZW5lLCByZXNldCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNjZW5lO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTl9XSwxMjA4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIHN1YlR5cGVzID0gX2RlcmVxXygnLi4vc2NhdHRlci9zdWJ0eXBlcycpO1xudmFyIGhlbHBlcnMgPSBfZGVyZXFfKCcuL2hlbHBlcnMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzZWxlY3Qoc2VhcmNoSW5mbywgc2VsZWN0aW9uVGVzdGVyKSB7XG4gICAgdmFyIGNkID0gc2VhcmNoSW5mby5jZDtcbiAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcbiAgICB2YXIgc3Rhc2ggPSBjZFswXS50O1xuICAgIHZhciBzY2VuZSA9IHNlYXJjaEluZm8uc2NlbmU7XG4gICAgdmFyIGNkYXRhID0gc2NlbmUubWF0cml4T3B0aW9ucy5jZGF0YTtcbiAgICB2YXIgeGEgPSBzZWFyY2hJbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHNlYXJjaEluZm8ueWF4aXM7XG4gICAgdmFyIHNlbGVjdGlvbiA9IFtdO1xuXG4gICAgaWYoIXNjZW5lKSByZXR1cm4gc2VsZWN0aW9uO1xuXG4gICAgdmFyIGhhc09ubHlMaW5lcyA9ICghc3ViVHlwZXMuaGFzTWFya2Vycyh0cmFjZSkgJiYgIXN1YlR5cGVzLmhhc1RleHQodHJhY2UpKTtcbiAgICBpZih0cmFjZS52aXNpYmxlICE9PSB0cnVlIHx8IGhhc09ubHlMaW5lcykgcmV0dXJuIHNlbGVjdGlvbjtcblxuICAgIHZhciB4aSA9IGhlbHBlcnMuZ2V0RGltSW5kZXgodHJhY2UsIHhhKTtcbiAgICB2YXIgeWkgPSBoZWxwZXJzLmdldERpbUluZGV4KHRyYWNlLCB5YSk7XG4gICAgaWYoeGkgPT09IGZhbHNlIHx8IHlpID09PSBmYWxzZSkgcmV0dXJuIHNlbGVjdGlvbjtcblxuICAgIHZhciB4cHggPSBzdGFzaC54cHhbeGldO1xuICAgIHZhciB5cHggPSBzdGFzaC55cHhbeWldO1xuICAgIHZhciB4ID0gY2RhdGFbeGldO1xuICAgIHZhciB5ID0gY2RhdGFbeWldO1xuICAgIHZhciBlbHMgPSBbXTtcbiAgICB2YXIgdW5lbHMgPSBbXTtcblxuICAgIC8vIGRlZ2VuZXJhdGUgcG9seWdvbiBkb2VzIG5vdCBlbmFibGUgc2VsZWN0aW9uXG4gICAgLy8gZmlsdGVyIG91dCBwb2ludHMgYnkgdmlzaWJsZSBzY2F0dGVyIG9uZXNcbiAgICBpZihzZWxlY3Rpb25UZXN0ZXIgIT09IGZhbHNlICYmICFzZWxlY3Rpb25UZXN0ZXIuZGVnZW5lcmF0ZSkge1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYoc2VsZWN0aW9uVGVzdGVyLmNvbnRhaW5zKFt4cHhbaV0sIHlweFtpXV0sIG51bGwsIGksIHNlYXJjaEluZm8pKSB7XG4gICAgICAgICAgICAgICAgZWxzLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBwb2ludE51bWJlcjogaSxcbiAgICAgICAgICAgICAgICAgICAgeDogeFtpXSxcbiAgICAgICAgICAgICAgICAgICAgeTogeVtpXVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB1bmVscy5wdXNoKGkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIG1hdHJpeE9wdHMgPSBzY2VuZS5tYXRyaXhPcHRpb25zO1xuXG4gICAgaWYoIWVscy5sZW5ndGggJiYgIXVuZWxzLmxlbmd0aCkge1xuICAgICAgICBzY2VuZS5tYXRyaXgudXBkYXRlKG1hdHJpeE9wdHMsIG51bGwpO1xuICAgIH0gZWxzZSBpZighc2NlbmUuc2VsZWN0QmF0Y2gubGVuZ3RoICYmICFzY2VuZS51bnNlbGVjdEJhdGNoLmxlbmd0aCkge1xuICAgICAgICBzY2VuZS5tYXRyaXgudXBkYXRlKFxuICAgICAgICAgICAgc2NlbmUudW5zZWxlY3RlZE9wdGlvbnMsXG4gICAgICAgICAgICBMaWIuZXh0ZW5kRmxhdCh7fSwgbWF0cml4T3B0cywgc2NlbmUuc2VsZWN0ZWRPcHRpb25zLCBzY2VuZS52aWV3T3B0cylcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBzY2VuZS5zZWxlY3RCYXRjaCA9IGVscztcbiAgICBzY2VuZS51bnNlbGVjdEJhdGNoID0gdW5lbHM7XG5cbiAgICByZXR1cm4gc2VsZWN0aW9uO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi9zY2F0dGVyL3N1YnR5cGVzXCI6MTEzNSxcIi4vaGVscGVyc1wiOjEyMDN9XSwxMjA5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBtZXNoM2RBdHRycyA9IF9kZXJlcV8oJy4uL21lc2gzZC9hdHRyaWJ1dGVzJyk7XG52YXIgYmFzZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvYXR0cmlidXRlcycpO1xuXG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xuXG52YXIgYXR0cnMgPSB7XG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMrY2xlYXJBeGlzVHlwZXMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjK2NsZWFyQXhpc1R5cGVzJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB6OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYytjbGVhckF4aXNUeXBlcycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB1OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB2OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICB3OiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHN0YXJ0czoge1xuICAgICAgICB4OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgejoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgfSxcblxuICAgIG1heGRpc3BsYXllZDoge1xuICAgICAgICB2YWxUeXBlOiAnaW50ZWdlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgZGZsdDogMTAwMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICAvLyBUT0RPXG4gICAgLy9cbiAgICAvLyBTaG91bGQgYWRkICdhYnNvbHV0ZScgKGxpa2UgY29uZSB0cmFjZXMgaGF2ZSksIGJ1dCBjdXJyZW50bHkgZ2wtc3RyZWFtdHViZTNkJ3NcbiAgICAvLyBgYWJzb2x1dGVUdWJlU2l6ZWAgZG9lc24ndCBiZWhhdmUgd2VsbCBlbm91Z2ggZm9yIG91ciBuZWVkcy5cbiAgICAvL1xuICAgIC8vICdmaXhlZCcgd291bGQgYmUgYSBuaWNlIGFkZGl0aW9uIHRvIHBsb3Qgc3RyZWFtICdsaW5lcycsIHNlZVxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvcGxvdGx5LmpzL2NvbW1pdC84MTJiZTIwNzUwZTIxZTBhMTgzMTk3NTAwMWMyNDhkMzY1ODUwZjczI3IyOTEyOTg3N1xuICAgIC8vXG4gICAgLy8gc2l6ZW1vZGU6IHtcbiAgICAvLyAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgIC8vICAgICB2YWx1ZXM6IFsnc2NhbGVkJywgJ2Fic29sdXRlJywgJ2ZpeGVkJ10sXG4gICAgLy8gICAgIGRmbHQ6ICdzY2FsZWQnLFxuICAgIC8vICAgICBcbiAgICAvLyAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAvLyAgICAgXG4gICAgLy8gfSxcblxuICAgIHNpemVyZWY6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIGRmbHQ6IDEsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKHtlZGl0VHlwZTogJ2NhbGMnfSwge1xuICAgICAgICBrZXlzOiBbXG4gICAgICAgICAgICAndHViZXgnLCAndHViZXknLCAndHViZXonLFxuICAgICAgICAgICAgJ3R1YmV1JywgJ3R1YmV2JywgJ3R1YmV3JyxcbiAgICAgICAgICAgICdub3JtJywgJ2RpdmVyZ2VuY2UnXG4gICAgICAgIF1cbiAgICB9KVxufTtcblxuZXh0ZW5kRmxhdChhdHRycywgY29sb3JTY2FsZUF0dHJzKCcnLCB7XG4gICAgY29sb3JBdHRyOiAndS92L3cgbm9ybScsXG4gICAgc2hvd1NjYWxlRGZsdDogdHJ1ZSxcbiAgICBlZGl0VHlwZU92ZXJyaWRlOiAnY2FsYydcbn0pKTtcblxudmFyIGZyb21NZXNoM2QgPSBbJ29wYWNpdHknLCAnbGlnaHRwb3NpdGlvbicsICdsaWdodGluZyddO1xuZnJvbU1lc2gzZC5mb3JFYWNoKGZ1bmN0aW9uKGspIHtcbiAgICBhdHRyc1trXSA9IG1lc2gzZEF0dHJzW2tdO1xufSk7XG5cbmF0dHJzLmhvdmVyaW5mbyA9IGV4dGVuZEZsYXQoe30sIGJhc2VBdHRycy5ob3ZlcmluZm8sIHtcbiAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgIGZsYWdzOiBbJ3gnLCAneScsICd6JywgJ3UnLCAndicsICd3JywgJ25vcm0nLCAnZGl2ZXJnZW5jZScsICd0ZXh0JywgJ25hbWUnXSxcbiAgICBkZmx0OiAneCt5K3orbm9ybSt0ZXh0K25hbWUnXG59KTtcblxuYXR0cnMudHJhbnNmb3JtcyA9IHVuZGVmaW5lZDtcblxubW9kdWxlLmV4cG9ydHMgPSBhdHRycztcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvYXR0cmlidXRlc1wiOjYwMCxcIi4uLy4uL2NvbXBvbmVudHMvZngvaG92ZXJ0ZW1wbGF0ZV9hdHRyaWJ1dGVzXCI6NjMxLFwiLi4vLi4vbGliL2V4dGVuZFwiOjcxMCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9tZXNoM2QvYXR0cmlidXRlc1wiOjEwNTN9XSwxMjEwOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGNvbG9yc2NhbGVDYWxjID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjYWxjKGdkLCB0cmFjZSkge1xuICAgIHZhciBpO1xuXG4gICAgdmFyIHUgPSB0cmFjZS51O1xuICAgIHZhciB2ID0gdHJhY2UudjtcbiAgICB2YXIgdyA9IHRyYWNlLnc7XG4gICAgdmFyIHggPSB0cmFjZS54O1xuICAgIHZhciB5ID0gdHJhY2UueTtcbiAgICB2YXIgeiA9IHRyYWNlLno7XG4gICAgdmFyIGxlbiA9IE1hdGgubWluKHgubGVuZ3RoLCB5Lmxlbmd0aCwgei5sZW5ndGgsIHUubGVuZ3RoLCB2Lmxlbmd0aCwgdy5sZW5ndGgpO1xuXG4gICAgdmFyIHNsZW4gPSAwO1xuICAgIHZhciBzdGFydHgsIHN0YXJ0eSwgc3RhcnR6O1xuICAgIGlmKHRyYWNlLnN0YXJ0cykge1xuICAgICAgICBzdGFydHggPSB0cmFjZS5zdGFydHMueCB8fCBbXTtcbiAgICAgICAgc3RhcnR5ID0gdHJhY2Uuc3RhcnRzLnkgfHwgW107XG4gICAgICAgIHN0YXJ0eiA9IHRyYWNlLnN0YXJ0cy56IHx8IFtdO1xuICAgICAgICBzbGVuID0gTWF0aC5taW4oc3RhcnR4Lmxlbmd0aCwgc3RhcnR5Lmxlbmd0aCwgc3RhcnR6Lmxlbmd0aCk7XG4gICAgfVxuXG4gICAgdmFyIG5vcm1NYXggPSAwO1xuICAgIHZhciBub3JtTWluID0gSW5maW5pdHk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgdXUgPSB1W2ldO1xuICAgICAgICB2YXIgdnYgPSB2W2ldO1xuICAgICAgICB2YXIgd3cgPSB3W2ldO1xuICAgICAgICB2YXIgbm9ybSA9IE1hdGguc3FydCh1dSAqIHV1ICsgdnYgKiB2diArIHd3ICogd3cpO1xuXG4gICAgICAgIG5vcm1NYXggPSBNYXRoLm1heChub3JtTWF4LCBub3JtKTtcbiAgICAgICAgbm9ybU1pbiA9IE1hdGgubWluKG5vcm1NaW4sIG5vcm0pO1xuICAgIH1cblxuICAgIGNvbG9yc2NhbGVDYWxjKGdkLCB0cmFjZSwge1xuICAgICAgICB2YWxzOiBbbm9ybU1pbiwgbm9ybU1heF0sXG4gICAgICAgIGNvbnRhaW5lclN0cjogJycsXG4gICAgICAgIGNMZXR0ZXI6ICdjJ1xuICAgIH0pO1xuXG4gICAgdmFyIHhNYXggPSAtSW5maW5pdHk7XG4gICAgdmFyIHhNaW4gPSBJbmZpbml0eTtcbiAgICB2YXIgeU1heCA9IC1JbmZpbml0eTtcbiAgICB2YXIgeU1pbiA9IEluZmluaXR5O1xuICAgIHZhciB6TWF4ID0gLUluZmluaXR5O1xuICAgIHZhciB6TWluID0gSW5maW5pdHk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgeHggPSB4W2ldO1xuICAgICAgICB4TWF4ID0gTWF0aC5tYXgoeE1heCwgeHgpO1xuICAgICAgICB4TWluID0gTWF0aC5taW4oeE1pbiwgeHgpO1xuXG4gICAgICAgIHZhciB5eSA9IHlbaV07XG4gICAgICAgIHlNYXggPSBNYXRoLm1heCh5TWF4LCB5eSk7XG4gICAgICAgIHlNaW4gPSBNYXRoLm1pbih5TWluLCB5eSk7XG5cbiAgICAgICAgdmFyIHp6ID0geltpXTtcbiAgICAgICAgek1heCA9IE1hdGgubWF4KHpNYXgsIHp6KTtcbiAgICAgICAgek1pbiA9IE1hdGgubWluKHpNaW4sIHp6KTtcbiAgICB9XG4gICAgZm9yKGkgPSAwOyBpIDwgc2xlbjsgaSsrKSB7XG4gICAgICAgIHZhciBzeCA9IHN0YXJ0eFtpXTtcbiAgICAgICAgeE1heCA9IE1hdGgubWF4KHhNYXgsIHN4KTtcbiAgICAgICAgeE1pbiA9IE1hdGgubWluKHhNaW4sIHN4KTtcblxuICAgICAgICB2YXIgc3kgPSBzdGFydHlbaV07XG4gICAgICAgIHlNYXggPSBNYXRoLm1heCh5TWF4LCBzeSk7XG4gICAgICAgIHlNaW4gPSBNYXRoLm1pbih5TWluLCBzeSk7XG5cbiAgICAgICAgdmFyIHN6ID0gc3RhcnR6W2ldO1xuICAgICAgICB6TWF4ID0gTWF0aC5tYXgoek1heCwgc3opO1xuICAgICAgICB6TWluID0gTWF0aC5taW4oek1pbiwgc3opO1xuICAgIH1cblxuICAgIHRyYWNlLl9sZW4gPSBsZW47XG4gICAgdHJhY2UuX3NsZW4gPSBzbGVuO1xuICAgIHRyYWNlLl9ub3JtTWF4ID0gbm9ybU1heDtcbiAgICB0cmFjZS5feGJuZHMgPSBbeE1pbiwgeE1heF07XG4gICAgdHJhY2UuX3libmRzID0gW3lNaW4sIHlNYXhdO1xuICAgIHRyYWNlLl96Ym5kcyA9IFt6TWluLCB6TWF4XTtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2NhbGNcIjo2MDF9XSwxMjExOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHR1YmUybWVzaCA9IF9kZXJlcV8oJ2dsLXN0cmVhbXR1YmUzZCcpO1xudmFyIGNyZWF0ZVR1YmVNZXNoID0gdHViZTJtZXNoLmNyZWF0ZVR1YmVNZXNoO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgcGFyc2VDb2xvclNjYWxlID0gX2RlcmVxXygnLi4vLi4vbGliL2dsX2Zvcm1hdF9jb2xvcicpLnBhcnNlQ29sb3JTY2FsZTtcbnZhciBleHRyYWN0T3B0cyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZScpLmV4dHJhY3RPcHRzO1xudmFyIHppcDMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9nbDNkL3ppcDMnKTtcblxudmFyIGF4aXNOYW1lMnNjYWxlSW5kZXggPSB7eGF4aXM6IDAsIHlheGlzOiAxLCB6YXhpczogMn07XG5cbmZ1bmN0aW9uIFN0cmVhbXR1YmUoc2NlbmUsIHVpZCkge1xuICAgIHRoaXMuc2NlbmUgPSBzY2VuZTtcbiAgICB0aGlzLnVpZCA9IHVpZDtcbiAgICB0aGlzLm1lc2ggPSBudWxsO1xuICAgIHRoaXMuZGF0YSA9IG51bGw7XG59XG5cbnZhciBwcm90byA9IFN0cmVhbXR1YmUucHJvdG90eXBlO1xuXG5wcm90by5oYW5kbGVQaWNrID0gZnVuY3Rpb24oc2VsZWN0aW9uKSB7XG4gICAgdmFyIHNjZW5lTGF5b3V0ID0gdGhpcy5zY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIGRhdGFTY2FsZSA9IHRoaXMuc2NlbmUuZGF0YVNjYWxlO1xuXG4gICAgZnVuY3Rpb24gZnJvbURhdGFTY2FsZSh2LCBheGlzTmFtZSkge1xuICAgICAgICB2YXIgYXggPSBzY2VuZUxheW91dFtheGlzTmFtZV07XG4gICAgICAgIHZhciBzY2FsZSA9IGRhdGFTY2FsZVtheGlzTmFtZTJzY2FsZUluZGV4W2F4aXNOYW1lXV07XG4gICAgICAgIHJldHVybiBheC5sMmModikgLyBzY2FsZTtcbiAgICB9XG5cbiAgICBpZihzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLm1lc2gpIHtcbiAgICAgICAgdmFyIHBvcyA9IHNlbGVjdGlvbi5kYXRhLnBvc2l0aW9uO1xuICAgICAgICB2YXIgdXZ4ID0gc2VsZWN0aW9uLmRhdGEudmVsb2NpdHk7XG5cbiAgICAgICAgc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZSA9IFtcbiAgICAgICAgICAgIGZyb21EYXRhU2NhbGUocG9zWzBdLCAneGF4aXMnKSxcbiAgICAgICAgICAgIGZyb21EYXRhU2NhbGUocG9zWzFdLCAneWF4aXMnKSxcbiAgICAgICAgICAgIGZyb21EYXRhU2NhbGUocG9zWzJdLCAnemF4aXMnKSxcblxuICAgICAgICAgICAgZnJvbURhdGFTY2FsZSh1dnhbMF0sICd4YXhpcycpLFxuICAgICAgICAgICAgZnJvbURhdGFTY2FsZSh1dnhbMV0sICd5YXhpcycpLFxuICAgICAgICAgICAgZnJvbURhdGFTY2FsZSh1dnhbMl0sICd6YXhpcycpLFxuXG4gICAgICAgICAgICAvLyB1L3YvdyBub3JtXG4gICAgICAgICAgICBzZWxlY3Rpb24uZGF0YS5pbnRlbnNpdHkgKiB0aGlzLmRhdGEuX25vcm1NYXgsXG4gICAgICAgICAgICAvLyBkaXZlcmdlbmNlXG4gICAgICAgICAgICBzZWxlY3Rpb24uZGF0YS5kaXZlcmdlbmNlXG4gICAgICAgIF07XG5cbiAgICAgICAgc2VsZWN0aW9uLnRleHRMYWJlbCA9IHRoaXMuZGF0YS5ob3ZlcnRleHQgfHwgdGhpcy5kYXRhLnRleHQ7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gZGlzdGluY3RWYWxzKGNvbCkge1xuICAgIHJldHVybiBMaWIuZGlzdGluY3RWYWxzKGNvbCkudmFscztcbn1cblxuZnVuY3Rpb24gZ2V0RGZsdFN0YXJ0aW5nUG9zaXRpb25zKHZlYykge1xuICAgIHZhciBsZW4gPSB2ZWMubGVuZ3RoO1xuICAgIHZhciBzO1xuXG4gICAgaWYobGVuID4gMikge1xuICAgICAgICBzID0gdmVjLnNsaWNlKDEsIGxlbiAtIDEpO1xuICAgIH0gZWxzZSBpZihsZW4gPT09IDIpIHtcbiAgICAgICAgcyA9IFsodmVjWzBdICsgdmVjWzFdKSAvIDJdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHMgPSB2ZWM7XG4gICAgfVxuICAgIHJldHVybiBzO1xufVxuXG5mdW5jdGlvbiBnZXRCb3VuZFBhZHModmVjKSB7XG4gICAgdmFyIGxlbiA9IHZlYy5sZW5ndGg7XG4gICAgaWYobGVuID09PSAxKSB7XG4gICAgICAgIHJldHVybiBbMC41LCAwLjVdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbdmVjWzFdIC0gdmVjWzBdLCB2ZWNbbGVuIC0gMV0gLSB2ZWNbbGVuIC0gMl1dO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gY29udmVydChzY2VuZSwgdHJhY2UpIHtcbiAgICB2YXIgc2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIGRhdGFTY2FsZSA9IHNjZW5lLmRhdGFTY2FsZTtcbiAgICB2YXIgbGVuID0gdHJhY2UuX2xlbjtcbiAgICB2YXIgdHViZU9wdHMgPSB7fTtcblxuICAgIGZ1bmN0aW9uIHRvRGF0YUNvb3JkcyhhcnIsIGF4aXNOYW1lKSB7XG4gICAgICAgIHZhciBheCA9IHNjZW5lTGF5b3V0W2F4aXNOYW1lXTtcbiAgICAgICAgdmFyIHNjYWxlID0gZGF0YVNjYWxlW2F4aXNOYW1lMnNjYWxlSW5kZXhbYXhpc05hbWVdXTtcbiAgICAgICAgcmV0dXJuIExpYi5zaW1wbGVNYXAoYXJyLCBmdW5jdGlvbih2KSB7IHJldHVybiBheC5kMmwodikgKiBzY2FsZTsgfSk7XG4gICAgfVxuXG4gICAgdHViZU9wdHMudmVjdG9ycyA9IHppcDMoXG4gICAgICAgIHRvRGF0YUNvb3Jkcyh0cmFjZS51LCAneGF4aXMnKSxcbiAgICAgICAgdG9EYXRhQ29vcmRzKHRyYWNlLnYsICd5YXhpcycpLFxuICAgICAgICB0b0RhdGFDb29yZHModHJhY2UudywgJ3pheGlzJyksXG4gICAgICAgIGxlblxuICAgICk7XG5cbiAgICB2YXIgdmFsc3ggPSBkaXN0aW5jdFZhbHModHJhY2UueC5zbGljZSgwLCBsZW4pKTtcbiAgICB2YXIgdmFsc3kgPSBkaXN0aW5jdFZhbHModHJhY2UueS5zbGljZSgwLCBsZW4pKTtcbiAgICB2YXIgdmFsc3ogPSBkaXN0aW5jdFZhbHModHJhY2Uuei5zbGljZSgwLCBsZW4pKTtcblxuICAgIC8vIE92ZXItc3BlY2lmaWVkIG1lc2ggY2FzZSwgdGhpcyB3b3VsZCBlcnJvciBpbiB0dWJlMm1lc2hcbiAgICBpZih2YWxzeC5sZW5ndGggKiB2YWxzeS5sZW5ndGggKiB2YWxzei5sZW5ndGggPiBsZW4pIHtcbiAgICAgICAgcmV0dXJuIHtwb3NpdGlvbnM6IFtdLCBjZWxsczogW119O1xuICAgIH1cblxuICAgIHZhciBtZXNoeCA9IHRvRGF0YUNvb3Jkcyh2YWxzeCwgJ3hheGlzJyk7XG4gICAgdmFyIG1lc2h5ID0gdG9EYXRhQ29vcmRzKHZhbHN5LCAneWF4aXMnKTtcbiAgICB2YXIgbWVzaHogPSB0b0RhdGFDb29yZHModmFsc3osICd6YXhpcycpO1xuXG4gICAgdHViZU9wdHMubWVzaGdyaWQgPSBbbWVzaHgsIG1lc2h5LCBtZXNoel07XG5cbiAgICBpZih0cmFjZS5zdGFydHMpIHtcbiAgICAgICAgdmFyIHNsZW4gPSB0cmFjZS5fc2xlbjtcbiAgICAgICAgdHViZU9wdHMuc3RhcnRpbmdQb3NpdGlvbnMgPSB6aXAzKFxuICAgICAgICAgICAgdG9EYXRhQ29vcmRzKHRyYWNlLnN0YXJ0cy54LnNsaWNlKDAsIHNsZW4pLCAneGF4aXMnKSxcbiAgICAgICAgICAgIHRvRGF0YUNvb3Jkcyh0cmFjZS5zdGFydHMueS5zbGljZSgwLCBzbGVuKSwgJ3lheGlzJyksXG4gICAgICAgICAgICB0b0RhdGFDb29yZHModHJhY2Uuc3RhcnRzLnouc2xpY2UoMCwgc2xlbiksICd6YXhpcycpXG4gICAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRGVmYXVsdCBzdGFydGluZyBwb3NpdGlvbnM6XG4gICAgICAgIC8vXG4gICAgICAgIC8vIGlmIGxlbj4yLCBjdXQgeHogcGxhbmUgYXQgbWluLXksXG4gICAgICAgIC8vIHRha2VzIGFsbCB4L3kveiBwdHMgb24gdGhhdCBwbGFuZSBleGNlcHQgdGhvc2Ugb24gdGhlIGVkZ2VzXG4gICAgICAgIC8vIHRvIGdlbmVyYXRlIFwid2VsbC1kZWZpbmVkXCIgdHViZXMsXG4gICAgICAgIC8vXG4gICAgICAgIC8vIGlmIGxlbj0yLCB0YWtlIHBvc2l0aW9uIGhhbGZ3YXkgYmV0d2VlbiB0d28gdGhlIHB0cyxcbiAgICAgICAgLy9cbiAgICAgICAgLy8gaWYgbGVuPTEsIHRha2UgdGhhdCBwdFxuICAgICAgICB2YXIgc3kwID0gbWVzaHlbMF07XG4gICAgICAgIHZhciBzeCA9IGdldERmbHRTdGFydGluZ1Bvc2l0aW9ucyhtZXNoeCk7XG4gICAgICAgIHZhciBzeiA9IGdldERmbHRTdGFydGluZ1Bvc2l0aW9ucyhtZXNoeik7XG4gICAgICAgIHZhciBzdGFydGluZ1Bvc2l0aW9ucyA9IG5ldyBBcnJheShzeC5sZW5ndGggKiBzei5sZW5ndGgpO1xuICAgICAgICB2YXIgbSA9IDA7XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHN4Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBmb3IodmFyIGsgPSAwOyBrIDwgc3oubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICBzdGFydGluZ1Bvc2l0aW9uc1ttKytdID0gW3N4W2ldLCBzeTAsIHN6W2tdXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0dWJlT3B0cy5zdGFydGluZ1Bvc2l0aW9ucyA9IHN0YXJ0aW5nUG9zaXRpb25zO1xuICAgIH1cblxuICAgIHR1YmVPcHRzLmNvbG9ybWFwID0gcGFyc2VDb2xvclNjYWxlKHRyYWNlKTtcbiAgICB0dWJlT3B0cy50dWJlU2l6ZSA9IHRyYWNlLnNpemVyZWY7XG4gICAgdHViZU9wdHMubWF4TGVuZ3RoID0gdHJhY2UubWF4ZGlzcGxheWVkO1xuXG4gICAgLy8gYWRkIHNvbWUgcGFkZGluZyBhcm91bmQgdGhlIGJvdW5kc1xuICAgIC8vIHRvIGUuZy4gYWxsb3cgdHViZXMgc3RhcnRpbmcgZnJvbSBhIHNsaWNlIG9mIHRoZSB4L3kveiBtZXNoXG4gICAgLy8gdG8gZ28gYmV5b25kIGJvdW5kcyBhIGxpdHRsZSBiaXQgdy9vIGdldHRpbmcgY2xpcHBlZFxuICAgIHZhciB4Ym5kcyA9IHRvRGF0YUNvb3Jkcyh0cmFjZS5feGJuZHMsICd4YXhpcycpO1xuICAgIHZhciB5Ym5kcyA9IHRvRGF0YUNvb3Jkcyh0cmFjZS5feWJuZHMsICd5YXhpcycpO1xuICAgIHZhciB6Ym5kcyA9IHRvRGF0YUNvb3Jkcyh0cmFjZS5femJuZHMsICd6YXhpcycpO1xuICAgIHZhciB4cGFkcyA9IGdldEJvdW5kUGFkcyhtZXNoeCk7XG4gICAgdmFyIHlwYWRzID0gZ2V0Qm91bmRQYWRzKG1lc2h5KTtcbiAgICB2YXIgenBhZHMgPSBnZXRCb3VuZFBhZHMobWVzaHopO1xuXG4gICAgdmFyIGJvdW5kcyA9IFtcbiAgICAgICAgW3hibmRzWzBdIC0geHBhZHNbMF0sIHlibmRzWzBdIC0geXBhZHNbMF0sIHpibmRzWzBdIC0genBhZHNbMF1dLFxuICAgICAgICBbeGJuZHNbMV0gKyB4cGFkc1sxXSwgeWJuZHNbMV0gKyB5cGFkc1sxXSwgemJuZHNbMV0gKyB6cGFkc1sxXV1cbiAgICBdO1xuXG4gICAgdmFyIG1lc2hEYXRhID0gdHViZTJtZXNoKHR1YmVPcHRzLCBib3VuZHMpO1xuXG4gICAgLy8gTi5CLiBjbWluL2NtYXggY29ycmVzcG9uZCB0byB0aGUgbWluL21heCB2ZWN0b3Igbm9ybVxuICAgIC8vIGluIHRoZSB1L3YvdyBhcnJheXMsIHdoaWNoIGluIGdlbmVyYWwgaXMgTk9UIGVxdWFsIHRvIG1heFxuICAgIC8vIGludGVuc2l0eSB0aGF0IGNvbG9ycyB0aGUgdHViZXMuXG4gICAgdmFyIGNPcHRzID0gZXh0cmFjdE9wdHModHJhY2UpO1xuICAgIG1lc2hEYXRhLnZlcnRleEludGVuc2l0eUJvdW5kcyA9IFtjT3B0cy5taW4gLyB0cmFjZS5fbm9ybU1heCwgY09wdHMubWF4IC8gdHJhY2UuX25vcm1NYXhdO1xuXG4gICAgLy8gcGFzcyBnbC1tZXNoM2QgbGlnaHRpbmcgYXR0cmlidXRlc1xuICAgIHZhciBscCA9IHRyYWNlLmxpZ2h0cG9zaXRpb247XG4gICAgbWVzaERhdGEubGlnaHRQb3NpdGlvbiA9IFtscC54LCBscC55LCBscC56XTtcbiAgICBtZXNoRGF0YS5hbWJpZW50ID0gdHJhY2UubGlnaHRpbmcuYW1iaWVudDtcbiAgICBtZXNoRGF0YS5kaWZmdXNlID0gdHJhY2UubGlnaHRpbmcuZGlmZnVzZTtcbiAgICBtZXNoRGF0YS5zcGVjdWxhciA9IHRyYWNlLmxpZ2h0aW5nLnNwZWN1bGFyO1xuICAgIG1lc2hEYXRhLnJvdWdobmVzcyA9IHRyYWNlLmxpZ2h0aW5nLnJvdWdobmVzcztcbiAgICBtZXNoRGF0YS5mcmVzbmVsID0gdHJhY2UubGlnaHRpbmcuZnJlc25lbDtcbiAgICBtZXNoRGF0YS5vcGFjaXR5ID0gdHJhY2Uub3BhY2l0eTtcblxuICAgIC8vIHN0YXNoIGF1dG9yYW5nZSBwYWQgdmFsdWVcbiAgICB0cmFjZS5fcGFkID0gbWVzaERhdGEudHViZVNjYWxlICogdHJhY2Uuc2l6ZXJlZiAqIDI7XG5cbiAgICByZXR1cm4gbWVzaERhdGE7XG59XG5cbnByb3RvLnVwZGF0ZSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuXG4gICAgdmFyIG1lc2hEYXRhID0gY29udmVydCh0aGlzLnNjZW5lLCBkYXRhKTtcbiAgICB0aGlzLm1lc2gudXBkYXRlKG1lc2hEYXRhKTtcbn07XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5tZXNoKTtcbiAgICB0aGlzLm1lc2guZGlzcG9zZSgpO1xufTtcblxuZnVuY3Rpb24gY3JlYXRlU3RyZWFtdHViZVRyYWNlKHNjZW5lLCBkYXRhKSB7XG4gICAgdmFyIGdsID0gc2NlbmUuZ2xwbG90LmdsO1xuXG4gICAgdmFyIG1lc2hEYXRhID0gY29udmVydChzY2VuZSwgZGF0YSk7XG4gICAgdmFyIG1lc2ggPSBjcmVhdGVUdWJlTWVzaChnbCwgbWVzaERhdGEpO1xuXG4gICAgdmFyIHN0cmVhbXR1YmUgPSBuZXcgU3RyZWFtdHViZShzY2VuZSwgZGF0YS51aWQpO1xuICAgIHN0cmVhbXR1YmUubWVzaCA9IG1lc2g7XG4gICAgc3RyZWFtdHViZS5kYXRhID0gZGF0YTtcbiAgICBtZXNoLl90cmFjZSA9IHN0cmVhbXR1YmU7XG5cbiAgICBzY2VuZS5nbHBsb3QuYWRkKG1lc2gpO1xuXG4gICAgcmV0dXJuIHN0cmVhbXR1YmU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU3RyZWFtdHViZVRyYWNlO1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZVwiOjYwNSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL2xpYi9nbF9mb3JtYXRfY29sb3JcIjo3MTYsXCIuLi8uLi9wbG90cy9nbDNkL3ppcDNcIjo4MTgsXCJnbC1zdHJlYW10dWJlM2RcIjozMTN9XSwxMjEyOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgY29sb3JzY2FsZURlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgdSA9IGNvZXJjZSgndScpO1xuICAgIHZhciB2ID0gY29lcmNlKCd2Jyk7XG4gICAgdmFyIHcgPSBjb2VyY2UoJ3cnKTtcblxuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIHkgPSBjb2VyY2UoJ3knKTtcbiAgICB2YXIgeiA9IGNvZXJjZSgneicpO1xuXG4gICAgaWYoXG4gICAgICAgICF1IHx8ICF1Lmxlbmd0aCB8fCAhdiB8fCAhdi5sZW5ndGggfHwgIXcgfHwgIXcubGVuZ3RoIHx8XG4gICAgICAgICF4IHx8ICF4Lmxlbmd0aCB8fCAheSB8fCAheS5sZW5ndGggfHwgIXogfHwgIXoubGVuZ3RoXG4gICAgKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgnc3RhcnRzLngnKTtcbiAgICBjb2VyY2UoJ3N0YXJ0cy55Jyk7XG4gICAgY29lcmNlKCdzdGFydHMueicpO1xuXG4gICAgY29lcmNlKCdtYXhkaXNwbGF5ZWQnKTtcbiAgICBjb2VyY2UoJ3NpemVyZWYnKTtcblxuICAgIGNvZXJjZSgnbGlnaHRpbmcuYW1iaWVudCcpO1xuICAgIGNvZXJjZSgnbGlnaHRpbmcuZGlmZnVzZScpO1xuICAgIGNvZXJjZSgnbGlnaHRpbmcuc3BlY3VsYXInKTtcbiAgICBjb2VyY2UoJ2xpZ2h0aW5nLnJvdWdobmVzcycpO1xuICAgIGNvZXJjZSgnbGlnaHRpbmcuZnJlc25lbCcpO1xuICAgIGNvZXJjZSgnbGlnaHRwb3NpdGlvbi54Jyk7XG4gICAgY29lcmNlKCdsaWdodHBvc2l0aW9uLnknKTtcbiAgICBjb2VyY2UoJ2xpZ2h0cG9zaXRpb24ueicpO1xuXG4gICAgY29sb3JzY2FsZURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwge3ByZWZpeDogJycsIGNMZXR0ZXI6ICdjJ30pO1xuXG4gICAgY29lcmNlKCd0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGVtcGxhdGUnKTtcblxuICAgIC8vIGRpc2FibGUgMUQgdHJhbnNmb3JtcyAoZm9yIG5vdylcbiAgICAvLyB4L3kveiBhbmQgdS92L3cgaGF2ZSBtYXRjaGluZyBsZW5ndGhzLFxuICAgIC8vIGJ1dCB0aGV5IGRvbid0IGhhdmUgdG8gbWF0Y2ggd2l0aCBzdGFydHMuKHh8eXx6KVxuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBudWxsO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvZGVmYXVsdHNcIjo2MDMsXCIuLi8uLi9saWJcIjo3MTksXCIuL2F0dHJpYnV0ZXNcIjoxMjA5fV0sMTIxMzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3N0cmVhbXR1YmUnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9nbDNkJyksXG4gICAgY2F0ZWdvcmllczogWydnbDNkJ10sXG5cbiAgICBhdHRyaWJ1dGVzOiBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNvbG9yYmFyOiB7XG4gICAgICAgIG1pbjogJ2NtaW4nLFxuICAgICAgICBtYXg6ICdjbWF4J1xuICAgIH0sXG4gICAgY2FsYzogX2RlcmVxXygnLi9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9jb252ZXJ0JyksXG4gICAgZXZlbnREYXRhOiBmdW5jdGlvbihvdXQsIHB0KSB7XG4gICAgICAgIG91dC50dWJleCA9IG91dC54O1xuICAgICAgICBvdXQudHViZXkgPSBvdXQueTtcbiAgICAgICAgb3V0LnR1YmV6ID0gb3V0Lno7XG5cbiAgICAgICAgb3V0LnR1YmV1ID0gcHQudHJhY2VDb29yZGluYXRlWzNdO1xuICAgICAgICBvdXQudHViZXYgPSBwdC50cmFjZUNvb3JkaW5hdGVbNF07XG4gICAgICAgIG91dC50dWJldyA9IHB0LnRyYWNlQ29vcmRpbmF0ZVs1XTtcblxuICAgICAgICBvdXQubm9ybSA9IHB0LnRyYWNlQ29vcmRpbmF0ZVs2XTtcbiAgICAgICAgb3V0LmRpdmVyZ2VuY2UgPSBwdC50cmFjZUNvb3JkaW5hdGVbN107XG5cbiAgICAgICAgLy8gRG9lcyBub3QgY29ycmVzcG9uZCB0byBpbnB1dCB4L3kveiwgc28gZGVsZXRlIHRoZW1cbiAgICAgICAgZGVsZXRlIG91dC54O1xuICAgICAgICBkZWxldGUgb3V0Lnk7XG4gICAgICAgIGRlbGV0ZSBvdXQuejtcblxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH0sXG5cbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvZ2wzZFwiOjgwNyxcIi4vYXR0cmlidXRlc1wiOjEyMDksXCIuL2NhbGNcIjoxMjEwLFwiLi9jb252ZXJ0XCI6MTIxMSxcIi4vZGVmYXVsdHNcIjoxMjEyfV0sMTIxNDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBwbG90QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBkb21haW5BdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2RvbWFpbicpLmF0dHJpYnV0ZXM7XG52YXIgcGllQXR0cyA9IF9kZXJlcV8oJy4uL3BpZS9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGxhYmVsczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgcGFyZW50czoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB2YWx1ZXM6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGJyYW5jaHZhbHVlczoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogWydyZW1haW5kZXInLCAndG90YWwnXSxcbiAgICAgICAgZGZsdDogJ3JlbWFpbmRlcicsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbGV2ZWw6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgIGFuaW06IHRydWUsXG4gICAgICAgIFxuICAgICAgICBcbiAgICB9LFxuICAgIG1heGRlcHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdpbnRlZ2VyJyxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgXG4gICAgICAgIGRmbHQ6IC0xLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbWFya2VyOiB7XG4gICAgICAgIGNvbG9yczoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIC8vIGNvbG9yaW5oZXJpdGFuY2U6IHtcbiAgICAgICAgLy8gICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgLy8gICAgIHZhbHVlczogWydwZXItYnJhbmNoJywgJ3Blci1sYWJlbCcsIGZhbHNlXVxuICAgICAgICAvLyB9LFxuXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIGNvbG9yOiBleHRlbmRGbGF0KHt9LCBwaWVBdHRzLm1hcmtlci5saW5lLmNvbG9yLCB7XG4gICAgICAgICAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgd2lkdGg6IGV4dGVuZEZsYXQoe30sIHBpZUF0dHMubWFya2VyLmxpbmUud2lkdGgsIHtkZmx0OiAxfSksXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYydcbiAgICB9LFxuXG4gICAgbGVhZjoge1xuICAgICAgICBvcGFjaXR5OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAwLjcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgIH0sXG5cbiAgICB0ZXh0OiBwaWVBdHRzLnRleHQsXG4gICAgdGV4dGluZm86IGV4dGVuZEZsYXQoe30sIHBpZUF0dHMudGV4dGluZm8sIHtcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgZmxhZ3M6IFsnbGFiZWwnLCAndGV4dCcsICd2YWx1ZSddXG4gICAgfSksXG4gICAgdGV4dGZvbnQ6IHBpZUF0dHMudGV4dGZvbnQsXG5cbiAgICBob3ZlcnRleHQ6IHBpZUF0dHMuaG92ZXJ0ZXh0LFxuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgcGxvdEF0dHJzLmhvdmVyaW5mbywge1xuICAgICAgICBmbGFnczogWydsYWJlbCcsICd0ZXh0JywgJ3ZhbHVlJywgJ25hbWUnXVxuICAgIH0pLFxuICAgIGhvdmVydGVtcGxhdGU6IGhvdmVydGVtcGxhdGVBdHRycygpLFxuXG4gICAgaW5zaWRldGV4dGZvbnQ6IHBpZUF0dHMuaW5zaWRldGV4dGZvbnQsXG4gICAgb3V0c2lkZXRleHRmb250OiBwaWVBdHRzLm91dHNpZGV0ZXh0Zm9udCxcblxuICAgIGRvbWFpbjogZG9tYWluQXR0cnMoe25hbWU6ICdzdW5idXJzdCcsIHRyYWNlOiB0cnVlLCBlZGl0VHlwZTogJ2NhbGMnfSlcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXNcIjo2MzEsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NCxcIi4uLy4uL3Bsb3RzL2RvbWFpblwiOjc5MixcIi4uL3BpZS9hdHRyaWJ1dGVzXCI6MTA4Nn1dLDEyMTU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIGdldE1vZHVsZUNhbGNEYXRhID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2V0X2RhdGEnKS5nZXRNb2R1bGVDYWxjRGF0YTtcblxudmFyIG5hbWUgPSBleHBvcnRzLm5hbWUgPSAnc3VuYnVyc3QnO1xuXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbihnZCwgdHJhY2VzLCB0cmFuc2l0aW9uT3B0cywgbWFrZU9uQ29tcGxldGVDYWxsYmFjaykge1xuICAgIHZhciBfbW9kdWxlID0gUmVnaXN0cnkuZ2V0TW9kdWxlKG5hbWUpO1xuICAgIHZhciBjZG1vZHVsZSA9IGdldE1vZHVsZUNhbGNEYXRhKGdkLmNhbGNkYXRhLCBfbW9kdWxlKVswXTtcbiAgICBfbW9kdWxlLnBsb3QoZ2QsIGNkbW9kdWxlLCB0cmFuc2l0aW9uT3B0cywgbWFrZU9uQ29tcGxldGVDYWxsYmFjayk7XG59O1xuXG5leHBvcnRzLmNsZWFuID0gZnVuY3Rpb24obmV3RnVsbERhdGEsIG5ld0Z1bGxMYXlvdXQsIG9sZEZ1bGxEYXRhLCBvbGRGdWxsTGF5b3V0KSB7XG4gICAgdmFyIGhhZCA9IChvbGRGdWxsTGF5b3V0Ll9oYXMgJiYgb2xkRnVsbExheW91dC5faGFzKG5hbWUpKTtcbiAgICB2YXIgaGFzID0gKG5ld0Z1bGxMYXlvdXQuX2hhcyAmJiBuZXdGdWxsTGF5b3V0Ll9oYXMobmFtZSkpO1xuXG4gICAgaWYoaGFkICYmICFoYXMpIHtcbiAgICAgICAgb2xkRnVsbExheW91dC5fc3VuYnVyc3RsYXllci5zZWxlY3RBbGwoJ2cudHJhY2UnKS5yZW1vdmUoKTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2dldF9kYXRhXCI6ODAyLFwiLi4vLi4vcmVnaXN0cnlcIjo4NDd9XSwxMjE2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzSGllcmFyY2h5ID0gX2RlcmVxXygnZDMtaGllcmFyY2h5Jyk7XG52YXIgaXNOdW1lcmljID0gX2RlcmVxXygnZmFzdC1pc251bWVyaWMnKTtcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIG1ha2VQdWxsQ29sb3JGbiA9IF9kZXJlcV8oJy4uL3BpZS9jYWxjJykubWFrZVB1bGxDb2xvckZuO1xudmFyIGdlbmVyYXRlRXh0ZW5kZWRDb2xvcnMgPSBfZGVyZXFfKCcuLi9waWUvY2FsYycpLmdlbmVyYXRlRXh0ZW5kZWRDb2xvcnM7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gTGliLmlzQXJyYXlPclR5cGVkQXJyYXk7XG5cbnZhciBzdW5idXJzdEV4dGVuZGVkQ29sb3JXYXlzID0ge307XG5cbmV4cG9ydHMuY2FsYyA9IGZ1bmN0aW9uKGdkLCB0cmFjZSkge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG4gICAgdmFyIGlkcyA9IHRyYWNlLmlkcztcbiAgICB2YXIgaGFzSWRzID0gaXNBcnJheU9yVHlwZWRBcnJheShpZHMpO1xuICAgIHZhciBsYWJlbHMgPSB0cmFjZS5sYWJlbHM7XG4gICAgdmFyIHBhcmVudHMgPSB0cmFjZS5wYXJlbnRzO1xuICAgIHZhciB2YWxzID0gdHJhY2UudmFsdWVzO1xuICAgIHZhciBoYXNWYWxzID0gaXNBcnJheU9yVHlwZWRBcnJheSh2YWxzKTtcbiAgICB2YXIgY2QgPSBbXTtcblxuICAgIHZhciBwYXJlbnQyY2hpbGRyZW4gPSB7fTtcbiAgICB2YXIgcmVmcyA9IHt9O1xuICAgIHZhciBhZGRUb0xvb2t1cCA9IGZ1bmN0aW9uKHBhcmVudCwgdikge1xuICAgICAgICBpZihwYXJlbnQyY2hpbGRyZW5bcGFyZW50XSkgcGFyZW50MmNoaWxkcmVuW3BhcmVudF0ucHVzaCh2KTtcbiAgICAgICAgZWxzZSBwYXJlbnQyY2hpbGRyZW5bcGFyZW50XSA9IFt2XTtcbiAgICAgICAgcmVmc1t2XSA9IDE7XG4gICAgfTtcblxuICAgIC8vIHRyZWF0IG51bWJlciBgMGAgYXMgdmFsaWRcbiAgICB2YXIgaXNWYWxpZEtleSA9IGZ1bmN0aW9uKGspIHtcbiAgICAgICAgcmV0dXJuIGsgfHwgdHlwZW9mIGsgPT09ICdudW1iZXInO1xuICAgIH07XG5cbiAgICB2YXIgaXNWYWxpZFZhbCA9IGZ1bmN0aW9uKGkpIHtcbiAgICAgICAgcmV0dXJuICFoYXNWYWxzIHx8IChpc051bWVyaWModmFsc1tpXSkgJiYgdmFsc1tpXSA+PSAwKTtcbiAgICB9O1xuXG4gICAgdmFyIGxlbjtcbiAgICB2YXIgaXNWYWxpZDtcbiAgICB2YXIgZ2V0SWQ7XG5cbiAgICBpZihoYXNJZHMpIHtcbiAgICAgICAgbGVuID0gTWF0aC5taW4oaWRzLmxlbmd0aCwgcGFyZW50cy5sZW5ndGgpO1xuICAgICAgICBpc1ZhbGlkID0gZnVuY3Rpb24oaSkgeyByZXR1cm4gaXNWYWxpZEtleShpZHNbaV0pICYmIGlzVmFsaWRWYWwoaSk7IH07XG4gICAgICAgIGdldElkID0gZnVuY3Rpb24oaSkgeyByZXR1cm4gU3RyaW5nKGlkc1tpXSk7IH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbGVuID0gTWF0aC5taW4obGFiZWxzLmxlbmd0aCwgcGFyZW50cy5sZW5ndGgpO1xuICAgICAgICBpc1ZhbGlkID0gZnVuY3Rpb24oaSkgeyByZXR1cm4gaXNWYWxpZEtleShsYWJlbHNbaV0pICYmIGlzVmFsaWRWYWwoaSk7IH07XG4gICAgICAgIC8vIFRPRE8gV2UgY291bGQgYWxsb3cgc29tZSBsYWJlbCAvIHBhcmVudCBkdXBsaWNhdGlvblxuICAgICAgICAvL1xuICAgICAgICAvLyBGcm9tIEFKOlxuICAgICAgICAvLyAgSXQgd291bGQgd29yayBPSyBmb3Igb25lIGxldmVsXG4gICAgICAgIC8vICAobXVsdGlwbGUgcm93cyB3aXRoIHRoZSBzYW1lIG5hbWUgYW5kIGRpZmZlcmVudCBwYXJlbnRzIC1cbiAgICAgICAgLy8gIG9yIGV2ZW4gdGhlIHNhbWUgcGFyZW50KSBidXQgaWYgdGhhdCBuYW1lIGlzIHRoZW4gdXNlZCBhcyBhIHBhcmVudFxuICAgICAgICAvLyAgd2hpY2ggb25lIGlzIGl0P1xuICAgICAgICBnZXRJZCA9IGZ1bmN0aW9uKGkpIHsgcmV0dXJuIFN0cmluZyhsYWJlbHNbaV0pOyB9O1xuICAgIH1cblxuICAgIGlmKGhhc1ZhbHMpIGxlbiA9IE1hdGgubWluKGxlbiwgdmFscy5sZW5ndGgpO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGlmKGlzVmFsaWQoaSkpIHtcbiAgICAgICAgICAgIHZhciBpZCA9IGdldElkKGkpO1xuICAgICAgICAgICAgdmFyIHBpZCA9IGlzVmFsaWRLZXkocGFyZW50c1tpXSkgPyBTdHJpbmcocGFyZW50c1tpXSkgOiAnJztcblxuICAgICAgICAgICAgdmFyIGNkaSA9IHtcbiAgICAgICAgICAgICAgICBpOiBpLFxuICAgICAgICAgICAgICAgIGlkOiBpZCxcbiAgICAgICAgICAgICAgICBwaWQ6IHBpZCxcbiAgICAgICAgICAgICAgICBsYWJlbDogaXNWYWxpZEtleShsYWJlbHNbaV0pID8gU3RyaW5nKGxhYmVsc1tpXSkgOiAnJ1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYoaGFzVmFscykgY2RpLnYgPSArdmFsc1tpXTtcbiAgICAgICAgICAgIGNkLnB1c2goY2RpKTtcbiAgICAgICAgICAgIGFkZFRvTG9va3VwKHBpZCwgaWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoIXBhcmVudDJjaGlsZHJlblsnJ10pIHtcbiAgICAgICAgdmFyIGltcGxpZWRSb290cyA9IFtdO1xuICAgICAgICB2YXIgaztcbiAgICAgICAgZm9yKGsgaW4gcGFyZW50MmNoaWxkcmVuKSB7XG4gICAgICAgICAgICBpZighcmVmc1trXSkge1xuICAgICAgICAgICAgICAgIGltcGxpZWRSb290cy5wdXNoKGspO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gaWYgYW4gYGlkYCBoYXMgbm8gcmVmIGluIHRoZSBgcGFyZW50c2AgYXJyYXksXG4gICAgICAgIC8vIHRha2UgaXQgYXMgYmVpbmcgdGhlIHJvb3Qgbm9kZVxuXG4gICAgICAgIGlmKGltcGxpZWRSb290cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIGsgPSBpbXBsaWVkUm9vdHNbMF07XG4gICAgICAgICAgICBjZC51bnNoaWZ0KHtcbiAgICAgICAgICAgICAgICBpZDogayxcbiAgICAgICAgICAgICAgICBwaWQ6ICcnLFxuICAgICAgICAgICAgICAgIGxhYmVsOiBrXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBMaWIud2FybignTXVsdGlwbGUgaW1wbGllZCByb290cywgY2Fubm90IGJ1aWxkIHN1bmJ1cnN0IGhpZXJhcmNoeS4nKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZihwYXJlbnQyY2hpbGRyZW5bJyddLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdmFyIGR1bW15SWQgPSBMaWIucmFuZHN0cigpO1xuXG4gICAgICAgIC8vIGlmIG11bHRpcGxlIHJvd3MgbGlua2VkIHRvIHRoZSByb290IG5vZGUsXG4gICAgICAgIC8vIGFkZCBkdW1teSBcInJvb3Qgb2Ygcm9vdHNcIiBub2RlIHRvIG1ha2UgZDMgYnVpbGQgdGhlIGhpZXJhcmNoeSBzdWNjZXNzZnVsbHlcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2QubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKGNkW2pdLnBpZCA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICBjZFtqXS5waWQgPSBkdW1teUlkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY2QudW5zaGlmdCh7XG4gICAgICAgICAgICBoYXNNdWx0aXBsZVJvb3RzOiB0cnVlLFxuICAgICAgICAgICAgaWQ6IGR1bW15SWQsXG4gICAgICAgICAgICBwaWQ6ICcnXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIFRPRE8gbWlnaHQgYmUgYmV0dGVyIHRvIHJlcGxhY2Ugc3RyYXRpZnkoKSB3aXRoIG91ciBvd24gYWxnb3JpdGhtXG4gICAgdmFyIHJvb3Q7XG4gICAgdHJ5IHtcbiAgICAgICAgcm9vdCA9IGQzSGllcmFyY2h5LnN0cmF0aWZ5KClcbiAgICAgICAgICAgIC5pZChmdW5jdGlvbihkKSB7IHJldHVybiBkLmlkOyB9KVxuICAgICAgICAgICAgLnBhcmVudElkKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQucGlkOyB9KShjZCk7XG4gICAgfSBjYXRjaChlKSB7XG4gICAgICAgIHJldHVybiBMaWIud2FybignRmFpbGVkIHRvIGJ1aWxkIHN1bmJ1cnN0IGhpZXJhcmNoeS4gRXJyb3I6ICcgKyBlLm1lc3NhZ2UpO1xuICAgIH1cblxuICAgIHZhciBoaWVyYXJjaHkgPSBkM0hpZXJhcmNoeS5oaWVyYXJjaHkocm9vdCk7XG4gICAgdmFyIGZhaWxlZCA9IGZhbHNlO1xuXG4gICAgaWYoaGFzVmFscykge1xuICAgICAgICBzd2l0Y2godHJhY2UuYnJhbmNodmFsdWVzKSB7XG4gICAgICAgICAgICBjYXNlICdyZW1haW5kZXInOlxuICAgICAgICAgICAgICAgIGhpZXJhcmNoeS5zdW0oZnVuY3Rpb24oZCkgeyByZXR1cm4gZC5kYXRhLnY7IH0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndG90YWwnOlxuICAgICAgICAgICAgICAgIGhpZXJhcmNoeS5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHYgPSBkLmRhdGEuZGF0YS52O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGQuY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwYXJ0aWFsU3VtID0gZC5jaGlsZHJlbi5yZWR1Y2UoZnVuY3Rpb24oYSwgYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhICsgYy5kYXRhLmRhdGEudjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYodiA8IHBhcnRpYWxTdW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBMaWIud2FybihbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdUb3RhbCB2YWx1ZSBmb3Igbm9kZScsIGQuZGF0YS5kYXRhLmlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnaXMgc21hbGxlciB0aGFuIHRoZSBzdW0gb2YgaXRzIGNoaWxkcmVuLidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdLmpvaW4oJyAnKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBkLnZhbHVlID0gdjtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGhpZXJhcmNoeS5jb3VudCgpO1xuICAgIH1cblxuICAgIGlmKGZhaWxlZCkgcmV0dXJuO1xuXG4gICAgLy8gVE9ETyBhZGQgd2F5IHRvIHNvcnQgYnkgaGVpZ2h0IGFsc28/XG4gICAgaGllcmFyY2h5LnNvcnQoZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYi52YWx1ZSAtIGEudmFsdWU7IH0pO1xuXG4gICAgdmFyIGNvbG9ycyA9IHRyYWNlLm1hcmtlci5jb2xvcnMgfHwgW107XG4gICAgdmFyIHB1bGxDb2xvciA9IG1ha2VQdWxsQ29sb3JGbihmdWxsTGF5b3V0Ll9zdW5idXJzdGNvbG9ybWFwKTtcblxuICAgIC8vIFRPRE8ga2VlcCB0cmFjayBvZiAncm9vdC1jaGlsZHJlbicgKGkuZS4gYnJhbmNoKSBmb3IgaG92ZXIgaW5mbyBldGMuXG5cbiAgICBoaWVyYXJjaHkuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBjZGkgPSBkLmRhdGEuZGF0YTtcbiAgICAgICAgdmFyIGlkID0gY2RpLmlkO1xuICAgICAgICAvLyBOLkIuIHRoaXMgbXV0YXRlcyBpdGVtcyBpbiBgY2RgXG4gICAgICAgIGNkaS5jb2xvciA9IHB1bGxDb2xvcihjb2xvcnNbY2RpLmldLCBpZCk7XG4gICAgfSk7XG5cbiAgICBjZFswXS5oaWVyYXJjaHkgPSBoaWVyYXJjaHk7XG5cbiAgICByZXR1cm4gY2Q7XG59O1xuXG4vKlxuICogYGNhbGNgIGZpbGxlZCBpbiAoYW5kIGNvbGxhdGVkKSBleHBsaWNpdCBjb2xvcnMuXG4gKiBOb3cgd2UgbmVlZCB0byBwcm9wYWdhdGUgdGhlc2UgZXhwbGljaXQgY29sb3JzIHRvIG90aGVyIHRyYWNlcyxcbiAqIGFuZCBmaWxsIGluIGRlZmF1bHQgY29sb3JzLlxuICogVGhpcyBpcyBkb25lIGFmdGVyIHNvcnRpbmcsIHNvIHdlIHBpY2sgZGVmYXVsdHNcbiAqIGluIHRoZSBvcmRlciBzbGljZXMgd2lsbCBiZSBkaXNwbGF5ZWRcbiAqL1xuZXhwb3J0cy5jcm9zc1RyYWNlQ2FsYyA9IGZ1bmN0aW9uKGdkKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgY2FsY2RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgY29sb3JXYXkgPSBmdWxsTGF5b3V0LnN1bmJ1cnN0Y29sb3J3YXk7XG4gICAgdmFyIGNvbG9yTWFwID0gZnVsbExheW91dC5fc3VuYnVyc3Rjb2xvcm1hcDtcblxuICAgIGlmKGZ1bGxMYXlvdXQuZXh0ZW5kc3VuYnVyc3Rjb2xvcnMpIHtcbiAgICAgICAgY29sb3JXYXkgPSBnZW5lcmF0ZUV4dGVuZGVkQ29sb3JzKGNvbG9yV2F5LCBzdW5idXJzdEV4dGVuZGVkQ29sb3JXYXlzKTtcbiAgICB9XG4gICAgdmFyIGRmbHRDb2xvckNvdW50ID0gMDtcblxuICAgIGZ1bmN0aW9uIHBpY2tDb2xvcihkKSB7XG4gICAgICAgIHZhciBjZGkgPSBkLmRhdGEuZGF0YTtcbiAgICAgICAgdmFyIGlkID0gY2RpLmlkO1xuXG4gICAgICAgIGlmKGNkaS5jb2xvciA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGlmKGNvbG9yTWFwW2lkXSkge1xuICAgICAgICAgICAgICAgIC8vIGhhdmUgd2Ugc2VlbiB0aGlzIGxhYmVsIGFuZCBhc3NpZ25lZCBhIGNvbG9yIHRvIGl0IGluIGEgcHJldmlvdXMgdHJhY2U/XG4gICAgICAgICAgICAgICAgY2RpLmNvbG9yID0gY29sb3JNYXBbaWRdO1xuICAgICAgICAgICAgfSBlbHNlIGlmKGQucGFyZW50KSB7XG4gICAgICAgICAgICAgICAgaWYoZC5wYXJlbnQucGFyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGZyb20gdGhpcmQtbGV2ZWwgb24sIGluaGVyaXQgZnJvbSBwYXJlbnRcbiAgICAgICAgICAgICAgICAgICAgY2RpLmNvbG9yID0gZC5wYXJlbnQuZGF0YS5kYXRhLmNvbG9yO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHBpY2sgbmV3IGNvbG9yIGZvciBzZWNvbmQgbGV2ZWxcbiAgICAgICAgICAgICAgICAgICAgY29sb3JNYXBbaWRdID0gY2RpLmNvbG9yID0gY29sb3JXYXlbZGZsdENvbG9yQ291bnQgJSBjb2xvcldheS5sZW5ndGhdO1xuICAgICAgICAgICAgICAgICAgICBkZmx0Q29sb3JDb3VudCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gcm9vdCBnZXRzIG5vIGNvbG9yaW5nIGJ5IGRlZmF1bHRcbiAgICAgICAgICAgICAgICBjZGkuY29sb3IgPSAncmdiYSgwLDAsMCwwKSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2FsY2RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkID0gY2FsY2RhdGFbaV07XG4gICAgICAgIHZhciBjZDAgPSBjZFswXTtcbiAgICAgICAgaWYoY2QwLnRyYWNlLnR5cGUgPT09ICdzdW5idXJzdCcgJiYgY2QwLmhpZXJhcmNoeSkge1xuICAgICAgICAgICAgY2QwLmhpZXJhcmNoeS5lYWNoKHBpY2tDb2xvcik7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL3BpZS9jYWxjXCI6MTA4OCxcImQzLWhpZXJhcmNoeVwiOjE1NyxcImZhc3QtaXNudW1lcmljXCI6MjI1fV0sMTIxNzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIENMSUNLX1RSQU5TSVRJT05fVElNRTogNzUwLFxuICAgIENMSUNLX1RSQU5TSVRJT05fRUFTSU5HOiAnbGluZWFyJ1xufTtcblxufSx7fV0sMTIxODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG52YXIgaGFuZGxlRG9tYWluRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9kb21haW4nKS5kZWZhdWx0cztcbnZhciBoYW5kbGVUZXh0ID0gX2RlcmVxXygnLi4vYmFyL2RlZmF1bHRzJykuaGFuZGxlVGV4dDtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxhYmVscyA9IGNvZXJjZSgnbGFiZWxzJyk7XG4gICAgdmFyIHBhcmVudHMgPSBjb2VyY2UoJ3BhcmVudHMnKTtcblxuICAgIGlmKCFsYWJlbHMgfHwgIWxhYmVscy5sZW5ndGggfHwgIXBhcmVudHMgfHwgIXBhcmVudHMubGVuZ3RoKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciB2YWxzID0gY29lcmNlKCd2YWx1ZXMnKTtcbiAgICBpZih2YWxzICYmIHZhbHMubGVuZ3RoKSBjb2VyY2UoJ2JyYW5jaHZhbHVlcycpO1xuXG4gICAgY29lcmNlKCdsZXZlbCcpO1xuICAgIGNvZXJjZSgnbWF4ZGVwdGgnKTtcblxuICAgIHZhciBsaW5lV2lkdGggPSBjb2VyY2UoJ21hcmtlci5saW5lLndpZHRoJyk7XG4gICAgaWYobGluZVdpZHRoKSBjb2VyY2UoJ21hcmtlci5saW5lLmNvbG9yJywgbGF5b3V0LnBhcGVyX2JnY29sb3IpO1xuXG4gICAgY29lcmNlKCdtYXJrZXIuY29sb3JzJyk7XG5cbiAgICBjb2VyY2UoJ2xlYWYub3BhY2l0eScpO1xuXG4gICAgdmFyIHRleHQgPSBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ3RleHRpbmZvJywgQXJyYXkuaXNBcnJheSh0ZXh0KSA/ICd0ZXh0K2xhYmVsJyA6ICdsYWJlbCcpO1xuXG4gICAgY29lcmNlKCdob3ZlcnRleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGVtcGxhdGUnKTtcblxuICAgIHZhciB0ZXh0cG9zaXRpb24gPSAnYXV0byc7XG4gICAgaGFuZGxlVGV4dCh0cmFjZUluLCB0cmFjZU91dCwgbGF5b3V0LCBjb2VyY2UsIHRleHRwb3NpdGlvbiwge1xuICAgICAgICBtb2R1bGVIYXNTZWxlY3RlZDogZmFsc2UsXG4gICAgICAgIG1vZHVsZUhhc1Vuc2VsZWN0ZWQ6IGZhbHNlLFxuICAgICAgICBtb2R1bGVIYXNDb25zdHJhaW46IGZhbHNlLFxuICAgICAgICBtb2R1bGVIYXNDbGlwb25heGlzOiBmYWxzZSxcbiAgICAgICAgbW9kdWxlSGFzVGV4dGFuZ2xlOiBmYWxzZSxcbiAgICAgICAgbW9kdWxlSGFzSW5zaWRlYW5jaG9yOiBmYWxzZVxuICAgIH0pO1xuXG4gICAgaGFuZGxlRG9tYWluRGVmYXVsdHModHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcblxuICAgIC8vIGRvIG5vdCBzdXBwb3J0IHRyYW5zZm9ybXMgZm9yIG5vd1xuICAgIHRyYWNlT3V0Ll9sZW5ndGggPSBudWxsO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9kb21haW5cIjo3OTIsXCIuLi9iYXIvZGVmYXVsdHNcIjo4NjEsXCIuL2F0dHJpYnV0ZXNcIjoxMjE0fV0sMTIxOTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3N1bmJ1cnN0JyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi9iYXNlX3Bsb3QnKSxcbiAgICBjYXRlZ29yaWVzOiBbXSxcbiAgICBhbmltYXRhYmxlOiB0cnVlLFxuXG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgbGF5b3V0QXR0cmlidXRlczogX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgc3VwcGx5TGF5b3V0RGVmYXVsdHM6IF9kZXJlcV8oJy4vbGF5b3V0X2RlZmF1bHRzJyksXG5cbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKS5jYWxjLFxuICAgIGNyb3NzVHJhY2VDYWxjOiBfZGVyZXFfKCcuL2NhbGMnKS5jcm9zc1RyYWNlQ2FsYyxcblxuICAgIHBsb3Q6IF9kZXJlcV8oJy4vcGxvdCcpLFxuICAgIHN0eWxlOiBfZGVyZXFfKCcuL3N0eWxlJykuc3R5bGUsXG5cbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi9hdHRyaWJ1dGVzXCI6MTIxNCxcIi4vYmFzZV9wbG90XCI6MTIxNSxcIi4vY2FsY1wiOjEyMTYsXCIuL2RlZmF1bHRzXCI6MTIxOCxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjoxMjIwLFwiLi9sYXlvdXRfZGVmYXVsdHNcIjoxMjIxLFwiLi9wbG90XCI6MTIyMixcIi4vc3R5bGVcIjoxMjIzfV0sMTIyMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN1bmJ1cnN0Y29sb3J3YXk6IHtcbiAgICAgICAgdmFsVHlwZTogJ2NvbG9ybGlzdCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGV4dGVuZHN1bmJ1cnN0Y29sb3JzOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se31dLDEyMjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGF5b3V0SW4sIGxheW91dE91dCwgbGF5b3V0QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuICAgIGNvZXJjZSgnc3VuYnVyc3Rjb2xvcndheScsIGxheW91dE91dC5jb2xvcndheSk7XG4gICAgY29lcmNlKCdleHRlbmRzdW5idXJzdGNvbG9ycycpO1xufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6MTIyMH1dLDEyMjI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIGQzSGllcmFyY2h5ID0gX2RlcmVxXygnZDMtaGllcmFyY2h5Jyk7XG5cbnZhciBSZWdpc3RyeSA9IF9kZXJlcV8oJy4uLy4uL3JlZ2lzdHJ5Jyk7XG52YXIgRnggPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2Z4Jyk7XG52YXIgQ29sb3IgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEV2ZW50cyA9IF9kZXJlcV8oJy4uLy4uL2xpYi9ldmVudHMnKTtcbnZhciBzdmdUZXh0VXRpbHMgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3ZnX3RleHRfdXRpbHMnKTtcbnZhciBzZXRDdXJzb3IgPSBfZGVyZXFfKCcuLi8uLi9saWIvc2V0Y3Vyc29yJyk7XG52YXIgYXBwZW5kQXJyYXlQb2ludFZhbHVlID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9oZWxwZXJzJykuYXBwZW5kQXJyYXlQb2ludFZhbHVlO1xuXG52YXIgdHJhbnNmb3JtSW5zaWRlVGV4dCA9IF9kZXJlcV8oJy4uL3BpZS9wbG90JykudHJhbnNmb3JtSW5zaWRlVGV4dDtcbnZhciBmb3JtYXRQaWVWYWx1ZSA9IF9kZXJlcV8oJy4uL3BpZS9oZWxwZXJzJykuZm9ybWF0UGllVmFsdWU7XG52YXIgc3R5bGVPbmUgPSBfZGVyZXFfKCcuL3N0eWxlJykuc3R5bGVPbmU7XG5cbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGdkLCBjZG1vZHVsZSwgdHJhbnNpdGlvbk9wdHMsIG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2spIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBsYXllciA9IGZ1bGxMYXlvdXQuX3N1bmJ1cnN0bGF5ZXI7XG4gICAgdmFyIGpvaW4sIG9uQ29tcGxldGU7XG5cbiAgICAvLyBJZiB0cmFuc2l0aW9uIGNvbmZpZyBpcyBwcm92aWRlZCwgdGhlbiBpdCBpcyBvbmx5IGEgcGFydGlhbCByZXBsb3QgYW5kIHRyYWNlcyBub3RcbiAgICAvLyB1cGRhdGVkIGFyZSByZW1vdmVkLlxuICAgIHZhciBpc0Z1bGxSZXBsb3QgPSAhdHJhbnNpdGlvbk9wdHM7XG4gICAgdmFyIGhhc1RyYW5zaXRpb24gPSB0cmFuc2l0aW9uT3B0cyAmJiB0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbiA+IDA7XG5cbiAgICBqb2luID0gbGF5ZXIuc2VsZWN0QWxsKCdnLnRyYWNlLnN1bmJ1cnN0JylcbiAgICAgICAgLmRhdGEoY2Rtb2R1bGUsIGZ1bmN0aW9uKGNkKSB7IHJldHVybiBjZFswXS50cmFjZS51aWQ7IH0pO1xuXG4gICAgLy8gdXNpbmcgc2FtZSAnc3Ryb2tlLWxpbmVqb2luJyBhcyBwaWUgdHJhY2VzXG4gICAgam9pbi5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCd0cmFjZScsIHRydWUpXG4gICAgICAgIC5jbGFzc2VkKCdzdW5idXJzdCcsIHRydWUpXG4gICAgICAgIC5hdHRyKCdzdHJva2UtbGluZWpvaW4nLCAncm91bmQnKTtcblxuICAgIGpvaW4ub3JkZXIoKTtcblxuICAgIGlmKGhhc1RyYW5zaXRpb24pIHtcbiAgICAgICAgaWYobWFrZU9uQ29tcGxldGVDYWxsYmFjaykge1xuICAgICAgICAgICAgLy8gSWYgaXQgd2FzIHBhc3NlZCBhIGNhbGxiYWNrIHRvIHJlZ2lzdGVyIGNvbXBsZXRpb24sIG1ha2UgYSBjYWxsYmFjay4gSWZcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgY3JlYXRlZCwgdGhlbiBpdCBtdXN0IGJlIGV4ZWN1dGVkIG9uIGNvbXBsZXRpb24sIG90aGVyd2lzZSB0aGVcbiAgICAgICAgICAgIC8vIHBvcy10cmFuc2l0aW9uIHJlZHJhdyB3aWxsIG5vdCBleGVjdXRlOlxuICAgICAgICAgICAgb25Db21wbGV0ZSA9IG1ha2VPbkNvbXBsZXRlQ2FsbGJhY2soKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0cmFuc2l0aW9uID0gZDMudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAuZHVyYXRpb24odHJhbnNpdGlvbk9wdHMuZHVyYXRpb24pXG4gICAgICAgICAgICAuZWFzZSh0cmFuc2l0aW9uT3B0cy5lYXNpbmcpXG4gICAgICAgICAgICAuZWFjaCgnZW5kJywgZnVuY3Rpb24oKSB7IG9uQ29tcGxldGUgJiYgb25Db21wbGV0ZSgpOyB9KVxuICAgICAgICAgICAgLmVhY2goJ2ludGVycnVwdCcsIGZ1bmN0aW9uKCkgeyBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUoKTsgfSk7XG5cbiAgICAgICAgdHJhbnNpdGlvbi5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgLy8gTXVzdCBydW4gdGhlIHNlbGVjdGlvbiBhZ2FpbiBzaW5jZSBvdGhlcndpc2UgZW50ZXJzL3VwZGF0ZXMgZ2V0IGdyb3VwZWQgdG9nZXRoZXJcbiAgICAgICAgICAgIC8vIGFuZCB0aGVzZSBnZXQgZXhlY3V0ZWQgb3V0IG9mIG9yZGVyLiBFeGNlcHQgd2UgbmVlZCB0aGVtIGluIG9yZGVyIVxuICAgICAgICAgICAgbGF5ZXIuc2VsZWN0QWxsKCdnLnRyYWNlJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICAgICAgICAgIHBsb3RPbmUoZ2QsIGNkLCB0aGlzLCB0cmFuc2l0aW9uT3B0cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgam9pbi5lYWNoKGZ1bmN0aW9uKGNkKSB7XG4gICAgICAgICAgICBwbG90T25lKGdkLCBjZCwgdGhpcywgdHJhbnNpdGlvbk9wdHMpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpZihpc0Z1bGxSZXBsb3QpIHtcbiAgICAgICAgam9pbi5leGl0KCkucmVtb3ZlKCk7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gcGxvdE9uZShnZCwgY2QsIGVsZW1lbnQsIHRyYW5zaXRpb25PcHRzKSB7XG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICAvLyBXZSBjb3VsZCBvcHRpbWl6ZSBoYXNUcmFuc2l0aW9uIHBlciB0cmFjZSxcbiAgICAvLyBhcyBzdW5idXJzdCBoYXMgbm8gY3Jvc3MtdHJhY2UgbG9naWMhXG4gICAgdmFyIGhhc1RyYW5zaXRpb24gPSB0cmFuc2l0aW9uT3B0cyAmJiB0cmFuc2l0aW9uT3B0cy5kdXJhdGlvbiA+IDA7XG5cbiAgICB2YXIgZ1RyYWNlID0gZDMuc2VsZWN0KGVsZW1lbnQpO1xuICAgIHZhciBzbGljZXMgPSBnVHJhY2Uuc2VsZWN0QWxsKCdnLnNsaWNlJyk7XG5cbiAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgdmFyIHRyYWNlID0gY2QwLnRyYWNlO1xuICAgIHZhciBoaWVyYXJjaHkgPSBjZDAuaGllcmFyY2h5O1xuICAgIHZhciBlbnRyeSA9IGZpbmRFbnRyeVdpdGhMZXZlbChoaWVyYXJjaHksIHRyYWNlLmxldmVsKTtcbiAgICB2YXIgbWF4RGVwdGggPSB0cmFjZS5tYXhkZXB0aCA+PSAwID8gdHJhY2UubWF4ZGVwdGggOiBJbmZpbml0eTtcblxuICAgIHZhciBncyA9IGZ1bGxMYXlvdXQuX3NpemU7XG4gICAgdmFyIGRvbWFpbiA9IHRyYWNlLmRvbWFpbjtcbiAgICB2YXIgdnB3ID0gZ3MudyAqIChkb21haW4ueFsxXSAtIGRvbWFpbi54WzBdKTtcbiAgICB2YXIgdnBoID0gZ3MuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKTtcbiAgICB2YXIgck1heCA9IDAuNSAqIE1hdGgubWluKHZwdywgdnBoKTtcbiAgICB2YXIgY3ggPSBjZDAuY3ggPSBncy5sICsgZ3MudyAqIChkb21haW4ueFsxXSArIGRvbWFpbi54WzBdKSAvIDI7XG4gICAgdmFyIGN5ID0gY2QwLmN5ID0gZ3MudCArIGdzLmggKiAoMSAtIGRvbWFpbi55WzBdKSAtIHZwaCAvIDI7XG5cbiAgICBpZighZW50cnkpIHtcbiAgICAgICAgcmV0dXJuIHNsaWNlcy5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICAvLyBwcmV2aW91cyByb290ICdwdCcgKGNhbiBiZSBlbXB0eSlcbiAgICB2YXIgcHJldkVudHJ5ID0gbnVsbDtcbiAgICAvLyBzdGFzaCBvZiAncHJldmlvdXMnIHBvc2l0aW9uIGRhdGEgdXNlZCBieSB0d2VlbmluZyBmdW5jdGlvbnNcbiAgICB2YXIgcHJldkxvb2t1cCA9IHt9O1xuXG4gICAgaWYoaGFzVHJhbnNpdGlvbikge1xuICAgICAgICAvLyBJbXBvcnRhbnQ6IGRvIHRoaXMgYmVmb3JlIGJpbmRpbmcgbmV3IHNsaWNlRGF0YSFcbiAgICAgICAgc2xpY2VzLmVhY2goZnVuY3Rpb24ocHQpIHtcbiAgICAgICAgICAgIHByZXZMb29rdXBbZ2V0UHRJZChwdCldID0ge1xuICAgICAgICAgICAgICAgIHJweDA6IHB0LnJweDAsXG4gICAgICAgICAgICAgICAgcnB4MTogcHQucnB4MSxcbiAgICAgICAgICAgICAgICB4MDogcHQueDAsXG4gICAgICAgICAgICAgICAgeDE6IHB0LngxLFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcHQudHJhbnNmb3JtXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZighcHJldkVudHJ5ICYmIGlzRW50cnkocHQpKSB7XG4gICAgICAgICAgICAgICAgcHJldkVudHJ5ID0gcHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIE4uQi4gc2xpY2UgZGF0YSBpc24ndCB0aGUgY2FsY2RhdGEsXG4gICAgLy8gZ3JhYiBjb3JyZXNwb25kaW5nIGNhbGNkYXRhIGl0ZW0gaW4gc2xpY2VEYXRhW2ldLmRhdGEuZGF0YVxuICAgIHZhciBzbGljZURhdGEgPSBwYXJ0aXRpb24oZW50cnkpLmRlc2NlbmRhbnRzKCk7XG4gICAgdmFyIG1heEhlaWdodCA9IGVudHJ5LmhlaWdodCArIDE7XG4gICAgdmFyIHlPZmZzZXQgPSAwO1xuICAgIHZhciBjdXRvZmYgPSBtYXhEZXB0aDtcblxuICAgIC8vIE4uQi4gaGFuZGxlIG11bHRpcGxlLXJvb3Qgc3BlY2lhbCBjYXNlXG4gICAgaWYoY2QwLmhhc011bHRpcGxlUm9vdHMgJiYgaXNIaWVyYWNoeVJvb3QoZW50cnkpKSB7XG4gICAgICAgIHNsaWNlRGF0YSA9IHNsaWNlRGF0YS5zbGljZSgxKTtcbiAgICAgICAgbWF4SGVpZ2h0IC09IDE7XG4gICAgICAgIHlPZmZzZXQgPSAxO1xuICAgICAgICBjdXRvZmYgKz0gMTtcbiAgICB9XG5cbiAgICAvLyBmaWx0ZXIgb3V0IHNsaWNlcyB0aGF0IHdvbid0IHNob3cgdXAgb24gZ3JhcGhcbiAgICBzbGljZURhdGEgPSBzbGljZURhdGEuZmlsdGVyKGZ1bmN0aW9uKHB0KSB7IHJldHVybiBwdC55MSA8PSBjdXRvZmY7IH0pO1xuXG4gICAgLy8gcGFydGl0aW9uIHNwYW4gKCd5JykgdG8gc2VjdG9yIHJhZGlhbCBweCB2YWx1ZVxuICAgIHZhciBtYXhZID0gTWF0aC5taW4obWF4SGVpZ2h0LCBtYXhEZXB0aCk7XG4gICAgdmFyIHkycnB4ID0gZnVuY3Rpb24oeSkgeyByZXR1cm4gKHkgLSB5T2Zmc2V0KSAvIG1heFkgKiByTWF4OyB9O1xuICAgIC8vIChyYWRpYWwgcHggdmFsdWUsIHBhcnRpdGlvbiBhbmdsZSAoJ3gnKSkgIHRvIHB4IFt4LHldXG4gICAgdmFyIHJ4MnB4ID0gZnVuY3Rpb24ociwgeCkgeyByZXR1cm4gW3IgKiBNYXRoLmNvcyh4KSwgLXIgKiBNYXRoLnNpbih4KV07IH07XG4gICAgLy8gc2xpY2UgcGF0aCBnZW5lcmF0aW9uIGZuXG4gICAgdmFyIHBhdGhTbGljZSA9IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIExpYi5wYXRoQW5udWx1cyhkLnJweDAsIGQucnB4MSwgZC54MCwgZC54MSwgY3gsIGN5KTsgfTtcbiAgICAvLyBzbGljZSB0ZXh0IHRyYW5zbGF0ZSB4L3lcbiAgICB2YXIgdHJhbnNUZXh0WCA9IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGN4ICsgZC5weG1pZFswXSAqIGQudHJhbnNmb3JtLnJDZW50ZXIgKyAoZC50cmFuc2Zvcm0ueCB8fCAwKTsgfTtcbiAgICB2YXIgdHJhbnNUZXh0WSA9IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGN5ICsgZC5weG1pZFsxXSAqIGQudHJhbnNmb3JtLnJDZW50ZXIgKyAoZC50cmFuc2Zvcm0ueSB8fCAwKTsgfTtcblxuICAgIHNsaWNlcyA9IHNsaWNlcy5kYXRhKHNsaWNlRGF0YSwgZnVuY3Rpb24ocHQpIHsgcmV0dXJuIGdldFB0SWQocHQpOyB9KTtcblxuICAgIHNsaWNlcy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKCdzbGljZScsIHRydWUpO1xuXG4gICAgaWYoaGFzVHJhbnNpdGlvbikge1xuICAgICAgICBzbGljZXMuZXhpdCgpLnRyYW5zaXRpb24oKVxuICAgICAgICAgICAgLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNsaWNlVG9wID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHNsaWNlUGF0aCA9IHNsaWNlVG9wLnNlbGVjdCgncGF0aC5zdXJmYWNlJyk7XG4gICAgICAgICAgICAgICAgc2xpY2VQYXRoLnRyYW5zaXRpb24oKS5hdHRyVHdlZW4oJ2QnLCBmdW5jdGlvbihwdDIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGludGVycCA9IG1ha2VFeGl0U2xpY2VJbnRlcnBvbGF0b3IocHQyKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHsgcmV0dXJuIHBhdGhTbGljZShpbnRlcnAodCkpOyB9O1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIHNsaWNlVGV4dEdyb3VwID0gc2xpY2VUb3Auc2VsZWN0KCdnLnNsaWNldGV4dCcpO1xuICAgICAgICAgICAgICAgIHNsaWNlVGV4dEdyb3VwLmF0dHIoJ29wYWNpdHknLCAwKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAucmVtb3ZlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc2xpY2VzLmV4aXQoKS5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICBzbGljZXMub3JkZXIoKTtcblxuICAgIC8vIG5leHQgeDEgKGkuZS4gc2VjdG9yIGVuZCBhbmdsZSkgb2YgcHJldmlvdXMgZW50cnlcbiAgICB2YXIgbmV4dFgxb2ZQcmV2RW50cnkgPSBudWxsO1xuICAgIGlmKGhhc1RyYW5zaXRpb24gJiYgcHJldkVudHJ5KSB7XG4gICAgICAgIHZhciBwcmV2RW50cnlJZCA9IGdldFB0SWQocHJldkVudHJ5KTtcbiAgICAgICAgc2xpY2VzLmVhY2goZnVuY3Rpb24ocHQpIHtcbiAgICAgICAgICAgIGlmKG5leHRYMW9mUHJldkVudHJ5ID09PSBudWxsICYmIChnZXRQdElkKHB0KSA9PT0gcHJldkVudHJ5SWQpKSB7XG4gICAgICAgICAgICAgICAgbmV4dFgxb2ZQcmV2RW50cnkgPSBwdC54MTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIHVwZGF0ZVNsaWNlcyA9IHNsaWNlcztcbiAgICBpZihoYXNUcmFuc2l0aW9uKSB7XG4gICAgICAgIHVwZGF0ZVNsaWNlcyA9IHVwZGF0ZVNsaWNlcy50cmFuc2l0aW9uKCkuZWFjaCgnZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBOLkIuIGdkLl90cmFuc2l0aW9uaW5nIGlzIChzdGlsbCkgKnRydWUqIGJ5IHRoZSB0aW1lXG4gICAgICAgICAgICAvLyB0cmFuc2l0aW9uIHVwZGF0ZXMgZ2V0IGhhcmVcbiAgICAgICAgICAgIHZhciBzbGljZVRvcCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIHNldFNsaWNlQ3Vyc29yKHNsaWNlVG9wLCBnZCwge2lzVHJhbnNpdGlvbmluZzogZmFsc2V9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdXBkYXRlU2xpY2VzLmVhY2goZnVuY3Rpb24ocHQpIHtcbiAgICAgICAgdmFyIHNsaWNlVG9wID0gZDMuc2VsZWN0KHRoaXMpO1xuXG4gICAgICAgIHZhciBzbGljZVBhdGggPSBMaWIuZW5zdXJlU2luZ2xlKHNsaWNlVG9wLCAncGF0aCcsICdzdXJmYWNlJywgZnVuY3Rpb24ocykge1xuICAgICAgICAgICAgcy5zdHlsZSgncG9pbnRlci1ldmVudHMnLCAnYWxsJyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHB0LnJweDAgPSB5MnJweChwdC55MCk7XG4gICAgICAgIHB0LnJweDEgPSB5MnJweChwdC55MSk7XG4gICAgICAgIHB0LnhtaWQgPSAocHQueDAgKyBwdC54MSkgLyAyO1xuICAgICAgICBwdC5weG1pZCA9IHJ4MnB4KHB0LnJweDEsIHB0LnhtaWQpO1xuICAgICAgICBwdC5taWRhbmdsZSA9IC0ocHQueG1pZCAtIE1hdGguUEkgLyAyKTtcbiAgICAgICAgcHQuaGFsZmFuZ2xlID0gMC41ICogTWF0aC5taW4oTGliLmFuZ2xlRGVsdGEocHQueDAsIHB0LngxKSB8fCBNYXRoLlBJLCBNYXRoLlBJKTtcbiAgICAgICAgcHQucmluZyA9IDEgLSAocHQucnB4MCAvIHB0LnJweDEpO1xuICAgICAgICBwdC5ySW5zY3JpYmVkID0gZ2V0SW5zY3JpYmVkUmFkaXVzRnJhY3Rpb24ocHQsIHRyYWNlKTtcblxuICAgICAgICBpZihoYXNUcmFuc2l0aW9uKSB7XG4gICAgICAgICAgICBzbGljZVBhdGgudHJhbnNpdGlvbigpLmF0dHJUd2VlbignZCcsIGZ1bmN0aW9uKHB0Mikge1xuICAgICAgICAgICAgICAgIHZhciBpbnRlcnAgPSBtYWtlVXBkYXRlU2xpY2VJbnRlcG9sYXRvcihwdDIpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih0KSB7IHJldHVybiBwYXRoU2xpY2UoaW50ZXJwKHQpKTsgfTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2xpY2VQYXRoLmF0dHIoJ2QnLCBwYXRoU2xpY2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2xpY2VUb3BcbiAgICAgICAgICAgIC5jYWxsKGF0dGFjaEZ4SGFuZGxlcnMsIGdkLCBjZClcbiAgICAgICAgICAgIC5jYWxsKHNldFNsaWNlQ3Vyc29yLCBnZCwge2lzVHJhbnNpdGlvbmluZzogZ2QuX3RyYW5zaXRpb25pbmd9KTtcblxuICAgICAgICBzbGljZVBhdGguY2FsbChzdHlsZU9uZSwgcHQsIHRyYWNlKTtcblxuICAgICAgICB2YXIgc2xpY2VUZXh0R3JvdXAgPSBMaWIuZW5zdXJlU2luZ2xlKHNsaWNlVG9wLCAnZycsICdzbGljZXRleHQnKTtcbiAgICAgICAgdmFyIHNsaWNlVGV4dCA9IExpYi5lbnN1cmVTaW5nbGUoc2xpY2VUZXh0R3JvdXAsICd0ZXh0JywgJycsIGZ1bmN0aW9uKHMpIHtcbiAgICAgICAgICAgIC8vIHByb2hpYml0IHRleCBpbnRlcnByZXRhdGlvbiB1bnRpbCB3ZSBjYW4gaGFuZGxlXG4gICAgICAgICAgICAvLyB0ZXggYW5kIHJlZ3VsYXIgdGV4dCB0b2dldGhlclxuICAgICAgICAgICAgcy5hdHRyKCdkYXRhLW5vdGV4JywgMSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNsaWNlVGV4dC50ZXh0KGZvcm1hdFNsaWNlTGFiZWwocHQsIHRyYWNlLCBmdWxsTGF5b3V0KSlcbiAgICAgICAgICAgIC5jbGFzc2VkKCdzbGljZXRleHQnLCB0cnVlKVxuICAgICAgICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpXG4gICAgICAgICAgICAuY2FsbChEcmF3aW5nLmZvbnQsIGlzSGllcmFjaHlSb290KHB0KSA/XG4gICAgICAgICAgICAgIGRldGVybWluZU91dHNpZGVUZXh0Rm9udCh0cmFjZSwgcHQsIGZ1bGxMYXlvdXQuZm9udCkgOlxuICAgICAgICAgICAgICBkZXRlcm1pbmVJbnNpZGVUZXh0Rm9udCh0cmFjZSwgcHQsIGZ1bGxMYXlvdXQuZm9udCkpXG4gICAgICAgICAgICAuY2FsbChzdmdUZXh0VXRpbHMuY29udmVydFRvVHNwYW5zLCBnZCk7XG5cbiAgICAgICAgLy8gcG9zaXRpb24gdGhlIHRleHQgcmVsYXRpdmUgdG8gdGhlIHNsaWNlXG4gICAgICAgIHZhciB0ZXh0QkIgPSBEcmF3aW5nLmJCb3goc2xpY2VUZXh0Lm5vZGUoKSk7XG4gICAgICAgIHB0LnRyYW5zZm9ybSA9IHRyYW5zZm9ybUluc2lkZVRleHQodGV4dEJCLCBwdCwgY2QwKTtcbiAgICAgICAgcHQudHJhbnNsYXRlWCA9IHRyYW5zVGV4dFgocHQpO1xuICAgICAgICBwdC50cmFuc2xhdGVZID0gdHJhbnNUZXh0WShwdCk7XG5cbiAgICAgICAgdmFyIHN0clRyYW5zZm9ybSA9IGZ1bmN0aW9uKGQsIHRleHRCQikge1xuICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIGQudHJhbnNsYXRlWCArICcsJyArIGQudHJhbnNsYXRlWSArICcpJyArXG4gICAgICAgICAgICAgICAgKGQudHJhbnNmb3JtLnNjYWxlIDwgMSA/ICgnc2NhbGUoJyArIGQudHJhbnNmb3JtLnNjYWxlICsgJyknKSA6ICcnKSArXG4gICAgICAgICAgICAgICAgKGQudHJhbnNmb3JtLnJvdGF0ZSA/ICgncm90YXRlKCcgKyBkLnRyYW5zZm9ybS5yb3RhdGUgKyAnKScpIDogJycpICtcbiAgICAgICAgICAgICAgICAndHJhbnNsYXRlKCcgK1xuICAgICAgICAgICAgICAgICAgICAoLSh0ZXh0QkIubGVmdCArIHRleHRCQi5yaWdodCkgLyAyKSArICcsJyArXG4gICAgICAgICAgICAgICAgICAgICgtKHRleHRCQi50b3AgKyB0ZXh0QkIuYm90dG9tKSAvIDIpICtcbiAgICAgICAgICAgICAgICAnKSc7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYoaGFzVHJhbnNpdGlvbikge1xuICAgICAgICAgICAgc2xpY2VUZXh0LnRyYW5zaXRpb24oKS5hdHRyVHdlZW4oJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKHB0Mikge1xuICAgICAgICAgICAgICAgIHZhciBpbnRlcnAgPSBtYWtlVXBkYXRlVGV4dEludGVycG9sYXIocHQyKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24odCkgeyByZXR1cm4gc3RyVHJhbnNmb3JtKGludGVycCh0KSwgdGV4dEJCKTsgfTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2xpY2VUZXh0LmF0dHIoJ3RyYW5zZm9ybScsIHN0clRyYW5zZm9ybShwdCwgdGV4dEJCKSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGZ1bmN0aW9uIG1ha2VFeGl0U2xpY2VJbnRlcnBvbGF0b3IocHQpIHtcbiAgICAgICAgdmFyIGlkID0gZ2V0UHRJZChwdCk7XG4gICAgICAgIHZhciBwcmV2ID0gcHJldkxvb2t1cFtpZF07XG4gICAgICAgIHZhciBlbnRyeVByZXYgPSBwcmV2TG9va3VwW2dldFB0SWQoZW50cnkpXTtcbiAgICAgICAgdmFyIG5leHQ7XG5cbiAgICAgICAgaWYoZW50cnlQcmV2KSB7XG4gICAgICAgICAgICB2YXIgYSA9IHB0LngxID4gZW50cnlQcmV2LngxID8gMiAqIE1hdGguUEkgOiAwO1xuICAgICAgICAgICAgLy8gaWYgcHQgdG8gcmVtb3ZlOlxuICAgICAgICAgICAgLy8gLSBpZiAnYmVsb3cnIHdoZXJlIHRoZSByb290LW5vZGUgdXNlZCB0byBiZTogc2hyaW5rIGl0IHJhZGlhbGx5IGlud2FyZFxuICAgICAgICAgICAgLy8gLSBvdGhlcndpc2UsIGNvbGxhcHNlIGl0IGNsb2Nrd2lzZSBvciBjb3VudGVyY2xvY2t3aXNlIHdoaWNoIGV2ZXIgaXMgc2hvcnRlc3QgdG8gdGhldGE9MFxuICAgICAgICAgICAgbmV4dCA9IHB0LnJweDEgPCBlbnRyeVByZXYucnB4MSA/IHtycHgwOiAwLCBycHgxOiAwfSA6IHt4MDogYSwgeDE6IGF9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdGhpcyBoYXBwZW5zIHdoZW4gbWF4ZGVwdGggaXMgc2V0LCB3aGVuIGxlYXZlcyBtdXN0XG4gICAgICAgICAgICAvLyBiZSByZW1vdmVkIGFuZCB0aGUgcm9vdFB0IGlzIG5ldyAoaS5lLiBkb2VzIG5vdCBoYXZlIGEgJ3ByZXYnIG9iamVjdClcbiAgICAgICAgICAgIHZhciBwYXJlbnQ7XG4gICAgICAgICAgICB2YXIgcGFyZW50SWQgPSBnZXRQdElkKHB0LnBhcmVudCk7XG4gICAgICAgICAgICBzbGljZXMuZWFjaChmdW5jdGlvbihwdDIpIHtcbiAgICAgICAgICAgICAgICBpZihnZXRQdElkKHB0MikgPT09IHBhcmVudElkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnQgPSBwdDI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgcGFyZW50Q2hpbGRyZW4gPSBwYXJlbnQuY2hpbGRyZW47XG4gICAgICAgICAgICB2YXIgY2k7XG4gICAgICAgICAgICBwYXJlbnRDaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uKHB0MiwgaSkge1xuICAgICAgICAgICAgICAgIGlmKGdldFB0SWQocHQyKSA9PT0gaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNpID0gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHZhciBuID0gcGFyZW50Q2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIGludGVycCA9IGQzLmludGVycG9sYXRlKHBhcmVudC54MCwgcGFyZW50LngxKTtcbiAgICAgICAgICAgIG5leHQgPSB7XG4gICAgICAgICAgICAgICAgcnB4MDogck1heCwgcnB4MTogck1heCxcbiAgICAgICAgICAgICAgICB4MDogaW50ZXJwKGNpIC8gbiksIHgxOiBpbnRlcnAoKGNpICsgMSkgLyBuKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkMy5pbnRlcnBvbGF0ZShwcmV2LCBuZXh0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlVXBkYXRlU2xpY2VJbnRlcG9sYXRvcihwdCkge1xuICAgICAgICB2YXIgcHJldjAgPSBwcmV2TG9va3VwW2dldFB0SWQocHQpXTtcbiAgICAgICAgdmFyIHByZXY7XG4gICAgICAgIHZhciBuZXh0ID0ge3gwOiBwdC54MCwgeDE6IHB0LngxLCBycHgwOiBwdC5ycHgwLCBycHgxOiBwdC5ycHgxfTtcblxuICAgICAgICBpZihwcmV2MCkge1xuICAgICAgICAgICAgLy8gaWYgcHQgYWxyZWFkeSBvbiBncmFwaCwgdGhpcyBpcyBlYXN5XG4gICAgICAgICAgICBwcmV2ID0gcHJldjA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBmb3IgbmV3IHB0czpcbiAgICAgICAgICAgIGlmKHByZXZFbnRyeSkge1xuICAgICAgICAgICAgICAgIC8vIGlmIHRyYWNlIHdhcyB2aXNpYmxlIGJlZm9yZVxuICAgICAgICAgICAgICAgIGlmKHB0LnBhcmVudCkge1xuICAgICAgICAgICAgICAgICAgICBpZihuZXh0WDFvZlByZXZFbnRyeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgbmV3IGJyYW5jaCwgdHdpc3QgaXQgaW4gY2xvY2t3aXNlIG9yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb3VudGVyY2xvY2t3aXNlIHdoaWNoIGV2ZXIgaXMgc2hvcnRlciB0b1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRzIGZpbmFsIGFuZ2xlXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHB0LngxID4gbmV4dFgxb2ZQcmV2RW50cnkgPyAyICogTWF0aC5QSSA6IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2ID0ge3gwOiBhLCB4MTogYX07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBuZXcgbGVhZiAod2hlbiBtYXhkZXB0aCBpcyBzZXQpLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZ3JvdyBpdCByYWRpYWxseSBhbmQgYW5ndWxhcmx5IGZyb21cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0cyBwYXJlbnQgbm9kZVxuICAgICAgICAgICAgICAgICAgICAgICAgcHJldiA9IHtycHgwOiByTWF4LCBycHgxOiByTWF4fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIExpYi5leHRlbmRGbGF0KHByZXYsIGludGVycFgwWDFGcm9tUGFyZW50KHB0KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiBuZXcgcm9vdC1ub2RlLCBncm93IGl0IHJhZGlhbGx5XG4gICAgICAgICAgICAgICAgICAgIHByZXYgPSB7cnB4MDogMCwgcnB4MTogMH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBzdGFydCBzZWN0b3Igb2YgbmV3IHRyYWNlcyBmcm9tIHRoZXRhPTBcbiAgICAgICAgICAgICAgICBwcmV2ID0ge3gwOiAwLCB4MTogMH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZDMuaW50ZXJwb2xhdGUocHJldiwgbmV4dCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFrZVVwZGF0ZVRleHRJbnRlcnBvbGFyKHB0KSB7XG4gICAgICAgIHZhciBwcmV2MCA9IHByZXZMb29rdXBbZ2V0UHRJZChwdCldO1xuICAgICAgICB2YXIgcHJldjtcbiAgICAgICAgdmFyIHRyYW5zZm9ybSA9IHB0LnRyYW5zZm9ybTtcblxuICAgICAgICBpZihwcmV2MCkge1xuICAgICAgICAgICAgcHJldiA9IHByZXYwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJldiA9IHtcbiAgICAgICAgICAgICAgICBycHgxOiBwdC5ycHgxLFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybToge1xuICAgICAgICAgICAgICAgICAgICBzY2FsZTogMCxcbiAgICAgICAgICAgICAgICAgICAgcm90YXRlOiB0cmFuc2Zvcm0ucm90YXRlLFxuICAgICAgICAgICAgICAgICAgICByQ2VudGVyOiB0cmFuc2Zvcm0uckNlbnRlcixcbiAgICAgICAgICAgICAgICAgICAgeDogdHJhbnNmb3JtLngsXG4gICAgICAgICAgICAgICAgICAgIHk6IHRyYW5zZm9ybS55XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gZm9yIG5ldyBwdHM6XG4gICAgICAgICAgICBpZihwcmV2RW50cnkpIHtcbiAgICAgICAgICAgICAgICAvLyBpZiB0cmFjZSB3YXMgdmlzaWJsZSBiZWZvcmVcbiAgICAgICAgICAgICAgICBpZihwdC5wYXJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYobmV4dFgxb2ZQcmV2RW50cnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIG5ldyBicmFuY2gsIHR3aXN0IGl0IGluIGNsb2Nrd2lzZSBvclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY291bnRlcmNsb2Nrd2lzZSB3aGljaCBldmVyIGlzIHNob3J0ZXIgdG9cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0cyBmaW5hbCBhbmdsZVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSBwdC54MSA+IG5leHRYMW9mUHJldkVudHJ5ID8gMiAqIE1hdGguUEkgOiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldi54MCA9IHByZXYueDEgPSBhO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgbGVhZlxuICAgICAgICAgICAgICAgICAgICAgICAgTGliLmV4dGVuZEZsYXQocHJldiwgaW50ZXJwWDBYMUZyb21QYXJlbnQocHQpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIG5ldyByb290LW5vZGVcbiAgICAgICAgICAgICAgICAgICAgcHJldi54MCA9IHByZXYueDEgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gb24gbmV3IHRyYWNlc1xuICAgICAgICAgICAgICAgIHByZXYueDAgPSBwcmV2LngxID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBycHgxRm4gPSBkMy5pbnRlcnBvbGF0ZShwcmV2LnJweDEsIHB0LnJweDEpO1xuICAgICAgICB2YXIgeDBGbiA9IGQzLmludGVycG9sYXRlKHByZXYueDAsIHB0LngwKTtcbiAgICAgICAgdmFyIHgxRm4gPSBkMy5pbnRlcnBvbGF0ZShwcmV2LngxLCBwdC54MSk7XG4gICAgICAgIHZhciBzY2FsZUZuID0gZDMuaW50ZXJwb2xhdGUocHJldi50cmFuc2Zvcm0uc2NhbGUsIHRyYW5zZm9ybS5zY2FsZSk7XG4gICAgICAgIHZhciByb3RhdGVGbiA9IGQzLmludGVycG9sYXRlKHByZXYudHJhbnNmb3JtLnJvdGF0ZSwgdHJhbnNmb3JtLnJvdGF0ZSk7XG5cbiAgICAgICAgLy8gc21vb3RoIG91dCBzdGFydC9lbmQgZnJvbSBlbnRyeSwgdG8gdHJ5IHRvIGtlZXAgdGV4dCBpbnNpZGUgc2VjdG9yXG4gICAgICAgIC8vIHdoaWxlIGtlZXBpbmcgdHJhbnNpdGlvbiBzbW9vdGhcbiAgICAgICAgdmFyIHBvdyA9IHRyYW5zZm9ybS5yQ2VudGVyID09PSAwID8gMyA6XG4gICAgICAgICAgICBwcmV2LnRyYW5zZm9ybS5yQ2VudGVyID09PSAwID8gMSAvIDMgOlxuICAgICAgICAgICAgMTtcbiAgICAgICAgdmFyIF9yQ2VudGVyRm4gPSBkMy5pbnRlcnBvbGF0ZShwcmV2LnRyYW5zZm9ybS5yQ2VudGVyLCB0cmFuc2Zvcm0uckNlbnRlcik7XG4gICAgICAgIHZhciByQ2VudGVyRm4gPSBmdW5jdGlvbih0KSB7IHJldHVybiBfckNlbnRlckZuKE1hdGgucG93KHQsIHBvdykpOyB9O1xuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICAgICAgICB2YXIgcnB4MSA9IHJweDFGbih0KTtcbiAgICAgICAgICAgIHZhciB4MCA9IHgwRm4odCk7XG4gICAgICAgICAgICB2YXIgeDEgPSB4MUZuKHQpO1xuICAgICAgICAgICAgdmFyIHJDZW50ZXIgPSByQ2VudGVyRm4odCk7XG5cbiAgICAgICAgICAgIHZhciBkID0ge1xuICAgICAgICAgICAgICAgIHB4bWlkOiByeDJweChycHgxLCAoeDAgKyB4MSkgLyAyKSxcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm06IHtcbiAgICAgICAgICAgICAgICAgICAgckNlbnRlcjogckNlbnRlcixcbiAgICAgICAgICAgICAgICAgICAgeDogdHJhbnNmb3JtLngsXG4gICAgICAgICAgICAgICAgICAgIHk6IHRyYW5zZm9ybS55XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdmFyIG91dCA9IHtcbiAgICAgICAgICAgICAgICBycHgxOiBycHgxRm4odCksXG4gICAgICAgICAgICAgICAgdHJhbnNsYXRlWDogdHJhbnNUZXh0WChkKSxcbiAgICAgICAgICAgICAgICB0cmFuc2xhdGVZOiB0cmFuc1RleHRZKGQpLFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybToge1xuICAgICAgICAgICAgICAgICAgICBzY2FsZTogc2NhbGVGbih0KSxcbiAgICAgICAgICAgICAgICAgICAgcm90YXRlOiByb3RhdGVGbih0KSxcbiAgICAgICAgICAgICAgICAgICAgckNlbnRlcjogckNlbnRlclxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJldHVybiBvdXQ7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW50ZXJwWDBYMUZyb21QYXJlbnQocHQpIHtcbiAgICAgICAgdmFyIHBhcmVudCA9IHB0LnBhcmVudDtcbiAgICAgICAgdmFyIHBhcmVudFByZXYgPSBwcmV2TG9va3VwW2dldFB0SWQocGFyZW50KV07XG4gICAgICAgIHZhciBvdXQgPSB7fTtcblxuICAgICAgICBpZihwYXJlbnRQcmV2KSB7XG4gICAgICAgICAgICAvLyBpZiBwYXJlbnQgaXMgdmlzaWJsZVxuICAgICAgICAgICAgdmFyIHBhcmVudENoaWxkcmVuID0gcGFyZW50LmNoaWxkcmVuO1xuICAgICAgICAgICAgdmFyIGNpID0gcGFyZW50Q2hpbGRyZW4uaW5kZXhPZihwdCk7XG4gICAgICAgICAgICB2YXIgbiA9IHBhcmVudENoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBpbnRlcnAgPSBkMy5pbnRlcnBvbGF0ZShwYXJlbnRQcmV2LngwLCBwYXJlbnRQcmV2LngxKTtcbiAgICAgICAgICAgIG91dC54MCA9IGludGVycChjaSAvIG4pO1xuICAgICAgICAgICAgb3V0LngxID0gaW50ZXJwKGNpIC8gbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB3L28gdmlzaWJsZSBwYXJlbnRcbiAgICAgICAgICAgIC8vIFRPRE8gISEhIEhPVyA/Pz9cbiAgICAgICAgICAgIG91dC54MCA9IG91dC54MSA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cbn1cblxuLy8geFswLTFdIGtleXMgYXJlIGFuZ2xlcyBbcmFkaWFuc11cbi8vIHlbMC0xXSBrZXlzIGFyZSBoaWVyYXJjaHkgaGVpZ2h0cyBbaW50ZWdlcnNdXG5mdW5jdGlvbiBwYXJ0aXRpb24oZW50cnkpIHtcbiAgICByZXR1cm4gZDNIaWVyYXJjaHkucGFydGl0aW9uKClcbiAgICAgICAgLnNpemUoWzIgKiBNYXRoLlBJLCBlbnRyeS5oZWlnaHQgKyAxXSkoZW50cnkpO1xufVxuXG5mdW5jdGlvbiBmaW5kRW50cnlXaXRoTGV2ZWwoaGllcmFyY2h5LCBsZXZlbCkge1xuICAgIHZhciBvdXQ7XG4gICAgaWYobGV2ZWwpIHtcbiAgICAgICAgaGllcmFyY2h5LmVhY2hBZnRlcihmdW5jdGlvbihwdCkge1xuICAgICAgICAgICAgaWYoZ2V0UHRJZChwdCkgPT09IGxldmVsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dCA9IHB0LmNvcHkoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBvdXQgfHwgaGllcmFyY2h5O1xufVxuXG5mdW5jdGlvbiBmaW5kRW50cnlXaXRoQ2hpbGQoaGllcmFyY2h5LCBjaGlsZElkKSB7XG4gICAgdmFyIG91dDtcbiAgICBoaWVyYXJjaHkuZWFjaEFmdGVyKGZ1bmN0aW9uKHB0KSB7XG4gICAgICAgIHZhciBjaGlsZHJlbiA9IHB0LmNoaWxkcmVuIHx8IFtdO1xuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgaWYoZ2V0UHRJZChjaGlsZCkgPT09IGNoaWxkSWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb3V0ID0gcHQuY29weSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG91dCB8fCBoaWVyYXJjaHk7XG59XG5cbmZ1bmN0aW9uIGlzSGllcmFjaHlSb290KHB0KSB7XG4gICAgdmFyIGNkaSA9IHB0LmRhdGEuZGF0YTtcbiAgICByZXR1cm4gY2RpLnBpZCA9PT0gJyc7XG59XG5cbmZ1bmN0aW9uIGlzRW50cnkocHQpIHtcbiAgICByZXR1cm4gIXB0LnBhcmVudDtcbn1cblxuZnVuY3Rpb24gaXNMZWFmKHB0KSB7XG4gICAgcmV0dXJuICFwdC5jaGlsZHJlbjtcbn1cblxuZnVuY3Rpb24gZ2V0UHRJZChwdCkge1xuICAgIHZhciBjZGkgPSBwdC5kYXRhLmRhdGE7XG4gICAgcmV0dXJuIGNkaS5pZDtcbn1cblxuZnVuY3Rpb24gc2V0U2xpY2VDdXJzb3Ioc2xpY2VUb3AsIGdkLCBvcHRzKSB7XG4gICAgdmFyIHB0ID0gc2xpY2VUb3AuZGF0dW0oKTtcbiAgICB2YXIgaXNUcmFuc2l0aW9uaW5nID0gKG9wdHMgfHwge30pLmlzVHJhbnNpdGlvbmluZztcbiAgICBzZXRDdXJzb3Ioc2xpY2VUb3AsIChpc1RyYW5zaXRpb25pbmcgfHwgaXNMZWFmKHB0KSB8fCBpc0hpZXJhY2h5Um9vdChwdCkpID8gbnVsbCA6ICdwb2ludGVyJyk7XG59XG5cbmZ1bmN0aW9uIGF0dGFjaEZ4SGFuZGxlcnMoc2xpY2VUb3AsIGdkLCBjZCkge1xuICAgIHZhciBjZDAgPSBjZFswXTtcbiAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG5cbiAgICAvLyBob3ZlciBzdGF0ZSB2YXJzXG4gICAgLy8gaGF2ZSB3ZSBkcmF3biBhIGhvdmVyIGxhYmVsLCBzbyBpdCBzaG91bGQgYmUgY2xlYXJlZCBsYXRlclxuICAgIGlmKCEoJ19oYXNIb3ZlckxhYmVsJyBpbiB0cmFjZSkpIHRyYWNlLl9oYXNIb3ZlckxhYmVsID0gZmFsc2U7XG4gICAgLy8gaGF2ZSB3ZSBlbWl0dGVkIGEgaG92ZXIgZXZlbnQsIHNvIGxhdGVyIGFuIHVuaG92ZXIgZXZlbnQgc2hvdWxkIGJlIGVtaXR0ZWRcbiAgICAvLyBub3RlIHRoYXQgY2xpY2sgZXZlbnRzIGRvIG5vdCBkZXBlbmQgb24gdGhpcyAtIHlvdSBjYW4gc3RpbGwgZ2V0IHRoZW1cbiAgICAvLyB3aXRoIGhvdmVybW9kZTogZmFsc2Ugb3IgaWYgeW91IHdlcmUgZWFybGllciBkcmFnZ2luZywgdGhlbiBjbGlja2VkXG4gICAgLy8gaW4gdGhlIHNhbWUgc2xpY2UgdGhhdCB5b3UgbW91c2VkIHVwIGluXG4gICAgaWYoISgnX2hhc0hvdmVyRXZlbnQnIGluIHRyYWNlKSkgdHJhY2UuX2hhc0hvdmVyRXZlbnQgPSBmYWxzZTtcblxuICAgIHNsaWNlVG9wLm9uKCdtb3VzZW92ZXInLCBmdW5jdGlvbihwdCkge1xuICAgICAgICB2YXIgZnVsbExheW91dE5vdyA9IGdkLl9mdWxsTGF5b3V0O1xuXG4gICAgICAgIGlmKGdkLl9kcmFnZ2luZyB8fCBmdWxsTGF5b3V0Tm93LmhvdmVybW9kZSA9PT0gZmFsc2UpIHJldHVybjtcblxuICAgICAgICB2YXIgdHJhY2VOb3cgPSBnZC5fZnVsbERhdGFbdHJhY2UuaW5kZXhdO1xuICAgICAgICB2YXIgY2RpID0gcHQuZGF0YS5kYXRhO1xuICAgICAgICB2YXIgcHROdW1iZXIgPSBjZGkuaTtcblxuICAgICAgICB2YXIgX2Nhc3QgPSBmdW5jdGlvbihhc3RyKSB7XG4gICAgICAgICAgICByZXR1cm4gTGliLmNhc3RPcHRpb24odHJhY2VOb3csIHB0TnVtYmVyLCBhc3RyKTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgaG92ZXJ0ZW1wbGF0ZSA9IF9jYXN0KCdob3ZlcnRlbXBsYXRlJyk7XG4gICAgICAgIHZhciBob3ZlcmluZm8gPSBGeC5jYXN0SG92ZXJpbmZvKHRyYWNlTm93LCBmdWxsTGF5b3V0Tm93LCBwdE51bWJlcik7XG4gICAgICAgIHZhciBzZXBhcmF0b3JzID0gZnVsbExheW91dE5vdy5zZXBhcmF0b3JzO1xuXG4gICAgICAgIGlmKGhvdmVydGVtcGxhdGUgfHwgKGhvdmVyaW5mbyAmJiBob3ZlcmluZm8gIT09ICdub25lJyAmJiBob3ZlcmluZm8gIT09ICdza2lwJykpIHtcbiAgICAgICAgICAgIHZhciBySW5zY3JpYmVkID0gcHQuckluc2NyaWJlZDtcbiAgICAgICAgICAgIHZhciBob3ZlckNlbnRlclggPSBjZDAuY3ggKyBwdC5weG1pZFswXSAqICgxIC0gckluc2NyaWJlZCk7XG4gICAgICAgICAgICB2YXIgaG92ZXJDZW50ZXJZID0gY2QwLmN5ICsgcHQucHhtaWRbMV0gKiAoMSAtIHJJbnNjcmliZWQpO1xuICAgICAgICAgICAgdmFyIGhvdmVyUHQgPSB7fTtcbiAgICAgICAgICAgIHZhciBwYXJ0cyA9IFtdO1xuICAgICAgICAgICAgdmFyIHRoaXNUZXh0ID0gW107XG4gICAgICAgICAgICB2YXIgaGFzRmxhZyA9IGZ1bmN0aW9uKGZsYWcpIHsgcmV0dXJuIHBhcnRzLmluZGV4T2YoZmxhZykgIT09IC0xOyB9O1xuXG4gICAgICAgICAgICBpZihob3ZlcmluZm8pIHtcbiAgICAgICAgICAgICAgICBwYXJ0cyA9IGhvdmVyaW5mbyA9PT0gJ2FsbCcgP1xuICAgICAgICAgICAgICAgICAgICB0cmFjZU5vdy5fbW9kdWxlLmF0dHJpYnV0ZXMuaG92ZXJpbmZvLmZsYWdzIDpcbiAgICAgICAgICAgICAgICAgICAgaG92ZXJpbmZvLnNwbGl0KCcrJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGhvdmVyUHQubGFiZWwgPSBjZGkubGFiZWw7XG4gICAgICAgICAgICBpZihoYXNGbGFnKCdsYWJlbCcpICYmIGhvdmVyUHQubGFiZWwpIHRoaXNUZXh0LnB1c2goaG92ZXJQdC5sYWJlbCk7XG5cbiAgICAgICAgICAgIGlmKGNkaS5oYXNPd25Qcm9wZXJ0eSgndicpKSB7XG4gICAgICAgICAgICAgICAgaG92ZXJQdC52YWx1ZSA9IGNkaS52O1xuICAgICAgICAgICAgICAgIGhvdmVyUHQudmFsdWVMYWJlbCA9IGZvcm1hdFBpZVZhbHVlKGhvdmVyUHQudmFsdWUsIHNlcGFyYXRvcnMpO1xuICAgICAgICAgICAgICAgIGlmKGhhc0ZsYWcoJ3ZhbHVlJykpIHRoaXNUZXh0LnB1c2goaG92ZXJQdC52YWx1ZUxhYmVsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaG92ZXJQdC50ZXh0ID0gX2Nhc3QoJ2hvdmVydGV4dCcpIHx8IF9jYXN0KCd0ZXh0Jyk7XG4gICAgICAgICAgICBpZihoYXNGbGFnKCd0ZXh0JykpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHggPSBob3ZlclB0LnRleHQ7XG4gICAgICAgICAgICAgICAgaWYoTGliLmlzVmFsaWRUZXh0VmFsdWUodHgpKSB0aGlzVGV4dC5wdXNoKHR4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRngubG9uZUhvdmVyKHtcbiAgICAgICAgICAgICAgICB0cmFjZTogdHJhY2VOb3csXG4gICAgICAgICAgICAgICAgeDA6IGhvdmVyQ2VudGVyWCAtIHJJbnNjcmliZWQgKiBwdC5ycHgxLFxuICAgICAgICAgICAgICAgIHgxOiBob3ZlckNlbnRlclggKyBySW5zY3JpYmVkICogcHQucnB4MSxcbiAgICAgICAgICAgICAgICB5OiBob3ZlckNlbnRlclksXG4gICAgICAgICAgICAgICAgaWRlYWxBbGlnbjogcHQucHhtaWRbMF0gPCAwID8gJ2xlZnQnIDogJ3JpZ2h0JyxcbiAgICAgICAgICAgICAgICB0ZXh0OiB0aGlzVGV4dC5qb2luKCc8YnI+JyksXG4gICAgICAgICAgICAgICAgbmFtZTogKGhvdmVydGVtcGxhdGUgfHwgaGFzRmxhZygnbmFtZScpKSA/IHRyYWNlTm93Lm5hbWUgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgY29sb3I6IF9jYXN0KCdob3ZlcmxhYmVsLmJnY29sb3InKSB8fCBjZGkuY29sb3IsXG4gICAgICAgICAgICAgICAgYm9yZGVyQ29sb3I6IF9jYXN0KCdob3ZlcmxhYmVsLmJvcmRlcmNvbG9yJyksXG4gICAgICAgICAgICAgICAgZm9udEZhbWlseTogX2Nhc3QoJ2hvdmVybGFiZWwuZm9udC5mYW1pbHknKSxcbiAgICAgICAgICAgICAgICBmb250U2l6ZTogX2Nhc3QoJ2hvdmVybGFiZWwuZm9udC5zaXplJyksXG4gICAgICAgICAgICAgICAgZm9udENvbG9yOiBfY2FzdCgnaG92ZXJsYWJlbC5mb250LmNvbG9yJyksXG4gICAgICAgICAgICAgICAgbmFtZUxlbmd0aDogX2Nhc3QoJ2hvdmVybGFiZWwubmFtZWxlbmd0aCcpLFxuICAgICAgICAgICAgICAgIHRleHRBbGlnbjogX2Nhc3QoJ2hvdmVybGFiZWwuYWxpZ24nKSxcbiAgICAgICAgICAgICAgICBob3ZlcnRlbXBsYXRlOiBob3ZlcnRlbXBsYXRlLFxuICAgICAgICAgICAgICAgIGhvdmVydGVtcGxhdGVMYWJlbHM6IGhvdmVyUHQsXG4gICAgICAgICAgICAgICAgZXZlbnREYXRhOiBbbWFrZUV2ZW50RGF0YShwdCwgdHJhY2VOb3cpXVxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lcjogZnVsbExheW91dE5vdy5faG92ZXJsYXllci5ub2RlKCksXG4gICAgICAgICAgICAgICAgb3V0ZXJDb250YWluZXI6IGZ1bGxMYXlvdXROb3cuX3BhcGVyLm5vZGUoKSxcbiAgICAgICAgICAgICAgICBnZDogZ2RcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0cmFjZS5faGFzSG92ZXJMYWJlbCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB0cmFjZS5faGFzSG92ZXJFdmVudCA9IHRydWU7XG4gICAgICAgIGdkLmVtaXQoJ3Bsb3RseV9ob3ZlcicsIHtcbiAgICAgICAgICAgIHBvaW50czogW21ha2VFdmVudERhdGEocHQsIHRyYWNlTm93KV0sXG4gICAgICAgICAgICBldmVudDogZDMuZXZlbnRcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBzbGljZVRvcC5vbignbW91c2VvdXQnLCBmdW5jdGlvbihldnQpIHtcbiAgICAgICAgdmFyIGZ1bGxMYXlvdXROb3cgPSBnZC5fZnVsbExheW91dDtcbiAgICAgICAgdmFyIHRyYWNlTm93ID0gZ2QuX2Z1bGxEYXRhW3RyYWNlLmluZGV4XTtcbiAgICAgICAgdmFyIHB0ID0gZDMuc2VsZWN0KHRoaXMpLmRhdHVtKCk7XG5cbiAgICAgICAgaWYodHJhY2UuX2hhc0hvdmVyRXZlbnQpIHtcbiAgICAgICAgICAgIGV2dC5vcmlnaW5hbEV2ZW50ID0gZDMuZXZlbnQ7XG4gICAgICAgICAgICBnZC5lbWl0KCdwbG90bHlfdW5ob3ZlcicsIHtcbiAgICAgICAgICAgICAgICBwb2ludHM6IFttYWtlRXZlbnREYXRhKHB0LCB0cmFjZU5vdyldLFxuICAgICAgICAgICAgICAgIGV2ZW50OiBkMy5ldmVudFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0cmFjZS5faGFzSG92ZXJFdmVudCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodHJhY2UuX2hhc0hvdmVyTGFiZWwpIHtcbiAgICAgICAgICAgIEZ4LmxvbmVVbmhvdmVyKGZ1bGxMYXlvdXROb3cuX2hvdmVybGF5ZXIubm9kZSgpKTtcbiAgICAgICAgICAgIHRyYWNlLl9oYXNIb3ZlckxhYmVsID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHNsaWNlVG9wLm9uKCdjbGljaycsIGZ1bmN0aW9uKHB0KSB7XG4gICAgICAgIC8vIFRPRE86IHRoaXMgZG9lcyBub3Qgc3VwcG9ydCByaWdodC1jbGljay4gSWYgd2Ugd2FudCB0byBzdXBwb3J0IGl0LCB3ZVxuICAgICAgICAvLyB3b3VsZCBsaWtlbHkgbmVlZCB0byBjaGFuZ2UgcGllIHRvIHVzZSBkcmFnRWxlbWVudCBpbnN0ZWFkIG9mIHN0cmFpZ2h0XG4gICAgICAgIC8vIG1hcGJveCBldmVudCBiaW5kaW5nLiBPciBwZXJoYXBzIGJldHRlciwgbWFrZSBhIHNpbXBsZSB3cmFwcGVyIHdpdGggdGhlXG4gICAgICAgIC8vIHJpZ2h0IG1vdXNlZG93biwgbW91c2Vtb3ZlLCBhbmQgbW91c2V1cCBoYW5kbGVycyBqdXN0IGZvciBhIGxlZnQvcmlnaHQgY2xpY2tcbiAgICAgICAgLy8gbWFwYm94IHdvdWxkIHVzZSB0aGlzIHRvby5cbiAgICAgICAgdmFyIGZ1bGxMYXlvdXROb3cgPSBnZC5fZnVsbExheW91dDtcbiAgICAgICAgdmFyIHRyYWNlTm93ID0gZ2QuX2Z1bGxEYXRhW3RyYWNlLmluZGV4XTtcblxuICAgICAgICB2YXIgY2xpY2tWYWwgPSBFdmVudHMudHJpZ2dlckhhbmRsZXIoZ2QsICdwbG90bHlfc3VuYnVyc3RjbGljaycsIHtcbiAgICAgICAgICAgIHBvaW50czogW21ha2VFdmVudERhdGEocHQsIHRyYWNlTm93KV0sXG4gICAgICAgICAgICBldmVudDogZDMuZXZlbnRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gJ3JlZ3VsYXInIGNsaWNrIGV2ZW50IHdoZW4gc3VuYnVyc3RjbGljayBpcyBkaXNhYmxlZCBvciB3aGVuXG4gICAgICAgIC8vIGNsaWtjaW4gb24gbGVhdmVzIG9yIHRoZSBoaWVyYXJjaHkgcm9vdFxuICAgICAgICBpZihjbGlja1ZhbCA9PT0gZmFsc2UgfHwgaXNMZWFmKHB0KSB8fCBpc0hpZXJhY2h5Um9vdChwdCkpIHtcbiAgICAgICAgICAgIGlmKGZ1bGxMYXlvdXROb3cuaG92ZXJtb2RlKSB7XG4gICAgICAgICAgICAgICAgZ2QuX2hvdmVyZGF0YSA9IFttYWtlRXZlbnREYXRhKHB0LCB0cmFjZU5vdyldO1xuICAgICAgICAgICAgICAgIEZ4LmNsaWNrKGdkLCBkMy5ldmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBza2lwIGlmIHRyaWdnZXJlZCBmcm9tIGRyYWdnaW5nIGEgbmVhcmJ5IGNhcnRlc2lhbiBzdWJwbG90XG4gICAgICAgIGlmKGdkLl9kcmFnZ2luZykgcmV0dXJuO1xuXG4gICAgICAgIC8vIHNraXAgZHVyaW5nIHRyYW5zaXRpb25zLCB0byBhdm9pZCBwb3RlbnRpYWwgYnVnc1xuICAgICAgICAvLyB3ZSBjb3VsZCByZW1vdmUgdGhpcyBjaGVjayBsYXRlclxuICAgICAgICBpZihnZC5fdHJhbnNpdGlvbmluZykgcmV0dXJuO1xuXG4gICAgICAgIC8vIHN0b3JlICdvbGQnIGxldmVsIGluIGd1aUVkaXQgc3Rhc2gsIHNvIHRoYXQgc3Vic2VxdWVudCBQbG90bHkucmVhY3RcbiAgICAgICAgLy8gY2FsbHMgd2l0aCB0aGUgc2FtZSB1aXJldmlzaW9uIGNhbiBzdGFydCBmcm9tIHRoZSBzYW1lIGVudHJ5XG4gICAgICAgIFJlZ2lzdHJ5LmNhbGwoJ19zdG9yZURpcmVjdEdVSUVkaXQnLCB0cmFjZU5vdywgZnVsbExheW91dE5vdy5fdHJhY2VQcmVHVUlbdHJhY2VOb3cudWlkXSwge2xldmVsOiB0cmFjZU5vdy5sZXZlbH0pO1xuXG4gICAgICAgIHZhciBoaWVyYXJjaHkgPSBjZDAuaGllcmFyY2h5O1xuICAgICAgICB2YXIgaWQgPSBnZXRQdElkKHB0KTtcbiAgICAgICAgdmFyIG5leHRFbnRyeSA9IGlzRW50cnkocHQpID9cbiAgICAgICAgICAgIGZpbmRFbnRyeVdpdGhDaGlsZChoaWVyYXJjaHksIGlkKSA6XG4gICAgICAgICAgICBmaW5kRW50cnlXaXRoTGV2ZWwoaGllcmFyY2h5LCBpZCk7XG5cbiAgICAgICAgdmFyIGZyYW1lID0ge1xuICAgICAgICAgICAgZGF0YTogW3tsZXZlbDogZ2V0UHRJZChuZXh0RW50cnkpfV0sXG4gICAgICAgICAgICB0cmFjZXM6IFt0cmFjZS5pbmRleF1cbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgYW5pbU9wdHMgPSB7XG4gICAgICAgICAgICBmcmFtZToge1xuICAgICAgICAgICAgICAgIHJlZHJhdzogZmFsc2UsXG4gICAgICAgICAgICAgICAgZHVyYXRpb246IGNvbnN0YW50cy5DTElDS19UUkFOU0lUSU9OX1RJTUVcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0cmFuc2l0aW9uOiB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb246IGNvbnN0YW50cy5DTElDS19UUkFOU0lUSU9OX1RJTUUsXG4gICAgICAgICAgICAgICAgZWFzaW5nOiBjb25zdGFudHMuQ0xJQ0tfVFJBTlNJVElPTl9FQVNJTkdcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtb2RlOiAnaW1tZWRpYXRlJyxcbiAgICAgICAgICAgIGZyb21jdXJyZW50OiB0cnVlXG4gICAgICAgIH07XG5cbiAgICAgICAgRngubG9uZVVuaG92ZXIoZnVsbExheW91dE5vdy5faG92ZXJsYXllci5ub2RlKCkpO1xuICAgICAgICBSZWdpc3RyeS5jYWxsKCdhbmltYXRlJywgZ2QsIGZyYW1lLCBhbmltT3B0cyk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIG1ha2VFdmVudERhdGEocHQsIHRyYWNlKSB7XG4gICAgdmFyIGNkaSA9IHB0LmRhdGEuZGF0YTtcblxuICAgIHZhciBvdXQgPSB7XG4gICAgICAgIGN1cnZlTnVtYmVyOiB0cmFjZS5pbmRleCxcbiAgICAgICAgcG9pbnROdW1iZXI6IGNkaS5pLFxuICAgICAgICBkYXRhOiB0cmFjZS5faW5wdXQsXG4gICAgICAgIGZ1bGxEYXRhOiB0cmFjZSxcblxuICAgICAgICAvLyBUT0RPIG1vcmUgdGhpbmdzIGxpa2UgJ2NoaWxkcmVuJywgJ3NpYmxpbmdzJywgJ2hpZXJhcmNoeT9cbiAgICB9O1xuXG4gICAgYXBwZW5kQXJyYXlQb2ludFZhbHVlKG91dCwgdHJhY2UsIGNkaS5pKTtcblxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFNsaWNlTGFiZWwocHQsIHRyYWNlLCBmdWxsTGF5b3V0KSB7XG4gICAgdmFyIHRleHRpbmZvID0gdHJhY2UudGV4dGluZm87XG5cbiAgICBpZighdGV4dGluZm8gfHwgdGV4dGluZm8gPT09ICdub25lJykge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgdmFyIGNkaSA9IHB0LmRhdGEuZGF0YTtcbiAgICB2YXIgc2VwYXJhdG9ycyA9IGZ1bGxMYXlvdXQuc2VwYXJhdG9ycztcbiAgICB2YXIgcGFydHMgPSB0ZXh0aW5mby5zcGxpdCgnKycpO1xuICAgIHZhciBoYXNGbGFnID0gZnVuY3Rpb24oZmxhZykgeyByZXR1cm4gcGFydHMuaW5kZXhPZihmbGFnKSAhPT0gLTE7IH07XG4gICAgdmFyIHRoaXNUZXh0ID0gW107XG5cbiAgICBpZihoYXNGbGFnKCdsYWJlbCcpICYmIGNkaS5sYWJlbCkgdGhpc1RleHQucHVzaChjZGkubGFiZWwpO1xuXG4gICAgaWYoY2RpLmhhc093blByb3BlcnR5KCd2JykgJiYgaGFzRmxhZygndmFsdWUnKSkge1xuICAgICAgICB0aGlzVGV4dC5wdXNoKGZvcm1hdFBpZVZhbHVlKGNkaS52LCBzZXBhcmF0b3JzKSk7XG4gICAgfVxuXG4gICAgaWYoaGFzRmxhZygndGV4dCcpKSB7XG4gICAgICAgIHZhciB0eCA9IExpYi5jYXN0T3B0aW9uKHRyYWNlLCBjZGkuaSwgJ3RleHQnKTtcbiAgICAgICAgaWYoTGliLmlzVmFsaWRUZXh0VmFsdWUodHgpKSB0aGlzVGV4dC5wdXNoKHR4KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpc1RleHQuam9pbignPGJyPicpO1xufVxuXG5mdW5jdGlvbiBkZXRlcm1pbmVPdXRzaWRlVGV4dEZvbnQodHJhY2UsIHB0LCBsYXlvdXRGb250KSB7XG4gICAgdmFyIGNkaSA9IHB0LmRhdGEuZGF0YTtcbiAgICB2YXIgcHROdW1iZXIgPSBjZGkuaTtcblxuICAgIHZhciBjb2xvciA9IExpYi5jYXN0T3B0aW9uKHRyYWNlLCBwdE51bWJlciwgJ291dHNpZGV0ZXh0Zm9udC5jb2xvcicpIHx8XG4gICAgICAgIExpYi5jYXN0T3B0aW9uKHRyYWNlLCBwdE51bWJlciwgJ3RleHRmb250LmNvbG9yJykgfHxcbiAgICAgICAgbGF5b3V0Rm9udC5jb2xvcjtcblxuICAgIHZhciBmYW1pbHkgPSBMaWIuY2FzdE9wdGlvbih0cmFjZSwgcHROdW1iZXIsICdvdXRzaWRldGV4dGZvbnQuZmFtaWx5JykgfHxcbiAgICAgICAgTGliLmNhc3RPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAndGV4dGZvbnQuZmFtaWx5JykgfHxcbiAgICAgICAgbGF5b3V0Rm9udC5mYW1pbHk7XG5cbiAgICB2YXIgc2l6ZSA9IExpYi5jYXN0T3B0aW9uKHRyYWNlLCBwdE51bWJlciwgJ291dHNpZGV0ZXh0Zm9udC5zaXplJykgfHxcbiAgICAgICAgTGliLmNhc3RPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAndGV4dGZvbnQuc2l6ZScpIHx8XG4gICAgICAgIGxheW91dEZvbnQuc2l6ZTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGNvbG9yOiBjb2xvcixcbiAgICAgICAgZmFtaWx5OiBmYW1pbHksXG4gICAgICAgIHNpemU6IHNpemVcbiAgICB9O1xufVxuXG5mdW5jdGlvbiBkZXRlcm1pbmVJbnNpZGVUZXh0Rm9udCh0cmFjZSwgcHQsIGxheW91dEZvbnQpIHtcbiAgICB2YXIgY2RpID0gcHQuZGF0YS5kYXRhO1xuICAgIHZhciBwdE51bWJlciA9IGNkaS5pO1xuXG4gICAgdmFyIGN1c3RvbUNvbG9yID0gTGliLmNhc3RPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnaW5zaWRldGV4dGZvbnQuY29sb3InKTtcbiAgICBpZighY3VzdG9tQ29sb3IgJiYgdHJhY2UuX2lucHV0LnRleHRmb250KSB7XG4gICAgICAgIC8vIFdoeSBub3Qgc2ltcGx5IHVzaW5nIHRyYWNlLnRleHRmb250PyBCZWNhdXNlIGlmIG5vdCBzZXQsIGl0XG4gICAgICAgIC8vIGRlZmF1bHRzIHRvIGxheW91dC5mb250IHdoaWNoIGhhcyBhIGRlZmF1bHQgY29sb3IuIEJ1dCBpZlxuICAgICAgICAvLyB0ZXh0Zm9udC5jb2xvciBhbmQgaW5zaWRldGV4dGZvbnQuY29sb3IgZG9uJ3Qgc3VwcGx5IGEgdmFsdWUsXG4gICAgICAgIC8vIGEgY29udHJhc3RpbmcgY29sb3Igc2hhbGwgYmUgdXNlZC5cbiAgICAgICAgY3VzdG9tQ29sb3IgPSBMaWIuY2FzdE9wdGlvbih0cmFjZS5faW5wdXQsIHB0TnVtYmVyLCAndGV4dGZvbnQuY29sb3InKTtcbiAgICB9XG5cbiAgICB2YXIgZmFtaWx5ID0gTGliLmNhc3RPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnaW5zaWRldGV4dGZvbnQuZmFtaWx5JykgfHxcbiAgICAgICAgTGliLmNhc3RPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAndGV4dGZvbnQuZmFtaWx5JykgfHxcbiAgICAgICAgbGF5b3V0Rm9udC5mYW1pbHk7XG5cbiAgICB2YXIgc2l6ZSA9IExpYi5jYXN0T3B0aW9uKHRyYWNlLCBwdE51bWJlciwgJ2luc2lkZXRleHRmb250LnNpemUnKSB8fFxuICAgICAgICBMaWIuY2FzdE9wdGlvbih0cmFjZSwgcHROdW1iZXIsICd0ZXh0Zm9udC5zaXplJykgfHxcbiAgICAgICAgbGF5b3V0Rm9udC5zaXplO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgY29sb3I6IGN1c3RvbUNvbG9yIHx8IENvbG9yLmNvbnRyYXN0KGNkaS5jb2xvciksXG4gICAgICAgIGZhbWlseTogZmFtaWx5LFxuICAgICAgICBzaXplOiBzaXplXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0SW5zY3JpYmVkUmFkaXVzRnJhY3Rpb24ocHQpIHtcbiAgICBpZihwdC5ycHgwID09PSAwICYmIExpYi5pc0Z1bGxDaXJjbGUoW3B0LngwLCBwdC54MV0pKSB7XG4gICAgICAgIC8vIHNwZWNpYWwgY2FzZSBvZiAxMDAlIHdpdGggbm8gaG9sZVxuICAgICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4oXG4gICAgICAgICAgICAxIC8gKDEgKyAxIC8gTWF0aC5zaW4ocHQuaGFsZmFuZ2xlKSksXG4gICAgICAgICAgICBwdC5yaW5nIC8gMlxuICAgICAgICApKTtcbiAgICB9XG59XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2NvbXBvbmVudHMvZnhcIjo2MzIsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hlbHBlcnNcIjo2MjgsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZXZlbnRzXCI6NzA5LFwiLi4vLi4vbGliL3NldGN1cnNvclwiOjczOSxcIi4uLy4uL2xpYi9zdmdfdGV4dF91dGlsc1wiOjc0MyxcIi4uLy4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi4vcGllL2hlbHBlcnNcIjoxMDkxLFwiLi4vcGllL3Bsb3RcIjoxMDk1LFwiLi9jb25zdGFudHNcIjoxMjE3LFwiLi9zdHlsZVwiOjEyMjMsXCJkM1wiOjE2MyxcImQzLWhpZXJhcmNoeVwiOjE1N31dLDEyMjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG5mdW5jdGlvbiBzdHlsZShnZCkge1xuICAgIGdkLl9mdWxsTGF5b3V0Ll9zdW5idXJzdGxheWVyLnNlbGVjdEFsbCgnLnRyYWNlJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgZ1RyYWNlID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgY2QwID0gY2RbMF07XG4gICAgICAgIHZhciB0cmFjZSA9IGNkMC50cmFjZTtcblxuICAgICAgICBnVHJhY2Uuc3R5bGUoJ29wYWNpdHknLCB0cmFjZS5vcGFjaXR5KTtcblxuICAgICAgICBnVHJhY2Uuc2VsZWN0QWxsKCdwYXRoLnN1cmZhY2UnKS5lYWNoKGZ1bmN0aW9uKHB0KSB7XG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuY2FsbChzdHlsZU9uZSwgcHQsIHRyYWNlKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHN0eWxlT25lKHMsIHB0LCB0cmFjZSkge1xuICAgIHZhciBjZGkgPSBwdC5kYXRhLmRhdGE7XG4gICAgdmFyIGlzTGVhZiA9ICFwdC5jaGlsZHJlbjtcbiAgICB2YXIgcHROdW1iZXIgPSBjZGkuaTtcbiAgICB2YXIgbGluZUNvbG9yID0gTGliLmNhc3RPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnbWFya2VyLmxpbmUuY29sb3InKSB8fCBDb2xvci5kZWZhdWx0TGluZTtcbiAgICB2YXIgbGluZVdpZHRoID0gTGliLmNhc3RPcHRpb24odHJhY2UsIHB0TnVtYmVyLCAnbWFya2VyLmxpbmUud2lkdGgnKSB8fCAwO1xuXG4gICAgcy5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgbGluZVdpZHRoKVxuICAgICAgICAuY2FsbChDb2xvci5maWxsLCBjZGkuY29sb3IpXG4gICAgICAgIC5jYWxsKENvbG9yLnN0cm9rZSwgbGluZUNvbG9yKVxuICAgICAgICAuc3R5bGUoJ29wYWNpdHknLCBpc0xlYWYgPyB0cmFjZS5sZWFmLm9wYWNpdHkgOiBudWxsKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3R5bGU6IHN0eWxlLFxuICAgIHN0eWxlT25lOiBzdHlsZU9uZVxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5LFwiZDNcIjoxNjN9XSwxMjI0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGNvbG9yU2NhbGVBdHRycyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBiYXNlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbmZ1bmN0aW9uIG1ha2VDb250b3VyUHJvakF0dHIoYXhMZXR0ZXIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIFxuICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gbWFrZUNvbnRvdXJBdHRyKGF4TGV0dGVyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc2hvdzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBzdGFydDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgLy8gaW1wbGllZEVkaXRzOiB7J15hdXRvY29udG91cic6IGZhbHNlfSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlbmQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgIC8vIGltcGxpZWRFZGl0czogeydeYXV0b2NvbnRvdXInOiBmYWxzZX0sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc2l6ZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgLy8gaW1wbGllZEVkaXRzOiB7J15hdXRvY29udG91cic6IGZhbHNlfSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBwcm9qZWN0OiB7XG4gICAgICAgICAgICB4OiBtYWtlQ29udG91clByb2pBdHRyKCd4JyksXG4gICAgICAgICAgICB5OiBtYWtlQ29udG91clByb2pBdHRyKCd5JyksXG4gICAgICAgICAgICB6OiBtYWtlQ29udG91clByb2pBdHRyKCd6JylcbiAgICAgICAgfSxcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IENvbG9yLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHVzZWNvbG9ybWFwOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAxLFxuICAgICAgICAgICAgbWF4OiAxNixcbiAgICAgICAgICAgIGRmbHQ6IDIsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgaGlnaGxpZ2h0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgaGlnaGxpZ2h0Y29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IENvbG9yLmRlZmF1bHRMaW5lLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGhpZ2hsaWdodHdpZHRoOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAxLFxuICAgICAgICAgICAgbWF4OiAxNixcbiAgICAgICAgICAgIGRmbHQ6IDIsXG4gICAgICAgICAgICBcbiAgICAgICAgfVxuICAgIH07XG59XG5cbnZhciBhdHRycyA9IG1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoZXh0ZW5kRmxhdCh7XG4gICAgejoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeDoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgIH0sXG4gICAgeToge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZXh0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIFxuICAgIH0sXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKCksXG5cbiAgICBjb25uZWN0Z2Fwczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIHN1cmZhY2Vjb2xvcjoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIFxuICAgIH0sXG59LFxuXG5jb2xvclNjYWxlQXR0cnMoJycsIHtcbiAgICBjb2xvckF0dHI6ICd6IG9yIHN1cmZhY2Vjb2xvcicsXG4gICAgc2hvd1NjYWxlRGZsdDogdHJ1ZSxcbiAgICBhdXRvQ29sb3JEZmx0OiBmYWxzZSxcbiAgICBlZGl0VHlwZU92ZXJyaWRlOiAnY2FsYydcbn0pLCB7XG4gICAgY29udG91cnM6IHtcbiAgICAgICAgeDogbWFrZUNvbnRvdXJBdHRyKCd4JyksXG4gICAgICAgIHk6IG1ha2VDb250b3VyQXR0cigneScpLFxuICAgICAgICB6OiBtYWtlQ29udG91ckF0dHIoJ3onKVxuICAgIH0sXG4gICAgaGlkZXN1cmZhY2U6IHtcbiAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsaWdodHBvc2l0aW9uOiB7XG4gICAgICAgIHg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IC0xZTUsXG4gICAgICAgICAgICBtYXg6IDFlNSxcbiAgICAgICAgICAgIGRmbHQ6IDEwLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHk6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IC0xZTUsXG4gICAgICAgICAgICBtYXg6IDFlNSxcbiAgICAgICAgICAgIGRmbHQ6IDFlNCxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB6OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAtMWU1LFxuICAgICAgICAgICAgbWF4OiAxZTUsXG4gICAgICAgICAgICBkZmx0OiAwLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgbGlnaHRpbmc6IHtcbiAgICAgICAgYW1iaWVudDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMC4wMCxcbiAgICAgICAgICAgIG1heDogMS4wLFxuICAgICAgICAgICAgZGZsdDogMC44LFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGRpZmZ1c2U6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAuMDAsXG4gICAgICAgICAgICBtYXg6IDEuMDAsXG4gICAgICAgICAgICBkZmx0OiAwLjgsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgc3BlY3VsYXI6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBtaW46IDAuMDAsXG4gICAgICAgICAgICBtYXg6IDIuMDAsXG4gICAgICAgICAgICBkZmx0OiAwLjA1LFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHJvdWdobmVzczoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMC4wMCxcbiAgICAgICAgICAgIG1heDogMS4wMCxcbiAgICAgICAgICAgIGRmbHQ6IDAuNSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBmcmVzbmVsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLjAwLFxuICAgICAgICAgICAgbWF4OiA1LjAwLFxuICAgICAgICAgICAgZGZsdDogMC4yLFxuICAgICAgICAgICAgXG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgb3BhY2l0eToge1xuICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBkZmx0OiAxLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgX2RlcHJlY2F0ZWQ6IHtcbiAgICAgICAgemF1dG86IGV4dGVuZEZsYXQoe30sIGNvbG9yU2NhbGVBdHRycy56YXV0bywge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICB6bWluOiBleHRlbmRGbGF0KHt9LCBjb2xvclNjYWxlQXR0cnMuem1pbiwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pLFxuICAgICAgICB6bWF4OiBleHRlbmRGbGF0KHt9LCBjb2xvclNjYWxlQXR0cnMuem1heCwge1xuICAgICAgICAgICAgXG4gICAgICAgIH0pXG4gICAgfSxcblxuICAgIGhvdmVyaW5mbzogZXh0ZW5kRmxhdCh7fSwgYmFzZUF0dHJzLmhvdmVyaW5mbylcbn0pLCAnY2FsYycsICduZXN0ZWQnKTtcblxuYXR0cnMueC5lZGl0VHlwZSA9IGF0dHJzLnkuZWRpdFR5cGUgPSBhdHRycy56LmVkaXRUeXBlID0gJ2NhbGMrY2xlYXJBeGlzVHlwZXMnO1xuYXR0cnMudHJhbnNmb3JtcyA9IHVuZGVmaW5lZDtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXNcIjo2MDAsXCIuLi8uLi9jb21wb25lbnRzL2Z4L2hvdmVydGVtcGxhdGVfYXR0cmlidXRlc1wiOjYzMSxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NH1dLDEyMjU6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjb2xvcnNjYWxlQ2FsYyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3JzY2FsZS9jYWxjJyk7XG5cblxuLy8gQ29tcHV0ZSBhdXRvLXogYW5kIGF1dG9jb2xvcnNjYWxlIGlmIGFwcGxpY2FibGVcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICBpZih0cmFjZS5zdXJmYWNlY29sb3IpIHtcbiAgICAgICAgY29sb3JzY2FsZUNhbGMoZ2QsIHRyYWNlLCB7XG4gICAgICAgICAgICB2YWxzOiB0cmFjZS5zdXJmYWNlY29sb3IsXG4gICAgICAgICAgICBjb250YWluZXJTdHI6ICcnLFxuICAgICAgICAgICAgY0xldHRlcjogJ2MnXG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbG9yc2NhbGVDYWxjKGdkLCB0cmFjZSwge1xuICAgICAgICAgICAgdmFsczogdHJhY2UueixcbiAgICAgICAgICAgIGNvbnRhaW5lclN0cjogJycsXG4gICAgICAgICAgICBjTGV0dGVyOiAnYydcbiAgICAgICAgfSk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUvY2FsY1wiOjYwMX1dLDEyMjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVTdXJmYWNlID0gX2RlcmVxXygnZ2wtc3VyZmFjZTNkJyk7XG5cbnZhciBuZGFycmF5ID0gX2RlcmVxXygnbmRhcnJheScpO1xudmFyIGhvbW9ncmFwaHkgPSBfZGVyZXFfKCduZGFycmF5LWhvbW9ncmFwaHknKTtcbnZhciBmaWxsID0gX2RlcmVxXygnbmRhcnJheS1maWxsJyk7XG5cbnZhciBpc0FycmF5T3JUeXBlZEFycmF5ID0gX2RlcmVxXygnLi4vLi4vbGliJykuaXNBcnJheU9yVHlwZWRBcnJheTtcbnZhciBwYXJzZUNvbG9yU2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9saWIvZ2xfZm9ybWF0X2NvbG9yJykucGFyc2VDb2xvclNjYWxlO1xudmFyIHN0cjJSZ2JhQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3RyMnJnYmFycmF5Jyk7XG52YXIgZXh0cmFjdE9wdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKS5leHRyYWN0T3B0cztcblxudmFyIGludGVycDJkID0gX2RlcmVxXygnLi4vaGVhdG1hcC9pbnRlcnAyZCcpO1xudmFyIGZpbmRFbXB0aWVzID0gX2RlcmVxXygnLi4vaGVhdG1hcC9maW5kX2VtcHRpZXMnKTtcblxuZnVuY3Rpb24gU3VyZmFjZVRyYWNlKHNjZW5lLCBzdXJmYWNlLCB1aWQpIHtcbiAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgdGhpcy51aWQgPSB1aWQ7XG4gICAgdGhpcy5zdXJmYWNlID0gc3VyZmFjZTtcbiAgICB0aGlzLmRhdGEgPSBudWxsO1xuICAgIHRoaXMuc2hvd0NvbnRvdXIgPSBbZmFsc2UsIGZhbHNlLCBmYWxzZV07XG4gICAgdGhpcy5jb250b3VyU3RhcnQgPSBbbnVsbCwgbnVsbCwgbnVsbF07XG4gICAgdGhpcy5jb250b3VyRW5kID0gW251bGwsIG51bGwsIG51bGxdO1xuICAgIHRoaXMuY29udG91clNpemUgPSBbMCwgMCwgMF07XG4gICAgdGhpcy5taW5WYWx1ZXMgPSBbSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV07XG4gICAgdGhpcy5tYXhWYWx1ZXMgPSBbLUluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV07XG4gICAgdGhpcy5kYXRhU2NhbGVYID0gMS4wO1xuICAgIHRoaXMuZGF0YVNjYWxlWSA9IDEuMDtcbiAgICB0aGlzLnJlZmluZURhdGEgPSB0cnVlO1xuICAgIHRoaXMub2JqZWN0T2Zmc2V0ID0gWzAsIDAsIDBdO1xufVxuXG52YXIgcHJvdG8gPSBTdXJmYWNlVHJhY2UucHJvdG90eXBlO1xuXG5wcm90by5nZXRYYXQgPSBmdW5jdGlvbihhLCBiLCBjYWxlbmRhciwgYXhpcykge1xuICAgIHZhciB2ID0gKFxuICAgICAgICghaXNBcnJheU9yVHlwZWRBcnJheSh0aGlzLmRhdGEueCkpID9cbiAgICAgICAgICAgIGEgOlxuICAgICAgIChpc0FycmF5T3JUeXBlZEFycmF5KHRoaXMuZGF0YS54WzBdKSkgP1xuICAgICAgICAgICAgdGhpcy5kYXRhLnhbYl1bYV0gOlxuICAgICAgICAgICAgdGhpcy5kYXRhLnhbYV1cbiAgICApO1xuXG4gICAgcmV0dXJuIChjYWxlbmRhciA9PT0gdW5kZWZpbmVkKSA/IHYgOiBheGlzLmQybCh2LCAwLCBjYWxlbmRhcik7XG59O1xuXG5wcm90by5nZXRZYXQgPSBmdW5jdGlvbihhLCBiLCBjYWxlbmRhciwgYXhpcykge1xuICAgIHZhciB2ID0gKFxuICAgICAgICghaXNBcnJheU9yVHlwZWRBcnJheSh0aGlzLmRhdGEueSkpID9cbiAgICAgICAgICAgIGIgOlxuICAgICAgIChpc0FycmF5T3JUeXBlZEFycmF5KHRoaXMuZGF0YS55WzBdKSkgP1xuICAgICAgICAgICAgdGhpcy5kYXRhLnlbYl1bYV0gOlxuICAgICAgICAgICAgdGhpcy5kYXRhLnlbYl1cbiAgICApO1xuXG4gICAgcmV0dXJuIChjYWxlbmRhciA9PT0gdW5kZWZpbmVkKSA/IHYgOiBheGlzLmQybCh2LCAwLCBjYWxlbmRhcik7XG59O1xuXG5wcm90by5nZXRaYXQgPSBmdW5jdGlvbihhLCBiLCBjYWxlbmRhciwgYXhpcykge1xuICAgIHZhciB2ID0gdGhpcy5kYXRhLnpbYl1bYV07XG5cbiAgICBpZih2ID09PSBudWxsICYmIHRoaXMuZGF0YS5jb25uZWN0Z2FwcyAmJiB0aGlzLmRhdGEuX2ludGVycG9sYXRlZFopIHtcbiAgICAgICAgdiA9IHRoaXMuZGF0YS5faW50ZXJwb2xhdGVkWltiXVthXTtcbiAgICB9XG5cbiAgICByZXR1cm4gKGNhbGVuZGFyID09PSB1bmRlZmluZWQpID8gdiA6IGF4aXMuZDJsKHYsIDAsIGNhbGVuZGFyKTtcbn07XG5cbnByb3RvLmhhbmRsZVBpY2sgPSBmdW5jdGlvbihzZWxlY3Rpb24pIHtcbiAgICBpZihzZWxlY3Rpb24ub2JqZWN0ID09PSB0aGlzLnN1cmZhY2UpIHtcbiAgICAgICAgdmFyIHhSYXRpbyA9IChzZWxlY3Rpb24uZGF0YS5pbmRleFswXSAtIDEpIC8gdGhpcy5kYXRhU2NhbGVYIC0gMTtcbiAgICAgICAgdmFyIHlSYXRpbyA9IChzZWxlY3Rpb24uZGF0YS5pbmRleFsxXSAtIDEpIC8gdGhpcy5kYXRhU2NhbGVZIC0gMTtcblxuICAgICAgICB2YXIgaiA9IE1hdGgubWF4KE1hdGgubWluKE1hdGgucm91bmQoeFJhdGlvKSwgdGhpcy5kYXRhLnpbMF0ubGVuZ3RoIC0gMSksIDApO1xuICAgICAgICB2YXIgayA9IE1hdGgubWF4KE1hdGgubWluKE1hdGgucm91bmQoeVJhdGlvKSwgdGhpcy5kYXRhLl95bGVuZ3RoIC0gMSksIDApO1xuXG4gICAgICAgIHNlbGVjdGlvbi5pbmRleCA9IFtqLCBrXTtcblxuICAgICAgICBzZWxlY3Rpb24udHJhY2VDb29yZGluYXRlID0gW1xuICAgICAgICAgICAgdGhpcy5nZXRYYXQoaiwgayksXG4gICAgICAgICAgICB0aGlzLmdldFlhdChqLCBrKSxcbiAgICAgICAgICAgIHRoaXMuZ2V0WmF0KGosIGspXG4gICAgICAgIF07XG5cbiAgICAgICAgc2VsZWN0aW9uLmRhdGFDb29yZGluYXRlID0gW1xuICAgICAgICAgICAgdGhpcy5nZXRYYXQoaiwgaywgdGhpcy5kYXRhLnhjYWxlbmRhciwgdGhpcy5zY2VuZS5mdWxsU2NlbmVMYXlvdXQueGF4aXMpLFxuICAgICAgICAgICAgdGhpcy5nZXRZYXQoaiwgaywgdGhpcy5kYXRhLnljYWxlbmRhciwgdGhpcy5zY2VuZS5mdWxsU2NlbmVMYXlvdXQueWF4aXMpLFxuICAgICAgICAgICAgdGhpcy5nZXRaYXQoaiwgaywgdGhpcy5kYXRhLnpjYWxlbmRhciwgdGhpcy5zY2VuZS5mdWxsU2NlbmVMYXlvdXQuemF4aXMpXG4gICAgICAgIF07XG5cbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICAgICAgdmFyIHYgPSBzZWxlY3Rpb24uZGF0YUNvb3JkaW5hdGVbaV07XG4gICAgICAgICAgICBpZih2ICE9PSBudWxsICYmIHYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5kYXRhQ29vcmRpbmF0ZVtpXSAqPSB0aGlzLnNjZW5lLmRhdGFTY2FsZVtpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0ZXh0ID0gdGhpcy5kYXRhLmhvdmVydGV4dCB8fCB0aGlzLmRhdGEudGV4dDtcbiAgICAgICAgaWYoQXJyYXkuaXNBcnJheSh0ZXh0KSAmJiB0ZXh0W2tdICYmIHRleHRba11bal0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgc2VsZWN0aW9uLnRleHRMYWJlbCA9IHRleHRba11bal07XG4gICAgICAgIH0gZWxzZSBpZih0ZXh0KSB7XG4gICAgICAgICAgICBzZWxlY3Rpb24udGV4dExhYmVsID0gdGV4dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlbGVjdGlvbi50ZXh0TGFiZWwgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGVjdGlvbi5kYXRhLmRhdGFDb29yZGluYXRlID0gc2VsZWN0aW9uLmRhdGFDb29yZGluYXRlLnNsaWNlKCk7XG5cbiAgICAgICAgdGhpcy5zdXJmYWNlLmhpZ2hsaWdodChzZWxlY3Rpb24uZGF0YSk7XG5cbiAgICAgICAgLy8gU25hcCBzcGlrZXMgdG8gZGF0YSBjb29yZGluYXRlXG4gICAgICAgIHRoaXMuc2NlbmUuZ2xwbG90LnNwaWtlcy5wb3NpdGlvbiA9IHNlbGVjdGlvbi5kYXRhQ29vcmRpbmF0ZTtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBpc0NvbG9ybWFwQ2lyY3VsYXIoY29sb3JtYXApIHtcbiAgICB2YXIgZmlyc3QgPSBjb2xvcm1hcFswXS5yZ2I7XG4gICAgdmFyIGxhc3QgPSBjb2xvcm1hcFtjb2xvcm1hcC5sZW5ndGggLSAxXS5yZ2I7XG5cbiAgICByZXR1cm4gKFxuICAgICAgICBmaXJzdFswXSA9PT0gbGFzdFswXSAmJlxuICAgICAgICBmaXJzdFsxXSA9PT0gbGFzdFsxXSAmJlxuICAgICAgICBmaXJzdFsyXSA9PT0gbGFzdFsyXSAmJlxuICAgICAgICBmaXJzdFszXSA9PT0gbGFzdFszXVxuICAgICk7XG59XG5cbnZhciBzaG9ydFByaW1lcyA9IFtcbiAgICAyLCAzLCA1LCA3LCAxMSwgMTMsIDE3LCAxOSwgMjMsIDI5LCAzMSwgMzcsIDQxLCA0MywgNDcsIDUzLCA1OSwgNjEsIDY3LCA3MSwgNzMsIDc5LCA4MywgODksIDk3LFxuICAgIDEwMSwgMTAzLCAxMDcsIDEwOSwgMTEzLCAxMjcsIDEzMSwgMTM3LCAxMzksIDE0OSwgMTUxLCAxNTcsIDE2MywgMTY3LCAxNzMsIDE3OSwgMTgxLCAxOTEsIDE5MywgMTk3LCAxOTksXG4gICAgMjExLCAyMjMsIDIyNywgMjI5LCAyMzMsIDIzOSwgMjQxLCAyNTEsIDI1NywgMjYzLCAyNjksIDI3MSwgMjc3LCAyODEsIDI4MywgMjkzLFxuICAgIDMwNywgMzExLCAzMTMsIDMxNywgMzMxLCAzMzcsIDM0NywgMzQ5LCAzNTMsIDM1OSwgMzY3LCAzNzMsIDM3OSwgMzgzLCAzODksIDM5NyxcbiAgICA0MDEsIDQwOSwgNDE5LCA0MjEsIDQzMSwgNDMzLCA0MzksIDQ0MywgNDQ5LCA0NTcsIDQ2MSwgNDYzLCA0NjcsIDQ3OSwgNDg3LCA0OTEsIDQ5OSxcbiAgICA1MDMsIDUwOSwgNTIxLCA1MjMsIDU0MSwgNTQ3LCA1NTcsIDU2MywgNTY5LCA1NzEsIDU3NywgNTg3LCA1OTMsIDU5OSxcbiAgICA2MDEsIDYwNywgNjEzLCA2MTcsIDYxOSwgNjMxLCA2NDEsIDY0MywgNjQ3LCA2NTMsIDY1OSwgNjYxLCA2NzMsIDY3NywgNjgzLCA2OTEsXG4gICAgNzAxLCA3MDksIDcxOSwgNzI3LCA3MzMsIDczOSwgNzQzLCA3NTEsIDc1NywgNzYxLCA3NjksIDc3MywgNzg3LCA3OTcsXG4gICAgODA5LCA4MTEsIDgyMSwgODIzLCA4MjcsIDgyOSwgODM5LCA4NTMsIDg1NywgODU5LCA4NjMsIDg3NywgODgxLCA4ODMsIDg4NyxcbiAgICA5MDcsIDkxMSwgOTE5LCA5MjksIDkzNywgOTQxLCA5NDcsIDk1MywgOTY3LCA5NzEsIDk3NywgOTgzLCA5OTEsIDk5NyxcbiAgICAxMDA5LCAxMDEzLCAxMDE5LCAxMDIxLCAxMDMxLCAxMDMzLCAxMDM5LCAxMDQ5LCAxMDUxLCAxMDYxLCAxMDYzLCAxMDY5LCAxMDg3LCAxMDkxLCAxMDkzLCAxMDk3LFxuICAgIDExMDMsIDExMDksIDExMTcsIDExMjMsIDExMjksIDExNTEsIDExNTMsIDExNjMsIDExNzEsIDExODEsIDExODcsIDExOTMsXG4gICAgMTIwMSwgMTIxMywgMTIxNywgMTIyMywgMTIyOSwgMTIzMSwgMTIzNywgMTI0OSwgMTI1OSwgMTI3NywgMTI3OSwgMTI4MywgMTI4OSwgMTI5MSwgMTI5NyxcbiAgICAxMzAxLCAxMzAzLCAxMzA3LCAxMzE5LCAxMzIxLCAxMzI3LCAxMzYxLCAxMzY3LCAxMzczLCAxMzgxLCAxMzk5LFxuICAgIDE0MDksIDE0MjMsIDE0MjcsIDE0MjksIDE0MzMsIDE0MzksIDE0NDcsIDE0NTEsIDE0NTMsIDE0NTksIDE0NzEsIDE0ODEsIDE0ODMsIDE0ODcsIDE0ODksIDE0OTMsIDE0OTksXG4gICAgMTUxMSwgMTUyMywgMTUzMSwgMTU0MywgMTU0OSwgMTU1MywgMTU1OSwgMTU2NywgMTU3MSwgMTU3OSwgMTU4MywgMTU5NyxcbiAgICAxNjAxLCAxNjA3LCAxNjA5LCAxNjEzLCAxNjE5LCAxNjIxLCAxNjI3LCAxNjM3LCAxNjU3LCAxNjYzLCAxNjY3LCAxNjY5LCAxNjkzLCAxNjk3LCAxNjk5LFxuICAgIDE3MDksIDE3MjEsIDE3MjMsIDE3MzMsIDE3NDEsIDE3NDcsIDE3NTMsIDE3NTksIDE3NzcsIDE3ODMsIDE3ODcsIDE3ODksXG4gICAgMTgwMSwgMTgxMSwgMTgyMywgMTgzMSwgMTg0NywgMTg2MSwgMTg2NywgMTg3MSwgMTg3MywgMTg3NywgMTg3OSwgMTg4OSxcbiAgICAxOTAxLCAxOTA3LCAxOTEzLCAxOTMxLCAxOTMzLCAxOTQ5LCAxOTUxLCAxOTczLCAxOTc5LCAxOTg3LCAxOTkzLCAxOTk3LCAxOTk5LFxuICAgIDIwMDMsIDIwMTEsIDIwMTcsIDIwMjcsIDIwMjksIDIwMzksIDIwNTMsIDIwNjMsIDIwNjksIDIwODEsIDIwODMsIDIwODcsIDIwODksIDIwOTksXG4gICAgMjExMSwgMjExMywgMjEyOSwgMjEzMSwgMjEzNywgMjE0MSwgMjE0MywgMjE1MywgMjE2MSwgMjE3OSxcbiAgICAyMjAzLCAyMjA3LCAyMjEzLCAyMjIxLCAyMjM3LCAyMjM5LCAyMjQzLCAyMjUxLCAyMjY3LCAyMjY5LCAyMjczLCAyMjgxLCAyMjg3LCAyMjkzLCAyMjk3LFxuICAgIDIzMDksIDIzMTEsIDIzMzMsIDIzMzksIDIzNDEsIDIzNDcsIDIzNTEsIDIzNTcsIDIzNzEsIDIzNzcsIDIzODEsIDIzODMsIDIzODksIDIzOTMsIDIzOTksXG4gICAgMjQxMSwgMjQxNywgMjQyMywgMjQzNywgMjQ0MSwgMjQ0NywgMjQ1OSwgMjQ2NywgMjQ3MywgMjQ3NyxcbiAgICAyNTAzLCAyNTIxLCAyNTMxLCAyNTM5LCAyNTQzLCAyNTQ5LCAyNTUxLCAyNTU3LCAyNTc5LCAyNTkxLCAyNTkzLFxuICAgIDI2MDksIDI2MTcsIDI2MjEsIDI2MzMsIDI2NDcsIDI2NTcsIDI2NTksIDI2NjMsIDI2NzEsIDI2NzcsIDI2ODMsIDI2ODcsIDI2ODksIDI2OTMsIDI2OTksXG4gICAgMjcwNywgMjcxMSwgMjcxMywgMjcxOSwgMjcyOSwgMjczMSwgMjc0MSwgMjc0OSwgMjc1MywgMjc2NywgMjc3NywgMjc4OSwgMjc5MSwgMjc5NyxcbiAgICAyODAxLCAyODAzLCAyODE5LCAyODMzLCAyODM3LCAyODQzLCAyODUxLCAyODU3LCAyODYxLCAyODc5LCAyODg3LCAyODk3LFxuICAgIDI5MDMsIDI5MDksIDI5MTcsIDI5MjcsIDI5MzksIDI5NTMsIDI5NTcsIDI5NjMsIDI5NjksIDI5NzEsIDI5OTlcbl07XG5cbmZ1bmN0aW9uIGdldFBvdyhhLCBiKSB7XG4gICAgaWYoYSA8IGIpIHJldHVybiAwO1xuICAgIHZhciBuID0gMDtcbiAgICB3aGlsZShNYXRoLmZsb29yKGEgJSBiKSA9PT0gMCkge1xuICAgICAgICBhIC89IGI7XG4gICAgICAgIG4rKztcbiAgICB9XG4gICAgcmV0dXJuIG47XG59XG5cbmZ1bmN0aW9uIGdldEZhY3RvcnMoYSkge1xuICAgIHZhciBwb3dlcnMgPSBbXTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgc2hvcnRQcmltZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGIgPSBzaG9ydFByaW1lc1tpXTtcbiAgICAgICAgcG93ZXJzLnB1c2goXG4gICAgICAgICAgICBnZXRQb3coYSwgYilcbiAgICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHBvd2Vycztcbn1cblxuZnVuY3Rpb24gc21hbGxlc3REaXZpc29yKGEpIHtcbiAgICB2YXIgQSA9IGdldEZhY3RvcnMoYSk7XG4gICAgdmFyIHJlc3VsdCA9IGE7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNob3J0UHJpbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKEFbaV0gPiAwKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBzaG9ydFByaW1lc1tpXTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIGxlYXN0Q29tbW9uTXVsdGlwbGUoYSwgYikge1xuICAgIGlmKGEgPCAxIHx8IGIgPCAxKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHZhciBBID0gZ2V0RmFjdG9ycyhhKTtcbiAgICB2YXIgQiA9IGdldEZhY3RvcnMoYik7XG4gICAgdmFyIG4gPSAxO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBzaG9ydFByaW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBuICo9IE1hdGgucG93KFxuICAgICAgICAgICAgc2hvcnRQcmltZXNbaV0sIE1hdGgubWF4KEFbaV0sIEJbaV0pXG4gICAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBuO1xufVxuXG5mdW5jdGlvbiBhcnJheUxDTShBKSB7XG4gICAgaWYoQS5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWQ7XG4gICAgdmFyIG4gPSAxO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBBLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG4gPSBsZWFzdENvbW1vbk11bHRpcGxlKG4sIEFbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gbjtcbn1cblxucHJvdG8uY2FsY1hudW1zID0gZnVuY3Rpb24oeGxlbikge1xuICAgIHZhciBpO1xuICAgIHZhciBudW1zID0gW107XG4gICAgZm9yKGkgPSAxOyBpIDwgeGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciBhID0gdGhpcy5nZXRYYXQoaSAtIDEsIDApO1xuICAgICAgICB2YXIgYiA9IHRoaXMuZ2V0WGF0KGksIDApO1xuXG4gICAgICAgIGlmKGIgIT09IGEgJiZcbiAgICAgICAgICAgIGEgIT09IHVuZGVmaW5lZCAmJiBhICE9PSBudWxsICYmXG4gICAgICAgICAgICBiICE9PSB1bmRlZmluZWQgJiYgYiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgbnVtc1tpIC0gMV0gPSBNYXRoLmFicyhiIC0gYSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBudW1zW2kgLSAxXSA9IDA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdG90YWxEaXN0ID0gMDtcbiAgICBmb3IoaSA9IDE7IGkgPCB4bGVuOyBpKyspIHtcbiAgICAgICAgdG90YWxEaXN0ICs9IG51bXNbaSAtIDFdO1xuICAgIH1cblxuICAgIGZvcihpID0gMTsgaSA8IHhsZW47IGkrKykge1xuICAgICAgICBpZihudW1zW2kgLSAxXSA9PT0gMCkge1xuICAgICAgICAgICAgbnVtc1tpIC0gMV0gPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbnVtc1tpIC0gMV0gPSBNYXRoLnJvdW5kKHRvdGFsRGlzdCAvIG51bXNbaSAtIDFdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudW1zO1xufTtcblxucHJvdG8uY2FsY1ludW1zID0gZnVuY3Rpb24oeWxlbikge1xuICAgIHZhciBpO1xuICAgIHZhciBudW1zID0gW107XG4gICAgZm9yKGkgPSAxOyBpIDwgeWxlbjsgaSsrKSB7XG4gICAgICAgIHZhciBhID0gdGhpcy5nZXRZYXQoMCwgaSAtIDEpO1xuICAgICAgICB2YXIgYiA9IHRoaXMuZ2V0WWF0KDAsIGkpO1xuXG4gICAgICAgIGlmKGIgIT09IGEgJiZcbiAgICAgICAgICAgIGEgIT09IHVuZGVmaW5lZCAmJiBhICE9PSBudWxsICYmXG4gICAgICAgICAgICBiICE9PSB1bmRlZmluZWQgJiYgYiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgbnVtc1tpIC0gMV0gPSBNYXRoLmFicyhiIC0gYSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBudW1zW2kgLSAxXSA9IDA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdG90YWxEaXN0ID0gMDtcbiAgICBmb3IoaSA9IDE7IGkgPCB5bGVuOyBpKyspIHtcbiAgICAgICAgdG90YWxEaXN0ICs9IG51bXNbaSAtIDFdO1xuICAgIH1cblxuICAgIGZvcihpID0gMTsgaSA8IHlsZW47IGkrKykge1xuICAgICAgICBpZihudW1zW2kgLSAxXSA9PT0gMCkge1xuICAgICAgICAgICAgbnVtc1tpIC0gMV0gPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbnVtc1tpIC0gMV0gPSBNYXRoLnJvdW5kKHRvdGFsRGlzdCAvIG51bXNbaSAtIDFdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudW1zO1xufTtcblxudmFyIGhpZ2hseUNvbXBvc2l0ZXMgPSBbMSwgMiwgNCwgNiwgMTIsIDI0LCAzNiwgNDgsIDYwLCAxMjAsIDE4MCwgMjQwLCAzNjAsIDcyMCwgODQwLCAxMjYwXTtcblxudmFyIE1JTl9SRVNPTFVUSU9OID0gaGlnaGx5Q29tcG9zaXRlc1s5XTtcbnZhciBNQVhfUkVTT0xVVElPTiA9IGhpZ2hseUNvbXBvc2l0ZXNbMTNdO1xuXG5wcm90by5lc3RpbWF0ZVNjYWxlID0gZnVuY3Rpb24ocmVzU3JjLCBheGlzKSB7XG4gICAgdmFyIG51bXMgPSAoYXhpcyA9PT0gMCkgP1xuICAgICAgICB0aGlzLmNhbGNYbnVtcyhyZXNTcmMpIDpcbiAgICAgICAgdGhpcy5jYWxjWW51bXMocmVzU3JjKTtcblxuICAgIHZhciByZXNEc3QgPSAxICsgYXJyYXlMQ00obnVtcyk7XG5cbiAgICB3aGlsZShyZXNEc3QgPCBNSU5fUkVTT0xVVElPTikge1xuICAgICAgICByZXNEc3QgKj0gMjtcbiAgICB9XG5cbiAgICB3aGlsZShyZXNEc3QgPiBNQVhfUkVTT0xVVElPTikge1xuICAgICAgICByZXNEc3QtLTtcbiAgICAgICAgcmVzRHN0IC89IHNtYWxsZXN0RGl2aXNvcihyZXNEc3QpO1xuICAgICAgICByZXNEc3QrKztcblxuICAgICAgICBpZihyZXNEc3QgPCBNSU5fUkVTT0xVVElPTikge1xuICAgICAgICAgLy8gcmVzRHN0ID0gTUlOX1JFU09MVVRJT047IC8vIG9wdGlvbiAxOiB1c2UgbWluIHJlc29sdXRpb25cbiAgICAgICAgICAgIHJlc0RzdCA9IE1BWF9SRVNPTFVUSU9OOyAvLyBvcHRpb24gMjogdXNlIG1heCByZXNvbHV0aW9uXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc2NhbGUgPSBNYXRoLnJvdW5kKHJlc0RzdCAvIHJlc1NyYyk7XG4gICAgcmV0dXJuIChzY2FsZSA+IDEpID8gc2NhbGUgOiAxO1xufTtcblxucHJvdG8ucmVmaW5lQ29vcmRzID0gZnVuY3Rpb24oY29vcmRzKSB7XG4gICAgdmFyIHNjYWxlVyA9IHRoaXMuZGF0YVNjYWxlWDtcbiAgICB2YXIgc2NhbGVIID0gdGhpcy5kYXRhU2NhbGVZO1xuXG4gICAgdmFyIHdpZHRoID0gY29vcmRzWzBdLnNoYXBlWzBdO1xuICAgIHZhciBoZWlnaHQgPSBjb29yZHNbMF0uc2hhcGVbMV07XG5cbiAgICB2YXIgbmV3V2lkdGggPSBNYXRoLmZsb29yKGNvb3Jkc1swXS5zaGFwZVswXSAqIHNjYWxlVyArIDEpIHwgMDtcbiAgICB2YXIgbmV3SGVpZ2h0ID0gTWF0aC5mbG9vcihjb29yZHNbMF0uc2hhcGVbMV0gKiBzY2FsZUggKyAxKSB8IDA7XG5cbiAgICAvLyBQYWQgY29vcmRzIGJ5ICsxXG4gICAgdmFyIHBhZFdpZHRoID0gMSArIHdpZHRoICsgMTtcbiAgICB2YXIgcGFkSGVpZ2h0ID0gMSArIGhlaWdodCArIDE7XG4gICAgdmFyIHBhZEltZyA9IG5kYXJyYXkobmV3IEZsb2F0MzJBcnJheShwYWRXaWR0aCAqIHBhZEhlaWdodCksIFtwYWRXaWR0aCwgcGFkSGVpZ2h0XSk7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY29vcmRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHRoaXMuc3VyZmFjZS5wYWRGaWVsZChwYWRJbWcsIGNvb3Jkc1tpXSk7XG5cbiAgICAgICAgdmFyIHNjYWxlZEltZyA9IG5kYXJyYXkobmV3IEZsb2F0MzJBcnJheShuZXdXaWR0aCAqIG5ld0hlaWdodCksIFtuZXdXaWR0aCwgbmV3SGVpZ2h0XSk7XG4gICAgICAgIGhvbW9ncmFwaHkoc2NhbGVkSW1nLCBwYWRJbWcsXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgc2NhbGVXLCAwLCAwLFxuICAgICAgICAgICAgICAgIDAsIHNjYWxlSCwgMCxcbiAgICAgICAgICAgICAgICAwLCAwLCAxXG4gICAgICAgICAgICBdXG4gICAgICAgICk7XG4gICAgICAgIGNvb3Jkc1tpXSA9IHNjYWxlZEltZztcbiAgICB9XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRJZk5ld0xldmVsKGFyciwgbmV3VmFsdWUpIHtcbiAgICB2YXIgZm91bmQgPSBmYWxzZTtcbiAgICBmb3IodmFyIGsgPSAwOyBrIDwgYXJyLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIGlmKG5ld1ZhbHVlID09PSBhcnJba10pIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmKGZvdW5kID09PSBmYWxzZSkgYXJyLnB1c2gobmV3VmFsdWUpO1xufVxuXG5wcm90by5zZXRDb250b3VyTGV2ZWxzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG5ld0xldmVscyA9IFtbXSwgW10sIFtdXTtcbiAgICB2YXIgdXNlTmV3TGV2ZWxzID0gW2ZhbHNlLCBmYWxzZSwgZmFsc2VdO1xuICAgIHZhciBuZWVkc1VwZGF0ZSA9IGZhbHNlO1xuXG4gICAgdmFyIGksIGosIHZhbHVlO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIGlmKHRoaXMuc2hvd0NvbnRvdXJbaV0pIHtcbiAgICAgICAgICAgIG5lZWRzVXBkYXRlID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYoXG4gICAgICAgICAgICAgICAgdGhpcy5jb250b3VyU2l6ZVtpXSA+IDAgJiZcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRvdXJTdGFydFtpXSAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgIHRoaXMuY29udG91ckVuZFtpXSAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgICAgIHRoaXMuY29udG91ckVuZFtpXSA+IHRoaXMuY29udG91clN0YXJ0W2ldXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICB1c2VOZXdMZXZlbHNbaV0gPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgZm9yKGogPSB0aGlzLmNvbnRvdXJTdGFydFtpXTsgaiA8IHRoaXMuY29udG91ckVuZFtpXTsgaiArPSB0aGlzLmNvbnRvdXJTaXplW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gaiAqIHRoaXMuc2NlbmUuZGF0YVNjYWxlW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGluc2VydElmTmV3TGV2ZWwobmV3TGV2ZWxzW2ldLCB2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYobmVlZHNVcGRhdGUpIHtcbiAgICAgICAgdmFyIGFsbExldmVscyA9IFtbXSwgW10sIFtdXTtcbiAgICAgICAgZm9yKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgICAgICBpZih0aGlzLnNob3dDb250b3VyW2ldKSB7XG4gICAgICAgICAgICAgICAgYWxsTGV2ZWxzW2ldID0gdXNlTmV3TGV2ZWxzW2ldID8gbmV3TGV2ZWxzW2ldIDogdGhpcy5zY2VuZS5jb250b3VyTGV2ZWxzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3VyZmFjZS51cGRhdGUoeyBsZXZlbHM6IGFsbExldmVscyB9KTtcbiAgICB9XG59O1xuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgdmFyIHNjZW5lID0gdGhpcy5zY2VuZTtcbiAgICB2YXIgc2NlbmVMYXlvdXQgPSBzY2VuZS5mdWxsU2NlbmVMYXlvdXQ7XG4gICAgdmFyIHN1cmZhY2UgPSB0aGlzLnN1cmZhY2U7XG4gICAgdmFyIGFscGhhID0gZGF0YS5vcGFjaXR5O1xuICAgIHZhciBjb2xvcm1hcCA9IHBhcnNlQ29sb3JTY2FsZShkYXRhLCBhbHBoYSk7XG4gICAgdmFyIHNjYWxlRmFjdG9yID0gc2NlbmUuZGF0YVNjYWxlO1xuICAgIHZhciB4bGVuID0gZGF0YS56WzBdLmxlbmd0aDtcbiAgICB2YXIgeWxlbiA9IGRhdGEuX3lsZW5ndGg7XG4gICAgdmFyIGNvbnRvdXJMZXZlbHMgPSBzY2VuZS5jb250b3VyTGV2ZWxzO1xuXG4gICAgLy8gU2F2ZSBkYXRhXG4gICAgdGhpcy5kYXRhID0gZGF0YTtcblxuICAgIC8qXG4gICAgICogRmlsbCBhbmQgdHJhbnNwb3NlIHpkYXRhLlxuICAgICAqIENvbnNpc3RlbnQgd2l0aCAnaGVhdG1hcCcgYW5kICdjb250b3VyJywgcGxvdGx5ICdzdXJmYWNlJ1xuICAgICAqICd6JyBhcmUgc3VjaCB0aGF0IHN1Yi1hcnJheXMgY29ycmVzcG9uZCB0byB5LWNvb3Jkc1xuICAgICAqIGFuZCB0aGF0IHRoZSBzdWItYXJyYXkgZW50cmllcyBjb3JyZXNwb25kIHRvIGEgeC1jb29yZHMsXG4gICAgICogd2hpY2ggaXMgdGhlIHRyYW5zcG9zZSBvZiAnZ2wtc3VyZmFjZS1wbG90Jy5cbiAgICAgKi9cblxuICAgIHZhciBpLCBqLCBrLCB2O1xuICAgIHZhciByYXdDb29yZHMgPSBbXTtcbiAgICBmb3IoaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgcmF3Q29vcmRzW2ldID0gW107XG4gICAgICAgIGZvcihqID0gMDsgaiA8IHhsZW47IGorKykge1xuICAgICAgICAgICAgcmF3Q29vcmRzW2ldW2pdID0gW107XG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgeWxlbjsgaysrKSB7XG4gICAgICAgICAgICAgICAgcmF3Q29vcmRzW2ldW2pdW2tdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgKi9cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNvb3JkcyB4LCB5ICYgelxuICAgIGZvcihqID0gMDsgaiA8IHhsZW47IGorKykge1xuICAgICAgICBmb3IoayA9IDA7IGsgPCB5bGVuOyBrKyspIHtcbiAgICAgICAgICAgIHJhd0Nvb3Jkc1swXVtqXVtrXSA9IHRoaXMuZ2V0WGF0KGosIGssIGRhdGEueGNhbGVuZGFyLCBzY2VuZUxheW91dC54YXhpcyk7XG4gICAgICAgICAgICByYXdDb29yZHNbMV1bal1ba10gPSB0aGlzLmdldFlhdChqLCBrLCBkYXRhLnljYWxlbmRhciwgc2NlbmVMYXlvdXQueWF4aXMpO1xuICAgICAgICAgICAgcmF3Q29vcmRzWzJdW2pdW2tdID0gdGhpcy5nZXRaYXQoaiwgaywgZGF0YS56Y2FsZW5kYXIsIHNjZW5lTGF5b3V0LnpheGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGRhdGEuY29ubmVjdGdhcHMpIHtcbiAgICAgICAgZGF0YS5fZW1wdHlwb2ludHMgPSBmaW5kRW1wdGllcyhyYXdDb29yZHNbMl0pO1xuICAgICAgICBpbnRlcnAyZChyYXdDb29yZHNbMl0sIGRhdGEuX2VtcHR5cG9pbnRzKTtcblxuICAgICAgICBkYXRhLl9pbnRlcnBvbGF0ZWRaID0gW107XG4gICAgICAgIGZvcihqID0gMDsgaiA8IHhsZW47IGorKykge1xuICAgICAgICAgICAgZGF0YS5faW50ZXJwb2xhdGVkWltqXSA9IFtdO1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgeWxlbjsgaysrKSB7XG4gICAgICAgICAgICAgICAgZGF0YS5faW50ZXJwb2xhdGVkWltqXVtrXSA9IHJhd0Nvb3Jkc1syXVtqXVtrXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdGU6IGxvZyBheGVzIGFyZSBub3QgZGVmaW5lZCBpbiBzdXJmYWNlcyB5ZXQuXG4gICAgLy8gYnV0IHRoZXkgY291bGQgYmUgZGVmaW5lZCBoZXJlLi4uXG5cbiAgICBmb3IoaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgeGxlbjsgaisrKSB7XG4gICAgICAgICAgICBmb3IoayA9IDA7IGsgPCB5bGVuOyBrKyspIHtcbiAgICAgICAgICAgICAgICB2ID0gcmF3Q29vcmRzW2ldW2pdW2tdO1xuICAgICAgICAgICAgICAgIGlmKHYgPT09IG51bGwgfHwgdiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJhd0Nvb3Jkc1tpXVtqXVtrXSA9IE5hTjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2ID0gcmF3Q29vcmRzW2ldW2pdW2tdICo9IHNjYWxlRmFjdG9yW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgICBmb3IoaiA9IDA7IGogPCB4bGVuOyBqKyspIHtcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IHlsZW47IGsrKykge1xuICAgICAgICAgICAgICAgIHYgPSByYXdDb29yZHNbaV1bal1ba107XG4gICAgICAgICAgICAgICAgaWYodiAhPT0gbnVsbCAmJiB2ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYodGhpcy5taW5WYWx1ZXNbaV0gPiB2KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1pblZhbHVlc1tpXSA9IHY7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYodGhpcy5tYXhWYWx1ZXNbaV0gPCB2KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1heFZhbHVlc1tpXSA9IHY7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IoaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgdGhpcy5vYmplY3RPZmZzZXRbaV0gPSAwLjUgKiAodGhpcy5taW5WYWx1ZXNbaV0gKyB0aGlzLm1heFZhbHVlc1tpXSk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgMzsgaSsrKSB7XG4gICAgICAgIGZvcihqID0gMDsgaiA8IHhsZW47IGorKykge1xuICAgICAgICAgICAgZm9yKGsgPSAwOyBrIDwgeWxlbjsgaysrKSB7XG4gICAgICAgICAgICAgICAgdiA9IHJhd0Nvb3Jkc1tpXVtqXVtrXTtcbiAgICAgICAgICAgICAgICBpZih2ICE9PSBudWxsICYmIHYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByYXdDb29yZHNbaV1bal1ba10gLT0gdGhpcy5vYmplY3RPZmZzZXRbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gY29udmVydCBwcm9jZXNzZWQgcmF3IGRhdGEgdG8gRmxvYXQzMiBtYXRyaWNlc1xuICAgIHZhciBjb29yZHMgPSBbXG4gICAgICAgIG5kYXJyYXkobmV3IEZsb2F0MzJBcnJheSh4bGVuICogeWxlbiksIFt4bGVuLCB5bGVuXSksXG4gICAgICAgIG5kYXJyYXkobmV3IEZsb2F0MzJBcnJheSh4bGVuICogeWxlbiksIFt4bGVuLCB5bGVuXSksXG4gICAgICAgIG5kYXJyYXkobmV3IEZsb2F0MzJBcnJheSh4bGVuICogeWxlbiksIFt4bGVuLCB5bGVuXSlcbiAgICBdO1xuICAgIGZpbGwoY29vcmRzWzBdLCBmdW5jdGlvbihyb3csIGNvbCkgeyByZXR1cm4gcmF3Q29vcmRzWzBdW3Jvd11bY29sXTsgfSk7XG4gICAgZmlsbChjb29yZHNbMV0sIGZ1bmN0aW9uKHJvdywgY29sKSB7IHJldHVybiByYXdDb29yZHNbMV1bcm93XVtjb2xdOyB9KTtcbiAgICBmaWxsKGNvb3Jkc1syXSwgZnVuY3Rpb24ocm93LCBjb2wpIHsgcmV0dXJuIHJhd0Nvb3Jkc1syXVtyb3ddW2NvbF07IH0pO1xuICAgIHJhd0Nvb3JkcyA9IFtdOyAvLyBmcmVlIG1lbW9yeVxuXG4gICAgdmFyIHBhcmFtcyA9IHtcbiAgICAgICAgY29sb3JtYXA6IGNvbG9ybWFwLFxuICAgICAgICBsZXZlbHM6IFtbXSwgW10sIFtdXSxcbiAgICAgICAgc2hvd0NvbnRvdXI6IFt0cnVlLCB0cnVlLCB0cnVlXSxcbiAgICAgICAgc2hvd1N1cmZhY2U6ICFkYXRhLmhpZGVzdXJmYWNlLFxuICAgICAgICBjb250b3VyUHJvamVjdDogW1xuICAgICAgICAgICAgW2ZhbHNlLCBmYWxzZSwgZmFsc2VdLFxuICAgICAgICAgICAgW2ZhbHNlLCBmYWxzZSwgZmFsc2VdLFxuICAgICAgICAgICAgW2ZhbHNlLCBmYWxzZSwgZmFsc2VdXG4gICAgICAgIF0sXG4gICAgICAgIGNvbnRvdXJXaWR0aDogWzEsIDEsIDFdLFxuICAgICAgICBjb250b3VyQ29sb3I6IFtbMSwgMSwgMSwgMV0sIFsxLCAxLCAxLCAxXSwgWzEsIDEsIDEsIDFdXSxcbiAgICAgICAgY29udG91clRpbnQ6IFsxLCAxLCAxXSxcbiAgICAgICAgZHluYW1pY0NvbG9yOiBbWzEsIDEsIDEsIDFdLCBbMSwgMSwgMSwgMV0sIFsxLCAxLCAxLCAxXV0sXG4gICAgICAgIGR5bmFtaWNXaWR0aDogWzEsIDEsIDFdLFxuICAgICAgICBkeW5hbWljVGludDogWzEsIDEsIDFdLFxuICAgICAgICBvcGFjaXR5OiBkYXRhLm9wYWNpdHlcbiAgICB9O1xuXG4gICAgdmFyIGNPcHRzID0gZXh0cmFjdE9wdHMoZGF0YSk7XG4gICAgcGFyYW1zLmludGVuc2l0eUJvdW5kcyA9IFtjT3B0cy5taW4sIGNPcHRzLm1heF07XG5cbiAgICAvLyBSZWZpbmUgc3VyZmFjZSBjb2xvciBpZiBuZWNlc3NhcnlcbiAgICBpZihkYXRhLnN1cmZhY2Vjb2xvcikge1xuICAgICAgICB2YXIgaW50ZW5zaXR5ID0gbmRhcnJheShuZXcgRmxvYXQzMkFycmF5KHhsZW4gKiB5bGVuKSwgW3hsZW4sIHlsZW5dKTtcblxuICAgICAgICBmaWxsKGludGVuc2l0eSwgZnVuY3Rpb24ocm93LCBjb2wpIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRhLnN1cmZhY2Vjb2xvcltjb2xdW3Jvd107XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvb3Jkcy5wdXNoKGludGVuc2l0eSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gd2hlbiAneicgaXMgdXNlZCBhcyAnaW50ZW5zaXR5JyxcbiAgICAgICAgLy8gd2UgbXVzdCBzY2FsZSBpdHMgdmFsdWVcbiAgICAgICAgcGFyYW1zLmludGVuc2l0eUJvdW5kc1swXSAqPSBzY2FsZUZhY3RvclsyXTtcbiAgICAgICAgcGFyYW1zLmludGVuc2l0eUJvdW5kc1sxXSAqPSBzY2FsZUZhY3RvclsyXTtcbiAgICB9XG5cbiAgICBpZihNQVhfUkVTT0xVVElPTiA8IGNvb3Jkc1swXS5zaGFwZVswXSB8fFxuICAgICAgICBNQVhfUkVTT0xVVElPTiA8IGNvb3Jkc1swXS5zaGFwZVsxXSkge1xuICAgICAgICB0aGlzLnJlZmluZURhdGEgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZih0aGlzLnJlZmluZURhdGEgPT09IHRydWUpIHtcbiAgICAgICAgdGhpcy5kYXRhU2NhbGVYID0gdGhpcy5lc3RpbWF0ZVNjYWxlKGNvb3Jkc1swXS5zaGFwZVswXSwgMCk7XG4gICAgICAgIHRoaXMuZGF0YVNjYWxlWSA9IHRoaXMuZXN0aW1hdGVTY2FsZShjb29yZHNbMF0uc2hhcGVbMV0sIDEpO1xuICAgICAgICBpZih0aGlzLmRhdGFTY2FsZVggIT09IDEgfHwgdGhpcy5kYXRhU2NhbGVZICE9PSAxKSB7XG4gICAgICAgICAgICB0aGlzLnJlZmluZUNvb3Jkcyhjb29yZHMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoZGF0YS5zdXJmYWNlY29sb3IpIHtcbiAgICAgICAgcGFyYW1zLmludGVuc2l0eSA9IGNvb3Jkcy5wb3AoKTtcbiAgICB9XG5cbiAgICB2YXIgaGlnaGxpZ2h0RW5hYmxlID0gW3RydWUsIHRydWUsIHRydWVdO1xuICAgIHZhciBheGlzID0gWyd4JywgJ3knLCAneiddO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIHZhciBjb250b3VyUGFyYW1zID0gZGF0YS5jb250b3Vyc1theGlzW2ldXTtcbiAgICAgICAgaGlnaGxpZ2h0RW5hYmxlW2ldID0gY29udG91clBhcmFtcy5oaWdobGlnaHQ7XG5cbiAgICAgICAgcGFyYW1zLnNob3dDb250b3VyW2ldID0gY29udG91clBhcmFtcy5zaG93IHx8IGNvbnRvdXJQYXJhbXMuaGlnaGxpZ2h0O1xuICAgICAgICBpZighcGFyYW1zLnNob3dDb250b3VyW2ldKSBjb250aW51ZTtcblxuICAgICAgICBwYXJhbXMuY29udG91clByb2plY3RbaV0gPSBbXG4gICAgICAgICAgICBjb250b3VyUGFyYW1zLnByb2plY3QueCxcbiAgICAgICAgICAgIGNvbnRvdXJQYXJhbXMucHJvamVjdC55LFxuICAgICAgICAgICAgY29udG91clBhcmFtcy5wcm9qZWN0LnpcbiAgICAgICAgXTtcblxuICAgICAgICBpZihjb250b3VyUGFyYW1zLnNob3cpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd0NvbnRvdXJbaV0gPSB0cnVlO1xuICAgICAgICAgICAgcGFyYW1zLmxldmVsc1tpXSA9IGNvbnRvdXJMZXZlbHNbaV07XG4gICAgICAgICAgICBzdXJmYWNlLmhpZ2hsaWdodENvbG9yW2ldID0gcGFyYW1zLmNvbnRvdXJDb2xvcltpXSA9IHN0cjJSZ2JhQXJyYXkoY29udG91clBhcmFtcy5jb2xvcik7XG5cbiAgICAgICAgICAgIGlmKGNvbnRvdXJQYXJhbXMudXNlY29sb3JtYXApIHtcbiAgICAgICAgICAgICAgICBzdXJmYWNlLmhpZ2hsaWdodFRpbnRbaV0gPSBwYXJhbXMuY29udG91clRpbnRbaV0gPSAwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzdXJmYWNlLmhpZ2hsaWdodFRpbnRbaV0gPSBwYXJhbXMuY29udG91clRpbnRbaV0gPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGFyYW1zLmNvbnRvdXJXaWR0aFtpXSA9IGNvbnRvdXJQYXJhbXMud2lkdGg7XG5cbiAgICAgICAgICAgIHRoaXMuY29udG91clN0YXJ0W2ldID0gY29udG91clBhcmFtcy5zdGFydDtcbiAgICAgICAgICAgIHRoaXMuY29udG91ckVuZFtpXSA9IGNvbnRvdXJQYXJhbXMuZW5kO1xuICAgICAgICAgICAgdGhpcy5jb250b3VyU2l6ZVtpXSA9IGNvbnRvdXJQYXJhbXMuc2l6ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd0NvbnRvdXJbaV0gPSBmYWxzZTtcblxuICAgICAgICAgICAgdGhpcy5jb250b3VyU3RhcnRbaV0gPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5jb250b3VyRW5kW2ldID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuY29udG91clNpemVbaV0gPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoY29udG91clBhcmFtcy5oaWdobGlnaHQpIHtcbiAgICAgICAgICAgIHBhcmFtcy5keW5hbWljQ29sb3JbaV0gPSBzdHIyUmdiYUFycmF5KGNvbnRvdXJQYXJhbXMuaGlnaGxpZ2h0Y29sb3IpO1xuICAgICAgICAgICAgcGFyYW1zLmR5bmFtaWNXaWR0aFtpXSA9IGNvbnRvdXJQYXJhbXMuaGlnaGxpZ2h0d2lkdGg7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3Bsb3RseS9wbG90bHkuanMvaXNzdWVzLzk0MFxuICAgIGlmKGlzQ29sb3JtYXBDaXJjdWxhcihjb2xvcm1hcCkpIHtcbiAgICAgICAgcGFyYW1zLnZlcnRleENvbG9yID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBwYXJhbXMub2JqZWN0T2Zmc2V0ID0gdGhpcy5vYmplY3RPZmZzZXQ7XG5cbiAgICBwYXJhbXMuY29vcmRzID0gY29vcmRzO1xuICAgIHN1cmZhY2UudXBkYXRlKHBhcmFtcyk7XG5cbiAgICBzdXJmYWNlLnZpc2libGUgPSBkYXRhLnZpc2libGU7XG4gICAgc3VyZmFjZS5lbmFibGVEeW5hbWljID0gaGlnaGxpZ2h0RW5hYmxlO1xuICAgIHN1cmZhY2UuZW5hYmxlSGlnaGxpZ2h0ID0gaGlnaGxpZ2h0RW5hYmxlO1xuXG4gICAgc3VyZmFjZS5zbmFwVG9EYXRhID0gdHJ1ZTtcblxuICAgIGlmKCdsaWdodGluZycgaW4gZGF0YSkge1xuICAgICAgICBzdXJmYWNlLmFtYmllbnRMaWdodCA9IGRhdGEubGlnaHRpbmcuYW1iaWVudDtcbiAgICAgICAgc3VyZmFjZS5kaWZmdXNlTGlnaHQgPSBkYXRhLmxpZ2h0aW5nLmRpZmZ1c2U7XG4gICAgICAgIHN1cmZhY2Uuc3BlY3VsYXJMaWdodCA9IGRhdGEubGlnaHRpbmcuc3BlY3VsYXI7XG4gICAgICAgIHN1cmZhY2Uucm91Z2huZXNzID0gZGF0YS5saWdodGluZy5yb3VnaG5lc3M7XG4gICAgICAgIHN1cmZhY2UuZnJlc25lbCA9IGRhdGEubGlnaHRpbmcuZnJlc25lbDtcbiAgICB9XG5cbiAgICBpZignbGlnaHRwb3NpdGlvbicgaW4gZGF0YSkge1xuICAgICAgICBzdXJmYWNlLmxpZ2h0UG9zaXRpb24gPSBbZGF0YS5saWdodHBvc2l0aW9uLngsIGRhdGEubGlnaHRwb3NpdGlvbi55LCBkYXRhLmxpZ2h0cG9zaXRpb24uel07XG4gICAgfVxuXG4gICAgaWYoYWxwaGEgJiYgYWxwaGEgPCAxKSB7XG4gICAgICAgIHN1cmZhY2Uuc3VwcG9ydHNUcmFuc3BhcmVuY3kgPSB0cnVlO1xuICAgIH1cbn07XG5cbnByb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnNjZW5lLmdscGxvdC5yZW1vdmUodGhpcy5zdXJmYWNlKTtcbiAgICB0aGlzLnN1cmZhY2UuZGlzcG9zZSgpO1xufTtcblxuZnVuY3Rpb24gY3JlYXRlU3VyZmFjZVRyYWNlKHNjZW5lLCBkYXRhKSB7XG4gICAgdmFyIGdsID0gc2NlbmUuZ2xwbG90LmdsO1xuICAgIHZhciBzdXJmYWNlID0gY3JlYXRlU3VyZmFjZSh7IGdsOiBnbCB9KTtcbiAgICB2YXIgcmVzdWx0ID0gbmV3IFN1cmZhY2VUcmFjZShzY2VuZSwgc3VyZmFjZSwgZGF0YS51aWQpO1xuICAgIHN1cmZhY2UuX3RyYWNlID0gcmVzdWx0O1xuICAgIHJlc3VsdC51cGRhdGUoZGF0YSk7XG4gICAgc2NlbmUuZ2xwbG90LmFkZChzdXJmYWNlKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVN1cmZhY2VUcmFjZTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGVcIjo2MDUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZ2xfZm9ybWF0X2NvbG9yXCI6NzE2LFwiLi4vLi4vbGliL3N0cjJyZ2JhcnJheVwiOjc0MixcIi4uL2hlYXRtYXAvZmluZF9lbXB0aWVzXCI6MTAwNyxcIi4uL2hlYXRtYXAvaW50ZXJwMmRcIjoxMDEwLFwiZ2wtc3VyZmFjZTNkXCI6MzE2LFwibmRhcnJheVwiOjQ1MCxcIm5kYXJyYXktZmlsbFwiOjQ0MCxcIm5kYXJyYXktaG9tb2dyYXBoeVwiOjQ0Mn1dLDEyMjc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi8uLi9yZWdpc3RyeScpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xuXG52YXIgY29sb3JzY2FsZURlZmF1bHRzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN1cHBseURlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBkZWZhdWx0Q29sb3IsIGxheW91dCkge1xuICAgIHZhciBpLCBqO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciB4ID0gY29lcmNlKCd4Jyk7XG4gICAgdmFyIHkgPSBjb2VyY2UoJ3knKTtcblxuICAgIHZhciB6ID0gY29lcmNlKCd6Jyk7XG4gICAgaWYoIXogfHwgIXoubGVuZ3RoIHx8XG4gICAgICAgKHggPyAoeC5sZW5ndGggPCAxKSA6IGZhbHNlKSB8fFxuICAgICAgICh5ID8gKHkubGVuZ3RoIDwgMSkgOiBmYWxzZSlcbiAgICApIHtcbiAgICAgICAgdHJhY2VPdXQudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJhY2VPdXQuX3hsZW5ndGggPSAoQXJyYXkuaXNBcnJheSh4KSAmJiBMaWIuaXNBcnJheU9yVHlwZWRBcnJheSh4WzBdKSkgPyB6Lmxlbmd0aCA6IHpbMF0ubGVuZ3RoO1xuICAgIHRyYWNlT3V0Ll95bGVuZ3RoID0gei5sZW5ndGg7XG5cbiAgICB2YXIgaGFuZGxlQ2FsZW5kYXJEZWZhdWx0cyA9IFJlZ2lzdHJ5LmdldENvbXBvbmVudE1ldGhvZCgnY2FsZW5kYXJzJywgJ2hhbmRsZVRyYWNlRGVmYXVsdHMnKTtcbiAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKHRyYWNlSW4sIHRyYWNlT3V0LCBbJ3gnLCAneScsICd6J10sIGxheW91dCk7XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcbiAgICBjb2VyY2UoJ2hvdmVydGV4dCcpO1xuICAgIGNvZXJjZSgnaG92ZXJ0ZW1wbGF0ZScpO1xuXG4gICAgLy8gQ29lcmNlIHJlbWFpbmluZyBwcm9wZXJ0aWVzXG4gICAgW1xuICAgICAgICAnbGlnaHRpbmcuYW1iaWVudCcsXG4gICAgICAgICdsaWdodGluZy5kaWZmdXNlJyxcbiAgICAgICAgJ2xpZ2h0aW5nLnNwZWN1bGFyJyxcbiAgICAgICAgJ2xpZ2h0aW5nLnJvdWdobmVzcycsXG4gICAgICAgICdsaWdodGluZy5mcmVzbmVsJyxcbiAgICAgICAgJ2xpZ2h0cG9zaXRpb24ueCcsXG4gICAgICAgICdsaWdodHBvc2l0aW9uLnknLFxuICAgICAgICAnbGlnaHRwb3NpdGlvbi56JyxcbiAgICAgICAgJ2hpZGVzdXJmYWNlJyxcbiAgICAgICAgJ2Nvbm5lY3RnYXBzJyxcbiAgICAgICAgJ29wYWNpdHknXG4gICAgXS5mb3JFYWNoKGZ1bmN0aW9uKHgpIHsgY29lcmNlKHgpOyB9KTtcblxuICAgIHZhciBzdXJmYWNlQ29sb3IgPSBjb2VyY2UoJ3N1cmZhY2Vjb2xvcicpO1xuXG4gICAgdmFyIGRpbXMgPSBbJ3gnLCAneScsICd6J107XG4gICAgZm9yKGkgPSAwOyBpIDwgMzsgKytpKSB7XG4gICAgICAgIHZhciBjb250b3VyRGltID0gJ2NvbnRvdXJzLicgKyBkaW1zW2ldO1xuICAgICAgICB2YXIgc2hvdyA9IGNvZXJjZShjb250b3VyRGltICsgJy5zaG93Jyk7XG4gICAgICAgIHZhciBoaWdobGlnaHQgPSBjb2VyY2UoY29udG91ckRpbSArICcuaGlnaGxpZ2h0Jyk7XG5cbiAgICAgICAgaWYoc2hvdyB8fCBoaWdobGlnaHQpIHtcbiAgICAgICAgICAgIGZvcihqID0gMDsgaiA8IDM7ICsraikge1xuICAgICAgICAgICAgICAgIGNvZXJjZShjb250b3VyRGltICsgJy5wcm9qZWN0LicgKyBkaW1zW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHNob3cpIHtcbiAgICAgICAgICAgIGNvZXJjZShjb250b3VyRGltICsgJy5jb2xvcicpO1xuICAgICAgICAgICAgY29lcmNlKGNvbnRvdXJEaW0gKyAnLndpZHRoJyk7XG4gICAgICAgICAgICBjb2VyY2UoY29udG91ckRpbSArICcudXNlY29sb3JtYXAnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGhpZ2hsaWdodCkge1xuICAgICAgICAgICAgY29lcmNlKGNvbnRvdXJEaW0gKyAnLmhpZ2hsaWdodGNvbG9yJyk7XG4gICAgICAgICAgICBjb2VyY2UoY29udG91ckRpbSArICcuaGlnaGxpZ2h0d2lkdGgnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvZXJjZShjb250b3VyRGltICsgJy5zdGFydCcpO1xuICAgICAgICBjb2VyY2UoY29udG91ckRpbSArICcuZW5kJyk7XG4gICAgICAgIGNvZXJjZShjb250b3VyRGltICsgJy5zaXplJyk7XG4gICAgfVxuXG4gICAgLy8gYmFja3dhcmQgY29tcGF0aWJpbGl0eSBibG9ja1xuICAgIGlmKCFzdXJmYWNlQ29sb3IpIHtcbiAgICAgICAgbWFwTGVnYWN5KHRyYWNlSW4sICd6bWluJywgJ2NtaW4nKTtcbiAgICAgICAgbWFwTGVnYWN5KHRyYWNlSW4sICd6bWF4JywgJ2NtYXgnKTtcbiAgICAgICAgbWFwTGVnYWN5KHRyYWNlSW4sICd6YXV0bycsICdjYXV0bycpO1xuICAgIH1cblxuICAgIC8vIFRPRE8gaWYgY29udG91cnMuPy51c2Vjb2xvcm1hcCBhcmUgZmFsc2UgYW5kIGhpZGVzdXJmYWNlIGlzIHRydWVcbiAgICAvLyB0aGUgY29sb3JiYXIgc2hvdWxkbid0IGJlIHNob3duIGJ5IGRlZmF1bHRcblxuICAgIGNvbG9yc2NhbGVEZWZhdWx0cyhcbiAgICAgICAgdHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlLCB7cHJlZml4OiAnJywgY0xldHRlcjogJ2MnfVxuICAgICk7XG5cbiAgICAvLyBkaXNhYmxlIDFEIHRyYW5zZm9ybXMgLSBjdXJyZW50bHkgc3VyZmFjZSBkb2VzIE5PVCBzdXBwb3J0IGNvbHVtbiBkYXRhIGxpa2UgaGVhdG1hcCBkb2VzXG4gICAgLy8geW91IGNhbiB1c2UgbWVzaDNkIGZvciB0aGlzIHVzZSBjYXNlLCBidXQgbm90IHN1cmZhY2VcbiAgICB0cmFjZU91dC5fbGVuZ3RoID0gbnVsbDtcbn07XG5cbmZ1bmN0aW9uIG1hcExlZ2FjeSh0cmFjZUluLCBvbGRBdHRyLCBuZXdBdHRyKSB7XG4gICAgaWYob2xkQXR0ciBpbiB0cmFjZUluICYmICEobmV3QXR0ciBpbiB0cmFjZUluKSkge1xuICAgICAgICB0cmFjZUluW25ld0F0dHJdID0gdHJhY2VJbltvbGRBdHRyXTtcbiAgICB9XG59XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2RlZmF1bHRzXCI6NjAzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcmVnaXN0cnlcIjo4NDcsXCIuL2F0dHJpYnV0ZXNcIjoxMjI0fV0sMTIyODpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgY29sb3JiYXI6IHtcbiAgICAgICAgbWluOiAnY21pbicsXG4gICAgICAgIG1heDogJ2NtYXgnXG4gICAgfSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL2NvbnZlcnQnKSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3N1cmZhY2UnLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9nbDNkJyksXG4gICAgY2F0ZWdvcmllczogWydnbDNkJywgJzJkTWFwJywgJ25vT3BhY2l0eSddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9nbDNkXCI6ODA3LFwiLi9hdHRyaWJ1dGVzXCI6MTIyNCxcIi4vY2FsY1wiOjEyMjUsXCIuL2NvbnZlcnRcIjoxMjI2LFwiLi9kZWZhdWx0c1wiOjEyMjd9XSwxMjI5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGFubkF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9hbm5vdGF0aW9ucy9hdHRyaWJ1dGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIG92ZXJyaWRlQWxsID0gX2RlcmVxXygnLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlcycpLm92ZXJyaWRlQWxsO1xudmFyIGZvbnRBdHRycyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2ZvbnRfYXR0cmlidXRlcycpO1xudmFyIGRvbWFpbkF0dHJzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZG9tYWluJykuYXR0cmlidXRlcztcblxudmFyIEZPUk1BVF9MSU5LID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2RvY3MnKS5GT1JNQVRfTElOSztcblxudmFyIGF0dHJzID0gbW9kdWxlLmV4cG9ydHMgPSBvdmVycmlkZUFsbCh7XG4gICAgZG9tYWluOiBkb21haW5BdHRycyh7bmFtZTogJ3RhYmxlJywgdHJhY2U6IHRydWV9KSxcblxuICAgIGNvbHVtbndpZHRoOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBcbiAgICAgICAgXG4gICAgfSxcblxuICAgIGNvbHVtbm9yZGVyOiB7XG4gICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBoZWFkZXI6IHtcblxuICAgICAgICB2YWx1ZXM6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogW10sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBmb3JtYXQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdkYXRhX2FycmF5JyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZGZsdDogW10sXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBwcmVmaXg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIHN1ZmZpeDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgZGZsdDogbnVsbCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgaGVpZ2h0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIGRmbHQ6IDI4LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBhbGlnbjogZXh0ZW5kRmxhdCh7fSwgYW5uQXR0cnMuYWxpZ24sIHthcnJheU9rOiB0cnVlfSksXG5cbiAgICAgICAgbGluZToge1xuICAgICAgICAgICAgd2lkdGg6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRmbHQ6IDEsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICAgICAgZGZsdDogJ2dyZXknLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIGZpbGw6IHtcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICd3aGl0ZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgZm9udDogZXh0ZW5kRmxhdCh7fSwgZm9udEF0dHJzKHthcnJheU9rOiB0cnVlfSkpXG4gICAgfSxcblxuICAgIGNlbGxzOiB7XG5cbiAgICAgICAgdmFsdWVzOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IFtdLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgZm9ybWF0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IFtdLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgcHJlZml4OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcblxuICAgICAgICBzdWZmaXg6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgIGRmbHQ6IG51bGwsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuXG4gICAgICAgIGhlaWdodDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBkZmx0OiAyMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG5cbiAgICAgICAgYWxpZ246IGV4dGVuZEZsYXQoe30sIGFubkF0dHJzLmFsaWduLCB7YXJyYXlPazogdHJ1ZX0pLFxuXG4gICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkZmx0OiAxLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRmbHQ6ICdncmV5JyxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBmaWxsOiB7XG4gICAgICAgICAgICBjb2xvcjoge1xuICAgICAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICAgICAgYXJyYXlPazogdHJ1ZSxcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBkZmx0OiAnd2hpdGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIGZvbnQ6IGV4dGVuZEZsYXQoe30sIGZvbnRBdHRycyh7YXJyYXlPazogdHJ1ZX0pKVxuICAgIH1cbn0sICdjYWxjJywgJ2Zyb20tcm9vdCcpO1xuYXR0cnMudHJhbnNmb3JtcyA9IHVuZGVmaW5lZDtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2Fubm90YXRpb25zL2F0dHJpYnV0ZXNcIjo1NzYsXCIuLi8uLi9jb25zdGFudHMvZG9jc1wiOjY5MCxcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTAsXCIuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzXCI6NzUwLFwiLi4vLi4vcGxvdHMvZG9tYWluXCI6NzkyLFwiLi4vLi4vcGxvdHMvZm9udF9hdHRyaWJ1dGVzXCI6NzkzfV0sMTIzMDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBnZXRNb2R1bGVDYWxjRGF0YSA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2dldF9kYXRhJykuZ2V0TW9kdWxlQ2FsY0RhdGE7XG52YXIgdGFibGVQbG90ID0gX2RlcmVxXygnLi9wbG90Jyk7XG5cbnZhciBUQUJMRSA9ICd0YWJsZSc7XG5cbmV4cG9ydHMubmFtZSA9IFRBQkxFO1xuXG5leHBvcnRzLnBsb3QgPSBmdW5jdGlvbihnZCkge1xuICAgIHZhciBjYWxjRGF0YSA9IGdldE1vZHVsZUNhbGNEYXRhKGdkLmNhbGNkYXRhLCBUQUJMRSlbMF07XG4gICAgaWYoY2FsY0RhdGEubGVuZ3RoKSB0YWJsZVBsb3QoZ2QsIGNhbGNEYXRhKTtcbn07XG5cbmV4cG9ydHMuY2xlYW4gPSBmdW5jdGlvbihuZXdGdWxsRGF0YSwgbmV3RnVsbExheW91dCwgb2xkRnVsbERhdGEsIG9sZEZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgaGFkVGFibGUgPSAob2xkRnVsbExheW91dC5faGFzICYmIG9sZEZ1bGxMYXlvdXQuX2hhcyhUQUJMRSkpO1xuICAgIHZhciBoYXNUYWJsZSA9IChuZXdGdWxsTGF5b3V0Ll9oYXMgJiYgbmV3RnVsbExheW91dC5faGFzKFRBQkxFKSk7XG5cbiAgICBpZihoYWRUYWJsZSAmJiAhaGFzVGFibGUpIHtcbiAgICAgICAgb2xkRnVsbExheW91dC5fcGFwZXJkaXYuc2VsZWN0QWxsKCcudGFibGUnKS5yZW1vdmUoKTtcbiAgICB9XG59O1xuXG59LHtcIi4uLy4uL3Bsb3RzL2dldF9kYXRhXCI6ODAyLFwiLi9wbG90XCI6MTIzN31dLDEyMzE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgd3JhcCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9ndXAnKS53cmFwO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoKSB7XG4gICAgLy8gd2UgZG9uJ3QgYWN0dWFsbHkgbmVlZCB0byBpbmNsdWRlIHRoZSB0cmFjZSBoZXJlLCBzaW5jZSB0aGF0IHdpbGwgYmUgYWRkZWRcbiAgICAvLyBieSBQbG90cy5kb0NhbGNkYXRhLCBhbmQgdGhhdCdzIGFsbCB3ZSBhY3R1YWxseSBuZWVkIGxhdGVyLlxuICAgIHJldHVybiB3cmFwKHt9KTtcbn07XG5cbn0se1wiLi4vLi4vbGliL2d1cFwiOjcxN31dLDEyMzI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjZWxsUGFkOiA4LFxuICAgIGNvbHVtbkV4dGVudE9mZnNldDogMTAsXG4gICAgY29sdW1uVGl0bGVPZmZzZXQ6IDI4LFxuICAgIGVtcHR5SGVhZGVySGVpZ2h0OiAxNixcbiAgICBsYXRleENoZWNrOiAvXlxcJC4qXFwkJC8sXG4gICAgZ29sZGVuUmF0aW86IDEuNjE4LFxuICAgIGxpbmVCcmVha2VyOiAnPGJyPicsXG4gICAgbWF4RGltZW5zaW9uQ291bnQ6IDYwLFxuICAgIG92ZXJkcmFnOiA0NSxcbiAgICByZWxlYXNlVHJhbnNpdGlvbkR1cmF0aW9uOiAxMjAsXG4gICAgcmVsZWFzZVRyYW5zaXRpb25FYXNlOiAnY3ViaWMtb3V0JyxcbiAgICBzY3JvbGxiYXJDYXB0dXJlV2lkdGg6IDE4LFxuICAgIHNjcm9sbGJhckhpZGVEZWxheTogMTAwMCxcbiAgICBzY3JvbGxiYXJIaWRlRHVyYXRpb246IDEwMDAsXG4gICAgc2Nyb2xsYmFyT2Zmc2V0OiA1LFxuICAgIHNjcm9sbGJhcldpZHRoOiA4LFxuICAgIHRyYW5zaXRpb25EdXJhdGlvbjogMTAwLFxuICAgIHRyYW5zaXRpb25FYXNlOiAnY3ViaWMtb3V0JyxcbiAgICB1cGxpZnQ6IDUsXG4gICAgd3JhcFNwYWNlcjogJyAnLFxuICAgIHdyYXBTcGxpdENoYXJhY3RlcjogJyAnLFxuICAgIGNuOiB7XG4gICAgICAgIC8vIGdlbmVyYWwgY2xhc3MgbmFtZXNcbiAgICAgICAgdGFibGU6ICd0YWJsZScsXG4gICAgICAgIHRhYmxlQ29udHJvbFZpZXc6ICd0YWJsZS1jb250cm9sLXZpZXcnLFxuICAgICAgICBzY3JvbGxCYWNrZ3JvdW5kOiAnc2Nyb2xsLWJhY2tncm91bmQnLFxuICAgICAgICB5Q29sdW1uOiAneS1jb2x1bW4nLFxuICAgICAgICBjb2x1bW5CbG9jazogJ2NvbHVtbi1ibG9jaycsXG4gICAgICAgIHNjcm9sbEFyZWFDbGlwOiAnc2Nyb2xsLWFyZWEtY2xpcCcsXG4gICAgICAgIHNjcm9sbEFyZWFDbGlwUmVjdDogJ3Njcm9sbC1hcmVhLWNsaXAtcmVjdCcsXG4gICAgICAgIGNvbHVtbkJvdW5kYXJ5OiAnY29sdW1uLWJvdW5kYXJ5JyxcbiAgICAgICAgY29sdW1uQm91bmRhcnlDbGlwcGF0aDogJ2NvbHVtbi1ib3VuZGFyeS1jbGlwcGF0aCcsXG4gICAgICAgIGNvbHVtbkJvdW5kYXJ5UmVjdDogJ2NvbHVtbi1ib3VuZGFyeS1yZWN0JyxcbiAgICAgICAgY29sdW1uQ2VsbHM6ICdjb2x1bW4tY2VsbHMnLFxuICAgICAgICBjb2x1bW5DZWxsOiAnY29sdW1uLWNlbGwnLFxuICAgICAgICBjZWxsUmVjdDogJ2NlbGwtcmVjdCcsXG4gICAgICAgIGNlbGxUZXh0OiAnY2VsbC10ZXh0JyxcbiAgICAgICAgY2VsbFRleHRIb2xkZXI6ICdjZWxsLXRleHQtaG9sZGVyJyxcblxuICAgICAgICAvLyBzY3JvbGwgcmVsYXRlZCBjbGFzcyBuYW1lc1xuICAgICAgICBzY3JvbGxiYXJLaXQ6ICdzY3JvbGxiYXIta2l0JyxcbiAgICAgICAgc2Nyb2xsYmFyOiAnc2Nyb2xsYmFyJyxcbiAgICAgICAgc2Nyb2xsYmFyU2xpZGVyOiAnc2Nyb2xsYmFyLXNsaWRlcicsXG4gICAgICAgIHNjcm9sbGJhckdseXBoOiAnc2Nyb2xsYmFyLWdseXBoJyxcbiAgICAgICAgc2Nyb2xsYmFyQ2FwdHVyZVpvbmU6ICdzY3JvbGxiYXItY2FwdHVyZS16b25lJ1xuICAgIH1cbn07XG5cbn0se31dLDEyMzM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9leHRlbmQnKS5leHRlbmRGbGF0O1xudmFyIGlzTnVtZXJpYyA9IF9kZXJlcV8oJ2Zhc3QtaXNudW1lcmljJyk7XG5cbi8vIHB1cmUgZnVuY3Rpb25zLCBkb24ndCBhbHRlciBidXQgcGFzc2VzIG9uIGBnZGAgYW5kIHBhcnRzIG9mIGB0cmFjZWAgd2l0aG91dCBkZWVwIGNvcHlpbmdcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgY2VsbHNWYWx1ZXMgPSBzcXVhcmVTdHJpbmdNYXRyaXgodHJhY2UuY2VsbHMudmFsdWVzKTtcbiAgICB2YXIgc2xpY2VyID0gZnVuY3Rpb24oYSkge1xuICAgICAgICByZXR1cm4gYS5zbGljZSh0cmFjZS5oZWFkZXIudmFsdWVzLmxlbmd0aCwgYS5sZW5ndGgpO1xuICAgIH07XG4gICAgdmFyIGhlYWRlclZhbHVlc0luID0gc3F1YXJlU3RyaW5nTWF0cml4KHRyYWNlLmhlYWRlci52YWx1ZXMpO1xuICAgIGlmKGhlYWRlclZhbHVlc0luLmxlbmd0aCAmJiAhaGVhZGVyVmFsdWVzSW5bMF0ubGVuZ3RoKSB7XG4gICAgICAgIGhlYWRlclZhbHVlc0luWzBdID0gWycnXTtcbiAgICAgICAgaGVhZGVyVmFsdWVzSW4gPSBzcXVhcmVTdHJpbmdNYXRyaXgoaGVhZGVyVmFsdWVzSW4pO1xuICAgIH1cbiAgICB2YXIgaGVhZGVyVmFsdWVzID0gaGVhZGVyVmFsdWVzSW5cbiAgICAgICAgLmNvbmNhdChzbGljZXIoY2VsbHNWYWx1ZXMpLm1hcChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiBlbXB0eVN0cmluZ3MoKGhlYWRlclZhbHVlc0luWzBdIHx8IFsnJ10pLmxlbmd0aCk7XG4gICAgICAgIH0pKTtcblxuICAgIHZhciBkb21haW4gPSB0cmFjZS5kb21haW47XG4gICAgdmFyIGdyb3VwV2lkdGggPSBNYXRoLmZsb29yKGdkLl9mdWxsTGF5b3V0Ll9zaXplLncgKiAoZG9tYWluLnhbMV0gLSBkb21haW4ueFswXSkpO1xuICAgIHZhciBncm91cEhlaWdodCA9IE1hdGguZmxvb3IoZ2QuX2Z1bGxMYXlvdXQuX3NpemUuaCAqIChkb21haW4ueVsxXSAtIGRvbWFpbi55WzBdKSk7XG4gICAgdmFyIGhlYWRlclJvd0hlaWdodHMgPSB0cmFjZS5oZWFkZXIudmFsdWVzLmxlbmd0aCA/XG4gICAgICAgIGhlYWRlclZhbHVlc1swXS5tYXAoZnVuY3Rpb24oKSB7IHJldHVybiB0cmFjZS5oZWFkZXIuaGVpZ2h0OyB9KSA6XG4gICAgICAgIFtjLmVtcHR5SGVhZGVySGVpZ2h0XTtcbiAgICB2YXIgcm93SGVpZ2h0cyA9IGNlbGxzVmFsdWVzLmxlbmd0aCA/IGNlbGxzVmFsdWVzWzBdLm1hcChmdW5jdGlvbigpIHsgcmV0dXJuIHRyYWNlLmNlbGxzLmhlaWdodDsgfSkgOiBbXTtcbiAgICB2YXIgaGVhZGVySGVpZ2h0ID0gaGVhZGVyUm93SGVpZ2h0cy5yZWR1Y2Uoc3VtLCAwKTtcbiAgICB2YXIgc2Nyb2xsSGVpZ2h0ID0gZ3JvdXBIZWlnaHQgLSBoZWFkZXJIZWlnaHQ7XG4gICAgdmFyIG1pbmltdW1GaWxsSGVpZ2h0ID0gc2Nyb2xsSGVpZ2h0ICsgYy51cGxpZnQ7XG4gICAgdmFyIGFuY2hvclRvUm93QmxvY2sgPSBtYWtlQW5jaG9yVG9Sb3dCbG9jayhyb3dIZWlnaHRzLCBtaW5pbXVtRmlsbEhlaWdodCk7XG4gICAgdmFyIGFuY2hvclRvSGVhZGVyUm93QmxvY2sgPSBtYWtlQW5jaG9yVG9Sb3dCbG9jayhoZWFkZXJSb3dIZWlnaHRzLCBoZWFkZXJIZWlnaHQpO1xuICAgIHZhciBoZWFkZXJSb3dCbG9ja3MgPSBtYWtlUm93QmxvY2soYW5jaG9yVG9IZWFkZXJSb3dCbG9jaywgW10pO1xuICAgIHZhciByb3dCbG9ja3MgPSBtYWtlUm93QmxvY2soYW5jaG9yVG9Sb3dCbG9jaywgaGVhZGVyUm93QmxvY2tzKTtcbiAgICB2YXIgdW5pcXVlS2V5cyA9IHt9O1xuICAgIHZhciBjb2x1bW5PcmRlciA9IHRyYWNlLl9mdWxsSW5wdXQuY29sdW1ub3JkZXIuY29uY2F0KHNsaWNlcihjZWxsc1ZhbHVlcy5tYXAoZnVuY3Rpb24oZCwgaSkge3JldHVybiBpO30pKSk7XG4gICAgdmFyIGNvbHVtbldpZHRocyA9IGhlYWRlclZhbHVlcy5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgICB2YXIgdmFsdWUgPSBBcnJheS5pc0FycmF5KHRyYWNlLmNvbHVtbndpZHRoKSA/XG4gICAgICAgICAgICB0cmFjZS5jb2x1bW53aWR0aFtNYXRoLm1pbihpLCB0cmFjZS5jb2x1bW53aWR0aC5sZW5ndGggLSAxKV0gOlxuICAgICAgICAgICAgdHJhY2UuY29sdW1ud2lkdGg7XG4gICAgICAgIHJldHVybiBpc051bWVyaWModmFsdWUpID8gTnVtYmVyKHZhbHVlKSA6IDE7XG4gICAgfSk7XG4gICAgdmFyIHRvdGFsQ29sdW1uV2lkdGhzID0gY29sdW1uV2lkdGhzLnJlZHVjZShzdW0sIDApO1xuXG4gICAgLy8gZml0IGNvbHVtbnMgaW4gdGhlIGF2YWlsYWJsZSB2ZXJ0aWNhbCBzcGFjZSBhcyB0aGVyZSdzIG5vIHZlcnRpY2FsIHNjcm9sbGluZyBub3dcbiAgICBjb2x1bW5XaWR0aHMgPSBjb2x1bW5XaWR0aHMubWFwKGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQgLyB0b3RhbENvbHVtbldpZHRocyAqIGdyb3VwV2lkdGg7IH0pO1xuXG4gICAgdmFyIG1heExpbmVXaWR0aCA9IE1hdGgubWF4KGFycmF5TWF4KHRyYWNlLmhlYWRlci5saW5lLndpZHRoKSwgYXJyYXlNYXgodHJhY2UuY2VsbHMubGluZS53aWR0aCkpO1xuXG4gICAgdmFyIGNhbGNkYXRhID0ge1xuICAgICAgICAvLyBpbmNsdWRlIHN0YXRpY1Bsb3QgaW4gdGhlIGtleSBzbyBpZiBpdCBjaGFuZ2VzIHdlIGRlbGV0ZSBhbmQgcmVkcmF3XG4gICAgICAgIGtleTogdHJhY2UudWlkICsgZ2QuX2NvbnRleHQuc3RhdGljUGxvdCxcbiAgICAgICAgdHJhbnNsYXRlWDogZG9tYWluLnhbMF0gKiBnZC5fZnVsbExheW91dC5fc2l6ZS53LFxuICAgICAgICB0cmFuc2xhdGVZOiBnZC5fZnVsbExheW91dC5fc2l6ZS5oICogKDEgLSBkb21haW4ueVsxXSksXG4gICAgICAgIHNpemU6IGdkLl9mdWxsTGF5b3V0Ll9zaXplLFxuICAgICAgICB3aWR0aDogZ3JvdXBXaWR0aCxcbiAgICAgICAgbWF4TGluZVdpZHRoOiBtYXhMaW5lV2lkdGgsXG4gICAgICAgIGhlaWdodDogZ3JvdXBIZWlnaHQsXG4gICAgICAgIGNvbHVtbk9yZGVyOiBjb2x1bW5PcmRlciwgLy8gd2lsbCBiZSBtdXRhdGVkIG9uIGNvbHVtbiBtb3ZlLCB0b2RvIHVzZSBpbiBjYWxsYmFja1xuICAgICAgICBncm91cEhlaWdodDogZ3JvdXBIZWlnaHQsXG4gICAgICAgIHJvd0Jsb2Nrczogcm93QmxvY2tzLFxuICAgICAgICBoZWFkZXJSb3dCbG9ja3M6IGhlYWRlclJvd0Jsb2NrcyxcbiAgICAgICAgc2Nyb2xsWTogMCwgLy8gd2lsbCBiZSBtdXRhdGVkIG9uIHNjcm9sbFxuICAgICAgICBjZWxsczogZXh0ZW5kRmxhdCh7fSwgdHJhY2UuY2VsbHMsIHt2YWx1ZXM6IGNlbGxzVmFsdWVzfSksXG4gICAgICAgIGhlYWRlckNlbGxzOiBleHRlbmRGbGF0KHt9LCB0cmFjZS5oZWFkZXIsIHt2YWx1ZXM6IGhlYWRlclZhbHVlc30pLFxuICAgICAgICBnZENvbHVtbnM6IGhlYWRlclZhbHVlcy5tYXAoZnVuY3Rpb24oZCkge3JldHVybiBkWzBdO30pLFxuICAgICAgICBnZENvbHVtbnNPcmlnaW5hbE9yZGVyOiBoZWFkZXJWYWx1ZXMubWFwKGZ1bmN0aW9uKGQpIHtyZXR1cm4gZFswXTt9KSxcbiAgICAgICAgcHJldlBhZ2VzOiBbMCwgMF0sXG4gICAgICAgIHNjcm9sbGJhclN0YXRlOiB7c2Nyb2xsYmFyU2Nyb2xsSW5Qcm9ncmVzczogZmFsc2V9LFxuICAgICAgICBjb2x1bW5zOiBoZWFkZXJWYWx1ZXMubWFwKGZ1bmN0aW9uKGxhYmVsLCBpKSB7XG4gICAgICAgICAgICB2YXIgZm91bmRLZXkgPSB1bmlxdWVLZXlzW2xhYmVsXTtcbiAgICAgICAgICAgIHVuaXF1ZUtleXNbbGFiZWxdID0gKGZvdW5kS2V5IHx8IDApICsgMTtcbiAgICAgICAgICAgIHZhciBrZXkgPSBsYWJlbCArICdfXycgKyB1bmlxdWVLZXlzW2xhYmVsXTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAga2V5OiBrZXksXG4gICAgICAgICAgICAgICAgbGFiZWw6IGxhYmVsLFxuICAgICAgICAgICAgICAgIHNwZWNJbmRleDogaSxcbiAgICAgICAgICAgICAgICB4SW5kZXg6IGNvbHVtbk9yZGVyW2ldLFxuICAgICAgICAgICAgICAgIHhTY2FsZTogeFNjYWxlLFxuICAgICAgICAgICAgICAgIHg6IHVuZGVmaW5lZCwgLy8gaW5pdGlhbGl6ZWQgYmVsb3dcbiAgICAgICAgICAgICAgICBjYWxjZGF0YTogdW5kZWZpbmVkLCAvLyBpbml0aWFsaXplZCBiZWxvd1xuICAgICAgICAgICAgICAgIGNvbHVtbldpZHRoOiBjb2x1bW5XaWR0aHNbaV1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pXG4gICAgfTtcblxuICAgIGNhbGNkYXRhLmNvbHVtbnMuZm9yRWFjaChmdW5jdGlvbihjb2wpIHtcbiAgICAgICAgY29sLmNhbGNkYXRhID0gY2FsY2RhdGE7XG4gICAgICAgIGNvbC54ID0geFNjYWxlKGNvbCk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gY2FsY2RhdGE7XG59O1xuXG5mdW5jdGlvbiBhcnJheU1heChtYXliZUFycmF5KSB7XG4gICAgaWYoQXJyYXkuaXNBcnJheShtYXliZUFycmF5KSkge1xuICAgICAgICB2YXIgbWF4ID0gMDtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG1heWJlQXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG1heCA9IE1hdGgubWF4KG1heCwgYXJyYXlNYXgobWF5YmVBcnJheVtpXSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtYXg7XG4gICAgfVxuICAgIHJldHVybiBtYXliZUFycmF5O1xufVxuXG5mdW5jdGlvbiBzdW0oYSwgYikgeyByZXR1cm4gYSArIGI7IH1cblxuLy8gZmlsbCBtYXRyaXggaW4gcGxhY2UgdG8gZXF1YWwgbGVuZ3Roc1xuLy8gYW5kIGVuc3VyZSBpdCdzIHVuaWZvcm1seSAyRFxuZnVuY3Rpb24gc3F1YXJlU3RyaW5nTWF0cml4KG1hdHJpeEluKSB7XG4gICAgdmFyIG1hdHJpeCA9IG1hdHJpeEluLnNsaWNlKCk7XG4gICAgdmFyIG1pbkxlbiA9IEluZmluaXR5O1xuICAgIHZhciBtYXhMZW4gPSAwO1xuICAgIHZhciBpO1xuICAgIGZvcihpID0gMDsgaSA8IG1hdHJpeC5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZighQXJyYXkuaXNBcnJheShtYXRyaXhbaV0pKSBtYXRyaXhbaV0gPSBbbWF0cml4W2ldXTtcbiAgICAgICAgbWluTGVuID0gTWF0aC5taW4obWluTGVuLCBtYXRyaXhbaV0ubGVuZ3RoKTtcbiAgICAgICAgbWF4TGVuID0gTWF0aC5tYXgobWF4TGVuLCBtYXRyaXhbaV0ubGVuZ3RoKTtcbiAgICB9XG5cbiAgICBpZihtaW5MZW4gIT09IG1heExlbikge1xuICAgICAgICBmb3IoaSA9IDA7IGkgPCBtYXRyaXgubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBwYWRMZW4gPSBtYXhMZW4gLSBtYXRyaXhbaV0ubGVuZ3RoO1xuICAgICAgICAgICAgaWYocGFkTGVuKSBtYXRyaXhbaV0gPSBtYXRyaXhbaV0uY29uY2F0KGVtcHR5U3RyaW5ncyhwYWRMZW4pKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbWF0cml4O1xufVxuXG5mdW5jdGlvbiBlbXB0eVN0cmluZ3MobGVuKSB7XG4gICAgdmFyIHBhZEFycmF5ID0gbmV3IEFycmF5KGxlbik7XG4gICAgZm9yKHZhciBqID0gMDsgaiA8IGxlbjsgaisrKSBwYWRBcnJheVtqXSA9ICcnO1xuICAgIHJldHVybiBwYWRBcnJheTtcbn1cblxuZnVuY3Rpb24geFNjYWxlKGQpIHtcbiAgICByZXR1cm4gZC5jYWxjZGF0YS5jb2x1bW5zLnJlZHVjZShmdW5jdGlvbihwcmV2LCBuZXh0KSB7XG4gICAgICAgIHJldHVybiBuZXh0LnhJbmRleCA8IGQueEluZGV4ID8gcHJldiArIG5leHQuY29sdW1uV2lkdGggOiBwcmV2O1xuICAgIH0sIDApO1xufVxuXG5mdW5jdGlvbiBtYWtlUm93QmxvY2soYW5jaG9yVG9Sb3dCbG9jaywgYXV4aWxpYXJ5KSB7XG4gICAgdmFyIGJsb2NrQW5jaG9yS2V5cyA9IE9iamVjdC5rZXlzKGFuY2hvclRvUm93QmxvY2spO1xuICAgIHJldHVybiBibG9ja0FuY2hvcktleXMubWFwKGZ1bmN0aW9uKGspIHtyZXR1cm4gZXh0ZW5kRmxhdCh7fSwgYW5jaG9yVG9Sb3dCbG9ja1trXSwge2F1eGlsaWFyeUJsb2NrczogYXV4aWxpYXJ5fSk7fSk7XG59XG5cbmZ1bmN0aW9uIG1ha2VBbmNob3JUb1Jvd0Jsb2NrKHJvd0hlaWdodHMsIG1pbmltdW1GaWxsSGVpZ2h0KSB7XG4gICAgdmFyIGFuY2hvclRvUm93QmxvY2sgPSB7fTtcbiAgICB2YXIgY3VycmVudFJvd0hlaWdodDtcbiAgICB2YXIgY3VycmVudEFuY2hvciA9IDA7XG4gICAgdmFyIGN1cnJlbnRCbG9ja0hlaWdodCA9IDA7XG4gICAgdmFyIGN1cnJlbnRCbG9jayA9IG1ha2VJZGVudGl0eSgpO1xuICAgIHZhciBjdXJyZW50Rmlyc3RSb3dJbmRleCA9IDA7XG4gICAgdmFyIGJsb2NrQ291bnRlciA9IDA7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHJvd0hlaWdodHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY3VycmVudFJvd0hlaWdodCA9IHJvd0hlaWdodHNbaV07XG4gICAgICAgIGN1cnJlbnRCbG9jay5yb3dzLnB1c2goe1xuICAgICAgICAgICAgcm93SW5kZXg6IGksXG4gICAgICAgICAgICByb3dIZWlnaHQ6IGN1cnJlbnRSb3dIZWlnaHRcbiAgICAgICAgfSk7XG4gICAgICAgIGN1cnJlbnRCbG9ja0hlaWdodCArPSBjdXJyZW50Um93SGVpZ2h0O1xuICAgICAgICBpZihjdXJyZW50QmxvY2tIZWlnaHQgPj0gbWluaW11bUZpbGxIZWlnaHQgfHwgaSA9PT0gcm93SGVpZ2h0cy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBhbmNob3JUb1Jvd0Jsb2NrW2N1cnJlbnRBbmNob3JdID0gY3VycmVudEJsb2NrO1xuICAgICAgICAgICAgY3VycmVudEJsb2NrLmtleSA9IGJsb2NrQ291bnRlcisrO1xuICAgICAgICAgICAgY3VycmVudEJsb2NrLmZpcnN0Um93SW5kZXggPSBjdXJyZW50Rmlyc3RSb3dJbmRleDtcbiAgICAgICAgICAgIGN1cnJlbnRCbG9jay5sYXN0Um93SW5kZXggPSBpO1xuICAgICAgICAgICAgY3VycmVudEJsb2NrID0gbWFrZUlkZW50aXR5KCk7XG4gICAgICAgICAgICBjdXJyZW50QW5jaG9yICs9IGN1cnJlbnRCbG9ja0hlaWdodDtcbiAgICAgICAgICAgIGN1cnJlbnRGaXJzdFJvd0luZGV4ID0gaSArIDE7XG4gICAgICAgICAgICBjdXJyZW50QmxvY2tIZWlnaHQgPSAwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGFuY2hvclRvUm93QmxvY2s7XG59XG5cbmZ1bmN0aW9uIG1ha2VJZGVudGl0eSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBmaXJzdFJvd0luZGV4OiBudWxsLFxuICAgICAgICBsYXN0Um93SW5kZXg6IG51bGwsXG4gICAgICAgIHJvd3M6IFtdXG4gICAgfTtcbn1cblxufSx7XCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi9jb25zdGFudHNcIjoxMjMyLFwiZmFzdC1pc251bWVyaWNcIjoyMjV9XSwxMjM0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxuLy8gcHVyZSBmdW5jdGlvbnMsIGRvbid0IGFsdGVyIGJ1dCBwYXNzZXMgb24gYGdkYCBhbmQgcGFydHMgb2YgYHRyYWNlYCB3aXRob3V0IGRlZXAgY29weWluZ1xuXG5leHBvcnRzLnNwbGl0VG9QYW5lbHMgPSBmdW5jdGlvbihkKSB7XG4gICAgdmFyIHByZXZQYWdlcyA9IFswLCAwXTtcbiAgICB2YXIgaGVhZGVyUGFuZWwgPSBleHRlbmRGbGF0KHt9LCBkLCB7XG4gICAgICAgIGtleTogJ2hlYWRlcicsXG4gICAgICAgIHR5cGU6ICdoZWFkZXInLFxuICAgICAgICBwYWdlOiAwLFxuICAgICAgICBwcmV2UGFnZXM6IHByZXZQYWdlcyxcbiAgICAgICAgY3VycmVudFJlcGFpbnQ6IFtudWxsLCBudWxsXSxcbiAgICAgICAgZHJhZ0hhbmRsZTogdHJ1ZSxcbiAgICAgICAgdmFsdWVzOiBkLmNhbGNkYXRhLmhlYWRlckNlbGxzLnZhbHVlc1tkLnNwZWNJbmRleF0sXG4gICAgICAgIHJvd0Jsb2NrczogZC5jYWxjZGF0YS5oZWFkZXJSb3dCbG9ja3MsXG4gICAgICAgIGNhbGNkYXRhOiBleHRlbmRGbGF0KHt9LCBkLmNhbGNkYXRhLCB7Y2VsbHM6IGQuY2FsY2RhdGEuaGVhZGVyQ2VsbHN9KVxuICAgIH0pO1xuICAgIHZhciByZXZvbHZlclBhbmVsMSA9IGV4dGVuZEZsYXQoe30sIGQsIHtcbiAgICAgICAga2V5OiAnY2VsbHMxJyxcbiAgICAgICAgdHlwZTogJ2NlbGxzJyxcbiAgICAgICAgcGFnZTogMCxcbiAgICAgICAgcHJldlBhZ2VzOiBwcmV2UGFnZXMsXG4gICAgICAgIGN1cnJlbnRSZXBhaW50OiBbbnVsbCwgbnVsbF0sXG4gICAgICAgIGRyYWdIYW5kbGU6IGZhbHNlLFxuICAgICAgICB2YWx1ZXM6IGQuY2FsY2RhdGEuY2VsbHMudmFsdWVzW2Quc3BlY0luZGV4XSxcbiAgICAgICAgcm93QmxvY2tzOiBkLmNhbGNkYXRhLnJvd0Jsb2Nrc1xuICAgIH0pO1xuICAgIHZhciByZXZvbHZlclBhbmVsMiA9IGV4dGVuZEZsYXQoe30sIGQsIHtcbiAgICAgICAga2V5OiAnY2VsbHMyJyxcbiAgICAgICAgdHlwZTogJ2NlbGxzJyxcbiAgICAgICAgcGFnZTogMSxcbiAgICAgICAgcHJldlBhZ2VzOiBwcmV2UGFnZXMsXG4gICAgICAgIGN1cnJlbnRSZXBhaW50OiBbbnVsbCwgbnVsbF0sXG4gICAgICAgIGRyYWdIYW5kbGU6IGZhbHNlLFxuICAgICAgICB2YWx1ZXM6IGQuY2FsY2RhdGEuY2VsbHMudmFsdWVzW2Quc3BlY0luZGV4XSxcbiAgICAgICAgcm93QmxvY2tzOiBkLmNhbGNkYXRhLnJvd0Jsb2Nrc1xuICAgIH0pO1xuICAgIC8vIG9yZGVyIGR1ZSB0byBTVkcgdXNpbmcgcGFpbnRlcidzIGFsZ286XG4gICAgcmV0dXJuIFtyZXZvbHZlclBhbmVsMSwgcmV2b2x2ZXJQYW5lbDIsIGhlYWRlclBhbmVsXTtcbn07XG5cbmV4cG9ydHMuc3BsaXRUb0NlbGxzID0gZnVuY3Rpb24oZCkge1xuICAgIHZhciBmcm9tVG8gPSByb3dGcm9tVG8oZCk7XG4gICAgcmV0dXJuIChkLnZhbHVlcyB8fCBbXSkuc2xpY2UoZnJvbVRvWzBdLCBmcm9tVG9bMV0pLm1hcChmdW5jdGlvbih2LCBpKSB7XG4gICAgICAgIC8vIEJ5IGtlZXBpbmcgaWRlbnRpY2FsIGtleSwgYSBET00gbm9kZSByZW1vdmFsLCBjcmVhdGlvbiBhbmQgYWRkaXRpb24gaXMgc3BhcmVkLCBpbXBvcnRhbnQgd2hlbiB2aXNpYmxlXG4gICAgICAgIC8vIGdyaWQgaGFzIGEgbG90IG9mIGVsZW1lbnRzIChxdWFkcmF0aWMgd2l0aCB4Y29sL3ljb2wgY291bnQpLlxuICAgICAgICAvLyBCdXQgaXQgaGFzIHRvIGJlIGJ1c3RlZCB3aGVuIGBzdmdVdGlsLmNvbnZlcnRUb1RzcGFuc2AgaXMgdXNlZCBhcyBpdCByZXNoYXBlcyBjZWxsIHN1YnRyZWVzIGFzeW5jaHJvbm91c2x5LFxuICAgICAgICAvLyBhbmQgYnkgdGhhdCB0aW1lIHRoZSB1c2VyIG1heSBoYXZlIHNjcm9sbGVkIGF3YXksIHJlc3VsdGluZyBpbiBzdGFsZSBvdmVyd3JpdGVzLiBUaGUgcmVhbCBzb2x1dGlvbiB3aWxsIGJlXG4gICAgICAgIC8vIHRvIHR1cm4gYHN2Z1V0aWwuY29udmVydFRvVHNwYW5zYCBpbnRvIGEgY2FuY2VsYWJsZSByZXF1ZXN0LCBpbiB3aGljaCBjYXNlIG5vIGtleSBidXN0aW5nIGlzIG5lZWRlZC5cbiAgICAgICAgdmFyIGJ1c3RlciA9ICh0eXBlb2YgdiA9PT0gJ3N0cmluZycpICYmIHYubWF0Y2goL1s8JCY+IF0vKSA/ICdfa2V5YnVzdGVyXycgKyBNYXRoLnJhbmRvbSgpIDogJyc7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAvLyBrZXlXaXRoaW5CbG9jazogLypmcm9tVG9bMF0gKyAqL2ksIC8vIG9wdGltaXplZCBmdXR1cmUgdmVyc2lvbiAtIG5vIGJ1c3RpbmdcbiAgICAgICAgICAgIC8vIGtleVdpdGhpbkJsb2NrOiBmcm9tVG9bMF0gKyBpLCAvLyBpbml0aWFsIGFsd2F5cy11bm9wdGltaXplZCB2ZXJzaW9uIC0gamFua3kgc2Nyb2xsaW5nIHdpdGggNSsgY29sdW1uc1xuICAgICAgICAgICAga2V5V2l0aGluQmxvY2s6IGkgKyBidXN0ZXIsIC8vIGN1cnJlbnQgY29tcHJvbWlzZTogcmVndWxhciBjb250ZW50IGlzIHZlcnkgZmFzdDsgYXN5bmMgY29udGVudCBpcyBwb3NzaWJsZVxuICAgICAgICAgICAga2V5OiBmcm9tVG9bMF0gKyBpLFxuICAgICAgICAgICAgY29sdW1uOiBkLFxuICAgICAgICAgICAgY2FsY2RhdGE6IGQuY2FsY2RhdGEsXG4gICAgICAgICAgICBwYWdlOiBkLnBhZ2UsXG4gICAgICAgICAgICByb3dCbG9ja3M6IGQucm93QmxvY2tzLFxuICAgICAgICAgICAgdmFsdWU6IHZcbiAgICAgICAgfTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIHJvd0Zyb21UbyhkKSB7XG4gICAgdmFyIHJvd0Jsb2NrID0gZC5yb3dCbG9ja3NbZC5wYWdlXTtcbiAgICAvLyBmaXhtZSByb3dCbG9jayB0cnV0aGluZXNzIGNoZWNrIGlzIGR1ZSB0byB1Z2x5IGhhY2sgb2YgcGxhY2luZyAybmQgcGFuZWwgYXMgZC5wYWdlID0gLTFcbiAgICB2YXIgcm93RnJvbSA9IHJvd0Jsb2NrID8gcm93QmxvY2sucm93c1swXS5yb3dJbmRleCA6IDA7XG4gICAgdmFyIHJvd1RvID0gcm93QmxvY2sgPyByb3dGcm9tICsgcm93QmxvY2sucm93cy5sZW5ndGggOiAwO1xuICAgIHJldHVybiBbcm93RnJvbSwgcm93VG9dO1xufVxuXG59LHtcIi4uLy4uL2xpYi9leHRlbmRcIjo3MTB9XSwxMjM1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIGF0dHJpYnV0ZXMgPSBfZGVyZXFfKCcuL2F0dHJpYnV0ZXMnKTtcbnZhciBoYW5kbGVEb21haW5EZWZhdWx0cyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2RvbWFpbicpLmRlZmF1bHRzO1xuXG5mdW5jdGlvbiBkZWZhdWx0Q29sdW1uT3JkZXIodHJhY2VPdXQsIGNvZXJjZSkge1xuICAgIHZhciBzcGVjaWZpZWRDb2x1bW5PcmRlciA9IHRyYWNlT3V0LmNvbHVtbm9yZGVyIHx8IFtdO1xuICAgIHZhciBjb21tb25MZW5ndGggPSB0cmFjZU91dC5oZWFkZXIudmFsdWVzLmxlbmd0aDtcbiAgICB2YXIgdHJ1bmNhdGVkID0gc3BlY2lmaWVkQ29sdW1uT3JkZXIuc2xpY2UoMCwgY29tbW9uTGVuZ3RoKTtcbiAgICB2YXIgc29ydGVkID0gdHJ1bmNhdGVkLnNsaWNlKCkuc29ydChmdW5jdGlvbihhLCBiKSB7cmV0dXJuIGEgLSBiO30pO1xuICAgIHZhciBvbmVTdGVwcGVkID0gdHJ1bmNhdGVkLm1hcChmdW5jdGlvbihkKSB7cmV0dXJuIHNvcnRlZC5pbmRleE9mKGQpO30pO1xuICAgIGZvcih2YXIgaSA9IG9uZVN0ZXBwZWQubGVuZ3RoOyBpIDwgY29tbW9uTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgb25lU3RlcHBlZC5wdXNoKGkpO1xuICAgIH1cbiAgICBjb2VyY2UoJ2NvbHVtbm9yZGVyJywgb25lU3RlcHBlZCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIGhhbmRsZURvbWFpbkRlZmF1bHRzKHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSk7XG5cbiAgICBjb2VyY2UoJ2NvbHVtbndpZHRoJyk7XG5cbiAgICBjb2VyY2UoJ2hlYWRlci52YWx1ZXMnKTtcbiAgICBjb2VyY2UoJ2hlYWRlci5mb3JtYXQnKTtcbiAgICBjb2VyY2UoJ2hlYWRlci5hbGlnbicpO1xuXG4gICAgY29lcmNlKCdoZWFkZXIucHJlZml4Jyk7XG4gICAgY29lcmNlKCdoZWFkZXIuc3VmZml4Jyk7XG4gICAgY29lcmNlKCdoZWFkZXIuaGVpZ2h0Jyk7XG4gICAgY29lcmNlKCdoZWFkZXIubGluZS53aWR0aCcpO1xuICAgIGNvZXJjZSgnaGVhZGVyLmxpbmUuY29sb3InKTtcbiAgICBjb2VyY2UoJ2hlYWRlci5maWxsLmNvbG9yJyk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnaGVhZGVyLmZvbnQnLCBMaWIuZXh0ZW5kRmxhdCh7fSwgbGF5b3V0LmZvbnQpKTtcblxuICAgIGRlZmF1bHRDb2x1bW5PcmRlcih0cmFjZU91dCwgY29lcmNlKTtcblxuICAgIGNvZXJjZSgnY2VsbHMudmFsdWVzJyk7XG4gICAgY29lcmNlKCdjZWxscy5mb3JtYXQnKTtcbiAgICBjb2VyY2UoJ2NlbGxzLmFsaWduJyk7XG4gICAgY29lcmNlKCdjZWxscy5wcmVmaXgnKTtcbiAgICBjb2VyY2UoJ2NlbGxzLnN1ZmZpeCcpO1xuICAgIGNvZXJjZSgnY2VsbHMuaGVpZ2h0Jyk7XG4gICAgY29lcmNlKCdjZWxscy5saW5lLndpZHRoJyk7XG4gICAgY29lcmNlKCdjZWxscy5saW5lLmNvbG9yJyk7XG4gICAgY29lcmNlKCdjZWxscy5maWxsLmNvbG9yJyk7XG4gICAgTGliLmNvZXJjZUZvbnQoY29lcmNlLCAnY2VsbHMuZm9udCcsIExpYi5leHRlbmRGbGF0KHt9LCBsYXlvdXQuZm9udCkpO1xuXG4gICAgLy8gZGlzYWJsZSAxRCB0cmFuc2Zvcm1zXG4gICAgdHJhY2VPdXQuX2xlbmd0aCA9IG51bGw7XG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2RvbWFpblwiOjc5MixcIi4vYXR0cmlidXRlc1wiOjEyMjl9XSwxMjM2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXR0cmlidXRlczogX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyksXG4gICAgc3VwcGx5RGVmYXVsdHM6IF9kZXJlcV8oJy4vZGVmYXVsdHMnKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3RhYmxlJyxcbiAgICBiYXNlUGxvdE1vZHVsZTogX2RlcmVxXygnLi9iYXNlX3Bsb3QnKSxcbiAgICBjYXRlZ29yaWVzOiBbJ25vT3BhY2l0eSddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuL2F0dHJpYnV0ZXNcIjoxMjI5LFwiLi9iYXNlX3Bsb3RcIjoxMjMwLFwiLi9jYWxjXCI6MTIzMSxcIi4vZGVmYXVsdHNcIjoxMjM1LFwiLi9wbG90XCI6MTIzN31dLDEyMzc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYyA9IF9kZXJlcV8oJy4vY29uc3RhbnRzJyk7XG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIGd1cCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9ndXAnKTtcbnZhciBEcmF3aW5nID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nJyk7XG52YXIgc3ZnVXRpbCA9IF9kZXJlcV8oJy4uLy4uL2xpYi9zdmdfdGV4dF91dGlscycpO1xudmFyIHJhaXNlVG9Ub3AgPSBfZGVyZXFfKCcuLi8uLi9saWInKS5yYWlzZVRvVG9wO1xudmFyIGNhbmNlbEVlYXNlQ29sdW1uID0gX2RlcmVxXygnLi4vLi4vbGliJykuY2FuY2VsVHJhbnNpdGlvbjtcbnZhciBwcmVwYXJlRGF0YSA9IF9kZXJlcV8oJy4vZGF0YV9wcmVwYXJhdGlvbl9oZWxwZXInKTtcbnZhciBzcGxpdERhdGEgPSBfZGVyZXFfKCcuL2RhdGFfc3BsaXRfaGVscGVycycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHdyYXBwZWRUcmFjZUhvbGRlcnMpIHtcbiAgICB2YXIgZHluYW1pYyA9ICFnZC5fY29udGV4dC5zdGF0aWNQbG90O1xuXG4gICAgdmFyIHRhYmxlID0gZ2QuX2Z1bGxMYXlvdXQuX3BhcGVyLnNlbGVjdEFsbCgnLicgKyBjLmNuLnRhYmxlKVxuICAgICAgICAuZGF0YSh3cmFwcGVkVHJhY2VIb2xkZXJzLm1hcChmdW5jdGlvbih3cmFwcGVkVHJhY2VIb2xkZXIpIHtcbiAgICAgICAgICAgIHZhciB0cmFjZUhvbGRlciA9IGd1cC51bndyYXAod3JhcHBlZFRyYWNlSG9sZGVyKTtcbiAgICAgICAgICAgIHZhciB0cmFjZSA9IHRyYWNlSG9sZGVyLnRyYWNlO1xuICAgICAgICAgICAgcmV0dXJuIHByZXBhcmVEYXRhKGdkLCB0cmFjZSk7XG4gICAgICAgIH0pLCBndXAua2V5RnVuKTtcblxuICAgIHRhYmxlLmV4aXQoKS5yZW1vdmUoKTtcblxuICAgIHRhYmxlLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24udGFibGUsIHRydWUpXG4gICAgICAgIC5hdHRyKCdvdmVyZmxvdycsICd2aXNpYmxlJylcbiAgICAgICAgLnN0eWxlKCdib3gtc2l6aW5nJywgJ2NvbnRlbnQtYm94JylcbiAgICAgICAgLnN0eWxlKCdwb3NpdGlvbicsICdhYnNvbHV0ZScpXG4gICAgICAgIC5zdHlsZSgnbGVmdCcsIDApXG4gICAgICAgIC5zdHlsZSgnb3ZlcmZsb3cnLCAndmlzaWJsZScpXG4gICAgICAgIC5zdHlsZSgnc2hhcGUtcmVuZGVyaW5nJywgJ2NyaXNwRWRnZXMnKVxuICAgICAgICAuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpO1xuXG4gICAgdGFibGVcbiAgICAgICAgLmF0dHIoJ3dpZHRoJywgZnVuY3Rpb24oZCkge3JldHVybiBkLndpZHRoICsgZC5zaXplLmwgKyBkLnNpemUucjt9KVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCkge3JldHVybiBkLmhlaWdodCArIGQuc2l6ZS50ICsgZC5zaXplLmI7fSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyBkLnRyYW5zbGF0ZVggKyAnLCcgKyBkLnRyYW5zbGF0ZVkgKyAnKSc7XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIHRhYmxlQ29udHJvbFZpZXcgPSB0YWJsZS5zZWxlY3RBbGwoJy4nICsgYy5jbi50YWJsZUNvbnRyb2xWaWV3KVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIHZhciBjdkVudGVyID0gdGFibGVDb250cm9sVmlldy5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnRhYmxlQ29udHJvbFZpZXcsIHRydWUpXG4gICAgICAgIC5zdHlsZSgnYm94LXNpemluZycsICdjb250ZW50LWJveCcpO1xuICAgIGlmKGR5bmFtaWMpIHtcbiAgICAgICAgY3ZFbnRlclxuICAgICAgICAgICAgLm9uKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgdGFibGVDb250cm9sVmlld1xuICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uKGRkKSB7cmV0dXJuIGQgPT09IGRkO30pXG4gICAgICAgICAgICAgICAgICAgIC5jYWxsKHJlbmRlclNjcm9sbGJhcktpdCwgZ2QpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5vbignbW91c2V3aGVlbCcsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBpZihkLnNjcm9sbGJhclN0YXRlLndoZWVsaW5nKSByZXR1cm47XG4gICAgICAgICAgICAgICAgZC5zY3JvbGxiYXJTdGF0ZS53aGVlbGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld1kgPSBkLnNjcm9sbFkgKyBkMy5ldmVudC5kZWx0YVk7XG4gICAgICAgICAgICAgICAgdmFyIG5vQ2hhbmdlID0gbWFrZURyYWdSb3coZ2QsIHRhYmxlQ29udHJvbFZpZXcsIG51bGwsIG5ld1kpKGQpO1xuICAgICAgICAgICAgICAgIGlmKCFub0NoYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICBkMy5ldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgZDMuZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZC5zY3JvbGxiYXJTdGF0ZS53aGVlbGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYWxsKHJlbmRlclNjcm9sbGJhcktpdCwgZ2QsIHRydWUpO1xuICAgIH1cblxuICAgIHRhYmxlQ29udHJvbFZpZXdcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gJ3RyYW5zbGF0ZSgnICsgZC5zaXplLmwgKyAnICcgKyBkLnNpemUudCArICcpJzt9KTtcblxuICAgIC8vIHNjcm9sbEJhY2tncm91bmQgbWVyZWx5IGVuc3VyZXMgdGhhdCBtb3VzZSBldmVudHMgYXJlIGNhcHR1cmVkIGV2ZW4gb24gY3JhenkgZmFzdCBzY3JvbGx3aGVlbGluZ1xuICAgIC8vIG90aGVyd2lzZSByZW5kZXJpbmcgZ2xpdGNoZXMgbWF5IG9jY3VyXG4gICAgdmFyIHNjcm9sbEJhY2tncm91bmQgPSB0YWJsZUNvbnRyb2xWaWV3LnNlbGVjdEFsbCgnLicgKyBjLmNuLnNjcm9sbEJhY2tncm91bmQpXG4gICAgICAgIC5kYXRhKGd1cC5yZXBlYXQsIGd1cC5rZXlGdW4pO1xuXG4gICAgc2Nyb2xsQmFja2dyb3VuZC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNjcm9sbEJhY2tncm91bmQsIHRydWUpXG4gICAgICAgIC5hdHRyKCdmaWxsJywgJ25vbmUnKTtcblxuICAgIHNjcm9sbEJhY2tncm91bmRcbiAgICAgICAgLmF0dHIoJ3dpZHRoJywgZnVuY3Rpb24oZCkge3JldHVybiBkLndpZHRoO30pXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuaGVpZ2h0O30pO1xuXG4gICAgdGFibGVDb250cm9sVmlldy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKGQzLnNlbGVjdCh0aGlzKSwgc2Nyb2xsQXJlYUJvdHRvbUNsaXBLZXkoZ2QsIGQpLCBnZCk7XG4gICAgfSk7XG5cbiAgICB2YXIgeUNvbHVtbiA9IHRhYmxlQ29udHJvbFZpZXcuc2VsZWN0QWxsKCcuJyArIGMuY24ueUNvbHVtbilcbiAgICAgICAgLmRhdGEoZnVuY3Rpb24odm0pIHtyZXR1cm4gdm0uY29sdW1uczt9LCBndXAua2V5RnVuKTtcblxuICAgIHlDb2x1bW4uZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi55Q29sdW1uLCB0cnVlKTtcblxuICAgIHlDb2x1bW4uZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgeUNvbHVtbi5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbihkKSB7cmV0dXJuICd0cmFuc2xhdGUoJyArIGQueCArICcgMCknO30pO1xuXG4gICAgaWYoZHluYW1pYykge1xuICAgICAgICB5Q29sdW1uLmNhbGwoZDMuYmVoYXZpb3IuZHJhZygpXG4gICAgICAgICAgICAub3JpZ2luKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB2YXIgbW92ZWRDb2x1bW4gPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgICAgICAgICAgZWFzZUNvbHVtbihtb3ZlZENvbHVtbiwgZCwgLWMudXBsaWZ0KTtcbiAgICAgICAgICAgICAgICByYWlzZVRvVG9wKHRoaXMpO1xuICAgICAgICAgICAgICAgIGQuY2FsY2RhdGEuY29sdW1uRHJhZ0luUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJlbmRlclNjcm9sbGJhcktpdCh0YWJsZUNvbnRyb2xWaWV3LmZpbHRlcihmdW5jdGlvbihkZCkge3JldHVybiBkLmNhbGNkYXRhLmtleSA9PT0gZGQua2V5O30pLCBnZCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdkcmFnJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgIHZhciBtb3ZlZENvbHVtbiA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgICAgICB2YXIgZ2V0dGVyID0gZnVuY3Rpb24oZGQpIHtyZXR1cm4gKGQgPT09IGRkID8gZDMuZXZlbnQueCA6IGRkLngpICsgZGQuY29sdW1uV2lkdGggLyAyO307XG4gICAgICAgICAgICAgICAgZC54ID0gTWF0aC5tYXgoLWMub3ZlcmRyYWcsIE1hdGgubWluKGQuY2FsY2RhdGEud2lkdGggKyBjLm92ZXJkcmFnIC0gZC5jb2x1bW5XaWR0aCwgZDMuZXZlbnQueCkpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHNvcnRhYmxlQ29sdW1ucyA9IGZsYXREYXRhKHlDb2x1bW4pLmZpbHRlcihmdW5jdGlvbihkZCkge3JldHVybiBkZC5jYWxjZGF0YS5rZXkgPT09IGQuY2FsY2RhdGEua2V5O30pO1xuICAgICAgICAgICAgICAgIHZhciBuZXdPcmRlciA9IHNvcnRhYmxlQ29sdW1ucy5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtyZXR1cm4gZ2V0dGVyKGEpIC0gZ2V0dGVyKGIpO30pO1xuICAgICAgICAgICAgICAgIG5ld09yZGVyLmZvckVhY2goZnVuY3Rpb24oZGQsIGkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGQueEluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgZGQueCA9IGQgPT09IGRkID8gZGQueCA6IGRkLnhTY2FsZShkZCk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICB5Q29sdW1uLmZpbHRlcihmdW5jdGlvbihkZCkge3JldHVybiBkICE9PSBkZDt9KVxuICAgICAgICAgICAgICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgICAgICAgICAgICAgIC5lYXNlKGMudHJhbnNpdGlvbkVhc2UpXG4gICAgICAgICAgICAgICAgICAgIC5kdXJhdGlvbihjLnRyYW5zaXRpb25EdXJhdGlvbilcbiAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gJ3RyYW5zbGF0ZSgnICsgZC54ICsgJyAwKSc7fSk7XG4gICAgICAgICAgICAgICAgbW92ZWRDb2x1bW5cbiAgICAgICAgICAgICAgICAgICAgLmNhbGwoY2FuY2VsRWVhc2VDb2x1bW4pXG4gICAgICAgICAgICAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlKCcgKyBkLnggKyAnIC0nICsgYy51cGxpZnQgKyAnICknKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAub24oJ2RyYWdlbmQnLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1vdmVkQ29sdW1uID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgICAgIHZhciBwID0gZC5jYWxjZGF0YTtcbiAgICAgICAgICAgICAgICBkLnggPSBkLnhTY2FsZShkKTtcbiAgICAgICAgICAgICAgICBkLmNhbGNkYXRhLmNvbHVtbkRyYWdJblByb2dyZXNzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZWFzZUNvbHVtbihtb3ZlZENvbHVtbiwgZCwgMCk7XG4gICAgICAgICAgICAgICAgY29sdW1uTW92ZWQoZ2QsIHAsIHAuY29sdW1ucy5tYXAoZnVuY3Rpb24oZGQpIHtyZXR1cm4gZGQueEluZGV4O30pKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgeUNvbHVtbi5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgRHJhd2luZy5zZXRDbGlwVXJsKGQzLnNlbGVjdCh0aGlzKSwgY29sdW1uQm91bmRhcnlDbGlwS2V5KGdkLCBkKSwgZ2QpO1xuICAgIH0pO1xuXG4gICAgdmFyIGNvbHVtbkJsb2NrID0geUNvbHVtbi5zZWxlY3RBbGwoJy4nICsgYy5jbi5jb2x1bW5CbG9jaylcbiAgICAgICAgLmRhdGEoc3BsaXREYXRhLnNwbGl0VG9QYW5lbHMsIGd1cC5rZXlGdW4pO1xuXG4gICAgY29sdW1uQmxvY2suZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5jb2x1bW5CbG9jaywgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2lkJywgZnVuY3Rpb24oZCkge3JldHVybiBkLmtleTt9KTtcblxuICAgIGNvbHVtbkJsb2NrXG4gICAgICAgIC5zdHlsZSgnY3Vyc29yJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuZHJhZ0hhbmRsZSA/ICdldy1yZXNpemUnIDogZC5jYWxjZGF0YS5zY3JvbGxiYXJTdGF0ZS5iYXJXaWdnbGVSb29tID8gJ25zLXJlc2l6ZScgOiAnZGVmYXVsdCc7XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIGhlYWRlckNvbHVtbkJsb2NrID0gY29sdW1uQmxvY2suZmlsdGVyKGhlYWRlckJsb2NrKTtcbiAgICB2YXIgY2VsbHNDb2x1bW5CbG9jayA9IGNvbHVtbkJsb2NrLmZpbHRlcihjZWxsc0Jsb2NrKTtcblxuICAgIGlmKGR5bmFtaWMpIHtcbiAgICAgICAgY2VsbHNDb2x1bW5CbG9jay5jYWxsKGQzLmJlaGF2aW9yLmRyYWcoKVxuICAgICAgICAgICAgLm9yaWdpbihmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICAgICAgZDMuZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGQ7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm9uKCdkcmFnJywgbWFrZURyYWdSb3coZ2QsIHRhYmxlQ29udHJvbFZpZXcsIC0xKSlcbiAgICAgICAgICAgIC5vbignZHJhZ2VuZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIC8vIGZpeG1lIGVtaXQgcGxvdGx5IG5vdGlmaWNhdGlvblxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBpbml0aWFsIHJlbmRlcmluZzogaGVhZGVyIGlzIHJlbmRlcmVkIGZpcnN0LCBhcyBpdCBtYXkgbWF5IGhhdmUgYXN5bmMgTGFUZVggKHNob3cgaGVhZGVyIGZpcnN0KVxuICAgIC8vIGJ1dCBibG9ja3MgYXJlIF9lbnRlcmVkXyB0aGUgd2F5IHRoZXkgYXJlIGR1ZSB0byBwYWludGVyJ3MgYWxnbyAoaGVhZGVyIG9uIHRvcClcbiAgICByZW5kZXJDb2x1bW5DZWxsVHJlZShnZCwgdGFibGVDb250cm9sVmlldywgaGVhZGVyQ29sdW1uQmxvY2ssIGNvbHVtbkJsb2NrKTtcbiAgICByZW5kZXJDb2x1bW5DZWxsVHJlZShnZCwgdGFibGVDb250cm9sVmlldywgY2VsbHNDb2x1bW5CbG9jaywgY29sdW1uQmxvY2spO1xuXG4gICAgdmFyIHNjcm9sbEFyZWFDbGlwID0gdGFibGVDb250cm9sVmlldy5zZWxlY3RBbGwoJy4nICsgYy5jbi5zY3JvbGxBcmVhQ2xpcClcbiAgICAgICAgLmRhdGEoZ3VwLnJlcGVhdCwgZ3VwLmtleUZ1bik7XG5cbiAgICBzY3JvbGxBcmVhQ2xpcC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2NsaXBQYXRoJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5zY3JvbGxBcmVhQ2xpcCwgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2lkJywgZnVuY3Rpb24oZCkge3JldHVybiBzY3JvbGxBcmVhQm90dG9tQ2xpcEtleShnZCwgZCk7fSk7XG5cbiAgICB2YXIgc2Nyb2xsQXJlYUNsaXBSZWN0ID0gc2Nyb2xsQXJlYUNsaXAuc2VsZWN0QWxsKCcuJyArIGMuY24uc2Nyb2xsQXJlYUNsaXBSZWN0KVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIHNjcm9sbEFyZWFDbGlwUmVjdC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNjcm9sbEFyZWFDbGlwUmVjdCwgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ3gnLCAtYy5vdmVyZHJhZylcbiAgICAgICAgLmF0dHIoJ3knLCAtYy51cGxpZnQpXG4gICAgICAgIC5hdHRyKCdmaWxsJywgJ25vbmUnKTtcblxuICAgIHNjcm9sbEFyZWFDbGlwUmVjdFxuICAgICAgICAuYXR0cignd2lkdGgnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQud2lkdGggKyAyICogYy5vdmVyZHJhZzt9KVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgZnVuY3Rpb24oZCkge3JldHVybiBkLmhlaWdodCArIGMudXBsaWZ0O30pO1xuXG4gICAgdmFyIGNvbHVtbkJvdW5kYXJ5ID0geUNvbHVtbi5zZWxlY3RBbGwoJy4nICsgYy5jbi5jb2x1bW5Cb3VuZGFyeSlcbiAgICAgICAgLmRhdGEoZ3VwLnJlcGVhdCwgZ3VwLmtleUZ1bik7XG5cbiAgICBjb2x1bW5Cb3VuZGFyeS5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmNvbHVtbkJvdW5kYXJ5LCB0cnVlKTtcblxuICAgIHZhciBjb2x1bW5Cb3VuZGFyeUNsaXBwYXRoID0geUNvbHVtbi5zZWxlY3RBbGwoJy4nICsgYy5jbi5jb2x1bW5Cb3VuZGFyeUNsaXBwYXRoKVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIC8vIFNWRyBzcGVjIGRvZXNuJ3QgbWFuZGF0ZSB3cmFwcGluZyBpbnRvIGEgPGRlZnM+IGFuZCBkb2Vzbid0IHNlZW0gdG8gY2F1c2UgYSBzcGVlZCBkaWZmZXJlbmNlXG4gICAgY29sdW1uQm91bmRhcnlDbGlwcGF0aC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2NsaXBQYXRoJylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5jb2x1bW5Cb3VuZGFyeUNsaXBwYXRoLCB0cnVlKTtcblxuICAgIGNvbHVtbkJvdW5kYXJ5Q2xpcHBhdGhcbiAgICAgICAgLmF0dHIoJ2lkJywgZnVuY3Rpb24oZCkge3JldHVybiBjb2x1bW5Cb3VuZGFyeUNsaXBLZXkoZ2QsIGQpO30pO1xuXG4gICAgdmFyIGNvbHVtbkJvdW5kYXJ5UmVjdCA9IGNvbHVtbkJvdW5kYXJ5Q2xpcHBhdGguc2VsZWN0QWxsKCcuJyArIGMuY24uY29sdW1uQm91bmRhcnlSZWN0KVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIGNvbHVtbkJvdW5kYXJ5UmVjdC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmNvbHVtbkJvdW5kYXJ5UmVjdCwgdHJ1ZSlcbiAgICAgICAgLmF0dHIoJ2ZpbGwnLCAnbm9uZScpO1xuXG4gICAgY29sdW1uQm91bmRhcnlSZWN0XG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQuY29sdW1uV2lkdGggKyAyICogcm91bmRIYWxmV2lkdGgoZCk7IH0pXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGQuY2FsY2RhdGEuaGVpZ2h0ICsgMiAqIHJvdW5kSGFsZldpZHRoKGQpICsgYy51cGxpZnQ7fSlcbiAgICAgICAgLmF0dHIoJ3gnLCBmdW5jdGlvbihkKSB7IHJldHVybiAtcm91bmRIYWxmV2lkdGgoZCk7IH0pXG4gICAgICAgIC5hdHRyKCd5JywgZnVuY3Rpb24oZCkgeyByZXR1cm4gLXJvdW5kSGFsZldpZHRoKGQpOyB9KTtcblxuICAgIHVwZGF0ZUJsb2NrWVBvc2l0aW9uKG51bGwsIGNlbGxzQ29sdW1uQmxvY2ssIHRhYmxlQ29udHJvbFZpZXcpO1xufTtcblxuZnVuY3Rpb24gcm91bmRIYWxmV2lkdGgoZCkge1xuICAgIHJldHVybiBNYXRoLmNlaWwoZC5jYWxjZGF0YS5tYXhMaW5lV2lkdGggLyAyKTtcbn1cblxuZnVuY3Rpb24gc2Nyb2xsQXJlYUJvdHRvbUNsaXBLZXkoZ2QsIGQpIHtcbiAgICByZXR1cm4gJ2NsaXAnICsgZ2QuX2Z1bGxMYXlvdXQuX3VpZCArICdfc2Nyb2xsQXJlYUJvdHRvbUNsaXBfJyArIGQua2V5O1xufVxuXG5mdW5jdGlvbiBjb2x1bW5Cb3VuZGFyeUNsaXBLZXkoZ2QsIGQpIHtcbiAgICByZXR1cm4gJ2NsaXAnICsgZ2QuX2Z1bGxMYXlvdXQuX3VpZCArICdfY29sdW1uQm91bmRhcnlDbGlwcGF0aF8nICsgZC5jYWxjZGF0YS5rZXkgKyAnXycgKyBkLnNwZWNJbmRleDtcbn1cblxuZnVuY3Rpb24gZmxhdERhdGEoc2VsZWN0aW9uKSB7XG4gICAgcmV0dXJuIFtdLmNvbmNhdC5hcHBseShbXSwgc2VsZWN0aW9uLm1hcChmdW5jdGlvbihnKSB7cmV0dXJuIGc7fSkpXG4gICAgICAgIC5tYXAoZnVuY3Rpb24oZykge3JldHVybiBnLl9fZGF0YV9fO30pO1xufVxuXG5mdW5jdGlvbiByZW5kZXJTY3JvbGxiYXJLaXQodGFibGVDb250cm9sVmlldywgZ2QsIGJ5cGFzc1Zpc2libGVCYXIpIHtcbiAgICBmdW5jdGlvbiBjYWxjVG90YWxIZWlnaHQoZCkge1xuICAgICAgICB2YXIgYmxvY2tzID0gZC5yb3dCbG9ja3M7XG4gICAgICAgIHJldHVybiBmaXJzdFJvd0FuY2hvcihibG9ja3MsIGJsb2Nrcy5sZW5ndGggLSAxKSArIChibG9ja3MubGVuZ3RoID8gcm93c0hlaWdodChibG9ja3NbYmxvY2tzLmxlbmd0aCAtIDFdLCBJbmZpbml0eSkgOiAxKTtcbiAgICB9XG5cbiAgICB2YXIgc2Nyb2xsYmFyS2l0ID0gdGFibGVDb250cm9sVmlldy5zZWxlY3RBbGwoJy4nICsgYy5jbi5zY3JvbGxiYXJLaXQpXG4gICAgICAgIC5kYXRhKGd1cC5yZXBlYXQsIGd1cC5rZXlGdW4pO1xuXG4gICAgc2Nyb2xsYmFyS2l0LmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Nyb2xsYmFyS2l0LCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ3NoYXBlLXJlbmRlcmluZycsICdnZW9tZXRyaWNQcmVjaXNpb24nKTtcblxuICAgIHNjcm9sbGJhcktpdFxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgcyA9IGQuc2Nyb2xsYmFyU3RhdGU7XG4gICAgICAgICAgICBzLnRvdGFsSGVpZ2h0ID0gY2FsY1RvdGFsSGVpZ2h0KGQpO1xuICAgICAgICAgICAgcy5zY3JvbGxhYmxlQXJlYUhlaWdodCA9IGQuZ3JvdXBIZWlnaHQgLSBoZWFkZXJIZWlnaHQoZCk7XG4gICAgICAgICAgICBzLmN1cnJlbnRseVZpc2libGVIZWlnaHQgPSBNYXRoLm1pbihzLnRvdGFsSGVpZ2h0LCBzLnNjcm9sbGFibGVBcmVhSGVpZ2h0KTtcbiAgICAgICAgICAgIHMucmF0aW8gPSBzLmN1cnJlbnRseVZpc2libGVIZWlnaHQgLyBzLnRvdGFsSGVpZ2h0O1xuICAgICAgICAgICAgcy5iYXJMZW5ndGggPSBNYXRoLm1heChzLnJhdGlvICogcy5jdXJyZW50bHlWaXNpYmxlSGVpZ2h0LCBjLmdvbGRlblJhdGlvICogYy5zY3JvbGxiYXJXaWR0aCk7XG4gICAgICAgICAgICBzLmJhcldpZ2dsZVJvb20gPSBzLmN1cnJlbnRseVZpc2libGVIZWlnaHQgLSBzLmJhckxlbmd0aDtcbiAgICAgICAgICAgIHMud2lnZ2xlUm9vbSA9IE1hdGgubWF4KDAsIHMudG90YWxIZWlnaHQgLSBzLnNjcm9sbGFibGVBcmVhSGVpZ2h0KTtcbiAgICAgICAgICAgIHMudG9wWSA9IHMuYmFyV2lnZ2xlUm9vbSA9PT0gMCA/IDAgOiAoZC5zY3JvbGxZIC8gcy53aWdnbGVSb29tKSAqIHMuYmFyV2lnZ2xlUm9vbTtcbiAgICAgICAgICAgIHMuYm90dG9tWSA9IHMudG9wWSArIHMuYmFyTGVuZ3RoO1xuICAgICAgICAgICAgcy5kcmFnTXVsdGlwbGllciA9IHMud2lnZ2xlUm9vbSAvIHMuYmFyV2lnZ2xlUm9vbTtcbiAgICAgICAgfSlcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB4UG9zaXRpb24gPSBkLndpZHRoICsgYy5zY3JvbGxiYXJXaWR0aCAvIDIgKyBjLnNjcm9sbGJhck9mZnNldDtcbiAgICAgICAgICAgIHJldHVybiAndHJhbnNsYXRlKCcgKyB4UG9zaXRpb24gKyAnICcgKyBoZWFkZXJIZWlnaHQoZCkgKyAnKSc7XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIHNjcm9sbGJhciA9IHNjcm9sbGJhcktpdC5zZWxlY3RBbGwoJy4nICsgYy5jbi5zY3JvbGxiYXIpXG4gICAgICAgIC5kYXRhKGd1cC5yZXBlYXQsIGd1cC5rZXlGdW4pO1xuXG4gICAgc2Nyb2xsYmFyLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Nyb2xsYmFyLCB0cnVlKTtcblxuICAgIHZhciBzY3JvbGxiYXJTbGlkZXIgPSBzY3JvbGxiYXIuc2VsZWN0QWxsKCcuJyArIGMuY24uc2Nyb2xsYmFyU2xpZGVyKVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIHNjcm9sbGJhclNsaWRlci5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLnNjcm9sbGJhclNsaWRlciwgdHJ1ZSk7XG5cbiAgICBzY3JvbGxiYXJTbGlkZXJcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiAndHJhbnNsYXRlKDAgJyArIChkLnNjcm9sbGJhclN0YXRlLnRvcFkgfHwgMCkgKyAnKSc7XG4gICAgICAgIH0pO1xuXG4gICAgdmFyIHNjcm9sbGJhckdseXBoID0gc2Nyb2xsYmFyU2xpZGVyLnNlbGVjdEFsbCgnLicgKyBjLmNuLnNjcm9sbGJhckdseXBoKVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIHNjcm9sbGJhckdseXBoLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnbGluZScpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Nyb2xsYmFyR2x5cGgsIHRydWUpXG4gICAgICAgIC5hdHRyKCdzdHJva2UnLCAnYmxhY2snKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgYy5zY3JvbGxiYXJXaWR0aClcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS1saW5lY2FwJywgJ3JvdW5kJylcbiAgICAgICAgLmF0dHIoJ3kxJywgYy5zY3JvbGxiYXJXaWR0aCAvIDIpO1xuXG4gICAgc2Nyb2xsYmFyR2x5cGhcbiAgICAgICAgLmF0dHIoJ3kyJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuc2Nyb2xsYmFyU3RhdGUuYmFyTGVuZ3RoIC0gYy5zY3JvbGxiYXJXaWR0aCAvIDI7XG4gICAgICAgIH0pXG4gICAgICAgIC5hdHRyKCdzdHJva2Utb3BhY2l0eScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHJldHVybiBkLmNvbHVtbkRyYWdJblByb2dyZXNzIHx8ICFkLnNjcm9sbGJhclN0YXRlLmJhcldpZ2dsZVJvb20gfHwgYnlwYXNzVmlzaWJsZUJhciA/IDAgOiAwLjQ7XG4gICAgICAgIH0pO1xuXG4gICAgLy8gY2FuY2VsIHRyYW5zaXRpb246IHBvc3NpYmxlIHBlbmRpbmcgKGFsc28sIGRlbGF5ZWQpIHRyYW5zaXRpb25cbiAgICBzY3JvbGxiYXJHbHlwaFxuICAgICAgICAudHJhbnNpdGlvbigpLmRlbGF5KDApLmR1cmF0aW9uKDApO1xuXG4gICAgc2Nyb2xsYmFyR2x5cGhcbiAgICAgICAgLnRyYW5zaXRpb24oKS5kZWxheShjLnNjcm9sbGJhckhpZGVEZWxheSkuZHVyYXRpb24oYy5zY3JvbGxiYXJIaWRlRHVyYXRpb24pXG4gICAgICAgIC5hdHRyKCdzdHJva2Utb3BhY2l0eScsIDApO1xuXG4gICAgdmFyIHNjcm9sbGJhckNhcHR1cmVab25lID0gc2Nyb2xsYmFyLnNlbGVjdEFsbCgnLicgKyBjLmNuLnNjcm9sbGJhckNhcHR1cmVab25lKVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIHNjcm9sbGJhckNhcHR1cmVab25lLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnbGluZScpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uc2Nyb2xsYmFyQ2FwdHVyZVpvbmUsIHRydWUpXG4gICAgICAgIC5hdHRyKCdzdHJva2UnLCAnd2hpdGUnKVxuICAgICAgICAuYXR0cignc3Ryb2tlLW9wYWNpdHknLCAwLjAxKSAvLyBzb21lIGJyb3dzZXIgbWlnaHQgZ2V0IHJpZCBvZiBhIDAgb3BhY2l0eSBlbGVtZW50XG4gICAgICAgIC5hdHRyKCdzdHJva2Utd2lkdGgnLCBjLnNjcm9sbGJhckNhcHR1cmVXaWR0aClcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS1saW5lY2FwJywgJ2J1dHQnKVxuICAgICAgICAuYXR0cigneTEnLCAwKVxuICAgICAgICAub24oJ21vdXNlZG93bicsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB5ID0gZDMuZXZlbnQueTtcbiAgICAgICAgICAgIHZhciBiYm94ID0gdGhpcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgIHZhciBzID0gZC5zY3JvbGxiYXJTdGF0ZTtcbiAgICAgICAgICAgIHZhciBwaXhlbFZhbCA9IHkgLSBiYm94LnRvcDtcbiAgICAgICAgICAgIHZhciBpbnZlcnNlU2NhbGUgPSBkMy5zY2FsZS5saW5lYXIoKS5kb21haW4oWzAsIHMuc2Nyb2xsYWJsZUFyZWFIZWlnaHRdKS5yYW5nZShbMCwgcy50b3RhbEhlaWdodF0pLmNsYW1wKHRydWUpO1xuICAgICAgICAgICAgaWYoIShzLnRvcFkgPD0gcGl4ZWxWYWwgJiYgcGl4ZWxWYWwgPD0gcy5ib3R0b21ZKSkge1xuICAgICAgICAgICAgICAgIG1ha2VEcmFnUm93KGdkLCB0YWJsZUNvbnRyb2xWaWV3LCBudWxsLCBpbnZlcnNlU2NhbGUocGl4ZWxWYWwgLSBzLmJhckxlbmd0aCAvIDIpKShkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhbGwoZDMuYmVoYXZpb3IuZHJhZygpXG4gICAgICAgICAgICAub3JpZ2luKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICBkMy5ldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBkLnNjcm9sbGJhclN0YXRlLnNjcm9sbGJhclNjcm9sbEluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiBkO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5vbignZHJhZycsIG1ha2VEcmFnUm93KGdkLCB0YWJsZUNvbnRyb2xWaWV3KSlcbiAgICAgICAgICAgIC5vbignZHJhZ2VuZCcsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIC8vIGZpeG1lIGVtaXQgUGxvdGx5IGV2ZW50XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgc2Nyb2xsYmFyQ2FwdHVyZVpvbmVcbiAgICAgICAgLmF0dHIoJ3kyJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgcmV0dXJuIGQuc2Nyb2xsYmFyU3RhdGUuc2Nyb2xsYWJsZUFyZWFIZWlnaHQ7XG4gICAgICAgIH0pO1xuXG4gICAgLy8gUmVtb3ZlIHNjcm9sbCBnbHlwaCBhbmQgY2FwdHVyZSB6b25lIG9uIHN0YXRpYyBwbG90c1xuICAgIC8vIGFzIHRoZXkgZG9uJ3QgcmVuZGVyIHByb3Blcmx5IHdoZW4gY29udmVydGVkIHRvIFBERlxuICAgIC8vIGluIHRoZSBDaHJvbWUgUERGIHZpZXdlclxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9wbG90bHkvc3RyZWFtYmVkL2lzc3Vlcy8xMTYxOFxuICAgIGlmKGdkLl9jb250ZXh0LnN0YXRpY1Bsb3QpIHtcbiAgICAgICAgc2Nyb2xsYmFyR2x5cGgucmVtb3ZlKCk7XG4gICAgICAgIHNjcm9sbGJhckNhcHR1cmVab25lLnJlbW92ZSgpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyQ29sdW1uQ2VsbFRyZWUoZ2QsIHRhYmxlQ29udHJvbFZpZXcsIGNvbHVtbkJsb2NrLCBhbGxDb2x1bW5CbG9jaykge1xuICAgIC8vIGZpeG1lIHRoaXMgcGVyZiBob3RzcG90XG4gICAgLy8gdGhpcyBpcyBwZXJmb3JtYW5jZSBjcml0aWNhbCBjb2RlIGFzIHNjcm9sbGluZyBjYWxscyBpdCBvbiBldmVyeSByZXZvbHZlciBzd2l0Y2hcbiAgICAvLyBpdCBhcHBlYXJzIHN1ZmZpY2llbnRseSBmYXN0IGJ1dCB0aGVyZSBhcmUgcGxlbnR5IG9mIGxvdy1oYW5naW5nIGZydWl0cyBmb3IgcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uXG5cbiAgICB2YXIgY29sdW1uQ2VsbHMgPSByZW5kZXJDb2x1bW5DZWxscyhjb2x1bW5CbG9jayk7XG5cbiAgICB2YXIgY29sdW1uQ2VsbCA9IHJlbmRlckNvbHVtbkNlbGwoY29sdW1uQ2VsbHMpO1xuXG4gICAgc3VwcGx5U3R5bGluZ1ZhbHVlcyhjb2x1bW5DZWxsKTtcblxuICAgIHZhciBjZWxsUmVjdCA9IHJlbmRlckNlbGxSZWN0KGNvbHVtbkNlbGwpO1xuXG4gICAgc2l6ZUFuZFN0eWxlUmVjdChjZWxsUmVjdCk7XG5cbiAgICB2YXIgY2VsbFRleHRIb2xkZXIgPSByZW5kZXJDZWxsVGV4dEhvbGRlcihjb2x1bW5DZWxsKTtcblxuICAgIHZhciBjZWxsVGV4dCA9IHJlbmRlckNlbGxUZXh0KGNlbGxUZXh0SG9sZGVyKTtcblxuICAgIHNldEZvbnQoY2VsbFRleHQpO1xuICAgIHBvcHVsYXRlQ2VsbFRleHQoY2VsbFRleHQsIHRhYmxlQ29udHJvbFZpZXcsIGFsbENvbHVtbkJsb2NrLCBnZCk7XG5cbiAgICAvLyBkb2luZyB0aGlzIGF0IHRoZSBlbmQgd2hlbiB0ZXh0LCBhbmQgdGV4dCBzdGx5aW5nIGFyZSBzZXRcbiAgICBzZXRDZWxsSGVpZ2h0QW5kUG9zaXRpb25ZKGNvbHVtbkNlbGwpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJDb2x1bW5DZWxscyhjb2x1bW5CbG9jaykge1xuICAgIHZhciBjb2x1bW5DZWxscyA9IGNvbHVtbkJsb2NrLnNlbGVjdEFsbCgnLicgKyBjLmNuLmNvbHVtbkNlbGxzKVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBndXAua2V5RnVuKTtcblxuICAgIGNvbHVtbkNlbGxzLmVudGVyKClcbiAgICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAgIC5jbGFzc2VkKGMuY24uY29sdW1uQ2VsbHMsIHRydWUpO1xuXG4gICAgY29sdW1uQ2VsbHMuZXhpdCgpXG4gICAgICAgIC5yZW1vdmUoKTtcblxuICAgIHJldHVybiBjb2x1bW5DZWxscztcbn1cblxuZnVuY3Rpb24gcmVuZGVyQ29sdW1uQ2VsbChjb2x1bW5DZWxscykge1xuICAgIHZhciBjb2x1bW5DZWxsID0gY29sdW1uQ2VsbHMuc2VsZWN0QWxsKCcuJyArIGMuY24uY29sdW1uQ2VsbClcbiAgICAgICAgLmRhdGEoc3BsaXREYXRhLnNwbGl0VG9DZWxscywgZnVuY3Rpb24oZCkge3JldHVybiBkLmtleVdpdGhpbkJsb2NrO30pO1xuXG4gICAgY29sdW1uQ2VsbC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmNvbHVtbkNlbGwsIHRydWUpO1xuXG4gICAgY29sdW1uQ2VsbC5leGl0KClcbiAgICAgICAgLnJlbW92ZSgpO1xuXG4gICAgcmV0dXJuIGNvbHVtbkNlbGw7XG59XG5cbmZ1bmN0aW9uIHJlbmRlckNlbGxSZWN0KGNvbHVtbkNlbGwpIHtcbiAgICB2YXIgY2VsbFJlY3QgPSBjb2x1bW5DZWxsLnNlbGVjdEFsbCgnLicgKyBjLmNuLmNlbGxSZWN0KVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBmdW5jdGlvbihkKSB7cmV0dXJuIGQua2V5V2l0aGluQmxvY2s7fSk7XG5cbiAgICBjZWxsUmVjdC5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmNlbGxSZWN0LCB0cnVlKTtcblxuICAgIHJldHVybiBjZWxsUmVjdDtcbn1cblxuZnVuY3Rpb24gcmVuZGVyQ2VsbFRleHQoY2VsbFRleHRIb2xkZXIpIHtcbiAgICB2YXIgY2VsbFRleHQgPSBjZWxsVGV4dEhvbGRlci5zZWxlY3RBbGwoJy4nICsgYy5jbi5jZWxsVGV4dClcbiAgICAgICAgLmRhdGEoZ3VwLnJlcGVhdCwgZnVuY3Rpb24oZCkge3JldHVybiBkLmtleVdpdGhpbkJsb2NrO30pO1xuXG4gICAgY2VsbFRleHQuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCd0ZXh0JylcbiAgICAgICAgLmNsYXNzZWQoYy5jbi5jZWxsVGV4dCwgdHJ1ZSlcbiAgICAgICAgLnN0eWxlKCdjdXJzb3InLCBmdW5jdGlvbigpIHtyZXR1cm4gJ2F1dG8nO30pXG4gICAgICAgIC5vbignbW91c2Vkb3duJywgZnVuY3Rpb24oKSB7ZDMuZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7fSk7XG5cbiAgICByZXR1cm4gY2VsbFRleHQ7XG59XG5cbmZ1bmN0aW9uIHJlbmRlckNlbGxUZXh0SG9sZGVyKGNvbHVtbkNlbGwpIHtcbiAgICB2YXIgY2VsbFRleHRIb2xkZXIgPSBjb2x1bW5DZWxsLnNlbGVjdEFsbCgnLicgKyBjLmNuLmNlbGxUZXh0SG9sZGVyKVxuICAgICAgICAuZGF0YShndXAucmVwZWF0LCBmdW5jdGlvbihkKSB7cmV0dXJuIGQua2V5V2l0aGluQmxvY2s7fSk7XG5cbiAgICBjZWxsVGV4dEhvbGRlci5lbnRlcigpXG4gICAgICAgIC5hcHBlbmQoJ2cnKVxuICAgICAgICAuY2xhc3NlZChjLmNuLmNlbGxUZXh0SG9sZGVyLCB0cnVlKVxuICAgICAgICAuc3R5bGUoJ3NoYXBlLXJlbmRlcmluZycsICdnZW9tZXRyaWNQcmVjaXNpb24nKTtcblxuICAgIHJldHVybiBjZWxsVGV4dEhvbGRlcjtcbn1cblxuZnVuY3Rpb24gc3VwcGx5U3R5bGluZ1ZhbHVlcyhjb2x1bW5DZWxsKSB7XG4gICAgY29sdW1uQ2VsbFxuICAgICAgICAuZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICB2YXIgc3BlYyA9IGQuY2FsY2RhdGEuY2VsbHMuZm9udDtcbiAgICAgICAgICAgIHZhciBjb2wgPSBkLmNvbHVtbi5zcGVjSW5kZXg7XG4gICAgICAgICAgICB2YXIgZm9udCA9IHtcbiAgICAgICAgICAgICAgICBzaXplOiBncmlkUGljayhzcGVjLnNpemUsIGNvbCwgaSksXG4gICAgICAgICAgICAgICAgY29sb3I6IGdyaWRQaWNrKHNwZWMuY29sb3IsIGNvbCwgaSksXG4gICAgICAgICAgICAgICAgZmFtaWx5OiBncmlkUGljayhzcGVjLmZhbWlseSwgY29sLCBpKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGQucm93TnVtYmVyID0gZC5rZXk7XG4gICAgICAgICAgICBkLmFsaWduID0gZ3JpZFBpY2soZC5jYWxjZGF0YS5jZWxscy5hbGlnbiwgY29sLCBpKTtcbiAgICAgICAgICAgIGQuY2VsbEJvcmRlcldpZHRoID0gZ3JpZFBpY2soZC5jYWxjZGF0YS5jZWxscy5saW5lLndpZHRoLCBjb2wsIGkpO1xuICAgICAgICAgICAgZC5mb250ID0gZm9udDtcbiAgICAgICAgfSk7XG59XG5cbmZ1bmN0aW9uIHNldEZvbnQoY2VsbFRleHQpIHtcbiAgICBjZWxsVGV4dFxuICAgICAgICAuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICBEcmF3aW5nLmZvbnQoZDMuc2VsZWN0KHRoaXMpLCBkLmZvbnQpO1xuICAgICAgICB9KTtcbn1cblxuZnVuY3Rpb24gc2l6ZUFuZFN0eWxlUmVjdChjZWxsUmVjdCkge1xuICAgIGNlbGxSZWN0XG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5jb2x1bW4uY29sdW1uV2lkdGg7fSlcbiAgICAgICAgLmF0dHIoJ3N0cm9rZS13aWR0aCcsIGZ1bmN0aW9uKGQpIHtyZXR1cm4gZC5jZWxsQm9yZGVyV2lkdGg7fSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGF0b21pY1NlbGVjdGlvbiA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgICAgIENvbG9yLnN0cm9rZShhdG9taWNTZWxlY3Rpb24sIGdyaWRQaWNrKGQuY2FsY2RhdGEuY2VsbHMubGluZS5jb2xvciwgZC5jb2x1bW4uc3BlY0luZGV4LCBkLnJvd051bWJlcikpO1xuICAgICAgICAgICAgQ29sb3IuZmlsbChhdG9taWNTZWxlY3Rpb24sIGdyaWRQaWNrKGQuY2FsY2RhdGEuY2VsbHMuZmlsbC5jb2xvciwgZC5jb2x1bW4uc3BlY0luZGV4LCBkLnJvd051bWJlcikpO1xuICAgICAgICB9KTtcbn1cblxuZnVuY3Rpb24gcG9wdWxhdGVDZWxsVGV4dChjZWxsVGV4dCwgdGFibGVDb250cm9sVmlldywgYWxsQ29sdW1uQmxvY2ssIGdkKSB7XG4gICAgY2VsbFRleHRcbiAgICAgICAgLnRleHQoZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGNvbCA9IGQuY29sdW1uLnNwZWNJbmRleDtcbiAgICAgICAgICAgIHZhciByb3cgPSBkLnJvd051bWJlcjtcblxuICAgICAgICAgICAgdmFyIHVzZXJTdXBwbGllZENvbnRlbnQgPSBkLnZhbHVlO1xuICAgICAgICAgICAgdmFyIHN0cmluZ1N1cHBsaWVkID0gKHR5cGVvZiB1c2VyU3VwcGxpZWRDb250ZW50ID09PSAnc3RyaW5nJyk7XG4gICAgICAgICAgICB2YXIgaGFzQnJlYWtzID0gc3RyaW5nU3VwcGxpZWQgJiYgdXNlclN1cHBsaWVkQ29udGVudC5tYXRjaCgvPGJyPi9pKTtcbiAgICAgICAgICAgIHZhciB1c2VyQnJva2VuVGV4dCA9ICFzdHJpbmdTdXBwbGllZCB8fCBoYXNCcmVha3M7XG4gICAgICAgICAgICBkLm1heUhhdmVNYXJrdXAgPSBzdHJpbmdTdXBwbGllZCAmJiB1c2VyU3VwcGxpZWRDb250ZW50Lm1hdGNoKC9bPCY+XS8pO1xuXG4gICAgICAgICAgICB2YXIgbGF0ZXggPSBpc0xhdGV4KHVzZXJTdXBwbGllZENvbnRlbnQpO1xuICAgICAgICAgICAgZC5sYXRleCA9IGxhdGV4O1xuXG4gICAgICAgICAgICB2YXIgcHJlZml4ID0gbGF0ZXggPyAnJyA6IGdyaWRQaWNrKGQuY2FsY2RhdGEuY2VsbHMucHJlZml4LCBjb2wsIHJvdykgfHwgJyc7XG4gICAgICAgICAgICB2YXIgc3VmZml4ID0gbGF0ZXggPyAnJyA6IGdyaWRQaWNrKGQuY2FsY2RhdGEuY2VsbHMuc3VmZml4LCBjb2wsIHJvdykgfHwgJyc7XG4gICAgICAgICAgICB2YXIgZm9ybWF0ID0gbGF0ZXggPyBudWxsIDogZ3JpZFBpY2soZC5jYWxjZGF0YS5jZWxscy5mb3JtYXQsIGNvbCwgcm93KSB8fCBudWxsO1xuXG4gICAgICAgICAgICB2YXIgcHJlZml4U3VmZml4ZWRUZXh0ID0gcHJlZml4ICsgKGZvcm1hdCA/IGQzLmZvcm1hdChmb3JtYXQpKGQudmFsdWUpIDogZC52YWx1ZSkgKyBzdWZmaXg7XG5cbiAgICAgICAgICAgIHZhciBoYXNXcmFwU3BsaXRDaGFyYWN0ZXI7XG4gICAgICAgICAgICBkLndyYXBwaW5nTmVlZGVkID0gIWQud3JhcHBlZCAmJiAhdXNlckJyb2tlblRleHQgJiYgIWxhdGV4ICYmIChoYXNXcmFwU3BsaXRDaGFyYWN0ZXIgPSBoYXNXcmFwQ2hhcmFjdGVyKHByZWZpeFN1ZmZpeGVkVGV4dCkpO1xuICAgICAgICAgICAgZC5jZWxsSGVpZ2h0TWF5SW5jcmVhc2UgPSBoYXNCcmVha3MgfHwgbGF0ZXggfHwgZC5tYXlIYXZlTWFya3VwIHx8IChoYXNXcmFwU3BsaXRDaGFyYWN0ZXIgPT09IHZvaWQoMCkgPyBoYXNXcmFwQ2hhcmFjdGVyKHByZWZpeFN1ZmZpeGVkVGV4dCkgOiBoYXNXcmFwU3BsaXRDaGFyYWN0ZXIpO1xuICAgICAgICAgICAgZC5uZWVkc0NvbnZlcnRUb1RzcGFucyA9IGQubWF5SGF2ZU1hcmt1cCB8fCBkLndyYXBwaW5nTmVlZGVkIHx8IGQubGF0ZXg7XG5cbiAgICAgICAgICAgIHZhciB0ZXh0VG9SZW5kZXI7XG4gICAgICAgICAgICBpZihkLndyYXBwaW5nTmVlZGVkKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhyZWZQcmVzZXJ2ZWRUZXh0ID0gYy53cmFwU3BsaXRDaGFyYWN0ZXIgPT09ICcgJyA/IHByZWZpeFN1ZmZpeGVkVGV4dC5yZXBsYWNlKC88YSBocmVmPS9pZywgJzxhX2hyZWY9JykgOiBwcmVmaXhTdWZmaXhlZFRleHQ7XG4gICAgICAgICAgICAgICAgdmFyIGZyYWdtZW50cyA9IGhyZWZQcmVzZXJ2ZWRUZXh0LnNwbGl0KGMud3JhcFNwbGl0Q2hhcmFjdGVyKTtcbiAgICAgICAgICAgICAgICB2YXIgaHJlZlJlc3RvcmVkRnJhZ21lbnRzID0gYy53cmFwU3BsaXRDaGFyYWN0ZXIgPT09ICcgJyA/IGZyYWdtZW50cy5tYXAoZnVuY3Rpb24oZnJhZykge3JldHVybiBmcmFnLnJlcGxhY2UoLzxhX2hyZWY9L2lnLCAnPGEgaHJlZj0nKTt9KSA6IGZyYWdtZW50cztcbiAgICAgICAgICAgICAgICBkLmZyYWdtZW50cyA9IGhyZWZSZXN0b3JlZEZyYWdtZW50cy5tYXAoZnVuY3Rpb24oZikge3JldHVybiB7dGV4dDogZiwgd2lkdGg6IG51bGx9O30pO1xuICAgICAgICAgICAgICAgIGQuZnJhZ21lbnRzLnB1c2goe2ZyYWdtZW50OiBjLndyYXBTcGFjZXIsIHdpZHRoOiBudWxsfSk7XG4gICAgICAgICAgICAgICAgdGV4dFRvUmVuZGVyID0gaHJlZlJlc3RvcmVkRnJhZ21lbnRzLmpvaW4oYy5saW5lQnJlYWtlcikgKyBjLmxpbmVCcmVha2VyICsgYy53cmFwU3BhY2VyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgZC5mcmFnbWVudHM7XG4gICAgICAgICAgICAgICAgdGV4dFRvUmVuZGVyID0gcHJlZml4U3VmZml4ZWRUZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGV4dFRvUmVuZGVyO1xuICAgICAgICB9KVxuICAgICAgICAuYXR0cignZHknLCBmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICByZXR1cm4gZC5uZWVkc0NvbnZlcnRUb1RzcGFucyA/IDAgOiAnMC43NWVtJztcbiAgICAgICAgfSlcbiAgICAgICAgLmVhY2goZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIHNlbGVjdGlvbiA9IGQzLnNlbGVjdChlbGVtZW50KTtcblxuICAgICAgICAgICAgLy8gZmluYWxpemUgd2hhdCdzIGluIHRoZSBET01cblxuICAgICAgICAgICAgdmFyIHJlbmRlckNhbGxiYWNrID0gZC53cmFwcGluZ05lZWRlZCA/IHdyYXBUZXh0TWFrZXIgOiB1cGRhdGVZUG9zaXRpb25NYWtlcjtcbiAgICAgICAgICAgIGlmKGQubmVlZHNDb252ZXJ0VG9Uc3BhbnMpIHtcbiAgICAgICAgICAgICAgICBzdmdVdGlsLmNvbnZlcnRUb1RzcGFucyhzZWxlY3Rpb24sIGdkLCByZW5kZXJDYWxsYmFjayhhbGxDb2x1bW5CbG9jaywgZWxlbWVudCwgdGFibGVDb250cm9sVmlldywgZ2QsIGQpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZDMuc2VsZWN0KGVsZW1lbnQucGFyZW50Tm9kZSlcbiAgICAgICAgICAgICAgICAgICAgLy8gYmFzaWMgY2VsbCBhZGp1c3RtZW50IC0gY29tcGxpYW5jZSB3aXRoIGBjZWxsUGFkYFxuICAgICAgICAgICAgICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge3JldHVybiAndHJhbnNsYXRlKCcgKyB4UG9zaXRpb24oZCkgKyAnICcgKyBjLmNlbGxQYWQgKyAnKSc7fSlcbiAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ3RleHQtYW5jaG9yJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVmdDogJ3N0YXJ0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZW50ZXI6ICdtaWRkbGUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0OiAnZW5kJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlbZC5hbGlnbl07XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbn1cblxuZnVuY3Rpb24gaXNMYXRleChjb250ZW50KSB7XG4gICAgcmV0dXJuIHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJyAmJiBjb250ZW50Lm1hdGNoKGMubGF0ZXhDaGVjayk7XG59XG5cbmZ1bmN0aW9uIGhhc1dyYXBDaGFyYWN0ZXIodGV4dCkge3JldHVybiB0ZXh0LmluZGV4T2YoYy53cmFwU3BsaXRDaGFyYWN0ZXIpICE9PSAtMTt9XG5cbmZ1bmN0aW9uIGNvbHVtbk1vdmVkKGdkLCBjYWxjZGF0YSwgaW5kaWNlcykge1xuICAgIHZhciBvID0gY2FsY2RhdGEuZ2RDb2x1bW5zT3JpZ2luYWxPcmRlcjtcbiAgICBjYWxjZGF0YS5nZENvbHVtbnMuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgIHJldHVybiBpbmRpY2VzW28uaW5kZXhPZihhKV0gLSBpbmRpY2VzW28uaW5kZXhPZihiKV07XG4gICAgfSk7XG5cbiAgICBjYWxjZGF0YS5jb2x1bW5vcmRlciA9IGluZGljZXM7XG5cbiAgICAvLyBUT0RPOiB0aGVyZSdzIG5vIGRhdGEgaGVyZSwgYnV0IGFsc28gdGhpcyByZW9yZGVyaW5nIGlzIG5vdCByZWZsZWN0ZWRcbiAgICAvLyBpbiBnZC5kYXRhIG9yIGV2ZW4gZ2QuX2Z1bGxEYXRhLlxuICAgIC8vIEZvciBub3cgSSB3aWxsIG5vdCBhdHRlbXB0IHRvIHBlcnNpc3QgdGhpcyBpbiBfcHJlR1VJXG4gICAgZ2QuZW1pdCgncGxvdGx5X3Jlc3R5bGUnKTtcbn1cblxuZnVuY3Rpb24gZ3JpZFBpY2soc3BlYywgY29sLCByb3cpIHtcbiAgICBpZihBcnJheS5pc0FycmF5KHNwZWMpKSB7XG4gICAgICAgIHZhciBjb2x1bW4gPSBzcGVjW01hdGgubWluKGNvbCwgc3BlYy5sZW5ndGggLSAxKV07XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkoY29sdW1uKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbHVtbltNYXRoLm1pbihyb3csIGNvbHVtbi5sZW5ndGggLSAxKV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gY29sdW1uO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHNwZWM7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBlYXNlQ29sdW1uKHNlbGVjdGlvbiwgZCwgeSkge1xuICAgIHNlbGVjdGlvblxuICAgICAgICAudHJhbnNpdGlvbigpXG4gICAgICAgIC5lYXNlKGMucmVsZWFzZVRyYW5zaXRpb25FYXNlKVxuICAgICAgICAuZHVyYXRpb24oYy5yZWxlYXNlVHJhbnNpdGlvbkR1cmF0aW9uKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgZC54ICsgJyAnICsgeSArICcpJyk7XG59XG5cbmZ1bmN0aW9uIGNlbGxzQmxvY2soZCkge3JldHVybiBkLnR5cGUgPT09ICdjZWxscyc7fVxuZnVuY3Rpb24gaGVhZGVyQmxvY2soZCkge3JldHVybiBkLnR5cGUgPT09ICdoZWFkZXInO31cblxuLyoqXG4gKiBSZXZvbHZlciBwYW5lbCBhbmQgY2VsbCBjb250ZW50cyBsYXlvdXRpbmdcbiAqL1xuXG5mdW5jdGlvbiBoZWFkZXJIZWlnaHQoZCkge1xuICAgIHZhciBoZWFkZXJCbG9ja3MgPSBkLnJvd0Jsb2Nrcy5sZW5ndGggPyBkLnJvd0Jsb2Nrc1swXS5hdXhpbGlhcnlCbG9ja3MgOiBbXTtcbiAgICByZXR1cm4gaGVhZGVyQmxvY2tzLnJlZHVjZShmdW5jdGlvbihwLCBuKSB7cmV0dXJuIHAgKyByb3dzSGVpZ2h0KG4sIEluZmluaXR5KTt9LCAwKTtcbn1cblxuZnVuY3Rpb24gZmluZFBhZ2VzQW5kQ2FjaGVIZWlnaHRzKGJsb2Nrcywgc2Nyb2xsWSwgc2Nyb2xsSGVpZ2h0KSB7XG4gICAgdmFyIHBhZ2VzID0gW107XG4gICAgdmFyIHBUb3AgPSAwO1xuXG4gICAgZm9yKHZhciBibG9ja0luZGV4ID0gMDsgYmxvY2tJbmRleCA8IGJsb2Nrcy5sZW5ndGg7IGJsb2NrSW5kZXgrKykge1xuICAgICAgICB2YXIgYmxvY2sgPSBibG9ja3NbYmxvY2tJbmRleF07XG4gICAgICAgIHZhciBibG9ja1Jvd3MgPSBibG9jay5yb3dzO1xuICAgICAgICB2YXIgcm93c0hlaWdodCA9IDA7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBibG9ja1Jvd3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJvd3NIZWlnaHQgKz0gYmxvY2tSb3dzW2ldLnJvd0hlaWdodDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNhY2hpbmcgYWxsUm93c0hlaWdodCBvbiB0aGUgYmxvY2sgLSBpdCdzIHNhZmUgYXMgdGhpcyBmdW5jdGlvbiBpcyBhbHdheXMgY2FsbGVkIGZyb20gd2l0aGluIHRoZSBjb2RlIHBhcnRcbiAgICAgICAgLy8gdGhhdCBoYW5kbGVzIGluY3JlYXNlcyB0byByb3cgaGVpZ2h0c1xuICAgICAgICBibG9jay5hbGxSb3dzSGVpZ2h0ID0gcm93c0hlaWdodDtcblxuICAgICAgICB2YXIgcEJvdHRvbSA9IHBUb3AgKyByb3dzSGVpZ2h0O1xuICAgICAgICB2YXIgd2luZG93VG9wID0gc2Nyb2xsWTtcbiAgICAgICAgdmFyIHdpbmRvd0JvdHRvbSA9IHdpbmRvd1RvcCArIHNjcm9sbEhlaWdodDtcbiAgICAgICAgaWYod2luZG93VG9wIDwgcEJvdHRvbSAmJiB3aW5kb3dCb3R0b20gPiBwVG9wKSB7XG4gICAgICAgICAgICBwYWdlcy5wdXNoKGJsb2NrSW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIHBUb3AgKz0gcm93c0hlaWdodDtcblxuICAgICAgICAvLyBjb25zaWRlciB0aGlzIG5pY2UgZmluYWwgb3B0aW1pemF0aW9uOyBwdXQgaXQgaW4gYGZvcmAgY29uZGl0aW9uIC0gY2F2ZWF0LCBjdXJyZW50bHkgdGhlXG4gICAgICAgIC8vIGJsb2NrLmFsbFJvd3NIZWlnaHQgcmVsaWVzIG9uIGJlaW5nIGludmFsaWRhdGVkLCBzbyBlbmFibGluZyB0aGlzIG9wdCBtYXkgbm90IGJlIHNhZmVcbiAgICAgICAgLy8gaWYocGFnZXMubGVuZ3RoID4gMSkgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhZ2VzO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVCbG9ja1lQb3NpdGlvbihnZCwgY2VsbHNDb2x1bW5CbG9jaywgdGFibGVDb250cm9sVmlldykge1xuICAgIHZhciBkID0gZmxhdERhdGEoY2VsbHNDb2x1bW5CbG9jaylbMF07XG4gICAgaWYoZCA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgdmFyIGJsb2NrcyA9IGQucm93QmxvY2tzO1xuICAgIHZhciBjYWxjZGF0YSA9IGQuY2FsY2RhdGE7XG5cbiAgICB2YXIgYm90dG9tID0gZmlyc3RSb3dBbmNob3IoYmxvY2tzLCBibG9ja3MubGVuZ3RoKTtcbiAgICB2YXIgc2Nyb2xsSGVpZ2h0ID0gZC5jYWxjZGF0YS5ncm91cEhlaWdodCAtIGhlYWRlckhlaWdodChkKTtcbiAgICB2YXIgc2Nyb2xsWSA9IGNhbGNkYXRhLnNjcm9sbFkgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihib3R0b20gLSBzY3JvbGxIZWlnaHQsIGNhbGNkYXRhLnNjcm9sbFkpKTtcblxuICAgIHZhciBwYWdlcyA9IGZpbmRQYWdlc0FuZENhY2hlSGVpZ2h0cyhibG9ja3MsIHNjcm9sbFksIHNjcm9sbEhlaWdodCk7XG4gICAgaWYocGFnZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIGlmKHBhZ2VzWzBdID09PSBibG9ja3MubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgcGFnZXMudW5zaGlmdChwYWdlc1swXSAtIDEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGFnZXMucHVzaChwYWdlc1swXSArIDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gbWFrZSBwaGFzZWQgb3V0IHBhZ2UganVtcCBieSAyIHdoaWxlIGxlYXZpbmcgc3RhdGlvbmFyeSBwYWdlIGludGFjdFxuICAgIGlmKHBhZ2VzWzBdICUgMikge1xuICAgICAgICBwYWdlcy5yZXZlcnNlKCk7XG4gICAgfVxuXG4gICAgY2VsbHNDb2x1bW5CbG9ja1xuICAgICAgICAuZWFjaChmdW5jdGlvbihkLCBpKSB7XG4gICAgICAgICAgICAvLyB0aGVzZSB2YWx1ZXMgd2lsbCBhbHNvIGJlIG5lZWRlZCB3aGVuIGEgYmxvY2sgaXMgdHJhbnNsYXRlZCBhZ2FpbiBkdWUgdG8gZ3Jvd2luZyBjZWxsIGhlaWdodFxuICAgICAgICAgICAgZC5wYWdlID0gcGFnZXNbaV07XG4gICAgICAgICAgICBkLnNjcm9sbFkgPSBzY3JvbGxZO1xuICAgICAgICB9KTtcblxuICAgIGNlbGxzQ29sdW1uQmxvY2tcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciB5VHJhbnNsYXRlID0gZmlyc3RSb3dBbmNob3IoZC5yb3dCbG9ja3MsIGQucGFnZSkgLSBkLnNjcm9sbFk7XG4gICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgwICcgKyB5VHJhbnNsYXRlICsgJyknO1xuICAgICAgICB9KTtcblxuICAgIC8vIGNvbmRpdGlvbmFsbHkgcmVyZW5kZXJpbmcgcGFuZWwgMCBhbmQgMVxuICAgIGlmKGdkKSB7XG4gICAgICAgIGNvbmRpdGlvbmFsUGFuZWxSZXJlbmRlcihnZCwgdGFibGVDb250cm9sVmlldywgY2VsbHNDb2x1bW5CbG9jaywgcGFnZXMsIGQucHJldlBhZ2VzLCBkLCAwKTtcbiAgICAgICAgY29uZGl0aW9uYWxQYW5lbFJlcmVuZGVyKGdkLCB0YWJsZUNvbnRyb2xWaWV3LCBjZWxsc0NvbHVtbkJsb2NrLCBwYWdlcywgZC5wcmV2UGFnZXMsIGQsIDEpO1xuICAgICAgICByZW5kZXJTY3JvbGxiYXJLaXQodGFibGVDb250cm9sVmlldywgZ2QpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gbWFrZURyYWdSb3coZ2QsIGFsbFRhYmxlQ29udHJvbFZpZXcsIG9wdGlvbmFsTXVsdGlwbGllciwgb3B0aW9uYWxQb3NpdGlvbikge1xuICAgIHJldHVybiBmdW5jdGlvbiBkcmFnUm93KGV2ZW50RCkge1xuICAgICAgICAvLyBtYXkgY29tZSBmcm9tIHdoaWNoZXZlciBET00gZXZlbnQgdGFyZ2V0OiBkcmFnLCB3aGVlbCwgYmFyLi4uIGV2ZW50RCBjb3JyZXNwb25kcyB0byBldmVudCB0YXJnZXRcbiAgICAgICAgdmFyIGQgPSBldmVudEQuY2FsY2RhdGEgPyBldmVudEQuY2FsY2RhdGEgOiBldmVudEQ7XG4gICAgICAgIHZhciB0YWJsZUNvbnRyb2xWaWV3ID0gYWxsVGFibGVDb250cm9sVmlldy5maWx0ZXIoZnVuY3Rpb24oZGQpIHtyZXR1cm4gZC5rZXkgPT09IGRkLmtleTt9KTtcbiAgICAgICAgdmFyIG11bHRpcGxpZXIgPSBvcHRpb25hbE11bHRpcGxpZXIgfHwgZC5zY3JvbGxiYXJTdGF0ZS5kcmFnTXVsdGlwbGllcjtcblxuICAgICAgICB2YXIgaW5pdGlhbFNjcm9sbFkgPSBkLnNjcm9sbFk7XG5cbiAgICAgICAgZC5zY3JvbGxZID0gb3B0aW9uYWxQb3NpdGlvbiA9PT0gdm9pZCgwKSA/IGQuc2Nyb2xsWSArIG11bHRpcGxpZXIgKiBkMy5ldmVudC5keSA6IG9wdGlvbmFsUG9zaXRpb247XG4gICAgICAgIHZhciBjZWxsc0NvbHVtbkJsb2NrID0gdGFibGVDb250cm9sVmlldy5zZWxlY3RBbGwoJy4nICsgYy5jbi55Q29sdW1uKS5zZWxlY3RBbGwoJy4nICsgYy5jbi5jb2x1bW5CbG9jaykuZmlsdGVyKGNlbGxzQmxvY2spO1xuICAgICAgICB1cGRhdGVCbG9ja1lQb3NpdGlvbihnZCwgY2VsbHNDb2x1bW5CbG9jaywgdGFibGVDb250cm9sVmlldyk7XG5cbiAgICAgICAgLy8gcmV0dXJuIGZhbHNlIGlmIHdlJ3ZlIFwidXNlZFwiIHRoZSBzY3JvbGwsIGllIGl0IGRpZCBzb21ldGhpbmcsXG4gICAgICAgIC8vIHNvIHRoZSBldmVudCBzaG91bGRuJ3QgYnViYmxlIChpZiBhcHByb3ByaWF0ZSlcbiAgICAgICAgcmV0dXJuIGQuc2Nyb2xsWSA9PT0gaW5pdGlhbFNjcm9sbFk7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gY29uZGl0aW9uYWxQYW5lbFJlcmVuZGVyKGdkLCB0YWJsZUNvbnRyb2xWaWV3LCBjZWxsc0NvbHVtbkJsb2NrLCBwYWdlcywgcHJldlBhZ2VzLCBkLCByZXZvbHZlckluZGV4KSB7XG4gICAgdmFyIHNob3VsZENvbXBvbmVudFVwZGF0ZSA9IHBhZ2VzW3Jldm9sdmVySW5kZXhdICE9PSBwcmV2UGFnZXNbcmV2b2x2ZXJJbmRleF07XG4gICAgaWYoc2hvdWxkQ29tcG9uZW50VXBkYXRlKSB7XG4gICAgICAgIGNsZWFyVGltZW91dChkLmN1cnJlbnRSZXBhaW50W3Jldm9sdmVySW5kZXhdKTtcbiAgICAgICAgZC5jdXJyZW50UmVwYWludFtyZXZvbHZlckluZGV4XSA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAvLyBzZXRUaW1lb3V0IG1pZ2h0IGxhZyByZW5kZXJpbmcgYnV0IHlpZWxkcyBhIHNtb290aGVyIHNjcm9sbCwgYmVjYXVzZSBmYXN0IHNjcm9sbGluZyBtYWtlc1xuICAgICAgICAgICAgLy8gc29tZSByZXBhaW50cyBpbnZpc2libGUgaWUuIHdhc3RlZnVsIChET00gd29yayBibG9ja3MgdGhlIG1haW4gdGhyZWFkKVxuICAgICAgICAgICAgdmFyIHRvUmVyZW5kZXIgPSBjZWxsc0NvbHVtbkJsb2NrLmZpbHRlcihmdW5jdGlvbihkLCBpKSB7cmV0dXJuIGkgPT09IHJldm9sdmVySW5kZXggJiYgcGFnZXNbaV0gIT09IHByZXZQYWdlc1tpXTt9KTtcbiAgICAgICAgICAgIHJlbmRlckNvbHVtbkNlbGxUcmVlKGdkLCB0YWJsZUNvbnRyb2xWaWV3LCB0b1JlcmVuZGVyLCBjZWxsc0NvbHVtbkJsb2NrKTtcbiAgICAgICAgICAgIHByZXZQYWdlc1tyZXZvbHZlckluZGV4XSA9IHBhZ2VzW3Jldm9sdmVySW5kZXhdO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHdyYXBUZXh0TWFrZXIoY29sdW1uQmxvY2ssIGVsZW1lbnQsIHRhYmxlQ29udHJvbFZpZXcsIGdkKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIHdyYXBUZXh0KCkge1xuICAgICAgICB2YXIgY2VsbFRleHRIb2xkZXIgPSBkMy5zZWxlY3QoZWxlbWVudC5wYXJlbnROb2RlKTtcbiAgICAgICAgY2VsbFRleHRIb2xkZXJcbiAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgICAgICB2YXIgZnJhZ21lbnRzID0gZC5mcmFnbWVudHM7XG4gICAgICAgICAgICAgICAgY2VsbFRleHRIb2xkZXIuc2VsZWN0QWxsKCd0c3Bhbi5saW5lJykuZWFjaChmdW5jdGlvbihkZCwgaSkge1xuICAgICAgICAgICAgICAgICAgICBmcmFnbWVudHNbaV0ud2lkdGggPSB0aGlzLmdldENvbXB1dGVkVGV4dExlbmd0aCgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIC8vIGxhc3QgZWxlbWVudCBpcyBvbmx5IGZvciBtZWFzdXJpbmcgdGhlIHNlcGFyYXRvciBjaGFyYWN0ZXIsIHNvIGl0J3MgaWdub3JlZDpcbiAgICAgICAgICAgICAgICB2YXIgc2VwYXJhdG9yTGVuZ3RoID0gZnJhZ21lbnRzW2ZyYWdtZW50cy5sZW5ndGggLSAxXS53aWR0aDtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdCA9IGZyYWdtZW50cy5zbGljZSgwLCAtMSk7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRSb3cgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEFkZGl0aW9uLCBjdXJyZW50QWRkaXRpb25MZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRSb3dMZW5ndGggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByb3dMZW5ndGhMaW1pdCA9IGQuY29sdW1uLmNvbHVtbldpZHRoIC0gMiAqIGMuY2VsbFBhZDtcbiAgICAgICAgICAgICAgICBkLnZhbHVlID0gJyc7XG4gICAgICAgICAgICAgICAgd2hpbGUocmVzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEFkZGl0aW9uID0gcmVzdC5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50QWRkaXRpb25MZW5ndGggPSBjdXJyZW50QWRkaXRpb24ud2lkdGggKyBzZXBhcmF0b3JMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGlmKGN1cnJlbnRSb3dMZW5ndGggKyBjdXJyZW50QWRkaXRpb25MZW5ndGggPiByb3dMZW5ndGhMaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZC52YWx1ZSArPSBjdXJyZW50Um93LmpvaW4oYy53cmFwU3BhY2VyKSArIGMubGluZUJyZWFrZXI7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93ID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93TGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93LnB1c2goY3VycmVudEFkZGl0aW9uLnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Um93TGVuZ3RoICs9IGN1cnJlbnRBZGRpdGlvbkxlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYoY3VycmVudFJvd0xlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBkLnZhbHVlICs9IGN1cnJlbnRSb3cuam9pbihjLndyYXBTcGFjZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkLndyYXBwZWQgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gdGhlIHByZS13cmFwcGVkIHRleHQgd2FzIHJlbmRlcmVkIG9ubHkgZm9yIHRoZSB0ZXh0IG1lYXN1cmVtZW50c1xuICAgICAgICBjZWxsVGV4dEhvbGRlci5zZWxlY3RBbGwoJ3RzcGFuLmxpbmUnKS5yZW1vdmUoKTtcblxuICAgICAgICAvLyByZXN1cHBseSB0ZXh0LCBub3cgd3JhcHBlZFxuICAgICAgICBwb3B1bGF0ZUNlbGxUZXh0KGNlbGxUZXh0SG9sZGVyLnNlbGVjdCgnLicgKyBjLmNuLmNlbGxUZXh0KSwgdGFibGVDb250cm9sVmlldywgY29sdW1uQmxvY2ssIGdkKTtcbiAgICAgICAgZDMuc2VsZWN0KGVsZW1lbnQucGFyZW50Tm9kZS5wYXJlbnROb2RlKS5jYWxsKHNldENlbGxIZWlnaHRBbmRQb3NpdGlvblkpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVlQb3NpdGlvbk1ha2VyKGNvbHVtbkJsb2NrLCBlbGVtZW50LCB0YWJsZUNvbnRyb2xWaWV3LCBnZCwgZCkge1xuICAgIHJldHVybiBmdW5jdGlvbiB1cGRhdGVZUG9zaXRpb24oKSB7XG4gICAgICAgIGlmKGQuc2V0dGxlZFkpIHJldHVybjtcbiAgICAgICAgdmFyIGNlbGxUZXh0SG9sZGVyID0gZDMuc2VsZWN0KGVsZW1lbnQucGFyZW50Tm9kZSk7XG4gICAgICAgIHZhciBsID0gZ2V0QmxvY2soZCk7XG4gICAgICAgIHZhciByb3dJbmRleCA9IGQua2V5IC0gbC5maXJzdFJvd0luZGV4O1xuXG4gICAgICAgIHZhciBkZWNsYXJlZFJvd0hlaWdodCA9IGwucm93c1tyb3dJbmRleF0ucm93SGVpZ2h0O1xuXG4gICAgICAgIHZhciByZXF1aXJlZEhlaWdodCA9IGQuY2VsbEhlaWdodE1heUluY3JlYXNlID8gZWxlbWVudC5wYXJlbnROb2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCArIDIgKiBjLmNlbGxQYWQgOiBkZWNsYXJlZFJvd0hlaWdodDtcblxuICAgICAgICB2YXIgZmluYWxIZWlnaHQgPSBNYXRoLm1heChyZXF1aXJlZEhlaWdodCwgZGVjbGFyZWRSb3dIZWlnaHQpO1xuICAgICAgICB2YXIgaW5jcmVhc2UgPSBmaW5hbEhlaWdodCAtIGwucm93c1tyb3dJbmRleF0ucm93SGVpZ2h0O1xuXG4gICAgICAgIGlmKGluY3JlYXNlKSB7XG4gICAgICAgICAgICAvLyBjdXJyZW50IHJvdyBoZWlnaHQgaW5jcmVhc2VkXG4gICAgICAgICAgICBsLnJvd3Nbcm93SW5kZXhdLnJvd0hlaWdodCA9IGZpbmFsSGVpZ2h0O1xuXG4gICAgICAgICAgICBjb2x1bW5CbG9ja1xuICAgICAgICAgICAgICAgIC5zZWxlY3RBbGwoJy4nICsgYy5jbi5jb2x1bW5DZWxsKVxuICAgICAgICAgICAgICAgIC5jYWxsKHNldENlbGxIZWlnaHRBbmRQb3NpdGlvblkpO1xuXG4gICAgICAgICAgICB1cGRhdGVCbG9ja1lQb3NpdGlvbihudWxsLCBjb2x1bW5CbG9jay5maWx0ZXIoY2VsbHNCbG9jayksIDApO1xuXG4gICAgICAgICAgICAvLyBpZiBkLmNvbHVtbi50eXBlID09PSAnaGVhZGVyJywgdGhlbiB0aGUgc2Nyb2xsYmFyIGhhcyB0byBiZSBwdXNoZWQgZG93bndhcmQgdG8gdGhlIHNjcm9sbGFibGUgYXJlYVxuICAgICAgICAgICAgLy8gaWYgZC5jb2x1bW4udHlwZSA9PT0gJ2NlbGxzJywgaXQgY2FuIHN0aWxsIGJlIHJlbGV2YW50IGlmIHRvdGFsIHNjcm9sbGluZyBjb250ZW50IGhlaWdodCBpcyBsZXNzIHRoYW4gdGhlXG4gICAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxhYmxlIHdpbmRvdywgYXMgaW5jcmVhc2VzIHRvIHJvdyBoZWlnaHRzIG1heSBuZWVkIHNjcm9sbGJhciB1cGRhdGVzXG4gICAgICAgICAgICByZW5kZXJTY3JvbGxiYXJLaXQodGFibGVDb250cm9sVmlldywgZ2QsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgY2VsbFRleHRIb2xkZXJcbiAgICAgICAgICAgIC5hdHRyKCd0cmFuc2Zvcm0nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAvLyB0aGlzIGNvZGUgYmxvY2sgaXMgb25seSBpbnZva2VkIGZvciBpdGVtcyB3aGVyZSBkLmNlbGxIZWlnaHRNYXlJbmNyZWFzZSBpcyB0cnV0aHlcbiAgICAgICAgICAgICAgICB2YXIgZWxlbWVudCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgdmFyIGNvbHVtbkNlbGxFbGVtZW50ID0gZWxlbWVudC5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBib3ggPSBjb2x1bW5DZWxsRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICAgICAgICB2YXIgcmVjdEJveCA9IGQzLnNlbGVjdChlbGVtZW50LnBhcmVudE5vZGUpLnNlbGVjdCgnLicgKyBjLmNuLmNlbGxSZWN0KS5ub2RlKCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRUcmFuc2Zvcm0gPSBlbGVtZW50LnRyYW5zZm9ybS5iYXNlVmFsLmNvbnNvbGlkYXRlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHlQb3NpdGlvbiA9IHJlY3RCb3gudG9wIC0gYm94LnRvcCArIChjdXJyZW50VHJhbnNmb3JtID8gY3VycmVudFRyYW5zZm9ybS5tYXRyaXguZiA6IGMuY2VsbFBhZCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuICd0cmFuc2xhdGUoJyArIHhQb3NpdGlvbihkLCBkMy5zZWxlY3QoZWxlbWVudC5wYXJlbnROb2RlKS5zZWxlY3QoJy4nICsgYy5jbi5jZWxsVGV4dEhvbGRlcikubm9kZSgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoKSArICcgJyArIHlQb3NpdGlvbiArICcpJztcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIGQuc2V0dGxlZFkgPSB0cnVlO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIHhQb3NpdGlvbihkLCBvcHRpb25hbFdpZHRoKSB7XG4gICAgc3dpdGNoKGQuYWxpZ24pIHtcbiAgICAgICAgY2FzZSAnbGVmdCc6IHJldHVybiBjLmNlbGxQYWQ7XG4gICAgICAgIGNhc2UgJ3JpZ2h0JzogcmV0dXJuIGQuY29sdW1uLmNvbHVtbldpZHRoIC0gKG9wdGlvbmFsV2lkdGggfHwgMCkgLSBjLmNlbGxQYWQ7XG4gICAgICAgIGNhc2UgJ2NlbnRlcic6IHJldHVybiAoZC5jb2x1bW4uY29sdW1uV2lkdGggLSAob3B0aW9uYWxXaWR0aCB8fCAwKSkgLyAyO1xuICAgICAgICBkZWZhdWx0OiByZXR1cm4gYy5jZWxsUGFkO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc2V0Q2VsbEhlaWdodEFuZFBvc2l0aW9uWShjb2x1bW5DZWxsKSB7XG4gICAgY29sdW1uQ2VsbFxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgdmFyIGhlYWRlckhlaWdodCA9IGQucm93QmxvY2tzWzBdLmF1eGlsaWFyeUJsb2Nrcy5yZWR1Y2UoZnVuY3Rpb24ocCwgbikge3JldHVybiBwICsgcm93c0hlaWdodChuLCBJbmZpbml0eSk7fSwgMCk7XG4gICAgICAgICAgICB2YXIgbCA9IGdldEJsb2NrKGQpO1xuICAgICAgICAgICAgdmFyIHJvd0FuY2hvciA9IHJvd3NIZWlnaHQobCwgZC5rZXkpO1xuICAgICAgICAgICAgdmFyIHlPZmZzZXQgPSByb3dBbmNob3IgKyBoZWFkZXJIZWlnaHQ7XG4gICAgICAgICAgICByZXR1cm4gJ3RyYW5zbGF0ZSgwICcgKyB5T2Zmc2V0ICsgJyknO1xuICAgICAgICB9KVxuICAgICAgICAuc2VsZWN0QWxsKCcuJyArIGMuY24uY2VsbFJlY3QpXG4gICAgICAgIC5hdHRyKCdoZWlnaHQnLCBmdW5jdGlvbihkKSB7cmV0dXJuIGdldFJvdyhnZXRCbG9jayhkKSwgZC5rZXkpLnJvd0hlaWdodDt9KTtcbn1cblxuZnVuY3Rpb24gZmlyc3RSb3dBbmNob3IoYmxvY2tzLCBwYWdlKSB7XG4gICAgdmFyIHRvdGFsID0gMDtcbiAgICBmb3IodmFyIGkgPSBwYWdlIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdG90YWwgKz0gYWxsUm93c0hlaWdodChibG9ja3NbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gdG90YWw7XG59XG5cbmZ1bmN0aW9uIHJvd3NIZWlnaHQocm93QmxvY2ssIGtleSkge1xuICAgIHZhciB0b3RhbCA9IDA7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHJvd0Jsb2NrLnJvd3MubGVuZ3RoICYmIHJvd0Jsb2NrLnJvd3NbaV0ucm93SW5kZXggPCBrZXk7IGkrKykge1xuICAgICAgICB0b3RhbCArPSByb3dCbG9jay5yb3dzW2ldLnJvd0hlaWdodDtcbiAgICB9XG4gICAgcmV0dXJuIHRvdGFsO1xufVxuXG5mdW5jdGlvbiBhbGxSb3dzSGVpZ2h0KHJvd0Jsb2NrKSB7XG4gICAgdmFyIGNhY2hlZCA9IHJvd0Jsb2NrLmFsbFJvd3NIZWlnaHQ7XG5cbiAgICBpZihjYWNoZWQgIT09IHZvaWQoMCkpIHtcbiAgICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICB9XG5cbiAgICB2YXIgdG90YWwgPSAwO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCByb3dCbG9jay5yb3dzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRvdGFsICs9IHJvd0Jsb2NrLnJvd3NbaV0ucm93SGVpZ2h0O1xuICAgIH1cbiAgICByb3dCbG9jay5hbGxSb3dzSGVpZ2h0ID0gdG90YWw7XG5cbiAgICByZXR1cm4gdG90YWw7XG59XG5cbmZ1bmN0aW9uIGdldEJsb2NrKGQpIHtyZXR1cm4gZC5yb3dCbG9ja3NbZC5wYWdlXTt9XG5mdW5jdGlvbiBnZXRSb3cobCwgaSkge3JldHVybiBsLnJvd3NbaSAtIGwuZmlyc3RSb3dJbmRleF07fVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9jb21wb25lbnRzL2RyYXdpbmdcIjo2MTQsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9saWIvZ3VwXCI6NzE3LFwiLi4vLi4vbGliL3N2Z190ZXh0X3V0aWxzXCI6NzQzLFwiLi9jb25zdGFudHNcIjoxMjMyLFwiLi9kYXRhX3ByZXBhcmF0aW9uX2hlbHBlclwiOjEyMzMsXCIuL2RhdGFfc3BsaXRfaGVscGVyc1wiOjEyMzQsXCJkM1wiOjE2M31dLDEyMzg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYm94QXR0cnMgPSBfZGVyZXFfKCcuLi9ib3gvYXR0cmlidXRlcycpO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgeTogYm94QXR0cnMueSxcbiAgICB4OiBib3hBdHRycy54LFxuICAgIHgwOiBib3hBdHRycy54MCxcbiAgICB5MDogYm94QXR0cnMueTAsXG4gICAgbmFtZTogZXh0ZW5kRmxhdCh7fSwgYm94QXR0cnMubmFtZSwge1xuICAgICAgICBcbiAgICB9KSxcbiAgICBvcmllbnRhdGlvbjogZXh0ZW5kRmxhdCh7fSwgYm94QXR0cnMub3JpZW50YXRpb24sIHtcbiAgICAgICAgXG4gICAgfSksXG5cbiAgICBiYW5kd2lkdGg6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBzY2FsZWdyb3VwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZGZsdDogJycsXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgc2NhbGVtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ3dpZHRoJywgJ2NvdW50J10sXG4gICAgICAgIGRmbHQ6ICd3aWR0aCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgc3Bhbm1vZGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICB2YWx1ZXM6IFsnc29mdCcsICdoYXJkJywgJ21hbnVhbCddLFxuICAgICAgICBkZmx0OiAnc29mdCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHNwYW46IHtcbiAgICAgICAgdmFsVHlwZTogJ2luZm9fYXJyYXknLFxuICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAge3ZhbFR5cGU6ICdhbnknLCBlZGl0VHlwZTogJ2NhbGMnfSxcbiAgICAgICAgICAgIHt2YWxUeXBlOiAnYW55JywgZWRpdFR5cGU6ICdjYWxjJ31cbiAgICAgICAgXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBsaW5lOiB7XG4gICAgICAgIGNvbG9yOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIGRmbHQ6IDIsXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnXG4gICAgfSxcbiAgICBmaWxsY29sb3I6IGJveEF0dHJzLmZpbGxjb2xvcixcblxuICAgIHBvaW50czogZXh0ZW5kRmxhdCh7fSwgYm94QXR0cnMuYm94cG9pbnRzLCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIGppdHRlcjogZXh0ZW5kRmxhdCh7fSwgYm94QXR0cnMuaml0dGVyLCB7XG4gICAgICAgIFxuICAgIH0pLFxuICAgIHBvaW50cG9zOiBleHRlbmRGbGF0KHt9LCBib3hBdHRycy5wb2ludHBvcywge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIHdpZHRoOiBleHRlbmRGbGF0KHt9LCBib3hBdHRycy53aWR0aCwge1xuICAgICAgICBcbiAgICB9KSxcblxuICAgIG1hcmtlcjogYm94QXR0cnMubWFya2VyLFxuICAgIHRleHQ6IGJveEF0dHJzLnRleHQsXG4gICAgaG92ZXJ0ZXh0OiBib3hBdHRycy5ob3ZlcnRleHQsXG4gICAgaG92ZXJ0ZW1wbGF0ZTogYm94QXR0cnMuaG92ZXJ0ZW1wbGF0ZSxcblxuICAgIGJveDoge1xuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB3aWR0aDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICBtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEsXG4gICAgICAgICAgICBkZmx0OiAwLjI1LFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGZpbGxjb2xvcjoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2NvbG9yJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgbGluZToge1xuICAgICAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgICAgICB2YWxUeXBlOiAnY29sb3InLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuXG4gICAgbWVhbmxpbmU6IHtcbiAgICAgICAgdmlzaWJsZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgZGZsdDogZmFsc2UsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCcsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgY29sb3I6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdjb2xvcicsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90J1xuICAgIH0sXG5cbiAgICBzaWRlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2JvdGgnLCAncG9zaXRpdmUnLCAnbmVnYXRpdmUnXSxcbiAgICAgICAgZGZsdDogJ2JvdGgnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcblxuICAgIG9mZnNldGdyb3VwOiBib3hBdHRycy5vZmZzZXRncm91cCxcbiAgICBhbGlnbm1lbnRncm91cDogYm94QXR0cnMuYWxpZ25tZW50Z3JvdXAsXG5cbiAgICBzZWxlY3RlZDogYm94QXR0cnMuc2VsZWN0ZWQsXG4gICAgdW5zZWxlY3RlZDogYm94QXR0cnMudW5zZWxlY3RlZCxcblxuICAgIGhvdmVyb246IHtcbiAgICAgICAgdmFsVHlwZTogJ2ZsYWdsaXN0JyxcbiAgICAgICAgZmxhZ3M6IFsndmlvbGlucycsICdwb2ludHMnLCAna2RlJ10sXG4gICAgICAgIGRmbHQ6ICd2aW9saW5zK3BvaW50cytrZGUnLFxuICAgICAgICBleHRyYXM6IFsnYWxsJ10sXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vYm94L2F0dHJpYnV0ZXNcIjo4ODB9XSwxMjM5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGJveENhbGMgPSBfZGVyZXFfKCcuLi9ib3gvY2FsYycpO1xudmFyIGhlbHBlcnMgPSBfZGVyZXFfKCcuL2hlbHBlcnMnKTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNhbGMoZ2QsIHRyYWNlKSB7XG4gICAgdmFyIGNkID0gYm94Q2FsYyhnZCwgdHJhY2UpO1xuXG4gICAgaWYoY2RbMF0udC5lbXB0eSkgcmV0dXJuIGNkO1xuXG4gICAgdmFyIGZ1bGxMYXlvdXQgPSBnZC5fZnVsbExheW91dDtcbiAgICB2YXIgdmFsQXhpcyA9IEF4ZXMuZ2V0RnJvbUlkKFxuICAgICAgICBnZCxcbiAgICAgICAgdHJhY2VbdHJhY2Uub3JpZW50YXRpb24gPT09ICdoJyA/ICd4YXhpcycgOiAneWF4aXMnXVxuICAgICk7XG5cbiAgICB2YXIgc3Bhbk1pbiA9IEluZmluaXR5O1xuICAgIHZhciBzcGFuTWF4ID0gLUluZmluaXR5O1xuICAgIHZhciBtYXhLREUgPSAwO1xuICAgIHZhciBtYXhDb3VudCA9IDA7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgY2QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNkaSA9IGNkW2ldO1xuICAgICAgICB2YXIgdmFscyA9IGNkaS5wdHMubWFwKGhlbHBlcnMuZXh0cmFjdFZhbCk7XG5cbiAgICAgICAgdmFyIGJhbmR3aWR0aCA9IGNkaS5iYW5kd2lkdGggPSBjYWxjQmFuZHdpZHRoKHRyYWNlLCBjZGksIHZhbHMpO1xuICAgICAgICB2YXIgc3BhbiA9IGNkaS5zcGFuID0gY2FsY1NwYW4odHJhY2UsIGNkaSwgdmFsQXhpcywgYmFuZHdpZHRoKTtcblxuICAgICAgICBpZihjZGkubWluID09PSBjZGkubWF4ICYmIGJhbmR3aWR0aCA9PT0gMCkge1xuICAgICAgICAgICAgLy8gaWYgc3BhbiBpcyB6ZXJvIGFuZCBiYW5kd2lkdGggaXMgemVybywgd2Ugd2FudCBhIHZpb2xpbiB3aXRoIHplcm8gd2lkdGhcbiAgICAgICAgICAgIHNwYW4gPSBjZGkuc3BhbiA9IFtjZGkubWluLCBjZGkubWF4XTtcbiAgICAgICAgICAgIGNkaS5kZW5zaXR5ID0gW3t2OiAxLCB0OiBzcGFuWzBdfV07XG4gICAgICAgICAgICBjZGkuYmFuZHdpZHRoID0gYmFuZHdpZHRoO1xuICAgICAgICAgICAgbWF4S0RFID0gTWF0aC5tYXgobWF4S0RFLCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHN0ZXAgdGhhdCB3ZWxsIGNvdmVycyB0aGUgYmFuZHdpZHRoIGFuZCBpcyBtdWx0aXBsZSBvZiBzcGFuIGRpc3RhbmNlXG4gICAgICAgICAgICB2YXIgZGlzdCA9IHNwYW5bMV0gLSBzcGFuWzBdO1xuICAgICAgICAgICAgdmFyIG4gPSBNYXRoLmNlaWwoZGlzdCAvIChiYW5kd2lkdGggLyAzKSk7XG4gICAgICAgICAgICB2YXIgc3RlcCA9IGRpc3QgLyBuO1xuXG4gICAgICAgICAgICBpZighaXNGaW5pdGUoc3RlcCkgfHwgIWlzRmluaXRlKG4pKSB7XG4gICAgICAgICAgICAgICAgTGliLmVycm9yKCdTb21ldGhpbmcgd2VudCB3cm9uZyB3aXRoIGNvbXB1dGluZyB0aGUgdmlvbGluIHNwYW4nKTtcbiAgICAgICAgICAgICAgICBjZFswXS50LmVtcHR5ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2Q7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBrZGUgPSBoZWxwZXJzLm1ha2VLREUoY2RpLCB0cmFjZSwgdmFscyk7XG4gICAgICAgICAgICBjZGkuZGVuc2l0eSA9IG5ldyBBcnJheShuKTtcblxuICAgICAgICAgICAgZm9yKHZhciBrID0gMCwgdCA9IHNwYW5bMF07IHQgPCAoc3BhblsxXSArIHN0ZXAgLyAyKTsgaysrLCB0ICs9IHN0ZXApIHtcbiAgICAgICAgICAgICAgICB2YXIgdiA9IGtkZSh0KTtcbiAgICAgICAgICAgICAgICBjZGkuZGVuc2l0eVtrXSA9IHt2OiB2LCB0OiB0fTtcbiAgICAgICAgICAgICAgICBtYXhLREUgPSBNYXRoLm1heChtYXhLREUsIHYpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbWF4Q291bnQgPSBNYXRoLm1heChtYXhDb3VudCwgdmFscy5sZW5ndGgpO1xuICAgICAgICBzcGFuTWluID0gTWF0aC5taW4oc3Bhbk1pbiwgc3BhblswXSk7XG4gICAgICAgIHNwYW5NYXggPSBNYXRoLm1heChzcGFuTWF4LCBzcGFuWzFdKTtcbiAgICB9XG5cbiAgICB2YXIgZXh0cmVtZXMgPSBBeGVzLmZpbmRFeHRyZW1lcyh2YWxBeGlzLCBbc3Bhbk1pbiwgc3Bhbk1heF0sIHtwYWRkZWQ6IHRydWV9KTtcbiAgICB0cmFjZS5fZXh0cmVtZXNbdmFsQXhpcy5faWRdID0gZXh0cmVtZXM7XG5cbiAgICBpZih0cmFjZS53aWR0aCkge1xuICAgICAgICBjZFswXS50Lm1heEtERSA9IG1heEtERTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgdmlvbGluU2NhbGVHcm91cFN0YXRzID0gZnVsbExheW91dC5fdmlvbGluU2NhbGVHcm91cFN0YXRzO1xuICAgICAgICB2YXIgc2NhbGVHcm91cCA9IHRyYWNlLnNjYWxlZ3JvdXA7XG4gICAgICAgIHZhciBncm91cFN0YXRzID0gdmlvbGluU2NhbGVHcm91cFN0YXRzW3NjYWxlR3JvdXBdO1xuXG4gICAgICAgIGlmKGdyb3VwU3RhdHMpIHtcbiAgICAgICAgICAgIGdyb3VwU3RhdHMubWF4S0RFID0gTWF0aC5tYXgoZ3JvdXBTdGF0cy5tYXhLREUsIG1heEtERSk7XG4gICAgICAgICAgICBncm91cFN0YXRzLm1heENvdW50ID0gTWF0aC5tYXgoZ3JvdXBTdGF0cy5tYXhDb3VudCwgbWF4Q291bnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmlvbGluU2NhbGVHcm91cFN0YXRzW3NjYWxlR3JvdXBdID0ge1xuICAgICAgICAgICAgICAgIG1heEtERTogbWF4S0RFLFxuICAgICAgICAgICAgICAgIG1heENvdW50OiBtYXhDb3VudFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNkWzBdLnQubGFiZWxzLmtkZSA9IExpYi5fKGdkLCAna2RlOicpO1xuXG4gICAgcmV0dXJuIGNkO1xufTtcblxuLy8gRGVmYXVsdCB0byBTaWx2ZW1hbidzIHJ1bGUgb2YgdGh1bWJcbi8vIC0gaHR0cHM6Ly9zdGF0cy5zdGFja2V4Y2hhbmdlLmNvbS9hLzY2NzFcbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvS2VybmVsX2RlbnNpdHlfZXN0aW1hdGlvbiNBX3J1bGUtb2YtdGh1bWJfYmFuZHdpZHRoX2VzdGltYXRvclxuLy8gLSBodHRwczovL2dpdGh1Yi5jb20vc3RhdHNtb2RlbHMvc3RhdHNtb2RlbHMvYmxvYi9tYXN0ZXIvc3RhdHNtb2RlbHMvbm9ucGFyYW1ldHJpYy9iYW5kd2lkdGhzLnB5XG5mdW5jdGlvbiBzaWx2ZXJtYW5SdWxlKGxlbiwgc3NkLCBpcXIpIHtcbiAgICB2YXIgYSA9IE1hdGgubWluKHNzZCwgaXFyIC8gMS4zNDkpO1xuICAgIHJldHVybiAxLjA1OSAqIGEgKiBNYXRoLnBvdyhsZW4sIC0wLjIpO1xufVxuXG5mdW5jdGlvbiBjYWxjQmFuZHdpZHRoKHRyYWNlLCBjZGksIHZhbHMpIHtcbiAgICB2YXIgc3BhbiA9IGNkaS5tYXggLSBjZGkubWluO1xuXG4gICAgLy8gSWYgc3BhbiBpcyB6ZXJvXG4gICAgaWYoIXNwYW4pIHtcbiAgICAgICAgaWYodHJhY2UuYmFuZHdpZHRoKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJhY2UuYmFuZHdpZHRoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gaWYgc3BhbiBpcyB6ZXJvIGFuZCBubyBiYW5kd2lkdGggaXMgc3BlY2lmaWVkXG4gICAgICAgICAgICAvLyBpdCByZXR1cm5zIHplcm8gYmFuZHdpZHRoIHdoaWNoIGlzIGEgc3BlY2lhbCBjYXNlXG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIExpbWl0IGhvdyBzbWFsbCB0aGUgYmFuZHdpZHRoIGNhbiBiZS5cbiAgICAvL1xuICAgIC8vIFNpbHZlcm1hbidzIHJ1bGUgb2YgdGh1bWIgY2FuIGJlIFwidmVyeVwiIHNtYWxsXG4gICAgLy8gd2hlbiBJUVIgZG9lcyBhIHBvb3Igam9iIGF0IGRlc2NyaWJpbmcgdGhlIHNwcmVhZFxuICAgIC8vIG9mIHRoZSBkaXN0cmlidXRpb24uXG4gICAgLy8gV2UgYWxzbyB3YW50IHRvIGxpbWl0IGN1c3RvbSBiYW5kd2lkdGhzXG4gICAgLy8gdG8gbm90IGJsb3cgdXAga2RlIGNvbXB1dGF0aW9ucy5cblxuICAgIGlmKHRyYWNlLmJhbmR3aWR0aCkge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgodHJhY2UuYmFuZHdpZHRoLCBzcGFuIC8gMWU0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgbGVuID0gdmFscy5sZW5ndGg7XG4gICAgICAgIHZhciBzc2QgPSBMaWIuc3RkZXYodmFscywgbGVuIC0gMSwgY2RpLm1lYW4pO1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoXG4gICAgICAgICAgICBzaWx2ZXJtYW5SdWxlKGxlbiwgc3NkLCBjZGkucTMgLSBjZGkucTEpLFxuICAgICAgICAgICAgc3BhbiAvIDEwMFxuICAgICAgICApO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gY2FsY1NwYW4odHJhY2UsIGNkaSwgdmFsQXhpcywgYmFuZHdpZHRoKSB7XG4gICAgdmFyIHNwYW5tb2RlID0gdHJhY2Uuc3Bhbm1vZGU7XG4gICAgdmFyIHNwYW5JbiA9IHRyYWNlLnNwYW4gfHwgW107XG4gICAgdmFyIHNwYW5UaWdodCA9IFtjZGkubWluLCBjZGkubWF4XTtcbiAgICB2YXIgc3Bhbkxvb3NlID0gW2NkaS5taW4gLSAyICogYmFuZHdpZHRoLCBjZGkubWF4ICsgMiAqIGJhbmR3aWR0aF07XG4gICAgdmFyIHNwYW5PdXQ7XG5cbiAgICBmdW5jdGlvbiBjYWxjU3Bhbkl0ZW0oaW5kZXgpIHtcbiAgICAgICAgdmFyIHMgPSBzcGFuSW5baW5kZXhdO1xuICAgICAgICB2YXIgc2MgPSB2YWxBeGlzLnR5cGUgPT09ICdtdWx0aWNhdGVnb3J5JyA/XG4gICAgICAgICAgICB2YWxBeGlzLnIyYyhzKSA6XG4gICAgICAgICAgICB2YWxBeGlzLmQyYyhzLCAwLCB0cmFjZVtjZGkudmFsTGV0dGVyICsgJ2NhbGVuZGFyJ10pO1xuICAgICAgICByZXR1cm4gc2MgPT09IEJBRE5VTSA/IHNwYW5Mb29zZVtpbmRleF0gOiBzYztcbiAgICB9XG5cbiAgICBpZihzcGFubW9kZSA9PT0gJ3NvZnQnKSB7XG4gICAgICAgIHNwYW5PdXQgPSBzcGFuTG9vc2U7XG4gICAgfSBlbHNlIGlmKHNwYW5tb2RlID09PSAnaGFyZCcpIHtcbiAgICAgICAgc3Bhbk91dCA9IHNwYW5UaWdodDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzcGFuT3V0ID0gW2NhbGNTcGFuSXRlbSgwKSwgY2FsY1NwYW5JdGVtKDEpXTtcbiAgICB9XG5cbiAgICAvLyB0byByZXVzZSB0aGUgZXF1YWwtcmFuZ2UtaXRlbSBibG9ja1xuICAgIHZhciBkdW1teUF4ID0ge1xuICAgICAgICB0eXBlOiAnbGluZWFyJyxcbiAgICAgICAgcmFuZ2U6IHNwYW5PdXRcbiAgICB9O1xuICAgIEF4ZXMuc2V0Q29udmVydChkdW1teUF4KTtcbiAgICBkdW1teUF4LmNsZWFuUmFuZ2UoKTtcblxuICAgIHJldHVybiBzcGFuT3V0O1xufVxuXG59LHtcIi4uLy4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi8uLi9saWJcIjo3MTksXCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL2JveC9jYWxjXCI6ODgxLFwiLi9oZWxwZXJzXCI6MTI0Mn1dLDEyNDA6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc2V0UG9zaXRpb25PZmZzZXQgPSBfZGVyZXFfKCcuLi9ib3gvY3Jvc3NfdHJhY2VfY2FsYycpLnNldFBvc2l0aW9uT2Zmc2V0O1xudmFyIG9yaWVudGF0aW9ucyA9IFsndicsICdoJ107XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3Jvc3NUcmFjZUNhbGMoZ2QsIHBsb3RpbmZvKSB7XG4gICAgdmFyIGNhbGNkYXRhID0gZ2QuY2FsY2RhdGE7XG4gICAgdmFyIHhhID0gcGxvdGluZm8ueGF4aXM7XG4gICAgdmFyIHlhID0gcGxvdGluZm8ueWF4aXM7XG5cbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgb3JpZW50YXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBvcmllbnRhdGlvbiA9IG9yaWVudGF0aW9uc1tpXTtcbiAgICAgICAgdmFyIHBvc0F4aXMgPSBvcmllbnRhdGlvbiA9PT0gJ2gnID8geWEgOiB4YTtcbiAgICAgICAgdmFyIHZpb2xpbkxpc3QgPSBbXTtcblxuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgY2FsY2RhdGEubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIHZhciBjZCA9IGNhbGNkYXRhW2pdO1xuICAgICAgICAgICAgdmFyIHQgPSBjZFswXS50O1xuICAgICAgICAgICAgdmFyIHRyYWNlID0gY2RbMF0udHJhY2U7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlLnZpc2libGUgPT09IHRydWUgJiYgdHJhY2UudHlwZSA9PT0gJ3Zpb2xpbicgJiZcbiAgICAgICAgICAgICAgICAgICAgIXQuZW1wdHkgJiZcbiAgICAgICAgICAgICAgICAgICAgdHJhY2Uub3JpZW50YXRpb24gPT09IG9yaWVudGF0aW9uICYmXG4gICAgICAgICAgICAgICAgICAgIHRyYWNlLnhheGlzID09PSB4YS5faWQgJiZcbiAgICAgICAgICAgICAgICAgICAgdHJhY2UueWF4aXMgPT09IHlhLl9pZFxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICB2aW9saW5MaXN0LnB1c2goaik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXRQb3NpdGlvbk9mZnNldCgndmlvbGluJywgZ2QsIHZpb2xpbkxpc3QsIHBvc0F4aXMpO1xuICAgIH1cbn07XG5cbn0se1wiLi4vYm94L2Nyb3NzX3RyYWNlX2NhbGNcIjo4ODJ9XSwxMjQxOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xuXG52YXIgYm94RGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9ib3gvZGVmYXVsdHMnKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc3VwcGx5RGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0KSB7XG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UodHJhY2VJbiwgdHJhY2VPdXQsIGF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjb2VyY2UyKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UyKHRyYWNlSW4sIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICBib3hEZWZhdWx0cy5oYW5kbGVTYW1wbGVEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgY29lcmNlLCBsYXlvdXQpO1xuICAgIGlmKHRyYWNlT3V0LnZpc2libGUgPT09IGZhbHNlKSByZXR1cm47XG5cbiAgICBjb2VyY2UoJ2JhbmR3aWR0aCcpO1xuICAgIGNvZXJjZSgnc2lkZScpO1xuXG4gICAgdmFyIHdpZHRoID0gY29lcmNlKCd3aWR0aCcpO1xuICAgIGlmKCF3aWR0aCkge1xuICAgICAgICBjb2VyY2UoJ3NjYWxlZ3JvdXAnLCB0cmFjZU91dC5uYW1lKTtcbiAgICAgICAgY29lcmNlKCdzY2FsZW1vZGUnKTtcbiAgICB9XG5cbiAgICB2YXIgc3BhbiA9IGNvZXJjZSgnc3BhbicpO1xuICAgIHZhciBzcGFubW9kZURmbHQ7XG4gICAgaWYoQXJyYXkuaXNBcnJheShzcGFuKSkgc3Bhbm1vZGVEZmx0ID0gJ21hbnVhbCc7XG4gICAgY29lcmNlKCdzcGFubW9kZScsIHNwYW5tb2RlRGZsdCk7XG5cbiAgICB2YXIgbGluZUNvbG9yID0gY29lcmNlKCdsaW5lLmNvbG9yJywgKHRyYWNlSW4ubWFya2VyIHx8IHt9KS5jb2xvciB8fCBkZWZhdWx0Q29sb3IpO1xuICAgIHZhciBsaW5lV2lkdGggPSBjb2VyY2UoJ2xpbmUud2lkdGgnKTtcbiAgICB2YXIgZmlsbENvbG9yID0gY29lcmNlKCdmaWxsY29sb3InLCBDb2xvci5hZGRPcGFjaXR5KHRyYWNlT3V0LmxpbmUuY29sb3IsIDAuNSkpO1xuXG4gICAgYm94RGVmYXVsdHMuaGFuZGxlUG9pbnRzRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGNvZXJjZSwge3ByZWZpeDogJyd9KTtcblxuICAgIHZhciBib3hXaWR0aCA9IGNvZXJjZTIoJ2JveC53aWR0aCcpO1xuICAgIHZhciBib3hGaWxsQ29sb3IgPSBjb2VyY2UyKCdib3guZmlsbGNvbG9yJywgZmlsbENvbG9yKTtcbiAgICB2YXIgYm94TGluZUNvbG9yID0gY29lcmNlMignYm94LmxpbmUuY29sb3InLCBsaW5lQ29sb3IpO1xuICAgIHZhciBib3hMaW5lV2lkdGggPSBjb2VyY2UyKCdib3gubGluZS53aWR0aCcsIGxpbmVXaWR0aCk7XG4gICAgdmFyIGJveFZpc2libGUgPSBjb2VyY2UoJ2JveC52aXNpYmxlJywgQm9vbGVhbihib3hXaWR0aCB8fCBib3hGaWxsQ29sb3IgfHwgYm94TGluZUNvbG9yIHx8IGJveExpbmVXaWR0aCkpO1xuICAgIGlmKCFib3hWaXNpYmxlKSB0cmFjZU91dC5ib3ggPSB7dmlzaWJsZTogZmFsc2V9O1xuXG4gICAgdmFyIG1lYW5MaW5lQ29sb3IgPSBjb2VyY2UyKCdtZWFubGluZS5jb2xvcicsIGxpbmVDb2xvcik7XG4gICAgdmFyIG1lYW5MaW5lV2lkdGggPSBjb2VyY2UyKCdtZWFubGluZS53aWR0aCcsIGxpbmVXaWR0aCk7XG4gICAgdmFyIG1lYW5MaW5lVmlzaWJsZSA9IGNvZXJjZSgnbWVhbmxpbmUudmlzaWJsZScsIEJvb2xlYW4obWVhbkxpbmVDb2xvciB8fCBtZWFuTGluZVdpZHRoKSk7XG4gICAgaWYoIW1lYW5MaW5lVmlzaWJsZSkgdHJhY2VPdXQubWVhbmxpbmUgPSB7dmlzaWJsZTogZmFsc2V9O1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vYm94L2RlZmF1bHRzXCI6ODgzLFwiLi9hdHRyaWJ1dGVzXCI6MTIzOH1dLDEyNDI6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG5cbi8vIE1heWJlIGFkZCBrZXJuZWxzIG1vcmUgZG93biB0aGUgcm9hZCxcbi8vIGJ1dCBub3RlIHRoYXQgdGhlIGRlZmF1bHQgYHNwYW5tb2RlOiAnc29mdCdgIGJvdW5kcyBtaWdodCBoYXZlXG4vLyB0byBiZWNvbWUga2VybmVsLWRlcGVuZGVudFxudmFyIGtlcm5lbHMgPSB7XG4gICAgZ2F1c3NpYW46IGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgcmV0dXJuICgxIC8gTWF0aC5zcXJ0KDIgKiBNYXRoLlBJKSkgKiBNYXRoLmV4cCgtMC41ICogdiAqIHYpO1xuICAgIH1cbn07XG5cbmV4cG9ydHMubWFrZUtERSA9IGZ1bmN0aW9uKGNhbGNJdGVtLCB0cmFjZSwgdmFscykge1xuICAgIHZhciBsZW4gPSB2YWxzLmxlbmd0aDtcbiAgICB2YXIga2VybmVsID0ga2VybmVscy5nYXVzc2lhbjtcbiAgICB2YXIgYmFuZHdpZHRoID0gY2FsY0l0ZW0uYmFuZHdpZHRoO1xuICAgIHZhciBmYWN0b3IgPSAxIC8gKGxlbiAqIGJhbmR3aWR0aCk7XG5cbiAgICAvLyBkb24ndCB1c2UgTGliLmFnZ051bXMgdG8gc2tpcCBpc051bWVyaWMgY2hlY2tzXG4gICAgcmV0dXJuIGZ1bmN0aW9uKHgpIHtcbiAgICAgICAgdmFyIHN1bSA9IDA7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgc3VtICs9IGtlcm5lbCgoeCAtIHZhbHNbaV0pIC8gYmFuZHdpZHRoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFjdG9yICogc3VtO1xuICAgIH07XG59O1xuXG5leHBvcnRzLmdldFBvc2l0aW9uT25LZGVQYXRoID0gZnVuY3Rpb24oY2FsY0l0ZW0sIHRyYWNlLCB2YWx1ZVB4KSB7XG4gICAgdmFyIHBvc0xldHRlciwgdmFsTGV0dGVyO1xuXG4gICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICBwb3NMZXR0ZXIgPSAneSc7XG4gICAgICAgIHZhbExldHRlciA9ICd4JztcbiAgICB9IGVsc2Uge1xuICAgICAgICBwb3NMZXR0ZXIgPSAneCc7XG4gICAgICAgIHZhbExldHRlciA9ICd5JztcbiAgICB9XG5cbiAgICB2YXIgcG9pbnRPblBhdGggPSBMaWIuZmluZFBvaW50T25QYXRoKFxuICAgICAgICBjYWxjSXRlbS5wYXRoLFxuICAgICAgICB2YWx1ZVB4LFxuICAgICAgICB2YWxMZXR0ZXIsXG4gICAgICAgIHtwYXRoTGVuZ3RoOiBjYWxjSXRlbS5wYXRoTGVuZ3RofVxuICAgICk7XG5cbiAgICB2YXIgcG9zQ2VudGVyUHggPSBjYWxjSXRlbS5wb3NDZW50ZXJQeDtcbiAgICB2YXIgcG9zT25QYXRoMCA9IHBvaW50T25QYXRoW3Bvc0xldHRlcl07XG4gICAgdmFyIHBvc09uUGF0aDEgPSB0cmFjZS5zaWRlID09PSAnYm90aCcgP1xuICAgICAgICAyICogcG9zQ2VudGVyUHggLSBwb3NPblBhdGgwIDpcbiAgICAgICAgcG9zQ2VudGVyUHg7XG5cbiAgICByZXR1cm4gW3Bvc09uUGF0aDAsIHBvc09uUGF0aDFdO1xufTtcblxuZXhwb3J0cy5nZXRLZGVWYWx1ZSA9IGZ1bmN0aW9uKGNhbGNJdGVtLCB0cmFjZSwgdmFsdWVEaXN0KSB7XG4gICAgdmFyIHZhbHMgPSBjYWxjSXRlbS5wdHMubWFwKGV4cG9ydHMuZXh0cmFjdFZhbCk7XG4gICAgdmFyIGtkZSA9IGV4cG9ydHMubWFrZUtERShjYWxjSXRlbSwgdHJhY2UsIHZhbHMpO1xuICAgIHJldHVybiBrZGUodmFsdWVEaXN0KSAvIGNhbGNJdGVtLnBvc0RlbnNpdHlTY2FsZTtcbn07XG5cbmV4cG9ydHMuZXh0cmFjdFZhbCA9IGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8udjsgfTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTl9XSwxMjQzOltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIGJveEhvdmVyUG9pbnRzID0gX2RlcmVxXygnLi4vYm94L2hvdmVyJyk7XG52YXIgaGVscGVycyA9IF9kZXJlcV8oJy4vaGVscGVycycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGhvdmVyUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlLCBob3ZlckxheWVyKSB7XG4gICAgdmFyIGNkID0gcG9pbnREYXRhLmNkO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciBob3Zlcm9uID0gdHJhY2UuaG92ZXJvbjtcbiAgICB2YXIgaGFzSG92ZXJvblZpb2xpbnMgPSBob3Zlcm9uLmluZGV4T2YoJ3Zpb2xpbnMnKSAhPT0gLTE7XG4gICAgdmFyIGhhc0hvdmVyb25LREUgPSBob3Zlcm9uLmluZGV4T2YoJ2tkZScpICE9PSAtMTtcbiAgICB2YXIgY2xvc2VEYXRhID0gW107XG4gICAgdmFyIGNsb3NlUHREYXRhO1xuICAgIHZhciB2aW9saW5MaW5lQXR0cnM7XG5cbiAgICBpZihoYXNIb3Zlcm9uVmlvbGlucyB8fCBoYXNIb3Zlcm9uS0RFKSB7XG4gICAgICAgIHZhciBjbG9zZUJveERhdGEgPSBib3hIb3ZlclBvaW50cy5ob3Zlck9uQm94ZXMocG9pbnREYXRhLCB4dmFsLCB5dmFsLCBob3Zlcm1vZGUpO1xuXG4gICAgICAgIGlmKGhhc0hvdmVyb25LREUgJiYgY2xvc2VCb3hEYXRhLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHZhciB4YSA9IHBvaW50RGF0YS54YTtcbiAgICAgICAgICAgIHZhciB5YSA9IHBvaW50RGF0YS55YTtcbiAgICAgICAgICAgIHZhciBwTGV0dGVyLCB2TGV0dGVyLCBwQXhpcywgdkF4aXMsIHZWYWw7XG5cbiAgICAgICAgICAgIGlmKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpIHtcbiAgICAgICAgICAgICAgICB2VmFsID0geHZhbDtcbiAgICAgICAgICAgICAgICBwTGV0dGVyID0gJ3knO1xuICAgICAgICAgICAgICAgIHBBeGlzID0geWE7XG4gICAgICAgICAgICAgICAgdkxldHRlciA9ICd4JztcbiAgICAgICAgICAgICAgICB2QXhpcyA9IHhhO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2VmFsID0geXZhbDtcbiAgICAgICAgICAgICAgICBwTGV0dGVyID0gJ3gnO1xuICAgICAgICAgICAgICAgIHBBeGlzID0geGE7XG4gICAgICAgICAgICAgICAgdkxldHRlciA9ICd5JztcbiAgICAgICAgICAgICAgICB2QXhpcyA9IHlhO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZGkgPSBjZFtwb2ludERhdGEuaW5kZXhdO1xuXG4gICAgICAgICAgICBpZih2VmFsID49IGRpLnNwYW5bMF0gJiYgdlZhbCA8PSBkaS5zcGFuWzFdKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtkZVBvaW50RGF0YSA9IExpYi5leHRlbmRGbGF0KHt9LCBwb2ludERhdGEpO1xuICAgICAgICAgICAgICAgIHZhciB2VmFsUHggPSB2QXhpcy5jMnAodlZhbCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgdmFyIGtkZVZhbCA9IGhlbHBlcnMuZ2V0S2RlVmFsdWUoZGksIHRyYWNlLCB2VmFsKTtcbiAgICAgICAgICAgICAgICB2YXIgcE9uUGF0aCA9IGhlbHBlcnMuZ2V0UG9zaXRpb25PbktkZVBhdGgoZGksIHRyYWNlLCB2VmFsUHgpO1xuICAgICAgICAgICAgICAgIHZhciBwYU9mZnNldCA9IHBBeGlzLl9vZmZzZXQ7XG4gICAgICAgICAgICAgICAgdmFyIHBhTGVuZ3RoID0gcEF4aXMuX2xlbmd0aDtcblxuICAgICAgICAgICAgICAgIGtkZVBvaW50RGF0YVtwTGV0dGVyICsgJzAnXSA9IHBPblBhdGhbMF07XG4gICAgICAgICAgICAgICAga2RlUG9pbnREYXRhW3BMZXR0ZXIgKyAnMSddID0gcE9uUGF0aFsxXTtcbiAgICAgICAgICAgICAgICBrZGVQb2ludERhdGFbdkxldHRlciArICcwJ10gPSBrZGVQb2ludERhdGFbdkxldHRlciArICcxJ10gPSB2VmFsUHg7XG4gICAgICAgICAgICAgICAga2RlUG9pbnREYXRhW3ZMZXR0ZXIgKyAnTGFiZWwnXSA9IHZMZXR0ZXIgKyAnOiAnICsgQXhlcy5ob3ZlckxhYmVsVGV4dCh2QXhpcywgdlZhbCkgKyAnLCAnICsgY2RbMF0udC5sYWJlbHMua2RlICsgJyAnICsga2RlVmFsLnRvRml4ZWQoMyk7XG5cbiAgICAgICAgICAgICAgICAvLyBtb3ZlIHRoZSBzcGlrZSB0byB0aGUgS0RFIHBvaW50XG4gICAgICAgICAgICAgICAga2RlUG9pbnREYXRhLnNwaWtlRGlzdGFuY2UgPSBjbG9zZUJveERhdGFbMF0uc3Bpa2VEaXN0YW5jZTtcbiAgICAgICAgICAgICAgICB2YXIgc3Bpa2VQb3NBdHRyID0gcExldHRlciArICdTcGlrZSc7XG4gICAgICAgICAgICAgICAga2RlUG9pbnREYXRhW3NwaWtlUG9zQXR0cl0gPSBjbG9zZUJveERhdGFbMF1bc3Bpa2VQb3NBdHRyXTtcbiAgICAgICAgICAgICAgICBjbG9zZUJveERhdGFbMF0uc3Bpa2VEaXN0YW5jZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBjbG9zZUJveERhdGFbMF1bc3Bpa2VQb3NBdHRyXSA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIG5vIGhvdmVydGVtcGxhdGUgc3VwcG9ydCB5ZXRcbiAgICAgICAgICAgICAgICBrZGVQb2ludERhdGEuaG92ZXJ0ZW1wbGF0ZSA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgY2xvc2VEYXRhLnB1c2goa2RlUG9pbnREYXRhKTtcblxuICAgICAgICAgICAgICAgIHZpb2xpbkxpbmVBdHRycyA9IHtzdHJva2U6IHBvaW50RGF0YS5jb2xvcn07XG4gICAgICAgICAgICAgICAgdmlvbGluTGluZUF0dHJzW3BMZXR0ZXIgKyAnMSddID0gTGliLmNvbnN0cmFpbihwYU9mZnNldCArIHBPblBhdGhbMF0sIHBhT2Zmc2V0LCBwYU9mZnNldCArIHBhTGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB2aW9saW5MaW5lQXR0cnNbcExldHRlciArICcyJ10gPSBMaWIuY29uc3RyYWluKHBhT2Zmc2V0ICsgcE9uUGF0aFsxXSwgcGFPZmZzZXQsIHBhT2Zmc2V0ICsgcGFMZW5ndGgpO1xuICAgICAgICAgICAgICAgIHZpb2xpbkxpbmVBdHRyc1t2TGV0dGVyICsgJzEnXSA9IHZpb2xpbkxpbmVBdHRyc1t2TGV0dGVyICsgJzInXSA9IHZBeGlzLl9vZmZzZXQgKyB2VmFsUHg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihoYXNIb3Zlcm9uVmlvbGlucykge1xuICAgICAgICAgICAgY2xvc2VEYXRhID0gY2xvc2VEYXRhLmNvbmNhdChjbG9zZUJveERhdGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoaG92ZXJvbi5pbmRleE9mKCdwb2ludHMnKSAhPT0gLTEpIHtcbiAgICAgICAgY2xvc2VQdERhdGEgPSBib3hIb3ZlclBvaW50cy5ob3Zlck9uUG9pbnRzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCk7XG4gICAgfVxuXG4gICAgLy8gdXBkYXRlIHZpb2xpbiBsaW5lIChpZiBhbnkpXG4gICAgdmFyIHZpb2xpbkxpbmUgPSBob3ZlckxheWVyLnNlbGVjdEFsbCgnLnZpb2xpbmxpbmUtJyArIHRyYWNlLnVpZClcbiAgICAgICAgLmRhdGEodmlvbGluTGluZUF0dHJzID8gWzBdIDogW10pO1xuICAgIHZpb2xpbkxpbmUuZW50ZXIoKS5hcHBlbmQoJ2xpbmUnKVxuICAgICAgICAuY2xhc3NlZCgndmlvbGlubGluZS0nICsgdHJhY2UudWlkLCB0cnVlKVxuICAgICAgICAuYXR0cignc3Ryb2tlLXdpZHRoJywgMS41KTtcbiAgICB2aW9saW5MaW5lLmV4aXQoKS5yZW1vdmUoKTtcbiAgICB2aW9saW5MaW5lLmF0dHIodmlvbGluTGluZUF0dHJzKTtcblxuICAgIC8vIHNhbWUgY29tYmluZSBsb2dpYyBhcyBib3ggaG92ZXJQb2ludHNcbiAgICBpZihob3Zlcm1vZGUgPT09ICdjbG9zZXN0Jykge1xuICAgICAgICBpZihjbG9zZVB0RGF0YSkgcmV0dXJuIFtjbG9zZVB0RGF0YV07XG4gICAgICAgIHJldHVybiBjbG9zZURhdGE7XG4gICAgfVxuICAgIGlmKGNsb3NlUHREYXRhKSB7XG4gICAgICAgIGNsb3NlRGF0YS5wdXNoKGNsb3NlUHREYXRhKTtcbiAgICAgICAgcmV0dXJuIGNsb3NlRGF0YTtcbiAgICB9XG4gICAgcmV0dXJuIGNsb3NlRGF0YTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuLi9ib3gvaG92ZXJcIjo4ODUsXCIuL2hlbHBlcnNcIjoxMjQyfV0sMTI0NDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIGxheW91dEF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLFxuICAgIGNyb3NzVHJhY2VEZWZhdWx0czogX2RlcmVxXygnLi4vYm94L2RlZmF1bHRzJykuY3Jvc3NUcmFjZURlZmF1bHRzLFxuICAgIHN1cHBseUxheW91dERlZmF1bHRzOiBfZGVyZXFfKCcuL2xheW91dF9kZWZhdWx0cycpLFxuICAgIGNhbGM6IF9kZXJlcV8oJy4vY2FsYycpLFxuICAgIGNyb3NzVHJhY2VDYWxjOiBfZGVyZXFfKCcuL2Nyb3NzX3RyYWNlX2NhbGMnKSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL3Bsb3QnKSxcbiAgICBzdHlsZTogX2RlcmVxXygnLi9zdHlsZScpLFxuICAgIHN0eWxlT25TZWxlY3Q6IF9kZXJlcV8oJy4uL3NjYXR0ZXIvc3R5bGUnKS5zdHlsZU9uU2VsZWN0LFxuICAgIGhvdmVyUG9pbnRzOiBfZGVyZXFfKCcuL2hvdmVyJyksXG4gICAgc2VsZWN0UG9pbnRzOiBfZGVyZXFfKCcuLi9ib3gvc2VsZWN0JyksXG5cbiAgICBtb2R1bGVUeXBlOiAndHJhY2UnLFxuICAgIG5hbWU6ICd2aW9saW4nLFxuICAgIGJhc2VQbG90TW9kdWxlOiBfZGVyZXFfKCcuLi8uLi9wbG90cy9jYXJ0ZXNpYW4nKSxcbiAgICBjYXRlZ29yaWVzOiBbJ2NhcnRlc2lhbicsICdzdmcnLCAnc3ltYm9scycsICdvcmllbnRlZCcsICdib3gtdmlvbGluJywgJ3Nob3dMZWdlbmQnLCAndmlvbGluTGF5b3V0JywgJ3pvb21TY2FsZSddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW5cIjo3NzgsXCIuLi9ib3gvZGVmYXVsdHNcIjo4ODMsXCIuLi9ib3gvc2VsZWN0XCI6ODkwLFwiLi4vc2NhdHRlci9zdHlsZVwiOjExMzQsXCIuL2F0dHJpYnV0ZXNcIjoxMjM4LFwiLi9jYWxjXCI6MTIzOSxcIi4vY3Jvc3NfdHJhY2VfY2FsY1wiOjEyNDAsXCIuL2RlZmF1bHRzXCI6MTI0MSxcIi4vaG92ZXJcIjoxMjQzLFwiLi9sYXlvdXRfYXR0cmlidXRlc1wiOjEyNDUsXCIuL2xheW91dF9kZWZhdWx0c1wiOjEyNDYsXCIuL3Bsb3RcIjoxMjQ3LFwiLi9zdHlsZVwiOjEyNDh9XSwxMjQ1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGJveExheW91dEF0dHJzID0gX2RlcmVxXygnLi4vYm94L2xheW91dF9hdHRyaWJ1dGVzJyk7XG52YXIgZXh0ZW5kRmxhdCA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLmV4dGVuZEZsYXQ7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHZpb2xpbm1vZGU6IGV4dGVuZEZsYXQoe30sIGJveExheW91dEF0dHJzLmJveG1vZGUsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgdmlvbGluZ2FwOiBleHRlbmRGbGF0KHt9LCBib3hMYXlvdXRBdHRycy5ib3hnYXAsIHtcbiAgICAgICAgXG4gICAgfSksXG4gICAgdmlvbGluZ3JvdXBnYXA6IGV4dGVuZEZsYXQoe30sIGJveExheW91dEF0dHJzLmJveGdyb3VwZ2FwLCB7XG4gICAgICAgIFxuICAgIH0pXG59O1xuXG59LHtcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2JveC9sYXlvdXRfYXR0cmlidXRlc1wiOjg4N31dLDEyNDY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgbGF5b3V0QXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKTtcbnZhciBib3hMYXlvdXREZWZhdWx0cyA9IF9kZXJlcV8oJy4uL2JveC9sYXlvdXRfZGVmYXVsdHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlMYXlvdXREZWZhdWx0cyhsYXlvdXRJbiwgbGF5b3V0T3V0LCBmdWxsRGF0YSkge1xuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKGxheW91dEluLCBsYXlvdXRPdXQsIGxheW91dEF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cbiAgICBib3hMYXlvdXREZWZhdWx0cy5fc3VwcGx5KGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhLCBjb2VyY2UsICd2aW9saW4nKTtcbn07XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vYm94L2xheW91dF9kZWZhdWx0c1wiOjg4OCxcIi4vbGF5b3V0X2F0dHJpYnV0ZXNcIjoxMjQ1fV0sMTI0NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBkMyA9IF9kZXJlcV8oJ2QzJyk7XG52YXIgTGliID0gX2RlcmVxXygnLi4vLi4vbGliJyk7XG52YXIgRHJhd2luZyA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvZHJhd2luZycpO1xuXG52YXIgYm94UGxvdCA9IF9kZXJlcV8oJy4uL2JveC9wbG90Jyk7XG52YXIgbGluZVBvaW50cyA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvbGluZV9wb2ludHMnKTtcbnZhciBoZWxwZXJzID0gX2RlcmVxXygnLi9oZWxwZXJzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGxvdChnZCwgcGxvdGluZm8sIGNkVmlvbGlucywgdmlvbGluTGF5ZXIpIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciB4YSA9IHBsb3RpbmZvLnhheGlzO1xuICAgIHZhciB5YSA9IHBsb3RpbmZvLnlheGlzO1xuXG4gICAgZnVuY3Rpb24gbWFrZVBhdGgocHRzKSB7XG4gICAgICAgIHZhciBzZWdtZW50cyA9IGxpbmVQb2ludHMocHRzLCB7XG4gICAgICAgICAgICB4YXhpczogeGEsXG4gICAgICAgICAgICB5YXhpczogeWEsXG4gICAgICAgICAgICBjb25uZWN0R2FwczogdHJ1ZSxcbiAgICAgICAgICAgIGJhc2VUb2xlcmFuY2U6IDAuNzUsXG4gICAgICAgICAgICBzaGFwZTogJ3NwbGluZScsXG4gICAgICAgICAgICBzaW1wbGlmeTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIERyYXdpbmcuc21vb3Rob3BlbihzZWdtZW50c1swXSwgMSk7XG4gICAgfVxuXG4gICAgTGliLm1ha2VUcmFjZUdyb3Vwcyh2aW9saW5MYXllciwgY2RWaW9saW5zLCAndHJhY2UgdmlvbGlucycpLmVhY2goZnVuY3Rpb24oY2QpIHtcbiAgICAgICAgdmFyIHBsb3RHcm91cCA9IGQzLnNlbGVjdCh0aGlzKTtcbiAgICAgICAgdmFyIGNkMCA9IGNkWzBdO1xuICAgICAgICB2YXIgdCA9IGNkMC50O1xuICAgICAgICB2YXIgdHJhY2UgPSBjZDAudHJhY2U7XG5cbiAgICAgICAgaWYodHJhY2UudmlzaWJsZSAhPT0gdHJ1ZSB8fCB0LmVtcHR5KSB7XG4gICAgICAgICAgICBwbG90R3JvdXAucmVtb3ZlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYlBvcyA9IHQuYlBvcztcbiAgICAgICAgdmFyIGJkUG9zID0gdC5iZFBvcztcbiAgICAgICAgdmFyIHZhbEF4aXMgPSBwbG90aW5mb1t0LnZhbExldHRlciArICdheGlzJ107XG4gICAgICAgIHZhciBwb3NBeGlzID0gcGxvdGluZm9bdC5wb3NMZXR0ZXIgKyAnYXhpcyddO1xuICAgICAgICB2YXIgaGFzQm90aFNpZGVzID0gdHJhY2Uuc2lkZSA9PT0gJ2JvdGgnO1xuICAgICAgICB2YXIgaGFzUG9zaXRpdmVTaWRlID0gaGFzQm90aFNpZGVzIHx8IHRyYWNlLnNpZGUgPT09ICdwb3NpdGl2ZSc7XG4gICAgICAgIHZhciBoYXNOZWdhdGl2ZVNpZGUgPSBoYXNCb3RoU2lkZXMgfHwgdHJhY2Uuc2lkZSA9PT0gJ25lZ2F0aXZlJztcblxuICAgICAgICB2YXIgdmlvbGlucyA9IHBsb3RHcm91cC5zZWxlY3RBbGwoJ3BhdGgudmlvbGluJykuZGF0YShMaWIuaWRlbnRpdHkpO1xuXG4gICAgICAgIHZpb2xpbnMuZW50ZXIoKS5hcHBlbmQoJ3BhdGgnKVxuICAgICAgICAgICAgLnN0eWxlKCd2ZWN0b3ItZWZmZWN0JywgJ25vbi1zY2FsaW5nLXN0cm9rZScpXG4gICAgICAgICAgICAuYXR0cignY2xhc3MnLCAndmlvbGluJyk7XG5cbiAgICAgICAgdmlvbGlucy5leGl0KCkucmVtb3ZlKCk7XG5cbiAgICAgICAgdmlvbGlucy5lYWNoKGZ1bmN0aW9uKGQpIHtcbiAgICAgICAgICAgIHZhciBwYXRoU2VsID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIGRlbnNpdHkgPSBkLmRlbnNpdHk7XG4gICAgICAgICAgICB2YXIgbGVuID0gZGVuc2l0eS5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgcG9zQ2VudGVyID0gZC5wb3MgKyBiUG9zO1xuICAgICAgICAgICAgdmFyIHBvc0NlbnRlclB4ID0gcG9zQXhpcy5jMnAocG9zQ2VudGVyKTtcblxuICAgICAgICAgICAgdmFyIHNjYWxlO1xuICAgICAgICAgICAgaWYodHJhY2Uud2lkdGgpIHtcbiAgICAgICAgICAgICAgICBzY2FsZSA9IHQubWF4S0RFIC8gYmRQb3M7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBncm91cFN0YXRzID0gZnVsbExheW91dC5fdmlvbGluU2NhbGVHcm91cFN0YXRzW3RyYWNlLnNjYWxlZ3JvdXBdO1xuICAgICAgICAgICAgICAgIHNjYWxlID0gdHJhY2Uuc2NhbGVtb2RlID09PSAnY291bnQnID9cbiAgICAgICAgICAgICAgICAgICAgKGdyb3VwU3RhdHMubWF4S0RFIC8gYmRQb3MpICogKGdyb3VwU3RhdHMubWF4Q291bnQgLyBkLnB0cy5sZW5ndGgpIDpcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBTdGF0cy5tYXhLREUgLyBiZFBvcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHBhdGhQb3MsIHBhdGhOZWcsIHBhdGg7XG4gICAgICAgICAgICB2YXIgaSwgaywgcHRzLCBwdDtcblxuICAgICAgICAgICAgaWYoaGFzUG9zaXRpdmVTaWRlKSB7XG4gICAgICAgICAgICAgICAgcHRzID0gbmV3IEFycmF5KGxlbik7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcHQgPSBwdHNbaV0gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgcHRbdC5wb3NMZXR0ZXJdID0gcG9zQ2VudGVyICsgKGRlbnNpdHlbaV0udiAvIHNjYWxlKTtcbiAgICAgICAgICAgICAgICAgICAgcHRbdC52YWxMZXR0ZXJdID0gZGVuc2l0eVtpXS50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXRoUG9zID0gbWFrZVBhdGgocHRzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaGFzTmVnYXRpdmVTaWRlKSB7XG4gICAgICAgICAgICAgICAgcHRzID0gbmV3IEFycmF5KGxlbik7XG4gICAgICAgICAgICAgICAgZm9yKGsgPSAwLCBpID0gbGVuIC0gMTsgayA8IGxlbjsgaysrLCBpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgcHQgPSBwdHNba10gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgcHRbdC5wb3NMZXR0ZXJdID0gcG9zQ2VudGVyIC0gKGRlbnNpdHlbaV0udiAvIHNjYWxlKTtcbiAgICAgICAgICAgICAgICAgICAgcHRbdC52YWxMZXR0ZXJdID0gZGVuc2l0eVtpXS50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwYXRoTmVnID0gbWFrZVBhdGgocHRzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYoaGFzQm90aFNpZGVzKSB7XG4gICAgICAgICAgICAgICAgcGF0aCA9IHBhdGhQb3MgKyAnTCcgKyBwYXRoTmVnLnN1YnN0cigxKSArICdaJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIHN0YXJ0UHQgPSBbcG9zQ2VudGVyUHgsIHZhbEF4aXMuYzJwKGRlbnNpdHlbMF0udCldO1xuICAgICAgICAgICAgICAgIHZhciBlbmRQdCA9IFtwb3NDZW50ZXJQeCwgdmFsQXhpcy5jMnAoZGVuc2l0eVtsZW4gLSAxXS50KV07XG5cbiAgICAgICAgICAgICAgICBpZih0cmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0UHQucmV2ZXJzZSgpO1xuICAgICAgICAgICAgICAgICAgICBlbmRQdC5yZXZlcnNlKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoaGFzUG9zaXRpdmVTaWRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGggPSAnTScgKyBzdGFydFB0ICsgJ0wnICsgcGF0aFBvcy5zdWJzdHIoMSkgKyAnTCcgKyBlbmRQdDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwYXRoID0gJ00nICsgZW5kUHQgKyAnTCcgKyBwYXRoTmVnLnN1YnN0cigxKSArICdMJyArIHN0YXJ0UHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGF0aFNlbC5hdHRyKCdkJywgcGF0aCk7XG5cbiAgICAgICAgICAgIC8vIHNhdmUgYSBmZXcgdGhpbmdzIHVzZWQgaW4gZ2V0UG9zaXRpb25PbktkZVBhdGgsIGdldEtkZVZhbHVlXG4gICAgICAgICAgICAvLyBvbiBob3ZlciBhbmQgZm9yIG1lYW5saW5lIGRyYXcgYmxvY2sgYmVsb3dcbiAgICAgICAgICAgIGQucG9zQ2VudGVyUHggPSBwb3NDZW50ZXJQeDtcbiAgICAgICAgICAgIGQucG9zRGVuc2l0eVNjYWxlID0gc2NhbGUgKiBiZFBvcztcbiAgICAgICAgICAgIGQucGF0aCA9IHBhdGhTZWwubm9kZSgpO1xuICAgICAgICAgICAgZC5wYXRoTGVuZ3RoID0gZC5wYXRoLmdldFRvdGFsTGVuZ3RoKCkgLyAoaGFzQm90aFNpZGVzID8gMiA6IDEpO1xuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgYm94QXR0cnMgPSB0cmFjZS5ib3g7XG4gICAgICAgIHZhciBib3hXaWR0aCA9IGJveEF0dHJzLndpZHRoO1xuICAgICAgICB2YXIgYm94TGluZVdpZHRoID0gKGJveEF0dHJzLmxpbmUgfHwge30pLndpZHRoO1xuICAgICAgICB2YXIgYmRQb3NTY2FsZWQ7XG4gICAgICAgIHZhciBiUG9zUHhPZmZzZXQ7XG5cbiAgICAgICAgaWYoaGFzQm90aFNpZGVzKSB7XG4gICAgICAgICAgICBiZFBvc1NjYWxlZCA9IGJkUG9zICogYm94V2lkdGg7XG4gICAgICAgICAgICBiUG9zUHhPZmZzZXQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYoaGFzUG9zaXRpdmVTaWRlKSB7XG4gICAgICAgICAgICBiZFBvc1NjYWxlZCA9IFswLCBiZFBvcyAqIGJveFdpZHRoIC8gMl07XG4gICAgICAgICAgICBiUG9zUHhPZmZzZXQgPSAtYm94TGluZVdpZHRoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYmRQb3NTY2FsZWQgPSBbYmRQb3MgKiBib3hXaWR0aCAvIDIsIDBdO1xuICAgICAgICAgICAgYlBvc1B4T2Zmc2V0ID0gYm94TGluZVdpZHRoO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaW5uZXIgYm94XG4gICAgICAgIGJveFBsb3QucGxvdEJveEFuZFdoaXNrZXJzKHBsb3RHcm91cCwge3BvczogcG9zQXhpcywgdmFsOiB2YWxBeGlzfSwgdHJhY2UsIHtcbiAgICAgICAgICAgIGJQb3M6IGJQb3MsXG4gICAgICAgICAgICBiZFBvczogYmRQb3NTY2FsZWQsXG4gICAgICAgICAgICBiUG9zUHhPZmZzZXQ6IGJQb3NQeE9mZnNldFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBtZWFubGluZSBpbnNpZGVyIGJveFxuICAgICAgICBib3hQbG90LnBsb3RCb3hNZWFuKHBsb3RHcm91cCwge3BvczogcG9zQXhpcywgdmFsOiB2YWxBeGlzfSwgdHJhY2UsIHtcbiAgICAgICAgICAgIGJQb3M6IGJQb3MsXG4gICAgICAgICAgICBiZFBvczogYmRQb3NTY2FsZWQsXG4gICAgICAgICAgICBiUG9zUHhPZmZzZXQ6IGJQb3NQeE9mZnNldFxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgZm47XG4gICAgICAgIGlmKCF0cmFjZS5ib3gudmlzaWJsZSAmJiB0cmFjZS5tZWFubGluZS52aXNpYmxlKSB7XG4gICAgICAgICAgICBmbiA9IExpYi5pZGVudGl0eTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE4uQi4gdXNlIGRpZmZlcmVudCBjbGFzcyBuYW1lIHRoYW4gYm94UGxvdC5wbG90Qm94TWVhbixcbiAgICAgICAgLy8gdG8gYXZvaWQgc2VsZWN0QWxsIGNvbmZsaWN0XG4gICAgICAgIHZhciBtZWFuUGF0aHMgPSBwbG90R3JvdXAuc2VsZWN0QWxsKCdwYXRoLm1lYW5saW5lJykuZGF0YShmbiB8fCBbXSk7XG4gICAgICAgIG1lYW5QYXRocy5lbnRlcigpLmFwcGVuZCgncGF0aCcpXG4gICAgICAgICAgICAuYXR0cignY2xhc3MnLCAnbWVhbmxpbmUnKVxuICAgICAgICAgICAgLnN0eWxlKCdmaWxsJywgJ25vbmUnKVxuICAgICAgICAgICAgLnN0eWxlKCd2ZWN0b3ItZWZmZWN0JywgJ25vbi1zY2FsaW5nLXN0cm9rZScpO1xuICAgICAgICBtZWFuUGF0aHMuZXhpdCgpLnJlbW92ZSgpO1xuICAgICAgICBtZWFuUGF0aHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgICAgICB2YXIgdiA9IHZhbEF4aXMuYzJwKGQubWVhbiwgdHJ1ZSk7XG4gICAgICAgICAgICB2YXIgcCA9IGhlbHBlcnMuZ2V0UG9zaXRpb25PbktkZVBhdGgoZCwgdHJhY2UsIHYpO1xuXG4gICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuYXR0cignZCcsXG4gICAgICAgICAgICAgICAgdHJhY2Uub3JpZW50YXRpb24gPT09ICdoJyA/XG4gICAgICAgICAgICAgICAgICAgICdNJyArIHYgKyAnLCcgKyBwWzBdICsgJ1YnICsgcFsxXSA6XG4gICAgICAgICAgICAgICAgICAgICdNJyArIHBbMF0gKyAnLCcgKyB2ICsgJ0gnICsgcFsxXVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYm94UGxvdC5wbG90UG9pbnRzKHBsb3RHcm91cCwge3g6IHhhLCB5OiB5YX0sIHRyYWNlLCB0KTtcbiAgICB9KTtcbn07XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vbGliXCI6NzE5LFwiLi4vYm94L3Bsb3RcIjo4ODksXCIuLi9zY2F0dGVyL2xpbmVfcG9pbnRzXCI6MTEyNSxcIi4vaGVscGVyc1wiOjEyNDIsXCJkM1wiOjE2M31dLDEyNDg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIHN0eWxlUG9pbnRzID0gX2RlcmVxXygnLi4vc2NhdHRlci9zdHlsZScpLnN0eWxlUG9pbnRzO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN0eWxlKGdkKSB7XG4gICAgdmFyIHMgPSBkMy5zZWxlY3QoZ2QpLnNlbGVjdEFsbCgnZy50cmFjZS52aW9saW5zJyk7XG5cbiAgICBzLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oZCkgeyByZXR1cm4gZFswXS50cmFjZS5vcGFjaXR5OyB9KTtcblxuICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGRbMF0udHJhY2U7XG4gICAgICAgIHZhciBzZWwgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciBib3ggPSB0cmFjZS5ib3ggfHwge307XG4gICAgICAgIHZhciBib3hMaW5lID0gYm94LmxpbmUgfHwge307XG4gICAgICAgIHZhciBtZWFubGluZSA9IHRyYWNlLm1lYW5saW5lIHx8IHt9O1xuICAgICAgICB2YXIgbWVhbkxpbmVXaWR0aCA9IG1lYW5saW5lLndpZHRoO1xuXG4gICAgICAgIHNlbC5zZWxlY3RBbGwoJ3BhdGgudmlvbGluJylcbiAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgdHJhY2UubGluZS53aWR0aCArICdweCcpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIHRyYWNlLmxpbmUuY29sb3IpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCB0cmFjZS5maWxsY29sb3IpO1xuXG4gICAgICAgIHNlbC5zZWxlY3RBbGwoJ3BhdGguYm94JylcbiAgICAgICAgICAgIC5zdHlsZSgnc3Ryb2tlLXdpZHRoJywgYm94TGluZS53aWR0aCArICdweCcpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIGJveExpbmUuY29sb3IpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBib3guZmlsbGNvbG9yKTtcblxuICAgICAgICB2YXIgbWVhbkxpbmVTdHlsZSA9IHtcbiAgICAgICAgICAgICdzdHJva2Utd2lkdGgnOiBtZWFuTGluZVdpZHRoICsgJ3B4JyxcbiAgICAgICAgICAgICdzdHJva2UtZGFzaGFycmF5JzogKDIgKiBtZWFuTGluZVdpZHRoKSArICdweCwnICsgbWVhbkxpbmVXaWR0aCArICdweCdcbiAgICAgICAgfTtcblxuICAgICAgICBzZWwuc2VsZWN0QWxsKCdwYXRoLm1lYW4nKVxuICAgICAgICAgICAgLnN0eWxlKG1lYW5MaW5lU3R5bGUpXG4gICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIG1lYW5saW5lLmNvbG9yKTtcblxuICAgICAgICBzZWwuc2VsZWN0QWxsKCdwYXRoLm1lYW5saW5lJylcbiAgICAgICAgICAgIC5zdHlsZShtZWFuTGluZVN0eWxlKVxuICAgICAgICAgICAgLmNhbGwoQ29sb3Iuc3Ryb2tlLCBtZWFubGluZS5jb2xvcik7XG5cbiAgICAgICAgc3R5bGVQb2ludHMoc2VsLCB0cmFjZSwgZ2QpO1xuICAgIH0pO1xufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vc2NhdHRlci9zdHlsZVwiOjExMzQsXCJkM1wiOjE2M31dLDEyNDk6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgY29sb3JTY2FsZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXMnKTtcbnZhciBpc29zdXJmYWNlQXR0cnMgPSBfZGVyZXFfKCcuLi9pc29zdXJmYWNlL2F0dHJpYnV0ZXMnKTtcbnZhciBiYXNlQXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG5cbnZhciBleHRlbmRGbGF0ID0gX2RlcmVxXygnLi4vLi4vbGliL2V4dGVuZCcpLmV4dGVuZEZsYXQ7XG52YXIgb3ZlcnJpZGVBbGwgPSBfZGVyZXFfKCcuLi8uLi9wbG90X2FwaS9lZGl0X3R5cGVzJykub3ZlcnJpZGVBbGw7XG5cbnZhciBhdHRycyA9IG1vZHVsZS5leHBvcnRzID0gb3ZlcnJpZGVBbGwoZXh0ZW5kRmxhdCh7XG4gICAgeDogaXNvc3VyZmFjZUF0dHJzLngsXG4gICAgeTogaXNvc3VyZmFjZUF0dHJzLnksXG4gICAgejogaXNvc3VyZmFjZUF0dHJzLnosXG4gICAgdmFsdWU6IGlzb3N1cmZhY2VBdHRycy52YWx1ZSxcbiAgICBpc29taW46IGlzb3N1cmZhY2VBdHRycy5pc29taW4sXG4gICAgaXNvbWF4OiBpc29zdXJmYWNlQXR0cnMuaXNvbWF4LFxuICAgIHN1cmZhY2U6IGlzb3N1cmZhY2VBdHRycy5zdXJmYWNlLFxuICAgIHNwYWNlZnJhbWU6IHtcbiAgICAgICAgc2hvdzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBkZmx0OiBmYWxzZSxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICBmaWxsOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxLFxuICAgICAgICAgICAgZGZsdDogMSxcbiAgICAgICAgICAgIFxuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNsaWNlczogaXNvc3VyZmFjZUF0dHJzLnNsaWNlcyxcbiAgICBjYXBzOiBpc29zdXJmYWNlQXR0cnMuY2FwcyxcbiAgICB0ZXh0OiBpc29zdXJmYWNlQXR0cnMudGV4dCxcbiAgICBob3ZlcnRleHQ6IGlzb3N1cmZhY2VBdHRycy5ob3ZlcnRleHQsXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaXNvc3VyZmFjZUF0dHJzLmhvdmVydGVtcGxhdGVcbn0sXG5cbmNvbG9yU2NhbGVBdHRycygnJywge1xuICAgIGNvbG9yQXR0cjogJ2B2YWx1ZWAnLFxuICAgIHNob3dTY2FsZURmbHQ6IHRydWUsXG4gICAgZWRpdFR5cGVPdmVycmlkZTogJ2NhbGMnXG59KSwge1xuXG4gICAgY29sb3JiYXI6IGlzb3N1cmZhY2VBdHRycy5jb2xvcmJhcixcbiAgICBvcGFjaXR5OiBpc29zdXJmYWNlQXR0cnMub3BhY2l0eSxcbiAgICBvcGFjaXR5c2NhbGU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuXG4gICAgbGlnaHRwb3NpdGlvbjogaXNvc3VyZmFjZUF0dHJzLmxpZ2h0cG9zaXRpb24sXG4gICAgbGlnaHRpbmc6IGlzb3N1cmZhY2VBdHRycy5saWdodGluZyxcbiAgICBmbGF0c2hhZGluZzogaXNvc3VyZmFjZUF0dHJzLmZsYXRzaGFkaW5nLFxuICAgIGNvbnRvdXI6IGlzb3N1cmZhY2VBdHRycy5jb250b3VyLFxuXG4gICAgaG92ZXJpbmZvOiBleHRlbmRGbGF0KHt9LCBiYXNlQXR0cnMuaG92ZXJpbmZvKVxufSksICdjYWxjJywgJ25lc3RlZCcpO1xuXG5hdHRycy54LmVkaXRUeXBlID0gYXR0cnMueS5lZGl0VHlwZSA9IGF0dHJzLnouZWRpdFR5cGUgPSBhdHRycy52YWx1ZS5lZGl0VHlwZSA9ICdjYWxjK2NsZWFyQXhpc1R5cGVzJztcbmF0dHJzLnRyYW5zZm9ybXMgPSB1bmRlZmluZWQ7XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlL2F0dHJpYnV0ZXNcIjo2MDAsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdF9hcGkvZWRpdF90eXBlc1wiOjc1MCxcIi4uLy4uL3Bsb3RzL2F0dHJpYnV0ZXNcIjo3NjQsXCIuLi9pc29zdXJmYWNlL2F0dHJpYnV0ZXNcIjoxMDQ4fV0sMTI1MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVNZXNoID0gX2RlcmVxXygnZ2wtbWVzaDNkJyk7XG5cbnZhciBwYXJzZUNvbG9yU2NhbGUgPSBfZGVyZXFfKCcuLi8uLi9saWIvZ2xfZm9ybWF0X2NvbG9yJykucGFyc2VDb2xvclNjYWxlO1xudmFyIHN0cjJSZ2JhQXJyYXkgPSBfZGVyZXFfKCcuLi8uLi9saWIvc3RyMnJnYmFycmF5Jyk7XG52YXIgZXh0cmFjdE9wdHMgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2NvbG9yc2NhbGUnKS5leHRyYWN0T3B0cztcbnZhciB6aXAzID0gX2RlcmVxXygnLi4vLi4vcGxvdHMvZ2wzZC96aXAzJyk7XG5cbnZhciBmaW5kTmVhcmVzdE9uQXhpcyA9IF9kZXJlcV8oJy4uL2lzb3N1cmZhY2UvY29udmVydCcpLmZpbmROZWFyZXN0T25BeGlzO1xudmFyIGdlbmVyYXRlSXNvTWVzaGVzID0gX2RlcmVxXygnLi4vaXNvc3VyZmFjZS9jb252ZXJ0JykuZ2VuZXJhdGVJc29NZXNoZXM7XG5cbmZ1bmN0aW9uIFZvbHVtZVRyYWNlKHNjZW5lLCBtZXNoLCB1aWQpIHtcbiAgICB0aGlzLnNjZW5lID0gc2NlbmU7XG4gICAgdGhpcy51aWQgPSB1aWQ7XG4gICAgdGhpcy5tZXNoID0gbWVzaDtcbiAgICB0aGlzLm5hbWUgPSAnJztcbiAgICB0aGlzLmRhdGEgPSBudWxsO1xuICAgIHRoaXMuc2hvd0NvbnRvdXIgPSBmYWxzZTtcbn1cblxudmFyIHByb3RvID0gVm9sdW1lVHJhY2UucHJvdG90eXBlO1xuXG5wcm90by5oYW5kbGVQaWNrID0gZnVuY3Rpb24oc2VsZWN0aW9uKSB7XG4gICAgaWYoc2VsZWN0aW9uLm9iamVjdCA9PT0gdGhpcy5tZXNoKSB7XG4gICAgICAgIHZhciByYXdJZCA9IHNlbGVjdGlvbi5kYXRhLmluZGV4O1xuXG4gICAgICAgIHZhciB4ID0gdGhpcy5kYXRhLl94W3Jhd0lkXTtcbiAgICAgICAgdmFyIHkgPSB0aGlzLmRhdGEuX3lbcmF3SWRdO1xuICAgICAgICB2YXIgeiA9IHRoaXMuZGF0YS5feltyYXdJZF07XG5cbiAgICAgICAgdmFyIGhlaWdodCA9IHRoaXMuZGF0YS5fWXMubGVuZ3RoO1xuICAgICAgICB2YXIgZGVwdGggPSB0aGlzLmRhdGEuX1pzLmxlbmd0aDtcblxuICAgICAgICB2YXIgaSA9IGZpbmROZWFyZXN0T25BeGlzKHgsIHRoaXMuZGF0YS5fWHMpLmlkO1xuICAgICAgICB2YXIgaiA9IGZpbmROZWFyZXN0T25BeGlzKHksIHRoaXMuZGF0YS5fWXMpLmlkO1xuICAgICAgICB2YXIgayA9IGZpbmROZWFyZXN0T25BeGlzKHosIHRoaXMuZGF0YS5fWnMpLmlkO1xuXG4gICAgICAgIHZhciBzZWxlY3RJbmRleCA9IHNlbGVjdGlvbi5pbmRleCA9IGsgKyBkZXB0aCAqIGogKyBkZXB0aCAqIGhlaWdodCAqIGk7XG5cbiAgICAgICAgc2VsZWN0aW9uLnRyYWNlQ29vcmRpbmF0ZSA9IFtcbiAgICAgICAgICAgIHRoaXMuZGF0YS5feFtzZWxlY3RJbmRleF0sXG4gICAgICAgICAgICB0aGlzLmRhdGEuX3lbc2VsZWN0SW5kZXhdLFxuICAgICAgICAgICAgdGhpcy5kYXRhLl96W3NlbGVjdEluZGV4XSxcbiAgICAgICAgICAgIHRoaXMuZGF0YS52YWx1ZVtzZWxlY3RJbmRleF1cbiAgICAgICAgXTtcblxuICAgICAgICB2YXIgdGV4dCA9IHRoaXMuZGF0YS5ob3ZlcnRleHQgfHwgdGhpcy5kYXRhLnRleHQ7XG4gICAgICAgIGlmKEFycmF5LmlzQXJyYXkodGV4dCkgJiYgdGV4dFtzZWxlY3RJbmRleF0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgc2VsZWN0aW9uLnRleHRMYWJlbCA9IHRleHRbc2VsZWN0SW5kZXhdO1xuICAgICAgICB9IGVsc2UgaWYodGV4dCkge1xuICAgICAgICAgICAgc2VsZWN0aW9uLnRleHRMYWJlbCA9IHRleHQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59O1xuXG5wcm90by51cGRhdGUgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgdmFyIHNjZW5lID0gdGhpcy5zY2VuZTtcbiAgICB2YXIgbGF5b3V0ID0gc2NlbmUuZnVsbFNjZW5lTGF5b3V0O1xuXG4gICAgdGhpcy5kYXRhID0gZ2VuZXJhdGVJc29NZXNoZXMoZGF0YSk7XG5cbiAgICAvLyBVbnBhY2sgcG9zaXRpb24gZGF0YVxuICAgIGZ1bmN0aW9uIHRvRGF0YUNvb3JkcyhheGlzLCBjb29yZCwgc2NhbGUsIGNhbGVuZGFyKSB7XG4gICAgICAgIHJldHVybiBjb29yZC5tYXAoZnVuY3Rpb24oeCkge1xuICAgICAgICAgICAgcmV0dXJuIGF4aXMuZDJsKHgsIDAsIGNhbGVuZGFyKSAqIHNjYWxlO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB2YXIgcG9zaXRpb25zID0gemlwMyhcbiAgICAgICAgdG9EYXRhQ29vcmRzKGxheW91dC54YXhpcywgZGF0YS5feCwgc2NlbmUuZGF0YVNjYWxlWzBdLCBkYXRhLnhjYWxlbmRhciksXG4gICAgICAgIHRvRGF0YUNvb3JkcyhsYXlvdXQueWF4aXMsIGRhdGEuX3ksIHNjZW5lLmRhdGFTY2FsZVsxXSwgZGF0YS55Y2FsZW5kYXIpLFxuICAgICAgICB0b0RhdGFDb29yZHMobGF5b3V0LnpheGlzLCBkYXRhLl96LCBzY2VuZS5kYXRhU2NhbGVbMl0sIGRhdGEuemNhbGVuZGFyKSk7XG5cbiAgICB2YXIgY2VsbHMgPSB6aXAzKGRhdGEuX2ksIGRhdGEuX2osIGRhdGEuX2spO1xuXG4gICAgdmFyIGNvbmZpZyA9IHtcbiAgICAgICAgcG9zaXRpb25zOiBwb3NpdGlvbnMsXG4gICAgICAgIGNlbGxzOiBjZWxscyxcbiAgICAgICAgbGlnaHRQb3NpdGlvbjogW2RhdGEubGlnaHRwb3NpdGlvbi54LCBkYXRhLmxpZ2h0cG9zaXRpb24ueSwgZGF0YS5saWdodHBvc2l0aW9uLnpdLFxuICAgICAgICBhbWJpZW50OiBkYXRhLmxpZ2h0aW5nLmFtYmllbnQsXG4gICAgICAgIGRpZmZ1c2U6IGRhdGEubGlnaHRpbmcuZGlmZnVzZSxcbiAgICAgICAgc3BlY3VsYXI6IGRhdGEubGlnaHRpbmcuc3BlY3VsYXIsXG4gICAgICAgIHJvdWdobmVzczogZGF0YS5saWdodGluZy5yb3VnaG5lc3MsXG4gICAgICAgIGZyZXNuZWw6IGRhdGEubGlnaHRpbmcuZnJlc25lbCxcbiAgICAgICAgdmVydGV4Tm9ybWFsc0Vwc2lsb246IGRhdGEubGlnaHRpbmcudmVydGV4bm9ybWFsc2Vwc2lsb24sXG4gICAgICAgIGZhY2VOb3JtYWxzRXBzaWxvbjogZGF0YS5saWdodGluZy5mYWNlbm9ybWFsc2Vwc2lsb24sXG4gICAgICAgIG9wYWNpdHk6IGRhdGEub3BhY2l0eSxcbiAgICAgICAgb3BhY2l0eXNjYWxlOiBkYXRhLm9wYWNpdHlzY2FsZSxcbiAgICAgICAgY29udG91ckVuYWJsZTogZGF0YS5jb250b3VyLnNob3csXG4gICAgICAgIGNvbnRvdXJDb2xvcjogc3RyMlJnYmFBcnJheShkYXRhLmNvbnRvdXIuY29sb3IpLnNsaWNlKDAsIDMpLFxuICAgICAgICBjb250b3VyV2lkdGg6IGRhdGEuY29udG91ci53aWR0aCxcbiAgICAgICAgdXNlRmFjZXROb3JtYWxzOiBkYXRhLmZsYXRzaGFkaW5nXG4gICAgfTtcblxuICAgIHZhciBjT3B0cyA9IGV4dHJhY3RPcHRzKGRhdGEpO1xuICAgIGNvbmZpZy52ZXJ0ZXhJbnRlbnNpdHkgPSBkYXRhLl9pbnRlbnNpdHk7XG4gICAgY29uZmlnLnZlcnRleEludGVuc2l0eUJvdW5kcyA9IFtjT3B0cy5taW4sIGNPcHRzLm1heF07XG4gICAgY29uZmlnLmNvbG9ybWFwID0gcGFyc2VDb2xvclNjYWxlKGRhdGEpO1xuXG4gICAgLy8gVXBkYXRlIG1lc2hcbiAgICB0aGlzLm1lc2gudXBkYXRlKGNvbmZpZyk7XG59O1xuXG5wcm90by5kaXNwb3NlID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5zY2VuZS5nbHBsb3QucmVtb3ZlKHRoaXMubWVzaCk7XG4gICAgdGhpcy5tZXNoLmRpc3Bvc2UoKTtcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZVZvbHVtZVRyYWNlKHNjZW5lLCBkYXRhKSB7XG4gICAgdmFyIGdsID0gc2NlbmUuZ2xwbG90LmdsO1xuICAgIHZhciBtZXNoID0gY3JlYXRlTWVzaCh7Z2w6IGdsfSk7XG4gICAgdmFyIHJlc3VsdCA9IG5ldyBWb2x1bWVUcmFjZShzY2VuZSwgbWVzaCwgZGF0YS51aWQpO1xuXG4gICAgbWVzaC5fdHJhY2UgPSByZXN1bHQ7XG4gICAgcmVzdWx0LnVwZGF0ZShkYXRhKTtcbiAgICBzY2VuZS5nbHBsb3QuYWRkKG1lc2gpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlVm9sdW1lVHJhY2U7XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvcnNjYWxlXCI6NjA1LFwiLi4vLi4vbGliL2dsX2Zvcm1hdF9jb2xvclwiOjcxNixcIi4uLy4uL2xpYi9zdHIycmdiYXJyYXlcIjo3NDIsXCIuLi8uLi9wbG90cy9nbDNkL3ppcDNcIjo4MTgsXCIuLi9pc29zdXJmYWNlL2NvbnZlcnRcIjoxMDUwLFwiZ2wtbWVzaDNkXCI6MjgwfV0sMTI1MTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBhdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9hdHRyaWJ1dGVzJyk7XG52YXIgc3VwcGx5SXNvRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9pc29zdXJmYWNlL2RlZmF1bHRzJykuc3VwcGx5SXNvRGVmYXVsdHM7XG5cbnZhciBNSU4gPSAwLjE7IC8vIE5vdGU6IG9mdGVuIHdlIGRvbid0IHdhbnQgdGhlIGRhdGEgY3ViZSB0byBiZSBkaXNhcHBlYXJlZFxuXG5mdW5jdGlvbiBjcmVhdGVXYXZlKG4sIG1pbk9wYWNpdHkpIHtcbiAgICB2YXIgYXJyID0gW107XG4gICAgdmFyIHN0ZXBzID0gMzI7IC8vIE1heDogMjU2XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHN0ZXBzOyBpKyspIHtcbiAgICAgICAgdmFyIHUgPSBpIC8gKHN0ZXBzIC0gMSk7XG4gICAgICAgIHZhciB2ID0gbWluT3BhY2l0eSArICgxIC0gbWluT3BhY2l0eSkgKiAoMSAtIE1hdGgucG93KE1hdGguc2luKG4gKiB1ICogTWF0aC5QSSksIDIpKTtcbiAgICAgICAgYXJyLnB1c2goW1xuICAgICAgICAgICAgdSxcbiAgICAgICAgICAgIE1hdGgubWF4KDEsIE1hdGgubWluKDAsIHYpKVxuICAgICAgICBdKTtcbiAgICB9XG4gICAgcmV0dXJuIGFycjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgc3VwcGx5SXNvRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGRlZmF1bHRDb2xvciwgbGF5b3V0LCBjb2VyY2UpO1xuXG4gICAgdmFyIG9wYWNpdHlzY2FsZSA9IGNvZXJjZSgnb3BhY2l0eXNjYWxlJyk7XG4gICAgaWYob3BhY2l0eXNjYWxlID09PSAnbWF4Jykge1xuICAgICAgICB0cmFjZU91dC5vcGFjaXR5c2NhbGUgPSBbWzAsIE1JTl0sIFsxLCAxXV07XG4gICAgfSBlbHNlIGlmKG9wYWNpdHlzY2FsZSA9PT0gJ21pbicpIHtcbiAgICAgICAgdHJhY2VPdXQub3BhY2l0eXNjYWxlID0gW1swLCAxXSwgWzEsIE1JTl1dO1xuICAgIH0gZWxzZSBpZihvcGFjaXR5c2NhbGUgPT09ICdleHRyZW1lcycpIHtcbiAgICAgICAgdHJhY2VPdXQub3BhY2l0eXNjYWxlID0gY3JlYXRlV2F2ZSgxLCBNSU4pO1xuICAgIH0gZWxzZSBpZighaXNWYWxpZFNjYWxlQXJyYXkob3BhY2l0eXNjYWxlKSkge1xuICAgICAgICB0cmFjZU91dC5vcGFjaXR5c2NhbGUgPSB1bmRlZmluZWQ7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gaXNWYWxpZFNjYWxlQXJyYXkoc2NsKSB7XG4gICAgdmFyIGhpZ2hlc3RWYWwgPSAwO1xuXG4gICAgaWYoIUFycmF5LmlzQXJyYXkoc2NsKSB8fCBzY2wubGVuZ3RoIDwgMikgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYoIXNjbFswXSB8fCAhc2NsW3NjbC5sZW5ndGggLSAxXSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYoK3NjbFswXVswXSAhPT0gMCB8fCArc2NsW3NjbC5sZW5ndGggLSAxXVswXSAhPT0gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNjbC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc2kgPSBzY2xbaV07XG5cbiAgICAgICAgaWYoc2kubGVuZ3RoICE9PSAyIHx8ICtzaVswXSA8IGhpZ2hlc3RWYWwpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGhpZ2hlc3RWYWwgPSArc2lbMF07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG59XG5cbn0se1wiLi4vLi4vbGliXCI6NzE5LFwiLi4vaXNvc3VyZmFjZS9kZWZhdWx0c1wiOjEwNTEsXCIuL2F0dHJpYnV0ZXNcIjoxMjQ5fV0sMTI1MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIHN1cHBseURlZmF1bHRzOiBfZGVyZXFfKCcuL2RlZmF1bHRzJyksXG4gICAgY2FsYzogX2RlcmVxXygnLi4vaXNvc3VyZmFjZS9jYWxjJyksXG4gICAgY29sb3JiYXI6IHtcbiAgICAgICAgbWluOiAnY21pbicsXG4gICAgICAgIG1heDogJ2NtYXgnXG4gICAgfSxcbiAgICBwbG90OiBfZGVyZXFfKCcuL2NvbnZlcnQnKSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3ZvbHVtZScsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2dsM2QnKSxcbiAgICBjYXRlZ29yaWVzOiBbJ2dsM2QnXSxcbiAgICBtZXRhOiB7XG4gICAgICAgIFxuICAgIH1cbn07XG5cbn0se1wiLi4vLi4vcGxvdHMvZ2wzZFwiOjgwNyxcIi4uL2lzb3N1cmZhY2UvY2FsY1wiOjEwNDksXCIuL2F0dHJpYnV0ZXNcIjoxMjQ5LFwiLi9jb252ZXJ0XCI6MTI1MCxcIi4vZGVmYXVsdHNcIjoxMjUxfV0sMTI1MzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBiYXJBdHRycyA9IF9kZXJlcV8oJy4uL2Jhci9hdHRyaWJ1dGVzJyk7XG52YXIgbGluZUF0dHJzID0gX2RlcmVxXygnLi4vc2NhdHRlci9hdHRyaWJ1dGVzJykubGluZTtcbnZhciBwbG90QXR0cnMgPSBfZGVyZXFfKCcuLi8uLi9wbG90cy9hdHRyaWJ1dGVzJyk7XG52YXIgaG92ZXJ0ZW1wbGF0ZUF0dHJzID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXMnKTtcbnZhciBjb25zdGFudHMgPSBfZGVyZXFfKCcuL2NvbnN0YW50cycpO1xudmFyIGV4dGVuZEZsYXQgPSBfZGVyZXFfKCcuLi8uLi9saWIvZXh0ZW5kJykuZXh0ZW5kRmxhdDtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcblxuZnVuY3Rpb24gZGlyZWN0aW9uQXR0cnMoZGlyVHh0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgbWFya2VyOiB7XG4gICAgICAgICAgICBjb2xvcjogZXh0ZW5kRmxhdCh7fSwgYmFyQXR0cnMubWFya2VyLmNvbG9yLCB7XG4gICAgICAgICAgICAgICAgYXJyYXlPazogZmFsc2UsXG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdzdHlsZScsXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIGxpbmU6IHtcbiAgICAgICAgICAgICAgICBjb2xvcjogZXh0ZW5kRmxhdCh7fSwgYmFyQXR0cnMubWFya2VyLmxpbmUuY29sb3IsIHtcbiAgICAgICAgICAgICAgICAgICAgYXJyYXlPazogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICB3aWR0aDogZXh0ZW5kRmxhdCh7fSwgYmFyQXR0cnMubWFya2VyLmxpbmUud2lkdGgsIHtcbiAgICAgICAgICAgICAgICAgICAgYXJyYXlPazogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGVkaXRUeXBlOiAnc3R5bGUnLFxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgICAgICB9LFxuICAgICAgICBlZGl0VHlwZTogJ3N0eWxlJ1xuICAgIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIG1lYXN1cmU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2RhdGFfYXJyYXknLFxuICAgICAgICBkZmx0OiBbXSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICBiYXNlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBkZmx0OiBudWxsLFxuICAgICAgICBhcnJheU9rOiBmYWxzZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB4OiBiYXJBdHRycy54LFxuICAgIHgwOiBiYXJBdHRycy54MCxcbiAgICBkeDogYmFyQXR0cnMuZHgsXG4gICAgeTogYmFyQXR0cnMueSxcbiAgICB5MDogYmFyQXR0cnMueTAsXG4gICAgZHk6IGJhckF0dHJzLmR5LFxuXG4gICAgaG92ZXJ0ZXh0OiBiYXJBdHRycy5ob3ZlcnRleHQsXG4gICAgaG92ZXJ0ZW1wbGF0ZTogaG92ZXJ0ZW1wbGF0ZUF0dHJzKHt9LCB7XG4gICAgICAgIGtleXM6IGNvbnN0YW50cy5ldmVudERhdGFLZXlzXG4gICAgfSksXG5cbiAgICBob3ZlcmluZm86IGV4dGVuZEZsYXQoe30sIHBsb3RBdHRycy5ob3ZlcmluZm8sIHtcbiAgICAgICAgZmxhZ3M6IFsnbmFtZScsICd4JywgJ3knLCAndGV4dCcsICdpbml0aWFsJywgJ2RlbHRhJywgJ2ZpbmFsJ11cbiAgICB9KSxcblxuICAgIHRleHRpbmZvOiB7XG4gICAgICAgIHZhbFR5cGU6ICdmbGFnbGlzdCcsXG4gICAgICAgIGZsYWdzOiBbJ2xhYmVsJywgJ3RleHQnLCAnaW5pdGlhbCcsICdkZWx0YScsICdmaW5hbCddLFxuICAgICAgICBleHRyYXM6IFsnbm9uZSddLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgYXJyYXlPazogZmFsc2UsXG4gICAgICAgIFxuICAgIH0sXG5cbiAgICB0ZXh0OiBiYXJBdHRycy50ZXh0LFxuICAgIHRleHRwb3NpdGlvbjogYmFyQXR0cnMudGV4dHBvc2l0aW9uLFxuICAgIGluc2lkZXRleHRhbmNob3I6IGJhckF0dHJzLmluc2lkZXRleHRhbmNob3IsXG4gICAgdGV4dGFuZ2xlOiBiYXJBdHRycy50ZXh0YW5nbGUsXG4gICAgdGV4dGZvbnQ6IGJhckF0dHJzLnRleHRmb250LFxuICAgIGluc2lkZXRleHRmb250OiBiYXJBdHRycy5pbnNpZGV0ZXh0Zm9udCxcbiAgICBvdXRzaWRldGV4dGZvbnQ6IGJhckF0dHJzLm91dHNpZGV0ZXh0Zm9udCxcbiAgICBjb25zdHJhaW50ZXh0OiBiYXJBdHRycy5jb25zdHJhaW50ZXh0LFxuXG4gICAgY2xpcG9uYXhpczogYmFyQXR0cnMuY2xpcG9uYXhpcyxcbiAgICBvcmllbnRhdGlvbjogYmFyQXR0cnMub3JpZW50YXRpb24sXG5cbiAgICBvZmZzZXQ6IGJhckF0dHJzLm9mZnNldCxcbiAgICB3aWR0aDogYmFyQXR0cnMud2lkdGgsXG5cbiAgICBpbmNyZWFzaW5nOiBkaXJlY3Rpb25BdHRycygnaW5jcmVhc2luZycpLFxuICAgIGRlY3JlYXNpbmc6IGRpcmVjdGlvbkF0dHJzKCdkZWNyZWFzaW5nJyksXG4gICAgdG90YWxzOiBkaXJlY3Rpb25BdHRycygnaW50ZXJtZWRpYXRlIHN1bXMgYW5kIHRvdGFsJyksXG5cbiAgICBjb25uZWN0b3I6IHtcbiAgICAgICAgbGluZToge1xuICAgICAgICAgICAgY29sb3I6IGV4dGVuZEZsYXQoe30sIGxpbmVBdHRycy5jb2xvciwge2RmbHQ6IENvbG9yLmRlZmF1bHRMaW5lfSksXG4gICAgICAgICAgICB3aWR0aDogZXh0ZW5kRmxhdCh7fSwgbGluZUF0dHJzLndpZHRoLCB7XG4gICAgICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JywgLy8gaS5lLiB0byBhZGp1c3QgYmFycyBpcyBtb2RlOiAnYmV0d2VlbicuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vcGxvdGx5L3Bsb3RseS5qcy9pc3N1ZXMvMzc4N1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBkYXNoOiBsaW5lQXR0cnMuZGFzaCxcbiAgICAgICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICAgICAgfSxcbiAgICAgICAgbW9kZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ3NwYW5uaW5nJywgJ2JldHdlZW4nXSxcbiAgICAgICAgICAgIGRmbHQ6ICdiZXR3ZWVuJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdwbG90JyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB2aXNpYmxlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZmx0OiB0cnVlLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ3Bsb3QnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVkaXRUeXBlOiAncGxvdCdcbiAgICB9LFxuXG4gICAgb2Zmc2V0Z3JvdXA6IGJhckF0dHJzLm9mZnNldGdyb3VwLFxuICAgIGFsaWdubWVudGdyb3VwOiBiYXJBdHRycy5hbGlnbm1lbnRncm91cFxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9meC9ob3ZlcnRlbXBsYXRlX2F0dHJpYnV0ZXNcIjo2MzEsXCIuLi8uLi9saWIvZXh0ZW5kXCI6NzEwLFwiLi4vLi4vcGxvdHMvYXR0cmlidXRlc1wiOjc2NCxcIi4uL2Jhci9hdHRyaWJ1dGVzXCI6ODU3LFwiLi4vc2NhdHRlci9hdHRyaWJ1dGVzXCI6MTExMixcIi4vY29uc3RhbnRzXCI6MTI1NX1dLDEyNTQ6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgQXhlcyA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJyk7XG52YXIgbWVyZ2VBcnJheSA9IF9kZXJlcV8oJy4uLy4uL2xpYicpLm1lcmdlQXJyYXk7XG52YXIgY2FsY1NlbGVjdGlvbiA9IF9kZXJlcV8oJy4uL3NjYXR0ZXIvY2FsY19zZWxlY3Rpb24nKTtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG5mdW5jdGlvbiBpc0Fic29sdXRlKGEpIHtcbiAgICByZXR1cm4gKGEgPT09ICdhJyB8fCBhID09PSAnYWJzb2x1dGUnKTtcbn1cblxuZnVuY3Rpb24gaXNUb3RhbChhKSB7XG4gICAgcmV0dXJuIChhID09PSAndCcgfHwgYSA9PT0gJ3RvdGFsJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY2FsYyhnZCwgdHJhY2UpIHtcbiAgICB2YXIgeGEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueGF4aXMgfHwgJ3gnKTtcbiAgICB2YXIgeWEgPSBBeGVzLmdldEZyb21JZChnZCwgdHJhY2UueWF4aXMgfHwgJ3knKTtcbiAgICB2YXIgc2l6ZSwgcG9zO1xuXG4gICAgaWYodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJykge1xuICAgICAgICBzaXplID0geGEubWFrZUNhbGNkYXRhKHRyYWNlLCAneCcpO1xuICAgICAgICBwb3MgPSB5YS5tYWtlQ2FsY2RhdGEodHJhY2UsICd5Jyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc2l6ZSA9IHlhLm1ha2VDYWxjZGF0YSh0cmFjZSwgJ3knKTtcbiAgICAgICAgcG9zID0geGEubWFrZUNhbGNkYXRhKHRyYWNlLCAneCcpO1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSB0aGUgXCJjYWxjdWxhdGVkIGRhdGFcIiB0byBwbG90XG4gICAgdmFyIHNlcmllc2xlbiA9IE1hdGgubWluKHBvcy5sZW5ndGgsIHNpemUubGVuZ3RoKTtcbiAgICB2YXIgY2QgPSBuZXcgQXJyYXkoc2VyaWVzbGVuKTtcblxuICAgIC8vIHNldCBwb3NpdGlvbiBhbmQgc2l6ZSAoYXMgd2VsbCBhcyBmb3Igd2F0ZXJmYWxsIHRvdGFsIHNpemUpXG4gICAgdmFyIHByZXZpb3VzU3VtID0gMDtcbiAgICB2YXIgbmV3U2l6ZTtcbiAgICAvLyB0cmFjZS13aWRlIGZsYWdzXG4gICAgdmFyIGhhc1RvdGFscyA9IGZhbHNlO1xuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHNlcmllc2xlbjsgaSsrKSB7XG4gICAgICAgIHZhciBhbW91bnQgPSBzaXplW2ldIHx8IDA7XG5cbiAgICAgICAgdmFyIGNvbm5lY3RUb05leHQgPSBmYWxzZTtcbiAgICAgICAgaWYoc2l6ZVtpXSAhPT0gQkFETlVNIHx8IGlzVG90YWwodHJhY2UubWVhc3VyZVtpXSkgfHwgaXNBYnNvbHV0ZSh0cmFjZS5tZWFzdXJlW2ldKSkge1xuICAgICAgICAgICAgaWYoaSArIDEgPCBzZXJpZXNsZW4gJiYgKHNpemVbaSArIDFdICE9PSBCQUROVU0gfHwgaXNUb3RhbCh0cmFjZS5tZWFzdXJlW2kgKyAxXSkgfHwgaXNBYnNvbHV0ZSh0cmFjZS5tZWFzdXJlW2kgKyAxXSkpKSB7XG4gICAgICAgICAgICAgICAgY29ubmVjdFRvTmV4dCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY2RpID0gY2RbaV0gPSB7XG4gICAgICAgICAgICBpOiBpLFxuICAgICAgICAgICAgcDogcG9zW2ldLFxuICAgICAgICAgICAgczogYW1vdW50LFxuICAgICAgICAgICAgcmF3UzogYW1vdW50LFxuICAgICAgICAgICAgY05leHQ6IGNvbm5lY3RUb05leHRcbiAgICAgICAgfTtcblxuICAgICAgICBpZihpc0Fic29sdXRlKHRyYWNlLm1lYXN1cmVbaV0pKSB7XG4gICAgICAgICAgICBwcmV2aW91c1N1bSA9IGNkaS5zO1xuXG4gICAgICAgICAgICBjZGkuaXNTdW0gPSB0cnVlO1xuICAgICAgICAgICAgY2RpLmRpciA9ICd0b3RhbHMnO1xuICAgICAgICAgICAgY2RpLnMgPSBwcmV2aW91c1N1bTtcbiAgICAgICAgfSBlbHNlIGlmKGlzVG90YWwodHJhY2UubWVhc3VyZVtpXSkpIHtcbiAgICAgICAgICAgIGNkaS5pc1N1bSA9IHRydWU7XG4gICAgICAgICAgICBjZGkuZGlyID0gJ3RvdGFscyc7XG4gICAgICAgICAgICBjZGkucyA9IHByZXZpb3VzU3VtO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZGVmYXVsdDogcmVsYXRpdmVcbiAgICAgICAgICAgIGNkaS5pc1N1bSA9IGZhbHNlO1xuICAgICAgICAgICAgY2RpLmRpciA9IGNkaS5yYXdTIDwgMCA/ICdkZWNyZWFzaW5nJyA6ICdpbmNyZWFzaW5nJztcbiAgICAgICAgICAgIG5ld1NpemUgPSBjZGkucztcbiAgICAgICAgICAgIGNkaS5zID0gcHJldmlvdXNTdW0gKyBuZXdTaXplO1xuICAgICAgICAgICAgcHJldmlvdXNTdW0gKz0gbmV3U2l6ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGNkaS5kaXIgPT09ICd0b3RhbHMnKSB7XG4gICAgICAgICAgICBoYXNUb3RhbHMgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYodHJhY2UuaWRzKSB7XG4gICAgICAgICAgICBjZGkuaWQgPSBTdHJpbmcodHJhY2UuaWRzW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNkaS52ID0gKHRyYWNlLmJhc2UgfHwgMCkgKyBwcmV2aW91c1N1bTtcbiAgICB9XG5cbiAgICBpZihjZC5sZW5ndGgpIGNkWzBdLmhhc1RvdGFscyA9IGhhc1RvdGFscztcblxuICAgIG1lcmdlQXJyYXkodHJhY2UudGV4dCwgY2QsICd0eCcpO1xuICAgIG1lcmdlQXJyYXkodHJhY2UuaG92ZXJ0ZXh0LCBjZCwgJ2h0eCcpO1xuICAgIGNhbGNTZWxlY3Rpb24oY2QsIHRyYWNlKTtcblxuICAgIHJldHVybiBjZDtcbn07XG5cbn0se1wiLi4vLi4vY29uc3RhbnRzL251bWVyaWNhbFwiOjY5NSxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vc2NhdHRlci9jYWxjX3NlbGVjdGlvblwiOjExMTR9XSwxMjU1OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZXZlbnREYXRhS2V5czogW1xuICAgICAgICAnaW5pdGlhbCcsXG4gICAgICAgICdkZWx0YScsXG4gICAgICAgICdmaW5hbCdcbiAgICBdXG59O1xuXG59LHt9XSwxMjU2OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIHNldEdyb3VwUG9zaXRpb25zID0gX2RlcmVxXygnLi4vYmFyL2Nyb3NzX3RyYWNlX2NhbGMnKS5zZXRHcm91cFBvc2l0aW9ucztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcm9zc1RyYWNlQ2FsYyhnZCwgcGxvdGluZm8pIHtcbiAgICB2YXIgZnVsbExheW91dCA9IGdkLl9mdWxsTGF5b3V0O1xuICAgIHZhciBmdWxsRGF0YSA9IGdkLl9mdWxsRGF0YTtcbiAgICB2YXIgY2FsY2RhdGEgPSBnZC5jYWxjZGF0YTtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcbiAgICB2YXIgd2F0ZXJmYWxscyA9IFtdO1xuICAgIHZhciB3YXRlcmZhbGxzVmVydCA9IFtdO1xuICAgIHZhciB3YXRlcmZhbGxzSG9yeiA9IFtdO1xuICAgIHZhciBjZCwgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBmdWxsVHJhY2UgPSBmdWxsRGF0YVtpXTtcblxuICAgICAgICBpZihcbiAgICAgICAgICAgIGZ1bGxUcmFjZS52aXNpYmxlID09PSB0cnVlICYmXG4gICAgICAgICAgICBmdWxsVHJhY2UueGF4aXMgPT09IHhhLl9pZCAmJlxuICAgICAgICAgICAgZnVsbFRyYWNlLnlheGlzID09PSB5YS5faWQgJiZcbiAgICAgICAgICAgIGZ1bGxUcmFjZS50eXBlID09PSAnd2F0ZXJmYWxsJ1xuICAgICAgICApIHtcbiAgICAgICAgICAgIGNkID0gY2FsY2RhdGFbaV07XG5cbiAgICAgICAgICAgIGlmKGZ1bGxUcmFjZS5vcmllbnRhdGlvbiA9PT0gJ2gnKSB7XG4gICAgICAgICAgICAgICAgd2F0ZXJmYWxsc0hvcnoucHVzaChjZCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHdhdGVyZmFsbHNWZXJ0LnB1c2goY2QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB3YXRlcmZhbGxzLnB1c2goY2QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIG9wdHMgPSB7XG4gICAgICAgIG1vZGU6IGZ1bGxMYXlvdXQud2F0ZXJmYWxsbW9kZSxcbiAgICAgICAgbm9ybTogZnVsbExheW91dC53YXRlcmZhbGxub3JtLFxuICAgICAgICBnYXA6IGZ1bGxMYXlvdXQud2F0ZXJmYWxsZ2FwLFxuICAgICAgICBncm91cGdhcDogZnVsbExheW91dC53YXRlcmZhbGxncm91cGdhcFxuICAgIH07XG5cbiAgICBzZXRHcm91cFBvc2l0aW9ucyhnZCwgeGEsIHlhLCB3YXRlcmZhbGxzVmVydCwgb3B0cyk7XG4gICAgc2V0R3JvdXBQb3NpdGlvbnMoZ2QsIHlhLCB4YSwgd2F0ZXJmYWxsc0hvcnosIG9wdHMpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgd2F0ZXJmYWxscy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjZCA9IHdhdGVyZmFsbHNbaV07XG5cbiAgICAgICAgZm9yKHZhciBqID0gMDsgaiA8IGNkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICB2YXIgZGkgPSBjZFtqXTtcblxuICAgICAgICAgICAgaWYoZGkuaXNTdW0gPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgZGkuczAgKz0gKGogPT09IDApID8gMCA6IGNkW2ogLSAxXS5zO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihqICsgMSA8IGNkLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGNkW2pdLm5leHRQMCA9IGNkW2ogKyAxXS5wMDtcbiAgICAgICAgICAgICAgICBjZFtqXS5uZXh0UzAgPSBjZFtqICsgMV0uczA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG59LHtcIi4uL2Jhci9jcm9zc190cmFjZV9jYWxjXCI6ODYwfV0sMTI1NzpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcblxudmFyIGhhbmRsZUdyb3VwaW5nRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9iYXIvZGVmYXVsdHMnKS5oYW5kbGVHcm91cGluZ0RlZmF1bHRzO1xudmFyIGhhbmRsZVRleHQgPSBfZGVyZXFfKCcuLi9iYXIvZGVmYXVsdHMnKS5oYW5kbGVUZXh0O1xudmFyIGhhbmRsZVhZRGVmYXVsdHMgPSBfZGVyZXFfKCcuLi9zY2F0dGVyL3h5X2RlZmF1bHRzJyk7XG52YXIgYXR0cmlidXRlcyA9IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpO1xudmFyIENvbG9yID0gX2RlcmVxXygnLi4vLi4vY29tcG9uZW50cy9jb2xvcicpO1xudmFyIGRlbHRhID0gX2RlcmVxXygnLi4vLi4vY29uc3RhbnRzL2RlbHRhLmpzJyk7XG5cbnZhciBJTkNSRUFTSU5HX0NPTE9SID0gZGVsdGEuSU5DUkVBU0lORy5DT0xPUjtcbnZhciBERUNSRUFTSU5HX0NPTE9SID0gZGVsdGEuREVDUkVBU0lORy5DT0xPUjtcbnZhciBUT1RBTFNfQ09MT1IgPSAnIzQ0OTlGRic7XG5cbmZ1bmN0aW9uIGhhbmRsZURpcmVjdGlvbihjb2VyY2UsIGRpcmVjdGlvbiwgZGVmYXVsdENvbG9yKSB7XG4gICAgY29lcmNlKGRpcmVjdGlvbiArICcubWFya2VyLmNvbG9yJywgZGVmYXVsdENvbG9yKTtcbiAgICBjb2VyY2UoZGlyZWN0aW9uICsgJy5tYXJrZXIubGluZS5jb2xvcicsIENvbG9yLmRlZmF1bHRMaW5lKTtcbiAgICBjb2VyY2UoZGlyZWN0aW9uICsgJy5tYXJrZXIubGluZS53aWR0aCcpO1xufVxuXG5mdW5jdGlvbiBzdXBwbHlEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZGVmYXVsdENvbG9yLCBsYXlvdXQpIHtcbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZUluLCB0cmFjZU91dCwgYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGxlbiA9IGhhbmRsZVhZRGVmYXVsdHModHJhY2VJbiwgdHJhY2VPdXQsIGxheW91dCwgY29lcmNlKTtcbiAgICBpZighbGVuKSB7XG4gICAgICAgIHRyYWNlT3V0LnZpc2libGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvZXJjZSgnbWVhc3VyZScpO1xuXG4gICAgY29lcmNlKCdvcmllbnRhdGlvbicsICh0cmFjZU91dC54ICYmICF0cmFjZU91dC55KSA/ICdoJyA6ICd2Jyk7XG4gICAgY29lcmNlKCdiYXNlJyk7XG4gICAgY29lcmNlKCdvZmZzZXQnKTtcbiAgICBjb2VyY2UoJ3dpZHRoJyk7XG5cbiAgICBjb2VyY2UoJ3RleHQnKTtcblxuICAgIGNvZXJjZSgnaG92ZXJ0ZXh0Jyk7XG4gICAgY29lcmNlKCdob3ZlcnRlbXBsYXRlJyk7XG5cbiAgICB2YXIgdGV4dHBvc2l0aW9uID0gY29lcmNlKCd0ZXh0cG9zaXRpb24nKTtcbiAgICBoYW5kbGVUZXh0KHRyYWNlSW4sIHRyYWNlT3V0LCBsYXlvdXQsIGNvZXJjZSwgdGV4dHBvc2l0aW9uLCB7XG4gICAgICAgIG1vZHVsZUhhc1NlbGVjdGVkOiBmYWxzZSxcbiAgICAgICAgbW9kdWxlSGFzVW5zZWxlY3RlZDogZmFsc2UsXG4gICAgICAgIG1vZHVsZUhhc0NvbnN0cmFpbjogdHJ1ZSxcbiAgICAgICAgbW9kdWxlSGFzQ2xpcG9uYXhpczogdHJ1ZSxcbiAgICAgICAgbW9kdWxlSGFzVGV4dGFuZ2xlOiB0cnVlLFxuICAgICAgICBtb2R1bGVIYXNJbnNpZGVhbmNob3I6IHRydWVcbiAgICB9KTtcblxuXG4gICAgaWYodHJhY2VPdXQudGV4dHBvc2l0aW9uICE9PSAnbm9uZScpIHtcbiAgICAgICAgY29lcmNlKCd0ZXh0aW5mbycpO1xuICAgIH1cblxuICAgIGhhbmRsZURpcmVjdGlvbihjb2VyY2UsICdpbmNyZWFzaW5nJywgSU5DUkVBU0lOR19DT0xPUik7XG4gICAgaGFuZGxlRGlyZWN0aW9uKGNvZXJjZSwgJ2RlY3JlYXNpbmcnLCBERUNSRUFTSU5HX0NPTE9SKTtcbiAgICBoYW5kbGVEaXJlY3Rpb24oY29lcmNlLCAndG90YWxzJywgVE9UQUxTX0NPTE9SKTtcblxuICAgIHZhciBjb25uZWN0b3JWaXNpYmxlID0gY29lcmNlKCdjb25uZWN0b3IudmlzaWJsZScpO1xuICAgIGlmKGNvbm5lY3RvclZpc2libGUpIHtcbiAgICAgICAgY29lcmNlKCdjb25uZWN0b3IubW9kZScpO1xuICAgICAgICB2YXIgY29ubmVjdG9yTGluZVdpZHRoID0gY29lcmNlKCdjb25uZWN0b3IubGluZS53aWR0aCcpO1xuICAgICAgICBpZihjb25uZWN0b3JMaW5lV2lkdGgpIHtcbiAgICAgICAgICAgIGNvZXJjZSgnY29ubmVjdG9yLmxpbmUuY29sb3InKTtcbiAgICAgICAgICAgIGNvZXJjZSgnY29ubmVjdG9yLmxpbmUuZGFzaCcpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjcm9zc1RyYWNlRGVmYXVsdHMoZnVsbERhdGEsIGZ1bGxMYXlvdXQpIHtcbiAgICB2YXIgdHJhY2VJbiwgdHJhY2VPdXQ7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0cikge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFjZU91dC5faW5wdXQsIHRyYWNlT3V0LCBhdHRyaWJ1dGVzLCBhdHRyKTtcbiAgICB9XG5cbiAgICBpZihmdWxsTGF5b3V0LndhdGVyZmFsbG1vZGUgPT09ICdncm91cCcpIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0cmFjZU91dCA9IGZ1bGxEYXRhW2ldO1xuICAgICAgICAgICAgdHJhY2VJbiA9IHRyYWNlT3V0Ll9pbnB1dDtcblxuICAgICAgICAgICAgaGFuZGxlR3JvdXBpbmdEZWZhdWx0cyh0cmFjZUluLCB0cmFjZU91dCwgZnVsbExheW91dCwgY29lcmNlKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc3VwcGx5RGVmYXVsdHM6IHN1cHBseURlZmF1bHRzLFxuICAgIGNyb3NzVHJhY2VEZWZhdWx0czogY3Jvc3NUcmFjZURlZmF1bHRzXG59O1xuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvY29sb3JcIjo1OTMsXCIuLi8uLi9jb25zdGFudHMvZGVsdGEuanNcIjo2ODksXCIuLi8uLi9saWJcIjo3MTksXCIuLi9iYXIvZGVmYXVsdHNcIjo4NjEsXCIuLi9zY2F0dGVyL3h5X2RlZmF1bHRzXCI6MTEzNyxcIi4vYXR0cmlidXRlc1wiOjEyNTN9XSwxMjU4OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBldmVudERhdGEob3V0LCBwdCAvKiAsIHRyYWNlLCBjZCwgcG9pbnROdW1iZXIgKi8pIHtcbiAgICAvLyBzdGFuZGFyZCBjYXJ0ZXNpYW4gZXZlbnQgZGF0YVxuICAgIG91dC54ID0gJ3hWYWwnIGluIHB0ID8gcHQueFZhbCA6IHB0Lng7XG4gICAgb3V0LnkgPSAneVZhbCcgaW4gcHQgPyBwdC55VmFsIDogcHQueTtcblxuICAgIC8vIGZvciBmdW5uZWxcbiAgICBpZignaW5pdGlhbCcgaW4gcHQpIG91dC5pbml0aWFsID0gcHQuaW5pdGlhbDtcbiAgICBpZignZGVsdGEnIGluIHB0KSBvdXQuZGVsdGEgPSBwdC5kZWx0YTtcbiAgICBpZignZmluYWwnIGluIHB0KSBvdXQuZmluYWwgPSBwdC5maW5hbDtcblxuICAgIGlmKHB0LnhhKSBvdXQueGF4aXMgPSBwdC54YTtcbiAgICBpZihwdC55YSkgb3V0LnlheGlzID0gcHQueWE7XG5cbiAgICByZXR1cm4gb3V0O1xufTtcblxufSx7fV0sMTI1OTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBob3ZlckxhYmVsVGV4dCA9IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzJykuaG92ZXJMYWJlbFRleHQ7XG52YXIgb3BhY2l0eSA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKS5vcGFjaXR5O1xudmFyIGhvdmVyT25CYXJzID0gX2RlcmVxXygnLi4vYmFyL2hvdmVyJykuaG92ZXJPbkJhcnM7XG52YXIgZGVsdGEgPSBfZGVyZXFfKCcuLi8uLi9jb25zdGFudHMvZGVsdGEuanMnKTtcblxudmFyIERJUlNZTUJPTCA9IHtcbiAgICBpbmNyZWFzaW5nOiBkZWx0YS5JTkNSRUFTSU5HLlNZTUJPTCxcbiAgICBkZWNyZWFzaW5nOiBkZWx0YS5ERUNSRUFTSU5HLlNZTUJPTFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBob3ZlclBvaW50cyhwb2ludERhdGEsIHh2YWwsIHl2YWwsIGhvdmVybW9kZSkge1xuICAgIHZhciBwb2ludCA9IGhvdmVyT25CYXJzKHBvaW50RGF0YSwgeHZhbCwgeXZhbCwgaG92ZXJtb2RlKTtcbiAgICBpZighcG9pbnQpIHJldHVybjtcblxuICAgIHZhciBjZCA9IHBvaW50LmNkO1xuICAgIHZhciB0cmFjZSA9IGNkWzBdLnRyYWNlO1xuICAgIHZhciBpc0hvcml6b250YWwgPSAodHJhY2Uub3JpZW50YXRpb24gPT09ICdoJyk7XG5cbiAgICB2YXIgdkF4aXMgPSBpc0hvcml6b250YWwgPyBwb2ludERhdGEueGEgOiBwb2ludERhdGEueWE7XG5cbiAgICBmdW5jdGlvbiBmb3JtYXROdW1iZXIoYSkge1xuICAgICAgICByZXR1cm4gaG92ZXJMYWJlbFRleHQodkF4aXMsIGEpO1xuICAgIH1cblxuICAgIC8vIHRoZSBjbG9zZXN0IGRhdGEgcG9pbnRcbiAgICB2YXIgaW5kZXggPSBwb2ludC5pbmRleDtcbiAgICB2YXIgZGkgPSBjZFtpbmRleF07XG5cbiAgICB2YXIgc2l6ZSA9IChkaS5pc1N1bSkgPyBkaS5iICsgZGkucyA6IGRpLnJhd1M7XG5cbiAgICBpZighZGkuaXNTdW0pIHtcbiAgICAgICAgcG9pbnQuaW5pdGlhbCA9IGRpLmIgKyBkaS5zIC0gc2l6ZTtcbiAgICAgICAgcG9pbnQuZGVsdGEgPSBzaXplO1xuICAgICAgICBwb2ludC5maW5hbCA9IHBvaW50LmluaXRpYWwgKyBwb2ludC5kZWx0YTtcblxuICAgICAgICB2YXIgdiA9IGZvcm1hdE51bWJlcihNYXRoLmFicyhwb2ludC5kZWx0YSkpO1xuICAgICAgICBwb2ludC5kZWx0YUxhYmVsID0gc2l6ZSA8IDAgPyAnKCcgKyB2ICsgJyknIDogdjtcbiAgICAgICAgcG9pbnQuZmluYWxMYWJlbCA9IGZvcm1hdE51bWJlcihwb2ludC5maW5hbCk7XG4gICAgICAgIHBvaW50LmluaXRpYWxMYWJlbCA9IGZvcm1hdE51bWJlcihwb2ludC5pbml0aWFsKTtcbiAgICB9XG5cbiAgICB2YXIgaG92ZXJpbmZvID0gZGkuaGkgfHwgdHJhY2UuaG92ZXJpbmZvO1xuICAgIHZhciB0ZXh0ID0gW107XG4gICAgaWYoaG92ZXJpbmZvICYmIGhvdmVyaW5mbyAhPT0gJ25vbmUnICYmIGhvdmVyaW5mbyAhPT0gJ3NraXAnKSB7XG4gICAgICAgIHZhciBpc0FsbCA9IChob3ZlcmluZm8gPT09ICdhbGwnKTtcbiAgICAgICAgdmFyIHBhcnRzID0gaG92ZXJpbmZvLnNwbGl0KCcrJyk7XG5cbiAgICAgICAgdmFyIGhhc0ZsYWcgPSBmdW5jdGlvbihmbGFnKSB7IHJldHVybiBpc0FsbCB8fCBwYXJ0cy5pbmRleE9mKGZsYWcpICE9PSAtMTsgfTtcblxuICAgICAgICBpZighZGkuaXNTdW0pIHtcbiAgICAgICAgICAgIGlmKGhhc0ZsYWcoJ2ZpbmFsJykgJiZcbiAgICAgICAgICAgICAgICAoaXNIb3Jpem9udGFsID8gIWhhc0ZsYWcoJ3gnKSA6ICFoYXNGbGFnKCd5JykpIC8vIGRvbid0IGRpc3BsYXkgcmVkdW5kYW50IGluZm8uXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICB0ZXh0LnB1c2gocG9pbnQuZmluYWxMYWJlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZihoYXNGbGFnKCdkZWx0YScpKSB7XG4gICAgICAgICAgICAgICAgaWYoc2l6ZSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dC5wdXNoKHBvaW50LmRlbHRhTGFiZWwgKyAnICcgKyBESVJTWU1CT0wuZGVjcmVhc2luZyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dC5wdXNoKHBvaW50LmRlbHRhTGFiZWwgKyAnICcgKyBESVJTWU1CT0wuaW5jcmVhc2luZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoaGFzRmxhZygnaW5pdGlhbCcpKSB7XG4gICAgICAgICAgICAgICAgdGV4dC5wdXNoKCdJbml0aWFsOiAnICsgcG9pbnQuaW5pdGlhbExhYmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKHRleHQubGVuZ3RoKSBwb2ludC5leHRyYVRleHQgPSB0ZXh0LmpvaW4oJzxicj4nKTtcblxuICAgIHBvaW50LmNvbG9yID0gZ2V0VHJhY2VDb2xvcih0cmFjZSwgZGkpO1xuXG4gICAgcmV0dXJuIFtwb2ludF07XG59O1xuXG5mdW5jdGlvbiBnZXRUcmFjZUNvbG9yKHRyYWNlLCBkaSkge1xuICAgIHZhciBjb250ID0gdHJhY2VbZGkuZGlyXS5tYXJrZXI7XG4gICAgdmFyIG1jID0gY29udC5jb2xvcjtcbiAgICB2YXIgbWxjID0gY29udC5saW5lLmNvbG9yO1xuICAgIHZhciBtbHcgPSBjb250LmxpbmUud2lkdGg7XG4gICAgaWYob3BhY2l0eShtYykpIHJldHVybiBtYztcbiAgICBlbHNlIGlmKG9wYWNpdHkobWxjKSAmJiBtbHcpIHJldHVybiBtbGM7XG59XG5cbn0se1wiLi4vLi4vY29tcG9uZW50cy9jb2xvclwiOjU5MyxcIi4uLy4uL2NvbnN0YW50cy9kZWx0YS5qc1wiOjY4OSxcIi4uLy4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi4vYmFyL2hvdmVyXCI6ODYzfV0sMTI2MDpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vYXR0cmlidXRlcycpLFxuICAgIGxheW91dEF0dHJpYnV0ZXM6IF9kZXJlcV8oJy4vbGF5b3V0X2F0dHJpYnV0ZXMnKSxcbiAgICBzdXBwbHlEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLnN1cHBseURlZmF1bHRzLFxuICAgIGNyb3NzVHJhY2VEZWZhdWx0czogX2RlcmVxXygnLi9kZWZhdWx0cycpLmNyb3NzVHJhY2VEZWZhdWx0cyxcbiAgICBzdXBwbHlMYXlvdXREZWZhdWx0czogX2RlcmVxXygnLi9sYXlvdXRfZGVmYXVsdHMnKSxcbiAgICBjYWxjOiBfZGVyZXFfKCcuL2NhbGMnKSxcbiAgICBjcm9zc1RyYWNlQ2FsYzogX2RlcmVxXygnLi9jcm9zc190cmFjZV9jYWxjJyksXG4gICAgcGxvdDogX2RlcmVxXygnLi9wbG90JyksXG4gICAgc3R5bGU6IF9kZXJlcV8oJy4vc3R5bGUnKS5zdHlsZSxcbiAgICBob3ZlclBvaW50czogX2RlcmVxXygnLi9ob3ZlcicpLFxuICAgIGV2ZW50RGF0YTogX2RlcmVxXygnLi9ldmVudF9kYXRhJyksXG5cbiAgICBzZWxlY3RQb2ludHM6IF9kZXJlcV8oJy4uL2Jhci9zZWxlY3QnKSxcblxuICAgIG1vZHVsZVR5cGU6ICd0cmFjZScsXG4gICAgbmFtZTogJ3dhdGVyZmFsbCcsXG4gICAgYmFzZVBsb3RNb2R1bGU6IF9kZXJlcV8oJy4uLy4uL3Bsb3RzL2NhcnRlc2lhbicpLFxuICAgIGNhdGVnb3JpZXM6IFsnYmFyLWxpa2UnLCAnY2FydGVzaWFuJywgJ3N2ZycsICdvcmllbnRlZCcsICdzaG93TGVnZW5kJywgJ3pvb21TY2FsZSddLFxuICAgIG1ldGE6IHtcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9wbG90cy9jYXJ0ZXNpYW5cIjo3NzgsXCIuLi9iYXIvc2VsZWN0XCI6ODY4LFwiLi9hdHRyaWJ1dGVzXCI6MTI1MyxcIi4vY2FsY1wiOjEyNTQsXCIuL2Nyb3NzX3RyYWNlX2NhbGNcIjoxMjU2LFwiLi9kZWZhdWx0c1wiOjEyNTcsXCIuL2V2ZW50X2RhdGFcIjoxMjU4LFwiLi9ob3ZlclwiOjEyNTksXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6MTI2MSxcIi4vbGF5b3V0X2RlZmF1bHRzXCI6MTI2MixcIi4vcGxvdFwiOjEyNjMsXCIuL3N0eWxlXCI6MTI2NH1dLDEyNjE6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICB3YXRlcmZhbGxtb2RlOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2dyb3VwJywgJ292ZXJsYXknXSxcbiAgICAgICAgZGZsdDogJ2dyb3VwJyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgd2F0ZXJmYWxsZ2FwOiB7XG4gICAgICAgIHZhbFR5cGU6ICdudW1iZXInLFxuICAgICAgICBtaW46IDAsXG4gICAgICAgIG1heDogMSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgd2F0ZXJmYWxsZ3JvdXBnYXA6IHtcbiAgICAgICAgdmFsVHlwZTogJ251bWJlcicsXG4gICAgICAgIG1pbjogMCxcbiAgICAgICAgbWF4OiAxLFxuICAgICAgICBkZmx0OiAwLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfVxufTtcblxufSx7fV0sMTI2MjpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBMaWIgPSBfZGVyZXFfKCcuLi8uLi9saWInKTtcbnZhciBsYXlvdXRBdHRyaWJ1dGVzID0gX2RlcmVxXygnLi9sYXlvdXRfYXR0cmlidXRlcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKGxheW91dEluLCBsYXlvdXRPdXQsIGZ1bGxEYXRhKSB7XG4gICAgdmFyIGhhc1RyYWNlVHlwZSA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gY29lcmNlKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UobGF5b3V0SW4sIGxheW91dE91dCwgbGF5b3V0QXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGZ1bGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0cmFjZSA9IGZ1bGxEYXRhW2ldO1xuXG4gICAgICAgIGlmKHRyYWNlLnZpc2libGUgJiYgdHJhY2UudHlwZSA9PT0gJ3dhdGVyZmFsbCcpIHtcbiAgICAgICAgICAgIGhhc1RyYWNlVHlwZSA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGhhc1RyYWNlVHlwZSkge1xuICAgICAgICBjb2VyY2UoJ3dhdGVyZmFsbG1vZGUnKTtcbiAgICAgICAgY29lcmNlKCd3YXRlcmZhbGxnYXAnLCAwLjIpO1xuICAgICAgICBjb2VyY2UoJ3dhdGVyZmFsbGdyb3VwZ2FwJyk7XG4gICAgfVxufTtcblxufSx7XCIuLi8uLi9saWJcIjo3MTksXCIuL2xheW91dF9hdHRyaWJ1dGVzXCI6MTI2MX1dLDEyNjM6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgZDMgPSBfZGVyZXFfKCdkMycpO1xudmFyIExpYiA9IF9kZXJlcV8oJy4uLy4uL2xpYicpO1xudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBiYXJQbG90ID0gX2RlcmVxXygnLi4vYmFyL3Bsb3QnKS5wbG90O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBsb3QoZ2QsIHBsb3RpbmZvLCBjZE1vZHVsZSwgdHJhY2VMYXllcikge1xuICAgIHZhciBmdWxsTGF5b3V0ID0gZ2QuX2Z1bGxMYXlvdXQ7XG5cbiAgICBiYXJQbG90KGdkLCBwbG90aW5mbywgY2RNb2R1bGUsIHRyYWNlTGF5ZXIsIHtcbiAgICAgICAgbW9kZTogZnVsbExheW91dC53YXRlcmZhbGxtb2RlLFxuICAgICAgICBub3JtOiBmdWxsTGF5b3V0LndhdGVyZmFsbG1vZGUsXG4gICAgICAgIGdhcDogZnVsbExheW91dC53YXRlcmZhbGxnYXAsXG4gICAgICAgIGdyb3VwZ2FwOiBmdWxsTGF5b3V0LndhdGVyZmFsbGdyb3VwZ2FwXG4gICAgfSk7XG5cbiAgICBwbG90Q29ubmVjdG9ycyhnZCwgcGxvdGluZm8sIGNkTW9kdWxlLCB0cmFjZUxheWVyKTtcbn07XG5cbmZ1bmN0aW9uIHBsb3RDb25uZWN0b3JzKGdkLCBwbG90aW5mbywgY2RNb2R1bGUsIHRyYWNlTGF5ZXIpIHtcbiAgICB2YXIgeGEgPSBwbG90aW5mby54YXhpcztcbiAgICB2YXIgeWEgPSBwbG90aW5mby55YXhpcztcblxuICAgIExpYi5tYWtlVHJhY2VHcm91cHModHJhY2VMYXllciwgY2RNb2R1bGUsICd0cmFjZSBiYXJzJykuZWFjaChmdW5jdGlvbihjZCkge1xuICAgICAgICB2YXIgcGxvdEdyb3VwID0gZDMuc2VsZWN0KHRoaXMpO1xuICAgICAgICB2YXIgdHJhY2UgPSBjZFswXS50cmFjZTtcblxuICAgICAgICB2YXIgZ3JvdXAgPSBMaWIuZW5zdXJlU2luZ2xlKHBsb3RHcm91cCwgJ2cnLCAnbGluZXMnKTtcblxuICAgICAgICBpZighdHJhY2UuY29ubmVjdG9yIHx8ICF0cmFjZS5jb25uZWN0b3IudmlzaWJsZSkge1xuICAgICAgICAgICAgZ3JvdXAucmVtb3ZlKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaXNIb3Jpem9udGFsID0gKHRyYWNlLm9yaWVudGF0aW9uID09PSAnaCcpO1xuICAgICAgICB2YXIgbW9kZSA9IHRyYWNlLmNvbm5lY3Rvci5tb2RlO1xuXG4gICAgICAgIHZhciBjb25uZWN0b3JzID0gZ3JvdXAuc2VsZWN0QWxsKCdnLmxpbmUnKS5kYXRhKExpYi5pZGVudGl0eSk7XG5cbiAgICAgICAgY29ubmVjdG9ycy5lbnRlcigpLmFwcGVuZCgnZycpXG4gICAgICAgICAgICAuY2xhc3NlZCgnbGluZScsIHRydWUpO1xuXG4gICAgICAgIGNvbm5lY3RvcnMuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgICAgIHZhciBsZW4gPSBjb25uZWN0b3JzLnNpemUoKTtcblxuICAgICAgICBjb25uZWN0b3JzLmVhY2goZnVuY3Rpb24oZGksIGkpIHtcbiAgICAgICAgICAgIC8vIGRvbid0IGRyYXcgbGluZXMgYmV0d2VlbiBudWxsc1xuICAgICAgICAgICAgaWYoaSAhPT0gbGVuIC0gMSAmJiAhZGkuY05leHQpIHJldHVybjtcblxuICAgICAgICAgICAgdmFyIHh5ID0gZ2V0WFkoZGksIHhhLCB5YSwgaXNIb3Jpem9udGFsKTtcbiAgICAgICAgICAgIHZhciB4ID0geHlbMF07XG4gICAgICAgICAgICB2YXIgeSA9IHh5WzFdO1xuXG4gICAgICAgICAgICB2YXIgc2hhcGUgPSAnJztcblxuICAgICAgICAgICAgaWYobW9kZSA9PT0gJ3NwYW5uaW5nJykge1xuICAgICAgICAgICAgICAgIGlmKCFkaS5pc1N1bSAmJiBpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBpZihpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlICs9ICdNJyArIHhbMF0gKyAnLCcgKyB5WzFdICsgJ1YnICsgeVswXTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlICs9ICdNJyArIHhbMV0gKyAnLCcgKyB5WzBdICsgJ0gnICsgeFswXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYobW9kZSAhPT0gJ2JldHdlZW4nKSB7XG4gICAgICAgICAgICAgICAgaWYoZGkuaXNTdW0gfHwgaSA8IGxlbiAtIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYoaXNIb3Jpem9udGFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaGFwZSArPSAnTScgKyB4WzFdICsgJywnICsgeVswXSArICdWJyArIHlbMV07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaGFwZSArPSAnTScgKyB4WzBdICsgJywnICsgeVsxXSArICdIJyArIHhbMV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHhbMl0gIT09IHVuZGVmaW5lZCAmJiB5WzJdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZihpc0hvcml6b250YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgc2hhcGUgKz0gJ00nICsgeFsxXSArICcsJyArIHlbMV0gKyAnVicgKyB5WzJdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNoYXBlICs9ICdNJyArIHhbMV0gKyAnLCcgKyB5WzFdICsgJ0gnICsgeFsyXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHNoYXBlID09PSAnJykgc2hhcGUgPSAnTTAsMFonO1xuXG4gICAgICAgICAgICBMaWIuZW5zdXJlU2luZ2xlKGQzLnNlbGVjdCh0aGlzKSwgJ3BhdGgnKVxuICAgICAgICAgICAgICAgIC5hdHRyKCdkJywgc2hhcGUpXG4gICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5zZXRDbGlwVXJsLCBwbG90aW5mby5sYXllckNsaXBJZCwgZ2QpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZ2V0WFkoZGksIHhhLCB5YSwgaXNIb3Jpem9udGFsKSB7XG4gICAgdmFyIHMgPSBbXTtcbiAgICB2YXIgcCA9IFtdO1xuXG4gICAgdmFyIHNBeGlzID0gaXNIb3Jpem9udGFsID8geGEgOiB5YTtcbiAgICB2YXIgcEF4aXMgPSBpc0hvcml6b250YWwgPyB5YSA6IHhhO1xuXG4gICAgc1swXSA9IHNBeGlzLmMycChkaS5zMCwgdHJ1ZSk7XG4gICAgcFswXSA9IHBBeGlzLmMycChkaS5wMCwgdHJ1ZSk7XG5cbiAgICBzWzFdID0gc0F4aXMuYzJwKGRpLnMxLCB0cnVlKTtcbiAgICBwWzFdID0gcEF4aXMuYzJwKGRpLnAxLCB0cnVlKTtcblxuICAgIHNbMl0gPSBzQXhpcy5jMnAoZGkubmV4dFMwLCB0cnVlKTtcbiAgICBwWzJdID0gcEF4aXMuYzJwKGRpLm5leHRQMCwgdHJ1ZSk7XG5cbiAgICByZXR1cm4gaXNIb3Jpem9udGFsID8gW3MsIHBdIDogW3AsIHNdO1xufVxuXG59LHtcIi4uLy4uL2NvbXBvbmVudHMvZHJhd2luZ1wiOjYxNCxcIi4uLy4uL2xpYlwiOjcxOSxcIi4uL2Jhci9wbG90XCI6ODY3LFwiZDNcIjoxNjN9XSwxMjY0OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIGQzID0gX2RlcmVxXygnZDMnKTtcblxudmFyIERyYXdpbmcgPSBfZGVyZXFfKCcuLi8uLi9jb21wb25lbnRzL2RyYXdpbmcnKTtcbnZhciBDb2xvciA9IF9kZXJlcV8oJy4uLy4uL2NvbXBvbmVudHMvY29sb3InKTtcbnZhciBERVNFTEVDVERJTSA9IF9kZXJlcV8oJy4uLy4uL2NvbnN0YW50cy9pbnRlcmFjdGlvbnMnKS5ERVNFTEVDVERJTTtcblxudmFyIHN0eWxlVGV4dFBvaW50cyA9IF9kZXJlcV8oJy4uL2Jhci9zdHlsZScpLnN0eWxlVGV4dFBvaW50cztcblxuZnVuY3Rpb24gc3R5bGUoZ2QsIGNkLCBzZWwpIHtcbiAgICB2YXIgcyA9IHNlbCA/IHNlbCA6IGQzLnNlbGVjdChnZCkuc2VsZWN0QWxsKCdnLndhdGVyZmFsbGxheWVyJykuc2VsZWN0QWxsKCdnLnRyYWNlJyk7XG5cbiAgICBzLnN0eWxlKCdvcGFjaXR5JywgZnVuY3Rpb24oZCkgeyByZXR1cm4gZFswXS50cmFjZS5vcGFjaXR5OyB9KTtcblxuICAgIHMuZWFjaChmdW5jdGlvbihkKSB7XG4gICAgICAgIHZhciBnVHJhY2UgPSBkMy5zZWxlY3QodGhpcyk7XG4gICAgICAgIHZhciB0cmFjZSA9IGRbMF0udHJhY2U7XG5cbiAgICAgICAgZ1RyYWNlLnNlbGVjdEFsbCgnLnBvaW50ID4gcGF0aCcpLmVhY2goZnVuY3Rpb24oZGkpIHtcbiAgICAgICAgICAgIGlmKCFkaS5pc0JsYW5rKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnQgPSB0cmFjZVtkaS5kaXJdLm1hcmtlcjtcblxuICAgICAgICAgICAgICAgIGQzLnNlbGVjdCh0aGlzKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5maWxsLCBjb250LmNvbG9yKVxuICAgICAgICAgICAgICAgICAgICAuY2FsbChDb2xvci5zdHJva2UsIGNvbnQubGluZS5jb2xvcilcbiAgICAgICAgICAgICAgICAgICAgLmNhbGwoRHJhd2luZy5kYXNoTGluZSwgY29udC5saW5lLmRhc2gsIGNvbnQubGluZS53aWR0aClcbiAgICAgICAgICAgICAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgdHJhY2Uuc2VsZWN0ZWRwb2ludHMgJiYgIWRpLnNlbGVjdGVkID8gREVTRUxFQ1RESU0gOiAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3R5bGVUZXh0UG9pbnRzKGdUcmFjZSwgdHJhY2UsIGdkKTtcblxuICAgICAgICBnVHJhY2Uuc2VsZWN0QWxsKCcubGluZXMnKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGNvbnQgPSB0cmFjZS5jb25uZWN0b3IubGluZTtcblxuICAgICAgICAgICAgRHJhd2luZy5saW5lR3JvdXBTdHlsZShcbiAgICAgICAgICAgICAgICBkMy5zZWxlY3QodGhpcykuc2VsZWN0QWxsKCdwYXRoJyksXG4gICAgICAgICAgICAgICAgY29udC53aWR0aCxcbiAgICAgICAgICAgICAgICBjb250LmNvbG9yLFxuICAgICAgICAgICAgICAgIGNvbnQuZGFzaFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHN0eWxlOiBzdHlsZVxufTtcblxufSx7XCIuLi8uLi9jb21wb25lbnRzL2NvbG9yXCI6NTkzLFwiLi4vLi4vY29tcG9uZW50cy9kcmF3aW5nXCI6NjE0LFwiLi4vLi4vY29uc3RhbnRzL2ludGVyYWN0aW9uc1wiOjY5NCxcIi4uL2Jhci9zdHlsZVwiOjg3MCxcImQzXCI6MTYzfV0sMTI2NTpbZnVuY3Rpb24oX2RlcmVxXyxtb2R1bGUsZXhwb3J0cyl7XG4vKipcbiogQ29weXJpZ2h0IDIwMTItMjAxOSwgUGxvdGx5LCBJbmMuXG4qIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4qXG4qIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4qL1xuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBBeGVzID0gX2RlcmVxXygnLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXMnKTtcbnZhciBMaWIgPSBfZGVyZXFfKCcuLi9saWInKTtcbnZhciBQbG90U2NoZW1hID0gX2RlcmVxXygnLi4vcGxvdF9hcGkvcGxvdF9zY2hlbWEnKTtcbnZhciBwb2ludHNBY2Nlc3NvckZ1bmN0aW9uID0gX2RlcmVxXygnLi9oZWxwZXJzJykucG9pbnRzQWNjZXNzb3JGdW5jdGlvbjtcbnZhciBCQUROVU0gPSBfZGVyZXFfKCcuLi9jb25zdGFudHMvbnVtZXJpY2FsJykuQkFETlVNO1xuXG5leHBvcnRzLm1vZHVsZVR5cGUgPSAndHJhbnNmb3JtJztcblxuZXhwb3J0cy5uYW1lID0gJ2FnZ3JlZ2F0ZSc7XG5cbnZhciBhdHRycyA9IGV4cG9ydHMuYXR0cmlidXRlcyA9IHtcbiAgICBlbmFibGVkOiB7XG4gICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgZGZsdDogdHJ1ZSxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgZ3JvdXBzOiB7XG4gICAgICAgIC8vIFRPRE86IGdyb3VwYnkgc2hvdWxkIHN1cHBvcnQgc3RyaW5nIG9yIGFycmF5IGdyb3VwaW5nIHRoaXMgd2F5IHRvb1xuICAgICAgICAvLyBjdXJyZW50bHkgZ3JvdXBieSBvbmx5IGFsbG93cyBhIGdyb3VwaW5nIGFycmF5XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBzdHJpY3Q6IHRydWUsXG4gICAgICAgIG5vQmxhbms6IHRydWUsXG4gICAgICAgIGFycmF5T2s6IHRydWUsXG4gICAgICAgIGRmbHQ6ICd4JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgYWdncmVnYXRpb25zOiB7XG4gICAgICAgIF9pc0xpbmtlZFRvQXJyYXk6ICdhZ2dyZWdhdGlvbicsXG4gICAgICAgIHRhcmdldDoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZnVuYzoge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2VudW1lcmF0ZWQnLFxuICAgICAgICAgICAgdmFsdWVzOiBbJ2NvdW50JywgJ3N1bScsICdhdmcnLCAnbWVkaWFuJywgJ21vZGUnLCAncm1zJywgJ3N0ZGRldicsICdtaW4nLCAnbWF4JywgJ2ZpcnN0JywgJ2xhc3QnLCAnY2hhbmdlJywgJ3JhbmdlJ10sXG4gICAgICAgICAgICBkZmx0OiAnZmlyc3QnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmNtb2RlOiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgICAgICB2YWx1ZXM6IFsnc2FtcGxlJywgJ3BvcHVsYXRpb24nXSxcbiAgICAgICAgICAgIGRmbHQ6ICdzYW1wbGUnLFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICAgICAgXG4gICAgICAgIH0sXG4gICAgICAgIGVuYWJsZWQ6IHtcbiAgICAgICAgICAgIHZhbFR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgICAgICBcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufTtcblxudmFyIGFnZ0F0dHJzID0gYXR0cnMuYWdncmVnYXRpb25zO1xuXG4vKipcbiAqIFN1cHBseSB0cmFuc2Zvcm0gYXR0cmlidXRlcyBkZWZhdWx0c1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSB0cmFuc2Zvcm1JblxuICogIG9iamVjdCBsaW5rZWQgdG8gdHJhY2UudHJhbnNmb3Jtc1tpXSB3aXRoICdmdW5jJyBzZXQgdG8gZXhwb3J0cy5uYW1lXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2VPdXRcbiAqICB0aGUgX2Z1bGxEYXRhIHRyYWNlIHRoaXMgdHJhbnNmb3JtIGFwcGxpZXMgdG9cbiAqIEBwYXJhbSB7b2JqZWN0fSBsYXlvdXRcbiAqICB0aGUgcGxvdCdzIChub3Qtc28tZnVsbCkgbGF5b3V0XG4gKiBAcGFyYW0ge29iamVjdH0gdHJhY2VJblxuICogIHRoZSBpbnB1dCBkYXRhIHRyYWNlIHRoaXMgdHJhbnNmb3JtIGFwcGxpZXMgdG9cbiAqXG4gKiBAcmV0dXJuIHtvYmplY3R9IHRyYW5zZm9ybU91dFxuICogIGNvcHkgb2YgdHJhbnNmb3JtSW4gdGhhdCBjb250YWlucyBhdHRyaWJ1dGUgZGVmYXVsdHNcbiAqL1xuZXhwb3J0cy5zdXBwbHlEZWZhdWx0cyA9IGZ1bmN0aW9uKHRyYW5zZm9ybUluLCB0cmFjZU91dCkge1xuICAgIHZhciB0cmFuc2Zvcm1PdXQgPSB7fTtcbiAgICB2YXIgaTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYW5zZm9ybUluLCB0cmFuc2Zvcm1PdXQsIGF0dHJzLCBhdHRyLCBkZmx0KTtcbiAgICB9XG5cbiAgICB2YXIgZW5hYmxlZCA9IGNvZXJjZSgnZW5hYmxlZCcpO1xuXG4gICAgaWYoIWVuYWJsZWQpIHJldHVybiB0cmFuc2Zvcm1PdXQ7XG5cbiAgICAvKlxuICAgICAqIE5vcm1hbGx5IF9hcnJheUF0dHJzIGlzIGNhbGN1bGF0ZWQgZHVyaW5nIGRvQ2FsYywgYnV0IHRoYXQgY29tZXMgbGF0ZXIuXG4gICAgICogQW55d2F5IHRoaXMgY2FuIGNoYW5nZSBkdWUgdG8gKmNvdW50KiBhZ2dyZWdhdGlvbnMgKHNlZSBiZWxvdykgc28gaXQncyBub3RcbiAgICAgKiBuZWNlc3NhcmlseSB0aGUgc2FtZSBzZXQuXG4gICAgICpcbiAgICAgKiBGb3IgcGVyZm9ybWFuY2Ugd2UgdHVybiBpdCBpbnRvIGFuIG9iamVjdCBvZiB0cnV0aHkgdmFsdWVzXG4gICAgICogd2UnbGwgdXNlIDEgZm9yIGFycmF5cyB3ZSBoYXZlbid0IGFnZ3JlZ2F0ZWQgeWV0LCAwIGZvciBmaW5pc2hlZCBhcnJheXMsXG4gICAgICogYXMgZGlzdGluY3QgZnJvbSB1bmRlZmluZWQgd2hpY2ggbWVhbnMgdGhpcyBhcnJheSBpc24ndCBwcmVzZW50IGluIHRoZSBpbnB1dFxuICAgICAqIG1pc3NpbmcgYXJyYXlzIGNhbiBzdGlsbCBiZSBhZ2dyZWdhdGUgb3V0cHV0cyBmb3IgKmNvdW50KiBhZ2dyZWdhdGlvbnMuXG4gICAgICovXG4gICAgdmFyIGFycmF5QXR0ckFycmF5ID0gUGxvdFNjaGVtYS5maW5kQXJyYXlBdHRyaWJ1dGVzKHRyYWNlT3V0KTtcbiAgICB2YXIgYXJyYXlBdHRycyA9IHt9O1xuICAgIGZvcihpID0gMDsgaSA8IGFycmF5QXR0ckFycmF5Lmxlbmd0aDsgaSsrKSBhcnJheUF0dHJzW2FycmF5QXR0ckFycmF5W2ldXSA9IDE7XG5cbiAgICB2YXIgZ3JvdXBzID0gY29lcmNlKCdncm91cHMnKTtcblxuICAgIGlmKCFBcnJheS5pc0FycmF5KGdyb3VwcykpIHtcbiAgICAgICAgaWYoIWFycmF5QXR0cnNbZ3JvdXBzXSkge1xuICAgICAgICAgICAgdHJhbnNmb3JtT3V0LmVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1PdXQ7XG4gICAgICAgIH1cbiAgICAgICAgYXJyYXlBdHRyc1tncm91cHNdID0gMDtcbiAgICB9XG5cbiAgICB2YXIgYWdncmVnYXRpb25zSW4gPSB0cmFuc2Zvcm1Jbi5hZ2dyZWdhdGlvbnMgfHwgW107XG4gICAgdmFyIGFnZ3JlZ2F0aW9uc091dCA9IHRyYW5zZm9ybU91dC5hZ2dyZWdhdGlvbnMgPSBuZXcgQXJyYXkoYWdncmVnYXRpb25zSW4ubGVuZ3RoKTtcbiAgICB2YXIgYWdncmVnYXRpb25PdXQ7XG5cbiAgICBmdW5jdGlvbiBjb2VyY2VpKGF0dHIsIGRmbHQpIHtcbiAgICAgICAgcmV0dXJuIExpYi5jb2VyY2UoYWdncmVnYXRpb25zSW5baV0sIGFnZ3JlZ2F0aW9uT3V0LCBhZ2dBdHRycywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgYWdncmVnYXRpb25zSW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYWdncmVnYXRpb25PdXQgPSB7X2luZGV4OiBpfTtcbiAgICAgICAgdmFyIHRhcmdldCA9IGNvZXJjZWkoJ3RhcmdldCcpO1xuICAgICAgICB2YXIgZnVuYyA9IGNvZXJjZWkoJ2Z1bmMnKTtcbiAgICAgICAgdmFyIGVuYWJsZWRpID0gY29lcmNlaSgnZW5hYmxlZCcpO1xuXG4gICAgICAgIC8vIGFkZCB0aGlzIGFnZ3JlZ2F0aW9uIHRvIHRoZSBvdXRwdXQgb25seSBpZiBpdCdzIHRoZSBmaXJzdCBpbnN0YW5jZVxuICAgICAgICAvLyBvZiBhIHZhbGlkIHRhcmdldCBhdHRyaWJ1dGUgLSBvciBhbiB1bnVzZWQgdGFyZ2V0IGF0dHJpYnV0ZSB3aXRoIFwiY291bnRcIlxuICAgICAgICBpZihlbmFibGVkaSAmJiB0YXJnZXQgJiYgKGFycmF5QXR0cnNbdGFyZ2V0XSB8fCAoZnVuYyA9PT0gJ2NvdW50JyAmJiBhcnJheUF0dHJzW3RhcmdldF0gPT09IHVuZGVmaW5lZCkpKSB7XG4gICAgICAgICAgICBpZihmdW5jID09PSAnc3RkZGV2JykgY29lcmNlaSgnZnVuY21vZGUnKTtcblxuICAgICAgICAgICAgYXJyYXlBdHRyc1t0YXJnZXRdID0gMDtcbiAgICAgICAgICAgIGFnZ3JlZ2F0aW9uc091dFtpXSA9IGFnZ3JlZ2F0aW9uT3V0O1xuICAgICAgICB9IGVsc2UgYWdncmVnYXRpb25zT3V0W2ldID0ge2VuYWJsZWQ6IGZhbHNlLCBfaW5kZXg6IGl9O1xuICAgIH1cblxuICAgIC8vIGFueSBhcnJheSBhdHRyaWJ1dGVzIHdlIGhhdmVuJ3QgeWV0IGNvdmVyZWQsIGZpbGwgdGhlbSB3aXRoIHRoZSBkZWZhdWx0IGFnZ3JlZ2F0aW9uXG4gICAgZm9yKGkgPSAwOyBpIDwgYXJyYXlBdHRyQXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoYXJyYXlBdHRyc1thcnJheUF0dHJBcnJheVtpXV0pIHtcbiAgICAgICAgICAgIGFnZ3JlZ2F0aW9uc091dC5wdXNoKHtcbiAgICAgICAgICAgICAgICB0YXJnZXQ6IGFycmF5QXR0ckFycmF5W2ldLFxuICAgICAgICAgICAgICAgIGZ1bmM6IGFnZ0F0dHJzLmZ1bmMuZGZsdCxcbiAgICAgICAgICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICAgICAgICAgIF9pbmRleDogLTFcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyYW5zZm9ybU91dDtcbn07XG5cblxuZXhwb3J0cy5jYWxjVHJhbnNmb3JtID0gZnVuY3Rpb24oZ2QsIHRyYWNlLCBvcHRzKSB7XG4gICAgaWYoIW9wdHMuZW5hYmxlZCkgcmV0dXJuO1xuXG4gICAgdmFyIGdyb3VwcyA9IG9wdHMuZ3JvdXBzO1xuXG4gICAgdmFyIGdyb3VwQXJyYXkgPSBMaWIuZ2V0VGFyZ2V0QXJyYXkodHJhY2UsIHt0YXJnZXQ6IGdyb3Vwc30pO1xuICAgIGlmKCFncm91cEFycmF5KSByZXR1cm47XG5cbiAgICB2YXIgaSwgdmksIGdyb3VwSW5kZXgsIG5ld0dyb3VwaW5nO1xuXG4gICAgdmFyIGdyb3VwSW5kaWNlcyA9IHt9O1xuICAgIHZhciBpbmRleFRvUG9pbnRzID0ge307XG4gICAgdmFyIGdyb3VwaW5ncyA9IFtdO1xuXG4gICAgdmFyIG9yaWdpbmFsUG9pbnRzQWNjZXNzb3IgPSBwb2ludHNBY2Nlc3NvckZ1bmN0aW9uKHRyYWNlLnRyYW5zZm9ybXMsIG9wdHMpO1xuXG4gICAgdmFyIGxlbiA9IGdyb3VwQXJyYXkubGVuZ3RoO1xuICAgIGlmKHRyYWNlLl9sZW5ndGgpIGxlbiA9IE1hdGgubWluKGxlbiwgdHJhY2UuX2xlbmd0aCk7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2aSA9IGdyb3VwQXJyYXlbaV07XG4gICAgICAgIGdyb3VwSW5kZXggPSBncm91cEluZGljZXNbdmldO1xuICAgICAgICBpZihncm91cEluZGV4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGdyb3VwSW5kaWNlc1t2aV0gPSBncm91cGluZ3MubGVuZ3RoO1xuICAgICAgICAgICAgbmV3R3JvdXBpbmcgPSBbaV07XG4gICAgICAgICAgICBncm91cGluZ3MucHVzaChuZXdHcm91cGluZyk7XG4gICAgICAgICAgICBpbmRleFRvUG9pbnRzW2dyb3VwSW5kaWNlc1t2aV1dID0gb3JpZ2luYWxQb2ludHNBY2Nlc3NvcihpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdyb3VwaW5nc1tncm91cEluZGV4XS5wdXNoKGkpO1xuICAgICAgICAgICAgaW5kZXhUb1BvaW50c1tncm91cEluZGljZXNbdmldXSA9IChpbmRleFRvUG9pbnRzW2dyb3VwSW5kaWNlc1t2aV1dIHx8IFtdKS5jb25jYXQob3JpZ2luYWxQb2ludHNBY2Nlc3NvcihpKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvcHRzLl9pbmRleFRvUG9pbnRzID0gaW5kZXhUb1BvaW50cztcblxuICAgIHZhciBhZ2dyZWdhdGlvbnMgPSBvcHRzLmFnZ3JlZ2F0aW9ucztcblxuICAgIGZvcihpID0gMDsgaSA8IGFnZ3JlZ2F0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBhZ2dyZWdhdGVPbmVBcnJheShnZCwgdHJhY2UsIGdyb3VwaW5ncywgYWdncmVnYXRpb25zW2ldKTtcbiAgICB9XG5cbiAgICBpZih0eXBlb2YgZ3JvdXBzID09PSAnc3RyaW5nJykge1xuICAgICAgICBhZ2dyZWdhdGVPbmVBcnJheShnZCwgdHJhY2UsIGdyb3VwaW5ncywge1xuICAgICAgICAgICAgdGFyZ2V0OiBncm91cHMsXG4gICAgICAgICAgICBmdW5jOiAnZmlyc3QnLFxuICAgICAgICAgICAgZW5hYmxlZDogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB0cmFjZS5fbGVuZ3RoID0gZ3JvdXBpbmdzLmxlbmd0aDtcbn07XG5cbmZ1bmN0aW9uIGFnZ3JlZ2F0ZU9uZUFycmF5KGdkLCB0cmFjZSwgZ3JvdXBpbmdzLCBhZ2dyZWdhdGlvbikge1xuICAgIGlmKCFhZ2dyZWdhdGlvbi5lbmFibGVkKSByZXR1cm47XG5cbiAgICB2YXIgYXR0ciA9IGFnZ3JlZ2F0aW9uLnRhcmdldDtcbiAgICB2YXIgdGFyZ2V0TlAgPSBMaWIubmVzdGVkUHJvcGVydHkodHJhY2UsIGF0dHIpO1xuICAgIHZhciBhcnJheUluID0gdGFyZ2V0TlAuZ2V0KCk7XG4gICAgdmFyIGNvbnZlcnNpb25zID0gQXhlcy5nZXREYXRhQ29udmVyc2lvbnMoZ2QsIHRyYWNlLCBhdHRyLCBhcnJheUluKTtcbiAgICB2YXIgZnVuYyA9IGdldEFnZ3JlZ2F0ZUZ1bmN0aW9uKGFnZ3JlZ2F0aW9uLCBjb252ZXJzaW9ucyk7XG5cbiAgICB2YXIgYXJyYXlPdXQgPSBuZXcgQXJyYXkoZ3JvdXBpbmdzLmxlbmd0aCk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGdyb3VwaW5ncy5sZW5ndGg7IGkrKykge1xuICAgICAgICBhcnJheU91dFtpXSA9IGZ1bmMoYXJyYXlJbiwgZ3JvdXBpbmdzW2ldKTtcbiAgICB9XG4gICAgdGFyZ2V0TlAuc2V0KGFycmF5T3V0KTtcblxuICAgIGlmKGFnZ3JlZ2F0aW9uLmZ1bmMgPT09ICdjb3VudCcpIHtcbiAgICAgICAgLy8gY291bnQgZG9lcyBub3QgZGVwZW5kIG9uIGFuIGlucHV0IGFycmF5LCBzbyBpdCdzIGxpa2VseSBub3QgcGFydCBvZiBfYXJyYXlBdHRycyB5ZXRcbiAgICAgICAgLy8gYnV0IGFmdGVyIHRoaXMgdHJhbnNmb3JtIGl0IG1vc3QgZGVmaW5pdGVseSAqaXMqIGFuIGFycmF5IGF0dHJpYnV0ZS5cbiAgICAgICAgTGliLnB1c2hVbmlxdWUodHJhY2UuX2FycmF5QXR0cnMsIGF0dHIpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0QWdncmVnYXRlRnVuY3Rpb24ob3B0cywgY29udmVyc2lvbnMpIHtcbiAgICB2YXIgZnVuYyA9IG9wdHMuZnVuYztcbiAgICB2YXIgZDJjID0gY29udmVyc2lvbnMuZDJjO1xuICAgIHZhciBjMmQgPSBjb252ZXJzaW9ucy5jMmQ7XG5cbiAgICBzd2l0Y2goZnVuYykge1xuICAgICAgICAvLyBjb3VudCwgZmlyc3QsIGFuZCBsYXN0IGRvbid0IGRlcGVuZCBvbiBhbnl0aGluZyBhYm91dCB0aGUgZGF0YVxuICAgICAgICAvLyBwb2ludCBiYWNrIHRvIHB1cmUgZnVuY3Rpb25zIGZvciBwZXJmb3JtYW5jZVxuICAgICAgICBjYXNlICdjb3VudCc6XG4gICAgICAgICAgICByZXR1cm4gY291bnQ7XG4gICAgICAgIGNhc2UgJ2ZpcnN0JzpcbiAgICAgICAgICAgIHJldHVybiBmaXJzdDtcbiAgICAgICAgY2FzZSAnbGFzdCc6XG4gICAgICAgICAgICByZXR1cm4gbGFzdDtcblxuICAgICAgICBjYXNlICdzdW0nOlxuICAgICAgICAgICAgLy8gVGhpcyB3aWxsIHByb2R1Y2Ugb3V0cHV0IGluIGFsbCBjYXNlcyBldmVuIHRob3VnaCBpdCdzIG5vbnNlbnNpY2FsXG4gICAgICAgICAgICAvLyBmb3IgZGF0ZSBvciBjYXRlZ29yeSBkYXRhLlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBpbmRpY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvdGFsID0gMDtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmkgPSBkMmMoYXJyYXlbaW5kaWNlc1tpXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih2aSAhPT0gQkFETlVNKSB0b3RhbCArPSB2aTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGMyZCh0b3RhbCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJ2F2Zyc6XG4gICAgICAgICAgICAvLyBHZW5lcmFsbHkgbWVhbmluZ2xlc3MgZm9yIGNhdGVnb3J5IGRhdGEgYnV0IGl0IHN0aWxsIGRvZXMgc29tZXRoaW5nLlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBpbmRpY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvdGFsID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgY250ID0gMDtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmkgPSBkMmMoYXJyYXlbaW5kaWNlc1tpXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih2aSAhPT0gQkFETlVNKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b3RhbCArPSB2aTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNudCsrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBjbnQgPyBjMmQodG90YWwgLyBjbnQpIDogQkFETlVNO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICBjYXNlICdtaW4nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBpbmRpY2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIG91dCA9IEluZmluaXR5O1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2aSA9IGQyYyhhcnJheVtpbmRpY2VzW2ldXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHZpICE9PSBCQUROVU0pIG91dCA9IE1hdGgubWluKG91dCwgdmkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gKG91dCA9PT0gSW5maW5pdHkpID8gQkFETlVNIDogYzJkKG91dCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJ21heCc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIGluZGljZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgb3V0ID0gLUluZmluaXR5O1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2aSA9IGQyYyhhcnJheVtpbmRpY2VzW2ldXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHZpICE9PSBCQUROVU0pIG91dCA9IE1hdGgubWF4KG91dCwgdmkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gKG91dCA9PT0gLUluZmluaXR5KSA/IEJBRE5VTSA6IGMyZChvdXQpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICBjYXNlICdyYW5nZSc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIGluZGljZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbWluID0gSW5maW5pdHk7XG4gICAgICAgICAgICAgICAgdmFyIG1heCA9IC1JbmZpbml0eTtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmkgPSBkMmMoYXJyYXlbaW5kaWNlc1tpXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZih2aSAhPT0gQkFETlVNKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW4gPSBNYXRoLm1pbihtaW4sIHZpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heCA9IE1hdGgubWF4KG1heCwgdmkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiAobWF4ID09PSAtSW5maW5pdHkgfHwgbWluID09PSBJbmZpbml0eSkgPyBCQUROVU0gOiBjMmQobWF4IC0gbWluKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnY2hhbmdlJzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgaW5kaWNlcykge1xuICAgICAgICAgICAgICAgIHZhciBmaXJzdCA9IGQyYyhhcnJheVtpbmRpY2VzWzBdXSk7XG4gICAgICAgICAgICAgICAgdmFyIGxhc3QgPSBkMmMoYXJyYXlbaW5kaWNlc1tpbmRpY2VzLmxlbmd0aCAtIDFdXSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChmaXJzdCA9PT0gQkFETlVNIHx8IGxhc3QgPT09IEJBRE5VTSkgPyBCQUROVU0gOiBjMmQobGFzdCAtIGZpcnN0KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnbWVkaWFuJzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgaW5kaWNlcykge1xuICAgICAgICAgICAgICAgIHZhciBzb3J0Q2FsYyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2aSA9IGQyYyhhcnJheVtpbmRpY2VzW2ldXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHZpICE9PSBCQUROVU0pIHNvcnRDYWxjLnB1c2godmkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZighc29ydENhbGMubGVuZ3RoKSByZXR1cm4gQkFETlVNO1xuICAgICAgICAgICAgICAgIHNvcnRDYWxjLnNvcnQoKTtcbiAgICAgICAgICAgICAgICB2YXIgbWlkID0gKHNvcnRDYWxjLmxlbmd0aCAtIDEpIC8gMjtcbiAgICAgICAgICAgICAgICByZXR1cm4gYzJkKChzb3J0Q2FsY1tNYXRoLmZsb29yKG1pZCldICsgc29ydENhbGNbTWF0aC5jZWlsKG1pZCldKSAvIDIpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICBjYXNlICdtb2RlJzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgaW5kaWNlcykge1xuICAgICAgICAgICAgICAgIHZhciBjb3VudHMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWF4Q250ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgb3V0ID0gQkFETlVNO1xuICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2aSA9IGQyYyhhcnJheVtpbmRpY2VzW2ldXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHZpICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjb3VudGkgPSBjb3VudHNbdmldID0gKGNvdW50c1t2aV0gfHwgMCkgKyAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoY291bnRpID4gbWF4Q250KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4Q250ID0gY291bnRpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dCA9IHZpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtYXhDbnQgPyBjMmQob3V0KSA6IEJBRE5VTTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAncm1zJzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgaW5kaWNlcykge1xuICAgICAgICAgICAgICAgIHZhciB0b3RhbCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGNudCA9IDA7XG4gICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpID0gZDJjKGFycmF5W2luZGljZXNbaV1dKTtcbiAgICAgICAgICAgICAgICAgICAgaWYodmkgIT09IEJBRE5VTSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG90YWwgKz0gdmkgKiB2aTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNudCsrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBjbnQgPyBjMmQoTWF0aC5zcXJ0KHRvdGFsIC8gY250KSkgOiBCQUROVU07XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJ3N0ZGRldic6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIGluZGljZXMpIHtcbiAgICAgICAgICAgICAgICAvLyBiYWxhbmNlIG51bWVyaWNhbCBzdGFiaWxpdHkgd2l0aCBwZXJmb3JtYW5jZTpcbiAgICAgICAgICAgICAgICAvLyBzbyB0aGF0IHdlIGNhbGwgZDJjIG9uY2UgcGVyIGVsZW1lbnQgYnV0IGRvbid0IG5lZWQgdG9cbiAgICAgICAgICAgICAgICAvLyBzdG9yZSB0aGVtLCByZWZlcmVuY2UgYWxsIHRvIHRoZSBmaXJzdCBlbGVtZW50XG4gICAgICAgICAgICAgICAgdmFyIHRvdGFsID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgdG90YWwyID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgY250ID0gMTtcbiAgICAgICAgICAgICAgICB2YXIgdjAgPSBCQUROVU07XG4gICAgICAgICAgICAgICAgdmFyIGk7XG4gICAgICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGggJiYgdjAgPT09IEJBRE5VTTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHYwID0gZDJjKGFycmF5W2luZGljZXNbaV1dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYodjAgPT09IEJBRE5VTSkgcmV0dXJuIEJBRE5VTTtcblxuICAgICAgICAgICAgICAgIGZvcig7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2aSA9IGQyYyhhcnJheVtpbmRpY2VzW2ldXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKHZpICE9PSBCQUROVU0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkdiA9IHZpIC0gdjA7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b3RhbCArPSBkdjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsMiArPSBkdiAqIGR2O1xuICAgICAgICAgICAgICAgICAgICAgICAgY250Kys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBUaGlzIGlzIHBvcHVsYXRpb24gc3RkIGRldiwgaWYgd2Ugd2FudCBzYW1wbGUgc3RkIGRldlxuICAgICAgICAgICAgICAgIC8vIHdlIHdvdWxkIG5lZWQgKC4uLikgLyAoY250IC0gMSlcbiAgICAgICAgICAgICAgICAvLyBBbHNvIG5vdGUgdGhlcmUncyBubyBjMmQgaGVyZSAtIHRoYXQgbWVhbnMgZm9yIGRhdGVzIHRoZSByZXN1bHRcbiAgICAgICAgICAgICAgICAvLyBpcyBhIG51bWJlciBvZiBtaWxsaXNlY29uZHMsIGFuZCBmb3IgY2F0ZWdvcmllcyBpdCdzIGEgbnVtYmVyXG4gICAgICAgICAgICAgICAgLy8gb2YgY2F0ZWdvcnkgZGlmZmVyZW5jZXMsIHdoaWNoIGlzIG5vdCBnZW5lcmljYWxseSBtZWFuaW5nZnVsIGJ1dFxuICAgICAgICAgICAgICAgIC8vIGFzIGluIG90aGVyIGNhc2VzIHdlIGRvbid0IGZvcmJpZCBpdC5cbiAgICAgICAgICAgICAgICB2YXIgbm9ybSA9IChvcHRzLmZ1bmNtb2RlID09PSAnc2FtcGxlJykgPyAoY250IC0gMSkgOiBjbnQ7XG4gICAgICAgICAgICAgICAgLy8gdGhpcyBpcyBkZWJhdGFibGU6IHNob3VsZCBhIGNvdW50IG9mIDEgcmV0dXJuIHNhbXBsZSBzdGRkZXYgb2ZcbiAgICAgICAgICAgICAgICAvLyAwIG9yIHVuZGVmaW5lZD9cbiAgICAgICAgICAgICAgICBpZighbm9ybSkgcmV0dXJuIDA7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE1hdGguc3FydCgodG90YWwyIC0gKHRvdGFsICogdG90YWwgLyBjbnQpKSAvIG5vcm0pO1xuICAgICAgICAgICAgfTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNvdW50KGFycmF5LCBpbmRpY2VzKSB7XG4gICAgcmV0dXJuIGluZGljZXMubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBmaXJzdChhcnJheSwgaW5kaWNlcykge1xuICAgIHJldHVybiBhcnJheVtpbmRpY2VzWzBdXTtcbn1cblxuZnVuY3Rpb24gbGFzdChhcnJheSwgaW5kaWNlcykge1xuICAgIHJldHVybiBhcnJheVtpbmRpY2VzW2luZGljZXMubGVuZ3RoIC0gMV1dO1xufVxuXG59LHtcIi4uL2NvbnN0YW50cy9udW1lcmljYWxcIjo2OTUsXCIuLi9saWJcIjo3MTksXCIuLi9wbG90X2FwaS9wbG90X3NjaGVtYVwiOjc1NixcIi4uL3Bsb3RzL2NhcnRlc2lhbi9heGVzXCI6NzY3LFwiLi9oZWxwZXJzXCI6MTI2OH1dLDEyNjY6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG52YXIgUmVnaXN0cnkgPSBfZGVyZXFfKCcuLi9yZWdpc3RyeScpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIHBvaW50c0FjY2Vzc29yRnVuY3Rpb24gPSBfZGVyZXFfKCcuL2hlbHBlcnMnKS5wb2ludHNBY2Nlc3NvckZ1bmN0aW9uO1xuXG52YXIgZmlsdGVyT3BzID0gX2RlcmVxXygnLi4vY29uc3RhbnRzL2ZpbHRlcl9vcHMnKTtcbnZhciBDT01QQVJJU09OX09QUyA9IGZpbHRlck9wcy5DT01QQVJJU09OX09QUztcbnZhciBJTlRFUlZBTF9PUFMgPSBmaWx0ZXJPcHMuSU5URVJWQUxfT1BTO1xudmFyIFNFVF9PUFMgPSBmaWx0ZXJPcHMuU0VUX09QUztcblxuZXhwb3J0cy5tb2R1bGVUeXBlID0gJ3RyYW5zZm9ybSc7XG5cbmV4cG9ydHMubmFtZSA9ICdmaWx0ZXInO1xuXG5leHBvcnRzLmF0dHJpYnV0ZXMgPSB7XG4gICAgZW5hYmxlZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRhcmdldDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgc3RyaWN0OiB0cnVlLFxuICAgICAgICBub0JsYW5rOiB0cnVlLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBkZmx0OiAneCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG9wZXJhdGlvbjoge1xuICAgICAgICB2YWxUeXBlOiAnZW51bWVyYXRlZCcsXG4gICAgICAgIHZhbHVlczogW11cbiAgICAgICAgICAgIC5jb25jYXQoQ09NUEFSSVNPTl9PUFMpXG4gICAgICAgICAgICAuY29uY2F0KElOVEVSVkFMX09QUylcbiAgICAgICAgICAgIC5jb25jYXQoU0VUX09QUyksXG4gICAgICAgIGRmbHQ6ICc9JyxcbiAgICAgICAgXG4gICAgICAgIGVkaXRUeXBlOiAnY2FsYycsXG4gICAgICAgIFxuICAgIH0sXG4gICAgdmFsdWU6IHtcbiAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgIGRmbHQ6IDAsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHByZXNlcnZlZ2Fwczoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IGZhbHNlLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuXG5leHBvcnRzLnN1cHBseURlZmF1bHRzID0gZnVuY3Rpb24odHJhbnNmb3JtSW4pIHtcbiAgICB2YXIgdHJhbnNmb3JtT3V0ID0ge307XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFuc2Zvcm1JbiwgdHJhbnNmb3JtT3V0LCBleHBvcnRzLmF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBlbmFibGVkID0gY29lcmNlKCdlbmFibGVkJyk7XG5cbiAgICBpZihlbmFibGVkKSB7XG4gICAgICAgIHZhciB0YXJnZXQgPSBjb2VyY2UoJ3RhcmdldCcpO1xuXG4gICAgICAgIGlmKExpYi5pc0FycmF5T3JUeXBlZEFycmF5KHRhcmdldCkgJiYgdGFyZ2V0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdHJhbnNmb3JtT3V0LmVuYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1PdXQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb2VyY2UoJ3ByZXNlcnZlZ2FwcycpO1xuICAgICAgICBjb2VyY2UoJ29wZXJhdGlvbicpO1xuICAgICAgICBjb2VyY2UoJ3ZhbHVlJyk7XG5cbiAgICAgICAgdmFyIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHMgPSBSZWdpc3RyeS5nZXRDb21wb25lbnRNZXRob2QoJ2NhbGVuZGFycycsICdoYW5kbGVEZWZhdWx0cycpO1xuICAgICAgICBoYW5kbGVDYWxlbmRhckRlZmF1bHRzKHRyYW5zZm9ybUluLCB0cmFuc2Zvcm1PdXQsICd2YWx1ZWNhbGVuZGFyJywgbnVsbCk7XG4gICAgICAgIGhhbmRsZUNhbGVuZGFyRGVmYXVsdHModHJhbnNmb3JtSW4sIHRyYW5zZm9ybU91dCwgJ3RhcmdldGNhbGVuZGFyJywgbnVsbCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyYW5zZm9ybU91dDtcbn07XG5cbmV4cG9ydHMuY2FsY1RyYW5zZm9ybSA9IGZ1bmN0aW9uKGdkLCB0cmFjZSwgb3B0cykge1xuICAgIGlmKCFvcHRzLmVuYWJsZWQpIHJldHVybjtcblxuICAgIHZhciB0YXJnZXRBcnJheSA9IExpYi5nZXRUYXJnZXRBcnJheSh0cmFjZSwgb3B0cyk7XG4gICAgaWYoIXRhcmdldEFycmF5KSByZXR1cm47XG5cbiAgICB2YXIgdGFyZ2V0ID0gb3B0cy50YXJnZXQ7XG5cbiAgICB2YXIgbGVuID0gdGFyZ2V0QXJyYXkubGVuZ3RoO1xuICAgIGlmKHRyYWNlLl9sZW5ndGgpIGxlbiA9IE1hdGgubWluKGxlbiwgdHJhY2UuX2xlbmd0aCk7XG5cbiAgICB2YXIgdGFyZ2V0Q2FsZW5kYXIgPSBvcHRzLnRhcmdldGNhbGVuZGFyO1xuICAgIHZhciBhcnJheUF0dHJzID0gdHJhY2UuX2FycmF5QXR0cnM7XG4gICAgdmFyIHByZXNlcnZlZ2FwcyA9IG9wdHMucHJlc2VydmVnYXBzO1xuXG4gICAgLy8gZXZlbiBpZiB5b3UgcHJvdmlkZSB0YXJnZXRjYWxlbmRhciwgaWYgdGFyZ2V0IGlzIGEgc3RyaW5nIGFuZCB0aGVyZVxuICAgIC8vIGlzIGEgY2FsZW5kYXIgYXR0cmlidXRlIG1hdGNoaW5nIHRhcmdldCBpdCB3aWxsIGdldCB1c2VkIGluc3RlYWQuXG4gICAgaWYodHlwZW9mIHRhcmdldCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIGF0dHJUYXJnZXRDYWxlbmRhciA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgdGFyZ2V0ICsgJ2NhbGVuZGFyJykuZ2V0KCk7XG4gICAgICAgIGlmKGF0dHJUYXJnZXRDYWxlbmRhcikgdGFyZ2V0Q2FsZW5kYXIgPSBhdHRyVGFyZ2V0Q2FsZW5kYXI7XG4gICAgfVxuXG4gICAgdmFyIGQyYyA9IEF4ZXMuZ2V0RGF0YVRvQ29vcmRGdW5jKGdkLCB0cmFjZSwgdGFyZ2V0LCB0YXJnZXRBcnJheSk7XG4gICAgdmFyIGZpbHRlckZ1bmMgPSBnZXRGaWx0ZXJGdW5jKG9wdHMsIGQyYywgdGFyZ2V0Q2FsZW5kYXIpO1xuICAgIHZhciBvcmlnaW5hbEFycmF5cyA9IHt9O1xuICAgIHZhciBpbmRleFRvUG9pbnRzID0ge307XG4gICAgdmFyIGluZGV4ID0gMDtcblxuICAgIGZ1bmN0aW9uIGZvckFsbEF0dHJzKGZuLCBpbmRleCkge1xuICAgICAgICBmb3IodmFyIGogPSAwOyBqIDwgYXJyYXlBdHRycy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgdmFyIG5wID0gTGliLm5lc3RlZFByb3BlcnR5KHRyYWNlLCBhcnJheUF0dHJzW2pdKTtcbiAgICAgICAgICAgIGZuKG5wLCBpbmRleCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgaW5pdEZuO1xuICAgIHZhciBmaWxsRm47XG4gICAgaWYocHJlc2VydmVnYXBzKSB7XG4gICAgICAgIGluaXRGbiA9IGZ1bmN0aW9uKG5wKSB7XG4gICAgICAgICAgICBvcmlnaW5hbEFycmF5c1tucC5hc3RyXSA9IExpYi5leHRlbmREZWVwKFtdLCBucC5nZXQoKSk7XG4gICAgICAgICAgICBucC5zZXQobmV3IEFycmF5KGxlbikpO1xuICAgICAgICB9O1xuICAgICAgICBmaWxsRm4gPSBmdW5jdGlvbihucCwgaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciB2YWwgPSBvcmlnaW5hbEFycmF5c1tucC5hc3RyXVtpbmRleF07XG4gICAgICAgICAgICBucC5nZXQoKVtpbmRleF0gPSB2YWw7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaW5pdEZuID0gZnVuY3Rpb24obnApIHtcbiAgICAgICAgICAgIG9yaWdpbmFsQXJyYXlzW25wLmFzdHJdID0gTGliLmV4dGVuZERlZXAoW10sIG5wLmdldCgpKTtcbiAgICAgICAgICAgIG5wLnNldChbXSk7XG4gICAgICAgIH07XG4gICAgICAgIGZpbGxGbiA9IGZ1bmN0aW9uKG5wLCBpbmRleCkge1xuICAgICAgICAgICAgdmFyIHZhbCA9IG9yaWdpbmFsQXJyYXlzW25wLmFzdHJdW2luZGV4XTtcbiAgICAgICAgICAgIG5wLmdldCgpLnB1c2godmFsKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBjb3B5IGFsbCBvcmlnaW5hbCBhcnJheSBhdHRyaWJ1dGUgdmFsdWVzLCBhbmQgY2xlYXIgYXJyYXlzIGluIHRyYWNlXG4gICAgZm9yQWxsQXR0cnMoaW5pdEZuKTtcblxuICAgIHZhciBvcmlnaW5hbFBvaW50c0FjY2Vzc29yID0gcG9pbnRzQWNjZXNzb3JGdW5jdGlvbih0cmFjZS50cmFuc2Zvcm1zLCBvcHRzKTtcblxuICAgIC8vIGxvb3AgdGhyb3VnaCBmaWx0ZXIgYXJyYXksIGZpbGwgdHJhY2UgYXJyYXlzIGlmIHBhc3NlZFxuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgcGFzc2VkID0gZmlsdGVyRnVuYyh0YXJnZXRBcnJheVtpXSk7XG4gICAgICAgIGlmKHBhc3NlZCkge1xuICAgICAgICAgICAgZm9yQWxsQXR0cnMoZmlsbEZuLCBpKTtcbiAgICAgICAgICAgIGluZGV4VG9Qb2ludHNbaW5kZXgrK10gPSBvcmlnaW5hbFBvaW50c0FjY2Vzc29yKGkpO1xuICAgICAgICB9IGVsc2UgaWYocHJlc2VydmVnYXBzKSBpbmRleCsrO1xuICAgIH1cblxuICAgIG9wdHMuX2luZGV4VG9Qb2ludHMgPSBpbmRleFRvUG9pbnRzO1xuICAgIHRyYWNlLl9sZW5ndGggPSBpbmRleDtcbn07XG5cbmZ1bmN0aW9uIGdldEZpbHRlckZ1bmMob3B0cywgZDJjLCB0YXJnZXRDYWxlbmRhcikge1xuICAgIHZhciBvcGVyYXRpb24gPSBvcHRzLm9wZXJhdGlvbjtcbiAgICB2YXIgdmFsdWUgPSBvcHRzLnZhbHVlO1xuICAgIHZhciBoYXNBcnJheVZhbHVlID0gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG5cbiAgICBmdW5jdGlvbiBpc09wZXJhdGlvbkluKGFycmF5KSB7XG4gICAgICAgIHJldHVybiBhcnJheS5pbmRleE9mKG9wZXJhdGlvbikgIT09IC0xO1xuICAgIH1cblxuICAgIHZhciBkMmNWYWx1ZSA9IGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGQyYyh2LCAwLCBvcHRzLnZhbHVlY2FsZW5kYXIpOyB9O1xuICAgIHZhciBkMmNUYXJnZXQgPSBmdW5jdGlvbih2KSB7IHJldHVybiBkMmModiwgMCwgdGFyZ2V0Q2FsZW5kYXIpOyB9O1xuXG4gICAgdmFyIGNvZXJjZWRWYWx1ZTtcblxuICAgIGlmKGlzT3BlcmF0aW9uSW4oQ09NUEFSSVNPTl9PUFMpKSB7XG4gICAgICAgIGNvZXJjZWRWYWx1ZSA9IGhhc0FycmF5VmFsdWUgPyBkMmNWYWx1ZSh2YWx1ZVswXSkgOiBkMmNWYWx1ZSh2YWx1ZSk7XG4gICAgfSBlbHNlIGlmKGlzT3BlcmF0aW9uSW4oSU5URVJWQUxfT1BTKSkge1xuICAgICAgICBjb2VyY2VkVmFsdWUgPSBoYXNBcnJheVZhbHVlID9cbiAgICAgICAgICAgIFtkMmNWYWx1ZSh2YWx1ZVswXSksIGQyY1ZhbHVlKHZhbHVlWzFdKV0gOlxuICAgICAgICAgICAgW2QyY1ZhbHVlKHZhbHVlKSwgZDJjVmFsdWUodmFsdWUpXTtcbiAgICB9IGVsc2UgaWYoaXNPcGVyYXRpb25JbihTRVRfT1BTKSkge1xuICAgICAgICBjb2VyY2VkVmFsdWUgPSBoYXNBcnJheVZhbHVlID8gdmFsdWUubWFwKGQyY1ZhbHVlKSA6IFtkMmNWYWx1ZSh2YWx1ZSldO1xuICAgIH1cblxuICAgIHN3aXRjaChvcGVyYXRpb24pIHtcbiAgICAgICAgY2FzZSAnPSc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24odikgeyByZXR1cm4gZDJjVGFyZ2V0KHYpID09PSBjb2VyY2VkVmFsdWU7IH07XG5cbiAgICAgICAgY2FzZSAnIT0nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGQyY1RhcmdldCh2KSAhPT0gY29lcmNlZFZhbHVlOyB9O1xuXG4gICAgICAgIGNhc2UgJzwnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGQyY1RhcmdldCh2KSA8IGNvZXJjZWRWYWx1ZTsgfTtcblxuICAgICAgICBjYXNlICc8PSc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24odikgeyByZXR1cm4gZDJjVGFyZ2V0KHYpIDw9IGNvZXJjZWRWYWx1ZTsgfTtcblxuICAgICAgICBjYXNlICc+JzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7IHJldHVybiBkMmNUYXJnZXQodikgPiBjb2VyY2VkVmFsdWU7IH07XG5cbiAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHsgcmV0dXJuIGQyY1RhcmdldCh2KSA+PSBjb2VyY2VkVmFsdWU7IH07XG5cbiAgICAgICAgY2FzZSAnW10nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2ID49IGNvZXJjZWRWYWx1ZVswXSAmJiBjdiA8PSBjb2VyY2VkVmFsdWVbMV07XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJygpJzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICAgICAgdmFyIGN2ID0gZDJjVGFyZ2V0KHYpO1xuICAgICAgICAgICAgICAgIHJldHVybiBjdiA+IGNvZXJjZWRWYWx1ZVswXSAmJiBjdiA8IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnWyknOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2ID49IGNvZXJjZWRWYWx1ZVswXSAmJiBjdiA8IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnKF0nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2ID4gY29lcmNlZFZhbHVlWzBdICYmIGN2IDw9IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnXVsnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2IDw9IGNvZXJjZWRWYWx1ZVswXSB8fCBjdiA+PSBjb2VyY2VkVmFsdWVbMV07XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJykoJzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICAgICAgdmFyIGN2ID0gZDJjVGFyZ2V0KHYpO1xuICAgICAgICAgICAgICAgIHJldHVybiBjdiA8IGNvZXJjZWRWYWx1ZVswXSB8fCBjdiA+IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnXSgnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2IDw9IGNvZXJjZWRWYWx1ZVswXSB8fCBjdiA+IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAnKVsnOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICB2YXIgY3YgPSBkMmNUYXJnZXQodik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGN2IDwgY29lcmNlZFZhbHVlWzBdIHx8IGN2ID49IGNvZXJjZWRWYWx1ZVsxXTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgY2FzZSAne30nOlxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29lcmNlZFZhbHVlLmluZGV4T2YoZDJjVGFyZ2V0KHYpKSAhPT0gLTE7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIGNhc2UgJ317JzpcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvZXJjZWRWYWx1ZS5pbmRleE9mKGQyY1RhcmdldCh2KSkgPT09IC0xO1xuICAgICAgICAgICAgfTtcbiAgICB9XG59XG5cbn0se1wiLi4vY29uc3RhbnRzL2ZpbHRlcl9vcHNcIjo2OTEsXCIuLi9saWJcIjo3MTksXCIuLi9wbG90cy9jYXJ0ZXNpYW4vYXhlc1wiOjc2NyxcIi4uL3JlZ2lzdHJ5XCI6ODQ3LFwiLi9oZWxwZXJzXCI6MTI2OH1dLDEyNjc6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgTGliID0gX2RlcmVxXygnLi4vbGliJyk7XG52YXIgUGxvdFNjaGVtYSA9IF9kZXJlcV8oJy4uL3Bsb3RfYXBpL3Bsb3Rfc2NoZW1hJyk7XG52YXIgUGxvdHMgPSBfZGVyZXFfKCcuLi9wbG90cy9wbG90cycpO1xudmFyIHBvaW50c0FjY2Vzc29yRnVuY3Rpb24gPSBfZGVyZXFfKCcuL2hlbHBlcnMnKS5wb2ludHNBY2Nlc3NvckZ1bmN0aW9uO1xuXG5leHBvcnRzLm1vZHVsZVR5cGUgPSAndHJhbnNmb3JtJztcblxuZXhwb3J0cy5uYW1lID0gJ2dyb3VwYnknO1xuXG5leHBvcnRzLmF0dHJpYnV0ZXMgPSB7XG4gICAgZW5hYmxlZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIGdyb3Vwczoge1xuICAgICAgICB2YWxUeXBlOiAnZGF0YV9hcnJheScsXG4gICAgICAgIGRmbHQ6IFtdLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBuYW1lZm9ybWF0OiB7XG4gICAgICAgIHZhbFR5cGU6ICdzdHJpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBzdHlsZXM6IHtcbiAgICAgICAgX2lzTGlua2VkVG9BcnJheTogJ3N0eWxlJyxcbiAgICAgICAgdGFyZ2V0OiB7XG4gICAgICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICB9LFxuICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgdmFsVHlwZTogJ2FueScsXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRmbHQ6IHt9LFxuICAgICAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgX2NvbXBhcmVBc0pTT046IHRydWVcbiAgICAgICAgfSxcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJ1xuICAgIH0sXG4gICAgZWRpdFR5cGU6ICdjYWxjJ1xufTtcblxuLyoqXG4gKiBTdXBwbHkgdHJhbnNmb3JtIGF0dHJpYnV0ZXMgZGVmYXVsdHNcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gdHJhbnNmb3JtSW5cbiAqICBvYmplY3QgbGlua2VkIHRvIHRyYWNlLnRyYW5zZm9ybXNbaV0gd2l0aCAndHlwZScgc2V0IHRvIGV4cG9ydHMubmFtZVxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlT3V0XG4gKiAgdGhlIF9mdWxsRGF0YSB0cmFjZSB0aGlzIHRyYW5zZm9ybSBhcHBsaWVzIHRvXG4gKiBAcGFyYW0ge29iamVjdH0gbGF5b3V0XG4gKiAgdGhlIHBsb3QncyAobm90LXNvLWZ1bGwpIGxheW91dFxuICogQHBhcmFtIHtvYmplY3R9IHRyYWNlSW5cbiAqICB0aGUgaW5wdXQgZGF0YSB0cmFjZSB0aGlzIHRyYW5zZm9ybSBhcHBsaWVzIHRvXG4gKlxuICogQHJldHVybiB7b2JqZWN0fSB0cmFuc2Zvcm1PdXRcbiAqICBjb3B5IG9mIHRyYW5zZm9ybUluIHRoYXQgY29udGFpbnMgYXR0cmlidXRlIGRlZmF1bHRzXG4gKi9cbmV4cG9ydHMuc3VwcGx5RGVmYXVsdHMgPSBmdW5jdGlvbih0cmFuc2Zvcm1JbiwgdHJhY2VPdXQsIGxheW91dCkge1xuICAgIHZhciBpO1xuICAgIHZhciB0cmFuc2Zvcm1PdXQgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGNvZXJjZShhdHRyLCBkZmx0KSB7XG4gICAgICAgIHJldHVybiBMaWIuY29lcmNlKHRyYW5zZm9ybUluLCB0cmFuc2Zvcm1PdXQsIGV4cG9ydHMuYXR0cmlidXRlcywgYXR0ciwgZGZsdCk7XG4gICAgfVxuXG4gICAgdmFyIGVuYWJsZWQgPSBjb2VyY2UoJ2VuYWJsZWQnKTtcblxuICAgIGlmKCFlbmFibGVkKSByZXR1cm4gdHJhbnNmb3JtT3V0O1xuXG4gICAgY29lcmNlKCdncm91cHMnKTtcbiAgICBjb2VyY2UoJ25hbWVmb3JtYXQnLCBsYXlvdXQuX2RhdGFMZW5ndGggPiAxID8gJyV7Z3JvdXB9ICgle3RyYWNlfSknIDogJyV7Z3JvdXB9Jyk7XG5cbiAgICB2YXIgc3R5bGVJbiA9IHRyYW5zZm9ybUluLnN0eWxlcztcbiAgICB2YXIgc3R5bGVPdXQgPSB0cmFuc2Zvcm1PdXQuc3R5bGVzID0gW107XG5cbiAgICBpZihzdHlsZUluKSB7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHN0eWxlSW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0aGlzU3R5bGUgPSBzdHlsZU91dFtpXSA9IHt9O1xuICAgICAgICAgICAgTGliLmNvZXJjZShzdHlsZUluW2ldLCBzdHlsZU91dFtpXSwgZXhwb3J0cy5hdHRyaWJ1dGVzLnN0eWxlcywgJ3RhcmdldCcpO1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gTGliLmNvZXJjZShzdHlsZUluW2ldLCBzdHlsZU91dFtpXSwgZXhwb3J0cy5hdHRyaWJ1dGVzLnN0eWxlcywgJ3ZhbHVlJyk7XG5cbiAgICAgICAgICAgIC8vIHNvIHRoYXQgeW91IGNhbiBlZGl0IHZhbHVlIGluIHBsYWNlIGFuZCBoYXZlIFBsb3RseS5yZWFjdCBub3RpY2UgaXQsIG9yXG4gICAgICAgICAgICAvLyByZWJ1aWxkIGl0IGV2ZXJ5IHRpbWUgYW5kIGhhdmUgUGxvdGx5LnJlYWN0IE5PVCB0aGluayBpdCBjaGFuZ2VkOlxuICAgICAgICAgICAgLy8gdXNlIF9jb21wYXJlQXNKU09OIHRvIHNheSB3ZSBzaG91bGQgZGlmZiB0aGUgX0pTT05fdmFsdWVcbiAgICAgICAgICAgIGlmKExpYi5pc1BsYWluT2JqZWN0KHZhbHVlKSkgdGhpc1N0eWxlLnZhbHVlID0gTGliLmV4dGVuZERlZXAoe30sIHZhbHVlKTtcbiAgICAgICAgICAgIGVsc2UgaWYodmFsdWUpIGRlbGV0ZSB0aGlzU3R5bGUudmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJhbnNmb3JtT3V0O1xufTtcblxuXG4vKipcbiAqIEFwcGx5IHRyYW5zZm9ybSAhISFcbiAqXG4gKiBAcGFyYW0ge2FycmF5fSBkYXRhXG4gKiAgYXJyYXkgb2YgdHJhbnNmb3JtZWQgdHJhY2VzIChpcyBbZnVsbFRyYWNlXSB1cG9uIGZpcnN0IHRyYW5zZm9ybSlcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gc3RhdGVcbiAqICBzdGF0ZSBvYmplY3Qgd2hpY2ggaW5jbHVkZXM6XG4gKiAgICAgIC0gdHJhbnNmb3JtIHtvYmplY3R9IGZ1bGwgdHJhbnNmb3JtIGF0dHJpYnV0ZXNcbiAqICAgICAgLSBmdWxsVHJhY2Uge29iamVjdH0gZnVsbCB0cmFjZSBvYmplY3Qgd2hpY2ggaXMgYmVpbmcgdHJhbnNmb3JtZWRcbiAqICAgICAgLSBmdWxsRGF0YSB7YXJyYXl9IGZ1bGwgcHJlLXRyYW5zZm9ybShzKSBkYXRhIGFycmF5XG4gKiAgICAgIC0gbGF5b3V0IHtvYmplY3R9IHRoZSBwbG90J3MgKG5vdC1zby1mdWxsKSBsYXlvdXRcbiAqXG4gKiBAcmV0dXJuIHtvYmplY3R9IG5ld0RhdGFcbiAqICBhcnJheSBvZiB0cmFuc2Zvcm1lZCB0cmFjZXNcbiAqL1xuZXhwb3J0cy50cmFuc2Zvcm0gPSBmdW5jdGlvbihkYXRhLCBzdGF0ZSkge1xuICAgIHZhciBuZXdUcmFjZXMsIGksIGo7XG4gICAgdmFyIG5ld0RhdGEgPSBbXTtcblxuICAgIGZvcihpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbmV3VHJhY2VzID0gdHJhbnNmb3JtT25lKGRhdGFbaV0sIHN0YXRlKTtcblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBuZXdUcmFjZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIG5ld0RhdGEucHVzaChuZXdUcmFjZXNbal0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld0RhdGE7XG59O1xuXG5mdW5jdGlvbiB0cmFuc2Zvcm1PbmUodHJhY2UsIHN0YXRlKSB7XG4gICAgdmFyIGksIGosIGssIGF0dHIsIHNyY0FycmF5LCBncm91cE5hbWUsIG5ld1RyYWNlLCB0cmFuc2Zvcm1zLCBhcnJheUxvb2t1cDtcbiAgICB2YXIgZ3JvdXBOYW1lT2JqO1xuXG4gICAgdmFyIG9wdHMgPSBzdGF0ZS50cmFuc2Zvcm07XG4gICAgdmFyIHRyYW5zZm9ybUluZGV4ID0gc3RhdGUudHJhbnNmb3JtSW5kZXg7XG4gICAgdmFyIGdyb3VwcyA9IHRyYWNlLnRyYW5zZm9ybXNbdHJhbnNmb3JtSW5kZXhdLmdyb3VwcztcbiAgICB2YXIgb3JpZ2luYWxQb2ludHNBY2Nlc3NvciA9IHBvaW50c0FjY2Vzc29yRnVuY3Rpb24odHJhY2UudHJhbnNmb3Jtcywgb3B0cyk7XG5cbiAgICBpZighKEFycmF5LmlzQXJyYXkoZ3JvdXBzKSkgfHwgZ3JvdXBzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gW3RyYWNlXTtcbiAgICB9XG5cbiAgICB2YXIgZ3JvdXBOYW1lcyA9IExpYi5maWx0ZXJVbmlxdWUoZ3JvdXBzKTtcbiAgICB2YXIgbmV3RGF0YSA9IG5ldyBBcnJheShncm91cE5hbWVzLmxlbmd0aCk7XG4gICAgdmFyIGxlbiA9IGdyb3Vwcy5sZW5ndGg7XG5cbiAgICB2YXIgYXJyYXlBdHRycyA9IFBsb3RTY2hlbWEuZmluZEFycmF5QXR0cmlidXRlcyh0cmFjZSk7XG5cbiAgICB2YXIgc3R5bGVzID0gb3B0cy5zdHlsZXMgfHwgW107XG4gICAgdmFyIHN0eWxlTG9va3VwID0ge307XG4gICAgZm9yKGkgPSAwOyBpIDwgc3R5bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHN0eWxlTG9va3VwW3N0eWxlc1tpXS50YXJnZXRdID0gc3R5bGVzW2ldLnZhbHVlO1xuICAgIH1cblxuICAgIGlmKG9wdHMuc3R5bGVzKSB7XG4gICAgICAgIGdyb3VwTmFtZU9iaiA9IExpYi5rZXllZENvbnRhaW5lcihvcHRzLCAnc3R5bGVzJywgJ3RhcmdldCcsICd2YWx1ZS5uYW1lJyk7XG4gICAgfVxuXG4gICAgLy8gQW4gaW5kZXggdG8gbWFwIGdyb3VwIG5hbWUgLS0+IGV4cGFuZGVkIHRyYWNlIGluZGV4XG4gICAgdmFyIGluZGV4TG9va3VwID0ge307XG4gICAgdmFyIGluZGV4Q250cyA9IHt9O1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgZ3JvdXBOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBncm91cE5hbWUgPSBncm91cE5hbWVzW2ldO1xuICAgICAgICBpbmRleExvb2t1cFtncm91cE5hbWVdID0gaTtcbiAgICAgICAgaW5kZXhDbnRzW2dyb3VwTmFtZV0gPSAwO1xuXG4gICAgICAgIC8vIFN0YXJ0IHdpdGggYSBkZWVwIGV4dGVuZCB0aGF0IGp1c3QgY29waWVzIGFycmF5IHJlZmVyZW5jZXMuXG4gICAgICAgIG5ld1RyYWNlID0gbmV3RGF0YVtpXSA9IExpYi5leHRlbmREZWVwTm9BcnJheXMoe30sIHRyYWNlKTtcbiAgICAgICAgbmV3VHJhY2UuX2dyb3VwID0gZ3JvdXBOYW1lO1xuICAgICAgICBuZXdUcmFjZS50cmFuc2Zvcm1zW3RyYW5zZm9ybUluZGV4XS5faW5kZXhUb1BvaW50cyA9IHt9O1xuXG4gICAgICAgIHZhciBzdXBwbGllZE5hbWUgPSBudWxsO1xuICAgICAgICBpZihncm91cE5hbWVPYmopIHtcbiAgICAgICAgICAgIHN1cHBsaWVkTmFtZSA9IGdyb3VwTmFtZU9iai5nZXQoZ3JvdXBOYW1lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHN1cHBsaWVkTmFtZSB8fCBzdXBwbGllZE5hbWUgPT09ICcnKSB7XG4gICAgICAgICAgICBuZXdUcmFjZS5uYW1lID0gc3VwcGxpZWROYW1lO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3VHJhY2UubmFtZSA9IExpYi50ZW1wbGF0ZVN0cmluZyhvcHRzLm5hbWVmb3JtYXQsIHtcbiAgICAgICAgICAgICAgICB0cmFjZTogdHJhY2UubmFtZSxcbiAgICAgICAgICAgICAgICBncm91cDogZ3JvdXBOYW1lXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluIG9yZGVyIGZvciBncm91cHMgdG8gYXBwbHkgY29ycmVjdGx5IHRvIG90aGVyIHRyYW5zZm9ybSBkYXRhIChlLmcuXG4gICAgICAgIC8vIGEgZmlsdGVyIHRyYW5zZm9ybSksIHdlIGhhdmUgdG8gYnJlYWsgdGhlIGNvbm5lY3Rpb24gYW5kIGNsb25lIHRoZVxuICAgICAgICAvLyB0cmFuc2Zvcm1zIHNvIHRoYXQgZWFjaCBncm91cCB3cml0ZXMgZ3JvdXBlZCB2YWx1ZXMgaW50byBhIGRpZmZlcmVudFxuICAgICAgICAvLyBkZXN0aW5hdGlvbi4gVGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBicmVhayB0aGUgYXJyYXkgcmVmZXJlbmNlXG4gICAgICAgIC8vIGNvbm5lY3Rpb24gYmV0d2VlbiB0aGUgc3BsaXQgdHJhbnNmb3JtcyBpdCBjcmVhdGVzLiBUaGF0J3MgaGFuZGxlZCBpblxuICAgICAgICAvLyBpbml0aWFsaXplLCB3aGljaCBjcmVhdGVzIGEgbmV3IGVtcHR5IGFycmF5IGZvciBlYWNoIGFycmF5QXR0ci5cbiAgICAgICAgdHJhbnNmb3JtcyA9IG5ld1RyYWNlLnRyYW5zZm9ybXM7XG4gICAgICAgIG5ld1RyYWNlLnRyYW5zZm9ybXMgPSBbXTtcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgdHJhbnNmb3Jtcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgbmV3VHJhY2UudHJhbnNmb3Jtc1tqXSA9IExpYi5leHRlbmREZWVwTm9BcnJheXMoe30sIHRyYW5zZm9ybXNbal0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBlbXB0eSBhcnJheXMgZm9yIHRoZSBhcnJheUF0dHJzLCB0byBiZSBzcGxpdCBpbiB0aGUgbmV4dCBzdGVwXG4gICAgICAgIGZvcihqID0gMDsgaiA8IGFycmF5QXR0cnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIExpYi5uZXN0ZWRQcm9wZXJ0eShuZXdUcmFjZSwgYXJyYXlBdHRyc1tqXSkuc2V0KFtdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEZvciBlYWNoIGFycmF5IGF0dHJpYnV0ZSBpbmNsdWRpbmcgdGhvc2UgbmVzdGVkIGluc2lkZSB0aGlzIGFuZCBvdGhlclxuICAgIC8vIHRyYW5zZm9ybXMgKHNtYWxsIG5vdGUgdGhhdCB3ZSB0ZWNobmljYWxseSBvbmx5IG5lZWQgdG8gZG8gdGhpcyBmb3JcbiAgICAvLyB0cmFuc2Zvcm1zIHRoYXQgaGF2ZSBub3QgeWV0IGJlZW4gYXBwbGllZCk6XG4gICAgZm9yKGsgPSAwOyBrIDwgYXJyYXlBdHRycy5sZW5ndGg7IGsrKykge1xuICAgICAgICBhdHRyID0gYXJyYXlBdHRyc1trXTtcblxuICAgICAgICAvLyBDYWNoZSBhbGwgdGhlIGFycmF5cyB0byB3aGljaCB3ZSdsbCBwdXNoOlxuICAgICAgICBmb3IoaiA9IDAsIGFycmF5TG9va3VwID0gW107IGogPCBncm91cE5hbWVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBhcnJheUxvb2t1cFtqXSA9IExpYi5uZXN0ZWRQcm9wZXJ0eShuZXdEYXRhW2pdLCBhdHRyKS5nZXQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCB0aGUgaW5wdXQgZGF0YTpcbiAgICAgICAgc3JjQXJyYXkgPSBMaWIubmVzdGVkUHJvcGVydHkodHJhY2UsIGF0dHIpLmdldCgpO1xuXG4gICAgICAgIC8vIFNlbmQgZWFjaCBkYXRhIHBvaW50IHRvIHRoZSBhcHByb3ByaWF0ZSBleHBhbmRlZCB0cmFjZTpcbiAgICAgICAgZm9yKGogPSAwOyBqIDwgbGVuOyBqKyspIHtcbiAgICAgICAgICAgIC8vIE1hcCBncm91cCBkYXRhIC0tPiB0cmFjZSBpbmRleCAtLT4gYXJyYXkgYW5kIHB1c2ggZGF0YSBvbnRvIGl0XG4gICAgICAgICAgICBhcnJheUxvb2t1cFtpbmRleExvb2t1cFtncm91cHNbal1dXS5wdXNoKHNyY0FycmF5W2pdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvcihqID0gMDsgaiA8IGxlbjsgaisrKSB7XG4gICAgICAgIG5ld1RyYWNlID0gbmV3RGF0YVtpbmRleExvb2t1cFtncm91cHNbal1dXTtcblxuICAgICAgICB2YXIgaW5kZXhUb1BvaW50cyA9IG5ld1RyYWNlLnRyYW5zZm9ybXNbdHJhbnNmb3JtSW5kZXhdLl9pbmRleFRvUG9pbnRzO1xuICAgICAgICBpbmRleFRvUG9pbnRzW2luZGV4Q250c1tncm91cHNbal1dXSA9IG9yaWdpbmFsUG9pbnRzQWNjZXNzb3Ioaik7XG4gICAgICAgIGluZGV4Q250c1tncm91cHNbal1dKys7XG4gICAgfVxuXG4gICAgZm9yKGkgPSAwOyBpIDwgZ3JvdXBOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBncm91cE5hbWUgPSBncm91cE5hbWVzW2ldO1xuICAgICAgICBuZXdUcmFjZSA9IG5ld0RhdGFbaV07XG5cbiAgICAgICAgUGxvdHMuY2xlYXJFeHBhbmRlZFRyYWNlRGVmYXVsdENvbG9ycyhuZXdUcmFjZSk7XG5cbiAgICAgICAgLy8gdGhlcmUncyBubyBuZWVkIHRvIGNvZXJjZSBzdHlsZUxvb2t1cFtncm91cE5hbWVdIGhlcmVcbiAgICAgICAgLy8gYXMgYW5vdGhlciByb3VuZCBvZiBzdXBwbHlEZWZhdWx0cyBpcyBkb25lIG9uIHRoZSB0cmFuc2Zvcm1lZCB0cmFjZXNcbiAgICAgICAgbmV3VHJhY2UgPSBMaWIuZXh0ZW5kRGVlcE5vQXJyYXlzKG5ld1RyYWNlLCBzdHlsZUxvb2t1cFtncm91cE5hbWVdIHx8IHt9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3RGF0YTtcbn1cblxufSx7XCIuLi9saWJcIjo3MTksXCIuLi9wbG90X2FwaS9wbG90X3NjaGVtYVwiOjc1NixcIi4uL3Bsb3RzL3Bsb3RzXCI6ODI4LFwiLi9oZWxwZXJzXCI6MTI2OH1dLDEyNjg6W2Z1bmN0aW9uKF9kZXJlcV8sbW9kdWxlLGV4cG9ydHMpe1xuLyoqXG4qIENvcHlyaWdodCAyMDEyLTIwMTksIFBsb3RseSwgSW5jLlxuKiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuKlxuKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLnBvaW50c0FjY2Vzc29yRnVuY3Rpb24gPSBmdW5jdGlvbih0cmFuc2Zvcm1zLCBvcHRzKSB7XG4gICAgdmFyIHRyO1xuICAgIHZhciBwcmV2SW5kZXhUb1BvaW50cztcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdHJhbnNmb3Jtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0ciA9IHRyYW5zZm9ybXNbaV07XG4gICAgICAgIGlmKHRyID09PSBvcHRzKSBicmVhaztcbiAgICAgICAgaWYoIXRyLl9pbmRleFRvUG9pbnRzIHx8IHRyLmVuYWJsZWQgPT09IGZhbHNlKSBjb250aW51ZTtcbiAgICAgICAgcHJldkluZGV4VG9Qb2ludHMgPSB0ci5faW5kZXhUb1BvaW50cztcbiAgICB9XG4gICAgdmFyIG9yaWdpbmFsUG9pbnRzQWNjZXNzb3IgPSBwcmV2SW5kZXhUb1BvaW50cyA/XG4gICAgICAgIGZ1bmN0aW9uKGkpIHtyZXR1cm4gcHJldkluZGV4VG9Qb2ludHNbaV07fSA6XG4gICAgICAgIGZ1bmN0aW9uKGkpIHtyZXR1cm4gW2ldO307XG4gICAgcmV0dXJuIG9yaWdpbmFsUG9pbnRzQWNjZXNzb3I7XG59O1xuXG59LHt9XSwxMjY5OltmdW5jdGlvbihfZGVyZXFfLG1vZHVsZSxleHBvcnRzKXtcbi8qKlxuKiBDb3B5cmlnaHQgMjAxMi0yMDE5LCBQbG90bHksIEluYy5cbiogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbipcbiogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4qIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIExpYiA9IF9kZXJlcV8oJy4uL2xpYicpO1xudmFyIEF4ZXMgPSBfZGVyZXFfKCcuLi9wbG90cy9jYXJ0ZXNpYW4vYXhlcycpO1xudmFyIHBvaW50c0FjY2Vzc29yRnVuY3Rpb24gPSBfZGVyZXFfKCcuL2hlbHBlcnMnKS5wb2ludHNBY2Nlc3NvckZ1bmN0aW9uO1xuXG5leHBvcnRzLm1vZHVsZVR5cGUgPSAndHJhbnNmb3JtJztcblxuZXhwb3J0cy5uYW1lID0gJ3NvcnQnO1xuXG5leHBvcnRzLmF0dHJpYnV0ZXMgPSB7XG4gICAgZW5hYmxlZDoge1xuICAgICAgICB2YWxUeXBlOiAnYm9vbGVhbicsXG4gICAgICAgIGRmbHQ6IHRydWUsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIHRhcmdldDoge1xuICAgICAgICB2YWxUeXBlOiAnc3RyaW5nJyxcbiAgICAgICAgc3RyaWN0OiB0cnVlLFxuICAgICAgICBub0JsYW5rOiB0cnVlLFxuICAgICAgICBhcnJheU9rOiB0cnVlLFxuICAgICAgICBkZmx0OiAneCcsXG4gICAgICAgIFxuICAgICAgICBlZGl0VHlwZTogJ2NhbGMnLFxuICAgICAgICBcbiAgICB9LFxuICAgIG9yZGVyOiB7XG4gICAgICAgIHZhbFR5cGU6ICdlbnVtZXJhdGVkJyxcbiAgICAgICAgdmFsdWVzOiBbJ2FzY2VuZGluZycsICdkZXNjZW5kaW5nJ10sXG4gICAgICAgIGRmbHQ6ICdhc2NlbmRpbmcnLFxuICAgICAgICBcbiAgICAgICAgZWRpdFR5cGU6ICdjYWxjJyxcbiAgICAgICAgXG4gICAgfSxcbiAgICBlZGl0VHlwZTogJ2NhbGMnXG59O1xuXG5leHBvcnRzLnN1cHBseURlZmF1bHRzID0gZnVuY3Rpb24odHJhbnNmb3JtSW4pIHtcbiAgICB2YXIgdHJhbnNmb3JtT3V0ID0ge307XG5cbiAgICBmdW5jdGlvbiBjb2VyY2UoYXR0ciwgZGZsdCkge1xuICAgICAgICByZXR1cm4gTGliLmNvZXJjZSh0cmFuc2Zvcm1JbiwgdHJhbnNmb3JtT3V0LCBleHBvcnRzLmF0dHJpYnV0ZXMsIGF0dHIsIGRmbHQpO1xuICAgIH1cblxuICAgIHZhciBlbmFibGVkID0gY29lcmNlKCdlbmFibGVkJyk7XG5cbiAgICBpZihlbmFibGVkKSB7XG4gICAgICAgIGNvZXJjZSgndGFyZ2V0Jyk7XG4gICAgICAgIGNvZXJjZSgnb3JkZXInKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJhbnNmb3JtT3V0O1xufTtcblxuZXhwb3J0cy5jYWxjVHJhbnNmb3JtID0gZnVuY3Rpb24oZ2QsIHRyYWNlLCBvcHRzKSB7XG4gICAgaWYoIW9wdHMuZW5hYmxlZCkgcmV0dXJuO1xuXG4gICAgdmFyIHRhcmdldEFycmF5ID0gTGliLmdldFRhcmdldEFycmF5KHRyYWNlLCBvcHRzKTtcbiAgICBpZighdGFyZ2V0QXJyYXkpIHJldHVybjtcblxuICAgIHZhciB0YXJnZXQgPSBvcHRzLnRhcmdldDtcblxuICAgIHZhciBsZW4gPSB0YXJnZXRBcnJheS5sZW5ndGg7XG4gICAgaWYodHJhY2UuX2xlbmd0aCkgbGVuID0gTWF0aC5taW4obGVuLCB0cmFjZS5fbGVuZ3RoKTtcblxuICAgIHZhciBhcnJheUF0dHJzID0gdHJhY2UuX2FycmF5QXR0cnM7XG4gICAgdmFyIGQyYyA9IEF4ZXMuZ2V0RGF0YVRvQ29vcmRGdW5jKGdkLCB0cmFjZSwgdGFyZ2V0LCB0YXJnZXRBcnJheSk7XG4gICAgdmFyIGluZGljZXMgPSBnZXRJbmRpY2VzKG9wdHMsIHRhcmdldEFycmF5LCBkMmMsIGxlbik7XG4gICAgdmFyIG9yaWdpbmFsUG9pbnRzQWNjZXNzb3IgPSBwb2ludHNBY2Nlc3NvckZ1bmN0aW9uKHRyYWNlLnRyYW5zZm9ybXMsIG9wdHMpO1xuICAgIHZhciBpbmRleFRvUG9pbnRzID0ge307XG4gICAgdmFyIGksIGo7XG5cbiAgICBmb3IoaSA9IDA7IGkgPCBhcnJheUF0dHJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBucCA9IExpYi5uZXN0ZWRQcm9wZXJ0eSh0cmFjZSwgYXJyYXlBdHRyc1tpXSk7XG4gICAgICAgIHZhciBhcnJheU9sZCA9IG5wLmdldCgpO1xuICAgICAgICB2YXIgYXJyYXlOZXcgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgICAgICBmb3IoaiA9IDA7IGogPCBsZW47IGorKykge1xuICAgICAgICAgICAgYXJyYXlOZXdbal0gPSBhcnJheU9sZFtpbmRpY2VzW2pdXTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5wLnNldChhcnJheU5ldyk7XG4gICAgfVxuXG4gICAgZm9yKGogPSAwOyBqIDwgbGVuOyBqKyspIHtcbiAgICAgICAgaW5kZXhUb1BvaW50c1tqXSA9IG9yaWdpbmFsUG9pbnRzQWNjZXNzb3IoaW5kaWNlc1tqXSk7XG4gICAgfVxuXG4gICAgb3B0cy5faW5kZXhUb1BvaW50cyA9IGluZGV4VG9Qb2ludHM7XG4gICAgdHJhY2UuX2xlbmd0aCA9IGxlbjtcbn07XG5cbmZ1bmN0aW9uIGdldEluZGljZXMob3B0cywgdGFyZ2V0QXJyYXksIGQyYywgbGVuKSB7XG4gICAgdmFyIHNvcnRlZEFycmF5ID0gbmV3IEFycmF5KGxlbik7XG4gICAgdmFyIGluZGljZXMgPSBuZXcgQXJyYXkobGVuKTtcbiAgICB2YXIgaTtcblxuICAgIGZvcihpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHNvcnRlZEFycmF5W2ldID0ge3Y6IHRhcmdldEFycmF5W2ldLCBpOiBpfTtcbiAgICB9XG5cbiAgICBzb3J0ZWRBcnJheS5zb3J0KGdldFNvcnRGdW5jKG9wdHMsIGQyYykpO1xuXG4gICAgZm9yKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaW5kaWNlc1tpXSA9IHNvcnRlZEFycmF5W2ldLmk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGluZGljZXM7XG59XG5cbmZ1bmN0aW9uIGdldFNvcnRGdW5jKG9wdHMsIGQyYykge1xuICAgIHN3aXRjaChvcHRzLm9yZGVyKSB7XG4gICAgICAgIGNhc2UgJ2FzY2VuZGluZyc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gZDJjKGEudikgLSBkMmMoYi52KTsgfTtcbiAgICAgICAgY2FzZSAnZGVzY2VuZGluZyc6XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gZDJjKGIudikgLSBkMmMoYS52KTsgfTtcbiAgICB9XG59XG5cbn0se1wiLi4vbGliXCI6NzE5LFwiLi4vcGxvdHMvY2FydGVzaWFuL2F4ZXNcIjo3NjcsXCIuL2hlbHBlcnNcIjoxMjY4fV19LHt9LFsyNV0pKDI1KVxufSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vcGxvdGx5LmpzLWRpc3QvcGxvdGx5LmpzXG4vLyBtb2R1bGUgaWQgPSAxMVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJpbXBvcnQgeyBRdWVzdGlvbiB9IGZyb20gXCJzdXJ2ZXktY29yZVwiO1xuaW1wb3J0IGMzIGZyb20gXCJjM1wiO1xuaW1wb3J0IHsgVmlzdWFsaXphdGlvbk1hbmFnZXIgfSBmcm9tIFwiLi4vdmlzdWFsaXphdGlvbk1hbmFnZXJcIjtcbmltcG9ydCB7IFNlbGVjdEJhc2UgfSBmcm9tIFwiLi4vc2VsZWN0QmFzZVwiO1xuXG5leHBvcnQgY2xhc3MgU2VsZWN0QmFzZUMzIGV4dGVuZHMgU2VsZWN0QmFzZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudCxcbiAgICBxdWVzdGlvbjogUXVlc3Rpb24sXG4gICAgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgICBvcHRpb25zPzogT2JqZWN0XG4gICkge1xuICAgIHN1cGVyKHRhcmdldEVsZW1lbnQsIHF1ZXN0aW9uLCBkYXRhLCBvcHRpb25zKTtcbiAgfVxuXG4gIHByaXZhdGUgY2hhcnQ6IGMzLkNoYXJ0QVBJO1xuICBwcm90ZWN0ZWQgY2hhcnRUeXBlcyA9IFtcImJhclwiLCBcImxpbmVcIiwgXCJwaWVcIiwgXCJkb251dFwiXTtcbiAgY2hhcnRUeXBlID0gXCJiYXJcIjtcbiAgY2hhcnROb2RlID0gPEhUTUxFbGVtZW50PmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG5cbiAgZGVzdHJveSgpIHtcbiAgICBpZiAoIXRoaXMuY2hhcnQpIHJldHVybjtcbiAgICB0aGlzLmNoYXJ0LmRlc3Ryb3koKTtcbiAgfVxuXG4gIHRvb2xiYXJDaGFuZ2VIYW5kbGVyID0gKGU6IGFueSkgPT4ge1xuICAgIGlmICh0aGlzLmNoYXJ0VHlwZSAhPT0gZS50YXJnZXQudmFsdWUpIHtcbiAgICAgIHRoaXMuY2hhcnRUeXBlID0gZS50YXJnZXQudmFsdWU7XG4gICAgICB0aGlzLmNoYXJ0LmRlc3Ryb3koKTtcbiAgICAgIHRoaXMuY2hhcnQgPSB0aGlzLmdldENoYXJ0QzModGhpcy5jaGFydE5vZGUsIHRoaXMuY2hhcnRUeXBlKTtcbiAgICB9XG4gIH07XG5cbiAgY3JlYXRlQ2hhcnQoKSB7XG4gICAgdGhpcy5jaGFydCA9IHRoaXMuZ2V0Q2hhcnRDMyh0aGlzLmNoYXJ0Tm9kZSwgdGhpcy5jaGFydFR5cGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDaGFydEMzKGNoYXJ0Tm9kZTogSFRNTEVsZW1lbnQsIGNoYXJ0VHlwZTogc3RyaW5nKTogYzMuQ2hhcnRBUEkge1xuICAgIHZhciBkYXRhID0gdGhpcy5nZXREYXRhKCk7XG4gICAgdmFyIHN0YXRpc3RpY3MgPSBkYXRhWzBdO1xuICAgIHZhciBjb2x1bW5zID0gW1tcInhcIl0uY29uY2F0KHRoaXMuZ2V0TGFiZWxzKCkpXTtcblxuICAgIGRhdGEuZm9yRWFjaCgoZGF0YXNldCwgaW5kZXgpID0+IHtcbiAgICAgIGNvbHVtbnMucHVzaChbXCJcIiArIGluZGV4XS5jb25jYXQoZGF0YXNldCkpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGMzLmdlbmVyYXRlKHtcbiAgICAgIGJpbmR0bzogY2hhcnROb2RlLFxuICAgICAgZGF0YToge1xuICAgICAgICB4OiBcInhcIixcbiAgICAgICAgY29sdW1uczogY29sdW1ucyxcbiAgICAgICAgdHlwZTogdGhpcy5jaGFydFR5cGVcbiAgICAgIH0sXG4gICAgICBjb2xvcjoge1xuICAgICAgICBwYXR0ZXJuOiB0aGlzLmdldENvbG9ycygpXG4gICAgICB9LFxuICAgICAgYmFyOiB7XG4gICAgICAgIHdpZHRoOiB7XG4gICAgICAgICAgcmF0aW86IDAuNSAvLyB0aGlzIG1ha2VzIGJhciB3aWR0aCA1MCUgb2YgbGVuZ3RoIGJldHdlZW4gdGlja3NcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGF4aXM6IHtcbiAgICAgICAgeDoge1xuICAgICAgICAgIHR5cGU6IFwiY2F0ZWdvcnlcIlxuICAgICAgICB9LFxuICAgICAgICB5OiB7XG4gICAgICAgICAgdGljazoge1xuICAgICAgICAgICAgdmFsdWVzOiBzdGF0aXN0aWNzXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgdG9vbHRpcDoge1xuICAgICAgICBzaG93OiB0cnVlXG4gICAgICB9LFxuICAgICAgbGVnZW5kOiB7XG4gICAgICAgIHNob3c6IGZhbHNlXG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cblxuLy8gVmlzdWFsaXphdGlvbk1hbmFnZXIucmVnaXN0ZXJWaXN1YWxpemVyKFwiY2hlY2tib3hcIiwgU2VsZWN0QmFzZUMzKTtcbi8vIFZpc3VhbGl6YXRpb25NYW5hZ2VyLnJlZ2lzdGVyVmlzdWFsaXplcihcInJhZGlvZ3JvdXBcIiwgU2VsZWN0QmFzZUMzKTtcbi8vIFZpc3VhbGl6YXRpb25NYW5hZ2VyLnJlZ2lzdGVyVmlzdWFsaXplcihcImRyb3Bkb3duXCIsIFNlbGVjdEJhc2VDMyk7XG4vLyBWaXN1YWxpemF0aW9uTWFuYWdlci5yZWdpc3RlclZpc3VhbGl6ZXIoXCJpbWFnZXBpY2tlclwiLCBTZWxlY3RCYXNlQzMpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2MzL3NlbGVjdEJhc2UudHMiLCJpbXBvcnQgeyBRdWVzdGlvbiwgSXRlbVZhbHVlIH0gZnJvbSBcInN1cnZleS1jb3JlXCI7XG52YXIgUGxvdGx5ID0gPGFueT5yZXF1aXJlKFwicGxvdGx5LmpzLWRpc3RcIik7XG5pbXBvcnQgeyBWaXN1YWxpemF0aW9uTWFuYWdlciB9IGZyb20gXCIuLi92aXN1YWxpemF0aW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgU2VsZWN0QmFzZSB9IGZyb20gXCIuLi9zZWxlY3RCYXNlXCI7XG5cbmV4cG9ydCBjbGFzcyBTZWxlY3RCYXNlUGxvdGx5IGV4dGVuZHMgU2VsZWN0QmFzZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudCxcbiAgICBxdWVzdGlvbjogUXVlc3Rpb24sXG4gICAgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgICBvcHRpb25zPzogT2JqZWN0XG4gICkge1xuICAgIHN1cGVyKHRhcmdldEVsZW1lbnQsIHF1ZXN0aW9uLCBkYXRhLCBvcHRpb25zKTtcbiAgICB0aGlzLmNoYXJ0VHlwZXMgPSBTZWxlY3RCYXNlUGxvdGx5LnR5cGVzO1xuICAgIHRoaXMuY2hhcnRUeXBlID0gdGhpcy5jaGFydFR5cGVzWzBdO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGFydDogUHJvbWlzZTxQbG90bHkuUGxvdGx5SFRNTEVsZW1lbnQ+O1xuICBwcml2YXRlIHNlbGVjdGVkSXRlbTogSXRlbVZhbHVlID0gdW5kZWZpbmVkO1xuICBwcml2YXRlIGZpbHRlclRleHQ6IEhUTUxTcGFuRWxlbWVudCA9IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBmaWx0ZXI6IEhUTUxEaXZFbGVtZW50ID0gdW5kZWZpbmVkO1xuICBwdWJsaWMgc3RhdGljIHR5cGVzID0gW1wiYmFyXCIsIFwicGllXCIsIFwic2NhdHRlclwiXTtcblxuICB1cGRhdGUoZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9Pikge1xuICAgIHN1cGVyLnVwZGF0ZShkYXRhKTtcbiAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICB0aGlzLmNoYXJ0ID0gdGhpcy5nZXRQbG90bHlDaGFydCh0aGlzLmNoYXJ0Tm9kZSwgdGhpcy5jaGFydFR5cGUpO1xuICAgIHRoaXMuaW52b2tlT25VcGRhdGUoKTtcbiAgfVxuXG4gIGRlc3Ryb3koKSB7XG4gICAgUGxvdGx5LnB1cmdlKHRoaXMuY2hhcnROb2RlKTtcbiAgfVxuXG4gIGNyZWF0ZUNoYXJ0KCkge1xuICAgIHRoaXMuY2hhcnQgPSB0aGlzLmdldFBsb3RseUNoYXJ0KHRoaXMuY2hhcnROb2RlLCB0aGlzLmNoYXJ0VHlwZSk7XG4gIH1cblxuICBzZXRTZWxlY3Rpb24oaXRlbTogSXRlbVZhbHVlLCBjbGVhclNlbGVjdGlvbjogYm9vbGVhbiA9IGZhbHNlKSB7XG4gICAgdGhpcy5zZWxlY3RlZEl0ZW0gPSBpdGVtO1xuICAgIHRoaXMudXBkYXRlRmlsdGVyKCk7XG4gICAgdGhpcy5vbkRhdGFJdGVtU2VsZWN0ZWQoKGl0ZW0gJiYgaXRlbS52YWx1ZSkgfHwgdW5kZWZpbmVkLCBjbGVhclNlbGVjdGlvbik7XG4gIH1cblxuICB1cGRhdGVGaWx0ZXIoKSB7XG4gICAgdGhpcy5maWx0ZXIuc3R5bGUuZGlzcGxheSA9ICEhdGhpcy5zZWxlY3RlZEl0ZW0gPyBcImlubGluZS1ibG9ja1wiIDogXCJub25lXCI7XG4gICAgdGhpcy5maWx0ZXJUZXh0LmlubmVySFRNTCA9ICEhdGhpcy5zZWxlY3RlZEl0ZW1cbiAgICAgID8gXCJGaWx0ZXI6IFtcIiArIHRoaXMuc2VsZWN0ZWRJdGVtLnRleHQgKyBcIl1cIlxuICAgICAgOiBcIlwiO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNyZWF0ZVRvb2xiYXJJdGVtcyh0b29sYmFyOiBIVE1MRGl2RWxlbWVudCkge1xuICAgIHN1cGVyLmNyZWF0ZVRvb2xiYXJJdGVtcyh0b29sYmFyKTtcbiAgICB0aGlzLmZpbHRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgdGhpcy5maWx0ZXIuY2xhc3NOYW1lID0gXCJzdmEtcXVlc3Rpb25fX2ZpbHRlclwiO1xuXG4gICAgdGhpcy5maWx0ZXJUZXh0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgdGhpcy5maWx0ZXJUZXh0LmNsYXNzTmFtZSA9IFwic3ZhLXF1ZXN0aW9uX19maWx0ZXItdGV4dFwiO1xuICAgIHRoaXMuZmlsdGVyLmFwcGVuZENoaWxkKHRoaXMuZmlsdGVyVGV4dCk7XG5cbiAgICBjb25zdCBmaWx0ZXJDbGVhciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgIGZpbHRlckNsZWFyLmNsYXNzTmFtZSA9IFwic3ZhLXF1ZXN0aW9uX19maWx0ZXItY2xlYXJcIjtcbiAgICBmaWx0ZXJDbGVhci5pbm5lckhUTUwgPSBcIkNsZWFyXCI7XG4gICAgZmlsdGVyQ2xlYXIub25jbGljayA9ICgpID0+IHtcbiAgICAgIHRoaXMuc2V0U2VsZWN0aW9uKHVuZGVmaW5lZCk7XG4gICAgfTtcbiAgICB0aGlzLmZpbHRlci5hcHBlbmRDaGlsZChmaWx0ZXJDbGVhcik7XG5cbiAgICAvLyBjb25zdCBmaWx0ZXJDbGVhckFsbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgIC8vIGZpbHRlckNsZWFyQWxsLmNsYXNzTmFtZSA9IFwic3ZhLXF1ZXN0aW9uX19maWx0ZXItY2xlYXJcIjtcbiAgICAvLyBmaWx0ZXJDbGVhckFsbC5pbm5lckhUTUwgPSBcIkNsZWFyIEFsbFwiO1xuICAgIC8vIGZpbHRlckNsZWFyQWxsLm9uY2xpY2sgPSAoKSA9PiB7XG4gICAgLy8gICB0aGlzLnNldFNlbGVjdGlvbih1bmRlZmluZWQsIHRydWUpO1xuICAgIC8vIH07XG4gICAgLy8gdGhpcy5maWx0ZXIuYXBwZW5kQ2hpbGQoZmlsdGVyQ2xlYXJBbGwpO1xuXG4gICAgdG9vbGJhci5hcHBlbmRDaGlsZCh0aGlzLmZpbHRlcik7XG5cbiAgICB0aGlzLnVwZGF0ZUZpbHRlcigpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRQbG90bHlDaGFydChcbiAgICBjaGFydE5vZGU6IEhUTUxFbGVtZW50LFxuICAgIGNoYXJ0VHlwZTogc3RyaW5nXG4gICk6IFByb21pc2U8UGxvdGx5LlBsb3RseUhUTUxFbGVtZW50PiB7XG4gICAgY29uc3QgcXVlc3Rpb24gPSB0aGlzLnF1ZXN0aW9uO1xuICAgIGNvbnN0IGRhdGFzZXRzID0gdGhpcy5nZXREYXRhKCk7XG4gICAgY29uc3QgbGFiZWxzID0gdGhpcy5nZXRMYWJlbHMoKTtcbiAgICBjb25zdCB0cmFjZXM6IGFueSA9IFtdO1xuICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuZ2V0Q29sb3JzKCk7XG5cbiAgICBjb25zdCB0cmFjZUNvbmZpZzogYW55ID0ge1xuICAgICAgdHlwZTogY2hhcnRUeXBlLFxuICAgICAgeTogbGFiZWxzLm1hcChsID0+IHtcbiAgICAgICAgaWYgKGwubGVuZ3RoID4gMzApIHtcbiAgICAgICAgICByZXR1cm4gbC5zdWJzdHJpbmcoMCwgMjcpICsgXCIuLi5cIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbDtcbiAgICAgIH0pLFxuICAgICAgdGV4dDogbGFiZWxzLFxuICAgICAgb3JpZW50YXRpb246IFwiaFwiLFxuICAgICAgbW9kZTogXCJtYXJrZXJzXCIsXG4gICAgICB3aWR0aDogMC41XG4gICAgfTtcblxuICAgIGlmIChkYXRhc2V0cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHRyYWNlQ29uZmlnW1wibWFya2VyXCJdID0geyBjb2xvcjogY29sb3JzIH07XG4gICAgfVxuXG4gICAgZGF0YXNldHMuZm9yRWFjaChkYXRhc2V0ID0+IHtcbiAgICAgIGlmICh0aGlzLmNoYXJ0VHlwZSA9PT0gXCJwaWVcIikge1xuICAgICAgICB0cmFjZXMucHVzaChPYmplY3QuYXNzaWduKHt9LCB0cmFjZUNvbmZpZywgeyB2YWx1ZXM6IGRhdGFzZXQgfSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJhY2VzLnB1c2goT2JqZWN0LmFzc2lnbih7fSwgdHJhY2VDb25maWcsIHsgeDogZGF0YXNldCB9KSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCBoZWlnaHQgPVxuICAgICAgY2hhcnRUeXBlID09PSBcInBpZVwiXG4gICAgICAgID8gNDUwXG4gICAgICAgIDogKGxhYmVscy5sZW5ndGggKyAobGFiZWxzLmxlbmd0aCArIDEpICogMC41KSAqIDIwO1xuXG4gICAgY29uc3QgbGF5b3V0OiBhbnkgPSB7XG4gICAgICBmb250OiB7XG4gICAgICAgIGZhbWlseTogXCJTZWdvZSBVSSwgc2Fucy1zZXJpZlwiLFxuICAgICAgICBzaXplOiAxNCxcbiAgICAgICAgd2VpZ2h0OiBcIm5vcm1hbFwiLFxuICAgICAgICBjb2xvcjogXCIjNDA0MDQwXCJcbiAgICAgIH0sXG4gICAgICBoZWlnaHQ6IGhlaWdodCxcbiAgICAgIG1hcmdpbjoge1xuICAgICAgICB0OiAwLFxuICAgICAgICBiOiAwLFxuICAgICAgICByOiAxMFxuICAgICAgfSxcbiAgICAgIGNvbG9yd2F5OiBjb2xvcnMsXG4gICAgICB5YXhpczoge1xuICAgICAgICBhdXRvbWFyZ2luOiB0cnVlLFxuICAgICAgICB0eXBlOiBcImNhdGVnb3J5XCIsXG4gICAgICAgIHRpY2tsZW46IDUsXG4gICAgICAgIHRpY2tjb2xvcjogXCJ0cmFuc3BhcmVudFwiXG4gICAgICB9LFxuICAgICAgeGF4aXM6IHtcbiAgICAgICAgYXV0b21hcmdpbjogdHJ1ZVxuICAgICAgfSxcbiAgICAgIHBsb3RfYmdjb2xvcjogdGhpcy5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICBwYXBlcl9iZ2NvbG9yOiB0aGlzLmJhY2tncm91bmRDb2xvclxuICAgIH07XG5cbiAgICBjb25zdCBjb25maWcgPSB7XG4gICAgICBkaXNwbGF5bG9nbzogZmFsc2UsXG4gICAgICByZXNwb25zaXZlOiB0cnVlXG4gICAgfTtcblxuICAgIGNvbnN0IHBsb3QgPSBQbG90bHkubmV3UGxvdChjaGFydE5vZGUsIHRyYWNlcywgbGF5b3V0LCBjb25maWcpO1xuXG4gICAgKDxhbnk+Y2hhcnROb2RlKVtcIm9uXCJdKFwicGxvdGx5X2NsaWNrXCIsIChkYXRhOiBhbnkpID0+IHtcbiAgICAgIGlmIChkYXRhLnBvaW50cy5sZW5ndGggPiAwICYmIHRoaXMub25EYXRhSXRlbVNlbGVjdGVkKSB7XG4gICAgICAgIGNvbnN0IGl0ZW1UZXh0ID0gZGF0YS5wb2ludHNbMF0udGV4dDtcbiAgICAgICAgY29uc3QgaXRlbTogSXRlbVZhbHVlID0gdGhpcy5xdWVzdGlvbi5jaG9pY2VzLmZpbHRlcihcbiAgICAgICAgICAoY2hvaWNlOiBJdGVtVmFsdWUpID0+IGNob2ljZS50ZXh0ID09PSBpdGVtVGV4dFxuICAgICAgICApWzBdO1xuICAgICAgICB0aGlzLnNldFNlbGVjdGlvbihpdGVtLCAhZGF0YS5ldmVudC5jdHJsS2V5KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHZhciBkcmFnTGF5ZXIgPSA8SFRNTEVsZW1lbnQ+KFxuICAgICAgY2hhcnROb2RlLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJuc2V3ZHJhZ1wiKVswXVxuICAgICk7XG4gICAgKDxhbnk+Y2hhcnROb2RlKVtcIm9uXCJdKFwicGxvdGx5X2hvdmVyXCIsICgpID0+IHtcbiAgICAgIGRyYWdMYXllci5zdHlsZS5jdXJzb3IgPSBcInBvaW50ZXJcIjtcbiAgICB9KTtcbiAgICAoPGFueT5jaGFydE5vZGUpW1wib25cIl0oXCJwbG90bHlfdW5ob3ZlclwiLCAoKSA9PiB7XG4gICAgICBkcmFnTGF5ZXIuc3R5bGUuY3Vyc29yID0gXCJcIjtcbiAgICB9KTtcblxuICAgIHJldHVybiBwbG90O1xuICB9XG59XG5cblZpc3VhbGl6YXRpb25NYW5hZ2VyLnJlZ2lzdGVyVmlzdWFsaXplcihcImNoZWNrYm94XCIsIFNlbGVjdEJhc2VQbG90bHkpO1xuVmlzdWFsaXphdGlvbk1hbmFnZXIucmVnaXN0ZXJWaXN1YWxpemVyKFwicmFkaW9ncm91cFwiLCBTZWxlY3RCYXNlUGxvdGx5KTtcblZpc3VhbGl6YXRpb25NYW5hZ2VyLnJlZ2lzdGVyVmlzdWFsaXplcihcImRyb3Bkb3duXCIsIFNlbGVjdEJhc2VQbG90bHkpO1xuVmlzdWFsaXphdGlvbk1hbmFnZXIucmVnaXN0ZXJWaXN1YWxpemVyKFwiaW1hZ2VwaWNrZXJcIiwgU2VsZWN0QmFzZVBsb3RseSk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvcGxvdGx5L3NlbGVjdEJhc2UudHMiLCJtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfMTRfXztcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCB7XCJyb290XCI6XCJjM1wiLFwiY29tbW9uanMyXCI6XCJjM1wiLFwiY29tbW9uanNcIjpcImMzXCIsXCJhbWRcIjpcImMzXCJ9XG4vLyBtb2R1bGUgaWQgPSAxNFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJleHBvcnQgKiBmcm9tIFwiLi9tYXRyaXhcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3NlbGVjdEJhc2VcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3JhdGluZ1wiO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2MzL2luZGV4LnRzIiwiZXhwb3J0ICogZnJvbSBcIi4vbWF0cml4XCI7XG5leHBvcnQgKiBmcm9tIFwiLi9zZWxlY3RCYXNlXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9yYXRpbmdcIjtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9jaGFydGpzL2luZGV4LnRzIiwiaW1wb3J0ICogYXMgJCBmcm9tIFwianF1ZXJ5XCI7XG5pbXBvcnQgeyBTdXJ2ZXlNb2RlbCwgUXVlc3Rpb24gfSBmcm9tIFwic3VydmV5LWNvcmVcIjtcbmltcG9ydCBcIi4vZGF0YXRhYmxlcy5zY3NzXCI7XG5cbmludGVyZmFjZSBEYXRhVGFibGVzT3B0aW9ucyB7XG4gIGJ1dHRvbnM6XG4gICAgfCBib29sZWFuXG4gICAgfCBzdHJpbmdbXVxuICAgIHwgRGF0YVRhYmxlcy5CdXR0b25zU2V0dGluZ3NcbiAgICB8IERhdGFUYWJsZXMuQnV0dG9uU2V0dGluZ3NbXTtcblxuICBkb206IHN0cmluZztcblxuICBvcmRlckZpeGVkOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+IHwgQXJyYXk8QXJyYXk8bnVtYmVyIHwgc3RyaW5nPj4gfCBvYmplY3Q7XG5cbiAgcm93R3JvdXA6IGJvb2xlYW4gfCBEYXRhVGFibGVzLlJvd0dyb3VwU2V0dGluZ3M7XG5cbiAgaGVhZGVyQ2FsbGJhY2s6IERhdGFUYWJsZXMuRnVuY3Rpb25IZWFkZXJDYWxsYmFjaztcbn1cblxuZXhwb3J0IGNsYXNzIERhdGFUYWJsZXMge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHRhcmdldE5vZGU6IEhUTUxFbGVtZW50LFxuICAgIHByaXZhdGUgc3VydmV5OiBTdXJ2ZXlNb2RlbCxcbiAgICBwcml2YXRlIGRhdGE6IEFycmF5PE9iamVjdD4sXG4gICAgcHJpdmF0ZSBvcHRpb25zOiBEYXRhVGFibGVzT3B0aW9uc1xuICApIHt9XG5cbiAgZ3JvdXBCeTogQXJyYXk8c3RyaW5nPiA9IFtdO1xuXG4gIHJlbmRlcigpIHtcbiAgICBjb25zdCB0YWJsZU5vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwidGFibGVcIik7XG4gICAgY29uc3QgY3JlYXRlR3JvdXBpbmdCdXR0b24gPSB0aGlzLmNyZWF0ZUdyb3VwaW5nQnV0dG9uO1xuICAgIGNvbnN0IGNyZWF0ZVNlbGVjdEJ1dHRvbiA9IHRoaXMuY3JlYXRlU2VsZWN0QnV0dG9uO1xuXG4gICAgdmFyIGNvbHVtbnNEYXRhOiBhbnkgPSB0aGlzLmdldENvbHVtbnMoKS5tYXAoKGM6IGFueSkgPT4gYy5kYXRhKTtcblxuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMgfHwge1xuICAgICAgYnV0dG9uczogW1wiY29weVwiLCBcImNzdlwiLCBcInByaW50XCJdLFxuICAgICAgZG9tOiBcIkJsZnJ0aXBcIixcbiAgICAgIGRhdGE6IHRoaXMuZGF0YSxcbiAgICAgIGNvbHVtbnM6IHRoaXMuZ2V0Q29sdW1ucygpLFxuICAgICAgLy8gb3JkZXJGaXhlZDogW1sxLCBcImFzY1wiXV0sXG4gICAgICByb3dHcm91cDoge1xuICAgICAgICBkYXRhU3JjOiBjb2x1bW5zRGF0YVswXSxcbiAgICAgICAgZW5kUmVuZGVyOiBmdW5jdGlvbihyb3dzLCBncm91cCkge1xuICAgICAgICAgIHJldHVybiBcIkNvdW50OiBcIiArIHJvd3MuZGF0YSgpLmNvdW50KCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBzZWxlY3Q6IFwiYXBpXCIsXG4gICAgICBoZWFkZXJDYWxsYmFjazogKHRoZWFkLCBkYXRhLCBzdGFydCwgZW5kLCBkaXNwbGF5KSA9PiB7XG4gICAgICAgIHZhciBkYXRhdGFibGVBcGkgPSAkKHRhYmxlTm9kZSlcbiAgICAgICAgICAuZGF0YVRhYmxlKClcbiAgICAgICAgICAuYXBpKCk7XG4gICAgICAgICQodGhlYWQpXG4gICAgICAgICAgLmNoaWxkcmVuKFwidGhcIilcbiAgICAgICAgICAuZWFjaChmdW5jdGlvbihpbmRleCwgbm9kZSkge1xuICAgICAgICAgICAgdmFyIHRoTm9kZSA9ICQodGhpcyk7XG5cbiAgICAgICAgICAgIGlmICh0aE5vZGUuaGFzKFwiYnV0dG9uXCIpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICB0aE5vZGUucHJlcGVuZChcbiAgICAgICAgICAgICAgICBjcmVhdGVHcm91cGluZ0J1dHRvbihkYXRhdGFibGVBcGksIGNvbHVtbnNEYXRhW2luZGV4XSlcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhOb2RlLnByZXBlbmQoXG4gICAgICAgICAgICAgICAgY3JlYXRlU2VsZWN0QnV0dG9uKGRhdGF0YWJsZUFwaSwgaW5kZXgsIGNvbHVtbnNEYXRhW2luZGV4XSlcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgdGhpcy50YXJnZXROb2RlLmFwcGVuZENoaWxkKHRhYmxlTm9kZSk7XG4gICAgdGFibGVOb2RlLmNsYXNzTmFtZSA9IFwic2EtZGF0YXRhYmxlIGRpc3BsYXkgZGF0YVRhYmxlXCI7XG5cbiAgICBjb25zdCBkYXRhdGFibGVBcGkgPSAkKHRhYmxlTm9kZSkuRGF0YVRhYmxlKG9wdGlvbnMpO1xuICAgIGRhdGF0YWJsZUFwaVxuICAgICAgLnJvd0dyb3VwKClcbiAgICAgIC5lbmFibGUoZmFsc2UpXG4gICAgICAuZHJhdygpO1xuXG4gICAgLy8gZGF0YXRhYmxlQXBpLm9uKFwicm93Z3JvdXAtZGF0YXNyY1wiLCBmdW5jdGlvbihlLCBkdCwgdmFsKSB7XG4gICAgLy8gZGF0YXRhYmxlQXBpLm9yZGVyLmZpeGVkKHsgcHJlOiBbW2NvbHVtbnNEYXRhLmluZGV4T2YodmFsKSwgXCJhc2NcIl1dIH0pLmRyYXcoKTtcbiAgICAvLyB9KTtcbiAgfVxuXG4gIGNyZWF0ZVNlbGVjdEJ1dHRvbiA9IChcbiAgICBkYXRhdGFibGVBcGk6IERhdGFUYWJsZXMuQXBpLFxuICAgIGNvbElkeDogbnVtYmVyLFxuICAgIGNvbHVtbk5hbWU6IHN0cmluZ1xuICApOiBIVE1MQnV0dG9uRWxlbWVudCA9PiB7XG4gICAgY29uc3QgYnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJ1dHRvblwiKTtcbiAgICBidXR0b24uaW5uZXJIVE1MID0gXCJTZWxlY3QgTWVcIjtcbiAgICBidXR0b24ub25jbGljayA9IGUgPT4ge1xuICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICg8YW55PmRhdGF0YWJsZUFwaS5jb2x1bW5zKCkpLmRlc2VsZWN0KCk7XG4gICAgICAoPGFueT5kYXRhdGFibGVBcGkuY29sdW1uKGNvbElkeCkpLnNlbGVjdCgpO1xuICAgICAgISF0aGlzLm9uQ29sdW1uU2VsZWN0ZWQgJiYgdGhpcy5vbkNvbHVtblNlbGVjdGVkKGNvbHVtbk5hbWUpO1xuICAgIH07XG4gICAgcmV0dXJuIGJ1dHRvbjtcbiAgfTtcblxuICBjcmVhdGVHcm91cGluZ0J1dHRvbiA9IChcbiAgICBkYXRhdGFibGVBcGk6IERhdGFUYWJsZXMuQXBpLFxuICAgIGNvbHVtbk5hbWU6IHN0cmluZ1xuICApOiBIVE1MQnV0dG9uRWxlbWVudCA9PiB7XG4gICAgY29uc3QgYnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJ1dHRvblwiKTtcbiAgICBidXR0b24uaW5uZXJIVE1MID0gXCJHcm91cCBCeSBNZVwiO1xuXG4gICAgYnV0dG9uLm9uY2xpY2sgPSBlID0+IHtcbiAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5ncm91cEJ5LmluZGV4T2YoY29sdW1uTmFtZSk7XG4gICAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICAgIHRoaXMuZ3JvdXBCeS5wdXNoKGNvbHVtbk5hbWUpO1xuICAgICAgICBidXR0b24uaW5uZXJIVE1MID0gXCJVbmdyb3VwIEJ5IE1lXCI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBidXR0b24uaW5uZXJIVE1MID0gXCJHcm91cCBCeSBNZVwiO1xuICAgICAgICB0aGlzLmdyb3VwQnkuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIH1cblxuICAgICAgZGF0YXRhYmxlQXBpLnJvd0dyb3VwKCkuZW5hYmxlKHRoaXMuZ3JvdXBCeS5sZW5ndGggPiAwKTtcbiAgICAgIGlmICh0aGlzLmdyb3VwQnkubGVuZ3RoID4gMCkge1xuICAgICAgICBkYXRhdGFibGVBcGkucm93R3JvdXAoKS5kYXRhU3JjKDxhbnk+dGhpcy5ncm91cEJ5KTtcbiAgICAgIH1cbiAgICAgIGRhdGF0YWJsZUFwaS5kcmF3KCk7XG4gICAgfTtcblxuICAgIHJldHVybiBidXR0b247XG4gIH07XG5cbiAgZ2V0Q29sdW1ucygpOiBBcnJheTxPYmplY3Q+IHtcbiAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5zdXJ2ZXkuZ2V0QWxsUXVlc3Rpb25zKCkubWFwKHF1ZXN0aW9uID0+IHtcbiAgICAgIGNvbnN0IHEgPSA8UXVlc3Rpb24+cXVlc3Rpb247XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRhdGE6IHEubmFtZSxcbiAgICAgICAgc1RpdGxlOiAocS50aXRsZSB8fCBcIlwiKS50cmltKCkgfHwgcS5uYW1lLFxuICAgICAgICBtUmVuZGVyOiAoZGF0YTogb2JqZWN0LCB0eXBlOiBzdHJpbmcsIHJvdzogb2JqZWN0KSA9PiB7XG4gICAgICAgICAgdGhpcy5zdXJ2ZXkuZGF0YSA9IHJvdztcbiAgICAgICAgICB2YXIgZGlzcGxheVZhbHVlID0gcS5kaXNwbGF5VmFsdWU7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICh0eXBlb2YgZGlzcGxheVZhbHVlID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgID8gZGlzcGxheVZhbHVlXG4gICAgICAgICAgICAgIDogSlNPTi5zdHJpbmdpZnkoZGlzcGxheVZhbHVlKSkgfHwgXCJcIlxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICByZXR1cm4gY29sdW1ucztcbiAgfVxuXG4gIHB1YmxpYyBvbkNvbHVtblNlbGVjdGVkOiAoZGF0YU5hbWU6IHN0cmluZykgPT4gdm9pZDtcbn1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9kYXRhdGFibGVzL2RhdGF0YWJsZXMudHMiLCJleHBvcnQgKiBmcm9tIFwiLi9zZWxlY3RCYXNlXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9yYXRpbmdcIjtcbmV4cG9ydCAqIGZyb20gXCIuL21hdHJpeFwiO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL3Bsb3RseS9pbmRleC50cyIsImltcG9ydCB7IFZpc3VhbGl6YXRpb25NYW5hZ2VyIH0gZnJvbSBcIi4vdmlzdWFsaXphdGlvbk1hbmFnZXJcIjtcbmltcG9ydCB7IFF1ZXN0aW9uLCBRdWVzdGlvbk1hdHJpeERyb3Bkb3duTW9kZWwgfSBmcm9tIFwic3VydmV5LWNvcmVcIjtcbmltcG9ydCB7IFZpc3VhbGl6YXRpb25QYW5lbER5bmFtaWMgfSBmcm9tIFwiLi92aXN1YWxpemF0aW9uUGFuZWxEeW5hbWljXCI7XG5cbmV4cG9ydCBjbGFzcyBWaXN1YWxpemF0aW9uTWF0cml4RHluYW1pYyBleHRlbmRzIFZpc3VhbGl6YXRpb25QYW5lbER5bmFtaWMge1xuICBjb25zdHJ1Y3RvcihcbiAgICB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudCxcbiAgICBxdWVzdGlvbjogUXVlc3Rpb24sXG4gICAgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgICBvcHRpb25zPzogT2JqZWN0XG4gICkge1xuICAgIHN1cGVyKHRhcmdldEVsZW1lbnQsIHF1ZXN0aW9uLCBkYXRhLCBvcHRpb25zKTtcbiAgfVxuXG4gIGdldFF1ZXN0aW9ucygpIHtcbiAgICBjb25zdCBtYXRyaXhkeW5hbWljOiBRdWVzdGlvbk1hdHJpeERyb3Bkb3duTW9kZWwgPSA8YW55PnRoaXMucXVlc3Rpb247XG4gICAgY29uc3QgdmlzaWJsZVJvd3MgPSBtYXRyaXhkeW5hbWljLnZpc2libGVSb3dzO1xuXG4gICAgaWYgKHZpc2libGVSb3dzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFtdO1xuXG4gICAgcmV0dXJuIHZpc2libGVSb3dzWzBdLmNlbGxzLm1hcChjID0+IGMucXVlc3Rpb24pO1xuICB9XG59XG5cblZpc3VhbGl6YXRpb25NYW5hZ2VyLnJlZ2lzdGVyVmlzdWFsaXplcihcbiAgXCJtYXRyaXhkeW5hbWljXCIsXG4gIFZpc3VhbGl6YXRpb25NYXRyaXhEeW5hbWljXG4pO1xuXG5WaXN1YWxpemF0aW9uTWFuYWdlci5yZWdpc3RlclZpc3VhbGl6ZXIoXG4gIFwibWF0cml4ZHJvcGRvd25cIixcbiAgVmlzdWFsaXphdGlvbk1hdHJpeER5bmFtaWNcbik7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvdmlzdWFsaXphdGlvbk1hdHJpeER5bmFtaWMudHMiLCJpbXBvcnQgeyBRdWVzdGlvbiB9IGZyb20gXCJzdXJ2ZXktY29yZVwiO1xuaW1wb3J0IFdvcmRDbG91ZExpYiBmcm9tIFwid29yZGNsb3VkXCI7XG5pbXBvcnQgeyBWaXN1YWxpemVyQmFzZSB9IGZyb20gXCIuLi92aXN1YWxpemVyQmFzZVwiO1xuaW1wb3J0IHsgVmlzdWFsaXphdGlvbk1hbmFnZXIgfSBmcm9tIFwiLi4vdmlzdWFsaXphdGlvbk1hbmFnZXJcIjtcbmltcG9ydCB7IHRleHRIZWxwZXIgfSBmcm9tIFwiLi9zdG9wd29yZHMvaW5kZXhcIjtcblxuZXhwb3J0IGNsYXNzIFdvcmRDbG91ZCBleHRlbmRzIFZpc3VhbGl6ZXJCYXNlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgdGFyZ2V0RWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgcXVlc3Rpb246IFF1ZXN0aW9uLFxuICAgIGRhdGE6IEFycmF5PHsgW2luZGV4OiBzdHJpbmddOiBhbnkgfT4sXG4gICAgb3B0aW9ucz86IE9iamVjdFxuICApIHtcbiAgICBzdXBlcih0YXJnZXRFbGVtZW50LCBxdWVzdGlvbiwgZGF0YSwgb3B0aW9ucyk7XG4gIH1cblxuICBwcml2YXRlIGNsb3VkOiBhbnk7XG5cbiAgZ2V0RGF0YSgpIHtcbiAgICBsZXQgcmVzdWx0OiB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9ID0ge307XG5cbiAgICBsZXQgc3RvcFdvcmRzID0gdGV4dEhlbHBlci5nZXRTdG9wV29yZHMoKTtcbiAgICBsZXQgc3RvcFRoZVdvcmQgPSAod29yZDogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAoc3RvcFdvcmRzLmluZGV4T2Yod29yZCkgIT09IC0xKSB7XG4gICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdvcmQ7XG4gICAgfTtcblxuICAgIGxldCBwcm9jZXNzU3RyaW5nID0gKHJvdzogc3RyaW5nKSA9PiB7XG4gICAgICByb3cgPSBcIlwiICsgcm93O1xuICAgICAgaWYgKCEhcm93KSB7XG4gICAgICAgIHJvdy5zcGxpdChcIiBcIikuZm9yRWFjaCh3b3JkID0+IHtcbiAgICAgICAgICB3b3JkID0gc3RvcFRoZVdvcmQod29yZC50b0xvd2VyQ2FzZSgpIHx8IFwiXCIpO1xuICAgICAgICAgIGlmICghIXdvcmQpIHtcbiAgICAgICAgICAgIGlmICghcmVzdWx0W3dvcmRdKSB7XG4gICAgICAgICAgICAgIHJlc3VsdFt3b3JkXSA9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXN1bHRbd29yZF0rKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLmRhdGEuZm9yRWFjaChyb3cgPT4ge1xuICAgICAgY29uc3Qgcm93VmFsdWU6IGFueSA9IHJvd1t0aGlzLnF1ZXN0aW9uLm5hbWVdO1xuICAgICAgaWYgKCEhcm93VmFsdWUpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocm93VmFsdWUpKSB7XG4gICAgICAgICAgcm93VmFsdWUuZm9yRWFjaChwcm9jZXNzU3RyaW5nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHJvd1ZhbHVlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhyb3dWYWx1ZSkuZm9yRWFjaChrZXkgPT4gcHJvY2Vzc1N0cmluZyhyb3dWYWx1ZVtrZXldKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHByb2Nlc3NTdHJpbmcocm93VmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHJlc3VsdCkubWFwKGtleSA9PiB7XG4gICAgICByZXR1cm4gW2tleSwgcmVzdWx0W2tleV1dO1xuICAgIH0pO1xuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IGRhdGEgPSB0aGlzLmdldERhdGEoKTtcbiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLmdldENvbG9ycygpO1xuICAgIGNvbnN0IGNhbnZhc05vZGUgPSA8SFRNTENhbnZhc0VsZW1lbnQ+ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtcbiAgICBjb25zdCBlbXB0eVRleHROb2RlID0gPEhUTUxFbGVtZW50PmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJwXCIpO1xuICAgIGVtcHR5VGV4dE5vZGUuaW5uZXJIVE1MID0gXCJUaGVyZSBpcyBubyByZXN1bHRzIHlldFwiO1xuXG4gICAgaWYgKGRhdGEubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnRhcmdldEVsZW1lbnQuYXBwZW5kQ2hpbGQoZW1wdHlUZXh0Tm9kZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy50YXJnZXRFbGVtZW50LmFwcGVuZENoaWxkKGNhbnZhc05vZGUpO1xuXG4gICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgbGlzdDogZGF0YSxcbiAgICAgIHdlaWdodEZhY3RvcjogMjAsXG4gICAgICBmb250RmFtaWx5OiBcIlNlZ29lIFVJIEJvbGQsIHNhbnMtc2VyaWZcIixcbiAgICAgIGNvbG9yOiAod29yZDogc3RyaW5nLCB3ZWlnaHQ6IG51bWJlcikgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRSYW5kb21Db2xvcigpO1xuICAgICAgfSxcbiAgICAgIHJvdGF0ZVJhdGlvOiAwLjUsXG4gICAgICByb3RhdGlvblN0ZXBzOiAyLFxuICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLmJhY2tncm91bmRDb2xvcixcbiAgICAgIGNsaWNrOiBmdW5jdGlvbihpdGVtOiBhbnkpIHtcbiAgICAgICAgY29uc29sZS5sb2coaXRlbVswXSArIFwiOiBcIiArIGl0ZW1bMV0pO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLmNsb3VkID0gV29yZENsb3VkTGliKGNhbnZhc05vZGUsIGNvbmZpZyk7XG4gIH1cblxuICBkZXN0cm95KCkge1xuICAgIGlmICghIXRoaXMuY2xvdWQpIHtcbiAgICAgIHRoaXMuY2xvdWQgPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLnRhcmdldEVsZW1lbnQuaW5uZXJIVE1MID0gXCJcIjtcbiAgICB9XG4gIH1cbn1cblxuVmlzdWFsaXphdGlvbk1hbmFnZXIucmVnaXN0ZXJWaXN1YWxpemVyKFwidGV4dFwiLCBXb3JkQ2xvdWQpO1xuVmlzdWFsaXphdGlvbk1hbmFnZXIucmVnaXN0ZXJWaXN1YWxpemVyKFwiY29tbWVudFwiLCBXb3JkQ2xvdWQpO1xuVmlzdWFsaXphdGlvbk1hbmFnZXIucmVnaXN0ZXJWaXN1YWxpemVyKFwibXVsdGlwbGV0ZXh0XCIsIFdvcmRDbG91ZCk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvd29yZGNsb3VkL3dvcmRjbG91ZC50cyIsIi8qKlxuICogbWF0Y2hlc1NlbGVjdG9yIHYyLjAuMlxuICogbWF0Y2hlc1NlbGVjdG9yKCBlbGVtZW50LCAnLnNlbGVjdG9yJyApXG4gKiBNSVQgbGljZW5zZVxuICovXG5cbi8qanNoaW50IGJyb3dzZXI6IHRydWUsIHN0cmljdDogdHJ1ZSwgdW5kZWY6IHRydWUsIHVudXNlZDogdHJ1ZSAqL1xuXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIC8qZ2xvYmFsIGRlZmluZTogZmFsc2UsIG1vZHVsZTogZmFsc2UgKi9cbiAgJ3VzZSBzdHJpY3QnO1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgaWYgKCB0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCApIHtcbiAgICAvLyBBTURcbiAgICBkZWZpbmUoIGZhY3RvcnkgKTtcbiAgfSBlbHNlIGlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgICAvLyBDb21tb25KU1xuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuICB9IGVsc2Uge1xuICAgIC8vIGJyb3dzZXIgZ2xvYmFsXG4gICAgd2luZG93Lm1hdGNoZXNTZWxlY3RvciA9IGZhY3RvcnkoKTtcbiAgfVxuXG59KCB3aW5kb3csIGZ1bmN0aW9uIGZhY3RvcnkoKSB7XG4gICd1c2Ugc3RyaWN0JztcblxuICB2YXIgbWF0Y2hlc01ldGhvZCA9ICggZnVuY3Rpb24oKSB7XG4gICAgdmFyIEVsZW1Qcm90byA9IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZTtcbiAgICAvLyBjaGVjayBmb3IgdGhlIHN0YW5kYXJkIG1ldGhvZCBuYW1lIGZpcnN0XG4gICAgaWYgKCBFbGVtUHJvdG8ubWF0Y2hlcyApIHtcbiAgICAgIHJldHVybiAnbWF0Y2hlcyc7XG4gICAgfVxuICAgIC8vIGNoZWNrIHVuLXByZWZpeGVkXG4gICAgaWYgKCBFbGVtUHJvdG8ubWF0Y2hlc1NlbGVjdG9yICkge1xuICAgICAgcmV0dXJuICdtYXRjaGVzU2VsZWN0b3InO1xuICAgIH1cbiAgICAvLyBjaGVjayB2ZW5kb3IgcHJlZml4ZXNcbiAgICB2YXIgcHJlZml4ZXMgPSBbICd3ZWJraXQnLCAnbW96JywgJ21zJywgJ28nIF07XG5cbiAgICBmb3IgKCB2YXIgaT0wOyBpIDwgcHJlZml4ZXMubGVuZ3RoOyBpKysgKSB7XG4gICAgICB2YXIgcHJlZml4ID0gcHJlZml4ZXNbaV07XG4gICAgICB2YXIgbWV0aG9kID0gcHJlZml4ICsgJ01hdGNoZXNTZWxlY3Rvcic7XG4gICAgICBpZiAoIEVsZW1Qcm90b1sgbWV0aG9kIF0gKSB7XG4gICAgICAgIHJldHVybiBtZXRob2Q7XG4gICAgICB9XG4gICAgfVxuICB9KSgpO1xuXG4gIHJldHVybiBmdW5jdGlvbiBtYXRjaGVzU2VsZWN0b3IoIGVsZW0sIHNlbGVjdG9yICkge1xuICAgIHJldHVybiBlbGVtWyBtYXRjaGVzTWV0aG9kIF0oIHNlbGVjdG9yICk7XG4gIH07XG5cbn0pKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9kZXNhbmRyby1tYXRjaGVzLXNlbGVjdG9yL21hdGNoZXMtc2VsZWN0b3IuanNcbi8vIG1vZHVsZSBpZCA9IDIxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIHJlbW92ZWQgYnkgZXh0cmFjdC10ZXh0LXdlYnBhY2stcGx1Z2luXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvZGF0YXRhYmxlcy9kYXRhdGFibGVzLnNjc3Ncbi8vIG1vZHVsZSBpZCA9IDIyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vIHJlbW92ZWQgYnkgZXh0cmFjdC10ZXh0LXdlYnBhY2stcGx1Z2luXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvaW5kZXguc2Nzc1xuLy8gbW9kdWxlIGlkID0gMjNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyoqXG4gKiBGaXp6eSBVSSB1dGlscyB2Mi4wLjdcbiAqIE1JVCBsaWNlbnNlXG4gKi9cblxuLypqc2hpbnQgYnJvd3NlcjogdHJ1ZSwgdW5kZWY6IHRydWUsIHVudXNlZDogdHJ1ZSwgc3RyaWN0OiB0cnVlICovXG5cbiggZnVuY3Rpb24oIHdpbmRvdywgZmFjdG9yeSApIHtcbiAgLy8gdW5pdmVyc2FsIG1vZHVsZSBkZWZpbml0aW9uXG4gIC8qanNoaW50IHN0cmljdDogZmFsc2UgKi8gLypnbG9iYWxzIGRlZmluZSwgbW9kdWxlLCByZXF1aXJlICovXG5cbiAgaWYgKCB0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCApIHtcbiAgICAvLyBBTURcbiAgICBkZWZpbmUoIFtcbiAgICAgICdkZXNhbmRyby1tYXRjaGVzLXNlbGVjdG9yL21hdGNoZXMtc2VsZWN0b3InXG4gICAgXSwgZnVuY3Rpb24oIG1hdGNoZXNTZWxlY3RvciApIHtcbiAgICAgIHJldHVybiBmYWN0b3J5KCB3aW5kb3csIG1hdGNoZXNTZWxlY3RvciApO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKCB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzICkge1xuICAgIC8vIENvbW1vbkpTXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KFxuICAgICAgd2luZG93LFxuICAgICAgcmVxdWlyZSgnZGVzYW5kcm8tbWF0Y2hlcy1zZWxlY3RvcicpXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBicm93c2VyIGdsb2JhbFxuICAgIHdpbmRvdy5maXp6eVVJVXRpbHMgPSBmYWN0b3J5KFxuICAgICAgd2luZG93LFxuICAgICAgd2luZG93Lm1hdGNoZXNTZWxlY3RvclxuICAgICk7XG4gIH1cblxufSggd2luZG93LCBmdW5jdGlvbiBmYWN0b3J5KCB3aW5kb3csIG1hdGNoZXNTZWxlY3RvciApIHtcblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSB7fTtcblxuLy8gLS0tLS0gZXh0ZW5kIC0tLS0tIC8vXG5cbi8vIGV4dGVuZHMgb2JqZWN0c1xudXRpbHMuZXh0ZW5kID0gZnVuY3Rpb24oIGEsIGIgKSB7XG4gIGZvciAoIHZhciBwcm9wIGluIGIgKSB7XG4gICAgYVsgcHJvcCBdID0gYlsgcHJvcCBdO1xuICB9XG4gIHJldHVybiBhO1xufTtcblxuLy8gLS0tLS0gbW9kdWxvIC0tLS0tIC8vXG5cbnV0aWxzLm1vZHVsbyA9IGZ1bmN0aW9uKCBudW0sIGRpdiApIHtcbiAgcmV0dXJuICggKCBudW0gJSBkaXYgKSArIGRpdiApICUgZGl2O1xufTtcblxuLy8gLS0tLS0gbWFrZUFycmF5IC0tLS0tIC8vXG5cbnZhciBhcnJheVNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuXG4vLyB0dXJuIGVsZW1lbnQgb3Igbm9kZUxpc3QgaW50byBhbiBhcnJheVxudXRpbHMubWFrZUFycmF5ID0gZnVuY3Rpb24oIG9iaiApIHtcbiAgaWYgKCBBcnJheS5pc0FycmF5KCBvYmogKSApIHtcbiAgICAvLyB1c2Ugb2JqZWN0IGlmIGFscmVhZHkgYW4gYXJyYXlcbiAgICByZXR1cm4gb2JqO1xuICB9XG4gIC8vIHJldHVybiBlbXB0eSBhcnJheSBpZiB1bmRlZmluZWQgb3IgbnVsbC4gIzZcbiAgaWYgKCBvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQgKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgdmFyIGlzQXJyYXlMaWtlID0gdHlwZW9mIG9iaiA9PSAnb2JqZWN0JyAmJiB0eXBlb2Ygb2JqLmxlbmd0aCA9PSAnbnVtYmVyJztcbiAgaWYgKCBpc0FycmF5TGlrZSApIHtcbiAgICAvLyBjb252ZXJ0IG5vZGVMaXN0IHRvIGFycmF5XG4gICAgcmV0dXJuIGFycmF5U2xpY2UuY2FsbCggb2JqICk7XG4gIH1cblxuICAvLyBhcnJheSBvZiBzaW5nbGUgaW5kZXhcbiAgcmV0dXJuIFsgb2JqIF07XG59O1xuXG4vLyAtLS0tLSByZW1vdmVGcm9tIC0tLS0tIC8vXG5cbnV0aWxzLnJlbW92ZUZyb20gPSBmdW5jdGlvbiggYXJ5LCBvYmogKSB7XG4gIHZhciBpbmRleCA9IGFyeS5pbmRleE9mKCBvYmogKTtcbiAgaWYgKCBpbmRleCAhPSAtMSApIHtcbiAgICBhcnkuc3BsaWNlKCBpbmRleCwgMSApO1xuICB9XG59O1xuXG4vLyAtLS0tLSBnZXRQYXJlbnQgLS0tLS0gLy9cblxudXRpbHMuZ2V0UGFyZW50ID0gZnVuY3Rpb24oIGVsZW0sIHNlbGVjdG9yICkge1xuICB3aGlsZSAoIGVsZW0ucGFyZW50Tm9kZSAmJiBlbGVtICE9IGRvY3VtZW50LmJvZHkgKSB7XG4gICAgZWxlbSA9IGVsZW0ucGFyZW50Tm9kZTtcbiAgICBpZiAoIG1hdGNoZXNTZWxlY3RvciggZWxlbSwgc2VsZWN0b3IgKSApIHtcbiAgICAgIHJldHVybiBlbGVtO1xuICAgIH1cbiAgfVxufTtcblxuLy8gLS0tLS0gZ2V0UXVlcnlFbGVtZW50IC0tLS0tIC8vXG5cbi8vIHVzZSBlbGVtZW50IGFzIHNlbGVjdG9yIHN0cmluZ1xudXRpbHMuZ2V0UXVlcnlFbGVtZW50ID0gZnVuY3Rpb24oIGVsZW0gKSB7XG4gIGlmICggdHlwZW9mIGVsZW0gPT0gJ3N0cmluZycgKSB7XG4gICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIGVsZW0gKTtcbiAgfVxuICByZXR1cm4gZWxlbTtcbn07XG5cbi8vIC0tLS0tIGhhbmRsZUV2ZW50IC0tLS0tIC8vXG5cbi8vIGVuYWJsZSAub250eXBlIHRvIHRyaWdnZXIgZnJvbSAuYWRkRXZlbnRMaXN0ZW5lciggZWxlbSwgJ3R5cGUnIClcbnV0aWxzLmhhbmRsZUV2ZW50ID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICB2YXIgbWV0aG9kID0gJ29uJyArIGV2ZW50LnR5cGU7XG4gIGlmICggdGhpc1sgbWV0aG9kIF0gKSB7XG4gICAgdGhpc1sgbWV0aG9kIF0oIGV2ZW50ICk7XG4gIH1cbn07XG5cbi8vIC0tLS0tIGZpbHRlckZpbmRFbGVtZW50cyAtLS0tLSAvL1xuXG51dGlscy5maWx0ZXJGaW5kRWxlbWVudHMgPSBmdW5jdGlvbiggZWxlbXMsIHNlbGVjdG9yICkge1xuICAvLyBtYWtlIGFycmF5IG9mIGVsZW1zXG4gIGVsZW1zID0gdXRpbHMubWFrZUFycmF5KCBlbGVtcyApO1xuICB2YXIgZmZFbGVtcyA9IFtdO1xuXG4gIGVsZW1zLmZvckVhY2goIGZ1bmN0aW9uKCBlbGVtICkge1xuICAgIC8vIGNoZWNrIHRoYXQgZWxlbSBpcyBhbiBhY3R1YWwgZWxlbWVudFxuICAgIGlmICggISggZWxlbSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50ICkgKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIGFkZCBlbGVtIGlmIG5vIHNlbGVjdG9yXG4gICAgaWYgKCAhc2VsZWN0b3IgKSB7XG4gICAgICBmZkVsZW1zLnB1c2goIGVsZW0gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gZmlsdGVyICYgZmluZCBpdGVtcyBpZiB3ZSBoYXZlIGEgc2VsZWN0b3JcbiAgICAvLyBmaWx0ZXJcbiAgICBpZiAoIG1hdGNoZXNTZWxlY3RvciggZWxlbSwgc2VsZWN0b3IgKSApIHtcbiAgICAgIGZmRWxlbXMucHVzaCggZWxlbSApO1xuICAgIH1cbiAgICAvLyBmaW5kIGNoaWxkcmVuXG4gICAgdmFyIGNoaWxkRWxlbXMgPSBlbGVtLnF1ZXJ5U2VsZWN0b3JBbGwoIHNlbGVjdG9yICk7XG4gICAgLy8gY29uY2F0IGNoaWxkRWxlbXMgdG8gZmlsdGVyRm91bmQgYXJyYXlcbiAgICBmb3IgKCB2YXIgaT0wOyBpIDwgY2hpbGRFbGVtcy5sZW5ndGg7IGkrKyApIHtcbiAgICAgIGZmRWxlbXMucHVzaCggY2hpbGRFbGVtc1tpXSApO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIGZmRWxlbXM7XG59O1xuXG4vLyAtLS0tLSBkZWJvdW5jZU1ldGhvZCAtLS0tLSAvL1xuXG51dGlscy5kZWJvdW5jZU1ldGhvZCA9IGZ1bmN0aW9uKCBfY2xhc3MsIG1ldGhvZE5hbWUsIHRocmVzaG9sZCApIHtcbiAgdGhyZXNob2xkID0gdGhyZXNob2xkIHx8IDEwMDtcbiAgLy8gb3JpZ2luYWwgbWV0aG9kXG4gIHZhciBtZXRob2QgPSBfY2xhc3MucHJvdG90eXBlWyBtZXRob2ROYW1lIF07XG4gIHZhciB0aW1lb3V0TmFtZSA9IG1ldGhvZE5hbWUgKyAnVGltZW91dCc7XG5cbiAgX2NsYXNzLnByb3RvdHlwZVsgbWV0aG9kTmFtZSBdID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHRpbWVvdXQgPSB0aGlzWyB0aW1lb3V0TmFtZSBdO1xuICAgIGNsZWFyVGltZW91dCggdGltZW91dCApO1xuXG4gICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgdmFyIF90aGlzID0gdGhpcztcbiAgICB0aGlzWyB0aW1lb3V0TmFtZSBdID0gc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG4gICAgICBtZXRob2QuYXBwbHkoIF90aGlzLCBhcmdzICk7XG4gICAgICBkZWxldGUgX3RoaXNbIHRpbWVvdXROYW1lIF07XG4gICAgfSwgdGhyZXNob2xkICk7XG4gIH07XG59O1xuXG4vLyAtLS0tLSBkb2NSZWFkeSAtLS0tLSAvL1xuXG51dGlscy5kb2NSZWFkeSA9IGZ1bmN0aW9uKCBjYWxsYmFjayApIHtcbiAgdmFyIHJlYWR5U3RhdGUgPSBkb2N1bWVudC5yZWFkeVN0YXRlO1xuICBpZiAoIHJlYWR5U3RhdGUgPT0gJ2NvbXBsZXRlJyB8fCByZWFkeVN0YXRlID09ICdpbnRlcmFjdGl2ZScgKSB7XG4gICAgLy8gZG8gYXN5bmMgdG8gYWxsb3cgZm9yIG90aGVyIHNjcmlwdHMgdG8gcnVuLiBtZXRhZml6enkvZmxpY2tpdHkjNDQxXG4gICAgc2V0VGltZW91dCggY2FsbGJhY2sgKTtcbiAgfSBlbHNlIHtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCAnRE9NQ29udGVudExvYWRlZCcsIGNhbGxiYWNrICk7XG4gIH1cbn07XG5cbi8vIC0tLS0tIGh0bWxJbml0IC0tLS0tIC8vXG5cbi8vIGh0dHA6Ly9qYW1lc3JvYmVydHMubmFtZS9ibG9nLzIwMTAvMDIvMjIvc3RyaW5nLWZ1bmN0aW9ucy1mb3ItamF2YXNjcmlwdC10cmltLXRvLWNhbWVsLWNhc2UtdG8tZGFzaGVkLWFuZC10by11bmRlcnNjb3JlL1xudXRpbHMudG9EYXNoZWQgPSBmdW5jdGlvbiggc3RyICkge1xuICByZXR1cm4gc3RyLnJlcGxhY2UoIC8oLikoW0EtWl0pL2csIGZ1bmN0aW9uKCBtYXRjaCwgJDEsICQyICkge1xuICAgIHJldHVybiAkMSArICctJyArICQyO1xuICB9KS50b0xvd2VyQ2FzZSgpO1xufTtcblxudmFyIGNvbnNvbGUgPSB3aW5kb3cuY29uc29sZTtcbi8qKlxuICogYWxsb3cgdXNlciB0byBpbml0aWFsaXplIGNsYXNzZXMgdmlhIFtkYXRhLW5hbWVzcGFjZV0gb3IgLmpzLW5hbWVzcGFjZSBjbGFzc1xuICogaHRtbEluaXQoIFdpZGdldCwgJ3dpZGdldE5hbWUnIClcbiAqIG9wdGlvbnMgYXJlIHBhcnNlZCBmcm9tIGRhdGEtbmFtZXNwYWNlLW9wdGlvbnNcbiAqL1xudXRpbHMuaHRtbEluaXQgPSBmdW5jdGlvbiggV2lkZ2V0Q2xhc3MsIG5hbWVzcGFjZSApIHtcbiAgdXRpbHMuZG9jUmVhZHkoIGZ1bmN0aW9uKCkge1xuICAgIHZhciBkYXNoZWROYW1lc3BhY2UgPSB1dGlscy50b0Rhc2hlZCggbmFtZXNwYWNlICk7XG4gICAgdmFyIGRhdGFBdHRyID0gJ2RhdGEtJyArIGRhc2hlZE5hbWVzcGFjZTtcbiAgICB2YXIgZGF0YUF0dHJFbGVtcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoICdbJyArIGRhdGFBdHRyICsgJ10nICk7XG4gICAgdmFyIGpzRGFzaEVsZW1zID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCggJy5qcy0nICsgZGFzaGVkTmFtZXNwYWNlICk7XG4gICAgdmFyIGVsZW1zID0gdXRpbHMubWFrZUFycmF5KCBkYXRhQXR0ckVsZW1zIClcbiAgICAgIC5jb25jYXQoIHV0aWxzLm1ha2VBcnJheSgganNEYXNoRWxlbXMgKSApO1xuICAgIHZhciBkYXRhT3B0aW9uc0F0dHIgPSBkYXRhQXR0ciArICctb3B0aW9ucyc7XG4gICAgdmFyIGpRdWVyeSA9IHdpbmRvdy5qUXVlcnk7XG5cbiAgICBlbGVtcy5mb3JFYWNoKCBmdW5jdGlvbiggZWxlbSApIHtcbiAgICAgIHZhciBhdHRyID0gZWxlbS5nZXRBdHRyaWJ1dGUoIGRhdGFBdHRyICkgfHxcbiAgICAgICAgZWxlbS5nZXRBdHRyaWJ1dGUoIGRhdGFPcHRpb25zQXR0ciApO1xuICAgICAgdmFyIG9wdGlvbnM7XG4gICAgICB0cnkge1xuICAgICAgICBvcHRpb25zID0gYXR0ciAmJiBKU09OLnBhcnNlKCBhdHRyICk7XG4gICAgICB9IGNhdGNoICggZXJyb3IgKSB7XG4gICAgICAgIC8vIGxvZyBlcnJvciwgZG8gbm90IGluaXRpYWxpemVcbiAgICAgICAgaWYgKCBjb25zb2xlICkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoICdFcnJvciBwYXJzaW5nICcgKyBkYXRhQXR0ciArICcgb24gJyArIGVsZW0uY2xhc3NOYW1lICtcbiAgICAgICAgICAnOiAnICsgZXJyb3IgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICAvLyBpbml0aWFsaXplXG4gICAgICB2YXIgaW5zdGFuY2UgPSBuZXcgV2lkZ2V0Q2xhc3MoIGVsZW0sIG9wdGlvbnMgKTtcbiAgICAgIC8vIG1ha2UgYXZhaWxhYmxlIHZpYSAkKCkuZGF0YSgnbmFtZXNwYWNlJylcbiAgICAgIGlmICggalF1ZXJ5ICkge1xuICAgICAgICBqUXVlcnkuZGF0YSggZWxlbSwgbmFtZXNwYWNlLCBpbnN0YW5jZSApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gIH0pO1xufTtcblxuLy8gLS0tLS0gIC0tLS0tIC8vXG5cbnJldHVybiB1dGlscztcblxufSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2Zpenp5LXVpLXV0aWxzL3V0aWxzLmpzXG4vLyBtb2R1bGUgaWQgPSAyNFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiFcbiAqIE1hc29ucnkgdjQuMi4yXG4gKiBDYXNjYWRpbmcgZ3JpZCBsYXlvdXQgbGlicmFyeVxuICogaHR0cHM6Ly9tYXNvbnJ5LmRlc2FuZHJvLmNvbVxuICogTUlUIExpY2Vuc2VcbiAqIGJ5IERhdmlkIERlU2FuZHJvXG4gKi9cblxuKCBmdW5jdGlvbiggd2luZG93LCBmYWN0b3J5ICkge1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgLyoganNoaW50IHN0cmljdDogZmFsc2UgKi8gLypnbG9iYWxzIGRlZmluZSwgbW9kdWxlLCByZXF1aXJlICovXG4gIGlmICggdHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgKSB7XG4gICAgLy8gQU1EXG4gICAgZGVmaW5lKCBbXG4gICAgICAgICdvdXRsYXllci9vdXRsYXllcicsXG4gICAgICAgICdnZXQtc2l6ZS9nZXQtc2l6ZSdcbiAgICAgIF0sXG4gICAgICBmYWN0b3J5ICk7XG4gIH0gZWxzZSBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlNcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoXG4gICAgICByZXF1aXJlKCdvdXRsYXllcicpLFxuICAgICAgcmVxdWlyZSgnZ2V0LXNpemUnKVxuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgLy8gYnJvd3NlciBnbG9iYWxcbiAgICB3aW5kb3cuTWFzb25yeSA9IGZhY3RvcnkoXG4gICAgICB3aW5kb3cuT3V0bGF5ZXIsXG4gICAgICB3aW5kb3cuZ2V0U2l6ZVxuICAgICk7XG4gIH1cblxufSggd2luZG93LCBmdW5jdGlvbiBmYWN0b3J5KCBPdXRsYXllciwgZ2V0U2l6ZSApIHtcblxuJ3VzZSBzdHJpY3QnO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBtYXNvbnJ5RGVmaW5pdGlvbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gIC8vIGNyZWF0ZSBhbiBPdXRsYXllciBsYXlvdXQgY2xhc3NcbiAgdmFyIE1hc29ucnkgPSBPdXRsYXllci5jcmVhdGUoJ21hc29ucnknKTtcbiAgLy8gaXNGaXRXaWR0aCAtPiBmaXRXaWR0aFxuICBNYXNvbnJ5LmNvbXBhdE9wdGlvbnMuZml0V2lkdGggPSAnaXNGaXRXaWR0aCc7XG5cbiAgdmFyIHByb3RvID0gTWFzb25yeS5wcm90b3R5cGU7XG5cbiAgcHJvdG8uX3Jlc2V0TGF5b3V0ID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5nZXRTaXplKCk7XG4gICAgdGhpcy5fZ2V0TWVhc3VyZW1lbnQoICdjb2x1bW5XaWR0aCcsICdvdXRlcldpZHRoJyApO1xuICAgIHRoaXMuX2dldE1lYXN1cmVtZW50KCAnZ3V0dGVyJywgJ291dGVyV2lkdGgnICk7XG4gICAgdGhpcy5tZWFzdXJlQ29sdW1ucygpO1xuXG4gICAgLy8gcmVzZXQgY29sdW1uIFlcbiAgICB0aGlzLmNvbFlzID0gW107XG4gICAgZm9yICggdmFyIGk9MDsgaSA8IHRoaXMuY29sczsgaSsrICkge1xuICAgICAgdGhpcy5jb2xZcy5wdXNoKCAwICk7XG4gICAgfVxuXG4gICAgdGhpcy5tYXhZID0gMDtcbiAgICB0aGlzLmhvcml6b250YWxDb2xJbmRleCA9IDA7XG4gIH07XG5cbiAgcHJvdG8ubWVhc3VyZUNvbHVtbnMgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLmdldENvbnRhaW5lcldpZHRoKCk7XG4gICAgLy8gaWYgY29sdW1uV2lkdGggaXMgMCwgZGVmYXVsdCB0byBvdXRlcldpZHRoIG9mIGZpcnN0IGl0ZW1cbiAgICBpZiAoICF0aGlzLmNvbHVtbldpZHRoICkge1xuICAgICAgdmFyIGZpcnN0SXRlbSA9IHRoaXMuaXRlbXNbMF07XG4gICAgICB2YXIgZmlyc3RJdGVtRWxlbSA9IGZpcnN0SXRlbSAmJiBmaXJzdEl0ZW0uZWxlbWVudDtcbiAgICAgIC8vIGNvbHVtbldpZHRoIGZhbGwgYmFjayB0byBpdGVtIG9mIGZpcnN0IGVsZW1lbnRcbiAgICAgIHRoaXMuY29sdW1uV2lkdGggPSBmaXJzdEl0ZW1FbGVtICYmIGdldFNpemUoIGZpcnN0SXRlbUVsZW0gKS5vdXRlcldpZHRoIHx8XG4gICAgICAgIC8vIGlmIGZpcnN0IGVsZW0gaGFzIG5vIHdpZHRoLCBkZWZhdWx0IHRvIHNpemUgb2YgY29udGFpbmVyXG4gICAgICAgIHRoaXMuY29udGFpbmVyV2lkdGg7XG4gICAgfVxuXG4gICAgdmFyIGNvbHVtbldpZHRoID0gdGhpcy5jb2x1bW5XaWR0aCArPSB0aGlzLmd1dHRlcjtcblxuICAgIC8vIGNhbGN1bGF0ZSBjb2x1bW5zXG4gICAgdmFyIGNvbnRhaW5lcldpZHRoID0gdGhpcy5jb250YWluZXJXaWR0aCArIHRoaXMuZ3V0dGVyO1xuICAgIHZhciBjb2xzID0gY29udGFpbmVyV2lkdGggLyBjb2x1bW5XaWR0aDtcbiAgICAvLyBmaXggcm91bmRpbmcgZXJyb3JzLCB0eXBpY2FsbHkgd2l0aCBndXR0ZXJzXG4gICAgdmFyIGV4Y2VzcyA9IGNvbHVtbldpZHRoIC0gY29udGFpbmVyV2lkdGggJSBjb2x1bW5XaWR0aDtcbiAgICAvLyBpZiBvdmVyc2hvb3QgaXMgbGVzcyB0aGFuIGEgcGl4ZWwsIHJvdW5kIHVwLCBvdGhlcndpc2UgZmxvb3IgaXRcbiAgICB2YXIgbWF0aE1ldGhvZCA9IGV4Y2VzcyAmJiBleGNlc3MgPCAxID8gJ3JvdW5kJyA6ICdmbG9vcic7XG4gICAgY29scyA9IE1hdGhbIG1hdGhNZXRob2QgXSggY29scyApO1xuICAgIHRoaXMuY29scyA9IE1hdGgubWF4KCBjb2xzLCAxICk7XG4gIH07XG5cbiAgcHJvdG8uZ2V0Q29udGFpbmVyV2lkdGggPSBmdW5jdGlvbigpIHtcbiAgICAvLyBjb250YWluZXIgaXMgcGFyZW50IGlmIGZpdCB3aWR0aFxuICAgIHZhciBpc0ZpdFdpZHRoID0gdGhpcy5fZ2V0T3B0aW9uKCdmaXRXaWR0aCcpO1xuICAgIHZhciBjb250YWluZXIgPSBpc0ZpdFdpZHRoID8gdGhpcy5lbGVtZW50LnBhcmVudE5vZGUgOiB0aGlzLmVsZW1lbnQ7XG4gICAgLy8gY2hlY2sgdGhhdCB0aGlzLnNpemUgYW5kIHNpemUgYXJlIHRoZXJlXG4gICAgLy8gSUU4IHRyaWdnZXJzIHJlc2l6ZSBvbiBib2R5IHNpemUgY2hhbmdlLCBzbyB0aGV5IG1pZ2h0IG5vdCBiZVxuICAgIHZhciBzaXplID0gZ2V0U2l6ZSggY29udGFpbmVyICk7XG4gICAgdGhpcy5jb250YWluZXJXaWR0aCA9IHNpemUgJiYgc2l6ZS5pbm5lcldpZHRoO1xuICB9O1xuXG4gIHByb3RvLl9nZXRJdGVtTGF5b3V0UG9zaXRpb24gPSBmdW5jdGlvbiggaXRlbSApIHtcbiAgICBpdGVtLmdldFNpemUoKTtcbiAgICAvLyBob3cgbWFueSBjb2x1bW5zIGRvZXMgdGhpcyBicmljayBzcGFuXG4gICAgdmFyIHJlbWFpbmRlciA9IGl0ZW0uc2l6ZS5vdXRlcldpZHRoICUgdGhpcy5jb2x1bW5XaWR0aDtcbiAgICB2YXIgbWF0aE1ldGhvZCA9IHJlbWFpbmRlciAmJiByZW1haW5kZXIgPCAxID8gJ3JvdW5kJyA6ICdjZWlsJztcbiAgICAvLyByb3VuZCBpZiBvZmYgYnkgMSBwaXhlbCwgb3RoZXJ3aXNlIHVzZSBjZWlsXG4gICAgdmFyIGNvbFNwYW4gPSBNYXRoWyBtYXRoTWV0aG9kIF0oIGl0ZW0uc2l6ZS5vdXRlcldpZHRoIC8gdGhpcy5jb2x1bW5XaWR0aCApO1xuICAgIGNvbFNwYW4gPSBNYXRoLm1pbiggY29sU3BhbiwgdGhpcy5jb2xzICk7XG4gICAgLy8gdXNlIGhvcml6b250YWwgb3IgdG9wIGNvbHVtbiBwb3NpdGlvblxuICAgIHZhciBjb2xQb3NNZXRob2QgPSB0aGlzLm9wdGlvbnMuaG9yaXpvbnRhbE9yZGVyID9cbiAgICAgICdfZ2V0SG9yaXpvbnRhbENvbFBvc2l0aW9uJyA6ICdfZ2V0VG9wQ29sUG9zaXRpb24nO1xuICAgIHZhciBjb2xQb3NpdGlvbiA9IHRoaXNbIGNvbFBvc01ldGhvZCBdKCBjb2xTcGFuLCBpdGVtICk7XG4gICAgLy8gcG9zaXRpb24gdGhlIGJyaWNrXG4gICAgdmFyIHBvc2l0aW9uID0ge1xuICAgICAgeDogdGhpcy5jb2x1bW5XaWR0aCAqIGNvbFBvc2l0aW9uLmNvbCxcbiAgICAgIHk6IGNvbFBvc2l0aW9uLnlcbiAgICB9O1xuICAgIC8vIGFwcGx5IHNldEhlaWdodCB0byBuZWNlc3NhcnkgY29sdW1uc1xuICAgIHZhciBzZXRIZWlnaHQgPSBjb2xQb3NpdGlvbi55ICsgaXRlbS5zaXplLm91dGVySGVpZ2h0O1xuICAgIHZhciBzZXRNYXggPSBjb2xTcGFuICsgY29sUG9zaXRpb24uY29sO1xuICAgIGZvciAoIHZhciBpID0gY29sUG9zaXRpb24uY29sOyBpIDwgc2V0TWF4OyBpKysgKSB7XG4gICAgICB0aGlzLmNvbFlzW2ldID0gc2V0SGVpZ2h0O1xuICAgIH1cblxuICAgIHJldHVybiBwb3NpdGlvbjtcbiAgfTtcblxuICBwcm90by5fZ2V0VG9wQ29sUG9zaXRpb24gPSBmdW5jdGlvbiggY29sU3BhbiApIHtcbiAgICB2YXIgY29sR3JvdXAgPSB0aGlzLl9nZXRUb3BDb2xHcm91cCggY29sU3BhbiApO1xuICAgIC8vIGdldCB0aGUgbWluaW11bSBZIHZhbHVlIGZyb20gdGhlIGNvbHVtbnNcbiAgICB2YXIgbWluaW11bVkgPSBNYXRoLm1pbi5hcHBseSggTWF0aCwgY29sR3JvdXAgKTtcblxuICAgIHJldHVybiB7XG4gICAgICBjb2w6IGNvbEdyb3VwLmluZGV4T2YoIG1pbmltdW1ZICksXG4gICAgICB5OiBtaW5pbXVtWSxcbiAgICB9O1xuICB9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gY29sU3BhbiAtIG51bWJlciBvZiBjb2x1bW5zIHRoZSBlbGVtZW50IHNwYW5zXG4gICAqIEByZXR1cm5zIHtBcnJheX0gY29sR3JvdXBcbiAgICovXG4gIHByb3RvLl9nZXRUb3BDb2xHcm91cCA9IGZ1bmN0aW9uKCBjb2xTcGFuICkge1xuICAgIGlmICggY29sU3BhbiA8IDIgKSB7XG4gICAgICAvLyBpZiBicmljayBzcGFucyBvbmx5IG9uZSBjb2x1bW4sIHVzZSBhbGwgdGhlIGNvbHVtbiBZc1xuICAgICAgcmV0dXJuIHRoaXMuY29sWXM7XG4gICAgfVxuXG4gICAgdmFyIGNvbEdyb3VwID0gW107XG4gICAgLy8gaG93IG1hbnkgZGlmZmVyZW50IHBsYWNlcyBjb3VsZCB0aGlzIGJyaWNrIGZpdCBob3Jpem9udGFsbHlcbiAgICB2YXIgZ3JvdXBDb3VudCA9IHRoaXMuY29scyArIDEgLSBjb2xTcGFuO1xuICAgIC8vIGZvciBlYWNoIGdyb3VwIHBvdGVudGlhbCBob3Jpem9udGFsIHBvc2l0aW9uXG4gICAgZm9yICggdmFyIGkgPSAwOyBpIDwgZ3JvdXBDb3VudDsgaSsrICkge1xuICAgICAgY29sR3JvdXBbaV0gPSB0aGlzLl9nZXRDb2xHcm91cFkoIGksIGNvbFNwYW4gKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbEdyb3VwO1xuICB9O1xuXG4gIHByb3RvLl9nZXRDb2xHcm91cFkgPSBmdW5jdGlvbiggY29sLCBjb2xTcGFuICkge1xuICAgIGlmICggY29sU3BhbiA8IDIgKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb2xZc1sgY29sIF07XG4gICAgfVxuICAgIC8vIG1ha2UgYW4gYXJyYXkgb2YgY29sWSB2YWx1ZXMgZm9yIHRoYXQgb25lIGdyb3VwXG4gICAgdmFyIGdyb3VwQ29sWXMgPSB0aGlzLmNvbFlzLnNsaWNlKCBjb2wsIGNvbCArIGNvbFNwYW4gKTtcbiAgICAvLyBhbmQgZ2V0IHRoZSBtYXggdmFsdWUgb2YgdGhlIGFycmF5XG4gICAgcmV0dXJuIE1hdGgubWF4LmFwcGx5KCBNYXRoLCBncm91cENvbFlzICk7XG4gIH07XG5cbiAgLy8gZ2V0IGNvbHVtbiBwb3NpdGlvbiBiYXNlZCBvbiBob3Jpem9udGFsIGluZGV4LiAjODczXG4gIHByb3RvLl9nZXRIb3Jpem9udGFsQ29sUG9zaXRpb24gPSBmdW5jdGlvbiggY29sU3BhbiwgaXRlbSApIHtcbiAgICB2YXIgY29sID0gdGhpcy5ob3Jpem9udGFsQ29sSW5kZXggJSB0aGlzLmNvbHM7XG4gICAgdmFyIGlzT3ZlciA9IGNvbFNwYW4gPiAxICYmIGNvbCArIGNvbFNwYW4gPiB0aGlzLmNvbHM7XG4gICAgLy8gc2hpZnQgdG8gbmV4dCByb3cgaWYgaXRlbSBjYW4ndCBmaXQgb24gY3VycmVudCByb3dcbiAgICBjb2wgPSBpc092ZXIgPyAwIDogY29sO1xuICAgIC8vIGRvbid0IGxldCB6ZXJvLXNpemUgaXRlbXMgdGFrZSB1cCBzcGFjZVxuICAgIHZhciBoYXNTaXplID0gaXRlbS5zaXplLm91dGVyV2lkdGggJiYgaXRlbS5zaXplLm91dGVySGVpZ2h0O1xuICAgIHRoaXMuaG9yaXpvbnRhbENvbEluZGV4ID0gaGFzU2l6ZSA/IGNvbCArIGNvbFNwYW4gOiB0aGlzLmhvcml6b250YWxDb2xJbmRleDtcblxuICAgIHJldHVybiB7XG4gICAgICBjb2w6IGNvbCxcbiAgICAgIHk6IHRoaXMuX2dldENvbEdyb3VwWSggY29sLCBjb2xTcGFuICksXG4gICAgfTtcbiAgfTtcblxuICBwcm90by5fbWFuYWdlU3RhbXAgPSBmdW5jdGlvbiggc3RhbXAgKSB7XG4gICAgdmFyIHN0YW1wU2l6ZSA9IGdldFNpemUoIHN0YW1wICk7XG4gICAgdmFyIG9mZnNldCA9IHRoaXMuX2dldEVsZW1lbnRPZmZzZXQoIHN0YW1wICk7XG4gICAgLy8gZ2V0IHRoZSBjb2x1bW5zIHRoYXQgdGhpcyBzdGFtcCBhZmZlY3RzXG4gICAgdmFyIGlzT3JpZ2luTGVmdCA9IHRoaXMuX2dldE9wdGlvbignb3JpZ2luTGVmdCcpO1xuICAgIHZhciBmaXJzdFggPSBpc09yaWdpbkxlZnQgPyBvZmZzZXQubGVmdCA6IG9mZnNldC5yaWdodDtcbiAgICB2YXIgbGFzdFggPSBmaXJzdFggKyBzdGFtcFNpemUub3V0ZXJXaWR0aDtcbiAgICB2YXIgZmlyc3RDb2wgPSBNYXRoLmZsb29yKCBmaXJzdFggLyB0aGlzLmNvbHVtbldpZHRoICk7XG4gICAgZmlyc3RDb2wgPSBNYXRoLm1heCggMCwgZmlyc3RDb2wgKTtcbiAgICB2YXIgbGFzdENvbCA9IE1hdGguZmxvb3IoIGxhc3RYIC8gdGhpcy5jb2x1bW5XaWR0aCApO1xuICAgIC8vIGxhc3RDb2wgc2hvdWxkIG5vdCBnbyBvdmVyIGlmIG11bHRpcGxlIG9mIGNvbHVtbldpZHRoICM0MjVcbiAgICBsYXN0Q29sIC09IGxhc3RYICUgdGhpcy5jb2x1bW5XaWR0aCA/IDAgOiAxO1xuICAgIGxhc3RDb2wgPSBNYXRoLm1pbiggdGhpcy5jb2xzIC0gMSwgbGFzdENvbCApO1xuICAgIC8vIHNldCBjb2xZcyB0byBib3R0b20gb2YgdGhlIHN0YW1wXG5cbiAgICB2YXIgaXNPcmlnaW5Ub3AgPSB0aGlzLl9nZXRPcHRpb24oJ29yaWdpblRvcCcpO1xuICAgIHZhciBzdGFtcE1heFkgPSAoIGlzT3JpZ2luVG9wID8gb2Zmc2V0LnRvcCA6IG9mZnNldC5ib3R0b20gKSArXG4gICAgICBzdGFtcFNpemUub3V0ZXJIZWlnaHQ7XG4gICAgZm9yICggdmFyIGkgPSBmaXJzdENvbDsgaSA8PSBsYXN0Q29sOyBpKysgKSB7XG4gICAgICB0aGlzLmNvbFlzW2ldID0gTWF0aC5tYXgoIHN0YW1wTWF4WSwgdGhpcy5jb2xZc1tpXSApO1xuICAgIH1cbiAgfTtcblxuICBwcm90by5fZ2V0Q29udGFpbmVyU2l6ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMubWF4WSA9IE1hdGgubWF4LmFwcGx5KCBNYXRoLCB0aGlzLmNvbFlzICk7XG4gICAgdmFyIHNpemUgPSB7XG4gICAgICBoZWlnaHQ6IHRoaXMubWF4WVxuICAgIH07XG5cbiAgICBpZiAoIHRoaXMuX2dldE9wdGlvbignZml0V2lkdGgnKSApIHtcbiAgICAgIHNpemUud2lkdGggPSB0aGlzLl9nZXRDb250YWluZXJGaXRXaWR0aCgpO1xuICAgIH1cblxuICAgIHJldHVybiBzaXplO1xuICB9O1xuXG4gIHByb3RvLl9nZXRDb250YWluZXJGaXRXaWR0aCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB1bnVzZWRDb2xzID0gMDtcbiAgICAvLyBjb3VudCB1bnVzZWQgY29sdW1uc1xuICAgIHZhciBpID0gdGhpcy5jb2xzO1xuICAgIHdoaWxlICggLS1pICkge1xuICAgICAgaWYgKCB0aGlzLmNvbFlzW2ldICE9PSAwICkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHVudXNlZENvbHMrKztcbiAgICB9XG4gICAgLy8gZml0IGNvbnRhaW5lciB0byBjb2x1bW5zIHRoYXQgaGF2ZSBiZWVuIHVzZWRcbiAgICByZXR1cm4gKCB0aGlzLmNvbHMgLSB1bnVzZWRDb2xzICkgKiB0aGlzLmNvbHVtbldpZHRoIC0gdGhpcy5ndXR0ZXI7XG4gIH07XG5cbiAgcHJvdG8ubmVlZHNSZXNpemVMYXlvdXQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcHJldmlvdXNXaWR0aCA9IHRoaXMuY29udGFpbmVyV2lkdGg7XG4gICAgdGhpcy5nZXRDb250YWluZXJXaWR0aCgpO1xuICAgIHJldHVybiBwcmV2aW91c1dpZHRoICE9IHRoaXMuY29udGFpbmVyV2lkdGg7XG4gIH07XG5cbiAgcmV0dXJuIE1hc29ucnk7XG5cbn0pKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9tYXNvbnJ5LWxheW91dC9tYXNvbnJ5LmpzXG4vLyBtb2R1bGUgaWQgPSAyNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKipcbiAqIE91dGxheWVyIEl0ZW1cbiAqL1xuXG4oIGZ1bmN0aW9uKCB3aW5kb3csIGZhY3RvcnkgKSB7XG4gIC8vIHVuaXZlcnNhbCBtb2R1bGUgZGVmaW5pdGlvblxuICAvKiBqc2hpbnQgc3RyaWN0OiBmYWxzZSAqLyAvKiBnbG9iYWxzIGRlZmluZSwgbW9kdWxlLCByZXF1aXJlICovXG4gIGlmICggdHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgKSB7XG4gICAgLy8gQU1EIC0gUmVxdWlyZUpTXG4gICAgZGVmaW5lKCBbXG4gICAgICAgICdldi1lbWl0dGVyL2V2LWVtaXR0ZXInLFxuICAgICAgICAnZ2V0LXNpemUvZ2V0LXNpemUnXG4gICAgICBdLFxuICAgICAgZmFjdG9yeVxuICAgICk7XG4gIH0gZWxzZSBpZiAoIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMgKSB7XG4gICAgLy8gQ29tbW9uSlMgLSBCcm93c2VyaWZ5LCBXZWJwYWNrXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KFxuICAgICAgcmVxdWlyZSgnZXYtZW1pdHRlcicpLFxuICAgICAgcmVxdWlyZSgnZ2V0LXNpemUnKVxuICAgICk7XG4gIH0gZWxzZSB7XG4gICAgLy8gYnJvd3NlciBnbG9iYWxcbiAgICB3aW5kb3cuT3V0bGF5ZXIgPSB7fTtcbiAgICB3aW5kb3cuT3V0bGF5ZXIuSXRlbSA9IGZhY3RvcnkoXG4gICAgICB3aW5kb3cuRXZFbWl0dGVyLFxuICAgICAgd2luZG93LmdldFNpemVcbiAgICApO1xuICB9XG5cbn0oIHdpbmRvdywgZnVuY3Rpb24gZmFjdG9yeSggRXZFbWl0dGVyLCBnZXRTaXplICkge1xuJ3VzZSBzdHJpY3QnO1xuXG4vLyAtLS0tLSBoZWxwZXJzIC0tLS0tIC8vXG5cbmZ1bmN0aW9uIGlzRW1wdHlPYmooIG9iaiApIHtcbiAgZm9yICggdmFyIHByb3AgaW4gb2JqICkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBwcm9wID0gbnVsbDtcbiAgcmV0dXJuIHRydWU7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIENTUzMgc3VwcG9ydCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG5cbnZhciBkb2NFbGVtU3R5bGUgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGU7XG5cbnZhciB0cmFuc2l0aW9uUHJvcGVydHkgPSB0eXBlb2YgZG9jRWxlbVN0eWxlLnRyYW5zaXRpb24gPT0gJ3N0cmluZycgP1xuICAndHJhbnNpdGlvbicgOiAnV2Via2l0VHJhbnNpdGlvbic7XG52YXIgdHJhbnNmb3JtUHJvcGVydHkgPSB0eXBlb2YgZG9jRWxlbVN0eWxlLnRyYW5zZm9ybSA9PSAnc3RyaW5nJyA/XG4gICd0cmFuc2Zvcm0nIDogJ1dlYmtpdFRyYW5zZm9ybSc7XG5cbnZhciB0cmFuc2l0aW9uRW5kRXZlbnQgPSB7XG4gIFdlYmtpdFRyYW5zaXRpb246ICd3ZWJraXRUcmFuc2l0aW9uRW5kJyxcbiAgdHJhbnNpdGlvbjogJ3RyYW5zaXRpb25lbmQnXG59WyB0cmFuc2l0aW9uUHJvcGVydHkgXTtcblxuLy8gY2FjaGUgYWxsIHZlbmRvciBwcm9wZXJ0aWVzIHRoYXQgY291bGQgaGF2ZSB2ZW5kb3IgcHJlZml4XG52YXIgdmVuZG9yUHJvcGVydGllcyA9IHtcbiAgdHJhbnNmb3JtOiB0cmFuc2Zvcm1Qcm9wZXJ0eSxcbiAgdHJhbnNpdGlvbjogdHJhbnNpdGlvblByb3BlcnR5LFxuICB0cmFuc2l0aW9uRHVyYXRpb246IHRyYW5zaXRpb25Qcm9wZXJ0eSArICdEdXJhdGlvbicsXG4gIHRyYW5zaXRpb25Qcm9wZXJ0eTogdHJhbnNpdGlvblByb3BlcnR5ICsgJ1Byb3BlcnR5JyxcbiAgdHJhbnNpdGlvbkRlbGF5OiB0cmFuc2l0aW9uUHJvcGVydHkgKyAnRGVsYXknXG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBJdGVtIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbmZ1bmN0aW9uIEl0ZW0oIGVsZW1lbnQsIGxheW91dCApIHtcbiAgaWYgKCAhZWxlbWVudCApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAvLyBwYXJlbnQgbGF5b3V0IGNsYXNzLCBpLmUuIE1hc29ucnksIElzb3RvcGUsIG9yIFBhY2tlcnlcbiAgdGhpcy5sYXlvdXQgPSBsYXlvdXQ7XG4gIHRoaXMucG9zaXRpb24gPSB7XG4gICAgeDogMCxcbiAgICB5OiAwXG4gIH07XG5cbiAgdGhpcy5fY3JlYXRlKCk7XG59XG5cbi8vIGluaGVyaXQgRXZFbWl0dGVyXG52YXIgcHJvdG8gPSBJdGVtLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoIEV2RW1pdHRlci5wcm90b3R5cGUgKTtcbnByb3RvLmNvbnN0cnVjdG9yID0gSXRlbTtcblxucHJvdG8uX2NyZWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAvLyB0cmFuc2l0aW9uIG9iamVjdHNcbiAgdGhpcy5fdHJhbnNuID0ge1xuICAgIGluZ1Byb3BlcnRpZXM6IHt9LFxuICAgIGNsZWFuOiB7fSxcbiAgICBvbkVuZDoge31cbiAgfTtcblxuICB0aGlzLmNzcyh7XG4gICAgcG9zaXRpb246ICdhYnNvbHV0ZSdcbiAgfSk7XG59O1xuXG4vLyB0cmlnZ2VyIHNwZWNpZmllZCBoYW5kbGVyIGZvciBldmVudCB0eXBlXG5wcm90by5oYW5kbGVFdmVudCA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgdmFyIG1ldGhvZCA9ICdvbicgKyBldmVudC50eXBlO1xuICBpZiAoIHRoaXNbIG1ldGhvZCBdICkge1xuICAgIHRoaXNbIG1ldGhvZCBdKCBldmVudCApO1xuICB9XG59O1xuXG5wcm90by5nZXRTaXplID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuc2l6ZSA9IGdldFNpemUoIHRoaXMuZWxlbWVudCApO1xufTtcblxuLyoqXG4gKiBhcHBseSBDU1Mgc3R5bGVzIHRvIGVsZW1lbnRcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdHlsZVxuICovXG5wcm90by5jc3MgPSBmdW5jdGlvbiggc3R5bGUgKSB7XG4gIHZhciBlbGVtU3R5bGUgPSB0aGlzLmVsZW1lbnQuc3R5bGU7XG5cbiAgZm9yICggdmFyIHByb3AgaW4gc3R5bGUgKSB7XG4gICAgLy8gdXNlIHZlbmRvciBwcm9wZXJ0eSBpZiBhdmFpbGFibGVcbiAgICB2YXIgc3VwcG9ydGVkUHJvcCA9IHZlbmRvclByb3BlcnRpZXNbIHByb3AgXSB8fCBwcm9wO1xuICAgIGVsZW1TdHlsZVsgc3VwcG9ydGVkUHJvcCBdID0gc3R5bGVbIHByb3AgXTtcbiAgfVxufTtcblxuIC8vIG1lYXN1cmUgcG9zaXRpb24sIGFuZCBzZXRzIGl0XG5wcm90by5nZXRQb3NpdGlvbiA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKCB0aGlzLmVsZW1lbnQgKTtcbiAgdmFyIGlzT3JpZ2luTGVmdCA9IHRoaXMubGF5b3V0Ll9nZXRPcHRpb24oJ29yaWdpbkxlZnQnKTtcbiAgdmFyIGlzT3JpZ2luVG9wID0gdGhpcy5sYXlvdXQuX2dldE9wdGlvbignb3JpZ2luVG9wJyk7XG4gIHZhciB4VmFsdWUgPSBzdHlsZVsgaXNPcmlnaW5MZWZ0ID8gJ2xlZnQnIDogJ3JpZ2h0JyBdO1xuICB2YXIgeVZhbHVlID0gc3R5bGVbIGlzT3JpZ2luVG9wID8gJ3RvcCcgOiAnYm90dG9tJyBdO1xuICB2YXIgeCA9IHBhcnNlRmxvYXQoIHhWYWx1ZSApO1xuICB2YXIgeSA9IHBhcnNlRmxvYXQoIHlWYWx1ZSApO1xuICAvLyBjb252ZXJ0IHBlcmNlbnQgdG8gcGl4ZWxzXG4gIHZhciBsYXlvdXRTaXplID0gdGhpcy5sYXlvdXQuc2l6ZTtcbiAgaWYgKCB4VmFsdWUuaW5kZXhPZignJScpICE9IC0xICkge1xuICAgIHggPSAoIHggLyAxMDAgKSAqIGxheW91dFNpemUud2lkdGg7XG4gIH1cbiAgaWYgKCB5VmFsdWUuaW5kZXhPZignJScpICE9IC0xICkge1xuICAgIHkgPSAoIHkgLyAxMDAgKSAqIGxheW91dFNpemUuaGVpZ2h0O1xuICB9XG4gIC8vIGNsZWFuIHVwICdhdXRvJyBvciBvdGhlciBub24taW50ZWdlciB2YWx1ZXNcbiAgeCA9IGlzTmFOKCB4ICkgPyAwIDogeDtcbiAgeSA9IGlzTmFOKCB5ICkgPyAwIDogeTtcbiAgLy8gcmVtb3ZlIHBhZGRpbmcgZnJvbSBtZWFzdXJlbWVudFxuICB4IC09IGlzT3JpZ2luTGVmdCA/IGxheW91dFNpemUucGFkZGluZ0xlZnQgOiBsYXlvdXRTaXplLnBhZGRpbmdSaWdodDtcbiAgeSAtPSBpc09yaWdpblRvcCA/IGxheW91dFNpemUucGFkZGluZ1RvcCA6IGxheW91dFNpemUucGFkZGluZ0JvdHRvbTtcblxuICB0aGlzLnBvc2l0aW9uLnggPSB4O1xuICB0aGlzLnBvc2l0aW9uLnkgPSB5O1xufTtcblxuLy8gc2V0IHNldHRsZWQgcG9zaXRpb24sIGFwcGx5IHBhZGRpbmdcbnByb3RvLmxheW91dFBvc2l0aW9uID0gZnVuY3Rpb24oKSB7XG4gIHZhciBsYXlvdXRTaXplID0gdGhpcy5sYXlvdXQuc2l6ZTtcbiAgdmFyIHN0eWxlID0ge307XG4gIHZhciBpc09yaWdpbkxlZnQgPSB0aGlzLmxheW91dC5fZ2V0T3B0aW9uKCdvcmlnaW5MZWZ0Jyk7XG4gIHZhciBpc09yaWdpblRvcCA9IHRoaXMubGF5b3V0Ll9nZXRPcHRpb24oJ29yaWdpblRvcCcpO1xuXG4gIC8vIHhcbiAgdmFyIHhQYWRkaW5nID0gaXNPcmlnaW5MZWZ0ID8gJ3BhZGRpbmdMZWZ0JyA6ICdwYWRkaW5nUmlnaHQnO1xuICB2YXIgeFByb3BlcnR5ID0gaXNPcmlnaW5MZWZ0ID8gJ2xlZnQnIDogJ3JpZ2h0JztcbiAgdmFyIHhSZXNldFByb3BlcnR5ID0gaXNPcmlnaW5MZWZ0ID8gJ3JpZ2h0JyA6ICdsZWZ0JztcblxuICB2YXIgeCA9IHRoaXMucG9zaXRpb24ueCArIGxheW91dFNpemVbIHhQYWRkaW5nIF07XG4gIC8vIHNldCBpbiBwZXJjZW50YWdlIG9yIHBpeGVsc1xuICBzdHlsZVsgeFByb3BlcnR5IF0gPSB0aGlzLmdldFhWYWx1ZSggeCApO1xuICAvLyByZXNldCBvdGhlciBwcm9wZXJ0eVxuICBzdHlsZVsgeFJlc2V0UHJvcGVydHkgXSA9ICcnO1xuXG4gIC8vIHlcbiAgdmFyIHlQYWRkaW5nID0gaXNPcmlnaW5Ub3AgPyAncGFkZGluZ1RvcCcgOiAncGFkZGluZ0JvdHRvbSc7XG4gIHZhciB5UHJvcGVydHkgPSBpc09yaWdpblRvcCA/ICd0b3AnIDogJ2JvdHRvbSc7XG4gIHZhciB5UmVzZXRQcm9wZXJ0eSA9IGlzT3JpZ2luVG9wID8gJ2JvdHRvbScgOiAndG9wJztcblxuICB2YXIgeSA9IHRoaXMucG9zaXRpb24ueSArIGxheW91dFNpemVbIHlQYWRkaW5nIF07XG4gIC8vIHNldCBpbiBwZXJjZW50YWdlIG9yIHBpeGVsc1xuICBzdHlsZVsgeVByb3BlcnR5IF0gPSB0aGlzLmdldFlWYWx1ZSggeSApO1xuICAvLyByZXNldCBvdGhlciBwcm9wZXJ0eVxuICBzdHlsZVsgeVJlc2V0UHJvcGVydHkgXSA9ICcnO1xuXG4gIHRoaXMuY3NzKCBzdHlsZSApO1xuICB0aGlzLmVtaXRFdmVudCggJ2xheW91dCcsIFsgdGhpcyBdICk7XG59O1xuXG5wcm90by5nZXRYVmFsdWUgPSBmdW5jdGlvbiggeCApIHtcbiAgdmFyIGlzSG9yaXpvbnRhbCA9IHRoaXMubGF5b3V0Ll9nZXRPcHRpb24oJ2hvcml6b250YWwnKTtcbiAgcmV0dXJuIHRoaXMubGF5b3V0Lm9wdGlvbnMucGVyY2VudFBvc2l0aW9uICYmICFpc0hvcml6b250YWwgP1xuICAgICggKCB4IC8gdGhpcy5sYXlvdXQuc2l6ZS53aWR0aCApICogMTAwICkgKyAnJScgOiB4ICsgJ3B4Jztcbn07XG5cbnByb3RvLmdldFlWYWx1ZSA9IGZ1bmN0aW9uKCB5ICkge1xuICB2YXIgaXNIb3Jpem9udGFsID0gdGhpcy5sYXlvdXQuX2dldE9wdGlvbignaG9yaXpvbnRhbCcpO1xuICByZXR1cm4gdGhpcy5sYXlvdXQub3B0aW9ucy5wZXJjZW50UG9zaXRpb24gJiYgaXNIb3Jpem9udGFsID9cbiAgICAoICggeSAvIHRoaXMubGF5b3V0LnNpemUuaGVpZ2h0ICkgKiAxMDAgKSArICclJyA6IHkgKyAncHgnO1xufTtcblxucHJvdG8uX3RyYW5zaXRpb25UbyA9IGZ1bmN0aW9uKCB4LCB5ICkge1xuICB0aGlzLmdldFBvc2l0aW9uKCk7XG4gIC8vIGdldCBjdXJyZW50IHggJiB5IGZyb20gdG9wL2xlZnRcbiAgdmFyIGN1clggPSB0aGlzLnBvc2l0aW9uLng7XG4gIHZhciBjdXJZID0gdGhpcy5wb3NpdGlvbi55O1xuXG4gIHZhciBkaWROb3RNb3ZlID0geCA9PSB0aGlzLnBvc2l0aW9uLnggJiYgeSA9PSB0aGlzLnBvc2l0aW9uLnk7XG5cbiAgLy8gc2F2ZSBlbmQgcG9zaXRpb25cbiAgdGhpcy5zZXRQb3NpdGlvbiggeCwgeSApO1xuXG4gIC8vIGlmIGRpZCBub3QgbW92ZSBhbmQgbm90IHRyYW5zaXRpb25pbmcsIGp1c3QgZ28gdG8gbGF5b3V0XG4gIGlmICggZGlkTm90TW92ZSAmJiAhdGhpcy5pc1RyYW5zaXRpb25pbmcgKSB7XG4gICAgdGhpcy5sYXlvdXRQb3NpdGlvbigpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciB0cmFuc1ggPSB4IC0gY3VyWDtcbiAgdmFyIHRyYW5zWSA9IHkgLSBjdXJZO1xuICB2YXIgdHJhbnNpdGlvblN0eWxlID0ge307XG4gIHRyYW5zaXRpb25TdHlsZS50cmFuc2Zvcm0gPSB0aGlzLmdldFRyYW5zbGF0ZSggdHJhbnNYLCB0cmFuc1kgKTtcblxuICB0aGlzLnRyYW5zaXRpb24oe1xuICAgIHRvOiB0cmFuc2l0aW9uU3R5bGUsXG4gICAgb25UcmFuc2l0aW9uRW5kOiB7XG4gICAgICB0cmFuc2Zvcm06IHRoaXMubGF5b3V0UG9zaXRpb25cbiAgICB9LFxuICAgIGlzQ2xlYW5pbmc6IHRydWVcbiAgfSk7XG59O1xuXG5wcm90by5nZXRUcmFuc2xhdGUgPSBmdW5jdGlvbiggeCwgeSApIHtcbiAgLy8gZmxpcCBjb29yaWRpbmF0ZXMgaWYgb3JpZ2luIG9uIHJpZ2h0IG9yIGJvdHRvbVxuICB2YXIgaXNPcmlnaW5MZWZ0ID0gdGhpcy5sYXlvdXQuX2dldE9wdGlvbignb3JpZ2luTGVmdCcpO1xuICB2YXIgaXNPcmlnaW5Ub3AgPSB0aGlzLmxheW91dC5fZ2V0T3B0aW9uKCdvcmlnaW5Ub3AnKTtcbiAgeCA9IGlzT3JpZ2luTGVmdCA/IHggOiAteDtcbiAgeSA9IGlzT3JpZ2luVG9wID8geSA6IC15O1xuICByZXR1cm4gJ3RyYW5zbGF0ZTNkKCcgKyB4ICsgJ3B4LCAnICsgeSArICdweCwgMCknO1xufTtcblxuLy8gbm9uIHRyYW5zaXRpb24gKyB0cmFuc2Zvcm0gc3VwcG9ydFxucHJvdG8uZ29UbyA9IGZ1bmN0aW9uKCB4LCB5ICkge1xuICB0aGlzLnNldFBvc2l0aW9uKCB4LCB5ICk7XG4gIHRoaXMubGF5b3V0UG9zaXRpb24oKTtcbn07XG5cbnByb3RvLm1vdmVUbyA9IHByb3RvLl90cmFuc2l0aW9uVG87XG5cbnByb3RvLnNldFBvc2l0aW9uID0gZnVuY3Rpb24oIHgsIHkgKSB7XG4gIHRoaXMucG9zaXRpb24ueCA9IHBhcnNlRmxvYXQoIHggKTtcbiAgdGhpcy5wb3NpdGlvbi55ID0gcGFyc2VGbG9hdCggeSApO1xufTtcblxuLy8gLS0tLS0gdHJhbnNpdGlvbiAtLS0tLSAvL1xuXG4vKipcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdHlsZSAtIENTU1xuICogQHBhcmFtIHtGdW5jdGlvbn0gb25UcmFuc2l0aW9uRW5kXG4gKi9cblxuLy8gbm9uIHRyYW5zaXRpb24sIGp1c3QgdHJpZ2dlciBjYWxsYmFja1xucHJvdG8uX25vblRyYW5zaXRpb24gPSBmdW5jdGlvbiggYXJncyApIHtcbiAgdGhpcy5jc3MoIGFyZ3MudG8gKTtcbiAgaWYgKCBhcmdzLmlzQ2xlYW5pbmcgKSB7XG4gICAgdGhpcy5fcmVtb3ZlU3R5bGVzKCBhcmdzLnRvICk7XG4gIH1cbiAgZm9yICggdmFyIHByb3AgaW4gYXJncy5vblRyYW5zaXRpb25FbmQgKSB7XG4gICAgYXJncy5vblRyYW5zaXRpb25FbmRbIHByb3AgXS5jYWxsKCB0aGlzICk7XG4gIH1cbn07XG5cbi8qKlxuICogcHJvcGVyIHRyYW5zaXRpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBhcmdzIC0gYXJndW1lbnRzXG4gKiAgIEBwYXJhbSB7T2JqZWN0fSB0byAtIHN0eWxlIHRvIHRyYW5zaXRpb24gdG9cbiAqICAgQHBhcmFtIHtPYmplY3R9IGZyb20gLSBzdHlsZSB0byBzdGFydCB0cmFuc2l0aW9uIGZyb21cbiAqICAgQHBhcmFtIHtCb29sZWFufSBpc0NsZWFuaW5nIC0gcmVtb3ZlcyB0cmFuc2l0aW9uIHN0eWxlcyBhZnRlciB0cmFuc2l0aW9uXG4gKiAgIEBwYXJhbSB7RnVuY3Rpb259IG9uVHJhbnNpdGlvbkVuZCAtIGNhbGxiYWNrXG4gKi9cbnByb3RvLnRyYW5zaXRpb24gPSBmdW5jdGlvbiggYXJncyApIHtcbiAgLy8gcmVkaXJlY3QgdG8gbm9uVHJhbnNpdGlvbiBpZiBubyB0cmFuc2l0aW9uIGR1cmF0aW9uXG4gIGlmICggIXBhcnNlRmxvYXQoIHRoaXMubGF5b3V0Lm9wdGlvbnMudHJhbnNpdGlvbkR1cmF0aW9uICkgKSB7XG4gICAgdGhpcy5fbm9uVHJhbnNpdGlvbiggYXJncyApO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBfdHJhbnNpdGlvbiA9IHRoaXMuX3RyYW5zbjtcbiAgLy8ga2VlcCB0cmFjayBvZiBvblRyYW5zaXRpb25FbmQgY2FsbGJhY2sgYnkgY3NzIHByb3BlcnR5XG4gIGZvciAoIHZhciBwcm9wIGluIGFyZ3Mub25UcmFuc2l0aW9uRW5kICkge1xuICAgIF90cmFuc2l0aW9uLm9uRW5kWyBwcm9wIF0gPSBhcmdzLm9uVHJhbnNpdGlvbkVuZFsgcHJvcCBdO1xuICB9XG4gIC8vIGtlZXAgdHJhY2sgb2YgcHJvcGVydGllcyB0aGF0IGFyZSB0cmFuc2l0aW9uaW5nXG4gIGZvciAoIHByb3AgaW4gYXJncy50byApIHtcbiAgICBfdHJhbnNpdGlvbi5pbmdQcm9wZXJ0aWVzWyBwcm9wIF0gPSB0cnVlO1xuICAgIC8vIGtlZXAgdHJhY2sgb2YgcHJvcGVydGllcyB0byBjbGVhbiB1cCB3aGVuIHRyYW5zaXRpb24gaXMgZG9uZVxuICAgIGlmICggYXJncy5pc0NsZWFuaW5nICkge1xuICAgICAgX3RyYW5zaXRpb24uY2xlYW5bIHByb3AgXSA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgLy8gc2V0IGZyb20gc3R5bGVzXG4gIGlmICggYXJncy5mcm9tICkge1xuICAgIHRoaXMuY3NzKCBhcmdzLmZyb20gKTtcbiAgICAvLyBmb3JjZSByZWRyYXcuIGh0dHA6Ly9ibG9nLmFsZXhtYWNjYXcuY29tL2Nzcy10cmFuc2l0aW9uc1xuICAgIHZhciBoID0gdGhpcy5lbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgICAvLyBoYWNrIGZvciBKU0hpbnQgdG8gaHVzaCBhYm91dCB1bnVzZWQgdmFyXG4gICAgaCA9IG51bGw7XG4gIH1cbiAgLy8gZW5hYmxlIHRyYW5zaXRpb25cbiAgdGhpcy5lbmFibGVUcmFuc2l0aW9uKCBhcmdzLnRvICk7XG4gIC8vIHNldCBzdHlsZXMgdGhhdCBhcmUgdHJhbnNpdGlvbmluZ1xuICB0aGlzLmNzcyggYXJncy50byApO1xuXG4gIHRoaXMuaXNUcmFuc2l0aW9uaW5nID0gdHJ1ZTtcblxufTtcblxuLy8gZGFzaCBiZWZvcmUgYWxsIGNhcCBsZXR0ZXJzLCBpbmNsdWRpbmcgZmlyc3QgZm9yXG4vLyBXZWJraXRUcmFuc2Zvcm0gPT4gLXdlYmtpdC10cmFuc2Zvcm1cbmZ1bmN0aW9uIHRvRGFzaGVkQWxsKCBzdHIgKSB7XG4gIHJldHVybiBzdHIucmVwbGFjZSggLyhbQS1aXSkvZywgZnVuY3Rpb24oICQxICkge1xuICAgIHJldHVybiAnLScgKyAkMS50b0xvd2VyQ2FzZSgpO1xuICB9KTtcbn1cblxudmFyIHRyYW5zaXRpb25Qcm9wcyA9ICdvcGFjaXR5LCcgKyB0b0Rhc2hlZEFsbCggdHJhbnNmb3JtUHJvcGVydHkgKTtcblxucHJvdG8uZW5hYmxlVHJhbnNpdGlvbiA9IGZ1bmN0aW9uKC8qIHN0eWxlICovKSB7XG4gIC8vIEhBQ0sgY2hhbmdpbmcgdHJhbnNpdGlvblByb3BlcnR5IGR1cmluZyBhIHRyYW5zaXRpb25cbiAgLy8gd2lsbCBjYXVzZSB0cmFuc2l0aW9uIHRvIGp1bXBcbiAgaWYgKCB0aGlzLmlzVHJhbnNpdGlvbmluZyApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBtYWtlIGB0cmFuc2l0aW9uOiBmb28sIGJhciwgYmF6YCBmcm9tIHN0eWxlIG9iamVjdFxuICAvLyBIQUNLIHVuLWNvbW1lbnQgdGhpcyB3aGVuIGVuYWJsZVRyYW5zaXRpb24gY2FuIHdvcmtcbiAgLy8gd2hpbGUgYSB0cmFuc2l0aW9uIGlzIGhhcHBlbmluZ1xuICAvLyB2YXIgdHJhbnNpdGlvblZhbHVlcyA9IFtdO1xuICAvLyBmb3IgKCB2YXIgcHJvcCBpbiBzdHlsZSApIHtcbiAgLy8gICAvLyBkYXNoLWlmeSBjYW1lbENhc2VkIHByb3BlcnRpZXMgbGlrZSBXZWJraXRUcmFuc2l0aW9uXG4gIC8vICAgcHJvcCA9IHZlbmRvclByb3BlcnRpZXNbIHByb3AgXSB8fCBwcm9wO1xuICAvLyAgIHRyYW5zaXRpb25WYWx1ZXMucHVzaCggdG9EYXNoZWRBbGwoIHByb3AgKSApO1xuICAvLyB9XG4gIC8vIG11bmdlIG51bWJlciB0byBtaWxsaXNlY29uZCwgdG8gbWF0Y2ggc3RhZ2dlclxuICB2YXIgZHVyYXRpb24gPSB0aGlzLmxheW91dC5vcHRpb25zLnRyYW5zaXRpb25EdXJhdGlvbjtcbiAgZHVyYXRpb24gPSB0eXBlb2YgZHVyYXRpb24gPT0gJ251bWJlcicgPyBkdXJhdGlvbiArICdtcycgOiBkdXJhdGlvbjtcbiAgLy8gZW5hYmxlIHRyYW5zaXRpb24gc3R5bGVzXG4gIHRoaXMuY3NzKHtcbiAgICB0cmFuc2l0aW9uUHJvcGVydHk6IHRyYW5zaXRpb25Qcm9wcyxcbiAgICB0cmFuc2l0aW9uRHVyYXRpb246IGR1cmF0aW9uLFxuICAgIHRyYW5zaXRpb25EZWxheTogdGhpcy5zdGFnZ2VyRGVsYXkgfHwgMFxuICB9KTtcbiAgLy8gbGlzdGVuIGZvciB0cmFuc2l0aW9uIGVuZCBldmVudFxuICB0aGlzLmVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggdHJhbnNpdGlvbkVuZEV2ZW50LCB0aGlzLCBmYWxzZSApO1xufTtcblxuLy8gLS0tLS0gZXZlbnRzIC0tLS0tIC8vXG5cbnByb3RvLm9ud2Via2l0VHJhbnNpdGlvbkVuZCA9IGZ1bmN0aW9uKCBldmVudCApIHtcbiAgdGhpcy5vbnRyYW5zaXRpb25lbmQoIGV2ZW50ICk7XG59O1xuXG5wcm90by5vbm90cmFuc2l0aW9uZW5kID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICB0aGlzLm9udHJhbnNpdGlvbmVuZCggZXZlbnQgKTtcbn07XG5cbi8vIHByb3BlcnRpZXMgdGhhdCBJIG11bmdlIHRvIG1ha2UgbXkgbGlmZSBlYXNpZXJcbnZhciBkYXNoZWRWZW5kb3JQcm9wZXJ0aWVzID0ge1xuICAnLXdlYmtpdC10cmFuc2Zvcm0nOiAndHJhbnNmb3JtJ1xufTtcblxucHJvdG8ub250cmFuc2l0aW9uZW5kID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuICAvLyBkaXNyZWdhcmQgYnViYmxlZCBldmVudHMgZnJvbSBjaGlsZHJlblxuICBpZiAoIGV2ZW50LnRhcmdldCAhPT0gdGhpcy5lbGVtZW50ICkge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgX3RyYW5zaXRpb24gPSB0aGlzLl90cmFuc247XG4gIC8vIGdldCBwcm9wZXJ0eSBuYW1lIG9mIHRyYW5zaXRpb25lZCBwcm9wZXJ0eSwgY29udmVydCB0byBwcmVmaXgtZnJlZVxuICB2YXIgcHJvcGVydHlOYW1lID0gZGFzaGVkVmVuZG9yUHJvcGVydGllc1sgZXZlbnQucHJvcGVydHlOYW1lIF0gfHwgZXZlbnQucHJvcGVydHlOYW1lO1xuXG4gIC8vIHJlbW92ZSBwcm9wZXJ0eSB0aGF0IGhhcyBjb21wbGV0ZWQgdHJhbnNpdGlvbmluZ1xuICBkZWxldGUgX3RyYW5zaXRpb24uaW5nUHJvcGVydGllc1sgcHJvcGVydHlOYW1lIF07XG4gIC8vIGNoZWNrIGlmIGFueSBwcm9wZXJ0aWVzIGFyZSBzdGlsbCB0cmFuc2l0aW9uaW5nXG4gIGlmICggaXNFbXB0eU9iaiggX3RyYW5zaXRpb24uaW5nUHJvcGVydGllcyApICkge1xuICAgIC8vIGFsbCBwcm9wZXJ0aWVzIGhhdmUgY29tcGxldGVkIHRyYW5zaXRpb25pbmdcbiAgICB0aGlzLmRpc2FibGVUcmFuc2l0aW9uKCk7XG4gIH1cbiAgLy8gY2xlYW4gc3R5bGVcbiAgaWYgKCBwcm9wZXJ0eU5hbWUgaW4gX3RyYW5zaXRpb24uY2xlYW4gKSB7XG4gICAgLy8gY2xlYW4gdXAgc3R5bGVcbiAgICB0aGlzLmVsZW1lbnQuc3R5bGVbIGV2ZW50LnByb3BlcnR5TmFtZSBdID0gJyc7XG4gICAgZGVsZXRlIF90cmFuc2l0aW9uLmNsZWFuWyBwcm9wZXJ0eU5hbWUgXTtcbiAgfVxuICAvLyB0cmlnZ2VyIG9uVHJhbnNpdGlvbkVuZCBjYWxsYmFja1xuICBpZiAoIHByb3BlcnR5TmFtZSBpbiBfdHJhbnNpdGlvbi5vbkVuZCApIHtcbiAgICB2YXIgb25UcmFuc2l0aW9uRW5kID0gX3RyYW5zaXRpb24ub25FbmRbIHByb3BlcnR5TmFtZSBdO1xuICAgIG9uVHJhbnNpdGlvbkVuZC5jYWxsKCB0aGlzICk7XG4gICAgZGVsZXRlIF90cmFuc2l0aW9uLm9uRW5kWyBwcm9wZXJ0eU5hbWUgXTtcbiAgfVxuXG4gIHRoaXMuZW1pdEV2ZW50KCAndHJhbnNpdGlvbkVuZCcsIFsgdGhpcyBdICk7XG59O1xuXG5wcm90by5kaXNhYmxlVHJhbnNpdGlvbiA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnJlbW92ZVRyYW5zaXRpb25TdHlsZXMoKTtcbiAgdGhpcy5lbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoIHRyYW5zaXRpb25FbmRFdmVudCwgdGhpcywgZmFsc2UgKTtcbiAgdGhpcy5pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcbn07XG5cbi8qKlxuICogcmVtb3ZlcyBzdHlsZSBwcm9wZXJ0eSBmcm9tIGVsZW1lbnRcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdHlsZVxuKiovXG5wcm90by5fcmVtb3ZlU3R5bGVzID0gZnVuY3Rpb24oIHN0eWxlICkge1xuICAvLyBjbGVhbiB1cCB0cmFuc2l0aW9uIHN0eWxlc1xuICB2YXIgY2xlYW5TdHlsZSA9IHt9O1xuICBmb3IgKCB2YXIgcHJvcCBpbiBzdHlsZSApIHtcbiAgICBjbGVhblN0eWxlWyBwcm9wIF0gPSAnJztcbiAgfVxuICB0aGlzLmNzcyggY2xlYW5TdHlsZSApO1xufTtcblxudmFyIGNsZWFuVHJhbnNpdGlvblN0eWxlID0ge1xuICB0cmFuc2l0aW9uUHJvcGVydHk6ICcnLFxuICB0cmFuc2l0aW9uRHVyYXRpb246ICcnLFxuICB0cmFuc2l0aW9uRGVsYXk6ICcnXG59O1xuXG5wcm90by5yZW1vdmVUcmFuc2l0aW9uU3R5bGVzID0gZnVuY3Rpb24oKSB7XG4gIC8vIHJlbW92ZSB0cmFuc2l0aW9uXG4gIHRoaXMuY3NzKCBjbGVhblRyYW5zaXRpb25TdHlsZSApO1xufTtcblxuLy8gLS0tLS0gc3RhZ2dlciAtLS0tLSAvL1xuXG5wcm90by5zdGFnZ2VyID0gZnVuY3Rpb24oIGRlbGF5ICkge1xuICBkZWxheSA9IGlzTmFOKCBkZWxheSApID8gMCA6IGRlbGF5O1xuICB0aGlzLnN0YWdnZXJEZWxheSA9IGRlbGF5ICsgJ21zJztcbn07XG5cbi8vIC0tLS0tIHNob3cvaGlkZS9yZW1vdmUgLS0tLS0gLy9cblxuLy8gcmVtb3ZlIGVsZW1lbnQgZnJvbSBET01cbnByb3RvLnJlbW92ZUVsZW0gPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5lbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIHRoaXMuZWxlbWVudCApO1xuICAvLyByZW1vdmUgZGlzcGxheTogbm9uZVxuICB0aGlzLmNzcyh7IGRpc3BsYXk6ICcnIH0pO1xuICB0aGlzLmVtaXRFdmVudCggJ3JlbW92ZScsIFsgdGhpcyBdICk7XG59O1xuXG5wcm90by5yZW1vdmUgPSBmdW5jdGlvbigpIHtcbiAgLy8ganVzdCByZW1vdmUgZWxlbWVudCBpZiBubyB0cmFuc2l0aW9uIHN1cHBvcnQgb3Igbm8gdHJhbnNpdGlvblxuICBpZiAoICF0cmFuc2l0aW9uUHJvcGVydHkgfHwgIXBhcnNlRmxvYXQoIHRoaXMubGF5b3V0Lm9wdGlvbnMudHJhbnNpdGlvbkR1cmF0aW9uICkgKSB7XG4gICAgdGhpcy5yZW1vdmVFbGVtKCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gc3RhcnQgdHJhbnNpdGlvblxuICB0aGlzLm9uY2UoICd0cmFuc2l0aW9uRW5kJywgZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5yZW1vdmVFbGVtKCk7XG4gIH0pO1xuICB0aGlzLmhpZGUoKTtcbn07XG5cbnByb3RvLnJldmVhbCA9IGZ1bmN0aW9uKCkge1xuICBkZWxldGUgdGhpcy5pc0hpZGRlbjtcbiAgLy8gcmVtb3ZlIGRpc3BsYXk6IG5vbmVcbiAgdGhpcy5jc3MoeyBkaXNwbGF5OiAnJyB9KTtcblxuICB2YXIgb3B0aW9ucyA9IHRoaXMubGF5b3V0Lm9wdGlvbnM7XG5cbiAgdmFyIG9uVHJhbnNpdGlvbkVuZCA9IHt9O1xuICB2YXIgdHJhbnNpdGlvbkVuZFByb3BlcnR5ID0gdGhpcy5nZXRIaWRlUmV2ZWFsVHJhbnNpdGlvbkVuZFByb3BlcnR5KCd2aXNpYmxlU3R5bGUnKTtcbiAgb25UcmFuc2l0aW9uRW5kWyB0cmFuc2l0aW9uRW5kUHJvcGVydHkgXSA9IHRoaXMub25SZXZlYWxUcmFuc2l0aW9uRW5kO1xuXG4gIHRoaXMudHJhbnNpdGlvbih7XG4gICAgZnJvbTogb3B0aW9ucy5oaWRkZW5TdHlsZSxcbiAgICB0bzogb3B0aW9ucy52aXNpYmxlU3R5bGUsXG4gICAgaXNDbGVhbmluZzogdHJ1ZSxcbiAgICBvblRyYW5zaXRpb25FbmQ6IG9uVHJhbnNpdGlvbkVuZFxuICB9KTtcbn07XG5cbnByb3RvLm9uUmV2ZWFsVHJhbnNpdGlvbkVuZCA9IGZ1bmN0aW9uKCkge1xuICAvLyBjaGVjayBpZiBzdGlsbCB2aXNpYmxlXG4gIC8vIGR1cmluZyB0cmFuc2l0aW9uLCBpdGVtIG1heSBoYXZlIGJlZW4gaGlkZGVuXG4gIGlmICggIXRoaXMuaXNIaWRkZW4gKSB7XG4gICAgdGhpcy5lbWl0RXZlbnQoJ3JldmVhbCcpO1xuICB9XG59O1xuXG4vKipcbiAqIGdldCBzdHlsZSBwcm9wZXJ0eSB1c2UgZm9yIGhpZGUvcmV2ZWFsIHRyYW5zaXRpb24gZW5kXG4gKiBAcGFyYW0ge1N0cmluZ30gc3R5bGVQcm9wZXJ0eSAtIGhpZGRlblN0eWxlL3Zpc2libGVTdHlsZVxuICogQHJldHVybnMge1N0cmluZ31cbiAqL1xucHJvdG8uZ2V0SGlkZVJldmVhbFRyYW5zaXRpb25FbmRQcm9wZXJ0eSA9IGZ1bmN0aW9uKCBzdHlsZVByb3BlcnR5ICkge1xuICB2YXIgb3B0aW9uU3R5bGUgPSB0aGlzLmxheW91dC5vcHRpb25zWyBzdHlsZVByb3BlcnR5IF07XG4gIC8vIHVzZSBvcGFjaXR5XG4gIGlmICggb3B0aW9uU3R5bGUub3BhY2l0eSApIHtcbiAgICByZXR1cm4gJ29wYWNpdHknO1xuICB9XG4gIC8vIGdldCBmaXJzdCBwcm9wZXJ0eVxuICBmb3IgKCB2YXIgcHJvcCBpbiBvcHRpb25TdHlsZSApIHtcbiAgICByZXR1cm4gcHJvcDtcbiAgfVxufTtcblxucHJvdG8uaGlkZSA9IGZ1bmN0aW9uKCkge1xuICAvLyBzZXQgZmxhZ1xuICB0aGlzLmlzSGlkZGVuID0gdHJ1ZTtcbiAgLy8gcmVtb3ZlIGRpc3BsYXk6IG5vbmVcbiAgdGhpcy5jc3MoeyBkaXNwbGF5OiAnJyB9KTtcblxuICB2YXIgb3B0aW9ucyA9IHRoaXMubGF5b3V0Lm9wdGlvbnM7XG5cbiAgdmFyIG9uVHJhbnNpdGlvbkVuZCA9IHt9O1xuICB2YXIgdHJhbnNpdGlvbkVuZFByb3BlcnR5ID0gdGhpcy5nZXRIaWRlUmV2ZWFsVHJhbnNpdGlvbkVuZFByb3BlcnR5KCdoaWRkZW5TdHlsZScpO1xuICBvblRyYW5zaXRpb25FbmRbIHRyYW5zaXRpb25FbmRQcm9wZXJ0eSBdID0gdGhpcy5vbkhpZGVUcmFuc2l0aW9uRW5kO1xuXG4gIHRoaXMudHJhbnNpdGlvbih7XG4gICAgZnJvbTogb3B0aW9ucy52aXNpYmxlU3R5bGUsXG4gICAgdG86IG9wdGlvbnMuaGlkZGVuU3R5bGUsXG4gICAgLy8ga2VlcCBoaWRkZW4gc3R1ZmYgaGlkZGVuXG4gICAgaXNDbGVhbmluZzogdHJ1ZSxcbiAgICBvblRyYW5zaXRpb25FbmQ6IG9uVHJhbnNpdGlvbkVuZFxuICB9KTtcbn07XG5cbnByb3RvLm9uSGlkZVRyYW5zaXRpb25FbmQgPSBmdW5jdGlvbigpIHtcbiAgLy8gY2hlY2sgaWYgc3RpbGwgaGlkZGVuXG4gIC8vIGR1cmluZyB0cmFuc2l0aW9uLCBpdGVtIG1heSBoYXZlIGJlZW4gdW4taGlkZGVuXG4gIGlmICggdGhpcy5pc0hpZGRlbiApIHtcbiAgICB0aGlzLmNzcyh7IGRpc3BsYXk6ICdub25lJyB9KTtcbiAgICB0aGlzLmVtaXRFdmVudCgnaGlkZScpO1xuICB9XG59O1xuXG5wcm90by5kZXN0cm95ID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuY3NzKHtcbiAgICBwb3NpdGlvbjogJycsXG4gICAgbGVmdDogJycsXG4gICAgcmlnaHQ6ICcnLFxuICAgIHRvcDogJycsXG4gICAgYm90dG9tOiAnJyxcbiAgICB0cmFuc2l0aW9uOiAnJyxcbiAgICB0cmFuc2Zvcm06ICcnXG4gIH0pO1xufTtcblxucmV0dXJuIEl0ZW07XG5cbn0pKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9vdXRsYXllci9pdGVtLmpzXG4vLyBtb2R1bGUgaWQgPSAyNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiFcbiAqIE91dGxheWVyIHYyLjEuMVxuICogdGhlIGJyYWlucyBhbmQgZ3V0cyBvZiBhIGxheW91dCBsaWJyYXJ5XG4gKiBNSVQgbGljZW5zZVxuICovXG5cbiggZnVuY3Rpb24oIHdpbmRvdywgZmFjdG9yeSApIHtcbiAgJ3VzZSBzdHJpY3QnO1xuICAvLyB1bml2ZXJzYWwgbW9kdWxlIGRlZmluaXRpb25cbiAgLyoganNoaW50IHN0cmljdDogZmFsc2UgKi8gLyogZ2xvYmFscyBkZWZpbmUsIG1vZHVsZSwgcmVxdWlyZSAqL1xuICBpZiAoIHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kICkge1xuICAgIC8vIEFNRCAtIFJlcXVpcmVKU1xuICAgIGRlZmluZSggW1xuICAgICAgICAnZXYtZW1pdHRlci9ldi1lbWl0dGVyJyxcbiAgICAgICAgJ2dldC1zaXplL2dldC1zaXplJyxcbiAgICAgICAgJ2Zpenp5LXVpLXV0aWxzL3V0aWxzJyxcbiAgICAgICAgJy4vaXRlbSdcbiAgICAgIF0sXG4gICAgICBmdW5jdGlvbiggRXZFbWl0dGVyLCBnZXRTaXplLCB1dGlscywgSXRlbSApIHtcbiAgICAgICAgcmV0dXJuIGZhY3RvcnkoIHdpbmRvdywgRXZFbWl0dGVyLCBnZXRTaXplLCB1dGlscywgSXRlbSk7XG4gICAgICB9XG4gICAgKTtcbiAgfSBlbHNlIGlmICggdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cyApIHtcbiAgICAvLyBDb21tb25KUyAtIEJyb3dzZXJpZnksIFdlYnBhY2tcbiAgICBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoXG4gICAgICB3aW5kb3csXG4gICAgICByZXF1aXJlKCdldi1lbWl0dGVyJyksXG4gICAgICByZXF1aXJlKCdnZXQtc2l6ZScpLFxuICAgICAgcmVxdWlyZSgnZml6enktdWktdXRpbHMnKSxcbiAgICAgIHJlcXVpcmUoJy4vaXRlbScpXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBicm93c2VyIGdsb2JhbFxuICAgIHdpbmRvdy5PdXRsYXllciA9IGZhY3RvcnkoXG4gICAgICB3aW5kb3csXG4gICAgICB3aW5kb3cuRXZFbWl0dGVyLFxuICAgICAgd2luZG93LmdldFNpemUsXG4gICAgICB3aW5kb3cuZml6enlVSVV0aWxzLFxuICAgICAgd2luZG93Lk91dGxheWVyLkl0ZW1cbiAgICApO1xuICB9XG5cbn0oIHdpbmRvdywgZnVuY3Rpb24gZmFjdG9yeSggd2luZG93LCBFdkVtaXR0ZXIsIGdldFNpemUsIHV0aWxzLCBJdGVtICkge1xuJ3VzZSBzdHJpY3QnO1xuXG4vLyAtLS0tLSB2YXJzIC0tLS0tIC8vXG5cbnZhciBjb25zb2xlID0gd2luZG93LmNvbnNvbGU7XG52YXIgalF1ZXJ5ID0gd2luZG93LmpRdWVyeTtcbnZhciBub29wID0gZnVuY3Rpb24oKSB7fTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gT3V0bGF5ZXIgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuLy8gZ2xvYmFsbHkgdW5pcXVlIGlkZW50aWZpZXJzXG52YXIgR1VJRCA9IDA7XG4vLyBpbnRlcm5hbCBzdG9yZSBvZiBhbGwgT3V0bGF5ZXIgaW50YW5jZXNcbnZhciBpbnN0YW5jZXMgPSB7fTtcblxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudCwgU3RyaW5nfSBlbGVtZW50XG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogQGNvbnN0cnVjdG9yXG4gKi9cbmZ1bmN0aW9uIE91dGxheWVyKCBlbGVtZW50LCBvcHRpb25zICkge1xuICB2YXIgcXVlcnlFbGVtZW50ID0gdXRpbHMuZ2V0UXVlcnlFbGVtZW50KCBlbGVtZW50ICk7XG4gIGlmICggIXF1ZXJ5RWxlbWVudCApIHtcbiAgICBpZiAoIGNvbnNvbGUgKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCAnQmFkIGVsZW1lbnQgZm9yICcgKyB0aGlzLmNvbnN0cnVjdG9yLm5hbWVzcGFjZSArXG4gICAgICAgICc6ICcgKyAoIHF1ZXJ5RWxlbWVudCB8fCBlbGVtZW50ICkgKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG4gIHRoaXMuZWxlbWVudCA9IHF1ZXJ5RWxlbWVudDtcbiAgLy8gYWRkIGpRdWVyeVxuICBpZiAoIGpRdWVyeSApIHtcbiAgICB0aGlzLiRlbGVtZW50ID0galF1ZXJ5KCB0aGlzLmVsZW1lbnQgKTtcbiAgfVxuXG4gIC8vIG9wdGlvbnNcbiAgdGhpcy5vcHRpb25zID0gdXRpbHMuZXh0ZW5kKCB7fSwgdGhpcy5jb25zdHJ1Y3Rvci5kZWZhdWx0cyApO1xuICB0aGlzLm9wdGlvbiggb3B0aW9ucyApO1xuXG4gIC8vIGFkZCBpZCBmb3IgT3V0bGF5ZXIuZ2V0RnJvbUVsZW1lbnRcbiAgdmFyIGlkID0gKytHVUlEO1xuICB0aGlzLmVsZW1lbnQub3V0bGF5ZXJHVUlEID0gaWQ7IC8vIGV4cGFuZG9cbiAgaW5zdGFuY2VzWyBpZCBdID0gdGhpczsgLy8gYXNzb2NpYXRlIHZpYSBpZFxuXG4gIC8vIGtpY2sgaXQgb2ZmXG4gIHRoaXMuX2NyZWF0ZSgpO1xuXG4gIHZhciBpc0luaXRMYXlvdXQgPSB0aGlzLl9nZXRPcHRpb24oJ2luaXRMYXlvdXQnKTtcbiAgaWYgKCBpc0luaXRMYXlvdXQgKSB7XG4gICAgdGhpcy5sYXlvdXQoKTtcbiAgfVxufVxuXG4vLyBzZXR0aW5ncyBhcmUgZm9yIGludGVybmFsIHVzZSBvbmx5XG5PdXRsYXllci5uYW1lc3BhY2UgPSAnb3V0bGF5ZXInO1xuT3V0bGF5ZXIuSXRlbSA9IEl0ZW07XG5cbi8vIGRlZmF1bHQgb3B0aW9uc1xuT3V0bGF5ZXIuZGVmYXVsdHMgPSB7XG4gIGNvbnRhaW5lclN0eWxlOiB7XG4gICAgcG9zaXRpb246ICdyZWxhdGl2ZSdcbiAgfSxcbiAgaW5pdExheW91dDogdHJ1ZSxcbiAgb3JpZ2luTGVmdDogdHJ1ZSxcbiAgb3JpZ2luVG9wOiB0cnVlLFxuICByZXNpemU6IHRydWUsXG4gIHJlc2l6ZUNvbnRhaW5lcjogdHJ1ZSxcbiAgLy8gaXRlbSBvcHRpb25zXG4gIHRyYW5zaXRpb25EdXJhdGlvbjogJzAuNHMnLFxuICBoaWRkZW5TdHlsZToge1xuICAgIG9wYWNpdHk6IDAsXG4gICAgdHJhbnNmb3JtOiAnc2NhbGUoMC4wMDEpJ1xuICB9LFxuICB2aXNpYmxlU3R5bGU6IHtcbiAgICBvcGFjaXR5OiAxLFxuICAgIHRyYW5zZm9ybTogJ3NjYWxlKDEpJ1xuICB9XG59O1xuXG52YXIgcHJvdG8gPSBPdXRsYXllci5wcm90b3R5cGU7XG4vLyBpbmhlcml0IEV2RW1pdHRlclxudXRpbHMuZXh0ZW5kKCBwcm90bywgRXZFbWl0dGVyLnByb3RvdHlwZSApO1xuXG4vKipcbiAqIHNldCBvcHRpb25zXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0c1xuICovXG5wcm90by5vcHRpb24gPSBmdW5jdGlvbiggb3B0cyApIHtcbiAgdXRpbHMuZXh0ZW5kKCB0aGlzLm9wdGlvbnMsIG9wdHMgKTtcbn07XG5cbi8qKlxuICogZ2V0IGJhY2t3YXJkcyBjb21wYXRpYmxlIG9wdGlvbiB2YWx1ZSwgY2hlY2sgb2xkIG5hbWVcbiAqL1xucHJvdG8uX2dldE9wdGlvbiA9IGZ1bmN0aW9uKCBvcHRpb24gKSB7XG4gIHZhciBvbGRPcHRpb24gPSB0aGlzLmNvbnN0cnVjdG9yLmNvbXBhdE9wdGlvbnNbIG9wdGlvbiBdO1xuICByZXR1cm4gb2xkT3B0aW9uICYmIHRoaXMub3B0aW9uc1sgb2xkT3B0aW9uIF0gIT09IHVuZGVmaW5lZCA/XG4gICAgdGhpcy5vcHRpb25zWyBvbGRPcHRpb24gXSA6IHRoaXMub3B0aW9uc1sgb3B0aW9uIF07XG59O1xuXG5PdXRsYXllci5jb21wYXRPcHRpb25zID0ge1xuICAvLyBjdXJyZW50TmFtZTogb2xkTmFtZVxuICBpbml0TGF5b3V0OiAnaXNJbml0TGF5b3V0JyxcbiAgaG9yaXpvbnRhbDogJ2lzSG9yaXpvbnRhbCcsXG4gIGxheW91dEluc3RhbnQ6ICdpc0xheW91dEluc3RhbnQnLFxuICBvcmlnaW5MZWZ0OiAnaXNPcmlnaW5MZWZ0JyxcbiAgb3JpZ2luVG9wOiAnaXNPcmlnaW5Ub3AnLFxuICByZXNpemU6ICdpc1Jlc2l6ZUJvdW5kJyxcbiAgcmVzaXplQ29udGFpbmVyOiAnaXNSZXNpemluZ0NvbnRhaW5lcidcbn07XG5cbnByb3RvLl9jcmVhdGUgPSBmdW5jdGlvbigpIHtcbiAgLy8gZ2V0IGl0ZW1zIGZyb20gY2hpbGRyZW5cbiAgdGhpcy5yZWxvYWRJdGVtcygpO1xuICAvLyBlbGVtZW50cyB0aGF0IGFmZmVjdCBsYXlvdXQsIGJ1dCBhcmUgbm90IGxhaWQgb3V0XG4gIHRoaXMuc3RhbXBzID0gW107XG4gIHRoaXMuc3RhbXAoIHRoaXMub3B0aW9ucy5zdGFtcCApO1xuICAvLyBzZXQgY29udGFpbmVyIHN0eWxlXG4gIHV0aWxzLmV4dGVuZCggdGhpcy5lbGVtZW50LnN0eWxlLCB0aGlzLm9wdGlvbnMuY29udGFpbmVyU3R5bGUgKTtcblxuICAvLyBiaW5kIHJlc2l6ZSBtZXRob2RcbiAgdmFyIGNhbkJpbmRSZXNpemUgPSB0aGlzLl9nZXRPcHRpb24oJ3Jlc2l6ZScpO1xuICBpZiAoIGNhbkJpbmRSZXNpemUgKSB7XG4gICAgdGhpcy5iaW5kUmVzaXplKCk7XG4gIH1cbn07XG5cbi8vIGdvZXMgdGhyb3VnaCBhbGwgY2hpbGRyZW4gYWdhaW4gYW5kIGdldHMgYnJpY2tzIGluIHByb3BlciBvcmRlclxucHJvdG8ucmVsb2FkSXRlbXMgPSBmdW5jdGlvbigpIHtcbiAgLy8gY29sbGVjdGlvbiBvZiBpdGVtIGVsZW1lbnRzXG4gIHRoaXMuaXRlbXMgPSB0aGlzLl9pdGVtaXplKCB0aGlzLmVsZW1lbnQuY2hpbGRyZW4gKTtcbn07XG5cblxuLyoqXG4gKiB0dXJuIGVsZW1lbnRzIGludG8gT3V0bGF5ZXIuSXRlbXMgdG8gYmUgdXNlZCBpbiBsYXlvdXRcbiAqIEBwYXJhbSB7QXJyYXkgb3IgTm9kZUxpc3Qgb3IgSFRNTEVsZW1lbnR9IGVsZW1zXG4gKiBAcmV0dXJucyB7QXJyYXl9IGl0ZW1zIC0gY29sbGVjdGlvbiBvZiBuZXcgT3V0bGF5ZXIgSXRlbXNcbiAqL1xucHJvdG8uX2l0ZW1pemUgPSBmdW5jdGlvbiggZWxlbXMgKSB7XG5cbiAgdmFyIGl0ZW1FbGVtcyA9IHRoaXMuX2ZpbHRlckZpbmRJdGVtRWxlbWVudHMoIGVsZW1zICk7XG4gIHZhciBJdGVtID0gdGhpcy5jb25zdHJ1Y3Rvci5JdGVtO1xuXG4gIC8vIGNyZWF0ZSBuZXcgT3V0bGF5ZXIgSXRlbXMgZm9yIGNvbGxlY3Rpb25cbiAgdmFyIGl0ZW1zID0gW107XG4gIGZvciAoIHZhciBpPTA7IGkgPCBpdGVtRWxlbXMubGVuZ3RoOyBpKysgKSB7XG4gICAgdmFyIGVsZW0gPSBpdGVtRWxlbXNbaV07XG4gICAgdmFyIGl0ZW0gPSBuZXcgSXRlbSggZWxlbSwgdGhpcyApO1xuICAgIGl0ZW1zLnB1c2goIGl0ZW0gKTtcbiAgfVxuXG4gIHJldHVybiBpdGVtcztcbn07XG5cbi8qKlxuICogZ2V0IGl0ZW0gZWxlbWVudHMgdG8gYmUgdXNlZCBpbiBsYXlvdXRcbiAqIEBwYXJhbSB7QXJyYXkgb3IgTm9kZUxpc3Qgb3IgSFRNTEVsZW1lbnR9IGVsZW1zXG4gKiBAcmV0dXJucyB7QXJyYXl9IGl0ZW1zIC0gaXRlbSBlbGVtZW50c1xuICovXG5wcm90by5fZmlsdGVyRmluZEl0ZW1FbGVtZW50cyA9IGZ1bmN0aW9uKCBlbGVtcyApIHtcbiAgcmV0dXJuIHV0aWxzLmZpbHRlckZpbmRFbGVtZW50cyggZWxlbXMsIHRoaXMub3B0aW9ucy5pdGVtU2VsZWN0b3IgKTtcbn07XG5cbi8qKlxuICogZ2V0dGVyIG1ldGhvZCBmb3IgZ2V0dGluZyBpdGVtIGVsZW1lbnRzXG4gKiBAcmV0dXJucyB7QXJyYXl9IGVsZW1zIC0gY29sbGVjdGlvbiBvZiBpdGVtIGVsZW1lbnRzXG4gKi9cbnByb3RvLmdldEl0ZW1FbGVtZW50cyA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5pdGVtcy5tYXAoIGZ1bmN0aW9uKCBpdGVtICkge1xuICAgIHJldHVybiBpdGVtLmVsZW1lbnQ7XG4gIH0pO1xufTtcblxuLy8gLS0tLS0gaW5pdCAmIGxheW91dCAtLS0tLSAvL1xuXG4vKipcbiAqIGxheXMgb3V0IGFsbCBpdGVtc1xuICovXG5wcm90by5sYXlvdXQgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5fcmVzZXRMYXlvdXQoKTtcbiAgdGhpcy5fbWFuYWdlU3RhbXBzKCk7XG5cbiAgLy8gZG9uJ3QgYW5pbWF0ZSBmaXJzdCBsYXlvdXRcbiAgdmFyIGxheW91dEluc3RhbnQgPSB0aGlzLl9nZXRPcHRpb24oJ2xheW91dEluc3RhbnQnKTtcbiAgdmFyIGlzSW5zdGFudCA9IGxheW91dEluc3RhbnQgIT09IHVuZGVmaW5lZCA/XG4gICAgbGF5b3V0SW5zdGFudCA6ICF0aGlzLl9pc0xheW91dEluaXRlZDtcbiAgdGhpcy5sYXlvdXRJdGVtcyggdGhpcy5pdGVtcywgaXNJbnN0YW50ICk7XG5cbiAgLy8gZmxhZyBmb3IgaW5pdGFsaXplZFxuICB0aGlzLl9pc0xheW91dEluaXRlZCA9IHRydWU7XG59O1xuXG4vLyBfaW5pdCBpcyBhbGlhcyBmb3IgbGF5b3V0XG5wcm90by5faW5pdCA9IHByb3RvLmxheW91dDtcblxuLyoqXG4gKiBsb2dpYyBiZWZvcmUgYW55IG5ldyBsYXlvdXRcbiAqL1xucHJvdG8uX3Jlc2V0TGF5b3V0ID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZ2V0U2l6ZSgpO1xufTtcblxuXG5wcm90by5nZXRTaXplID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuc2l6ZSA9IGdldFNpemUoIHRoaXMuZWxlbWVudCApO1xufTtcblxuLyoqXG4gKiBnZXQgbWVhc3VyZW1lbnQgZnJvbSBvcHRpb24sIGZvciBjb2x1bW5XaWR0aCwgcm93SGVpZ2h0LCBndXR0ZXJcbiAqIGlmIG9wdGlvbiBpcyBTdHJpbmcgLT4gZ2V0IGVsZW1lbnQgZnJvbSBzZWxlY3RvciBzdHJpbmcsICYgZ2V0IHNpemUgb2YgZWxlbWVudFxuICogaWYgb3B0aW9uIGlzIEVsZW1lbnQgLT4gZ2V0IHNpemUgb2YgZWxlbWVudFxuICogZWxzZSB1c2Ugb3B0aW9uIGFzIGEgbnVtYmVyXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1lYXN1cmVtZW50XG4gKiBAcGFyYW0ge1N0cmluZ30gc2l6ZSAtIHdpZHRoIG9yIGhlaWdodFxuICogQHByaXZhdGVcbiAqL1xucHJvdG8uX2dldE1lYXN1cmVtZW50ID0gZnVuY3Rpb24oIG1lYXN1cmVtZW50LCBzaXplICkge1xuICB2YXIgb3B0aW9uID0gdGhpcy5vcHRpb25zWyBtZWFzdXJlbWVudCBdO1xuICB2YXIgZWxlbTtcbiAgaWYgKCAhb3B0aW9uICkge1xuICAgIC8vIGRlZmF1bHQgdG8gMFxuICAgIHRoaXNbIG1lYXN1cmVtZW50IF0gPSAwO1xuICB9IGVsc2Uge1xuICAgIC8vIHVzZSBvcHRpb24gYXMgYW4gZWxlbWVudFxuICAgIGlmICggdHlwZW9mIG9wdGlvbiA9PSAnc3RyaW5nJyApIHtcbiAgICAgIGVsZW0gPSB0aGlzLmVsZW1lbnQucXVlcnlTZWxlY3Rvciggb3B0aW9uICk7XG4gICAgfSBlbHNlIGlmICggb3B0aW9uIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQgKSB7XG4gICAgICBlbGVtID0gb3B0aW9uO1xuICAgIH1cbiAgICAvLyB1c2Ugc2l6ZSBvZiBlbGVtZW50LCBpZiBlbGVtZW50XG4gICAgdGhpc1sgbWVhc3VyZW1lbnQgXSA9IGVsZW0gPyBnZXRTaXplKCBlbGVtIClbIHNpemUgXSA6IG9wdGlvbjtcbiAgfVxufTtcblxuLyoqXG4gKiBsYXlvdXQgYSBjb2xsZWN0aW9uIG9mIGl0ZW0gZWxlbWVudHNcbiAqIEBhcGkgcHVibGljXG4gKi9cbnByb3RvLmxheW91dEl0ZW1zID0gZnVuY3Rpb24oIGl0ZW1zLCBpc0luc3RhbnQgKSB7XG4gIGl0ZW1zID0gdGhpcy5fZ2V0SXRlbXNGb3JMYXlvdXQoIGl0ZW1zICk7XG5cbiAgdGhpcy5fbGF5b3V0SXRlbXMoIGl0ZW1zLCBpc0luc3RhbnQgKTtcblxuICB0aGlzLl9wb3N0TGF5b3V0KCk7XG59O1xuXG4vKipcbiAqIGdldCB0aGUgaXRlbXMgdG8gYmUgbGFpZCBvdXRcbiAqIHlvdSBtYXkgd2FudCB0byBza2lwIG92ZXIgc29tZSBpdGVtc1xuICogQHBhcmFtIHtBcnJheX0gaXRlbXNcbiAqIEByZXR1cm5zIHtBcnJheX0gaXRlbXNcbiAqL1xucHJvdG8uX2dldEl0ZW1zRm9yTGF5b3V0ID0gZnVuY3Rpb24oIGl0ZW1zICkge1xuICByZXR1cm4gaXRlbXMuZmlsdGVyKCBmdW5jdGlvbiggaXRlbSApIHtcbiAgICByZXR1cm4gIWl0ZW0uaXNJZ25vcmVkO1xuICB9KTtcbn07XG5cbi8qKlxuICogbGF5b3V0IGl0ZW1zXG4gKiBAcGFyYW0ge0FycmF5fSBpdGVtc1xuICogQHBhcmFtIHtCb29sZWFufSBpc0luc3RhbnRcbiAqL1xucHJvdG8uX2xheW91dEl0ZW1zID0gZnVuY3Rpb24oIGl0ZW1zLCBpc0luc3RhbnQgKSB7XG4gIHRoaXMuX2VtaXRDb21wbGV0ZU9uSXRlbXMoICdsYXlvdXQnLCBpdGVtcyApO1xuXG4gIGlmICggIWl0ZW1zIHx8ICFpdGVtcy5sZW5ndGggKSB7XG4gICAgLy8gbm8gaXRlbXMsIGVtaXQgZXZlbnQgd2l0aCBlbXB0eSBhcnJheVxuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhciBxdWV1ZSA9IFtdO1xuXG4gIGl0ZW1zLmZvckVhY2goIGZ1bmN0aW9uKCBpdGVtICkge1xuICAgIC8vIGdldCB4L3kgb2JqZWN0IGZyb20gbWV0aG9kXG4gICAgdmFyIHBvc2l0aW9uID0gdGhpcy5fZ2V0SXRlbUxheW91dFBvc2l0aW9uKCBpdGVtICk7XG4gICAgLy8gZW5xdWV1ZVxuICAgIHBvc2l0aW9uLml0ZW0gPSBpdGVtO1xuICAgIHBvc2l0aW9uLmlzSW5zdGFudCA9IGlzSW5zdGFudCB8fCBpdGVtLmlzTGF5b3V0SW5zdGFudDtcbiAgICBxdWV1ZS5wdXNoKCBwb3NpdGlvbiApO1xuICB9LCB0aGlzICk7XG5cbiAgdGhpcy5fcHJvY2Vzc0xheW91dFF1ZXVlKCBxdWV1ZSApO1xufTtcblxuLyoqXG4gKiBnZXQgaXRlbSBsYXlvdXQgcG9zaXRpb25cbiAqIEBwYXJhbSB7T3V0bGF5ZXIuSXRlbX0gaXRlbVxuICogQHJldHVybnMge09iamVjdH0geCBhbmQgeSBwb3NpdGlvblxuICovXG5wcm90by5fZ2V0SXRlbUxheW91dFBvc2l0aW9uID0gZnVuY3Rpb24oIC8qIGl0ZW0gKi8gKSB7XG4gIHJldHVybiB7XG4gICAgeDogMCxcbiAgICB5OiAwXG4gIH07XG59O1xuXG4vKipcbiAqIGl0ZXJhdGUgb3ZlciBhcnJheSBhbmQgcG9zaXRpb24gZWFjaCBpdGVtXG4gKiBSZWFzb24gYmVpbmcgLSBzZXBhcmF0aW5nIHRoaXMgbG9naWMgcHJldmVudHMgJ2xheW91dCBpbnZhbGlkYXRpb24nXG4gKiB0aHggQHBhdWxfaXJpc2hcbiAqIEBwYXJhbSB7QXJyYXl9IHF1ZXVlXG4gKi9cbnByb3RvLl9wcm9jZXNzTGF5b3V0UXVldWUgPSBmdW5jdGlvbiggcXVldWUgKSB7XG4gIHRoaXMudXBkYXRlU3RhZ2dlcigpO1xuICBxdWV1ZS5mb3JFYWNoKCBmdW5jdGlvbiggb2JqLCBpICkge1xuICAgIHRoaXMuX3Bvc2l0aW9uSXRlbSggb2JqLml0ZW0sIG9iai54LCBvYmoueSwgb2JqLmlzSW5zdGFudCwgaSApO1xuICB9LCB0aGlzICk7XG59O1xuXG4vLyBzZXQgc3RhZ2dlciBmcm9tIG9wdGlvbiBpbiBtaWxsaXNlY29uZHMgbnVtYmVyXG5wcm90by51cGRhdGVTdGFnZ2VyID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzdGFnZ2VyID0gdGhpcy5vcHRpb25zLnN0YWdnZXI7XG4gIGlmICggc3RhZ2dlciA9PT0gbnVsbCB8fCBzdGFnZ2VyID09PSB1bmRlZmluZWQgKSB7XG4gICAgdGhpcy5zdGFnZ2VyID0gMDtcbiAgICByZXR1cm47XG4gIH1cbiAgdGhpcy5zdGFnZ2VyID0gZ2V0TWlsbGlzZWNvbmRzKCBzdGFnZ2VyICk7XG4gIHJldHVybiB0aGlzLnN0YWdnZXI7XG59O1xuXG4vKipcbiAqIFNldHMgcG9zaXRpb24gb2YgaXRlbSBpbiBET01cbiAqIEBwYXJhbSB7T3V0bGF5ZXIuSXRlbX0gaXRlbVxuICogQHBhcmFtIHtOdW1iZXJ9IHggLSBob3Jpem9udGFsIHBvc2l0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0geSAtIHZlcnRpY2FsIHBvc2l0aW9uXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGlzSW5zdGFudCAtIGRpc2FibGVzIHRyYW5zaXRpb25zXG4gKi9cbnByb3RvLl9wb3NpdGlvbkl0ZW0gPSBmdW5jdGlvbiggaXRlbSwgeCwgeSwgaXNJbnN0YW50LCBpICkge1xuICBpZiAoIGlzSW5zdGFudCApIHtcbiAgICAvLyBpZiBub3QgdHJhbnNpdGlvbiwganVzdCBzZXQgQ1NTXG4gICAgaXRlbS5nb1RvKCB4LCB5ICk7XG4gIH0gZWxzZSB7XG4gICAgaXRlbS5zdGFnZ2VyKCBpICogdGhpcy5zdGFnZ2VyICk7XG4gICAgaXRlbS5tb3ZlVG8oIHgsIHkgKTtcbiAgfVxufTtcblxuLyoqXG4gKiBBbnkgbG9naWMgeW91IHdhbnQgdG8gZG8gYWZ0ZXIgZWFjaCBsYXlvdXQsXG4gKiBpLmUuIHNpemUgdGhlIGNvbnRhaW5lclxuICovXG5wcm90by5fcG9zdExheW91dCA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnJlc2l6ZUNvbnRhaW5lcigpO1xufTtcblxucHJvdG8ucmVzaXplQ29udGFpbmVyID0gZnVuY3Rpb24oKSB7XG4gIHZhciBpc1Jlc2l6aW5nQ29udGFpbmVyID0gdGhpcy5fZ2V0T3B0aW9uKCdyZXNpemVDb250YWluZXInKTtcbiAgaWYgKCAhaXNSZXNpemluZ0NvbnRhaW5lciApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIHNpemUgPSB0aGlzLl9nZXRDb250YWluZXJTaXplKCk7XG4gIGlmICggc2l6ZSApIHtcbiAgICB0aGlzLl9zZXRDb250YWluZXJNZWFzdXJlKCBzaXplLndpZHRoLCB0cnVlICk7XG4gICAgdGhpcy5fc2V0Q29udGFpbmVyTWVhc3VyZSggc2l6ZS5oZWlnaHQsIGZhbHNlICk7XG4gIH1cbn07XG5cbi8qKlxuICogU2V0cyB3aWR0aCBvciBoZWlnaHQgb2YgY29udGFpbmVyIGlmIHJldHVybmVkXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBzaXplXG4gKiAgIEBwYXJhbSB7TnVtYmVyfSB3aWR0aFxuICogICBAcGFyYW0ge051bWJlcn0gaGVpZ2h0XG4gKi9cbnByb3RvLl9nZXRDb250YWluZXJTaXplID0gbm9vcDtcblxuLyoqXG4gKiBAcGFyYW0ge051bWJlcn0gbWVhc3VyZSAtIHNpemUgb2Ygd2lkdGggb3IgaGVpZ2h0XG4gKiBAcGFyYW0ge0Jvb2xlYW59IGlzV2lkdGhcbiAqL1xucHJvdG8uX3NldENvbnRhaW5lck1lYXN1cmUgPSBmdW5jdGlvbiggbWVhc3VyZSwgaXNXaWR0aCApIHtcbiAgaWYgKCBtZWFzdXJlID09PSB1bmRlZmluZWQgKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGVsZW1TaXplID0gdGhpcy5zaXplO1xuICAvLyBhZGQgcGFkZGluZyBhbmQgYm9yZGVyIHdpZHRoIGlmIGJvcmRlciBib3hcbiAgaWYgKCBlbGVtU2l6ZS5pc0JvcmRlckJveCApIHtcbiAgICBtZWFzdXJlICs9IGlzV2lkdGggPyBlbGVtU2l6ZS5wYWRkaW5nTGVmdCArIGVsZW1TaXplLnBhZGRpbmdSaWdodCArXG4gICAgICBlbGVtU2l6ZS5ib3JkZXJMZWZ0V2lkdGggKyBlbGVtU2l6ZS5ib3JkZXJSaWdodFdpZHRoIDpcbiAgICAgIGVsZW1TaXplLnBhZGRpbmdCb3R0b20gKyBlbGVtU2l6ZS5wYWRkaW5nVG9wICtcbiAgICAgIGVsZW1TaXplLmJvcmRlclRvcFdpZHRoICsgZWxlbVNpemUuYm9yZGVyQm90dG9tV2lkdGg7XG4gIH1cblxuICBtZWFzdXJlID0gTWF0aC5tYXgoIG1lYXN1cmUsIDAgKTtcbiAgdGhpcy5lbGVtZW50LnN0eWxlWyBpc1dpZHRoID8gJ3dpZHRoJyA6ICdoZWlnaHQnIF0gPSBtZWFzdXJlICsgJ3B4Jztcbn07XG5cbi8qKlxuICogZW1pdCBldmVudENvbXBsZXRlIG9uIGEgY29sbGVjdGlvbiBvZiBpdGVtcyBldmVudHNcbiAqIEBwYXJhbSB7U3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7QXJyYXl9IGl0ZW1zIC0gT3V0bGF5ZXIuSXRlbXNcbiAqL1xucHJvdG8uX2VtaXRDb21wbGV0ZU9uSXRlbXMgPSBmdW5jdGlvbiggZXZlbnROYW1lLCBpdGVtcyApIHtcbiAgdmFyIF90aGlzID0gdGhpcztcbiAgZnVuY3Rpb24gb25Db21wbGV0ZSgpIHtcbiAgICBfdGhpcy5kaXNwYXRjaEV2ZW50KCBldmVudE5hbWUgKyAnQ29tcGxldGUnLCBudWxsLCBbIGl0ZW1zIF0gKTtcbiAgfVxuXG4gIHZhciBjb3VudCA9IGl0ZW1zLmxlbmd0aDtcbiAgaWYgKCAhaXRlbXMgfHwgIWNvdW50ICkge1xuICAgIG9uQ29tcGxldGUoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgZG9uZUNvdW50ID0gMDtcbiAgZnVuY3Rpb24gdGljaygpIHtcbiAgICBkb25lQ291bnQrKztcbiAgICBpZiAoIGRvbmVDb3VudCA9PSBjb3VudCApIHtcbiAgICAgIG9uQ29tcGxldGUoKTtcbiAgICB9XG4gIH1cblxuICAvLyBiaW5kIGNhbGxiYWNrXG4gIGl0ZW1zLmZvckVhY2goIGZ1bmN0aW9uKCBpdGVtICkge1xuICAgIGl0ZW0ub25jZSggZXZlbnROYW1lLCB0aWNrICk7XG4gIH0pO1xufTtcblxuLyoqXG4gKiBlbWl0cyBldmVudHMgdmlhIEV2RW1pdHRlciBhbmQgalF1ZXJ5IGV2ZW50c1xuICogQHBhcmFtIHtTdHJpbmd9IHR5cGUgLSBuYW1lIG9mIGV2ZW50XG4gKiBAcGFyYW0ge0V2ZW50fSBldmVudCAtIG9yaWdpbmFsIGV2ZW50XG4gKiBAcGFyYW0ge0FycmF5fSBhcmdzIC0gZXh0cmEgYXJndW1lbnRzXG4gKi9cbnByb3RvLmRpc3BhdGNoRXZlbnQgPSBmdW5jdGlvbiggdHlwZSwgZXZlbnQsIGFyZ3MgKSB7XG4gIC8vIGFkZCBvcmlnaW5hbCBldmVudCB0byBhcmd1bWVudHNcbiAgdmFyIGVtaXRBcmdzID0gZXZlbnQgPyBbIGV2ZW50IF0uY29uY2F0KCBhcmdzICkgOiBhcmdzO1xuICB0aGlzLmVtaXRFdmVudCggdHlwZSwgZW1pdEFyZ3MgKTtcblxuICBpZiAoIGpRdWVyeSApIHtcbiAgICAvLyBzZXQgdGhpcy4kZWxlbWVudFxuICAgIHRoaXMuJGVsZW1lbnQgPSB0aGlzLiRlbGVtZW50IHx8IGpRdWVyeSggdGhpcy5lbGVtZW50ICk7XG4gICAgaWYgKCBldmVudCApIHtcbiAgICAgIC8vIGNyZWF0ZSBqUXVlcnkgZXZlbnRcbiAgICAgIHZhciAkZXZlbnQgPSBqUXVlcnkuRXZlbnQoIGV2ZW50ICk7XG4gICAgICAkZXZlbnQudHlwZSA9IHR5cGU7XG4gICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoICRldmVudCwgYXJncyApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBqdXN0IHRyaWdnZXIgd2l0aCB0eXBlIGlmIG5vIGV2ZW50IGF2YWlsYWJsZVxuICAgICAgdGhpcy4kZWxlbWVudC50cmlnZ2VyKCB0eXBlLCBhcmdzICk7XG4gICAgfVxuICB9XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBpZ25vcmUgJiBzdGFtcHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuXG4vKipcbiAqIGtlZXAgaXRlbSBpbiBjb2xsZWN0aW9uLCBidXQgZG8gbm90IGxheSBpdCBvdXRcbiAqIGlnbm9yZWQgaXRlbXMgZG8gbm90IGdldCBza2lwcGVkIGluIGxheW91dFxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtXG4gKi9cbnByb3RvLmlnbm9yZSA9IGZ1bmN0aW9uKCBlbGVtICkge1xuICB2YXIgaXRlbSA9IHRoaXMuZ2V0SXRlbSggZWxlbSApO1xuICBpZiAoIGl0ZW0gKSB7XG4gICAgaXRlbS5pc0lnbm9yZWQgPSB0cnVlO1xuICB9XG59O1xuXG4vKipcbiAqIHJldHVybiBpdGVtIHRvIGxheW91dCBjb2xsZWN0aW9uXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1cbiAqL1xucHJvdG8udW5pZ25vcmUgPSBmdW5jdGlvbiggZWxlbSApIHtcbiAgdmFyIGl0ZW0gPSB0aGlzLmdldEl0ZW0oIGVsZW0gKTtcbiAgaWYgKCBpdGVtICkge1xuICAgIGRlbGV0ZSBpdGVtLmlzSWdub3JlZDtcbiAgfVxufTtcblxuLyoqXG4gKiBhZGRzIGVsZW1lbnRzIHRvIHN0YW1wc1xuICogQHBhcmFtIHtOb2RlTGlzdCwgQXJyYXksIEVsZW1lbnQsIG9yIFN0cmluZ30gZWxlbXNcbiAqL1xucHJvdG8uc3RhbXAgPSBmdW5jdGlvbiggZWxlbXMgKSB7XG4gIGVsZW1zID0gdGhpcy5fZmluZCggZWxlbXMgKTtcbiAgaWYgKCAhZWxlbXMgKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdGhpcy5zdGFtcHMgPSB0aGlzLnN0YW1wcy5jb25jYXQoIGVsZW1zICk7XG4gIC8vIGlnbm9yZVxuICBlbGVtcy5mb3JFYWNoKCB0aGlzLmlnbm9yZSwgdGhpcyApO1xufTtcblxuLyoqXG4gKiByZW1vdmVzIGVsZW1lbnRzIHRvIHN0YW1wc1xuICogQHBhcmFtIHtOb2RlTGlzdCwgQXJyYXksIG9yIEVsZW1lbnR9IGVsZW1zXG4gKi9cbnByb3RvLnVuc3RhbXAgPSBmdW5jdGlvbiggZWxlbXMgKSB7XG4gIGVsZW1zID0gdGhpcy5fZmluZCggZWxlbXMgKTtcbiAgaWYgKCAhZWxlbXMgKXtcbiAgICByZXR1cm47XG4gIH1cblxuICBlbGVtcy5mb3JFYWNoKCBmdW5jdGlvbiggZWxlbSApIHtcbiAgICAvLyBmaWx0ZXIgb3V0IHJlbW92ZWQgc3RhbXAgZWxlbWVudHNcbiAgICB1dGlscy5yZW1vdmVGcm9tKCB0aGlzLnN0YW1wcywgZWxlbSApO1xuICAgIHRoaXMudW5pZ25vcmUoIGVsZW0gKTtcbiAgfSwgdGhpcyApO1xufTtcblxuLyoqXG4gKiBmaW5kcyBjaGlsZCBlbGVtZW50c1xuICogQHBhcmFtIHtOb2RlTGlzdCwgQXJyYXksIEVsZW1lbnQsIG9yIFN0cmluZ30gZWxlbXNcbiAqIEByZXR1cm5zIHtBcnJheX0gZWxlbXNcbiAqL1xucHJvdG8uX2ZpbmQgPSBmdW5jdGlvbiggZWxlbXMgKSB7XG4gIGlmICggIWVsZW1zICkge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBpZiBzdHJpbmcsIHVzZSBhcmd1bWVudCBhcyBzZWxlY3RvciBzdHJpbmdcbiAgaWYgKCB0eXBlb2YgZWxlbXMgPT0gJ3N0cmluZycgKSB7XG4gICAgZWxlbXMgPSB0aGlzLmVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCggZWxlbXMgKTtcbiAgfVxuICBlbGVtcyA9IHV0aWxzLm1ha2VBcnJheSggZWxlbXMgKTtcbiAgcmV0dXJuIGVsZW1zO1xufTtcblxucHJvdG8uX21hbmFnZVN0YW1wcyA9IGZ1bmN0aW9uKCkge1xuICBpZiAoICF0aGlzLnN0YW1wcyB8fCAhdGhpcy5zdGFtcHMubGVuZ3RoICkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRoaXMuX2dldEJvdW5kaW5nUmVjdCgpO1xuXG4gIHRoaXMuc3RhbXBzLmZvckVhY2goIHRoaXMuX21hbmFnZVN0YW1wLCB0aGlzICk7XG59O1xuXG4vLyB1cGRhdGUgYm91bmRpbmdMZWZ0IC8gVG9wXG5wcm90by5fZ2V0Qm91bmRpbmdSZWN0ID0gZnVuY3Rpb24oKSB7XG4gIC8vIGdldCBib3VuZGluZyByZWN0IGZvciBjb250YWluZXIgZWxlbWVudFxuICB2YXIgYm91bmRpbmdSZWN0ID0gdGhpcy5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICB2YXIgc2l6ZSA9IHRoaXMuc2l6ZTtcbiAgdGhpcy5fYm91bmRpbmdSZWN0ID0ge1xuICAgIGxlZnQ6IGJvdW5kaW5nUmVjdC5sZWZ0ICsgc2l6ZS5wYWRkaW5nTGVmdCArIHNpemUuYm9yZGVyTGVmdFdpZHRoLFxuICAgIHRvcDogYm91bmRpbmdSZWN0LnRvcCArIHNpemUucGFkZGluZ1RvcCArIHNpemUuYm9yZGVyVG9wV2lkdGgsXG4gICAgcmlnaHQ6IGJvdW5kaW5nUmVjdC5yaWdodCAtICggc2l6ZS5wYWRkaW5nUmlnaHQgKyBzaXplLmJvcmRlclJpZ2h0V2lkdGggKSxcbiAgICBib3R0b206IGJvdW5kaW5nUmVjdC5ib3R0b20gLSAoIHNpemUucGFkZGluZ0JvdHRvbSArIHNpemUuYm9yZGVyQm90dG9tV2lkdGggKVxuICB9O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IHN0YW1wXG4qKi9cbnByb3RvLl9tYW5hZ2VTdGFtcCA9IG5vb3A7XG5cbi8qKlxuICogZ2V0IHgveSBwb3NpdGlvbiBvZiBlbGVtZW50IHJlbGF0aXZlIHRvIGNvbnRhaW5lciBlbGVtZW50XG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1cbiAqIEByZXR1cm5zIHtPYmplY3R9IG9mZnNldCAtIGhhcyBsZWZ0LCB0b3AsIHJpZ2h0LCBib3R0b21cbiAqL1xucHJvdG8uX2dldEVsZW1lbnRPZmZzZXQgPSBmdW5jdGlvbiggZWxlbSApIHtcbiAgdmFyIGJvdW5kaW5nUmVjdCA9IGVsZW0uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gIHZhciB0aGlzUmVjdCA9IHRoaXMuX2JvdW5kaW5nUmVjdDtcbiAgdmFyIHNpemUgPSBnZXRTaXplKCBlbGVtICk7XG4gIHZhciBvZmZzZXQgPSB7XG4gICAgbGVmdDogYm91bmRpbmdSZWN0LmxlZnQgLSB0aGlzUmVjdC5sZWZ0IC0gc2l6ZS5tYXJnaW5MZWZ0LFxuICAgIHRvcDogYm91bmRpbmdSZWN0LnRvcCAtIHRoaXNSZWN0LnRvcCAtIHNpemUubWFyZ2luVG9wLFxuICAgIHJpZ2h0OiB0aGlzUmVjdC5yaWdodCAtIGJvdW5kaW5nUmVjdC5yaWdodCAtIHNpemUubWFyZ2luUmlnaHQsXG4gICAgYm90dG9tOiB0aGlzUmVjdC5ib3R0b20gLSBib3VuZGluZ1JlY3QuYm90dG9tIC0gc2l6ZS5tYXJnaW5Cb3R0b21cbiAgfTtcbiAgcmV0dXJuIG9mZnNldDtcbn07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHJlc2l6ZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4vLyBlbmFibGUgZXZlbnQgaGFuZGxlcnMgZm9yIGxpc3RlbmVyc1xuLy8gaS5lLiByZXNpemUgLT4gb25yZXNpemVcbnByb3RvLmhhbmRsZUV2ZW50ID0gdXRpbHMuaGFuZGxlRXZlbnQ7XG5cbi8qKlxuICogQmluZCBsYXlvdXQgdG8gd2luZG93IHJlc2l6aW5nXG4gKi9cbnByb3RvLmJpbmRSZXNpemUgPSBmdW5jdGlvbigpIHtcbiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoICdyZXNpemUnLCB0aGlzICk7XG4gIHRoaXMuaXNSZXNpemVCb3VuZCA9IHRydWU7XG59O1xuXG4vKipcbiAqIFVuYmluZCBsYXlvdXQgdG8gd2luZG93IHJlc2l6aW5nXG4gKi9cbnByb3RvLnVuYmluZFJlc2l6ZSA9IGZ1bmN0aW9uKCkge1xuICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lciggJ3Jlc2l6ZScsIHRoaXMgKTtcbiAgdGhpcy5pc1Jlc2l6ZUJvdW5kID0gZmFsc2U7XG59O1xuXG5wcm90by5vbnJlc2l6ZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLnJlc2l6ZSgpO1xufTtcblxudXRpbHMuZGVib3VuY2VNZXRob2QoIE91dGxheWVyLCAnb25yZXNpemUnLCAxMDAgKTtcblxucHJvdG8ucmVzaXplID0gZnVuY3Rpb24oKSB7XG4gIC8vIGRvbid0IHRyaWdnZXIgaWYgc2l6ZSBkaWQgbm90IGNoYW5nZVxuICAvLyBvciBpZiByZXNpemUgd2FzIHVuYm91bmQuIFNlZSAjOVxuICBpZiAoICF0aGlzLmlzUmVzaXplQm91bmQgfHwgIXRoaXMubmVlZHNSZXNpemVMYXlvdXQoKSApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB0aGlzLmxheW91dCgpO1xufTtcblxuLyoqXG4gKiBjaGVjayBpZiBsYXlvdXQgaXMgbmVlZGVkIHBvc3QgbGF5b3V0XG4gKiBAcmV0dXJucyBCb29sZWFuXG4gKi9cbnByb3RvLm5lZWRzUmVzaXplTGF5b3V0ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzaXplID0gZ2V0U2l6ZSggdGhpcy5lbGVtZW50ICk7XG4gIC8vIGNoZWNrIHRoYXQgdGhpcy5zaXplIGFuZCBzaXplIGFyZSB0aGVyZVxuICAvLyBJRTggdHJpZ2dlcnMgcmVzaXplIG9uIGJvZHkgc2l6ZSBjaGFuZ2UsIHNvIHRoZXkgbWlnaHQgbm90IGJlXG4gIHZhciBoYXNTaXplcyA9IHRoaXMuc2l6ZSAmJiBzaXplO1xuICByZXR1cm4gaGFzU2l6ZXMgJiYgc2l6ZS5pbm5lcldpZHRoICE9PSB0aGlzLnNpemUuaW5uZXJXaWR0aDtcbn07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIG1ldGhvZHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuLyoqXG4gKiBhZGQgaXRlbXMgdG8gT3V0bGF5ZXIgaW5zdGFuY2VcbiAqIEBwYXJhbSB7QXJyYXkgb3IgTm9kZUxpc3Qgb3IgRWxlbWVudH0gZWxlbXNcbiAqIEByZXR1cm5zIHtBcnJheX0gaXRlbXMgLSBPdXRsYXllci5JdGVtc1xuKiovXG5wcm90by5hZGRJdGVtcyA9IGZ1bmN0aW9uKCBlbGVtcyApIHtcbiAgdmFyIGl0ZW1zID0gdGhpcy5faXRlbWl6ZSggZWxlbXMgKTtcbiAgLy8gYWRkIGl0ZW1zIHRvIGNvbGxlY3Rpb25cbiAgaWYgKCBpdGVtcy5sZW5ndGggKSB7XG4gICAgdGhpcy5pdGVtcyA9IHRoaXMuaXRlbXMuY29uY2F0KCBpdGVtcyApO1xuICB9XG4gIHJldHVybiBpdGVtcztcbn07XG5cbi8qKlxuICogTGF5b3V0IG5ld2x5LWFwcGVuZGVkIGl0ZW0gZWxlbWVudHNcbiAqIEBwYXJhbSB7QXJyYXkgb3IgTm9kZUxpc3Qgb3IgRWxlbWVudH0gZWxlbXNcbiAqL1xucHJvdG8uYXBwZW5kZWQgPSBmdW5jdGlvbiggZWxlbXMgKSB7XG4gIHZhciBpdGVtcyA9IHRoaXMuYWRkSXRlbXMoIGVsZW1zICk7XG4gIGlmICggIWl0ZW1zLmxlbmd0aCApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gbGF5b3V0IGFuZCByZXZlYWwganVzdCB0aGUgbmV3IGl0ZW1zXG4gIHRoaXMubGF5b3V0SXRlbXMoIGl0ZW1zLCB0cnVlICk7XG4gIHRoaXMucmV2ZWFsKCBpdGVtcyApO1xufTtcblxuLyoqXG4gKiBMYXlvdXQgcHJlcGVuZGVkIGVsZW1lbnRzXG4gKiBAcGFyYW0ge0FycmF5IG9yIE5vZGVMaXN0IG9yIEVsZW1lbnR9IGVsZW1zXG4gKi9cbnByb3RvLnByZXBlbmRlZCA9IGZ1bmN0aW9uKCBlbGVtcyApIHtcbiAgdmFyIGl0ZW1zID0gdGhpcy5faXRlbWl6ZSggZWxlbXMgKTtcbiAgaWYgKCAhaXRlbXMubGVuZ3RoICkge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBhZGQgaXRlbXMgdG8gYmVnaW5uaW5nIG9mIGNvbGxlY3Rpb25cbiAgdmFyIHByZXZpb3VzSXRlbXMgPSB0aGlzLml0ZW1zLnNsaWNlKDApO1xuICB0aGlzLml0ZW1zID0gaXRlbXMuY29uY2F0KCBwcmV2aW91c0l0ZW1zICk7XG4gIC8vIHN0YXJ0IG5ldyBsYXlvdXRcbiAgdGhpcy5fcmVzZXRMYXlvdXQoKTtcbiAgdGhpcy5fbWFuYWdlU3RhbXBzKCk7XG4gIC8vIGxheW91dCBuZXcgc3R1ZmYgd2l0aG91dCB0cmFuc2l0aW9uXG4gIHRoaXMubGF5b3V0SXRlbXMoIGl0ZW1zLCB0cnVlICk7XG4gIHRoaXMucmV2ZWFsKCBpdGVtcyApO1xuICAvLyBsYXlvdXQgcHJldmlvdXMgaXRlbXNcbiAgdGhpcy5sYXlvdXRJdGVtcyggcHJldmlvdXNJdGVtcyApO1xufTtcblxuLyoqXG4gKiByZXZlYWwgYSBjb2xsZWN0aW9uIG9mIGl0ZW1zXG4gKiBAcGFyYW0ge0FycmF5IG9mIE91dGxheWVyLkl0ZW1zfSBpdGVtc1xuICovXG5wcm90by5yZXZlYWwgPSBmdW5jdGlvbiggaXRlbXMgKSB7XG4gIHRoaXMuX2VtaXRDb21wbGV0ZU9uSXRlbXMoICdyZXZlYWwnLCBpdGVtcyApO1xuICBpZiAoICFpdGVtcyB8fCAhaXRlbXMubGVuZ3RoICkge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgc3RhZ2dlciA9IHRoaXMudXBkYXRlU3RhZ2dlcigpO1xuICBpdGVtcy5mb3JFYWNoKCBmdW5jdGlvbiggaXRlbSwgaSApIHtcbiAgICBpdGVtLnN0YWdnZXIoIGkgKiBzdGFnZ2VyICk7XG4gICAgaXRlbS5yZXZlYWwoKTtcbiAgfSk7XG59O1xuXG4vKipcbiAqIGhpZGUgYSBjb2xsZWN0aW9uIG9mIGl0ZW1zXG4gKiBAcGFyYW0ge0FycmF5IG9mIE91dGxheWVyLkl0ZW1zfSBpdGVtc1xuICovXG5wcm90by5oaWRlID0gZnVuY3Rpb24oIGl0ZW1zICkge1xuICB0aGlzLl9lbWl0Q29tcGxldGVPbkl0ZW1zKCAnaGlkZScsIGl0ZW1zICk7XG4gIGlmICggIWl0ZW1zIHx8ICFpdGVtcy5sZW5ndGggKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBzdGFnZ2VyID0gdGhpcy51cGRhdGVTdGFnZ2VyKCk7XG4gIGl0ZW1zLmZvckVhY2goIGZ1bmN0aW9uKCBpdGVtLCBpICkge1xuICAgIGl0ZW0uc3RhZ2dlciggaSAqIHN0YWdnZXIgKTtcbiAgICBpdGVtLmhpZGUoKTtcbiAgfSk7XG59O1xuXG4vKipcbiAqIHJldmVhbCBpdGVtIGVsZW1lbnRzXG4gKiBAcGFyYW0ge0FycmF5fSwge0VsZW1lbnR9LCB7Tm9kZUxpc3R9IGl0ZW1zXG4gKi9cbnByb3RvLnJldmVhbEl0ZW1FbGVtZW50cyA9IGZ1bmN0aW9uKCBlbGVtcyApIHtcbiAgdmFyIGl0ZW1zID0gdGhpcy5nZXRJdGVtcyggZWxlbXMgKTtcbiAgdGhpcy5yZXZlYWwoIGl0ZW1zICk7XG59O1xuXG4vKipcbiAqIGhpZGUgaXRlbSBlbGVtZW50c1xuICogQHBhcmFtIHtBcnJheX0sIHtFbGVtZW50fSwge05vZGVMaXN0fSBpdGVtc1xuICovXG5wcm90by5oaWRlSXRlbUVsZW1lbnRzID0gZnVuY3Rpb24oIGVsZW1zICkge1xuICB2YXIgaXRlbXMgPSB0aGlzLmdldEl0ZW1zKCBlbGVtcyApO1xuICB0aGlzLmhpZGUoIGl0ZW1zICk7XG59O1xuXG4vKipcbiAqIGdldCBPdXRsYXllci5JdGVtLCBnaXZlbiBhbiBFbGVtZW50XG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gKiBAcmV0dXJucyB7T3V0bGF5ZXIuSXRlbX0gaXRlbVxuICovXG5wcm90by5nZXRJdGVtID0gZnVuY3Rpb24oIGVsZW0gKSB7XG4gIC8vIGxvb3AgdGhyb3VnaCBpdGVtcyB0byBnZXQgdGhlIG9uZSB0aGF0IG1hdGNoZXNcbiAgZm9yICggdmFyIGk9MDsgaSA8IHRoaXMuaXRlbXMubGVuZ3RoOyBpKysgKSB7XG4gICAgdmFyIGl0ZW0gPSB0aGlzLml0ZW1zW2ldO1xuICAgIGlmICggaXRlbS5lbGVtZW50ID09IGVsZW0gKSB7XG4gICAgICAvLyByZXR1cm4gaXRlbVxuICAgICAgcmV0dXJuIGl0ZW07XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIGdldCBjb2xsZWN0aW9uIG9mIE91dGxheWVyLkl0ZW1zLCBnaXZlbiBFbGVtZW50c1xuICogQHBhcmFtIHtBcnJheX0gZWxlbXNcbiAqIEByZXR1cm5zIHtBcnJheX0gaXRlbXMgLSBPdXRsYXllci5JdGVtc1xuICovXG5wcm90by5nZXRJdGVtcyA9IGZ1bmN0aW9uKCBlbGVtcyApIHtcbiAgZWxlbXMgPSB1dGlscy5tYWtlQXJyYXkoIGVsZW1zICk7XG4gIHZhciBpdGVtcyA9IFtdO1xuICBlbGVtcy5mb3JFYWNoKCBmdW5jdGlvbiggZWxlbSApIHtcbiAgICB2YXIgaXRlbSA9IHRoaXMuZ2V0SXRlbSggZWxlbSApO1xuICAgIGlmICggaXRlbSApIHtcbiAgICAgIGl0ZW1zLnB1c2goIGl0ZW0gKTtcbiAgICB9XG4gIH0sIHRoaXMgKTtcblxuICByZXR1cm4gaXRlbXM7XG59O1xuXG4vKipcbiAqIHJlbW92ZSBlbGVtZW50KHMpIGZyb20gaW5zdGFuY2UgYW5kIERPTVxuICogQHBhcmFtIHtBcnJheSBvciBOb2RlTGlzdCBvciBFbGVtZW50fSBlbGVtc1xuICovXG5wcm90by5yZW1vdmUgPSBmdW5jdGlvbiggZWxlbXMgKSB7XG4gIHZhciByZW1vdmVJdGVtcyA9IHRoaXMuZ2V0SXRlbXMoIGVsZW1zICk7XG5cbiAgdGhpcy5fZW1pdENvbXBsZXRlT25JdGVtcyggJ3JlbW92ZScsIHJlbW92ZUl0ZW1zICk7XG5cbiAgLy8gYmFpbCBpZiBubyBpdGVtcyB0byByZW1vdmVcbiAgaWYgKCAhcmVtb3ZlSXRlbXMgfHwgIXJlbW92ZUl0ZW1zLmxlbmd0aCApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICByZW1vdmVJdGVtcy5mb3JFYWNoKCBmdW5jdGlvbiggaXRlbSApIHtcbiAgICBpdGVtLnJlbW92ZSgpO1xuICAgIC8vIHJlbW92ZSBpdGVtIGZyb20gY29sbGVjdGlvblxuICAgIHV0aWxzLnJlbW92ZUZyb20oIHRoaXMuaXRlbXMsIGl0ZW0gKTtcbiAgfSwgdGhpcyApO1xufTtcblxuLy8gLS0tLS0gZGVzdHJveSAtLS0tLSAvL1xuXG4vLyByZW1vdmUgYW5kIGRpc2FibGUgT3V0bGF5ZXIgaW5zdGFuY2VcbnByb3RvLmRlc3Ryb3kgPSBmdW5jdGlvbigpIHtcbiAgLy8gY2xlYW4gdXAgZHluYW1pYyBzdHlsZXNcbiAgdmFyIHN0eWxlID0gdGhpcy5lbGVtZW50LnN0eWxlO1xuICBzdHlsZS5oZWlnaHQgPSAnJztcbiAgc3R5bGUucG9zaXRpb24gPSAnJztcbiAgc3R5bGUud2lkdGggPSAnJztcbiAgLy8gZGVzdHJveSBpdGVtc1xuICB0aGlzLml0ZW1zLmZvckVhY2goIGZ1bmN0aW9uKCBpdGVtICkge1xuICAgIGl0ZW0uZGVzdHJveSgpO1xuICB9KTtcblxuICB0aGlzLnVuYmluZFJlc2l6ZSgpO1xuXG4gIHZhciBpZCA9IHRoaXMuZWxlbWVudC5vdXRsYXllckdVSUQ7XG4gIGRlbGV0ZSBpbnN0YW5jZXNbIGlkIF07IC8vIHJlbW92ZSByZWZlcmVuY2UgdG8gaW5zdGFuY2UgYnkgaWRcbiAgZGVsZXRlIHRoaXMuZWxlbWVudC5vdXRsYXllckdVSUQ7XG4gIC8vIHJlbW92ZSBkYXRhIGZvciBqUXVlcnlcbiAgaWYgKCBqUXVlcnkgKSB7XG4gICAgalF1ZXJ5LnJlbW92ZURhdGEoIHRoaXMuZWxlbWVudCwgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lc3BhY2UgKTtcbiAgfVxuXG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBkYXRhIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbi8qKlxuICogZ2V0IE91dGxheWVyIGluc3RhbmNlIGZyb20gZWxlbWVudFxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtXG4gKiBAcmV0dXJucyB7T3V0bGF5ZXJ9XG4gKi9cbk91dGxheWVyLmRhdGEgPSBmdW5jdGlvbiggZWxlbSApIHtcbiAgZWxlbSA9IHV0aWxzLmdldFF1ZXJ5RWxlbWVudCggZWxlbSApO1xuICB2YXIgaWQgPSBlbGVtICYmIGVsZW0ub3V0bGF5ZXJHVUlEO1xuICByZXR1cm4gaWQgJiYgaW5zdGFuY2VzWyBpZCBdO1xufTtcblxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBjcmVhdGUgT3V0bGF5ZXIgY2xhc3MgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuLyoqXG4gKiBjcmVhdGUgYSBsYXlvdXQgY2xhc3NcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lc3BhY2VcbiAqL1xuT3V0bGF5ZXIuY3JlYXRlID0gZnVuY3Rpb24oIG5hbWVzcGFjZSwgb3B0aW9ucyApIHtcbiAgLy8gc3ViLWNsYXNzIE91dGxheWVyXG4gIHZhciBMYXlvdXQgPSBzdWJjbGFzcyggT3V0bGF5ZXIgKTtcbiAgLy8gYXBwbHkgbmV3IG9wdGlvbnMgYW5kIGNvbXBhdE9wdGlvbnNcbiAgTGF5b3V0LmRlZmF1bHRzID0gdXRpbHMuZXh0ZW5kKCB7fSwgT3V0bGF5ZXIuZGVmYXVsdHMgKTtcbiAgdXRpbHMuZXh0ZW5kKCBMYXlvdXQuZGVmYXVsdHMsIG9wdGlvbnMgKTtcbiAgTGF5b3V0LmNvbXBhdE9wdGlvbnMgPSB1dGlscy5leHRlbmQoIHt9LCBPdXRsYXllci5jb21wYXRPcHRpb25zICApO1xuXG4gIExheW91dC5uYW1lc3BhY2UgPSBuYW1lc3BhY2U7XG5cbiAgTGF5b3V0LmRhdGEgPSBPdXRsYXllci5kYXRhO1xuXG4gIC8vIHN1Yi1jbGFzcyBJdGVtXG4gIExheW91dC5JdGVtID0gc3ViY2xhc3MoIEl0ZW0gKTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBkZWNsYXJhdGl2ZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gIHV0aWxzLmh0bWxJbml0KCBMYXlvdXQsIG5hbWVzcGFjZSApO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGpRdWVyeSBicmlkZ2UgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAvLyBtYWtlIGludG8galF1ZXJ5IHBsdWdpblxuICBpZiAoIGpRdWVyeSAmJiBqUXVlcnkuYnJpZGdldCApIHtcbiAgICBqUXVlcnkuYnJpZGdldCggbmFtZXNwYWNlLCBMYXlvdXQgKTtcbiAgfVxuXG4gIHJldHVybiBMYXlvdXQ7XG59O1xuXG5mdW5jdGlvbiBzdWJjbGFzcyggUGFyZW50ICkge1xuICBmdW5jdGlvbiBTdWJDbGFzcygpIHtcbiAgICBQYXJlbnQuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuICB9XG5cbiAgU3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSggUGFyZW50LnByb3RvdHlwZSApO1xuICBTdWJDbGFzcy5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBTdWJDbGFzcztcblxuICByZXR1cm4gU3ViQ2xhc3M7XG59XG5cbi8vIC0tLS0tIGhlbHBlcnMgLS0tLS0gLy9cblxuLy8gaG93IG1hbnkgbWlsbGlzZWNvbmRzIGFyZSBpbiBlYWNoIHVuaXRcbnZhciBtc1VuaXRzID0ge1xuICBtczogMSxcbiAgczogMTAwMFxufTtcblxuLy8gbXVuZ2UgdGltZS1saWtlIHBhcmFtZXRlciBpbnRvIG1pbGxpc2Vjb25kIG51bWJlclxuLy8gJzAuNHMnIC0+IDQwXG5mdW5jdGlvbiBnZXRNaWxsaXNlY29uZHMoIHRpbWUgKSB7XG4gIGlmICggdHlwZW9mIHRpbWUgPT0gJ251bWJlcicgKSB7XG4gICAgcmV0dXJuIHRpbWU7XG4gIH1cbiAgdmFyIG1hdGNoZXMgPSB0aW1lLm1hdGNoKCAvKF5cXGQqXFwuP1xcZCopKFxcdyopLyApO1xuICB2YXIgbnVtID0gbWF0Y2hlcyAmJiBtYXRjaGVzWzFdO1xuICB2YXIgdW5pdCA9IG1hdGNoZXMgJiYgbWF0Y2hlc1syXTtcbiAgaWYgKCAhbnVtLmxlbmd0aCApIHtcbiAgICByZXR1cm4gMDtcbiAgfVxuICBudW0gPSBwYXJzZUZsb2F0KCBudW0gKTtcbiAgdmFyIG11bHQgPSBtc1VuaXRzWyB1bml0IF0gfHwgMTtcbiAgcmV0dXJuIG51bSAqIG11bHQ7XG59XG5cbi8vIC0tLS0tIGZpbiAtLS0tLSAvL1xuXG4vLyBiYWNrIGluIGdsb2JhbFxuT3V0bGF5ZXIuSXRlbSA9IEl0ZW07XG5cbnJldHVybiBPdXRsYXllcjtcblxufSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L291dGxheWVyL291dGxheWVyLmpzXG4vLyBtb2R1bGUgaWQgPSAyN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJpbXBvcnQgeyBJdGVtVmFsdWUsIFF1ZXN0aW9uTWF0cml4TW9kZWwsIFF1ZXN0aW9uIH0gZnJvbSBcInN1cnZleS1jb3JlXCI7XG5cbmltcG9ydCB7IFZpc3VhbGl6YXRpb25NYW5hZ2VyIH0gZnJvbSBcIi4uL3Zpc3VhbGl6YXRpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBTZWxlY3RCYXNlQzMgfSBmcm9tIFwiLi9zZWxlY3RCYXNlXCI7XG5cbmV4cG9ydCBjbGFzcyBNYXRyaXjQoTMgZXh0ZW5kcyBTZWxlY3RCYXNlQzMge1xuICBjb25zdHJ1Y3RvcihcbiAgICB0YXJnZXROb2RlOiBIVE1MRWxlbWVudCxcbiAgICBxdWVzdGlvbjogUXVlc3Rpb24sXG4gICAgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgICBvcHRpb25zPzogT2JqZWN0XG4gICkge1xuICAgIHN1cGVyKHRhcmdldE5vZGUsIHF1ZXN0aW9uLCBkYXRhLCBvcHRpb25zKTtcbiAgICB0aGlzLmNoYXJ0VHlwZSA9IFwiYmFyXCI7XG4gIH1cblxuICB2YWx1ZXNTb3VyY2UoKTogYW55W10ge1xuICAgIGNvbnN0IHF1ZXN0aW9uOiBRdWVzdGlvbk1hdHJpeE1vZGVsID0gPGFueT50aGlzLnF1ZXN0aW9uO1xuICAgIHJldHVybiBxdWVzdGlvbi5jb2x1bW5zO1xuICB9XG5cbiAgZ2V0TGFiZWxzKCk6IGFueVtdIHtcbiAgICBjb25zdCBxdWVzdGlvbjogUXVlc3Rpb25NYXRyaXhNb2RlbCA9IDxhbnk+dGhpcy5xdWVzdGlvbjtcbiAgICByZXR1cm4gcXVlc3Rpb24ucm93cy5tYXAocm93ID0+XG4gICAgICBJdGVtVmFsdWUuZ2V0VGV4dE9ySHRtbEJ5VmFsdWUocXVlc3Rpb24ucm93cywgcm93LnZhbHVlKVxuICAgICk7XG4gIH1cblxuICBnZXREYXRhKCk6IGFueVtdIHtcbiAgICBjb25zdCBxdWVzdGlvbjogUXVlc3Rpb25NYXRyaXhNb2RlbCA9IDxhbnk+dGhpcy5xdWVzdGlvbjtcbiAgICBjb25zdCBkYXRhc2V0czogQXJyYXk8YW55PiA9IHRoaXMudmFsdWVzU291cmNlKCkubWFwKGNob2ljZSA9PiB7XG4gICAgICByZXR1cm4gcXVlc3Rpb24ucm93cy5tYXAodiA9PiAwKTtcbiAgICB9KTtcblxuICAgIHRoaXMuZGF0YS5mb3JFYWNoKHJvd0RhdGEgPT4ge1xuICAgICAgY29uc3QgcXVlc3Rpb25WYWx1ZTogYW55ID0gcm93RGF0YVt0aGlzLnF1ZXN0aW9uLm5hbWVdO1xuICAgICAgaWYgKCEhcXVlc3Rpb25WYWx1ZSkge1xuICAgICAgICBxdWVzdGlvbi5yb3dzLmZvckVhY2goKHJvdzogYW55LCBpbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgdGhpcy5nZXRWYWx1ZXMoKS5mb3JFYWNoKCh2YWw6IGFueSwgZHNJbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBpZiAocXVlc3Rpb25WYWx1ZVtyb3cudmFsdWVdID09IHZhbCkge1xuICAgICAgICAgICAgICBkYXRhc2V0c1tkc0luZGV4XVtpbmRleF0rKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGRhdGFzZXRzO1xuICB9XG59XG5cbi8vIFZpc3VhbGl6YXRpb25NYW5hZ2VyLnJlZ2lzdGVyVmlzdWFsaXplcihcIm1hdHJpeFwiLCBNYXRyaXjQoTMpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2MzL21hdHJpeC50cyIsImltcG9ydCB7IFF1ZXN0aW9uIH0gZnJvbSBcInN1cnZleS1jb3JlXCI7XG5pbXBvcnQgeyBWaXN1YWxpemVyQmFzZSB9IGZyb20gXCIuLi92aXN1YWxpemVyQmFzZVwiO1xuaW1wb3J0IHsgVmlzdWFsaXphdGlvbk1hbmFnZXIgfSBmcm9tIFwiLi4vdmlzdWFsaXphdGlvbk1hbmFnZXJcIjtcblxuaW1wb3J0IGMzIGZyb20gXCJjM1wiO1xuXG5leHBvcnQgY2xhc3MgR2F1Z2VDMyBleHRlbmRzIFZpc3VhbGl6ZXJCYXNlIHtcbiAgcHJpdmF0ZSBfcmVzdWx0OiBhbnk7XG4gIHByaXZhdGUgY2hhcnQ6IGMzLkNoYXJ0QVBJO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCB0YXJnZXROb2RlOiBIVE1MRWxlbWVudCxcbiAgICBxdWVzdGlvbjogUXVlc3Rpb24sXG4gICAgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgICBvcHRpb25zPzogT2JqZWN0XG4gICkge1xuICAgIHN1cGVyKHRhcmdldE5vZGUsIHF1ZXN0aW9uLCBkYXRhLCBvcHRpb25zKTtcbiAgfVxuXG4gIGRlc3Ryb3koKSB7XG4gICAgaWYgKCF0aGlzLmNoYXJ0KSByZXR1cm47XG4gICAgdGhpcy5jaGFydC5kZXN0cm95KCk7XG4gIH1cblxuICByZW5kZXIoKSB7XG4gICAgdGhpcy5jaGFydCA9IGMzLmdlbmVyYXRlKHtcbiAgICAgIGJpbmR0bzogdGhpcy50YXJnZXROb2RlLFxuICAgICAgZGF0YToge1xuICAgICAgICBjb2x1bW5zOiBbW3RoaXMucXVlc3Rpb24udGl0bGUsIHRoaXMucmVzdWx0XV0sXG4gICAgICAgIHR5cGU6IFwiZ2F1Z2VcIlxuICAgICAgfSxcbiAgICAgIGdhdWdlOiB7XG4gICAgICAgIG1pbjogdGhpcy5xdWVzdGlvbi5yYXRlTWluLFxuICAgICAgICBtYXg6IHRoaXMucXVlc3Rpb24ucmF0ZU1heCxcbiAgICAgICAgbGFiZWw6IHtcbiAgICAgICAgICBmb3JtYXQ6IGZ1bmN0aW9uKHZhbHVlLCByYXRpbykge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGNvbG9yOiB7XG4gICAgICAgIHBhdHRlcm46IFt0aGlzLmdldFJhbmRvbUNvbG9yKCldXG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBnZXQgcmVzdWx0KCkge1xuICAgIGlmICh0aGlzLl9yZXN1bHQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgcXVlc3Rpb25WYWx1ZXM6IEFycmF5PGFueT4gPSBbXTtcblxuICAgICAgdGhpcy5kYXRhLmZvckVhY2gocm93RGF0YSA9PiB7XG4gICAgICAgIGNvbnN0IHF1ZXN0aW9uVmFsdWU6IGFueSA9IHJvd0RhdGFbdGhpcy5xdWVzdGlvbi5uYW1lXTtcbiAgICAgICAgaWYgKCEhcXVlc3Rpb25WYWx1ZSkge1xuICAgICAgICAgIHF1ZXN0aW9uVmFsdWVzLnB1c2gocXVlc3Rpb25WYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9yZXN1bHQgPVxuICAgICAgICBxdWVzdGlvblZhbHVlcy5yZWR1Y2UoKGEsIGIpID0+IHtcbiAgICAgICAgICByZXR1cm4gYSArIGI7XG4gICAgICAgIH0pIC8gcXVlc3Rpb25WYWx1ZXMubGVuZ3RoO1xuICAgICAgdGhpcy5fcmVzdWx0ID0gTWF0aC5jZWlsKHRoaXMuX3Jlc3VsdCAqIDEwMCkgLyAxMDA7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9yZXN1bHQ7XG4gIH1cbn1cblxuLy8gVmlzdWFsaXphdGlvbk1hbmFnZXIucmVnaXN0ZXJWaXN1YWxpemVyKFwicmF0aW5nXCIsIEdhdWdlQzMpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2MzL3JhdGluZy50cyIsImltcG9ydCB7IEl0ZW1WYWx1ZSwgUXVlc3Rpb25NYXRyaXhNb2RlbCwgUXVlc3Rpb24gfSBmcm9tIFwic3VydmV5LWNvcmVcIjtcblxuaW1wb3J0IHsgVmlzdWFsaXphdGlvbk1hbmFnZXIgfSBmcm9tIFwiLi4vdmlzdWFsaXphdGlvbk1hbmFnZXJcIjtcbmltcG9ydCB7IFNlbGVjdEJhc2VDaGFydEpTIH0gZnJvbSBcIi4vc2VsZWN0QmFzZVwiO1xuXG5leHBvcnQgY2xhc3MgTWF0cml4Q2hhcnRKUyBleHRlbmRzIFNlbGVjdEJhc2VDaGFydEpTIHtcbiAgY29uc3RydWN0b3IoXG4gICAgdGFyZ2V0Tm9kZTogSFRNTEVsZW1lbnQsXG4gICAgcXVlc3Rpb246IFF1ZXN0aW9uLFxuICAgIGRhdGE6IEFycmF5PHsgW2luZGV4OiBzdHJpbmddOiBhbnkgfT4sXG4gICAgb3B0aW9ucz86IE9iamVjdFxuICApIHtcbiAgICBzdXBlcih0YXJnZXROb2RlLCBxdWVzdGlvbiwgZGF0YSwgb3B0aW9ucyk7XG4gICAgdGhpcy5jaGFydFR5cGUgPSBcImJhclwiO1xuICB9XG5cbiAgdmFsdWVzU291cmNlKCk6IGFueVtdIHtcbiAgICBjb25zdCBxdWVzdGlvbjogUXVlc3Rpb25NYXRyaXhNb2RlbCA9IDxhbnk+dGhpcy5xdWVzdGlvbjtcbiAgICByZXR1cm4gcXVlc3Rpb24uY29sdW1ucztcbiAgfVxuXG4gIGdldExhYmVscygpOiBhbnlbXSB7XG4gICAgY29uc3QgcXVlc3Rpb246IFF1ZXN0aW9uTWF0cml4TW9kZWwgPSA8YW55PnRoaXMucXVlc3Rpb247XG4gICAgcmV0dXJuIHF1ZXN0aW9uLnJvd3MubWFwKHJvdyA9PlxuICAgICAgSXRlbVZhbHVlLmdldFRleHRPckh0bWxCeVZhbHVlKHF1ZXN0aW9uLnJvd3MsIHJvdy52YWx1ZSlcbiAgICApO1xuICB9XG5cbiAgZ2V0T3B0aW9ucygpIHtcbiAgICBsZXQgb3B0aW9ucyA9IHN1cGVyLmdldE9wdGlvbnMoKTtcbiAgICBvcHRpb25zLnNjYWxlcyA9IHVuZGVmaW5lZDtcbiAgICAvLyBvcHRpb25zLnNjYWxlcyA9IHtcbiAgICAvLyAgIHhBeGVzOiBbeyBzdGFja2VkOiB0cnVlIH1dLFxuICAgIC8vICAgeUF4ZXM6IFt7IHN0YWNrZWQ6IHRydWUgfV1cbiAgICAvLyB9XG4gICAgcmV0dXJuIG9wdGlvbnM7XG4gIH1cblxuICBnZXREYXRhKCk6IGFueVtdIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgZ2V0RGF0YXNldHMoKTogYW55W10ge1xuICAgIGNvbnN0IHF1ZXN0aW9uOiBRdWVzdGlvbk1hdHJpeE1vZGVsID0gPGFueT50aGlzLnF1ZXN0aW9uO1xuICAgIGNvbnN0IGRhdGFzZXRzOiBBcnJheTxhbnk+ID0gdGhpcy52YWx1ZXNTb3VyY2UoKS5tYXAoY2hvaWNlID0+IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGxhYmVsOiBJdGVtVmFsdWUuZ2V0VGV4dE9ySHRtbEJ5VmFsdWUoXG4gICAgICAgICAgdGhpcy52YWx1ZXNTb3VyY2UoKSxcbiAgICAgICAgICBjaG9pY2UudmFsdWVcbiAgICAgICAgKSxcbiAgICAgICAgZGF0YTogcXVlc3Rpb24ucm93cy5tYXAoKCkgPT4gMCksXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogdGhpcy5nZXRSYW5kb21Db2xvcigpXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgdGhpcy5kYXRhLmZvckVhY2gocm93RGF0YSA9PiB7XG4gICAgICBjb25zdCBxdWVzdGlvblZhbHVlOiBhbnkgPSByb3dEYXRhW3RoaXMucXVlc3Rpb24ubmFtZV07XG4gICAgICBpZiAoISFxdWVzdGlvblZhbHVlKSB7XG4gICAgICAgIHF1ZXN0aW9uLnJvd3MuZm9yRWFjaCgocm93OiBhbnksIGluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICB0aGlzLmdldFZhbHVlcygpLmZvckVhY2goKHZhbDogYW55LCBkc0luZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGlmIChxdWVzdGlvblZhbHVlW3Jvdy52YWx1ZV0gPT0gdmFsKSB7XG4gICAgICAgICAgICAgIGRhdGFzZXRzW2RzSW5kZXhdLmRhdGFbaW5kZXhdKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBkYXRhc2V0cztcbiAgfVxufVxuXG4vLyBWaXN1YWxpemF0aW9uTWFuYWdlci5yZWdpc3RlclZpc3VhbGl6ZXIoXCJtYXRyaXhcIiwgTWF0cml4Q2hhcnRKUyk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvY2hhcnRqcy9tYXRyaXgudHMiLCJpbXBvcnQgeyBRdWVzdGlvbiB9IGZyb20gXCJzdXJ2ZXktY29yZVwiO1xuXG5pbXBvcnQgeyBWaXN1YWxpemF0aW9uTWFuYWdlciB9IGZyb20gXCIuLi92aXN1YWxpemF0aW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgU2VsZWN0QmFzZUNoYXJ0SlMgfSBmcm9tIFwiLi9zZWxlY3RCYXNlXCI7XG5cbmV4cG9ydCBjbGFzcyBSYWRpYWxHYXVnZUNoYXJ0SlMgZXh0ZW5kcyBTZWxlY3RCYXNlQ2hhcnRKUyB7XG4gIHByaXZhdGUgX3Jlc3VsdDogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHRhcmdldE5vZGU6IEhUTUxFbGVtZW50LFxuICAgIHF1ZXN0aW9uOiBRdWVzdGlvbixcbiAgICBkYXRhOiBBcnJheTx7IFtpbmRleDogc3RyaW5nXTogYW55IH0+LFxuICAgIG9wdGlvbnM/OiBPYmplY3RcbiAgKSB7XG4gICAgc3VwZXIodGFyZ2V0Tm9kZSwgcXVlc3Rpb24sIGRhdGEsIG9wdGlvbnMpO1xuICAgIHRoaXMuY2hhcnRUeXBlcyA9IFtcImRvdWdobnV0XCIsIFwicGllXCJdO1xuICAgIHRoaXMuY2hhcnRUeXBlID0gXCJkb3VnaG51dFwiO1xuICB9XG5cbiAgZ2V0IHJlc3VsdCgpIHtcbiAgICBpZiAodGhpcy5fcmVzdWx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHF1ZXN0aW9uVmFsdWVzOiBBcnJheTxhbnk+ID0gW107XG5cbiAgICAgIHRoaXMuZGF0YS5mb3JFYWNoKHJvd0RhdGEgPT4ge1xuICAgICAgICBjb25zdCBxdWVzdGlvblZhbHVlOiBhbnkgPSByb3dEYXRhW3RoaXMucXVlc3Rpb24ubmFtZV07XG4gICAgICAgIGlmICghIXF1ZXN0aW9uVmFsdWUpIHtcbiAgICAgICAgICBxdWVzdGlvblZhbHVlcy5wdXNoKHF1ZXN0aW9uVmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5fcmVzdWx0ID1cbiAgICAgICAgcXVlc3Rpb25WYWx1ZXMucmVkdWNlKChhLCBiKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGEgKyBiO1xuICAgICAgICB9KSAvIHF1ZXN0aW9uVmFsdWVzLmxlbmd0aDtcbiAgICAgIHRoaXMuX3Jlc3VsdCA9IE1hdGguY2VpbCh0aGlzLl9yZXN1bHQgKiAxMDApIC8gMTAwO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fcmVzdWx0O1xuICB9XG5cbiAgZ2V0TGFiZWxzKCk6IGFueVtdIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBnZXRPcHRpb25zKCkge1xuICAgIGxldCBvcHRpb25zID0ge1xuICAgICAgcmVzcG9uc2l2ZTogdHJ1ZSxcbiAgICAgIG1haW50YWluQXNwZWN0UmF0aW86IGZhbHNlLFxuICAgICAgcm90YXRpb246IDEgKiBNYXRoLlBJLFxuICAgICAgY2lyY3VtZmVyZW5jZTogMSAqIE1hdGguUElcbiAgICB9O1xuICAgIHJldHVybiBvcHRpb25zO1xuICB9XG5cbiAgZ2V0RGF0YSgpOiBhbnlbXSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGdldFZhbHVlcygpOiBBcnJheTxhbnk+IHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGdldERhdGFzZXRzKCk6IGFueVtdIHtcbiAgICByZXR1cm4gW1xuICAgICAge1xuICAgICAgICBkYXRhOiBbXG4gICAgICAgICAgdGhpcy5yZXN1bHQgLSB0aGlzLnF1ZXN0aW9uLnJhdGVNaW4sXG4gICAgICAgICAgdGhpcy5xdWVzdGlvbi5yYXRlTWF4IC0gdGhpcy5xdWVzdGlvbi5yYXRlTWluIC0gdGhpcy5yZXN1bHRcbiAgICAgICAgXSxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBbdGhpcy5nZXRSYW5kb21Db2xvcigpLCB0aGlzLmdldFJhbmRvbUNvbG9yKCldXG4gICAgICB9XG4gICAgXTtcbiAgfVxufVxuXG4vLyBWaXN1YWxpemF0aW9uTWFuYWdlci5yZWdpc3RlclZpc3VhbGl6ZXIoXCJyYXRpbmdcIiwgUmFkaWFsR2F1Z2VDaGFydEpTKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9jaGFydGpzL3JhdGluZy50cyIsImltcG9ydCB7IEl0ZW1WYWx1ZSwgUXVlc3Rpb25NYXRyaXhNb2RlbCwgUXVlc3Rpb24gfSBmcm9tIFwic3VydmV5LWNvcmVcIjtcbmltcG9ydCB7IFZpc3VhbGl6YXRpb25NYW5hZ2VyIH0gZnJvbSBcIi4uL3Zpc3VhbGl6YXRpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBTZWxlY3RCYXNlUGxvdGx5IH0gZnJvbSBcIi4vc2VsZWN0QmFzZVwiO1xuXG5leHBvcnQgY2xhc3MgTWF0cml4UGxvdGx5IGV4dGVuZHMgU2VsZWN0QmFzZVBsb3RseSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHRhcmdldE5vZGU6IEhUTUxFbGVtZW50LFxuICAgIHF1ZXN0aW9uOiBRdWVzdGlvbixcbiAgICBkYXRhOiBBcnJheTx7IFtpbmRleDogc3RyaW5nXTogYW55IH0+LFxuICAgIG9wdGlvbnM/OiBPYmplY3RcbiAgKSB7XG4gICAgc3VwZXIodGFyZ2V0Tm9kZSwgcXVlc3Rpb24sIGRhdGEsIG9wdGlvbnMpO1xuICB9XG5cbiAgdmFsdWVzU291cmNlKCk6IGFueVtdIHtcbiAgICBjb25zdCBxdWVzdGlvbjogUXVlc3Rpb25NYXRyaXhNb2RlbCA9IDxhbnk+dGhpcy5xdWVzdGlvbjtcbiAgICByZXR1cm4gcXVlc3Rpb24uY29sdW1ucztcbiAgfVxuXG4gIGdldExhYmVscygpOiBhbnlbXSB7XG4gICAgY29uc3QgcXVlc3Rpb246IFF1ZXN0aW9uTWF0cml4TW9kZWwgPSA8YW55PnRoaXMucXVlc3Rpb247XG4gICAgcmV0dXJuIHF1ZXN0aW9uLnJvd3MubWFwKHJvdyA9PlxuICAgICAgSXRlbVZhbHVlLmdldFRleHRPckh0bWxCeVZhbHVlKHF1ZXN0aW9uLnJvd3MsIHJvdy52YWx1ZSlcbiAgICApO1xuICB9XG5cbiAgZ2V0RGF0YSgpOiBhbnlbXSB7XG4gICAgY29uc3QgcXVlc3Rpb246IFF1ZXN0aW9uTWF0cml4TW9kZWwgPSA8YW55PnRoaXMucXVlc3Rpb247XG4gICAgY29uc3QgZGF0YXNldHM6IEFycmF5PGFueT4gPSB0aGlzLnZhbHVlc1NvdXJjZSgpLm1hcChjaG9pY2UgPT4ge1xuICAgICAgcmV0dXJuIHF1ZXN0aW9uLnJvd3MubWFwKHYgPT4gMCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmRhdGEuZm9yRWFjaChyb3dEYXRhID0+IHtcbiAgICAgIGNvbnN0IHF1ZXN0aW9uVmFsdWU6IGFueSA9IHJvd0RhdGFbdGhpcy5xdWVzdGlvbi5uYW1lXTtcbiAgICAgIGlmICghIXF1ZXN0aW9uVmFsdWUpIHtcbiAgICAgICAgcXVlc3Rpb24ucm93cy5mb3JFYWNoKChyb3c6IGFueSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICAgIHRoaXMuZ2V0VmFsdWVzKCkuZm9yRWFjaCgodmFsOiBhbnksIGRzSW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgaWYgKHF1ZXN0aW9uVmFsdWVbcm93LnZhbHVlXSA9PSB2YWwpIHtcbiAgICAgICAgICAgICAgZGF0YXNldHNbZHNJbmRleF1baW5kZXhdKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBkYXRhc2V0cztcbiAgfVxufVxuXG5WaXN1YWxpemF0aW9uTWFuYWdlci5yZWdpc3RlclZpc3VhbGl6ZXIoXCJtYXRyaXhcIiwgTWF0cml4UGxvdGx5KTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9wbG90bHkvbWF0cml4LnRzIiwiaW1wb3J0IHsgUXVlc3Rpb24gfSBmcm9tIFwic3VydmV5LWNvcmVcIjtcbnZhciBQbG90bHkgPSA8YW55PnJlcXVpcmUoXCJwbG90bHkuanMtZGlzdFwiKTtcbmltcG9ydCB7IFZpc3VhbGl6ZXJCYXNlIH0gZnJvbSBcIi4uL3Zpc3VhbGl6ZXJCYXNlXCI7XG5pbXBvcnQgeyBWaXN1YWxpemF0aW9uTWFuYWdlciB9IGZyb20gXCIuLi92aXN1YWxpemF0aW9uTWFuYWdlclwiO1xuXG5leHBvcnQgY2xhc3MgR2F1Z2VQbG90bHkgZXh0ZW5kcyBWaXN1YWxpemVyQmFzZSB7XG4gIHByaXZhdGUgX3Jlc3VsdDogYW55O1xuICBwcml2YXRlIGNoYXJ0OiBQcm9taXNlPFBsb3RseS5QbG90bHlIVE1MRWxlbWVudD47XG5cbiAgcHVibGljIHN0YXRpYyBzdGVwc0NvdW50ID0gNTtcbiAgcHVibGljIHN0YXRpYyBnZW5lcmF0ZVRleHRzQ2FsbGJhY2s6IChcbiAgICBxdWVzdGlvbjogUXVlc3Rpb24sXG4gICAgbWF4VmFsdWU6IG51bWJlcixcbiAgICBtaW5WYWx1ZTogbnVtYmVyLFxuICAgIHN0ZXBzQ291bnQ6IG51bWJlcixcbiAgICB0ZXh0czogc3RyaW5nW11cbiAgKSA9PiBzdHJpbmdbXTtcblxuICBwcm90ZWN0ZWQgY2hhcnRUeXBlcyA9IFtcImdhdWdlXCIsIFwiYnVsbGV0XCJdO1xuICBjaGFydFR5cGUgPSBcImdhdWdlXCI7XG4gIGNoYXJ0Tm9kZSA9IDxIVE1MRWxlbWVudD5kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudCxcbiAgICBxdWVzdGlvbjogUXVlc3Rpb24sXG4gICAgZGF0YTogQXJyYXk8eyBbaW5kZXg6IHN0cmluZ106IGFueSB9PixcbiAgICBvcHRpb25zPzogT2JqZWN0XG4gICkge1xuICAgIHN1cGVyKHRhcmdldEVsZW1lbnQsIHF1ZXN0aW9uLCBkYXRhLCBvcHRpb25zKTtcbiAgfVxuXG4gIHVwZGF0ZShkYXRhOiBBcnJheTx7IFtpbmRleDogc3RyaW5nXTogYW55IH0+KSB7XG4gICAgc3VwZXIudXBkYXRlKGRhdGEpO1xuICAgIHRoaXMuZGVzdHJveSgpO1xuICAgIHRoaXMuY3JlYXRlQ2hhcnQoKTtcbiAgICB0aGlzLmludm9rZU9uVXBkYXRlKCk7XG4gIH1cblxuICBwcml2YXRlIHRvb2xiYXJDaGFuZ2VIYW5kbGVyID0gKGU6IGFueSkgPT4ge1xuICAgIGlmICh0aGlzLmNoYXJ0VHlwZSAhPT0gZS50YXJnZXQudmFsdWUpIHtcbiAgICAgIHRoaXMuY2hhcnRUeXBlID0gZS50YXJnZXQudmFsdWU7XG4gICAgICB0aGlzLnVwZGF0ZSh0aGlzLmRhdGEpO1xuICAgIH1cbiAgfTtcblxuICBwcml2YXRlIGNyZWF0ZVRvb2xiYXIoXG4gICAgY29udGFpbmVyOiBIVE1MRGl2RWxlbWVudCxcbiAgICBjaGFuZ2VIYW5kbGVyOiAoZTogYW55KSA9PiB2b2lkXG4gICkge1xuICAgIGlmICh0aGlzLmNoYXJ0VHlwZXMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgdG9vbGJhciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICB0b29sYmFyLmNsYXNzTmFtZSA9IFwic3ZhLXF1ZXN0aW9uX190b29sYmFyXCI7XG5cbiAgICAgIGNvbnN0IHNlbGVjdFdyYXBwZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgc2VsZWN0V3JhcHBlci5jbGFzc05hbWUgPSBcInN2YS1xdWVzdGlvbl9fc2VsZWN0LXdyYXBwZXJcIjtcbiAgICAgIGNvbnN0IHNlbGVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzZWxlY3RcIik7XG4gICAgICBzZWxlY3QuY2xhc3NOYW1lID0gXCJzdmEtcXVlc3Rpb25fX3NlbGVjdFwiO1xuICAgICAgdGhpcy5jaGFydFR5cGVzLmZvckVhY2goY2hhcnRUeXBlID0+IHtcbiAgICAgICAgbGV0IG9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgIG9wdGlvbi52YWx1ZSA9IGNoYXJ0VHlwZTtcbiAgICAgICAgb3B0aW9uLnRleHQgPSBjaGFydFR5cGU7XG4gICAgICAgIG9wdGlvbi5zZWxlY3RlZCA9IHRoaXMuY2hhcnRUeXBlID09PSBjaGFydFR5cGU7XG4gICAgICAgIHNlbGVjdC5hcHBlbmRDaGlsZChvcHRpb24pO1xuICAgICAgfSk7XG4gICAgICBzZWxlY3Qub25jaGFuZ2UgPSBjaGFuZ2VIYW5kbGVyO1xuICAgICAgc2VsZWN0V3JhcHBlci5hcHBlbmRDaGlsZChzZWxlY3QpO1xuICAgICAgdG9vbGJhci5hcHBlbmRDaGlsZChzZWxlY3RXcmFwcGVyKTtcblxuICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHRvb2xiYXIpO1xuICAgIH1cbiAgfVxuXG4gIGRlc3Ryb3koKSB7XG4gICAgUGxvdGx5LnB1cmdlKHRoaXMuY2hhcnROb2RlKTtcbiAgICB0aGlzLl9yZXN1bHQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBnZW5lcmF0ZVRleHQobWF4VmFsdWU6IG51bWJlciwgbWluVmFsdWU6IG51bWJlciwgc3RlcHNDb3VudDogbnVtYmVyKSB7XG4gICAgbGV0IHRleHRzOiBhbnkgPSBbXTtcblxuICAgIGlmIChzdGVwc0NvdW50ID09PSA1KSB7XG4gICAgICB0ZXh0cyA9IFtcbiAgICAgICAgXCJ2ZXJ5IGhpZ2ggKFwiICsgbWF4VmFsdWUgKyBcIilcIixcbiAgICAgICAgXCJoaWdoXCIsXG4gICAgICAgIFwibWVkaXVtXCIsXG4gICAgICAgIFwibG93XCIsXG4gICAgICAgIFwidmVyeSBsb3cgKFwiICsgbWluVmFsdWUgKyBcIilcIlxuICAgICAgXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGV4dHMucHVzaChtYXhWYWx1ZSk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN0ZXBzQ291bnQgLSAyOyBpKyspIHtcbiAgICAgICAgdGV4dHMucHVzaChcIlwiKTtcbiAgICAgIH1cbiAgICAgIHRleHRzLnB1c2gobWluVmFsdWUpO1xuICAgIH1cblxuICAgIGlmICghIUdhdWdlUGxvdGx5LmdlbmVyYXRlVGV4dHNDYWxsYmFjaykge1xuICAgICAgcmV0dXJuIEdhdWdlUGxvdGx5LmdlbmVyYXRlVGV4dHNDYWxsYmFjayhcbiAgICAgICAgdGhpcy5xdWVzdGlvbixcbiAgICAgICAgbWF4VmFsdWUsXG4gICAgICAgIG1pblZhbHVlLFxuICAgICAgICBzdGVwc0NvdW50LFxuICAgICAgICB0ZXh0c1xuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGV4dHM7XG4gIH1cblxuICBnZW5lcmF0ZVZhbHVlcyhtYXhWYWx1ZTogbnVtYmVyLCBzdGVwc0NvdW50OiBudW1iZXIpIHtcbiAgICBjb25zdCB2YWx1ZXMgPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RlcHNDb3VudDsgaSsrKSB7XG4gICAgICB2YWx1ZXMucHVzaChtYXhWYWx1ZSAvIHN0ZXBzQ291bnQpO1xuICAgIH1cblxuICAgIHZhbHVlcy5wdXNoKG1heFZhbHVlKTtcblxuICAgIHJldHVybiB2YWx1ZXM7XG4gIH1cblxuICBnZW5lcmF0ZUNvbG9ycyhtYXhWYWx1ZTogbnVtYmVyLCBtaW5WYWx1ZTogbnVtYmVyLCBzdGVwc0NvdW50OiBudW1iZXIpIHtcbiAgICBjb25zdCBwYWxldHRlID0gdGhpcy5nZXRDb2xvcnMoKTtcbiAgICBjb25zdCBjb2xvcnMgPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RlcHNDb3VudDsgaSsrKSB7XG4gICAgICBjb2xvcnMucHVzaChwYWxldHRlW2ldKTtcbiAgICB9XG5cbiAgICBjb2xvcnMucHVzaChcInJnYmEoMjU1LCAyNTUsIDI1NSwgMClcIik7XG5cbiAgICByZXR1cm4gY29sb3JzO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVUb29sYmFyQ29udGFpbmVyKCkge1xuICAgIGNvbnN0IGNoYXJ0Tm9kZUNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgY29uc3QgdG9vbGJhck5vZGVDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuXG4gICAgY2hhcnROb2RlQ29udGFpbmVyLmFwcGVuZENoaWxkKHRvb2xiYXJOb2RlQ29udGFpbmVyKTtcbiAgICBjaGFydE5vZGVDb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5jaGFydE5vZGUpO1xuICAgIHRoaXMudGFyZ2V0RWxlbWVudC5hcHBlbmRDaGlsZChjaGFydE5vZGVDb250YWluZXIpO1xuXG4gICAgdGhpcy5jcmVhdGVUb29sYmFyKHRvb2xiYXJOb2RlQ29udGFpbmVyLCB0aGlzLnRvb2xiYXJDaGFuZ2VIYW5kbGVyKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlQ2hhcnQoKSB7XG4gICAgY29uc3QgcXVlc3Rpb24gPSB0aGlzLnF1ZXN0aW9uO1xuICAgIGNvbnN0IGFycm93Q29sb3IgPSBcIiM0ZTYxOThcIjtcblxuICAgIGNvbnN0IG1heFZhbHVlID0gcXVlc3Rpb24ucmF0ZU1heDtcbiAgICBjb25zdCBtaW5WYWx1ZSA9IHF1ZXN0aW9uLnJhdGVNaW47XG4gICAgY29uc3QgdmFsdWVzID0gdGhpcy5nZW5lcmF0ZVZhbHVlcyhtYXhWYWx1ZSwgR2F1Z2VQbG90bHkuc3RlcHNDb3VudCk7XG4gICAgY29uc3QgdGV4dCA9IHRoaXMuZ2VuZXJhdGVUZXh0KG1heFZhbHVlLCBtaW5WYWx1ZSwgR2F1Z2VQbG90bHkuc3RlcHNDb3VudCk7XG4gICAgY29uc3QgY29sb3JzID0gdGhpcy5nZW5lcmF0ZUNvbG9ycyhcbiAgICAgIG1heFZhbHVlLFxuICAgICAgbWluVmFsdWUsXG4gICAgICBHYXVnZVBsb3RseS5zdGVwc0NvdW50XG4gICAgKTtcblxuICAgIC8vIEVudGVyIGEgc3BlZWQgYmV0d2VlbiAwIGFuZCAxODBcbiAgICB2YXIgbGV2ZWwgPSB0aGlzLnJlc3VsdDtcblxuICAgIHZhciBkYXRhOiBhbnkgPSBbXG4gICAgICB7XG4gICAgICAgIHR5cGU6IFwiaW5kaWNhdG9yXCIsXG4gICAgICAgIG1vZGU6IFwiZ2F1Z2UrbnVtYmVyXCIsXG4gICAgICAgIGdhdWdlOiB7XG4gICAgICAgICAgc2hhcGU6IHRoaXMuY2hhcnRUeXBlLFxuICAgICAgICAgIGJnY29sb3I6IFwid2hpdGVcIixcbiAgICAgICAgICBiYXI6IHsgY29sb3I6IGNvbG9yc1swXSB9XG4gICAgICAgIH0sXG4gICAgICAgIHZhbHVlOiBsZXZlbCxcbiAgICAgICAgdGV4dDogcXVlc3Rpb24ubmFtZSxcbiAgICAgICAgZG9tYWluOiB7IHg6IFswLCAxXSwgeTogWzAsIDFdIH1cbiAgICAgIH1cbiAgICBdO1xuXG4gICAgdmFyIGxheW91dCA9IHtcbiAgICAgIHdpZHRoOiA2MDAsXG4gICAgICBoZWlnaHQ6IDQwMCxcbiAgICAgIHBsb3RfYmdjb2xvcjogdGhpcy5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICBwYXBlcl9iZ2NvbG9yOiB0aGlzLmJhY2tncm91bmRDb2xvclxuICAgIH07XG5cbiAgICAvLyB0aGlzLmNoYXJ0Tm9kZS5zdHlsZS5tYXhIZWlnaHQgPSBcIjQwMHB4XCI7IC8vIGZpeGVkIGNoYXJ0IGhlaWdodFxuICAgIC8vIHRoaXMuY2hhcnROb2RlLnN0eWxlLm92ZXJmbG93ID0gXCJoaWRkZW5cIjtcblxuICAgIGNvbnN0IGNvbmZpZyA9IHtcbiAgICAgIGRpc3BsYXlNb2RlQmFyOiBmYWxzZSxcbiAgICAgIHN0YXRpY1Bsb3Q6IHRydWVcbiAgICB9O1xuXG4gICAgdGhpcy5jaGFydCA9IFBsb3RseS5uZXdQbG90KHRoaXMuY2hhcnROb2RlLCBkYXRhLCBsYXlvdXQsIGNvbmZpZyk7XG4gIH1cblxuICByZW5kZXIoKSB7XG4gICAgdGhpcy5jcmVhdGVUb29sYmFyQ29udGFpbmVyKCk7XG4gICAgdGhpcy5jcmVhdGVDaGFydCgpO1xuICB9XG5cbiAgZ2V0IHJlc3VsdCgpIHtcbiAgICBpZiAodGhpcy5fcmVzdWx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHF1ZXN0aW9uVmFsdWVzOiBBcnJheTxhbnk+ID0gW107XG5cbiAgICAgIHRoaXMuZGF0YS5mb3JFYWNoKHJvd0RhdGEgPT4ge1xuICAgICAgICBjb25zdCBxdWVzdGlvblZhbHVlOiBhbnkgPSByb3dEYXRhW3RoaXMucXVlc3Rpb24ubmFtZV07XG4gICAgICAgIGlmICghIXF1ZXN0aW9uVmFsdWUpIHtcbiAgICAgICAgICBxdWVzdGlvblZhbHVlcy5wdXNoKHF1ZXN0aW9uVmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5fcmVzdWx0ID1cbiAgICAgICAgcXVlc3Rpb25WYWx1ZXMucmVkdWNlKChhLCBiKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGEgKyBiO1xuICAgICAgICB9KSAvIHF1ZXN0aW9uVmFsdWVzLmxlbmd0aDtcbiAgICAgIHRoaXMuX3Jlc3VsdCA9IE1hdGguY2VpbCh0aGlzLl9yZXN1bHQgKiAxMDApIC8gMTAwO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fcmVzdWx0O1xuICB9XG59XG5cblZpc3VhbGl6YXRpb25NYW5hZ2VyLnJlZ2lzdGVyVmlzdWFsaXplcihcInJhdGluZ1wiLCBHYXVnZVBsb3RseSk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvcGxvdGx5L3JhdGluZy50cyIsImV4cG9ydCB2YXIgc3RvcFdvcmRzID0gbmV3IEFycmF5KFxuICBcImFcIixcbiAgXCJhYm91dFwiLFxuICBcImFib3ZlXCIsXG4gIFwiYWNyb3NzXCIsXG4gIFwiYWZ0ZXJcIixcbiAgXCJhZ2FpblwiLFxuICBcImFnYWluc3RcIixcbiAgXCJhbGxcIixcbiAgXCJhbG1vc3RcIixcbiAgXCJhbG9uZVwiLFxuICBcImFsb25nXCIsXG4gIFwiYWxyZWFkeVwiLFxuICBcImFsc29cIixcbiAgXCJhbHRob3VnaFwiLFxuICBcImFsd2F5c1wiLFxuICBcImFtb25nXCIsXG4gIFwiYW5cIixcbiAgXCJhbmRcIixcbiAgXCJhbm90aGVyXCIsXG4gIFwiYW55XCIsXG4gIFwiYW55Ym9keVwiLFxuICBcImFueW9uZVwiLFxuICBcImFueXRoaW5nXCIsXG4gIFwiYW55d2hlcmVcIixcbiAgXCJhcmVcIixcbiAgXCJhcmVhXCIsXG4gIFwiYXJlYXNcIixcbiAgXCJhcm91bmRcIixcbiAgXCJhc1wiLFxuICBcImFza1wiLFxuICBcImFza2VkXCIsXG4gIFwiYXNraW5nXCIsXG4gIFwiYXNrc1wiLFxuICBcImF0XCIsXG4gIFwiYXdheVwiLFxuICBcImJcIixcbiAgXCJiYWNrXCIsXG4gIFwiYmFja2VkXCIsXG4gIFwiYmFja2luZ1wiLFxuICBcImJhY2tzXCIsXG4gIFwiYmVcIixcbiAgXCJiZWNhbWVcIixcbiAgXCJiZWNhdXNlXCIsXG4gIFwiYmVjb21lXCIsXG4gIFwiYmVjb21lc1wiLFxuICBcImJlZW5cIixcbiAgXCJiZWZvcmVcIixcbiAgXCJiZWdhblwiLFxuICBcImJlaGluZFwiLFxuICBcImJlaW5nXCIsXG4gIFwiYmVpbmdzXCIsXG4gIFwiYmVzdFwiLFxuICBcImJldHRlclwiLFxuICBcImJldHdlZW5cIixcbiAgXCJiaWdcIixcbiAgXCJib3RoXCIsXG4gIFwiYnV0XCIsXG4gIFwiYnlcIixcbiAgXCJjXCIsXG4gIFwiY2FtZVwiLFxuICBcImNhblwiLFxuICBcImNhbm5vdFwiLFxuICBcImNhc2VcIixcbiAgXCJjYXNlc1wiLFxuICBcImNlcnRhaW5cIixcbiAgXCJjZXJ0YWlubHlcIixcbiAgXCJjbGVhclwiLFxuICBcImNsZWFybHlcIixcbiAgXCJjb21lXCIsXG4gIFwiY291bGRcIixcbiAgXCJkXCIsXG4gIFwiZGlkXCIsXG4gIFwiZGlmZmVyXCIsXG4gIFwiZGlmZmVyZW50XCIsXG4gIFwiZGlmZmVyZW50bHlcIixcbiAgXCJkb1wiLFxuICBcImRvZXNcIixcbiAgXCJkb25lXCIsXG4gIFwiZG93blwiLFxuICBcImRvd25cIixcbiAgXCJkb3duZWRcIixcbiAgXCJkb3duaW5nXCIsXG4gIFwiZG93bnNcIixcbiAgXCJkdXJpbmdcIixcbiAgXCJlXCIsXG4gIFwiZWFjaFwiLFxuICBcImVhcmx5XCIsXG4gIFwiZWl0aGVyXCIsXG4gIFwiZW5kXCIsXG4gIFwiZW5kZWRcIixcbiAgXCJlbmRpbmdcIixcbiAgXCJlbmRzXCIsXG4gIFwiZW5vdWdoXCIsXG4gIFwiZXZlblwiLFxuICBcImV2ZW5seVwiLFxuICBcImV2ZXJcIixcbiAgXCJldmVyeVwiLFxuICBcImV2ZXJ5Ym9keVwiLFxuICBcImV2ZXJ5b25lXCIsXG4gIFwiZXZlcnl0aGluZ1wiLFxuICBcImV2ZXJ5d2hlcmVcIixcbiAgXCJmXCIsXG4gIFwiZmFjZVwiLFxuICBcImZhY2VzXCIsXG4gIFwiZmFjdFwiLFxuICBcImZhY3RzXCIsXG4gIFwiZmFyXCIsXG4gIFwiZmVsdFwiLFxuICBcImZld1wiLFxuICBcImZpbmRcIixcbiAgXCJmaW5kc1wiLFxuICBcImZpcnN0XCIsXG4gIFwiZm9yXCIsXG4gIFwiZm91clwiLFxuICBcImZyb21cIixcbiAgXCJmdWxsXCIsXG4gIFwiZnVsbHlcIixcbiAgXCJmdXJ0aGVyXCIsXG4gIFwiZnVydGhlcmVkXCIsXG4gIFwiZnVydGhlcmluZ1wiLFxuICBcImZ1cnRoZXJzXCIsXG4gIFwiZ1wiLFxuICBcImdhdmVcIixcbiAgXCJnZW5lcmFsXCIsXG4gIFwiZ2VuZXJhbGx5XCIsXG4gIFwiZ2V0XCIsXG4gIFwiZ2V0c1wiLFxuICBcImdpdmVcIixcbiAgXCJnaXZlblwiLFxuICBcImdpdmVzXCIsXG4gIFwiZ29cIixcbiAgXCJnb2luZ1wiLFxuICBcImdvb2RcIixcbiAgXCJnb29kc1wiLFxuICBcImdvdFwiLFxuICBcImdyZWF0XCIsXG4gIFwiZ3JlYXRlclwiLFxuICBcImdyZWF0ZXN0XCIsXG4gIFwiZ3JvdXBcIixcbiAgXCJncm91cGVkXCIsXG4gIFwiZ3JvdXBpbmdcIixcbiAgXCJncm91cHNcIixcbiAgXCJoXCIsXG4gIFwiaGFkXCIsXG4gIFwiaGFzXCIsXG4gIFwiaGF2ZVwiLFxuICBcImhhdmluZ1wiLFxuICBcImhlXCIsXG4gIFwiaGVyXCIsXG4gIFwiaGVyZVwiLFxuICBcImhlcnNlbGZcIixcbiAgXCJoaWdoXCIsXG4gIFwiaGlnaFwiLFxuICBcImhpZ2hcIixcbiAgXCJoaWdoZXJcIixcbiAgXCJoaWdoZXN0XCIsXG4gIFwiaGltXCIsXG4gIFwiaGltc2VsZlwiLFxuICBcImhpc1wiLFxuICBcImhvd1wiLFxuICBcImhvd2V2ZXJcIixcbiAgXCJpXCIsXG4gIFwiaWZcIixcbiAgXCJpbXBvcnRhbnRcIixcbiAgXCJpblwiLFxuICBcImludGVyZXN0XCIsXG4gIFwiaW50ZXJlc3RlZFwiLFxuICBcImludGVyZXN0aW5nXCIsXG4gIFwiaW50ZXJlc3RzXCIsXG4gIFwiaW50b1wiLFxuICBcImlzXCIsXG4gIFwiaXRcIixcbiAgXCJpdHNcIixcbiAgXCJpdHNlbGZcIixcbiAgXCJqXCIsXG4gIFwianVzdFwiLFxuICBcImtcIixcbiAgXCJrZWVwXCIsXG4gIFwia2VlcHNcIixcbiAgXCJraW5kXCIsXG4gIFwia25ld1wiLFxuICBcImtub3dcIixcbiAgXCJrbm93blwiLFxuICBcImtub3dzXCIsXG4gIFwibFwiLFxuICBcImxhcmdlXCIsXG4gIFwibGFyZ2VseVwiLFxuICBcImxhc3RcIixcbiAgXCJsYXRlclwiLFxuICBcImxhdGVzdFwiLFxuICBcImxlYXN0XCIsXG4gIFwibGVzc1wiLFxuICBcImxldFwiLFxuICBcImxldHNcIixcbiAgXCJsaWtlXCIsXG4gIFwibGlrZWx5XCIsXG4gIFwibG9uZ1wiLFxuICBcImxvbmdlclwiLFxuICBcImxvbmdlc3RcIixcbiAgXCJtXCIsXG4gIFwibWFkZVwiLFxuICBcIm1ha2VcIixcbiAgXCJtYWtpbmdcIixcbiAgXCJtYW5cIixcbiAgXCJtYW55XCIsXG4gIFwibWF5XCIsXG4gIFwibWVcIixcbiAgXCJtZW1iZXJcIixcbiAgXCJtZW1iZXJzXCIsXG4gIFwibWVuXCIsXG4gIFwibWlnaHRcIixcbiAgXCJtb3JlXCIsXG4gIFwibW9zdFwiLFxuICBcIm1vc3RseVwiLFxuICBcIm1yXCIsXG4gIFwibXJzXCIsXG4gIFwibXVjaFwiLFxuICBcIm11c3RcIixcbiAgXCJteVwiLFxuICBcIm15c2VsZlwiLFxuICBcIm5cIixcbiAgXCJuZWNlc3NhcnlcIixcbiAgXCJuZWVkXCIsXG4gIFwibmVlZGVkXCIsXG4gIFwibmVlZGluZ1wiLFxuICBcIm5lZWRzXCIsXG4gIFwibmV2ZXJcIixcbiAgXCJuZXdcIixcbiAgXCJuZXdcIixcbiAgXCJuZXdlclwiLFxuICBcIm5ld2VzdFwiLFxuICBcIm5leHRcIixcbiAgXCJub1wiLFxuICBcIm5vYm9keVwiLFxuICBcIm5vblwiLFxuICBcIm5vb25lXCIsXG4gIFwibm90XCIsXG4gIFwibm90aGluZ1wiLFxuICBcIm5vd1wiLFxuICBcIm5vd2hlcmVcIixcbiAgXCJudW1iZXJcIixcbiAgXCJudW1iZXJzXCIsXG4gIFwib1wiLFxuICBcIm9mXCIsXG4gIFwib2ZmXCIsXG4gIFwib2Z0ZW5cIixcbiAgXCJvbGRcIixcbiAgXCJvbGRlclwiLFxuICBcIm9sZGVzdFwiLFxuICBcIm9uXCIsXG4gIFwib25jZVwiLFxuICBcIm9uZVwiLFxuICBcIm9ubHlcIixcbiAgXCJvcGVuXCIsXG4gIFwib3BlbmVkXCIsXG4gIFwib3BlbmluZ1wiLFxuICBcIm9wZW5zXCIsXG4gIFwib3JcIixcbiAgXCJvcmRlclwiLFxuICBcIm9yZGVyZWRcIixcbiAgXCJvcmRlcmluZ1wiLFxuICBcIm9yZGVyc1wiLFxuICBcIm90aGVyXCIsXG4gIFwib3RoZXJzXCIsXG4gIFwib3VyXCIsXG4gIFwib3V0XCIsXG4gIFwib3ZlclwiLFxuICBcInBcIixcbiAgXCJwYXJ0XCIsXG4gIFwicGFydGVkXCIsXG4gIFwicGFydGluZ1wiLFxuICBcInBhcnRzXCIsXG4gIFwicGVyXCIsXG4gIFwicGVyaGFwc1wiLFxuICBcInBsYWNlXCIsXG4gIFwicGxhY2VzXCIsXG4gIFwicG9pbnRcIixcbiAgXCJwb2ludGVkXCIsXG4gIFwicG9pbnRpbmdcIixcbiAgXCJwb2ludHNcIixcbiAgXCJwb3NzaWJsZVwiLFxuICBcInByZXNlbnRcIixcbiAgXCJwcmVzZW50ZWRcIixcbiAgXCJwcmVzZW50aW5nXCIsXG4gIFwicHJlc2VudHNcIixcbiAgXCJwcm9ibGVtXCIsXG4gIFwicHJvYmxlbXNcIixcbiAgXCJwdXRcIixcbiAgXCJwdXRzXCIsXG4gIFwicVwiLFxuICBcInF1aXRlXCIsXG4gIFwiclwiLFxuICBcInJhdGhlclwiLFxuICBcInJlYWxseVwiLFxuICBcInJpZ2h0XCIsXG4gIFwicmlnaHRcIixcbiAgXCJyb29tXCIsXG4gIFwicm9vbXNcIixcbiAgXCJzXCIsXG4gIFwic2FpZFwiLFxuICBcInNhbWVcIixcbiAgXCJzYXdcIixcbiAgXCJzYXlcIixcbiAgXCJzYXlzXCIsXG4gIFwic2Vjb25kXCIsXG4gIFwic2Vjb25kc1wiLFxuICBcInNlZVwiLFxuICBcInNlZW1cIixcbiAgXCJzZWVtZWRcIixcbiAgXCJzZWVtaW5nXCIsXG4gIFwic2VlbXNcIixcbiAgXCJzZWVzXCIsXG4gIFwic2V2ZXJhbFwiLFxuICBcInNoYWxsXCIsXG4gIFwic2hlXCIsXG4gIFwic2hvdWxkXCIsXG4gIFwic2hvd1wiLFxuICBcInNob3dlZFwiLFxuICBcInNob3dpbmdcIixcbiAgXCJzaG93c1wiLFxuICBcInNpZGVcIixcbiAgXCJzaWRlc1wiLFxuICBcInNpbmNlXCIsXG4gIFwic21hbGxcIixcbiAgXCJzbWFsbGVyXCIsXG4gIFwic21hbGxlc3RcIixcbiAgXCJzb1wiLFxuICBcInNvbWVcIixcbiAgXCJzb21lYm9keVwiLFxuICBcInNvbWVvbmVcIixcbiAgXCJzb21ldGhpbmdcIixcbiAgXCJzb21ld2hlcmVcIixcbiAgXCJzdGF0ZVwiLFxuICBcInN0YXRlc1wiLFxuICBcInN0aWxsXCIsXG4gIFwic3RpbGxcIixcbiAgXCJzdWNoXCIsXG4gIFwic3VyZVwiLFxuICBcInRcIixcbiAgXCJ0YWtlXCIsXG4gIFwidGFrZW5cIixcbiAgXCJ0aGFuXCIsXG4gIFwidGhhdFwiLFxuICBcInRoZVwiLFxuICBcInRoZWlyXCIsXG4gIFwidGhlbVwiLFxuICBcInRoZW5cIixcbiAgXCJ0aGVyZVwiLFxuICBcInRoZXJlZm9yZVwiLFxuICBcInRoZXNlXCIsXG4gIFwidGhleVwiLFxuICBcInRoaW5nXCIsXG4gIFwidGhpbmdzXCIsXG4gIFwidGhpbmtcIixcbiAgXCJ0aGlua3NcIixcbiAgXCJ0aGlzXCIsXG4gIFwidGhvc2VcIixcbiAgXCJ0aG91Z2hcIixcbiAgXCJ0aG91Z2h0XCIsXG4gIFwidGhvdWdodHNcIixcbiAgXCJ0aHJlZVwiLFxuICBcInRocm91Z2hcIixcbiAgXCJ0aHVzXCIsXG4gIFwidG9cIixcbiAgXCJ0b2RheVwiLFxuICBcInRvZ2V0aGVyXCIsXG4gIFwidG9vXCIsXG4gIFwidG9va1wiLFxuICBcInRvd2FyZFwiLFxuICBcInR1cm5cIixcbiAgXCJ0dXJuZWRcIixcbiAgXCJ0dXJuaW5nXCIsXG4gIFwidHVybnNcIixcbiAgXCJ0d29cIixcbiAgXCJ1XCIsXG4gIFwidW5kZXJcIixcbiAgXCJ1bnRpbFwiLFxuICBcInVwXCIsXG4gIFwidXBvblwiLFxuICBcInVzXCIsXG4gIFwidXNlXCIsXG4gIFwidXNlZFwiLFxuICBcInVzZXNcIixcbiAgXCJ2XCIsXG4gIFwidmVyeVwiLFxuICBcIndcIixcbiAgXCJ3YW50XCIsXG4gIFwid2FudGVkXCIsXG4gIFwid2FudGluZ1wiLFxuICBcIndhbnRzXCIsXG4gIFwid2FzXCIsXG4gIFwid2F5XCIsXG4gIFwid2F5c1wiLFxuICBcIndlXCIsXG4gIFwid2VsbFwiLFxuICBcIndlbGxzXCIsXG4gIFwid2VudFwiLFxuICBcIndlcmVcIixcbiAgXCJ3aGF0XCIsXG4gIFwid2hlblwiLFxuICBcIndoZXJlXCIsXG4gIFwid2hldGhlclwiLFxuICBcIndoaWNoXCIsXG4gIFwid2hpbGVcIixcbiAgXCJ3aG9cIixcbiAgXCJ3aG9sZVwiLFxuICBcIndob3NlXCIsXG4gIFwid2h5XCIsXG4gIFwid2lsbFwiLFxuICBcIndpdGhcIixcbiAgXCJ3aXRoaW5cIixcbiAgXCJ3aXRob3V0XCIsXG4gIFwid29ya1wiLFxuICBcIndvcmtlZFwiLFxuICBcIndvcmtpbmdcIixcbiAgXCJ3b3Jrc1wiLFxuICBcIndvdWxkXCIsXG4gIFwieFwiLFxuICBcInlcIixcbiAgXCJ5ZWFyXCIsXG4gIFwieWVhcnNcIixcbiAgXCJ5ZXRcIixcbiAgXCJ5b3VcIixcbiAgXCJ5b3VuZ1wiLFxuICBcInlvdW5nZXJcIixcbiAgXCJ5b3VuZ2VzdFwiLFxuICBcInlvdXJcIixcbiAgXCJ5b3Vyc1wiLFxuICBcInpcIlxuKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy93b3JkY2xvdWQvc3RvcHdvcmRzL2VuZ2xpc2gudHMiLCJ2YXIgZztcclxuXHJcbi8vIFRoaXMgd29ya3MgaW4gbm9uLXN0cmljdCBtb2RlXHJcbmcgPSAoZnVuY3Rpb24oKSB7XHJcblx0cmV0dXJuIHRoaXM7XHJcbn0pKCk7XHJcblxyXG50cnkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgZXZhbCBpcyBhbGxvd2VkIChzZWUgQ1NQKVxyXG5cdGcgPSBnIHx8IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKSB8fCAoMSxldmFsKShcInRoaXNcIik7XHJcbn0gY2F0Y2goZSkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgdGhlIHdpbmRvdyByZWZlcmVuY2UgaXMgYXZhaWxhYmxlXHJcblx0aWYodHlwZW9mIHdpbmRvdyA9PT0gXCJvYmplY3RcIilcclxuXHRcdGcgPSB3aW5kb3c7XHJcbn1cclxuXHJcbi8vIGcgY2FuIHN0aWxsIGJlIHVuZGVmaW5lZCwgYnV0IG5vdGhpbmcgdG8gZG8gYWJvdXQgaXQuLi5cclxuLy8gV2UgcmV0dXJuIHVuZGVmaW5lZCwgaW5zdGVhZCBvZiBub3RoaW5nIGhlcmUsIHNvIGl0J3NcclxuLy8gZWFzaWVyIHRvIGhhbmRsZSB0aGlzIGNhc2UuIGlmKCFnbG9iYWwpIHsgLi4ufVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBnO1xyXG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAod2VicGFjaykvYnVpbGRpbi9nbG9iYWwuanNcbi8vIG1vZHVsZSBpZCA9IDM1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV8zNl9fO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIHtcInJvb3RcIjpcIkNoYXJ0XCIsXCJjb21tb25qczJcIjpcImNoYXJ0LmpzXCIsXCJjb21tb25qc1wiOlwiY2hhcnQuanNcIixcImFtZFwiOlwiY2hhcnQuanNcIn1cbi8vIG1vZHVsZSBpZCA9IDM2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV8zN19fO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIHtcInJvb3RcIjpcIldvcmRDbG91ZFwiLFwiY29tbW9uanMyXCI6XCJ3b3JkY2xvdWRcIixcImNvbW1vbmpzXCI6XCJ3b3JkY2xvdWRcIixcImFtZFwiOlwid29yZGNsb3VkXCJ9XG4vLyBtb2R1bGUgaWQgPSAzN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfMzhfXztcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCB7XCJyb290XCI6XCJqUXVlcnlcIixcImNvbW1vbmpzMlwiOlwianF1ZXJ5XCIsXCJjb21tb25qc1wiOlwianF1ZXJ5XCIsXCJhbWRcIjpcImpxdWVyeVwifVxuLy8gbW9kdWxlIGlkID0gMzhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiZXhwb3J0ICogZnJvbSBcIi4vdmlzdWFsaXplckJhc2VcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3Zpc3VhbGl6YXRpb25NYW5hZ2VyXCI7XG5leHBvcnQgKiBmcm9tIFwiLi92aXN1YWxpemF0aW9uUGFuZWxcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3Zpc3VhbGl6YXRpb25QYW5lbER5bmFtaWNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3Zpc3VhbGl6YXRpb25NYXRyaXhEeW5hbWljXCI7XG5cbmV4cG9ydCAqIGZyb20gXCIuL2RhdGF0YWJsZXMvZGF0YXRhYmxlc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vY2hhcnRqcy9pbmRleFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vYzMvaW5kZXhcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3Bsb3RseS9pbmRleFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vd29yZGNsb3VkL3dvcmRjbG91ZFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vd29yZGNsb3VkL3N0b3B3b3Jkcy9pbmRleFwiO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2luZGV4LnRzIl0sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file